From 844a65636793d284526ff7d623ef477ed4473ab4 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 4 Mar 2016 22:55:25 -0800 Subject: [PATCH 0001/9938] iio: potentiometer: tpl0102: change i2c functionality return code Change i2c_check_functionality condition check return from ENOTSUPP to EOPNOTSUPP which is now the standard return code. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/potentiometer/tpl0102.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c index 313124b6fd59..5c304d42d713 100644 --- a/drivers/iio/potentiometer/tpl0102.c +++ b/drivers/iio/potentiometer/tpl0102.c @@ -118,7 +118,7 @@ static int tpl0102_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) - return -ENOTSUPP; + return -EOPNOTSUPP; indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) -- GitLab From 7a948c5e05febd23ee8e61db95c3dc96737fe17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gor=20Boirie?= Date: Tue, 1 Mar 2016 11:31:37 +0100 Subject: [PATCH 0002/9938] iio:pressure:ms5611: complete DT support Add device-tree ID tables and document bindings. Signed-off-by: Gregor Boirie Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/pressure/ms5611.txt | 19 +++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.txt | 1 + drivers/iio/pressure/ms5611_i2c.c | 13 +++++++++++++ drivers/iio/pressure/ms5611_spi.c | 13 +++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/pressure/ms5611.txt diff --git a/Documentation/devicetree/bindings/iio/pressure/ms5611.txt b/Documentation/devicetree/bindings/iio/pressure/ms5611.txt new file mode 100644 index 000000000000..17bca866c084 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/pressure/ms5611.txt @@ -0,0 +1,19 @@ +MEAS ms5611 family pressure sensors + +Pressure sensors from MEAS Switzerland with SPI and I2C bus interfaces. + +Required properties: +- compatible: "meas,ms5611" or "meas,ms5607" +- reg: the I2C address or SPI chip select the device will respond to + +Optional properties: +- vdd-supply: an optional regulator that needs to be on to provide VDD + power to the sensor. + +Example: + +ms5607@77 { + compatible = "meas,ms5607"; + reg = <0x77>; + vdd-supply = <&ldo_3v3_gnss>; +}; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 44ddc980b085..7733f8ca5e7b 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -136,6 +136,7 @@ lsi LSI Corp. (LSI Logic) lltc Linear Technology Corporation marvell Marvell Technology Group Ltd. maxim Maxim Integrated Products +meas Measurement Specialties mediatek MediaTek Inc. melexis Melexis N.V. merrii Merrii Technology Co., Ltd. diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c index 7f6fc8eee922..57a8f2cfa235 100644 --- a/drivers/iio/pressure/ms5611_i2c.c +++ b/drivers/iio/pressure/ms5611_i2c.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "ms5611.h" @@ -113,6 +114,17 @@ static int ms5611_i2c_remove(struct i2c_client *client) return ms5611_remove(i2c_get_clientdata(client)); } +#if defined(CONFIG_OF) +static const struct of_device_id ms5611_i2c_matches[] = { + { .compatible = "meas,ms5611" }, + { .compatible = "ms5611" }, + { .compatible = "meas,ms5607" }, + { .compatible = "ms5607" }, + { } +}; +MODULE_DEVICE_TABLE(of, ms5611_i2c_matches); +#endif + static const struct i2c_device_id ms5611_id[] = { { "ms5611", MS5611 }, { "ms5607", MS5607 }, @@ -123,6 +135,7 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id); static struct i2c_driver ms5611_driver = { .driver = { .name = "ms5611", + .of_match_table = of_match_ptr(ms5611_i2c_matches) }, .id_table = ms5611_id, .probe = ms5611_i2c_probe, diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index 5cc009e85f0e..7ec0c6498f93 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "ms5611.h" @@ -114,6 +115,17 @@ static int ms5611_spi_remove(struct spi_device *spi) return ms5611_remove(spi_get_drvdata(spi)); } +#if defined(CONFIG_OF) +static const struct of_device_id ms5611_spi_matches[] = { + { .compatible = "meas,ms5611" }, + { .compatible = "ms5611" }, + { .compatible = "meas,ms5607" }, + { .compatible = "ms5607" }, + { } +}; +MODULE_DEVICE_TABLE(of, ms5611_spi_matches); +#endif + static const struct spi_device_id ms5611_id[] = { { "ms5611", MS5611 }, { "ms5607", MS5607 }, @@ -124,6 +136,7 @@ MODULE_DEVICE_TABLE(spi, ms5611_id); static struct spi_driver ms5611_driver = { .driver = { .name = "ms5611", + .of_match_table = of_match_ptr(ms5611_spi_matches) }, .id_table = ms5611_id, .probe = ms5611_spi_probe, -- GitLab From 033691a9a12f684c68f443f3676806dd64011295 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Tue, 1 Mar 2016 11:31:38 +0100 Subject: [PATCH 0003/9938] iio:pressure:ms5611: oversampling rate support Add support for setting and retrieving OverSampling Rate independently for each of the temperature and pressure channels. This allows userspace to fine tune hardware sampling process according to the following tradeoffs : * the higher the OSR, the finer the resolution ; * the higher the OSR, the lower the noise ; BUT: * the higher the OSR, the larger the drift ; * the higher the OSR, the longer the response time, i.e. less samples per unit of time. Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611.h | 20 ++++-- drivers/iio/pressure/ms5611_core.c | 105 ++++++++++++++++++++++++++++- drivers/iio/pressure/ms5611_i2c.c | 12 ++-- drivers/iio/pressure/ms5611_spi.c | 19 +++--- 4 files changed, 133 insertions(+), 23 deletions(-) diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h index 8b08e4b7e3a9..d725a3077a17 100644 --- a/drivers/iio/pressure/ms5611.h +++ b/drivers/iio/pressure/ms5611.h @@ -19,12 +19,6 @@ #define MS5611_RESET 0x1e #define MS5611_READ_ADC 0x00 #define MS5611_READ_PROM_WORD 0xA0 -#define MS5611_START_TEMP_CONV 0x58 -#define MS5611_START_PRESSURE_CONV 0x48 - -#define MS5611_CONV_TIME_MIN 9040 -#define MS5611_CONV_TIME_MAX 10000 - #define MS5611_PROM_WORDS_NB 8 enum { @@ -39,10 +33,24 @@ struct ms5611_chip_info { s32 *temp, s32 *pressure); }; +/* + * OverSampling Rate descriptor. + * Warning: cmd MUST be kept aligned on a word boundary (see + * m5611_spi_read_adc_temp_and_pressure in ms5611_spi.c). + */ +struct ms5611_osr { + unsigned long conv_usec; + u8 cmd; + unsigned short rate; +}; + struct ms5611_state { void *client; struct mutex lock; + const struct ms5611_osr *pressure_osr; + const struct ms5611_osr *temp_osr; + int (*reset)(struct device *dev); int (*read_prom_word)(struct device *dev, int index, u16 *word); int (*read_adc_temp_and_pressure)(struct device *dev, diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 992ad8d3b67a..37dbc0401599 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -18,11 +18,44 @@ #include #include +#include #include #include #include #include "ms5611.h" +#define MS5611_INIT_OSR(_cmd, _conv_usec, _rate) \ + { .cmd = _cmd, .conv_usec = _conv_usec, .rate = _rate } + +static const struct ms5611_osr ms5611_avail_pressure_osr[] = { + MS5611_INIT_OSR(0x40, 600, 256), + MS5611_INIT_OSR(0x42, 1170, 512), + MS5611_INIT_OSR(0x44, 2280, 1024), + MS5611_INIT_OSR(0x46, 4540, 2048), + MS5611_INIT_OSR(0x48, 9040, 4096) +}; + +static const struct ms5611_osr ms5611_avail_temp_osr[] = { + MS5611_INIT_OSR(0x50, 600, 256), + MS5611_INIT_OSR(0x52, 1170, 512), + MS5611_INIT_OSR(0x54, 2280, 1024), + MS5611_INIT_OSR(0x56, 4540, 2048), + MS5611_INIT_OSR(0x58, 9040, 4096) +}; + +static const char ms5611_show_osr[] = "256 512 1024 2048 4096"; + +static IIO_CONST_ATTR(oversampling_ratio_available, ms5611_show_osr); + +static struct attribute *ms5611_attributes[] = { + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ms5611_attribute_group = { + .attrs = ms5611_attributes, +}; + static bool ms5611_prom_is_valid(u16 *prom, size_t len) { int i, j; @@ -239,11 +272,70 @@ static int ms5611_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (chan->type != IIO_TEMP && chan->type != IIO_PRESSURE) + break; + mutex_lock(&st->lock); + if (chan->type == IIO_TEMP) + *val = (int)st->temp_osr->rate; + else + *val = (int)st->pressure_osr->rate; + mutex_unlock(&st->lock); + return IIO_VAL_INT; } return -EINVAL; } +static const struct ms5611_osr *ms5611_find_osr(int rate, + const struct ms5611_osr *osr, + size_t count) +{ + unsigned int r; + + for (r = 0; r < count; r++) + if ((unsigned short)rate == osr[r].rate) + break; + if (r >= count) + return NULL; + return &osr[r]; +} + +static int ms5611_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct ms5611_state *st = iio_priv(indio_dev); + const struct ms5611_osr *osr = NULL; + + if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO) + return -EINVAL; + + if (chan->type == IIO_TEMP) + osr = ms5611_find_osr(val, ms5611_avail_temp_osr, + ARRAY_SIZE(ms5611_avail_temp_osr)); + else if (chan->type == IIO_PRESSURE) + osr = ms5611_find_osr(val, ms5611_avail_pressure_osr, + ARRAY_SIZE(ms5611_avail_pressure_osr)); + if (!osr) + return -EINVAL; + + mutex_lock(&st->lock); + + if (iio_buffer_enabled(indio_dev)) { + mutex_unlock(&st->lock); + return -EBUSY; + } + + if (chan->type == IIO_TEMP) + st->temp_osr = osr; + else + st->pressure_osr = osr; + + mutex_unlock(&st->lock); + return 0; +} + static const unsigned long ms5611_scan_masks[] = {0x3, 0}; static struct ms5611_chip_info chip_info_tbl[] = { @@ -259,7 +351,8 @@ static const struct iio_chan_spec ms5611_channels[] = { { .type = IIO_PRESSURE, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | - BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), .scan_index = 0, .scan_type = { .sign = 's', @@ -271,7 +364,8 @@ static const struct iio_chan_spec ms5611_channels[] = { { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | - BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), .scan_index = 1, .scan_type = { .sign = 's', @@ -285,6 +379,8 @@ static const struct iio_chan_spec ms5611_channels[] = { static const struct iio_info ms5611_info = { .read_raw = &ms5611_read_raw, + .write_raw = &ms5611_write_raw, + .attrs = &ms5611_attribute_group, .driver_module = THIS_MODULE, }; @@ -319,6 +415,11 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, mutex_init(&st->lock); st->chip_info = &chip_info_tbl[type]; + st->temp_osr = + &ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1]; + st->pressure_osr = + &ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr) + - 1]; indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ms5611_info; diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c index 57a8f2cfa235..55fb5fc0b6ea 100644 --- a/drivers/iio/pressure/ms5611_i2c.c +++ b/drivers/iio/pressure/ms5611_i2c.c @@ -63,23 +63,23 @@ static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev, { int ret; struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); + const struct ms5611_osr *osr = st->temp_osr; - ret = i2c_smbus_write_byte(st->client, MS5611_START_TEMP_CONV); + ret = i2c_smbus_write_byte(st->client, osr->cmd); if (ret < 0) return ret; - usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); - + usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); ret = ms5611_i2c_read_adc(st, temp); if (ret < 0) return ret; - ret = i2c_smbus_write_byte(st->client, MS5611_START_PRESSURE_CONV); + osr = st->pressure_osr; + ret = i2c_smbus_write_byte(st->client, osr->cmd); if (ret < 0) return ret; - usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); - + usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); return ms5611_i2c_read_adc(st, pressure); } diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index 7ec0c6498f93..7600483e8cb4 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -56,28 +56,29 @@ static int ms5611_spi_read_adc(struct device *dev, s32 *val) static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev, s32 *temp, s32 *pressure) { - u8 cmd; int ret; struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); + const struct ms5611_osr *osr = st->temp_osr; - cmd = MS5611_START_TEMP_CONV; - ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0); + /* + * Warning: &osr->cmd MUST be aligned on a word boundary since used as + * 2nd argument (void*) of spi_write_then_read. + */ + ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0); if (ret < 0) return ret; - usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); - + usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); ret = ms5611_spi_read_adc(dev, temp); if (ret < 0) return ret; - cmd = MS5611_START_PRESSURE_CONV; - ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0); + osr = st->pressure_osr; + ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0); if (ret < 0) return ret; - usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); - + usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); return ms5611_spi_read_adc(dev, pressure); } -- GitLab From 43d33f7458383ff6ce9838fca7b78b9b64fb988a Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 3 Mar 2016 17:09:13 +0100 Subject: [PATCH 0004/9938] iio:adc:at91-sama5d2: fix typo Fix typo in the name of a macro. Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index dbee13ad33a3..33bacece325c 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -140,7 +140,7 @@ /* Version Register */ #define AT91_SAMA5D2_VERSION 0xfc -#define AT91_AT91_SAMA5D2_CHAN(num, addr) \ +#define AT91_SAMA5D2_CHAN(num, addr) \ { \ .type = IIO_VOLTAGE, \ .channel = num, \ @@ -185,18 +185,18 @@ struct at91_adc_state { }; static const struct iio_chan_spec at91_adc_channels[] = { - AT91_AT91_SAMA5D2_CHAN(0, 0x50), - AT91_AT91_SAMA5D2_CHAN(1, 0x54), - AT91_AT91_SAMA5D2_CHAN(2, 0x58), - AT91_AT91_SAMA5D2_CHAN(3, 0x5c), - AT91_AT91_SAMA5D2_CHAN(4, 0x60), - AT91_AT91_SAMA5D2_CHAN(5, 0x64), - AT91_AT91_SAMA5D2_CHAN(6, 0x68), - AT91_AT91_SAMA5D2_CHAN(7, 0x6c), - AT91_AT91_SAMA5D2_CHAN(8, 0x70), - AT91_AT91_SAMA5D2_CHAN(9, 0x74), - AT91_AT91_SAMA5D2_CHAN(10, 0x78), - AT91_AT91_SAMA5D2_CHAN(11, 0x7c), + AT91_SAMA5D2_CHAN(0, 0x50), + AT91_SAMA5D2_CHAN(1, 0x54), + AT91_SAMA5D2_CHAN(2, 0x58), + AT91_SAMA5D2_CHAN(3, 0x5c), + AT91_SAMA5D2_CHAN(4, 0x60), + AT91_SAMA5D2_CHAN(5, 0x64), + AT91_SAMA5D2_CHAN(6, 0x68), + AT91_SAMA5D2_CHAN(7, 0x6c), + AT91_SAMA5D2_CHAN(8, 0x70), + AT91_SAMA5D2_CHAN(9, 0x74), + AT91_SAMA5D2_CHAN(10, 0x78), + AT91_SAMA5D2_CHAN(11, 0x7c), }; static unsigned at91_adc_startup_time(unsigned startup_time_min, -- GitLab From f0fa15cce13d5987c50907eb98846d13e2b4d9ca Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 3 Mar 2016 17:09:14 +0100 Subject: [PATCH 0005/9938] iio:adc:at91-sama5d2: fix identation Remove some extra tabs. Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 33bacece325c..5bc038f23609 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -92,13 +92,13 @@ /* Last Converted Data Register */ #define AT91_SAMA5D2_LCDR 0x20 /* Interrupt Enable Register */ -#define AT91_SAMA5D2_IER 0x24 +#define AT91_SAMA5D2_IER 0x24 /* Interrupt Disable Register */ -#define AT91_SAMA5D2_IDR 0x28 +#define AT91_SAMA5D2_IDR 0x28 /* Interrupt Mask Register */ -#define AT91_SAMA5D2_IMR 0x2c +#define AT91_SAMA5D2_IMR 0x2c /* Interrupt Status Register */ -#define AT91_SAMA5D2_ISR 0x30 +#define AT91_SAMA5D2_ISR 0x30 /* Last Channel Trigger Mode Register */ #define AT91_SAMA5D2_LCTMR 0x34 /* Last Channel Compare Window Register */ @@ -106,17 +106,17 @@ /* Overrun Status Register */ #define AT91_SAMA5D2_OVER 0x3c /* Extended Mode Register */ -#define AT91_SAMA5D2_EMR 0x40 +#define AT91_SAMA5D2_EMR 0x40 /* Compare Window Register */ -#define AT91_SAMA5D2_CWR 0x44 +#define AT91_SAMA5D2_CWR 0x44 /* Channel Gain Register */ -#define AT91_SAMA5D2_CGR 0x48 +#define AT91_SAMA5D2_CGR 0x48 /* Channel Offset Register */ -#define AT91_SAMA5D2_COR 0x4c +#define AT91_SAMA5D2_COR 0x4c /* Channel Data Register 0 */ #define AT91_SAMA5D2_CDR0 0x50 /* Analog Control Register */ -#define AT91_SAMA5D2_ACR 0x94 +#define AT91_SAMA5D2_ACR 0x94 /* Touchscreen Mode Register */ #define AT91_SAMA5D2_TSMR 0xb0 /* Touchscreen X Position Register */ @@ -130,7 +130,7 @@ /* Correction Select Register */ #define AT91_SAMA5D2_COSR 0xd0 /* Correction Value Register */ -#define AT91_SAMA5D2_CVR 0xd4 +#define AT91_SAMA5D2_CVR 0xd4 /* Channel Error Correction Register */ #define AT91_SAMA5D2_CECR 0xd8 /* Write Protection Mode Register */ -- GitLab From 55c0c530f7113d98cb1a0d42f15b8abe5e4b6928 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Thu, 3 Mar 2016 11:44:03 +0100 Subject: [PATCH 0006/9938] iio:magnetometer:ak8975: fix uninitialized chipset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ak_def_array bounds are not properly checked in case of ACPI matching failure. GCC warns with the following message at line 799: ‘chipset’ may be used uninitialized in this function. Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 9c5c9ef3f1da..11059b2c39a4 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -774,8 +774,11 @@ static int ak8975_probe(struct i2c_client *client, if (id) { chipset = (enum asahi_compass_chipset)(id->driver_data); name = id->name; - } else if (ACPI_HANDLE(&client->dev)) + } else if (ACPI_HANDLE(&client->dev)) { name = ak8975_match_acpi_device(&client->dev, &chipset); + if (!name) + return -ENODEV; + } else return -ENOSYS; -- GitLab From d3546af67f4937075d0747adb3bf56d3c46b32f0 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Thu, 3 Mar 2016 11:44:04 +0100 Subject: [PATCH 0007/9938] iio:magnetometer:ak8975: remove unused field Remove unused struct ak8975_data attrs field. Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 11059b2c39a4..896b13e39dae 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -361,7 +361,6 @@ static const struct ak_def ak_def_array[AK_MAX_TYPE] = { struct ak8975_data { struct i2c_client *client; const struct ak_def *def; - struct attribute_group attrs; struct mutex lock; u8 asa[3]; long raw_to_gauss[3]; -- GitLab From 63d5d525cbbc8938d9fa3d6d6fbd4183e784b6e9 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Thu, 3 Mar 2016 11:44:05 +0100 Subject: [PATCH 0008/9938] iio:magnetometer:ak8975: power regulator support Add support for an optional regulator which, if found into device-tree, will power on device at probing time. The regulator is declared into ak8975 DTS entry as a "vdd-supply" property. Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- .../bindings/iio/magnetometer/ak8975.txt | 2 ++ drivers/iio/magnetometer/ak8975.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt index 011679f1a425..34a3206eefdf 100644 --- a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt +++ b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt @@ -8,6 +8,7 @@ Required properties: Optional properties: - gpios : should be device tree identifier of the magnetometer DRDY pin + - vdd-supply: an optional regulator that needs to be on to provide VDD Example: @@ -15,4 +16,5 @@ ak8975@0c { compatible = "asahi-kasei,ak8975"; reg = <0x0c>; gpios = <&gpj0 7 0>; + vdd-supply = <&ldo_3v3_gnss>; }; diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 896b13e39dae..72c03d9fbeb2 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -379,8 +380,23 @@ static int ak8975_who_i_am(struct i2c_client *client, enum asahi_compass_chipset type) { u8 wia_val[2]; + struct regulator *vdd = devm_regulator_get_optional(&client->dev, + "vdd"); int ret; + /* Enable attached regulator if any. */ + if (!IS_ERR(vdd)) { + ret = regulator_enable(vdd); + if (ret) { + dev_err(&client->dev, "Failed to enable Vdd supply\n"); + return ret; + } + } else { + ret = PTR_ERR(vdd); + if (ret != -ENODEV) + return ret; + } + /* * Signature for each device: * Device | WIA1 | WIA2 -- GitLab From 8b8ff3a6a6e2325662e3af174f54b47487d3ed75 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 3 Mar 2016 09:24:01 +0100 Subject: [PATCH 0009/9938] iio: mma8452: coding style fixes fix checkpatch issues like "space before tabs", too long lines or alignment. Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 7f4994f32a90..17d72bc2e6fa 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -357,7 +357,8 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_CALIBBIAS: ret = i2c_smbus_read_byte_data(data->client, - MMA8452_OFF_X + chan->scan_index); + MMA8452_OFF_X + + chan->scan_index); if (ret < 0) return ret; @@ -418,7 +419,7 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val) return ret; } -/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */ +/* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */ static int mma8452_freefall_mode_enabled(struct mma8452_data *data) { int val; @@ -668,7 +669,8 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev, if (ret < 0) return ret; - return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift)); + return !!(ret & BIT(chan->scan_index + + chip->ev_cfg_chan_shift)); default: return -EINVAL; } @@ -1003,7 +1005,7 @@ static const struct mma_chip_info mma_chip_info_table[] = { * bit. * The userspace interface uses m/s^2 and we declare micro units * So scale factor for 12 bit here is given by: - * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665 + * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665 */ .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} }, .ev_cfg = MMA8452_TRANSIENT_CFG, -- GitLab From e866853d67868ac0f7e0779d19aaad07285c9ff3 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 3 Mar 2016 09:24:02 +0100 Subject: [PATCH 0010/9938] iio: mma8452: avoid switching to active because of config change The devices' config registers can only be changed in standby mode. Up until now the driver just held the device *always* active, so for changing a config it was *always* necessary to switch to standby. For upcoming support for runtime pm, the device can as well be in standby mode. Instead of putting runtime pm functions in there, just keep the device in standby if it already is. This section is protected by a lock after all. Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 17d72bc2e6fa..9c4a84a72ad4 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -393,24 +393,47 @@ static int mma8452_active(struct mma8452_data *data) data->ctrl_reg1); } +/* returns >0 if active, 0 if in standby and <0 on error */ +static int mma8452_is_active(struct mma8452_data *data) +{ + int reg; + + reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG1); + if (reg < 0) + return reg; + + return reg & MMA8452_CTRL_ACTIVE; +} + static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val) { int ret; + int is_active; mutex_lock(&data->lock); - /* config can only be changed when in standby */ - ret = mma8452_standby(data); - if (ret < 0) + is_active = mma8452_is_active(data); + if (is_active < 0) { + ret = is_active; goto fail; + } + + /* config can only be changed when in standby */ + if (is_active > 0) { + ret = mma8452_standby(data); + if (ret < 0) + goto fail; + } ret = i2c_smbus_write_byte_data(data->client, reg, val); if (ret < 0) goto fail; - ret = mma8452_active(data); - if (ret < 0) - goto fail; + if (is_active > 0) { + ret = mma8452_active(data); + if (ret < 0) + goto fail; + } ret = 0; fail: -- GitLab From 96c0cb2bbfe0a58bd0c37cf34d50a20f9cd75aa8 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 3 Mar 2016 09:24:03 +0100 Subject: [PATCH 0011/9938] iio: mma8452: add support for runtime power management This adds support for runtime power management and, if configured, activates automatic standby after 2 seconds of inactivity. Inactivity means no read of acceleration values and no events triggered or activated. If CONFIG_PM is not set, this doesn't change anything for existing users. Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 118 +++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 10 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 9c4a84a72ad4..5ca0d169f912 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -31,6 +31,7 @@ #include #include #include +#include #define MMA8452_STATUS 0x00 #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) @@ -92,6 +93,8 @@ #define MMA8652_DEVICE_ID 0x4a #define MMA8653_DEVICE_ID 0x5a +#define MMA8452_AUTO_SUSPEND_DELAY_MS 2000 + struct mma8452_data { struct i2c_client *client; struct mutex lock; @@ -172,6 +175,31 @@ static int mma8452_drdy(struct mma8452_data *data) return -EIO; } +static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on) +{ +#ifdef CONFIG_PM + int ret; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + } else { + pm_runtime_mark_last_busy(&client->dev); + ret = pm_runtime_put_autosuspend(&client->dev); + } + + if (ret < 0) { + dev_err(&client->dev, + "failed to change power state to %d\n", on); + if (on) + pm_runtime_put_noidle(&client->dev); + + return ret; + } +#endif + + return 0; +} + static int mma8452_read(struct mma8452_data *data, __be16 buf[3]) { int ret = mma8452_drdy(data); @@ -179,8 +207,16 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3]) if (ret < 0) return ret; - return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X, - 3 * sizeof(__be16), (u8 *)buf); + ret = mma8452_set_runtime_pm_state(data->client, true); + if (ret) + return ret; + + ret = i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X, + 3 * sizeof(__be16), (u8 *)buf); + + ret = mma8452_set_runtime_pm_state(data->client, false); + + return ret; } static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2], @@ -707,7 +743,11 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, { struct mma8452_data *data = iio_priv(indio_dev); const struct mma_chip_info *chip = data->chip_info; - int val; + int val, ret; + + ret = mma8452_set_runtime_pm_state(data->client, state); + if (ret) + return ret; switch (dir) { case IIO_EV_DIR_FALLING: @@ -1139,7 +1179,11 @@ static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig, { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct mma8452_data *data = iio_priv(indio_dev); - int reg; + int reg, ret; + + ret = mma8452_set_runtime_pm_state(data->client, state); + if (ret) + return ret; reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4); if (reg < 0) @@ -1365,6 +1409,15 @@ static int mma8452_probe(struct i2c_client *client, goto buffer_cleanup; } + ret = pm_runtime_set_active(&client->dev); + if (ret < 0) + goto buffer_cleanup; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, + MMA8452_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + ret = iio_device_register(indio_dev); if (ret < 0) goto buffer_cleanup; @@ -1389,6 +1442,11 @@ static int mma8452_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + iio_triggered_buffer_cleanup(indio_dev); mma8452_trigger_cleanup(indio_dev); mma8452_standby(iio_priv(indio_dev)); @@ -1396,6 +1454,45 @@ static int mma8452_remove(struct i2c_client *client) return 0; } +#ifdef CONFIG_PM +static int mma8452_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma8452_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = mma8452_standby(data); + mutex_unlock(&data->lock); + if (ret < 0) { + dev_err(&data->client->dev, "powering off device failed\n"); + return -EAGAIN; + } + + return 0; +} + +static int mma8452_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma8452_data *data = iio_priv(indio_dev); + int ret, sleep_val; + + ret = mma8452_active(data); + if (ret < 0) + return ret; + + ret = mma8452_get_odr_index(data); + sleep_val = 1000 / mma8452_samp_freq[ret][0]; + if (sleep_val < 20) + usleep_range(sleep_val * 1000, 20000); + else + msleep_interruptible(sleep_val); + + return 0; +} +#endif + #ifdef CONFIG_PM_SLEEP static int mma8452_suspend(struct device *dev) { @@ -1408,13 +1505,14 @@ static int mma8452_resume(struct device *dev) return mma8452_active(iio_priv(i2c_get_clientdata( to_i2c_client(dev)))); } - -static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume); -#define MMA8452_PM_OPS (&mma8452_pm_ops) -#else -#define MMA8452_PM_OPS NULL #endif +static const struct dev_pm_ops mma8452_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mma8452_suspend, mma8452_resume) + SET_RUNTIME_PM_OPS(mma8452_runtime_suspend, + mma8452_runtime_resume, NULL) +}; + static const struct i2c_device_id mma8452_id[] = { { "mma8452", mma8452 }, { "mma8453", mma8453 }, @@ -1428,7 +1526,7 @@ static struct i2c_driver mma8452_driver = { .driver = { .name = "mma8452", .of_match_table = of_match_ptr(mma8452_dt_ids), - .pm = MMA8452_PM_OPS, + .pm = &mma8452_pm_ops, }, .probe = mma8452_probe, .remove = mma8452_remove, -- GitLab From c816d9e7a57bd436b2cff8f48b0e8cff128f05db Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Wed, 2 Mar 2016 19:18:12 -0800 Subject: [PATCH 0012/9938] iio: imu: mpu6050: fix possible NULL dereferences Fix possible null dereferencing of i2c and spi driver data. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 3 ++- drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index f581256d9d4c..d0c0e20c7122 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -117,6 +117,7 @@ static int inv_mpu_probe(struct i2c_client *client, struct inv_mpu6050_state *st; int result; const char *name = id ? id->name : NULL; + const int chip_type = id ? id->driver_data : 0; struct regmap *regmap; if (!i2c_check_functionality(client->adapter, @@ -131,7 +132,7 @@ static int inv_mpu_probe(struct i2c_client *client, } result = inv_mpu_core_probe(regmap, client->irq, name, - NULL, id->driver_data); + NULL, chip_type); if (result < 0) return result; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index dea6c4361de0..7bcb8d839f05 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -46,6 +46,7 @@ static int inv_mpu_probe(struct spi_device *spi) struct regmap *regmap; const struct spi_device_id *id = spi_get_device_id(spi); const char *name = id ? id->name : NULL; + const int chip_type = id ? id->driver_data : 0; regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config); if (IS_ERR(regmap)) { @@ -55,7 +56,7 @@ static int inv_mpu_probe(struct spi_device *spi) } return inv_mpu_core_probe(regmap, spi->irq, name, - inv_mpu_i2c_disable, id->driver_data); + inv_mpu_i2c_disable, chip_type); } static int inv_mpu_remove(struct spi_device *spi) -- GitLab From e84a41d5db891eab6f1f4a2625bb97f3c6415eee Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 4 Mar 2016 10:05:26 +0900 Subject: [PATCH 0013/9938] iio: adc: Fix build error of missing devm_ioremap_resource on UM The devres.o gets linked if HAS_IOMEM is present so on ARCH=um allyesconfig (COMPILE_TEST) failed with: drivers/built-in.o: In function `at91_adc_probe': at91-sama5d2_adc.c:(.text+0x48f548): undefined reference to `devm_ioremap_resource' Signed-off-by: Krzysztof Kozlowski Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 932de1f9d1e7..a8819a08a828 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -134,6 +134,7 @@ config AT91_ADC config AT91_SAMA5D2_ADC tristate "Atmel AT91 SAMA5D2 ADC" depends on ARCH_AT91 || COMPILE_TEST + depends on HAS_IOMEM help Say yes here to build support for Atmel SAMA5D2 ADC which is available on SAMA5D2 SoC family. -- GitLab From f2f6ecabebddcbc54485cf3fca544e985457c0f4 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 1 Mar 2016 11:32:46 +0100 Subject: [PATCH 0014/9938] ath10k: refactor tx code This prepares the code for future reuse with ieee80211_txq and wake_tx_queue() in mind. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 151 ++++++++++++++++---------- 1 file changed, 96 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 78999c9de23b..b3a790addb0a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3271,6 +3271,26 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, } } +static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, + struct ieee80211_vif *vif, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); + + cb->flags = 0; + if (!ath10k_tx_h_use_hwcrypto(vif, skb)) + cb->flags |= ATH10K_SKB_F_NO_HWCRYPT; + + if (ieee80211_is_mgmt(hdr->frame_control)) + cb->flags |= ATH10K_SKB_F_MGMT; + + if (ieee80211_is_data_qos(hdr->frame_control)) + cb->flags |= ATH10K_SKB_F_QOS; + + cb->vif = vif; +} + bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) { /* FIXME: Not really sure since when the behaviour changed. At some @@ -3306,8 +3326,9 @@ static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) return ret; } -static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode, - struct sk_buff *skb) +static int ath10k_mac_tx_submit(struct ath10k *ar, + enum ath10k_hw_txrx_mode txmode, + struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; int ret = 0; @@ -3334,6 +3355,63 @@ static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode, ret); ieee80211_free_txskb(ar->hw, skb); } + + return ret; +} + +/* This function consumes the sk_buff regardless of return value as far as + * caller is concerned so no freeing is necessary afterwards. + */ +static int ath10k_mac_tx(struct ath10k *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ath10k_hw_txrx_mode txmode, + struct sk_buff *skb) +{ + struct ieee80211_hw *hw = ar->hw; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int ret; + + /* We should disable CCK RATE due to P2P */ + if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) + ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n"); + + switch (txmode) { + case ATH10K_HW_TXRX_MGMT: + case ATH10K_HW_TXRX_NATIVE_WIFI: + ath10k_tx_h_nwifi(hw, skb); + ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb); + ath10k_tx_h_seq_no(vif, skb); + break; + case ATH10K_HW_TXRX_ETHERNET: + ath10k_tx_h_8023(skb); + break; + case ATH10K_HW_TXRX_RAW: + if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { + WARN_ON_ONCE(1); + ieee80211_free_txskb(hw, skb); + return -ENOTSUPP; + } + } + + if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { + if (!ath10k_mac_tx_frm_has_freq(ar)) { + ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n", + skb); + + skb_queue_tail(&ar->offchan_tx_queue, skb); + ieee80211_queue_work(hw, &ar->offchan_tx_work); + return 0; + } + } + + ret = ath10k_mac_tx_submit(ar, txmode, skb); + if (ret) { + ath10k_warn(ar, "failed to submit frame: %d\n", ret); + return ret; + } + + return 0; } void ath10k_offchan_tx_purge(struct ath10k *ar) @@ -3354,12 +3432,12 @@ void ath10k_offchan_tx_work(struct work_struct *work) struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work); struct ath10k_peer *peer; struct ath10k_vif *arvif; + enum ath10k_hw_txrx_mode txmode; struct ieee80211_hdr *hdr; struct ieee80211_vif *vif; struct ieee80211_sta *sta; struct sk_buff *skb; const u8 *peer_addr; - enum ath10k_hw_txrx_mode txmode; int vdev_id; int ret; unsigned long time_left; @@ -3424,7 +3502,12 @@ void ath10k_offchan_tx_work(struct work_struct *work) txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); - ath10k_mac_tx(ar, txmode, skb); + ret = ath10k_mac_tx(ar, vif, sta, txmode, skb); + if (ret) { + ath10k_warn(ar, "failed to transmit offchannel frame: %d\n", + ret); + /* not serious */ + } time_left = wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ); @@ -3638,66 +3721,24 @@ static int ath10k_start_scan(struct ath10k *ar, /* mac80211 callbacks */ /**********************/ -static void ath10k_tx(struct ieee80211_hw *hw, - struct ieee80211_tx_control *control, - struct sk_buff *skb) +static void ath10k_mac_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct ath10k *ar = hw->priv; - struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct ieee80211_sta *sta = control->sta; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; enum ath10k_hw_txrx_mode txmode; + int ret; - /* We should disable CCK RATE due to P2P */ - if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) - ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n"); + ath10k_mac_tx_h_fill_cb(ar, vif, skb); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); - skb_cb->flags = 0; - if (!ath10k_tx_h_use_hwcrypto(vif, skb)) - skb_cb->flags |= ATH10K_SKB_F_NO_HWCRYPT; - - if (ieee80211_is_mgmt(hdr->frame_control)) - skb_cb->flags |= ATH10K_SKB_F_MGMT; - - if (ieee80211_is_data_qos(hdr->frame_control)) - skb_cb->flags |= ATH10K_SKB_F_QOS; - - skb_cb->vif = vif; - - switch (txmode) { - case ATH10K_HW_TXRX_MGMT: - case ATH10K_HW_TXRX_NATIVE_WIFI: - ath10k_tx_h_nwifi(hw, skb); - ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb); - ath10k_tx_h_seq_no(vif, skb); - break; - case ATH10K_HW_TXRX_ETHERNET: - ath10k_tx_h_8023(skb); - break; - case ATH10K_HW_TXRX_RAW: - if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { - WARN_ON_ONCE(1); - ieee80211_free_txskb(hw, skb); - return; - } - } - - if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { - if (!ath10k_mac_tx_frm_has_freq(ar)) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n", - skb); - - skb_queue_tail(&ar->offchan_tx_queue, skb); - ieee80211_queue_work(hw, &ar->offchan_tx_work); - return; - } - } - - ath10k_mac_tx(ar, txmode, skb); + ret = ath10k_mac_tx(ar, vif, sta, txmode, skb); + if (ret) + ath10k_warn(ar, "failed to transmit frame: %d\n", ret); } /* Must not be called with conf_mutex held as workers can use that also. */ @@ -6807,7 +6848,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, } static const struct ieee80211_ops ath10k_ops = { - .tx = ath10k_tx, + .tx = ath10k_mac_op_tx, .start = ath10k_start, .stop = ath10k_stop, .config = ath10k_config, -- GitLab From a30c7d009ed56df43f09ab9af11e0bdd3a3f2a3f Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:23 +0200 Subject: [PATCH 0015/9938] ath10k: unify txpath decision Some future changes will need to determine final tx method early on. Prepare the code. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 54 +++++++++++++++++++++------ 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b3a790addb0a..67a50a61afb4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2994,6 +2994,13 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, /* TX handlers */ /***************/ +enum ath10k_mac_tx_path { + ATH10K_MAC_TX_HTT, + ATH10K_MAC_TX_HTT_MGMT, + ATH10K_MAC_TX_WMI_MGMT, + ATH10K_MAC_TX_UNKNOWN, +}; + void ath10k_mac_tx_lock(struct ath10k *ar, int reason) { lockdep_assert_held(&ar->htt.tx_lock); @@ -3326,27 +3333,52 @@ static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) return ret; } -static int ath10k_mac_tx_submit(struct ath10k *ar, - enum ath10k_hw_txrx_mode txmode, - struct sk_buff *skb) +static enum ath10k_mac_tx_path +ath10k_mac_tx_h_get_txpath(struct ath10k *ar, + struct sk_buff *skb, + enum ath10k_hw_txrx_mode txmode) { - struct ath10k_htt *htt = &ar->htt; - int ret = 0; - switch (txmode) { case ATH10K_HW_TXRX_RAW: case ATH10K_HW_TXRX_NATIVE_WIFI: case ATH10K_HW_TXRX_ETHERNET: - ret = ath10k_htt_tx(htt, txmode, skb); - break; + return ATH10K_MAC_TX_HTT; case ATH10K_HW_TXRX_MGMT: if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, ar->fw_features)) - ret = ath10k_mac_tx_wmi_mgmt(ar, skb); + return ATH10K_MAC_TX_WMI_MGMT; else if (ar->htt.target_version_major >= 3) - ret = ath10k_htt_tx(htt, txmode, skb); + return ATH10K_MAC_TX_HTT; else - ret = ath10k_htt_mgmt_tx(htt, skb); + return ATH10K_MAC_TX_HTT_MGMT; + } + + return ATH10K_MAC_TX_UNKNOWN; +} + +static int ath10k_mac_tx_submit(struct ath10k *ar, + enum ath10k_hw_txrx_mode txmode, + struct sk_buff *skb) +{ + struct ath10k_htt *htt = &ar->htt; + enum ath10k_mac_tx_path txpath; + int ret; + + txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); + + switch (txpath) { + case ATH10K_MAC_TX_HTT: + ret = ath10k_htt_tx(htt, txmode, skb); + break; + case ATH10K_MAC_TX_HTT_MGMT: + ret = ath10k_htt_mgmt_tx(htt, skb); + break; + case ATH10K_MAC_TX_WMI_MGMT: + ret = ath10k_mac_tx_wmi_mgmt(ar, skb); + break; + case ATH10K_MAC_TX_UNKNOWN: + WARN_ON_ONCE(1); + ret = -EINVAL; break; } -- GitLab From 6421969f248fdf9d8cd38353a617ed7cc5ddab94 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:25 +0200 Subject: [PATCH 0016/9938] ath10k: refactor tx pending management Tx pending counter logic assumed that the sk_buff is already known and hence was performed in HTT functions themselves. However, for the sake of future wake_tx_queue() usage the driver must be able to tell whether it can submit more frames to firmware before it dequeues frame from ieee80211_txq (and thus long before HTT Tx functions are called) because once a frame is dequeued it cannot be requeud back to mac80211. This prepares the driver for future changes. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 7 +- drivers/net/wireless/ath/ath10k/htt_tx.c | 85 ++++++------------------ drivers/net/wireless/ath/ath10k/mac.c | 51 +++++++++++--- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- 4 files changed, 71 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 13391ea4422d..cb6d4fd687da 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1753,7 +1753,12 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, u8 max_subfrms_amsdu); void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb); -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc); +void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, + bool is_mgmt); +int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, + bool is_mgmt, + bool is_presp); + int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 95acb727c068..860661d3812f 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -22,9 +22,12 @@ #include "txrx.h" #include "debug.h" -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc) +void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, + bool is_mgmt) { - if (limit_mgmt_desc) + lockdep_assert_held(&htt->tx_lock); + + if (is_mgmt) htt->num_pending_mgmt_tx--; htt->num_pending_tx--; @@ -32,43 +35,31 @@ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc) ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); } -static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, - bool limit_mgmt_desc) -{ - spin_lock_bh(&htt->tx_lock); - __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); - spin_unlock_bh(&htt->tx_lock); -} - -static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, - bool limit_mgmt_desc, bool is_probe_resp) +int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, + bool is_mgmt, + bool is_presp) { struct ath10k *ar = htt->ar; - int ret = 0; - spin_lock_bh(&htt->tx_lock); + lockdep_assert_held(&htt->tx_lock); - if (htt->num_pending_tx >= htt->max_num_pending_tx) { - ret = -EBUSY; - goto exit; - } + if (htt->num_pending_tx >= htt->max_num_pending_tx) + return -EBUSY; - if (limit_mgmt_desc) { - if (is_probe_resp && (htt->num_pending_mgmt_tx > - ar->hw_params.max_probe_resp_desc_thres)) { - ret = -EBUSY; - goto exit; - } + if (is_mgmt && + is_presp && + ar->hw_params.max_probe_resp_desc_thres && + ar->hw_params.max_probe_resp_desc_thres < htt->num_pending_mgmt_tx) + return -EBUSY; + + if (is_mgmt) htt->num_pending_mgmt_tx++; - } htt->num_pending_tx++; if (htt->num_pending_tx == htt->max_num_pending_tx) ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); -exit: - spin_unlock_bh(&htt->tx_lock); - return ret; + return 0; } int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb) @@ -576,20 +567,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int msdu_id = -1; int res; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; - bool limit_mgmt_desc = false; - bool is_probe_resp = false; - - if (ar->hw_params.max_probe_resp_desc_thres) { - limit_mgmt_desc = true; - - if (ieee80211_is_probe_resp(hdr->frame_control)) - is_probe_resp = true; - } - - res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); - - if (res) - goto err; len += sizeof(cmd->hdr); len += sizeof(cmd->mgmt_tx); @@ -598,7 +575,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); if (res < 0) - goto err_tx_dec; + goto err; msdu_id = res; @@ -649,8 +626,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); -err_tx_dec: - ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } @@ -677,26 +652,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, u32 frags_paddr = 0; u32 txbuf_paddr; struct htt_msdu_ext_desc *ext_desc = NULL; - bool limit_mgmt_desc = false; - bool is_probe_resp = false; - - if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) && - ar->hw_params.max_probe_resp_desc_thres) { - limit_mgmt_desc = true; - - if (ieee80211_is_probe_resp(hdr->frame_control)) - is_probe_resp = true; - } - - res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); - if (res) - goto err; spin_lock_bh(&htt->tx_lock); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); if (res < 0) - goto err_tx_dec; + goto err; msdu_id = res; @@ -862,11 +823,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, err_unmap_msdu: dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); err_free_msdu_id: - spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); - spin_unlock_bh(&htt->tx_lock); -err_tx_dec: - ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 67a50a61afb4..140ad250ea69 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3358,13 +3358,11 @@ ath10k_mac_tx_h_get_txpath(struct ath10k *ar, static int ath10k_mac_tx_submit(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode, + enum ath10k_mac_tx_path txpath, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; - enum ath10k_mac_tx_path txpath; - int ret; - - txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); + int ret = -EINVAL; switch (txpath) { case ATH10K_MAC_TX_HTT: @@ -3398,6 +3396,7 @@ static int ath10k_mac_tx(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, enum ath10k_hw_txrx_mode txmode, + enum ath10k_mac_tx_path txpath, struct sk_buff *skb) { struct ieee80211_hw *hw = ar->hw; @@ -3437,7 +3436,7 @@ static int ath10k_mac_tx(struct ath10k *ar, } } - ret = ath10k_mac_tx_submit(ar, txmode, skb); + ret = ath10k_mac_tx_submit(ar, txmode, txpath, skb); if (ret) { ath10k_warn(ar, "failed to submit frame: %d\n", ret); return ret; @@ -3465,6 +3464,7 @@ void ath10k_offchan_tx_work(struct work_struct *work) struct ath10k_peer *peer; struct ath10k_vif *arvif; enum ath10k_hw_txrx_mode txmode; + enum ath10k_mac_tx_path txpath; struct ieee80211_hdr *hdr; struct ieee80211_vif *vif; struct ieee80211_sta *sta; @@ -3533,8 +3533,9 @@ void ath10k_offchan_tx_work(struct work_struct *work) } txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); + txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); - ret = ath10k_mac_tx(ar, vif, sta, txmode, skb); + ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); if (ret) { ath10k_warn(ar, "failed to transmit offchannel frame: %d\n", ret); @@ -3758,19 +3759,53 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ath10k *ar = hw->priv; + struct ath10k_htt *htt = &ar->htt; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct ieee80211_sta *sta = control->sta; + struct ieee80211_hdr *hdr = (void *)skb->data; enum ath10k_hw_txrx_mode txmode; + enum ath10k_mac_tx_path txpath; + bool is_htt; + bool is_mgmt; + bool is_presp; int ret; ath10k_mac_tx_h_fill_cb(ar, vif, skb); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); + txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); + is_htt = (txpath == ATH10K_MAC_TX_HTT || + txpath == ATH10K_MAC_TX_HTT_MGMT); - ret = ath10k_mac_tx(ar, vif, sta, txmode, skb); - if (ret) + if (is_htt) { + spin_lock_bh(&ar->htt.tx_lock); + + is_mgmt = ieee80211_is_mgmt(hdr->frame_control); + is_presp = ieee80211_is_probe_resp(hdr->frame_control); + + ret = ath10k_htt_tx_inc_pending(htt, is_mgmt, is_presp); + if (ret) { + ath10k_warn(ar, "failed to increase tx pending count: %d, dropping\n", + ret); + spin_unlock_bh(&ar->htt.tx_lock); + ieee80211_free_txskb(ar->hw, skb); + return; + } + + spin_unlock_bh(&ar->htt.tx_lock); + } + + ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); + if (ret) { ath10k_warn(ar, "failed to transmit frame: %d\n", ret); + if (is_htt) { + spin_lock_bh(&ar->htt.tx_lock); + ath10k_htt_tx_dec_pending(htt, is_mgmt); + spin_unlock_bh(&ar->htt.tx_lock); + } + return; + } } /* Must not be called with conf_mutex held as workers can use that also. */ diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index fbfb608e48ab..118586ece20e 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -86,7 +86,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, limit_mgmt_desc = true; ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); - __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); + ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); if (htt->num_pending_tx == 0) wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); -- GitLab From bb8f0c6af83f2217aebbe45540e81d31b754b805 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:27 +0200 Subject: [PATCH 0017/9938] ath10k: maintain peer_id for each sta and vif The 10.4.3 firmware with congestion control guarantees that each peer has only a single peer_id mapping. The 1:1 mapping isn't the case for older firmwares (e.g. 10.4.1, 10.2, 10.1) but it should not matter. This 1:1 mapping is going to be only used by future code which inherently (flow-wise) is for 10.4.3. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 2 ++ drivers/net/wireless/ath/ath10k/mac.c | 38 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index a62b62a62266..523585e85f35 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -313,6 +313,7 @@ struct ath10k_sta { u32 bw; u32 nss; u32 smps; + u16 peer_id; struct work_struct update_wk; @@ -335,6 +336,7 @@ struct ath10k_vif { struct list_head list; u32 vdev_id; + u16 peer_id; enum wmi_vdev_type vdev_type; enum wmi_vdev_subtype vdev_subtype; u32 beacon_interval; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 140ad250ea69..72b8f177445d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4421,6 +4421,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_peer *peer; enum wmi_sta_powersave_param param; int ret = 0; u32 value; @@ -4620,6 +4621,24 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->vdev_id, ret); goto err_vdev_delete; } + + spin_lock_bh(&ar->data_lock); + + peer = ath10k_peer_find(ar, arvif->vdev_id, vif->addr); + if (!peer) { + ath10k_warn(ar, "failed to lookup peer %pM on vdev %i\n", + vif->addr, arvif->vdev_id); + spin_unlock_bh(&ar->data_lock); + ret = -ENOENT; + goto err_peer_delete; + } + + arvif->peer_id = find_first_bit(peer->peer_ids, + ATH10K_MAX_NUM_PEER_IDS); + + spin_unlock_bh(&ar->data_lock); + } else { + arvif->peer_id = HTT_INVALID_PEERID; } if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { @@ -5501,6 +5520,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; + struct ath10k_peer *peer; int ret = 0; if (old_state == IEEE80211_STA_NOTEXIST && @@ -5551,6 +5571,24 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, goto exit; } + spin_lock_bh(&ar->data_lock); + + peer = ath10k_peer_find(ar, arvif->vdev_id, sta->addr); + if (!peer) { + ath10k_warn(ar, "failed to lookup peer %pM on vdev %i\n", + vif->addr, arvif->vdev_id); + spin_unlock_bh(&ar->data_lock); + ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); + ath10k_mac_dec_num_stations(arvif, sta); + ret = -ENOENT; + goto exit; + } + + arsta->peer_id = find_first_bit(peer->peer_ids, + ATH10K_MAX_NUM_PEER_IDS); + + spin_unlock_bh(&ar->data_lock); + if (!sta->tdls) goto exit; -- GitLab From 6942726f7f7bfc3c197795befe84c8e3c57435a0 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:30 +0200 Subject: [PATCH 0018/9938] ath10k: add fast peer_map lookup The pull-push functionality of 10.4 will be based on peer_id and tid. These will need to be mapped, eventually, to ieee80211_txq to be used with ieee80211_tx_dequeue(). Iterating over existing stations every time peer_id needs to be mapped to a station would be inefficient wrt CPU time. The new firmware, which will be the only user of the code flow-wise, will guarantee to use low peer_ids first so despite peer_map's apparent huge size d-cache thrashing should not be a problem. Older firmware hot paths will effectively not use peer_map. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 4 ++ drivers/net/wireless/ath/ath10k/mac.c | 71 +++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/txrx.c | 2 + 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 523585e85f35..5f447444fe97 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -297,6 +297,9 @@ struct ath10k_dfs_stats { struct ath10k_peer { struct list_head list; + struct ieee80211_vif *vif; + struct ieee80211_sta *sta; + int vdev_id; u8 addr[ETH_ALEN]; DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS); @@ -791,6 +794,7 @@ struct ath10k { struct list_head arvifs; struct list_head peers; + struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS]; wait_queue_head_t peer_mapping_wq; /* protected by conf_mutex */ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 72b8f177445d..4b69a373382b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -618,10 +618,15 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw, *def = &conf->def; } -static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr, +static int ath10k_peer_create(struct ath10k *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + u32 vdev_id, + const u8 *addr, enum wmi_peer_type peer_type) { struct ath10k_vif *arvif; + struct ath10k_peer *peer; int num_peers = 0; int ret; @@ -650,6 +655,22 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr, return ret; } + spin_lock_bh(&ar->data_lock); + + peer = ath10k_peer_find(ar, vdev_id, addr); + if (!peer) { + ath10k_warn(ar, "failed to find peer %pM on vdev %i after creation\n", + addr, vdev_id); + ath10k_wmi_peer_delete(ar, vdev_id, addr); + spin_unlock_bh(&ar->data_lock); + return -ENOENT; + } + + peer->vif = vif; + peer->sta = sta; + + spin_unlock_bh(&ar->data_lock); + ar->num_peers++; return 0; @@ -731,6 +752,7 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) { struct ath10k_peer *peer, *tmp; + int peer_id; lockdep_assert_held(&ar->conf_mutex); @@ -742,6 +764,11 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n", peer->addr, vdev_id); + for_each_set_bit(peer_id, peer->peer_ids, + ATH10K_MAX_NUM_PEER_IDS) { + ar->peer_map[peer_id] = NULL; + } + list_del(&peer->list); kfree(peer); ar->num_peers--; @@ -3506,7 +3533,8 @@ void ath10k_offchan_tx_work(struct work_struct *work) peer_addr, vdev_id); if (!peer) { - ret = ath10k_peer_create(ar, vdev_id, peer_addr, + ret = ath10k_peer_create(ar, NULL, NULL, vdev_id, + peer_addr, WMI_PEER_TYPE_DEFAULT); if (ret) ath10k_warn(ar, "failed to create peer %pM on vdev %d: %d\n", @@ -4614,8 +4642,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, if (arvif->vdev_type == WMI_VDEV_TYPE_AP || arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { - ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr, - WMI_PEER_TYPE_DEFAULT); + ret = ath10k_peer_create(ar, vif, NULL, arvif->vdev_id, + vif->addr, WMI_PEER_TYPE_DEFAULT); if (ret) { ath10k_warn(ar, "failed to create vdev %i peer for AP/IBSS: %d\n", arvif->vdev_id, ret); @@ -4749,7 +4777,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_peer *peer; int ret; + int i; cancel_work_sync(&arvif->ap_csa_work); cancel_delayed_work_sync(&arvif->connection_loss_work); @@ -4803,6 +4833,20 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); } + spin_lock_bh(&ar->data_lock); + for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { + peer = ar->peer_map[i]; + if (!peer) + continue; + + if (peer->vif == vif) { + ath10k_warn(ar, "found vif peer %pM entry on vdev %i after it was supposedly removed\n", + vif->addr, arvif->vdev_id); + peer->vif = NULL; + } + } + spin_unlock_bh(&ar->data_lock); + ath10k_peer_cleanup(ar, arvif->vdev_id); if (vif->type == NL80211_IFTYPE_MONITOR) { @@ -5522,6 +5566,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; struct ath10k_peer *peer; int ret = 0; + int i; if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { @@ -5562,8 +5607,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, if (sta->tdls) peer_type = WMI_PEER_TYPE_TDLS; - ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr, - peer_type); + ret = ath10k_peer_create(ar, vif, sta, arvif->vdev_id, + sta->addr, peer_type); if (ret) { ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n", sta->addr, arvif->vdev_id, ret); @@ -5651,6 +5696,20 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ath10k_mac_dec_num_stations(arvif, sta); + spin_lock_bh(&ar->data_lock); + for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { + peer = ar->peer_map[i]; + if (!peer) + continue; + + if (peer->sta == sta) { + ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n", + sta->addr, arvif->vdev_id); + peer->sta = NULL; + } + } + spin_unlock_bh(&ar->data_lock); + if (!sta->tdls) goto exit; diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 118586ece20e..202e5192235b 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -203,6 +203,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n", ev->vdev_id, ev->addr, ev->peer_id); + ar->peer_map[ev->peer_id] = peer; set_bit(ev->peer_id, peer->peer_ids); exit: spin_unlock_bh(&ar->data_lock); @@ -225,6 +226,7 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n", peer->vdev_id, peer->addr, ev->peer_id); + ar->peer_map[ev->peer_id] = NULL; clear_bit(ev->peer_id, peer->peer_ids); if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) { -- GitLab From 839ae6371e56594f06ef05a64fc90cd156007232 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:32 +0200 Subject: [PATCH 0019/9938] ath10k: add new htt message generation/parsing logic This merely adds some parsing, generation and sanity checks with placeholders for real code/functionality to be added later. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 5 + drivers/net/wireless/ath/ath10k/htt_rx.c | 198 ++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/htt_tx.c | 53 ++++++ 3 files changed, 255 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index cb6d4fd687da..65dcd22f31df 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1752,6 +1752,11 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, u8 max_subfrms_ampdu, u8 max_subfrms_amsdu); void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb); +int ath10k_htt_tx_fetch_resp(struct ath10k *ar, + __le32 token, + __le16 fetch_seq_num, + struct htt_tx_fetch_record *records, + size_t num_records); void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool is_mgmt); diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index ae9b686a4e91..8b367e98f929 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1982,6 +1982,198 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) tasklet_schedule(&htt->rx_replenish_task); } +static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, + const __le32 *resp_ids, + int num_resp_ids) +{ + int i; + u32 resp_id; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch confirm num_resp_ids %d\n", + num_resp_ids); + + for (i = 0; i < num_resp_ids; i++) { + resp_id = le32_to_cpu(resp_ids[i]); + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch confirm resp_id %u\n", + resp_id); + + /* TODO: free resp_id */ + } +} + +static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) +{ + struct htt_resp *resp = (struct htt_resp *)skb->data; + struct htt_tx_fetch_record *record; + size_t len; + size_t max_num_bytes; + size_t max_num_msdus; + const __le32 *resp_ids; + u16 num_records; + u16 num_resp_ids; + u16 peer_id; + u8 tid; + int i; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n"); + + len = sizeof(resp->hdr) + sizeof(resp->tx_fetch_ind); + if (unlikely(skb->len < len)) { + ath10k_warn(ar, "received corrupted tx_fetch_ind event: buffer too short\n"); + return; + } + + num_records = le16_to_cpu(resp->tx_fetch_ind.num_records); + num_resp_ids = le16_to_cpu(resp->tx_fetch_ind.num_resp_ids); + + len += sizeof(resp->tx_fetch_ind.records[0]) * num_records; + len += sizeof(resp->tx_fetch_ind.resp_ids[0]) * num_resp_ids; + + if (unlikely(skb->len < len)) { + ath10k_warn(ar, "received corrupted tx_fetch_ind event: too many records/resp_ids\n"); + return; + } + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind num records %hu num resps %hu seq %hu\n", + num_records, num_resp_ids, + le16_to_cpu(resp->tx_fetch_ind.fetch_seq_num)); + + /* TODO: runtime sanity checks */ + + for (i = 0; i < num_records; i++) { + record = &resp->tx_fetch_ind.records[i]; + peer_id = MS(le16_to_cpu(record->info), + HTT_TX_FETCH_RECORD_INFO_PEER_ID); + tid = MS(le16_to_cpu(record->info), + HTT_TX_FETCH_RECORD_INFO_TID); + max_num_msdus = le16_to_cpu(record->num_msdus); + max_num_bytes = le32_to_cpu(record->num_bytes); + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch record %i peer_id %hu tid %hhu msdus %zu bytes %zu\n", + i, peer_id, tid, max_num_msdus, max_num_bytes); + + if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) || + unlikely(tid >= ar->htt.tx_q_state.num_tids)) { + ath10k_warn(ar, "received out of range peer_id %hu tid %hhu\n", + peer_id, tid); + continue; + } + + /* TODO: dequeue and submit tx to device */ + } + + resp_ids = ath10k_htt_get_tx_fetch_ind_resp_ids(&resp->tx_fetch_ind); + ath10k_htt_rx_tx_fetch_resp_id_confirm(ar, resp_ids, num_resp_ids); + + /* TODO: generate and send fetch response to device */ +} + +static void ath10k_htt_rx_tx_fetch_confirm(struct ath10k *ar, + struct sk_buff *skb) +{ + const struct htt_resp *resp = (void *)skb->data; + size_t len; + int num_resp_ids; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch confirm\n"); + + len = sizeof(resp->hdr) + sizeof(resp->tx_fetch_confirm); + if (unlikely(skb->len < len)) { + ath10k_warn(ar, "received corrupted tx_fetch_confirm event: buffer too short\n"); + return; + } + + num_resp_ids = le16_to_cpu(resp->tx_fetch_confirm.num_resp_ids); + len += sizeof(resp->tx_fetch_confirm.resp_ids[0]) * num_resp_ids; + + if (unlikely(skb->len < len)) { + ath10k_warn(ar, "received corrupted tx_fetch_confirm event: resp_ids buffer overflow\n"); + return; + } + + ath10k_htt_rx_tx_fetch_resp_id_confirm(ar, + resp->tx_fetch_confirm.resp_ids, + num_resp_ids); +} + +static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar, + struct sk_buff *skb) +{ + const struct htt_resp *resp = (void *)skb->data; + const struct htt_tx_mode_switch_record *record; + size_t len; + size_t num_records; + enum htt_tx_mode_switch_mode mode; + bool enable; + u16 info0; + u16 info1; + u16 threshold; + u16 peer_id; + u8 tid; + int i; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx mode switch ind\n"); + + len = sizeof(resp->hdr) + sizeof(resp->tx_mode_switch_ind); + if (unlikely(skb->len < len)) { + ath10k_warn(ar, "received corrupted tx_mode_switch_ind event: buffer too short\n"); + return; + } + + info0 = le16_to_cpu(resp->tx_mode_switch_ind.info0); + info1 = le16_to_cpu(resp->tx_mode_switch_ind.info1); + + enable = !!(info0 & HTT_TX_MODE_SWITCH_IND_INFO0_ENABLE); + num_records = MS(info0, HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD); + mode = MS(info1, HTT_TX_MODE_SWITCH_IND_INFO1_MODE); + threshold = MS(info1, HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD); + + ath10k_dbg(ar, ATH10K_DBG_HTT, + "htt rx tx mode switch ind info0 0x%04hx info1 0x%04hx enable %d num records %zd mode %d threshold %hu\n", + info0, info1, enable, num_records, mode, threshold); + + len += sizeof(resp->tx_mode_switch_ind.records[0]) * num_records; + + if (unlikely(skb->len < len)) { + ath10k_warn(ar, "received corrupted tx_mode_switch_mode_ind event: too many records\n"); + return; + } + + switch (mode) { + case HTT_TX_MODE_SWITCH_PUSH: + case HTT_TX_MODE_SWITCH_PUSH_PULL: + break; + default: + ath10k_warn(ar, "received invalid tx_mode_switch_mode_ind mode %d, ignoring\n", + mode); + return; + } + + if (!enable) + return; + + /* TODO: apply configuration */ + + for (i = 0; i < num_records; i++) { + record = &resp->tx_mode_switch_ind.records[i]; + info0 = le16_to_cpu(record->info0); + peer_id = MS(info0, HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID); + tid = MS(info0, HTT_TX_MODE_SWITCH_RECORD_INFO0_TID); + + if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) || + unlikely(tid >= ar->htt.tx_q_state.num_tids)) { + ath10k_warn(ar, "received out of range peer_id %hu tid %hhu\n", + peer_id, tid); + continue; + } + + /* TODO: apply configuration */ + } + + /* TODO: apply configuration */ +} + void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; @@ -2120,9 +2312,13 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) case HTT_T2H_MSG_TYPE_AGGR_CONF: break; case HTT_T2H_MSG_TYPE_TX_FETCH_IND: + ath10k_htt_rx_tx_fetch_ind(ar, skb); + break; case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: + ath10k_htt_rx_tx_fetch_confirm(ar, skb); + break; case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: - /* TODO: Implement pull-push logic */ + ath10k_htt_rx_tx_mode_switch_ind(ar, skb); break; case HTT_T2H_MSG_TYPE_EN_STATS: default: diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 860661d3812f..225f0561b3fd 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -526,6 +526,59 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, return 0; } +int ath10k_htt_tx_fetch_resp(struct ath10k *ar, + __le32 token, + __le16 fetch_seq_num, + struct htt_tx_fetch_record *records, + size_t num_records) +{ + struct sk_buff *skb; + struct htt_cmd *cmd; + u16 resp_id; + int len = 0; + int ret; + + len += sizeof(cmd->hdr); + len += sizeof(cmd->tx_fetch_resp); + len += sizeof(cmd->tx_fetch_resp.records[0]) * num_records; + + skb = ath10k_htc_alloc_skb(ar, len); + if (!skb) + return -ENOMEM; + + resp_id = 0; /* TODO: allocate resp_id */ + ret = 0; + if (ret) + goto err_free_skb; + + skb_put(skb, len); + cmd = (struct htt_cmd *)skb->data; + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FETCH_RESP; + cmd->tx_fetch_resp.resp_id = cpu_to_le16(resp_id); + cmd->tx_fetch_resp.fetch_seq_num = fetch_seq_num; + cmd->tx_fetch_resp.num_records = cpu_to_le16(num_records); + cmd->tx_fetch_resp.token = token; + + memcpy(cmd->tx_fetch_resp.records, records, + sizeof(records[0]) * num_records); + + ret = ath10k_htc_send(&ar->htc, ar->htt.eid, skb); + if (ret) { + ath10k_warn(ar, "failed to submit htc command: %d\n", ret); + goto err_free_resp_id; + } + + return 0; + +err_free_resp_id: + (void)resp_id; /* TODO: free resp_id */ + +err_free_skb: + dev_kfree_skb_any(skb); + + return ret; +} + static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- GitLab From 299468782d94331f99a7eeb6e0d56598863be9fe Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:34 +0200 Subject: [PATCH 0020/9938] ath10k: implement wake_tx_queue This implements very basic support for software queueing. It also contains some knobs that will be patched later. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 2 + drivers/net/wireless/ath/ath10k/core.h | 7 ++ drivers/net/wireless/ath/ath10k/htt_rx.c | 3 + drivers/net/wireless/ath/ath10k/mac.c | 144 +++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/mac.h | 1 + 5 files changed, 157 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index c84c2d30ef1f..6f606f8fce25 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2048,7 +2048,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, mutex_init(&ar->conf_mutex); spin_lock_init(&ar->data_lock); + spin_lock_init(&ar->txqs_lock); + INIT_LIST_HEAD(&ar->txqs); INIT_LIST_HEAD(&ar->peers); init_waitqueue_head(&ar->peer_mapping_wq); init_waitqueue_head(&ar->htt.empty_tx_wq); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 5f447444fe97..7df35628ca35 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -308,6 +308,10 @@ struct ath10k_peer { struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; }; +struct ath10k_txq { + struct list_head list; +}; + struct ath10k_sta { struct ath10k_vif *arvif; @@ -791,7 +795,10 @@ struct ath10k { /* protects shared structure data */ spinlock_t data_lock; + /* protects: ar->txqs, artxq->list */ + spinlock_t txqs_lock; + struct list_head txqs; struct list_head arvifs; struct list_head peers; struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS]; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 8b367e98f929..4a25a1d63843 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2242,6 +2242,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) } ath10k_txrx_tx_unref(htt, &tx_done); + ath10k_mac_tx_push_pending(ar); break; } case HTT_T2H_MSG_TYPE_TX_COMPL_IND: @@ -2374,6 +2375,8 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) dev_kfree_skb_any(skb); } + ath10k_mac_tx_push_pending(ar); + while ((skb = __skb_dequeue(&rx_q))) { resp = (struct htt_resp *)skb->data; spin_lock_bh(&htt->rx_ring.lock); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4b69a373382b..74a42e3465e4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3620,6 +3620,123 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) } } +static void ath10k_mac_txq_init(struct ieee80211_txq *txq) +{ + struct ath10k_txq *artxq = (void *)txq->drv_priv; + + if (!txq) + return; + + INIT_LIST_HEAD(&artxq->list); +} + +static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) +{ + struct ath10k_txq *artxq = (void *)txq->drv_priv; + + if (!txq) + return; + + spin_lock_bh(&ar->txqs_lock); + if (!list_empty(&artxq->list)) + list_del_init(&artxq->list); + spin_unlock_bh(&ar->txqs_lock); +} + +static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + return 1; /* TBD */ +} + +static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + const bool is_mgmt = false; + const bool is_presp = false; + struct ath10k *ar = hw->priv; + struct ath10k_htt *htt = &ar->htt; + struct ieee80211_vif *vif = txq->vif; + struct ieee80211_sta *sta = txq->sta; + enum ath10k_hw_txrx_mode txmode; + enum ath10k_mac_tx_path txpath; + struct sk_buff *skb; + int ret; + + spin_lock_bh(&ar->htt.tx_lock); + ret = ath10k_htt_tx_inc_pending(htt, is_mgmt, is_presp); + spin_unlock_bh(&ar->htt.tx_lock); + + if (ret) + return ret; + + skb = ieee80211_tx_dequeue(hw, txq); + if (!skb) { + spin_lock_bh(&ar->htt.tx_lock); + ath10k_htt_tx_dec_pending(htt, is_mgmt); + spin_unlock_bh(&ar->htt.tx_lock); + + return -ENOENT; + } + + ath10k_mac_tx_h_fill_cb(ar, vif, skb); + + txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); + txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); + + ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); + if (unlikely(ret)) { + ath10k_warn(ar, "failed to push frame: %d\n", ret); + + spin_lock_bh(&ar->htt.tx_lock); + ath10k_htt_tx_dec_pending(htt, is_mgmt); + spin_unlock_bh(&ar->htt.tx_lock); + + return ret; + } + + return 0; +} + +void ath10k_mac_tx_push_pending(struct ath10k *ar) +{ + struct ieee80211_hw *hw = ar->hw; + struct ieee80211_txq *txq; + struct ath10k_txq *artxq; + struct ath10k_txq *last; + int ret; + int max; + + spin_lock_bh(&ar->txqs_lock); + rcu_read_lock(); + + last = list_last_entry(&ar->txqs, struct ath10k_txq, list); + while (!list_empty(&ar->txqs)) { + artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); + txq = container_of((void *)artxq, struct ieee80211_txq, + drv_priv); + + /* Prevent aggressive sta/tid taking over tx queue */ + max = 16; + while (max--) { + ret = ath10k_mac_tx_push_txq(hw, txq); + if (ret < 0) + break; + } + + list_del_init(&artxq->list); + + if (artxq == last || (ret < 0 && ret != -ENOENT)) { + if (ret != -ENOENT) + list_add_tail(&artxq->list, &ar->txqs); + break; + } + } + + rcu_read_unlock(); + spin_unlock_bh(&ar->txqs_lock); +} + /************/ /* Scanning */ /************/ @@ -3836,6 +3953,22 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, } } +static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + struct ath10k *ar = hw->priv; + struct ath10k_txq *artxq = (void *)txq->drv_priv; + + if (ath10k_mac_tx_can_push(hw, txq)) { + spin_lock_bh(&ar->txqs_lock); + if (list_empty(&artxq->list)) + list_add_tail(&artxq->list, &ar->txqs); + spin_unlock_bh(&ar->txqs_lock); + + tasklet_schedule(&ar->htt.txrx_compl_task); + } +} + /* Must not be called with conf_mutex held as workers can use that also. */ void ath10k_drain_tx(struct ath10k *ar) { @@ -4462,6 +4595,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); memset(arvif, 0, sizeof(*arvif)); + ath10k_mac_txq_init(vif->txq); arvif->ar = ar; arvif->vif = vif; @@ -4860,6 +4994,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_mac_vif_tx_unlock_all(arvif); spin_unlock_bh(&ar->htt.tx_lock); + ath10k_mac_txq_unref(ar, vif->txq); + mutex_unlock(&ar->conf_mutex); } @@ -5573,6 +5709,9 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, memset(arsta, 0, sizeof(*arsta)); arsta->arvif = arvif; INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk); + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + ath10k_mac_txq_init(sta->txq[i]); } /* cancel must be done outside the mutex to avoid deadlock */ @@ -5710,6 +5849,9 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, } spin_unlock_bh(&ar->data_lock); + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + ath10k_mac_txq_unref(ar, sta->txq[i]); + if (!sta->tdls) goto exit; @@ -7013,6 +7155,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, static const struct ieee80211_ops ath10k_ops = { .tx = ath10k_mac_op_tx, + .wake_tx_queue = ath10k_mac_op_wake_tx_queue, .start = ath10k_start, .stop = ath10k_stop, .config = ath10k_config, @@ -7467,6 +7610,7 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->vif_data_size = sizeof(struct ath10k_vif); ar->hw->sta_data_size = sizeof(struct ath10k_sta); + ar->hw->txq_data_size = sizeof(struct ath10k_txq); ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 53091588090d..453f606a250e 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -75,6 +75,7 @@ void ath10k_mac_tx_unlock(struct ath10k *ar, int reason); void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason); void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason); bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar); +void ath10k_mac_tx_push_pending(struct ath10k *ar); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { -- GitLab From c1a43d9720d8dcde1eb735f6cbdba181e564ec20 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:36 +0200 Subject: [PATCH 0021/9938] ath10k: implement updating shared htt txq state Firmware 10.4.3 onwards can support a pull-push Tx model where it shares a Tx queue state with the host. The host updates the DMA region it pointed to during HTT setup whenever number of software queued from (on host) changes. Based on this information firmware issues fetch requests to the host telling the host how many frames from a list of given stations/tids should be submitted to the firmware. The code won't be called because not all appropriate HTT events are processed yet. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 3 + drivers/net/wireless/ath/ath10k/htt_tx.c | 104 +++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/mac.c | 3 + 3 files changed, 110 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 65dcd22f31df..b1e40f44e76b 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1667,6 +1667,7 @@ struct ath10k_htt { } txbuf; struct { + bool enabled; struct htt_q_state *vaddr; dma_addr_t paddr; u16 num_peers; @@ -1758,6 +1759,8 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar, struct htt_tx_fetch_record *records, size_t num_records); +void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw, + struct ieee80211_txq *txq); void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool is_mgmt); int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 225f0561b3fd..6643be8692b5 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -22,6 +22,110 @@ #include "txrx.h" #include "debug.h" +static u8 ath10k_htt_tx_txq_calc_size(size_t count) +{ + int exp; + int factor; + + exp = 0; + factor = count >> 7; + + while (factor >= 64 && exp < 4) { + factor >>= 3; + exp++; + } + + if (exp == 4) + return 0xff; + + if (count > 0) + factor = max(1, factor); + + return SM(exp, HTT_TX_Q_STATE_ENTRY_EXP) | + SM(factor, HTT_TX_Q_STATE_ENTRY_FACTOR); +} + +static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + struct ath10k *ar = hw->priv; + struct ath10k_sta *arsta = (void *)txq->sta->drv_priv; + struct ath10k_vif *arvif = (void *)txq->vif->drv_priv; + unsigned long frame_cnt; + unsigned long byte_cnt; + int idx; + u32 bit; + u16 peer_id; + u8 tid; + u8 count; + + lockdep_assert_held(&ar->htt.tx_lock); + + if (!ar->htt.tx_q_state.enabled) + return; + + if (txq->sta) + peer_id = arsta->peer_id; + else + peer_id = arvif->peer_id; + + tid = txq->tid; + bit = BIT(peer_id % 32); + idx = peer_id / 32; + + ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt); + count = ath10k_htt_tx_txq_calc_size(byte_cnt); + + if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) || + unlikely(tid >= ar->htt.tx_q_state.num_tids)) { + ath10k_warn(ar, "refusing to update txq for peer_id %hu tid %hhu due to out of bounds\n", + peer_id, tid); + return; + } + + ar->htt.tx_q_state.vaddr->count[tid][peer_id] = count; + ar->htt.tx_q_state.vaddr->map[tid][idx] &= ~bit; + ar->htt.tx_q_state.vaddr->map[tid][idx] |= count ? bit : 0; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update peer_id %hu tid %hhu count %hhu\n", + peer_id, tid, count); +} + +static void __ath10k_htt_tx_txq_sync(struct ath10k *ar) +{ + u32 seq; + size_t size; + + lockdep_assert_held(&ar->htt.tx_lock); + + if (!ar->htt.tx_q_state.enabled) + return; + + seq = le32_to_cpu(ar->htt.tx_q_state.vaddr->seq); + seq++; + ar->htt.tx_q_state.vaddr->seq = cpu_to_le32(seq); + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update commit seq %u\n", + seq); + + size = sizeof(*ar->htt.tx_q_state.vaddr); + dma_sync_single_for_device(ar->dev, + ar->htt.tx_q_state.paddr, + size, + DMA_TO_DEVICE); +} + +void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + struct ath10k *ar = hw->priv; + + spin_lock_bh(&ar->htt.tx_lock); + __ath10k_htt_tx_txq_recalc(hw, txq); + __ath10k_htt_tx_txq_sync(ar); + spin_unlock_bh(&ar->htt.tx_lock); +} + void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool is_mgmt) { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 74a42e3465e4..900c64b65b43 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3725,6 +3725,7 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar) } list_del_init(&artxq->list); + ath10k_htt_tx_txq_update(hw, txq); if (artxq == last || (ret < 0 && ret != -ENOENT)) { if (ret != -ENOENT) @@ -3967,6 +3968,8 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, tasklet_schedule(&ar->htt.txrx_compl_task); } + + ath10k_htt_tx_txq_update(hw, txq); } /* Must not be called with conf_mutex held as workers can use that also. */ -- GitLab From dd4717b6f45e70b609d4282667eb0a89f9660268 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:39 +0200 Subject: [PATCH 0022/9938] ath10k: store txq in skb_cb This will be necessary for later. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7df35628ca35..89f789f3e5b4 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -98,6 +98,7 @@ struct ath10k_skb_cb { u8 eid; u16 msdu_id; struct ieee80211_vif *vif; + struct ieee80211_txq *txq; } __packed; struct ath10k_skb_rxcb { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 900c64b65b43..8d02d53fdc2c 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3307,6 +3307,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, struct ieee80211_vif *vif, + struct ieee80211_txq *txq, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (void *)skb->data; @@ -3323,6 +3324,7 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, cb->flags |= ATH10K_SKB_F_QOS; cb->vif = vif; + cb->txq = txq; } bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) @@ -3633,6 +3635,9 @@ static void ath10k_mac_txq_init(struct ieee80211_txq *txq) static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) { struct ath10k_txq *artxq = (void *)txq->drv_priv; + struct ath10k_skb_cb *cb; + struct sk_buff *msdu; + int msdu_id; if (!txq) return; @@ -3641,6 +3646,14 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) if (!list_empty(&artxq->list)) list_del_init(&artxq->list); spin_unlock_bh(&ar->txqs_lock); + + spin_lock_bh(&ar->htt.tx_lock); + idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) { + cb = ATH10K_SKB_CB(msdu); + if (cb->txq == txq) + cb->txq = NULL; + } + spin_unlock_bh(&ar->htt.tx_lock); } static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, @@ -3679,7 +3692,7 @@ static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, return -ENOENT; } - ath10k_mac_tx_h_fill_cb(ar, vif, skb); + ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); @@ -3909,6 +3922,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct ieee80211_sta *sta = control->sta; + struct ieee80211_txq *txq = NULL; struct ieee80211_hdr *hdr = (void *)skb->data; enum ath10k_hw_txrx_mode txmode; enum ath10k_mac_tx_path txpath; @@ -3917,7 +3931,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, bool is_presp; int ret; - ath10k_mac_tx_h_fill_cb(ar, vif, skb); + ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); @@ -4985,6 +4999,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); ath10k_peer_cleanup(ar, arvif->vdev_id); + ath10k_mac_txq_unref(ar, vif->txq); if (vif->type == NL80211_IFTYPE_MONITOR) { ar->monitor_arvif = NULL; -- GitLab From 3cc0fef6170dce8e7d4ec29afb4f34267fb9bf14 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:41 +0200 Subject: [PATCH 0023/9938] ath10k: keep track of queue depth per txq This will be necessary for later. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 5 +++++ drivers/net/wireless/ath/ath10k/txrx.c | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 89f789f3e5b4..926ecb2244a5 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -311,6 +311,7 @@ struct ath10k_peer { struct ath10k_txq { struct list_head list; + unsigned long num_fw_queued; }; struct ath10k_sta { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8d02d53fdc2c..5bf614f1f75a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3669,6 +3669,7 @@ static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, const bool is_presp = false; struct ath10k *ar = hw->priv; struct ath10k_htt *htt = &ar->htt; + struct ath10k_txq *artxq = (void *)txq->drv_priv; struct ieee80211_vif *vif = txq->vif; struct ieee80211_sta *sta = txq->sta; enum ath10k_hw_txrx_mode txmode; @@ -3708,6 +3709,10 @@ static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, return ret; } + spin_lock_bh(&ar->htt.tx_lock); + artxq->num_fw_queued++; + spin_unlock_bh(&ar->htt.tx_lock); + return 0; } diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 202e5192235b..ea4d3000c8c3 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -55,7 +55,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct device *dev = ar->dev; struct ieee80211_tx_info *info; + struct ieee80211_txq *txq; struct ath10k_skb_cb *skb_cb; + struct ath10k_txq *artxq; struct sk_buff *msdu; bool limit_mgmt_desc = false; @@ -80,11 +82,16 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, } skb_cb = ATH10K_SKB_CB(msdu); + txq = skb_cb->txq; + artxq = (void *)txq->drv_priv; if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) && ar->hw_params.max_probe_resp_desc_thres) limit_mgmt_desc = true; + if (txq) + artxq->num_fw_queued--; + ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); if (htt->num_pending_tx == 0) -- GitLab From 426e10eaf76d7229ed6c2978f0d473d04ba0b377 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Sun, 6 Mar 2016 16:14:43 +0200 Subject: [PATCH 0024/9938] ath10k: implement push-pull tx The current/old tx path design was that host, at its own leisure, pushed tx frames to the device. For HTT there was ~1000-1400 msdu queue depth. After reaching that limit the driver would request mac80211 to stop queues. There was little control over what packets got in there as far as DA/RA was considered so it was rather easy to starve per-station traffic flows. With MU-MIMO this became a significant problem because the queue depth was insufficient to buffer frames from multiple clients (which could have different signal quality and capabilities) in an efficient fashion. Hence the new tx path in 10.4 was introduced: a pull-push mode. Firmware and host can share tx queue state via DMA. The state is logically a 2 dimensional array addressed via peer_id+tid pair. Each entry is a counter (either number of bytes or packets. Host keeps it updated and firmware uses it for scheduling Tx pull requests to host. This allows MU-MIMO to become a lot more effective with 10+ clients. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/htt.h | 6 ++ drivers/net/wireless/ath/ath10k/htt_rx.c | 113 +++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 39 ++++++-- drivers/net/wireless/ath/ath10k/mac.c | 44 ++++++++- drivers/net/wireless/ath/ath10k/mac.h | 5 + 6 files changed, 186 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 926ecb2244a5..3050e497fd22 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -312,6 +312,7 @@ struct ath10k_peer { struct ath10k_txq { struct list_head list; unsigned long num_fw_queued; + unsigned long num_push_allowed; }; struct ath10k_sta { diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index b1e40f44e76b..02cf55d306e8 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1652,6 +1652,7 @@ struct ath10k_htt { struct sk_buff_head tx_compl_q; struct sk_buff_head rx_compl_q; struct sk_buff_head rx_in_ord_compl_q; + struct sk_buff_head tx_fetch_ind_q; /* rx_status template */ struct ieee80211_rx_status rx_status; @@ -1670,8 +1671,10 @@ struct ath10k_htt { bool enabled; struct htt_q_state *vaddr; dma_addr_t paddr; + u16 num_push_allowed; u16 num_peers; u16 num_tids; + enum htt_tx_mode_switch_mode mode; enum htt_q_depth_type type; } tx_q_state; }; @@ -1761,6 +1764,9 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar, void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw, struct ieee80211_txq *txq); +void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw, + struct ieee80211_txq *txq); +void ath10k_htt_tx_txq_sync(struct ath10k *ar); void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool is_mgmt); int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 4a25a1d63843..40f969c72de8 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -229,6 +229,7 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) skb_queue_purge(&htt->tx_compl_q); skb_queue_purge(&htt->rx_compl_q); skb_queue_purge(&htt->rx_in_ord_compl_q); + skb_queue_purge(&htt->tx_fetch_ind_q); ath10k_htt_rx_ring_free(htt); @@ -569,6 +570,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) skb_queue_head_init(&htt->tx_compl_q); skb_queue_head_init(&htt->rx_compl_q); skb_queue_head_init(&htt->rx_in_ord_compl_q); + skb_queue_head_init(&htt->tx_fetch_ind_q); tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task, (unsigned long)htt); @@ -2004,16 +2006,21 @@ static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) { + struct ieee80211_hw *hw = ar->hw; + struct ieee80211_txq *txq; struct htt_resp *resp = (struct htt_resp *)skb->data; struct htt_tx_fetch_record *record; size_t len; size_t max_num_bytes; size_t max_num_msdus; + size_t num_bytes; + size_t num_msdus; const __le32 *resp_ids; u16 num_records; u16 num_resp_ids; u16 peer_id; u8 tid; + int ret; int i; ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n"); @@ -2039,7 +2046,17 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) num_records, num_resp_ids, le16_to_cpu(resp->tx_fetch_ind.fetch_seq_num)); - /* TODO: runtime sanity checks */ + if (!ar->htt.tx_q_state.enabled) { + ath10k_warn(ar, "received unexpected tx_fetch_ind event: not enabled\n"); + return; + } + + if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH) { + ath10k_warn(ar, "received unexpected tx_fetch_ind event: in push mode\n"); + return; + } + + rcu_read_lock(); for (i = 0; i < num_records; i++) { record = &resp->tx_fetch_ind.records[i]; @@ -2060,13 +2077,56 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) continue; } - /* TODO: dequeue and submit tx to device */ + spin_lock_bh(&ar->data_lock); + txq = ath10k_mac_txq_lookup(ar, peer_id, tid); + spin_unlock_bh(&ar->data_lock); + + /* It is okay to release the lock and use txq because RCU read + * lock is held. + */ + + if (unlikely(!txq)) { + ath10k_warn(ar, "failed to lookup txq for peer_id %hu tid %hhu\n", + peer_id, tid); + continue; + } + + num_msdus = 0; + num_bytes = 0; + + while (num_msdus < max_num_msdus && + num_bytes < max_num_bytes) { + ret = ath10k_mac_tx_push_txq(hw, txq); + if (ret < 0) + break; + + num_msdus++; + num_bytes += ret; + } + + record->num_msdus = cpu_to_le16(num_msdus); + record->num_bytes = cpu_to_le32(num_bytes); + + ath10k_htt_tx_txq_recalc(hw, txq); } + rcu_read_unlock(); + resp_ids = ath10k_htt_get_tx_fetch_ind_resp_ids(&resp->tx_fetch_ind); ath10k_htt_rx_tx_fetch_resp_id_confirm(ar, resp_ids, num_resp_ids); - /* TODO: generate and send fetch response to device */ + ret = ath10k_htt_tx_fetch_resp(ar, + resp->tx_fetch_ind.token, + resp->tx_fetch_ind.fetch_seq_num, + resp->tx_fetch_ind.records, + num_records); + if (unlikely(ret)) { + ath10k_warn(ar, "failed to submit tx fetch resp for token 0x%08x: %d\n", + le32_to_cpu(resp->tx_fetch_ind.token), ret); + /* FIXME: request fw restart */ + } + + ath10k_htt_tx_txq_sync(ar); } static void ath10k_htt_rx_tx_fetch_confirm(struct ath10k *ar, @@ -2102,6 +2162,8 @@ static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar, { const struct htt_resp *resp = (void *)skb->data; const struct htt_tx_mode_switch_record *record; + struct ieee80211_txq *txq; + struct ath10k_txq *artxq; size_t len; size_t num_records; enum htt_tx_mode_switch_mode mode; @@ -2153,7 +2215,11 @@ static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar, if (!enable) return; - /* TODO: apply configuration */ + ar->htt.tx_q_state.enabled = enable; + ar->htt.tx_q_state.mode = mode; + ar->htt.tx_q_state.num_push_allowed = threshold; + + rcu_read_lock(); for (i = 0; i < num_records; i++) { record = &resp->tx_mode_switch_ind.records[i]; @@ -2168,10 +2234,29 @@ static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar, continue; } - /* TODO: apply configuration */ + spin_lock_bh(&ar->data_lock); + txq = ath10k_mac_txq_lookup(ar, peer_id, tid); + spin_unlock_bh(&ar->data_lock); + + /* It is okay to release the lock and use txq because RCU read + * lock is held. + */ + + if (unlikely(!txq)) { + ath10k_warn(ar, "failed to lookup txq for peer_id %hu tid %hhu\n", + peer_id, tid); + continue; + } + + spin_lock_bh(&ar->htt.tx_lock); + artxq = (void *)txq->drv_priv; + artxq->num_push_allowed = le16_to_cpu(record->num_max_msdus); + spin_unlock_bh(&ar->htt.tx_lock); } - /* TODO: apply configuration */ + rcu_read_unlock(); + + ath10k_mac_tx_push_pending(ar); } void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) @@ -2313,8 +2398,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) case HTT_T2H_MSG_TYPE_AGGR_CONF: break; case HTT_T2H_MSG_TYPE_TX_FETCH_IND: - ath10k_htt_rx_tx_fetch_ind(ar, skb); - break; + skb_queue_tail(&htt->tx_fetch_ind_q, skb); + tasklet_schedule(&htt->txrx_compl_task); + return; case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: ath10k_htt_rx_tx_fetch_confirm(ar, skb); break; @@ -2350,6 +2436,7 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) struct sk_buff_head tx_q; struct sk_buff_head rx_q; struct sk_buff_head rx_ind_q; + struct sk_buff_head tx_ind_q; struct htt_resp *resp; struct sk_buff *skb; unsigned long flags; @@ -2357,6 +2444,7 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) __skb_queue_head_init(&tx_q); __skb_queue_head_init(&rx_q); __skb_queue_head_init(&rx_ind_q); + __skb_queue_head_init(&tx_ind_q); spin_lock_irqsave(&htt->tx_compl_q.lock, flags); skb_queue_splice_init(&htt->tx_compl_q, &tx_q); @@ -2370,11 +2458,20 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q); spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags); + spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags); + skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q); + spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags); + while ((skb = __skb_dequeue(&tx_q))) { ath10k_htt_rx_frm_tx_compl(htt->ar, skb); dev_kfree_skb_any(skb); } + while ((skb = __skb_dequeue(&tx_ind_q))) { + ath10k_htt_rx_tx_fetch_ind(ar, skb); + dev_kfree_skb_any(skb); + } + ath10k_mac_tx_push_pending(ar); while ((skb = __skb_dequeue(&rx_q))) { diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 6643be8692b5..a30c34eae0a7 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -64,6 +64,9 @@ static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw, if (!ar->htt.tx_q_state.enabled) return; + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL) + return; + if (txq->sta) peer_id = arsta->peer_id; else @@ -101,6 +104,9 @@ static void __ath10k_htt_tx_txq_sync(struct ath10k *ar) if (!ar->htt.tx_q_state.enabled) return; + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL) + return; + seq = le32_to_cpu(ar->htt.tx_q_state.vaddr->seq); seq++; ar->htt.tx_q_state.vaddr->seq = cpu_to_le32(seq); @@ -115,6 +121,23 @@ static void __ath10k_htt_tx_txq_sync(struct ath10k *ar) DMA_TO_DEVICE); } +void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + struct ath10k *ar = hw->priv; + + spin_lock_bh(&ar->htt.tx_lock); + __ath10k_htt_tx_txq_recalc(hw, txq); + spin_unlock_bh(&ar->htt.tx_lock); +} + +void ath10k_htt_tx_txq_sync(struct ath10k *ar) +{ + spin_lock_bh(&ar->htt.tx_lock); + __ath10k_htt_tx_txq_sync(ar); + spin_unlock_bh(&ar->htt.tx_lock); +} + void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { @@ -638,10 +661,14 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar, { struct sk_buff *skb; struct htt_cmd *cmd; - u16 resp_id; + const u16 resp_id = 0; int len = 0; int ret; + /* Response IDs are echo-ed back only for host driver convienence + * purposes. They aren't used for anything in the driver yet so use 0. + */ + len += sizeof(cmd->hdr); len += sizeof(cmd->tx_fetch_resp); len += sizeof(cmd->tx_fetch_resp.records[0]) * num_records; @@ -650,11 +677,6 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar, if (!skb) return -ENOMEM; - resp_id = 0; /* TODO: allocate resp_id */ - ret = 0; - if (ret) - goto err_free_skb; - skb_put(skb, len); cmd = (struct htt_cmd *)skb->data; cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FETCH_RESP; @@ -669,14 +691,11 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar, ret = ath10k_htc_send(&ar->htc, ar->htt.eid, skb); if (ret) { ath10k_warn(ar, "failed to submit htc command: %d\n", ret); - goto err_free_resp_id; + goto err_free_skb; } return 0; -err_free_resp_id: - (void)resp_id; /* TODO: free resp_id */ - err_free_skb: dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 5bf614f1f75a..4a27f27a8e8b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3656,14 +3656,48 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) spin_unlock_bh(&ar->htt.tx_lock); } +struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, + u16 peer_id, + u8 tid) +{ + struct ath10k_peer *peer; + + lockdep_assert_held(&ar->data_lock); + + peer = ar->peer_map[peer_id]; + if (!peer) + return NULL; + + if (peer->sta) + return peer->sta->txq[tid]; + else if (peer->vif) + return peer->vif->txq; + else + return NULL; +} + static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { - return 1; /* TBD */ + struct ath10k *ar = hw->priv; + struct ath10k_txq *artxq = (void *)txq->drv_priv; + + /* No need to get locks */ + + if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH) + return true; + + if (ar->htt.num_pending_tx < ar->htt.tx_q_state.num_push_allowed) + return true; + + if (artxq->num_fw_queued < artxq->num_push_allowed) + return true; + + return false; } -static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, - struct ieee80211_txq *txq) +int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) { const bool is_mgmt = false; const bool is_presp = false; @@ -3675,6 +3709,7 @@ static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, enum ath10k_hw_txrx_mode txmode; enum ath10k_mac_tx_path txpath; struct sk_buff *skb; + size_t skb_len; int ret; spin_lock_bh(&ar->htt.tx_lock); @@ -3695,6 +3730,7 @@ static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); + skb_len = skb->len; txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); @@ -3713,7 +3749,7 @@ static int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, artxq->num_fw_queued++; spin_unlock_bh(&ar->htt.tx_lock); - return 0; + return skb_len; } void ath10k_mac_tx_push_pending(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 453f606a250e..2c3327beb445 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -76,6 +76,11 @@ void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason); void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason); bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar); void ath10k_mac_tx_push_pending(struct ath10k *ar); +int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, + struct ieee80211_txq *txq); +struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, + u16 peer_id, + u8 tid); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { -- GitLab From 43c9e3846ba30ca3d657bd82f1005d1573bb3a6d Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 1 Mar 2016 13:16:10 +0100 Subject: [PATCH 0025/9938] ath10k: fix HTT Tx CE ring size QCA4019 can queue up to 2500 frames at a time. This means it requires roughly 5000 entires on the ring to work properly. Otherwise random tx failure may occur. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 47b734ce7ecf..dac676817532 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -22,7 +22,7 @@ /* Maximum number of Copy Engine's supported */ #define CE_COUNT_MAX 12 -#define CE_HTT_H2T_MSG_SRC_NENTRIES 4096 +#define CE_HTT_H2T_MSG_SRC_NENTRIES 8192 /* Descriptor rings must be aligned to this boundary */ #define CE_DESC_RING_ALIGN 8 -- GitLab From 99ad1cba313fc86797bca55d64e7c6c809098511 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 1 Mar 2016 13:16:11 +0100 Subject: [PATCH 0026/9938] ath10k: change htt tx desc/qcache peer limit config The number of HTT Tx descriptors and qcache peer limit aren't hw-specific. In fact they are firmware specific and should not be placed in hw_params. The QCA4019 limits were submitted with the peer flow control firmware only and to my understanding there's no non-peer-flow-ctrl QCA4019 firmware. However QCA99X0 is planned to run firmware supporting the feature as well. Therefore this patch enables QCA99X0 to use 2500 tx descriptors whenever possible instead of just 1424. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 11 ++++++----- drivers/net/wireless/ath/ath10k/core.h | 2 -- drivers/net/wireless/ath/ath10k/hw.h | 4 ++++ drivers/net/wireless/ath/ath10k/wmi.c | 10 ++++++++-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 6f606f8fce25..2389c0713c13 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -156,8 +156,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 150000, .max_probe_resp_desc_thres = 24, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, - .num_msdu_desc = 1424, - .qcache_active_peers = 50, .tx_chain_mask = 0xf, .rx_chain_mask = 0xf, .max_spatial_stream = 4, @@ -217,8 +215,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 125000, .max_probe_resp_desc_thres = 24, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, - .num_msdu_desc = 2500, - .qcache_active_peers = 35, .tx_chain_mask = 0x3, .rx_chain_mask = 0x3, .max_spatial_stream = 2, @@ -1538,9 +1534,14 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS; ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; ar->num_tids = TARGET_10_4_TGT_NUM_TIDS; - ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc; ar->fw_stats_req_mask = WMI_STAT_PEER; ar->max_spatial_stream = ar->hw_params.max_spatial_stream; + + if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->fw_features)) + ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC; + else + ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC; break; case ATH10K_FW_WMI_OP_VERSION_UNSET: case ATH10K_FW_WMI_OP_VERSION_MAX: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 3050e497fd22..23ba03fb7a5f 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -692,8 +692,6 @@ struct ath10k { /* The padding bytes's location is different on various chips */ enum ath10k_hw_4addr_pad hw_4addr_pad; - u32 num_msdu_desc; - u32 qcache_active_peers; u32 tx_chain_mask; u32 rx_chain_mask; u32 max_spatial_stream; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f0cfbc745c97..1ff617b05010 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -431,10 +431,14 @@ enum ath10k_hw_4addr_pad { #define TARGET_10_4_ACTIVE_PEERS 0 #define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512 +#define TARGET_10_4_QCACHE_ACTIVE_PEERS 50 +#define TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC 35 #define TARGET_10_4_NUM_OFFLOAD_PEERS 0 #define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0 #define TARGET_10_4_NUM_PEER_KEYS 2 #define TARGET_10_4_TGT_NUM_TIDS ((TARGET_10_4_NUM_PEERS) * 2) +#define TARGET_10_4_NUM_MSDU_DESC (1024 + 400) +#define TARGET_10_4_NUM_MSDU_DESC_PFC 2500 #define TARGET_10_4_AST_SKID_LIMIT 32 /* 100 ms for video, best-effort, and background */ diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 70261387d1a5..c31b4878cdc6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4617,10 +4617,16 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) } if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { + if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->fw_features)) + ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC + + ar->max_num_vdevs; + else + ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS + + ar->max_num_vdevs; + ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX + ar->max_num_vdevs; - ar->num_active_peers = ar->hw_params.qcache_active_peers + - ar->max_num_vdevs; ar->num_tids = ar->num_active_peers * 2; ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX; } -- GitLab From 8a75fc54745fd3ce9062ab1cc6429a9da9ac2a68 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 2 Mar 2016 20:13:52 +0530 Subject: [PATCH 0027/9938] ath10k: fix firmware assert in monitor mode commit 166de3f1895d ("ath10k: remove supported chain mask") had revealed an issue on monitor mode. Configuring NSS upon monitor interface creation is causing target assert in all qca9888x and qca6174 firmware. Firmware assert issue can be reproduced by below sequence even after reverting commit 166de3f1895d ("ath10k: remove supported chain mask"). ip link set wlan0 down iw wlan0 set type monitor iw phy0 set antenna 7 ip link set wlan0 up This issue is originally reported on qca9888 with 10.1 firmware. Fixes: 5572a95b4b ("ath10k: apply chainmask settings to vdev on creation") Cc: stable@vger.kernel.org Reported-by: Janusz Dziedzic Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4a27f27a8e8b..ebff9c0a0784 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4818,7 +4818,10 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, goto err_vdev_delete; } - if (ar->cfg_tx_chainmask) { + /* Configuring number of spatial stream for monitor interface is causing + * target assert in qca9888 and qca6174. + */ + if (ar->cfg_tx_chainmask && (vif->type != NL80211_IFTYPE_MONITOR)) { u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask); vdev_param = ar->wmi.vdev_param->nss; -- GitLab From 361486b27c7e57dab657dbffd1e17818c7911c72 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 1 Mar 2016 19:18:04 +0200 Subject: [PATCH 0028/9938] wil6210: remove BACK RX and TX workers WMI synchronous handling has changed and WMI calls that provide a buffer for the reply are completed in the WMI interrupt context. This allows sending the RX and TX BACK commands from the WMI event handler without the need for the worker thread. This is a better approach as it can decrease the handshake time in the connect flow and prevent race conditions in case of fast disconnects. An example for such a race is handling of wil_back_rx_handle during a disconnect event, as wil_back_rx_handle is not protected by the wil mutex and a disconnect can be handled after sta->status is verified as connected. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 10 - drivers/net/wireless/ath/wil6210/rx_reorder.c | 204 ++++-------------- drivers/net/wireless/ath/wil6210/wil6210.h | 29 --- 3 files changed, 41 insertions(+), 202 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 78ba6e04c944..35db9940c519 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -440,8 +440,6 @@ int wil_priv_init(struct wil6210_priv *wil) mutex_init(&wil->mutex); mutex_init(&wil->wmi_mutex); - mutex_init(&wil->back_rx_mutex); - mutex_init(&wil->back_tx_mutex); mutex_init(&wil->probe_client_mutex); init_completion(&wil->wmi_ready); @@ -454,13 +452,9 @@ int wil_priv_init(struct wil6210_priv *wil) INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); - INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker); - INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker); INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); INIT_LIST_HEAD(&wil->pending_wmi_ev); - INIT_LIST_HEAD(&wil->back_rx_pending); - INIT_LIST_HEAD(&wil->back_tx_pending); INIT_LIST_HEAD(&wil->probe_client_pending); spin_lock_init(&wil->wmi_ev_lock); init_waitqueue_head(&wil->wq); @@ -520,10 +514,6 @@ void wil_priv_deinit(struct wil6210_priv *wil) wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); mutex_unlock(&wil->mutex); wmi_event_flush(wil); - wil_back_rx_flush(wil); - cancel_work_sync(&wil->back_rx_worker); - wil_back_tx_flush(wil); - cancel_work_sync(&wil->back_tx_worker); wil_probe_client_flush(wil); cancel_work_sync(&wil->probe_client_worker); destroy_workqueue(wil->wq_service); diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 32031e7a11d5..19ed127d4d05 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -291,35 +291,15 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize) return min(max_agg_size, req_agg_wsize); } -/* Block Ack - Rx side (recipient */ +/* Block Ack - Rx side (recipient) */ int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl) -{ - struct wil_back_rx *req = kzalloc(sizeof(*req), GFP_KERNEL); - - if (!req) - return -ENOMEM; - - req->cidxtid = cidxtid; - req->dialog_token = dialog_token; - req->ba_param_set = le16_to_cpu(ba_param_set); - req->ba_timeout = le16_to_cpu(ba_timeout); - req->ba_seq_ctrl = le16_to_cpu(ba_seq_ctrl); - - mutex_lock(&wil->back_rx_mutex); - list_add_tail(&req->list, &wil->back_rx_pending); - mutex_unlock(&wil->back_rx_mutex); - - queue_work(wil->wq_service, &wil->back_rx_worker); - - return 0; -} - -static void wil_back_rx_handle(struct wil6210_priv *wil, - struct wil_back_rx *req) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { + u16 param_set = le16_to_cpu(ba_param_set); + u16 agg_timeout = le16_to_cpu(ba_timeout); + u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl); struct wil_sta_info *sta; u8 cid, tid; u16 agg_wsize = 0; @@ -328,34 +308,35 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) * bits 2..5: TID * bits 6..15: buffer size */ - u16 req_agg_wsize = WIL_GET_BITS(req->ba_param_set, 6, 15); - bool agg_amsdu = !!(req->ba_param_set & BIT(0)); - int ba_policy = req->ba_param_set & BIT(1); - u16 agg_timeout = req->ba_timeout; + u16 req_agg_wsize = WIL_GET_BITS(param_set, 6, 15); + bool agg_amsdu = !!(param_set & BIT(0)); + int ba_policy = param_set & BIT(1); u16 status = WLAN_STATUS_SUCCESS; - u16 ssn = req->ba_seq_ctrl >> 4; + u16 ssn = seq_ctrl >> 4; struct wil_tid_ampdu_rx *r; - int rc; + int rc = 0; might_sleep(); - parse_cidxtid(req->cidxtid, &cid, &tid); + parse_cidxtid(cidxtid, &cid, &tid); /* sanity checks */ if (cid >= WIL6210_MAX_CID) { wil_err(wil, "BACK: invalid CID %d\n", cid); - return; + rc = -EINVAL; + goto out; } sta = &wil->sta[cid]; if (sta->status != wil_sta_connected) { wil_err(wil, "BACK: CID %d not connected\n", cid); - return; + rc = -EINVAL; + goto out; } wil_dbg_wmi(wil, "ADDBA request for CID %d %pM TID %d size %d timeout %d AMSDU%s policy %d token %d SSN 0x%03x\n", - cid, sta->addr, tid, req_agg_wsize, req->ba_timeout, - agg_amsdu ? "+" : "-", !!ba_policy, req->dialog_token, ssn); + cid, sta->addr, tid, req_agg_wsize, agg_timeout, + agg_amsdu ? "+" : "-", !!ba_policy, dialog_token, ssn); /* apply policies */ if (ba_policy) { @@ -365,10 +346,13 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) if (status == WLAN_STATUS_SUCCESS) agg_wsize = wil_agg_size(wil, req_agg_wsize); - rc = wmi_addba_rx_resp(wil, cid, tid, req->dialog_token, status, + rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status, agg_amsdu, agg_wsize, agg_timeout); - if (rc || (status != WLAN_STATUS_SUCCESS)) - return; + if (rc || (status != WLAN_STATUS_SUCCESS)) { + wil_err(wil, "%s: do not apply ba, rc(%d), status(%d)\n", + __func__, rc, status); + goto out; + } /* apply */ r = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn); @@ -376,143 +360,37 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]); sta->tid_rx[tid] = r; spin_unlock_bh(&sta->tid_rx_lock); -} - -void wil_back_rx_flush(struct wil6210_priv *wil) -{ - struct wil_back_rx *evt, *t; - wil_dbg_misc(wil, "%s()\n", __func__); - - mutex_lock(&wil->back_rx_mutex); - - list_for_each_entry_safe(evt, t, &wil->back_rx_pending, list) { - list_del(&evt->list); - kfree(evt); - } - - mutex_unlock(&wil->back_rx_mutex); -} - -/* Retrieve next ADDBA request from the pending list */ -static struct list_head *next_back_rx(struct wil6210_priv *wil) -{ - struct list_head *ret = NULL; - - mutex_lock(&wil->back_rx_mutex); - - if (!list_empty(&wil->back_rx_pending)) { - ret = wil->back_rx_pending.next; - list_del(ret); - } - - mutex_unlock(&wil->back_rx_mutex); - - return ret; -} - -void wil_back_rx_worker(struct work_struct *work) -{ - struct wil6210_priv *wil = container_of(work, struct wil6210_priv, - back_rx_worker); - struct wil_back_rx *evt; - struct list_head *lh; - - while ((lh = next_back_rx(wil)) != NULL) { - evt = list_entry(lh, struct wil_back_rx, list); - - wil_back_rx_handle(wil, evt); - kfree(evt); - } +out: + return rc; } -/* BACK - Tx (originator) side */ -static void wil_back_tx_handle(struct wil6210_priv *wil, - struct wil_back_tx *req) +/* BACK - Tx side (originator) */ +int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) { - struct vring_tx_data *txdata = &wil->vring_tx_data[req->ringid]; - int rc; + u8 agg_wsize = wil_agg_size(wil, wsize); + u16 agg_timeout = 0; + struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; + int rc = 0; if (txdata->addba_in_progress) { wil_dbg_misc(wil, "ADDBA for vring[%d] already in progress\n", - req->ringid); - return; + ringid); + goto out; } if (txdata->agg_wsize) { wil_dbg_misc(wil, - "ADDBA for vring[%d] already established wsize %d\n", - req->ringid, txdata->agg_wsize); - return; + "ADDBA for vring[%d] already done for wsize %d\n", + ringid, txdata->agg_wsize); + goto out; } txdata->addba_in_progress = true; - rc = wmi_addba(wil, req->ringid, req->agg_wsize, req->agg_timeout); - if (rc) + rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout); + if (rc) { + wil_err(wil, "%s: wmi_addba failed, rc (%d)", __func__, rc); txdata->addba_in_progress = false; -} - -static struct list_head *next_back_tx(struct wil6210_priv *wil) -{ - struct list_head *ret = NULL; - - mutex_lock(&wil->back_tx_mutex); - - if (!list_empty(&wil->back_tx_pending)) { - ret = wil->back_tx_pending.next; - list_del(ret); - } - - mutex_unlock(&wil->back_tx_mutex); - - return ret; -} - -void wil_back_tx_worker(struct work_struct *work) -{ - struct wil6210_priv *wil = container_of(work, struct wil6210_priv, - back_tx_worker); - struct wil_back_tx *evt; - struct list_head *lh; - - while ((lh = next_back_tx(wil)) != NULL) { - evt = list_entry(lh, struct wil_back_tx, list); - - wil_back_tx_handle(wil, evt); - kfree(evt); } -} - -void wil_back_tx_flush(struct wil6210_priv *wil) -{ - struct wil_back_tx *evt, *t; - - wil_dbg_misc(wil, "%s()\n", __func__); - - mutex_lock(&wil->back_tx_mutex); - - list_for_each_entry_safe(evt, t, &wil->back_tx_pending, list) { - list_del(&evt->list); - kfree(evt); - } - - mutex_unlock(&wil->back_tx_mutex); -} - -int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) -{ - struct wil_back_tx *req = kzalloc(sizeof(*req), GFP_KERNEL); - - if (!req) - return -ENOMEM; - req->ringid = ringid; - req->agg_wsize = wil_agg_size(wil, wsize); - req->agg_timeout = 0; - - mutex_lock(&wil->back_tx_mutex); - list_add_tail(&req->list, &wil->back_tx_pending); - mutex_unlock(&wil->back_tx_mutex); - - queue_work(wil->wq_service, &wil->back_tx_worker); - - return 0; +out: + return rc; } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 8427d68b6fa8..d59c3f29941e 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -507,24 +507,6 @@ enum { hw_capability_last }; -struct wil_back_rx { - struct list_head list; - /* request params, converted to CPU byte order - what we asked for */ - u8 cidxtid; - u8 dialog_token; - u16 ba_param_set; - u16 ba_timeout; - u16 ba_seq_ctrl; -}; - -struct wil_back_tx { - struct list_head list; - /* request params, converted to CPU byte order - what we asked for */ - u8 ringid; - u8 agg_wsize; - u16 agg_timeout; -}; - struct wil_probe_client_req { struct list_head list; u64 cookie; @@ -595,13 +577,6 @@ struct wil6210_priv { spinlock_t wmi_ev_lock; struct napi_struct napi_rx; struct napi_struct napi_tx; - /* BACK */ - struct list_head back_rx_pending; - struct mutex back_rx_mutex; /* protect @back_rx_pending */ - struct work_struct back_rx_worker; - struct list_head back_tx_pending; - struct mutex back_tx_mutex; /* protect @back_tx_pending */ - struct work_struct back_tx_worker; /* keep alive */ struct list_head probe_client_pending; struct mutex probe_client_mutex; /* protect @probe_client_pending */ @@ -765,11 +740,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl); -void wil_back_rx_worker(struct work_struct *work); -void wil_back_rx_flush(struct wil6210_priv *wil); int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); -void wil_back_tx_worker(struct work_struct *work); -void wil_back_tx_flush(struct wil6210_priv *wil); void wil6210_clear_irq(struct wil6210_priv *wil); int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi); -- GitLab From 3d287fb398c03189a1394778162f6404e4d44ad2 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 1 Mar 2016 19:18:05 +0200 Subject: [PATCH 0029/9938] wil6210: AP: prevent connecting to already connected station wmi_evt_connect doesn't check if the connect event is received for an already connected station. This can lead to memory leak as a new vring is allocated without freeing the previously allocated vring and to unexpected behavior of nl80211 layer due to unexpected notification of a new station. Add a check in wmi_evt_connect in AP mode to verify that the requested CID is not associated to an already connected station. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/wmi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 493e721c4fa7..fb090350df6d 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -487,6 +487,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) return; } del_timer_sync(&wil->connect_timer); + } else if ((wdev->iftype == NL80211_IFTYPE_AP) || + (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { + if (wil->sta[evt->cid].status != wil_sta_unused) { + wil_err(wil, "%s: AP: Invalid status %d for CID %d\n", + __func__, wil->sta[evt->cid].status, evt->cid); + mutex_unlock(&wil->mutex); + return; + } } /* FIXME FW can transmit only ucast frames to peer */ -- GitLab From b42f11963f7bd8c54d0a28d679c13d9e83b85357 Mon Sep 17 00:00:00 2001 From: Hamad Kadmany Date: Tue, 1 Mar 2016 19:18:06 +0200 Subject: [PATCH 0030/9938] wil6210: Set permanent MAC address to wiphy MAC address of wil6210 was not set in wiphy Signed-off-by: Hamad Kadmany Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 35db9940c519..997a740e0a4b 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -627,6 +627,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) static int wil_get_bl_info(struct wil6210_priv *wil) { struct net_device *ndev = wil_to_ndev(wil); + struct wiphy *wiphy = wil_to_wiphy(wil); union { struct bl_dedicated_registers_v0 bl0; struct bl_dedicated_registers_v1 bl1; @@ -671,6 +672,7 @@ static int wil_get_bl_info(struct wil6210_priv *wil) } ether_addr_copy(ndev->perm_addr, mac); + ether_addr_copy(wiphy->perm_addr, mac); if (!is_valid_ether_addr(ndev->dev_addr)) ether_addr_copy(ndev->dev_addr, mac); -- GitLab From 58527421489dcc1110f6bcfd3b50d479199af4e0 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Tue, 1 Mar 2016 19:18:07 +0200 Subject: [PATCH 0031/9938] wil6210: replay attack detection Check PN for encrypted frames. Maintain PN data for Rx keys, pairwise per TID and group. Print PN's in the debugfs "stations" entry, like: [0] 04:ce:14:0a:3c:3d connected [ 0] ([32] 0 TU) 0x0fe [____________________________|___] total 252 drop 0 (dup 0 + old 0) last 0x000 [ 0] PN [0+]000000000000 [1-]000000000000 [2-]000000000000 [3-]000000000000 [GR] PN [0-]000000000000 [1+]000000000000 [2+]000000000000 [3-]000000000000 Rx invalid frame: non-data 0, short 0, large 0, replay 0 Rx/MCS: 0 110 65 65 65 0 12 0 0 0 0 0 0 [1] 00:00:00:00:00:00 unused [2] 00:00:00:00:00:00 unused [3] 00:00:00:00:00:00 unused [4] 00:00:00:00:00:00 unused [5] 00:00:00:00:00:00 unused [6] 00:00:00:00:00:00 unused [7] 00:00:00:00:00:00 unused Signed-off-by: Vladimir Kondratiev Signed-off-by: Hamad Kadmany Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 100 +++++++++++++++++--- drivers/net/wireless/ath/wil6210/debugfs.c | 41 +++++++- drivers/net/wireless/ath/wil6210/main.c | 9 +- drivers/net/wireless/ath/wil6210/txrx.c | 63 ++++++++++++ drivers/net/wireless/ath/wil6210/txrx.h | 12 ++- drivers/net/wireless/ath/wil6210/wil6210.h | 18 ++++ 6 files changed, 226 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 11f1bb8dfebe..ddadda90cfa0 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -82,6 +82,12 @@ static const u32 wil_cipher_suites[] = { WLAN_CIPHER_SUITE_GCMP, }; +static const char * const key_usage_str[] = { + [WMI_KEY_USE_PAIRWISE] = "PTK", + [WMI_KEY_USE_RX_GROUP] = "RX_GTK", + [WMI_KEY_USE_TX_GROUP] = "TX_GTK", +}; + int wil_iftype_nl2wmi(enum nl80211_iftype type) { static const struct { @@ -610,11 +616,6 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, { struct wireless_dev *wdev = wil->wdev; enum wmi_key_usage rc; - static const char * const key_usage_str[] = { - [WMI_KEY_USE_PAIRWISE] = "WMI_KEY_USE_PAIRWISE", - [WMI_KEY_USE_RX_GROUP] = "WMI_KEY_USE_RX_GROUP", - [WMI_KEY_USE_TX_GROUP] = "WMI_KEY_USE_TX_GROUP", - }; if (pairwise) { rc = WMI_KEY_USE_PAIRWISE; @@ -638,20 +639,86 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, return rc; } +static struct wil_tid_crypto_rx_single * +wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index, + enum wmi_key_usage key_usage, const u8 *mac_addr) +{ + int cid = -EINVAL; + int tid = 0; + struct wil_sta_info *s; + struct wil_tid_crypto_rx *c; + + if (key_usage == WMI_KEY_USE_TX_GROUP) + return NULL; /* not needed */ + + /* supplicant provides Rx group key in STA mode with NULL MAC address */ + if (mac_addr) + cid = wil_find_cid(wil, mac_addr); + else if (key_usage == WMI_KEY_USE_RX_GROUP) + cid = wil_find_cid_by_idx(wil, 0); + if (cid < 0) { + wil_err(wil, "No CID for %pM %s[%d]\n", mac_addr, + key_usage_str[key_usage], key_index); + return ERR_PTR(cid); + } + + s = &wil->sta[cid]; + if (key_usage == WMI_KEY_USE_PAIRWISE) + c = &s->tid_crypto_rx[tid]; + else + c = &s->group_crypto_rx; + + return &c->key_id[key_index]; +} + static int wil_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { + int rc; struct wil6210_priv *wil = wiphy_to_wil(wiphy); enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); + struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil, + key_index, + key_usage, + mac_addr); + + wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__, + mac_addr, key_usage_str[key_usage], key_index, + params->seq_len, params->seq); + + if (IS_ERR(cc)) { + wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n", + __func__, mac_addr, key_usage_str[key_usage], key_index, + params->seq_len, params->seq); + return -EINVAL; + } + + if (cc) + cc->key_set = false; - wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index, - pairwise ? "PTK" : "GTK"); + if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) { + wil_err(wil, + "Wrong PN len %d, %s(%pM %s[%d] PN %*phN)\n", + params->seq_len, __func__, mac_addr, + key_usage_str[key_usage], key_index, + params->seq_len, params->seq); + return -EINVAL; + } - return wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len, - params->key, key_usage); + rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len, + params->key, key_usage); + if ((rc == 0) && cc) { + if (params->seq) + memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN); + else + memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN); + cc->key_set = true; + } + + return rc; } static int wil_cfg80211_del_key(struct wiphy *wiphy, @@ -661,9 +728,20 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); + struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil, + key_index, + key_usage, + mac_addr); + + wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr, + key_usage_str[key_usage], key_index); + + if (IS_ERR(cc)) + wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__, + mac_addr, key_usage_str[key_usage], key_index); - wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index, - pairwise ? "PTK" : "GTK"); + if (!IS_ERR_OR_NULL(cc)) + cc->key_set = false; return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage); } diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 3bbe73b6d05a..d80bb75c6576 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1333,6 +1333,34 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) r->ssn_last_drop); } +static void wil_print_rxtid_crypto(struct seq_file *s, int tid, + struct wil_tid_crypto_rx *c) +{ + int i; + + for (i = 0; i < 4; i++) { + struct wil_tid_crypto_rx_single *cc = &c->key_id[i]; + + if (cc->key_set) + goto has_keys; + } + return; + +has_keys: + if (tid < WIL_STA_TID_NUM) + seq_printf(s, " [%2d] PN", tid); + else + seq_puts(s, " [GR] PN"); + + for (i = 0; i < 4; i++) { + struct wil_tid_crypto_rx_single *cc = &c->key_id[i]; + + seq_printf(s, " [%i%s]%6phN", i, cc->key_set ? "+" : "-", + cc->pn); + } + seq_puts(s, "\n"); +} + static int wil_sta_debugfs_show(struct seq_file *s, void *data) __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) { @@ -1360,18 +1388,25 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) spin_lock_bh(&p->tid_rx_lock); for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { struct wil_tid_ampdu_rx *r = p->tid_rx[tid]; + struct wil_tid_crypto_rx *c = + &p->tid_crypto_rx[tid]; if (r) { - seq_printf(s, "[%2d] ", tid); + seq_printf(s, " [%2d] ", tid); wil_print_rxtid(s, r); } + + wil_print_rxtid_crypto(s, tid, c); } + wil_print_rxtid_crypto(s, WIL_STA_TID_NUM, + &p->group_crypto_rx); spin_unlock_bh(&p->tid_rx_lock); seq_printf(s, - "Rx invalid frame: non-data %lu, short %lu, large %lu\n", + "Rx invalid frame: non-data %lu, short %lu, large %lu, replay %lu\n", p->stats.rx_non_data_frame, p->stats.rx_short_frame, - p->stats.rx_large_frame); + p->stats.rx_large_frame, + p->stats.rx_replay); seq_puts(s, "Rx/MCS:"); for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 997a740e0a4b..1fa215d0eeed 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -149,7 +149,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) might_sleep(); wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid, sta->status); - + /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { if (!from_event) wmi_disconnect_sta(wil, sta->addr, reason_code, true); @@ -165,7 +165,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) } sta->status = wil_sta_unused; } - + /* reorder buffers */ for (i = 0; i < WIL_STA_TID_NUM; i++) { struct wil_tid_ampdu_rx *r; @@ -177,10 +177,15 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) spin_unlock_bh(&sta->tid_rx_lock); } + /* crypto context */ + memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx)); + memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx)); + /* release vrings */ for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { if (wil->vring2cid_tid[i][0] == cid) wil_vring_fini_tx(wil, i); } + /* statistics */ memset(&sta->stats, 0, sizeof(sta->stats)); } diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 6af20903cf89..f383001b86aa 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -549,6 +549,60 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) return rc; } +/** + * reverse_memcmp - Compare two areas of memory, in reverse order + * @cs: One area of memory + * @ct: Another area of memory + * @count: The size of the area. + * + * Cut'n'paste from original memcmp (see lib/string.c) + * with minimal modifications + */ +static int reverse_memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1, *su2; + int res = 0; + + for (su1 = cs + count - 1, su2 = ct + count - 1; count > 0; + --su1, --su2, count--) { + res = *su1 - *su2; + if (res) + break; + } + return res; +} + +static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) +{ + struct vring_rx_desc *d = wil_skb_rxdesc(skb); + int cid = wil_rxdesc_cid(d); + int tid = wil_rxdesc_tid(d); + int key_id = wil_rxdesc_key_id(d); + int mc = wil_rxdesc_mcast(d); + struct wil_sta_info *s = &wil->sta[cid]; + struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx : + &s->tid_crypto_rx[tid]; + struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id]; + const u8 *pn = (u8 *)&d->mac.pn_15_0; + + if (!cc->key_set) { + wil_err_ratelimited(wil, + "Key missing. CID %d TID %d MCast %d KEY_ID %d\n", + cid, tid, mc, key_id); + return -EINVAL; + } + + if (reverse_memcmp(pn, cc->pn, IEEE80211_GCMP_PN_LEN) <= 0) { + wil_err_ratelimited(wil, + "Replay attack. CID %d TID %d MCast %d KEY_ID %d PN %6phN last %6phN\n", + cid, tid, mc, key_id, pn, cc->pn); + return -EINVAL; + } + memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN); + + return 0; +} + /* * Pass Rx packet to the netif. Update statistics. * Called in softirq context (NAPI poll). @@ -561,6 +615,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) unsigned int len = skb->len; struct vring_rx_desc *d = wil_skb_rxdesc(skb); int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ + int security = wil_rxdesc_security(d); struct ethhdr *eth = (void *)skb->data; /* here looking for DA, not A1, thus Rxdesc's 'mcast' indication * is not suitable, need to look at data @@ -586,6 +641,13 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) skb_orphan(skb); + if (security && (wil_rx_crypto_check(wil, skb) != 0)) { + rc = GRO_DROP; + dev_kfree_skb(skb); + stats->rx_replay++; + goto stats; + } + if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) { if (mcast) { /* send multicast frames both to higher layers in @@ -627,6 +689,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n", len, gro_res_str[rc]); } +stats: /* statistics. rc set to GRO_NORMAL for AP bridging */ if (unlikely(rc == GRO_DROP)) { ndev->stats.rx_dropped++; diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index ee7c7b4b9a17..fcdffaa8251b 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -480,6 +480,16 @@ static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d) return WIL_GET_BITS(d->mac.d0, 28, 31); } +static inline int wil_rxdesc_key_id(struct vring_rx_desc *d) +{ + return WIL_GET_BITS(d->mac.d1, 4, 5); +} + +static inline int wil_rxdesc_security(struct vring_rx_desc *d) +{ + return WIL_GET_BITS(d->mac.d1, 7, 7); +} + static inline int wil_rxdesc_ds_bits(struct vring_rx_desc *d) { return WIL_GET_BITS(d->mac.d1, 8, 9); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index d59c3f29941e..44ff040e2fea 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -455,6 +455,21 @@ struct wil_tid_ampdu_rx { bool first_time; /* is it 1-st time this buffer used? */ }; +/** + * struct wil_tid_crypto_rx_single - TID crypto information (Rx). + * + * @pn: GCMP PN for the session + * @key_set: valid key present + */ +struct wil_tid_crypto_rx_single { + u8 pn[IEEE80211_GCMP_PN_LEN]; + bool key_set; +}; + +struct wil_tid_crypto_rx { + struct wil_tid_crypto_rx_single key_id[4]; +}; + enum wil_sta_status { wil_sta_unused = 0, wil_sta_conn_pending = 1, @@ -474,6 +489,7 @@ struct wil_net_stats { unsigned long rx_non_data_frame; unsigned long rx_short_frame; unsigned long rx_large_frame; + unsigned long rx_replay; u16 last_mcs_rx; u64 rx_per_mcs[WIL_MCS_MAX + 1]; }; @@ -495,6 +511,8 @@ struct wil_sta_info { spinlock_t tid_rx_lock; /* guarding tid_rx array */ unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)]; unsigned long tid_rx_stop_requested[BITS_TO_LONGS(WIL_STA_TID_NUM)]; + struct wil_tid_crypto_rx tid_crypto_rx[WIL_STA_TID_NUM]; + struct wil_tid_crypto_rx group_crypto_rx; }; enum { -- GitLab From 74997a53d257e327699e359b78b3ecfd33f80cab Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:08 +0200 Subject: [PATCH 0032/9938] wil6210: add support for discovery mode during scan Add support for discovery mode during scan. When discovery mode is active, station transmits special beacons while scanning. This can optimize the scan mainly when there is only one AP/PCP around. Discovery mode is implicitly used by firmware during P2P search. Since there is currently no use case where user space has a reason to directly control discovery mode, we expose it only through a debugfs flag. Also fix name confusion in the wmi_scan_type enumeration. The type previously called WMI_LONG_SCAN is actually WMI_ACTIVE_SCAN. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 6 ++++++ drivers/net/wireless/ath/wil6210/debugfs.c | 6 ++++++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + drivers/net/wireless/ath/wil6210/wmi.h | 7 ++++--- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index ddadda90cfa0..1ccf136b34e7 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -319,6 +319,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO); memset(&cmd, 0, sizeof(cmd)); + cmd.cmd.scan_type = WMI_ACTIVE_SCAN; cmd.cmd.num_channels = 0; n = min(request->n_channels, 4U); for (i = 0; i < n; i++) { @@ -346,6 +347,11 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, if (rc) goto out; + if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) { + cmd.cmd.discovery_mode = 1; + wil_dbg_misc(wil, "active scan with discovery_mode=1\n"); + } + rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index d80bb75c6576..8b7e1fddb5bd 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -37,6 +37,7 @@ enum dbg_off_type { doff_x32 = 1, doff_ulong = 2, doff_io32 = 3, + doff_u8 = 4 }; /* offset to "wil" */ @@ -346,6 +347,10 @@ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil, tbl[i].mode, dbg, base + tbl[i].off); break; + case doff_u8: + f = debugfs_create_u8(tbl[i].name, tbl[i].mode, dbg, + base + tbl[i].off); + break; default: f = ERR_PTR(-EINVAL); } @@ -1522,6 +1527,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(hw_version, S_IRUGO, doff_x32), WIL_FIELD(recovery_count, S_IRUGO, doff_u32), WIL_FIELD(ap_isolate, S_IRUGO, doff_u32), + WIL_FIELD(discovery_mode, S_IRUGO | S_IWUSR, doff_u8), {}, }; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 44ff040e2fea..f662f7676a31 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -615,6 +615,7 @@ struct wil6210_priv { /* debugfs */ struct dentry *debug; struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)]; + u8 discovery_mode; void *platform_handle; struct wil_platform_ops platform_ops; diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 6e90e78f1554..430a4c09db59 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -286,16 +286,17 @@ struct wmi_delete_cipher_key_cmd { * - WMI_SCAN_COMPLETE_EVENTID */ enum wmi_scan_type { - WMI_LONG_SCAN = 0, + WMI_ACTIVE_SCAN = 0, WMI_SHORT_SCAN = 1, WMI_PBC_SCAN = 2, WMI_DIRECT_SCAN = 3, - WMI_ACTIVE_SCAN = 4, + WMI_LONG_SCAN = 4, }; struct wmi_start_scan_cmd { u8 direct_scan_mac_addr[6]; - u8 reserved[2]; + u8 discovery_mode; + u8 reserved; __le32 home_dwell_time; /* Max duration in the home channel(ms) */ __le32 force_scan_interval; /* Time interval between scans (ms)*/ u8 scan_type; /* wmi_scan_type */ -- GitLab From b874ddecae0a087aee024ef808c63060434a2d50 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:09 +0200 Subject: [PATCH 0033/9938] wil6210: switch to generated wmi.h Switch to auto-generated version of wmi.h which is maintained by FW team. This will allow better sync between teams in the future and avoid bugs because of unexpected API changes. The wmi.h will have many differences but most are cosmetic. It also includes these real differences: 1. is_go parameter added to BCON_CTRL and START_PCP commands. 2. max_rx_pl_per_desc added to CFG_RX_CHAIN command. 3. various small API updates that are not currently used by driver. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 4 +- drivers/net/wireless/ath/wil6210/debugfs.c | 8 +- drivers/net/wireless/ath/wil6210/trace.h | 19 +- drivers/net/wireless/ath/wil6210/txrx.c | 4 +- drivers/net/wireless/ath/wil6210/wil6210.h | 21 +- drivers/net/wireless/ath/wil6210/wmi.c | 36 +- drivers/net/wireless/ath/wil6210/wmi.h | 1261 +++++++++---------- 7 files changed, 652 insertions(+), 701 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 1ccf136b34e7..0c25e8beec3c 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -119,7 +119,7 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, .interval_usec = 0, }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_notify_req_done_event evt; } __packed reply; struct wil_net_stats *stats = &wil->sta[cid].stats; @@ -580,7 +580,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_mgmt *mgmt_frame = (void *)buf; struct wmi_sw_tx_req_cmd *cmd; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_sw_tx_complete_event evt; } __packed evt; diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 8b7e1fddb5bd..a4d3f70c3d29 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -826,9 +826,9 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { struct wil6210_priv *wil = file->private_data; - struct wil6210_mbox_hdr_wmi *wmi; + struct wmi_cmd_hdr *wmi; void *cmd; - int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi); + int cmdlen = len - sizeof(struct wmi_cmd_hdr); u16 cmdid; int rc, rc1; @@ -846,7 +846,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, } cmd = &wmi[1]; - cmdid = le16_to_cpu(wmi->id); + cmdid = le16_to_cpu(wmi->command_id); rc1 = wmi_send(wil, cmdid, cmd, cmdlen); kfree(wmi); @@ -990,7 +990,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data) .interval_usec = 0, }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_notify_req_done_event evt; } __packed reply; diff --git a/drivers/net/wireless/ath/wil6210/trace.h b/drivers/net/wireless/ath/wil6210/trace.h index e59239d22b94..c4db2a9d9f7f 100644 --- a/drivers/net/wireless/ath/wil6210/trace.h +++ b/drivers/net/wireless/ath/wil6210/trace.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Qualcomm Atheros, Inc. + * Copyright (c) 2013-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -37,39 +37,40 @@ static inline void trace_ ## name(proto) {} #endif /* !CONFIG_WIL6210_TRACING || defined(__CHECKER__) */ DECLARE_EVENT_CLASS(wil6210_wmi, - TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len), + TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len), TP_ARGS(wmi, buf, buf_len), TP_STRUCT__entry( __field(u8, mid) - __field(u16, id) - __field(u32, timestamp) + __field(u16, command_id) + __field(u32, fw_timestamp) __field(u16, buf_len) __dynamic_array(u8, buf, buf_len) ), TP_fast_assign( __entry->mid = wmi->mid; - __entry->id = le16_to_cpu(wmi->id); - __entry->timestamp = le32_to_cpu(wmi->timestamp); + __entry->command_id = le16_to_cpu(wmi->command_id); + __entry->fw_timestamp = le32_to_cpu(wmi->fw_timestamp); __entry->buf_len = buf_len; memcpy(__get_dynamic_array(buf), buf, buf_len); ), TP_printk( "MID %d id 0x%04x len %d timestamp %d", - __entry->mid, __entry->id, __entry->buf_len, __entry->timestamp + __entry->mid, __entry->command_id, __entry->buf_len, + __entry->fw_timestamp ) ); DEFINE_EVENT(wil6210_wmi, wil6210_wmi_cmd, - TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len), + TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len), TP_ARGS(wmi, buf, buf_len) ); DEFINE_EVENT(wil6210_wmi, wil6210_wmi_event, - TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len), + TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len), TP_ARGS(wmi, buf, buf_len) ); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index f383001b86aa..f260b232fd57 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -820,7 +820,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, }, }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_vring_cfg_done_event cmd; } __packed reply; struct vring *vring = &wil->vring_tx[id]; @@ -897,7 +897,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) }, }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_vring_cfg_done_event cmd; } __packed reply; struct vring *vring = &wil->vring_tx[id]; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f662f7676a31..e69df0c1a125 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -22,6 +22,7 @@ #include #include #include +#include "wmi.h" #include "wil_platform.h" extern bool no_fw_recovery; @@ -334,29 +335,11 @@ struct wil6210_mbox_hdr { /* max. value for wil6210_mbox_hdr.len */ #define MAX_MBOXITEM_SIZE (240) -/** - * struct wil6210_mbox_hdr_wmi - WMI header - * - * @mid: MAC ID - * 00 - default, created by FW - * 01..0f - WiFi ports, driver to create - * 10..fe - debug - * ff - broadcast - * @id: command/event ID - * @timestamp: FW fills for events, free-running msec timer - */ -struct wil6210_mbox_hdr_wmi { - u8 mid; - u8 reserved; - __le16 id; - __le32 timestamp; -} __packed; - struct pending_wmi_event { struct list_head list; struct { struct wil6210_mbox_hdr hdr; - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; u8 data[0]; } __packed event; }; diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index fb090350df6d..db7d2b602d1a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -176,7 +176,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) { struct { struct wil6210_mbox_hdr hdr; - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; } __packed cmd = { .hdr = { .type = WIL_MBOX_HDR_TYPE_WMI, @@ -185,7 +185,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) }, .wmi = { .mid = 0, - .id = cpu_to_le16(cmdid), + .command_id = cpu_to_le16(cmdid), }, }; struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx; @@ -656,7 +656,7 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, int len) { - struct wmi_vring_ba_status_event *evt = d; + struct wmi_ba_status_event *evt = d; struct vring_tx_data *txdata; wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n", @@ -842,10 +842,10 @@ void wmi_recv_cmd(struct wil6210_priv *wil) offsetof(struct wil6210_mbox_ring_desc, sync), 0); /* indicate */ if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && - (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { - struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi; - u16 id = le16_to_cpu(wmi->id); - u32 tstamp = le32_to_cpu(wmi->timestamp); + (len >= sizeof(struct wmi_cmd_hdr))) { + struct wmi_cmd_hdr *wmi = &evt->event.wmi; + u16 id = le16_to_cpu(wmi->command_id); + u32 tstamp = le32_to_cpu(wmi->fw_timestamp); spin_lock_irqsave(&wil->wmi_ev_lock, flags); if (wil->reply_id && wil->reply_id == id) { if (wil->reply_buf) { @@ -968,7 +968,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, .hidden_ssid = hidden_ssid, }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_pcp_started_event evt; } __packed reply; @@ -1022,7 +1022,7 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) { int rc; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_set_ssid_cmd cmd; } __packed reply; int len; /* reply.cmd.ssid_len in CPU order */ @@ -1055,7 +1055,7 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) { int rc; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_set_pcp_channel_cmd cmd; } __packed reply; @@ -1163,7 +1163,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) { int rc; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_listen_started_event evt; } __packed reply; @@ -1200,7 +1200,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh), }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_cfg_rx_chain_done_event evt; } __packed evt; int rc; @@ -1254,7 +1254,7 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW), }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_temp_sense_done_event evt; } __packed reply; @@ -1280,7 +1280,7 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, .disconnect_reason = cpu_to_le16(reason), }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_disconnect_event evt; } __packed reply; @@ -1372,7 +1372,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, .ba_timeout = cpu_to_le16(timeout), }; struct { - struct wil6210_mbox_hdr_wmi wmi; + struct wmi_cmd_hdr wmi; struct wmi_rcp_addba_resp_sent_event evt; } __packed reply; @@ -1428,10 +1428,10 @@ static void wmi_event_handle(struct wil6210_priv *wil, u16 len = le16_to_cpu(hdr->len); if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && - (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { - struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]); + (len >= sizeof(struct wmi_cmd_hdr))) { + struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]); void *evt_data = (void *)(&wmi[1]); - u16 id = le16_to_cpu(wmi->id); + u16 id = le16_to_cpu(wmi->command_id); wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n", id, wil->reply_id); diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 430a4c09db59..29865e0b5203 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. - * Copyright (c) 2006-2012 Wilocity . + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2006-2012 Wilocity * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,187 +17,197 @@ /* * This file contains the definitions of the WMI protocol specified in the - * Wireless Module Interface (WMI) for the Wilocity - * MARLON 60 Gigabit wireless solution. + * Wireless Module Interface (WMI) for the Qualcomm + * 60 GHz wireless solution. * It includes definitions of all the commands and events. * Commands are messages from the host to the WM. * Events are messages from the WM to the host. + * + * This is an automatically generated file. */ #ifndef __WILOCITY_WMI_H__ #define __WILOCITY_WMI_H__ /* General */ -#define WILOCITY_MAX_ASSOC_STA (8) -#define WILOCITY_DEFAULT_ASSOC_STA (1) -#define WMI_MAC_LEN (6) -#define WMI_PROX_RANGE_NUM (3) -#define WMI_MAX_LOSS_DMG_BEACONS (32) +#define WMI_MAX_ASSOC_STA (8) +#define WMI_DEFAULT_ASSOC_STA (1) +#define WMI_MAC_LEN (6) +#define WMI_PROX_RANGE_NUM (3) +#define WMI_MAX_LOSS_DMG_BEACONS (20) + +/* Mailbox interface + * used for commands and events + */ +enum wmi_mid { + MID_DEFAULT = 0x00, + FIRST_DBG_MID_ID = 0x10, + LAST_DBG_MID_ID = 0xFE, + MID_BROADCAST = 0xFF, +}; + +/* WMI_CMD_HDR */ +struct wmi_cmd_hdr { + u8 mid; + u8 reserved; + __le16 command_id; + __le32 fw_timestamp; +} __packed; /* List of Commands */ enum wmi_command_id { - WMI_CONNECT_CMDID = 0x0001, - WMI_DISCONNECT_CMDID = 0x0003, - WMI_DISCONNECT_STA_CMDID = 0x0004, - WMI_START_SCAN_CMDID = 0x0007, - WMI_SET_BSS_FILTER_CMDID = 0x0009, - WMI_SET_PROBED_SSID_CMDID = 0x000a, - WMI_SET_LISTEN_INT_CMDID = 0x000b, - WMI_BCON_CTRL_CMDID = 0x000f, - WMI_ADD_CIPHER_KEY_CMDID = 0x0016, - WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, - WMI_SET_APPIE_CMDID = 0x003f, - WMI_SET_WSC_STATUS_CMDID = 0x0041, - WMI_PXMT_RANGE_CFG_CMDID = 0x0042, - WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, -/* WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, */ - WMI_MEM_READ_CMDID = 0x0800, - WMI_MEM_WR_CMDID = 0x0801, - WMI_ECHO_CMDID = 0x0803, - WMI_DEEP_ECHO_CMDID = 0x0804, - WMI_CONFIG_MAC_CMDID = 0x0805, - WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, - WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, - WMI_PHY_GET_STATISTICS_CMDID = 0x0809, - WMI_FS_TUNE_CMDID = 0x080a, - WMI_CORR_MEASURE_CMDID = 0x080b, - WMI_READ_RSSI_CMDID = 0x080c, - WMI_TEMP_SENSE_CMDID = 0x080e, - WMI_DC_CALIB_CMDID = 0x080f, - WMI_SEND_TONE_CMDID = 0x0810, - WMI_IQ_TX_CALIB_CMDID = 0x0811, - WMI_IQ_RX_CALIB_CMDID = 0x0812, - WMI_SET_UCODE_IDLE_CMDID = 0x0813, - WMI_SET_WORK_MODE_CMDID = 0x0815, - WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, - WMI_MARLON_R_READ_CMDID = 0x0818, - WMI_MARLON_R_WRITE_CMDID = 0x0819, - WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, - MAC_IO_STATIC_PARAMS_CMDID = 0x081b, - MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, - WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, - WMI_RF_RX_TEST_CMDID = 0x081e, - WMI_CFG_RX_CHAIN_CMDID = 0x0820, - WMI_VRING_CFG_CMDID = 0x0821, - WMI_BCAST_VRING_CFG_CMDID = 0x0822, - WMI_VRING_BA_EN_CMDID = 0x0823, - WMI_VRING_BA_DIS_CMDID = 0x0824, - WMI_RCP_ADDBA_RESP_CMDID = 0x0825, - WMI_RCP_DELBA_CMDID = 0x0826, - WMI_SET_SSID_CMDID = 0x0827, - WMI_GET_SSID_CMDID = 0x0828, - WMI_SET_PCP_CHANNEL_CMDID = 0x0829, - WMI_GET_PCP_CHANNEL_CMDID = 0x082a, - WMI_SW_TX_REQ_CMDID = 0x082b, - WMI_READ_MAC_RXQ_CMDID = 0x0830, - WMI_READ_MAC_TXQ_CMDID = 0x0831, - WMI_WRITE_MAC_RXQ_CMDID = 0x0832, - WMI_WRITE_MAC_TXQ_CMDID = 0x0833, - WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834, - WMI_MLME_PUSH_CMDID = 0x0835, - WMI_BEAMFORMING_MGMT_CMDID = 0x0836, - WMI_BF_TXSS_MGMT_CMDID = 0x0837, - WMI_BF_SM_MGMT_CMDID = 0x0838, - WMI_BF_RXSS_MGMT_CMDID = 0x0839, - WMI_BF_TRIG_CMDID = 0x083A, - WMI_SET_SECTORS_CMDID = 0x0849, - WMI_MAINTAIN_PAUSE_CMDID = 0x0850, - WMI_MAINTAIN_RESUME_CMDID = 0x0851, - WMI_RS_MGMT_CMDID = 0x0852, - WMI_RF_MGMT_CMDID = 0x0853, - WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x0854, - WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x0855, + WMI_CONNECT_CMDID = 0x01, + WMI_DISCONNECT_CMDID = 0x03, + WMI_DISCONNECT_STA_CMDID = 0x04, + WMI_START_SCAN_CMDID = 0x07, + WMI_SET_BSS_FILTER_CMDID = 0x09, + WMI_SET_PROBED_SSID_CMDID = 0x0A, + WMI_SET_LISTEN_INT_CMDID = 0x0B, + WMI_BCON_CTRL_CMDID = 0x0F, + WMI_ADD_CIPHER_KEY_CMDID = 0x16, + WMI_DELETE_CIPHER_KEY_CMDID = 0x17, + WMI_PCP_CONF_CMDID = 0x18, + WMI_SET_APPIE_CMDID = 0x3F, + WMI_SET_WSC_STATUS_CMDID = 0x41, + WMI_PXMT_RANGE_CFG_CMDID = 0x42, + WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x43, + WMI_MEM_READ_CMDID = 0x800, + WMI_MEM_WR_CMDID = 0x801, + WMI_ECHO_CMDID = 0x803, + WMI_DEEP_ECHO_CMDID = 0x804, + WMI_CONFIG_MAC_CMDID = 0x805, + WMI_CONFIG_PHY_DEBUG_CMDID = 0x806, + WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x808, + WMI_PHY_GET_STATISTICS_CMDID = 0x809, + WMI_FS_TUNE_CMDID = 0x80A, + WMI_CORR_MEASURE_CMDID = 0x80B, + WMI_READ_RSSI_CMDID = 0x80C, + WMI_TEMP_SENSE_CMDID = 0x80E, + WMI_DC_CALIB_CMDID = 0x80F, + WMI_SEND_TONE_CMDID = 0x810, + WMI_IQ_TX_CALIB_CMDID = 0x811, + WMI_IQ_RX_CALIB_CMDID = 0x812, + WMI_SET_UCODE_IDLE_CMDID = 0x813, + WMI_SET_WORK_MODE_CMDID = 0x815, + WMI_LO_LEAKAGE_CALIB_CMDID = 0x816, + WMI_MARLON_R_READ_CMDID = 0x818, + WMI_MARLON_R_WRITE_CMDID = 0x819, + WMI_MARLON_R_TXRX_SEL_CMDID = 0x81A, + MAC_IO_STATIC_PARAMS_CMDID = 0x81B, + MAC_IO_DYNAMIC_PARAMS_CMDID = 0x81C, + WMI_SILENT_RSSI_CALIB_CMDID = 0x81D, + WMI_RF_RX_TEST_CMDID = 0x81E, + WMI_CFG_RX_CHAIN_CMDID = 0x820, + WMI_VRING_CFG_CMDID = 0x821, + WMI_BCAST_VRING_CFG_CMDID = 0x822, + WMI_VRING_BA_EN_CMDID = 0x823, + WMI_VRING_BA_DIS_CMDID = 0x824, + WMI_RCP_ADDBA_RESP_CMDID = 0x825, + WMI_RCP_DELBA_CMDID = 0x826, + WMI_SET_SSID_CMDID = 0x827, + WMI_GET_SSID_CMDID = 0x828, + WMI_SET_PCP_CHANNEL_CMDID = 0x829, + WMI_GET_PCP_CHANNEL_CMDID = 0x82A, + WMI_SW_TX_REQ_CMDID = 0x82B, + WMI_READ_MAC_RXQ_CMDID = 0x830, + WMI_READ_MAC_TXQ_CMDID = 0x831, + WMI_WRITE_MAC_RXQ_CMDID = 0x832, + WMI_WRITE_MAC_TXQ_CMDID = 0x833, + WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x834, + WMI_MLME_PUSH_CMDID = 0x835, + WMI_BEAMFORMING_MGMT_CMDID = 0x836, + WMI_BF_TXSS_MGMT_CMDID = 0x837, + WMI_BF_SM_MGMT_CMDID = 0x838, + WMI_BF_RXSS_MGMT_CMDID = 0x839, + WMI_BF_TRIG_CMDID = 0x83A, + WMI_SET_SECTORS_CMDID = 0x849, + WMI_MAINTAIN_PAUSE_CMDID = 0x850, + WMI_MAINTAIN_RESUME_CMDID = 0x851, + WMI_RS_MGMT_CMDID = 0x852, + WMI_RF_MGMT_CMDID = 0x853, + WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x854, + WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855, + WMI_OTP_READ_CMDID = 0x856, + WMI_OTP_WRITE_CMDID = 0x857, /* Performance monitoring commands */ - WMI_BF_CTRL_CMDID = 0x0862, - WMI_NOTIFY_REQ_CMDID = 0x0863, - WMI_GET_STATUS_CMDID = 0x0864, - WMI_UNIT_TEST_CMDID = 0x0900, - WMI_HICCUP_CMDID = 0x0901, - WMI_FLASH_READ_CMDID = 0x0902, - WMI_FLASH_WRITE_CMDID = 0x0903, - WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, - /*P2P*/ - WMI_P2P_CFG_CMDID = 0x0910, - WMI_PORT_ALLOCATE_CMDID = 0x0911, - WMI_PORT_DELETE_CMDID = 0x0912, - WMI_POWER_MGMT_CFG_CMDID = 0x0913, - WMI_START_LISTEN_CMDID = 0x0914, - WMI_START_SEARCH_CMDID = 0x0915, - WMI_DISCOVERY_START_CMDID = 0x0916, - WMI_DISCOVERY_STOP_CMDID = 0x0917, - WMI_PCP_START_CMDID = 0x0918, - WMI_PCP_STOP_CMDID = 0x0919, - WMI_GET_PCP_FACTOR_CMDID = 0x091b, - - WMI_SET_MAC_ADDRESS_CMDID = 0xf003, - WMI_ABORT_SCAN_CMDID = 0xf007, - WMI_SET_PMK_CMDID = 0xf028, - - WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041, - WMI_GET_PMK_CMDID = 0xf048, - WMI_SET_PASSPHRASE_CMDID = 0xf049, - WMI_SEND_ASSOC_RES_CMDID = 0xf04a, - WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b, - WMI_EAPOL_TX_CMDID = 0xf04c, - WMI_MAC_ADDR_REQ_CMDID = 0xf04d, - WMI_FW_VER_CMDID = 0xf04e, - WMI_PMC_CMDID = 0xf04f, + WMI_BF_CTRL_CMDID = 0x862, + WMI_NOTIFY_REQ_CMDID = 0x863, + WMI_GET_STATUS_CMDID = 0x864, + WMI_UNIT_TEST_CMDID = 0x900, + WMI_HICCUP_CMDID = 0x901, + WMI_FLASH_READ_CMDID = 0x902, + WMI_FLASH_WRITE_CMDID = 0x903, + /* P2P */ + WMI_P2P_CFG_CMDID = 0x910, + WMI_PORT_ALLOCATE_CMDID = 0x911, + WMI_PORT_DELETE_CMDID = 0x912, + WMI_POWER_MGMT_CFG_CMDID = 0x913, + WMI_START_LISTEN_CMDID = 0x914, + WMI_START_SEARCH_CMDID = 0x915, + WMI_DISCOVERY_START_CMDID = 0x916, + WMI_DISCOVERY_STOP_CMDID = 0x917, + WMI_PCP_START_CMDID = 0x918, + WMI_PCP_STOP_CMDID = 0x919, + WMI_GET_PCP_FACTOR_CMDID = 0x91B, + WMI_SET_MAC_ADDRESS_CMDID = 0xF003, + WMI_ABORT_SCAN_CMDID = 0xF007, + WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, + WMI_GET_PMK_CMDID = 0xF048, + WMI_SET_PASSPHRASE_CMDID = 0xF049, + WMI_SEND_ASSOC_RES_CMDID = 0xF04A, + WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xF04B, + WMI_MAC_ADDR_REQ_CMDID = 0xF04D, + WMI_FW_VER_CMDID = 0xF04E, + WMI_PMC_CMDID = 0xF04F, }; -/* - * Commands data structures - */ - -/* - * WMI_CONNECT_CMDID - */ +/* WMI_CONNECT_CMDID */ enum wmi_network_type { WMI_NETTYPE_INFRA = 0x01, WMI_NETTYPE_ADHOC = 0x02, WMI_NETTYPE_ADHOC_CREATOR = 0x04, WMI_NETTYPE_AP = 0x10, WMI_NETTYPE_P2P = 0x20, - WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */ + /* PCIE over 60g */ + WMI_NETTYPE_WBE = 0x40, }; enum wmi_dot11_auth_mode { - WMI_AUTH11_OPEN = 0x01, - WMI_AUTH11_SHARED = 0x02, - WMI_AUTH11_LEAP = 0x04, - WMI_AUTH11_WSC = 0x08, + WMI_AUTH11_OPEN = 0x01, + WMI_AUTH11_SHARED = 0x02, + WMI_AUTH11_LEAP = 0x04, + WMI_AUTH11_WSC = 0x08, }; enum wmi_auth_mode { - WMI_AUTH_NONE = 0x01, - WMI_AUTH_WPA = 0x02, - WMI_AUTH_WPA2 = 0x04, - WMI_AUTH_WPA_PSK = 0x08, - WMI_AUTH_WPA2_PSK = 0x10, - WMI_AUTH_WPA_CCKM = 0x20, - WMI_AUTH_WPA2_CCKM = 0x40, + WMI_AUTH_NONE = 0x01, + WMI_AUTH_WPA = 0x02, + WMI_AUTH_WPA2 = 0x04, + WMI_AUTH_WPA_PSK = 0x08, + WMI_AUTH_WPA2_PSK = 0x10, + WMI_AUTH_WPA_CCKM = 0x20, + WMI_AUTH_WPA2_CCKM = 0x40, }; enum wmi_crypto_type { - WMI_CRYPT_NONE = 0x01, - WMI_CRYPT_WEP = 0x02, - WMI_CRYPT_TKIP = 0x04, - WMI_CRYPT_AES = 0x08, - WMI_CRYPT_AES_GCMP = 0x20, + WMI_CRYPT_NONE = 0x01, + WMI_CRYPT_AES_GCMP = 0x20, }; enum wmi_connect_ctrl_flag_bits { - WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, - WMI_CONNECT_SEND_REASSOC = 0x0002, - WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER = 0x0004, - WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, - WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, - WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, - WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040, - WMI_CONNECT_DO_NOT_DEAUTH = 0x0080, + WMI_CONNECT_ASSOC_POLICY_USER = 0x01, + WMI_CONNECT_SEND_REASSOC = 0x02, + WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER = 0x04, + WMI_CONNECT_PROFILE_MATCH_DONE = 0x08, + WMI_CONNECT_IGNORE_AAC_BEACON = 0x10, + WMI_CONNECT_CSA_FOLLOW_BSS = 0x20, + WMI_CONNECT_DO_WPA_OFFLOAD = 0x40, + WMI_CONNECT_DO_NOT_DEAUTH = 0x80, }; -#define WMI_MAX_SSID_LEN (32) +#define WMI_MAX_SSID_LEN (32) +/* WMI_CONNECT_CMDID */ struct wmi_connect_cmd { u8 network_type; u8 dot11_auth_mode; @@ -216,31 +226,17 @@ struct wmi_connect_cmd { u8 reserved1[2]; } __packed; -/* - * WMI_DISCONNECT_STA_CMDID - */ +/* WMI_DISCONNECT_STA_CMDID */ struct wmi_disconnect_sta_cmd { u8 dst_mac[WMI_MAC_LEN]; __le16 disconnect_reason; } __packed; -/* - * WMI_SET_PMK_CMDID - */ - -#define WMI_MIN_KEY_INDEX (0) #define WMI_MAX_KEY_INDEX (3) #define WMI_MAX_KEY_LEN (32) #define WMI_PASSPHRASE_LEN (64) -#define WMI_PMK_LEN (32) - -struct wmi_set_pmk_cmd { - u8 pmk[WMI_PMK_LEN]; -} __packed; -/* - * WMI_SET_PASSPHRASE_CMDID - */ +/* WMI_SET_PASSPHRASE_CMDID */ struct wmi_set_passphrase_cmd { u8 ssid[WMI_MAX_SSID_LEN]; u8 passphrase[WMI_PASSPHRASE_LEN]; @@ -248,36 +244,34 @@ struct wmi_set_passphrase_cmd { u8 passphrase_len; } __packed; -/* - * WMI_ADD_CIPHER_KEY_CMDID - */ +/* WMI_ADD_CIPHER_KEY_CMDID */ enum wmi_key_usage { - WMI_KEY_USE_PAIRWISE = 0, - WMI_KEY_USE_RX_GROUP = 1, - WMI_KEY_USE_TX_GROUP = 2, + WMI_KEY_USE_PAIRWISE = 0x00, + WMI_KEY_USE_RX_GROUP = 0x01, + WMI_KEY_USE_TX_GROUP = 0x02, }; struct wmi_add_cipher_key_cmd { u8 key_index; u8 key_type; - u8 key_usage; /* enum wmi_key_usage */ + /* enum wmi_key_usage */ + u8 key_usage; u8 key_len; - u8 key_rsc[8]; /* key replay sequence counter */ + /* key replay sequence counter */ + u8 key_rsc[8]; u8 key[WMI_MAX_KEY_LEN]; - u8 key_op_ctrl; /* Additional Key Control information */ + /* Additional Key Control information */ + u8 key_op_ctrl; u8 mac[WMI_MAC_LEN]; } __packed; -/* - * WMI_DELETE_CIPHER_KEY_CMDID - */ +/* WMI_DELETE_CIPHER_KEY_CMDID */ struct wmi_delete_cipher_key_cmd { u8 key_index; u8 mac[WMI_MAC_LEN]; } __packed; -/* - * WMI_START_SCAN_CMDID +/* WMI_START_SCAN_CMDID * * Start L1 scan operation * @@ -286,147 +280,142 @@ struct wmi_delete_cipher_key_cmd { * - WMI_SCAN_COMPLETE_EVENTID */ enum wmi_scan_type { - WMI_ACTIVE_SCAN = 0, - WMI_SHORT_SCAN = 1, - WMI_PBC_SCAN = 2, - WMI_DIRECT_SCAN = 3, - WMI_LONG_SCAN = 4, + WMI_ACTIVE_SCAN = 0x00, + WMI_SHORT_SCAN = 0x01, + WMI_PASSIVE_SCAN = 0x02, + WMI_DIRECT_SCAN = 0x03, + WMI_LONG_SCAN = 0x04, }; +/* WMI_START_SCAN_CMDID */ struct wmi_start_scan_cmd { - u8 direct_scan_mac_addr[6]; + u8 direct_scan_mac_addr[WMI_MAC_LEN]; + /* DMG Beacon frame is transmitted during active scanning */ u8 discovery_mode; + /* reserved */ u8 reserved; - __le32 home_dwell_time; /* Max duration in the home channel(ms) */ - __le32 force_scan_interval; /* Time interval between scans (ms)*/ - u8 scan_type; /* wmi_scan_type */ - u8 num_channels; /* how many channels follow */ + /* Max duration in the home channel(ms) */ + __le32 dwell_time; + /* Time interval between scans (ms) */ + __le32 force_scan_interval; + /* enum wmi_scan_type */ + u8 scan_type; + /* how many channels follow */ + u8 num_channels; + /* channels ID's: + * 0 - 58320 MHz + * 1 - 60480 MHz + * 2 - 62640 MHz + */ struct { u8 channel; u8 reserved; - } channel_list[0]; /* channels ID's */ - /* 0 - 58320 MHz */ - /* 1 - 60480 MHz */ - /* 2 - 62640 MHz */ + } channel_list[0]; } __packed; -/* - * WMI_SET_PROBED_SSID_CMDID - */ +/* WMI_SET_PROBED_SSID_CMDID */ #define MAX_PROBED_SSID_INDEX (3) enum wmi_ssid_flag { - WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ - WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */ - WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */ + /* disables entry */ + WMI_SSID_FLAG_DISABLE = 0x00, + /* probes specified ssid */ + WMI_SSID_FLAG_SPECIFIC = 0x01, + /* probes for any ssid */ + WMI_SSID_FLAG_ANY = 0x02, }; struct wmi_probed_ssid_cmd { - u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */ - u8 flag; /* enum wmi_ssid_flag */ + /* 0 to MAX_PROBED_SSID_INDEX */ + u8 entry_index; + /* enum wmi_ssid_flag */ + u8 flag; u8 ssid_len; u8 ssid[WMI_MAX_SSID_LEN]; } __packed; -/* - * WMI_SET_APPIE_CMDID +/* WMI_SET_APPIE_CMDID * Add Application specified IE to a management frame */ -#define WMI_MAX_IE_LEN (1024) +#define WMI_MAX_IE_LEN (1024) -/* - * Frame Types - */ +/* Frame Types */ enum wmi_mgmt_frame_type { - WMI_FRAME_BEACON = 0, - WMI_FRAME_PROBE_REQ = 1, - WMI_FRAME_PROBE_RESP = 2, - WMI_FRAME_ASSOC_REQ = 3, - WMI_FRAME_ASSOC_RESP = 4, - WMI_NUM_MGMT_FRAME, + WMI_FRAME_BEACON = 0x00, + WMI_FRAME_PROBE_REQ = 0x01, + WMI_FRAME_PROBE_RESP = 0x02, + WMI_FRAME_ASSOC_REQ = 0x03, + WMI_FRAME_ASSOC_RESP = 0x04, + WMI_NUM_MGMT_FRAME = 0x05, }; struct wmi_set_appie_cmd { - u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ + /* enum wmi_mgmt_frame_type */ + u8 mgmt_frm_type; u8 reserved; - __le16 ie_len; /* Length of the IE to be added to MGMT frame */ + /* Length of the IE to be added to MGMT frame */ + __le16 ie_len; u8 ie_info[0]; } __packed; -/* - * WMI_PXMT_RANGE_CFG_CMDID - */ +/* WMI_PXMT_RANGE_CFG_CMDID */ struct wmi_pxmt_range_cfg_cmd { u8 dst_mac[WMI_MAC_LEN]; __le16 range; } __packed; -/* - * WMI_PXMT_SNR2_RANGE_CFG_CMDID - */ +/* WMI_PXMT_SNR2_RANGE_CFG_CMDID */ struct wmi_pxmt_snr2_range_cfg_cmd { - s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; + s8 snr2range_arr[2]; } __packed; -/* - * WMI_RF_MGMT_CMDID - */ +/* WMI_RF_MGMT_CMDID */ enum wmi_rf_mgmt_type { - WMI_RF_MGMT_W_DISABLE = 0, - WMI_RF_MGMT_W_ENABLE = 1, - WMI_RF_MGMT_GET_STATUS = 2, + WMI_RF_MGMT_W_DISABLE = 0x00, + WMI_RF_MGMT_W_ENABLE = 0x01, + WMI_RF_MGMT_GET_STATUS = 0x02, }; +/* WMI_RF_MGMT_CMDID */ struct wmi_rf_mgmt_cmd { __le32 rf_mgmt_type; } __packed; -/* - * WMI_THERMAL_THROTTLING_CTRL_CMDID - */ +/* WMI_THERMAL_THROTTLING_CTRL_CMDID */ #define THERMAL_THROTTLING_USE_DEFAULT_MAX_TXOP_LENGTH (0xFFFFFFFF) +/* WMI_THERMAL_THROTTLING_CTRL_CMDID */ struct wmi_thermal_throttling_ctrl_cmd { __le32 time_on_usec; __le32 time_off_usec; __le32 max_txop_length_usec; } __packed; -/* - * WMI_RF_RX_TEST_CMDID - */ +/* WMI_RF_RX_TEST_CMDID */ struct wmi_rf_rx_test_cmd { __le32 sector; } __packed; -/* - * WMI_CORR_MEASURE_CMDID - */ +/* WMI_CORR_MEASURE_CMDID */ struct wmi_corr_measure_cmd { - s32 freq_mhz; + __le32 freq_mhz; __le32 length_samples; __le32 iterations; } __packed; -/* - * WMI_SET_SSID_CMDID - */ +/* WMI_SET_SSID_CMDID */ struct wmi_set_ssid_cmd { __le32 ssid_len; u8 ssid[WMI_MAX_SSID_LEN]; } __packed; -/* - * WMI_SET_PCP_CHANNEL_CMDID - */ +/* WMI_SET_PCP_CHANNEL_CMDID */ struct wmi_set_pcp_channel_cmd { u8 channel; u8 reserved[3]; } __packed; -/* - * WMI_BCON_CTRL_CMDID - */ +/* WMI_BCON_CTRL_CMDID */ struct wmi_bcon_ctrl_cmd { __le16 bcon_interval; __le16 frag_num; @@ -435,214 +424,192 @@ struct wmi_bcon_ctrl_cmd { u8 pcp_max_assoc_sta; u8 disable_sec_offload; u8 disable_sec; + u8 hidden_ssid; + u8 is_go; + u8 reserved[2]; } __packed; -/******* P2P ***********/ - -/* - * WMI_PORT_ALLOCATE_CMDID - */ +/* WMI_PORT_ALLOCATE_CMDID */ enum wmi_port_role { - WMI_PORT_STA = 0, - WMI_PORT_PCP = 1, - WMI_PORT_AP = 2, - WMI_PORT_P2P_DEV = 3, - WMI_PORT_P2P_CLIENT = 4, - WMI_PORT_P2P_GO = 5, + WMI_PORT_STA = 0x00, + WMI_PORT_PCP = 0x01, + WMI_PORT_AP = 0x02, + WMI_PORT_P2P_DEV = 0x03, + WMI_PORT_P2P_CLIENT = 0x04, + WMI_PORT_P2P_GO = 0x05, }; +/* WMI_PORT_ALLOCATE_CMDID */ struct wmi_port_allocate_cmd { u8 mac[WMI_MAC_LEN]; u8 port_role; u8 mid; } __packed; -/* - * WMI_PORT_DELETE_CMDID - */ -struct wmi_delete_port_cmd { +/* WMI_PORT_DELETE_CMDID */ +struct wmi_port_delete_cmd { u8 mid; u8 reserved[3]; } __packed; -/* - * WMI_P2P_CFG_CMDID - */ +/* WMI_P2P_CFG_CMDID */ enum wmi_discovery_mode { - WMI_DISCOVERY_MODE_NON_OFFLOAD = 0, - WMI_DISCOVERY_MODE_OFFLOAD = 1, - WMI_DISCOVERY_MODE_PEER2PEER = 2, + WMI_DISCOVERY_MODE_NON_OFFLOAD = 0x00, + WMI_DISCOVERY_MODE_OFFLOAD = 0x01, + WMI_DISCOVERY_MODE_PEER2PEER = 0x02, }; struct wmi_p2p_cfg_cmd { - u8 discovery_mode; /* wmi_discovery_mode */ + /* enum wmi_discovery_mode */ + u8 discovery_mode; u8 channel; - __le16 bcon_interval; /* base to listen/search duration calculation */ + /* base to listen/search duration calculation */ + __le16 bcon_interval; } __packed; -/* - * WMI_POWER_MGMT_CFG_CMDID - */ +/* WMI_POWER_MGMT_CFG_CMDID */ enum wmi_power_source_type { - WMI_POWER_SOURCE_BATTERY = 0, - WMI_POWER_SOURCE_OTHER = 1, + WMI_POWER_SOURCE_BATTERY = 0x00, + WMI_POWER_SOURCE_OTHER = 0x01, }; struct wmi_power_mgmt_cfg_cmd { - u8 power_source; /* wmi_power_source_type */ + /* enum wmi_power_source_type */ + u8 power_source; u8 reserved[3]; } __packed; -/* - * WMI_PCP_START_CMDID - */ - -enum wmi_hidden_ssid { - WMI_HIDDEN_SSID_DISABLED = 0, - WMI_HIDDEN_SSID_SEND_EMPTY = 1, - WMI_HIDDEN_SSID_CLEAR = 2, -}; - +/* WMI_PCP_START_CMDID */ struct wmi_pcp_start_cmd { __le16 bcon_interval; u8 pcp_max_assoc_sta; u8 hidden_ssid; - u8 reserved0[8]; + u8 is_go; + u8 reserved0[7]; u8 network_type; u8 channel; u8 disable_sec_offload; u8 disable_sec; } __packed; -/* - * WMI_SW_TX_REQ_CMDID - */ +/* WMI_SW_TX_REQ_CMDID */ struct wmi_sw_tx_req_cmd { u8 dst_mac[WMI_MAC_LEN]; __le16 len; u8 payload[0]; } __packed; -/* - * WMI_VRING_CFG_CMDID - */ - struct wmi_sw_ring_cfg { __le64 ring_mem_base; __le16 ring_size; __le16 max_mpdu_size; } __packed; +/* wmi_vring_cfg_schd */ struct wmi_vring_cfg_schd { __le16 priority; __le16 timeslot_us; } __packed; enum wmi_vring_cfg_encap_trans_type { - WMI_VRING_ENC_TYPE_802_3 = 0, - WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1, + WMI_VRING_ENC_TYPE_802_3 = 0x00, + WMI_VRING_ENC_TYPE_NATIVE_WIFI = 0x01, }; enum wmi_vring_cfg_ds_cfg { - WMI_VRING_DS_PBSS = 0, - WMI_VRING_DS_STATION = 1, - WMI_VRING_DS_AP = 2, - WMI_VRING_DS_ADDR4 = 3, + WMI_VRING_DS_PBSS = 0x00, + WMI_VRING_DS_STATION = 0x01, + WMI_VRING_DS_AP = 0x02, + WMI_VRING_DS_ADDR4 = 0x03, }; enum wmi_vring_cfg_nwifi_ds_trans_type { - WMI_NWIFI_TX_TRANS_MODE_NO = 0, - WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1, - WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2, + WMI_NWIFI_TX_TRANS_MODE_NO = 0x00, + WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 0x01, + WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 0x02, }; enum wmi_vring_cfg_schd_params_priority { - WMI_SCH_PRIO_REGULAR = 0, - WMI_SCH_PRIO_HIGH = 1, + WMI_SCH_PRIO_REGULAR = 0x00, + WMI_SCH_PRIO_HIGH = 0x01, }; -#define CIDXTID_CID_POS (0) -#define CIDXTID_CID_LEN (4) -#define CIDXTID_CID_MSK (0xF) -#define CIDXTID_TID_POS (4) -#define CIDXTID_TID_LEN (4) -#define CIDXTID_TID_MSK (0xF0) +#define CIDXTID_CID_POS (0) +#define CIDXTID_CID_LEN (4) +#define CIDXTID_CID_MSK (0xF) +#define CIDXTID_TID_POS (4) +#define CIDXTID_TID_LEN (4) +#define CIDXTID_TID_MSK (0xF0) +#define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) +#define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) +#define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) +#define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) +#define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) +#define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) +#define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) +#define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) +#define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) struct wmi_vring_cfg { struct wmi_sw_ring_cfg tx_sw_ring; - u8 ringid; /* 0-23 vrings */ - + /* 0-23 vrings */ + u8 ringid; u8 cidxtid; - u8 encap_trans_type; - u8 ds_cfg; /* 802.3 DS cfg */ + /* 802.3 DS cfg */ + u8 ds_cfg; u8 nwifi_ds_trans_type; - - #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) - #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) - #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) - #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) - #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) - #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) u8 mac_ctrl; - - #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) - #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) - #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) u8 to_resolution; u8 agg_max_wsize; struct wmi_vring_cfg_schd schd_params; } __packed; enum wmi_vring_cfg_cmd_action { - WMI_VRING_CMD_ADD = 0, - WMI_VRING_CMD_MODIFY = 1, - WMI_VRING_CMD_DELETE = 2, + WMI_VRING_CMD_ADD = 0x00, + WMI_VRING_CMD_MODIFY = 0x01, + WMI_VRING_CMD_DELETE = 0x02, }; +/* WMI_VRING_CFG_CMDID */ struct wmi_vring_cfg_cmd { __le32 action; struct wmi_vring_cfg vring_cfg; } __packed; -/* - * WMI_BCAST_VRING_CFG_CMDID - */ struct wmi_bcast_vring_cfg { struct wmi_sw_ring_cfg tx_sw_ring; - u8 ringid; /* 0-23 vrings */ + /* 0-23 vrings */ + u8 ringid; u8 encap_trans_type; - u8 ds_cfg; /* 802.3 DS cfg */ + /* 802.3 DS cfg */ + u8 ds_cfg; u8 nwifi_ds_trans_type; } __packed; +/* WMI_BCAST_VRING_CFG_CMDID */ struct wmi_bcast_vring_cfg_cmd { __le32 action; struct wmi_bcast_vring_cfg vring_cfg; } __packed; -/* - * WMI_VRING_BA_EN_CMDID - */ +/* WMI_VRING_BA_EN_CMDID */ struct wmi_vring_ba_en_cmd { u8 ringid; u8 agg_max_wsize; __le16 ba_timeout; u8 amsdu; + u8 reserved[3]; } __packed; -/* - * WMI_VRING_BA_DIS_CMDID - */ +/* WMI_VRING_BA_DIS_CMDID */ struct wmi_vring_ba_dis_cmd { u8 ringid; u8 reserved; __le16 reason; } __packed; -/* - * WMI_NOTIFY_REQ_CMDID - */ +/* WMI_NOTIFY_REQ_CMDID */ struct wmi_notify_req_cmd { u8 cid; u8 year; @@ -655,102 +622,100 @@ struct wmi_notify_req_cmd { u8 miliseconds; } __packed; -/* - * WMI_CFG_RX_CHAIN_CMDID - */ +/* WMI_CFG_RX_CHAIN_CMDID */ enum wmi_sniffer_cfg_mode { - WMI_SNIFFER_OFF = 0, - WMI_SNIFFER_ON = 1, + WMI_SNIFFER_OFF = 0x00, + WMI_SNIFFER_ON = 0x01, }; enum wmi_sniffer_cfg_phy_info_mode { - WMI_SNIFFER_PHY_INFO_DISABLED = 0, - WMI_SNIFFER_PHY_INFO_ENABLED = 1, + WMI_SNIFFER_PHY_INFO_DISABLED = 0x00, + WMI_SNIFFER_PHY_INFO_ENABLED = 0x01, }; enum wmi_sniffer_cfg_phy_support { - WMI_SNIFFER_CP = 0, - WMI_SNIFFER_DP = 1, - WMI_SNIFFER_BOTH_PHYS = 2, + WMI_SNIFFER_CP = 0x00, + WMI_SNIFFER_DP = 0x01, + WMI_SNIFFER_BOTH_PHYS = 0x02, }; +/* wmi_sniffer_cfg */ struct wmi_sniffer_cfg { - __le32 mode; /* enum wmi_sniffer_cfg_mode */ - __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */ - __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */ + /* enum wmi_sniffer_cfg_mode */ + __le32 mode; + /* enum wmi_sniffer_cfg_phy_info_mode */ + __le32 phy_info_mode; + /* enum wmi_sniffer_cfg_phy_support */ + __le32 phy_support; u8 channel; u8 reserved[3]; } __packed; enum wmi_cfg_rx_chain_cmd_action { - WMI_RX_CHAIN_ADD = 0, - WMI_RX_CHAIN_DEL = 1, + WMI_RX_CHAIN_ADD = 0x00, + WMI_RX_CHAIN_DEL = 0x01, }; enum wmi_cfg_rx_chain_cmd_decap_trans_type { - WMI_DECAP_TYPE_802_3 = 0, - WMI_DECAP_TYPE_NATIVE_WIFI = 1, - WMI_DECAP_TYPE_NONE = 2, + WMI_DECAP_TYPE_802_3 = 0x00, + WMI_DECAP_TYPE_NATIVE_WIFI = 0x01, + WMI_DECAP_TYPE_NONE = 0x02, }; enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { - WMI_NWIFI_RX_TRANS_MODE_NO = 0, - WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1, - WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, + WMI_NWIFI_RX_TRANS_MODE_NO = 0x00, + WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 0x01, + WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 0x02, }; enum wmi_cfg_rx_chain_cmd_reorder_type { - WMI_RX_HW_REORDER = 0, - WMI_RX_SW_REORDER = 1, + WMI_RX_HW_REORDER = 0x00, + WMI_RX_SW_REORDER = 0x01, }; +#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) +#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) +#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) +#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS (1) +#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN (1) +#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK (0x2) +#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) +#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) +#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) +#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) +#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) +#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) +#define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) +#define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) +#define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) +#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) +#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) +#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) +#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) +#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) +#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) +#define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) +#define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) +#define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) +#define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) +#define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) +#define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) +#define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) +#define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) +#define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) + +/* WMI_CFG_RX_CHAIN_CMDID */ struct wmi_cfg_rx_chain_cmd { __le32 action; struct wmi_sw_ring_cfg rx_sw_ring; u8 mid; u8 decap_trans_type; - - #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) - #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) - #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) - #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS (1) - #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN (1) - #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK (0x2) u8 l2_802_3_offload_ctrl; - - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) u8 l2_nwifi_offload_ctrl; - u8 vlan_id; u8 nwifi_ds_trans_type; - - #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) - #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) - #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) - #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) - #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) - #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) u8 l3_l4_ctrl; - - #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) - #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) - #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) - #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) - #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) - #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) - #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) - #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) u8 ring_ctrl; - __le16 prefetch_thrsh; __le16 wb_thrsh; __le32 itr_value; @@ -758,31 +723,27 @@ struct wmi_cfg_rx_chain_cmd { u8 reorder_type; u8 reserved; struct wmi_sniffer_cfg sniffer_cfg; + __le16 max_rx_pl_per_desc; } __packed; -/* - * WMI_RCP_ADDBA_RESP_CMDID - */ +/* WMI_RCP_ADDBA_RESP_CMDID */ struct wmi_rcp_addba_resp_cmd { u8 cidxtid; u8 dialog_token; __le16 status_code; - __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ + /* ieee80211_ba_parameterset field to send */ + __le16 ba_param_set; __le16 ba_timeout; } __packed; -/* - * WMI_RCP_DELBA_CMDID - */ +/* WMI_RCP_DELBA_CMDID */ struct wmi_rcp_delba_cmd { u8 cidxtid; u8 reserved; __le16 reason; } __packed; -/* - * WMI_RCP_ADDBA_REQ_CMDID - */ +/* WMI_RCP_ADDBA_REQ_CMDID */ struct wmi_rcp_addba_req_cmd { u8 cidxtid; u8 dialog_token; @@ -793,32 +754,16 @@ struct wmi_rcp_addba_req_cmd { __le16 ba_seq_ctrl; } __packed; -/* - * WMI_SET_MAC_ADDRESS_CMDID - */ +/* WMI_SET_MAC_ADDRESS_CMDID */ struct wmi_set_mac_address_cmd { u8 mac[WMI_MAC_LEN]; u8 reserved[2]; } __packed; -/* -* WMI_EAPOL_TX_CMDID -*/ -struct wmi_eapol_tx_cmd { - u8 dst_mac[WMI_MAC_LEN]; - __le16 eapol_len; - u8 eapol[0]; -} __packed; - -/* - * WMI_ECHO_CMDID - * +/* WMI_ECHO_CMDID * Check FW is alive - * * WMI_DEEP_ECHO_CMDID - * * Check FW and ucode are alive - * * Returned event: WMI_ECHO_RSP_EVENTID * same event for both commands */ @@ -826,70 +771,79 @@ struct wmi_echo_cmd { __le32 value; } __packed; -/* - * WMI_TEMP_SENSE_CMDID +/* WMI_OTP_READ_CMDID */ +struct wmi_otp_read_cmd { + __le32 addr; + __le32 size; + __le32 values; +} __packed; + +/* WMI_OTP_WRITE_CMDID */ +struct wmi_otp_write_cmd { + __le32 addr; + __le32 size; + __le32 values; +} __packed; + +/* WMI_TEMP_SENSE_CMDID * * Measure MAC and radio temperatures + * + * Possible modes for temperature measurement */ - -/* Possible modes for temperature measurement */ enum wmi_temperature_measure_mode { - TEMPERATURE_USE_OLD_VALUE = 0x1, - TEMPERATURE_MEASURE_NOW = 0x2, + TEMPERATURE_USE_OLD_VALUE = 0x01, + TEMPERATURE_MEASURE_NOW = 0x02, }; +/* WMI_TEMP_SENSE_CMDID */ struct wmi_temp_sense_cmd { __le32 measure_baseband_en; __le32 measure_rf_en; __le32 measure_mode; } __packed; -/* - * WMI_PMC_CMDID - */ -enum wmi_pmc_op_e { - WMI_PMC_ALLOCATE = 0, - WMI_PMC_RELEASE = 1, +enum wmi_pmc_op { + WMI_PMC_ALLOCATE = 0x00, + WMI_PMC_RELEASE = 0x01, }; +/* WMI_PMC_CMDID */ struct wmi_pmc_cmd { - u8 op; /* enum wmi_pmc_cmd_op_type */ + /* enum wmi_pmc_cmd_op_type */ + u8 op; u8 reserved; __le16 ring_size; __le64 mem_base; } __packed; -/* - * WMI Events - */ - -/* +/* WMI Events * List of Events (target to host) */ enum wmi_event_id { WMI_READY_EVENTID = 0x1001, WMI_CONNECT_EVENTID = 0x1002, WMI_DISCONNECT_EVENTID = 0x1003, - WMI_SCAN_COMPLETE_EVENTID = 0x100a, - WMI_REPORT_STATISTICS_EVENTID = 0x100b, + WMI_SCAN_COMPLETE_EVENTID = 0x100A, + WMI_REPORT_STATISTICS_EVENTID = 0x100B, WMI_RD_MEM_RSP_EVENTID = 0x1800, WMI_FW_READY_EVENTID = 0x1801, - WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, + WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x200, WMI_ECHO_RSP_EVENTID = 0x1803, - WMI_FS_TUNE_DONE_EVENTID = 0x180a, - WMI_CORR_MEASURE_EVENTID = 0x180b, - WMI_READ_RSSI_EVENTID = 0x180c, - WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, - WMI_DC_CALIB_DONE_EVENTID = 0x180f, + WMI_FS_TUNE_DONE_EVENTID = 0x180A, + WMI_CORR_MEASURE_EVENTID = 0x180B, + WMI_READ_RSSI_EVENTID = 0x180C, + WMI_TEMP_SENSE_DONE_EVENTID = 0x180E, + WMI_DC_CALIB_DONE_EVENTID = 0x180F, WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, - WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, - WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, - WMI_RF_RX_TEST_DONE_EVENTID = 0x181e, + WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181A, + WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181D, + WMI_RF_RX_TEST_DONE_EVENTID = 0x181E, WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, WMI_VRING_CFG_DONE_EVENTID = 0x1821, WMI_BA_STATUS_EVENTID = 0x1823, @@ -897,15 +851,13 @@ enum wmi_event_id { WMI_RCP_ADDBA_RESP_SENT_EVENTID = 0x1825, WMI_DELBA_EVENTID = 0x1826, WMI_GET_SSID_EVENTID = 0x1828, - WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, - WMI_SW_TX_COMPLETE_EVENTID = 0x182b, - + WMI_GET_PCP_CHANNEL_EVENTID = 0x182A, + WMI_SW_TX_COMPLETE_EVENTID = 0x182B, WMI_READ_MAC_RXQ_EVENTID = 0x1830, WMI_READ_MAC_TXQ_EVENTID = 0x1831, WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, - WMI_BEAMFORMING_MGMT_DONE_EVENTID = 0x1836, WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, @@ -915,20 +867,18 @@ enum wmi_event_id { WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, WMI_RX_MGMT_PACKET_EVENTID = 0x1840, WMI_TX_MGMT_PACKET_EVENTID = 0x1841, - + WMI_OTP_READ_RESULT_EVENTID = 0x1856, /* Performance monitoring events */ WMI_DATA_PORT_OPEN_EVENTID = 0x1860, WMI_WBE_LINK_DOWN_EVENTID = 0x1861, - WMI_BF_CTRL_DONE_EVENTID = 0x1862, WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, WMI_GET_STATUS_DONE_EVENTID = 0x1864, WMI_VRING_EN_EVENTID = 0x1865, - WMI_UNIT_TEST_EVENTID = 0x1900, WMI_FLASH_READ_DONE_EVENTID = 0x1902, WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, - /*P2P*/ + /* P2P */ WMI_P2P_CFG_DONE_EVENTID = 0x1910, WMI_PORT_ALLOCATED_EVENTID = 0x1911, WMI_PORT_DELETED_EVENTID = 0x1912, @@ -938,49 +888,42 @@ enum wmi_event_id { WMI_DISCOVERY_STOPPED_EVENTID = 0x1917, WMI_PCP_STARTED_EVENTID = 0x1918, WMI_PCP_STOPPED_EVENTID = 0x1919, - WMI_PCP_FACTOR_EVENTID = 0x191a, + WMI_PCP_FACTOR_EVENTID = 0x191A, WMI_SET_CHANNEL_EVENTID = 0x9000, WMI_ASSOC_REQ_EVENTID = 0x9001, WMI_EAPOL_RX_EVENTID = 0x9002, WMI_MAC_ADDR_RESP_EVENTID = 0x9003, WMI_FW_VER_EVENTID = 0x9004, + WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID = 0x9005, }; -/* - * Events data structures - */ - +/* Events data structures */ enum wmi_fw_status { - WMI_FW_STATUS_SUCCESS, - WMI_FW_STATUS_FAILURE, + WMI_FW_STATUS_SUCCESS = 0x00, + WMI_FW_STATUS_FAILURE = 0x01, }; -/* - * WMI_RF_MGMT_STATUS_EVENTID - */ +/* WMI_RF_MGMT_STATUS_EVENTID */ enum wmi_rf_status { - WMI_RF_ENABLED = 0, - WMI_RF_DISABLED_HW = 1, - WMI_RF_DISABLED_SW = 2, - WMI_RF_DISABLED_HW_SW = 3, + WMI_RF_ENABLED = 0x00, + WMI_RF_DISABLED_HW = 0x01, + WMI_RF_DISABLED_SW = 0x02, + WMI_RF_DISABLED_HW_SW = 0x03, }; +/* WMI_RF_MGMT_STATUS_EVENTID */ struct wmi_rf_mgmt_status_event { __le32 rf_status; } __packed; -/* - * WMI_THERMAL_THROTTLING_STATUS_EVENTID - */ +/* WMI_THERMAL_THROTTLING_STATUS_EVENTID */ struct wmi_thermal_throttling_status_event { __le32 time_on_usec; __le32 time_off_usec; __le32 max_txop_length_usec; } __packed; -/* - * WMI_GET_STATUS_DONE_EVENTID - */ +/* WMI_GET_STATUS_DONE_EVENTID */ struct wmi_get_status_done_event { __le32 is_associated; u8 cid; @@ -996,9 +939,7 @@ struct wmi_get_status_done_event { __le32 is_secured; } __packed; -/* - * WMI_FW_VER_EVENTID - */ +/* WMI_FW_VER_EVENTID */ struct wmi_fw_ver_event { u8 major; u8 minor; @@ -1006,9 +947,7 @@ struct wmi_fw_ver_event { __le16 build; } __packed; -/* -* WMI_MAC_ADDR_RESP_EVENTID -*/ +/* WMI_MAC_ADDR_RESP_EVENTID */ struct wmi_mac_addr_resp_event { u8 mac[WMI_MAC_LEN]; u8 auth_mode; @@ -1016,42 +955,38 @@ struct wmi_mac_addr_resp_event { __le32 offload_mode; } __packed; -/* -* WMI_EAPOL_RX_EVENTID -*/ +/* WMI_EAPOL_RX_EVENTID */ struct wmi_eapol_rx_event { u8 src_mac[WMI_MAC_LEN]; __le16 eapol_len; u8 eapol[0]; } __packed; -/* -* WMI_READY_EVENTID -*/ +/* WMI_READY_EVENTID */ enum wmi_phy_capability { - WMI_11A_CAPABILITY = 1, - WMI_11G_CAPABILITY = 2, - WMI_11AG_CAPABILITY = 3, - WMI_11NA_CAPABILITY = 4, - WMI_11NG_CAPABILITY = 5, - WMI_11NAG_CAPABILITY = 6, - WMI_11AD_CAPABILITY = 7, - WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY, + WMI_11A_CAPABILITY = 0x01, + WMI_11G_CAPABILITY = 0x02, + WMI_11AG_CAPABILITY = 0x03, + WMI_11NA_CAPABILITY = 0x04, + WMI_11NG_CAPABILITY = 0x05, + WMI_11NAG_CAPABILITY = 0x06, + WMI_11AD_CAPABILITY = 0x07, + WMI_11N_CAPABILITY_OFFSET = 0x03, }; struct wmi_ready_event { __le32 sw_version; __le32 abi_version; u8 mac[WMI_MAC_LEN]; - u8 phy_capability; /* enum wmi_phy_capability */ + /* enum wmi_phy_capability */ + u8 phy_capability; u8 numof_additional_mids; } __packed; -/* - * WMI_NOTIFY_REQ_DONE_EVENTID - */ +/* WMI_NOTIFY_REQ_DONE_EVENTID */ struct wmi_notify_req_done_event { - __le32 status; /* beamforming status, 0: fail; 1: OK; 2: retrying */ + /* beamforming status, 0: fail; 1: OK; 2: retrying */ + __le32 status; __le64 tsf; __le32 snr_val; __le32 tx_tpt; @@ -1067,9 +1002,7 @@ struct wmi_notify_req_done_event { u8 reserved[3]; } __packed; -/* - * WMI_CONNECT_EVENTID - */ +/* WMI_CONNECT_EVENTID */ struct wmi_connect_event { u8 channel; u8 reserved0; @@ -1083,68 +1016,103 @@ struct wmi_connect_event { u8 assoc_resp_len; u8 cid; u8 reserved2[3]; + /* not in use */ u8 assoc_info[0]; } __packed; -/* - * WMI_DISCONNECT_EVENTID - */ +/* WMI_DISCONNECT_EVENTID */ enum wmi_disconnect_reason { - WMI_DIS_REASON_NO_NETWORK_AVAIL = 1, - WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */ - WMI_DIS_REASON_DISCONNECT_CMD = 3, - WMI_DIS_REASON_BSS_DISCONNECTED = 4, - WMI_DIS_REASON_AUTH_FAILED = 5, - WMI_DIS_REASON_ASSOC_FAILED = 6, - WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7, - WMI_DIS_REASON_CSERV_DISCONNECT = 8, - WMI_DIS_REASON_INVALID_PROFILE = 10, - WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11, - WMI_DIS_REASON_PROFILE_MISMATCH = 12, - WMI_DIS_REASON_CONNECTION_EVICTED = 13, - WMI_DIS_REASON_IBSS_MERGE = 14, + WMI_DIS_REASON_NO_NETWORK_AVAIL = 0x01, + /* bmiss */ + WMI_DIS_REASON_LOST_LINK = 0x02, + WMI_DIS_REASON_DISCONNECT_CMD = 0x03, + WMI_DIS_REASON_BSS_DISCONNECTED = 0x04, + WMI_DIS_REASON_AUTH_FAILED = 0x05, + WMI_DIS_REASON_ASSOC_FAILED = 0x06, + WMI_DIS_REASON_NO_RESOURCES_AVAIL = 0x07, + WMI_DIS_REASON_CSERV_DISCONNECT = 0x08, + WMI_DIS_REASON_INVALID_PROFILE = 0x0A, + WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 0x0B, + WMI_DIS_REASON_PROFILE_MISMATCH = 0x0C, + WMI_DIS_REASON_CONNECTION_EVICTED = 0x0D, + WMI_DIS_REASON_IBSS_MERGE = 0x0E, }; struct wmi_disconnect_event { - __le16 protocol_reason_status; /* reason code, see 802.11 spec. */ - u8 bssid[WMI_MAC_LEN]; /* set if known */ - u8 disconnect_reason; /* see wmi_disconnect_reason */ - u8 assoc_resp_len; /* not used */ - u8 assoc_info[0]; /* not used */ + /* reason code, see 802.11 spec. */ + __le16 protocol_reason_status; + /* set if known */ + u8 bssid[WMI_MAC_LEN]; + /* see enum wmi_disconnect_reason */ + u8 disconnect_reason; + /* last assoc req may passed to host - not in used */ + u8 assoc_resp_len; + /* last assoc req may passed to host - not in used */ + u8 assoc_info[0]; } __packed; -/* - * WMI_SCAN_COMPLETE_EVENTID - */ +/* WMI_SCAN_COMPLETE_EVENTID */ enum scan_status { - WMI_SCAN_SUCCESS = 0, - WMI_SCAN_FAILED = 1, - WMI_SCAN_ABORTED = 2, - WMI_SCAN_REJECTED = 3, + WMI_SCAN_SUCCESS = 0x00, + WMI_SCAN_FAILED = 0x01, + WMI_SCAN_ABORTED = 0x02, + WMI_SCAN_REJECTED = 0x03, + WMI_SCAN_ABORT_REJECTED = 0x04, }; struct wmi_scan_complete_event { - __le32 status; /* scan_status */ + /* enum scan_status */ + __le32 status; } __packed; -/* - * WMI_BA_STATUS_EVENTID - */ +/* WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT */ +enum wmi_acs_info_bitmask { + WMI_ACS_INFO_BITMASK_BEACON_FOUND = 0x01, + WMI_ACS_INFO_BITMASK_BUSY_TIME = 0x02, + WMI_ACS_INFO_BITMASK_TX_TIME = 0x04, + WMI_ACS_INFO_BITMASK_RX_TIME = 0x08, + WMI_ACS_INFO_BITMASK_NOISE = 0x10, +}; + +struct scan_acs_info { + u8 channel; + u8 beacon_found; + /* msec */ + __le16 busy_time; + __le16 tx_time; + __le16 rx_time; + u8 noise; + u8 reserved[3]; +} __packed; + +struct wmi_acs_passive_scan_complete_event { + __le32 dwell_time; + /* valid fields within channel info according to + * their appearance in struct order + */ + __le16 filled; + u8 num_scanned_channels; + u8 reserved; + struct scan_acs_info scan_info_list[0]; +} __packed; + +/* WMI_BA_STATUS_EVENTID */ enum wmi_vring_ba_status { - WMI_BA_AGREED = 0, - WMI_BA_NON_AGREED = 1, + WMI_BA_AGREED = 0x00, + WMI_BA_NON_AGREED = 0x01, /* BA_EN in middle of teardown flow */ - WMI_BA_TD_WIP = 2, + WMI_BA_TD_WIP = 0x02, /* BA_DIS or BA_EN in middle of BA SETUP flow */ - WMI_BA_SETUP_WIP = 3, + WMI_BA_SETUP_WIP = 0x03, /* BA_EN when the BA session is already active */ - WMI_BA_SESSION_ACTIVE = 4, + WMI_BA_SESSION_ACTIVE = 0x04, /* BA_DIS when the BA session is not active */ - WMI_BA_SESSION_NOT_ACTIVE = 5, + WMI_BA_SESSION_NOT_ACTIVE = 0x05, }; -struct wmi_vring_ba_status_event { - __le16 status; /* enum wmi_vring_ba_status */ +struct wmi_ba_status_event { + /* enum wmi_vring_ba_status */ + __le16 status; u8 reserved[2]; u8 ringid; u8 agg_wsize; @@ -1152,18 +1120,14 @@ struct wmi_vring_ba_status_event { u8 amsdu; } __packed; -/* - * WMI_DELBA_EVENTID - */ +/* WMI_DELBA_EVENTID */ struct wmi_delba_event { u8 cidxtid; u8 from_initiator; __le16 reason; } __packed; -/* - * WMI_VRING_CFG_DONE_EVENTID - */ +/* WMI_VRING_CFG_DONE_EVENTID */ struct wmi_vring_cfg_done_event { u8 ringid; u8 status; @@ -1171,174 +1135,151 @@ struct wmi_vring_cfg_done_event { __le32 tx_vring_tail_ptr; } __packed; -/* - * WMI_RCP_ADDBA_RESP_SENT_EVENTID - */ +/* WMI_RCP_ADDBA_RESP_SENT_EVENTID */ struct wmi_rcp_addba_resp_sent_event { u8 cidxtid; u8 reserved; __le16 status; } __packed; -/* - * WMI_RCP_ADDBA_REQ_EVENTID - */ +/* WMI_RCP_ADDBA_REQ_EVENTID */ struct wmi_rcp_addba_req_event { u8 cidxtid; u8 dialog_token; - __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ + /* ieee80211_ba_parameterset as it received */ + __le16 ba_param_set; __le16 ba_timeout; - __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */ + /* ieee80211_ba_seqstrl field as it received */ + __le16 ba_seq_ctrl; } __packed; -/* - * WMI_CFG_RX_CHAIN_DONE_EVENTID - */ +/* WMI_CFG_RX_CHAIN_DONE_EVENTID */ enum wmi_cfg_rx_chain_done_event_status { - WMI_CFG_RX_CHAIN_SUCCESS = 1, + WMI_CFG_RX_CHAIN_SUCCESS = 0x01, }; struct wmi_cfg_rx_chain_done_event { - __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */ + /* V-Ring Tail pointer */ + __le32 rx_ring_tail_ptr; __le32 status; } __packed; -/* - * WMI_WBE_LINK_DOWN_EVENTID - */ +/* WMI_WBE_LINK_DOWN_EVENTID */ enum wmi_wbe_link_down_event_reason { - WMI_WBE_REASON_USER_REQUEST = 0, - WMI_WBE_REASON_RX_DISASSOC = 1, - WMI_WBE_REASON_BAD_PHY_LINK = 2, + WMI_WBE_REASON_USER_REQUEST = 0x00, + WMI_WBE_REASON_RX_DISASSOC = 0x01, + WMI_WBE_REASON_BAD_PHY_LINK = 0x02, }; +/* WMI_WBE_LINK_DOWN_EVENTID */ struct wmi_wbe_link_down_event { u8 cid; u8 reserved[3]; __le32 reason; } __packed; -/* - * WMI_DATA_PORT_OPEN_EVENTID - */ +/* WMI_DATA_PORT_OPEN_EVENTID */ struct wmi_data_port_open_event { u8 cid; u8 reserved[3]; } __packed; -/* - * WMI_VRING_EN_EVENTID - */ +/* WMI_VRING_EN_EVENTID */ struct wmi_vring_en_event { u8 vring_index; u8 reserved[3]; } __packed; -/* - * WMI_GET_PCP_CHANNEL_EVENTID - */ +/* WMI_GET_PCP_CHANNEL_EVENTID */ struct wmi_get_pcp_channel_event { u8 channel; u8 reserved[3]; } __packed; -/* - * WMI_P2P_CFG_DONE_EVENTID - */ +/* WMI_P2P_CFG_DONE_EVENTID */ struct wmi_p2p_cfg_done_event { - u8 status; /* wmi_fw_status */ + /* wmi_fw_status */ + u8 status; u8 reserved[3]; } __packed; -/* -* WMI_PORT_ALLOCATED_EVENTID -*/ +/* WMI_PORT_ALLOCATED_EVENTID */ struct wmi_port_allocated_event { - u8 status; /* wmi_fw_status */ + /* wmi_fw_status */ + u8 status; u8 reserved[3]; } __packed; -/* -* WMI_PORT_DELETED_EVENTID -*/ +/* WMI_PORT_DELETED_EVENTID */ struct wmi_port_deleted_event { - u8 status; /* wmi_fw_status */ + /* wmi_fw_status */ + u8 status; u8 reserved[3]; } __packed; -/* - * WMI_LISTEN_STARTED_EVENTID - */ +/* WMI_LISTEN_STARTED_EVENTID */ struct wmi_listen_started_event { - u8 status; /* wmi_fw_status */ + /* wmi_fw_status */ + u8 status; u8 reserved[3]; } __packed; -/* - * WMI_SEARCH_STARTED_EVENTID - */ +/* WMI_SEARCH_STARTED_EVENTID */ struct wmi_search_started_event { - u8 status; /* wmi_fw_status */ + /* wmi_fw_status */ + u8 status; u8 reserved[3]; } __packed; -/* - * WMI_PCP_STARTED_EVENTID - */ +/* WMI_PCP_STARTED_EVENTID */ struct wmi_pcp_started_event { - u8 status; /* wmi_fw_status */ + /* wmi_fw_status */ + u8 status; u8 reserved[3]; } __packed; -/* - * WMI_PCP_FACTOR_EVENTID - */ +/* WMI_PCP_FACTOR_EVENTID */ struct wmi_pcp_factor_event { __le32 pcp_factor; } __packed; -/* - * WMI_SW_TX_COMPLETE_EVENTID - */ enum wmi_sw_tx_status { - WMI_TX_SW_STATUS_SUCCESS = 0, - WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1, - WMI_TX_SW_STATUS_FAILED_TX = 2, + WMI_TX_SW_STATUS_SUCCESS = 0x00, + WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 0x01, + WMI_TX_SW_STATUS_FAILED_TX = 0x02, }; +/* WMI_SW_TX_COMPLETE_EVENTID */ struct wmi_sw_tx_complete_event { - u8 status; /* enum wmi_sw_tx_status */ + /* enum wmi_sw_tx_status */ + u8 status; u8 reserved[3]; } __packed; -/* - * WMI_CORR_MEASURE_EVENTID - */ +/* WMI_CORR_MEASURE_EVENTID */ struct wmi_corr_measure_event { - s32 i; - s32 q; - s32 image_i; - s32 image_q; + /* signed */ + __le32 i; + /* signed */ + __le32 q; + /* signed */ + __le32 image_i; + /* signed */ + __le32 image_q; } __packed; -/* - * WMI_READ_RSSI_EVENTID - */ +/* WMI_READ_RSSI_EVENTID */ struct wmi_read_rssi_event { __le32 ina_rssi_adc_dbm; } __packed; -/* - * WMI_GET_SSID_EVENTID - */ +/* WMI_GET_SSID_EVENTID */ struct wmi_get_ssid_event { __le32 ssid_len; u8 ssid[WMI_MAX_SSID_LEN]; } __packed; -/* - * WMI_RX_MGMT_PACKET_EVENTID - */ +/* wmi_rx_mgmt_info */ struct wmi_rx_mgmt_info { u8 mcs; s8 snr; @@ -1347,39 +1288,65 @@ struct wmi_rx_mgmt_info { __le16 stype; __le16 status; __le32 len; + /* Not resolved when == 0xFFFFFFFF ==> Broadcast to all MIDS */ u8 qid; + /* Not resolved when == 0xFFFFFFFF ==> Broadcast to all MIDS */ u8 mid; u8 cid; - u8 channel; /* From Radio MNGR */ + /* From Radio MNGR */ + u8 channel; } __packed; -/* - * WMI_TX_MGMT_PACKET_EVENTID - */ +/* wmi_otp_read_write_cmd */ +struct wmi_otp_read_write_cmd { + __le32 addr; + __le32 size; + u8 values[0]; +} __packed; + +/* WMI_OTP_READ_RESULT_EVENTID */ +struct wmi_otp_read_result_event { + u8 payload[0]; +} __packed; + +/* WMI_TX_MGMT_PACKET_EVENTID */ struct wmi_tx_mgmt_packet_event { u8 payload[0]; } __packed; +/* WMI_RX_MGMT_PACKET_EVENTID */ struct wmi_rx_mgmt_packet_event { struct wmi_rx_mgmt_info info; u8 payload[0]; } __packed; -/* - * WMI_ECHO_RSP_EVENTID - */ -struct wmi_echo_event { +/* WMI_ECHO_RSP_EVENTID */ +struct wmi_echo_rsp_event { __le32 echoed_value; } __packed; -/* - * WMI_TEMP_SENSE_DONE_EVENTID +/* WMI_TEMP_SENSE_DONE_EVENTID * * Measure MAC and radio temperatures */ struct wmi_temp_sense_done_event { + /* Temperature times 1000 (actual temperature will be achieved by + * dividing the value by 1000) + */ __le32 baseband_t1000; + /* Temperature times 1000 (actual temperature will be achieved by + * dividing the value by 1000) + */ __le32 rf_t1000; } __packed; +#define WMI_SCAN_DWELL_TIME_MS (100) +#define WMI_SURVEY_TIMEOUT_MS (10000) + +enum wmi_hidden_ssid { + WMI_HIDDEN_SSID_DISABLED = 0x00, + WMI_HIDDEN_SSID_SEND_EMPTY = 0x10, + WMI_HIDDEN_SSID_CLEAR = 0xFE, +}; + #endif /* __WILOCITY_WMI_H__ */ -- GitLab From eabb03b4a37cc7945ca62453402c74a0622e5a05 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:10 +0200 Subject: [PATCH 0034/9938] wil6210: basic PBSS/PCP support PBSS (Personal Basic Service Set) is a new BSS type for DMG networks. It is similar to infrastructure BSS, having an AP-like entity called PCP (PBSS Control Point), but it has few differences. For example, stations inside a PBSS can communicate directly, and the PCP role can be transferred between stations. This change adds PBSS support, and has 2 main parts: 1. When starting an AP, add an option to start as a PCP instead. This is implemented by a new PBSS flag which is passed as part of the cfg80211_ap_settings structure. 2. When connecting to a BSS, add an option to connect to a PCP instead of an AP. This is again implemented by a new PBSS flag, added to the cfg80211_connect_params structure. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 27 +++++++++++---------- drivers/net/wireless/ath/wil6210/wil6210.h | 2 ++ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 0c25e8beec3c..4a95e1c8bc22 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -402,6 +402,7 @@ static void wil_print_connect_params(struct wil6210_priv *wil, print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, 16, 1, sme->ssid, sme->ssid_len, true); wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); + wil_info(wil, " PBSS: %d\n", sme->pbss); wil_print_crypto(wil, &sme->crypto); } @@ -416,6 +417,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, const u8 *rsn_eid; int ch; int rc = 0; + enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; wil_print_connect_params(wil, sme); @@ -434,14 +436,12 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, if (sme->privacy && !rsn_eid) wil_info(wil, "WSC connection\n"); - if (sme->pbss) { - wil_err(wil, "connect - PBSS not yet supported\n"); - return -EOPNOTSUPP; - } + if (sme->pbss) + bss_type = IEEE80211_BSS_TYPE_PBSS; bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, sme->ssid_len, - IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); + bss_type, IEEE80211_PRIVACY_ANY); if (!bss) { wil_err(wil, "Unable to find BSS\n"); return -ENOENT; @@ -936,13 +936,16 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, const u8 *ssid, size_t ssid_len, u32 privacy, int bi, u8 chan, struct cfg80211_beacon_data *bcon, - u8 hidden_ssid) + u8 hidden_ssid, u32 pbss) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; struct wireless_dev *wdev = ndev->ieee80211_ptr; u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); + if (pbss) + wmi_nettype = WMI_NETTYPE_P2P; + wil_set_recovery_state(wil, fw_recovery_idle); mutex_lock(&wil->mutex); @@ -963,6 +966,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, wil->privacy = privacy; wil->channel = chan; wil->hidden_ssid = hidden_ssid; + wil->pbss = pbss; netif_carrier_on(ndev); @@ -1012,7 +1016,8 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, wdev->ssid_len, privacy, wdev->beacon_interval, wil->channel, bcon, - wil->hidden_ssid); + wil->hidden_ssid, + wil->pbss); } else { rc = _wil_cfg80211_set_ies(wiphy, bcon); } @@ -1038,11 +1043,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, return -EINVAL; } - if (info->pbss) { - wil_err(wil, "AP: PBSS not yet supported\n"); - return -EOPNOTSUPP; - } - switch (info->hidden_ssid) { case NL80211_HIDDEN_SSID_NOT_IN_USE: hidden_ssid = WMI_HIDDEN_SSID_DISABLED; @@ -1068,6 +1068,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, info->hidden_ssid); wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval, info->dtim_period); + wil_dbg_misc(wil, "PBSS %d\n", info->pbss); print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, info->ssid, info->ssid_len); wil_print_bcon_data(bcon); @@ -1076,7 +1077,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, rc = _wil_cfg80211_start_ap(wiphy, ndev, info->ssid, info->ssid_len, info->privacy, info->beacon_interval, channel->hw_value, - bcon, hidden_ssid); + bcon, hidden_ssid, info->pbss); return rc; } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index e69df0c1a125..69d970a74aae 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -604,6 +604,8 @@ struct wil6210_priv { struct wil_platform_ops platform_ops; struct pmc_ctx pmc; + + bool pbss; }; #define wil_to_wiphy(i) (i->wdev->wiphy) -- GitLab From 5f0823ef8b76f446ab8b187fabfb4e7560bc33a1 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 1 Mar 2016 19:18:11 +0200 Subject: [PATCH 0035/9938] wil6210: add support for platform specific notification events Add the ability to notify the platform driver on different events, such as FW crash, pre reset and FW ready. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/interrupt.c | 5 +-- drivers/net/wireless/ath/wil6210/main.c | 32 +++++++++++++++++-- .../net/wireless/ath/wil6210/wil_platform.h | 8 ++++- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 4f2ffa5c6e17..ae902958bf55 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -394,9 +394,10 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) wil_fw_core_dump(wil); wil_notify_fw_error(wil); isr &= ~ISR_MISC_FW_ERROR; - if (wil->platform_ops.notify_crash) { + if (wil->platform_ops.notify) { wil_err(wil, "notify platform driver about FW crash"); - wil->platform_ops.notify_crash(wil->platform_handle); + wil->platform_ops.notify(wil->platform_handle, + WIL_PLATFORM_EVT_FW_CRASH); } else { wil_fw_error_recovery(wil); } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 1fa215d0eeed..1472978dd3f0 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -764,6 +764,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (wil->hw_version == HW_VER_UNKNOWN) return -ENODEV; + if (wil->platform_ops.notify) { + rc = wil->platform_ops.notify(wil->platform_handle, + WIL_PLATFORM_EVT_PRE_RESET); + if (rc) + wil_err(wil, + "%s: PRE_RESET platform notify failed, rc %d\n", + __func__, rc); + } + set_bit(wil_status_resetting, wil->status); cancel_work_sync(&wil->disconnect_worker); @@ -843,8 +852,27 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) /* we just started MAC, wait for FW ready */ rc = wil_wait_for_fw_ready(wil); - if (rc == 0) /* check FW is responsive */ - rc = wmi_echo(wil); + if (rc) + return rc; + + /* check FW is responsive */ + rc = wmi_echo(wil); + if (rc) { + wil_err(wil, "%s: wmi_echo failed, rc %d\n", + __func__, rc); + return rc; + } + + if (wil->platform_ops.notify) { + rc = wil->platform_ops.notify(wil->platform_handle, + WIL_PLATFORM_EVT_FW_RDY); + if (rc) { + wil_err(wil, + "%s: FW_RDY notify failed, rc %d\n", + __func__, rc); + rc = 0; + } + } } return rc; diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h index 9a949d910343..33d4a34b3b1c 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.h +++ b/drivers/net/wireless/ath/wil6210/wil_platform.h @@ -19,6 +19,12 @@ struct device; +enum wil_platform_event { + WIL_PLATFORM_EVT_FW_CRASH = 0, + WIL_PLATFORM_EVT_PRE_RESET = 1, + WIL_PLATFORM_EVT_FW_RDY = 2, +}; + /** * struct wil_platform_ops - wil platform module calls from this * driver to platform driver @@ -28,7 +34,7 @@ struct wil_platform_ops { int (*suspend)(void *handle); int (*resume)(void *handle); void (*uninit)(void *handle); - int (*notify_crash)(void *handle); + int (*notify)(void *handle, enum wil_platform_event evt); }; /** -- GitLab From e6d68341e7286386451adf14cebb635a52b0effe Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Tue, 1 Mar 2016 19:18:12 +0200 Subject: [PATCH 0036/9938] wil6210: p2p initial support supporting p2p_find, p2p_listen and p2p_connect Use updated cfg80211_get_bss API (additional argument) Signed-off-by: Dedy Lansky Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/Makefile | 1 + drivers/net/wireless/ath/wil6210/cfg80211.c | 67 ++++-- drivers/net/wireless/ath/wil6210/main.c | 6 + drivers/net/wireless/ath/wil6210/p2p.c | 220 ++++++++++++++++++++ drivers/net/wireless/ath/wil6210/wil6210.h | 31 ++- drivers/net/wireless/ath/wil6210/wmi.c | 80 ++++++- 6 files changed, 389 insertions(+), 16 deletions(-) create mode 100644 drivers/net/wireless/ath/wil6210/p2p.c diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index fdf63d5fe82b..11b544b26c74 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile @@ -18,6 +18,7 @@ wil6210-$(CONFIG_WIL6210_TRACING) += trace.o wil6210-y += wil_platform.o wil6210-y += ethtool.o wil6210-y += wil_crash_dump.o +wil6210-y += p2p.o # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 4a95e1c8bc22..80e1482f480d 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -18,6 +18,8 @@ #include "wil6210.h" #include "wmi.h" +#define WIL_MAX_ROC_DURATION_MS 5000 + #define CHAN60G(_channel, _flags) { \ .band = IEEE80211_BAND_60GHZ, \ .center_freq = 56160 + (2160 * (_channel)), \ @@ -239,6 +241,20 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); struct wireless_dev *wdev = wil->wdev; + int rc; + + wil_dbg_misc(wil, "%s() type=%d\n", __func__, type); + + if (netif_running(wil_to_ndev(wil))) { + wil_dbg_misc(wil, "interface is up. resetting...\n"); + mutex_lock(&wil->mutex); + __wil_down(wil); + rc = __wil_up(wil); + mutex_unlock(&wil->mutex); + + if (rc) + return rc; + } switch (type) { case NL80211_IFTYPE_STATION: @@ -274,6 +290,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, uint i, n; int rc; + wil_dbg_misc(wil, "%s()\n", __func__); + if (wil->scan_request) { wil_err(wil, "Already scanning\n"); return -EAGAIN; @@ -294,6 +312,14 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } + /* check if scan request is a P2P search request */ + if (wil_scan_is_p2p_search(wil, request)) { + wil->scan_request = request; + return wil_p2p_search(wil, request); + } + + wil_p2p_stop_discovery(wil); + wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); wil_dbg_misc(wil, "SSID count: %d", request->n_ssids); @@ -419,6 +445,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, int rc = 0; enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; + wil_dbg_misc(wil, "%s()\n", __func__); wil_print_connect_params(wil, sme); if (test_bit(wil_status_fwconnecting, wil->status) || @@ -584,6 +611,16 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct wmi_sw_tx_complete_event evt; } __packed evt; + /* Note, currently we do not support the "wait" parameter, user-space + * must call remain_on_channel before mgmt_tx or listen on a channel + * another way (AP/PCP or connected station) + * in addition we need to check if specified "chan" argument is + * different from currently "listened" channel and fail if it is. + */ + + wil_dbg_misc(wil, "%s()\n", __func__); + print_hex_dump_bytes("mgmt tx frame ", DUMP_PREFIX_OFFSET, buf, len); + cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL); if (!cmd) { rc = -ENOMEM; @@ -628,9 +665,11 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, } else { switch (wdev->iftype) { case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: rc = WMI_KEY_USE_RX_GROUP; break; case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: rc = WMI_KEY_USE_TX_GROUP; break; default: @@ -770,16 +809,17 @@ static int wil_remain_on_channel(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; - /* TODO: handle duration */ - wil_info(wil, "%s(%d, %d ms)\n", __func__, chan->center_freq, duration); + wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d\n", __func__, + chan->center_freq, duration); - rc = wmi_set_channel(wil, chan->hw_value); + rc = wil_p2p_listen(wil, duration, chan, cookie); if (rc) return rc; - rc = wmi_rxon(wil, true); + cfg80211_ready_on_channel(wil->wdev, *cookie, chan, duration, + GFP_KERNEL); - return rc; + return 0; } static int wil_cancel_remain_on_channel(struct wiphy *wiphy, @@ -787,13 +827,12 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, u64 cookie) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - int rc; - wil_info(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "%s()\n", __func__); - rc = wmi_rxon(wil, false); + wil_p2p_cancel_listen(wil, cookie); - return rc; + return 0; } /** @@ -1251,14 +1290,18 @@ static void wil_wiphy_init(struct wiphy *wiphy) { wiphy->max_scan_ssids = 1; wiphy->max_scan_ie_len = WMI_MAX_IE_LEN; + wiphy->max_remain_on_channel_duration = WIL_MAX_ROC_DURATION_MS; wiphy->max_num_pmkids = 0 /* TODO: */; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | + /* enable this when supporting multi vif + * BIT(NL80211_IFTYPE_P2P_DEVICE) | + */ BIT(NL80211_IFTYPE_MONITOR); - /* TODO: enable P2P when integrated with supplicant: - * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) - */ wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", __func__, wiphy->flags); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 1472978dd3f0..025751e223c2 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -453,6 +453,8 @@ int wil_priv_init(struct wil6210_priv *wil) wil->bcast_vring = -1; setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); + setup_timer(&wil->p2p.discovery_timer, wil_p2p_discovery_timer_fn, + (ulong)wil); INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); @@ -513,8 +515,10 @@ void wil_priv_deinit(struct wil6210_priv *wil) wil_set_recovery_state(wil, fw_recovery_idle); del_timer_sync(&wil->scan_timer); + del_timer_sync(&wil->p2p.discovery_timer); cancel_work_sync(&wil->disconnect_worker); cancel_work_sync(&wil->fw_error_worker); + cancel_work_sync(&wil->p2p.discovery_expired_work); mutex_lock(&wil->mutex); wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); mutex_unlock(&wil->mutex); @@ -979,6 +983,8 @@ int __wil_down(struct wil6210_priv *wil) } wil_enable_irq(wil); + wil_p2p_stop_discovery(wil); + if (wil->scan_request) { wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request); diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c new file mode 100644 index 000000000000..974bf84dbf52 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "wil6210.h" +#include "wmi.h" + +#define P2P_WILDCARD_SSID "DIRECT-" +#define P2P_DMG_SOCIAL_CHANNEL 2 +#define P2P_SEARCH_DURATION_MS 500 +#define P2P_DEFAULT_BI 100 + +int wil_scan_is_p2p_search(struct wil6210_priv *wil, + struct cfg80211_scan_request *request) +{ + /* need P2P_DEVICE changes to make this work */ + return 0; +} + +void wil_p2p_discovery_timer_fn(ulong x) +{ + struct wil6210_priv *wil = (void *)x; + + wil_dbg_misc(wil, "%s\n", __func__); + + schedule_work(&wil->p2p.discovery_expired_work); +} + +int wil_p2p_search(struct wil6210_priv *wil, + struct cfg80211_scan_request *request) +{ + int rc; + struct wil_p2p_info *p2p = &wil->p2p; + + wil_dbg_misc(wil, "%s: channel %d\n", + __func__, P2P_DMG_SOCIAL_CHANNEL); + + mutex_lock(&wil->mutex); + + if (p2p->discovery_started) { + wil_err(wil, "%s: search failed. discovery already ongoing\n", + __func__); + rc = -EBUSY; + goto out; + } + + rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI); + if (rc) { + wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__); + goto out; + } + + rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); + if (rc) { + wil_err(wil, "%s: wmi_set_ssid failed\n", __func__); + goto out_stop; + } + + /* Set application IE to probe request and probe response */ + rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, + request->ie_len, request->ie); + if (rc) { + wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n", + __func__); + goto out_stop; + } + + /* supplicant doesn't provide Probe Response IEs. As a workaround - + * re-use Probe Request IEs + */ + rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, + request->ie_len, request->ie); + if (rc) { + wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n", + __func__); + goto out_stop; + } + + rc = wmi_start_search(wil); + if (rc) { + wil_err(wil, "%s: wmi_start_search failed\n", __func__); + goto out_stop; + } + + p2p->discovery_started = 1; + INIT_WORK(&p2p->discovery_expired_work, wil_p2p_search_expired); + mod_timer(&p2p->discovery_timer, + jiffies + msecs_to_jiffies(P2P_SEARCH_DURATION_MS)); + +out_stop: + if (rc) + wmi_stop_discovery(wil); + +out: + mutex_unlock(&wil->mutex); + return rc; +} + +int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, + struct ieee80211_channel *chan, u64 *cookie) +{ + struct wil_p2p_info *p2p = &wil->p2p; + u8 channel = P2P_DMG_SOCIAL_CHANNEL; + int rc; + + if (chan) + channel = chan->hw_value; + + wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration); + + mutex_lock(&wil->mutex); + + if (p2p->discovery_started) { + wil_err(wil, "%s: discovery already ongoing\n", __func__); + rc = -EBUSY; + goto out; + } + + rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI); + if (rc) { + wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__); + goto out; + } + + rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); + if (rc) { + wil_err(wil, "%s: wmi_set_ssid failed\n", __func__); + goto out_stop; + } + + rc = wmi_start_listen(wil); + if (rc) { + wil_err(wil, "%s: wmi_start_listen failed\n", __func__); + goto out_stop; + } + + memcpy(&p2p->listen_chan, chan, sizeof(*chan)); + *cookie = ++p2p->cookie; + + p2p->discovery_started = 1; + INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired); + mod_timer(&p2p->discovery_timer, + jiffies + msecs_to_jiffies(duration)); + +out_stop: + if (rc) + wmi_stop_discovery(wil); + +out: + mutex_unlock(&wil->mutex); + return rc; +} + +void wil_p2p_stop_discovery(struct wil6210_priv *wil) +{ + struct wil_p2p_info *p2p = &wil->p2p; + + if (p2p->discovery_started) { + del_timer_sync(&p2p->discovery_timer); + p2p->discovery_started = 0; + wmi_stop_discovery(wil); + } +} + +void wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) +{ + struct wil_p2p_info *p2p = &wil->p2p; + + if (cookie != p2p->cookie) + wil_info(wil, "%s: Cookie mismatch: 0x%016llx vs. 0x%016llx\n", + __func__, p2p->cookie, cookie); + + wil_p2p_stop_discovery(wil); + cfg80211_remain_on_channel_expired(wil->wdev, + p2p->cookie, + &p2p->listen_chan, + GFP_KERNEL); +} + +void wil_p2p_listen_expired(struct work_struct *work) +{ + struct wil_p2p_info *p2p = container_of(work, + struct wil_p2p_info, discovery_expired_work); + struct wil6210_priv *wil = container_of(p2p, + struct wil6210_priv, p2p); + + wil_dbg_misc(wil, "%s()\n", __func__); + + wil_p2p_stop_discovery(wil); + cfg80211_remain_on_channel_expired(wil->wdev, + p2p->cookie, + &p2p->listen_chan, + GFP_KERNEL); +} + +void wil_p2p_search_expired(struct work_struct *work) +{ + struct wil_p2p_info *p2p = container_of(work, + struct wil_p2p_info, discovery_expired_work); + struct wil6210_priv *wil = container_of(p2p, + struct wil6210_priv, p2p); + + wil_dbg_misc(wil, "%s()\n", __func__); + + wil_p2p_stop_discovery(wil); + cfg80211_scan_done(wil->scan_request, 0); + wil->scan_request = NULL; +} diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 69d970a74aae..0aba86c6b05e 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -453,6 +453,14 @@ struct wil_tid_crypto_rx { struct wil_tid_crypto_rx_single key_id[4]; }; +struct wil_p2p_info { + struct ieee80211_channel listen_chan; + u8 discovery_started; + u64 cookie; + struct timer_list discovery_timer; /* listen/search duration */ + struct work_struct discovery_expired_work; /* listen/search expire */ +}; + enum wil_sta_status { wil_sta_unused = 0, wil_sta_conn_pending = 1, @@ -606,6 +614,8 @@ struct wil6210_priv { struct pmc_ctx pmc; bool pbss; + + struct wil_p2p_info p2p; }; #define wil_to_wiphy(i) (i->wdev->wiphy) @@ -731,7 +741,6 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, int wmi_echo(struct wil6210_priv *wil); int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); -int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); int wmi_rxon(struct wil6210_priv *wil, bool on); int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, @@ -754,6 +763,26 @@ void wil_unmask_irq(struct wil6210_priv *wil); void wil_configure_interrupt_moderation(struct wil6210_priv *wil); void wil_disable_irq(struct wil6210_priv *wil); void wil_enable_irq(struct wil6210_priv *wil); + +/* P2P */ +int wil_scan_is_p2p_search(struct wil6210_priv *wil, + struct cfg80211_scan_request *request); +void wil_p2p_discovery_timer_fn(ulong x); +int wil_p2p_search(struct wil6210_priv *wil, + struct cfg80211_scan_request *request); +int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, + struct ieee80211_channel *chan, u64 *cookie); +void wil_p2p_stop_discovery(struct wil6210_priv *wil); +void wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); +void wil_p2p_listen_expired(struct work_struct *work); +void wil_p2p_search_expired(struct work_struct *work); + +/* WMI for P2P */ +int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi); +int wmi_start_listen(struct wil6210_priv *wil); +int wmi_start_search(struct wil6210_priv *wil); +int wmi_stop_discovery(struct wil6210_priv *wil); + int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_mgmt_tx_params *params, u64 *cookie); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index db7d2b602d1a..4a1cdd256ef2 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -368,6 +368,8 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf, ie_len, true); + wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap); + bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame, d_len, signal, GFP_KERNEL); if (bss) { @@ -1072,14 +1074,86 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) return 0; } -int wmi_p2p_cfg(struct wil6210_priv *wil, int channel) +int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi) { + int rc; struct wmi_p2p_cfg_cmd cmd = { - .discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD, + .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER, + .bcon_interval = cpu_to_le16(bi), .channel = channel - 1, }; + struct { + struct wmi_cmd_hdr wmi; + struct wmi_p2p_cfg_done_event evt; + } __packed reply; + + wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n"); + + rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd), + WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300); + if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { + wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status); + rc = -EINVAL; + } + + return rc; +} + +int wmi_start_listen(struct wil6210_priv *wil) +{ + int rc; + struct { + struct wmi_cmd_hdr wmi; + struct wmi_listen_started_event evt; + } __packed reply; + + wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n"); + + rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0, + WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300); + if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { + wil_err(wil, "device failed to start listen. status %d\n", + reply.evt.status); + rc = -EINVAL; + } - return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd)); + return rc; +} + +int wmi_start_search(struct wil6210_priv *wil) +{ + int rc; + struct { + struct wmi_cmd_hdr wmi; + struct wmi_search_started_event evt; + } __packed reply; + + wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n"); + + rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0, + WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300); + if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { + wil_err(wil, "device failed to start search. status %d\n", + reply.evt.status); + rc = -EINVAL; + } + + return rc; +} + +int wmi_stop_discovery(struct wil6210_priv *wil) +{ + int rc; + + wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n"); + + rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0, + WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100); + + if (rc) + wil_err(wil, "Failed to stop discovery\n"); + + return rc; } int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, -- GitLab From 4332cac17b5c0cb80d8b99fda33a0faad3238b0e Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:13 +0200 Subject: [PATCH 0037/9938] wil6210: P2P_DEVICE virtual interface support Added support for the P2P_DEVICE virtual interface. This interface is intended for P2P management operations such as discovery and GO negotiation. Normally it is implemented by drivers to allow a separate interface for P2P management with its own MAC address, but for 11ad drivers it is needed to support P2P search, since it cannot otherwise be separated from normal scan. Since we only support a single interface/MAC address, we can't easily separate between primary and P2P_DEVICE interfaces. For example when a management packet arrives we can't tell for which interface it is intended. To work around this, we store a pointer to the interface where the last "radio operation" was triggered such as scan or remain on channel, and we forward management packets and scan results to this interface. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 136 ++++++++++++++++++-- drivers/net/wireless/ath/wil6210/main.c | 1 + drivers/net/wireless/ath/wil6210/netdev.c | 1 + drivers/net/wireless/ath/wil6210/p2p.c | 24 ++-- drivers/net/wireless/ath/wil6210/pcie_bus.c | 1 + drivers/net/wireless/ath/wil6210/wil6210.h | 8 +- drivers/net/wireless/ath/wil6210/wmi.c | 7 +- 7 files changed, 152 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 80e1482f480d..24f9829c8222 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -78,6 +78,12 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) }, + [NL80211_IFTYPE_P2P_DEVICE] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, }; static const u32 wil_cipher_suites[] = { @@ -234,13 +240,68 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy, return rc; } +static struct wireless_dev * +wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, struct vif_params *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct net_device *ndev = wil_to_ndev(wil); + struct wireless_dev *p2p_wdev; + + wil_dbg_misc(wil, "%s()\n", __func__); + + if (type != NL80211_IFTYPE_P2P_DEVICE) { + wil_err(wil, "%s: unsupported iftype %d\n", __func__, type); + return ERR_PTR(-EINVAL); + } + + if (wil->p2p_wdev) { + wil_err(wil, "%s: P2P_DEVICE interface already created\n", + __func__); + return ERR_PTR(-EINVAL); + } + + p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL); + if (!p2p_wdev) + return ERR_PTR(-ENOMEM); + + p2p_wdev->iftype = type; + p2p_wdev->wiphy = wiphy; + /* use our primary ethernet address */ + ether_addr_copy(p2p_wdev->address, ndev->perm_addr); + + wil->p2p_wdev = p2p_wdev; + + return p2p_wdev; +} + +static int wil_cfg80211_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + wil_dbg_misc(wil, "%s()\n", __func__); + + if (wdev != wil->p2p_wdev) { + wil_err(wil, "%s: delete of incorrect interface 0x%p\n", + __func__, wdev); + return -EINVAL; + } + + wil_p2p_wdev_free(wil); + + return 0; +} + static int wil_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = wil->wdev; + struct wireless_dev *wdev = wil_to_wdev(wil); int rc; wil_dbg_misc(wil, "%s() type=%d\n", __func__, type); @@ -282,7 +343,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = wil->wdev; + struct wireless_dev *wdev = request->wdev; struct { struct wmi_start_scan_cmd cmd; u16 chnl[4]; @@ -290,7 +351,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, uint i, n; int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n", + __func__, wdev, wdev->iftype); if (wil->scan_request) { wil_err(wil, "Already scanning\n"); @@ -301,6 +363,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, switch (wdev->iftype) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_DEVICE: break; default: return -EOPNOTSUPP; @@ -312,10 +375,16 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } - /* check if scan request is a P2P search request */ - if (wil_scan_is_p2p_search(wil, request)) { + /* scan on P2P_DEVICE is handled as p2p search */ + if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { wil->scan_request = request; - return wil_p2p_search(wil, request); + wil->radio_wdev = wdev; + rc = wil_p2p_search(wil, request); + if (rc) { + wil->radio_wdev = wil_to_wdev(wil); + wil->scan_request = NULL; + } + return rc; } wil_p2p_stop_discovery(wil); @@ -378,12 +447,14 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, wil_dbg_misc(wil, "active scan with discovery_mode=1\n"); } + wil->radio_wdev = wdev; rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); out: if (rc) { del_timer_sync(&wil->scan_timer); + wil->radio_wdev = wil_to_wdev(wil); wil->scan_request = NULL; } @@ -647,7 +718,7 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = wil->wdev; + struct wireless_dev *wdev = wil_to_wdev(wil); wdev->preset_chandef = *chandef; @@ -657,7 +728,7 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy, static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, bool pairwise) { - struct wireless_dev *wdev = wil->wdev; + struct wireless_dev *wdev = wil_to_wdev(wil); enum wmi_key_usage rc; if (pairwise) { @@ -809,14 +880,16 @@ static int wil_remain_on_channel(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; - wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d\n", __func__, - chan->center_freq, duration); + wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n", + __func__, chan->center_freq, duration, wdev->iftype); rc = wil_p2p_listen(wil, duration, chan, cookie); if (rc) return rc; - cfg80211_ready_on_channel(wil->wdev, *cookie, chan, duration, + wil->radio_wdev = wdev; + + cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL); return 0; @@ -1263,7 +1336,26 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy, return 0; } +static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + wil_dbg_misc(wil, "%s: entered\n", __func__); + return 0; +} + +static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + wil_dbg_misc(wil, "%s: entered\n", __func__); +} + static struct cfg80211_ops wil_cfg80211_ops = { + .add_virtual_intf = wil_cfg80211_add_iface, + .del_virtual_intf = wil_cfg80211_del_iface, .scan = wil_cfg80211_scan, .connect = wil_cfg80211_connect, .disconnect = wil_cfg80211_disconnect, @@ -1284,6 +1376,9 @@ static struct cfg80211_ops wil_cfg80211_ops = { .del_station = wil_cfg80211_del_station, .probe_client = wil_cfg80211_probe_client, .change_bss = wil_cfg80211_change_bss, + /* P2P device */ + .start_p2p_device = wil_cfg80211_start_p2p_device, + .stop_p2p_device = wil_cfg80211_stop_p2p_device, }; static void wil_wiphy_init(struct wiphy *wiphy) @@ -1296,9 +1391,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | - /* enable this when supporting multi vif - * BIT(NL80211_IFTYPE_P2P_DEVICE) | - */ + BIT(NL80211_IFTYPE_P2P_DEVICE) | BIT(NL80211_IFTYPE_MONITOR); wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | @@ -1369,3 +1462,18 @@ void wil_wdev_free(struct wil6210_priv *wil) wiphy_free(wdev->wiphy); kfree(wdev); } + +void wil_p2p_wdev_free(struct wil6210_priv *wil) +{ + struct wireless_dev *p2p_wdev; + + mutex_lock(&wil->p2p_wdev_mutex); + p2p_wdev = wil->p2p_wdev; + if (p2p_wdev) { + wil->p2p_wdev = NULL; + wil->radio_wdev = wil_to_wdev(wil); + cfg80211_unregister_wdev(p2p_wdev); + kfree(p2p_wdev); + } + mutex_unlock(&wil->p2p_wdev_mutex); +} diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 025751e223c2..e09e9bb28e39 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -446,6 +446,7 @@ int wil_priv_init(struct wil6210_priv *wil) mutex_init(&wil->mutex); mutex_init(&wil->wmi_mutex); mutex_init(&wil->probe_client_mutex); + mutex_init(&wil->p2p_wdev_mutex); init_completion(&wil->wmi_ready); init_completion(&wil->wmi_call); diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index ecc3c1bdae4b..d4ec5b278eb3 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -149,6 +149,7 @@ void *wil_if_alloc(struct device *dev) wil = wdev_to_wil(wdev); wil->wdev = wdev; + wil->radio_wdev = wdev; wil_dbg_misc(wil, "%s()\n", __func__); diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index 974bf84dbf52..d223648076a0 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -22,13 +22,6 @@ #define P2P_SEARCH_DURATION_MS 500 #define P2P_DEFAULT_BI 100 -int wil_scan_is_p2p_search(struct wil6210_priv *wil, - struct cfg80211_scan_request *request) -{ - /* need P2P_DEVICE changes to make this work */ - return 0; -} - void wil_p2p_discovery_timer_fn(ulong x) { struct wil6210_priv *wil = (void *)x; @@ -183,10 +176,14 @@ void wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) __func__, p2p->cookie, cookie); wil_p2p_stop_discovery(wil); - cfg80211_remain_on_channel_expired(wil->wdev, + + mutex_lock(&wil->p2p_wdev_mutex); + cfg80211_remain_on_channel_expired(wil->radio_wdev, p2p->cookie, &p2p->listen_chan, GFP_KERNEL); + wil->radio_wdev = wil->wdev; + mutex_unlock(&wil->p2p_wdev_mutex); } void wil_p2p_listen_expired(struct work_struct *work) @@ -199,10 +196,15 @@ void wil_p2p_listen_expired(struct work_struct *work) wil_dbg_misc(wil, "%s()\n", __func__); wil_p2p_stop_discovery(wil); - cfg80211_remain_on_channel_expired(wil->wdev, + + mutex_lock(&wil->p2p_wdev_mutex); + cfg80211_remain_on_channel_expired(wil->radio_wdev, p2p->cookie, &p2p->listen_chan, GFP_KERNEL); + wil->radio_wdev = wil->wdev; + mutex_unlock(&wil->p2p_wdev_mutex); + } void wil_p2p_search_expired(struct work_struct *work) @@ -215,6 +217,10 @@ void wil_p2p_search_expired(struct work_struct *work) wil_dbg_misc(wil, "%s()\n", __func__); wil_p2p_stop_discovery(wil); + + mutex_lock(&wil->p2p_wdev_mutex); cfg80211_scan_done(wil->scan_request, 0); wil->scan_request = NULL; + wil->radio_wdev = wil->wdev; + mutex_unlock(&wil->p2p_wdev_mutex); } diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index e36f2a0c8cb6..aeb72c438e44 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -275,6 +275,7 @@ static void wil_pcie_remove(struct pci_dev *pdev) pci_disable_device(pdev); if (wil->platform_ops.uninit) wil->platform_ops.uninit(wil->platform_handle); + wil_p2p_wdev_free(wil); wil_if_free(wil); } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 0aba86c6b05e..9b77a0844a83 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -616,6 +616,11 @@ struct wil6210_priv { bool pbss; struct wil_p2p_info p2p; + + /* P2P_DEVICE vif */ + struct wireless_dev *p2p_wdev; + struct mutex p2p_wdev_mutex; /* protect @p2p_wdev */ + struct wireless_dev *radio_wdev; }; #define wil_to_wiphy(i) (i->wdev->wiphy) @@ -765,8 +770,6 @@ void wil_disable_irq(struct wil6210_priv *wil); void wil_enable_irq(struct wil6210_priv *wil); /* P2P */ -int wil_scan_is_p2p_search(struct wil6210_priv *wil, - struct cfg80211_scan_request *request); void wil_p2p_discovery_timer_fn(ulong x); int wil_p2p_search(struct wil6210_priv *wil, struct cfg80211_scan_request *request); @@ -794,6 +797,7 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, struct wireless_dev *wil_cfg80211_init(struct device *dev); void wil_wdev_free(struct wil6210_priv *wil); +void wil_p2p_wdev_free(struct wil6210_priv *wil); int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 4a1cdd256ef2..f0761758fac7 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -380,8 +380,10 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) wil_err(wil, "cfg80211_inform_bss_frame() failed\n"); } } else { - cfg80211_rx_mgmt(wil->wdev, freq, signal, + mutex_lock(&wil->p2p_wdev_mutex); + cfg80211_rx_mgmt(wil->radio_wdev, freq, signal, (void *)rx_mgmt_frame, d_len, 0); + mutex_unlock(&wil->p2p_wdev_mutex); } } @@ -408,7 +410,10 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, wil->scan_request, aborted); del_timer_sync(&wil->scan_timer); + mutex_lock(&wil->p2p_wdev_mutex); cfg80211_scan_done(wil->scan_request, aborted); + wil->radio_wdev = wil->wdev; + mutex_unlock(&wil->p2p_wdev_mutex); wil->scan_request = NULL; } else { wil_err(wil, "SCAN_COMPLETE while not scanning\n"); -- GitLab From 280ab987ef21d1c196acb3af4663a99f94d9da00 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:14 +0200 Subject: [PATCH 0038/9938] wil6210: fix race conditions in p2p listen and search Fix 2 race conditions found during test runs of P2P discovery: 1. Because wil_p2p_cancel_listen was not protected, user space could start a new P2P listen/search before wmi_stop_discovery completed. This caused a crash in the firmware. 2. In P2P listen, when listen timer expires and user space calls cancel_remain_on_channel at the same time, code could send the cfg80211_remain_on_channel_expired notification twice. Added protections with wil->mutex to several places that call wmi_stop_discovery. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 9 +-- drivers/net/wireless/ath/wil6210/main.c | 2 +- drivers/net/wireless/ath/wil6210/p2p.c | 63 +++++++++++++++------ drivers/net/wireless/ath/wil6210/wil6210.h | 4 +- 4 files changed, 53 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 24f9829c8222..e867c76a4197 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -387,7 +387,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, return rc; } - wil_p2p_stop_discovery(wil); + (void)wil_p2p_stop_discovery(wil); wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); wil_dbg_misc(wil, "SSID count: %d", request->n_ssids); @@ -868,6 +868,9 @@ static int wil_cfg80211_set_default_key(struct wiphy *wiphy, u8 key_index, bool unicast, bool multicast) { + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + wil_dbg_misc(wil, "%s: entered\n", __func__); return 0; } @@ -903,9 +906,7 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, wil_dbg_misc(wil, "%s()\n", __func__); - wil_p2p_cancel_listen(wil, cookie); - - return 0; + return wil_p2p_cancel_listen(wil, cookie); } /** diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index e09e9bb28e39..05a4ae7a7765 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -984,7 +984,7 @@ int __wil_down(struct wil6210_priv *wil) } wil_enable_irq(wil); - wil_p2p_stop_discovery(wil); + (void)wil_p2p_stop_discovery(wil); if (wil->scan_request) { wil_dbg_misc(wil, "Abort scan_request 0x%p\n", diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index d223648076a0..2c1b8958180e 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -156,26 +156,42 @@ int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, return rc; } -void wil_p2p_stop_discovery(struct wil6210_priv *wil) +u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) { struct wil_p2p_info *p2p = &wil->p2p; + u8 started = p2p->discovery_started; if (p2p->discovery_started) { del_timer_sync(&p2p->discovery_timer); p2p->discovery_started = 0; wmi_stop_discovery(wil); } + + return started; } -void wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) +int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) { struct wil_p2p_info *p2p = &wil->p2p; + u8 started; + + mutex_lock(&wil->mutex); - if (cookie != p2p->cookie) + if (cookie != p2p->cookie) { wil_info(wil, "%s: Cookie mismatch: 0x%016llx vs. 0x%016llx\n", __func__, p2p->cookie, cookie); + mutex_unlock(&wil->mutex); + return -ENOENT; + } + + started = wil_p2p_stop_discovery(wil); + + mutex_unlock(&wil->mutex); - wil_p2p_stop_discovery(wil); + if (!started) { + wil_err(wil, "%s: listen not started\n", __func__); + return -ENOENT; + } mutex_lock(&wil->p2p_wdev_mutex); cfg80211_remain_on_channel_expired(wil->radio_wdev, @@ -184,6 +200,7 @@ void wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) GFP_KERNEL); wil->radio_wdev = wil->wdev; mutex_unlock(&wil->p2p_wdev_mutex); + return 0; } void wil_p2p_listen_expired(struct work_struct *work) @@ -192,18 +209,23 @@ void wil_p2p_listen_expired(struct work_struct *work) struct wil_p2p_info, discovery_expired_work); struct wil6210_priv *wil = container_of(p2p, struct wil6210_priv, p2p); + u8 started; wil_dbg_misc(wil, "%s()\n", __func__); - wil_p2p_stop_discovery(wil); + mutex_lock(&wil->mutex); + started = wil_p2p_stop_discovery(wil); + mutex_unlock(&wil->mutex); - mutex_lock(&wil->p2p_wdev_mutex); - cfg80211_remain_on_channel_expired(wil->radio_wdev, - p2p->cookie, - &p2p->listen_chan, - GFP_KERNEL); - wil->radio_wdev = wil->wdev; - mutex_unlock(&wil->p2p_wdev_mutex); + if (started) { + mutex_lock(&wil->p2p_wdev_mutex); + cfg80211_remain_on_channel_expired(wil->radio_wdev, + p2p->cookie, + &p2p->listen_chan, + GFP_KERNEL); + wil->radio_wdev = wil->wdev; + mutex_unlock(&wil->p2p_wdev_mutex); + } } @@ -213,14 +235,19 @@ void wil_p2p_search_expired(struct work_struct *work) struct wil_p2p_info, discovery_expired_work); struct wil6210_priv *wil = container_of(p2p, struct wil6210_priv, p2p); + u8 started; wil_dbg_misc(wil, "%s()\n", __func__); - wil_p2p_stop_discovery(wil); + mutex_lock(&wil->mutex); + started = wil_p2p_stop_discovery(wil); + mutex_unlock(&wil->mutex); - mutex_lock(&wil->p2p_wdev_mutex); - cfg80211_scan_done(wil->scan_request, 0); - wil->scan_request = NULL; - wil->radio_wdev = wil->wdev; - mutex_unlock(&wil->p2p_wdev_mutex); + if (started) { + mutex_lock(&wil->p2p_wdev_mutex); + cfg80211_scan_done(wil->scan_request, 0); + wil->scan_request = NULL; + wil->radio_wdev = wil->wdev; + mutex_unlock(&wil->p2p_wdev_mutex); + } } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 9b77a0844a83..68f60eadde13 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -775,8 +775,8 @@ int wil_p2p_search(struct wil6210_priv *wil, struct cfg80211_scan_request *request); int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, struct ieee80211_channel *chan, u64 *cookie); -void wil_p2p_stop_discovery(struct wil6210_priv *wil); -void wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); +u8 wil_p2p_stop_discovery(struct wil6210_priv *wil); +int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); void wil_p2p_listen_expired(struct work_struct *work); void wil_p2p_search_expired(struct work_struct *work); -- GitLab From 6777e71ca91ea488488362a919900488e0ade3f2 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:15 +0200 Subject: [PATCH 0039/9938] wil6210: clean ioctl debug message Fix a debug message related to IOCTL that was incorrectly logged with the MISC category, and move it inside wil_ioctl so it will always be logged even if we call wil_ioctl from other places. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/ioctl.c | 11 +++++++++-- drivers/net/wireless/ath/wil6210/netdev.c | 6 +----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/ioctl.c b/drivers/net/wireless/ath/wil6210/ioctl.c index f7f948621951..630380078236 100644 --- a/drivers/net/wireless/ath/wil6210/ioctl.c +++ b/drivers/net/wireless/ath/wil6210/ioctl.c @@ -161,13 +161,20 @@ static int wil_ioc_memio_block(struct wil6210_priv *wil, void __user *data) int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd) { + int ret; + switch (cmd) { case WIL_IOCTL_MEMIO: - return wil_ioc_memio_dword(wil, data); + ret = wil_ioc_memio_dword(wil, data); + break; case WIL_IOCTL_MEMIO_BLOCK: - return wil_ioc_memio_block(wil, data); + ret = wil_ioc_memio_block(wil, data); + break; default: wil_dbg_ioctl(wil, "Unsupported IOCTL 0x%04x\n", cmd); return -ENOIOCTLCMD; } + + wil_dbg_ioctl(wil, "ioctl(0x%04x) -> %d\n", cmd, ret); + return ret; } diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index d4ec5b278eb3..3bc0e2634db0 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -60,11 +60,7 @@ static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) { struct wil6210_priv *wil = ndev_to_wil(ndev); - int ret = wil_ioctl(wil, ifr->ifr_data, cmd); - - wil_dbg_misc(wil, "ioctl(0x%04x) -> %d\n", cmd, ret); - - return ret; + return wil_ioctl(wil, ifr->ifr_data, cmd); } static const struct net_device_ops wil_netdev_ops = { -- GitLab From 375a173fc1524eb569c7e8f9cf331126a9d29033 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:16 +0200 Subject: [PATCH 0040/9938] wil6210: fix no_fw_recovery mode with change_virtual_intf When FW crashed with no_fw_recovery mode enabled, user space could still call wil_cfg80211_change_iface quickly to change interface type, and this would cause recovery to proceed and FW crash logs may be lost. Fix this problem by not resetting the FW in case no_fw_recovery is enabled. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 2 +- drivers/net/wireless/ath/wil6210/interrupt.c | 1 + drivers/net/wireless/ath/wil6210/main.c | 5 +++++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index e867c76a4197..33e54519602f 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -306,7 +306,7 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, wil_dbg_misc(wil, "%s() type=%d\n", __func__, type); - if (netif_running(wil_to_ndev(wil))) { + if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) { wil_dbg_misc(wil, "interface is up. resetting...\n"); mutex_lock(&wil->mutex); __wil_down(wil); diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index ae902958bf55..fe66b2b646f0 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -391,6 +391,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); if (isr & ISR_MISC_FW_ERROR) { + wil->recovery_state = fw_recovery_pending; wil_fw_core_dump(wil); wil_notify_fw_error(wil); isr &= ~ISR_MISC_FW_ERROR; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 05a4ae7a7765..c2a0a6625252 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -305,6 +305,11 @@ void wil_set_recovery_state(struct wil6210_priv *wil, int state) wake_up_interruptible(&wil->wq); } +bool wil_is_recovery_blocked(struct wil6210_priv *wil) +{ + return no_fw_recovery && (wil->recovery_state == fw_recovery_pending); +} + static void wil_fw_error_worker(struct work_struct *work) { struct wil6210_priv *wil = container_of(work, struct wil6210_priv, diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 68f60eadde13..a23dcee886a0 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -716,6 +716,7 @@ void wil_priv_deinit(struct wil6210_priv *wil); int wil_reset(struct wil6210_priv *wil, bool no_fw); void wil_fw_error_recovery(struct wil6210_priv *wil); void wil_set_recovery_state(struct wil6210_priv *wil, int state); +bool wil_is_recovery_blocked(struct wil6210_priv *wil); int wil_up(struct wil6210_priv *wil); int __wil_up(struct wil6210_priv *wil); int wil_down(struct wil6210_priv *wil); -- GitLab From b4944f2c081ea0e2fa7bc8bb510e1e6e5667f30b Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:17 +0200 Subject: [PATCH 0041/9938] wil6210: pass is_go flag to firmware When starting a PCP, pass the is_go flag to firmware in wmi_pcp_start. This flag indicates whether we started a PCP which is also a GO(P2P group owner) or just a regular PCP. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 9 ++++++++- drivers/net/wireless/ath/wil6210/wil6210.h | 2 +- drivers/net/wireless/ath/wil6210/wmi.c | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 33e54519602f..12cae3c005fb 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1055,10 +1055,17 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, int rc; struct wireless_dev *wdev = ndev->ieee80211_ptr; u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); + u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO); if (pbss) wmi_nettype = WMI_NETTYPE_P2P; + wil_dbg_misc(wil, "%s: is_go=%d\n", __func__, is_go); + if (is_go && !pbss) { + wil_err(wil, "%s: P2P GO must be in PBSS\n", __func__); + return -ENOTSUPP; + } + wil_set_recovery_state(wil, fw_recovery_idle); mutex_lock(&wil->mutex); @@ -1083,7 +1090,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, netif_carrier_on(ndev); - rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid); + rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go); if (rc) goto err_pcp_start; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index a23dcee886a0..d18c448c4a32 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -802,7 +802,7 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil); int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, - u8 chan, u8 hidden_ssid); + u8 chan, u8 hidden_ssid, u8 is_go); int wmi_pcp_stop(struct wil6210_priv *wil); void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, u16 reason_code, bool from_event); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index f0761758fac7..3cc4462aec1a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -962,7 +962,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) } int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, - u8 chan, u8 hidden_ssid) + u8 chan, u8 hidden_ssid, u8 is_go) { int rc; @@ -973,6 +973,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, .channel = chan - 1, .pcp_max_assoc_sta = max_assoc_sta, .hidden_ssid = hidden_ssid, + .is_go = is_go, }; struct { struct wmi_cmd_hdr wmi; -- GitLab From 1f1a361abf73edfb94ca010c51587de378bc7c68 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 1 Mar 2016 19:18:18 +0200 Subject: [PATCH 0042/9938] wil6210: add oob_mode module parameter Add module parameter oob_mode. Takes effect the next time the interface is brought up and FW is loaded. Puts the FW in special "out of the box" (OOB) mode which is used for diagnostics and certification. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 16 ++++++++++++++++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index c2a0a6625252..8d4e8843004e 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -27,6 +27,11 @@ bool debug_fw; /* = false; */ module_param(debug_fw, bool, S_IRUGO); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); +static bool oob_mode; +module_param(oob_mode, bool, S_IRUGO); +MODULE_PARM_DESC(oob_mode, + " enable out of the box (OOB) mode in FW, for diagnostics and certification"); + bool no_fw_recovery; module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery"); @@ -547,6 +552,16 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) wil_w(wil, RGF_USER_USER_CPU_0, 1); } +static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable) +{ + wil_info(wil, "%s: enable=%d\n", __func__, enable); + if (enable) { + wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); + } else { + wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); + } +} + static int wil_target_reset(struct wil6210_priv *wil) { int delay = 0; @@ -823,6 +838,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (rc) return rc; + wil_set_oob_mode(wil, oob_mode); if (load_fw) { wil_info(wil, "Use firmware <%s> + board <%s>\n", WIL_FW_NAME, WIL_FW2_NAME); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index d18c448c4a32..4d699ea46373 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -132,6 +132,7 @@ struct RGF_ICR { /* registers - FW addresses */ #define RGF_USER_USAGE_1 (0x880004) #define RGF_USER_USAGE_6 (0x880018) + #define BIT_USER_OOB_MODE BIT(31) #define RGF_USER_HW_MACHINE_STATE (0x8801dc) #define HW_MACHINE_BOOT_DONE (0x3fffffd) #define RGF_USER_USER_CPU_0 (0x8801e0) -- GitLab From 60549cab2ea5ffa100076cb06d49579e05edd966 Mon Sep 17 00:00:00 2001 From: Grzegorz Bajorski Date: Mon, 30 Nov 2015 13:56:59 +0100 Subject: [PATCH 0043/9938] ath10k: deliver mgmt frames from htt to monitor vifs only Until now only WMI originating mgmt frames were reported to mac80211. Management frames on HTT were basically dropped (except frames which looked like management but had FCS error). To allow sniffing all frames (including offloaded frames) without interfering with mac80211 operation and states a new rx_flag was introduced and is not being used to distinguish frames and classify them for mac80211. Signed-off-by: Grzegorz Bajorski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 70 ++++++++++++------------ drivers/net/wireless/ath/ath10k/wmi.c | 6 ++ 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 40f969c72de8..84b060efa1b5 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1078,20 +1078,25 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, hdr = (void *)msdu->data; /* Tail */ - skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype)); + if (status->flag & RX_FLAG_IV_STRIPPED) + skb_trim(msdu, msdu->len - + ath10k_htt_rx_crypto_tail_len(ar, enctype)); /* MMIC */ - if (!ieee80211_has_morefrags(hdr->frame_control) && + if ((status->flag & RX_FLAG_MMIC_STRIPPED) && + !ieee80211_has_morefrags(hdr->frame_control) && enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) skb_trim(msdu, msdu->len - 8); /* Head */ - hdr_len = ieee80211_hdrlen(hdr->frame_control); - crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); + if (status->flag & RX_FLAG_IV_STRIPPED) { + hdr_len = ieee80211_hdrlen(hdr->frame_control); + crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); - memmove((void *)msdu->data + crypto_len, - (void *)msdu->data, hdr_len); - skb_pull(msdu, crypto_len); + memmove((void *)msdu->data + crypto_len, + (void *)msdu->data, hdr_len); + skb_pull(msdu, crypto_len); + } } static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, @@ -1345,6 +1350,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, bool has_tkip_err; bool has_peer_idx_invalid; bool is_decrypted; + bool is_mgmt; u32 attention; if (skb_queue_empty(amsdu)) @@ -1353,6 +1359,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, first = skb_peek(amsdu); rxd = (void *)first->data - sizeof(*rxd); + is_mgmt = !!(rxd->attention.flags & + __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE)); + enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), RX_MPDU_START_INFO0_ENCRYPT_TYPE); @@ -1394,6 +1403,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, RX_FLAG_MMIC_ERROR | RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | + RX_FLAG_ONLY_MONITOR | RX_FLAG_MMIC_STRIPPED); if (has_fcs_err) @@ -1402,10 +1412,21 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, if (has_tkip_err) status->flag |= RX_FLAG_MMIC_ERROR; - if (is_decrypted) - status->flag |= RX_FLAG_DECRYPTED | - RX_FLAG_IV_STRIPPED | - RX_FLAG_MMIC_STRIPPED; + /* Firmware reports all necessary management frames via WMI already. + * They are not reported to monitor interfaces at all so pass the ones + * coming via HTT to monitor interfaces instead. This simplifies + * matters a lot. + */ + if (is_mgmt) + status->flag |= RX_FLAG_ONLY_MONITOR; + + if (is_decrypted) { + status->flag |= RX_FLAG_DECRYPTED; + + if (likely(!is_mgmt)) + status->flag |= RX_FLAG_IV_STRIPPED | + RX_FLAG_MMIC_STRIPPED; +} skb_queue_walk(amsdu, msdu) { ath10k_htt_rx_h_csum_offload(msdu); @@ -1418,6 +1439,8 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, */ if (!is_decrypted) continue; + if (is_mgmt) + continue; hdr = (void *)msdu->data; hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); @@ -1518,14 +1541,6 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, struct sk_buff_head *amsdu, struct ieee80211_rx_status *rx_status) { - struct sk_buff *msdu; - struct htt_rx_desc *rxd; - bool is_mgmt; - bool has_fcs_err; - - msdu = skb_peek(amsdu); - rxd = (void *)msdu->data - sizeof(*rxd); - /* FIXME: It might be a good idea to do some fuzzy-testing to drop * invalid/dangerous frames. */ @@ -1535,23 +1550,6 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, return false; } - is_mgmt = !!(rxd->attention.flags & - __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE)); - has_fcs_err = !!(rxd->attention.flags & - __cpu_to_le32(RX_ATTENTION_FLAGS_FCS_ERR)); - - /* Management frames are handled via WMI events. The pros of such - * approach is that channel is explicitly provided in WMI events - * whereas HTT doesn't provide channel information for Rxed frames. - * - * However some firmware revisions don't report corrupted frames via - * WMI so don't drop them. - */ - if (is_mgmt && !has_fcs_err) { - ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); - return false; - } - if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) { ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx cac running\n"); return false; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index c31b4878cdc6..651220e98c72 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2310,6 +2310,12 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) hdr = (struct ieee80211_hdr *)skb->data; fc = le16_to_cpu(hdr->frame_control); + /* Firmware is guaranteed to report all essential management frames via + * WMI while it can deliver some extra via HTT. Since there can be + * duplicates split the reporting wrt monitor/sniffing. + */ + status->flag |= RX_FLAG_SKIP_MONITOR; + ath10k_wmi_handle_wep_reauth(ar, skb, status); /* FW delivers WEP Shared Auth frame with Protected Bit set and -- GitLab From 8d130963d38a5677dfd30a2fda83e5cd0b9f4f69 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Tue, 1 Mar 2016 09:52:49 -0800 Subject: [PATCH 0044/9938] ath10k: set MAC timestamp in management Rx frame Check and set Rx MAC timestamp when firmware indicates it. Firmware adds it in Rx beacon frame only at this moment. Driver and mac80211 may utilize it to detect such clockdrift or beacon collision and use the result for beacon collision avoidance. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 13 +++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 651220e98c72..c2608946f773 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2167,8 +2167,10 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb, struct wmi_mgmt_rx_event_v1 *ev_v1; struct wmi_mgmt_rx_event_v2 *ev_v2; struct wmi_mgmt_rx_hdr_v1 *ev_hdr; + struct wmi_mgmt_rx_ext_info *ext_info; size_t pull_len; u32 msdu_len; + u32 len; if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) { ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data; @@ -2195,6 +2197,12 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb, if (skb->len < msdu_len) return -EPROTO; + if (le32_to_cpu(arg->status) & WMI_RX_STATUS_EXT_INFO) { + len = ALIGN(le32_to_cpu(arg->buf_len), 4); + ext_info = (struct wmi_mgmt_rx_ext_info *)(skb->data + len); + memcpy(&arg->ext_info, ext_info, + sizeof(struct wmi_mgmt_rx_ext_info)); + } /* the WMI buffer might've ended up being padded to 4 bytes due to HTC * trailer with credit update. Trim the excess garbage. */ @@ -2281,6 +2289,11 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) if (rx_status & WMI_RX_STATUS_ERR_MIC) status->flag |= RX_FLAG_MMIC_ERROR; + if (rx_status & WMI_RX_STATUS_EXT_INFO) { + status->mactime = + __le64_to_cpu(arg.ext_info.rx_mac_timestamp); + status->flag |= RX_FLAG_MACTIME_END; + } /* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to * MODE_11B. This means phy_mode is not a reliable source for the band * of mgmt rx. diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 4d3cbc44fcd2..bb42f7a6ba23 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -3037,11 +3037,17 @@ struct wmi_10_4_mgmt_rx_event { u8 buf[0]; } __packed; +struct wmi_mgmt_rx_ext_info { + __le64 rx_mac_timestamp; +} __packed __aligned(4); + #define WMI_RX_STATUS_OK 0x00 #define WMI_RX_STATUS_ERR_CRC 0x01 #define WMI_RX_STATUS_ERR_DECRYPT 0x08 #define WMI_RX_STATUS_ERR_MIC 0x10 #define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20 +/* Extension data at the end of mgmt frame */ +#define WMI_RX_STATUS_EXT_INFO 0x40 #define PHY_ERROR_GEN_SPECTRAL_SCAN 0x26 #define PHY_ERROR_GEN_FALSE_RADAR_EXT 0x24 @@ -6116,6 +6122,7 @@ struct wmi_mgmt_rx_ev_arg { __le32 phy_mode; __le32 buf_len; __le32 status; /* %WMI_RX_STATUS_ */ + struct wmi_mgmt_rx_ext_info ext_info; }; struct wmi_ch_info_ev_arg { -- GitLab From 88ae3aedb8ec20a6b6ea8f7bd1990c0eb7c6f5d5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 7 Mar 2016 15:22:31 +0100 Subject: [PATCH 0045/9938] staging:iio:adis16204: Remove adis16204 driver The ADIS16204 part has been obsoleted, which makes it hard to get the hardware to even test the driver. Considering this there is no expectation that the driver will be cleaned up and be able to move out of staging, so remove the driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/Kconfig | 12 - drivers/staging/iio/accel/Makefile | 3 - drivers/staging/iio/accel/adis16204.h | 68 ------ drivers/staging/iio/accel/adis16204_core.c | 253 --------------------- 4 files changed, 336 deletions(-) delete mode 100644 drivers/staging/iio/accel/adis16204.h delete mode 100644 drivers/staging/iio/accel/adis16204_core.c diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index fa67da9408b6..5bc98031a34d 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -27,18 +27,6 @@ config ADIS16203 To compile this driver as a module, say M here: the module will be called adis16203. -config ADIS16204 - tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder" - depends on SPI - select IIO_ADIS_LIB - select IIO_ADIS_LIB_BUFFER if IIO_BUFFER - help - Say Y here to build support for Analog Devices adis16204 Programmable - High-g Digital Impact Sensor and Recorder. - - To compile this driver as a module, say M here: the module will be - called adis16204. - config ADIS16209 tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer" depends on SPI diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index 1ed137f1a506..8ad9732e3dbb 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -8,9 +8,6 @@ obj-$(CONFIG_ADIS16201) += adis16201.o adis16203-y := adis16203_core.o obj-$(CONFIG_ADIS16203) += adis16203.o -adis16204-y := adis16204_core.o -obj-$(CONFIG_ADIS16204) += adis16204.o - adis16209-y := adis16209_core.o obj-$(CONFIG_ADIS16209) += adis16209.o diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h deleted file mode 100644 index 0b23f0b5c52f..000000000000 --- a/drivers/staging/iio/accel/adis16204.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef SPI_ADIS16204_H_ -#define SPI_ADIS16204_H_ - -#define ADIS16204_STARTUP_DELAY 220 /* ms */ - -#define ADIS16204_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16204_SUPPLY_OUT 0x02 /* Output, power supply */ -#define ADIS16204_XACCL_OUT 0x04 /* Output, x-axis accelerometer */ -#define ADIS16204_YACCL_OUT 0x06 /* Output, y-axis accelerometer */ -#define ADIS16204_AUX_ADC 0x08 /* Output, auxiliary ADC input */ -#define ADIS16204_TEMP_OUT 0x0A /* Output, temperature */ -#define ADIS16204_X_PEAK_OUT 0x0C /* Twos complement */ -#define ADIS16204_Y_PEAK_OUT 0x0E /* Twos complement */ -#define ADIS16204_XACCL_NULL 0x10 /* Calibration, x-axis acceleration offset null */ -#define ADIS16204_YACCL_NULL 0x12 /* Calibration, y-axis acceleration offset null */ -#define ADIS16204_XACCL_SCALE 0x14 /* X-axis scale factor calibration register */ -#define ADIS16204_YACCL_SCALE 0x16 /* Y-axis scale factor calibration register */ -#define ADIS16204_XY_RSS_OUT 0x18 /* XY combined acceleration (RSS) */ -#define ADIS16204_XY_PEAK_OUT 0x1A /* Peak, XY combined output (RSS) */ -#define ADIS16204_CAP_BUF_1 0x1C /* Capture buffer output register 1 */ -#define ADIS16204_CAP_BUF_2 0x1E /* Capture buffer output register 2 */ -#define ADIS16204_ALM_MAG1 0x20 /* Alarm 1 amplitude threshold */ -#define ADIS16204_ALM_MAG2 0x22 /* Alarm 2 amplitude threshold */ -#define ADIS16204_ALM_CTRL 0x28 /* Alarm control */ -#define ADIS16204_CAPT_PNTR 0x2A /* Capture register address pointer */ -#define ADIS16204_AUX_DAC 0x30 /* Auxiliary DAC data */ -#define ADIS16204_GPIO_CTRL 0x32 /* General-purpose digital input/output control */ -#define ADIS16204_MSC_CTRL 0x34 /* Miscellaneous control */ -#define ADIS16204_SMPL_PRD 0x36 /* Internal sample period (rate) control */ -#define ADIS16204_AVG_CNT 0x38 /* Operation, filter configuration */ -#define ADIS16204_SLP_CNT 0x3A /* Operation, sleep mode control */ -#define ADIS16204_DIAG_STAT 0x3C /* Diagnostics, system status register */ -#define ADIS16204_GLOB_CMD 0x3E /* Operation, system command register */ - -/* MSC_CTRL */ -#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST BIT(10) /* Self-test at power-on: 1 = disabled, 0 = enabled */ -#define ADIS16204_MSC_CTRL_SELF_TEST_EN BIT(8) /* Self-test enable */ -#define ADIS16204_MSC_CTRL_DATA_RDY_EN BIT(2) /* Data-ready enable: 1 = enabled, 0 = disabled */ -#define ADIS16204_MSC_CTRL_ACTIVE_HIGH BIT(1) /* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2 BIT(0) /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */ - -/* DIAG_STAT */ -#define ADIS16204_DIAG_STAT_ALARM2 BIT(9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16204_DIAG_STAT_ALARM1 BIT(8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag: 1 = error condition, - 0 = normal operation */ -#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */ -#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */ -#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */ -#define ADIS16204_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 2.975 V */ - -/* GLOB_CMD */ -#define ADIS16204_GLOB_CMD_SW_RESET BIT(7) -#define ADIS16204_GLOB_CMD_CLEAR_STAT BIT(4) -#define ADIS16204_GLOB_CMD_FACTORY_CAL BIT(1) - -#define ADIS16204_ERROR_ACTIVE BIT(14) - -enum adis16204_scan { - ADIS16204_SCAN_ACC_X, - ADIS16204_SCAN_ACC_Y, - ADIS16204_SCAN_ACC_XY, - ADIS16204_SCAN_SUPPLY, - ADIS16204_SCAN_AUX_ADC, - ADIS16204_SCAN_TEMP, -}; - -#endif /* SPI_ADIS16204_H_ */ diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c deleted file mode 100644 index 20a9df64f1ed..000000000000 --- a/drivers/staging/iio/accel/adis16204_core.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * ADIS16204 Programmable High-g Digital Impact Sensor and Recorder - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "adis16204.h" - -/* Unique to this driver currently */ - -static const u8 adis16204_addresses[][2] = { - [ADIS16204_SCAN_ACC_X] = { ADIS16204_XACCL_NULL, ADIS16204_X_PEAK_OUT }, - [ADIS16204_SCAN_ACC_Y] = { ADIS16204_YACCL_NULL, ADIS16204_Y_PEAK_OUT }, - [ADIS16204_SCAN_ACC_XY] = { 0, ADIS16204_XY_PEAK_OUT }, -}; - -static int adis16204_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct adis *st = iio_priv(indio_dev); - int ret; - int bits; - u8 addr; - s16 val16; - int addrind; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - return adis_single_conversion(indio_dev, chan, - ADIS16204_ERROR_ACTIVE, val); - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_VOLTAGE: - if (chan->channel == 0) { - *val = 1; - *val2 = 220000; /* 1.22 mV */ - } else { - *val = 0; - *val2 = 610000; /* 0.61 mV */ - } - return IIO_VAL_INT_PLUS_MICRO; - case IIO_TEMP: - *val = -470; /* 0.47 C */ - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_ACCEL: - *val = 0; - switch (chan->channel2) { - case IIO_MOD_X: - case IIO_MOD_ROOT_SUM_SQUARED_X_Y: - *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */ - break; - case IIO_MOD_Y: - case IIO_MOD_Z: - *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */ - break; - } - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - break; - case IIO_CHAN_INFO_OFFSET: - *val = 25000 / -470 - 1278; /* 25 C = 1278 */ - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS: - case IIO_CHAN_INFO_PEAK: - if (mask == IIO_CHAN_INFO_CALIBBIAS) { - bits = 12; - addrind = 0; - } else { /* PEAK_SEPARATE */ - bits = 14; - addrind = 1; - } - mutex_lock(&indio_dev->mlock); - addr = adis16204_addresses[chan->scan_index][addrind]; - ret = adis_read_reg_16(st, addr, &val16); - if (ret) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - val16 &= (1 << bits) - 1; - val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); - *val = val16; - mutex_unlock(&indio_dev->mlock); - return IIO_VAL_INT; - } - return -EINVAL; -} - -static int adis16204_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct adis *st = iio_priv(indio_dev); - int bits; - s16 val16; - u8 addr; - - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - switch (chan->type) { - case IIO_ACCEL: - bits = 12; - break; - default: - return -EINVAL; - } - val16 = val & ((1 << bits) - 1); - addr = adis16204_addresses[chan->scan_index][1]; - return adis_write_reg_16(st, addr, val16); - } - return -EINVAL; -} - -static const struct iio_chan_spec adis16204_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12), - ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12), - ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12), - ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), - 0, 14), - ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), - 0, 14), - ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT, - ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14), - IIO_CHAN_SOFT_TIMESTAMP(5), -}; - -static const struct iio_info adis16204_info = { - .read_raw = &adis16204_read_raw, - .write_raw = &adis16204_write_raw, - .update_scan_mode = adis_update_scan_mode, - .driver_module = THIS_MODULE, -}; - -static const char * const adis16204_status_error_msgs[] = { - [ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure", - [ADIS16204_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", - [ADIS16204_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", - [ADIS16204_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", - [ADIS16204_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", -}; - -static const struct adis_data adis16204_data = { - .read_delay = 20, - .msc_ctrl_reg = ADIS16204_MSC_CTRL, - .glob_cmd_reg = ADIS16204_GLOB_CMD, - .diag_stat_reg = ADIS16204_DIAG_STAT, - - .self_test_mask = ADIS16204_MSC_CTRL_SELF_TEST_EN, - .startup_delay = ADIS16204_STARTUP_DELAY, - - .status_error_msgs = adis16204_status_error_msgs, - .status_error_mask = BIT(ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT) | - BIT(ADIS16204_DIAG_STAT_SPI_FAIL_BIT) | - BIT(ADIS16204_DIAG_STAT_FLASH_UPT_BIT) | - BIT(ADIS16204_DIAG_STAT_POWER_HIGH_BIT) | - BIT(ADIS16204_DIAG_STAT_POWER_LOW_BIT), -}; - -static int adis16204_probe(struct spi_device *spi) -{ - int ret; - struct adis *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adis16204_info; - indio_dev->channels = adis16204_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16204_channels); - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = adis_init(st, indio_dev, spi, &adis16204_data); - if (ret) - return ret; - - ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); - if (ret) - return ret; - - /* Get the device into a sane initial state */ - ret = adis_initial_startup(st); - if (ret) - goto error_cleanup_buffer_trigger; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_buffer_trigger; - - return 0; - -error_cleanup_buffer_trigger: - adis_cleanup_buffer_and_trigger(st, indio_dev); - return ret; -} - -static int adis16204_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - adis_cleanup_buffer_and_trigger(st, indio_dev); - - return 0; -} - -static struct spi_driver adis16204_driver = { - .driver = { - .name = "adis16204", - }, - .probe = adis16204_probe, - .remove = adis16204_remove, -}; -module_spi_driver(adis16204_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:adis16204"); -- GitLab From 2bcdb3f2e05f011b7456d363a6fc5a0177196587 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 7 Mar 2016 15:22:32 +0100 Subject: [PATCH 0046/9938] staging:iio:adis16220: Remove adis16220 driver The ADIS16220 part has been obsoleted, which makes it hard to get the hardware to even test the driver. Considering this there is no expectation that the driver will be cleaned up and be able to move out of staging, so remove the driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/Kconfig | 11 - drivers/staging/iio/accel/Makefile | 3 - drivers/staging/iio/accel/adis16220.h | 140 ------ drivers/staging/iio/accel/adis16220_core.c | 494 --------------------- 4 files changed, 648 deletions(-) delete mode 100644 drivers/staging/iio/accel/adis16220.h delete mode 100644 drivers/staging/iio/accel/adis16220_core.c diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index 5bc98031a34d..f066aa30f0ac 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -39,17 +39,6 @@ config ADIS16209 To compile this driver as a module, say M here: the module will be called adis16209. -config ADIS16220 - tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor" - depends on SPI - select IIO_ADIS_LIB - help - Say Y here to build support for Analog Devices adis16220 programmable - digital vibration sensor. - - To compile this driver as a module, say M here: the module will be - called adis16220. - config ADIS16240 tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder" depends on SPI diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index 8ad9732e3dbb..415329c96f0c 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -11,9 +11,6 @@ obj-$(CONFIG_ADIS16203) += adis16203.o adis16209-y := adis16209_core.o obj-$(CONFIG_ADIS16209) += adis16209.o -adis16220-y := adis16220_core.o -obj-$(CONFIG_ADIS16220) += adis16220.o - adis16240-y := adis16240_core.o obj-$(CONFIG_ADIS16240) += adis16240.o diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h deleted file mode 100644 index eab86331124f..000000000000 --- a/drivers/staging/iio/accel/adis16220.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef SPI_ADIS16220_H_ -#define SPI_ADIS16220_H_ - -#include - -#define ADIS16220_STARTUP_DELAY 220 /* ms */ - -/* Flash memory write count */ -#define ADIS16220_FLASH_CNT 0x00 -/* Control, acceleration offset adjustment control */ -#define ADIS16220_ACCL_NULL 0x02 -/* Control, AIN1 offset adjustment control */ -#define ADIS16220_AIN1_NULL 0x04 -/* Control, AIN2 offset adjustment control */ -#define ADIS16220_AIN2_NULL 0x06 -/* Output, power supply during capture */ -#define ADIS16220_CAPT_SUPPLY 0x0A -/* Output, temperature during capture */ -#define ADIS16220_CAPT_TEMP 0x0C -/* Output, peak acceleration during capture */ -#define ADIS16220_CAPT_PEAKA 0x0E -/* Output, peak AIN1 level during capture */ -#define ADIS16220_CAPT_PEAK1 0x10 -/* Output, peak AIN2 level during capture */ -#define ADIS16220_CAPT_PEAK2 0x12 -/* Output, capture buffer for acceleration */ -#define ADIS16220_CAPT_BUFA 0x14 -/* Output, capture buffer for AIN1 */ -#define ADIS16220_CAPT_BUF1 0x16 -/* Output, capture buffer for AIN2 */ -#define ADIS16220_CAPT_BUF2 0x18 -/* Control, capture buffer address pointer */ -#define ADIS16220_CAPT_PNTR 0x1A -/* Control, capture control register */ -#define ADIS16220_CAPT_CTRL 0x1C -/* Control, capture period (automatic mode) */ -#define ADIS16220_CAPT_PRD 0x1E -/* Control, Alarm A, acceleration peak threshold */ -#define ADIS16220_ALM_MAGA 0x20 -/* Control, Alarm 1, AIN1 peak threshold */ -#define ADIS16220_ALM_MAG1 0x22 -/* Control, Alarm 2, AIN2 peak threshold */ -#define ADIS16220_ALM_MAG2 0x24 -/* Control, Alarm S, peak threshold */ -#define ADIS16220_ALM_MAGS 0x26 -/* Control, alarm configuration register */ -#define ADIS16220_ALM_CTRL 0x28 -/* Control, general I/O configuration */ -#define ADIS16220_GPIO_CTRL 0x32 -/* Control, self-test control, AIN configuration */ -#define ADIS16220_MSC_CTRL 0x34 -/* Control, digital I/O configuration */ -#define ADIS16220_DIO_CTRL 0x36 -/* Control, filter configuration */ -#define ADIS16220_AVG_CNT 0x38 -/* Status, system status */ -#define ADIS16220_DIAG_STAT 0x3C -/* Control, system commands */ -#define ADIS16220_GLOB_CMD 0x3E -/* Status, self-test response */ -#define ADIS16220_ST_DELTA 0x40 -/* Lot Identification Code 1 */ -#define ADIS16220_LOT_ID1 0x52 -/* Lot Identification Code 2 */ -#define ADIS16220_LOT_ID2 0x54 -/* Product identifier; convert to decimal = 16220 */ -#define ADIS16220_PROD_ID 0x56 -/* Serial number */ -#define ADIS16220_SERIAL_NUM 0x58 - -#define ADIS16220_CAPTURE_SIZE 2048 - -/* MSC_CTRL */ -#define ADIS16220_MSC_CTRL_SELF_TEST_EN BIT(8) -#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN1 BIT(1) -#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN2 BIT(0) - -/* DIO_CTRL */ -#define ADIS16220_MSC_CTRL_DIO2_BUSY_IND (BIT(5) | BIT(4)) -#define ADIS16220_MSC_CTRL_DIO1_BUSY_IND (BIT(3) | BIT(2)) -#define ADIS16220_MSC_CTRL_DIO2_ACT_HIGH BIT(1) -#define ADIS16220_MSC_CTRL_DIO1_ACT_HIGH BIT(0) - -/* DIAG_STAT */ -/* AIN2 sample > ALM_MAG2 */ -#define ADIS16220_DIAG_STAT_ALM_MAG2 BIT(14) -/* AIN1 sample > ALM_MAG1 */ -#define ADIS16220_DIAG_STAT_ALM_MAG1 BIT(13) -/* Acceleration sample > ALM_MAGA */ -#define ADIS16220_DIAG_STAT_ALM_MAGA BIT(12) -/* Error condition programmed into ALM_MAGS[11:0] and ALM_CTRL[5:4] is true */ -#define ADIS16220_DIAG_STAT_ALM_MAGS BIT(11) -/* |Peak value in AIN2 data capture| > ALM_MAG2 */ -#define ADIS16220_DIAG_STAT_PEAK_AIN2 BIT(10) -/* |Peak value in AIN1 data capture| > ALM_MAG1 */ -#define ADIS16220_DIAG_STAT_PEAK_AIN1 BIT(9) -/* |Peak value in acceleration data capture| > ALM_MAGA */ -#define ADIS16220_DIAG_STAT_PEAK_ACCEL BIT(8) -/* Data ready, capture complete */ -#define ADIS16220_DIAG_STAT_DATA_RDY BIT(7) -#define ADIS16220_DIAG_STAT_FLASH_CHK BIT(6) -#define ADIS16220_DIAG_STAT_SELF_TEST BIT(5) -/* Capture period violation/interruption */ -#define ADIS16220_DIAG_STAT_VIOLATION_BIT 4 -/* SPI communications failure */ -#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT 3 -/* Flash update failure */ -#define ADIS16220_DIAG_STAT_FLASH_UPT_BIT 2 -/* Power supply above 3.625 V */ -#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT 1 -/* Power supply below 3.15 V */ -#define ADIS16220_DIAG_STAT_POWER_LOW_BIT 0 - -/* GLOB_CMD */ -#define ADIS16220_GLOB_CMD_SW_RESET BIT(7) -#define ADIS16220_GLOB_CMD_SELF_TEST BIT(2) -#define ADIS16220_GLOB_CMD_PWR_DOWN BIT(1) - -#define ADIS16220_MAX_TX 2048 -#define ADIS16220_MAX_RX 2048 - -#define ADIS16220_SPI_BURST (u32)(1000 * 1000) -#define ADIS16220_SPI_FAST (u32)(2000 * 1000) - -/** - * struct adis16220_state - device instance specific data - * @adis: adis device - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16220_state { - struct adis adis; - - struct mutex buf_lock; - u8 tx[ADIS16220_MAX_TX] ____cacheline_aligned; - u8 rx[ADIS16220_MAX_RX]; -}; - -#endif /* SPI_ADIS16220_H_ */ diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c deleted file mode 100644 index d0165218b60c..000000000000 --- a/drivers/staging/iio/accel/adis16220_core.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * ADIS16220 Programmable Digital Vibration Sensor driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "adis16220.h" - -static ssize_t adis16220_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adis16220_state *st = iio_priv(indio_dev); - ssize_t ret; - u16 val; - - /* Take the iio_dev status lock */ - mutex_lock(&indio_dev->mlock); - ret = adis_read_reg_16(&st->adis, this_attr->address, &val); - mutex_unlock(&indio_dev->mlock); - if (ret) - return ret; - return sprintf(buf, "%u\n", val); -} - -static ssize_t adis16220_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct adis16220_state *st = iio_priv(indio_dev); - int ret; - u16 val; - - ret = kstrtou16(buf, 10, &val); - if (ret) - goto error_ret; - ret = adis_write_reg_16(&st->adis, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static int adis16220_capture(struct iio_dev *indio_dev) -{ - struct adis16220_state *st = iio_priv(indio_dev); - int ret; - - /* initiates a manual data capture */ - ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08); - if (ret) - dev_err(&indio_dev->dev, "problem beginning capture"); - - usleep_range(10000, 11000); /* delay for capture to finish */ - - return ret; -} - -static ssize_t adis16220_write_capture(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - ret = adis16220_capture(indio_dev); - if (ret) - return ret; - - return len; -} - -static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, - char *buf, - loff_t off, - size_t count, - int addr) -{ - struct adis16220_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 25, - }, { - .tx_buf = st->tx, - .rx_buf = st->rx, - .bits_per_word = 8, - .cs_change = 1, - .delay_usecs = 25, - }, - }; - int ret; - int i; - - if (unlikely(!count)) - return count; - - if ((off >= ADIS16220_CAPTURE_SIZE) || (count & 1) || (off & 1)) - return -EINVAL; - - if (off + count > ADIS16220_CAPTURE_SIZE) - count = ADIS16220_CAPTURE_SIZE - off; - - /* write the begin position of capture buffer */ - ret = adis_write_reg_16(&st->adis, - ADIS16220_CAPT_PNTR, - off > 1); - if (ret) - return -EIO; - - /* read count/2 values from capture buffer */ - mutex_lock(&st->buf_lock); - - for (i = 0; i < count; i += 2) { - st->tx[i] = ADIS_READ_REG(addr); - st->tx[i + 1] = 0; - } - xfers[1].len = count; - - ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers)); - if (ret) { - mutex_unlock(&st->buf_lock); - return -EIO; - } - - memcpy(buf, st->rx, count); - - mutex_unlock(&st->buf_lock); - return count; -} - -static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, - loff_t off, - size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); - - return adis16220_capture_buffer_read(indio_dev, buf, - off, count, - ADIS16220_CAPT_BUFA); -} - -static struct bin_attribute accel_bin = { - .attr = { - .name = "accel_bin", - .mode = S_IRUGO, - }, - .read = adis16220_accel_bin_read, - .size = ADIS16220_CAPTURE_SIZE, -}; - -static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, - size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); - - return adis16220_capture_buffer_read(indio_dev, buf, - off, count, - ADIS16220_CAPT_BUF1); -} - -static struct bin_attribute adc1_bin = { - .attr = { - .name = "in0_bin", - .mode = S_IRUGO, - }, - .read = adis16220_adc1_bin_read, - .size = ADIS16220_CAPTURE_SIZE, -}; - -static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, - size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); - - return adis16220_capture_buffer_read(indio_dev, buf, - off, count, - ADIS16220_CAPT_BUF2); -} - -static struct bin_attribute adc2_bin = { - .attr = { - .name = "in1_bin", - .mode = S_IRUGO, - }, - .read = adis16220_adc2_bin_read, - .size = ADIS16220_CAPTURE_SIZE, -}; - -#define IIO_DEV_ATTR_CAPTURE(_store) \ - IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0) - -static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture); - -#define IIO_DEV_ATTR_CAPTURE_COUNT(_mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(capture_count, _mode, _show, _store, _addr) - -static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO, - adis16220_read_16bit, - adis16220_write_16bit, - ADIS16220_CAPT_PNTR); - -enum adis16220_channel { - in_supply, in_1, in_2, accel, temp -}; - -struct adis16220_address_spec { - u8 addr; - u8 bits; - bool sign; -}; - -/* Address / bits / signed */ -static const struct adis16220_address_spec adis16220_addresses[][3] = { - [in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, }, - [in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 }, - { ADIS16220_AIN1_NULL, 16, 1 }, - { ADIS16220_CAPT_PEAK1, 16, 1 }, }, - [in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 }, - { ADIS16220_AIN2_NULL, 16, 1 }, - { ADIS16220_CAPT_PEAK2, 16, 1 }, }, - [accel] = { { ADIS16220_CAPT_BUFA, 16, 1 }, - { ADIS16220_ACCL_NULL, 16, 1 }, - { ADIS16220_CAPT_PEAKA, 16, 1 }, }, - [temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, } -}; - -static int adis16220_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct adis16220_state *st = iio_priv(indio_dev); - const struct adis16220_address_spec *addr; - int ret = -EINVAL; - int addrind = 0; - u16 uval; - s16 sval; - u8 bits; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - addrind = 0; - break; - case IIO_CHAN_INFO_OFFSET: - if (chan->type == IIO_TEMP) { - *val = 25000 / -470 - 1278; /* 25 C = 1278 */ - return IIO_VAL_INT; - } - addrind = 1; - break; - case IIO_CHAN_INFO_PEAK: - addrind = 2; - break; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_TEMP: - *val = -470; /* -0.47 C */ - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_ACCEL: - *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */ - return IIO_VAL_INT_PLUS_MICRO; - case IIO_VOLTAGE: - if (chan->channel == 0) { - *val = 1; - *val2 = 220700; /* 1.2207 mV */ - } else { - /* Should really be dependent on VDD */ - *val2 = 305180; /* 305.18 uV */ - } - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - default: - return -EINVAL; - } - addr = &adis16220_addresses[chan->address][addrind]; - if (addr->sign) { - ret = adis_read_reg_16(&st->adis, addr->addr, &sval); - if (ret) - return ret; - bits = addr->bits; - sval &= (1 << bits) - 1; - sval = (s16)(sval << (16 - bits)) >> (16 - bits); - *val = sval; - return IIO_VAL_INT; - } - ret = adis_read_reg_16(&st->adis, addr->addr, &uval); - if (ret) - return ret; - bits = addr->bits; - uval &= (1 << bits) - 1; - *val = uval; - return IIO_VAL_INT; -} - -static const struct iio_chan_spec adis16220_channels[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .extend_name = "supply", - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE), - .address = in_supply, - }, { - .type = IIO_ACCEL, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_OFFSET) | - BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_PEAK), - .address = accel, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_OFFSET) | - BIT(IIO_CHAN_INFO_SCALE), - .address = temp, - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_OFFSET) | - BIT(IIO_CHAN_INFO_SCALE), - .address = in_1, - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .address = in_2, - } -}; - -static struct attribute *adis16220_attributes[] = { - &iio_dev_attr_capture.dev_attr.attr, - &iio_dev_attr_capture_count.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16220_attribute_group = { - .attrs = adis16220_attributes, -}; - -static const struct iio_info adis16220_info = { - .attrs = &adis16220_attribute_group, - .driver_module = THIS_MODULE, - .read_raw = &adis16220_read_raw, -}; - -static const char * const adis16220_status_error_msgs[] = { - [ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption", - [ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", - [ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", - [ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", - [ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", -}; - -static const struct adis_data adis16220_data = { - .read_delay = 35, - .write_delay = 35, - .msc_ctrl_reg = ADIS16220_MSC_CTRL, - .glob_cmd_reg = ADIS16220_GLOB_CMD, - .diag_stat_reg = ADIS16220_DIAG_STAT, - - .self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN, - .startup_delay = ADIS16220_STARTUP_DELAY, - - .status_error_msgs = adis16220_status_error_msgs, - .status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) | - BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) | - BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) | - BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) | - BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT), -}; - -static int adis16220_probe(struct spi_device *spi) -{ - int ret; - struct adis16220_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adis16220_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = adis16220_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); - - ret = devm_iio_device_register(&spi->dev, indio_dev); - if (ret) - return ret; - - ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin); - if (ret) - return ret; - - ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin); - if (ret) - goto error_rm_accel_bin; - - ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc2_bin); - if (ret) - goto error_rm_adc1_bin; - - ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data); - if (ret) - goto error_rm_adc2_bin; - /* Get the device into a sane initial state */ - ret = adis_initial_startup(&st->adis); - if (ret) - goto error_rm_adc2_bin; - return 0; - -error_rm_adc2_bin: - sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); -error_rm_adc1_bin: - sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); -error_rm_accel_bin: - sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); - return ret; -} - -static int adis16220_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); - sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); - sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); - - return 0; -} - -static struct spi_driver adis16220_driver = { - .driver = { - .name = "adis16220", - }, - .probe = adis16220_probe, - .remove = adis16220_remove, -}; -module_spi_driver(adis16220_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:adis16220"); -- GitLab From 33ea008db7569686310268d60232f284ad213982 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:31 +0800 Subject: [PATCH 0047/9938] ath9k: Update QCA953x initvals commit 14c5932805eb ("ath9k: Update QCA953x initvals") disabled HW peak detect calibartion on QCA953x 1.0, which should also be applied on 2.0. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar953x_initvals.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index c0b90daa3e3d..924ae6bde7f1 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h @@ -988,7 +988,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946220, 0xcf946220}, {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -1008,7 +1008,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, -- GitLab From 137ef139b523a4e5f2582be0f58adbcce9996fe3 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:32 +0800 Subject: [PATCH 0048/9938] ath9k: Update AR9003 2.2 initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index c38399bc9aa9..c07866a2fdf9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -331,7 +331,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -351,7 +351,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- GitLab From 7da1ddddd55fdf478f712643e145e5d343f4ba46 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:33 +0800 Subject: [PATCH 0049/9938] ath9k: Update AR933x initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h | 4 ++-- drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h index 2c42ff05efa3..29479afbc4f1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h @@ -40,7 +40,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, - {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -59,7 +59,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h index 2154efcd3900..c4a6ffa55e8c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h @@ -345,7 +345,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, - {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -364,7 +364,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- GitLab From 7b5c904ddc777f704d794c1e28942b0f35e7db32 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:34 +0800 Subject: [PATCH 0050/9938] ath9k: Update AR9340 initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9340_initvals.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index b995ffe88b33..2eb163fc1c18 100644 --- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h @@ -245,7 +245,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -265,7 +265,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110}, {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00041983, 0x00041983, 0x00041982, 0x00041982}, {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- GitLab From 63a0bc0e6f16e1f25eeb2f730de76ef1b072b876 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:35 +0800 Subject: [PATCH 0051/9938] ath9k: Update AR9462 initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | 4 ++-- drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 1b6b4d0cfa97..b00dd649453d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -59,7 +59,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c780, 0xcfd5c280}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -79,7 +79,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h index dc3adda46e8b..0f8745ec73b1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h @@ -239,7 +239,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c780, 0xcfd5c280}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -259,7 +259,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- GitLab From 93edb3addad8d1648c66b84673a10eb4905a1fb7 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:36 +0800 Subject: [PATCH 0052/9938] ath9k: Update AR9485 initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9485_initvals.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index ce83ce47a1ca..bdf6f107f6f1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -1026,7 +1026,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, {0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0}, @@ -1044,7 +1044,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- GitLab From 836ff650eb4a1505a65bfc0d22ae51d478415e4f Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:37 +0800 Subject: [PATCH 0053/9938] ath9k: Update AR955x initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h index 148562addd38..67edf344b427 100644 --- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h @@ -83,7 +83,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, -- GitLab From f294b096c6cfb89b2d1baac8314a7dc49daab995 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:38 +0800 Subject: [PATCH 0054/9938] ath9k: Update AR9565 initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index 10d4a6cb1c3b..35c1bbb2fa8a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h @@ -347,7 +347,7 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a4, 0x000003a4}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946220, 0xcf946220}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220}, {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, -- GitLab From 628bb7056bfb9156e53e1bcb5486cb15623ee43a Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:39 +0800 Subject: [PATCH 0055/9938] ath9k: Update QCA956x initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar956x_initvals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar956x_initvals.h b/drivers/net/wireless/ath/ath9k/ar956x_initvals.h index c3a47eaaf0c0..db051071c676 100644 --- a/drivers/net/wireless/ath/ath9k/ar956x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar956x_initvals.h @@ -220,7 +220,7 @@ static const u32 qca956x_1p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a6, 0x000003a6}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946220, 0xcf946220}, {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, -- GitLab From fcf5dfda6e520813323559eeaa66ea9f31b10736 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:40 +0800 Subject: [PATCH 0056/9938] ath9k: Update AR9580 initvals HW peak detect calibration would fail for AR9300 chips and we went for implementing the SW way of doing it instead of HW doing the peak detect calibration. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index 5d4629f96c15..f4c9befb3949 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -1290,7 +1290,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = { {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -1310,7 +1310,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- GitLab From 27ae9cd258a84ce7259afbee38dbe7841e723a68 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:41 +0800 Subject: [PATCH 0057/9938] ath9k: enable manual peak cal for all ar9300 chips HW peak detect calibration would fail, enable all ar9300 chips manual peak calibration instead. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 0c391997a2f7..99bc1a6393c6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1641,14 +1641,12 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, skip_tx_iqcal: if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { - if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) || - AR_SREV_9561(ah)) { - for (i = 0; i < AR9300_MAX_CHAINS; i++) { - if (!(ah->rxchainmask & (1 << i))) - continue; - ar9003_hw_manual_peak_cal(ah, i, - IS_CHAN_2GHZ(chan)); - } + for (i = 0; i < AR9300_MAX_CHAINS; i++) { + if (!(ah->rxchainmask & (1 << i))) + continue; + + ar9003_hw_manual_peak_cal(ah, i, + IS_CHAN_2GHZ(chan)); } /* -- GitLab From 9c8ec9951d1e30f1339bcde8d324996412a3586b Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:42 +0800 Subject: [PATCH 0058/9938] ath9k: use AR_SREV_9003_PCOEM to identify PCOEM chips commit f49c90db4d23 ("ath9k: Add a macro to identify PCOEM chips") defined AR_SREV_9003_PCOEM macro, its more clear to use the macro instead of checking one by one. Also removed PCOEM chips checking in the callback of ar9003_hw_do_pcoem_manual_peak_cal() which only for PCOEM chips. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 99bc1a6393c6..e1573ab6a609 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1311,9 +1311,6 @@ static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah, struct ath9k_hw_cal_data *caldata = ah->caldata; int i; - if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah)) - return; - if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal) return; @@ -1707,7 +1704,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah) struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); struct ath_hw_ops *ops = ath9k_hw_ops(ah); - if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah)) + if (AR_SREV_9003_PCOEM(ah)) priv_ops->init_cal = ar9003_hw_init_cal_pcoem; else priv_ops->init_cal = ar9003_hw_init_cal_soc; -- GitLab From 1f64252d0b731d55f262a80f8eef914240334d17 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 26 Feb 2016 16:08:43 +0800 Subject: [PATCH 0059/9938] ath9k: set correct peak detect threshold Set QCA9561 peak detect threshold to 11. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index e1573ab6a609..518e649ecff3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1203,12 +1203,12 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) { int offset[8] = {0}, total = 0, test; - int agc_out, i, peak_detect_threshold; + int agc_out, i, peak_detect_threshold = 0; if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) peak_detect_threshold = 8; - else - peak_detect_threshold = 0; + else if (AR_SREV_9561(ah)) + peak_detect_threshold = 11; /* * Turn off LNA/SW. @@ -1249,17 +1249,14 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); - if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || - AR_SREV_9561(ah)) { - if (is_2g) - REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), - AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, - peak_detect_threshold); - else - REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), - AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, - peak_detect_threshold); - } + if (is_2g) + REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), + AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, + peak_detect_threshold); + else + REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), + AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, + peak_detect_threshold); for (i = 6; i > 0; i--) { offset[i] = BIT(i - 1); -- GitLab From 0eb69ef355c3b77f8ce8f54b61759909ad3abcf8 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Feb 2016 20:07:55 -0500 Subject: [PATCH 0060/9938] ath5k: fix incorrect indentation smatch said: drivers/net/wireless/ath/ath5k/phy.c:1449 ath5k_hw_channel() warn: inconsistent indenting drivers/net/wireless/ath/ath5k/reset.c:637 ath5k_hw_on_hold() warn: inconsistent indenting drivers/net/wireless/ath/ath5k/reset.c:702 ath5k_hw_nic_wakeup() warn: inconsistent indenting All of these lines were indented a tabstop too far. Signed-off-by: Bob Copeland Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath5k/phy.c | 2 +- drivers/net/wireless/ath/ath5k/reset.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 0fce1c76638e..98ee85456321 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1446,7 +1446,7 @@ ath5k_hw_channel(struct ath5k_hw *ah, "channel frequency (%u MHz) out of supported " "band range\n", channel->center_freq); - return -EINVAL; + return -EINVAL; } /* diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 99e62f99a182..4b1c87fa15ac 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -634,7 +634,7 @@ ath5k_hw_on_hold(struct ath5k_hw *ah) ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - usleep_range(2000, 2500); + usleep_range(2000, 2500); } else { ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND | bus_flags); @@ -699,7 +699,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - usleep_range(2000, 2500); + usleep_range(2000, 2500); } else { if (ath5k_get_bus_type(ah) == ATH_AHB) ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | -- GitLab From 1451a3634ff5a443e256eb693627ffb1e34cd337 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Feb 2016 20:07:56 -0500 Subject: [PATCH 0061/9938] ath9k: fix a misleading indentation These lines belong inside the if-statement above, not in the main body of the switch. Found by smatch. Signed-off-by: Bob Copeland Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 06c1ca6e8290..be14a8e01916 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1337,11 +1337,11 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, chan->channel, aniState->mrcCCK ? "on" : "off", is_on ? "on" : "off"); - if (is_on) - ah->stats.ast_ani_ccklow++; - else - ah->stats.ast_ani_cckhigh++; - aniState->mrcCCK = is_on; + if (is_on) + ah->stats.ast_ani_ccklow++; + else + ah->stats.ast_ani_cckhigh++; + aniState->mrcCCK = is_on; } break; } -- GitLab From c8c91b02a8ddb802259b712245ee97f9c3067a7f Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Feb 2016 20:07:57 -0500 Subject: [PATCH 0062/9938] ath9k_htc: fix up indents with spaces Use tabs here. Found by smatch. Signed-off-by: Bob Copeland Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8647ab77c019..c2249ad54085 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -262,11 +262,11 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr, __be32 tmpval[8]; int i, ret; - for (i = 0; i < count; i++) { - tmpaddr[i] = cpu_to_be32(addr[i]); - } + for (i = 0; i < count; i++) { + tmpaddr[i] = cpu_to_be32(addr[i]); + } - ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, + ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, (u8 *)tmpaddr , sizeof(u32) * count, (u8 *)tmpval, sizeof(u32) * count, 100); @@ -275,9 +275,9 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr, "Multiple REGISTER READ FAILED (count: %d)\n", count); } - for (i = 0; i < count; i++) { - val[i] = be32_to_cpu(tmpval[i]); - } + for (i = 0; i < count; i++) { + val[i] = be32_to_cpu(tmpval[i]); + } } static void ath9k_regwrite_multi(struct ath_common *common) -- GitLab From a01ab81b09c55025365c1de1345b941a18e05529 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:14 +0800 Subject: [PATCH 0063/9938] ath9k: define correct GPIO numbers and bits mask Define correct GPIO numbers and MASK bits to indicate the WMAC GPIO resource. Allow SOC chips(AR9340, AR9531, AR9550, AR9561) to access all GPIOs which rely on gpiolib framework. But restrict SOC AR9330 only to access WMAC GPIO which has the same design with the old chips. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hw.c | 70 ++++++++++++++++++++++------ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/reg.h | 42 +++++++++++++++-- 3 files changed, 96 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e7a31016f370..f14242b3213e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2385,6 +2385,61 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah) } } +static void ath9k_gpio_cap_init(struct ath_hw *ah) +{ + struct ath9k_hw_capabilities *pCap = &ah->caps; + + if (AR_SREV_9271(ah)) { + pCap->num_gpio_pins = AR9271_NUM_GPIO; + pCap->gpio_mask = AR9271_GPIO_MASK; + } else if (AR_DEVID_7010(ah)) { + pCap->num_gpio_pins = AR7010_NUM_GPIO; + pCap->gpio_mask = AR7010_GPIO_MASK; + } else if (AR_SREV_9287(ah)) { + pCap->num_gpio_pins = AR9287_NUM_GPIO; + pCap->gpio_mask = AR9287_GPIO_MASK; + } else if (AR_SREV_9285(ah)) { + pCap->num_gpio_pins = AR9285_NUM_GPIO; + pCap->gpio_mask = AR9285_GPIO_MASK; + } else if (AR_SREV_9280(ah)) { + pCap->num_gpio_pins = AR9280_NUM_GPIO; + pCap->gpio_mask = AR9280_GPIO_MASK; + } else if (AR_SREV_9300(ah)) { + pCap->num_gpio_pins = AR9300_NUM_GPIO; + pCap->gpio_mask = AR9300_GPIO_MASK; + } else if (AR_SREV_9330(ah)) { + pCap->num_gpio_pins = AR9330_NUM_GPIO; + pCap->gpio_mask = AR9330_GPIO_MASK; + } else if (AR_SREV_9340(ah)) { + pCap->num_gpio_pins = AR9340_NUM_GPIO; + pCap->gpio_mask = AR9340_GPIO_MASK; + } else if (AR_SREV_9462(ah)) { + pCap->num_gpio_pins = AR9462_NUM_GPIO; + pCap->gpio_mask = AR9462_GPIO_MASK; + } else if (AR_SREV_9485(ah)) { + pCap->num_gpio_pins = AR9485_NUM_GPIO; + pCap->gpio_mask = AR9485_GPIO_MASK; + } else if (AR_SREV_9531(ah)) { + pCap->num_gpio_pins = AR9531_NUM_GPIO; + pCap->gpio_mask = AR9531_GPIO_MASK; + } else if (AR_SREV_9550(ah)) { + pCap->num_gpio_pins = AR9550_NUM_GPIO; + pCap->gpio_mask = AR9550_GPIO_MASK; + } else if (AR_SREV_9561(ah)) { + pCap->num_gpio_pins = AR9561_NUM_GPIO; + pCap->gpio_mask = AR9561_GPIO_MASK; + } else if (AR_SREV_9565(ah)) { + pCap->num_gpio_pins = AR9565_NUM_GPIO; + pCap->gpio_mask = AR9565_GPIO_MASK; + } else if (AR_SREV_9580(ah)) { + pCap->num_gpio_pins = AR9580_NUM_GPIO; + pCap->gpio_mask = AR9580_GPIO_MASK; + } else { + pCap->num_gpio_pins = AR_NUM_GPIO; + pCap->gpio_mask = AR_GPIO_MASK; + } +} + int ath9k_hw_fill_cap_info(struct ath_hw *ah) { struct ath9k_hw_capabilities *pCap = &ah->caps; @@ -2478,20 +2533,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - if (AR_SREV_9271(ah)) - pCap->num_gpio_pins = AR9271_NUM_GPIO; - else if (AR_DEVID_7010(ah)) - pCap->num_gpio_pins = AR7010_NUM_GPIO; - else if (AR_SREV_9300_20_OR_LATER(ah)) - pCap->num_gpio_pins = AR9300_NUM_GPIO; - else if (AR_SREV_9287_11_OR_LATER(ah)) - pCap->num_gpio_pins = AR9287_NUM_GPIO; - else if (AR_SREV_9285_12_OR_LATER(ah)) - pCap->num_gpio_pins = AR9285_NUM_GPIO; - else if (AR_SREV_9280_20_OR_LATER(ah)) - pCap->num_gpio_pins = AR928X_NUM_GPIO; - else - pCap->num_gpio_pins = AR_NUM_GPIO; + ath9k_gpio_cap_init(ah); if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 831a54415a25..c0740d6b3e97 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -301,6 +301,7 @@ struct ath9k_hw_capabilities { u8 max_txchains; u8 max_rxchains; u8 num_gpio_pins; + u32 gpio_mask; u8 rx_hp_qdepth; u8 rx_lp_qdepth; u8 rx_status_len; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index c8d35febaf0f..c06fdb955787 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -985,6 +985,10 @@ #define AR_SREV_9561(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9561)) +#define AR_SREV_SOC(_ah) \ + (AR_SREV_9340(_ah) || AR_SREV_9531(_ah) || AR_SREV_9550(ah) || \ + AR_SREV_9561(ah)) + /* NOTE: When adding chips newer than Peacock, add chip check here */ #define AR_SREV_9580_10_OR_LATER(_ah) \ (AR_SREV_9580(_ah)) @@ -1104,14 +1108,46 @@ enum { #define AR_PCIE_PHY_REG3 0x18c08 +/* Define correct GPIO numbers and MASK bits to indicate the WMAC + * GPIO resource. + * Allow SOC chips(AR9340, AR9531, AR9550, AR9561) to access all GPIOs + * which rely on gpiolib framework. But restrict SOC AR9330 only to + * access WMAC GPIO which has the same design with the old chips. + */ #define AR_NUM_GPIO 14 -#define AR928X_NUM_GPIO 10 +#define AR9280_NUM_GPIO 10 #define AR9285_NUM_GPIO 12 -#define AR9287_NUM_GPIO 11 +#define AR9287_NUM_GPIO 10 #define AR9271_NUM_GPIO 16 -#define AR9300_NUM_GPIO 17 +#define AR9300_NUM_GPIO 16 +#define AR9330_NUM_GPIO 16 +#define AR9340_NUM_GPIO 23 +#define AR9462_NUM_GPIO 10 +#define AR9485_NUM_GPIO 12 +#define AR9531_NUM_GPIO 18 +#define AR9550_NUM_GPIO 24 +#define AR9561_NUM_GPIO 23 +#define AR9565_NUM_GPIO 12 +#define AR9580_NUM_GPIO 16 #define AR7010_NUM_GPIO 16 +#define AR_GPIO_MASK 0x00003FFF +#define AR9271_GPIO_MASK 0x0000FFFF +#define AR9280_GPIO_MASK 0x000003FF +#define AR9285_GPIO_MASK 0x00000FFF +#define AR9287_GPIO_MASK 0x000003FF +#define AR9300_GPIO_MASK 0x0000F4FF +#define AR9330_GPIO_MASK 0x0000F4FF +#define AR9340_GPIO_MASK 0x0000000F +#define AR9462_GPIO_MASK 0x000003FF +#define AR9485_GPIO_MASK 0x00000FFF +#define AR9531_GPIO_MASK 0x0000000F +#define AR9550_GPIO_MASK 0x0000000F +#define AR9561_GPIO_MASK 0x0000000F +#define AR9565_GPIO_MASK 0x00000FFF +#define AR9580_GPIO_MASK 0x0000F4FF +#define AR7010_GPIO_MASK 0x0000FFFF + #define AR_GPIO_IN_OUT (AR_SREV_9340(ah) ? 0x4028 : 0x4048) #define AR_GPIO_IN_VAL 0x0FFFC000 #define AR_GPIO_IN_VAL_S 14 -- GitLab From b2d70d4944c1789bc64376ad97a811f37e230c87 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:15 +0800 Subject: [PATCH 0064/9938] ath9k: make GPIO API to support both of WMAC and SOC commit 61b559dea40e ("ath9k: add extra GPIO led support") added ath9k to support access SOC's GPIOs, but implemented in a separated API: ath9k_hw_request_gpio(). So this patch make the APIs more common, to support both of WMAC and SOC GPIOs. The new APIs as below, void ath9k_hw_gpio_request_in(); void ath9k_hw_gpio_request_out(); void ath9k_hw_gpio_free(); NOTE, the BSP of the SOC chips(AR9340, AR9531, AR9550, AR9561) should set the corresponding MUX registers correctly. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- .../net/wireless/ath/ath9k/ar9003_eeprom.c | 4 +- drivers/net/wireless/ath/ath9k/ar9003_mci.c | 39 ++-- drivers/net/wireless/ath/ath9k/btcoex.c | 27 +-- drivers/net/wireless/ath/ath9k/gpio.c | 6 +- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 6 +- drivers/net/wireless/ath/ath9k/hw.c | 196 +++++++++++------- drivers/net/wireless/ath/ath9k/hw.h | 10 +- drivers/net/wireless/ath/ath9k/main.c | 6 +- 8 files changed, 174 insertions(+), 120 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 54ed2f72d35e..36b602577905 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3590,8 +3590,8 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) else gpio = AR9300_EXT_LNA_CTL_GPIO_AR9485; - ath9k_hw_cfg_output(ah, gpio, - AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED); + ath9k_hw_gpio_request_out(ah, gpio, NULL, + AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED); } value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index af5ee416a560..0fe9c8378249 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c @@ -427,21 +427,34 @@ static void ar9003_mci_observation_set_up(struct ath_hw *ah) struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) { - ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); - ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); - ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); - ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); + ath9k_hw_gpio_request_out(ah, 3, NULL, + AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); + ath9k_hw_gpio_request_out(ah, 2, NULL, + AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); + ath9k_hw_gpio_request_out(ah, 1, NULL, + AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); + ath9k_hw_gpio_request_out(ah, 0, NULL, + AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) { - ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX); - ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX); - ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); - ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); - ath9k_hw_cfg_output(ah, 5, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_gpio_request_out(ah, 3, NULL, + AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX); + ath9k_hw_gpio_request_out(ah, 2, NULL, + AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX); + ath9k_hw_gpio_request_out(ah, 1, NULL, + AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); + ath9k_hw_gpio_request_out(ah, 0, NULL, + AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); + ath9k_hw_gpio_request_out(ah, 5, NULL, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) { - ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); - ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); - ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); - ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); + ath9k_hw_gpio_request_out(ah, 3, NULL, + AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); + ath9k_hw_gpio_request_out(ah, 2, NULL, + AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); + ath9k_hw_gpio_request_out(ah, 1, NULL, + AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); + ath9k_hw_gpio_request_out(ah, 0, NULL, + AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); } else return; diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 5a084d94ed90..7719cb1d8b68 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -142,7 +142,8 @@ void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah) btcoex_hw->btactive_gpio); /* Configure the desired gpio port for input */ - ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio); + ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio, + "ath9k-btactive"); } EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire); @@ -166,9 +167,10 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah) btcoex_hw->btpriority_gpio); /* Configure the desired GPIO ports for input */ - - ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio); - ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btpriority_gpio); + ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio, + "ath9k-btactive"); + ath9k_hw_gpio_request_in(ah, btcoex_hw->btpriority_gpio, + "ath9k-btpriority"); } EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire); @@ -201,8 +203,9 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah) struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; /* Configure the desired GPIO port for TX_FRAME output */ - ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); + ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio, + "ath9k-wlanactive", + AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); } /* @@ -271,7 +274,6 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode); REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2); - if (AR_SREV_9300_20_OR_LATER(ah)) { REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]); REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, btcoex->wlan_weight[1]); @@ -281,8 +283,6 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) } else REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex->bt_coex_weights); - - if (AR_SREV_9271(ah)) { val = REG_READ(ah, 0x50040); val &= 0xFFFFFEFF; @@ -292,8 +292,9 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); - ath9k_hw_cfg_output(ah, btcoex->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); + ath9k_hw_gpio_request_out(ah, btcoex->wlanactive_gpio, + "ath9k-wlanactive", + AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); } static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah) @@ -364,8 +365,8 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) if (!AR_SREV_9300_20_OR_LATER(ah)) ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0); - ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio, + NULL, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 284706798c71..b41dfb7c2784 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -74,7 +74,8 @@ void ath_fill_led_pin(struct ath_softc *sc) if (ah->led_pin >= 0) { if (!((1 << ah->led_pin) & AR_GPIO_OE_OUT_MASK)) - ath9k_hw_request_gpio(ah, ah->led_pin, "ath9k-led"); + ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); return; } @@ -90,7 +91,8 @@ void ath_fill_led_pin(struct ath_softc *sc) ah->led_pin = ATH_LED_PIN_DEF; /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 2aabcbdaba4e..d9b640a2488c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -259,11 +259,11 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv) void ath9k_configure_leds(struct ath9k_htc_priv *priv) { /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_gpio_request_out(priv->ah, priv->ah->led_pin, + "ath9k-led", + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); - } void ath9k_init_leds(struct ath9k_htc_priv *priv) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f14242b3213e..7f39b13a4ca0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1582,7 +1582,8 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) if (!(gpio_mask & 1)) continue; - ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_gpio_request_out(ah, i, NULL, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); } } @@ -1958,7 +1959,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_qos(ah); if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); + ath9k_hw_gpio_request_in(ah, ah->rfkill_gpio, "ath9k-rfkill"); ath9k_hw_init_global_settings(ah); @@ -2654,8 +2655,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) /* GPIO / RFKILL / Antennae */ /****************************/ -static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, - u32 gpio, u32 type) +static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, u32 gpio, u32 type) { int addr; u32 gpio_shift, tmp; @@ -2669,8 +2669,8 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, gpio_shift = (gpio % 6) * 5; - if (AR_SREV_9280_20_OR_LATER(ah) - || (addr != AR_GPIO_OUTPUT_MUX1)) { + if (AR_SREV_9280_20_OR_LATER(ah) || + (addr != AR_GPIO_OUTPUT_MUX1)) { REG_RMW(ah, addr, (type << gpio_shift), (0x1f << gpio_shift)); } else { @@ -2682,106 +2682,144 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, } } -void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) +/* BSP should set the corresponding MUX register correctly. + */ +static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out, + const char *label) { - u32 gpio_shift; + if (ah->caps.gpio_requested & BIT(gpio)) + return; - BUG_ON(gpio >= ah->caps.num_gpio_pins); + /* may be requested by BSP, free anyway */ + gpio_free(gpio); - if (AR_DEVID_7010(ah)) { - gpio_shift = gpio; - REG_RMW(ah, AR7010_GPIO_OE, - (AR7010_GPIO_OE_AS_INPUT << gpio_shift), - (AR7010_GPIO_OE_MASK << gpio_shift)); + if (gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label)) return; - } - gpio_shift = gpio << 1; - REG_RMW(ah, - AR_GPIO_OE_OUT, - (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), - (AR_GPIO_OE_OUT_DRV << gpio_shift)); + ah->caps.gpio_requested |= BIT(gpio); } -EXPORT_SYMBOL(ath9k_hw_cfg_gpio_input); -u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) +static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out, + u32 ah_signal_type) { -#define MS_REG_READ(x, y) \ - (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y))) - - if (gpio >= ah->caps.num_gpio_pins) - return 0xffffffff; + u32 gpio_set, gpio_shift = gpio; if (AR_DEVID_7010(ah)) { - u32 val; - val = REG_READ(ah, AR7010_GPIO_IN); - return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0; - } else if (AR_SREV_9300_20_OR_LATER(ah)) - return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) & - AR_GPIO_BIT(gpio)) != 0; - else if (AR_SREV_9271(ah)) - return MS_REG_READ(AR9271, gpio) != 0; - else if (AR_SREV_9287_11_OR_LATER(ah)) - return MS_REG_READ(AR9287, gpio) != 0; - else if (AR_SREV_9285_12_OR_LATER(ah)) - return MS_REG_READ(AR9285, gpio) != 0; - else if (AR_SREV_9280_20_OR_LATER(ah)) - return MS_REG_READ(AR928X, gpio) != 0; - else - return MS_REG_READ(AR, gpio) != 0; + gpio_set = out ? + AR7010_GPIO_OE_AS_OUTPUT : AR7010_GPIO_OE_AS_INPUT; + REG_RMW(ah, AR7010_GPIO_OE, gpio_set << gpio_shift, + AR7010_GPIO_OE_MASK << gpio_shift); + } else if (AR_SREV_SOC(ah)) { + gpio_set = out ? 1 : 0; + REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift, + gpio_set << gpio_shift); + } else { + gpio_shift = gpio << 1; + gpio_set = out ? + AR_GPIO_OE_OUT_DRV_ALL : AR_GPIO_OE_OUT_DRV_NO; + REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift, + AR_GPIO_OE_OUT_DRV << gpio_shift); + + if (out) + ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); + } } -EXPORT_SYMBOL(ath9k_hw_gpio_get); -void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, - u32 ah_signal_type) +static void ath9k_hw_gpio_request(struct ath_hw *ah, u32 gpio, bool out, + const char *label, u32 ah_signal_type) { - u32 gpio_shift; + WARN_ON(gpio >= ah->caps.num_gpio_pins); - if (AR_DEVID_7010(ah)) { - gpio_shift = gpio; - REG_RMW(ah, AR7010_GPIO_OE, - (AR7010_GPIO_OE_AS_OUTPUT << gpio_shift), - (AR7010_GPIO_OE_MASK << gpio_shift)); - return; - } + if (BIT(gpio) & ah->caps.gpio_mask) + ath9k_hw_gpio_cfg_wmac(ah, gpio, out, ah_signal_type); + else if (AR_SREV_SOC(ah)) + ath9k_hw_gpio_cfg_soc(ah, gpio, out, label); + else + WARN_ON(1); +} - ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); - gpio_shift = 2 * gpio; - REG_RMW(ah, - AR_GPIO_OE_OUT, - (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), - (AR_GPIO_OE_OUT_DRV << gpio_shift)); +void ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label) +{ + ath9k_hw_gpio_request(ah, gpio, false, label, 0); } -EXPORT_SYMBOL(ath9k_hw_cfg_output); +EXPORT_SYMBOL(ath9k_hw_gpio_request_in); -void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) +void ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label, + u32 ah_signal_type) { - if (AR_DEVID_7010(ah)) { - val = val ? 0 : 1; - REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio), - AR_GPIO_BIT(gpio)); + ath9k_hw_gpio_request(ah, gpio, true, label, ah_signal_type); +} +EXPORT_SYMBOL(ath9k_hw_gpio_request_out); + +void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio) +{ + if (!AR_SREV_SOC(ah)) return; + + WARN_ON(gpio >= ah->caps.num_gpio_pins); + + if (ah->caps.gpio_requested & BIT(gpio)) { + gpio_free(gpio); + ah->caps.gpio_requested &= ~BIT(gpio); } +} +EXPORT_SYMBOL(ath9k_hw_gpio_free); - if (AR_SREV_9271(ah)) - val = ~val; +u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) +{ + u32 val = 0xffffffff; - if ((1 << gpio) & AR_GPIO_OE_OUT_MASK) - REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), - AR_GPIO_BIT(gpio)); - else - gpio_set_value(gpio, val & 1); +#define MS_REG_READ(x, y) \ + (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & BIT(y)) + + WARN_ON(gpio >= ah->caps.num_gpio_pins); + + if (BIT(gpio) & ah->caps.gpio_mask) { + if (AR_SREV_9271(ah)) + val = MS_REG_READ(AR9271, gpio); + else if (AR_SREV_9287(ah)) + val = MS_REG_READ(AR9287, gpio); + else if (AR_SREV_9285(ah)) + val = MS_REG_READ(AR9285, gpio); + else if (AR_SREV_9280(ah)) + val = MS_REG_READ(AR928X, gpio); + else if (AR_DEVID_7010(ah)) + val = REG_READ(ah, AR7010_GPIO_IN) & BIT(gpio); + else if (AR_SREV_9300_20_OR_LATER(ah)) + val = REG_READ(ah, AR_GPIO_IN) & BIT(gpio); + else + val = MS_REG_READ(AR, gpio); + } else if (BIT(gpio) & ah->caps.gpio_requested) { + val = gpio_get_value(gpio) & BIT(gpio); + } else { + WARN_ON(1); + } + + return val; } -EXPORT_SYMBOL(ath9k_hw_set_gpio); +EXPORT_SYMBOL(ath9k_hw_gpio_get); -void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label) +void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) { - if (gpio >= ah->caps.num_gpio_pins) - return; + WARN_ON(gpio >= ah->caps.num_gpio_pins); - gpio_request_one(gpio, GPIOF_DIR_OUT | GPIOF_INIT_LOW, label); + if (AR_DEVID_7010(ah) || AR_SREV_9271(ah)) + val = !val; + else + val = !!val; + + if (BIT(gpio) & ah->caps.gpio_mask) { + u32 out_addr = AR_DEVID_7010(ah) ? + AR7010_GPIO_OUT : AR_GPIO_IN_OUT; + + REG_RMW(ah, out_addr, val << gpio, BIT(gpio)); + } else if (BIT(gpio) & ah->caps.gpio_requested) { + gpio_set_value(gpio, val); + } else { + WARN_ON(1); + } } -EXPORT_SYMBOL(ath9k_hw_request_gpio); +EXPORT_SYMBOL(ath9k_hw_set_gpio); void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index c0740d6b3e97..9cbca1229bac 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -160,7 +160,6 @@ #define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA 0x1e #define AR_GPIOD_MASK 0x00001FFF -#define AR_GPIO_BIT(_gpio) (1 << (_gpio)) #define BASE_ACTIVATE_DELAY 100 #define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100) @@ -302,6 +301,7 @@ struct ath9k_hw_capabilities { u8 max_rxchains; u8 num_gpio_pins; u32 gpio_mask; + u32 gpio_requested; u8 rx_hp_qdepth; u8 rx_lp_qdepth; u8 rx_status_len; @@ -1020,12 +1020,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah); u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); /* GPIO / RFKILL / Antennae */ -void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); +void ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label); +void ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label, + u32 ah_signal_type); +void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio); u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); -void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, - u32 ah_signal_type); void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); -void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label); void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); /* General Operation */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3aed43a63f94..a8fcadb2fa84 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -719,10 +719,10 @@ static int ath9k_start(struct ieee80211_hw *hw) ah->reset_power_on = false; if (ah->led_pin >= 0) { - ath9k_hw_cfg_output(ah, ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 1 : 0); + ath9k_hw_gpio_request_out(ah, ah->led_pin, NULL, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } /* @@ -870,7 +870,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) if (ah->led_pin >= 0) { ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1); - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + ath9k_hw_gpio_request_in(ah, ah->led_pin, NULL); } ath_prepare_reset(sc); -- GitLab From db2221901fbded787daed153281ed875de489692 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:16 +0800 Subject: [PATCH 0065/9938] ath9k: free GPIO resource for SOC GPIOs For SOC GPIOs, should call ath9k_hw_gpio_free() to release the GPIO resource. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/btcoex.c | 10 ++++++++++ drivers/net/wireless/ath/ath9k/btcoex.h | 1 + drivers/net/wireless/ath/ath9k/gpio.c | 9 +++++++++ drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 2 ++ drivers/net/wireless/ath/ath9k/hw.c | 1 + 5 files changed, 23 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 7719cb1d8b68..4737aa947f99 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -174,6 +174,16 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire); +void ath9k_hw_btcoex_deinit(struct ath_hw *ah) +{ + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; + + ath9k_hw_gpio_free(ah, btcoex_hw->btactive_gpio); + ath9k_hw_gpio_free(ah, btcoex_hw->btpriority_gpio); + ath9k_hw_gpio_free(ah, btcoex_hw->wlanactive_gpio); +} +EXPORT_SYMBOL(ath9k_hw_btcoex_deinit); + void ath9k_hw_btcoex_init_mci(struct ath_hw *ah) { ah->btcoex_hw.mci.ready = false; diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index cd2f0a2373cb..0f7c4e61ac13 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -123,6 +123,7 @@ struct ath_btcoex_hw { void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah); void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); +void ath9k_hw_btcoex_deinit(struct ath_hw *ah); void ath9k_hw_btcoex_init_mci(struct ath_hw *ah); void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index b41dfb7c2784..4964bb36dad2 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -40,6 +40,8 @@ void ath_deinit_leds(struct ath_softc *sc) ath_led_brightness(&sc->led_cdev, LED_OFF); led_classdev_unregister(&sc->led_cdev); + + ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin); } void ath_init_leds(struct ath_softc *sc) @@ -404,6 +406,13 @@ void ath9k_deinit_btcoex(struct ath_softc *sc) if (ath9k_hw_mci_is_enabled(ah)) ath_mci_cleanup(sc); + else { + enum ath_btcoex_scheme scheme = ath9k_hw_get_btcoex_scheme(ah); + + if (scheme == ATH_BTCOEX_CFG_2WIRE || + scheme == ATH_BTCOEX_CFG_3WIRE) + ath9k_hw_btcoex_deinit(sc->sc_ah); + } } int ath9k_init_btcoex(struct ath_softc *sc) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index d9b640a2488c..ecb848b60725 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -253,6 +253,8 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv) ath9k_led_brightness(&priv->led_cdev, LED_OFF); led_classdev_unregister(&priv->led_cdev); cancel_work_sync(&priv->led_work); + + ath9k_hw_gpio_free(priv->ah, priv->ah->led_pin); } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7f39b13a4ca0..42009065e234 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1585,6 +1585,7 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) ath9k_hw_gpio_request_out(ah, i, NULL, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); + ath9k_hw_gpio_free(ah, i); } } -- GitLab From 79d4db1214a0c7b1818aaf64d0606b17ff1acea7 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:17 +0800 Subject: [PATCH 0066/9938] ath9k: cleanup led_pin initial Make ath_init_leds() and ath_deinit_leds() pairs as the only API to set leds, also removed direction configuration from ath9k_start() and ath9k_stop(). So the initial is more clear now. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 -- drivers/net/wireless/ath/ath9k/gpio.c | 62 ++++++++++++-------------- drivers/net/wireless/ath/ath9k/init.c | 1 - drivers/net/wireless/ath/ath9k/main.c | 9 +--- drivers/net/wireless/ath/ath9k/reg.h | 2 - 5 files changed, 31 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 5294595da5a7..93b3793cce2f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -813,7 +813,6 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size) #ifdef CONFIG_MAC80211_LEDS void ath_init_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc); -void ath_fill_led_pin(struct ath_softc *sc); #else static inline void ath_init_leds(struct ath_softc *sc) { @@ -822,9 +821,6 @@ static inline void ath_init_leds(struct ath_softc *sc) static inline void ath_deinit_leds(struct ath_softc *sc) { } -static inline void ath_fill_led_pin(struct ath_softc *sc) -{ -} #endif /************************/ diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 4964bb36dad2..490f74d9ddf0 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -21,6 +21,33 @@ /********************************/ #ifdef CONFIG_MAC80211_LEDS + +void ath_fill_led_pin(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + + /* Set default led pin if invalid */ + if (ah->led_pin < 0) { + if (AR_SREV_9287(ah)) + ah->led_pin = ATH_LED_PIN_9287; + else if (AR_SREV_9485(ah)) + ah->led_pin = ATH_LED_PIN_9485; + else if (AR_SREV_9300(ah)) + ah->led_pin = ATH_LED_PIN_9300; + else if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + ah->led_pin = ATH_LED_PIN_9462; + else + ah->led_pin = ATH_LED_PIN_DEF; + } + + /* Configure gpio for output */ + ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + + /* LED off, active low */ + ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1); +} + static void ath_led_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { @@ -51,6 +78,8 @@ void ath_init_leds(struct ath_softc *sc) if (AR_SREV_9100(sc->sc_ah)) return; + ath_fill_led_pin(sc); + if (!ath9k_led_blink) sc->led_cdev.default_trigger = ieee80211_get_radio_led_name(sc->hw); @@ -66,39 +95,6 @@ void ath_init_leds(struct ath_softc *sc) sc->led_registered = true; } - -void ath_fill_led_pin(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - if (AR_SREV_9100(ah)) - return; - - if (ah->led_pin >= 0) { - if (!((1 << ah->led_pin) & AR_GPIO_OE_OUT_MASK)) - ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - return; - } - - if (AR_SREV_9287(ah)) - ah->led_pin = ATH_LED_PIN_9287; - else if (AR_SREV_9485(sc->sc_ah)) - ah->led_pin = ATH_LED_PIN_9485; - else if (AR_SREV_9300(sc->sc_ah)) - ah->led_pin = ATH_LED_PIN_9300; - else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah)) - ah->led_pin = ATH_LED_PIN_9462; - else - ah->led_pin = ATH_LED_PIN_DEF; - - /* Configure gpio 1 for output */ - ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - - /* LED off, active low */ - ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1); -} #endif /*******************/ diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d4e0ac946c3a..d986687870af 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -660,7 +660,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, ath9k_cmn_init_crypto(sc->sc_ah); ath9k_init_misc(sc); - ath_fill_led_pin(sc); ath_chanctx_init(sc); ath9k_offchannel_init(sc); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a8fcadb2fa84..50ec4c9a9da7 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -718,12 +718,9 @@ static int ath9k_start(struct ieee80211_hw *hw) if (!ath_complete_reset(sc, false)) ah->reset_power_on = false; - if (ah->led_pin >= 0) { + if (ah->led_pin >= 0) ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 1 : 0); - ath9k_hw_gpio_request_out(ah, ah->led_pin, NULL, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - } /* * Reset key cache to sane defaults (all entries cleared) instead of @@ -867,11 +864,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) spin_lock_bh(&sc->sc_pcu_lock); - if (ah->led_pin >= 0) { + if (ah->led_pin >= 0) ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1); - ath9k_hw_gpio_request_in(ah, ah->led_pin, NULL); - } ath_prepare_reset(sc); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index c06fdb955787..909c6b5f4f7b 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1168,8 +1168,6 @@ enum { #define AR_GPIO_OE_OUT (AR_SREV_9340(ah) ? 0x4030 : \ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)) -#define AR_GPIO_OE_OUT_MASK (AR_SREV_9550_OR_LATER(ah) ? \ - 0x0000000F : 0xFFFFFFFF) #define AR_GPIO_OE_OUT_DRV 0x3 #define AR_GPIO_OE_OUT_DRV_NO 0x0 #define AR_GPIO_OE_OUT_DRV_LOW 0x1 -- GitLab From c8770bcf5cefa8cbfae21c07c4fe3428f5a9d42a Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:18 +0800 Subject: [PATCH 0067/9938] ath9k: Allow platform override BTCoex pin Add new platform data to allow override BTCoex default pin. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/btcoex.c | 45 +++++++++++++++++++------ include/linux/ath9k_platform.h | 4 +++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 4737aa947f99..95a810ba98ac 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -15,6 +15,8 @@ */ #include +#include +#include #include "hw.h" enum ath_bt_mode { @@ -90,6 +92,29 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) } EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw); +static void ath9k_hw_btcoex_pin_init(struct ath_hw *ah, u8 wlanactive_gpio, + u8 btactive_gpio, u8 btpriority_gpio) +{ + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; + struct ath9k_platform_data *pdata = ah->dev->platform_data; + + if (btcoex_hw->scheme != ATH_BTCOEX_CFG_2WIRE && + btcoex_hw->scheme != ATH_BTCOEX_CFG_3WIRE) + return; + + /* bt priority GPIO will be ignored by 2 wire scheme */ + if (pdata && (pdata->bt_active_pin || pdata->bt_priority_pin || + pdata->wlan_active_pin)) { + btcoex_hw->btactive_gpio = pdata->bt_active_pin; + btcoex_hw->wlanactive_gpio = pdata->wlan_active_pin; + btcoex_hw->btpriority_gpio = pdata->bt_priority_pin; + } else { + btcoex_hw->btactive_gpio = btactive_gpio; + btcoex_hw->wlanactive_gpio = wlanactive_gpio; + btcoex_hw->btpriority_gpio = btpriority_gpio; + } +} + void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -107,19 +132,19 @@ void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah) btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI; } else if (AR_SREV_9300_20_OR_LATER(ah)) { btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; - btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; - btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300; - } else if (AR_SREV_9280_20_OR_LATER(ah)) { - btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280; - btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280; - if (AR_SREV_9285(ah)) { + ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9300, + ATH_BTACTIVE_GPIO_9300, + ATH_BTPRIORITY_GPIO_9300); + } else if (AR_SREV_9280_20_OR_LATER(ah)) { + if (AR_SREV_9285(ah)) btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9285; - } else { + else btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; - } + + ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9280, + ATH_BTACTIVE_GPIO_9280, + ATH_BTPRIORITY_GPIO_9285); } } EXPORT_SYMBOL(ath9k_hw_btcoex_init_scheme); diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h index 33eb274cd0e6..e66153d60bd5 100644 --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h @@ -31,6 +31,10 @@ struct ath9k_platform_data { u32 gpio_mask; u32 gpio_val; + u32 bt_active_pin; + u32 bt_priority_pin; + u32 wlan_active_pin; + bool endian_check; bool is_clk_25mhz; bool tx_gain_buffalo; -- GitLab From 668ae0a3e48ac6811f431915b466514bf167e2f4 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:19 +0800 Subject: [PATCH 0068/9938] ath9k: add bits definition of BTCoex MODE2/3 for SOC chips Add bits definition for AR_BT_COEX_MODE2 and AR_BT_COEX_MODE3, which needed by SOC chips (AR9340, AR9531, AR9550, AR9561). Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/reg.h | 46 ++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 909c6b5f4f7b..9272ca90632b 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1892,15 +1892,33 @@ enum { #define AR9300_BT_WGHT 0xcccc4444 -#define AR_BT_COEX_MODE2 0x817c -#define AR_BT_BCN_MISS_THRESH 0x000000ff -#define AR_BT_BCN_MISS_THRESH_S 0 -#define AR_BT_BCN_MISS_CNT 0x0000ff00 -#define AR_BT_BCN_MISS_CNT_S 8 -#define AR_BT_HOLD_RX_CLEAR 0x00010000 -#define AR_BT_HOLD_RX_CLEAR_S 16 -#define AR_BT_DISABLE_BT_ANT 0x00100000 -#define AR_BT_DISABLE_BT_ANT_S 20 +#define AR_BT_COEX_MODE2 0x817c +#define AR_BT_BCN_MISS_THRESH 0x000000ff +#define AR_BT_BCN_MISS_THRESH_S 0 +#define AR_BT_BCN_MISS_CNT 0x0000ff00 +#define AR_BT_BCN_MISS_CNT_S 8 +#define AR_BT_HOLD_RX_CLEAR 0x00010000 +#define AR_BT_HOLD_RX_CLEAR_S 16 +#define AR_BT_PROTECT_BT_AFTER_WAKEUP 0x00080000 +#define AR_BT_PROTECT_BT_AFTER_WAKEUP_S 19 +#define AR_BT_DISABLE_BT_ANT 0x00100000 +#define AR_BT_DISABLE_BT_ANT_S 20 +#define AR_BT_QUIET_2_WIRE 0x00200000 +#define AR_BT_QUIET_2_WIRE_S 21 +#define AR_BT_WL_ACTIVE_MODE 0x00c00000 +#define AR_BT_WL_ACTIVE_MODE_S 22 +#define AR_BT_WL_TXRX_SEPARATE 0x01000000 +#define AR_BT_WL_TXRX_SEPARATE_S 24 +#define AR_BT_RS_DISCARD_EXTEND 0x02000000 +#define AR_BT_RS_DISCARD_EXTEND_S 25 +#define AR_BT_TSF_BT_ACTIVE_CTRL 0x0c000000 +#define AR_BT_TSF_BT_ACTIVE_CTRL_S 26 +#define AR_BT_TSF_BT_PRIORITY_CTRL 0x30000000 +#define AR_BT_TSF_BT_PRIORITY_CTRL_S 28 +#define AR_BT_INTERRUPT_ENABLE 0x40000000 +#define AR_BT_INTERRUPT_ENABLE_S 30 +#define AR_BT_PHY_ERR_BT_COLL_ENABLE 0x80000000 +#define AR_BT_PHY_ERR_BT_COLL_ENABLE_S 31 #define AR_TXSIFS 0x81d0 #define AR_TXSIFS_TIME 0x000000FF @@ -1909,6 +1927,16 @@ enum { #define AR_TXSIFS_ACK_SHIFT 0x00007000 #define AR_TXSIFS_ACK_SHIFT_S 12 +#define AR_BT_COEX_MODE3 0x81d4 +#define AR_BT_WL_ACTIVE_TIME 0x000000ff +#define AR_BT_WL_ACTIVE_TIME_S 0 +#define AR_BT_WL_QC_TIME 0x0000ff00 +#define AR_BT_WL_QC_TIME_S 8 +#define AR_BT_ALLOW_CONCURRENT_ACCESS 0x000f0000 +#define AR_BT_ALLOW_CONCURRENT_ACCESS_S 16 +#define AR_BT_AGC_SATURATION_CNT_ENABLE 0x00100000 +#define AR_BT_AGC_SATURATION_CNT_ENABLE_S 20 + #define AR_TXOP_X 0x81ec #define AR_TXOP_X_VAL 0x000000FF -- GitLab From dfcf02cd2998e2240b2bc7b4f4412578b8070bdb Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:20 +0800 Subject: [PATCH 0069/9938] ath9k: fix BTCoex access invalid registers for SOC chips The registers of AR_GPIO_INPUT_MUX1 and AR_GPIO_PDPU were removed from SOC chips, fix invalid accessing Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/btcoex.c | 27 ++++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 95a810ba98ac..d46cd319d524 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -162,9 +162,10 @@ void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah) AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); /* Set input mux for bt_active to gpio pin */ - REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, - AR_GPIO_INPUT_MUX1_BT_ACTIVE, - btcoex_hw->btactive_gpio); + if (!AR_SREV_SOC(ah)) + REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_ACTIVE, + btcoex_hw->btactive_gpio); /* Configure the desired gpio port for input */ ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio, @@ -183,13 +184,14 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah) /* Set input mux for bt_prority_async and * bt_active_async to GPIO pins */ - REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, - AR_GPIO_INPUT_MUX1_BT_ACTIVE, - btcoex_hw->btactive_gpio); - - REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, - AR_GPIO_INPUT_MUX1_BT_PRIORITY, - btcoex_hw->btpriority_gpio); + if (!AR_SREV_SOC(ah)) { + REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_ACTIVE, + btcoex_hw->btactive_gpio); + REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_PRIORITY, + btcoex_hw->btpriority_gpio); + } /* Configure the desired GPIO ports for input */ ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio, @@ -285,13 +287,13 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, txprio_shift[i-1]); } } + /* Last WLAN weight has to be adjusted wrt tx priority */ if (concur_tx) { btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]); btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type] << txprio_shift[i-1]); } - } EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); @@ -375,7 +377,8 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah) break; } - if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI) { + if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI && + !AR_SREV_SOC(ah)) { REG_RMW(ah, AR_GPIO_PDPU, (0x2 << (btcoex_hw->btactive_gpio * 2)), (0x3 << (btcoex_hw->btactive_gpio * 2))); -- GitLab From c7212b7136ba69efb9785df68b669381cb893920 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 7 Mar 2016 10:38:21 +0800 Subject: [PATCH 0070/9938] ath9k: fix BTCoex configuration for SOC chips Allow to set wl_active_time and wl_qc_time for SOC chips, also adjust bt_time_extend and bt_first_slot_time. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/btcoex.c | 31 ++++++++++++++++++++++--- drivers/net/wireless/ath/ath9k/btcoex.h | 1 + 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index d46cd319d524..618c9df35fc1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -36,6 +36,8 @@ struct ath_btcoex_config { u8 bt_priority_time; u8 bt_first_slot_time; bool bt_hold_rx_clear; + u8 wl_active_time; + u8 wl_qc_time; }; static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX] @@ -67,25 +69,42 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) .bt_priority_time = 2, .bt_first_slot_time = 5, .bt_hold_rx_clear = true, + .wl_active_time = 0x20, + .wl_qc_time = 0x20, }; bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; + u8 time_extend = ath_bt_config.bt_time_extend; + u8 first_slot_time = ath_bt_config.bt_first_slot_time; if (AR_SREV_9300_20_OR_LATER(ah)) rxclear_polarity = !ath_bt_config.bt_rxclear_polarity; + if (AR_SREV_SOC(ah)) { + first_slot_time = 0x1d; + time_extend = 0xa; + + btcoex_hw->bt_coex_mode3 = + SM(ath_bt_config.wl_active_time, AR_BT_WL_ACTIVE_TIME) | + SM(ath_bt_config.wl_qc_time, AR_BT_WL_QC_TIME); + + btcoex_hw->bt_coex_mode2 = + AR_BT_PROTECT_BT_AFTER_WAKEUP | + AR_BT_PHY_ERR_BT_COLL_ENABLE; + } + btcoex_hw->bt_coex_mode = (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | - SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | + SM(time_extend, AR_BT_TIME_EXTEND) | SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | SM(ath_bt_config.bt_mode, AR_BT_MODE) | SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | - SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | + SM(first_slot_time, AR_BT_FIRST_SLOT_TIME) | SM(qnum, AR_BT_QCU_THRESH); - btcoex_hw->bt_coex_mode2 = + btcoex_hw->bt_coex_mode2 |= SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | AR_BT_DISABLE_BT_ANT; @@ -308,9 +327,15 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) * Program coex mode and weight registers to * enable coex 3-wire */ + if (AR_SREV_SOC(ah)) + REG_CLR_BIT(ah, AR_BT_COEX_MODE2, AR_BT_PHY_ERR_BT_COLL_ENABLE); + REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode); REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2); + if (AR_SREV_SOC(ah)) + REG_WRITE(ah, AR_BT_COEX_MODE3, btcoex->bt_coex_mode3); + if (AR_SREV_9300_20_OR_LATER(ah)) { REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]); REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, btcoex->wlan_weight[1]); diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 0f7c4e61ac13..1bdfa8465b92 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -115,6 +115,7 @@ struct ath_btcoex_hw { u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ + u32 bt_coex_mode3; /* Register setting for AR_BT_COEX_MODE3 */ u32 bt_weight[AR9300_NUM_BT_WEIGHTS]; u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; u8 tx_prio[ATH_BTCOEX_STOMP_MAX]; -- GitLab From c9b260a684d0493238433e08fc2ac7865a89aece Mon Sep 17 00:00:00 2001 From: Steve deRosier Date: Mon, 7 Mar 2016 16:58:50 -0800 Subject: [PATCH 0071/9938] ath6kl: ignore WMI_TXE_NOTIFY_EVENTID based on fw capability flags Certain 6004 firmware releases redefine the WMI_TXE_NOTIFY_EVENTID event number and sends the new event frequently. However it doesn't have the tx-err-notify feature and thus this firmware capability flag isn't set on the firmware package. By guarding the processing of this event by the same method we guard the sending of the WMI_SET_TXE_NOTIFY_CMDID command, we can ignore the spurious event that we don't know how to process. Without this change we call cfg80211_cqm_txe_notify() with possibly bad data. Signed-off-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/wmi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index a5e1de75a4a3..0b3e9c0293e0 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -1584,6 +1584,11 @@ static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len, if (len < sizeof(*ev)) return -EINVAL; + if (vif->nw_type != INFRA_NETWORK || + !test_bit(ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, + vif->ar->fw_capabilities)) + return -EOPNOTSUPP; + if (vif->sme_state != SME_CONNECTED) return -ENOTCONN; -- GitLab From 181c007dedacefaaf634b72b1f52c3b0415f87c1 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 8 Mar 2016 11:19:37 +0800 Subject: [PATCH 0072/9938] ath9k: fix reg dump data bus error Changes: - restrict only dump MAC registers - skip the register memory holes Data bus error, epc == 831d4040, ra == 831d403c Oops[#1]: CPU: 0 PID: 1536 Comm: cat Not tainted 3.14.0 #3 task: 82f87840 ti: 82f88000 task.ti: 82f88000 $ 0 : 00000000 00000001 deadc0de 1000fc03 $ 4 : b8100200 00000200 831e0000 80218788 $ 8 : 00000030 00000003 00000001 09524547 $12 : 00000000 810594f4 00000000 3a206d61 $16 : 831dd3c0 00000081 00000a00 c05ff000 $20 : 00005af6 00000200 00071b39 00071139 $24 : 00000001 80217760 $28 : 82f88000 82f89c60 c05ffa00 831d403c Hi : 00000000 Lo : 453c0000 epc : 831d4040 ath_ahb_exit+0x2198/0x2904 [ath9k] Not tainted ra : 831d403c ath_ahb_exit+0x2194/0x2904 [ath9k] Status: 1000fc03 KERNEL EXL IE Cause : 4080801c PrId : 00019374 (MIPS 24Kc) Stack : 00000001 00000000 0000000e 80475c60 0000000e 800a8ebc 00000000 00000000 00000001 00000007 00000000 800a9678 00000000 00000004 00000002 00000010 00000000 00000000 00000000 00000000 80475c60 0000000e 000009ec c05ff000 831dd3c0 00000080 00000a00 c05ff000 00005af6 00000200 00071b39 0007114d c05ff9ec 800a9904 831dd3c0 82f89d10 00000001 81082194 831d8f0c 82f89d14 ... Call Trace: [<831d4040>] ath_ahb_exit+0x2198/0x2904 [ath9k] [<831d403c>] ath_ahb_exit+0x2194/0x2904 [ath9k] Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/debug.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 6de64cface3c..c56e40ff35e5 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -916,10 +916,21 @@ static int open_file_regdump(struct inode *inode, struct file *file) struct ath_softc *sc = inode->i_private; unsigned int len = 0; u8 *buf; - int i; + int i, j = 0; unsigned long num_regs, regdump_len, max_reg_offset; + const struct reg_hole { + u32 start; + u32 end; + } reg_hole_list[] = { + {0x0200, 0x07fc}, + {0x0c00, 0x0ffc}, + {0x2000, 0x3ffc}, + {0x4100, 0x6ffc}, + {0x705c, 0x7ffc}, + {0x0000, 0x0000} + }; - max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x16bd4 : 0xb500; + max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x8800 : 0xb500; num_regs = max_reg_offset / 4 + 1; regdump_len = num_regs * REGDUMP_LINE_SIZE + 1; buf = vmalloc(regdump_len); @@ -927,9 +938,16 @@ static int open_file_regdump(struct inode *inode, struct file *file) return -ENOMEM; ath9k_ps_wakeup(sc); - for (i = 0; i < num_regs; i++) + for (i = 0; i < num_regs; i++) { + if (reg_hole_list[j].start == i << 2) { + i = reg_hole_list[j].end >> 2; + j++; + continue; + } + len += scnprintf(buf + len, regdump_len - len, "0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2)); + } ath9k_ps_restore(sc); file->private_data = buf; -- GitLab From 1e52fefc9b0c481f8ca860e19781720fb5404383 Mon Sep 17 00:00:00 2001 From: Tiberiu Breana Date: Wed, 9 Mar 2016 14:06:14 +0200 Subject: [PATCH 0073/9938] iio: accel: Add support for the h3lis331dl accelerometer This commit adds support for STMicroelectronics h3lis331dl high-g accelerometer. The datasheet for this device can be found here: http://www.st.com/web/en/resource/technical/document/ datasheet/DM00053090.pdf Signed-off-by: Tiberiu Breana Reviewed-by: Denis Ciocca Acked-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/st-sensors.txt | 1 + drivers/iio/accel/Kconfig | 2 +- drivers/iio/accel/st_accel.h | 1 + drivers/iio/accel/st_accel_core.c | 92 +++++++++++++++++++ drivers/iio/accel/st_accel_i2c.c | 4 + 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt index d4b87cc1e446..71b7bdff21cd 100644 --- a/Documentation/devicetree/bindings/iio/st-sensors.txt +++ b/Documentation/devicetree/bindings/iio/st-sensors.txt @@ -37,6 +37,7 @@ Accelerometers: - st,lsm330-accel - st,lsm303agr-accel - st,lis2dh12-accel +- st,h3lis331dl-accel Gyroscopes: - st,l3g4200d-gyro diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index b0d3ecf3318b..7636eec63ea5 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS help Say yes here to build support for STMicroelectronics accelerometers: LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, - LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12. + LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL. This driver can also be built as a module. If so, these modules will be created: diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index 5d4a1897b293..57f83a67948c 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -14,6 +14,7 @@ #include #include +#define H3LIS331DL_DRIVER_NAME "h3lis331dl_accel" #define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel" #define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel" #define LIS3DH_ACCEL_DEV_NAME "lis3dh" diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index a03a1417dd63..fee32e3d7a05 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -39,6 +39,9 @@ #define ST_ACCEL_FS_AVL_6G 6 #define ST_ACCEL_FS_AVL_8G 8 #define ST_ACCEL_FS_AVL_16G 16 +#define ST_ACCEL_FS_AVL_100G 100 +#define ST_ACCEL_FS_AVL_200G 200 +#define ST_ACCEL_FS_AVL_400G 400 /* CUSTOM VALUES FOR SENSOR 1 */ #define ST_ACCEL_1_WAI_EXP 0x33 @@ -181,6 +184,33 @@ #define ST_ACCEL_5_IG1_EN_MASK 0x08 #define ST_ACCEL_5_MULTIREAD_BIT false +/* CUSTOM VALUES FOR SENSOR 6 */ +#define ST_ACCEL_6_WAI_EXP 0x32 +#define ST_ACCEL_6_ODR_ADDR 0x20 +#define ST_ACCEL_6_ODR_MASK 0x18 +#define ST_ACCEL_6_ODR_AVL_50HZ_VAL 0x00 +#define ST_ACCEL_6_ODR_AVL_100HZ_VAL 0x01 +#define ST_ACCEL_6_ODR_AVL_400HZ_VAL 0x02 +#define ST_ACCEL_6_ODR_AVL_1000HZ_VAL 0x03 +#define ST_ACCEL_6_PW_ADDR 0x20 +#define ST_ACCEL_6_PW_MASK 0x20 +#define ST_ACCEL_6_FS_ADDR 0x23 +#define ST_ACCEL_6_FS_MASK 0x30 +#define ST_ACCEL_6_FS_AVL_100_VAL 0x00 +#define ST_ACCEL_6_FS_AVL_200_VAL 0x01 +#define ST_ACCEL_6_FS_AVL_400_VAL 0x03 +#define ST_ACCEL_6_FS_AVL_100_GAIN IIO_G_TO_M_S_2(49000) +#define ST_ACCEL_6_FS_AVL_200_GAIN IIO_G_TO_M_S_2(98000) +#define ST_ACCEL_6_FS_AVL_400_GAIN IIO_G_TO_M_S_2(195000) +#define ST_ACCEL_6_BDU_ADDR 0x23 +#define ST_ACCEL_6_BDU_MASK 0x80 +#define ST_ACCEL_6_DRDY_IRQ_ADDR 0x22 +#define ST_ACCEL_6_DRDY_IRQ_INT1_MASK 0x02 +#define ST_ACCEL_6_DRDY_IRQ_INT2_MASK 0x10 +#define ST_ACCEL_6_IHL_IRQ_ADDR 0x22 +#define ST_ACCEL_6_IHL_IRQ_MASK 0x80 +#define ST_ACCEL_6_MULTIREAD_BIT true + static const struct iio_chan_spec st_accel_8bit_channels[] = { ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), @@ -557,6 +587,68 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, .bootime = 2, /* guess */ }, + { + .wai = ST_ACCEL_6_WAI_EXP, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = H3LIS331DL_DRIVER_NAME, + }, + .ch = (struct iio_chan_spec *)st_accel_12bit_channels, + .odr = { + .addr = ST_ACCEL_6_ODR_ADDR, + .mask = ST_ACCEL_6_ODR_MASK, + .odr_avl = { + { 50, ST_ACCEL_6_ODR_AVL_50HZ_VAL }, + { 100, ST_ACCEL_6_ODR_AVL_100HZ_VAL, }, + { 400, ST_ACCEL_6_ODR_AVL_400HZ_VAL, }, + { 1000, ST_ACCEL_6_ODR_AVL_1000HZ_VAL, }, + }, + }, + .pw = { + .addr = ST_ACCEL_6_PW_ADDR, + .mask = ST_ACCEL_6_PW_MASK, + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = ST_ACCEL_6_FS_ADDR, + .mask = ST_ACCEL_6_FS_MASK, + .fs_avl = { + [0] = { + .num = ST_ACCEL_FS_AVL_100G, + .value = ST_ACCEL_6_FS_AVL_100_VAL, + .gain = ST_ACCEL_6_FS_AVL_100_GAIN, + }, + [1] = { + .num = ST_ACCEL_FS_AVL_200G, + .value = ST_ACCEL_6_FS_AVL_200_VAL, + .gain = ST_ACCEL_6_FS_AVL_200_GAIN, + }, + [2] = { + .num = ST_ACCEL_FS_AVL_400G, + .value = ST_ACCEL_6_FS_AVL_400_VAL, + .gain = ST_ACCEL_6_FS_AVL_400_GAIN, + }, + }, + }, + .bdu = { + .addr = ST_ACCEL_6_BDU_ADDR, + .mask = ST_ACCEL_6_BDU_MASK, + }, + .drdy_irq = { + .addr = ST_ACCEL_6_DRDY_IRQ_ADDR, + .mask_int1 = ST_ACCEL_6_DRDY_IRQ_INT1_MASK, + .mask_int2 = ST_ACCEL_6_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_ACCEL_6_IHL_IRQ_ADDR, + .mask_ihl = ST_ACCEL_6_IHL_IRQ_MASK, + }, + .multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT, + .bootime = 2, + }, }; static int st_accel_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 294a32f89367..7333ee9fb11b 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -76,6 +76,10 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,lis2dh12-accel", .data = LIS2DH12_ACCEL_DEV_NAME, }, + { + .compatible = "st,h3lis331dl-accel", + .data = H3LIS331DL_DRIVER_NAME, + }, {}, }; MODULE_DEVICE_TABLE(of, st_accel_of_match); -- GitLab From e8731180fbf6fd45351b587d67cdc0685ce99a7a Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Wed, 9 Mar 2016 12:01:29 +0100 Subject: [PATCH 0074/9938] iio: mma8452: add support for FXLS8471Q This adds support for Freescale's (now NXP's) FXLS8471Q accelerometer. We use MMA8451Q's configuration because for what the driver supports, FXLS8471Q is the same. Support for FXLS8471Q's features (fast SPI interface and a larger FIFO, among others) can be added to this driver anytime. See it's datasheet for the details: http://cache.nxp.com/files/sensors/doc/data_sheet/FXLS8471Q.pdf Signed-off-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/accel/mma8452.txt | 3 ++- drivers/iio/accel/Kconfig | 3 ++- drivers/iio/accel/mma8452.c | 22 +++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/accel/mma8452.txt b/Documentation/devicetree/bindings/iio/accel/mma8452.txt index 165937e1ac1c..45f5c5c5929c 100644 --- a/Documentation/devicetree/bindings/iio/accel/mma8452.txt +++ b/Documentation/devicetree/bindings/iio/accel/mma8452.txt @@ -1,4 +1,4 @@ -Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC +Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC or FXLS8471Q triaxial accelerometer Required properties: @@ -9,6 +9,7 @@ Required properties: * "fsl,mma8453" * "fsl,mma8652" * "fsl,mma8653" + * "fsl,fxls8471" - reg: the I2C address of the chip diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 7636eec63ea5..e4a758cd7d35 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -143,7 +143,8 @@ config MMA8452 select IIO_TRIGGERED_BUFFER help Say yes here to build support for the following Freescale 3-axis - accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC. + accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC, + FXLS8471Q. To compile this driver as a module, choose M here: the module will be called mma8452. diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 5ca0d169f912..305ed0e37dfb 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -6,6 +6,7 @@ * MMA8453Q (10 bit) * MMA8652FC (12 bit) * MMA8653FC (10 bit) + * FXLS8471Q (14 bit) * * Copyright 2015 Martin Kepplinger * Copyright 2014 Peter Meerwald @@ -92,6 +93,7 @@ #define MMA8453_DEVICE_ID 0x3a #define MMA8652_DEVICE_ID 0x4a #define MMA8653_DEVICE_ID 0x5a +#define FXLS8471_DEVICE_ID 0x6a #define MMA8452_AUTO_SUSPEND_DELAY_MS 2000 @@ -1055,6 +1057,7 @@ enum { mma8453, mma8652, mma8653, + fxls8471, }; static const struct mma_chip_info mma_chip_info_table[] = { @@ -1146,6 +1149,22 @@ static const struct mma_chip_info mma_chip_info_table[] = { .ev_ths_mask = MMA8452_FF_MT_THS_MASK, .ev_count = MMA8452_FF_MT_COUNT, }, + [fxls8471] = { + .chip_id = FXLS8471_DEVICE_ID, + .channels = mma8451_channels, + .num_channels = ARRAY_SIZE(mma8451_channels), + .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} }, + .ev_cfg = MMA8452_TRANSIENT_CFG, + .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE, + .ev_cfg_chan_shift = 1, + .ev_src = MMA8452_TRANSIENT_SRC, + .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE, + .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE, + .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE, + .ev_ths = MMA8452_TRANSIENT_THS, + .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK, + .ev_count = MMA8452_TRANSIENT_COUNT, + }, }; static struct attribute *mma8452_attributes[] = { @@ -1275,6 +1294,7 @@ static const struct of_device_id mma8452_dt_ids[] = { { .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] }, { .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] }, { .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] }, + { .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] }, { } }; MODULE_DEVICE_TABLE(of, mma8452_dt_ids); @@ -1312,6 +1332,7 @@ static int mma8452_probe(struct i2c_client *client, case MMA8453_DEVICE_ID: case MMA8652_DEVICE_ID: case MMA8653_DEVICE_ID: + case FXLS8471_DEVICE_ID: if (ret == data->chip_info->chip_id) break; default: @@ -1518,6 +1539,7 @@ static const struct i2c_device_id mma8452_id[] = { { "mma8453", mma8453 }, { "mma8652", mma8652 }, { "mma8653", mma8653 }, + { "fxls8471", fxls8471 }, { } }; MODULE_DEVICE_TABLE(i2c, mma8452_id); -- GitLab From 08a33805518e7845486f88287e8aace6f8439391 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Wed, 9 Mar 2016 11:30:12 -0800 Subject: [PATCH 0075/9938] iio: core: implement iio_device_{claim|release}_direct_mode() It is often the case that the driver wants to be sure a device stays in direct mode while it is executing a task or series of tasks. To accomplish this today, the driver performs this sequence: 1) take the device state lock, 2) verify it is not in a buffered mode, 3) execute some tasks, and 4) release that lock. This patch introduces a pair of helper functions that simplify these steps and make it more semantically expressive. iio_device_claim_direct_mode() If the device is not in any buffered mode it is guaranteed to stay that way until iio_release_direct_mode() is called. iio_device_release_direct_mode() Release the claim. Device is no longer guaranteed to stay in direct mode. Signed-off-by: Alison Schofield Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 39 +++++++++++++++++++++++++++++++++ include/linux/iio/iio.h | 2 ++ 2 files changed, 41 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 70cb7eb0a75c..2e768bc99f05 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "iio_core.h" #include "iio_core_trigger.h" @@ -1375,6 +1376,44 @@ void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev) } EXPORT_SYMBOL_GPL(devm_iio_device_unregister); +/** + * iio_device_claim_direct_mode - Keep device in direct mode + * @indio_dev: the iio_dev associated with the device + * + * If the device is in direct mode it is guaranteed to stay + * that way until iio_device_release_direct_mode() is called. + * + * Use with iio_device_release_direct_mode() + * + * Returns: 0 on success, -EBUSY on failure + */ +int iio_device_claim_direct_mode(struct iio_dev *indio_dev) +{ + mutex_lock(&indio_dev->mlock); + + if (iio_buffer_enabled(indio_dev)) { + mutex_unlock(&indio_dev->mlock); + return -EBUSY; + } + return 0; +} +EXPORT_SYMBOL_GPL(iio_device_claim_direct_mode); + +/** + * iio_device_release_direct_mode - releases claim on direct mode + * @indio_dev: the iio_dev associated with the device + * + * Release the claim. Device is no longer guaranteed to stay + * in direct mode. + * + * Use with iio_device_claim_direct_mode() + */ +void iio_device_release_direct_mode(struct iio_dev *indio_dev) +{ + mutex_unlock(&indio_dev->mlock); +} +EXPORT_SYMBOL_GPL(iio_device_release_direct_mode); + subsys_initcall(iio_init); module_exit(iio_exit); diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index b2b16772c651..0b2773ada0ba 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -527,6 +527,8 @@ void iio_device_unregister(struct iio_dev *indio_dev); int devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev); void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev); int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); +int iio_device_claim_direct_mode(struct iio_dev *indio_dev); +void iio_device_release_direct_mode(struct iio_dev *indio_dev); extern struct bus_type iio_bus_type; -- GitLab From 1c118b7230a16cb627061de9bd548ed7fdbdad24 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Wed, 9 Mar 2016 11:30:43 -0800 Subject: [PATCH 0076/9938] staging: iio: ad7192: use iio_device_{claim|release}_direct_mode() Replace the code that guarantees the device stays in direct mode with iio_device_{claim|release}_direct_mode() which does same. Signed-off-by: Alison Schofield Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index f843f19cf675..15d965c089ff 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -349,11 +349,9 @@ static ssize_t ad7192_write_frequency(struct device *dev, if (lval == 0) return -EINVAL; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; div = st->mclk / (lval * st->f_order * 1024); if (div < 1 || div > 1023) { @@ -366,7 +364,7 @@ static ssize_t ad7192_write_frequency(struct device *dev, ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); out: - mutex_unlock(&indio_dev->mlock); + iio_device_release_direct_mode(indio_dev); return ret ? ret : len; } @@ -434,11 +432,9 @@ static ssize_t ad7192_set(struct device *dev, if (ret < 0) return ret; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch ((u32)this_attr->address) { case AD7192_REG_GPOCON: @@ -461,7 +457,7 @@ static ssize_t ad7192_set(struct device *dev, ret = -EINVAL; } - mutex_unlock(&indio_dev->mlock); + iio_device_release_direct_mode(indio_dev); return ret ? ret : len; } @@ -555,11 +551,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, int ret, i; unsigned int tmp; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -582,7 +576,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, ret = -EINVAL; } - mutex_unlock(&indio_dev->mlock); + iio_device_release_direct_mode(indio_dev); return ret; } -- GitLab From a583c24deefdaaaf5bd96a1117b850904a294804 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sat, 12 Mar 2016 13:30:14 +0100 Subject: [PATCH 0077/9938] iio: adc: add NXP LPC18xx ADC driver Add base support for the 10-bit SAR ADC peripheral found on NXP LPC18xx/43xx SoCs. This is a minimal driver that does not support burst mode, interrupts, DMA or hardware triggers. User manual with register description can be found on: LPC18xx: www.nxp.com/documents/user_manual/UM10430.pdf LPC43xx: www.nxp.com/documents/user_manual/UM10503.pdf Signed-off-by: Joachim Eastwood Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/lpc18xx_adc.c | 231 ++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 drivers/iio/adc/lpc18xx_adc.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a8819a08a828..9ddcd5db039b 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -235,6 +235,16 @@ config LP8788_ADC To compile this driver as a module, choose M here: the module will be called lp8788_adc. +config LPC18XX_ADC + tristate "NXP LPC18xx ADC driver" + depends on ARCH_LPC18XX || COMPILE_TEST + depends on OF && HAS_IOMEM + help + Say yes here to build support for NXP LPC18XX ADC. + + To compile this driver as a module, choose M here: the module will be + called lpc18xx_adc. + config MAX1027 tristate "Maxim max1027 ADC driver" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index b1aa456e6af3..1a4ac4590857 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_HI8435) += hi8435.o obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o +obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MCP320X) += mcp320x.o diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c new file mode 100644 index 000000000000..3ef18f4b27f0 --- /dev/null +++ b/drivers/iio/adc/lpc18xx_adc.c @@ -0,0 +1,231 @@ +/* + * IIO ADC driver for NXP LPC18xx ADC + * + * Copyright (C) 2016 Joachim Eastwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * UNSUPPORTED hardware features: + * - Hardware triggers + * - Burst mode + * - Interrupts + * - DMA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* LPC18XX ADC registers and bits */ +#define LPC18XX_ADC_CR 0x000 +#define LPC18XX_ADC_CR_CLKDIV_SHIFT 8 +#define LPC18XX_ADC_CR_PDN BIT(21) +#define LPC18XX_ADC_CR_START_NOW (0x1 << 24) +#define LPC18XX_ADC_GDR 0x004 + +/* Data register bits */ +#define LPC18XX_ADC_SAMPLE_SHIFT 6 +#define LPC18XX_ADC_SAMPLE_MASK 0x3ff +#define LPC18XX_ADC_CONV_DONE BIT(31) + +/* Clock should be 4.5 MHz or less */ +#define LPC18XX_ADC_CLK_TARGET 4500000 + +struct lpc18xx_adc { + struct regulator *vref; + void __iomem *base; + struct device *dev; + struct mutex lock; + struct clk *clk; + u32 cr_reg; +}; + +#define LPC18XX_ADC_CHAN(_idx) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _idx, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = { + LPC18XX_ADC_CHAN(0), + LPC18XX_ADC_CHAN(1), + LPC18XX_ADC_CHAN(2), + LPC18XX_ADC_CHAN(3), + LPC18XX_ADC_CHAN(4), + LPC18XX_ADC_CHAN(5), + LPC18XX_ADC_CHAN(6), + LPC18XX_ADC_CHAN(7), +}; + +static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch) +{ + int ret; + u32 reg; + + reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW; + writel(reg, adc->base + LPC18XX_ADC_CR); + + ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg, + reg & LPC18XX_ADC_CONV_DONE, 3, 9); + if (ret) { + dev_warn(adc->dev, "adc read timed out\n"); + return ret; + } + + return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK; +} + +static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct lpc18xx_adc *adc = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&adc->lock); + *val = lpc18xx_adc_read_chan(adc, chan->channel); + mutex_unlock(&adc->lock); + if (*val < 0) + return *val; + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = regulator_get_voltage(adc->vref) / 1000; + *val2 = 10; + + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static const struct iio_info lpc18xx_adc_info = { + .read_raw = lpc18xx_adc_read_raw, + .driver_module = THIS_MODULE, +}; + +static int lpc18xx_adc_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev; + struct lpc18xx_adc *adc; + struct resource *res; + unsigned int clkdiv; + unsigned long rate; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc)); + if (!indio_dev) + return -ENOMEM; + + platform_set_drvdata(pdev, indio_dev); + adc = iio_priv(indio_dev); + adc->dev = &pdev->dev; + mutex_init(&adc->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + adc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(adc->base)) + return PTR_ERR(adc->base); + + adc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(adc->clk)) { + dev_err(&pdev->dev, "error getting clock\n"); + return PTR_ERR(adc->clk); + } + + rate = clk_get_rate(adc->clk); + clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET); + + adc->vref = devm_regulator_get(&pdev->dev, "vref"); + if (IS_ERR(adc->vref)) { + dev_err(&pdev->dev, "error getting regulator\n"); + return PTR_ERR(adc->vref); + } + + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &lpc18xx_adc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = lpc18xx_adc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels); + + ret = regulator_enable(adc->vref); + if (ret) { + dev_err(&pdev->dev, "unable to enable regulator\n"); + return ret; + } + + ret = clk_prepare_enable(adc->clk); + if (ret) { + dev_err(&pdev->dev, "unable to enable clock\n"); + goto dis_reg; + } + + adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) | + LPC18XX_ADC_CR_PDN; + writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "unable to register device\n"); + goto dis_clk; + } + + return 0; + +dis_clk: + writel(0, adc->base + LPC18XX_ADC_CR); + clk_disable_unprepare(adc->clk); +dis_reg: + regulator_disable(adc->vref); + return ret; +} + +static int lpc18xx_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct lpc18xx_adc *adc = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + writel(0, adc->base + LPC18XX_ADC_CR); + clk_disable_unprepare(adc->clk); + regulator_disable(adc->vref); + + return 0; +} + +static const struct of_device_id lpc18xx_adc_match[] = { + { .compatible = "nxp,lpc1850-adc" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lpc18xx_adc_match); + +static struct platform_driver lpc18xx_adc_driver = { + .probe = lpc18xx_adc_probe, + .remove = lpc18xx_adc_remove, + .driver = { + .name = "lpc18xx-adc", + .of_match_table = lpc18xx_adc_match, + }, +}; +module_platform_driver(lpc18xx_adc_driver); + +MODULE_DESCRIPTION("LPC18xx ADC driver"); +MODULE_AUTHOR("Joachim Eastwood "); +MODULE_LICENSE("GPL v2"); -- GitLab From edcb2d26c10206b35a5736139f5dce02fc4bbdc9 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sat, 12 Mar 2016 13:30:15 +0100 Subject: [PATCH 0078/9938] dt: document NXP LPC1850 ADC driver bindings Signed-off-by: Joachim Eastwood Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/lpc1850-adc.txt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt diff --git a/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt b/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt new file mode 100644 index 000000000000..0bcae5140bc5 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt @@ -0,0 +1,21 @@ +NXP LPC1850 ADC bindings + +Required properties: +- compatible: Should be "nxp,lpc1850-adc" +- reg: Offset and length of the register set for the ADC device +- interrupts: The interrupt number for the ADC device +- clocks: The root clock of the ADC controller +- vref-supply: The regulator supply ADC reference voltage +- resets: phandle to reset controller and line specifier + +Example: + +adc0: adc@400e3000 { + compatible = "nxp,lpc1850-adc"; + reg = <0x400e3000 0x1000>; + interrupts = <17>; + clocks = <&ccu1 CLK_APB3_ADC0>; + vref-supply = <®_vdda>; + resets = <&rgu 40>; + status = "disabled"; +}; -- GitLab From 9bbccbe11ab78c74bed9a2bc99943929f49ca565 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sat, 12 Mar 2016 13:30:16 +0100 Subject: [PATCH 0079/9938] iio: dac: add NXP LPC18xx DAC driver Add base support for the 10-bit DAC peripheral found on NXP LPC18xx/43xx SoCs. This is a minimal driver that does not support DMA or interrupts. User manual with register description can be found on: LPC18xx: www.nxp.com/documents/user_manual/UM10430.pdf LPC43xx: www.nxp.com/documents/user_manual/UM10503.pdf Signed-off-by: Joachim Eastwood Signed-off-by: Jonathan Cameron --- drivers/iio/dac/Kconfig | 10 ++ drivers/iio/dac/Makefile | 1 + drivers/iio/dac/lpc18xx_dac.c | 210 ++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 drivers/iio/dac/lpc18xx_dac.c diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index a995139f907c..210db81ca144 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -154,6 +154,16 @@ config AD7303 To compile this driver as module choose M here: the module will be called ad7303. +config LPC18XX_DAC + tristate "NXP LPC18xx DAC driver" + depends on ARCH_LPC18XX || COMPILE_TEST + depends on OF && HAS_IOMEM + help + Say yes here to build support for NXP LPC18XX DAC. + + To compile this driver as a module, choose M here: the module will be + called lpc18xx_dac. + config M62332 tristate "Mitsubishi M62332 DAC driver" depends on I2C diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 67b48429686d..420a15cdaa53 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD7303) += ad7303.o +obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o obj-$(CONFIG_M62332) += m62332.o obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX5821) += max5821.o diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c new file mode 100644 index 000000000000..55d1456a059d --- /dev/null +++ b/drivers/iio/dac/lpc18xx_dac.c @@ -0,0 +1,210 @@ +/* + * IIO DAC driver for NXP LPC18xx DAC + * + * Copyright (C) 2016 Joachim Eastwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * UNSUPPORTED hardware features: + * - Interrupts + * - DMA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* LPC18XX DAC registers and bits */ +#define LPC18XX_DAC_CR 0x000 +#define LPC18XX_DAC_CR_VALUE_SHIFT 6 +#define LPC18XX_DAC_CR_VALUE_MASK 0x3ff +#define LPC18XX_DAC_CR_BIAS BIT(16) +#define LPC18XX_DAC_CTRL 0x004 +#define LPC18XX_DAC_CTRL_DMA_ENA BIT(3) + +struct lpc18xx_dac { + struct regulator *vref; + void __iomem *base; + struct mutex lock; + struct clk *clk; +}; + +static const struct iio_chan_spec lpc18xx_dac_iio_channels[] = { + { + .type = IIO_VOLTAGE, + .output = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static int lpc18xx_dac_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct lpc18xx_dac *dac = iio_priv(indio_dev); + u32 reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + reg = readl(dac->base + LPC18XX_DAC_CR); + *val = reg >> LPC18XX_DAC_CR_VALUE_SHIFT; + *val &= LPC18XX_DAC_CR_VALUE_MASK; + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = regulator_get_voltage(dac->vref) / 1000; + *val2 = 10; + + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static int lpc18xx_dac_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct lpc18xx_dac *dac = iio_priv(indio_dev); + u32 reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val < 0 || val > LPC18XX_DAC_CR_VALUE_MASK) + return -EINVAL; + + reg = LPC18XX_DAC_CR_BIAS; + reg |= val << LPC18XX_DAC_CR_VALUE_SHIFT; + + mutex_lock(&dac->lock); + writel(reg, dac->base + LPC18XX_DAC_CR); + writel(LPC18XX_DAC_CTRL_DMA_ENA, dac->base + LPC18XX_DAC_CTRL); + mutex_unlock(&dac->lock); + + return 0; + } + + return -EINVAL; +} + +static const struct iio_info lpc18xx_dac_info = { + .read_raw = lpc18xx_dac_read_raw, + .write_raw = lpc18xx_dac_write_raw, + .driver_module = THIS_MODULE, +}; + +static int lpc18xx_dac_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev; + struct lpc18xx_dac *dac; + struct resource *res; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*dac)); + if (!indio_dev) + return -ENOMEM; + + platform_set_drvdata(pdev, indio_dev); + dac = iio_priv(indio_dev); + mutex_init(&dac->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dac->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dac->base)) + return PTR_ERR(dac->base); + + dac->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(dac->clk)) { + dev_err(&pdev->dev, "error getting clock\n"); + return PTR_ERR(dac->clk); + } + + dac->vref = devm_regulator_get(&pdev->dev, "vref"); + if (IS_ERR(dac->vref)) { + dev_err(&pdev->dev, "error getting regulator\n"); + return PTR_ERR(dac->vref); + } + + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &lpc18xx_dac_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = lpc18xx_dac_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(lpc18xx_dac_iio_channels); + + ret = regulator_enable(dac->vref); + if (ret) { + dev_err(&pdev->dev, "unable to enable regulator\n"); + return ret; + } + + ret = clk_prepare_enable(dac->clk); + if (ret) { + dev_err(&pdev->dev, "unable to enable clock\n"); + goto dis_reg; + } + + writel(0, dac->base + LPC18XX_DAC_CTRL); + writel(0, dac->base + LPC18XX_DAC_CR); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "unable to register device\n"); + goto dis_clk; + } + + return 0; + +dis_clk: + clk_disable_unprepare(dac->clk); +dis_reg: + regulator_disable(dac->vref); + return ret; +} + +static int lpc18xx_dac_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct lpc18xx_dac *dac = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + writel(0, dac->base + LPC18XX_DAC_CTRL); + clk_disable_unprepare(dac->clk); + regulator_disable(dac->vref); + + return 0; +} + +static const struct of_device_id lpc18xx_dac_match[] = { + { .compatible = "nxp,lpc1850-dac" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lpc18xx_dac_match); + +static struct platform_driver lpc18xx_dac_driver = { + .probe = lpc18xx_dac_probe, + .remove = lpc18xx_dac_remove, + .driver = { + .name = "lpc18xx-dac", + .of_match_table = lpc18xx_dac_match, + }, +}; +module_platform_driver(lpc18xx_dac_driver); + +MODULE_DESCRIPTION("LPC18xx DAC driver"); +MODULE_AUTHOR("Joachim Eastwood "); +MODULE_LICENSE("GPL v2"); -- GitLab From 5bf59bd5e9a5b262110df8c1ea5ad8820d7d524a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 14 Mar 2016 18:20:13 +0530 Subject: [PATCH 0080/9938] regulator: pwm: Prints error number along with detail Prints the error number along with error message when any error occurs. This help on getting the reason of failure quickly from log without any code instrument. Signed-off-by: Laxman Dewangan Cc: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/pwm-regulator.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index 4689d62f4841..f99a6970be29 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -70,7 +70,7 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev, ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period); if (ret) { - dev_err(&rdev->dev, "Failed to configure PWM\n"); + dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); return ret; } @@ -146,13 +146,13 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev, ret = pwm_config(drvdata->pwm, (period / 100) * duty_cycle, period); if (ret) { - dev_err(&rdev->dev, "Failed to configure PWM\n"); + dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); return ret; } ret = pwm_enable(drvdata->pwm); if (ret) { - dev_err(&rdev->dev, "Failed to enable PWM\n"); + dev_err(&rdev->dev, "Failed to enable PWM: %d\n", ret); return ret; } drvdata->volt_uV = min_uV; @@ -200,8 +200,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev, if ((length < sizeof(*duty_cycle_table)) || (length % sizeof(*duty_cycle_table))) { - dev_err(&pdev->dev, - "voltage-table length(%d) is invalid\n", + dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", length); return -EINVAL; } @@ -214,7 +213,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev, (u32 *)duty_cycle_table, length / sizeof(u32)); if (ret) { - dev_err(&pdev->dev, "Failed to read voltage-table\n"); + dev_err(&pdev->dev, "Failed to read voltage-table: %d\n", ret); return ret; } @@ -277,16 +276,18 @@ static int pwm_regulator_probe(struct platform_device *pdev) drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); if (IS_ERR(drvdata->pwm)) { - dev_err(&pdev->dev, "Failed to get PWM\n"); - return PTR_ERR(drvdata->pwm); + ret = PTR_ERR(drvdata->pwm); + dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret); + return ret; } regulator = devm_regulator_register(&pdev->dev, &drvdata->desc, &config); if (IS_ERR(regulator)) { - dev_err(&pdev->dev, "Failed to register regulator %s\n", - drvdata->desc.name); - return PTR_ERR(regulator); + ret = PTR_ERR(regulator); + dev_err(&pdev->dev, "Failed to register regulator %s: %d\n", + drvdata->desc.name, ret); + return ret; } return 0; -- GitLab From 6ad3122a08e3a9c2148873665752e87cf4f393cc Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Mon, 22 Feb 2016 10:40:07 +0100 Subject: [PATCH 0081/9938] flowcache: Avoid OOM condition under preasure We can hit an OOM condition if we are under presure because we can not free the entries in gc_list fast enough. So add a counter for the not yet freed entries in the gc_list and refuse new allocations if the value is too high. Signed-off-by: Steffen Klassert --- include/net/netns/xfrm.h | 1 + net/core/flow.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 730d82ad6ee5..24cd3949a9a4 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -80,6 +80,7 @@ struct netns_xfrm { struct flow_cache flow_cache_global; atomic_t flow_cache_genid; struct list_head flow_cache_gc_list; + atomic_t flow_cache_gc_count; spinlock_t flow_cache_gc_lock; struct work_struct flow_cache_gc_work; struct work_struct flow_cache_flush_work; diff --git a/net/core/flow.c b/net/core/flow.c index 1033725be40b..3937b1b68d5b 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -92,8 +92,11 @@ static void flow_cache_gc_task(struct work_struct *work) list_splice_tail_init(&xfrm->flow_cache_gc_list, &gc_list); spin_unlock_bh(&xfrm->flow_cache_gc_lock); - list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) + list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) { flow_entry_kill(fce, xfrm); + atomic_dec(&xfrm->flow_cache_gc_count); + WARN_ON(atomic_read(&xfrm->flow_cache_gc_count) < 0); + } } static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp, @@ -101,6 +104,7 @@ static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp, struct netns_xfrm *xfrm) { if (deleted) { + atomic_add(deleted, &xfrm->flow_cache_gc_count); fcp->hash_count -= deleted; spin_lock_bh(&xfrm->flow_cache_gc_lock); list_splice_tail(gc_list, &xfrm->flow_cache_gc_list); @@ -232,6 +236,13 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, if (fcp->hash_count > fc->high_watermark) flow_cache_shrink(fc, fcp); + if (fcp->hash_count > 2 * fc->high_watermark || + atomic_read(&net->xfrm.flow_cache_gc_count) > fc->high_watermark) { + atomic_inc(&net->xfrm.flow_cache_genid); + flo = ERR_PTR(-ENOBUFS); + goto ret_object; + } + fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC); if (fle) { fle->net = net; @@ -446,6 +457,7 @@ int flow_cache_init(struct net *net) INIT_WORK(&net->xfrm.flow_cache_gc_work, flow_cache_gc_task); INIT_WORK(&net->xfrm.flow_cache_flush_work, flow_cache_flush_task); mutex_init(&net->xfrm.flow_flush_sem); + atomic_set(&net->xfrm.flow_cache_gc_count, 0); fc->hash_shift = 10; fc->low_watermark = 2 * flow_cache_hash_size(fc); -- GitLab From 215276c0147ef49bc07692ca68bae35a30a64b9a Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Mon, 22 Feb 2016 10:56:45 +0100 Subject: [PATCH 0082/9938] xfrm: Reset encapsulation field of the skb before transformation The inner headers are invalid after a xfrm transformation. So reset the skb encapsulation field to ensure nobody tries to access the inner headers. Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_output.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index ff4a91fcab9f..637387bbaaea 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -99,6 +99,9 @@ static int xfrm_output_one(struct sk_buff *skb, int err) skb_dst_force(skb); + /* Inner headers are invalid now. */ + skb->encapsulation = 0; + err = x->type->output(x, skb); if (err == -EINPROGRESS) goto out; -- GitLab From 8d48794bb3bf7d7e421204a8cc3bd5c95ffc609b Mon Sep 17 00:00:00 2001 From: Mihai Mihalache Date: Wed, 16 Mar 2016 08:21:12 -0700 Subject: [PATCH 0083/9938] regulator: gpio: check return value of of_get_named_gpio At boot time the regulator driver can be initialized before the gpio, in which case the call to of_get_named_gpio will return EPROBE_DEFER. This value is silently passed to regulator_register which will return success, although the gpio is not registered (regulator_ena_gpio_request not called) as the value passed is detected as invalid. The gpio_regulator_probe will therefore succeed win no gpio requested. Signed-off-by: Mihai Mihalache Reviewed-by: Hans Holmberg Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index a8718e98674a..83e89e5d4752 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -162,6 +162,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, of_property_read_u32(np, "startup-delay-us", &config->startup_delay); config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); + if (config->enable_gpio == -EPROBE_DEFER) + return ERR_PTR(-EPROBE_DEFER); /* Fetch GPIOs. - optional property*/ ret = of_gpio_count(np); -- GitLab From 6727f086cfe4ddcc651eb2bf4301abfcf619be06 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 11:39:17 +0000 Subject: [PATCH 0084/9938] clk: bcm2835: pll_off should only update CM_PLL_ANARST bcm2835_pll_off is currently assigning CM_PLL_ANARST to the control register, which may lose the other bits that are currently set by the clock dividers. It also now locks during the read/modify/write cycle of both registers. Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index c74ed3fd496d..adbaa55e939c 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -910,8 +910,14 @@ static void bcm2835_pll_off(struct clk_hw *hw) struct bcm2835_cprman *cprman = pll->cprman; const struct bcm2835_pll_data *data = pll->data; - cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST); - cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN); + spin_lock(&cprman->regs_lock); + cprman_write(cprman, data->cm_ctrl_reg, + cprman_read(cprman, data->cm_ctrl_reg) | + CM_PLL_ANARST); + cprman_write(cprman, data->a2w_ctrl_reg, + cprman_read(cprman, data->a2w_ctrl_reg) | + A2W_PLL_CTRL_PWRDN); + spin_unlock(&cprman->regs_lock); } static int bcm2835_pll_on(struct clk_hw *hw) -- GitLab From ec36a5c6682fdd5328abf15c3c67281bed0241d7 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 11:39:18 +0000 Subject: [PATCH 0085/9938] clk: bcm2835: add locking to pll*_on/off methods Add missing locking to: * bcm2835_pll_divider_on * bcm2835_pll_divider_off to protect the read modify write cycle for the register access protecting both cm_reg and a2w_reg registers. Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index adbaa55e939c..a39f8a7b6410 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1085,10 +1085,12 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw) struct bcm2835_cprman *cprman = divider->cprman; const struct bcm2835_pll_divider_data *data = divider->data; + spin_lock(&cprman->regs_lock); cprman_write(cprman, data->cm_reg, (cprman_read(cprman, data->cm_reg) & ~data->load_mask) | data->hold_mask); cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE); + spin_unlock(&cprman->regs_lock); } static int bcm2835_pll_divider_on(struct clk_hw *hw) @@ -1097,12 +1099,14 @@ static int bcm2835_pll_divider_on(struct clk_hw *hw) struct bcm2835_cprman *cprman = divider->cprman; const struct bcm2835_pll_divider_data *data = divider->data; + spin_lock(&cprman->regs_lock); cprman_write(cprman, data->a2w_reg, cprman_read(cprman, data->a2w_reg) & ~A2W_PLL_CHANNEL_DISABLE); cprman_write(cprman, data->cm_reg, cprman_read(cprman, data->cm_reg) & ~data->hold_mask); + spin_unlock(&cprman->regs_lock); return 0; } -- GitLab From 997f16bd5d2e9b3456027f96fcadfe1e2bf12f4e Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 11:39:20 +0000 Subject: [PATCH 0086/9938] clk: bcm2835: divider value has to be 1 or more Current clamping of a normal divider allows a value < 1 to be valid. A divider of < 1 would actually only be possible if we had a PLL... So this patch clamps the divider to 1. Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index a39f8a7b6410..1fee1fd87cea 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1190,8 +1190,9 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, div += unused_frac_mask + 1; div &= ~unused_frac_mask; - /* Clamp to the limits. */ - div = max(div, unused_frac_mask + 1); + /* clamp to min divider of 1 */ + div = max_t(u32, div, 1 << CM_DIV_FRAC_BITS); + /* clamp to the highest possible fractional divider */ div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1, CM_DIV_FRAC_BITS - data->frac_bits)); -- GitLab From 959ca92a3235fc4b17c1e18483fc390b3d612254 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 11:39:21 +0000 Subject: [PATCH 0087/9938] clk: bcm2835: correctly enable fractional clock support The current driver calculates the clock divider with fractional support enabled. But it does not enable fractional support in the control register itself resulting in an integer only divider, but in clk_set_rate responds back the fractionally divided clock frequency. This patch enables fractional support in the control register whenever there is a fractional bit set in the requested clock divider. Mash clock limits are are also handled for the PWM clock applying the correct divider limits (2 and max_int) applicable to basic fractional divider support (mash order of 1). It also adds locking to protect the read/modify/write cycle of the register modification. Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 45 ++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 1fee1fd87cea..1ee9a3549473 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -51,6 +51,7 @@ #define CM_GNRICCTL 0x000 #define CM_GNRICDIV 0x004 # define CM_DIV_FRAC_BITS 12 +# define CM_DIV_FRAC_MASK GENMASK(CM_DIV_FRAC_BITS - 1, 0) #define CM_VPUCTL 0x008 #define CM_VPUDIV 0x00c @@ -128,6 +129,7 @@ # define CM_GATE BIT(CM_GATE_BIT) # define CM_BUSY BIT(7) # define CM_BUSYD BIT(8) +# define CM_FRAC BIT(9) # define CM_SRC_SHIFT 0 # define CM_SRC_BITS 4 # define CM_SRC_MASK 0xf @@ -644,6 +646,7 @@ struct bcm2835_clock_data { u32 frac_bits; bool is_vpu_clock; + bool is_mash_clock; }; static const char *const bcm2835_clock_per_parents[] = { @@ -825,6 +828,7 @@ static const struct bcm2835_clock_data bcm2835_clock_pwm_data = { .div_reg = CM_PWMDIV, .int_bits = 12, .frac_bits = 12, + .is_mash_clock = true, }; struct bcm2835_pll { @@ -1180,7 +1184,7 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1; u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS; u64 rem; - u32 div; + u32 div, mindiv, maxdiv; rem = do_div(temp, rate); div = temp; @@ -1190,11 +1194,23 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, div += unused_frac_mask + 1; div &= ~unused_frac_mask; - /* clamp to min divider of 1 */ - div = max_t(u32, div, 1 << CM_DIV_FRAC_BITS); - /* clamp to the highest possible fractional divider */ - div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1, - CM_DIV_FRAC_BITS - data->frac_bits)); + /* different clamping limits apply for a mash clock */ + if (data->is_mash_clock) { + /* clamp to min divider of 2 */ + mindiv = 2 << CM_DIV_FRAC_BITS; + /* clamp to the highest possible integer divider */ + maxdiv = (BIT(data->int_bits) - 1) << CM_DIV_FRAC_BITS; + } else { + /* clamp to min divider of 1 */ + mindiv = 1 << CM_DIV_FRAC_BITS; + /* clamp to the highest possible fractional divider */ + maxdiv = GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1, + CM_DIV_FRAC_BITS - data->frac_bits); + } + + /* apply the clamping limits */ + div = max_t(u32, div, mindiv); + div = min_t(u32, div, maxdiv); return div; } @@ -1288,9 +1304,26 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, struct bcm2835_cprman *cprman = clock->cprman; const struct bcm2835_clock_data *data = clock->data; u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false); + u32 ctl; + + spin_lock(&cprman->regs_lock); + + /* + * Setting up frac support + * + * In principle it is recommended to stop/start the clock first, + * but as we set CLK_SET_RATE_GATE during registration of the + * clock this requirement should be take care of by the + * clk-framework. + */ + ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC; + ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0; + cprman_write(cprman, data->ctl_reg, ctl); cprman_write(cprman, data->div_reg, div); + spin_unlock(&cprman->regs_lock); + return 0; } -- GitLab From 6e1e60dacee7b32aef1468ea461b02e4c7a90a45 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 11:39:22 +0000 Subject: [PATCH 0088/9938] clk: bcm2835: clean up coding style issues Fix all the checkpatch complaints for clk-bcm2835.c Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 1ee9a3549473..5e55b4797b36 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -12,9 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** @@ -299,7 +296,7 @@ struct bcm2835_cprman { struct device *dev; void __iomem *regs; - spinlock_t regs_lock; + spinlock_t regs_lock; /* spinlock for all clocks */ const char *osc_name; struct clk_onecell_data onecell; @@ -1328,7 +1325,7 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, } static int bcm2835_clock_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) + struct clk_rate_request *req) { struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); struct clk_hw *parent, *best_parent = NULL; @@ -1386,7 +1383,6 @@ static u8 bcm2835_clock_get_parent(struct clk_hw *hw) return (src & CM_SRC_MASK) >> CM_SRC_SHIFT; } - static const struct clk_ops bcm2835_clock_clk_ops = { .is_prepared = bcm2835_clock_is_on, .prepare = bcm2835_clock_on, -- GitLab From 96bf9c69d5729781018a00f08e2ae395ec3346b4 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 14:20:15 +0000 Subject: [PATCH 0089/9938] clk: bcm2835: expose raw clock-registers via debugfs For debugging purposes under some circumstance it helps to be able to see the actual clock registers. E.g: when looking at the clock divider it is helpful to see what the actual clock divider is. This patch exposes all the clock registers specific to each clock/pll/pll-divider via debugfs. Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Acked-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 101 ++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 5e55b4797b36..b3ab7f8a9688 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -313,6 +314,27 @@ static inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg) return readl(cprman->regs + reg); } +static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base, + struct debugfs_reg32 *regs, size_t nregs, + struct dentry *dentry) +{ + struct dentry *regdump; + struct debugfs_regset32 *regset; + + regset = devm_kzalloc(cprman->dev, sizeof(*regset), GFP_KERNEL); + if (!regset) + return -ENOMEM; + + regset->regs = regs; + regset->nregs = nregs; + regset->base = cprman->regs + base; + + regdump = debugfs_create_regset32("regdump", S_IRUGO, dentry, + regset); + + return regdump ? 0 : -ENOMEM; +} + /* * These are fixed clocks. They're probably not all root clocks and it may * be possible to turn them on and off but until this is mapped out better @@ -1037,6 +1059,36 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, return 0; } +static int bcm2835_pll_debug_init(struct clk_hw *hw, + struct dentry *dentry) +{ + struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw); + struct bcm2835_cprman *cprman = pll->cprman; + const struct bcm2835_pll_data *data = pll->data; + struct debugfs_reg32 *regs; + + regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL); + if (!regs) + return -ENOMEM; + + regs[0].name = "cm_ctrl"; + regs[0].offset = data->cm_ctrl_reg; + regs[1].name = "a2w_ctrl"; + regs[1].offset = data->a2w_ctrl_reg; + regs[2].name = "frac"; + regs[2].offset = data->frac_reg; + regs[3].name = "ana0"; + regs[3].offset = data->ana_reg_base + 0 * 4; + regs[4].name = "ana1"; + regs[4].offset = data->ana_reg_base + 1 * 4; + regs[5].name = "ana2"; + regs[5].offset = data->ana_reg_base + 2 * 4; + regs[6].name = "ana3"; + regs[6].offset = data->ana_reg_base + 3 * 4; + + return bcm2835_debugfs_regset(cprman, 0, regs, 7, dentry); +} + static const struct clk_ops bcm2835_pll_clk_ops = { .is_prepared = bcm2835_pll_is_on, .prepare = bcm2835_pll_on, @@ -1044,6 +1096,7 @@ static const struct clk_ops bcm2835_pll_clk_ops = { .recalc_rate = bcm2835_pll_get_rate, .set_rate = bcm2835_pll_set_rate, .round_rate = bcm2835_pll_round_rate, + .debug_init = bcm2835_pll_debug_init, }; struct bcm2835_pll_divider { @@ -1135,6 +1188,26 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw, return 0; } +static int bcm2835_pll_divider_debug_init(struct clk_hw *hw, + struct dentry *dentry) +{ + struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw); + struct bcm2835_cprman *cprman = divider->cprman; + const struct bcm2835_pll_divider_data *data = divider->data; + struct debugfs_reg32 *regs; + + regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL); + if (!regs) + return -ENOMEM; + + regs[0].name = "cm"; + regs[0].offset = data->cm_reg; + regs[1].name = "a2w"; + regs[1].offset = data->a2w_reg; + + return bcm2835_debugfs_regset(cprman, 0, regs, 2, dentry); +} + static const struct clk_ops bcm2835_pll_divider_clk_ops = { .is_prepared = bcm2835_pll_divider_is_on, .prepare = bcm2835_pll_divider_on, @@ -1142,6 +1215,7 @@ static const struct clk_ops bcm2835_pll_divider_clk_ops = { .recalc_rate = bcm2835_pll_divider_get_rate, .set_rate = bcm2835_pll_divider_set_rate, .round_rate = bcm2835_pll_divider_round_rate, + .debug_init = bcm2835_pll_divider_debug_init, }; /* @@ -1383,6 +1457,31 @@ static u8 bcm2835_clock_get_parent(struct clk_hw *hw) return (src & CM_SRC_MASK) >> CM_SRC_SHIFT; } +static struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = { + { + .name = "ctl", + .offset = 0, + }, + { + .name = "div", + .offset = 4, + }, +}; + +static int bcm2835_clock_debug_init(struct clk_hw *hw, + struct dentry *dentry) +{ + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; + const struct bcm2835_clock_data *data = clock->data; + + return bcm2835_debugfs_regset( + cprman, data->ctl_reg, + bcm2835_debugfs_clock_reg32, + ARRAY_SIZE(bcm2835_debugfs_clock_reg32), + dentry); +} + static const struct clk_ops bcm2835_clock_clk_ops = { .is_prepared = bcm2835_clock_is_on, .prepare = bcm2835_clock_on, @@ -1392,6 +1491,7 @@ static const struct clk_ops bcm2835_clock_clk_ops = { .determine_rate = bcm2835_clock_determine_rate, .set_parent = bcm2835_clock_set_parent, .get_parent = bcm2835_clock_get_parent, + .debug_init = bcm2835_clock_debug_init, }; static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) @@ -1410,6 +1510,7 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = { .determine_rate = bcm2835_clock_determine_rate, .set_parent = bcm2835_clock_set_parent, .get_parent = bcm2835_clock_get_parent, + .debug_init = bcm2835_clock_debug_init, }; static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman, -- GitLab From 56eb3a2ed9726961e1bcfa69d4a3f86d68f0eb52 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 12:51:41 +0000 Subject: [PATCH 0090/9938] clk: bcm2835: remove use of BCM2835_CLOCK_COUNT in driver As the use of BCM2835_CLOCK_COUNT in include/dt-bindings/clock/bcm2835.h is frowned upon as it needs to get modified every time a new clock gets introduced this patch changes the clk-bcm2835 driver to use a different scheme for registration of clocks and pll, so that there is no more need for BCM2835_CLOCK_COUNT to be defined. Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 167 ++++++++++++++++------------ include/dt-bindings/clock/bcm2835.h | 2 - 2 files changed, 94 insertions(+), 75 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index b3ab7f8a9688..71504a81cb0c 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -301,7 +301,7 @@ struct bcm2835_cprman { const char *osc_name; struct clk_onecell_data onecell; - struct clk *clks[BCM2835_CLOCK_COUNT]; + struct clk *clks[]; }; static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val) @@ -850,6 +850,25 @@ static const struct bcm2835_clock_data bcm2835_clock_pwm_data = { .is_mash_clock = true, }; +struct bcm2835_gate_data { + const char *name; + const char *parent; + + u32 ctl_reg; +}; + +/* + * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if + * you have the debug bit set in the power manager, which we + * don't bother exposing) are individual gates off of the + * non-stop vpu clock. + */ +static const struct bcm2835_gate_data bcm2835_clock_peri_image_data = { + .name = "peri_image", + .parent = "vpu", + .ctl_reg = CM_PERIICTL, +}; + struct bcm2835_pll { struct clk_hw hw; struct bcm2835_cprman *cprman; @@ -1642,14 +1661,81 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, return devm_clk_register(cprman->dev, &clock->hw); } +static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman, + const struct bcm2835_gate_data *data) +{ + return clk_register_gate(cprman->dev, data->name, data->parent, + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, + cprman->regs + data->ctl_reg, + CM_GATE_BIT, 0, &cprman->regs_lock); +} + +typedef struct clk *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman, + const void *data); +struct bcm2835_clk_desc { + bcm2835_clk_register clk_register; + const void *data; +}; + +#define _REGISTER(f, d) { .clk_register = (bcm2835_clk_register)f, \ + .data = d } +#define REGISTER_PLL(d) _REGISTER(&bcm2835_register_pll, d) +#define REGISTER_PLL_DIV(d) _REGISTER(&bcm2835_register_pll_divider, d) +#define REGISTER_CLK(d) _REGISTER(&bcm2835_register_clock, d) +#define REGISTER_GATE(d) _REGISTER(&bcm2835_register_gate, d) + +static const struct bcm2835_clk_desc clk_desc_array[] = { + /* register PLL */ + [BCM2835_PLLA] = REGISTER_PLL(&bcm2835_plla_data), + [BCM2835_PLLB] = REGISTER_PLL(&bcm2835_pllb_data), + [BCM2835_PLLC] = REGISTER_PLL(&bcm2835_pllc_data), + [BCM2835_PLLD] = REGISTER_PLL(&bcm2835_plld_data), + [BCM2835_PLLH] = REGISTER_PLL(&bcm2835_pllh_data), + /* the PLL dividers */ + [BCM2835_PLLA_CORE] = REGISTER_PLL_DIV(&bcm2835_plla_core_data), + [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(&bcm2835_plla_per_data), + [BCM2835_PLLC_CORE0] = REGISTER_PLL_DIV(&bcm2835_pllc_core0_data), + [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV(&bcm2835_pllc_core1_data), + [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV(&bcm2835_pllc_core2_data), + [BCM2835_PLLC_PER] = REGISTER_PLL_DIV(&bcm2835_pllc_per_data), + [BCM2835_PLLD_CORE] = REGISTER_PLL_DIV(&bcm2835_plld_core_data), + [BCM2835_PLLD_PER] = REGISTER_PLL_DIV(&bcm2835_plld_per_data), + [BCM2835_PLLH_RCAL] = REGISTER_PLL_DIV(&bcm2835_pllh_rcal_data), + [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV(&bcm2835_pllh_aux_data), + [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(&bcm2835_pllh_pix_data), + /* the clocks */ + [BCM2835_CLOCK_TIMER] = REGISTER_CLK(&bcm2835_clock_timer_data), + [BCM2835_CLOCK_OTP] = REGISTER_CLK(&bcm2835_clock_otp_data), + [BCM2835_CLOCK_TSENS] = REGISTER_CLK(&bcm2835_clock_tsens_data), + [BCM2835_CLOCK_VPU] = REGISTER_CLK(&bcm2835_clock_vpu_data), + [BCM2835_CLOCK_V3D] = REGISTER_CLK(&bcm2835_clock_v3d_data), + [BCM2835_CLOCK_ISP] = REGISTER_CLK(&bcm2835_clock_isp_data), + [BCM2835_CLOCK_H264] = REGISTER_CLK(&bcm2835_clock_h264_data), + [BCM2835_CLOCK_V3D] = REGISTER_CLK(&bcm2835_clock_v3d_data), + [BCM2835_CLOCK_SDRAM] = REGISTER_CLK(&bcm2835_clock_sdram_data), + [BCM2835_CLOCK_UART] = REGISTER_CLK(&bcm2835_clock_uart_data), + [BCM2835_CLOCK_VEC] = REGISTER_CLK(&bcm2835_clock_vec_data), + [BCM2835_CLOCK_HSM] = REGISTER_CLK(&bcm2835_clock_hsm_data), + [BCM2835_CLOCK_EMMC] = REGISTER_CLK(&bcm2835_clock_emmc_data), + [BCM2835_CLOCK_PWM] = REGISTER_CLK(&bcm2835_clock_pwm_data), + /* the gates */ + [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE( + &bcm2835_clock_peri_image_data), +}; + static int bcm2835_clk_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct clk **clks; struct bcm2835_cprman *cprman; struct resource *res; + const struct bcm2835_clk_desc *desc; + const size_t asize = ARRAY_SIZE(clk_desc_array); + size_t i; - cprman = devm_kzalloc(dev, sizeof(*cprman), GFP_KERNEL); + cprman = devm_kzalloc(dev, + sizeof(*cprman) + asize * sizeof(*clks), + GFP_KERNEL); if (!cprman) return -ENOMEM; @@ -1666,80 +1752,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cprman); - cprman->onecell.clk_num = BCM2835_CLOCK_COUNT; + cprman->onecell.clk_num = asize; cprman->onecell.clks = cprman->clks; clks = cprman->clks; - clks[BCM2835_PLLA] = bcm2835_register_pll(cprman, &bcm2835_plla_data); - clks[BCM2835_PLLB] = bcm2835_register_pll(cprman, &bcm2835_pllb_data); - clks[BCM2835_PLLC] = bcm2835_register_pll(cprman, &bcm2835_pllc_data); - clks[BCM2835_PLLD] = bcm2835_register_pll(cprman, &bcm2835_plld_data); - clks[BCM2835_PLLH] = bcm2835_register_pll(cprman, &bcm2835_pllh_data); - - clks[BCM2835_PLLA_CORE] = - bcm2835_register_pll_divider(cprman, &bcm2835_plla_core_data); - clks[BCM2835_PLLA_PER] = - bcm2835_register_pll_divider(cprman, &bcm2835_plla_per_data); - clks[BCM2835_PLLC_CORE0] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core0_data); - clks[BCM2835_PLLC_CORE1] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core1_data); - clks[BCM2835_PLLC_CORE2] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core2_data); - clks[BCM2835_PLLC_PER] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_per_data); - clks[BCM2835_PLLD_CORE] = - bcm2835_register_pll_divider(cprman, &bcm2835_plld_core_data); - clks[BCM2835_PLLD_PER] = - bcm2835_register_pll_divider(cprman, &bcm2835_plld_per_data); - clks[BCM2835_PLLH_RCAL] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllh_rcal_data); - clks[BCM2835_PLLH_AUX] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllh_aux_data); - clks[BCM2835_PLLH_PIX] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllh_pix_data); - - clks[BCM2835_CLOCK_TIMER] = - bcm2835_register_clock(cprman, &bcm2835_clock_timer_data); - clks[BCM2835_CLOCK_OTP] = - bcm2835_register_clock(cprman, &bcm2835_clock_otp_data); - clks[BCM2835_CLOCK_TSENS] = - bcm2835_register_clock(cprman, &bcm2835_clock_tsens_data); - clks[BCM2835_CLOCK_VPU] = - bcm2835_register_clock(cprman, &bcm2835_clock_vpu_data); - clks[BCM2835_CLOCK_V3D] = - bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data); - clks[BCM2835_CLOCK_ISP] = - bcm2835_register_clock(cprman, &bcm2835_clock_isp_data); - clks[BCM2835_CLOCK_H264] = - bcm2835_register_clock(cprman, &bcm2835_clock_h264_data); - clks[BCM2835_CLOCK_V3D] = - bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data); - clks[BCM2835_CLOCK_SDRAM] = - bcm2835_register_clock(cprman, &bcm2835_clock_sdram_data); - clks[BCM2835_CLOCK_UART] = - bcm2835_register_clock(cprman, &bcm2835_clock_uart_data); - clks[BCM2835_CLOCK_VEC] = - bcm2835_register_clock(cprman, &bcm2835_clock_vec_data); - clks[BCM2835_CLOCK_HSM] = - bcm2835_register_clock(cprman, &bcm2835_clock_hsm_data); - clks[BCM2835_CLOCK_EMMC] = - bcm2835_register_clock(cprman, &bcm2835_clock_emmc_data); - - /* - * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if - * you have the debug bit set in the power manager, which we - * don't bother exposing) are individual gates off of the - * non-stop vpu clock. - */ - clks[BCM2835_CLOCK_PERI_IMAGE] = - clk_register_gate(dev, "peri_image", "vpu", - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, - cprman->regs + CM_PERIICTL, CM_GATE_BIT, - 0, &cprman->regs_lock); - - clks[BCM2835_CLOCK_PWM] = - bcm2835_register_clock(cprman, &bcm2835_clock_pwm_data); + for (i = 0; i < asize; i++) { + desc = &clk_desc_array[i]; + if (desc->clk_register && desc->data) + clks[i] = desc->clk_register(cprman, desc->data); + } return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &cprman->onecell); diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h index 61f1d20c2a67..87235ac76ef1 100644 --- a/include/dt-bindings/clock/bcm2835.h +++ b/include/dt-bindings/clock/bcm2835.h @@ -44,5 +44,3 @@ #define BCM2835_CLOCK_EMMC 28 #define BCM2835_CLOCK_PERI_IMAGE 29 #define BCM2835_CLOCK_PWM 30 - -#define BCM2835_CLOCK_COUNT 31 -- GitLab From 3b15afefbef9b5952e3d68ad73d93f981b9faca8 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 12:51:42 +0000 Subject: [PATCH 0091/9938] clk: bcm2835: reorganize bcm2835_clock_array assignment Reorganize bcm2835_clock_array so that there is no more need for separate bcm2835_*_data structures to be defined. Instead the required structures are generated inline via helper macros. To allow this to also work for pll alone it was required that the parent_pll was changed from a pointer to bcm2835_pll_data to the name of the pll instead. Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 852 ++++++++++++++++------------------ 1 file changed, 393 insertions(+), 459 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 71504a81cb0c..a4b91a4233af 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -415,115 +415,10 @@ static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = { .fb_prediv_mask = BIT(11), }; -/* - * PLLA is the auxiliary PLL, used to drive the CCP2 (Compact Camera - * Port 2) transmitter clock. - * - * It is in the PX LDO power domain, which is on when the AUDIO domain - * is on. - */ -static const struct bcm2835_pll_data bcm2835_plla_data = { - .name = "plla", - .cm_ctrl_reg = CM_PLLA, - .a2w_ctrl_reg = A2W_PLLA_CTRL, - .frac_reg = A2W_PLLA_FRAC, - .ana_reg_base = A2W_PLLA_ANA0, - .reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE, - .lock_mask = CM_LOCK_FLOCKA, - - .ana = &bcm2835_ana_default, - - .min_rate = 600000000u, - .max_rate = 2400000000u, - .max_fb_rate = BCM2835_MAX_FB_RATE, -}; - -/* PLLB is used for the ARM's clock. */ -static const struct bcm2835_pll_data bcm2835_pllb_data = { - .name = "pllb", - .cm_ctrl_reg = CM_PLLB, - .a2w_ctrl_reg = A2W_PLLB_CTRL, - .frac_reg = A2W_PLLB_FRAC, - .ana_reg_base = A2W_PLLB_ANA0, - .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE, - .lock_mask = CM_LOCK_FLOCKB, - - .ana = &bcm2835_ana_default, - - .min_rate = 600000000u, - .max_rate = 3000000000u, - .max_fb_rate = BCM2835_MAX_FB_RATE, -}; - -/* - * PLLC is the core PLL, used to drive the core VPU clock. - * - * It is in the PX LDO power domain, which is on when the AUDIO domain - * is on. -*/ -static const struct bcm2835_pll_data bcm2835_pllc_data = { - .name = "pllc", - .cm_ctrl_reg = CM_PLLC, - .a2w_ctrl_reg = A2W_PLLC_CTRL, - .frac_reg = A2W_PLLC_FRAC, - .ana_reg_base = A2W_PLLC_ANA0, - .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, - .lock_mask = CM_LOCK_FLOCKC, - - .ana = &bcm2835_ana_default, - - .min_rate = 600000000u, - .max_rate = 3000000000u, - .max_fb_rate = BCM2835_MAX_FB_RATE, -}; - -/* - * PLLD is the display PLL, used to drive DSI display panels. - * - * It is in the PX LDO power domain, which is on when the AUDIO domain - * is on. - */ -static const struct bcm2835_pll_data bcm2835_plld_data = { - .name = "plld", - .cm_ctrl_reg = CM_PLLD, - .a2w_ctrl_reg = A2W_PLLD_CTRL, - .frac_reg = A2W_PLLD_FRAC, - .ana_reg_base = A2W_PLLD_ANA0, - .reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE, - .lock_mask = CM_LOCK_FLOCKD, - - .ana = &bcm2835_ana_default, - - .min_rate = 600000000u, - .max_rate = 2400000000u, - .max_fb_rate = BCM2835_MAX_FB_RATE, -}; - -/* - * PLLH is used to supply the pixel clock or the AUX clock for the TV - * encoder. - * - * It is in the HDMI power domain. - */ -static const struct bcm2835_pll_data bcm2835_pllh_data = { - "pllh", - .cm_ctrl_reg = CM_PLLH, - .a2w_ctrl_reg = A2W_PLLH_CTRL, - .frac_reg = A2W_PLLH_FRAC, - .ana_reg_base = A2W_PLLH_ANA0, - .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, - .lock_mask = CM_LOCK_FLOCKH, - - .ana = &bcm2835_ana_pllh, - - .min_rate = 600000000u, - .max_rate = 3000000000u, - .max_fb_rate = BCM2835_MAX_FB_RATE, -}; - struct bcm2835_pll_divider_data { const char *name; - const struct bcm2835_pll_data *source_pll; + const char *source_pll; + u32 cm_reg; u32 a2w_reg; @@ -532,124 +427,6 @@ struct bcm2835_pll_divider_data { u32 fixed_divider; }; -static const struct bcm2835_pll_divider_data bcm2835_plla_core_data = { - .name = "plla_core", - .source_pll = &bcm2835_plla_data, - .cm_reg = CM_PLLA, - .a2w_reg = A2W_PLLA_CORE, - .load_mask = CM_PLLA_LOADCORE, - .hold_mask = CM_PLLA_HOLDCORE, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_plla_per_data = { - .name = "plla_per", - .source_pll = &bcm2835_plla_data, - .cm_reg = CM_PLLA, - .a2w_reg = A2W_PLLA_PER, - .load_mask = CM_PLLA_LOADPER, - .hold_mask = CM_PLLA_HOLDPER, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllb_arm_data = { - .name = "pllb_arm", - .source_pll = &bcm2835_pllb_data, - .cm_reg = CM_PLLB, - .a2w_reg = A2W_PLLB_ARM, - .load_mask = CM_PLLB_LOADARM, - .hold_mask = CM_PLLB_HOLDARM, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllc_core0_data = { - .name = "pllc_core0", - .source_pll = &bcm2835_pllc_data, - .cm_reg = CM_PLLC, - .a2w_reg = A2W_PLLC_CORE0, - .load_mask = CM_PLLC_LOADCORE0, - .hold_mask = CM_PLLC_HOLDCORE0, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllc_core1_data = { - .name = "pllc_core1", .source_pll = &bcm2835_pllc_data, - .cm_reg = CM_PLLC, A2W_PLLC_CORE1, - .load_mask = CM_PLLC_LOADCORE1, - .hold_mask = CM_PLLC_HOLDCORE1, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllc_core2_data = { - .name = "pllc_core2", - .source_pll = &bcm2835_pllc_data, - .cm_reg = CM_PLLC, - .a2w_reg = A2W_PLLC_CORE2, - .load_mask = CM_PLLC_LOADCORE2, - .hold_mask = CM_PLLC_HOLDCORE2, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllc_per_data = { - .name = "pllc_per", - .source_pll = &bcm2835_pllc_data, - .cm_reg = CM_PLLC, - .a2w_reg = A2W_PLLC_PER, - .load_mask = CM_PLLC_LOADPER, - .hold_mask = CM_PLLC_HOLDPER, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_plld_core_data = { - .name = "plld_core", - .source_pll = &bcm2835_plld_data, - .cm_reg = CM_PLLD, - .a2w_reg = A2W_PLLD_CORE, - .load_mask = CM_PLLD_LOADCORE, - .hold_mask = CM_PLLD_HOLDCORE, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_plld_per_data = { - .name = "plld_per", - .source_pll = &bcm2835_plld_data, - .cm_reg = CM_PLLD, - .a2w_reg = A2W_PLLD_PER, - .load_mask = CM_PLLD_LOADPER, - .hold_mask = CM_PLLD_HOLDPER, - .fixed_divider = 1, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllh_rcal_data = { - .name = "pllh_rcal", - .source_pll = &bcm2835_pllh_data, - .cm_reg = CM_PLLH, - .a2w_reg = A2W_PLLH_RCAL, - .load_mask = CM_PLLH_LOADRCAL, - .hold_mask = 0, - .fixed_divider = 10, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllh_aux_data = { - .name = "pllh_aux", - .source_pll = &bcm2835_pllh_data, - .cm_reg = CM_PLLH, - .a2w_reg = A2W_PLLH_AUX, - .load_mask = CM_PLLH_LOADAUX, - .hold_mask = 0, - .fixed_divider = 10, -}; - -static const struct bcm2835_pll_divider_data bcm2835_pllh_pix_data = { - .name = "pllh_pix", - .source_pll = &bcm2835_pllh_data, - .cm_reg = CM_PLLH, - .a2w_reg = A2W_PLLH_PIX, - .load_mask = CM_PLLH_LOADPIX, - .hold_mask = 0, - .fixed_divider = 10, -}; - struct bcm2835_clock_data { const char *name; @@ -668,188 +445,6 @@ struct bcm2835_clock_data { bool is_mash_clock; }; -static const char *const bcm2835_clock_per_parents[] = { - "gnd", - "xosc", - "testdebug0", - "testdebug1", - "plla_per", - "pllc_per", - "plld_per", - "pllh_aux", -}; - -static const char *const bcm2835_clock_vpu_parents[] = { - "gnd", - "xosc", - "testdebug0", - "testdebug1", - "plla_core", - "pllc_core0", - "plld_core", - "pllh_aux", - "pllc_core1", - "pllc_core2", -}; - -static const char *const bcm2835_clock_osc_parents[] = { - "gnd", - "xosc", - "testdebug0", - "testdebug1" -}; - -/* - * Used for a 1Mhz clock for the system clocksource, and also used by - * the watchdog timer and the camera pulse generator. - */ -static const struct bcm2835_clock_data bcm2835_clock_timer_data = { - .name = "timer", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), - .parents = bcm2835_clock_osc_parents, - .ctl_reg = CM_TIMERCTL, - .div_reg = CM_TIMERDIV, - .int_bits = 6, - .frac_bits = 12, -}; - -/* One Time Programmable Memory clock. Maximum 10Mhz. */ -static const struct bcm2835_clock_data bcm2835_clock_otp_data = { - .name = "otp", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), - .parents = bcm2835_clock_osc_parents, - .ctl_reg = CM_OTPCTL, - .div_reg = CM_OTPDIV, - .int_bits = 4, - .frac_bits = 0, -}; - -/* - * VPU clock. This doesn't have an enable bit, since it drives the - * bus for everything else, and is special so it doesn't need to be - * gated for rate changes. It is also known as "clk_audio" in various - * hardware documentation. - */ -static const struct bcm2835_clock_data bcm2835_clock_vpu_data = { - .name = "vpu", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), - .parents = bcm2835_clock_vpu_parents, - .ctl_reg = CM_VPUCTL, - .div_reg = CM_VPUDIV, - .int_bits = 12, - .frac_bits = 8, - .is_vpu_clock = true, -}; - -static const struct bcm2835_clock_data bcm2835_clock_v3d_data = { - .name = "v3d", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), - .parents = bcm2835_clock_vpu_parents, - .ctl_reg = CM_V3DCTL, - .div_reg = CM_V3DDIV, - .int_bits = 4, - .frac_bits = 8, -}; - -static const struct bcm2835_clock_data bcm2835_clock_isp_data = { - .name = "isp", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), - .parents = bcm2835_clock_vpu_parents, - .ctl_reg = CM_ISPCTL, - .div_reg = CM_ISPDIV, - .int_bits = 4, - .frac_bits = 8, -}; - -static const struct bcm2835_clock_data bcm2835_clock_h264_data = { - .name = "h264", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), - .parents = bcm2835_clock_vpu_parents, - .ctl_reg = CM_H264CTL, - .div_reg = CM_H264DIV, - .int_bits = 4, - .frac_bits = 8, -}; - -/* TV encoder clock. Only operating frequency is 108Mhz. */ -static const struct bcm2835_clock_data bcm2835_clock_vec_data = { - .name = "vec", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), - .parents = bcm2835_clock_per_parents, - .ctl_reg = CM_VECCTL, - .div_reg = CM_VECDIV, - .int_bits = 4, - .frac_bits = 0, -}; - -static const struct bcm2835_clock_data bcm2835_clock_uart_data = { - .name = "uart", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), - .parents = bcm2835_clock_per_parents, - .ctl_reg = CM_UARTCTL, - .div_reg = CM_UARTDIV, - .int_bits = 10, - .frac_bits = 12, -}; - -/* HDMI state machine */ -static const struct bcm2835_clock_data bcm2835_clock_hsm_data = { - .name = "hsm", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), - .parents = bcm2835_clock_per_parents, - .ctl_reg = CM_HSMCTL, - .div_reg = CM_HSMDIV, - .int_bits = 4, - .frac_bits = 8, -}; - -/* - * Secondary SDRAM clock. Used for low-voltage modes when the PLL in - * the SDRAM controller can't be used. - */ -static const struct bcm2835_clock_data bcm2835_clock_sdram_data = { - .name = "sdram", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), - .parents = bcm2835_clock_vpu_parents, - .ctl_reg = CM_SDCCTL, - .div_reg = CM_SDCDIV, - .int_bits = 6, - .frac_bits = 0, -}; - -/* Clock for the temperature sensor. Generally run at 2Mhz, max 5Mhz. */ -static const struct bcm2835_clock_data bcm2835_clock_tsens_data = { - .name = "tsens", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), - .parents = bcm2835_clock_osc_parents, - .ctl_reg = CM_TSENSCTL, - .div_reg = CM_TSENSDIV, - .int_bits = 5, - .frac_bits = 0, -}; - -/* Arasan EMMC clock */ -static const struct bcm2835_clock_data bcm2835_clock_emmc_data = { - .name = "emmc", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), - .parents = bcm2835_clock_per_parents, - .ctl_reg = CM_EMMCCTL, - .div_reg = CM_EMMCDIV, - .int_bits = 4, - .frac_bits = 8, -}; - -static const struct bcm2835_clock_data bcm2835_clock_pwm_data = { - .name = "pwm", - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), - .parents = bcm2835_clock_per_parents, - .ctl_reg = CM_PWMCTL, - .div_reg = CM_PWMDIV, - .int_bits = 12, - .frac_bits = 12, - .is_mash_clock = true, -}; - struct bcm2835_gate_data { const char *name; const char *parent; @@ -857,18 +452,6 @@ struct bcm2835_gate_data { u32 ctl_reg; }; -/* - * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if - * you have the debug bit set in the power manager, which we - * don't bother exposing) are individual gates off of the - * non-stop vpu clock. - */ -static const struct bcm2835_gate_data bcm2835_clock_peri_image_data = { - .name = "peri_image", - .parent = "vpu", - .ctl_reg = CM_PERIICTL, -}; - struct bcm2835_pll { struct clk_hw hw; struct bcm2835_cprman *cprman; @@ -1578,7 +1161,7 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, memset(&init, 0, sizeof(init)); - init.parent_names = &data->source_pll->name; + init.parent_names = &data->source_pll; init.num_parents = 1; init.name = divider_name; init.ops = &bcm2835_pll_divider_clk_ops; @@ -1677,50 +1260,401 @@ struct bcm2835_clk_desc { const void *data; }; -#define _REGISTER(f, d) { .clk_register = (bcm2835_clk_register)f, \ - .data = d } -#define REGISTER_PLL(d) _REGISTER(&bcm2835_register_pll, d) -#define REGISTER_PLL_DIV(d) _REGISTER(&bcm2835_register_pll_divider, d) -#define REGISTER_CLK(d) _REGISTER(&bcm2835_register_clock, d) -#define REGISTER_GATE(d) _REGISTER(&bcm2835_register_gate, d) +/* assignment helper macros for different clock types */ +#define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \ + .data = __VA_ARGS__ } +#define REGISTER_PLL(...) _REGISTER(&bcm2835_register_pll, \ + &(struct bcm2835_pll_data) \ + {__VA_ARGS__}) +#define REGISTER_PLL_DIV(...) _REGISTER(&bcm2835_register_pll_divider, \ + &(struct bcm2835_pll_divider_data) \ + {__VA_ARGS__}) +#define REGISTER_CLK(...) _REGISTER(&bcm2835_register_clock, \ + &(struct bcm2835_clock_data) \ + {__VA_ARGS__}) +#define REGISTER_GATE(...) _REGISTER(&bcm2835_register_gate, \ + &(struct bcm2835_gate_data) \ + {__VA_ARGS__}) + +/* parent mux arrays plus helper macros */ + +/* main oscillator parent mux */ +static const char *const bcm2835_clock_osc_parents[] = { + "gnd", + "xosc", + "testdebug0", + "testdebug1" +}; + +#define REGISTER_OSC_CLK(...) REGISTER_CLK( \ + .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), \ + .parents = bcm2835_clock_osc_parents, \ + __VA_ARGS__) + +/* main peripherial parent mux */ +static const char *const bcm2835_clock_per_parents[] = { + "gnd", + "xosc", + "testdebug0", + "testdebug1", + "plla_per", + "pllc_per", + "plld_per", + "pllh_aux", +}; + +#define REGISTER_PER_CLK(...) REGISTER_CLK( \ + .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), \ + .parents = bcm2835_clock_per_parents, \ + __VA_ARGS__) +/* main vpu parent mux */ +static const char *const bcm2835_clock_vpu_parents[] = { + "gnd", + "xosc", + "testdebug0", + "testdebug1", + "plla_core", + "pllc_core0", + "plld_core", + "pllh_aux", + "pllc_core1", + "pllc_core2", +}; + +#define REGISTER_VPU_CLK(...) REGISTER_CLK( \ + .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), \ + .parents = bcm2835_clock_vpu_parents, \ + __VA_ARGS__) + +/* + * the real definition of all the pll, pll_dividers and clocks + * these make use of the above REGISTER_* macros + */ static const struct bcm2835_clk_desc clk_desc_array[] = { - /* register PLL */ - [BCM2835_PLLA] = REGISTER_PLL(&bcm2835_plla_data), - [BCM2835_PLLB] = REGISTER_PLL(&bcm2835_pllb_data), - [BCM2835_PLLC] = REGISTER_PLL(&bcm2835_pllc_data), - [BCM2835_PLLD] = REGISTER_PLL(&bcm2835_plld_data), - [BCM2835_PLLH] = REGISTER_PLL(&bcm2835_pllh_data), - /* the PLL dividers */ - [BCM2835_PLLA_CORE] = REGISTER_PLL_DIV(&bcm2835_plla_core_data), - [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(&bcm2835_plla_per_data), - [BCM2835_PLLC_CORE0] = REGISTER_PLL_DIV(&bcm2835_pllc_core0_data), - [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV(&bcm2835_pllc_core1_data), - [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV(&bcm2835_pllc_core2_data), - [BCM2835_PLLC_PER] = REGISTER_PLL_DIV(&bcm2835_pllc_per_data), - [BCM2835_PLLD_CORE] = REGISTER_PLL_DIV(&bcm2835_plld_core_data), - [BCM2835_PLLD_PER] = REGISTER_PLL_DIV(&bcm2835_plld_per_data), - [BCM2835_PLLH_RCAL] = REGISTER_PLL_DIV(&bcm2835_pllh_rcal_data), - [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV(&bcm2835_pllh_aux_data), - [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(&bcm2835_pllh_pix_data), + /* the PLL + PLL dividers */ + + /* + * PLLA is the auxiliary PLL, used to drive the CCP2 + * (Compact Camera Port 2) transmitter clock. + * + * It is in the PX LDO power domain, which is on when the + * AUDIO domain is on. + */ + [BCM2835_PLLA] = REGISTER_PLL( + .name = "plla", + .cm_ctrl_reg = CM_PLLA, + .a2w_ctrl_reg = A2W_PLLA_CTRL, + .frac_reg = A2W_PLLA_FRAC, + .ana_reg_base = A2W_PLLA_ANA0, + .reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE, + .lock_mask = CM_LOCK_FLOCKA, + + .ana = &bcm2835_ana_default, + + .min_rate = 600000000u, + .max_rate = 2400000000u, + .max_fb_rate = BCM2835_MAX_FB_RATE), + [BCM2835_PLLA_CORE] = REGISTER_PLL_DIV( + .name = "plla_core", + .source_pll = "plla", + .cm_reg = CM_PLLA, + .a2w_reg = A2W_PLLA_CORE, + .load_mask = CM_PLLA_LOADCORE, + .hold_mask = CM_PLLA_HOLDCORE, + .fixed_divider = 1), + [BCM2835_PLLA_PER] = REGISTER_PLL_DIV( + .name = "plla_per", + .source_pll = "plla", + .cm_reg = CM_PLLA, + .a2w_reg = A2W_PLLA_PER, + .load_mask = CM_PLLA_LOADPER, + .hold_mask = CM_PLLA_HOLDPER, + .fixed_divider = 1), + + /* PLLB is used for the ARM's clock. */ + [BCM2835_PLLB] = REGISTER_PLL( + .name = "pllb", + .cm_ctrl_reg = CM_PLLB, + .a2w_ctrl_reg = A2W_PLLB_CTRL, + .frac_reg = A2W_PLLB_FRAC, + .ana_reg_base = A2W_PLLB_ANA0, + .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE, + .lock_mask = CM_LOCK_FLOCKB, + + .ana = &bcm2835_ana_default, + + .min_rate = 600000000u, + .max_rate = 3000000000u, + .max_fb_rate = BCM2835_MAX_FB_RATE), + [BCM2835_PLLB_ARM] = REGISTER_PLL_DIV( + .name = "pllb_arm", + .source_pll = "pllb", + .cm_reg = CM_PLLB, + .a2w_reg = A2W_PLLB_ARM, + .load_mask = CM_PLLB_LOADARM, + .hold_mask = CM_PLLB_HOLDARM, + .fixed_divider = 1), + + /* + * PLLC is the core PLL, used to drive the core VPU clock. + * + * It is in the PX LDO power domain, which is on when the + * AUDIO domain is on. + */ + [BCM2835_PLLC] = REGISTER_PLL( + .name = "pllc", + .cm_ctrl_reg = CM_PLLC, + .a2w_ctrl_reg = A2W_PLLC_CTRL, + .frac_reg = A2W_PLLC_FRAC, + .ana_reg_base = A2W_PLLC_ANA0, + .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, + .lock_mask = CM_LOCK_FLOCKC, + + .ana = &bcm2835_ana_default, + + .min_rate = 600000000u, + .max_rate = 3000000000u, + .max_fb_rate = BCM2835_MAX_FB_RATE), + [BCM2835_PLLC_CORE0] = REGISTER_PLL_DIV( + .name = "pllc_core0", + .source_pll = "pllc", + .cm_reg = CM_PLLC, + .a2w_reg = A2W_PLLC_CORE0, + .load_mask = CM_PLLC_LOADCORE0, + .hold_mask = CM_PLLC_HOLDCORE0, + .fixed_divider = 1), + [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV( + .name = "pllc_core1", + .source_pll = "pllc", + .cm_reg = CM_PLLC, + .a2w_reg = A2W_PLLC_CORE1, + .load_mask = CM_PLLC_LOADCORE1, + .hold_mask = CM_PLLC_HOLDCORE1, + .fixed_divider = 1), + [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV( + .name = "pllc_core2", + .source_pll = "pllc", + .cm_reg = CM_PLLC, + .a2w_reg = A2W_PLLC_CORE2, + .load_mask = CM_PLLC_LOADCORE2, + .hold_mask = CM_PLLC_HOLDCORE2, + .fixed_divider = 1), + [BCM2835_PLLC_PER] = REGISTER_PLL_DIV( + .name = "pllc_per", + .source_pll = "pllc", + .cm_reg = CM_PLLC, + .a2w_reg = A2W_PLLC_PER, + .load_mask = CM_PLLC_LOADPER, + .hold_mask = CM_PLLC_HOLDPER, + .fixed_divider = 1), + + /* + * PLLD is the display PLL, used to drive DSI display panels. + * + * It is in the PX LDO power domain, which is on when the + * AUDIO domain is on. + */ + [BCM2835_PLLD] = REGISTER_PLL( + .name = "plld", + .cm_ctrl_reg = CM_PLLD, + .a2w_ctrl_reg = A2W_PLLD_CTRL, + .frac_reg = A2W_PLLD_FRAC, + .ana_reg_base = A2W_PLLD_ANA0, + .reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE, + .lock_mask = CM_LOCK_FLOCKD, + + .ana = &bcm2835_ana_default, + + .min_rate = 600000000u, + .max_rate = 2400000000u, + .max_fb_rate = BCM2835_MAX_FB_RATE), + [BCM2835_PLLD_CORE] = REGISTER_PLL_DIV( + .name = "plld_core", + .source_pll = "plld", + .cm_reg = CM_PLLD, + .a2w_reg = A2W_PLLD_CORE, + .load_mask = CM_PLLD_LOADCORE, + .hold_mask = CM_PLLD_HOLDCORE, + .fixed_divider = 1), + [BCM2835_PLLD_PER] = REGISTER_PLL_DIV( + .name = "plld_per", + .source_pll = "plld", + .cm_reg = CM_PLLD, + .a2w_reg = A2W_PLLD_PER, + .load_mask = CM_PLLD_LOADPER, + .hold_mask = CM_PLLD_HOLDPER, + .fixed_divider = 1), + + /* + * PLLH is used to supply the pixel clock or the AUX clock for the + * TV encoder. + * + * It is in the HDMI power domain. + */ + [BCM2835_PLLH] = REGISTER_PLL( + "pllh", + .cm_ctrl_reg = CM_PLLH, + .a2w_ctrl_reg = A2W_PLLH_CTRL, + .frac_reg = A2W_PLLH_FRAC, + .ana_reg_base = A2W_PLLH_ANA0, + .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, + .lock_mask = CM_LOCK_FLOCKH, + + .ana = &bcm2835_ana_pllh, + + .min_rate = 600000000u, + .max_rate = 3000000000u, + .max_fb_rate = BCM2835_MAX_FB_RATE), + [BCM2835_PLLH_RCAL] = REGISTER_PLL_DIV( + .name = "pllh_rcal", + .source_pll = "pllh", + .cm_reg = CM_PLLH, + .a2w_reg = A2W_PLLH_RCAL, + .load_mask = CM_PLLH_LOADRCAL, + .hold_mask = 0, + .fixed_divider = 10), + [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV( + .name = "pllh_aux", + .source_pll = "pllh", + .cm_reg = CM_PLLH, + .a2w_reg = A2W_PLLH_AUX, + .load_mask = CM_PLLH_LOADAUX, + .hold_mask = 0, + .fixed_divider = 10), + [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV( + .name = "pllh_pix", + .source_pll = "pllh", + .cm_reg = CM_PLLH, + .a2w_reg = A2W_PLLH_PIX, + .load_mask = CM_PLLH_LOADPIX, + .hold_mask = 0, + .fixed_divider = 10), + /* the clocks */ - [BCM2835_CLOCK_TIMER] = REGISTER_CLK(&bcm2835_clock_timer_data), - [BCM2835_CLOCK_OTP] = REGISTER_CLK(&bcm2835_clock_otp_data), - [BCM2835_CLOCK_TSENS] = REGISTER_CLK(&bcm2835_clock_tsens_data), - [BCM2835_CLOCK_VPU] = REGISTER_CLK(&bcm2835_clock_vpu_data), - [BCM2835_CLOCK_V3D] = REGISTER_CLK(&bcm2835_clock_v3d_data), - [BCM2835_CLOCK_ISP] = REGISTER_CLK(&bcm2835_clock_isp_data), - [BCM2835_CLOCK_H264] = REGISTER_CLK(&bcm2835_clock_h264_data), - [BCM2835_CLOCK_V3D] = REGISTER_CLK(&bcm2835_clock_v3d_data), - [BCM2835_CLOCK_SDRAM] = REGISTER_CLK(&bcm2835_clock_sdram_data), - [BCM2835_CLOCK_UART] = REGISTER_CLK(&bcm2835_clock_uart_data), - [BCM2835_CLOCK_VEC] = REGISTER_CLK(&bcm2835_clock_vec_data), - [BCM2835_CLOCK_HSM] = REGISTER_CLK(&bcm2835_clock_hsm_data), - [BCM2835_CLOCK_EMMC] = REGISTER_CLK(&bcm2835_clock_emmc_data), - [BCM2835_CLOCK_PWM] = REGISTER_CLK(&bcm2835_clock_pwm_data), + + /* clocks with oscillator parent mux */ + + /* One Time Programmable Memory clock. Maximum 10Mhz. */ + [BCM2835_CLOCK_OTP] = REGISTER_OSC_CLK( + .name = "otp", + .ctl_reg = CM_OTPCTL, + .div_reg = CM_OTPDIV, + .int_bits = 4, + .frac_bits = 0), + /* + * Used for a 1Mhz clock for the system clocksource, and also used + * bythe watchdog timer and the camera pulse generator. + */ + [BCM2835_CLOCK_TIMER] = REGISTER_OSC_CLK( + .name = "timer", + .ctl_reg = CM_TIMERCTL, + .div_reg = CM_TIMERDIV, + .int_bits = 6, + .frac_bits = 12), + /* + * Clock for the temperature sensor. + * Generally run at 2Mhz, max 5Mhz. + */ + [BCM2835_CLOCK_TSENS] = REGISTER_OSC_CLK( + .name = "tsens", + .ctl_reg = CM_TSENSCTL, + .div_reg = CM_TSENSDIV, + .int_bits = 5, + .frac_bits = 0), + + /* clocks with vpu parent mux */ + [BCM2835_CLOCK_H264] = REGISTER_VPU_CLK( + .name = "h264", + .ctl_reg = CM_H264CTL, + .div_reg = CM_H264DIV, + .int_bits = 4, + .frac_bits = 8), + [BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK( + .name = "isp", + .ctl_reg = CM_ISPCTL, + .div_reg = CM_ISPDIV, + .int_bits = 4, + .frac_bits = 8), + /* + * Secondary SDRAM clock. Used for low-voltage modes when the PLL + * in the SDRAM controller can't be used. + */ + [BCM2835_CLOCK_SDRAM] = REGISTER_VPU_CLK( + .name = "sdram", + .ctl_reg = CM_SDCCTL, + .div_reg = CM_SDCDIV, + .int_bits = 6, + .frac_bits = 0), + [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK( + .name = "v3d", + .ctl_reg = CM_V3DCTL, + .div_reg = CM_V3DDIV, + .int_bits = 4, + .frac_bits = 8), + /* + * VPU clock. This doesn't have an enable bit, since it drives + * the bus for everything else, and is special so it doesn't need + * to be gated for rate changes. It is also known as "clk_audio" + * in various hardware documentation. + */ + [BCM2835_CLOCK_VPU] = REGISTER_VPU_CLK( + .name = "vpu", + .ctl_reg = CM_VPUCTL, + .div_reg = CM_VPUDIV, + .int_bits = 12, + .frac_bits = 8, + .is_vpu_clock = true), + + /* clocks with per parent mux */ + + /* Arasan EMMC clock */ + [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK( + .name = "emmc", + .ctl_reg = CM_EMMCCTL, + .div_reg = CM_EMMCDIV, + .int_bits = 4, + .frac_bits = 8), + /* HDMI state machine */ + [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK( + .name = "hsm", + .ctl_reg = CM_HSMCTL, + .div_reg = CM_HSMDIV, + .int_bits = 4, + .frac_bits = 8), + [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( + .name = "pwm", + .ctl_reg = CM_PWMCTL, + .div_reg = CM_PWMDIV, + .int_bits = 12, + .frac_bits = 12, + .is_mash_clock = true), + [BCM2835_CLOCK_UART] = REGISTER_PER_CLK( + .name = "uart", + .ctl_reg = CM_UARTCTL, + .div_reg = CM_UARTDIV, + .int_bits = 10, + .frac_bits = 12), + /* TV encoder clock. Only operating frequency is 108Mhz. */ + [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( + .name = "vec", + .ctl_reg = CM_VECCTL, + .div_reg = CM_VECDIV, + .int_bits = 4, + .frac_bits = 0), + /* the gates */ + + /* + * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if + * you have the debug bit set in the power manager, which we + * don't bother exposing) are individual gates off of the + * non-stop vpu clock. + */ [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE( - &bcm2835_clock_peri_image_data), + .name = "peri_image", + .parent = "vpu", + .ctl_reg = CM_PERIICTL), }; static int bcm2835_clk_probe(struct platform_device *pdev) -- GitLab From 33b689600f43094a9316a1b582f2286d17bc737b Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 12:51:43 +0000 Subject: [PATCH 0092/9938] clk: bcm2835: enable management of PCM clock Enable the PCM clock in the SOC, which is used by the bcm2835-i2s driver. Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 7 +++++++ include/dt-bindings/clock/bcm2835.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index a4b91a4233af..156ce548ebf5 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1622,6 +1622,13 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .div_reg = CM_HSMDIV, .int_bits = 4, .frac_bits = 8), + [BCM2835_CLOCK_PCM] = REGISTER_PER_CLK( + .name = "pcm", + .ctl_reg = CM_PCMCTL, + .div_reg = CM_PCMDIV, + .int_bits = 12, + .frac_bits = 12, + .is_mash_clock = true), [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( .name = "pwm", .ctl_reg = CM_PWMCTL, diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h index 87235ac76ef1..9a7b4a5cd6e6 100644 --- a/include/dt-bindings/clock/bcm2835.h +++ b/include/dt-bindings/clock/bcm2835.h @@ -44,3 +44,4 @@ #define BCM2835_CLOCK_EMMC 28 #define BCM2835_CLOCK_PERI_IMAGE 29 #define BCM2835_CLOCK_PWM 30 +#define BCM2835_CLOCK_PCM 31 -- GitLab From 728436956aa172b24a3212295f8b53feb6479f32 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 15:43:56 +0000 Subject: [PATCH 0093/9938] clk: bcm2835: add missing PLL clock dividers Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 32 +++++++++++++++++++++++++++++ include/dt-bindings/clock/bcm2835.h | 5 +++++ 2 files changed, 37 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 156ce548ebf5..fa444d09c2d4 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1371,6 +1371,22 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .load_mask = CM_PLLA_LOADPER, .hold_mask = CM_PLLA_HOLDPER, .fixed_divider = 1), + [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV( + .name = "plla_dsi0", + .source_pll = "plla", + .cm_reg = CM_PLLA, + .a2w_reg = A2W_PLLA_DSI0, + .load_mask = CM_PLLA_LOADDSI0, + .hold_mask = CM_PLLA_HOLDDSI0, + .fixed_divider = 1), + [BCM2835_PLLA_CCP2] = REGISTER_PLL_DIV( + .name = "plla_ccp2", + .source_pll = "plla", + .cm_reg = CM_PLLA, + .a2w_reg = A2W_PLLA_CCP2, + .load_mask = CM_PLLA_LOADCCP2, + .hold_mask = CM_PLLA_HOLDCCP2, + .fixed_divider = 1), /* PLLB is used for the ARM's clock. */ [BCM2835_PLLB] = REGISTER_PLL( @@ -1485,6 +1501,22 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .load_mask = CM_PLLD_LOADPER, .hold_mask = CM_PLLD_HOLDPER, .fixed_divider = 1), + [BCM2835_PLLD_DSI0] = REGISTER_PLL_DIV( + .name = "plld_dsi0", + .source_pll = "plld", + .cm_reg = CM_PLLD, + .a2w_reg = A2W_PLLD_DSI0, + .load_mask = CM_PLLD_LOADDSI0, + .hold_mask = CM_PLLD_HOLDDSI0, + .fixed_divider = 1), + [BCM2835_PLLD_DSI1] = REGISTER_PLL_DIV( + .name = "plld_dsi1", + .source_pll = "plld", + .cm_reg = CM_PLLD, + .a2w_reg = A2W_PLLD_DSI1, + .load_mask = CM_PLLD_LOADDSI1, + .hold_mask = CM_PLLD_HOLDDSI1, + .fixed_divider = 1), /* * PLLH is used to supply the pixel clock or the AUX clock for the diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h index 9a7b4a5cd6e6..a001e3865134 100644 --- a/include/dt-bindings/clock/bcm2835.h +++ b/include/dt-bindings/clock/bcm2835.h @@ -45,3 +45,8 @@ #define BCM2835_CLOCK_PERI_IMAGE 29 #define BCM2835_CLOCK_PWM 30 #define BCM2835_CLOCK_PCM 31 + +#define BCM2835_PLLA_DSI0 32 +#define BCM2835_PLLA_CCP2 33 +#define BCM2835_PLLD_DSI0 34 +#define BCM2835_PLLD_DSI1 35 -- GitLab From d3d6f15fd376e3dbba851724057b112558c70b79 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 29 Feb 2016 15:43:57 +0000 Subject: [PATCH 0094/9938] clk: bcm2835: add missing osc and per clocks Add AVE0, DFT, GP0, GP1, GP2, SLIM, SMI, TEC, DPI, CAM0, CAM1, DSI0E, and DSI1E. PULSE is not added because it has an extra divider. Signed-off-by: Martin Sperl Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- drivers/clk/bcm/clk-bcm2835.c | 90 +++++++++++++++++++++++++++++ include/dt-bindings/clock/bcm2835.h | 14 +++++ 2 files changed, 104 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index fa444d09c2d4..4c0f1b504e2f 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -117,6 +117,8 @@ #define CM_SDCCTL 0x1a8 #define CM_SDCDIV 0x1ac #define CM_ARMCTL 0x1b0 +#define CM_AVEOCTL 0x1b8 +#define CM_AVEODIV 0x1bc #define CM_EMMCCTL 0x1c0 #define CM_EMMCDIV 0x1c4 @@ -1594,6 +1596,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .div_reg = CM_TSENSDIV, .int_bits = 5, .frac_bits = 0), + [BCM2835_CLOCK_TEC] = REGISTER_OSC_CLK( + .name = "tec", + .ctl_reg = CM_TECCTL, + .div_reg = CM_TECDIV, + .int_bits = 6, + .frac_bits = 0), /* clocks with vpu parent mux */ [BCM2835_CLOCK_H264] = REGISTER_VPU_CLK( @@ -1608,6 +1616,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .div_reg = CM_ISPDIV, .int_bits = 4, .frac_bits = 8), + /* * Secondary SDRAM clock. Used for low-voltage modes when the PLL * in the SDRAM controller can't be used. @@ -1639,6 +1648,36 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .is_vpu_clock = true), /* clocks with per parent mux */ + [BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK( + .name = "aveo", + .ctl_reg = CM_AVEOCTL, + .div_reg = CM_AVEODIV, + .int_bits = 4, + .frac_bits = 0), + [BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK( + .name = "cam0", + .ctl_reg = CM_CAM0CTL, + .div_reg = CM_CAM0DIV, + .int_bits = 4, + .frac_bits = 8), + [BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK( + .name = "cam1", + .ctl_reg = CM_CAM1CTL, + .div_reg = CM_CAM1DIV, + .int_bits = 4, + .frac_bits = 8), + [BCM2835_CLOCK_DFT] = REGISTER_PER_CLK( + .name = "dft", + .ctl_reg = CM_DFTCTL, + .div_reg = CM_DFTDIV, + .int_bits = 5, + .frac_bits = 0), + [BCM2835_CLOCK_DPI] = REGISTER_PER_CLK( + .name = "dpi", + .ctl_reg = CM_DPICTL, + .div_reg = CM_DPIDIV, + .int_bits = 4, + .frac_bits = 8), /* Arasan EMMC clock */ [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK( @@ -1647,6 +1686,29 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .div_reg = CM_EMMCDIV, .int_bits = 4, .frac_bits = 8), + + /* General purpose (GPIO) clocks */ + [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK( + .name = "gp0", + .ctl_reg = CM_GP0CTL, + .div_reg = CM_GP0DIV, + .int_bits = 12, + .frac_bits = 12, + .is_mash_clock = true), + [BCM2835_CLOCK_GP1] = REGISTER_PER_CLK( + .name = "gp1", + .ctl_reg = CM_GP1CTL, + .div_reg = CM_GP1DIV, + .int_bits = 12, + .frac_bits = 12, + .is_mash_clock = true), + [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK( + .name = "gp2", + .ctl_reg = CM_GP2CTL, + .div_reg = CM_GP2DIV, + .int_bits = 12, + .frac_bits = 12), + /* HDMI state machine */ [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK( .name = "hsm", @@ -1668,12 +1730,26 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .int_bits = 12, .frac_bits = 12, .is_mash_clock = true), + [BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK( + .name = "slim", + .ctl_reg = CM_SLIMCTL, + .div_reg = CM_SLIMDIV, + .int_bits = 12, + .frac_bits = 12, + .is_mash_clock = true), + [BCM2835_CLOCK_SMI] = REGISTER_PER_CLK( + .name = "smi", + .ctl_reg = CM_SMICTL, + .div_reg = CM_SMIDIV, + .int_bits = 4, + .frac_bits = 8), [BCM2835_CLOCK_UART] = REGISTER_PER_CLK( .name = "uart", .ctl_reg = CM_UARTCTL, .div_reg = CM_UARTDIV, .int_bits = 10, .frac_bits = 12), + /* TV encoder clock. Only operating frequency is 108Mhz. */ [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( .name = "vec", @@ -1682,6 +1758,20 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .int_bits = 4, .frac_bits = 0), + /* dsi clocks */ + [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK( + .name = "dsi0e", + .ctl_reg = CM_DSI0ECTL, + .div_reg = CM_DSI0EDIV, + .int_bits = 4, + .frac_bits = 8), + [BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK( + .name = "dsi1e", + .ctl_reg = CM_DSI1ECTL, + .div_reg = CM_DSI1EDIV, + .int_bits = 4, + .frac_bits = 8), + /* the gates */ /* diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h index a001e3865134..360e00cefd35 100644 --- a/include/dt-bindings/clock/bcm2835.h +++ b/include/dt-bindings/clock/bcm2835.h @@ -50,3 +50,17 @@ #define BCM2835_PLLA_CCP2 33 #define BCM2835_PLLD_DSI0 34 #define BCM2835_PLLD_DSI1 35 + +#define BCM2835_CLOCK_AVEO 36 +#define BCM2835_CLOCK_DFT 37 +#define BCM2835_CLOCK_GP0 38 +#define BCM2835_CLOCK_GP1 39 +#define BCM2835_CLOCK_GP2 40 +#define BCM2835_CLOCK_SLIM 41 +#define BCM2835_CLOCK_SMI 42 +#define BCM2835_CLOCK_TEC 43 +#define BCM2835_CLOCK_DPI 44 +#define BCM2835_CLOCK_CAM0 45 +#define BCM2835_CLOCK_CAM1 46 +#define BCM2835_CLOCK_DSI0E 47 +#define BCM2835_CLOCK_DSI1E 48 -- GitLab From 2596e07a3ed5a5f4d8b89be316c2b704d6f5dc5f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 17 Mar 2016 18:23:40 +0100 Subject: [PATCH 0095/9938] regmap: fix documentation to match code The regmap binding talks about one thing, which is register endianess, and it gets almost every aspect of it wrong. This replaces the current text of the file with a version that makes more sense and that matches what we implement now. Signed-off-by: Arnd Bergmann Fixes: a06c488da0b0 ("regmap: Add explict native endian flag to DT bindings") Fixes: 275876e208e2 ("regmap: Add the DT binding documentation for endianness") Signed-off-by: Mark Brown --- .../devicetree/bindings/regmap/regmap.txt | 59 ++++++------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt index e98a9652ccc8..0127be360fe8 100644 --- a/Documentation/devicetree/bindings/regmap/regmap.txt +++ b/Documentation/devicetree/bindings/regmap/regmap.txt @@ -1,50 +1,29 @@ -Device-Tree binding for regmap - -The endianness mode of CPU & Device scenarios: -Index Device Endianness properties ---------------------------------------------------- -1 BE 'big-endian' -2 LE 'little-endian' -3 Native 'native-endian' - -For one device driver, which will run in different scenarios above -on different SoCs using the devicetree, we need one way to simplify -this. +Devicetree binding for regmap Optional properties: -- {big,little,native}-endian: these are boolean properties, if absent - then the implementation will choose a default based on the device - being controlled. These properties are for register values and all - the buffers only. Native endian means that the CPU and device have - the same endianness. -Examples: -Scenario 1 : CPU in LE mode & device in LE mode. -dev: dev@40031000 { - compatible = "name"; - reg = <0x40031000 0x1000>; - ... -}; + little-endian, + big-endian, + native-endian: See common-properties.txt for a definition -Scenario 2 : CPU in LE mode & device in BE mode. -dev: dev@40031000 { - compatible = "name"; - reg = <0x40031000 0x1000>; - ... - big-endian; -}; +Note: +Regmap defaults to little-endian register access on MMIO based +devices, this is by far the most common setting. On CPU +architectures that typically run big-endian operating systems +(e.g. PowerPC), registers can be defined as big-endian and must +be marked that way in the devicetree. -Scenario 3 : CPU in BE mode & device in BE mode. -dev: dev@40031000 { - compatible = "name"; - reg = <0x40031000 0x1000>; - ... -}; +On SoCs that can be operated in both big-endian and little-endian +modes, with a single hardware switch controlling both the endianess +of the CPU and a byteswap for MMIO registers (e.g. many Broadcom MIPS +chips), "native-endian" is used to allow using the same device tree +blob in both cases. -Scenario 4 : CPU in BE mode & device in LE mode. +Examples: +Scenario 1 : a register set in big-endian mode. dev: dev@40031000 { - compatible = "name"; + compatible = "syscon"; reg = <0x40031000 0x1000>; + big-endian; ... - little-endian; }; -- GitLab From 2ce9b25cefa64f11bcb21b21cf4a5e8c58c6d0af Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 8 Mar 2016 22:57:23 +0530 Subject: [PATCH 0096/9938] ath10k: handle channel change htt event Whenever firmware is configuring operating channel during scan or home channel, channel change event will be indicated to host. In some cases (device probe/ last vdev down), target will be configured to default channel whereas host is unaware of target's operating channel. This leads to packet drop due to unknown channel and kernel log will be filled up with "no channel configured; ignoring frame(s)!". Fix that by handling HTT_T2H_MSG_TYPE_CHAN_CHANGE event. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 3 ++ drivers/net/wireless/ath/ath10k/htt.h | 9 ++++++ drivers/net/wireless/ath/ath10k/htt_rx.c | 41 +++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi.c | 28 ---------------- 4 files changed, 52 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 23ba03fb7a5f..bb5f7e22fc1e 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -766,6 +766,9 @@ struct ath10k { /* current operating channel definition */ struct cfg80211_chan_def chandef; + /* currently configured operating channel in firmware */ + struct ieee80211_channel *tgt_oper_chan; + unsigned long long free_vdev_map; struct ath10k_vif *monitor_arvif; bool monitor; diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 02cf55d306e8..3583fd99df48 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1461,6 +1461,14 @@ struct htt_tx_mode_switch_ind { struct htt_tx_mode_switch_record records[0]; } __packed; +struct htt_channel_change { + u8 pad[3]; + __le32 freq; + __le32 center_freq1; + __le32 center_freq2; + __le32 phymode; +} __packed; + union htt_rx_pn_t { /* WEP: 24-bit PN */ u32 pn24; @@ -1511,6 +1519,7 @@ struct htt_resp { struct htt_tx_fetch_ind tx_fetch_ind; struct htt_tx_fetch_confirm tx_fetch_confirm; struct htt_tx_mode_switch_ind tx_mode_switch_ind; + struct htt_channel_change chan_change; }; } __packed; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 84b060efa1b5..24fe3b6b5eb6 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -862,6 +862,8 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar, ch = ath10k_htt_rx_h_vdev_channel(ar, vdev_id); if (!ch) ch = ath10k_htt_rx_h_any_channel(ar); + if (!ch) + ch = ar->tgt_oper_chan; spin_unlock_bh(&ar->data_lock); if (!ch) @@ -2257,6 +2259,34 @@ static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar, ath10k_mac_tx_push_pending(ar); } +static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) +{ + enum ieee80211_band band; + + switch (phy_mode) { + case MODE_11A: + case MODE_11NA_HT20: + case MODE_11NA_HT40: + case MODE_11AC_VHT20: + case MODE_11AC_VHT40: + case MODE_11AC_VHT80: + band = IEEE80211_BAND_5GHZ; + break; + case MODE_11G: + case MODE_11B: + case MODE_11GONLY: + case MODE_11NG_HT20: + case MODE_11NG_HT40: + case MODE_11AC_VHT20_2G: + case MODE_11AC_VHT40_2G: + case MODE_11AC_VHT80_2G: + default: + band = IEEE80211_BAND_2GHZ; + } + + return band; +} + void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; @@ -2391,8 +2421,17 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) } case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: break; - case HTT_T2H_MSG_TYPE_CHAN_CHANGE: + case HTT_T2H_MSG_TYPE_CHAN_CHANGE: { + u32 phymode = __le32_to_cpu(resp->chan_change.phymode); + u32 freq = __le32_to_cpu(resp->chan_change.freq); + + ar->tgt_oper_chan = + __ieee80211_get_channel(ar->hw->wiphy, freq); + ath10k_dbg(ar, ATH10K_DBG_HTT, + "htt chan change freq %u phymode %s\n", + freq, ath10k_wmi_phymode_str(phymode)); break; + } case HTT_T2H_MSG_TYPE_AGGR_CONF: break; case HTT_T2H_MSG_TYPE_TX_FETCH_IND: diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index c2608946f773..91375664dc35 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2099,34 +2099,6 @@ int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) return 0; } -static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) -{ - enum ieee80211_band band; - - switch (phy_mode) { - case MODE_11A: - case MODE_11NA_HT20: - case MODE_11NA_HT40: - case MODE_11AC_VHT20: - case MODE_11AC_VHT40: - case MODE_11AC_VHT80: - band = IEEE80211_BAND_5GHZ; - break; - case MODE_11G: - case MODE_11B: - case MODE_11GONLY: - case MODE_11NG_HT20: - case MODE_11NG_HT40: - case MODE_11AC_VHT20_2G: - case MODE_11AC_VHT40_2G: - case MODE_11AC_VHT80_2G: - default: - band = IEEE80211_BAND_2GHZ; - } - - return band; -} - /* If keys are configured, HW decrypts all frames * with protected bit set. Mark such frames as decrypted. */ -- GitLab From cac085524cf16434ac1d42427a8644cf532d3e87 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 9 Mar 2016 20:25:46 +0530 Subject: [PATCH 0097/9938] ath10k: move mgmt descriptor limit handle under mgmt_tx Frames that are transmitted via MGMT_TX are using reserved descriptor slots in firmware. This limitation is for the htt_mgmt_tx path itself, not for mgmt frames per se. In 16 MBSSID scenario, these reserved slots will be easy exhausted due to frequent probe responses. So for 10.4 based solutions, probe responses are limited by a threshold (24). management tx path is separate for all except tlv based solutions. Since tlv solutions (qca6174 & qca9377) do not support 16 AP interfaces, it is safe to move management descriptor limitation check under mgmt_tx function. Though CPU improvement is negligible, unlikely conditions or never hit conditions in hot path can be avoided on data transmission. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 10 ++--- drivers/net/wireless/ath/ath10k/htt_rx.c | 7 +++- drivers/net/wireless/ath/ath10k/htt_tx.c | 50 +++++++++++++++--------- drivers/net/wireless/ath/ath10k/mac.c | 26 +++++++----- drivers/net/wireless/ath/ath10k/txrx.c | 18 ++++----- drivers/net/wireless/ath/ath10k/txrx.h | 4 +- 6 files changed, 68 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 3583fd99df48..d196bcc50e50 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1776,11 +1776,11 @@ void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw, void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw, struct ieee80211_txq *txq); void ath10k_htt_tx_txq_sync(struct ath10k *ar); -void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, - bool is_mgmt); -int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, - bool is_mgmt, - bool is_presp); +void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); +int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt); +void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt); +int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt, + bool is_presp); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 24fe3b6b5eb6..06975bf49351 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2354,7 +2354,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; } - ath10k_txrx_tx_unref(htt, &tx_done); + status = ath10k_txrx_tx_unref(htt, &tx_done); + if (!status) { + spin_lock_bh(&htt->tx_lock); + ath10k_htt_tx_mgmt_dec_pending(htt); + spin_unlock_bh(&htt->tx_lock); + } ath10k_mac_tx_push_pending(ar); break; } diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index a30c34eae0a7..b2ae122381ca 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -149,39 +149,22 @@ void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw, spin_unlock_bh(&ar->htt.tx_lock); } -void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, - bool is_mgmt) +void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) { lockdep_assert_held(&htt->tx_lock); - if (is_mgmt) - htt->num_pending_mgmt_tx--; - htt->num_pending_tx--; if (htt->num_pending_tx == htt->max_num_pending_tx - 1) ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); } -int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, - bool is_mgmt, - bool is_presp) +int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) { - struct ath10k *ar = htt->ar; - lockdep_assert_held(&htt->tx_lock); if (htt->num_pending_tx >= htt->max_num_pending_tx) return -EBUSY; - if (is_mgmt && - is_presp && - ar->hw_params.max_probe_resp_desc_thres && - ar->hw_params.max_probe_resp_desc_thres < htt->num_pending_mgmt_tx) - return -EBUSY; - - if (is_mgmt) - htt->num_pending_mgmt_tx++; - htt->num_pending_tx++; if (htt->num_pending_tx == htt->max_num_pending_tx) ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); @@ -189,6 +172,35 @@ int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, return 0; } +int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt, + bool is_presp) +{ + struct ath10k *ar = htt->ar; + + lockdep_assert_held(&htt->tx_lock); + + if (!is_mgmt || !ar->hw_params.max_probe_resp_desc_thres) + return 0; + + if (is_presp && + ar->hw_params.max_probe_resp_desc_thres < htt->num_pending_mgmt_tx) + return -EBUSY; + + htt->num_pending_mgmt_tx++; + + return 0; +} + +void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt) +{ + lockdep_assert_held(&htt->tx_lock); + + if (!htt->ar->hw_params.max_probe_resp_desc_thres) + return; + + htt->num_pending_mgmt_tx--; +} + int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb) { struct ath10k *ar = htt->ar; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ebff9c0a0784..209c13d113a7 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3699,8 +3699,6 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { - const bool is_mgmt = false; - const bool is_presp = false; struct ath10k *ar = hw->priv; struct ath10k_htt *htt = &ar->htt; struct ath10k_txq *artxq = (void *)txq->drv_priv; @@ -3713,7 +3711,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, int ret; spin_lock_bh(&ar->htt.tx_lock); - ret = ath10k_htt_tx_inc_pending(htt, is_mgmt, is_presp); + ret = ath10k_htt_tx_inc_pending(htt); spin_unlock_bh(&ar->htt.tx_lock); if (ret) @@ -3722,7 +3720,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, skb = ieee80211_tx_dequeue(hw, txq); if (!skb) { spin_lock_bh(&ar->htt.tx_lock); - ath10k_htt_tx_dec_pending(htt, is_mgmt); + ath10k_htt_tx_dec_pending(htt); spin_unlock_bh(&ar->htt.tx_lock); return -ENOENT; @@ -3739,7 +3737,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to push frame: %d\n", ret); spin_lock_bh(&ar->htt.tx_lock); - ath10k_htt_tx_dec_pending(htt, is_mgmt); + ath10k_htt_tx_dec_pending(htt); spin_unlock_bh(&ar->htt.tx_lock); return ret; @@ -3978,14 +3976,13 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); is_htt = (txpath == ATH10K_MAC_TX_HTT || txpath == ATH10K_MAC_TX_HTT_MGMT); + is_mgmt = (txpath == ATH10K_MAC_TX_HTT_MGMT); if (is_htt) { spin_lock_bh(&ar->htt.tx_lock); - - is_mgmt = ieee80211_is_mgmt(hdr->frame_control); is_presp = ieee80211_is_probe_resp(hdr->frame_control); - ret = ath10k_htt_tx_inc_pending(htt, is_mgmt, is_presp); + ret = ath10k_htt_tx_inc_pending(htt); if (ret) { ath10k_warn(ar, "failed to increase tx pending count: %d, dropping\n", ret); @@ -3994,6 +3991,15 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, return; } + ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp); + if (ret) { + ath10k_warn(ar, "failed to increase tx mgmt pending count: %d, dropping\n", + ret); + ath10k_htt_tx_dec_pending(htt); + spin_unlock_bh(&ar->htt.tx_lock); + ieee80211_free_txskb(ar->hw, skb); + return; + } spin_unlock_bh(&ar->htt.tx_lock); } @@ -4002,7 +4008,9 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to transmit frame: %d\n", ret); if (is_htt) { spin_lock_bh(&ar->htt.tx_lock); - ath10k_htt_tx_dec_pending(htt, is_mgmt); + ath10k_htt_tx_dec_pending(htt); + if (is_mgmt) + ath10k_htt_tx_mgmt_dec_pending(htt); spin_unlock_bh(&ar->htt.tx_lock); } return; diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index ea4d3000c8c3..48e26cdfe9a5 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -49,8 +49,8 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb) spin_unlock_bh(&ar->data_lock); } -void ath10k_txrx_tx_unref(struct ath10k_htt *htt, - const struct htt_tx_done *tx_done) +int ath10k_txrx_tx_unref(struct ath10k_htt *htt, + const struct htt_tx_done *tx_done) { struct ath10k *ar = htt->ar; struct device *dev = ar->dev; @@ -59,7 +59,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct ath10k_skb_cb *skb_cb; struct ath10k_txq *artxq; struct sk_buff *msdu; - bool limit_mgmt_desc = false; ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d success %d\n", @@ -69,7 +68,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, if (tx_done->msdu_id >= htt->max_num_pending_tx) { ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n", tx_done->msdu_id); - return; + return -EINVAL; } spin_lock_bh(&htt->tx_lock); @@ -78,22 +77,18 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n", tx_done->msdu_id); spin_unlock_bh(&htt->tx_lock); - return; + return -ENOENT; } skb_cb = ATH10K_SKB_CB(msdu); txq = skb_cb->txq; artxq = (void *)txq->drv_priv; - if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) && - ar->hw_params.max_probe_resp_desc_thres) - limit_mgmt_desc = true; - if (txq) artxq->num_fw_queued--; ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); - ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); + ath10k_htt_tx_dec_pending(htt); if (htt->num_pending_tx == 0) wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); @@ -108,7 +103,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, if (tx_done->discard) { ieee80211_free_txskb(htt->ar->hw, msdu); - return; + return 0; } if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) @@ -122,6 +117,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ieee80211_tx_status(htt->ar->hw, msdu); /* we do not own the msdu anymore */ + return 0; } struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h index a90e09f5c7f2..e7ea1ae1c438 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.h +++ b/drivers/net/wireless/ath/ath10k/txrx.h @@ -19,8 +19,8 @@ #include "htt.h" -void ath10k_txrx_tx_unref(struct ath10k_htt *htt, - const struct htt_tx_done *tx_done); +int ath10k_txrx_tx_unref(struct ath10k_htt *htt, + const struct htt_tx_done *tx_done); struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, const u8 *addr); -- GitLab From b9c191be3fbdd9d78be11160dd7a3ddb9fdc6d42 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Thu, 10 Mar 2016 10:25:07 +0530 Subject: [PATCH 0098/9938] ath10k: free cached fw bin contents when get board id fails ath10k_core_probe_fw() simply returns error without freeing cached firmware file content when get board id operation fails. Free cached fw bin data in failure case to avoid memory leak. Fixes: db0984e51a18 ("ath10k: select board data based on BMI chip id and board id") Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2389c0713c13..d5d0b88aa5fe 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1839,7 +1839,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar) if (ret && ret != -EOPNOTSUPP) { ath10k_err(ar, "failed to get board id from otp: %d\n", ret); - return ret; + goto err_free_firmware_files; } ret = ath10k_core_fetch_board_file(ar); -- GitLab From 9ddc486aa09a3413a6c492fcf160ce61bfccb7b1 Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Fri, 11 Mar 2016 11:46:39 +0530 Subject: [PATCH 0099/9938] ath10k: fix debugfs pktlog_filter write It is observed that, we are disabling the packet log if we write same value to the pktlog_filter for the second time. Always enable pktlogs on non zero filter. Fixes: 90174455ae05 ("ath10k: add support to configure pktlog filter") Cc: stable@vger.kernel.org Signed-off-by: Anilkumar Kolli Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 076d29b53ddf..0f834646e6a7 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -2019,7 +2019,12 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file, goto out; } - if (filter && (filter != ar->debug.pktlog_filter)) { + if (filter == ar->debug.pktlog_filter) { + ret = count; + goto out; + } + + if (filter) { ret = ath10k_wmi_pdev_pktlog_enable(ar, filter); if (ret) { ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n", -- GitLab From bf031bc4d6a168029b8a640373fd00837746b47d Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 15 Mar 2016 15:25:53 +0530 Subject: [PATCH 0100/9938] ath10k: advertise force AP scan feature Results obtained from scan can be used for spectrum management by doing something like building information of preferred channel lists and sharing them with stations around. It is to be noted that traffic to the connected stations would be affected during the scan. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 209c13d113a7..eedfe821700b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7705,7 +7705,8 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->max_remain_on_channel_duration = 5000; ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; - ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; + ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_AP_SCAN; ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations; -- GitLab From d4e44f1418d71cf53d685e236a95c525089e065a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 18 Mar 2016 12:28:49 +0200 Subject: [PATCH 0101/9938] ASoC: omap-mcbsp: Enable/disable sidetone block auto clock gating for omap3 OMAP3's McBSP2 and McBSP3 module have integrated sidetone block with dedicated SYSCONFIG register. The sidetone is operating from the maain McBSP module's ICLK. For normal operation the sidetone clock auto idle support needs to be disabled when it is activated. Note: This is not enough to avoid choppy sidetone because this AUTOIDLE bit is controlling only the clock auto idle from the McBSP to the sidetone block. If the McBSP_ICLK is idling, the sidetone clock is going to do the same. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/mcbsp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index c7563e230c7d..4a16e778966b 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -260,6 +260,10 @@ static void omap_st_on(struct omap_mcbsp *mcbsp) if (mcbsp->pdata->enable_st_clock) mcbsp->pdata->enable_st_clock(mcbsp->id, 1); + /* Disable Sidetone clock auto-gating for normal operation */ + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); + /* Enable McBSP Sidetone */ w = MCBSP_READ(mcbsp, SSELCR); MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN); @@ -279,6 +283,10 @@ static void omap_st_off(struct omap_mcbsp *mcbsp) w = MCBSP_READ(mcbsp, SSELCR); MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); + /* Enable Sidetone clock auto-gating to reduce power consumption */ + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE); + if (mcbsp->pdata->enable_st_clock) mcbsp->pdata->enable_st_clock(mcbsp->id, 0); } -- GitLab From d03b65967c902f4e8c0bd139542a9e4a7cc9a10d Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sat, 12 Mar 2016 13:30:17 +0100 Subject: [PATCH 0102/9938] dt: document NXP LPC1850 DAC driver bindings Signed-off-by: Joachim Eastwood Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/dac/lpc1850-dac.txt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt diff --git a/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt b/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt new file mode 100644 index 000000000000..7d6647d4af5e --- /dev/null +++ b/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt @@ -0,0 +1,20 @@ +NXP LPC1850 DAC bindings + +Required properties: +- compatible: Should be "nxp,lpc1850-dac" +- reg: Offset and length of the register set for the ADC device +- interrupts: The interrupt number for the ADC device +- clocks: The root clock of the ADC controller +- vref-supply: The regulator supply ADC reference voltage +- resets: phandle to reset controller and line specifier + +Example: +dac: dac@400e1000 { + compatible = "nxp,lpc1850-dac"; + reg = <0x400e1000 0x1000>; + interrupts = <0>; + clocks = <&ccu1 CLK_APB3_DAC>; + vref-supply = <®_vdda>; + resets = <&rgu 42>; + status = "disabled"; +}; -- GitLab From 6fca5aa8658e61bf01158c4262cabcd8d7f72533 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler Date: Sun, 13 Mar 2016 16:22:33 +0100 Subject: [PATCH 0103/9938] MAINTAINERS: update pmeerw's name happily married for 4 month :) Signed-off-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index dd9ee367d05c..048c3d17634d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5458,7 +5458,7 @@ IIO SUBSYSTEM AND DRIVERS M: Jonathan Cameron R: Hartmut Knaack R: Lars-Peter Clausen -R: Peter Meerwald +R: Peter Meerwald-Stadler L: linux-iio@vger.kernel.org S: Maintained F: drivers/iio/ -- GitLab From 4fbcfa09f9e7b8b51af23bacf6e9adc45b6d0f3b Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 13 Mar 2016 16:02:22 +0100 Subject: [PATCH 0104/9938] iio: ABI: Fix typo in in_proximity_raw description Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 3c6624881375..17a9210fa6b5 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1233,7 +1233,7 @@ KernelVersion: 3.4 Contact: linux-iio@vger.kernel.org Description: Proximity measurement indicating that some - object is near the sensor, usually be observing + object is near the sensor, usually by observing reflectivity of infrared or ultrasound emitted. Often these sensors are unit less and as such conversion to SI units is not possible. Higher proximity measurements -- GitLab From ddb851affbb8a669cdfe237745aaab7523a31919 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Mon, 14 Mar 2016 12:33:14 +0100 Subject: [PATCH 0105/9938] iio: mma8452: add i2c_device_id for mma8451 This was forgotten about and is added for consistency now Signed-off-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 305ed0e37dfb..6aa2517b4688 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1535,6 +1535,7 @@ static const struct dev_pm_ops mma8452_pm_ops = { }; static const struct i2c_device_id mma8452_id[] = { + { "mma8451", mma8451 }, { "mma8452", mma8452 }, { "mma8453", mma8453 }, { "mma8652", mma8652 }, -- GitLab From bce59b602dace036b797144b1a5851318cbc85f0 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Mon, 14 Mar 2016 12:26:29 +0100 Subject: [PATCH 0106/9938] iio: mma8452: use runtime pm instead of device specific autosleep What is this autosleep? ----------------------- It slows down the device after x seconds of inactivity. The thing is, we have really achieved almost the same by runtime pm. differnces are: autosleep * uses more power during inactivity * the first read after inactivity slightly faster * complicated to understand for the user * no documented sysfs interface (afaik) * complicated to read and maintain runtime pm * already merged in mma8452 * uses less power during inactivity * first read after inactivity slower * easy to use. well documented. * easy to maintain and understand The two approaches solve the same problem. runtime pm has more advantages than autosleep and comes quite close to it's behaviour anyways. As I see it, autosleep, even if somehow supported, would never be used anyways. So resolve this issue by "ignoring" autosleep. Signed-off-by: Martin Kepplinger Reviewed-by: Martina Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 6aa2517b4688..e225d3c53bd5 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -17,7 +17,7 @@ * * 7-bit I2C slave address 0x1c/0x1d (pin selectable) * - * TODO: orientation events, autosleep + * TODO: orientation events */ #include -- GitLab From 6ad515c6d6beea3cbb8557ba2b0f57c39301b0f7 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler Date: Tue, 15 Mar 2016 22:54:51 +0100 Subject: [PATCH 0107/9938] tools: iio: Update iio_event_monitor names add recently added channel types and modifiers Signed-off-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- tools/iio/iio_event_monitor.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index d51eb04202e9..90980f586f7a 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -53,6 +53,9 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_ENERGY] = "energy", [IIO_DISTANCE] = "distance", [IIO_VELOCITY] = "velocity", + [IIO_CONCENTRATION] = "concentration", + [IIO_RESISTANCE] = "resistance", + [IIO_PH] = "ph", }; static const char * const iio_ev_type_text[] = { @@ -102,6 +105,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_WALKING] = "walking", [IIO_MOD_STILL] = "still", [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", + [IIO_MOD_I] = "i", + [IIO_MOD_Q] = "q", + [IIO_MOD_CO2] = "co2", + [IIO_MOD_VOC] = "voc", }; static bool event_is_known(struct iio_event_data *event) @@ -136,6 +143,9 @@ static bool event_is_known(struct iio_event_data *event) case IIO_ENERGY: case IIO_DISTANCE: case IIO_VELOCITY: + case IIO_CONCENTRATION: + case IIO_RESISTANCE: + case IIO_PH: break; default: return false; @@ -174,6 +184,10 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_WALKING: case IIO_MOD_STILL: case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z: + case IIO_MOD_I: + case IIO_MOD_Q: + case IIO_MOD_CO2: + case IIO_MOD_VOC: break; default: return false; -- GitLab From 722fc31663d506d668e6a3bea4e9dca8ab957d3a Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Tue, 15 Mar 2016 11:49:12 -0700 Subject: [PATCH 0108/9938] staging: iio: isl29028: use regmap to retrieve struct device Driver includes struct regmap and struct device in its global data. Remove the struct device and use regmap API to retrieve device info. Simplified version of Coccinelle semantic patch used: @ a @ identifier drvdata, r; position p; @@ struct drvdata@p { ... struct regmap *r; ... }; @ b @ identifier a.drvdata, d; position a.p; @@ struct drvdata@p { ... - struct device *d; ... }; @ passed depends on b @ identifier a.drvdata, a.r, b.d, i, f; @@ f (..., struct drvdata *i ,...) { + struct device *dev = regmap_get_device(i->r); <+... - i->d + dev ...+> } Signed-off-by: Alison Schofield Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29028.c | 55 +++++++++++++++------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 6e2ba458c24d..2e3b1d64e32a 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -69,7 +69,6 @@ enum als_ir_mode { }; struct isl29028_chip { - struct device *dev; struct mutex lock; struct regmap *regmap; @@ -166,20 +165,21 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir) { + struct device *dev = regmap_get_device(chip->regmap); unsigned int lsb; unsigned int msb; int ret; ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb); if (ret < 0) { - dev_err(chip->dev, + dev_err(dev, "Error in reading register ALSIR_L err %d\n", ret); return ret; } ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb); if (ret < 0) { - dev_err(chip->dev, + dev_err(dev, "Error in reading register ALSIR_U err %d\n", ret); return ret; } @@ -190,12 +190,13 @@ static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir) static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox) { + struct device *dev = regmap_get_device(chip->regmap); unsigned int data; int ret; ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data); if (ret < 0) { - dev_err(chip->dev, "Error in reading register %d, error %d\n", + dev_err(dev, "Error in reading register %d, error %d\n", ISL29028_REG_PROX_DATA, ret); return ret; } @@ -218,13 +219,14 @@ static int isl29028_proxim_get(struct isl29028_chip *chip, int *prox_data) static int isl29028_als_get(struct isl29028_chip *chip, int *als_data) { + struct device *dev = regmap_get_device(chip->regmap); int ret; int als_ir_data; if (chip->als_ir_mode != MODE_ALS) { ret = isl29028_set_als_ir_mode(chip, MODE_ALS); if (ret < 0) { - dev_err(chip->dev, + dev_err(dev, "Error in enabling ALS mode err %d\n", ret); return ret; } @@ -251,12 +253,13 @@ static int isl29028_als_get(struct isl29028_chip *chip, int *als_data) static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data) { + struct device *dev = regmap_get_device(chip->regmap); int ret; if (chip->als_ir_mode != MODE_IR) { ret = isl29028_set_als_ir_mode(chip, MODE_IR); if (ret < 0) { - dev_err(chip->dev, + dev_err(dev, "Error in enabling IR mode err %d\n", ret); return ret; } @@ -271,25 +274,26 @@ static int isl29028_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct isl29028_chip *chip = iio_priv(indio_dev); + struct device *dev = regmap_get_device(chip->regmap); int ret = -EINVAL; mutex_lock(&chip->lock); switch (chan->type) { case IIO_PROXIMITY: if (mask != IIO_CHAN_INFO_SAMP_FREQ) { - dev_err(chip->dev, + dev_err(dev, "proximity: mask value 0x%08lx not supported\n", mask); break; } if (val < 1 || val > 100) { - dev_err(chip->dev, + dev_err(dev, "Samp_freq %d is not in range[1:100]\n", val); break; } ret = isl29028_set_proxim_sampling(chip, val); if (ret < 0) { - dev_err(chip->dev, + dev_err(dev, "Setting proximity samp_freq fail, err %d\n", ret); break; @@ -299,19 +303,19 @@ static int isl29028_write_raw(struct iio_dev *indio_dev, case IIO_LIGHT: if (mask != IIO_CHAN_INFO_SCALE) { - dev_err(chip->dev, + dev_err(dev, "light: mask value 0x%08lx not supported\n", mask); break; } if ((val != 125) && (val != 2000)) { - dev_err(chip->dev, + dev_err(dev, "lux scale %d is invalid [125, 2000]\n", val); break; } ret = isl29028_set_als_scale(chip, val); if (ret < 0) { - dev_err(chip->dev, + dev_err(dev, "Setting lux scale fail with error %d\n", ret); break; } @@ -319,7 +323,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev, break; default: - dev_err(chip->dev, "Unsupported channel type\n"); + dev_err(dev, "Unsupported channel type\n"); break; } mutex_unlock(&chip->lock); @@ -331,6 +335,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct isl29028_chip *chip = iio_priv(indio_dev); + struct device *dev = regmap_get_device(chip->regmap); int ret = -EINVAL; mutex_lock(&chip->lock); @@ -370,7 +375,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, break; default: - dev_err(chip->dev, "mask value 0x%08lx not supported\n", mask); + dev_err(dev, "mask value 0x%08lx not supported\n", mask); break; } mutex_unlock(&chip->lock); @@ -417,6 +422,7 @@ static const struct iio_info isl29028_info = { static int isl29028_chip_init(struct isl29028_chip *chip) { + struct device *dev = regmap_get_device(chip->regmap); int ret; chip->enable_prox = false; @@ -426,35 +432,33 @@ static int isl29028_chip_init(struct isl29028_chip *chip) ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0); if (ret < 0) { - dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", + dev_err(dev, "%s(): write to reg %d failed, err = %d\n", __func__, ISL29028_REG_TEST1_MODE, ret); return ret; } ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0); if (ret < 0) { - dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", + dev_err(dev, "%s(): write to reg %d failed, err = %d\n", __func__, ISL29028_REG_TEST2_MODE, ret); return ret; } ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0); if (ret < 0) { - dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n", + dev_err(dev, "%s(): write to reg %d failed, err = %d\n", __func__, ISL29028_REG_CONFIGURE, ret); return ret; } ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling); if (ret < 0) { - dev_err(chip->dev, "setting the proximity, err = %d\n", - ret); + dev_err(dev, "setting the proximity, err = %d\n", ret); return ret; } ret = isl29028_set_als_scale(chip, chip->lux_scale); if (ret < 0) - dev_err(chip->dev, - "setting als scale failed, err = %d\n", ret); + dev_err(dev, "setting als scale failed, err = %d\n", ret); return ret; } @@ -496,19 +500,19 @@ static int isl29028_probe(struct i2c_client *client, chip = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); - chip->dev = &client->dev; mutex_init(&chip->lock); chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config); if (IS_ERR(chip->regmap)) { ret = PTR_ERR(chip->regmap); - dev_err(chip->dev, "regmap initialization failed: %d\n", ret); + dev_err(&client->dev, "regmap initialization failed: %d\n", + ret); return ret; } ret = isl29028_chip_init(chip); if (ret < 0) { - dev_err(chip->dev, "chip initialization failed: %d\n", ret); + dev_err(&client->dev, "chip initialization failed: %d\n", ret); return ret; } @@ -520,7 +524,8 @@ static int isl29028_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); if (ret < 0) { - dev_err(chip->dev, "iio registration fails with error %d\n", + dev_err(&client->dev, + "iio registration fails with error %d\n", ret); return ret; } -- GitLab From ae549a72212c94c757fa3ecbcaa986cc9d2e2b96 Mon Sep 17 00:00:00 2001 From: David Wu Date: Wed, 16 Mar 2016 01:44:15 +0800 Subject: [PATCH 0109/9938] iio: adc: rockchip_saradc: add saradc support for rk3399 The ADC is a 6-channel signal-ended 10-bit Successive Approximation Register (SAR) A/D Converter. Signed-off-by: David Wu Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/rockchip-saradc.txt | 6 +++++- drivers/iio/adc/rockchip_saradc.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt index a9a5fe19ff2a..bf99e2f24788 100644 --- a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt +++ b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt @@ -1,7 +1,11 @@ Rockchip Successive Approximation Register (SAR) A/D Converter bindings Required properties: -- compatible: Should be "rockchip,saradc" or "rockchip,rk3066-tsadc" +- compatible: should be "rockchip,-saradc" or "rockchip,rk3066-tsadc" + - "rockchip,saradc": for rk3188, rk3288 + - "rockchip,rk3066-tsadc": for rk3036 + - "rockchip,rk3399-saradc": for rk3399 + - reg: physical base address of the controller and length of memory mapped region. - interrupts: The interrupt number to the cpu. The interrupt specifier format diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 9c311c1e1ac7..f9ad6c2d6821 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -159,6 +159,22 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = { .clk_rate = 50000, }; +static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = { + ADC_CHANNEL(0, "adc0"), + ADC_CHANNEL(1, "adc1"), + ADC_CHANNEL(2, "adc2"), + ADC_CHANNEL(3, "adc3"), + ADC_CHANNEL(4, "adc4"), + ADC_CHANNEL(5, "adc5"), +}; + +static const struct rockchip_saradc_data rk3399_saradc_data = { + .num_bits = 10, + .channels = rockchip_rk3399_saradc_iio_channels, + .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels), + .clk_rate = 1000000, +}; + static const struct of_device_id rockchip_saradc_match[] = { { .compatible = "rockchip,saradc", @@ -166,6 +182,9 @@ static const struct of_device_id rockchip_saradc_match[] = { }, { .compatible = "rockchip,rk3066-tsadc", .data = &rk3066_tsadc_data, + }, { + .compatible = "rockchip,rk3399-saradc", + .data = &rk3399_saradc_data, }, {}, }; -- GitLab From 01d11cd12d85e88518eb884891e115cb4bf696a2 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 9 Mar 2016 17:38:47 +0200 Subject: [PATCH 0110/9938] iwlwifi: pcie: clear trans reference on queue stop Currently when stop flow is performed, there might be transport TX RTPM references that are not freed in case we unmap a queue that still has packets not reclaimed. Fix that. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 59 ++++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 16ad820ca824..cc6fa00d350b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -596,6 +596,28 @@ static void iwl_pcie_free_tso_page(struct sk_buff *skb) } } +static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + lockdep_assert_held(&trans_pcie->reg_lock); + + if (trans_pcie->ref_cmd_in_flight) { + trans_pcie->ref_cmd_in_flight = false; + IWL_DEBUG_RPM(trans, "clear ref_cmd_in_flight - unref\n"); + iwl_trans_pcie_unref(trans); + } + + if (!trans->cfg->base_params->apmg_wake_up_wa) + return; + if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) + return; + + trans_pcie->cmd_hold_nic_awake = false; + __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); +} + /* * iwl_pcie_txq_unmap - Unmap any remaining DMA mappings and free skb's */ @@ -620,6 +642,20 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) } iwl_pcie_txq_free_tfd(trans, txq); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr); + + if (q->read_ptr == q->write_ptr) { + unsigned long flags; + + spin_lock_irqsave(&trans_pcie->reg_lock, flags); + if (txq_id != trans_pcie->cmd_queue) { + IWL_DEBUG_RPM(trans, "Q %d - last tx freed\n", + q->id); + iwl_trans_pcie_unref(trans); + } else { + iwl_pcie_clear_cmd_in_flight(trans); + } + spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); + } } txq->active = false; @@ -1148,29 +1184,6 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, return 0; } -static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - lockdep_assert_held(&trans_pcie->reg_lock); - - if (trans_pcie->ref_cmd_in_flight) { - trans_pcie->ref_cmd_in_flight = false; - IWL_DEBUG_RPM(trans, "clear ref_cmd_in_flight - unref\n"); - iwl_trans_pcie_unref(trans); - } - - if (trans->cfg->base_params->apmg_wake_up_wa) { - if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) - return 0; - - trans_pcie->cmd_hold_nic_awake = false; - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - } - return 0; -} - /* * iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd * -- GitLab From c94d7996db64582770103b178ea4060516d7e646 Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Wed, 9 Mar 2016 10:54:10 +0200 Subject: [PATCH 0111/9938] iwlwifi: mvm: Decrease size of the paging download buffer Currently the driver has 2 buffers for paging: 1. paging db - this contains all of the pages that were in the FW image, that the driver stores for the FW. This is allocated for each block separately (not contiguous). 2. download buffer - we need to provide this empty buffer for the iwl_sdio_load_fw_chunk function to copy the requested pages to the shared memory. This is one big buffer of contiguous memory whose size is the size of all the blocks that the fw paging section can contain. This download buffer size is too big, and causes the allocation to fail sometimes. Since the driver allocates memory for each block separately, it is not possible for the FW to request all of the pages in one request (the FW gives an address and size, so blocks need to be contiguous for this to happen), therefore the FW is limited to request only one block. Decrease the size of the paging download buffer to be the size of a paging block. Signed-off-by: Matti Gottlieb Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 594cd0dc7df9..ebbadcf41ea0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -410,7 +410,9 @@ static int iwl_trans_get_paging_item(struct iwl_mvm *mvm) goto exit; } - mvm->trans->paging_download_buf = kzalloc(MAX_PAGING_IMAGE_SIZE, + /* Add an extra page for headers */ + mvm->trans->paging_download_buf = kzalloc(PAGING_BLOCK_SIZE + + FW_PAGING_SIZE, GFP_KERNEL); if (!mvm->trans->paging_download_buf) { ret = -ENOMEM; -- GitLab From 718ba46e5f4e21e45141bf55fd4cccd4b3ba9939 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 17 Mar 2016 18:32:44 +0200 Subject: [PATCH 0112/9938] iio: imu: mpu6050: Fix name/chip_id when using ACPI When using ACPI, id is NULL and the current code automatically defaults name to NULL and chip id to 0. We should instead use the data provided in the ACPI device table. Fixes: c816d9e7a57b ("iio: imu: mpu6050: fix possible NULL dereferences") Signed-off-by: Daniel Baluta Reviewed-By: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 29 ++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index d0c0e20c7122..5ee4e0dc093e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, return 0; } +static const char *inv_mpu_match_acpi_device(struct device *dev, int *chip_id) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + + *chip_id = (int)id->driver_data; + + return dev_name(dev); +} + /** * inv_mpu_probe() - probe function. * @client: i2c client. @@ -115,15 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct inv_mpu6050_state *st; - int result; - const char *name = id ? id->name : NULL; - const int chip_type = id ? id->driver_data : 0; + int result, chip_type; struct regmap *regmap; + const char *name; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) return -EOPNOTSUPP; + if (id) { + chip_type = (int)id->driver_data; + name = id->name; + } else if (ACPI_HANDLE(&client->dev)) { + name = inv_mpu_match_acpi_device(&client->dev, &chip_type); + if (!name) + return -ENODEV; + } else { + return -ENOSYS; + } + regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config); if (IS_ERR(regmap)) { dev_err(&client->dev, "Failed to register i2c regmap %d\n", -- GitLab From 334ecdd0ba45bb68bce0f1429a4a1e9584ba437e Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Thu, 17 Mar 2016 12:55:03 +0100 Subject: [PATCH 0113/9938] iio:pressure:ms5611: fix missing regulator_disable Ensure optional regulator is properly disabled when present. Fixes: 3145229f9191 ("iio:pressure:ms5611: power regulator support") Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611.h | 3 +++ drivers/iio/pressure/ms5611_core.c | 41 +++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h index d725a3077a17..ccda63c5b3c3 100644 --- a/drivers/iio/pressure/ms5611.h +++ b/drivers/iio/pressure/ms5611.h @@ -16,6 +16,8 @@ #include #include +struct regulator; + #define MS5611_RESET 0x1e #define MS5611_READ_ADC 0x00 #define MS5611_READ_PROM_WORD 0xA0 @@ -57,6 +59,7 @@ struct ms5611_state { s32 *temp, s32 *pressure); struct ms5611_chip_info *chip_info; + struct regulator *vdd; }; int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 37dbc0401599..c4e65868bc28 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -387,24 +387,45 @@ static const struct iio_info ms5611_info = { static int ms5611_init(struct iio_dev *indio_dev) { int ret; - struct regulator *vdd = devm_regulator_get(indio_dev->dev.parent, - "vdd"); + struct ms5611_state *st = iio_priv(indio_dev); /* Enable attached regulator if any. */ - if (!IS_ERR(vdd)) { - ret = regulator_enable(vdd); + st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd"); + if (!IS_ERR(st->vdd)) { + ret = regulator_enable(st->vdd); if (ret) { dev_err(indio_dev->dev.parent, - "failed to enable Vdd supply: %d\n", ret); + "failed to enable Vdd supply: %d\n", ret); return ret; } + } else { + ret = PTR_ERR(st->vdd); + if (ret != -ENODEV) + return ret; } ret = ms5611_reset(indio_dev); if (ret < 0) - return ret; + goto err_regulator_disable; + + ret = ms5611_read_prom(indio_dev); + if (ret < 0) + goto err_regulator_disable; + + return 0; - return ms5611_read_prom(indio_dev); +err_regulator_disable: + if (!IS_ERR_OR_NULL(st->vdd)) + regulator_disable(st->vdd); + return ret; +} + +static void ms5611_fini(const struct iio_dev *indio_dev) +{ + const struct ms5611_state *st = iio_priv(indio_dev); + + if (!IS_ERR_OR_NULL(st->vdd)) + regulator_disable(st->vdd); } int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, @@ -436,7 +457,7 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, ms5611_trigger_handler, NULL); if (ret < 0) { dev_err(dev, "iio triggered buffer setup failed\n"); - return ret; + goto err_fini; } ret = iio_device_register(indio_dev); @@ -449,7 +470,8 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, err_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); - +err_fini: + ms5611_fini(indio_dev); return ret; } EXPORT_SYMBOL(ms5611_probe); @@ -458,6 +480,7 @@ int ms5611_remove(struct iio_dev *indio_dev) { iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); + ms5611_fini(indio_dev); return 0; } -- GitLab From 9e61d901155bcd4e58cbce5eb4aaa8e870267334 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Thu, 17 Mar 2016 19:25:11 +0530 Subject: [PATCH 0114/9938] iio: light: tsl2563: Remove flush_scheduled_work flush_scheduled_work is scheduled for deprecation. Replace cancel_delayed_work and flush_scheduled_work with cancel_delayed_work_sync instead to ensure there is no pending or running work item. Since there is only one work item, chip->poweroff_work, there are no further dependencies of flush_scheduled_work(). Acked-by: Tejun Heo Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2563.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index 12731d6b89ec..57b108c30e98 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -806,8 +806,7 @@ static int tsl2563_probe(struct i2c_client *client, return 0; fail: - cancel_delayed_work(&chip->poweroff_work); - flush_scheduled_work(); + cancel_delayed_work_sync(&chip->poweroff_work); return err; } -- GitLab From a9b72c90fc1a7cd547a333e382b3a7c2201fc3e4 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Thu, 17 Mar 2016 17:43:26 +0100 Subject: [PATCH 0115/9938] iio:magnetometer:ak8975: fix missing regulator_disable Ensure optional regulator is properly disabled when present. Fixes: 63d5d525cbbc ("iio:magnetometer:ak8975: power regulator support") Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 78 ++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 72c03d9fbeb2..48d127a45d90 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -370,8 +370,40 @@ struct ak8975_data { wait_queue_head_t data_ready_queue; unsigned long flags; u8 cntl_cache; + struct regulator *vdd; }; +/* Enable attached power regulator if any. */ +static int ak8975_power_on(struct i2c_client *client) +{ + const struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ak8975_data *data = iio_priv(indio_dev); + int ret; + + data->vdd = devm_regulator_get(&client->dev, "vdd"); + if (IS_ERR_OR_NULL(data->vdd)) { + ret = PTR_ERR(data->vdd); + if (ret == -ENODEV) + ret = 0; + } else { + ret = regulator_enable(data->vdd); + } + + if (ret) + dev_err(&client->dev, "failed to enable Vdd supply: %d\n", ret); + return ret; +} + +/* Disable attached power regulator if any. */ +static void ak8975_power_off(const struct i2c_client *client) +{ + const struct iio_dev *indio_dev = i2c_get_clientdata(client); + const struct ak8975_data *data = iio_priv(indio_dev); + + if (!IS_ERR_OR_NULL(data->vdd)) + regulator_disable(data->vdd); +} + /* * Return 0 if the i2c device is the one we expect. * return a negative error number otherwise @@ -380,23 +412,8 @@ static int ak8975_who_i_am(struct i2c_client *client, enum asahi_compass_chipset type) { u8 wia_val[2]; - struct regulator *vdd = devm_regulator_get_optional(&client->dev, - "vdd"); int ret; - /* Enable attached regulator if any. */ - if (!IS_ERR(vdd)) { - ret = regulator_enable(vdd); - if (ret) { - dev_err(&client->dev, "Failed to enable Vdd supply\n"); - return ret; - } - } else { - ret = PTR_ERR(vdd); - if (ret != -ENODEV) - return ret; - } - /* * Signature for each device: * Device | WIA1 | WIA2 @@ -804,10 +821,15 @@ static int ak8975_probe(struct i2c_client *client, } data->def = &ak_def_array[chipset]; + + err = ak8975_power_on(client); + if (err) + return err; + err = ak8975_who_i_am(client, data->def->type); if (err < 0) { dev_err(&client->dev, "Unexpected device\n"); - return err; + goto power_off; } dev_dbg(&client->dev, "Asahi compass chip %s\n", name); @@ -815,7 +837,7 @@ static int ak8975_probe(struct i2c_client *client, err = ak8975_setup(client); if (err < 0) { dev_err(&client->dev, "%s initialization fails\n", name); - return err; + goto power_off; } mutex_init(&data->lock); @@ -825,7 +847,26 @@ static int ak8975_probe(struct i2c_client *client, indio_dev->info = &ak8975_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = name; - return devm_iio_device_register(&client->dev, indio_dev); + + err = iio_device_register(indio_dev); + if (err) + goto power_off; + + return 0; + +power_off: + ak8975_power_off(client); + return err; +} + +static int ak8975_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + ak8975_power_off(client); + + return 0; } static const struct i2c_device_id ak8975_id[] = { @@ -859,6 +900,7 @@ static struct i2c_driver ak8975_driver = { .acpi_match_table = ACPI_PTR(ak_acpi_match), }, .probe = ak8975_probe, + .remove = ak8975_remove, .id_table = ak8975_id, }; module_i2c_driver(ak8975_driver); -- GitLab From cd47a3d3c72825b5feeb31c1974b0dc875692481 Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Thu, 10 Mar 2016 16:18:26 +0200 Subject: [PATCH 0116/9938] iwlwifi: mvm: make sure FW contains the right amount of paging sections Paging contains 3 sections in the fw. The first for the paging separator, The second for the CSS block, the third with the paging data. Currently if the driver finds the paging separator, and there is only section left (CSS), once reading the CSS section, the driver will attempt to read the paging data and will go out of the arrays bounds. Make sure that the FW image contains the right amount of sections for paging. Signed-off-by: Matti Gottlieb Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index ebbadcf41ea0..766c262500d2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -174,8 +174,12 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) } } - if (sec_idx >= IWL_UCODE_SECTION_MAX) { - IWL_ERR(mvm, "driver didn't find paging image\n"); + /* + * If paging is enabled there should be at least 2 more sections left + * (one for CSS and one for Paging data) + */ + if (sec_idx >= ARRAY_SIZE(image->sec) - 1) { + IWL_ERR(mvm, "Paging: Missing CSS and/or paging sections\n"); iwl_free_fw_paging(mvm); return -EINVAL; } -- GitLab From 5b086414293f906d8c5692cbbfa3500458982e5d Mon Sep 17 00:00:00 2001 From: Golan Ben-Ami Date: Tue, 9 Feb 2016 12:57:16 +0200 Subject: [PATCH 0117/9938] iwlwifi: mvm: support dumping UMAC internal txfifos In case of FW error, support dumping the UMAC internal txfifos. To do so, support version 2 of shared memory cfg command, which contains the sizes of the internal txfifos, and move the command to the system group. Signed-off-by: Golan Ben-Ami Signed-off-by: Emmanuel Grumbach --- .../intel/iwlwifi/iwl-fw-error-dump.h | 1 + .../net/wireless/intel/iwlwifi/iwl-fw-file.h | 3 + drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 12 +++ .../net/wireless/intel/iwlwifi/mvm/fw-api.h | 17 +++- .../net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 79 ++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 28 ++++++- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 8 ++ 8 files changed, 146 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h index 8425e1a587d9..09b7ea28f4a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h @@ -105,6 +105,7 @@ enum iwl_fw_error_dump_type { IWL_FW_ERROR_DUMP_RB = 11, IWL_FW_ERROR_DUMP_PAGING = 12, IWL_FW_ERROR_DUMP_RADIO_REG = 13, + IWL_FW_ERROR_DUMP_INTERNAL_TXF = 14, IWL_FW_ERROR_DUMP_MAX, }; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 15ec4e2907d8..3a72b9715930 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -324,6 +324,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_CTDP_SUPPORT: supports cTDP command * @IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED: supports usniffer enabled in * regular image. + * @IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG: support getting more shared + * memory addresses from the firmware. * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -361,6 +363,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT = (__force iwl_ucode_tlv_capa_t)75, IWL_UCODE_TLV_CAPA_CTDP_SUPPORT = (__force iwl_ucode_tlv_capa_t)76, IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED = (__force iwl_ucode_tlv_capa_t)77, + IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG = (__force iwl_ucode_tlv_capa_t)80, NUM_IWL_UCODE_TLV_CAPA #ifdef __CHECKER__ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index c46e596e12b1..6c1d20ded04b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -7,6 +7,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -33,6 +34,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -345,6 +347,16 @@ enum secure_load_status_reg { #define TXF_READ_MODIFY_DATA (0xa00448) #define TXF_READ_MODIFY_ADDR (0xa0044c) +/* UMAC Internal Tx Fifo */ +#define TXF_CPU2_FIFO_ITEM_CNT (0xA00538) +#define TXF_CPU2_WR_PTR (0xA00514) +#define TXF_CPU2_RD_PTR (0xA00510) +#define TXF_CPU2_FENCE_PTR (0xA00518) +#define TXF_CPU2_LOCK_FENCE (0xA00524) +#define TXF_CPU2_NUM (0xA0053C) +#define TXF_CPU2_READ_MODIFY_DATA (0xA00548) +#define TXF_CPU2_READ_MODIFY_ADDR (0xA0054C) + /* Radio registers access */ #define RSP_RADIO_CMD (0xa02804) #define RSP_RADIO_RDDAT (0xa02814) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 4a0fc47c81f2..61711b10ff82 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -287,6 +287,10 @@ enum iwl_phy_ops_subcmd_ids { DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, }; +enum iwl_system_subcmd_ids { + SHARED_MEM_CFG_CMD = 0x0, +}; + enum iwl_data_path_subcmd_ids { UPDATE_MU_GROUPS_CMD = 0x1, TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2, @@ -302,6 +306,7 @@ enum iwl_prot_offload_subcmd_ids { enum { LEGACY_GROUP = 0x0, LONG_GROUP = 0x1, + SYSTEM_GROUP = 0x2, PHY_OPS_GROUP = 0x4, DATA_PATH_GROUP = 0x5, PROT_OFFLOAD_GROUP = 0xb, @@ -1923,6 +1928,7 @@ struct iwl_tdls_config_res { #define TX_FIFO_MAX_NUM 8 #define RX_FIFO_MAX_NUM 2 +#define TX_FIFO_INTERNAL_MAX_NUM 6 /** * Shared memory configuration information from the FW @@ -1940,6 +1946,12 @@ struct iwl_tdls_config_res { * @page_buff_addr: used by UMAC and performance debug (page miss analysis), * when paging is not supported this should be 0 * @page_buff_size: size of %page_buff_addr + * @rxfifo_addr: Start address of rxFifo + * @internal_txfifo_addr: start address of internalFifo + * @internal_txfifo_size: internal fifos' size + * + * NOTE: on firmware that don't have IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG + * set, the last 3 members don't exist. */ struct iwl_shared_mem_cfg { __le32 shared_mem_addr; @@ -1951,7 +1963,10 @@ struct iwl_shared_mem_cfg { __le32 rxfifo_size[RX_FIFO_MAX_NUM]; __le32 page_buff_addr; __le32 page_buff_size; -} __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */ + __le32 rxfifo_addr; + __le32 internal_txfifo_addr; + __le32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM]; +} __packed; /* SHARED_MEM_ALLOC_API_S_VER_2 */ /** * VHT MU-MIMO group configuration diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 4856eac120f6..6ef706c13cda 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -7,7 +7,7 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -32,7 +32,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -265,6 +265,65 @@ static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm, *dump_data = iwl_fw_error_next_data(*dump_data); } + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) { + /* Pull UMAC internal TXF data from all TXFs */ + for (i = 0; + i < ARRAY_SIZE(mvm->shared_mem_cfg.internal_txfifo_size); + i++) { + /* Mark the number of TXF we're pulling now */ + iwl_trans_write_prph(mvm->trans, TXF_CPU2_NUM, i); + + fifo_hdr = (void *)(*dump_data)->data; + fifo_data = (void *)fifo_hdr->data; + fifo_len = mvm->shared_mem_cfg.internal_txfifo_size[i]; + + /* No need to try to read the data if the length is 0 */ + if (fifo_len == 0) + continue; + + /* Add a TLV for the internal FIFOs */ + (*dump_data)->type = + cpu_to_le32(IWL_FW_ERROR_DUMP_INTERNAL_TXF); + (*dump_data)->len = + cpu_to_le32(fifo_len + sizeof(*fifo_hdr)); + + fifo_hdr->fifo_num = cpu_to_le32(i); + fifo_hdr->available_bytes = + cpu_to_le32(iwl_trans_read_prph(mvm->trans, + TXF_CPU2_FIFO_ITEM_CNT)); + fifo_hdr->wr_ptr = + cpu_to_le32(iwl_trans_read_prph(mvm->trans, + TXF_CPU2_WR_PTR)); + fifo_hdr->rd_ptr = + cpu_to_le32(iwl_trans_read_prph(mvm->trans, + TXF_CPU2_RD_PTR)); + fifo_hdr->fence_ptr = + cpu_to_le32(iwl_trans_read_prph(mvm->trans, + TXF_CPU2_FENCE_PTR)); + fifo_hdr->fence_mode = + cpu_to_le32(iwl_trans_read_prph(mvm->trans, + TXF_CPU2_LOCK_FENCE)); + + /* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */ + iwl_trans_write_prph(mvm->trans, + TXF_CPU2_READ_MODIFY_ADDR, + TXF_CPU2_WR_PTR); + + /* Dummy-read to advance the read pointer to head */ + iwl_trans_read_prph(mvm->trans, + TXF_CPU2_READ_MODIFY_DATA); + + /* Read FIFO */ + fifo_len /= sizeof(u32); /* Size in DWORDS */ + for (j = 0; j < fifo_len; j++) + fifo_data[j] = + iwl_trans_read_prph(mvm->trans, + TXF_CPU2_READ_MODIFY_DATA); + *dump_data = iwl_fw_error_next_data(*dump_data); + } + } + iwl_trans_release_nic_access(mvm->trans, &flags); } @@ -494,6 +553,22 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) sizeof(struct iwl_fw_error_dump_fifo); } + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) { + for (i = 0; + i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); + i++) { + if (!mem_cfg->internal_txfifo_size[i]) + continue; + + /* Add header info */ + fifo_data_len += + mem_cfg->internal_txfifo_size[i] + + sizeof(*dump_data) + + sizeof(struct iwl_fw_error_dump_fifo); + } + } + /* Make room for PRPH registers */ for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) { /* The range includes both boundaries */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 766c262500d2..f375275ee98e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -794,17 +794,22 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) static void iwl_mvm_get_shared_mem_conf(struct iwl_mvm *mvm) { struct iwl_host_cmd cmd = { - .id = SHARED_MEM_CFG, .flags = CMD_WANT_SKB, .data = { NULL, }, .len = { 0, }, }; - struct iwl_rx_packet *pkt; struct iwl_shared_mem_cfg *mem_cfg; + struct iwl_rx_packet *pkt; u32 i; lockdep_assert_held(&mvm->mutex); + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) + cmd.id = iwl_cmd_id(SHARED_MEM_CFG_CMD, SYSTEM_GROUP, 0); + else + cmd.id = SHARED_MEM_CFG; + if (WARN_ON(iwl_mvm_send_cmd(mvm, &cmd))) return; @@ -830,6 +835,25 @@ static void iwl_mvm_get_shared_mem_conf(struct iwl_mvm *mvm) le32_to_cpu(mem_cfg->page_buff_addr); mvm->shared_mem_cfg.page_buff_size = le32_to_cpu(mem_cfg->page_buff_size); + + /* new API has more data */ + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) { + mvm->shared_mem_cfg.rxfifo_addr = + le32_to_cpu(mem_cfg->rxfifo_addr); + mvm->shared_mem_cfg.internal_txfifo_addr = + le32_to_cpu(mem_cfg->internal_txfifo_addr); + + BUILD_BUG_ON(sizeof(mvm->shared_mem_cfg.internal_txfifo_size) != + sizeof(mem_cfg->internal_txfifo_size)); + + for (i = 0; + i < ARRAY_SIZE(mvm->shared_mem_cfg.internal_txfifo_size); + i++) + mvm->shared_mem_cfg.internal_txfifo_size[i] = + le32_to_cpu(mem_cfg->internal_txfifo_size[i]); + } + IWL_DEBUG_INFO(mvm, "SHARED MEM CFG: got memory offsets/sizes\n"); iwl_free_resp(&cmd); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 9abbc93e3c06..6c67c0f631c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -602,6 +602,9 @@ struct iwl_mvm_shared_mem_cfg { u32 rxfifo_size[RX_FIFO_MAX_NUM]; u32 page_buff_addr; u32 page_buff_size; + u32 rxfifo_addr; + u32 internal_txfifo_addr; + u32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM]; }; struct iwl_mvm { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 5e8ab796d5bc..ccf6ecd21b18 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -418,6 +418,13 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(REPLY_DEBUG_CMD), }; +/* Please keep this array *SORTED* by hex value. + * Access is done through binary search + */ +static const struct iwl_hcmd_names iwl_mvm_system_names[] = { + HCMD_NAME(SHARED_MEM_CFG_CMD), +}; + /* Please keep this array *SORTED* by hex value. * Access is done through binary search */ @@ -449,6 +456,7 @@ static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = { static const struct iwl_hcmd_arr iwl_mvm_groups[] = { [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), + [SYSTEM_GROUP] = HCMD_ARR(iwl_mvm_system_names), [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), [DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names), [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), -- GitLab From 95a293c7ba17253b8cffcacbdd716ebfbfe42587 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Sun, 20 Mar 2016 23:29:45 -0300 Subject: [PATCH 0118/9938] regulator: Remove unneded check for regulator supply The regulator_resolve_supply() function checks if a supply has been associated with a regulator to avoid enabling it if that is not the case. But the supply was already looked up with regulator_resolve_supply() and set with set_supply() before the check and both return on error. So the fact that this statement has been reached means that neither of them failed and a supply must be associated with the regulator. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0b764284773..6dd63523bcfe 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1532,7 +1532,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) } /* Cascade always-on state to supply */ - if (_regulator_is_enabled(rdev) && rdev->supply) { + if (_regulator_is_enabled(rdev)) { ret = regulator_enable(rdev->supply); if (ret < 0) { _regulator_put(rdev->supply); -- GitLab From 3ae36c8b67e450dcb7011181658c198bec386e98 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 Mar 2016 08:54:46 +0800 Subject: [PATCH 0119/9938] spi: octeon: Convert to use devm_ioremap_resource Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi-octeon.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c index 07e4ce8273df..3b170093989f 100644 --- a/drivers/spi/spi-octeon.c +++ b/drivers/spi/spi-octeon.c @@ -175,6 +175,7 @@ static int octeon_spi_transfer_one_message(struct spi_master *master, static int octeon_spi_probe(struct platform_device *pdev) { struct resource *res_mem; + void __iomem *reg_base; struct spi_master *master; struct octeon_spi *p; int err = -ENOENT; @@ -186,19 +187,13 @@ static int octeon_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res_mem == NULL) { - dev_err(&pdev->dev, "found no memory resource\n"); - err = -ENXIO; - goto fail; - } - if (!devm_request_mem_region(&pdev->dev, res_mem->start, - resource_size(res_mem), res_mem->name)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); + reg_base = devm_ioremap_resource(&pdev->dev, res_mem); + if (IS_ERR(reg_base)) { + err = PTR_ERR(reg_base); goto fail; } - p->register_base = (u64)devm_ioremap(&pdev->dev, res_mem->start, - resource_size(res_mem)); + + p->register_base = (u64)reg_base; master->num_chipselect = 4; master->mode_bits = SPI_CPHA | -- GitLab From 9d71d47eed20f34620e54e29bcc90f959d5873b8 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 17 Mar 2016 10:51:04 +0100 Subject: [PATCH 0120/9938] ath10k: fix tx hang The wake_tx_queue/push_pending logic had a bug which could stop queues indefinitely effectivelly breaking traffic. Fixes: 299468782d94 ("ath10k: implement wake_tx_queue") Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index eedfe821700b..1bc4bf1916a6 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3777,13 +3777,13 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar) } list_del_init(&artxq->list); + if (ret != -ENOENT) + list_add_tail(&artxq->list, &ar->txqs); + ath10k_htt_tx_txq_update(hw, txq); - if (artxq == last || (ret < 0 && ret != -ENOENT)) { - if (ret != -ENOENT) - list_add_tail(&artxq->list, &ar->txqs); + if (artxq == last || (ret < 0 && ret != -ENOENT)) break; - } } rcu_read_unlock(); -- GitLab From 750eeed89cf3c466df302e4707491b015531e26c Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 17 Mar 2016 10:51:05 +0100 Subject: [PATCH 0121/9938] ath10k: fix pull-push tx threshold handling This prevents tx hangs or hiccups if pull-push supporting firmware defines per-txq thresholds or switches modes dynamically. Fixes: 299468782d94 ("ath10k: implement wake_tx_queue") Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 1bc4bf1916a6..ed00853ea9cc 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3770,7 +3770,8 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar) /* Prevent aggressive sta/tid taking over tx queue */ max = 16; - while (max--) { + ret = 0; + while (ath10k_mac_tx_can_push(hw, txq) && max--) { ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; @@ -4023,14 +4024,13 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, struct ath10k *ar = hw->priv; struct ath10k_txq *artxq = (void *)txq->drv_priv; - if (ath10k_mac_tx_can_push(hw, txq)) { - spin_lock_bh(&ar->txqs_lock); - if (list_empty(&artxq->list)) - list_add_tail(&artxq->list, &ar->txqs); - spin_unlock_bh(&ar->txqs_lock); + spin_lock_bh(&ar->txqs_lock); + if (list_empty(&artxq->list)) + list_add_tail(&artxq->list, &ar->txqs); + spin_unlock_bh(&ar->txqs_lock); + if (ath10k_mac_tx_can_push(hw, txq)) tasklet_schedule(&ar->htt.txrx_compl_task); - } ath10k_htt_tx_txq_update(hw, txq); } -- GitLab From 8866c727440d5b059637cb97927e383548099e8c Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 17 Mar 2016 10:52:08 +0100 Subject: [PATCH 0122/9938] ath10k: fix null deref if device crashes early If device failed to init during early probing (which is quite rare) it triggered driver to compute crc before ar->firmware was ready causing an oops. Fixes: 3e58044b61a9 ("ath10k: print crc32 checksums for firmware and board files") Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 0f834646e6a7..2cf1b350ac73 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -127,6 +127,7 @@ EXPORT_SYMBOL(ath10k_info); void ath10k_debug_print_hwfw_info(struct ath10k *ar) { char fw_features[128] = {}; + u32 crc = 0; ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features)); @@ -143,11 +144,14 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar) config_enabled(CONFIG_ATH10K_DFS_CERTIFIED), config_enabled(CONFIG_NL80211_TESTMODE)); + if (ar->firmware) + crc = crc32_le(0, ar->firmware->data, ar->firmware->size); + ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n", ar->hw->wiphy->fw_version, ar->fw_api, fw_features, - crc32_le(0, ar->firmware->data, ar->firmware->size)); + crc); } void ath10k_debug_print_board_info(struct ath10k *ar) -- GitLab From a47aaa69de88913d1640c4bd28c67fad142c61a3 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 18 Mar 2016 11:44:21 +0200 Subject: [PATCH 0123/9938] dt: bindings: add new dt entry for pre calibration in qcom, ath10k.txt There two things done in this patch, 1) Existing device tree entry 'qcom,ath10k-calibration-data' carries not only calibration data, it carries board specific data too. So, make appropriate update in doc. 2) ipq4019 wifi needs new devie tree entry to carry calibration data alone (called pre cal data, it doesn't include any other info). Using 'qcom,ath10k-calibration-data' for ipq4019 would alter the purpose of it. Hence, add new device tree entry called 'qcom,ath10k-pre-calibration-data' to carry only pre calibration data. Signed-off-by: Raja Mani Acked-by: Rob Herring Signed-off-by: Kalle Valo --- .../bindings/net/wireless/qcom,ath10k.txt | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt index 96aae6b4f736..74d7f0af209c 100644 --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt @@ -5,12 +5,18 @@ Required properties: * "qcom,ath10k" * "qcom,ipq4019-wifi" -PCI based devices uses compatible string "qcom,ath10k" and takes only -calibration data via "qcom,ath10k-calibration-data". Rest of the properties -are not applicable for PCI based devices. +PCI based devices uses compatible string "qcom,ath10k" and takes calibration +data along with board specific data via "qcom,ath10k-calibration-data". +Rest of the properties are not applicable for PCI based devices. AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi" -and also uses most of the properties defined in this doc. +and also uses most of the properties defined in this doc (except +"qcom,ath10k-calibration-data"). It uses "qcom,ath10k-pre-calibration-data" +to carry pre calibration data. + +In general, entry "qcom,ath10k-pre-calibration-data" and +"qcom,ath10k-calibration-data" conflict with each other and only one +can be provided per device. Optional properties: - reg: Address and length of the register set for the device. @@ -35,8 +41,11 @@ Optional properties: - qcom,msi_addr: MSI interrupt address. - qcom,msi_base: Base value to add before writing MSI data into MSI address register. -- qcom,ath10k-calibration-data : calibration data as an array, the - length can vary between hw versions +- qcom,ath10k-calibration-data : calibration data + board specific data + as an array, the length can vary between + hw versions. +- qcom,ath10k-pre-calibration-data : pre calibration data as an array, + the length can vary between hw versions. Example (to supply the calibration data alone): @@ -105,5 +114,5 @@ wifi0: wifi@a000000 { "legacy"; qcom,msi_addr = <0x0b006040>; qcom,msi_base = <0x40>; - qcom,ath10k-calibration-data = [ 01 02 03 ... ]; + qcom,ath10k-pre-calibration-data = [ 01 02 03 ... ]; }; -- GitLab From de14ba67378df74c6328f75fd6972ef83ed4639b Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Thu, 17 Mar 2016 15:05:05 +0100 Subject: [PATCH 0124/9938] regulator: act8865: Remove redundant dev lookups The local variable "dev" already contains a pointer to the device, so there is no need to take the address of "client->dev" again. Signed-off-by: Maarten ter Huurne Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 000d566e32a4..89f856f257f7 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -498,8 +498,7 @@ static int act8865_pmic_probe(struct i2c_client *client, act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config); if (IS_ERR(act8865->regmap)) { ret = PTR_ERR(act8865->regmap); - dev_err(&client->dev, "Failed to allocate register map: %d\n", - ret); + dev_err(dev, "Failed to allocate register map: %d\n", ret); return ret; } @@ -526,7 +525,7 @@ static int act8865_pmic_probe(struct i2c_client *client, config.driver_data = act8865; config.regmap = act8865->regmap; - rdev = devm_regulator_register(&client->dev, desc, &config); + rdev = devm_regulator_register(dev, desc, &config); if (IS_ERR(rdev)) { dev_err(dev, "failed to register %s\n", desc->name); return PTR_ERR(rdev); -- GitLab From e6e79fd9cee682b137779d2da3b379251927d99f Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Thu, 17 Mar 2016 15:05:06 +0100 Subject: [PATCH 0125/9938] regulator: act8865: Remove "too many regulators" error handler The check would dereference pdata, which can be NULL in the non-DT use case. Nothing will break if pdata->num_regulators is larger than the number of regulators that the driver defines: pdata->num_regulators is only read in act8865_get_init_data() to iterate through pdata->regulators. The error handler might have some value as a sanity check on the platform data, but the platform data could be broken in many other ways that are not checked for (unknown IDs, duplicate IDs), so I see no reason to perform only this specific check. Signed-off-by: Maarten ter Huurne Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 89f856f257f7..69cdad0f71ba 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -485,12 +485,6 @@ static int act8865_pmic_probe(struct i2c_client *client, pdata = &pdata_of; } - if (pdata->num_regulators > num_regulators) { - dev_err(dev, "too many regulators: %d\n", - pdata->num_regulators); - return -EINVAL; - } - act8865 = devm_kzalloc(dev, sizeof(struct act8865), GFP_KERNEL); if (!act8865) return -ENOMEM; -- GitLab From 178ff7c6f3916aff3c3eaaec8636be3b41e93011 Mon Sep 17 00:00:00 2001 From: John Lin Date: Mon, 15 Feb 2016 10:40:17 +0800 Subject: [PATCH 0126/9938] ASoC: rt5645: Add dmi_system_id "Google Setzer" Add platform specific data for Setzer project. Signed-off-by: John Lin Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 7af5e7380d61..dff706ac7895 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3557,6 +3557,12 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), }, }, + { + .ident = "Google Setzer", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"), + }, + }, { } }; -- GitLab From d1ef4f2cae6705925088047554e89c34048f926a Mon Sep 17 00:00:00 2001 From: Marc Titinger Date: Mon, 14 Mar 2016 11:20:44 +0100 Subject: [PATCH 0127/9938] iio: ina2xx-adc: update the CALIB. register when RShunt changes The user (or an init script) may setup RShunt via sysfs after the driver was initialized, for instance based on the EEPROM contents of a modular probe. The calibration register must be set accordingly. Signed-off-by: Marc Titinger Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ina2xx-adc.c | 39 ++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 65909d5858b1..4e56fe3580bf 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev, return len; } +/* + * Set current LSB to 1mA, shunt is in uOhms + * (equation 13 in datasheet). We hardcode a Current_LSB + * of 1.0 x10-6. The only remaining parameter is RShunt. + * There is no need to expose the CALIBRATION register + * to the user for now. But we need to reset this register + * if the user updates RShunt after driver init, e.g upon + * reading an EEPROM/Probe-type value. + */ +static int ina2xx_set_calibration(struct ina2xx_chip_info *chip) +{ + u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor, + chip->shunt_resistor); + + return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval); +} + static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val) { if (val <= 0 || val > chip->config->calibration_factor) @@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, if (ret) return ret; + /* Update the Calibration register */ + ret = ina2xx_set_calibration(chip); + if (ret) + return ret; + return len; } @@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = { /* Initialize the configuration and calibration registers. */ static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config) { - u16 regval; - int ret; - - ret = regmap_write(chip->regmap, INA2XX_CONFIG, config); + int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config); if (ret) return ret; - /* - * Set current LSB to 1mA, shunt is in uOhms - * (equation 13 in datasheet). We hardcode a Current_LSB - * of 1.0 x10-6. The only remaining parameter is RShunt. - * There is no need to expose the CALIBRATION register - * to the user for now. - */ - regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor, - chip->shunt_resistor); - - return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval); + return ina2xx_set_calibration(chip); } static int ina2xx_probe(struct i2c_client *client, -- GitLab From 895fe2321efaf62023fdd8239d1846394df68570 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Mar 2016 18:17:43 +0000 Subject: [PATCH 0128/9938] regulator: core: Always flag voltage constraints as appliable Allow the core to always use the voltage constraints to set the voltage on startup. A forthcoming change in that code will ensure that we bring out of constraints voltages into spec with this setting. Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 6b0aa80b22fd..d2ddefaaddaf 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -43,12 +43,10 @@ static void of_get_regulation_constraints(struct device_node *np, constraints->max_uV = pval; /* Voltage change possible? */ - if (constraints->min_uV != constraints->max_uV) + if (constraints->min_uV != constraints->max_uV) { constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; - /* Only one voltage? Then make sure it's set. */ - if (constraints->min_uV && constraints->max_uV && - constraints->min_uV == constraints->max_uV) constraints->apply_uV = true; + } if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval)) constraints->uV_offset = pval; -- GitLab From f454add47adb4133f297e1b7af07bf07b3983044 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 18 Mar 2016 11:44:21 +0200 Subject: [PATCH 0129/9938] ath10k: pass cal data location as an argument to ath10k_download_cal_{file|dt} Both ath10k_download_cal_file() and ath10k_download_cal_dt() uses hard coded file pointer (ar->cal_file) and device tree entry (qcom,ath10k-calibration-data) respectively to get calibration data content. There is a need to use those two functions in qca4019 calibration download sequence with different file pointer and device tree entry name. Modify those two functions to take cal data location as an argument. So that it can serve the purpose for other file pointer and device tree entry. This is just preparation before adding actual qca4019 calibration download sequence. No functional changes. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index d5d0b88aa5fe..7c4a9c99b268 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -462,18 +462,18 @@ static int ath10k_download_board_data(struct ath10k *ar, const void *data, return ret; } -static int ath10k_download_cal_file(struct ath10k *ar) +static int ath10k_download_cal_file(struct ath10k *ar, + const struct firmware *file) { int ret; - if (!ar->cal_file) + if (!file) return -ENOENT; - if (IS_ERR(ar->cal_file)) - return PTR_ERR(ar->cal_file); + if (IS_ERR(file)) + return PTR_ERR(file); - ret = ath10k_download_board_data(ar, ar->cal_file->data, - ar->cal_file->size); + ret = ath10k_download_board_data(ar, file->data, file->size); if (ret) { ath10k_err(ar, "failed to download cal_file data: %d\n", ret); return ret; @@ -484,7 +484,7 @@ static int ath10k_download_cal_file(struct ath10k *ar) return 0; } -static int ath10k_download_cal_dt(struct ath10k *ar) +static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name) { struct device_node *node; int data_len; @@ -498,8 +498,7 @@ static int ath10k_download_cal_dt(struct ath10k *ar) */ return -ENOENT; - if (!of_get_property(node, "qcom,ath10k-calibration-data", - &data_len)) { + if (!of_get_property(node, dt_name, &data_len)) { /* The calibration data node is optional */ return -ENOENT; } @@ -517,8 +516,7 @@ static int ath10k_download_cal_dt(struct ath10k *ar) goto out; } - ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data", - data, data_len); + ret = of_property_read_u8_array(node, dt_name, data, data_len); if (ret) { ath10k_warn(ar, "failed to read calibration data from DT: %d\n", ret); @@ -1258,7 +1256,7 @@ static int ath10k_download_cal_data(struct ath10k *ar) { int ret; - ret = ath10k_download_cal_file(ar); + ret = ath10k_download_cal_file(ar, ar->cal_file); if (ret == 0) { ar->cal_mode = ATH10K_CAL_MODE_FILE; goto done; @@ -1268,7 +1266,7 @@ static int ath10k_download_cal_data(struct ath10k *ar) "boot did not find a calibration file, try DT next: %d\n", ret); - ret = ath10k_download_cal_dt(ar); + ret = ath10k_download_cal_dt(ar, "qcom,ath10k-calibration-data"); if (ret == 0) { ar->cal_mode = ATH10K_CAL_MODE_DT; goto done; -- GitLab From 0b8e3c4ca29fe2c0efd3d41a76e34a657b9f17a4 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 18 Mar 2016 11:44:22 +0200 Subject: [PATCH 0130/9938] ath10k: move cal data len to hw_params ath10k_download_cal_dt() compares obtained cal data content length against QCA988X_CAL_DATA_LEN (2116 bytes). It was written by keeping qca988x in mind. In fact, cal data length is more chip specific. To make ath10k_download_cal_dt() more generic and reusable for other chipsets (like qca4019), cal data length is moved to hw_params. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 11 ++++++++++- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/debug.c | 7 ++++--- drivers/net/wireless/ath/ath10k/hw.h | 2 -- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 7c4a9c99b268..c33fad96a1e8 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -60,6 +60,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, + .cal_data_len = 2116, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .fw = QCA988X_HW_2_0_FW_FILE, @@ -78,6 +79,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, + .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, .fw = QCA6174_HW_2_1_FW_FILE, @@ -97,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, + .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, .fw = QCA6174_HW_2_1_FW_FILE, @@ -116,6 +119,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, + .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, .fw = QCA6174_HW_3_0_FW_FILE, @@ -135,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, + .cal_data_len = 8124, .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, @@ -159,6 +164,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .tx_chain_mask = 0xf, .rx_chain_mask = 0xf, .max_spatial_stream = 4, + .cal_data_len = 12064, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, @@ -177,6 +183,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, + .cal_data_len = 8124, .fw = { .dir = QCA9377_HW_1_0_FW_DIR, .fw = QCA9377_HW_1_0_FW_FILE, @@ -195,6 +202,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, + .cal_data_len = 8124, .fw = { .dir = QCA9377_HW_1_0_FW_DIR, .fw = QCA9377_HW_1_0_FW_FILE, @@ -218,6 +226,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .tx_chain_mask = 0x3, .rx_chain_mask = 0x3, .max_spatial_stream = 2, + .cal_data_len = 12064, .fw = { .dir = QCA4019_HW_1_0_FW_DIR, .fw = QCA4019_HW_1_0_FW_FILE, @@ -503,7 +512,7 @@ static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name) return -ENOENT; } - if (data_len != QCA988X_CAL_DATA_LEN) { + if (data_len != ar->hw_params.cal_data_len) { ath10k_warn(ar, "invalid calibration data length in DT: %d\n", data_len); ret = -EMSGSIZE; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index bb5f7e22fc1e..73edd69ed7e7 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -695,6 +695,7 @@ struct ath10k { u32 tx_chain_mask; u32 rx_chain_mask; u32 max_spatial_stream; + u32 cal_data_len; struct ath10k_hw_params_fw { const char *dir; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 2cf1b350ac73..dec7e054b4b6 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1451,7 +1451,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file) goto err; } - buf = vmalloc(QCA988X_CAL_DATA_LEN); + buf = vmalloc(ar->hw_params.cal_data_len); if (!buf) { ret = -ENOMEM; goto err; @@ -1466,7 +1466,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file) } ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf, - QCA988X_CAL_DATA_LEN); + ar->hw_params.cal_data_len); if (ret) { ath10k_warn(ar, "failed to read calibration data: %d\n", ret); goto err_vfree; @@ -1491,10 +1491,11 @@ static ssize_t ath10k_debug_cal_data_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { + struct ath10k *ar = file->private_data; void *buf = file->private_data; return simple_read_from_buffer(user_buf, count, ppos, - buf, QCA988X_CAL_DATA_LEN); + buf, ar->hw_params.cal_data_len); } static int ath10k_debug_cal_data_release(struct inode *inode, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 1ff617b05010..c0179bc4af29 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -134,8 +134,6 @@ enum qca9377_chip_id_rev { #define REG_DUMP_COUNT_QCA988X 60 -#define QCA988X_CAL_DATA_LEN 2116 - struct ath10k_fw_ie { __le32 id; __le32 len; -- GitLab From 3d9195ea19e4854d7daa11688b01905e244aead9 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 18 Mar 2016 11:44:22 +0200 Subject: [PATCH 0131/9938] ath10k: incorporate qca4019 cal data download sequence qca4019 calibration data is stored in the host memory and it's mandatory to download it even before reading board id and chip id from the target. Also, there is a need to execute otp (download and run) twice, one after cal data download and another one after board data download. Existing cal data file name 'cal--.bin' and device tree entry 'qcom,ath10k-calibration-data' used in ath10k has assumption that it carries other data (like board data) also along with the calibration data. But, qca4019 cal data contains pure calibration data (doesn't include any other info). So, using existing same cal file name and DT entry in qca4019 case would alter the purpose of it. To avoid this, new cal file name 'pre-cal--.bin' and new device tree entry name 'qcom,ath10k-pre-calibration-data are introduced. Overall qca4019's firmware download sequence would look like, 1) Download cal data (either from a file or device tree entry) at the address specified by target in the host interest area member "hi_board_data". 2) Download otp and run with 0x10 (PARAM_GET_EEPROM_BOARD_ID) as a argument. At this point, otp will take back up of downloaded cal data content in another location in the target and return valid board id and chip id to the host. 3) Download board data at the address specified by target in host interest area member "hi_board_data". 4) Download otp and run with 0x10000 (PARAM_FLASH_SECTION_ALL) as a argument. Now otp will apply cal data content from it's backup on top of board data download in step 3 and prepare final data base. 5) Download code swap and athwlan binary content. Above sequences are implemented (step 1 to step 4) in the name of pre calibration configuration. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 85 +++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/core.h | 11 +++- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index c33fad96a1e8..8b35e3adcee9 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -729,6 +729,14 @@ static int ath10k_fetch_cal_file(struct ath10k *ar) { char filename[100]; + /* pre-cal--.bin */ + scnprintf(filename, sizeof(filename), "pre-cal-%s-%s.bin", + ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); + + ar->pre_cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); + if (!IS_ERR(ar->pre_cal_file)) + goto success; + /* cal--.bin */ scnprintf(filename, sizeof(filename), "cal-%s-%s.bin", ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); @@ -737,7 +745,7 @@ static int ath10k_fetch_cal_file(struct ath10k *ar) if (IS_ERR(ar->cal_file)) /* calibration file is optional, don't print any warnings */ return PTR_ERR(ar->cal_file); - +success: ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n", ATH10K_FW_DIR, filename); @@ -1261,10 +1269,76 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) return 0; } +static int ath10k_core_pre_cal_download(struct ath10k *ar) +{ + int ret; + + ret = ath10k_download_cal_file(ar, ar->pre_cal_file); + if (ret == 0) { + ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE; + goto success; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot did not find a pre calibration file, try DT next: %d\n", + ret); + + ret = ath10k_download_cal_dt(ar, "qcom,ath10k-pre-calibration-data"); + if (ret) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "unable to load pre cal data from DT: %d\n", ret); + return ret; + } + ar->cal_mode = ATH10K_PRE_CAL_MODE_DT; + +success: + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n", + ath10k_cal_mode_str(ar->cal_mode)); + + return 0; +} + +static int ath10k_core_pre_cal_config(struct ath10k *ar) +{ + int ret; + + ret = ath10k_core_pre_cal_download(ar); + if (ret) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "failed to load pre cal data: %d\n", ret); + return ret; + } + + ret = ath10k_core_get_board_id_from_otp(ar); + if (ret) { + ath10k_err(ar, "failed to get board id: %d\n", ret); + return ret; + } + + ret = ath10k_download_and_run_otp(ar); + if (ret) { + ath10k_err(ar, "failed to run otp: %d\n", ret); + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "pre cal configuration done successfully\n"); + + return 0; +} + static int ath10k_download_cal_data(struct ath10k *ar) { int ret; + ret = ath10k_core_pre_cal_config(ar); + if (ret == 0) + return 0; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "pre cal download procedure failed, try cal file: %d\n", + ret); + ret = ath10k_download_cal_file(ar, ar->cal_file); if (ret == 0) { ar->cal_mode = ATH10K_CAL_MODE_FILE; @@ -1842,6 +1916,15 @@ static int ath10k_core_probe_fw(struct ath10k *ar) ath10k_debug_print_hwfw_info(ar); + ret = ath10k_core_pre_cal_download(ar); + if (ret) { + /* pre calibration data download is not necessary + * for all the chipsets. Ignore failures and continue. + */ + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "could not load pre cal data: %d\n", ret); + } + ret = ath10k_core_get_board_id_from_otp(ar); if (ret && ret != -EOPNOTSUPP) { ath10k_err(ar, "failed to get board id from otp: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 73edd69ed7e7..b6c157ef705a 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -567,6 +567,8 @@ enum ath10k_cal_mode { ATH10K_CAL_MODE_FILE, ATH10K_CAL_MODE_OTP, ATH10K_CAL_MODE_DT, + ATH10K_PRE_CAL_MODE_FILE, + ATH10K_PRE_CAL_MODE_DT, }; enum ath10k_crypt_mode { @@ -585,6 +587,10 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode) return "otp"; case ATH10K_CAL_MODE_DT: return "dt"; + case ATH10K_PRE_CAL_MODE_FILE: + return "pre-cal-file"; + case ATH10K_PRE_CAL_MODE_DT: + return "pre-cal-dt"; } return "unknown"; @@ -719,7 +725,10 @@ struct ath10k { const void *firmware_data; size_t firmware_len; - const struct firmware *cal_file; + union { + const struct firmware *pre_cal_file; + const struct firmware *cal_file; + }; struct { const void *firmware_codeswap_data; -- GitLab From cc61a1bbbc0ebbda3cc155bcbe164f4609fd62f6 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 16 Mar 2016 18:13:32 +0530 Subject: [PATCH 0132/9938] ath10k: enable debugfs provision to enable Peer Stats feature Provide a debugfs entry to enable/ disable Peer Stats feature. Peer Stats feature is for developers/users who are more interested in studying in Rx/Tx stats with multiple clients connected, hence disable this by default. Enabling this feature by default results in unneccessary processing of Peer Stats event for every 500ms and updating peer_stats list (allocating memory) and cleaning it up ifexceeds the higher limit and this can be an unnecessary overhead during long run stress testing. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 2 +- drivers/net/wireless/ath/ath10k/core.h | 12 ++++ drivers/net/wireless/ath/ath10k/debug.c | 80 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.c | 12 ++-- 5 files changed, 94 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 8b35e3adcee9..7a714d971615 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1586,7 +1586,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) case ATH10K_FW_WMI_OP_VERSION_10_1: case ATH10K_FW_WMI_OP_VERSION_10_2: case ATH10K_FW_WMI_OP_VERSION_10_2_4: - if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { + if (ath10k_peer_stats_enabled(ar)) { ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS; ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS; } else { diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index b6c157ef705a..c23c37312ef7 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -561,6 +561,9 @@ enum ath10k_dev_flags { /* Bluetooth coexistance enabled */ ATH10K_FLAG_BTCOEX, + + /* Per Station statistics service */ + ATH10K_FLAG_PEER_STATS, }; enum ath10k_cal_mode { @@ -903,6 +906,15 @@ struct ath10k { u8 drv_priv[0] __aligned(sizeof(void *)); }; +static inline bool ath10k_peer_stats_enabled(struct ath10k *ar) +{ + if (test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) && + test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) + return true; + + return false; +} + struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, enum ath10k_bus bus, enum ath10k_hw_rev hw_rev, diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index dec7e054b4b6..76bbe17b25b6 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -323,7 +323,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_fw_stats stats = {}; - bool is_start, is_started, is_end, peer_stats_svc; + bool is_start, is_started, is_end; size_t num_peers; size_t num_vdevs; int ret; @@ -350,13 +350,11 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) * b) consume stat update events until another one with pdev stats is * delivered which is treated as end-of-data and is itself discarded */ - - peer_stats_svc = test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map); - if (peer_stats_svc) + if (ath10k_peer_stats_enabled(ar)) ath10k_sta_update_rx_duration(ar, &stats.peers); if (ar->debug.fw_stats_done) { - if (!peer_stats_svc) + if (!ath10k_peer_stats_enabled(ar)) ath10k_warn(ar, "received unsolicited stats update event\n"); goto free; @@ -2184,6 +2182,73 @@ static const struct file_operations fops_btcoex = { .open = simple_open }; +static ssize_t ath10k_write_peer_stats(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + char buf[32]; + size_t buf_size; + int ret = 0; + bool val; + + buf_size = min(count, (sizeof(buf) - 1)); + if (copy_from_user(buf, ubuf, buf_size)) + return -EFAULT; + + buf[buf_size] = '\0'; + + if (strtobool(buf, &val) != 0) + return -EINVAL; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH10K_STATE_ON && + ar->state != ATH10K_STATE_RESTARTED) { + ret = -ENETDOWN; + goto exit; + } + + if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) + goto exit; + + if (val) + set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags); + else + clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags); + + ath10k_info(ar, "restarting firmware due to Peer stats change"); + + queue_work(ar->workqueue, &ar->restart_work); + ret = count; + +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) + +{ + char buf[32]; + struct ath10k *ar = file->private_data; + int len = 0; + + mutex_lock(&ar->conf_mutex); + len = scnprintf(buf, sizeof(buf) - len, "%d\n", + test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags)); + mutex_unlock(&ar->conf_mutex); + + return simple_read_from_buffer(ubuf, count, ppos, buf, len); +} + +static const struct file_operations fops_peer_stats = { + .read = ath10k_read_peer_stats, + .write = ath10k_write_peer_stats, + .open = simple_open +}; + static ssize_t ath10k_debug_fw_checksums_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -2347,6 +2412,11 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("btcoex", S_IRUGO | S_IWUSR, ar->debug.debugfs_phy, ar, &fops_btcoex); + if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) + debugfs_create_file("peer_stats", S_IRUGO | S_IWUSR, + ar->debug.debugfs_phy, ar, + &fops_peer_stats); + debugfs_create_file("fw_checksums", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_fw_checksums); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ed00853ea9cc..20d72e29dfa1 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4435,7 +4435,7 @@ static int ath10k_start(struct ieee80211_hw *hw) ar->ani_enabled = true; - if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { + if (ath10k_peer_stats_enabled(ar)) { param = ar->wmi.pdev_param->peer_stats_update_period; ret = ath10k_wmi_pdev_set_param(ar, param, PEER_DEFAULT_STATS_UPDATE_PERIOD); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 91375664dc35..afed9dab74f4 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2856,11 +2856,8 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, const struct wmi_10_2_4_ext_peer_stats *src; struct ath10k_fw_stats_peer *dst; int stats_len; - bool ext_peer_stats_support; - ext_peer_stats_support = test_bit(WMI_SERVICE_PEER_STATS, - ar->wmi.svc_map); - if (ext_peer_stats_support) + if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) stats_len = sizeof(struct wmi_10_2_4_ext_peer_stats); else stats_len = sizeof(struct wmi_10_2_4_peer_stats); @@ -2877,7 +2874,7 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate); - if (ext_peer_stats_support) + if (ath10k_peer_stats_enabled(ar)) dst->rx_duration = __le32_to_cpu(src->rx_duration); /* FIXME: expose 10.2 specific values */ @@ -5514,7 +5511,8 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); - if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { + + if (ath10k_peer_stats_enabled(ar)) { config.num_peers = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_PEERS); config.num_tids = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_TIDS); } else { @@ -5576,7 +5574,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map)) features |= WMI_10_2_COEX_GPIO; - if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) + if (ath10k_peer_stats_enabled(ar)) features |= WMI_10_2_PEER_STATS; cmd->resource_config.feature_mask = __cpu_to_le32(features); -- GitLab From bf23d1917d551487e85378c4f4a7a0efcfe77f4e Mon Sep 17 00:00:00 2001 From: Kamlakant Patel Date: Tue, 22 Mar 2016 18:38:14 +0530 Subject: [PATCH 0133/9938] spi: xlp: Enable SPI driver for Broadcom Vulcan ARM64 - Vulcan spi controller is compatible with netlogic,xlp832-spi. - Add depends on ARCH_VULCAN to Kconfig to enable spi controller driver for Broadcom Vulcan ARM64 SoCs. Signed-off-by: Kamlakant Patel Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9d8c84bb1544..6536068ce74f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -656,7 +656,7 @@ config SPI_XILINX config SPI_XLP tristate "Netlogic XLP SPI controller driver" - depends on CPU_XLP || COMPILE_TEST + depends on CPU_XLP || ARCH_VULCAN || COMPILE_TEST help Enable support for the SPI controller on the Netlogic XLP SoCs. Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, XLP9XX -- GitLab From d13d3a573be5535123beacd926be38e571097bc5 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 23 Mar 2016 11:24:47 +0000 Subject: [PATCH 0134/9938] regulator: add missing descriptions in regulator_desc Members csel_reg and csel_mask of the regulator_desc struct are missing descriptions for documentation. Adding them. Signed-off-by: Luis de Bethencourt Signed-off-by: Mark Brown --- include/linux/regulator/driver.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index cd271e89a7e6..01d26244a610 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -255,6 +255,8 @@ enum regulator_type { * * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_mask: Mask for register bitfield used for selector + * @csel_reg: Register for TPS65218 LS3 current regulator + * @csel_mask: Mask for TPS65218 LS3 current regulator * @apply_reg: Register for initiate voltage change on the output when * using regulator_set_voltage_sel_regmap * @apply_bit: Register bitfield used for initiate voltage change on the -- GitLab From abf2f825d115397944cab91a20c937331d77e37c Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 23 Mar 2016 11:35:39 +0000 Subject: [PATCH 0135/9938] regulator: add missing description for set_over_current_protection Over current protection is missing descriptions for documentation. Signed-off-by: Luis de Bethencourt Signed-off-by: Mark Brown --- include/linux/regulator/driver.h | 3 +++ include/linux/regulator/machine.h | 1 + 2 files changed, 4 insertions(+) diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 01d26244a610..1392022fe509 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -93,6 +93,9 @@ struct regulator_linear_range { * @get_current_limit: Get the configured limit for a current-limited regulator. * @set_input_current_limit: Configure an input limit. * + * @set_over_current_protection: Support capability of automatically shutting + * down when detecting an over current event. + * * @set_active_discharge: Set active discharge enable/disable of regulators. * * @set_mode: Set the configured operating mode for the regulator. diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 5d627c83a630..ad3e5158e586 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -97,6 +97,7 @@ struct regulator_state { * @ramp_disable: Disable ramp delay when initialising or when setting voltage. * @soft_start: Enable soft start so that voltage ramps slowly. * @pull_down: Enable pull down when regulator is disabled. + * @over_current_protection: Auto disable on over current event. * * @input_uV: Input voltage for regulator when supplied by another regulator. * -- GitLab From 9f9f8b863ad130ec0c25f378bdbad64ba71291de Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 23 Mar 2016 12:13:12 +0000 Subject: [PATCH 0136/9938] regmap: mmio: Fix value endianness selection Currently when selecting value endianness we check the register endiannes, not the value endianness. Reported-by: Alexander Stein Tested-by: Alexander Stein Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 7526906ca080..b27573c69af7 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -245,7 +245,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, ctx->val_bytes = config->val_bits / 8; ctx->clk = ERR_PTR(-ENODEV); - switch (config->reg_format_endian) { + switch (config->val_format_endian) { case REGMAP_ENDIAN_DEFAULT: case REGMAP_ENDIAN_LITTLE: #ifdef __LITTLE_ENDIAN -- GitLab From 9419b2006cf47c75985ea51d36ddc51346d29efd Mon Sep 17 00:00:00 2001 From: Bhuvanchandra DV Date: Tue, 22 Mar 2016 01:41:52 +0530 Subject: [PATCH 0137/9938] spi: fsl-dspi: Set max_speed_hz for master Calculate and update max speed from bus clock for SoCs using DSPI IP. The bus clock factor's are taken from the data sheets of respective SoCs. Signed-off-by: Bhuvanchandra DV Acked-by: Stefan Agner Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 39412c9097c6..559ed70fd229 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -121,18 +121,22 @@ enum dspi_trans_mode { struct fsl_dspi_devtype_data { enum dspi_trans_mode trans_mode; + u8 max_clock_factor; }; static const struct fsl_dspi_devtype_data vf610_data = { .trans_mode = DSPI_EOQ_MODE, + .max_clock_factor = 2, }; static const struct fsl_dspi_devtype_data ls1021a_v1_data = { .trans_mode = DSPI_TCFQ_MODE, + .max_clock_factor = 8, }; static const struct fsl_dspi_devtype_data ls2085a_data = { .trans_mode = DSPI_TCFQ_MODE, + .max_clock_factor = 8, }; struct fsl_dspi { @@ -726,6 +730,9 @@ static int dspi_probe(struct platform_device *pdev) } clk_prepare_enable(dspi->clk); + master->max_speed_hz = + clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; + init_waitqueue_head(&dspi->waitq); platform_set_drvdata(pdev, master); -- GitLab From 267c85860308d36bc163c5573308cd024f659d7c Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Wed, 23 Mar 2016 09:26:33 -0500 Subject: [PATCH 0138/9938] regmap: cache: Fix typo in cache_bypass parameter description Setting the flag 'cache_bypass' will bypass the cache not the hardware. Fix this comment here. Fixes: 0eef6b0415f5 ("regmap: Fix doc comment") Signed-off-by: Andrew F. Davis Signed-off-by: Mark Brown --- drivers/base/regmap/regcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 4170b7d95276..df7ff7290821 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -529,7 +529,7 @@ EXPORT_SYMBOL_GPL(regcache_mark_dirty); * regcache_cache_bypass: Put a register map into cache bypass mode * * @map: map to configure - * @cache_bypass: flag if changes should not be written to the hardware + * @cache_bypass: flag if changes should not be written to the cache * * When a register map is marked with the cache bypass option, writes * to the register map API will only update the hardware and not the -- GitLab From 3e11e530415027a57936545957126aff49267b76 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 23 Mar 2016 14:29:59 -0400 Subject: [PATCH 0139/9938] GFS2: ignore unlock failures after withdraw After gfs2 has withdrawn the filesystem, it may still have many locks not in the unlocked state. If it is using lock_dlm, it will failed trying the unlocks since it has already unmounted the lock manager. Instead, it should set the SDF_SKIP_DLM_UNLOCK flag on withdraw, to signal that it can skip the lock_manager on unlocks, and failback to lock_nolock style unlocking. Signed-off-by: Benjamin Marzinski Signed-off-by: Bob Peterson --- fs/gfs2/glock.c | 9 ++++++++- fs/gfs2/util.c | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 6539131c52a2..2897ced5fca0 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -475,7 +475,14 @@ __acquires(&gl->gl_lockref.lock) if (sdp->sd_lockstruct.ls_ops->lm_lock) { /* lock_dlm */ ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags); - if (ret) { + if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED && + target == LM_ST_UNLOCKED && + test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags)) { + finish_xmote(gl, target); + if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) + gfs2_glock_put(gl); + } + else if (ret) { pr_err("lm_lock ret %d\n", ret); GLOCK_BUG_ON(gl, 1); } diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index cf645835710f..aee4485ad8a9 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -68,6 +68,7 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, const char *fmt, ...) fs_err(sdp, "telling LM to unmount\n"); lm->lm_unmount(sdp); } + set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags); fs_err(sdp, "withdrawn\n"); dump_stack(); } -- GitLab From 8f507c8b0fa5d679e2957aad0e5ecd47675fca9a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 16 Mar 2016 16:59:38 -0700 Subject: [PATCH 0140/9938] HID: hidraw: switch to using memdup_user Instead of open-coding memory allocation and copying form user memory sequence let's use memdup_user(). Signed-off-by: Dmitry Torokhov Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hidraw.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 9c2d7c23f296..b9a76e3a7f17 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -123,7 +124,6 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, dev = hidraw_table[minor]->hid; - if (count > HID_MAX_BUFFER_SIZE) { hid_warn(dev, "pid %d passed too large report\n", task_pid_nr(current)); @@ -138,17 +138,12 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, goto out; } - buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; + buf = memdup_user(buffer, count); + if (IS_ERR(buf)) { + ret = PTR_ERR(buf); goto out; } - if (copy_from_user(buf, buffer, count)) { - ret = -EFAULT; - goto out_free; - } - if ((report_type == HID_OUTPUT_REPORT) && !(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) { ret = hid_hw_output_report(dev, buf, count); -- GitLab From e437b90026ac754a0f8b4fe44b844d12ce6162d1 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Thu, 24 Mar 2016 21:52:01 +0200 Subject: [PATCH 0141/9938] regulator: core: Remove duplicate copy of active-discharge parsing Apparently due to a wrongly resolved merge conflict between two branches, which contained the same commit, the commit contents partially was added two times in a row. This change reverts the latter wrong inclusion of commit 909f7ee0b5f3 ("regulator: core: Add support for active-discharge configuration"). The first applied commit 670666b9e0af ("regulator: core: Add support for active-discharge configuration") is not touched. Signed-off-by: Vladimir Zapolskiy Cc: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/core.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0b764284773..1cff11205642 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1150,17 +1150,6 @@ static int set_machine_constraints(struct regulator_dev *rdev, } } - if (rdev->constraints->active_discharge && ops->set_active_discharge) { - bool ad_state = (rdev->constraints->active_discharge == - REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; - - ret = ops->set_active_discharge(rdev, ad_state); - if (ret < 0) { - rdev_err(rdev, "failed to set active discharge\n"); - return ret; - } - } - print_constraints(rdev); return 0; } -- GitLab From 9387bfd19b457085189d918ef117ffd63c4d67a0 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 9 Mar 2016 10:43:31 +0800 Subject: [PATCH 0142/9938] clk: rockchip: add a COMPOSITE_FRACMUX_NOGATE type Because there are some frac clock mux nodes don't have a gate node on the RK3399. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 39c198bbcbee..f3da205073ee 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -428,6 +428,22 @@ struct rockchip_clk_branch { .child = ch, \ } +#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \ + { \ + .id = _id, \ + .branch_type = branch_fraction_divider, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = mo, \ + .div_shift = 16, \ + .div_width = 16, \ + .div_flags = df, \ + .gate_offset = -1, \ + .child = ch, \ + } + #define MUX(_id, cname, pnames, f, o, s, w, mf) \ { \ .id = _id, \ -- GitLab From d9abae3ca5e8fa30fe5074aafd52a5bdfb8b2ed8 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Tue, 2 Feb 2016 11:40:50 +0800 Subject: [PATCH 0143/9938] ARM: dts: rockchip: add vop device node for rk3036 The rk3036 support two overlay plane and one hwc plane, it supports IOMMU, and its IOMMU same as rk3288's. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036.dtsi | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index d0f4bb7e1e50..4932abf2a784 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -119,6 +119,11 @@ interrupt-affinity = <&cpu0>, <&cpu1>; }; + display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <&vop_out>; + }; + timer { compatible = "arm,armv7-timer"; arm,cpu-registers-not-fw-configured; @@ -149,6 +154,32 @@ }; }; + vop: vop@10118000 { + compatible = "rockchip,rk3036-vop"; + reg = <0x10118000 0x19c>; + interrupts = ; + clocks = <&cru ACLK_LCDC>, <&cru SCLK_LCDC>, <&cru HCLK_LCDC>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + resets = <&cru SRST_LCDC1_A>, <&cru SRST_LCDC1_H>, <&cru SRST_LCDC1_D>; + reset-names = "axi", "ahb", "dclk"; + iommus = <&vop_mmu>; + status = "disabled"; + + vop_out: port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + vop_mmu: iommu@10118300 { + compatible = "rockchip,iommu"; + reg = <0x10118300 0x100>; + interrupts = ; + interrupt-names = "vop_mmu"; + #iommu-cells = <0>; + status = "disabled"; + }; + gic: interrupt-controller@10139000 { compatible = "arm,gic-400"; interrupt-controller; -- GitLab From b7217cf19c633dc542ba4980f8fa34933ca1d343 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Tue, 2 Feb 2016 11:40:50 +0800 Subject: [PATCH 0144/9938] ARM: dts: rockchip: add hdmi device node for rk3036 Add the Innosilicon hdmi node for HDMI display. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036.dtsi | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 4932abf2a784..8139fbf3de7f 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -168,6 +168,10 @@ vop_out: port { #address-cells = <1>; #size-cells = <0>; + vop_out_hdmi: endpoint@0 { + reg = <0>; + remote-endpoint = <&hdmi_in_vop>; + }; }; }; @@ -328,6 +332,27 @@ status = "disabled"; }; + hdmi: hdmi@20034000 { + compatible = "rockchip,rk3036-inno-hdmi"; + reg = <0x20034000 0x4000>; + interrupts = ; + clocks = <&cru PCLK_HDMI>; + clock-names = "pclk"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_ctl>; + status = "disabled"; + + hdmi_in: port { + #address-cells = <1>; + #size-cells = <0>; + hdmi_in_vop: endpoint@0 { + reg = <0>; + remote-endpoint = <&vop_out_hdmi>; + }; + }; + }; + timer: timer@20044000 { compatible = "rockchip,rk3036-timer", "rockchip,rk3288-timer"; reg = <0x20044000 0x20>; @@ -675,6 +700,15 @@ }; }; + hdmi { + hdmi_ctl: hdmi-ctl { + rockchip,pins = <1 8 RK_FUNC_1 &pcfg_pull_none>, + <1 9 RK_FUNC_1 &pcfg_pull_none>, + <1 10 RK_FUNC_1 &pcfg_pull_none>, + <1 11 RK_FUNC_1 &pcfg_pull_none>; + }; + }; + uart0 { uart0_xfer: uart0-xfer { rockchip,pins = <0 16 RK_FUNC_1 &pcfg_pull_default>, -- GitLab From cef0abefa146877019e63c4e6ae439d40d01804f Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Tue, 2 Feb 2016 11:40:50 +0800 Subject: [PATCH 0145/9938] ARM: dts: rockchip: enable graphics support on rk3036-kylin Enable the recently added vop and hdmi nodes on the rk3036-kylin board. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036-kylin.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rk3036-kylin.dts index 6251d109eff4..01dd4a805c81 100644 --- a/arch/arm/boot/dts/rk3036-kylin.dts +++ b/arch/arm/boot/dts/rk3036-kylin.dts @@ -130,6 +130,10 @@ status = "okay"; }; +&hdmi { + status = "okay"; +}; + &i2c1 { clock-frequency = <400000>; @@ -385,6 +389,14 @@ status = "okay"; }; +&vop { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + &pinctrl { leds { led_ctl: led-ctl { -- GitLab From 5415ba40650900f7d663a4b79f346c45dddd4ce0 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 23 Feb 2016 13:40:59 +0000 Subject: [PATCH 0146/9938] ARM: dts: rockchip: fix MIPI interrupt on rk3288 This isn't currently used by the driver but the correct value is 19 since DSIHOST0 is 51 in the TRM and the GIC offset requires 32 to be subtracted. Signed-off-by: John Keeping Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 31f7e20ef418..872ccf01d509 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -878,7 +878,7 @@ mipi_dsi: mipi@ff960000 { compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; reg = <0xff960000 0x4000>; - interrupts = ; + interrupts = ; clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>; clock-names = "ref", "pclk"; rockchip,grf = <&grf>; -- GitLab From 57dcfa56138c883905a265979cc84ef69675ae00 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 23 Feb 2016 13:41:00 +0000 Subject: [PATCH 0147/9938] ARM: dts: rockchip: fix audio interrupts on rk3288 These must be translated from the values in the TRM by subtracting 32, which has not been done. The SPDIF interrupt is also off-by-one. Signed-off-by: John Keeping Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 872ccf01d509..e6e181387630 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -765,7 +765,7 @@ clocks = <&cru HCLK_SPDIF8CH>, <&cru SCLK_SPDIF8CH>; dmas = <&dmac_bus_s 3>; dma-names = "tx"; - interrupts = ; + interrupts = ; pinctrl-names = "default"; pinctrl-0 = <&spdif_tx>; rockchip,grf = <&grf>; @@ -775,7 +775,7 @@ i2s: i2s@ff890000 { compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s"; reg = <0xff890000 0x10000>; - interrupts = ; + interrupts = ; #address-cells = <1>; #size-cells = <0>; dmas = <&dmac_bus_s 0>, <&dmac_bus_s 1>; -- GitLab From 1946a201b3963b78a9e2123aedbdd11c4c4849dd Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 23 Feb 2016 12:39:41 +0000 Subject: [PATCH 0148/9938] ARM: dts: rockchip: add mipi_dsi to VIO power domain on rk3288 The MIPI controllers are part of the VIO power domain so add the necessary property to indicate this for the controller we support. Signed-off-by: John Keeping Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index e6e181387630..74eae995c330 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -881,6 +881,7 @@ interrupts = ; clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>; clock-names = "ref", "pclk"; + power-domains = <&power RK3288_PD_VIO>; rockchip,grf = <&grf>; #address-cells = <1>; #size-cells = <0>; -- GitLab From fe95effb4c381355e38f5bffced4917a2b6dc7d3 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 23 Feb 2016 15:01:01 +0800 Subject: [PATCH 0149/9938] dt-bindings: add bindings for Rockchip grf Add devicetree bindings for Rockchip grf which found on Rockchip SoCs. Signed-off-by: Jianqun Xu Acked-by: Rob Herring Signed-off-by: Heiko Stuebner --- .../devicetree/bindings/soc/rockchip/grf.txt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/rockchip/grf.txt diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.txt b/Documentation/devicetree/bindings/soc/rockchip/grf.txt new file mode 100644 index 000000000000..013e71a2cdc7 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/rockchip/grf.txt @@ -0,0 +1,35 @@ +* Rockchip General Register Files (GRF) + +The general register file will be used to do static set by software, which +is composed of many registers for system control. + +From RK3368 SoCs, the GRF is divided into two sections, +- GRF, used for general non-secure system, +- PMUGRF, used for always on system + +Required Properties: + +- compatible: GRF should be one of the followings + - "rockchip,rk3066-grf", "syscon": for rk3066 + - "rockchip,rk3188-grf", "syscon": for rk3188 + - "rockchip,rk3228-grf", "syscon": for rk3228 + - "rockchip,rk3288-grf", "syscon": for rk3288 + - "rockchip,rk3368-grf", "syscon": for rk3368 + - "rockchip,rk3399-grf", "syscon": for rk3399 +- compatible: PMUGRF should be one of the followings + - "rockchip,rk3368-pmugrf", "syscon": for rk3368 + - "rockchip,rk3399-pmugrf", "syscon": for rk3399 +- reg: physical base address of the controller and length of memory mapped + region. + +Example: GRF and PMUGRF of RK3399 SoCs + + pmugrf: syscon@ff320000 { + compatible = "rockchip,rk3399-pmugrf", "syscon"; + reg = <0x0 0xff320000 0x0 0x1000>; + }; + + grf: syscon@ff770000 { + compatible = "rockchip,rk3399-grf", "syscon"; + reg = <0x0 0xff770000 0x0 0x10000>; + }; -- GitLab From 7796031eec9e41099af35bc531f04843358fa3f1 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Mon, 15 Feb 2016 15:33:32 +0800 Subject: [PATCH 0150/9938] ARM: dts: rockchip: add the thermal main info found on rk3228 This patch adds the thermal needed main information for rk3228 SoCS. Basically has the following content: 1) TSADC controller: Add the needed attributes for rk3036 TSADC controller. Especially for the TSHUT, in some cases if we are unable to shut it down in orderly fashion (says: kernel is stuck holding a lock or similar), then hardware TSHUT will reset it. If the temperature is over 95C over a period of time the thermal shutdown of the tsadc is invoked with can either reset the entire chip via the CRU, or notify the PMIC via a GPIO. This should be set in the specific board. 2) Thermal zones: Add the needed device mode for thermal generic framework. Detail in Documentation/devicetree/bindings/thermal/thermal.txt. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3228.dtsi | 69 +++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/arch/arm/boot/dts/rk3228.dtsi b/arch/arm/boot/dts/rk3228.dtsi index 4dae42a01509..f9c34124ccc3 100644 --- a/arch/arm/boot/dts/rk3228.dtsi +++ b/arch/arm/boot/dts/rk3228.dtsi @@ -43,6 +43,7 @@ #include #include #include +#include #include "skeleton.dtsi" / { @@ -69,6 +70,7 @@ /* KHz uV */ 816000 1000000 >; + #cooling-cells = <2>; /* min followed by max */ clock-latency = <40000>; clocks = <&cru ARMCLK>; }; @@ -247,6 +249,63 @@ assigned-clock-rates = <594000000>; }; + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 0>; + + trips { + cpu_alert0: cpu_alert0 { + temperature = <70000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_alert1: cpu_alert1 { + temperature = <75000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_crit: cpu_crit { + temperature = <90000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT 6>; + }; + map1 { + trip = <&cpu_alert1>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; + + tsadc: tsadc@11150000 { + compatible = "rockchip,rk3228-tsadc"; + reg = <0x11150000 0x100>; + interrupts = ; + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; + pinctrl-0 = <&otp_gpio>; + pinctrl-1 = <&otp_out>; + pinctrl-2 = <&otp_gpio>; + #thermal-sensor-cells = <0>; + rockchip,hw-tshut-temp = <95000>; + status = "disabled"; + }; + emmc: dwmmc@30020000 { compatible = "rockchip,rk3288-dw-mshc"; reg = <0x30020000 0x4000>; @@ -394,6 +453,16 @@ }; }; + tsadc { + otp_gpio: otp-gpio { + rockchip,pins = <0 24 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + otp_out: otp-out { + rockchip,pins = <0 24 RK_FUNC_2 &pcfg_pull_none>; + }; + }; + uart0 { uart0_xfer: uart0-xfer { rockchip,pins = <2 26 RK_FUNC_1 &pcfg_pull_none>, -- GitLab From 26f5e19dfb07de627112074721f254482f941dab Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Mon, 15 Feb 2016 15:33:33 +0800 Subject: [PATCH 0151/9938] ARM: dts: rockchip: enable the tsadc for rk3228 evb This patch enables the tsadc for rk3228 evb board. The rk3228 evb board uses the CRU to reset the chip since it hasn't the PMIC to connect it, and TSHUT is low active on evb board. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3228-evb.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/rk3228-evb.dts b/arch/arm/boot/dts/rk3228-evb.dts index e3898b810150..c75cc41d8c1f 100644 --- a/arch/arm/boot/dts/rk3228-evb.dts +++ b/arch/arm/boot/dts/rk3228-evb.dts @@ -61,6 +61,13 @@ status = "okay"; }; +&tsadc { + status = "okay"; + + rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */ +}; + &uart2 { status = "okay"; }; -- GitLab From 57375d88fa3f6bf9351051529464c708f72adb1d Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 26 Jan 2016 10:06:43 +0800 Subject: [PATCH 0152/9938] ARM: dts: rockchip: remove broken-cd from emmc and sdio Only one of "broken-cd" and "non-removable" should be supplied according to Documentation/devicetree/bindings/mmc/mmc.txt. Obviously emmc and sdio-wifi are non-removable devices, while broken-cd is for removable device whose card detect pin is broken. Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036-kylin.dts | 1 - arch/arm/boot/dts/rk3036.dtsi | 1 - arch/arm/boot/dts/rk3066a-rayeager.dts | 2 -- arch/arm/boot/dts/rk3228-evb.dts | 1 - arch/arm/boot/dts/rk3288-evb.dtsi | 1 - arch/arm/boot/dts/rk3288-firefly.dtsi | 2 -- arch/arm/boot/dts/rk3288-popmetal.dts | 1 - arch/arm/boot/dts/rk3288-veyron.dtsi | 2 -- 8 files changed, 11 deletions(-) diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rk3036-kylin.dts index 01dd4a805c81..951f15d675c7 100644 --- a/arch/arm/boot/dts/rk3036-kylin.dts +++ b/arch/arm/boot/dts/rk3036-kylin.dts @@ -345,7 +345,6 @@ &sdio { status = "okay"; - broken-cd; bus-width = <4>; cap-sd-highspeed; cap-sdio-irq; diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 8139fbf3de7f..fa6b5cf31aa7 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -272,7 +272,6 @@ compatible = "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x1021c000 0x4000>; interrupts = ; - broken-cd; bus-width = <8>; cap-mmc-highspeed; clock-frequency = <37500000>; diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts b/arch/arm/boot/dts/rk3066a-rayeager.dts index 05533005a809..3a5989b1724a 100644 --- a/arch/arm/boot/dts/rk3066a-rayeager.dts +++ b/arch/arm/boot/dts/rk3066a-rayeager.dts @@ -182,7 +182,6 @@ }; &emmc { - broken-cd; bus-width = <8>; cap-mmc-highspeed; disable-wp; @@ -348,7 +347,6 @@ }; &mmc1 { - broken-cd; bus-width = <4>; disable-wp; non-removable; diff --git a/arch/arm/boot/dts/rk3228-evb.dts b/arch/arm/boot/dts/rk3228-evb.dts index c75cc41d8c1f..5956e8246abe 100644 --- a/arch/arm/boot/dts/rk3228-evb.dts +++ b/arch/arm/boot/dts/rk3228-evb.dts @@ -53,7 +53,6 @@ }; &emmc { - broken-cd; cap-mmc-highspeed; mmc-ddr-1_8v; disable-wp; diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 78d47f7d2938..3ccd8f35a841 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -172,7 +172,6 @@ }; &emmc { - broken-cd; bus-width = <8>; cap-mmc-highspeed; disable-wp; diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi index 98c586a43c73..5f06d8c1b9f6 100644 --- a/arch/arm/boot/dts/rk3288-firefly.dtsi +++ b/arch/arm/boot/dts/rk3288-firefly.dtsi @@ -208,7 +208,6 @@ }; &emmc { - broken-cd; bus-width = <8>; cap-mmc-highspeed; disable-wp; @@ -509,7 +508,6 @@ }; &sdio0 { - broken-cd; bus-width = <4>; disable-wp; non-removable; diff --git a/arch/arm/boot/dts/rk3288-popmetal.dts b/arch/arm/boot/dts/rk3288-popmetal.dts index 2ff9689d2e1b..eb77276e1cc2 100644 --- a/arch/arm/boot/dts/rk3288-popmetal.dts +++ b/arch/arm/boot/dts/rk3288-popmetal.dts @@ -162,7 +162,6 @@ }; &emmc { - broken-cd; bus-width = <8>; cap-mmc-highspeed; disable-wp; diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi index 412809c60d01..bfb20c878384 100644 --- a/arch/arm/boot/dts/rk3288-veyron.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi @@ -146,7 +146,6 @@ &emmc { status = "okay"; - broken-cd; bus-width = <8>; cap-mmc-highspeed; rockchip,default-sample-phase = <158>; @@ -347,7 +346,6 @@ &sdio0 { status = "okay"; - broken-cd; bus-width = <4>; cap-sd-highspeed; cap-sdio-irq; -- GitLab From 04317584ff1ad6977ba37acf38d2c6b841ce20a4 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Mon, 15 Feb 2016 11:30:58 +0800 Subject: [PATCH 0153/9938] arm64: dts: rockchip: fix the incorrect otp-out pin on rk3368 This patch fixes the incorrect Over-temperature protection pin. since the rk3368 io list said the otp pin is gpio0a3. Anyway, that should be fixed in here. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3368.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index 49d119103e31..394916341680 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -926,11 +926,11 @@ tsadc { otp_gpio: otp-gpio { - rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_none>; + rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>; }; otp_out: otp-out { - rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>; + rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_none>; }; }; -- GitLab From 1ade61c141e259ae045930420702f0d628fc88fc Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 26 Jan 2016 10:06:59 +0800 Subject: [PATCH 0154/9938] arm64: dts: rockchip: remove broken-cd from emmc and sdio Only one of "broken-cd" and "non-removable" should be supplied according to Documentation/devicetree/bindings/mmc/mmc.txt. Obviously emmc and sdio-wifi are non-removable devices, while broken-cd is for removable device whose card detect pin is broken. Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi | 1 - arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi index 6e27b22704df..06bbe421db37 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi @@ -152,7 +152,6 @@ }; &emmc { - broken-cd; bus-width = <8>; cap-mmc-highspeed; disable-wp; diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts index 1f2b642e794a..a1d1aa9c16fe 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts @@ -185,7 +185,6 @@ }; &emmc { - broken-cd; bus-width = <8>; cap-mmc-highspeed; disable-wp; -- GitLab From fa93fd4ecc9c58475abac6db93a797bff893bc16 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Mar 2016 18:12:52 +0000 Subject: [PATCH 0155/9938] regulator: core: Ensure we are at least in bounds for our constraints Currently we only attempt to set the voltage during constraints application if an exact voltage is specified. Extend this so that if the currently set voltage for the regulator is outside the bounds set in constraints we will move the voltage to the nearest constraint, raising to the minimum or lowering to the maximum as needed. This ensures that drivers can probe without the hardware being driven out of spec. Reported-by: Ivaylo Dimitrov Tested-by: Ivaylo Dimitrov Signed-off-by: Mark Brown --- drivers/regulator/core.c | 32 +++++++++++++++++++++++++------- drivers/regulator/of_regulator.c | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0b764284773..881c37e61f75 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -906,7 +906,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, /* do we need to apply the constraint voltage */ if (rdev->constraints->apply_uV && - rdev->constraints->min_uV == rdev->constraints->max_uV) { + rdev->constraints->min_uV && rdev->constraints->max_uV) { + int target_min, target_max; int current_uV = _regulator_get_voltage(rdev); if (current_uV < 0) { rdev_err(rdev, @@ -914,15 +915,32 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, current_uV); return current_uV; } - if (current_uV < rdev->constraints->min_uV || - current_uV > rdev->constraints->max_uV) { + + /* + * If we're below the minimum voltage move up to the + * minimum voltage, if we're above the maximum voltage + * then move down to the maximum. + */ + target_min = current_uV; + target_max = current_uV; + + if (current_uV < rdev->constraints->min_uV) { + target_min = rdev->constraints->min_uV; + target_max = rdev->constraints->min_uV; + } + + if (current_uV > rdev->constraints->max_uV) { + target_min = rdev->constraints->max_uV; + target_max = rdev->constraints->max_uV; + } + + if (target_min != current_uV || target_max != current_uV) { ret = _regulator_do_set_voltage( - rdev, rdev->constraints->min_uV, - rdev->constraints->max_uV); + rdev, target_min, target_max); if (ret < 0) { rdev_err(rdev, - "failed to apply %duV constraint(%d)\n", - rdev->constraints->min_uV, ret); + "failed to apply %d-%duV constraint(%d)\n", + target_min, target_max, ret); return ret; } } diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index d2ddefaaddaf..f45106a44635 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -43,7 +43,7 @@ static void of_get_regulation_constraints(struct device_node *np, constraints->max_uV = pval; /* Voltage change possible? */ - if (constraints->min_uV != constraints->max_uV) { + if (constraints->min_uV && constraints->max_uV) { constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; constraints->apply_uV = true; } -- GitLab From 268aebaa2410152bf91ea1ede6b284ff8138822d Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 9 Mar 2016 10:37:03 +0800 Subject: [PATCH 0156/9938] clk: rockchip: allow varying mux parameters for cpuclk pll-sources Thers are only two parent PLLs that APLL and GPLL for core on the previous SoCs (RK3066/RK3188/RK3288/RK3368). Hence, we set fixed GPLL as alternate parent when core is switching freq. Since RK3399 big.LITTLE architecture, we need to select and adapt more PLLs (ALPLL/ABPLL/DPLL/GPLL) sources. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-cpu.c | 29 ++++++++++++++++++----------- drivers/clk/rockchip/clk-rk3036.c | 3 +++ drivers/clk/rockchip/clk-rk3188.c | 6 ++++++ drivers/clk/rockchip/clk-rk3228.c | 3 +++ drivers/clk/rockchip/clk-rk3288.c | 3 +++ drivers/clk/rockchip/clk-rk3368.c | 6 ++++++ drivers/clk/rockchip/clk.h | 6 ++++++ 7 files changed, 45 insertions(+), 11 deletions(-) diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 4e73ed5cab58..4bb130cd0062 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -158,12 +158,16 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask, reg_data->div_core_shift) | - HIWORD_UPDATE(1, 1, reg_data->mux_core_shift), + HIWORD_UPDATE(reg_data->mux_core_alt, + reg_data->mux_core_mask, + reg_data->mux_core_shift), cpuclk->reg_base + reg_data->core_reg); } else { /* select alternate parent */ - writel(HIWORD_UPDATE(1, 1, reg_data->mux_core_shift), - cpuclk->reg_base + reg_data->core_reg); + writel(HIWORD_UPDATE(reg_data->mux_core_alt, + reg_data->mux_core_mask, + reg_data->mux_core_shift), + cpuclk->reg_base + reg_data->core_reg); } spin_unlock_irqrestore(cpuclk->lock, flags); @@ -198,7 +202,9 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, writel(HIWORD_UPDATE(0, reg_data->div_core_mask, reg_data->div_core_shift) | - HIWORD_UPDATE(0, 1, reg_data->mux_core_shift), + HIWORD_UPDATE(reg_data->mux_core_main, + reg_data->mux_core_mask, + reg_data->mux_core_shift), cpuclk->reg_base + reg_data->core_reg); if (ndata->old_rate > ndata->new_rate) @@ -252,7 +258,7 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, return ERR_PTR(-ENOMEM); init.name = name; - init.parent_names = &parent_names[0]; + init.parent_names = &parent_names[reg_data->mux_core_main]; init.num_parents = 1; init.ops = &rockchip_cpuclk_ops; @@ -270,10 +276,10 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb; cpuclk->hw.init = &init; - cpuclk->alt_parent = __clk_lookup(parent_names[1]); + cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]); if (!cpuclk->alt_parent) { - pr_err("%s: could not lookup alternate parent\n", - __func__); + pr_err("%s: could not lookup alternate parent: (%d)\n", + __func__, reg_data->mux_core_alt); ret = -EINVAL; goto free_cpuclk; } @@ -285,10 +291,11 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, goto free_cpuclk; } - clk = __clk_lookup(parent_names[0]); + clk = __clk_lookup(parent_names[reg_data->mux_core_main]); if (!clk) { - pr_err("%s: could not lookup parent clock %s\n", - __func__, parent_names[0]); + pr_err("%s: could not lookup parent clock: (%d) %s\n", + __func__, reg_data->mux_core_main, + parent_names[reg_data->mux_core_main]); ret = -EINVAL; goto free_alt_parent; } diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 7cdb2d61f3e0..f9cbba0eac36 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -113,7 +113,10 @@ static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = { .core_reg = RK2928_CLKSEL_CON(0), .div_core_shift = 0, .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 7, + .mux_core_mask = 0x1, }; PNAME(mux_pll_p) = { "xin24m", "xin24m" }; diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 40bab3901491..e832403a0f9f 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -155,7 +155,10 @@ static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = { .core_reg = RK2928_CLKSEL_CON(0), .div_core_shift = 0, .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 8, + .mux_core_mask = 0x1, }; #define RK3188_DIV_ACLK_CORE_MASK 0x7 @@ -191,7 +194,10 @@ static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = { .core_reg = RK2928_CLKSEL_CON(0), .div_core_shift = 9, .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 8, + .mux_core_mask = 0x1, }; PNAME(mux_pll_p) = { "xin24m", "xin32k" }; diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 7702d2855e9c..4b4137e85125 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -111,7 +111,10 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { .core_reg = RK2928_CLKSEL_CON(0), .div_core_shift = 0, .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 6, + .mux_core_mask = 0x1, }; PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 3cb72163a512..00faf3f9b179 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -165,7 +165,10 @@ static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = { .core_reg = RK3288_CLKSEL_CON(0), .div_core_shift = 8, .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 15, + .mux_core_mask = 0x1, }; PNAME(mux_pll_p) = { "xin24m", "xin32k" }; diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index a2bb12200465..c26ff4a36dcd 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -165,14 +165,20 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = { .core_reg = RK3368_CLKSEL_CON(0), .div_core_shift = 0, .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 7, + .mux_core_mask = 0x1, }; static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { .core_reg = RK3368_CLKSEL_CON(2), .div_core_shift = 0, + .mux_core_alt = 1, + .mux_core_main = 0, .div_core_mask = 0x1f, .mux_core_shift = 7, + .mux_core_mask = 0x1, }; #define RK3368_DIV_ACLKM_MASK 0x1f diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index f3da205073ee..4133bfc8f827 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -217,14 +217,20 @@ struct rockchip_cpuclk_rate_table { * @core_reg: register offset of the core settings register * @div_core_shift: core divider offset used to divide the pll value * @div_core_mask: core divider mask + * @mux_core_alt: mux value to select alternate parent + * @mux_core_main: mux value to select main parent of core * @mux_core_shift: offset of the core multiplexer + * @mux_core_mask: core multiplexer mask */ struct rockchip_cpuclk_reg_data { int core_reg; u8 div_core_shift; u32 div_core_mask; int mux_core_reg; + u8 mux_core_alt; + u8 mux_core_main; u8 mux_core_shift; + u32 mux_core_mask; }; struct clk *rockchip_clk_register_cpuclk(const char *name, -- GitLab From ef1d9feeccc094f59b72bb11fe14ec886eb574d3 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 9 Mar 2016 10:37:04 +0800 Subject: [PATCH 0157/9938] clk: rockchip: Add support for multiple clock providers There are need to support Multi-CRUs probability in future, but it is not supported on the current Rockchip Clock Framework. Therefore, this patch add support a provider as the parameter handler when we call the clock register functions for per CRU. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-pll.c | 30 +++--- drivers/clk/rockchip/clk-rk3036.c | 17 +++- drivers/clk/rockchip/clk-rk3188.c | 44 ++++++--- drivers/clk/rockchip/clk-rk3228.c | 17 +++- drivers/clk/rockchip/clk-rk3288.c | 19 ++-- drivers/clk/rockchip/clk-rk3368.c | 21 +++-- drivers/clk/rockchip/clk.c | 148 +++++++++++++++++++----------- drivers/clk/rockchip/clk.h | 51 +++++++--- 8 files changed, 229 insertions(+), 118 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 5de797e34d54..27be66a2a358 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -46,6 +46,8 @@ struct rockchip_clk_pll { const struct rockchip_pll_rate_table *rate_table; unsigned int rate_count; spinlock_t *lock; + + struct rockchip_clk_provider *ctx; }; #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) @@ -90,7 +92,7 @@ static long rockchip_pll_round_rate(struct clk_hw *hw, */ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) { - struct regmap *grf = rockchip_clk_get_grf(); + struct regmap *grf = rockchip_clk_get_grf(pll->ctx); unsigned int val; int delay = 24000000, ret; @@ -251,7 +253,7 @@ static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate, struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); const struct rockchip_pll_rate_table *rate; unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate); - struct regmap *grf = rockchip_clk_get_grf(); + struct regmap *grf = rockchip_clk_get_grf(pll->ctx); if (IS_ERR(grf)) { pr_debug("%s: grf regmap not available, aborting rate change\n", @@ -490,7 +492,7 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); const struct rockchip_pll_rate_table *rate; unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); - struct regmap *grf = rockchip_clk_get_grf(); + struct regmap *grf = rockchip_clk_get_grf(pll->ctx); if (IS_ERR(grf)) { pr_debug("%s: grf regmap not available, aborting rate change\n", @@ -563,7 +565,7 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw) rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb); if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf || rate->nb != cur.nb) { - struct regmap *grf = rockchip_clk_get_grf(); + struct regmap *grf = rockchip_clk_get_grf(pll->ctx); if (IS_ERR(grf)) return; @@ -595,12 +597,13 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { * Common registering of pll clocks */ -struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, +struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, + enum rockchip_pll_type pll_type, const char *name, const char *const *parent_names, - u8 num_parents, void __iomem *base, int con_offset, - int grf_lock_offset, int lock_shift, int mode_offset, - int mode_shift, struct rockchip_pll_rate_table *rate_table, - u8 clk_pll_flags, spinlock_t *lock) + u8 num_parents, int con_offset, int grf_lock_offset, + int lock_shift, int mode_offset, int mode_shift, + struct rockchip_pll_rate_table *rate_table, + u8 clk_pll_flags) { const char *pll_parents[3]; struct clk_init_data init; @@ -624,11 +627,11 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, /* create the mux on top of the real pll */ pll->pll_mux_ops = &clk_mux_ops; pll_mux = &pll->pll_mux; - pll_mux->reg = base + mode_offset; + pll_mux->reg = ctx->reg_base + mode_offset; pll_mux->shift = mode_shift; pll_mux->mask = PLL_MODE_MASK; pll_mux->flags = 0; - pll_mux->lock = lock; + pll_mux->lock = &ctx->lock; pll_mux->hw.init = &init; if (pll_type == pll_rk3036 || pll_type == pll_rk3066) @@ -695,11 +698,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, pll->hw.init = &init; pll->type = pll_type; - pll->reg_base = base + con_offset; + pll->reg_base = ctx->reg_base + con_offset; pll->lock_offset = grf_lock_offset; pll->lock_shift = lock_shift; pll->flags = clk_pll_flags; - pll->lock = lock; + pll->lock = &ctx->lock; + pll->ctx = ctx; pll_clk = clk_register(NULL, &pll->hw); if (IS_ERR(pll_clk)) { diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index f9cbba0eac36..c7c8260e1c66 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -440,6 +440,7 @@ static const char *const rk3036_critical_clocks[] __initconst = { static void __init rk3036_clk_init(struct device_node *np) { + struct rockchip_clk_provider *ctx; void __iomem *reg_base; struct clk *clk; @@ -449,22 +450,26 @@ static void __init rk3036_clk_init(struct device_node *np) return; } - rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return; + } clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); if (IS_ERR(clk)) pr_warn("%s: could not register clock usb480m: %ld\n", __func__, PTR_ERR(clk)); - rockchip_clk_register_plls(rk3036_pll_clks, + rockchip_clk_register_plls(ctx, rk3036_pll_clks, ARRAY_SIZE(rk3036_pll_clks), RK3036_GRF_SOC_STATUS0); - rockchip_clk_register_branches(rk3036_clk_branches, + rockchip_clk_register_branches(ctx, rk3036_clk_branches, ARRAY_SIZE(rk3036_clk_branches)); rockchip_clk_protect_critical(rk3036_critical_clocks, ARRAY_SIZE(rk3036_critical_clocks)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3036_cpuclk_data, rk3036_cpuclk_rates, ARRAY_SIZE(rk3036_cpuclk_rates)); @@ -472,6 +477,8 @@ static void __init rk3036_clk_init(struct device_node *np) rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); + rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index e832403a0f9f..0fcce2295b37 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -759,57 +759,74 @@ static const char *const rk3188_critical_clocks[] __initconst = { "hclk_cpubus" }; -static void __init rk3188_common_clk_init(struct device_node *np) +static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np) { + struct rockchip_clk_provider *ctx; void __iomem *reg_base; reg_base = of_iomap(np, 0); if (!reg_base) { pr_err("%s: could not map cru region\n", __func__); - return; + return ERR_PTR(-ENOMEM); } - rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return ERR_PTR(-ENOMEM); + } - rockchip_clk_register_branches(common_clk_branches, + rockchip_clk_register_branches(ctx, common_clk_branches, ARRAY_SIZE(common_clk_branches)); rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); + rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); + + return ctx; } static void __init rk3066a_clk_init(struct device_node *np) { - rk3188_common_clk_init(np); - rockchip_clk_register_plls(rk3066_pll_clks, + struct rockchip_clk_provider *ctx; + + ctx = rk3188_common_clk_init(np); + if (IS_ERR(ctx)) + return; + + rockchip_clk_register_plls(ctx, rk3066_pll_clks, ARRAY_SIZE(rk3066_pll_clks), RK3066_GRF_SOC_STATUS); - rockchip_clk_register_branches(rk3066a_clk_branches, + rockchip_clk_register_branches(ctx, rk3066a_clk_branches, ARRAY_SIZE(rk3066a_clk_branches)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3066_cpuclk_data, rk3066_cpuclk_rates, ARRAY_SIZE(rk3066_cpuclk_rates)); rockchip_clk_protect_critical(rk3188_critical_clocks, ARRAY_SIZE(rk3188_critical_clocks)); + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); static void __init rk3188a_clk_init(struct device_node *np) { + struct rockchip_clk_provider *ctx; struct clk *clk1, *clk2; unsigned long rate; int ret; - rk3188_common_clk_init(np); - rockchip_clk_register_plls(rk3188_pll_clks, + ctx = rk3188_common_clk_init(np); + if (IS_ERR(ctx)) + return; + + rockchip_clk_register_plls(ctx, rk3188_pll_clks, ARRAY_SIZE(rk3188_pll_clks), RK3188_GRF_SOC_STATUS); - rockchip_clk_register_branches(rk3188_clk_branches, + rockchip_clk_register_branches(ctx, rk3188_clk_branches, ARRAY_SIZE(rk3188_clk_branches)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3188_cpuclk_data, rk3188_cpuclk_rates, ARRAY_SIZE(rk3188_cpuclk_rates)); @@ -833,6 +850,7 @@ static void __init rk3188a_clk_init(struct device_node *np) rockchip_clk_protect_critical(rk3188_critical_clocks, ARRAY_SIZE(rk3188_critical_clocks)); + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 4b4137e85125..c112b2f95224 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -628,6 +628,7 @@ static const char *const rk3228_critical_clocks[] __initconst = { static void __init rk3228_clk_init(struct device_node *np) { + struct rockchip_clk_provider *ctx; void __iomem *reg_base; reg_base = of_iomap(np, 0); @@ -636,17 +637,21 @@ static void __init rk3228_clk_init(struct device_node *np) return; } - rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return; + } - rockchip_clk_register_plls(rk3228_pll_clks, + rockchip_clk_register_plls(ctx, rk3228_pll_clks, ARRAY_SIZE(rk3228_pll_clks), RK3228_GRF_SOC_STATUS0); - rockchip_clk_register_branches(rk3228_clk_branches, + rockchip_clk_register_branches(ctx, rk3228_clk_branches, ARRAY_SIZE(rk3228_clk_branches)); rockchip_clk_protect_critical(rk3228_critical_clocks, ARRAY_SIZE(rk3228_critical_clocks)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3228_cpuclk_data, rk3228_cpuclk_rates, ARRAY_SIZE(rk3228_cpuclk_rates)); @@ -654,6 +659,8 @@ static void __init rk3228_clk_init(struct device_node *np) rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK3228_GLB_SRST_FST, NULL); + rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 00faf3f9b179..d1031d1149ce 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -881,6 +881,7 @@ static struct syscore_ops rk3288_clk_syscore_ops = { static void __init rk3288_clk_init(struct device_node *np) { + struct rockchip_clk_provider *ctx; struct clk *clk; rk3288_cru_base = of_iomap(np, 0); @@ -889,7 +890,11 @@ static void __init rk3288_clk_init(struct device_node *np) return; } - rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); + ctx = rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return; + } /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); @@ -897,17 +902,17 @@ static void __init rk3288_clk_init(struct device_node *np) pr_warn("%s: could not register clock pclk_wdt: %ld\n", __func__, PTR_ERR(clk)); else - rockchip_clk_add_lookup(clk, PCLK_WDT); + rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); - rockchip_clk_register_plls(rk3288_pll_clks, + rockchip_clk_register_plls(ctx, rk3288_pll_clks, ARRAY_SIZE(rk3288_pll_clks), RK3288_GRF_SOC_STATUS1); - rockchip_clk_register_branches(rk3288_clk_branches, + rockchip_clk_register_branches(ctx, rk3288_clk_branches, ARRAY_SIZE(rk3288_clk_branches)); rockchip_clk_protect_critical(rk3288_critical_clocks, ARRAY_SIZE(rk3288_critical_clocks)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3288_cpuclk_data, rk3288_cpuclk_rates, ARRAY_SIZE(rk3288_cpuclk_rates)); @@ -916,8 +921,10 @@ static void __init rk3288_clk_init(struct device_node *np) rk3288_cru_base + RK3288_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK3288_GLB_SRST_FST, + rockchip_register_restart_notifier(ctx, RK3288_GLB_SRST_FST, rk3288_clk_shutdown); register_syscore_ops(&rk3288_clk_syscore_ops); + + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index c26ff4a36dcd..3121414cfd63 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -862,6 +862,7 @@ static const char *const rk3368_critical_clocks[] __initconst = { static void __init rk3368_clk_init(struct device_node *np) { + struct rockchip_clk_provider *ctx; void __iomem *reg_base; struct clk *clk; @@ -871,7 +872,11 @@ static void __init rk3368_clk_init(struct device_node *np) return; } - rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return; + } /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */ clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); @@ -879,22 +884,22 @@ static void __init rk3368_clk_init(struct device_node *np) pr_warn("%s: could not register clock pclk_wdt: %ld\n", __func__, PTR_ERR(clk)); else - rockchip_clk_add_lookup(clk, PCLK_WDT); + rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); - rockchip_clk_register_plls(rk3368_pll_clks, + rockchip_clk_register_plls(ctx, rk3368_pll_clks, ARRAY_SIZE(rk3368_pll_clks), RK3368_GRF_SOC_STATUS0); - rockchip_clk_register_branches(rk3368_clk_branches, + rockchip_clk_register_branches(ctx, rk3368_clk_branches, ARRAY_SIZE(rk3368_clk_branches)); rockchip_clk_protect_critical(rk3368_critical_clocks, ARRAY_SIZE(rk3368_critical_clocks)); - rockchip_clk_register_armclk(ARMCLKB, "armclkb", + rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb", mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p), &rk3368_cpuclkb_data, rk3368_cpuclkb_rates, ARRAY_SIZE(rk3368_cpuclkb_rates)); - rockchip_clk_register_armclk(ARMCLKL, "armclkl", + rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl", mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), &rk3368_cpuclkl_data, rk3368_cpuclkl_rates, ARRAY_SIZE(rk3368_cpuclkl_rates)); @@ -902,6 +907,8 @@ static void __init rk3368_clk_init(struct device_node *np) rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK3368_GLB_SRST_FST, NULL); + rockchip_register_restart_notifier(ctx, RK3368_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init); diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index ec06350c78c4..5618a8761dee 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -2,6 +2,9 @@ * Copyright (c) 2014 MundoReader S.L. * Author: Heiko Stuebner * + * Copyright (c) 2016 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng + * * based on * * samsung/clk.c @@ -157,7 +160,8 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, return notifier_from_errno(ret); } -static struct clk *rockchip_clk_register_frac_branch(const char *name, +static struct clk *rockchip_clk_register_frac_branch( + struct rockchip_clk_provider *ctx, const char *name, const char *const *parent_names, u8 num_parents, void __iomem *base, int muxdiv_offset, u8 div_flags, int gate_offset, u8 gate_shift, u8 gate_flags, @@ -250,7 +254,7 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name, if (IS_ERR(mux_clk)) return clk; - rockchip_clk_add_lookup(mux_clk, child->id); + rockchip_clk_add_lookup(ctx, mux_clk, child->id); /* notifier on the fraction divider to catch rate changes */ if (frac->mux_frac_idx >= 0) { @@ -314,66 +318,94 @@ static struct clk *rockchip_clk_register_factor_branch(const char *name, return clk; } -static DEFINE_SPINLOCK(clk_lock); -static struct clk **clk_table; -static void __iomem *reg_base; -static struct clk_onecell_data clk_data; -static struct device_node *cru_node; -static struct regmap *grf; - -void __init rockchip_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks) +struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, + void __iomem *base, unsigned long nr_clks) { - reg_base = base; - cru_node = np; - grf = ERR_PTR(-EPROBE_DEFER); + struct rockchip_clk_provider *ctx; + struct clk **clk_table; + int i; + + ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL); + if (!ctx) { + pr_err("%s: Could not allocate clock provider context\n", + __func__); + return ERR_PTR(-ENOMEM); + } clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); - if (!clk_table) - pr_err("%s: could not allocate clock lookup table\n", __func__); + if (!clk_table) { + pr_err("%s: Could not allocate clock lookup table\n", + __func__); + goto err_free; + } + + for (i = 0; i < nr_clks; ++i) + clk_table[i] = ERR_PTR(-ENOENT); - clk_data.clks = clk_table; - clk_data.clk_num = nr_clks; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + ctx->reg_base = base; + ctx->clk_data.clks = clk_table; + ctx->clk_data.clk_num = nr_clks; + ctx->cru_node = np; + ctx->grf = ERR_PTR(-EPROBE_DEFER); + spin_lock_init(&ctx->lock); + + return ctx; + +err_free: + kfree(ctx); + return ERR_PTR(-ENOMEM); +} + +void __init rockchip_clk_of_add_provider(struct device_node *np, + struct rockchip_clk_provider *ctx) +{ + if (np) { + if (of_clk_add_provider(np, of_clk_src_onecell_get, + &ctx->clk_data)) + pr_err("%s: could not register clk provider\n", __func__); + } } -struct regmap *rockchip_clk_get_grf(void) +struct regmap *rockchip_clk_get_grf(struct rockchip_clk_provider *ctx) { - if (IS_ERR(grf)) - grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf"); - return grf; + if (IS_ERR(ctx->grf)) + ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, "rockchip,grf"); + return ctx->grf; } -void rockchip_clk_add_lookup(struct clk *clk, unsigned int id) +void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, + struct clk *clk, unsigned int id) { - if (clk_table && id) - clk_table[id] = clk; + if (ctx->clk_data.clks && id) + ctx->clk_data.clks[id] = clk; } -void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list, +void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, + struct rockchip_pll_clock *list, unsigned int nr_pll, int grf_lock_offset) { struct clk *clk; int idx; for (idx = 0; idx < nr_pll; idx++, list++) { - clk = rockchip_clk_register_pll(list->type, list->name, + clk = rockchip_clk_register_pll(ctx, list->type, list->name, list->parent_names, list->num_parents, - reg_base, list->con_offset, grf_lock_offset, + list->con_offset, grf_lock_offset, list->lock_shift, list->mode_offset, list->mode_shift, list->rate_table, - list->pll_flags, &clk_lock); + list->pll_flags); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } - rockchip_clk_add_lookup(clk, list->id); + rockchip_clk_add_lookup(ctx, clk, list->id); } } void __init rockchip_clk_register_branches( + struct rockchip_clk_provider *ctx, struct rockchip_clk_branch *list, unsigned int nr_clk) { @@ -389,56 +421,56 @@ void __init rockchip_clk_register_branches( case branch_mux: clk = clk_register_mux(NULL, list->name, list->parent_names, list->num_parents, - flags, reg_base + list->muxdiv_offset, + flags, ctx->reg_base + list->muxdiv_offset, list->mux_shift, list->mux_width, - list->mux_flags, &clk_lock); + list->mux_flags, &ctx->lock); break; case branch_divider: if (list->div_table) clk = clk_register_divider_table(NULL, list->name, list->parent_names[0], - flags, reg_base + list->muxdiv_offset, + flags, ctx->reg_base + list->muxdiv_offset, list->div_shift, list->div_width, list->div_flags, list->div_table, - &clk_lock); + &ctx->lock); else clk = clk_register_divider(NULL, list->name, list->parent_names[0], flags, - reg_base + list->muxdiv_offset, + ctx->reg_base + list->muxdiv_offset, list->div_shift, list->div_width, - list->div_flags, &clk_lock); + list->div_flags, &ctx->lock); break; case branch_fraction_divider: - clk = rockchip_clk_register_frac_branch(list->name, + clk = rockchip_clk_register_frac_branch(ctx, list->name, list->parent_names, list->num_parents, - reg_base, list->muxdiv_offset, list->div_flags, + ctx->reg_base, list->muxdiv_offset, list->div_flags, list->gate_offset, list->gate_shift, list->gate_flags, flags, list->child, - &clk_lock); + &ctx->lock); break; case branch_gate: flags |= CLK_SET_RATE_PARENT; clk = clk_register_gate(NULL, list->name, list->parent_names[0], flags, - reg_base + list->gate_offset, - list->gate_shift, list->gate_flags, &clk_lock); + ctx->reg_base + list->gate_offset, + list->gate_shift, list->gate_flags, &ctx->lock); break; case branch_composite: clk = rockchip_clk_register_branch(list->name, list->parent_names, list->num_parents, - reg_base, list->muxdiv_offset, list->mux_shift, + ctx->reg_base, list->muxdiv_offset, list->mux_shift, list->mux_width, list->mux_flags, list->div_shift, list->div_width, list->div_flags, list->div_table, list->gate_offset, list->gate_shift, - list->gate_flags, flags, &clk_lock); + list->gate_flags, flags, &ctx->lock); break; case branch_mmc: clk = rockchip_clk_register_mmc( list->name, list->parent_names, list->num_parents, - reg_base + list->muxdiv_offset, + ctx->reg_base + list->muxdiv_offset, list->div_shift ); break; @@ -446,16 +478,16 @@ void __init rockchip_clk_register_branches( clk = rockchip_clk_register_inverter( list->name, list->parent_names, list->num_parents, - reg_base + list->muxdiv_offset, - list->div_shift, list->div_flags, &clk_lock); + ctx->reg_base + list->muxdiv_offset, + list->div_shift, list->div_flags, &ctx->lock); break; case branch_factor: clk = rockchip_clk_register_factor_branch( list->name, list->parent_names, - list->num_parents, reg_base, + list->num_parents, ctx->reg_base, list->div_shift, list->div_width, list->gate_offset, list->gate_shift, - list->gate_flags, flags, &clk_lock); + list->gate_flags, flags, &ctx->lock); break; } @@ -472,11 +504,12 @@ void __init rockchip_clk_register_branches( continue; } - rockchip_clk_add_lookup(clk, list->id); + rockchip_clk_add_lookup(ctx, clk, list->id); } } -void __init rockchip_clk_register_armclk(unsigned int lookup_id, +void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, + unsigned int lookup_id, const char *name, const char *const *parent_names, u8 num_parents, const struct rockchip_cpuclk_reg_data *reg_data, @@ -486,15 +519,15 @@ void __init rockchip_clk_register_armclk(unsigned int lookup_id, struct clk *clk; clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, - reg_data, rates, nrates, reg_base, - &clk_lock); + reg_data, rates, nrates, ctx->reg_base, + &ctx->lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s: %ld\n", __func__, name, PTR_ERR(clk)); return; } - rockchip_clk_add_lookup(clk, lookup_id); + rockchip_clk_add_lookup(ctx, clk, lookup_id); } void __init rockchip_clk_protect_critical(const char *const clocks[], @@ -511,6 +544,7 @@ void __init rockchip_clk_protect_critical(const char *const clocks[], } } +static void __iomem *rst_base; static unsigned int reg_restart; static void (*cb_restart)(void); static int rockchip_restart_notify(struct notifier_block *this, @@ -519,7 +553,7 @@ static int rockchip_restart_notify(struct notifier_block *this, if (cb_restart) cb_restart(); - writel(0xfdb9, reg_base + reg_restart); + writel(0xfdb9, rst_base + reg_restart); return NOTIFY_DONE; } @@ -528,10 +562,12 @@ static struct notifier_block rockchip_restart_handler = { .priority = 128, }; -void __init rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)) +void __init rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, + unsigned int reg, void (*cb)(void)) { int ret; + rst_base = ctx->reg_base; reg_restart = reg; cb_restart = cb; ret = register_restart_handler(&rockchip_restart_handler); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 4133bfc8f827..e243d509da89 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -27,6 +27,7 @@ #define CLK_ROCKCHIP_CLK_H #include +#include struct clk; @@ -127,6 +128,22 @@ enum rockchip_pll_type { .nb = _nb, \ } +/** + * struct rockchip_clk_provider: information about clock provider + * @reg_base: virtual address for the register base. + * @clk_data: holds clock related data like clk* and number of clocks. + * @cru_node: device-node of the clock-provider + * @grf: regmap of the general-register-files syscon + * @lock: maintains exclusion between callbacks for a given clock-provider. + */ +struct rockchip_clk_provider { + void __iomem *reg_base; + struct clk_onecell_data clk_data; + struct device_node *cru_node; + struct regmap *grf; + spinlock_t lock; +}; + struct rockchip_pll_rate_table { unsigned long rate; unsigned int nr; @@ -194,12 +211,13 @@ struct rockchip_pll_clock { .rate_table = _rtable, \ } -struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, +struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, + enum rockchip_pll_type pll_type, const char *name, const char *const *parent_names, - u8 num_parents, void __iomem *base, int con_offset, - int grf_lock_offset, int lock_shift, int reg_mode, - int mode_shift, struct rockchip_pll_rate_table *rate_table, - u8 clk_pll_flags, spinlock_t *lock); + u8 num_parents, int con_offset, int grf_lock_offset, + int lock_shift, int mode_offset, int mode_shift, + struct rockchip_pll_rate_table *rate_table, + u8 clk_pll_flags); struct rockchip_cpuclk_clksel { int reg; @@ -558,21 +576,28 @@ struct rockchip_clk_branch { .gate_flags = gf, \ } -void rockchip_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks); -struct regmap *rockchip_clk_get_grf(void); -void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); -void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, +struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, + void __iomem *base, unsigned long nr_clks); +void rockchip_clk_of_add_provider(struct device_node *np, + struct rockchip_clk_provider *ctx); +struct regmap *rockchip_clk_get_grf(struct rockchip_clk_provider *ctx); +void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, + struct clk *clk, unsigned int id); +void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, + struct rockchip_clk_branch *list, unsigned int nr_clk); -void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, +void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, + struct rockchip_pll_clock *pll_list, unsigned int nr_pll, int grf_lock_offset); -void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, +void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, + unsigned int lookup_id, const char *name, const char *const *parent_names, u8 num_parents, const struct rockchip_cpuclk_reg_data *reg_data, const struct rockchip_cpuclk_rate_table *rates, int nrates); void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); -void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)); +void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, + unsigned int reg, void (*cb)(void)); #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) -- GitLab From b40baccd236a9a91fbb077efb8dadb41fdfb55ab Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 10 Mar 2016 11:47:01 +0800 Subject: [PATCH 0158/9938] clk: rockchip: add new pll-type for rk3399 and similar socs The rk3399's pll and clock are similar with rk3036's, it different with base on the rk3066(rk3188, rk3288, rk3368 use it), there are different adjust foctors and control registers, so these should be independent and separate from the series of rk3066s. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-pll.c | 271 ++++++++++++++++++++++++++++++++- drivers/clk/rockchip/clk.h | 3 +- 2 files changed, 272 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 27be66a2a358..128a6b2fca7f 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -593,6 +593,267 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { .init = rockchip_rk3066_pll_init, }; +/** + * PLL used in RK3399 + */ + +#define RK3399_PLLCON(i) (i * 0x4) +#define RK3399_PLLCON0_FBDIV_MASK 0xfff +#define RK3399_PLLCON0_FBDIV_SHIFT 0 +#define RK3399_PLLCON1_REFDIV_MASK 0x3f +#define RK3399_PLLCON1_REFDIV_SHIFT 0 +#define RK3399_PLLCON1_POSTDIV1_MASK 0x7 +#define RK3399_PLLCON1_POSTDIV1_SHIFT 8 +#define RK3399_PLLCON1_POSTDIV2_MASK 0x7 +#define RK3399_PLLCON1_POSTDIV2_SHIFT 12 +#define RK3399_PLLCON2_FRAC_MASK 0xffffff +#define RK3399_PLLCON2_FRAC_SHIFT 0 +#define RK3399_PLLCON2_LOCK_STATUS BIT(31) +#define RK3399_PLLCON3_PWRDOWN BIT(0) +#define RK3399_PLLCON3_DSMPD_MASK 0x1 +#define RK3399_PLLCON3_DSMPD_SHIFT 3 + +static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) +{ + u32 pllcon; + int delay = 24000000; + + /* poll check the lock status in rk3399 xPLLCON2 */ + while (delay > 0) { + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); + if (pllcon & RK3399_PLLCON2_LOCK_STATUS) + return 0; + + delay--; + } + + pr_err("%s: timeout waiting for pll to lock\n", __func__); + return -ETIMEDOUT; +} + +static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, + struct rockchip_pll_rate_table *rate) +{ + u32 pllcon; + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0)); + rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT) + & RK3399_PLLCON0_FBDIV_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1)); + rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT) + & RK3399_PLLCON1_REFDIV_MASK); + rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT) + & RK3399_PLLCON1_POSTDIV1_MASK); + rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT) + & RK3399_PLLCON1_POSTDIV2_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); + rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT) + & RK3399_PLLCON2_FRAC_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3)); + rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT) + & RK3399_PLLCON3_DSMPD_MASK); +} + +static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + struct rockchip_pll_rate_table cur; + u64 rate64 = prate; + + rockchip_rk3399_pll_get_params(pll, &cur); + + rate64 *= cur.fbdiv; + do_div(rate64, cur.refdiv); + + if (cur.dsmpd == 0) { + /* fractional mode */ + u64 frac_rate64 = prate * cur.frac; + + do_div(frac_rate64, cur.refdiv); + rate64 += frac_rate64 >> 24; + } + + do_div(rate64, cur.postdiv1); + do_div(rate64, cur.postdiv2); + + return (unsigned long)rate64; +} + +static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll, + const struct rockchip_pll_rate_table *rate) +{ + const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; + struct clk_mux *pll_mux = &pll->pll_mux; + struct rockchip_pll_rate_table cur; + u32 pllcon; + int rate_change_remuxed = 0; + int cur_parent; + int ret; + + pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, + rate->postdiv2, rate->dsmpd, rate->frac); + + rockchip_rk3399_pll_get_params(pll, &cur); + cur.rate = 0; + + cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); + if (cur_parent == PLL_MODE_NORM) { + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); + rate_change_remuxed = 1; + } + + /* update pll values */ + writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK, + RK3399_PLLCON0_FBDIV_SHIFT), + pll->reg_base + RK3399_PLLCON(0)); + + writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK, + RK3399_PLLCON1_REFDIV_SHIFT) | + HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK, + RK3399_PLLCON1_POSTDIV1_SHIFT) | + HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK, + RK3399_PLLCON1_POSTDIV2_SHIFT), + pll->reg_base + RK3399_PLLCON(1)); + + /* xPLL CON2 is not HIWORD_MASK */ + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); + pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT); + pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT; + writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2)); + + writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK, + RK3399_PLLCON3_DSMPD_SHIFT), + pll->reg_base + RK3399_PLLCON(3)); + + /* wait for the pll to lock */ + ret = rockchip_rk3399_pll_wait_lock(pll); + if (ret) { + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", + __func__); + rockchip_rk3399_pll_set_params(pll, &cur); + } + + if (rate_change_remuxed) + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); + + return ret; +} + +static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + unsigned long old_rate = rockchip_rk3399_pll_recalc_rate(hw, prate); + + pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", + __func__, __clk_get_name(hw->clk), old_rate, drate, prate); + + /* Get required rate settings from table */ + rate = rockchip_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + return rockchip_rk3399_pll_set_params(pll, rate); +} + +static int rockchip_rk3399_pll_enable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3399_PLLCON(3)); + + return 0; +} + +static void rockchip_rk3399_pll_disable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN, + RK3399_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3399_PLLCON(3)); +} + +static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(3)); + + return !(pllcon & RK3399_PLLCON3_PWRDOWN); +} + +static void rockchip_rk3399_pll_init(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + struct rockchip_pll_rate_table cur; + unsigned long drate; + + if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) + return; + + drate = clk_hw_get_rate(hw); + rate = rockchip_get_pll_settings(pll, drate); + + /* when no rate setting for the current rate, rely on clk_set_rate */ + if (!rate) + return; + + rockchip_rk3399_pll_get_params(pll, &cur); + + pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk), + drate); + pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2, + cur.dsmpd, cur.frac); + pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, + rate->dsmpd, rate->frac); + + if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || + rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || + rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) { + struct clk *parent = clk_get_parent(hw->clk); + + if (!parent) { + pr_warn("%s: parent of %s not available\n", + __func__, __clk_get_name(hw->clk)); + return; + } + + pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", + __func__, __clk_get_name(hw->clk)); + rockchip_rk3399_pll_set_params(pll, rate); + } +} + +static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = { + .recalc_rate = rockchip_rk3399_pll_recalc_rate, + .enable = rockchip_rk3399_pll_enable, + .disable = rockchip_rk3399_pll_disable, + .is_enabled = rockchip_rk3399_pll_is_enabled, +}; + +static const struct clk_ops rockchip_rk3399_pll_clk_ops = { + .recalc_rate = rockchip_rk3399_pll_recalc_rate, + .round_rate = rockchip_pll_round_rate, + .set_rate = rockchip_rk3399_pll_set_rate, + .enable = rockchip_rk3399_pll_enable, + .disable = rockchip_rk3399_pll_disable, + .is_enabled = rockchip_rk3399_pll_is_enabled, + .init = rockchip_rk3399_pll_init, +}; + /* * Common registering of pll clocks */ @@ -634,7 +895,9 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, pll_mux->lock = &ctx->lock; pll_mux->hw.init = &init; - if (pll_type == pll_rk3036 || pll_type == pll_rk3066) + if (pll_type == pll_rk3036 || + pll_type == pll_rk3066 || + pll_type == pll_rk3399) pll_mux->flags |= CLK_MUX_HIWORD_MASK; /* the actual muxing is xin24m, pll-output, xin32k */ @@ -691,6 +954,12 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, else init.ops = &rockchip_rk3066_pll_clk_ops; break; + case pll_rk3399: + if (!pll->rate_table) + init.ops = &rockchip_rk3399_pll_clk_norate_ops; + else + init.ops = &rockchip_rk3399_pll_clk_ops; + break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, name); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index e243d509da89..4798786703b8 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -96,6 +96,7 @@ struct clk; enum rockchip_pll_type { pll_rk3036, pll_rk3066, + pll_rk3399, }; #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ @@ -150,7 +151,7 @@ struct rockchip_pll_rate_table { unsigned int nf; unsigned int no; unsigned int nb; - /* for RK3036 */ + /* for RK3036/RK3399 */ unsigned int fbdiv; unsigned int postdiv1; unsigned int refdiv; -- GitLab From cb3abdd628abe8583c81b07d5bb8b6d1dbd12227 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Sun, 13 Mar 2016 00:25:00 +0800 Subject: [PATCH 0159/9938] clk: rockchip: remove mux_core_reg from rockchip_cpuclk_reg_data mux_core_reg isn't been used anywhere, let's remove it. Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 4798786703b8..b298f99dae97 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -245,7 +245,6 @@ struct rockchip_cpuclk_reg_data { int core_reg; u8 div_core_shift; u32 div_core_mask; - int mux_core_reg; u8 mux_core_alt; u8 mux_core_main; u8 mux_core_shift; -- GitLab From 2af2544d60f007277a98f66391a521ec377a6a67 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Sun, 13 Mar 2016 00:25:14 +0800 Subject: [PATCH 0160/9938] clk: rockchip: fix warning reported by kernel-doc ./scripts/kernel-doc -man -v drivers/clk/rockchip/clk.h > /dev/null drivers/clk/rockchip/clk.h:133: warning: missing initial short description on line: * struct rockchip_clk_provider: information about clock provider drivers/clk/rockchip/clk.h:133: info: Scanning doc for struct drivers/clk/rockchip/clk.h:164: warning: missing initial short description on line: * struct rockchip_pll_clock: information about pll clock drivers/clk/rockchip/clk.h:164: info: Scanning doc for struct drivers/clk/rockchip/clk.h:194: warning: No description found for parameter 'parent_names' drivers/clk/rockchip/clk.h:194: warning: No description found for parameter 'num_parents' drivers/clk/rockchip/clk.h:194: warning: Excess struct/union/enum/typedef member 'parent_name' description in 'rockchip_pll_clock' drivers/clk/rockchip/clk.h:235: warning: missing initial short description on line: * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index b298f99dae97..cb6a63963693 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -130,7 +130,7 @@ enum rockchip_pll_type { } /** - * struct rockchip_clk_provider: information about clock provider + * struct rockchip_clk_provider - information about clock provider * @reg_base: virtual address for the register base. * @clk_data: holds clock related data like clk* and number of clocks. * @cru_node: device-node of the clock-provider @@ -161,10 +161,11 @@ struct rockchip_pll_rate_table { }; /** - * struct rockchip_pll_clock: information about pll clock + * struct rockchip_pll_clock - information about pll clock * @id: platform specific id of the clock. * @name: name of this pll clock. - * @parent_name: name of the parent clock. + * @parent_names: name of the parent clock. + * @num_parents: number of parents * @flags: optional flags for basic clock. * @con_offset: offset of the register for configuring the PLL. * @mode_offset: offset of the register for configuring the PLL-mode. @@ -232,7 +233,7 @@ struct rockchip_cpuclk_rate_table { }; /** - * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock + * struct rockchip_cpuclk_reg_data - describes register offsets and masks of the cpuclock * @core_reg: register offset of the core settings register * @div_core_shift: core divider offset used to divide the pll value * @div_core_mask: core divider mask -- GitLab From ff1ae209617cb31a5297bd103709d6b9e2db77d2 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Sun, 13 Mar 2016 00:25:53 +0800 Subject: [PATCH 0161/9938] clk: rockchip: remove redundant checking of device_node rockchip_clk_of_add_provider is used by sub-clk driver which already call of_iomap before calling it. If device_node does not exist, of_iomap returns NULL which will fail to init the sub-clk driver. So really it's redundant. Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 5618a8761dee..277f9270bf72 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -359,11 +359,9 @@ struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, void __init rockchip_clk_of_add_provider(struct device_node *np, struct rockchip_clk_provider *ctx) { - if (np) { - if (of_clk_add_provider(np, of_clk_src_onecell_get, - &ctx->clk_data)) - pr_err("%s: could not register clk provider\n", __func__); - } + if (of_clk_add_provider(np, of_clk_src_onecell_get, + &ctx->clk_data)) + pr_err("%s: could not register clk provider\n", __func__); } struct regmap *rockchip_clk_get_grf(struct rockchip_clk_provider *ctx) -- GitLab From 1d003eb0805ac5b549e76202a1e95da33f62cb9a Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Sun, 13 Mar 2016 12:13:22 +0800 Subject: [PATCH 0162/9938] clk: rockchip: release io resource when failing to init clk We should call iounmap to relase reg_base since it's not going to be used any more if failing to init clk. Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 1 + drivers/clk/rockchip/clk-rk3188.c | 1 + drivers/clk/rockchip/clk-rk3228.c | 1 + drivers/clk/rockchip/clk-rk3288.c | 1 + drivers/clk/rockchip/clk-rk3368.c | 1 + 5 files changed, 5 insertions(+) diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index c7c8260e1c66..924f560dcf80 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -453,6 +453,7 @@ static void __init rk3036_clk_init(struct device_node *np) ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); return; } diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 0fcce2295b37..d0e722a0e8cf 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -773,6 +773,7 @@ static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); return ERR_PTR(-ENOMEM); } diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index c112b2f95224..016bdb0b793a 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -640,6 +640,7 @@ static void __init rk3228_clk_init(struct device_node *np) ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); return; } diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index d1031d1149ce..39af05a589b3 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -893,6 +893,7 @@ static void __init rk3288_clk_init(struct device_node *np) ctx = rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(rk3288_cru_base); return; } diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 3121414cfd63..6cb474c593e7 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -875,6 +875,7 @@ static void __init rk3368_clk_init(struct device_node *np) ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); return; } -- GitLab From cb53c7fc2045503cb7be0b225babd529df4d8cd3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 10 Mar 2016 22:38:02 +0100 Subject: [PATCH 0163/9938] ARM: dts: sun5i-a13-inet98v-rev2: Remove mmc2 node The sun5i-a13-inet98v-rev2 does not have an emmc, it uses nand, the mmc2 node in the dts comes from a copy and paste error from the utoo-p66 dts, remove it. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts b/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts index 6fa54b661423..1b11ec95ae53 100644 --- a/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts +++ b/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts @@ -123,21 +123,6 @@ status = "okay"; }; -&mmc2 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc2_pins_a>; - vmmc-supply = <®_vcc3v3>; - bus-width = <8>; - non-removable; - status = "okay"; - - mmccard: mmccard@0 { - reg = <0>; - compatible = "mmc-card"; - broken-hpi; - }; -}; - &otg_sram { status = "okay"; }; -- GitLab From 163172c08af685667199c293b8dc66705eb7430c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 10 Mar 2016 22:38:03 +0100 Subject: [PATCH 0164/9938] ARM: dts: sun5i-a13-empire-electronix-d709: Remove mmc2 node The empire-electronix-d709 does not have an emmc, it uses nand, the mmc2 node in the dts comes from a copy and paste error from the inet98fv2 dts, remove it. While at it also do s/inet98fv2/d709/ to fix some other copy/paste leftovers. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- .../dts/sun5i-a13-empire-electronix-d709.dts | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts b/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts index 7fbb0b0558a9..6efbba6d40a9 100644 --- a/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts +++ b/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts @@ -123,7 +123,7 @@ &mmc0 { pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_inet98fv2>; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_d709>; vmmc-supply = <®_vcc3v3>; bus-width = <4>; cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ @@ -131,27 +131,12 @@ status = "okay"; }; -&mmc2 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc2_pins_a>; - vmmc-supply = <®_vcc3v3>; - bus-width = <8>; - non-removable; - status = "okay"; - - mmccard: mmccard@0 { - reg = <0>; - compatible = "mmc-card"; - broken-hpi; - }; -}; - &otg_sram { status = "okay"; }; &pio { - mmc0_cd_pin_inet98fv2: mmc0_cd_pin@0 { + mmc0_cd_pin_d709: mmc0_cd_pin@0 { allwinner,pins = "PG0"; allwinner,function = "gpio_in"; allwinner,drive = ; -- GitLab From daac65ce575d906af7b7e4e2f914a65890696c57 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 10 Mar 2016 22:38:04 +0100 Subject: [PATCH 0165/9938] ARM: dts: sun5i: Add dts for Difrence DIT4350 tablet The Difrnce dit4350 tablet is a tiny tablet with a 4.3" 16:9 480x272 LCD, A13 SoC, 512M RAM, 4G NAND, solomon systech ssd2532qn6 touchscreen at i2c1 address 0x48, Memsic MXC622X accelerometer at i2c1 address 0x15 and rtl8188etv wifi. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/sun5i-a13-difrnce-dit4350.dts | 226 ++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..a4e973b4efaf 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -660,6 +660,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \ sun5i-a10s-olinuxino-micro.dtb \ sun5i-a10s-r7-tv-dongle.dtb \ sun5i-a10s-wobo-i5.dtb \ + sun5i-a13-difrnce-dit4350.dtb \ sun5i-a13-empire-electronix-d709.dtb \ sun5i-a13-hsg-h702.dtb \ sun5i-a13-inet-98v-rev2.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts b/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts new file mode 100644 index 000000000000..6546fa02901d --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts @@ -0,0 +1,226 @@ +/* + * Copyright 2016 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun5i-a13.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include +#include +#include +#include + +/ { + model = "Difrnce DIT4350"; + compatible = "difrnce,dit4350", "allwinner,sun5i-a13"; + + aliases { + serial0 = &uart1; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; + default-brightness-level = <8>; + /* TODO: backlight uses axp gpio1 as enable pin */ + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_d709>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ + cd-inverted; + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_d709: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PG2"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins>; + status = "okay"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_ldo3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_usb0_vbus { + gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */ + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usb0_vbus_pin_a { + allwinner,pins = "PG12"; +}; + +&usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */ + usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_ldo3>; + status = "okay"; +}; -- GitLab From aab42cde173acb1c7fe3f53706bc720d1a41681b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 9 Mar 2016 22:50:30 +0100 Subject: [PATCH 0166/9938] ARM: dts: sun6i: Add dts for colorfly e708 q1 tablet The colorfly e708 q1 is a 7" tablet which is clearly marked as colorfly e708 q1 on the back. It features a 9:16 800x1280 IPS LCD, A31s SoC, 1GB RAM, 8G NAND, ilitek 2139qt004 touchscreen on i2c-1 addr 0x41, stk8313 accelerometer on i2c-2 addr 0x22 and a rtl8188etv wifi chip. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/sun6i-a31s-colorfly-e708-q1.dts | 208 ++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index a4e973b4efaf..2c0801085515 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -676,6 +676,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \ sun6i-a31-i7.dtb \ sun6i-a31-m9.dtb \ sun6i-a31-mele-a1000g-quad.dtb \ + sun6i-a31s-colorfly-e708-q1.dtb \ sun6i-a31s-cs908.dtb \ sun6i-a31s-primo81.dtb \ sun6i-a31s-sina31s.dtb \ diff --git a/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts b/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts new file mode 100644 index 000000000000..e182eec6d878 --- /dev/null +++ b/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts @@ -0,0 +1,208 @@ +/* + * Copyright 2016 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun6i-a31s.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Colorfly E708 Q1 tablet"; + compatible = "colorfly,e708-q1", "allwinner,sun6i-a31s"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc3>; +}; + +&ehci0 { + /* rtl8188etv wifi is connected here */ + status = "okay"; +}; + +&lradc { + vref-supply = <®_aldo3>; + status = "okay"; + + button@1000 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <1000000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_e708_q1>; + vmmc-supply = <®_dcdc1>; + bus-width = <4>; + cd-gpios = <&pio 0 8 GPIO_ACTIVE_HIGH>; /* PA8 */ + cd-inverted; + status = "okay"; +}; + +&pio { + mma8452_int_e708_q1: mma8452_int_pin@0 { + allwinner,pins = "PA9"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_cd_pin_e708_q1: mmc0_cd_pin@0 { + allwinner,pins = "PA8"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&p2wi { + status = "okay"; + + axp22x: pmic@68 { + compatible = "x-powers,axp221"; + reg = <0x68>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +#include "axp22x.dtsi" + +®_aldo3 { + regulator-always-on; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3300000>; + regulator-name = "avcc"; +}; + +®_dc1sw { + regulator-name = "vcc-lcd"; +}; + +®_dc5ldo { + regulator-always-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1320000>; + regulator-name = "vdd-cpus"; /* This is an educated guess */ +}; + +®_dcdc1 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc-3v0"; +}; + +®_dcdc2 { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1320000>; + regulator-name = "vdd-gpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1320000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc4 { + regulator-always-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1320000>; + regulator-name = "vdd-sys-dll"; +}; + +®_dcdc5 { + regulator-always-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vcc-dram"; +}; + +®_dldo1 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_dldo2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-pg"; +}; + +&simplefb_lcd { + vcc-lcd-supply = <®_dc1sw>; + vcc-pg-supply = <®_dldo2>; +}; + +/* + * FIXME for now we only support host mode and rely on u-boot to have + * turned on Vbus which is controlled by the axp221 pmic on the board. + * + * Once we have axp221 power-supply and vbus-usb support we should switch + * to fully supporting otg. + */ +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_dldo1>; + status = "okay"; +}; -- GitLab From a1162a917da256e752c2842b2f7950f98d8fab3f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 13 Mar 2016 08:39:36 +0100 Subject: [PATCH 0167/9938] ARM: dts: sun8i: Add pmic nodes to sun8i-a23-gt90h-v4 Add nodes for the axp223 pmic and its regulators as found on a23-gt90h-v4 tablets. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts | 89 ++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts index 1aeb06c649b9..6a22ee3dcb55 100644 --- a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts +++ b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts @@ -123,12 +123,100 @@ }; }; +&r_rsb { + status = "okay"; + + axp22x: pmic@3a3 { + compatible = "x-powers,axp223"; + reg = <0x3a3>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + eldoin-supply = <®_dcdc1>; + }; +}; + &r_uart { pinctrl-names = "default"; pinctrl-0 = <&r_uart_pins_a>; status = "okay"; }; +#include "axp22x.dtsi" + +®_aldo1 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc-io"; +}; + +®_aldo2 { + regulator-always-on; + regulator-min-microvolt = <2350000>; + regulator-max-microvolt = <2650000>; + regulator-name = "vdd-dll"; +}; + +®_aldo3 { + regulator-always-on; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pll-avcc"; +}; + +®_dc1sw { + regulator-name = "vcc-lcd"; +}; + +®_dc5ldo { + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpus"; +}; + +®_dcdc1 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc-3v0"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-sys"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc5 { + regulator-always-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vcc-dram"; +}; + +®_dldo1 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_rtc_ldo { + regulator-name = "vcc-rtc"; +}; + +&simplefb_lcd { + vcc-lcd-supply = <®_dc1sw>; +}; + /* * FIXME for now we only support host mode and rely on u-boot to have * turned on Vbus which is controlled by the axp223 pmic on the board. @@ -141,5 +229,6 @@ }; &usbphy { + usb1_vbus-supply = <®_dldo1>; status = "okay"; }; -- GitLab From f7eda3d52b6215cb08535934eeba7b561076e09b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 13 Mar 2016 08:39:37 +0100 Subject: [PATCH 0168/9938] ARM: dts: sun8i: Add backlight / pwm nodes to sun8i-a23-gt90h-v4 Add nodes for the backlight / pwm found on a23-gt90h-v4 tablets. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts index 6a22ee3dcb55..1be8d5f6134d 100644 --- a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts +++ b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts @@ -47,6 +47,7 @@ #include #include #include +#include / { model = "Allwinner GT90H Quad Core Tablet (v4)"; @@ -56,6 +57,16 @@ serial0 = &r_uart; }; + backlight: backlight { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + pinctrl-0 = <&bl_en_pin_gt90h>; + pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; + default-brightness-level = <8>; + enable-gpios = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */ + }; + chosen { stdout-path = "serial0:115200n8"; }; @@ -115,6 +126,13 @@ }; &pio { + bl_en_pin_gt90h: bl_en_pin@0 { + allwinner,pins = "PH6"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + mmc0_cd_pin_gt90h: mmc0_cd_pin@0 { allwinner,pins = "PB4"; allwinner,function = "gpio_in"; @@ -123,6 +141,12 @@ }; }; +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins>; + status = "okay"; +}; + &r_rsb { status = "okay"; -- GitLab From 388bc9a70fddef3102992d70d45e57e5b3beb496 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Mar 2016 17:32:23 +0100 Subject: [PATCH 0169/9938] ARM: dts: sun8i: Fix wrong Quad core / a33 compat for sun8i-a23-gt90h-v4 As the dts file name already implies sun8i-a23-gt90h-v4.dts is for an a23 equipped tablet. I don't know how the "Quad Core" or a33 comaptible got in there, likely a copy and paste error. Regardless this commit fixes this, note this is almost purely a cosmetical fix, for all things that matter at the machine compatible level the a23 and a33 are compatible. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts index 1be8d5f6134d..1d68f5ce1890 100644 --- a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts +++ b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts @@ -50,8 +50,8 @@ #include / { - model = "Allwinner GT90H Quad Core Tablet (v4)"; - compatible = "allwinner,gt90h-v4", "allwinner,sun8i-a33"; + model = "Allwinner GT90H Dual Core Tablet (v4)"; + compatible = "allwinner,gt90h-v4", "allwinner,sun8i-a23"; aliases { serial0 = &r_uart; -- GitLab From cbed866e57bad958ccbf8ba2b13c987bd1167de3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Mar 2016 17:32:24 +0100 Subject: [PATCH 0170/9938] ARM: dts: sun8i: Fix regulator for mmc0 for sun8i-a23-gt90h-v4 Address the FIXME comment in sun8i-a23-gt90h-v4.dts now that we've proper regulator support. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts index 1d68f5ce1890..b2ce284a65a2 100644 --- a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts +++ b/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts @@ -117,8 +117,7 @@ &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_gt90h>; - /* FIXME this really is aldo1, correct once we've pmic support */ - vmmc-supply = <®_vcc3v0>; + vmmc-supply = <®_aldo1>; bus-width = <4>; cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ cd-inverted; -- GitLab From 3dc2fdadf9d9183ada98c629abcf3d0807e42e54 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Mar 2016 17:32:25 +0100 Subject: [PATCH 0171/9938] ARM: dts: sun8i: Add dts file for the Polaroid MID2809PXE4 tablet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Polaroid MID2809PXE4 is a 9" tablet which is clearly marked Polaroid MID2809PXE4 on the back. It features a 9" 16:9 800x480 LCD, A23 Soc, 1GB RAM, 8GB NAND, gsl3670 touchscreen and esp8089 wifi. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + .../dts/sun8i-a23-polaroid-mid2809pxe04.dts | 243 ++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 2c0801085515..64faed2e839e 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -709,6 +709,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a23-gt90h-v4.dtb \ sun8i-a23-ippo-q8h-v5.dtb \ sun8i-a23-ippo-q8h-v1.2.dtb \ + sun8i-a23-polaroid-mid2809pxe04.dtb \ sun8i-a23-q8-tablet.dtb \ sun8i-a33-et-q8-v1.6.dtb \ sun8i-a33-ga10h-v1.1.dtb \ diff --git a/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts b/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts new file mode 100644 index 000000000000..cb5daafcb7c2 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts @@ -0,0 +1,243 @@ +/* + * Copyright 2016 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun8i-a23.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include +#include + +/ { + model = "Polaroid MID2809PXE04 tablet"; + compatible = "polaroid,mid2809pxe04", "allwinner,sun8i-a23"; + + aliases { + serial0 = &r_uart; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + pinctrl-0 = <&bl_en_pin_mid2809>; + pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; + default-brightness-level = <8>; + enable-gpios = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */ + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; + + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_mid2809>; + vmmc-supply = <®_dcdc1>; + bus-width = <4>; + cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ + cd-inverted; + status = "okay"; +}; + +&pio { + bl_en_pin_mid2809: bl_en_pin@0 { + allwinner,pins = "PH6"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_cd_pin_mid2809: mmc0_cd_pin@0 { + allwinner,pins = "PB4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins>; + status = "okay"; +}; + +&r_rsb { + status = "okay"; + + axp22x: pmic@3a3 { + compatible = "x-powers,axp223"; + reg = <0x3a3>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + eldoin-supply = <®_dcdc1>; + }; +}; + +&r_uart { + pinctrl-names = "default"; + pinctrl-0 = <&r_uart_pins_a>; + status = "okay"; +}; + +#include "axp22x.dtsi" + +®_aldo1 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc-io"; +}; + +®_aldo2 { + regulator-always-on; + regulator-min-microvolt = <2350000>; + regulator-max-microvolt = <2650000>; + regulator-name = "vdd-dll"; +}; + +®_aldo3 { + regulator-always-on; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pll-avcc"; +}; + +®_dc1sw { + regulator-name = "vcc-lcd"; +}; + +®_dc5ldo { + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpus"; +}; + +®_dcdc1 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc-3v0"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-sys"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc5 { + regulator-always-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vcc-dram"; +}; + +®_rtc_ldo { + regulator-name = "vcc-rtc"; +}; + +&simplefb_lcd { + vcc-lcd-supply = <®_dc1sw>; +}; + +/* + * FIXME for now we only support host mode and rely on u-boot to have + * turned on Vbus which is controlled by the axp223 pmic on the board. + * + * Once we have axp223 support we should switch to fully supporting otg. + */ +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; -- GitLab From 80410d49f821447ee9955eb0417f295648158f3b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 Mar 2016 08:53:52 +0100 Subject: [PATCH 0172/9938] ARM: dts: sun4i: Add dts file for Dserve DSRV9703C tablet The Dserve DSRV9703C is a 9.7" A10 tablet with a 1024x768 ips LCD, 1G RAM, 4GB flash, a Focaltech FT5406EE8 touchscreen and rtl8188ctv wifi. Signed-off-by: Hans de Goede Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/sun4i-a10-dserve-dsrv9703c.dts | 281 ++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 64faed2e839e..6ba68a2e7ce4 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -637,6 +637,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-ba10-tvbox.dtb \ sun4i-a10-chuwi-v7-cw0825.dtb \ sun4i-a10-cubieboard.dtb \ + sun4i-a10-dserve-dsrv9703c.dtb \ sun4i-a10-gemei-g9.dtb \ sun4i-a10-hackberry.dtb \ sun4i-a10-hyundai-a7hd.dtb \ diff --git a/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts b/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts new file mode 100644 index 000000000000..893497e397da --- /dev/null +++ b/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts @@ -0,0 +1,281 @@ +/* + * Copyright 2016 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun4i-a10.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include +#include +#include +#include + +/ { + model = "Dserve DSRV9703C"; + compatible = "dserve,dsrv9703c", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + pinctrl-0 = <&bl_en_pin_dsrv9703c>; + pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; + default-brightness-level = <8>; + enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */ + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + haptics { + compatible = "regulator-haptic"; + haptic-supply = <®_motor>; + min-microvolt = <3000000>; + max-microvolt = <3000000>; + }; + + reg_motor: reg_motor { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&motor_pins>; + regulator-name = "vcc-motor"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + enable-active-high; + gpio = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ + }; +}; + +&codec { + pinctrl-names = "default"; + pinctrl-0 = <&codec_pa_pin>; + allwinner,pa-gpios = <&pio 7 15 GPIO_ACTIVE_HIGH>; /* PH15 */ + status = "okay"; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + /* pull-ups and devices require AXP209 LDO3 */ + status = "failed"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; + + ft5406ee8: touchscreen@38 { + compatible = "edt,edt-ft5406"; + reg = <0x38>; + interrupt-parent = <&pio>; + interrupts = <7 21 IRQ_TYPE_EDGE_FALLING>; + pinctrl-names = "default"; + pinctrl-0 = <&touchscreen_pins>; + reset-gpios = <&pio 1 13 GPIO_ACTIVE_LOW>; + touchscreen-size-x = <1024>; + touchscreen-size-y = <768>; + }; +}; + +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; + + button@800 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <800000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pio { + bl_en_pin_dsrv9703c: bl_en_pin@0 { + allwinner,pins = "PH7"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + codec_pa_pin: codec_pa_pin@0 { + allwinner,pins = "PH15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + motor_pins: motor_pins@0 { + allwinner,pins = "PB3"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + touchscreen_pins: touchscreen_pins@0 { + allwinner,pins = "PB13"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PH5"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins_a>; + status = "okay"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb0_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; -- GitLab From 9461faf20fdf037abc9c755cc5cc01a1fb56c7e1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 20 Mar 2016 17:00:29 +0100 Subject: [PATCH 0173/9938] ARM: dts: sun8i: Add mmc2_8bit_pins to sun8i-h3.dtsi Add a pinctrl node for mmc2 in 8 bits mode on H3 SoCs. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index dadb7f60c062..d1be2f54fb0d 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -417,6 +417,16 @@ allwinner,drive = ; allwinner,pull = ; }; + + mmc2_8bit_pins: mmc2_8bit { + allwinner,pins = "PC5", "PC6", "PC8", + "PC9", "PC10", "PC11", + "PC12", "PC13", "PC14", + "PC15", "PC16"; + allwinner,function = "mmc2"; + allwinner,drive = ; + allwinner,pull = ; + }; }; ahb_rst: reset@01c202c0 { -- GitLab From bc9aa43fa94b25b2cf31c5efd02e8b2d2322cdb3 Mon Sep 17 00:00:00 2001 From: Reinder de Haan Date: Sun, 20 Mar 2016 17:00:30 +0100 Subject: [PATCH 0174/9938] ARM: dts: sun8i: Add support for H3 usb clocks Add a node describing the usb-clks found on the H3. Signed-off-by: Reinder de Haan Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index d1be2f54fb0d..3a2e6e2ae0bb 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -269,6 +269,18 @@ "mmc2_sample"; }; + usb_clk: clk@01c200cc { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun8i-h3-usb-clk"; + reg = <0x01c200cc 0x4>; + clocks = <&osc24M>; + clock-output-names = "usb_phy0", "usb_phy1", + "usb_phy2", "usb_phy3", + "usb_ohci0", "usb_ohci1", + "usb_ohci2", "usb_ohci3"; + }; + mbus_clk: clk@01c2015c { #clock-cells = <0>; compatible = "allwinner,sun8i-a23-mbus-clk"; -- GitLab From 4cf9654eb568ac96817693d5f629100becbfa650 Mon Sep 17 00:00:00 2001 From: Reinder de Haan Date: Sun, 20 Mar 2016 17:00:31 +0100 Subject: [PATCH 0175/9938] ARM: dts: sun8i: Add usbphy and usb host controller nodes Add nodes describing the H3's usbphy and usb host controller nodes. Signed-off-by: Reinder de Haan Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3.dtsi | 101 ++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index 3a2e6e2ae0bb..4a4926b0b0ed 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -389,6 +389,107 @@ #size-cells = <0>; }; + usbphy: phy@01c19400 { + compatible = "allwinner,sun8i-h3-usb-phy"; + reg = <0x01c19400 0x2c>, + <0x01c1a800 0x4>, + <0x01c1b800 0x4>, + <0x01c1c800 0x4>, + <0x01c1d800 0x4>; + reg-names = "phy_ctrl", + "pmu0", + "pmu1", + "pmu2", + "pmu3"; + clocks = <&usb_clk 8>, + <&usb_clk 9>, + <&usb_clk 10>, + <&usb_clk 11>; + clock-names = "usb0_phy", + "usb1_phy", + "usb2_phy", + "usb3_phy"; + resets = <&usb_clk 0>, + <&usb_clk 1>, + <&usb_clk 2>, + <&usb_clk 3>; + reset-names = "usb0_reset", + "usb1_reset", + "usb2_reset", + "usb3_reset"; + status = "disabled"; + #phy-cells = <1>; + }; + + ehci1: usb@01c1b000 { + compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; + reg = <0x01c1b000 0x100>; + interrupts = ; + clocks = <&bus_gates 25>, <&bus_gates 29>; + resets = <&ahb_rst 25>, <&ahb_rst 29>; + phys = <&usbphy 1>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci1: usb@01c1b400 { + compatible = "allwinner,sun8i-h3-ohci", "generic-ohci"; + reg = <0x01c1b400 0x100>; + interrupts = ; + clocks = <&bus_gates 29>, <&bus_gates 25>, + <&usb_clk 17>; + resets = <&ahb_rst 29>, <&ahb_rst 25>; + phys = <&usbphy 1>; + phy-names = "usb"; + status = "disabled"; + }; + + ehci2: usb@01c1c000 { + compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; + reg = <0x01c1c000 0x100>; + interrupts = ; + clocks = <&bus_gates 26>, <&bus_gates 30>; + resets = <&ahb_rst 26>, <&ahb_rst 30>; + phys = <&usbphy 2>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci2: usb@01c1c400 { + compatible = "allwinner,sun8i-h3-ohci", "generic-ohci"; + reg = <0x01c1c400 0x100>; + interrupts = ; + clocks = <&bus_gates 30>, <&bus_gates 26>, + <&usb_clk 18>; + resets = <&ahb_rst 30>, <&ahb_rst 26>; + phys = <&usbphy 2>; + phy-names = "usb"; + status = "disabled"; + }; + + ehci3: usb@01c1d000 { + compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; + reg = <0x01c1d000 0x100>; + interrupts = ; + clocks = <&bus_gates 27>, <&bus_gates 31>; + resets = <&ahb_rst 27>, <&ahb_rst 31>; + phys = <&usbphy 3>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci3: usb@01c1d400 { + compatible = "allwinner,sun8i-h3-ohci", "generic-ohci"; + reg = <0x01c1d400 0x100>; + interrupts = ; + clocks = <&bus_gates 31>, <&bus_gates 27>, + <&usb_clk 19>; + resets = <&ahb_rst 31>, <&ahb_rst 27>; + phys = <&usbphy 3>; + phy-names = "usb"; + status = "disabled"; + }; + pio: pinctrl@01c20800 { compatible = "allwinner,sun8i-h3-pinctrl"; reg = <0x01c20800 0x400>; -- GitLab From c2da9e05afa775633c38307c2d1de5b785227ea2 Mon Sep 17 00:00:00 2001 From: Jens Kuske Date: Sun, 20 Mar 2016 17:00:32 +0100 Subject: [PATCH 0176/9938] ARM: dts: sun8i: Enable USB host controllers on Orangepi Plus boards Enable the 2 USB host controllers used on the Orange Pi Plus and add the necessary regulators. Signed-off-by: Reinder de Haan Signed-off-by: Hans de Goede Signed-off-by: Jens Kuske Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index 79f40c3e6101..64aa8adbd632 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -90,6 +90,35 @@ gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; }; }; + + reg_usb3_vbus: usb3-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_vbus_pin_a>; + regulator-name = "usb3-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + enable-active-high; + gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; + }; +}; + +&ehci1 { + status = "okay"; +}; + +&ehci3 { + status = "okay"; +}; + +&pio { + usb3_vbus_pin_a: usb3_vbus_pin@0 { + allwinner,pins = "PG11"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; }; &pio { @@ -127,8 +156,23 @@ status = "okay"; }; +®_usb1_vbus { + gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins_a>; status = "okay"; }; + +&usb1_vbus_pin_a { + allwinner,pins = "PG13"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb3_vbus-supply = <®_usb3_vbus>; + status = "okay"; +}; -- GitLab From 99f9483ab475f735195f40f6cff46ba96cd89fc7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 20 Mar 2016 17:00:33 +0100 Subject: [PATCH 0177/9938] ARM: dts: sun8i: Enable IR receiver on Orangepi Plus boards Enable the ir receiver found on the orangepi plus board. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index 64aa8adbd632..ba7a959d304a 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -112,6 +112,12 @@ status = "okay"; }; +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + &pio { usb3_vbus_pin_a: usb3_vbus_pin@0 { allwinner,pins = "PG11"; -- GitLab From 4bf89c1dc692ad58d774c88dcf8f7946759ab04d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 20 Mar 2016 17:00:35 +0100 Subject: [PATCH 0178/9938] ARM: dts: sun8i: Add wifi dt node on Orangepi Plus boards The Orangepi Plus and Orangepi Plus 2 have a realtek rtl8189etv sdio wifi chip. This commit adds a device-tree node to power it up, so that the mmc subsys can scan it, and enables the mmc controller which is connected to it. Note that this just makes the wifi controller show up as a sdio device. In order for it to work a compatible sdio driver is necessary, an out of tree driver is available here: https://github.com/jwrdegoede/rtl8189ES_linux/ Binding the driver is not done through device tree, but through sdio vendor- and device-id, so it can safely be enabled in devicetree without having a driver upstream yet. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index ba7a959d304a..c5c17bdf8542 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -102,6 +102,13 @@ enable-active-high; gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_pwrseq_pin_orangepi>; + reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 WIFI_EN */ + }; }; &ehci1 { @@ -150,6 +157,13 @@ allwinner,drive = ; allwinner,pull = ; }; + + wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin@0 { + allwinner,pins = "PL7"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; }; &mmc0 { @@ -162,6 +176,16 @@ status = "okay"; }; +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>; + vmmc-supply = <®_vcc3v3>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + ®_usb1_vbus { gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; status = "okay"; -- GitLab From 1bfbcfd1475886ef0f49ef99850b730873843124 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 20 Mar 2016 17:00:36 +0100 Subject: [PATCH 0179/9938] ARM: dts: sun8i: Add eMMC dt node on Orangepi Plus boards The Orangepi Plus has a 16GB eMMC, the vcc, the lack of pull-ups and the use of the hw-reset pin have all been verified with the board schematic. With this dts node for mmc2, the eMMC runs at the following ios settings: clock: 52000000 Hz vdd: 21 (3.3 ~ 3.4 V) bus mode: 2 (push-pull) chip select: 0 (don't care) power mode: 2 (on) bus width: 3 (8 bits) timing spec: 8 (mmc DDR52) signal voltage: 0 (3.30 V) driver type: 0 (driver type B) Note the mmcblk1boot0/boot1 partitions are unused as the BROM will load the SPL from 8k from the start of the main blockdev, just as with a regular sdcard in mmc0. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index c5c17bdf8542..6273ddfa8c8f 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -186,6 +186,23 @@ status = "okay"; }; +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_8bit_pins>; + vmmc-supply = <®_vcc3v3>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + status = "okay"; +}; + +&mmc2_8bit_pins { + /* Increase drive strength for DDR modes */ + allwinner,drive = ; + /* eMMC is missing pull-ups */ + allwinner,pull = ; +}; + ®_usb1_vbus { gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; status = "okay"; -- GitLab From 79f969f08afe569d0705e509713bd2ce1f1062c4 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:00:59 +0100 Subject: [PATCH 0180/9938] ARM: dts: sun4i: Add SPDIF TX pin to the A10 Add the SPDIF TX pin to the A10 dtsi. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 2c8f5e6ad905..62fcef9b5eca 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -1006,6 +1006,13 @@ allwinner,drive = ; allwinner,pull = ; }; + + spdif_tx_pins_a: spdif@0 { + allwinner,pins = "PB13"; + allwinner,function = "spdif"; + allwinner,drive = ; + allwinner,pull = ; + }; }; timer@01c20c00 { -- GitLab From bdd08a84beafd21f3003af2b9e9c6496e701feef Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:01:00 +0100 Subject: [PATCH 0181/9938] ARM: dts: sun7i: Add SPDIF TX pin to the A20 Add the SPDIF TX pin to the A20 dtsi. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 0940a788f824..0c207d00d6c2 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -1193,6 +1193,13 @@ allwinner,drive = ; allwinner,pull = ; }; + + spdif_tx_pins_a: spdif@0 { + allwinner,pins = "PB13"; + allwinner,function = "spdif"; + allwinner,drive = ; + allwinner,pull = ; + }; }; timer@01c20c00 { -- GitLab From 1010cd549974dcee5ee172bd878f989c521c409f Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:01:01 +0100 Subject: [PATCH 0182/9938] ARM: dts: sun4i: Add the SPDIF clk to the A10 Add the SPDIF clock to the A10 dtsi. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 62fcef9b5eca..57475221b0e1 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -477,6 +477,17 @@ clock-output-names = "ir1"; }; + spdif_clk: clk@01c200c0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod1-clk"; + reg = <0x01c200c0 0x4>; + clocks = <&pll2 SUN4I_A10_PLL2_8X>, + <&pll2 SUN4I_A10_PLL2_4X>, + <&pll2 SUN4I_A10_PLL2_2X>, + <&pll2 SUN4I_A10_PLL2_1X>; + clock-output-names = "spdif"; + }; + usb_clk: clk@01c200cc { #clock-cells = <1>; #reset-cells = <1>; -- GitLab From 90b7a48935421d4605a181ee49de03224b93c205 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:01:02 +0100 Subject: [PATCH 0183/9938] ARM: dts: sun7i: Add the SPDIF clk to the A20 Add the SPDIF clock to the A20 dtsi. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 0c207d00d6c2..108cad4fb1fb 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -476,6 +476,17 @@ clock-output-names = "ir1"; }; + spdif_clk: clk@01c200c0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod1-clk"; + reg = <0x01c200c0 0x4>; + clocks = <&pll2 SUN4I_A10_PLL2_8X>, + <&pll2 SUN4I_A10_PLL2_4X>, + <&pll2 SUN4I_A10_PLL2_2X>, + <&pll2 SUN4I_A10_PLL2_1X>; + clock-output-names = "spdif"; + }; + keypad_clk: clk@01c200c4 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-mod0-clk"; -- GitLab From 166db83e0c127969f3e7acb0c9460251b107dc53 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:01:03 +0100 Subject: [PATCH 0184/9938] ARM: dts: sun4i: Add the SPDIF block to the A10 Add the SPDIF transceiver controller block to the A10 dtsi. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 57475221b0e1..7171a2712c8d 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -1052,6 +1052,19 @@ status = "disabled"; }; + spdif: spdif@01c21000 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun4i-a10-spdif"; + reg = <0x01c21000 0x400>; + interrupts = <13>; + clocks = <&apb0_gates 1>, <&spdif_clk>; + clock-names = "apb", "spdif"; + dmas = <&dma SUN4I_DMA_NORMAL 2>, + <&dma SUN4I_DMA_NORMAL 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + ir0: ir@01c21800 { compatible = "allwinner,sun4i-a10-ir"; clocks = <&apb0_gates 6>, <&ir0_clk>; -- GitLab From a34d6ce5eab955aa75232c151837e6e33cc8d5b6 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:01:04 +0100 Subject: [PATCH 0185/9938] ARM: dts: sun7i: Add the SPDIF block to the A20 Add the SPDIF transceiver controller block to the A20 dtsi. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 108cad4fb1fb..99444965f24e 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -1244,6 +1244,19 @@ status = "disabled"; }; + spdif: spdif@01c21000 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun4i-a10-spdif"; + reg = <0x01c21000 0x400>; + interrupts = ; + clocks = <&apb0_gates 1>, <&spdif_clk>; + clock-names = "apb", "spdif"; + dmas = <&dma SUN4I_DMA_NORMAL 2>, + <&dma SUN4I_DMA_NORMAL 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + ir0: ir@01c21800 { compatible = "allwinner,sun4i-a10-ir"; clocks = <&apb0_gates 6>, <&ir0_clk>; -- GitLab From 8bdc4a0d7bd292c9fd09274431b0d6466faa7e8f Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:01:05 +0100 Subject: [PATCH 0186/9938] ARM: dts: sun4i: Add SPDIF to the Mele A1000 Enable the S/PDIF transmitter that is present on the A1000. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-a1000.dts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts index 97570cb7f2fc..c92a1ae33a1e 100644 --- a/arch/arm/boot/dts/sun4i-a10-a1000.dts +++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts @@ -87,6 +87,24 @@ enable-active-high; gpio = <&pio 7 15 GPIO_ACTIVE_HIGH>; }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "On-board SPDIF"; + + simple-audio-card,cpu { + sound-dai = <&spdif>; + }; + + simple-audio-card,codec { + sound-dai = <&spdif_out>; + }; + }; + + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; }; &ahci { @@ -188,6 +206,12 @@ status = "okay"; }; +&spdif { + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx_pins_a>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins_a>; -- GitLab From be0f167a85765e9f559785745d85364022b8395c Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Mon, 21 Mar 2016 21:01:06 +0100 Subject: [PATCH 0187/9938] ARM: dts: sun7i: Add SPDIF to the Itead Ibox Enable the S/PDIF transmitter that is present on the Itead Ibox. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-itead-ibox.dts | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts index 661c21d9bdbd..10d48cbf81ff 100644 --- a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts +++ b/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts @@ -65,6 +65,24 @@ default-state = "on"; }; }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "On-board SPDIF"; + + simple-audio-card,cpu { + sound-dai = <&spdif>; + }; + + simple-audio-card,codec { + sound-dai = <&spdif_out>; + }; + }; + + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; }; &ahci { @@ -123,3 +141,9 @@ ®_ahci_5v { status = "okay"; }; + +&spdif { + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx_pins_a>; + status = "okay"; +}; -- GitLab From 1813ac1abdc7360839c914a146a8ce5a25834f6c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 22 Mar 2016 21:53:21 +0100 Subject: [PATCH 0188/9938] ARM: dts: sun8i: Fix pio nodes Orangepi Plus dts Fix sun8i-h3-orangepi-plus.dts: 1) Having 2 pio nodes, by merging these into one 2) Having the pio and r_pio nodes before the mmc nodes, while they should be sorted by alphabet Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 80 ++++++++++---------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index 6273ddfa8c8f..3d9996f1f947 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -125,47 +125,6 @@ status = "okay"; }; -&pio { - usb3_vbus_pin_a: usb3_vbus_pin@0 { - allwinner,pins = "PG11"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; -}; - -&pio { - leds_opc: led_pins@0 { - allwinner,pins = "PA15"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; -}; - -&r_pio { - leds_r_opc: led_pins@0 { - allwinner,pins = "PL10"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - sw_r_opc: key_pins@0 { - allwinner,pins = "PL03"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin@0 { - allwinner,pins = "PL7"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; -}; - &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; @@ -203,6 +162,45 @@ allwinner,pull = ; }; +&pio { + leds_opc: led_pins@0 { + allwinner,pins = "PA15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb3_vbus_pin_a: usb3_vbus_pin@0 { + allwinner,pins = "PG11"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&r_pio { + leds_r_opc: led_pins@0 { + allwinner,pins = "PL10"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + sw_r_opc: key_pins@0 { + allwinner,pins = "PL03"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin@0 { + allwinner,pins = "PL7"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + ®_usb1_vbus { gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; status = "okay"; -- GitLab From 7b4fad5f22d54639c17d206b94dd1b245b22c494 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 22 Mar 2016 22:37:29 +0100 Subject: [PATCH 0189/9938] ARM: dts: sun8i: Add Orange Pi PC support The Orange Pi PC is an SBC based on the Allwinner H3 SoC with a uSD slot, 3 USB ports directly from the SoC, a 10/100M ethernet port using the SoC's integrated PHY, USB OTG, HDMI, a TRRS headphone jack for stereo out and composite out, a microphone, an IR receiver, a CSI connector, 2 LEDs, a 3 pin UART header, and a 40-pin GPIO header. Signed-off-by: Chen-Yu Tsai Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 167 +++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 6ba68a2e7ce4..5b72ff773729 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -719,6 +719,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a33-sinlinx-sina33.dtb \ sun8i-a83t-allwinner-h8homlet-v2.dtb \ sun8i-a83t-cubietruck-plus.dtb \ + sun8i-h3-orangepi-pc.dtb \ sun8i-h3-orangepi-plus.dtb dtb-$(CONFIG_MACH_SUN9I) += \ sun9i-a80-optimus.dtb \ diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts new file mode 100644 index 000000000000..daf50b9a6657 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2015 Chen-Yu Tsai + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun8i-h3.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Xunlong Orange Pi PC"; + compatible = "xunlong,orangepi-pc", "allwinner,sun8i-h3"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_opc>, <&leds_r_opc>; + + pwr_led { + label = "orangepi:green:pwr"; + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + status_led { + label = "orangepi:red:status"; + gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; + }; + }; + + r_gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&sw_r_opc>; + + sw4 { + label = "sw4"; + linux,code = ; + gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&ehci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&ehci3 { + status = "okay"; +}; + +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ + cd-inverted; + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +&ohci3 { + status = "okay"; +}; + +&pio { + leds_opc: led_pins@0 { + allwinner,pins = "PA15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&r_pio { + leds_r_opc: led_pins@0 { + allwinner,pins = "PL10"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + sw_r_opc: key_pins@0 { + allwinner,pins = "PL3"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + /* USB VBUS is always on */ + status = "okay"; +}; -- GitLab From c4392ef6c52506823e05d98b1a3ff73c85fed491 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 23 Mar 2016 11:17:05 +0100 Subject: [PATCH 0190/9938] ARM: dts: sun8i: Add dts for Orange Pi 2 SBC The Orange Pi 2 is a SBC based on the Allwinner H3 SoC with a uSD slot, 4 USB ports connected via a USB-2 hub, a 10/100M ethernet port using the SoC's integrated PHY, Wifi via a RTL8189ETV sdio wifi chip, USB OTG, HDMI, a TRRS headphone jack for stereo out and composite out, a microphone, an IR receiver, a CSI connector, 2 LEDs, a 3 pin UART header and a 40-pin GPIO header. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 186 ++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-2.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 5b72ff773729..9208da82459d 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -719,6 +719,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a33-sinlinx-sina33.dtb \ sun8i-a83t-allwinner-h8homlet-v2.dtb \ sun8i-a83t-cubietruck-plus.dtb \ + sun8i-h3-orangepi-2.dtb \ sun8i-h3-orangepi-pc.dtb \ sun8i-h3-orangepi-plus.dtb dtb-$(CONFIG_MACH_SUN9I) += \ diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts new file mode 100644 index 000000000000..f93f5d1695c4 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2016 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun8i-h3.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Xunlong Orange Pi 2"; + compatible = "xunlong,orangepi-2", "allwinner,sun8i-h3"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_opc>, <&leds_r_opc>; + + status_led { + label = "orangepi:red:status"; + gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; + }; + + pwr_led { + label = "orangepi:green:pwr"; + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + + r_gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&sw_r_opc>; + + sw2 { + label = "sw2"; + linux,code = ; + gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; + }; + + sw4 { + label = "sw4"; + linux,code = ; + gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; + }; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_pwrseq_pin_orangepi>; + reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 WIFI_EN */ + }; +}; + +&ehci1 { + status = "okay"; +}; + +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ + cd-inverted; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>; + vmmc-supply = <®_vcc3v3>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&pio { + leds_opc: led_pins@0 { + allwinner,pins = "PA15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&r_pio { + leds_r_opc: led_pins@0 { + allwinner,pins = "PL10"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + sw_r_opc: key_pins@0 { + allwinner,pins = "PL3", "PL4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin@0 { + allwinner,pins = "PL7"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb1_vbus_pin_a { + allwinner,pins = "PG13"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; -- GitLab From cd544a8466506385dfa943f0f8bab89f82cf0bf0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 22 Mar 2016 21:53:22 +0100 Subject: [PATCH 0191/9938] ARM: dts: sun8i: Orangepi plus gpio keys fixes and improvements Fix the following issues with the gpio_keys node: 1) Use of undocumented input-name property 2) Use of a unit-address on the sw2 node 3) Having "PL03" in the pinctrl node which does not exist, this should be "PL3" And add support for the sw2 button on the board. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index 3d9996f1f947..94f8b0b834cd 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -79,12 +79,16 @@ r_gpio_keys { compatible = "gpio-keys"; - input-name = "sw4"; - pinctrl-names = "default"; pinctrl-0 = <&sw_r_opc>; - sw4@0 { + sw2 { + label = "sw2"; + linux,code = ; + gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; + }; + + sw4 { label = "sw4"; linux,code = ; gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; @@ -187,7 +191,7 @@ }; sw_r_opc: key_pins@0 { - allwinner,pins = "PL03"; + allwinner,pins = "PL3", "PL4"; allwinner,function = "gpio_in"; allwinner,drive = ; allwinner,pull = ; -- GitLab From 0c1747a24855f6ce9668283be0b6839f4c0ab4cf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 23 Mar 2016 23:14:16 +0100 Subject: [PATCH 0192/9938] ARM: dts: sun8i: Base Orange Pi Plus dts on the Orange Pi 2 dts The Orange Pi Plus really is an Orange Pi 2 extended with: 1) A sata <-> usb bridge connected to ehci3 2) An eMMC on mmc2 3) An external gigabit ethernet phy instead of the integrated 100Mbit phy This commit changes the dts to reflect this by making it include the Orange Pi 2 dts and then adding the extra bits. Note that the difference in ethernet phy is not taken into account because we do not have an ethernet driver for the H3 yet. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 136 +------------------ 1 file changed, 2 insertions(+), 134 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index 94f8b0b834cd..b0cb41787e09 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -40,61 +40,13 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -/dts-v1/; -#include "sun8i-h3.dtsi" -#include "sunxi-common-regulators.dtsi" - -#include -#include -#include +/* The Orange Pi Plus is an extended version of the Orange Pi 2 */ +#include "sun8i-h3-orangepi-2.dts" / { model = "Xunlong Orange Pi Plus"; compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3"; - aliases { - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&leds_opc>, <&leds_r_opc>; - - status_led { - label = "orangepi-plus:red:status"; - gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; - }; - - pwr_led { - label = "orangepi-plus:green:pwr"; - gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - }; - - r_gpio_keys { - compatible = "gpio-keys"; - pinctrl-names = "default"; - pinctrl-0 = <&sw_r_opc>; - - sw2 { - label = "sw2"; - linux,code = ; - gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; - }; - - sw4 { - label = "sw4"; - linux,code = ; - gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; - }; - }; - reg_usb3_vbus: usb3-vbus { compatible = "regulator-fixed"; pinctrl-names = "default"; @@ -106,49 +58,12 @@ enable-active-high; gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; }; - - wifi_pwrseq: wifi_pwrseq { - compatible = "mmc-pwrseq-simple"; - pinctrl-names = "default"; - pinctrl-0 = <&wifi_pwrseq_pin_orangepi>; - reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 WIFI_EN */ - }; -}; - -&ehci1 { - status = "okay"; }; &ehci3 { status = "okay"; }; -&ir { - pinctrl-names = "default"; - pinctrl-0 = <&ir_pins_a>; - status = "okay"; -}; - -&mmc0 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ - cd-inverted; - status = "okay"; -}; - -&mmc1 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc1_pins_a>; - vmmc-supply = <®_vcc3v3>; - mmc-pwrseq = <&wifi_pwrseq>; - bus-width = <4>; - non-removable; - status = "okay"; -}; - &mmc2 { pinctrl-names = "default"; pinctrl-0 = <&mmc2_8bit_pins>; @@ -167,13 +82,6 @@ }; &pio { - leds_opc: led_pins@0 { - allwinner,pins = "PA15"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - usb3_vbus_pin_a: usb3_vbus_pin@0 { allwinner,pins = "PG11"; allwinner,function = "gpio_out"; @@ -182,46 +90,6 @@ }; }; -&r_pio { - leds_r_opc: led_pins@0 { - allwinner,pins = "PL10"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - sw_r_opc: key_pins@0 { - allwinner,pins = "PL3", "PL4"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin@0 { - allwinner,pins = "PL7"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; -}; - -®_usb1_vbus { - gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; - status = "okay"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; -}; - -&usb1_vbus_pin_a { - allwinner,pins = "PG13"; -}; - &usbphy { - usb1_vbus-supply = <®_usb1_vbus>; usb3_vbus-supply = <®_usb3_vbus>; - status = "okay"; }; -- GitLab From 59dbdd844a8b8e2d6793d3ee491da796752b97d5 Mon Sep 17 00:00:00 2001 From: JM Friedt Date: Thu, 24 Mar 2016 14:18:53 +0100 Subject: [PATCH 0193/9938] ARM: dts: sun5i-a13-olinuxino-micro: enable USB DRC Enable the OTG controller on the Olinuxino A13-micro. Signed-off-by: Jean-Michel Friedt Signed-off-by: Maxime Ripard --- .../boot/dts/sun5i-a13-olinuxino-micro.dts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts index ad84fe4276c9..081329e2b80b 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts @@ -109,6 +109,10 @@ status = "okay"; }; +&otg_sram { + status = "okay"; +}; + &pio { mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { allwinner,pins = "PG0"; @@ -124,6 +128,27 @@ allwinner,pull = ; }; + usb0_id_detect_pin: usb0_id_detect_pin@0 { + allwinner,pins = "PG2"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_pin_olinuxinom: usb0_vbus_pin@0 { + allwinner,pins = "PG12"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + usb1_vbus_pin_olinuxinom: usb1_vbus_pin@0 { allwinner,pins = "PG11"; allwinner,function = "gpio_out"; @@ -132,6 +157,12 @@ }; }; +®_usb0_vbus { + pinctrl-0 = <&usb0_vbus_pin_olinuxinom>; + gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + ®_usb1_vbus { pinctrl-0 = <&usb1_vbus_pin_olinuxinom>; gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; @@ -144,7 +175,17 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; + usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */ + usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + usb0_vbus-supply = <®_usb0_vbus>; usb1_vbus-supply = <®_usb1_vbus>; status = "okay"; }; -- GitLab From bec38aaafd9ec1463dd3857f02bc029707e4213d Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Thu, 24 Mar 2016 21:52:16 +0200 Subject: [PATCH 0194/9938] ARM: sun4i: dt: Enable dram gate 5 (tve0 clock) for simplefb TV output Seems like dram_gate 5 was forgotten when DRAM gate driver was added. Enable it. Cc: stable@vger.kernel.org Fixes: 82f8582feef4 (ARM: dts: sun4i: Add DRAM gates) Signed-off-by: Priit Laes Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 7171a2712c8d..268a1504d984 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -96,7 +96,7 @@ allwinner,pipeline = "de_fe0-de_be0-lcd0-tve0"; clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>, <&ahb_gates 44>, <&ahb_gates 46>, - <&dram_gates 25>, <&dram_gates 26>; + <&dram_gates 5>, <&dram_gates 25>, <&dram_gates 26>; status = "disabled"; }; }; -- GitLab From 4b8ccef22fb547007ac38c4e5a28a773adee1e6e Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Thu, 24 Mar 2016 21:52:17 +0200 Subject: [PATCH 0195/9938] ARM: sun7i: dt: Enable dram gate 5 (tve0 clock) for simplefb TV output Seems like dram_gate 5 was forgotten when DRAM gating driver was added. Add it. Cc: stable@vger.kernel.org Fixes: 0b4bf5a5200b (ARM: dts: sun7i: Add DRAM gates) Signed-off-by: Priit Laes Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 99444965f24e..bf5d05685d7d 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -85,8 +85,9 @@ compatible = "allwinner,simple-framebuffer", "simple-framebuffer"; allwinner,pipeline = "de_be0-lcd0-tve0"; - clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>, - <&ahb_gates 44>, <&dram_gates 26>; + clocks = <&pll5 1>, + <&ahb_gates 34>, <&ahb_gates 36>, <&ahb_gates 44>, + <&dram_gates 5>, <&dram_gates 26>; status = "disabled"; }; }; -- GitLab From fa3d2aede8bf9dd69e9309230169b5ec1cc234e4 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:57:10 +0900 Subject: [PATCH 0196/9938] arm64: dts: salvator-x: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the kzm9g device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- .../boot/dts/renesas/r8a7795-salvator-x.dts | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index b992b1a3d956..5165d450c10b 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -146,57 +146,57 @@ pinctrl-names = "default"; scif1_pins: scif1 { - renesas,groups = "scif1_data_a", "scif1_ctrl"; - renesas,function = "scif1"; + groups = "scif1_data_a", "scif1_ctrl"; + function = "scif1"; }; scif2_pins: scif2 { - renesas,groups = "scif2_data_a"; - renesas,function = "scif2"; + groups = "scif2_data_a"; + function = "scif2"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk_a"; - renesas,function = "scif_clk"; + groups = "scif_clk_a"; + function = "scif_clk"; }; i2c2_pins: i2c2 { - renesas,groups = "i2c2_a"; - renesas,function = "i2c2"; + groups = "i2c2_a"; + function = "i2c2"; }; avb_pins: avb { - renesas,groups = "avb_mdc"; - renesas,function = "avb"; + groups = "avb_mdc"; + function = "avb"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; }; sdhi3_pins: sd3 { - renesas,groups = "sdhi3_data4", "sdhi3_ctrl"; - renesas,function = "sdhi3"; + groups = "sdhi3_data4", "sdhi3_ctrl"; + function = "sdhi3"; }; sound_pins: sound { - renesas,groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; - renesas,function = "ssi"; + groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; + function = "ssi"; }; sound_clk_pins: sound_clk { - renesas,groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", - "audio_clkout_a", "audio_clkout3_a"; - renesas,function = "audio_clk"; + groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", + "audio_clkout_a", "audio_clkout3_a"; + function = "audio_clk"; }; usb1_pins: usb1 { - renesas,groups = "usb1"; - renesas,function = "usb1"; + groups = "usb1"; + function = "usb1"; }; usb2_pins: usb2 { - renesas,groups = "usb2"; - renesas,function = "usb2"; + groups = "usb2"; + function = "usb2"; }; }; -- GitLab From 7811482f0e2521249bb6cf76dffd863a3dda8e07 Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Fri, 26 Feb 2016 16:38:47 +0000 Subject: [PATCH 0197/9938] arm64: dts: r8a7795: Add CAN external clock support Adds external CAN clock node for r8a7795. This clock can be used as fCAN clock of CAN and CAN FD controller. Signed-off-by: Ramesh Shanmugasundaram Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index a7315ebe3883..4049182e6608 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -115,6 +115,14 @@ clock-frequency = <0>; }; + /* External CAN clock - to be overridden by boards that provide it */ + can_clk: can { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + status = "disabled"; + }; + /* External SCIF clock - to be overridden by boards that provide it */ scif_clk: scif { compatible = "fixed-clock"; -- GitLab From 308b7e4ba62e2ab60efcaf426cc219d591f0cd28 Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Mon, 29 Feb 2016 14:22:39 +0000 Subject: [PATCH 0198/9938] arm64: dts: r8a7795: Add CAN support Adds CAN controller nodes for r8a7795. Note: CAN channel register base address mentioned in R-Car Gen3 Hardware User Manual v0.5E is incorrect. The corrected base addresses are: CAN Channel 0 - 0xe6c30000 CAN Channel 1 - 0xe6c38000 Signed-off-by: Ramesh Shanmugasundaram Signed-off-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index 4049182e6608..a88f8d840c48 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -523,6 +523,36 @@ #size-cells = <0>; }; + can0: can@e6c30000 { + compatible = "renesas,can-r8a7795", + "renesas,rcar-gen3-can"; + reg = <0 0xe6c30000 0 0x1000>; + interrupts = ; + clocks = <&cpg CPG_MOD 916>, + <&cpg CPG_CORE R8A7795_CLK_CANFD>, + <&can_clk>; + clock-names = "clkp1", "clkp2", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>; + assigned-clock-rates = <40000000>; + power-domains = <&cpg>; + status = "disabled"; + }; + + can1: can@e6c38000 { + compatible = "renesas,can-r8a7795", + "renesas,rcar-gen3-can"; + reg = <0 0xe6c38000 0 0x1000>; + interrupts = ; + clocks = <&cpg CPG_MOD 915>, + <&cpg CPG_CORE R8A7795_CLK_CANFD>, + <&can_clk>; + clock-names = "clkp1", "clkp2", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>; + assigned-clock-rates = <40000000>; + power-domains = <&cpg>; + status = "disabled"; + }; + hscif0: serial@e6540000 { compatible = "renesas,hscif-r8a7795", "renesas,rcar-gen3-hscif", -- GitLab From 81ae0ac31bb90baef10850fdfdc2a9f72f36aa6f Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 24 Mar 2016 11:01:09 +0900 Subject: [PATCH 0199/9938] arm64: dts: r8a7795: Use USB3.0 fallback compatibility string Use recently added fallback compatibility string in r8a7795 device tree. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index a88f8d840c48..868c10eaea48 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -982,7 +982,7 @@ }; xhci0: usb@ee000000 { - compatible = "renesas,xhci-r8a7795"; + compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci"; reg = <0 0xee000000 0 0xc00>; interrupts = ; clocks = <&cpg CPG_MOD 328>; @@ -991,7 +991,7 @@ }; xhci1: usb@ee0400000 { - compatible = "renesas,xhci-r8a7795"; + compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci"; reg = <0 0xee040000 0 0xc00>; interrupts = ; clocks = <&cpg CPG_MOD 327>; -- GitLab From 2ffc224f3ab047f16d2dc73b90a6fe148c03f946 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 16 Mar 2016 10:03:09 +0900 Subject: [PATCH 0200/9938] ARM: dts: lager: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the lager device tree to use the generic rather than renesas-specific properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven Acked-by: Laurent Pinchart --- arch/arm/boot/dts/r8a7790-lager.dts | 92 ++++++++++++++--------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index aa6ca92a9485..a5828721ab7c 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -314,119 +314,119 @@ pinctrl-names = "default"; du_pins: du { - renesas,groups = "du_rgb666", "du_sync_1", "du_clk_out_0"; - renesas,function = "du"; + groups = "du_rgb666", "du_sync_1", "du_clk_out_0"; + function = "du"; }; scif0_pins: serial0 { - renesas,groups = "scif0_data"; - renesas,function = "scif0"; + groups = "scif0_data"; + function = "scif0"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk"; - renesas,function = "scif_clk"; + groups = "scif_clk"; + function = "scif_clk"; }; ether_pins: ether { - renesas,groups = "eth_link", "eth_mdio", "eth_rmii"; - renesas,function = "eth"; + groups = "eth_link", "eth_mdio", "eth_rmii"; + function = "eth"; }; phy1_pins: phy1 { - renesas,groups = "intc_irq0"; - renesas,function = "intc"; + groups = "intc_irq0"; + function = "intc"; }; scifa1_pins: serial1 { - renesas,groups = "scifa1_data"; - renesas,function = "scifa1"; + groups = "scifa1_data"; + function = "scifa1"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; }; sdhi2_pins: sd2 { - renesas,groups = "sdhi2_data4", "sdhi2_ctrl"; - renesas,function = "sdhi2"; + groups = "sdhi2_data4", "sdhi2_ctrl"; + function = "sdhi2"; }; mmc1_pins: mmc1 { - renesas,groups = "mmc1_data8", "mmc1_ctrl"; - renesas,function = "mmc1"; + groups = "mmc1_data8", "mmc1_ctrl"; + function = "mmc1"; }; qspi_pins: spi0 { - renesas,groups = "qspi_ctrl", "qspi_data4"; - renesas,function = "qspi"; + groups = "qspi_ctrl", "qspi_data4"; + function = "qspi"; }; msiof1_pins: spi2 { - renesas,groups = "msiof1_clk", "msiof1_sync", "msiof1_rx", + groups = "msiof1_clk", "msiof1_sync", "msiof1_rx", "msiof1_tx"; - renesas,function = "msiof1"; + function = "msiof1"; }; i2c0_pins: i2c0 { - renesas,groups = "i2c0"; - renesas,function = "i2c0"; + groups = "i2c0"; + function = "i2c0"; }; iic0_pins: iic0 { - renesas,groups = "iic0"; - renesas,function = "iic0"; + groups = "iic0"; + function = "iic0"; }; iic1_pins: iic1 { - renesas,groups = "iic1"; - renesas,function = "iic1"; + groups = "iic1"; + function = "iic1"; }; iic2_pins: iic2 { - renesas,groups = "iic2"; - renesas,function = "iic2"; + groups = "iic2"; + function = "iic2"; }; iic3_pins: iic3 { - renesas,groups = "iic3"; - renesas,function = "iic3"; + groups = "iic3"; + function = "iic3"; }; hsusb_pins: hsusb { - renesas,groups = "usb0_ovc_vbus"; - renesas,function = "usb0"; + groups = "usb0_ovc_vbus"; + function = "usb0"; }; usb0_pins: usb0 { - renesas,groups = "usb0"; - renesas,function = "usb0"; + groups = "usb0"; + function = "usb0"; }; usb1_pins: usb1 { - renesas,groups = "usb1"; - renesas,function = "usb1"; + groups = "usb1"; + function = "usb1"; }; usb2_pins: usb2 { - renesas,groups = "usb2"; - renesas,function = "usb2"; + groups = "usb2"; + function = "usb2"; }; vin1_pins: vin { - renesas,groups = "vin1_data8", "vin1_clk"; - renesas,function = "vin1"; + groups = "vin1_data8", "vin1_clk"; + function = "vin1"; }; sound_pins: sound { - renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; - renesas,function = "ssi"; + groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; + function = "ssi"; }; sound_clk_pins: sound_clk { - renesas,groups = "audio_clk_a"; - renesas,function = "audio_clk"; + groups = "audio_clk_a"; + function = "audio_clk"; }; }; -- GitLab From a32f5cff122b41f01a4ed18a9007871344b651c3 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:52:11 +0900 Subject: [PATCH 0201/9938] ARM: dts: ape6evm: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the ape6evm device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index 590257095700..93ace33e3e36 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -189,28 +189,28 @@ &pfc { scifa0_pins: serial0 { - renesas,groups = "scifa0_data"; - renesas,function = "scifa0"; + groups = "scifa0_data"; + function = "scifa0"; }; mmc0_pins: mmc { - renesas,groups = "mmc0_data8", "mmc0_ctrl"; - renesas,function = "mmc0"; + groups = "mmc0_data8", "mmc0_ctrl"; + function = "mmc0"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd"; + function = "sdhi0"; }; sdhi1_pins: sd1 { - renesas,groups = "sdhi1_data4", "sdhi1_ctrl"; - renesas,function = "sdhi1"; + groups = "sdhi1_data4", "sdhi1_ctrl"; + function = "sdhi1"; }; keyboard_pins: keyboard { - renesas,pins = "PORT324", "PORT325", "PORT326", "PORT327", - "PORT328", "PORT329"; + pins = "PORT324", "PORT325", "PORT326", "PORT327", "PORT328", + "PORT329"; bias-pull-up; }; }; -- GitLab From 1ba1e26ededf070da2b1af117f912d2d9f05accf Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:53:17 +0900 Subject: [PATCH 0202/9938] ARM: dts: armadillo800eva: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the armadillo800eva device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts index c548cabb102f..2c82dab2b6f4 100644 --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts @@ -228,44 +228,44 @@ pinctrl-names = "default"; ether_pins: ether { - renesas,groups = "gether_mii", "gether_int"; - renesas,function = "gether"; + groups = "gether_mii", "gether_int"; + function = "gether"; }; scifa1_pins: serial1 { - renesas,groups = "scifa1_data"; - renesas,function = "scifa1"; + groups = "scifa1_data"; + function = "scifa1"; }; st1232_pins: touchscreen { - renesas,groups = "intc_irq10"; - renesas,function = "intc"; + groups = "intc_irq10"; + function = "intc"; }; backlight_pins: backlight { - renesas,groups = "tpu0_to2_1"; - renesas,function = "tpu0"; + groups = "tpu0_to2_1"; + function = "tpu0"; }; mmc0_pins: mmc0 { - renesas,groups = "mmc0_data8_1", "mmc0_ctrl_1"; - renesas,function = "mmc0"; + groups = "mmc0_data8_1", "mmc0_ctrl_1"; + function = "mmc0"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_wp"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_wp"; + function = "sdhi0"; }; fsia_pins: sounda { - renesas,groups = "fsia_sclk_in", "fsia_mclk_out", - "fsia_data_in_1", "fsia_data_out_0"; - renesas,function = "fsia"; + groups = "fsia_sclk_in", "fsia_mclk_out", + "fsia_data_in_1", "fsia_data_out_0"; + function = "fsia"; }; lcd0_pins: lcd0 { - renesas,groups = "lcd0_data24_0", "lcd0_lclk_1", "lcd0_sync"; - renesas,function = "lcd0"; + groups = "lcd0_data24_0", "lcd0_lclk_1", "lcd0_sync"; + function = "lcd0"; /* DBGMD/LCDC0/FSIA MUX */ gpio-hog; -- GitLab From ddf72563890a3361f7da82510ef8baca37a13830 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:53:54 +0900 Subject: [PATCH 0203/9938] ARM: dts: bockw: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the bockw device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7778-bockw.dts | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/r8a7778-bockw.dts b/arch/arm/boot/dts/r8a7778-bockw.dts index 21e3b9dda2da..e0dab1464648 100644 --- a/arch/arm/boot/dts/r8a7778-bockw.dts +++ b/arch/arm/boot/dts/r8a7778-bockw.dts @@ -130,53 +130,53 @@ pinctrl-names = "default"; scif0_pins: serial0 { - renesas,groups = "scif0_data_a", "scif0_ctrl"; - renesas,function = "scif0"; + groups = "scif0_data_a", "scif0_ctrl"; + function = "scif0"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk"; - renesas,function = "scif_clk"; + groups = "scif_clk"; + function = "scif_clk"; }; mmc_pins: mmc { - renesas,groups = "mmc_data8", "mmc_ctrl"; - renesas,function = "mmc"; + groups = "mmc_data8", "mmc_ctrl"; + function = "mmc"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; }; sdhi0_pup_pins: sd0_pup { - renesas,groups = "sdhi0_cd", "sdhi0_wp"; - renesas,function = "sdhi0"; + groups = "sdhi0_cd", "sdhi0_wp"; + function = "sdhi0"; bias-pull-up; }; hspi0_pins: hspi0 { - renesas,groups = "hspi0_a"; - renesas,function = "hspi0"; + groups = "hspi0_a"; + function = "hspi0"; }; usb0_pins: usb0 { - renesas,groups = "usb0"; - renesas,function = "usb0"; + groups = "usb0"; + function = "usb0"; }; usb1_pins: usb1 { - renesas,groups = "usb1"; - renesas,function = "usb1"; + groups = "usb1"; + function = "usb1"; }; vin0_pins: vin0 { - renesas,groups = "vin0_data8", "vin0_clk"; - renesas,function = "vin0"; + groups = "vin0_data8", "vin0_clk"; + function = "vin0"; }; vin1_pins: vin1 { - renesas,groups = "vin1_data8", "vin1_clk"; - renesas,function = "vin1"; + groups = "vin1_data8", "vin1_clk"; + function = "vin1"; }; }; -- GitLab From 8870d1393e0685d0bb1ae879fb1db3ffcf9a1020 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:54:24 +0900 Subject: [PATCH 0204/9938] ARM: dts: marzen: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the marzen device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7779-marzen.dts | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts index e111d35d02ae..b795da6f5503 100644 --- a/arch/arm/boot/dts/r8a7779-marzen.dts +++ b/arch/arm/boot/dts/r8a7779-marzen.dts @@ -170,49 +170,49 @@ du_pins: du { du0 { - renesas,groups = "du0_rgb888", "du0_sync_1", "du0_clk_out_0"; - renesas,function = "du0"; + groups = "du0_rgb888", "du0_sync_1", "du0_clk_out_0"; + function = "du0"; }; du1 { - renesas,groups = "du1_rgb666", "du1_sync_1", "du1_clk_out"; - renesas,function = "du1"; + groups = "du1_rgb666", "du1_sync_1", "du1_clk_out"; + function = "du1"; }; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk_b"; - renesas,function = "scif_clk"; + groups = "scif_clk_b"; + function = "scif_clk"; }; ethernet_pins: ethernet { intc { - renesas,groups = "intc_irq1_b"; - renesas,function = "intc"; + groups = "intc_irq1_b"; + function = "intc"; }; lbsc { - renesas,groups = "lbsc_ex_cs0"; - renesas,function = "lbsc"; + groups = "lbsc_ex_cs0"; + function = "lbsc"; }; }; scif2_pins: serial2 { - renesas,groups = "scif2_data_c"; - renesas,function = "scif2"; + groups = "scif2_data_c"; + function = "scif2"; }; scif4_pins: serial4 { - renesas,groups = "scif4_data"; - renesas,function = "scif4"; + groups = "scif4_data"; + function = "scif4"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd"; + function = "sdhi0"; }; hspi0_pins: hspi0 { - renesas,groups = "hspi0"; - renesas,function = "hspi0"; + groups = "hspi0"; + function = "hspi0"; }; }; -- GitLab From fec7b9f8952f396d88228677f44d52c7e20a6be8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:55:10 +0900 Subject: [PATCH 0205/9938] ARM: dts: koelsch: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the koelsch device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-koelsch.dts | 68 +++++++++++++-------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 0ad71b81d3a2..c6b43c85a0b1 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -324,89 +324,89 @@ pinctrl-names = "default"; i2c2_pins: i2c2 { - renesas,groups = "i2c2"; - renesas,function = "i2c2"; + groups = "i2c2"; + function = "i2c2"; }; du_pins: du { - renesas,groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; - renesas,function = "du"; + groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; + function = "du"; }; scif0_pins: serial0 { - renesas,groups = "scif0_data_d"; - renesas,function = "scif0"; + groups = "scif0_data_d"; + function = "scif0"; }; scif1_pins: serial1 { - renesas,groups = "scif1_data_d"; - renesas,function = "scif1"; + groups = "scif1_data_d"; + function = "scif1"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk"; - renesas,function = "scif_clk"; + groups = "scif_clk"; + function = "scif_clk"; }; ether_pins: ether { - renesas,groups = "eth_link", "eth_mdio", "eth_rmii"; - renesas,function = "eth"; + groups = "eth_link", "eth_mdio", "eth_rmii"; + function = "eth"; }; phy1_pins: phy1 { - renesas,groups = "intc_irq0"; - renesas,function = "intc"; + groups = "intc_irq0"; + function = "intc"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; }; sdhi1_pins: sd1 { - renesas,groups = "sdhi1_data4", "sdhi1_ctrl"; - renesas,function = "sdhi1"; + groups = "sdhi1_data4", "sdhi1_ctrl"; + function = "sdhi1"; }; sdhi2_pins: sd2 { - renesas,groups = "sdhi2_data4", "sdhi2_ctrl"; - renesas,function = "sdhi2"; + groups = "sdhi2_data4", "sdhi2_ctrl"; + function = "sdhi2"; }; qspi_pins: spi0 { - renesas,groups = "qspi_ctrl", "qspi_data4"; - renesas,function = "qspi"; + groups = "qspi_ctrl", "qspi_data4"; + function = "qspi"; }; msiof0_pins: spi1 { - renesas,groups = "msiof0_clk", "msiof0_sync", "msiof0_rx", + groups = "msiof0_clk", "msiof0_sync", "msiof0_rx", "msiof0_tx"; - renesas,function = "msiof0"; + function = "msiof0"; }; usb0_pins: usb0 { - renesas,groups = "usb0"; - renesas,function = "usb0"; + groups = "usb0"; + function = "usb0"; }; usb1_pins: usb1 { - renesas,groups = "usb1"; - renesas,function = "usb1"; + groups = "usb1"; + function = "usb1"; }; vin1_pins: vin1 { - renesas,groups = "vin1_data8", "vin1_clk"; - renesas,function = "vin1"; + groups = "vin1_data8", "vin1_clk"; + function = "vin1"; }; sound_pins: sound { - renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; - renesas,function = "ssi"; + groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; + function = "ssi"; }; sound_clk_pins: sound_clk { - renesas,groups = "audio_clk_a"; - renesas,function = "audio_clk"; + groups = "audio_clk_a"; + function = "audio_clk"; }; }; -- GitLab From b2abb296ad8cb576ea90e813842fa204bc21aebb Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:55:31 +0900 Subject: [PATCH 0206/9938] ARM: dts: porter: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the porter device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-porter.dts | 60 ++++++++++++++-------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts index 6c08314427d6..af3751ff519a 100644 --- a/arch/arm/boot/dts/r8a7791-porter.dts +++ b/arch/arm/boot/dts/r8a7791-porter.dts @@ -147,78 +147,78 @@ pinctrl-names = "default"; scif0_pins: serial0 { - renesas,groups = "scif0_data_d"; - renesas,function = "scif0"; + groups = "scif0_data_d"; + function = "scif0"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk"; - renesas,function = "scif_clk"; + groups = "scif_clk"; + function = "scif_clk"; }; ether_pins: ether { - renesas,groups = "eth_link", "eth_mdio", "eth_rmii"; - renesas,function = "eth"; + groups = "eth_link", "eth_mdio", "eth_rmii"; + function = "eth"; }; phy1_pins: phy1 { - renesas,groups = "intc_irq0"; - renesas,function = "intc"; + groups = "intc_irq0"; + function = "intc"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; }; sdhi2_pins: sd2 { - renesas,groups = "sdhi2_data4", "sdhi2_ctrl"; - renesas,function = "sdhi2"; + groups = "sdhi2_data4", "sdhi2_ctrl"; + function = "sdhi2"; }; qspi_pins: spi0 { - renesas,groups = "qspi_ctrl", "qspi_data4"; - renesas,function = "qspi"; + groups = "qspi_ctrl", "qspi_data4"; + function = "qspi"; }; i2c2_pins: i2c2 { - renesas,groups = "i2c2"; - renesas,function = "i2c2"; + groups = "i2c2"; + function = "i2c2"; }; usb0_pins: usb0 { - renesas,groups = "usb0"; - renesas,function = "usb0"; + groups = "usb0"; + function = "usb0"; }; usb1_pins: usb1 { - renesas,groups = "usb1"; - renesas,function = "usb1"; + groups = "usb1"; + function = "usb1"; }; vin0_pins: vin0 { - renesas,groups = "vin0_data8", "vin0_clk"; - renesas,function = "vin0"; + groups = "vin0_data8", "vin0_clk"; + function = "vin0"; }; can0_pins: can0 { - renesas,groups = "can0_data"; - renesas,function = "can0"; + groups = "can0_data"; + function = "can0"; }; du_pins: du { - renesas,groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; - renesas,function = "du"; + groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; + function = "du"; }; ssi_pins: sound { - renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; - renesas,function = "ssi"; + groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; + function = "ssi"; }; audio_clk_pins: audio_clk { - renesas,groups = "audio_clk_a"; - renesas,function = "audio_clk"; + groups = "audio_clk_a"; + function = "audio_clk"; }; }; -- GitLab From 2e207c1cd0f883a7d89b5241295c167e45f994b2 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:55:47 +0900 Subject: [PATCH 0207/9938] ARM: dts: gose: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the gose device tree to use the generic Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7793-gose.dts | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts index 87e89ec9dd47..c61df8b316ee 100644 --- a/arch/arm/boot/dts/r8a7793-gose.dts +++ b/arch/arm/boot/dts/r8a7793-gose.dts @@ -240,53 +240,53 @@ pinctrl-names = "default"; i2c2_pins: i2c2 { - renesas,groups = "i2c2"; - renesas,function = "i2c2"; + groups = "i2c2"; + function = "i2c2"; }; du_pins: du { - renesas,groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; - renesas,function = "du"; + groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; + function = "du"; }; scif0_pins: serial0 { - renesas,groups = "scif0_data_d"; - renesas,function = "scif0"; + groups = "scif0_data_d"; + function = "scif0"; }; scif1_pins: serial1 { - renesas,groups = "scif1_data_d"; - renesas,function = "scif1"; + groups = "scif1_data_d"; + function = "scif1"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk"; - renesas,function = "scif_clk"; + groups = "scif_clk"; + function = "scif_clk"; }; ether_pins: ether { - renesas,groups = "eth_link", "eth_mdio", "eth_rmii"; - renesas,function = "eth"; + groups = "eth_link", "eth_mdio", "eth_rmii"; + function = "eth"; }; phy1_pins: phy1 { - renesas,groups = "intc_irq0"; - renesas,function = "intc"; + groups = "intc_irq0"; + function = "intc"; }; qspi_pins: spi0 { - renesas,groups = "qspi_ctrl", "qspi_data4"; - renesas,function = "qspi"; + groups = "qspi_ctrl", "qspi_data4"; + function = "qspi"; }; sound_pins: sound { - renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; - renesas,function = "ssi"; + groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data"; + function = "ssi"; }; sound_clk_pins: sound_clk { - renesas,groups = "audio_clk_a"; - renesas,function = "audio_clk"; + groups = "audio_clk_a"; + function = "audio_clk"; }; }; -- GitLab From be7359dd9813e44bad827607048dd16298076bb8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:56:21 +0900 Subject: [PATCH 0208/9938] ARM: dts: alt: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the alt device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794-alt.dts | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/r8a7794-alt.dts index ca9bc4fff287..383ad791f1db 100644 --- a/arch/arm/boot/dts/r8a7794-alt.dts +++ b/arch/arm/boot/dts/r8a7794-alt.dts @@ -107,38 +107,38 @@ pinctrl-names = "default"; du_pins: du { - renesas,groups = "du1_rgb666", "du1_sync", "du1_disp", "du1_dotclkout0"; - renesas,function = "du"; + groups = "du1_rgb666", "du1_sync", "du1_disp", "du1_dotclkout0"; + function = "du"; }; scif2_pins: serial2 { - renesas,groups = "scif2_data"; - renesas,function = "scif2"; + groups = "scif2_data"; + function = "scif2"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk"; - renesas,function = "scif_clk"; + groups = "scif_clk"; + function = "scif_clk"; }; ether_pins: ether { - renesas,groups = "eth_link", "eth_mdio", "eth_rmii"; - renesas,function = "eth"; + groups = "eth_link", "eth_mdio", "eth_rmii"; + function = "eth"; }; phy1_pins: phy1 { - renesas,groups = "intc_irq8"; - renesas,function = "intc"; + groups = "intc_irq8"; + function = "intc"; }; i2c1_pins: i2c1 { - renesas,groups = "i2c1"; - renesas,function = "i2c1"; + groups = "i2c1"; + function = "i2c1"; }; vin0_pins: vin0 { - renesas,groups = "vin0_data8", "vin0_clk"; - renesas,function = "vin0"; + groups = "vin0_data8", "vin0_clk"; + function = "vin0"; }; }; @@ -148,8 +148,8 @@ &pfc { qspi_pins: spi0 { - renesas,groups = "qspi_ctrl", "qspi_data4"; - renesas,function = "qspi"; + groups = "qspi_ctrl", "qspi_data4"; + function = "qspi"; }; }; -- GitLab From 4386ed21e5c1944f9b666f405796499526c5e59b Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:57:28 +0900 Subject: [PATCH 0209/9938] ARM: dts: silk: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the silk device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794-silk.dts | 44 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts index 66f077a3ca41..56d98d5b2185 100644 --- a/arch/arm/boot/dts/r8a7794-silk.dts +++ b/arch/arm/boot/dts/r8a7794-silk.dts @@ -130,58 +130,58 @@ pinctrl-names = "default"; scif2_pins: serial2 { - renesas,groups = "scif2_data"; - renesas,function = "scif2"; + groups = "scif2_data"; + function = "scif2"; }; scif_clk_pins: scif_clk { - renesas,groups = "scif_clk"; - renesas,function = "scif_clk"; + groups = "scif_clk"; + function = "scif_clk"; }; ether_pins: ether { - renesas,groups = "eth_link", "eth_mdio", "eth_rmii"; - renesas,function = "eth"; + groups = "eth_link", "eth_mdio", "eth_rmii"; + function = "eth"; }; phy1_pins: phy1 { - renesas,groups = "intc_irq8"; - renesas,function = "intc"; + groups = "intc_irq8"; + function = "intc"; }; i2c1_pins: i2c1 { - renesas,groups = "i2c1"; - renesas,function = "i2c1"; + groups = "i2c1"; + function = "i2c1"; }; mmcif0_pins: mmcif0 { - renesas,groups = "mmc_data8", "mmc_ctrl"; - renesas,function = "mmc"; + groups = "mmc_data8", "mmc_ctrl"; + function = "mmc"; }; sdhi1_pins: sd1 { - renesas,groups = "sdhi1_data4", "sdhi1_ctrl"; - renesas,function = "sdhi1"; + groups = "sdhi1_data4", "sdhi1_ctrl"; + function = "sdhi1"; }; qspi_pins: spi0 { - renesas,groups = "qspi_ctrl", "qspi_data4"; - renesas,function = "qspi"; + groups = "qspi_ctrl", "qspi_data4"; + function = "qspi"; }; vin0_pins: vin0 { - renesas,groups = "vin0_data8", "vin0_clk"; - renesas,function = "vin0"; + groups = "vin0_data8", "vin0_clk"; + function = "vin0"; }; usb0_pins: usb0 { - renesas,groups = "usb0"; - renesas,function = "usb0"; + groups = "usb0"; + function = "usb0"; }; usb1_pins: usb1 { - renesas,groups = "usb1"; - renesas,function = "usb1"; + groups = "usb1"; + function = "usb1"; }; }; -- GitLab From ffff86d16ed25655643f75fdb83eb70f0a8496af Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:57:10 +0900 Subject: [PATCH 0210/9938] ARM: dts: kzm9g: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the kzm9g device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/sh73a0-kzm9g.dts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/sh73a0-kzm9g.dts index aa8bae3b8fcf..e40a2f23b6cd 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts @@ -329,41 +329,41 @@ &pfc { i2c3_pins: i2c3 { - renesas,groups = "i2c3_1"; - renesas,function = "i2c3"; + groups = "i2c3_1"; + function = "i2c3"; }; mmcif_pins: mmc { mux { - renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0"; - renesas,function = "mmc0"; + groups = "mmc0_data8_0", "mmc0_ctrl_0"; + function = "mmc0"; }; cfg { - renesas,groups = "mmc0_data8_0"; - renesas,pins = "PORT279"; + groups = "mmc0_data8_0"; + pins = "PORT279"; bias-pull-up; }; }; scifa4_pins: serial4 { - renesas,groups = "scifa4_data", "scifa4_ctrl"; - renesas,function = "scifa4"; + groups = "scifa4_data", "scifa4_ctrl"; + function = "scifa4"; }; sdhi0_pins: sd0 { - renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp"; - renesas,function = "sdhi0"; + groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp"; + function = "sdhi0"; }; sdhi2_pins: sd2 { - renesas,groups = "sdhi2_data4", "sdhi2_ctrl"; - renesas,function = "sdhi2"; + groups = "sdhi2_data4", "sdhi2_ctrl"; + function = "sdhi2"; }; fsia_pins: sounda { - renesas,groups = "fsia_mclk_in", "fsia_sclk_in", - "fsia_data_in", "fsia_data_out"; - renesas,function = "fsia"; + groups = "fsia_mclk_in", "fsia_sclk_in", + "fsia_data_in", "fsia_data_out"; + function = "fsia"; }; }; -- GitLab From 20ccdd90ab22808e582d81cdfac09e3b804e7b20 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 07:57:10 +0900 Subject: [PATCH 0211/9938] ARM: dts: kzm9d: use generic pinctrl properties Since 16ccaf5bb5a5 ("pinctrl: sh-pfc: Accept standard function, pins and groups properties") renesas pfc drivers accept generic "function", "pins" and "groups" properties. This patch updates the kzm9d device tree to use the generic properties. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/emev2-kzm9d.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts index 8c24975e8f9d..a35b851e1cd7 100644 --- a/arch/arm/boot/dts/emev2-kzm9d.dts +++ b/arch/arm/boot/dts/emev2-kzm9d.dts @@ -105,8 +105,8 @@ &pfc { uart1_pins: serial@e1030000 { - renesas,groups = "uart1_ctrl", "uart1_data"; - renesas,function = "uart1"; + groups = "uart1_ctrl", "uart1_data"; + function = "uart1"; }; }; -- GitLab From b19dd47b27d2bd719d304f27c0a4fcd3f51632dd Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 16 Mar 2016 09:21:13 +0900 Subject: [PATCH 0212/9938] ARM: dts: r8a7790: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary the nodes. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790.dtsi | 88 +++++++++++----------------------- 1 file changed, 28 insertions(+), 60 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 38b706399a6b..283698fc0fea 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1003,20 +1003,18 @@ ranges; /* External root clock */ - extal_clk: extal_clk { + extal_clk: extal { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overriden by the board. */ clock-frequency = <0>; - clock-output-names = "extal"; }; /* External PCIe clock - can be overridden by the board */ - pcie_bus_clk: pcie_bus_clk { + pcie_bus_clk: pcie_bus { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <100000000>; - clock-output-names = "pcie_bus"; status = "disabled"; }; @@ -1028,19 +1026,16 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_a"; }; audio_clk_b: audio_clk_b { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_b"; }; audio_clk_c: audio_clk_c { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_c"; }; /* External SCIF clock */ @@ -1053,11 +1048,10 @@ }; /* External USB clock - can be overridden by the board */ - usb_extal_clk: usb_extal_clk { + usb_extal_clk: usb_extal { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <48000000>; - clock-output-names = "usb_extal"; }; /* External CAN clock */ @@ -1066,7 +1060,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - clock-output-names = "can_clk"; status = "disabled"; }; @@ -1084,201 +1077,176 @@ }; /* Variable factor clocks */ - sd2_clk: sd2_clk@e6150078 { + sd2_clk: sd2@e6150078 { compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150078 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd2"; }; - sd3_clk: sd3_clk@e615026c { + sd3_clk: sd3@e615026c { compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615026c 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd3"; }; - mmc0_clk: mmc0_clk@e6150240 { + mmc0_clk: mmc0@e6150240 { compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150240 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "mmc0"; }; - mmc1_clk: mmc1_clk@e6150244 { + mmc1_clk: mmc1@e6150244 { compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150244 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "mmc1"; }; - ssp_clk: ssp_clk@e6150248 { + ssp_clk: ssp@e6150248 { compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150248 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "ssp"; }; - ssprs_clk: ssprs_clk@e615024c { + ssprs_clk: ssprs@e615024c { compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615024c 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "ssprs"; }; /* Fixed factor clocks */ - pll1_div2_clk: pll1_div2_clk { + pll1_div2_clk: pll1_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pll1_div2"; }; - z2_clk: z2_clk { + z2_clk: z2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "z2"; }; - zg_clk: zg_clk { + zg_clk: zg { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <3>; clock-mult = <1>; - clock-output-names = "zg"; }; - zx_clk: zx_clk { + zx_clk: zx { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <3>; clock-mult = <1>; - clock-output-names = "zx"; }; - zs_clk: zs_clk { + zs_clk: zs { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <6>; clock-mult = <1>; - clock-output-names = "zs"; }; - hp_clk: hp_clk { + hp_clk: hp { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "hp"; }; - i_clk: i_clk { + i_clk: i { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "i"; }; - b_clk: b_clk { + b_clk: b { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "b"; }; - p_clk: p_clk { + p_clk: p { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <24>; clock-mult = <1>; - clock-output-names = "p"; }; - cl_clk: cl_clk { + cl_clk: cl { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <48>; clock-mult = <1>; - clock-output-names = "cl"; }; - m2_clk: m2_clk { + m2_clk: m2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "m2"; }; - imp_clk: imp_clk { + imp_clk: imp { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <4>; clock-mult = <1>; - clock-output-names = "imp"; }; - rclk_clk: rclk_clk { + rclk_clk: rclk { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <(48 * 1024)>; clock-mult = <1>; - clock-output-names = "rclk"; }; - oscclk_clk: oscclk_clk { + oscclk_clk: oscclk { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL1>; #clock-cells = <0>; clock-div = <(12 * 1024)>; clock-mult = <1>; - clock-output-names = "oscclk"; }; - zb3_clk: zb3_clk { + zb3_clk: zb3 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL3>; #clock-cells = <0>; clock-div = <4>; clock-mult = <1>; - clock-output-names = "zb3"; }; - zb3d2_clk: zb3d2_clk { + zb3d2_clk: zb3d2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL3>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "zb3d2"; }; - ddr_clk: ddr_clk { + ddr_clk: ddr { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7790_CLK_PLL3>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "ddr"; }; - mp_clk: mp_clk { + mp_clk: mp { compatible = "fixed-factor-clock"; clocks = <&pll1_div2_clk>; #clock-cells = <0>; clock-div = <15>; clock-mult = <1>; - clock-output-names = "mp"; }; - cp_clk: cp_clk { + cp_clk: cp { compatible = "fixed-factor-clock"; clocks = <&extal_clk>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "cp"; }; /* Gate clocks */ -- GitLab From 21f189705929b9d27a44f0ae3d2ddd390c545670 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:10:44 +0900 Subject: [PATCH 0213/9938] ARM: dts: r7s72100: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r7s72100.dtsi | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi index 89e46ebef1bc..e8e2a5d71976 100644 --- a/arch/arm/boot/dts/r7s72100.dtsi +++ b/arch/arm/boot/dts/r7s72100.dtsi @@ -37,46 +37,41 @@ #size-cells = <1>; /* External clocks */ - extal_clk: extal_clk { + extal_clk: extal { #clock-cells = <0>; compatible = "fixed-clock"; /* If clk present, value must be set by board */ clock-frequency = <0>; - clock-output-names = "extal"; }; - usb_x1_clk: usb_x1_clk { + usb_x1_clk: usb_x1 { #clock-cells = <0>; compatible = "fixed-clock"; /* If clk present, value must be set by board */ clock-frequency = <0>; - clock-output-names = "usb_x1"; }; /* Fixed factor clocks */ - b_clk: b_clk { + b_clk: b { #clock-cells = <0>; compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R7S72100_CLK_PLL>; clock-mult = <1>; clock-div = <3>; - clock-output-names = "b"; }; - p1_clk: p1_clk { + p1_clk: p1 { #clock-cells = <0>; compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R7S72100_CLK_PLL>; clock-mult = <1>; clock-div = <6>; - clock-output-names = "p1"; }; - p0_clk: p0_clk { + p0_clk: p0 { #clock-cells = <0>; compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R7S72100_CLK_PLL>; clock-mult = <1>; clock-div = <12>; - clock-output-names = "p0"; }; /* Special CPG clocks */ -- GitLab From 2dca78980372f154a2181e6044db71be9da626e9 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:14:31 +0900 Subject: [PATCH 0214/9938] ARM: dts: r8a7740: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7740.dtsi | 57 ++++++++++++---------------------- 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi index 995fbda74b7a..39b2f88ad151 100644 --- a/arch/arm/boot/dts/r8a7740.dtsi +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -422,53 +422,45 @@ ranges; /* External root clock */ - extalr_clk: extalr_clk { + extalr_clk: extalr { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <32768>; - clock-output-names = "extalr"; }; - extal1_clk: extal1_clk { + extal1_clk: extal1 { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "extal1"; }; - extal2_clk: extal2_clk { + extal2_clk: extal2 { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "extal2"; }; - dv_clk: dv_clk { + dv_clk: dv { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <27000000>; - clock-output-names = "dv"; }; - fmsick_clk: fmsick_clk { + fmsick_clk: fmsick { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "fmsick"; }; - fmsock_clk: fmsock_clk { + fmsock_clk: fmsock { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "fmsock"; }; - fsiack_clk: fsiack_clk { + fsiack_clk: fsiack { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "fsiack"; }; - fsibck_clk: fsibck_clk { + fsibck_clk: fsibck { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "fsibck"; }; /* Special CPG clocks */ @@ -486,7 +478,7 @@ }; /* Variable factor clocks (DIV6) */ - vclk1_clk: vclk1_clk@e6150008 { + vclk1_clk: vclk1@e6150008 { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150008 4>; clocks = <&pllc1_div2_clk>, <0>, <&dv_clk>, @@ -494,9 +486,8 @@ <&extal1_div2_clk>, <&extalr_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "vclk1"; }; - vclk2_clk: vclk2_clk@e615000c { + vclk2_clk: vclk2@e615000c { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615000c 4>; clocks = <&pllc1_div2_clk>, <0>, <&dv_clk>, @@ -504,77 +495,67 @@ <&extal1_div2_clk>, <&extalr_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "vclk2"; }; - fmsi_clk: fmsi_clk@e6150010 { + fmsi_clk: fmsi@e6150010 { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150010 4>; clocks = <&pllc1_div2_clk>, <&fmsick_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "fmsi"; }; - fmso_clk: fmso_clk@e6150014 { + fmso_clk: fmso@e6150014 { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150014 4>; clocks = <&pllc1_div2_clk>, <&fmsock_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "fmso"; }; - fsia_clk: fsia_clk@e6150018 { + fsia_clk: fsia@e6150018 { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150018 4>; clocks = <&pllc1_div2_clk>, <&fsiack_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "fsia"; }; - sub_clk: sub_clk@e6150080 { + sub_clk: sub@e6150080 { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150080 4>; clocks = <&pllc1_div2_clk>, <&cpg_clocks R8A7740_CLK_USB24S>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "sub"; }; - spu_clk: spu_clk@e6150084 { + spu_clk: spu@e6150084 { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150084 4>; clocks = <&pllc1_div2_clk>, <&cpg_clocks R8A7740_CLK_USB24S>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "spu"; }; - vou_clk: vou_clk@e6150088 { + vou_clk: vou@e6150088 { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150088 4>; clocks = <&pllc1_div2_clk>, <&extal1_clk>, <&dv_clk>, <0>; #clock-cells = <0>; - clock-output-names = "vou"; }; - stpro_clk: stpro_clk@e615009c { + stpro_clk: stpro@e615009c { compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615009c 4>; clocks = <&cpg_clocks R8A7740_CLK_PLLC0>; #clock-cells = <0>; - clock-output-names = "stpro"; }; /* Fixed factor clocks */ - pllc1_div2_clk: pllc1_div2_clk { + pllc1_div2_clk: pllc1_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7740_CLK_PLLC1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pllc1_div2"; }; - extal1_div2_clk: extal1_div2_clk { + extal1_div2_clk: extal1_div2 { compatible = "fixed-factor-clock"; clocks = <&extal1_clk>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "extal1_div2"; }; /* Gate clocks */ -- GitLab From 452fc89994c2a81ade92096088b94ecbfef436a8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:15:11 +0900 Subject: [PATCH 0215/9938] ARM: dts: r8a7778: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7778.dtsi | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi index f83a348fc07a..99c10ebbaca2 100644 --- a/arch/arm/boot/dts/r8a7778.dtsi +++ b/arch/arm/boot/dts/r8a7778.dtsi @@ -443,11 +443,10 @@ ranges; /* External input clock */ - extal_clk: extal_clk { + extal_clk: extal { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "extal"; }; /* External SCIF clock */ @@ -474,59 +473,51 @@ audio_clk_a: audio_clk_a { compatible = "fixed-clock"; #clock-cells = <0>; - clock-output-names = "audio_clk_a"; }; audio_clk_b: audio_clk_b { compatible = "fixed-clock"; #clock-cells = <0>; - clock-output-names = "audio_clk_b"; }; audio_clk_c: audio_clk_c { compatible = "fixed-clock"; #clock-cells = <0>; - clock-output-names = "audio_clk_c"; }; /* Fixed ratio clocks */ - g_clk: g_clk { + g_clk: g { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7778_CLK_PLLA>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "g"; }; - i_clk: i_clk { + i_clk: i { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7778_CLK_PLLA>; #clock-cells = <0>; clock-div = <1>; clock-mult = <1>; - clock-output-names = "i"; }; - s3_clk: s3_clk { + s3_clk: s3 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7778_CLK_PLLA>; #clock-cells = <0>; clock-div = <4>; clock-mult = <1>; - clock-output-names = "s3"; }; - s4_clk: s4_clk { + s4_clk: s4 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7778_CLK_PLLA>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "s4"; }; - z_clk: z_clk { + z_clk: z { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7778_CLK_PLLB>; #clock-cells = <0>; clock-div = <1>; clock-mult = <1>; - clock-output-names = "z"; }; /* Gate clocks */ -- GitLab From 3f6dba702c57908c5f66601ced6ef9f131759611 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:15:34 +0900 Subject: [PATCH 0216/9938] ARM: dts: r8a7779: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7779.dtsi | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index a0cc08e6295b..60bc1e66bba9 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -445,12 +445,11 @@ ranges; /* External root clock */ - extal_clk: extal_clk { + extal_clk: extal { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overriden by the board. */ clock-frequency = <0>; - clock-output-names = "extal"; }; /* External SCIF clock */ @@ -474,37 +473,33 @@ }; /* Fixed factor clocks */ - i_clk: i_clk { + i_clk: i { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7779_CLK_PLLA>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "i"; }; - s3_clk: s3_clk { + s3_clk: s3 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7779_CLK_PLLA>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "s3"; }; - s4_clk: s4_clk { + s4_clk: s4 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7779_CLK_PLLA>; #clock-cells = <0>; clock-div = <16>; clock-mult = <1>; - clock-output-names = "s4"; }; - g_clk: g_clk { + g_clk: g { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7779_CLK_PLLA>; #clock-cells = <0>; clock-div = <24>; clock-mult = <1>; - clock-output-names = "g"; }; /* Gate clocks */ -- GitLab From f617604fe5d74b9c8d3333bad2e4959abe4594a4 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:16:23 +0900 Subject: [PATCH 0217/9938] ARM: dts: r8a7791: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791.dtsi | 79 +++++++++++----------------------- 1 file changed, 25 insertions(+), 54 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 6439f0569fe2..8010d935300f 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1048,12 +1048,11 @@ ranges; /* External root clock */ - extal_clk: extal_clk { + extal_clk: extal { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overriden by the board. */ clock-frequency = <0>; - clock-output-names = "extal"; }; /* @@ -1064,27 +1063,23 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_a"; }; audio_clk_b: audio_clk_b { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_b"; }; audio_clk_c: audio_clk_c { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_c"; }; /* External PCIe clock - can be overridden by the board */ - pcie_bus_clk: pcie_bus_clk { + pcie_bus_clk: pcie_bus { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <100000000>; - clock-output-names = "pcie_bus"; status = "disabled"; }; @@ -1098,11 +1093,10 @@ }; /* External USB clock - can be overridden by the board */ - usb_extal_clk: usb_extal_clk { + usb_extal_clk: usb_extal { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <48000000>; - clock-output-names = "usb_extal"; }; /* External CAN clock */ @@ -1111,7 +1105,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - clock-output-names = "can_clk"; status = "disabled"; }; @@ -1129,178 +1122,156 @@ }; /* Variable factor clocks */ - sd2_clk: sd2_clk@e6150078 { + sd2_clk: sd2@e6150078 { compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150078 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd2"; }; - sd3_clk: sd3_clk@e615026c { + sd3_clk: sd3@e615026c { compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615026c 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd3"; }; - mmc0_clk: mmc0_clk@e6150240 { + mmc0_clk: mmc0@e6150240 { compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150240 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "mmc0"; }; - ssp_clk: ssp_clk@e6150248 { + ssp_clk: ssp@e6150248 { compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150248 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "ssp"; }; - ssprs_clk: ssprs_clk@e615024c { + ssprs_clk: ssprs@e615024c { compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615024c 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "ssprs"; }; /* Fixed factor clocks */ - pll1_div2_clk: pll1_div2_clk { + pll1_div2_clk: pll1_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pll1_div2"; }; - zg_clk: zg_clk { + zg_clk: zg { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <3>; clock-mult = <1>; - clock-output-names = "zg"; }; - zx_clk: zx_clk { + zx_clk: zx { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <3>; clock-mult = <1>; - clock-output-names = "zx"; }; - zs_clk: zs_clk { + zs_clk: zs { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <6>; clock-mult = <1>; - clock-output-names = "zs"; }; - hp_clk: hp_clk { + hp_clk: hp { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "hp"; }; - i_clk: i_clk { + i_clk: i { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "i"; }; - b_clk: b_clk { + b_clk: b { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "b"; }; - p_clk: p_clk { + p_clk: p { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <24>; clock-mult = <1>; - clock-output-names = "p"; }; - cl_clk: cl_clk { + cl_clk: cl { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <48>; clock-mult = <1>; - clock-output-names = "cl"; }; - m2_clk: m2_clk { + m2_clk: m2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "m2"; }; - rclk_clk: rclk_clk { + rclk_clk: rclk { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <(48 * 1024)>; clock-mult = <1>; - clock-output-names = "rclk"; }; - oscclk_clk: oscclk_clk { + oscclk_clk: oscclk { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL1>; #clock-cells = <0>; clock-div = <(12 * 1024)>; clock-mult = <1>; - clock-output-names = "oscclk"; }; - zb3_clk: zb3_clk { + zb3_clk: zb3 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL3>; #clock-cells = <0>; clock-div = <4>; clock-mult = <1>; - clock-output-names = "zb3"; }; - zb3d2_clk: zb3d2_clk { + zb3d2_clk: zb3d2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL3>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "zb3d2"; }; - ddr_clk: ddr_clk { + ddr_clk: ddr { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7791_CLK_PLL3>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "ddr"; }; - mp_clk: mp_clk { + mp_clk: mp { compatible = "fixed-factor-clock"; clocks = <&pll1_div2_clk>; #clock-cells = <0>; clock-div = <15>; clock-mult = <1>; - clock-output-names = "mp"; }; - cp_clk: cp_clk { + cp_clk: cp { compatible = "fixed-factor-clock"; clocks = <&extal_clk>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "cp"; }; /* Gate clocks */ -- GitLab From 3b81c0ce13c53445b1e38fa1ff86025e5b8a9199 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:17:09 +0900 Subject: [PATCH 0218/9938] ARM: dts: r8a7793: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7793.dtsi | 45 +++++++++++----------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index b48215945241..95bbed95b0c1 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -812,12 +812,11 @@ ranges; /* External root clock */ - extal_clk: extal_clk { + extal_clk: extal { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - clock-output-names = "extal"; }; /* @@ -828,19 +827,16 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_a"; }; audio_clk_b: audio_clk_b { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_b"; }; audio_clk_c: audio_clk_c { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "audio_clk_c"; }; /* External SCIF clock */ @@ -866,111 +862,98 @@ }; /* Variable factor clocks */ - sd2_clk: sd2_clk@e6150078 { + sd2_clk: sd2@e6150078 { compatible = "renesas,r8a7793-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150078 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd2"; }; - sd3_clk: sd3_clk@e615026c { + sd3_clk: sd3@e615026c { compatible = "renesas,r8a7793-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615026c 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd3"; }; - mmc0_clk: mmc0_clk@e6150240 { + mmc0_clk: mmc0@e6150240 { compatible = "renesas,r8a7793-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150240 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "mmc0"; }; /* Fixed factor clocks */ - pll1_div2_clk: pll1_div2_clk { + pll1_div2_clk: pll1_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pll1_div2"; }; - zg_clk: zg_clk { + zg_clk: zg { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <5>; clock-mult = <1>; - clock-output-names = "zg"; }; - zx_clk: zx_clk { + zx_clk: zx { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <3>; clock-mult = <1>; - clock-output-names = "zx"; }; - zs_clk: zs_clk { + zs_clk: zs { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <6>; clock-mult = <1>; - clock-output-names = "zs"; }; - hp_clk: hp_clk { + hp_clk: hp { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "hp"; }; - p_clk: p_clk { + p_clk: p { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <24>; clock-mult = <1>; - clock-output-names = "p"; }; - m2_clk: m2_clk { + m2_clk: m2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "m2"; }; - rclk_clk: rclk_clk { + rclk_clk: rclk { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7793_CLK_PLL1>; #clock-cells = <0>; clock-div = <(48 * 1024)>; clock-mult = <1>; - clock-output-names = "rclk"; }; - mp_clk: mp_clk { + mp_clk: mp { compatible = "fixed-factor-clock"; clocks = <&pll1_div2_clk>; #clock-cells = <0>; clock-div = <15>; clock-mult = <1>; - clock-output-names = "mp"; }; - cp_clk: cp_clk { + cp_clk: cp { compatible = "fixed-factor-clock"; clocks = <&extal_clk>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "cp"; }; /* Gate clocks */ -- GitLab From 337f6bef6dd8dd9d2621980e2d34150d2014909c Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:17:57 +0900 Subject: [PATCH 0219/9938] ARM: dts: r8a7794: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 66 ++++++++++++---------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index eacb2b291361..7d7d18766540 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -836,12 +836,11 @@ ranges; /* External root clock */ - extal_clk: extal_clk { + extal_clk: extal { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overriden by the board. */ clock-frequency = <0>; - clock-output-names = "extal"; }; /* External SCIF clock */ @@ -865,173 +864,152 @@ #power-domain-cells = <0>; }; /* Variable factor clocks */ - sd2_clk: sd2_clk@e6150078 { + sd2_clk: sd2@e6150078 { compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150078 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd2"; }; - sd3_clk: sd3_clk@e615026c { + sd3_clk: sd3@e615026c { compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615026c 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "sd3"; }; - mmc0_clk: mmc0_clk@e6150240 { + mmc0_clk: mmc0@e6150240 { compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150240 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; - clock-output-names = "mmc0"; }; /* Fixed factor clocks */ - pll1_div2_clk: pll1_div2_clk { + pll1_div2_clk: pll1_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pll1_div2"; }; - zg_clk: zg_clk { + zg_clk: zg { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <6>; clock-mult = <1>; - clock-output-names = "zg"; }; - zx_clk: zx_clk { + zx_clk: zx { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <3>; clock-mult = <1>; - clock-output-names = "zx"; }; - zs_clk: zs_clk { + zs_clk: zs { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <6>; clock-mult = <1>; - clock-output-names = "zs"; }; - hp_clk: hp_clk { + hp_clk: hp { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "hp"; }; - i_clk: i_clk { + i_clk: i { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "i"; }; - b_clk: b_clk { + b_clk: b { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <12>; clock-mult = <1>; - clock-output-names = "b"; }; - p_clk: p_clk { + p_clk: p { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <24>; clock-mult = <1>; - clock-output-names = "p"; }; - cl_clk: cl_clk { + cl_clk: cl { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <48>; clock-mult = <1>; - clock-output-names = "cl"; }; - m2_clk: m2_clk { + m2_clk: m2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "m2"; }; - rclk_clk: rclk_clk { + rclk_clk: rclk { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <(48 * 1024)>; clock-mult = <1>; - clock-output-names = "rclk"; }; - oscclk_clk: oscclk_clk { + oscclk_clk: oscclk { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <(12 * 1024)>; clock-mult = <1>; - clock-output-names = "oscclk"; }; - zb3_clk: zb3_clk { + zb3_clk: zb3 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL3>; #clock-cells = <0>; clock-div = <4>; clock-mult = <1>; - clock-output-names = "zb3"; }; - zb3d2_clk: zb3d2_clk { + zb3d2_clk: zb3d2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL3>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "zb3d2"; }; - ddr_clk: ddr_clk { + ddr_clk: ddr { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL3>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; - clock-output-names = "ddr"; }; - mp_clk: mp_clk { + mp_clk: mp { compatible = "fixed-factor-clock"; clocks = <&pll1_div2_clk>; #clock-cells = <0>; clock-div = <15>; clock-mult = <1>; - clock-output-names = "mp"; }; - cp_clk: cp_clk { + cp_clk: cp { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A7794_CLK_PLL1>; #clock-cells = <0>; clock-div = <48>; clock-mult = <1>; - clock-output-names = "cp"; }; - acp_clk: acp_clk { + acp_clk: acp { compatible = "fixed-factor-clock"; clocks = <&extal_clk>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "acp"; }; /* Gate clocks */ -- GitLab From 45e4f51311f3d4551326bfa43547f86b00af0a94 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:17:57 +0900 Subject: [PATCH 0220/9938] ARM: dts: gose: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7793-gose.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts index c61df8b316ee..3cd1c804621f 100644 --- a/arch/arm/boot/dts/r8a7793-gose.dts +++ b/arch/arm/boot/dts/r8a7793-gose.dts @@ -158,11 +158,10 @@ }; }; - audio_clock: clock { + audio_clock: audio_clock { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <11289600>; - clock-output-names = "audio_clock"; }; rsnd_ak4643: sound { -- GitLab From 62c7e9da598611827f09984386fa1438ccc46f87 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:17:57 +0900 Subject: [PATCH 0221/9938] ARM: dts: koelsch: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-koelsch.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index c6b43c85a0b1..1adf8770db7e 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -242,11 +242,10 @@ 1800000 0>; }; - audio_clock: clock { + audio_clock: audio_clock { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <11289600>; - clock-output-names = "audio_clock"; }; rsnd_ak4643: sound { -- GitLab From 203f0ef865303412a9d03a88a2f845db682ac628 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:17:57 +0900 Subject: [PATCH 0222/9938] ARM: dts: porter: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-porter.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts index af3751ff519a..9554d13362f6 100644 --- a/arch/arm/boot/dts/r8a7791-porter.dts +++ b/arch/arm/boot/dts/r8a7791-porter.dts @@ -113,11 +113,10 @@ clock-frequency = <74250000>; }; - x14_clk: x14-clock { + x14_clk: audio_clock { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <11289600>; - clock-output-names = "audio_clock"; }; sound { -- GitLab From a5bad2c7c9ee0f5e188b97baeb383753fad53c86 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 18 Mar 2016 08:17:57 +0900 Subject: [PATCH 0223/9938] ARM: dts: lager: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790-lager.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index a5828721ab7c..823a119cb1b4 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -176,11 +176,10 @@ 1800000 0>; }; - audio_clock: clock { + audio_clock: audio_clock { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <11289600>; - clock-output-names = "audio_clock"; }; rsnd_ak4643: sound { -- GitLab From 57c75d1ed6890b8c57fce5d0c557a6b486c4d898 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 23 Mar 2016 10:06:42 +0900 Subject: [PATCH 0224/9938] ARM: dts: r8a73a4: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. The clock-output-names property is left in place for the zb_clk which is thus treated as a special case as the MSTP clock driver (clk-mstp.c) explicitly looks for a clock with node name zb_clk for the r8a73a4 and sh73a0 SoCs. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a73a4.dtsi | 75 ++++++++++++---------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi index 6583a1dfca1f..6954912a3753 100644 --- a/arch/arm/boot/dts/r8a73a4.dtsi +++ b/arch/arm/boot/dts/r8a73a4.dtsi @@ -486,37 +486,32 @@ ranges; /* External root clocks */ - extalr_clk: extalr_clk { + extalr_clk: extalr { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <32768>; - clock-output-names = "extalr"; }; - extal1_clk: extal1_clk { + extal1_clk: extal1 { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <25000000>; - clock-output-names = "extal1"; }; - extal2_clk: extal2_clk { + extal2_clk: extal2 { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <48000000>; - clock-output-names = "extal2"; }; - fsiack_clk: fsiack_clk { + fsiack_clk: fsiack { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - clock-output-names = "fsiack"; }; - fsibck_clk: fsibck_clk { + fsibck_clk: fsibck { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - clock-output-names = "fsibck"; }; /* Special CPG clocks */ @@ -540,171 +535,151 @@ #clock-cells = <0>; clock-output-names = "zb"; }; - sdhi0_clk: sdhi0_clk@e6150074 { + sdhi0_clk: sdhi0ck@e6150074 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150074 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "sdhi0ck"; }; - sdhi1_clk: sdhi1_clk@e6150078 { + sdhi1_clk: sdhi1ck@e6150078 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150078 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "sdhi1ck"; }; - sdhi2_clk: sdhi2_clk@e615007c { + sdhi2_clk: sdhi2ck@e615007c { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615007c 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "sdhi2ck"; }; - mmc0_clk: mmc0_clk@e6150240 { + mmc0_clk: mmc0@e6150240 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150240 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "mmc0"; }; - mmc1_clk: mmc1_clk@e6150244 { + mmc1_clk: mmc1@e6150244 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150244 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "mmc1"; }; - vclk1_clk: vclk1_clk@e6150008 { + vclk1_clk: vclk1@e6150008 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150008 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>, <&main_div2_clk>, <&extalr_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "vclk1"; }; - vclk2_clk: vclk2_clk@e615000c { + vclk2_clk: vclk2@e615000c { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615000c 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>, <&main_div2_clk>, <&extalr_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "vclk2"; }; - vclk3_clk: vclk3_clk@e615001c { + vclk3_clk: vclk3@e615001c { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615001c 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>, <&main_div2_clk>, <&extalr_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "vclk3"; }; - vclk4_clk: vclk4_clk@e6150014 { + vclk4_clk: vclk4@e6150014 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150014 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>, <&main_div2_clk>, <&extalr_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "vclk4"; }; - vclk5_clk: vclk5_clk@e6150034 { + vclk5_clk: vclk5@e6150034 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150034 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>, <&extal2_clk>, <&main_div2_clk>, <&extalr_clk>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "vclk5"; }; - fsia_clk: fsia_clk@e6150018 { + fsia_clk: fsia@e6150018 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150018 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <&fsiack_clk>, <0>; #clock-cells = <0>; - clock-output-names = "fsia"; }; - fsib_clk: fsib_clk@e6150090 { + fsib_clk: fsib@e6150090 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150090 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <&fsibck_clk>, <0>; #clock-cells = <0>; - clock-output-names = "fsib"; }; - mp_clk: mp_clk@e6150080 { + mp_clk: mp@e6150080 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150080 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <&extal2_clk>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "mp"; }; - m4_clk: m4_clk@e6150098 { + m4_clk: m4@e6150098 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150098 0 4>; clocks = <&cpg_clocks R8A73A4_CLK_PLL2S>; #clock-cells = <0>; - clock-output-names = "m4"; }; - hsi_clk: hsi_clk@e615026c { + hsi_clk: hsi@e615026c { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe615026c 0 4>; clocks = <&cpg_clocks R8A73A4_CLK_PLL2H>, <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>; #clock-cells = <0>; - clock-output-names = "hsi"; }; - spuv_clk: spuv_clk@e6150094 { + spuv_clk: spuv@e6150094 { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0 0xe6150094 0 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <&extal2_clk>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "spuv"; }; /* Fixed factor clocks */ - main_div2_clk: main_div2_clk { + main_div2_clk: main_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A73A4_CLK_MAIN>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "main_div2"; }; - pll0_div2_clk: pll0_div2_clk { + pll0_div2_clk: pll0_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A73A4_CLK_PLL0>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pll0_div2"; }; - pll1_div2_clk: pll1_div2_clk { + pll1_div2_clk: pll1_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks R8A73A4_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pll1_div2"; }; - extal1_div2_clk: extal1_div2_clk { + extal1_div2_clk: extal1_div2 { compatible = "fixed-factor-clock"; clocks = <&extal1_clk>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "extal1_div2"; }; /* Gate clocks */ -- GitLab From 000025cfbb9e8bafd0a1fa84d8d83526d24bde42 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 23 Mar 2016 10:06:43 +0900 Subject: [PATCH 0225/9938] ARM: dts: sh73a0: Remove unnecessary clock-output-names properties * Fixed rate and fixed factor clocks do not require an clock-output-names property. * Since 07705583e920fef6 ("clk: shmobile: div6: Make clock-output-names optional") Renesas div6 clocks do not require a clock-output-names property. In the above cases there is only one clock output and its name is taken from that of the clock node. Accordingly, remove the unnecessary clock-output-names properties and as necessary update the node names. The clock-output-names property is left in place for the zb_clk which is thus treated as a special case as the MSTP clock driver (clk-mstp.c) explicitly looks for a clock with node name zb_clk for the r8a73a4 and sh73a0 SoCs. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/sh73a0.dtsi | 87 ++++++++++++----------------------- 1 file changed, 29 insertions(+), 58 deletions(-) diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index bf825ca4f6f7..639ea2d76970 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -602,39 +602,33 @@ ranges; /* External root clocks */ - extalr_clk: extalr_clk { + extalr_clk: extalr { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <32768>; - clock-output-names = "extalr"; }; - extal1_clk: extal1_clk { + extal1_clk: extal1 { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <26000000>; - clock-output-names = "extal1"; }; - extal2_clk: extal2_clk { + extal2_clk: extal2 { compatible = "fixed-clock"; #clock-cells = <0>; - clock-output-names = "extal2"; }; - extcki_clk: extcki_clk { + extcki_clk: extcki { compatible = "fixed-clock"; #clock-cells = <0>; - clock-output-names = "extcki"; }; - fsiack_clk: fsiack_clk { + fsiack_clk: fsiack { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "fsiack"; }; - fsibck_clk: fsibck_clk { + fsibck_clk: fsibck { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - clock-output-names = "fsibck"; }; /* Special CPG clocks */ @@ -650,7 +644,7 @@ }; /* Variable factor clocks (DIV6) */ - vclk1_clk: vclk1_clk@e6150008 { + vclk1_clk: vclk1@e6150008 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150008 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, @@ -658,9 +652,8 @@ <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>, <0>; #clock-cells = <0>; - clock-output-names = "vclk1"; }; - vclk2_clk: vclk2_clk@e615000c { + vclk2_clk: vclk2@e615000c { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615000c 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, @@ -668,9 +661,8 @@ <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>, <0>; #clock-cells = <0>; - clock-output-names = "vclk2"; }; - vclk3_clk: vclk3_clk@e615001c { + vclk3_clk: vclk3@e615001c { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615001c 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, @@ -678,7 +670,6 @@ <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>, <0>; #clock-cells = <0>; - clock-output-names = "vclk3"; }; zb_clk: zb_clk@e6150010 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; @@ -688,168 +679,148 @@ #clock-cells = <0>; clock-output-names = "zb"; }; - flctl_clk: flctl_clk@e6150014 { + flctl_clk: flctlck@e6150014 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150014 4>; clocks = <&pll1_div2_clk>, <0>, <&cpg_clocks SH73A0_CLK_PLL2>, <0>; #clock-cells = <0>; - clock-output-names = "flctlck"; }; - sdhi0_clk: sdhi0_clk@e6150074 { + sdhi0_clk: sdhi0ck@e6150074 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150074 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&pll1_div13_clk>, <0>; #clock-cells = <0>; - clock-output-names = "sdhi0ck"; }; - sdhi1_clk: sdhi1_clk@e6150078 { + sdhi1_clk: sdhi1ck@e6150078 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150078 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&pll1_div13_clk>, <0>; #clock-cells = <0>; - clock-output-names = "sdhi1ck"; }; - sdhi2_clk: sdhi2_clk@e615007c { + sdhi2_clk: sdhi2ck@e615007c { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615007c 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&pll1_div13_clk>, <0>; #clock-cells = <0>; - clock-output-names = "sdhi2ck"; }; - fsia_clk: fsia_clk@e6150018 { + fsia_clk: fsia@e6150018 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150018 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&fsiack_clk>, <&fsiack_clk>; #clock-cells = <0>; - clock-output-names = "fsia"; }; - fsib_clk: fsib_clk@e6150090 { + fsib_clk: fsib@e6150090 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150090 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&fsibck_clk>, <&fsibck_clk>; #clock-cells = <0>; - clock-output-names = "fsib"; }; - sub_clk: sub_clk@e6150080 { + sub_clk: sub@e6150080 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150080 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&extal2_clk>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "sub"; }; - spua_clk: spua_clk@e6150084 { + spua_clk: spua@e6150084 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150084 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&extal2_clk>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "spua"; }; - spuv_clk: spuv_clk@e6150094 { + spuv_clk: spuv@e6150094 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150094 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&extal2_clk>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "spuv"; }; - msu_clk: msu_clk@e6150088 { + msu_clk: msu@e6150088 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150088 4>; clocks = <&pll1_div2_clk>, <0>, <&cpg_clocks SH73A0_CLK_PLL2>, <0>; #clock-cells = <0>; - clock-output-names = "msu"; }; - hsi_clk: hsi_clk@e615008c { + hsi_clk: hsi@e615008c { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615008c 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&pll1_div7_clk>, <0>; #clock-cells = <0>; - clock-output-names = "hsi"; }; - mfg1_clk: mfg1_clk@e6150098 { + mfg1_clk: mfg1@e6150098 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150098 4>; clocks = <&pll1_div2_clk>, <0>, <&cpg_clocks SH73A0_CLK_PLL2>, <0>; #clock-cells = <0>; - clock-output-names = "mfg1"; }; - mfg2_clk: mfg2_clk@e615009c { + mfg2_clk: mfg2@e615009c { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615009c 4>; clocks = <&pll1_div2_clk>, <0>, <&cpg_clocks SH73A0_CLK_PLL2>, <0>; #clock-cells = <0>; - clock-output-names = "mfg2"; }; - dsit_clk: dsit_clk@e6150060 { + dsit_clk: dsit@e6150060 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150060 4>; clocks = <&pll1_div2_clk>, <0>, <&cpg_clocks SH73A0_CLK_PLL2>, <0>; #clock-cells = <0>; - clock-output-names = "dsit"; }; - dsi0p_clk: dsi0p_clk@e6150064 { + dsi0p_clk: dsi0pck@e6150064 { compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe6150064 4>; clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>, <&cpg_clocks SH73A0_CLK_MAIN>, <&extal2_clk>, <&extcki_clk>, <0>, <0>, <0>; #clock-cells = <0>; - clock-output-names = "dsi0pck"; }; /* Fixed factor clocks */ - main_div2_clk: main_div2_clk { + main_div2_clk: main_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks SH73A0_CLK_MAIN>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "main_div2"; }; - pll1_div2_clk: pll1_div2_clk { + pll1_div2_clk: pll1_div2 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks SH73A0_CLK_PLL1>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; - clock-output-names = "pll1_div2"; }; - pll1_div7_clk: pll1_div7_clk { + pll1_div7_clk: pll1_div7 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks SH73A0_CLK_PLL1>; #clock-cells = <0>; clock-div = <7>; clock-mult = <1>; - clock-output-names = "pll1_div7"; }; - pll1_div13_clk: pll1_div13_clk { + pll1_div13_clk: pll1_div13 { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks SH73A0_CLK_PLL1>; #clock-cells = <0>; clock-div = <13>; clock-mult = <1>; - clock-output-names = "pll1_div13"; }; - twd_clk: twd_clk { + twd_clk: twd { compatible = "fixed-factor-clock"; clocks = <&cpg_clocks SH73A0_CLK_Z>; #clock-cells = <0>; clock-div = <4>; clock-mult = <1>; - clock-output-names = "twd"; }; /* Gate clocks */ -- GitLab From 651435d68253b0a5059175e2f113528080e5928e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 24 Feb 2016 11:01:31 +0100 Subject: [PATCH 0226/9938] ARM: multi_v7_defconfig: enable I2C demultiplexer and slave eeprom The Renesas Lager board shall be a reference platform for the runtime I2C IP core switcher and for I2C slave support. Enable the needed drivers for this. Signed-off-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/configs/multi_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 28234906a064..434f86b110bb 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -322,6 +322,7 @@ CONFIG_I2C_MUX=y CONFIG_I2C_ARB_GPIO_CHALLENGE=m CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_MUX_PINCTRL=y +CONFIG_I2C_DEMUX_PINCTRL=y CONFIG_I2C_AT91=m CONFIG_I2C_BCM2835=y CONFIG_I2C_CADENCE=y @@ -345,6 +346,7 @@ CONFIG_I2C_UNIPHIER_F=y CONFIG_I2C_XILINX=y CONFIG_I2C_RCAR=y CONFIG_I2C_CROS_EC_TUNNEL=m +CONFIG_I2C_SLAVE_EEPROM=y CONFIG_SPI=y CONFIG_SPI_ATMEL=m CONFIG_SPI_BCM2835=y -- GitLab From 41feae79f2621d9fcea1437d4a2f29dc731fdbb0 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 3 Mar 2016 10:39:58 +0900 Subject: [PATCH 0227/9938] bus: simple-pm-bus: Use ARCH_RENESAS Make use of ARCH_RENESAS in place of ARCH_SHMOBILE. This is part of an ongoing process to migrate from ARCH_SHMOBILE to ARCH_RENESAS the motivation for which being that RENESAS seems to be a more appropriate name than SHMOBILE for the majority of Renesas ARM based SoCs. Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/bus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index d4a3a3133da5..67cebd3d7f2d 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -110,7 +110,7 @@ config OMAP_OCP2SCP config SIMPLE_PM_BUS bool "Simple Power-Managed Bus Driver" depends on OF && PM - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST help Driver for transparent busses that don't need a real driver, but where the bus controller is part of a PM domain, or under the control -- GitLab From 352486b164ad41f2536f77d568ada7d729d080c2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 15 Feb 2016 13:57:48 +0100 Subject: [PATCH 0228/9938] ARM: shmobile: defconfig: enable I2C demultiplexer and slave eeprom The Lager board shall be the reference platform for the runtime I2C IP core switcher and for I2C slave support. Enable the needed drivers for this. Signed-off-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index b7b714c3958c..e06acb9b38ce 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -99,11 +99,14 @@ CONFIG_SERIAL_SH_SCI=y CONFIG_SERIAL_SH_SCI_NR_UARTS=20 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +CONFIG_I2C_DEMUX_PINCTRL=y CONFIG_I2C_EMEV2=y CONFIG_I2C_GPIO=y CONFIG_I2C_RIIC=y CONFIG_I2C_SH_MOBILE=y CONFIG_I2C_RCAR=y +CONFIG_I2C_SLAVE_EEPROM=y CONFIG_SPI=y CONFIG_SPI_RSPI=y CONFIG_SPI_SH_MSIOF=y -- GitLab From 2c7661ff419580f5c06ea409e31407e0ff52cb95 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:18:14 -0400 Subject: [PATCH 0229/9938] [apparmor] constify struct path * in a bunch of helpers Signed-off-by: Al Viro --- security/apparmor/file.c | 2 +- security/apparmor/include/file.h | 2 +- security/apparmor/include/path.h | 2 +- security/apparmor/lsm.c | 2 +- security/apparmor/path.c | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 913f377a038a..4dfc5d0d8413 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -275,7 +275,7 @@ static inline bool is_deleted(struct dentry *dentry) * * Returns: %0 else error if access denied or other error */ -int aa_path_perm(int op, struct aa_profile *profile, struct path *path, +int aa_path_perm(int op, struct aa_profile *profile, const struct path *path, int flags, u32 request, struct path_cond *cond) { char *buffer = NULL; diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index 2c922b86bd44..afc5b294e0d5 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h @@ -171,7 +171,7 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, const char *name, struct path_cond *cond, struct file_perms *perms); -int aa_path_perm(int op, struct aa_profile *profile, struct path *path, +int aa_path_perm(int op, struct aa_profile *profile, const struct path *path, int flags, u32 request, struct path_cond *cond); int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h index 286ac75dc88b..73560f258784 100644 --- a/security/apparmor/include/path.h +++ b/security/apparmor/include/path.h @@ -26,7 +26,7 @@ enum path_flags { PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ }; -int aa_path_name(struct path *path, int flags, char **buffer, +int aa_path_name(const struct path *path, int flags, char **buffer, const char **name, const char **info); #endif /* __AA_PATH_H */ diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index dec607c17b64..9713037e5257 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -149,7 +149,7 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, * * Returns: %0 else error code if error or permission denied */ -static int common_perm(int op, struct path *path, u32 mask, +static int common_perm(int op, const struct path *path, u32 mask, struct path_cond *cond) { struct aa_profile *profile; diff --git a/security/apparmor/path.c b/security/apparmor/path.c index 71e0e3a15b9d..edddc026406b 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c @@ -53,7 +53,7 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen) * When no error the path name is returned in @name which points to * to a position in @buf */ -static int d_namespace_path(struct path *path, char *buf, int buflen, +static int d_namespace_path(const struct path *path, char *buf, int buflen, char **name, int flags) { char *res; @@ -158,7 +158,7 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, * * Returns: %0 else error on failure */ -static int get_name_to_buffer(struct path *path, int flags, char *buffer, +static int get_name_to_buffer(const struct path *path, int flags, char *buffer, int size, char **name, const char **info) { int adjust = (flags & PATH_IS_DIR) ? 1 : 0; @@ -204,8 +204,8 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer, * * Returns: %0 else error code if could retrieve name */ -int aa_path_name(struct path *path, int flags, char **buffer, const char **name, - const char **info) +int aa_path_name(const struct path *path, int flags, char **buffer, + const char **name, const char **info) { char *buf, *str = NULL; int size = 256; -- GitLab From 87f15d4add758fb7fc76655721af94be57a4c17d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Mar 2016 14:43:24 -0400 Subject: [PATCH 0230/9938] mtd: switch open_mtd_by_chdev() to use of vfs_stat() Signed-off-by: Al Viro --- drivers/mtd/ubi/build.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 22fd19c0c5d3..a7d1febf667a 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -1142,22 +1142,19 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) */ static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev) { - int err, major, minor, mode; - struct path path; + struct kstat stat; + int err, minor; /* Probably this is an MTD character device node path */ - err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path); + err = vfs_stat(mtd_dev, &stat); if (err) return ERR_PTR(err); /* MTD device number is defined by the major / minor numbers */ - major = imajor(d_backing_inode(path.dentry)); - minor = iminor(d_backing_inode(path.dentry)); - mode = d_backing_inode(path.dentry)->i_mode; - path_put(&path); - if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode)) + if (MAJOR(stat.rdev) != MTD_CHAR_MAJOR || !S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); + minor = MINOR(stat.rdev); if (minor & 1) /* * Just do not think the "/dev/mtdrX" devices support is need, -- GitLab From 322ea0bbf3003df17b6253f76e572c37d79a6810 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Mar 2016 14:47:18 -0400 Subject: [PATCH 0231/9938] mtd: switch ubi_open_volume_path() to vfs_stat() Signed-off-by: Al Viro --- drivers/mtd/ubi/kapi.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index e844887732fb..437757c89b9e 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -301,27 +301,24 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm); */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { - int error, ubi_num, vol_id, mod; - struct inode *inode; - struct path path; + int error, ubi_num, vol_id; + struct kstat stat; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); - error = kern_path(pathname, LOOKUP_FOLLOW, &path); + error = vfs_stat(pathname, &stat); if (error) return ERR_PTR(error); - inode = d_backing_inode(path.dentry); - mod = inode->i_mode; - ubi_num = ubi_major2num(imajor(inode)); - vol_id = iminor(inode) - 1; - path_put(&path); - - if (!S_ISCHR(mod)) + if (!S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); + + ubi_num = ubi_major2num(MAJOR(stat.rdev)); + vol_id = MINOR(stat.rdev) - 1; + if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); -- GitLab From 798434bda36e357af9ccaf68a7ba1129658c8332 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Mar 2016 20:38:43 -0400 Subject: [PATCH 0232/9938] __d_alloc(): treat NULL name as QSTR("/", 1) Signed-off-by: Al Viro --- fs/dcache.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 32ceae3e6112..3cb98dfd9f96 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1558,7 +1558,11 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) * be overwriting an internal NUL character */ dentry->d_iname[DNAME_INLINE_LEN-1] = 0; - if (name->len > DNAME_INLINE_LEN-1) { + if (unlikely(!name)) { + static const struct qstr anon = QSTR_INIT("/", 1); + name = &anon; + dname = dentry->d_iname; + } else if (name->len > DNAME_INLINE_LEN-1) { size_t size = offsetof(struct external_name, name[1]); struct external_name *p = kmalloc(size + name->len, GFP_KERNEL_ACCOUNT); @@ -1812,9 +1816,7 @@ struct dentry *d_make_root(struct inode *root_inode) struct dentry *res = NULL; if (root_inode) { - static const struct qstr name = QSTR_INIT("/", 1); - - res = __d_alloc(root_inode->i_sb, &name); + res = __d_alloc(root_inode->i_sb, NULL); if (res) d_instantiate(res, root_inode); else @@ -1855,7 +1857,6 @@ EXPORT_SYMBOL(d_find_any_alias); static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected) { - static const struct qstr anonstring = QSTR_INIT("/", 1); struct dentry *tmp; struct dentry *res; unsigned add_flags; @@ -1869,7 +1870,7 @@ static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected) if (res) goto out_iput; - tmp = __d_alloc(inode->i_sb, &anonstring); + tmp = __d_alloc(inode->i_sb, NULL); if (!tmp) { res = ERR_PTR(-ENOMEM); goto out_iput; -- GitLab From 0c93b7d85d40b690f04786ea0f18798b73182e4f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 12:06:51 -0400 Subject: [PATCH 0233/9938] bpf: reject invalid names right in ->lookup() ... and other methods won't see them at all Signed-off-by: Al Viro --- kernel/bpf/inode.c | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index f2ece3c174a5..35d21c189bb0 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -119,18 +119,10 @@ static int bpf_inode_type(const struct inode *inode, enum bpf_type *type) return 0; } -static bool bpf_dname_reserved(const struct dentry *dentry) -{ - return strchr(dentry->d_name.name, '.'); -} - static int bpf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct inode *inode; - if (bpf_dname_reserved(dentry)) - return -EPERM; - inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFDIR); if (IS_ERR(inode)) return PTR_ERR(inode); @@ -152,9 +144,6 @@ static int bpf_mkobj_ops(struct inode *dir, struct dentry *dentry, { struct inode *inode; - if (bpf_dname_reserved(dentry)) - return -EPERM; - inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFREG); if (IS_ERR(inode)) return PTR_ERR(inode); @@ -187,31 +176,21 @@ static int bpf_mkobj(struct inode *dir, struct dentry *dentry, umode_t mode, } } -static int bpf_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +static struct dentry * +bpf_lookup(struct inode *dir, struct dentry *dentry, unsigned flags) { - if (bpf_dname_reserved(new_dentry)) - return -EPERM; - - return simple_link(old_dentry, dir, new_dentry); -} - -static int bpf_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - if (bpf_dname_reserved(new_dentry)) - return -EPERM; - - return simple_rename(old_dir, old_dentry, new_dir, new_dentry); + if (strchr(dentry->d_name.name, '.')) + return ERR_PTR(-EPERM); + return simple_lookup(dir, dentry, flags); } static const struct inode_operations bpf_dir_iops = { - .lookup = simple_lookup, + .lookup = bpf_lookup, .mknod = bpf_mkobj, .mkdir = bpf_mkdir, .rmdir = simple_rmdir, - .rename = bpf_rename, - .link = bpf_link, + .rename = simple_rename, + .link = simple_link, .unlink = simple_unlink, }; -- GitLab From 81f4c50607b423a59f8a1b03e1e8fc409a1dcd22 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:22:01 -0400 Subject: [PATCH 0234/9938] constify security_path_truncate() Signed-off-by: Al Viro --- include/linux/lsm_hooks.h | 2 +- include/linux/security.h | 4 ++-- security/apparmor/lsm.c | 2 +- security/security.c | 2 +- security/tomoyo/tomoyo.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index cdee11cbcdf1..77c3bfdacf16 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1366,7 +1366,7 @@ union security_list_options { int (*path_rmdir)(struct path *dir, struct dentry *dentry); int (*path_mknod)(struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev); - int (*path_truncate)(struct path *path); + int (*path_truncate)(const struct path *path); int (*path_symlink)(struct path *dir, struct dentry *dentry, const char *old_name); int (*path_link)(struct dentry *old_dentry, struct path *new_dir, diff --git a/include/linux/security.h b/include/linux/security.h index 157f0cb1e4d2..be37ccab2286 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1447,7 +1447,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode); int security_path_rmdir(struct path *dir, struct dentry *dentry); int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev); -int security_path_truncate(struct path *path); +int security_path_truncate(const struct path *path); int security_path_symlink(struct path *dir, struct dentry *dentry, const char *old_name); int security_path_link(struct dentry *old_dentry, struct path *new_dir, @@ -1481,7 +1481,7 @@ static inline int security_path_mknod(struct path *dir, struct dentry *dentry, return 0; } -static inline int security_path_truncate(struct path *path) +static inline int security_path_truncate(const struct path *path) { return 0; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 9713037e5257..83e9c3c2cfc8 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -269,7 +269,7 @@ static int apparmor_path_mknod(struct path *dir, struct dentry *dentry, return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode); } -static int apparmor_path_truncate(struct path *path) +static int apparmor_path_truncate(const struct path *path) { struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, d_backing_inode(path->dentry)->i_mode diff --git a/security/security.c b/security/security.c index 3644b0344d29..23ffb6cc3974 100644 --- a/security/security.c +++ b/security/security.c @@ -478,7 +478,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry, } EXPORT_SYMBOL(security_path_rename); -int security_path_truncate(struct path *path) +int security_path_truncate(const struct path *path) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index cbf3df422c87..8573eee2b58e 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -150,7 +150,7 @@ static int tomoyo_inode_getattr(const struct path *path) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_truncate(struct path *path) +static int tomoyo_path_truncate(const struct path *path) { return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL); } -- GitLab From 7df818b2370a9aab5fc58a85b70b8af3d835affa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:24:09 -0400 Subject: [PATCH 0235/9938] constify vfs_truncate() Signed-off-by: Al Viro --- fs/open.c | 2 +- include/linux/fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/open.c b/fs/open.c index 17cb6b1dab75..2f49fce5c952 100644 --- a/fs/open.c +++ b/fs/open.c @@ -65,7 +65,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, return ret; } -long vfs_truncate(struct path *path, loff_t length) +long vfs_truncate(const struct path *path, loff_t length) { struct inode *inode; long error; diff --git a/include/linux/fs.h b/include/linux/fs.h index 14a97194b34b..09a68517e952 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2253,7 +2253,7 @@ struct filename { const char iname[]; }; -extern long vfs_truncate(struct path *, loff_t); +extern long vfs_truncate(const struct path *, loff_t); extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, struct file *filp); extern int vfs_fallocate(struct file *file, int mode, loff_t offset, -- GitLab From 928e1ebfb576f6c0480ac852becfc142b248242c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:24:49 -0400 Subject: [PATCH 0236/9938] apparmor_path_truncate(): path->mnt is never NULL Signed-off-by: Al Viro --- security/apparmor/lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 83e9c3c2cfc8..21dae6070bb9 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -275,7 +275,7 @@ static int apparmor_path_truncate(const struct path *path) d_backing_inode(path->dentry)->i_mode }; - if (!path->mnt || !mediated_filesystem(path->dentry)) + if (!mediated_filesystem(path->dentry)) return 0; return common_perm(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE, -- GitLab From e6641eddf0e7f0227493e91a1d91546f6bd73525 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:41:28 -0400 Subject: [PATCH 0237/9938] tomoyo: constify assorted struct path * Signed-off-by: Al Viro --- security/tomoyo/common.h | 12 ++++++------ security/tomoyo/file.c | 10 +++++----- security/tomoyo/mount.c | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f9c9fb1d56b4..361e7a284699 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -957,7 +957,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name); const struct tomoyo_path_info *tomoyo_path_matches_group (const struct tomoyo_path_info *pathname, const struct tomoyo_group *group); int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, - struct path *path, const int flag); + const struct path *path, const int flag); void tomoyo_close_control(struct tomoyo_io_buffer *head); int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env); int tomoyo_execute_permission(struct tomoyo_request_info *r, @@ -968,15 +968,15 @@ int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, int tomoyo_init_request_info(struct tomoyo_request_info *r, struct tomoyo_domain_info *domain, const u8 index); -int tomoyo_mkdev_perm(const u8 operation, struct path *path, +int tomoyo_mkdev_perm(const u8 operation, const struct path *path, const unsigned int mode, unsigned int dev); -int tomoyo_mount_permission(const char *dev_name, struct path *path, +int tomoyo_mount_permission(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data_page); int tomoyo_open_control(const u8 type, struct file *file); -int tomoyo_path2_perm(const u8 operation, struct path *path1, - struct path *path2); -int tomoyo_path_number_perm(const u8 operation, struct path *path, +int tomoyo_path2_perm(const u8 operation, const struct path *path1, + const struct path *path2); +int tomoyo_path_number_perm(const u8 operation, const struct path *path, unsigned long number); int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target); diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 2367b100cc62..7041a580019e 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -687,7 +687,7 @@ static int tomoyo_update_path_number_acl(const u8 perm, * * Returns 0 on success, negative value otherwise. */ -int tomoyo_path_number_perm(const u8 type, struct path *path, +int tomoyo_path_number_perm(const u8 type, const struct path *path, unsigned long number) { struct tomoyo_request_info r; @@ -733,7 +733,7 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, * Returns 0 on success, negative value otherwise. */ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, - struct path *path, const int flag) + const struct path *path, const int flag) { const u8 acc_mode = ACC_MODE(flag); int error = 0; @@ -838,7 +838,7 @@ int tomoyo_path_perm(const u8 operation, const struct path *path, const char *ta * * Returns 0 on success, negative value otherwise. */ -int tomoyo_mkdev_perm(const u8 operation, struct path *path, +int tomoyo_mkdev_perm(const u8 operation, const struct path *path, const unsigned int mode, unsigned int dev) { struct tomoyo_request_info r; @@ -882,8 +882,8 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path, * * Returns 0 on success, negative value otherwise. */ -int tomoyo_path2_perm(const u8 operation, struct path *path1, - struct path *path2) +int tomoyo_path2_perm(const u8 operation, const struct path *path1, + const struct path *path2) { int error = -ENOMEM; struct tomoyo_path_info buf1; diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 390c646013cb..14b53fb2a0cf 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -73,7 +73,7 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, */ static int tomoyo_mount_acl(struct tomoyo_request_info *r, const char *dev_name, - struct path *dir, const char *type, + const struct path *dir, const char *type, unsigned long flags) { struct tomoyo_obj_info obj = { }; @@ -184,7 +184,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, * * Returns 0 on success, negative value otherwise. */ -int tomoyo_mount_permission(const char *dev_name, struct path *path, +int tomoyo_mount_permission(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data_page) { -- GitLab From 7fd25dac9ad3970bede16f2834daf9f9d779d1b0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:44:41 -0400 Subject: [PATCH 0238/9938] constify chown_common/security_path_chown Signed-off-by: Al Viro --- fs/open.c | 2 +- include/linux/lsm_hooks.h | 2 +- include/linux/security.h | 4 ++-- security/apparmor/lsm.c | 2 +- security/security.c | 2 +- security/tomoyo/tomoyo.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/open.c b/fs/open.c index 2f49fce5c952..651bf74745a2 100644 --- a/fs/open.c +++ b/fs/open.c @@ -564,7 +564,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode) return sys_fchmodat(AT_FDCWD, filename, mode); } -static int chown_common(struct path *path, uid_t user, gid_t group) +static int chown_common(const struct path *path, uid_t user, gid_t group) { struct inode *inode = path->dentry->d_inode; struct inode *delegated_inode = NULL; diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 77c3bfdacf16..84f76cbc6d06 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1375,7 +1375,7 @@ union security_list_options { struct path *new_dir, struct dentry *new_dentry); int (*path_chmod)(struct path *path, umode_t mode); - int (*path_chown)(struct path *path, kuid_t uid, kgid_t gid); + int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); int (*path_chroot)(struct path *path); #endif diff --git a/include/linux/security.h b/include/linux/security.h index be37ccab2286..f83ca920ed46 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1456,7 +1456,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry, unsigned int flags); int security_path_chmod(struct path *path, umode_t mode); -int security_path_chown(struct path *path, kuid_t uid, kgid_t gid); +int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid); int security_path_chroot(struct path *path); #else /* CONFIG_SECURITY_PATH */ static inline int security_path_unlink(struct path *dir, struct dentry *dentry) @@ -1513,7 +1513,7 @@ static inline int security_path_chmod(struct path *path, umode_t mode) return 0; } -static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid) +static inline int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { return 0; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 21dae6070bb9..3adbff987b77 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -342,7 +342,7 @@ static int apparmor_path_chmod(struct path *path, umode_t mode) return common_perm_mnt_dentry(OP_CHMOD, path->mnt, path->dentry, AA_MAY_CHMOD); } -static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid) +static int apparmor_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, d_backing_inode(path->dentry)->i_mode diff --git a/security/security.c b/security/security.c index 23ffb6cc3974..4a3e7e99abbb 100644 --- a/security/security.c +++ b/security/security.c @@ -492,7 +492,7 @@ int security_path_chmod(struct path *path, umode_t mode) return call_int_hook(path_chmod, 0, path, mode); } -int security_path_chown(struct path *path, kuid_t uid, kgid_t gid) +int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 8573eee2b58e..f0989ec978e1 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -366,7 +366,7 @@ static int tomoyo_path_chmod(struct path *path, umode_t mode) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_chown(struct path *path, kuid_t uid, kgid_t gid) +static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { int error = 0; if (uid_valid(uid)) -- GitLab From 8a04c43b8741ebb40508d160cf87ca74b70941af Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:52:53 -0400 Subject: [PATCH 0239/9938] constify security_sb_mount() Signed-off-by: Al Viro --- include/linux/lsm_hooks.h | 2 +- include/linux/security.h | 4 ++-- security/security.c | 2 +- security/selinux/hooks.c | 2 +- security/tomoyo/tomoyo.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 84f76cbc6d06..47117751f4eb 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1343,7 +1343,7 @@ union security_list_options { int (*sb_kern_mount)(struct super_block *sb, int flags, void *data); int (*sb_show_options)(struct seq_file *m, struct super_block *sb); int (*sb_statfs)(struct dentry *dentry); - int (*sb_mount)(const char *dev_name, struct path *path, + int (*sb_mount)(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data); int (*sb_umount)(struct vfsmount *mnt, int flags); int (*sb_pivotroot)(struct path *old_path, struct path *new_path); diff --git a/include/linux/security.h b/include/linux/security.h index f83ca920ed46..415a357efe4c 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -222,7 +222,7 @@ int security_sb_remount(struct super_block *sb, void *data); int security_sb_kern_mount(struct super_block *sb, int flags, void *data); int security_sb_show_options(struct seq_file *m, struct super_block *sb); int security_sb_statfs(struct dentry *dentry); -int security_sb_mount(const char *dev_name, struct path *path, +int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data); int security_sb_umount(struct vfsmount *mnt, int flags); int security_sb_pivotroot(struct path *old_path, struct path *new_path); @@ -530,7 +530,7 @@ static inline int security_sb_statfs(struct dentry *dentry) return 0; } -static inline int security_sb_mount(const char *dev_name, struct path *path, +static inline int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { diff --git a/security/security.c b/security/security.c index 4a3e7e99abbb..fc567656b16f 100644 --- a/security/security.c +++ b/security/security.c @@ -302,7 +302,7 @@ int security_sb_statfs(struct dentry *dentry) return call_int_hook(sb_statfs, 0, dentry); } -int security_sb_mount(const char *dev_name, struct path *path, +int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 912deee3f01e..e3aeacc13545 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2760,7 +2760,7 @@ static int selinux_sb_statfs(struct dentry *dentry) } static int selinux_mount(const char *dev_name, - struct path *path, + const struct path *path, const char *type, unsigned long flags, void *data) diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index f0989ec978e1..c1177f885247 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -401,7 +401,7 @@ static int tomoyo_path_chroot(struct path *path) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_sb_mount(const char *dev_name, struct path *path, +static int tomoyo_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { return tomoyo_mount_permission(dev_name, path, type, flags, data); -- GitLab From be01f9f28e66fa846f02196eb047c6bc445642db Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 14:56:23 -0400 Subject: [PATCH 0240/9938] constify chmod_common/security_path_chmod Signed-off-by: Al Viro --- fs/open.c | 2 +- include/linux/lsm_hooks.h | 2 +- include/linux/security.h | 4 ++-- security/apparmor/lsm.c | 2 +- security/security.c | 2 +- security/tomoyo/tomoyo.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/open.c b/fs/open.c index 651bf74745a2..cfdf71a6704e 100644 --- a/fs/open.c +++ b/fs/open.c @@ -499,7 +499,7 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) return error; } -static int chmod_common(struct path *path, umode_t mode) +static int chmod_common(const struct path *path, umode_t mode) { struct inode *inode = path->dentry->d_inode; struct inode *delegated_inode = NULL; diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 47117751f4eb..294fdfe902bf 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1374,7 +1374,7 @@ union security_list_options { int (*path_rename)(struct path *old_dir, struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry); - int (*path_chmod)(struct path *path, umode_t mode); + int (*path_chmod)(const struct path *path, umode_t mode); int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); int (*path_chroot)(struct path *path); #endif diff --git a/include/linux/security.h b/include/linux/security.h index 415a357efe4c..d6593ee2d0a9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1455,7 +1455,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir, int security_path_rename(struct path *old_dir, struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry, unsigned int flags); -int security_path_chmod(struct path *path, umode_t mode); +int security_path_chmod(const struct path *path, umode_t mode); int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid); int security_path_chroot(struct path *path); #else /* CONFIG_SECURITY_PATH */ @@ -1508,7 +1508,7 @@ static inline int security_path_rename(struct path *old_dir, return 0; } -static inline int security_path_chmod(struct path *path, umode_t mode) +static inline int security_path_chmod(const struct path *path, umode_t mode) { return 0; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 3adbff987b77..8d19615dcb73 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -334,7 +334,7 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry, return error; } -static int apparmor_path_chmod(struct path *path, umode_t mode) +static int apparmor_path_chmod(const struct path *path, umode_t mode) { if (!mediated_filesystem(path->dentry)) return 0; diff --git a/security/security.c b/security/security.c index fc567656b16f..b333429fe718 100644 --- a/security/security.c +++ b/security/security.c @@ -485,7 +485,7 @@ int security_path_truncate(const struct path *path) return call_int_hook(path_truncate, 0, path); } -int security_path_chmod(struct path *path, umode_t mode) +int security_path_chmod(const struct path *path, umode_t mode) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index c1177f885247..e48d0a4e4128 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -351,7 +351,7 @@ static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_chmod(struct path *path, umode_t mode) +static int tomoyo_path_chmod(const struct path *path, umode_t mode) { return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path, mode & S_IALLUGO); -- GitLab From 741aca71d61c3485d1e9db3bcea00d4509cf2301 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:04:36 -0400 Subject: [PATCH 0241/9938] apparmor: new helper - common_path_perm() was open-coded in several places... Signed-off-by: Al Viro --- security/apparmor/lsm.c | 47 +++++++++++------------------------------ 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8d19615dcb73..ead56bfaa056 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -182,23 +182,22 @@ static int common_perm_dir_dentry(int op, struct path *dir, } /** - * common_perm_mnt_dentry - common permission wrapper when mnt, dentry + * common_perm_path - common permission wrapper when mnt, dentry * @op: operation being checked - * @mnt: mount point of dentry (NOT NULL) - * @dentry: dentry to check (NOT NULL) + * @path: location to check (NOT NULL) * @mask: requested permissions mask * * Returns: %0 else error code if error or permission denied */ -static int common_perm_mnt_dentry(int op, struct vfsmount *mnt, - struct dentry *dentry, u32 mask) +static inline int common_perm_path(int op, const struct path *path, u32 mask) { - struct path path = { mnt, dentry }; - struct path_cond cond = { d_backing_inode(dentry)->i_uid, - d_backing_inode(dentry)->i_mode + struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, + d_backing_inode(path->dentry)->i_mode }; + if (!mediated_filesystem(path->dentry)) + return 0; - return common_perm(op, &path, mask, &cond); + return common_perm(op, path, mask, &cond); } /** @@ -271,15 +270,7 @@ static int apparmor_path_mknod(struct path *dir, struct dentry *dentry, static int apparmor_path_truncate(const struct path *path) { - struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, - d_backing_inode(path->dentry)->i_mode - }; - - if (!mediated_filesystem(path->dentry)) - return 0; - - return common_perm(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE, - &cond); + return common_perm_path(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE); } static int apparmor_path_symlink(struct path *dir, struct dentry *dentry, @@ -336,31 +327,17 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry, static int apparmor_path_chmod(const struct path *path, umode_t mode) { - if (!mediated_filesystem(path->dentry)) - return 0; - - return common_perm_mnt_dentry(OP_CHMOD, path->mnt, path->dentry, AA_MAY_CHMOD); + return common_perm_path(OP_CHMOD, path, AA_MAY_CHMOD); } static int apparmor_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { - struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, - d_backing_inode(path->dentry)->i_mode - }; - - if (!mediated_filesystem(path->dentry)) - return 0; - - return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond); + return common_perm_path(OP_CHOWN, path, AA_MAY_CHOWN); } static int apparmor_inode_getattr(const struct path *path) { - if (!mediated_filesystem(path->dentry)) - return 0; - - return common_perm_mnt_dentry(OP_GETATTR, path->mnt, path->dentry, - AA_MAY_META_READ); + return common_perm_path(OP_GETATTR, path, AA_MAY_META_READ); } static int apparmor_file_open(struct file *file, const struct cred *cred) -- GitLab From 3539aaf670cdd68a37314cd5db400c0c77287c88 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:07:03 -0400 Subject: [PATCH 0242/9938] apparmor: constify aa_path_link() Signed-off-by: Al Viro --- security/apparmor/file.c | 2 +- security/apparmor/include/file.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 4dfc5d0d8413..d186674f973a 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -346,7 +346,7 @@ static inline bool xindex_is_subset(u32 link, u32 target) * Returns: %0 if allowed else error */ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry) + const struct path *new_dir, struct dentry *new_dentry) { struct path link = { new_dir->mnt, new_dentry }; struct path target = { new_dir->mnt, old_dentry }; diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index afc5b294e0d5..4803c97d1992 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h @@ -175,7 +175,7 @@ int aa_path_perm(int op, struct aa_profile *profile, const struct path *path, int flags, u32 request, struct path_cond *cond); int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry); + const struct path *new_dir, struct dentry *new_dentry); int aa_file_perm(int op, struct aa_profile *profile, struct file *file, u32 request); -- GitLab From d6b49f7ad2f38b5c3af27ac1a6f475b1ec13ea6e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:10:04 -0400 Subject: [PATCH 0243/9938] apparmor: constify common_perm_...() Signed-off-by: Al Viro --- security/apparmor/lsm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ead56bfaa056..4d2638f4676d 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -172,7 +172,7 @@ static int common_perm(int op, const struct path *path, u32 mask, * * Returns: %0 else error code if error or permission denied */ -static int common_perm_dir_dentry(int op, struct path *dir, +static int common_perm_dir_dentry(int op, const struct path *dir, struct dentry *dentry, u32 mask, struct path_cond *cond) { @@ -209,7 +209,7 @@ static inline int common_perm_path(int op, const struct path *path, u32 mask) * * Returns: %0 else error code if error or permission denied */ -static int common_perm_rm(int op, struct path *dir, +static int common_perm_rm(int op, const struct path *dir, struct dentry *dentry, u32 mask) { struct inode *inode = d_backing_inode(dentry); @@ -234,8 +234,8 @@ static int common_perm_rm(int op, struct path *dir, * * Returns: %0 else error code if error or permission denied */ -static int common_perm_create(int op, struct path *dir, struct dentry *dentry, - u32 mask, umode_t mode) +static int common_perm_create(int op, const struct path *dir, + struct dentry *dentry, u32 mask, umode_t mode) { struct path_cond cond = { current_fsuid(), mode }; -- GitLab From 989f74e0500a1e136d369bb619adc22786ea5e68 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:13:39 -0400 Subject: [PATCH 0244/9938] constify security_path_{unlink,rmdir} Signed-off-by: Al Viro --- include/linux/lsm_hooks.h | 4 ++-- include/linux/security.h | 8 ++++---- security/apparmor/lsm.c | 4 ++-- security/security.c | 4 ++-- security/tomoyo/tomoyo.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 294fdfe902bf..322912cc2da1 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1360,10 +1360,10 @@ union security_list_options { #ifdef CONFIG_SECURITY_PATH - int (*path_unlink)(struct path *dir, struct dentry *dentry); + int (*path_unlink)(const struct path *dir, struct dentry *dentry); int (*path_mkdir)(struct path *dir, struct dentry *dentry, umode_t mode); - int (*path_rmdir)(struct path *dir, struct dentry *dentry); + int (*path_rmdir)(const struct path *dir, struct dentry *dentry); int (*path_mknod)(struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev); int (*path_truncate)(const struct path *path); diff --git a/include/linux/security.h b/include/linux/security.h index d6593ee2d0a9..e292d8cb21d7 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1442,9 +1442,9 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi #endif /* CONFIG_SECURITY_NETWORK_XFRM */ #ifdef CONFIG_SECURITY_PATH -int security_path_unlink(struct path *dir, struct dentry *dentry); +int security_path_unlink(const struct path *dir, struct dentry *dentry); int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode); -int security_path_rmdir(struct path *dir, struct dentry *dentry); +int security_path_rmdir(const struct path *dir, struct dentry *dentry); int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev); int security_path_truncate(const struct path *path); @@ -1459,7 +1459,7 @@ int security_path_chmod(const struct path *path, umode_t mode); int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid); int security_path_chroot(struct path *path); #else /* CONFIG_SECURITY_PATH */ -static inline int security_path_unlink(struct path *dir, struct dentry *dentry) +static inline int security_path_unlink(const struct path *dir, struct dentry *dentry) { return 0; } @@ -1470,7 +1470,7 @@ static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, return 0; } -static inline int security_path_rmdir(struct path *dir, struct dentry *dentry) +static inline int security_path_rmdir(const struct path *dir, struct dentry *dentry) { return 0; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 4d2638f4676d..b760fe026b82 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -245,7 +245,7 @@ static int common_perm_create(int op, const struct path *dir, return common_perm_dir_dentry(op, dir, dentry, mask, &cond); } -static int apparmor_path_unlink(struct path *dir, struct dentry *dentry) +static int apparmor_path_unlink(const struct path *dir, struct dentry *dentry) { return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE); } @@ -257,7 +257,7 @@ static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry, S_IFDIR); } -static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry) +static int apparmor_path_rmdir(const struct path *dir, struct dentry *dentry) { return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE); } diff --git a/security/security.c b/security/security.c index b333429fe718..20f2070b3ace 100644 --- a/security/security.c +++ b/security/security.c @@ -427,14 +427,14 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode) } EXPORT_SYMBOL(security_path_mkdir); -int security_path_rmdir(struct path *dir, struct dentry *dentry) +int security_path_rmdir(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; return call_int_hook(path_rmdir, 0, dir, dentry); } -int security_path_unlink(struct path *dir, struct dentry *dentry) +int security_path_unlink(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index e48d0a4e4128..be5b1ae02f02 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -163,7 +163,7 @@ static int tomoyo_path_truncate(const struct path *path) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) +static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) { struct path path = { parent->mnt, dentry }; return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); @@ -194,7 +194,7 @@ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) +static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) { struct path path = { parent->mnt, dentry }; return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); -- GitLab From d360775217070ff0f4291e47d3f568f0fe0b7374 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:21:09 -0400 Subject: [PATCH 0245/9938] constify security_path_{mkdir,mknod,symlink} ... as well as unix_mknod() and may_o_create() Signed-off-by: Al Viro --- fs/namei.c | 2 +- include/linux/lsm_hooks.h | 6 +++--- include/linux/security.h | 12 ++++++------ net/unix/af_unix.c | 2 +- security/apparmor/lsm.c | 6 +++--- security/security.c | 6 +++--- security/tomoyo/tomoyo.c | 6 +++--- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 794f81dce766..8c97544d6883 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2783,7 +2783,7 @@ static inline int open_to_namei_flags(int flag) return flag; } -static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode) +static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t mode) { int error = security_path_mknod(dir, dentry, mode, 0); if (error) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 322912cc2da1..919fb4f98e4f 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1361,13 +1361,13 @@ union security_list_options { #ifdef CONFIG_SECURITY_PATH int (*path_unlink)(const struct path *dir, struct dentry *dentry); - int (*path_mkdir)(struct path *dir, struct dentry *dentry, + int (*path_mkdir)(const struct path *dir, struct dentry *dentry, umode_t mode); int (*path_rmdir)(const struct path *dir, struct dentry *dentry); - int (*path_mknod)(struct path *dir, struct dentry *dentry, + int (*path_mknod)(const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev); int (*path_truncate)(const struct path *path); - int (*path_symlink)(struct path *dir, struct dentry *dentry, + int (*path_symlink)(const struct path *dir, struct dentry *dentry, const char *old_name); int (*path_link)(struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry); diff --git a/include/linux/security.h b/include/linux/security.h index e292d8cb21d7..ccb8c2a170e3 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1443,12 +1443,12 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi #ifdef CONFIG_SECURITY_PATH int security_path_unlink(const struct path *dir, struct dentry *dentry); -int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode); +int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t mode); int security_path_rmdir(const struct path *dir, struct dentry *dentry); -int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode, +int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev); int security_path_truncate(const struct path *path); -int security_path_symlink(struct path *dir, struct dentry *dentry, +int security_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name); int security_path_link(struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry); @@ -1464,7 +1464,7 @@ static inline int security_path_unlink(const struct path *dir, struct dentry *de return 0; } -static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, +static inline int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t mode) { return 0; @@ -1475,7 +1475,7 @@ static inline int security_path_rmdir(const struct path *dir, struct dentry *den return 0; } -static inline int security_path_mknod(struct path *dir, struct dentry *dentry, +static inline int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev) { return 0; @@ -1486,7 +1486,7 @@ static inline int security_path_truncate(const struct path *path) return 0; } -static inline int security_path_symlink(struct path *dir, struct dentry *dentry, +static inline int security_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name) { return 0; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 8269da73e9e5..80aa6a3e6817 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -953,7 +953,7 @@ static struct sock *unix_find_other(struct net *net, return NULL; } -static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode, +static int unix_mknod(struct dentry *dentry, const struct path *path, umode_t mode, struct path *res) { int err; diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index b760fe026b82..7ae540565097 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -250,7 +250,7 @@ static int apparmor_path_unlink(const struct path *dir, struct dentry *dentry) return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE); } -static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry, +static int apparmor_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t mode) { return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE, @@ -262,7 +262,7 @@ static int apparmor_path_rmdir(const struct path *dir, struct dentry *dentry) return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE); } -static int apparmor_path_mknod(struct path *dir, struct dentry *dentry, +static int apparmor_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev) { return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode); @@ -273,7 +273,7 @@ static int apparmor_path_truncate(const struct path *path) return common_perm_path(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE); } -static int apparmor_path_symlink(struct path *dir, struct dentry *dentry, +static int apparmor_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name) { return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE, diff --git a/security/security.c b/security/security.c index 20f2070b3ace..7f62e2ed6a28 100644 --- a/security/security.c +++ b/security/security.c @@ -410,7 +410,7 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir, EXPORT_SYMBOL(security_old_inode_init_security); #ifdef CONFIG_SECURITY_PATH -int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode, +int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) @@ -419,7 +419,7 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode, } EXPORT_SYMBOL(security_path_mknod); -int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode) +int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; @@ -442,7 +442,7 @@ int security_path_unlink(const struct path *dir, struct dentry *dentry) } EXPORT_SYMBOL(security_path_unlink); -int security_path_symlink(struct path *dir, struct dentry *dentry, +int security_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index be5b1ae02f02..d44752562b9b 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -178,7 +178,7 @@ static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, +static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, umode_t mode) { struct path path = { parent->mnt, dentry }; @@ -209,7 +209,7 @@ static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, +static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, const char *old_name) { struct path path = { parent->mnt, dentry }; @@ -226,7 +226,7 @@ static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, +static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, umode_t mode, unsigned int dev) { struct path path = { parent->mnt, dentry }; -- GitLab From 8db0185659c33143915768bdd33fc2fb1b1cbb58 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:22:49 -0400 Subject: [PATCH 0246/9938] apparmor: remove useless checks for NULL ->mnt Signed-off-by: Al Viro --- security/apparmor/lsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 7ae540565097..eadaa58bd6fd 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -215,7 +215,7 @@ static int common_perm_rm(int op, const struct path *dir, struct inode *inode = d_backing_inode(dentry); struct path_cond cond = { }; - if (!inode || !dir->mnt || !mediated_filesystem(dentry)) + if (!inode || !mediated_filesystem(dentry)) return 0; cond.uid = inode->i_uid; @@ -239,7 +239,7 @@ static int common_perm_create(int op, const struct path *dir, { struct path_cond cond = { current_fsuid(), mode }; - if (!dir->mnt || !mediated_filesystem(dir->dentry)) + if (!mediated_filesystem(dir->dentry)) return 0; return common_perm_dir_dentry(op, dir, dentry, mask, &cond); -- GitLab From 3ccee46ab487d5b87d0621824efe2500b2857c58 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:27:45 -0400 Subject: [PATCH 0247/9938] constify security_path_{link,rename} Signed-off-by: Al Viro --- include/linux/lsm_hooks.h | 6 +++--- include/linux/security.h | 12 ++++++------ security/apparmor/lsm.c | 6 +++--- security/security.c | 6 +++--- security/tomoyo/tomoyo.c | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 919fb4f98e4f..52c2ac5f4855 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1369,10 +1369,10 @@ union security_list_options { int (*path_truncate)(const struct path *path); int (*path_symlink)(const struct path *dir, struct dentry *dentry, const char *old_name); - int (*path_link)(struct dentry *old_dentry, struct path *new_dir, + int (*path_link)(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry); - int (*path_rename)(struct path *old_dir, struct dentry *old_dentry, - struct path *new_dir, + int (*path_rename)(const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry); int (*path_chmod)(const struct path *path, umode_t mode); int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); diff --git a/include/linux/security.h b/include/linux/security.h index ccb8c2a170e3..82854115e36b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1450,10 +1450,10 @@ int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t m int security_path_truncate(const struct path *path); int security_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name); -int security_path_link(struct dentry *old_dentry, struct path *new_dir, +int security_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry); -int security_path_rename(struct path *old_dir, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry, +int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry, unsigned int flags); int security_path_chmod(const struct path *path, umode_t mode); int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid); @@ -1493,15 +1493,15 @@ static inline int security_path_symlink(const struct path *dir, struct dentry *d } static inline int security_path_link(struct dentry *old_dentry, - struct path *new_dir, + const struct path *new_dir, struct dentry *new_dentry) { return 0; } -static inline int security_path_rename(struct path *old_dir, +static inline int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, - struct path *new_dir, + const struct path *new_dir, struct dentry *new_dentry, unsigned int flags) { diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index eadaa58bd6fd..2660fbcf94d1 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -280,7 +280,7 @@ static int apparmor_path_symlink(const struct path *dir, struct dentry *dentry, S_IFLNK); } -static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir, +static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { struct aa_profile *profile; @@ -295,8 +295,8 @@ static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir, return error; } -static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry) +static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry) { struct aa_profile *profile; int error = 0; diff --git a/security/security.c b/security/security.c index 7f62e2ed6a28..33b85a960128 100644 --- a/security/security.c +++ b/security/security.c @@ -450,7 +450,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, return call_int_hook(path_symlink, 0, dir, dentry, old_name); } -int security_path_link(struct dentry *old_dentry, struct path *new_dir, +int security_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) @@ -458,8 +458,8 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir, return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); } -int security_path_rename(struct path *old_dir, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry, +int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry, unsigned int flags) { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) || diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index d44752562b9b..6a858f2f4063 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -265,7 +265,7 @@ static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, +static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { struct path path1 = { new_dir->mnt, old_dentry }; @@ -283,9 +283,9 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_rename(struct path *old_parent, +static int tomoyo_path_rename(const struct path *old_parent, struct dentry *old_dentry, - struct path *new_parent, + const struct path *new_parent, struct dentry *new_dentry) { struct path path1 = { old_parent->mnt, old_dentry }; -- GitLab From 77b286c0d26a5399912f5affd90ed73e2d8b42a5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:28:43 -0400 Subject: [PATCH 0248/9938] constify security_path_chroot() Signed-off-by: Al Viro --- include/linux/lsm_hooks.h | 2 +- include/linux/security.h | 4 ++-- security/security.c | 2 +- security/tomoyo/tomoyo.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 52c2ac5f4855..e2baca48e596 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1376,7 +1376,7 @@ union security_list_options { struct dentry *new_dentry); int (*path_chmod)(const struct path *path, umode_t mode); int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); - int (*path_chroot)(struct path *path); + int (*path_chroot)(const struct path *path); #endif int (*inode_alloc_security)(struct inode *inode); diff --git a/include/linux/security.h b/include/linux/security.h index 82854115e36b..cb53cffbfae4 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1457,7 +1457,7 @@ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, unsigned int flags); int security_path_chmod(const struct path *path, umode_t mode); int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid); -int security_path_chroot(struct path *path); +int security_path_chroot(const struct path *path); #else /* CONFIG_SECURITY_PATH */ static inline int security_path_unlink(const struct path *dir, struct dentry *dentry) { @@ -1518,7 +1518,7 @@ static inline int security_path_chown(const struct path *path, kuid_t uid, kgid_ return 0; } -static inline int security_path_chroot(struct path *path) +static inline int security_path_chroot(const struct path *path) { return 0; } diff --git a/security/security.c b/security/security.c index 33b85a960128..cf6f31df524a 100644 --- a/security/security.c +++ b/security/security.c @@ -499,7 +499,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) return call_int_hook(path_chown, 0, path, uid, gid); } -int security_path_chroot(struct path *path) +int security_path_chroot(const struct path *path) { return call_int_hook(path_chroot, 0, path); } diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 6a858f2f4063..c7764bb747aa 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -385,7 +385,7 @@ static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_path_chroot(struct path *path) +static int tomoyo_path_chroot(const struct path *path) { return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); } -- GitLab From 3b73b68c05db0b3c9b282c6e8e6eb71acc589a02 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:31:19 -0400 Subject: [PATCH 0249/9938] constify security_sb_pivotroot() Signed-off-by: Al Viro --- include/linux/lsm_hooks.h | 2 +- include/linux/security.h | 6 +++--- security/security.c | 2 +- security/tomoyo/tomoyo.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index e2baca48e596..41c0aa6d39ea 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1346,7 +1346,7 @@ union security_list_options { int (*sb_mount)(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data); int (*sb_umount)(struct vfsmount *mnt, int flags); - int (*sb_pivotroot)(struct path *old_path, struct path *new_path); + int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path); int (*sb_set_mnt_opts)(struct super_block *sb, struct security_mnt_opts *opts, unsigned long kern_flags, diff --git a/include/linux/security.h b/include/linux/security.h index cb53cffbfae4..fcfa211c694f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -225,7 +225,7 @@ int security_sb_statfs(struct dentry *dentry); int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data); int security_sb_umount(struct vfsmount *mnt, int flags); -int security_sb_pivotroot(struct path *old_path, struct path *new_path); +int security_sb_pivotroot(const struct path *old_path, const struct path *new_path); int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts, unsigned long kern_flags, @@ -542,8 +542,8 @@ static inline int security_sb_umount(struct vfsmount *mnt, int flags) return 0; } -static inline int security_sb_pivotroot(struct path *old_path, - struct path *new_path) +static inline int security_sb_pivotroot(const struct path *old_path, + const struct path *new_path) { return 0; } diff --git a/security/security.c b/security/security.c index cf6f31df524a..f7af0aaa173e 100644 --- a/security/security.c +++ b/security/security.c @@ -313,7 +313,7 @@ int security_sb_umount(struct vfsmount *mnt, int flags) return call_int_hook(sb_umount, 0, mnt, flags); } -int security_sb_pivotroot(struct path *old_path, struct path *new_path) +int security_sb_pivotroot(const struct path *old_path, const struct path *new_path) { return call_int_hook(sb_pivotroot, 0, old_path, new_path); } diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index c7764bb747aa..75c998700190 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -429,7 +429,7 @@ static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) +static int tomoyo_sb_pivotroot(const struct path *old_path, const struct path *new_path) { return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); } -- GitLab From 81cd8896a64cc34bd59f097fa619b11ab40ca7a6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Mar 2016 15:33:04 -0400 Subject: [PATCH 0250/9938] constify ima_d_path() Signed-off-by: Al Viro --- security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_api.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 5d0f61163d98..d3a939bf2781 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -170,7 +170,7 @@ int ima_alloc_init_template(struct ima_event_data *event_data, int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename); void ima_free_template_entry(struct ima_template_entry *entry); -const char *ima_d_path(struct path *path, char **pathbuf); +const char *ima_d_path(const struct path *path, char **pathbuf); /* IMA policy related functions */ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 370e42dfc5c5..5a2218fe877a 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -313,7 +313,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint, iint->flags |= IMA_AUDITED; } -const char *ima_d_path(struct path *path, char **pathbuf) +const char *ima_d_path(const struct path *path, char **pathbuf) { char *pathname = NULL; -- GitLab From a686632fd9a857776798f3479e2b58b07d938076 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 21 Mar 2016 12:18:33 +0100 Subject: [PATCH 0251/9938] ALSA: hda - Split out Intel-specific codes from patch_generic_hdmi() We have too many Intel-specific codes in patch_hdmi_generic() despite its function name. And this makes it difficult to adjust per chipset, e.g. for allowing the audio notifier on an old chipset, one would need to add an explicit if() check. This patch attempts some code refactoring and cleanups in this regard; the Intel-specific codes are moved out of patch_generic_hdmi() into the new functions, patch_i915_hsw_hdmi() and patch_i915_byt_hdmi(), depending on the chipset. The other old Intel chipsets keep using patch_generic_hdmi() without Intel hacks. The existing patch_generic_hdmi() is also split to a few components so that they can be called from the Intel codec parsers. There are still many is_haswell*() and is_valleyview*() macro usages in the code. They will be cleaned up later. For the time being, only the entry are concerned. Along with this change, the i915_bound flag and the on-demand i915 component binding have been removed as a cleanup, since there is no user at this moment. This will be added back later once when Cougar Point and else start using the i915 eld notifier. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 218 +++++++++++++++++++++++-------------- 1 file changed, 139 insertions(+), 79 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 5af372d01834..48c63fea7018 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -154,7 +154,6 @@ struct hdmi_spec { /* i915/powerwell (Haswell+/Valleyview+) specific */ bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ struct i915_audio_component_audio_ops i915_audio_ops; - bool i915_bound; /* was i915 bound in this driver? */ struct hdac_chmap chmap; }; @@ -2074,6 +2073,18 @@ static void hdmi_array_free(struct hdmi_spec *spec) snd_array_free(&spec->cvts); } +static void generic_spec_free(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + + if (spec) { + hdmi_array_free(spec); + kfree(spec); + codec->spec = NULL; + } + codec->dp_mst = false; +} + static void generic_hdmi_free(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -2098,10 +2109,7 @@ static void generic_hdmi_free(struct hda_codec *codec) spec->pcm_rec[pcm_idx].jack = NULL; } - if (spec->i915_bound) - snd_hdac_i915_exit(&codec->bus->core); - hdmi_array_free(spec); - kfree(spec); + generic_spec_free(codec); } #ifdef CONFIG_PM @@ -2139,6 +2147,54 @@ static const struct hdmi_ops generic_standard_hdmi_ops = { .setup_stream = hdmi_setup_stream, }; +/* allocate codec->spec and assign/initialize generic parser ops */ +static int alloc_generic_hdmi(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + spec->ops = generic_standard_hdmi_ops; + mutex_init(&spec->pcm_lock); + snd_hdac_register_chmap_ops(&codec->core, &spec->chmap); + + spec->chmap.ops.get_chmap = hdmi_get_chmap; + spec->chmap.ops.set_chmap = hdmi_set_chmap; + spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached; + + codec->spec = spec; + hdmi_array_init(spec, 4); + + codec->patch_ops = generic_hdmi_patch_ops; + + return 0; +} + +/* generic HDMI parser */ +static int patch_generic_hdmi(struct hda_codec *codec) +{ + int err; + + err = alloc_generic_hdmi(codec); + if (err < 0) + return err; + + err = hdmi_parse_codec(codec); + if (err < 0) { + generic_spec_free(codec); + return err; + } + + generic_hdmi_init_per_pins(codec); + return 0; +} + +/* + * Intel codec parsers and helpers + */ + static void intel_haswell_fixup_connect_list(struct hda_codec *codec, hda_nid_t nid) { @@ -2234,92 +2290,96 @@ static void intel_pin_eld_notify(void *audio_ptr, int port) check_presence_and_report(codec, pin_nid); } -static int patch_generic_hdmi(struct hda_codec *codec) +/* register i915 component pin_eld_notify callback */ +static void register_i915_notifier(struct hda_codec *codec) { - struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - spec->ops = generic_standard_hdmi_ops; - mutex_init(&spec->pcm_lock); - snd_hdac_register_chmap_ops(&codec->core, &spec->chmap); + struct hdmi_spec *spec = codec->spec; - spec->chmap.ops.get_chmap = hdmi_get_chmap; - spec->chmap.ops.set_chmap = hdmi_set_chmap; - spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached; + spec->use_acomp_notifier = true; + spec->i915_audio_ops.audio_ptr = codec; + /* intel_audio_codec_enable() or intel_audio_codec_disable() + * will call pin_eld_notify with using audio_ptr pointer + * We need make sure audio_ptr is really setup + */ + wmb(); + spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; + snd_hdac_i915_register_notifier(&spec->i915_audio_ops); +} - codec->spec = spec; - hdmi_array_init(spec, 4); +/* Intel Haswell and onwards; audio component with eld notifier */ +static int patch_i915_hsw_hdmi(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + int err; -#ifdef CONFIG_SND_HDA_I915 - /* Try to bind with i915 for Intel HSW+ codecs (if not done yet) */ - if ((codec->core.vendor_id >> 16) == 0x8086 && - is_haswell_plus(codec)) { -#if 0 - /* on-demand binding leads to an unbalanced refcount when - * both i915 and hda drivers are probed concurrently; - * disabled temporarily for now - */ - if (!codec->bus->core.audio_component) - if (!snd_hdac_i915_init(&codec->bus->core)) - spec->i915_bound = true; -#endif - /* use i915 audio component notifier for hotplug */ - if (codec->bus->core.audio_component) - spec->use_acomp_notifier = true; + /* HSW+ requires i915 binding */ + if (!codec->bus->core.audio_component) { + codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); + return -ENODEV; } -#endif - if (is_haswell_plus(codec)) { - intel_haswell_enable_all_pins(codec, true); - intel_haswell_fixup_enable_dp12(codec); - } + err = alloc_generic_hdmi(codec); + if (err < 0) + return err; + spec = codec->spec; - /* For Valleyview/Cherryview, only the display codec is in the display - * power well and can use link_power ops to request/release the power. - * For Haswell/Broadwell, the controller is also in the power well and + intel_haswell_enable_all_pins(codec, true); + intel_haswell_fixup_enable_dp12(codec); + + /* For Haswell/Broadwell, the controller is also in the power well and * can cover the codec power request, and so need not set this flag. - * For previous platforms, there is no such power well feature. */ - if (is_valleyview_plus(codec) || is_skylake(codec) || - is_broxton(codec)) + if (!is_haswell(codec) && !is_broadwell(codec)) codec->core.link_power_control = 1; - if (hdmi_parse_codec(codec) < 0) { - if (spec->i915_bound) - snd_hdac_i915_exit(&codec->bus->core); - codec->spec = NULL; - kfree(spec); - return -EINVAL; + codec->patch_ops.set_power_state = haswell_set_power_state; + codec->dp_mst = true; + codec->depop_delay = 0; + codec->auto_runtime_pm = 1; + + err = hdmi_parse_codec(codec); + if (err < 0) { + generic_spec_free(codec); + return err; } - codec->patch_ops = generic_hdmi_patch_ops; - if (is_haswell_plus(codec)) { - codec->patch_ops.set_power_state = haswell_set_power_state; - codec->dp_mst = true; + + generic_hdmi_init_per_pins(codec); + register_i915_notifier(codec); + return 0; +} + +/* Intel Baytrail and Braswell; without get_eld notifier */ +static int patch_i915_byt_hdmi(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + int err; + + /* requires i915 binding */ + if (!codec->bus->core.audio_component) { + codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); + return -ENODEV; } - /* Enable runtime pm for HDMI audio codec of HSW/BDW/SKL/BYT/BSW */ - if (is_haswell_plus(codec) || is_valleyview_plus(codec)) - codec->auto_runtime_pm = 1; + err = alloc_generic_hdmi(codec); + if (err < 0) + return err; + spec = codec->spec; - generic_hdmi_init_per_pins(codec); + /* For Valleyview/Cherryview, only the display codec is in the display + * power well and can use link_power ops to request/release the power. + */ + codec->core.link_power_control = 1; + codec->depop_delay = 0; + codec->auto_runtime_pm = 1; - if (codec_has_acomp(codec)) { - codec->depop_delay = 0; - spec->i915_audio_ops.audio_ptr = codec; - /* intel_audio_codec_enable() or intel_audio_codec_disable() - * will call pin_eld_notify with using audio_ptr pointer - * We need make sure audio_ptr is really setup - */ - wmb(); - spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; - snd_hdac_i915_register_notifier(&spec->i915_audio_ops); + err = hdmi_parse_codec(codec); + if (err < 0) { + generic_spec_free(codec); + return err; } - WARN_ON(spec->dyn_pcm_assign && !codec_has_acomp(codec)); + generic_hdmi_init_per_pins(codec); return 0; } @@ -3498,14 +3558,14 @@ HDA_CODEC_ENTRY(0x80862803, "Eaglelake HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_i915_hsw_hdmi), +HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_i915_hsw_hdmi), +HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_i915_hsw_hdmi), +HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_i915_hsw_hdmi), +HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi), HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), +HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x808629fb, "Crestline HDMI", patch_generic_hdmi), /* special ID for generic HDMI */ HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi), -- GitLab From 44bb6d0c3f690e60670517859925417bd7c42a22 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 21 Mar 2016 12:36:44 +0100 Subject: [PATCH 0252/9938] ALSA: hda - Apply AMP fix in hdmi_setup_audio_infoframe() generically The need for reprogramming the AMP mute bit at each audio info frame setup isn't always specific to Intel chips. It's safer to set it generically for all codecs with the amp bit, as this verb execution itself isn't too much load. This eliminates one usage of is_haswell_plus() macro, after all. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 48c63fea7018..fcd207d3ce7d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -683,7 +683,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, if (!channels) return; - if (is_haswell_plus(codec)) + /* some HW (e.g. HSW+) needs reprogramming the amp at each time */ + if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); -- GitLab From 2c1c9b86c6b22dc0cbac3f4ca2c8272c472dc463 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 21 Mar 2016 12:42:06 +0100 Subject: [PATCH 0253/9938] ALSA: hda - Override HDMI setup_stream ops for Intel HSW+ Instead of checking at each time with is_haswell_plus() macro, override the setup_stream ops itself for HSW+ chips. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index fcd207d3ce7d..985518891b99 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -864,9 +864,6 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, struct hdmi_spec *spec = codec->spec; int err; - if (is_haswell_plus(codec)) - haswell_verify_D0(codec, cvt_nid, pin_nid); - err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format)); if (err) { @@ -2307,6 +2304,14 @@ static void register_i915_notifier(struct hda_codec *codec) snd_hdac_i915_register_notifier(&spec->i915_audio_ops); } +/* setup_stream ops override for HSW+ */ +static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, + hda_nid_t pin_nid, u32 stream_tag, int format) +{ + haswell_verify_D0(codec, cvt_nid, pin_nid); + return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); +} + /* Intel Haswell and onwards; audio component with eld notifier */ static int patch_i915_hsw_hdmi(struct hda_codec *codec) { @@ -2338,6 +2343,8 @@ static int patch_i915_hsw_hdmi(struct hda_codec *codec) codec->depop_delay = 0; codec->auto_runtime_pm = 1; + spec->ops.setup_stream = i915_hsw_setup_stream; + err = hdmi_parse_codec(codec); if (err < 0) { generic_spec_free(codec); -- GitLab From 4846a67eb5a1d7cac76e1b22f66e88a8cbbdff3f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 21 Mar 2016 12:56:46 +0100 Subject: [PATCH 0254/9938] ALSA: hda - Introduce pin_cvt_fixup() ops to hdmi parser For reducing the splat of is_haswell_plus() or such macros, this patch introduces pin_cvt_fixup() ops to hdmi_spec. For HSW+ and VLV+ codecs, set this ops so that the driver can call the Intel-specific workarounds appropriately. A gratis bonus that we can remove the mux_id argument from hdmi_choose_cvt(), too, since the fixup function always refers the mux_idx from the given per_pin object. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 82 +++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 985518891b99..3481b43476dc 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -114,6 +114,9 @@ struct hdmi_ops { int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid, hda_nid_t pin_nid, u32 stream_tag, int format); + void (*pin_cvt_fixup)(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin, + hda_nid_t cvt_nid); }; struct hdmi_pcm { @@ -881,7 +884,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, * of the pin. */ static int hdmi_choose_cvt(struct hda_codec *codec, - int pin_idx, int *cvt_id, int *mux_id) + int pin_idx, int *cvt_id) { struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; @@ -922,8 +925,6 @@ static int hdmi_choose_cvt(struct hda_codec *codec, if (cvt_id) *cvt_id = cvt_idx; - if (mux_id) - *mux_id = mux_idx; return 0; } @@ -1016,9 +1017,6 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec, int mux_idx; struct hdmi_spec *spec = codec->spec; - if (!is_haswell_plus(codec) && !is_valleyview_plus(codec)) - return; - /* On Intel platform, the mapping of converter nid to * mux index of the pins are always the same. * The pin nid may be 0, this means all pins will not @@ -1029,6 +1027,17 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec, intel_not_share_assigned_cvt(codec, pin_nid, mux_idx); } +/* skeleton caller of pin_cvt_fixup ops */ +static void pin_cvt_fixup(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin, + hda_nid_t cvt_nid) +{ + struct hdmi_spec *spec = codec->spec; + + if (spec->ops.pin_cvt_fixup) + spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid); +} + /* called in hdmi_pcm_open when no pin is assigned to the PCM * in dyn_pcm_assign mode. */ @@ -1046,7 +1055,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, if (pcm_idx < 0) return -EINVAL; - err = hdmi_choose_cvt(codec, -1, &cvt_idx, NULL); + err = hdmi_choose_cvt(codec, -1, &cvt_idx); if (err) return err; @@ -1054,7 +1063,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, per_cvt->assigned = 1; hinfo->nid = per_cvt->cvt_nid; - intel_not_share_assigned_cvt_nid(codec, 0, per_cvt->cvt_nid); + pin_cvt_fixup(codec, NULL, per_cvt->cvt_nid); set_bit(pcm_idx, &spec->pcm_in_use); /* todo: setup spdif ctls assign */ @@ -1086,7 +1095,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, { struct hdmi_spec *spec = codec->spec; struct snd_pcm_runtime *runtime = substream->runtime; - int pin_idx, cvt_idx, pcm_idx, mux_idx = 0; + int pin_idx, cvt_idx, pcm_idx; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; struct hdmi_spec_per_cvt *per_cvt = NULL; @@ -1115,7 +1124,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, } } - err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx); + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); if (err < 0) { mutex_unlock(&spec->pcm_lock); return err; @@ -1132,11 +1141,10 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, AC_VERB_SET_CONNECT_SEL, - mux_idx); + per_pin->mux_idx); /* configure unused pins to choose other converters */ - if (is_haswell_plus(codec) || is_valleyview_plus(codec)) - intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); + pin_cvt_fixup(codec, per_pin, 0); snd_hda_spdif_ctls_assign(codec, pcm_idx, per_cvt->cvt_nid); @@ -1369,12 +1377,7 @@ static void update_eld(struct hda_codec *codec, * and this can make HW reset converter selection on a pin. */ if (eld->eld_valid && !old_eld_valid && per_pin->setup) { - if (is_haswell_plus(codec) || is_valleyview_plus(codec)) { - intel_verify_pin_cvt_connect(codec, per_pin); - intel_not_share_assigned_cvt(codec, per_pin->pin_nid, - per_pin->mux_idx); - } - + pin_cvt_fixup(codec, per_pin, 0); hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); } @@ -1709,7 +1712,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, * skip pin setup and return 0 to make audio playback * be ongoing */ - intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid); + pin_cvt_fixup(codec, NULL, cvt_nid); snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); mutex_unlock(&spec->pcm_lock); @@ -1722,18 +1725,16 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, } per_pin = get_pin(spec, pin_idx); pin_nid = per_pin->pin_nid; - if (is_haswell_plus(codec) || is_valleyview_plus(codec)) { - /* Verify pin:cvt selections to avoid silent audio after S3. - * After S3, the audio driver restores pin:cvt selections - * but this can happen before gfx is ready and such selection - * is overlooked by HW. Thus multiple pins can share a same - * default convertor and mute control will affect each other, - * which can cause a resumed audio playback become silent - * after S3. - */ - intel_verify_pin_cvt_connect(codec, per_pin); - intel_not_share_assigned_cvt(codec, pin_nid, per_pin->mux_idx); - } + + /* Verify pin:cvt selections to avoid silent audio after S3. + * After S3, the audio driver restores pin:cvt selections + * but this can happen before gfx is ready and such selection + * is overlooked by HW. Thus multiple pins can share a same + * default convertor and mute control will affect each other, + * which can cause a resumed audio playback become silent + * after S3. + */ + pin_cvt_fixup(codec, per_pin, 0); /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ /* Todo: add DP1.2 MST audio support later */ @@ -2312,6 +2313,20 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); } +/* pin_cvt_fixup ops override for HSW+ and VLV+ */ +static void i915_pin_cvt_fixup(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin, + hda_nid_t cvt_nid) +{ + if (per_pin) { + intel_verify_pin_cvt_connect(codec, per_pin); + intel_not_share_assigned_cvt(codec, per_pin->pin_nid, + per_pin->mux_idx); + } else { + intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid); + } +} + /* Intel Haswell and onwards; audio component with eld notifier */ static int patch_i915_hsw_hdmi(struct hda_codec *codec) { @@ -2344,6 +2359,7 @@ static int patch_i915_hsw_hdmi(struct hda_codec *codec) codec->auto_runtime_pm = 1; spec->ops.setup_stream = i915_hsw_setup_stream; + spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; err = hdmi_parse_codec(codec); if (err < 0) { @@ -2381,6 +2397,8 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) codec->depop_delay = 0; codec->auto_runtime_pm = 1; + spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; + err = hdmi_parse_codec(codec); if (err < 0) { generic_spec_free(codec); -- GitLab From e85015a3797f2665cc6f0339e6407adc00ac4245 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 21 Mar 2016 13:56:19 +0100 Subject: [PATCH 0255/9938] ALSA: hda - Use eld notifier for Intel SandyBridge and IvyBridge HDMI/DP Intel SandyBridge and IvyBridge (CougarPoint and PantherPoint platforms) have also the same digital port vs audio widget mapping (from port B = NID 0x05 to port D = NID 0x07) as Haswell & co. So, we can reuse the existing functions for HSW+ for these platforms without changing there, but just by re-adding the on-demand i915 binding in HDMI codec driver. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 41 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 3481b43476dc..09eb26c5730c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -157,6 +157,7 @@ struct hdmi_spec { /* i915/powerwell (Haswell+/Valleyview+) specific */ bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ struct i915_audio_component_audio_ops i915_audio_ops; + bool i915_bound; /* was i915 bound in this driver? */ struct hdac_chmap chmap; }; @@ -2077,6 +2078,8 @@ static void generic_spec_free(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; if (spec) { + if (spec->i915_bound) + snd_hdac_i915_exit(&codec->bus->core); hdmi_array_free(spec); kfree(spec); codec->spec = NULL; @@ -2409,6 +2412,40 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) return 0; } +/* Intel SandyBridge and IvyBridge; with i915 eld notifier */ +static int patch_i915_cpt_hdmi(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + int err; + + /* no i915 component should have been bound before this */ + if (WARN_ON(codec->bus->core.audio_component)) + return -EBUSY; + + err = alloc_generic_hdmi(codec); + if (err < 0) + return err; + spec = codec->spec; + + /* Try to bind with i915 now */ + err = snd_hdac_i915_init(&codec->bus->core); + if (err < 0) + goto error; + spec->i915_bound = true; + + err = hdmi_parse_codec(codec); + if (err < 0) + goto error; + + generic_hdmi_init_per_pins(codec); + register_i915_notifier(codec); + return 0; + + error: + generic_spec_free(codec); + return err; +} + /* * Shared non-generic implementations */ @@ -3582,8 +3619,8 @@ HDA_CODEC_ENTRY(0x80862801, "Bearlake HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862802, "Cantiga HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862803, "Eaglelake HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_i915_cpt_hdmi), +HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_i915_cpt_hdmi), HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_i915_hsw_hdmi), HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_i915_hsw_hdmi), HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_i915_hsw_hdmi), -- GitLab From d745f5e7b8b2961f68b0b9093a0f914a8a83c2ae Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 21 Mar 2016 14:41:58 +0100 Subject: [PATCH 0256/9938] ALSA: hda - Add the pin / port mapping on Intel ILK and VLV Intel IronLake and ValleyView platforms have different HDMI widget pin and digital port mapping from other newer ones. The recent ones (HSW+) have NID 0x05 to 0x07 for port B to port D, while these chips have NID 0x04 to 0x06. For adapting this mapping, pass the codec object instead of the bus object to snd_hdac_sync_audio_rate() and snd_hdac_acomp_get_eld() so that they can check the codec ID and calculate the mapping properly. The changes in the HDMI codec driver side will follow in the later patch. Signed-off-by: Takashi Iwai --- include/sound/hda_i915.h | 10 ++++----- sound/hda/hdac_i915.c | 45 ++++++++++++++++++++++++++++---------- sound/pci/hda/patch_hdmi.c | 4 ++-- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h index fa341fcb5829..eed87a7559b7 100644 --- a/include/sound/hda_i915.h +++ b/include/sound/hda_i915.h @@ -10,8 +10,8 @@ int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); int snd_hdac_display_power(struct hdac_bus *bus, bool enable); int snd_hdac_get_display_clk(struct hdac_bus *bus); -int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid, int rate); -int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid, +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int rate); +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, bool *audio_enabled, char *buffer, int max_bytes); int snd_hdac_i915_init(struct hdac_bus *bus); int snd_hdac_i915_exit(struct hdac_bus *bus); @@ -29,12 +29,12 @@ static inline int snd_hdac_get_display_clk(struct hdac_bus *bus) { return 0; } -static inline int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid, - int rate) +static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec, + hda_nid_t nid, int rate) { return 0; } -static inline int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid, +static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, bool *audio_enabled, char *buffer, int max_bytes) { diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index fb96aead8257..750a4ea49fa9 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -118,22 +118,40 @@ int snd_hdac_get_display_clk(struct hdac_bus *bus) } EXPORT_SYMBOL_GPL(snd_hdac_get_display_clk); -/* There is a fixed mapping between audio pin node and display port - * on current Intel platforms: +/* There is a fixed mapping between audio pin node and display port. + * on SNB, IVY, HSW, BSW, SKL, BXT, KBL: * Pin Widget 5 - PORT B (port = 1 in i915 driver) * Pin Widget 6 - PORT C (port = 2 in i915 driver) * Pin Widget 7 - PORT D (port = 3 in i915 driver) + * + * on VLV, ILK: + * Pin Widget 4 - PORT B (port = 1 in i915 driver) + * Pin Widget 5 - PORT C (port = 2 in i915 driver) + * Pin Widget 6 - PORT D (port = 3 in i915 driver) */ -static int pin2port(hda_nid_t pin_nid) +static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid) { - if (WARN_ON(pin_nid < 5 || pin_nid > 7)) + int base_nid; + + switch (codec->vendor_id) { + case 0x80860054: /* ILK */ + case 0x80862804: /* ILK */ + case 0x80862882: /* VLV */ + base_nid = 3; + break; + default: + base_nid = 4; + break; + } + + if (WARN_ON(pin_nid <= base_nid || pin_nid > base_nid + 3)) return -1; - return pin_nid - 4; + return pin_nid - base_nid; } /** * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate - * @bus: HDA core bus + * @codec: HDA codec * @nid: the pin widget NID * @rate: the sample rate to set * @@ -143,14 +161,15 @@ static int pin2port(hda_nid_t pin_nid) * This function sets N/CTS value based on the given sample rate. * Returns zero for success, or a negative error code. */ -int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid, int rate) +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int rate) { + struct hdac_bus *bus = codec->bus; struct i915_audio_component *acomp = bus->audio_component; int port; if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) return -ENODEV; - port = pin2port(nid); + port = pin2port(codec, nid); if (port < 0) return -EINVAL; return acomp->ops->sync_audio_rate(acomp->dev, port, rate); @@ -159,7 +178,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); /** * snd_hdac_acomp_get_eld - Get the audio state and ELD via component - * @bus: HDA core bus + * @codec: HDA codec * @nid: the pin widget NID * @audio_enabled: the pointer to store the current audio state * @buffer: the buffer pointer to store ELD bytes @@ -177,16 +196,17 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); * thus it may be over @max_bytes. If it's over @max_bytes, it implies * that only a part of ELD bytes have been fetched. */ -int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid, +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, bool *audio_enabled, char *buffer, int max_bytes) { + struct hdac_bus *bus = codec->bus; struct i915_audio_component *acomp = bus->audio_component; int port; if (!acomp || !acomp->ops || !acomp->ops->get_eld) return -ENODEV; - port = pin2port(nid); + port = pin2port(codec, nid); if (port < 0) return -EINVAL; return acomp->ops->get_eld(acomp->dev, port, audio_enabled, @@ -286,6 +306,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus) struct i915_audio_component *acomp; int ret; + if (WARN_ON(hdac_acomp)) + return -EBUSY; + acomp = kzalloc(sizeof(*acomp), GFP_KERNEL); if (!acomp) return -ENOMEM; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 09eb26c5730c..7e09f5e584c6 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1486,7 +1486,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec, mutex_lock(&per_pin->lock); eld->monitor_present = false; - size = snd_hdac_acomp_get_eld(&codec->bus->core, per_pin->pin_nid, + size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, &eld->monitor_present, eld->eld_buffer, ELD_MAX_SIZE); if (size > 0) { @@ -1740,7 +1740,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ /* Todo: add DP1.2 MST audio support later */ if (codec_has_acomp(codec)) - snd_hdac_sync_audio_rate(&codec->bus->core, pin_nid, runtime->rate); + snd_hdac_sync_audio_rate(&codec->core, pin_nid, runtime->rate); non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); mutex_lock(&per_pin->lock); -- GitLab From 7ff652ffc06afc7f81839fb1780c57470ac09db6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 21 Mar 2016 14:50:24 +0100 Subject: [PATCH 0257/9938] ALSA: hda - Enable i915 ELD notifier for Intel IronLake and Baytrail Since we have the fixed pin-port mapping for Intel IronLake (IbexPeak) and Baytrail (ValleyView) platforms in the code side, now it's time to add the support in the codec driver side. This patch simply enables the i915 ELD notifier for these in addition with the fix of the mapping from the port to NID in the callback. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 7e09f5e584c6..4833c7bdd1e8 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2274,12 +2274,23 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, static void intel_pin_eld_notify(void *audio_ptr, int port) { struct hda_codec *codec = audio_ptr; - int pin_nid = port + 0x04; + int pin_nid; /* we assume only from port-B to port-D */ if (port < 1 || port > 3) return; + switch (codec->core.vendor_id) { + case 0x80860054: /* ILK */ + case 0x80862804: /* ILK */ + case 0x80862882: /* VLV */ + pin_nid = port + 0x03; + break; + default: + pin_nid = port + 0x04; + break; + } + /* skip notification during system suspend (but not in runtime PM); * the state will be updated at resume */ @@ -2375,7 +2386,7 @@ static int patch_i915_hsw_hdmi(struct hda_codec *codec) return 0; } -/* Intel Baytrail and Braswell; without get_eld notifier */ +/* Intel Baytrail and Braswell; with eld notifier */ static int patch_i915_byt_hdmi(struct hda_codec *codec) { struct hdmi_spec *spec; @@ -2409,10 +2420,11 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) } generic_hdmi_init_per_pins(codec); + register_i915_notifier(codec); return 0; } -/* Intel SandyBridge and IvyBridge; with i915 eld notifier */ +/* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */ static int patch_i915_cpt_hdmi(struct hda_codec *codec) { struct hdmi_spec *spec; @@ -3614,11 +3626,11 @@ HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP", patch_via_hdmi), HDA_CODEC_ENTRY(0x11069f81, "VX900 HDMI/DP", patch_via_hdmi), HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP", patch_generic_hdmi), HDA_CODEC_ENTRY(0x11069f85, "VX11 HDMI/DP", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_i915_cpt_hdmi), HDA_CODEC_ENTRY(0x80862801, "Bearlake HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862802, "Cantiga HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862803, "Eaglelake HDMI", patch_generic_hdmi), -HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_i915_cpt_hdmi), HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_i915_cpt_hdmi), HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_i915_cpt_hdmi), HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_i915_hsw_hdmi), -- GitLab From 093dd449782737b50f8e1ee1608720dfd46d8ed2 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 27 Mar 2016 16:09:06 +0900 Subject: [PATCH 0258/9938] ALSA: bebob: remove needless argument from local function The 'vendor_id' argument is not used in the local function. Let's remove it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 3e4e0756e3fe..932901de255f 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -67,7 +67,7 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); #define MODEL_MAUDIO_PROJECTMIX 0x00010091 static int -name_device(struct snd_bebob *bebob, unsigned int vendor_id) +name_device(struct snd_bebob *bebob) { struct fw_device *fw_dev = fw_parent_device(bebob->unit); char vendor[24] = {0}; @@ -232,7 +232,7 @@ bebob_probe(struct fw_unit *unit, spin_lock_init(&bebob->lock); init_waitqueue_head(&bebob->hwdep_wait); - err = name_device(bebob, entry->vendor_id); + err = name_device(bebob); if (err < 0) goto error; -- GitLab From 329fec2f7f7ead9dcab0a08684c700a5c55f3884 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 27 Mar 2016 16:09:07 +0900 Subject: [PATCH 0259/9938] ALSA: oxfw: remove needless member from private structure In former commit, 'struct device_info' is obsoleted, whereas private structure still keeps a pointer to it. This commit remove the member. d6ce6bbd7d83('ALSA: oxfw: rename a structure so that it means backward compatibility to old drivers') Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index 9beecc214767..2c84714e9bbd 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -36,7 +36,6 @@ struct snd_oxfw { struct snd_card *card; struct fw_unit *unit; - const struct device_info *device_info; struct mutex mutex; spinlock_t lock; -- GitLab From 0655ac2f4089321766bb9af19586900ad6cef7bc Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 27 Mar 2016 16:09:08 +0900 Subject: [PATCH 0260/9938] ALSA: fireworks: move model quirk detection code to information parser Currently, model-specific quirks are detected out of information parser, however it's natural to detect it in the parser. This commit applies the idea. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c index 8f27b67503c8..8380fb572202 100644 --- a/sound/firewire/fireworks/fireworks.c +++ b/sound/firewire/fireworks/fireworks.c @@ -168,6 +168,17 @@ get_hardware_info(struct snd_efw *efw) sizeof(struct snd_efw_phys_grp) * hwinfo->phys_in_grp_count); memcpy(&efw->phys_out_grps, hwinfo->phys_out_grps, sizeof(struct snd_efw_phys_grp) * hwinfo->phys_out_grp_count); + + /* AudioFire8 (since 2009) and AudioFirePre8 */ + if (hwinfo->type == MODEL_ECHO_AUDIOFIRE_9) + efw->is_af9 = true; + /* These models uses the same firmware. */ + if (hwinfo->type == MODEL_ECHO_AUDIOFIRE_2 || + hwinfo->type == MODEL_ECHO_AUDIOFIRE_4 || + hwinfo->type == MODEL_ECHO_AUDIOFIRE_9 || + hwinfo->type == MODEL_GIBSON_RIP || + hwinfo->type == MODEL_GIBSON_GOLDTOP) + efw->is_fireworks3 = true; end: kfree(hwinfo); return err; @@ -248,16 +259,6 @@ efw_probe(struct fw_unit *unit, err = get_hardware_info(efw); if (err < 0) goto error; - /* AudioFire8 (since 2009) and AudioFirePre8 */ - if (entry->model_id == MODEL_ECHO_AUDIOFIRE_9) - efw->is_af9 = true; - /* These models uses the same firmware. */ - if (entry->model_id == MODEL_ECHO_AUDIOFIRE_2 || - entry->model_id == MODEL_ECHO_AUDIOFIRE_4 || - entry->model_id == MODEL_ECHO_AUDIOFIRE_9 || - entry->model_id == MODEL_GIBSON_RIP || - entry->model_id == MODEL_GIBSON_GOLDTOP) - efw->is_fireworks3 = true; snd_efw_proc_init(efw); -- GitLab From 25c0e953eb56168c05fed88fbad00f76e105e2c8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 27 Mar 2016 16:09:09 +0900 Subject: [PATCH 0261/9938] ALSA: firewire-tascam: add Kconfig entry for TASCAM FW-1804 I forgot it. Fixes: 3e78e1518e12('ALSA: firewire-tascam: add support for FW-1804') Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 2a779c2f63ab..ab894ed1ff67 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -134,6 +134,7 @@ config SND_FIREWIRE_TASCAM Say Y here to include support for TASCAM. * FW-1884 * FW-1082 + * FW-1804 To compile this driver as a module, choose M here: the module will be called snd-firewire-tascam. -- GitLab From e6e45420f41fc613569e8bb6d15e0472dc0ea1ab Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Mar 2016 14:18:03 +0100 Subject: [PATCH 0262/9938] iio: st_sensors: simplify buffer address handling The driver goes to some length to dynamically allocate an array to hold the channel addresses. However no ST sensor has more than three channels (x, y, z at most). Instead of kmalloc():ing and kfree():in the address array, just use a fixed array of three elements. Cc: Giuseppe Barba Signed-off-by: Linus Walleij Acked-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- .../iio/common/st_sensors/st_sensors_buffer.c | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index e18bc6782256..73764961feac 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -24,19 +24,13 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { - u8 *addr; + u8 addr[3]; /* no ST sensor has more than 3 channels */ int i, n = 0, len; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned int num_data_channels = sdata->num_data_channels; unsigned int byte_for_channel = indio_dev->channels[0].scan_type.storagebits >> 3; - addr = kmalloc(num_data_channels, GFP_KERNEL); - if (!addr) { - len = -ENOMEM; - goto st_sensors_get_buffer_element_error; - } - for (i = 0; i < num_data_channels; i++) { if (test_bit(i, indio_dev->active_scan_mask)) { addr[n] = indio_dev->channels[i].address; @@ -57,10 +51,8 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) u8 *rx_array; rx_array = kmalloc(byte_for_channel * num_data_channels, GFP_KERNEL); - if (!rx_array) { - len = -ENOMEM; - goto st_sensors_free_memory; - } + if (!rx_array) + return -ENOMEM; len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, addr[0], @@ -68,7 +60,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) rx_array, sdata->multiread_bit); if (len < 0) { kfree(rx_array); - goto st_sensors_free_memory; + return len; } for (i = 0; i < n * byte_for_channel; i++) { @@ -87,17 +79,11 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) buf, sdata->multiread_bit); break; default: - len = -EINVAL; - goto st_sensors_free_memory; - } - if (len != byte_for_channel * n) { - len = -EIO; - goto st_sensors_free_memory; + return -EINVAL; } + if (len != byte_for_channel * n) + return -EIO; -st_sensors_free_memory: - kfree(addr); -st_sensors_get_buffer_element_error: return len; } EXPORT_SYMBOL(st_sensors_get_buffer_element); -- GitLab From 51fadb985786929af9377245042b412302d2c9a2 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sat, 26 Mar 2016 12:50:24 -0700 Subject: [PATCH 0263/9938] staging: iio: convert bare unsigned usage to unsigned int Use kernel preferred unsigned int declaration style. Patch created using: git ls-files drivers/staging/iio | \ xargs ./scripts/checkpatch.pl -f --fix-inplace --types=unspecified_int Hand edits restored columns in structure definitions. Signed-off-by: Alison Schofield Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 40 +++++++++---------- drivers/staging/iio/adc/ad7280a.h | 8 ++-- drivers/staging/iio/adc/ad7606.h | 28 ++++++------- drivers/staging/iio/adc/ad7606_core.c | 6 +-- drivers/staging/iio/adc/ad7780.c | 2 +- .../staging/iio/impedance-analyzer/ad5933.c | 14 +++---- drivers/staging/iio/meter/ade7758_ring.c | 4 +- drivers/staging/iio/resolver/ad2s1210.h | 8 ++-- .../staging/iio/trigger/iio-trig-bfin-timer.c | 12 +++--- 9 files changed, 61 insertions(+), 61 deletions(-) diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 62e5ecacf634..a06b46cb81ca 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -155,7 +155,7 @@ static void ad7280_crc8_build_table(unsigned char *crc_tab) } } -static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val) +static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned int val) { unsigned char crc; @@ -165,7 +165,7 @@ static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val) return crc ^ (val & 0xFF); } -static int ad7280_check_crc(struct ad7280_state *st, unsigned val) +static int ad7280_check_crc(struct ad7280_state *st, unsigned int val) { unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10); @@ -191,7 +191,7 @@ static void ad7280_delay(struct ad7280_state *st) usleep_range(250, 500); } -static int __ad7280_read32(struct ad7280_state *st, unsigned *val) +static int __ad7280_read32(struct ad7280_state *st, unsigned int *val) { int ret; struct spi_transfer t = { @@ -211,10 +211,10 @@ static int __ad7280_read32(struct ad7280_state *st, unsigned *val) return 0; } -static int ad7280_write(struct ad7280_state *st, unsigned devaddr, - unsigned addr, bool all, unsigned val) +static int ad7280_write(struct ad7280_state *st, unsigned int devaddr, + unsigned int addr, bool all, unsigned int val) { - unsigned reg = devaddr << 27 | addr << 21 | + unsigned int reg = devaddr << 27 | addr << 21 | (val & 0xFF) << 13 | all << 12; reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; @@ -223,11 +223,11 @@ static int ad7280_write(struct ad7280_state *st, unsigned devaddr, return spi_write(st->spi, &st->buf[0], 4); } -static int ad7280_read(struct ad7280_state *st, unsigned devaddr, - unsigned addr) +static int ad7280_read(struct ad7280_state *st, unsigned int devaddr, + unsigned int addr) { int ret; - unsigned tmp; + unsigned int tmp; /* turns off the read operation on all parts */ ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, @@ -261,11 +261,11 @@ static int ad7280_read(struct ad7280_state *st, unsigned devaddr, return (tmp >> 13) & 0xFF; } -static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, - unsigned addr) +static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr, + unsigned int addr) { int ret; - unsigned tmp; + unsigned int tmp; ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2); if (ret) @@ -299,11 +299,11 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, return (tmp >> 11) & 0xFFF; } -static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, - unsigned *array) +static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt, + unsigned int *array) { int i, ret; - unsigned tmp, sum = 0; + unsigned int tmp, sum = 0; ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1, AD7280A_CELL_VOLTAGE_1 << 2); @@ -338,7 +338,7 @@ static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, static int ad7280_chain_setup(struct ad7280_state *st) { - unsigned val, n; + unsigned int val, n; int ret; ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1, @@ -401,7 +401,7 @@ static ssize_t ad7280_store_balance_sw(struct device *dev, struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); bool readin; int ret; - unsigned devaddr, ch; + unsigned int devaddr, ch; ret = strtobool(buf, &readin); if (ret) @@ -431,7 +431,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev, struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; - unsigned msecs; + unsigned int msecs; mutex_lock(&indio_dev->mlock); ret = ad7280_read(st, this_attr->address >> 8, @@ -602,7 +602,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7280_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned val; + unsigned int val; switch ((u32)this_attr->address) { case AD7280A_CELL_OVERVOLTAGE: @@ -683,7 +683,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; struct ad7280_state *st = iio_priv(indio_dev); - unsigned *channels; + unsigned int *channels; int i, ret; channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL); diff --git a/drivers/staging/iio/adc/ad7280a.h b/drivers/staging/iio/adc/ad7280a.h index 732347a9bce4..ccfb90d20e71 100644 --- a/drivers/staging/iio/adc/ad7280a.h +++ b/drivers/staging/iio/adc/ad7280a.h @@ -29,10 +29,10 @@ #define AD7280A_ALERT_REMOVE_AUX4_AUX5 BIT(1) struct ad7280_platform_data { - unsigned acquisition_time; - unsigned conversion_averaging; - unsigned chain_last_alert_ignore; - bool thermistor_term_en; + unsigned int acquisition_time; + unsigned int conversion_averaging; + unsigned int chain_last_alert_ignore; + bool thermistor_term_en; }; #endif /* IIO_ADC_AD7280_H_ */ diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index cca946924c58..39f50440d915 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -28,16 +28,16 @@ */ struct ad7606_platform_data { - unsigned default_os; - unsigned default_range; - unsigned gpio_convst; - unsigned gpio_reset; - unsigned gpio_range; - unsigned gpio_os0; - unsigned gpio_os1; - unsigned gpio_os2; - unsigned gpio_frstdata; - unsigned gpio_stby; + unsigned int default_os; + unsigned int default_range; + unsigned int gpio_convst; + unsigned int gpio_reset; + unsigned int gpio_range; + unsigned int gpio_os0; + unsigned int gpio_os1; + unsigned int gpio_os2; + unsigned int gpio_frstdata; + unsigned int gpio_stby; }; /** @@ -52,7 +52,7 @@ struct ad7606_chip_info { const char *name; u16 int_vref_mv; const struct iio_chan_spec *channels; - unsigned num_channels; + unsigned int num_channels; }; /** @@ -67,8 +67,8 @@ struct ad7606_state { struct work_struct poll_work; wait_queue_head_t wq_data_avail; const struct ad7606_bus_ops *bops; - unsigned range; - unsigned oversampling; + unsigned int range; + unsigned int oversampling; bool done; void __iomem *base_address; @@ -86,7 +86,7 @@ struct ad7606_bus_ops { }; struct iio_dev *ad7606_probe(struct device *dev, int irq, - void __iomem *base_address, unsigned id, + void __iomem *base_address, unsigned int id, const struct ad7606_bus_ops *bops); int ad7606_remove(struct iio_dev *indio_dev, int irq); int ad7606_reset(struct ad7606_state *st); diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index fe6caeee0843..6dbc811730ae 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -36,7 +36,7 @@ int ad7606_reset(struct ad7606_state *st) return -ENODEV; } -static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned ch) +static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) { struct ad7606_state *st = iio_priv(indio_dev); int ret; @@ -155,7 +155,7 @@ static ssize_t ad7606_show_oversampling_ratio(struct device *dev, return sprintf(buf, "%u\n", st->oversampling); } -static int ad7606_oversampling_get_index(unsigned val) +static int ad7606_oversampling_get_index(unsigned int val) { unsigned char supported[] = {0, 2, 4, 8, 16, 32, 64}; int i; @@ -446,7 +446,7 @@ static const struct iio_info ad7606_info_range = { struct iio_dev *ad7606_probe(struct device *dev, int irq, void __iomem *base_address, - unsigned id, + unsigned int id, const struct ad7606_bus_ops *bops) { struct ad7606_platform_data *pdata = dev->platform_data; diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index 1439cfdbb09c..c9a0c2aa602f 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -63,7 +63,7 @@ static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta, enum ad_sigma_delta_mode mode) { struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta); - unsigned val; + unsigned int val; switch (mode) { case AD_SD_MODE_SINGLE: diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index d1218d896725..65947d38edd7 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -93,14 +93,14 @@ struct ad5933_state { unsigned long mclk_hz; unsigned char ctrl_hb; unsigned char ctrl_lb; - unsigned range_avail[4]; + unsigned int range_avail[4]; unsigned short vref_mv; unsigned short settling_cycles; unsigned short freq_points; - unsigned freq_start; - unsigned freq_inc; - unsigned state; - unsigned poll_time_jiffies; + unsigned int freq_start; + unsigned int freq_inc; + unsigned int state; + unsigned int poll_time_jiffies; }; static struct ad5933_platform_data ad5933_default_pdata = { @@ -214,7 +214,7 @@ static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event) } static int ad5933_set_freq(struct ad5933_state *st, - unsigned reg, unsigned long freq) + unsigned int reg, unsigned long freq) { unsigned long long freqreg; union { @@ -274,7 +274,7 @@ static int ad5933_setup(struct ad5933_state *st) static void ad5933_calc_out_ranges(struct ad5933_state *st) { int i; - unsigned normalized_3v3[4] = {1980, 198, 383, 970}; + unsigned int normalized_3v3[4] = {1980, 198, 383, 970}; for (i = 0; i < 4; i++) st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300; diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index 9a24e0226f8b..a6b76d4b1c80 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -33,7 +33,7 @@ static int ade7758_spi_read_burst(struct iio_dev *indio_dev) return ret; } -static int ade7758_write_waveform_type(struct device *dev, unsigned type) +static int ade7758_write_waveform_type(struct device *dev, unsigned int type) { int ret; u8 reg; @@ -85,7 +85,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) **/ static int ade7758_ring_preenable(struct iio_dev *indio_dev) { - unsigned channel; + unsigned int channel; if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) return -EINVAL; diff --git a/drivers/staging/iio/resolver/ad2s1210.h b/drivers/staging/iio/resolver/ad2s1210.h index c7158f6e61c2..e9b2147701fc 100644 --- a/drivers/staging/iio/resolver/ad2s1210.h +++ b/drivers/staging/iio/resolver/ad2s1210.h @@ -12,9 +12,9 @@ #define _AD2S1210_H struct ad2s1210_platform_data { - unsigned sample; - unsigned a[2]; - unsigned res[2]; - bool gpioin; + unsigned int sample; + unsigned int a[2]; + unsigned int res[2]; + bool gpioin; }; #endif /* _AD2S1210_H */ diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 035dd456d7d6..aeafad41f9c0 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -55,12 +55,12 @@ static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = { }; struct bfin_tmr_state { - struct iio_trigger *trig; - struct bfin_timer *t; - unsigned timer_num; - bool output_enable; - unsigned int duty; - int irq; + struct iio_trigger *trig; + struct bfin_timer *t; + unsigned int timer_num; + bool output_enable; + unsigned int duty; + int irq; }; static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state) -- GitLab From 3b672623079bb3e5685b8549e514f2dfaa564406 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 28 Mar 2016 13:09:56 +0900 Subject: [PATCH 0264/9938] regulator: s2mps11: Fix invalid selector mask and voltages for buck9 The buck9 regulator of S2MPS11 PMIC had incorrect vsel_mask (0xff instead of 0x1f) thus reading entire register as buck9's voltage. This effectively caused regulator core to interpret values as higher voltages than they were and then to set real voltage much lower than intended. The buck9 provides power to other regulators, including LDO13 and LDO19 which supply the MMC2 (SD card). On Odroid XU3/XU4 the lower voltage caused SD card detection errors on Odroid XU3/XU4: mmc1: card never left busy state mmc1: error -110 whilst initialising SD card During driver probe the regulator core was checking whether initial voltage matches the constraints. With incorrect vsel_mask of 0xff and default value of 0x50, the core interpreted this as 5 V which is outside of constraints (3-3.775 V). Then the regulator core was adjusting the voltage to match the constraints. With incorrect vsel_mask this new voltage mapped to a vere low voltage in the driver. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Signed-off-by: Mark Brown Cc: --- drivers/regulator/s2mps11.c | 28 ++++++++++++++++++++++------ include/linux/mfd/samsung/s2mps11.h | 2 ++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index d24e2c783dc5..6dfa3502e1f1 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -308,7 +308,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_s2mps11_buck6_10(num, min, step) { \ +#define regulator_desc_s2mps11_buck67810(num, min, step) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num, \ .ops = &s2mps11_buck_ops, \ @@ -324,6 +324,22 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } +#define regulator_desc_s2mps11_buck9 { \ + .name = "BUCK9", \ + .id = S2MPS11_BUCK9, \ + .ops = &s2mps11_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MIN_3000_MV, \ + .uV_step = STEP_25_MV, \ + .n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ + .vsel_reg = S2MPS11_REG_B9CTRL2, \ + .vsel_mask = S2MPS11_BUCK9_VSEL_MASK, \ + .enable_reg = S2MPS11_REG_B9CTRL1, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} + static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_ldo(1, STEP_25_MV), regulator_desc_s2mps11_ldo(2, STEP_50_MV), @@ -368,11 +384,11 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck1_4(3), regulator_desc_s2mps11_buck1_4(4), regulator_desc_s2mps11_buck5, - regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV), - regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck9, + regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV), }; static struct regulator_ops s2mps14_reg_ops; diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index b288965e8101..2c14eeca46f0 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -173,10 +173,12 @@ enum s2mps11_regulators { #define S2MPS11_LDO_VSEL_MASK 0x3F #define S2MPS11_BUCK_VSEL_MASK 0xFF +#define S2MPS11_BUCK9_VSEL_MASK 0x1F #define S2MPS11_ENABLE_MASK (0x03 << S2MPS11_ENABLE_SHIFT) #define S2MPS11_ENABLE_SHIFT 0x06 #define S2MPS11_LDO_N_VOLTAGES (S2MPS11_LDO_VSEL_MASK + 1) #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) +#define S2MPS11_BUCK9_N_VOLTAGES (S2MPS11_BUCK9_VSEL_MASK + 1) #define S2MPS11_RAMP_DELAY 25000 /* uV/us */ #define S2MPS11_CTRL1_PWRHOLD_MASK BIT(4) -- GitLab From 2330b05c095bdeaaf1261c54cd2d4b9127496996 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Sat, 26 Mar 2016 10:28:13 +0200 Subject: [PATCH 0265/9938] regulator: twl: Make sure we have access to powerbus before trying to write to it According to the TRM, we need to enable i2c access to powerbus before writing to it. Also, a new write to powerbus should not be attempted if there is a pending transfer. The current code does not implement that functionality and while there are no known problems caused by that, it is better to follow what TRM says. Signed-off-by: Ivaylo Dimitrov Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 78 +++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 955a6fb1355c..aad748b00e1a 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -21,7 +21,7 @@ #include #include #include - +#include /* * The TWL4030/TW5030/TPS659x0/TWL6030 family chips include power management, a @@ -188,6 +188,74 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev) return grp && (val == TWL6030_CFG_STATE_ON); } +#define PB_I2C_BUSY BIT(0) +#define PB_I2C_BWEN BIT(1) + +/* Wait until buffer empty/ready to send a word on power bus. */ +static int twl4030_wait_pb_ready(void) +{ + + int ret; + int timeout = 10; + u8 val; + + do { + ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, + TWL4030_PM_MASTER_PB_CFG); + if (ret < 0) + return ret; + + if (!(val & PB_I2C_BUSY)) + return 0; + + mdelay(1); + timeout--; + } while (timeout); + + return -ETIMEDOUT; +} + +/* Send a word over the powerbus */ +static int twl4030_send_pb_msg(unsigned msg) +{ + u8 val; + int ret; + + /* save powerbus configuration */ + ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, + TWL4030_PM_MASTER_PB_CFG); + if (ret < 0) + return ret; + + /* Enable i2c access to powerbus */ + ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val | PB_I2C_BWEN, + TWL4030_PM_MASTER_PB_CFG); + if (ret < 0) + return ret; + + ret = twl4030_wait_pb_ready(); + if (ret < 0) + return ret; + + ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, msg >> 8, + TWL4030_PM_MASTER_PB_WORD_MSB); + if (ret < 0) + return ret; + + ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, msg & 0xff, + TWL4030_PM_MASTER_PB_WORD_LSB); + if (ret < 0) + return ret; + + ret = twl4030_wait_pb_ready(); + if (ret < 0) + return ret; + + /* Restore powerbus configuration */ + return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val, + TWL_MODULE_PM_MASTER); +} + static int twl4030reg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); @@ -324,13 +392,7 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030))) return -EACCES; - status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, - message >> 8, TWL4030_PM_MASTER_PB_WORD_MSB); - if (status < 0) - return status; - - return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, - message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB); + return twl4030_send_pb_msg(message); } static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) -- GitLab From 32e5deac3627a508f43806788dafa933b51d5d46 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Sat, 26 Mar 2016 10:28:15 +0200 Subject: [PATCH 0266/9938] regulator: twl: Regulator mode should not depend on regulator enabled state When machine constraints are applied, regulator framework first sets initial mode (if any) and then enables the regulator if needed. The current code in twl4030reg_set_mode always checks if the regulator is enabled before applying the mode. That results in -EACCES error returned for "always-on" regulators which have "initial-mode" set in the board DTS. Fix that by removing the unneeded check. Signed-off-by: Ivaylo Dimitrov Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index aad748b00e1a..7355616194ab 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -371,7 +371,6 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) { struct twlreg_info *info = rdev_get_drvdata(rdev); unsigned message; - int status; /* We can only set the mode through state machine commands... */ switch (mode) { @@ -385,13 +384,6 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) return -EINVAL; } - /* Ensure the resource is associated with some group */ - status = twlreg_grp(rdev); - if (status < 0) - return status; - if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030))) - return -EACCES; - return twl4030_send_pb_msg(message); } -- GitLab From 50314e55a140a0bc898d5f34b591e4e4ecedc75f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 25 Mar 2016 14:35:08 -0700 Subject: [PATCH 0267/9938] regulator: qcom_spmi: Add support for pm8994 Document the regulators available on pm8994 and add support for this PMIC to the SPMI PMIC regulator driver. Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- .../regulator/qcom,spmi-regulator.txt | 37 ++++++++++++++ drivers/regulator/qcom_spmi-regulator.c | 51 +++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt index d00bfd8624a5..46c6f3ed1a1c 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt @@ -7,6 +7,7 @@ Qualcomm SPMI Regulators "qcom,pm8841-regulators" "qcom,pm8916-regulators" "qcom,pm8941-regulators" + "qcom,pm8994-regulators" - interrupts: Usage: optional @@ -68,6 +69,37 @@ Qualcomm SPMI Regulators Definition: Reference to regulator supplying the input pin, as described in the data sheet. +- vdd_s1-supply: +- vdd_s2-supply: +- vdd_s3-supply: +- vdd_s4-supply: +- vdd_s5-supply: +- vdd_s6-supply: +- vdd_s7-supply: +- vdd_s8-supply: +- vdd_s9-supply: +- vdd_s10-supply: +- vdd_s11-supply: +- vdd_s12-supply: +- vdd_l1-supply: +- vdd_l2_l26_l28-supply: +- vdd_l3_l11-supply: +- vdd_l4_l27_l31-supply: +- vdd_l5_l7-supply: +- vdd_l6_l12_l32-supply: +- vdd_l8_l16_l30-supply: +- vdd_l9_l10_l18_l22-supply: +- vdd_l13_l19_l23_l24-supply: +- vdd_l14_l15-supply: +- vdd_l17_l29-supply: +- vdd_l20_l21-supply: +- vdd_l25-supply: +- vdd_lvs_1_2-supply: + Usage: optional (pm8994 only) + Value type: + Definition: Reference to regulator supplying the input pin, as + described in the data sheet. + The regulator node houses sub-nodes for each regulator within the device. Each sub-node is identified using the node's name, with valid values listed for each @@ -85,6 +117,11 @@ pm8941: l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3, mvs1, mvs2 +pm8994: + s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, l1, l2, l3, l4, l5, + l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, + l21, l22, l23, l24, l25, l26, l27, l28, l29, l30, l31, l32, lvs1, lvs2 + The content of each sub-node is defined by the standard binding for regulators - see regulator.txt - with additional custom properties described below: diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 88a5dc88badc..07689fd0c0b0 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -1510,10 +1510,61 @@ static const struct spmi_regulator_data pm8916_regulators[] = { { } }; +static const struct spmi_regulator_data pm8994_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s4", }, + { "s5", 0x2000, "vdd_s5", }, + { "s6", 0x2300, "vdd_s6", }, + { "s7", 0x2600, "vdd_s7", }, + { "s8", 0x2900, "vdd_s8", }, + { "s9", 0x2c00, "vdd_s9", }, + { "s10", 0x2f00, "vdd_s10", }, + { "s11", 0x3200, "vdd_s11", }, + { "s12", 0x3500, "vdd_s12", }, + { "l1", 0x4000, "vdd_l1", }, + { "l2", 0x4100, "vdd_l2_l26_l28", }, + { "l3", 0x4200, "vdd_l3_l11", }, + { "l4", 0x4300, "vdd_l4_l27_l31", }, + { "l5", 0x4400, "vdd_l5_l7", }, + { "l6", 0x4500, "vdd_l6_l12_l32", }, + { "l7", 0x4600, "vdd_l5_l7", }, + { "l8", 0x4700, "vdd_l8_l16_l30", }, + { "l9", 0x4800, "vdd_l9_l10_l18_l22", }, + { "l10", 0x4900, "vdd_l9_l10_l18_l22", }, + { "l11", 0x4a00, "vdd_l3_l11", }, + { "l12", 0x4b00, "vdd_l6_l12_l32", }, + { "l13", 0x4c00, "vdd_l13_l19_l23_l24", }, + { "l14", 0x4d00, "vdd_l14_l15", }, + { "l15", 0x4e00, "vdd_l14_l15", }, + { "l16", 0x4f00, "vdd_l8_l16_l30", }, + { "l17", 0x5000, "vdd_l17_l29", }, + { "l18", 0x5100, "vdd_l9_l10_l18_l22", }, + { "l19", 0x5200, "vdd_l13_l19_l23_l24", }, + { "l20", 0x5300, "vdd_l20_l21", }, + { "l21", 0x5400, "vdd_l20_l21", }, + { "l22", 0x5500, "vdd_l9_l10_l18_l22", }, + { "l23", 0x5600, "vdd_l13_l19_l23_l24", }, + { "l24", 0x5700, "vdd_l13_l19_l23_l24", }, + { "l25", 0x5800, "vdd_l25", }, + { "l26", 0x5900, "vdd_l2_l26_l28", }, + { "l27", 0x5a00, "vdd_l4_l27_l31", }, + { "l28", 0x5b00, "vdd_l2_l26_l28", }, + { "l29", 0x5c00, "vdd_l17_l29", }, + { "l30", 0x5d00, "vdd_l8_l16_l30", }, + { "l31", 0x5e00, "vdd_l4_l27_l31", }, + { "l32", 0x5f00, "vdd_l6_l12_l32", }, + { "lvs1", 0x8000, "vdd_lvs_1_2", }, + { "lvs2", 0x8100, "vdd_lvs_1_2", }, + { } +}; + static const struct of_device_id qcom_spmi_regulator_match[] = { { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, { .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators }, { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, + { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, { } }; MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); -- GitLab From 6ee5c04407f59122774c8da26f3ee8d6db9cec9b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 25 Mar 2016 14:35:09 -0700 Subject: [PATCH 0268/9938] regulator: qcom_spmi: Keep trying to add regulators if read fails On some designs, a handful of the regulators can't be read via SPMI transactions because they're "secure" and not intended to be touched by non-secure processors. This driver unconditionally attempts to read the id registers of all the regulators though, leading to probe failing and no regulators being registered. Let's ignore any errors from failing to read the registers and keep adding other regulators so that this driver can probe on such devices. Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 07689fd0c0b0..3550f7f7c2eb 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -1201,7 +1201,7 @@ static int spmi_regulator_match(struct spmi_regulator *vreg, u16 force_type) ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_DIG_MAJOR_REV, version, ARRAY_SIZE(version)); if (ret) { - dev_err(vreg->dev, "could not read version registers\n"); + dev_dbg(vreg->dev, "could not read version registers\n"); return ret; } dig_major_rev = version[SPMI_COMMON_REG_DIG_MAJOR_REV @@ -1624,7 +1624,7 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) ret = spmi_regulator_match(vreg, reg->force_type); if (ret) - goto err; + continue; config.dev = dev; config.driver_data = vreg; -- GitLab From 7d1f1bf699efc9b0f0e92c910dc667a4511943f5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 24 Mar 2016 15:35:42 +0200 Subject: [PATCH 0269/9938] spi: pxa2xx: handle error of pxa2xx_spi_dma_prepare() If by some reason pxa2xx_spi_dma_prepare() fails we have not to ignore its error. In such case we abort the transfer and return the error to upper level. Signed-off-by: Andy Shevchenko [Jarkko: Avoid leaking TX descriptors in case RX descriptor allocation fails. Noted by Robert Jarzmik . Unmap also buffers in case of failure.] Signed-off-by: Jarkko Nikula Acked-by: Robert Jarzmik Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-dma.c | 13 +++++++++++-- drivers/spi/spi-pxa2xx.c | 8 +++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 365fc22c3572..b1883d228103 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -267,19 +267,22 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data) int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst) { struct dma_async_tx_descriptor *tx_desc, *rx_desc; + int err = 0; tx_desc = pxa2xx_spi_dma_prepare_one(drv_data, DMA_MEM_TO_DEV); if (!tx_desc) { dev_err(&drv_data->pdev->dev, "failed to get DMA TX descriptor\n"); - return -EBUSY; + err = -EBUSY; + goto err_tx; } rx_desc = pxa2xx_spi_dma_prepare_one(drv_data, DMA_DEV_TO_MEM); if (!rx_desc) { dev_err(&drv_data->pdev->dev, "failed to get DMA RX descriptor\n"); - return -EBUSY; + err = -EBUSY; + goto err_rx; } /* We are ready when RX completes */ @@ -289,6 +292,12 @@ int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst) dmaengine_submit(rx_desc); dmaengine_submit(tx_desc); return 0; + +err_rx: + dmaengine_terminate_async(drv_data->tx_chan); +err_tx: + pxa2xx_spi_unmap_dma_buffers(drv_data); + return err; } void pxa2xx_spi_dma_start(struct driver_data *drv_data) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 85e59a406a4c..47bdbd350a24 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -928,6 +928,7 @@ static void pump_transfers(unsigned long data) u32 dma_thresh = drv_data->cur_chip->dma_threshold; u32 dma_burst = drv_data->cur_chip->dma_burst_size; u32 change_mask = pxa2xx_spi_get_ssrc1_change_mask(drv_data); + int err; /* Get current state information */ message = drv_data->cur_msg; @@ -1047,7 +1048,12 @@ static void pump_transfers(unsigned long data) /* Ensure we have the correct interrupt handler */ drv_data->transfer_handler = pxa2xx_spi_dma_transfer; - pxa2xx_spi_dma_prepare(drv_data, dma_burst); + err = pxa2xx_spi_dma_prepare(drv_data, dma_burst); + if (err) { + message->status = err; + giveback(drv_data); + return; + } /* Clear status and start DMA engine */ cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1; -- GitLab From 68335ec76e45fb3a1b796b26c3ea49ce1231d8fb Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 24 Mar 2016 15:35:43 +0200 Subject: [PATCH 0270/9938] spi: pxa2xx: Remove rx_/tx_map_len members from struct driver_data spi-pxa2xx-dma.c DMA engine implementation stopped using PIO for unaligned trailing bytes in the commit 111e0a9dc71e ("spi/pxa2xx: Prevent DMA from transferring too many bytes"). This means there is no need to update tx/rx transfer buffer pointers after DMA completion. These buffer pointers will be set to new buffers when handling the next transfer. Because this buffer pointer update was only remaining use for rx_map_len and tx_map_len members in struct driver_data after removing the legacy PXA DMA implementation they can be removed now. Signed-off-by: Jarkko Nikula Acked-by: Robert Jarzmik Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-dma.c | 5 ----- drivers/spi/spi-pxa2xx.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index b1883d228103..624cb06bd2e1 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -33,12 +33,10 @@ static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data, dmadev = drv_data->tx_chan->device->dev; sgt = &drv_data->tx_sgt; buf = drv_data->tx; - drv_data->tx_map_len = len; } else { dmadev = drv_data->rx_chan->device->dev; sgt = &drv_data->rx_sgt; buf = drv_data->rx; - drv_data->rx_map_len = len; } nents = DIV_ROUND_UP(len, SZ_2K); @@ -133,9 +131,6 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, if (!error) { pxa2xx_spi_unmap_dma_buffers(drv_data); - drv_data->tx += drv_data->tx_map_len; - drv_data->rx += drv_data->rx_map_len; - msg->actual_length += drv_data->len; msg->state = pxa2xx_spi_next_transfer(drv_data); } else { diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index a1ef88948144..85017f9ca67c 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -69,8 +69,6 @@ struct driver_data { void *rx; void *rx_end; int dma_mapped; - size_t rx_map_len; - size_t tx_map_len; u8 n_bytes; int (*write)(struct driver_data *drv_data); int (*read)(struct driver_data *drv_data); -- GitLab From 8c3ad488fe0e4478b3b29b9501074c5fb1bfda0d Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 24 Mar 2016 15:35:44 +0200 Subject: [PATCH 0271/9938] spi: pxa2xx: Use dummy buffers provided by SPI core Dummy buffer is used for half duplex transfers that don't have TX or RX buffer set. Instead of own dummy buffer management here let the SPI core to handle it by setting the SPI_MASTER_MUST_RX and SPI_MASTER_MUST_TX flags. Then core makes sure both transfer buffers are set. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-dma.c | 10 +--------- drivers/spi/spi-pxa2xx.c | 1 + drivers/spi/spi-pxa2xx.h | 1 - 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 624cb06bd2e1..a18a03d0afb7 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -53,11 +53,7 @@ static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data, for_each_sg(sgt->sgl, sg, sgt->nents, i) { size_t bytes = min_t(size_t, len, SZ_2K); - if (buf) - sg_set_buf(sg, pbuf, bytes); - else - sg_set_buf(sg, drv_data->dummy, bytes); - + sg_set_buf(sg, pbuf, bytes); pbuf += bytes; len -= bytes; } @@ -312,10 +308,6 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data) dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - drv_data->dummy = devm_kzalloc(dev, SZ_2K, GFP_KERNEL); - if (!drv_data->dummy) - return -ENOMEM; - drv_data->tx_chan = dma_request_slave_channel_compat(mask, pdata->dma_filter, pdata->tx_param, dev, "tx"); if (!drv_data->tx_chan) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 47bdbd350a24..86c155aea0cf 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1562,6 +1562,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer; master->fw_translate_cs = pxa2xx_spi_fw_translate_cs; master->auto_runtime_pm = true; + master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; drv_data->ssp_type = ssp->type; diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 85017f9ca67c..e6b09000ff14 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -56,7 +56,6 @@ struct driver_data { struct sg_table tx_sgt; int rx_nents; int tx_nents; - void *dummy; atomic_t dma_running; /* Current message transfer state info */ -- GitLab From 5e3ca2b349b1e2c80b060b51bbf2af37448fad85 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 23 Mar 2016 20:59:34 -0300 Subject: [PATCH 0272/9938] regulator: Try to resolve regulators supplies on registration Commit 6261b06de565 ("regulator: Defer lookup of supply to regulator_get") moved the regulator supplies lookup logic from the regulators registration to the regulators get time. Unfortunately, that changed the behavior of the regulator core since now a parent supply with a child regulator marked as always-on, won't be enabled unless a client driver attempts to get the child regulator during boot. This patch tries to resolve the parent supply for the already registered regulators each time that a new regulator is registered. So the regulators that have child regulators marked as always on will be enabled regardless if a driver gets the child regulator or not. That was the behavior before the mentioned commit, since parent supplies were looked up at regulator registration time instead of during child get. Since regulator_resolve_supply() checks for rdev->supply, most of the times it will be a no-op. Errors aren't checked to keep the possible out of order dependencies which was the motivation for the mentioned commit. Also, the supply being available will be enforced on regulator get anyways in case the resolve fails on regulators registration. Fixes: 6261b06de565 ("regulator: Defer lookup of supply to regulator_get") Suggested-by: Mark Brown Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown Cc: # 4.1+ --- drivers/regulator/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0b764284773..ab1838138877 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3840,6 +3840,11 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) &rdev->bypass_count); } +static int regulator_register_resolve_supply(struct device *dev, void *data) +{ + return regulator_resolve_supply(dev_to_rdev(dev)); +} + /** * regulator_register - register regulator * @regulator_desc: regulator to register @@ -3986,6 +3991,10 @@ regulator_register(const struct regulator_desc *regulator_desc, } rdev_init_debugfs(rdev); + + /* try to resolve regulators supply since a new one was registered */ + class_for_each_device(®ulator_class, NULL, NULL, + regulator_register_resolve_supply); out: mutex_unlock(®ulator_list_mutex); kfree(config); -- GitLab From 6aa841c8097fee1b17b343719c45694e3166ca34 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 10 Mar 2016 05:22:53 +0800 Subject: [PATCH 0273/9938] soc: rockchip: power-domain: make idle handling optional Not all new socs need to handle idle states on domain state changes, so add the possibility to make them optional. Signed-off-by: Elaine Zhang Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 43155e1f97b9..7ae7d84e6776 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -68,9 +68,9 @@ struct rockchip_pmu { { \ .pwr_mask = BIT(pwr), \ .status_mask = BIT(status), \ - .req_mask = BIT(req), \ - .idle_mask = BIT(idle), \ - .ack_mask = BIT(ack), \ + .req_mask = (req >= 0) ? BIT(req) : 0, \ + .idle_mask = (idle >= 0) ? BIT(idle) : 0, \ + .ack_mask = (ack >= 0) ? BIT(ack) : 0, \ } #define DOMAIN_RK3288(pwr, status, req) \ @@ -96,6 +96,9 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, struct rockchip_pmu *pmu = pd->pmu; unsigned int val; + if (pd_info->req_mask == 0) + return 0; + regmap_update_bits(pmu->regmap, pmu->info->req_offset, pd_info->req_mask, idle ? -1U : 0); -- GitLab From 1fe767a56c32730a947fc2bfcac5d14490bde6ff Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 10 Mar 2016 05:22:54 +0800 Subject: [PATCH 0274/9938] soc: rockchip: power-domain: allow domains only handling idle requests On some Rockchip SoC there exist child-domains only handling their idle state with the actual power-state handled by a (shared) parent- domain. So allow such types of domains. For them, we can determine their state (on/off) by checking the inverse idle-state instead. There exist one special case if both idle as well power handling were set as not present, but as the domain-data is defined in the code itself, we can expect the reasonable developer to define them in a correct way, without adding more checks. Signed-off-by: Elaine Zhang Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 7ae7d84e6776..fbad052c191a 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -66,8 +66,8 @@ struct rockchip_pmu { #define DOMAIN(pwr, status, req, idle, ack) \ { \ - .pwr_mask = BIT(pwr), \ - .status_mask = BIT(status), \ + .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \ + .status_mask = (status >= 0) ? BIT(status) : 0, \ .req_mask = (req >= 0) ? BIT(req) : 0, \ .idle_mask = (idle >= 0) ? BIT(idle) : 0, \ .ack_mask = (ack >= 0) ? BIT(ack) : 0, \ @@ -119,6 +119,10 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) struct rockchip_pmu *pmu = pd->pmu; unsigned int val; + /* check idle status for idle-only domains */ + if (pd->info->status_mask == 0) + return !rockchip_pmu_domain_is_idle(pd); + regmap_read(pmu->regmap, pmu->info->status_offset, &val); /* 1'b0: power on, 1'b1: power off */ @@ -130,6 +134,9 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, { struct rockchip_pmu *pmu = pd->pmu; + if (pd->info->pwr_mask == 0) + return; + regmap_update_bits(pmu->regmap, pmu->info->pwr_offset, pd->info->pwr_mask, on ? 0 : -1U); -- GitLab From ccd63c20fe834a3f98f46f0447e5f106c4ffa2a4 Mon Sep 17 00:00:00 2001 From: Weongyo Jeong Date: Tue, 15 Mar 2016 10:57:44 -0700 Subject: [PATCH 0275/9938] netfilter: nf_conntrack: Uses pr_fmt() for logging. Uses pr_fmt() macro for debugging messages of nf_conntrack module. Signed-off-by: Weongyo Jeong Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_core.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index afde5f5e728a..2fd607408998 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -12,6 +12,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -966,7 +968,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, if (!l4proto->new(ct, skb, dataoff, timeouts)) { nf_conntrack_free(ct); - pr_debug("init conntrack: can't track with proto module\n"); + pr_debug("can't track with proto module\n"); return NULL; } @@ -988,7 +990,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, spin_lock(&nf_conntrack_expect_lock); exp = nf_ct_find_expectation(net, zone, tuple); if (exp) { - pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", + pr_debug("expectation arrives ct=%p exp=%p\n", ct, exp); /* Welcome, Mr. Bond. We've been expecting you... */ __set_bit(IPS_EXPECTED_BIT, &ct->status); @@ -1053,7 +1055,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num, protonum, net, &tuple, l3proto, l4proto)) { - pr_debug("resolve_normal_ct: Can't get tuple\n"); + pr_debug("Can't get tuple\n"); return NULL; } @@ -1079,14 +1081,13 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, } else { /* Once we've had two way comms, always ESTABLISHED. */ if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { - pr_debug("nf_conntrack_in: normal packet for %p\n", ct); + pr_debug("normal packet for %p\n", ct); *ctinfo = IP_CT_ESTABLISHED; } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) { - pr_debug("nf_conntrack_in: related packet for %p\n", - ct); + pr_debug("related packet for %p\n", ct); *ctinfo = IP_CT_RELATED; } else { - pr_debug("nf_conntrack_in: new packet for %p\n", ct); + pr_debug("new packet for %p\n", ct); *ctinfo = IP_CT_NEW; } *set_reply = 0; -- GitLab From 6be05b5ec16132f3df3f1d857ab01e30f726b542 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 10 Mar 2016 05:22:55 +0800 Subject: [PATCH 0276/9938] soc: rockchip: power-domain: add support for sub-power domains This patch adds support for making one power domain a sub-domain of other domain. This is useful for modeling power dependences, which needs to have more than one power domain enabled to be operational. Signed-off-by: Elaine Zhang [restructured error handling in subdomain-addition] Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 63 +++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index fbad052c191a..c179de3cd514 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -370,6 +370,61 @@ static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu, regmap_write(pmu->regmap, domain_reg_offset + 4, count); } +static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, + struct device_node *parent) +{ + struct device_node *np; + struct generic_pm_domain *child_domain, *parent_domain; + int error; + + for_each_child_of_node(parent, np) { + u32 idx; + + error = of_property_read_u32(parent, "reg", &idx); + if (error) { + dev_err(pmu->dev, + "%s: failed to retrieve domain id (reg): %d\n", + parent->name, error); + goto err_out; + } + parent_domain = pmu->genpd_data.domains[idx]; + + error = rockchip_pm_add_one_domain(pmu, np); + if (error) { + dev_err(pmu->dev, "failed to handle node %s: %d\n", + np->name, error); + goto err_out; + } + + error = of_property_read_u32(np, "reg", &idx); + if (error) { + dev_err(pmu->dev, + "%s: failed to retrieve domain id (reg): %d\n", + np->name, error); + goto err_out; + } + child_domain = pmu->genpd_data.domains[idx]; + + error = pm_genpd_add_subdomain(parent_domain, child_domain); + if (error) { + dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n", + parent_domain->name, child_domain->name, error); + goto err_out; + } else { + dev_dbg(pmu->dev, "%s add subdomain: %s\n", + parent_domain->name, child_domain->name); + } + + rockchip_pm_add_subdomain(pmu, np); + } + + return 0; + +err_out: + of_node_put(np); + return error; +} + static int rockchip_pm_domain_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -436,6 +491,14 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev) of_node_put(node); goto err_out; } + + error = rockchip_pm_add_subdomain(pmu, node); + if (error < 0) { + dev_err(dev, "failed to handle subdomain node %s: %d\n", + node->name, error); + of_node_put(node); + goto err_out; + } } if (error) { -- GitLab From 86e6e64be72be95debac65aa4d2118bd70982ee9 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 10 Mar 2016 05:22:56 +0800 Subject: [PATCH 0277/9938] dt-bindings: add power-domain header for RK3399 SoCs According to a description from TRM, add all the power domains Signed-off-by: Elaine Zhang Signed-off-by: Heiko Stuebner --- include/dt-bindings/power/rk3399-power.h | 53 ++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 include/dt-bindings/power/rk3399-power.h diff --git a/include/dt-bindings/power/rk3399-power.h b/include/dt-bindings/power/rk3399-power.h new file mode 100644 index 000000000000..168b3bfbd6f5 --- /dev/null +++ b/include/dt-bindings/power/rk3399-power.h @@ -0,0 +1,53 @@ +#ifndef __DT_BINDINGS_POWER_RK3399_POWER_H__ +#define __DT_BINDINGS_POWER_RK3399_POWER_H__ + +/* VD_CORE_L */ +#define RK3399_PD_A53_L0 0 +#define RK3399_PD_A53_L1 1 +#define RK3399_PD_A53_L2 2 +#define RK3399_PD_A53_L3 3 +#define RK3399_PD_SCU_L 4 + +/* VD_CORE_B */ +#define RK3399_PD_A72_B0 5 +#define RK3399_PD_A72_B1 6 +#define RK3399_PD_SCU_B 7 + +/* VD_LOGIC */ +#define RK3399_PD_TCPD0 8 +#define RK3399_PD_TCPD1 9 +#define RK3399_PD_CCI 10 +#define RK3399_PD_CCI0 11 +#define RK3399_PD_CCI1 12 +#define RK3399_PD_PERILP 13 +#define RK3399_PD_PERIHP 14 +#define RK3399_PD_VIO 15 +#define RK3399_PD_VO 16 +#define RK3399_PD_VOPB 17 +#define RK3399_PD_VOPL 18 +#define RK3399_PD_ISP0 19 +#define RK3399_PD_ISP1 20 +#define RK3399_PD_HDCP 21 +#define RK3399_PD_GMAC 22 +#define RK3399_PD_EMMC 23 +#define RK3399_PD_USB3 24 +#define RK3399_PD_EDP 25 +#define RK3399_PD_GIC 26 +#define RK3399_PD_SD 27 +#define RK3399_PD_SDIOAUDIO 28 +#define RK3399_PD_ALIVE 29 + +/* VD_CENTER */ +#define RK3399_PD_CENTER 30 +#define RK3399_PD_VCODEC 31 +#define RK3399_PD_VDU 32 +#define RK3399_PD_RGA 33 +#define RK3399_PD_IEP 34 + +/* VD_GPU */ +#define RK3399_PD_GPU 35 + +/* VD_PMU */ +#define RK3399_PD_PMU 36 + +#endif -- GitLab From e6e270aecbb0ed605b7267fdf6f828945014de24 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 10 Mar 2016 05:24:21 +0800 Subject: [PATCH 0278/9938] dt-bindings: add binding for rk3399 power domains Add binding documentation for the power domains found on Rockchip RK3399 SoCs Signed-off-by: Elaine Zhang Acked-by: Kevin Hilman Signed-off-by: Heiko Stuebner --- .../bindings/soc/rockchip/power_domain.txt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt index 13dc6a3fdb4a..98085c888d65 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt +++ b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt @@ -7,6 +7,7 @@ Required properties for power domain controller: - compatible: Should be one of the following. "rockchip,rk3288-power-controller" - for RK3288 SoCs. "rockchip,rk3368-power-controller" - for RK3368 SoCs. + "rockchip,rk3399-power-controller" - for RK3399 SoCs. - #power-domain-cells: Number of cells in a power-domain specifier. Should be 1 for multiple PM domains. - #address-cells: Should be 1. @@ -16,6 +17,7 @@ Required properties for power domain sub nodes: - reg: index of the power domain, should use macros in: "include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain. "include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain. + "include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain. - clocks (optional): phandles to clocks which need to be enabled while power domain switches state. @@ -45,12 +47,41 @@ Example: }; }; +Example 2: + power: power-controller { + compatible = "rockchip,rk3399-power-controller"; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + pd_vio { + #address-cells = <1>; + #size-cells = <0>; + reg = ; + + pd_vo { + #address-cells = <1>; + #size-cells = <0>; + reg = ; + + pd_vopb { + reg = ; + }; + + pd_vopl { + reg = ; + }; + }; + }; + }; + Node of a device using power domains must have a power-domains property, containing a phandle to the power device node and an index specifying which power domain to use. The index should use macros in: "include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain. "include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain. + "include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain. Example of the node using power domain: @@ -65,3 +96,9 @@ Example of the node using power domain: power-domains = <&power RK3368_PD_GPU_1>; /* ... */ }; + + node { + /* ... */ + power-domains = <&power RK3399_PD_VOPB>; + /* ... */ + }; -- GitLab From fd8b62cc38b356bcdf20ac8f1a647db7b11240cf Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 10 Mar 2016 05:24:38 +0800 Subject: [PATCH 0279/9938] soc: rockchip: power-domain: Modify power domain driver for rk3399 This driver is modified to support RK3399 SoC. Signed-off-by: Elaine Zhang [small indentation fixups] Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 55 +++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index c179de3cd514..2116131528f7 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -19,6 +19,7 @@ #include #include #include +#include struct rockchip_domain_info { int pwr_mask; @@ -79,6 +80,9 @@ struct rockchip_pmu { #define DOMAIN_RK3368(pwr, status, req) \ DOMAIN(pwr, status, req, (req) + 16, req) +#define DOMAIN_RK3399(pwr, status, req) \ + DOMAIN(pwr, status, req, req, req) + static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) { struct rockchip_pmu *pmu = pd->pmu; @@ -530,6 +534,36 @@ static const struct rockchip_domain_info rk3368_pm_domains[] = { [RK3368_PD_GPU_1] = DOMAIN_RK3368(17, 16, 2), }; +static const struct rockchip_domain_info rk3399_pm_domains[] = { + [RK3399_PD_TCPD0] = DOMAIN_RK3399(8, 8, -1), + [RK3399_PD_TCPD1] = DOMAIN_RK3399(9, 9, -1), + [RK3399_PD_CCI] = DOMAIN_RK3399(10, 10, -1), + [RK3399_PD_CCI0] = DOMAIN_RK3399(-1, -1, 15), + [RK3399_PD_CCI1] = DOMAIN_RK3399(-1, -1, 16), + [RK3399_PD_PERILP] = DOMAIN_RK3399(11, 11, 1), + [RK3399_PD_PERIHP] = DOMAIN_RK3399(12, 12, 2), + [RK3399_PD_CENTER] = DOMAIN_RK3399(13, 13, 14), + [RK3399_PD_VIO] = DOMAIN_RK3399(14, 14, 17), + [RK3399_PD_GPU] = DOMAIN_RK3399(15, 15, 0), + [RK3399_PD_VCODEC] = DOMAIN_RK3399(16, 16, 3), + [RK3399_PD_VDU] = DOMAIN_RK3399(17, 17, 4), + [RK3399_PD_RGA] = DOMAIN_RK3399(18, 18, 5), + [RK3399_PD_IEP] = DOMAIN_RK3399(19, 19, 6), + [RK3399_PD_VO] = DOMAIN_RK3399(20, 20, -1), + [RK3399_PD_VOPB] = DOMAIN_RK3399(-1, -1, 7), + [RK3399_PD_VOPL] = DOMAIN_RK3399(-1, -1, 8), + [RK3399_PD_ISP0] = DOMAIN_RK3399(22, 22, 9), + [RK3399_PD_ISP1] = DOMAIN_RK3399(23, 23, 10), + [RK3399_PD_HDCP] = DOMAIN_RK3399(24, 24, 11), + [RK3399_PD_GMAC] = DOMAIN_RK3399(25, 25, 23), + [RK3399_PD_EMMC] = DOMAIN_RK3399(26, 26, 24), + [RK3399_PD_USB3] = DOMAIN_RK3399(27, 27, 12), + [RK3399_PD_EDP] = DOMAIN_RK3399(28, 28, 22), + [RK3399_PD_GIC] = DOMAIN_RK3399(29, 29, 27), + [RK3399_PD_SD] = DOMAIN_RK3399(30, 30, 28), + [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399(31, 31, 29), +}; + static const struct rockchip_pmu_info rk3288_pmu = { .pwr_offset = 0x08, .status_offset = 0x0c, @@ -564,6 +598,23 @@ static const struct rockchip_pmu_info rk3368_pmu = { .domain_info = rk3368_pm_domains, }; +static const struct rockchip_pmu_info rk3399_pmu = { + .pwr_offset = 0x14, + .status_offset = 0x18, + .req_offset = 0x60, + .idle_offset = 0x64, + .ack_offset = 0x68, + + .core_pwrcnt_offset = 0x9c, + .gpu_pwrcnt_offset = 0xa4, + + .core_power_transition_time = 24, + .gpu_power_transition_time = 24, + + .num_domains = ARRAY_SIZE(rk3399_pm_domains), + .domain_info = rk3399_pm_domains, +}; + static const struct of_device_id rockchip_pm_domain_dt_match[] = { { .compatible = "rockchip,rk3288-power-controller", @@ -573,6 +624,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = { .compatible = "rockchip,rk3368-power-controller", .data = (void *)&rk3368_pmu, }, + { + .compatible = "rockchip,rk3399-power-controller", + .data = (void *)&rk3399_pmu, + }, { /* sentinel */ }, }; -- GitLab From f35f622536b8279574edc1b3d82f8f35ddd89132 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Mon, 28 Mar 2016 17:51:36 +0800 Subject: [PATCH 0280/9938] clk: rockchip: add dt-binding header for rk3399 Add the dt-bindings header for the rk3399, that gets shared between the clock controller and the clock references in the dts. Signed-off-by: Xing Zheng Signed-off-by: Jianqun Xu Acked-by: Rob Herring Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3399-cru.h | 752 +++++++++++++++++++++++++ 1 file changed, 752 insertions(+) create mode 100644 include/dt-bindings/clock/rk3399-cru.h diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h new file mode 100644 index 000000000000..244746e7dc4c --- /dev/null +++ b/include/dt-bindings/clock/rk3399-cru.h @@ -0,0 +1,752 @@ +/* + * Copyright (c) 2016 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3399_H +#define _DT_BINDINGS_CLK_ROCKCHIP_RK3399_H + +/* core clocks */ +#define PLL_APLLL 1 +#define PLL_APLLB 2 +#define PLL_DPLL 3 +#define PLL_CPLL 4 +#define PLL_GPLL 5 +#define PLL_NPLL 6 +#define PLL_VPLL 7 +#define ARMCLKL 8 +#define ARMCLKB 9 + +/* sclk gates (special clocks) */ +#define SCLK_I2C1 65 +#define SCLK_I2C2 66 +#define SCLK_I2C3 67 +#define SCLK_I2C5 68 +#define SCLK_I2C6 69 +#define SCLK_I2C7 70 +#define SCLK_SPI0 71 +#define SCLK_SPI1 72 +#define SCLK_SPI2 73 +#define SCLK_SPI4 74 +#define SCLK_SPI5 75 +#define SCLK_SDMMC 76 +#define SCLK_SDIO 77 +#define SCLK_EMMC 78 +#define SCLK_TSADC 79 +#define SCLK_SARADC 80 +#define SCLK_UART0 81 +#define SCLK_UART1 82 +#define SCLK_UART2 83 +#define SCLK_UART3 84 +#define SCLK_SPDIF_8CH 85 +#define SCLK_I2S0_8CH 86 +#define SCLK_I2S1_8CH 87 +#define SCLK_I2S2_8CH 88 +#define SCLK_I2S_8CH_OUT 89 +#define SCLK_TIMER00 90 +#define SCLK_TIMER01 91 +#define SCLK_TIMER02 92 +#define SCLK_TIMER03 93 +#define SCLK_TIMER04 94 +#define SCLK_TIMER05 95 +#define SCLK_TIMER06 96 +#define SCLK_TIMER07 97 +#define SCLK_TIMER08 98 +#define SCLK_TIMER09 99 +#define SCLK_TIMER10 100 +#define SCLK_TIMER11 101 +#define SCLK_MACREF 102 +#define SCLK_MAC_RX 103 +#define SCLK_MAC_TX 104 +#define SCLK_MAC 105 +#define SCLK_MACREF_OUT 106 +#define SCLK_VOP0_PWM 107 +#define SCLK_VOP1_PWM 108 +#define SCLK_RGA 109 +#define SCLK_ISP0 110 +#define SCLK_ISP1 111 +#define SCLK_HDMI_CEC 112 +#define SCLK_HDMI_SFR 113 +#define SCLK_DP_CORE 114 +#define SCLK_PVTM_CORE_L 115 +#define SCLK_PVTM_CORE_B 116 +#define SCLK_PVTM_GPU 117 +#define SCLK_PVTM_DDR 118 +#define SCLK_MIPIDPHY_REF 119 +#define SCLK_MIPIDPHY_CFG 120 +#define SCLK_HSICPHY 121 +#define SCLK_USBPHY480M 122 +#define SCLK_USB2PHY0_REF 123 +#define SCLK_USB2PHY1_REF 124 +#define SCLK_UPHY0_TCPDPHY_REF 125 +#define SCLK_UPHY0_TCPDCORE 126 +#define SCLK_UPHY1_TCPDPHY_REF 127 +#define SCLK_UPHY1_TCPDCORE 128 +#define SCLK_USB3OTG0_REF 129 +#define SCLK_USB3OTG1_REF 130 +#define SCLK_USB3OTG0_SUSPEND 131 +#define SCLK_USB3OTG1_SUSPEND 132 +#define SCLK_CRYPTO0 133 +#define SCLK_CRYPTO1 134 +#define SCLK_CCI_TRACE 135 +#define SCLK_CS 136 +#define SCLK_CIF_OUT 137 +#define SCLK_PCIEPHY_REF 138 +#define SCLK_PCIE_CORE 139 +#define SCLK_M0_PERILP 140 +#define SCLK_M0_PERILP_DEC 141 +#define SCLK_CM0S 142 +#define SCLK_DBG_NOC 143 +#define SCLK_DBG_PD_CORE_B 144 +#define SCLK_DBG_PD_CORE_L 145 +#define SCLK_DFIMON0_TIMER 146 +#define SCLK_DFIMON1_TIMER 147 +#define SCLK_INTMEM0 148 +#define SCLK_INTMEM1 149 +#define SCLK_INTMEM2 150 +#define SCLK_INTMEM3 151 +#define SCLK_INTMEM4 152 +#define SCLK_INTMEM5 153 +#define SCLK_SDMMC_DRV 154 +#define SCLK_SDMMC_SAMPLE 155 +#define SCLK_SDIO_DRV 156 +#define SCLK_SDIO_SAMPLE 157 +#define SCLK_VDU_CORE 158 +#define SCLK_VDU_CA 159 +#define SCLK_PCIE_PM 160 +#define SCLK_SPDIF_REC_DPTX 161 +#define SCLK_DPHY_PLL 162 +#define SCLK_DPHY_TX0_CFG 163 +#define SCLK_DPHY_TX1RX1_CFG 164 +#define SCLK_DPHY_RX0_CFG 165 + +#define DCLK_VOP0 180 +#define DCLK_VOP1 181 +#define DCLK_VOP0_DIV 182 +#define DCLK_VOP1_DIV 183 +#define DCLK_M0_PERILP 184 + +#define FCLK_CM0S 190 + +/* aclk gates */ +#define ACLK_PERIHP 192 +#define ACLK_PERIHP_NOC 193 +#define ACLK_PERILP0 194 +#define ACLK_PERILP0_NOC 195 +#define ACLK_PERF_PCIE 196 +#define ACLK_PCIE 197 +#define ACLK_INTMEM 198 +#define ACLK_TZMA 199 +#define ACLK_DCF 200 +#define ACLK_CCI 201 +#define ACLK_CCI_NOC0 202 +#define ACLK_CCI_NOC1 203 +#define ACLK_CCI_GRF 204 +#define ACLK_CENTER 205 +#define ACLK_CENTER_MAIN_NOC 206 +#define ACLK_CENTER_PERI_NOC 207 +#define ACLK_GPU 208 +#define ACLK_PERF_GPU 209 +#define ACLK_GPU_GRF 210 +#define ACLK_DMAC0_PERILP 211 +#define ACLK_DMAC1_PERILP 212 +#define ACLK_GMAC 213 +#define ACLK_GMAC_NOC 214 +#define ACLK_PERF_GMAC 215 +#define ACLK_VOP0_NOC 216 +#define ACLK_VOP0 217 +#define ACLK_VOP1_NOC 218 +#define ACLK_VOP1 219 +#define ACLK_RGA 220 +#define ACLK_RGA_NOC 221 +#define ACLK_HDCP 222 +#define ACLK_HDCP_NOC 223 +#define ACLK_HDCP22 224 +#define ACLK_IEP 225 +#define ACLK_IEP_NOC 226 +#define ACLK_VIO 227 +#define ACLK_VIO_NOC 228 +#define ACLK_ISP0 229 +#define ACLK_ISP1 230 +#define ACLK_ISP0_NOC 231 +#define ACLK_ISP1_NOC 232 +#define ACLK_ISP0_WRAPPER 233 +#define ACLK_ISP1_WRAPPER 234 +#define ACLK_VCODEC 235 +#define ACLK_VCODEC_NOC 236 +#define ACLK_VDU 237 +#define ACLK_VDU_NOC 238 +#define ACLK_PERI 239 +#define ACLK_EMMC 240 +#define ACLK_EMMC_CORE 241 +#define ACLK_EMMC_NOC 242 +#define ACLK_EMMC_GRF 243 +#define ACLK_USB3 244 +#define ACLK_USB3_NOC 245 +#define ACLK_USB3OTG0 246 +#define ACLK_USB3OTG1 247 +#define ACLK_USB3_RKSOC_AXI_PERF 248 +#define ACLK_USB3_GRF 249 +#define ACLK_GIC 250 +#define ACLK_GIC_NOC 251 +#define ACLK_GIC_ADB400_CORE_L_2_GIC 252 +#define ACLK_GIC_ADB400_CORE_B_2_GIC 253 +#define ACLK_GIC_ADB400_GIC_2_CORE_L 254 +#define ACLK_GIC_ADB400_GIC_2_CORE_B 255 +#define ACLK_CORE_ADB400_CORE_L_2_CCI500 256 +#define ACLK_CORE_ADB400_CORE_B_2_CCI500 257 +#define ACLK_ADB400M_PD_CORE_L 258 +#define ACLK_ADB400M_PD_CORE_B 259 +#define ACLK_PERF_CORE_L 260 +#define ACLK_PERF_CORE_B 261 +#define ACLK_GIC_PRE 262 +#define ACLK_VOP0_PRE 263 +#define ACLK_VOP1_PRE 264 + +/* pclk gates */ +#define PCLK_PERIHP 320 +#define PCLK_PERIHP_NOC 321 +#define PCLK_PERILP0 322 +#define PCLK_PERILP1 323 +#define PCLK_PERILP1_NOC 324 +#define PCLK_PERILP_SGRF 325 +#define PCLK_PERIHP_GRF 326 +#define PCLK_PCIE 327 +#define PCLK_SGRF 328 +#define PCLK_INTR_ARB 329 +#define PCLK_CENTER_MAIN_NOC 330 +#define PCLK_CIC 331 +#define PCLK_COREDBG_B 332 +#define PCLK_COREDBG_L 333 +#define PCLK_DBG_CXCS_PD_CORE_B 334 +#define PCLK_DCF 335 +#define PCLK_GPIO2 336 +#define PCLK_GPIO3 337 +#define PCLK_GPIO4 338 +#define PCLK_GRF 339 +#define PCLK_HSICPHY 340 +#define PCLK_I2C1 341 +#define PCLK_I2C2 342 +#define PCLK_I2C3 343 +#define PCLK_I2C5 344 +#define PCLK_I2C6 345 +#define PCLK_I2C7 346 +#define PCLK_SPI0 347 +#define PCLK_SPI1 348 +#define PCLK_SPI2 349 +#define PCLK_SPI4 350 +#define PCLK_SPI5 351 +#define PCLK_UART0 352 +#define PCLK_UART1 353 +#define PCLK_UART2 354 +#define PCLK_UART3 355 +#define PCLK_TSADC 356 +#define PCLK_SARADC 357 +#define PCLK_GMAC 358 +#define PCLK_GMAC_NOC 359 +#define PCLK_TIMER0 360 +#define PCLK_TIMER1 361 +#define PCLK_EDP 362 +#define PCLK_EDP_NOC 363 +#define PCLK_EDP_CTRL 364 +#define PCLK_VIO 365 +#define PCLK_VIO_NOC 366 +#define PCLK_VIO_GRF 367 +#define PCLK_MIPI_DSI0 368 +#define PCLK_MIPI_DSI1 369 +#define PCLK_HDCP 370 +#define PCLK_HDCP_NOC 371 +#define PCLK_HDMI_CTRL 372 +#define PCLK_DP_CTRL 373 +#define PCLK_HDCP22 374 +#define PCLK_GASKET 375 +#define PCLK_DDR 376 +#define PCLK_DDR_MON 377 +#define PCLK_DDR_SGRF 378 +#define PCLK_ISP1_WRAPPER 379 +#define PCLK_WDT 380 +#define PCLK_EFUSE1024NS 381 +#define PCLK_EFUSE1024S 382 +#define PCLK_PMU_INTR_ARB 383 +#define PCLK_MAILBOX0 384 +#define PCLK_USBPHY_MUX_G 385 +#define PCLK_UPHY0_TCPHY_G 386 +#define PCLK_UPHY0_TCPD_G 387 +#define PCLK_UPHY1_TCPHY_G 388 +#define PCLK_UPHY1_TCPD_G 389 +#define PCLK_ALIVE 390 + +/* hclk gates */ +#define HCLK_PERIHP 448 +#define HCLK_PERILP0 449 +#define HCLK_PERILP1 450 +#define HCLK_PERILP0_NOC 451 +#define HCLK_PERILP1_NOC 452 +#define HCLK_M0_PERILP 453 +#define HCLK_M0_PERILP_NOC 454 +#define HCLK_AHB1TOM 455 +#define HCLK_HOST0 456 +#define HCLK_HOST0_ARB 457 +#define HCLK_HOST1 458 +#define HCLK_HOST1_ARB 459 +#define HCLK_HSIC 460 +#define HCLK_SD 461 +#define HCLK_SDMMC 462 +#define HCLK_SDMMC_NOC 463 +#define HCLK_M_CRYPTO0 464 +#define HCLK_M_CRYPTO1 465 +#define HCLK_S_CRYPTO0 466 +#define HCLK_S_CRYPTO1 467 +#define HCLK_I2S0_8CH 468 +#define HCLK_I2S1_8CH 469 +#define HCLK_I2S2_8CH 470 +#define HCLK_SPDIF 471 +#define HCLK_VOP0_NOC 472 +#define HCLK_VOP0 473 +#define HCLK_VOP1_NOC 474 +#define HCLK_VOP1 475 +#define HCLK_ROM 476 +#define HCLK_IEP 477 +#define HCLK_IEP_NOC 478 +#define HCLK_ISP0 479 +#define HCLK_ISP1 480 +#define HCLK_ISP0_NOC 481 +#define HCLK_ISP1_NOC 482 +#define HCLK_ISP0_WRAPPER 483 +#define HCLK_ISP1_WRAPPER 484 +#define HCLK_RGA 485 +#define HCLK_RGA_NOC 486 +#define HCLK_HDCP 487 +#define HCLK_HDCP_NOC 488 +#define HCLK_HDCP22 489 +#define HCLK_VCODEC 490 +#define HCLK_VCODEC_NOC 491 +#define HCLK_VDU 492 +#define HCLK_VDU_NOC 493 +#define HCLK_SDIO 494 +#define HCLK_SDIO_NOC 495 +#define HCLK_SDIOAUDIO_NOC 496 + +#define CLK_NR_CLKS (HCLK_SDIOAUDIO_NOC + 1) + +/* pmu-clocks indices */ + +#define PLL_PPLL 1 + +#define SCLK_32K_SUSPEND_PMU 2 +#define SCLK_SPI3_PMU 3 +#define SCLK_TIMER12_PMU 4 +#define SCLK_TIMER13_PMU 5 +#define SCLK_UART4_PMU 6 +#define SCLK_PVTM_PMU 7 +#define SCLK_WIFI_PMU 8 +#define SCLK_I2C0_PMU 9 +#define SCLK_I2C4_PMU 10 +#define SCLK_I2C8_PMU 11 + +#define PCLK_SRC_PMU 19 +#define PCLK_PMU 20 +#define PCLK_PMUGRF_PMU 21 +#define PCLK_INTMEM1_PMU 22 +#define PCLK_GPIO0_PMU 23 +#define PCLK_GPIO1_PMU 24 +#define PCLK_SGRF_PMU 25 +#define PCLK_NOC_PMU 26 +#define PCLK_I2C0_PMU 27 +#define PCLK_I2C4_PMU 28 +#define PCLK_I2C8_PMU 29 +#define PCLK_RKPWM_PMU 30 +#define PCLK_SPI3_PMU 31 +#define PCLK_TIMER_PMU 32 +#define PCLK_MAILBOX_PMU 33 +#define PCLK_UART4_PMU 34 +#define PCLK_WDT_M0_PMU 35 + +#define FCLK_CM0S_SRC_PMU 44 +#define FCLK_CM0S_PMU 45 +#define SCLK_CM0S_PMU 46 +#define HCLK_CM0S_PMU 47 +#define DCLK_CM0S_PMU 48 +#define PCLK_INTR_ARB_PMU 49 +#define HCLK_NOC_PMU 50 + +#define CLKPMU_NR_CLKS (HCLK_NOC_PMU + 1) + +/* soft-reset indices */ + +/* cru_softrst_con0 */ +#define SRST_CORE_L0 0 +#define SRST_CORE_B0 1 +#define SRST_CORE_PO_L0 2 +#define SRST_CORE_PO_B0 3 +#define SRST_L2_L 4 +#define SRST_L2_B 5 +#define SRST_ADB_L 6 +#define SRST_ADB_B 7 +#define SRST_A_CCI 8 +#define SRST_A_CCIM0_NOC 9 +#define SRST_A_CCIM1_NOC 10 +#define SRST_DBG_NOC 11 + +/* cru_softrst_con1 */ +#define SRST_CORE_L0_T 16 +#define SRST_CORE_L1 17 +#define SRST_CORE_L2 18 +#define SRST_CORE_L3 19 +#define SRST_CORE_PO_L0_T 20 +#define SRST_CORE_PO_L1 21 +#define SRST_CORE_PO_L2 22 +#define SRST_CORE_PO_L3 23 +#define SRST_A_ADB400_GIC2COREL 24 +#define SRST_A_ADB400_COREL2GIC 25 +#define SRST_P_DBG_L 26 +#define SRST_L2_L_T 28 +#define SRST_ADB_L_T 29 +#define SRST_A_RKPERF_L 30 +#define SRST_PVTM_CORE_L 31 + +/* cru_softrst_con2 */ +#define SRST_CORE_B0_T 32 +#define SRST_CORE_B1 33 +#define SRST_CORE_PO_B0_T 36 +#define SRST_CORE_PO_B1 37 +#define SRST_A_ADB400_GIC2COREB 40 +#define SRST_A_ADB400_COREB2GIC 41 +#define SRST_P_DBG_B 42 +#define SRST_L2_B_T 43 +#define SRST_ADB_B_T 45 +#define SRST_A_RKPERF_B 46 +#define SRST_PVTM_CORE_B 47 + +/* cru_softrst_con3 */ +#define SRST_A_CCI_T 50 +#define SRST_A_CCIM0_NOC_T 51 +#define SRST_A_CCIM1_NOC_T 52 +#define SRST_A_ADB400M_PD_CORE_B_T 53 +#define SRST_A_ADB400M_PD_CORE_L_T 54 +#define SRST_DBG_NOC_T 55 +#define SRST_DBG_CXCS 56 +#define SRST_CCI_TRACE 57 +#define SRST_P_CCI_GRF 58 + +/* cru_softrst_con4 */ +#define SRST_A_CENTER_MAIN_NOC 64 +#define SRST_A_CENTER_PERI_NOC 65 +#define SRST_P_CENTER_MAIN 66 +#define SRST_P_DDRMON 67 +#define SRST_P_CIC 68 +#define SRST_P_CENTER_SGRF 69 +#define SRST_DDR0_MSCH 70 +#define SRST_DDRCFG0_MSCH 71 +#define SRST_DDR0 72 +#define SRST_DDRPHY0 73 +#define SRST_DDR1_MSCH 74 +#define SRST_DDRCFG1_MSCH 75 +#define SRST_DDR1 76 +#define SRST_DDRPHY1 77 +#define SRST_DDR_CIC 78 +#define SRST_PVTM_DDR 79 + +/* cru_softrst_con5 */ +#define SRST_A_VCODEC_NOC 80 +#define SRST_A_VCODEC 81 +#define SRST_H_VCODEC_NOC 82 +#define SRST_H_VCODEC 83 +#define SRST_A_VDU_NOC 88 +#define SRST_A_VDU 89 +#define SRST_H_VDU_NOC 90 +#define SRST_H_VDU 91 +#define SRST_VDU_CORE 92 +#define SRST_VDU_CA 93 + +/* cru_softrst_con6 */ +#define SRST_A_IEP_NOC 96 +#define SRST_A_VOP_IEP 97 +#define SRST_A_IEP 98 +#define SRST_H_IEP_NOC 99 +#define SRST_H_IEP 100 +#define SRST_A_RGA_NOC 102 +#define SRST_A_RGA 103 +#define SRST_H_RGA_NOC 104 +#define SRST_H_RGA 105 +#define SRST_RGA_CORE 106 +#define SRST_EMMC_NOC 108 +#define SRST_EMMC 109 +#define SRST_EMMC_GRF 110 + +/* cru_softrst_con7 */ +#define SRST_A_PERIHP_NOC 112 +#define SRST_P_PERIHP_GRF 113 +#define SRST_H_PERIHP_NOC 114 +#define SRST_USBHOST0 115 +#define SRST_HOSTC0_AUX 116 +#define SRST_HOST0_ARB 117 +#define SRST_USBHOST1 118 +#define SRST_HOSTC1_AUX 119 +#define SRST_HOST1_ARB 120 +#define SRST_SDIO0 121 +#define SRST_SDMMC 122 +#define SRST_HSIC 123 +#define SRST_HSIC_AUX 124 +#define SRST_AHB1TOM 125 +#define SRST_P_PERIHP_NOC 126 +#define SRST_HSICPHY 127 + +/* cru_softrst_con8 */ +#define SRST_A_PCIE 128 +#define SRST_P_PCIE 129 +#define SRST_PCIE_CORE 130 +#define SRST_PCIE_MGMT 131 +#define SRST_PCIE_MGMT_STICKY 132 +#define SRST_PCIE_PIPE 133 +#define SRST_PCIE_PM 134 +#define SRST_PCIEPHY 135 +#define SRST_A_GMAC_NOC 136 +#define SRST_A_GMAC 137 +#define SRST_P_GMAC_NOC 138 +#define SRST_P_GMAC_GRF 140 +#define SRST_HSICPHY_POR 142 +#define SRST_HSICPHY_UTMI 143 + +/* cru_softrst_con9 */ +#define SRST_USB2PHY0_POR 144 +#define SRST_USB2PHY0_UTMI_PORT0 145 +#define SRST_USB2PHY0_UTMI_PORT1 146 +#define SRST_USB2PHY0_EHCIPHY 147 +#define SRST_UPHY0_PIPE_L00 148 +#define SRST_UPHY0 149 +#define SRST_UPHY0_TCPDPWRUP 150 +#define SRST_USB2PHY1_POR 152 +#define SRST_USB2PHY1_UTMI_PORT0 153 +#define SRST_USB2PHY1_UTMI_PORT1 154 +#define SRST_USB2PHY1_EHCIPHY 155 +#define SRST_UPHY1_PIPE_L00 156 +#define SRST_UPHY1 157 +#define SRST_UPHY1_TCPDPWRUP 158 + +/* cru_softrst_con10 */ +#define SRST_A_PERILP0_NOC 160 +#define SRST_A_DCF 161 +#define SRST_GIC500 162 +#define SRST_DMAC0_PERILP0 163 +#define SRST_DMAC1_PERILP0 164 +#define SRST_TZMA 165 +#define SRST_INTMEM 166 +#define SRST_ADB400_MST0 167 +#define SRST_ADB400_MST1 168 +#define SRST_ADB400_SLV0 169 +#define SRST_ADB400_SLV1 170 +#define SRST_H_PERILP0 171 +#define SRST_H_PERILP0_NOC 172 +#define SRST_ROM 173 +#define SRST_CRYPTO_S 174 +#define SRST_CRYPTO_M 175 + +/* cru_softrst_con11 */ +#define SRST_P_DCF 176 +#define SRST_CM0S_NOC 177 +#define SRST_CM0S 178 +#define SRST_CM0S_DBG 179 +#define SRST_CM0S_PO 180 +#define SRST_CRYPTO 181 +#define SRST_P_PERILP1_SGRF 182 +#define SRST_P_PERILP1_GRF 183 +#define SRST_CRYPTO1_S 184 +#define SRST_CRYPTO1_M 185 +#define SRST_CRYPTO1 186 +#define SRST_GIC_NOC 188 +#define SRST_SD_NOC 189 +#define SRST_SDIOAUDIO_BRG 190 + +/* cru_softrst_con12 */ +#define SRST_H_PERILP1 192 +#define SRST_H_PERILP1_NOC 193 +#define SRST_H_I2S0_8CH 194 +#define SRST_H_I2S1_8CH 195 +#define SRST_H_I2S2_8CH 196 +#define SRST_H_SPDIF_8CH 197 +#define SRST_P_PERILP1_NOC 198 +#define SRST_P_EFUSE_1024 199 +#define SRST_P_EFUSE_1024S 200 +#define SRST_P_I2C0 201 +#define SRST_P_I2C1 202 +#define SRST_P_I2C2 203 +#define SRST_P_I2C3 204 +#define SRST_P_I2C4 205 +#define SRST_P_I2C5 206 +#define SRST_P_MAILBOX0 207 + +/* cru_softrst_con13 */ +#define SRST_P_UART0 208 +#define SRST_P_UART1 209 +#define SRST_P_UART2 210 +#define SRST_P_UART3 211 +#define SRST_P_SARADC 212 +#define SRST_P_TSADC 213 +#define SRST_P_SPI0 214 +#define SRST_P_SPI1 215 +#define SRST_P_SPI2 216 +#define SRST_P_SPI3 217 +#define SRST_P_SPI4 218 +#define SRST_SPI0 219 +#define SRST_SPI1 220 +#define SRST_SPI2 221 +#define SRST_SPI3 222 +#define SRST_SPI4 223 + +/* cru_softrst_con14 */ +#define SRST_I2S0_8CH 224 +#define SRST_I2S1_8CH 225 +#define SRST_I2S2_8CH 226 +#define SRST_SPDIF_8CH 227 +#define SRST_UART0 228 +#define SRST_UART1 229 +#define SRST_UART2 230 +#define SRST_UART3 231 +#define SRST_TSADC 232 +#define SRST_I2C0 233 +#define SRST_I2C1 234 +#define SRST_I2C2 235 +#define SRST_I2C3 236 +#define SRST_I2C4 237 +#define SRST_I2C5 238 +#define SRST_SDIOAUDIO_NOC 239 + +/* cru_softrst_con15 */ +#define SRST_A_VIO_NOC 240 +#define SRST_A_HDCP_NOC 241 +#define SRST_A_HDCP 242 +#define SRST_H_HDCP_NOC 243 +#define SRST_H_HDCP 244 +#define SRST_P_HDCP_NOC 245 +#define SRST_P_HDCP 246 +#define SRST_P_HDMI_CTRL 247 +#define SRST_P_DP_CTRL 248 +#define SRST_S_DP_CTRL 249 +#define SRST_C_DP_CTRL 250 +#define SRST_P_MIPI_DSI0 251 +#define SRST_P_MIPI_DSI1 252 +#define SRST_DP_CORE 253 +#define SRST_DP_I2S 254 + +/* cru_softrst_con16 */ +#define SRST_GASKET 256 +#define SRST_VIO_GRF 258 +#define SRST_DPTX_SPDIF_REC 259 +#define SRST_HDMI_CTRL 260 +#define SRST_HDCP_CTRL 261 +#define SRST_A_ISP0_NOC 262 +#define SRST_A_ISP1_NOC 263 +#define SRST_H_ISP0_NOC 266 +#define SRST_H_ISP1_NOC 267 +#define SRST_H_ISP0 268 +#define SRST_H_ISP1 269 +#define SRST_ISP0 270 +#define SRST_ISP1 271 + +/* cru_softrst_con17 */ +#define SRST_A_VOP0_NOC 272 +#define SRST_A_VOP1_NOC 273 +#define SRST_A_VOP0 274 +#define SRST_A_VOP1 275 +#define SRST_H_VOP0_NOC 276 +#define SRST_H_VOP1_NOC 277 +#define SRST_H_VOP0 278 +#define SRST_H_VOP1 279 +#define SRST_D_VOP0 280 +#define SRST_D_VOP1 281 +#define SRST_VOP0_PWM 282 +#define SRST_VOP1_PWM 283 +#define SRST_P_EDP_NOC 284 +#define SRST_P_EDP_CTRL 285 + +/* cru_softrst_con18 */ +#define SRST_A_GPU_NOC 289 +#define SRST_A_GPU_GRF 290 +#define SRST_PVTM_GPU 291 +#define SRST_A_USB3_NOC 292 +#define SRST_A_USB3_OTG0 293 +#define SRST_A_USB3_OTG1 294 +#define SRST_A_USB3_GRF 295 +#define SRST_PMU 296 + +/* cru_softrst_con19 */ +#define SRST_P_TIMER0_5 304 +#define SRST_TIMER0 305 +#define SRST_TIMER1 306 +#define SRST_TIMER2 307 +#define SRST_TIMER3 308 +#define SRST_TIMER4 309 +#define SRST_TIMER5 310 +#define SRST_P_TIMER6_11 311 +#define SRST_TIMER6 312 +#define SRST_TIMER7 313 +#define SRST_TIMER8 314 +#define SRST_TIMER9 315 +#define SRST_TIMER10 316 +#define SRST_TIMER11 317 +#define SRST_P_INTR_ARB_PMU 318 +#define SRST_P_ALIVE_SGRF 319 + +/* cru_softrst_con20 */ +#define SRST_P_GPIO2 320 +#define SRST_P_GPIO3 321 +#define SRST_P_GPIO4 322 +#define SRST_P_GRF 323 +#define SRST_P_ALIVE_NOC 324 +#define SRST_P_WDT0 325 +#define SRST_P_WDT1 326 +#define SRST_P_INTR_ARB 327 +#define SRST_P_UPHY0_DPTX 328 +#define SRST_P_UPHY0_APB 330 +#define SRST_P_UPHY0_TCPHY 332 +#define SRST_P_UPHY1_TCPHY 333 +#define SRST_P_UPHY0_TCPDCTRL 334 +#define SRST_P_UPHY1_TCPDCTRL 335 + +/* pmu soft-reset indices */ + +/* pmu_cru_softrst_con0 */ +#define SRST_P_NOC 0 +#define SRST_P_INTMEM 1 +#define SRST_H_CM0S 2 +#define SRST_H_CM0S_NOC 3 +#define SRST_DBG_CM0S 4 +#define SRST_PO_CM0S 5 +#define SRST_P_SPI6 6 +#define SRST_SPI6 7 +#define SRST_P_TIMER_0_1 8 +#define SRST_P_TIMER_0 9 +#define SRST_P_TIMER_1 10 +#define SRST_P_UART4 11 +#define SRST_UART4 12 +#define SRST_P_WDT 13 + +/* pmu_cru_softrst_con1 */ +#define SRST_P_I2C6 16 +#define SRST_P_I2C7 17 +#define SRST_P_I2C8 18 +#define SRST_P_MAILBOX 19 +#define SRST_P_RKPWM 20 +#define SRST_P_PMUGRF 21 +#define SRST_P_SGRF 22 +#define SRST_P_GPIO0 23 +#define SRST_P_GPIO1 24 +#define SRST_P_CRU 25 +#define SRST_P_INTR 26 +#define SRST_PVTM 27 +#define SRST_I2C6 28 +#define SRST_I2C7 29 +#define SRST_I2C8 30 + +#endif -- GitLab From 485a40d7cd4aab5ae939320278809776388f5c06 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Mon, 28 Mar 2016 17:51:35 +0800 Subject: [PATCH 0281/9938] dt-bindings: add bindings for rk3399 clock controller Add devicetree bindings for Rockchip cru which found on Rockchip SoCs. Signed-off-by: Xing Zheng Signed-off-by: Jianqun Xu Acked-by: Rob Herring Signed-off-by: Heiko Stuebner --- .../bindings/clock/rockchip,rk3399-cru.txt | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt new file mode 100644 index 000000000000..3888dd33fcbd --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt @@ -0,0 +1,62 @@ +* Rockchip RK3399 Clock and Reset Unit + +The RK3399 clock controller generates and supplies clock to various +controllers within the SoC and also implements a reset controller for SoC +peripherals. + +Required Properties: + +- compatible: PMU for CRU should be "rockchip,rk3399-pmucru" +- compatible: CRU should be "rockchip,rk3399-cru" +- reg: physical base address of the controller and length of memory mapped + region. +- #clock-cells: should be 1. +- #reset-cells: should be 1. + +Each clock is assigned an identifier and client nodes can use this identifier +to specify the clock which they consume. All available clocks are defined as +preprocessor macros in the dt-bindings/clock/rk3399-cru.h headers and can be +used in device tree sources. Similar macros exist for the reset sources in +these files. + +External clocks: + +There are several clocks that are generated outside the SoC. It is expected +that they are defined using standard clock bindings with following +clock-output-names: + - "xin24m" - crystal input - required, + - "xin32k" - rtc clock - optional, + - "clkin_gmac" - external GMAC clock - optional, + - "clkin_i2s" - external I2S clock - optional, + - "pclkin_cif" - external ISP clock - optional, + - "clk_usbphy0_480m" - output clock of the pll in the usbphy0 + - "clk_usbphy1_480m" - output clock of the pll in the usbphy1 + +Example: Clock controller node: + + pmucru: pmu-clock-controller@ff750000 { + compatible = "rockchip,rk3399-pmucru"; + reg = <0x0 0xff750000 0x0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + cru: clock-controller@ff760000 { + compatible = "rockchip,rk3399-cru"; + reg = <0x0 0xff760000 0x0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + +Example: UART controller node that consumes the clock generated by the clock + controller: + + uart0: serial@ff1a0000 { + compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff180000 0x0 0x100>; + clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; + clock-names = "baudclk", "apb_pclk"; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + }; -- GitLab From 115510053e5e5872f1f19a2220b04aab5542c5c4 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Mon, 28 Mar 2016 17:51:37 +0800 Subject: [PATCH 0282/9938] clk: rockchip: add clock controller for the RK3399 Add the clock tree definition for the new RK3399 SoC. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk-rk3399.c | 1540 +++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 22 +- 3 files changed, 1562 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/rockchip/clk-rk3399.c diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 80b9a379beb4..f47a2fa962d2 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -15,3 +15,4 @@ obj-y += clk-rk3188.o obj-y += clk-rk3228.o obj-y += clk-rk3288.o obj-y += clk-rk3368.o +obj-y += clk-rk3399.o diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c new file mode 100644 index 000000000000..356e13256242 --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -0,0 +1,1540 @@ +/* + * Copyright (c) 2016 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include "clk.h" + +enum rk3399_plls { + lpll, bpll, dpll, cpll, gpll, npll, vpll, +}; + +enum rk3399_pmu_plls { + ppll, +}; + +static struct rockchip_pll_rate_table rk3399_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0), + RK3036_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0), + RK3036_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0), + RK3036_PLL_RATE(2136000000, 1, 89, 1, 1, 1, 0), + RK3036_PLL_RATE(2112000000, 1, 88, 1, 1, 1, 0), + RK3036_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0), + RK3036_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0), + RK3036_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0), + RK3036_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0), + RK3036_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0), + RK3036_PLL_RATE(1968000000, 1, 82, 1, 1, 1, 0), + RK3036_PLL_RATE(1944000000, 1, 81, 1, 1, 1, 0), + RK3036_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0), + RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), + RK3036_PLL_RATE(1872000000, 1, 78, 1, 1, 1, 0), + RK3036_PLL_RATE(1848000000, 1, 77, 1, 1, 1, 0), + RK3036_PLL_RATE(1824000000, 1, 76, 1, 1, 1, 0), + RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), + RK3036_PLL_RATE(1776000000, 1, 74, 1, 1, 1, 0), + RK3036_PLL_RATE(1752000000, 1, 73, 1, 1, 1, 0), + RK3036_PLL_RATE(1728000000, 1, 72, 1, 1, 1, 0), + RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), + RK3036_PLL_RATE(1680000000, 1, 70, 1, 1, 1, 0), + RK3036_PLL_RATE(1656000000, 1, 69, 1, 1, 1, 0), + RK3036_PLL_RATE(1632000000, 1, 68, 1, 1, 1, 0), + RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), + RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), + RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), + RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), + RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), + RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), + RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), + RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), + RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), + RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), + RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), + RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), + RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), + RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), + RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), + RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), + RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), + RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), + RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), + RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), + RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), + RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), + RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), + RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), + RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), + RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), + RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), + RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0), + RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), + RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), + RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0), + RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), + RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0), + RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), + RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), + RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), + RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), + RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), + RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), + { /* sentinel */ }, +}; + +/* CRU parents */ +PNAME(mux_pll_p) = { "xin24m", "xin32k" }; + +PNAME(mux_armclkl_p) = { "clk_core_l_lpll_src", + "clk_core_l_bpll_src", + "clk_core_l_dpll_src", + "clk_core_l_gpll_src" }; +PNAME(mux_armclkb_p) = { "clk_core_b_lpll_src", + "clk_core_b_bpll_src", + "clk_core_b_dpll_src", + "clk_core_b_gpll_src" }; +PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src", + "gpll_aclk_cci_src", + "npll_aclk_cci_src", + "vpll_aclk_cci_src" }; +PNAME(mux_cci_trace_p) = { "cpll_cci_trace", "gpll_cci_trace" }; +PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", "npll_cs"}; +PNAME(mux_aclk_perihp_p) = { "cpll_aclk_perihp_src", "gpll_aclk_perihp_src" }; + +PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; +PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" }; +PNAME(mux_pll_src_cpll_gpll_ppll_p) = { "cpll", "gpll", "ppll" }; +PNAME(mux_pll_src_cpll_gpll_upll_p) = { "cpll", "gpll", "upll" }; +PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" }; +PNAME(mux_pll_src_cpll_gpll_npll_ppll_p) = { "cpll", "gpll", "npll", "ppll" }; +PNAME(mux_pll_src_cpll_gpll_npll_24m_p) = { "cpll", "gpll", "npll", "xin24m" }; +PNAME(mux_pll_src_cpll_gpll_npll_usbphy480m_p) = { "cpll", "gpll", "npll", "clk_usbphy_480m" }; +PNAME(mux_pll_src_ppll_cpll_gpll_npll_p) = { "ppll", "cpll", "gpll", "npll", "upll" }; +PNAME(mux_pll_src_cpll_gpll_npll_upll_24m_p) = { "cpll", "gpll", "npll", "upll", "xin24m" }; +PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", "ppll", "upll", "xin24m" }; + +PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" }; +PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", "npll" }; +PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", "xin24m" }; + +PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", "dclk_vop0_frac" }; +PNAME(mux_dclk_vop1_p) = { "dclk_vop1_div", "dclk_vop1_frac" }; + +PNAME(mux_clk_cif_p) = { "clk_cifout_div", "xin24m" }; + +PNAME(mux_pll_src_24m_usbphy480m_p) = { "xin24m", "clk_usbphy_480m" }; +PNAME(mux_pll_src_24m_pciephy_p) = { "xin24m", "clk_pciephy_ref100m" }; +PNAME(mux_pll_src_24m_32k_cpll_gpll_p) = { "xin24m", "xin32k", "cpll", "gpll" }; +PNAME(mux_pciecore_cru_phy_p) = { "clk_pcie_core_cru", "clk_pcie_core_phy" }; + +PNAME(mux_aclk_emmc_p) = { "cpll_aclk_emmc_src", "gpll_aclk_emmc_src" }; + +PNAME(mux_aclk_perilp0_p) = { "cpll_aclk_perilp0_src", "gpll_aclk_perilp0_src" }; + +PNAME(mux_fclk_cm0s_p) = { "cpll_fclk_cm0s_src", "gpll_fclk_cm0s_src" }; + +PNAME(mux_hclk_perilp1_p) = { "cpll_hclk_perilp1_src", "gpll_hclk_perilp1_src" }; + +PNAME(mux_clk_testout1_p) = { "clk_testout1_pll_src", "xin24m" }; +PNAME(mux_clk_testout2_p) = { "clk_testout2_pll_src", "xin24m" }; + +PNAME(mux_usbphy_480m_p) = { "clk_usbphy0_480m_src", "clk_usbphy1_480m_src" }; +PNAME(mux_aclk_gmac_p) = { "cpll_aclk_gmac_src", "gpll_aclk_gmac_src" }; +PNAME(mux_rmii_p) = { "clk_gmac", "clkin_gmac" }; +PNAME(mux_spdif_p) = { "clk_spdif_div", "clk_spdif_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2s0_p) = { "clk_i2s0_div", "clk_i2s0_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2s1_p) = { "clk_i2s1_div", "clk_i2s1_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2s2_p) = { "clk_i2s2_div", "clk_i2s2_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2sch_p) = { "clk_i2s0", "clk_i2s1", "clk_i2s2" }; +PNAME(mux_i2sout_p) = { "clk_i2sout_src", "xin12m" }; + +PNAME(mux_uart0_p) = { "clk_uart0_div", "clk_uart0_frac", "xin24m" }; +PNAME(mux_uart1_p) = { "clk_uart1_div", "clk_uart1_frac", "xin24m" }; +PNAME(mux_uart2_p) = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; +PNAME(mux_uart3_p) = { "clk_uart3_div", "clk_uart3_frac", "xin24m" }; + +/* PMU CRU parents */ +PNAME(mux_ppll_24m_p) = { "ppll", "xin24m" }; +PNAME(mux_24m_ppll_p) = { "xin24m", "ppll" }; +PNAME(mux_fclk_cm0s_pmu_ppll_p) = { "fclk_cm0s_pmu_ppll_src", "xin24m" }; +PNAME(mux_wifi_pmu_p) = { "clk_wifi_div", "clk_wifi_frac" }; +PNAME(mux_uart4_pmu_p) = { "clk_uart4_div", "clk_uart4_frac", "xin24m" }; +PNAME(mux_clk_testout2_2io_p) = { "clk_testout2", "clk_32k_suspend_pmu" }; + +static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = { + [lpll] = PLL(pll_rk3399, PLL_APLLL, "lpll", mux_pll_p, 0, RK3399_PLL_CON(0), + RK3399_PLL_CON(3), 8, 31, 0, rk3399_pll_rates), + [bpll] = PLL(pll_rk3399, PLL_APLLB, "bpll", mux_pll_p, 0, RK3399_PLL_CON(8), + RK3399_PLL_CON(11), 8, 31, 0, rk3399_pll_rates), + [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK3399_PLL_CON(16), + RK3399_PLL_CON(19), 8, 31, 0, NULL), + [cpll] = PLL(pll_rk3399, PLL_CPLL, "cpll", mux_pll_p, 0, RK3399_PLL_CON(24), + RK3399_PLL_CON(27), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), + [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK3399_PLL_CON(32), + RK3399_PLL_CON(35), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), + [npll] = PLL(pll_rk3399, PLL_NPLL, "npll", mux_pll_p, 0, RK3399_PLL_CON(40), + RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), + [vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll", mux_pll_p, 0, RK3399_PLL_CON(48), + RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), +}; + +static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = { + [ppll] = PLL(pll_rk3399, PLL_PPLL, "ppll", mux_pll_p, 0, RK3399_PMU_PLL_CON(0), + RK3399_PMU_PLL_CON(3), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), +}; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) +#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK + +static struct rockchip_clk_branch rk3399_spdif_fracmux __initdata = + MUX(0, "clk_spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(32), 13, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_i2s0_fracmux __initdata = + MUX(0, "clk_i2s0_mux", mux_i2s0_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(28), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_i2s1_fracmux __initdata = + MUX(0, "clk_i2s1_mux", mux_i2s1_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(29), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_i2s2_fracmux __initdata = + MUX(0, "clk_i2s2_mux", mux_i2s2_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(30), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_uart0_fracmux __initdata = + MUX(SCLK_UART0, "clk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(33), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_uart1_fracmux __initdata = + MUX(SCLK_UART1, "clk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(34), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_uart2_fracmux __initdata = + MUX(SCLK_UART2, "clk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(35), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_uart3_fracmux __initdata = + MUX(SCLK_UART3, "clk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(36), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata = + MUX(SCLK_UART4_PMU, "clk_uart4_pmu", mux_uart4_pmu_p, CLK_SET_RATE_PARENT, + RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata = + MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(49), 11, 1, MFLAGS); + +static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata = + MUX(DCLK_VOP1, "dclk_vop1", mux_dclk_vop1_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(50), 11, 1, MFLAGS); + +static struct rockchip_clk_branch rk3399_pmuclk_wifi_fracmux __initdata = + MUX(SCLK_WIFI_PMU, "clk_wifi_pmu", mux_wifi_pmu_p, CLK_SET_RATE_PARENT, + RK3399_PMU_CLKSEL_CON(1), 14, 1, MFLAGS); + +static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = { + .core_reg = RK3399_CLKSEL_CON(0), + .div_core_shift = 0, + .div_core_mask = 0x1f, + .mux_core_alt = 3, + .mux_core_main = 0, + .mux_core_shift = 6, + .mux_core_mask = 0x3, +}; + +static const struct rockchip_cpuclk_reg_data rk3399_cpuclkb_data = { + .core_reg = RK3399_CLKSEL_CON(2), + .div_core_shift = 0, + .div_core_mask = 0x1f, + .mux_core_alt = 3, + .mux_core_main = 1, + .mux_core_shift = 6, + .mux_core_mask = 0x3, +}; + +#define RK3399_DIV_ACLKM_MASK 0x1f +#define RK3399_DIV_ACLKM_SHIFT 8 +#define RK3399_DIV_ATCLK_MASK 0x1f +#define RK3399_DIV_ATCLK_SHIFT 0 +#define RK3399_DIV_PCLK_DBG_MASK 0x1f +#define RK3399_DIV_PCLK_DBG_SHIFT 8 + +#define RK3399_CLKSEL0(_offs, _aclkm) \ + { \ + .reg = RK3399_CLKSEL_CON(0 + _offs), \ + .val = HIWORD_UPDATE(_aclkm, RK3399_DIV_ACLKM_MASK, \ + RK3399_DIV_ACLKM_SHIFT), \ + } +#define RK3399_CLKSEL1(_offs, _atclk, _pdbg) \ + { \ + .reg = RK3399_CLKSEL_CON(1 + _offs), \ + .val = HIWORD_UPDATE(_atclk, RK3399_DIV_ATCLK_MASK, \ + RK3399_DIV_ATCLK_SHIFT) | \ + HIWORD_UPDATE(_pdbg, RK3399_DIV_PCLK_DBG_MASK, \ + RK3399_DIV_PCLK_DBG_SHIFT), \ + } + +/* cluster_l: aclkm in clksel0, rest in clksel1 */ +#define RK3399_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg) \ + { \ + .prate = _prate##U, \ + .divs = { \ + RK3399_CLKSEL0(0, _aclkm), \ + RK3399_CLKSEL1(0, _atclk, _pdbg), \ + }, \ + } + +/* cluster_b: aclkm in clksel2, rest in clksel3 */ +#define RK3399_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg) \ + { \ + .prate = _prate##U, \ + .divs = { \ + RK3399_CLKSEL0(2, _aclkm), \ + RK3399_CLKSEL1(2, _atclk, _pdbg), \ + }, \ + } + +static struct rockchip_cpuclk_rate_table rk3399_cpuclkl_rates[] __initdata = { + RK3399_CPUCLKL_RATE(1800000000, 1, 8, 8), + RK3399_CPUCLKL_RATE(1704000000, 1, 8, 8), + RK3399_CPUCLKL_RATE(1608000000, 1, 7, 7), + RK3399_CPUCLKL_RATE(1512000000, 1, 7, 7), + RK3399_CPUCLKL_RATE(1488000000, 1, 6, 6), + RK3399_CPUCLKL_RATE(1416000000, 1, 6, 6), + RK3399_CPUCLKL_RATE(1200000000, 1, 5, 5), + RK3399_CPUCLKL_RATE(1008000000, 1, 5, 5), + RK3399_CPUCLKL_RATE( 816000000, 1, 4, 4), + RK3399_CPUCLKL_RATE( 696000000, 1, 3, 3), + RK3399_CPUCLKL_RATE( 600000000, 1, 3, 3), + RK3399_CPUCLKL_RATE( 408000000, 1, 2, 2), + RK3399_CPUCLKL_RATE( 312000000, 1, 1, 1), +}; + +static struct rockchip_cpuclk_rate_table rk3399_cpuclkb_rates[] __initdata = { + RK3399_CPUCLKB_RATE(2208000000, 1, 11, 11), + RK3399_CPUCLKB_RATE(2184000000, 1, 11, 11), + RK3399_CPUCLKB_RATE(2088000000, 1, 10, 10), + RK3399_CPUCLKB_RATE(2040000000, 1, 10, 10), + RK3399_CPUCLKB_RATE(1992000000, 1, 9, 9), + RK3399_CPUCLKB_RATE(1896000000, 1, 9, 9), + RK3399_CPUCLKB_RATE(1800000000, 1, 8, 8), + RK3399_CPUCLKB_RATE(1704000000, 1, 8, 8), + RK3399_CPUCLKB_RATE(1608000000, 1, 7, 7), + RK3399_CPUCLKB_RATE(1512000000, 1, 7, 7), + RK3399_CPUCLKB_RATE(1488000000, 1, 6, 6), + RK3399_CPUCLKB_RATE(1416000000, 1, 6, 6), + RK3399_CPUCLKB_RATE(1200000000, 1, 5, 5), + RK3399_CPUCLKB_RATE(1008000000, 1, 5, 5), + RK3399_CPUCLKB_RATE( 816000000, 1, 4, 4), + RK3399_CPUCLKB_RATE( 696000000, 1, 3, 3), + RK3399_CPUCLKB_RATE( 600000000, 1, 3, 3), + RK3399_CPUCLKB_RATE( 408000000, 1, 2, 2), + RK3399_CPUCLKB_RATE( 312000000, 1, 1, 1), +}; + +static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { + /* + * CRU Clock-Architecture + */ + + /* usbphy */ + GATE(SCLK_USB2PHY0_REF, "clk_usb2phy0_ref", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(6), 5, GFLAGS), + GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(6), 6, GFLAGS), + + GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(13), 12, GFLAGS), + GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(13), 12, GFLAGS), + MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(14), 6, 1, MFLAGS), + + MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0, + RK3399_CLKSEL_CON(14), 15, 1, MFLAGS), + + COMPOSITE_NODIV(SCLK_HSICPHY, "clk_hsicphy", mux_pll_src_cpll_gpll_npll_usbphy480m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(19), 0, 2, MFLAGS, + RK3399_CLKGATE_CON(6), 4, GFLAGS), + + COMPOSITE(ACLK_USB3, "aclk_usb3", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(39), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 0, GFLAGS), + GATE(ACLK_USB3_NOC, "aclk_usb3_noc", "aclk_usb3", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 0, GFLAGS), + GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 1, GFLAGS), + GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 2, GFLAGS), + GATE(ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 3, GFLAGS), + GATE(ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 4, GFLAGS), + + GATE(SCLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(12), 1, GFLAGS), + GATE(SCLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(12), 2, GFLAGS), + + COMPOSITE(SCLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", mux_pll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(40), 15, 1, MFLAGS, 0, 10, DFLAGS, + RK3399_CLKGATE_CON(12), 3, GFLAGS), + + COMPOSITE(SCLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", mux_pll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(41), 15, 1, MFLAGS, 0, 10, DFLAGS, + RK3399_CLKGATE_CON(12), 4, GFLAGS), + + COMPOSITE(SCLK_UPHY0_TCPDPHY_REF, "clk_uphy0_tcpdphy_ref", mux_pll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(64), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 4, GFLAGS), + + COMPOSITE(SCLK_UPHY0_TCPDCORE, "clk_uphy0_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(64), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 5, GFLAGS), + + COMPOSITE(SCLK_UPHY1_TCPDPHY_REF, "clk_uphy1_tcpdphy_ref", mux_pll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(65), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 6, GFLAGS), + + COMPOSITE(SCLK_UPHY1_TCPDCORE, "clk_uphy1_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(65), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 7, GFLAGS), + + /* little core */ + GATE(0, "clk_core_l_lpll_src", "lpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(0), 0, GFLAGS), + GATE(0, "clk_core_l_bpll_src", "bpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(0), 1, GFLAGS), + GATE(0, "clk_core_l_dpll_src", "dpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(0), 2, GFLAGS), + GATE(0, "clk_core_l_gpll_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(0), 3, GFLAGS), + + COMPOSITE_NOMUX(0, "aclkm_core_l", "armclkl", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3399_CLKGATE_CON(0), 4, GFLAGS), + COMPOSITE_NOMUX(0, "atclk_core_l", "armclkl", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3399_CLKGATE_CON(0), 5, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg_core_l", "armclkl", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3399_CLKGATE_CON(0), 6, GFLAGS), + + GATE(ACLK_CORE_ADB400_CORE_L_2_CCI500, "aclk_core_adb400_core_l_2_cci500", "aclkm_core_l", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 12, GFLAGS), + GATE(ACLK_PERF_CORE_L, "aclk_perf_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 13, GFLAGS), + + GATE(0, "clk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 9, GFLAGS), + GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_core_adb400_gic_2_core_l", "armclkl", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 10, GFLAGS), + GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 11, GFLAGS), + GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(0), 7, GFLAGS), + + /* big core */ + GATE(0, "clk_core_b_lpll_src", "lpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(1), 0, GFLAGS), + GATE(0, "clk_core_b_bpll_src", "bpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(1), 1, GFLAGS), + GATE(0, "clk_core_b_dpll_src", "dpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(1), 2, GFLAGS), + GATE(0, "clk_core_b_gpll_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(1), 3, GFLAGS), + + COMPOSITE_NOMUX(0, "aclkm_core_b", "armclkb", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3399_CLKGATE_CON(1), 4, GFLAGS), + COMPOSITE_NOMUX(0, "atclk_core_b", "armclkb", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3399_CLKGATE_CON(1), 5, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg_core_b", "armclkb", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3399_CLKGATE_CON(1), 6, GFLAGS), + + GATE(ACLK_CORE_ADB400_CORE_B_2_CCI500, "aclk_core_adb400_core_b_2_cci500", "aclkm_core_b", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 5, GFLAGS), + GATE(ACLK_PERF_CORE_B, "aclk_perf_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 6, GFLAGS), + + GATE(0, "clk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 1, GFLAGS), + GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_core_adb400_gic_2_core_b", "armclkb", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 3, GFLAGS), + GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_core_adb400_core_b_2_gic", "armclkb", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 4, GFLAGS), + + DIV(0, "pclken_dbg_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(3), 13, 2, DFLAGS | CLK_DIVIDER_READ_ONLY), + + GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(14), 2, GFLAGS), + + GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(1), 7, GFLAGS), + + /* gmac */ + GATE(0, "cpll_aclk_gmac_src", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(6), 9, GFLAGS), + GATE(0, "gpll_aclk_gmac_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(6), 8, GFLAGS), + COMPOSITE(0, "aclk_gmac_pre", mux_aclk_gmac_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(6), 10, GFLAGS), + + GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 0, GFLAGS), + GATE(ACLK_GMAC_NOC, "aclk_gmac_noc", "aclk_gmac_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 1, GFLAGS), + GATE(ACLK_PERF_GMAC, "aclk_perf_gmac", "aclk_gmac_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 4, GFLAGS), + + COMPOSITE_NOMUX(0, "pclk_gmac_pre", "aclk_gmac_pre", 0, + RK3399_CLKSEL_CON(19), 8, 3, DFLAGS, + RK3399_CLKGATE_CON(6), 11, GFLAGS), + GATE(PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 2, GFLAGS), + GATE(PCLK_GMAC_NOC, "pclk_gmac_noc", "pclk_gmac_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 3, GFLAGS), + + COMPOSITE(SCLK_MAC, "clk_gmac", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(20), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(5), 5, GFLAGS), + + MUX(0, "clk_rmii_src", mux_rmii_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(19), 4, 1, MFLAGS), + GATE(SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(5), 6, GFLAGS), + GATE(SCLK_MACREF, "clk_mac_ref", "clk_rmii_src", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(5), 7, GFLAGS), + GATE(SCLK_MAC_RX, "clk_rmii_rx", "clk_rmii_src", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(5), 8, GFLAGS), + GATE(SCLK_MAC_TX, "clk_rmii_tx", "clk_rmii_src", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(5), 9, GFLAGS), + + /* spdif */ + COMPOSITE(0, "clk_spdif_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(8), 13, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(99), 0, + RK3399_CLKGATE_CON(8), 14, GFLAGS, + &rk3399_spdif_fracmux), + GATE(SCLK_SPDIF_8CH, "clk_spdif", "clk_spdif_mux", CLK_SET_RATE_PARENT, + RK3399_CLKGATE_CON(8), 15, GFLAGS), + + COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 6, GFLAGS), + /* i2s */ + COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(28), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(8), 3, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(96), 0, + RK3399_CLKGATE_CON(8), 4, GFLAGS, + &rk3399_i2s0_fracmux), + GATE(SCLK_I2S0_8CH, "clk_i2s0", "clk_i2s0_mux", CLK_SET_RATE_PARENT, + RK3399_CLKGATE_CON(8), 5, GFLAGS), + + COMPOSITE(0, "clk_i2s1_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(29), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(8), 6, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(97), 0, + RK3399_CLKGATE_CON(8), 7, GFLAGS, + &rk3399_i2s1_fracmux), + GATE(SCLK_I2S1_8CH, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT, + RK3399_CLKGATE_CON(8), 8, GFLAGS), + + COMPOSITE(0, "clk_i2s2_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(30), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(8), 9, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(98), 0, + RK3399_CLKGATE_CON(8), 10, GFLAGS, + &rk3399_i2s2_fracmux), + GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT, + RK3399_CLKGATE_CON(8), 11, GFLAGS), + + MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(31), 0, 2, MFLAGS), + COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(30), 8, 2, MFLAGS, + RK3399_CLKGATE_CON(8), 12, GFLAGS), + + /* uart */ + MUX(0, "clk_uart0_src", mux_pll_src_cpll_gpll_upll_p, 0, + RK3399_CLKSEL_CON(33), 12, 2, MFLAGS), + COMPOSITE_NOMUX(0, "clk_uart0_div", "clk_uart0_src", 0, + RK3399_CLKSEL_CON(33), 0, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 0, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(100), 0, + RK3399_CLKGATE_CON(9), 1, GFLAGS, + &rk3399_uart0_fracmux), + + MUX(0, "clk_uart_src", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(33), 15, 1, MFLAGS), + COMPOSITE_NOMUX(0, "clk_uart1_div", "clk_uart_src", 0, + RK3399_CLKSEL_CON(34), 0, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 2, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(101), 0, + RK3399_CLKGATE_CON(9), 3, GFLAGS, + &rk3399_uart1_fracmux), + + COMPOSITE_NOMUX(0, "clk_uart2_div", "clk_uart_src", 0, + RK3399_CLKSEL_CON(35), 0, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 4, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(102), 0, + RK3399_CLKGATE_CON(9), 5, GFLAGS, + &rk3399_uart2_fracmux), + + COMPOSITE_NOMUX(0, "clk_uart3_div", "clk_uart_src", 0, + RK3399_CLKSEL_CON(36), 0, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 6, GFLAGS), + COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(103), 0, + RK3399_CLKGATE_CON(9), 7, GFLAGS, + &rk3399_uart3_fracmux), + + COMPOSITE(0, "pclk_ddr", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(6), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(3), 4, GFLAGS), + + GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(18), 10, GFLAGS), + GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(18), 12, GFLAGS), + GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(18), 15, GFLAGS), + GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(19), 2, GFLAGS), + + GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(4), 11, GFLAGS), + GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(3), 5, GFLAGS), + GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(3), 6, GFLAGS), + + /* cci */ + GATE(0, "cpll_aclk_cci_src", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 0, GFLAGS), + GATE(0, "gpll_aclk_cci_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 1, GFLAGS), + GATE(0, "npll_aclk_cci_src", "npll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 2, GFLAGS), + GATE(0, "vpll_aclk_cci_src", "vpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 3, GFLAGS), + + COMPOSITE(0, "aclk_cci_pre", mux_aclk_cci_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(2), 4, GFLAGS), + + GATE(ACLK_ADB400M_PD_CORE_L, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 0, GFLAGS), + GATE(ACLK_ADB400M_PD_CORE_B, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 1, GFLAGS), + GATE(ACLK_CCI, "aclk_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 2, GFLAGS), + GATE(ACLK_CCI_NOC0, "aclk_cci_noc0", "aclk_cci_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 3, GFLAGS), + GATE(ACLK_CCI_NOC1, "aclk_cci_noc1", "aclk_cci_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 4, GFLAGS), + GATE(ACLK_CCI_GRF, "aclk_cci_grf", "aclk_cci_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 7, GFLAGS), + + GATE(0, "cpll_cci_trace", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 5, GFLAGS), + GATE(0, "gpll_cci_trace", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 6, GFLAGS), + COMPOSITE(SCLK_CCI_TRACE, "clk_cci_trace", mux_cci_trace_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(5), 15, 2, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(2), 7, GFLAGS), + + GATE(0, "cpll_cs", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 8, GFLAGS), + GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 9, GFLAGS), + GATE(0, "npll_cs", "npll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(2), 10, GFLAGS), + COMPOSITE_NOGATE(0, "clk_cs", mux_cs_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS), + GATE(0, "clk_dbg_cxcs", "clk_cs", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 5, GFLAGS), + GATE(0, "clk_dbg_noc", "clk_cs", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(15), 6, GFLAGS), + + /* vcodec */ + COMPOSITE(0, "aclk_vcodec_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, + RK3399_CLKSEL_CON(7), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 0, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_vcodec_pre", "aclk_vcodec_pre", 0, + RK3399_CLKSEL_CON(7), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 1, GFLAGS), + GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 2, GFLAGS), + GATE(0, "hclk_vcodec_noc", "hclk_vcodec_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 3, GFLAGS), + + GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 0, GFLAGS), + GATE(0, "aclk_vcodec_noc", "aclk_vcodec_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 1, GFLAGS), + + /* vdu */ + COMPOSITE(SCLK_VDU_CORE, "clk_vdu_core", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 4, GFLAGS), + COMPOSITE(SCLK_VDU_CA, "clk_vdu_ca", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(9), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 5, GFLAGS), + + COMPOSITE(0, "aclk_vdu_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, + RK3399_CLKSEL_CON(8), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 2, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_vdu_pre", "aclk_vdu_pre", 0, + RK3399_CLKSEL_CON(8), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 3, GFLAGS), + GATE(HCLK_VDU, "hclk_vdu", "hclk_vdu_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 10, GFLAGS), + GATE(HCLK_VDU_NOC, "hclk_vdu_noc", "hclk_vdu_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 11, GFLAGS), + + GATE(ACLK_VDU, "aclk_vdu", "aclk_vdu_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 8, GFLAGS), + GATE(ACLK_VDU_NOC, "aclk_vdu_noc", "aclk_vdu_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(17), 9, GFLAGS), + + /* iep */ + COMPOSITE(0, "aclk_iep_pre", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(10), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 6, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_iep_pre", "aclk_iep_pre", 0, + RK3399_CLKSEL_CON(10), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 7, GFLAGS), + GATE(HCLK_IEP, "hclk_iep", "hclk_iep_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 2, GFLAGS), + GATE(HCLK_IEP_NOC, "hclk_iep_noc", "hclk_iep_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 3, GFLAGS), + + GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 0, GFLAGS), + GATE(ACLK_IEP_NOC, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 1, GFLAGS), + + /* rga */ + COMPOSITE(0, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 10, GFLAGS), + + COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 8, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_rga_pre", "aclk_rga_pre", 0, + RK3399_CLKSEL_CON(11), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(4), 9, GFLAGS), + GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 10, GFLAGS), + GATE(HCLK_RGA_NOC, "hclk_rga_noc", "hclk_rga_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 11, GFLAGS), + + GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 8, GFLAGS), + GATE(ACLK_RGA_NOC, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(16), 9, GFLAGS), + + /* center */ + COMPOSITE(0, "aclk_center", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(3), 7, GFLAGS), + GATE(ACLK_CENTER_MAIN_NOC, "aclk_center_main_noc", "aclk_center", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(19), 0, GFLAGS), + GATE(ACLK_CENTER_PERI_NOC, "aclk_center_peri_noc", "aclk_center", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(19), 1, GFLAGS), + + /* gpu */ + COMPOSITE(0, "aclk_gpu_pre", mux_pll_src_ppll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(13), 5, 3, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 0, GFLAGS), + GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 8, GFLAGS), + GATE(ACLK_PERF_GPU, "aclk_perf_gpu", "aclk_gpu_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 10, GFLAGS), + GATE(ACLK_GPU_GRF, "aclk_gpu_grf", "aclk_gpu_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(30), 11, GFLAGS), + GATE(SCLK_PVTM_GPU, "aclk_pvtm_gpu", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(13), 1, GFLAGS), + + /* perihp */ + GATE(0, "cpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(5), 0, GFLAGS), + GATE(0, "gpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(5), 1, GFLAGS), + COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(5), 2, GFLAGS), + COMPOSITE_NOMUX(HCLK_PERIHP, "hclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(14), 8, 2, DFLAGS, + RK3399_CLKGATE_CON(5), 3, GFLAGS), + COMPOSITE_NOMUX(PCLK_PERIHP, "pclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(14), 12, 2, DFLAGS, + RK3399_CLKGATE_CON(5), 4, GFLAGS), + + GATE(ACLK_PERF_PCIE, "aclk_perf_pcie", "aclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 2, GFLAGS), + GATE(ACLK_PCIE, "aclk_pcie", "aclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 10, GFLAGS), + GATE(0, "aclk_perihp_noc", "aclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 12, GFLAGS), + + GATE(HCLK_HOST0, "hclk_host0", "hclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 5, GFLAGS), + GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 6, GFLAGS), + GATE(HCLK_HOST1, "hclk_host1", "hclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 7, GFLAGS), + GATE(HCLK_HOST1_ARB, "hclk_host1_arb", "hclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 8, GFLAGS), + GATE(HCLK_HSIC, "hclk_hsic", "hclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 9, GFLAGS), + GATE(0, "hclk_perihp_noc", "hclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 13, GFLAGS), + GATE(0, "hclk_ahb1tom", "hclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 15, GFLAGS), + + GATE(PCLK_PERIHP_GRF, "pclk_perihp_grf", "pclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 4, GFLAGS), + GATE(PCLK_PCIE, "pclk_pcie", "pclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 11, GFLAGS), + GATE(0, "pclk_perihp_noc", "pclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(20), 14, GFLAGS), + GATE(PCLK_HSICPHY, "pclk_hsicphy", "pclk_perihp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(31), 8, GFLAGS), + + /* sdio & sdmmc */ + COMPOSITE(0, "hclk_sd", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(13), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 13, GFLAGS), + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(33), 8, GFLAGS), + GATE(0, "hclk_sdmmc_noc", "hclk_sd", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(33), 9, GFLAGS), + + COMPOSITE(SCLK_SDIO, "clk_sdio", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(15), 8, 3, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(6), 0, GFLAGS), + + COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(16), 8, 3, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(6), 1, GFLAGS), + + MMC(SCLK_SDMMC_DRV, "emmc_drv", "clk_sdmmc", RK3399_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "emmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", RK3399_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", RK3399_SDIO_CON1, 1), + + /* pcie */ + COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(17), 8, 3, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(6), 2, GFLAGS), + + COMPOSITE_NOMUX(0, "clk_pciephy_ref100m", "npll", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(18), 11, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 6, GFLAGS), + MUX(SCLK_PCIEPHY_REF, "clk_pciephy_ref", mux_pll_src_24m_pciephy_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(18), 10, 1, MFLAGS), + + COMPOSITE(0, "clk_pcie_core_cru", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(6), 3, GFLAGS), + MUX(SCLK_PCIE_CORE, "clk_pcie_core", mux_pciecore_cru_phy_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(18), 7, 1, MFLAGS), + + /* emmc */ + COMPOSITE(SCLK_EMMC, "clk_emmc", mux_pll_src_cpll_gpll_npll_upll_24m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(22), 8, 3, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(6), 14, GFLAGS), + + GATE(0, "cpll_aclk_emmc_src", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(6), 12, GFLAGS), + GATE(0, "gpll_aclk_emmc_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(6), 13, GFLAGS), + COMPOSITE_NOGATE(ACLK_EMMC, "aclk_emmc", mux_aclk_emmc_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(21), 7, 1, MFLAGS, 0, 5, DFLAGS), + GATE(ACLK_EMMC_CORE, "aclk_emmccore", "aclk_emmc", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 8, GFLAGS), + GATE(ACLK_EMMC_NOC, "aclk_emmc_noc", "aclk_emmc", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 9, GFLAGS), + GATE(ACLK_EMMC_GRF, "aclk_emmcgrf", "aclk_emmc", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 10, GFLAGS), + + /* perilp0 */ + GATE(0, "cpll_aclk_perilp0_src", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(7), 1, GFLAGS), + GATE(0, "gpll_aclk_perilp0_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(7), 0, GFLAGS), + COMPOSITE(ACLK_PERILP0, "aclk_perilp0", mux_aclk_perilp0_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(23), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(7), 2, GFLAGS), + COMPOSITE_NOMUX(HCLK_PERILP0, "hclk_perilp0", "aclk_perilp0", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(23), 8, 2, DFLAGS, + RK3399_CLKGATE_CON(7), 3, GFLAGS), + COMPOSITE_NOMUX(PCLK_PERILP0, "pclk_perilp0", "aclk_perilp0", 0, + RK3399_CLKSEL_CON(23), 12, 3, DFLAGS, + RK3399_CLKGATE_CON(7), 4, GFLAGS), + + /* aclk_perilp0 gates */ + GATE(ACLK_INTMEM, "aclk_intmem", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 0, GFLAGS), + GATE(ACLK_TZMA, "aclk_tzma", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 1, GFLAGS), + GATE(SCLK_INTMEM0, "clk_intmem0", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 2, GFLAGS), + GATE(SCLK_INTMEM1, "clk_intmem1", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 3, GFLAGS), + GATE(SCLK_INTMEM2, "clk_intmem2", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 4, GFLAGS), + GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS), + GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS), + GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS), + GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS), + GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS), + GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS), + GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 7, GFLAGS), + + /* hclk_perilp0 gates */ + GATE(HCLK_ROM, "hclk_rom", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 4, GFLAGS), + GATE(HCLK_M_CRYPTO0, "hclk_m_crypto0", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 5, GFLAGS), + GATE(HCLK_S_CRYPTO0, "hclk_s_crypto0", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 6, GFLAGS), + GATE(HCLK_M_CRYPTO1, "hclk_m_crypto1", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 14, GFLAGS), + GATE(HCLK_S_CRYPTO1, "hclk_s_crypto1", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 15, GFLAGS), + GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS), + + /* pclk_perilp0 gates */ + GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS), + + /* crypto */ + COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(24), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(7), 7, GFLAGS), + + COMPOSITE(SCLK_CRYPTO1, "clk_crypto1", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(26), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(7), 8, GFLAGS), + + /* cm0s_perilp */ + GATE(0, "cpll_fclk_cm0s_src", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(7), 6, GFLAGS), + GATE(0, "gpll_fclk_cm0s_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(7), 5, GFLAGS), + COMPOSITE(FCLK_CM0S, "fclk_cm0s", mux_fclk_cm0s_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(24), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(7), 9, GFLAGS), + + /* fclk_cm0s gates */ + GATE(SCLK_M0_PERILP, "sclk_m0_perilp", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 8, GFLAGS), + GATE(HCLK_M0_PERILP, "hclk_m0_perilp", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 9, GFLAGS), + GATE(DCLK_M0_PERILP, "dclk_m0_perilp", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 10, GFLAGS), + GATE(SCLK_M0_PERILP_DEC, "clk_m0_perilp_dec", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 11, GFLAGS), + GATE(HCLK_M0_PERILP_NOC, "hclk_m0_perilp_noc", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 11, GFLAGS), + + /* perilp1 */ + GATE(0, "cpll_hclk_perilp1_src", "cpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(8), 1, GFLAGS), + GATE(0, "gpll_hclk_perilp1_src", "gpll", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(8), 0, GFLAGS), + COMPOSITE_NOGATE(HCLK_PERILP1, "hclk_perilp1", mux_hclk_perilp1_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(25), 7, 1, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(PCLK_PERILP1, "pclk_perilp1", "hclk_perilp1", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(25), 8, 3, DFLAGS, + RK3399_CLKGATE_CON(8), 2, GFLAGS), + + /* hclk_perilp1 gates */ + GATE(0, "hclk_perilp1_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 9, GFLAGS), + GATE(0, "hclk_sdio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 12, GFLAGS), + GATE(HCLK_I2S0_8CH, "hclk_i2s0", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 0, GFLAGS), + GATE(HCLK_I2S1_8CH, "hclk_i2s1", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 1, GFLAGS), + GATE(HCLK_I2S2_8CH, "hclk_i2s2", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 2, GFLAGS), + GATE(HCLK_SPDIF, "hclk_spdif", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 3, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 4, GFLAGS), + GATE(PCLK_SPI5, "pclk_spi5", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 5, GFLAGS), + GATE(0, "hclk_sdioaudio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 6, GFLAGS), + + /* pclk_perilp1 gates */ + GATE(PCLK_UART0, "pclk_uart0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 0, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 1, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 2, GFLAGS), + GATE(PCLK_UART3, "pclk_uart3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 3, GFLAGS), + GATE(PCLK_I2C7, "pclk_rki2c7", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 5, GFLAGS), + GATE(PCLK_I2C1, "pclk_rki2c1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 6, GFLAGS), + GATE(PCLK_I2C5, "pclk_rki2c5", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 7, GFLAGS), + GATE(PCLK_I2C6, "pclk_rki2c6", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 8, GFLAGS), + GATE(PCLK_I2C2, "pclk_rki2c2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 9, GFLAGS), + GATE(PCLK_I2C3, "pclk_rki2c3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 10, GFLAGS), + GATE(PCLK_MAILBOX0, "pclk_mailbox0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 11, GFLAGS), + GATE(PCLK_SARADC, "pclk_saradc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 12, GFLAGS), + GATE(PCLK_TSADC, "pclk_tsadc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 13, GFLAGS), + GATE(PCLK_EFUSE1024NS, "pclk_efuse1024ns", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 14, GFLAGS), + GATE(PCLK_EFUSE1024S, "pclk_efuse1024s", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 15, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 10, GFLAGS), + GATE(PCLK_SPI1, "pclk_spi1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 11, GFLAGS), + GATE(PCLK_SPI2, "pclk_spi2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 12, GFLAGS), + GATE(PCLK_SPI4, "pclk_spi4", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 13, GFLAGS), + GATE(PCLK_PERIHP_GRF, "pclk_perilp_sgrf", "pclk_perilp1", 0, RK3399_CLKGATE_CON(24), 13, GFLAGS), + GATE(0, "pclk_perilp1_noc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(25), 10, GFLAGS), + + /* saradc */ + COMPOSITE_NOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 0, + RK3399_CLKSEL_CON(26), 8, 8, DFLAGS, + RK3399_CLKGATE_CON(9), 11, GFLAGS), + + /* tsadc */ + COMPOSITE(SCLK_TSADC, "clk_tsadc", mux_pll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(27), 15, 1, MFLAGS, 0, 10, DFLAGS, + RK3399_CLKGATE_CON(9), 10, GFLAGS), + + /* cif_testout */ + MUX(0, "clk_testout1_pll_src", mux_pll_src_cpll_gpll_npll_p, 0, + RK3399_CLKSEL_CON(38), 6, 2, MFLAGS), + COMPOSITE(0, "clk_testout1", mux_clk_testout1_p, 0, + RK3399_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 14, GFLAGS), + + MUX(0, "clk_testout2_pll_src", mux_pll_src_cpll_gpll_npll_p, 0, + RK3399_CLKSEL_CON(38), 14, 2, MFLAGS), + COMPOSITE(0, "clk_testout2", mux_clk_testout2_p, 0, + RK3399_CLKSEL_CON(38), 13, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(13), 15, GFLAGS), + + /* vio */ + COMPOSITE(ACLK_VIO, "aclk_vio", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 10, GFLAGS), + COMPOSITE_NOMUX(PCLK_VIO, "pclk_vio", "aclk_vio", 0, + RK3399_CLKSEL_CON(43), 0, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 1, GFLAGS), + + GATE(ACLK_VIO_NOC, "aclk_vio_noc", "aclk_vio", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 0, GFLAGS), + + GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "pclk_vio", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 1, GFLAGS), + GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "pclk_vio", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 2, GFLAGS), + GATE(PCLK_VIO_GRF, "pclk_vio_grf", "pclk_vio", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 12, GFLAGS), + + /* hdcp */ + COMPOSITE(ACLK_HDCP, "aclk_hdcp", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 12, GFLAGS), + COMPOSITE_NOMUX(HCLK_HDCP, "hclk_hdcp", "aclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(43), 5, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 3, GFLAGS), + COMPOSITE_NOMUX(PCLK_HDCP, "pclk_hdcp", "aclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(43), 10, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 10, GFLAGS), + + GATE(ACLK_HDCP_NOC, "aclk_hdcp_noc", "aclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 4, GFLAGS), + GATE(ACLK_HDCP22, "aclk_hdcp22", "aclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 10, GFLAGS), + + GATE(HCLK_HDCP_NOC, "hclk_hdcp_noc", "hclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 5, GFLAGS), + GATE(HCLK_HDCP22, "hclk_hdcp22", "hclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 9, GFLAGS), + + GATE(PCLK_HDCP_NOC, "pclk_hdcp_noc", "pclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 3, GFLAGS), + GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 6, GFLAGS), + GATE(PCLK_DP_CTRL, "pclk_dp_ctrl", "pclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 7, GFLAGS), + GATE(PCLK_HDCP22, "pclk_hdcp22", "pclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 8, GFLAGS), + GATE(PCLK_GASKET, "pclk_gasket", "pclk_hdcp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(29), 11, GFLAGS), + + /* edp */ + COMPOSITE(SCLK_DP_CORE, "clk_dp_core", mux_pll_src_npll_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 8, GFLAGS), + + COMPOSITE(PCLK_EDP, "pclk_edp", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(44), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 11, GFLAGS), + GATE(PCLK_EDP_NOC, "pclk_edp_noc", "pclk_edp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 12, GFLAGS), + GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_edp", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(32), 13, GFLAGS), + + /* hdmi */ + GATE(SCLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(11), 6, GFLAGS), + + COMPOSITE(SCLK_HDMI_CEC, "clk_hdmi_cec", mux_pll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(45), 15, 1, MFLAGS, 0, 10, DFLAGS, + RK3399_CLKGATE_CON(11), 7, GFLAGS), + + /* vop0 */ + COMPOSITE(ACLK_VOP0_PRE, "aclk_vop0_pre", mux_pll_src_vpll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(47), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 8, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_vop0_pre", "aclk_vop0_pre", 0, + RK3399_CLKSEL_CON(47), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 9, GFLAGS), + + GATE(ACLK_VOP0, "aclk_vop0", "aclk_vop0_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 3, GFLAGS), + GATE(ACLK_VOP0_NOC, "aclk_vop0_noc", "aclk_vop0_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 1, GFLAGS), + + GATE(HCLK_VOP0, "hclk_vop0", "hclk_vop0_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 2, GFLAGS), + GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 0, GFLAGS), + + COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS, + RK3399_CLKGATE_CON(10), 12, GFLAGS), + + COMPOSITE_FRACMUX_NOGATE(0, "dclk_vop0_frac", "dclk_vop0_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(106), 0, + &rk3399_dclk_vop0_fracmux), + + COMPOSITE(SCLK_VOP0_PWM, "clk_vop0_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(51), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 14, GFLAGS), + + /* vop1 */ + COMPOSITE(ACLK_VOP1_PRE, "aclk_vop1_pre", mux_pll_src_vpll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 10, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_vop1_pre", "aclk_vop1_pre", 0, + RK3399_CLKSEL_CON(48), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 11, GFLAGS), + + GATE(ACLK_VOP1, "aclk_vop1", "aclk_vop1_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 7, GFLAGS), + GATE(ACLK_VOP1_NOC, "aclk_vop1_noc", "aclk_vop1_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 5, GFLAGS), + + GATE(HCLK_VOP1, "hclk_vop1", "hclk_vop1_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 6, GFLAGS), + GATE(HCLK_VOP1_NOC, "hclk_vop1_noc", "hclk_vop1_pre", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(28), 4, GFLAGS), + + COMPOSITE(DCLK_VOP1_DIV, "dclk_vop1_div", mux_pll_src_vpll_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 8, DFLAGS, + RK3399_CLKGATE_CON(10), 13, GFLAGS), + + COMPOSITE_FRACMUX_NOGATE(0, "dclk_vop1_frac", "dclk_vop1_div", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(107), 0, + &rk3399_dclk_vop1_fracmux), + + COMPOSITE(SCLK_VOP1_PWM, "clk_vop1_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(52), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 15, GFLAGS), + + /* isp */ + COMPOSITE(0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(53), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 8, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_isp0", "aclk_isp0", 0, + RK3399_CLKSEL_CON(53), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 9, GFLAGS), + + GATE(ACLK_ISP0_NOC, "aclk_isp0_noc", "aclk_isp0", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 1, GFLAGS), + GATE(ACLK_ISP0_WRAPPER, "aclk_isp0_wrapper", "aclk_isp0", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 5, GFLAGS), + GATE(HCLK_ISP1_WRAPPER, "hclk_isp1_wrapper", "aclk_isp0", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 7, GFLAGS), + + GATE(HCLK_ISP0_NOC, "hclk_isp0_noc", "hclk_isp0", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 0, GFLAGS), + GATE(HCLK_ISP0_WRAPPER, "hclk_isp0_wrapper", "hclk_isp0", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 4, GFLAGS), + + COMPOSITE(SCLK_ISP0, "clk_isp0", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 4, GFLAGS), + + COMPOSITE(ACLK_ISP1, "aclk_isp1", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(54), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 10, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_isp1", "aclk_isp1", 0, + RK3399_CLKSEL_CON(54), 8, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 11, GFLAGS), + + GATE(ACLK_ISP1_NOC, "aclk_isp1_noc", "aclk_isp1", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 3, GFLAGS), + + GATE(HCLK_ISP1_NOC, "hclk_isp1_noc", "hclk_isp1", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 2, GFLAGS), + GATE(ACLK_ISP1_WRAPPER, "aclk_isp1_wrapper", "hclk_isp1", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 8, GFLAGS), + + COMPOSITE(SCLK_ISP1, "clk_isp1", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(55), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(11), 5, GFLAGS), + + /* + * We use pclkin_cifinv by default GRF_SOC_CON20[9] (GSC20_9) setting in system, + * so we ignore the mux and make clocks nodes as following, + * + * pclkin_cifinv --|-------\ + * |GSC20_9|-- pclkin_cifmux -- |G27_6| -- pclkin_isp1_wrapper + * pclkin_cif --|-------/ + */ + GATE(PCLK_ISP1_WRAPPER, "pclkin_isp1_wrapper", "pclkin_cif", CLK_IGNORE_UNUSED, + RK3399_CLKGATE_CON(27), 6, GFLAGS), + + /* cif */ + COMPOSITE(0, "clk_cifout_div", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(56), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKGATE_CON(10), 7, GFLAGS), + MUX(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(56), 5, 1, MFLAGS), + + /* gic */ + COMPOSITE(ACLK_GIC_PRE, "aclk_gic_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK3399_CLKSEL_CON(56), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_CLKGATE_CON(12), 12, GFLAGS), + + GATE(ACLK_GIC, "aclk_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 0, GFLAGS), + GATE(ACLK_GIC_NOC, "aclk_gic_noc", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 1, GFLAGS), + GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_gic_adb400_core_l_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 2, GFLAGS), + GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_gic_adb400_core_b_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 3, GFLAGS), + GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_gic_adb400_gic_2_core_l", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 4, GFLAGS), + GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_gic_adb400_gic_2_core_b", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 5, GFLAGS), + + /* alive */ + /* pclk_alive_gpll_src is controlled by PMUGRF_SOC_CON0[6] */ + DIV(PCLK_ALIVE, "pclk_alive", "gpll", 0, + RK3399_CLKSEL_CON(57), 0, 5, DFLAGS), + + GATE(PCLK_USBPHY_MUX_G, "pclk_usbphy_mux_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 4, GFLAGS), + GATE(PCLK_UPHY0_TCPHY_G, "pclk_uphy0_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 5, GFLAGS), + GATE(PCLK_UPHY0_TCPD_G, "pclk_uphy0_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 6, GFLAGS), + GATE(PCLK_UPHY1_TCPHY_G, "pclk_uphy1_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 8, GFLAGS), + GATE(PCLK_UPHY1_TCPD_G, "pclk_uphy1_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 9, GFLAGS), + + GATE(PCLK_GRF, "pclk_grf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 1, GFLAGS), + GATE(PCLK_INTR_ARB, "pclk_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 2, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 3, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 4, GFLAGS), + GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 5, GFLAGS), + GATE(PCLK_TIMER0, "pclk_timer0", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 6, GFLAGS), + GATE(PCLK_TIMER1, "pclk_timer1", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 7, GFLAGS), + GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS), + GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS), + + GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(11), 14, GFLAGS), + GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS), + + GATE(SCLK_MIPIDPHY_CFG, "clk_mipidphy_cfg", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(11), 15, GFLAGS), + GATE(SCLK_DPHY_TX0_CFG, "clk_dphy_tx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 1, GFLAGS), + GATE(SCLK_DPHY_TX1RX1_CFG, "clk_dphy_tx1rx1_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 2, GFLAGS), + GATE(SCLK_DPHY_RX0_CFG, "clk_dphy_rx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 3, GFLAGS), + + /* testout */ + MUX(0, "clk_test_pre", mux_pll_src_cpll_gpll_p, CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(58), 7, 1, MFLAGS), + COMPOSITE_FRAC(0, "clk_test_frac", "clk_test_pre", CLK_SET_RATE_PARENT, + RK3399_CLKSEL_CON(105), 0, + RK3399_CLKGATE_CON(13), 9, GFLAGS), + + DIV(0, "clk_test_24m", "xin24m", 0, + RK3399_CLKSEL_CON(57), 6, 10, DFLAGS), + + /* spi */ + COMPOSITE(SCLK_SPI0, "clk_spi0", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(59), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 12, GFLAGS), + + COMPOSITE(SCLK_SPI1, "clk_spi1", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(59), 15, 1, MFLAGS, 8, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 13, GFLAGS), + + COMPOSITE(SCLK_SPI2, "clk_spi2", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(60), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 14, GFLAGS), + + COMPOSITE(SCLK_SPI4, "clk_spi4", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(60), 15, 1, MFLAGS, 8, 7, DFLAGS, + RK3399_CLKGATE_CON(9), 15, GFLAGS), + + COMPOSITE(SCLK_SPI5, "clk_spi5", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(58), 15, 1, MFLAGS, 8, 7, DFLAGS, + RK3399_CLKGATE_CON(13), 13, GFLAGS), + + /* i2c */ + COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(61), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(10), 0, GFLAGS), + + COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(62), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(10), 2, GFLAGS), + + COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(63), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_CLKGATE_CON(10), 4, GFLAGS), + + COMPOSITE(SCLK_I2C5, "clk_i2c5", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(61), 15, 1, MFLAGS, 8, 7, DFLAGS, + RK3399_CLKGATE_CON(10), 1, GFLAGS), + + COMPOSITE(SCLK_I2C6, "clk_i2c6", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(62), 15, 1, MFLAGS, 8, 7, DFLAGS, + RK3399_CLKGATE_CON(10), 3, GFLAGS), + + COMPOSITE(SCLK_I2C7, "clk_i2c7", mux_pll_src_cpll_gpll_p, 0, + RK3399_CLKSEL_CON(63), 15, 1, MFLAGS, 8, 7, DFLAGS, + RK3399_CLKGATE_CON(10), 5, GFLAGS), + + /* timer */ + GATE(SCLK_TIMER00, "clk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 0, GFLAGS), + GATE(SCLK_TIMER01, "clk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 1, GFLAGS), + GATE(SCLK_TIMER02, "clk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 2, GFLAGS), + GATE(SCLK_TIMER03, "clk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 3, GFLAGS), + GATE(SCLK_TIMER04, "clk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 4, GFLAGS), + GATE(SCLK_TIMER05, "clk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 5, GFLAGS), + GATE(SCLK_TIMER06, "clk_timer06", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 6, GFLAGS), + GATE(SCLK_TIMER07, "clk_timer07", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 7, GFLAGS), + GATE(SCLK_TIMER08, "clk_timer08", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 8, GFLAGS), + GATE(SCLK_TIMER09, "clk_timer09", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 9, GFLAGS), + GATE(SCLK_TIMER10, "clk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 10, GFLAGS), + GATE(SCLK_TIMER11, "clk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 11, GFLAGS), + + /* clk_test */ + /* clk_test_pre is controlled by CRU_MISC_CON[3] */ + COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED, + RK3368_CLKSEL_CON(58), 0, 5, DFLAGS, + RK3368_CLKGATE_CON(13), 11, GFLAGS), +}; + +static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = { + /* + * PMU CRU Clock-Architecture + */ + + GATE(0, "fclk_cm0s_pmu_ppll_src", "ppll", CLK_IGNORE_UNUSED, + RK3399_PMU_CLKGATE_CON(0), 1, GFLAGS), + + COMPOSITE_NOGATE(FCLK_CM0S_SRC_PMU, "fclk_cm0s_src_pmu", mux_fclk_cm0s_pmu_ppll_p, CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS), + + COMPOSITE(SCLK_SPI3_PMU, "clk_spi3_pmu", mux_24m_ppll_p, CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(1), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_PMU_CLKGATE_CON(0), 2, GFLAGS), + + COMPOSITE(0, "clk_wifi_div", mux_ppll_24m_p, CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(1), 13, 1, MFLAGS, 8, 5, DFLAGS, + RK3399_PMU_CLKGATE_CON(0), 8, GFLAGS), + + COMPOSITE_FRACMUX_NOGATE(0, "clk_wifi_frac", "clk_wifi_div", CLK_SET_RATE_PARENT, + RK3399_PMU_CLKSEL_CON(7), 0, + &rk3399_pmuclk_wifi_fracmux), + + MUX(0, "clk_timer_src_pmu", mux_pll_p, CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(1), 15, 1, MFLAGS), + + COMPOSITE_NOMUX(SCLK_I2C0_PMU, "clk_i2c0_pmu", "ppll", 0, + RK3399_PMU_CLKSEL_CON(2), 0, 7, DFLAGS, + RK3399_PMU_CLKGATE_CON(0), 9, GFLAGS), + + COMPOSITE_NOMUX(SCLK_I2C4_PMU, "clk_i2c4_pmu", "ppll", 0, + RK3399_PMU_CLKSEL_CON(3), 0, 7, DFLAGS, + RK3399_PMU_CLKGATE_CON(0), 11, GFLAGS), + + COMPOSITE_NOMUX(SCLK_I2C8_PMU, "clk_i2c8_pmu", "ppll", 0, + RK3399_PMU_CLKSEL_CON(2), 8, 7, DFLAGS, + RK3399_PMU_CLKGATE_CON(0), 10, GFLAGS), + + DIV(0, "clk_32k_suspend_pmu", "xin24m", CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(4), 0, 10, DFLAGS), + MUX(0, "clk_testout_2io", mux_clk_testout2_2io_p, CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(4), 15, 1, MFLAGS), + + COMPOSITE(0, "clk_uart4_div", mux_24m_ppll_p, CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(5), 10, 1, MFLAGS, 0, 7, DFLAGS, + RK3399_PMU_CLKGATE_CON(0), 5, GFLAGS), + + COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_div", CLK_SET_RATE_PARENT, + RK3399_PMU_CLKSEL_CON(6), 0, + RK3399_PMU_CLKGATE_CON(0), 6, GFLAGS, + &rk3399_uart4_pmu_fracmux), + + DIV(PCLK_SRC_PMU, "pclk_pmu_src", "ppll", CLK_IGNORE_UNUSED, + RK3399_PMU_CLKSEL_CON(0), 0, 5, DFLAGS), + + /* pmu clock gates */ + GATE(SCLK_TIMER12_PMU, "clk_timer0_pmu", "clk_timer_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 3, GFLAGS), + GATE(SCLK_TIMER13_PMU, "clk_timer1_pmu", "clk_timer_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 4, GFLAGS), + + GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 7, GFLAGS), + + GATE(PCLK_PMU, "pclk_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 0, GFLAGS), + GATE(PCLK_PMUGRF_PMU, "pclk_pmugrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 1, GFLAGS), + GATE(PCLK_INTMEM1_PMU, "pclk_intmem1_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 2, GFLAGS), + GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 3, GFLAGS), + GATE(PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 4, GFLAGS), + GATE(PCLK_SGRF_PMU, "pclk_sgrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 5, GFLAGS), + GATE(PCLK_NOC_PMU, "pclk_noc_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 6, GFLAGS), + GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 7, GFLAGS), + GATE(PCLK_I2C4_PMU, "pclk_i2c4_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 8, GFLAGS), + GATE(PCLK_I2C8_PMU, "pclk_i2c8_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 9, GFLAGS), + GATE(PCLK_RKPWM_PMU, "pclk_rkpwm_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 10, GFLAGS), + GATE(PCLK_SPI3_PMU, "pclk_spi3_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 11, GFLAGS), + GATE(PCLK_TIMER_PMU, "pclk_timer_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 12, GFLAGS), + GATE(PCLK_MAILBOX_PMU, "pclk_mailbox_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 13, GFLAGS), + GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS), + GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS), + + GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS), + GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS), + GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS), + GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS), + GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS), +}; + +static const char *const rk3399_cru_critical_clocks[] __initconst = { + "aclk_cci_pre", + "pclk_perilp0", + "pclk_perilp0", + "hclk_perilp0", + "hclk_perilp0_noc", + "pclk_perilp1", + "pclk_perilp1_noc", + "pclk_perihp", + "pclk_perihp_noc", + "hclk_perihp", + "aclk_perihp", + "aclk_perihp_noc", + "aclk_perilp0", + "aclk_perilp0_noc", + "hclk_perilp1", + "hclk_perilp1_noc", + "aclk_dmac0_perilp", + "gpll_hclk_perilp1_src", + "gpll_aclk_perilp0_src", + "gpll_aclk_perihp_src", +}; + +static const char *const rk3399_pmucru_critical_clocks[] __initconst = { + "ppll", + "pclk_pmu_src", + "fclk_cm0s_src_pmu", + "clk_timer_src_pmu", +}; + +static void __init rk3399_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + void __iomem *reg_base; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return; + } + + rockchip_clk_register_plls(ctx, rk3399_pll_clks, + ARRAY_SIZE(rk3399_pll_clks), -1); + + rockchip_clk_register_branches(ctx, rk3399_clk_branches, + ARRAY_SIZE(rk3399_clk_branches)); + + rockchip_clk_protect_critical(rk3399_cru_critical_clocks, + ARRAY_SIZE(rk3399_cru_critical_clocks)); + + rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl", + mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), + &rk3399_cpuclkl_data, rk3399_cpuclkl_rates, + ARRAY_SIZE(rk3399_cpuclkl_rates)); + + rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb", + mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p), + &rk3399_cpuclkb_data, rk3399_cpuclkb_rates, + ARRAY_SIZE(rk3399_cpuclkb_rates)); + + rockchip_register_softrst(np, 21, reg_base + RK3399_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + rockchip_register_restart_notifier(ctx, RK3399_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); +} +CLK_OF_DECLARE(rk3399_cru, "rockchip,rk3399-cru", rk3399_clk_init); + +static void __init rk3399_pmu_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + void __iomem *reg_base; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru pmu region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip pmu clk init failed\n", __func__); + return; + } + + rockchip_clk_register_plls(ctx, rk3399_pmu_pll_clks, + ARRAY_SIZE(rk3399_pmu_pll_clks), -1); + + rockchip_clk_register_branches(ctx, rk3399_clk_pmu_branches, + ARRAY_SIZE(rk3399_clk_pmu_branches)); + + rockchip_clk_protect_critical(rk3399_pmucru_critical_clocks, + ARRAY_SIZE(rk3399_pmucru_critical_clocks)); + + rockchip_register_softrst(np, 2, reg_base + RK3399_PMU_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + rockchip_clk_of_add_provider(np, ctx); +} +CLK_OF_DECLARE(rk3399_cru_pmu, "rockchip,rk3399-pmucru", rk3399_pmu_clk_init); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index cb6a63963693..880349f6d3d7 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -34,7 +34,7 @@ struct clk; #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) -/* register positions shared by RK2928, RK3036, RK3066, RK3188 and RK3228 */ +/* register positions shared by RK2928, RK3036, RK3066, RK3188, RK3228, RK3399 */ #define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) @@ -93,6 +93,26 @@ struct clk; #define RK3368_EMMC_CON0 0x418 #define RK3368_EMMC_CON1 0x41c +#define RK3399_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300) +#define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400) +#define RK3399_GLB_SRST_FST 0x500 +#define RK3399_GLB_SRST_SND 0x504 +#define RK3399_GLB_CNT_TH 0x508 +#define RK3399_MISC_CON 0x50c +#define RK3399_RST_CON 0x510 +#define RK3399_RST_ST 0x514 +#define RK3399_SDMMC_CON0 0x580 +#define RK3399_SDMMC_CON1 0x584 +#define RK3399_SDIO_CON0 0x588 +#define RK3399_SDIO_CON1 0x58c + +#define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80) +#define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100) +#define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110) + enum rockchip_pll_type { pll_rk3036, pll_rk3066, -- GitLab From 3d1477309806459d39e13d8c3206ba35d183c34a Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 19 Mar 2016 18:02:55 +0530 Subject: [PATCH 0283/9938] staging: lustre: lnet: Replace sg++ with sg = sg_next(sg) With scatterlist chaining, simply incrementing the array does not work. sg_next macro was thus introduced to follow the chain links when necessary. So replace sg++ with sg_next. This change was made with the help of the following Coccinelle semantic patch: // @@ struct scatterlist *sg; @@ -sg++ +sg = sg_next(sg) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 2323e8d3a318..cd3fde7c4fbd 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -704,7 +704,7 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, fragnob = min(fragnob, (int)PAGE_SIZE - page_offset); sg_set_page(sg, page, fragnob, page_offset); - sg++; + sg = sg_next(sg); if (offset + fragnob < iov->iov_len) { offset += fragnob; @@ -748,7 +748,7 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, sg_set_page(sg, kiov->kiov_page, fragnob, kiov->kiov_offset + offset); - sg++; + sg = sg_next(sg); offset = 0; kiov++; -- GitLab From bde98b0603cf6ebdf2d5aea7f83f02f88aa35a7f Mon Sep 17 00:00:00 2001 From: James Nunez Date: Sat, 12 Mar 2016 13:00:31 -0500 Subject: [PATCH 0284/9938] staging: lustre: Correct missing newline for CERROR call in sfw_handle_server_rpc This is one of the fixes broken out of patch 10000 that was missed in the merger. With this fix the CERROR called in sfw_handle_server_rpc will print out correctly. Signed-off-by: James Nunez Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4871 Reviewed-on: http://review.whamcloud.com/10000 Reviewed-by: Andreas Dilger Reviewed-by: John L. Hammond Reviewed-by: Cliff White Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/framework.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 926c3970c498..0f32f0be4edc 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -1244,7 +1244,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) /* Remove timer to avoid racing with it or expiring active session */ if (sfw_del_session_timer()) { - CERROR("Dropping RPC (%s) from %s: racing with expiry timer.", + CERROR("dropping RPC %s from %s: racing with expiry timer\n", sv->sv_name, libcfs_id2str(rpc->srpc_peer)); spin_unlock(&sfw_data.fw_lock); return -EAGAIN; -- GitLab From ea25f451a063e1934402fab578d85ea8254d3dee Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Sat, 12 Mar 2016 13:00:32 -0500 Subject: [PATCH 0285/9938] staging: lustre: add missing buffer overflow fix for console.c Patch 9389 change a strncpy call into a strlcpy call. This was missed in the merger into the upstream client. Signed-off-by: Dmitry Eremin Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4629 Reviewed-on: http://review.whamcloud.com/9389 Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 1a923ea3a755..c009ad348a06 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1749,7 +1749,7 @@ lstcon_session_new(char *name, int key, unsigned feats, if (strlen(name) > sizeof(console_session.ses_name) - 1) return -E2BIG; - strncpy(console_session.ses_name, name, + strlcpy(console_session.ses_name, name, sizeof(console_session.ses_name)); rc = lstcon_batch_add(LST_DEFAULT_BATCH); -- GitLab From 3eaf9fcc4b97dc3a475d2328c29cfd46615b3e55 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sat, 12 Mar 2016 13:00:33 -0500 Subject: [PATCH 0286/9938] staging: lustre: handle error returned from wait_event_timeout seltest timer The function wait_event_timeout can fail and return an error. Handle this case in stt_timer_main(). Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/timer.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index 8be52526ae5a..ef8a8a748cbe 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -170,20 +170,22 @@ stt_check_timers(unsigned long *last) static int stt_timer_main(void *arg) { + int rc = 0; + cfs_block_allsigs(); while (!stt_data.stt_shuttingdown) { stt_check_timers(&stt_data.stt_prev_slot); - wait_event_timeout(stt_data.stt_waitq, - stt_data.stt_shuttingdown, - cfs_time_seconds(STTIMER_SLOTTIME)); + rc = wait_event_timeout(stt_data.stt_waitq, + stt_data.stt_shuttingdown, + cfs_time_seconds(STTIMER_SLOTTIME)); } spin_lock(&stt_data.stt_lock); stt_data.stt_nthreads--; spin_unlock(&stt_data.stt_lock); - return 0; + return rc; } static int -- GitLab From 9b8fa4456cf3f6428958a71fdcc5fef64f3f0e11 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sat, 12 Mar 2016 13:00:34 -0500 Subject: [PATCH 0287/9938] staging: lustre: remove excess blank lines in lnet selftest code Remove extra blank lines missed by checkpatch. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/brw_test.c | 2 -- drivers/staging/lustre/lnet/selftest/conrpc.c | 2 -- drivers/staging/lustre/lnet/selftest/console.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index eebc92412061..69812fc3c9ed 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -91,7 +91,6 @@ brw_client_init(sfw_test_instance_t *tsi) * but we have to keep it for compatibility */ len = npg * PAGE_CACHE_SIZE; - } else { test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; @@ -279,7 +278,6 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, flags = breq->blk_flags; npg = breq->blk_npg; len = npg * PAGE_CACHE_SIZE; - } else { test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index bcd78888f9cc..d11869aa5db4 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -531,7 +531,6 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, continue; error = readent(trans->tas_opc, msg, ent); - if (error) return error; } @@ -841,7 +840,6 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, trq->tsr_ndest = 0; trq->tsr_loop = nmax * test->tes_dist * test->tes_concur; - } else { bulk = &(*crpc)->crp_rpc->crpc_bulk; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index c009ad348a06..17d0d132d103 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -977,7 +977,6 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, if (!test) { entp->u.tbe_batch.bae_ntest = bat->bat_ntest; entp->u.tbe_batch.bae_state = bat->bat_state; - } else { entp->u.tbe_test.tse_type = test->tes_type; entp->u.tbe_test.tse_loop = test->tes_loop; @@ -1423,7 +1422,6 @@ lstcon_test_batch_query(char *name, int testidx, int client, translist = &batch->bat_trans_list; ndlist = &batch->bat_cli_list; hdr = &batch->bat_hdr; - } else { /* query specified test only */ rc = lstcon_test_find(batch, testidx, &test); -- GitLab From 0b4427deebab7cf86917772f8e00061c63494cd3 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sat, 12 Mar 2016 13:00:35 -0500 Subject: [PATCH 0288/9938] staging: lustre: realign some code in lnet selftest so its readable Two places to align the code so it is easier to read. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/console.c | 2 +- drivers/staging/lustre/lnet/selftest/ping_test.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 17d0d132d103..6ec895208c26 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -733,7 +733,7 @@ lstcon_group_list(int index, int len, char __user *name_up) list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) { if (!index--) { return copy_to_user(name_up, grp->grp_name, len) ? - -EFAULT : 0; + -EFAULT : 0; } } diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index 81a45045e186..438fca2e9b95 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -86,8 +86,8 @@ ping_client_fini(sfw_test_instance_t *tsi) } static int -ping_client_prep_rpc(sfw_test_unit_t *tsu, - lnet_process_id_t dest, srpc_client_rpc_t **rpc) +ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, + srpc_client_rpc_t **rpc) { srpc_ping_reqst_t *req; sfw_test_instance_t *tsi = tsu->tsu_instance; -- GitLab From dae0587ef0c8e6584837d3737fc5555eb2b36097 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sat, 12 Mar 2016 13:00:36 -0500 Subject: [PATCH 0289/9938] staging: lustre: cleanup comment style for lnet selftest Apply a consistent style for comments in the lnet selftest code. Realign some of the comments to make it easier to read. This also fixes a few checkpatch issues as well. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 2 +- drivers/staging/lustre/lnet/selftest/conctl.c | 50 +++++++++---------- drivers/staging/lustre/lnet/selftest/conrpc.c | 17 ++++--- .../staging/lustre/lnet/selftest/console.c | 5 +- .../staging/lustre/lnet/selftest/framework.c | 12 ++--- .../staging/lustre/lnet/selftest/ping_test.c | 2 +- drivers/staging/lustre/lnet/selftest/rpc.c | 8 +-- drivers/staging/lustre/lnet/selftest/timer.c | 2 +- 8 files changed, 50 insertions(+), 48 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 69812fc3c9ed..b33c35694eb1 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -327,7 +327,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) if (rpc->crpc_status) { CERROR("BRW RPC to %s failed with %d\n", libcfs_id2str(rpc->crpc_dest), rpc->crpc_status); - if (!tsi->tsi_stopping) /* rpc could have been aborted */ + if (!tsi->tsi_stopping) /* rpc could have been aborted */ atomic_inc(&sn->sn_brw_errors); return; } diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index 5c7cb72eac9a..6e2a81d8e730 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -51,9 +51,9 @@ lst_session_new_ioctl(lstio_session_new_args_t *args) char *name; int rc; - if (!args->lstio_ses_idp || /* address for output sid */ - !args->lstio_ses_key || /* no key is specified */ - !args->lstio_ses_namep || /* session name */ + if (!args->lstio_ses_idp || /* address for output sid */ + !args->lstio_ses_key || /* no key is specified */ + !args->lstio_ses_namep || /* session name */ args->lstio_ses_nmlen <= 0 || args->lstio_ses_nmlen > LST_NAME_SIZE) return -EINVAL; @@ -95,11 +95,11 @@ lst_session_info_ioctl(lstio_session_info_args_t *args) { /* no checking of key */ - if (!args->lstio_ses_idp || /* address for output sid */ - !args->lstio_ses_keyp || /* address for output key */ - !args->lstio_ses_featp || /* address for output features */ - !args->lstio_ses_ndinfo || /* address for output ndinfo */ - !args->lstio_ses_namep || /* address for output name */ + if (!args->lstio_ses_idp || /* address for output sid */ + !args->lstio_ses_keyp || /* address for output key */ + !args->lstio_ses_featp || /* address for output features */ + !args->lstio_ses_ndinfo || /* address for output ndinfo */ + !args->lstio_ses_namep || /* address for output name */ args->lstio_ses_nmlen <= 0 || args->lstio_ses_nmlen > LST_NAME_SIZE) return -EINVAL; @@ -125,7 +125,7 @@ lst_debug_ioctl(lstio_debug_args_t *args) if (!args->lstio_dbg_resultp) return -EINVAL; - if (args->lstio_dbg_namep && /* name of batch/group */ + if (args->lstio_dbg_namep && /* name of batch/group */ (args->lstio_dbg_nmlen <= 0 || args->lstio_dbg_nmlen > LST_NAME_SIZE)) return -EINVAL; @@ -326,7 +326,7 @@ lst_nodes_add_ioctl(lstio_group_nodes_args_t *args) if (args->lstio_grp_key != console_session.ses_key) return -EACCES; - if (!args->lstio_grp_idsp || /* array of ids */ + if (!args->lstio_grp_idsp || /* array of ids */ args->lstio_grp_count <= 0 || !args->lstio_grp_resultp || !args->lstio_grp_featp || @@ -394,13 +394,13 @@ lst_group_info_ioctl(lstio_group_info_args_t *args) args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; - if (!args->lstio_grp_entp && /* output: group entry */ - !args->lstio_grp_dentsp) /* output: node entry */ + if (!args->lstio_grp_entp && /* output: group entry */ + !args->lstio_grp_dentsp) /* output: node entry */ return -EINVAL; - if (args->lstio_grp_dentsp) { /* have node entry */ - if (!args->lstio_grp_idxp || /* node index */ - !args->lstio_grp_ndentp) /* # of node entry */ + if (args->lstio_grp_dentsp) { /* have node entry */ + if (!args->lstio_grp_idxp || /* node index */ + !args->lstio_grp_ndentp) /* # of node entry */ return -EINVAL; if (copy_from_user(&ndent, args->lstio_grp_ndentp, @@ -612,18 +612,18 @@ lst_batch_info_ioctl(lstio_batch_info_args_t *args) if (args->lstio_bat_key != console_session.ses_key) return -EACCES; - if (!args->lstio_bat_namep || /* batch name */ + if (!args->lstio_bat_namep || /* batch name */ args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; - if (!args->lstio_bat_entp && /* output: batch entry */ - !args->lstio_bat_dentsp) /* output: node entry */ + if (!args->lstio_bat_entp && /* output: batch entry */ + !args->lstio_bat_dentsp) /* output: node entry */ return -EINVAL; - if (args->lstio_bat_dentsp) { /* have node entry */ - if (!args->lstio_bat_idxp || /* node index */ - !args->lstio_bat_ndentp) /* # of node entry */ + if (args->lstio_bat_dentsp) { /* have node entry */ + if (!args->lstio_bat_idxp || /* node index */ + !args->lstio_bat_ndentp) /* # of node entry */ return -EINVAL; if (copy_from_user(&index, args->lstio_bat_idxp, @@ -722,18 +722,18 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) if (!args->lstio_tes_resultp || !args->lstio_tes_retp || - !args->lstio_tes_bat_name || /* no specified batch */ + !args->lstio_tes_bat_name || /* no specified batch */ args->lstio_tes_bat_nmlen <= 0 || args->lstio_tes_bat_nmlen > LST_NAME_SIZE || - !args->lstio_tes_sgrp_name || /* no source group */ + !args->lstio_tes_sgrp_name || /* no source group */ args->lstio_tes_sgrp_nmlen <= 0 || args->lstio_tes_sgrp_nmlen > LST_NAME_SIZE || - !args->lstio_tes_dgrp_name || /* no target group */ + !args->lstio_tes_dgrp_name || /* no target group */ args->lstio_tes_dgrp_nmlen <= 0 || args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE) return -EINVAL; - if (!args->lstio_tes_loop || /* negative is infinite */ + if (!args->lstio_tes_loop || /* negative is infinite */ args->lstio_tes_concur <= 0 || args->lstio_tes_dist <= 0 || args->lstio_tes_span <= 0) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index d11869aa5db4..3908c100ccb2 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -296,8 +296,8 @@ lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) spin_lock(&rpc->crpc_lock); - if (!crpc->crp_posted || /* not posted */ - crpc->crp_stamp) { /* rpc done or aborted already */ + if (!crpc->crp_posted || /* not posted */ + crpc->crp_stamp) { /* rpc done or aborted already */ if (!crpc->crp_stamp) { crpc->crp_stamp = cfs_time_current(); crpc->crp_status = -EINTR; @@ -562,10 +562,10 @@ lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) } /* - * rpcs can be still not callbacked (even LNetMDUnlink is called) - * because huge timeout for inaccessible network, don't make - * user wait for them, just abandon them, they will be recycled - * in callback + * rpcs can be still not callbacked (even LNetMDUnlink is + * called) because huge timeout for inaccessible network, + * don't make user wait for them, just abandon them, they + * will be recycled in callback */ LASSERT(crpc->crp_status); @@ -938,7 +938,7 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, if (!trans->tas_feats_updated) { spin_lock(&console_session.ses_rpc_lock); - if (!trans->tas_feats_updated) { /* recheck with lock */ + if (!trans->tas_feats_updated) { /* recheck with lock */ trans->tas_feats_updated = 1; trans->tas_features = reply->msg_ses_feats; } @@ -1178,7 +1178,8 @@ lstcon_rpc_pinger(void *arg) int count = 0; int rc; - /* RPC pinger is a special case of transaction, + /* + * RPC pinger is a special case of transaction, * it's called by timer at 8 seconds interval. */ mutex_lock(&console_session.ses_mutex); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 6ec895208c26..dcfc83d0ad41 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -277,7 +277,7 @@ lstcon_group_find(const char *name, lstcon_group_t **grpp) if (strncmp(grp->grp_name, name, LST_NAME_SIZE)) continue; - lstcon_group_addref(grp); /* +1 ref for caller */ + lstcon_group_addref(grp); /* +1 ref for caller */ *grpp = grp; return 0; } @@ -1446,7 +1446,8 @@ lstcon_test_batch_query(char *name, int testidx, int client, lstcon_rpc_trans_postwait(trans, timeout); - if (!testidx && /* query a batch, not a test */ + /* query a batch, not a test */ + if (!testidx && !lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) && !lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0)) { /* all RPCs finished, and no active test */ diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 0f32f0be4edc..aa646a780f58 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -226,7 +226,7 @@ __must_hold(&sfw_data.fw_lock) } if (nactive) - return; /* wait for active batches to stop */ + return; /* wait for active batches to stop */ list_del_init(&sn->sn_list); spin_unlock(&sfw_data.fw_lock); @@ -693,7 +693,7 @@ sfw_unpack_addtest_req(srpc_msg_t *msg) LASSERT(req->tsr_is_client); if (msg->msg_magic == SRPC_MSG_MAGIC) - return; /* no flipping needed */ + return; /* no flipping needed */ LASSERT(msg->msg_magic == __swab32(SRPC_MSG_MAGIC)); @@ -789,7 +789,7 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) int j; dests = page_address(bk->bk_iovs[i / SFW_ID_PER_PAGE].kiov_page); - LASSERT(dests); /* my pages are within KVM always */ + LASSERT(dests); /* my pages are within KVM always */ id = dests[i % SFW_ID_PER_PAGE]; if (msg->msg_magic != SRPC_MSG_MAGIC) sfw_unpack_id(id); @@ -844,8 +844,8 @@ sfw_test_unit_done(sfw_test_unit_t *tsu) spin_lock(&sfw_data.fw_lock); - if (!atomic_dec_and_test(&tsb->bat_nactive) ||/* tsb still active */ - sn == sfw_data.fw_session) { /* sn also active */ + if (!atomic_dec_and_test(&tsb->bat_nactive) || /* tsb still active */ + sn == sfw_data.fw_session) { /* sn also active */ spin_unlock(&sfw_data.fw_lock); return; } @@ -1273,7 +1273,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) } } else if (request->msg_ses_feats & ~LST_FEATS_MASK) { - /** + /* * NB: at this point, old version will ignore features and * create new session anyway, so console should be able * to handle this diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index 438fca2e9b95..c7c50be6dab4 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -129,7 +129,7 @@ ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) LASSERT(sn); if (rpc->crpc_status) { - if (!tsi->tsi_stopping) /* rpc could have been aborted */ + if (!tsi->tsi_stopping) /* rpc could have been aborted */ atomic_inc(&sn->sn_ping_errors); CERROR("Unable to ping %s (%d): %d\n", libcfs_id2str(rpc->crpc_dest), diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 69be7d6f48fa..ab8ba3724954 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -1332,8 +1332,8 @@ srpc_abort_rpc(srpc_client_rpc_t *rpc, int why) { LASSERT(why); - if (rpc->crpc_aborted || /* already aborted */ - rpc->crpc_closed) /* callback imminent */ + if (rpc->crpc_aborted || /* already aborted */ + rpc->crpc_closed) /* callback imminent */ return; CDEBUG(D_NET, "Aborting RPC: service %d, peer %s, state %s, why %d\n", @@ -1401,7 +1401,7 @@ srpc_send_reply(struct srpc_server_rpc *rpc) rpc->srpc_peer, rpc->srpc_self, &rpc->srpc_replymdh, ev); if (rc) - ev->ev_fired = 1; /* no more event expected */ + ev->ev_fired = 1; /* no more event expected */ return rc; } @@ -1509,7 +1509,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) scd->scd_buf_err = 0; } - if (!scd->scd_buf_err && /* adding buffer is enabled */ + if (!scd->scd_buf_err && /* adding buffer is enabled */ !scd->scd_buf_adjust && scd->scd_buf_nposted < scd->scd_buf_low) { scd->scd_buf_adjust = max(scd->scd_buf_total / 2, diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index ef8a8a748cbe..b6c4aae007af 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -49,7 +49,7 @@ * sorted by increasing expiry time. The number of slots is 2**7 (128), * to cover a time period of 1024 seconds into the future before wrapping. */ -#define STTIMER_MINPOLL 3 /* log2 min poll interval (8 s) */ +#define STTIMER_MINPOLL 3 /* log2 min poll interval (8 s) */ #define STTIMER_SLOTTIME (1 << STTIMER_MINPOLL) #define STTIMER_SLOTTIMEMASK (~(STTIMER_SLOTTIME - 1)) #define STTIMER_NSLOTS (1 << 7) -- GitLab From b899963f158056f19928ed5dc7314fac5b57db97 Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 11 Mar 2016 17:01:38 -0500 Subject: [PATCH 0290/9938] staging: unisys: visorbus: cleanup goto in setup_crash_devices_work_queue If visorbus has registered yet just reschedule and exit. The rest of the function doesn't need to reschedule so just move it up to the initial check. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 5fbda7b218c7..3fd4bea6535d 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1979,8 +1979,11 @@ setup_crash_devices_work_queue(struct work_struct *work) u16 local_crash_msg_count; /* make sure visorbus is registered for controlvm callbacks */ - if (visorchipset_visorbusregwait && !visorbusregistered) - goto cleanup; + if (visorchipset_visorbusregwait && !visorbusregistered) { + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); + return; + } POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO); @@ -2057,13 +2060,6 @@ setup_crash_devices_work_queue(struct work_struct *work) return; } POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO); - return; - -cleanup: - - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); } static void -- GitLab From dde29996cdb1514a457ffbfaaf8f795d66fe2a5a Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 11 Mar 2016 17:01:39 -0500 Subject: [PATCH 0291/9938] staging: unisys: visorbus: get rid of gotos in intialize_controlvm_payload_info Get rid of the gotos in initialize_controlvm_payload_info. The check in the error path if payload was valid was never called so get rid of that as well. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorchipset.c | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 3fd4bea6535d..6ab659cbd6d5 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1382,35 +1382,23 @@ initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes, struct visor_controlvm_payload_info *info) { u8 *payload = NULL; - int rc = CONTROLVM_RESP_SUCCESS; - if (!info) { - rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; - goto cleanup; - } + if (!info) + return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); - if ((offset == 0) || (bytes == 0)) { - rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; - goto cleanup; - } + if ((offset == 0) || (bytes == 0)) + return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; + payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB); - if (!payload) { - rc = -CONTROLVM_RESP_ERROR_IOREMAP_FAILED; - goto cleanup; - } + if (!payload) + return -CONTROLVM_RESP_ERROR_IOREMAP_FAILED; info->offset = offset; info->bytes = bytes; info->ptr = payload; -cleanup: - if (rc < 0) { - if (payload) { - memunmap(payload); - payload = NULL; - } - } - return rc; + return CONTROLVM_RESP_SUCCESS; } static void -- GitLab From d79f56b59917fcd3e21190f281e07ebda628eb17 Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 11 Mar 2016 17:01:40 -0500 Subject: [PATCH 0292/9938] staging: unisys: visorbus: cleanup gotos in parser_init_byte_stream Clean up the goto in parser_init_byte_stream and make the goto section the error case. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorchipset.c | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 6ab659cbd6d5..6598d6977263 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -359,8 +359,7 @@ static struct parser_context * parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) { int allocbytes = sizeof(struct parser_context) + bytes; - struct parser_context *rc = NULL; - struct parser_context *ctx = NULL; + struct parser_context *ctx; if (retry) *retry = false; @@ -374,15 +373,13 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) > MAX_CONTROLVM_PAYLOAD_BYTES) { if (retry) *retry = true; - rc = NULL; - goto cleanup; + return NULL; } ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); if (!ctx) { if (retry) *retry = true; - rc = NULL; - goto cleanup; + return NULL; } ctx->allocbytes = allocbytes; @@ -393,35 +390,27 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) if (local) { void *p; - if (addr > virt_to_phys(high_memory - 1)) { - rc = NULL; - goto cleanup; - } + if (addr > virt_to_phys(high_memory - 1)) + goto err_finish_ctx; p = __va((unsigned long)(addr)); memcpy(ctx->data, p, bytes); } else { void *mapping = memremap(addr, bytes, MEMREMAP_WB); - if (!mapping) { - rc = NULL; - goto cleanup; - } + if (!mapping) + goto err_finish_ctx; memcpy(ctx->data, mapping, bytes); memunmap(mapping); } ctx->byte_stream = true; - rc = ctx; -cleanup: - if (rc) { - controlvm_payload_bytes_buffered += ctx->param_bytes; - } else { - if (ctx) { - parser_done(ctx); - ctx = NULL; - } - } - return rc; + controlvm_payload_bytes_buffered += ctx->param_bytes; + + return ctx; + +err_finish_ctx: + parser_done(ctx); + return NULL; } static uuid_le -- GitLab From 5233d1ebb6c99ca67521cdeb66dccd1256820d5f Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 11 Mar 2016 17:01:41 -0500 Subject: [PATCH 0293/9938] staging: unisys: visorbus: chipset_init rename goto Change the goto label "cleanup" to something more useful like out_respond. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 6598d6977263..e278595d68e2 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -761,7 +761,7 @@ chipset_init(struct controlvm_message *inmsg) POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); if (chipset_inited) { rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; + goto out_respond; } chipset_inited = 1; POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); @@ -778,7 +778,7 @@ chipset_init(struct controlvm_message *inmsg) */ features |= ULTRA_CHIPSET_FEATURE_REPLY; -cleanup: +out_respond: if (inmsg->hdr.flags.response_expected) controlvm_respond_chipset_init(&inmsg->hdr, rc, features); } -- GitLab From 9fd04060abdfd1e2ec763ea0096cc91026c77cca Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 11 Mar 2016 17:01:42 -0500 Subject: [PATCH 0294/9938] staging: unisys: visorbus: Cleanup goto in bus_create Rename it to what it does instead of the default ambiguous cleanup. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index e278595d68e2..49d99229d241 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1131,14 +1131,14 @@ bus_create(struct controlvm_message *inmsg) POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; + goto out_bus_epilog; } bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL); if (!bus_info) { POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto cleanup; + goto out_bus_epilog; } INIT_LIST_HEAD(&bus_info->list_all); @@ -1158,7 +1158,7 @@ bus_create(struct controlvm_message *inmsg) rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; kfree(bus_info); bus_info = NULL; - goto cleanup; + goto out_bus_epilog; } bus_info->visorchannel = visorchannel; if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) { @@ -1168,7 +1168,7 @@ bus_create(struct controlvm_message *inmsg) POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); -cleanup: +out_bus_epilog: bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr, rc, inmsg->hdr.flags.response_expected == 1); } -- GitLab From 368acb3f512b415d11bfc3801b4a3d1453cc455d Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 11 Mar 2016 17:01:43 -0500 Subject: [PATCH 0295/9938] staging: unisys: visorbus: Cleanup bus_epilog goto statements Cleaned up bus_epilogs vague gotos and in the process discovered some error paths that could unlock a non locked semaphore. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 49d99229d241..b1c5e9e78679 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -962,25 +962,29 @@ bus_epilog(struct visor_device *bus_info, bool notified = false; struct controlvm_message_header *pmsg_hdr = NULL; + down(¬ifier_lock); + if (!bus_info) { /* relying on a valid passed in response code */ /* be lazy and re-use msg_hdr for this failure, is this ok?? */ pmsg_hdr = msg_hdr; - goto away; + goto out_respond_and_unlock; } if (bus_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = bus_info->pending_msg_hdr; - goto away; + goto out_respond_and_unlock; } if (need_response) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { - response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto away; + POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd, + bus_info->chipset_bus_no, + POSTCODE_SEVERITY_ERR); + goto out_unlock; } memcpy(pmsg_hdr, msg_hdr, @@ -988,7 +992,6 @@ bus_epilog(struct visor_device *bus_info, bus_info->pending_msg_hdr = pmsg_hdr; } - down(¬ifier_lock); if (response == CONTROLVM_RESP_SUCCESS) { switch (cmd) { case CONTROLVM_BUS_CREATE: @@ -1005,7 +1008,8 @@ bus_epilog(struct visor_device *bus_info, break; } } -away: + +out_respond_and_unlock: if (notified) /* The callback function just called above is responsible * for calling the appropriate visorchipset_busdev_responders @@ -1019,6 +1023,8 @@ bus_epilog(struct visor_device *bus_info, * directly and kfree() there. */ bus_responder(cmd, pmsg_hdr, response); + +out_unlock: up(¬ifier_lock); } -- GitLab From c6af7a9cbcfa65b9322436836ad7cc323d2d5d6d Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 11 Mar 2016 17:01:44 -0500 Subject: [PATCH 0296/9938] staging: unisys: visorbus: fix my_create_device goto statements Don't use the abmiguous cleanup, make it more meaningful. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index b1c5e9e78679..17bedbc6761d 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1255,14 +1255,14 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - goto cleanup; + goto out_respond; } if (bus_info->state.created == 0) { POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - goto cleanup; + goto out_respond; } dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL); @@ -1270,7 +1270,7 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; + goto out_respond; } dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); @@ -1278,7 +1278,7 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto cleanup; + goto out_respond; } dev_info->chipset_bus_no = bus_no; @@ -1303,7 +1303,7 @@ my_device_create(struct controlvm_message *inmsg) rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; kfree(dev_info); dev_info = NULL; - goto cleanup; + goto out_respond; } dev_info->visorchannel = visorchannel; dev_info->channel_type_guid = cmd->create_device.data_type_uuid; @@ -1313,7 +1313,7 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no, POSTCODE_SEVERITY_INFO); -cleanup: +out_respond: device_epilog(dev_info, segment_state_running, CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc, inmsg->hdr.flags.response_expected == 1, 1); -- GitLab From 4000622ec21ba5e93fdb74bc4168a9545a089ce7 Mon Sep 17 00:00:00 2001 From: David Kershner Date: Sat, 12 Mar 2016 21:27:08 -0500 Subject: [PATCH 0297/9938] staging: unisys: visorbus: Fix up visordriver_probe Fixup the visordriver_probe function. Rearrange the function to avoid needing gotos and removed unnecessary wmb(). Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorbus_main.c | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 533bb5b3d284..6a12829151e0 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -752,36 +752,28 @@ dev_stop_periodic_work(struct visor_device *dev) static int visordriver_probe_device(struct device *xdev) { - int rc; + int res; struct visor_driver *drv; struct visor_device *dev; drv = to_visor_driver(xdev->driver); dev = to_visor_device(xdev); + + if (!drv->probe) + return -ENODEV; + down(&dev->visordriver_callback_lock); dev->being_removed = false; - /* - * ensure that the dev->being_removed flag is cleared before - * we start the probe - */ - wmb(); - get_device(&dev->device); - if (!drv->probe) { - up(&dev->visordriver_callback_lock); - rc = -ENODEV; - goto away; + + res = drv->probe(dev); + if (res >= 0) { + /* success: reference kept via unmatched get_device() */ + get_device(&dev->device); + fix_vbus_dev_info(dev); } - rc = drv->probe(dev); - if (rc < 0) - goto away; - fix_vbus_dev_info(dev); up(&dev->visordriver_callback_lock); - rc = 0; -away: - if (rc != 0) - put_device(&dev->device); - return rc; + return res; } /** This is called when device_unregister() is called for each child device -- GitLab From b750b05939778a8b43fc7e3c96a48f59d123451d Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Sat, 12 Mar 2016 21:27:09 -0500 Subject: [PATCH 0298/9938] staging: unisys: visorbus: remove unused sysfs attribute devmajorminor/* The sysfs attribute directory at: /sys/bus/visorbus/devices/vbus:dev/devmajorminor/* or /sys/devices/visorbus/vbus:dev/devmajorminor/* previously provided a location where a visorbus function driver could publish information (for usermode use) about possibly-multiple major and minor device numbers for character devices created for a each visorbus device, using visorbus_registerdevnode(). This functionality is not currently used, so it has been removed by this cset. Signed-off-by: Tim Sell Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/Documentation/overview.txt | 19 -- drivers/staging/unisys/include/visorbus.h | 3 - .../staging/unisys/visorbus/visorbus_main.c | 194 ------------------ 3 files changed, 216 deletions(-) diff --git a/drivers/staging/unisys/Documentation/overview.txt b/drivers/staging/unisys/Documentation/overview.txt index c2d8dd4a2e41..1146c1cf5c2a 100644 --- a/drivers/staging/unisys/Documentation/overview.txt +++ b/drivers/staging/unisys/Documentation/overview.txt @@ -137,12 +137,6 @@ called automatically by the visorbus driver at appropriate times: * The resume() function is the "book-end" to pause(), and is described above. -If/when a function driver creates a Linux device (that needs to be accessed -from usermode), it calls visorbus_registerdevnode(), passing the major and -minor number of the device. (Of course not all function drivers will need -to do this.) This simply creates the appropriate "devmajorminor" sysfs entry -described below, so that a hotplug script can use it to create a device node. - 2.1.3. sysfs Advertised Information ----------------------------------- @@ -197,19 +191,6 @@ The following files exist under /sys/devices/visorbus/vbus:dev: if the appropriate function driver has not been loaded yet. - devmajorminor - - if applicable, each file here identifies (via - ... its file contents) the - ":" needed for a device node to - enable access from usermode. There is exactly - one file here for each different device node - that can be accessed (from usermode). Note - that this info is provided by a particular - function driver, so these will not exist - until AFTER the appropriate function driver - controlling this device class is loaded. - channel properties of the device channel (all in ascii text format) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 2a64a9ce0208..9c47a138e748 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -136,7 +136,6 @@ struct visor_device { struct periodic_work *periodic_work; bool being_removed; bool responded_to_device_create; - struct kobject kobjdevmajorminor; /* visorbus/dev/devmajorminor/*/ struct { int major, minor; void *attr; /* private use by devmajorminor_attr.c you can @@ -174,8 +173,6 @@ int visorbus_write_channel(struct visor_device *dev, unsigned long nbytes); int visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch, unsigned long nbytes); -int visorbus_registerdevnode(struct visor_device *dev, - const char *name, int major, int minor); void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); #endif diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 6a12829151e0..813d29ea0c4e 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -243,180 +243,6 @@ visorbus_release_device(struct device *xdev) kfree(dev); } -/* Implement publishing of device node attributes under: - * - * /sys/bus/visorbus/dev/devmajorminor - * - */ - -#define to_devmajorminor_attr(_attr) \ - container_of(_attr, struct devmajorminor_attribute, attr) -#define to_visor_device_from_kobjdevmajorminor(obj) \ - container_of(obj, struct visor_device, kobjdevmajorminor) - -struct devmajorminor_attribute { - struct attribute attr; - int slot; - ssize_t (*show)(struct visor_device *, int slot, char *buf); - ssize_t (*store)(struct visor_device *, int slot, const char *buf, - size_t count); -}; - -static ssize_t DEVMAJORMINOR_ATTR(struct visor_device *dev, int slot, char *buf) -{ - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - - if (slot < 0 || slot >= maxdevnodes) - return 0; - return snprintf(buf, PAGE_SIZE, "%d:%d\n", - dev->devnodes[slot].major, dev->devnodes[slot].minor); -} - -static ssize_t -devmajorminor_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct devmajorminor_attribute *devmajorminor_attr = - to_devmajorminor_attr(attr); - struct visor_device *dev = to_visor_device_from_kobjdevmajorminor(kobj); - ssize_t ret = 0; - - if (devmajorminor_attr->show) - ret = devmajorminor_attr->show(dev, - devmajorminor_attr->slot, buf); - return ret; -} - -static ssize_t -devmajorminor_attr_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - struct devmajorminor_attribute *devmajorminor_attr = - to_devmajorminor_attr(attr); - struct visor_device *dev = to_visor_device_from_kobjdevmajorminor(kobj); - ssize_t ret = 0; - - if (devmajorminor_attr->store) - ret = devmajorminor_attr->store(dev, - devmajorminor_attr->slot, - buf, count); - return ret; -} - -static int register_devmajorminor_attributes(struct visor_device *dev); - -static int -devmajorminor_create_file(struct visor_device *dev, const char *name, - int major, int minor) -{ - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - struct devmajorminor_attribute *myattr = NULL; - int x = -1, rc = 0, slot = -1; - - register_devmajorminor_attributes(dev); - for (slot = 0; slot < maxdevnodes; slot++) - if (!dev->devnodes[slot].attr) - break; - if (slot == maxdevnodes) { - rc = -ENOMEM; - goto away; - } - myattr = kzalloc(sizeof(*myattr), GFP_KERNEL); - if (!myattr) { - rc = -ENOMEM; - goto away; - } - myattr->show = DEVMAJORMINOR_ATTR; - myattr->store = NULL; - myattr->slot = slot; - myattr->attr.name = name; - myattr->attr.mode = S_IRUGO; - dev->devnodes[slot].attr = myattr; - dev->devnodes[slot].major = major; - dev->devnodes[slot].minor = minor; - x = sysfs_create_file(&dev->kobjdevmajorminor, &myattr->attr); - if (x < 0) { - rc = x; - goto away; - } - kobject_uevent(&dev->device.kobj, KOBJ_ONLINE); -away: - if (rc < 0) { - kfree(myattr); - myattr = NULL; - dev->devnodes[slot].attr = NULL; - } - return rc; -} - -static void -devmajorminor_remove_file(struct visor_device *dev, int slot) -{ - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - struct devmajorminor_attribute *myattr = NULL; - - if (slot < 0 || slot >= maxdevnodes) - return; - myattr = (struct devmajorminor_attribute *)(dev->devnodes[slot].attr); - if (!myattr) - return; - sysfs_remove_file(&dev->kobjdevmajorminor, &myattr->attr); - kobject_uevent(&dev->device.kobj, KOBJ_OFFLINE); - dev->devnodes[slot].attr = NULL; - kfree(myattr); -} - -static void -devmajorminor_remove_all_files(struct visor_device *dev) -{ - int i = 0; - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - - for (i = 0; i < maxdevnodes; i++) - devmajorminor_remove_file(dev, i); -} - -static const struct sysfs_ops devmajorminor_sysfs_ops = { - .show = devmajorminor_attr_show, - .store = devmajorminor_attr_store, -}; - -static struct kobj_type devmajorminor_kobj_type = { - .sysfs_ops = &devmajorminor_sysfs_ops -}; - -static int -register_devmajorminor_attributes(struct visor_device *dev) -{ - int rc = 0, x = 0; - - if (dev->kobjdevmajorminor.parent) - goto away; /* already registered */ - x = kobject_init_and_add(&dev->kobjdevmajorminor, - &devmajorminor_kobj_type, &dev->device.kobj, - "devmajorminor"); - if (x < 0) { - rc = x; - goto away; - } - - kobject_uevent(&dev->kobjdevmajorminor, KOBJ_ADD); - -away: - return rc; -} - -static void -unregister_devmajorminor_attributes(struct visor_device *dev) -{ - if (!dev->kobjdevmajorminor.parent) - return; /* already unregistered */ - devmajorminor_remove_all_files(dev); - - kobject_del(&dev->kobjdevmajorminor); - kobject_put(&dev->kobjdevmajorminor); - dev->kobjdevmajorminor.parent = NULL; -} - /* begin implementation of specific channel attributes to appear under * /sys/bus/visorbus/dev/channel */ @@ -801,7 +627,6 @@ visordriver_remove_device(struct device *xdev) } up(&dev->visordriver_callback_lock); dev_stop_periodic_work(dev); - devmajorminor_remove_all_files(dev); put_device(&dev->device); @@ -920,14 +745,6 @@ visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch, } EXPORT_SYMBOL_GPL(visorbus_clear_channel); -int -visorbus_registerdevnode(struct visor_device *dev, - const char *name, int major, int minor) -{ - return devmajorminor_create_file(dev, name, major, minor); -} -EXPORT_SYMBOL_GPL(visorbus_registerdevnode); - /** We don't really have a real interrupt, so for now we just call the * interrupt function periodically... */ @@ -1018,19 +835,9 @@ create_visor_device(struct visor_device *dev) goto away; } - rc = register_devmajorminor_attributes(dev); - if (rc < 0) { - POSTCODE_LINUX_3(DEVICE_REGISTER_FAILURE_PC, chipset_dev_no, - DIAG_SEVERITY_ERR); - goto away_unregister; - } - list_add_tail(&dev->list_all, &list_all_device_instances); return 0; -away_unregister: - device_unregister(&dev->device); - away: put_device(&dev->device); return rc; @@ -1040,7 +847,6 @@ static void remove_visor_device(struct visor_device *dev) { list_del(&dev->list_all); - unregister_devmajorminor_attributes(dev); put_device(&dev->device); device_unregister(&dev->device); } -- GitLab From 78af1aef662eef4ffac6f453fdc46d3389274f34 Mon Sep 17 00:00:00 2001 From: David Kershner Date: Sat, 12 Mar 2016 21:27:10 -0500 Subject: [PATCH 0299/9938] staging: unisys: visorbus: fix up gotos in visorbus_init This patch fixes the gotos in visorbus_init Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorbus_main.c | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 813d29ea0c4e..816a16dea763 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -1275,24 +1275,24 @@ struct channel_size_info { int visorbus_init(void) { - int rc = 0; + int err; - POSTCODE_LINUX_3(DRIVER_ENTRY_PC, rc, POSTCODE_SEVERITY_INFO); + POSTCODE_LINUX_3(DRIVER_ENTRY_PC, 0, POSTCODE_SEVERITY_INFO); bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus", VERSION, NULL); - rc = create_bus_type(); - if (rc < 0) { + err = create_bus_type(); + if (err < 0) { POSTCODE_LINUX_2(BUS_CREATE_ENTRY_PC, DIAG_SEVERITY_ERR); - goto away; + goto error; } periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev"); if (!periodic_dev_workqueue) { POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR); - rc = -ENOMEM; - goto away; + err = -ENOMEM; + goto error; } /* This enables us to receive notifications when devices appear for @@ -1302,13 +1302,11 @@ visorbus_init(void) &chipset_responders, &chipset_driverinfo); - rc = 0; + return 0; -away: - if (rc) - POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc, - POSTCODE_SEVERITY_ERR); - return rc; +error: + POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR); + return err; } void -- GitLab From 8e33f48c9585c82258c8bef1d93149ca27f8d91d Mon Sep 17 00:00:00 2001 From: David Kershner Date: Sat, 12 Mar 2016 21:27:11 -0500 Subject: [PATCH 0300/9938] staging: unisys: visorbus: Remove gotos in visorbus_match Gotos in visorbus_match are not needed. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorbus_main.c | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 816a16dea763..b31c44f8043f 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -182,7 +182,6 @@ static int visorbus_match(struct device *xdev, struct device_driver *xdrv) { uuid_le channel_type; - int rc = 0; int i; struct visor_device *dev; struct visor_driver *drv; @@ -190,26 +189,23 @@ visorbus_match(struct device *xdev, struct device_driver *xdrv) dev = to_visor_device(xdev); drv = to_visor_driver(xdrv); channel_type = visorchannel_get_uuid(dev->visorchannel); - if (visorbus_forcematch) { - rc = 1; - goto away; - } - if (visorbus_forcenomatch) - goto away; + if (visorbus_forcematch) + return 1; + if (visorbus_forcenomatch) + return 0; if (!drv->channel_types) - goto away; + return 0; + for (i = 0; (uuid_le_cmp(drv->channel_types[i].guid, NULL_UUID_LE) != 0) || (drv->channel_types[i].name); i++) if (uuid_le_cmp(drv->channel_types[i].guid, - channel_type) == 0) { - rc = i + 1; - goto away; - } -away: - return rc; + channel_type) == 0) + return i + 1; + + return 0; } /** This is called when device_unregister() is called for the bus device -- GitLab From 0b2acf34f3680c4b0857625af667dcd53d39028e Mon Sep 17 00:00:00 2001 From: David Kershner Date: Sat, 12 Mar 2016 21:27:12 -0500 Subject: [PATCH 0301/9938] staging: unisys: visorbus: rename create_visor_device gotos Away is ambiguous when specifying error vs success. Make return labels more meaningful by marking them as error paths. Signed-off-by: David Kershner Signed-off-by: Timothy Sell Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorbus_main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index b31c44f8043f..54d77dd26be0 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -775,7 +775,7 @@ EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts); static int create_visor_device(struct visor_device *dev) { - int rc; + int err; u32 chipset_bus_no = dev->chipset_bus_no; u32 chipset_dev_no = dev->chipset_dev_no; @@ -797,8 +797,8 @@ create_visor_device(struct visor_device *dev) if (!dev->periodic_work) { POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no, DIAG_SEVERITY_ERR); - rc = -EINVAL; - goto away; + err = -EINVAL; + goto err_put; } /* bus_id must be a unique name with respect to this bus TYPE @@ -824,19 +824,19 @@ create_visor_device(struct visor_device *dev) * claim the device. The device will be linked onto * bus_type.klist_devices regardless (use bus_for_each_dev). */ - rc = device_add(&dev->device); - if (rc < 0) { + err = device_add(&dev->device); + if (err < 0) { POSTCODE_LINUX_3(DEVICE_ADD_PC, chipset_bus_no, DIAG_SEVERITY_ERR); - goto away; + goto err_put; } list_add_tail(&dev->list_all, &list_all_device_instances); - return 0; + return 0; /* success: reference kept via unmatched get_device() */ -away: +err_put: put_device(&dev->device); - return rc; + return err; } static void -- GitLab From 437ba274b5e5c813c2cede7051701ff3f0959022 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sat, 12 Mar 2016 16:19:20 +0800 Subject: [PATCH 0302/9938] staging: iio: tsl2x7x_core: adjust alignment to match open parenthesis Align the parameters to match open parenthesis. Issue detected using checkpatch. CHECK: Alignment should match open parenthesis Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2x7x_core.c | 164 +++++++++++++---------- 1 file changed, 92 insertions(+), 72 deletions(-) diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 5f308bae41b9..4948791b2cd7 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -349,13 +349,13 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) if (chip->tsl2x7x_chip_status != TSL2X7X_CHIP_WORKING) { /* device is not enabled */ dev_err(&chip->client->dev, "%s: device is not enabled\n", - __func__); + __func__); ret = -EBUSY; goto out_unlock; } ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &buf[0]); + (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &buf[0]); if (ret < 0) { dev_err(&chip->client->dev, "%s: Failed to read STATUS Reg\n", __func__); @@ -371,8 +371,8 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) for (i = 0; i < 4; i++) { ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | (TSL2X7X_ALS_CHAN0LO + i)), - &buf[i]); + (TSL2X7X_CMD_REG | + (TSL2X7X_ALS_CHAN0LO + i)), &buf[i]); if (ret < 0) { dev_err(&chip->client->dev, "failed to read. err=%x\n", ret); @@ -382,9 +382,9 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) /* clear any existing interrupt status */ ret = i2c_smbus_write_byte(chip->client, - (TSL2X7X_CMD_REG | - TSL2X7X_CMD_SPL_FN | - TSL2X7X_CMD_ALS_INT_CLR)); + (TSL2X7X_CMD_REG | + TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_ALS_INT_CLR)); if (ret < 0) { dev_err(&chip->client->dev, "i2c_write_command failed - err = %d\n", ret); @@ -488,7 +488,7 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) } ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &status); + (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &status); if (ret < 0) { dev_err(&chip->client->dev, "i2c err=%d\n", ret); goto prox_poll_err; @@ -515,8 +515,8 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) for (i = 0; i < 2; i++) { ret = tsl2x7x_i2c_read(chip->client, - (TSL2X7X_CMD_REG | - (TSL2X7X_PRX_LO + i)), &chdata[i]); + (TSL2X7X_CMD_REG | + (TSL2X7X_PRX_LO + i)), &chdata[i]); if (ret < 0) goto prox_poll_err; } @@ -542,19 +542,19 @@ static void tsl2x7x_defaults(struct tsl2X7X_chip *chip) { /* If Operational settings defined elsewhere.. */ if (chip->pdata && chip->pdata->platform_default_settings) - memcpy(&(chip->tsl2x7x_settings), - chip->pdata->platform_default_settings, - sizeof(tsl2x7x_default_settings)); + memcpy(&chip->tsl2x7x_settings, + chip->pdata->platform_default_settings, + sizeof(tsl2x7x_default_settings)); else - memcpy(&(chip->tsl2x7x_settings), - &tsl2x7x_default_settings, - sizeof(tsl2x7x_default_settings)); + memcpy(&chip->tsl2x7x_settings, + &tsl2x7x_default_settings, + sizeof(tsl2x7x_default_settings)); /* Load up the proper lux table. */ if (chip->pdata && chip->pdata->platform_lux_table[0].ratio != 0) memcpy(chip->tsl2x7x_device_lux, - chip->pdata->platform_lux_table, - sizeof(chip->pdata->platform_lux_table)); + chip->pdata->platform_lux_table, + sizeof(chip->pdata->platform_lux_table)); else memcpy(chip->tsl2x7x_device_lux, (struct tsl2x7x_lux *)tsl2x7x_default_lux_table_group[chip->id], @@ -576,7 +576,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) int lux_val; ret = i2c_smbus_write_byte(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); + (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); if (ret < 0) { dev_err(&chip->client->dev, "failed to write CNTRL register, ret=%d\n", ret); @@ -592,7 +592,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) } ret = i2c_smbus_write_byte(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); + (TSL2X7X_CMD_REG | TSL2X7X_CNTRL)); if (ret < 0) { dev_err(&chip->client->dev, "failed to write ctrl reg: ret=%d\n", ret); @@ -609,7 +609,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) lux_val = tsl2x7x_get_lux(indio_dev); if (lux_val < 0) { dev_err(&chip->client->dev, - "%s: failed to get lux\n", __func__); + "%s: failed to get lux\n", __func__); return lux_val; } @@ -620,7 +620,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) chip->tsl2x7x_settings.als_gain_trim = gain_trim_val; dev_info(&chip->client->dev, - "%s als_calibrate completed\n", chip->client->name); + "%s als_calibrate completed\n", chip->client->name); return (int) gain_trim_val; } @@ -699,7 +699,7 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) * Power on the device 1st. */ utmp = TSL2X7X_CNTL_PWR_ON; ret = i2c_smbus_write_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp); + TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp); if (ret < 0) { dev_err(&chip->client->dev, "%s: failed on CNTRL reg.\n", __func__); @@ -711,7 +711,8 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) for (i = 0, dev_reg = chip->tsl2x7x_config; i < TSL2X7X_MAX_CONFIG_REG; i++) { ret = i2c_smbus_write_byte_data(chip->client, - TSL2X7X_CMD_REG + i, *dev_reg++); + TSL2X7X_CMD_REG + i, + *dev_reg++); if (ret < 0) { dev_err(&chip->client->dev, "failed on write to reg %d.\n", i); @@ -727,7 +728,7 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PROX_DET_ENBL; ret = i2c_smbus_write_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp); + TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp); if (ret < 0) { dev_err(&chip->client->dev, "%s: failed on 2nd CTRL reg.\n", __func__); @@ -741,12 +742,13 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) reg_val = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL; if ((chip->tsl2x7x_settings.interrupts_en == 0x20) || - (chip->tsl2x7x_settings.interrupts_en == 0x30)) + (chip->tsl2x7x_settings.interrupts_en == 0x30)) reg_val |= TSL2X7X_CNTL_PROX_DET_ENBL; reg_val |= chip->tsl2x7x_settings.interrupts_en; ret = i2c_smbus_write_byte_data(chip->client, - (TSL2X7X_CMD_REG | TSL2X7X_CNTRL), reg_val); + (TSL2X7X_CMD_REG | + TSL2X7X_CNTRL), reg_val); if (ret < 0) dev_err(&chip->client->dev, "%s: failed in tsl2x7x_IOCTL_INT_SET.\n", @@ -754,8 +756,9 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) /* Clear out any initial interrupts */ ret = i2c_smbus_write_byte(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | - TSL2X7X_CMD_PROXALS_INT_CLR); + TSL2X7X_CMD_REG | + TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_PROXALS_INT_CLR); if (ret < 0) { dev_err(&chip->client->dev, "%s: Failed to clear Int status\n", @@ -776,7 +779,7 @@ static int tsl2x7x_chip_off(struct iio_dev *indio_dev) chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED; ret = i2c_smbus_write_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CNTRL, 0x00); + TSL2X7X_CMD_REG | TSL2X7X_CNTRL, 0x00); if (chip->pdata && chip->pdata->power_off) chip->pdata->power_off(chip->client); @@ -819,7 +822,7 @@ int tsl2x7x_invoke_change(struct iio_dev *indio_dev) static void tsl2x7x_prox_calculate(int *data, int length, - struct tsl2x7x_prox_stat *statP) + struct tsl2x7x_prox_stat *statP) { int i; int sample_sum; @@ -886,20 +889,21 @@ static void tsl2x7x_prox_cal(struct iio_dev *indio_dev) tsl2x7x_get_prox(indio_dev); prox_history[i] = chip->prox_data; dev_info(&chip->client->dev, "2 i=%d prox data= %d\n", - i, chip->prox_data); + i, chip->prox_data); } tsl2x7x_chip_off(indio_dev); calP = &prox_stat_data[PROX_STAT_CAL]; tsl2x7x_prox_calculate(prox_history, - chip->tsl2x7x_settings.prox_max_samples_cal, calP); + chip->tsl2x7x_settings.prox_max_samples_cal, + calP); chip->tsl2x7x_settings.prox_thres_high = (calP->max << 1) - calP->mean; dev_info(&chip->client->dev, " cal min=%d mean=%d max=%d\n", - calP->min, calP->mean, calP->max); + calP->min, calP->mean, calP->max); dev_info(&chip->client->dev, - "%s proximity threshold set to %d\n", - chip->client->name, chip->tsl2x7x_settings.prox_thres_high); + "%s proximity threshold set to %d\n", + chip->client->name, chip->tsl2x7x_settings.prox_thres_high); /* back to the way they were */ chip->tsl2x7x_settings.interrupts_en = tmp_irq_settings; @@ -908,7 +912,8 @@ static void tsl2x7x_prox_cal(struct iio_dev *indio_dev) } static ssize_t tsl2x7x_power_state_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); @@ -916,7 +921,8 @@ static ssize_t tsl2x7x_power_state_show(struct device *dev, } static ssize_t tsl2x7x_power_state_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); bool value; @@ -933,7 +939,8 @@ static ssize_t tsl2x7x_power_state_store(struct device *dev, } static ssize_t tsl2x7x_gain_available_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); @@ -950,13 +957,15 @@ static ssize_t tsl2x7x_gain_available_show(struct device *dev, } static ssize_t tsl2x7x_prox_gain_available_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", "1 2 4 8"); } static ssize_t tsl2x7x_als_time_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); int y, z; @@ -970,7 +979,8 @@ static ssize_t tsl2x7x_als_time_show(struct device *dev, } static ssize_t tsl2x7x_als_time_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); @@ -986,7 +996,7 @@ static ssize_t tsl2x7x_als_time_store(struct device *dev, TSL2X7X_MAX_TIMER_CNT - (u8)result.fract; dev_info(&chip->client->dev, "%s: als time = %d", - __func__, chip->tsl2x7x_settings.als_time); + __func__, chip->tsl2x7x_settings.als_time); tsl2x7x_invoke_change(indio_dev); @@ -997,7 +1007,8 @@ static IIO_CONST_ATTR(in_illuminance0_integration_time_available, ".00272 - .696"); static ssize_t tsl2x7x_als_cal_target_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); @@ -1006,7 +1017,8 @@ static ssize_t tsl2x7x_als_cal_target_show(struct device *dev, } static ssize_t tsl2x7x_als_cal_target_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); @@ -1025,7 +1037,8 @@ static ssize_t tsl2x7x_als_cal_target_store(struct device *dev, /* persistence settings */ static ssize_t tsl2x7x_als_persistence_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); int y, z, filter_delay; @@ -1041,7 +1054,8 @@ static ssize_t tsl2x7x_als_persistence_show(struct device *dev, } static ssize_t tsl2x7x_als_persistence_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); @@ -1063,7 +1077,7 @@ static ssize_t tsl2x7x_als_persistence_store(struct device *dev, chip->tsl2x7x_settings.persistence |= (filter_delay & 0x0F); dev_info(&chip->client->dev, "%s: als persistence = %d", - __func__, filter_delay); + __func__, filter_delay); tsl2x7x_invoke_change(indio_dev); @@ -1071,7 +1085,8 @@ static ssize_t tsl2x7x_als_persistence_store(struct device *dev, } static ssize_t tsl2x7x_prox_persistence_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); int y, z, filter_delay; @@ -1087,7 +1102,8 @@ static ssize_t tsl2x7x_prox_persistence_show(struct device *dev, } static ssize_t tsl2x7x_prox_persistence_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); @@ -1109,7 +1125,7 @@ static ssize_t tsl2x7x_prox_persistence_store(struct device *dev, chip->tsl2x7x_settings.persistence |= ((filter_delay << 4) & 0xF0); dev_info(&chip->client->dev, "%s: prox persistence = %d", - __func__, filter_delay); + __func__, filter_delay); tsl2x7x_invoke_change(indio_dev); @@ -1117,7 +1133,8 @@ static ssize_t tsl2x7x_prox_persistence_store(struct device *dev, } static ssize_t tsl2x7x_do_calibrate(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); bool value; @@ -1134,7 +1151,8 @@ static ssize_t tsl2x7x_do_calibrate(struct device *dev, } static ssize_t tsl2x7x_luxtable_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); int i = 0; @@ -1159,7 +1177,8 @@ static ssize_t tsl2x7x_luxtable_show(struct device *dev, } static ssize_t tsl2x7x_luxtable_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); @@ -1175,7 +1194,7 @@ static ssize_t tsl2x7x_luxtable_store(struct device *dev, */ n = value[0]; if ((n % 3) || n < 6 || - n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 3)) { + n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 3)) { dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n); return -EINVAL; } @@ -1198,7 +1217,8 @@ static ssize_t tsl2x7x_luxtable_store(struct device *dev, } static ssize_t tsl2x7x_do_prox_calibrate(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); bool value; @@ -1391,10 +1411,10 @@ static int tsl2x7x_read_raw(struct iio_dev *indio_dev, } static int tsl2x7x_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); @@ -1529,7 +1549,7 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) u8 value; value = i2c_smbus_read_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_STATUS); + TSL2X7X_CMD_REG | TSL2X7X_STATUS); /* What type of interrupt do we need to process */ if (value & TSL2X7X_STA_PRX_INTR) { @@ -1545,16 +1565,16 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) if (value & TSL2X7X_STA_ALS_INTR) { tsl2x7x_get_lux(indio_dev); /* freshen data for ABI */ iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE(IIO_LIGHT, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_EITHER), - timestamp); + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + timestamp); } /* Clear interrupt now that we have handled it. */ ret = i2c_smbus_write_byte(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | - TSL2X7X_CMD_PROXALS_INT_CLR); + TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_PROXALS_INT_CLR); if (ret < 0) dev_err(&chip->client->dev, "Failed to clear irq from event handler. err = %d\n", @@ -1857,7 +1877,7 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { }; static int tsl2x7x_probe(struct i2c_client *clientp, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { int ret; unsigned char device_id; @@ -1873,14 +1893,14 @@ static int tsl2x7x_probe(struct i2c_client *clientp, i2c_set_clientdata(clientp, indio_dev); ret = tsl2x7x_i2c_read(chip->client, - TSL2X7X_CHIPID, &device_id); + TSL2X7X_CHIPID, &device_id); if (ret < 0) return ret; if ((!tsl2x7x_device_id(&device_id, id->driver_data)) || - (tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) { + (tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) { dev_info(&chip->client->dev, - "%s: i2c device found does not match expected id\n", + "%s: i2c device found does not match expected id\n", __func__); return -EINVAL; } -- GitLab From 2cbc8b34ef9fd081a4ae90460b9e26756ddebfe4 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sat, 12 Mar 2016 16:19:21 +0800 Subject: [PATCH 0303/9938] staging: iio: tsl2x7x_core: use preferred comment style Adjust block comments by adding the necessary trailing */ on a separate line. Checkpatch found this issue. Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2x7x_core.c | 38 ++++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 4948791b2cd7..de069be7f8f5 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -187,9 +187,11 @@ struct tsl2X7X_chip { const struct tsl2x7x_chip_info *chip_info; const struct iio_info *info; s64 event_timestamp; - /* This structure is intentionally large to accommodate - * updates via sysfs. */ - /* Sized to 9 = max 8 segments + 1 termination segment */ + /* + * This structure is intentionally large to accommodate + * updates via sysfs. + * Sized to 9 = max 8 segments + 1 termination segment + */ struct tsl2x7x_lux tsl2x7x_device_lux[TSL2X7X_MAX_LUX_TABLE_SIZE]; }; @@ -695,8 +697,10 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) chip->als_saturation = als_count * 922; /* 90% of full scale */ chip->als_time_scale = (als_time + 25) / 50; - /* TSL2X7X Specific power-on / adc enable sequence - * Power on the device 1st. */ + /* + * TSL2X7X Specific power-on / adc enable sequence + * Power on the device 1st. + */ utmp = TSL2X7X_CNTL_PWR_ON; ret = i2c_smbus_write_byte_data(chip->client, TSL2X7X_CMD_REG | TSL2X7X_CNTRL, utmp); @@ -706,8 +710,10 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) return ret; } - /* Use the following shadow copy for our delay before enabling ADC. - * Write all the registers. */ + /* + * Use the following shadow copy for our delay before enabling ADC. + * Write all the registers. + */ for (i = 0, dev_reg = chip->tsl2x7x_config; i < TSL2X7X_MAX_CONFIG_REG; i++) { ret = i2c_smbus_write_byte_data(chip->client, @@ -722,8 +728,10 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) mdelay(3); /* Power-on settling time */ - /* NOW enable the ADC - * initialize the desired mode of operation */ + /* + * NOW enable the ADC + * initialize the desired mode of operation + */ utmp = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PROX_DET_ENBL; @@ -1164,8 +1172,10 @@ static ssize_t tsl2x7x_luxtable_show(struct device *dev, chip->tsl2x7x_device_lux[i].ch0, chip->tsl2x7x_device_lux[i].ch1); if (chip->tsl2x7x_device_lux[i].ratio == 0) { - /* We just printed the first "0" entry. - * Now get rid of the extra "," and break. */ + /* + * We just printed the first "0" entry. + * Now get rid of the extra "," and break. + */ offset--; break; } @@ -1912,8 +1922,10 @@ static int tsl2x7x_probe(struct i2c_client *clientp, return ret; } - /* ALS and PROX functions can be invoked via user space poll - * or H/W interrupt. If busy return last sample. */ + /* + * ALS and PROX functions can be invoked via user space poll + * or H/W interrupt. If busy return last sample. + */ mutex_init(&chip->als_mutex); mutex_init(&chip->prox_mutex); -- GitLab From 54a0cd3e5757e6cbec63911f234190287ebeca29 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sat, 12 Mar 2016 16:19:22 +0800 Subject: [PATCH 0304/9938] staging: iio: tsl2x7x_core: remove space after a cast Delete unneeded space after a cast as suggested by checkpatch. CHECK: No space is necessary after a cast. Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2x7x_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index de069be7f8f5..6291a71d9565 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -413,7 +413,7 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) /* calculate ratio */ ratio = (ch1 << 15) / ch0; /* convert to unscaled lux using the pointer to the table */ - p = (struct tsl2x7x_lux *) chip->tsl2x7x_device_lux; + p = (struct tsl2x7x_lux *)chip->tsl2x7x_device_lux; while (p->ratio != 0 && p->ratio < ratio) p++; @@ -624,7 +624,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) dev_info(&chip->client->dev, "%s als_calibrate completed\n", chip->client->name); - return (int) gain_trim_val; + return (int)gain_trim_val; } static int tsl2x7x_chip_on(struct iio_dev *indio_dev) -- GitLab From 95066a028b6bf9a1f4c6fcb69fab8474952bc858 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sat, 12 Mar 2016 16:19:23 +0800 Subject: [PATCH 0305/9938] staging: iio: tsl2x7x_core: add spaces around operators Address the checkpatch check by adding the necessary whitespace around operators: CHECK: spaces preferred around that '/' (ctx:VxV) Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2x7x_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 6291a71d9565..a72bb2912622 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -854,7 +854,7 @@ void tsl2x7x_prox_calculate(int *data, int length, tmp = data[i] - statP->mean; sample_sum += tmp * tmp; } - statP->stddev = int_sqrt((long)sample_sum)/length; + statP->stddev = int_sqrt((long)sample_sum) / length; } /** @@ -1192,7 +1192,7 @@ static ssize_t tsl2x7x_luxtable_store(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int value[ARRAY_SIZE(chip->tsl2x7x_device_lux)*3 + 1]; + int value[ARRAY_SIZE(chip->tsl2x7x_device_lux) * 3 + 1]; int n; get_options(buf, ARRAY_SIZE(value), value); -- GitLab From b026338289d65ef6fddfefcf5d1ba7932bc77c8a Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sat, 12 Mar 2016 16:19:24 +0800 Subject: [PATCH 0306/9938] staging: iio: tsl2x7x_core: add blank line after struct declaration Add the missing blank line after struct declaration. Checkpatch found this issue. CHECK: Please use a blank line after function/struct/union/enum declarations Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2x7x_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index a72bb2912622..d553c8e18fcc 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -1646,6 +1646,7 @@ static struct attribute *tsl2X7X_ALS_event_attrs[] = { &dev_attr_in_intensity0_thresh_period.attr, NULL, }; + static struct attribute *tsl2X7X_PRX_event_attrs[] = { &dev_attr_in_proximity0_thresh_period.attr, NULL, -- GitLab From 5e3d1d520ffccb956a5b00c8a858416747869058 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sun, 13 Mar 2016 23:11:30 -0700 Subject: [PATCH 0307/9938] staging: iio: meter: remove fixme comment on device remove This comment was in place in the original drafts of these drivers when the remove function did a whole lot of work: flushed queues, unregistered interrupts, uninitialized rings, unconfigured rings, and a few kfree's. The remove functions have since been reduced to unregistering and stopping the device. This is the inverse of what was done during probe and is correct. Time to remove the comment. Signed-off-by: Alison Schofield Acked-by: Daniel Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/meter/ade7753.c | 1 - drivers/staging/iio/meter/ade7754.c | 1 - drivers/staging/iio/meter/ade7759.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 69287108f793..b0bc99a958c5 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -528,7 +528,6 @@ static int ade7753_probe(struct spi_device *spi) return iio_device_register(indio_dev); } -/* fixme, confirm ordering in this function */ static int ade7753_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index f4188e17d30b..fed11804d548 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -558,7 +558,6 @@ static int ade7754_probe(struct spi_device *spi) return ret; } -/* fixme, confirm ordering in this function */ static int ade7754_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 684e612a88b9..c14892db7e4c 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -476,7 +476,6 @@ static int ade7759_probe(struct spi_device *spi) return iio_device_register(indio_dev); } -/* fixme, confirm ordering in this function */ static int ade7759_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); -- GitLab From 7b58e2402f965c97c191570e187fa107230d09b4 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sun, 13 Mar 2016 23:13:49 -0700 Subject: [PATCH 0308/9938] staging: iio: ad5933: use dev_get_platdata() Use dev_get_platdata() for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Alison Schofield Acked-by: Daniel Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/impedance-analyzer/ad5933.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index d1218d896725..428587433c4a 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -699,7 +699,7 @@ static int ad5933_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret, voltage_uv = 0; - struct ad5933_platform_data *pdata = client->dev.platform_data; + struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev); struct ad5933_state *st; struct iio_dev *indio_dev; -- GitLab From e279ee89d349af16fc7b77f4d715cd2826ac8249 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sun, 13 Mar 2016 23:15:51 -0700 Subject: [PATCH 0309/9938] staging: iio: io-trig-bfin-timer: use dev_get_platdata() Use dev_get_platdata() for retrieving the platform data instead of accessing dev->platform_data directly. Move the assignment out of the declaration (avoid lines over 80 char and put it close to usage). Signed-off-by: Alison Schofield Acked-by: Daniel Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/trigger/iio-trig-bfin-timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 035dd456d7d6..8667334f3f41 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -178,7 +178,7 @@ static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = { static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) { - struct iio_bfin_timer_trigger_pdata *pdata = pdev->dev.platform_data; + struct iio_bfin_timer_trigger_pdata *pdata; struct bfin_tmr_state *st; unsigned int config; int ret; @@ -221,6 +221,7 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) config = PWM_OUT | PERIOD_CNT | IRQ_ENA; + pdata = dev_get_platdata(&pdev->dev); if (pdata && pdata->output_enable) { unsigned long long val; -- GitLab From f5d82ad9bca2df8204c9b47748cbf1c5f3eb691d Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Wed, 16 Mar 2016 23:59:19 -0700 Subject: [PATCH 0310/9938] staging: iio: ad5933: move contents of header file to source file The contents of the header file are used only by this single source file. Move content into .c and remove .h. Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- .../staging/iio/impedance-analyzer/ad5933.c | 14 ++++++++-- .../staging/iio/impedance-analyzer/ad5933.h | 28 ------------------- 2 files changed, 12 insertions(+), 30 deletions(-) delete mode 100644 drivers/staging/iio/impedance-analyzer/ad5933.h diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 428587433c4a..f2c305cfdfc3 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -24,8 +24,6 @@ #include #include -#include "ad5933.h" - /* AD5933/AD5934 Registers */ #define AD5933_REG_CONTROL_HB 0x80 /* R/W, 2 bytes */ #define AD5933_REG_CONTROL_LB 0x81 /* R/W, 2 bytes */ @@ -86,6 +84,18 @@ #define AD5933_POLL_TIME_ms 10 #define AD5933_INIT_EXCITATION_TIME_ms 100 +/** + * struct ad5933_platform_data - platform specific data + * @ext_clk_Hz: the external clock frequency in Hz, if not set + * the driver uses the internal clock (16.776 MHz) + * @vref_mv: the external reference voltage in millivolt + */ + +struct ad5933_platform_data { + unsigned long ext_clk_Hz; + unsigned short vref_mv; +}; + struct ad5933_state { struct i2c_client *client; struct regulator *reg; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.h b/drivers/staging/iio/impedance-analyzer/ad5933.h deleted file mode 100644 index b140e42d67cf..000000000000 --- a/drivers/staging/iio/impedance-analyzer/ad5933.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * AD5933 AD5934 Impedance Converter, Network Analyzer - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#ifndef IIO_ADC_AD5933_H_ -#define IIO_ADC_AD5933_H_ - -/* - * TODO: struct ad5933_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad5933_platform_data - platform specific data - * @ext_clk_Hz: the external clock frequency in Hz, if not set - * the driver uses the internal clock (16.776 MHz) - * @vref_mv: the external reference voltage in millivolt - */ - -struct ad5933_platform_data { - unsigned long ext_clk_Hz; - unsigned short vref_mv; -}; - -#endif /* IIO_ADC_AD5933_H_ */ -- GitLab From 5359ada246eb651679b80cfaa036c1d1ebcd0896 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Thu, 17 Mar 2016 00:00:20 -0700 Subject: [PATCH 0311/9938] staging: iio: ad5933: remove unused #includes Remove #includes no longer used in this module. Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/impedance-analyzer/ad5933.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index f2c305cfdfc3..af3a19045363 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -12,12 +12,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include -- GitLab From 0eea4ce3f4be3253206ca7bb84a458cea0c41e01 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 13:11:15 +0530 Subject: [PATCH 0312/9938] Staging: iio: ade7758_core: Fix open parentheses alignment issues. Fix open parentheses alignment issues. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/meter/ade7758_core.c | 73 +++++++++--------------- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 40f5afaa984b..d6e35c76ad09 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -24,9 +24,7 @@ #include "meter.h" #include "ade7758.h" -int ade7758_spi_write_reg_8(struct device *dev, - u8 reg_address, - u8 val) +int ade7758_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -42,9 +40,8 @@ int ade7758_spi_write_reg_8(struct device *dev, return ret; } -static int ade7758_spi_write_reg_16(struct device *dev, - u8 reg_address, - u16 value) +static int ade7758_spi_write_reg_16(struct device *dev, u8 reg_address, + u16 value) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -68,9 +65,8 @@ static int ade7758_spi_write_reg_16(struct device *dev, return ret; } -static int ade7758_spi_write_reg_24(struct device *dev, - u8 reg_address, - u32 value) +static int ade7758_spi_write_reg_24(struct device *dev, u8 reg_address, + u32 value) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -95,9 +91,7 @@ static int ade7758_spi_write_reg_24(struct device *dev, return ret; } -int ade7758_spi_read_reg_8(struct device *dev, - u8 reg_address, - u8 *val) +int ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); @@ -124,7 +118,7 @@ int ade7758_spi_read_reg_8(struct device *dev, ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", - reg_address); + reg_address); goto error_ret; } *val = st->rx[0]; @@ -134,9 +128,8 @@ int ade7758_spi_read_reg_8(struct device *dev, return ret; } -static int ade7758_spi_read_reg_16(struct device *dev, - u8 reg_address, - u16 *val) +static int ade7758_spi_read_reg_16(struct device *dev, u8 reg_address, + u16 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); @@ -165,7 +158,7 @@ static int ade7758_spi_read_reg_16(struct device *dev, ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - reg_address); + reg_address); goto error_ret; } @@ -176,9 +169,8 @@ static int ade7758_spi_read_reg_16(struct device *dev, return ret; } -static int ade7758_spi_read_reg_24(struct device *dev, - u8 reg_address, - u32 *val) +static int ade7758_spi_read_reg_24(struct device *dev, u8 reg_address, + u32 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); @@ -207,7 +199,7 @@ static int ade7758_spi_read_reg_24(struct device *dev, ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", - reg_address); + reg_address); goto error_ret; } *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; @@ -218,8 +210,7 @@ static int ade7758_spi_read_reg_24(struct device *dev, } static ssize_t ade7758_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { int ret; u8 val = 0; @@ -233,8 +224,7 @@ static ssize_t ade7758_read_8bit(struct device *dev, } static ssize_t ade7758_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { int ret; u16 val = 0; @@ -248,8 +238,7 @@ static ssize_t ade7758_read_16bit(struct device *dev, } static ssize_t ade7758_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { int ret; u32 val = 0; @@ -263,9 +252,8 @@ static ssize_t ade7758_read_24bit(struct device *dev, } static ssize_t ade7758_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -281,9 +269,8 @@ static ssize_t ade7758_write_8bit(struct device *dev, } static ssize_t ade7758_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -479,16 +466,13 @@ static int ade7758_initial_setup(struct iio_dev *indio_dev) } static ssize_t ade7758_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { int ret; u8 t; int sps; - ret = ade7758_spi_read_reg_8(dev, - ADE7758_WAVMODE, - &t); + ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, &t); if (ret) return ret; @@ -499,9 +483,8 @@ static ssize_t ade7758_read_frequency(struct device *dev, } static ssize_t ade7758_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); u16 val; @@ -532,18 +515,14 @@ static ssize_t ade7758_write_frequency(struct device *dev, goto out; } - ret = ade7758_spi_read_reg_8(dev, - ADE7758_WAVMODE, - ®); + ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, ®); if (ret) goto out; reg &= ~(5 << 3); reg |= t << 5; - ret = ade7758_spi_write_reg_8(dev, - ADE7758_WAVMODE, - reg); + ret = ade7758_spi_write_reg_8(dev, ADE7758_WAVMODE, reg); out: mutex_unlock(&indio_dev->mlock); -- GitLab From 929d2691f202c1904db5a8a471636e030eaef570 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 13:13:46 +0530 Subject: [PATCH 0313/9938] Staging: iio: ade7758_core: Remove unnecessary blank line. Remove unnecessary blank line. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/meter/ade7758_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index d6e35c76ad09..310296573e52 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -149,7 +149,6 @@ static int ade7758_spi_read_reg_16(struct device *dev, u8 reg_address, }, }; - mutex_lock(&st->buf_lock); st->tx[0] = ADE7758_READ_REG(reg_address); st->tx[1] = 0; -- GitLab From 93636775b9b68f239cf6a100f9148c0936dbd02e Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 13:15:13 +0530 Subject: [PATCH 0314/9938] Staging: iio: ade7758: Use a blank line after function/struct declarations. Use a blank line after function/struct declarations. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/meter/ade7758.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index f6739e2c24b1..ff7c7641546c 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -129,6 +129,7 @@ struct ade7758_state { unsigned char tx_buf[8]; }; + #ifdef CONFIG_IIO_BUFFER /* At the moment triggers are only used for ring buffer * filling. This may change! @@ -157,6 +158,7 @@ int ade7758_spi_read_reg_8(struct device *dev, static inline void ade7758_remove_trigger(struct iio_dev *indio_dev) { } + static inline int ade7758_probe_trigger(struct iio_dev *indio_dev) { return 0; @@ -166,16 +168,20 @@ static int ade7758_configure_ring(struct iio_dev *indio_dev) { return 0; } + static inline void ade7758_unconfigure_ring(struct iio_dev *indio_dev) { } + static inline int ade7758_initialize_ring(struct iio_ring_buffer *ring) { return 0; } + static inline void ade7758_uninitialize_ring(struct iio_dev *indio_dev) { } + #endif /* CONFIG_IIO_BUFFER */ #endif -- GitLab From 04e1f7b9b0b24b0d2fb669ea8fdce429478da72f Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 13:17:01 +0530 Subject: [PATCH 0315/9938] Staging: iio: ade7758: Fix open parentheses alignment issues. Fix open parentheses alignment issues. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/meter/ade7758.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index ff7c7641546c..1d04ec9524c8 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -139,19 +139,15 @@ void ade7758_remove_trigger(struct iio_dev *indio_dev); int ade7758_probe_trigger(struct iio_dev *indio_dev); ssize_t ade7758_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - + struct device_attribute *attr, char *buf); int ade7758_configure_ring(struct iio_dev *indio_dev); void ade7758_unconfigure_ring(struct iio_dev *indio_dev); int ade7758_set_irq(struct device *dev, bool enable); -int ade7758_spi_write_reg_8(struct device *dev, - u8 reg_address, u8 val); -int ade7758_spi_read_reg_8(struct device *dev, - u8 reg_address, u8 *val); +int ade7758_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val); +int ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val); #else /* CONFIG_IIO_BUFFER */ -- GitLab From 7df7ee9be9801a7d0c73e9a4ef3e4912aef8b083 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 17:19:44 +0530 Subject: [PATCH 0316/9938] Staging: iio: ad5933: Remove unnecessary space after cast. Remove unnecessary space after cast. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/impedance-analyzer/ad5933.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index af3a19045363..620b33a61a2d 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -315,10 +315,10 @@ static ssize_t ad5933_show_frequency(struct device *dev, freqreg = be32_to_cpu(dat.d32) & 0xFFFFFF; - freqreg = (u64) freqreg * (u64) (st->mclk_hz / 4); + freqreg = (u64)freqreg * (u64)(st->mclk_hz / 4); do_div(freqreg, 1 << 27); - return sprintf(buf, "%d\n", (int) freqreg); + return sprintf(buf, "%d\n", (int)freqreg); } static ssize_t ad5933_store_frequency(struct device *dev, @@ -366,7 +366,7 @@ static ssize_t ad5933_show(struct device *dev, int ret = 0, len = 0; mutex_lock(&indio_dev->mlock); - switch ((u32) this_attr->address) { + switch ((u32)this_attr->address) { case AD5933_OUT_RANGE: len = sprintf(buf, "%u\n", st->range_avail[(st->ctrl_hb >> 1) & 0x3]); @@ -417,7 +417,7 @@ static ssize_t ad5933_store(struct device *dev, } mutex_lock(&indio_dev->mlock); - switch ((u32) this_attr->address) { + switch ((u32)this_attr->address) { case AD5933_OUT_RANGE: for (i = 0; i < 4; i++) if (val == st->range_avail[i]) { -- GitLab From afb105549d4879018e45bbf77e76034237d8fc20 Mon Sep 17 00:00:00 2001 From: PrasannaKumar Muralidharan Date: Sat, 12 Mar 2016 14:03:09 +0530 Subject: [PATCH 0317/9938] Staging: most: Remove atomic_counter_t typedef Remove atomic_counter_t typedef, use int instead. Signed-off-by: PrasannaKumar Muralidharan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-dim2/dim2_hal.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index fc73d4f97734..9f8e88028181 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -42,14 +42,12 @@ struct dim_ch_state_t { u16 done_buffers; /* Number of completed buffers */ }; -typedef int atomic_counter_t; - struct int_ch_state { /* changed only in interrupt context */ - volatile atomic_counter_t request_counter; + volatile int request_counter; /* changed only in task context */ - volatile atomic_counter_t service_counter; + volatile int service_counter; u8 idx1; u8 idx2; -- GitLab From 514dd88df707a1094e937c20d5a0b1ec619e1f96 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 12 Mar 2016 15:01:04 +0530 Subject: [PATCH 0318/9938] staging: slicoss: Add error check for pci_map_single Currently, DMA mapping failure is not detected, causing the hardware to attempt a DMA from an invalid address. This patch adds the corresponding error check for pci_map_single i.e. pci_dma_mapping_error. Problem found using the following Coccinelle semantic patch: // @@ expression e1; identifier x; @@ x= ( *dma_map_single(...) | *dma_map_page(...) ) ... when != dma_mapping_error(e1,x) @@ expression e1; identifier x; @@ x = ( *pci_map_single(...) | *pci_map_page(...) ) ... when != pci_dma_mapping_error(e1,x) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slicoss.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 6d50fc4fd02e..fa61e8e9964b 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1855,6 +1855,11 @@ static void slic_xmit_build_request(struct adapter *adapter, ihcmd->u.slic_buffers.totlen = skb->len; phys_addr = pci_map_single(adapter->pcidev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(adapter->pcidev, phys_addr)) { + kfree_skb(skb); + dev_err(&adapter->pcidev->dev, "DMA mapping error\n"); + return; + } ihcmd->u.slic_buffers.bufs[0].paddrl = SLIC_GET_ADDR_LOW(phys_addr); ihcmd->u.slic_buffers.bufs[0].paddrh = SLIC_GET_ADDR_HIGH(phys_addr); ihcmd->u.slic_buffers.bufs[0].length = skb->len; -- GitLab From c2598d468f3cccb1266a8ffe1a0d7268ff2d8eb4 Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Sat, 12 Mar 2016 16:03:50 +0100 Subject: [PATCH 0319/9938] staging: octeon: Use type int instead of int32_t Prefer the use of type int instead of int32_t. Checkpatch detected these issues. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-tx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index ffe9bd77a7bb..93f65589f72a 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -58,9 +58,9 @@ static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup, 0); /* Maximum number of SKBs to try to free per xmit packet. */ #define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2) -static inline int32_t cvm_oct_adjust_skb_to_free(int32_t skb_to_free, int fau) +static inline int cvm_oct_adjust_skb_to_free(int skb_to_free, int fau) { - int32_t undo; + int undo; undo = skb_to_free > 0 ? MAX_SKB_TO_FREE : skb_to_free + MAX_SKB_TO_FREE; @@ -83,7 +83,7 @@ static void cvm_oct_kick_tx_poll_watchdog(void) static void cvm_oct_free_tx_skbs(struct net_device *dev) { - int32_t skb_to_free; + int skb_to_free; int qos, queues_per_port; int total_freed = 0; int total_remaining = 0; @@ -148,8 +148,8 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) enum {QUEUE_CORE, QUEUE_HW, QUEUE_DROP} queue_type; struct octeon_ethernet *priv = netdev_priv(dev); struct sk_buff *to_free_list; - int32_t skb_to_free; - int32_t buffers_to_free; + int skb_to_free; + int buffers_to_free; u32 total_to_clean; unsigned long flags; #if REUSE_SKBUFFS_WITHOUT_FREE -- GitLab From ac05a587c8a7b6ae8c4acef5a6db7e6ccfbcfd3e Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Sat, 12 Mar 2016 16:35:30 +0100 Subject: [PATCH 0320/9938] staging: octeon: Fix alignment with open parenthesis Alignment should match open parenthesis. Checkpatch detected these issues. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-rx.c | 7 ++++--- drivers/staging/octeon/ethernet-rx.h | 2 +- drivers/staging/octeon/ethernet-tx.c | 5 +++-- drivers/staging/octeon/ethernet.c | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index b6993b0b8170..a10fe3af9a9c 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -172,12 +172,13 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { old_group_mask = cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid), - 1ull << pow_receive_group); + 1ull << pow_receive_group); cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */ } else { old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid)); cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), - (old_group_mask & ~0xFFFFull) | 1 << pow_receive_group); + (old_group_mask & ~0xFFFFull) | + 1 << pow_receive_group); } if (USE_ASYNC_IOBDMA) { @@ -374,7 +375,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) * doesn't exist. */ printk_ratelimited("Port %d not controlled by Linux, packet dropped\n", - port); + port); dev_kfree_skb_irq(skb); } /* diff --git a/drivers/staging/octeon/ethernet-rx.h b/drivers/staging/octeon/ethernet-rx.h index a5973fd015fc..315a63d7094f 100644 --- a/drivers/staging/octeon/ethernet-rx.h +++ b/drivers/staging/octeon/ethernet-rx.h @@ -30,7 +30,7 @@ static inline void cvm_oct_rx_refill_pool(int fill_threshold) number_to_free); if (num_freed != number_to_free) { cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, - number_to_free - num_freed); + number_to_free - num_freed); } } } diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 93f65589f72a..6b4c20872323 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -220,7 +220,8 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) priv->fau + qos * 4, MAX_SKB_TO_FREE); } skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, - priv->fau + qos * 4); + priv->fau + + qos * 4); spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); goto skip_xmit; } @@ -402,7 +403,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) } skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, - priv->fau + qos * 4); + priv->fau + qos * 4); /* * If we're sending faster than the receive can free them then diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 271e1b8d8506..e9cd5f242921 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -635,7 +635,7 @@ static struct device_node *cvm_oct_of_get_child( } static struct device_node *cvm_oct_node_for_port(struct device_node *pip, - int interface, int port) + int interface, int port) { struct device_node *ni, *np; @@ -815,7 +815,7 @@ static int cvm_oct_probe(struct platform_device *pdev) free_netdev(dev); } else if (register_netdev(dev) < 0) { pr_err("Failed to register ethernet device for interface %d, port %d\n", - interface, priv->port); + interface, priv->port); free_netdev(dev); } else { cvm_oct_device[priv->port] = dev; -- GitLab From 9fc27699bd16707ae95218ba553bde144f5afbed Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Sat, 12 Mar 2016 16:20:04 +0100 Subject: [PATCH 0321/9938] staging: nvec: Remove space after a cast No space is required after a cast. Checkpatch detected this issue. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 9fda136b8e05..dc38ca815806 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -659,10 +659,11 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) } else if (nvec->tx && nvec->tx->pos < nvec->tx->size) { to_send = nvec->tx->data[nvec->tx->pos++]; } else { - dev_err(nvec->dev, "tx buffer underflow on %p (%u > %u)\n", + dev_err(nvec->dev, + "tx buffer underflow on %p (%u > %u)\n", nvec->tx, - (uint) (nvec->tx ? nvec->tx->pos : 0), - (uint) (nvec->tx ? nvec->tx->size : 0)); + (uint)(nvec->tx ? nvec->tx->pos : 0), + (uint)(nvec->tx ? nvec->tx->size : 0)); nvec->state = 0; } break; -- GitLab From f05f33fae3c720bd555ceb15b46beb4c642b663a Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Sat, 12 Mar 2016 16:19:11 +0100 Subject: [PATCH 0322/9938] staging: nvec: Fix comparison to NULL Replace the use of comparison to NULL, use ! instead. Checkpatch detected these issues. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index dc38ca815806..c1feccf8d94a 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -264,7 +264,7 @@ int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, msg = nvec_msg_alloc(nvec, NVEC_MSG_TX); - if (msg == NULL) + if (!msg) return -ENOMEM; msg->data[0] = size; @@ -620,7 +620,7 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) } else { nvec->rx = nvec_msg_alloc(nvec, NVEC_MSG_RX); /* Should not happen in a normal world */ - if (unlikely(nvec->rx == NULL)) { + if (unlikely(!nvec->rx)) { nvec->state = 0; break; } -- GitLab From a3dac5a35cc54fa983e3de56ec010734c87315c4 Mon Sep 17 00:00:00 2001 From: Ben Marsh Date: Tue, 15 Mar 2016 19:37:54 +0100 Subject: [PATCH 0323/9938] Staging: nvec: removes a useless cast on a void pointer Remove an unnecessary cast on a void pointer in nvec_power.c Signed-off-by: Ben Marsh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec_power.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c index b4a0545e8806..fcbb0fa03765 100644 --- a/drivers/staging/nvec/nvec_power.c +++ b/drivers/staging/nvec/nvec_power.c @@ -90,7 +90,7 @@ static int nvec_power_notifier(struct notifier_block *nb, { struct nvec_power *power = container_of(nb, struct nvec_power, notifier); - struct bat_response *res = (struct bat_response *)data; + struct bat_response *res = data; if (event_type != NVEC_SYS) return NOTIFY_DONE; @@ -126,7 +126,7 @@ static int nvec_power_bat_notifier(struct notifier_block *nb, { struct nvec_power *power = container_of(nb, struct nvec_power, notifier); - struct bat_response *res = (struct bat_response *)data; + struct bat_response *res = data; int status_changed = 0; if (event_type != NVEC_BAT) -- GitLab From 6422ea03f335bf7441150555de1ab048ac82ee99 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Tue, 15 Mar 2016 18:48:08 +0900 Subject: [PATCH 0324/9938] staging: wilc1000: removes function 'init_tcp_tracking()' This patch removes function 'init_tcp_tracking()'. The function is an unnecessary return. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index fd938fb43dd3..ca9054a5ff88 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -150,11 +150,6 @@ static u32 pending_base; static u32 tcp_session; static u32 pending_acks; -static inline int init_tcp_tracking(void) -{ - return 0; -} - static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq) { if (tcp_session < 2 * MAX_TCP_SESSION) { @@ -1440,7 +1435,6 @@ int wilc_wlan_init(struct net_device *dev) ret = -EIO; goto _fail_; } - init_tcp_tracking(); return 1; -- GitLab From 9635d338303c3ed80e06c03b54ee171651438984 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Tue, 15 Mar 2016 18:48:09 +0900 Subject: [PATCH 0325/9938] staging: wilc1000: wilc_spi.c: removes debug print log This patches removes unnecessary debug print logs. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_spi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index d41b8b6790af..4268e2f29307 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -196,9 +196,6 @@ static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len) dev_err(&spi->dev, "can't write data with the following length: %d\n", len); - dev_err(&spi->dev, - "FAILED due to NULL buffer or ZERO length check the following length: %d\n", - len); ret = -EINVAL; } -- GitLab From 2dfad49a8f93ceae8a74bc403664fd13f801f8fe Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Tue, 15 Mar 2016 18:48:10 +0900 Subject: [PATCH 0326/9938] staging: wilc1000: removes duplicate vif variable setting This patches removes duplicate vif variable setting. This value has already been set previously. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index bfa754bb022d..8a1083133a1b 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -912,7 +912,6 @@ int wilc_mac_open(struct net_device *ndev) return -ENODEV; } - vif = netdev_priv(ndev); wilc = vif->wilc; priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev); -- GitLab From ba7504730b26b7eb49731a5ac7972c34f0513ac1 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Tue, 15 Mar 2016 18:48:11 +0900 Subject: [PATCH 0327/9938] staging: wilc1000: removes duplicate wilc variable setting This patches removes duplicate wilc variable setting. This value has already been set to wl variable previously. Replace wilc with wl as well. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 8a1083133a1b..1a5de2e911cb 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -896,7 +896,6 @@ static int mac_init_fn(struct net_device *ndev) int wilc_mac_open(struct net_device *ndev) { struct wilc_vif *vif; - struct wilc *wilc; unsigned char mac_add[ETH_ALEN] = {0}; int ret = 0; @@ -912,7 +911,6 @@ int wilc_mac_open(struct net_device *ndev) return -ENODEV; } - wilc = vif->wilc; priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev); @@ -932,13 +930,13 @@ int wilc_mac_open(struct net_device *ndev) wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), 0); - } else if (!wilc_wlan_get_num_conn_ifcs(wilc)) { + } else if (!wilc_wlan_get_num_conn_ifcs(wl)) { wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - wilc->open_ifcs); + wl->open_ifcs); } else { - if (memcmp(wilc->vif[i ^ 1]->bssid, - wilc->vif[i ^ 1]->src_addr, 6)) + if (memcmp(wl->vif[i ^ 1]->bssid, + wl->vif[i ^ 1]->src_addr, 6)) wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), 0); -- GitLab From 90fd4cc5d25d5baf5540c99c100e82ce06af63f0 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Tue, 15 Mar 2016 18:48:12 +0900 Subject: [PATCH 0328/9938] staging: wilc1000: changes an ambiguous debug messages This patches changes an ambiguous debug messages. The device types are both SDIO or SPI. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 1a5de2e911cb..e949f218885c 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -907,7 +907,7 @@ int wilc_mac_open(struct net_device *ndev) wl = vif->wilc; if (!wl || !wl->dev) { - netdev_err(ndev, "wilc1000: SPI device not ready\n"); + netdev_err(ndev, "device not ready\n"); return -ENODEV; } -- GitLab From 5c6021da1c3c46f3c2727626b4a3b9c96bf688ec Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Tue, 15 Mar 2016 18:48:13 +0900 Subject: [PATCH 0329/9938] staging: wilc1000: removes goto definitions from wilc_wlan_firmware_download This patch removes goto definitions from wilc_wlan_firmware_download function. Goto '_fail_1' feature is error return. It returns error type directly without result variable replacement as well. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index ca9054a5ff88..ea671a985089 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -946,10 +946,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, blksz = BIT(12); dma_buffer = kmalloc(blksz, GFP_KERNEL); - if (!dma_buffer) { - ret = -EIO; - goto _fail_1; - } + if (!dma_buffer) + return -EIO; offset = 0; do { @@ -987,8 +985,6 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, kfree(dma_buffer); -_fail_1: - return (ret < 0) ? ret : 0; } -- GitLab From 88253ab8e637f210decc8d3ec910e5205cb75b34 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Tue, 15 Mar 2016 18:48:14 +0900 Subject: [PATCH 0330/9938] staging: wilc1000: removes an unnecessary if-condition This patch removes an unnecessary if-condition. Regardless of an if-condition is performed unconditionally '_end_' statement. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index ea671a985089..08937fe42b42 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -895,8 +895,6 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) DATA_INT_CLR | ENABLE_RX_VMM); ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size); - if (!ret) - goto _end_; _end_: if (ret) { offset += size; -- GitLab From 613eaa39d68b928c52a8d93bec4573925f009b62 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 14 Mar 2016 09:40:27 +0900 Subject: [PATCH 0331/9938] staging: wilc1000: use completion instead of struct semaphore hif_sema_wait_response This patch replaces struct semaphore hif_sema_wait_response with struct completion hif_wait_response. In case of struct hif_sema_wait_response, it better to use completion than semaphore. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0a922c7c7cbf..e73ee89cf6d4 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -232,7 +232,7 @@ static struct task_struct *hif_thread_handler; static struct message_queue hif_msg_q; static struct semaphore hif_sema_thread; static struct semaphore hif_sema_driver; -static struct semaphore hif_sema_wait_response; +static struct completion hif_wait_response; static struct semaphore hif_sema_deinit; static struct timer_list periodic_rssi; @@ -430,7 +430,7 @@ static s32 handle_get_mac_address(struct wilc_vif *vif, netdev_err(vif->ndev, "Failed to get mac address\n"); result = -EFAULT; } - up(&hif_sema_wait_response); + complete(&hif_wait_response); return result; } @@ -1938,7 +1938,7 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, wilc_enable_tcp_ack_filter(false); if (pstrStatistics != &vif->wilc->dummy_statistics) - up(&hif_sema_wait_response); + complete(&hif_wait_response); return 0; } @@ -2172,7 +2172,7 @@ static void Handle_DelAllSta(struct wilc_vif *vif, ERRORHANDLER: kfree(wid.val); - up(&hif_sema_wait_response); + complete(&hif_wait_response); } static void Handle_DelStation(struct wilc_vif *vif, @@ -2485,7 +2485,7 @@ static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr) if (ret) netdev_err(vif->ndev, "Failed to get TX PWR\n"); - up(&hif_sema_wait_response); + complete(&hif_wait_response); } static int hostIFthread(void *pvArg) @@ -3007,7 +3007,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return -EFAULT; } - down(&hif_sema_wait_response); + wait_for_completion(&hif_wait_response); return result; } @@ -3272,7 +3272,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) } if (stats != &vif->wilc->dummy_statistics) - down(&hif_sema_wait_response); + wait_for_completion(&hif_wait_response); return result; } @@ -3382,7 +3382,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) scan_while_connected = false; - sema_init(&hif_sema_wait_response, 0); + init_completion(&hif_wait_response); hif_drv = kzalloc(sizeof(struct host_if_drv), GFP_KERNEL); if (!hif_drv) { @@ -3888,7 +3888,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) if (result) netdev_err(vif->ndev, "wilc_mq_send fail\n"); - down(&hif_sema_wait_response); + wait_for_completion(&hif_wait_response); return result; } @@ -4221,7 +4221,7 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power) if (ret) netdev_err(vif->ndev, "Failed to get TX PWR\n"); - down(&hif_sema_wait_response); + wait_for_completion(&hif_wait_response); *tx_power = msg.body.tx_power.tx_pwr; return ret; -- GitLab From a5c3f8db438ab3627992124eae98fefcce53977f Mon Sep 17 00:00:00 2001 From: Anchal Jain Date: Sun, 13 Mar 2016 15:14:38 +0530 Subject: [PATCH 0332/9938] staging: wilc1000: else is not generally useful after a break or return Remove else after a break. Because else is generally not useful after a break or return. Signed-off-by: Anchal Jain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 08937fe42b42..30e1c039e80a 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -621,13 +621,12 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if ((reg & 0x1) == 0) { break; - } else { - counter++; - if (counter > 200) { - counter = 0; - ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0); - break; - } + } + counter++; + if (counter > 200) { + counter = 0; + ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0); + break; } } while (!wilc->quit); @@ -653,9 +652,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if ((reg >> 2) & 0x1) { entries = ((reg >> 3) & 0x3f); break; - } else { - release_bus(wilc, RELEASE_ALLOW_SLEEP); } + release_bus(wilc, RELEASE_ALLOW_SLEEP); } while (--timeout); if (timeout <= 0) { ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0); @@ -674,9 +672,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (!ret) break; break; - } else { - break; } + break; } while (1); if (!ret) -- GitLab From 1b7c69e84bcea7a8054b44e6671e7b9ad758c2d8 Mon Sep 17 00:00:00 2001 From: Anchal Jain Date: Mon, 14 Mar 2016 18:06:54 +0530 Subject: [PATCH 0333/9938] staging: wilc1000: Fix lines over 80 characters Break lines so that they do not exceed 80 characters. Problem found using checkpatch. Signed-off-by: Anchal Jain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 7d9e5ded8ff4..6503316314f8 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -59,9 +59,10 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) /* Get WILC header */ memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - - /* The packet offset field conain info about what type of managment frame */ - /* we are dealing with and ack status */ + /* + * The packet offset field contain info about what type of management + * the frame we are dealing with and ack status + */ pkt_offset = GET_PKT_OFFSET(header); if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { @@ -105,7 +106,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr)); hdr->hdr.it_present = cpu_to_le32 - (1 << IEEE80211_RADIOTAP_RATE); /* | */ + (1 << IEEE80211_RADIOTAP_RATE); /* | */ hdr->rate = 5; /* txrate->bitrate / 5; */ } @@ -127,8 +128,10 @@ struct tx_complete_mon_data { static void mgmt_tx_complete(void *priv, int status) { struct tx_complete_mon_data *pv_data = priv; - - /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */ + /* + * in case of fully hosting mode, the freeing will be done + * in response to the cfg packet + */ kfree(pv_data->buff); kfree(pv_data); @@ -255,7 +258,8 @@ static const struct net_device_ops wilc_wfi_netdev_ops = { * @date 12 JUL 2012 * @version 1.0 */ -struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_device *real_dev) +struct net_device *WILC_WFI_init_mon_interface(const char *name, + struct net_device *real_dev) { u32 ret = 0; struct WILC_WFI_mon_priv *priv; -- GitLab From e0c1496fcf6a1bbc9b827e763f58535585b249d5 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Mon, 14 Mar 2016 10:34:14 -0700 Subject: [PATCH 0334/9938] staging: wilc1000: replace semaphore sem_inactive_time with a completion Semaphore sem_inactive_time is used to signal completion of its host interface message. Since the thread locking this semaphore will have to wait, completions are the preferred mechanism and will offer a performance improvement. Signed-off-by: Alison Schofield Reviewed-by: Arnd Bergmann Tested-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 7 ++++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e73ee89cf6d4..2f14370b3ecc 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "host_interface.h" #include "coreconfigurator.h" #include "wilc_wlan.h" @@ -1979,7 +1980,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, return -EFAULT; } - up(&hif_drv->sem_inactive_time); + complete(&hif_drv->comp_inactive_time); return result; } @@ -3220,7 +3221,7 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, if (result) netdev_err(vif->ndev, "Failed to send get host ch param\n"); - down(&hif_drv->sem_inactive_time); + wait_for_completion(&hif_drv->comp_inactive_time); *pu32InactiveTime = inactive_time; @@ -3407,7 +3408,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) sema_init(&hif_drv->sem_test_key_block, 0); sema_init(&hif_drv->sem_test_disconn_block, 0); sema_init(&hif_drv->sem_get_rssi, 0); - sema_init(&hif_drv->sem_inactive_time, 0); + init_completion(&hif_drv->comp_inactive_time); if (clients_count == 0) { result = wilc_mq_create(&hif_msg_q); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 01f3222a4231..68852b3404d2 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -278,7 +278,7 @@ struct host_if_drv { struct semaphore sem_test_key_block; struct semaphore sem_test_disconn_block; struct semaphore sem_get_rssi; - struct semaphore sem_inactive_time; + struct completion comp_inactive_time; struct timer_list scan_timer; struct timer_list connect_timer; -- GitLab From 7c8a3dcac82f11681e3e6ad61fb2e5802a136c24 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Mon, 14 Mar 2016 10:34:39 -0700 Subject: [PATCH 0335/9938] staging: wilc1000: replace semaphore sem_get_rssi with a completion Semaphore sem_get_rssi is used to signal completion of its host interface message. Since the thread locking this semaphore will have to wait, completions are the preferred mechanism and will offer a performance improvement. Signed-off-by: Alison Schofield Reviewed-by: Arnd Bergmann Tested-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2f14370b3ecc..697491e8cfb2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1886,7 +1886,7 @@ static void Handle_GetRssi(struct wilc_vif *vif) result = -EFAULT; } - up(&vif->hif_drv->sem_get_rssi); + complete(&vif->hif_drv->comp_get_rssi); } static s32 Handle_GetStatistics(struct wilc_vif *vif, @@ -3244,7 +3244,7 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) return -EFAULT; } - down(&hif_drv->sem_get_rssi); + wait_for_completion(&hif_drv->comp_get_rssi); if (!rssi_level) { netdev_err(vif->ndev, "RSS pointer value is null\n"); @@ -3407,7 +3407,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) sema_init(&hif_drv->sem_test_key_block, 0); sema_init(&hif_drv->sem_test_disconn_block, 0); - sema_init(&hif_drv->sem_get_rssi, 0); + init_completion(&hif_drv->comp_get_rssi); init_completion(&hif_drv->comp_inactive_time); if (clients_count == 0) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 68852b3404d2..085adeeaa767 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -277,7 +277,7 @@ struct host_if_drv { struct mutex cfg_values_lock; struct semaphore sem_test_key_block; struct semaphore sem_test_disconn_block; - struct semaphore sem_get_rssi; + struct completion comp_get_rssi; struct completion comp_inactive_time; struct timer_list scan_timer; -- GitLab From 96adbd276e7194320f08fd7f00c4a1be2d910d11 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Mon, 14 Mar 2016 10:35:05 -0700 Subject: [PATCH 0336/9938] staging: wilc1000: replace sem_test_disconn_block with a completion Semaphore sem_test_disconn_block is used to signal completion of its host interface message. Since the thread locking this semaphore will have to wait, completions are the preferred mechanism and will offer a performance improvement. Signed-off-by: Alison Schofield Reviewed-by: Arnd Bergmann Tested-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 697491e8cfb2..ed7f011b3eca 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1857,7 +1857,7 @@ static void Handle_Disconnect(struct wilc_vif *vif) } } - up(&hif_drv->sem_test_disconn_block); + complete(&hif_drv->comp_test_disconn_block); } void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) @@ -3099,7 +3099,7 @@ int wilc_disconnect(struct wilc_vif *vif, u16 reason_code) if (result) netdev_err(vif->ndev, "Failed to send message: disconnect\n"); - down(&hif_drv->sem_test_disconn_block); + wait_for_completion(&hif_drv->comp_test_disconn_block); return result; } @@ -3406,7 +3406,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) } sema_init(&hif_drv->sem_test_key_block, 0); - sema_init(&hif_drv->sem_test_disconn_block, 0); + init_completion(&hif_drv->comp_test_disconn_block); init_completion(&hif_drv->comp_get_rssi); init_completion(&hif_drv->comp_inactive_time); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 085adeeaa767..3ab94a7ba5e9 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -276,7 +276,7 @@ struct host_if_drv { struct mutex cfg_values_lock; struct semaphore sem_test_key_block; - struct semaphore sem_test_disconn_block; + struct completion comp_test_disconn_block; struct completion comp_get_rssi; struct completion comp_inactive_time; -- GitLab From 702962f33ba664d3a6ce2008d076dccd93c420a2 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Mon, 14 Mar 2016 10:35:41 -0700 Subject: [PATCH 0337/9938] staging: wilc1000: replace sem_test_key_block with a completion Semaphore sem_test_key_block is used to signal completion of its host interface message. Since the thread locking this semaphore will have to wait, completions are the preferred mechanism and will offer a performance improvement. Signed-off-by: Alison Schofield Reviewed-by: Arnd Bergmann Tested-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 24 +++++++++++------------ drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ed7f011b3eca..f50571ffcf32 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1611,7 +1611,7 @@ static int Handle_Key(struct wilc_vif *vif, &wid, 1, wilc_get_vif_idx(vif)); } - up(&hif_drv->sem_test_key_block); + complete(&hif_drv->comp_test_key_block); break; case WPA_RX_GTK: @@ -1645,7 +1645,7 @@ static int Handle_Key(struct wilc_vif *vif, wilc_get_vif_idx(vif)); kfree(pu8keybuf); - up(&hif_drv->sem_test_key_block); + complete(&hif_drv->comp_test_key_block); } else if (pstrHostIFkeyAttr->action & ADDKEY) { pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL); if (pu8keybuf == NULL) { @@ -1674,7 +1674,7 @@ static int Handle_Key(struct wilc_vif *vif, wilc_get_vif_idx(vif)); kfree(pu8keybuf); - up(&hif_drv->sem_test_key_block); + complete(&hif_drv->comp_test_key_block); } _WPARxGtk_end_case_: kfree(pstrHostIFkeyAttr->attr.wpa.key); @@ -1712,7 +1712,7 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList, 2, wilc_get_vif_idx(vif)); kfree(pu8keybuf); - up(&hif_drv->sem_test_key_block); + complete(&hif_drv->comp_test_key_block); } else if (pstrHostIFkeyAttr->action & ADDKEY) { pu8keybuf = kmalloc(PTK_KEY_MSG_LEN, GFP_KERNEL); if (!pu8keybuf) { @@ -1735,7 +1735,7 @@ static int Handle_Key(struct wilc_vif *vif, &wid, 1, wilc_get_vif_idx(vif)); kfree(pu8keybuf); - up(&hif_drv->sem_test_key_block); + complete(&hif_drv->comp_test_key_block); } _WPAPtk_end_case_: @@ -2731,7 +2731,7 @@ int wilc_remove_wep_key(struct wilc_vif *vif, u8 index) result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) netdev_err(vif->ndev, "Request to remove WEP key\n"); - down(&hif_drv->sem_test_key_block); + wait_for_completion(&hif_drv->comp_test_key_block); return result; } @@ -2759,7 +2759,7 @@ int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index) result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) netdev_err(vif->ndev, "Default key index\n"); - down(&hif_drv->sem_test_key_block); + wait_for_completion(&hif_drv->comp_test_key_block); return result; } @@ -2792,7 +2792,7 @@ int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) netdev_err(vif->ndev, "STA - WEP Key\n"); - down(&hif_drv->sem_test_key_block); + wait_for_completion(&hif_drv->comp_test_key_block); return result; } @@ -2828,7 +2828,7 @@ int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, if (result) netdev_err(vif->ndev, "AP - WEP Key\n"); - down(&hif_drv->sem_test_key_block); + wait_for_completion(&hif_drv->comp_test_key_block); return result; } @@ -2884,7 +2884,7 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, if (result) netdev_err(vif->ndev, "PTK Key\n"); - down(&hif_drv->sem_test_key_block); + wait_for_completion(&hif_drv->comp_test_key_block); return result; } @@ -2952,7 +2952,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, if (result) netdev_err(vif->ndev, "RX GTK\n"); - down(&hif_drv->sem_test_key_block); + wait_for_completion(&hif_drv->comp_test_key_block); return result; } @@ -3405,7 +3405,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) sema_init(&hif_sema_deinit, 1); } - sema_init(&hif_drv->sem_test_key_block, 0); + init_completion(&hif_drv->comp_test_key_block); init_completion(&hif_drv->comp_test_disconn_block); init_completion(&hif_drv->comp_get_rssi); init_completion(&hif_drv->comp_inactive_time); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3ab94a7ba5e9..8d2dd0db0bed 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -275,7 +275,7 @@ struct host_if_drv { struct cfg_param_attr cfg_values; struct mutex cfg_values_lock; - struct semaphore sem_test_key_block; + struct completion comp_test_key_block; struct completion comp_test_disconn_block; struct completion comp_get_rssi; struct completion comp_inactive_time; -- GitLab From d5e27e8b83b1da0cd64a6a090e273a199c2805fc Mon Sep 17 00:00:00 2001 From: "Roger H. Newell" Date: Sat, 19 Mar 2016 12:49:21 -0230 Subject: [PATCH 0338/9938] staging: wilc1000: Removed braces from single block statements This patch corrects warnings generated by checkpatch.pl by removing braces from single block statements. Signed-ff-by: Roger H. Newell Signed-off-by: Greg Kroah-Hartman --- .../staging/wilc1000/wilc_wfi_cfgoperations.c | 31 +++++++------------ drivers/staging/wilc1000/wilc_wlan_cfg.c | 3 +- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 448a5c8c4514..70625f8a2e3c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -558,11 +558,11 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, if (!pstrWFIDrv->p2p_connect) wlan_channel = INVALID_CHANNEL; - if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev)) { + if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev)) pstrDisconnectNotifInfo->reason = 3; - } else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev)) { + else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev)) pstrDisconnectNotifInfo->reason = 1; - } + cfg80211_disconnected(dev, pstrDisconnectNotifInfo->reason, pstrDisconnectNotifInfo->ie, pstrDisconnectNotifInfo->ie_len, false, GFP_KERNEL); @@ -739,18 +739,15 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len, sme->key_idx); } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) { - if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) { + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) u8security = ENCRYPT_ENABLED | WPA2 | TKIP; - } else { + else u8security = ENCRYPT_ENABLED | WPA2 | AES; - } } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) { - if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) { + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) u8security = ENCRYPT_ENABLED | WPA | TKIP; - } else { + else u8security = ENCRYPT_ENABLED | WPA | AES; - } - } else { s32Error = -ENOTSUPP; netdev_err(dev, "Not supported cipher\n"); @@ -762,11 +759,10 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) { for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) { - if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP) { + if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP) u8security = u8security | TKIP; - } else { + else u8security = u8security | AES; - } } } @@ -1355,9 +1351,8 @@ static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len) u8 channel_list_attr_index = 0; while (index < len) { - if (buf[index] == GO_INTENT_ATTR_ID) { + if (buf[index] == GO_INTENT_ATTR_ID) buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1); - } if (buf[index] == CHANLIST_ATTR_ID) channel_list_attr_index = index; @@ -1369,9 +1364,8 @@ static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len) if (channel_list_attr_index) { for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) { if (buf[i] == 0x51) { - for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) { + for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) buf[j] = wlan_channel; - } break; } } @@ -1409,9 +1403,8 @@ static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftyp if (channel_list_attr_index) { for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) { if (buf[i] == 0x51) { - for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) { + for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) buf[j] = wlan_channel; - } break; } } diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index b3425b9cec94..b9711caac0da 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -253,9 +253,8 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) if ((b != NULL) && (size != 0)) { memcpy(&buf[4], b, size); - for (i = 0; i < size; i++) { + for (i = 0; i < size; i++) checksum += buf[i + 4]; - } } buf[size + 4] = checksum; -- GitLab From b59958ee900c81692da131873c0fc0b1599f164f Mon Sep 17 00:00:00 2001 From: "Roger H. Newell" Date: Sat, 19 Mar 2016 12:50:52 -0230 Subject: [PATCH 0339/9938] staging: wilc1000: Replaced comparison to NULL statements This patch corrects checks generated by checkpatch.pl by replacing comparison to null statements with equivalent statements in the form "x" or "!x" Signed-off-by: Roger H. Newell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_wlan_cfg.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index f50571ffcf32..4be8b3183b28 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1648,7 +1648,7 @@ static int Handle_Key(struct wilc_vif *vif, complete(&hif_drv->comp_test_key_block); } else if (pstrHostIFkeyAttr->action & ADDKEY) { pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL); - if (pu8keybuf == NULL) { + if (!pu8keybuf) { ret = -ENOMEM; goto _WPARxGtk_end_case_; } diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index b9711caac0da..926fc16319b6 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -230,7 +230,7 @@ static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str, u32 siz buf[1] = (u8)(id >> 8); buf[2] = (u8)size; - if ((str != NULL) && (size != 0)) + if ((str) && (size != 0)) memcpy(&buf[3], str, size); return (size + 3); @@ -251,7 +251,7 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) buf[2] = (u8)size; buf[3] = (u8)(size >> 8); - if ((b != NULL) && (size != 0)) { + if ((b) && (size != 0)) { memcpy(&buf[4], b, size); for (i = 0; i < size; i++) checksum += buf[i + 4]; -- GitLab From 4dadfb97b73f0fbcc0c6f5a6897c0942c05a9dd3 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sun, 13 Mar 2016 15:07:30 -0300 Subject: [PATCH 0340/9938] staging: rtl8712: hal_init.c: fix comment block code style This patch fixes several warnings caused by malformed comments on hal_init.c and found by checkpatch.pl. Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/hal_init.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 8008efe5686d..37fe0a4db602 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -297,7 +297,8 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) tmp8 = r8712_read8(padapter, 0x1025000A); if (tmp8 & BIT(4)) /* When boot from EEPROM, - & FW need more time to read EEPROM */ + * & FW need more time to read EEPROM + */ i = 60; else /* boot from EFUSE */ i = 30; @@ -332,7 +333,8 @@ uint rtl8712_hal_init(struct _adapter *padapter) r8712_read32(padapter, RCR)); val32 = r8712_read32(padapter, RCR); r8712_write32(padapter, RCR, (val32 | BIT(26))); /* Enable RX TCP - Checksum offload */ + * Checksum offload + */ netdev_info(padapter->pnetdev, "2 RCR=0x%x\n", r8712_read32(padapter, RCR)); val32 = r8712_read32(padapter, RCR); @@ -346,7 +348,8 @@ uint rtl8712_hal_init(struct _adapter *padapter) r8712_write8(padapter, 0x102500BD, r8712_read8(padapter, 0x102500BD) | BIT(7)); /* enable usb rx aggregation */ r8712_write8(padapter, 0x102500D9, 1); /* TH=1 => means that invalidate - * usb rx aggregation */ + * usb rx aggregation + */ r8712_write8(padapter, 0x1025FE5B, 0x04); /* 1.7ms/4 */ /* Fix the RX FIFO issue(USB error) */ r8712_write8(padapter, 0x1025fe5C, r8712_read8(padapter, 0x1025fe5C) @@ -367,7 +370,8 @@ uint rtl8712_hal_deinit(struct _adapter *padapter) r8712_write8(padapter, SYS_FUNC_EN + 1, 0x70); r8712_write8(padapter, PMC_FSM, 0x06); /* Enable Loader Data Keep */ r8712_write8(padapter, SYS_ISO_CTRL, 0xF9); /* Isolation signals from - * CORE, PLL */ + * CORE, PLL + */ r8712_write8(padapter, SYS_ISO_CTRL + 1, 0xe8); /* Enable EFUSE 1.2V */ r8712_write8(padapter, AFE_PLL_CTRL, 0x00); /* Disable AFE PLL. */ r8712_write8(padapter, LDOA15_CTRL, 0x54); /* Disable A15V */ -- GitLab From 7fcf92c0a4847b0d66fbc09446561752ec2d2575 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues Date: Sun, 13 Mar 2016 15:30:57 -0300 Subject: [PATCH 0341/9938] staging: rtl8712: rtl8712_cmd.c: fixed comparison to null This patch fixes multiple "comparison to NULL" checkpatch.pl issues: CHECK: Comparison to NULL could be written "!pcmd" + if (pcmd == NULL) Signed-off-by: Juliana Rodrigues Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_cmd.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 50f400234593..13c018340ff2 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -135,7 +135,7 @@ static u8 read_macreg_hdl(struct _adapter *padapter, u8 *pbuf) /* invoke cmd->callback function */ pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (pcmd_callback == NULL) + if (!pcmd_callback) r8712_free_cmd_obj(pcmd); else pcmd_callback(padapter, pcmd); @@ -149,7 +149,7 @@ static u8 write_macreg_hdl(struct _adapter *padapter, u8 *pbuf) /* invoke cmd->callback function */ pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (pcmd_callback == NULL) + if (!pcmd_callback) r8712_free_cmd_obj(pcmd); else pcmd_callback(padapter, pcmd); @@ -165,7 +165,7 @@ static u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf) if (pcmd->rsp && pcmd->rspsz > 0) memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz); pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (pcmd_callback == NULL) + if (!pcmd_callback) r8712_free_cmd_obj(pcmd); else pcmd_callback(padapter, pcmd); @@ -178,7 +178,7 @@ static u8 write_bbreg_hdl(struct _adapter *padapter, u8 *pbuf) struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (pcmd_callback == NULL) + if (!pcmd_callback) r8712_free_cmd_obj(pcmd); else pcmd_callback(padapter, pcmd); @@ -194,7 +194,7 @@ static u8 read_rfreg_hdl(struct _adapter *padapter, u8 *pbuf) if (pcmd->rsp && pcmd->rspsz > 0) memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz); pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (pcmd_callback == NULL) + if (!pcmd_callback) r8712_free_cmd_obj(pcmd); else pcmd_callback(padapter, pcmd); @@ -207,7 +207,7 @@ static u8 write_rfreg_hdl(struct _adapter *padapter, u8 *pbuf) struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (pcmd_callback == NULL) + if (!pcmd_callback) r8712_free_cmd_obj(pcmd); else pcmd_callback(padapter, pcmd); @@ -227,7 +227,7 @@ static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, { struct cmd_obj *pcmd_r; - if (pcmd == NULL) + if (!pcmd) return pcmd; pcmd_r = NULL; @@ -416,7 +416,7 @@ int r8712_cmd_thread(void *context) /* free all cmd_obj resources */ do { pcmd = r8712_dequeue_cmd(&(pcmdpriv->cmd_queue)); - if (pcmd == NULL) + if (!pcmd) break; r8712_free_cmd_obj(pcmd); } while (1); @@ -431,7 +431,7 @@ void r8712_event_handle(struct _adapter *padapter, uint *peventbuf) void (*event_callback)(struct _adapter *dev, u8 *pbuf); struct evt_priv *pevt_priv = &(padapter->evtpriv); - if (peventbuf == NULL) + if (!peventbuf) goto _abort_event_; evt_sz = (u16)(le32_to_cpu(*peventbuf) & 0xffff); evt_seq = (u8)((le32_to_cpu(*peventbuf) >> 24) & 0x7f); -- GitLab From 5a9e10a11e6a76f726235a788265b7c6c5bd1bd7 Mon Sep 17 00:00:00 2001 From: Ben Marsh Date: Sat, 12 Mar 2016 10:33:00 +0100 Subject: [PATCH 0342/9938] Staging: rtl8188eu: removes an unnecessary cast on a void pointer. Patch to rtl8188e_rxdesc.c to remove an unnecessary cast on a void pointer. Signed-off-by: Ben Marsh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 53cf3baf46e0..4c78369673b6 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -64,7 +64,7 @@ static void process_link_qual(struct adapter *padapter, void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe) { - struct recv_frame *precvframe = (struct recv_frame *)prframe; + struct recv_frame *precvframe = prframe; /* Check RSSI */ process_rssi(padapter, precvframe); -- GitLab From fb025382b4c2e394dd2b5ac4d173d42d2d9b5b69 Mon Sep 17 00:00:00 2001 From: Kyle Kuffermann Date: Sun, 13 Mar 2016 10:16:27 -0400 Subject: [PATCH 0343/9938] staging: rtl8188eu: Remove license paragraph with mailing address This fixes the issue reported by checkpatch.pl: "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL." in all files for the rtl8188eu driver. Signed-off-by: Kyle Kuffermann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ap.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_cmd.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_debug.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_efuse.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_ieee80211.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_ioctl_set.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_mlme.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_pwrctrl.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_recv.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_rf.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_security.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_sreset.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_sta_mgt.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 5 ----- drivers/staging/rtl8188eu/core/rtw_xmit.c | 5 ----- drivers/staging/rtl8188eu/hal/bb_cfg.c | 5 ----- drivers/staging/rtl8188eu/hal/fw.c | 4 ---- drivers/staging/rtl8188eu/hal/hal_com.c | 5 ----- drivers/staging/rtl8188eu/hal/hal_intf.c | 5 ----- drivers/staging/rtl8188eu/hal/mac_cfg.c | 5 ----- drivers/staging/rtl8188eu/hal/odm.c | 5 ----- drivers/staging/rtl8188eu/hal/odm_HWConfig.c | 5 ----- drivers/staging/rtl8188eu/hal/odm_RTL8188E.c | 5 ----- drivers/staging/rtl8188eu/hal/phy.c | 5 ----- drivers/staging/rtl8188eu/hal/pwrseq.c | 5 ----- drivers/staging/rtl8188eu/hal/pwrseqcmd.c | 4 ---- drivers/staging/rtl8188eu/hal/rf.c | 4 ---- drivers/staging/rtl8188eu/hal/rf_cfg.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188e_dm.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188eu_led.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c | 5 ----- drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c | 5 ----- drivers/staging/rtl8188eu/hal/usb_halinit.c | 5 ----- drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h | 5 ----- drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h | 5 ----- drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h | 5 ----- drivers/staging/rtl8188eu/include/HalVerDef.h | 5 ----- drivers/staging/rtl8188eu/include/basic_types.h | 5 ----- drivers/staging/rtl8188eu/include/drv_types.h | 5 ----- drivers/staging/rtl8188eu/include/fw.h | 4 ---- drivers/staging/rtl8188eu/include/hal_com.h | 5 ----- drivers/staging/rtl8188eu/include/hal_intf.h | 5 ----- drivers/staging/rtl8188eu/include/ieee80211.h | 5 ----- drivers/staging/rtl8188eu/include/mlme_osdep.h | 5 ----- drivers/staging/rtl8188eu/include/mp_custom_oid.h | 5 ----- drivers/staging/rtl8188eu/include/odm.h | 5 ----- drivers/staging/rtl8188eu/include/odm_HWConfig.h | 4 ---- drivers/staging/rtl8188eu/include/odm_RTL8188E.h | 5 ----- drivers/staging/rtl8188eu/include/odm_RegDefine11N.h | 5 ----- drivers/staging/rtl8188eu/include/odm_debug.h | 5 ----- drivers/staging/rtl8188eu/include/odm_precomp.h | 5 ----- drivers/staging/rtl8188eu/include/odm_reg.h | 5 ----- drivers/staging/rtl8188eu/include/odm_types.h | 5 ----- drivers/staging/rtl8188eu/include/osdep_intf.h | 5 ----- drivers/staging/rtl8188eu/include/osdep_service.h | 5 ----- drivers/staging/rtl8188eu/include/pwrseq.h | 5 ----- drivers/staging/rtl8188eu/include/pwrseqcmd.h | 5 ----- drivers/staging/rtl8188eu/include/recv_osdep.h | 5 ----- drivers/staging/rtl8188eu/include/rtl8188e_cmd.h | 5 ----- drivers/staging/rtl8188eu/include/rtl8188e_dm.h | 5 ----- drivers/staging/rtl8188eu/include/rtl8188e_hal.h | 5 ----- drivers/staging/rtl8188eu/include/rtl8188e_led.h | 5 ----- drivers/staging/rtl8188eu/include/rtl8188e_recv.h | 5 ----- drivers/staging/rtl8188eu/include/rtl8188e_spec.h | 4 ---- drivers/staging/rtl8188eu/include/rtl8188e_xmit.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_android.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_ap.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_cmd.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_debug.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_eeprom.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_efuse.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_event.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_ht.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_ioctl.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_ioctl_rtl.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_ioctl_set.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_iol.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_mlme.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_mlme_ext.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_pwrctrl.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_qos.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_recv.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_rf.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_security.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_sreset.h | 5 ----- drivers/staging/rtl8188eu/include/rtw_xmit.h | 5 ----- drivers/staging/rtl8188eu/include/sta_info.h | 5 ----- drivers/staging/rtl8188eu/include/usb_hal.h | 5 ----- drivers/staging/rtl8188eu/include/usb_ops_linux.h | 5 ----- drivers/staging/rtl8188eu/include/wifi.h | 5 ----- drivers/staging/rtl8188eu/include/wlan_bssdef.h | 5 ----- drivers/staging/rtl8188eu/include/xmit_osdep.h | 5 ----- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 5 ----- drivers/staging/rtl8188eu/os_dep/mlme_linux.c | 5 ----- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 5 ----- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 5 ----- drivers/staging/rtl8188eu/os_dep/recv_linux.c | 5 ----- drivers/staging/rtl8188eu/os_dep/rtw_android.c | 5 ----- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 5 ----- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 4 ---- drivers/staging/rtl8188eu/os_dep/xmit_linux.c | 5 ----- 107 files changed, 528 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 012860b34651..a5755358cc5d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_AP_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index e5a6b7a70df7..f08d052f8e52 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_CMD_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c index 93e898d598fe..db5c952ac852 100644 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ b/drivers/staging/rtl8188eu/core/rtw_debug.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_DEBUG_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 19f11d04d152..fbce1f7e68ca 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_EFUSE_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index f4e4baf6054a..0b0d78fe83ed 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _IEEE80211_C diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index cf60717a6c19..f85a6abec3a3 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_IOCTL_SET_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index a645a620ebe2..472cd3f381cb 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_MLME_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 591a9127b573..da6ccc1a69cc 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_MLME_EXT_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 5e1ef9fdcf47..59c6d8ab60f6 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_PWRCTRL_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 5f53aa1cfd8a..977bb2532c3e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_RECV_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_rf.c b/drivers/staging/rtl8188eu/core/rtw_rf.c index 4ad2d8f63acf..3fc1a8fd367c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_rf.c +++ b/drivers/staging/rtl8188eu/core/rtw_rf.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_RF_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index b781ccf45bc0..442a614a3726 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_SECURITY_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_sreset.c b/drivers/staging/rtl8188eu/core/rtw_sreset.c index e725a4708775..13a5bf4730ab 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sreset.c +++ b/drivers/staging/rtl8188eu/core/rtw_sreset.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #include diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c index 78a9b9bf3b32..a71e25294add 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_STA_MGT_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 83096696cd5b..4410fe8d7c68 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_WLAN_UTIL_C_ diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index f2dd7a60f67c..e0a5567f5942 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTW_XMIT_C_ diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index c2ad6a3b99da..cce1ea259b76 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * -* You should have received a copy of the GNU General Public License along with -* this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA -* -* ******************************************************************************/ #include "odm_precomp.h" diff --git a/drivers/staging/rtl8188eu/hal/fw.c b/drivers/staging/rtl8188eu/hal/fw.c index 656133c47426..03d091bad13a 100644 --- a/drivers/staging/rtl8188eu/hal/fw.c +++ b/drivers/staging/rtl8188eu/hal/fw.c @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * The full GNU General Public License is included in this distribution in the * file called LICENSE. * diff --git a/drivers/staging/rtl8188eu/hal/hal_com.c b/drivers/staging/rtl8188eu/hal/hal_com.c index 3871cda2eec2..960cc406d238 100644 --- a/drivers/staging/rtl8188eu/hal/hal_com.c +++ b/drivers/staging/rtl8188eu/hal/hal_com.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #include #include diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 85c17ef942f3..c49c86ccea76 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _HAL_INTF_C_ diff --git a/drivers/staging/rtl8188eu/hal/mac_cfg.c b/drivers/staging/rtl8188eu/hal/mac_cfg.c index 0bc1b215219a..6ed5e15ce661 100644 --- a/drivers/staging/rtl8188eu/hal/mac_cfg.c +++ b/drivers/staging/rtl8188eu/hal/mac_cfg.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * -* You should have received a copy of the GNU General Public License along with -* this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA -* -* ******************************************************************************/ #include "odm_precomp.h" diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 8d2316b9e6e5..57a127501694 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ /* include files */ diff --git a/drivers/staging/rtl8188eu/hal/odm_HWConfig.c b/drivers/staging/rtl8188eu/hal/odm_HWConfig.c index 28b9f7f591c0..0555e42a3787 100644 --- a/drivers/staging/rtl8188eu/hal/odm_HWConfig.c +++ b/drivers/staging/rtl8188eu/hal/odm_HWConfig.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ /* include files */ diff --git a/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c b/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c index c0242a095c19..dd9b902c8ae3 100644 --- a/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c +++ b/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #include "odm_precomp.h" diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index ae42b4492c77..a83bbea9be93 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTL8188E_PHYCFG_C_ diff --git a/drivers/staging/rtl8188eu/hal/pwrseq.c b/drivers/staging/rtl8188eu/hal/pwrseq.c index 20dce42cee1d..d92a34ea8d60 100644 --- a/drivers/staging/rtl8188eu/hal/pwrseq.c +++ b/drivers/staging/rtl8188eu/hal/pwrseq.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #include "pwrseq.h" diff --git a/drivers/staging/rtl8188eu/hal/pwrseqcmd.c b/drivers/staging/rtl8188eu/hal/pwrseqcmd.c index b76b0f5d6220..2867864bbfbe 100644 --- a/drivers/staging/rtl8188eu/hal/pwrseqcmd.c +++ b/drivers/staging/rtl8188eu/hal/pwrseqcmd.c @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * ******************************************************************************/ #include diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c index 38845d17d593..1596274eefc5 100644 --- a/drivers/staging/rtl8188eu/hal/rf.c +++ b/drivers/staging/rtl8188eu/hal/rf.c @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * ******************************************************************************/ #include diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 44945427cc34..453f9e729067 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * -* You should have received a copy of the GNU General Public License along with -* this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA -* -* ******************************************************************************/ #include "odm_precomp.h" diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 580876313e98..2422c0297a50 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTL8188E_CMD_C_ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index f9919a94a77e..81f2931876f8 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ /* */ /* Description: */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 2592bc298f84..0b444fd3e550 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _HAL_INIT_C_ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 4c78369673b6..4ac6bcf9dada 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTL8188E_REDESC_C_ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c index a6ba53b488e3..460a20558bc0 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTL8188E_XMIT_C_ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index 564cf53bff1b..d9e677ef8f84 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #include diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index d6d009aafcf0..255d6f215091 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTL8188EU_RECV_C_ #include diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index c96d80487a56..ec21d8c82eba 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _RTL8188E_XMIT_C_ #include diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 07a61b8271f0..358762d3fb45 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _HCI_HAL_INIT_C_ diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h index 2670d6b6a79e..8990748a1919 100644 --- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h +++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __INC_HAL8188EPHYCFG_H__ #define __INC_HAL8188EPHYCFG_H__ diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h index 9f2969bf8355..344c73d1081b 100644 --- a/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h +++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __INC_HAL8188EPHYREG_H__ #define __INC_HAL8188EPHYREG_H__ diff --git a/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h b/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h index 1bf9bc70a696..dbb55247b0c6 100644 --- a/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h +++ b/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * -* You should have received a copy of the GNU General Public License along with -* this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA -* -* ******************************************************************************/ #ifndef __INC_FW_8188E_HW_IMG_H diff --git a/drivers/staging/rtl8188eu/include/HalVerDef.h b/drivers/staging/rtl8188eu/include/HalVerDef.h index 6f2b2a436b04..d244efff3593 100644 --- a/drivers/staging/rtl8188eu/include/HalVerDef.h +++ b/drivers/staging/rtl8188eu/include/HalVerDef.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __HAL_VERSION_DEF_H__ #define __HAL_VERSION_DEF_H__ diff --git a/drivers/staging/rtl8188eu/include/basic_types.h b/drivers/staging/rtl8188eu/include/basic_types.h index 3fb691daa5af..2c1676d2ac6e 100644 --- a/drivers/staging/rtl8188eu/include/basic_types.h +++ b/drivers/staging/rtl8188eu/include/basic_types.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __BASIC_TYPES_H__ #define __BASIC_TYPES_H__ diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index dcb032b6c3a7..55506a7da1a4 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ /*----------------------------------------------------------------------------- diff --git a/drivers/staging/rtl8188eu/include/fw.h b/drivers/staging/rtl8188eu/include/fw.h index 7884d8f65763..b016f32a8992 100644 --- a/drivers/staging/rtl8188eu/include/fw.h +++ b/drivers/staging/rtl8188eu/include/fw.h @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * The full GNU General Public License is included in this distribution in the * file called LICENSE. * diff --git a/drivers/staging/rtl8188eu/include/hal_com.h b/drivers/staging/rtl8188eu/include/hal_com.h index 47715d949d54..aaf444733507 100644 --- a/drivers/staging/rtl8188eu/include/hal_com.h +++ b/drivers/staging/rtl8188eu/include/hal_com.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __HAL_COMMON_H__ #define __HAL_COMMON_H__ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 1b1c10292456..eaf939bd4103 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __HAL_INTF_H__ #define __HAL_INTF_H__ diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index f8f5eb6b7976..d8284c84f09c 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __IEEE80211_H #define __IEEE80211_H diff --git a/drivers/staging/rtl8188eu/include/mlme_osdep.h b/drivers/staging/rtl8188eu/include/mlme_osdep.h index ae1722c67032..5a35b0866db6 100644 --- a/drivers/staging/rtl8188eu/include/mlme_osdep.h +++ b/drivers/staging/rtl8188eu/include/mlme_osdep.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __MLME_OSDEP_H_ #define __MLME_OSDEP_H_ diff --git a/drivers/staging/rtl8188eu/include/mp_custom_oid.h b/drivers/staging/rtl8188eu/include/mp_custom_oid.h index 6fa52cf99c4e..1a06ee6ad460 100644 --- a/drivers/staging/rtl8188eu/include/mp_custom_oid.h +++ b/drivers/staging/rtl8188eu/include/mp_custom_oid.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __CUSTOM_OID_H #define __CUSTOM_OID_H diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index af781c7cd3a5..dbebf17f36d3 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ diff --git a/drivers/staging/rtl8188eu/include/odm_HWConfig.h b/drivers/staging/rtl8188eu/include/odm_HWConfig.h index ef792bfd535e..da7325d599c6 100644 --- a/drivers/staging/rtl8188eu/include/odm_HWConfig.h +++ b/drivers/staging/rtl8188eu/include/odm_HWConfig.h @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * ******************************************************************************/ diff --git a/drivers/staging/rtl8188eu/include/odm_RTL8188E.h b/drivers/staging/rtl8188eu/include/odm_RTL8188E.h index 14dce6c4b1bc..72b4db67ac33 100644 --- a/drivers/staging/rtl8188eu/include/odm_RTL8188E.h +++ b/drivers/staging/rtl8188eu/include/odm_RTL8188E.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __ODM_RTL8188E_H__ #define __ODM_RTL8188E_H__ diff --git a/drivers/staging/rtl8188eu/include/odm_RegDefine11N.h b/drivers/staging/rtl8188eu/include/odm_RegDefine11N.h index 5a61f902bc1b..c82c09013487 100644 --- a/drivers/staging/rtl8188eu/include/odm_RegDefine11N.h +++ b/drivers/staging/rtl8188eu/include/odm_RegDefine11N.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __ODM_REGDEFINE11N_H__ diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h index e9390963d6ff..52e51f19f752 100644 --- a/drivers/staging/rtl8188eu/include/odm_debug.h +++ b/drivers/staging/rtl8188eu/include/odm_debug.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ diff --git a/drivers/staging/rtl8188eu/include/odm_precomp.h b/drivers/staging/rtl8188eu/include/odm_precomp.h index 0f236da09277..9e5fe1777e6c 100644 --- a/drivers/staging/rtl8188eu/include/odm_precomp.h +++ b/drivers/staging/rtl8188eu/include/odm_precomp.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __ODM_PRECOMP_H__ diff --git a/drivers/staging/rtl8188eu/include/odm_reg.h b/drivers/staging/rtl8188eu/include/odm_reg.h index 7f10b695cf9d..3405a44a19ed 100644 --- a/drivers/staging/rtl8188eu/include/odm_reg.h +++ b/drivers/staging/rtl8188eu/include/odm_reg.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ /* */ /* File Name: odm_reg.h */ diff --git a/drivers/staging/rtl8188eu/include/odm_types.h b/drivers/staging/rtl8188eu/include/odm_types.h index c1355b959c55..3474a9c72640 100644 --- a/drivers/staging/rtl8188eu/include/odm_types.h +++ b/drivers/staging/rtl8188eu/include/odm_types.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __ODM_TYPES_H__ #define __ODM_TYPES_H__ diff --git a/drivers/staging/rtl8188eu/include/osdep_intf.h b/drivers/staging/rtl8188eu/include/osdep_intf.h index 1521744d626c..54fca79827e3 100644 --- a/drivers/staging/rtl8188eu/include/osdep_intf.h +++ b/drivers/staging/rtl8188eu/include/osdep_intf.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __OSDEP_INTF_H_ diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 22de53d6539a..5475956c5ee5 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __OSDEP_SERVICE_H_ #define __OSDEP_SERVICE_H_ diff --git a/drivers/staging/rtl8188eu/include/pwrseq.h b/drivers/staging/rtl8188eu/include/pwrseq.h index 9dbf8435f147..afd61cf4cb15 100644 --- a/drivers/staging/rtl8188eu/include/pwrseq.h +++ b/drivers/staging/rtl8188eu/include/pwrseq.h @@ -12,11 +12,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __HAL8188EPWRSEQ_H__ diff --git a/drivers/staging/rtl8188eu/include/pwrseqcmd.h b/drivers/staging/rtl8188eu/include/pwrseqcmd.h index 468a3fb28e00..c4a919ea17ea 100644 --- a/drivers/staging/rtl8188eu/include/pwrseqcmd.h +++ b/drivers/staging/rtl8188eu/include/pwrseqcmd.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __HALPWRSEQCMD_H__ #define __HALPWRSEQCMD_H__ diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h index fdeb603b6cc1..cad31587c30a 100644 --- a/drivers/staging/rtl8188eu/include/recv_osdep.h +++ b/drivers/staging/rtl8188eu/include/recv_osdep.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RECV_OSDEP_H_ #define __RECV_OSDEP_H_ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h index f813ce0563f8..4d7d804658c2 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTL8188E_CMD_H__ #define __RTL8188E_CMD_H__ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h index 5e0ac31ef464..4190112a50bf 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTL8188E_DM_H__ #define __RTL8188E_DM_H__ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 9f5050e6f6ab..9dd5c293a54b 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTL8188E_HAL_H__ #define __RTL8188E_HAL_H__ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_led.h b/drivers/staging/rtl8188eu/include/rtl8188e_led.h index c0147e73cd8c..fca6d8c81e90 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_led.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_led.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTL8188E_LED_H__ #define __RTL8188E_LED_H__ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h index 5fed30d389a2..54048bc826e5 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTL8188E_RECV_H__ #define __RTL8188E_RECV_H__ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h index beeee4a6b0bc..fb82f663b1f5 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * *******************************************************************************/ #ifndef __RTL8188E_SPEC_H__ #define __RTL8188E_SPEC_H__ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h index 0b96d42e290b..65a63df2077f 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTL8188E_XMIT_H__ #define __RTL8188E_XMIT_H__ diff --git a/drivers/staging/rtl8188eu/include/rtw_android.h b/drivers/staging/rtl8188eu/include/rtw_android.h index e85bf1ff01f8..e81ee92b0ae2 100644 --- a/drivers/staging/rtl8188eu/include/rtw_android.h +++ b/drivers/staging/rtl8188eu/include/rtw_android.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_ANDROID_H__ diff --git a/drivers/staging/rtl8188eu/include/rtw_ap.h b/drivers/staging/rtl8188eu/include/rtw_ap.h index 6128ccce91ba..b820684bc3fe 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ap.h +++ b/drivers/staging/rtl8188eu/include/rtw_ap.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_AP_H_ #define __RTW_AP_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index 9e9f5f4af8f1..08ca59217cb7 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_CMD_H_ #define __RTW_CMD_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h index 971bf457f32d..7ed4cada7efa 100644 --- a/drivers/staging/rtl8188eu/include/rtw_debug.h +++ b/drivers/staging/rtl8188eu/include/rtw_debug.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_DEBUG_H__ #define __RTW_DEBUG_H__ diff --git a/drivers/staging/rtl8188eu/include/rtw_eeprom.h b/drivers/staging/rtl8188eu/include/rtw_eeprom.h index 904fea1fad6c..5dd73841dd9e 100644 --- a/drivers/staging/rtl8188eu/include/rtw_eeprom.h +++ b/drivers/staging/rtl8188eu/include/rtw_eeprom.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_EEPROM_H__ #define __RTW_EEPROM_H__ diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h index 5660eed7196b..9bfb10c302b5 100644 --- a/drivers/staging/rtl8188eu/include/rtw_efuse.h +++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_EFUSE_H__ #define __RTW_EFUSE_H__ diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h index 52151dc4495a..5c34e567d341 100644 --- a/drivers/staging/rtl8188eu/include/rtw_event.h +++ b/drivers/staging/rtl8188eu/include/rtw_event.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_EVENT_H_ #define _RTW_EVENT_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h index beb210b37083..b45483fd069f 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ht.h +++ b/drivers/staging/rtl8188eu/include/rtw_ht.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_HT_H_ #define _RTW_HT_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl.h b/drivers/staging/rtl8188eu/include/rtw_ioctl.h index ee2cb54a7552..3a652df4b26c 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ioctl.h +++ b/drivers/staging/rtl8188eu/include/rtw_ioctl.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_IOCTL_H_ #define _RTW_IOCTL_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl_rtl.h b/drivers/staging/rtl8188eu/include/rtw_ioctl_rtl.h index 8fa3858cb776..da4949f94f4c 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ioctl_rtl.h +++ b/drivers/staging/rtl8188eu/include/rtw_ioctl_rtl.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_IOCTL_RTL_H_ #define _RTW_IOCTL_RTL_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h b/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h index fa9d655eaab9..b6e14a8b7a11 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h +++ b/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_IOCTL_SET_H_ #define __RTW_IOCTL_SET_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_iol.h b/drivers/staging/rtl8188eu/include/rtw_iol.h index 68aae7f0b02f..1f324e68d2ae 100644 --- a/drivers/staging/rtl8188eu/include/rtw_iol.h +++ b/drivers/staging/rtl8188eu/include/rtw_iol.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_IOL_H_ #define __RTW_IOL_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 4c992573e3ca..5d8bce0f58db 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_MLME_H_ #define __RTW_MLME_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 44711332b90c..27382ff24a84 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_MLME_EXT_H_ #define __RTW_MLME_EXT_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h b/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h index 30fd17f23bf1..02b300217185 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h +++ b/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ /***************************************************************************** * diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h index a493d4c37ef1..9680e2eab62f 100644 --- a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h +++ b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_PWRCTRL_H_ #define __RTW_PWRCTRL_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_qos.h b/drivers/staging/rtl8188eu/include/rtw_qos.h index bbee1ddc00bb..45a77f6f8427 100644 --- a/drivers/staging/rtl8188eu/include/rtw_qos.h +++ b/drivers/staging/rtl8188eu/include/rtw_qos.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_QOS_H_ #define _RTW_QOS_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index eb1ac3d03123..b0373b6216d6 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_RECV_H_ #define _RTW_RECV_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_rf.h b/drivers/staging/rtl8188eu/include/rtw_rf.h index 35f61be12acd..66896af02042 100644 --- a/drivers/staging/rtl8188eu/include/rtw_rf.h +++ b/drivers/staging/rtl8188eu/include/rtw_rf.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_RF_H_ #define __RTW_RF_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_security.h b/drivers/staging/rtl8188eu/include/rtw_security.h index a1aebe6c8452..ca1247bce6e3 100644 --- a/drivers/staging/rtl8188eu/include/rtw_security.h +++ b/drivers/staging/rtl8188eu/include/rtw_security.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __RTW_SECURITY_H_ #define __RTW_SECURITY_H_ diff --git a/drivers/staging/rtl8188eu/include/rtw_sreset.h b/drivers/staging/rtl8188eu/include/rtw_sreset.h index 3a62ed010875..ce027dfdecc5 100644 --- a/drivers/staging/rtl8188eu/include/rtw_sreset.h +++ b/drivers/staging/rtl8188eu/include/rtw_sreset.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_SRESET_C_ #define _RTW_SRESET_C_ diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h index b7c20883d355..a0853bab3edb 100644 --- a/drivers/staging/rtl8188eu/include/rtw_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _RTW_XMIT_H_ #define _RTW_XMIT_H_ diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/rtl8188eu/include/sta_info.h index d4e78326fc8d..42a035123365 100644 --- a/drivers/staging/rtl8188eu/include/sta_info.h +++ b/drivers/staging/rtl8188eu/include/sta_info.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __STA_INFO_H_ #define __STA_INFO_H_ diff --git a/drivers/staging/rtl8188eu/include/usb_hal.h b/drivers/staging/rtl8188eu/include/usb_hal.h index 8a65995d5e48..b1bf07a9013e 100644 --- a/drivers/staging/rtl8188eu/include/usb_hal.h +++ b/drivers/staging/rtl8188eu/include/usb_hal.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __USB_HAL_H__ #define __USB_HAL_H__ diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index 4fdc536cba79..220733314f8b 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __USB_OPS_LINUX_H__ #define __USB_OPS_LINUX_H__ diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index 6cb5beca1672..e7c512183619 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef _WIFI_H_ #define _WIFI_H_ diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/rtl8188eu/include/wlan_bssdef.h index 85b99da49a2d..560966cd7dfe 100644 --- a/drivers/staging/rtl8188eu/include/wlan_bssdef.h +++ b/drivers/staging/rtl8188eu/include/wlan_bssdef.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __WLAN_BSSDEF_H__ #define __WLAN_BSSDEF_H__ diff --git a/drivers/staging/rtl8188eu/include/xmit_osdep.h b/drivers/staging/rtl8188eu/include/xmit_osdep.h index 13965f2489db..f96ca6af934d 100644 --- a/drivers/staging/rtl8188eu/include/xmit_osdep.h +++ b/drivers/staging/rtl8188eu/include/xmit_osdep.h @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #ifndef __XMIT_OSDEP_H_ #define __XMIT_OSDEP_H_ diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 911980495fb2..eeb1694d8bbe 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _IOCTL_LINUX_C_ diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c index 08bfa76f4975..bc756267c7fc 100644 --- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 7986e678521a..ae2caff030f1 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _OS_INTFS_C_ diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index f090bef59594..764250b4ba86 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c index d4734baffc8a..0c44914ea3e6 100644 --- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #include #include diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c index 5f3337c281ee..41e1b1d15b81 100644 --- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c +++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #include diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 794cc114348c..8fd608d6027a 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define pr_fmt(fmt) "R8188EU: " fmt diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 0fea338d7313..ce1e1a135f1b 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * ******************************************************************************/ #define _USB_OPS_LINUX_C_ diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c index 1593e280e060..221e2750652e 100644 --- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c @@ -11,11 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * ******************************************************************************/ #define _XMIT_OSDEP_C_ -- GitLab From 17d4591d96d66806d0edd759897699ae50f0e4d4 Mon Sep 17 00:00:00 2001 From: Nicholas Sim Date: Fri, 18 Mar 2016 12:11:07 +0000 Subject: [PATCH 0344/9938] staging: rtl8188eu: remove return at end of void function call Remove unnecessary return statement from last line of void function call Signed-off-by: Nicholas Sim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index da6ccc1a69cc..86108d4bec0a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -2100,7 +2100,6 @@ static void site_survey(struct adapter *padapter) issue_action_BSSCoexistPacket(padapter); issue_action_BSSCoexistPacket(padapter); } - return; } /* collect bss info from Beacon and Probe request/response frames. */ -- GitLab From 7f69e09aba50113c639a2ed1cbc0e033808b16f2 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 19 Mar 2016 16:14:30 +0530 Subject: [PATCH 0345/9938] Staging: rtl8188eu: Hal8188ERateAdaptive: Use x instead of x != NULL. Use x instead of x != NULL. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c b/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c index a108e8032327..201c15b07f9e 100644 --- a/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c +++ b/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c @@ -557,7 +557,7 @@ int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid) u8 WirelessMode = 0xFF; /* invalid value */ u8 max_rate_idx = 0x13; /* MCS7 */ - if (dm_odm->pWirelessMode != NULL) + if (dm_odm->pWirelessMode) WirelessMode = *(dm_odm->pWirelessMode); if (WirelessMode != 0xFF) { -- GitLab From 79146cedc30aba94045114020608dbf951f4c1ff Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 19 Mar 2016 16:16:38 +0530 Subject: [PATCH 0346/9938] Staging: rtl8188eu: hal_intf: Use x instead of x != NULL. Use x instead of x != NULL. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/hal_intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index c49c86ccea76..085f0fbd0c43 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -181,7 +181,7 @@ s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) s32 rtw_hal_init_xmit_priv(struct adapter *adapt) { - if (adapt->HalFunc.init_xmit_priv != NULL) + if (adapt->HalFunc.init_xmit_priv) return adapt->HalFunc.init_xmit_priv(adapt); return _FAIL; } -- GitLab From eec1c50002eafe1c48b550fff10bf3eca83f46ea Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 19 Mar 2016 16:18:47 +0530 Subject: [PATCH 0347/9938] Staging: rtl8188eu: rtl8188e_rxdesc: Use !x instead of x == NULL. Use !x instead of x == NULL. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 4ac6bcf9dada..f110c961df70 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -40,7 +40,7 @@ static void process_link_qual(struct adapter *padapter, struct rx_pkt_attrib *pattrib; struct signal_stat *signal_stat; - if (prframe == NULL || padapter == NULL) + if (!prframe || !padapter) return; pattrib = &prframe->attrib; -- GitLab From f3e80d80e9db08edc3de35996027a657b4a8c8de Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 19 Mar 2016 16:20:25 +0530 Subject: [PATCH 0348/9938] Staging: rtl8188eu: usb_halinit: Use !x instead of x == NULL. Use !x instead of x == NULL. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 358762d3fb45..0c7456f39fb5 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2078,7 +2078,7 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) adapt->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); - if (adapt->HalData == NULL) + if (!adapt->HalData) DBG_88E("cant not alloc memory for HAL DATA\n"); halfunc->hal_power_on = rtl8188eu_InitPowerOn; -- GitLab From 57d8dfed8586427880516536cf0abc3aa19cea78 Mon Sep 17 00:00:00 2001 From: Sam Horlbeck Olsen Date: Mon, 14 Mar 2016 02:09:58 -0500 Subject: [PATCH 0349/9938] staging: dgnc: Add whitespace around OR'd flags ("|") This patch fixes the checkpatch.pl message: CHECK: spaces preferred around that '|' (ctx:VxV) + writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), ^ ^ As per the guidelines for coding style in the kernel, I have updated the digi international driver to include spaces around the OR'd flags; not only is this formatting issue caught by `checkpatch.pl`, in the next `if` block the correct formatting is used, leading to both incorrect and inconsistent code formatting. This patch puts the line in question at 82 characters---while this is over the recommended limit, there are no clear locations to break the line and it barely breaks the cutoff. Signed-off-by: Sam Horlbeck Olsen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_cls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 0ff3139e52b6..5e46ac8dfac5 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -1168,7 +1168,7 @@ static void cls_uart_init(struct channel_t *ch) /* Clear out UART and FIFO */ readb(&ch->ch_cls_uart->txrx); - writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), &ch->ch_cls_uart->isr_fcr); udelay(10); -- GitLab From 3733d3f997b468481e609d47fa35badd47d0bf06 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 18 Mar 2016 13:32:12 -0700 Subject: [PATCH 0350/9938] staging: skein: threefish_block: Use ror64 Use the inline instead of direct code to improve readability and shorten the code a little. Done with perl: $ perl -p -i -e 's/\((\w+) \>\> (\d+)\) \| \(\1 \<\< \(64 \- \2\)\)/ror64(\1, \2)/g' drivers/staging/skein/threefish_block.c Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/skein/threefish_block.c | 2144 +++++++++++------------ 1 file changed, 1072 insertions(+), 1072 deletions(-) diff --git a/drivers/staging/skein/threefish_block.c b/drivers/staging/skein/threefish_block.c index e19ac4368651..a95563fad071 100644 --- a/drivers/staging/skein/threefish_block.c +++ b/drivers/staging/skein/threefish_block.c @@ -512,622 +512,622 @@ void threefish_decrypt_256(struct threefish_key *key_ctx, u64 *input, b2 -= k0 + t1; b3 -= k1 + 18; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k2; b1 -= k3 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k4 + t0; b3 -= k0 + 17; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k1; b1 -= k2 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k3 + t2; b3 -= k4 + 16; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k0; b1 -= k1 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k2 + t1; b3 -= k3 + 15; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k4; b1 -= k0 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k1 + t0; b3 -= k2 + 14; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k3; b1 -= k4 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k0 + t2; b3 -= k1 + 13; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k2; b1 -= k3 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k4 + t1; b3 -= k0 + 12; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k1; b1 -= k2 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k3 + t0; b3 -= k4 + 11; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k0; b1 -= k1 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k2 + t2; b3 -= k3 + 10; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k4; b1 -= k0 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k1 + t1; b3 -= k2 + 9; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k3; b1 -= k4 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k0 + t0; b3 -= k1 + 8; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k2; b1 -= k3 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k4 + t2; b3 -= k0 + 7; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k1; b1 -= k2 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k3 + t1; b3 -= k4 + 6; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k0; b1 -= k1 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k2 + t0; b3 -= k3 + 5; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k4; b1 -= k0 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k1 + t2; b3 -= k2 + 4; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k3; b1 -= k4 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k0 + t1; b3 -= k1 + 3; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k2; b1 -= k3 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k4 + t0; b3 -= k0 + 2; tmp = b3 ^ b0; - b3 = (tmp >> 32) | (tmp << (64 - 32)); + b3 = ror64(tmp, 32); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 32) | (tmp << (64 - 32)); + b1 = ror64(tmp, 32); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 58) | (tmp << (64 - 58)); + b1 = ror64(tmp, 58); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 46) | (tmp << (64 - 46)); + b3 = ror64(tmp, 46); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 12) | (tmp << (64 - 12)); + b1 = ror64(tmp, 12); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b0 -= b1 + k1; b1 -= k2 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 33) | (tmp << (64 - 33)); + b3 = ror64(tmp, 33); b2 -= b3 + k3 + t2; b3 -= k4 + 1; tmp = b3 ^ b0; - b3 = (tmp >> 5) | (tmp << (64 - 5)); + b3 = ror64(tmp, 5); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 37) | (tmp << (64 - 37)); + b1 = ror64(tmp, 37); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b0 -= b1; tmp = b3 ^ b2; - b3 = (tmp >> 40) | (tmp << (64 - 40)); + b3 = ror64(tmp, 40); b2 -= b3; tmp = b3 ^ b0; - b3 = (tmp >> 52) | (tmp << (64 - 52)); + b3 = ror64(tmp, 52); b0 -= b3; tmp = b1 ^ b2; - b1 = (tmp >> 57) | (tmp << (64 - 57)); + b1 = ror64(tmp, 57); b2 -= b1; tmp = b1 ^ b0; - b1 = (tmp >> 14) | (tmp << (64 - 14)); + b1 = ror64(tmp, 14); b0 -= b1 + k0; b1 -= k1 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b2 -= b3 + k2 + t1; b3 -= k3; @@ -2125,1226 +2125,1226 @@ void threefish_decrypt_512(struct threefish_key *key_ctx, u64 *input, b7 -= k7 + 18; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k5 + t0; b7 -= k6 + 17; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k3; b5 -= k4 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k1; b3 -= k2; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k8; b1 -= k0; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k4 + t2; b7 -= k5 + 16; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k2; b5 -= k3 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k0; b3 -= k1; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k7; b1 -= k8; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k3 + t1; b7 -= k4 + 15; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k1; b5 -= k2 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k8; b3 -= k0; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k6; b1 -= k7; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k2 + t0; b7 -= k3 + 14; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k0; b5 -= k1 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k7; b3 -= k8; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k5; b1 -= k6; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k1 + t2; b7 -= k2 + 13; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k8; b5 -= k0 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k6; b3 -= k7; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k4; b1 -= k5; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k0 + t1; b7 -= k1 + 12; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k7; b5 -= k8 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k5; b3 -= k6; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k3; b1 -= k4; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k8 + t0; b7 -= k0 + 11; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k6; b5 -= k7 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k4; b3 -= k5; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k2; b1 -= k3; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k7 + t2; b7 -= k8 + 10; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k5; b5 -= k6 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k3; b3 -= k4; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k1; b1 -= k2; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k6 + t1; b7 -= k7 + 9; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k4; b5 -= k5 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k2; b3 -= k3; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k0; b1 -= k1; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k5 + t0; b7 -= k6 + 8; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k3; b5 -= k4 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k1; b3 -= k2; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k8; b1 -= k0; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k4 + t2; b7 -= k5 + 7; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k2; b5 -= k3 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k0; b3 -= k1; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k7; b1 -= k8; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k3 + t1; b7 -= k4 + 6; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k1; b5 -= k2 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k8; b3 -= k0; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k6; b1 -= k7; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k2 + t0; b7 -= k3 + 5; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k0; b5 -= k1 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k7; b3 -= k8; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k5; b1 -= k6; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k1 + t2; b7 -= k2 + 4; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k8; b5 -= k0 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k6; b3 -= k7; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k4; b1 -= k5; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k0 + t1; b7 -= k1 + 3; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k7; b5 -= k8 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k5; b3 -= k6; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k3; b1 -= k4; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k8 + t0; b7 -= k0 + 2; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k6; b5 -= k7 + t2; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k4; b3 -= k5; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k2; b1 -= k3; tmp = b3 ^ b4; - b3 = (tmp >> 22) | (tmp << (64 - 22)); + b3 = ror64(tmp, 22); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 56) | (tmp << (64 - 56)); + b5 = ror64(tmp, 56); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 35) | (tmp << (64 - 35)); + b7 = ror64(tmp, 35); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 8) | (tmp << (64 - 8)); + b1 = ror64(tmp, 8); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 43) | (tmp << (64 - 43)); + b7 = ror64(tmp, 43); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 39) | (tmp << (64 - 39)); + b5 = ror64(tmp, 39); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 29) | (tmp << (64 - 29)); + b3 = ror64(tmp, 29); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 25) | (tmp << (64 - 25)); + b1 = ror64(tmp, 25); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 17) | (tmp << (64 - 17)); + b3 = ror64(tmp, 17); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 10) | (tmp << (64 - 10)); + b5 = ror64(tmp, 10); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 50) | (tmp << (64 - 50)); + b7 = ror64(tmp, 50); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 24) | (tmp << (64 - 24)); + b7 = ror64(tmp, 24); b6 -= b7 + k7 + t2; b7 -= k8 + 1; tmp = b5 ^ b4; - b5 = (tmp >> 34) | (tmp << (64 - 34)); + b5 = ror64(tmp, 34); b4 -= b5 + k5; b5 -= k6 + t1; tmp = b3 ^ b2; - b3 = (tmp >> 30) | (tmp << (64 - 30)); + b3 = ror64(tmp, 30); b2 -= b3 + k3; b3 -= k4; tmp = b1 ^ b0; - b1 = (tmp >> 39) | (tmp << (64 - 39)); + b1 = ror64(tmp, 39); b0 -= b1 + k1; b1 -= k2; tmp = b3 ^ b4; - b3 = (tmp >> 56) | (tmp << (64 - 56)); + b3 = ror64(tmp, 56); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 54) | (tmp << (64 - 54)); + b5 = ror64(tmp, 54); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 9) | (tmp << (64 - 9)); + b7 = ror64(tmp, 9); b0 -= b7; tmp = b1 ^ b6; - b1 = (tmp >> 44) | (tmp << (64 - 44)); + b1 = ror64(tmp, 44); b6 -= b1; tmp = b7 ^ b2; - b7 = (tmp >> 39) | (tmp << (64 - 39)); + b7 = ror64(tmp, 39); b2 -= b7; tmp = b5 ^ b0; - b5 = (tmp >> 36) | (tmp << (64 - 36)); + b5 = ror64(tmp, 36); b0 -= b5; tmp = b3 ^ b6; - b3 = (tmp >> 49) | (tmp << (64 - 49)); + b3 = ror64(tmp, 49); b6 -= b3; tmp = b1 ^ b4; - b1 = (tmp >> 17) | (tmp << (64 - 17)); + b1 = ror64(tmp, 17); b4 -= b1; tmp = b3 ^ b0; - b3 = (tmp >> 42) | (tmp << (64 - 42)); + b3 = ror64(tmp, 42); b0 -= b3; tmp = b5 ^ b6; - b5 = (tmp >> 14) | (tmp << (64 - 14)); + b5 = ror64(tmp, 14); b6 -= b5; tmp = b7 ^ b4; - b7 = (tmp >> 27) | (tmp << (64 - 27)); + b7 = ror64(tmp, 27); b4 -= b7; tmp = b1 ^ b2; - b1 = (tmp >> 33) | (tmp << (64 - 33)); + b1 = ror64(tmp, 33); b2 -= b1; tmp = b7 ^ b6; - b7 = (tmp >> 37) | (tmp << (64 - 37)); + b7 = ror64(tmp, 37); b6 -= b7 + k6 + t1; b7 -= k7; tmp = b5 ^ b4; - b5 = (tmp >> 19) | (tmp << (64 - 19)); + b5 = ror64(tmp, 19); b4 -= b5 + k4; b5 -= k5 + t0; tmp = b3 ^ b2; - b3 = (tmp >> 36) | (tmp << (64 - 36)); + b3 = ror64(tmp, 36); b2 -= b3 + k2; b3 -= k3; tmp = b1 ^ b0; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b0 -= b1 + k0; b1 -= k1; @@ -5521,2722 +5521,2722 @@ void threefish_decrypt_1024(struct threefish_key *key_ctx, u64 *input, b14 -= k0 + t0; b15 -= k1 + 20; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k16 + t2; b15 -= k0 + 19; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k14; b13 -= k15 + t1; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k12; b11 -= k13; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k10; b9 -= k11; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k8; b7 -= k9; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k6; b5 -= k7; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k4; b3 -= k5; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k2; b1 -= k3; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k15 + t1; b15 -= k16 + 18; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k13; b13 -= k14 + t0; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k11; b11 -= k12; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k9; b9 -= k10; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k7; b7 -= k8; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k5; b5 -= k6; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k3; b3 -= k4; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k1; b1 -= k2; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k14 + t0; b15 -= k15 + 17; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k12; b13 -= k13 + t2; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k10; b11 -= k11; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k8; b9 -= k9; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k6; b7 -= k7; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k4; b5 -= k5; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k2; b3 -= k3; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k0; b1 -= k1; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k13 + t2; b15 -= k14 + 16; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k11; b13 -= k12 + t1; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k9; b11 -= k10; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k7; b9 -= k8; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k5; b7 -= k6; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k3; b5 -= k4; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k1; b3 -= k2; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k16; b1 -= k0; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k12 + t1; b15 -= k13 + 15; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k10; b13 -= k11 + t0; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k8; b11 -= k9; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k6; b9 -= k7; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k4; b7 -= k5; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k2; b5 -= k3; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k0; b3 -= k1; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k15; b1 -= k16; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k11 + t0; b15 -= k12 + 14; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k9; b13 -= k10 + t2; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k7; b11 -= k8; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k5; b9 -= k6; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k3; b7 -= k4; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k1; b5 -= k2; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k16; b3 -= k0; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k14; b1 -= k15; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k10 + t2; b15 -= k11 + 13; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k8; b13 -= k9 + t1; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k6; b11 -= k7; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k4; b9 -= k5; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k2; b7 -= k3; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k0; b5 -= k1; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k15; b3 -= k16; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k13; b1 -= k14; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k9 + t1; b15 -= k10 + 12; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k7; b13 -= k8 + t0; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k5; b11 -= k6; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k3; b9 -= k4; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k1; b7 -= k2; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k16; b5 -= k0; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k14; b3 -= k15; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k12; b1 -= k13; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k8 + t0; b15 -= k9 + 11; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k6; b13 -= k7 + t2; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k4; b11 -= k5; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k2; b9 -= k3; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k0; b7 -= k1; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k15; b5 -= k16; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k13; b3 -= k14; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k11; b1 -= k12; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k7 + t2; b15 -= k8 + 10; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k5; b13 -= k6 + t1; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k3; b11 -= k4; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k1; b9 -= k2; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k16; b7 -= k0; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k14; b5 -= k15; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k12; b3 -= k13; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k10; b1 -= k11; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k6 + t1; b15 -= k7 + 9; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k4; b13 -= k5 + t0; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k2; b11 -= k3; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k0; b9 -= k1; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k15; b7 -= k16; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k13; b5 -= k14; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k11; b3 -= k12; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k9; b1 -= k10; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k5 + t0; b15 -= k6 + 8; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k3; b13 -= k4 + t2; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k1; b11 -= k2; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k16; b9 -= k0; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k14; b7 -= k15; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k12; b5 -= k13; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k10; b3 -= k11; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k8; b1 -= k9; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k4 + t2; b15 -= k5 + 7; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k2; b13 -= k3 + t1; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k0; b11 -= k1; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k15; b9 -= k16; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k13; b7 -= k14; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k11; b5 -= k12; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k9; b3 -= k10; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k7; b1 -= k8; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k3 + t1; b15 -= k4 + 6; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k1; b13 -= k2 + t0; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k16; b11 -= k0; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k14; b9 -= k15; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k12; b7 -= k13; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k10; b5 -= k11; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k8; b3 -= k9; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k6; b1 -= k7; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k2 + t0; b15 -= k3 + 5; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k0; b13 -= k1 + t2; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k15; b11 -= k16; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k13; b9 -= k14; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k11; b7 -= k12; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k9; b5 -= k10; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k7; b3 -= k8; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k5; b1 -= k6; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k1 + t2; b15 -= k2 + 4; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k16; b13 -= k0 + t1; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k14; b11 -= k15; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k12; b9 -= k13; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k10; b7 -= k11; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k8; b5 -= k9; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k6; b3 -= k7; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k4; b1 -= k5; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k0 + t1; b15 -= k1 + 3; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k15; b13 -= k16 + t0; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k13; b11 -= k14; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k11; b9 -= k12; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k9; b7 -= k10; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k7; b5 -= k8; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k5; b3 -= k6; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k3; b1 -= k4; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k16 + t0; b15 -= k0 + 2; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k14; b13 -= k15 + t2; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k12; b11 -= k13; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k10; b9 -= k11; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k8; b7 -= k9; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k6; b5 -= k7; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k4; b3 -= k5; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k2; b1 -= k3; tmp = b7 ^ b12; - b7 = (tmp >> 20) | (tmp << (64 - 20)); + b7 = ror64(tmp, 20); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 37) | (tmp << (64 - 37)); + b3 = ror64(tmp, 37); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 31) | (tmp << (64 - 31)); + b5 = ror64(tmp, 31); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 23) | (tmp << (64 - 23)); + b1 = ror64(tmp, 23); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 52) | (tmp << (64 - 52)); + b9 = ror64(tmp, 52); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 35) | (tmp << (64 - 35)); + b13 = ror64(tmp, 35); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 48) | (tmp << (64 - 48)); + b11 = ror64(tmp, 48); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 9) | (tmp << (64 - 9)); + b15 = ror64(tmp, 9); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 25) | (tmp << (64 - 25)); + b9 = ror64(tmp, 25); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 44) | (tmp << (64 - 44)); + b11 = ror64(tmp, 44); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 42) | (tmp << (64 - 42)); + b13 = ror64(tmp, 42); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 19) | (tmp << (64 - 19)); + b15 = ror64(tmp, 19); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 46) | (tmp << (64 - 46)); + b1 = ror64(tmp, 46); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 47) | (tmp << (64 - 47)); + b3 = ror64(tmp, 47); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 44) | (tmp << (64 - 44)); + b5 = ror64(tmp, 44); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 42) | (tmp << (64 - 42)); + b5 = ror64(tmp, 42); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 53) | (tmp << (64 - 53)); + b3 = ror64(tmp, 53); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 4) | (tmp << (64 - 4)); + b7 = ror64(tmp, 4); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 51) | (tmp << (64 - 51)); + b15 = ror64(tmp, 51); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 56) | (tmp << (64 - 56)); + b11 = ror64(tmp, 56); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 34) | (tmp << (64 - 34)); + b13 = ror64(tmp, 34); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 16) | (tmp << (64 - 16)); + b9 = ror64(tmp, 16); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 30) | (tmp << (64 - 30)); + b15 = ror64(tmp, 30); b14 -= b15 + k15 + t2; b15 -= k16 + 1; tmp = b13 ^ b12; - b13 = (tmp >> 44) | (tmp << (64 - 44)); + b13 = ror64(tmp, 44); b12 -= b13 + k13; b13 -= k14 + t1; tmp = b11 ^ b10; - b11 = (tmp >> 47) | (tmp << (64 - 47)); + b11 = ror64(tmp, 47); b10 -= b11 + k11; b11 -= k12; tmp = b9 ^ b8; - b9 = (tmp >> 12) | (tmp << (64 - 12)); + b9 = ror64(tmp, 12); b8 -= b9 + k9; b9 -= k10; tmp = b7 ^ b6; - b7 = (tmp >> 31) | (tmp << (64 - 31)); + b7 = ror64(tmp, 31); b6 -= b7 + k7; b7 -= k8; tmp = b5 ^ b4; - b5 = (tmp >> 37) | (tmp << (64 - 37)); + b5 = ror64(tmp, 37); b4 -= b5 + k5; b5 -= k6; tmp = b3 ^ b2; - b3 = (tmp >> 9) | (tmp << (64 - 9)); + b3 = ror64(tmp, 9); b2 -= b3 + k3; b3 -= k4; tmp = b1 ^ b0; - b1 = (tmp >> 41) | (tmp << (64 - 41)); + b1 = ror64(tmp, 41); b0 -= b1 + k1; b1 -= k2; tmp = b7 ^ b12; - b7 = (tmp >> 25) | (tmp << (64 - 25)); + b7 = ror64(tmp, 25); b12 -= b7; tmp = b3 ^ b10; - b3 = (tmp >> 16) | (tmp << (64 - 16)); + b3 = ror64(tmp, 16); b10 -= b3; tmp = b5 ^ b8; - b5 = (tmp >> 28) | (tmp << (64 - 28)); + b5 = ror64(tmp, 28); b8 -= b5; tmp = b1 ^ b14; - b1 = (tmp >> 47) | (tmp << (64 - 47)); + b1 = ror64(tmp, 47); b14 -= b1; tmp = b9 ^ b4; - b9 = (tmp >> 41) | (tmp << (64 - 41)); + b9 = ror64(tmp, 41); b4 -= b9; tmp = b13 ^ b6; - b13 = (tmp >> 48) | (tmp << (64 - 48)); + b13 = ror64(tmp, 48); b6 -= b13; tmp = b11 ^ b2; - b11 = (tmp >> 20) | (tmp << (64 - 20)); + b11 = ror64(tmp, 20); b2 -= b11; tmp = b15 ^ b0; - b15 = (tmp >> 5) | (tmp << (64 - 5)); + b15 = ror64(tmp, 5); b0 -= b15; tmp = b9 ^ b10; - b9 = (tmp >> 17) | (tmp << (64 - 17)); + b9 = ror64(tmp, 17); b10 -= b9; tmp = b11 ^ b8; - b11 = (tmp >> 59) | (tmp << (64 - 59)); + b11 = ror64(tmp, 59); b8 -= b11; tmp = b13 ^ b14; - b13 = (tmp >> 41) | (tmp << (64 - 41)); + b13 = ror64(tmp, 41); b14 -= b13; tmp = b15 ^ b12; - b15 = (tmp >> 34) | (tmp << (64 - 34)); + b15 = ror64(tmp, 34); b12 -= b15; tmp = b1 ^ b6; - b1 = (tmp >> 13) | (tmp << (64 - 13)); + b1 = ror64(tmp, 13); b6 -= b1; tmp = b3 ^ b4; - b3 = (tmp >> 51) | (tmp << (64 - 51)); + b3 = ror64(tmp, 51); b4 -= b3; tmp = b5 ^ b2; - b5 = (tmp >> 4) | (tmp << (64 - 4)); + b5 = ror64(tmp, 4); b2 -= b5; tmp = b7 ^ b0; - b7 = (tmp >> 33) | (tmp << (64 - 33)); + b7 = ror64(tmp, 33); b0 -= b7; tmp = b1 ^ b8; - b1 = (tmp >> 52) | (tmp << (64 - 52)); + b1 = ror64(tmp, 52); b8 -= b1; tmp = b5 ^ b14; - b5 = (tmp >> 23) | (tmp << (64 - 23)); + b5 = ror64(tmp, 23); b14 -= b5; tmp = b3 ^ b12; - b3 = (tmp >> 18) | (tmp << (64 - 18)); + b3 = ror64(tmp, 18); b12 -= b3; tmp = b7 ^ b10; - b7 = (tmp >> 49) | (tmp << (64 - 49)); + b7 = ror64(tmp, 49); b10 -= b7; tmp = b15 ^ b4; - b15 = (tmp >> 55) | (tmp << (64 - 55)); + b15 = ror64(tmp, 55); b4 -= b15; tmp = b11 ^ b6; - b11 = (tmp >> 10) | (tmp << (64 - 10)); + b11 = ror64(tmp, 10); b6 -= b11; tmp = b13 ^ b2; - b13 = (tmp >> 19) | (tmp << (64 - 19)); + b13 = ror64(tmp, 19); b2 -= b13; tmp = b9 ^ b0; - b9 = (tmp >> 38) | (tmp << (64 - 38)); + b9 = ror64(tmp, 38); b0 -= b9; tmp = b15 ^ b14; - b15 = (tmp >> 37) | (tmp << (64 - 37)); + b15 = ror64(tmp, 37); b14 -= b15 + k14 + t1; b15 -= k15; tmp = b13 ^ b12; - b13 = (tmp >> 22) | (tmp << (64 - 22)); + b13 = ror64(tmp, 22); b12 -= b13 + k12; b13 -= k13 + t0; tmp = b11 ^ b10; - b11 = (tmp >> 17) | (tmp << (64 - 17)); + b11 = ror64(tmp, 17); b10 -= b11 + k10; b11 -= k11; tmp = b9 ^ b8; - b9 = (tmp >> 8) | (tmp << (64 - 8)); + b9 = ror64(tmp, 8); b8 -= b9 + k8; b9 -= k9; tmp = b7 ^ b6; - b7 = (tmp >> 47) | (tmp << (64 - 47)); + b7 = ror64(tmp, 47); b6 -= b7 + k6; b7 -= k7; tmp = b5 ^ b4; - b5 = (tmp >> 8) | (tmp << (64 - 8)); + b5 = ror64(tmp, 8); b4 -= b5 + k4; b5 -= k5; tmp = b3 ^ b2; - b3 = (tmp >> 13) | (tmp << (64 - 13)); + b3 = ror64(tmp, 13); b2 -= b3 + k2; b3 -= k3; tmp = b1 ^ b0; - b1 = (tmp >> 24) | (tmp << (64 - 24)); + b1 = ror64(tmp, 24); b0 -= b1 + k0; b1 -= k1; -- GitLab From de40f2ab975977375e4620448a2967b69cc3c9cb Mon Sep 17 00:00:00 2001 From: Dilek Uzulmez Date: Sun, 13 Mar 2016 23:31:08 +0200 Subject: [PATCH 0351/9938] Staging: rts5208: Add space around '+' Add space around operator '+'. Problem found using checkpatch.pl CHECK: spaces preferred around that '+' (ctx:VxV) Signed-off-by: Dilek Uzulmez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index a780185a3754..3e75db751c41 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -2691,7 +2691,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) } if ((log_blk < ms_start_idx[seg_no]) || - (log_blk >= ms_start_idx[seg_no+1])) { + (log_blk >= ms_start_idx[seg_no + 1])) { if (!(chip->card_wp & MS_CARD)) { retval = ms_erase_block(chip, phy_blk); if (retval != STATUS_SUCCESS) @@ -3836,7 +3836,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, start_page = (u8)(start_sector & ms_card->page_off); for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) { - if (log_blk < ms_start_idx[seg_no+1]) + if (log_blk < ms_start_idx[seg_no + 1]) break; } @@ -4264,7 +4264,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) memset(buf1, 0, 32); rtsx_stor_get_xfer_buf(buf2, min_t(int, 12, scsi_bufflen(srb)), srb); for (i = 0; i < 8; i++) - buf1[8+i] = buf2[4+i]; + buf1[8 + i] = buf2[4 + i]; retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32); @@ -4399,10 +4399,10 @@ int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_stor_get_xfer_buf(buf, bufflen, srb); for (i = 0; i < 8; i++) - buf[i] = buf[4+i]; + buf[i] = buf[4 + i]; for (i = 0; i < 24; i++) - buf[8+i] = 0; + buf[8 + i] = 0; retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); @@ -4511,10 +4511,10 @@ int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_stor_get_xfer_buf(buf, bufflen, srb); for (i = 0; i < 8; i++) - buf[i] = buf[4+i]; + buf[i] = buf[4 + i]; for (i = 0; i < 24; i++) - buf[8+i] = 0; + buf[8 + i] = 0; retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); -- GitLab From 8aba6c6e9821a83937cccbc7f2292e06e605d340 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 13 Mar 2016 15:48:15 +0530 Subject: [PATCH 0352/9938] Staging: gs_fpgaboot: Fix alignment to match open parenthesis. Fix alignment to match open parenthesis. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/gs_fpgaboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index 7b7c9786c162..de1a9a69993a 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -201,7 +201,7 @@ static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) #endif /* DEBUG_FPGA */ if (!xl_supported_prog_bus_width(bus_bytes)) { pr_err("unsupported program bus width %d\n", - bus_bytes); + bus_bytes); return -1; } @@ -277,7 +277,7 @@ static int gs_set_download_method(struct fpgaimage *fimage) static int init_driver(void) { firmware_pdev = platform_device_register_simple("fpgaboot", -1, - NULL, 0); + NULL, 0); return PTR_ERR_OR_ZERO(firmware_pdev); } -- GitLab From e58463b3415f242bbfad816810eb24454f5a0bb1 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 13 Mar 2016 15:50:03 +0530 Subject: [PATCH 0353/9938] Staging: gs_fpgaboot: Remove unnecessary blank lines. Remove unnecessary blank lines. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/gs_fpgaboot.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index de1a9a69993a..1af0745fa26a 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -93,7 +93,6 @@ static int readlength_bitstream(char *bitdata, int *lendata, int *offset) return 0; } - /* * read first 13 bytes to check bitstream magic number */ @@ -331,7 +330,6 @@ static int gs_fpgaboot(void) kfree(fimage); return -1; - } static int __init gs_fpgaboot_init(void) -- GitLab From c5471a6fa66cffdf5c868a9fbec2e06c6fa057c5 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 13 Mar 2016 15:52:15 +0530 Subject: [PATCH 0354/9938] Staging: gs_fpgaboot: Add space around '+'. Add space around '+'. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/gs_fpgaboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index 1af0745fa26a..a221f261c3d3 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -221,7 +221,7 @@ static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) pr_info("device init done\n"); for (i = 0; i < size; i += bus_bytes) - xl_shift_bytes_out(bus_bytes, bitdata+i); + xl_shift_bytes_out(bus_bytes, bitdata + i); pr_info("program done\n"); -- GitLab From c70aa60bdc12347120b0f3277de2ec6c26988a2e Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 13 Mar 2016 16:41:23 +0530 Subject: [PATCH 0355/9938] Staging: gs_fpgaboot: Replace 'int32_t' with 'int'. Replace 'int32_t' with 'int'. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/gs_fpgaboot.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h index f41f4cc798cc..8cc32555dbf3 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h @@ -51,6 +51,6 @@ struct fpgaimage { char part[MAX_STR]; char date[MAX_STR]; char time[MAX_STR]; - int32_t lendata; + int lendata; char *fpgadata; }; -- GitLab From abe341744574c3fd076e40f053a6fb2f6e549abc Mon Sep 17 00:00:00 2001 From: Dilek Uzulmez Date: Sun, 13 Mar 2016 23:58:08 +0200 Subject: [PATCH 0356/9938] Staging: emxx_udc: Add space around '-' Add space around operator '-'. Problem found using checkpatch.pl CHECK: spaces preferred around that '-' (ctx:VxV) Signed-off-by: Dilek Uzulmez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index e8cacaecf9ad..58e189b7f184 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -418,9 +418,9 @@ static void _nbu2ss_ep_dma_abort(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep) { struct fc_regs *preg = udc->p_regs; - _nbu2ss_bitclr(&preg->EP_DCR[ep->epnum-1].EP_DCR1, DCR1_EPn_REQEN); + _nbu2ss_bitclr(&preg->EP_DCR[ep->epnum - 1].EP_DCR1, DCR1_EPn_REQEN); mdelay(DMA_DISABLE_TIME); /* DCR1_EPn_REQEN Clear */ - _nbu2ss_bitclr(&preg->EP_REGS[ep->epnum-1].EP_DMA_CTRL, EPn_DMA_EN); + _nbu2ss_bitclr(&preg->EP_REGS[ep->epnum - 1].EP_DMA_CTRL, EPn_DMA_EN); } /*-------------------------------------------------------------------------*/ @@ -909,7 +909,7 @@ static int _nbu2ss_epn_out_pio( /* Copy of every four bytes */ for (i = 0; i < iWordLength; i++) { pBuf32->dw = - _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_READ); + _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_READ); pBuf32++; } result = iWordLength * sizeof(u32); @@ -919,7 +919,7 @@ static int _nbu2ss_epn_out_pio( if (data > 0) { /*---------------------------------------------------------*/ /* Copy of fraction byte */ - Temp32.dw = _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_READ); + Temp32.dw = _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_READ); for (i = 0 ; i < data ; i++) pBuf32->byte.DATA[i] = Temp32.byte.DATA[i]; result += data; @@ -1128,7 +1128,7 @@ static int _nbu2ss_epn_in_pio( if (iWordLength > 0) { for (i = 0; i < iWordLength; i++) { _nbu2ss_writel( - &preg->EP_REGS[ep->epnum-1].EP_WRITE + &preg->EP_REGS[ep->epnum - 1].EP_WRITE , pBuf32->dw ); @@ -1290,7 +1290,7 @@ static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) if (ep->epnum > 0) { length = _nbu2ss_readl( - &ep->udc->p_regs->EP_REGS[ep->epnum-1].EP_LEN_DCNT); + &ep->udc->p_regs->EP_REGS[ep->epnum - 1].EP_LEN_DCNT); length &= EPn_LDATA; if (length < ep->ep.maxpacket) @@ -1463,7 +1463,7 @@ static int _nbu2ss_get_ep_stall(struct nbu2ss_udc *udc, u8 ep_adrs) bit_data = EP0_STL; } else { - data = _nbu2ss_readl(&preg->EP_REGS[epnum-1].EP_CONTROL); + data = _nbu2ss_readl(&preg->EP_REGS[epnum - 1].EP_CONTROL); if ((data & EPn_EN) == 0) return -1; @@ -1558,7 +1558,7 @@ static void _nbu2ss_epn_set_stall( ; limit_cnt++) { regdata = _nbu2ss_readl( - &preg->EP_REGS[ep->epnum-1].EP_STATUS); + &preg->EP_REGS[ep->epnum - 1].EP_STATUS); if ((regdata & EPn_IN_DATA) == 0) break; @@ -1983,7 +1983,7 @@ static inline void _nbu2ss_epn_in_int( if (req->zero && ((req->req.actual % ep->ep.maxpacket) == 0)) { status = - _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_STATUS); + _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_STATUS); if ((status & EPn_IN_FULL) == 0) { /*-----------------------------------------*/ @@ -2894,7 +2894,7 @@ static int nbu2ss_ep_fifo_status(struct usb_ep *_ep) data = _nbu2ss_readl(&preg->EP0_LENGTH) & EP0_LDATA; } else { - data = _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_LEN_DCNT) + data = _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_LEN_DCNT) & EPn_LDATA; } -- GitLab From b6d3b4577e49fa8d9a37912ea36ae8449d630b0b Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Fri, 18 Mar 2016 13:56:00 +0530 Subject: [PATCH 0357/9938] Staging: emxx_udc: emxx_udc: Add space around operator. Add space around operator.This patch is found by checkpatch.pl script. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.h | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h index 4a2cc38de7b3..39769e3a801c 100644 --- a/drivers/staging/emxx_udc/emxx_udc.h +++ b/drivers/staging/emxx_udc/emxx_udc.h @@ -97,7 +97,7 @@ #define BIT30 0x40000000 #define BIT31 0x80000000 -#define TEST_FORCE_ENABLE (BIT18+BIT16) +#define TEST_FORCE_ENABLE (BIT18 + BIT16) #define INT_SEL BIT10 #define CONSTFS BIT09 @@ -125,15 +125,15 @@ /*------- (0x0008) USB Address Register */ #define USB_ADDR 0x007F0000 #define SOF_STATUS BIT15 -#define UFRAME (BIT14+BIT13+BIT12) +#define UFRAME (BIT14 + BIT13 + BIT12) #define FRAME 0x000007FF #define USB_ADRS_SHIFT 16 /*------- (0x000C) UTMI Characteristic 1 Register */ -#define SQUSET (BIT07+BIT06+BIT05+BIT04) +#define SQUSET (BIT07 + BIT06 + BIT05 + BIT04) -#define USB_SQUSET (BIT06+BIT05+BIT04) +#define USB_SQUSET (BIT06 + BIT05 + BIT04) /*------- (0x0010) TEST Control Register */ #define FORCEHS BIT02 @@ -196,7 +196,7 @@ #define RSUM_EN BIT01 #define USB_INT_EN_BIT \ - (EP0_EN|SPEED_MODE_EN|USB_RST_EN|SPND_EN|RSUM_EN) + (EP0_EN | SPEED_MODE_EN | USB_RST_EN | SPND_EN | RSUM_EN) /*------- (0x0028) EP0 Control Register */ #define EP0_STGSEL BIT18 @@ -205,9 +205,9 @@ #define EP0_PIDCLR BIT09 #define EP0_BCLR BIT08 #define EP0_DEND BIT07 -#define EP0_DW (BIT06+BIT05) +#define EP0_DW (BIT06 + BIT05) #define EP0_DW4 0 -#define EP0_DW3 (BIT06+BIT05) +#define EP0_DW3 (BIT06 + BIT05) #define EP0_DW2 BIT06 #define EP0_DW1 BIT05 @@ -238,7 +238,7 @@ #define STG_START_INT BIT01 #define SETUP_INT BIT00 -#define EP0_STATUS_RW_BIT (BIT16|BIT15|BIT11|0xFF) +#define EP0_STATUS_RW_BIT (BIT16 | BIT15 | BIT11 | 0xFF) /*------- (0x0030) EP0 Interrupt Enable Register */ #define EP0_PERR_NAK_EN BIT16 @@ -256,7 +256,7 @@ #define SETUP_EN BIT00 #define EP0_INT_EN_BIT \ - (EP0_OUT_OR_EN|EP0_OUT_EN|EP0_IN_EN|STG_END_EN|SETUP_EN) + (EP0_OUT_OR_EN | EP0_OUT_EN | EP0_IN_EN | STG_END_EN | SETUP_EN) /*------- (0x0034) EP0 Length Register */ #define EP0_LDATA 0x0000007F @@ -270,7 +270,7 @@ #define EPn_BUF_SINGLE BIT30 #define EPn_DIR0 BIT26 -#define EPn_MODE (BIT25+BIT24) +#define EPn_MODE (BIT25 + BIT24) #define EPn_BULK 0 #define EPn_INTERRUPT BIT24 #define EPn_ISO BIT25 @@ -283,9 +283,9 @@ #define EPn_BCLR BIT09 #define EPn_CBCLR BIT08 #define EPn_DEND BIT07 -#define EPn_DW (BIT06+BIT05) +#define EPn_DW (BIT06 + BIT05) #define EPn_DW4 0 -#define EPn_DW3 (BIT06+BIT05) +#define EPn_DW3 (BIT06 + BIT05) #define EPn_DW2 BIT06 #define EPn_DW1 BIT05 @@ -324,7 +324,7 @@ #define EPn_IN_EMPTY BIT00 /* R */ #define EPn_INT_EN \ - (EPn_OUT_END_INT|EPn_OUT_INT|EPn_IN_END_INT|EPn_IN_INT) + (EPn_OUT_END_INT | EPn_OUT_INT | EPn_IN_END_INT | EPn_IN_INT) /*------- (0x0048:) EPn Interrupt Enable Register */ #define EPn_OUT_END_EN BIT23 /* RW */ @@ -368,7 +368,7 @@ #define ARBITER_CTR BIT31 /* RW */ #define MCYCLE_RST BIT12 /* RW */ -#define ENDIAN_CTR (BIT09+BIT08) /* RW */ +#define ENDIAN_CTR (BIT09 + BIT08) /* RW */ #define ENDIAN_BYTE_SWAP BIT09 #define ENDIAN_HALF_WORD_SWAP ENDIAN_CTR @@ -376,7 +376,7 @@ #define HTRANS_MODE BIT04 /* RW */ #define WBURST_TYPE BIT02 /* RW */ -#define BURST_TYPE (BIT01+BIT00) /* RW */ +#define BURST_TYPE (BIT01 + BIT00) /* RW */ #define BURST_MAX_16 0 #define BURST_MAX_8 BIT00 #define BURST_MAX_4 BIT01 @@ -412,7 +412,7 @@ #define EPC_RST BIT00 /* RW */ /*------- (0x1014) USBF_EPTEST Register */ -#define LINESTATE (BIT09+BIT08) /* R */ +#define LINESTATE (BIT09 + BIT08) /* R */ #define DM_LEVEL BIT09 /* R */ #define DP_LEVEL BIT08 /* R */ @@ -485,7 +485,7 @@ struct fc_regs { struct ep_regs EP_REGS[REG_EP_NUM]; /* Endpoint Register */ - u8 Reserved220[0x1000-0x220]; /* (0x0220:0x0FFF) Reserved */ + u8 Reserved220[0x1000 - 0x220]; /* (0x0220:0x0FFF) Reserved */ u32 AHBSCTR; /* (0x1000) AHBSCTR */ u32 AHBMCTR; /* (0x1004) AHBMCTR */ @@ -494,16 +494,16 @@ struct fc_regs { u32 EPCTR; /* (0x1010) EPCTR */ u32 USBF_EPTEST; /* (0x1014) USBF_EPTEST */ - u8 Reserved1018[0x20-0x18]; /* (0x1018:0x101F) Reserved */ + u8 Reserved1018[0x20 - 0x18]; /* (0x1018:0x101F) Reserved */ u32 USBSSVER; /* (0x1020) USBSSVER */ u32 USBSSCONF; /* (0x1024) USBSSCONF */ - u8 Reserved1028[0x110-0x28]; /* (0x1028:0x110F) Reserved */ + u8 Reserved1028[0x110 - 0x28]; /* (0x1028:0x110F) Reserved */ struct ep_dcr EP_DCR[REG_EP_NUM]; /* */ - u8 Reserved1200[0x1000-0x200]; /* Reserved */ + u8 Reserved1200[0x1000 - 0x200]; /* Reserved */ } __aligned(32); #define EP0_PACKETSIZE 64 -- GitLab From 364076730cd046ab347f5883cf9193f33adea1da Mon Sep 17 00:00:00 2001 From: Heena Sirwani Date: Mon, 14 Mar 2016 17:23:00 +0530 Subject: [PATCH 0358/9938] staging: media: omap4iss: Match alignment with open parenthesis. The following patch fixes the following checkpatch.pl warning: CHECK: Alignment should match open parenthesis Signed-off-by: Heena Sirwani Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/omap4iss/iss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index c5a5138b3d3b..6ceb4eb00493 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss) } ret = media_create_pad_link(&sensor->entity, 0, input, pad, - flags); + flags); if (ret < 0) goto done; } -- GitLab From 8cd977c3166e448684aba578df6e00dad83d990c Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Fri, 18 Mar 2016 14:56:31 +0530 Subject: [PATCH 0359/9938] Staging: fbtft: fbtft_device: No space is necessary after cast. No space is necessary after cast. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fbtft_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index 241d7c6bebde..e4a355aefb25 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -1254,7 +1254,7 @@ static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len) "%s(len=%d): ", __func__, len); while (len) { - data = *(u16 *) buf; + data = *(u16 *)buf; /* Start writing by pulling down /WR */ gpio_set_value(par->gpio.wr, 0); @@ -1283,7 +1283,7 @@ static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len) gpio_set_value(par->gpio.wr, 1); #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO - prev_data = *(u16 *) buf; + prev_data = *(u16 *)buf; #endif buf += 2; len -= 2; @@ -1436,7 +1436,7 @@ static int __init fbtft_device_init(void) } strncpy(fbtft_device_param_gpios[i].name, p_name, FBTFT_GPIO_NAME_SIZE - 1); - fbtft_device_param_gpios[i++].gpio = (int) val; + fbtft_device_param_gpios[i++].gpio = (int)val; if (i == MAX_GPIOS) { pr_err("gpios parameter: exceeded max array size: %d\n", MAX_GPIOS); -- GitLab From 8d771ea8bf27ae02bf185bd32c67f4d314865945 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Fri, 18 Mar 2016 14:59:34 +0530 Subject: [PATCH 0360/9938] Staging: fbtft: fbtft-io: No space is necessary after cast. No space is necessary after cast.This patch is found by checkpatch.pl script. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fbtft-io.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c index a6f091fb975c..4dcea2e0b3ae 100644 --- a/drivers/staging/fbtft/fbtft-io.c +++ b/drivers/staging/fbtft/fbtft-io.c @@ -141,7 +141,7 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) "%s(len=%d): ", __func__, len); while (len--) { - data = *(u8 *) buf; + data = *(u8 *)buf; /* Start writing by pulling down /WR */ gpio_set_value(par->gpio.wr, 0); @@ -170,7 +170,7 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) gpio_set_value(par->gpio.wr, 1); #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO - prev_data = *(u8 *) buf; + prev_data = *(u8 *)buf; #endif buf++; } @@ -191,7 +191,7 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) "%s(len=%d): ", __func__, len); while (len) { - data = *(u16 *) buf; + data = *(u16 *)buf; /* Start writing by pulling down /WR */ gpio_set_value(par->gpio.wr, 0); @@ -220,7 +220,7 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) gpio_set_value(par->gpio.wr, 1); #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO - prev_data = *(u16 *) buf; + prev_data = *(u16 *)buf; #endif buf += 2; len -= 2; -- GitLab From 60abe3510e55cbd74a1ed163fed75a25cae8d45c Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Fri, 18 Mar 2016 15:02:41 +0530 Subject: [PATCH 0361/9938] Staging: fbtft: fb_agm1264k-fl: No space is necessary after cast. No space is necessary after cast.This problem is found by checkpatch.pl script. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_agm1264k-fl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index ba9fc444b848..82b46cd27ca7 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -414,7 +414,7 @@ static int write(struct fbtft_par *par, void *buf, size_t len) while (len--) { u8 i, data; - data = *(u8 *) buf++; + data = *(u8 *)buf++; /* set data bus */ for (i = 0; i < 8; ++i) -- GitLab From f3fe438db281cc2d115843d27c7e196bf7404d3c Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 20 Mar 2016 16:47:28 +0530 Subject: [PATCH 0362/9938] Staging: i4l: pcbit: layer2: Add parentheses to complex macro. Add parentheses to complex macro. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/layer2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/i4l/pcbit/layer2.h b/drivers/staging/i4l/pcbit/layer2.h index be1327bc162a..6b9063e388cd 100644 --- a/drivers/staging/i4l/pcbit/layer2.h +++ b/drivers/staging/i4l/pcbit/layer2.h @@ -109,7 +109,7 @@ #define SCHED_READ 0x01 #define SCHED_WRITE 0x02 -#define SET_RUN_TIMEOUT 2 * HZ /* 2 seconds */ +#define SET_RUN_TIMEOUT (2 * HZ) /* 2 seconds */ struct frame_buf { ulong msg; -- GitLab From f2cef3f2db6647975bb7e8a83fcdfc52146b55c0 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 20 Mar 2016 16:49:02 +0530 Subject: [PATCH 0363/9938] Staging: i4l: pcbit: edss1: Use !x instead of x == NULL. Use !x instead of x == NULL. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/edss1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/i4l/pcbit/edss1.c b/drivers/staging/i4l/pcbit/edss1.c index b2262ba6f0c9..e72c16420712 100644 --- a/drivers/staging/i4l/pcbit/edss1.c +++ b/drivers/staging/i4l/pcbit/edss1.c @@ -254,7 +254,7 @@ static void pcbit_fsm_timer(unsigned long data) dev = chan2dev(chan); - if (dev == NULL) { + if (!dev) { printk(KERN_WARNING "pcbit: timer for unknown device\n"); return; } -- GitLab From 3e735d1e3a9a045cbd2610ff33e9fd355d09e632 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 20 Mar 2016 16:50:49 +0530 Subject: [PATCH 0364/9938] Staging: i4l: pcbit: drv: Do not initialise statics to 0. Do not initialise statics to 0. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/i4l/pcbit/drv.c b/drivers/staging/i4l/pcbit/drv.c index 4172e22ae7ed..c79ee84b56db 100644 --- a/drivers/staging/i4l/pcbit/drv.c +++ b/drivers/staging/i4l/pcbit/drv.c @@ -699,8 +699,8 @@ void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg, */ static char statbuf[STATBUF_LEN]; -static int stat_st = 0; -static int stat_end = 0; +static int stat_st; +static int stat_end; static int pcbit_stat(u_char __user *buf, int len, int driver, int channel) { -- GitLab From 8c9a093e1cec027bec070134fd56d9ae98b080a8 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sun, 20 Mar 2016 16:52:35 +0530 Subject: [PATCH 0365/9938] Staging: i4l: pcbit: capi: Add parentheses to complex macro. Add parentheses to complex macro. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/capi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/i4l/pcbit/capi.h b/drivers/staging/i4l/pcbit/capi.h index 635f63476944..6f6f4dd0714e 100644 --- a/drivers/staging/i4l/pcbit/capi.h +++ b/drivers/staging/i4l/pcbit/capi.h @@ -17,7 +17,7 @@ #define REQ_DISPLAY 0x04 #define REQ_USER_TO_USER 0x08 -#define AppInfoMask REQ_CAUSE | REQ_DISPLAY | REQ_USER_TO_USER +#define AppInfoMask (REQ_CAUSE | REQ_DISPLAY | REQ_USER_TO_USER) /* Connection Setup */ extern int capi_conn_req(const char *calledPN, struct sk_buff **buf, -- GitLab From 5c722af4c454c881349fec4f8ee3a4ee0a2a77ed Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Fri, 18 Mar 2016 08:45:08 +0530 Subject: [PATCH 0366/9938] Staging: i4l: pcbit: drv: Remove unnecessary semicolon. Remove unnecessary semicolon.This issue is detected by coccinelle script. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i4l/pcbit/drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/i4l/pcbit/drv.c b/drivers/staging/i4l/pcbit/drv.c index c79ee84b56db..c5270e229efb 100644 --- a/drivers/staging/i4l/pcbit/drv.c +++ b/drivers/staging/i4l/pcbit/drv.c @@ -284,7 +284,7 @@ static int pcbit_command(isdn_ctrl *ctl) default: printk(KERN_DEBUG "pcbit_command: unknown command\n"); break; - }; + } return 0; } @@ -968,7 +968,7 @@ static int pcbit_ioctl(isdn_ctrl *ctl) default: printk("error: unknown ioctl\n"); break; - }; + } return 0; } -- GitLab From bb94df96f7a260ff0d4384719fd8cac477e4c31d Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 18:06:03 +0530 Subject: [PATCH 0367/9938] Staging: lustre: lib-move: Remove unnecessary space after cast. Remove unnecessary space after cast. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/lib-move.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 0009a8de77d5..44e2bd6dba63 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -407,7 +407,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, LASSERT(niov > 0); LASSERT(nkiov > 0); this_nob = min(iov->iov_len - iovoffset, - (__kernel_size_t) kiov->kiov_len - kiovoffset); + (__kernel_size_t)kiov->kiov_len - kiovoffset); this_nob = min(this_nob, nob); if (!addr) @@ -477,7 +477,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, do { LASSERT(nkiov > 0); LASSERT(niov > 0); - this_nob = min((__kernel_size_t) kiov->kiov_len - kiovoffset, + this_nob = min((__kernel_size_t)kiov->kiov_len - kiovoffset, iov->iov_len - iovoffset); this_nob = min(this_nob, nob); @@ -996,7 +996,7 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) LASSERT(msg2->msg_txpeer->lp_ni == ni); LASSERT(msg2->msg_tx_delayed); - (void) lnet_post_send_locked(msg2, 1); + (void)lnet_post_send_locked(msg2, 1); } } @@ -1019,7 +1019,7 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) LASSERT(msg2->msg_txpeer == txpeer); LASSERT(msg2->msg_tx_delayed); - (void) lnet_post_send_locked(msg2, 1); + (void)lnet_post_send_locked(msg2, 1); } } @@ -1142,7 +1142,7 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) lnet_msg_t, msg_list); list_del(&msg2->msg_list); - (void) lnet_post_routed_recv_locked(msg2, 1); + (void)lnet_post_routed_recv_locked(msg2, 1); } } if (rxpeer) { -- GitLab From 4f296211583ade450f25a14be0a669a309ea6303 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 19:15:24 +0530 Subject: [PATCH 0368/9938] Staging: lustre: socklnd_lib: Remove return statement from void function. Remove return statement from void function. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 3e1f24e77f64..acebc6fe0dbe 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -675,7 +675,6 @@ ksocknal_lib_set_callback(struct socket *sock, ksock_conn_t *conn) sock->sk->sk_user_data = conn; sock->sk->sk_data_ready = ksocknal_data_ready; sock->sk->sk_write_space = ksocknal_write_space; - return; } void @@ -695,8 +694,6 @@ ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn) * sk_user_data is NULL. */ sock->sk->sk_user_data = NULL; - - return ; } int -- GitLab From 4ec4595272240b21365b6563c24b1e22570c3880 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 19:16:48 +0530 Subject: [PATCH 0369/9938] Staging: lustre: socklnd: Remove return statement from void function. Remove return statement from void function. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index cca7b2f7f1a7..406c0e7a57b9 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -2582,7 +2582,6 @@ ksocknal_debug_peerhash(lnet_ni_t *ni) } read_unlock(&ksocknal_data.ksnd_global_lock); - return; } void -- GitLab From 9899cb68c6c23d58b27035c237b2d425f4c6133c Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 19:51:12 +0530 Subject: [PATCH 0370/9938] Staging: lustre: rpc: Use sizeof type *pointer instead of sizeof type. Use sizeof type *pointer instead of sizeof type. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index ab8ba3724954..5d8908d258df 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -256,7 +256,7 @@ srpc_service_init(struct srpc_service *svc) svc->sv_shuttingdown = 0; svc->sv_cpt_data = cfs_percpt_alloc(lnet_cpt_table(), - sizeof(struct srpc_service_cd)); + sizeof(*svc->sv_cpt_data)); if (!svc->sv_cpt_data) return -ENOMEM; -- GitLab From 017168b5fd913df50a80b65b9c086066f1484a13 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 19:52:44 +0530 Subject: [PATCH 0371/9938] Staging: lustre: o2iblnd: Use sizeof type *pointer instead of sizeof type. Use sizeof type *pointer instead of sizeof type. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 0d32e6541a3f..89f939092af4 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -1968,7 +1968,7 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) */ net->ibn_fmr_ps = cfs_percpt_alloc(lnet_cpt_table(), - sizeof(kib_fmr_poolset_t)); + sizeof(*net->ibn_fmr_ps)); if (!net->ibn_fmr_ps) { CERROR("Failed to allocate FMR pool array\n"); rc = -ENOMEM; @@ -1992,7 +1992,7 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) create_tx_pool: net->ibn_tx_ps = cfs_percpt_alloc(lnet_cpt_table(), - sizeof(kib_tx_poolset_t)); + sizeof(*net->ibn_tx_ps)); if (!net->ibn_tx_ps) { CERROR("Failed to allocate tx pool array\n"); rc = -ENOMEM; -- GitLab From a6634f83402c5c8baf636998143f956feecfa770 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Mon, 21 Mar 2016 15:39:53 -0700 Subject: [PATCH 0372/9938] staging: iio: use kernel preferred block commenting style Use * on subsequent lines and trailing */ on a separate line in block comments. Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7192.c | 20 +++++++++---------- .../staging/iio/impedance-analyzer/ad5933.c | 5 +++-- drivers/staging/iio/meter/ade7753.c | 3 ++- drivers/staging/iio/meter/ade7754.c | 3 ++- drivers/staging/iio/meter/ade7758_core.c | 3 ++- drivers/staging/iio/meter/ade7759.c | 3 ++- drivers/staging/iio/meter/ade7854.c | 3 ++- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index f843f19cf675..f91468e20b84 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -35,10 +35,10 @@ #define AD7192_REG_DATA 3 /* Data Register (RO, 24/32-bit) */ #define AD7192_REG_ID 4 /* ID Register (RO, 8-bit) */ #define AD7192_REG_GPOCON 5 /* GPOCON Register (RO, 8-bit) */ -#define AD7192_REG_OFFSET 6 /* Offset Register (RW, 16-bit - * (AD7792)/24-bit (AD7192)) */ -#define AD7192_REG_FULLSALE 7 /* Full-Scale Register - * (RW, 16-bit (AD7792)/24-bit (AD7192)) */ +#define AD7192_REG_OFFSET 6 /* Offset Register (RW, 16-bit */ + /* (AD7792)/24-bit (AD7192)) */ +#define AD7192_REG_FULLSALE 7 /* Full-Scale Register */ + /* (RW, 16-bit (AD7792)/24-bit (AD7192)) */ /* Communications Register Bit Designations (AD7192_REG_COMM) */ #define AD7192_COMM_WEN BIT(7) /* Write Enable */ @@ -80,13 +80,13 @@ #define AD7192_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */ /* Mode Register: AD7192_MODE_CLKSRC options */ -#define AD7192_CLK_EXT_MCLK1_2 0 /* External 4.92 MHz Clock connected - * from MCLK1 to MCLK2 */ +#define AD7192_CLK_EXT_MCLK1_2 0 /* External 4.92 MHz Clock connected*/ + /* from MCLK1 to MCLK2 */ #define AD7192_CLK_EXT_MCLK2 1 /* External Clock applied to MCLK2 */ -#define AD7192_CLK_INT 2 /* Internal 4.92 MHz Clock not - * available at the MCLK2 pin */ -#define AD7192_CLK_INT_CO 3 /* Internal 4.92 MHz Clock available - * at the MCLK2 pin */ +#define AD7192_CLK_INT 2 /* Internal 4.92 MHz Clock not */ + /* available at the MCLK2 pin */ +#define AD7192_CLK_INT_CO 3 /* Internal 4.92 MHz Clock available*/ + /* at the MCLK2 pin */ /* Configuration Register Bit Designations (AD7192_REG_CONF) */ diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 620b33a61a2d..e6fdb3d54e25 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -691,8 +691,9 @@ static void ad5933_work(struct work_struct *work) } if (status & AD5933_STAT_SWEEP_DONE) { - /* last sample received - power down do nothing until - * the ring enable is toggled */ + /* last sample received - power down do + * nothing until the ring enable is toggled + */ ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); } else { /* we just received a valid datum, move on to the next */ diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index b0bc99a958c5..4b5f05fdadcd 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -333,7 +333,8 @@ static int ade7753_set_irq(struct device *dev, bool enable) if (enable) irqen |= BIT(3); /* Enables an interrupt when a data is - present in the waveform register */ + * present in the waveform register + */ else irqen &= ~BIT(3); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index fed11804d548..c46bef641613 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -351,7 +351,8 @@ static int ade7754_set_irq(struct device *dev, bool enable) if (enable) irqen |= BIT(14); /* Enables an interrupt when a data is - present in the waveform register */ + * present in the waveform register + */ else irqen &= ~BIT(14); diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 310296573e52..ebb8a1993303 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -413,7 +413,8 @@ int ade7758_set_irq(struct device *dev, bool enable) if (enable) irqen |= BIT(16); /* Enables an interrupt when a data is - present in the waveform register */ + * present in the waveform register + */ else irqen &= ~BIT(16); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index c14892db7e4c..80144d40d9ca 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -289,7 +289,8 @@ static int ade7759_set_irq(struct device *dev, bool enable) if (enable) irqen |= BIT(3); /* Enables an interrupt when a data is - present in the waveform register */ + * present in the waveform register + */ else irqen &= ~BIT(3); diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index 9e439af7100d..75e8685e6df2 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -421,7 +421,8 @@ static int ade7854_set_irq(struct device *dev, bool enable) if (enable) irqen |= BIT(17); /* 1: interrupt enabled when all periodical - (at 8 kHz rate) DSP computations finish. */ + * (at 8 kHz rate) DSP computations finish. + */ else irqen &= ~BIT(17); -- GitLab From 968b4e6bd3b00c3c05715f916e27439ff71c737d Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 19 Mar 2016 11:44:05 +0530 Subject: [PATCH 0373/9938] Staging: netlogic: Remove & from function name. Remove & from function name,when function name passed as an argument to another function. Function name is used as pointer without &. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/netlogic/xlr_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index aa1cdf602cf6..99445d0fcf9c 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -850,7 +850,7 @@ static int xlr_mii_probe(struct xlr_net_priv *priv) /* Attach MAC to PHY */ phydev = phy_connect(priv->ndev, phydev_name(phydev), - &xlr_gmac_link_adjust, priv->nd->phy_interface); + xlr_gmac_link_adjust, priv->nd->phy_interface); if (IS_ERR(phydev)) { pr_err("could not attach PHY\n"); -- GitLab From 6c1c9f9d5a079f3139d4dd34836da6eb49cbd5d4 Mon Sep 17 00:00:00 2001 From: Ben Marsh Date: Mon, 14 Mar 2016 17:40:20 +0100 Subject: [PATCH 0374/9938] Staging: rtl8192u: remove extra blank lines. This patch removes blank lines in r8192U_wx.c that were flagged by checkpatch.pl Signed-off-by: Ben Marsh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_wx.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c index f828e6441f2d..837704de3ea4 100644 --- a/drivers/staging/rtl8192u/r8192U_wx.c +++ b/drivers/staging/rtl8192u/r8192U_wx.c @@ -30,7 +30,6 @@ static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000, 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000}; - #ifndef ENETDOWN #define ENETDOWN 1 #endif @@ -44,7 +43,6 @@ static int r8192_wx_get_freq(struct net_device *dev, return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b); } - static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a, union iwreq_data *wrqu, char *b) { @@ -53,8 +51,6 @@ static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a, return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b); } - - static int r8192_wx_get_rate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -64,8 +60,6 @@ static int r8192_wx_get_rate(struct net_device *dev, return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra); } - - static int r8192_wx_set_rate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -82,7 +76,6 @@ static int r8192_wx_set_rate(struct net_device *dev, return ret; } - static int r8192_wx_set_rts(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -148,7 +141,6 @@ static int r8192_wx_force_reset(struct net_device *dev, } - static int r8192_wx_set_rawtx(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -301,7 +293,6 @@ static int rtl8180_wx_get_range(struct net_device *dev, /* range->min_r_time; */ /* Minimal retry lifetime */ /* range->max_r_time; */ /* Maximal retry lifetime */ - for (i = 0, val = 0; i < 14; i++) { /* Include only legal frequencies for some countries */ @@ -326,7 +317,6 @@ static int rtl8180_wx_get_range(struct net_device *dev, return 0; } - static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, union iwreq_data *wrqu, char *b) { @@ -396,9 +386,6 @@ static int r8192_wx_set_essid(struct net_device *dev, return ret; } - - - static int r8192_wx_get_essid(struct net_device *dev, struct iw_request_info *a, union iwreq_data *wrqu, char *b) @@ -415,7 +402,6 @@ static int r8192_wx_get_essid(struct net_device *dev, return ret; } - static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a, union iwreq_data *wrqu, char *b) { @@ -439,7 +425,6 @@ static int r8192_wx_get_name(struct net_device *dev, return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); } - static int r8192_wx_set_frag(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -493,7 +478,6 @@ static int r8192_wx_set_wap(struct net_device *dev, } - static int r8192_wx_get_wap(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -503,7 +487,6 @@ static int r8192_wx_get_wap(struct net_device *dev, return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra); } - static int r8192_wx_get_enc(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *key) @@ -695,7 +678,6 @@ static int r8192_wx_get_retry(struct net_device *dev, wrqu->retry.value = priv->retry_data; } - return 0; } @@ -711,7 +693,6 @@ static int r8192_wx_get_sens(struct net_device *dev, return 0; } - static int r8192_wx_set_sens(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -862,7 +843,6 @@ static int dummy(struct net_device *dev, struct iw_request_info *a, return -1; } - static iw_handler r8192_wx_handlers[] = { NULL, /* SIOCSIWCOMMIT */ r8192_wx_get_name, /* SIOCGIWNAME */ @@ -949,7 +929,6 @@ static const struct iw_priv_args r8192_private_args[] = { }; - static iw_handler r8192_private_handler[] = { r8192_wx_set_crcmon, r8192_wx_set_scan_type, @@ -985,7 +964,6 @@ struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) return wstats; } - struct iw_handler_def r8192_wx_handlers_def = { .standard = r8192_wx_handlers, .num_standard = ARRAY_SIZE(r8192_wx_handlers), -- GitLab From 46347b3e096c649adcbe902798eb31c47ad5637c Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Fri, 18 Mar 2016 09:15:45 +0530 Subject: [PATCH 0375/9938] Staging: rtl8192u: Remove unnecessary semicolon. Remove unnecessary semicolon.This issue is found by coccinelle script. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8190_rtl8256.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c index 5c3bb3be2720..d733fb2ade91 100644 --- a/drivers/staging/rtl8192u/r8190_rtl8256.c +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -194,7 +194,7 @@ void phy_RF8256_Config_ParaFile(struct net_device *dev) break; } - /*----Restore RFENV control type----*/; + /*----Restore RFENV control type----*/ switch (eRFPath) { case RF90_PATH_A: case RF90_PATH_C: -- GitLab From 58493d8e405e6ebe530d04f97bfe32724608c89e Mon Sep 17 00:00:00 2001 From: Nik Nyby Date: Sun, 20 Mar 2016 15:46:35 -0400 Subject: [PATCH 0376/9938] staging: rtl8192u: fix typo in debug message This fixes a mis-spelled word in a few debug statements. Signed-off-by: Nik Nyby Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 2 +- drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index f18fc0b6775b..051c2be842d0 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -746,7 +746,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, // Indicate packets if(index>REORDER_WIN_SIZE){ - IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n"); + IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"); kfree(prxbIndicateArray); return; } diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index 148d0d45547b..6033502eff3d 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -75,7 +75,7 @@ static void RxPktPendingTimeout(unsigned long data) // Indicate packets if(index > REORDER_WIN_SIZE){ - IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n"); + IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"); spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); return; } -- GitLab From 13c1cce614d339ab369b9c2b10bc2a2d49ad3f6b Mon Sep 17 00:00:00 2001 From: Edward Lipinsky Date: Sat, 12 Mar 2016 11:45:44 -0800 Subject: [PATCH 0377/9938] staging: rtl8723au: Fix line longer than 80 columns. This patch fixes the checkpatch.pl warning: WARNING: line over 80 characters Signed-off-by: Edward Lipinsky Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/core/rtw_ap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c index f68e2770255d..aad686da3cf0 100644 --- a/drivers/staging/rtl8723au/core/rtw_ap.c +++ b/drivers/staging/rtl8723au/core/rtw_ap.c @@ -1719,7 +1719,8 @@ void stop_ap_mode23a(struct rtw_adapter *padapter) } spin_unlock_bh(&pacl_node_q->lock); - DBG_8723A("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num); + DBG_8723A("%s, free acl_node_queue, num =%d\n", + __func__, pacl_list->num); rtw_sta_flush23a(padapter); -- GitLab From 299ccc8a07b79199b79bcfb3f701866f10b42063 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Fri, 18 Mar 2016 09:26:02 +0530 Subject: [PATCH 0378/9938] Staging: rtl8723au: rtl8723a_rf6052: Remove unnecessary semicolon. Remove unnecessary semicolon. Coccinelle sementic patch as follows: @r_case@ position p; @@ switch (...) { case ...: ...;@p } @r_default@ position p; @@ switch (...) { default: ...;@p } @r1@ statement S; position p1; position p != {r_case.p, r_default.p}; identifier label; @@ ( label:; | S@p1;@p ) Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c b/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c index ce0d8d894787..24c0ff3d82bc 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c @@ -465,7 +465,7 @@ static int phy_RF6052_Config_ParaFile(struct rtw_adapter *Adapter) break; } - /*----Restore RFENV control type----*/; + /*----Restore RFENV control type----*/ switch (eRFPath) { case RF_PATH_A: PHY_SetBBReg(Adapter, pPhyReg->rfintfs, -- GitLab From 9555ece315c7809f32ca5bdb8eb19d8160b91517 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Sat, 19 Mar 2016 10:47:47 +0530 Subject: [PATCH 0379/9938] Staging: rtl8723au: Remove unnecessary return statement. Remove unnecessary return statement. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c index e81301fcb01d..1ea0af499ce9 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c @@ -1175,8 +1175,6 @@ int InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary) /* Let last entry point to the start entry of ring buffer */ status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy); - if (status != _SUCCESS) - return status; return status; } -- GitLab From d08073d92463820bcebf8594279c635a793f6772 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Fri, 18 Mar 2016 23:26:18 +0530 Subject: [PATCH 0380/9938] staging: rtl8712: rtl871x_ioctl_set: Remove unused macro Removed Unused macro IS_MAC_ADDRESS_BROADCAST. Grep'd to find occurences. Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_set.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index f772675ae9cd..56760cda8e89 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -34,12 +34,6 @@ #include "usb_osintf.h" #include "usb_ops.h" -#define IS_MAC_ADDRESS_BROADCAST(addr) \ -( \ - ((addr[0] == 0xff) && (addr[1] == 0xff) && \ - (addr[2] == 0xff) && (addr[3] == 0xff) && \ - (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \ -) static u8 validate_ssid(struct ndis_802_11_ssid *ssid) { -- GitLab From b7af4e6cc7f8f1b69e20ebd25cb633e30de4799e Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Mon, 21 Mar 2016 01:23:17 +0530 Subject: [PATCH 0381/9938] staging: rtl8712: os_intfs: Change form of NULL comparisons Change null comparisons of the form x == NULL to !x. This was done using Coccinelle. @@ expression e; @@ - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index ab19112eae13..57211f7e68a5 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -389,7 +389,7 @@ static int netdev_open(struct net_device *pnetdev) padapter->bup = true; if (rtl871x_hal_init(padapter) != _SUCCESS) goto netdev_open_error; - if (r8712_initmac == NULL) + if (!r8712_initmac) /* Use the mac address stored in the Efuse */ memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN); @@ -413,7 +413,7 @@ static int netdev_open(struct net_device *pnetdev) } if (start_drv_threads(padapter) != _SUCCESS) goto netdev_open_error; - if (padapter->dvobjpriv.inirp_init == NULL) + if (!padapter->dvobjpriv.inirp_init) goto netdev_open_error; else padapter->dvobjpriv.inirp_init(padapter); -- GitLab From ddf6451ff98c5139c63639db826df540173db2d5 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Mon, 21 Mar 2016 02:08:36 +0530 Subject: [PATCH 0382/9938] staging: rtl8712: usb_ops_linux: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/usb_ops_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index 454cdf6c7fa1..6f12345709c2 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -504,7 +504,7 @@ int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value, u8 *palloc_buf, *pIo_buf; palloc_buf = kmalloc((u32)len + 16, GFP_ATOMIC); - if (palloc_buf == NULL) + if (!palloc_buf) return -ENOMEM; pIo_buf = palloc_buf + 16 - ((addr_t)(palloc_buf) & 0x0f); if (requesttype == 0x01) { -- GitLab From 670e3fef68b82a0d43200fcbb3588c7ffa46ca08 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Mon, 21 Mar 2016 02:09:17 +0530 Subject: [PATCH 0383/9938] staging: rtl8712: rtl871x_mlme: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_mlme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 62d4ae85af15..f8b1c8960192 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -1205,7 +1205,7 @@ sint r8712_set_auth(struct _adapter *adapter, return _FAIL; psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC); - if (psetauthparm == NULL) { + if (!psetauthparm) { kfree(pcmd); return _FAIL; } @@ -1234,7 +1234,7 @@ sint r8712_set_key(struct _adapter *adapter, if (!pcmd) return _FAIL; psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC); - if (psetkeyparm == NULL) { + if (!psetkeyparm) { ret = _FAIL; goto err_free_cmd; } -- GitLab From b1d055005519985784f9a613df81b8dd928c0090 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Mon, 21 Mar 2016 02:09:49 +0530 Subject: [PATCH 0384/9938] staging: rtl8712: rtl871x_cmd: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_cmd.c | 80 +++++++++++++-------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index 86136cc73672..aed03cfbb1ba 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -225,10 +225,10 @@ u8 r8712_sitesurvey_cmd(struct _adapter *padapter, struct mlme_priv *pmlmepriv = &padapter->mlmepriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC); - if (psurveyPara == NULL) { + if (!psurveyPara) { kfree(ph2c); return _FAIL; } @@ -258,10 +258,10 @@ u8 r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC); - if (pbsetdataratepara == NULL) { + if (!pbsetdataratepara) { kfree(ph2c); return _FAIL; } @@ -280,10 +280,10 @@ u8 r8712_set_chplan_cmd(struct _adapter *padapter, int chplan) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC); - if (psetchplanpara == NULL) { + if (!psetchplanpara) { kfree(ph2c); return _FAIL; } @@ -301,10 +301,10 @@ u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; pssetbasicratepara = kmalloc(sizeof(*pssetbasicratepara), GFP_ATOMIC); - if (pssetbasicratepara == NULL) { + if (!pssetbasicratepara) { kfree(ph2c); return _FAIL; } @@ -322,10 +322,10 @@ u8 r8712_setfwdig_cmd(struct _adapter *padapter, u8 type) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC); - if (pwriteptmparm == NULL) { + if (!pwriteptmparm) { kfree(ph2c); return _FAIL; } @@ -342,10 +342,10 @@ u8 r8712_setfwra_cmd(struct _adapter *padapter, u8 type) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC); - if (pwriteptmparm == NULL) { + if (!pwriteptmparm) { kfree(ph2c); return _FAIL; } @@ -362,10 +362,10 @@ u8 r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC); - if (pwriterfparm == NULL) { + if (!pwriterfparm) { kfree(ph2c); return _FAIL; } @@ -383,10 +383,10 @@ u8 r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC); - if (prdrfparm == NULL) { + if (!prdrfparm) { kfree(ph2c); return _FAIL; } @@ -427,7 +427,7 @@ u8 r8712_createbss_cmd(struct _adapter *padapter) padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); - if (pcmd == NULL) + if (!pcmd) return _FAIL; INIT_LIST_HEAD(&pcmd->list); pcmd->cmdcode = _CreateBss_CMD_; @@ -457,7 +457,7 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); - if (pcmd == NULL) + if (!pcmd) return _FAIL; /* for hidden ap to set fw_state here */ @@ -587,10 +587,10 @@ u8 r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */ struct cmd_priv *pcmdpriv = &padapter->cmdpriv; pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC); - if (pdisconnect_cmd == NULL) + if (!pdisconnect_cmd) return _FAIL; pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC); - if (pdisconnect == NULL) { + if (!pdisconnect) { kfree(pdisconnect_cmd); return _FAIL; } @@ -609,10 +609,10 @@ u8 r8712_setopmode_cmd(struct _adapter *padapter, struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC); - if (psetop == NULL) { + if (!psetop) { kfree(ph2c); return _FAIL; } @@ -633,15 +633,15 @@ u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key) struct sta_info *sta = (struct sta_info *)psta; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC); - if (psetstakey_para == NULL) { + if (!psetstakey_para) { kfree(ph2c); return _FAIL; } psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC); - if (psetstakey_rsp == NULL) { + if (!psetstakey_rsp) { kfree(ph2c); kfree(psetstakey_para); return _FAIL; @@ -673,10 +673,10 @@ u8 r8712_setrfintfs_cmd(struct _adapter *padapter, u8 mode) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psetrfintfsparm = kmalloc(sizeof(*psetrfintfsparm), GFP_ATOMIC); - if (psetrfintfsparm == NULL) { + if (!psetrfintfsparm) { kfree(ph2c); return _FAIL; } @@ -695,10 +695,10 @@ u8 r8712_setrttbl_cmd(struct _adapter *padapter, struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psetrttblparm = kmalloc(sizeof(*psetrttblparm), GFP_ATOMIC); - if (psetrttblparm == NULL) { + if (!psetrttblparm) { kfree(ph2c); return _FAIL; } @@ -716,10 +716,10 @@ u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr) struct SetMacAddr_param *psetMacAddr_para; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC); - if (psetMacAddr_para == NULL) { + if (!psetMacAddr_para) { kfree(ph2c); return _FAIL; } @@ -738,15 +738,15 @@ u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr) struct set_assocsta_rsp *psetassocsta_rsp = NULL; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psetassocsta_para = kmalloc(sizeof(*psetassocsta_para), GFP_ATOMIC); - if (psetassocsta_para == NULL) { + if (!psetassocsta_para) { kfree(ph2c); return _FAIL; } psetassocsta_rsp = kmalloc(sizeof(*psetassocsta_rsp), GFP_ATOMIC); - if (psetassocsta_rsp == NULL) { + if (!psetassocsta_rsp) { kfree(ph2c); kfree(psetassocsta_para); return _FAIL; @@ -766,10 +766,10 @@ u8 r8712_addbareq_cmd(struct _adapter *padapter, u8 tid) struct addBaReq_parm *paddbareq_parm; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC); - if (paddbareq_parm == NULL) { + if (!paddbareq_parm) { kfree(ph2c); return _FAIL; } @@ -787,10 +787,10 @@ u8 r8712_wdg_wk_cmd(struct _adapter *padapter) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC); - if (pdrvintcmd_param == NULL) { + if (!pdrvintcmd_param) { kfree(ph2c); return _FAIL; } @@ -961,10 +961,10 @@ u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, struct cmd_priv *pcmdpriv = &adapter->cmdpriv; ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; param = kzalloc(sizeof(*param), GFP_ATOMIC); - if (param == NULL) { + if (!param) { kfree(ph2c); return _FAIL; } -- GitLab From 0b90c305c93e4e94e80d7f10091867e28f275d37 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Mon, 21 Mar 2016 02:10:21 +0530 Subject: [PATCH 0385/9938] staging: rtl8712: rtl871x_ioctl_linux: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index 1b9e24900477..6c02e9b29e2d 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -399,7 +399,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, if (wep_key_len > 0) { wep_key_len = wep_key_len <= 5 ? 5 : 13; pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC); - if (pwep == NULL) + if (!pwep) return -ENOMEM; pwep->KeyLength = wep_key_len; pwep->Length = wep_key_len + @@ -1793,7 +1793,7 @@ static int r871x_wx_set_enc_ext(struct net_device *dev, param_len = sizeof(struct ieee_param) + pext->key_len; param = kzalloc(param_len, GFP_ATOMIC); - if (param == NULL) + if (!param) return -ENOMEM; param->cmd = IEEE_CMD_SET_ENCRYPTION; eth_broadcast_addr(param->sta_addr); -- GitLab From b2def44cf0616f600636e36f8376061804b83e62 Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Tue, 22 Mar 2016 05:11:00 +0530 Subject: [PATCH 0386/9938] staging: rtl8712: Fixed FSF address warning in basic_types.h Fixed checkpatch warning after removing FSF address paragraph as per guidelines. Signed-off-by: Parth Sane Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/basic_types.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/rtl8712/basic_types.h b/drivers/staging/rtl8712/basic_types.h index 7561bed5dd44..f5c0231891b1 100644 --- a/drivers/staging/rtl8712/basic_types.h +++ b/drivers/staging/rtl8712/basic_types.h @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * Modifications for inclusion into the Linux staging tree are * Copyright(c) 2010 Larry Finger. All rights reserved. * -- GitLab From 501ef12a74a51ffa1a1fe9057565c450be564050 Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Tue, 22 Mar 2016 05:11:01 +0530 Subject: [PATCH 0387/9938] staging: rtl8712: Fixed FSF address warning in drv_types.h Fixed checkpatch warning after removing FSF address block as per guidelines. Signed-off-by: Parth Sane Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/drv_types.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h index 29e47e1501c5..ae79047ac6dc 100644 --- a/drivers/staging/rtl8712/drv_types.h +++ b/drivers/staging/rtl8712/drv_types.h @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * Modifications for inclusion into the Linux staging tree are * Copyright(c) 2010 Larry Finger. All rights reserved. * -- GitLab From c7838db04dc9a6921d3e3771c2deefe9dfe7c1a9 Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Tue, 22 Mar 2016 05:11:02 +0530 Subject: [PATCH 0388/9938] staging: rtl8712: Fixed FSF address warning in ethernet.h Fixed checkpatch warning after removing FSF address block as per guidelines. Signed-off-by: Parth Sane Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/ethernet.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/rtl8712/ethernet.h b/drivers/staging/rtl8712/ethernet.h index fad173f4097e..039da36fad3d 100644 --- a/drivers/staging/rtl8712/ethernet.h +++ b/drivers/staging/rtl8712/ethernet.h @@ -11,10 +11,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * Modifications for inclusion into the Linux staging tree are * Copyright(c) 2010 Larry Finger. All rights reserved. * -- GitLab From e8aad70c97ba280152463f6cb4f5e6ee2dd8e230 Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Tue, 22 Mar 2016 05:11:03 +0530 Subject: [PATCH 0389/9938] staging: rtl8712: Fixed FSF address warning in hal_init.c Fixed checkpatch warning after removing FSF address block as per guidelines. Signed-off-by: Parth Sane Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/hal_init.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 37fe0a4db602..0c76fbc3e702 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -13,10 +13,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * Modifications for inclusion into the Linux staging tree are * Copyright(c) 2010 Larry Finger. All rights reserved. * -- GitLab From 5ab2ce4305eb3c3b2dff7834993b1f6fb0c409be Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Tue, 22 Mar 2016 05:11:04 +0530 Subject: [PATCH 0390/9938] staging: rtl8712: Fixed FSF address warning in ieee80211.c Fixed checkpatch warning after removing FSF address block as per guidelines. Signed-off-by: Parth Sane Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/ieee80211.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c index d13b4d53c256..8918654b44ed 100644 --- a/drivers/staging/rtl8712/ieee80211.c +++ b/drivers/staging/rtl8712/ieee80211.c @@ -13,10 +13,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * * Modifications for inclusion into the Linux staging tree are * Copyright(c) 2010 Larry Finger. All rights reserved. * -- GitLab From b5e12ec38331256c3055591031ee96454c868209 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 19:49:51 +0530 Subject: [PATCH 0391/9938] Staging: rtl8188eu: rtw_efuse: Use sizeof type *pointer instead of sizeof type. Use sizeof type *pointer instead of sizeof type. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index fbce1f7e68ca..c17870cddb5b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -102,7 +102,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) if (!efuseTbl) return; - eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); + eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(*eFuseWord)); if (!eFuseWord) { DBG_88E("%s: alloc eFuseWord fail!\n", __func__); goto eFuseWord_failed; -- GitLab From 78822dc3c371ba7a909de72525ee176f78ea236c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 14 Mar 2016 22:45:13 +0200 Subject: [PATCH 0392/9938] Staging: wlan-ng: defined oui_rfc1042[] and oui_8021h[] arrays as const arrays This patch defines oui_rfc1042[] and oui_8021h[] arrays from p80211conv.c as const arrays since these are not changed anywhere in code. Signed-off-by: Claudiu Beznea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 0a8f3960d465..bdb50a51483b 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -75,8 +75,8 @@ #include "p80211ioctl.h" #include "p80211req.h" -static u8 oui_rfc1042[] = { 0x00, 0x00, 0x00 }; -static u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; +static const u8 oui_rfc1042[] = { 0x00, 0x00, 0x00 }; +static const u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; /*---------------------------------------------------------------- * p80211pb_ether_to_80211 -- GitLab From f3dbe30655a651cd846303ecc7d5c5176c00a023 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar Date: Mon, 21 Mar 2016 20:46:15 +0530 Subject: [PATCH 0393/9938] Staging: wlan-ng: Use x instead of x != NULL. Use x instead of x != NULL.This issue is detected by checkpatch.pl script. Signed-off-by: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 88255ce2871b..fdfc82152312 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -156,7 +156,7 @@ static int p80211knetdev_open(netdevice_t *netdev) return -ENODEV; /* Tell the MSD to open */ - if (wlandev->open != NULL) { + if (wlandev->open) { result = wlandev->open(wlandev); if (result == 0) { netif_start_queue(wlandev->netdev); @@ -186,7 +186,7 @@ static int p80211knetdev_stop(netdevice_t *netdev) int result = 0; wlandevice_t *wlandev = netdev->ml_priv; - if (wlandev->close != NULL) + if (wlandev->close) result = wlandev->close(wlandev); netif_stop_queue(wlandev->netdev); -- GitLab From f6b1160eb27f990cc1c48b67a5f83cb63115284e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 17 Mar 2016 10:10:40 -0700 Subject: [PATCH 0394/9938] staging: comedi: dt282x: tidy up register bit defines Arnd Bergmann pointed out that gcc-6 warns about passing negative signed integer into swab16() due to the macro expansion of 'outw'. It appears that the register map constants are causing the warnings. Actually, it might just be the (1 << 15) ones... Convert all the constants as suggested by checkpatch.pl: CHECK: Prefer using the BIT macro The BIT() macro will make all the constants explicitly 'unsigned', which helps to avoid the warning. Fix the, unsused, DT2821_CHANCSR_PRESLA() macro. The "Present List Address" (PRESLA) bits in the CHANCSR register are read only. This define was meant to extract the bits from the read value. Signed-off-by: H Hartley Sweeten Reported-by: Arnd Bergmann Reviewed-by: Ian Abbott Tested-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 65 +++++++++++++------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 40bf00984fa5..06a87a10a2d0 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -69,48 +69,49 @@ * Register map */ #define DT2821_ADCSR_REG 0x00 -#define DT2821_ADCSR_ADERR (1 << 15) -#define DT2821_ADCSR_ADCLK (1 << 9) -#define DT2821_ADCSR_MUXBUSY (1 << 8) -#define DT2821_ADCSR_ADDONE (1 << 7) -#define DT2821_ADCSR_IADDONE (1 << 6) +#define DT2821_ADCSR_ADERR BIT(15) +#define DT2821_ADCSR_ADCLK BIT(9) +#define DT2821_ADCSR_MUXBUSY BIT(8) +#define DT2821_ADCSR_ADDONE BIT(7) +#define DT2821_ADCSR_IADDONE BIT(6) #define DT2821_ADCSR_GS(x) (((x) & 0x3) << 4) #define DT2821_ADCSR_CHAN(x) (((x) & 0xf) << 0) #define DT2821_CHANCSR_REG 0x02 -#define DT2821_CHANCSR_LLE (1 << 15) -#define DT2821_CHANCSR_PRESLA(x) (((x) & 0xf) >> 8) +#define DT2821_CHANCSR_LLE BIT(15) +#define DT2821_CHANCSR_TO_PRESLA(x) (((x) >> 8) & 0xf) #define DT2821_CHANCSR_NUMB(x) ((((x) - 1) & 0xf) << 0) #define DT2821_ADDAT_REG 0x04 #define DT2821_DACSR_REG 0x06 -#define DT2821_DACSR_DAERR (1 << 15) +#define DT2821_DACSR_DAERR BIT(15) #define DT2821_DACSR_YSEL(x) ((x) << 9) -#define DT2821_DACSR_SSEL (1 << 8) -#define DT2821_DACSR_DACRDY (1 << 7) -#define DT2821_DACSR_IDARDY (1 << 6) -#define DT2821_DACSR_DACLK (1 << 5) -#define DT2821_DACSR_HBOE (1 << 1) -#define DT2821_DACSR_LBOE (1 << 0) +#define DT2821_DACSR_SSEL BIT(8) +#define DT2821_DACSR_DACRDY BIT(7) +#define DT2821_DACSR_IDARDY BIT(6) +#define DT2821_DACSR_DACLK BIT(5) +#define DT2821_DACSR_HBOE BIT(1) +#define DT2821_DACSR_LBOE BIT(0) #define DT2821_DADAT_REG 0x08 #define DT2821_DIODAT_REG 0x0a #define DT2821_SUPCSR_REG 0x0c -#define DT2821_SUPCSR_DMAD (1 << 15) -#define DT2821_SUPCSR_ERRINTEN (1 << 14) -#define DT2821_SUPCSR_CLRDMADNE (1 << 13) -#define DT2821_SUPCSR_DDMA (1 << 12) -#define DT2821_SUPCSR_DS_PIO (0 << 10) -#define DT2821_SUPCSR_DS_AD_CLK (1 << 10) -#define DT2821_SUPCSR_DS_DA_CLK (2 << 10) -#define DT2821_SUPCSR_DS_AD_TRIG (3 << 10) -#define DT2821_SUPCSR_BUFFB (1 << 9) -#define DT2821_SUPCSR_SCDN (1 << 8) -#define DT2821_SUPCSR_DACON (1 << 7) -#define DT2821_SUPCSR_ADCINIT (1 << 6) -#define DT2821_SUPCSR_DACINIT (1 << 5) -#define DT2821_SUPCSR_PRLD (1 << 4) -#define DT2821_SUPCSR_STRIG (1 << 3) -#define DT2821_SUPCSR_XTRIG (1 << 2) -#define DT2821_SUPCSR_XCLK (1 << 1) -#define DT2821_SUPCSR_BDINIT (1 << 0) +#define DT2821_SUPCSR_DMAD BIT(15) +#define DT2821_SUPCSR_ERRINTEN BIT(14) +#define DT2821_SUPCSR_CLRDMADNE BIT(13) +#define DT2821_SUPCSR_DDMA BIT(12) +#define DT2821_SUPCSR_DS(x) (((x) & 0x3) << 10) +#define DT2821_SUPCSR_DS_PIO DT2821_SUPCSR_DS(0) +#define DT2821_SUPCSR_DS_AD_CLK DT2821_SUPCSR_DS(1) +#define DT2821_SUPCSR_DS_DA_CLK DT2821_SUPCSR_DS(2) +#define DT2821_SUPCSR_DS_AD_TRIG DT2821_SUPCSR_DS(3) +#define DT2821_SUPCSR_BUFFB BIT(9) +#define DT2821_SUPCSR_SCDN BIT(8) +#define DT2821_SUPCSR_DACON BIT(7) +#define DT2821_SUPCSR_ADCINIT BIT(6) +#define DT2821_SUPCSR_DACINIT BIT(5) +#define DT2821_SUPCSR_PRLD BIT(4) +#define DT2821_SUPCSR_STRIG BIT(3) +#define DT2821_SUPCSR_XTRIG BIT(2) +#define DT2821_SUPCSR_XCLK BIT(1) +#define DT2821_SUPCSR_BDINIT BIT(0) #define DT2821_TMRCTR_REG 0x0e static const struct comedi_lrange range_dt282x_ai_lo_bipolar = { -- GitLab From 938cae7ab3b046af9669aa7454fab0546231ba48 Mon Sep 17 00:00:00 2001 From: Leslie Klein Date: Sun, 20 Mar 2016 20:26:12 -0400 Subject: [PATCH 0395/9938] Staging: comedi: comedi_buf: Replace 'unsigned' with 'unsigned int' Fix checkpatch warning: Prefer 'unsigned int' to bare use of 'unsigned' in file comedi_buf.c Signed-off-by: Leslie Klein Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_buf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 90c28016c6c1..c7d7682b1412 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -80,14 +80,14 @@ static void __comedi_buf_free(struct comedi_device *dev, static void __comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned n_pages) + unsigned int n_pages) { struct comedi_async *async = s->async; struct page **pages = NULL; struct comedi_buf_map *bm; struct comedi_buf_page *buf; unsigned long flags; - unsigned i; + unsigned int i; if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) { dev_err(dev->class_dev, @@ -208,7 +208,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, /* allocate new buffer */ if (new_size) { - unsigned n_pages = new_size >> PAGE_SHIFT; + unsigned int n_pages = new_size >> PAGE_SHIFT; __comedi_buf_alloc(dev, s, n_pages); @@ -302,7 +302,7 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s, { struct comedi_async *async = s->async; unsigned int count = 0; - const unsigned num_sample_bytes = comedi_bytes_per_sample(s); + const unsigned int num_sample_bytes = comedi_bytes_per_sample(s); if (!s->munge || (async->cmd.flags & CMDF_RAWDATA)) { async->munge_count += num_bytes; @@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(comedi_buf_write_free); unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s) { struct comedi_async *async = s->async; - unsigned num_bytes; + unsigned int num_bytes; if (!async) return 0; -- GitLab From d4d47895a906779b5e8df157f703f906d22305b5 Mon Sep 17 00:00:00 2001 From: Leslie Klein Date: Mon, 21 Mar 2016 09:18:35 -0400 Subject: [PATCH 0396/9938] Staging: comedi: comedi_fops: Replace 'unsigned' with 'unsigned int' Fix checkpatch warning: Prefer 'unsigned int' to bare use of 'unsigned' in file comedi_fops.c Signed-off-by: Leslie Klein Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 48 ++++++++++++++-------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 7c7b477b0f28..4bdea202c46c 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -186,7 +186,7 @@ static bool comedi_clear_board_dev(struct comedi_device *dev) return cleared; } -static struct comedi_device *comedi_clear_board_minor(unsigned minor) +static struct comedi_device *comedi_clear_board_minor(unsigned int minor) { struct comedi_device *dev; @@ -210,7 +210,7 @@ static void comedi_free_board_dev(struct comedi_device *dev) } static struct comedi_subdevice -*comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned minor) +*comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor) { struct comedi_subdevice *s; unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; @@ -223,7 +223,7 @@ static struct comedi_subdevice return s; } -static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor) +static struct comedi_device *comedi_dev_get_from_board_minor(unsigned int minor) { struct comedi_device *dev; @@ -233,7 +233,7 @@ static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor) return dev; } -static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) +static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned int minor) { struct comedi_device *dev; struct comedi_subdevice *s; @@ -258,7 +258,7 @@ static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) * reference incremented. Return NULL if no COMEDI device exists with the * specified minor device number. */ -struct comedi_device *comedi_dev_get_from_minor(unsigned minor) +struct comedi_device *comedi_dev_get_from_minor(unsigned int minor) { if (minor < COMEDI_NUM_BOARD_MINORS) return comedi_dev_get_from_board_minor(minor); @@ -342,7 +342,7 @@ static struct comedi_subdevice *comedi_file_write_subdevice(struct file *file) } static int resize_async_buffer(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned new_size) + struct comedi_subdevice *s, unsigned int new_size) { struct comedi_async *async = s->async; int retval; @@ -616,19 +616,19 @@ static struct attribute *comedi_dev_attrs[] = { ATTRIBUTE_GROUPS(comedi_dev); static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s, - unsigned bits) + unsigned int bits) { s->runflags &= ~bits; } static void __comedi_set_subdevice_runflags(struct comedi_subdevice *s, - unsigned bits) + unsigned int bits) { s->runflags |= bits; } static void comedi_update_subdevice_runflags(struct comedi_subdevice *s, - unsigned mask, unsigned bits) + unsigned int mask, unsigned int bits) { unsigned long flags; @@ -638,15 +638,15 @@ static void comedi_update_subdevice_runflags(struct comedi_subdevice *s, spin_unlock_irqrestore(&s->spin_lock, flags); } -static unsigned __comedi_get_subdevice_runflags(struct comedi_subdevice *s) +static unsigned int __comedi_get_subdevice_runflags(struct comedi_subdevice *s) { return s->runflags; } -static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) +static unsigned int comedi_get_subdevice_runflags(struct comedi_subdevice *s) { unsigned long flags; - unsigned runflags; + unsigned int runflags; spin_lock_irqsave(&s->spin_lock, flags); runflags = __comedi_get_subdevice_runflags(s); @@ -654,12 +654,12 @@ static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) return runflags; } -static bool comedi_is_runflags_running(unsigned runflags) +static bool comedi_is_runflags_running(unsigned int runflags) { return runflags & COMEDI_SRF_RUNNING; } -static bool comedi_is_runflags_in_error(unsigned runflags) +static bool comedi_is_runflags_in_error(unsigned int runflags) { return runflags & COMEDI_SRF_ERROR; } @@ -673,7 +673,7 @@ static bool comedi_is_runflags_in_error(unsigned runflags) */ bool comedi_is_subdevice_running(struct comedi_subdevice *s) { - unsigned runflags = comedi_get_subdevice_runflags(s); + unsigned int runflags = comedi_get_subdevice_runflags(s); return comedi_is_runflags_running(runflags); } @@ -681,14 +681,14 @@ EXPORT_SYMBOL_GPL(comedi_is_subdevice_running); static bool __comedi_is_subdevice_running(struct comedi_subdevice *s) { - unsigned runflags = __comedi_get_subdevice_runflags(s); + unsigned int runflags = __comedi_get_subdevice_runflags(s); return comedi_is_runflags_running(runflags); } bool comedi_can_auto_free_spriv(struct comedi_subdevice *s) { - unsigned runflags = __comedi_get_subdevice_runflags(s); + unsigned int runflags = __comedi_get_subdevice_runflags(s); return runflags & COMEDI_SRF_FREE_SPRIV; } @@ -2038,7 +2038,7 @@ static int do_setwsubd_ioctl(struct comedi_device *dev, unsigned long arg, static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - unsigned minor = iminor(file_inode(file)); + unsigned int minor = iminor(file_inode(file)); struct comedi_file *cfp = file->private_data; struct comedi_device *dev = cfp->dev; int rc; @@ -2342,7 +2342,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, add_wait_queue(&async->wait_head, &wait); while (count == 0 && !retval) { - unsigned runflags; + unsigned int runflags; unsigned int wp, n1, n2; set_current_state(TASK_INTERRUPTIBLE); @@ -2485,7 +2485,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, n = min_t(size_t, m, nbytes); if (n == 0) { - unsigned runflags = comedi_get_subdevice_runflags(s); + unsigned int runflags = comedi_get_subdevice_runflags(s); if (!comedi_is_runflags_running(runflags)) { if (comedi_is_runflags_in_error(runflags)) @@ -2573,7 +2573,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, static int comedi_open(struct inode *inode, struct file *file) { - const unsigned minor = iminor(inode); + const unsigned int minor = iminor(inode); struct comedi_file *cfp; struct comedi_device *dev = comedi_dev_get_from_minor(minor); int rc; @@ -2733,7 +2733,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) { struct comedi_device *dev; struct device *csdev; - unsigned i; + unsigned int i; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -2791,7 +2791,7 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s) { struct comedi_device *dev = s->device; struct device *csdev; - unsigned i; + unsigned int i; mutex_lock(&comedi_subdevice_minor_table_lock); for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) { @@ -2841,7 +2841,7 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s) static void comedi_cleanup_board_minors(void) { struct comedi_device *dev; - unsigned i; + unsigned int i; for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) { dev = comedi_clear_board_minor(i); -- GitLab From 6c5f37dfbbc9b2121b39be3a7a61b93dbba3ed08 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 14 Mar 2016 21:55:20 +0200 Subject: [PATCH 0397/9938] Staging: vt6655: defined byVT3253InitTab_RFMD[] and byVT3253B0_RFMD[] as const arrays. This patch changes byVT3253InitTab_RFMD[] and byVT3253B0_RFMD[] arrays in const arrays since these are not changed anywhere in the code. Signed-off-by: Claudiu Beznea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 1e6c0c4a0307..94a7e64baf5f 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -66,7 +66,7 @@ /*--------------------- Static Variables --------------------------*/ #define CB_VT3253_INIT_FOR_RFMD 446 -static unsigned char byVT3253InitTab_RFMD[CB_VT3253_INIT_FOR_RFMD][2] = { +static const unsigned char byVT3253InitTab_RFMD[CB_VT3253_INIT_FOR_RFMD][2] = { {0x00, 0x30}, {0x01, 0x00}, {0x02, 0x00}, @@ -516,7 +516,7 @@ static unsigned char byVT3253InitTab_RFMD[CB_VT3253_INIT_FOR_RFMD][2] = { }; #define CB_VT3253B0_INIT_FOR_RFMD 256 -static unsigned char byVT3253B0_RFMD[CB_VT3253B0_INIT_FOR_RFMD][2] = { +static const unsigned char byVT3253B0_RFMD[CB_VT3253B0_INIT_FOR_RFMD][2] = { {0x00, 0x31}, {0x01, 0x00}, {0x02, 0x00}, -- GitLab From 779bee40b907de23771bb8eaf334b81be53018b1 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 15 Mar 2016 21:34:59 +0100 Subject: [PATCH 0398/9938] Staging: speakup: Clear hi font bit from attributes Previously, speakup would see the hi-font bit in attributes. Since this bit has nothing to do with attributes, we need to clear it. Signed-off-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index a22fb07512a1..97ca4ecca8a9 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -263,7 +263,7 @@ static struct notifier_block vt_notifier_block = { static unsigned char get_attributes(struct vc_data *vc, u16 *pos) { pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, 1); - return (u_char) (scr_readw(pos) >> 8); + return (scr_readw(pos) & ~vc->vc_hi_font_mask) >> 8; } static void speakup_date(struct vc_data *vc) @@ -473,8 +473,10 @@ static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs) w = scr_readw(pos); c = w & 0xff; - if (w & vc->vc_hi_font_mask) + if (w & vc->vc_hi_font_mask) { + w &= ~vc->vc_hi_font_mask; c |= 0x100; + } ch = inverse_translate(vc, c, 0); *attribs = (w & 0xff00) >> 8; -- GitLab From 5150d01ea99230576060e864f7a6f15e29b8dc4d Mon Sep 17 00:00:00 2001 From: Kathryn Hampton Date: Tue, 15 Mar 2016 18:16:24 -0700 Subject: [PATCH 0399/9938] staging: vt6655: fix style violations for lines over 80 characters This patch addresses line length errors reported by checkpatch.pl that could be fixed with simple line breaks. Signed-off-by: Kathryn Hampton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 20 +++++-- drivers/staging/vt6655/baseband.h | 6 +- drivers/staging/vt6655/card.c | 95 +++++++++++++++++++++---------- drivers/staging/vt6655/card.h | 9 ++- drivers/staging/vt6655/desc.h | 3 +- drivers/staging/vt6655/mac.c | 15 +++-- drivers/staging/vt6655/srom.c | 9 ++- 7 files changed, 106 insertions(+), 51 deletions(-) diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 94a7e64baf5f..654d072bdc28 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -36,8 +36,10 @@ * Revision History: * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. * 08-07-2003 Bryan YC Fan: Add MAXIM2827/2825 and RFMD2959 support. - * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and BBvCalculateParameter(). - * cancel the setting of MAC_REG_SOFTPWRCTL on BBbVT3253Init(). + * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and + * BBvCalculateParameter(). + * cancel the setting of MAC_REG_SOFTPWRCTL on + * BBbVT3253Init(). * Add the comments. * 09-01-2003 Bryan YC Fan: RF & BB tables updated. * Modified BBvLoopbackOn & BBvLoopbackOff(). @@ -777,7 +779,8 @@ static const unsigned char byVT3253B0_RFMD[CB_VT3253B0_INIT_FOR_RFMD][2] = { #define CB_VT3253B0_AGC_FOR_RFMD2959 195 /* For RFMD2959 */ -static unsigned char byVT3253B0_AGC4_RFMD2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = { +static +unsigned char byVT3253B0_AGC4_RFMD2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = { {0xF0, 0x00}, {0xF1, 0x3E}, {0xF0, 0x80}, @@ -977,7 +980,8 @@ static unsigned char byVT3253B0_AGC4_RFMD2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = #define CB_VT3253B0_INIT_FOR_AIROHA2230 256 /* For AIROHA */ -static unsigned char byVT3253B0_AIROHA2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = { +static +unsigned char byVT3253B0_AIROHA2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = { {0x00, 0x31}, {0x01, 0x00}, {0x02, 0x00}, @@ -2160,9 +2164,13 @@ bool BBbVT3253Init(struct vnt_private *priv) /* {{ RobertYu:20050223, request by JerryChung */ - /* Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) */ + /* Init ANT B select,TX Config CR09 = 0x61->0x45, + * 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) + */ /*bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);*/ - /* Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) */ + /* Init ANT B select,RX Config CR10 = 0x28->0x2A, + * 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) + */ /*bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28);*/ /* Select VC1/VC2, CR215 = 0x02->0x06 */ bResult &= BBbWriteEmbedded(priv, 0xd7, 0x06); diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index 43a4fb1f3570..b4e8c43180ec 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -77,8 +77,10 @@ BBuGetFrameTime( void vnt_get_phy_field(struct vnt_private *, u32 frame_length, u16 tx_rate, u8 pkt_type, struct vnt_phy_field *); -bool BBbReadEmbedded(struct vnt_private *, unsigned char byBBAddr, unsigned char *pbyData); -bool BBbWriteEmbedded(struct vnt_private *, unsigned char byBBAddr, unsigned char byData); +bool BBbReadEmbedded(struct vnt_private *, unsigned char byBBAddr, + unsigned char *pbyData); +bool BBbWriteEmbedded(struct vnt_private *, unsigned char byBBAddr, + unsigned char byData); void BBvSetShortSlotTime(struct vnt_private *); void BBvSetVGAGainOffset(struct vnt_private *, unsigned char byData); diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 3d338122b590..afb1e8bde975 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -336,7 +336,8 @@ bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type) } if (priv->byCWMaxMin != byCWMaxMin) { priv->byCWMaxMin = byCWMaxMin; - VNSvOutPortB(priv->PortOffset + MAC_REG_CWMAXMIN0, priv->byCWMaxMin); + VNSvOutPortB(priv->PortOffset + MAC_REG_CWMAXMIN0, + priv->byCWMaxMin); } priv->byPacketType = CARDbyGetPktType(priv); @@ -373,9 +374,12 @@ bool CARDbUpdateTSF(struct vnt_private *priv, unsigned char byRxRate, qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, local_tsf); /* adjust TSF, HW's TSF add TSF Offset reg */ - VNSvOutPortD(priv->PortOffset + MAC_REG_TSFOFST, (u32)qwTSFOffset); - VNSvOutPortD(priv->PortOffset + MAC_REG_TSFOFST + 4, (u32)(qwTSFOffset >> 32)); - MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN); + VNSvOutPortD(priv->PortOffset + MAC_REG_TSFOFST, + (u32)qwTSFOffset); + VNSvOutPortD(priv->PortOffset + MAC_REG_TSFOFST + 4, + (u32)(qwTSFOffset >> 32)); + MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, + TFTCTL_TSFSYNCEN); } return true; } @@ -407,7 +411,8 @@ bool CARDbSetBeaconPeriod(struct vnt_private *priv, priv->wBeaconInterval = wBeaconInterval; /* Set NextTBTT */ VNSvOutPortD(priv->PortOffset + MAC_REG_NEXTTBTT, (u32)qwNextTBTT); - VNSvOutPortD(priv->PortOffset + MAC_REG_NEXTTBTT + 4, (u32)(qwNextTBTT >> 32)); + VNSvOutPortD(priv->PortOffset + MAC_REG_NEXTTBTT + 4, + (u32)(qwNextTBTT >> 32)); MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); return true; @@ -433,15 +438,19 @@ bool CARDbRadioPowerOff(struct vnt_private *priv) switch (priv->byRFType) { case RF_RFMD2959: - MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV); - MACvWordRegBitsOn(priv->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1); + MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_TXPEINV); + MACvWordRegBitsOn(priv->PortOffset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_SWPE1); break; case RF_AIROHA: case RF_AL2230S: case RF_AIROHA7230: - MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE2); - MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_SWPE2); + MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_SWPE3); break; } @@ -451,7 +460,8 @@ bool CARDbRadioPowerOff(struct vnt_private *priv) priv->bRadioOff = true; pr_debug("chester power off\n"); - MACvRegBitsOn(priv->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET); /* LED issue */ + MACvRegBitsOn(priv->PortOffset, MAC_REG_GPIOCTL0, + LED_ACTSET); /* LED issue */ return bResult; } @@ -488,21 +498,24 @@ bool CARDbRadioPowerOn(struct vnt_private *priv) switch (priv->byRFType) { case RF_RFMD2959: - MACvWordRegBitsOn(priv->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV); - MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1); + MACvWordRegBitsOn(priv->PortOffset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_TXPEINV); + MACvWordRegBitsOff(priv->PortOffset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_SWPE1); break; case RF_AIROHA: case RF_AL2230S: case RF_AIROHA7230: - MACvWordRegBitsOn(priv->PortOffset, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 | - SOFTPWRCTL_SWPE3)); + MACvWordRegBitsOn(priv->PortOffset, MAC_REG_SOFTPWRCTL, + (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); break; } priv->bRadioOff = false; pr_debug("chester power on\n"); - MACvRegBitsOff(priv->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET); /* LED issue */ + MACvRegBitsOff(priv->PortOffset, MAC_REG_GPIOCTL0, + LED_ACTSET); /* LED issue */ return bResult; } @@ -717,55 +730,72 @@ void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type) bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_6, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_9 */ s_vCalculateOFDMRParameter(RATE_9M, bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_9, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_12 */ s_vCalculateOFDMRParameter(RATE_12M, bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_12, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_18 */ s_vCalculateOFDMRParameter(RATE_18M, bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_18, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_24 */ s_vCalculateOFDMRParameter(RATE_24M, bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_24, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_36 */ - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, RATE_36M), + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate( + (void *)priv, + RATE_36M), bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_36, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_48 */ - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, RATE_48M), + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate( + (void *)priv, + RATE_48M), bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_48, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_54 */ - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, RATE_54M), + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate( + (void *)priv, + RATE_54M), bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_54, + MAKEWORD(byTxRate, byRsvTime)); /* RSPINF_a_72 */ - s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, RATE_54M), + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate( + (void *)priv, + RATE_54M), bb_type, &byTxRate, &byRsvTime); - VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate, byRsvTime)); + VNSvOutPortW(priv->PortOffset + MAC_REG_RSPINF_A_72, + MAKEWORD(byTxRate, byRsvTime)); /* Set to Page0 */ MACvSelectPage0(priv->PortOffset); @@ -830,7 +860,8 @@ unsigned char CARDbyGetPktType(struct vnt_private *priv) * * Return Value: none */ -void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode) +void CARDvSetLoopbackMode(struct vnt_private *priv, + unsigned short wLoopbackMode) { switch (wLoopbackMode) { case CARD_LB_NONE: @@ -965,7 +996,8 @@ u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval) * * Return Value: none */ -void CARDvSetFirstNextTBTT(struct vnt_private *priv, unsigned short wBeaconInterval) +void CARDvSetFirstNextTBTT(struct vnt_private *priv, + unsigned short wBeaconInterval) { void __iomem *dwIoBase = priv->PortOffset; u64 qwNextTBTT = 0; @@ -993,7 +1025,8 @@ void CARDvSetFirstNextTBTT(struct vnt_private *priv, unsigned short wBeaconInter * * Return Value: none */ -void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, unsigned short wBeaconInterval) +void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, + unsigned short wBeaconInterval) { void __iomem *dwIoBase = priv->PortOffset; diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 16cca49e680a..0203c7fd91a2 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -38,7 +38,8 @@ * LOBYTE is MAC LB mode, HIBYTE is MII LB mode */ #define CARD_LB_NONE MAKEWORD(MAC_LB_NONE, 0) -#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, 0) /* PHY must ISO, avoid MAC loopback packet go out */ +/* PHY must ISO, avoid MAC loopback packet go out */ +#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, 0) #define CARD_LB_PHY MAKEWORD(MAC_LB_EXT, 0) #define DEFAULT_MSDU_LIFETIME 512 /* ms */ @@ -71,8 +72,10 @@ void CARDvUpdateBasicTopRate(struct vnt_private *); bool CARDbIsOFDMinBasicRate(struct vnt_private *); void CARDvSetLoopbackMode(struct vnt_private *, unsigned short wLoopbackMode); bool CARDbSoftwareReset(struct vnt_private *); -void CARDvSetFirstNextTBTT(struct vnt_private *, unsigned short wBeaconInterval); -void CARDvUpdateNextTBTT(struct vnt_private *, u64 qwTSF, unsigned short wBeaconInterval); +void CARDvSetFirstNextTBTT(struct vnt_private *, + unsigned short wBeaconInterval); +void CARDvUpdateNextTBTT(struct vnt_private *, u64 qwTSF, + unsigned short wBeaconInterval); bool CARDbGetCurrentTSF(struct vnt_private *, u64 *pqwCurrTSF); u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval); u64 CARDqGetTSFOffset(unsigned char byRxRate, u64 qwTSF1, u64 qwTSF2); diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index 9fbc7172484e..2d7f6ae89164 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -157,7 +157,8 @@ /* TD_INFO flags control bit */ #define TD_FLAGS_NETIF_SKB 0x01 /* check if need release skb */ -#define TD_FLAGS_PRIV_SKB 0x02 /* check if called from private skb (hostap) */ +/* check if called from private skb (hostap) */ +#define TD_FLAGS_PRIV_SKB 0x02 #define TD_FLAGS_PS_RETRY 0x04 /* check if PS STA frame re-transmit */ /* diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 45196c6e9e12..8e13f7f41415 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -47,7 +47,8 @@ * * Revision History: * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53 - * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()& MACvEnableBusSusEn() + * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()& + * MACvEnableBusSusEn() * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry * */ @@ -138,7 +139,8 @@ bool MACbIsIntDisable(struct vnt_private *priv) * Return Value: none * */ -void MACvSetShortRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit) +void MACvSetShortRetryLimit(struct vnt_private *priv, + unsigned char byRetryLimit) { void __iomem *io_base = priv->PortOffset; /* set SRT */ @@ -160,7 +162,8 @@ void MACvSetShortRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit * Return Value: none * */ -void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit) +void MACvSetLongRetryLimit(struct vnt_private *priv, + unsigned char byRetryLimit) { void __iomem *io_base = priv->PortOffset; /* set LRT */ @@ -304,7 +307,8 @@ bool MACbSoftwareReset(struct vnt_private *priv) /* * Description: - * save some important register's value, then do reset, then restore register's value + * save some important register's value, then do reset, then restore + * register's value * * Parameters: * In: @@ -738,7 +742,8 @@ void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay) * Return Value: none * */ -void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime) +void MACvOneShotTimer1MicroSec(struct vnt_private *priv, + unsigned int uDelayTime) { void __iomem *io_base = priv->PortOffset; diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index 9ec49e653b61..ee992772066f 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -72,7 +72,8 @@ * Return Value: data read * */ -unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, unsigned char byContntOffset) +unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, + unsigned char byContntOffset) { unsigned short wDelay, wNoACK; unsigned char byWait; @@ -124,7 +125,8 @@ void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs) /* ii = Rom Address */ for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) { - *pbyEepromRegs = SROMbyReadEmbedded(dwIoBase, (unsigned char)ii); + *pbyEepromRegs = SROMbyReadEmbedded(dwIoBase, + (unsigned char)ii); pbyEepromRegs++; } } @@ -141,7 +143,8 @@ void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs) * Return Value: none * */ -void SROMvReadEtherAddress(void __iomem *dwIoBase, unsigned char *pbyEtherAddress) +void SROMvReadEtherAddress(void __iomem *dwIoBase, + unsigned char *pbyEtherAddress) { unsigned char ii; -- GitLab From 896802a8e208997faff6e38d711cd9b13c7a2e23 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Mar 2016 08:39:24 +0900 Subject: [PATCH 0400/9938] staging: wilc1000: use mutex instead of struct semaphore hif_sema_deinit This patch replaces struct semaphore hif_sema_deinit with struct mutex hif_deinit_lock. It is better to use mutex because mutex gives better performance than semaphore. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4be8b3183b28..b1ffa91dfe52 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -234,7 +234,7 @@ static struct message_queue hif_msg_q; static struct semaphore hif_sema_thread; static struct semaphore hif_sema_driver; static struct completion hif_wait_response; -static struct semaphore hif_sema_deinit; +static struct mutex hif_deinit_lock; static struct timer_list periodic_rssi; u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN]; @@ -3402,7 +3402,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) if (clients_count == 0) { sema_init(&hif_sema_thread, 0); sema_init(&hif_sema_driver, 0); - sema_init(&hif_sema_deinit, 1); + mutex_init(&hif_deinit_lock); } init_completion(&hif_drv->comp_test_key_block); @@ -3470,7 +3470,7 @@ int wilc_deinit(struct wilc_vif *vif) return -EFAULT; } - down(&hif_sema_deinit); + mutex_lock(&hif_deinit_lock); terminated_handle = hif_drv; @@ -3512,7 +3512,7 @@ int wilc_deinit(struct wilc_vif *vif) clients_count--; terminated_handle = NULL; - up(&hif_sema_deinit); + mutex_unlock(&hif_deinit_lock); return result; } @@ -3559,25 +3559,25 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *pu8Buffer, struct host_if_drv *hif_drv = NULL; struct wilc_vif *vif; - down(&hif_sema_deinit); + mutex_lock(&hif_deinit_lock); id = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24)); vif = wilc_get_vif_from_idx(wilc, id); if (!vif) { - up(&hif_sema_deinit); + mutex_unlock(&hif_deinit_lock); return; } hif_drv = vif->hif_drv; if (!hif_drv || hif_drv == terminated_handle) { - up(&hif_sema_deinit); + mutex_unlock(&hif_deinit_lock); return; } if (!hif_drv->usr_conn_req.conn_result) { netdev_err(vif->ndev, "there is no current Connect Request\n"); - up(&hif_sema_deinit); + mutex_unlock(&hif_deinit_lock); return; } @@ -3594,7 +3594,7 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *pu8Buffer, if (result) netdev_err(vif->ndev, "synchronous info (%d)\n", result); - up(&hif_sema_deinit); + mutex_unlock(&hif_deinit_lock); } void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, -- GitLab From 094c0741dec38c73793f674293dcd2026d1e77d7 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 22 Mar 2016 10:28:51 +0530 Subject: [PATCH 0401/9938] staging: comedi: amplc_pci230: Convert macro GAT_CONFIG to static inline function Convert macro GAT_CONFIG to static inline function as static inline functions are preferred over macros. This change is possible since the arguments at all call sites have the same type. This was done using Coccinelle: @r@ expression e; @@ - #define GAT_CONFIG(chan, src) e + static inline unsigned int pci230_gat_config(unsigned int chan, + unsigned int src) +{ + return ((chan & 3) << 3) | (src & 7); +} @r1@ expression dev,reg,chan,src; @@ -GAT_CONFIG(chan, src) +pci230_gat_config(chan, src) Also, the comment describing the macro has been removed manually. Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 907c39cc89d7..cf5ac8aad236 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -379,8 +379,12 @@ #define GAT_GND 1 /* GND (i.e. disabled) */ #define GAT_EXT 2 /* external gate input (PPCn on PCI230) */ #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */ -/* Macro to construct gate input configuration register value. */ -#define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7)) + +static inline unsigned int pci230_gat_config(unsigned int chan, + unsigned int src) +{ + return ((chan & 3) << 3) | (src & 7); +} /* * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260: @@ -1263,7 +1267,8 @@ static void pci230_ao_start(struct comedi_device *dev, irqflags); } /* Set CT1 gate high to start counting. */ - outb(GAT_CONFIG(1, GAT_VCC), dev->iobase + PCI230_ZGAT_SCE); + outb(pci230_gat_config(1, GAT_VCC), + dev->iobase + PCI230_ZGAT_SCE); break; case TRIG_INT: async->inttrig = pci230_ao_inttrig_scan_begin; @@ -1351,7 +1356,8 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * cmd->scan_begin_arg is sampling period in ns. * Gate it off for now. */ - outb(GAT_CONFIG(1, GAT_GND), dev->iobase + PCI230_ZGAT_SCE); + outb(pci230_gat_config(1, GAT_GND), + dev->iobase + PCI230_ZGAT_SCE); pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, cmd->scan_begin_arg, cmd->flags); @@ -1792,9 +1798,9 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev, spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); if (devpriv->ai_cmd_started) { /* Trigger scan by waggling CT0 gate source. */ - zgat = GAT_CONFIG(0, GAT_GND); + zgat = pci230_gat_config(0, GAT_GND); outb(zgat, dev->iobase + PCI230_ZGAT_SCE); - zgat = GAT_CONFIG(0, GAT_VCC); + zgat = pci230_gat_config(0, GAT_VCC); outb(zgat, dev->iobase + PCI230_ZGAT_SCE); } spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); @@ -1926,20 +1932,20 @@ static void pci230_ai_start(struct comedi_device *dev, * Conversion timer CT2 needs to be gated by * inverted output of monostable CT2. */ - zgat = GAT_CONFIG(2, GAT_NOUTNM2); + zgat = pci230_gat_config(2, GAT_NOUTNM2); } else { /* * Conversion timer CT2 needs to be gated on * continuously. */ - zgat = GAT_CONFIG(2, GAT_VCC); + zgat = pci230_gat_config(2, GAT_VCC); } outb(zgat, dev->iobase + PCI230_ZGAT_SCE); if (cmd->scan_begin_src != TRIG_FOLLOW) { /* Set monostable CT0 trigger source. */ switch (cmd->scan_begin_src) { default: - zgat = GAT_CONFIG(0, GAT_VCC); + zgat = pci230_gat_config(0, GAT_VCC); break; case TRIG_EXT: /* @@ -1950,21 +1956,21 @@ static void pci230_ai_start(struct comedi_device *dev, * input in order to use it as an external scan * trigger. */ - zgat = GAT_CONFIG(0, GAT_EXT); + zgat = pci230_gat_config(0, GAT_EXT); break; case TRIG_TIMER: /* * Monostable CT0 triggered by rising edge on * inverted output of CT1 (falling edge on CT1). */ - zgat = GAT_CONFIG(0, GAT_NOUTNM2); + zgat = pci230_gat_config(0, GAT_NOUTNM2); break; case TRIG_INT: /* * Monostable CT0 is triggered by inttrig * function waggling the CT0 gate source. */ - zgat = GAT_CONFIG(0, GAT_VCC); + zgat = pci230_gat_config(0, GAT_VCC); break; } outb(zgat, dev->iobase + PCI230_ZGAT_SCE); @@ -1974,7 +1980,7 @@ static void pci230_ai_start(struct comedi_device *dev, * Scan period timer CT1 needs to be * gated on to start counting. */ - zgat = GAT_CONFIG(1, GAT_VCC); + zgat = pci230_gat_config(1, GAT_VCC); outb(zgat, dev->iobase + PCI230_ZGAT_SCE); break; case TRIG_INT: @@ -2216,7 +2222,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * Note, counter/timer output 2 can be monitored on the * connector: PCI230 pin 21, PCI260 pin 18. */ - zgat = GAT_CONFIG(2, GAT_GND); + zgat = pci230_gat_config(2, GAT_GND); outb(zgat, dev->iobase + PCI230_ZGAT_SCE); /* Set counter/timer 2 to the specified conversion period. */ pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg, @@ -2234,7 +2240,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * monostable to stop it triggering. The trigger * source will be changed later. */ - zgat = GAT_CONFIG(0, GAT_VCC); + zgat = pci230_gat_config(0, GAT_VCC); outb(zgat, dev->iobase + PCI230_ZGAT_SCE); pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1, ((uint64_t)cmd->convert_arg * @@ -2247,7 +2253,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * * Set up CT1 but gate it off for now. */ - zgat = GAT_CONFIG(1, GAT_GND); + zgat = pci230_gat_config(1, GAT_GND); outb(zgat, dev->iobase + PCI230_ZGAT_SCE); pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, cmd->scan_begin_arg, -- GitLab From a5948d917c5201fb8c4503d82fb6fc09da7ae726 Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 07:51:36 +0300 Subject: [PATCH 0402/9938] Staging: iio: ad9832: Replace 'unsigned' with 'unsigned int' Replace 'unsigned' with 'unsigned int' to avoid checkpatch.pl warning. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/frequency/ad9832.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 18b27a1984b2..358400b22d33 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -31,7 +31,7 @@ static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout) } static int ad9832_write_frequency(struct ad9832_state *st, - unsigned addr, unsigned long fout) + unsigned int addr, unsigned long fout) { unsigned long regval; -- GitLab From 3261c31c7c2bfbca6db3a7a934ba9341bf65b16d Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 11:43:08 +0300 Subject: [PATCH 0403/9938] staging: iio: accel: adis16240: Replace 'unsigned' with 'unsigned int' Replace 'unsigned' with 'unsigned int' to avoid checkpatch warning. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16240_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 1b5b685a8691..a425e1894863 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -29,13 +29,13 @@ static ssize_t adis16240_spi_read_signed(struct device *dev, struct device_attribute *attr, char *buf, - unsigned bits) + unsigned int bits) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct adis *st = iio_priv(indio_dev); int ret; s16 val = 0; - unsigned shift = 16 - bits; + unsigned int shift = 16 - bits; struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); ret = adis_read_reg_16(st, -- GitLab From 81da8a8913e768d8ce0de9edb5699f3879c1dd51 Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 18:07:22 +0300 Subject: [PATCH 0404/9938] staging: iio: accel: adis16204: Fix 'line over 80 characters' warning Many of the comments in the same lines with #define caused checkpatch warning 'line over 80 characters'. Move all such comments to line before #define. This style is already used in some other .h files in accel: Add blank lines after #define to improve readability. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16204.h | 159 +++++++++++++++++++------- 1 file changed, 118 insertions(+), 41 deletions(-) diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h index 0b23f0b5c52f..cfc4038ffdfb 100644 --- a/drivers/staging/iio/accel/adis16204.h +++ b/drivers/staging/iio/accel/adis16204.h @@ -3,53 +3,130 @@ #define ADIS16204_STARTUP_DELAY 220 /* ms */ -#define ADIS16204_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16204_SUPPLY_OUT 0x02 /* Output, power supply */ -#define ADIS16204_XACCL_OUT 0x04 /* Output, x-axis accelerometer */ -#define ADIS16204_YACCL_OUT 0x06 /* Output, y-axis accelerometer */ -#define ADIS16204_AUX_ADC 0x08 /* Output, auxiliary ADC input */ -#define ADIS16204_TEMP_OUT 0x0A /* Output, temperature */ -#define ADIS16204_X_PEAK_OUT 0x0C /* Twos complement */ -#define ADIS16204_Y_PEAK_OUT 0x0E /* Twos complement */ -#define ADIS16204_XACCL_NULL 0x10 /* Calibration, x-axis acceleration offset null */ -#define ADIS16204_YACCL_NULL 0x12 /* Calibration, y-axis acceleration offset null */ -#define ADIS16204_XACCL_SCALE 0x14 /* X-axis scale factor calibration register */ -#define ADIS16204_YACCL_SCALE 0x16 /* Y-axis scale factor calibration register */ -#define ADIS16204_XY_RSS_OUT 0x18 /* XY combined acceleration (RSS) */ -#define ADIS16204_XY_PEAK_OUT 0x1A /* Peak, XY combined output (RSS) */ -#define ADIS16204_CAP_BUF_1 0x1C /* Capture buffer output register 1 */ -#define ADIS16204_CAP_BUF_2 0x1E /* Capture buffer output register 2 */ -#define ADIS16204_ALM_MAG1 0x20 /* Alarm 1 amplitude threshold */ -#define ADIS16204_ALM_MAG2 0x22 /* Alarm 2 amplitude threshold */ -#define ADIS16204_ALM_CTRL 0x28 /* Alarm control */ -#define ADIS16204_CAPT_PNTR 0x2A /* Capture register address pointer */ -#define ADIS16204_AUX_DAC 0x30 /* Auxiliary DAC data */ -#define ADIS16204_GPIO_CTRL 0x32 /* General-purpose digital input/output control */ -#define ADIS16204_MSC_CTRL 0x34 /* Miscellaneous control */ -#define ADIS16204_SMPL_PRD 0x36 /* Internal sample period (rate) control */ -#define ADIS16204_AVG_CNT 0x38 /* Operation, filter configuration */ -#define ADIS16204_SLP_CNT 0x3A /* Operation, sleep mode control */ -#define ADIS16204_DIAG_STAT 0x3C /* Diagnostics, system status register */ -#define ADIS16204_GLOB_CMD 0x3E /* Operation, system command register */ +/* Flash memory write count */ +#define ADIS16204_FLASH_CNT 0x00 + +/* Output, power supply */ +#define ADIS16204_SUPPLY_OUT 0x02 + +/* Output, x-axis accelerometer */ +#define ADIS16204_XACCL_OUT 0x04 + +/* Output, y-axis accelerometer */ +#define ADIS16204_YACCL_OUT 0x06 + +/* Output, auxiliary ADC input */ +#define ADIS16204_AUX_ADC 0x08 + +/* Output, temperature */ +#define ADIS16204_TEMP_OUT 0x0A + +/* Twos complement */ +#define ADIS16204_X_PEAK_OUT 0x0C +#define ADIS16204_Y_PEAK_OUT 0x0E + +/* Calibration, x-axis acceleration offset null */ +#define ADIS16204_XACCL_NULL 0x10 + +/* Calibration, y-axis acceleration offset null */ +#define ADIS16204_YACCL_NULL 0x12 + +/* X-axis scale factor calibration register */ +#define ADIS16204_XACCL_SCALE 0x14 + +/* Y-axis scale factor calibration register */ +#define ADIS16204_YACCL_SCALE 0x16 + +/* XY combined acceleration (RSS) */ +#define ADIS16204_XY_RSS_OUT 0x18 + +/* Peak, XY combined output (RSS) */ +#define ADIS16204_XY_PEAK_OUT 0x1A + +/* Capture buffer output register 1 */ +#define ADIS16204_CAP_BUF_1 0x1C + +/* Capture buffer output register 2 */ +#define ADIS16204_CAP_BUF_2 0x1E + +/* Alarm 1 amplitude threshold */ +#define ADIS16204_ALM_MAG1 0x20 + +/* Alarm 2 amplitude threshold */ +#define ADIS16204_ALM_MAG2 0x22 + +/* Alarm control */ +#define ADIS16204_ALM_CTRL 0x28 + +/* Capture register address pointer */ +#define ADIS16204_CAPT_PNTR 0x2A + +/* Auxiliary DAC data */ +#define ADIS16204_AUX_DAC 0x30 + +/* General-purpose digital input/output control */ +#define ADIS16204_GPIO_CTRL 0x32 + +/* Miscellaneous control */ +#define ADIS16204_MSC_CTRL 0x34 + +/* Internal sample period (rate) control */ +#define ADIS16204_SMPL_PRD 0x36 + +/* Operation, filter configuration */ +#define ADIS16204_AVG_CNT 0x38 + +/* Operation, sleep mode control */ +#define ADIS16204_SLP_CNT 0x3A + +/* Diagnostics, system status register */ +#define ADIS16204_DIAG_STAT 0x3C + +/* Operation, system command register */ +#define ADIS16204_GLOB_CMD 0x3E /* MSC_CTRL */ -#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST BIT(10) /* Self-test at power-on: 1 = disabled, 0 = enabled */ -#define ADIS16204_MSC_CTRL_SELF_TEST_EN BIT(8) /* Self-test enable */ -#define ADIS16204_MSC_CTRL_DATA_RDY_EN BIT(2) /* Data-ready enable: 1 = enabled, 0 = disabled */ -#define ADIS16204_MSC_CTRL_ACTIVE_HIGH BIT(1) /* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2 BIT(0) /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */ + +/* Self-test at power-on: 1 = disabled, 0 = enabled */ +#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST BIT(10) + +/* Self-test enable */ +#define ADIS16204_MSC_CTRL_SELF_TEST_EN BIT(8) + +/* Data-ready enable: 1 = enabled, 0 = disabled */ +#define ADIS16204_MSC_CTRL_DATA_RDY_EN BIT(2) + +/* Data-ready polarity: 1 = active high, 0 = active low */ +#define ADIS16204_MSC_CTRL_ACTIVE_HIGH BIT(1) + +/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */ +#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2 BIT(0) /* DIAG_STAT */ -#define ADIS16204_DIAG_STAT_ALARM2 BIT(9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16204_DIAG_STAT_ALARM1 BIT(8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag: 1 = error condition, - 0 = normal operation */ -#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */ -#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */ -#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */ -#define ADIS16204_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 2.975 V */ + +/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16204_DIAG_STAT_ALARM2 BIT(9) + +/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16204_DIAG_STAT_ALARM1 BIT(8) + +/* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */ +#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 + +/* SPI communications failure */ +#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT 3 + +/* Flash update failure */ +#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT 2 + +/* Power supply above 3.625 V */ +#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT 1 + +/* Power supply below 2.975 V */ +#define ADIS16204_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ + #define ADIS16204_GLOB_CMD_SW_RESET BIT(7) #define ADIS16204_GLOB_CMD_CLEAR_STAT BIT(4) #define ADIS16204_GLOB_CMD_FACTORY_CAL BIT(1) -- GitLab From a48b2362dd8bcdb3d8c65c7e5eca942bda7762b5 Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 18:08:03 +0300 Subject: [PATCH 0405/9938] staging: iio: accel: adis16203: Fix 'line over 80 characters' warning Many of the comments in the same lines with #define caused checkpatch warning 'line over 80 characters'. Move all such comments to line before #define. This style is already used in some other .h files in accel: Add blank lines after #define to improve readability. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16203.h | 132 +++++++++++++++++++------- 1 file changed, 99 insertions(+), 33 deletions(-) diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h index 6426e38bf006..b483e4e6475b 100644 --- a/drivers/staging/iio/accel/adis16203.h +++ b/drivers/staging/iio/accel/adis16203.h @@ -3,45 +3,111 @@ #define ADIS16203_STARTUP_DELAY 220 /* ms */ -#define ADIS16203_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16203_SUPPLY_OUT 0x02 /* Output, power supply */ -#define ADIS16203_AUX_ADC 0x08 /* Output, auxiliary ADC input */ -#define ADIS16203_TEMP_OUT 0x0A /* Output, temperature */ -#define ADIS16203_XINCL_OUT 0x0C /* Output, x-axis inclination */ -#define ADIS16203_YINCL_OUT 0x0E /* Output, y-axis inclination */ -#define ADIS16203_INCL_NULL 0x18 /* Incline null calibration */ -#define ADIS16203_ALM_MAG1 0x20 /* Alarm 1 amplitude threshold */ -#define ADIS16203_ALM_MAG2 0x22 /* Alarm 2 amplitude threshold */ -#define ADIS16203_ALM_SMPL1 0x24 /* Alarm 1, sample period */ -#define ADIS16203_ALM_SMPL2 0x26 /* Alarm 2, sample period */ -#define ADIS16203_ALM_CTRL 0x28 /* Alarm control */ -#define ADIS16203_AUX_DAC 0x30 /* Auxiliary DAC data */ -#define ADIS16203_GPIO_CTRL 0x32 /* General-purpose digital input/output control */ -#define ADIS16203_MSC_CTRL 0x34 /* Miscellaneous control */ -#define ADIS16203_SMPL_PRD 0x36 /* Internal sample period (rate) control */ -#define ADIS16203_AVG_CNT 0x38 /* Operation, filter configuration */ -#define ADIS16203_SLP_CNT 0x3A /* Operation, sleep mode control */ -#define ADIS16203_DIAG_STAT 0x3C /* Diagnostics, system status register */ -#define ADIS16203_GLOB_CMD 0x3E /* Operation, system command register */ +/* Flash memory write count */ +#define ADIS16203_FLASH_CNT 0x00 + +/* Output, power supply */ +#define ADIS16203_SUPPLY_OUT 0x02 + +/* Output, auxiliary ADC input */ +#define ADIS16203_AUX_ADC 0x08 + +/* Output, temperature */ +#define ADIS16203_TEMP_OUT 0x0A + +/* Output, x-axis inclination */ +#define ADIS16203_XINCL_OUT 0x0C + +/* Output, y-axis inclination */ +#define ADIS16203_YINCL_OUT 0x0E + +/* Incline null calibration */ +#define ADIS16203_INCL_NULL 0x18 + +/* Alarm 1 amplitude threshold */ +#define ADIS16203_ALM_MAG1 0x20 + +/* Alarm 2 amplitude threshold */ +#define ADIS16203_ALM_MAG2 0x22 + +/* Alarm 1, sample period */ +#define ADIS16203_ALM_SMPL1 0x24 + +/* Alarm 2, sample period */ +#define ADIS16203_ALM_SMPL2 0x26 + +/* Alarm control */ +#define ADIS16203_ALM_CTRL 0x28 + +/* Auxiliary DAC data */ +#define ADIS16203_AUX_DAC 0x30 + +/* General-purpose digital input/output control */ +#define ADIS16203_GPIO_CTRL 0x32 + +/* Miscellaneous control */ +#define ADIS16203_MSC_CTRL 0x34 + +/* Internal sample period (rate) control */ +#define ADIS16203_SMPL_PRD 0x36 + +/* Operation, filter configuration */ +#define ADIS16203_AVG_CNT 0x38 + +/* Operation, sleep mode control */ +#define ADIS16203_SLP_CNT 0x3A + +/* Diagnostics, system status register */ +#define ADIS16203_DIAG_STAT 0x3C + +/* Operation, system command register */ +#define ADIS16203_GLOB_CMD 0x3E /* MSC_CTRL */ -#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST BIT(10) /* Self-test at power-on: 1 = disabled, 0 = enabled */ -#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN BIT(9) /* Reverses rotation of both inclination outputs */ -#define ADIS16203_MSC_CTRL_SELF_TEST_EN BIT(8) /* Self-test enable */ -#define ADIS16203_MSC_CTRL_DATA_RDY_EN BIT(2) /* Data-ready enable: 1 = enabled, 0 = disabled */ -#define ADIS16203_MSC_CTRL_ACTIVE_HIGH BIT(1) /* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 BIT(0) /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ + +/* Self-test at power-on: 1 = disabled, 0 = enabled */ +#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST BIT(10) + +/* Reverses rotation of both inclination outputs */ +#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN BIT(9) + +/* Self-test enable */ +#define ADIS16203_MSC_CTRL_SELF_TEST_EN BIT(8) + +/* Data-ready enable: 1 = enabled, 0 = disabled */ +#define ADIS16203_MSC_CTRL_DATA_RDY_EN BIT(2) + +/* Data-ready polarity: 1 = active high, 0 = active low */ +#define ADIS16203_MSC_CTRL_ACTIVE_HIGH BIT(1) + +/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ +#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 BIT(0) /* DIAG_STAT */ -#define ADIS16203_DIAG_STAT_ALARM2 BIT(9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16203_DIAG_STAT_ALARM1 BIT(8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag */ -#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */ -#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */ -#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */ -#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 3.15 V */ + +/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16203_DIAG_STAT_ALARM2 BIT(9) + +/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16203_DIAG_STAT_ALARM1 BIT(8) + +/* Self-test diagnostic error flag */ +#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 + +/* SPI communications failure */ +#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3 + +/* Flash update failure */ +#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2 + +/* Power supply above 3.625 V */ +#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1 + +/* Power supply below 3.15 V */ +#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ + #define ADIS16203_GLOB_CMD_SW_RESET BIT(7) #define ADIS16203_GLOB_CMD_CLEAR_STAT BIT(4) #define ADIS16203_GLOB_CMD_FACTORY_CAL BIT(1) -- GitLab From 0f5c42116ee7c6f9495222bf53370d19003b946b Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 18:08:38 +0300 Subject: [PATCH 0406/9938] staging: iio: accel: adis16201: Fix 'line over 80 characters' warning Many of the comments in the same lines with #define caused checkpatch warning 'line over 80 characters'. Move all such comments to line before #define. This style is already used in some other .h files in accel: Add blank lines after #define to improve readability. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16201.h | 156 +++++++++++++++++++------- 1 file changed, 117 insertions(+), 39 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h index e6b8c9af6e22..64844adcaacd 100644 --- a/drivers/staging/iio/accel/adis16201.h +++ b/drivers/staging/iio/accel/adis16201.h @@ -3,51 +3,129 @@ #define ADIS16201_STARTUP_DELAY 220 /* ms */ -#define ADIS16201_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16201_SUPPLY_OUT 0x02 /* Output, power supply */ -#define ADIS16201_XACCL_OUT 0x04 /* Output, x-axis accelerometer */ -#define ADIS16201_YACCL_OUT 0x06 /* Output, y-axis accelerometer */ -#define ADIS16201_AUX_ADC 0x08 /* Output, auxiliary ADC input */ -#define ADIS16201_TEMP_OUT 0x0A /* Output, temperature */ -#define ADIS16201_XINCL_OUT 0x0C /* Output, x-axis inclination */ -#define ADIS16201_YINCL_OUT 0x0E /* Output, y-axis inclination */ -#define ADIS16201_XACCL_OFFS 0x10 /* Calibration, x-axis acceleration offset */ -#define ADIS16201_YACCL_OFFS 0x12 /* Calibration, y-axis acceleration offset */ -#define ADIS16201_XACCL_SCALE 0x14 /* x-axis acceleration scale factor */ -#define ADIS16201_YACCL_SCALE 0x16 /* y-axis acceleration scale factor */ -#define ADIS16201_XINCL_OFFS 0x18 /* Calibration, x-axis inclination offset */ -#define ADIS16201_YINCL_OFFS 0x1A /* Calibration, y-axis inclination offset */ -#define ADIS16201_XINCL_SCALE 0x1C /* x-axis inclination scale factor */ -#define ADIS16201_YINCL_SCALE 0x1E /* y-axis inclination scale factor */ -#define ADIS16201_ALM_MAG1 0x20 /* Alarm 1 amplitude threshold */ -#define ADIS16201_ALM_MAG2 0x22 /* Alarm 2 amplitude threshold */ -#define ADIS16201_ALM_SMPL1 0x24 /* Alarm 1, sample period */ -#define ADIS16201_ALM_SMPL2 0x26 /* Alarm 2, sample period */ -#define ADIS16201_ALM_CTRL 0x28 /* Alarm control */ -#define ADIS16201_AUX_DAC 0x30 /* Auxiliary DAC data */ -#define ADIS16201_GPIO_CTRL 0x32 /* General-purpose digital input/output control */ -#define ADIS16201_MSC_CTRL 0x34 /* Miscellaneous control */ -#define ADIS16201_SMPL_PRD 0x36 /* Internal sample period (rate) control */ -#define ADIS16201_AVG_CNT 0x38 /* Operation, filter configuration */ -#define ADIS16201_SLP_CNT 0x3A /* Operation, sleep mode control */ -#define ADIS16201_DIAG_STAT 0x3C /* Diagnostics, system status register */ -#define ADIS16201_GLOB_CMD 0x3E /* Operation, system command register */ +/* Flash memory write count */ +#define ADIS16201_FLASH_CNT 0x00 + +/* Output, power supply */ +#define ADIS16201_SUPPLY_OUT 0x02 + +/* Output, x-axis accelerometer */ +#define ADIS16201_XACCL_OUT 0x04 + +/* Output, y-axis accelerometer */ +#define ADIS16201_YACCL_OUT 0x06 + +/* Output, auxiliary ADC input */ +#define ADIS16201_AUX_ADC 0x08 + +/* Output, temperature */ +#define ADIS16201_TEMP_OUT 0x0A + +/* Output, x-axis inclination */ +#define ADIS16201_XINCL_OUT 0x0C + +/* Output, y-axis inclination */ +#define ADIS16201_YINCL_OUT 0x0E + +/* Calibration, x-axis acceleration offset */ +#define ADIS16201_XACCL_OFFS 0x10 + +/* Calibration, y-axis acceleration offset */ +#define ADIS16201_YACCL_OFFS 0x12 + +/* x-axis acceleration scale factor */ +#define ADIS16201_XACCL_SCALE 0x14 + +/* y-axis acceleration scale factor */ +#define ADIS16201_YACCL_SCALE 0x16 + +/* Calibration, x-axis inclination offset */ +#define ADIS16201_XINCL_OFFS 0x18 + +/* Calibration, y-axis inclination offset */ +#define ADIS16201_YINCL_OFFS 0x1A + +/* x-axis inclination scale factor */ +#define ADIS16201_XINCL_SCALE 0x1C + +/* y-axis inclination scale factor */ +#define ADIS16201_YINCL_SCALE 0x1E + +/* Alarm 1 amplitude threshold */ +#define ADIS16201_ALM_MAG1 0x20 + +/* Alarm 2 amplitude threshold */ +#define ADIS16201_ALM_MAG2 0x22 + +/* Alarm 1, sample period */ +#define ADIS16201_ALM_SMPL1 0x24 + +/* Alarm 2, sample period */ +#define ADIS16201_ALM_SMPL2 0x26 + +/* Alarm control */ +#define ADIS16201_ALM_CTRL 0x28 + +/* Auxiliary DAC data */ +#define ADIS16201_AUX_DAC 0x30 + +/* General-purpose digital input/output control */ +#define ADIS16201_GPIO_CTRL 0x32 + +/* Miscellaneous control */ +#define ADIS16201_MSC_CTRL 0x34 + +/* Internal sample period (rate) control */ +#define ADIS16201_SMPL_PRD 0x36 + +/* Operation, filter configuration */ +#define ADIS16201_AVG_CNT 0x38 + +/* Operation, sleep mode control */ +#define ADIS16201_SLP_CNT 0x3A + +/* Diagnostics, system status register */ +#define ADIS16201_DIAG_STAT 0x3C + +/* Operation, system command register */ +#define ADIS16201_GLOB_CMD 0x3E /* MSC_CTRL */ -#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8) /* Self-test enable */ -#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2) /* Data-ready enable: 1 = enabled, 0 = disabled */ -#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1) /* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0) /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ + +/* Self-test enable */ +#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8) + +/* Data-ready enable: 1 = enabled, 0 = disabled */ +#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2) + +/* Data-ready polarity: 1 = active high, 0 = active low */ +#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1) + +/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ +#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0) /* DIAG_STAT */ -#define ADIS16201_DIAG_STAT_ALARM2 BIT(9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16201_DIAG_STAT_ALARM1 BIT(8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 /* SPI communications failure */ -#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2 /* Flash update failure */ -#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */ -#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 /* Power supply below 3.15 V */ + +/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16201_DIAG_STAT_ALARM2 BIT(9) + +/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16201_DIAG_STAT_ALARM1 BIT(8) + +/* SPI communications failure */ +#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 + +/* Flash update failure */ +#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2 + +/* Power supply above 3.625 V */ +#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 + +/* Power supply below 3.15 V */ +#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ + #define ADIS16201_GLOB_CMD_SW_RESET BIT(7) #define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1) -- GitLab From 328bdff8ec599ff1b86e52f5d99d31e55c4fbb0b Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 18:09:21 +0300 Subject: [PATCH 0407/9938] staging: iio: accel: adis16209: Improve readability Lines with #define interlaced with comment lines making a mess. Separate groups of #define-comment with blank lines. Separate section title comments with blank lines. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16209.h | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h index 813698d18ec8..315f1c0c46e8 100644 --- a/drivers/staging/iio/accel/adis16209.h +++ b/drivers/staging/iio/accel/adis16209.h @@ -5,88 +5,127 @@ /* Flash memory write count */ #define ADIS16209_FLASH_CNT 0x00 + /* Output, power supply */ #define ADIS16209_SUPPLY_OUT 0x02 + /* Output, x-axis accelerometer */ #define ADIS16209_XACCL_OUT 0x04 + /* Output, y-axis accelerometer */ #define ADIS16209_YACCL_OUT 0x06 + /* Output, auxiliary ADC input */ #define ADIS16209_AUX_ADC 0x08 + /* Output, temperature */ #define ADIS16209_TEMP_OUT 0x0A + /* Output, x-axis inclination */ #define ADIS16209_XINCL_OUT 0x0C + /* Output, y-axis inclination */ #define ADIS16209_YINCL_OUT 0x0E + /* Output, +/-180 vertical rotational position */ #define ADIS16209_ROT_OUT 0x10 + /* Calibration, x-axis acceleration offset null */ #define ADIS16209_XACCL_NULL 0x12 + /* Calibration, y-axis acceleration offset null */ #define ADIS16209_YACCL_NULL 0x14 + /* Calibration, x-axis inclination offset null */ #define ADIS16209_XINCL_NULL 0x16 + /* Calibration, y-axis inclination offset null */ #define ADIS16209_YINCL_NULL 0x18 + /* Calibration, vertical rotation offset null */ #define ADIS16209_ROT_NULL 0x1A + /* Alarm 1 amplitude threshold */ #define ADIS16209_ALM_MAG1 0x20 + /* Alarm 2 amplitude threshold */ #define ADIS16209_ALM_MAG2 0x22 + /* Alarm 1, sample period */ #define ADIS16209_ALM_SMPL1 0x24 + /* Alarm 2, sample period */ #define ADIS16209_ALM_SMPL2 0x26 + /* Alarm control */ #define ADIS16209_ALM_CTRL 0x28 + /* Auxiliary DAC data */ #define ADIS16209_AUX_DAC 0x30 + /* General-purpose digital input/output control */ #define ADIS16209_GPIO_CTRL 0x32 + /* Miscellaneous control */ #define ADIS16209_MSC_CTRL 0x34 + /* Internal sample period (rate) control */ #define ADIS16209_SMPL_PRD 0x36 + /* Operation, filter configuration */ #define ADIS16209_AVG_CNT 0x38 + /* Operation, sleep mode control */ #define ADIS16209_SLP_CNT 0x3A + /* Diagnostics, system status register */ #define ADIS16209_DIAG_STAT 0x3C + /* Operation, system command register */ #define ADIS16209_GLOB_CMD 0x3E /* MSC_CTRL */ + /* Self-test at power-on: 1 = disabled, 0 = enabled */ #define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST BIT(10) + /* Self-test enable */ #define ADIS16209_MSC_CTRL_SELF_TEST_EN BIT(8) + /* Data-ready enable: 1 = enabled, 0 = disabled */ #define ADIS16209_MSC_CTRL_DATA_RDY_EN BIT(2) + /* Data-ready polarity: 1 = active high, 0 = active low */ #define ADIS16209_MSC_CTRL_ACTIVE_HIGH BIT(1) + /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */ #define ADIS16209_MSC_CTRL_DATA_RDY_DIO2 BIT(0) /* DIAG_STAT */ + /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16209_DIAG_STAT_ALARM2 BIT(9) + /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16209_DIAG_STAT_ALARM1 BIT(8) + /* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */ #define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT 5 + /* SPI communications failure */ #define ADIS16209_DIAG_STAT_SPI_FAIL_BIT 3 + /* Flash update failure */ #define ADIS16209_DIAG_STAT_FLASH_UPT_BIT 2 + /* Power supply above 3.625 V */ #define ADIS16209_DIAG_STAT_POWER_HIGH_BIT 1 + /* Power supply below 3.15 V */ #define ADIS16209_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ + #define ADIS16209_GLOB_CMD_SW_RESET BIT(7) #define ADIS16209_GLOB_CMD_CLEAR_STAT BIT(4) #define ADIS16209_GLOB_CMD_FACTORY_CAL BIT(1) -- GitLab From 7da6ec4870801c7be8cafb861a87697dd842a1d4 Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 18:09:53 +0300 Subject: [PATCH 0408/9938] staging: iio: accel: adis16220: Improve readability Lines with #define interlaced with comment lines making a mess. Separate groups of #define-comment with blank lines. Separate section title comments with blank lines. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16220.h | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h index eab86331124f..31a1268bbfad 100644 --- a/drivers/staging/iio/accel/adis16220.h +++ b/drivers/staging/iio/accel/adis16220.h @@ -7,111 +7,159 @@ /* Flash memory write count */ #define ADIS16220_FLASH_CNT 0x00 + /* Control, acceleration offset adjustment control */ #define ADIS16220_ACCL_NULL 0x02 + /* Control, AIN1 offset adjustment control */ #define ADIS16220_AIN1_NULL 0x04 + /* Control, AIN2 offset adjustment control */ #define ADIS16220_AIN2_NULL 0x06 + /* Output, power supply during capture */ #define ADIS16220_CAPT_SUPPLY 0x0A + /* Output, temperature during capture */ #define ADIS16220_CAPT_TEMP 0x0C + /* Output, peak acceleration during capture */ #define ADIS16220_CAPT_PEAKA 0x0E + /* Output, peak AIN1 level during capture */ #define ADIS16220_CAPT_PEAK1 0x10 + /* Output, peak AIN2 level during capture */ #define ADIS16220_CAPT_PEAK2 0x12 + /* Output, capture buffer for acceleration */ #define ADIS16220_CAPT_BUFA 0x14 + /* Output, capture buffer for AIN1 */ #define ADIS16220_CAPT_BUF1 0x16 + /* Output, capture buffer for AIN2 */ #define ADIS16220_CAPT_BUF2 0x18 + /* Control, capture buffer address pointer */ #define ADIS16220_CAPT_PNTR 0x1A + /* Control, capture control register */ #define ADIS16220_CAPT_CTRL 0x1C + /* Control, capture period (automatic mode) */ #define ADIS16220_CAPT_PRD 0x1E + /* Control, Alarm A, acceleration peak threshold */ #define ADIS16220_ALM_MAGA 0x20 + /* Control, Alarm 1, AIN1 peak threshold */ #define ADIS16220_ALM_MAG1 0x22 + /* Control, Alarm 2, AIN2 peak threshold */ #define ADIS16220_ALM_MAG2 0x24 + /* Control, Alarm S, peak threshold */ #define ADIS16220_ALM_MAGS 0x26 + /* Control, alarm configuration register */ #define ADIS16220_ALM_CTRL 0x28 + /* Control, general I/O configuration */ #define ADIS16220_GPIO_CTRL 0x32 + /* Control, self-test control, AIN configuration */ #define ADIS16220_MSC_CTRL 0x34 + /* Control, digital I/O configuration */ #define ADIS16220_DIO_CTRL 0x36 + /* Control, filter configuration */ #define ADIS16220_AVG_CNT 0x38 + /* Status, system status */ #define ADIS16220_DIAG_STAT 0x3C + /* Control, system commands */ #define ADIS16220_GLOB_CMD 0x3E + /* Status, self-test response */ #define ADIS16220_ST_DELTA 0x40 + /* Lot Identification Code 1 */ #define ADIS16220_LOT_ID1 0x52 + /* Lot Identification Code 2 */ #define ADIS16220_LOT_ID2 0x54 + /* Product identifier; convert to decimal = 16220 */ #define ADIS16220_PROD_ID 0x56 + /* Serial number */ #define ADIS16220_SERIAL_NUM 0x58 #define ADIS16220_CAPTURE_SIZE 2048 /* MSC_CTRL */ + #define ADIS16220_MSC_CTRL_SELF_TEST_EN BIT(8) #define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN1 BIT(1) #define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN2 BIT(0) /* DIO_CTRL */ + #define ADIS16220_MSC_CTRL_DIO2_BUSY_IND (BIT(5) | BIT(4)) #define ADIS16220_MSC_CTRL_DIO1_BUSY_IND (BIT(3) | BIT(2)) #define ADIS16220_MSC_CTRL_DIO2_ACT_HIGH BIT(1) #define ADIS16220_MSC_CTRL_DIO1_ACT_HIGH BIT(0) /* DIAG_STAT */ + /* AIN2 sample > ALM_MAG2 */ #define ADIS16220_DIAG_STAT_ALM_MAG2 BIT(14) + /* AIN1 sample > ALM_MAG1 */ #define ADIS16220_DIAG_STAT_ALM_MAG1 BIT(13) + /* Acceleration sample > ALM_MAGA */ #define ADIS16220_DIAG_STAT_ALM_MAGA BIT(12) + /* Error condition programmed into ALM_MAGS[11:0] and ALM_CTRL[5:4] is true */ #define ADIS16220_DIAG_STAT_ALM_MAGS BIT(11) + /* |Peak value in AIN2 data capture| > ALM_MAG2 */ #define ADIS16220_DIAG_STAT_PEAK_AIN2 BIT(10) + /* |Peak value in AIN1 data capture| > ALM_MAG1 */ #define ADIS16220_DIAG_STAT_PEAK_AIN1 BIT(9) + /* |Peak value in acceleration data capture| > ALM_MAGA */ #define ADIS16220_DIAG_STAT_PEAK_ACCEL BIT(8) + /* Data ready, capture complete */ #define ADIS16220_DIAG_STAT_DATA_RDY BIT(7) + #define ADIS16220_DIAG_STAT_FLASH_CHK BIT(6) + #define ADIS16220_DIAG_STAT_SELF_TEST BIT(5) + /* Capture period violation/interruption */ #define ADIS16220_DIAG_STAT_VIOLATION_BIT 4 + /* SPI communications failure */ #define ADIS16220_DIAG_STAT_SPI_FAIL_BIT 3 + /* Flash update failure */ #define ADIS16220_DIAG_STAT_FLASH_UPT_BIT 2 + /* Power supply above 3.625 V */ #define ADIS16220_DIAG_STAT_POWER_HIGH_BIT 1 + /* Power supply below 3.15 V */ #define ADIS16220_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ + #define ADIS16220_GLOB_CMD_SW_RESET BIT(7) #define ADIS16220_GLOB_CMD_SELF_TEST BIT(2) #define ADIS16220_GLOB_CMD_PWR_DOWN BIT(1) -- GitLab From b075286912ac435f72d864b2a6dae7ec25eece5d Mon Sep 17 00:00:00 2001 From: Svetlana Orlik Date: Tue, 22 Mar 2016 18:10:32 +0300 Subject: [PATCH 0409/9938] staging: iio: accel: adis16240: Improve readability Lines with #define interlaced with comment lines making a mess. Separate groups of #define-comment with blank lines. Separate section title comments with blank lines. Signed-off-by: Svetlana Orlik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16240.h | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h index 66b5ad2f42c5..b2cb37b95913 100644 --- a/drivers/staging/iio/accel/adis16240.h +++ b/drivers/staging/iio/accel/adis16240.h @@ -5,110 +5,160 @@ /* Flash memory write count */ #define ADIS16240_FLASH_CNT 0x00 + /* Output, power supply */ #define ADIS16240_SUPPLY_OUT 0x02 + /* Output, x-axis accelerometer */ #define ADIS16240_XACCL_OUT 0x04 + /* Output, y-axis accelerometer */ #define ADIS16240_YACCL_OUT 0x06 + /* Output, z-axis accelerometer */ #define ADIS16240_ZACCL_OUT 0x08 + /* Output, auxiliary ADC input */ #define ADIS16240_AUX_ADC 0x0A + /* Output, temperature */ #define ADIS16240_TEMP_OUT 0x0C + /* Output, x-axis acceleration peak */ #define ADIS16240_XPEAK_OUT 0x0E + /* Output, y-axis acceleration peak */ #define ADIS16240_YPEAK_OUT 0x10 + /* Output, z-axis acceleration peak */ #define ADIS16240_ZPEAK_OUT 0x12 + /* Output, sum-of-squares acceleration peak */ #define ADIS16240_XYZPEAK_OUT 0x14 + /* Output, Capture Buffer 1, X and Y acceleration */ #define ADIS16240_CAPT_BUF1 0x16 + /* Output, Capture Buffer 2, Z acceleration */ #define ADIS16240_CAPT_BUF2 0x18 + /* Diagnostic, error flags */ #define ADIS16240_DIAG_STAT 0x1A + /* Diagnostic, event counter */ #define ADIS16240_EVNT_CNTR 0x1C + /* Diagnostic, check sum value from firmware test */ #define ADIS16240_CHK_SUM 0x1E + /* Calibration, x-axis acceleration offset adjustment */ #define ADIS16240_XACCL_OFF 0x20 + /* Calibration, y-axis acceleration offset adjustment */ #define ADIS16240_YACCL_OFF 0x22 + /* Calibration, z-axis acceleration offset adjustment */ #define ADIS16240_ZACCL_OFF 0x24 + /* Clock, hour and minute */ #define ADIS16240_CLK_TIME 0x2E + /* Clock, month and day */ #define ADIS16240_CLK_DATE 0x30 + /* Clock, year */ #define ADIS16240_CLK_YEAR 0x32 + /* Wake-up setting, hour and minute */ #define ADIS16240_WAKE_TIME 0x34 + /* Wake-up setting, month and day */ #define ADIS16240_WAKE_DATE 0x36 + /* Alarm 1 amplitude threshold */ #define ADIS16240_ALM_MAG1 0x38 + /* Alarm 2 amplitude threshold */ #define ADIS16240_ALM_MAG2 0x3A + /* Alarm control */ #define ADIS16240_ALM_CTRL 0x3C + /* Capture, external trigger control */ #define ADIS16240_XTRIG_CTRL 0x3E + /* Capture, address pointer */ #define ADIS16240_CAPT_PNTR 0x40 + /* Capture, configuration and control */ #define ADIS16240_CAPT_CTRL 0x42 + /* General-purpose digital input/output control */ #define ADIS16240_GPIO_CTRL 0x44 + /* Miscellaneous control */ #define ADIS16240_MSC_CTRL 0x46 + /* Internal sample period (rate) control */ #define ADIS16240_SMPL_PRD 0x48 + /* System command */ #define ADIS16240_GLOB_CMD 0x4A /* MSC_CTRL */ + /* Enables sum-of-squares output (XYZPEAK_OUT) */ #define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN BIT(15) + /* Enables peak tracking output (XPEAK_OUT, YPEAK_OUT, and ZPEAK_OUT) */ #define ADIS16240_MSC_CTRL_X_Y_ZPEAK_OUT_EN BIT(14) + /* Self-test enable: 1 = apply electrostatic force, 0 = disabled */ #define ADIS16240_MSC_CTRL_SELF_TEST_EN BIT(8) + /* Data-ready enable: 1 = enabled, 0 = disabled */ #define ADIS16240_MSC_CTRL_DATA_RDY_EN BIT(2) + /* Data-ready polarity: 1 = active high, 0 = active low */ #define ADIS16240_MSC_CTRL_ACTIVE_HIGH BIT(1) + /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */ #define ADIS16240_MSC_CTRL_DATA_RDY_DIO2 BIT(0) /* DIAG_STAT */ + /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16240_DIAG_STAT_ALARM2 BIT(9) + /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16240_DIAG_STAT_ALARM1 BIT(8) + /* Capture buffer full: 1 = capture buffer is full */ #define ADIS16240_DIAG_STAT_CPT_BUF_FUL BIT(7) + /* Flash test, checksum flag: 1 = mismatch, 0 = match */ #define ADIS16240_DIAG_STAT_CHKSUM BIT(6) + /* Power-on, self-test flag: 1 = failure, 0 = pass */ #define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT 5 + /* Power-on self-test: 1 = in-progress, 0 = complete */ #define ADIS16240_DIAG_STAT_PWRON_BUSY BIT(4) + /* SPI communications failure */ #define ADIS16240_DIAG_STAT_SPI_FAIL_BIT 3 + /* Flash update failure */ #define ADIS16240_DIAG_STAT_FLASH_UPT_BIT 2 + /* Power supply above 3.625 V */ #define ADIS16240_DIAG_STAT_POWER_HIGH_BIT 1 + /* Power supply below 3.15 V */ #define ADIS16240_DIAG_STAT_POWER_LOW_BIT 0 /* GLOB_CMD */ + #define ADIS16240_GLOB_CMD_RESUME BIT(8) #define ADIS16240_GLOB_CMD_SW_RESET BIT(7) #define ADIS16240_GLOB_CMD_STANDBY BIT(2) -- GitLab From 992aa7b59f62411cb2e5d4192f8598c0f87f12a6 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Tue, 22 Mar 2016 18:20:46 +0900 Subject: [PATCH 0410/9938] staging: dgnc: fix camelcase of SerialDriver and PrintDriver fix the checkpatch.pl warning about CamelCase. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_driver.h | 4 +- drivers/staging/dgnc/dgnc_tty.c | 118 ++++++++++++++--------------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index e4be81b66041..953c891d4064 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -202,9 +202,9 @@ struct dgnc_board { * to our channels. */ - struct tty_driver SerialDriver; + struct tty_driver serial_driver; char SerialName[200]; - struct tty_driver PrintDriver; + struct tty_driver print_driver; char PrintName[200]; bool dgnc_Major_Serial_Registered; diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index bcd2bdfb9c8f..081ac75abc88 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -178,20 +178,20 @@ int dgnc_tty_register(struct dgnc_board *brd) { int rc = 0; - brd->SerialDriver.magic = TTY_DRIVER_MAGIC; + brd->serial_driver.magic = TTY_DRIVER_MAGIC; snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum); - brd->SerialDriver.name = brd->SerialName; - brd->SerialDriver.name_base = 0; - brd->SerialDriver.major = 0; - brd->SerialDriver.minor_start = 0; - brd->SerialDriver.num = brd->maxports; - brd->SerialDriver.type = TTY_DRIVER_TYPE_SERIAL; - brd->SerialDriver.subtype = SERIAL_TYPE_NORMAL; - brd->SerialDriver.init_termios = DgncDefaultTermios; - brd->SerialDriver.driver_name = DRVSTR; - brd->SerialDriver.flags = (TTY_DRIVER_REAL_RAW | + brd->serial_driver.name = brd->SerialName; + brd->serial_driver.name_base = 0; + brd->serial_driver.major = 0; + brd->serial_driver.minor_start = 0; + brd->serial_driver.num = brd->maxports; + brd->serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + brd->serial_driver.subtype = SERIAL_TYPE_NORMAL; + brd->serial_driver.init_termios = DgncDefaultTermios; + brd->serial_driver.driver_name = DRVSTR; + brd->serial_driver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK); @@ -199,28 +199,28 @@ int dgnc_tty_register(struct dgnc_board *brd) * The kernel wants space to store pointers to * tty_struct's and termios's. */ - brd->SerialDriver.ttys = kcalloc(brd->maxports, - sizeof(*brd->SerialDriver.ttys), + brd->serial_driver.ttys = kcalloc(brd->maxports, + sizeof(*brd->serial_driver.ttys), GFP_KERNEL); - if (!brd->SerialDriver.ttys) + if (!brd->serial_driver.ttys) return -ENOMEM; - kref_init(&brd->SerialDriver.kref); - brd->SerialDriver.termios = kcalloc(brd->maxports, - sizeof(*brd->SerialDriver.termios), + kref_init(&brd->serial_driver.kref); + brd->serial_driver.termios = kcalloc(brd->maxports, + sizeof(*brd->serial_driver.termios), GFP_KERNEL); - if (!brd->SerialDriver.termios) + if (!brd->serial_driver.termios) return -ENOMEM; /* * Entry points for driver. Called by the kernel from * tty_io.c and n_tty.c. */ - tty_set_operations(&brd->SerialDriver, &dgnc_tty_ops); + tty_set_operations(&brd->serial_driver, &dgnc_tty_ops); if (!brd->dgnc_Major_Serial_Registered) { /* Register tty devices */ - rc = tty_register_driver(&brd->SerialDriver); + rc = tty_register_driver(&brd->serial_driver); if (rc < 0) { dev_dbg(&brd->pdev->dev, "Can't register tty device (%d)\n", rc); @@ -234,19 +234,19 @@ int dgnc_tty_register(struct dgnc_board *brd) * again, separately so we don't get the LD confused about what major * we are when we get into the dgnc_tty_open() routine. */ - brd->PrintDriver.magic = TTY_DRIVER_MAGIC; + brd->print_driver.magic = TTY_DRIVER_MAGIC; snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum); - brd->PrintDriver.name = brd->PrintName; - brd->PrintDriver.name_base = 0; - brd->PrintDriver.major = brd->SerialDriver.major; - brd->PrintDriver.minor_start = 0x80; - brd->PrintDriver.num = brd->maxports; - brd->PrintDriver.type = TTY_DRIVER_TYPE_SERIAL; - brd->PrintDriver.subtype = SERIAL_TYPE_NORMAL; - brd->PrintDriver.init_termios = DgncDefaultTermios; - brd->PrintDriver.driver_name = DRVSTR; - brd->PrintDriver.flags = (TTY_DRIVER_REAL_RAW | + brd->print_driver.name = brd->PrintName; + brd->print_driver.name_base = 0; + brd->print_driver.major = brd->serial_driver.major; + brd->print_driver.minor_start = 0x80; + brd->print_driver.num = brd->maxports; + brd->print_driver.type = TTY_DRIVER_TYPE_SERIAL; + brd->print_driver.subtype = SERIAL_TYPE_NORMAL; + brd->print_driver.init_termios = DgncDefaultTermios; + brd->print_driver.driver_name = DRVSTR; + brd->print_driver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK); @@ -255,27 +255,27 @@ int dgnc_tty_register(struct dgnc_board *brd) * tty_struct's and termios's. Must be separated from * the Serial Driver so we don't get confused */ - brd->PrintDriver.ttys = kcalloc(brd->maxports, - sizeof(*brd->PrintDriver.ttys), + brd->print_driver.ttys = kcalloc(brd->maxports, + sizeof(*brd->print_driver.ttys), GFP_KERNEL); - if (!brd->PrintDriver.ttys) + if (!brd->print_driver.ttys) return -ENOMEM; - kref_init(&brd->PrintDriver.kref); - brd->PrintDriver.termios = kcalloc(brd->maxports, - sizeof(*brd->PrintDriver.termios), + kref_init(&brd->print_driver.kref); + brd->print_driver.termios = kcalloc(brd->maxports, + sizeof(*brd->print_driver.termios), GFP_KERNEL); - if (!brd->PrintDriver.termios) + if (!brd->print_driver.termios) return -ENOMEM; /* * Entry points for driver. Called by the kernel from * tty_io.c and n_tty.c. */ - tty_set_operations(&brd->PrintDriver, &dgnc_tty_ops); + tty_set_operations(&brd->print_driver, &dgnc_tty_ops); if (!brd->dgnc_Major_TransparentPrint_Registered) { /* Register Transparent Print devices */ - rc = tty_register_driver(&brd->PrintDriver); + rc = tty_register_driver(&brd->print_driver); if (rc < 0) { dev_dbg(&brd->pdev->dev, "Can't register Transparent Print device(%d)\n", @@ -285,9 +285,9 @@ int dgnc_tty_register(struct dgnc_board *brd) brd->dgnc_Major_TransparentPrint_Registered = true; } - dgnc_BoardsByMajor[brd->SerialDriver.major] = brd; - brd->dgnc_Serial_Major = brd->SerialDriver.major; - brd->dgnc_TransparentPrint_Major = brd->PrintDriver.major; + dgnc_BoardsByMajor[brd->serial_driver.major] = brd; + brd->dgnc_Serial_Major = brd->serial_driver.major; + brd->dgnc_TransparentPrint_Major = brd->print_driver.major; return rc; } @@ -364,12 +364,12 @@ int dgnc_tty_init(struct dgnc_board *brd) { struct device *classp; - classp = tty_register_device(&brd->SerialDriver, i, + classp = tty_register_device(&brd->serial_driver, i, &ch->ch_bd->pdev->dev); ch->ch_tun.un_sysfs = classp; dgnc_create_tty_sysfs(&ch->ch_tun, classp); - classp = tty_register_device(&brd->PrintDriver, i, + classp = tty_register_device(&brd->print_driver, i, &ch->ch_bd->pdev->dev); ch->ch_pun.un_sysfs = classp; dgnc_create_tty_sysfs(&ch->ch_pun, classp); @@ -408,39 +408,39 @@ void dgnc_tty_uninit(struct dgnc_board *brd) int i = 0; if (brd->dgnc_Major_Serial_Registered) { - dgnc_BoardsByMajor[brd->SerialDriver.major] = NULL; + dgnc_BoardsByMajor[brd->serial_driver.major] = NULL; brd->dgnc_Serial_Major = 0; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> ch_tun.un_sysfs); - tty_unregister_device(&brd->SerialDriver, i); + tty_unregister_device(&brd->serial_driver, i); } - tty_unregister_driver(&brd->SerialDriver); + tty_unregister_driver(&brd->serial_driver); brd->dgnc_Major_Serial_Registered = false; } if (brd->dgnc_Major_TransparentPrint_Registered) { - dgnc_BoardsByMajor[brd->PrintDriver.major] = NULL; + dgnc_BoardsByMajor[brd->print_driver.major] = NULL; brd->dgnc_TransparentPrint_Major = 0; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> ch_pun.un_sysfs); - tty_unregister_device(&brd->PrintDriver, i); + tty_unregister_device(&brd->print_driver, i); } - tty_unregister_driver(&brd->PrintDriver); + tty_unregister_driver(&brd->print_driver); brd->dgnc_Major_TransparentPrint_Registered = false; } - kfree(brd->SerialDriver.ttys); - brd->SerialDriver.ttys = NULL; - kfree(brd->SerialDriver.termios); - brd->SerialDriver.termios = NULL; - kfree(brd->PrintDriver.ttys); - brd->PrintDriver.ttys = NULL; - kfree(brd->PrintDriver.termios); - brd->PrintDriver.termios = NULL; + kfree(brd->serial_driver.ttys); + brd->serial_driver.ttys = NULL; + kfree(brd->serial_driver.termios); + brd->serial_driver.termios = NULL; + kfree(brd->print_driver.ttys); + brd->print_driver.ttys = NULL; + kfree(brd->print_driver.termios); + brd->print_driver.termios = NULL; } /* -- GitLab From add0f9fefe481cfe719fc8302764e3613de9a054 Mon Sep 17 00:00:00 2001 From: Anchal Jain Date: Tue, 22 Mar 2016 18:01:42 +0530 Subject: [PATCH 0411/9938] staging: wilc1000: Remove camel case in variable names. Remove a problem detect by checkpatch.pl CHECK: Avoid CamelCase: Signed-off-by: Anchal Jain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 6503316314f8..242f82f4d24f 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -24,7 +24,7 @@ struct wilc_wfi_radiotap_cb_hdr { static struct net_device *wilc_wfi_mon; /* global monitor netdev */ -static u8 srcAdd[6]; +static u8 srcadd[6]; static u8 bssid[6]; static u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /** @@ -228,11 +228,11 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, skb->dev = mon_priv->real_ndev; /* Identify if Ethernet or MAC header (data or mgmt) */ - memcpy(srcAdd, &skb->data[10], 6); + memcpy(srcadd, &skb->data[10], 6); memcpy(bssid, &skb->data[16], 6); /* if source address and bssid fields are equal>>Mac header */ /*send it to mgmt frames handler */ - if (!(memcmp(srcAdd, bssid, 6))) { + if (!(memcmp(srcadd, bssid, 6))) { ret = mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len); if (ret) netdev_err(dev, "fail to mgmt tx\n"); -- GitLab From 06884afcf2ab18d314d94456fbf1ac3c860e99bb Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Tue, 22 Mar 2016 18:25:37 +0530 Subject: [PATCH 0412/9938] staging: vt6656: Fixed multiple logical comparisions warnings Using comparison to false and true is error prone. Fixed multiple warnings as per checkpatch guidelines. Signed-off-by: Parth Sane Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 4846a898d39b..95faaeb7432a 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -97,7 +97,7 @@ void vnt_run_command(struct work_struct *work) if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) return; - if (priv->cmd_running != true) + if (!priv->cmd_running) return; switch (priv->command_state) { @@ -143,13 +143,13 @@ void vnt_run_command(struct work_struct *work) if (priv->rx_antenna_sel == 0) { priv->rx_antenna_sel = 1; - if (priv->tx_rx_ant_inv == true) + if (priv->tx_rx_ant_inv) vnt_set_antenna_mode(priv, ANT_RXA); else vnt_set_antenna_mode(priv, ANT_RXB); } else { priv->rx_antenna_sel = 0; - if (priv->tx_rx_ant_inv == true) + if (priv->tx_rx_ant_inv) vnt_set_antenna_mode(priv, ANT_RXB); else vnt_set_antenna_mode(priv, ANT_RXA); @@ -174,7 +174,7 @@ int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd command) ADD_ONE_WITH_WRAP_AROUND(priv->cmd_enqueue_idx, CMD_Q_SIZE); priv->free_cmd_queue--; - if (priv->cmd_running == false) + if (!priv->cmd_running) vnt_cmd_complete(priv); return true; -- GitLab From 4d97b691475060ea6e1345ea7a7c2cba4658a631 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 22 Mar 2016 20:29:13 +0530 Subject: [PATCH 0413/9938] staging: rtl8712: mlme_linux: Clean up tests if NULL returned on failure Some functions like kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/mlme_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/mlme_linux.c b/drivers/staging/rtl8712/mlme_linux.c index e4e4bdee78be..af7c4a47738a 100644 --- a/drivers/staging/rtl8712/mlme_linux.c +++ b/drivers/staging/rtl8712/mlme_linux.c @@ -153,7 +153,7 @@ void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie) buff = NULL; if (authmode == _WPA_IE_ID_) { buff = kzalloc(IW_CUSTOM_MAX, GFP_ATOMIC); - if (buff == NULL) + if (!buff) return; p = buff; p += sprintf(p, "ASSOCINFO(ReqIEs="); -- GitLab From 12f037ece36267c7e7c6e0e65bc1abdd4019fb5d Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 22 Mar 2016 20:28:28 +0530 Subject: [PATCH 0414/9938] staging: rtl8188eu: rtw_cmd: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_cmd.c | 44 ++++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index f08d052f8e52..77485235c615 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -258,11 +258,11 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) return _FAIL; psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); - if (psurveyPara == NULL) { + if (!psurveyPara) { kfree(ph2c); return _FAIL; } @@ -345,7 +345,7 @@ u8 rtw_createbss_cmd(struct adapter *padapter) RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmd == NULL) { + if (!pcmd) { res = _FAIL; goto exit; } @@ -516,7 +516,7 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu /* prepare cmd parameter */ param = kzalloc(sizeof(*param), GFP_KERNEL); - if (param == NULL) { + if (!param) { res = _FAIL; goto exit; } @@ -525,7 +525,7 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu if (enqueue) { /* need enqueue, prepare cmd_obj and enqueue */ cmdobj = kzalloc(sizeof(*cmdobj), GFP_KERNEL); - if (cmdobj == NULL) { + if (!cmdobj) { res = _FAIL; kfree(param); goto exit; @@ -624,20 +624,20 @@ u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue) clear_cam_entry(padapter, entry); } else { ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_ATOMIC); - if (psetstakey_para == NULL) { + if (!psetstakey_para) { kfree(ph2c); res = _FAIL; goto exit; } psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_ATOMIC); - if (psetstakey_rsp == NULL) { + if (!psetstakey_rsp) { kfree(ph2c); kfree(psetstakey_para); res = _FAIL; @@ -671,13 +671,13 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_KERNEL); - if (paddbareq_parm == NULL) { + if (!paddbareq_parm) { kfree(ph2c); res = _FAIL; goto exit; @@ -708,13 +708,13 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); - if (pdrvextra_cmd_parm == NULL) { + if (!pdrvextra_cmd_parm) { kfree(ph2c); res = _FAIL; goto exit; @@ -752,7 +752,7 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue) /* prepare cmd parameter */ setChannelPlan_param = kzalloc(sizeof(struct SetChannelPlan_param), GFP_KERNEL); - if (setChannelPlan_param == NULL) { + if (!setChannelPlan_param) { res = _FAIL; goto exit; } @@ -761,7 +761,7 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue) if (enqueue) { /* need enqueue, prepare cmd_obj and enqueue */ pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmdobj == NULL) { + if (!pcmdobj) { kfree(setChannelPlan_param); res = _FAIL; goto exit; @@ -920,13 +920,13 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) if (enqueue) { ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); - if (pdrvextra_cmd_parm == NULL) { + if (!pdrvextra_cmd_parm) { kfree(ph2c); res = _FAIL; goto exit; @@ -963,13 +963,13 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time) u8 res = _SUCCESS; ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC); - if (pdrvextra_cmd_parm == NULL) { + if (!pdrvextra_cmd_parm) { kfree(ph2c); res = _FAIL; goto exit; @@ -1005,13 +1005,13 @@ u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue) if (enqueue) { ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL); - if (pdrvextra_cmd_parm == NULL) { + if (!pdrvextra_cmd_parm) { kfree(ph2c); res = _FAIL; goto exit; @@ -1103,13 +1103,13 @@ u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) u8 res = _SUCCESS; ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL); - if (pdrvextra_cmd_parm == NULL) { + if (!pdrvextra_cmd_parm) { kfree(ph2c); res = _FAIL; goto exit; -- GitLab From a703f4726583318b24f76bb6bc61d46a5319f248 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 22 Mar 2016 20:27:39 +0530 Subject: [PATCH 0415/9938] staging: rtl8188eu: rtw_mlme_ext: Clean up tests if NULL returned on failure Some functions like kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 86108d4bec0a..439c035fbb7b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4289,12 +4289,12 @@ void report_survey_event(struct adapter *padapter, pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (pcmd_obj == NULL) + if (!pcmd_obj) return; cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header); pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (pevtcmd == NULL) { + if (!pevtcmd) { kfree(pcmd_obj); return; } @@ -4341,12 +4341,12 @@ void report_surveydone_event(struct adapter *padapter) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmd_obj == NULL) + if (!pcmd_obj) return; cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header); pevtcmd = kzalloc(cmdsz, GFP_KERNEL); - if (pevtcmd == NULL) { + if (!pevtcmd) { kfree(pcmd_obj); return; } @@ -4387,12 +4387,12 @@ void report_join_res(struct adapter *padapter, int res) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (pcmd_obj == NULL) + if (!pcmd_obj) return; cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header); pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (pevtcmd == NULL) { + if (!pevtcmd) { kfree(pcmd_obj); return; } @@ -4440,12 +4440,12 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi struct cmd_priv *pcmdpriv = &padapter->cmdpriv; pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmd_obj == NULL) + if (!pcmd_obj) return; cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header); pevtcmd = kzalloc(cmdsz, GFP_KERNEL); - if (pevtcmd == NULL) { + if (!pevtcmd) { kfree(pcmd_obj); return; } @@ -4495,12 +4495,12 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int struct cmd_priv *pcmdpriv = &padapter->cmdpriv; pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmd_obj == NULL) + if (!pcmd_obj) return; cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header); pevtcmd = kzalloc(cmdsz, GFP_KERNEL); - if (pevtcmd == NULL) { + if (!pevtcmd) { kfree(pcmd_obj); return; } @@ -4911,11 +4911,11 @@ void survey_timer_hdl(unsigned long data) } ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (ph2c == NULL) + if (!ph2c) goto exit_survey_timer_hdl; psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); - if (psurveyPara == NULL) { + if (!psurveyPara) { kfree(ph2c); goto exit_survey_timer_hdl; } @@ -5479,7 +5479,7 @@ u8 set_tx_beacon_cmd(struct adapter *padapter) ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } -- GitLab From 6e9aeda3fa6fb1462cfc3d188ecfa734b1af6b21 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 22 Mar 2016 20:26:33 +0530 Subject: [PATCH 0416/9938] staging: rtl8188eu: core: rtw_mlme: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 472cd3f381cb..1456499b84bf 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -1579,13 +1579,13 @@ int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv) int res = _SUCCESS; pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmd == NULL) { + if (!pcmd) { res = _FAIL; /* try again */ goto exit; } psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL); - if (psetauthparm == NULL) { + if (!psetauthparm) { kfree(pcmd); res = _FAIL; goto exit; @@ -1616,11 +1616,11 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in int res = _SUCCESS; pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmd == NULL) + if (!pcmd) return _FAIL; /* try again */ psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL); - if (psetkeyparm == NULL) { + if (!psetkeyparm) { res = _FAIL; goto err_free_cmd; } -- GitLab From 574502caed4c11c7bbb6b4532a8bb544f626f2dc Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 22 Mar 2016 20:25:55 +0530 Subject: [PATCH 0417/9938] staging: rtl8188eu: os_dep: usb_intf: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 8fd608d6027a..11d51a30170f 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -60,7 +60,7 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) struct usb_device *pusbd; pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); - if (pdvobjpriv == NULL) + if (!pdvobjpriv) return NULL; pdvobjpriv->pusbintf = usb_intf; -- GitLab From 4ada295da12e9d0647801577cef37cfc48d41b38 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 22 Mar 2016 20:19:49 +0530 Subject: [PATCH 0418/9938] staging: rtl8188eu: os_dep: ioctl_linux: Clean up tests if NULL returned on failure Some functions like kmalloc/kzalloc return NULL on failure. When NULL represents failure, !x is commonly used. This was done using Coccinelle: @@ expression *e; identifier l1; @@ e = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\)(...); ... - e == NULL + !e Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index eeb1694d8bbe..5672f014cc46 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -2115,13 +2115,13 @@ static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta) u8 res = _SUCCESS; ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (ph2c == NULL) { + if (!ph2c) { res = _FAIL; goto exit; } psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); - if (psetstakey_para == NULL) { + if (!psetstakey_para) { kfree(ph2c); res = _FAIL; goto exit; @@ -2153,12 +2153,12 @@ static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid) DBG_88E("%s\n", __func__); pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (pcmd == NULL) { + if (!pcmd) { res = _FAIL; goto exit; } psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL); - if (psetkeyparm == NULL) { + if (!psetkeyparm) { kfree(pcmd); res = _FAIL; goto exit; -- GitLab From f90272f432f7515044d9e13a6fa2c8bf1ac14838 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Tue, 22 Mar 2016 22:22:41 +0530 Subject: [PATCH 0419/9938] staging: media: omap1: Replace clk_get with devm_clk_get devm_clk_get allocated resources get released when a driver detaches. Replace clk_get with devm_clk_get and remove corresponding data releasing function clk_put from probe and remove functions of a platform device. Also remove an unnecessary label. This change was made with the help of the following Coccinelle semantic patch: @platform@ identifier p, probefn, removefn; @@ struct platform_driver p = { .probe = probefn, .remove = removefn, }; @prb@ identifier platform.probefn, pdev; expression e; @@ probefn(struct platform_device *pdev, ...) { ... e = - clk_get + devm_clk_get (...); ... ?- clk_put(...); ... } @remove depends on prb@ identifier platform.removefn; @@ removefn(...) { ... ?- clk_put(...); ... } Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/omap1/omap1_camera.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/staging/media/omap1/omap1_camera.c b/drivers/staging/media/omap1/omap1_camera.c index bd721e35474a..bd001804ed47 100644 --- a/drivers/staging/media/omap1/omap1_camera.c +++ b/drivers/staging/media/omap1/omap1_camera.c @@ -1576,17 +1576,14 @@ static int omap1_cam_probe(struct platform_device *pdev) goto exit; } - clk = clk_get(&pdev->dev, "armper_ck"); - if (IS_ERR(clk)) { - err = PTR_ERR(clk); - goto exit; - } + clk = devm_clk_get(&pdev->dev, "armper_ck"); + if (IS_ERR(clk)) + return PTR_ERR(clk); pcdev = kzalloc(sizeof(*pcdev) + resource_size(res), GFP_KERNEL); if (!pcdev) { dev_err(&pdev->dev, "Could not allocate pcdev\n"); - err = -ENOMEM; - goto exit_put_clk; + return -ENOMEM; } pcdev->res = res; @@ -1685,8 +1682,6 @@ static int omap1_cam_probe(struct platform_device *pdev) release_mem_region(res->start, resource_size(res)); exit_kfree: kfree(pcdev); -exit_put_clk: - clk_put(clk); exit: return err; } @@ -1709,8 +1704,6 @@ static int omap1_cam_remove(struct platform_device *pdev) res = pcdev->res; release_mem_region(res->start, resource_size(res)); - clk_put(pcdev->clk); - kfree(pcdev); dev_info(&pdev->dev, "OMAP1 Camera Interface driver unloaded\n"); -- GitLab From ba99a0f19ae04820104c1cba11027ec69495879c Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Tue, 22 Mar 2016 22:22:48 +0530 Subject: [PATCH 0420/9938] staging: media: omap1: Replace kzalloc with devm_kzalloc Replace kzalloc with devm_kzalloc and consequently remove kfrees in probe and remove functions of a platform device. As a result of this change, remove unnecessary out of memory message and an unnecessary label. Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/omap1/omap1_camera.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/staging/media/omap1/omap1_camera.c b/drivers/staging/media/omap1/omap1_camera.c index bd001804ed47..8cc4a0a5a835 100644 --- a/drivers/staging/media/omap1/omap1_camera.c +++ b/drivers/staging/media/omap1/omap1_camera.c @@ -1580,11 +1580,10 @@ static int omap1_cam_probe(struct platform_device *pdev) if (IS_ERR(clk)) return PTR_ERR(clk); - pcdev = kzalloc(sizeof(*pcdev) + resource_size(res), GFP_KERNEL); - if (!pcdev) { - dev_err(&pdev->dev, "Could not allocate pcdev\n"); + pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev) + resource_size(res), + GFP_KERNEL); + if (!pcdev) return -ENOMEM; - } pcdev->res = res; pcdev->clk = clk; @@ -1620,10 +1619,8 @@ static int omap1_cam_probe(struct platform_device *pdev) /* * Request the region. */ - if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) { - err = -EBUSY; - goto exit_kfree; - } + if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) + return -EBUSY; base = ioremap(res->start, resource_size(res)); if (!base) { @@ -1680,8 +1677,6 @@ static int omap1_cam_probe(struct platform_device *pdev) iounmap(base); exit_release: release_mem_region(res->start, resource_size(res)); -exit_kfree: - kfree(pcdev); exit: return err; } @@ -1704,8 +1699,6 @@ static int omap1_cam_remove(struct platform_device *pdev) res = pcdev->res; release_mem_region(res->start, resource_size(res)); - kfree(pcdev); - dev_info(&pdev->dev, "OMAP1 Camera Interface driver unloaded\n"); return 0; -- GitLab From 76e543382bd4f488f2a1ca726b7494e6c5f4cc89 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Tue, 22 Mar 2016 22:22:56 +0530 Subject: [PATCH 0421/9938] staging: media: omap1: Switch to devm_ioremap_resource Replace calls to request_mem_region and ioremap with a direct call to devm_ioremap_resource instead and modify error handling. Move the call to platform_get_resource adjacent to the call to devm_ioremap_resource to make the connection between them more clear. Also remove unnecessary labels, variable initialisations and release_mem_region iounmap from probe and remove functions. Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/omap1/omap1_camera.c | 31 +++++----------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/drivers/staging/media/omap1/omap1_camera.c b/drivers/staging/media/omap1/omap1_camera.c index 8cc4a0a5a835..c4450b42a4c4 100644 --- a/drivers/staging/media/omap1/omap1_camera.c +++ b/drivers/staging/media/omap1/omap1_camera.c @@ -1569,9 +1569,8 @@ static int omap1_cam_probe(struct platform_device *pdev) unsigned int irq; int err = 0; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || (int)irq <= 0) { + if ((int)irq <= 0) { err = -ENODEV; goto exit; } @@ -1585,7 +1584,6 @@ static int omap1_cam_probe(struct platform_device *pdev) if (!pcdev) return -ENOMEM; - pcdev->res = res; pcdev->clk = clk; pcdev->pdata = pdev->dev.platform_data; @@ -1616,17 +1614,11 @@ static int omap1_cam_probe(struct platform_device *pdev) INIT_LIST_HEAD(&pcdev->capture); spin_lock_init(&pcdev->lock); - /* - * Request the region. - */ - if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) - return -EBUSY; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); - base = ioremap(res->start, resource_size(res)); - if (!base) { - err = -ENOMEM; - goto exit_release; - } pcdev->irq = irq; pcdev->base = base; @@ -1636,8 +1628,7 @@ static int omap1_cam_probe(struct platform_device *pdev) dma_isr, (void *)pcdev, &pcdev->dma_ch); if (err < 0) { dev_err(&pdev->dev, "Can't request DMA for OMAP1 Camera\n"); - err = -EBUSY; - goto exit_iounmap; + return -EBUSY; } dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_ch); @@ -1673,10 +1664,6 @@ static int omap1_cam_probe(struct platform_device *pdev) free_irq(pcdev->irq, pcdev); exit_free_dma: omap_free_dma(pcdev->dma_ch); -exit_iounmap: - iounmap(base); -exit_release: - release_mem_region(res->start, resource_size(res)); exit: return err; } @@ -1686,7 +1673,6 @@ static int omap1_cam_remove(struct platform_device *pdev) struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct omap1_cam_dev *pcdev = container_of(soc_host, struct omap1_cam_dev, soc_host); - struct resource *res; free_irq(pcdev->irq, pcdev); @@ -1694,11 +1680,6 @@ static int omap1_cam_remove(struct platform_device *pdev) soc_camera_host_unregister(soc_host); - iounmap(pcdev->base); - - res = pcdev->res; - release_mem_region(res->start, resource_size(res)); - dev_info(&pdev->dev, "OMAP1 Camera Interface driver unloaded\n"); return 0; -- GitLab From 62d727c4a99a97e5cc73294d86ccf4b7250bfc3b Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Tue, 22 Mar 2016 22:23:02 +0530 Subject: [PATCH 0422/9938] staging: media: omap1: Replace request_irq with devm_request_irq Replace request_irq with devm_request_irq to get the interrupt for device which is automatically freed on exit. Remove corresponding free_irq from probe and remove functions of a platform device. Also, remove an unnecessary label. Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/omap1/omap1_camera.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/omap1/omap1_camera.c b/drivers/staging/media/omap1/omap1_camera.c index c4450b42a4c4..54b8dd2d2bba 100644 --- a/drivers/staging/media/omap1/omap1_camera.c +++ b/drivers/staging/media/omap1/omap1_camera.c @@ -1640,7 +1640,8 @@ static int omap1_cam_probe(struct platform_device *pdev) /* setup DMA autoinitialization */ omap_dma_link_lch(pcdev->dma_ch, pcdev->dma_ch); - err = request_irq(pcdev->irq, cam_isr, 0, DRIVER_NAME, pcdev); + err = devm_request_irq(&pdev->dev, pcdev->irq, cam_isr, 0, DRIVER_NAME, + pcdev); if (err) { dev_err(&pdev->dev, "Camera interrupt register failed\n"); goto exit_free_dma; @@ -1654,14 +1655,12 @@ static int omap1_cam_probe(struct platform_device *pdev) err = soc_camera_host_register(&pcdev->soc_host); if (err) - goto exit_free_irq; + return err; dev_info(&pdev->dev, "OMAP1 Camera Interface driver loaded\n"); return 0; -exit_free_irq: - free_irq(pcdev->irq, pcdev); exit_free_dma: omap_free_dma(pcdev->dma_ch); exit: @@ -1674,8 +1673,6 @@ static int omap1_cam_remove(struct platform_device *pdev) struct omap1_cam_dev *pcdev = container_of(soc_host, struct omap1_cam_dev, soc_host); - free_irq(pcdev->irq, pcdev); - omap_free_dma(pcdev->dma_ch); soc_camera_host_unregister(soc_host); -- GitLab From 7e221b6088eda47589480bcb29f4aaba44da49c7 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 24 Mar 2016 11:24:02 -0400 Subject: [PATCH 0423/9938] staging: lustre: lnet: revert commit 4671a0266 Commit 4671a0266 change the parameter of the second parameter of cfs_precpt_alloc() from a sizeof type to sizeof type *pointer. This was incorrect in this case and it caused a crash when the LNet layer was brought up in my testing. The reason is cfs_precpt_alloc() creates an array of items where the arrays size is equal to the number of CPTs that exist. Changing to type *pointer only had cfs_precpt_alloc() create an array of pointers instead of an array of actual data structures. This patch reverse this change and adds comments to explain what cfs_precpt_alloc() is actually doing to avoid potential issues like this again. Changelog: v1) Simple revert of the original patch v2) Added in comments to explain why cfs_precpt_alloc() has the arguments it uses. Signed-off-by: James Simmons Cc: Sandhya Bankar Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 89f939092af4..e89c2a1bfa13 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -1965,10 +1965,13 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) /* * premapping can fail if ibd_nmr > 1, so we always create * FMR pool and map-on-demand if premapping failed + * + * cfs_precpt_alloc is creating an array of struct kib_fmr_poolset + * The number of struct kib_fmr_poolsets create is equal to the + * number of CPTs that exist, i.e net->ibn_fmr_ps[cpt]. */ - net->ibn_fmr_ps = cfs_percpt_alloc(lnet_cpt_table(), - sizeof(*net->ibn_fmr_ps)); + sizeof(kib_fmr_poolset_t)); if (!net->ibn_fmr_ps) { CERROR("Failed to allocate FMR pool array\n"); rc = -ENOMEM; @@ -1991,8 +1994,13 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) LASSERT(i == ncpts); create_tx_pool: + /* + * cfs_precpt_alloc is creating an array of struct kib_tx_poolset + * The number of struct kib_tx_poolsets create is equal to the + * number of CPTs that exist, i.e net->ibn_tx_ps[cpt]. + */ net->ibn_tx_ps = cfs_percpt_alloc(lnet_cpt_table(), - sizeof(*net->ibn_tx_ps)); + sizeof(kib_tx_poolset_t)); if (!net->ibn_tx_ps) { CERROR("Failed to allocate tx pool array\n"); rc = -ENOMEM; -- GitLab From ae664e824e3e4a85dbe857815d269f209d998e36 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:48 -0400 Subject: [PATCH 0424/9938] staging: lustre: libcfs: replace LNET_MAX_IOCTL_BUF_LEN with something bigger The size of LNET_MAX_IOCTL_BUF_LEN restricts the size of libcfs ioctl to the maximum needs of the LNet layer. Since libcfs also handles things like debugging we might need to let user land pass more data to or from the kernel than what is possible Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 3 +++ drivers/staging/lustre/lnet/libcfs/module.c | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 5ca99bd6f4e9..c71d1250ff96 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -49,6 +49,9 @@ struct libcfs_ioctl_hdr { __u32 ioc_version; }; +/** max size to copy from userspace */ +#define LIBCFS_IOC_DATA_MAX (128 * 1024) + struct libcfs_ioctl_data { struct libcfs_ioctl_hdr ioc_hdr; diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index cdc640bfdba8..f9f9d59052f8 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -54,9 +54,6 @@ # define DEBUG_SUBSYSTEM S_LNET -#define LNET_MAX_IOCTL_BUF_LEN (sizeof(struct lnet_ioctl_net_config) + \ - sizeof(struct lnet_ioctl_config_data)) - #include "../../include/linux/libcfs/libcfs.h" #include @@ -186,7 +183,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, * do a check here to restrict the size of the memory * to allocate to guard against DoS attacks. */ - if (buf_len > LNET_MAX_IOCTL_BUF_LEN) { + if (buf_len > LIBCFS_IOC_DATA_MAX) { CERROR("LNET: user buffer exceeds kernel buffer\n"); return -EINVAL; } -- GitLab From 74bfc129826a0e2e44821a5aea6ecda43fff5f87 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:49 -0400 Subject: [PATCH 0425/9938] staging: lustre: libcfs: use break in switch options for libcfs_ioctl_handle Instead of just returning for each switch condition use a break. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/module.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index f9f9d59052f8..3fe281064067 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -116,7 +116,7 @@ static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, void __user *arg, struct libcfs_ioctl_hdr *hdr) { struct libcfs_ioctl_data *data = NULL; - int err = -EINVAL; + int err = 0; /* * The libcfs_ioctl_data_adjust() function performs adjustment @@ -134,7 +134,7 @@ static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, switch (cmd) { case IOC_LIBCFS_CLEAR_DEBUG: libcfs_debug_clear_buffer(); - return 0; + break; /* * case IOC_LIBCFS_PANIC: * Handled in arch/cfs_module.c @@ -144,7 +144,7 @@ static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0') return -EINVAL; libcfs_debug_mark_buffer(data->ioc_inlbuf1); - return 0; + break; default: { struct libcfs_ioctl_handler *hand; @@ -161,8 +161,7 @@ static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, } } up_read(&ioctl_list_sem); - break; - } + break; } } return err; -- GitLab From e4efb34a3fc335ea7c837a10f5c03fe446e176d0 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:50 -0400 Subject: [PATCH 0426/9938] staging: lustre: libcfs: merge code from libcfs_ioctl into libcfs_ioctl_getdata This is apart of the cleanup of libcfs_ioctl* code. In this part some of the code in libcfs_ioctl is migrated into libcfs_ioctl_getdata_len() which is renamed libcfs_ioctl_getdata() Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_ioctl.h | 4 +-- .../lustre/lnet/libcfs/linux/linux-module.c | 23 +++++++++++---- drivers/staging/lustre/lnet/libcfs/module.c | 28 ++----------------- 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index c71d1250ff96..9c1deae4e226 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -225,8 +225,8 @@ static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); -int libcfs_ioctl_getdata_len(const struct libcfs_ioctl_hdr __user *arg, - __u32 *buf_len); +int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, + const struct libcfs_ioctl_hdr __user *uparam); int libcfs_ioctl_popdata(void __user *arg, void *buf, int size); int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data); diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index ebc60ac9bb7a..a326ac63c752 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -57,12 +57,13 @@ int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data) return 0; } -int libcfs_ioctl_getdata_len(const struct libcfs_ioctl_hdr __user *arg, - __u32 *len) +int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, + const struct libcfs_ioctl_hdr __user *uhdr) { struct libcfs_ioctl_hdr hdr; + int err = 0; - if (copy_from_user(&hdr, arg, sizeof(hdr))) + if (copy_from_user(&hdr, uhdr, sizeof(uhdr))) return -EFAULT; if (hdr.ioc_version != LIBCFS_IOCTL_VERSION && @@ -72,9 +73,21 @@ int libcfs_ioctl_getdata_len(const struct libcfs_ioctl_hdr __user *arg, return -EINVAL; } - *len = hdr.ioc_len; + if (hdr.ioc_len > LIBCFS_IOC_DATA_MAX) { + CERROR("libcfs ioctl: user buffer is too large %d/%d\n", + hdr.ioc_len, LIBCFS_IOC_DATA_MAX); + return -EINVAL; + } - return 0; + LIBCFS_ALLOC(*hdr_pp, hdr.ioc_len); + if (!*hdr_pp) + return -ENOMEM; + + if (copy_from_user(*hdr_pp, uhdr, hdr.ioc_len)) { + LIBCFS_FREE(*hdr_pp, hdr.ioc_len); + err = -EFAULT; + } + return err; } int libcfs_ioctl_popdata(void __user *arg, void *data, int size) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 3fe281064067..5a20e5325f05 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -172,36 +172,14 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, { struct libcfs_ioctl_hdr *hdr; int err = 0; - __u32 buf_len; - err = libcfs_ioctl_getdata_len(arg, &buf_len); + /* 'cmd' and permissions get checked in our arch-specific caller */ + err = libcfs_ioctl_getdata(&hdr, arg); if (err) return err; - /* - * do a check here to restrict the size of the memory - * to allocate to guard against DoS attacks. - */ - if (buf_len > LIBCFS_IOC_DATA_MAX) { - CERROR("LNET: user buffer exceeds kernel buffer\n"); - return -EINVAL; - } - - LIBCFS_ALLOC_GFP(hdr, buf_len, GFP_KERNEL); - if (!hdr) - return -ENOMEM; - - /* 'cmd' and permissions get checked in our arch-specific caller */ - if (copy_from_user(hdr, arg, buf_len)) { - CERROR("LNET ioctl: data error\n"); - err = -EFAULT; - goto out; - } - err = libcfs_ioctl_handle(pfile, cmd, arg, hdr); - -out: - LIBCFS_FREE(hdr, buf_len); + LIBCFS_FREE(hdr, hdr->ioc_len); return err; } -- GitLab From db469aa868657ccf4944fb8a8bc13b54002b356e Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:51 -0400 Subject: [PATCH 0427/9938] staging: lustre: libcfs: merge libcfs_ioctl_handle into libcfs_ioctl This is apart of the cleanup of libcfs_ioctl* code. In this part we turn libcfs_ioctl_handle into libcfs_ioctl since libcfs_ioctl is now a skeleton function. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/module.c | 37 +++++++++------------ 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 5a20e5325f05..8beb954c152c 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -112,11 +112,17 @@ int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand) } EXPORT_SYMBOL(libcfs_deregister_ioctl); -static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, - void __user *arg, struct libcfs_ioctl_hdr *hdr) +static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, + void __user *arg) { struct libcfs_ioctl_data *data = NULL; - int err = 0; + struct libcfs_ioctl_hdr *hdr; + int err; + + /* 'cmd' and permissions get checked in our arch-specific caller */ + err = libcfs_ioctl_getdata(&hdr, arg); + if (err) + return err; /* * The libcfs_ioctl_data_adjust() function performs adjustment @@ -128,7 +134,7 @@ static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr); err = libcfs_ioctl_data_adjust(data); if (err) - return err; + goto out; } switch (cmd) { @@ -141,8 +147,10 @@ static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, */ case IOC_LIBCFS_MARK_DEBUG: if (!data->ioc_inlbuf1 || - data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0') - return -EINVAL; + data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0') { + err = -EINVAL; + goto out; + } libcfs_debug_mark_buffer(data->ioc_inlbuf1); break; @@ -163,22 +171,7 @@ static int libcfs_ioctl_handle(struct cfs_psdev_file *pfile, unsigned long cmd, up_read(&ioctl_list_sem); break; } } - - return err; -} - -static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, - void __user *arg) -{ - struct libcfs_ioctl_hdr *hdr; - int err = 0; - - /* 'cmd' and permissions get checked in our arch-specific caller */ - err = libcfs_ioctl_getdata(&hdr, arg); - if (err) - return err; - - err = libcfs_ioctl_handle(pfile, cmd, arg, hdr); +out: LIBCFS_FREE(hdr, hdr->ioc_len); return err; } -- GitLab From ea1bffa45b1c4c0f33590850aa1cad9bc298b816 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:52 -0400 Subject: [PATCH 0428/9938] staging: lustre: libcfs: add debugging info for libcfs_ioctl Added some lustre debugging to track down potential future bugs. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/module.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 8beb954c152c..b7575af84f95 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -121,8 +121,11 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, /* 'cmd' and permissions get checked in our arch-specific caller */ err = libcfs_ioctl_getdata(&hdr, arg); - if (err) + if (err) { + CDEBUG_LIMIT(D_ERROR, + "libcfs ioctl: data header error %d\n", err); return err; + } /* * The libcfs_ioctl_data_adjust() function performs adjustment @@ -137,6 +140,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, goto out; } + CDEBUG(D_IOCTL, "libcfs ioctl cmd %lu\n", cmd); switch (cmd) { case IOC_LIBCFS_CLEAR_DEBUG: libcfs_debug_clear_buffer(); -- GitLab From 0d674c10b04f2698c07953476393ead13980fa7f Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:53 -0400 Subject: [PATCH 0429/9938] staging: lustre: libcfs: move comment in libcfs_ioctl Move the comment about libcfs_ioctl_data_adjust to the section where libcfs_ioctl_data_adjust is actually called. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/module.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index b7575af84f95..4c3fe8796545 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -127,13 +127,13 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, return err; } - /* - * The libcfs_ioctl_data_adjust() function performs adjustment - * operations on the libcfs_ioctl_data structure to make - * it usable by the code. This doesn't need to be called - * for new data structures added. - */ if (hdr->ioc_version == LIBCFS_IOCTL_VERSION) { + /* + * The libcfs_ioctl_data_adjust() function performs adjustment + * operations on the libcfs_ioctl_data structure to make + * it usable by the code. This doesn't need to be called + * for new data structures added. + */ data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr); err = libcfs_ioctl_data_adjust(data); if (err) -- GitLab From 4e31dad14dfec5746bdaa593db0cf0d8a6736b1c Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:54 -0400 Subject: [PATCH 0430/9938] staging: lustre: libcfs: test if data is NULL Make sure data is not NULL otherwise we get an oops when using the IOC_LIBCFS_MARK_DEBUG ioctl. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 4c3fe8796545..cce6ce35bd80 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -150,7 +150,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, * Handled in arch/cfs_module.c */ case IOC_LIBCFS_MARK_DEBUG: - if (!data->ioc_inlbuf1 || + if (!data || !data->ioc_inlbuf1 || data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0') { err = -EINVAL; goto out; -- GitLab From 77f716360939767016e2ceab17f8234d0cabc61b Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:55 -0400 Subject: [PATCH 0431/9938] staging: lustre: libcfs: invert test condition for libcfs_ioctl Invert the test of error returned by the handle_ioctl pointer. This reduces the code by one indentation level. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/module.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index cce6ce35bd80..97fc905ad78a 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -165,12 +165,13 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, down_read(&ioctl_list_sem); list_for_each_entry(hand, &ioctl_list, item) { err = hand->handle_ioctl(cmd, hdr); - if (err != -EINVAL) { - if (err == 0) - err = libcfs_ioctl_popdata(arg, - hdr, hdr->ioc_len); - break; - } + if (err == -EINVAL) + continue; + + if (!err) + err = libcfs_ioctl_popdata(arg, hdr, + hdr->ioc_len); + break; } up_read(&ioctl_list_sem); break; } -- GitLab From 6d0aeaa36178382898a15836c8c6542d92527a8c Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:56 -0400 Subject: [PATCH 0432/9938] staging: lustre: libcfs: update error messages in linux-module.c The error message are for libcfs layer not LNet. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index a326ac63c752..35e2fcf238e1 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -43,7 +43,7 @@ int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data) { if (libcfs_ioctl_is_invalid(data)) { - CERROR("LNET: ioctl not correctly formatted\n"); + CERROR("libcfs ioctl: parameter not correctly formatted\n"); return -EINVAL; } @@ -68,7 +68,7 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, if (hdr.ioc_version != LIBCFS_IOCTL_VERSION && hdr.ioc_version != LIBCFS_IOCTL_VERSION2) { - CERROR("LNET: version mismatch expected %#x, got %#x\n", + CERROR("libcfs ioctl: version mismatch expected %#x, got %#x\n", LIBCFS_IOCTL_VERSION, hdr.ioc_version); return -EINVAL; } -- GitLab From ed2f549dc0f687f5d454cb20754340e83e5b9c4f Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:57 -0400 Subject: [PATCH 0433/9938] staging: lustre: libcfs: test if userland data is to small Ensure that user land data is at least the smallest size. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-module.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index 35e2fcf238e1..ae058956f209 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -73,6 +73,11 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, return -EINVAL; } + if (hdr.ioc_len < sizeof(struct libcfs_ioctl_data)) { + CERROR("libcfs ioctl: user buffer too small for ioctl\n"); + return -EINVAL; + } + if (hdr.ioc_len > LIBCFS_IOC_DATA_MAX) { CERROR("libcfs ioctl: user buffer is too large %d/%d\n", hdr.ioc_len, LIBCFS_IOC_DATA_MAX); -- GitLab From da4e5898375a100e6c1be984ceee84fb5911b6f6 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:58 -0400 Subject: [PATCH 0434/9938] staging: lustre: lnet: make sure lnet data not greater than LIBCFS_IOC_DATA_MAX Fail to compile if largest LNet user land data structures passed to kernel are larger than LIBCFS_IOC_DATA_MAX Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/api-ni.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 8764755544c9..f825784b79e1 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1864,6 +1864,10 @@ LNetCtl(unsigned int cmd, void *arg) int rc; unsigned long secs_passed; + BUILD_BUG_ON(LIBCFS_IOC_DATA_MAX < + sizeof(struct lnet_ioctl_net_config) + + sizeof(struct lnet_ioctl_config_data)); + switch (cmd) { case IOC_LIBCFS_GET_NI: rc = LNetGetId(data->ioc_count, &id); -- GitLab From a0d5fce76d69f574df1577d20dc3b25f99031167 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Tue, 22 Mar 2016 19:03:59 -0400 Subject: [PATCH 0435/9938] staging: lustre: simple cleanup in obd_ioctl_popdata Code simplification for obd_ioctl_popdata. Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 8eddf206f1ed..2cd4522462d9 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -158,9 +158,7 @@ int obd_ioctl_popdata(void __user *arg, void *data, int len) { int err; - err = copy_to_user(arg, data, len); - if (err) - err = -EFAULT; + err = copy_to_user(arg, data, len) ? -EFAULT : 0; return err; } EXPORT_SYMBOL(obd_ioctl_popdata); -- GitLab From 7401a6b067bcea2469cb0d6bdae34d8dcafc2a0d Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:00 -0400 Subject: [PATCH 0436/9938] staging: lustre: libcfs: change variable name Change arg to uparam name for libcfs_ioctl(). Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5435 Reviewed-on: http://review.whamcloud.com/11313 Reviewed-by: Bobi Jam Reviewed-by: Johann Lombardi Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 97fc905ad78a..839145e80d98 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -113,14 +113,14 @@ int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand) EXPORT_SYMBOL(libcfs_deregister_ioctl); static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, - void __user *arg) + void __user *uparam) { struct libcfs_ioctl_data *data = NULL; struct libcfs_ioctl_hdr *hdr; int err; /* 'cmd' and permissions get checked in our arch-specific caller */ - err = libcfs_ioctl_getdata(&hdr, arg); + err = libcfs_ioctl_getdata(&hdr, uparam); if (err) { CDEBUG_LIMIT(D_ERROR, "libcfs ioctl: data header error %d\n", err); @@ -169,7 +169,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, continue; if (!err) - err = libcfs_ioctl_popdata(arg, hdr, + err = libcfs_ioctl_popdata(uparam, hdr, hdr->ioc_len); break; } -- GitLab From 4801919d0825fa35a7290c3625464f460083f9d9 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 22 Mar 2016 19:04:01 -0400 Subject: [PATCH 0437/9938] staging: lustre: libcfs: remove libcfsutil.h in comment The header libcfsutil.h has been long gone in the upstream client. Replace libcfsutil.h reference to the current user land header instead. Signed-off-by: John L. Hammond Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/14180 Reviewed-by: Dmitry Eremin Reviewed-by: frank zago Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 9c1deae4e226..01bf8d6dedc6 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -34,7 +34,7 @@ * libcfs/include/libcfs/libcfs_ioctl.h * * Low-level ioctl data structures. Kernel ioctl functions declared here, - * and user space functions are in libcfsutil_ioctl.h. + * and user space functions are in libcfs/util/ioctl.h. * */ -- GitLab From 7b54d08b01e61d35d57cb5cdbaf6cd02babcdf17 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 22 Mar 2016 19:04:02 -0400 Subject: [PATCH 0438/9938] staging: lustre: libcfs: move libcfs_ioctl_handler stuff to libcfs.h Move all the libcfs_ioctl_handler code from libcfs_ioctl.h to libcfs.h. The header libcfs_ioctl.h is a uapi header so their is no reason to keep kernel internals in that header. Signed-off-by: John L. Hammond Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/14180 Reviewed-by: Dmitry Eremin Reviewed-by: frank zago Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs.h | 14 ++++++++++++++ .../lustre/include/linux/libcfs/libcfs_ioctl.h | 13 ------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 40af75c4201a..0ce52deac625 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -119,6 +119,20 @@ void cfs_get_random_bytes(void *buf, int size); #include "libcfs_fail.h" #include "libcfs_crypto.h" +struct libcfs_ioctl_handler { + struct list_head item; + int (*handle_ioctl)(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); +}; + +#define DECLARE_IOCTL_HANDLER(ident, func) \ + struct libcfs_ioctl_handler ident = { \ + .item = LIST_HEAD_INIT(ident.item), \ + .handle_ioctl = func \ + } + +int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); +int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); + /* container_of depends on "likely" which is defined in libcfs_private.h */ static inline void *__container_of(void *ptr, unsigned long shift) { diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 01bf8d6dedc6..d167d2eaa84d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -91,17 +91,6 @@ do { \ data.ioc_len = sizeof(data); \ } while (0) -struct libcfs_ioctl_handler { - struct list_head item; - int (*handle_ioctl)(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); -}; - -#define DECLARE_IOCTL_HANDLER(ident, func) \ - struct libcfs_ioctl_handler ident = { \ - /* .item = */ LIST_HEAD_INIT(ident.item), \ - /* .handle_ioctl = */ func \ - } - /* FIXME check conflict with lustre_lib.h */ #define LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long) @@ -223,8 +212,6 @@ static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) return 0; } -int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); -int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, const struct libcfs_ioctl_hdr __user *uparam); int libcfs_ioctl_popdata(void __user *arg, void *buf, int size); -- GitLab From 5206726ad8e286a09e73ae4a542de47f96d62f27 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 22 Mar 2016 19:04:03 -0400 Subject: [PATCH 0439/9938] staging: lustre: libcfs: remove libcfs_ioctl_popdata wrapper Lets just use copy_to_user() directly instead of having a wrapper function. Signed-off-by: John L. Hammond Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/14180 Reviewed-by: Dmitry Eremin Reviewed-by: frank zago Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 1 - drivers/staging/lustre/lnet/libcfs/linux/linux-module.c | 7 ------- drivers/staging/lustre/lnet/libcfs/module.c | 7 ++++--- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index d167d2eaa84d..45d1165a6ed4 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -214,7 +214,6 @@ static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, const struct libcfs_ioctl_hdr __user *uparam); -int libcfs_ioctl_popdata(void __user *arg, void *buf, int size); int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data); #endif /* __LIBCFS_IOCTL_H__ */ diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index ae058956f209..890a4588049d 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -95,13 +95,6 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, return err; } -int libcfs_ioctl_popdata(void __user *arg, void *data, int size) -{ - if (copy_to_user(arg, data, size)) - return -EFAULT; - return 0; -} - static int libcfs_psdev_open(struct inode *inode, struct file *file) { diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 839145e80d98..74b92369ac02 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -168,9 +168,10 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, if (err == -EINVAL) continue; - if (!err) - err = libcfs_ioctl_popdata(uparam, hdr, - hdr->ioc_len); + if (!err) { + if (copy_to_user(uparam, hdr, hdr->ioc_len)) + err = -EFAULT; + } break; } up_read(&ioctl_list_sem); -- GitLab From 68cf5b83659ecee9ad8a14d8ce74e9c5df6d0956 Mon Sep 17 00:00:00 2001 From: Parinay Kondekar Date: Tue, 22 Mar 2016 19:04:04 -0400 Subject: [PATCH 0440/9938] staging:lustre: remove last bits of the IOC_LIBCFS_PANIC ioctl A few pieces still exist for the IOC_LIBCFS_PANIC ioctl. Remove these last bits to prevent old tools from using them. The latest lustre utilities no longer use this ioctl. Signed-off-by: Parinay Kondekar Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5844 Reviewed-on: http://review.whamcloud.com/17492 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 2 +- drivers/staging/lustre/lnet/libcfs/linux/linux-module.c | 9 --------- drivers/staging/lustre/lnet/libcfs/module.c | 5 +---- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 45d1165a6ed4..d158cd12a19e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -97,7 +97,7 @@ do { \ #define IOC_LIBCFS_TYPE 'e' #define IOC_LIBCFS_MIN_NR 30 /* libcfs ioctls */ -#define IOC_LIBCFS_PANIC _IOWR('e', 30, long) +/* IOC_LIBCFS_PANIC obsolete in 2.8.0, was _IOWR('e', 30, IOCTL_LIBCFS_TYPE) */ #define IOC_LIBCFS_CLEAR_DEBUG _IOWR('e', 31, long) #define IOC_LIBCFS_MARK_DEBUG _IOWR('e', 32, long) #define IOC_LIBCFS_MEMHOG _IOWR('e', 36, long) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index 890a4588049d..d801d8770cf7 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -141,15 +141,6 @@ static long libcfs_ioctl(struct file *file, return -EINVAL; } - /* Handle platform-dependent IOC requests */ - switch (cmd) { - case IOC_LIBCFS_PANIC: - if (!capable(CFS_CAP_SYS_BOOT)) - return -EPERM; - panic("debugctl-invoked panic"); - return 0; - } - if (libcfs_psdev_ops.p_ioctl) rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void __user *)arg); else diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 74b92369ac02..3a88e6447d3b 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -145,10 +145,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, case IOC_LIBCFS_CLEAR_DEBUG: libcfs_debug_clear_buffer(); break; - /* - * case IOC_LIBCFS_PANIC: - * Handled in arch/cfs_module.c - */ + case IOC_LIBCFS_MARK_DEBUG: if (!data || !data->ioc_inlbuf1 || data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0') { -- GitLab From c878547fdfa4f8023930cd43b75023f3061f9aa6 Mon Sep 17 00:00:00 2001 From: Parinay Kondekar Date: Tue, 22 Mar 2016 19:04:05 -0400 Subject: [PATCH 0441/9938] staging:lustre: remove the IOC_LIBCFS_MEMHOG ioctl The IOC_LIBCFS_MEMHOG is not needed so remove the last bits. Signed-off-by: Parinay Kondekar Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5844 Reviewed-on: http://review.whamcloud.com/17492 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index d158cd12a19e..2e4e31b2cc41 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -100,7 +100,7 @@ do { \ /* IOC_LIBCFS_PANIC obsolete in 2.8.0, was _IOWR('e', 30, IOCTL_LIBCFS_TYPE) */ #define IOC_LIBCFS_CLEAR_DEBUG _IOWR('e', 31, long) #define IOC_LIBCFS_MARK_DEBUG _IOWR('e', 32, long) -#define IOC_LIBCFS_MEMHOG _IOWR('e', 36, long) +/* IOC_LIBCFS_MEMHOG obsolete in 2.8.0, was _IOWR('e', 36, IOCTL_LIBCFS_TYPE) */ /* lnet ioctls */ #define IOC_LIBCFS_GET_NI _IOWR('e', 50, long) #define IOC_LIBCFS_FAIL_NID _IOWR('e', 51, long) -- GitLab From 4678d183caf1b8a68860ca07fad95d9c6de14cc3 Mon Sep 17 00:00:00 2001 From: Parinay Kondekar Date: Tue, 22 Mar 2016 19:04:06 -0400 Subject: [PATCH 0442/9938] staging:lustre: remove libcfs_psdev_[open|release] With struct libcfs_device_userstate gone we can remove the remaining code of libcfs_psdev_ops.p_[open|close] as well as the libcfs_psdev_[open|release] functions. Signed-off-by: Parinay Kondekar Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5844 Reviewed-on: http://review.whamcloud.com/17492 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs.h | 2 -- .../lustre/lnet/libcfs/linux/linux-module.c | 32 +------------------ drivers/staging/lustre/lnet/libcfs/module.c | 16 ---------- 3 files changed, 1 insertion(+), 49 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 0ce52deac625..5d228e5b438e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -73,8 +73,6 @@ struct cfs_psdev_file { }; struct cfs_psdev_ops { - int (*p_open)(unsigned long, void *); - int (*p_close)(unsigned long, void *); int (*p_read)(struct cfs_psdev_file *, char *, unsigned long); int (*p_write)(struct cfs_psdev_file *, char *, unsigned long); int (*p_ioctl)(struct cfs_psdev_file *, unsigned long, void __user *); diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index d801d8770cf7..633d76bec63c 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -95,35 +95,6 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, return err; } -static int -libcfs_psdev_open(struct inode *inode, struct file *file) -{ - int rc = 0; - - if (!inode) - return -EINVAL; - if (libcfs_psdev_ops.p_open) - rc = libcfs_psdev_ops.p_open(0, NULL); - else - return -EPERM; - return rc; -} - -/* called when closing /dev/device */ -static int -libcfs_psdev_release(struct inode *inode, struct file *file) -{ - int rc = 0; - - if (!inode) - return -EINVAL; - if (libcfs_psdev_ops.p_close) - rc = libcfs_psdev_ops.p_close(0, NULL); - else - rc = -EPERM; - return rc; -} - static long libcfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -149,9 +120,8 @@ static long libcfs_ioctl(struct file *file, } static const struct file_operations libcfs_fops = { + .owner = THIS_MODULE, .unlocked_ioctl = libcfs_ioctl, - .open = libcfs_psdev_open, - .release = libcfs_psdev_release, }; struct miscdevice libcfs_dev = { diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 3a88e6447d3b..4d38aafb0b18 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -65,20 +65,6 @@ static struct dentry *lnet_debugfs_root; -/* called when opening /dev/device */ -static int libcfs_psdev_open(unsigned long flags, void *args) -{ - try_module_get(THIS_MODULE); - return 0; -} - -/* called when closing /dev/device */ -static int libcfs_psdev_release(unsigned long flags, void *args) -{ - module_put(THIS_MODULE); - return 0; -} - static DECLARE_RWSEM(ioctl_list_sem); static LIST_HEAD(ioctl_list); @@ -180,8 +166,6 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, } struct cfs_psdev_ops libcfs_psdev_ops = { - libcfs_psdev_open, - libcfs_psdev_release, NULL, NULL, libcfs_ioctl -- GitLab From ae272a48a16b53f77215749a68777c6c89ec9925 Mon Sep 17 00:00:00 2001 From: Parinay Kondekar Date: Tue, 22 Mar 2016 19:04:07 -0400 Subject: [PATCH 0443/9938] staging:lustre: call libcfs_ioctl directly No reason to go through the cfs_psdev_ops abstract to call libcfs_ioctl. Just call libcfs_ioctl directly. Signed-off-by: Parinay Kondekar Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5844 Reviewed-on: http://review.whamcloud.com/17492 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs.h | 3 ++- .../staging/lustre/lnet/libcfs/linux/linux-module.c | 13 ++++--------- drivers/staging/lustre/lnet/libcfs/module.c | 5 ++--- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 5d228e5b438e..592ad31fbfac 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -75,7 +75,6 @@ struct cfs_psdev_file { struct cfs_psdev_ops { int (*p_read)(struct cfs_psdev_file *, char *, unsigned long); int (*p_write)(struct cfs_psdev_file *, char *, unsigned long); - int (*p_ioctl)(struct cfs_psdev_file *, unsigned long, void __user *); }; /* @@ -131,6 +130,8 @@ struct libcfs_ioctl_handler { int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); +int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg); + /* container_of depends on "likely" which is defined in libcfs_private.h */ static inline void *__container_of(void *ptr, unsigned long shift) { diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index 633d76bec63c..6f35a80e20a1 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -95,11 +95,10 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, return err; } -static long libcfs_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long +libcfs_psdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cfs_psdev_file pfile; - int rc = 0; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -112,16 +111,12 @@ static long libcfs_ioctl(struct file *file, return -EINVAL; } - if (libcfs_psdev_ops.p_ioctl) - rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void __user *)arg); - else - rc = -EPERM; - return rc; + return libcfs_ioctl(&pfile, cmd, (void __user *)arg); } static const struct file_operations libcfs_fops = { .owner = THIS_MODULE, - .unlocked_ioctl = libcfs_ioctl, + .unlocked_ioctl = libcfs_psdev_ioctl, }; struct miscdevice libcfs_dev = { diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 4d38aafb0b18..4af455733a3b 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -98,8 +98,8 @@ int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand) } EXPORT_SYMBOL(libcfs_deregister_ioctl); -static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, - void __user *uparam) +int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, + void __user *uparam) { struct libcfs_ioctl_data *data = NULL; struct libcfs_ioctl_hdr *hdr; @@ -168,7 +168,6 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, struct cfs_psdev_ops libcfs_psdev_ops = { NULL, NULL, - libcfs_ioctl }; int lprocfs_call_handler(void *data, int write, loff_t *ppos, -- GitLab From 89010fbc22162708c39447129580c4a47b03260e Mon Sep 17 00:00:00 2001 From: Parinay Kondekar Date: Tue, 22 Mar 2016 19:04:08 -0400 Subject: [PATCH 0444/9938] staging:lustre: remove libcfs pseudo device abstraction With the libcfs ioctl cleanup we no longer need the libcfs pseudo device abstraction. Signed-off-by: Parinay Kondekar Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5844 Reviewed-on: http://review.whamcloud.com/17492 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs.h | 22 +------------------ .../lustre/lnet/libcfs/linux/linux-module.c | 4 +--- drivers/staging/lustre/lnet/libcfs/module.c | 8 +------ 3 files changed, 3 insertions(+), 31 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 592ad31fbfac..1cd18790d22e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -59,24 +59,6 @@ #define LNET_ACCEPTOR_MIN_RESERVED_PORT 512 #define LNET_ACCEPTOR_MAX_RESERVED_PORT 1023 -/* - * libcfs pseudo device operations - * - * It's just draft now. - */ - -struct cfs_psdev_file { - unsigned long off; - void *private_data; - unsigned long reserved1; - unsigned long reserved2; -}; - -struct cfs_psdev_ops { - int (*p_read)(struct cfs_psdev_file *, char *, unsigned long); - int (*p_write)(struct cfs_psdev_file *, char *, unsigned long); -}; - /* * Drop into debugger, if possible. Implementation is provided by platform. */ @@ -130,7 +112,7 @@ struct libcfs_ioctl_handler { int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); -int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg); +int libcfs_ioctl(unsigned long cmd, void *arg); /* container_of depends on "likely" which is defined in libcfs_private.h */ static inline void *__container_of(void *ptr, unsigned long shift) @@ -156,8 +138,6 @@ extern struct miscdevice libcfs_dev; extern char lnet_upcall[1024]; extern char lnet_debug_log_upcall[1024]; -extern struct cfs_psdev_ops libcfs_psdev_ops; - extern struct cfs_wi_sched *cfs_sched_rehash; struct lnet_debugfs_symlink_def { diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index 6f35a80e20a1..7634551afed3 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -98,8 +98,6 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, static long libcfs_psdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct cfs_psdev_file pfile; - if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -111,7 +109,7 @@ libcfs_psdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; } - return libcfs_ioctl(&pfile, cmd, (void __user *)arg); + return libcfs_ioctl(cmd, (void __user *)arg); } static const struct file_operations libcfs_fops = { diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 4af455733a3b..49c2d03dc9de 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -98,8 +98,7 @@ int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand) } EXPORT_SYMBOL(libcfs_deregister_ioctl); -int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, - void __user *uparam) +int libcfs_ioctl(unsigned long cmd, void __user *uparam) { struct libcfs_ioctl_data *data = NULL; struct libcfs_ioctl_hdr *hdr; @@ -165,11 +164,6 @@ int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, return err; } -struct cfs_psdev_ops libcfs_psdev_ops = { - NULL, - NULL, -}; - int lprocfs_call_handler(void *data, int write, loff_t *ppos, void __user *buffer, size_t *lenp, int (*handler)(void *data, int write, loff_t pos, -- GitLab From b02e9d87a76501f2782436c3d5c8d2dde63023dc Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:09 -0400 Subject: [PATCH 0445/9938] staging: lustre: libcfs: removal all userland only macros from libcfs_ioctl.h All the macros in libcfs_ioctl.h that is needed by user land have been moved into the lustre utilities software stack. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 2e4e31b2cc41..e109a4b0f45a 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -76,21 +76,12 @@ struct libcfs_ioctl_data { char ioc_bulk[0]; }; -#define ioc_priority ioc_u32[0] - struct libcfs_debug_ioctl_data { struct libcfs_ioctl_hdr hdr; unsigned int subs; unsigned int debug; }; -#define LIBCFS_IOC_INIT(data) \ -do { \ - memset(&data, 0, sizeof(data)); \ - data.ioc_version = LIBCFS_IOCTL_VERSION; \ - data.ioc_len = sizeof(data); \ -} while (0) - /* FIXME check conflict with lustre_lib.h */ #define LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long) -- GitLab From cfec4b5c66fa3412b712a6409c2c3d4192faea45 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:10 -0400 Subject: [PATCH 0446/9938] staging: lustre: libcfs: migrate inline functions to source file Move large inline functions out of libcfs_ioctl.h to the source file linux-module.c belonging to libcfs. This code is only used by the core of libcfs and such inline functions don't belong in a uapi header file. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_ioctl.h | 65 ------------------- .../lustre/lnet/libcfs/linux/linux-module.c | 65 +++++++++++++++++++ 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index e109a4b0f45a..3af13e43169f 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -138,71 +138,6 @@ struct libcfs_debug_ioctl_data { #define IOC_LIBCFS_GET_LNET_STATS _IOWR(IOC_LIBCFS_TYPE, 91, IOCTL_CONFIG_SIZE) #define IOC_LIBCFS_MAX_NR 91 -static inline int libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) -{ - int len = sizeof(*data); - - len += cfs_size_round(data->ioc_inllen1); - len += cfs_size_round(data->ioc_inllen2); - return len; -} - -static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) -{ - if (data->ioc_hdr.ioc_len > (1 << 30)) { - CERROR("LIBCFS ioctl: ioc_len larger than 1<<30\n"); - return 1; - } - if (data->ioc_inllen1 > (1<<30)) { - CERROR("LIBCFS ioctl: ioc_inllen1 larger than 1<<30\n"); - return 1; - } - if (data->ioc_inllen2 > (1<<30)) { - CERROR("LIBCFS ioctl: ioc_inllen2 larger than 1<<30\n"); - return 1; - } - if (data->ioc_inlbuf1 && !data->ioc_inllen1) { - CERROR("LIBCFS ioctl: inlbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf2 && !data->ioc_inllen2) { - CERROR("LIBCFS ioctl: inlbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf1 && !data->ioc_plen1) { - CERROR("LIBCFS ioctl: pbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf2 && !data->ioc_plen2) { - CERROR("LIBCFS ioctl: pbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_plen1 && !data->ioc_pbuf1) { - CERROR("LIBCFS ioctl: plen1 nonzero but no pbuf1 pointer\n"); - return 1; - } - if (data->ioc_plen2 && !data->ioc_pbuf2) { - CERROR("LIBCFS ioctl: plen2 nonzero but no pbuf2 pointer\n"); - return 1; - } - if ((__u32)libcfs_ioctl_packlen(data) != data->ioc_hdr.ioc_len) { - CERROR("LIBCFS ioctl: packlen != ioc_len\n"); - return 1; - } - if (data->ioc_inllen1 && - data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { - CERROR("LIBCFS ioctl: inlbuf1 not 0 terminated\n"); - return 1; - } - if (data->ioc_inllen2 && - data->ioc_bulk[cfs_size_round(data->ioc_inllen1) + - data->ioc_inllen2 - 1] != '\0') { - CERROR("LIBCFS ioctl: inlbuf2 not 0 terminated\n"); - return 1; - } - return 0; -} - int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, const struct libcfs_ioctl_hdr __user *uparam); int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data); diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index 7634551afed3..af19f3cabd2c 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -40,6 +40,71 @@ #define LNET_MINOR 240 +static inline int libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) +{ + int len = sizeof(*data); + + len += cfs_size_round(data->ioc_inllen1); + len += cfs_size_round(data->ioc_inllen2); + return len; +} + +static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) +{ + if (data->ioc_hdr.ioc_len > (1 << 30)) { + CERROR("LIBCFS ioctl: ioc_len larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen1 > (1<<30)) { + CERROR("LIBCFS ioctl: ioc_inllen1 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen2 > (1<<30)) { + CERROR("LIBCFS ioctl: ioc_inllen2 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inlbuf1 && !data->ioc_inllen1) { + CERROR("LIBCFS ioctl: inlbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_inlbuf2 && !data->ioc_inllen2) { + CERROR("LIBCFS ioctl: inlbuf2 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf1 && !data->ioc_plen1) { + CERROR("LIBCFS ioctl: pbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf2 && !data->ioc_plen2) { + CERROR("LIBCFS ioctl: pbuf2 pointer but 0 length\n"); + return 1; + } + if (data->ioc_plen1 && !data->ioc_pbuf1) { + CERROR("LIBCFS ioctl: plen1 nonzero but no pbuf1 pointer\n"); + return 1; + } + if (data->ioc_plen2 && !data->ioc_pbuf2) { + CERROR("LIBCFS ioctl: plen2 nonzero but no pbuf2 pointer\n"); + return 1; + } + if ((__u32)libcfs_ioctl_packlen(data) != data->ioc_hdr.ioc_len) { + CERROR("LIBCFS ioctl: packlen != ioc_len\n"); + return 1; + } + if (data->ioc_inllen1 && + data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { + CERROR("LIBCFS ioctl: inlbuf1 not 0 terminated\n"); + return 1; + } + if (data->ioc_inllen2 && + data->ioc_bulk[cfs_size_round(data->ioc_inllen1) + + data->ioc_inllen2 - 1] != '\0') { + CERROR("LIBCFS ioctl: inlbuf2 not 0 terminated\n"); + return 1; + } + return 0; +} + int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data) { if (libcfs_ioctl_is_invalid(data)) { -- GitLab From 659bd8d9792a354ba755dab623dc9909cd03206e Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:11 -0400 Subject: [PATCH 0447/9938] staging: lustre: libcfs: move function declarations from libcfs_ioctl.h Move the function declartions that are used only by kernel space to libcfs.h This makes libcfs_ioctl.h a offical uapi header now. Move large inline functions out of libcfs_ioctl.h to the source file linux-module.c belonging to libcfs. This code is only used by the core of libcfs and such inline functions don't belong in a uapi header file. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 3 +++ drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 1cd18790d22e..6a8e0d0d61bf 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -112,6 +112,9 @@ struct libcfs_ioctl_handler { int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); +int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, + const struct libcfs_ioctl_hdr __user *uparam); +int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data); int libcfs_ioctl(unsigned long cmd, void *arg); /* container_of depends on "likely" which is defined in libcfs_private.h */ diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 3af13e43169f..c379d29992d1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -138,8 +138,4 @@ struct libcfs_debug_ioctl_data { #define IOC_LIBCFS_GET_LNET_STATS _IOWR(IOC_LIBCFS_TYPE, 91, IOCTL_CONFIG_SIZE) #define IOC_LIBCFS_MAX_NR 91 -int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, - const struct libcfs_ioctl_hdr __user *uparam); -int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data); - #endif /* __LIBCFS_IOCTL_H__ */ -- GitLab From da71485102ff8d4b3481dedddcb5a79164f1e4bb Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:12 -0400 Subject: [PATCH 0448/9938] staging: lustre: libcfs: make libcfs_ioctl.h readable Fix up all thw whitescapes and line up the IOCTL defines so it is readable. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_ioctl.h | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index c379d29992d1..48372c4cc9a3 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -82,41 +82,42 @@ struct libcfs_debug_ioctl_data { unsigned int debug; }; -/* FIXME check conflict with lustre_lib.h */ -#define LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long) +/* 'f' ioctls are defined in lustre_ioctl.h and lustre_user.h except for: */ +#define LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long) +#define IOCTL_LIBCFS_TYPE long -#define IOC_LIBCFS_TYPE 'e' -#define IOC_LIBCFS_MIN_NR 30 +#define IOC_LIBCFS_TYPE ('e') +#define IOC_LIBCFS_MIN_NR 30 /* libcfs ioctls */ /* IOC_LIBCFS_PANIC obsolete in 2.8.0, was _IOWR('e', 30, IOCTL_LIBCFS_TYPE) */ -#define IOC_LIBCFS_CLEAR_DEBUG _IOWR('e', 31, long) -#define IOC_LIBCFS_MARK_DEBUG _IOWR('e', 32, long) +#define IOC_LIBCFS_CLEAR_DEBUG _IOWR('e', 31, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_MARK_DEBUG _IOWR('e', 32, IOCTL_LIBCFS_TYPE) /* IOC_LIBCFS_MEMHOG obsolete in 2.8.0, was _IOWR('e', 36, IOCTL_LIBCFS_TYPE) */ /* lnet ioctls */ -#define IOC_LIBCFS_GET_NI _IOWR('e', 50, long) -#define IOC_LIBCFS_FAIL_NID _IOWR('e', 51, long) -#define IOC_LIBCFS_NOTIFY_ROUTER _IOWR('e', 55, long) -#define IOC_LIBCFS_UNCONFIGURE _IOWR('e', 56, long) -/* #define IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, long) */ -#define IOC_LIBCFS_LNET_DIST _IOWR('e', 58, long) -#define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, long) -#define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, long) -#define IOC_LIBCFS_PING _IOWR('e', 61, long) -/* #define IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, long) */ -#define IOC_LIBCFS_LNETST _IOWR('e', 63, long) -#define IOC_LIBCFS_LNET_FAULT _IOWR('e', 64, long) +#define IOC_LIBCFS_GET_NI _IOWR('e', 50, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_FAIL_NID _IOWR('e', 51, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_NOTIFY_ROUTER _IOWR('e', 55, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_UNCONFIGURE _IOWR('e', 56, IOCTL_LIBCFS_TYPE) +/* IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, IOCTL_LIBCFS_TYPE) */ +#define IOC_LIBCFS_LNET_DIST _IOWR('e', 58, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_PING _IOWR('e', 61, IOCTL_LIBCFS_TYPE) +/* IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, IOCTL_LIBCFS_TYPE) */ +#define IOC_LIBCFS_LNETST _IOWR('e', 63, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_LNET_FAULT _IOWR('e', 64, IOCTL_LIBCFS_TYPE) /* lnd ioctls */ -#define IOC_LIBCFS_REGISTER_MYNID _IOWR('e', 70, long) -#define IOC_LIBCFS_CLOSE_CONNECTION _IOWR('e', 71, long) -#define IOC_LIBCFS_PUSH_CONNECTION _IOWR('e', 72, long) -#define IOC_LIBCFS_GET_CONN _IOWR('e', 73, long) -#define IOC_LIBCFS_DEL_PEER _IOWR('e', 74, long) -#define IOC_LIBCFS_ADD_PEER _IOWR('e', 75, long) -#define IOC_LIBCFS_GET_PEER _IOWR('e', 76, long) +#define IOC_LIBCFS_REGISTER_MYNID _IOWR('e', 70, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_CLOSE_CONNECTION _IOWR('e', 71, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_PUSH_CONNECTION _IOWR('e', 72, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_GET_CONN _IOWR('e', 73, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_DEL_PEER _IOWR('e', 74, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_ADD_PEER _IOWR('e', 75, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_GET_PEER _IOWR('e', 76, IOCTL_LIBCFS_TYPE) /* ioctl 77 is free for use */ -#define IOC_LIBCFS_ADD_INTERFACE _IOWR('e', 78, long) -#define IOC_LIBCFS_DEL_INTERFACE _IOWR('e', 79, long) -#define IOC_LIBCFS_GET_INTERFACE _IOWR('e', 80, long) +#define IOC_LIBCFS_ADD_INTERFACE _IOWR('e', 78, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_DEL_INTERFACE _IOWR('e', 79, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_GET_INTERFACE _IOWR('e', 80, IOCTL_LIBCFS_TYPE) /* * DLC Specific IOCTL numbers. -- GitLab From 92c18e1335cf757d9881864b58e725482b38a398 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:13 -0400 Subject: [PATCH 0449/9938] staging: lustre: libcfs: add uapi headers to libcfs_ioctl.h Need a few uapi headers to make libcfs_ioctl.h compilable in userland. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 48372c4cc9a3..4b9102bd95d5 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -41,6 +41,9 @@ #ifndef __LIBCFS_IOCTL_H__ #define __LIBCFS_IOCTL_H__ +#include +#include + #define LIBCFS_IOCTL_VERSION 0x0001000a #define LIBCFS_IOCTL_VERSION2 0x0001000b -- GitLab From 460a222d9e1c5c0b2f1e037aeab0408a733031dc Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:14 -0400 Subject: [PATCH 0450/9938] staging: lustre: libcfs: return proper bool values Return real bool values for libcfs_ioctl_is_invalid(). Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lnet/libcfs/linux/linux-module.c | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index af19f3cabd2c..d5b7d3a210da 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -53,56 +53,56 @@ static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) { if (data->ioc_hdr.ioc_len > (1 << 30)) { CERROR("LIBCFS ioctl: ioc_len larger than 1<<30\n"); - return 1; + return true; } if (data->ioc_inllen1 > (1<<30)) { CERROR("LIBCFS ioctl: ioc_inllen1 larger than 1<<30\n"); - return 1; + return true; } if (data->ioc_inllen2 > (1<<30)) { CERROR("LIBCFS ioctl: ioc_inllen2 larger than 1<<30\n"); - return 1; + return true; } if (data->ioc_inlbuf1 && !data->ioc_inllen1) { CERROR("LIBCFS ioctl: inlbuf1 pointer but 0 length\n"); - return 1; + return true; } if (data->ioc_inlbuf2 && !data->ioc_inllen2) { CERROR("LIBCFS ioctl: inlbuf2 pointer but 0 length\n"); - return 1; + return true; } if (data->ioc_pbuf1 && !data->ioc_plen1) { CERROR("LIBCFS ioctl: pbuf1 pointer but 0 length\n"); - return 1; + return true; } if (data->ioc_pbuf2 && !data->ioc_plen2) { CERROR("LIBCFS ioctl: pbuf2 pointer but 0 length\n"); - return 1; + return true; } if (data->ioc_plen1 && !data->ioc_pbuf1) { CERROR("LIBCFS ioctl: plen1 nonzero but no pbuf1 pointer\n"); - return 1; + return true; } if (data->ioc_plen2 && !data->ioc_pbuf2) { CERROR("LIBCFS ioctl: plen2 nonzero but no pbuf2 pointer\n"); - return 1; + return true; } if ((__u32)libcfs_ioctl_packlen(data) != data->ioc_hdr.ioc_len) { CERROR("LIBCFS ioctl: packlen != ioc_len\n"); - return 1; + return true; } if (data->ioc_inllen1 && data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { CERROR("LIBCFS ioctl: inlbuf1 not 0 terminated\n"); - return 1; + return true; } if (data->ioc_inllen2 && data->ioc_bulk[cfs_size_round(data->ioc_inllen1) + data->ioc_inllen2 - 1] != '\0') { CERROR("LIBCFS ioctl: inlbuf2 not 0 terminated\n"); - return 1; + return true; } - return 0; + return false; } int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data) -- GitLab From 243fddea35f8337016049d1bffc1599cd28330a4 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:15 -0400 Subject: [PATCH 0451/9938] staging: lustre: libcfs: use BIT macro in linux-module.c Use the proper BIT macro for libcfs_ioctl_is_invalid(). Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index d5b7d3a210da..cf191ef26410 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -51,15 +51,15 @@ static inline int libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) static inline bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) { - if (data->ioc_hdr.ioc_len > (1 << 30)) { + if (data->ioc_hdr.ioc_len > BIT(30)) { CERROR("LIBCFS ioctl: ioc_len larger than 1<<30\n"); return true; } - if (data->ioc_inllen1 > (1<<30)) { + if (data->ioc_inllen1 > BIT(30)) { CERROR("LIBCFS ioctl: ioc_inllen1 larger than 1<<30\n"); return true; } - if (data->ioc_inllen2 > (1<<30)) { + if (data->ioc_inllen2 > BIT(30)) { CERROR("LIBCFS ioctl: ioc_inllen2 larger than 1<<30\n"); return true; } -- GitLab From c9493bd6c98d3f737341dc8eb7d4aac574934a0d Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 22 Mar 2016 19:04:16 -0400 Subject: [PATCH 0452/9938] staging: lustre: libcfs: return size_t for libcfs_ioctl_packlen Change return value to size_t. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17643 Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index cf191ef26410..b86e93795846 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -40,9 +40,9 @@ #define LNET_MINOR 240 -static inline int libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) +static inline size_t libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) { - int len = sizeof(*data); + size_t len = sizeof(*data); len += cfs_size_round(data->ioc_inllen1); len += cfs_size_round(data->ioc_inllen2); -- GitLab From 800aecc30b946e849f256e52dfe5c278fc32eb13 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Thu, 24 Mar 2016 09:18:09 -0400 Subject: [PATCH 0453/9938] staging: unisys: remove channel.h double negative comparison This patch removes the double negative comparisons for function readb. Signed-off-by: Erik Arfvidson Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/channel.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index 5af59a5fce61..b3c747b77dd0 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -411,7 +411,7 @@ spar_channel_client_acquire_os(void __iomem *ch, u8 *id) mb(); /* required for channel synch */ } if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { - if (readb(&hdr->cli_error_os) != 0) { + if (readb(&hdr->cli_error_os)) { /* we are in an error msg throttling state; * come out of it */ @@ -459,7 +459,7 @@ spar_channel_client_acquire_os(void __iomem *ch, u8 *id) mb(); /* required for channel synch */ return 0; } - if (readb(&hdr->cli_error_os) != 0) { + if (readb(&hdr->cli_error_os)) { /* we are in an error msg throttling state; come out of it */ pr_info("%s Channel OS client acquire now successful\n", id); writeb(0, &hdr->cli_error_os); @@ -472,7 +472,7 @@ spar_channel_client_release_os(void __iomem *ch, u8 *id) { struct channel_header __iomem *hdr = ch; - if (readb(&hdr->cli_error_os) != 0) { + if (readb(&hdr->cli_error_os)) { /* we are in an error msg throttling state; come out of it */ pr_info("%s Channel OS client error state cleared\n", id); writeb(0, &hdr->cli_error_os); -- GitLab From 4d12b5ee26e31b964b8918e7adde081103213b06 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Thu, 24 Mar 2016 09:18:10 -0400 Subject: [PATCH 0454/9938] staging: unisys: remove visorinput.c double negative comparison This patch simply removes the double negative comparison for test_bit since test_bit already preforms this check. Signed-off-by: Erik Arfvidson Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorinput/visorinput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 13c0316112ac..3299cf502aa0 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -470,7 +470,7 @@ handle_locking_key(struct input_dev *visorinput_dev, break; } if (led >= 0) { - int old_state = (test_bit(led, visorinput_dev->led) != 0); + int old_state = (test_bit(led, visorinput_dev->led)); if (old_state != desired_state) { input_report_key(visorinput_dev, keycode, 1); -- GitLab From 48f571489c0e8263b7a37dcd794ecf19b852a4df Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 23 Mar 2016 22:15:49 -0400 Subject: [PATCH 0455/9938] staging: unisys: visorbus: replaced vague variable name in typeguid_show The variable name "s" doesn't indicate the purpose of the string, which is to store the id collected from the visorchannel_id function. This just replaces the name with "typeid". Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 54d77dd26be0..af5add50c940 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -279,12 +279,12 @@ static ssize_t typeguid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); - char s[99]; + char typeid[99]; if (!vdev->visorchannel) return 0; return snprintf(buf, PAGE_SIZE, "%s\n", - visorchannel_id(vdev->visorchannel, s)); + visorchannel_id(vdev->visorchannel, typeid)); } static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr, -- GitLab From 62f3dc856736d5ddc782ee1313626ef1adfe18a9 Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 23 Mar 2016 22:15:50 -0400 Subject: [PATCH 0456/9938] staging: unisys: visorbus: replaced vague variable name in zoneguid_show The variable name "s" doesn't indicate the purpose of the string, which is to store the id collected from the visorchannel_zoneid function. This just replaces the name with "zoneid". Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index af5add50c940..41a6d3a0d1ca 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -291,12 +291,12 @@ static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); - char s[99]; + char zoneid[99]; if (!vdev->visorchannel) return 0; return snprintf(buf, PAGE_SIZE, "%s\n", - visorchannel_zoneid(vdev->visorchannel, s)); + visorchannel_zoneid(vdev->visorchannel, zoneid)); } static ssize_t typename_show(struct device *dev, struct device_attribute *attr, -- GitLab From 8d7da1d8c2aa5564af442b4371216b4a4288cd5a Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 23 Mar 2016 22:15:51 -0400 Subject: [PATCH 0457/9938] staging: unisys: visorbus: replaced vague 'p' variable with 'pos' In the case of client_bus_info_show, the variable 'p' was used to indicate the position in the output buffer. This was changed to 'pos' to indicate that it kept track of the current position in the output buffer. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorbus_main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 41a6d3a0d1ca..33407a760ab9 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -422,7 +422,7 @@ static ssize_t client_bus_info_show(struct device *dev, int i, x, remain = PAGE_SIZE; unsigned long off; - char *p = buf; + char *pos = buf; u8 *partition_name; struct ultra_vbus_deviceinfo dev_info; @@ -430,10 +430,10 @@ static ssize_t client_bus_info_show(struct device *dev, if (channel) { if (vdev->name) partition_name = vdev->name; - x = snprintf(p, remain, + x = snprintf(pos, remain, "Client device / client driver info for %s partition (vbus #%d):\n", partition_name, vdev->chipset_dev_no); - p += x; + pos += x; remain -= x; x = visorchannel_read(channel, offsetof(struct @@ -441,9 +441,9 @@ static ssize_t client_bus_info_show(struct device *dev, chp_info), &dev_info, sizeof(dev_info)); if (x >= 0) { - x = vbuschannel_devinfo_to_string(&dev_info, p, + x = vbuschannel_devinfo_to_string(&dev_info, pos, remain, -1); - p += x; + pos += x; remain -= x; } x = visorchannel_read(channel, @@ -452,9 +452,9 @@ static ssize_t client_bus_info_show(struct device *dev, bus_info), &dev_info, sizeof(dev_info)); if (x >= 0) { - x = vbuschannel_devinfo_to_string(&dev_info, p, + x = vbuschannel_devinfo_to_string(&dev_info, pos, remain, -1); - p += x; + pos += x; remain -= x; } off = offsetof(struct spar_vbus_channel_protocol, dev_info); @@ -465,8 +465,8 @@ static ssize_t client_bus_info_show(struct device *dev, off, &dev_info, sizeof(dev_info)); if (x >= 0) { x = vbuschannel_devinfo_to_string - (&dev_info, p, remain, i); - p += x; + (&dev_info, pos, remain, i); + pos += x; remain -= x; } off += sizeof(dev_info); -- GitLab From a22f57c65062a5ca6b4e7ccfbd143c3819b9045b Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 23 Mar 2016 22:15:52 -0400 Subject: [PATCH 0458/9938] staging: unisys: visorbus: replaced use of vague 'x' variable In client_bus_info_show, the variable 'x' is used to create keep track of the offset that the current 'pos' in the output buffer needs to be incremented by. Since 'off' is already taken 'shift' was used since it's used to shift the pointer. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorbus_main.c | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 33407a760ab9..1fcb1775bb59 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -420,7 +420,7 @@ static ssize_t client_bus_info_show(struct device *dev, struct visor_device *vdev = to_visor_device(dev); struct visorchannel *channel = vdev->visorchannel; - int i, x, remain = PAGE_SIZE; + int i, shift, remain = PAGE_SIZE; unsigned long off; char *pos = buf; u8 *partition_name; @@ -430,44 +430,45 @@ static ssize_t client_bus_info_show(struct device *dev, if (channel) { if (vdev->name) partition_name = vdev->name; - x = snprintf(pos, remain, - "Client device / client driver info for %s partition (vbus #%d):\n", - partition_name, vdev->chipset_dev_no); - pos += x; - remain -= x; - x = visorchannel_read(channel, - offsetof(struct - spar_vbus_channel_protocol, - chp_info), - &dev_info, sizeof(dev_info)); - if (x >= 0) { - x = vbuschannel_devinfo_to_string(&dev_info, pos, - remain, -1); - pos += x; - remain -= x; + shift = snprintf(pos, remain, + "Client device / client driver info for %s eartition (vbus #%d):\n", + partition_name, vdev->chipset_dev_no); + pos += shift; + remain -= shift; + shift = visorchannel_read(channel, + offsetof(struct + spar_vbus_channel_protocol, + chp_info), + &dev_info, sizeof(dev_info)); + if (shift >= 0) { + shift = vbuschannel_devinfo_to_string(&dev_info, pos, + remain, -1); + pos += shift; + remain -= shift; } - x = visorchannel_read(channel, - offsetof(struct - spar_vbus_channel_protocol, - bus_info), - &dev_info, sizeof(dev_info)); - if (x >= 0) { - x = vbuschannel_devinfo_to_string(&dev_info, pos, - remain, -1); - pos += x; - remain -= x; + shift = visorchannel_read(channel, + offsetof(struct + spar_vbus_channel_protocol, + bus_info), + &dev_info, sizeof(dev_info)); + if (shift >= 0) { + shift = vbuschannel_devinfo_to_string(&dev_info, pos, + remain, -1); + pos += shift; + remain -= shift; } off = offsetof(struct spar_vbus_channel_protocol, dev_info); i = 0; while (off + sizeof(dev_info) <= visorchannel_get_nbytes(channel)) { - x = visorchannel_read(channel, - off, &dev_info, sizeof(dev_info)); - if (x >= 0) { - x = vbuschannel_devinfo_to_string + shift = visorchannel_read(channel, + off, &dev_info, + sizeof(dev_info)); + if (shift >= 0) { + shift = vbuschannel_devinfo_to_string (&dev_info, pos, remain, i); - pos += x; - remain -= x; + pos += shift; + remain -= shift; } off += sizeof(dev_info); i++; -- GitLab From 85d83cd8c629e053e3aaec0a4dd6c798d46c109d Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 23 Mar 2016 22:15:53 -0400 Subject: [PATCH 0459/9938] staging: unisys: include: changed 'v' variable to 'state' The argument for ULTRA_CHANNELCLI_STRING is supposed to be an integer representing the channel state. 'state' is a more descriptive variable name for this. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/channel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index b3c747b77dd0..db4e6b28755b 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -76,9 +76,9 @@ enum channel_clientstate { }; static inline const u8 * -ULTRA_CHANNELCLI_STRING(u32 v) +ULTRA_CHANNELCLI_STRING(u32 state) { - switch (v) { + switch (state) { case CHANNELCLI_DETACHED: return (const u8 *)("DETACHED"); case CHANNELCLI_DISABLED: -- GitLab From 04dd9a421111dfb88e1ae73af0ea27f285c89b74 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 23 Mar 2016 21:28:33 +0900 Subject: [PATCH 0460/9938] staging: wilc1000: use completion instead of struct semaphore hif_sema_thread struct semaphore hif_sema_thread is used to signal completion of host interface thread. This patch replaces struct semaphore hif_sema_thread with struct completion hif_thread_comp. It is better to use completion than semaphore for this case. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index b1ffa91dfe52..3d1797201c2c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -231,7 +231,7 @@ bool wilc_optaining_ip; static u8 P2P_LISTEN_STATE; static struct task_struct *hif_thread_handler; static struct message_queue hif_msg_q; -static struct semaphore hif_sema_thread; +static struct completion hif_thread_comp; static struct semaphore hif_sema_driver; static struct completion hif_wait_response; static struct mutex hif_deinit_lock; @@ -2668,7 +2668,7 @@ static int hostIFthread(void *pvArg) } } - up(&hif_sema_thread); + complete(&hif_thread_comp); return 0; } @@ -3400,7 +3400,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) wilc_optaining_ip = false; if (clients_count == 0) { - sema_init(&hif_sema_thread, 0); + init_completion(&hif_thread_comp); sema_init(&hif_sema_driver, 0); mutex_init(&hif_deinit_lock); } @@ -3503,7 +3503,7 @@ int wilc_deinit(struct wilc_vif *vif) if (result != 0) netdev_err(vif->ndev, "deinit : Error(%d)\n", result); - down(&hif_sema_thread); + wait_for_completion(&hif_thread_comp); wilc_mq_destroy(&hif_msg_q); } -- GitLab From 2bb02584cd95405da72b009d0960f803d31e2302 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 23 Mar 2016 21:28:34 +0900 Subject: [PATCH 0461/9938] staging: wilc1000: use completion instead of struct semaphore hif_sema_driver struct semaphore hif_sema_driver is used to signal completion of host interface message. This patch replaces struct semaphore hif_sema_driver with struct completion hif_driver_comp. It is better to use completion than semaphore for this case. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3d1797201c2c..29d4d8a88d12 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -232,7 +232,7 @@ static u8 P2P_LISTEN_STATE; static struct task_struct *hif_thread_handler; static struct message_queue hif_msg_q; static struct completion hif_thread_comp; -static struct semaphore hif_sema_driver; +static struct completion hif_driver_comp; static struct completion hif_wait_response; static struct mutex hif_deinit_lock; static struct timer_list periodic_rssi; @@ -321,7 +321,7 @@ static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif, hif_drv_handler->handler); if (!hif_drv_handler->handler) - up(&hif_sema_driver); + complete(&hif_driver_comp); if (result) { netdev_err(vif->ndev, "Failed to set driver handler\n"); @@ -346,7 +346,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, wilc_get_vif_idx(vif)); if ((hif_op_mode->mode) == IDLE_MODE) - up(&hif_sema_driver); + complete(&hif_driver_comp); if (result) { netdev_err(vif->ndev, "Failed to set driver handler\n"); @@ -3401,7 +3401,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) if (clients_count == 0) { init_completion(&hif_thread_comp); - sema_init(&hif_sema_driver, 0); + init_completion(&hif_driver_comp); mutex_init(&hif_deinit_lock); } @@ -3480,7 +3480,7 @@ int wilc_deinit(struct wilc_vif *vif) del_timer_sync(&hif_drv->remain_on_ch_timer); wilc_set_wfi_drv_handler(vif, 0, 0); - down(&hif_sema_driver); + wait_for_completion(&hif_driver_comp); if (hif_drv->usr_scan_req.scan_result) { hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, -- GitLab From 58e7003f53f32d5beb1a047fd41125d09a1a2467 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:46 +0900 Subject: [PATCH 0462/9938] staging: wilc1000: removes WIRELESS_EXT This patch removes WIRELESS_EXT. Does not used the WIRELESS_EXT define. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wilc1000/Kconfig b/drivers/staging/wilc1000/Kconfig index dce9cee9134a..73f7fefd3bc3 100644 --- a/drivers/staging/wilc1000/Kconfig +++ b/drivers/staging/wilc1000/Kconfig @@ -1,6 +1,5 @@ config WILC1000 tristate - select WIRELESS_EXT ---help--- This module only support IEEE 802.11n WiFi. -- GitLab From 6d11c5517f544b50827e4ee720fad512ac28e14a Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:47 +0900 Subject: [PATCH 0463/9938] staging: wilc1000: wilc_frame_register: removes unused hif_drv This patch removes unused hif_drv of wilc_frame_register function. It's perform an unnecessary null check and debug print log. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 29d4d8a88d12..04cbff50a0f1 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3689,12 +3689,6 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) { int result = 0; struct host_if_msg msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - netdev_err(vif->ndev, "driver is null\n"); - return -EFAULT; - } memset(&msg, 0, sizeof(struct host_if_msg)); -- GitLab From c92a869e6170c06219ca550a0e87fbefaa92a30b Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:48 +0900 Subject: [PATCH 0464/9938] staging: wilc1000: removes typedef of struct struct_frame_reg This patch removes typedef of struct struct_frame_reg. Renames the struct_frame_reg to frame_reg as well. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 4123cffe3a6e..f394484a1ceb 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -139,18 +139,17 @@ struct wilc_priv { }; -typedef struct { +struct frame_reg { u16 frame_type; bool reg; - -} struct_frame_reg; +}; struct wilc_vif { u8 idx; u8 iftype; int monitor_flag; int mac_opened; - struct_frame_reg g_struct_frame_reg[num_reg_frame]; + struct frame_reg g_struct_frame_reg[num_reg_frame]; struct net_device_stats netstats; struct wilc *wilc; u8 src_addr[ETH_ALEN]; -- GitLab From 89febb21c4ca25030c75ba5a7cb64fe02c2cb156 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:49 +0900 Subject: [PATCH 0465/9938] staging: wilc1000: replaces g_struct_frame_reg with frame_reg This patch replaces g_struct_frame_reg with frame_reg. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 12 ++++++------ drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 8 ++++---- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index e949f218885c..2f830cd3163b 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -966,12 +966,12 @@ int wilc_mac_open(struct net_device *ndev) wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy, vif->ndev->ieee80211_ptr, - vif->g_struct_frame_reg[0].frame_type, - vif->g_struct_frame_reg[0].reg); + vif->frame_reg[0].frame_type, + vif->frame_reg[0].reg); wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy, vif->ndev->ieee80211_ptr, - vif->g_struct_frame_reg[1].frame_type, - vif->g_struct_frame_reg[1].reg); + vif->frame_reg[1].frame_type, + vif->frame_reg[1].reg); netif_wake_queue(ndev); wl->open_ifcs++; vif->mac_opened = 1; @@ -1260,8 +1260,8 @@ void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size) } vif = netdev_priv(wilc->vif[1]->ndev); - if ((buff[0] == vif->g_struct_frame_reg[0].frame_type && vif->g_struct_frame_reg[0].reg) || - (buff[0] == vif->g_struct_frame_reg[1].frame_type && vif->g_struct_frame_reg[1].reg)) + if ((buff[0] == vif->frame_reg[0].frame_type && vif->frame_reg[0].reg) || + (buff[0] == vif->frame_reg[1].frame_type && vif->frame_reg[1].reg)) WILC_WFI_p2p_rx(wilc->vif[1]->ndev, buff, size); } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 70625f8a2e3c..3e0ffee89416 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1745,15 +1745,15 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, switch (frame_type) { case PROBE_REQ: { - vif->g_struct_frame_reg[0].frame_type = frame_type; - vif->g_struct_frame_reg[0].reg = reg; + vif->frame_reg[0].frame_type = frame_type; + vif->frame_reg[0].reg = reg; } break; case ACTION: { - vif->g_struct_frame_reg[1].frame_type = frame_type; - vif->g_struct_frame_reg[1].reg = reg; + vif->frame_reg[1].frame_type = frame_type; + vif->frame_reg[1].reg = reg; } break; diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index f394484a1ceb..3abe48188d3d 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -149,7 +149,7 @@ struct wilc_vif { u8 iftype; int monitor_flag; int mac_opened; - struct frame_reg g_struct_frame_reg[num_reg_frame]; + struct frame_reg frame_reg[num_reg_frame]; struct net_device_stats netstats; struct wilc *wilc; u8 src_addr[ETH_ALEN]; -- GitLab From 340a84ff96c4d9effbc841a085e2101c3977e5cf Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:50 +0900 Subject: [PATCH 0466/9938] staging: wilc1000: replaces frame_type with type of struct frame_reg This patch replaces frame_type with type of struct frame_reg. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 8 ++++---- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 4 ++-- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 2f830cd3163b..760d44d17056 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -966,11 +966,11 @@ int wilc_mac_open(struct net_device *ndev) wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy, vif->ndev->ieee80211_ptr, - vif->frame_reg[0].frame_type, + vif->frame_reg[0].type, vif->frame_reg[0].reg); wilc_mgmt_frame_register(vif->ndev->ieee80211_ptr->wiphy, vif->ndev->ieee80211_ptr, - vif->frame_reg[1].frame_type, + vif->frame_reg[1].type, vif->frame_reg[1].reg); netif_wake_queue(ndev); wl->open_ifcs++; @@ -1260,8 +1260,8 @@ void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size) } vif = netdev_priv(wilc->vif[1]->ndev); - if ((buff[0] == vif->frame_reg[0].frame_type && vif->frame_reg[0].reg) || - (buff[0] == vif->frame_reg[1].frame_type && vif->frame_reg[1].reg)) + if ((buff[0] == vif->frame_reg[0].type && vif->frame_reg[0].reg) || + (buff[0] == vif->frame_reg[1].type && vif->frame_reg[1].reg)) WILC_WFI_p2p_rx(wilc->vif[1]->ndev, buff, size); } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 3e0ffee89416..5785dda8f9d3 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1745,14 +1745,14 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, switch (frame_type) { case PROBE_REQ: { - vif->frame_reg[0].frame_type = frame_type; + vif->frame_reg[0].type = frame_type; vif->frame_reg[0].reg = reg; } break; case ACTION: { - vif->frame_reg[1].frame_type = frame_type; + vif->frame_reg[1].type = frame_type; vif->frame_reg[1].reg = reg; } break; diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 3abe48188d3d..debb139b7687 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -140,7 +140,7 @@ struct wilc_priv { }; struct frame_reg { - u16 frame_type; + u16 type; bool reg; }; -- GitLab From 5510730d5f95a37e9de29597e8e7328103bbaf60 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:51 +0900 Subject: [PATCH 0467/9938] staging: wilc1000: removes unused dead codes This patch removes unused dead codes that define custom feature. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 760d44d17056..db624ef31e69 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -691,14 +691,6 @@ void wilc1000_wlan_deinit(struct net_device *dev) wilc_wlan_stop(wl); wilc_wlan_cleanup(dev); -#if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31) - if (!wl->dev_irq_num && - wl->hif_func->disable_interrupt) { - mutex_lock(&wl->hif_cs); - wl->hif_func->disable_interrupt(wl); - mutex_unlock(&wl->hif_cs); - } -#endif wlan_deinit_locks(dev); wl->initialized = false; -- GitLab From e944ad751ff4fbbd0278ba4dd8595bf7fa3c7e9e Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:52 +0900 Subject: [PATCH 0468/9938] staging: wilc1000: removes unused debug flags This patch removes unused debug flags. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan_if.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 83cf84dd63b5..119b31348a1b 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -13,18 +13,6 @@ #include #include -/******************************************** - * - * Debug Flags - * - ********************************************/ - -#define N_INIT 0x00000001 -#define N_ERR 0x00000002 -#define N_TXQ 0x00000004 -#define N_INTR 0x00000008 -#define N_RXQ 0x00000010 - /******************************************** * * Host Interface Defines -- GitLab From fa63394152e9675c6d9ce32e57fbe00094efb4b8 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:53 +0900 Subject: [PATCH 0469/9938] staging: wilc1000: replaces memcmp with ether_addr_equal_unaligned This patch replaces memcmp with ether_addr_equal_unaligned. Warning reported by checkpatch.pl - Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index db624ef31e69..8f0a74d3ff86 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -259,10 +259,12 @@ static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header) for (i = 0; i < wilc->vif_num; i++) { if (wilc->vif[i]->mode == STATION_MODE) - if (!memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN)) + if (ether_addr_equal_unaligned(bssid, + wilc->vif[i]->bssid)) return wilc->vif[i]->ndev; if (wilc->vif[i]->mode == AP_MODE) - if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN)) + if (ether_addr_equal_unaligned(bssid1, + wilc->vif[i]->bssid)) return wilc->vif[i]->ndev; } -- GitLab From 7632d9b1a073834df3f3b1d59b9159d9fe5b5419 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:54 +0900 Subject: [PATCH 0470/9938] staging: wilc1000: removes unused define This patch removes unused define. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 -- drivers/staging/wilc1000/wilc_wlan_if.h | 9 --------- 2 files changed, 11 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 8f0a74d3ff86..127a9679cdae 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -30,8 +30,6 @@ static struct notifier_block g_dev_notifier = { .notifier_call = dev_state_ev_handler }; -#define IRQ_WAIT 1 -#define IRQ_NO_WAIT 0 static struct semaphore close_exit_sync; static int wlan_deinit_locks(struct net_device *dev); diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 119b31348a1b..410bfc034319 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -23,15 +23,6 @@ #define HIF_SPI BIT(0) #define HIF_SDIO_GPIO_IRQ BIT(2) -/******************************************** - * - * Tx/Rx Buffer Size Defines - * - ********************************************/ - -#define CE_TX_BUFFER_SIZE (64 * 1024) -#define CE_RX_BUFFER_SIZE (384 * 1024) - /******************************************** * * Wlan Interface Defines -- GitLab From 847109fc0f4e5f703107492684de1943069f4530 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:55 +0900 Subject: [PATCH 0471/9938] staging: wilc1000: removes define USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS This patch removes define USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS and use it's feature codes. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 127a9679cdae..fae03e8cda6f 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -303,22 +303,18 @@ int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc) return ret_val; } -#define USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS - static int linux_wlan_txq_task(void *vp) { int ret, txq_count; struct wilc_vif *vif; struct wilc *wl; struct net_device *dev = vp; -#if defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS #define TX_BACKOFF_WEIGHT_INCR_STEP (1) #define TX_BACKOFF_WEIGHT_DECR_STEP (1) #define TX_BACKOFF_WEIGHT_MAX (7) #define TX_BACKOFF_WEIGHT_MIN (0) #define TX_BACKOFF_WEIGHT_UNIT_MS (10) int backoff_weight = TX_BACKOFF_WEIGHT_MIN; -#endif vif = netdev_priv(dev); wl = vif->wilc; @@ -334,9 +330,6 @@ static int linux_wlan_txq_task(void *vp) schedule(); break; } -#if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS - ret = wilc_wlan_handle_txq(dev, &txq_count); -#else do { ret = wilc_wlan_handle_txq(dev, &txq_count); if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) { @@ -358,7 +351,6 @@ static int linux_wlan_txq_task(void *vp) } } } while (ret == WILC_TX_ERR_NO_BUF && !wl->close); -#endif } return 0; } -- GitLab From 8dc5fb4e0eb8802ff0615b0fde92f43f3bd5d56d Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Fri, 25 Mar 2016 21:16:56 +0900 Subject: [PATCH 0472/9938] staging: wilc1000: removes unused local variable This patch removes unused local variable. This variable is operation definition that back off from sending packets for some time. However, that has been deleted operation code. That is removes all relative code. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index fae03e8cda6f..a858552737b6 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -309,12 +309,6 @@ static int linux_wlan_txq_task(void *vp) struct wilc_vif *vif; struct wilc *wl; struct net_device *dev = vp; -#define TX_BACKOFF_WEIGHT_INCR_STEP (1) -#define TX_BACKOFF_WEIGHT_DECR_STEP (1) -#define TX_BACKOFF_WEIGHT_MAX (7) -#define TX_BACKOFF_WEIGHT_MIN (0) -#define TX_BACKOFF_WEIGHT_UNIT_MS (10) - int backoff_weight = TX_BACKOFF_WEIGHT_MIN; vif = netdev_priv(dev); wl = vif->wilc; @@ -338,18 +332,6 @@ static int linux_wlan_txq_task(void *vp) if (netif_queue_stopped(wl->vif[1]->ndev)) netif_wake_queue(wl->vif[1]->ndev); } - - if (ret == WILC_TX_ERR_NO_BUF) { - backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP; - if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) - backoff_weight = TX_BACKOFF_WEIGHT_MAX; - } else { - if (backoff_weight > TX_BACKOFF_WEIGHT_MIN) { - backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP; - if (backoff_weight < TX_BACKOFF_WEIGHT_MIN) - backoff_weight = TX_BACKOFF_WEIGHT_MIN; - } - } } while (ret == WILC_TX_ERR_NO_BUF && !wl->close); } return 0; -- GitLab From 22acd860137ad6952fec8f6041efa9a30e49c22d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:11 -0700 Subject: [PATCH 0473/9938] staging: comedi: ni_660x: change IOConfigReg() into a macro The BUG_ON() in this function is unnecessary. The 'pfi_channel' will always be in range of the subdevice 'n_chan' (NUM_PFI_CHANNELS) which will return a valid 'reg'. Convert the inline function into a simple macro. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 46647c64f369..10db2fff899e 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -156,13 +156,7 @@ enum ni_660x_register { NI660X_NUM_REGS, }; -static inline unsigned IOConfigReg(unsigned pfi_channel) -{ - unsigned reg = NI660X_IO_CFG_0_1 + pfi_channel / 2; - - BUG_ON(reg > NI660X_IO_CFG_38_39); - return reg; -} +#define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) enum ni_660x_register_width { DATA_1B, @@ -893,7 +887,7 @@ static void init_tio_chip(struct comedi_device *dev, int chipset) devpriv->dma_configuration_soft_copies[chipset], NI660X_DMA_CFG); for (i = 0; i < NUM_PFI_CHANNELS; ++i) - ni_660x_write_register(dev, chipset, 0, IOConfigReg(i)); + ni_660x_write_register(dev, chipset, 0, NI660X_IO_CFG(i)); } static int ni_660x_dio_insn_bits(struct comedi_device *dev, @@ -944,22 +938,22 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, if (idle_chipset != active_chipset) { idle_bits = ni_660x_read_register(dev, idle_chipset, - IOConfigReg(pfi_channel)); + NI660X_IO_CFG(pfi_channel)); idle_bits &= ~pfi_output_select_mask(pfi_channel); idle_bits |= pfi_output_select_bits(pfi_channel, pfi_output_select_high_Z); ni_660x_write_register(dev, idle_chipset, idle_bits, - IOConfigReg(pfi_channel)); + NI660X_IO_CFG(pfi_channel)); } active_bits = ni_660x_read_register(dev, active_chipset, - IOConfigReg(pfi_channel)); + NI660X_IO_CFG(pfi_channel)); active_bits &= ~pfi_output_select_mask(pfi_channel); active_bits |= pfi_output_select_bits(pfi_channel, output_select); ni_660x_write_register(dev, active_chipset, active_bits, - IOConfigReg(pfi_channel)); + NI660X_IO_CFG(pfi_channel)); } static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan, @@ -1025,10 +1019,10 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, break; case INSN_CONFIG_FILTER: - val = ni_660x_read_register(dev, 0, IOConfigReg(chan)); + val = ni_660x_read_register(dev, 0, NI660X_IO_CFG(chan)); val &= ~pfi_input_select_mask(chan); val |= pfi_input_select_bits(chan, data[1]); - ni_660x_write_register(dev, 0, val, IOConfigReg(chan)); + ni_660x_write_register(dev, 0, val, NI660X_IO_CFG(chan)); break; default: -- GitLab From f9565977bf488bd4bf9ef7322728970c20bbc908 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:12 -0700 Subject: [PATCH 0474/9938] staging: comedi: ni_660x: remove struct NI_660xRegisterData 'name' This member of the struct is not used, and just takes up space. Remove it. Instead, add the enum ni_660x_register indexes to the table to clarify, and document, the entries. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 197 +++++++++++------------ 1 file changed, 98 insertions(+), 99 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 10db2fff899e..10bb8394fd99 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -187,111 +187,110 @@ static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index) } struct NI_660xRegisterData { - const char *name; /* Register Name */ int offset; /* Offset from base address from GPCT chip */ enum ni_660x_register_direction direction; enum ni_660x_register_width size; /* 1 byte, 2 bytes, or 4 bytes */ }; static const struct NI_660xRegisterData registerData[NI660X_NUM_REGS] = { - {"G0 Interrupt Acknowledge", 0x004, NI_660x_WRITE, DATA_2B}, - {"G0 Status Register", 0x004, NI_660x_READ, DATA_2B}, - {"G1 Interrupt Acknowledge", 0x006, NI_660x_WRITE, DATA_2B}, - {"G1 Status Register", 0x006, NI_660x_READ, DATA_2B}, - {"G01 Status Register ", 0x008, NI_660x_READ, DATA_2B}, - {"G0 Command Register", 0x00C, NI_660x_WRITE, DATA_2B}, - {"STC DIO Parallel Input", 0x00E, NI_660x_READ, DATA_2B}, - {"G1 Command Register", 0x00E, NI_660x_WRITE, DATA_2B}, - {"G0 HW Save Register", 0x010, NI_660x_READ, DATA_4B}, - {"G1 HW Save Register", 0x014, NI_660x_READ, DATA_4B}, - {"STC DIO Output", 0x014, NI_660x_WRITE, DATA_2B}, - {"STC DIO Control", 0x016, NI_660x_WRITE, DATA_2B}, - {"G0 SW Save Register", 0x018, NI_660x_READ, DATA_4B}, - {"G1 SW Save Register", 0x01C, NI_660x_READ, DATA_4B}, - {"G0 Mode Register", 0x034, NI_660x_WRITE, DATA_2B}, - {"G01 Joint Status 1 Register", 0x036, NI_660x_READ, DATA_2B}, - {"G1 Mode Register", 0x036, NI_660x_WRITE, DATA_2B}, - {"STC DIO Serial Input", 0x038, NI_660x_READ, DATA_2B}, - {"G0 Load A Register", 0x038, NI_660x_WRITE, DATA_4B}, - {"G01 Joint Status 2 Register", 0x03A, NI_660x_READ, DATA_2B}, - {"G0 Load B Register", 0x03C, NI_660x_WRITE, DATA_4B}, - {"G1 Load A Register", 0x040, NI_660x_WRITE, DATA_4B}, - {"G1 Load B Register", 0x044, NI_660x_WRITE, DATA_4B}, - {"G0 Input Select Register", 0x048, NI_660x_WRITE, DATA_2B}, - {"G1 Input Select Register", 0x04A, NI_660x_WRITE, DATA_2B}, - {"G0 Autoincrement Register", 0x088, NI_660x_WRITE, DATA_2B}, - {"G1 Autoincrement Register", 0x08A, NI_660x_WRITE, DATA_2B}, - {"G01 Joint Reset Register", 0x090, NI_660x_WRITE, DATA_2B}, - {"G0 Interrupt Enable", 0x092, NI_660x_WRITE, DATA_2B}, - {"G1 Interrupt Enable", 0x096, NI_660x_WRITE, DATA_2B}, - {"G0 Counting Mode Register", 0x0B0, NI_660x_WRITE, DATA_2B}, - {"G1 Counting Mode Register", 0x0B2, NI_660x_WRITE, DATA_2B}, - {"G0 Second Gate Register", 0x0B4, NI_660x_WRITE, DATA_2B}, - {"G1 Second Gate Register", 0x0B6, NI_660x_WRITE, DATA_2B}, - {"G0 DMA Config Register", 0x0B8, NI_660x_WRITE, DATA_2B}, - {"G0 DMA Status Register", 0x0B8, NI_660x_READ, DATA_2B}, - {"G1 DMA Config Register", 0x0BA, NI_660x_WRITE, DATA_2B}, - {"G1 DMA Status Register", 0x0BA, NI_660x_READ, DATA_2B}, - {"G2 Interrupt Acknowledge", 0x104, NI_660x_WRITE, DATA_2B}, - {"G2 Status Register", 0x104, NI_660x_READ, DATA_2B}, - {"G3 Interrupt Acknowledge", 0x106, NI_660x_WRITE, DATA_2B}, - {"G3 Status Register", 0x106, NI_660x_READ, DATA_2B}, - {"G23 Status Register", 0x108, NI_660x_READ, DATA_2B}, - {"G2 Command Register", 0x10C, NI_660x_WRITE, DATA_2B}, - {"G3 Command Register", 0x10E, NI_660x_WRITE, DATA_2B}, - {"G2 HW Save Register", 0x110, NI_660x_READ, DATA_4B}, - {"G3 HW Save Register", 0x114, NI_660x_READ, DATA_4B}, - {"G2 SW Save Register", 0x118, NI_660x_READ, DATA_4B}, - {"G3 SW Save Register", 0x11C, NI_660x_READ, DATA_4B}, - {"G2 Mode Register", 0x134, NI_660x_WRITE, DATA_2B}, - {"G23 Joint Status 1 Register", 0x136, NI_660x_READ, DATA_2B}, - {"G3 Mode Register", 0x136, NI_660x_WRITE, DATA_2B}, - {"G2 Load A Register", 0x138, NI_660x_WRITE, DATA_4B}, - {"G23 Joint Status 2 Register", 0x13A, NI_660x_READ, DATA_2B}, - {"G2 Load B Register", 0x13C, NI_660x_WRITE, DATA_4B}, - {"G3 Load A Register", 0x140, NI_660x_WRITE, DATA_4B}, - {"G3 Load B Register", 0x144, NI_660x_WRITE, DATA_4B}, - {"G2 Input Select Register", 0x148, NI_660x_WRITE, DATA_2B}, - {"G3 Input Select Register", 0x14A, NI_660x_WRITE, DATA_2B}, - {"G2 Autoincrement Register", 0x188, NI_660x_WRITE, DATA_2B}, - {"G3 Autoincrement Register", 0x18A, NI_660x_WRITE, DATA_2B}, - {"G23 Joint Reset Register", 0x190, NI_660x_WRITE, DATA_2B}, - {"G2 Interrupt Enable", 0x192, NI_660x_WRITE, DATA_2B}, - {"G3 Interrupt Enable", 0x196, NI_660x_WRITE, DATA_2B}, - {"G2 Counting Mode Register", 0x1B0, NI_660x_WRITE, DATA_2B}, - {"G3 Counting Mode Register", 0x1B2, NI_660x_WRITE, DATA_2B}, - {"G3 Second Gate Register", 0x1B6, NI_660x_WRITE, DATA_2B}, - {"G2 Second Gate Register", 0x1B4, NI_660x_WRITE, DATA_2B}, - {"G2 DMA Config Register", 0x1B8, NI_660x_WRITE, DATA_2B}, - {"G2 DMA Status Register", 0x1B8, NI_660x_READ, DATA_2B}, - {"G3 DMA Config Register", 0x1BA, NI_660x_WRITE, DATA_2B}, - {"G3 DMA Status Register", 0x1BA, NI_660x_READ, DATA_2B}, - {"32 bit Digital Input", 0x414, NI_660x_READ, DATA_4B}, - {"32 bit Digital Output", 0x510, NI_660x_WRITE, DATA_4B}, - {"Clock Config Register", 0x73C, NI_660x_WRITE, DATA_4B}, - {"Global Interrupt Status Register", 0x754, NI_660x_READ, DATA_4B}, - {"DMA Configuration Register", 0x76C, NI_660x_WRITE, DATA_4B}, - {"Global Interrupt Config Register", 0x770, NI_660x_WRITE, DATA_4B}, - {"IO Config Register 0-1", 0x77C, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 2-3", 0x77E, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 4-5", 0x780, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 6-7", 0x782, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 8-9", 0x784, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 10-11", 0x786, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 12-13", 0x788, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 14-15", 0x78A, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 16-17", 0x78C, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 18-19", 0x78E, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 20-21", 0x790, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 22-23", 0x792, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 24-25", 0x794, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 26-27", 0x796, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 28-29", 0x798, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 30-31", 0x79A, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 32-33", 0x79C, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 34-35", 0x79E, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 36-37", 0x7A0, NI_660x_READ_WRITE, DATA_2B}, - {"IO Config Register 38-39", 0x7A2, NI_660x_READ_WRITE, DATA_2B} + [NI660X_G0_INT_ACK] = {0x004, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_STATUS] = {0x004, NI_660x_READ, DATA_2B}, + [NI660X_G1_INT_ACK] = {0x006, NI_660x_WRITE, DATA_2B}, + [NI660X_G1_STATUS] = {0x006, NI_660x_READ, DATA_2B}, + [NI660X_G01_STATUS] = {0x008, NI_660x_READ, DATA_2B}, + [NI660X_G0_CMD] = {0x00c, NI_660x_WRITE, DATA_2B}, + [NI660X_STC_DIO_PARALLEL_INPUT] = {0x00e, NI_660x_READ, DATA_2B}, + [NI660X_G1_CMD] = {0x00e, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_HW_SAVE] = {0x010, NI_660x_READ, DATA_4B}, + [NI660X_G1_HW_SAVE] = {0x014, NI_660x_READ, DATA_4B}, + [NI660X_STC_DIO_OUTPUT] = {0x014, NI_660x_WRITE, DATA_2B}, + [NI660X_STC_DIO_CONTROL] = {0x016, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_SW_SAVE] = {0x018, NI_660x_READ, DATA_4B}, + [NI660X_G1_SW_SAVE] = {0x01c, NI_660x_READ, DATA_4B}, + [NI660X_G0_MODE] = {0x034, NI_660x_WRITE, DATA_2B}, + [NI660X_G01_STATUS1] = {0x036, NI_660x_READ, DATA_2B}, + [NI660X_G1_MODE] = {0x036, NI_660x_WRITE, DATA_2B}, + [NI660X_STC_DIO_SERIAL_INPUT] = {0x038, NI_660x_READ, DATA_2B}, + [NI660X_G0_LOADA] = {0x038, NI_660x_WRITE, DATA_4B}, + [NI660X_G01_STATUS2] = {0x03a, NI_660x_READ, DATA_2B}, + [NI660X_G0_LOADB] = {0x03c, NI_660x_WRITE, DATA_4B}, + [NI660X_G1_LOADA] = {0x040, NI_660x_WRITE, DATA_4B}, + [NI660X_G1_LOADB] = {0x044, NI_660x_WRITE, DATA_4B}, + [NI660X_G0_INPUT_SEL] = {0x048, NI_660x_WRITE, DATA_2B}, + [NI660X_G1_INPUT_SEL] = {0x04a, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_AUTO_INC] = {0x088, NI_660x_WRITE, DATA_2B}, + [NI660X_G1_AUTO_INC] = {0x08a, NI_660x_WRITE, DATA_2B}, + [NI660X_G01_RESET] = {0x090, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_INT_ENA] = {0x092, NI_660x_WRITE, DATA_2B}, + [NI660X_G1_INT_ENA] = {0x096, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_CNT_MODE] = {0x0b0, NI_660x_WRITE, DATA_2B}, + [NI660X_G1_CNT_MODE] = {0x0b2, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_GATE2] = {0x0b4, NI_660x_WRITE, DATA_2B}, + [NI660X_G1_GATE2] = {0x0b6, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_DMA_CFG] = {0x0b8, NI_660x_WRITE, DATA_2B}, + [NI660X_G0_DMA_STATUS] = {0x0b8, NI_660x_READ, DATA_2B}, + [NI660X_G1_DMA_CFG] = {0x0ba, NI_660x_WRITE, DATA_2B}, + [NI660X_G1_DMA_STATUS] = {0x0ba, NI_660x_READ, DATA_2B}, + [NI660X_G2_INT_ACK] = {0x104, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_STATUS] = {0x104, NI_660x_READ, DATA_2B}, + [NI660X_G3_INT_ACK] = {0x106, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_STATUS] = {0x106, NI_660x_READ, DATA_2B}, + [NI660X_G23_STATUS] = {0x108, NI_660x_READ, DATA_2B}, + [NI660X_G2_CMD] = {0x10c, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_CMD] = {0x10e, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_HW_SAVE] = {0x110, NI_660x_READ, DATA_4B}, + [NI660X_G3_HW_SAVE] = {0x114, NI_660x_READ, DATA_4B}, + [NI660X_G2_SW_SAVE] = {0x118, NI_660x_READ, DATA_4B}, + [NI660X_G3_SW_SAVE] = {0x11c, NI_660x_READ, DATA_4B}, + [NI660X_G2_MODE] = {0x134, NI_660x_WRITE, DATA_2B}, + [NI660X_G23_STATUS1] = {0x136, NI_660x_READ, DATA_2B}, + [NI660X_G3_MODE] = {0x136, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_LOADA] = {0x138, NI_660x_WRITE, DATA_4B}, + [NI660X_G23_STATUS2] = {0x13a, NI_660x_READ, DATA_2B}, + [NI660X_G2_LOADB] = {0x13c, NI_660x_WRITE, DATA_4B}, + [NI660X_G3_LOADA] = {0x140, NI_660x_WRITE, DATA_4B}, + [NI660X_G3_LOADB] = {0x144, NI_660x_WRITE, DATA_4B}, + [NI660X_G2_INPUT_SEL] = {0x148, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_INPUT_SEL] = {0x14a, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_AUTO_INC] = {0x188, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_AUTO_INC] = {0x18a, NI_660x_WRITE, DATA_2B}, + [NI660X_G23_RESET] = {0x190, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_INT_ENA] = {0x192, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_INT_ENA] = {0x196, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_CNT_MODE] = {0x1b0, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_CNT_MODE] = {0x1b2, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_GATE2] = {0x1b6, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_GATE2] = {0x1b4, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_DMA_CFG] = {0x1b8, NI_660x_WRITE, DATA_2B}, + [NI660X_G2_DMA_STATUS] = {0x1b8, NI_660x_READ, DATA_2B}, + [NI660X_G3_DMA_CFG] = {0x1ba, NI_660x_WRITE, DATA_2B}, + [NI660X_G3_DMA_STATUS] = {0x1ba, NI_660x_READ, DATA_2B}, + [NI660X_DIO32_INPUT] = {0x414, NI_660x_READ, DATA_4B}, + [NI660X_DIO32_OUTPUT] = {0x510, NI_660x_WRITE, DATA_4B}, + [NI660X_CLK_CFG] = {0x73c, NI_660x_WRITE, DATA_4B}, + [NI660X_GLOBAL_INT_STATUS] = {0x754, NI_660x_READ, DATA_4B}, + [NI660X_DMA_CFG] = {0x76c, NI_660x_WRITE, DATA_4B}, + [NI660X_GLOBAL_INT_CFG] = {0x770, NI_660x_WRITE, DATA_4B}, + [NI660X_IO_CFG_0_1] = {0x77c, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_2_3] = {0x77e, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_4_5] = {0x780, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_6_7] = {0x782, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_8_9] = {0x784, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_10_11] = {0x786, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_12_13] = {0x788, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_14_15] = {0x78a, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_16_17] = {0x78c, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_18_19] = {0x78e, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_20_21] = {0x790, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_22_23] = {0x792, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_24_25] = {0x794, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_26_27] = {0x796, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_28_29] = {0x798, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_30_31] = {0x79a, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_32_33] = {0x79c, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_34_35] = {0x79e, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_36_37] = {0x7a0, NI_660x_READ_WRITE, DATA_2B}, + [NI660X_IO_CFG_38_39] = {0x7a2, NI_660x_READ_WRITE, DATA_2B} }; /* kind of ENABLE for the second counter */ -- GitLab From 87090141749ad320d937375dcec6d5b925f728c7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:13 -0700 Subject: [PATCH 0475/9938] staging: comedi: ni_660x: remove enum ni_register_width All the registers are defined struct NI_660xRegisterData and they are either 2 or 4 bytes in size. Remove the enum and just use a char member to define the size as 2 or 4 bytes. Simplify the ni_660x_{write,read}_register() functions and remove the unnecessary BUG() in each. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 226 +++++++++++------------ 1 file changed, 103 insertions(+), 123 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 10bb8394fd99..dbbeb968ae59 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -158,12 +158,6 @@ enum ni_660x_register { #define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) -enum ni_660x_register_width { - DATA_1B, - DATA_2B, - DATA_4B -}; - enum ni_660x_register_direction { NI_660x_READ, NI_660x_WRITE, @@ -189,108 +183,108 @@ static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index) struct NI_660xRegisterData { int offset; /* Offset from base address from GPCT chip */ enum ni_660x_register_direction direction; - enum ni_660x_register_width size; /* 1 byte, 2 bytes, or 4 bytes */ + char size; /* 2 or 4 bytes */ }; static const struct NI_660xRegisterData registerData[NI660X_NUM_REGS] = { - [NI660X_G0_INT_ACK] = {0x004, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_STATUS] = {0x004, NI_660x_READ, DATA_2B}, - [NI660X_G1_INT_ACK] = {0x006, NI_660x_WRITE, DATA_2B}, - [NI660X_G1_STATUS] = {0x006, NI_660x_READ, DATA_2B}, - [NI660X_G01_STATUS] = {0x008, NI_660x_READ, DATA_2B}, - [NI660X_G0_CMD] = {0x00c, NI_660x_WRITE, DATA_2B}, - [NI660X_STC_DIO_PARALLEL_INPUT] = {0x00e, NI_660x_READ, DATA_2B}, - [NI660X_G1_CMD] = {0x00e, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_HW_SAVE] = {0x010, NI_660x_READ, DATA_4B}, - [NI660X_G1_HW_SAVE] = {0x014, NI_660x_READ, DATA_4B}, - [NI660X_STC_DIO_OUTPUT] = {0x014, NI_660x_WRITE, DATA_2B}, - [NI660X_STC_DIO_CONTROL] = {0x016, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_SW_SAVE] = {0x018, NI_660x_READ, DATA_4B}, - [NI660X_G1_SW_SAVE] = {0x01c, NI_660x_READ, DATA_4B}, - [NI660X_G0_MODE] = {0x034, NI_660x_WRITE, DATA_2B}, - [NI660X_G01_STATUS1] = {0x036, NI_660x_READ, DATA_2B}, - [NI660X_G1_MODE] = {0x036, NI_660x_WRITE, DATA_2B}, - [NI660X_STC_DIO_SERIAL_INPUT] = {0x038, NI_660x_READ, DATA_2B}, - [NI660X_G0_LOADA] = {0x038, NI_660x_WRITE, DATA_4B}, - [NI660X_G01_STATUS2] = {0x03a, NI_660x_READ, DATA_2B}, - [NI660X_G0_LOADB] = {0x03c, NI_660x_WRITE, DATA_4B}, - [NI660X_G1_LOADA] = {0x040, NI_660x_WRITE, DATA_4B}, - [NI660X_G1_LOADB] = {0x044, NI_660x_WRITE, DATA_4B}, - [NI660X_G0_INPUT_SEL] = {0x048, NI_660x_WRITE, DATA_2B}, - [NI660X_G1_INPUT_SEL] = {0x04a, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_AUTO_INC] = {0x088, NI_660x_WRITE, DATA_2B}, - [NI660X_G1_AUTO_INC] = {0x08a, NI_660x_WRITE, DATA_2B}, - [NI660X_G01_RESET] = {0x090, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_INT_ENA] = {0x092, NI_660x_WRITE, DATA_2B}, - [NI660X_G1_INT_ENA] = {0x096, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_CNT_MODE] = {0x0b0, NI_660x_WRITE, DATA_2B}, - [NI660X_G1_CNT_MODE] = {0x0b2, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_GATE2] = {0x0b4, NI_660x_WRITE, DATA_2B}, - [NI660X_G1_GATE2] = {0x0b6, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_DMA_CFG] = {0x0b8, NI_660x_WRITE, DATA_2B}, - [NI660X_G0_DMA_STATUS] = {0x0b8, NI_660x_READ, DATA_2B}, - [NI660X_G1_DMA_CFG] = {0x0ba, NI_660x_WRITE, DATA_2B}, - [NI660X_G1_DMA_STATUS] = {0x0ba, NI_660x_READ, DATA_2B}, - [NI660X_G2_INT_ACK] = {0x104, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_STATUS] = {0x104, NI_660x_READ, DATA_2B}, - [NI660X_G3_INT_ACK] = {0x106, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_STATUS] = {0x106, NI_660x_READ, DATA_2B}, - [NI660X_G23_STATUS] = {0x108, NI_660x_READ, DATA_2B}, - [NI660X_G2_CMD] = {0x10c, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_CMD] = {0x10e, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_HW_SAVE] = {0x110, NI_660x_READ, DATA_4B}, - [NI660X_G3_HW_SAVE] = {0x114, NI_660x_READ, DATA_4B}, - [NI660X_G2_SW_SAVE] = {0x118, NI_660x_READ, DATA_4B}, - [NI660X_G3_SW_SAVE] = {0x11c, NI_660x_READ, DATA_4B}, - [NI660X_G2_MODE] = {0x134, NI_660x_WRITE, DATA_2B}, - [NI660X_G23_STATUS1] = {0x136, NI_660x_READ, DATA_2B}, - [NI660X_G3_MODE] = {0x136, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_LOADA] = {0x138, NI_660x_WRITE, DATA_4B}, - [NI660X_G23_STATUS2] = {0x13a, NI_660x_READ, DATA_2B}, - [NI660X_G2_LOADB] = {0x13c, NI_660x_WRITE, DATA_4B}, - [NI660X_G3_LOADA] = {0x140, NI_660x_WRITE, DATA_4B}, - [NI660X_G3_LOADB] = {0x144, NI_660x_WRITE, DATA_4B}, - [NI660X_G2_INPUT_SEL] = {0x148, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_INPUT_SEL] = {0x14a, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_AUTO_INC] = {0x188, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_AUTO_INC] = {0x18a, NI_660x_WRITE, DATA_2B}, - [NI660X_G23_RESET] = {0x190, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_INT_ENA] = {0x192, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_INT_ENA] = {0x196, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_CNT_MODE] = {0x1b0, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_CNT_MODE] = {0x1b2, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_GATE2] = {0x1b6, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_GATE2] = {0x1b4, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_DMA_CFG] = {0x1b8, NI_660x_WRITE, DATA_2B}, - [NI660X_G2_DMA_STATUS] = {0x1b8, NI_660x_READ, DATA_2B}, - [NI660X_G3_DMA_CFG] = {0x1ba, NI_660x_WRITE, DATA_2B}, - [NI660X_G3_DMA_STATUS] = {0x1ba, NI_660x_READ, DATA_2B}, - [NI660X_DIO32_INPUT] = {0x414, NI_660x_READ, DATA_4B}, - [NI660X_DIO32_OUTPUT] = {0x510, NI_660x_WRITE, DATA_4B}, - [NI660X_CLK_CFG] = {0x73c, NI_660x_WRITE, DATA_4B}, - [NI660X_GLOBAL_INT_STATUS] = {0x754, NI_660x_READ, DATA_4B}, - [NI660X_DMA_CFG] = {0x76c, NI_660x_WRITE, DATA_4B}, - [NI660X_GLOBAL_INT_CFG] = {0x770, NI_660x_WRITE, DATA_4B}, - [NI660X_IO_CFG_0_1] = {0x77c, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_2_3] = {0x77e, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_4_5] = {0x780, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_6_7] = {0x782, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_8_9] = {0x784, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_10_11] = {0x786, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_12_13] = {0x788, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_14_15] = {0x78a, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_16_17] = {0x78c, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_18_19] = {0x78e, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_20_21] = {0x790, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_22_23] = {0x792, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_24_25] = {0x794, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_26_27] = {0x796, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_28_29] = {0x798, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_30_31] = {0x79a, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_32_33] = {0x79c, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_34_35] = {0x79e, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_36_37] = {0x7a0, NI_660x_READ_WRITE, DATA_2B}, - [NI660X_IO_CFG_38_39] = {0x7a2, NI_660x_READ_WRITE, DATA_2B} + [NI660X_G0_INT_ACK] = { 0x004, NI_660x_WRITE, 2 }, + [NI660X_G0_STATUS] = { 0x004, NI_660x_READ, 2 }, + [NI660X_G1_INT_ACK] = { 0x006, NI_660x_WRITE, 2 }, + [NI660X_G1_STATUS] = { 0x006, NI_660x_READ, 2 }, + [NI660X_G01_STATUS] = { 0x008, NI_660x_READ, 2 }, + [NI660X_G0_CMD] = { 0x00c, NI_660x_WRITE, 2 }, + [NI660X_STC_DIO_PARALLEL_INPUT] = { 0x00e, NI_660x_READ, 2 }, + [NI660X_G1_CMD] = { 0x00e, NI_660x_WRITE, 2 }, + [NI660X_G0_HW_SAVE] = { 0x010, NI_660x_READ, 4 }, + [NI660X_G1_HW_SAVE] = { 0x014, NI_660x_READ, 4 }, + [NI660X_STC_DIO_OUTPUT] = { 0x014, NI_660x_WRITE, 2 }, + [NI660X_STC_DIO_CONTROL] = { 0x016, NI_660x_WRITE, 2 }, + [NI660X_G0_SW_SAVE] = { 0x018, NI_660x_READ, 4 }, + [NI660X_G1_SW_SAVE] = { 0x01c, NI_660x_READ, 4 }, + [NI660X_G0_MODE] = { 0x034, NI_660x_WRITE, 2 }, + [NI660X_G01_STATUS1] = { 0x036, NI_660x_READ, 2 }, + [NI660X_G1_MODE] = { 0x036, NI_660x_WRITE, 2 }, + [NI660X_STC_DIO_SERIAL_INPUT] = { 0x038, NI_660x_READ, 2 }, + [NI660X_G0_LOADA] = { 0x038, NI_660x_WRITE, 4 }, + [NI660X_G01_STATUS2] = { 0x03a, NI_660x_READ, 2 }, + [NI660X_G0_LOADB] = { 0x03c, NI_660x_WRITE, 4 }, + [NI660X_G1_LOADA] = { 0x040, NI_660x_WRITE, 4 }, + [NI660X_G1_LOADB] = { 0x044, NI_660x_WRITE, 4 }, + [NI660X_G0_INPUT_SEL] = { 0x048, NI_660x_WRITE, 2 }, + [NI660X_G1_INPUT_SEL] = { 0x04a, NI_660x_WRITE, 2 }, + [NI660X_G0_AUTO_INC] = { 0x088, NI_660x_WRITE, 2 }, + [NI660X_G1_AUTO_INC] = { 0x08a, NI_660x_WRITE, 2 }, + [NI660X_G01_RESET] = { 0x090, NI_660x_WRITE, 2 }, + [NI660X_G0_INT_ENA] = { 0x092, NI_660x_WRITE, 2 }, + [NI660X_G1_INT_ENA] = { 0x096, NI_660x_WRITE, 2 }, + [NI660X_G0_CNT_MODE] = { 0x0b0, NI_660x_WRITE, 2 }, + [NI660X_G1_CNT_MODE] = { 0x0b2, NI_660x_WRITE, 2 }, + [NI660X_G0_GATE2] = { 0x0b4, NI_660x_WRITE, 2 }, + [NI660X_G1_GATE2] = { 0x0b6, NI_660x_WRITE, 2 }, + [NI660X_G0_DMA_CFG] = { 0x0b8, NI_660x_WRITE, 2 }, + [NI660X_G0_DMA_STATUS] = { 0x0b8, NI_660x_READ, 2 }, + [NI660X_G1_DMA_CFG] = { 0x0ba, NI_660x_WRITE, 2 }, + [NI660X_G1_DMA_STATUS] = { 0x0ba, NI_660x_READ, 2 }, + [NI660X_G2_INT_ACK] = { 0x104, NI_660x_WRITE, 2 }, + [NI660X_G2_STATUS] = { 0x104, NI_660x_READ, 2 }, + [NI660X_G3_INT_ACK] = { 0x106, NI_660x_WRITE, 2 }, + [NI660X_G3_STATUS] = { 0x106, NI_660x_READ, 2 }, + [NI660X_G23_STATUS] = { 0x108, NI_660x_READ, 2 }, + [NI660X_G2_CMD] = { 0x10c, NI_660x_WRITE, 2 }, + [NI660X_G3_CMD] = { 0x10e, NI_660x_WRITE, 2 }, + [NI660X_G2_HW_SAVE] = { 0x110, NI_660x_READ, 4 }, + [NI660X_G3_HW_SAVE] = { 0x114, NI_660x_READ, 4 }, + [NI660X_G2_SW_SAVE] = { 0x118, NI_660x_READ, 4 }, + [NI660X_G3_SW_SAVE] = { 0x11c, NI_660x_READ, 4 }, + [NI660X_G2_MODE] = { 0x134, NI_660x_WRITE, 2 }, + [NI660X_G23_STATUS1] = { 0x136, NI_660x_READ, 2 }, + [NI660X_G3_MODE] = { 0x136, NI_660x_WRITE, 2 }, + [NI660X_G2_LOADA] = { 0x138, NI_660x_WRITE, 4 }, + [NI660X_G23_STATUS2] = { 0x13a, NI_660x_READ, 2 }, + [NI660X_G2_LOADB] = { 0x13c, NI_660x_WRITE, 4 }, + [NI660X_G3_LOADA] = { 0x140, NI_660x_WRITE, 4 }, + [NI660X_G3_LOADB] = { 0x144, NI_660x_WRITE, 4 }, + [NI660X_G2_INPUT_SEL] = { 0x148, NI_660x_WRITE, 2 }, + [NI660X_G3_INPUT_SEL] = { 0x14a, NI_660x_WRITE, 2 }, + [NI660X_G2_AUTO_INC] = { 0x188, NI_660x_WRITE, 2 }, + [NI660X_G3_AUTO_INC] = { 0x18a, NI_660x_WRITE, 2 }, + [NI660X_G23_RESET] = { 0x190, NI_660x_WRITE, 2 }, + [NI660X_G2_INT_ENA] = { 0x192, NI_660x_WRITE, 2 }, + [NI660X_G3_INT_ENA] = { 0x196, NI_660x_WRITE, 2 }, + [NI660X_G2_CNT_MODE] = { 0x1b0, NI_660x_WRITE, 2 }, + [NI660X_G3_CNT_MODE] = { 0x1b2, NI_660x_WRITE, 2 }, + [NI660X_G3_GATE2] = { 0x1b6, NI_660x_WRITE, 2 }, + [NI660X_G2_GATE2] = { 0x1b4, NI_660x_WRITE, 2 }, + [NI660X_G2_DMA_CFG] = { 0x1b8, NI_660x_WRITE, 2 }, + [NI660X_G2_DMA_STATUS] = { 0x1b8, NI_660x_READ, 2 }, + [NI660X_G3_DMA_CFG] = { 0x1ba, NI_660x_WRITE, 2 }, + [NI660X_G3_DMA_STATUS] = { 0x1ba, NI_660x_READ, 2 }, + [NI660X_DIO32_INPUT] = { 0x414, NI_660x_READ, 4 }, + [NI660X_DIO32_OUTPUT] = { 0x510, NI_660x_WRITE, 4 }, + [NI660X_CLK_CFG] = { 0x73c, NI_660x_WRITE, 4 }, + [NI660X_GLOBAL_INT_STATUS] = { 0x754, NI_660x_READ, 4 }, + [NI660X_DMA_CFG] = { 0x76c, NI_660x_WRITE, 4 }, + [NI660X_GLOBAL_INT_CFG] = { 0x770, NI_660x_WRITE, 4 }, + [NI660X_IO_CFG_0_1] = { 0x77c, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_2_3] = { 0x77e, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_4_5] = { 0x780, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_6_7] = { 0x782, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_8_9] = { 0x784, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_10_11] = { 0x786, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_12_13] = { 0x788, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_14_15] = { 0x78a, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_16_17] = { 0x78c, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_18_19] = { 0x78e, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_20_21] = { 0x790, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_22_23] = { 0x792, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_24_25] = { 0x794, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_26_27] = { 0x796, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_28_29] = { 0x798, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_30_31] = { 0x79a, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_32_33] = { 0x79c, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_34_35] = { 0x79e, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_36_37] = { 0x7a0, NI_660x_READ_WRITE, 2 }, + [NI660X_IO_CFG_38_39] = { 0x7a2, NI_660x_READ_WRITE, 2 } }; /* kind of ENABLE for the second counter */ @@ -579,17 +573,10 @@ static inline void ni_660x_write_register(struct comedi_device *dev, { unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset; - switch (registerData[reg].size) { - case DATA_2B: + if (registerData[reg].size == 2) writew(bits, dev->mmio + addr); - break; - case DATA_4B: + else writel(bits, dev->mmio + addr); - break; - default: - BUG(); - break; - } } static inline unsigned ni_660x_read_register(struct comedi_device *dev, @@ -598,16 +585,9 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev, { unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset; - switch (registerData[reg].size) { - case DATA_2B: + if (registerData[reg].size == 2) return readw(dev->mmio + addr); - case DATA_4B: - return readl(dev->mmio + addr); - default: - BUG(); - break; - } - return 0; + return readl(dev->mmio + addr); } static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, -- GitLab From 9392e5dde2652ec335f48f28db3c0433cbdc9d92 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:14 -0700 Subject: [PATCH 0476/9938] staging: comedi: ni_660x: remove enum ni_660x_register_direction This enum is used to define the, unused, 'direction' of each register in struct NI_660xRegisterData. Remove the unused member, as well as the enum. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 203 +++++++++++------------ 1 file changed, 98 insertions(+), 105 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index dbbeb968ae59..409a776caac7 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -158,12 +158,6 @@ enum ni_660x_register { #define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) -enum ni_660x_register_direction { - NI_660x_READ, - NI_660x_WRITE, - NI_660x_READ_WRITE -}; - enum ni_660x_pfi_output_select { pfi_output_select_high_Z = 0, pfi_output_select_counter = 1, @@ -182,109 +176,108 @@ static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index) struct NI_660xRegisterData { int offset; /* Offset from base address from GPCT chip */ - enum ni_660x_register_direction direction; char size; /* 2 or 4 bytes */ }; static const struct NI_660xRegisterData registerData[NI660X_NUM_REGS] = { - [NI660X_G0_INT_ACK] = { 0x004, NI_660x_WRITE, 2 }, - [NI660X_G0_STATUS] = { 0x004, NI_660x_READ, 2 }, - [NI660X_G1_INT_ACK] = { 0x006, NI_660x_WRITE, 2 }, - [NI660X_G1_STATUS] = { 0x006, NI_660x_READ, 2 }, - [NI660X_G01_STATUS] = { 0x008, NI_660x_READ, 2 }, - [NI660X_G0_CMD] = { 0x00c, NI_660x_WRITE, 2 }, - [NI660X_STC_DIO_PARALLEL_INPUT] = { 0x00e, NI_660x_READ, 2 }, - [NI660X_G1_CMD] = { 0x00e, NI_660x_WRITE, 2 }, - [NI660X_G0_HW_SAVE] = { 0x010, NI_660x_READ, 4 }, - [NI660X_G1_HW_SAVE] = { 0x014, NI_660x_READ, 4 }, - [NI660X_STC_DIO_OUTPUT] = { 0x014, NI_660x_WRITE, 2 }, - [NI660X_STC_DIO_CONTROL] = { 0x016, NI_660x_WRITE, 2 }, - [NI660X_G0_SW_SAVE] = { 0x018, NI_660x_READ, 4 }, - [NI660X_G1_SW_SAVE] = { 0x01c, NI_660x_READ, 4 }, - [NI660X_G0_MODE] = { 0x034, NI_660x_WRITE, 2 }, - [NI660X_G01_STATUS1] = { 0x036, NI_660x_READ, 2 }, - [NI660X_G1_MODE] = { 0x036, NI_660x_WRITE, 2 }, - [NI660X_STC_DIO_SERIAL_INPUT] = { 0x038, NI_660x_READ, 2 }, - [NI660X_G0_LOADA] = { 0x038, NI_660x_WRITE, 4 }, - [NI660X_G01_STATUS2] = { 0x03a, NI_660x_READ, 2 }, - [NI660X_G0_LOADB] = { 0x03c, NI_660x_WRITE, 4 }, - [NI660X_G1_LOADA] = { 0x040, NI_660x_WRITE, 4 }, - [NI660X_G1_LOADB] = { 0x044, NI_660x_WRITE, 4 }, - [NI660X_G0_INPUT_SEL] = { 0x048, NI_660x_WRITE, 2 }, - [NI660X_G1_INPUT_SEL] = { 0x04a, NI_660x_WRITE, 2 }, - [NI660X_G0_AUTO_INC] = { 0x088, NI_660x_WRITE, 2 }, - [NI660X_G1_AUTO_INC] = { 0x08a, NI_660x_WRITE, 2 }, - [NI660X_G01_RESET] = { 0x090, NI_660x_WRITE, 2 }, - [NI660X_G0_INT_ENA] = { 0x092, NI_660x_WRITE, 2 }, - [NI660X_G1_INT_ENA] = { 0x096, NI_660x_WRITE, 2 }, - [NI660X_G0_CNT_MODE] = { 0x0b0, NI_660x_WRITE, 2 }, - [NI660X_G1_CNT_MODE] = { 0x0b2, NI_660x_WRITE, 2 }, - [NI660X_G0_GATE2] = { 0x0b4, NI_660x_WRITE, 2 }, - [NI660X_G1_GATE2] = { 0x0b6, NI_660x_WRITE, 2 }, - [NI660X_G0_DMA_CFG] = { 0x0b8, NI_660x_WRITE, 2 }, - [NI660X_G0_DMA_STATUS] = { 0x0b8, NI_660x_READ, 2 }, - [NI660X_G1_DMA_CFG] = { 0x0ba, NI_660x_WRITE, 2 }, - [NI660X_G1_DMA_STATUS] = { 0x0ba, NI_660x_READ, 2 }, - [NI660X_G2_INT_ACK] = { 0x104, NI_660x_WRITE, 2 }, - [NI660X_G2_STATUS] = { 0x104, NI_660x_READ, 2 }, - [NI660X_G3_INT_ACK] = { 0x106, NI_660x_WRITE, 2 }, - [NI660X_G3_STATUS] = { 0x106, NI_660x_READ, 2 }, - [NI660X_G23_STATUS] = { 0x108, NI_660x_READ, 2 }, - [NI660X_G2_CMD] = { 0x10c, NI_660x_WRITE, 2 }, - [NI660X_G3_CMD] = { 0x10e, NI_660x_WRITE, 2 }, - [NI660X_G2_HW_SAVE] = { 0x110, NI_660x_READ, 4 }, - [NI660X_G3_HW_SAVE] = { 0x114, NI_660x_READ, 4 }, - [NI660X_G2_SW_SAVE] = { 0x118, NI_660x_READ, 4 }, - [NI660X_G3_SW_SAVE] = { 0x11c, NI_660x_READ, 4 }, - [NI660X_G2_MODE] = { 0x134, NI_660x_WRITE, 2 }, - [NI660X_G23_STATUS1] = { 0x136, NI_660x_READ, 2 }, - [NI660X_G3_MODE] = { 0x136, NI_660x_WRITE, 2 }, - [NI660X_G2_LOADA] = { 0x138, NI_660x_WRITE, 4 }, - [NI660X_G23_STATUS2] = { 0x13a, NI_660x_READ, 2 }, - [NI660X_G2_LOADB] = { 0x13c, NI_660x_WRITE, 4 }, - [NI660X_G3_LOADA] = { 0x140, NI_660x_WRITE, 4 }, - [NI660X_G3_LOADB] = { 0x144, NI_660x_WRITE, 4 }, - [NI660X_G2_INPUT_SEL] = { 0x148, NI_660x_WRITE, 2 }, - [NI660X_G3_INPUT_SEL] = { 0x14a, NI_660x_WRITE, 2 }, - [NI660X_G2_AUTO_INC] = { 0x188, NI_660x_WRITE, 2 }, - [NI660X_G3_AUTO_INC] = { 0x18a, NI_660x_WRITE, 2 }, - [NI660X_G23_RESET] = { 0x190, NI_660x_WRITE, 2 }, - [NI660X_G2_INT_ENA] = { 0x192, NI_660x_WRITE, 2 }, - [NI660X_G3_INT_ENA] = { 0x196, NI_660x_WRITE, 2 }, - [NI660X_G2_CNT_MODE] = { 0x1b0, NI_660x_WRITE, 2 }, - [NI660X_G3_CNT_MODE] = { 0x1b2, NI_660x_WRITE, 2 }, - [NI660X_G3_GATE2] = { 0x1b6, NI_660x_WRITE, 2 }, - [NI660X_G2_GATE2] = { 0x1b4, NI_660x_WRITE, 2 }, - [NI660X_G2_DMA_CFG] = { 0x1b8, NI_660x_WRITE, 2 }, - [NI660X_G2_DMA_STATUS] = { 0x1b8, NI_660x_READ, 2 }, - [NI660X_G3_DMA_CFG] = { 0x1ba, NI_660x_WRITE, 2 }, - [NI660X_G3_DMA_STATUS] = { 0x1ba, NI_660x_READ, 2 }, - [NI660X_DIO32_INPUT] = { 0x414, NI_660x_READ, 4 }, - [NI660X_DIO32_OUTPUT] = { 0x510, NI_660x_WRITE, 4 }, - [NI660X_CLK_CFG] = { 0x73c, NI_660x_WRITE, 4 }, - [NI660X_GLOBAL_INT_STATUS] = { 0x754, NI_660x_READ, 4 }, - [NI660X_DMA_CFG] = { 0x76c, NI_660x_WRITE, 4 }, - [NI660X_GLOBAL_INT_CFG] = { 0x770, NI_660x_WRITE, 4 }, - [NI660X_IO_CFG_0_1] = { 0x77c, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_2_3] = { 0x77e, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_4_5] = { 0x780, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_6_7] = { 0x782, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_8_9] = { 0x784, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_10_11] = { 0x786, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_12_13] = { 0x788, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_14_15] = { 0x78a, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_16_17] = { 0x78c, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_18_19] = { 0x78e, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_20_21] = { 0x790, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_22_23] = { 0x792, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_24_25] = { 0x794, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_26_27] = { 0x796, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_28_29] = { 0x798, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_30_31] = { 0x79a, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_32_33] = { 0x79c, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_34_35] = { 0x79e, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_36_37] = { 0x7a0, NI_660x_READ_WRITE, 2 }, - [NI660X_IO_CFG_38_39] = { 0x7a2, NI_660x_READ_WRITE, 2 } + [NI660X_G0_INT_ACK] = { 0x004, 2 }, /* write */ + [NI660X_G0_STATUS] = { 0x004, 2 }, /* read */ + [NI660X_G1_INT_ACK] = { 0x006, 2 }, /* write */ + [NI660X_G1_STATUS] = { 0x006, 2 }, /* read */ + [NI660X_G01_STATUS] = { 0x008, 2 }, /* read */ + [NI660X_G0_CMD] = { 0x00c, 2 }, /* write */ + [NI660X_STC_DIO_PARALLEL_INPUT] = { 0x00e, 2 }, /* read */ + [NI660X_G1_CMD] = { 0x00e, 2 }, /* write */ + [NI660X_G0_HW_SAVE] = { 0x010, 4 }, /* read */ + [NI660X_G1_HW_SAVE] = { 0x014, 4 }, /* read */ + [NI660X_STC_DIO_OUTPUT] = { 0x014, 2 }, /* write */ + [NI660X_STC_DIO_CONTROL] = { 0x016, 2 }, /* write */ + [NI660X_G0_SW_SAVE] = { 0x018, 4 }, /* read */ + [NI660X_G1_SW_SAVE] = { 0x01c, 4 }, /* read */ + [NI660X_G0_MODE] = { 0x034, 2 }, /* write */ + [NI660X_G01_STATUS1] = { 0x036, 2 }, /* read */ + [NI660X_G1_MODE] = { 0x036, 2 }, /* write */ + [NI660X_STC_DIO_SERIAL_INPUT] = { 0x038, 2 }, /* read */ + [NI660X_G0_LOADA] = { 0x038, 4 }, /* write */ + [NI660X_G01_STATUS2] = { 0x03a, 2 }, /* read */ + [NI660X_G0_LOADB] = { 0x03c, 4 }, /* write */ + [NI660X_G1_LOADA] = { 0x040, 4 }, /* write */ + [NI660X_G1_LOADB] = { 0x044, 4 }, /* write */ + [NI660X_G0_INPUT_SEL] = { 0x048, 2 }, /* write */ + [NI660X_G1_INPUT_SEL] = { 0x04a, 2 }, /* write */ + [NI660X_G0_AUTO_INC] = { 0x088, 2 }, /* write */ + [NI660X_G1_AUTO_INC] = { 0x08a, 2 }, /* write */ + [NI660X_G01_RESET] = { 0x090, 2 }, /* write */ + [NI660X_G0_INT_ENA] = { 0x092, 2 }, /* write */ + [NI660X_G1_INT_ENA] = { 0x096, 2 }, /* write */ + [NI660X_G0_CNT_MODE] = { 0x0b0, 2 }, /* write */ + [NI660X_G1_CNT_MODE] = { 0x0b2, 2 }, /* write */ + [NI660X_G0_GATE2] = { 0x0b4, 2 }, /* write */ + [NI660X_G1_GATE2] = { 0x0b6, 2 }, /* write */ + [NI660X_G0_DMA_CFG] = { 0x0b8, 2 }, /* write */ + [NI660X_G0_DMA_STATUS] = { 0x0b8, 2 }, /* read */ + [NI660X_G1_DMA_CFG] = { 0x0ba, 2 }, /* write */ + [NI660X_G1_DMA_STATUS] = { 0x0ba, 2 }, /* read */ + [NI660X_G2_INT_ACK] = { 0x104, 2 }, /* write */ + [NI660X_G2_STATUS] = { 0x104, 2 }, /* read */ + [NI660X_G3_INT_ACK] = { 0x106, 2 }, /* write */ + [NI660X_G3_STATUS] = { 0x106, 2 }, /* read */ + [NI660X_G23_STATUS] = { 0x108, 2 }, /* read */ + [NI660X_G2_CMD] = { 0x10c, 2 }, /* write */ + [NI660X_G3_CMD] = { 0x10e, 2 }, /* write */ + [NI660X_G2_HW_SAVE] = { 0x110, 4 }, /* read */ + [NI660X_G3_HW_SAVE] = { 0x114, 4 }, /* read */ + [NI660X_G2_SW_SAVE] = { 0x118, 4 }, /* read */ + [NI660X_G3_SW_SAVE] = { 0x11c, 4 }, /* read */ + [NI660X_G2_MODE] = { 0x134, 2 }, /* write */ + [NI660X_G23_STATUS1] = { 0x136, 2 }, /* read */ + [NI660X_G3_MODE] = { 0x136, 2 }, /* write */ + [NI660X_G2_LOADA] = { 0x138, 4 }, /* write */ + [NI660X_G23_STATUS2] = { 0x13a, 2 }, /* read */ + [NI660X_G2_LOADB] = { 0x13c, 4 }, /* write */ + [NI660X_G3_LOADA] = { 0x140, 4 }, /* write */ + [NI660X_G3_LOADB] = { 0x144, 4 }, /* write */ + [NI660X_G2_INPUT_SEL] = { 0x148, 2 }, /* write */ + [NI660X_G3_INPUT_SEL] = { 0x14a, 2 }, /* write */ + [NI660X_G2_AUTO_INC] = { 0x188, 2 }, /* write */ + [NI660X_G3_AUTO_INC] = { 0x18a, 2 }, /* write */ + [NI660X_G23_RESET] = { 0x190, 2 }, /* write */ + [NI660X_G2_INT_ENA] = { 0x192, 2 }, /* write */ + [NI660X_G3_INT_ENA] = { 0x196, 2 }, /* write */ + [NI660X_G2_CNT_MODE] = { 0x1b0, 2 }, /* write */ + [NI660X_G3_CNT_MODE] = { 0x1b2, 2 }, /* write */ + [NI660X_G3_GATE2] = { 0x1b6, 2 }, /* write */ + [NI660X_G2_GATE2] = { 0x1b4, 2 }, /* write */ + [NI660X_G2_DMA_CFG] = { 0x1b8, 2 }, /* write */ + [NI660X_G2_DMA_STATUS] = { 0x1b8, 2 }, /* read */ + [NI660X_G3_DMA_CFG] = { 0x1ba, 2 }, /* write */ + [NI660X_G3_DMA_STATUS] = { 0x1ba, 2 }, /* read */ + [NI660X_DIO32_INPUT] = { 0x414, 4 }, /* read */ + [NI660X_DIO32_OUTPUT] = { 0x510, 4 }, /* write */ + [NI660X_CLK_CFG] = { 0x73c, 4 }, /* write */ + [NI660X_GLOBAL_INT_STATUS] = { 0x754, 4 }, /* read */ + [NI660X_DMA_CFG] = { 0x76c, 4 }, /* write */ + [NI660X_GLOBAL_INT_CFG] = { 0x770, 4 }, /* write */ + [NI660X_IO_CFG_0_1] = { 0x77c, 2 }, /* read/write */ + [NI660X_IO_CFG_2_3] = { 0x77e, 2 }, /* read/write */ + [NI660X_IO_CFG_4_5] = { 0x780, 2 }, /* read/write */ + [NI660X_IO_CFG_6_7] = { 0x782, 2 }, /* read/write */ + [NI660X_IO_CFG_8_9] = { 0x784, 2 }, /* read/write */ + [NI660X_IO_CFG_10_11] = { 0x786, 2 }, /* read/write */ + [NI660X_IO_CFG_12_13] = { 0x788, 2 }, /* read/write */ + [NI660X_IO_CFG_14_15] = { 0x78a, 2 }, /* read/write */ + [NI660X_IO_CFG_16_17] = { 0x78c, 2 }, /* read/write */ + [NI660X_IO_CFG_18_19] = { 0x78e, 2 }, /* read/write */ + [NI660X_IO_CFG_20_21] = { 0x790, 2 }, /* read/write */ + [NI660X_IO_CFG_22_23] = { 0x792, 2 }, /* read/write */ + [NI660X_IO_CFG_24_25] = { 0x794, 2 }, /* read/write */ + [NI660X_IO_CFG_26_27] = { 0x796, 2 }, /* read/write */ + [NI660X_IO_CFG_28_29] = { 0x798, 2 }, /* read/write */ + [NI660X_IO_CFG_30_31] = { 0x79a, 2 }, /* read/write */ + [NI660X_IO_CFG_32_33] = { 0x79c, 2 }, /* read/write */ + [NI660X_IO_CFG_34_35] = { 0x79e, 2 }, /* read/write */ + [NI660X_IO_CFG_36_37] = { 0x7a0, 2 }, /* read/write */ + [NI660X_IO_CFG_38_39] = { 0x7a2, 2 } /* read/write */ }; /* kind of ENABLE for the second counter */ -- GitLab From b38700a22a62aaaff04e644a7f1c6b2733249294 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:15 -0700 Subject: [PATCH 0477/9938] staging: comedi: ni_660x: rename CamelCase 'NI_660xRegisterData' Rename this CamelCase struct and the associated 'registerData' variable. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 409a776caac7..d76a5b026b91 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -174,12 +174,12 @@ static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index) return NI_660X_GPCT_SUBDEV_0 + index; } -struct NI_660xRegisterData { +struct ni_660x_register_data { int offset; /* Offset from base address from GPCT chip */ char size; /* 2 or 4 bytes */ }; -static const struct NI_660xRegisterData registerData[NI660X_NUM_REGS] = { +static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { [NI660X_G0_INT_ACK] = { 0x004, 2 }, /* write */ [NI660X_G0_STATUS] = { 0x004, 2 }, /* read */ [NI660X_G1_INT_ACK] = { 0x006, 2 }, /* write */ @@ -564,9 +564,9 @@ static inline void ni_660x_write_register(struct comedi_device *dev, unsigned chip, unsigned bits, enum ni_660x_register reg) { - unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset; + unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; - if (registerData[reg].size == 2) + if (ni_660x_reg_data[reg].size == 2) writew(bits, dev->mmio + addr); else writel(bits, dev->mmio + addr); @@ -576,9 +576,9 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev, unsigned chip, enum ni_660x_register reg) { - unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset; + unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; - if (registerData[reg].size == 2) + if (ni_660x_reg_data[reg].size == 2) return readw(dev->mmio + addr); return readl(dev->mmio + addr); } -- GitLab From 01ead0ded315d660b07baccb68ca36c2a7f3da0a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:16 -0700 Subject: [PATCH 0478/9938] staging: comedi: ni_660x: cleanup the NI660X_IO_CFG register helpers Convert the inline functions used to set the bits in the NI600X_IO_CFG registers into macros. Also convert the enum ni_660x_pfi_output_select into defines. This clarifies the association with the register. This also fixes a number of checkpatch.pl issues about: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 81 ++++++++---------------- 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index d76a5b026b91..75c60322a05d 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -156,14 +156,15 @@ enum ni_660x_register { NI660X_NUM_REGS, }; -#define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) - -enum ni_660x_pfi_output_select { - pfi_output_select_high_Z = 0, - pfi_output_select_counter = 1, - pfi_output_select_do = 2, - num_pfi_output_selects -}; +#define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) +#define NI660X_IO_CFG_OUT_SEL(_c, _s) (((_s) & 0x3) << (((_c) % 2) ? 0 : 8)) +#define NI660X_IO_CFG_OUT_SEL_MASK(_c) NI660X_IO_CFG_OUT_SEL((_c), 0x3) +#define NI660X_IO_CFG_OUT_SEL_HIGH_Z 0 +#define NI660X_IO_CFG_OUT_SEL_COUNTER 1 +#define NI660X_IO_CFG_OUT_SEL_DO 2 +#define NI660X_IO_CFG_OUT_SEL_MAX 3 +#define NI660X_IO_CFG_IN_SEL(_c, _s) (((_s) & 0x7) << (((_c) % 2) ? 4 : 12)) +#define NI660X_IO_CFG_IN_SEL_MASK(_c) NI660X_IO_CFG_IN_SEL((_c), 0x7) enum ni_660x_subdevices { NI_660X_DIO_SUBDEV = 1, @@ -285,34 +286,6 @@ enum clock_config_register_bits { CounterSwap = 0x1 << 21 }; -/* ioconfigreg */ -static inline unsigned ioconfig_bitshift(unsigned pfi_channel) -{ - return (pfi_channel % 2) ? 0 : 8; -} - -static inline unsigned pfi_output_select_mask(unsigned pfi_channel) -{ - return 0x3 << ioconfig_bitshift(pfi_channel); -} - -static inline unsigned pfi_output_select_bits(unsigned pfi_channel, - unsigned output_select) -{ - return (output_select & 0x3) << ioconfig_bitshift(pfi_channel); -} - -static inline unsigned pfi_input_select_mask(unsigned pfi_channel) -{ - return 0x7 << (4 + ioconfig_bitshift(pfi_channel)); -} - -static inline unsigned pfi_input_select_bits(unsigned pfi_channel, - unsigned input_select) -{ - return (input_select & 0x7) << (4 + ioconfig_bitshift(pfi_channel)); -} - /* dma configuration register bits */ static inline unsigned dma_select_mask(unsigned dma_channel) { @@ -808,7 +781,7 @@ static int ni_660x_allocate_private(struct comedi_device *dev) spin_lock_init(&devpriv->interrupt_lock); spin_lock_init(&devpriv->soft_reg_copy_lock); for (i = 0; i < NUM_PFI_CHANNELS; ++i) - devpriv->pfi_output_selects[i] = pfi_output_select_counter; + devpriv->pfi_output_selects[i] = NI660X_IO_CFG_OUT_SEL_COUNTER; return 0; } @@ -896,7 +869,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned idle_bits; if (board->n_chips > 1) { - if (output_select == pfi_output_select_counter && + if (output_select == NI660X_IO_CFG_OUT_SEL_COUNTER && pfi_channel >= counter_4_7_first_pfi && pfi_channel <= counter_4_7_last_pfi) { active_chipset = 1; @@ -911,10 +884,10 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, idle_bits = ni_660x_read_register(dev, idle_chipset, NI660X_IO_CFG(pfi_channel)); - idle_bits &= ~pfi_output_select_mask(pfi_channel); + idle_bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(pfi_channel); idle_bits |= - pfi_output_select_bits(pfi_channel, - pfi_output_select_high_Z); + NI660X_IO_CFG_OUT_SEL(pfi_channel, + NI660X_IO_CFG_OUT_SEL_HIGH_Z); ni_660x_write_register(dev, idle_chipset, idle_bits, NI660X_IO_CFG(pfi_channel)); } @@ -922,8 +895,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, active_bits = ni_660x_read_register(dev, active_chipset, NI660X_IO_CFG(pfi_channel)); - active_bits &= ~pfi_output_select_mask(pfi_channel); - active_bits |= pfi_output_select_bits(pfi_channel, output_select); + active_bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(pfi_channel); + active_bits |= NI660X_IO_CFG_OUT_SEL(pfi_channel, output_select); ni_660x_write_register(dev, active_chipset, active_bits, NI660X_IO_CFG(pfi_channel)); } @@ -933,15 +906,15 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan, { struct ni_660x_private *devpriv = dev->private; - if (source > num_pfi_output_selects) + if (source > NI660X_IO_CFG_OUT_SEL_MAX) return -EINVAL; - if (source == pfi_output_select_high_Z) + if (source == NI660X_IO_CFG_OUT_SEL_HIGH_Z) return -EINVAL; if (chan < min_counter_pfi_chan) { - if (source == pfi_output_select_counter) + if (source == NI660X_IO_CFG_OUT_SEL_COUNTER) return -EINVAL; } else if (chan > max_dio_pfi_chan) { - if (source == pfi_output_select_do) + if (source == NI660X_IO_CFG_OUT_SEL_DO) return -EINVAL; } @@ -972,7 +945,8 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, case INSN_CONFIG_DIO_INPUT: devpriv->pfi_direction_bits &= ~bit; - ni_660x_select_pfi_output(dev, chan, pfi_output_select_high_Z); + ni_660x_select_pfi_output(dev, chan, + NI660X_IO_CFG_OUT_SEL_HIGH_Z); break; case INSN_CONFIG_DIO_QUERY: @@ -992,8 +966,8 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, case INSN_CONFIG_FILTER: val = ni_660x_read_register(dev, 0, NI660X_IO_CFG(chan)); - val &= ~pfi_input_select_mask(chan); - val |= pfi_input_select_bits(chan, data[1]); + val &= ~NI660X_IO_CFG_IN_SEL_MASK(chan); + val |= NI660X_IO_CFG_IN_SEL(chan, data[1]); ni_660x_write_register(dev, 0, val, NI660X_IO_CFG(chan)); break; @@ -1108,11 +1082,12 @@ static int ni_660x_auto_attach(struct comedi_device *dev, for (i = 0; i < NUM_PFI_CHANNELS; ++i) { if (i < min_counter_pfi_chan) - ni_660x_set_pfi_routing(dev, i, pfi_output_select_do); + ni_660x_set_pfi_routing(dev, i, + NI660X_IO_CFG_OUT_SEL_DO); else ni_660x_set_pfi_routing(dev, i, - pfi_output_select_counter); - ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z); + NI660X_IO_CFG_OUT_SEL_COUNTER); + ni_660x_select_pfi_output(dev, i, NI660X_IO_CFG_OUT_SEL_HIGH_Z); } /* to be safe, set counterswap bits on tio chips after all the counter outputs have been set to high impedance mode */ -- GitLab From aa36af205e4e7fd94842be73c1f8a5bb5b12d302 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:17 -0700 Subject: [PATCH 0479/9938] staging: comedi: ni_660x: tidy up multi-line comment Reformat the multi-line comment in the kernel CodingStyle. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 25 ++++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 75c60322a05d..ab761aa040d7 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1,17 +1,16 @@ /* - comedi/drivers/ni_660x.c - Hardware driver for NI 660x devices - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Hardware driver for NI 660x devices + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* * Driver: ni_660x -- GitLab From 502552e161aee965026f9b5cc0da3dfb3775a8c7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:18 -0700 Subject: [PATCH 0480/9938] staging: comedi: ni_660x: remove enum clock_config_register_bits Remove this enum and add a define for the bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index ab761aa040d7..30089cd7f89b 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -155,6 +155,8 @@ enum ni_660x_register { NI660X_NUM_REGS, }; +#define NI660X_CLK_CFG_COUNTER_SWAP BIT(21) + #define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) #define NI660X_IO_CFG_OUT_SEL(_c, _s) (((_s) & 0x3) << (((_c) % 2) ? 0 : 8)) #define NI660X_IO_CFG_OUT_SEL_MASK(_c) NI660X_IO_CFG_OUT_SEL((_c), 0x3) @@ -280,11 +282,6 @@ static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { [NI660X_IO_CFG_38_39] = { 0x7a2, 2 } /* read/write */ }; -/* kind of ENABLE for the second counter */ -enum clock_config_register_bits { - CounterSwap = 0x1 << 21 -}; - /* dma configuration register bits */ static inline unsigned dma_select_mask(unsigned dma_channel) { @@ -704,7 +701,7 @@ static void set_tio_counterswap(struct comedi_device *dev, int chip) * first chip. */ if (chip) - bits = CounterSwap; + bits = NI660X_CLK_CFG_COUNTER_SWAP; ni_660x_write_register(dev, chip, bits, NI660X_CLK_CFG); } -- GitLab From fecf4cce0021aebd587f7bbd970806c24988ef26 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:19 -0700 Subject: [PATCH 0481/9938] staging: comedi: ni_660x: cleanup the NI660X_DMA_CFG register helpers The BUG_ON() checks in the helper functions are not necessary. The mite driver quiries the PCI chip to determine the number of DMA channels. This is then used when a DMA channel is requested so the channel will always be in range. Convert the inline functions used to set the bits in the NI600X_DMA_CFG register into macros. Also convert the associated enum dma_selection. This clarifies the association with the register. Rename the associated 'dma_configuration_soft_copies' member of the private data to allow shorting some of the ugly long lines in the driver. This also fixes a number of checkpatch.pl issues about: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 63 +++++++----------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 30089cd7f89b..0b37982f021e 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -157,6 +157,11 @@ enum ni_660x_register { #define NI660X_CLK_CFG_COUNTER_SWAP BIT(21) +#define NI660X_DMA_CFG_SEL(_c, _s) (((_s) & 0x1f) << (8 * (_c))) +#define NI660X_DMA_CFG_SEL_MASK(_c) NI660X_DMA_CFG_SEL((_c), 0x1f) +#define NI660X_DMA_CFG_SEL_NONE(_c) NI660X_DMA_CFG_SEL((_c), 0x1f) +#define NI660X_DMA_CFG_RESET(_c) NI660X_DMA_CFG_SEL((_c), 0x80) + #define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) #define NI660X_IO_CFG_OUT_SEL(_c, _s) (((_s) & 0x3) << (((_c) % 2) ? 0 : 8)) #define NI660X_IO_CFG_OUT_SEL_MASK(_c) NI660X_IO_CFG_OUT_SEL((_c), 0x3) @@ -282,29 +287,6 @@ static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { [NI660X_IO_CFG_38_39] = { 0x7a2, 2 } /* read/write */ }; -/* dma configuration register bits */ -static inline unsigned dma_select_mask(unsigned dma_channel) -{ - BUG_ON(dma_channel >= MAX_DMA_CHANNEL); - return 0x1f << (8 * dma_channel); -} - -enum dma_selection { - dma_selection_none = 0x1f, -}; - -static inline unsigned dma_select_bits(unsigned dma_channel, unsigned selection) -{ - BUG_ON(dma_channel >= MAX_DMA_CHANNEL); - return (selection << (8 * dma_channel)) & dma_select_mask(dma_channel); -} - -static inline unsigned dma_reset_bit(unsigned dma_channel) -{ - BUG_ON(dma_channel >= MAX_DMA_CHANNEL); - return 0x80 << (8 * dma_channel); -} - enum global_interrupt_status_register_bits { Counter_0_Int_Bit = 0x100, Counter_1_Int_Bit = 0x200, @@ -372,7 +354,7 @@ struct ni_660x_private { spinlock_t mite_channel_lock; /* interrupt_lock prevents races between interrupt and comedi_poll */ spinlock_t interrupt_lock; - unsigned dma_configuration_soft_copies[NI_660X_MAX_NUM_CHIPS]; + unsigned dma_cfg[NI_660X_MAX_NUM_CHIPS]; spinlock_t soft_reg_copy_lock; unsigned short pfi_output_selects[NUM_PFI_CHANNELS]; }; @@ -591,13 +573,12 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev, unsigned long flags; spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); - devpriv->dma_configuration_soft_copies[chip] &= - ~dma_select_mask(mite_channel); - devpriv->dma_configuration_soft_copies[chip] |= - dma_select_bits(mite_channel, counter->counter_index); - ni_660x_write_register(dev, chip, - devpriv->dma_configuration_soft_copies[chip] | - dma_reset_bit(mite_channel), NI660X_DMA_CFG); + devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); + devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL(mite_channel, + counter->counter_index); + ni_660x_write_register(dev, chip, devpriv->dma_cfg[chip] | + NI660X_DMA_CFG_RESET(mite_channel), + NI660X_DMA_CFG); mmiowb(); spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); } @@ -611,12 +592,9 @@ static inline void ni_660x_unset_dma_channel(struct comedi_device *dev, unsigned long flags; spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); - devpriv->dma_configuration_soft_copies[chip] &= - ~dma_select_mask(mite_channel); - devpriv->dma_configuration_soft_copies[chip] |= - dma_select_bits(mite_channel, dma_selection_none); - ni_660x_write_register(dev, chip, - devpriv->dma_configuration_soft_copies[chip], + devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); + devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL_NONE(mite_channel); + ni_660x_write_register(dev, chip, devpriv->dma_cfg[chip], NI660X_DMA_CFG); mmiowb(); spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); @@ -819,13 +797,10 @@ static void init_tio_chip(struct comedi_device *dev, int chipset) unsigned i; /* init dma configuration register */ - devpriv->dma_configuration_soft_copies[chipset] = 0; - for (i = 0; i < MAX_DMA_CHANNEL; ++i) { - devpriv->dma_configuration_soft_copies[chipset] |= - dma_select_bits(i, dma_selection_none) & dma_select_mask(i); - } - ni_660x_write_register(dev, chipset, - devpriv->dma_configuration_soft_copies[chipset], + devpriv->dma_cfg[chipset] = 0; + for (i = 0; i < MAX_DMA_CHANNEL; ++i) + devpriv->dma_cfg[chipset] |= NI660X_DMA_CFG_SEL_NONE(i); + ni_660x_write_register(dev, chipset, devpriv->dma_cfg[chipset], NI660X_DMA_CFG); for (i = 0; i < NUM_PFI_CHANNELS; ++i) ni_660x_write_register(dev, chipset, 0, NI660X_IO_CFG(i)); -- GitLab From 41014593caebadec2f022d96d3326816599d439d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:20 -0700 Subject: [PATCH 0482/9938] staging: comedi: ni_660x: cleanup the NI660X_GLOBAL_INT_{STATUS, CFG} Remove the enums global_interrupt_{status,config}_register_bits and add defines for the CamelCase values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 27 +++++++++--------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 0b37982f021e..773147af4137 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -157,6 +157,14 @@ enum ni_660x_register { #define NI660X_CLK_CFG_COUNTER_SWAP BIT(21) +#define NI660X_GLOBAL_INT_COUNTER0 BIT(8) +#define NI660X_GLOBAL_INT_COUNTER1 BIT(9) +#define NI660X_GLOBAL_INT_COUNTER2 BIT(10) +#define NI660X_GLOBAL_INT_COUNTER3 BIT(11) +#define NI660X_GLOBAL_INT_CASCADE BIT(29) +#define NI660X_GLOBAL_INT_GLOBAL_POL BIT(30) +#define NI660X_GLOBAL_INT_GLOBAL BIT(31) + #define NI660X_DMA_CFG_SEL(_c, _s) (((_s) & 0x1f) << (8 * (_c))) #define NI660X_DMA_CFG_SEL_MASK(_c) NI660X_DMA_CFG_SEL((_c), 0x1f) #define NI660X_DMA_CFG_SEL_NONE(_c) NI660X_DMA_CFG_SEL((_c), 0x1f) @@ -287,21 +295,6 @@ static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { [NI660X_IO_CFG_38_39] = { 0x7a2, 2 } /* read/write */ }; -enum global_interrupt_status_register_bits { - Counter_0_Int_Bit = 0x100, - Counter_1_Int_Bit = 0x200, - Counter_2_Int_Bit = 0x400, - Counter_3_Int_Bit = 0x800, - Cascade_Int_Bit = 0x20000000, - Global_Int_Bit = 0x80000000 -}; - -enum global_interrupt_config_register_bits { - Cascade_Int_Enable_Bit = 0x20000000, - Global_Int_Polarity_Bit = 0x40000000, - Global_Int_Enable_Bit = 0x80000000 -}; - /* Offset of the GPCT chips from the base-address of the card */ /* First chip is at base-address + 0x00, etc. */ static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 }; @@ -1072,9 +1065,9 @@ static int ni_660x_auto_attach(struct comedi_device *dev, return ret; } dev->irq = pcidev->irq; - global_interrupt_config_bits = Global_Int_Enable_Bit; + global_interrupt_config_bits = NI660X_GLOBAL_INT_GLOBAL; if (board->n_chips > 1) - global_interrupt_config_bits |= Cascade_Int_Enable_Bit; + global_interrupt_config_bits |= NI660X_GLOBAL_INT_CASCADE; ni_660x_write_register(dev, 0, global_interrupt_config_bits, NI660X_GLOBAL_INT_CFG); -- GitLab From 9678b73e273abcd5ab13b7ecc44521f501529ca4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:21 -0700 Subject: [PATCH 0483/9938] staging: comedi: ni_660x: tidy up ni_660x_write_register() Rename this function to help shorten some of the long lines. Remove the inline, let the compiler figure it out. Change the 'unsigned' parameters to 'unsigned int' to fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 42 +++++++++++------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 773147af4137..aa40ab6f02fa 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -504,9 +504,9 @@ static enum ni_660x_register ni_gpct_to_660x_register(enum ni_gpct_register reg) } } -static inline void ni_660x_write_register(struct comedi_device *dev, - unsigned chip, unsigned bits, - enum ni_660x_register reg) +static void ni_660x_write(struct comedi_device *dev, + unsigned int chip, unsigned int bits, + enum ni_660x_register reg) { unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; @@ -534,7 +534,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, enum ni_660x_register ni_660x_register = ni_gpct_to_660x_register(reg); unsigned chip = counter->chip_index; - ni_660x_write_register(dev, chip, bits, ni_660x_register); + ni_660x_write(dev, chip, bits, ni_660x_register); } static unsigned ni_gpct_read_register(struct ni_gpct *counter, @@ -569,9 +569,9 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev, devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL(mite_channel, counter->counter_index); - ni_660x_write_register(dev, chip, devpriv->dma_cfg[chip] | - NI660X_DMA_CFG_RESET(mite_channel), - NI660X_DMA_CFG); + ni_660x_write(dev, chip, devpriv->dma_cfg[chip] | + NI660X_DMA_CFG_RESET(mite_channel), + NI660X_DMA_CFG); mmiowb(); spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); } @@ -587,8 +587,7 @@ static inline void ni_660x_unset_dma_channel(struct comedi_device *dev, spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL_NONE(mite_channel); - ni_660x_write_register(dev, chip, devpriv->dma_cfg[chip], - NI660X_DMA_CFG); + ni_660x_write(dev, chip, devpriv->dma_cfg[chip], NI660X_DMA_CFG); mmiowb(); spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); } @@ -674,7 +673,7 @@ static void set_tio_counterswap(struct comedi_device *dev, int chip) if (chip) bits = NI660X_CLK_CFG_COUNTER_SWAP; - ni_660x_write_register(dev, chip, bits, NI660X_CLK_CFG); + ni_660x_write(dev, chip, bits, NI660X_CLK_CFG); } static void ni_660x_handle_gpct_interrupt(struct comedi_device *dev, @@ -793,10 +792,9 @@ static void init_tio_chip(struct comedi_device *dev, int chipset) devpriv->dma_cfg[chipset] = 0; for (i = 0; i < MAX_DMA_CHANNEL; ++i) devpriv->dma_cfg[chipset] |= NI660X_DMA_CFG_SEL_NONE(i); - ni_660x_write_register(dev, chipset, devpriv->dma_cfg[chipset], - NI660X_DMA_CFG); + ni_660x_write(dev, chipset, devpriv->dma_cfg[chipset], NI660X_DMA_CFG); for (i = 0; i < NUM_PFI_CHANNELS; ++i) - ni_660x_write_register(dev, chipset, 0, NI660X_IO_CFG(i)); + ni_660x_write(dev, chipset, 0, NI660X_IO_CFG(i)); } static int ni_660x_dio_insn_bits(struct comedi_device *dev, @@ -810,7 +808,7 @@ static int ni_660x_dio_insn_bits(struct comedi_device *dev, s->state &= ~(data[0] << base_bitfield_channel); s->state |= (data[0] & data[1]) << base_bitfield_channel; /* Write out the new digital output lines */ - ni_660x_write_register(dev, 0, s->state, NI660X_DIO32_OUTPUT); + ni_660x_write(dev, 0, s->state, NI660X_DIO32_OUTPUT); } /* on return, data[1] contains the value of the digital * input and output lines. */ @@ -852,8 +850,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, idle_bits |= NI660X_IO_CFG_OUT_SEL(pfi_channel, NI660X_IO_CFG_OUT_SEL_HIGH_Z); - ni_660x_write_register(dev, idle_chipset, idle_bits, - NI660X_IO_CFG(pfi_channel)); + ni_660x_write(dev, idle_chipset, idle_bits, + NI660X_IO_CFG(pfi_channel)); } active_bits = @@ -861,8 +859,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, NI660X_IO_CFG(pfi_channel)); active_bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(pfi_channel); active_bits |= NI660X_IO_CFG_OUT_SEL(pfi_channel, output_select); - ni_660x_write_register(dev, active_chipset, active_bits, - NI660X_IO_CFG(pfi_channel)); + ni_660x_write(dev, active_chipset, active_bits, + NI660X_IO_CFG(pfi_channel)); } static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan, @@ -932,7 +930,7 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, val = ni_660x_read_register(dev, 0, NI660X_IO_CFG(chan)); val &= ~NI660X_IO_CFG_IN_SEL_MASK(chan); val |= NI660X_IO_CFG_IN_SEL(chan, data[1]); - ni_660x_write_register(dev, 0, val, NI660X_IO_CFG(chan)); + ni_660x_write(dev, 0, val, NI660X_IO_CFG(chan)); break; default: @@ -1000,7 +998,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->insn_config = ni_660x_dio_insn_config; /* we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg */ - ni_660x_write_register(dev, 0, 0, NI660X_STC_DIO_CONTROL); + ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); devpriv->counter_dev = ni_gpct_device_construct(dev, &ni_gpct_write_register, @@ -1068,8 +1066,8 @@ static int ni_660x_auto_attach(struct comedi_device *dev, global_interrupt_config_bits = NI660X_GLOBAL_INT_GLOBAL; if (board->n_chips > 1) global_interrupt_config_bits |= NI660X_GLOBAL_INT_CASCADE; - ni_660x_write_register(dev, 0, global_interrupt_config_bits, - NI660X_GLOBAL_INT_CFG); + ni_660x_write(dev, 0, global_interrupt_config_bits, + NI660X_GLOBAL_INT_CFG); return 0; } -- GitLab From ad98c18cb9de633d1023114842d1e895766b99b2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:22 -0700 Subject: [PATCH 0484/9938] staging: comedi: ni_660x: tidy up ni_660x_read_register() Rename this function to help shorten some of the long lines. Remove the inline, let the compiler figure it out. Change the 'unsigned' parameters to 'unsigned int' to fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index aa40ab6f02fa..cd101bb66bad 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -516,9 +516,9 @@ static void ni_660x_write(struct comedi_device *dev, writel(bits, dev->mmio + addr); } -static inline unsigned ni_660x_read_register(struct comedi_device *dev, - unsigned chip, - enum ni_660x_register reg) +static unsigned int ni_660x_read(struct comedi_device *dev, + unsigned int chip, + enum ni_660x_register reg) { unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; @@ -544,7 +544,7 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter, enum ni_660x_register ni_660x_register = ni_gpct_to_660x_register(reg); unsigned chip = counter->chip_index; - return ni_660x_read_register(dev, chip, ni_660x_register); + return ni_660x_read(dev, chip, ni_660x_register); } static inline struct mite_dma_descriptor_ring *mite_ring(struct ni_660x_private @@ -812,7 +812,7 @@ static int ni_660x_dio_insn_bits(struct comedi_device *dev, } /* on return, data[1] contains the value of the digital * input and output lines. */ - data[1] = (ni_660x_read_register(dev, 0, NI660X_DIO32_INPUT) >> + data[1] = (ni_660x_read(dev, 0, NI660X_DIO32_INPUT) >> base_bitfield_channel); return insn->n; @@ -843,9 +843,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, } if (idle_chipset != active_chipset) { - idle_bits = - ni_660x_read_register(dev, idle_chipset, - NI660X_IO_CFG(pfi_channel)); + idle_bits = ni_660x_read(dev, idle_chipset, + NI660X_IO_CFG(pfi_channel)); idle_bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(pfi_channel); idle_bits |= NI660X_IO_CFG_OUT_SEL(pfi_channel, @@ -854,9 +853,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, NI660X_IO_CFG(pfi_channel)); } - active_bits = - ni_660x_read_register(dev, active_chipset, - NI660X_IO_CFG(pfi_channel)); + active_bits = ni_660x_read(dev, active_chipset, + NI660X_IO_CFG(pfi_channel)); active_bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(pfi_channel); active_bits |= NI660X_IO_CFG_OUT_SEL(pfi_channel, output_select); ni_660x_write(dev, active_chipset, active_bits, @@ -927,7 +925,7 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, break; case INSN_CONFIG_FILTER: - val = ni_660x_read_register(dev, 0, NI660X_IO_CFG(chan)); + val = ni_660x_read(dev, 0, NI660X_IO_CFG(chan)); val &= ~NI660X_IO_CFG_IN_SEL_MASK(chan); val |= NI660X_IO_CFG_IN_SEL(chan, data[1]); ni_660x_write(dev, 0, val, NI660X_IO_CFG(chan)); -- GitLab From dc285820cc19a666aea45ac74e9737c2afcf8189 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:23 -0700 Subject: [PATCH 0485/9938] staging: comedi: ni_660x: tidy up ni_gpct_{write, read}_register() Rename these functions so they have namespace associated with the driver. Fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index cd101bb66bad..e0532f4d6bc7 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -527,24 +527,22 @@ static unsigned int ni_660x_read(struct comedi_device *dev, return readl(dev->mmio + addr); } -static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, - enum ni_gpct_register reg) +static void ni_660x_gpct_write(struct ni_gpct *counter, unsigned int bits, + enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; enum ni_660x_register ni_660x_register = ni_gpct_to_660x_register(reg); - unsigned chip = counter->chip_index; - ni_660x_write(dev, chip, bits, ni_660x_register); + ni_660x_write(dev, counter->chip_index, bits, ni_660x_register); } -static unsigned ni_gpct_read_register(struct ni_gpct *counter, +static unsigned int ni_660x_gpct_read(struct ni_gpct *counter, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; enum ni_660x_register ni_660x_register = ni_gpct_to_660x_register(reg); - unsigned chip = counter->chip_index; - return ni_660x_read(dev, chip, ni_660x_register); + return ni_660x_read(dev, counter->chip_index, ni_660x_register); } static inline struct mite_dma_descriptor_ring *mite_ring(struct ni_660x_private @@ -999,8 +997,8 @@ static int ni_660x_auto_attach(struct comedi_device *dev, ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); devpriv->counter_dev = ni_gpct_device_construct(dev, - &ni_gpct_write_register, - &ni_gpct_read_register, + ni_660x_gpct_write, + ni_660x_gpct_read, ni_gpct_variant_660x, ni_660x_num_counters (dev)); -- GitLab From 518d38423b48ad23b2f4b13dd9a027aa37423f1d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:24 -0700 Subject: [PATCH 0486/9938] staging: comedi: ni_660x: tidy up ni_660x_select_pfi_output() Tidy up this function to fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' For aesthetics, remove the static const local variables. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 54 +++++++++++------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index e0532f4d6bc7..79678af8e02c 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -817,46 +817,40 @@ static int ni_660x_dio_insn_bits(struct comedi_device *dev, } static void ni_660x_select_pfi_output(struct comedi_device *dev, - unsigned pfi_channel, - unsigned output_select) + unsigned int chan, unsigned int out_sel) { const struct ni_660x_board *board = dev->board_ptr; - static const unsigned counter_4_7_first_pfi = 8; - static const unsigned counter_4_7_last_pfi = 23; - unsigned active_chipset = 0; - unsigned idle_chipset = 0; - unsigned active_bits; - unsigned idle_bits; + unsigned int active_chip = 0; + unsigned int idle_chip = 0; + unsigned int bits; if (board->n_chips > 1) { - if (output_select == NI660X_IO_CFG_OUT_SEL_COUNTER && - pfi_channel >= counter_4_7_first_pfi && - pfi_channel <= counter_4_7_last_pfi) { - active_chipset = 1; - idle_chipset = 0; + if (out_sel == NI660X_IO_CFG_OUT_SEL_COUNTER && + chan >= 8 && chan <= 23) { + /* counters 4-7 pfi channels */ + active_chip = 1; + idle_chip = 0; } else { - active_chipset = 0; - idle_chipset = 1; + /* counters 0-3 pfi channels */ + active_chip = 0; + idle_chip = 1; } } - if (idle_chipset != active_chipset) { - idle_bits = ni_660x_read(dev, idle_chipset, - NI660X_IO_CFG(pfi_channel)); - idle_bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(pfi_channel); - idle_bits |= - NI660X_IO_CFG_OUT_SEL(pfi_channel, - NI660X_IO_CFG_OUT_SEL_HIGH_Z); - ni_660x_write(dev, idle_chipset, idle_bits, - NI660X_IO_CFG(pfi_channel)); + if (idle_chip != active_chip) { + /* set the pfi channel to high-z on the inactive chip */ + bits = ni_660x_read(dev, idle_chip, NI660X_IO_CFG(chan)); + bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(chan); + bits |= NI660X_IO_CFG_OUT_SEL(chan, + NI660X_IO_CFG_OUT_SEL_HIGH_Z); + ni_660x_write(dev, idle_chip, bits, NI660X_IO_CFG(chan)); } - active_bits = ni_660x_read(dev, active_chipset, - NI660X_IO_CFG(pfi_channel)); - active_bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(pfi_channel); - active_bits |= NI660X_IO_CFG_OUT_SEL(pfi_channel, output_select); - ni_660x_write(dev, active_chipset, active_bits, - NI660X_IO_CFG(pfi_channel)); + /* set the pfi channel output on the active chip */ + bits = ni_660x_read(dev, active_chip, NI660X_IO_CFG(chan)); + bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(chan); + bits |= NI660X_IO_CFG_OUT_SEL(chan, out_sel); + ni_660x_write(dev, active_chip, bits, NI660X_IO_CFG(chan)); } static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan, -- GitLab From ff1e71be56d6c493084eac86afa0aeb59bca9c53 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:25 -0700 Subject: [PATCH 0487/9938] staging: comedi: ni_660x: remove BUG_ON() in ni_660x_request_mite_channel() This BUG_ON() happens if a mite DMA channel is already requested when an ansynchronous command is started for one of the counter subdevices. The comedi core will only call the (*do_cmd) if the subdevice is not busy. In this driver, the (*cancel) for the subdevice will always release any requested mite DMA channel. Remove the BUG_ON() which can never occur. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 79678af8e02c..232c89767da8 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -599,7 +599,6 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev, struct mite_channel *mite_chan; spin_lock_irqsave(&devpriv->mite_channel_lock, flags); - BUG_ON(counter->mite_chan); mite_chan = mite_request_channel(devpriv->mite, mite_ring(devpriv, counter)); if (!mite_chan) { -- GitLab From 6d40805b0b4e4392e68fea0028edcafa5fcdc04a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:26 -0700 Subject: [PATCH 0488/9938] staging: comedi: ni_660x: fix block comment issues Fix the checkpatch.pl issues about: WARNING: Block comments use * on subsequent lines WARNING: Block comments use a trailing */ on a separate line Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 232c89767da8..018349707947 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -48,8 +48,7 @@ enum ni_660x_constants { }; #define NUM_PFI_CHANNELS 40 -/* really there are only up to 3 dma channels, but the register layout allows -for 4 */ +/* there are only up to 3 dma channels, but the register layout allows for 4 */ #define MAX_DMA_CHANNEL 4 /* See Register-Level Programmer Manual page 3.1 */ @@ -985,8 +984,11 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = ni_660x_dio_insn_bits; s->insn_config = ni_660x_dio_insn_config; - /* we use the ioconfig registers to control dio direction, so zero - output enables in stc dio control reg */ + + /* + * We use the ioconfig registers to control dio direction, so zero + * output enables in stc dio control reg. + */ ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); devpriv->counter_dev = ni_gpct_device_construct(dev, @@ -1040,8 +1042,11 @@ static int ni_660x_auto_attach(struct comedi_device *dev, NI660X_IO_CFG_OUT_SEL_COUNTER); ni_660x_select_pfi_output(dev, i, NI660X_IO_CFG_OUT_SEL_HIGH_Z); } - /* to be safe, set counterswap bits on tio chips after all the counter - outputs have been set to high impedance mode */ + + /* + * To be safe, set counterswap bits on tio chips after all the counter + * outputs have been set to high impedance mode. + */ for (i = 0; i < board->n_chips; ++i) set_tio_counterswap(dev, i); -- GitLab From 520e61915186e0538a8fc46e5e268a2000141545 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:27 -0700 Subject: [PATCH 0489/9938] staging: comedi: ni_660x: remove enum ni_660x_subdevices Hard-coding the subdevice order is normally a bad idea. If a new subdevice is added, or removed, it could potentially break pretty badly. Remove the enum and associated NI_660X_GPCT_SUBDEV() helper that hard-code the subdevice order. Fix the (*auto_attach) so it initializes all the subdevices without depending on the hard-coded order. Change the interrupt handler so that all the counter subdevices are handled without depending on the hard-coded order. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 018349707947..595c862f236b 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -179,15 +179,6 @@ enum ni_660x_register { #define NI660X_IO_CFG_IN_SEL(_c, _s) (((_s) & 0x7) << (((_c) % 2) ? 4 : 12)) #define NI660X_IO_CFG_IN_SEL_MASK(_c) NI660X_IO_CFG_IN_SEL((_c), 0x7) -enum ni_660x_subdevices { - NI_660X_DIO_SUBDEV = 1, - NI_660X_GPCT_SUBDEV_0 = 2 -}; -static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index) -{ - return NI_660X_GPCT_SUBDEV_0 + index; -} - struct ni_660x_register_data { int offset; /* Offset from base address from GPCT chip */ char size; /* 2 or 4 bytes */ @@ -694,9 +685,10 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d) /* lock to avoid race with comedi_poll */ spin_lock_irqsave(&devpriv->interrupt_lock, flags); smp_mb(); - for (i = 0; i < ni_660x_num_counters(dev); ++i) { - s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)]; - ni_660x_handle_gpct_interrupt(dev, s); + for (i = 0; i < dev->n_subdevices; ++i) { + s = &dev->subdevices[i]; + if (s->type == COMEDI_SUBD_COUNTER) + ni_660x_handle_gpct_interrupt(dev, s); } spin_unlock_irqrestore(&devpriv->interrupt_lock, flags); return IRQ_HANDLED; @@ -935,6 +927,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, const struct ni_660x_board *board = NULL; struct ni_660x_private *devpriv; struct comedi_subdevice *s; + int subdev; int ret; unsigned i; unsigned global_interrupt_config_bits; @@ -971,11 +964,13 @@ static int ni_660x_auto_attach(struct comedi_device *dev, if (ret) return ret; - s = &dev->subdevices[0]; + subdev = 0; + + s = &dev->subdevices[subdev++]; /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */ s->type = COMEDI_SUBD_UNUSED; - s = &dev->subdevices[NI_660X_DIO_SUBDEV]; + s = &dev->subdevices[subdev++]; /* DIGITAL I/O SUBDEVICE */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -1000,7 +995,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, if (!devpriv->counter_dev) return -ENOMEM; for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) { - s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)]; + s = &dev->subdevices[subdev++]; if (i < ni_660x_num_counters(dev)) { s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | -- GitLab From b15f5069087128d42d2e00b6b1c666fd3ec42bfe Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:28 -0700 Subject: [PATCH 0490/9938] staging: comedi: ni_660x: remove ni_660x_num_counters() This inline function is only used by the (*auto_attach). Remove it and just use a local variable for the calculation. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 595c862f236b..6a3a12e03a21 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -342,13 +342,6 @@ struct ni_660x_private { unsigned short pfi_output_selects[NUM_PFI_CHANNELS]; }; -static inline unsigned ni_660x_num_counters(struct comedi_device *dev) -{ - const struct ni_660x_board *board = dev->board_ptr; - - return board->n_chips * counters_per_chip; -} - static enum ni_660x_register ni_gpct_to_660x_register(enum ni_gpct_register reg) { switch (reg) { @@ -927,6 +920,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, const struct ni_660x_board *board = NULL; struct ni_660x_private *devpriv; struct comedi_subdevice *s; + unsigned int n_counters; int subdev; int ret; unsigned i; @@ -986,17 +980,17 @@ static int ni_660x_auto_attach(struct comedi_device *dev, */ ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); + n_counters = board->n_chips * counters_per_chip; devpriv->counter_dev = ni_gpct_device_construct(dev, ni_660x_gpct_write, ni_660x_gpct_read, ni_gpct_variant_660x, - ni_660x_num_counters - (dev)); + n_counters); if (!devpriv->counter_dev) return -ENOMEM; for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) { s = &dev->subdevices[subdev++]; - if (i < ni_660x_num_counters(dev)) { + if (i < n_counters) { s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ; @@ -1025,7 +1019,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, for (i = 0; i < board->n_chips; ++i) init_tio_chip(dev, i); - for (i = 0; i < ni_660x_num_counters(dev); ++i) + for (i = 0; i < n_counters; ++i) ni_tio_init_counter(&devpriv->counter_dev->counters[i]); for (i = 0; i < NUM_PFI_CHANNELS; ++i) { -- GitLab From 2225320ec8cc7f99c05ff217343eb63d5319c314 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:29 -0700 Subject: [PATCH 0491/9938] staging: comedi: ni_660x: Prefer 'unsigned int' to bare use of 'unsigned' Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 6a3a12e03a21..6ca5c67b1a80 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -299,7 +299,7 @@ enum ni_660x_boardid { struct ni_660x_board { const char *name; - unsigned n_chips; /* total number of TIO chips */ + unsigned int n_chips; /* total number of TIO chips */ }; static const struct ni_660x_board ni_660x_boards[] = { @@ -337,7 +337,7 @@ struct ni_660x_private { spinlock_t mite_channel_lock; /* interrupt_lock prevents races between interrupt and comedi_poll */ spinlock_t interrupt_lock; - unsigned dma_cfg[NI_660X_MAX_NUM_CHIPS]; + unsigned int dma_cfg[NI_660X_MAX_NUM_CHIPS]; spinlock_t soft_reg_copy_lock; unsigned short pfi_output_selects[NUM_PFI_CHANNELS]; }; @@ -533,17 +533,17 @@ static inline struct mite_dma_descriptor_ring *mite_ring(struct ni_660x_private struct ni_gpct *counter) { - unsigned chip = counter->chip_index; + unsigned int chip = counter->chip_index; return priv->mite_rings[chip][counter->counter_index]; } static inline void ni_660x_set_dma_channel(struct comedi_device *dev, - unsigned mite_channel, + unsigned int mite_channel, struct ni_gpct *counter) { struct ni_660x_private *devpriv = dev->private; - unsigned chip = counter->chip_index; + unsigned int chip = counter->chip_index; unsigned long flags; spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); @@ -558,11 +558,11 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev, } static inline void ni_660x_unset_dma_channel(struct comedi_device *dev, - unsigned mite_channel, + unsigned int mite_channel, struct ni_gpct *counter) { struct ni_660x_private *devpriv = dev->private; - unsigned chip = counter->chip_index; + unsigned int chip = counter->chip_index; unsigned long flags; spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); @@ -642,7 +642,7 @@ static int ni_660x_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static void set_tio_counterswap(struct comedi_device *dev, int chip) { - unsigned bits = 0; + unsigned int bits = 0; /* * See P. 3.5 of the Register-Level Programming manual. @@ -670,7 +670,7 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d) struct comedi_device *dev = d; struct ni_660x_private *devpriv = dev->private; struct comedi_subdevice *s; - unsigned i; + unsigned int i; unsigned long flags; if (!dev->attached) @@ -718,7 +718,7 @@ static int ni_660x_buf_change(struct comedi_device *dev, static int ni_660x_allocate_private(struct comedi_device *dev) { struct ni_660x_private *devpriv; - unsigned i; + unsigned int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -737,8 +737,8 @@ static int ni_660x_alloc_mite_rings(struct comedi_device *dev) { const struct ni_660x_board *board = dev->board_ptr; struct ni_660x_private *devpriv = dev->private; - unsigned i; - unsigned j; + unsigned int i; + unsigned int j; for (i = 0; i < board->n_chips; ++i) { for (j = 0; j < counters_per_chip; ++j) { @@ -755,8 +755,8 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev) { const struct ni_660x_board *board = dev->board_ptr; struct ni_660x_private *devpriv = dev->private; - unsigned i; - unsigned j; + unsigned int i; + unsigned int j; for (i = 0; i < board->n_chips; ++i) { for (j = 0; j < counters_per_chip; ++j) @@ -767,7 +767,7 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev) static void init_tio_chip(struct comedi_device *dev, int chipset) { struct ni_660x_private *devpriv = dev->private; - unsigned i; + unsigned int i; /* init dma configuration register */ devpriv->dma_cfg[chipset] = 0; @@ -782,7 +782,7 @@ static int ni_660x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - unsigned base_bitfield_channel = CR_CHAN(insn->chanspec); + unsigned int base_bitfield_channel = CR_CHAN(insn->chanspec); /* Check if we have to write some bits */ if (data[0]) { @@ -836,8 +836,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, ni_660x_write(dev, active_chip, bits, NI660X_IO_CFG(chan)); } -static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan, - unsigned source) +static int ni_660x_set_pfi_routing(struct comedi_device *dev, + unsigned int chan, unsigned int source) { struct ni_660x_private *devpriv = dev->private; @@ -923,8 +923,8 @@ static int ni_660x_auto_attach(struct comedi_device *dev, unsigned int n_counters; int subdev; int ret; - unsigned i; - unsigned global_interrupt_config_bits; + unsigned int i; + unsigned int global_interrupt_config_bits; if (context < ARRAY_SIZE(ni_660x_boards)) board = &ni_660x_boards[context]; -- GitLab From cded944fa90cf8105eedb5766ecaee82a2f86b3a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:30 -0700 Subject: [PATCH 0492/9938] staging: comedi: ni_660x: Prefer kernel type 'u64' over 'uint64_t' Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 6ca5c67b1a80..4f7f5ca01e97 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -331,7 +331,7 @@ static const struct ni_660x_board ni_660x_boards[] = { struct ni_660x_private { struct mite_struct *mite; struct ni_gpct_device *counter_dev; - uint64_t pfi_direction_bits; + u64 pfi_direction_bits; struct mite_dma_descriptor_ring *mite_rings[NI_660X_MAX_NUM_CHIPS][counters_per_chip]; spinlock_t mite_channel_lock; @@ -854,7 +854,7 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev, } devpriv->pfi_output_selects[chan] = source; - if (devpriv->pfi_direction_bits & (((uint64_t) 1) << chan)) + if (devpriv->pfi_direction_bits & (1ULL << chan)) ni_660x_select_pfi_output(dev, chan, devpriv->pfi_output_selects[chan]); return 0; @@ -867,7 +867,7 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, { struct ni_660x_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - uint64_t bit = 1ULL << chan; + u64 bit = 1ULL << chan; unsigned int val; int ret; -- GitLab From 7e9061869435dbeefff970b032d2b8141ce9e301 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:31 -0700 Subject: [PATCH 0493/9938] staging: comedi: ni_660x: tidy up Digital I/O subdevice init Add some whitespace to the Digital I/O subdevice init and add a comment about the channels. This driver is a bit goofy, only 32 of the 40 channels can actually be used for Digital I/Os and 32 of them can be routed to the counters for alternate use. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 68 +++++++++++++++++++++--- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 4f7f5ca01e97..f24009c98e0a 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -964,15 +964,67 @@ static int ni_660x_auto_attach(struct comedi_device *dev, /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */ s->type = COMEDI_SUBD_UNUSED; + /* + * Digital I/O subdevice + * + * There are 40 channels but only the first 32 can be digital I/Os. + * The last 8 are dedicated to counters 0 and 1. + * + * Counter 0-3 signals are from the first TIO chip. + * Counter 4-7 signals are from the second TIO chip. + * + * Comedi External + * PFI Chan DIO Chan Counter Signal + * ------- -------- -------------- + * 0 0 + * 1 1 + * 2 2 + * 3 3 + * 4 4 + * 5 5 + * 6 6 + * 7 7 + * 8 8 CTR 7 OUT + * 9 9 CTR 7 AUX + * 10 10 CTR 7 GATE + * 11 11 CTR 7 SOURCE + * 12 12 CTR 6 OUT + * 13 13 CTR 6 AUX + * 14 14 CTR 6 GATE + * 15 15 CTR 6 SOURCE + * 16 16 CTR 5 OUT + * 17 17 CTR 5 AUX + * 18 18 CTR 5 GATE + * 19 19 CTR 5 SOURCE + * 20 20 CTR 4 OUT + * 21 21 CTR 4 AUX + * 22 22 CTR 4 GATE + * 23 23 CTR 4 SOURCE + * 24 24 CTR 3 OUT + * 25 25 CTR 3 AUX + * 26 26 CTR 3 GATE + * 27 27 CTR 3 SOURCE + * 28 28 CTR 2 OUT + * 29 29 CTR 2 AUX + * 30 30 CTR 2 GATE + * 31 31 CTR 2 SOURCE + * 32 CTR 1 OUT + * 33 CTR 1 AUX + * 34 CTR 1 GATE + * 35 CTR 1 SOURCE + * 36 CTR 0 OUT + * 37 CTR 0 AUX + * 38 CTR 0 GATE + * 39 CTR 0 SOURCE + */ s = &dev->subdevices[subdev++]; - /* DIGITAL I/O SUBDEVICE */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = NUM_PFI_CHANNELS; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = ni_660x_dio_insn_bits; - s->insn_config = ni_660x_dio_insn_config; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = NUM_PFI_CHANNELS; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_660x_dio_insn_bits; + s->insn_config = ni_660x_dio_insn_config; /* * We use the ioconfig registers to control dio direction, so zero -- GitLab From 826f783a0eb15c6860d03af6d88eea3eaea34ff4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:32 -0700 Subject: [PATCH 0494/9938] staging: comedi: ni_660x: tidy up ni_660x_dio_insn_bits() Use some local variables to clarify this function. This (*insn_bits) function is a bit different from most comedi drivers. Add some comments to clarify why the shifts are used. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 31 +++++++++++++++--------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index f24009c98e0a..f614927411cb 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -780,21 +780,30 @@ static void init_tio_chip(struct comedi_device *dev, int chipset) static int ni_660x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - unsigned int base_bitfield_channel = CR_CHAN(insn->chanspec); + unsigned int shift = CR_CHAN(insn->chanspec); + unsigned int mask = data[0] << shift; + unsigned int bits = data[1] << shift; - /* Check if we have to write some bits */ - if (data[0]) { - s->state &= ~(data[0] << base_bitfield_channel); - s->state |= (data[0] & data[1]) << base_bitfield_channel; - /* Write out the new digital output lines */ + /* + * There are 40 channels in this subdevice but only 32 are usable + * as DIO. The shift adjusts the mask/bits to account for the base + * channel in insn->chanspec. The state update can then be handled + * normally for the 32 usable channels. + */ + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); ni_660x_write(dev, 0, s->state, NI660X_DIO32_OUTPUT); } - /* on return, data[1] contains the value of the digital - * input and output lines. */ - data[1] = (ni_660x_read(dev, 0, NI660X_DIO32_INPUT) >> - base_bitfield_channel); + + /* + * Return the input channels, shifted back to account for the base + * channel. + */ + data[1] = ni_660x_read(dev, 0, NI660X_DIO32_INPUT) >> shift; return insn->n; } -- GitLab From aa94f288882583fb2a214110ad021a75e78ff809 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:33 -0700 Subject: [PATCH 0495/9938] staging: comedi: ni_660x: tidy up ni_660x_set_pfi_routing() Use the comedi.h provided constants (enum ni_660x_pfi_routing) instead of defining new ones for the output sources. Use a switch to clarify the channel/source validation. For aesthetics, rename the private data members 'pfi_output_selects' and 'pfi_direction_bits'. Remove the 'min_counter_pfi_chan' and 'max_dio_pfi_chan' from enum ni_660x_constants. The open coded values make the code easier to follow. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 65 ++++++++++-------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index f614927411cb..3415a15650fe 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -42,8 +42,6 @@ #include "ni_tio.h" enum ni_660x_constants { - min_counter_pfi_chan = 8, - max_dio_pfi_chan = 31, counters_per_chip = 4 }; @@ -172,10 +170,6 @@ enum ni_660x_register { #define NI660X_IO_CFG(x) (NI660X_IO_CFG_0_1 + ((x) / 2)) #define NI660X_IO_CFG_OUT_SEL(_c, _s) (((_s) & 0x3) << (((_c) % 2) ? 0 : 8)) #define NI660X_IO_CFG_OUT_SEL_MASK(_c) NI660X_IO_CFG_OUT_SEL((_c), 0x3) -#define NI660X_IO_CFG_OUT_SEL_HIGH_Z 0 -#define NI660X_IO_CFG_OUT_SEL_COUNTER 1 -#define NI660X_IO_CFG_OUT_SEL_DO 2 -#define NI660X_IO_CFG_OUT_SEL_MAX 3 #define NI660X_IO_CFG_IN_SEL(_c, _s) (((_s) & 0x7) << (((_c) % 2) ? 4 : 12)) #define NI660X_IO_CFG_IN_SEL_MASK(_c) NI660X_IO_CFG_IN_SEL((_c), 0x7) @@ -331,7 +325,6 @@ static const struct ni_660x_board ni_660x_boards[] = { struct ni_660x_private { struct mite_struct *mite; struct ni_gpct_device *counter_dev; - u64 pfi_direction_bits; struct mite_dma_descriptor_ring *mite_rings[NI_660X_MAX_NUM_CHIPS][counters_per_chip]; spinlock_t mite_channel_lock; @@ -339,7 +332,8 @@ struct ni_660x_private { spinlock_t interrupt_lock; unsigned int dma_cfg[NI_660X_MAX_NUM_CHIPS]; spinlock_t soft_reg_copy_lock; - unsigned short pfi_output_selects[NUM_PFI_CHANNELS]; + unsigned int io_cfg[NUM_PFI_CHANNELS]; + u64 io_dir; }; static enum ni_660x_register ni_gpct_to_660x_register(enum ni_gpct_register reg) @@ -728,7 +722,7 @@ static int ni_660x_allocate_private(struct comedi_device *dev) spin_lock_init(&devpriv->interrupt_lock); spin_lock_init(&devpriv->soft_reg_copy_lock); for (i = 0; i < NUM_PFI_CHANNELS; ++i) - devpriv->pfi_output_selects[i] = NI660X_IO_CFG_OUT_SEL_COUNTER; + devpriv->io_cfg[i] = NI_660X_PFI_OUTPUT_COUNTER; return 0; } @@ -817,7 +811,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned int bits; if (board->n_chips > 1) { - if (out_sel == NI660X_IO_CFG_OUT_SEL_COUNTER && + if (out_sel == NI_660X_PFI_OUTPUT_COUNTER && chan >= 8 && chan <= 23) { /* counters 4-7 pfi channels */ active_chip = 1; @@ -833,8 +827,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, /* set the pfi channel to high-z on the inactive chip */ bits = ni_660x_read(dev, idle_chip, NI660X_IO_CFG(chan)); bits &= ~NI660X_IO_CFG_OUT_SEL_MASK(chan); - bits |= NI660X_IO_CFG_OUT_SEL(chan, - NI660X_IO_CFG_OUT_SEL_HIGH_Z); + bits |= NI660X_IO_CFG_OUT_SEL(chan, 0); /* high-z */ ni_660x_write(dev, idle_chip, bits, NI660X_IO_CFG(chan)); } @@ -850,22 +843,21 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev, { struct ni_660x_private *devpriv = dev->private; - if (source > NI660X_IO_CFG_OUT_SEL_MAX) - return -EINVAL; - if (source == NI660X_IO_CFG_OUT_SEL_HIGH_Z) - return -EINVAL; - if (chan < min_counter_pfi_chan) { - if (source == NI660X_IO_CFG_OUT_SEL_COUNTER) + switch (source) { + case NI_660X_PFI_OUTPUT_COUNTER: + if (chan < 8) return -EINVAL; - } else if (chan > max_dio_pfi_chan) { - if (source == NI660X_IO_CFG_OUT_SEL_DO) + break; + case NI_660X_PFI_OUTPUT_DIO: + if (chan > 31) return -EINVAL; + default: + return -EINVAL; } - devpriv->pfi_output_selects[chan] = source; - if (devpriv->pfi_direction_bits & (1ULL << chan)) - ni_660x_select_pfi_output(dev, chan, - devpriv->pfi_output_selects[chan]); + devpriv->io_cfg[chan] = source; + if (devpriv->io_dir & (1ULL << chan)) + ni_660x_select_pfi_output(dev, chan, devpriv->io_cfg[chan]); return 0; } @@ -882,20 +874,18 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_DIO_OUTPUT: - devpriv->pfi_direction_bits |= bit; - ni_660x_select_pfi_output(dev, chan, - devpriv->pfi_output_selects[chan]); + devpriv->io_dir |= bit; + ni_660x_select_pfi_output(dev, chan, devpriv->io_cfg[chan]); break; case INSN_CONFIG_DIO_INPUT: - devpriv->pfi_direction_bits &= ~bit; - ni_660x_select_pfi_output(dev, chan, - NI660X_IO_CFG_OUT_SEL_HIGH_Z); + devpriv->io_dir &= ~bit; + ni_660x_select_pfi_output(dev, chan, 0); /* high-z */ break; case INSN_CONFIG_DIO_QUERY: - data[1] = (devpriv->pfi_direction_bits & bit) ? COMEDI_OUTPUT - : COMEDI_INPUT; + data[1] = (devpriv->io_dir & bit) ? COMEDI_OUTPUT + : COMEDI_INPUT; break; case INSN_CONFIG_SET_ROUTING: @@ -905,7 +895,7 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, break; case INSN_CONFIG_GET_ROUTING: - data[1] = devpriv->pfi_output_selects[chan]; + data[1] = devpriv->io_cfg[chan]; break; case INSN_CONFIG_FILTER: @@ -1084,13 +1074,12 @@ static int ni_660x_auto_attach(struct comedi_device *dev, ni_tio_init_counter(&devpriv->counter_dev->counters[i]); for (i = 0; i < NUM_PFI_CHANNELS; ++i) { - if (i < min_counter_pfi_chan) - ni_660x_set_pfi_routing(dev, i, - NI660X_IO_CFG_OUT_SEL_DO); + if (i < 8) + ni_660x_set_pfi_routing(dev, i, NI_660X_PFI_OUTPUT_DIO); else ni_660x_set_pfi_routing(dev, i, - NI660X_IO_CFG_OUT_SEL_COUNTER); - ni_660x_select_pfi_output(dev, i, NI660X_IO_CFG_OUT_SEL_HIGH_Z); + NI_660X_PFI_OUTPUT_COUNTER); + ni_660x_select_pfi_output(dev, i, 0); /* high-z */ } /* -- GitLab From f0c9305ede52b42021ea53a33b3a2878e0c5d51e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:34 -0700 Subject: [PATCH 0496/9938] staging: comedi: ni_660x: add a comment about the initial DIO state The (*auto_attach) initializes all the DIO channels to a default state. Add a comment for clarity. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 3415a15650fe..6f84946ea9a4 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1073,6 +1073,11 @@ static int ni_660x_auto_attach(struct comedi_device *dev, for (i = 0; i < n_counters; ++i) ni_tio_init_counter(&devpriv->counter_dev->counters[i]); + /* + * Default the DIO channels as: + * chan 0-7: DIO inputs + * chan 8-39: counter signal inputs + */ for (i = 0; i < NUM_PFI_CHANNELS; ++i) { if (i < 8) ni_660x_set_pfi_routing(dev, i, NI_660X_PFI_OUTPUT_DIO); -- GitLab From 0c9434e352d0ae9ddb84a89716e1d1e82f3185f1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:35 -0700 Subject: [PATCH 0497/9938] staging: comedi: ni_660x: refactor ni_gpct_to_660x_register() Convert this big switch into an array and refactor ni_660x_gpct_{write,read}() functions to use the array to find the register offset. All the TIO (GPCT) registers are included in the array except for NITIO_G0_ABZ and NITIO_G1_ABZ. These registers only exist on the ni_pcimio m-series boards and this driver will never read/write them. Just in case someone adds a new entry to the enum ni_gpct_register in ni_tio.h, add a dev_warn() for any unhandled registers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 236 +++++++++-------------- 1 file changed, 89 insertions(+), 147 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 6f84946ea9a4..3edea9928b09 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -279,6 +279,77 @@ static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { [NI660X_IO_CFG_38_39] = { 0x7a2, 2 } /* read/write */ }; +static const enum ni_660x_register ni_gpct_to_660x_register[] = { + [NITIO_G0_AUTO_INC] = NI660X_G0_AUTO_INC, + [NITIO_G1_AUTO_INC] = NI660X_G1_AUTO_INC, + [NITIO_G2_AUTO_INC] = NI660X_G2_AUTO_INC, + [NITIO_G3_AUTO_INC] = NI660X_G3_AUTO_INC, + [NITIO_G0_CMD] = NI660X_G0_CMD, + [NITIO_G1_CMD] = NI660X_G1_CMD, + [NITIO_G2_CMD] = NI660X_G2_CMD, + [NITIO_G3_CMD] = NI660X_G3_CMD, + [NITIO_G0_HW_SAVE] = NI660X_G0_HW_SAVE, + [NITIO_G1_HW_SAVE] = NI660X_G1_HW_SAVE, + [NITIO_G2_HW_SAVE] = NI660X_G2_HW_SAVE, + [NITIO_G3_HW_SAVE] = NI660X_G3_HW_SAVE, + [NITIO_G0_SW_SAVE] = NI660X_G0_SW_SAVE, + [NITIO_G1_SW_SAVE] = NI660X_G1_SW_SAVE, + [NITIO_G2_SW_SAVE] = NI660X_G2_SW_SAVE, + [NITIO_G3_SW_SAVE] = NI660X_G3_SW_SAVE, + [NITIO_G0_MODE] = NI660X_G0_MODE, + [NITIO_G1_MODE] = NI660X_G1_MODE, + [NITIO_G2_MODE] = NI660X_G2_MODE, + [NITIO_G3_MODE] = NI660X_G3_MODE, + [NITIO_G0_LOADA] = NI660X_G0_LOADA, + [NITIO_G1_LOADA] = NI660X_G1_LOADA, + [NITIO_G2_LOADA] = NI660X_G2_LOADA, + [NITIO_G3_LOADA] = NI660X_G3_LOADA, + [NITIO_G0_LOADB] = NI660X_G0_LOADB, + [NITIO_G1_LOADB] = NI660X_G1_LOADB, + [NITIO_G2_LOADB] = NI660X_G2_LOADB, + [NITIO_G3_LOADB] = NI660X_G3_LOADB, + [NITIO_G0_INPUT_SEL] = NI660X_G0_INPUT_SEL, + [NITIO_G1_INPUT_SEL] = NI660X_G1_INPUT_SEL, + [NITIO_G2_INPUT_SEL] = NI660X_G2_INPUT_SEL, + [NITIO_G3_INPUT_SEL] = NI660X_G3_INPUT_SEL, + [NITIO_G0_CNT_MODE] = NI660X_G0_CNT_MODE, + [NITIO_G1_CNT_MODE] = NI660X_G1_CNT_MODE, + [NITIO_G2_CNT_MODE] = NI660X_G2_CNT_MODE, + [NITIO_G3_CNT_MODE] = NI660X_G3_CNT_MODE, + [NITIO_G0_GATE2] = NI660X_G0_GATE2, + [NITIO_G1_GATE2] = NI660X_G1_GATE2, + [NITIO_G2_GATE2] = NI660X_G2_GATE2, + [NITIO_G3_GATE2] = NI660X_G3_GATE2, + [NITIO_G01_STATUS] = NI660X_G01_STATUS, + [NITIO_G23_STATUS] = NI660X_G23_STATUS, + [NITIO_G01_RESET] = NI660X_G01_RESET, + [NITIO_G23_RESET] = NI660X_G23_RESET, + [NITIO_G01_STATUS1] = NI660X_G01_STATUS1, + [NITIO_G23_STATUS1] = NI660X_G23_STATUS1, + [NITIO_G01_STATUS2] = NI660X_G01_STATUS2, + [NITIO_G23_STATUS2] = NI660X_G23_STATUS2, + [NITIO_G0_DMA_CFG] = NI660X_G0_DMA_CFG, + [NITIO_G1_DMA_CFG] = NI660X_G1_DMA_CFG, + [NITIO_G2_DMA_CFG] = NI660X_G2_DMA_CFG, + [NITIO_G3_DMA_CFG] = NI660X_G3_DMA_CFG, + [NITIO_G0_DMA_STATUS] = NI660X_G0_DMA_STATUS, + [NITIO_G1_DMA_STATUS] = NI660X_G1_DMA_STATUS, + [NITIO_G2_DMA_STATUS] = NI660X_G2_DMA_STATUS, + [NITIO_G3_DMA_STATUS] = NI660X_G3_DMA_STATUS, + [NITIO_G0_INT_ACK] = NI660X_G0_INT_ACK, + [NITIO_G1_INT_ACK] = NI660X_G1_INT_ACK, + [NITIO_G2_INT_ACK] = NI660X_G2_INT_ACK, + [NITIO_G3_INT_ACK] = NI660X_G3_INT_ACK, + [NITIO_G0_STATUS] = NI660X_G0_STATUS, + [NITIO_G1_STATUS] = NI660X_G1_STATUS, + [NITIO_G2_STATUS] = NI660X_G2_STATUS, + [NITIO_G3_STATUS] = NI660X_G3_STATUS, + [NITIO_G0_INT_ENA] = NI660X_G0_INT_ENA, + [NITIO_G1_INT_ENA] = NI660X_G1_INT_ENA, + [NITIO_G2_INT_ENA] = NI660X_G2_INT_ENA, + [NITIO_G3_INT_ENA] = NI660X_G3_INT_ENA, +}; + /* Offset of the GPCT chips from the base-address of the card */ /* First chip is at base-address + 0x00, etc. */ static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 }; @@ -336,151 +407,6 @@ struct ni_660x_private { u64 io_dir; }; -static enum ni_660x_register ni_gpct_to_660x_register(enum ni_gpct_register reg) -{ - switch (reg) { - case NITIO_G0_AUTO_INC: - return NI660X_G0_AUTO_INC; - case NITIO_G1_AUTO_INC: - return NI660X_G1_AUTO_INC; - case NITIO_G2_AUTO_INC: - return NI660X_G2_AUTO_INC; - case NITIO_G3_AUTO_INC: - return NI660X_G3_AUTO_INC; - case NITIO_G0_CMD: - return NI660X_G0_CMD; - case NITIO_G1_CMD: - return NI660X_G1_CMD; - case NITIO_G2_CMD: - return NI660X_G2_CMD; - case NITIO_G3_CMD: - return NI660X_G3_CMD; - case NITIO_G0_HW_SAVE: - return NI660X_G0_HW_SAVE; - case NITIO_G1_HW_SAVE: - return NI660X_G1_HW_SAVE; - case NITIO_G2_HW_SAVE: - return NI660X_G2_HW_SAVE; - case NITIO_G3_HW_SAVE: - return NI660X_G3_HW_SAVE; - case NITIO_G0_SW_SAVE: - return NI660X_G0_SW_SAVE; - case NITIO_G1_SW_SAVE: - return NI660X_G1_SW_SAVE; - case NITIO_G2_SW_SAVE: - return NI660X_G2_SW_SAVE; - case NITIO_G3_SW_SAVE: - return NI660X_G3_SW_SAVE; - case NITIO_G0_MODE: - return NI660X_G0_MODE; - case NITIO_G1_MODE: - return NI660X_G1_MODE; - case NITIO_G2_MODE: - return NI660X_G2_MODE; - case NITIO_G3_MODE: - return NI660X_G3_MODE; - case NITIO_G0_LOADA: - return NI660X_G0_LOADA; - case NITIO_G1_LOADA: - return NI660X_G1_LOADA; - case NITIO_G2_LOADA: - return NI660X_G2_LOADA; - case NITIO_G3_LOADA: - return NI660X_G3_LOADA; - case NITIO_G0_LOADB: - return NI660X_G0_LOADB; - case NITIO_G1_LOADB: - return NI660X_G1_LOADB; - case NITIO_G2_LOADB: - return NI660X_G2_LOADB; - case NITIO_G3_LOADB: - return NI660X_G3_LOADB; - case NITIO_G0_INPUT_SEL: - return NI660X_G0_INPUT_SEL; - case NITIO_G1_INPUT_SEL: - return NI660X_G1_INPUT_SEL; - case NITIO_G2_INPUT_SEL: - return NI660X_G2_INPUT_SEL; - case NITIO_G3_INPUT_SEL: - return NI660X_G3_INPUT_SEL; - case NITIO_G01_STATUS: - return NI660X_G01_STATUS; - case NITIO_G23_STATUS: - return NI660X_G23_STATUS; - case NITIO_G01_RESET: - return NI660X_G01_RESET; - case NITIO_G23_RESET: - return NI660X_G23_RESET; - case NITIO_G01_STATUS1: - return NI660X_G01_STATUS1; - case NITIO_G23_STATUS1: - return NI660X_G23_STATUS1; - case NITIO_G01_STATUS2: - return NI660X_G01_STATUS2; - case NITIO_G23_STATUS2: - return NI660X_G23_STATUS2; - case NITIO_G0_CNT_MODE: - return NI660X_G0_CNT_MODE; - case NITIO_G1_CNT_MODE: - return NI660X_G1_CNT_MODE; - case NITIO_G2_CNT_MODE: - return NI660X_G2_CNT_MODE; - case NITIO_G3_CNT_MODE: - return NI660X_G3_CNT_MODE; - case NITIO_G0_GATE2: - return NI660X_G0_GATE2; - case NITIO_G1_GATE2: - return NI660X_G1_GATE2; - case NITIO_G2_GATE2: - return NI660X_G2_GATE2; - case NITIO_G3_GATE2: - return NI660X_G3_GATE2; - case NITIO_G0_DMA_CFG: - return NI660X_G0_DMA_CFG; - case NITIO_G0_DMA_STATUS: - return NI660X_G0_DMA_STATUS; - case NITIO_G1_DMA_CFG: - return NI660X_G1_DMA_CFG; - case NITIO_G1_DMA_STATUS: - return NI660X_G1_DMA_STATUS; - case NITIO_G2_DMA_CFG: - return NI660X_G2_DMA_CFG; - case NITIO_G2_DMA_STATUS: - return NI660X_G2_DMA_STATUS; - case NITIO_G3_DMA_CFG: - return NI660X_G3_DMA_CFG; - case NITIO_G3_DMA_STATUS: - return NI660X_G3_DMA_STATUS; - case NITIO_G0_INT_ACK: - return NI660X_G0_INT_ACK; - case NITIO_G1_INT_ACK: - return NI660X_G1_INT_ACK; - case NITIO_G2_INT_ACK: - return NI660X_G2_INT_ACK; - case NITIO_G3_INT_ACK: - return NI660X_G3_INT_ACK; - case NITIO_G0_STATUS: - return NI660X_G0_STATUS; - case NITIO_G1_STATUS: - return NI660X_G1_STATUS; - case NITIO_G2_STATUS: - return NI660X_G2_STATUS; - case NITIO_G3_STATUS: - return NI660X_G3_STATUS; - case NITIO_G0_INT_ENA: - return NI660X_G0_INT_ENA; - case NITIO_G1_INT_ENA: - return NI660X_G1_INT_ENA; - case NITIO_G2_INT_ENA: - return NI660X_G2_INT_ENA; - case NITIO_G3_INT_ENA: - return NI660X_G3_INT_ENA; - default: - BUG(); - return 0; - } -} - static void ni_660x_write(struct comedi_device *dev, unsigned int chip, unsigned int bits, enum ni_660x_register reg) @@ -508,7 +434,15 @@ static void ni_660x_gpct_write(struct ni_gpct *counter, unsigned int bits, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; - enum ni_660x_register ni_660x_register = ni_gpct_to_660x_register(reg); + enum ni_660x_register ni_660x_register; + + if (reg < ARRAY_SIZE(ni_gpct_to_660x_register)) { + ni_660x_register = ni_gpct_to_660x_register[reg]; + } else { + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", + __func__, reg); + return; + } ni_660x_write(dev, counter->chip_index, bits, ni_660x_register); } @@ -517,7 +451,15 @@ static unsigned int ni_660x_gpct_read(struct ni_gpct *counter, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; - enum ni_660x_register ni_660x_register = ni_gpct_to_660x_register(reg); + enum ni_660x_register ni_660x_register; + + if (reg < ARRAY_SIZE(ni_gpct_to_660x_register)) { + ni_660x_register = ni_gpct_to_660x_register[reg]; + } else { + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", + __func__, reg); + return 0; + } return ni_660x_read(dev, counter->chip_index, ni_660x_register); } -- GitLab From e8f6e2b98d164d94bc29bb488413301d26cc5b3c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:36 -0700 Subject: [PATCH 0498/9938] staging: comedi: ni_660x: add comments for the spinlock_t definitions Fix the checkpatch.pl issues: CHECK: spinlock_t definition without comment For aesthetics, rename the 'soft_reg_copy_lock' to clarify what it's used for. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 3edea9928b09..2926d265f0bd 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -398,11 +398,13 @@ struct ni_660x_private { struct ni_gpct_device *counter_dev; struct mite_dma_descriptor_ring *mite_rings[NI_660X_MAX_NUM_CHIPS][counters_per_chip]; + /* protects mite channel request/release */ spinlock_t mite_channel_lock; - /* interrupt_lock prevents races between interrupt and comedi_poll */ + /* prevents races between interrupt and comedi_poll */ spinlock_t interrupt_lock; + /* protects dma_cfg changes */ + spinlock_t dma_cfg_lock; unsigned int dma_cfg[NI_660X_MAX_NUM_CHIPS]; - spinlock_t soft_reg_copy_lock; unsigned int io_cfg[NUM_PFI_CHANNELS]; u64 io_dir; }; @@ -482,7 +484,7 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev, unsigned int chip = counter->chip_index; unsigned long flags; - spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); + spin_lock_irqsave(&devpriv->dma_cfg_lock, flags); devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL(mite_channel, counter->counter_index); @@ -490,7 +492,7 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev, NI660X_DMA_CFG_RESET(mite_channel), NI660X_DMA_CFG); mmiowb(); - spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); + spin_unlock_irqrestore(&devpriv->dma_cfg_lock, flags); } static inline void ni_660x_unset_dma_channel(struct comedi_device *dev, @@ -501,12 +503,12 @@ static inline void ni_660x_unset_dma_channel(struct comedi_device *dev, unsigned int chip = counter->chip_index; unsigned long flags; - spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); + spin_lock_irqsave(&devpriv->dma_cfg_lock, flags); devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL_NONE(mite_channel); ni_660x_write(dev, chip, devpriv->dma_cfg[chip], NI660X_DMA_CFG); mmiowb(); - spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); + spin_unlock_irqrestore(&devpriv->dma_cfg_lock, flags); } static int ni_660x_request_mite_channel(struct comedi_device *dev, @@ -662,7 +664,7 @@ static int ni_660x_allocate_private(struct comedi_device *dev) spin_lock_init(&devpriv->mite_channel_lock); spin_lock_init(&devpriv->interrupt_lock); - spin_lock_init(&devpriv->soft_reg_copy_lock); + spin_lock_init(&devpriv->dma_cfg_lock); for (i = 0; i < NUM_PFI_CHANNELS; ++i) devpriv->io_cfg[i] = NI_660X_PFI_OUTPUT_COUNTER; -- GitLab From 5262d035ef260c3417254b2309892bba013dcab7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:37 -0700 Subject: [PATCH 0499/9938] staging: comedi: ni_660x: fix memory barrier without comment Fix the checkpatch.pl issue. Move the memory barrier to a better place. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 2926d265f0bd..bb5b5ff4e32f 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -613,9 +613,11 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d) if (!dev->attached) return IRQ_NONE; + /* make sure dev->attached is checked before doing anything else */ + smp_mb(); + /* lock to avoid race with comedi_poll */ spin_lock_irqsave(&devpriv->interrupt_lock, flags); - smp_mb(); for (i = 0; i < dev->n_subdevices; ++i) { s = &dev->subdevices[i]; if (s->type == COMEDI_SUBD_COUNTER) -- GitLab From ccef0da819dd7fa716b90e584a7793a8849b06f1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:38 -0700 Subject: [PATCH 0500/9938] staging: comedi: ni_660x: tidy up the misc. constants Remove enum ni_660x_constants and just #define the value. Move all the constant #defines so they are in one place and rename them so they are more conesistent. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 49 ++++++++++++------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index bb5b5ff4e32f..80499d6de44b 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -41,14 +41,6 @@ #include "mite.h" #include "ni_tio.h" -enum ni_660x_constants { - counters_per_chip = 4 -}; - -#define NUM_PFI_CHANNELS 40 -/* there are only up to 3 dma channels, but the register layout allows for 4 */ -#define MAX_DMA_CHANNEL 4 - /* See Register-Level Programmer Manual page 3.1 */ enum ni_660x_register { NI660X_G0_INT_ACK, @@ -390,22 +382,29 @@ static const struct ni_660x_board ni_660x_boards[] = { }, }; -#define NI_660X_MAX_NUM_CHIPS 2 -#define NI_660X_MAX_NUM_COUNTERS (NI_660X_MAX_NUM_CHIPS * counters_per_chip) +#define NI660X_NUM_PFI_CHANNELS 40 + +/* there are only up to 3 dma channels, but the register layout allows for 4 */ +#define NI660X_MAX_DMA_CHANNEL 4 + +#define NI660X_COUNTERS_PER_CHIP 4 +#define NI660X_MAX_CHIPS 2 +#define NI660X_MAX_COUNTERS (NI660X_MAX_CHIPS * \ + NI660X_COUNTERS_PER_CHIP) struct ni_660x_private { struct mite_struct *mite; struct ni_gpct_device *counter_dev; struct mite_dma_descriptor_ring - *mite_rings[NI_660X_MAX_NUM_CHIPS][counters_per_chip]; + *mite_rings[NI660X_MAX_CHIPS][NI660X_COUNTERS_PER_CHIP]; /* protects mite channel request/release */ spinlock_t mite_channel_lock; /* prevents races between interrupt and comedi_poll */ spinlock_t interrupt_lock; /* protects dma_cfg changes */ spinlock_t dma_cfg_lock; - unsigned int dma_cfg[NI_660X_MAX_NUM_CHIPS]; - unsigned int io_cfg[NUM_PFI_CHANNELS]; + unsigned int dma_cfg[NI660X_MAX_CHIPS]; + unsigned int io_cfg[NI660X_NUM_PFI_CHANNELS]; u64 io_dir; }; @@ -667,7 +666,7 @@ static int ni_660x_allocate_private(struct comedi_device *dev) spin_lock_init(&devpriv->mite_channel_lock); spin_lock_init(&devpriv->interrupt_lock); spin_lock_init(&devpriv->dma_cfg_lock); - for (i = 0; i < NUM_PFI_CHANNELS; ++i) + for (i = 0; i < NI660X_NUM_PFI_CHANNELS; ++i) devpriv->io_cfg[i] = NI_660X_PFI_OUTPUT_COUNTER; return 0; @@ -681,7 +680,7 @@ static int ni_660x_alloc_mite_rings(struct comedi_device *dev) unsigned int j; for (i = 0; i < board->n_chips; ++i) { - for (j = 0; j < counters_per_chip; ++j) { + for (j = 0; j < NI660X_COUNTERS_PER_CHIP; ++j) { devpriv->mite_rings[i][j] = mite_alloc_ring(devpriv->mite); if (!devpriv->mite_rings[i][j]) @@ -699,7 +698,7 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev) unsigned int j; for (i = 0; i < board->n_chips; ++i) { - for (j = 0; j < counters_per_chip; ++j) + for (j = 0; j < NI660X_COUNTERS_PER_CHIP; ++j) mite_free_ring(devpriv->mite_rings[i][j]); } } @@ -711,10 +710,10 @@ static void init_tio_chip(struct comedi_device *dev, int chipset) /* init dma configuration register */ devpriv->dma_cfg[chipset] = 0; - for (i = 0; i < MAX_DMA_CHANNEL; ++i) + for (i = 0; i < NI660X_MAX_DMA_CHANNEL; ++i) devpriv->dma_cfg[chipset] |= NI660X_DMA_CFG_SEL_NONE(i); ni_660x_write(dev, chipset, devpriv->dma_cfg[chipset], NI660X_DMA_CFG); - for (i = 0; i < NUM_PFI_CHANNELS; ++i) + for (i = 0; i < NI660X_NUM_PFI_CHANNELS; ++i) ni_660x_write(dev, chipset, 0, NI660X_IO_CFG(i)); } @@ -899,7 +898,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, if (ret < 0) return ret; - ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS); + ret = comedi_alloc_subdevices(dev, 2 + NI660X_MAX_COUNTERS); if (ret) return ret; @@ -965,7 +964,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s = &dev->subdevices[subdev++]; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = NUM_PFI_CHANNELS; + s->n_chan = NI660X_NUM_PFI_CHANNELS; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = ni_660x_dio_insn_bits; @@ -977,7 +976,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, */ ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); - n_counters = board->n_chips * counters_per_chip; + n_counters = board->n_chips * NI660X_COUNTERS_PER_CHIP; devpriv->counter_dev = ni_gpct_device_construct(dev, ni_660x_gpct_write, ni_660x_gpct_read, @@ -985,7 +984,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, n_counters); if (!devpriv->counter_dev) return -ENOMEM; - for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) { + for (i = 0; i < NI660X_MAX_COUNTERS; ++i) { s = &dev->subdevices[subdev++]; if (i < n_counters) { s->type = COMEDI_SUBD_COUNTER; @@ -1006,9 +1005,9 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->private = &devpriv->counter_dev->counters[i]; devpriv->counter_dev->counters[i].chip_index = - i / counters_per_chip; + i / NI660X_COUNTERS_PER_CHIP; devpriv->counter_dev->counters[i].counter_index = - i % counters_per_chip; + i % NI660X_COUNTERS_PER_CHIP; } else { s->type = COMEDI_SUBD_UNUSED; } @@ -1024,7 +1023,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, * chan 0-7: DIO inputs * chan 8-39: counter signal inputs */ - for (i = 0; i < NUM_PFI_CHANNELS; ++i) { + for (i = 0; i < NI660X_NUM_PFI_CHANNELS; ++i) { if (i < 8) ni_660x_set_pfi_routing(dev, i, NI_660X_PFI_OUTPUT_DIO); else -- GitLab From 32f89d8e70106f2b636c716a7cfb7fe53cfc5ebf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:39 -0700 Subject: [PATCH 0501/9938] staging: comedi: ni_660x: tidy up the counter subdevices init For aesthetics, add some whitespace to the subdevice init and use a couple local variables to make the code easier to follow. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 59 +++++++++++++----------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 80499d6de44b..35602cc7af61 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -864,6 +864,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev, const struct ni_660x_board *board = NULL; struct ni_660x_private *devpriv; struct comedi_subdevice *s; + struct ni_gpct_device *gpct_dev; unsigned int n_counters; int subdev; int ret; @@ -977,46 +978,50 @@ static int ni_660x_auto_attach(struct comedi_device *dev, ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); n_counters = board->n_chips * NI660X_COUNTERS_PER_CHIP; - devpriv->counter_dev = ni_gpct_device_construct(dev, - ni_660x_gpct_write, - ni_660x_gpct_read, - ni_gpct_variant_660x, - n_counters); - if (!devpriv->counter_dev) + gpct_dev = ni_gpct_device_construct(dev, + ni_660x_gpct_write, + ni_660x_gpct_read, + ni_gpct_variant_660x, + n_counters); + if (!gpct_dev) return -ENOMEM; + devpriv->counter_dev = gpct_dev; + + /* Counter subdevices (4 NI TIO General Purpose Counters per chip) */ for (i = 0; i < NI660X_MAX_COUNTERS; ++i) { s = &dev->subdevices[subdev++]; if (i < n_counters) { - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | + struct ni_gpct *counter = &gpct_dev->counters[i]; + + counter->chip_index = i / NI660X_COUNTERS_PER_CHIP; + counter->counter_index = i % NI660X_COUNTERS_PER_CHIP; + + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ; - s->n_chan = 3; - s->maxdata = 0xffffffff; - s->insn_read = ni_tio_insn_read; - s->insn_write = ni_tio_insn_write; - s->insn_config = ni_tio_insn_config; - s->do_cmd = &ni_660x_cmd; - s->len_chanlist = 1; - s->do_cmdtest = ni_tio_cmdtest; - s->cancel = &ni_660x_cancel; - s->poll = &ni_660x_input_poll; + s->n_chan = 3; + s->maxdata = 0xffffffff; + s->insn_read = ni_tio_insn_read; + s->insn_write = ni_tio_insn_write; + s->insn_config = ni_tio_insn_config; + s->len_chanlist = 1; + s->do_cmd = ni_660x_cmd; + s->do_cmdtest = ni_tio_cmdtest; + s->cancel = ni_660x_cancel; + s->poll = ni_660x_input_poll; + s->buf_change = ni_660x_buf_change; s->async_dma_dir = DMA_BIDIRECTIONAL; - s->buf_change = &ni_660x_buf_change; - s->private = &devpriv->counter_dev->counters[i]; - - devpriv->counter_dev->counters[i].chip_index = - i / NI660X_COUNTERS_PER_CHIP; - devpriv->counter_dev->counters[i].counter_index = - i % NI660X_COUNTERS_PER_CHIP; + s->private = counter; } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } } + for (i = 0; i < board->n_chips; ++i) init_tio_chip(dev, i); for (i = 0; i < n_counters; ++i) - ni_tio_init_counter(&devpriv->counter_dev->counters[i]); + ni_tio_init_counter(&gpct_dev->counters[i]); /* * Default the DIO channels as: -- GitLab From 26a0fe3ffa24c63a99b1fb314e03723c1e470ba0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:41 -0700 Subject: [PATCH 0502/9938] staging: comedi: ni_660x: ni_gpct_device_destroy() can handle a NULL pointer Remove the unnecessary NULL pointer check. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 35602cc7af61..2440cb6a72c7 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1067,8 +1067,7 @@ static void ni_660x_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); if (devpriv) { - if (devpriv->counter_dev) - ni_gpct_device_destroy(devpriv->counter_dev); + ni_gpct_device_destroy(devpriv->counter_dev); ni_660x_free_mite_rings(dev); mite_detach(devpriv->mite); } -- GitLab From 78d514fa4cc0f195e060b7918d3548b63d27050f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:43 -0700 Subject: [PATCH 0503/9938] staging: comedi: ni_660x: disable interrupts when detaching driver Make sure the interrupts are disabled before freeing the irq. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 2440cb6a72c7..c71dae8da804 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1064,8 +1064,10 @@ static void ni_660x_detach(struct comedi_device *dev) { struct ni_660x_private *devpriv = dev->private; - if (dev->irq) + if (dev->irq) { + ni_660x_write(dev, 0, 0, NI660X_GLOBAL_INT_CFG); free_irq(dev->irq, dev); + } if (devpriv) { ni_gpct_device_destroy(devpriv->counter_dev); ni_660x_free_mite_rings(dev); -- GitLab From 2363cbf073225537016aceb6bf122bbee6a0caa0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:44 -0700 Subject: [PATCH 0504/9938] staging: comedi: ni_660x: init TIO chips before subdevice init For aesthetics, initialize the TIO chips before the subdevices are allocated and initialized. Refactor the function to initialize all the TIO chips and move it to a better place in the driver. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 52 +++++++++++++----------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index c71dae8da804..afe62bf2de8b 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -703,20 +703,6 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev) } } -static void init_tio_chip(struct comedi_device *dev, int chipset) -{ - struct ni_660x_private *devpriv = dev->private; - unsigned int i; - - /* init dma configuration register */ - devpriv->dma_cfg[chipset] = 0; - for (i = 0; i < NI660X_MAX_DMA_CHANNEL; ++i) - devpriv->dma_cfg[chipset] |= NI660X_DMA_CFG_SEL_NONE(i); - ni_660x_write(dev, chipset, devpriv->dma_cfg[chipset], NI660X_DMA_CFG); - for (i = 0; i < NI660X_NUM_PFI_CHANNELS; ++i) - ni_660x_write(dev, chipset, 0, NI660X_IO_CFG(i)); -} - static int ni_660x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -857,6 +843,33 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, return insn->n; } +static void ni_660x_init_tio_chips(struct comedi_device *dev, + unsigned int n_chips) +{ + struct ni_660x_private *devpriv = dev->private; + unsigned int chip; + unsigned int chan; + + /* + * We use the ioconfig registers to control dio direction, so zero + * output enables in stc dio control reg. + */ + ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); + + for (chip = 0; chip < n_chips; ++chip) { + /* init dma configuration register */ + devpriv->dma_cfg[chip] = 0; + for (chan = 0; chan < NI660X_MAX_DMA_CHANNEL; ++chan) + devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL_NONE(chan); + ni_660x_write(dev, chip, devpriv->dma_cfg[chip], + NI660X_DMA_CFG); + + /* init ioconfig registers */ + for (chan = 0; chan < NI660X_NUM_PFI_CHANNELS; ++chan) + ni_660x_write(dev, chip, 0, NI660X_IO_CFG(chan)); + } +} + static int ni_660x_auto_attach(struct comedi_device *dev, unsigned long context) { @@ -899,6 +912,8 @@ static int ni_660x_auto_attach(struct comedi_device *dev, if (ret < 0) return ret; + ni_660x_init_tio_chips(dev, board->n_chips); + ret = comedi_alloc_subdevices(dev, 2 + NI660X_MAX_COUNTERS); if (ret) return ret; @@ -971,12 +986,6 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->insn_bits = ni_660x_dio_insn_bits; s->insn_config = ni_660x_dio_insn_config; - /* - * We use the ioconfig registers to control dio direction, so zero - * output enables in stc dio control reg. - */ - ni_660x_write(dev, 0, 0, NI660X_STC_DIO_CONTROL); - n_counters = board->n_chips * NI660X_COUNTERS_PER_CHIP; gpct_dev = ni_gpct_device_construct(dev, ni_660x_gpct_write, @@ -1017,9 +1026,6 @@ static int ni_660x_auto_attach(struct comedi_device *dev, } } - for (i = 0; i < board->n_chips; ++i) - init_tio_chip(dev, i); - for (i = 0; i < n_counters; ++i) ni_tio_init_counter(&gpct_dev->counters[i]); -- GitLab From f229594a327720c0761e7307a5472aea780268c3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:45 -0700 Subject: [PATCH 0505/9938] staging: comedi: ni_660x: allocate counters early in (*auto_attach) The ni_gpct_device_construct() could fail allocating the memory for device and its counters. For aesthetics, call the function before initializing the subdevices. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index afe62bf2de8b..636630380100 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -914,6 +914,16 @@ static int ni_660x_auto_attach(struct comedi_device *dev, ni_660x_init_tio_chips(dev, board->n_chips); + n_counters = board->n_chips * NI660X_COUNTERS_PER_CHIP; + gpct_dev = ni_gpct_device_construct(dev, + ni_660x_gpct_write, + ni_660x_gpct_read, + ni_gpct_variant_660x, + n_counters); + if (!gpct_dev) + return -ENOMEM; + devpriv->counter_dev = gpct_dev; + ret = comedi_alloc_subdevices(dev, 2 + NI660X_MAX_COUNTERS); if (ret) return ret; @@ -986,16 +996,6 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->insn_bits = ni_660x_dio_insn_bits; s->insn_config = ni_660x_dio_insn_config; - n_counters = board->n_chips * NI660X_COUNTERS_PER_CHIP; - gpct_dev = ni_gpct_device_construct(dev, - ni_660x_gpct_write, - ni_660x_gpct_read, - ni_gpct_variant_660x, - n_counters); - if (!gpct_dev) - return -ENOMEM; - devpriv->counter_dev = gpct_dev; - /* Counter subdevices (4 NI TIO General Purpose Counters per chip) */ for (i = 0; i < NI660X_MAX_COUNTERS; ++i) { s = &dev->subdevices[subdev++]; -- GitLab From 90ad57be6be10e7084ca677d6eddfba612b55a62 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:46 -0700 Subject: [PATCH 0506/9938] staging: comedi: ni_660x: initialize the counter with the subdevice init Remove the extra for loop and just initialize the counter as the subdevices are created. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 636630380100..5969723b6167 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1021,14 +1021,13 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->buf_change = ni_660x_buf_change; s->async_dma_dir = DMA_BIDIRECTIONAL; s->private = counter; + + ni_tio_init_counter(counter); } else { s->type = COMEDI_SUBD_UNUSED; } } - for (i = 0; i < n_counters; ++i) - ni_tio_init_counter(&gpct_dev->counters[i]); - /* * Default the DIO channels as: * chan 0-7: DIO inputs -- GitLab From 34b7f1f8194da6600eda6bb7c26659de19047a39 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:47 -0700 Subject: [PATCH 0507/9938] staging: comedi: ni_660x: default DIO channels with subdevice init For aesthetics, move the initialization of the default routing for the DIO channels so it happens when the subdevice is initialized. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 27 ++++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 5969723b6167..cf25892d92b2 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -996,6 +996,19 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->insn_bits = ni_660x_dio_insn_bits; s->insn_config = ni_660x_dio_insn_config; + /* + * Default the DIO channels as: + * chan 0-7: DIO inputs + * chan 8-39: counter signal inputs + */ + for (i = 0; i < s->n_chan; ++i) { + unsigned int source = (i < 8) ? NI_660X_PFI_OUTPUT_DIO + : NI_660X_PFI_OUTPUT_COUNTER; + + ni_660x_set_pfi_routing(dev, i, source); + ni_660x_select_pfi_output(dev, i, 0); /* high-z */ + } + /* Counter subdevices (4 NI TIO General Purpose Counters per chip) */ for (i = 0; i < NI660X_MAX_COUNTERS; ++i) { s = &dev->subdevices[subdev++]; @@ -1028,20 +1041,6 @@ static int ni_660x_auto_attach(struct comedi_device *dev, } } - /* - * Default the DIO channels as: - * chan 0-7: DIO inputs - * chan 8-39: counter signal inputs - */ - for (i = 0; i < NI660X_NUM_PFI_CHANNELS; ++i) { - if (i < 8) - ni_660x_set_pfi_routing(dev, i, NI_660X_PFI_OUTPUT_DIO); - else - ni_660x_set_pfi_routing(dev, i, - NI_660X_PFI_OUTPUT_COUNTER); - ni_660x_select_pfi_output(dev, i, 0); /* high-z */ - } - /* * To be safe, set counterswap bits on tio chips after all the counter * outputs have been set to high impedance mode. -- GitLab From 515b5e6b8afdd32a3b528a331f23b852fe083c26 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:48 -0700 Subject: [PATCH 0508/9938] staging: comedi: ni_660x: remove inline mite_ring() This fuction just returns a pointer from the private data. The name might provide some confusion since it appears to be an exported function from the mite driver. Just remove it and get the pointer directly where needed. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index cf25892d92b2..1cca9ea5cdd2 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -465,16 +465,6 @@ static unsigned int ni_660x_gpct_read(struct ni_gpct *counter, return ni_660x_read(dev, counter->chip_index, ni_660x_register); } -static inline struct mite_dma_descriptor_ring *mite_ring(struct ni_660x_private - *priv, - struct ni_gpct - *counter) -{ - unsigned int chip = counter->chip_index; - - return priv->mite_rings[chip][counter->counter_index]; -} - static inline void ni_660x_set_dma_channel(struct comedi_device *dev, unsigned int mite_channel, struct ni_gpct *counter) @@ -515,12 +505,13 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev, enum comedi_io_direction direction) { struct ni_660x_private *devpriv = dev->private; - unsigned long flags; + struct mite_dma_descriptor_ring *ring; struct mite_channel *mite_chan; + unsigned long flags; spin_lock_irqsave(&devpriv->mite_channel_lock, flags); - mite_chan = mite_request_channel(devpriv->mite, - mite_ring(devpriv, counter)); + ring = devpriv->mite_rings[counter->chip_index][counter->counter_index]; + mite_chan = mite_request_channel(devpriv->mite, ring); if (!mite_chan) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); dev_err(dev->class_dev, @@ -645,9 +636,11 @@ static int ni_660x_buf_change(struct comedi_device *dev, { struct ni_660x_private *devpriv = dev->private; struct ni_gpct *counter = s->private; + struct mite_dma_descriptor_ring *ring; int ret; - ret = mite_buf_change(mite_ring(devpriv, counter), s); + ring = devpriv->mite_rings[counter->chip_index][counter->counter_index]; + ret = mite_buf_change(ring, s); if (ret < 0) return ret; -- GitLab From 242311d1a9e5cebde39855e064dcc4ac0dabde93 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:49 -0700 Subject: [PATCH 0509/9938] staging: comedi: ni_660x: sort enum ni_660x_register Sort this enum so that it has a 1:1 relationship with the ni_tio.h enum ni_gpct_register. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 95 ++++++++++++------------ 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 1cca9ea5cdd2..ad67ee5ec7ff 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -43,78 +43,79 @@ /* See Register-Level Programmer Manual page 3.1 */ enum ni_660x_register { - NI660X_G0_INT_ACK, - NI660X_G0_STATUS, - NI660X_G1_INT_ACK, - NI660X_G1_STATUS, - NI660X_G01_STATUS, + NI660X_G0_AUTO_INC, + NI660X_G1_AUTO_INC, + NI660X_G2_AUTO_INC, + NI660X_G3_AUTO_INC, NI660X_G0_CMD, - NI660X_STC_DIO_PARALLEL_INPUT, NI660X_G1_CMD, + NI660X_G2_CMD, + NI660X_G3_CMD, NI660X_G0_HW_SAVE, NI660X_G1_HW_SAVE, - NI660X_STC_DIO_OUTPUT, - NI660X_STC_DIO_CONTROL, + NI660X_G2_HW_SAVE, + NI660X_G3_HW_SAVE, NI660X_G0_SW_SAVE, NI660X_G1_SW_SAVE, + NI660X_G2_SW_SAVE, + NI660X_G3_SW_SAVE, NI660X_G0_MODE, - NI660X_G01_STATUS1, NI660X_G1_MODE, - NI660X_STC_DIO_SERIAL_INPUT, + NI660X_G2_MODE, + NI660X_G3_MODE, NI660X_G0_LOADA, - NI660X_G01_STATUS2, - NI660X_G0_LOADB, NI660X_G1_LOADA, + NI660X_G2_LOADA, + NI660X_G3_LOADA, + NI660X_G0_LOADB, NI660X_G1_LOADB, + NI660X_G2_LOADB, + NI660X_G3_LOADB, NI660X_G0_INPUT_SEL, NI660X_G1_INPUT_SEL, - NI660X_G0_AUTO_INC, - NI660X_G1_AUTO_INC, - NI660X_G01_RESET, - NI660X_G0_INT_ENA, - NI660X_G1_INT_ENA, + NI660X_G2_INPUT_SEL, + NI660X_G3_INPUT_SEL, NI660X_G0_CNT_MODE, NI660X_G1_CNT_MODE, + NI660X_G2_CNT_MODE, + NI660X_G3_CNT_MODE, NI660X_G0_GATE2, NI660X_G1_GATE2, + NI660X_G2_GATE2, + NI660X_G3_GATE2, + NI660X_G01_STATUS, + NI660X_G23_STATUS, + NI660X_G01_RESET, + NI660X_G23_RESET, + NI660X_G01_STATUS1, + NI660X_G23_STATUS1, + NI660X_G01_STATUS2, + NI660X_G23_STATUS2, NI660X_G0_DMA_CFG, - NI660X_G0_DMA_STATUS, NI660X_G1_DMA_CFG, + NI660X_G2_DMA_CFG, + NI660X_G3_DMA_CFG, + NI660X_G0_DMA_STATUS, NI660X_G1_DMA_STATUS, + NI660X_G2_DMA_STATUS, + NI660X_G3_DMA_STATUS, + NI660X_G0_INT_ACK, + NI660X_G1_INT_ACK, NI660X_G2_INT_ACK, - NI660X_G2_STATUS, NI660X_G3_INT_ACK, + NI660X_G0_STATUS, + NI660X_G1_STATUS, + NI660X_G2_STATUS, NI660X_G3_STATUS, - NI660X_G23_STATUS, - NI660X_G2_CMD, - NI660X_G3_CMD, - NI660X_G2_HW_SAVE, - NI660X_G3_HW_SAVE, - NI660X_G2_SW_SAVE, - NI660X_G3_SW_SAVE, - NI660X_G2_MODE, - NI660X_G23_STATUS1, - NI660X_G3_MODE, - NI660X_G2_LOADA, - NI660X_G23_STATUS2, - NI660X_G2_LOADB, - NI660X_G3_LOADA, - NI660X_G3_LOADB, - NI660X_G2_INPUT_SEL, - NI660X_G3_INPUT_SEL, - NI660X_G2_AUTO_INC, - NI660X_G3_AUTO_INC, - NI660X_G23_RESET, + NI660X_G0_INT_ENA, + NI660X_G1_INT_ENA, NI660X_G2_INT_ENA, NI660X_G3_INT_ENA, - NI660X_G2_CNT_MODE, - NI660X_G3_CNT_MODE, - NI660X_G3_GATE2, - NI660X_G2_GATE2, - NI660X_G2_DMA_CFG, - NI660X_G2_DMA_STATUS, - NI660X_G3_DMA_CFG, - NI660X_G3_DMA_STATUS, + + NI660X_STC_DIO_PARALLEL_INPUT = NITIO_NUM_REGS, + NI660X_STC_DIO_OUTPUT, + NI660X_STC_DIO_CONTROL, + NI660X_STC_DIO_SERIAL_INPUT, NI660X_DIO32_INPUT, NI660X_DIO32_OUTPUT, NI660X_CLK_CFG, -- GitLab From 4f2c3b2077a9bb34c7b5afe31633a1f5b1ca80b4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:50 -0700 Subject: [PATCH 0510/9938] staging: comedi: ni_660x: remove ni_gpct_to_660x_register[] enum ni_gpct_register and enum ni_660x_register now have a 1:1 relationship for the NITIO_* registers. The static const array is no longer necessary to find the proper NI660X_* register for a given NITIO_*. Remove it and refactor the register read/write functions. Use the NITIO_* values to init the ni_660x_reg_data[] array and remove the unnecessary NI660X_* enum values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 307 ++++++----------------- 1 file changed, 74 insertions(+), 233 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index ad67ee5ec7ff..85c793a458f8 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -43,75 +43,7 @@ /* See Register-Level Programmer Manual page 3.1 */ enum ni_660x_register { - NI660X_G0_AUTO_INC, - NI660X_G1_AUTO_INC, - NI660X_G2_AUTO_INC, - NI660X_G3_AUTO_INC, - NI660X_G0_CMD, - NI660X_G1_CMD, - NI660X_G2_CMD, - NI660X_G3_CMD, - NI660X_G0_HW_SAVE, - NI660X_G1_HW_SAVE, - NI660X_G2_HW_SAVE, - NI660X_G3_HW_SAVE, - NI660X_G0_SW_SAVE, - NI660X_G1_SW_SAVE, - NI660X_G2_SW_SAVE, - NI660X_G3_SW_SAVE, - NI660X_G0_MODE, - NI660X_G1_MODE, - NI660X_G2_MODE, - NI660X_G3_MODE, - NI660X_G0_LOADA, - NI660X_G1_LOADA, - NI660X_G2_LOADA, - NI660X_G3_LOADA, - NI660X_G0_LOADB, - NI660X_G1_LOADB, - NI660X_G2_LOADB, - NI660X_G3_LOADB, - NI660X_G0_INPUT_SEL, - NI660X_G1_INPUT_SEL, - NI660X_G2_INPUT_SEL, - NI660X_G3_INPUT_SEL, - NI660X_G0_CNT_MODE, - NI660X_G1_CNT_MODE, - NI660X_G2_CNT_MODE, - NI660X_G3_CNT_MODE, - NI660X_G0_GATE2, - NI660X_G1_GATE2, - NI660X_G2_GATE2, - NI660X_G3_GATE2, - NI660X_G01_STATUS, - NI660X_G23_STATUS, - NI660X_G01_RESET, - NI660X_G23_RESET, - NI660X_G01_STATUS1, - NI660X_G23_STATUS1, - NI660X_G01_STATUS2, - NI660X_G23_STATUS2, - NI660X_G0_DMA_CFG, - NI660X_G1_DMA_CFG, - NI660X_G2_DMA_CFG, - NI660X_G3_DMA_CFG, - NI660X_G0_DMA_STATUS, - NI660X_G1_DMA_STATUS, - NI660X_G2_DMA_STATUS, - NI660X_G3_DMA_STATUS, - NI660X_G0_INT_ACK, - NI660X_G1_INT_ACK, - NI660X_G2_INT_ACK, - NI660X_G3_INT_ACK, - NI660X_G0_STATUS, - NI660X_G1_STATUS, - NI660X_G2_STATUS, - NI660X_G3_STATUS, - NI660X_G0_INT_ENA, - NI660X_G1_INT_ENA, - NI660X_G2_INT_ENA, - NI660X_G3_INT_ENA, - + /* see enum ni_gpct_register */ NI660X_STC_DIO_PARALLEL_INPUT = NITIO_NUM_REGS, NI660X_STC_DIO_OUTPUT, NI660X_STC_DIO_CONTROL, @@ -172,78 +104,78 @@ struct ni_660x_register_data { }; static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { - [NI660X_G0_INT_ACK] = { 0x004, 2 }, /* write */ - [NI660X_G0_STATUS] = { 0x004, 2 }, /* read */ - [NI660X_G1_INT_ACK] = { 0x006, 2 }, /* write */ - [NI660X_G1_STATUS] = { 0x006, 2 }, /* read */ - [NI660X_G01_STATUS] = { 0x008, 2 }, /* read */ - [NI660X_G0_CMD] = { 0x00c, 2 }, /* write */ + [NITIO_G0_INT_ACK] = { 0x004, 2 }, /* write */ + [NITIO_G0_STATUS] = { 0x004, 2 }, /* read */ + [NITIO_G1_INT_ACK] = { 0x006, 2 }, /* write */ + [NITIO_G1_STATUS] = { 0x006, 2 }, /* read */ + [NITIO_G01_STATUS] = { 0x008, 2 }, /* read */ + [NITIO_G0_CMD] = { 0x00c, 2 }, /* write */ [NI660X_STC_DIO_PARALLEL_INPUT] = { 0x00e, 2 }, /* read */ - [NI660X_G1_CMD] = { 0x00e, 2 }, /* write */ - [NI660X_G0_HW_SAVE] = { 0x010, 4 }, /* read */ - [NI660X_G1_HW_SAVE] = { 0x014, 4 }, /* read */ + [NITIO_G1_CMD] = { 0x00e, 2 }, /* write */ + [NITIO_G0_HW_SAVE] = { 0x010, 4 }, /* read */ + [NITIO_G1_HW_SAVE] = { 0x014, 4 }, /* read */ [NI660X_STC_DIO_OUTPUT] = { 0x014, 2 }, /* write */ [NI660X_STC_DIO_CONTROL] = { 0x016, 2 }, /* write */ - [NI660X_G0_SW_SAVE] = { 0x018, 4 }, /* read */ - [NI660X_G1_SW_SAVE] = { 0x01c, 4 }, /* read */ - [NI660X_G0_MODE] = { 0x034, 2 }, /* write */ - [NI660X_G01_STATUS1] = { 0x036, 2 }, /* read */ - [NI660X_G1_MODE] = { 0x036, 2 }, /* write */ + [NITIO_G0_SW_SAVE] = { 0x018, 4 }, /* read */ + [NITIO_G1_SW_SAVE] = { 0x01c, 4 }, /* read */ + [NITIO_G0_MODE] = { 0x034, 2 }, /* write */ + [NITIO_G01_STATUS1] = { 0x036, 2 }, /* read */ + [NITIO_G1_MODE] = { 0x036, 2 }, /* write */ [NI660X_STC_DIO_SERIAL_INPUT] = { 0x038, 2 }, /* read */ - [NI660X_G0_LOADA] = { 0x038, 4 }, /* write */ - [NI660X_G01_STATUS2] = { 0x03a, 2 }, /* read */ - [NI660X_G0_LOADB] = { 0x03c, 4 }, /* write */ - [NI660X_G1_LOADA] = { 0x040, 4 }, /* write */ - [NI660X_G1_LOADB] = { 0x044, 4 }, /* write */ - [NI660X_G0_INPUT_SEL] = { 0x048, 2 }, /* write */ - [NI660X_G1_INPUT_SEL] = { 0x04a, 2 }, /* write */ - [NI660X_G0_AUTO_INC] = { 0x088, 2 }, /* write */ - [NI660X_G1_AUTO_INC] = { 0x08a, 2 }, /* write */ - [NI660X_G01_RESET] = { 0x090, 2 }, /* write */ - [NI660X_G0_INT_ENA] = { 0x092, 2 }, /* write */ - [NI660X_G1_INT_ENA] = { 0x096, 2 }, /* write */ - [NI660X_G0_CNT_MODE] = { 0x0b0, 2 }, /* write */ - [NI660X_G1_CNT_MODE] = { 0x0b2, 2 }, /* write */ - [NI660X_G0_GATE2] = { 0x0b4, 2 }, /* write */ - [NI660X_G1_GATE2] = { 0x0b6, 2 }, /* write */ - [NI660X_G0_DMA_CFG] = { 0x0b8, 2 }, /* write */ - [NI660X_G0_DMA_STATUS] = { 0x0b8, 2 }, /* read */ - [NI660X_G1_DMA_CFG] = { 0x0ba, 2 }, /* write */ - [NI660X_G1_DMA_STATUS] = { 0x0ba, 2 }, /* read */ - [NI660X_G2_INT_ACK] = { 0x104, 2 }, /* write */ - [NI660X_G2_STATUS] = { 0x104, 2 }, /* read */ - [NI660X_G3_INT_ACK] = { 0x106, 2 }, /* write */ - [NI660X_G3_STATUS] = { 0x106, 2 }, /* read */ - [NI660X_G23_STATUS] = { 0x108, 2 }, /* read */ - [NI660X_G2_CMD] = { 0x10c, 2 }, /* write */ - [NI660X_G3_CMD] = { 0x10e, 2 }, /* write */ - [NI660X_G2_HW_SAVE] = { 0x110, 4 }, /* read */ - [NI660X_G3_HW_SAVE] = { 0x114, 4 }, /* read */ - [NI660X_G2_SW_SAVE] = { 0x118, 4 }, /* read */ - [NI660X_G3_SW_SAVE] = { 0x11c, 4 }, /* read */ - [NI660X_G2_MODE] = { 0x134, 2 }, /* write */ - [NI660X_G23_STATUS1] = { 0x136, 2 }, /* read */ - [NI660X_G3_MODE] = { 0x136, 2 }, /* write */ - [NI660X_G2_LOADA] = { 0x138, 4 }, /* write */ - [NI660X_G23_STATUS2] = { 0x13a, 2 }, /* read */ - [NI660X_G2_LOADB] = { 0x13c, 4 }, /* write */ - [NI660X_G3_LOADA] = { 0x140, 4 }, /* write */ - [NI660X_G3_LOADB] = { 0x144, 4 }, /* write */ - [NI660X_G2_INPUT_SEL] = { 0x148, 2 }, /* write */ - [NI660X_G3_INPUT_SEL] = { 0x14a, 2 }, /* write */ - [NI660X_G2_AUTO_INC] = { 0x188, 2 }, /* write */ - [NI660X_G3_AUTO_INC] = { 0x18a, 2 }, /* write */ - [NI660X_G23_RESET] = { 0x190, 2 }, /* write */ - [NI660X_G2_INT_ENA] = { 0x192, 2 }, /* write */ - [NI660X_G3_INT_ENA] = { 0x196, 2 }, /* write */ - [NI660X_G2_CNT_MODE] = { 0x1b0, 2 }, /* write */ - [NI660X_G3_CNT_MODE] = { 0x1b2, 2 }, /* write */ - [NI660X_G3_GATE2] = { 0x1b6, 2 }, /* write */ - [NI660X_G2_GATE2] = { 0x1b4, 2 }, /* write */ - [NI660X_G2_DMA_CFG] = { 0x1b8, 2 }, /* write */ - [NI660X_G2_DMA_STATUS] = { 0x1b8, 2 }, /* read */ - [NI660X_G3_DMA_CFG] = { 0x1ba, 2 }, /* write */ - [NI660X_G3_DMA_STATUS] = { 0x1ba, 2 }, /* read */ + [NITIO_G0_LOADA] = { 0x038, 4 }, /* write */ + [NITIO_G01_STATUS2] = { 0x03a, 2 }, /* read */ + [NITIO_G0_LOADB] = { 0x03c, 4 }, /* write */ + [NITIO_G1_LOADA] = { 0x040, 4 }, /* write */ + [NITIO_G1_LOADB] = { 0x044, 4 }, /* write */ + [NITIO_G0_INPUT_SEL] = { 0x048, 2 }, /* write */ + [NITIO_G1_INPUT_SEL] = { 0x04a, 2 }, /* write */ + [NITIO_G0_AUTO_INC] = { 0x088, 2 }, /* write */ + [NITIO_G1_AUTO_INC] = { 0x08a, 2 }, /* write */ + [NITIO_G01_RESET] = { 0x090, 2 }, /* write */ + [NITIO_G0_INT_ENA] = { 0x092, 2 }, /* write */ + [NITIO_G1_INT_ENA] = { 0x096, 2 }, /* write */ + [NITIO_G0_CNT_MODE] = { 0x0b0, 2 }, /* write */ + [NITIO_G1_CNT_MODE] = { 0x0b2, 2 }, /* write */ + [NITIO_G0_GATE2] = { 0x0b4, 2 }, /* write */ + [NITIO_G1_GATE2] = { 0x0b6, 2 }, /* write */ + [NITIO_G0_DMA_CFG] = { 0x0b8, 2 }, /* write */ + [NITIO_G0_DMA_STATUS] = { 0x0b8, 2 }, /* read */ + [NITIO_G1_DMA_CFG] = { 0x0ba, 2 }, /* write */ + [NITIO_G1_DMA_STATUS] = { 0x0ba, 2 }, /* read */ + [NITIO_G2_INT_ACK] = { 0x104, 2 }, /* write */ + [NITIO_G2_STATUS] = { 0x104, 2 }, /* read */ + [NITIO_G3_INT_ACK] = { 0x106, 2 }, /* write */ + [NITIO_G3_STATUS] = { 0x106, 2 }, /* read */ + [NITIO_G23_STATUS] = { 0x108, 2 }, /* read */ + [NITIO_G2_CMD] = { 0x10c, 2 }, /* write */ + [NITIO_G3_CMD] = { 0x10e, 2 }, /* write */ + [NITIO_G2_HW_SAVE] = { 0x110, 4 }, /* read */ + [NITIO_G3_HW_SAVE] = { 0x114, 4 }, /* read */ + [NITIO_G2_SW_SAVE] = { 0x118, 4 }, /* read */ + [NITIO_G3_SW_SAVE] = { 0x11c, 4 }, /* read */ + [NITIO_G2_MODE] = { 0x134, 2 }, /* write */ + [NITIO_G23_STATUS1] = { 0x136, 2 }, /* read */ + [NITIO_G3_MODE] = { 0x136, 2 }, /* write */ + [NITIO_G2_LOADA] = { 0x138, 4 }, /* write */ + [NITIO_G23_STATUS2] = { 0x13a, 2 }, /* read */ + [NITIO_G2_LOADB] = { 0x13c, 4 }, /* write */ + [NITIO_G3_LOADA] = { 0x140, 4 }, /* write */ + [NITIO_G3_LOADB] = { 0x144, 4 }, /* write */ + [NITIO_G2_INPUT_SEL] = { 0x148, 2 }, /* write */ + [NITIO_G3_INPUT_SEL] = { 0x14a, 2 }, /* write */ + [NITIO_G2_AUTO_INC] = { 0x188, 2 }, /* write */ + [NITIO_G3_AUTO_INC] = { 0x18a, 2 }, /* write */ + [NITIO_G23_RESET] = { 0x190, 2 }, /* write */ + [NITIO_G2_INT_ENA] = { 0x192, 2 }, /* write */ + [NITIO_G3_INT_ENA] = { 0x196, 2 }, /* write */ + [NITIO_G2_CNT_MODE] = { 0x1b0, 2 }, /* write */ + [NITIO_G3_CNT_MODE] = { 0x1b2, 2 }, /* write */ + [NITIO_G2_GATE2] = { 0x1b4, 2 }, /* write */ + [NITIO_G3_GATE2] = { 0x1b6, 2 }, /* write */ + [NITIO_G2_DMA_CFG] = { 0x1b8, 2 }, /* write */ + [NITIO_G2_DMA_STATUS] = { 0x1b8, 2 }, /* read */ + [NITIO_G3_DMA_CFG] = { 0x1ba, 2 }, /* write */ + [NITIO_G3_DMA_STATUS] = { 0x1ba, 2 }, /* read */ [NI660X_DIO32_INPUT] = { 0x414, 4 }, /* read */ [NI660X_DIO32_OUTPUT] = { 0x510, 4 }, /* write */ [NI660X_CLK_CFG] = { 0x73c, 4 }, /* write */ @@ -272,77 +204,6 @@ static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { [NI660X_IO_CFG_38_39] = { 0x7a2, 2 } /* read/write */ }; -static const enum ni_660x_register ni_gpct_to_660x_register[] = { - [NITIO_G0_AUTO_INC] = NI660X_G0_AUTO_INC, - [NITIO_G1_AUTO_INC] = NI660X_G1_AUTO_INC, - [NITIO_G2_AUTO_INC] = NI660X_G2_AUTO_INC, - [NITIO_G3_AUTO_INC] = NI660X_G3_AUTO_INC, - [NITIO_G0_CMD] = NI660X_G0_CMD, - [NITIO_G1_CMD] = NI660X_G1_CMD, - [NITIO_G2_CMD] = NI660X_G2_CMD, - [NITIO_G3_CMD] = NI660X_G3_CMD, - [NITIO_G0_HW_SAVE] = NI660X_G0_HW_SAVE, - [NITIO_G1_HW_SAVE] = NI660X_G1_HW_SAVE, - [NITIO_G2_HW_SAVE] = NI660X_G2_HW_SAVE, - [NITIO_G3_HW_SAVE] = NI660X_G3_HW_SAVE, - [NITIO_G0_SW_SAVE] = NI660X_G0_SW_SAVE, - [NITIO_G1_SW_SAVE] = NI660X_G1_SW_SAVE, - [NITIO_G2_SW_SAVE] = NI660X_G2_SW_SAVE, - [NITIO_G3_SW_SAVE] = NI660X_G3_SW_SAVE, - [NITIO_G0_MODE] = NI660X_G0_MODE, - [NITIO_G1_MODE] = NI660X_G1_MODE, - [NITIO_G2_MODE] = NI660X_G2_MODE, - [NITIO_G3_MODE] = NI660X_G3_MODE, - [NITIO_G0_LOADA] = NI660X_G0_LOADA, - [NITIO_G1_LOADA] = NI660X_G1_LOADA, - [NITIO_G2_LOADA] = NI660X_G2_LOADA, - [NITIO_G3_LOADA] = NI660X_G3_LOADA, - [NITIO_G0_LOADB] = NI660X_G0_LOADB, - [NITIO_G1_LOADB] = NI660X_G1_LOADB, - [NITIO_G2_LOADB] = NI660X_G2_LOADB, - [NITIO_G3_LOADB] = NI660X_G3_LOADB, - [NITIO_G0_INPUT_SEL] = NI660X_G0_INPUT_SEL, - [NITIO_G1_INPUT_SEL] = NI660X_G1_INPUT_SEL, - [NITIO_G2_INPUT_SEL] = NI660X_G2_INPUT_SEL, - [NITIO_G3_INPUT_SEL] = NI660X_G3_INPUT_SEL, - [NITIO_G0_CNT_MODE] = NI660X_G0_CNT_MODE, - [NITIO_G1_CNT_MODE] = NI660X_G1_CNT_MODE, - [NITIO_G2_CNT_MODE] = NI660X_G2_CNT_MODE, - [NITIO_G3_CNT_MODE] = NI660X_G3_CNT_MODE, - [NITIO_G0_GATE2] = NI660X_G0_GATE2, - [NITIO_G1_GATE2] = NI660X_G1_GATE2, - [NITIO_G2_GATE2] = NI660X_G2_GATE2, - [NITIO_G3_GATE2] = NI660X_G3_GATE2, - [NITIO_G01_STATUS] = NI660X_G01_STATUS, - [NITIO_G23_STATUS] = NI660X_G23_STATUS, - [NITIO_G01_RESET] = NI660X_G01_RESET, - [NITIO_G23_RESET] = NI660X_G23_RESET, - [NITIO_G01_STATUS1] = NI660X_G01_STATUS1, - [NITIO_G23_STATUS1] = NI660X_G23_STATUS1, - [NITIO_G01_STATUS2] = NI660X_G01_STATUS2, - [NITIO_G23_STATUS2] = NI660X_G23_STATUS2, - [NITIO_G0_DMA_CFG] = NI660X_G0_DMA_CFG, - [NITIO_G1_DMA_CFG] = NI660X_G1_DMA_CFG, - [NITIO_G2_DMA_CFG] = NI660X_G2_DMA_CFG, - [NITIO_G3_DMA_CFG] = NI660X_G3_DMA_CFG, - [NITIO_G0_DMA_STATUS] = NI660X_G0_DMA_STATUS, - [NITIO_G1_DMA_STATUS] = NI660X_G1_DMA_STATUS, - [NITIO_G2_DMA_STATUS] = NI660X_G2_DMA_STATUS, - [NITIO_G3_DMA_STATUS] = NI660X_G3_DMA_STATUS, - [NITIO_G0_INT_ACK] = NI660X_G0_INT_ACK, - [NITIO_G1_INT_ACK] = NI660X_G1_INT_ACK, - [NITIO_G2_INT_ACK] = NI660X_G2_INT_ACK, - [NITIO_G3_INT_ACK] = NI660X_G3_INT_ACK, - [NITIO_G0_STATUS] = NI660X_G0_STATUS, - [NITIO_G1_STATUS] = NI660X_G1_STATUS, - [NITIO_G2_STATUS] = NI660X_G2_STATUS, - [NITIO_G3_STATUS] = NI660X_G3_STATUS, - [NITIO_G0_INT_ENA] = NI660X_G0_INT_ENA, - [NITIO_G1_INT_ENA] = NI660X_G1_INT_ENA, - [NITIO_G2_INT_ENA] = NI660X_G2_INT_ENA, - [NITIO_G3_INT_ENA] = NI660X_G3_INT_ENA, -}; - /* Offset of the GPCT chips from the base-address of the card */ /* First chip is at base-address + 0x00, etc. */ static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 }; @@ -409,9 +270,8 @@ struct ni_660x_private { u64 io_dir; }; -static void ni_660x_write(struct comedi_device *dev, - unsigned int chip, unsigned int bits, - enum ni_660x_register reg) +static void ni_660x_write(struct comedi_device *dev, unsigned int chip, + unsigned int bits, unsigned int reg) { unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; @@ -422,8 +282,7 @@ static void ni_660x_write(struct comedi_device *dev, } static unsigned int ni_660x_read(struct comedi_device *dev, - unsigned int chip, - enum ni_660x_register reg) + unsigned int chip, unsigned int reg) { unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; @@ -436,34 +295,16 @@ static void ni_660x_gpct_write(struct ni_gpct *counter, unsigned int bits, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; - enum ni_660x_register ni_660x_register; - - if (reg < ARRAY_SIZE(ni_gpct_to_660x_register)) { - ni_660x_register = ni_gpct_to_660x_register[reg]; - } else { - dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", - __func__, reg); - return; - } - ni_660x_write(dev, counter->chip_index, bits, ni_660x_register); + ni_660x_write(dev, counter->chip_index, bits, reg); } static unsigned int ni_660x_gpct_read(struct ni_gpct *counter, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; - enum ni_660x_register ni_660x_register; - - if (reg < ARRAY_SIZE(ni_gpct_to_660x_register)) { - ni_660x_register = ni_gpct_to_660x_register[reg]; - } else { - dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", - __func__, reg); - return 0; - } - return ni_660x_read(dev, counter->chip_index, ni_660x_register); + return ni_660x_read(dev, counter->chip_index, reg); } static inline void ni_660x_set_dma_channel(struct comedi_device *dev, -- GitLab From 80c67b37fc27a3fc0542916798242e4af8148f28 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:51 -0700 Subject: [PATCH 0511/9938] staging: comedi: ni_660x: remove spinlock 'dma_cfg_lock' This spinlock is only used to protect changes to the private data 'dma_cfg'. Before calling any function that would change the 'dma_cfg' the spinlock 'mite_channel_lock' is also locked. That spinlock is not unlocked until after the 'dma_cfg' change. Remove the redundant spinlock. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 85c793a458f8..3b57ce59273e 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -263,8 +263,6 @@ struct ni_660x_private { spinlock_t mite_channel_lock; /* prevents races between interrupt and comedi_poll */ spinlock_t interrupt_lock; - /* protects dma_cfg changes */ - spinlock_t dma_cfg_lock; unsigned int dma_cfg[NI660X_MAX_CHIPS]; unsigned int io_cfg[NI660X_NUM_PFI_CHANNELS]; u64 io_dir; @@ -313,9 +311,7 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev, { struct ni_660x_private *devpriv = dev->private; unsigned int chip = counter->chip_index; - unsigned long flags; - spin_lock_irqsave(&devpriv->dma_cfg_lock, flags); devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL(mite_channel, counter->counter_index); @@ -323,7 +319,6 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev, NI660X_DMA_CFG_RESET(mite_channel), NI660X_DMA_CFG); mmiowb(); - spin_unlock_irqrestore(&devpriv->dma_cfg_lock, flags); } static inline void ni_660x_unset_dma_channel(struct comedi_device *dev, @@ -332,14 +327,11 @@ static inline void ni_660x_unset_dma_channel(struct comedi_device *dev, { struct ni_660x_private *devpriv = dev->private; unsigned int chip = counter->chip_index; - unsigned long flags; - spin_lock_irqsave(&devpriv->dma_cfg_lock, flags); devpriv->dma_cfg[chip] &= ~NI660X_DMA_CFG_SEL_MASK(mite_channel); devpriv->dma_cfg[chip] |= NI660X_DMA_CFG_SEL_NONE(mite_channel); ni_660x_write(dev, chip, devpriv->dma_cfg[chip], NI660X_DMA_CFG); mmiowb(); - spin_unlock_irqrestore(&devpriv->dma_cfg_lock, flags); } static int ni_660x_request_mite_channel(struct comedi_device *dev, @@ -500,7 +492,6 @@ static int ni_660x_allocate_private(struct comedi_device *dev) spin_lock_init(&devpriv->mite_channel_lock); spin_lock_init(&devpriv->interrupt_lock); - spin_lock_init(&devpriv->dma_cfg_lock); for (i = 0; i < NI660X_NUM_PFI_CHANNELS; ++i) devpriv->io_cfg[i] = NI_660X_PFI_OUTPUT_COUNTER; -- GitLab From 8f266d508c7aa7dad84fbb0d793aa95e8af95169 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:52 -0700 Subject: [PATCH 0512/9938] staging: comedi: ni_660x: refactor GPCT_OFFSET This driver supports boards that have 1 or 2 TIO chips with base addresses 0x800 apart. Replace the static const array 'GPCT_OFFSET' with a define and calculate the base address based on the chip index. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 3b57ce59273e..73ccd62eb450 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -204,9 +204,7 @@ static const struct ni_660x_register_data ni_660x_reg_data[NI660X_NUM_REGS] = { [NI660X_IO_CFG_38_39] = { 0x7a2, 2 } /* read/write */ }; -/* Offset of the GPCT chips from the base-address of the card */ -/* First chip is at base-address + 0x00, etc. */ -static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 }; +#define NI660X_CHIP_OFFSET 0x800 enum ni_660x_boardid { BOARD_PCI6601, @@ -271,7 +269,8 @@ struct ni_660x_private { static void ni_660x_write(struct comedi_device *dev, unsigned int chip, unsigned int bits, unsigned int reg) { - unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; + unsigned int addr = (chip * NI660X_CHIP_OFFSET) + + ni_660x_reg_data[reg].offset; if (ni_660x_reg_data[reg].size == 2) writew(bits, dev->mmio + addr); @@ -282,7 +281,8 @@ static void ni_660x_write(struct comedi_device *dev, unsigned int chip, static unsigned int ni_660x_read(struct comedi_device *dev, unsigned int chip, unsigned int reg) { - unsigned int addr = GPCT_OFFSET[chip] + ni_660x_reg_data[reg].offset; + unsigned int addr = (chip * NI660X_CHIP_OFFSET) + + ni_660x_reg_data[reg].offset; if (ni_660x_reg_data[reg].size == 2) return readw(dev->mmio + addr); -- GitLab From 47470216cc2fe413156aa44d7ae55e65712b0931 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:53 -0700 Subject: [PATCH 0513/9938] staging: comedi: ni_660x: update the MODULE_DESCRIPTION Change the generic MODULE_DESCRIPTION text to something more useful. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_660x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 73ccd62eb450..4345bdcec68e 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -940,5 +940,5 @@ static struct pci_driver ni_660x_pci_driver = { module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for NI 660x counter/timer boards"); MODULE_LICENSE("GPL"); -- GitLab From 581867bd9151ee77fad4b0fe47af96d923ac9ec2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 12:24:29 -0700 Subject: [PATCH 0514/9938] staging: comedi: dt282x: refactor dt282x_ns_to_timer() Define the pacer clock limits and remove the magic numbers. Refactor the code to use a common path to return the actual 'ns' timing and the timer divisor value. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 36 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 06a87a10a2d0..e6958eaf5178 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -113,6 +113,17 @@ #define DT2821_SUPCSR_XCLK BIT(1) #define DT2821_SUPCSR_BDINIT BIT(0) #define DT2821_TMRCTR_REG 0x0e +#define DT2821_TMRCTR_PRESCALE(x) (((x) & 0xf) << 8) +#define DT2821_TMRCTR_DIVIDER(x) ((255 - ((x) & 0xff)) << 0) + +/* Pacer Clock */ +#define DT2821_OSC_BASE 250 /* 4 MHz (in nanoseconds) */ +#define DT2821_PRESCALE(x) BIT(x) +#define DT2821_PRESCALE_MAX 15 +#define DT2821_DIVIDER_MAX 255 +#define DT2821_OSC_MAX (DT2821_OSC_BASE * \ + DT2821_PRESCALE(DT2821_PRESCALE_MAX) * \ + DT2821_DIVIDER_MAX) static const struct comedi_lrange range_dt282x_ai_lo_bipolar = { 4, { @@ -365,10 +376,10 @@ static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) { unsigned int prescale, base, divider; - for (prescale = 0; prescale < 16; prescale++) { - if (prescale == 1) + for (prescale = 0; prescale <= DT2821_PRESCALE_MAX; prescale++) { + if (prescale == 1) /* 0 and 1 are both divide by 1 */ continue; - base = 250 * (1 << prescale); + base = DT2821_OSC_BASE * DT2821_PRESCALE(prescale); switch (flags & CMDF_ROUND_MASK) { case CMDF_ROUND_NEAREST: default: @@ -381,15 +392,17 @@ static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) divider = DIV_ROUND_UP(*ns, base); break; } - if (divider < 256) { - *ns = divider * base; - return (prescale << 8) | (255 - divider); - } + if (divider <= DT2821_DIVIDER_MAX) + break; + } + if (divider > DT2821_DIVIDER_MAX) { + prescale = DT2821_PRESCALE_MAX; + divider = DT2821_DIVIDER_MAX; + base = DT2821_OSC_BASE * DT2821_PRESCALE(prescale); } - base = 250 * (1 << 15); - divider = 255; *ns = divider * base; - return (15 << 8) | (255 - divider); + return DT2821_TMRCTR_PRESCALE(prescale) | + DT2821_TMRCTR_DIVIDER(divider); } static void dt282x_munge(struct comedi_device *dev, @@ -689,8 +702,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 4000); -#define SLOWEST_TIMER (250*(1<<15)*255) - err |= comedi_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER); + err |= comedi_check_trigger_arg_max(&cmd->convert_arg, DT2821_OSC_MAX); err |= comedi_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); -- GitLab From 20ea5c3506abfe46c98dfa47d1bf933e2efa15c9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 12:24:30 -0700 Subject: [PATCH 0515/9938] staging: comedi: dt282x: remove redundant comedi_check_trigger_arg_min() The 'convert_arg' sets the acquisition timing of the analog input command. The maximum speed (the minimum timing) depends on the board 'ai_speed' which if always >= 4000. Remove the redundant 'min' check, Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index e6958eaf5178..661c3ada0712 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -697,11 +697,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, /* Step 3: check if arguments are trivially valid */ err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - - err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 4000); - err |= comedi_check_trigger_arg_max(&cmd->convert_arg, DT2821_OSC_MAX); err |= comedi_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, -- GitLab From f91e45e2acbd300c5042c9ce0133dbc602da9788 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 12:24:31 -0700 Subject: [PATCH 0516/9938] staging: comedi: dt282x: remove unnecessary comment The "Configuration options" are documented in the comedi driver comment block. Remove the redundant comment before the drivers (*attach) function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 661c3ada0712..d5295bbdd28c 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1093,20 +1093,6 @@ static int dt282x_initialize(struct comedi_device *dev) return 0; } -/* - options: - 0 i/o base - 1 irq - 2 dma1 - 3 dma2 - 4 0=single ended, 1=differential - 5 ai 0=straight binary, 1=2's comp - 6 ao0 0=straight binary, 1=2's comp - 7 ao1 0=straight binary, 1=2's comp - 8 ai 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V - 9 ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V - 10 ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V - */ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct dt282x_board *board = dev->board_ptr; -- GitLab From c5f764057f2313673aaf046776e6d573bf2662b6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:21:35 -0700 Subject: [PATCH 0517/9938] staging: comedi: ni_labpc: remove some unnecessary defines The EEPROM_SIZE and NUM_AO_CHAN defines are only used once and they don't add any significant clarity to the driver. They are also pretty generic symbol names. Remove them and just open code the values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.h | 3 --- drivers/staging/comedi/drivers/ni_labpc_common.c | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index 83f878adbd53..74db3ba82ab5 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -19,9 +19,6 @@ #ifndef _NI_LABPC_H #define _NI_LABPC_H -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define NUM_AO_CHAN 2 /* boards have two analog output channels */ - enum transfer_type { fifo_not_empty_transfer, fifo_half_full_transfer, isa_dma_transfer }; diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index 863afb28ee28..55ab05e3196b 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -1261,7 +1261,7 @@ int labpc_common_attach(struct comedi_device *dev, if (board->has_ao) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; - s->n_chan = NUM_AO_CHAN; + s->n_chan = 2; s->maxdata = 0x0fff; s->range_table = &range_labpc_ao; s->insn_write = labpc_ao_insn_write; @@ -1307,12 +1307,12 @@ int labpc_common_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } - /* EEPROM */ + /* EEPROM (256 bytes) */ s = &dev->subdevices[4]; if (board->is_labpc1200) { s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = EEPROM_SIZE; + s->n_chan = 256; s->maxdata = 0xff; s->insn_write = labpc_eeprom_insn_write; -- GitLab From 447785c641cafe586bcb6678e63e436904536432 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:21:36 -0700 Subject: [PATCH 0518/9938] staging: comedi: ni_labpc_regs.h: tidy up bit defines As suggested by checkpatch.pl: CHECK: Prefer using the BIT macro Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../staging/comedi/drivers/ni_labpc_regs.h | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc_regs.h b/drivers/staging/comedi/drivers/ni_labpc_regs.h index 2a274a3e4e73..8c52179e36fc 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_regs.h +++ b/drivers/staging/comedi/drivers/ni_labpc_regs.h @@ -9,32 +9,32 @@ * Register map (all registers are 8-bit) */ #define STAT1_REG 0x00 /* R: Status 1 reg */ -#define STAT1_DAVAIL (1 << 0) -#define STAT1_OVERRUN (1 << 1) -#define STAT1_OVERFLOW (1 << 2) -#define STAT1_CNTINT (1 << 3) -#define STAT1_GATA0 (1 << 5) -#define STAT1_EXTGATA0 (1 << 6) +#define STAT1_DAVAIL BIT(0) +#define STAT1_OVERRUN BIT(1) +#define STAT1_OVERFLOW BIT(2) +#define STAT1_CNTINT BIT(3) +#define STAT1_GATA0 BIT(5) +#define STAT1_EXTGATA0 BIT(6) #define CMD1_REG 0x00 /* W: Command 1 reg */ #define CMD1_MA(x) (((x) & 0x7) << 0) -#define CMD1_TWOSCMP (1 << 3) +#define CMD1_TWOSCMP BIT(3) #define CMD1_GAIN(x) (((x) & 0x7) << 4) -#define CMD1_SCANEN (1 << 7) +#define CMD1_SCANEN BIT(7) #define CMD2_REG 0x01 /* W: Command 2 reg */ -#define CMD2_PRETRIG (1 << 0) -#define CMD2_HWTRIG (1 << 1) -#define CMD2_SWTRIG (1 << 2) -#define CMD2_TBSEL (1 << 3) -#define CMD2_2SDAC0 (1 << 4) -#define CMD2_2SDAC1 (1 << 5) -#define CMD2_LDAC(x) (1 << (6 + (x))) +#define CMD2_PRETRIG BIT(0) +#define CMD2_HWTRIG BIT(1) +#define CMD2_SWTRIG BIT(2) +#define CMD2_TBSEL BIT(3) +#define CMD2_2SDAC0 BIT(4) +#define CMD2_2SDAC1 BIT(5) +#define CMD2_LDAC(x) BIT(6 + ((x) & 0x1)) #define CMD3_REG 0x02 /* W: Command 3 reg */ -#define CMD3_DMAEN (1 << 0) -#define CMD3_DIOINTEN (1 << 1) -#define CMD3_DMATCINTEN (1 << 2) -#define CMD3_CNTINTEN (1 << 3) -#define CMD3_ERRINTEN (1 << 4) -#define CMD3_FIFOINTEN (1 << 5) +#define CMD3_DMAEN BIT(0) +#define CMD3_DIOINTEN BIT(1) +#define CMD3_DMATCINTEN BIT(2) +#define CMD3_CNTINTEN BIT(3) +#define CMD3_ERRINTEN BIT(4) +#define CMD3_FIFOINTEN BIT(5) #define ADC_START_CONVERT_REG 0x03 /* W: Start Convert reg */ #define DAC_LSB_REG(x) (0x04 + 2 * (x)) /* W: DAC0/1 LSB reg */ #define DAC_MSB_REG(x) (0x05 + 2 * (x)) /* W: DAC0/1 MSB reg */ @@ -43,32 +43,32 @@ #define DMATC_CLEAR_REG 0x0a /* W: DMA Interrupt Clear reg */ #define TIMER_CLEAR_REG 0x0c /* W: Timer Interrupt Clear reg */ #define CMD6_REG 0x0e /* W: Command 6 reg */ -#define CMD6_NRSE (1 << 0) -#define CMD6_ADCUNI (1 << 1) -#define CMD6_DACUNI(x) (1 << (2 + (x))) -#define CMD6_HFINTEN (1 << 5) -#define CMD6_DQINTEN (1 << 6) -#define CMD6_SCANUP (1 << 7) +#define CMD6_NRSE BIT(0) +#define CMD6_ADCUNI BIT(1) +#define CMD6_DACUNI(x) BIT(2 + ((x) & 0x1)) +#define CMD6_HFINTEN BIT(5) +#define CMD6_DQINTEN BIT(6) +#define CMD6_SCANUP BIT(7) #define CMD4_REG 0x0f /* W: Command 3 reg */ -#define CMD4_INTSCAN (1 << 0) -#define CMD4_EOIRCV (1 << 1) -#define CMD4_ECLKDRV (1 << 2) -#define CMD4_SEDIFF (1 << 3) -#define CMD4_ECLKRCV (1 << 4) +#define CMD4_INTSCAN BIT(0) +#define CMD4_EOIRCV BIT(1) +#define CMD4_ECLKDRV BIT(2) +#define CMD4_SEDIFF BIT(3) +#define CMD4_ECLKRCV BIT(4) #define DIO_BASE_REG 0x10 /* R/W: 8255 DIO base reg */ #define COUNTER_A_BASE_REG 0x14 /* R/W: 8253 Counter A base reg */ #define COUNTER_B_BASE_REG 0x18 /* R/W: 8253 Counter B base reg */ #define CMD5_REG 0x1c /* W: Command 5 reg */ -#define CMD5_WRTPRT (1 << 2) -#define CMD5_DITHEREN (1 << 3) -#define CMD5_CALDACLD (1 << 4) -#define CMD5_SCLK (1 << 5) -#define CMD5_SDATA (1 << 6) -#define CMD5_EEPROMCS (1 << 7) +#define CMD5_WRTPRT BIT(2) +#define CMD5_DITHEREN BIT(3) +#define CMD5_CALDACLD BIT(4) +#define CMD5_SCLK BIT(5) +#define CMD5_SDATA BIT(6) +#define CMD5_EEPROMCS BIT(7) #define STAT2_REG 0x1d /* R: Status 2 reg */ -#define STAT2_PROMOUT (1 << 0) -#define STAT2_OUTA1 (1 << 1) -#define STAT2_FIFONHF (1 << 2) +#define STAT2_PROMOUT BIT(0) +#define STAT2_OUTA1 BIT(1) +#define STAT2_FIFONHF BIT(2) #define INTERVAL_COUNT_REG 0x1e /* W: Interval Counter Data reg */ #define INTERVAL_STROBE_REG 0x1f /* W: Interval Counter Strobe reg */ -- GitLab From a444abfc668405746767eb53f920531b2d40e8af Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:21:37 -0700 Subject: [PATCH 0519/9938] staging: comedi: ni_labpc_common: tidy up block comments Fix the checkpatch.pl issues: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../staging/comedi/drivers/ni_labpc_common.c | 59 ++++++++++++------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index 55ab05e3196b..b0dfb8eed16d 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -84,8 +84,10 @@ static const struct comedi_lrange range_labpc_ao = { } }; -/* functions that do inb/outb and readb/writeb so we can use - * function pointers to decide which to use */ +/* + * functions that do inb/outb and readb/writeb so we can use + * function pointers to decide which to use + */ static unsigned int labpc_inb(struct comedi_device *dev, unsigned long reg) { return inb(dev->iobase + reg); @@ -656,19 +658,24 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* figure out what method we will use to transfer data */ if (devpriv->dma && - /* dma unsafe at RT priority, - * and too much setup time for CMDF_WAKE_EOS */ - (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY)) == 0) + (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY)) == 0) { + /* + * dma unsafe at RT priority, + * and too much setup time for CMDF_WAKE_EOS + */ xfer = isa_dma_transfer; - else if (/* pc-plus has no fifo-half full interrupt */ - board->is_labpc1200 && - /* wake-end-of-scan should interrupt on fifo not empty */ - (cmd->flags & CMDF_WAKE_EOS) == 0 && - /* make sure we are taking more than just a few points */ - (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) + } else if (board->is_labpc1200 && + (cmd->flags & CMDF_WAKE_EOS) == 0 && + (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) { + /* + * pc-plus has no fifo-half full interrupt + * wake-end-of-scan should interrupt on fifo not empty + * make sure we are taking more than just a few points + */ xfer = fifo_half_full_transfer; - else + } else { xfer = fifo_not_empty_transfer; + } devpriv->current_transfer = xfer; labpc_ai_set_chan_and_gain(dev, mode, chan, range, aref); @@ -679,9 +686,11 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* manual says to set scan enable bit on second pass */ if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) { devpriv->cmd1 |= CMD1_SCANEN; - /* need a brief delay before enabling scan, or scan - * list will get screwed when you switch - * between scan up to scan down mode - dunno why */ + /* + * Need a brief delay before enabling scan, or scan + * list will get screwed when you switch between + * scan up to scan down mode - dunno why. + */ udelay(1); devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG); } @@ -728,8 +737,10 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->cmd4 = 0; if (cmd->convert_src != TRIG_EXT) devpriv->cmd4 |= CMD4_ECLKRCV; - /* XXX should discard first scan when using interval scanning - * since manual says it is not synced with scan clock */ + /* + * XXX should discard first scan when using interval scanning + * since manual says it is not synced with scan clock. + */ if (!labpc_use_continuous_mode(cmd, mode)) { devpriv->cmd4 |= CMD4_INTSCAN; if (cmd->scan_begin_src == TRIG_EXT) @@ -795,8 +806,10 @@ static int labpc_drain_fifo(struct comedi_device *dev) return 0; } -/* makes sure all data acquired by board is transferred to comedi (used - * when acquisition is terminated by stop_src == TRIG_EXT). */ +/* + * Makes sure all data acquired by board is transferred to comedi (used + * when acquisition is terminated by stop_src == TRIG_EXT). + */ static void labpc_drain_dregs(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; @@ -907,9 +920,11 @@ static int labpc_ao_insn_write(struct comedi_device *dev, channel = CR_CHAN(insn->chanspec); - /* turn off pacing of analog output channel */ - /* note: hardware bug in daqcard-1200 means pacing cannot - * be independently enabled/disabled for its the two channels */ + /* + * Turn off pacing of analog output channel. + * NOTE: hardware bug in daqcard-1200 means pacing cannot + * be independently enabled/disabled for its the two channels. + */ spin_lock_irqsave(&dev->spinlock, flags); devpriv->cmd2 &= ~CMD2_LDAC(channel); devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG); -- GitLab From a0b201caebfa863d89f0685127117c6c0dfe8c85 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:21:38 -0700 Subject: [PATCH 0520/9938] staging: comedi: ni_labpc_cs: fix block comment issues Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines WARNING: line over 80 characters Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc_cs.c | 95 +++++++++----------- 1 file changed, 44 insertions(+), 51 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index a1c69ac075d5..3d4d0b9ad4e1 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -1,57 +1,50 @@ /* - comedi/drivers/ni_labpc_cs.c - Driver for National Instruments daqcard-1200 boards - Copyright (C) 2001, 2002, 2003 Frank Mori Hess - - PCMCIA crap is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13 - from the pcmcia package. - The initial developer of the pcmcia dummy_cs.c code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_labpc_cs -Description: National Instruments Lab-PC (& compatibles) -Author: Frank Mori Hess -Devices: [National Instruments] DAQCard-1200 (daqcard-1200) -Status: works - -Thanks go to Fredrik Lingvall for much testing and perseverance in -helping to debug daqcard-1200 support. - -The 1200 series boards have onboard calibration dacs for correcting -analog input/output offsets and gains. The proper settings for these -caldacs are stored on the board's eeprom. To read the caldac values -from the eeprom and store them into a file that can be then be used by -comedilib, use the comedi_calibrate program. - -Configuration options: - none - -The daqcard-1200 has quirky chanlist requirements -when scanning multiple channels. Multiple channel scan -sequence must start at highest channel, then decrement down to -channel 0. Chanlists consisting of all one channel -are also legal, and allow you to pace conversions in bursts. - -*/ + * Driver for National Instruments daqcard-1200 boards + * Copyright (C) 2001, 2002, 2003 Frank Mori Hess + * + * PCMCIA crap is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13 + * from the pcmcia package. + * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * General Public License for more details. + */ /* - -NI manuals: -340988a (daqcard-1200) - -*/ + * Driver: ni_labpc_cs + * Description: National Instruments Lab-PC (& compatibles) + * Author: Frank Mori Hess + * Devices: [National Instruments] DAQCard-1200 (daqcard-1200) + * Status: works + * + * Thanks go to Fredrik Lingvall for much testing and perseverance in + * helping to debug daqcard-1200 support. + * + * The 1200 series boards have onboard calibration dacs for correcting + * analog input/output offsets and gains. The proper settings for these + * caldacs are stored on the board's eeprom. To read the caldac values + * from the eeprom and store them into a file that can be then be used by + * comedilib, use the comedi_calibrate program. + * + * Configuration options: none + * + * The daqcard-1200 has quirky chanlist requirements when scanning multiple + * channels. Multiple channel scan sequence must start at highest channel, + * then decrement down to channel 0. Chanlists consisting of all one channel + * are also legal, and allow you to pace conversions in bursts. + * + * NI manuals: + * 340988a (daqcard-1200) + */ #include -- GitLab From 0edf7b85d31f5255814483dbedd70ed13456e7a5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:21:39 -0700 Subject: [PATCH 0521/9938] staging: comedi: ni_labpc_pci: tidy up bit define As suggested by checkpatch.pl: CHECK: Prefer using the BIT macro Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 77d403801db5..cac089193121 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -51,8 +51,8 @@ static const struct labpc_boardinfo labpc_pci_boards[] = { }; /* ripped from mite.h and mite_setup2() to avoid mite dependency */ -#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ -#define WENAB (1 << 7) /* window enable */ +#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ +#define WENAB BIT(7) /* window enable */ static int labpc_pci_mite_init(struct pci_dev *pcidev) { -- GitLab From 2460e3cd9f5fad5630b3f9ce556bd37b7b5323f0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:21:40 -0700 Subject: [PATCH 0522/9938] staging: comedi: ni_labpc.h: fix block comment issues Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.h | 30 +++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index 74db3ba82ab5..be8d5cd3f7f0 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -1,20 +1,18 @@ /* - ni_labpc.h - - Header for ni_labpc.c and ni_labpc_cs.c - - Copyright (C) 2003 Frank Mori Hess - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Header for ni_labpc ISA/PCMCIA/PCI drivers + * + * Copyright (C) 2003 Frank Mori Hess + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _NI_LABPC_H #define _NI_LABPC_H -- GitLab From bed05b6c3434e62310c2e37ef234f02ce57cf74d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:40 -0700 Subject: [PATCH 0523/9938] staging: comedi: ni_tio: make ni_gpct_device_destroy() NULL pointer safe Modify the pointer check to make this function NULL pointer safe. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index b74e44ec521a..623fc6c7bff0 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1413,7 +1413,7 @@ EXPORT_SYMBOL_GPL(ni_gpct_device_construct); void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) { - if (!counter_dev->counters) + if (!counter_dev) return; kfree(counter_dev->counters); kfree(counter_dev); -- GitLab From 99307a69bf7166325bb8f0b1f1afcb0a0a1aca9a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:10:42 -0700 Subject: [PATCH 0524/9938] staging: comedi: ni_mio_common: ni_gpct_device_destroy() can handle a NULL pointer Remove the unnecessary NULL pointer check. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index dcaf7e89f299..71c8fd2cfff6 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -5675,8 +5675,6 @@ static void mio_common_detach(struct comedi_device *dev) { struct ni_private *devpriv = dev->private; - if (devpriv) { - if (devpriv->counter_dev) - ni_gpct_device_destroy(devpriv->counter_dev); - } + if (devpriv) + ni_gpct_device_destroy(devpriv->counter_dev); } -- GitLab From 1d734e3efabc6a4e6c68b2b21f626af1799124d6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:29:27 -0700 Subject: [PATCH 0525/9938] staging: comedi: z8536: tidy up bit defines Fix the checkpatch.pl issues: CHECK: Prefer using the BIT macro Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/z8536.h | 89 ++++++++++++++------------ 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/z8536.h b/drivers/staging/comedi/drivers/z8536.h index 7be53109cc8d..47eadbf4dcc0 100644 --- a/drivers/staging/comedi/drivers/z8536.h +++ b/drivers/staging/comedi/drivers/z8536.h @@ -24,11 +24,12 @@ #define Z8536_CFG_CTRL_PCE_CT3E BIT(4) /* Port C & C/T 3 Enable */ #define Z8536_CFG_CTRL_PLC BIT(3) /* Port A/B Link Control */ #define Z8536_CFG_CTRL_PAE BIT(2) /* Port A Enable */ -#define Z8536_CFG_CTRL_LC_INDEP (0 << 0)/* C/Ts Independent */ -#define Z8536_CFG_CTRL_LC_GATE (1 << 0)/* C/T 1 Out Gates C/T 2 */ -#define Z8536_CFG_CTRL_LC_TRIG (2 << 0)/* C/T 1 Out Triggers C/T 2 */ -#define Z8536_CFG_CTRL_LC_CLK (3 << 0)/* C/T 1 Out Clocks C/T 2 */ -#define Z8536_CFG_CTRL_LC_MASK (3 << 0)/* C/T Link Control mask */ +#define Z8536_CFG_CTRL_LC(x) (((x) & 0x3) << 0) /* Link Control */ +#define Z8536_CFG_CTRL_LC_INDEP Z8536_CFG_CTRL_LC(0)/* Independent */ +#define Z8536_CFG_CTRL_LC_GATE Z8536_CFG_CTRL_LC(1)/* 1 Gates 2 */ +#define Z8536_CFG_CTRL_LC_TRIG Z8536_CFG_CTRL_LC(2)/* 1 Triggers 2 */ +#define Z8536_CFG_CTRL_LC_CLK Z8536_CFG_CTRL_LC(3)/* 1 Clocks 2 */ +#define Z8536_CFG_CTRL_LC_MASK Z8536_CFG_CTRL_LC(3) /* Interrupt Vector registers */ #define Z8536_PA_INT_VECT_REG 0x02 @@ -43,15 +44,16 @@ #define Z8536_CT2_CMDSTAT_REG 0x0b #define Z8536_CT3_CMDSTAT_REG 0x0c #define Z8536_CT_CMDSTAT_REG(x) (0x0a + (x)) -#define Z8536_CMD_NULL (0 << 5)/* Null Code */ -#define Z8536_CMD_CLR_IP_IUS (1 << 5)/* Clear IP & IUS */ -#define Z8536_CMD_SET_IUS (2 << 5)/* Set IUS */ -#define Z8536_CMD_CLR_IUS (3 << 5)/* Clear IUS */ -#define Z8536_CMD_SET_IP (4 << 5)/* Set IP */ -#define Z8536_CMD_CLR_IP (5 << 5)/* Clear IP */ -#define Z8536_CMD_SET_IE (6 << 5)/* Set IE */ -#define Z8536_CMD_CLR_IE (7 << 5)/* Clear IE */ -#define Z8536_CMD_MASK (7 << 5) +#define Z8536_CMD(x) (((x) & 0x7) << 5) +#define Z8536_CMD_NULL Z8536_CMD(0) /* Null Code */ +#define Z8536_CMD_CLR_IP_IUS Z8536_CMD(1) /* Clear IP & IUS */ +#define Z8536_CMD_SET_IUS Z8536_CMD(2) /* Set IUS */ +#define Z8536_CMD_CLR_IUS Z8536_CMD(3) /* Clear IUS */ +#define Z8536_CMD_SET_IP Z8536_CMD(4) /* Set IP */ +#define Z8536_CMD_CLR_IP Z8536_CMD(5) /* Clear IP */ +#define Z8536_CMD_SET_IE Z8536_CMD(6) /* Set IE */ +#define Z8536_CMD_CLR_IE Z8536_CMD(7) /* Clear IE */ +#define Z8536_CMD_MASK Z8536_CMD(7) #define Z8536_STAT_IUS BIT(7) /* Interrupt Under Service */ #define Z8536_STAT_IE BIT(6) /* Interrupt Enable */ @@ -105,46 +107,51 @@ #define Z8536_CT_MODE_ETE BIT(4) /* External Trigger Enable */ #define Z8536_CT_MODE_EGE BIT(3) /* External Gate Enable */ #define Z8536_CT_MODE_REB BIT(2) /* Retrigger Enable Bit */ -#define Z8536_CT_MODE_DCS_PULSE (0 << 0)/* Duty Cycle - Pulse */ -#define Z8536_CT_MODE_DCS_ONESHOT (1 << 0)/* Duty Cycle - One-Shot */ -#define Z8536_CT_MODE_DCS_SQRWAVE (2 << 0)/* Duty Cycle - Square Wave */ -#define Z8536_CT_MODE_DCS_DO_NOT_USE (3 << 0)/* Duty Cycle - Do Not Use */ -#define Z8536_CT_MODE_DCS_MASK (3 << 0)/* Duty Cycle mask */ +#define Z8536_CT_MODE_DCS(x) (((x) & 0x3) << 0) /* Duty Cycle */ +#define Z8536_CT_MODE_DCS_PULSE Z8536_CT_MODE_DCS(0) /* Pulse */ +#define Z8536_CT_MODE_DCS_ONESHOT Z8536_CT_MODE_DCS(1) /* One-Shot */ +#define Z8536_CT_MODE_DCS_SQRWAVE Z8536_CT_MODE_DCS(2) /* Square Wave */ +#define Z8536_CT_MODE_DCS_DO_NOT_USE Z8536_CT_MODE_DCS(3) /* Do Not Use */ +#define Z8536_CT_MODE_DCS_MASK Z8536_CT_MODE_DCS(3) /* Port A/B Mode Specification registers */ #define Z8536_PA_MODE_REG 0x20 #define Z8536_PB_MODE_REG 0x28 -#define Z8536_PAB_MODE_PTS_BIT (0 << 6)/* Bit Port */ -#define Z8536_PAB_MODE_PTS_INPUT (1 << 6)/* Input Port */ -#define Z8536_PAB_MODE_PTS_OUTPUT (2 << 6)/* Output Port */ -#define Z8536_PAB_MODE_PTS_BIDIR (3 << 6)/* Bidirectional Port */ -#define Z8536_PAB_MODE_PTS_MASK (3 << 6)/* Port Type Select mask */ +#define Z8536_PAB_MODE_PTS(x) (((x) & 0x3) << 6) /* Port type */ +#define Z8536_PAB_MODE_PTS_BIT Z8536_PAB_MODE_PTS(0 << 6)/* Bit */ +#define Z8536_PAB_MODE_PTS_INPUT Z8536_PAB_MODE_PTS(1 << 6)/* Input */ +#define Z8536_PAB_MODE_PTS_OUTPUT Z8536_PAB_MODE_PTS(2 << 6)/* Output */ +#define Z8536_PAB_MODE_PTS_BIDIR Z8536_PAB_MODE_PTS(3 << 6)/* Bidir */ +#define Z8536_PAB_MODE_PTS_MASK Z8536_PAB_MODE_PTS(3 << 6) #define Z8536_PAB_MODE_ITB BIT(5) /* Interrupt on Two Bytes */ #define Z8536_PAB_MODE_SB BIT(4) /* Single Buffered mode */ #define Z8536_PAB_MODE_IMO BIT(3) /* Interrupt on Match Only */ -#define Z8536_PAB_MODE_PMS_DISABLE (0 << 1)/* Disable Pattern Match */ -#define Z8536_PAB_MODE_PMS_AND (1 << 1)/* "AND" mode */ -#define Z8536_PAB_MODE_PMS_OR (2 << 1)/* "OR" mode */ -#define Z8536_PAB_MODE_PMS_OR_PEV (3 << 1)/* "OR-Priority" mode */ -#define Z8536_PAB_MODE_PMS_MASK (3 << 1)/* Pattern Mode mask */ +#define Z8536_PAB_MODE_PMS(x) (((x) & 0x3) << 1) /* Pattern Mode */ +#define Z8536_PAB_MODE_PMS_DISABLE Z8536_PAB_MODE_PMS(0)/* Disabled */ +#define Z8536_PAB_MODE_PMS_AND Z8536_PAB_MODE_PMS(1)/* "AND" */ +#define Z8536_PAB_MODE_PMS_OR Z8536_PAB_MODE_PMS(2)/* "OR" */ +#define Z8536_PAB_MODE_PMS_OR_PEV Z8536_PAB_MODE_PMS(3)/* "OR-Priority" */ +#define Z8536_PAB_MODE_PMS_MASK Z8536_PAB_MODE_PMS(3) #define Z8536_PAB_MODE_LPM BIT(0) /* Latch on Pattern Match */ #define Z8536_PAB_MODE_DTE BIT(0) /* Deskew Timer Enabled */ /* Port A/B Handshake Specification registers */ #define Z8536_PA_HANDSHAKE_REG 0x21 #define Z8536_PB_HANDSHAKE_REG 0x29 -#define Z8536_PAB_HANDSHAKE_HST_INTER (0 << 6)/* Interlocked Handshake */ -#define Z8536_PAB_HANDSHAKE_HST_STROBED (1 << 6)/* Strobed Handshake */ -#define Z8536_PAB_HANDSHAKE_HST_PULSED (2 << 6)/* Pulsed Handshake */ -#define Z8536_PAB_HANDSHAKE_HST_3WIRE (3 << 6)/* Three-Wire Handshake */ -#define Z8536_PAB_HANDSHAKE_HST_MASK (3 << 6)/* Handshake Type mask */ -#define Z8536_PAB_HANDSHAKE_RWS_DISABLE (0 << 3)/* Req/Wait Disabled */ -#define Z8536_PAB_HANDSHAKE_RWS_OUTWAIT (1 << 3)/* Output Wait */ -#define Z8536_PAB_HANDSHAKE_RWS_INWAIT (3 << 3)/* Input Wait */ -#define Z8536_PAB_HANDSHAKE_RWS_SPREQ (4 << 3)/* Special Request */ -#define Z8536_PAB_HANDSHAKE_RWS_OUTREQ (5 << 4)/* Output Request */ -#define Z8536_PAB_HANDSHAKE_RWS_INREQ (7 << 3)/* Input Request */ -#define Z8536_PAB_HANDSHAKE_RWS_MASK (7 << 3)/* Req/Wait mask */ +#define Z8536_PAB_HANDSHAKE_HST(x) (((x) & 0x3) << 6) /* Handshake Type */ +#define Z8536_PAB_HANDSHAKE_HST_INTER Z8536_PAB_HANDSHAKE_HST(0)/*Interlock*/ +#define Z8536_PAB_HANDSHAKE_HST_STROBED Z8536_PAB_HANDSHAKE_HST(1)/* Strobed */ +#define Z8536_PAB_HANDSHAKE_HST_PULSED Z8536_PAB_HANDSHAKE_HST(2)/* Pulsed */ +#define Z8536_PAB_HANDSHAKE_HST_3WIRE Z8536_PAB_HANDSHAKE_HST(3)/* 3-Wire */ +#define Z8536_PAB_HANDSHAKE_HST_MASK Z8536_PAB_HANDSHAKE_HST(3) +#define Z8536_PAB_HANDSHAKE_RWS(x) (((x) & 0x7) << 3) /* Req/Wait */ +#define Z8536_PAB_HANDSHAKE_RWS_DISABLE Z8536_PAB_HANDSHAKE_RWS(0)/* Disabled */ +#define Z8536_PAB_HANDSHAKE_RWS_OUTWAIT Z8536_PAB_HANDSHAKE_RWS(1)/* Out Wait */ +#define Z8536_PAB_HANDSHAKE_RWS_INWAIT Z8536_PAB_HANDSHAKE_RWS(3)/* In Wait */ +#define Z8536_PAB_HANDSHAKE_RWS_SPREQ Z8536_PAB_HANDSHAKE_RWS(4)/* Special */ +#define Z8536_PAB_HANDSHAKE_RWS_OUTREQ Z8536_PAB_HANDSHAKE_RWS(5)/* Out Req */ +#define Z8536_PAB_HANDSHAKE_RWS_INREQ Z8536_PAB_HANDSHAKE_RWS(7)/* In Req */ +#define Z8536_PAB_HANDSHAKE_RWS_MASK Z8536_PAB_HANDSHAKE_RWS(7) #define Z8536_PAB_HANDSHAKE_DESKEW(x) ((x) << 0)/* Deskew Time */ #define Z8536_PAB_HANDSHAKE_DESKEW_MASK (3 << 0)/* Deskew Time mask */ -- GitLab From 5c0d139243c32ebfe1f4aabd3d2a9817e23e07a5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:51:54 -0700 Subject: [PATCH 0526/9938] staging: comedi: plx9052.h: tidy up bit defines Fix the checkpatch.pl issues: CHECK: Prefer using the BIT macro Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/plx9052.h | 87 ++++++++++++------------ 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h index fbcf25069807..131ebffa9376 100644 --- a/drivers/staging/comedi/drivers/plx9052.h +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -25,55 +25,56 @@ * INTCSR - Interrupt Control/Status register */ #define PLX9052_INTCSR 0x4c -#define PLX9052_INTCSR_LI1ENAB (1 << 0) /* LI1 enabled */ -#define PLX9052_INTCSR_LI1POL (1 << 1) /* LI1 active high */ -#define PLX9052_INTCSR_LI1STAT (1 << 2) /* LI1 active */ -#define PLX9052_INTCSR_LI2ENAB (1 << 3) /* LI2 enabled */ -#define PLX9052_INTCSR_LI2POL (1 << 4) /* LI2 active high */ -#define PLX9052_INTCSR_LI2STAT (1 << 5) /* LI2 active */ -#define PLX9052_INTCSR_PCIENAB (1 << 6) /* PCIINT enabled */ -#define PLX9052_INTCSR_SOFTINT (1 << 7) /* generate soft int */ -#define PLX9052_INTCSR_LI1SEL (1 << 8) /* LI1 edge */ -#define PLX9052_INTCSR_LI2SEL (1 << 9) /* LI2 edge */ -#define PLX9052_INTCSR_LI1CLRINT (1 << 10) /* LI1 clear int */ -#define PLX9052_INTCSR_LI2CLRINT (1 << 11) /* LI2 clear int */ -#define PLX9052_INTCSR_ISAMODE (1 << 12) /* ISA interface mode */ +#define PLX9052_INTCSR_LI1ENAB BIT(0) /* LI1 enabled */ +#define PLX9052_INTCSR_LI1POL BIT(1) /* LI1 active high */ +#define PLX9052_INTCSR_LI1STAT BIT(2) /* LI1 active */ +#define PLX9052_INTCSR_LI2ENAB BIT(3) /* LI2 enabled */ +#define PLX9052_INTCSR_LI2POL BIT(4) /* LI2 active high */ +#define PLX9052_INTCSR_LI2STAT BIT(5) /* LI2 active */ +#define PLX9052_INTCSR_PCIENAB BIT(6) /* PCIINT enabled */ +#define PLX9052_INTCSR_SOFTINT BIT(7) /* generate soft int */ +#define PLX9052_INTCSR_LI1SEL BIT(8) /* LI1 edge */ +#define PLX9052_INTCSR_LI2SEL BIT(9) /* LI2 edge */ +#define PLX9052_INTCSR_LI1CLRINT BIT(10) /* LI1 clear int */ +#define PLX9052_INTCSR_LI2CLRINT BIT(11) /* LI2 clear int */ +#define PLX9052_INTCSR_ISAMODE BIT(12) /* ISA interface mode */ /* * CNTRL - User I/O, Direct Slave Response, Serial EEPROM, and * Initialization Control register */ #define PLX9052_CNTRL 0x50 -#define PLX9052_CNTRL_WAITO (1 << 0) /* UIO0 or WAITO# select */ -#define PLX9052_CNTRL_UIO0_DIR (1 << 1) /* UIO0 direction */ -#define PLX9052_CNTRL_UIO0_DATA (1 << 2) /* UIO0 data */ -#define PLX9052_CNTRL_LLOCKO (1 << 3) /* UIO1 or LLOCKo# select */ -#define PLX9052_CNTRL_UIO1_DIR (1 << 4) /* UIO1 direction */ -#define PLX9052_CNTRL_UIO1_DATA (1 << 5) /* UIO1 data */ -#define PLX9052_CNTRL_CS2 (1 << 6) /* UIO2 or CS2# select */ -#define PLX9052_CNTRL_UIO2_DIR (1 << 7) /* UIO2 direction */ -#define PLX9052_CNTRL_UIO2_DATA (1 << 8) /* UIO2 data */ -#define PLX9052_CNTRL_CS3 (1 << 9) /* UIO3 or CS3# select */ -#define PLX9052_CNTRL_UIO3_DIR (1 << 10) /* UIO3 direction */ -#define PLX9052_CNTRL_UIO3_DATA (1 << 11) /* UIO3 data */ -#define PLX9052_CNTRL_PCIBAR01 (0 << 12) /* bar 0 (mem) and 1 (I/O) */ -#define PLX9052_CNTRL_PCIBAR0 (1 << 12) /* bar 0 (mem) only */ -#define PLX9052_CNTRL_PCIBAR1 (2 << 12) /* bar 1 (I/O) only */ -#define PLX9052_CNTRL_PCI2_1_FEATURES (1 << 14) /* PCI r2.1 features enabled */ -#define PLX9052_CNTRL_PCI_R_W_FLUSH (1 << 15) /* read w/write flush mode */ -#define PLX9052_CNTRL_PCI_R_NO_FLUSH (1 << 16) /* read no flush mode */ -#define PLX9052_CNTRL_PCI_R_NO_WRITE (1 << 17) /* read no write mode */ -#define PLX9052_CNTRL_PCI_W_RELEASE (1 << 18) /* write release bus mode */ -#define PLX9052_CNTRL_RETRY_CLKS(x) (((x) & 0xf) << 19) /* slave retry clks */ -#define PLX9052_CNTRL_LOCK_ENAB (1 << 23) /* slave LOCK# enable */ +#define PLX9052_CNTRL_WAITO BIT(0) /* UIO0 or WAITO# select */ +#define PLX9052_CNTRL_UIO0_DIR BIT(1) /* UIO0 direction */ +#define PLX9052_CNTRL_UIO0_DATA BIT(2) /* UIO0 data */ +#define PLX9052_CNTRL_LLOCKO BIT(3) /* UIO1 or LLOCKo# select */ +#define PLX9052_CNTRL_UIO1_DIR BIT(4) /* UIO1 direction */ +#define PLX9052_CNTRL_UIO1_DATA BIT(5) /* UIO1 data */ +#define PLX9052_CNTRL_CS2 BIT(6) /* UIO2 or CS2# select */ +#define PLX9052_CNTRL_UIO2_DIR BIT(7) /* UIO2 direction */ +#define PLX9052_CNTRL_UIO2_DATA BIT(8) /* UIO2 data */ +#define PLX9052_CNTRL_CS3 BIT(9) /* UIO3 or CS3# select */ +#define PLX9052_CNTRL_UIO3_DIR BIT(10) /* UIO3 direction */ +#define PLX9052_CNTRL_UIO3_DATA BIT(11) /* UIO3 data */ +#define PLX9052_CNTRL_PCIBAR(x) (((x) & 0x3) << 12) +#define PLX9052_CNTRL_PCIBAR01 PLX9052_CNTRL_PCIBAR(0) /* mem and IO */ +#define PLX9052_CNTRL_PCIBAR0 PLX9052_CNTRL_PCIBAR(1) /* mem only */ +#define PLX9052_CNTRL_PCIBAR1 PLX9052_CNTRL_PCIBAR(2) /* IO only */ +#define PLX9052_CNTRL_PCI2_1_FEATURES BIT(14) /* PCI v2.1 features enabled */ +#define PLX9052_CNTRL_PCI_R_W_FLUSH BIT(15) /* read w/write flush mode */ +#define PLX9052_CNTRL_PCI_R_NO_FLUSH BIT(16) /* read no flush mode */ +#define PLX9052_CNTRL_PCI_R_NO_WRITE BIT(17) /* read no write mode */ +#define PLX9052_CNTRL_PCI_W_RELEASE BIT(18) /* write release bus mode */ +#define PLX9052_CNTRL_RETRY_CLKS(x) (((x) & 0xf) << 19) /* retry clks */ +#define PLX9052_CNTRL_LOCK_ENAB BIT(23) /* slave LOCK# enable */ #define PLX9052_CNTRL_EEPROM_MASK (0x1f << 24) /* EEPROM bits */ -#define PLX9052_CNTRL_EEPROM_CLK (1 << 24) /* EEPROM clock */ -#define PLX9052_CNTRL_EEPROM_CS (1 << 25) /* EEPROM chip select */ -#define PLX9052_CNTRL_EEPROM_DOUT (1 << 26) /* EEPROM write bit */ -#define PLX9052_CNTRL_EEPROM_DIN (1 << 27) /* EEPROM read bit */ -#define PLX9052_CNTRL_EEPROM_PRESENT (1 << 28) /* EEPROM present */ -#define PLX9052_CNTRL_RELOAD_CFG (1 << 29) /* reload configuration */ -#define PLX9052_CNTRL_PCI_RESET (1 << 30) /* PCI adapter reset */ -#define PLX9052_CNTRL_MASK_REV (1 << 31) /* mask revision */ +#define PLX9052_CNTRL_EEPROM_CLK BIT(24) /* EEPROM clock */ +#define PLX9052_CNTRL_EEPROM_CS BIT(25) /* EEPROM chip select */ +#define PLX9052_CNTRL_EEPROM_DOUT BIT(26) /* EEPROM write bit */ +#define PLX9052_CNTRL_EEPROM_DIN BIT(27) /* EEPROM read bit */ +#define PLX9052_CNTRL_EEPROM_PRESENT BIT(28) /* EEPROM present */ +#define PLX9052_CNTRL_RELOAD_CFG BIT(29) /* reload configuration */ +#define PLX9052_CNTRL_PCI_RESET BIT(30) /* PCI adapter reset */ +#define PLX9052_CNTRL_MASK_REV BIT(31) /* mask revision */ #endif /* _PLX9052_H_ */ -- GitLab From 2892b3fa16d8950b2385ad8fcd7ca84fa54aefaf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 22 Mar 2016 11:51:55 -0700 Subject: [PATCH 0527/9938] staging: comedi: plx9052.h: fix block comment issues Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/plx9052.h | 35 ++++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h index 131ebffa9376..2892e6528967 100644 --- a/drivers/staging/comedi/drivers/plx9052.h +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -1,22 +1,21 @@ /* - comedi/drivers/plx9052.h - Definitions for the PLX-9052 PCI interface chip - - Copyright (C) 2002 MEV Ltd. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Definitions for the PLX-9052 PCI interface chip + * + * Copyright (C) 2002 MEV Ltd. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _PLX9052_H_ #define _PLX9052_H_ -- GitLab From 12fc6688ea34bd8b378e105da46ca016177f7c84 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:37 -0700 Subject: [PATCH 0528/9938] staging: comedi: ni_tio_internal.h: tidy up bit defines Fix the checkpatch.pl issues: CHECK: Prefer using the BIT macro Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../staging/comedi/drivers/ni_tio_internal.h | 199 +++++++++--------- 1 file changed, 102 insertions(+), 97 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 2bceae493e23..c51e01eb3de0 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -24,68 +24,73 @@ #define NITIO_AUTO_INC_REG(x) (NITIO_G0_AUTO_INC + (x)) #define GI_AUTO_INC_MASK 0xff #define NITIO_CMD_REG(x) (NITIO_G0_CMD + (x)) -#define GI_ARM (1 << 0) -#define GI_SAVE_TRACE (1 << 1) -#define GI_LOAD (1 << 2) -#define GI_DISARM (1 << 4) +#define GI_ARM BIT(0) +#define GI_SAVE_TRACE BIT(1) +#define GI_LOAD BIT(2) +#define GI_DISARM BIT(4) #define GI_CNT_DIR(x) (((x) & 0x3) << 5) -#define GI_CNT_DIR_MASK (3 << 5) -#define GI_WRITE_SWITCH (1 << 7) -#define GI_SYNC_GATE (1 << 8) -#define GI_LITTLE_BIG_ENDIAN (1 << 9) -#define GI_BANK_SWITCH_START (1 << 10) -#define GI_BANK_SWITCH_MODE (1 << 11) -#define GI_BANK_SWITCH_ENABLE (1 << 12) -#define GI_ARM_COPY (1 << 13) -#define GI_SAVE_TRACE_COPY (1 << 14) -#define GI_DISARM_COPY (1 << 15) +#define GI_CNT_DIR_MASK GI_CNT_DIR(3) +#define GI_WRITE_SWITCH BIT(7) +#define GI_SYNC_GATE BIT(8) +#define GI_LITTLE_BIG_ENDIAN BIT(9) +#define GI_BANK_SWITCH_START BIT(10) +#define GI_BANK_SWITCH_MODE BIT(11) +#define GI_BANK_SWITCH_ENABLE BIT(12) +#define GI_ARM_COPY BIT(13) +#define GI_SAVE_TRACE_COPY BIT(14) +#define GI_DISARM_COPY BIT(15) #define NITIO_HW_SAVE_REG(x) (NITIO_G0_HW_SAVE + (x)) #define NITIO_SW_SAVE_REG(x) (NITIO_G0_SW_SAVE + (x)) #define NITIO_MODE_REG(x) (NITIO_G0_MODE + (x)) -#define GI_GATING_DISABLED (0 << 0) -#define GI_LEVEL_GATING (1 << 0) -#define GI_RISING_EDGE_GATING (2 << 0) -#define GI_FALLING_EDGE_GATING (3 << 0) -#define GI_GATING_MODE_MASK (3 << 0) -#define GI_GATE_ON_BOTH_EDGES (1 << 2) -#define GI_EDGE_GATE_STARTS_STOPS (0 << 3) -#define GI_EDGE_GATE_STOPS_STARTS (1 << 3) -#define GI_EDGE_GATE_STARTS (2 << 3) -#define GI_EDGE_GATE_NO_STARTS_OR_STOPS (3 << 3) -#define GI_EDGE_GATE_MODE_MASK (3 << 3) -#define GI_STOP_ON_GATE (0 << 5) -#define GI_STOP_ON_GATE_OR_TC (1 << 5) -#define GI_STOP_ON_GATE_OR_SECOND_TC (2 << 5) -#define GI_STOP_MODE_MASK (3 << 5) -#define GI_LOAD_SRC_SEL (1 << 7) -#define GI_OUTPUT_TC_PULSE (1 << 8) -#define GI_OUTPUT_TC_TOGGLE (2 << 8) -#define GI_OUTPUT_TC_OR_GATE_TOGGLE (3 << 8) -#define GI_OUTPUT_MODE_MASK (3 << 8) -#define GI_NO_HARDWARE_DISARM (0 << 10) -#define GI_DISARM_AT_TC (1 << 10) -#define GI_DISARM_AT_GATE (2 << 10) -#define GI_DISARM_AT_TC_OR_GATE (3 << 10) -#define GI_COUNTING_ONCE_MASK (3 << 10) -#define GI_LOADING_ON_TC (1 << 12) -#define GI_GATE_POL_INVERT (1 << 13) -#define GI_LOADING_ON_GATE (1 << 14) -#define GI_RELOAD_SRC_SWITCHING (1 << 15) +#define GI_GATING_MODE(x) (((x) & 0x3) << 0) +#define GI_GATING_DISABLED GI_GATING_MODE(0) +#define GI_LEVEL_GATING GI_GATING_MODE(1) +#define GI_RISING_EDGE_GATING GI_GATING_MODE(2) +#define GI_FALLING_EDGE_GATING GI_GATING_MODE(3) +#define GI_GATING_MODE_MASK GI_GATING_MODE(3) +#define GI_GATE_ON_BOTH_EDGES BIT(2) +#define GI_EDGE_GATE_MODE(x) (((x) & 0x3) << 3) +#define GI_EDGE_GATE_STARTS_STOPS GI_EDGE_GATE_MODE(0) +#define GI_EDGE_GATE_STOPS_STARTS GI_EDGE_GATE_MODE(1) +#define GI_EDGE_GATE_STARTS GI_EDGE_GATE_MODE(2) +#define GI_EDGE_GATE_NO_STARTS_OR_STOPS GI_EDGE_GATE_MODE(3) +#define GI_EDGE_GATE_MODE_MASK GI_EDGE_GATE_MODE(3) +#define GI_STOP_MODE(x) (((x) & 0x3) << 5) +#define GI_STOP_ON_GATE GI_STOP_MODE(0) +#define GI_STOP_ON_GATE_OR_TC GI_STOP_MODE(1) +#define GI_STOP_ON_GATE_OR_SECOND_TC GI_STOP_MODE(2) +#define GI_STOP_MODE_MASK GI_STOP_MODE(3) +#define GI_LOAD_SRC_SEL BIT(7) +#define GI_OUTPUT_MODE(x) (((x) & 0x3) << 8) +#define GI_OUTPUT_TC_PULSE GI_OUTPUT_MODE(1) +#define GI_OUTPUT_TC_TOGGLE GI_OUTPUT_MODE(2) +#define GI_OUTPUT_TC_OR_GATE_TOGGLE GI_OUTPUT_MODE(3) +#define GI_OUTPUT_MODE_MASK GI_OUTPUT_MODE(3) +#define GI_COUNTING_ONCE(x) (((x) & 0x3) << 10) +#define GI_NO_HARDWARE_DISARM GI_COUNTING_ONCE(0) +#define GI_DISARM_AT_TC GI_COUNTING_ONCE(1) +#define GI_DISARM_AT_GATE GI_COUNTING_ONCE(2) +#define GI_DISARM_AT_TC_OR_GATE GI_COUNTING_ONCE(3) +#define GI_COUNTING_ONCE_MASK GI_COUNTING_ONCE(3) +#define GI_LOADING_ON_TC BIT(12) +#define GI_GATE_POL_INVERT BIT(13) +#define GI_LOADING_ON_GATE BIT(14) +#define GI_RELOAD_SRC_SWITCHING BIT(15) #define NITIO_LOADA_REG(x) (NITIO_G0_LOADA + (x)) #define NITIO_LOADB_REG(x) (NITIO_G0_LOADB + (x)) #define NITIO_INPUT_SEL_REG(x) (NITIO_G0_INPUT_SEL + (x)) -#define GI_READ_ACKS_IRQ (1 << 0) -#define GI_WRITE_ACKS_IRQ (1 << 1) +#define GI_READ_ACKS_IRQ BIT(0) +#define GI_WRITE_ACKS_IRQ BIT(1) #define GI_BITS_TO_SRC(x) (((x) >> 2) & 0x1f) #define GI_SRC_SEL(x) (((x) & 0x1f) << 2) -#define GI_SRC_SEL_MASK (0x1f << 2) +#define GI_SRC_SEL_MASK GI_SRC_SEL(0x1f) #define GI_BITS_TO_GATE(x) (((x) >> 7) & 0x1f) #define GI_GATE_SEL(x) (((x) & 0x1f) << 7) -#define GI_GATE_SEL_MASK (0x1f << 7) -#define GI_GATE_SEL_LOAD_SRC (1 << 12) -#define GI_OR_GATE (1 << 13) -#define GI_OUTPUT_POL_INVERT (1 << 14) -#define GI_SRC_POL_INVERT (1 << 15) +#define GI_GATE_SEL_MASK GI_GATE_SEL(0x1f) +#define GI_GATE_SEL_LOAD_SRC BIT(12) +#define GI_OR_GATE BIT(13) +#define GI_OUTPUT_POL_INVERT BIT(14) +#define GI_SRC_POL_INVERT BIT(15) #define NITIO_CNT_MODE_REG(x) (NITIO_G0_CNT_MODE + (x)) #define GI_CNT_MODE(x) (((x) & 0x7) << 0) #define GI_CNT_MODE_NORMAL GI_CNT_MODE(0) @@ -94,67 +99,67 @@ #define GI_CNT_MODE_QUADX4 GI_CNT_MODE(3) #define GI_CNT_MODE_TWO_PULSE GI_CNT_MODE(4) #define GI_CNT_MODE_SYNC_SRC GI_CNT_MODE(6) -#define GI_CNT_MODE_MASK (7 << 0) -#define GI_INDEX_MODE (1 << 4) +#define GI_CNT_MODE_MASK GI_CNT_MODE(7) +#define GI_INDEX_MODE BIT(4) #define GI_INDEX_PHASE(x) (((x) & 0x3) << 5) -#define GI_INDEX_PHASE_MASK (3 << 5) -#define GI_HW_ARM_ENA (1 << 7) +#define GI_INDEX_PHASE_MASK GI_INDEX_PHASE(3) +#define GI_HW_ARM_ENA BIT(7) #define GI_HW_ARM_SEL(x) ((x) << 8) -#define GI_660X_HW_ARM_SEL_MASK (0x7 << 8) -#define GI_M_HW_ARM_SEL_MASK (0x1f << 8) -#define GI_660X_PRESCALE_X8 (1 << 12) -#define GI_M_PRESCALE_X8 (1 << 13) -#define GI_660X_ALT_SYNC (1 << 13) -#define GI_M_ALT_SYNC (1 << 14) -#define GI_660X_PRESCALE_X2 (1 << 14) -#define GI_M_PRESCALE_X2 (1 << 15) +#define GI_660X_HW_ARM_SEL_MASK GI_HW_ARM_SEL(0x7) +#define GI_M_HW_ARM_SEL_MASK GI_HW_ARM_SEL(0x1f) +#define GI_660X_PRESCALE_X8 BIT(12) +#define GI_M_PRESCALE_X8 BIT(13) +#define GI_660X_ALT_SYNC BIT(13) +#define GI_M_ALT_SYNC BIT(14) +#define GI_660X_PRESCALE_X2 BIT(14) +#define GI_M_PRESCALE_X2 BIT(15) #define NITIO_GATE2_REG(x) (NITIO_G0_GATE2 + (x)) -#define GI_GATE2_MODE (1 << 0) +#define GI_GATE2_MODE BIT(0) #define GI_BITS_TO_GATE2(x) (((x) >> 7) & 0x1f) #define GI_GATE2_SEL(x) (((x) & 0x1f) << 7) -#define GI_GATE2_SEL_MASK (0x1f << 7) -#define GI_GATE2_POL_INVERT (1 << 13) -#define GI_GATE2_SUBSEL (1 << 14) -#define GI_SRC_SUBSEL (1 << 15) +#define GI_GATE2_SEL_MASK GI_GATE2_SEL(0x1f) +#define GI_GATE2_POL_INVERT BIT(13) +#define GI_GATE2_SUBSEL BIT(14) +#define GI_SRC_SUBSEL BIT(15) #define NITIO_SHARED_STATUS_REG(x) (NITIO_G01_STATUS + ((x) / 2)) -#define GI_SAVE(x) (((x) % 2) ? (1 << 1) : (1 << 0)) -#define GI_COUNTING(x) (((x) % 2) ? (1 << 3) : (1 << 2)) -#define GI_NEXT_LOAD_SRC(x) (((x) % 2) ? (1 << 5) : (1 << 4)) -#define GI_STALE_DATA(x) (((x) % 2) ? (1 << 7) : (1 << 6)) -#define GI_ARMED(x) (((x) % 2) ? (1 << 9) : (1 << 8)) -#define GI_NO_LOAD_BETWEEN_GATES(x) (((x) % 2) ? (1 << 11) : (1 << 10)) -#define GI_TC_ERROR(x) (((x) % 2) ? (1 << 13) : (1 << 12)) -#define GI_GATE_ERROR(x) (((x) % 2) ? (1 << 15) : (1 << 14)) +#define GI_SAVE(x) (((x) % 2) ? BIT(1) : BIT(0)) +#define GI_COUNTING(x) (((x) % 2) ? BIT(3) : BIT(2)) +#define GI_NEXT_LOAD_SRC(x) (((x) % 2) ? BIT(5) : BIT(4)) +#define GI_STALE_DATA(x) (((x) % 2) ? BIT(7) : BIT(6)) +#define GI_ARMED(x) (((x) % 2) ? BIT(9) : BIT(8)) +#define GI_NO_LOAD_BETWEEN_GATES(x) (((x) % 2) ? BIT(11) : BIT(10)) +#define GI_TC_ERROR(x) (((x) % 2) ? BIT(13) : BIT(12)) +#define GI_GATE_ERROR(x) (((x) % 2) ? BIT(15) : BIT(14)) #define NITIO_RESET_REG(x) (NITIO_G01_RESET + ((x) / 2)) -#define GI_RESET(x) (1 << (2 + ((x) % 2))) +#define GI_RESET(x) BIT(2 + ((x) % 2)) #define NITIO_STATUS1_REG(x) (NITIO_G01_STATUS1 + ((x) / 2)) #define NITIO_STATUS2_REG(x) (NITIO_G01_STATUS2 + ((x) / 2)) -#define GI_OUTPUT(x) (((x) % 2) ? (1 << 1) : (1 << 0)) -#define GI_HW_SAVE(x) (((x) % 2) ? (1 << 13) : (1 << 12)) -#define GI_PERMANENT_STALE(x) (((x) % 2) ? (1 << 15) : (1 << 14)) +#define GI_OUTPUT(x) (((x) % 2) ? BIT(1) : BIT(0)) +#define GI_HW_SAVE(x) (((x) % 2) ? BIT(13) : BIT(12)) +#define GI_PERMANENT_STALE(x) (((x) % 2) ? BIT(15) : BIT(14)) #define NITIO_DMA_CFG_REG(x) (NITIO_G0_DMA_CFG + (x)) -#define GI_DMA_ENABLE (1 << 0) -#define GI_DMA_WRITE (1 << 1) -#define GI_DMA_INT_ENA (1 << 2) -#define GI_DMA_RESET (1 << 3) -#define GI_DMA_BANKSW_ERROR (1 << 4) +#define GI_DMA_ENABLE BIT(0) +#define GI_DMA_WRITE BIT(1) +#define GI_DMA_INT_ENA BIT(2) +#define GI_DMA_RESET BIT(3) +#define GI_DMA_BANKSW_ERROR BIT(4) #define NITIO_DMA_STATUS_REG(x) (NITIO_G0_DMA_STATUS + (x)) -#define GI_DMA_READBANK (1 << 13) -#define GI_DRQ_ERROR (1 << 14) -#define GI_DRQ_STATUS (1 << 15) +#define GI_DMA_READBANK BIT(13) +#define GI_DRQ_ERROR BIT(14) +#define GI_DRQ_STATUS BIT(15) #define NITIO_ABZ_REG(x) (NITIO_G0_ABZ + (x)) #define NITIO_INT_ACK_REG(x) (NITIO_G0_INT_ACK + (x)) -#define GI_GATE_ERROR_CONFIRM(x) (((x) % 2) ? (1 << 1) : (1 << 5)) -#define GI_TC_ERROR_CONFIRM(x) (((x) % 2) ? (1 << 2) : (1 << 6)) -#define GI_TC_INTERRUPT_ACK (1 << 14) -#define GI_GATE_INTERRUPT_ACK (1 << 15) +#define GI_GATE_ERROR_CONFIRM(x) (((x) % 2) ? BIT(1) : BIT(5)) +#define GI_TC_ERROR_CONFIRM(x) (((x) % 2) ? BIT(2) : BIT(6)) +#define GI_TC_INTERRUPT_ACK BIT(14) +#define GI_GATE_INTERRUPT_ACK BIT(15) #define NITIO_STATUS_REG(x) (NITIO_G0_STATUS + (x)) -#define GI_GATE_INTERRUPT (1 << 2) -#define GI_TC (1 << 3) -#define GI_INTERRUPT (1 << 15) +#define GI_GATE_INTERRUPT BIT(2) +#define GI_TC BIT(3) +#define GI_INTERRUPT BIT(15) #define NITIO_INT_ENA_REG(x) (NITIO_G0_INT_ENA + (x)) -#define GI_TC_INTERRUPT_ENABLE(x) (((x) % 2) ? (1 << 9) : (1 << 6)) -#define GI_GATE_INTERRUPT_ENABLE(x) (((x) % 2) ? (1 << 10) : (1 << 8)) +#define GI_TC_INTERRUPT_ENABLE(x) (((x) % 2) ? BIT(9) : BIT(6)) +#define GI_GATE_INTERRUPT_ENABLE(x) (((x) % 2) ? BIT(10) : BIT(8)) static inline void write_register(struct ni_gpct *counter, unsigned bits, enum ni_gpct_register reg) -- GitLab From f79f218ec2aa2ac761e426f54419f8d27aa46d53 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:38 -0700 Subject: [PATCH 0529/9938] staging: comedi: ni_tio_internal.h: fix block comment issues Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../staging/comedi/drivers/ni_tio_internal.h | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index c51e01eb3de0..b659f058c8dc 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -1,20 +1,19 @@ /* - drivers/ni_tio_internal.h - Header file for NI general purpose counter support code (ni_tio.c and - ni_tiocmd.c) - - COMEDI - Linux Control and Measurement Device Interface - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Header file for NI general purpose counter support code (ni_tio.c and + * ni_tiocmd.c) + * + * COMEDI - Linux Control and Measurement Device Interface + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _COMEDI_NI_TIO_INTERNAL_H #define _COMEDI_NI_TIO_INTERNAL_H @@ -212,7 +211,8 @@ static inline void ni_tio_set_bits_transient(struct ni_gpct *counter, spin_unlock_irqrestore(&counter_dev->regs_lock, flags); } -/* ni_tio_set_bits( ) is for safely writing to registers whose bits may be +/* + * ni_tio_set_bits( ) is for safely writing to registers whose bits may be * twiddled in interrupt context, or whose software copy may be read in * interrupt context. */ @@ -224,10 +224,11 @@ static inline void ni_tio_set_bits(struct ni_gpct *counter, 0x0); } -/* ni_tio_get_soft_copy( ) is for safely reading the software copy of a register -whose bits might be modified in interrupt context, or whose software copy -might need to be read in interrupt context. -*/ +/* + * ni_tio_get_soft_copy( ) is for safely reading the software copy of a + * register whose bits might be modified in interrupt context, or whose + * software copy might need to be read in interrupt context. + */ static inline unsigned ni_tio_get_soft_copy(const struct ni_gpct *counter, enum ni_gpct_register register_index) -- GitLab From a4915d543f5bbb775a5fa6d012d33606ba22389b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:39 -0700 Subject: [PATCH 0530/9938] staging: comedi: ni_tio: fix ni_tio_set_gate_src() params/vars As suggested by checkpatch.pl: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 28 +++++++++---------- .../staging/comedi/drivers/ni_tio_internal.h | 3 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 623fc6c7bff0..abbc8b7a7092 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -891,16 +891,16 @@ static int ni_m_set_gate2(struct ni_gpct *counter, unsigned int gate_source) return 0; } -int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, - unsigned int gate_source) +int ni_tio_set_gate_src(struct ni_gpct *counter, + unsigned int gate, unsigned int src) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - unsigned int chan = CR_CHAN(gate_source); - unsigned gate2_reg = NITIO_GATE2_REG(cidx); - unsigned mode = 0; + unsigned int cidx = counter->counter_index; + unsigned int chan = CR_CHAN(src); + unsigned int gate2_reg = NITIO_GATE2_REG(cidx); + unsigned int mode = 0; - switch (gate_index) { + switch (gate) { case 0: if (chan == NI_GPCT_DISABLED_GATE_SELECT) { ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), @@ -908,9 +908,9 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, GI_GATING_DISABLED); return 0; } - if (gate_source & CR_INVERT) + if (src & CR_INVERT) mode |= GI_GATE_POL_INVERT; - if (gate_source & CR_EDGE) + if (src & CR_EDGE) mode |= GI_RISING_EDGE_GATING; else mode |= GI_LEVEL_GATING; @@ -921,9 +921,9 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: default: - return ni_m_set_gate(counter, gate_source); + return ni_m_set_gate(counter, src); case ni_gpct_variant_660x: - return ni_660x_set_gate(counter, gate_source); + return ni_660x_set_gate(counter, src); } break; case 1: @@ -936,15 +936,15 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, gate2_reg); return 0; } - if (gate_source & CR_INVERT) + if (src & CR_INVERT) counter_dev->regs[gate2_reg] |= GI_GATE2_POL_INVERT; else counter_dev->regs[gate2_reg] &= ~GI_GATE2_POL_INVERT; switch (counter_dev->variant) { case ni_gpct_variant_m_series: - return ni_m_set_gate2(counter, gate_source); + return ni_m_set_gate2(counter, src); case ni_gpct_variant_660x: - return ni_660x_set_gate2(counter, gate_source); + return ni_660x_set_gate2(counter, src); default: BUG(); break; diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index b659f058c8dc..ee02b36aa51d 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -245,7 +245,6 @@ static inline unsigned ni_tio_get_soft_copy(const struct ni_gpct *counter, } int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger); -int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, - unsigned int gate_source); +int ni_tio_set_gate_src(struct ni_gpct *, unsigned int gate, unsigned int src); #endif /* _COMEDI_NI_TIO_INTERNAL_H */ -- GitLab From c9813d50a514b451c4ad3acf1f5a400fff005c70 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:40 -0700 Subject: [PATCH 0531/9938] staging: comedi: ni_tio: fix ni_tio_arm() params/vars As suggested by checkpatch.pl: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' The 'arm' parameter is really a true/false flag. For aesthetics, change it to a bool. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 14 +++++++------- drivers/staging/comedi/drivers/ni_tio_internal.h | 2 +- drivers/staging/comedi/drivers/ni_tiocmd.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index abbc8b7a7092..35596b1a075c 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -484,11 +484,11 @@ static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) return 0; } -int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) +int ni_tio_arm(struct ni_gpct *counter, bool arm, unsigned int start_trigger) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - unsigned command_transient_bits = 0; + unsigned int cidx = counter->counter_index; + unsigned int command_transient_bits = 0; if (arm) { switch (start_trigger) { @@ -502,8 +502,8 @@ int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) break; } if (ni_tio_counting_mode_registers_present(counter_dev)) { - unsigned bits = 0; - unsigned sel_mask; + unsigned int bits = 0; + unsigned int sel_mask; sel_mask = GI_HW_ARM_SEL_MASK(counter_dev->variant); @@ -1180,9 +1180,9 @@ int ni_tio_insn_config(struct comedi_device *dev, case INSN_CONFIG_SET_COUNTER_MODE: return ni_tio_set_counter_mode(counter, data[1]); case INSN_CONFIG_ARM: - return ni_tio_arm(counter, 1, data[1]); + return ni_tio_arm(counter, true, data[1]); case INSN_CONFIG_DISARM: - ni_tio_arm(counter, 0, 0); + ni_tio_arm(counter, false, 0); return 0; case INSN_CONFIG_GET_COUNTER_STATUS: data[1] = 0; diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index ee02b36aa51d..1e9163304692 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -244,7 +244,7 @@ static inline unsigned ni_tio_get_soft_copy(const struct ni_gpct *counter, return value; } -int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger); +int ni_tio_arm(struct ni_gpct *, bool arm, unsigned int start_trigger); int ni_tio_set_gate_src(struct ni_gpct *, unsigned int gate, unsigned int src); #endif /* _COMEDI_NI_TIO_INTERNAL_H */ diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 823e47910004..0546a55b7277 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -103,7 +103,7 @@ static int ni_tio_input_inttrig(struct comedi_device *dev, spin_unlock_irqrestore(&counter->lock, flags); if (ret < 0) return ret; - ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); + ret = ni_tio_arm(counter, true, NI_GPCT_ARM_IMMEDIATE); s->async->inttrig = NULL; return ret; @@ -143,9 +143,9 @@ static int ni_tio_input_cmd(struct comedi_subdevice *s) mite_dma_arm(counter->mite_chan); if (cmd->start_src == TRIG_NOW) - ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); + ret = ni_tio_arm(counter, true, NI_GPCT_ARM_IMMEDIATE); else if (cmd->start_src == TRIG_EXT) - ret = ni_tio_arm(counter, 1, cmd->start_arg); + ret = ni_tio_arm(counter, true, cmd->start_arg); } return ret; } @@ -292,7 +292,7 @@ int ni_tio_cancel(struct ni_gpct *counter) unsigned cidx = counter->counter_index; unsigned long flags; - ni_tio_arm(counter, 0, 0); + ni_tio_arm(counter, false, 0); spin_lock_irqsave(&counter->lock, flags); if (counter->mite_chan) mite_dma_disarm(counter->mite_chan); -- GitLab From 85bfafa81f8e422503d31d48ae2658675aad1929 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:41 -0700 Subject: [PATCH 0532/9938] staging: comedi: ni_tio: export and fix ni_tio_get_soft_copy() Move the inline function from the header and export it instead. For the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' CHECK: Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON() The 'unsigned' vars can safely be changed to 'unsigned int'. The BUG_ON() is overkill. All the drivers that call this function pass 'register_index' values that are valid. Just check the 'register_index' and return 0 if it's not valid. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 25 +++++++++++++++++++ .../staging/comedi/drivers/ni_tio_internal.h | 21 ++-------------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 35596b1a075c..abbdad59552a 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -228,6 +228,31 @@ static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, return clock_period_ps; } +/** + * ni_tio_get_soft_copy() - Safely read the software copy of a counter register. + * @counter: struct ni_gpct counter. + * @reg: the register to read. + * + * Used to get the software copy of a register whose bits might be modified + * in interrupt context, or whose software copy might need to be read in + * interrupt context. + */ +unsigned int ni_tio_get_soft_copy(const struct ni_gpct *counter, + enum ni_gpct_register reg) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned int value = 0; + unsigned long flags; + + if (reg < NITIO_NUM_REGS) { + spin_lock_irqsave(&counter_dev->regs_lock, flags); + value = counter_dev->regs[reg]; + spin_unlock_irqrestore(&counter_dev->regs_lock, flags); + } + return value; +} +EXPORT_SYMBOL_GPL(ni_tio_get_soft_copy); + static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) { struct ni_gpct_device *counter_dev = counter->counter_dev; diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 1e9163304692..8c9027690c36 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -224,25 +224,8 @@ static inline void ni_tio_set_bits(struct ni_gpct *counter, 0x0); } -/* - * ni_tio_get_soft_copy( ) is for safely reading the software copy of a - * register whose bits might be modified in interrupt context, or whose - * software copy might need to be read in interrupt context. - */ -static inline unsigned ni_tio_get_soft_copy(const struct ni_gpct *counter, - enum ni_gpct_register - register_index) -{ - struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned long flags; - unsigned value; - - BUG_ON(register_index >= NITIO_NUM_REGS); - spin_lock_irqsave(&counter_dev->regs_lock, flags); - value = counter_dev->regs[register_index]; - spin_unlock_irqrestore(&counter_dev->regs_lock, flags); - return value; -} +unsigned int ni_tio_get_soft_copy(const struct ni_gpct *, + enum ni_gpct_register reg); int ni_tio_arm(struct ni_gpct *, bool arm, unsigned int start_trigger); int ni_tio_set_gate_src(struct ni_gpct *, unsigned int gate, unsigned int src); -- GitLab From f4e0331f3050f051ad0e8818635fc157cf354713 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:42 -0700 Subject: [PATCH 0533/9938] staging: comedi: ni_tio: export and fix ni_tio_set_bits() Move the inline function from the header and export it instead. Fix the checkpatch.pl issue: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' The 'unsigned' vars can safely be changed to 'unsigned int'. This allows moving ni_tio_set_bits_transient() into the driver and making it static. Fix the checkpatch.pl issue: CHECK: Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON() The BUG_ON() is overkill. All the drivers that call this function pass 'register_index' values that are valid. Just check the 'register_index' before updating the software copy and writing the register. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 37 +++++++++++++++++++ .../staging/comedi/drivers/ni_tio_internal.h | 35 +----------------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index abbdad59552a..5343fce88ebf 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -228,6 +228,43 @@ static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, return clock_period_ps; } +static void ni_tio_set_bits_transient(struct ni_gpct *counter, + enum ni_gpct_register reg, + unsigned int mask, unsigned int value, + unsigned int transient) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned long flags; + + if (reg < NITIO_NUM_REGS) { + spin_lock_irqsave(&counter_dev->regs_lock, flags); + counter_dev->regs[reg] &= ~mask; + counter_dev->regs[reg] |= (value & mask); + write_register(counter, counter_dev->regs[reg] | transient, + reg); + mmiowb(); + spin_unlock_irqrestore(&counter_dev->regs_lock, flags); + } +} + +/** + * ni_tio_set_bits() - Safely write a counter register. + * @counter: struct ni_gpct counter. + * @reg: the register to write. + * @mask: the bits to change. + * @value: the new bits value. + * + * Used to write to, and update the software copy, a register whose bits may + * be twiddled in interrupt context, or whose software copy may be read in + * interrupt context. + */ +void ni_tio_set_bits(struct ni_gpct *counter, enum ni_gpct_register reg, + unsigned int mask, unsigned int value) +{ + ni_tio_set_bits_transient(counter, reg, mask, value, 0x0); +} +EXPORT_SYMBOL_GPL(ni_tio_set_bits); + /** * ni_tio_get_soft_copy() - Safely read the software copy of a counter register. * @counter: struct ni_gpct counter. diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 8c9027690c36..c8ad66a9237f 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -191,39 +191,8 @@ static inline int ni_tio_counting_mode_registers_present(const struct return 0; } -static inline void ni_tio_set_bits_transient(struct ni_gpct *counter, - enum ni_gpct_register - register_index, unsigned bit_mask, - unsigned bit_values, - unsigned transient_bit_values) -{ - struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned long flags; - - BUG_ON(register_index >= NITIO_NUM_REGS); - spin_lock_irqsave(&counter_dev->regs_lock, flags); - counter_dev->regs[register_index] &= ~bit_mask; - counter_dev->regs[register_index] |= (bit_values & bit_mask); - write_register(counter, - counter_dev->regs[register_index] | transient_bit_values, - register_index); - mmiowb(); - spin_unlock_irqrestore(&counter_dev->regs_lock, flags); -} - -/* - * ni_tio_set_bits( ) is for safely writing to registers whose bits may be - * twiddled in interrupt context, or whose software copy may be read in - * interrupt context. - */ -static inline void ni_tio_set_bits(struct ni_gpct *counter, - enum ni_gpct_register register_index, - unsigned bit_mask, unsigned bit_values) -{ - ni_tio_set_bits_transient(counter, register_index, bit_mask, bit_values, - 0x0); -} - +void ni_tio_set_bits(struct ni_gpct *, enum ni_gpct_register reg, + unsigned int mask, unsigned int value); unsigned int ni_tio_get_soft_copy(const struct ni_gpct *, enum ni_gpct_register reg); -- GitLab From 73b2d13607f075ff27abbf75d57320a8b9f82461 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:43 -0700 Subject: [PATCH 0534/9938] staging: comedi: ni_tio_internal: simplify ni_tio_counting_mode_registers_present() Only the e series gpct variant does not have counting mode registers. Simplfy this function. For aesthetics, return bool instead of int. This fixes the checkpatch.pl issues: CHECK: spaces preferred around that '*' (ctx:ExV) CHECK: Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON() Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 2 +- .../staging/comedi/drivers/ni_tio_internal.h | 18 ++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 5343fce88ebf..44dea4c4da20 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -451,7 +451,7 @@ static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) unsigned mode; uint64_t clock_period_ps; - if (ni_tio_counting_mode_registers_present(counter_dev) == 0) + if (!ni_tio_counting_mode_registers_present(counter_dev)) return; mode = ni_tio_get_soft_copy(counter, counting_mode_reg); diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index c8ad66a9237f..1e795fd6f288 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -174,21 +174,11 @@ static inline unsigned read_register(struct ni_gpct *counter, return counter->counter_dev->read_register(counter, reg); } -static inline int ni_tio_counting_mode_registers_present(const struct - ni_gpct_device - *counter_dev) +static inline bool +ni_tio_counting_mode_registers_present(const struct ni_gpct_device *counter_dev) { - switch (counter_dev->variant) { - case ni_gpct_variant_e_series: - return 0; - case ni_gpct_variant_m_series: - case ni_gpct_variant_660x: - return 1; - default: - BUG(); - break; - } - return 0; + /* m series and 660x variants have counting mode registers */ + return counter_dev->variant != ni_gpct_variant_e_series; } void ni_tio_set_bits(struct ni_gpct *, enum ni_gpct_register reg, -- GitLab From 51f2e4eb2882209c84c2546b5a9b5c638b850f95 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:44 -0700 Subject: [PATCH 0535/9938] staging: comedi: ni_tio_internal: export {read, write)_register() Move these inline functions out of the header and export them instead. These functions have pretty generic names, rename them. Fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' CHECK: Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON() Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 72 +++++++++++++------ .../staging/comedi/drivers/ni_tio_internal.h | 15 +--- drivers/staging/comedi/drivers/ni_tiocmd.c | 10 +-- 3 files changed, 56 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 44dea4c4da20..a225279cb83f 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -179,11 +179,38 @@ static bool ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev) } } +/** + * ni_tio_write() - Write a TIO register using the driver provided callback. + * @counter: struct ni_gpct counter. + * @value: the value to write + * @reg: the register to write. + */ +void ni_tio_write(struct ni_gpct *counter, unsigned int value, + enum ni_gpct_register reg) +{ + if (reg < NITIO_NUM_REGS) + counter->counter_dev->write_register(counter, value, reg); +} +EXPORT_SYMBOL_GPL(ni_tio_write); + +/** + * ni_tio_read() - Read a TIO register using the driver provided callback. + * @counter: struct ni_gpct counter. + * @reg: the register to read. + */ +unsigned int ni_tio_read(struct ni_gpct *counter, enum ni_gpct_register reg) +{ + if (reg < NITIO_NUM_REGS) + return counter->counter_dev->read_register(counter, reg); + return 0; +} +EXPORT_SYMBOL_GPL(ni_tio_read); + static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) { unsigned cidx = counter->counter_index; - write_register(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx)); + ni_tio_write(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx)); } static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, @@ -240,8 +267,7 @@ static void ni_tio_set_bits_transient(struct ni_gpct *counter, spin_lock_irqsave(&counter_dev->regs_lock, flags); counter_dev->regs[reg] &= ~mask; counter_dev->regs[reg] |= (value & mask); - write_register(counter, counter_dev->regs[reg] | transient, - reg); + ni_tio_write(counter, counter_dev->regs[reg] | transient, reg); mmiowb(); spin_unlock_irqrestore(&counter_dev->regs_lock, flags); } @@ -736,8 +762,8 @@ static void ni_tio_set_source_subselect(struct ni_gpct *counter, default: return; } - write_register(counter, counter_dev->regs[second_gate_reg], - second_gate_reg); + ni_tio_write(counter, counter_dev->regs[second_gate_reg], + second_gate_reg); } static int ni_tio_set_clock_src(struct ni_gpct *counter, @@ -925,7 +951,7 @@ static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source) counter_dev->regs[gate2_reg] |= GI_GATE2_MODE; counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK; counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel); - write_register(counter, counter_dev->regs[gate2_reg], gate2_reg); + ni_tio_write(counter, counter_dev->regs[gate2_reg], gate2_reg); return 0; } @@ -949,7 +975,7 @@ static int ni_m_set_gate2(struct ni_gpct *counter, unsigned int gate_source) counter_dev->regs[gate2_reg] |= GI_GATE2_MODE; counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK; counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel); - write_register(counter, counter_dev->regs[gate2_reg], gate2_reg); + ni_tio_write(counter, counter_dev->regs[gate2_reg], gate2_reg); return 0; } @@ -994,8 +1020,8 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, if (chan == NI_GPCT_DISABLED_GATE_SELECT) { counter_dev->regs[gate2_reg] &= ~GI_GATE2_MODE; - write_register(counter, counter_dev->regs[gate2_reg], - gate2_reg); + ni_tio_write(counter, counter_dev->regs[gate2_reg], + gate2_reg); return 0; } if (src & CR_INVERT) @@ -1049,7 +1075,7 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, counter_dev->regs[abz_reg] &= ~mask; counter_dev->regs[abz_reg] |= (source << shift) & mask; - write_register(counter, counter_dev->regs[abz_reg], abz_reg); + ni_tio_write(counter, counter_dev->regs[abz_reg], abz_reg); return 0; } @@ -1248,7 +1274,7 @@ int ni_tio_insn_config(struct comedi_device *dev, return 0; case INSN_CONFIG_GET_COUNTER_STATUS: data[1] = 0; - status = read_register(counter, NITIO_SHARED_STATUS_REG(cidx)); + status = ni_tio_read(counter, NITIO_SHARED_STATUS_REG(cidx)); if (status & GI_ARMED(cidx)) { data[1] |= COMEDI_COUNTER_ARMED; if (status & GI_COUNTING(cidx)) @@ -1297,9 +1323,9 @@ static unsigned int ni_tio_read_sw_save_reg(struct comedi_device *dev, * will be correct since the count value will definitely have latched * by then. */ - val = read_register(counter, NITIO_SW_SAVE_REG(cidx)); - if (val != read_register(counter, NITIO_SW_SAVE_REG(cidx))) - val = read_register(counter, NITIO_SW_SAVE_REG(cidx)); + val = ni_tio_read(counter, NITIO_SW_SAVE_REG(cidx)); + if (val != ni_tio_read(counter, NITIO_SW_SAVE_REG(cidx))) + val = ni_tio_read(counter, NITIO_SW_SAVE_REG(cidx)); return val; } @@ -1336,7 +1362,7 @@ static unsigned ni_tio_next_load_register(struct ni_gpct *counter) { unsigned cidx = counter->counter_index; const unsigned bits = - read_register(counter, NITIO_SHARED_STATUS_REG(cidx)); + ni_tio_read(counter, NITIO_SHARED_STATUS_REG(cidx)); return (bits & GI_NEXT_LOAD_SRC(cidx)) ? NITIO_LOADB_REG(cidx) @@ -1368,19 +1394,19 @@ int ni_tio_insn_write(struct comedi_device *dev, * load register is already selected. */ load_reg = ni_tio_next_load_register(counter); - write_register(counter, data[0], load_reg); + ni_tio_write(counter, data[0], load_reg); ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx), 0, 0, GI_LOAD); /* restore load reg */ - write_register(counter, counter_dev->regs[load_reg], load_reg); + ni_tio_write(counter, counter_dev->regs[load_reg], load_reg); break; case 1: counter_dev->regs[NITIO_LOADA_REG(cidx)] = data[0]; - write_register(counter, data[0], NITIO_LOADA_REG(cidx)); + ni_tio_write(counter, data[0], NITIO_LOADA_REG(cidx)); break; case 2: counter_dev->regs[NITIO_LOADB_REG(cidx)] = data[0]; - write_register(counter, data[0], NITIO_LOADB_REG(cidx)); + ni_tio_write(counter, data[0], NITIO_LOADB_REG(cidx)); break; default: return -EINVAL; @@ -1398,7 +1424,7 @@ void ni_tio_init_counter(struct ni_gpct *counter) /* initialize counter registers */ counter_dev->regs[NITIO_AUTO_INC_REG(cidx)] = 0x0; - write_register(counter, 0x0, NITIO_AUTO_INC_REG(cidx)); + ni_tio_write(counter, 0x0, NITIO_AUTO_INC_REG(cidx)); ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), ~0, GI_SYNC_GATE); @@ -1406,10 +1432,10 @@ void ni_tio_init_counter(struct ni_gpct *counter) ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), ~0, 0); counter_dev->regs[NITIO_LOADA_REG(cidx)] = 0x0; - write_register(counter, 0x0, NITIO_LOADA_REG(cidx)); + ni_tio_write(counter, 0x0, NITIO_LOADA_REG(cidx)); counter_dev->regs[NITIO_LOADB_REG(cidx)] = 0x0; - write_register(counter, 0x0, NITIO_LOADB_REG(cidx)); + ni_tio_write(counter, 0x0, NITIO_LOADB_REG(cidx)); ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), ~0, 0); @@ -1418,7 +1444,7 @@ void ni_tio_init_counter(struct ni_gpct *counter) if (ni_tio_has_gate2_registers(counter_dev)) { counter_dev->regs[NITIO_GATE2_REG(cidx)] = 0x0; - write_register(counter, 0x0, NITIO_GATE2_REG(cidx)); + ni_tio_write(counter, 0x0, NITIO_GATE2_REG(cidx)); } ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), ~0, 0x0); diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 1e795fd6f288..b15b10833c42 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -160,19 +160,8 @@ #define GI_TC_INTERRUPT_ENABLE(x) (((x) % 2) ? BIT(9) : BIT(6)) #define GI_GATE_INTERRUPT_ENABLE(x) (((x) % 2) ? BIT(10) : BIT(8)) -static inline void write_register(struct ni_gpct *counter, unsigned bits, - enum ni_gpct_register reg) -{ - BUG_ON(reg >= NITIO_NUM_REGS); - counter->counter_dev->write_register(counter, bits, reg); -} - -static inline unsigned read_register(struct ni_gpct *counter, - enum ni_gpct_register reg) -{ - BUG_ON(reg >= NITIO_NUM_REGS); - return counter->counter_dev->read_register(counter, reg); -} +void ni_tio_write(struct ni_gpct *, unsigned int value, enum ni_gpct_register); +unsigned int ni_tio_read(struct ni_gpct *, enum ni_gpct_register); static inline bool ni_tio_counting_mode_registers_present(const struct ni_gpct_device *counter_dev) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 0546a55b7277..d5ffbb135844 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -342,9 +342,9 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *stale_data) { unsigned cidx = counter->counter_index; - const unsigned short gxx_status = read_register(counter, + const unsigned short gxx_status = ni_tio_read(counter, NITIO_SHARED_STATUS_REG(cidx)); - const unsigned short gi_status = read_register(counter, + const unsigned short gi_status = ni_tio_read(counter, NITIO_STATUS_REG(cidx)); unsigned ack = 0; @@ -380,14 +380,14 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, ack |= GI_GATE_INTERRUPT_ACK; } if (ack) - write_register(counter, ack, NITIO_INT_ACK_REG(cidx)); + ni_tio_write(counter, ack, NITIO_INT_ACK_REG(cidx)); if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) & GI_LOADING_ON_GATE) { if (gxx_status & GI_STALE_DATA(cidx)) { if (stale_data) *stale_data = 1; } - if (read_register(counter, NITIO_STATUS2_REG(cidx)) & + if (ni_tio_read(counter, NITIO_STATUS2_REG(cidx)) & GI_PERMANENT_STALE(cidx)) { dev_info(counter->counter_dev->dev->class_dev, "%s: Gi_Permanent_Stale_Data detected.\n", @@ -426,7 +426,7 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter, switch (counter->counter_dev->variant) { case ni_gpct_variant_m_series: case ni_gpct_variant_660x: - if (read_register(counter, NITIO_DMA_STATUS_REG(cidx)) & + if (ni_tio_read(counter, NITIO_DMA_STATUS_REG(cidx)) & GI_DRQ_ERROR) { dev_notice(counter->counter_dev->dev->class_dev, "%s: Gi_DRQ_Error detected.\n", __func__); -- GitLab From 5994e51b20600accd55e9aaeeb0b78e5ca038e19 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:45 -0700 Subject: [PATCH 0536/9938] staging: comedi: ni_tio: tidy up struct ni_gpct_device (*{write, read}_register) For aesthetics, rename these callbacks to simply read/write. Change the 'unsigned' parameters to 'unsigned int'. This fixes a number of checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 22 +++++++++++----------- drivers/staging/comedi/drivers/ni_tio.h | 19 +++++++++---------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index a225279cb83f..28bec3cfeef5 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -189,7 +189,7 @@ void ni_tio_write(struct ni_gpct *counter, unsigned int value, enum ni_gpct_register reg) { if (reg < NITIO_NUM_REGS) - counter->counter_dev->write_register(counter, value, reg); + counter->counter_dev->write(counter, value, reg); } EXPORT_SYMBOL_GPL(ni_tio_write); @@ -201,7 +201,7 @@ EXPORT_SYMBOL_GPL(ni_tio_write); unsigned int ni_tio_read(struct ni_gpct *counter, enum ni_gpct_register reg) { if (reg < NITIO_NUM_REGS) - return counter->counter_dev->read_register(counter, reg); + return counter->counter_dev->read(counter, reg); return 0; } EXPORT_SYMBOL_GPL(ni_tio_read); @@ -1455,17 +1455,17 @@ EXPORT_SYMBOL_GPL(ni_tio_init_counter); struct ni_gpct_device * ni_gpct_device_construct(struct comedi_device *dev, - void (*write_register)(struct ni_gpct *counter, - unsigned bits, - enum ni_gpct_register reg), - unsigned (*read_register)(struct ni_gpct *counter, - enum ni_gpct_register reg), + void (*write)(struct ni_gpct *counter, + unsigned int value, + enum ni_gpct_register reg), + unsigned int (*read)(struct ni_gpct *counter, + enum ni_gpct_register reg), enum ni_gpct_variant variant, - unsigned num_counters) + unsigned int num_counters) { struct ni_gpct_device *counter_dev; struct ni_gpct *counter; - unsigned i; + unsigned int i; if (num_counters == 0) return NULL; @@ -1475,8 +1475,8 @@ ni_gpct_device_construct(struct comedi_device *dev, return NULL; counter_dev->dev = dev; - counter_dev->write_register = write_register; - counter_dev->read_register = read_register; + counter_dev->write = write; + counter_dev->read = read; counter_dev->variant = variant; spin_lock_init(&counter_dev->regs_lock); diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 25aedd0e5867..63cec3edcfd4 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -115,10 +115,9 @@ struct ni_gpct { struct ni_gpct_device { struct comedi_device *dev; - void (*write_register)(struct ni_gpct *counter, unsigned bits, - enum ni_gpct_register reg); - unsigned (*read_register)(struct ni_gpct *counter, - enum ni_gpct_register reg); + void (*write)(struct ni_gpct *, unsigned int value, + enum ni_gpct_register); + unsigned int (*read)(struct ni_gpct *, enum ni_gpct_register); enum ni_gpct_variant variant; struct ni_gpct *counters; unsigned num_counters; @@ -128,13 +127,13 @@ struct ni_gpct_device { struct ni_gpct_device * ni_gpct_device_construct(struct comedi_device *, - void (*write_register)(struct ni_gpct *, - unsigned bits, - enum ni_gpct_register), - unsigned (*read_register)(struct ni_gpct *, - enum ni_gpct_register), + void (*write)(struct ni_gpct *, + unsigned int value, + enum ni_gpct_register), + unsigned int (*read)(struct ni_gpct *, + enum ni_gpct_register), enum ni_gpct_variant, - unsigned num_counters); + unsigned int num_counters); void ni_gpct_device_destroy(struct ni_gpct_device *); void ni_tio_init_counter(struct ni_gpct *); int ni_tio_insn_read(struct comedi_device *, struct comedi_subdevice *, -- GitLab From a38a1408868c6f476f8f41881b7d7757e24f61c2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:46 -0700 Subject: [PATCH 0537/9938] staging: comedi: ni_tio.h: tidy up struct ni_gpct_device Fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' CHECK: spinlock_t definition without comment Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 63cec3edcfd4..2f36dc1cad63 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -120,9 +120,9 @@ struct ni_gpct_device { unsigned int (*read)(struct ni_gpct *, enum ni_gpct_register); enum ni_gpct_variant variant; struct ni_gpct *counters; - unsigned num_counters; - unsigned regs[NITIO_NUM_REGS]; - spinlock_t regs_lock; + unsigned int num_counters; + unsigned int regs[NITIO_NUM_REGS]; + spinlock_t regs_lock; /* protects 'regs' */ }; struct ni_gpct_device * -- GitLab From 10142ced7dc10261b7ff3598dedb3f6c4cb64e6d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:47 -0700 Subject: [PATCH 0538/9938] staging: comedi: ni_tio.h: tidy up struct ni_gpct Fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' CHECK: Prefer kernel type 'u64' over 'uint64_t' CHECK: spinlock_t definition without comment Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 2f36dc1cad63..5d0374302301 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -106,11 +106,11 @@ enum ni_gpct_variant { struct ni_gpct { struct ni_gpct_device *counter_dev; - unsigned counter_index; - unsigned chip_index; - uint64_t clock_period_ps; /* clock period in picoseconds */ + unsigned int counter_index; + unsigned int chip_index; + u64 clock_period_ps; /* clock period in picoseconds */ struct mite_channel *mite_chan; - spinlock_t lock; + spinlock_t lock; /* protects 'mite_chan' */ }; struct ni_gpct_device { -- GitLab From 80168e9e583717b061cc144a06fc35dca2cc2e26 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:48 -0700 Subject: [PATCH 0539/9938] staging: comedi: ni_tio.h: fix block comment Fix the checkpatch.pl issue: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.h | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 5d0374302301..7ddafdd74095 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -1,19 +1,18 @@ /* - drivers/ni_tio.h - Header file for NI general purpose counter support code (ni_tio.c) - - COMEDI - Linux Control and Measurement Device Interface - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Header file for NI general purpose counter support code (ni_tio.c) + * + * COMEDI - Linux Control and Measurement Device Interface + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _COMEDI_NI_TIO_H #define _COMEDI_NI_TIO_H -- GitLab From 58011fdebb21a746ce43c8ada363a65c55200d74 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:49 -0700 Subject: [PATCH 0540/9938] staging: comedi: ni_tio.h: remove unnecessary forward declarations These struct forward declarations are not needed. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 7ddafdd74095..4978358f9b13 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -19,10 +19,6 @@ #include "../comedidev.h" -/* forward declarations */ -struct mite_struct; -struct ni_gpct_device; - enum ni_gpct_register { NITIO_G0_AUTO_INC, NITIO_G1_AUTO_INC, -- GitLab From 74ea93be6ce16f01e9e73a4ad5abeb984b0b02fc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:50 -0700 Subject: [PATCH 0541/9938] staging: comedi: ni_tio: Prefer 'unsigned int' to bare use of 'unsigned' Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 166 ++++++++++++------------ 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 28bec3cfeef5..ecf85270c264 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -115,7 +115,7 @@ #define NI_660X_LOGIC_LOW_GATE2_SEL 0x1f #define NI_660X_MAX_UP_DOWN_PIN 7 -static inline unsigned GI_ALT_SYNC(enum ni_gpct_variant variant) +static inline unsigned int GI_ALT_SYNC(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: @@ -128,7 +128,7 @@ static inline unsigned GI_ALT_SYNC(enum ni_gpct_variant variant) } } -static inline unsigned GI_PRESCALE_X2(enum ni_gpct_variant variant) +static inline unsigned int GI_PRESCALE_X2(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: @@ -141,7 +141,7 @@ static inline unsigned GI_PRESCALE_X2(enum ni_gpct_variant variant) } } -static inline unsigned GI_PRESCALE_X8(enum ni_gpct_variant variant) +static inline unsigned int GI_PRESCALE_X8(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: @@ -154,7 +154,7 @@ static inline unsigned GI_PRESCALE_X8(enum ni_gpct_variant variant) } } -static inline unsigned GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant) +static inline unsigned int GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: @@ -208,13 +208,13 @@ EXPORT_SYMBOL_GPL(ni_tio_read); static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) { - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; ni_tio_write(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx)); } static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, - unsigned generic_clock_source) + unsigned int generic_clock_source) { uint64_t clock_period_ps; @@ -316,13 +316,13 @@ unsigned int ni_tio_get_soft_copy(const struct ni_gpct *counter, } EXPORT_SYMBOL_GPL(ni_tio_get_soft_copy); -static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) +static unsigned int ni_tio_clock_src_modifiers(const struct ni_gpct *counter) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - const unsigned counting_mode_bits = + unsigned int cidx = counter->counter_index; + unsigned int counting_mode_bits = ni_tio_get_soft_copy(counter, NITIO_CNT_MODE_REG(cidx)); - unsigned bits = 0; + unsigned int bits = 0; if (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) & GI_SRC_POL_INVERT) @@ -334,14 +334,14 @@ static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) return bits; } -static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter) +static unsigned int ni_m_series_clock_src_select(const struct ni_gpct *counter) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); - unsigned clock_source = 0; - unsigned src; - unsigned i; + unsigned int cidx = counter->counter_index; + unsigned int second_gate_reg = NITIO_GATE2_REG(cidx); + unsigned int clock_source = 0; + unsigned int src; + unsigned int i; src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx))); @@ -399,12 +399,12 @@ static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter) return clock_source; } -static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter) +static unsigned int ni_660x_clock_src_select(const struct ni_gpct *counter) { - unsigned clock_source = 0; - unsigned cidx = counter->counter_index; - unsigned src; - unsigned i; + unsigned int clock_source = 0; + unsigned int cidx = counter->counter_index; + unsigned int src; + unsigned int i; src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx))); @@ -456,7 +456,8 @@ static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter) return clock_source; } -static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter) +static unsigned int +ni_tio_generic_clock_src_select(const struct ni_gpct *counter) { switch (counter->counter_dev->variant) { case ni_gpct_variant_e_series: @@ -471,10 +472,10 @@ static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter) static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - const unsigned counting_mode_reg = NITIO_CNT_MODE_REG(cidx); + unsigned int cidx = counter->counter_index; + unsigned int counting_mode_reg = NITIO_CNT_MODE_REG(cidx); static const uint64_t min_normal_sync_period_ps = 25000; - unsigned mode; + unsigned int mode; uint64_t clock_period_ps; if (!ni_tio_counting_mode_registers_present(counter_dev)) @@ -512,15 +513,15 @@ static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) } } -static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) +static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned int mode) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - unsigned mode_reg_mask; - unsigned mode_reg_values; - unsigned input_select_bits = 0; + unsigned int cidx = counter->counter_index; + unsigned int mode_reg_mask; + unsigned int mode_reg_values; + unsigned int input_select_bits = 0; /* these bits map directly on to the mode register */ - static const unsigned mode_reg_direct_mask = + static const unsigned int mode_reg_direct_mask = NI_GPCT_GATE_ON_BOTH_EDGES_BIT | NI_GPCT_EDGE_GATE_MODE_MASK | NI_GPCT_STOP_MODE_MASK | NI_GPCT_OUTPUT_MODE_MASK | NI_GPCT_HARDWARE_DISARM_MASK | NI_GPCT_LOADING_ON_TC_BIT | @@ -546,7 +547,7 @@ static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) mode_reg_mask, mode_reg_values); if (ni_tio_counting_mode_registers_present(counter_dev)) { - unsigned bits = 0; + unsigned int bits = 0; bits |= GI_CNT_MODE(mode >> NI_GPCT_COUNTING_MODE_SHIFT); bits |= GI_INDEX_PHASE((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT)); @@ -626,11 +627,11 @@ int ni_tio_arm(struct ni_gpct *counter, bool arm, unsigned int start_trigger) } EXPORT_SYMBOL_GPL(ni_tio_arm); -static unsigned ni_660x_clk_src(unsigned int clock_source) +static unsigned int ni_660x_clk_src(unsigned int clock_source) { - unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; - unsigned ni_660x_clock; - unsigned i; + unsigned int clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; + unsigned int ni_660x_clock; + unsigned int i; switch (clk_src) { case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: @@ -678,11 +679,11 @@ static unsigned ni_660x_clk_src(unsigned int clock_source) return GI_SRC_SEL(ni_660x_clock); } -static unsigned ni_m_clk_src(unsigned int clock_source) +static unsigned int ni_m_clk_src(unsigned int clock_source) { - unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; - unsigned ni_m_series_clock; - unsigned i; + unsigned int clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; + unsigned int ni_m_series_clock; + unsigned int i; switch (clk_src) { case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: @@ -742,8 +743,8 @@ static void ni_tio_set_source_subselect(struct ni_gpct *counter, unsigned int clock_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); + unsigned int cidx = counter->counter_index; + unsigned int second_gate_reg = NITIO_GATE2_REG(cidx); if (counter_dev->variant != ni_gpct_variant_m_series) return; @@ -771,8 +772,8 @@ static int ni_tio_set_clock_src(struct ni_gpct *counter, unsigned int period_ns) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - unsigned bits = 0; + unsigned int cidx = counter->counter_index; + unsigned int bits = 0; /* FIXME: validate clock source */ switch (counter_dev->variant) { @@ -829,9 +830,9 @@ static void ni_tio_get_clock_src(struct ni_gpct *counter, static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source) { unsigned int chan = CR_CHAN(gate_source); - unsigned cidx = counter->counter_index; - unsigned gate_sel; - unsigned i; + unsigned int cidx = counter->counter_index; + unsigned int gate_sel; + unsigned int i; switch (chan) { case NI_GPCT_NEXT_SOURCE_GATE_SELECT: @@ -870,9 +871,9 @@ static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source) static int ni_m_set_gate(struct ni_gpct *counter, unsigned int gate_source) { unsigned int chan = CR_CHAN(gate_source); - unsigned cidx = counter->counter_index; - unsigned gate_sel; - unsigned i; + unsigned int cidx = counter->counter_index; + unsigned int gate_sel; + unsigned int i; switch (chan) { case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT: @@ -912,11 +913,11 @@ static int ni_m_set_gate(struct ni_gpct *counter, unsigned int gate_source) static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; unsigned int chan = CR_CHAN(gate_source); - unsigned gate2_reg = NITIO_GATE2_REG(cidx); - unsigned gate2_sel; - unsigned i; + unsigned int gate2_reg = NITIO_GATE2_REG(cidx); + unsigned int gate2_sel; + unsigned int i; switch (chan) { case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: @@ -958,10 +959,10 @@ static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source) static int ni_m_set_gate2(struct ni_gpct *counter, unsigned int gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; unsigned int chan = CR_CHAN(gate_source); - unsigned gate2_reg = NITIO_GATE2_REG(cidx); - unsigned gate2_sel; + unsigned int gate2_reg = NITIO_GATE2_REG(cidx); + unsigned int gate2_sel; /* * FIXME: We don't know what the m-series second gate codes are, @@ -1045,11 +1046,11 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, } EXPORT_SYMBOL_GPL(ni_tio_set_gate_src); -static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, +static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned int index, unsigned int source) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; unsigned int abz_reg, shift, mask; if (counter_dev->variant != ni_gpct_variant_m_series) @@ -1079,9 +1080,9 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, return 0; } -static unsigned ni_660x_gate_to_generic_gate(unsigned gate) +static unsigned int ni_660x_gate_to_generic_gate(unsigned int gate) { - unsigned i; + unsigned int i; switch (gate) { case NI_660X_SRC_PIN_I_GATE_SEL: @@ -1109,9 +1110,9 @@ static unsigned ni_660x_gate_to_generic_gate(unsigned gate) return 0; }; -static unsigned ni_m_gate_to_generic_gate(unsigned gate) +static unsigned int ni_m_gate_to_generic_gate(unsigned int gate) { - unsigned i; + unsigned int i; switch (gate) { case NI_M_TIMESTAMP_MUX_GATE_SEL: @@ -1145,9 +1146,9 @@ static unsigned ni_m_gate_to_generic_gate(unsigned gate) return 0; }; -static unsigned ni_660x_gate2_to_generic_gate(unsigned gate) +static unsigned int ni_660x_gate2_to_generic_gate(unsigned int gate) { - unsigned i; + unsigned int i; switch (gate) { case NI_660X_SRC_PIN_I_GATE2_SEL: @@ -1177,7 +1178,7 @@ static unsigned ni_660x_gate2_to_generic_gate(unsigned gate) return 0; }; -static unsigned ni_m_gate2_to_generic_gate(unsigned gate) +static unsigned int ni_m_gate2_to_generic_gate(unsigned int gate) { /* * FIXME: the second gate sources for the m series are undocumented, @@ -1190,14 +1191,14 @@ static unsigned ni_m_gate2_to_generic_gate(unsigned gate) return 0; }; -static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index, +static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index, unsigned int *gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - unsigned mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); - unsigned gate2_reg = NITIO_GATE2_REG(cidx); - unsigned gate; + unsigned int cidx = counter->counter_index; + unsigned int mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); + unsigned int gate2_reg = NITIO_GATE2_REG(cidx); + unsigned int gate; switch (gate_index) { case 0: @@ -1261,8 +1262,8 @@ int ni_tio_insn_config(struct comedi_device *dev, unsigned int *data) { struct ni_gpct *counter = s->private; - unsigned cidx = counter->counter_index; - unsigned status; + unsigned int cidx = counter->counter_index; + unsigned int status; switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: @@ -1307,7 +1308,7 @@ static unsigned int ni_tio_read_sw_save_reg(struct comedi_device *dev, struct comedi_subdevice *s) { struct ni_gpct *counter = s->private; - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; unsigned int val; ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0); @@ -1338,7 +1339,7 @@ int ni_tio_insn_read(struct comedi_device *dev, struct ni_gpct *counter = s->private; struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned int channel = CR_CHAN(insn->chanspec); - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; int i; for (i = 0; i < insn->n; i++) { @@ -1358,11 +1359,10 @@ int ni_tio_insn_read(struct comedi_device *dev, } EXPORT_SYMBOL_GPL(ni_tio_insn_read); -static unsigned ni_tio_next_load_register(struct ni_gpct *counter) +static unsigned int ni_tio_next_load_register(struct ni_gpct *counter) { - unsigned cidx = counter->counter_index; - const unsigned bits = - ni_tio_read(counter, NITIO_SHARED_STATUS_REG(cidx)); + unsigned int cidx = counter->counter_index; + unsigned int bits = ni_tio_read(counter, NITIO_SHARED_STATUS_REG(cidx)); return (bits & GI_NEXT_LOAD_SRC(cidx)) ? NITIO_LOADB_REG(cidx) @@ -1376,9 +1376,9 @@ int ni_tio_insn_write(struct comedi_device *dev, { struct ni_gpct *counter = s->private; struct ni_gpct_device *counter_dev = counter->counter_dev; - const unsigned channel = CR_CHAN(insn->chanspec); - unsigned cidx = counter->counter_index; - unsigned load_reg; + unsigned int channel = CR_CHAN(insn->chanspec); + unsigned int cidx = counter->counter_index; + unsigned int load_reg; if (insn->n < 1) return 0; @@ -1418,7 +1418,7 @@ EXPORT_SYMBOL_GPL(ni_tio_insn_write); void ni_tio_init_counter(struct ni_gpct *counter) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; ni_tio_reset_count_and_disarm(counter); -- GitLab From 3676cdd9539a64d1b3e8cad8d8e5184bf860841a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:51 -0700 Subject: [PATCH 0542/9938] staging: comedi: ni_tio: Prefer kernel type 'u64' over 'uint64_t' Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index ecf85270c264..e4fd22123ef0 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -213,10 +213,10 @@ static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) ni_tio_write(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx)); } -static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, - unsigned int generic_clock_source) +static u64 ni_tio_clock_period_ps(const struct ni_gpct *counter, + unsigned int generic_clock_source) { - uint64_t clock_period_ps; + u64 clock_period_ps; switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: @@ -474,9 +474,9 @@ static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned int cidx = counter->counter_index; unsigned int counting_mode_reg = NITIO_CNT_MODE_REG(cidx); - static const uint64_t min_normal_sync_period_ps = 25000; + static const u64 min_normal_sync_period_ps = 25000; unsigned int mode; - uint64_t clock_period_ps; + u64 clock_period_ps; if (!ni_tio_counting_mode_registers_present(counter_dev)) return; @@ -819,7 +819,7 @@ static void ni_tio_get_clock_src(struct ni_gpct *counter, unsigned int *clock_source, unsigned int *period_ns) { - uint64_t temp64; + u64 temp64; *clock_source = ni_tio_generic_clock_src_select(counter); temp64 = ni_tio_clock_period_ps(counter, *clock_source); -- GitLab From 8e621cf0cb9761b7ef74a63d228ce62418dc5b8c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:52 -0700 Subject: [PATCH 0543/9938] staging: comedi: ni_tio: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 36 +++++++++++-------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index e4fd22123ef0..e7af98d78607 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1,19 +1,18 @@ /* - comedi/drivers/ni_tio.c - Support for NI general purpose counters - - Copyright (C) 2006 Frank Mori Hess - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Support for NI general purpose counters + * + * Copyright (C) 2006 Frank Mori Hess + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* * Module: ni_tio @@ -36,13 +35,10 @@ * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) * DAQ 6601/6602 User Manual (NI 322137B-01) * 340934b.pdf DAQ-STC reference manual + * + * TODO: Support use of both banks X and Y */ -/* -TODO: - Support use of both banks X and Y -*/ - #include #include -- GitLab From a56b3f57c2f08a6f42c957c3731ca9f8158b6355 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:53 -0700 Subject: [PATCH 0544/9938] staging: comedi: ni_tio: tidy up ni_tio_get_gate_src() Clarify the code a bit by handling the NI_GPCT_DISABLED_GATE_SELECT source in the common code path. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 32 ++++++++++++------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index e7af98d78607..ce64cc39e49c 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1192,19 +1192,22 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index, { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned int cidx = counter->counter_index; - unsigned int mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); - unsigned int gate2_reg = NITIO_GATE2_REG(cidx); + unsigned int mode; + unsigned int reg; unsigned int gate; + mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); + if (((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED) || + (gate_index == 1 && + !(counter_dev->regs[NITIO_GATE2_REG(cidx)] & GI_GATE2_MODE))) { + *gate_source = NI_GPCT_DISABLED_GATE_SELECT; + return 0; + } + switch (gate_index) { case 0: - if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED) { - *gate_source = NI_GPCT_DISABLED_GATE_SELECT; - return 0; - } - - gate = GI_BITS_TO_GATE(ni_tio_get_soft_copy(counter, - NITIO_INPUT_SEL_REG(cidx))); + reg = NITIO_INPUT_SEL_REG(cidx); + gate = GI_BITS_TO_GATE(ni_tio_get_soft_copy(counter, reg)); switch (counter_dev->variant) { case ni_gpct_variant_e_series: @@ -1222,13 +1225,8 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index, *gate_source |= CR_EDGE; break; case 1: - if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED || - !(counter_dev->regs[gate2_reg] & GI_GATE2_MODE)) { - *gate_source = NI_GPCT_DISABLED_GATE_SELECT; - return 0; - } - - gate = GI_BITS_TO_GATE2(counter_dev->regs[gate2_reg]); + reg = NITIO_GATE2_REG(cidx); + gate = GI_BITS_TO_GATE2(counter_dev->regs[reg]); switch (counter_dev->variant) { case ni_gpct_variant_e_series: @@ -1240,7 +1238,7 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index, *gate_source = ni_660x_gate2_to_generic_gate(gate); break; } - if (counter_dev->regs[gate2_reg] & GI_GATE2_POL_INVERT) + if (counter_dev->regs[reg] & GI_GATE2_POL_INVERT) *gate_source |= CR_INVERT; /* second gate can't have edge/level mode set independently */ if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING) -- GitLab From f51700a6428d7c8e94d48fd2fbb1062c604e8b2c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:54 -0700 Subject: [PATCH 0545/9938] staging: comedi: ni_tio: tidy up ni_tio_set_sync_mode() The 'force_alt_sync' paramater is always 0. Remove it. Absorb the GI_ALT_SYNC() inline helper and use some local variables to clarify this function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 65 ++++++++++++------------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index ce64cc39e49c..2c33b28bf114 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -111,19 +111,6 @@ #define NI_660X_LOGIC_LOW_GATE2_SEL 0x1f #define NI_660X_MAX_UP_DOWN_PIN 7 -static inline unsigned int GI_ALT_SYNC(enum ni_gpct_variant variant) -{ - switch (variant) { - case ni_gpct_variant_e_series: - default: - return 0; - case ni_gpct_variant_m_series: - return GI_M_ALT_SYNC; - case ni_gpct_variant_660x: - return GI_660X_ALT_SYNC; - } -} - static inline unsigned int GI_PRESCALE_X2(enum ni_gpct_variant variant) { switch (variant) { @@ -465,48 +452,56 @@ ni_tio_generic_clock_src_select(const struct ni_gpct *counter) } } -static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) +static void ni_tio_set_sync_mode(struct ni_gpct *counter) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned int cidx = counter->counter_index; - unsigned int counting_mode_reg = NITIO_CNT_MODE_REG(cidx); static const u64 min_normal_sync_period_ps = 25000; + unsigned int mask = 0; + unsigned int bits = 0; + unsigned int reg; unsigned int mode; - u64 clock_period_ps; + u64 ps; + bool force_alt_sync; - if (!ni_tio_counting_mode_registers_present(counter_dev)) + /* only m series and 660x variants have counting mode registers */ + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + default: return; + case ni_gpct_variant_m_series: + mask = GI_M_ALT_SYNC; + break; + case ni_gpct_variant_660x: + mask = GI_660X_ALT_SYNC; + break; + } - mode = ni_tio_get_soft_copy(counter, counting_mode_reg); + reg = NITIO_CNT_MODE_REG(cidx); + mode = ni_tio_get_soft_copy(counter, reg); switch (mode & GI_CNT_MODE_MASK) { case GI_CNT_MODE_QUADX1: case GI_CNT_MODE_QUADX2: case GI_CNT_MODE_QUADX4: case GI_CNT_MODE_SYNC_SRC: - force_alt_sync = 1; + force_alt_sync = true; break; default: + force_alt_sync = false; break; } - clock_period_ps = ni_tio_clock_period_ps(counter, - ni_tio_generic_clock_src_select(counter)); + ps = ni_tio_clock_period_ps(counter, + ni_tio_generic_clock_src_select(counter)); /* * It's not clear what we should do if clock_period is unknown, so we - * are not using the alt sync bit in that case, but allow the caller - * to decide by using the force_alt_sync parameter. + * are not using the alt sync bit in that case. */ - if (force_alt_sync || - (clock_period_ps && clock_period_ps < min_normal_sync_period_ps)) { - ni_tio_set_bits(counter, counting_mode_reg, - GI_ALT_SYNC(counter_dev->variant), - GI_ALT_SYNC(counter_dev->variant)); - } else { - ni_tio_set_bits(counter, counting_mode_reg, - GI_ALT_SYNC(counter_dev->variant), - 0x0); - } + if (force_alt_sync || (ps && ps < min_normal_sync_period_ps)) + bits = mask; + + ni_tio_set_bits(counter, reg, mask, bits); } static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned int mode) @@ -552,7 +547,7 @@ static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned int mode) ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), GI_CNT_MODE_MASK | GI_INDEX_PHASE_MASK | GI_INDEX_MODE, bits); - ni_tio_set_sync_mode(counter, 0); + ni_tio_set_sync_mode(counter); } ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_CNT_DIR_MASK, @@ -807,7 +802,7 @@ static int ni_tio_set_clock_src(struct ni_gpct *counter, GI_PRESCALE_X8(counter_dev->variant), bits); } counter->clock_period_ps = period_ns * 1000; - ni_tio_set_sync_mode(counter, 0); + ni_tio_set_sync_mode(counter); return 0; } -- GitLab From e3f7bb258b2f73c595ea8f2d26ad2cb137844b8a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:55 -0700 Subject: [PATCH 0546/9938] staging: comedi: ni_tio: tidy up ni_tio_arm() Make this function a bit more consise by absorbing the GI_HW_ARM_SEL_MASK() inline helper and combine the two switch (start_trigger) code paths. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 78 +++++++++++-------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 2c33b28bf114..e7209c1ca816 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -137,19 +137,6 @@ static inline unsigned int GI_PRESCALE_X8(enum ni_gpct_variant variant) } } -static inline unsigned int GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant) -{ - switch (variant) { - case ni_gpct_variant_e_series: - default: - return 0; - case ni_gpct_variant_m_series: - return GI_M_HW_ARM_SEL_MASK; - case ni_gpct_variant_660x: - return GI_660X_HW_ARM_SEL_MASK; - } -} - static bool ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev) { switch (counter_dev->variant) { @@ -568,52 +555,55 @@ int ni_tio_arm(struct ni_gpct *counter, bool arm, unsigned int start_trigger) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned int cidx = counter->counter_index; - unsigned int command_transient_bits = 0; + unsigned int transient_bits = 0; if (arm) { + unsigned int mask = 0; + unsigned int bits = 0; + + /* only m series and 660x have counting mode registers */ + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + default: + break; + case ni_gpct_variant_m_series: + mask = GI_M_HW_ARM_SEL_MASK; + break; + case ni_gpct_variant_660x: + mask = GI_660X_HW_ARM_SEL_MASK; + break; + } + switch (start_trigger) { case NI_GPCT_ARM_IMMEDIATE: - command_transient_bits |= GI_ARM; + transient_bits |= GI_ARM; break; case NI_GPCT_ARM_PAIRED_IMMEDIATE: - command_transient_bits |= GI_ARM | GI_ARM_COPY; + transient_bits |= GI_ARM | GI_ARM_COPY; break; default: + /* + * for m series and 660x, pass-through the least + * significant bits so we can figure out what select + * later + */ + if (mask && (start_trigger & NI_GPCT_ARM_UNKNOWN)) { + bits |= GI_HW_ARM_ENA | + (GI_HW_ARM_SEL(start_trigger) & mask); + } else { + return -EINVAL; + } break; } - if (ni_tio_counting_mode_registers_present(counter_dev)) { - unsigned int bits = 0; - unsigned int sel_mask; - sel_mask = GI_HW_ARM_SEL_MASK(counter_dev->variant); - - switch (start_trigger) { - case NI_GPCT_ARM_IMMEDIATE: - case NI_GPCT_ARM_PAIRED_IMMEDIATE: - break; - default: - if (start_trigger & NI_GPCT_ARM_UNKNOWN) { - /* - * pass-through the least significant - * bits so we can figure out what - * select later - */ - bits |= GI_HW_ARM_ENA | - (GI_HW_ARM_SEL(start_trigger) & - sel_mask); - } else { - return -EINVAL; - } - break; - } + if (mask) ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), - GI_HW_ARM_ENA | sel_mask, bits); - } + GI_HW_ARM_ENA | mask, bits); } else { - command_transient_bits |= GI_DISARM; + transient_bits |= GI_DISARM; } ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx), - 0, 0, command_transient_bits); + 0, 0, transient_bits); return 0; } EXPORT_SYMBOL_GPL(ni_tio_arm); -- GitLab From 9f62bee520b04346c3501a5da7534a96b873c01f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:56 -0700 Subject: [PATCH 0547/9938] staging: comedi: ni_tiocmd: Prefer 'unsigned int' to bare use of 'unsigned' Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tiocmd.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index d5ffbb135844..df4ffdbcd96d 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -51,9 +51,9 @@ static void ni_tio_configure_dma(struct ni_gpct *counter, bool enable, bool read) { struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - unsigned mask; - unsigned bits; + unsigned int cidx = counter->counter_index; + unsigned int mask; + unsigned int bits; mask = GI_READ_ACKS_IRQ | GI_WRITE_ACKS_IRQ; bits = 0; @@ -113,7 +113,7 @@ static int ni_tio_input_cmd(struct comedi_subdevice *s) { struct ni_gpct *counter = s->private; struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; int ret = 0; @@ -163,9 +163,9 @@ static int ni_tio_cmd_setup(struct comedi_subdevice *s) { struct comedi_cmd *cmd = &s->async->cmd; struct ni_gpct *counter = s->private; - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; int set_gate_source = 0; - unsigned gate_source; + unsigned int gate_source; int retval = 0; if (cmd->scan_begin_src == TRIG_EXT) { @@ -289,7 +289,7 @@ EXPORT_SYMBOL_GPL(ni_tio_cmdtest); int ni_tio_cancel(struct ni_gpct *counter) { - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; unsigned long flags; ni_tio_arm(counter, false, 0); @@ -341,12 +341,12 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *perm_stale_data, int *stale_data) { - unsigned cidx = counter->counter_index; + unsigned int cidx = counter->counter_index; const unsigned short gxx_status = ni_tio_read(counter, NITIO_SHARED_STATUS_REG(cidx)); const unsigned short gi_status = ni_tio_read(counter, NITIO_STATUS_REG(cidx)); - unsigned ack = 0; + unsigned int ack = 0; if (gate_error) *gate_error = 0; @@ -407,8 +407,8 @@ EXPORT_SYMBOL_GPL(ni_tio_acknowledge); void ni_tio_handle_interrupt(struct ni_gpct *counter, struct comedi_subdevice *s) { - unsigned cidx = counter->counter_index; - unsigned gpct_mite_status; + unsigned int cidx = counter->counter_index; + unsigned int gpct_mite_status; unsigned long flags; int gate_error; int tc_error; -- GitLab From b878a82ee15f77ff1106aa0e5be36a1ee3ec85ea Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:57 -0700 Subject: [PATCH 0548/9938] staging: comedi: ni_tiocmd: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tiocmd.c | 60 +++++++++++----------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index df4ffdbcd96d..1400b1f2305d 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -1,19 +1,18 @@ /* - comedi/drivers/ni_tiocmd.c - Command support for NI general purpose counters - - Copyright (C) 2006 Frank Mori Hess - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Command support for NI general purpose counters + * + * Copyright (C) 2006 Frank Mori Hess + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* * Module: ni_tiocmd @@ -36,13 +35,10 @@ * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) * DAQ 6601/6602 User Manual (NI 322137B-01) * 340934b.pdf DAQ-STC reference manual + * + * TODO: Support use of both banks X and Y */ -/* -TODO: - Support use of both banks X and Y -*/ - #include #include "ni_tio_internal.h" #include "mite.h" @@ -305,9 +301,6 @@ int ni_tio_cancel(struct ni_gpct *counter) } EXPORT_SYMBOL_GPL(ni_tio_cancel); - /* During buffered input counter operation for e-series, the gate - interrupt is acked automatically by the dma controller, due to the - Gi_Read/Write_Acknowledges_IRQ bits in the input select register. */ static int should_ack_gate(struct ni_gpct *counter) { unsigned long flags; @@ -315,12 +308,19 @@ static int should_ack_gate(struct ni_gpct *counter) switch (counter->counter_dev->variant) { case ni_gpct_variant_m_series: - /* not sure if 660x really supports gate - interrupts (the bits are not listed - in register-level manual) */ case ni_gpct_variant_660x: + /* + * not sure if 660x really supports gate interrupts + * (the bits are not listed in register-level manual) + */ return 1; case ni_gpct_variant_e_series: + /* + * During buffered input counter operation for e-series, + * the gate interrupt is acked automatically by the dma + * controller, due to the Gi_Read/Write_Acknowledges_IRQ + * bits in the input select register. + */ spin_lock_irqsave(&counter->lock, flags); { if (!counter->mite_chan || @@ -360,9 +360,11 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, if (gxx_status & GI_GATE_ERROR(cidx)) { ack |= GI_GATE_ERROR_CONFIRM(cidx); if (gate_error) { - /*660x don't support automatic acknowledgment - of gate interrupt via dma read/write - and report bogus gate errors */ + /* + * 660x don't support automatic acknowledgment + * of gate interrupt via dma read/write + * and report bogus gate errors + */ if (counter->counter_dev->variant != ni_gpct_variant_660x) *gate_error = 1; -- GitLab From 53d63371293dfc8fdd49f14716c2f2b80aa11373 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:58 -0700 Subject: [PATCH 0549/9938] staging: comedi: ni_tiocmd: remove unsed param from ni_tio_acknowledge_and_confirm() The 'stale_data' pointer is always NULL. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tiocmd.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 1400b1f2305d..2d801bf90e52 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -338,8 +338,7 @@ static int should_ack_gate(struct ni_gpct *counter) static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error, int *tc_error, - int *perm_stale_data, - int *stale_data) + int *perm_stale_data) { unsigned int cidx = counter->counter_index; const unsigned short gxx_status = ni_tio_read(counter, @@ -354,8 +353,6 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, *tc_error = 0; if (perm_stale_data) *perm_stale_data = 0; - if (stale_data) - *stale_data = 0; if (gxx_status & GI_GATE_ERROR(cidx)) { ack |= GI_GATE_ERROR_CONFIRM(cidx); @@ -385,10 +382,6 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, ni_tio_write(counter, ack, NITIO_INT_ACK_REG(cidx)); if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) & GI_LOADING_ON_GATE) { - if (gxx_status & GI_STALE_DATA(cidx)) { - if (stale_data) - *stale_data = 1; - } if (ni_tio_read(counter, NITIO_STATUS2_REG(cidx)) & GI_PERMANENT_STALE(cidx)) { dev_info(counter->counter_dev->dev->class_dev, @@ -402,7 +395,7 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, void ni_tio_acknowledge(struct ni_gpct *counter) { - ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); + ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL); } EXPORT_SYMBOL_GPL(ni_tio_acknowledge); @@ -417,7 +410,7 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter, int perm_stale_data; ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error, - &perm_stale_data, NULL); + &perm_stale_data); if (gate_error) { dev_notice(counter->counter_dev->dev->class_dev, "%s: Gi_Gate_Error detected.\n", __func__); -- GitLab From a19b9b476ae3612e6c61c60e7fad7c8974158ef9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:36:59 -0700 Subject: [PATCH 0550/9938] staging: comedi: ni_tiocmd: remove BUG() which can never occur All the counter_dev->variant options are handled by the switch. Remove the BUG() which can never occur. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tiocmd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 2d801bf90e52..3c3f5430e552 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -125,9 +125,6 @@ static int ni_tio_input_cmd(struct comedi_subdevice *s) case ni_gpct_variant_e_series: mite_prep_dma(counter->mite_chan, 16, 32); break; - default: - BUG(); - break; } ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0); ni_tio_configure_dma(counter, true, true); -- GitLab From d87f5e90585a8b8646c3e9fe92d4c47716f5e19d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:37:00 -0700 Subject: [PATCH 0551/9938] staging: comedi: ni_tio: validate clock source Refactor the functions that determine the clock source bits so that they return -EINVAL if the clock source is invalid. Pass the errno back to ni_tio_insn_config(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 34 ++++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index e7209c1ca816..564ec9bfd43d 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -608,7 +608,7 @@ int ni_tio_arm(struct ni_gpct *counter, bool arm, unsigned int start_trigger) } EXPORT_SYMBOL_GPL(ni_tio_arm); -static unsigned int ni_660x_clk_src(unsigned int clock_source) +static int ni_660x_clk_src(unsigned int clock_source, unsigned int *bits) { unsigned int clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; unsigned int ni_660x_clock; @@ -653,14 +653,13 @@ static unsigned int ni_660x_clk_src(unsigned int clock_source) } if (i <= NI_660X_MAX_SRC_PIN) break; - ni_660x_clock = 0; - BUG(); - break; + return -EINVAL; } - return GI_SRC_SEL(ni_660x_clock); + *bits = GI_SRC_SEL(ni_660x_clock); + return 0; } -static unsigned int ni_m_clk_src(unsigned int clock_source) +static int ni_m_clk_src(unsigned int clock_source, unsigned int *bits) { unsigned int clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; unsigned int ni_m_series_clock; @@ -711,13 +710,10 @@ static unsigned int ni_m_clk_src(unsigned int clock_source) } if (i <= NI_M_MAX_PFI_CHAN) break; - pr_err("invalid clock source 0x%lx\n", - (unsigned long)clock_source); - BUG(); - ni_m_series_clock = 0; - break; + return -EINVAL; } - return GI_SRC_SEL(ni_m_series_clock); + *bits = GI_SRC_SEL(ni_m_series_clock); + return 0; }; static void ni_tio_set_source_subselect(struct ni_gpct *counter, @@ -755,18 +751,26 @@ static int ni_tio_set_clock_src(struct ni_gpct *counter, struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned int cidx = counter->counter_index; unsigned int bits = 0; + int ret; - /* FIXME: validate clock source */ switch (counter_dev->variant) { case ni_gpct_variant_660x: - bits |= ni_660x_clk_src(clock_source); + ret = ni_660x_clk_src(clock_source, &bits); break; case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: default: - bits |= ni_m_clk_src(clock_source); + ret = ni_m_clk_src(clock_source, &bits); break; } + if (ret) { + struct comedi_device *dev = counter_dev->dev; + + dev_err(dev->class_dev, "invalid clock source 0x%x\n", + clock_source); + return ret; + } + if (clock_source & NI_GPCT_INVERT_CLOCK_SRC_BIT) bits |= GI_SRC_POL_INVERT; ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), -- GitLab From 475ea1ed14cce2608ed0f12474be2a3d75880eaf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:37:01 -0700 Subject: [PATCH 0552/9938] staging: comedi: ni_tio: remove BUG() checks for ni_tio_get_gate_src() This function calls some helper functions to convert the counter variant specific gate select bits into the generic enum ni_gpct_clock_source_bits equivelent. These helper functions currently BUG() if the gate select bits are invalid. This should never happen but refactor the code to return -EINVAL instead and remove the BUG() checks. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 146 ++++++++++++++++-------- 1 file changed, 97 insertions(+), 49 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 564ec9bfd43d..51dd368f788d 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1065,114 +1065,157 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned int index, return 0; } -static unsigned int ni_660x_gate_to_generic_gate(unsigned int gate) +static int ni_660x_gate_to_generic_gate(unsigned int gate, unsigned int *src) { + unsigned int source; unsigned int i; switch (gate) { case NI_660X_SRC_PIN_I_GATE_SEL: - return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; + source = NI_GPCT_SOURCE_PIN_i_GATE_SELECT; + break; case NI_660X_GATE_PIN_I_GATE_SEL: - return NI_GPCT_GATE_PIN_i_GATE_SELECT; + source = NI_GPCT_GATE_PIN_i_GATE_SELECT; + break; case NI_660X_NEXT_SRC_GATE_SEL: - return NI_GPCT_NEXT_SOURCE_GATE_SELECT; + source = NI_GPCT_NEXT_SOURCE_GATE_SELECT; + break; case NI_660X_NEXT_OUT_GATE_SEL: - return NI_GPCT_NEXT_OUT_GATE_SELECT; + source = NI_GPCT_NEXT_OUT_GATE_SELECT; + break; case NI_660X_LOGIC_LOW_GATE_SEL: - return NI_GPCT_LOGIC_LOW_GATE_SELECT; + source = NI_GPCT_LOGIC_LOW_GATE_SELECT; + break; default: for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { - if (gate == NI_660X_RTSI_GATE_SEL(i)) - return NI_GPCT_RTSI_GATE_SELECT(i); + if (gate == NI_660X_RTSI_GATE_SEL(i)) { + source = NI_GPCT_RTSI_GATE_SELECT(i); + break; + } } + if (i <= NI_660X_MAX_RTSI_CHAN) + break; for (i = 0; i <= NI_660X_MAX_GATE_PIN; ++i) { - if (gate == NI_660X_PIN_GATE_SEL(i)) - return NI_GPCT_GATE_PIN_GATE_SELECT(i); + if (gate == NI_660X_PIN_GATE_SEL(i)) { + source = NI_GPCT_GATE_PIN_GATE_SELECT(i); + break; + } } - BUG(); - break; + if (i <= NI_660X_MAX_GATE_PIN) + break; + return -EINVAL; } + *src = source; return 0; }; -static unsigned int ni_m_gate_to_generic_gate(unsigned int gate) +static int ni_m_gate_to_generic_gate(unsigned int gate, unsigned int *src) { + unsigned int source; unsigned int i; switch (gate) { case NI_M_TIMESTAMP_MUX_GATE_SEL: - return NI_GPCT_TIMESTAMP_MUX_GATE_SELECT; + source = NI_GPCT_TIMESTAMP_MUX_GATE_SELECT; + break; case NI_M_AI_START2_GATE_SEL: - return NI_GPCT_AI_START2_GATE_SELECT; + source = NI_GPCT_AI_START2_GATE_SELECT; + break; case NI_M_PXI_STAR_TRIGGER_GATE_SEL: - return NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT; + source = NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT; + break; case NI_M_NEXT_OUT_GATE_SEL: - return NI_GPCT_NEXT_OUT_GATE_SELECT; + source = NI_GPCT_NEXT_OUT_GATE_SELECT; + break; case NI_M_AI_START1_GATE_SEL: - return NI_GPCT_AI_START1_GATE_SELECT; + source = NI_GPCT_AI_START1_GATE_SELECT; + break; case NI_M_NEXT_SRC_GATE_SEL: - return NI_GPCT_NEXT_SOURCE_GATE_SELECT; + source = NI_GPCT_NEXT_SOURCE_GATE_SELECT; + break; case NI_M_ANALOG_TRIG_OUT_GATE_SEL: - return NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT; + source = NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT; + break; case NI_M_LOGIC_LOW_GATE_SEL: - return NI_GPCT_LOGIC_LOW_GATE_SELECT; + source = NI_GPCT_LOGIC_LOW_GATE_SELECT; + break; default: for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { - if (gate == NI_M_RTSI_GATE_SEL(i)) - return NI_GPCT_RTSI_GATE_SELECT(i); + if (gate == NI_M_RTSI_GATE_SEL(i)) { + source = NI_GPCT_RTSI_GATE_SELECT(i); + break; + } } + if (i <= NI_M_MAX_RTSI_CHAN) + break; for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { - if (gate == NI_M_PFI_GATE_SEL(i)) - return NI_GPCT_PFI_GATE_SELECT(i); + if (gate == NI_M_PFI_GATE_SEL(i)) { + source = NI_GPCT_PFI_GATE_SELECT(i); + break; + } } - BUG(); - break; + if (i <= NI_M_MAX_PFI_CHAN) + break; + return -EINVAL; } + *src = source; return 0; }; -static unsigned int ni_660x_gate2_to_generic_gate(unsigned int gate) +static int ni_660x_gate2_to_generic_gate(unsigned int gate, unsigned int *src) { + unsigned int source; unsigned int i; switch (gate) { case NI_660X_SRC_PIN_I_GATE2_SEL: - return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; + source = NI_GPCT_SOURCE_PIN_i_GATE_SELECT; + break; case NI_660X_UD_PIN_I_GATE2_SEL: - return NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT; + source = NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT; + break; case NI_660X_NEXT_SRC_GATE2_SEL: - return NI_GPCT_NEXT_SOURCE_GATE_SELECT; + source = NI_GPCT_NEXT_SOURCE_GATE_SELECT; + break; case NI_660X_NEXT_OUT_GATE2_SEL: - return NI_GPCT_NEXT_OUT_GATE_SELECT; + source = NI_GPCT_NEXT_OUT_GATE_SELECT; + break; case NI_660X_SELECTED_GATE2_SEL: - return NI_GPCT_SELECTED_GATE_GATE_SELECT; + source = NI_GPCT_SELECTED_GATE_GATE_SELECT; + break; case NI_660X_LOGIC_LOW_GATE2_SEL: - return NI_GPCT_LOGIC_LOW_GATE_SELECT; + source = NI_GPCT_LOGIC_LOW_GATE_SELECT; + break; default: for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { - if (gate == NI_660X_RTSI_GATE2_SEL(i)) - return NI_GPCT_RTSI_GATE_SELECT(i); + if (gate == NI_660X_RTSI_GATE2_SEL(i)) { + source = NI_GPCT_RTSI_GATE_SELECT(i); + break; + } } + if (i <= NI_660X_MAX_RTSI_CHAN) + break; for (i = 0; i <= NI_660X_MAX_UP_DOWN_PIN; ++i) { - if (gate == NI_660X_UD_PIN_GATE2_SEL(i)) - return NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i); + if (gate == NI_660X_UD_PIN_GATE2_SEL(i)) { + source = NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i); + break; + } } - BUG(); - break; + if (i <= NI_660X_MAX_UP_DOWN_PIN) + break; + return -EINVAL; } + *src = source; return 0; }; -static unsigned int ni_m_gate2_to_generic_gate(unsigned int gate) +static int ni_m_gate2_to_generic_gate(unsigned int gate, unsigned int *src) { /* * FIXME: the second gate sources for the m series are undocumented, * so we just return the raw bits for now. */ - switch (gate) { - default: - return gate; - } + *src = gate; return 0; }; @@ -1184,6 +1227,7 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index, unsigned int mode; unsigned int reg; unsigned int gate; + int ret; mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); if (((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED) || @@ -1202,12 +1246,14 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index, case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: default: - *gate_source = ni_m_gate_to_generic_gate(gate); + ret = ni_m_gate_to_generic_gate(gate, gate_source); break; case ni_gpct_variant_660x: - *gate_source = ni_660x_gate_to_generic_gate(gate); + ret = ni_660x_gate_to_generic_gate(gate, gate_source); break; } + if (ret) + return ret; if (mode & GI_GATE_POL_INVERT) *gate_source |= CR_INVERT; if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING) @@ -1221,12 +1267,14 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index, case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: default: - *gate_source = ni_m_gate2_to_generic_gate(gate); + ret = ni_m_gate2_to_generic_gate(gate, gate_source); break; case ni_gpct_variant_660x: - *gate_source = ni_660x_gate2_to_generic_gate(gate); + ret = ni_660x_gate2_to_generic_gate(gate, gate_source); break; } + if (ret) + return ret; if (counter_dev->regs[reg] & GI_GATE2_POL_INVERT) *gate_source |= CR_INVERT; /* second gate can't have edge/level mode set independently */ -- GitLab From 592ef9fb8d7e5deb359b02530c5bb0d0b717cfef Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:37:02 -0700 Subject: [PATCH 0553/9938] staging: comedi: ni_tio: fix ni_tio_insn_config() The (*insn_config) functions are supposed to return an errno or the number of 'data' values used for the instruction (insn->n). Currently this function returns an errno or 0. Fix the function to work like the core expects. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 51dd368f788d..10d4585ab25c 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1295,15 +1295,18 @@ int ni_tio_insn_config(struct comedi_device *dev, struct ni_gpct *counter = s->private; unsigned int cidx = counter->counter_index; unsigned int status; + int ret = 0; switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: - return ni_tio_set_counter_mode(counter, data[1]); + ret = ni_tio_set_counter_mode(counter, data[1]); + break; case INSN_CONFIG_ARM: - return ni_tio_arm(counter, true, data[1]); + ret = ni_tio_arm(counter, true, data[1]); + break; case INSN_CONFIG_DISARM: - ni_tio_arm(counter, false, 0); - return 0; + ret = ni_tio_arm(counter, false, 0); + break; case INSN_CONFIG_GET_COUNTER_STATUS: data[1] = 0; status = ni_tio_read(counter, NITIO_SHARED_STATUS_REG(cidx)); @@ -1313,25 +1316,29 @@ int ni_tio_insn_config(struct comedi_device *dev, data[1] |= COMEDI_COUNTER_COUNTING; } data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING; - return 0; + break; case INSN_CONFIG_SET_CLOCK_SRC: - return ni_tio_set_clock_src(counter, data[1], data[2]); + ret = ni_tio_set_clock_src(counter, data[1], data[2]); + break; case INSN_CONFIG_GET_CLOCK_SRC: ni_tio_get_clock_src(counter, &data[1], &data[2]); - return 0; + break; case INSN_CONFIG_SET_GATE_SRC: - return ni_tio_set_gate_src(counter, data[1], data[2]); + ret = ni_tio_set_gate_src(counter, data[1], data[2]); + break; case INSN_CONFIG_GET_GATE_SRC: - return ni_tio_get_gate_src(counter, data[1], &data[2]); + ret = ni_tio_get_gate_src(counter, data[1], &data[2]); + break; case INSN_CONFIG_SET_OTHER_SRC: - return ni_tio_set_other_src(counter, data[1], data[2]); + ret = ni_tio_set_other_src(counter, data[1], data[2]); + break; case INSN_CONFIG_RESET: ni_tio_reset_count_and_disarm(counter); - return 0; - default: break; + default: + return -EINVAL; } - return -EINVAL; + return ret ? ret : insn->n; } EXPORT_SYMBOL_GPL(ni_tio_insn_config); -- GitLab From fa74d136fda8512a17918fc5f97a72acd05c22e3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:37:03 -0700 Subject: [PATCH 0554/9938] staging: comedi: ni_tio: remove BUG() in ni_tio_set_gate_src() This BUG() can never happen. The previous ni_tio_has_gate2_registers() check will have already caused the function to return -EINVAL. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 10d4585ab25c..9ce3a9a92a9a 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1020,8 +1020,7 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, case ni_gpct_variant_660x: return ni_660x_set_gate2(counter, src); default: - BUG(); - break; + return -EINVAL; } break; default: -- GitLab From b42ca86ad605eb3e3f26618eed35ac6ff7435964 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 23 Mar 2016 15:37:04 -0700 Subject: [PATCH 0555/9938] staging: comedi: ni_tio: remove BUG() checks for ni_tio_get_clock_src() This function calls some helper functions to convert the counter variant specific clock select bits into the generic enum ni_gpct_clock_source_bits equivelent. These helper functions currently BUG() if the clock select bits are invalid. It then calls ni_tio_clock_period_ps() to figure out the clock period based on the generic clock source. This function could also BUG() if the prescale bits are invalid. In reality this should never happen but refactor the code to return -EINVAL instead and remove the BUG() checks. These functions are also called by ni_tio_set_sync_mode(). When this function is called by ni_tio_set_clock_src() the counter select bits have already been validated. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 60 ++++++++++++++----------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 9ce3a9a92a9a..7043eb0543f6 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -183,8 +183,9 @@ static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) ni_tio_write(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx)); } -static u64 ni_tio_clock_period_ps(const struct ni_gpct *counter, - unsigned int generic_clock_source) +static int ni_tio_clock_period_ps(const struct ni_gpct *counter, + unsigned int generic_clock_source, + u64 *period_ps) { u64 clock_period_ps; @@ -219,10 +220,10 @@ static u64 ni_tio_clock_period_ps(const struct ni_gpct *counter, clock_period_ps *= 8; break; default: - BUG(); - break; + return -EINVAL; } - return clock_period_ps; + *period_ps = clock_period_ps; + return 0; } static void ni_tio_set_bits_transient(struct ni_gpct *counter, @@ -304,7 +305,8 @@ static unsigned int ni_tio_clock_src_modifiers(const struct ni_gpct *counter) return bits; } -static unsigned int ni_m_series_clock_src_select(const struct ni_gpct *counter) +static int ni_m_series_clock_src_select(const struct ni_gpct *counter, + unsigned int *clk_src) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned int cidx = counter->counter_index; @@ -362,14 +364,15 @@ static unsigned int ni_m_series_clock_src_select(const struct ni_gpct *counter) } if (i <= NI_M_MAX_PFI_CHAN) break; - BUG(); - break; + return -EINVAL; } clock_source |= ni_tio_clock_src_modifiers(counter); - return clock_source; + *clk_src = clock_source; + return 0; } -static unsigned int ni_660x_clock_src_select(const struct ni_gpct *counter) +static int ni_660x_clock_src_select(const struct ni_gpct *counter, + unsigned int *clk_src) { unsigned int clock_source = 0; unsigned int cidx = counter->counter_index; @@ -419,23 +422,23 @@ static unsigned int ni_660x_clock_src_select(const struct ni_gpct *counter) } if (i <= NI_660X_MAX_SRC_PIN) break; - BUG(); - break; + return -EINVAL; } clock_source |= ni_tio_clock_src_modifiers(counter); - return clock_source; + *clk_src = clock_source; + return 0; } -static unsigned int -ni_tio_generic_clock_src_select(const struct ni_gpct *counter) +static int ni_tio_generic_clock_src_select(const struct ni_gpct *counter, + unsigned int *clk_src) { switch (counter->counter_dev->variant) { case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: default: - return ni_m_series_clock_src_select(counter); + return ni_m_series_clock_src_select(counter, clk_src); case ni_gpct_variant_660x: - return ni_660x_clock_src_select(counter); + return ni_660x_clock_src_select(counter, clk_src); } } @@ -448,6 +451,7 @@ static void ni_tio_set_sync_mode(struct ni_gpct *counter) unsigned int bits = 0; unsigned int reg; unsigned int mode; + unsigned int clk_src; u64 ps; bool force_alt_sync; @@ -478,8 +482,8 @@ static void ni_tio_set_sync_mode(struct ni_gpct *counter) break; } - ps = ni_tio_clock_period_ps(counter, - ni_tio_generic_clock_src_select(counter)); + ni_tio_generic_clock_src_select(counter, &clk_src); + ni_tio_clock_period_ps(counter, clk_src, &ps); /* * It's not clear what we should do if clock_period is unknown, so we @@ -800,16 +804,22 @@ static int ni_tio_set_clock_src(struct ni_gpct *counter, return 0; } -static void ni_tio_get_clock_src(struct ni_gpct *counter, - unsigned int *clock_source, - unsigned int *period_ns) +static int ni_tio_get_clock_src(struct ni_gpct *counter, + unsigned int *clock_source, + unsigned int *period_ns) { u64 temp64; + int ret; - *clock_source = ni_tio_generic_clock_src_select(counter); - temp64 = ni_tio_clock_period_ps(counter, *clock_source); + ret = ni_tio_generic_clock_src_select(counter, clock_source); + if (ret) + return ret; + ret = ni_tio_clock_period_ps(counter, *clock_source, &temp64); + if (ret) + return ret; do_div(temp64, 1000); /* ps to ns */ *period_ns = temp64; + return 0; } static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source) @@ -1320,7 +1330,7 @@ int ni_tio_insn_config(struct comedi_device *dev, ret = ni_tio_set_clock_src(counter, data[1], data[2]); break; case INSN_CONFIG_GET_CLOCK_SRC: - ni_tio_get_clock_src(counter, &data[1], &data[2]); + ret = ni_tio_get_clock_src(counter, &data[1], &data[2]); break; case INSN_CONFIG_SET_GATE_SRC: ret = ni_tio_set_gate_src(counter, data[1], data[2]); -- GitLab From ff59f2a6d44e4c96cd56e8b12c5678ef85a3b576 Mon Sep 17 00:00:00 2001 From: Okash Khawaja Date: Thu, 10 Mar 2016 20:21:35 +0000 Subject: [PATCH 0556/9938] staging: speakup: fix type mismatch warnings Compiling speakup driver with sparse produces following warning: drivers/staging/speakup/serialio.c:22:9: warning: incorrect type in initializer (different base types) drivers/staging/speakup/serialio.c:22:9: expected unsigned int [unsigned] flags drivers/staging/speakup/serialio.c:22:9: got restricted upf_t This patch fixes it. Signed-off-by: Okash Khawaja Acked-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/serialio.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/speakup/serialio.h b/drivers/staging/speakup/serialio.h index 1b399214ecf7..3ad7ff0bc3c3 100644 --- a/drivers/staging/speakup/serialio.h +++ b/drivers/staging/speakup/serialio.h @@ -6,6 +6,7 @@ #ifndef __sparc__ #include #endif +#include /* * this is cut&paste from 8250.h. Get rid of the structure, the definitions @@ -16,7 +17,7 @@ struct old_serial_port { unsigned int baud_base; unsigned int port; unsigned int irq; - unsigned int flags; /* unused */ + upf_t flags; /* unused */ }; /* countdown values for serial timeouts in us */ -- GitLab From 29efdd3d68fe91f5921e27bce79017e46a5fd57c Mon Sep 17 00:00:00 2001 From: PrasannaKumar Muralidharan Date: Wed, 23 Mar 2016 12:58:28 +0530 Subject: [PATCH 0557/9938] Staging: most: Remove __cplusplus check in header files Remove unnecessary __cplusplus check in header files as it is not required. Signed-off-by: PrasannaKumar Muralidharan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-dim2/dim2_errors.h | 8 -------- drivers/staging/most/hdm-dim2/dim2_hal.h | 8 -------- drivers/staging/most/hdm-dim2/dim2_reg.h | 8 -------- 3 files changed, 24 deletions(-) diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h index 5a713df1d1d4..66343ba426c1 100644 --- a/drivers/staging/most/hdm-dim2/dim2_errors.h +++ b/drivers/staging/most/hdm-dim2/dim2_errors.h @@ -15,10 +15,6 @@ #ifndef _MOST_DIM_ERRORS_H #define _MOST_DIM_ERRORS_H -#ifdef __cplusplus -extern "C" { -#endif - /** * MOST DIM errors. */ @@ -58,8 +54,4 @@ enum dim_errors_t { DIM_ERR_OVERFLOW, }; -#ifdef __cplusplus -} -#endif - #endif /* _MOST_DIM_ERRORS_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 9f8e88028181..1c924e869de7 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -18,10 +18,6 @@ #include #include "dim2_reg.h" -#ifdef __cplusplus -extern "C" { -#endif - /* * The values below are specified in the hardware specification. * So, they should not be changed until the hardware specification changes. @@ -108,8 +104,4 @@ void dimcb_io_write(u32 __iomem *ptr32, u32 value); void dimcb_on_error(u8 error_id, const char *error_message); -#ifdef __cplusplus -} -#endif - #endif /* _DIM2_HAL_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h index bcf6a79f6744..e0837b6b9ae1 100644 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ b/drivers/staging/most/hdm-dim2/dim2_reg.h @@ -17,10 +17,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - struct dim2_regs { /* 0x00 */ u32 MLBC0; /* 0x01 */ u32 rsvd0[1]; @@ -166,8 +162,4 @@ enum { CAT_CL_MASK = DIM2_MASK(6) }; -#ifdef __cplusplus -} -#endif - #endif /* DIM2_OS62420_H */ -- GitLab From 87787e5ef727ff15f7c552cc48823b469f2eb41b Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Wed, 23 Mar 2016 12:06:34 +0100 Subject: [PATCH 0558/9938] Staging: iio: Fix sparse endian warning Fix following sparse warning: warning: cast to restricted __be16 Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7606_spi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index d873a5164595..825da0769936 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -21,7 +21,8 @@ static int ad7606_spi_read_block(struct device *dev, { struct spi_device *spi = to_spi_device(dev); int i, ret; - unsigned short *data = buf; + unsigned short *data; + __be16 *bdata = buf; ret = spi_read(spi, buf, count * 2); if (ret < 0) { @@ -30,7 +31,7 @@ static int ad7606_spi_read_block(struct device *dev, } for (i = 0; i < count; i++) - data[i] = be16_to_cpu(data[i]); + data[i] = be16_to_cpu(bdata[i]); return 0; } -- GitLab From 80e3e241fa56312f7a837b7e4781ecffed0b8db6 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Wed, 23 Mar 2016 20:54:36 +0900 Subject: [PATCH 0559/9938] staging: dgnc: fix CamelCase in dgnc_driver.c fix checkpatch.pl warning about CamelCase. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_driver.c | 52 +++++++++++++++--------------- drivers/staging/dgnc/dgnc_driver.h | 6 ++-- drivers/staging/dgnc/dgnc_mgmt.c | 28 ++++++++-------- drivers/staging/dgnc/dgnc_sysfs.c | 2 +- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 4eb410e09609..af2e835efa1b 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -48,7 +48,7 @@ static void dgnc_do_remap(struct dgnc_board *brd); /* * File operations permitted on Control/Management major. */ -static const struct file_operations dgnc_BoardFops = { +static const struct file_operations dgnc_board_fops = { .owner = THIS_MODULE, .unlocked_ioctl = dgnc_mgmt_ioctl, .open = dgnc_mgmt_open, @@ -58,11 +58,11 @@ static const struct file_operations dgnc_BoardFops = { /* * Globals */ -uint dgnc_NumBoards; -struct dgnc_board *dgnc_Board[MAXBOARDS]; +uint dgnc_num_boards; +struct dgnc_board *dgnc_board[MAXBOARDS]; DEFINE_SPINLOCK(dgnc_global_lock); DEFINE_SPINLOCK(dgnc_poll_lock); /* Poll scheduling lock */ -uint dgnc_Major; +uint dgnc_major; int dgnc_poll_tick = 20; /* Poll interval - 20 ms */ /* @@ -92,7 +92,7 @@ struct board_id { unsigned int is_pci_express; }; -static struct board_id dgnc_Ids[] = { +static struct board_id dgnc_ids[] = { { PCI_DEVICE_CLASSIC_4_PCI_NAME, 4, 0 }, { PCI_DEVICE_CLASSIC_4_422_PCI_NAME, 4, 0 }, { PCI_DEVICE_CLASSIC_8_PCI_NAME, 8, 0 }, @@ -140,14 +140,14 @@ static void cleanup(bool sysfiles) if (sysfiles) dgnc_remove_driver_sysfiles(&dgnc_driver); - device_destroy(dgnc_class, MKDEV(dgnc_Major, 0)); + device_destroy(dgnc_class, MKDEV(dgnc_major, 0)); class_destroy(dgnc_class); - unregister_chrdev(dgnc_Major, "dgnc"); + unregister_chrdev(dgnc_major, "dgnc"); - for (i = 0; i < dgnc_NumBoards; ++i) { - dgnc_remove_ports_sysfiles(dgnc_Board[i]); - dgnc_tty_uninit(dgnc_Board[i]); - dgnc_cleanup_board(dgnc_Board[i]); + for (i = 0; i < dgnc_num_boards; ++i) { + dgnc_remove_ports_sysfiles(dgnc_board[i]); + dgnc_tty_uninit(dgnc_board[i]); + dgnc_cleanup_board(dgnc_board[i]); } dgnc_tty_post_uninit(); @@ -217,12 +217,12 @@ static int dgnc_start(void) * * Register management/dpa devices */ - rc = register_chrdev(0, "dgnc", &dgnc_BoardFops); + rc = register_chrdev(0, "dgnc", &dgnc_board_fops); if (rc < 0) { pr_err(DRVSTR ": Can't register dgnc driver device (%d)\n", rc); return rc; } - dgnc_Major = rc; + dgnc_major = rc; dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt"); if (IS_ERR(dgnc_class)) { @@ -232,7 +232,7 @@ static int dgnc_start(void) } dev = device_create(dgnc_class, NULL, - MKDEV(dgnc_Major, 0), + MKDEV(dgnc_major, 0), NULL, "dgnc_mgmt"); if (IS_ERR(dev)) { rc = PTR_ERR(dev); @@ -262,11 +262,11 @@ static int dgnc_start(void) return 0; failed_tty: - device_destroy(dgnc_class, MKDEV(dgnc_Major, 0)); + device_destroy(dgnc_class, MKDEV(dgnc_major, 0)); failed_device: class_destroy(dgnc_class); failed_class: - unregister_chrdev(dgnc_Major, "dgnc"); + unregister_chrdev(dgnc_major, "dgnc"); return rc; } @@ -283,7 +283,7 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = dgnc_found_board(pdev, ent->driver_data); if (rc == 0) - dgnc_NumBoards++; + dgnc_num_boards++; return rc; } @@ -346,7 +346,7 @@ static void dgnc_cleanup_board(struct dgnc_board *brd) } } - dgnc_Board[brd->boardnum] = NULL; + dgnc_board[brd->boardnum] = NULL; kfree(brd); } @@ -365,8 +365,8 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) unsigned long flags; /* get the board structure and prep it */ - dgnc_Board[dgnc_NumBoards] = kzalloc(sizeof(*brd), GFP_KERNEL); - brd = dgnc_Board[dgnc_NumBoards]; + dgnc_board[dgnc_num_boards] = kzalloc(sizeof(*brd), GFP_KERNEL); + brd = dgnc_board[dgnc_num_boards]; if (!brd) return -ENOMEM; @@ -382,15 +382,15 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) /* store the info for the board we've found */ brd->magic = DGNC_BOARD_MAGIC; - brd->boardnum = dgnc_NumBoards; + brd->boardnum = dgnc_num_boards; brd->vendor = dgnc_pci_tbl[id].vendor; brd->device = dgnc_pci_tbl[id].device; brd->pdev = pdev; brd->pci_bus = pdev->bus->number; brd->pci_slot = PCI_SLOT(pdev->devfn); - brd->name = dgnc_Ids[id].name; - brd->maxports = dgnc_Ids[id].maxports; - if (dgnc_Ids[i].is_pci_express) + brd->name = dgnc_ids[id].name; + brd->maxports = dgnc_ids[id].maxports; + if (dgnc_ids[i].is_pci_express) brd->bd_flags |= BD_IS_PCI_EXPRESS; brd->dpastatus = BD_NOFEP; init_waitqueue_head(&brd->state_wait); @@ -642,8 +642,8 @@ static void dgnc_poll_handler(ulong dummy) unsigned long new_time; /* Go thru each board, kicking off a tasklet for each if needed */ - for (i = 0; i < dgnc_NumBoards; i++) { - brd = dgnc_Board[i]; + for (i = 0; i < dgnc_num_boards; i++) { + brd = dgnc_board[i]; spin_lock_irqsave(&brd->bd_lock, flags); diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 953c891d4064..f3d00dfd2326 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -399,12 +399,12 @@ struct channel_t { /* * Our Global Variables. */ -extern uint dgnc_Major; /* Our driver/mgmt major */ +extern uint dgnc_major; /* Our driver/mgmt major */ extern int dgnc_poll_tick; /* Poll interval - 20 ms */ extern spinlock_t dgnc_global_lock; /* Driver global spinlock */ extern spinlock_t dgnc_poll_lock; /* Poll scheduling lock */ -extern uint dgnc_NumBoards; /* Total number of boards */ -extern struct dgnc_board *dgnc_Board[MAXBOARDS]; /* Array of board +extern uint dgnc_num_boards; /* Total number of boards */ +extern struct dgnc_board *dgnc_board[MAXBOARDS]; /* Array of board * structs */ diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c index ba29a8d913f2..683c098391d9 100644 --- a/drivers/staging/dgnc/dgnc_mgmt.c +++ b/drivers/staging/dgnc/dgnc_mgmt.c @@ -111,7 +111,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) spin_lock_irqsave(&dgnc_global_lock, flags); memset(&ddi, 0, sizeof(ddi)); - ddi.dinfo_nboards = dgnc_NumBoards; + ddi.dinfo_nboards = dgnc_num_boards; sprintf(ddi.dinfo_version, "%s", DG_PART); spin_unlock_irqrestore(&dgnc_global_lock, flags); @@ -131,27 +131,27 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (copy_from_user(&brd, uarg, sizeof(int))) return -EFAULT; - if (brd < 0 || brd >= dgnc_NumBoards) + if (brd < 0 || brd >= dgnc_num_boards) return -ENODEV; memset(&di, 0, sizeof(di)); di.info_bdnum = brd; - spin_lock_irqsave(&dgnc_Board[brd]->bd_lock, flags); + spin_lock_irqsave(&dgnc_board[brd]->bd_lock, flags); - di.info_bdtype = dgnc_Board[brd]->dpatype; - di.info_bdstate = dgnc_Board[brd]->dpastatus; + di.info_bdtype = dgnc_board[brd]->dpatype; + di.info_bdstate = dgnc_board[brd]->dpastatus; di.info_ioport = 0; - di.info_physaddr = (ulong)dgnc_Board[brd]->membase; - di.info_physsize = (ulong)dgnc_Board[brd]->membase - - dgnc_Board[brd]->membase_end; - if (dgnc_Board[brd]->state != BOARD_FAILED) - di.info_nports = dgnc_Board[brd]->nasync; + di.info_physaddr = (ulong)dgnc_board[brd]->membase; + di.info_physsize = (ulong)dgnc_board[brd]->membase + - dgnc_board[brd]->membase_end; + if (dgnc_board[brd]->state != BOARD_FAILED) + di.info_nports = dgnc_board[brd]->nasync; else di.info_nports = 0; - spin_unlock_irqrestore(&dgnc_Board[brd]->bd_lock, flags); + spin_unlock_irqrestore(&dgnc_board[brd]->bd_lock, flags); if (copy_to_user(uarg, &di, sizeof(di))) return -EFAULT; @@ -174,14 +174,14 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) channel = ni.channel; /* Verify boundaries on board */ - if (board >= dgnc_NumBoards) + if (board >= dgnc_num_boards) return -ENODEV; /* Verify boundaries on channel */ - if (channel >= dgnc_Board[board]->nasync) + if (channel >= dgnc_board[board]->nasync) return -ENODEV; - ch = dgnc_Board[board]->channels[channel]; + ch = dgnc_board[board]->channels[channel]; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return -ENODEV; diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c index 74a072599126..d825964180bc 100644 --- a/drivers/staging/dgnc/dgnc_sysfs.c +++ b/drivers/staging/dgnc/dgnc_sysfs.c @@ -33,7 +33,7 @@ static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL); static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards); + return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_num_boards); } static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL); -- GitLab From f96b36c779f92328bb1c802e6268609191d4449d Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 23 Mar 2016 20:37:26 +0200 Subject: [PATCH 0560/9938] Staging: wlan-ng: wiphy_free() is not called in case wiphy_register() fails This patch covers wiphy_register() failures in wlan_create_wiphy() from cfg80211.c by calling wiphy_free() for the correspondent struct wiphy allocated structure. Signed-off-by: Claudiu Beznea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8bad018eda47..ee989d1d5715 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -771,8 +771,10 @@ static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES; wiphy->cipher_suites = prism2_cipher_suites; - if (wiphy_register(wiphy) < 0) + if (wiphy_register(wiphy) < 0) { + wiphy_free(wiphy); return NULL; + } return wiphy; } -- GitLab From f72ea988418f3b86d4815f427105c4222622dd41 Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Thu, 24 Mar 2016 01:08:29 +0530 Subject: [PATCH 0561/9938] staging: vt6656: Fixed multiple logical comparisions warnings in main_usb.c Using comparison to false and true is error prone. Fixed multiple warnings as per checkpatch guidelines. Signed-off-by: Parth Sane Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index f9afab77b79f..5e774962e547 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -238,7 +238,7 @@ static int vnt_init_registers(struct vnt_private *priv) priv->tx_antenna_mode = ANT_B; priv->rx_antenna_sel = 1; - if (priv->tx_rx_ant_inv == true) + if (priv->tx_rx_ant_inv) priv->rx_antenna_mode = ANT_A; else priv->rx_antenna_mode = ANT_B; @@ -248,14 +248,14 @@ static int vnt_init_registers(struct vnt_private *priv) if (antenna & EEP_ANTENNA_AUX) { priv->tx_antenna_mode = ANT_A; - if (priv->tx_rx_ant_inv == true) + if (priv->tx_rx_ant_inv) priv->rx_antenna_mode = ANT_B; else priv->rx_antenna_mode = ANT_A; } else { priv->tx_antenna_mode = ANT_B; - if (priv->tx_rx_ant_inv == true) + if (priv->tx_rx_ant_inv) priv->rx_antenna_mode = ANT_A; else priv->rx_antenna_mode = ANT_B; -- GitLab From e7c77e437b7cbb632a3708ea3a3bb270f4fc4677 Mon Sep 17 00:00:00 2001 From: Nicholas Sim Date: Wed, 23 Mar 2016 22:35:39 +0000 Subject: [PATCH 0562/9938] staging: rtl8188eu: remove return at end of void function call Remove unnecessary return statements from last lines of void function call (several) Signed-off-by: Nicholas Sim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 439c035fbb7b..7f32b39e5869 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -601,8 +601,6 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) pattrib->last_txcmdsz = pattrib->pktlen; dump_mgntframe(padapter, pmgntframe); - - return; } static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, bool wait_ack) @@ -883,8 +881,6 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, rtw_wep_encrypt(padapter, (u8 *)pmgntframe); DBG_88E("%s\n", __func__); dump_mgntframe(padapter, pmgntframe); - - return; } @@ -1207,8 +1203,6 @@ static void issue_assocreq(struct adapter *padapter) rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen); else rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len); - - return; } /* when wait_ack is true, this function should be called at process context */ @@ -4326,8 +4320,6 @@ void report_survey_event(struct adapter *padapter, rtw_enqueue_cmd(pcmdpriv, pcmd_obj); pmlmeext->sitesurvey_res.bss_cnt++; - - return; } void report_surveydone_event(struct adapter *padapter) @@ -4371,8 +4363,6 @@ void report_surveydone_event(struct adapter *padapter) DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt); rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; } void report_join_res(struct adapter *padapter, int res) @@ -4423,8 +4413,6 @@ void report_join_res(struct adapter *padapter, int res) rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; } void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) @@ -4480,8 +4468,6 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi DBG_88E("report_del_sta_event: delete STA, mac_id =%d\n", mac_id); rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; } void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx) @@ -4526,8 +4512,6 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int DBG_88E("report_add_sta_event: add STA\n"); rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; } @@ -4963,7 +4947,6 @@ void link_timer_hdl(unsigned long data) issue_assocreq(padapter); set_link_timer(pmlmeext, REASSOC_TO); } - return; } void addba_timer_hdl(unsigned long data) -- GitLab From 26b694323637be61be89d391c1713d85d66b457d Mon Sep 17 00:00:00 2001 From: Nicholas Sim Date: Wed, 23 Mar 2016 23:02:24 +0000 Subject: [PATCH 0563/9938] staging: xgifb: ensure braces on all arms of if stmt Added braces on else arm of if statement where if arm already has braces as suggested for clarity in Documentation/CodingStyle Signed-off-by: Nicholas Sim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index f97c77d88173..14230c293145 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -3450,8 +3450,9 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))) tempbx >>= 1; - } else + } else { tempbx >>= 1; + } } tempbx -= 2; -- GitLab From aaeb5e7f03e97770fe7a0dc122854287ab020f19 Mon Sep 17 00:00:00 2001 From: Nicholas Sim Date: Wed, 23 Mar 2016 23:02:59 +0000 Subject: [PATCH 0564/9938] staging: xgifb: remove extra braces from if stmt (single branch) Remove braces from one branch of if statement where both branches only have a single line of code, as suggested in Documentation/CodingStyle Signed-off-by: Nicholas Sim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 14230c293145..40939c86ab7c 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -3840,9 +3840,9 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex, if (pVBInfo->VGAVDE == 525) { if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV - | VB_XGI301C)) { + | VB_XGI301C)) temp = 0xC6; - } else + else temp = 0xC4; xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp); @@ -3852,9 +3852,9 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex, if (pVBInfo->VGAVDE == 420) { if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV - | VB_XGI301C)) { + | VB_XGI301C)) temp = 0x4F; - } else + else temp = 0x4E; xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp); } -- GitLab From a25ad52020b5cde0121830733890c06d3cc2e656 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Thu, 24 Mar 2016 15:10:43 +0900 Subject: [PATCH 0565/9938] staging: dgnc: fix CamelCase in dgnc_drvier.h and fix checkpatch.pl warning about CamelCase Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_driver.h | 12 +++++------ drivers/staging/dgnc/dgnc_tty.c | 32 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index f3d00dfd2326..3d8e15f9a606 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -203,15 +203,15 @@ struct dgnc_board { */ struct tty_driver serial_driver; - char SerialName[200]; + char serial_name[200]; struct tty_driver print_driver; - char PrintName[200]; + char print_name[200]; - bool dgnc_Major_Serial_Registered; - bool dgnc_Major_TransparentPrint_Registered; + bool dgnc_major_serial_registered; + bool dgnc_major_transparent_print_registered; - uint dgnc_Serial_Major; - uint dgnc_TransparentPrint_Major; + uint dgnc_serial_major; + uint dgnc_transparent_print_major; uint TtyRefCnt; diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 081ac75abc88..98b88d1a5f04 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -180,9 +180,9 @@ int dgnc_tty_register(struct dgnc_board *brd) brd->serial_driver.magic = TTY_DRIVER_MAGIC; - snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum); + snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum); - brd->serial_driver.name = brd->SerialName; + brd->serial_driver.name = brd->serial_name; brd->serial_driver.name_base = 0; brd->serial_driver.major = 0; brd->serial_driver.minor_start = 0; @@ -218,7 +218,7 @@ int dgnc_tty_register(struct dgnc_board *brd) */ tty_set_operations(&brd->serial_driver, &dgnc_tty_ops); - if (!brd->dgnc_Major_Serial_Registered) { + if (!brd->dgnc_major_serial_registered) { /* Register tty devices */ rc = tty_register_driver(&brd->serial_driver); if (rc < 0) { @@ -226,7 +226,7 @@ int dgnc_tty_register(struct dgnc_board *brd) "Can't register tty device (%d)\n", rc); return rc; } - brd->dgnc_Major_Serial_Registered = true; + brd->dgnc_major_serial_registered = true; } /* @@ -235,9 +235,9 @@ int dgnc_tty_register(struct dgnc_board *brd) * we are when we get into the dgnc_tty_open() routine. */ brd->print_driver.magic = TTY_DRIVER_MAGIC; - snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum); + snprintf(brd->print_name, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum); - brd->print_driver.name = brd->PrintName; + brd->print_driver.name = brd->print_name; brd->print_driver.name_base = 0; brd->print_driver.major = brd->serial_driver.major; brd->print_driver.minor_start = 0x80; @@ -273,7 +273,7 @@ int dgnc_tty_register(struct dgnc_board *brd) */ tty_set_operations(&brd->print_driver, &dgnc_tty_ops); - if (!brd->dgnc_Major_TransparentPrint_Registered) { + if (!brd->dgnc_major_transparent_print_registered) { /* Register Transparent Print devices */ rc = tty_register_driver(&brd->print_driver); if (rc < 0) { @@ -282,12 +282,12 @@ int dgnc_tty_register(struct dgnc_board *brd) rc); return rc; } - brd->dgnc_Major_TransparentPrint_Registered = true; + brd->dgnc_major_transparent_print_registered = true; } dgnc_BoardsByMajor[brd->serial_driver.major] = brd; - brd->dgnc_Serial_Major = brd->serial_driver.major; - brd->dgnc_TransparentPrint_Major = brd->print_driver.major; + brd->dgnc_serial_major = brd->serial_driver.major; + brd->dgnc_transparent_print_major = brd->print_driver.major; return rc; } @@ -407,9 +407,9 @@ void dgnc_tty_uninit(struct dgnc_board *brd) { int i = 0; - if (brd->dgnc_Major_Serial_Registered) { + if (brd->dgnc_major_serial_registered) { dgnc_BoardsByMajor[brd->serial_driver.major] = NULL; - brd->dgnc_Serial_Major = 0; + brd->dgnc_serial_major = 0; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> @@ -417,12 +417,12 @@ void dgnc_tty_uninit(struct dgnc_board *brd) tty_unregister_device(&brd->serial_driver, i); } tty_unregister_driver(&brd->serial_driver); - brd->dgnc_Major_Serial_Registered = false; + brd->dgnc_major_serial_registered = false; } - if (brd->dgnc_Major_TransparentPrint_Registered) { + if (brd->dgnc_major_transparent_print_registered) { dgnc_BoardsByMajor[brd->print_driver.major] = NULL; - brd->dgnc_TransparentPrint_Major = 0; + brd->dgnc_transparent_print_major = 0; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> @@ -430,7 +430,7 @@ void dgnc_tty_uninit(struct dgnc_board *brd) tty_unregister_device(&brd->print_driver, i); } tty_unregister_driver(&brd->print_driver); - brd->dgnc_Major_TransparentPrint_Registered = false; + brd->dgnc_major_transparent_print_registered = false; } kfree(brd->serial_driver.ttys); -- GitLab From 195d85c1a0b37c2dd231980528d46100f35f9a0c Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Thu, 24 Mar 2016 15:11:08 +0900 Subject: [PATCH 0566/9938] staging: dgnc: remove unused variable in dgnc_board TtyRefCnt was not used anywhere in dgnc. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_driver.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 3d8e15f9a606..44216aede109 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -213,8 +213,6 @@ struct dgnc_board { uint dgnc_serial_major; uint dgnc_transparent_print_major; - uint TtyRefCnt; - u16 dpatype; /* The board "type", * as defined by DPA */ -- GitLab From 6175e73deeba06365eae1758d964a4e37d8db627 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Fri, 25 Mar 2016 11:44:06 +0900 Subject: [PATCH 0567/9938] staging: dgnc: fix 'line over 80 characters' fix checkpatch.pl warning about 'line over 80 characters' in dgnc_neo.c Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_neo.c | 66 ++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 31ac437cb4a4..10b596fb4681 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -77,7 +77,8 @@ struct board_ops dgnc_neo_ops = { .send_immediate_char = neo_send_immediate_char }; -static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; +static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, + 0x10, 0x20, 0x40, 0x80 }; /* * This function allows calls to ensure that all outstanding @@ -116,7 +117,8 @@ static inline void neo_set_cts_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr); + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), + &ch->ch_neo_uart->fctr); /* Feed the UART our trigger levels */ writeb(8, &ch->ch_neo_uart->tfifo); @@ -150,7 +152,8 @@ static inline void neo_set_rts_flow_control(struct channel_t *ch) /* Turn on UART enhanced bits */ writeb(efr, &ch->ch_neo_uart->efr); - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr); + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), + &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 4; writeb(32, &ch->ch_neo_uart->rfifo); @@ -187,7 +190,8 @@ static inline void neo_set_ixon_flow_control(struct channel_t *ch) /* Turn on UART enhanced bits */ writeb(efr, &ch->ch_neo_uart->efr); - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), + &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 4; writeb(32, &ch->ch_neo_uart->rfifo); @@ -225,7 +229,8 @@ static inline void neo_set_ixoff_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), + &ch->ch_neo_uart->fctr); writeb(8, &ch->ch_neo_uart->tfifo); ch->ch_t_tlevel = 8; @@ -265,7 +270,8 @@ static inline void neo_set_no_input_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), + &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 0; @@ -302,7 +308,8 @@ static inline void neo_set_no_output_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), + &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 0; @@ -321,7 +328,8 @@ static inline void neo_set_no_output_flow_control(struct channel_t *ch) static inline void neo_set_new_start_stop_chars(struct channel_t *ch) { /* if hardware flow control is set, then skip this whole thing */ - if (ch->ch_digi.digi_flags & (CTSPACE | RTSPACE) || ch->ch_c_cflag & CRTSCTS) + if (ch->ch_digi.digi_flags & (CTSPACE | RTSPACE) || + ch->ch_c_cflag & CRTSCTS) return; /* Tell UART what start/stop chars it should be looking for */ @@ -393,7 +401,8 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) break; /* - * Yank off the upper 2 bits, which just show that the FIFO's are enabled. + * Yank off the upper 2 bits, + * which just show that the FIFO's are enabled. */ isr &= ~(UART_17158_IIR_FIFO_ENABLED); @@ -666,7 +675,8 @@ static void neo_param(struct tty_struct *tty) }; /* Only use the TXPrint baud rate if the terminal unit is NOT open */ - if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT)) + if (!(ch->ch_tun.un_flags & UN_ISOPEN) && + (un->un_type == DGNC_PRINT)) baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; else baud = C_BAUD(ch->ch_tun.un_tty) & 0xff; @@ -679,7 +689,8 @@ static void neo_param(struct tty_struct *tty) jindex = baud; - if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) + if ((iindex >= 0) && (iindex < 4) && + (jindex >= 0) && (jindex < 16)) baud = bauds[iindex][jindex]; else baud = 0; @@ -787,7 +798,8 @@ static void neo_param(struct tty_struct *tty) neo_set_cts_flow_control(ch); } else if (ch->ch_c_iflag & IXON) { /* If start/stop is set to disable, then we should disable flow control */ - if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) + if ((ch->ch_startc == _POSIX_VDISABLE) || + (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_output_flow_control(ch); else neo_set_ixon_flow_control(ch); @@ -799,7 +811,8 @@ static void neo_param(struct tty_struct *tty) neo_set_rts_flow_control(ch); } else if (ch->ch_c_iflag & IXOFF) { /* If start/stop is set to disable, then we should disable flow control */ - if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) + if ((ch->ch_startc == _POSIX_VDISABLE) || + (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_input_flow_control(ch); else neo_set_ixoff_flow_control(ch); @@ -1172,7 +1185,8 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) linestatus = 0; /* Copy data from uart to the queue */ - memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n); + memcpy_fromio(ch->ch_rqueue + head, + &ch->ch_neo_uart->txrxburst, n); /* * Since RX_FIFO_DATA_ERROR was 0, we are guaranteed @@ -1225,7 +1239,8 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) * we don't miss our TX FIFO emptys. */ if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) { - linestatus &= ~(UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR); + linestatus &= ~(UART_LSR_THRE | + UART_17158_TX_AND_FIFO_CLR); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); } @@ -1255,7 +1270,8 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) qleft++; } - memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1); + memcpy_fromio(ch->ch_rqueue + head, + &ch->ch_neo_uart->txrxburst, 1); ch->ch_equeue[head] = (unsigned char)linestatus; /* Ditch any remaining linestatus value. */ @@ -1328,7 +1344,8 @@ static void neo_flush_uart_write(struct channel_t *ch) if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr); + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), + &ch->ch_neo_uart->isr_fcr); neo_pci_posting_flush(ch->ch_bd); for (i = 0; i < 10; i++) { @@ -1356,7 +1373,8 @@ static void neo_flush_uart_read(struct channel_t *ch) if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr); + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), + &ch->ch_neo_uart->isr_fcr); neo_pci_posting_flush(ch->ch_bd); for (i = 0; i < 10; i++) { @@ -1427,7 +1445,8 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) ch->ch_tun.un_flags |= (UN_EMPTY); } - writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx); + writeb(ch->ch_wqueue[ch->ch_w_tail], + &ch->ch_neo_uart->txrx); ch->ch_w_tail++; ch->ch_w_tail &= WQUEUEMASK; ch->ch_txcount++; @@ -1494,7 +1513,8 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) ch->ch_tun.un_flags |= (UN_EMPTY); } - memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s); + memcpy_toio(&ch->ch_neo_uart->txrxburst, + ch->ch_wqueue + tail, s); /* Add and flip queue if needed */ tail = (tail + s) & WQUEUEMASK; @@ -1628,7 +1648,8 @@ static void neo_uart_init(struct channel_t *ch) /* Clear out UART and FIFO */ readb(&ch->ch_neo_uart->txrx); - writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr); + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + &ch->ch_neo_uart->isr_fcr); readb(&ch->ch_neo_uart->lsr); readb(&ch->ch_neo_uart->msr); @@ -1725,7 +1746,8 @@ static void neo_send_immediate_char(struct channel_t *ch, unsigned char c) neo_pci_posting_flush(ch->ch_bd); } -static unsigned int neo_read_eeprom(unsigned char __iomem *base, unsigned int address) +static unsigned int neo_read_eeprom(unsigned char __iomem *base, + unsigned int address) { unsigned int enable; unsigned int bits; -- GitLab From 318723e4ff367f2c0b15eee534ed2854628d292a Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Fri, 25 Mar 2016 11:44:34 +0900 Subject: [PATCH 0568/9938] staging: dgnc: fix Logical continuations should be on the fix checkpatch.pl warning about 'Logical continuations should be on the previous line' in dgnc_neo.c file. I think the 'force' need to check first, because if the 'force' is true, it doesn't need to call another function call. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_neo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 10b596fb4681..d732e6e99408 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -359,8 +359,8 @@ static inline void neo_clear_break(struct channel_t *ch, int force) /* Turn break off, and unset some variables */ if (ch->ch_flags & CH_BREAK_SENDING) { - if (time_after_eq(jiffies, ch->ch_stop_sending_break) - || force) { + if (force || + time_after_eq(jiffies, ch->ch_stop_sending_break)) { unsigned char temp = readb(&ch->ch_neo_uart->lcr); writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr); -- GitLab From 7dffc87f2eea9f80889d2eb87bfbe63e51b9709c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 18 Mar 2016 13:25:43 -0400 Subject: [PATCH 0569/9938] reiserfs_cache_default_acl(): use get_acl() Signed-off-by: Al Viro --- fs/reiserfs/xattr_acl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 558a16beaacb..ec74bbedc873 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -370,7 +370,7 @@ int reiserfs_cache_default_acl(struct inode *inode) if (IS_PRIVATE(inode)) return 0; - acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); + acl = get_acl(inode, ACL_TYPE_DEFAULT); if (acl && !IS_ERR(acl)) { int size = reiserfs_acl_size(acl->a_count); -- GitLab From 8861964f4c7caecbacc89bcb6b513b40cf097a02 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 24 Mar 2016 14:38:36 +0100 Subject: [PATCH 0570/9938] jfs: Remove unnecessary code in jfs_get_acl The get_acl inode operation is called only when no ACL is cached. It makes no sense to check for a cached ACL as the first thing inside such inode operations. Signed-off-by: Andreas Gruenbacher Signed-off-by: Al Viro --- fs/jfs/acl.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 49456853e9de..ab4882801b24 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -34,10 +34,6 @@ struct posix_acl *jfs_get_acl(struct inode *inode, int type) int size; char *value = NULL; - acl = get_cached_acl(inode, type); - if (acl != ACL_NOT_CACHED) - return acl; - switch(type) { case ACL_TYPE_ACCESS: ea_name = XATTR_NAME_POSIX_ACL_ACCESS; -- GitLab From 2da62906b1e298695e1bb725927041cd59942c98 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 14 Mar 2015 21:13:46 -0400 Subject: [PATCH 0571/9938] [net] drop 'size' argument of sock_recvmsg() all callers have it equal to msg_data_left(msg). Signed-off-by: Al Viro --- drivers/target/iscsi/iscsi_target_util.c | 5 ++--- include/linux/net.h | 3 +-- net/socket.c | 23 ++++++++++------------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 428b0d9e3dba..57720385a751 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -1283,9 +1283,8 @@ static int iscsit_do_rx_data( iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, count->iov, count->iov_count, data); - while (total_rx < data) { - rx_loop = sock_recvmsg(conn->sock, &msg, - (data - total_rx), MSG_WAITALL); + while (msg_data_left(&msg)) { + rx_loop = sock_recvmsg(conn->sock, &msg, MSG_WAITALL); if (rx_loop <= 0) { pr_debug("rx_loop: %d total_rx: %d\n", rx_loop, total_rx); diff --git a/include/linux/net.h b/include/linux/net.h index 49175e4ced11..72c1e0622ce2 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -218,8 +218,7 @@ int sock_create_lite(int family, int type, int proto, struct socket **res); struct socket *sock_alloc(void); void sock_release(struct socket *sock); int sock_sendmsg(struct socket *sock, struct msghdr *msg); -int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, - int flags); +int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags); struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname); struct socket *sockfd_lookup(int fd, int *err); struct socket *sock_from_file(struct file *file, int *err); diff --git a/net/socket.c b/net/socket.c index 5f77a8e93830..956426e347af 100644 --- a/net/socket.c +++ b/net/socket.c @@ -709,17 +709,16 @@ void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, - size_t size, int flags) + int flags) { - return sock->ops->recvmsg(sock, msg, size, flags); + return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags); } -int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, - int flags) +int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags) { - int err = security_socket_recvmsg(sock, msg, size, flags); + int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags); - return err ?: sock_recvmsg_nosec(sock, msg, size, flags); + return err ?: sock_recvmsg_nosec(sock, msg, flags); } EXPORT_SYMBOL(sock_recvmsg); @@ -746,7 +745,7 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg, iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size); set_fs(KERNEL_DS); - result = sock_recvmsg(sock, msg, size, flags); + result = sock_recvmsg(sock, msg, flags); set_fs(oldfs); return result; } @@ -796,7 +795,7 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) if (!iov_iter_count(to)) /* Match SYS5 behaviour */ return 0; - res = sock_recvmsg(sock, &msg, iov_iter_count(to), msg.msg_flags); + res = sock_recvmsg(sock, &msg, msg.msg_flags); *to = msg.msg_iter; return res; } @@ -1696,7 +1695,7 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, msg.msg_iocb = NULL; if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags); + err = sock_recvmsg(sock, &msg, flags); if (err >= 0 && addr != NULL) { err2 = move_addr_to_user(&address, @@ -2073,7 +2072,7 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; unsigned long cmsg_ptr; - int total_len, len; + int len; ssize_t err; /* kernel mode address */ @@ -2091,7 +2090,6 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov); if (err < 0) return err; - total_len = iov_iter_count(&msg_sys->msg_iter); cmsg_ptr = (unsigned long)msg_sys->msg_control; msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); @@ -2101,8 +2099,7 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; - err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, - total_len, flags); + err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags); if (err < 0) goto out_freeiov; len = err; -- GitLab From 16c568efff82e4a6a75d2bd86576e648fad8a7fe Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 12 Nov 2015 22:46:49 -0500 Subject: [PATCH 0572/9938] cifs: merge the hash calculation helpers three practically identical copies... Signed-off-by: Al Viro --- fs/cifs/cifsencrypt.c | 97 ++++++++++++++++++++---------------- fs/cifs/cifsproto.h | 3 ++ fs/cifs/smb2transport.c | 107 ++++------------------------------------ 3 files changed, 67 insertions(+), 140 deletions(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 4897dacf8944..6aeb8d4616a4 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -66,45 +66,15 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) return 0; } -/* - * Calculate and return the CIFS signature based on the mac key and SMB PDU. - * The 16 byte signature must be allocated by the caller. Note we only use the - * 1st eight bytes and that the smb header signature field on input contains - * the sequence number before this function is called. Also, this function - * should be called with the server->srv_mutex held. - */ -static int cifs_calc_signature(struct smb_rqst *rqst, - struct TCP_Server_Info *server, char *signature) +int __cifs_calc_signature(struct smb_rqst *rqst, + struct TCP_Server_Info *server, char *signature, + struct shash_desc *shash) { int i; int rc; struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; - if (iov == NULL || signature == NULL || server == NULL) - return -EINVAL; - - if (!server->secmech.sdescmd5) { - rc = cifs_crypto_shash_md5_allocate(server); - if (rc) { - cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); - return -1; - } - } - - rc = crypto_shash_init(&server->secmech.sdescmd5->shash); - if (rc) { - cifs_dbg(VFS, "%s: Could not init md5\n", __func__); - return rc; - } - - rc = crypto_shash_update(&server->secmech.sdescmd5->shash, - server->session_key.response, server->session_key.len); - if (rc) { - cifs_dbg(VFS, "%s: Could not update with response\n", __func__); - return rc; - } - for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; @@ -117,12 +87,10 @@ static int cifs_calc_signature(struct smb_rqst *rqst, if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ - rc = - crypto_shash_update(&server->secmech.sdescmd5->shash, + rc = crypto_shash_update(shash, iov[i].iov_base + 4, iov[i].iov_len - 4); } else { - rc = - crypto_shash_update(&server->secmech.sdescmd5->shash, + rc = crypto_shash_update(shash, iov[i].iov_base, iov[i].iov_len); } if (rc) { @@ -134,21 +102,64 @@ static int cifs_calc_signature(struct smb_rqst *rqst, /* now hash over the rq_pages array */ for (i = 0; i < rqst->rq_npages; i++) { - struct kvec p_iov; + void *kaddr = kmap(rqst->rq_pages[i]); + size_t len = rqst->rq_pagesz; + + if (i == rqst->rq_npages - 1) + len = rqst->rq_tailsz; + + crypto_shash_update(shash, kaddr, len); - cifs_rqst_page_to_kvec(rqst, i, &p_iov); - crypto_shash_update(&server->secmech.sdescmd5->shash, - p_iov.iov_base, p_iov.iov_len); kunmap(rqst->rq_pages[i]); } - rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); + rc = crypto_shash_final(shash, signature); if (rc) - cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); + cifs_dbg(VFS, "%s: Could not generate hash\n", __func__); return rc; } +/* + * Calculate and return the CIFS signature based on the mac key and SMB PDU. + * The 16 byte signature must be allocated by the caller. Note we only use the + * 1st eight bytes and that the smb header signature field on input contains + * the sequence number before this function is called. Also, this function + * should be called with the server->srv_mutex held. + */ +static int cifs_calc_signature(struct smb_rqst *rqst, + struct TCP_Server_Info *server, char *signature) +{ + int rc; + + if (!rqst->rq_iov || !signature || !server) + return -EINVAL; + + if (!server->secmech.sdescmd5) { + rc = cifs_crypto_shash_md5_allocate(server); + if (rc) { + cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); + return -1; + } + } + + rc = crypto_shash_init(&server->secmech.sdescmd5->shash); + if (rc) { + cifs_dbg(VFS, "%s: Could not init md5\n", __func__); + return rc; + } + + rc = crypto_shash_update(&server->secmech.sdescmd5->shash, + server->session_key.response, server->session_key.len); + if (rc) { + cifs_dbg(VFS, "%s: Could not update with response\n", __func__); + return rc; + } + + return __cifs_calc_signature(rqst, server, signature, + &server->secmech.sdescmd5->shash); +} + /* must be called with server->srv_mutex held */ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index eed7ff50faf0..d9b4f444fdf9 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -512,4 +512,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const unsigned char *path, char *pbuf, unsigned int *pbytes_written); +int __cifs_calc_signature(struct smb_rqst *rqst, + struct TCP_Server_Info *server, char *signature, + struct shash_desc *shash); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 8732a43b1008..bc9a7b634643 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -135,11 +135,10 @@ smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) int smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { - int i, rc; + int rc; unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; unsigned char *sigptr = smb2_signature; struct kvec *iov = rqst->rq_iov; - int n_vec = rqst->rq_nvec; struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct cifs_ses *ses; @@ -171,53 +170,11 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) return rc; } - for (i = 0; i < n_vec; i++) { - if (iov[i].iov_len == 0) - continue; - if (iov[i].iov_base == NULL) { - cifs_dbg(VFS, "null iovec entry\n"); - return -EIO; - } - /* - * The first entry includes a length field (which does not get - * signed that occupies the first 4 bytes before the header). - */ - if (i == 0) { - if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ - break; /* nothing to sign or corrupt header */ - rc = - crypto_shash_update( - &server->secmech.sdeschmacsha256->shash, - iov[i].iov_base + 4, iov[i].iov_len - 4); - } else { - rc = - crypto_shash_update( - &server->secmech.sdeschmacsha256->shash, - iov[i].iov_base, iov[i].iov_len); - } - if (rc) { - cifs_dbg(VFS, "%s: Could not update with payload\n", - __func__); - return rc; - } - } - - /* now hash over the rq_pages array */ - for (i = 0; i < rqst->rq_npages; i++) { - struct kvec p_iov; - - cifs_rqst_page_to_kvec(rqst, i, &p_iov); - crypto_shash_update(&server->secmech.sdeschmacsha256->shash, - p_iov.iov_base, p_iov.iov_len); - kunmap(rqst->rq_pages[i]); - } - - rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash, - sigptr); - if (rc) - cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); + rc = __cifs_calc_signature(rqst, server, sigptr, + &server->secmech.sdeschmacsha256->shash); - memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); + if (!rc) + memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); return rc; } @@ -395,12 +352,10 @@ generate_smb311signingkey(struct cifs_ses *ses) int smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { - int i; int rc = 0; unsigned char smb3_signature[SMB2_CMACAES_SIZE]; unsigned char *sigptr = smb3_signature; struct kvec *iov = rqst->rq_iov; - int n_vec = rqst->rq_nvec; struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct cifs_ses *ses; @@ -431,54 +386,12 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); return rc; } + + rc = __cifs_calc_signature(rqst, server, sigptr, + &server->secmech.sdesccmacaes->shash); - for (i = 0; i < n_vec; i++) { - if (iov[i].iov_len == 0) - continue; - if (iov[i].iov_base == NULL) { - cifs_dbg(VFS, "null iovec entry"); - return -EIO; - } - /* - * The first entry includes a length field (which does not get - * signed that occupies the first 4 bytes before the header). - */ - if (i == 0) { - if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ - break; /* nothing to sign or corrupt header */ - rc = - crypto_shash_update( - &server->secmech.sdesccmacaes->shash, - iov[i].iov_base + 4, iov[i].iov_len - 4); - } else { - rc = - crypto_shash_update( - &server->secmech.sdesccmacaes->shash, - iov[i].iov_base, iov[i].iov_len); - } - if (rc) { - cifs_dbg(VFS, "%s: Couldn't update cmac aes with payload\n", - __func__); - return rc; - } - } - - /* now hash over the rq_pages array */ - for (i = 0; i < rqst->rq_npages; i++) { - struct kvec p_iov; - - cifs_rqst_page_to_kvec(rqst, i, &p_iov); - crypto_shash_update(&server->secmech.sdesccmacaes->shash, - p_iov.iov_base, p_iov.iov_len); - kunmap(rqst->rq_pages[i]); - } - - rc = crypto_shash_final(&server->secmech.sdesccmacaes->shash, - sigptr); - if (rc) - cifs_dbg(VFS, "%s: Could not generate cmac aes\n", __func__); - - memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); + if (!rc) + memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); return rc; } -- GitLab From 3ab3f2a1fee45f5788ddccd8b3ece6f74ae905bd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Nov 2015 02:36:04 -0500 Subject: [PATCH 0573/9938] cifs: quit playing games with draining iovecs ... and use ITER_BVEC for the page part of request to send Signed-off-by: Al Viro --- fs/cifs/cifsproto.h | 2 - fs/cifs/transport.c | 141 +++++++++++++------------------------------- 2 files changed, 41 insertions(+), 102 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d9b4f444fdf9..7d5f53a01922 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -37,8 +37,6 @@ extern void cifs_buf_release(void *); extern struct smb_hdr *cifs_small_buf_get(void); extern void cifs_small_buf_release(void *); extern void free_rsp_buf(int, void *); -extern void cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, - struct kvec *iov); extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, unsigned int /* length */); extern unsigned int _get_xid(void); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 87abe8ed074c..206a597b2293 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -124,41 +124,32 @@ cifs_delete_mid(struct mid_q_entry *mid) /* * smb_send_kvec - send an array of kvecs to the server * @server: Server to send the data to - * @iov: Pointer to array of kvecs - * @n_vec: length of kvec array + * @smb_msg: Message to send * @sent: amount of data sent on socket is stored here * * Our basic "send data to server" function. Should be called with srv_mutex * held. The caller is responsible for handling the results. */ static int -smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, - size_t *sent) +smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, + size_t *sent) { int rc = 0; - int i = 0; - struct msghdr smb_msg; - unsigned int remaining; - size_t first_vec = 0; + int retries = 0; struct socket *ssocket = server->ssocket; *sent = 0; - smb_msg.msg_name = (struct sockaddr *) &server->dstaddr; - smb_msg.msg_namelen = sizeof(struct sockaddr); - smb_msg.msg_control = NULL; - smb_msg.msg_controllen = 0; + smb_msg->msg_name = (struct sockaddr *) &server->dstaddr; + smb_msg->msg_namelen = sizeof(struct sockaddr); + smb_msg->msg_control = NULL; + smb_msg->msg_controllen = 0; if (server->noblocksnd) - smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; + smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; else - smb_msg.msg_flags = MSG_NOSIGNAL; - - remaining = 0; - for (i = 0; i < n_vec; i++) - remaining += iov[i].iov_len; + smb_msg->msg_flags = MSG_NOSIGNAL; - i = 0; - while (remaining) { + while (msg_data_left(smb_msg)) { /* * If blocking send, we try 3 times, since each can block * for 5 seconds. For nonblocking we have to try more @@ -177,35 +168,21 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, * after the retries we will kill the socket and * reconnect which may clear the network problem. */ - rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec], - n_vec - first_vec, remaining); + rc = sock_sendmsg(ssocket, smb_msg); if (rc == -EAGAIN) { - i++; - if (i >= 14 || (!server->noblocksnd && (i > 2))) { + retries++; + if (retries >= 14 || + (!server->noblocksnd && (retries > 2))) { cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", ssocket); - rc = -EAGAIN; - break; + return -EAGAIN; } - msleep(1 << i); + msleep(1 << retries); continue; } if (rc < 0) - break; - - /* send was at least partially successful */ - *sent += rc; - - if (rc == remaining) { - remaining = 0; - break; - } - - if (rc > remaining) { - cifs_dbg(VFS, "sent %d requested %d\n", rc, remaining); - break; - } + return rc; if (rc == 0) { /* should never happen, letting socket clear before @@ -215,59 +192,11 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, continue; } - remaining -= rc; - - /* the line below resets i */ - for (i = first_vec; i < n_vec; i++) { - if (iov[i].iov_len) { - if (rc > iov[i].iov_len) { - rc -= iov[i].iov_len; - iov[i].iov_len = 0; - } else { - iov[i].iov_base += rc; - iov[i].iov_len -= rc; - first_vec = i; - break; - } - } - } - - i = 0; /* in case we get ENOSPC on the next send */ - rc = 0; + /* send was at least partially successful */ + *sent += rc; + retries = 0; /* in case we get ENOSPC on the next send */ } - return rc; -} - -/** - * rqst_page_to_kvec - Turn a slot in the smb_rqst page array into a kvec - * @rqst: pointer to smb_rqst - * @idx: index into the array of the page - * @iov: pointer to struct kvec that will hold the result - * - * Helper function to convert a slot in the rqst->rq_pages array into a kvec. - * The page will be kmapped and the address placed into iov_base. The length - * will then be adjusted according to the ptailoff. - */ -void -cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, - struct kvec *iov) -{ - /* - * FIXME: We could avoid this kmap altogether if we used - * kernel_sendpage instead of kernel_sendmsg. That will only - * work if signing is disabled though as sendpage inlines the - * page directly into the fraglist. If userspace modifies the - * page after we calculate the signature, then the server will - * reject it and may break the connection. kernel_sendmsg does - * an extra copy of the data and avoids that issue. - */ - iov->iov_base = kmap(rqst->rq_pages[idx]); - - /* if last page, don't send beyond this offset into page */ - if (idx == (rqst->rq_npages - 1)) - iov->iov_len = rqst->rq_tailsz; - else - iov->iov_len = rqst->rq_pagesz; + return 0; } static unsigned long @@ -299,8 +228,9 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); unsigned long send_length; unsigned int i; - size_t total_len = 0, sent; + size_t total_len = 0, sent, size; struct socket *ssocket = server->ssocket; + struct msghdr smb_msg; int val = 1; if (ssocket == NULL) @@ -321,7 +251,13 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, (char *)&val, sizeof(val)); - rc = smb_send_kvec(server, iov, n_vec, &sent); + size = 0; + for (i = 0; i < n_vec; i++) + size += iov[i].iov_len; + + iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, iov, n_vec, size); + + rc = smb_send_kvec(server, &smb_msg, &sent); if (rc < 0) goto uncork; @@ -329,11 +265,16 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) /* now walk the page array and send each page in it */ for (i = 0; i < rqst->rq_npages; i++) { - struct kvec p_iov; - - cifs_rqst_page_to_kvec(rqst, i, &p_iov); - rc = smb_send_kvec(server, &p_iov, 1, &sent); - kunmap(rqst->rq_pages[i]); + size_t len = i == rqst->rq_npages - 1 + ? rqst->rq_tailsz + : rqst->rq_pagesz; + struct bio_vec bvec = { + .bv_page = rqst->rq_pages[i], + .bv_len = len + }; + iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC, + &bvec, 1, len); + rc = smb_send_kvec(server, &smb_msg, &sent); if (rc < 0) break; -- GitLab From 09aab880f7c5ac31e9db18a63353b980bcb52261 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Nov 2015 03:00:17 -0500 Subject: [PATCH 0574/9938] cifs: no need to wank with copying and advancing iovec on recvmsg side either Signed-off-by: Al Viro --- fs/cifs/cifsglob.h | 2 -- fs/cifs/connect.c | 72 ++++------------------------------------------ 2 files changed, 5 insertions(+), 69 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index d21da9f05bae..df03c5e7d633 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -615,8 +615,6 @@ struct TCP_Server_Info { bool sec_mskerberos; /* supports legacy MS Kerberos */ bool large_buf; /* is current buffer large? */ struct delayed_work echo; /* echo ping workqueue job */ - struct kvec *iov; /* reusable kvec array for receives */ - unsigned int nr_iov; /* number of kvecs in array */ char *smallbuf; /* pointer to current "small" buffer */ char *bigbuf; /* pointer to current "big" buffer */ unsigned int total_read; /* total amount of data read in this pass */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a763cd3d9e7c..eb426658566d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -501,77 +501,20 @@ server_unresponsive(struct TCP_Server_Info *server) return false; } -/* - * kvec_array_init - clone a kvec array, and advance into it - * @new: pointer to memory for cloned array - * @iov: pointer to original array - * @nr_segs: number of members in original array - * @bytes: number of bytes to advance into the cloned array - * - * This function will copy the array provided in iov to a section of memory - * and advance the specified number of bytes into the new array. It returns - * the number of segments in the new array. "new" must be at least as big as - * the original iov array. - */ -static unsigned int -kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs, - size_t bytes) -{ - size_t base = 0; - - while (bytes || !iov->iov_len) { - int copy = min(bytes, iov->iov_len); - - bytes -= copy; - base += copy; - if (iov->iov_len == base) { - iov++; - nr_segs--; - base = 0; - } - } - memcpy(new, iov, sizeof(*iov) * nr_segs); - new->iov_base += base; - new->iov_len -= base; - return nr_segs; -} - -static struct kvec * -get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs) -{ - struct kvec *new_iov; - - if (server->iov && nr_segs <= server->nr_iov) - return server->iov; - - /* not big enough -- allocate a new one and release the old */ - new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS); - if (new_iov) { - kfree(server->iov); - server->iov = new_iov; - server->nr_iov = nr_segs; - } - return new_iov; -} - int cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, unsigned int nr_segs, unsigned int to_read) { int length = 0; int total_read; - unsigned int segs; struct msghdr smb_msg; - struct kvec *iov; - - iov = get_server_iovec(server, nr_segs); - if (!iov) - return -ENOMEM; smb_msg.msg_control = NULL; smb_msg.msg_controllen = 0; + iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, + iov_orig, nr_segs, to_read); - for (total_read = 0; to_read; total_read += length, to_read -= length) { + for (total_read = 0; msg_data_left(&smb_msg); total_read += length) { try_to_freeze(); if (server_unresponsive(server)) { @@ -579,10 +522,7 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, break; } - segs = kvec_array_init(iov, iov_orig, nr_segs, total_read); - - length = kernel_recvmsg(server->ssocket, &smb_msg, - iov, segs, to_read, 0); + length = sock_recvmsg(server->ssocket, &smb_msg, 0); if (server->tcpStatus == CifsExiting) { total_read = -ESHUTDOWN; @@ -603,8 +543,7 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, length = 0; continue; } else if (length <= 0) { - cifs_dbg(FYI, "Received no data or error: expecting %d\n" - "got %d", to_read, length); + cifs_dbg(FYI, "Received no data or error: %d\n", length); cifs_reconnect(server); total_read = -ECONNABORTED; break; @@ -783,7 +722,6 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) } kfree(server->hostname); - kfree(server->iov); kfree(server); length = atomic_dec_return(&tcpSesAllocCount); -- GitLab From a6137305a8c47fa92ab1a8efcfe76f0e9fa96ab7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 9 Jan 2016 19:37:16 -0500 Subject: [PATCH 0575/9938] cifs_readv_receive: use cifs_read_from_socket() Signed-off-by: Al Viro --- fs/cifs/cifssmb.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 76fcb50295a3..3da077afad1f 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1447,10 +1447,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) len = min_t(unsigned int, buflen, server->vals->read_rsp_size) - HEADER_SIZE(server) + 1; - rdata->iov.iov_base = buf + HEADER_SIZE(server) - 1; - rdata->iov.iov_len = len; - - length = cifs_readv_from_socket(server, &rdata->iov, 1, len); + length = cifs_read_from_socket(server, + buf + HEADER_SIZE(server) - 1, len); if (length < 0) return length; server->total_read += length; @@ -1502,9 +1500,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) len = data_offset - server->total_read; if (len > 0) { /* read any junk before data into the rest of smallbuf */ - rdata->iov.iov_base = buf + server->total_read; - rdata->iov.iov_len = len; - length = cifs_readv_from_socket(server, &rdata->iov, 1, len); + length = cifs_read_from_socket(server, + buf + server->total_read, len); if (length < 0) return length; server->total_read += length; -- GitLab From 71335664c38f03de10d7cf1d82705fe55a130b33 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 9 Jan 2016 19:54:50 -0500 Subject: [PATCH 0576/9938] cifs: don't bother with kmap on read_pages side just do ITER_BVEC recvmsg Signed-off-by: Al Viro --- fs/cifs/cifsproto.h | 7 +++-- fs/cifs/connect.c | 65 ++++++++++++++++++++++++--------------------- fs/cifs/file.c | 53 ++++++++++++------------------------ 3 files changed, 55 insertions(+), 70 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7d5f53a01922..0f9a6bc4ba43 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -179,10 +179,9 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, - unsigned int to_read); -extern int cifs_readv_from_socket(struct TCP_Server_Info *server, - struct kvec *iov_orig, unsigned int nr_segs, - unsigned int to_read); + unsigned int to_read); +extern int cifs_read_page_from_socket(struct TCP_Server_Info *server, + struct page *page, unsigned int to_read); extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, struct cifs_sb_info *cifs_sb); extern int cifs_match_super(struct super_block *, void *); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index eb426658566d..e33c5e0ecfd0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -501,39 +501,34 @@ server_unresponsive(struct TCP_Server_Info *server) return false; } -int -cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, - unsigned int nr_segs, unsigned int to_read) +static int +cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg) { int length = 0; int total_read; - struct msghdr smb_msg; - smb_msg.msg_control = NULL; - smb_msg.msg_controllen = 0; - iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, - iov_orig, nr_segs, to_read); + smb_msg->msg_control = NULL; + smb_msg->msg_controllen = 0; - for (total_read = 0; msg_data_left(&smb_msg); total_read += length) { + for (total_read = 0; msg_data_left(smb_msg); total_read += length) { try_to_freeze(); - if (server_unresponsive(server)) { - total_read = -ECONNABORTED; - break; - } + if (server_unresponsive(server)) + return -ECONNABORTED; - length = sock_recvmsg(server->ssocket, &smb_msg, 0); + length = sock_recvmsg(server->ssocket, smb_msg, 0); - if (server->tcpStatus == CifsExiting) { - total_read = -ESHUTDOWN; - break; - } else if (server->tcpStatus == CifsNeedReconnect) { + if (server->tcpStatus == CifsExiting) + return -ESHUTDOWN; + + if (server->tcpStatus == CifsNeedReconnect) { cifs_reconnect(server); - total_read = -ECONNABORTED; - break; - } else if (length == -ERESTARTSYS || - length == -EAGAIN || - length == -EINTR) { + return -ECONNABORTED; + } + + if (length == -ERESTARTSYS || + length == -EAGAIN || + length == -EINTR) { /* * Minimum sleep to prevent looping, allowing socket * to clear and app threads to set tcpStatus @@ -542,11 +537,12 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, usleep_range(1000, 2000); length = 0; continue; - } else if (length <= 0) { + } + + if (length <= 0) { cifs_dbg(FYI, "Received no data or error: %d\n", length); cifs_reconnect(server); - total_read = -ECONNABORTED; - break; + return -ECONNABORTED; } } return total_read; @@ -556,12 +552,21 @@ int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, unsigned int to_read) { - struct kvec iov; + struct msghdr smb_msg; + struct kvec iov = {.iov_base = buf, .iov_len = to_read}; + iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read); - iov.iov_base = buf; - iov.iov_len = to_read; + return cifs_readv_from_socket(server, &smb_msg); +} - return cifs_readv_from_socket(server, &iov, 1, to_read); +int +cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page, + unsigned int to_read) +{ + struct msghdr smb_msg; + struct bio_vec bv = {.bv_page = page, .bv_len = to_read}; + iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read); + return cifs_readv_from_socket(server, &smb_msg); } static bool diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ff882aeaccc6..0f718679186e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2855,39 +2855,31 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, int result = 0; unsigned int i; unsigned int nr_pages = rdata->nr_pages; - struct kvec iov; rdata->got_bytes = 0; rdata->tailsz = PAGE_SIZE; for (i = 0; i < nr_pages; i++) { struct page *page = rdata->pages[i]; + size_t n; - if (len >= PAGE_SIZE) { - /* enough data to fill the page */ - iov.iov_base = kmap(page); - iov.iov_len = PAGE_SIZE; - cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n", - i, iov.iov_base, iov.iov_len); - len -= PAGE_SIZE; - } else if (len > 0) { - /* enough for partial page, fill and zero the rest */ - iov.iov_base = kmap(page); - iov.iov_len = len; - cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n", - i, iov.iov_base, iov.iov_len); - memset(iov.iov_base + len, '\0', PAGE_SIZE - len); - rdata->tailsz = len; - len = 0; - } else { + if (len <= 0) { /* no need to hold page hostage */ rdata->pages[i] = NULL; rdata->nr_pages--; put_page(page); continue; } - - result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len); - kunmap(page); + n = len; + if (len >= PAGE_SIZE) { + /* enough data to fill the page */ + n = PAGE_SIZE; + len -= n; + } else { + zero_user(page, len, PAGE_SIZE - len); + rdata->tailsz = len; + len = 0; + } + result = cifs_read_page_from_socket(server, page, n); if (result < 0) break; @@ -3303,7 +3295,6 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, u64 eof; pgoff_t eof_index; unsigned int nr_pages = rdata->nr_pages; - struct kvec iov; /* determine the eof that the server (probably) has */ eof = CIFS_I(rdata->mapping->host)->server_eof; @@ -3314,23 +3305,14 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, rdata->tailsz = PAGE_CACHE_SIZE; for (i = 0; i < nr_pages; i++) { struct page *page = rdata->pages[i]; + size_t n = PAGE_CACHE_SIZE; if (len >= PAGE_CACHE_SIZE) { - /* enough data to fill the page */ - iov.iov_base = kmap(page); - iov.iov_len = PAGE_CACHE_SIZE; - cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n", - i, page->index, iov.iov_base, iov.iov_len); len -= PAGE_CACHE_SIZE; } else if (len > 0) { /* enough for partial page, fill and zero the rest */ - iov.iov_base = kmap(page); - iov.iov_len = len; - cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n", - i, page->index, iov.iov_base, iov.iov_len); - memset(iov.iov_base + len, - '\0', PAGE_CACHE_SIZE - len); - rdata->tailsz = len; + zero_user(page, len, PAGE_CACHE_SIZE - len); + n = rdata->tailsz = len; len = 0; } else if (page->index > eof_index) { /* @@ -3360,8 +3342,7 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, continue; } - result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len); - kunmap(page); + result = cifs_read_page_from_socket(server, page, n); if (result < 0) break; -- GitLab From 86cf635a316e89ba6ae79f452cedb5acddccf570 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 17 Mar 2016 14:54:54 -0300 Subject: [PATCH 0577/9938] regulator: Rename files for Maxim PMIC drivers Most Maxim PMIC regulator drivers are for sub-devices of Multi-Function Devices with drivers under drivers/mfd. But for many of these, the same object file name was used for both the MFD and the regulator drivers. Having 2 different drivers with the same name causes a lot of confusion to Kbuild, specially if these are built as module since only one module will be installed and also exported symbols will be undefined due being overwritten by the other module during modpost. For example, it fixes the following issue when both drivers are module: $ make M=drivers/regulator/ ... CC [M] drivers/regulator//max14577.o Building modules, stage 2. MODPOST 1 modules WARNING: "maxim_charger_calc_reg_current" [drivers/regulator//max14577.ko] undefined! WARNING: "maxim_charger_currents" [drivers/regulator//max14577.ko] undefined! Reported-by: Chanwoo Choi Signed-off-by: Javier Martinez Canillas Reviewed-by: Chanwoo Choi Signed-off-by: Mark Brown --- MAINTAINERS | 4 ++-- drivers/regulator/Makefile | 6 +++--- drivers/regulator/{max14577.c => max14577-regulator.c} | 0 drivers/regulator/{max77693.c => max77693-regulator.c} | 0 drivers/regulator/{max8997.c => max8997-regulator.c} | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename drivers/regulator/{max14577.c => max14577-regulator.c} (100%) rename drivers/regulator/{max77693.c => max77693-regulator.c} (100%) rename drivers/regulator/{max8997.c => max8997-regulator.c} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..e0b7b599607c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7019,9 +7019,9 @@ M: Chanwoo Choi M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Supported -F: drivers/*/max14577.c +F: drivers/*/max14577*.c F: drivers/*/max77686*.c -F: drivers/*/max77693.c +F: drivers/*/max77693*.c F: drivers/extcon/extcon-max14577.c F: drivers/extcon/extcon-max77693.c F: drivers/rtc/rtc-max77686.c diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 61bfbb9d4a0c..8018b2ef13cb 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -46,7 +46,7 @@ obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o -obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o +obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o @@ -55,10 +55,10 @@ obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o -obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o +obj-$(CONFIG_REGULATOR_MAX8997) += max8997-regulator.o obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o -obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o +obj-$(CONFIG_REGULATOR_MAX77693) += max77693-regulator.o obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577-regulator.c similarity index 100% rename from drivers/regulator/max14577.c rename to drivers/regulator/max14577-regulator.c diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693-regulator.c similarity index 100% rename from drivers/regulator/max77693.c rename to drivers/regulator/max77693-regulator.c diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997-regulator.c similarity index 100% rename from drivers/regulator/max8997.c rename to drivers/regulator/max8997-regulator.c -- GitLab From a12ddd60ed0a88c3bb83a8d4c07762e41620bf8c Mon Sep 17 00:00:00 2001 From: Nobuteru Hayashi Date: Fri, 18 Mar 2016 11:35:21 +0000 Subject: [PATCH 0578/9938] spi/fsl-espi: Don't spin forever on SPIE_RXCNT Infinite loop on SPIE_RXCNT occurred. while (SPIE_RXCNT(events) < min(4, mspi->len)) { cpu_relax(); events = mpc8xxx_spi_read_reg(®_base->event); } We met a soft lockup at fsl_espi_cpu_irq() because of this. Fix it by using spin_event_timeout() so that fsl_espi_cpu_irq() can break loop with timeouts dmesg. Signed-off-by: Nobuteru Hayashi Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 7cb0c1921495..5d7fb81240cd 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -539,11 +539,18 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) if (events & SPIE_NE) { u32 rx_data, tmp; u8 rx_data_8; + int ret; /* Spin until RX is done */ - while (SPIE_RXCNT(events) < min(4, mspi->len)) { - cpu_relax(); - events = mpc8xxx_spi_read_reg(®_base->event); + if (SPIE_RXCNT(events) < min(4, mspi->len)) { + ret = spin_event_timeout( + !(SPIE_RXCNT(events = + mpc8xxx_spi_read_reg(®_base->event)) < + min(4, mspi->len)), + 10000, 0); /* 10 msec */ + if (!ret) + dev_err(mspi->dev, + "tired waiting for SPIE_RXCNT\n"); } if (mspi->len >= 4) { -- GitLab From aa70e567c4f0eeb849c6bcef3685bdf1fc3ca19d Mon Sep 17 00:00:00 2001 From: Nobuteru Hayashi Date: Fri, 18 Mar 2016 11:35:21 +0000 Subject: [PATCH 0579/9938] spi/fsl-espi: Don't wait transaction completion forever Because the eSPI driver uses wait_for_completion(), any stuck-able phenomenon at half-way transaction progress made worker task hang up. This phenomenon is perhaps caused by eSPI device errata which seems not to be published from vendor site yet. Anyway, we fix hang task by using fixed 2 seconds timeout that is our preferred value for eSPI maximum transaction size. It seems to be better that eSPI driver can detect this stuck and report error (EMSGSIZE) to the upper device driver because the upper device driver can decide to retry or recover. Signed-off-by: Nobuteru Hayashi Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 5d7fb81240cd..64d794b99803 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -245,7 +245,12 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) if (ret) return ret; - wait_for_completion(&mpc8xxx_spi->done); + /* Won't hang up forever, SPI bus sometimes got lost interrupts... */ + ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ); + if (ret == 0) + dev_err(mpc8xxx_spi->dev, + "Transaction hanging up (left %d bytes)\n", + mpc8xxx_spi->count); /* disable rx ints */ mpc8xxx_spi_write_reg(®_base->mask, 0); -- GitLab From 6319a68011b86fa61dc63e94dc4fb716628037f3 Mon Sep 17 00:00:00 2001 From: Nobuteru Hayashi Date: Fri, 18 Mar 2016 11:35:21 +0000 Subject: [PATCH 0580/9938] spi/fsl-espi: avoid infinite loops on fsl_espi_cpu_irq() It brought nearly infinite loops, and was possible to be occurred only if the SPI transaction total size are not alighed with 4. Loops are here at while (tmp--), tmp is unsigned, and set it with minus value. The loops are executed as a result of unexpected RX interrupt occurrence after that. This interrupt may be hardware eratta and is not fixed. Fix mspi->len from minus value to 0 and print warning message. Signed-off-by: Nobuteru Hayashi Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 64d794b99803..8d85a3c343da 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -544,6 +544,7 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) if (events & SPIE_NE) { u32 rx_data, tmp; u8 rx_data_8; + int rx_nr_bytes = 4; int ret; /* Spin until RX is done */ @@ -560,7 +561,14 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) if (mspi->len >= 4) { rx_data = mpc8xxx_spi_read_reg(®_base->receive); + } else if (mspi->len <= 0) { + dev_err(mspi->dev, + "unexpected RX(SPIE_NE) interrupt occurred,\n" + "(local rxlen %d bytes, reg rxlen %d bytes)\n", + min(4, mspi->len), SPIE_RXCNT(events)); + rx_nr_bytes = 0; } else { + rx_nr_bytes = mspi->len; tmp = mspi->len; rx_data = 0; while (tmp--) { @@ -571,7 +579,7 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) rx_data <<= (4 - mspi->len) * 8; } - mspi->len -= 4; + mspi->len -= rx_nr_bytes; if (mspi->rx) mspi->get_rx(rx_data, mspi); -- GitLab From a52db659c79ceede44e2d5ca63ca058d49df8dea Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sun, 20 Mar 2016 19:30:17 +0100 Subject: [PATCH 0581/9938] spi: pxa2xx: Fix cs_change management Fix cs_change management so that it is in line with other spi drivers. In the spi core api helpers such as spi_bus_lock/unlock and spi_sync_locked or cs_change field in spi_transfer help to manage chip select from the device driver. The driver was setting the chip select to idle if the message queue was empty despite cs_change or other status field set by spi_bus_lock/unlock or spi_sync_locked. Signed-off-by: Christophe Ricard Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 86c155aea0cf..0ce82db8e484 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -570,9 +570,8 @@ static void giveback(struct driver_data *drv_data) /* see if the next and current messages point * to the same chip */ - if (next_msg && next_msg->spi != msg->spi) - next_msg = NULL; - if (!next_msg || msg->state == ERROR_STATE) + if ((next_msg && next_msg->spi != msg->spi) || + msg->state == ERROR_STATE) cs_deassert(drv_data); } -- GitLab From 465011fc56717f0227d1aa7a99cce000abc614d8 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 27 Mar 2016 19:06:14 -0300 Subject: [PATCH 0582/9938] ASoC: wm8960: Provide a menu selection text Provide a menu selection text so that users can enable, disable or mark it as module in menuconfig. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 649e92a252ae..196101b2eab5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -909,7 +909,7 @@ config SND_SOC_WM8955 tristate config SND_SOC_WM8960 - tristate + tristate "Wolfson Microelectronics WM8960 CODEC" config SND_SOC_WM8961 tristate -- GitLab From 005e46857ed598bcf76035366cd2841e3b7f8c54 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Thu, 17 Mar 2016 15:05:07 +0100 Subject: [PATCH 0583/9938] regulator: act8865: Pass of_node via act8865_regulator_data This makes the code easier to read and it avoids a dynamic memory allocation. Signed-off-by: Maarten ter Huurne Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 28 ++++++++++++--------------- include/linux/regulator/act8865.h | 2 ++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 69cdad0f71ba..527926b045d5 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -319,7 +319,6 @@ static struct of_regulator_match act8600_matches[] = { }; static int act8865_pdata_from_dt(struct device *dev, - struct device_node **of_node, struct act8865_platform_data *pdata, unsigned long type) { @@ -370,7 +369,7 @@ static int act8865_pdata_from_dt(struct device *dev, regulator->id = i; regulator->name = matches[i].name; regulator->init_data = matches[i].init_data; - of_node[i] = matches[i].of_node; + regulator->of_node = matches[i].of_node; regulator++; } @@ -378,7 +377,6 @@ static int act8865_pdata_from_dt(struct device *dev, } #else static inline int act8865_pdata_from_dt(struct device *dev, - struct device_node **of_node, struct act8865_platform_data *pdata, unsigned long type) { @@ -386,8 +384,8 @@ static inline int act8865_pdata_from_dt(struct device *dev, } #endif -static struct regulator_init_data -*act8865_get_init_data(int id, struct act8865_platform_data *pdata) +static struct act8865_regulator_data *act8865_get_regulator_data( + int id, struct act8865_platform_data *pdata) { int i; @@ -396,7 +394,7 @@ static struct regulator_init_data for (i = 0; i < pdata->num_regulators; i++) { if (pdata->regulators[i].id == id) - return pdata->regulators[i].init_data; + return &pdata->regulators[i]; } return NULL; @@ -418,7 +416,6 @@ static int act8865_pmic_probe(struct i2c_client *client, const struct regulator_desc *regulators; struct act8865_platform_data pdata_of, *pdata; struct device *dev = &client->dev; - struct device_node **of_node; int i, ret, num_regulators; struct act8865 *act8865; unsigned long type; @@ -472,13 +469,8 @@ static int act8865_pmic_probe(struct i2c_client *client, return -EINVAL; } - of_node = devm_kzalloc(dev, sizeof(struct device_node *) * - num_regulators, GFP_KERNEL); - if (!of_node) - return -ENOMEM; - if (dev->of_node && !pdata) { - ret = act8865_pdata_from_dt(dev, of_node, &pdata_of, type); + ret = act8865_pdata_from_dt(dev, &pdata_of, type); if (ret < 0) return ret; @@ -511,14 +503,19 @@ static int act8865_pmic_probe(struct i2c_client *client, for (i = 0; i < num_regulators; i++) { const struct regulator_desc *desc = ®ulators[i]; struct regulator_config config = { }; + struct act8865_regulator_data *rdata; struct regulator_dev *rdev; config.dev = dev; - config.init_data = act8865_get_init_data(desc->id, pdata); - config.of_node = of_node[i]; config.driver_data = act8865; config.regmap = act8865->regmap; + rdata = act8865_get_regulator_data(desc->id, pdata); + if (rdata) { + config.init_data = rdata->init_data; + config.of_node = rdata->of_node; + } + rdev = devm_regulator_register(dev, desc, &config); if (IS_ERR(rdev)) { dev_err(dev, "failed to register %s\n", desc->name); @@ -527,7 +524,6 @@ static int act8865_pmic_probe(struct i2c_client *client, } i2c_set_clientdata(client, act8865); - devm_kfree(dev, of_node); return 0; } diff --git a/include/linux/regulator/act8865.h b/include/linux/regulator/act8865.h index 2eb386017fa5..113d861a1e4c 100644 --- a/include/linux/regulator/act8865.h +++ b/include/linux/regulator/act8865.h @@ -69,11 +69,13 @@ enum { * @id: regulator id * @name: regulator name * @init_data: regulator init data + * @of_node: device tree node (optional) */ struct act8865_regulator_data { int id; const char *name; struct regulator_init_data *init_data; + struct device_node *of_node; }; /** -- GitLab From c5c9c2df4d97e20cd4e05c848dc8ceff926d162f Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Thu, 17 Mar 2016 15:05:08 +0100 Subject: [PATCH 0584/9938] regulator: act8865: Configure register access for act8600 This can be used to expose the act8600 registers via debugfs. Signed-off-by: Maarten ter Huurne Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 74 ++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 527926b045d5..a1cd0d4f8257 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -139,6 +139,74 @@ struct act8865 { int off_mask; }; +static const struct regmap_range act8600_reg_ranges[] = { + regmap_reg_range(0x00, 0x01), + regmap_reg_range(0x10, 0x10), + regmap_reg_range(0x12, 0x12), + regmap_reg_range(0x20, 0x20), + regmap_reg_range(0x22, 0x22), + regmap_reg_range(0x30, 0x30), + regmap_reg_range(0x32, 0x32), + regmap_reg_range(0x40, 0x41), + regmap_reg_range(0x50, 0x51), + regmap_reg_range(0x60, 0x61), + regmap_reg_range(0x70, 0x71), + regmap_reg_range(0x80, 0x81), + regmap_reg_range(0x91, 0x91), + regmap_reg_range(0xA1, 0xA1), + regmap_reg_range(0xA8, 0xAA), + regmap_reg_range(0xB0, 0xB0), + regmap_reg_range(0xB2, 0xB2), + regmap_reg_range(0xC1, 0xC1), +}; + +static const struct regmap_range act8600_reg_ro_ranges[] = { + regmap_reg_range(0xAA, 0xAA), + regmap_reg_range(0xC1, 0xC1), +}; + +static const struct regmap_range act8600_reg_volatile_ranges[] = { + regmap_reg_range(0x00, 0x01), + regmap_reg_range(0x12, 0x12), + regmap_reg_range(0x22, 0x22), + regmap_reg_range(0x32, 0x32), + regmap_reg_range(0x41, 0x41), + regmap_reg_range(0x51, 0x51), + regmap_reg_range(0x61, 0x61), + regmap_reg_range(0x71, 0x71), + regmap_reg_range(0x81, 0x81), + regmap_reg_range(0xA8, 0xA8), + regmap_reg_range(0xAA, 0xAA), + regmap_reg_range(0xB0, 0xB0), + regmap_reg_range(0xC1, 0xC1), +}; + +static const struct regmap_access_table act8600_write_ranges_table = { + .yes_ranges = act8600_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(act8600_reg_ranges), + .no_ranges = act8600_reg_ro_ranges, + .n_no_ranges = ARRAY_SIZE(act8600_reg_ro_ranges), +}; + +static const struct regmap_access_table act8600_read_ranges_table = { + .yes_ranges = act8600_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(act8600_reg_ranges), +}; + +static const struct regmap_access_table act8600_volatile_ranges_table = { + .yes_ranges = act8600_reg_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(act8600_reg_volatile_ranges), +}; + +static const struct regmap_config act8600_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xFF, + .wr_table = &act8600_write_ranges_table, + .rd_table = &act8600_read_ranges_table, + .volatile_table = &act8600_volatile_ranges_table, +}; + static const struct regmap_config act8865_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -418,6 +486,7 @@ static int act8865_pmic_probe(struct i2c_client *client, struct device *dev = &client->dev; int i, ret, num_regulators; struct act8865 *act8865; + const struct regmap_config *regmap_config; unsigned long type; int off_reg, off_mask; int voltage_select = 0; @@ -444,12 +513,14 @@ static int act8865_pmic_probe(struct i2c_client *client, case ACT8600: regulators = act8600_regulators; num_regulators = ARRAY_SIZE(act8600_regulators); + regmap_config = &act8600_regmap_config; off_reg = -1; off_mask = -1; break; case ACT8846: regulators = act8846_regulators; num_regulators = ARRAY_SIZE(act8846_regulators); + regmap_config = &act8865_regmap_config; off_reg = ACT8846_GLB_OFF_CTRL; off_mask = ACT8846_OFF_SYSMASK; break; @@ -461,6 +532,7 @@ static int act8865_pmic_probe(struct i2c_client *client, regulators = act8865_regulators; num_regulators = ARRAY_SIZE(act8865_regulators); } + regmap_config = &act8865_regmap_config; off_reg = ACT8865_SYS_CTRL; off_mask = ACT8865_MSTROFF; break; @@ -481,7 +553,7 @@ static int act8865_pmic_probe(struct i2c_client *client, if (!act8865) return -ENOMEM; - act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config); + act8865->regmap = devm_regmap_init_i2c(client, regmap_config); if (IS_ERR(act8865->regmap)) { ret = PTR_ERR(act8865->regmap); dev_err(dev, "Failed to allocate register map: %d\n", ret); -- GitLab From 6c5eb1db1e4a1fdbb5c6a9626875c589b84860b7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 21 Mar 2016 17:29:39 +0900 Subject: [PATCH 0585/9938] ARM: dts: exynos: Add Security SubSystem node to Exynos4 Add Security SubSystem (SSS) node to Exynos4 which provides hardware acceleration of AES operations. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos4.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index c679b3cc3c48..39000f9c6b86 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -969,6 +969,15 @@ #iommu-cells = <0>; }; + sss: sss@10830000 { + compatible = "samsung,exynos4210-secss"; + reg = <0x10830000 0x300>; + interrupts = <0 112 0>; + clocks = <&clock CLK_SSS>; + clock-names = "secss"; + status = "disabled"; + }; + prng: rng@10830400 { compatible = "samsung,exynos4-rng"; reg = <0x10830400 0x200>; -- GitLab From f3a132f0eaed611c3782181130422f4a704ac114 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 21 Mar 2016 17:29:52 +0900 Subject: [PATCH 0586/9938] ARM: dts: exynos: Enable SSS on Trats2 Enable the Security SubSystem (SSS) on Trats2 (Exynos4412) board to provide hardware acceleration for AES operations. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos4412-trats2.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index ed017cc7b14f..2bf363c3bf62 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -1286,6 +1286,10 @@ }; }; +&sss { + status = "okay"; +}; + &tmu { vtmu-supply = <&ldo10_reg>; status = "okay"; -- GitLab From fb2d1b847fd6c02341f09a41d56d58c5c0ca1f92 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 23 Mar 2016 15:02:39 +0900 Subject: [PATCH 0587/9938] ARM: dts: exynos: Enable SSS on Odroid X/X2/U3 family Enable the Security SubSystem (SSS) on Exynos4412-based Odroid boards to provide hardware acceleration for AES operations. Suggested-by: Tobias Jakobi Signed-off-by: Krzysztof Kozlowski Tested-by: Tobias Jakobi --- arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index 5e5d3fecb04c..470e592e9232 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -492,6 +492,10 @@ status = "okay"; }; +&sss { + status = "okay"; +}; + &tmu { vtmu-supply = <&ldo10_reg>; status = "okay"; -- GitLab From fbfcf4bf1c11f16b0afbf77e366cba0c7a621003 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Fri, 26 Feb 2016 14:36:30 +0530 Subject: [PATCH 0588/9938] arm64: dts: exynos: Add TMU node for exynos7 This patch adds TMU node, related temprature sensor and triping point data for Atlas cpu core found on exynos7 SoC. Signed-off-by: Alim Akhtar Signed-off-by: Krzysztof Kozlowski --- .../dts/exynos/exynos7-tmu-sensor-conf.dtsi | 25 +++++++++ .../boot/dts/exynos/exynos7-trip-points.dtsi | 54 +++++++++++++++++++ arch/arm64/boot/dts/exynos/exynos7.dtsi | 20 +++++++ 3 files changed, 99 insertions(+) create mode 100644 arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi create mode 100644 arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi diff --git a/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi b/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi new file mode 100644 index 000000000000..1d6dcf2aadba --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi @@ -0,0 +1,25 @@ +/* + * Device tree sources for Exynos7 TMU sensor configuration + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include + +#thermal-sensor-cells = <0>; +samsung,tmu_gain = <9>; +samsung,tmu_reference_voltage = <17>; +samsung,tmu_noise_cancel_mode = <4>; +samsung,tmu_efuse_value = <75>; +samsung,tmu_min_efuse_value = <15>; +samsung,tmu_max_efuse_value = <100>; +samsung,tmu_first_point_trim = <25>; +samsung,tmu_second_point_trim = <85>; +samsung,tmu_default_temp_offset = <50>; +samsung,tmu_cal_type = ; diff --git a/arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi b/arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi new file mode 100644 index 000000000000..062358355a53 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi @@ -0,0 +1,54 @@ +/* + * Device tree sources for default Exynos7 thermal zone definition + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +trips { + cpu-alert-0 { + temperature = <75000>; /* millicelsius */ + hysteresis = <10000>; /* millicelsius */ + type = "passive"; + }; + cpu-alert-1 { + temperature = <80000>; /* millicelsius */ + hysteresis = <10000>; /* millicelsius */ + type = "passive"; + }; + cpu-alert-2 { + temperature = <85000>; /* millicelsius */ + hysteresis = <10000>; /* millicelsius */ + type = "passive"; + }; + cpu-alert-3 { + temperature = <90000>; /* millicelsius */ + hysteresis = <10000>; /* millicelsius */ + type = "passive"; + }; + cpu-alert-4 { + temperature = <95000>; /* millicelsius */ + hysteresis = <10000>; /* millicelsius */ + type = "passive"; + }; + cpu-alert-5 { + temperature = <100000>; /* millicelsius */ + hysteresis = <10000>; /* millicelsius */ + type = "passive"; + }; + cpu-alert-6 { + temperature = <110000>; /* millicelsius */ + hysteresis = <10000>; /* millicelsius */ + type = "passive"; + }; + cpu-crit-0 { + temperature = <115000>; /* millicelsius */ + hysteresis = <0>; /* millicelsius */ + type = "critical"; + }; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 93108f1a90f9..2450d0a06da5 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -27,6 +27,7 @@ pinctrl6 = &pinctrl_fsys0; pinctrl7 = &pinctrl_fsys1; pinctrl8 = &pinctrl_bus1; + tmuctrl0 = &tmuctrl_0; }; cpus { @@ -538,6 +539,25 @@ clocks = <&clock_peric0 PCLK_PWM>; clock-names = "timers"; }; + + tmuctrl_0: tmu@10060000 { + compatible = "samsung,exynos7-tmu"; + reg = <0x10060000 0x200>; + interrupts = <0 108 0>; + clocks = <&clock_peris PCLK_TMU>, + <&clock_peris SCLK_TMU>; + clock-names = "tmu_apbif", "tmu_sclk"; + #include "exynos7-tmu-sensor-conf.dtsi" + }; + + thermal-zones { + atlas_thermal: cluster0-thermal { + polling-delay-passive = <0>; /* milliseconds */ + polling-delay = <0>; /* milliseconds */ + thermal-sensors = <&tmuctrl_0>; + #include "exynos7-trip-points.dtsi" + }; + }; }; }; -- GitLab From a92de67c101581d49dfd43c3747f74f3792212e0 Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Fri, 25 Mar 2016 14:09:59 +0100 Subject: [PATCH 0589/9938] ARM: dts: exynos: Add HDMI CEC pin definition to exynos4 pinctrl Add pinctrl nodes for the HDMI CEC device to the Exynos4210 and Exynos4x12 SoCs. These are required by the HDMI CEC device. Signed-off-by: Kamil Debski Signed-off-by: Hans Verkuil Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4210-pinctrl.dtsi | 7 +++++++ arch/arm/boot/dts/exynos4x12-pinctrl.dtsi | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi index a7c212891674..9331c6252eff 100644 --- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi @@ -820,6 +820,13 @@ samsung,pin-pud = <1>; samsung,pin-drv = <0>; }; + + hdmi_cec: hdmi-cec { + samsung,pins = "gpx3-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; }; pinctrl@03860000 { diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi index bac25c672789..856b29254374 100644 --- a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi @@ -885,6 +885,13 @@ samsung,pin-pud = <0>; samsung,pin-drv = <0>; }; + + hdmi_cec: hdmi-cec { + samsung,pins = "gpx3-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; }; pinctrl_2: pinctrl@03860000 { -- GitLab From c795c88d986150745b541418113f17db58ba575f Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Fri, 25 Mar 2016 14:10:00 +0100 Subject: [PATCH 0590/9938] ARM: dts: exynos: Add node for the HDMI CEC device to exynos4 This patch adds HDMI CEC node specific to the Exynos4210/4x12 SoC series. Signed-off-by: Kamil Debski Signed-off-by: Hans Verkuil Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 39000f9c6b86..000d506c027b 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -743,6 +743,18 @@ status = "disabled"; }; + hdmicec: cec@100B0000 { + compatible = "samsung,s5p-cec"; + reg = <0x100B0000 0x200>; + interrupts = <0 114 0>; + clocks = <&clock CLK_HDMI_CEC>; + clock-names = "hdmicec"; + samsung,syscon-phandle = <&pmu_system_controller>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_cec>; + status = "disabled"; + }; + mixer: mixer@12C10000 { compatible = "samsung,exynos4210-mixer"; interrupts = <0 91 0>; -- GitLab From f1be903dbed810f71f6f27c2cb721ccf561052aa Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 25 Mar 2016 14:10:01 +0100 Subject: [PATCH 0591/9938] ARM: dts: exynos: Enable the HDMI CEC device on Exynos4412 Odroid boards Add a dts node entry and enable the HDMI CEC device present in the Exynos4 family of SoCs. Signed-off-by: Marek Szyprowski Signed-off-by: Hans Verkuil [k.kozlowski: Put the node in alphabetical order] Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index 470e592e9232..acd7e7b5fd13 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -188,6 +188,10 @@ status = "okay"; }; +&hdmicec { + status = "okay"; +}; + &hsotg { dr_mode = "peripheral"; status = "okay"; -- GitLab From 60d8fcef13e60484ecc5aa2c0a904b250750beba Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 12 Mar 2016 10:15:03 +0100 Subject: [PATCH 0592/9938] pinctrl: sh-pfc: r8a7790: Implement voltage switching for SDHI All the SHDIs can operate with either 3.3V or 1.8V signals, depending on negotiation with the card. Implement the {get,set}_io_voltage operations and set the related capability flag for the associated pins. Signed-off-by: Ben Hutchings Signed-off-by: Wolfram Sang Cc: linux-gpio@vger.kernel.org Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 54 +++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 0f4d48f9400b..eed8daa464cc 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -21,16 +21,21 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include "core.h" #include "sh_pfc.h" +/* + * All pins assigned to GPIO bank 3 can be used for SD interfaces in + * which case they support both 3.3V and 1.8V signalling. + */ #define CPU_ALL_PORT(fn, sfx) \ PORT_GP_32(0, fn, sfx), \ PORT_GP_30(1, fn, sfx), \ PORT_GP_30(2, fn, sfx), \ - PORT_GP_32(3, fn, sfx), \ + PORT_GP_CFG_32(3, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \ PORT_GP_32(4, fn, sfx), \ PORT_GP_32(5, fn, sfx) @@ -4691,6 +4696,47 @@ static const char * const vin3_groups[] = { "vin3_clk", }; +#define IOCTRL6 0x8c + +static int r8a7790_get_io_voltage(struct sh_pfc *pfc, unsigned int pin) +{ + u32 data, mask; + + if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin)) + return -EINVAL; + + data = ioread32(pfc->windows->virt + IOCTRL6), + /* Bits in IOCTRL6 are numbered in opposite order to pins */ + mask = 0x80000000 >> (pin & 0x1f); + + return (data & mask) ? 3300 : 1800; +} + +static int r8a7790_set_io_voltage(struct sh_pfc *pfc, unsigned int pin, u16 mV) +{ + u32 data, mask; + + if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin)) + return -EINVAL; + + if (mV != 1800 && mV != 3300) + return -EINVAL; + + data = ioread32(pfc->windows->virt + IOCTRL6); + /* Bits in IOCTRL6 are numbered in opposite order to pins */ + mask = 0x80000000 >> (pin & 0x1f); + + if (mV == 3300) + data |= mask; + else + data &= ~mask; + + iowrite32(~data, pfc->windows->virt); /* unlock reg */ + iowrite32(data, pfc->windows->virt + IOCTRL6); + + return 0; +} + static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(avb), @@ -5690,8 +5736,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { { }, }; +static const struct sh_pfc_soc_operations pinmux_ops = { + .get_io_voltage = r8a7790_get_io_voltage, + .set_io_voltage = r8a7790_set_io_voltage, +}; + const struct sh_pfc_soc_info r8a7790_pinmux_info = { .name = "r8a77900_pfc", + .ops = &pinmux_ops, .unlock_reg = 0xe6060000, /* PMMR */ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, -- GitLab From 93d2185dcabcf8ea08026234e58f5e31484ec6a6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 16 Mar 2016 00:48:11 +0000 Subject: [PATCH 0593/9938] pinctrl: sh-pfc: IPSRx and MOD_SELx should be set before GPSRx Gen2 / Gen3 datasheet will have below note in next version. This patch follows this note. IPSRx and MOD_SELx registers shall be set before setting GPSRx registers in case that they need to be configured. MOD_SELx registers can be set either earlier or later than setting IPSRx registers. Signed-off-by: Kuninori Morimoto Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/sh_pfc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index a490834e2089..87140790d1f1 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -276,7 +276,7 @@ struct sh_pfc_soc_info { * - msel: Module selector */ #define PINMUX_IPSR_MSEL(ipsr, fn, msel) \ - PINMUX_DATA(fn##_MARK, FN_##msel, FN_##ipsr, FN_##fn) + PINMUX_DATA(fn##_MARK, FN_##msel, FN_##fn, FN_##ipsr) /* * Describe a pinmux configuration for a single-function pin with GPIO -- GitLab From 3caa7d8c3f03ad6f1b66f10f67dc68cb3af55fe1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 23 Mar 2016 16:06:00 +0200 Subject: [PATCH 0594/9938] pinctrl: sh-pfc: Add drive strength support Add support for the drive-strengh pin configuration using the generic pinconf DT bindings. Signed-off-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- .../bindings/pinctrl/renesas,pfc-pinctrl.txt | 4 +- drivers/pinctrl/sh-pfc/core.c | 15 +++ drivers/pinctrl/sh-pfc/core.h | 3 + drivers/pinctrl/sh-pfc/pinctrl.c | 111 ++++++++++++++++++ drivers/pinctrl/sh-pfc/sh_pfc.h | 17 +++ 5 files changed, 148 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt index ffadb7a371f6..74e6ec0339d6 100644 --- a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt @@ -72,8 +72,8 @@ Pin Configuration Node Properties: The pin configuration parameters use the generic pinconf bindings defined in pinctrl-bindings.txt in this directory. The supported parameters are -bias-disable, bias-pull-up, bias-pull-down and power-source. For pins that -have a configurable I/O voltage, the power-source value should be the +bias-disable, bias-pull-up, bias-pull-down, drive strength and power-source. For +pins that have a configurable I/O voltage, the power-source value should be the nominal I/O voltage in millivolts. diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index dc3609f0c60b..0497bbb8a8e7 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -175,6 +175,21 @@ void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width, BUG(); } +u32 sh_pfc_read_reg(struct sh_pfc *pfc, u32 reg, unsigned int width) +{ + return sh_pfc_read_raw_reg(sh_pfc_phys_to_virt(pfc, reg), width); +} + +void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width, u32 data) +{ + if (pfc->info->unlock_reg) + sh_pfc_write_raw_reg( + sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32, + ~data); + + sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), width, data); +} + static void sh_pfc_config_reg_helper(struct sh_pfc *pfc, const struct pinmux_cfg_reg *crp, unsigned int in_pos, diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index 62f53b22ae85..fc05d0c516f3 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h @@ -62,6 +62,9 @@ int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc); u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width); void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width, u32 data); +u32 sh_pfc_read_reg(struct sh_pfc *pfc, u32 reg, unsigned int width); +void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width, + u32 data); int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin); int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type); diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index 87b0a599afaf..8efaa0631be6 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -476,6 +476,91 @@ static const struct pinmux_ops sh_pfc_pinmux_ops = { .gpio_set_direction = sh_pfc_gpio_set_direction, }; +static u32 sh_pfc_pinconf_find_drive_strength_reg(struct sh_pfc *pfc, + unsigned int pin, unsigned int *offset, unsigned int *size) +{ + const struct pinmux_drive_reg_field *field; + const struct pinmux_drive_reg *reg; + unsigned int i; + + for (reg = pfc->info->drive_regs; reg->reg; ++reg) { + for (i = 0; i < ARRAY_SIZE(reg->fields); ++i) { + field = ®->fields[i]; + + if (field->size && field->pin == pin) { + *offset = field->offset; + *size = field->size; + + return reg->reg; + } + } + } + + return 0; +} + +static int sh_pfc_pinconf_get_drive_strength(struct sh_pfc *pfc, + unsigned int pin) +{ + unsigned long flags; + unsigned int offset; + unsigned int size; + u32 reg; + u32 val; + + reg = sh_pfc_pinconf_find_drive_strength_reg(pfc, pin, &offset, &size); + if (!reg) + return -EINVAL; + + spin_lock_irqsave(&pfc->lock, flags); + val = sh_pfc_read_reg(pfc, reg, 32); + spin_unlock_irqrestore(&pfc->lock, flags); + + val = (val >> offset) & GENMASK(size - 1, 0); + + /* Convert the value to mA based on a full drive strength value of 24mA. + * We can make the full value configurable later if needed. + */ + return (val + 1) * (size == 2 ? 6 : 3); +} + +static int sh_pfc_pinconf_set_drive_strength(struct sh_pfc *pfc, + unsigned int pin, u16 strength) +{ + unsigned long flags; + unsigned int offset; + unsigned int size; + unsigned int step; + u32 reg; + u32 val; + + reg = sh_pfc_pinconf_find_drive_strength_reg(pfc, pin, &offset, &size); + if (!reg) + return -EINVAL; + + step = size == 2 ? 6 : 3; + + if (strength < step || strength > 24) + return -EINVAL; + + /* Convert the value from mA based on a full drive strength value of + * 24mA. We can make the full value configurable later if needed. + */ + strength = strength / step - 1; + + spin_lock_irqsave(&pfc->lock, flags); + + val = sh_pfc_read_reg(pfc, reg, 32); + val &= ~GENMASK(offset + size - 1, offset); + val |= strength << offset; + + sh_pfc_write_reg(pfc, reg, 32, val); + + spin_unlock_irqrestore(&pfc->lock, flags); + + return 0; +} + /* Check whether the requested parameter is supported for a pin. */ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin, enum pin_config_param param) @@ -493,6 +578,9 @@ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin, case PIN_CONFIG_BIAS_PULL_DOWN: return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN; + case PIN_CONFIG_DRIVE_STRENGTH: + return pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH; + case PIN_CONFIG_POWER_SOURCE: return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE; @@ -532,6 +620,17 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin, break; } + case PIN_CONFIG_DRIVE_STRENGTH: { + int ret; + + ret = sh_pfc_pinconf_get_drive_strength(pfc, _pin); + if (ret < 0) + return ret; + + *config = ret; + break; + } + case PIN_CONFIG_POWER_SOURCE: { int ret; @@ -584,6 +683,18 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin, break; + case PIN_CONFIG_DRIVE_STRENGTH: { + unsigned int arg = + pinconf_to_config_argument(configs[i]); + int ret; + + ret = sh_pfc_pinconf_set_drive_strength(pfc, _pin, arg); + if (ret < 0) + return ret; + + break; + } + case PIN_CONFIG_POWER_SOURCE: { unsigned int arg = pinconf_to_config_argument(configs[i]); diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 87140790d1f1..656ea32f776c 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -28,6 +28,7 @@ enum { #define SH_PFC_PIN_CFG_PULL_UP (1 << 2) #define SH_PFC_PIN_CFG_PULL_DOWN (1 << 3) #define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4) +#define SH_PFC_PIN_CFG_DRIVE_STRENGTH (1 << 5) #define SH_PFC_PIN_CFG_NO_GPIO (1 << 31) struct sh_pfc_pin { @@ -131,6 +132,21 @@ struct pinmux_cfg_reg { { var_fw0, var_fwn, 0 }, \ .enum_ids = (const u16 []) +struct pinmux_drive_reg_field { + u16 pin; + u8 offset; + u8 size; +}; + +struct pinmux_drive_reg { + u32 reg; + const struct pinmux_drive_reg_field fields[8]; +}; + +#define PINMUX_DRIVE_REG(name, r) \ + .reg = r, \ + .fields = + struct pinmux_data_reg { u32 reg; u8 reg_width; @@ -199,6 +215,7 @@ struct sh_pfc_soc_info { #endif const struct pinmux_cfg_reg *cfg_regs; + const struct pinmux_drive_reg *drive_regs; const struct pinmux_data_reg *data_regs; const u16 *pinmux_data; -- GitLab From 92e6d9a2cc827018a18885e0f3050ab9ff8c3206 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 23 Mar 2016 16:06:01 +0200 Subject: [PATCH 0595/9938] pinctrl: sh-pfc: r8a7795: Add drive strength support Define the drive strength registers for the R8A7795. As the PFC driver for the SoC only defines GPIO pins at the moment, limit drive strength support to those pins. Pins without GPIO capabilities will be supported later. Signed-off-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 218 ++++++++++++++++++++++++++- 1 file changed, 210 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index 5979dabc02fa..44632b1a5c97 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -14,14 +14,14 @@ #include "sh_pfc.h" #define CPU_ALL_PORT(fn, sfx) \ - PORT_GP_16(0, fn, sfx), \ - PORT_GP_28(1, fn, sfx), \ - PORT_GP_15(2, fn, sfx), \ - PORT_GP_16(3, fn, sfx), \ - PORT_GP_18(4, fn, sfx), \ - PORT_GP_26(5, fn, sfx), \ - PORT_GP_32(6, fn, sfx), \ - PORT_GP_4(7, fn, sfx) + PORT_GP_CFG_16(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ + PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ + PORT_GP_CFG_15(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ + PORT_GP_CFG_16(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ + PORT_GP_CFG_18(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ + PORT_GP_CFG_26(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ + PORT_GP_CFG_32(6, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ + PORT_GP_CFG_4(7, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH) /* * F_() : just information * FM() : macro for FN_xxx / xxx_MARK @@ -4564,6 +4564,207 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { { }, }; +static const struct pinmux_drive_reg pinmux_drive_regs[] = { + { PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) { + { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */ + { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */ + { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) { + { RCAR_GP_PIN(2, 12), 28, 3 }, /* AVB_LINK */ + { RCAR_GP_PIN(2, 13), 24, 3 }, /* AVB_AVTP_MATCH */ + { RCAR_GP_PIN(2, 14), 20, 3 }, /* AVB_AVTP_CAPTURE */ + { RCAR_GP_PIN(2, 0), 16, 3 }, /* IRQ0 */ + { RCAR_GP_PIN(2, 1), 12, 3 }, /* IRQ1 */ + { RCAR_GP_PIN(2, 2), 8, 3 }, /* IRQ2 */ + { RCAR_GP_PIN(2, 3), 4, 3 }, /* IRQ3 */ + { RCAR_GP_PIN(2, 4), 0, 3 }, /* IRQ4 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL5", 0xe6060314) { + { RCAR_GP_PIN(2, 5), 28, 3 }, /* IRQ5 */ + { RCAR_GP_PIN(2, 6), 24, 3 }, /* PWM0 */ + { RCAR_GP_PIN(2, 7), 20, 3 }, /* PWM1 */ + { RCAR_GP_PIN(2, 8), 16, 3 }, /* PWM2 */ + { RCAR_GP_PIN(1, 0), 12, 3 }, /* A0 */ + { RCAR_GP_PIN(1, 1), 8, 3 }, /* A1 */ + { RCAR_GP_PIN(1, 2), 4, 3 }, /* A2 */ + { RCAR_GP_PIN(1, 3), 0, 3 }, /* A3 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL6", 0xe6060318) { + { RCAR_GP_PIN(1, 4), 28, 3 }, /* A4 */ + { RCAR_GP_PIN(1, 5), 24, 3 }, /* A5 */ + { RCAR_GP_PIN(1, 6), 20, 3 }, /* A6 */ + { RCAR_GP_PIN(1, 7), 16, 3 }, /* A7 */ + { RCAR_GP_PIN(1, 8), 12, 3 }, /* A8 */ + { RCAR_GP_PIN(1, 9), 8, 3 }, /* A9 */ + { RCAR_GP_PIN(1, 10), 4, 3 }, /* A10 */ + { RCAR_GP_PIN(1, 11), 0, 3 }, /* A11 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL7", 0xe606031c) { + { RCAR_GP_PIN(1, 12), 28, 3 }, /* A12 */ + { RCAR_GP_PIN(1, 13), 24, 3 }, /* A13 */ + { RCAR_GP_PIN(1, 14), 20, 3 }, /* A14 */ + { RCAR_GP_PIN(1, 15), 16, 3 }, /* A15 */ + { RCAR_GP_PIN(1, 16), 12, 3 }, /* A16 */ + { RCAR_GP_PIN(1, 17), 8, 3 }, /* A17 */ + { RCAR_GP_PIN(1, 18), 4, 3 }, /* A18 */ + { RCAR_GP_PIN(1, 19), 0, 3 }, /* A19 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL8", 0xe6060320) { + { RCAR_GP_PIN(1, 20), 24, 3 }, /* CS0 */ + { RCAR_GP_PIN(1, 21), 20, 3 }, /* CS1_A26 */ + { RCAR_GP_PIN(1, 22), 16, 3 }, /* BS */ + { RCAR_GP_PIN(1, 23), 12, 3 }, /* RD */ + { RCAR_GP_PIN(1, 24), 8, 3 }, /* RD_WR */ + { RCAR_GP_PIN(1, 25), 4, 3 }, /* WE0 */ + { RCAR_GP_PIN(1, 26), 0, 3 }, /* WE1 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) { + { RCAR_GP_PIN(1, 27), 28, 3 }, /* EX_WAIT0 */ + { RCAR_GP_PIN(0, 0), 20, 3 }, /* D0 */ + { RCAR_GP_PIN(0, 1), 16, 3 }, /* D1 */ + { RCAR_GP_PIN(0, 2), 12, 3 }, /* D2 */ + { RCAR_GP_PIN(0, 3), 8, 3 }, /* D3 */ + { RCAR_GP_PIN(0, 4), 4, 3 }, /* D4 */ + { RCAR_GP_PIN(0, 5), 0, 3 }, /* D5 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL10", 0xe6060328) { + { RCAR_GP_PIN(0, 6), 28, 3 }, /* D6 */ + { RCAR_GP_PIN(0, 7), 24, 3 }, /* D7 */ + { RCAR_GP_PIN(0, 8), 20, 3 }, /* D8 */ + { RCAR_GP_PIN(0, 9), 16, 3 }, /* D9 */ + { RCAR_GP_PIN(0, 10), 12, 3 }, /* D10 */ + { RCAR_GP_PIN(0, 11), 8, 3 }, /* D11 */ + { RCAR_GP_PIN(0, 12), 4, 3 }, /* D12 */ + { RCAR_GP_PIN(0, 13), 0, 3 }, /* D13 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) { + { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */ + { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */ + { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */ + { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */ + { RCAR_GP_PIN(7, 2), 12, 3 }, /* HDMI0_CEC */ + { RCAR_GP_PIN(7, 3), 8, 3 }, /* HDMI1_CEC */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) { + { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */ + { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */ + { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */ + { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */ + { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */ + { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) { + { RCAR_GP_PIN(3, 6), 28, 3 }, /* SD1_CLK */ + { RCAR_GP_PIN(3, 7), 24, 3 }, /* SD1_CMD */ + { RCAR_GP_PIN(3, 8), 20, 3 }, /* SD1_DAT0 */ + { RCAR_GP_PIN(3, 9), 16, 3 }, /* SD1_DAT1 */ + { RCAR_GP_PIN(3, 10), 12, 3 }, /* SD1_DAT2 */ + { RCAR_GP_PIN(3, 11), 8, 3 }, /* SD1_DAT3 */ + { RCAR_GP_PIN(4, 0), 4, 3 }, /* SD2_CLK */ + { RCAR_GP_PIN(4, 1), 0, 3 }, /* SD2_CMD */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL15", 0xe606033c) { + { RCAR_GP_PIN(4, 2), 28, 3 }, /* SD2_DAT0 */ + { RCAR_GP_PIN(4, 3), 24, 3 }, /* SD2_DAT1 */ + { RCAR_GP_PIN(4, 4), 20, 3 }, /* SD2_DAT2 */ + { RCAR_GP_PIN(4, 5), 16, 3 }, /* SD2_DAT3 */ + { RCAR_GP_PIN(4, 6), 12, 3 }, /* SD2_DS */ + { RCAR_GP_PIN(4, 7), 8, 3 }, /* SD3_CLK */ + { RCAR_GP_PIN(4, 8), 4, 3 }, /* SD3_CMD */ + { RCAR_GP_PIN(4, 9), 0, 3 }, /* SD3_DAT0 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL16", 0xe6060340) { + { RCAR_GP_PIN(4, 10), 28, 3 }, /* SD3_DAT1 */ + { RCAR_GP_PIN(4, 11), 24, 3 }, /* SD3_DAT2 */ + { RCAR_GP_PIN(4, 12), 20, 3 }, /* SD3_DAT3 */ + { RCAR_GP_PIN(4, 13), 16, 3 }, /* SD3_DAT4 */ + { RCAR_GP_PIN(4, 14), 12, 3 }, /* SD3_DAT5 */ + { RCAR_GP_PIN(4, 15), 8, 3 }, /* SD3_DAT6 */ + { RCAR_GP_PIN(4, 16), 4, 3 }, /* SD3_DAT7 */ + { RCAR_GP_PIN(4, 17), 0, 3 }, /* SD3_DS */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL17", 0xe6060344) { + { RCAR_GP_PIN(3, 12), 28, 3 }, /* SD0_CD */ + { RCAR_GP_PIN(3, 13), 24, 3 }, /* SD0_WP */ + { RCAR_GP_PIN(3, 14), 20, 3 }, /* SD1_CD */ + { RCAR_GP_PIN(3, 15), 16, 3 }, /* SD1_WP */ + { RCAR_GP_PIN(5, 0), 12, 3 }, /* SCK0 */ + { RCAR_GP_PIN(5, 1), 8, 3 }, /* RX0 */ + { RCAR_GP_PIN(5, 2), 4, 3 }, /* TX0 */ + { RCAR_GP_PIN(5, 3), 0, 3 }, /* CTS0 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL18", 0xe6060348) { + { RCAR_GP_PIN(5, 4), 28, 3 }, /* RTS0_TANS */ + { RCAR_GP_PIN(5, 5), 24, 3 }, /* RX1 */ + { RCAR_GP_PIN(5, 6), 20, 3 }, /* TX1 */ + { RCAR_GP_PIN(5, 7), 16, 3 }, /* CTS1 */ + { RCAR_GP_PIN(5, 8), 12, 3 }, /* RTS1_TANS */ + { RCAR_GP_PIN(5, 9), 8, 3 }, /* SCK2 */ + { RCAR_GP_PIN(5, 10), 4, 3 }, /* TX2 */ + { RCAR_GP_PIN(5, 11), 0, 3 }, /* RX2 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL19", 0xe606034c) { + { RCAR_GP_PIN(5, 12), 28, 3 }, /* HSCK0 */ + { RCAR_GP_PIN(5, 13), 24, 3 }, /* HRX0 */ + { RCAR_GP_PIN(5, 14), 20, 3 }, /* HTX0 */ + { RCAR_GP_PIN(5, 15), 16, 3 }, /* HCTS0 */ + { RCAR_GP_PIN(5, 16), 12, 3 }, /* HRTS0 */ + { RCAR_GP_PIN(5, 17), 8, 3 }, /* MSIOF0_SCK */ + { RCAR_GP_PIN(5, 18), 4, 3 }, /* MSIOF0_SYNC */ + { RCAR_GP_PIN(5, 19), 0, 3 }, /* MSIOF0_SS1 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL20", 0xe6060350) { + { RCAR_GP_PIN(5, 20), 28, 3 }, /* MSIOF0_TXD */ + { RCAR_GP_PIN(5, 21), 24, 3 }, /* MSIOF0_SS2 */ + { RCAR_GP_PIN(5, 22), 20, 3 }, /* MSIOF0_RXD */ + { RCAR_GP_PIN(5, 23), 16, 3 }, /* MLB_CLK */ + { RCAR_GP_PIN(5, 24), 12, 3 }, /* MLB_SIG */ + { RCAR_GP_PIN(5, 25), 8, 3 }, /* MLB_DAT */ + { RCAR_GP_PIN(6, 0), 0, 3 }, /* SSI_SCK01239 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) { + { RCAR_GP_PIN(6, 1), 28, 3 }, /* SSI_WS01239 */ + { RCAR_GP_PIN(6, 2), 24, 3 }, /* SSI_SDATA0 */ + { RCAR_GP_PIN(6, 3), 20, 3 }, /* SSI_SDATA1 */ + { RCAR_GP_PIN(6, 4), 16, 3 }, /* SSI_SDATA2 */ + { RCAR_GP_PIN(6, 5), 12, 3 }, /* SSI_SCK34 */ + { RCAR_GP_PIN(6, 6), 8, 3 }, /* SSI_WS34 */ + { RCAR_GP_PIN(6, 7), 4, 3 }, /* SSI_SDATA3 */ + { RCAR_GP_PIN(6, 8), 0, 3 }, /* SSI_SCK4 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL22", 0xe6060358) { + { RCAR_GP_PIN(6, 9), 28, 3 }, /* SSI_WS4 */ + { RCAR_GP_PIN(6, 10), 24, 3 }, /* SSI_SDATA4 */ + { RCAR_GP_PIN(6, 11), 20, 3 }, /* SSI_SCK5 */ + { RCAR_GP_PIN(6, 12), 16, 3 }, /* SSI_WS5 */ + { RCAR_GP_PIN(6, 13), 12, 3 }, /* SSI_SDATA5 */ + { RCAR_GP_PIN(6, 14), 8, 3 }, /* SSI_SCK6 */ + { RCAR_GP_PIN(6, 15), 4, 3 }, /* SSI_WS6 */ + { RCAR_GP_PIN(6, 16), 0, 3 }, /* SSI_SDATA6 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL23", 0xe606035c) { + { RCAR_GP_PIN(6, 17), 28, 3 }, /* SSI_SCK78 */ + { RCAR_GP_PIN(6, 18), 24, 3 }, /* SSI_WS78 */ + { RCAR_GP_PIN(6, 19), 20, 3 }, /* SSI_SDATA7 */ + { RCAR_GP_PIN(6, 20), 16, 3 }, /* SSI_SDATA8 */ + { RCAR_GP_PIN(6, 21), 12, 3 }, /* SSI_SDATA9 */ + { RCAR_GP_PIN(6, 22), 8, 3 }, /* AUDIO_CLKA */ + { RCAR_GP_PIN(6, 23), 4, 3 }, /* AUDIO_CLKB */ + { RCAR_GP_PIN(6, 24), 0, 3 }, /* USB0_PWEN */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL24", 0xe6060360) { + { RCAR_GP_PIN(6, 25), 28, 3 }, /* USB0_OVC */ + { RCAR_GP_PIN(6, 26), 24, 3 }, /* USB1_PWEN */ + { RCAR_GP_PIN(6, 27), 20, 3 }, /* USB1_OVC */ + { RCAR_GP_PIN(6, 28), 16, 3 }, /* USB30_PWEN */ + { RCAR_GP_PIN(6, 29), 12, 3 }, /* USB30_OVC */ + { RCAR_GP_PIN(6, 30), 8, 3 }, /* USB31_PWEN */ + { RCAR_GP_PIN(6, 31), 4, 3 }, /* USB31_OVC */ + } }, + { }, +}; + const struct sh_pfc_soc_info r8a7795_pinmux_info = { .name = "r8a77950_pfc", .unlock_reg = 0xe6060000, /* PMMR */ @@ -4578,6 +4779,7 @@ const struct sh_pfc_soc_info r8a7795_pinmux_info = { .nr_functions = ARRAY_SIZE(pinmux_functions), .cfg_regs = pinmux_config_regs, + .drive_regs = pinmux_drive_regs, .pinmux_data = pinmux_data, .pinmux_data_size = ARRAY_SIZE(pinmux_data), -- GitLab From 847e87920c667ad9a9f4b628b60451c1471ae003 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 9 Mar 2016 17:56:02 +0100 Subject: [PATCH 0596/9938] clk: renesas: r8a7795: add PWM clock Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index b2198aef5ed4..9de458a6f7c8 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -148,6 +148,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1), DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1), + DEF_MOD("pwm", 523, R8A7795_CLK_S3D4), DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1), DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1), DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1), -- GitLab From ba8c1a81d4b7c22ac2d767265851ad77c4d01002 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 24 Mar 2016 13:50:41 +0100 Subject: [PATCH 0597/9938] clk: renesas: r8a7795: make SD clk definition specific for GEN3 About SD clocks: The clock type is Gen3 specific, the callbacks are all Gen3 specific; I think the clock definition should also be Gen3 specific and not in the general header file. Signed-off-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 11 +++++++---- drivers/clk/renesas/renesas-cpg-mssr.h | 3 --- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 9de458a6f7c8..9dc2b735ead8 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -65,6 +65,9 @@ enum r8a7795_clk_types { CLK_TYPE_GEN3_SD, }; +#define DEF_GEN3_SD(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) + static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -102,10 +105,10 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1), DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1), - DEF_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074), - DEF_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078), - DEF_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268), - DEF_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c), + DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074), + DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078), + DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268), + DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c), DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 952b6957233b..cad3c7d1b0c6 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -53,9 +53,6 @@ enum clk_types { DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) #define DEF_DIV6P1(_name, _id, _parent, _offset) \ DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset) -#define DEF_SD(_name, _id, _parent, _offset) \ - DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) - /* * Definitions of Module Clocks -- GitLab From 1b1e8e024b9ea4c07e05a44b9aeb48d5d89a06e0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Mar 2016 15:29:30 +0100 Subject: [PATCH 0598/9938] ARM: dts: ux500: use the GPIO DT header Use the header instead of using hardcoded values for the GPIO flags. Eradicate the totally bogus "0x4" flag used and set that to GPIO_ACTIVE_HIGH as is proper, switch the inverted card detect on the Snowball to flag using GPIO_ACTIVE_LOW instead of using the MMC-specific inversion flag. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-ccu9540.dts | 2 +- arch/arm/boot/dts/ste-dbx5x0.dtsi | 1 + arch/arm/boot/dts/ste-href-stuib.dtsi | 4 ++-- arch/arm/boot/dts/ste-href-tvk1281618.dtsi | 4 ++-- arch/arm/boot/dts/ste-hrefprev60.dtsi | 8 ++++---- arch/arm/boot/dts/ste-hrefv60plus.dtsi | 6 +++--- arch/arm/boot/dts/ste-snowball.dts | 19 +++++++++---------- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm/boot/dts/ste-ccu9540.dts b/arch/arm/boot/dts/ste-ccu9540.dts index c8b815819cfe..b3b9bb8e1aa8 100644 --- a/arch/arm/boot/dts/ste-ccu9540.dts +++ b/arch/arm/boot/dts/ste-ccu9540.dts @@ -49,7 +49,7 @@ cap-mmc-highspeed; vmmc-supply = <&ab8500_ldo_aux3_reg>; - cd-gpios = <&gpio7 6 0x4>; // 230 + cd-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>; // 230 cd-inverted; status = "okay"; diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 341f5b7ed242..d85830d80252 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include #include "skeleton.dtsi" / { diff --git a/arch/arm/boot/dts/ste-href-stuib.dtsi b/arch/arm/boot/dts/ste-href-stuib.dtsi index c3987ad06d79..6f720756057d 100644 --- a/arch/arm/boot/dts/ste-href-stuib.dtsi +++ b/arch/arm/boot/dts/ste-href-stuib.dtsi @@ -22,13 +22,13 @@ button@139 { /* Proximity sensor */ - gpios = <&gpio6 25 0x4>; + gpios = <&gpio6 25 GPIO_ACTIVE_HIGH>; linux,code = <11>; /* SW_FRONT_PROXIMITY */ label = "SFH7741 Proximity Sensor"; }; button@145 { /* Hall sensor */ - gpios = <&gpio4 17 0x4>; + gpios = <&gpio4 17 GPIO_ACTIVE_HIGH>; linux,code = <0>; /* SW_LID */ label = "HED54XXU11 Hall Effect Sensor"; }; diff --git a/arch/arm/boot/dts/ste-href-tvk1281618.dtsi b/arch/arm/boot/dts/ste-href-tvk1281618.dtsi index 55f9d0cc90f3..54d80da2a5df 100644 --- a/arch/arm/boot/dts/ste-href-tvk1281618.dtsi +++ b/arch/arm/boot/dts/ste-href-tvk1281618.dtsi @@ -24,13 +24,13 @@ button@139 { /* Proximity sensor */ - gpios = <&gpio6 25 0x4>; + gpios = <&gpio6 25 GPIO_ACTIVE_HIGH>; linux,code = <11>; /* SW_FRONT_PROXIMITY */ label = "SFH7741 Proximity Sensor"; }; button@145 { /* Hall sensor */ - gpios = <&gpio4 17 0x4>; + gpios = <&gpio4 17 GPIO_ACTIVE_HIGH>; linux,code = <0>; /* SW_LID */ label = "HED54XXU11 Hall Effect Sensor"; }; diff --git a/arch/arm/boot/dts/ste-hrefprev60.dtsi b/arch/arm/boot/dts/ste-hrefprev60.dtsi index b0278f4c486c..ece222d51717 100644 --- a/arch/arm/boot/dts/ste-hrefprev60.dtsi +++ b/arch/arm/boot/dts/ste-hrefprev60.dtsi @@ -18,7 +18,7 @@ / { gpio_keys { button@1 { - gpios = <&tc3589x_gpio 7 0x4>; + gpios = <&tc3589x_gpio 7 GPIO_ACTIVE_HIGH>; }; }; @@ -68,12 +68,12 @@ // External Micro SD slot sdi0_per1@80126000 { - cd-gpios = <&tc3589x_gpio 3 0x4>; + cd-gpios = <&tc3589x_gpio 3 GPIO_ACTIVE_HIGH>; }; vmmci: regulator-gpio { - gpios = <&tc3589x_gpio 18 0x4>; - enable-gpio = <&tc3589x_gpio 17 0x4>; + gpios = <&tc3589x_gpio 18 GPIO_ACTIVE_HIGH>; + enable-gpio = <&tc3589x_gpio 17 GPIO_ACTIVE_HIGH>; }; pinctrl { diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/ste-hrefv60plus.dtsi index 149a72e7e37a..45d7af326718 100644 --- a/arch/arm/boot/dts/ste-hrefv60plus.dtsi +++ b/arch/arm/boot/dts/ste-hrefv60plus.dtsi @@ -20,12 +20,12 @@ soc { // External Micro SD slot sdi0_per1@80126000 { - cd-gpios = <&gpio2 31 0x4>; // 95 + cd-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>; // 95 }; vmmci: regulator-gpio { - gpios = <&gpio0 5 0x4>; - enable-gpio = <&gpio5 9 0x4>; + gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + enable-gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>; }; pinctrl { diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts index 08f82077b64d..36e84efc401c 100644 --- a/arch/arm/boot/dts/ste-snowball.dts +++ b/arch/arm/boot/dts/ste-snowball.dts @@ -50,35 +50,35 @@ wakeup-source; linux,code = <2>; label = "userpb"; - gpios = <&gpio1 0 0x4>; + gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; }; button@2 { debounce_interval = <50>; wakeup-source; linux,code = <3>; label = "extkb1"; - gpios = <&gpio4 23 0x4>; + gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>; }; button@3 { debounce_interval = <50>; wakeup-source; linux,code = <4>; label = "extkb2"; - gpios = <&gpio4 24 0x4>; + gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>; }; button@4 { debounce_interval = <50>; wakeup-source; linux,code = <5>; label = "extkb3"; - gpios = <&gpio5 1 0x4>; + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; }; button@5 { debounce_interval = <50>; wakeup-source; linux,code = <6>; label = "extkb4"; - gpios = <&gpio5 2 0x4>; + gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; }; }; @@ -88,7 +88,7 @@ pinctrl-0 = <&gpioled_snowball_mode>; used-led { label = "user_led"; - gpios = <&gpio4 14 0x4>; + gpios = <&gpio4 14 GPIO_ACTIVE_HIGH>; default-state = "on"; linux,default-trigger = "heartbeat"; }; @@ -155,8 +155,8 @@ vmmci: regulator-gpio { compatible = "regulator-gpio"; - gpios = <&gpio7 4 0x4>; - enable-gpio = <&gpio6 25 0x4>; + gpios = <&gpio7 4 GPIO_ACTIVE_HIGH>; + enable-gpio = <&gpio6 25 GPIO_ACTIVE_HIGH>; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <2900000>; @@ -182,8 +182,7 @@ pinctrl-0 = <&sdi0_default_mode>; pinctrl-1 = <&sdi0_sleep_mode>; - cd-gpios = <&gpio6 26 0x4>; // 218 - cd-inverted; + cd-gpios = <&gpio6 26 GPIO_ACTIVE_LOW>; // 218 status = "okay"; }; -- GitLab From 0bfe5167b2d897a27b8a561d9b8b09026d8b16bd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Mar 2016 15:48:47 +0100 Subject: [PATCH 0599/9938] ARM: dts: ux500: use the GIC include header Use the header for generating the flags for the first cell of the interrupt definitions. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-dbx5x0.dtsi | 91 ++++++++++++++++--------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index d85830d80252..6ae56838bd3a 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -204,14 +205,14 @@ L2: l2-cache { compatible = "arm,pl310-cache"; reg = <0xa0412000 0x1000>; - interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; cache-unified; cache-level = <2>; }; pmu { compatible = "arm,cortex-a9-pmu"; - interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; }; pm_domains: pm_domains0 { @@ -254,7 +255,7 @@ /* Nomadik System Timer */ compatible = "st,nomadik-mtu"; reg = <0xa03c6000 0x1000>; - interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; clocks = <&prcmu_clk PRCMU_TIMCLK>, <&prcc_pclk 6 6>; clock-names = "timclk", "apb_pclk"; @@ -263,7 +264,7 @@ timer@a0410600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0xa0410600 0x20>; - interrupts = <1 13 0x304>; /* IRQ level high per-CPU */ + interrupts = ; clocks = <&smp_twd_clk>; }; @@ -271,14 +272,14 @@ watchdog@a0410620 { compatible = "arm,cortex-a9-twd-wdt"; reg = <0xa0410620 0x20>; - interrupts = <1 14 0x304>; + interrupts = ; clocks = <&smp_twd_clk>; }; rtc@80154000 { compatible = "arm,rtc-pl031", "arm,primecell"; reg = <0x80154000 0x1000>; - interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; clocks = <&rtc_clk>; clock-names = "apb_pclk"; @@ -288,7 +289,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8012e000 0x80>; - interrupts = <0 119 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -303,7 +304,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8012e080 0x80>; - interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -318,7 +319,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8000e000 0x80>; - interrupts = <0 121 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -333,7 +334,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8000e080 0x80>; - interrupts = <0 122 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -348,7 +349,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8000e100 0x80>; - interrupts = <0 123 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -363,7 +364,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8000e180 0x80>; - interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -378,7 +379,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8011e000 0x80>; - interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -393,7 +394,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0x8011e080 0x80>; - interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -408,7 +409,7 @@ compatible = "stericsson,db8500-gpio", "st,nomadik-gpio"; reg = <0xa03fe000 0x80>; - interrupts = <0 127 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; st,supports-sleepmode; @@ -430,7 +431,7 @@ usb_per5@a03e0000 { compatible = "stericsson,db8500-musb"; reg = <0xa03e0000 0x10000>; - interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-names = "mc"; dr_mode = "otg"; @@ -468,7 +469,7 @@ compatible = "stericsson,db8500-dma40", "stericsson,dma40"; reg = <0x801C0000 0x1000 0x40010000 0x800>; reg-names = "base", "lcpa"; - interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #dma-cells = <3>; memcpy-channels = <56 57 58 59 60>; @@ -480,7 +481,7 @@ compatible = "stericsson,db8500-prcmu"; reg = <0x80157000 0x2000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>; reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm"; - interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <1>; interrupt-controller; @@ -598,7 +599,7 @@ ab8500 { compatible = "stericsson,ab8500"; interrupt-parent = <&intc>; - interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; interrupt-controller; #interrupt-cells = <2>; @@ -786,7 +787,7 @@ i2c@80004000 { compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80004000 0x1000>; - interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; @@ -801,7 +802,7 @@ i2c@80122000 { compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80122000 0x1000>; - interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; @@ -817,7 +818,7 @@ i2c@80128000 { compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80128000 0x1000>; - interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; @@ -833,7 +834,7 @@ i2c@80110000 { compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80110000 0x1000>; - interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; @@ -849,7 +850,7 @@ i2c@8012a000 { compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x8012a000 0x1000>; - interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; @@ -865,7 +866,7 @@ ssp@80002000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x80002000 0x1000>; - interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&prcc_kclk 3 1>, <&prcc_pclk 3 1>; @@ -879,7 +880,7 @@ ssp@80003000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x80003000 0x1000>; - interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&prcc_kclk 3 2>, <&prcc_pclk 3 2>; @@ -893,7 +894,7 @@ spi@8011a000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x8011a000 0x1000>; - interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; /* Same clock wired to kernel and pclk */ @@ -908,7 +909,7 @@ spi@80112000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x80112000 0x1000>; - interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; /* Same clock wired to kernel and pclk */ @@ -923,7 +924,7 @@ spi@80111000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x80111000 0x1000>; - interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; /* Same clock wired to kernel and pclk */ @@ -938,7 +939,7 @@ spi@80129000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x80129000 0x1000>; - interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; #address-cells = <1>; #size-cells = <0>; /* Same clock wired to kernel and pclk */ @@ -953,7 +954,7 @@ ux500_serial0: uart@80120000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x80120000 0x1000>; - interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 13 0 0x2>, /* Logical - DevToMem */ <&dma 13 0 0x0>; /* Logical - MemToDev */ @@ -968,7 +969,7 @@ ux500_serial1: uart@80121000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x80121000 0x1000>; - interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 12 0 0x2>, /* Logical - DevToMem */ <&dma 12 0 0x0>; /* Logical - MemToDev */ @@ -983,7 +984,7 @@ ux500_serial2: uart@80007000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x80007000 0x1000>; - interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 11 0 0x2>, /* Logical - DevToMem */ <&dma 11 0 0x0>; /* Logical - MemToDev */ @@ -998,7 +999,7 @@ sdi0_per1@80126000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80126000 0x1000>; - interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 29 0 0x2>, /* Logical - DevToMem */ <&dma 29 0 0x0>; /* Logical - MemToDev */ @@ -1014,7 +1015,7 @@ sdi1_per2@80118000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80118000 0x1000>; - interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 32 0 0x2>, /* Logical - DevToMem */ <&dma 32 0 0x0>; /* Logical - MemToDev */ @@ -1030,7 +1031,7 @@ sdi2_per3@80005000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80005000 0x1000>; - interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 28 0 0x2>, /* Logical - DevToMem */ <&dma 28 0 0x0>; /* Logical - MemToDev */ @@ -1046,7 +1047,7 @@ sdi3_per2@80119000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80119000 0x1000>; - interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 41 0 0x2>, /* Logical - DevToMem */ <&dma 41 0 0x0>; /* Logical - MemToDev */ @@ -1062,7 +1063,7 @@ sdi4_per2@80114000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80114000 0x1000>; - interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 42 0 0x2>, /* Logical - DevToMem */ <&dma 42 0 0x0>; /* Logical - MemToDev */ @@ -1078,7 +1079,7 @@ sdi5_per3@80008000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80008000 0x1000>; - interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; dmas = <&dma 43 0 0x2>, /* Logical - DevToMem */ <&dma 43 0 0x0>; /* Logical - MemToDev */ @@ -1094,7 +1095,7 @@ msp0: msp@80123000 { compatible = "stericsson,ux500-msp-i2s"; reg = <0x80123000 0x1000>; - interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; v-ape-supply = <&db8500_vape_reg>; dmas = <&dma 31 0 0x12>, /* Logical - DevToMem - HighPrio */ @@ -1110,7 +1111,7 @@ msp1: msp@80124000 { compatible = "stericsson,ux500-msp-i2s"; reg = <0x80124000 0x1000>; - interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; v-ape-supply = <&db8500_vape_reg>; /* This DMA channel only exist on DB8500 v1 */ @@ -1127,7 +1128,7 @@ msp2: msp@80117000 { compatible = "stericsson,ux500-msp-i2s"; reg = <0x80117000 0x1000>; - interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; v-ape-supply = <&db8500_vape_reg>; dmas = <&dma 14 0 0x12>, /* Logical - DevToMem - HighPrio */ @@ -1144,7 +1145,7 @@ msp3: msp@80125000 { compatible = "stericsson,ux500-msp-i2s"; reg = <0x80125000 0x1000>; - interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; v-ape-supply = <&db8500_vape_reg>; /* This DMA channel only exist on DB8500 v2 */ @@ -1177,7 +1178,7 @@ <0xa0351000 0x1000>, /* DSI link 1 */ <0xa0352000 0x1000>, /* DSI link 2 */ <0xa0353000 0x1000>; /* DSI link 3 */ - interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */ <&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */ <&prcmu_clk PRCMU_PLLDSI>, /* HDMI clock */ @@ -1191,7 +1192,7 @@ cryp@a03cb000 { compatible = "stericsson,ux500-cryp"; reg = <0xa03cb000 0x1000>; - interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; v-ape-supply = <&db8500_vape_reg>; clocks = <&prcc_pclk 6 1>; -- GitLab From 3a8f21f170dc7c85f9c0fc5cc49a2fd31bd00628 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:38 -0500 Subject: [PATCH 0600/9938] EDAC, altera: Make L2C depend on L2x0 cache controller Make L2 cache depend instead of forcibly select the L2 cache support. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-2-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 37755e63cc28..6ca7474baf4a 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -378,12 +378,11 @@ config EDAC_ALTERA config EDAC_ALTERA_L2C bool "Altera L2 Cache ECC" - depends on EDAC_ALTERA=y - select CACHE_L2X0 + depends on EDAC_ALTERA=y && CACHE_L2X0 help Support for error detection and correction on the Altera L2 cache Memory for Altera SoCs. This option - requires L2 cache so it will force that selection. + requires L2 cache. config EDAC_ALTERA_OCRAM bool "Altera On-Chip RAM ECC" -- GitLab From 05b088b6f8f21ed6a451c9a5fc8ec23cec665f12 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:39 -0500 Subject: [PATCH 0601/9938] EDAC, altera: Move device structs and defines to the header Move the device structs and defines to altera_edac.h in preparation for adding the Arria10 L2 cache ECC. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-3-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 43 ------------------------------------- drivers/edac/altera_edac.h | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 63e42098726d..eee7a395666e 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -78,27 +78,6 @@ static const struct altr_sdram_prv_data a10_data = { .ue_set_mask = A10_DIAGINT_TDERRA_MASK, }; -/************************** EDAC Device Defines **************************/ - -/* OCRAM ECC Management Group Defines */ -#define ALTR_MAN_GRP_OCRAM_ECC_OFFSET 0x04 -#define ALTR_OCR_ECC_EN BIT(0) -#define ALTR_OCR_ECC_INJS BIT(1) -#define ALTR_OCR_ECC_INJD BIT(2) -#define ALTR_OCR_ECC_SERR BIT(3) -#define ALTR_OCR_ECC_DERR BIT(4) - -/* L2 ECC Management Group Defines */ -#define ALTR_MAN_GRP_L2_ECC_OFFSET 0x00 -#define ALTR_L2_ECC_EN BIT(0) -#define ALTR_L2_ECC_INJS BIT(1) -#define ALTR_L2_ECC_INJD BIT(2) - -#define ALTR_UE_TRIGGER_CHAR 'U' /* Trigger for UE */ -#define ALTR_TRIGGER_READ_WRD_CNT 32 /* Line size x 4 */ -#define ALTR_TRIG_OCRAM_BYTE_SIZE 128 /* Line size x 4 */ -#define ALTR_TRIG_L2C_BYTE_SIZE 4096 /* Full Page */ - /*********************** EDAC Memory Controller Functions ****************/ /* The SDRAM controller uses the EDAC Memory Controller framework. */ @@ -571,28 +550,6 @@ module_platform_driver(altr_edac_driver); const struct edac_device_prv_data ocramecc_data; const struct edac_device_prv_data l2ecc_data; -struct edac_device_prv_data { - int (*setup)(struct platform_device *pdev, void __iomem *base); - int ce_clear_mask; - int ue_clear_mask; - char dbgfs_name[20]; - void * (*alloc_mem)(size_t size, void **other); - void (*free_mem)(void *p, size_t size, void *other); - int ecc_enable_mask; - int ce_set_mask; - int ue_set_mask; - int trig_alloc_sz; -}; - -struct altr_edac_device_dev { - void __iomem *base; - int sb_irq; - int db_irq; - const struct edac_device_prv_data *data; - struct dentry *debugfs_dir; - char *edac_dev_name; -}; - static irqreturn_t altr_edac_device_handler(int irq, void *dev_id) { irqreturn_t ret_value = IRQ_NONE; diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index 953077d3e4f3..993bb0a7a372 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -195,4 +195,48 @@ struct altr_sdram_mc_data { const struct altr_sdram_prv_data *data; }; +/************************** EDAC Device Defines **************************/ +/***** General Device Trigger Defines *****/ +#define ALTR_UE_TRIGGER_CHAR 'U' /* Trigger for UE */ +#define ALTR_TRIGGER_READ_WRD_CNT 32 /* Line size x 4 */ +#define ALTR_TRIG_OCRAM_BYTE_SIZE 128 /* Line size x 4 */ +#define ALTR_TRIG_L2C_BYTE_SIZE 4096 /* Full Page */ + +/******* Cyclone5 and Arria5 Defines *******/ +/* OCRAM ECC Management Group Defines */ +#define ALTR_MAN_GRP_OCRAM_ECC_OFFSET 0x04 +#define ALTR_OCR_ECC_EN BIT(0) +#define ALTR_OCR_ECC_INJS BIT(1) +#define ALTR_OCR_ECC_INJD BIT(2) +#define ALTR_OCR_ECC_SERR BIT(3) +#define ALTR_OCR_ECC_DERR BIT(4) + +/* L2 ECC Management Group Defines */ +#define ALTR_MAN_GRP_L2_ECC_OFFSET 0x00 +#define ALTR_L2_ECC_EN BIT(0) +#define ALTR_L2_ECC_INJS BIT(1) +#define ALTR_L2_ECC_INJD BIT(2) + +struct edac_device_prv_data { + int (*setup)(struct platform_device *pdev, void __iomem *base); + int ce_clear_mask; + int ue_clear_mask; + char dbgfs_name[20]; + void * (*alloc_mem)(size_t size, void **other); + void (*free_mem)(void *p, size_t size, void *other); + int ecc_enable_mask; + int ce_set_mask; + int ue_set_mask; + int trig_alloc_sz; +}; + +struct altr_edac_device_dev { + void __iomem *base; + int sb_irq; + int db_irq; + const struct edac_device_prv_data *data; + struct dentry *debugfs_dir; + char *edac_dev_name; +}; + #endif /* #ifndef _ALTERA_EDAC_H */ -- GitLab From 328ca7ae81dd842ff56b35f1e8422e6af1c80c14 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:40 -0500 Subject: [PATCH 0602/9938] EDAC, altera: Remove platform device from check_deps() In preparation for the Arria10 peripheral ECCs, remove the platform device parameter from the check_deps() functions because it is not needed and makes the Arria10 check_deps() cleaner. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-4-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 10 +++++----- drivers/edac/altera_edac.h | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index eee7a395666e..e20a045cbf20 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -746,7 +746,7 @@ static int altr_edac_device_probe(struct platform_device *pdev) /* Check specific dependencies for the module */ if (drvdata->data->setup) { - res = drvdata->data->setup(pdev, drvdata->base); + res = drvdata->data->setup(drvdata); if (res) goto fail1; } @@ -856,9 +856,9 @@ static void ocram_free_mem(void *p, size_t size, void *other) * Can't turn on ECC here because accessing un-initialized * memory will cause CE/UE errors possibly causing an ABORT. */ -static int altr_ocram_check_deps(struct platform_device *pdev, - void __iomem *base) +static int altr_ocram_check_deps(struct altr_edac_device_dev *device) { + void __iomem *base = device->base; if (readl(base) & ALTR_OCR_ECC_EN) return 0; @@ -923,9 +923,9 @@ static void l2_free_mem(void *p, size_t size, void *other) * Bail if ECC is not enabled. * Note that L2 Cache Enable is forced at build time. */ -static int altr_l2_check_deps(struct platform_device *pdev, - void __iomem *base) +static int altr_l2_check_deps(struct altr_edac_device_dev *device) { + void __iomem *base = device->base; if (readl(base) & ALTR_L2_ECC_EN) return 0; diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index 993bb0a7a372..32c798a6f980 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -217,8 +217,10 @@ struct altr_sdram_mc_data { #define ALTR_L2_ECC_INJS BIT(1) #define ALTR_L2_ECC_INJD BIT(2) +struct altr_edac_device_dev; + struct edac_device_prv_data { - int (*setup)(struct platform_device *pdev, void __iomem *base); + int (*setup)(struct altr_edac_device_dev *device); int ce_clear_mask; int ue_clear_mask; char dbgfs_name[20]; -- GitLab From 27439a1a632d9936159863fb11f5bc4d55eaab04 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:41 -0500 Subject: [PATCH 0603/9938] EDAC, altera: Abstract ECC Enable Mask in check_deps() In preparation for the Arria10 peripheral ECCs, use the ECC Enable mask in place of hard coded masks in the check dependency functions. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-5-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index e20a045cbf20..0dbfa473f853 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -859,7 +859,9 @@ static void ocram_free_mem(void *p, size_t size, void *other) static int altr_ocram_check_deps(struct altr_edac_device_dev *device) { void __iomem *base = device->base; - if (readl(base) & ALTR_OCR_ECC_EN) + const struct edac_device_prv_data *prv = device->data; + + if (readl(base) & prv->ecc_enable_mask) return 0; edac_printk(KERN_ERR, EDAC_DEVICE, @@ -926,7 +928,10 @@ static void l2_free_mem(void *p, size_t size, void *other) static int altr_l2_check_deps(struct altr_edac_device_dev *device) { void __iomem *base = device->base; - if (readl(base) & ALTR_L2_ECC_EN) + const struct edac_device_prv_data *prv = device->data; + + if ((readl(base) & prv->ecc_enable_mask) == + prv->ecc_enable_mask) return 0; edac_printk(KERN_ERR, EDAC_DEVICE, -- GitLab From 811fce4f2a7aea0cd93815d0eaf42fbcc98bd930 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:42 -0500 Subject: [PATCH 0604/9938] EDAC, altera: Add register offset for ECC Error Inject In preparation for the Arria10 peripheral ECCs, add a register offset from the ECC base to the private data structure to index to the error injection register. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-6-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 7 +++++-- drivers/edac/altera_edac.h | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 0dbfa473f853..502bf1fcf9e5 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -622,8 +622,9 @@ static ssize_t altr_edac_device_trig(struct file *file, if (ACCESS_ONCE(ptemp[i])) result = -1; /* Toggle Error bit (it is latched), leave ECC enabled */ - writel(error_mask, drvdata->base); - writel(priv->ecc_enable_mask, drvdata->base); + writel(error_mask, (drvdata->base + priv->set_err_ofst)); + writel(priv->ecc_enable_mask, (drvdata->base + + priv->set_err_ofst)); ptemp[i] = i; } /* Ensure it has been written out */ @@ -879,6 +880,7 @@ const struct edac_device_prv_data ocramecc_data = { .ecc_enable_mask = ALTR_OCR_ECC_EN, .ce_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJS), .ue_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJD), + .set_err_ofst = ALTR_OCR_ECC_REG_OFFSET, .trig_alloc_sz = ALTR_TRIG_OCRAM_BYTE_SIZE, }; @@ -949,6 +951,7 @@ const struct edac_device_prv_data l2ecc_data = { .ecc_enable_mask = ALTR_L2_ECC_EN, .ce_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJS), .ue_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJD), + .set_err_ofst = ALTR_L2_ECC_REG_OFFSET, .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE, }; diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index 32c798a6f980..d7ef94c13b98 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -205,6 +205,7 @@ struct altr_sdram_mc_data { /******* Cyclone5 and Arria5 Defines *******/ /* OCRAM ECC Management Group Defines */ #define ALTR_MAN_GRP_OCRAM_ECC_OFFSET 0x04 +#define ALTR_OCR_ECC_REG_OFFSET 0x00 #define ALTR_OCR_ECC_EN BIT(0) #define ALTR_OCR_ECC_INJS BIT(1) #define ALTR_OCR_ECC_INJD BIT(2) @@ -213,6 +214,7 @@ struct altr_sdram_mc_data { /* L2 ECC Management Group Defines */ #define ALTR_MAN_GRP_L2_ECC_OFFSET 0x00 +#define ALTR_L2_ECC_REG_OFFSET 0x00 #define ALTR_L2_ECC_EN BIT(0) #define ALTR_L2_ECC_INJS BIT(1) #define ALTR_L2_ECC_INJD BIT(2) @@ -229,6 +231,7 @@ struct edac_device_prv_data { int ecc_enable_mask; int ce_set_mask; int ue_set_mask; + int set_err_ofst; int trig_alloc_sz; }; -- GitLab From 8b39ab7290d571b91867b15c02a59edf0a5b00bb Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:43 -0500 Subject: [PATCH 0605/9938] Documentation, dt, socfpga: Add Altera Arria10 L2 cache binding Add the device tree bindings needed to support the Altera L2 cache on the Arria10 chip. Since all the peripherals share IRQs, the IRQ fields are now in the ecc_manager. Signed-off-by: Thor Thayer Acked-by: Rob Herring Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-7-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- .../bindings/arm/altera/socfpga-eccmgr.txt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt index 885f93d14ef9..37ff9bfea5f4 100644 --- a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt +++ b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt @@ -3,6 +3,7 @@ This driver uses the EDAC framework to implement the SOCFPGA ECC Manager. The ECC Manager counts and corrects single bit errors and counts/handles double bit errors which are uncorrectable. +Cyclone5 and Arria5 ECC Manager Required Properties: - compatible : Should be "altr,socfpga-ecc-manager" - #address-cells: must be 1 @@ -47,3 +48,42 @@ Example: interrupts = <0 178 1>, <0 179 1>; }; }; + +Arria10 SoCFPGA ECC Manager +The Arria10 SoC ECC Manager handles the IRQs for each peripheral +in a shared register instead of individual IRQs like the Cyclone5 +and Arria5. Therefore the device tree is different as well. + +Required Properties: +- compatible : Should be "altr,socfpga-a10-ecc-manager" +- altr,sysgr-syscon : phandle to Arria10 System Manager Block + containing the ECC manager registers. +- #address-cells: must be 1 +- #size-cells: must be 1 +- interrupts : Should be single bit error interrupt, then double bit error + interrupt. Note the rising edge type. +- ranges : standard definition, should translate from local addresses + +Subcomponents: + +L2 Cache ECC +Required Properties: +- compatible : Should be "altr,socfpga-a10-l2-ecc" +- reg : Address and size for ECC error interrupt clear registers. + +Example: + + eccmgr: eccmgr@ffd06000 { + compatible = "altr,socfpga-a10-ecc-manager"; + altr,sysmgr-syscon = <&sysmgr>; + #address-cells = <1>; + #size-cells = <1>; + interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>, + <0 0 IRQ_TYPE_LEVEL_HIGH>; + ranges; + + l2-ecc@ffd06010 { + compatible = "altr,socfpga-a10-l2-ecc"; + reg = <0xffd06010 0x4>; + }; + }; -- GitLab From 588cb03ea208b303e6dee7e916f329043fd0fc26 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:44 -0500 Subject: [PATCH 0606/9938] EDAC, altera: Add Arria10 L2 Cache ECC handling Add a private data structure for Arria10 L2 cache ECC and the probe function for it. The Arria10 ECC device IRQs are in a shared register so the ECC Manager parent/child relationship requires a different probe function. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-8-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 231 +++++++++++++++++++++++++++++++++++++ drivers/edac/altera_edac.h | 42 +++++++ 2 files changed, 273 insertions(+) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 502bf1fcf9e5..0afdc582766e 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -549,6 +550,7 @@ module_platform_driver(altr_edac_driver); const struct edac_device_prv_data ocramecc_data; const struct edac_device_prv_data l2ecc_data; +const struct edac_device_prv_data a10_l2ecc_data; static irqreturn_t altr_edac_device_handler(int irq, void *dev_id) { @@ -673,6 +675,8 @@ static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci, static const struct of_device_id altr_edac_device_of_match[] = { #ifdef CONFIG_EDAC_ALTERA_L2C { .compatible = "altr,socfpga-l2-ecc", .data = (void *)&l2ecc_data }, + { .compatible = "altr,socfpga-a10-l2-ecc", + .data = (void *)&a10_l2ecc_data }, #endif #ifdef CONFIG_EDAC_ALTERA_OCRAM { .compatible = "altr,socfpga-ocram-ecc", @@ -941,6 +945,24 @@ static int altr_l2_check_deps(struct altr_edac_device_dev *device) return -ENODEV; } +static irqreturn_t altr_edac_a10_l2_irq(struct altr_edac_device_dev *dci, + bool sberr) +{ + if (sberr) { + regmap_write(dci->edac->ecc_mgr_map, + A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST, + A10_SYSGMR_MPU_CLEAR_L2_ECC_SB); + edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name); + } else { + regmap_write(dci->edac->ecc_mgr_map, + A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST, + A10_SYSGMR_MPU_CLEAR_L2_ECC_MB); + edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name); + panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n"); + } + return IRQ_HANDLED; +} + const struct edac_device_prv_data l2ecc_data = { .setup = altr_l2_check_deps, .ce_clear_mask = 0, @@ -955,8 +977,217 @@ const struct edac_device_prv_data l2ecc_data = { .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE, }; +const struct edac_device_prv_data a10_l2ecc_data = { + .setup = altr_l2_check_deps, + .ce_clear_mask = ALTR_A10_L2_ECC_SERR_CLR, + .ue_clear_mask = ALTR_A10_L2_ECC_MERR_CLR, + .irq_status_mask = A10_SYSMGR_ECC_INTSTAT_L2, + .dbgfs_name = "altr_l2_trigger", + .alloc_mem = l2_alloc_mem, + .free_mem = l2_free_mem, + .ecc_enable_mask = ALTR_A10_L2_ECC_EN_CTL, + .ce_set_mask = ALTR_A10_L2_ECC_CE_INJ_MASK, + .ue_set_mask = ALTR_A10_L2_ECC_UE_INJ_MASK, + .set_err_ofst = ALTR_A10_L2_ECC_INJ_OFST, + .ecc_irq_handler = altr_edac_a10_l2_irq, + .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE, +}; + #endif /* CONFIG_EDAC_ALTERA_L2C */ +/********************* Arria10 EDAC Device Functions *************************/ + +/* + * The Arria10 EDAC Device Functions differ from the Cyclone5/Arria5 + * because 2 IRQs are shared among the all ECC peripherals. The ECC + * manager manages the IRQs and the children. + * Based on xgene_edac.c peripheral code. + */ + +static irqreturn_t altr_edac_a10_irq_handler(int irq, void *dev_id) +{ + irqreturn_t rc = IRQ_NONE; + struct altr_arria10_edac *edac = dev_id; + struct altr_edac_device_dev *dci; + int irq_status; + bool sberr = (irq == edac->sb_irq) ? 1 : 0; + int sm_offset = sberr ? A10_SYSMGR_ECC_INTSTAT_SERR_OFST : + A10_SYSMGR_ECC_INTSTAT_DERR_OFST; + + regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status); + + if ((irq != edac->sb_irq) && (irq != edac->db_irq)) { + WARN_ON(1); + } else { + list_for_each_entry(dci, &edac->a10_ecc_devices, next) { + if (irq_status & dci->data->irq_status_mask) + rc = dci->data->ecc_irq_handler(dci, sberr); + } + } + + return rc; +} + +static int altr_edac_a10_device_add(struct altr_arria10_edac *edac, + struct device_node *np) +{ + struct edac_device_ctl_info *dci; + struct altr_edac_device_dev *altdev; + char *ecc_name = (char *)np->name; + struct resource res; + int edac_idx; + int rc = 0; + const struct edac_device_prv_data *prv; + /* Get matching node and check for valid result */ + const struct of_device_id *pdev_id = + of_match_node(altr_edac_device_of_match, np); + if (IS_ERR_OR_NULL(pdev_id)) + return -ENODEV; + + /* Get driver specific data for this EDAC device */ + prv = pdev_id->data; + if (IS_ERR_OR_NULL(prv)) + return -ENODEV; + + if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL)) + return -ENOMEM; + + rc = of_address_to_resource(np, 0, &res); + if (rc < 0) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s: no resource address\n", ecc_name); + goto err_release_group; + } + + edac_idx = edac_device_alloc_index(); + dci = edac_device_alloc_ctl_info(sizeof(*altdev), ecc_name, + 1, ecc_name, 1, 0, NULL, 0, + edac_idx); + + if (!dci) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s: Unable to allocate EDAC device\n", ecc_name); + rc = -ENOMEM; + goto err_release_group; + } + + altdev = dci->pvt_info; + dci->dev = edac->dev; + altdev->edac_dev_name = ecc_name; + altdev->edac_idx = edac_idx; + altdev->edac = edac; + altdev->edac_dev = dci; + altdev->data = prv; + altdev->ddev = *edac->dev; + dci->dev = &altdev->ddev; + dci->ctl_name = "Altera ECC Manager"; + dci->mod_name = ecc_name; + dci->dev_name = ecc_name; + + altdev->base = devm_ioremap_resource(edac->dev, &res); + if (IS_ERR(altdev->base)) { + rc = PTR_ERR(altdev->base); + goto err_release_group1; + } + + /* Check specific dependencies for the module */ + if (altdev->data->setup) { + rc = altdev->data->setup(altdev); + if (rc) + goto err_release_group1; + } + + rc = edac_device_add_device(dci); + if (rc) { + dev_err(edac->dev, "edac_device_add_device failed\n"); + rc = -ENOMEM; + goto err_release_group1; + } + + altr_create_edacdev_dbgfs(dci, prv); + + list_add(&altdev->next, &edac->a10_ecc_devices); + + devres_remove_group(edac->dev, altr_edac_a10_device_add); + + return 0; + +err_release_group1: + edac_device_free_ctl_info(dci); +err_release_group: + edac_printk(KERN_ALERT, EDAC_DEVICE, "%s: %d\n", __func__, __LINE__); + devres_release_group(edac->dev, NULL); + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s:Error setting up EDAC device: %d\n", ecc_name, rc); + + return rc; +} + +static int altr_edac_a10_probe(struct platform_device *pdev) +{ + struct altr_arria10_edac *edac; + struct device_node *child; + int rc; + + edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL); + if (!edac) + return -ENOMEM; + + edac->dev = &pdev->dev; + platform_set_drvdata(pdev, edac); + INIT_LIST_HEAD(&edac->a10_ecc_devices); + + edac->ecc_mgr_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "altr,sysmgr-syscon"); + if (IS_ERR(edac->ecc_mgr_map)) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "Unable to get syscon altr,sysmgr-syscon\n"); + return PTR_ERR(edac->ecc_mgr_map); + } + + edac->sb_irq = platform_get_irq(pdev, 0); + rc = devm_request_irq(&pdev->dev, edac->sb_irq, + altr_edac_a10_irq_handler, + IRQF_SHARED, dev_name(&pdev->dev), edac); + if (rc) { + edac_printk(KERN_ERR, EDAC_DEVICE, "No SBERR IRQ resource\n"); + return rc; + } + + edac->db_irq = platform_get_irq(pdev, 1); + rc = devm_request_irq(&pdev->dev, edac->db_irq, + altr_edac_a10_irq_handler, + IRQF_SHARED, dev_name(&pdev->dev), edac); + if (rc) { + edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n"); + return rc; + } + + for_each_child_of_node(pdev->dev.of_node, child) { + if (!of_device_is_available(child)) + continue; + if (of_device_is_compatible(child, "altr,socfpga-a10-l2-ecc")) + altr_edac_a10_device_add(edac, child); + } + + return 0; +} + +static const struct of_device_id altr_edac_a10_of_match[] = { + { .compatible = "altr,socfpga-a10-ecc-manager" }, + {}, +}; +MODULE_DEVICE_TABLE(of, altr_edac_a10_of_match); + +static struct platform_driver altr_edac_a10_driver = { + .probe = altr_edac_a10_probe, + .driver = { + .name = "socfpga_a10_ecc_manager", + .of_match_table = altr_edac_a10_of_match, + }, +}; +module_platform_driver(altr_edac_a10_driver); + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Thor Thayer"); MODULE_DESCRIPTION("EDAC Driver for Altera Memories"); diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index d7ef94c13b98..b0a17d03c715 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -219,12 +219,39 @@ struct altr_sdram_mc_data { #define ALTR_L2_ECC_INJS BIT(1) #define ALTR_L2_ECC_INJD BIT(2) +/* Arria10 General ECC Block Module Defines */ +#define A10_SYSMGR_ECC_INTSTAT_SERR_OFST 0x9C +#define A10_SYSMGR_ECC_INTSTAT_DERR_OFST 0xA0 +#define A10_SYSMGR_ECC_INTSTAT_L2 BIT(0) + +#define A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST 0xA8 +#define A10_SYSGMR_MPU_CLEAR_L2_ECC_SB BIT(15) +#define A10_SYSGMR_MPU_CLEAR_L2_ECC_MB BIT(31) + +/* Arria 10 L2 ECC Management Group Defines */ +#define ALTR_A10_L2_ECC_CTL_OFST 0x0 +#define ALTR_A10_L2_ECC_EN_CTL BIT(0) + +#define ALTR_A10_L2_ECC_STATUS 0xFFD060A4 +#define ALTR_A10_L2_ECC_STAT_OFST 0xA4 +#define ALTR_A10_L2_ECC_SERR_PEND BIT(0) +#define ALTR_A10_L2_ECC_MERR_PEND BIT(0) + +#define ALTR_A10_L2_ECC_CLR_OFST 0x4 +#define ALTR_A10_L2_ECC_SERR_CLR BIT(15) +#define ALTR_A10_L2_ECC_MERR_CLR BIT(31) + +#define ALTR_A10_L2_ECC_INJ_OFST ALTR_A10_L2_ECC_CTL_OFST +#define ALTR_A10_L2_ECC_CE_INJ_MASK 0x00000101 +#define ALTR_A10_L2_ECC_UE_INJ_MASK 0x00010101 + struct altr_edac_device_dev; struct edac_device_prv_data { int (*setup)(struct altr_edac_device_dev *device); int ce_clear_mask; int ue_clear_mask; + int irq_status_mask; char dbgfs_name[20]; void * (*alloc_mem)(size_t size, void **other); void (*free_mem)(void *p, size_t size, void *other); @@ -232,16 +259,31 @@ struct edac_device_prv_data { int ce_set_mask; int ue_set_mask; int set_err_ofst; + irqreturn_t (*ecc_irq_handler)(struct altr_edac_device_dev *dci, + bool sb); int trig_alloc_sz; }; struct altr_edac_device_dev { + struct list_head next; void __iomem *base; int sb_irq; int db_irq; const struct edac_device_prv_data *data; struct dentry *debugfs_dir; char *edac_dev_name; + struct altr_arria10_edac *edac; + struct edac_device_ctl_info *edac_dev; + struct device ddev; + int edac_idx; +}; + +struct altr_arria10_edac { + struct device *dev; + struct regmap *ecc_mgr_map; + int sb_irq; + int db_irq; + struct list_head a10_ecc_devices; }; #endif /* #ifndef _ALTERA_EDAC_H */ -- GitLab From ff6fd1478c531a40279cf013227279f31ff90b41 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 11:01:45 -0500 Subject: [PATCH 0607/9938] ARM: socfpga: Enable Arria10 L2 cache ECC on startup Enable ECC for Arria10 L2 cache on machine startup. The ECC has to be enabled before data is stored in memory otherwise the ECC will fail on reads. Use DT_MACHINE to select Arria10 L2 cache function. Signed-off-by: Thor Thayer Acked-by: Dinh Nguyen Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1458576106-24505-9-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- arch/arm/mach-socfpga/core.h | 1 + arch/arm/mach-socfpga/l2_cache.c | 49 ++++++++++++++++++++++++++++++++ arch/arm/mach-socfpga/socfpga.c | 10 ++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h index 575195be6687..bfbc78df15dd 100644 --- a/arch/arm/mach-socfpga/core.h +++ b/arch/arm/mach-socfpga/core.h @@ -38,6 +38,7 @@ extern void socfpga_init_clocks(void); extern void socfpga_sysmgr_init(void); void socfpga_init_l2_ecc(void); void socfpga_init_ocram_ecc(void); +void socfpga_init_arria10_l2_ecc(void); extern void __iomem *sys_manager_base_addr; extern void __iomem *rst_manager_base_addr; diff --git a/arch/arm/mach-socfpga/l2_cache.c b/arch/arm/mach-socfpga/l2_cache.c index e3907ab58d05..4267c95f2158 100644 --- a/arch/arm/mach-socfpga/l2_cache.c +++ b/arch/arm/mach-socfpga/l2_cache.c @@ -17,6 +17,20 @@ #include #include +#include "core.h" + +/* A10 System Manager L2 ECC Control register */ +#define A10_MPU_CTRL_L2_ECC_OFST 0x0 +#define A10_MPU_CTRL_L2_ECC_EN BIT(0) + +/* A10 System Manager Global IRQ Mask register */ +#define A10_SYSMGR_ECC_INTMASK_CLR_OFST 0x98 +#define A10_SYSMGR_ECC_INTMASK_CLR_L2 BIT(0) + +/* A10 System Manager L2 ECC IRQ Clear register */ +#define A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST 0xA8 +#define A10_SYSMGR_MPU_CLEAR_L2_ECC (BIT(31) | BIT(15)) + void socfpga_init_l2_ecc(void) { struct device_node *np; @@ -39,3 +53,38 @@ void socfpga_init_l2_ecc(void) writel(0x01, mapped_l2_edac_addr); iounmap(mapped_l2_edac_addr); } + +void socfpga_init_arria10_l2_ecc(void) +{ + struct device_node *np; + void __iomem *mapped_l2_edac_addr; + + /* Find the L2 EDAC device tree node */ + np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-l2-ecc"); + if (!np) { + pr_err("Unable to find socfpga-a10-l2-ecc in dtb\n"); + return; + } + + mapped_l2_edac_addr = of_iomap(np, 0); + of_node_put(np); + if (!mapped_l2_edac_addr) { + pr_err("Unable to find L2 ECC mapping in dtb\n"); + return; + } + + if (!sys_manager_base_addr) { + pr_err("System Mananger not mapped for L2 ECC\n"); + goto exit; + } + /* Clear any pending IRQs */ + writel(A10_SYSMGR_MPU_CLEAR_L2_ECC, (sys_manager_base_addr + + A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST)); + /* Enable ECC */ + writel(A10_SYSMGR_ECC_INTMASK_CLR_L2, sys_manager_base_addr + + A10_SYSMGR_ECC_INTMASK_CLR_OFST); + writel(A10_MPU_CTRL_L2_ECC_EN, mapped_l2_edac_addr + + A10_MPU_CTRL_L2_ECC_OFST); +exit: + iounmap(mapped_l2_edac_addr); +} diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index 7e0aad2ec3d1..e9b5b603df4b 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -66,6 +66,14 @@ static void __init socfpga_init_irq(void) socfpga_init_ocram_ecc(); } +static void __init socfpga_arria10_init_irq(void) +{ + irqchip_init(); + socfpga_sysmgr_init(); + if (IS_ENABLED(CONFIG_EDAC_ALTERA_L2C)) + socfpga_init_arria10_l2_ecc(); +} + static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd) { u32 temp; @@ -113,7 +121,7 @@ static const char *altera_a10_dt_match[] = { DT_MACHINE_START(SOCFPGA_A10, "Altera SOCFPGA Arria10") .l2c_aux_val = 0, .l2c_aux_mask = ~0, - .init_irq = socfpga_init_irq, + .init_irq = socfpga_arria10_init_irq, .restart = socfpga_arria10_restart, .dt_compat = altera_a10_dt_match, MACHINE_END -- GitLab From 02f037d641dc6672be5cfe7875a48ab99b95b154 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 Mar 2016 15:41:57 -0600 Subject: [PATCH 0608/9938] x86/mm/pat: Add support of non-default PAT MSR setting In preparation for fixing a regression caused by: 9cd25aac1f44 ("x86/mm/pat: Emulate PAT when it is disabled")' ... PAT needs to support a case that PAT MSR is initialized with a non-default value. When pat_init() is called and PAT is disabled, it initializes the PAT table with the BIOS default value. Xen, however, sets PAT MSR with a non-default value to enable WC. This causes inconsistency between the PAT table and PAT MSR when PAT is set to disable on Xen. Change pat_init() to handle the PAT disable cases properly. Add init_cache_modes() to handle two cases when PAT is set to disable. 1. CPU supports PAT: Set PAT table to be consistent with PAT MSR. 2. CPU does not support PAT: Set PAT table to be consistent with PWT and PCD bits in a PTE. Note, __init_cache_modes(), renamed from pat_init_cache_modes(), will be changed to a static function in a later patch. Signed-off-by: Toshi Kani Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Juergen Gross Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Toshi Kani Cc: elliott@hpe.com Cc: konrad.wilk@oracle.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-2-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pat.h | 2 +- arch/x86/mm/pat.c | 73 +++++++++++++++++++++++++++----------- arch/x86/xen/enlighten.c | 2 +- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h index ca6c228d5e62..97ea55bc2b54 100644 --- a/arch/x86/include/asm/pat.h +++ b/arch/x86/include/asm/pat.h @@ -6,7 +6,7 @@ bool pat_enabled(void); extern void pat_init(void); -void pat_init_cache_modes(u64); +void __init_cache_modes(u64); extern int reserve_memtype(u64 start, u64 end, enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm); diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index faec01e7a17d..b4663885308f 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -181,7 +181,7 @@ static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg) * configuration. * Using lower indices is preferred, so we start with highest index. */ -void pat_init_cache_modes(u64 pat) +void __init_cache_modes(u64 pat) { enum page_cache_mode cache; char pat_msg[33]; @@ -207,9 +207,6 @@ static void pat_bsp_init(u64 pat) return; } - if (!pat_enabled()) - goto done; - rdmsrl(MSR_IA32_CR_PAT, tmp_pat); if (!tmp_pat) { pat_disable("PAT MSR is 0, disabled."); @@ -218,15 +215,11 @@ static void pat_bsp_init(u64 pat) wrmsrl(MSR_IA32_CR_PAT, pat); -done: - pat_init_cache_modes(pat); + __init_cache_modes(pat); } static void pat_ap_init(u64 pat) { - if (!pat_enabled()) - return; - if (!cpu_has_pat) { /* * If this happens we are on a secondary CPU, but switched to @@ -238,18 +231,32 @@ static void pat_ap_init(u64 pat) wrmsrl(MSR_IA32_CR_PAT, pat); } -void pat_init(void) +static void init_cache_modes(void) { - u64 pat; - struct cpuinfo_x86 *c = &boot_cpu_data; + u64 pat = 0; + static int init_cm_done; - if (!pat_enabled()) { + if (init_cm_done) + return; + + if (boot_cpu_has(X86_FEATURE_PAT)) { + /* + * CPU supports PAT. Set PAT table to be consistent with + * PAT MSR. This case supports "nopat" boot option, and + * virtual machine environments which support PAT without + * MTRRs. In specific, Xen has unique setup to PAT MSR. + * + * If PAT MSR returns 0, it is considered invalid and emulates + * as No PAT. + */ + rdmsrl(MSR_IA32_CR_PAT, pat); + } + + if (!pat) { /* * No PAT. Emulate the PAT table that corresponds to the two - * cache bits, PWT (Write Through) and PCD (Cache Disable). This - * setup is the same as the BIOS default setup when the system - * has PAT but the "nopat" boot option has been specified. This - * emulated PAT table is used when MSR_IA32_CR_PAT returns 0. + * cache bits, PWT (Write Through) and PCD (Cache Disable). + * This setup is also the same as the BIOS default setup. * * PTE encoding: * @@ -266,10 +273,36 @@ void pat_init(void) */ pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) | PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC); + } + + __init_cache_modes(pat); + + init_cm_done = 1; +} + +/** + * pat_init - Initialize PAT MSR and PAT table + * + * This function initializes PAT MSR and PAT table with an OS-defined value + * to enable additional cache attributes, WC and WT. + * + * This function must be called on all CPUs using the specific sequence of + * operations defined in Intel SDM. mtrr_rendezvous_handler() provides this + * procedure for PAT. + */ +void pat_init(void) +{ + u64 pat; + struct cpuinfo_x86 *c = &boot_cpu_data; + + if (!pat_enabled()) { + init_cache_modes(); + return; + } - } else if ((c->x86_vendor == X86_VENDOR_INTEL) && - (((c->x86 == 0x6) && (c->x86_model <= 0xd)) || - ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) { + if ((c->x86_vendor == X86_VENDOR_INTEL) && + (((c->x86 == 0x6) && (c->x86_model <= 0xd)) || + ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) { /* * PAT support with the lower four entries. Intel Pentium 2, * 3, M, and 4 are affected by PAT errata, which makes the diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 880862c7d9dd..c469a7c7c309 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1623,7 +1623,7 @@ asmlinkage __visible void __init xen_start_kernel(void) * configuration. */ rdmsrl(MSR_IA32_CR_PAT, pat); - pat_init_cache_modes(pat); + __init_cache_modes(pat); /* keep using Xen gdt for now; no urgent need to change it */ -- GitLab From 224bb1e5d67ba0f2872c98002d6a6f991ac6fd4a Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 Mar 2016 15:41:58 -0600 Subject: [PATCH 0609/9938] x86/mm/pat: Add pat_disable() interface In preparation for fixing a regression caused by: 9cd25aac1f44 ("x86/mm/pat: Emulate PAT when it is disabled") ... PAT needs to provide an interface that prevents the OS from initializing the PAT MSR. PAT MSR initialization must be done on all CPUs using the specific sequence of operations defined in the Intel SDM. This requires MTRRs to be enabled since pat_init() is called as part of MTRR init from mtrr_rendezvous_handler(). Make pat_disable() as the interface that prevents the OS from initializing the PAT MSR. MTRR will call this interface when it cannot provide the SDM-defined sequence to initialize PAT. This also assures that pat_disable() called from pat_bsp_init() will set the PAT table properly when CPU does not support PAT. Signed-off-by: Toshi Kani Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Juergen Gross Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Robert Elliott Cc: Toshi Kani Cc: konrad.wilk@oracle.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-3-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pat.h | 1 + arch/x86/mm/pat.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h index 97ea55bc2b54..0ad356c066ef 100644 --- a/arch/x86/include/asm/pat.h +++ b/arch/x86/include/asm/pat.h @@ -5,6 +5,7 @@ #include bool pat_enabled(void); +void pat_disable(const char *reason); extern void pat_init(void); void __init_cache_modes(u64); diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index b4663885308f..1cc1d37f1de7 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -40,11 +40,22 @@ static bool boot_cpu_done; static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT); +static void init_cache_modes(void); -static inline void pat_disable(const char *reason) +void pat_disable(const char *reason) { + if (!__pat_enabled) + return; + + if (boot_cpu_done) { + WARN_ONCE(1, "x86/PAT: PAT cannot be disabled after initialization\n"); + return; + } + __pat_enabled = 0; pr_info("x86/PAT: %s\n", reason); + + init_cache_modes(); } static int __init nopat(char *str) -- GitLab From d63dcf49cf5ae5605f4d14229e3888e104f294b1 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 Mar 2016 15:41:59 -0600 Subject: [PATCH 0610/9938] x86/mm/pat: Replace cpu_has_pat with boot_cpu_has() Borislav Petkov suggested: > Please use on init paths boot_cpu_has(X86_FEATURE_PAT) and on fast > paths static_cpu_has(X86_FEATURE_PAT). No more of that cpu_has_XXX > ugliness. Replace the use of cpu_has_pat on init paths with boot_cpu_has(). Suggested-by: Borislav Petkov Signed-off-by: Toshi Kani Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Juergen Gross Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Robert Elliott Cc: Toshi Kani Cc: konrad.wilk@oracle.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-4-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 1cc1d37f1de7..59ec038b9833 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -213,7 +213,7 @@ static void pat_bsp_init(u64 pat) { u64 tmp_pat; - if (!cpu_has_pat) { + if (!boot_cpu_has(X86_FEATURE_PAT)) { pat_disable("PAT not supported by CPU."); return; } @@ -231,7 +231,7 @@ static void pat_bsp_init(u64 pat) static void pat_ap_init(u64 pat) { - if (!cpu_has_pat) { + if (!boot_cpu_has(X86_FEATURE_PAT)) { /* * If this happens we are on a secondary CPU, but switched to * PAT on the boot CPU. We have no way to undo PAT. -- GitLab From edfe63ec97ed8d4496225f7ba54c9ce4207c5431 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 Mar 2016 15:42:00 -0600 Subject: [PATCH 0611/9938] x86/mtrr: Fix Xorg crashes in Qemu sessions A Xorg failure on qemu32 was reported as a regression [1] caused by commit 9cd25aac1f44 ("x86/mm/pat: Emulate PAT when it is disabled"). This patch fixes the Xorg crash. Negative effects of this regression were the following two failures [2] in Xorg on QEMU with QEMU CPU model "qemu32" (-cpu qemu32), which were triggered by the fact that its virtual CPU does not support MTRRs. #1. copy_process() failed in the check in reserve_pfn_range() copy_process copy_mm dup_mm dup_mmap copy_page_range track_pfn_copy reserve_pfn_range A WC map request was tracked as WC in memtype, which set a PTE as UC (pgprot) per __cachemode2pte_tbl[]. This led to this error in reserve_pfn_range() called from track_pfn_copy(), which obtained a pgprot from a PTE. It converts pgprot to page_cache_mode, which does not necessarily result in the original page_cache_mode since __cachemode2pte_tbl[] redirects multiple types to UC. #2. error path in copy_process() then hit WARN_ON_ONCE in untrack_pfn(). x86/PAT: Xorg:509 map pfn expected mapping type uncached- minus for [mem 0xfd000000-0xfdffffff], got write-combining Call Trace: dump_stack warn_slowpath_common ? untrack_pfn ? untrack_pfn warn_slowpath_null untrack_pfn ? __kunmap_atomic unmap_single_vma ? pagevec_move_tail_fn unmap_vmas exit_mmap mmput copy_process.part.47 _do_fork SyS_clone do_syscall_32_irqs_on entry_INT80_32 These negative effects are caused by two separate bugs, but they can be addressed in separate patches. Fixing the pat_init() issue described below addresses the root cause, and avoids Xorg to hit these cases. When the CPU does not support MTRRs, MTRR does not call pat_init(), which leaves PAT enabled without initializing PAT. This pat_init() issue is a long-standing issue, but manifested as issue #1 (and then hit issue #2) with the above-mentioned commit because the memtype now tracks cache attribute with 'page_cache_mode'. This pat_init() issue existed before the commit, but we used pgprot in memtype. Hence, we did not have issue #1 before. But WC request resulted in WT in effect because WC pgrot is actually WT when PAT is not initialized. This is not how it was designed to work. When PAT is set to disable properly, WC is converted to UC. The use of WT can result in a system crash if the target range does not support WT. Fortunately, nobody ran into such issue before. To fix this pat_init() issue, PAT code has been enhanced to provide pat_disable() interface. Call this interface when MTRRs are disabled. By setting PAT to disable properly, PAT bypasses the memtype check, and avoids issue #1. [1]: https://lkml.org/lkml/2016/3/3/828 [2]: https://lkml.org/lkml/2016/3/4/775 Signed-off-by: Toshi Kani Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Juergen Gross Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Toshi Kani Cc: elliott@hpe.com Cc: konrad.wilk@oracle.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-5-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mtrr.h | 6 +++++- arch/x86/kernel/cpu/mtrr/main.c | 10 +++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index b94f6f64e23d..dbff1456d215 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -24,6 +24,7 @@ #define _ASM_X86_MTRR_H #include +#include /* @@ -83,9 +84,12 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn) static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) { } +static inline void mtrr_bp_init(void) +{ + pat_disable("MTRRs disabled, skipping PAT initialization too."); +} #define mtrr_ap_init() do {} while (0) -#define mtrr_bp_init() do {} while (0) #define set_mtrr_aps_delayed_init() do {} while (0) #define mtrr_aps_init() do {} while (0) #define mtrr_bp_restore() do {} while (0) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 10f8d4796240..8b1947ba3e62 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -759,8 +759,16 @@ void __init mtrr_bp_init(void) } } - if (!mtrr_enabled()) + if (!mtrr_enabled()) { pr_info("MTRR: Disabled\n"); + + /* + * PAT initialization relies on MTRR's rendezvous handler. + * Skip PAT init until the handler can initialize both + * features independently. + */ + pat_disable("MTRRs disabled, skipping PAT initialization too."); + } } void mtrr_ap_init(void) -- GitLab From ad025a73f0e9344ac73ffe1b74c184033e08e7d5 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 Mar 2016 15:42:01 -0600 Subject: [PATCH 0612/9938] x86/mtrr: Fix PAT init handling when MTRR is disabled get_mtrr_state() calls pat_init() on BSP even if MTRR is disabled. This results in calling pat_init() on BSP only since APs do not call pat_init() when MTRR is disabled. This inconsistency between BSP and APs leads to undefined behavior. Make BSP's calling condition to pat_init() consistent with AP's, mtrr_ap_init() and mtrr_aps_init(). Signed-off-by: Toshi Kani Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Juergen Gross Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Toshi Kani Cc: elliott@hpe.com Cc: konrad.wilk@oracle.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-6-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/generic.c | 24 ++++++++++++++---------- arch/x86/kernel/cpu/mtrr/main.c | 3 +++ arch/x86/kernel/cpu/mtrr/mtrr.h | 1 + 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 19f57360dfd2..8d7a29ed9377 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -444,11 +444,24 @@ static void __init print_mtrr_state(void) pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20); } +/* PAT setup for BP. We need to go through sync steps here */ +void __init mtrr_bp_pat_init(void) +{ + unsigned long flags; + + local_irq_save(flags); + prepare_set(); + + pat_init(); + + post_set(); + local_irq_restore(flags); +} + /* Grab all of the MTRR state for this CPU into *state */ bool __init get_mtrr_state(void) { struct mtrr_var_range *vrs; - unsigned long flags; unsigned lo, dummy; unsigned int i; @@ -481,15 +494,6 @@ bool __init get_mtrr_state(void) mtrr_state_set = 1; - /* PAT setup for BP. We need to go through sync steps here */ - local_irq_save(flags); - prepare_set(); - - pat_init(); - - post_set(); - local_irq_restore(flags); - return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED); } diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 8b1947ba3e62..7d393ecdeee6 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -752,6 +752,9 @@ void __init mtrr_bp_init(void) /* BIOS may override */ __mtrr_enabled = get_mtrr_state(); + if (mtrr_enabled()) + mtrr_bp_pat_init(); + if (mtrr_cleanup(phys_addr)) { changed_by_mtrr_cleanup = 1; mtrr_if->set_all(); diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h index 951884dcc433..6c7ced07d16d 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h @@ -52,6 +52,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt); void fill_mtrr_var_range(unsigned int index, u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); bool get_mtrr_state(void); +void mtrr_bp_pat_init(void); extern void set_mtrr_ops(const struct mtrr_ops *ops); -- GitLab From 88ba281108ed0c25c9d292b48bd3f272fcb90dd0 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 Mar 2016 15:42:02 -0600 Subject: [PATCH 0613/9938] x86/xen, pat: Remove PAT table init code from Xen Xen supports PAT without MTRRs for its guests. In order to enable WC attribute, it was necessary for xen_start_kernel() to call pat_init_cache_modes() to update PAT table before starting guest kernel. Now that the kernel initializes PAT table to the BIOS handoff state when MTRR is disabled, this Xen-specific PAT init code is no longer necessary. Delete it from xen_start_kernel(). Also change __init_cache_modes() to a static function since PAT table should not be tweaked by other modules. Signed-off-by: Toshi Kani Reviewed-by: Thomas Gleixner Acked-by: Juergen Gross Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Konrad Rzeszutek Wilk Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Toshi Kani Cc: elliott@hpe.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-7-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pat.h | 1 - arch/x86/mm/pat.c | 2 +- arch/x86/xen/enlighten.c | 9 --------- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h index 0ad356c066ef..0b1ff4c1c14e 100644 --- a/arch/x86/include/asm/pat.h +++ b/arch/x86/include/asm/pat.h @@ -7,7 +7,6 @@ bool pat_enabled(void); void pat_disable(const char *reason); extern void pat_init(void); -void __init_cache_modes(u64); extern int reserve_memtype(u64 start, u64 end, enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm); diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 59ec038b9833..c4c3ddcc9069 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -192,7 +192,7 @@ static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg) * configuration. * Using lower indices is preferred, so we start with highest index. */ -void __init_cache_modes(u64 pat) +static void __init_cache_modes(u64 pat) { enum page_cache_mode cache; char pat_msg[33]; diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c469a7c7c309..d8cca75e3b3e 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -75,7 +75,6 @@ #include #include #include -#include #include #ifdef CONFIG_ACPI @@ -1511,7 +1510,6 @@ asmlinkage __visible void __init xen_start_kernel(void) { struct physdev_set_iopl set_iopl; unsigned long initrd_start = 0; - u64 pat; int rc; if (!xen_start_info) @@ -1618,13 +1616,6 @@ asmlinkage __visible void __init xen_start_kernel(void) xen_start_info->nr_pages); xen_reserve_special_pages(); - /* - * Modify the cache mode translation tables to match Xen's PAT - * configuration. - */ - rdmsrl(MSR_IA32_CR_PAT, pat); - __init_cache_modes(pat); - /* keep using Xen gdt for now; no urgent need to change it */ #ifdef CONFIG_X86_32 -- GitLab From b6350c21cfe8aa9d65e189509a23c0ea4b8362c2 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 23 Mar 2016 15:42:03 -0600 Subject: [PATCH 0614/9938] x86/pat: Document the PAT initialization sequence Update PAT documentation to describe how PAT is initialized under various configurations. Signed-off-by: Toshi Kani Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Juergen Gross Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Toshi Kani Cc: elliott@hpe.com Cc: konrad.wilk@oracle.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-8-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar --- Documentation/x86/pat.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt index 54944c71b819..2a4ee6302122 100644 --- a/Documentation/x86/pat.txt +++ b/Documentation/x86/pat.txt @@ -196,3 +196,35 @@ Another, more verbose way of getting PAT related debug messages is with "debugpat" boot parameter. With this parameter, various debug messages are printed to dmesg log. +PAT Initialization +------------------ + +The following table describes how PAT is initialized under various +configurations. The PAT MSR must be updated by Linux in order to support WC +and WT attributes. Otherwise, the PAT MSR has the value programmed in it +by the firmware. Note, Xen enables WC attribute in the PAT MSR for guests. + + MTRR PAT Call Sequence PAT State PAT MSR + ========================================================= + E E MTRR -> PAT init Enabled OS + E D MTRR -> PAT init Disabled - + D E MTRR -> PAT disable Disabled BIOS + D D MTRR -> PAT disable Disabled - + - np/E PAT -> PAT disable Disabled BIOS + - np/D PAT -> PAT disable Disabled - + E !P/E MTRR -> PAT init Disabled BIOS + D !P/E MTRR -> PAT disable Disabled BIOS + !M !P/E MTRR stub -> PAT disable Disabled BIOS + + Legend + ------------------------------------------------ + E Feature enabled in CPU + D Feature disabled/unsupported in CPU + np "nopat" boot option specified + !P CONFIG_X86_PAT option unset + !M CONFIG_MTRR option unset + Enabled PAT state set to enabled + Disabled PAT state set to disabled + OS PAT initializes PAT MSR with OS setting + BIOS PAT keeps PAT MSR with BIOS setting + -- GitLab From faafd03d23c913633d2ef7e6ffebdce01b164409 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 29 Mar 2016 12:29:24 +0200 Subject: [PATCH 0615/9938] ALSA: hda - Clear the leftover component assignment at snd_hdac_i915_exit() The commit [d745f5e7b8b2: ALSA: hda - Add the pin / port mapping on Intel ILK and VLV] introduced a WARN_ON() to check the pointer for avoiding the double initializations. But hdac_acomp pointer wasn't cleared at snd_hdac_i915_exit(), thus after reloading the HD-audio driver, it may result in the false positive warning. This patch makes sure to clear the leftover pointer at exit. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94736 Reported-by: Daniela Doras-prodan Signed-off-by: Takashi Iwai --- sound/hda/hdac_i915.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 750a4ea49fa9..ae0f305a7e41 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -372,6 +372,7 @@ int snd_hdac_i915_exit(struct hdac_bus *bus) kfree(acomp); bus->audio_component = NULL; + hdac_acomp = NULL; return 0; } -- GitLab From b3edfda4382ffaef5e5c1cffb25a33b3b9ef4546 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 16 Mar 2016 13:19:29 +0100 Subject: [PATCH 0616/9938] x86/cpu: Do the feature test first in enable_sep_cpu() ... before assigning local vars. Kill out label too and simplify. No functionality change. Signed-off-by: Borislav Petkov Acked-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1458130769-24963-1-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 8394b3d1f94f..7fea4079d102 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1076,12 +1076,12 @@ void enable_sep_cpu(void) struct tss_struct *tss; int cpu; + if (!boot_cpu_has(X86_FEATURE_SEP)) + return; + cpu = get_cpu(); tss = &per_cpu(cpu_tss, cpu); - if (!boot_cpu_has(X86_FEATURE_SEP)) - goto out; - /* * We cache MSR_IA32_SYSENTER_CS's value in the TSS's ss1 field -- * see the big comment in struct x86_hw_tss's definition. @@ -1096,7 +1096,6 @@ void enable_sep_cpu(void) wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long)entry_SYSENTER_32, 0); -out: put_cpu(); } #endif -- GitLab From ac28634456867b23b95faccba7997a62ec430603 Mon Sep 17 00:00:00 2001 From: Stephane Bryant Date: Sat, 26 Mar 2016 08:42:10 +0100 Subject: [PATCH 0617/9938] netfilter: bridge: add nf_afinfo to enable queuing to userspace This just adds and registers a nf_afinfo for the ethernet bridge, which enables queuing to userspace for the AF_BRIDGE family. No checksum computation is done. Signed-off-by: Stephane Bryant Signed-off-by: Pablo Neira Ayuso --- net/bridge/netfilter/nf_tables_bridge.c | 47 +++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index 7fcdd7261d88..a78c4e2826e5 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c @@ -162,15 +162,57 @@ static const struct nf_chain_type filter_bridge = { (1 << NF_BR_POST_ROUTING), }; +static void nf_br_saveroute(const struct sk_buff *skb, + struct nf_queue_entry *entry) +{ +} + +static int nf_br_reroute(struct net *net, struct sk_buff *skb, + const struct nf_queue_entry *entry) +{ + return 0; +} + +static __sum16 nf_br_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +{ + return 0; +} + +static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, unsigned int len, + u_int8_t protocol) +{ + return 0; +} + +static int nf_br_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict __always_unused) +{ + return 0; +} + +static const struct nf_afinfo nf_br_afinfo = { + .family = AF_BRIDGE, + .checksum = nf_br_checksum, + .checksum_partial = nf_br_checksum_partial, + .route = nf_br_route, + .saveroute = nf_br_saveroute, + .reroute = nf_br_reroute, + .route_key_size = 0, +}; + static int __init nf_tables_bridge_init(void) { int ret; + nf_register_afinfo(&nf_br_afinfo); nft_register_chain_type(&filter_bridge); ret = register_pernet_subsys(&nf_tables_bridge_net_ops); - if (ret < 0) + if (ret < 0) { nft_unregister_chain_type(&filter_bridge); - + nf_unregister_afinfo(&nf_br_afinfo); + } return ret; } @@ -178,6 +220,7 @@ static void __exit nf_tables_bridge_exit(void) { unregister_pernet_subsys(&nf_tables_bridge_net_ops); nft_unregister_chain_type(&filter_bridge); + nf_unregister_afinfo(&nf_br_afinfo); } module_init(nf_tables_bridge_init); -- GitLab From 15824ab29f364abd3299ecd17ea48473d971aa79 Mon Sep 17 00:00:00 2001 From: Stephane Bryant Date: Sat, 26 Mar 2016 08:42:11 +0100 Subject: [PATCH 0618/9938] netfilter: bridge: pass L2 header and VLAN as netlink attributes in queues to userspace - This creates 2 netlink attribute NFQA_VLAN and NFQA_L2HDR. - These are filled up for the PF_BRIDGE family on the way to userspace. - NFQA_VLAN is a nested attribute, with the NFQA_VLAN_PROTO and the NFQA_VLAN_TCI carrying the corresponding vlan_proto and vlan_tci fields from the skb using big endian ordering (and using the CFI bit as the VLAN_TAG_PRESENT flag in vlan_tci as in the skb) Signed-off-by: Stephane Bryant Signed-off-by: Pablo Neira Ayuso --- .../uapi/linux/netfilter/nfnetlink_queue.h | 10 ++++ net/netfilter/nfnetlink_queue.c | 58 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h index b67a853638ff..ae30841ff94e 100644 --- a/include/uapi/linux/netfilter/nfnetlink_queue.h +++ b/include/uapi/linux/netfilter/nfnetlink_queue.h @@ -30,6 +30,14 @@ struct nfqnl_msg_packet_timestamp { __aligned_be64 usec; }; +enum nfqnl_vlan_attr { + NFQA_VLAN_UNSPEC, + NFQA_VLAN_PROTO, /* __be16 skb vlan_proto */ + NFQA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */ + __NFQA_VLAN_MAX, +}; +#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX + 1) + enum nfqnl_attr_type { NFQA_UNSPEC, NFQA_PACKET_HDR, @@ -50,6 +58,8 @@ enum nfqnl_attr_type { NFQA_UID, /* __u32 sk uid */ NFQA_GID, /* __u32 sk gid */ NFQA_SECCTX, /* security context string */ + NFQA_VLAN, /* nested attribute: packet vlan info */ + NFQA_L2HDR, /* full L2 header */ __NFQA_MAX }; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 75429997ed41..6889c7c855d1 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -295,6 +295,59 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata) return seclen; } +static u32 nfqnl_get_bridge_size(struct nf_queue_entry *entry) +{ + struct sk_buff *entskb = entry->skb; + u32 nlalen = 0; + + if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb)) + return 0; + + if (skb_vlan_tag_present(entskb)) + nlalen += nla_total_size(nla_total_size(sizeof(__be16)) + + nla_total_size(sizeof(__be16))); + + if (entskb->network_header > entskb->mac_header) + nlalen += nla_total_size((entskb->network_header - + entskb->mac_header)); + + return nlalen; +} + +static int nfqnl_put_bridge(struct nf_queue_entry *entry, struct sk_buff *skb) +{ + struct sk_buff *entskb = entry->skb; + + if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb)) + return 0; + + if (skb_vlan_tag_present(entskb)) { + struct nlattr *nest; + + nest = nla_nest_start(skb, NFQA_VLAN | NLA_F_NESTED); + if (!nest) + goto nla_put_failure; + + if (nla_put_be16(skb, NFQA_VLAN_TCI, htons(entskb->vlan_tci)) || + nla_put_be16(skb, NFQA_VLAN_PROTO, entskb->vlan_proto)) + goto nla_put_failure; + + nla_nest_end(skb, nest); + } + + if (entskb->mac_header < entskb->network_header) { + int len = (int)(entskb->network_header - entskb->mac_header); + + if (nla_put(skb, NFQA_L2HDR, len, skb_mac_header(entskb))) + goto nla_put_failure; + } + + return 0; + +nla_put_failure: + return -1; +} + static struct sk_buff * nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, struct nf_queue_entry *entry, @@ -334,6 +387,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, if (entskb->tstamp.tv64) size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); + size += nfqnl_get_bridge_size(entry); + if (entry->state.hook <= NF_INET_FORWARD || (entry->state.hook == NF_INET_POST_ROUTING && entskb->sk == NULL)) csum_verify = !skb_csum_unnecessary(entskb); @@ -497,6 +552,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, } } + if (nfqnl_put_bridge(entry, skb) < 0) + goto nla_put_failure; + if (entskb->tstamp.tv64) { struct nfqnl_msg_packet_timestamp ts; struct timespec64 kts = ktime_to_timespec64(skb->tstamp); -- GitLab From 8d45ff22f1b43249f0cf1baafe0262ca10d1666e Mon Sep 17 00:00:00 2001 From: Stephane Bryant Date: Sat, 26 Mar 2016 08:42:12 +0100 Subject: [PATCH 0619/9938] netfilter: bridge: nf queue verdict to use NFQA_VLAN and NFQA_L2HDR This makes nf queues use NFQA_VLAN and NFQA_L2HDR in verdict to modify the original skb Signed-off-by: Stephane Bryant Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_queue.c | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 6889c7c855d1..5bebe78b9bbd 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -964,12 +964,18 @@ static struct notifier_block nfqnl_rtnl_notifier = { .notifier_call = nfqnl_rcv_nl_event, }; +static const struct nla_policy nfqa_vlan_policy[NFQA_VLAN_MAX + 1] = { + [NFQA_VLAN_TCI] = { .type = NLA_U16}, + [NFQA_VLAN_PROTO] = { .type = NLA_U16}, +}; + static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = { [NFQA_VERDICT_HDR] = { .len = sizeof(struct nfqnl_msg_verdict_hdr) }, [NFQA_MARK] = { .type = NLA_U32 }, [NFQA_PAYLOAD] = { .type = NLA_UNSPEC }, [NFQA_CT] = { .type = NLA_UNSPEC }, [NFQA_EXP] = { .type = NLA_UNSPEC }, + [NFQA_VLAN] = { .type = NLA_NESTED }, }; static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { @@ -1083,6 +1089,40 @@ static struct nf_conn *nfqnl_ct_parse(struct nfnl_ct_hook *nfnl_ct, return ct; } +static int nfqa_parse_bridge(struct nf_queue_entry *entry, + const struct nlattr * const nfqa[]) +{ + if (nfqa[NFQA_VLAN]) { + struct nlattr *tb[NFQA_VLAN_MAX + 1]; + int err; + + err = nla_parse_nested(tb, NFQA_VLAN_MAX, nfqa[NFQA_VLAN], + nfqa_vlan_policy); + if (err < 0) + return err; + + if (!tb[NFQA_VLAN_TCI] || !tb[NFQA_VLAN_PROTO]) + return -EINVAL; + + entry->skb->vlan_tci = ntohs(nla_get_be16(tb[NFQA_VLAN_TCI])); + entry->skb->vlan_proto = nla_get_be16(tb[NFQA_VLAN_PROTO]); + } + + if (nfqa[NFQA_L2HDR]) { + int mac_header_len = entry->skb->network_header - + entry->skb->mac_header; + + if (mac_header_len != nla_len(nfqa[NFQA_L2HDR])) + return -EINVAL; + else if (mac_header_len > 0) + memcpy(skb_mac_header(entry->skb), + nla_data(nfqa[NFQA_L2HDR]), + mac_header_len); + } + + return 0; +} + static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, @@ -1098,6 +1138,7 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl, struct nfnl_ct_hook *nfnl_ct; struct nf_conn *ct = NULL; struct nfnl_queue_net *q = nfnl_queue_pernet(net); + int err; queue = instance_lookup(q, queue_num); if (!queue) @@ -1124,6 +1165,12 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl, ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo); } + if (entry->state.pf == PF_BRIDGE) { + err = nfqa_parse_bridge(entry, nfqa); + if (err < 0) + return err; + } + if (nfqa[NFQA_PAYLOAD]) { u16 payload_len = nla_len(nfqa[NFQA_PAYLOAD]); int diff = payload_len - entry->skb->len; -- GitLab From 8fef24ca90fb79de8454e26e9f3eae6cc610de1a Mon Sep 17 00:00:00 2001 From: Liping Zhang Date: Mon, 28 Mar 2016 22:27:27 +0800 Subject: [PATCH 0620/9938] netfilter: ip6t_SYNPROXY: remove magic number for hop_limit Replace '64' with the per-net ipv6_devconf_all's hop_limit when building the ipv6 header. Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/ip6t_SYNPROXY.c | 56 ++++++++++++++++-------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index 3deed5860a42..5d778dd11f66 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c @@ -20,15 +20,16 @@ #include static struct ipv6hdr * -synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr, - const struct in6_addr *daddr) +synproxy_build_ip(struct net *net, struct sk_buff *skb, + const struct in6_addr *saddr, + const struct in6_addr *daddr) { struct ipv6hdr *iph; skb_reset_network_header(skb); iph = (struct ipv6hdr *)skb_put(skb, sizeof(*iph)); ip6_flow_hdr(iph, 0, 0); - iph->hop_limit = 64; //XXX + iph->hop_limit = net->ipv6.devconf_all->hop_limit; iph->nexthdr = IPPROTO_TCP; iph->saddr = *saddr; iph->daddr = *daddr; @@ -37,13 +38,12 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr, } static void -synproxy_send_tcp(const struct synproxy_net *snet, +synproxy_send_tcp(struct net *net, const struct sk_buff *skb, struct sk_buff *nskb, struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo, struct ipv6hdr *niph, struct tcphdr *nth, unsigned int tcp_hdr_size) { - struct net *net = nf_ct_net(snet->tmpl); struct dst_entry *dst; struct flowi6 fl6; @@ -84,7 +84,7 @@ synproxy_send_tcp(const struct synproxy_net *snet, } static void -synproxy_send_client_synack(const struct synproxy_net *snet, +synproxy_send_client_synack(struct net *net, const struct sk_buff *skb, const struct tcphdr *th, const struct synproxy_options *opts) { @@ -103,7 +103,7 @@ synproxy_send_client_synack(const struct synproxy_net *snet, return; skb_reserve(nskb, MAX_TCP_HEADER); - niph = synproxy_build_ip(nskb, &iph->daddr, &iph->saddr); + niph = synproxy_build_ip(net, nskb, &iph->daddr, &iph->saddr); skb_reset_transport_header(nskb); nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size); @@ -121,15 +121,16 @@ synproxy_send_client_synack(const struct synproxy_net *snet, synproxy_build_options(nth, opts); - synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, + synproxy_send_tcp(net, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, niph, nth, tcp_hdr_size); } static void -synproxy_send_server_syn(const struct synproxy_net *snet, +synproxy_send_server_syn(struct net *net, const struct sk_buff *skb, const struct tcphdr *th, const struct synproxy_options *opts, u32 recv_seq) { + struct synproxy_net *snet = synproxy_pernet(net); struct sk_buff *nskb; struct ipv6hdr *iph, *niph; struct tcphdr *nth; @@ -144,7 +145,7 @@ synproxy_send_server_syn(const struct synproxy_net *snet, return; skb_reserve(nskb, MAX_TCP_HEADER); - niph = synproxy_build_ip(nskb, &iph->saddr, &iph->daddr); + niph = synproxy_build_ip(net, nskb, &iph->saddr, &iph->daddr); skb_reset_transport_header(nskb); nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size); @@ -165,12 +166,12 @@ synproxy_send_server_syn(const struct synproxy_net *snet, synproxy_build_options(nth, opts); - synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW, + synproxy_send_tcp(net, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW, niph, nth, tcp_hdr_size); } static void -synproxy_send_server_ack(const struct synproxy_net *snet, +synproxy_send_server_ack(struct net *net, const struct ip_ct_tcp *state, const struct sk_buff *skb, const struct tcphdr *th, const struct synproxy_options *opts) @@ -189,7 +190,7 @@ synproxy_send_server_ack(const struct synproxy_net *snet, return; skb_reserve(nskb, MAX_TCP_HEADER); - niph = synproxy_build_ip(nskb, &iph->daddr, &iph->saddr); + niph = synproxy_build_ip(net, nskb, &iph->daddr, &iph->saddr); skb_reset_transport_header(nskb); nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size); @@ -205,11 +206,11 @@ synproxy_send_server_ack(const struct synproxy_net *snet, synproxy_build_options(nth, opts); - synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); + synproxy_send_tcp(net, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); } static void -synproxy_send_client_ack(const struct synproxy_net *snet, +synproxy_send_client_ack(struct net *net, const struct sk_buff *skb, const struct tcphdr *th, const struct synproxy_options *opts) { @@ -227,7 +228,7 @@ synproxy_send_client_ack(const struct synproxy_net *snet, return; skb_reserve(nskb, MAX_TCP_HEADER); - niph = synproxy_build_ip(nskb, &iph->saddr, &iph->daddr); + niph = synproxy_build_ip(net, nskb, &iph->saddr, &iph->daddr); skb_reset_transport_header(nskb); nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size); @@ -243,15 +244,16 @@ synproxy_send_client_ack(const struct synproxy_net *snet, synproxy_build_options(nth, opts); - synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, + synproxy_send_tcp(net, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY, niph, nth, tcp_hdr_size); } static bool -synproxy_recv_client_ack(const struct synproxy_net *snet, +synproxy_recv_client_ack(struct net *net, const struct sk_buff *skb, const struct tcphdr *th, struct synproxy_options *opts, u32 recv_seq) { + struct synproxy_net *snet = synproxy_pernet(net); int mss; mss = __cookie_v6_check(ipv6_hdr(skb), th, ntohl(th->ack_seq) - 1); @@ -267,7 +269,7 @@ synproxy_recv_client_ack(const struct synproxy_net *snet, if (opts->options & XT_SYNPROXY_OPT_TIMESTAMP) synproxy_check_timestamp_cookie(opts); - synproxy_send_server_syn(snet, skb, th, opts, recv_seq); + synproxy_send_server_syn(net, skb, th, opts, recv_seq); return true; } @@ -275,7 +277,8 @@ static unsigned int synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_synproxy_info *info = par->targinfo; - struct synproxy_net *snet = synproxy_pernet(par->net); + struct net *net = par->net; + struct synproxy_net *snet = synproxy_pernet(net); struct synproxy_options opts = {}; struct tcphdr *th, _th; @@ -304,12 +307,12 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par) XT_SYNPROXY_OPT_SACK_PERM | XT_SYNPROXY_OPT_ECN); - synproxy_send_client_synack(snet, skb, th, &opts); + synproxy_send_client_synack(net, skb, th, &opts); return NF_DROP; } else if (th->ack && !(th->fin || th->rst || th->syn)) { /* ACK from client */ - synproxy_recv_client_ack(snet, skb, th, &opts, ntohl(th->seq)); + synproxy_recv_client_ack(net, skb, th, &opts, ntohl(th->seq)); return NF_DROP; } @@ -320,7 +323,8 @@ static unsigned int ipv6_synproxy_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *nhs) { - struct synproxy_net *snet = synproxy_pernet(nhs->net); + struct net *net = nhs->net; + struct synproxy_net *snet = synproxy_pernet(net); enum ip_conntrack_info ctinfo; struct nf_conn *ct; struct nf_conn_synproxy *synproxy; @@ -384,7 +388,7 @@ static unsigned int ipv6_synproxy_hook(void *priv, * therefore we need to add 1 to make the SYN sequence * number match the one of first SYN. */ - if (synproxy_recv_client_ack(snet, skb, th, &opts, + if (synproxy_recv_client_ack(net, skb, th, &opts, ntohl(th->seq) + 1)) this_cpu_inc(snet->stats->cookie_retrans); @@ -410,12 +414,12 @@ static unsigned int ipv6_synproxy_hook(void *priv, XT_SYNPROXY_OPT_SACK_PERM); swap(opts.tsval, opts.tsecr); - synproxy_send_server_ack(snet, state, skb, th, &opts); + synproxy_send_server_ack(net, state, skb, th, &opts); nf_ct_seqadj_init(ct, ctinfo, synproxy->isn - ntohl(th->seq)); swap(opts.tsval, opts.tsecr); - synproxy_send_client_ack(snet, skb, th, &opts); + synproxy_send_client_ack(net, skb, th, &opts); consume_skb(skb); return NF_STOLEN; -- GitLab From c8f26c2696f42b97bf68b643e59a948cb35fc397 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Thu, 17 Mar 2016 17:04:00 +0100 Subject: [PATCH 0621/9938] ARM: dts: at91: sama5d2: add SFR node This SFR node is looked up by the I2S controller driver to tune the SFR_I2SCLKSEL register. Signed-off-by: Cyrille Pitchen Signed-off-by: Ludovic Desroches Acked-by: Alexandre Belloni Acked-by: Rob Herring Signed-off-by: Nicolas Ferre --- .../devicetree/bindings/arm/atmel-at91.txt | 2 +- arch/arm/boot/dts/sama5d2.dtsi | 5 +++++ include/soc/at91/atmel-sfr.h | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 include/soc/at91/atmel-sfr.h diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 7fd64ec9ee1d..550fd6637993 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -155,7 +155,7 @@ elsewhere. required properties: - compatible: Should be "atmel,-sfr", "syscon". - can be "sama5d3" or "sama5d4". + can be "sama5d3", "sama5d4" or "sama5d2". - reg: Should contain registers location and length sfr@f0038000 { diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 78996bdbd3df..36bb29cbd603 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -973,6 +973,11 @@ status = "disabled"; }; + sfr: sfr@f8030000 { + compatible = "atmel,sama5d2-sfr", "syscon"; + reg = <0xf8030000 0x98>; + }; + flx0: flexcom@f8034000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xf8034000 0x200>; diff --git a/include/soc/at91/atmel-sfr.h b/include/soc/at91/atmel-sfr.h new file mode 100644 index 000000000000..2f9bb984a4df --- /dev/null +++ b/include/soc/at91/atmel-sfr.h @@ -0,0 +1,18 @@ +/* + * Atmel SFR (Special Function Registers) register offsets and bit definitions. + * + * Copyright (C) 2016 Atmel + * + * Author: Ludovic Desroches + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _LINUX_MFD_SYSCON_ATMEL_SFR_H +#define _LINUX_MFD_SYSCON_ATMEL_SFR_H + +#define AT91_SFR_I2SCLKSEL 0x90 /* I2SC Register */ + +#endif /* _LINUX_MFD_SYSCON_ATMEL_SFR_H */ -- GitLab From d77c23874f3972d5580ca0b507d8c1d8ae9a1c5c Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Fri, 18 Mar 2016 08:21:21 +0100 Subject: [PATCH 0622/9938] ARM: dts: at91: sama5d2: add chipid node Add node for chipid device in order to have access to the CIDR and EXID values. Signed-off-by: Ludovic Desroches Acked-by: Alexandre Belloni Acked-by: Arnd Bergmann Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/sama5d2.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 36bb29cbd603..0e4471d1fc46 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -1198,6 +1198,11 @@ clock-names = "tdes_clk"; status = "okay"; }; + + chipid@fc069000 { + compatible = "atmel,sama5d2-chipid"; + reg = <0xfc069000 0x8>; + }; }; }; }; -- GitLab From fd718627b31dfccc1875320a1e63bfc654ca4dc4 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 10 Mar 2016 14:25:16 +0100 Subject: [PATCH 0623/9938] ARM: dts: at91: sama5d2: add LCD controller Add LCD controller node that binds to the atmel_hlcdc DRM driver. Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/sama5d2.dtsi | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 0e4471d1fc46..12cc1d34097d 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -319,6 +319,32 @@ #size-cells = <1>; ranges; + hlcdc: hlcdc@f0000000 { + compatible = "atmel,sama5d2-hlcdc"; + reg = <0xf0000000 0x2000>; + interrupts = <45 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&lcdc_clk>, <&lcdck>, <&clk32k>; + clock-names = "periph_clk","sys_clk", "slow_clk"; + status = "disabled"; + + hlcdc-display-controller { + compatible = "atmel,hlcdc-display-controller"; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + }; + + hlcdc_pwm: hlcdc-pwm { + compatible = "atmel,hlcdc-pwm"; + #pwm-cells = <3>; + }; + }; + ramc0: ramc@f000c000 { compatible = "atmel,sama5d3-ddramc"; reg = <0xf000c000 0x200>; -- GitLab From 2f26e6189d3bdfcbf2b3bd0d6ff88eb8e7022246 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Fri, 18 Mar 2016 08:21:19 +0100 Subject: [PATCH 0624/9938] ARM: at91: use chipid device for soc detection So far, the CIDR and EXID registers were in the DBGU interface. This device has disappeared with the SAMA5D2 family. These registers are exposed through a new device called chipid. Signed-off-by: Ludovic Desroches [nicolas.ferre@atmel.com: remove useless warnings] Acked-by: Alexandre Belloni Acked-by: Rob Herring [arnd@arndb.de: suggest to use static functions to reduce scope] Acked-by: Arnd Bergmann Signed-off-by: Nicolas Ferre --- .../devicetree/bindings/arm/atmel-at91.txt | 4 + arch/arm/mach-at91/soc.c | 81 ++++++++++++++----- 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 7fd64ec9ee1d..0b1fcbfe2299 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -41,6 +41,10 @@ compatible: must be one of: - "atmel,sama5d43" - "atmel,sama5d44" +Chipid required properties: +- compatible: Should be "atmel,sama5d2-chipid" +- reg : Should contain registers location and length + PIT Timer required properties: - compatible: Should be "atmel,at91sam9260-pit" - reg: Should contain registers location and length diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c index 54343ffa3e53..c6fda75ddb89 100644 --- a/arch/arm/mach-at91/soc.c +++ b/arch/arm/mach-at91/soc.c @@ -22,48 +22,93 @@ #include "soc.h" #define AT91_DBGU_CIDR 0x40 -#define AT91_DBGU_CIDR_VERSION(x) ((x) & 0x1f) -#define AT91_DBGU_CIDR_EXT BIT(31) -#define AT91_DBGU_CIDR_MATCH_MASK 0x7fffffe0 #define AT91_DBGU_EXID 0x44 +#define AT91_CHIPID_CIDR 0x00 +#define AT91_CHIPID_EXID 0x04 +#define AT91_CIDR_VERSION(x) ((x) & 0x1f) +#define AT91_CIDR_EXT BIT(31) +#define AT91_CIDR_MATCH_MASK 0x7fffffe0 -struct soc_device * __init at91_soc_init(const struct at91_soc *socs) +static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid) { - struct soc_device_attribute *soc_dev_attr; - const struct at91_soc *soc; - struct soc_device *soc_dev; struct device_node *np; void __iomem *regs; - u32 cidr, exid; np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu"); if (!np) np = of_find_compatible_node(NULL, NULL, "atmel,at91sam9260-dbgu"); + if (!np) + return -ENODEV; - if (!np) { - pr_warn("Could not find DBGU node"); - return NULL; + regs = of_iomap(np, 0); + of_node_put(np); + + if (!regs) { + pr_warn("Could not map DBGU iomem range"); + return -ENXIO; } + *cidr = readl(regs + AT91_DBGU_CIDR); + *exid = readl(regs + AT91_DBGU_EXID); + + iounmap(regs); + + return 0; +} + +static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid) +{ + struct device_node *np; + void __iomem *regs; + + np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid"); + if (!np) + return -ENODEV; + regs = of_iomap(np, 0); of_node_put(np); if (!regs) { pr_warn("Could not map DBGU iomem range"); - return NULL; + return -ENXIO; } - cidr = readl(regs + AT91_DBGU_CIDR); - exid = readl(regs + AT91_DBGU_EXID); + *cidr = readl(regs + AT91_CHIPID_CIDR); + *exid = readl(regs + AT91_CHIPID_EXID); iounmap(regs); + return 0; +} + +struct soc_device * __init at91_soc_init(const struct at91_soc *socs) +{ + struct soc_device_attribute *soc_dev_attr; + const struct at91_soc *soc; + struct soc_device *soc_dev; + u32 cidr, exid; + int ret; + + /* + * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more + * in the dbgu device but in the chipid device whose purpose is only + * to expose these two registers. + */ + ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid); + if (ret) + ret = at91_get_cidr_exid_from_chipid(&cidr, &exid); + if (ret) { + if (ret == -ENODEV) + pr_warn("Could not find identification node"); + return NULL; + } + for (soc = socs; soc->name; soc++) { - if (soc->cidr_match != (cidr & AT91_DBGU_CIDR_MATCH_MASK)) + if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK)) continue; - if (!(cidr & AT91_DBGU_CIDR_EXT) || soc->exid_match == exid) + if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid) break; } @@ -79,7 +124,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) soc_dev_attr->family = soc->family; soc_dev_attr->soc_id = soc->name; soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", - AT91_DBGU_CIDR_VERSION(cidr)); + AT91_CIDR_VERSION(cidr)); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { kfree(soc_dev_attr->revision); @@ -91,7 +136,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) if (soc->family) pr_info("Detected SoC family: %s\n", soc->family); pr_info("Detected SoC: %s, revision %X\n", soc->name, - AT91_DBGU_CIDR_VERSION(cidr)); + AT91_CIDR_VERSION(cidr)); return soc_dev; } -- GitLab From c07f98a73978964065b57079cae9ab9d060769fe Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Fri, 18 Mar 2016 08:21:20 +0100 Subject: [PATCH 0625/9938] ARM: at91/soc: reference the whole sama5d2 family Add EXID of all SoCs of the SAMA5D2 family. Signed-off-by: Ludovic Desroches Acked-by: Alexandre Belloni Acked-by: Arnd Bergmann Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/sama5.c | 20 +++++++++++++++++++- arch/arm/mach-at91/soc.h | 12 +++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c index df8fdf1cf66d..922b85f07cd2 100644 --- a/arch/arm/mach-at91/sama5.c +++ b/arch/arm/mach-at91/sama5.c @@ -18,8 +18,26 @@ #include "soc.h" static const struct at91_soc sama5_socs[] = { - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH, + "sama5d21", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH, + "sama5d22", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH, + "sama5d23", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH, + "sama5d24", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH, + "sama5d24", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH, + "sama5d26", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH, "sama5d27", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH, + "sama5d27", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH, + "sama5d28", "sama5d2"), + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH, + "sama5d28", "sama5d2"), AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, "sama5d31", "sama5d3"), AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h index 8ede0ef86172..228efded5085 100644 --- a/arch/arm/mach-at91/soc.h +++ b/arch/arm/mach-at91/soc.h @@ -63,7 +63,17 @@ at91_soc_init(const struct at91_soc *socs); #define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0 #define SAMA5D2_CIDR_MATCH 0x0a5c08c0 -#define SAMA5D27_EXID_MATCH 0x00000021 +#define SAMA5D21CU_EXID_MATCH 0x0000005a +#define SAMA5D22CU_EXID_MATCH 0x00000059 +#define SAMA5D22CN_EXID_MATCH 0x00000069 +#define SAMA5D23CU_EXID_MATCH 0x00000058 +#define SAMA5D24CX_EXID_MATCH 0x00000004 +#define SAMA5D24CU_EXID_MATCH 0x00000014 +#define SAMA5D26CU_EXID_MATCH 0x00000012 +#define SAMA5D27CU_EXID_MATCH 0x00000011 +#define SAMA5D27CN_EXID_MATCH 0x00000021 +#define SAMA5D28CU_EXID_MATCH 0x00000010 +#define SAMA5D28CN_EXID_MATCH 0x00000020 #define SAMA5D3_CIDR_MATCH 0x0a5c07c0 #define SAMA5D31_EXID_MATCH 0x00444300 -- GitLab From 52d7c42664e6348fbe5fc062590bb8f152b65d94 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Tue, 28 Apr 2015 00:41:09 +0200 Subject: [PATCH 0626/9938] ARM: dts: lpc18xx: add creg-clk node Add node for the creg clock controller and change the input clock on cgu to use it. Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc18xx.dtsi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index 053a1f54f4bb..0b59eae1608d 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -195,6 +195,12 @@ clocks = <&ccu1 CLK_CPU_CREG>; resets = <&rgu 5>; + creg_clk: clock-controller { + compatible = "nxp,lpc1850-creg-clk"; + clocks = <&xtal32>; + #clock-cells = <1>; + }; + usb0_otg_phy: phy@004 { compatible = "nxp,lpc1850-usb-otg-phy"; clocks = <&ccu1 CLK_USB0>; @@ -213,7 +219,7 @@ compatible = "nxp,lpc1850-cgu"; reg = <0x40050000 0x1000>; #clock-cells = <1>; - clocks = <&xtal>, <&xtal32>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>; + clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>; }; ccu1: clock-controller@40051000 { -- GitLab From 9fe3219743dea7b6f14afec2f853c3f615b8849b Mon Sep 17 00:00:00 2001 From: Adam Baker Date: Sat, 5 Mar 2016 15:34:57 +0000 Subject: [PATCH 0627/9938] ARM: dts: kirkwood: Add the hardware monitor to the NSA320 device tree Add an entry for the hardware monitoring MCU [gregory.clement@free-electrons.com: rename the title to use the "standard" format] Signed-off-by: Adam Baker Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-nsa320.dts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-nsa320.dts b/arch/arm/boot/dts/kirkwood-nsa320.dts index 24f686d1044d..2a935e94f96f 100644 --- a/arch/arm/boot/dts/kirkwood-nsa320.dts +++ b/arch/arm/boot/dts/kirkwood-nsa320.dts @@ -193,10 +193,19 @@ }; }; + hwmon { + compatible = "zyxel,nsa320-mcu"; + pinctrl-0 = <&pmx_mcu_data &pmx_mcu_clk &pmx_mcu_act>; + pinctrl-names = "default"; + + data-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + clk-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + act-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + }; + /* The following pins are currently not assigned to a driver, some of them should be configured as inputs. - pinctrl-0 = <&pmx_mcu_data &pmx_mcu_clk &pmx_mcu_act - &pmx_htp &pmx_vid_b1 + pinctrl-0 = <&pmx_htp &pmx_vid_b1 &pmx_power_resume_data &pmx_power_resume_clk>; */ }; -- GitLab From 97cc2ed27e5a168cf423f67c3bc7c6cc41d12f82 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 29 Mar 2016 18:48:07 +0200 Subject: [PATCH 0628/9938] ALSA: hda - Fix yet another i915 pointer leftover in error path The hdac_acomp object in hdac_i915.c is left as assigned even after binding with i915 actually fails, and this leads to the WARN_ON() at the next load of the module. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94736 Signed-off-by: Takashi Iwai --- sound/hda/hdac_i915.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index ae0f305a7e41..d0da2508823e 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -339,6 +339,7 @@ int snd_hdac_i915_init(struct hdac_bus *bus) out_err: kfree(acomp); bus->audio_component = NULL; + hdac_acomp = NULL; dev_info(dev, "failed to add i915 component master (%d)\n", ret); return ret; -- GitLab From 6e4f28780f38e27cb7ca0edeb1d7ebb4edfd1fc5 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 29 Mar 2016 08:53:32 +0200 Subject: [PATCH 0629/9938] regcache: flat: Require max_registers to be set If max_register is unset, regcache_flat_get_index will return 0 and only memory for 1 unsigned int will be allocated, resulting in writing out of bounds. Signed-off-by: Alexander Stein Signed-off-by: Mark Brown --- drivers/base/regmap/regcache-flat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c index 3ee72550b1e3..4d2e50bfc726 100644 --- a/drivers/base/regmap/regcache-flat.c +++ b/drivers/base/regmap/regcache-flat.c @@ -27,7 +27,7 @@ static int regcache_flat_init(struct regmap *map) int i; unsigned int *cache; - if (!map || map->reg_stride_order < 0) + if (!map || map->reg_stride_order < 0 || !map->max_register) return -EINVAL; map->cache = kcalloc(regcache_flat_get_index(map, map->max_register) -- GitLab From 65147846796bd443972d9055b3b4c1339e15d53a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 28 Mar 2016 08:31:18 -0300 Subject: [PATCH 0630/9938] ASoC: wm8962: Disable clock if wm8962_runtime_resume() fails When regulator_bulk_enable() fails inside wm8962_runtime_resume(), we should disable the previously enabled clock. Signed-off-by: Fabio Estevam Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 88223608a33f..f3f71ba0ed12 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3800,7 +3800,7 @@ static int wm8962_runtime_resume(struct device *dev) if (ret != 0) { dev_err(dev, "Failed to enable supplies: %d\n", ret); - return ret; + goto disable_clock; } regcache_cache_only(wm8962->regmap, false); @@ -3838,6 +3838,10 @@ static int wm8962_runtime_resume(struct device *dev) msleep(5); return 0; + +disable_clock: + clk_disable_unprepare(wm8962->pdata.mclk); + return ret; } static int wm8962_runtime_suspend(struct device *dev) -- GitLab From 8bfa934e10d99b524bfe80b793e235b9188a7b58 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 28 Mar 2016 08:31:19 -0300 Subject: [PATCH 0631/9938] ASoC: wm8962: Fit error message into a single line The error message fits well into a single line. Signed-off-by: Fabio Estevam Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f3f71ba0ed12..93f75dcee388 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3798,8 +3798,7 @@ static int wm8962_runtime_resume(struct device *dev) ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); if (ret != 0) { - dev_err(dev, - "Failed to enable supplies: %d\n", ret); + dev_err(dev, "Failed to enable supplies: %d\n", ret); goto disable_clock; } -- GitLab From 937e92dc50231bb41294262abf56d2bdddc4d38c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 27 Mar 2016 18:36:13 -0300 Subject: [PATCH 0632/9938] ASoC: wm8962: Adjust clk definitions so that simple card can work When trying to use simple card with wm8962 the following probe error happens: wm8962 0-001a: simple-card: set_sysclk error asoc-simple-card sound: ASoC: failed to init 202c000.ssi-wm8962: -22 asoc-simple-card sound: ASoC: failed to instantiate card -22 asoc-simple-card: probe of sound failed with error -22 In simple-card.c the snd_soc_dai_set_sysclk() function is called with clk_id as 0, which is an invalid clock for wm8962. Adjust the clocks source definitions in wm8962.h so that the simple card driver can work successfully. Signed-off-by: Fabio Estevam Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h index 910aafd09d21..e63a318a3015 100644 --- a/sound/soc/codecs/wm8962.h +++ b/sound/soc/codecs/wm8962.h @@ -16,9 +16,9 @@ #include #include -#define WM8962_SYSCLK_MCLK 1 -#define WM8962_SYSCLK_FLL 2 -#define WM8962_SYSCLK_PLL3 3 +#define WM8962_SYSCLK_MCLK 0 +#define WM8962_SYSCLK_FLL 1 +#define WM8962_SYSCLK_PLL3 2 #define WM8962_FLL 1 -- GitLab From 612047f0baefe2aeef1bc5ad8c7107a532b7d957 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 28 Mar 2016 14:29:22 +0100 Subject: [PATCH 0633/9938] ASoC: wm_adsp: Fix some subtle races on compressed stream Firstly, we should be locking the pwr_lock when we initialise the compressed buffer. Secondly, fixup a couple of places when we should be pulling pointers only under the pwr_lock as they may be affected by operations that take that lock. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index d3b1cb15e7f0..4839d195c72a 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2240,9 +2240,13 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, if (ret != 0) goto err; + mutex_lock(&dsp->pwr_lock); + if (wm_adsp_fw[dsp->fw].num_caps != 0) ret = wm_adsp_buffer_init(dsp); + mutex_unlock(&dsp->pwr_lock); + break; case SND_SOC_DAPM_PRE_PMD: @@ -2814,12 +2818,15 @@ static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) { - struct wm_adsp_compr_buf *buf = dsp->buffer; - struct wm_adsp_compr *compr = dsp->compr; + struct wm_adsp_compr_buf *buf; + struct wm_adsp_compr *compr; int ret = 0; mutex_lock(&dsp->pwr_lock); + buf = dsp->buffer; + compr = dsp->compr; + if (!buf) { ret = -ENODEV; goto out; @@ -2879,14 +2886,16 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream, struct snd_compr_tstamp *tstamp) { struct wm_adsp_compr *compr = stream->runtime->private_data; - struct wm_adsp_compr_buf *buf = compr->buf; struct wm_adsp *dsp = compr->dsp; + struct wm_adsp_compr_buf *buf; int ret = 0; adsp_dbg(dsp, "Pointer request\n"); mutex_lock(&dsp->pwr_lock); + buf = compr->buf; + if (!compr->buf) { ret = -ENXIO; goto out; -- GitLab From 33d740e07d1f565e44d35e7f7756a619b4f1e4ba Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 28 Mar 2016 14:29:21 +0100 Subject: [PATCH 0634/9938] ASoC: wm_adsp: Show avail in bytes to match other messages All other debug messages talk about data on the compressed stream in bytes except avail which is shown in words. To avoid confusion show avail in bytes as well. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 4839d195c72a..953c4278b75e 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2809,7 +2809,7 @@ static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) avail += wm_adsp_buffer_size(buf); adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n", - buf->read_index, write_index, avail); + buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE); buf->avail = avail; -- GitLab From 9abe3dc77ea7ccad1c2112257bb352435dcee0ff Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 28 Mar 2016 14:29:23 +0100 Subject: [PATCH 0635/9938] ASoC: cs47l24: Fix a couple of small whitespace errors Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 576087bda330..383700a178c7 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1157,6 +1157,7 @@ static struct snd_compr_ops cs47l24_compr_ops = { static struct snd_soc_platform_driver cs47l24_compr_platform = { .compr_ops = &cs47l24_compr_ops, }; + static int cs47l24_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); @@ -1225,9 +1226,9 @@ static int cs47l24_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to register platform: %d\n", ret); return ret; } + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24, cs47l24_dai, ARRAY_SIZE(cs47l24_dai)); - if (ret < 0) { dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); snd_soc_unregister_platform(&pdev->dev); -- GitLab From c13202f7d7101a6f5542f3a31b9a6787ae7b746c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 28 Mar 2016 14:29:24 +0100 Subject: [PATCH 0636/9938] ASoC: cs47l24: Add support for audio trace firmware cs47l24 supports the audio trace firmware, this streams of audio to be captured from the CODEC over a compressed audio channel for analysis/debugging of audio processing firmwares. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 383700a178c7..6b8b5571d3cc 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -807,6 +807,9 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "IN2L PGA", NULL, "IN2L" }, { "IN2R PGA", NULL, "IN2R" }, + { "Audio Trace DSP", NULL, "DSP2" }, + { "Audio Trace DSP", NULL, "SYSCLK" }, + ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), @@ -1016,6 +1019,27 @@ static struct snd_soc_dai_driver cs47l24_dai[] = { .formats = CS47L24_FORMATS, }, }, + { + .name = "cs47l24-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 6, + .rates = CS47L24_RATES, + .formats = CS47L24_FORMATS, + }, + .compress_new = snd_soc_new_compress, + }, + { + .name = "cs47l24-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 6, + .rates = CS47L24_RATES, + .formats = CS47L24_FORMATS, + }, + }, }; static int cs47l24_open(struct snd_compr_stream *stream) @@ -1027,6 +1051,8 @@ static int cs47l24_open(struct snd_compr_stream *stream) if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-voicectrl") == 0) { n_adsp = 2; + } else if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-trace") == 0) { + n_adsp = 1; } else { dev_err(arizona->dev, "No suitable compressed stream for DAI '%s'\n", @@ -1041,10 +1067,16 @@ static irqreturn_t cs47l24_adsp2_irq(int irq, void *data) { struct cs47l24_priv *priv = data; struct arizona *arizona = priv->core.arizona; - int ret; + int serviced = 0; + int i, ret; + + for (i = 1; i <= 2; ++i) { + ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]); + if (ret != -ENODEV) + serviced++; + } - ret = wm_adsp_compr_handle_irq(&priv->core.adsp[2]); - if (ret == -ENODEV) { + if (!serviced) { dev_err(arizona->dev, "Spurious compressed data IRQ\n"); return IRQ_NONE; } -- GitLab From 00411b7b1e3ec477b75bb83ccd417c7609832db6 Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Mon, 22 Feb 2016 16:18:18 -0500 Subject: [PATCH 0637/9938] firmware: fw_cfg register offsets on supported architectures only Refrain from defining default fw_cfg register offsets on unsupported architectures -- throw an error instead. If QEMU were to add fw_cfg support on additional architectures, we should add them to the FW_CFG_SYSFS depends statement in drivers/firmware/Kconfig, and provide default values for register offsets in drivers/firmware/qemu_fw_cfg.c at that time. Suggested-by: Michael S. Tsirkin Signed-off-by: Gabriel Somlo Acked-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/qemu_fw_cfg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index fedbff55a7f3..7bba76c0206c 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -109,9 +109,7 @@ static void fw_cfg_io_cleanup(void) # define FW_CFG_CTRL_OFF 0x00 # define FW_CFG_DATA_OFF 0x01 # else -# warning "QEMU FW_CFG may not be available on this architecture!" -# define FW_CFG_CTRL_OFF 0x00 -# define FW_CFG_DATA_OFF 0x01 +# error "QEMU FW_CFG not available on this architecture!" # endif #endif -- GitLab From 49db08c358873af11ba3c25401de88156fa5d365 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 19 Feb 2016 15:36:07 +0100 Subject: [PATCH 0638/9938] chrdev: emit a warning when we go below dynamic major range Currently a dynamically allocated character device major is taken from 254 and downward. This mechanism is used for RTC, IIO and a few other subsystems. The kernel currently has no check prevening these dynamic allocations from eating into the assigned numbers at 233 and downward. In a recent test it was reported that so many dynamic device majors were used on a test server, that the major number for infiniband (231) was stolen. This occurred when allocating a new major number for GPIO chips. The error messages from the kernel were not helpful. (See: https://lkml.org/lkml/2016/2/14/124) This patch adds a defined lower limit of the dynamic major allocation region will henceforth emit a warning if we start to eat into the assigned numbers. It does not do any semantic changes and will not change the kernels behaviour: numbers will still continue to be stolen, but we will know from dmesg what is going on. This also updates the Documentation/devices.txt to clearly reflect that we are using this range of major numbers for dynamic allocation. Reported-by: Ying Huang Cc: Linus Torvalds Cc: Greg Kroah-Hartman Cc: Alan Cox Cc: Arnd Bergmann Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- Documentation/devices.txt | 6 +++--- fs/char_dev.c | 4 ++++ include/linux/fs.h | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 87b4c5e82d39..0a3588a9798d 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -3099,9 +3099,9 @@ Your cooperation is appreciated. 129 = /dev/ipath_sma Device used by Subnet Management Agent 130 = /dev/ipath_diag Device used by diagnostics programs -234-239 UNASSIGNED - -240-254 char LOCAL/EXPERIMENTAL USE +234-254 char RESERVED FOR DYNAMIC ASSIGNMENT + Character devices that request a dynamic allocation of major number will + take numbers starting from 254 and downward. 240-254 block LOCAL/EXPERIMENTAL USE Allocated for local/experimental use. For devices not diff --git a/fs/char_dev.c b/fs/char_dev.c index 24b142569ca9..687471dc04a0 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -91,6 +91,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, break; } + if (i < CHRDEV_MAJOR_DYN_END) + pr_warn("CHRDEV \"%s\" major number %d goes below the dynamic allocation range", + name, i); + if (i == 0) { ret = -EBUSY; goto out; diff --git a/include/linux/fs.h b/include/linux/fs.h index 14a97194b34b..60082be96de8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2385,6 +2385,8 @@ static inline void bd_unlink_disk_holder(struct block_device *bdev, /* fs/char_dev.c */ #define CHRDEV_MAJOR_HASH_SIZE 255 +/* Marks the bottom of the first segment of free char majors */ +#define CHRDEV_MAJOR_DYN_END 234 extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); extern int register_chrdev_region(dev_t, unsigned, const char *); extern int __register_chrdev(unsigned int major, unsigned int baseminor, -- GitLab From ebdf4040c16df572d95ea63fc1f64c156baeb947 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 19 Feb 2016 21:17:36 +0100 Subject: [PATCH 0639/9938] Documentation: update the devices.txt documentation Alan is no longer maintaining this list through the Linux assigned numbers authority. Make it a collective document by referring to "the maintainers" in plural throughout, and naming the chardev and block layer maintainers in particular as parties of involvement. Cut down and remove some sections that pertained to the process of maintaining the list at lanana.org and contacting Alan directly. Make it clear that this document, in the kernel, is the master document. Also move paragraphs around so as to emphasize dynamic major number allocation. Remove paragraph on 2.6 deprecation, that tag no longer appears anywhere in the file. Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Alan Cox Cc: Arnd Bergmann Cc: Jens Axboe Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- CREDITS | 1 + Documentation/devices.txt | 80 ++++++++++++--------------------------- 2 files changed, 26 insertions(+), 55 deletions(-) diff --git a/CREDITS b/CREDITS index 4312cd076b5b..0f0bf22afe0c 100644 --- a/CREDITS +++ b/CREDITS @@ -768,6 +768,7 @@ D: Z85230 driver D: Former security contact point (please use vendor-sec@lst.de) D: ex 2.2 maintainer D: 2.1.x modular sound +D: Assigned major/minor numbers maintainer at lanana.org S: c/o Red Hat UK Ltd S: Alexandra House S: Alexandra Terrace diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 0a3588a9798d..4035eca87144 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -1,20 +1,17 @@ - LINUX ALLOCATED DEVICES (2.6+ version) - - Maintained by Alan Cox - - Last revised: 6th April 2009 + LINUX ALLOCATED DEVICES (4.x+ version) This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating system. -The latest version of this list is available from -http://www.lanana.org/docs/device-list/ or -ftp://ftp.kernel.org/pub/linux/docs/device-list/. This version may be -newer than the one distributed with the Linux kernel. - -The LaTeX version of this document is no longer maintained. +The LaTeX version of this document is no longer maintained, nor is +the document that used to reside at lanana.org. This version in the +mainline Linux kernel is the master document. Updates shall be sent +as patches to the kernel maintainers (see the SubmittingPatches document). +Specifically explore the sections titled "CHAR and MISC DRIVERS", and +"BLOCK LAYER" in the MAINTAINERS file to find the right maintainers +to involve for character and block devices. This document is included by reference into the Filesystem Hierarchy Standard (FHS). The FHS is available from http://www.pathname.com/fhs/. @@ -23,60 +20,33 @@ Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga platform only. Allocations marked (68k/Atari) apply to Linux/68k on the Atari platform only. -The symbol {2.6} means the allocation is obsolete and scheduled for -removal once kernel version 2.6 (or equivalent) is released. Some of these -allocations have already been removed. - -This document is in the public domain. The author requests, however, +This document is in the public domain. The authors requests, however, that semantically altered versions are not distributed without -permission of the author, assuming the author can be contacted without +permission of the authors, assuming the authors can be contacted without an unreasonable effort. -In particular, please don't sent patches for this list to Linus, at -least not without contacting me first. - -I do not have any information about these devices beyond what appears -on this list. Any such information requests will be deleted without -reply. - **** DEVICE DRIVERS AUTHORS PLEASE READ THIS **** -To have a major number allocated, or a minor number in situations -where that applies (e.g. busmice), please contact me with the -appropriate device information. Also, if you have additional -information regarding any of the devices listed below, or if I have -made a mistake, I would greatly appreciate a note. - -I do, however, make a few requests about the nature of your report. -This is necessary for me to be able to keep this list up to date and -correct in a timely manner. First of all, *please* send it to the -correct address... . I receive hundreds of email -messages a day, so mail sent to other addresses may very well get lost -in the avalanche. Please put in a descriptive subject, so I can find -your mail again should I need to. Too many people send me email -saying just "device number request" in the subject. - -Second, please include a description of the device *in the same format -as this list*. The reason for this is that it is the only way I have -found to ensure I have all the requisite information to publish your -device and avoid conflicts. +Linux now has extensive support for dynamic allocation of device numbering +and can use sysfs and udev (systemd) to handle the naming needs. There are +still some exceptions in the serial and boot device area. Before asking +for a device number make sure you actually need one. -Third, please don't assume that the distributed version of the list is -up to date. Due to the number of registrations I have to maintain it -in "batch mode", so there is likely additional registrations that -haven't been listed yet. +To have a major number allocated, or a minor number in situations +where that applies (e.g. busmice), please submit a patch and send to +the authors as indicated above. -Fourth, remember that Linux now has extensive support for dynamic allocation -of device numbering and can use sysfs and udev to handle the naming needs. -There are still some exceptions in the serial and boot device area. Before -asking for a device number make sure you actually need one. +Keep the description of the device *in the same format +as this list*. The reason for this is that it is the only way we have +found to ensure we have all the requisite information to publish your +device and avoid conflicts. -Finally, sometimes I have to play "namespace police." Please don't be -offended. I often get submissions for /dev names that would be bound -to cause conflicts down the road. I am trying to avoid getting in a +Finally, sometimes we have to play "namespace police." Please don't be +offended. We often get submissions for /dev names that would be bound +to cause conflicts down the road. We are trying to avoid getting in a situation where we would have to suffer an incompatible forward -change. Therefore, please consult with me *before* you make your +change. Therefore, please consult with us *before* you make your device names and numbers in any way public, at least to the point where it would be at all difficult to get them changed. -- GitLab From b3c1be1b789cca6d3e39c950dfed690f0511fe76 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Fri, 22 Jan 2016 11:28:07 -0500 Subject: [PATCH 0640/9938] base: isa: Remove X86_32 dependency Many motherboards utilize a LPC to ISA bridge in order to decode ISA-style port-mapped I/O addresses. This is particularly true for embedded motherboards supporting the PC/104 bus (a bus specification derived from ISA). These motherboards are now commonly running 64-bit x86 processors. The X86_32 dependency should be removed from the ISA bus configuration option in order to support these newer motherboards. A new config option, CONFIG_ISA_BUS, is introduced to allow for the compilation of the ISA bus driver independent of the CONFIG_ISA option. Devices which communicate via ISA-compatible buses can now be supported independent of the dependencies of the CONFIG_ISA option. Signed-off-by: William Breathitt Gray Reviewed-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig | 6 ++++++ drivers/base/Makefile | 2 +- include/linux/isa.h | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2dc18605831f..a5977986f38b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2472,10 +2472,16 @@ config ISA_DMA_API Enables ISA-style DMA support for devices requiring such controllers. If unsure, say Y. +config ISA_BUS + bool "ISA bus support" + help + Enables ISA bus support for devices requiring such controllers. + if X86_32 config ISA bool "ISA support" + depends on ISA_BUS ---help--- Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 6b2a84e7f2be..4ebfb81cc7e9 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_DMA_CMA) += dma-contiguous.o obj-y += power/ obj-$(CONFIG_HAS_DMA) += dma-mapping.o obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o -obj-$(CONFIG_ISA) += isa.o +obj-$(CONFIG_ISA_BUS) += isa.o obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o diff --git a/include/linux/isa.h b/include/linux/isa.h index b0270e3814c8..2a02862775eb 100644 --- a/include/linux/isa.h +++ b/include/linux/isa.h @@ -22,7 +22,7 @@ struct isa_driver { #define to_isa_driver(x) container_of((x), struct isa_driver, driver) -#ifdef CONFIG_ISA +#ifdef CONFIG_ISA_BUS int isa_register_driver(struct isa_driver *, unsigned int); void isa_unregister_driver(struct isa_driver *); #else -- GitLab From a8f324a46fbe5473633af00039e81821be0ce51b Mon Sep 17 00:00:00 2001 From: Roman Pen Date: Tue, 9 Feb 2016 11:30:29 +0100 Subject: [PATCH 0641/9938] debugfs: fix inode i_nlink references for automount dentry Directory inodes should start off with i_nlink == 2 (one extra ref for "." entry). debugfs_create_automount() increases neither the i_nlink reference for current inode nor for parent inode. On attempt to remove the automount dentry, kernel complains: [ 86.288070] WARNING: CPU: 1 PID: 3616 at fs/inode.c:273 drop_nlink+0x3e/0x50() [ 86.288461] Modules linked in: debugfs_example2(O-) [ 86.288745] CPU: 1 PID: 3616 Comm: rmmod Tainted: G O 4.4.0-rc3-next-20151207+ #135 [ 86.289197] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.8.2-20150617_082717-anatol 04/01/2014 [ 86.289696] ffffffff81be05c9 ffff8800b9e6fda0 ffffffff81352e2c 0000000000000000 [ 86.290110] ffff8800b9e6fdd8 ffffffff81065142 ffff8801399175e8 ffff8800bb78b240 [ 86.290507] ffff8801399175e8 ffff8800b73d7898 ffff8800b73d7840 ffff8800b9e6fde8 [ 86.290933] Call Trace: [ 86.291080] [] dump_stack+0x4e/0x82 [ 86.291340] [] warn_slowpath_common+0x82/0xc0 [ 86.291640] [] warn_slowpath_null+0x1a/0x20 [ 86.291932] [] drop_nlink+0x3e/0x50 [ 86.292208] [] simple_unlink+0x4b/0x60 [ 86.292481] [] simple_rmdir+0x37/0x50 [ 86.292748] [] __debugfs_remove.part.16+0xa8/0xd0 [ 86.293082] [] debugfs_remove_recursive+0xdb/0x1c0 [ 86.293406] [] cleanup_module+0x2d/0x3b [debugfs_example2] [ 86.293762] [] SyS_delete_module+0x16b/0x220 [ 86.294077] [] entry_SYSCALL_64_fastpath+0x12/0x6a [ 86.294405] ---[ end trace c9fc53353fe14a36 ]--- [ 86.294639] ------------[ cut here ]------------ To reproduce the issue it is enough to invoke these lines: autom = debugfs_create_automount("automount", NULL, vfsmount_cb, data); BUG_ON(IS_ERR_OR_NULL(autom)); debugfs_remove(autom); The issue is fixed by increasing inode i_nlink references for current and parent inodes. Signed-off-by: Roman Pen Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index bece948b363d..13d65f8a7b12 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -461,7 +461,11 @@ struct dentry *debugfs_create_automount(const char *name, inode->i_flags |= S_AUTOMOUNT; inode->i_private = data; dentry->d_fsdata = (void *)f; + /* directory inodes start off with i_nlink == 2 (for "." entry) */ + inc_nlink(inode); d_instantiate(dentry, inode); + inc_nlink(d_inode(dentry->d_parent)); + fsnotify_mkdir(d_inode(dentry->d_parent), dentry); return end_creating(dentry); } EXPORT_SYMBOL(debugfs_create_automount); -- GitLab From 1b48b530dac3e600d92854d98a2a519243661f6c Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Mon, 22 Feb 2016 07:17:47 -0800 Subject: [PATCH 0642/9938] fs: debugfs: Replace CURRENT_TIME by current_fs_time() CURRENT_TIME macro is not appropriate for filesystems as it doesn't use the right granularity for filesystem timestamps. Use current_fs_time() instead. Signed-off-by: Deepa Dinamani Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 13d65f8a7b12..b1e7f35f3cd4 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -39,7 +39,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb) struct inode *inode = new_inode(sb); if (inode) { inode->i_ino = get_next_ino(); - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_atime = inode->i_mtime = + inode->i_ctime = current_fs_time(sb); } return inode; } -- GitLab From 3a3a5fece6f28c14d3d05c74fb7696412e53a067 Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Mon, 22 Feb 2016 07:17:53 -0800 Subject: [PATCH 0643/9938] fs: kernfs: Replace CURRENT_TIME by current_fs_time() This is in preparation for the series that transitions filesystem timestamps to use 64 bit time and hence make them y2038 safe. CURRENT_TIME macro will be deleted before merging the aforementioned series. Use current_fs_time() instead of CURRENT_TIME for inode timestamps. struct kernfs_node is associated with a sysfs file/ directory. Truncate the values to appropriate time granularity when writing to inode timestamps of the files. ktime_get_real_ts() is used to obtain times for struct kernfs_iattrs. Since these times are later assigned to inode times using timespec_truncate() for all filesystem based operations, we can save the supers list traversal time here by using ktime_get_real_ts() directly. Signed-off-by: Deepa Dinamani Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/dir.c | 8 +++++--- fs/kernfs/inode.c | 15 ++++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 03b688d19f69..eb2c58732bcf 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -753,7 +753,8 @@ int kernfs_add_one(struct kernfs_node *kn) ps_iattr = parent->iattr; if (ps_iattr) { struct iattr *ps_iattrs = &ps_iattr->ia_iattr; - ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; + ktime_get_real_ts(&ps_iattrs->ia_ctime); + ps_iattrs->ia_mtime = ps_iattrs->ia_ctime; } mutex_unlock(&kernfs_mutex); @@ -1279,8 +1280,9 @@ static void __kernfs_remove(struct kernfs_node *kn) /* update timestamps on the parent */ if (ps_iattr) { - ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME; - ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; + ktime_get_real_ts(&ps_iattr->ia_iattr.ia_ctime); + ps_iattr->ia_iattr.ia_mtime = + ps_iattr->ia_iattr.ia_ctime; } kernfs_put(pos); diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 16405ae88d2d..1ac1dbae5aba 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -54,7 +54,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) iattrs->ia_mode = kn->mode; iattrs->ia_uid = GLOBAL_ROOT_UID; iattrs->ia_gid = GLOBAL_ROOT_GID; - iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; + + ktime_get_real_ts(&iattrs->ia_atime); + iattrs->ia_mtime = iattrs->ia_atime; + iattrs->ia_ctime = iattrs->ia_atime; simple_xattrs_init(&kn->iattr->xattrs); out_unlock: @@ -236,16 +239,18 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) static inline void set_default_inode_attr(struct inode *inode, umode_t mode) { inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_atime = inode->i_mtime = + inode->i_ctime = current_fs_time(inode->i_sb); } static inline void set_inode_attr(struct inode *inode, struct iattr *iattr) { + struct super_block *sb = inode->i_sb; inode->i_uid = iattr->ia_uid; inode->i_gid = iattr->ia_gid; - inode->i_atime = iattr->ia_atime; - inode->i_mtime = iattr->ia_mtime; - inode->i_ctime = iattr->ia_ctime; + inode->i_atime = timespec_trunc(iattr->ia_atime, sb->s_time_gran); + inode->i_mtime = timespec_trunc(iattr->ia_mtime, sb->s_time_gran); + inode->i_ctime = timespec_trunc(iattr->ia_ctime, sb->s_time_gran); } static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) -- GitLab From 9895c03d48115c7783c0ef0a591447d53254ef84 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 21 Jan 2016 17:07:24 -0500 Subject: [PATCH 0644/9938] kbuild: record needed exported symbols for modules Kernel modules are partially linked object files with some undefined symbols that are expected to be matched with EXPORT_SYMBOL() entries from elsewhere. Each .tmp_versions/*.mod file currently contains two line of text separated by a newline character. The first line has the actual module file name while the second line has a list of object files constituting that module. Those files are parsed by modpost (scripts/mod/sumversion.c), scripts/Makefile.modpost, scripts/Makefile.modsign, etc. Only the modpost utility cares about the second line while the others retrieve only the first line. Therefore we can add a third line to record the list of undefined symbols aka required EXPORT_SYMBOL() entries for each module into that file without breaking anything. Like for the second line, symbols are separated by a blank and the list is terminated with a newline character. To avoid needless build overhead, the undefined symbols extraction is performed only when CONFIG_TRIM_UNUSED_KSYMS is selected. Signed-off-by: Nicolas Pitre Acked-by: Rusty Russell --- scripts/Makefile.build | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index e1bc1907090e..74556e5e4ec0 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -286,6 +286,13 @@ define rule_as_o_S mv -f $(dot-target).tmp $(dot-target).cmd endef +# List module undefined symbols (or empty line if not enabled) +ifdef CONFIG_TRIM_UNUSED_KSYMS +cmd_undef_syms = $(NM) $@ | sed -n 's/^ \+U //p' | xargs echo +else +cmd_undef_syms = echo +endif + # Built-in and composite module parts $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE $(call cmd,force_checksrc) @@ -296,7 +303,8 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE $(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) - @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod) + @{ echo $(@:.o=.ko); echo $@; \ + $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod) quiet_cmd_cc_lst_c = MKLST $@ cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ @@ -426,7 +434,8 @@ $(call multi_depend, $(multi-used-y), .o, -objs -y) $(multi-used-m): FORCE $(call if_changed,link_multi-m) - @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod) + @{ echo $(@:.o=.ko); echo $(link_multi_deps); \ + $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod) $(call multi_depend, $(multi-used-m), .o, -objs -y -m) targets += $(multi-used-y) $(multi-used-m) -- GitLab From 0400485076e8bb167d5f4b3eb5f6d05e4b4361b7 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Tue, 29 Mar 2016 09:39:36 +0200 Subject: [PATCH 0645/9938] ASoC: tas571x: implemented digital mute The driver did not have a mute function. The amplifier was brought out of shutdown mode (hard-mute) once for ever in probe(), which was causing clicks and pops when altering the I2C register configuration later. This adds the digital_mute() function. The amplifier unmute in probe() was removed. Signed-off-by: Petr Kulhavy Signed-off-by: Mark Brown --- sound/soc/codecs/tas571x.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 39307ad41a34..d003c6ce0794 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -167,6 +167,23 @@ static int tas571x_hw_params(struct snd_pcm_substream *substream, TAS571X_SDI_FMT_MASK, val); } +static int tas571x_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + u8 sysctl2; + int ret; + + sysctl2 = mute ? TAS571X_SYS_CTRL_2_SDN_MASK : 0; + + ret = snd_soc_update_bits(codec, + TAS571X_SYS_CTRL_2_REG, + TAS571X_SYS_CTRL_2_SDN_MASK, + sysctl2); + usleep_range(1000, 2000); + + return ret; +} + static int tas571x_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -214,6 +231,7 @@ static int tas571x_set_bias_level(struct snd_soc_codec *codec, static const struct snd_soc_dai_ops tas571x_dai_ops = { .set_fmt = tas571x_set_dai_fmt, .hw_params = tas571x_hw_params, + .digital_mute = tas571x_mute, }; static const char *const tas5711_supply_names[] = { @@ -445,10 +463,6 @@ static int tas571x_i2c_probe(struct i2c_client *client, if (ret) return ret; - ret = regmap_update_bits(priv->regmap, TAS571X_SYS_CTRL_2_REG, - TAS571X_SYS_CTRL_2_SDN_MASK, 0); - if (ret) - return ret; memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); priv->codec_driver.controls = priv->chip->controls; -- GitLab From b993734718c0106418e068f21c7be01afc12306c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 4 Mar 2016 08:56:58 -0600 Subject: [PATCH 0646/9938] scripts/dtc: Update to upstream version 53bf130b1cdd Sync to upstream dtc commit 53bf130b1cdd ("libfdt: simplify fdt_node_check_compatible()"). This adds the following commits from upstream: 53bf130 libfdt: simplify fdt_node_check_compatible() c9d9121 Warn on node name unit-address presence/absence mismatch 2e53f9d Catch unsigned 32bit overflow when parsing flattened device tree offsets Signed-off-by: Rob Herring --- scripts/dtc/checks.c | 26 ++++++++++++++++++++++++++ scripts/dtc/flattree.c | 4 ++-- scripts/dtc/libfdt/fdt_ro.c | 6 ++---- scripts/dtc/version_gen.h | 2 +- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 0c03ac9159c1..386f9563313f 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -294,6 +294,30 @@ static void check_node_name_format(struct check *c, struct node *dt, } NODE_ERROR(node_name_format, NULL, &node_name_chars); +static void check_unit_address_vs_reg(struct check *c, struct node *dt, + struct node *node) +{ + const char *unitname = get_unitname(node); + struct property *prop = get_property(node, "reg"); + + if (!prop) { + prop = get_property(node, "ranges"); + if (prop && !prop->val.len) + prop = NULL; + } + + if (prop) { + if (!unitname[0]) + FAIL(c, "Node %s has a reg or ranges property, but no unit name", + node->fullpath); + } else { + if (unitname[0]) + FAIL(c, "Node %s has a unit name, but no reg property", + node->fullpath); + } +} +NODE_WARNING(unit_address_vs_reg, NULL); + static void check_property_name_chars(struct check *c, struct node *dt, struct node *node, struct property *prop) { @@ -667,6 +691,8 @@ static struct check *check_table[] = { &addr_size_cells, ®_format, &ranges_format, + &unit_address_vs_reg, + &avoid_default_addr_size, &obsolete_chosen_interrupt_controller, diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index bd99fa2d33b8..ec14954f5810 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -889,7 +889,7 @@ struct boot_info *dt_from_blob(const char *fname) if (version >= 3) { uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings); - if (off_str+size_str > totalsize) + if ((off_str+size_str < off_str) || (off_str+size_str > totalsize)) die("String table extends past total size\n"); inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); } else { @@ -898,7 +898,7 @@ struct boot_info *dt_from_blob(const char *fname) if (version >= 17) { size_dt = fdt32_to_cpu(fdt->size_dt_struct); - if (off_dt+size_dt > totalsize) + if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize)) die("Structure block extends past total size\n"); } diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index e5b313682007..50cce864283c 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -647,10 +647,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); if (!prop) return len; - if (fdt_stringlist_contains(prop, len, compatible)) - return 0; - else - return 1; + + return !fdt_stringlist_contains(prop, len, compatible); } int fdt_node_offset_by_compatible(const void *fdt, int startoffset, diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 11d93e6d8220..ad9b05ae698b 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.1-gb06e55c8" +#define DTC_VERSION "DTC 1.4.1-g53bf130b" -- GitLab From e42839b012eb8179ed2e3571bfcd133fba5df154 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Thu, 24 Mar 2016 10:53:14 +0800 Subject: [PATCH 0647/9938] ASoC: topology: ABI - Define types for vendor tuples Tuples, a pair of token and value, can be used to define vendor specific data, for controls and widgets. This can avoid importing binary data blob from other files. Vendor specific tuple arrays will be embeded in the private data buffer of a control or widget object. To be backward compatible, union is used to define the tuple arrays in the existing private data ABI object 'struct snd_soc_tplg_private'. Vendors need to make sure the token values defined by the topology conf file match those defined by their driver. Now supported tuple types are uuid, string, bool, byte, short and word. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- include/uapi/sound/asoc.h | 42 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index c4cc1e40b35c..db86b447b515 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -116,6 +116,14 @@ #define SND_SOC_TPLG_STREAM_PLAYBACK 0 #define SND_SOC_TPLG_STREAM_CAPTURE 1 +/* vendor tuple types */ +#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0 +#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1 +#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2 +#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3 +#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 +#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 + /* * Block Header. * This header precedes all object and object arrays below. @@ -132,6 +140,35 @@ struct snd_soc_tplg_hdr { __le32 count; /* number of elements in block */ } __attribute__((packed)); +/* vendor tuple for uuid */ +struct snd_soc_tplg_vendor_uuid_elem { + __le32 token; + char uuid[16]; +} __attribute__((packed)); + +/* vendor tuple for a bool/byte/short/word value */ +struct snd_soc_tplg_vendor_value_elem { + __le32 token; + __le32 value; +} __attribute__((packed)); + +/* vendor tuple for string */ +struct snd_soc_tplg_vendor_string_elem { + __le32 token; + char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +} __attribute__((packed)); + +struct snd_soc_tplg_vendor_array { + __le32 size; /* size in bytes of the array, including all elements */ + __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */ + __le32 num_elems; /* number of elements in array */ + union { + struct snd_soc_tplg_vendor_uuid_elem uuid[0]; + struct snd_soc_tplg_vendor_value_elem value[0]; + struct snd_soc_tplg_vendor_string_elem string[0]; + }; +} __attribute__((packed)); + /* * Private data. * All topology objects may have private data that can be used by the driver or @@ -139,7 +176,10 @@ struct snd_soc_tplg_hdr { */ struct snd_soc_tplg_private { __le32 size; /* in bytes of private data */ - char data[0]; + union { + char data[0]; + struct snd_soc_tplg_vendor_array array[0]; + }; } __attribute__((packed)); /* -- GitLab From 997e518821ea0565bb92c5feba43c24c46be933d Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:45 -0400 Subject: [PATCH 0648/9938] staging: lustre: libcfs: limit scope of libcfs_crypto.h Remove from and only include it into the places where it is actually needed. This works out to be the same places as , so put it there. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 1 - drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c | 1 + drivers/staging/lustre/lustre/include/obd_cksum.h | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 6a8e0d0d61bf..d2e43617b0a1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -96,7 +96,6 @@ void cfs_get_random_bytes(void *buf, int size); #include "libcfs_workitem.h" #include "libcfs_hash.h" #include "libcfs_fail.h" -#include "libcfs_crypto.h" struct libcfs_ioctl_handler { struct list_head item; diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 8c9377ed850c..d4cb260dbcf7 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -30,6 +30,7 @@ #include #include #include "../../../include/linux/libcfs/libcfs.h" +#include "../../../include/linux/libcfs/libcfs_crypto.h" #include "linux-crypto.h" /** * Array of hash algorithm speed in MByte per second diff --git a/drivers/staging/lustre/lustre/include/obd_cksum.h b/drivers/staging/lustre/lustre/include/obd_cksum.h index 637fa22110a4..f6c18df906a8 100644 --- a/drivers/staging/lustre/lustre/include/obd_cksum.h +++ b/drivers/staging/lustre/lustre/include/obd_cksum.h @@ -35,6 +35,7 @@ #ifndef __OBD_CKSUM #define __OBD_CKSUM #include "../../include/linux/libcfs/libcfs.h" +#include "../../include/linux/libcfs/libcfs_crypto.h" #include "lustre/lustre_idl.h" static inline unsigned char cksum_obd2cfs(enum cksum_type cksum_type) -- GitLab From 020b02154d79e1e01f846da7a6beab59fd7c7840 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:46 -0400 Subject: [PATCH 0649/9938] staging: lustre: libcfs: add documentation for cfs_crypto_hash_*() Add comment blocks for cfs_crypto_hash_*() in linux-crypto.c and libcfs_crypto.h. Delete obsolete comment about shash handling in cfs_crypto_hash_alloc(). Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_crypto.h | 101 ++++-------- .../lustre/lnet/libcfs/linux/linux-crypto.c | 153 ++++++++++++++++-- 2 files changed, 174 insertions(+), 80 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h index e8663697e7a6..518241669ac8 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h @@ -61,7 +61,14 @@ static struct cfs_crypto_hash_type hash_types[] = { [CFS_HASH_ALG_SHA512] = { "sha512", 0, 64 }, }; -/** Return pointer to type of hash for valid hash algorithm identifier */ +/** + * Return hash algorithm information for the specified algorithm identifier + * + * Hash information includes algorithm name, initial seed, hash size. + * + * \retval cfs_crypto_hash_type for valid ID (CFS_HASH_ALG_*) + * \retval NULL for unknown algorithm identifier + */ static inline const struct cfs_crypto_hash_type * cfs_crypto_hash_type(unsigned char hash_alg) { @@ -75,7 +82,14 @@ static inline const struct cfs_crypto_hash_type * return NULL; } -/** Return hash name for valid hash algorithm identifier or "unknown" */ +/** + * Return hash name for hash algorithm identifier + * + * \param[in] hash_alg hash alrgorithm id (CFS_HASH_ALG_*) + * + * \retval string name of known hash algorithm + * \retval "unknown" if hash algorithm is unknown + */ static inline const char *cfs_crypto_hash_name(unsigned char hash_alg) { const struct cfs_crypto_hash_type *ht; @@ -86,7 +100,14 @@ static inline const char *cfs_crypto_hash_name(unsigned char hash_alg) return "unknown"; } -/** Return digest size for valid algorithm identifier or 0 */ +/** + * Return digest size for hash algorithm type + * + * \param[in] hash_alg hash alrgorithm id (CFS_HASH_ALG_*) + * + * \retval hash algorithm digest size in bytes + * \retval 0 if hash algorithm type is unknown + */ static inline int cfs_crypto_hash_digestsize(unsigned char hash_alg) { const struct cfs_crypto_hash_type *ht; @@ -97,7 +118,12 @@ static inline int cfs_crypto_hash_digestsize(unsigned char hash_alg) return 0; } -/** Return hash identifier for valid hash algorithm name or 0xFF */ +/** + * Find hash algorithm ID for the specified algorithm name + * + * \retval hash algorithm ID for valid ID (CFS_HASH_ALG_*) + * \retval CFS_HASH_ALG_UNKNOWN for unknown algorithm name + */ static inline unsigned char cfs_crypto_hash_alg(const char *algname) { unsigned char i; @@ -108,24 +134,6 @@ static inline unsigned char cfs_crypto_hash_alg(const char *algname) return (i == CFS_HASH_ALG_MAX ? 0xFF : i); } -/** Calculate hash digest for buffer. - * @param alg id of hash algorithm - * @param buf buffer of data - * @param buf_len buffer len - * @param key initial value for algorithm, if it is NULL, - * default initial value should be used. - * @param key_len len of initial value - * @param hash [out] pointer to hash, if it is NULL, hash_len is - * set to valid digest size in bytes, retval -ENOSPC. - * @param hash_len [in,out] size of hash buffer - * @returns status of operation - * @retval -EINVAL if buf, buf_len, hash_len or alg_id is invalid - * @retval -ENODEV if this algorithm is unsupported - * @retval -ENOSPC if pointer to hash is NULL, or hash_len less than - * digest size - * @retval 0 for success - * @retval < 0 other errors from lower layers. - */ int cfs_crypto_hash_digest(unsigned char alg, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, @@ -134,66 +142,17 @@ int cfs_crypto_hash_digest(unsigned char alg, /* cfs crypto hash descriptor */ struct cfs_crypto_hash_desc; -/** Allocate and initialize descriptor for hash algorithm. - * @param alg algorithm id - * @param key initial value for algorithm, if it is NULL, - * default initial value should be used. - * @param key_len len of initial value - * @returns pointer to descriptor of hash instance - * @retval ERR_PTR(error) when errors occurred. - */ struct cfs_crypto_hash_desc* cfs_crypto_hash_init(unsigned char alg, unsigned char *key, unsigned int key_len); - -/** Update digest by part of data. - * @param desc hash descriptor - * @param page data page - * @param offset data offset - * @param len data len - * @returns status of operation - * @retval 0 for success. - */ int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *desc, struct page *page, unsigned int offset, unsigned int len); - -/** Update digest by part of data. - * @param desc hash descriptor - * @param buf pointer to data buffer - * @param buf_len size of data at buffer - * @returns status of operation - * @retval 0 for success. - */ int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *desc, const void *buf, unsigned int buf_len); - -/** Finalize hash calculation, copy hash digest to buffer, destroy hash - * descriptor. - * @param desc hash descriptor - * @param hash buffer pointer to store hash digest - * @param hash_len pointer to hash buffer size, if NULL - * destroy hash descriptor - * @returns status of operation - * @retval -ENOSPC if hash is NULL, or *hash_len less than - * digest size - * @retval 0 for success - * @retval < 0 other errors from lower layers. - */ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *desc, unsigned char *hash, unsigned int *hash_len); -/** - * Register crypto hash algorithms - */ int cfs_crypto_register(void); - -/** - * Unregister - */ void cfs_crypto_unregister(void); - -/** Return hash speed in Mbytes per second for valid hash algorithm - * identifier. If test was unsuccessful -1 would be returned. - */ int cfs_crypto_hash_speed(unsigned char hash_alg); #endif diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index d4cb260dbcf7..8960c3aca10b 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -32,11 +32,31 @@ #include "../../../include/linux/libcfs/libcfs.h" #include "../../../include/linux/libcfs/libcfs_crypto.h" #include "linux-crypto.h" + /** - * Array of hash algorithm speed in MByte per second + * Array of hash algorithm speed in MByte per second */ static int cfs_crypto_hash_speeds[CFS_HASH_ALG_MAX]; +/** + * Initialize the state descriptor for the specified hash algorithm. + * + * An internal routine to allocate the hash-specific state in \a hdesc for + * use with cfs_crypto_hash_digest() to compute the hash of a single message, + * though possibly in multiple chunks. The descriptor internal state should + * be freed with cfs_crypto_hash_final(). + * + * \param[in] hash_alg hash algorithm id (CFS_HASH_ALG_*) + * \param[out] type pointer to the hash description in hash_types[] + * array + * \param[in,out] hdesc hash state descriptor to be initialized + * \param[in] key initial hash value/state, NULL to use default + * value + * \param[in] key_len length of \a key + * + * \retval 0 on success + * \retval negative errno on failure + */ static int cfs_crypto_hash_alloc(unsigned char alg_id, const struct cfs_crypto_hash_type **type, struct ahash_request **req, @@ -71,12 +91,6 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, ahash_request_set_callback(*req, 0, NULL, NULL); - /** Shash have different logic for initialization then digest - * shash: crypto_hash_setkey, crypto_hash_init - * digest: crypto_digest_init, crypto_digest_setkey - * Skip this function for digest, because we use shash logic at - * cfs_crypto_hash_alloc. - */ if (key) err = crypto_ahash_setkey(tfm, key, key_len); else if ((*type)->cht_key != 0) @@ -101,6 +115,32 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, return err; } +/** + * Calculate hash digest for the passed buffer. + * + * This should be used when computing the hash on a single contiguous buffer. + * It combines the hash initialization, computation, and cleanup. + * + * \param[in] hash_alg id of hash algorithm (CFS_HASH_ALG_*) + * \param[in] buf data buffer on which to compute hash + * \param[in] buf_len length of \a buf in bytes + * \param[in] key initial value/state for algorithm, + * if \a key = NULL use default initial value + * \param[in] key_len length of \a key in bytes + * \param[out] hash pointer to computed hash value, + * if \a hash = NULL then \a hash_len is to digest + * size in bytes, retval -ENOSPC + * \param[in,out] hash_len size of \a hash buffer + * + * \retval -EINVAL \a buf, \a buf_len, \a hash_len, + * \a alg_id invalid + * \retval -ENOENT \a hash_alg is unsupported + * \retval -ENOSPC \a hash is NULL, or \a hash_len less than + * digest size + * \retval 0 for success + * \retval negative errno for other errors from lower + * layers. + */ int cfs_crypto_hash_digest(unsigned char alg_id, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, @@ -135,6 +175,23 @@ int cfs_crypto_hash_digest(unsigned char alg_id, } EXPORT_SYMBOL(cfs_crypto_hash_digest); +/** + * Allocate and initialize desriptor for hash algorithm. + * + * This should be used to initialize a hash descriptor for multiple calls + * to a single hash function when computing the hash across multiple + * separate buffers or pages using cfs_crypto_hash_update{,_page}(). + * + * The hash descriptor should be freed with cfs_crypto_hash_final(). + * + * \param[in] hash_alg algorithm id (CFS_HASH_ALG_*) + * \param[in] key initial value/state for algorithm, if \a key = NULL + * use default initial value + * \param[in] key_len length of \a key in bytes + * + * \retval pointer to descriptor of hash instance + * \retval ERR_PTR(errno) in case of error + */ struct cfs_crypto_hash_desc * cfs_crypto_hash_init(unsigned char alg_id, unsigned char *key, unsigned int key_len) @@ -151,6 +208,17 @@ struct cfs_crypto_hash_desc * } EXPORT_SYMBOL(cfs_crypto_hash_init); +/** + * Update hash digest computed on data within the given \a page + * + * \param[in] hdesc hash state descriptor + * \param[in] page data page on which to compute the hash + * \param[in] offset offset within \a page at which to start hash + * \param[in] len length of data on which to compute hash + * + * \retval 0 for success + * \retval negative errno on failure + */ int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *hdesc, struct page *page, unsigned int offset, unsigned int len) @@ -166,6 +234,16 @@ int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *hdesc, } EXPORT_SYMBOL(cfs_crypto_hash_update_page); +/** + * Update hash digest computed on the specified data + * + * \param[in] hdesc hash state descriptor + * \param[in] buf data buffer on which to compute the hash + * \param[in] buf_len length of \buf on which to compute hash + * + * \retval 0 for success + * \retval negative errno on failure + */ int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *hdesc, const void *buf, unsigned int buf_len) { @@ -179,7 +257,18 @@ int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *hdesc, } EXPORT_SYMBOL(cfs_crypto_hash_update); -/* If hash_len pointer is NULL - destroy descriptor. */ +/** + * Finish hash calculation, copy hash digest to buffer, clean up hash descriptor + * + * \param[in] hdesc hash descriptor + * \param[out] hash pointer to hash buffer to store hash digest + * \param[in,out] hash_len pointer to hash buffer size, if \a hdesc = NULL + * only free \a hdesc instead of computing the hash + * + * \retval -ENOSPC if \a hash = NULL, or \a hash_len < digest size + * \retval 0 for success + * \retval negative errno for other errors from lower layers + */ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, unsigned char *hash, unsigned int *hash_len) { @@ -209,6 +298,17 @@ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, } EXPORT_SYMBOL(cfs_crypto_hash_final); +/** + * Compute the speed of specified hash function + * + * Run a speed test on the given hash algorithm on buffer of the given size. + * The speed is stored internally in the cfs_crypto_hash_speeds[] array, and + * is available through the cfs_crypto_hash_speed() function. + * + * \param[in] hash_alg hash algorithm id (CFS_HASH_ALG_*) + * \param[in] buf data buffer on which to compute the hash + * \param[in] buf_len length of \buf on which to compute hash + */ static void cfs_crypto_performance_test(unsigned char alg_id, const unsigned char *buf, unsigned int buf_len) @@ -243,6 +343,18 @@ static void cfs_crypto_performance_test(unsigned char alg_id, cfs_crypto_hash_name(alg_id), cfs_crypto_hash_speeds[alg_id]); } +/** + * hash speed in Mbytes per second for valid hash algorithm + * + * Return the performance of the specified \a hash_alg that was previously + * computed using cfs_crypto_performance_test(). + * + * \param[in] hash_alg hash algorithm id (CFS_HASH_ALG_*) + * + * \retval positive speed of the hash function in MB/s + * \retval -ENOENT if \a hash_alg is unsupported + * \retval negative errno if \a hash_alg speed is unavailable + */ int cfs_crypto_hash_speed(unsigned char hash_alg) { if (hash_alg < CFS_HASH_ALG_MAX) @@ -252,7 +364,22 @@ int cfs_crypto_hash_speed(unsigned char hash_alg) EXPORT_SYMBOL(cfs_crypto_hash_speed); /** - * Do performance test for all hash algorithms. + * Run the performance test for all hash algorithms. + * + * Run the cfs_crypto_performance_test() benchmark for all of the available + * hash functions using a 1MB buffer size. This is a reasonable buffer size + * for Lustre RPCs, even if the actual RPC size is larger or smaller. + * + * Since the setup cost and computation speed of various hash algorithms is + * a function of the buffer size (and possibly internal contention of offload + * engines), this speed only represents an estimate of the actual speed under + * actual usage, but is reasonable for comparing available algorithms. + * + * The actual speeds are available via cfs_crypto_hash_speed() for later + * comparison. + * + * \retval 0 on success + * \retval -ENOMEM if no memory is available for test buffer */ static int cfs_crypto_test_hashes(void) { @@ -280,6 +407,11 @@ static int cfs_crypto_test_hashes(void) static int adler32; +/** + * Register available hash functions + * + * \retval 0 + */ int cfs_crypto_register(void) { request_module("crc32c"); @@ -291,6 +423,9 @@ int cfs_crypto_register(void) return 0; } +/** + * Unregister previously registered hash functions + */ void cfs_crypto_unregister(void) { if (adler32 == 0) -- GitLab From 4d60ffa12c887e1944d5582d79cc9d7f3593eb00 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:47 -0400 Subject: [PATCH 0650/9938] staging: lustre: libcfs: rename some variables for crypto handling For the crypto algorthim type use the same name hash_alg everywhere. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_crypto.h | 4 +-- .../lustre/lnet/libcfs/linux/linux-crypto.c | 30 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h index 518241669ac8..0782bfb11ffa 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h @@ -134,7 +134,7 @@ static inline unsigned char cfs_crypto_hash_alg(const char *algname) return (i == CFS_HASH_ALG_MAX ? 0xFF : i); } -int cfs_crypto_hash_digest(unsigned char alg, +int cfs_crypto_hash_digest(unsigned char hash_alg, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, unsigned char *hash, unsigned int *hash_len); @@ -143,7 +143,7 @@ int cfs_crypto_hash_digest(unsigned char alg, struct cfs_crypto_hash_desc; struct cfs_crypto_hash_desc* - cfs_crypto_hash_init(unsigned char alg, + cfs_crypto_hash_init(unsigned char hash_alg, unsigned char *key, unsigned int key_len); int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *desc, struct page *page, unsigned int offset, diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 8960c3aca10b..1a9eb77ec986 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -57,7 +57,7 @@ static int cfs_crypto_hash_speeds[CFS_HASH_ALG_MAX]; * \retval 0 on success * \retval negative errno on failure */ -static int cfs_crypto_hash_alloc(unsigned char alg_id, +static int cfs_crypto_hash_alloc(unsigned char hash_alg, const struct cfs_crypto_hash_type **type, struct ahash_request **req, unsigned char *key, @@ -66,11 +66,11 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, struct crypto_ahash *tfm; int err = 0; - *type = cfs_crypto_hash_type(alg_id); + *type = cfs_crypto_hash_type(hash_alg); if (!*type) { CWARN("Unsupported hash algorithm id = %d, max id is %d\n", - alg_id, CFS_HASH_ALG_MAX); + hash_alg, CFS_HASH_ALG_MAX); return -EINVAL; } tfm = crypto_alloc_ahash((*type)->cht_name, 0, CRYPTO_ALG_ASYNC); @@ -105,7 +105,7 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, CDEBUG(D_INFO, "Using crypto hash: %s (%s) speed %d MB/s\n", crypto_ahash_alg_name(tfm), crypto_ahash_driver_name(tfm), - cfs_crypto_hash_speeds[alg_id]); + cfs_crypto_hash_speeds[hash_alg]); err = crypto_ahash_init(*req); if (err) { @@ -133,7 +133,7 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, * \param[in,out] hash_len size of \a hash buffer * * \retval -EINVAL \a buf, \a buf_len, \a hash_len, - * \a alg_id invalid + * \a hash_alg invalid * \retval -ENOENT \a hash_alg is unsupported * \retval -ENOSPC \a hash is NULL, or \a hash_len less than * digest size @@ -141,7 +141,7 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, * \retval negative errno for other errors from lower * layers. */ -int cfs_crypto_hash_digest(unsigned char alg_id, +int cfs_crypto_hash_digest(unsigned char hash_alg, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, unsigned char *hash, unsigned int *hash_len) @@ -154,7 +154,7 @@ int cfs_crypto_hash_digest(unsigned char alg_id, if (!buf || buf_len == 0 || !hash_len) return -EINVAL; - err = cfs_crypto_hash_alloc(alg_id, &type, &req, key, key_len); + err = cfs_crypto_hash_alloc(hash_alg, &type, &req, key, key_len); if (err != 0) return err; @@ -193,14 +193,14 @@ EXPORT_SYMBOL(cfs_crypto_hash_digest); * \retval ERR_PTR(errno) in case of error */ struct cfs_crypto_hash_desc * - cfs_crypto_hash_init(unsigned char alg_id, + cfs_crypto_hash_init(unsigned char hash_alg, unsigned char *key, unsigned int key_len) { struct ahash_request *req; int err; const struct cfs_crypto_hash_type *type; - err = cfs_crypto_hash_alloc(alg_id, &type, &req, key, key_len); + err = cfs_crypto_hash_alloc(hash_alg, &type, &req, key, key_len); if (err) return ERR_PTR(err); @@ -309,7 +309,7 @@ EXPORT_SYMBOL(cfs_crypto_hash_final); * \param[in] buf data buffer on which to compute the hash * \param[in] buf_len length of \buf on which to compute hash */ -static void cfs_crypto_performance_test(unsigned char alg_id, +static void cfs_crypto_performance_test(unsigned char hash_alg, const unsigned char *buf, unsigned int buf_len) { @@ -321,7 +321,7 @@ static void cfs_crypto_performance_test(unsigned char alg_id, for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { - err = cfs_crypto_hash_digest(alg_id, buf, buf_len, NULL, 0, + err = cfs_crypto_hash_digest(hash_alg, buf, buf_len, NULL, 0, hash, &hash_len); if (err) break; @@ -329,18 +329,18 @@ static void cfs_crypto_performance_test(unsigned char alg_id, end = jiffies; if (err) { - cfs_crypto_hash_speeds[alg_id] = -1; + cfs_crypto_hash_speeds[hash_alg] = -1; CDEBUG(D_INFO, "Crypto hash algorithm %s, err = %d\n", - cfs_crypto_hash_name(alg_id), err); + cfs_crypto_hash_name(hash_alg), err); } else { unsigned long tmp; tmp = ((bcount * buf_len / jiffies_to_msecs(end - start)) * 1000) / (1024 * 1024); - cfs_crypto_hash_speeds[alg_id] = (int)tmp; + cfs_crypto_hash_speeds[hash_alg] = (int)tmp; } CDEBUG(D_INFO, "Crypto hash algorithm %s speed = %d MB/s\n", - cfs_crypto_hash_name(alg_id), cfs_crypto_hash_speeds[alg_id]); + cfs_crypto_hash_name(hash_alg), cfs_crypto_hash_speeds[hash_alg]); } /** -- GitLab From 24a4e1ec63ffcd87f656f507709b5f03f6a5f155 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:48 -0400 Subject: [PATCH 0651/9938] staging: lustre: libcfs: add new definitions for cfs_crypto api Add CFS_HASH_ALG_UNKOWN for unknown hash names instead of using "0xFF" directly. Define the max digestsize the cfs crypto api can handle. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs_crypto.h | 9 +++++++-- drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h index 0782bfb11ffa..921aa7cbff97 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h @@ -46,7 +46,8 @@ enum cfs_crypto_hash_alg { CFS_HASH_ALG_SHA384, CFS_HASH_ALG_SHA512, CFS_HASH_ALG_CRC32C, - CFS_HASH_ALG_MAX + CFS_HASH_ALG_MAX, + CFS_HASH_ALG_UNKNOWN = 0xff }; static struct cfs_crypto_hash_type hash_types[] = { @@ -59,8 +60,12 @@ static struct cfs_crypto_hash_type hash_types[] = { [CFS_HASH_ALG_SHA256] = { "sha256", 0, 32 }, [CFS_HASH_ALG_SHA384] = { "sha384", 0, 48 }, [CFS_HASH_ALG_SHA512] = { "sha512", 0, 64 }, + [CFS_HASH_ALG_MAX] = { NULL, 0, 64 }, }; +/* Maximum size of hash_types[].cht_size */ +#define CFS_CRYPTO_HASH_DIGESTSIZE_MAX 64 + /** * Return hash algorithm information for the specified algorithm identifier * @@ -131,7 +136,7 @@ static inline unsigned char cfs_crypto_hash_alg(const char *algname) for (i = 0; i < CFS_HASH_ALG_MAX; i++) if (!strcmp(hash_types[i].cht_name, algname)) break; - return (i == CFS_HASH_ALG_MAX ? 0xFF : i); + return (i == CFS_HASH_ALG_MAX ? CFS_HASH_ALG_UNKNOWN : i); } int cfs_crypto_hash_digest(unsigned char hash_alg, diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 1a9eb77ec986..b4e203dacd38 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -316,8 +316,8 @@ static void cfs_crypto_performance_test(unsigned char hash_alg, unsigned long start, end; int bcount, err = 0; int sec = 1; /* do test only 1 sec */ - unsigned char hash[64]; - unsigned int hash_len = 64; + unsigned char hash[CFS_CRYPTO_HASH_DIGESTSIZE_MAX]; + unsigned int hash_len = sizeof(hash); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { -- GitLab From 56ebc2e875f1103b941163008ece8612c9e97ba4 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:49 -0400 Subject: [PATCH 0652/9938] staging: lustre: libcfs: small alignment change for cfs_crypto_hash_*() Change the aligment of some of the functions. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_crypto.h | 11 ++++++----- .../staging/lustre/lnet/libcfs/linux/linux-crypto.c | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h index 921aa7cbff97..ade88944988d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h @@ -75,7 +75,7 @@ static struct cfs_crypto_hash_type hash_types[] = { * \retval NULL for unknown algorithm identifier */ static inline const struct cfs_crypto_hash_type * - cfs_crypto_hash_type(unsigned char hash_alg) +cfs_crypto_hash_type(unsigned char hash_alg) { struct cfs_crypto_hash_type *ht; @@ -95,7 +95,8 @@ static inline const struct cfs_crypto_hash_type * * \retval string name of known hash algorithm * \retval "unknown" if hash algorithm is unknown */ -static inline const char *cfs_crypto_hash_name(unsigned char hash_alg) +static inline const char * +cfs_crypto_hash_name(unsigned char hash_alg) { const struct cfs_crypto_hash_type *ht; @@ -147,9 +148,9 @@ int cfs_crypto_hash_digest(unsigned char hash_alg, /* cfs crypto hash descriptor */ struct cfs_crypto_hash_desc; -struct cfs_crypto_hash_desc* - cfs_crypto_hash_init(unsigned char hash_alg, - unsigned char *key, unsigned int key_len); +struct cfs_crypto_hash_desc * +cfs_crypto_hash_init(unsigned char hash_alg, + unsigned char *key, unsigned int key_len); int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *desc, struct page *page, unsigned int offset, unsigned int len); diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index b4e203dacd38..024172929b62 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -193,8 +193,8 @@ EXPORT_SYMBOL(cfs_crypto_hash_digest); * \retval ERR_PTR(errno) in case of error */ struct cfs_crypto_hash_desc * - cfs_crypto_hash_init(unsigned char hash_alg, - unsigned char *key, unsigned int key_len) +cfs_crypto_hash_init(unsigned char hash_alg, + unsigned char *key, unsigned int key_len) { struct ahash_request *req; int err; -- GitLab From 244cd87cc078fd18a8cbbb4db2998b95760007f6 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:50 -0400 Subject: [PATCH 0653/9938] staging: lustre: libcfs: start using enum cfs_crypto_hash_alg Fix the cfs_crypto_hash_* functions to take enum cfs_crypto_hash_alg as the algorithm type, instead of an unsigned char. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_crypto.h | 23 ++++++++++--------- .../lustre/lnet/libcfs/linux/linux-crypto.c | 10 ++++---- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h index ade88944988d..02be7d7608a5 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h @@ -75,7 +75,7 @@ static struct cfs_crypto_hash_type hash_types[] = { * \retval NULL for unknown algorithm identifier */ static inline const struct cfs_crypto_hash_type * -cfs_crypto_hash_type(unsigned char hash_alg) +cfs_crypto_hash_type(enum cfs_crypto_hash_alg hash_alg) { struct cfs_crypto_hash_type *ht; @@ -96,7 +96,7 @@ cfs_crypto_hash_type(unsigned char hash_alg) * \retval "unknown" if hash algorithm is unknown */ static inline const char * -cfs_crypto_hash_name(unsigned char hash_alg) +cfs_crypto_hash_name(enum cfs_crypto_hash_alg hash_alg) { const struct cfs_crypto_hash_type *ht; @@ -114,7 +114,7 @@ cfs_crypto_hash_name(unsigned char hash_alg) * \retval hash algorithm digest size in bytes * \retval 0 if hash algorithm type is unknown */ -static inline int cfs_crypto_hash_digestsize(unsigned char hash_alg) +static inline int cfs_crypto_hash_digestsize(enum cfs_crypto_hash_alg hash_alg) { const struct cfs_crypto_hash_type *ht; @@ -132,15 +132,16 @@ static inline int cfs_crypto_hash_digestsize(unsigned char hash_alg) */ static inline unsigned char cfs_crypto_hash_alg(const char *algname) { - unsigned char i; + enum cfs_crypto_hash_alg hash_alg; - for (i = 0; i < CFS_HASH_ALG_MAX; i++) - if (!strcmp(hash_types[i].cht_name, algname)) - break; - return (i == CFS_HASH_ALG_MAX ? CFS_HASH_ALG_UNKNOWN : i); + for (hash_alg = 0; hash_alg < CFS_HASH_ALG_MAX; hash_alg++) + if (strcmp(hash_types[hash_alg].cht_name, algname) == 0) + return hash_alg; + + return CFS_HASH_ALG_UNKNOWN; } -int cfs_crypto_hash_digest(unsigned char hash_alg, +int cfs_crypto_hash_digest(enum cfs_crypto_hash_alg hash_alg, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, unsigned char *hash, unsigned int *hash_len); @@ -149,7 +150,7 @@ int cfs_crypto_hash_digest(unsigned char hash_alg, struct cfs_crypto_hash_desc; struct cfs_crypto_hash_desc * -cfs_crypto_hash_init(unsigned char hash_alg, +cfs_crypto_hash_init(enum cfs_crypto_hash_alg hash_alg, unsigned char *key, unsigned int key_len); int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *desc, struct page *page, unsigned int offset, @@ -160,5 +161,5 @@ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *desc, unsigned char *hash, unsigned int *hash_len); int cfs_crypto_register(void); void cfs_crypto_unregister(void); -int cfs_crypto_hash_speed(unsigned char hash_alg); +int cfs_crypto_hash_speed(enum cfs_crypto_hash_alg hash_alg); #endif diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 024172929b62..6fe1fdde001e 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -57,7 +57,7 @@ static int cfs_crypto_hash_speeds[CFS_HASH_ALG_MAX]; * \retval 0 on success * \retval negative errno on failure */ -static int cfs_crypto_hash_alloc(unsigned char hash_alg, +static int cfs_crypto_hash_alloc(enum cfs_crypto_hash_alg hash_alg, const struct cfs_crypto_hash_type **type, struct ahash_request **req, unsigned char *key, @@ -141,7 +141,7 @@ static int cfs_crypto_hash_alloc(unsigned char hash_alg, * \retval negative errno for other errors from lower * layers. */ -int cfs_crypto_hash_digest(unsigned char hash_alg, +int cfs_crypto_hash_digest(enum cfs_crypto_hash_alg hash_alg, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, unsigned char *hash, unsigned int *hash_len) @@ -193,7 +193,7 @@ EXPORT_SYMBOL(cfs_crypto_hash_digest); * \retval ERR_PTR(errno) in case of error */ struct cfs_crypto_hash_desc * -cfs_crypto_hash_init(unsigned char hash_alg, +cfs_crypto_hash_init(enum cfs_crypto_hash_alg hash_alg, unsigned char *key, unsigned int key_len) { struct ahash_request *req; @@ -309,7 +309,7 @@ EXPORT_SYMBOL(cfs_crypto_hash_final); * \param[in] buf data buffer on which to compute the hash * \param[in] buf_len length of \buf on which to compute hash */ -static void cfs_crypto_performance_test(unsigned char hash_alg, +static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg, const unsigned char *buf, unsigned int buf_len) { @@ -355,7 +355,7 @@ static void cfs_crypto_performance_test(unsigned char hash_alg, * \retval -ENOENT if \a hash_alg is unsupported * \retval negative errno if \a hash_alg speed is unavailable */ -int cfs_crypto_hash_speed(unsigned char hash_alg) +int cfs_crypto_hash_speed(enum cfs_crypto_hash_alg hash_alg) { if (hash_alg < CFS_HASH_ALG_MAX) return cfs_crypto_hash_speeds[hash_alg]; -- GitLab From c11e27a4ee39479b9afef86bfed8ef3f75756262 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:51 -0400 Subject: [PATCH 0654/9938] staging: lustre: libcfs: bug fixes for cfs_crypto_hash_final() Change cfs_crypto_hash_final() to always clean up the hash descrptor instead of not doing this in error cases. All of the callers were just calling cfs_crypto_hash_final() immediately to clean up the descriptor anyway, and the old behaviour is unlike other init/fini functions, and prone to memory leaks and other incorrect usage. The callers can call cfs_crypto_digest_size() to determine the hash size in advance if needed, and avoid complexity in cfs_crypto_hash_final(). Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lnet/libcfs/linux/linux-crypto.c | 24 +++++++++---------- .../staging/lustre/lustre/osc/osc_request.c | 5 +--- .../staging/lustre/lustre/ptlrpc/sec_bulk.c | 12 +++++----- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 6fe1fdde001e..d5bb10fec511 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -265,8 +265,8 @@ EXPORT_SYMBOL(cfs_crypto_hash_update); * \param[in,out] hash_len pointer to hash buffer size, if \a hdesc = NULL * only free \a hdesc instead of computing the hash * - * \retval -ENOSPC if \a hash = NULL, or \a hash_len < digest size * \retval 0 for success + * \retval -EOVERFLOW if hash_len is too small for the hash digest * \retval negative errno for other errors from lower layers */ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, @@ -276,22 +276,20 @@ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, struct ahash_request *req = (void *)hdesc; int size = crypto_ahash_digestsize(crypto_ahash_reqtfm(req)); - if (!hash_len) { - crypto_free_ahash(crypto_ahash_reqtfm(req)); - ahash_request_free(req); - return 0; + if (!hash || !hash_len) { + err = 0; + goto free_ahash; } - if (!hash || *hash_len < size) { - *hash_len = size; - return -ENOSPC; + if (*hash_len < size) { + err = -EOVERFLOW; + goto free_ahash; } + ahash_request_set_crypt(req, NULL, hash, 0); err = crypto_ahash_final(req); - - if (err < 0) { - /* May be caller can fix error */ - return err; - } + if (!err) + *hash_len = size; +free_ahash: crypto_free_ahash(crypto_ahash_reqtfm(req)); ahash_request_free(req); return err; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 74805f1ae888..ec0287feb3ce 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1208,12 +1208,9 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, i++; } - bufsize = 4; + bufsize = sizeof(cksum); err = cfs_crypto_hash_final(hdesc, (unsigned char *)&cksum, &bufsize); - if (err) - cfs_crypto_hash_final(hdesc, NULL, NULL); - /* For sending we only compute the wrong checksum instead * of corrupting the data so it is still correct on a redo */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 72d5b9bf5b29..54a0c1ff7b20 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -41,7 +41,6 @@ #define DEBUG_SUBSYSTEM S_SEC #include "../../include/linux/libcfs/libcfs.h" -#include #include "../include/obd.h" #include "../include/obd_cksum.h" @@ -511,7 +510,6 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, { struct cfs_crypto_hash_desc *hdesc; int hashsize; - char hashbuf[64]; unsigned int bufsize; int i, err; @@ -532,18 +530,20 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, desc->bd_iov[i].kiov_offset & ~CFS_PAGE_MASK, desc->bd_iov[i].kiov_len); } + if (hashsize > buflen) { + unsigned char hashbuf[CFS_CRYPTO_HASH_DIGESTSIZE_MAX]; + bufsize = sizeof(hashbuf); - err = cfs_crypto_hash_final(hdesc, (unsigned char *)hashbuf, - &bufsize); + LASSERTF(bufsize >= hashsize, "bufsize = %u < hashsize %u\n", + bufsize, hashsize); + err = cfs_crypto_hash_final(hdesc, hashbuf, &bufsize); memcpy(buf, hashbuf, buflen); } else { bufsize = buflen; err = cfs_crypto_hash_final(hdesc, buf, &bufsize); } - if (err) - cfs_crypto_hash_final(hdesc, NULL, NULL); return err; } EXPORT_SYMBOL(sptlrpc_get_bulk_checksum); -- GitLab From e43c658c5a97570f4c5be8e94eb2ad30d4033123 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:52 -0400 Subject: [PATCH 0655/9938] staging: lustre: libcfs: return proper error code for cfs_crypto_hash_speed() Return a real error code, -ENOENT, instead of a -1. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index d5bb10fec511..90d6e082aead 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -357,7 +357,7 @@ int cfs_crypto_hash_speed(enum cfs_crypto_hash_alg hash_alg) { if (hash_alg < CFS_HASH_ALG_MAX) return cfs_crypto_hash_speeds[hash_alg]; - return -1; + return -ENOENT; } EXPORT_SYMBOL(cfs_crypto_hash_speed); -- GitLab From 6ba3f37825982cf71e55ef87aadbffe8f4345a05 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:53 -0400 Subject: [PATCH 0656/9938] staging: lustre: libcfs: allocate memory in cfs_crypto_performance_test() Move memory allocation from cfs_crypto_test_hashes() into the function cfs_crypto_performance_test(). Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lnet/libcfs/linux/linux-crypto.c | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 90d6e082aead..4857a11c0dd6 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -307,16 +307,27 @@ EXPORT_SYMBOL(cfs_crypto_hash_final); * \param[in] buf data buffer on which to compute the hash * \param[in] buf_len length of \buf on which to compute hash */ -static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg, - const unsigned char *buf, - unsigned int buf_len) +static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg) { + int buf_len = max(PAGE_SIZE, 1048576UL); + void *buf; unsigned long start, end; int bcount, err = 0; int sec = 1; /* do test only 1 sec */ + struct page *page; unsigned char hash[CFS_CRYPTO_HASH_DIGESTSIZE_MAX]; unsigned int hash_len = sizeof(hash); + page = alloc_page(GFP_KERNEL); + if (!page) { + err = -ENOMEM; + goto out_err; + } + + buf = kmap(page); + memset(buf, 0xAD, PAGE_SIZE); + kunmap(page); + for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { err = cfs_crypto_hash_digest(hash_alg, buf, buf_len, NULL, 0, @@ -325,7 +336,8 @@ static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg, break; } end = jiffies; - + __free_page(page); +out_err: if (err) { cfs_crypto_hash_speeds[hash_alg] = -1; CDEBUG(D_INFO, "Crypto hash algorithm %s, err = %d\n", @@ -381,25 +393,11 @@ EXPORT_SYMBOL(cfs_crypto_hash_speed); */ static int cfs_crypto_test_hashes(void) { - unsigned char i; - unsigned char *data; - unsigned int j; - /* Data block size for testing hash. Maximum - * kmalloc size for 2.6.18 kernel is 128K - */ - unsigned int data_len = 1 * 128 * 1024; - - data = kmalloc(data_len, 0); - if (!data) - return -ENOMEM; - - for (j = 0; j < data_len; j++) - data[j] = j & 0xff; + enum cfs_crypto_hash_alg hash_alg; - for (i = 0; i < CFS_HASH_ALG_MAX; i++) - cfs_crypto_performance_test(i, data, data_len); + for (hash_alg = 0; hash_alg < CFS_HASH_ALG_MAX; hash_alg++) + cfs_crypto_performance_test(hash_alg); - kfree(data); return 0; } -- GitLab From 8260d4e2c72b6fc02ab0bae45f3ed0f259092368 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:54 -0400 Subject: [PATCH 0657/9938] staging: lustre: libcfs: print crypto performance result only on success Only print info about the crypto performance when no error is encounter. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 4857a11c0dd6..3d74fd1937c8 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -348,9 +348,10 @@ static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg) tmp = ((bcount * buf_len / jiffies_to_msecs(end - start)) * 1000) / (1024 * 1024); cfs_crypto_hash_speeds[hash_alg] = (int)tmp; + CDEBUG(D_CONFIG, "Crypto hash algorithm %s speed = %d MB/s\n", + cfs_crypto_hash_name(hash_alg), + cfs_crypto_hash_speeds[hash_alg]); } - CDEBUG(D_INFO, "Crypto hash algorithm %s speed = %d MB/s\n", - cfs_crypto_hash_name(hash_alg), cfs_crypto_hash_speeds[hash_alg]); } /** -- GitLab From 78675cb1abec09f1c93f53457b4f7859273d8d0a Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:55 -0400 Subject: [PATCH 0658/9938] staging: lustre: libcfs: improve reporting error for crypto performance Set cfs_crypto_hash_speeds[X] result to the actual error instead of -1. Make the error message more clear and informative. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053 Reviewed-on: http://review.whamcloud.com/9990 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 3d74fd1937c8..aec79165b5c7 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -339,8 +339,8 @@ static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg) __free_page(page); out_err: if (err) { - cfs_crypto_hash_speeds[hash_alg] = -1; - CDEBUG(D_INFO, "Crypto hash algorithm %s, err = %d\n", + cfs_crypto_hash_speeds[hash_alg] = err; + CDEBUG(D_INFO, "Crypto hash algorithm %s test error: rc = %d\n", cfs_crypto_hash_name(hash_alg), err); } else { unsigned long tmp; -- GitLab From 1bc55f796a9872208e19b57fd00f4c484be35318 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 26 Mar 2016 15:40:56 -0400 Subject: [PATCH 0659/9938] staging: lustre: libcfs: calculate crypto performance using pages Use alloc_page() and use cfs_crypto_hash_update_page() to compute the hash instead of cfs_crypto_hash_digest(), since tgt_checksum_bulk() computes the hash by page anyway. Signed-off-by: Andreas Dilger Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5279 Reviewed-on: http://review.whamcloud.com/10982 Reviewed-by: John L. Hammond Reviewed-by: James Simmons Reviewed-by: Alexander Boyko Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lnet/libcfs/linux/linux-crypto.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index aec79165b5c7..f8383dc430a5 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -330,8 +330,23 @@ static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg) for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { - err = cfs_crypto_hash_digest(hash_alg, buf, buf_len, NULL, 0, - hash, &hash_len); + struct cfs_crypto_hash_desc *hdesc; + int i; + + hdesc = cfs_crypto_hash_init(hash_alg, NULL, 0); + if (IS_ERR(hdesc)) { + err = PTR_ERR(hdesc); + break; + } + + for (i = 0; i < buf_len / PAGE_SIZE; i++) { + err = cfs_crypto_hash_update_page(hdesc, page, 0, + PAGE_SIZE); + if (err) + break; + } + + err = cfs_crypto_hash_final(hdesc, hash, &hash_len); if (err) break; } -- GitLab From 78ab125e63115a7f42d598a2113cd75092a40335 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 27 Mar 2016 12:05:03 -0400 Subject: [PATCH 0660/9938] staging/lustre/libcfs: Copy correct amount in libcfs_ioctl_getdata Commit b8ff756bc351 ("staging: lustre: libcfs: merge code from libcfs_ioctl into libcfs_ioctl_getdata") introduced a problem copying just a single pointer worth of data from userspace instead of whole libcfs_ioctl_hdr structure. Adjust the copying amount. Signed-off-by: Oleg Drokin Acked-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/libcfs/linux/linux-module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c index b86e93795846..d89f71ee45b2 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-module.c @@ -128,7 +128,7 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, struct libcfs_ioctl_hdr hdr; int err = 0; - if (copy_from_user(&hdr, uhdr, sizeof(uhdr))) + if (copy_from_user(&hdr, uhdr, sizeof(hdr))) return -EFAULT; if (hdr.ioc_version != LIBCFS_IOCTL_VERSION && -- GitLab From 3404f60d8b54647eff52b6aa03d60ef1ffa3deb2 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 27 Mar 2016 20:26:21 -0400 Subject: [PATCH 0661/9938] staging: lustre: libcfs: remove function declarations in libcfs.h A few function declarations are in libcfs.h that are not needed. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13874 Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index d2e43617b0a1..332394cca741 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -59,16 +59,9 @@ #define LNET_ACCEPTOR_MIN_RESERVED_PORT 512 #define LNET_ACCEPTOR_MAX_RESERVED_PORT 1023 -/* - * Drop into debugger, if possible. Implementation is provided by platform. - */ - -void cfs_enter_debugger(void); - /* * Defined by platform */ -int unshare_fs_struct(void); sigset_t cfs_block_allsigs(void); sigset_t cfs_block_sigs(unsigned long sigs); sigset_t cfs_block_sigsinv(unsigned long sigs); -- GitLab From 9af4826aeb4e12ba84a824d516432e223868f3b1 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 27 Mar 2016 20:26:22 -0400 Subject: [PATCH 0662/9938] staging: lustre: libcfs: remove cfs_signal_pending wrapper Use signal_pending() directly instead of a one line function wrapper. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13874 Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 1 - drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c | 7 ------- drivers/staging/lustre/lustre/include/lustre_lib.h | 2 +- drivers/staging/lustre/lustre/obdclass/cl_lock.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/client.c | 6 +++--- 5 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 332394cca741..9158c61f6851 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -66,7 +66,6 @@ sigset_t cfs_block_allsigs(void); sigset_t cfs_block_sigs(unsigned long sigs); sigset_t cfs_block_sigsinv(unsigned long sigs); void cfs_restore_sigs(sigset_t); -int cfs_signal_pending(void); void cfs_clear_sigpending(void); /* diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c index 89084460231a..7e5ef0a20f93 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c @@ -128,13 +128,6 @@ cfs_restore_sigs(sigset_t old) } EXPORT_SYMBOL(cfs_restore_sigs); -int -cfs_signal_pending(void) -{ - return signal_pending(current); -} -EXPORT_SYMBOL(cfs_signal_pending); - void cfs_clear_sigpending(void) { diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index f2223d55850a..c5713d74486a 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -578,7 +578,7 @@ do { \ \ if (condition) \ break; \ - if (cfs_signal_pending()) { \ + if (signal_pending(current)) { \ if (info->lwi_on_signal && \ (__timeout == 0 || __allow_intr)) { \ if (info->lwi_on_signal != LWI_ON_SIGNAL_NOOP) \ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index aec644eb4db9..f952c1cb0761 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -951,7 +951,7 @@ int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock) result = -ERESTARTSYS; if (likely(!OBD_FAIL_CHECK(OBD_FAIL_LOCK_STATE_WAIT_INTR))) { schedule(); - if (!cfs_signal_pending()) + if (!signal_pending(current)) result = 0; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 1b7673eec4d7..32a7c8710119 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -2087,7 +2087,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) CDEBUG(D_RPCTRACE, "set %p going to sleep for %d seconds\n", set, timeout); - if (timeout == 0 && !cfs_signal_pending()) + if (timeout == 0 && !signal_pending(current)) /* * No requests are in-flight (ether timed out * or delayed), so we can allow interrupts. @@ -2114,7 +2114,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) * it being ignored forever */ if (rc == -ETIMEDOUT && !lwi.lwi_allow_intr && - cfs_signal_pending()) { + signal_pending(current)) { sigset_t blocked_sigs = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); @@ -2124,7 +2124,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) * important signals since ptlrpc set is not easily * reentrant from userspace again */ - if (cfs_signal_pending()) + if (signal_pending(current)) ptlrpc_interrupted_set(set); cfs_restore_sigs(blocked_sigs); } -- GitLab From ccfb80c1861f9480572462b35f75451fc7c3517a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 27 Mar 2016 20:26:23 -0400 Subject: [PATCH 0663/9938] staging: lustre: libcfs: remove atomic cpt allocations libcfs contains functions to perform atomic memory operations. These functions have never been used so remove them. Signed-off-by: frank zago Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/15913 Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_private.h | 6 --- .../staging/lustre/lnet/libcfs/libcfs_lock.c | 41 ------------------- 2 files changed, 47 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index dab486261154..63e394eac47d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -351,12 +351,6 @@ void cfs_percpt_lock_free(struct cfs_percpt_lock *pcl); void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index); /* unlock private lock \a index of \a pcl */ void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index); -/* create percpt (atomic) refcount based on @cptab */ -atomic_t **cfs_percpt_atomic_alloc(struct cfs_cpt_table *cptab, int val); -/* destroy percpt refcount */ -void cfs_percpt_atomic_free(atomic_t **refs); -/* return sum of all percpu refs */ -int cfs_percpt_atomic_summary(atomic_t **refs); /** Compile-time assertion. diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c b/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c index 2de9eeae0232..d38954a38f9e 100644 --- a/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c +++ b/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c @@ -142,44 +142,3 @@ cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index) } } EXPORT_SYMBOL(cfs_percpt_unlock); - -/** free cpu-partition refcount */ -void -cfs_percpt_atomic_free(atomic_t **refs) -{ - cfs_percpt_free(refs); -} -EXPORT_SYMBOL(cfs_percpt_atomic_free); - -/** allocate cpu-partition refcount with initial value @init_val */ -atomic_t ** -cfs_percpt_atomic_alloc(struct cfs_cpt_table *cptab, int init_val) -{ - atomic_t **refs; - atomic_t *ref; - int i; - - refs = cfs_percpt_alloc(cptab, sizeof(*ref)); - if (!refs) - return NULL; - - cfs_percpt_for_each(ref, i, refs) - atomic_set(ref, init_val); - return refs; -} -EXPORT_SYMBOL(cfs_percpt_atomic_alloc); - -/** return sum of cpu-partition refs */ -int -cfs_percpt_atomic_summary(atomic_t **refs) -{ - atomic_t *ref; - int i; - int val = 0; - - cfs_percpt_for_each(ref, i, refs) - val += atomic_read(ref); - - return val; -} -EXPORT_SYMBOL(cfs_percpt_atomic_summary); -- GitLab From a18332b4564318c27cbc11596b2fe8b832e4c6c0 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 27 Mar 2016 20:26:24 -0400 Subject: [PATCH 0664/9938] staging: lustre: libcfs: remove cfs_percpt_[current|index] The functions cfs_percpt_current() and cfs_percpt_index() are not used anywhere. Remove it. Signed-off-by: frank zago Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/15913 Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_private.h | 2 -- .../staging/lustre/lnet/libcfs/libcfs_mem.c | 28 ------------------- 2 files changed, 30 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index 63e394eac47d..a41152745c2d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -193,8 +193,6 @@ void *cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size); */ void cfs_percpt_free(void *vars); int cfs_percpt_number(void *vars); -void *cfs_percpt_current(void *vars); -void *cfs_percpt_index(void *vars, int idx); #define cfs_percpt_for_each(var, i, vars) \ for (i = 0; i < cfs_percpt_number(vars) && \ diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_mem.c b/drivers/staging/lustre/lnet/libcfs/libcfs_mem.c index c5a6951516ed..d0e81bb41cdc 100644 --- a/drivers/staging/lustre/lnet/libcfs/libcfs_mem.c +++ b/drivers/staging/lustre/lnet/libcfs/libcfs_mem.c @@ -114,34 +114,6 @@ cfs_percpt_number(void *vars) } EXPORT_SYMBOL(cfs_percpt_number); -/* - * return memory block shadowed from current CPU - */ -void * -cfs_percpt_current(void *vars) -{ - struct cfs_var_array *arr; - int cpt; - - arr = container_of(vars, struct cfs_var_array, va_ptrs[0]); - cpt = cfs_cpt_current(arr->va_cptab, 0); - if (cpt < 0) - return NULL; - - return arr->va_ptrs[cpt]; -} - -void * -cfs_percpt_index(void *vars, int idx) -{ - struct cfs_var_array *arr; - - arr = container_of(vars, struct cfs_var_array, va_ptrs[0]); - - LASSERT(idx >= 0 && idx < arr->va_count); - return arr->va_ptrs[idx]; -} - /* * free variable array, see more detail in cfs_array_alloc */ -- GitLab From 762d266d7d27bc00f9249a21feadc03154ab07c7 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 27 Mar 2016 20:26:25 -0400 Subject: [PATCH 0665/9938] staging: lustre: libcfs: move all cpt handling to libcfs_cpu.h Move the CPT handling declartions out of libcfs_private.h to libcfs_cpu.h where it belongs. Signed-off-by: frank zago Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/15913 Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_cpu.h | 64 ++++++++++++++++++ .../include/linux/libcfs/libcfs_private.h | 67 ------------------- 2 files changed, 64 insertions(+), 67 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h index 9e62c59714b7..71ad93b2c6af 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h @@ -203,6 +203,70 @@ int cfs_cpt_spread_node(struct cfs_cpt_table *cptab, int cpt); */ int cfs_cpu_ht_nsiblings(int cpu); +/* + * allocate per-cpu-partition data, returned value is an array of pointers, + * variable can be indexed by CPU ID. + * cptab != NULL: size of array is number of CPU partitions + * cptab == NULL: size of array is number of HW cores + */ +void *cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size); +/* + * destory per-cpu-partition variable + */ +void cfs_percpt_free(void *vars); +int cfs_percpt_number(void *vars); + +#define cfs_percpt_for_each(var, i, vars) \ + for (i = 0; i < cfs_percpt_number(vars) && \ + ((var) = (vars)[i]) != NULL; i++) + +/* + * percpu partition lock + * + * There are some use-cases like this in Lustre: + * . each CPU partition has it's own private data which is frequently changed, + * and mostly by the local CPU partition. + * . all CPU partitions share some global data, these data are rarely changed. + * + * LNet is typical example. + * CPU partition lock is designed for this kind of use-cases: + * . each CPU partition has it's own private lock + * . change on private data just needs to take the private lock + * . read on shared data just needs to take _any_ of private locks + * . change on shared data needs to take _all_ private locks, + * which is slow and should be really rare. + */ +enum { + CFS_PERCPT_LOCK_EX = -1, /* negative */ +}; + +struct cfs_percpt_lock { + /* cpu-partition-table for this lock */ + struct cfs_cpt_table *pcl_cptab; + /* exclusively locked */ + unsigned int pcl_locked; + /* private lock table */ + spinlock_t **pcl_locks; +}; + +/* return number of private locks */ +#define cfs_percpt_lock_num(pcl) cfs_cpt_number(pcl->pcl_cptab) + +/* + * create a cpu-partition lock based on CPU partition table \a cptab, + * each private lock has extra \a psize bytes padding data + */ +struct cfs_percpt_lock *cfs_percpt_lock_alloc(struct cfs_cpt_table *cptab); + +/* destroy a cpu-partition lock */ +void cfs_percpt_lock_free(struct cfs_percpt_lock *pcl); + +/* lock private lock \a index of \a pcl */ +void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index); + +/* unlock private lock \a index of \a pcl */ +void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index); + /** * iterate over all CPU partitions in \a cptab */ diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index a41152745c2d..e18b57b5c64e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -181,23 +181,6 @@ int libcfs_debug_cleanup(void); int libcfs_debug_clear_buffer(void); int libcfs_debug_mark_buffer(const char *text); -/* - * allocate per-cpu-partition data, returned value is an array of pointers, - * variable can be indexed by CPU ID. - * cptable != NULL: size of array is number of CPU partitions - * cptable == NULL: size of array is number of HW cores - */ -void *cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size); -/* - * destroy per-cpu-partition variable - */ -void cfs_percpt_free(void *vars); -int cfs_percpt_number(void *vars); - -#define cfs_percpt_for_each(var, i, vars) \ - for (i = 0; i < cfs_percpt_number(vars) && \ - ((var) = (vars)[i]) != NULL; i++) - /* * allocate a variable array, returned value is an array of pointers. * Caller can specify length of array by count. @@ -300,56 +283,6 @@ do { \ #define CFS_ALLOC_PTR(ptr) LIBCFS_ALLOC(ptr, sizeof(*(ptr))) #define CFS_FREE_PTR(ptr) LIBCFS_FREE(ptr, sizeof(*(ptr))) -/* - * percpu partition lock - * - * There are some use-cases like this in Lustre: - * . each CPU partition has it's own private data which is frequently changed, - * and mostly by the local CPU partition. - * . all CPU partitions share some global data, these data are rarely changed. - * - * LNet is typical example. - * CPU partition lock is designed for this kind of use-cases: - * . each CPU partition has it's own private lock - * . change on private data just needs to take the private lock - * . read on shared data just needs to take _any_ of private locks - * . change on shared data needs to take _all_ private locks, - * which is slow and should be really rare. - */ - -enum { - CFS_PERCPT_LOCK_EX = -1, /* negative */ -}; - -struct cfs_percpt_lock { - /* cpu-partition-table for this lock */ - struct cfs_cpt_table *pcl_cptab; - /* exclusively locked */ - unsigned int pcl_locked; - /* private lock table */ - spinlock_t **pcl_locks; -}; - -/* return number of private locks */ -static inline int -cfs_percpt_lock_num(struct cfs_percpt_lock *pcl) -{ - return cfs_cpt_number(pcl->pcl_cptab); -} - -/* - * create a cpu-partition lock based on CPU partition table \a cptab, - * each private lock has extra \a psize bytes padding data - */ -struct cfs_percpt_lock *cfs_percpt_lock_alloc(struct cfs_cpt_table *cptab); -/* destroy a cpu-partition lock */ -void cfs_percpt_lock_free(struct cfs_percpt_lock *pcl); - -/* lock private lock \a index of \a pcl */ -void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index); -/* unlock private lock \a index of \a pcl */ -void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index); - /** Compile-time assertion. * Check an invariant described by a constant expression at compile time by -- GitLab From 2dc09ea8d91a97dd01c675f2903ce5b4d1fd48d3 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 27 Mar 2016 20:26:26 -0400 Subject: [PATCH 0666/9938] staging: lustre: libcfs: add lock-class for cfs_percpt_lock initialise lock-class for each sublock of cfs_percpt_lock to eliminate false alarm ""possible recursive locking detected" Signed-off-by: Liang Zhen Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6432 Reviewed-on: http://review.whamcloud.com/14368 Reviewed-by: James Simmons Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_cpu.h | 19 +++++++++++++++++-- .../staging/lustre/lnet/libcfs/libcfs_lock.c | 13 ++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h index 71ad93b2c6af..81d8079e3b5e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h @@ -256,8 +256,8 @@ struct cfs_percpt_lock { * create a cpu-partition lock based on CPU partition table \a cptab, * each private lock has extra \a psize bytes padding data */ -struct cfs_percpt_lock *cfs_percpt_lock_alloc(struct cfs_cpt_table *cptab); - +struct cfs_percpt_lock *cfs_percpt_lock_create(struct cfs_cpt_table *cptab, + struct lock_class_key *keys); /* destroy a cpu-partition lock */ void cfs_percpt_lock_free(struct cfs_percpt_lock *pcl); @@ -267,6 +267,21 @@ void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index); /* unlock private lock \a index of \a pcl */ void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index); +#define CFS_PERCPT_LOCK_KEYS 256 + +/* NB: don't allocate keys dynamically, lockdep needs them to be in ".data" */ +#define cfs_percpt_lock_alloc(cptab) \ +({ \ + static struct lock_class_key ___keys[CFS_PERCPT_LOCK_KEYS]; \ + struct cfs_percpt_lock *___lk; \ + \ + if (cfs_cpt_number(cptab) > CFS_PERCPT_LOCK_KEYS) \ + ___lk = cfs_percpt_lock_create(cptab, NULL); \ + else \ + ___lk = cfs_percpt_lock_create(cptab, ___keys); \ + ___lk; \ +}) + /** * iterate over all CPU partitions in \a cptab */ diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c b/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c index d38954a38f9e..83543f928279 100644 --- a/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c +++ b/drivers/staging/lustre/lnet/libcfs/libcfs_lock.c @@ -49,7 +49,8 @@ EXPORT_SYMBOL(cfs_percpt_lock_free); * reason we always allocate cacheline-aligned memory block. */ struct cfs_percpt_lock * -cfs_percpt_lock_alloc(struct cfs_cpt_table *cptab) +cfs_percpt_lock_create(struct cfs_cpt_table *cptab, + struct lock_class_key *keys) { struct cfs_percpt_lock *pcl; spinlock_t *lock; @@ -67,12 +68,18 @@ cfs_percpt_lock_alloc(struct cfs_cpt_table *cptab) return NULL; } - cfs_percpt_for_each(lock, i, pcl->pcl_locks) + if (!keys) + CWARN("Cannot setup class key for percpt lock, you may see recursive locking warnings which are actually fake.\n"); + + cfs_percpt_for_each(lock, i, pcl->pcl_locks) { spin_lock_init(lock); + if (keys != NULL) + lockdep_set_class(lock, &keys[i]); + } return pcl; } -EXPORT_SYMBOL(cfs_percpt_lock_alloc); +EXPORT_SYMBOL(cfs_percpt_lock_create); /** * lock a CPU partition -- GitLab From 304d13ff4d5dcccea2cf199d96d6716de31b7321 Mon Sep 17 00:00:00 2001 From: Jian Yu Date: Sun, 27 Mar 2016 20:26:27 -0400 Subject: [PATCH 0667/9938] staging: lustre: libcfs: replace direct HZ access with kernel APIs On some customers' systems, the kernel was compiled with HZ defined to 100, instead of 1000. This improves performance for HPC applications. However, to use these systems with Lustre, customers have to re-build Lustre for the kernel because Lustre directly uses the defined constant HZ. Since kernel 2.6.21, some non-HZ dependent timing APIs become non- inline functions, which can be used in Lustre codes to replace the direct HZ access. These kernel APIs include: jiffies_to_msecs() jiffies_to_usecs() jiffies_to_timespec() msecs_to_jiffies() usecs_to_jiffies() timespec_to_jiffies() And here are some samples of the replacement: HZ -> msecs_to_jiffies(MSEC_PER_SEC) n * HZ -> msecs_to_jiffies(n * MSEC_PER_SEC) HZ / n -> msecs_to_jiffies(MSEC_PER_SEC / n) n / HZ -> jiffies_to_msecs(n) / MSEC_PER_SEC n / HZ * 1000 -> jiffies_to_msecs(n) This patch replaces the direct HZ access in the libcfs module. Signed-off-by: Jian Yu Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5443 Reviewed-on: http://review.whamcloud.com/11993 Reviewed-by: Nathaniel Clark Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/linux/linux-time.h | 4 ++-- drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h index ed8764b11c80..7656b09b8752 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h @@ -70,12 +70,12 @@ static inline unsigned long cfs_time_current(void) static inline long cfs_time_seconds(int seconds) { - return ((long)seconds) * HZ; + return ((long)seconds) * msecs_to_jiffies(MSEC_PER_SEC); } static inline long cfs_duration_sec(long d) { - return d / HZ; + return d / msecs_to_jiffies(MSEC_PER_SEC); } #define cfs_time_current_64 get_jiffies_64 diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index f8383dc430a5..0715101c577c 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -313,7 +313,6 @@ static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg) void *buf; unsigned long start, end; int bcount, err = 0; - int sec = 1; /* do test only 1 sec */ struct page *page; unsigned char hash[CFS_CRYPTO_HASH_DIGESTSIZE_MAX]; unsigned int hash_len = sizeof(hash); @@ -328,8 +327,8 @@ static void cfs_crypto_performance_test(enum cfs_crypto_hash_alg hash_alg) memset(buf, 0xAD, PAGE_SIZE); kunmap(page); - for (start = jiffies, end = start + sec * HZ, bcount = 0; - time_before(jiffies, end); bcount++) { + for (start = jiffies, end = start + msecs_to_jiffies(MSEC_PER_SEC), + bcount = 0; time_before(jiffies, end); bcount++) { struct cfs_crypto_hash_desc *hdesc; int i; -- GitLab From d47b7026ba96f604318e46354e8ec129f9b960d7 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 27 Mar 2016 20:26:28 -0400 Subject: [PATCH 0668/9938] staging: lustre: libcfs: add CFS_FAULT_CHECK() Add the macro CFS_FAULT_CHECK() which behaves like CFS_FAIL_CHECK() except that any site may be matched by setting CFS_FAULT (0x02000000) in cfs_fail_loc. Add cfs_fail_err for use as a return value with CFS_FAULT_CHECK(). Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5409 Reviewed-on: http://review.whamcloud.com/11263 Reviewed-by: Robert Read Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_fail.h | 15 ++++++++++++--- drivers/staging/lustre/lnet/libcfs/fail.c | 3 +++ drivers/staging/lustre/lnet/libcfs/module.c | 7 +++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h index aa69c6a33d19..2e008bffc89a 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h @@ -38,6 +38,7 @@ extern unsigned long cfs_fail_loc; extern unsigned int cfs_fail_val; +extern int cfs_fail_err; extern wait_queue_head_t cfs_race_waitq; extern int cfs_race_state; @@ -70,9 +71,14 @@ enum { #define CFS_FAIL_RAND 0x08000000 /* fail 1/N of the times */ #define CFS_FAIL_USR1 0x04000000 /* user flag */ -#define CFS_FAIL_PRECHECK(id) (cfs_fail_loc && \ - (cfs_fail_loc & CFS_FAIL_MASK_LOC) == \ - ((id) & CFS_FAIL_MASK_LOC)) +#define CFS_FAULT 0x02000000 /* match any CFS_FAULT_CHECK */ + +static inline bool CFS_FAIL_PRECHECK(__u32 id) +{ + return cfs_fail_loc != 0 && + ((cfs_fail_loc & CFS_FAIL_MASK_LOC) == (id & CFS_FAIL_MASK_LOC) || + (cfs_fail_loc & id & CFS_FAULT)); +} static inline int cfs_fail_check_set(__u32 id, __u32 value, int set, int quiet) @@ -144,6 +150,9 @@ static inline int cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set) #define CFS_FAIL_TIMEOUT_MS_ORSET(id, value, ms) \ cfs_fail_timeout_set(id, value, ms, CFS_FAIL_LOC_ORSET) +#define CFS_FAULT_CHECK(id) \ + CFS_FAIL_CHECK(CFS_FAULT | (id)) + /* The idea here is to synchronise two threads to force a race. The * first thread that calls this with a matching fail_loc is put to * sleep. The next thread that calls with the same fail_loc wakes up diff --git a/drivers/staging/lustre/lnet/libcfs/fail.c b/drivers/staging/lustre/lnet/libcfs/fail.c index dadaf7685cbd..086e690bd6f2 100644 --- a/drivers/staging/lustre/lnet/libcfs/fail.c +++ b/drivers/staging/lustre/lnet/libcfs/fail.c @@ -41,6 +41,9 @@ EXPORT_SYMBOL(cfs_fail_loc); unsigned int cfs_fail_val; EXPORT_SYMBOL(cfs_fail_val); +int cfs_fail_err; +EXPORT_SYMBOL(cfs_fail_err); + DECLARE_WAIT_QUEUE_HEAD(cfs_race_waitq); EXPORT_SYMBOL(cfs_race_waitq); diff --git a/drivers/staging/lustre/lnet/libcfs/module.c b/drivers/staging/lustre/lnet/libcfs/module.c index 49c2d03dc9de..f2d041118cf7 100644 --- a/drivers/staging/lustre/lnet/libcfs/module.c +++ b/drivers/staging/lustre/lnet/libcfs/module.c @@ -424,6 +424,13 @@ static struct ctl_table lnet_table[] = { .mode = 0644, .proc_handler = &proc_dointvec }, + { + .procname = "fail_err", + .data = &cfs_fail_err, + .maxlen = sizeof(cfs_fail_err), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { } }; -- GitLab From 5d145b1ad404e8cb260283d8a8b0747261698c73 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sun, 27 Mar 2016 20:26:29 -0400 Subject: [PATCH 0669/9938] staging: lustre: libcfs: remove cfs_workitem_t typedefs Convert cfs_workitem_t to proper structure. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/17202 Reviewed-by: John L. Hammond Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_hash.h | 4 ++-- .../lustre/include/linux/libcfs/libcfs_workitem.h | 12 ++++++------ drivers/staging/lustre/lnet/libcfs/hash.c | 6 +++--- drivers/staging/lustre/lnet/libcfs/workitem.c | 12 ++++++------ drivers/staging/lustre/lnet/selftest/selftest.h | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h index c3f2332fa043..119986bc7961 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h @@ -245,7 +245,7 @@ struct cfs_hash { /** # of iterators (caller of cfs_hash_for_each_*) */ __u32 hs_iterators; /** rehash workitem */ - cfs_workitem_t hs_rehash_wi; + struct cfs_workitem hs_rehash_wi; /** refcount on this hash table */ atomic_t hs_refcount; /** rehash buckets-table */ @@ -262,7 +262,7 @@ struct cfs_hash { /** bits when we found the max depth */ unsigned int hs_dep_bits; /** workitem to output max depth */ - cfs_workitem_t hs_dep_wi; + struct cfs_workitem hs_dep_wi; #endif /** name of htable */ char hs_name[0]; diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_workitem.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_workitem.h index 5cc64f327a87..f9b20c5accbf 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_workitem.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_workitem.h @@ -73,7 +73,7 @@ int cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab, int cpt, struct cfs_workitem; typedef int (*cfs_wi_action_t) (struct cfs_workitem *); -typedef struct cfs_workitem { +struct cfs_workitem { /** chain on runq or rerunq */ struct list_head wi_list; /** working function */ @@ -84,10 +84,10 @@ typedef struct cfs_workitem { unsigned short wi_running:1; /** scheduled */ unsigned short wi_scheduled:1; -} cfs_workitem_t; +}; static inline void -cfs_wi_init(cfs_workitem_t *wi, void *data, cfs_wi_action_t action) +cfs_wi_init(struct cfs_workitem *wi, void *data, cfs_wi_action_t action) { INIT_LIST_HEAD(&wi->wi_list); @@ -97,9 +97,9 @@ cfs_wi_init(cfs_workitem_t *wi, void *data, cfs_wi_action_t action) wi->wi_action = action; } -void cfs_wi_schedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi); -int cfs_wi_deschedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi); -void cfs_wi_exit(struct cfs_wi_sched *sched, cfs_workitem_t *wi); +void cfs_wi_schedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi); +int cfs_wi_deschedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi); +void cfs_wi_exit(struct cfs_wi_sched *sched, struct cfs_workitem *wi); int cfs_wi_startup(void); void cfs_wi_shutdown(void); diff --git a/drivers/staging/lustre/lnet/libcfs/hash.c b/drivers/staging/lustre/lnet/libcfs/hash.c index f60feb3a3dc7..cc45ed82b2be 100644 --- a/drivers/staging/lustre/lnet/libcfs/hash.c +++ b/drivers/staging/lustre/lnet/libcfs/hash.c @@ -942,10 +942,10 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts, * @flags - CFS_HASH_REHASH enable synamic hash resizing * - CFS_HASH_SORT enable chained hash sort */ -static int cfs_hash_rehash_worker(cfs_workitem_t *wi); +static int cfs_hash_rehash_worker(struct cfs_workitem *wi); #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 -static int cfs_hash_dep_print(cfs_workitem_t *wi) +static int cfs_hash_dep_print(struct cfs_workitem *wi) { struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_dep_wi); int dep; @@ -1847,7 +1847,7 @@ cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old) } static int -cfs_hash_rehash_worker(cfs_workitem_t *wi) +cfs_hash_rehash_worker(struct cfs_workitem *wi) { struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_rehash_wi); struct cfs_hash_bucket **bkts; diff --git a/drivers/staging/lustre/lnet/libcfs/workitem.c b/drivers/staging/lustre/lnet/libcfs/workitem.c index c72fe00dce8d..92236ae59e49 100644 --- a/drivers/staging/lustre/lnet/libcfs/workitem.c +++ b/drivers/staging/lustre/lnet/libcfs/workitem.c @@ -111,7 +111,7 @@ cfs_wi_sched_cansleep(struct cfs_wi_sched *sched) * 1. when it returns no one shall try to schedule the workitem. */ void -cfs_wi_exit(struct cfs_wi_sched *sched, cfs_workitem_t *wi) +cfs_wi_exit(struct cfs_wi_sched *sched, struct cfs_workitem *wi) { LASSERT(!in_interrupt()); /* because we use plain spinlock */ LASSERT(!sched->ws_stopping); @@ -138,7 +138,7 @@ EXPORT_SYMBOL(cfs_wi_exit); * cancel schedule request of workitem \a wi */ int -cfs_wi_deschedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi) +cfs_wi_deschedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi) { int rc; @@ -179,7 +179,7 @@ EXPORT_SYMBOL(cfs_wi_deschedule); * be added, and even dynamic creation of serialised queues might be supported. */ void -cfs_wi_schedule(struct cfs_wi_sched *sched, cfs_workitem_t *wi) +cfs_wi_schedule(struct cfs_wi_sched *sched, struct cfs_workitem *wi) { LASSERT(!in_interrupt()); /* because we use plain spinlock */ LASSERT(!sched->ws_stopping); @@ -229,12 +229,12 @@ static int cfs_wi_scheduler(void *arg) while (!sched->ws_stopping) { int nloops = 0; int rc; - cfs_workitem_t *wi; + struct cfs_workitem *wi; while (!list_empty(&sched->ws_runq) && nloops < CFS_WI_RESCHED) { - wi = list_entry(sched->ws_runq.next, cfs_workitem_t, - wi_list); + wi = list_entry(sched->ws_runq.next, + struct cfs_workitem, wi_list); LASSERT(wi->wi_scheduled && !wi->wi_running); list_del_init(&wi->wi_list); diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 288522d4d7b9..f50580e5b02a 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -176,7 +176,7 @@ typedef int (*swi_action_t) (struct swi_workitem *); typedef struct swi_workitem { struct cfs_wi_sched *swi_sched; - cfs_workitem_t swi_workitem; + struct cfs_workitem swi_workitem; swi_action_t swi_action; int swi_state; } swi_workitem_t; @@ -461,7 +461,7 @@ srpc_serv_is_framework(struct srpc_service *svc) } static inline int -swi_wi_action(cfs_workitem_t *wi) +swi_wi_action(struct cfs_workitem *wi) { swi_workitem_t *swi = container_of(wi, swi_workitem_t, swi_workitem); -- GitLab From 6e7f9f5ad552327fcc1151e2dca141075f3e160a Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Tue, 27 Oct 2015 15:31:46 +0800 Subject: [PATCH 0670/9938] arm64: dts: rockchip: Add rk3368 mailbox device nodes This adds mailbox device nodes in dts. Mailbox is used by the Rockchip CPU cores to communicate requests to MCU processor. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3368.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index 394916341680..7056a0fa1921 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -555,6 +555,18 @@ status = "disabled"; }; + mbox: mbox@ff6b0000 { + compatible = "rockchip,rk3368-mailbox"; + reg = <0x0 0xff6b0000 0x0 0x1000>; + interrupts = , + , + , + ; + clocks = <&cru PCLK_MAILBOX>; + clock-names = "pclk_mailbox"; + #mbox-cells = <1>; + }; + pmugrf: syscon@ff738000 { compatible = "rockchip,rk3368-pmugrf", "syscon"; reg = <0x0 0xff738000 0x0 0x1000>; -- GitLab From 33e84ad03294b17d85a592ed4c5e80618bd197d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 16 Mar 2016 14:58:40 +0100 Subject: [PATCH 0671/9938] dt-bindings: Add vendor prefix for GeekBuying.com MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use "geekbuying". Signed-off-by: Andreas Färber Acked-by: Rob Herring Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 86740d4a270d..2988be977857 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -91,6 +91,7 @@ firefly Firefly focaltech FocalTech Systems Co.,Ltd fsl Freescale Semiconductor ge General Electric Company +geekbuying GeekBuying GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. geniatech Geniatech, Inc. -- GitLab From 479d75b7603c3db0cbaafb4368e3c3ba0da80864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 16 Mar 2016 14:58:43 +0100 Subject: [PATCH 0672/9938] arm64: dts: rockchip: Clean up gpio-keys nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop superfluous #address-cells and #size-cells. Use KEY_POWER define for 116. Rename sub-nodes to avoid new dtc warnings. Reported-by: Julien Chauveau Signed-off-by: Andreas Färber Reviewed-by: Julien Chauveau Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi | 7 +++---- arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi index 06bbe421db37..fff8b1931f26 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi @@ -40,6 +40,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include "rk3368.dtsi" @@ -105,16 +106,14 @@ keys: gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pwr_key>; - button@0 { + power { wakeup-source; gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; label = "GPIO Power"; - linux,code = <116>; + linux,code = ; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts index a1d1aa9c16fe..b56b7205e39b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts @@ -42,6 +42,7 @@ /dts-v1/; #include "rk3368.dtsi" +#include / { model = "Rockchip R88"; @@ -65,16 +66,14 @@ keys: gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pwr_key>; - button@0 { + power { wakeup-source; gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; label = "GPIO Power"; - linux,code = <116>; + linux,code = ; }; }; -- GitLab From 70011f5f2cbdadb52536ae752d2a4d59189df03f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 28 Mar 2016 13:55:56 +0900 Subject: [PATCH 0673/9938] staging: wilc1000: change data type of wid argument in wilc_wlan_cfg_set This patch changes data type of wid argument in wilc_wlan_cfg_set from u32 to u16. It is better to change data type of wid because wid has one of enum WID_T that is data type of u16. And, there is no need to use u16 type casting when calling wilc_wlan_cfg_set_wid function. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 4 ++-- drivers/staging/wilc1000/wilc_wlan.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 30e1c039e80a..d09aa3bd0c16 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1197,7 +1197,7 @@ static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type, return 0; } -int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer, +int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler) { u32 offset; @@ -1212,7 +1212,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer, offset = wilc->cfg_frame_offset; ret_size = wilc_wlan_cfg_set_wid(wilc->cfg_frame.frame, offset, - (u16)wid, buffer, buffer_size); + wid, buffer, buffer_size); offset += ret_size; wilc->cfg_frame_offset = offset; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index bcd4bfa5accc..ef7064207a9d 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -284,7 +284,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count); void wilc_handle_isr(struct wilc *wilc); void wilc_wlan_cleanup(struct net_device *dev); -int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer, +int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, u32 drv_handler); -- GitLab From 7db699dbe5107073050c123b05495e9c271f62fe Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 28 Mar 2016 13:55:57 +0900 Subject: [PATCH 0674/9938] staging: wilc1000: change data type of wid argument in wilc_wlan_cfg_get This patch changes data type of wid argument in wilc_wlan_cfg_get from u32 to u16. It is better to change data type of wid because wid has one of enum WID_T that is data type of u16. And, there is no need to use u16 type casting when calling wilc_wlan_cfg_get_wid function. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 5 ++--- drivers/staging/wilc1000/wilc_wlan.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d09aa3bd0c16..db79ae246828 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1239,7 +1239,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, return ret_size; } -int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, +int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler) { u32 offset; @@ -1253,8 +1253,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, wilc->cfg_frame_offset = 0; offset = wilc->cfg_frame_offset; - ret_size = wilc_wlan_cfg_get_wid(wilc->cfg_frame.frame, offset, - (u16)wid); + ret_size = wilc_wlan_cfg_get_wid(wilc->cfg_frame.frame, offset, wid); offset += ret_size; wilc->cfg_frame_offset = offset; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index ef7064207a9d..38edeeb53d7c 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -286,7 +286,7 @@ void wilc_handle_isr(struct wilc *wilc); void wilc_wlan_cleanup(struct net_device *dev); int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); -int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, +int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler); int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, -- GitLab From c975f9dd106461794d339348e2f4b4812d154875 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 28 Mar 2016 13:55:58 +0900 Subject: [PATCH 0675/9938] staging: wilc1000: change data type of wid argument in wilc_wlan_cfg_get_val This patch changes data type of wid argument in wilc_wlan_cfg_get_val from u32 to u16. It is better to change data type of wid because wid has one of enum WID_T that is data type of u16. And, there is no need to use u16 type casting when calling wilc_wlan_cfg_get_wid_value function. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 4 ++-- drivers/staging/wilc1000/wilc_wlan.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index db79ae246828..7da3b4ac1dc5 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1276,9 +1276,9 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, return ret_size; } -int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) +int wilc_wlan_cfg_get_val(u16 wid, u8 *buffer, u32 buffer_size) { - return wilc_wlan_cfg_get_wid_value((u16)wid, buffer, buffer_size); + return wilc_wlan_cfg_get_wid_value(wid, buffer, buffer_size); } int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 38edeeb53d7c..30e5312ee87e 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -288,7 +288,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler); -int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size); +int wilc_wlan_cfg_get_val(u16 wid, u8 *buffer, u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, wilc_tx_complete_func_t func); void wilc_chip_sleep_manually(struct wilc *wilc); -- GitLab From 589c667d8ae1d7359a974719dd0d09f85aee5606 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 28 Mar 2016 13:55:59 +0900 Subject: [PATCH 0676/9938] staging: wilc1000: remove unused struct semaphore SemHandleUpdateStats struct semaphore SemHandleUpdateStats is defined but never used in this driver, so just remove it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 1 - drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 5785dda8f9d3..f6aec474ff3a 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2262,7 +2262,6 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de } priv = wdev_priv(wdev); - sema_init(&(priv->SemHandleUpdateStats), 1); priv->wdev = wdev; wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID; #ifdef CONFIG_PM diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index debb139b7687..94a41b4a21a7 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -130,7 +130,6 @@ struct wilc_priv { struct wilc_wfi_key *wilc_ptk[MAX_NUM_STA]; u8 wilc_groupkey; /* semaphores */ - struct semaphore SemHandleUpdateStats; struct semaphore hSemScanReq; /* */ bool gbAutoRateAdjusted; -- GitLab From 086620978b2d06378f4a41afce2f7705c76a4625 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 28 Mar 2016 13:56:00 +0900 Subject: [PATCH 0677/9938] staging: wilc1000: use mutex instead of struct semaphore hSemScanReq This patch replaces struct semaphore hSemScanReq with struct mutex scan_req_lock. It is better to use mutex than semaphore. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 10 +++++----- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index f6aec474ff3a..358632b9aa83 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -451,7 +451,7 @@ static void CfgScanResult(enum scan_event scan_event, } else if (scan_event == SCAN_EVENT_DONE) { refresh_scan(priv, 1, false); - down(&(priv->hSemScanReq)); + mutex_lock(&priv->scan_req_lock); if (priv->pstrScanReq) { cfg80211_scan_done(priv->pstrScanReq, false); @@ -459,9 +459,9 @@ static void CfgScanResult(enum scan_event scan_event, priv->bCfgScanning = false; priv->pstrScanReq = NULL; } - up(&(priv->hSemScanReq)); + mutex_unlock(&priv->scan_req_lock); } else if (scan_event == SCAN_EVENT_ABORTED) { - down(&(priv->hSemScanReq)); + mutex_lock(&priv->scan_req_lock); if (priv->pstrScanReq) { update_scan_time(); @@ -471,7 +471,7 @@ static void CfgScanResult(enum scan_event scan_event, priv->bCfgScanning = false; priv->pstrScanReq = NULL; } - up(&(priv->hSemScanReq)); + mutex_unlock(&priv->scan_req_lock); } } } @@ -2307,7 +2307,7 @@ int wilc_init_host_int(struct net_device *net) priv->bInP2PlistenState = false; - sema_init(&(priv->hSemScanReq), 1); + mutex_init(&priv->scan_req_lock); s32Error = wilc_init(net, &priv->hif_drv); if (s32Error) netdev_err(net, "Error while initializing hostinterface\n"); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 94a41b4a21a7..3d0ca8e3ae24 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -130,7 +130,7 @@ struct wilc_priv { struct wilc_wfi_key *wilc_ptk[MAX_NUM_STA]; u8 wilc_groupkey; /* semaphores */ - struct semaphore hSemScanReq; + struct mutex scan_req_lock; /* */ bool gbAutoRateAdjusted; -- GitLab From ff3334276744ad49477e60c3c9e6acec8399b25d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 28 Mar 2016 16:51:17 -0700 Subject: [PATCH 0678/9938] staging: skein: Convert local rotl_64 to kernel's rol64 Remove the local inline and use the generic kernel rol64 instead. Miscellanea: o Added a newline between a multiple line macro for consistency with the other multiple line macros Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/skein/skein_base.h | 5 ----- drivers/staging/skein/skein_block.c | 30 +++++++++++++++-------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/staging/skein/skein_base.h b/drivers/staging/skein/skein_base.h index 3c7f8ad3627d..9c4be1ab2c5d 100644 --- a/drivers/staging/skein/skein_base.h +++ b/drivers/staging/skein/skein_base.h @@ -84,11 +84,6 @@ struct skein_1024_ctx { /* 1024-bit Skein hash context structure */ u8 b[SKEIN_1024_BLOCK_BYTES]; /* partial block buf (8-byte aligned) */ }; -static inline u64 rotl_64(u64 x, u8 N) -{ - return (x << N) | (x >> (64 - N)); -} - /* Skein APIs for (incremental) "straight hashing" */ int skein_256_init(struct skein_256_ctx *ctx, size_t hash_bit_len); int skein_512_init(struct skein_512_ctx *ctx, size_t hash_bit_len); diff --git a/drivers/staging/skein/skein_block.c b/drivers/staging/skein/skein_block.c index 45b47327e024..1a547b307b33 100644 --- a/drivers/staging/skein/skein_block.c +++ b/drivers/staging/skein/skein_block.c @@ -15,6 +15,7 @@ ************************************************************************/ #include +#include #include "skein_base.h" #include "skein_block.h" @@ -59,10 +60,10 @@ #define ROUND256(p0, p1, p2, p3, ROT, r_num) \ do { \ X##p0 += X##p1; \ - X##p1 = rotl_64(X##p1, ROT##_0); \ + X##p1 = rol64(X##p1, ROT##_0); \ X##p1 ^= X##p0; \ X##p2 += X##p3; \ - X##p3 = rotl_64(X##p3, ROT##_1); \ + X##p3 = rol64(X##p3, ROT##_1); \ X##p3 ^= X##p2; \ } while (0) @@ -136,15 +137,16 @@ #define ROUND512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \ do { \ X##p0 += X##p1; \ - X##p1 = rotl_64(X##p1, ROT##_0); \ + X##p1 = rol64(X##p1, ROT##_0); \ X##p1 ^= X##p0; \ X##p2 += X##p3; \ - X##p3 = rotl_64(X##p3, ROT##_1); \ + X##p3 = rol64(X##p3, ROT##_1); \ X##p3 ^= X##p2; \ X##p4 += X##p5; \ - X##p5 = rotl_64(X##p5, ROT##_2); \ + X##p5 = rol64(X##p5, ROT##_2); \ X##p5 ^= X##p4; \ - X##p6 += X##p7; X##p7 = rotl_64(X##p7, ROT##_3);\ + X##p6 += X##p7; \ + X##p7 = rol64(X##p7, ROT##_3); \ X##p7 ^= X##p6; \ } while (0) @@ -226,28 +228,28 @@ pF, ROT, r_num) \ do { \ X##p0 += X##p1; \ - X##p1 = rotl_64(X##p1, ROT##_0); \ + X##p1 = rol64(X##p1, ROT##_0); \ X##p1 ^= X##p0; \ X##p2 += X##p3; \ - X##p3 = rotl_64(X##p3, ROT##_1); \ + X##p3 = rol64(X##p3, ROT##_1); \ X##p3 ^= X##p2; \ X##p4 += X##p5; \ - X##p5 = rotl_64(X##p5, ROT##_2); \ + X##p5 = rol64(X##p5, ROT##_2); \ X##p5 ^= X##p4; \ X##p6 += X##p7; \ - X##p7 = rotl_64(X##p7, ROT##_3); \ + X##p7 = rol64(X##p7, ROT##_3); \ X##p7 ^= X##p6; \ X##p8 += X##p9; \ - X##p9 = rotl_64(X##p9, ROT##_4); \ + X##p9 = rol64(X##p9, ROT##_4); \ X##p9 ^= X##p8; \ X##pA += X##pB; \ - X##pB = rotl_64(X##pB, ROT##_5); \ + X##pB = rol64(X##pB, ROT##_5); \ X##pB ^= X##pA; \ X##pC += X##pD; \ - X##pD = rotl_64(X##pD, ROT##_6); \ + X##pD = rol64(X##pD, ROT##_6); \ X##pD ^= X##pC; \ X##pE += X##pF; \ - X##pF = rotl_64(X##pF, ROT##_7); \ + X##pF = rol64(X##pF, ROT##_7); \ X##pF ^= X##pE; \ } while (0) -- GitLab From d3d62d1d6c479dd2058694c36b7d7d54cbe3d42f Mon Sep 17 00:00:00 2001 From: Clifton Barnes Date: Sun, 27 Mar 2016 15:13:00 -0400 Subject: [PATCH 0679/9938] staging: xgifb: fix 'line over 80 characters' fix checkpatch.pl warning about 'line over 80 characters' Signed-off-by: Clifton Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 26b539bc6faf..29da955493c1 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -551,7 +551,8 @@ static int XGINew_ReadWriteRest(unsigned short StopAddr, writel(Position, fbaddr + Position); } - usleep_range(500, 1500); /* Fix #1759 Memory Size error in Multi-Adapter. */ + /* Fix #1759 Memory Size error in Multi-Adapter. */ + usleep_range(500, 1500); Position = 0; -- GitLab From c3f0692aeed9e79f52c53284df7471aeb8006b43 Mon Sep 17 00:00:00 2001 From: Clifton Barnes Date: Sun, 27 Mar 2016 15:13:01 -0400 Subject: [PATCH 0680/9938] staging: xgifb: fix code indent fix checkpatch.pl warning about 'suspect code indent for conditional statements' Signed-off-by: Clifton Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 40939c86ab7c..cc1ad768918a 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -108,9 +108,9 @@ static void XGI_SetATTRegs(unsigned short ModeIdIndex, if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { ARdata = 0; } else if ((pVBInfo->VBInfo & - (SetCRT2ToTV | SetCRT2ToLCD)) && - (pVBInfo->VBInfo & SetInSlaveMode)) { - ARdata = 0; + (SetCRT2ToTV | SetCRT2ToLCD)) && + (pVBInfo->VBInfo & SetInSlaveMode)) { + ARdata = 0; } } @@ -2983,7 +2983,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, if ((pVBInfo->VBInfo & SetCRT2ToHiVision) && !(pVBInfo->VBType & VB_SIS301LV) && (resinfo == 7)) - temp -= 2; + temp -= 2; } /* 0x05 Horizontal Display Start */ -- GitLab From d312007698241b79153d5ac101bddb14fa9c4956 Mon Sep 17 00:00:00 2001 From: Clifton Barnes Date: Sun, 27 Mar 2016 15:13:03 -0400 Subject: [PATCH 0681/9938] staging: xgifb: fix bare use of 'unsigned' fix checkpatch.pl warning about 'Prefer 'unsigned int' to bare use of 'unsigned'' Signed-off-by: Clifton Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 5 +++-- drivers/staging/xgifb/vb_util.h | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 7eadf922b21f..d56ef1425f6b 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1130,8 +1130,9 @@ static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var) return (var->bits_per_pixel == 8) ? 256 : 16; } -static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, struct fb_info *info) +static int XGIfb_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) { struct xgifb_video_info *xgifb_info = info->par; diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h index f613f54d522f..08db58b396b2 100644 --- a/drivers/staging/xgifb/vb_util.h +++ b/drivers/staging/xgifb/vb_util.h @@ -13,7 +13,7 @@ static inline u8 xgifb_reg_get(unsigned long port, u8 index) } static inline void xgifb_reg_and_or(unsigned long port, u8 index, - unsigned data_and, unsigned data_or) + unsigned int data_and, unsigned int data_or) { u8 temp; @@ -22,7 +22,8 @@ static inline void xgifb_reg_and_or(unsigned long port, u8 index, xgifb_reg_set(port, index, temp); } -static inline void xgifb_reg_and(unsigned long port, u8 index, unsigned data_and) +static inline void xgifb_reg_and(unsigned long port, u8 index, + unsigned int data_and) { u8 temp; @@ -31,7 +32,8 @@ static inline void xgifb_reg_and(unsigned long port, u8 index, unsigned data_and xgifb_reg_set(port, index, temp); } -static inline void xgifb_reg_or(unsigned long port, u8 index, unsigned data_or) +static inline void xgifb_reg_or(unsigned long port, u8 index, + unsigned int data_or) { u8 temp; -- GitLab From 0d6b23a427a9c62f93a175187cedcd4f3a3a95d7 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 26 Mar 2016 11:44:52 +0530 Subject: [PATCH 0682/9938] Staging: rtl8723au: Remove unused functions The functions rtw_get_oper_bw23a and rtw_get_oper_ch23aoffset are never used anywhere in the kernel. So, remove their definition and prototype. Grepped to find occurences. Signed-off-by: Bhumika Goyal Reviewed-by: Julian Calaby Acked-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/core/rtw_wlan_util.c | 10 ---------- drivers/staging/rtl8723au/include/rtw_mlme_ext.h | 2 -- 2 files changed, 12 deletions(-) diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c index cc2b84be9774..694cf17f82cf 100644 --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c @@ -304,21 +304,11 @@ inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch) adapter_to_dvobj(adapter)->oper_channel = ch; } -inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter) -{ - return adapter_to_dvobj(adapter)->oper_bwmode; -} - inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw) { adapter_to_dvobj(adapter)->oper_bwmode = bw; } -inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter) -{ - return adapter_to_dvobj(adapter)->oper_ch_offset; -} - inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset) { adapter_to_dvobj(adapter)->oper_ch_offset = offset; diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h index ea2a6c914d38..0e7d3da91471 100644 --- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h @@ -461,9 +461,7 @@ void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen); u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter); void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch); -u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter); void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw); -u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter); void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset); void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel, -- GitLab From 15ac352c5402513bd7bee5cfe6439118b5a5f337 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 26 Mar 2016 11:54:55 +0530 Subject: [PATCH 0683/9938] Staging: rtl8723au: Remove function rtw_enqueue_{recvbuf23a/recvbuf23a_to_head} The functions rtw_enqueue_recvbuf23a and rtw_enqueue_recvbuf23a_to_head are never used anywhere in the kernel. So, remove their definition and prototype. Grepped to find occurences. Signed-off-by: Bhumika Goyal Reviewed-by: Julian Calaby Acked-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/core/rtw_recv.c | 25 -------------------- drivers/staging/rtl8723au/include/rtw_recv.h | 2 -- 2 files changed, 27 deletions(-) diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c index 989ed0726817..150dabc2a58d 100644 --- a/drivers/staging/rtl8723au/core/rtw_recv.c +++ b/drivers/staging/rtl8723au/core/rtw_recv.c @@ -211,31 +211,6 @@ u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter) return cnt; } -int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct rtw_queue *queue) -{ - spin_lock_bh(&queue->lock); - - list_del_init(&precvbuf->list); - list_add(&precvbuf->list, get_list_head(queue)); - - spin_unlock_bh(&queue->lock); - - return _SUCCESS; -} - -int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue *queue) -{ - unsigned long irqL; - - spin_lock_irqsave(&queue->lock, irqL); - - list_del_init(&precvbuf->list); - - list_add_tail(&precvbuf->list, get_list_head(queue)); - spin_unlock_irqrestore(&queue->lock, irqL); - return _SUCCESS; -} - struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue) { unsigned long irqL; diff --git a/drivers/staging/rtl8723au/include/rtw_recv.h b/drivers/staging/rtl8723au/include/rtw_recv.h index dc784be3ddd9..85a5edb450e3 100644 --- a/drivers/staging/rtl8723au/include/rtw_recv.h +++ b/drivers/staging/rtl8723au/include/rtw_recv.h @@ -279,8 +279,6 @@ int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *qu u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter); -int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct rtw_queue *queue); -int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue *queue); struct recv_buf *rtw_dequeue_recvbuf23a(struct rtw_queue *queue); void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext); -- GitLab From db71dd988af5ffdc6280e93977591b3ebc4c7673 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 23 Mar 2016 10:55:21 +0000 Subject: [PATCH 0684/9938] staging: comedi: drivers: remove bogus ni_mio_c_common.c The zero-length file "ni_mio_c_common.c" was inadvertantly created by commit e563637b5fef ("staging: comedi: Use ARRAY_SIZE for sizes of arrays"). Remove it. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_c_common.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 drivers/staging/comedi/drivers/ni_mio_c_common.c diff --git a/drivers/staging/comedi/drivers/ni_mio_c_common.c b/drivers/staging/comedi/drivers/ni_mio_c_common.c deleted file mode 100644 index e69de29bb2d1..000000000000 -- GitLab From 7a4000e7128d9432ba78bc398bbedc6066825b80 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 25 Mar 2016 22:54:48 +0200 Subject: [PATCH 0685/9938] Staging: wlan-ng: no need for memcpy() since its arguments are already equal This patch removes the memcpy() for two variables which were previously tested with memcmp(). The result of memcmp() was zero which means that the previously tested variables were already equal. Signed-off-by: Claudiu Beznea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index bdb50a51483b..6354036ffb42 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -243,7 +243,6 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, for (i = 0; i < wlandev->spy_number; i++) { if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) { - memcpy(wlandev->spy_address[i], mac, ETH_ALEN); wlandev->spy_stat[i].level = rxmeta->signal; wlandev->spy_stat[i].noise = rxmeta->noise; wlandev->spy_stat[i].qual = -- GitLab From 71fa2cf90ad46b925c27c372fac9b927e8014ebf Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 25 Mar 2016 23:28:54 +0200 Subject: [PATCH 0686/9938] Staging: wlan-ng: convert usb_prism_tbl[] array into a const array This patch convert usb_prism_tbl[] into a const array since it is not modified anywhere in prism2usb.c file. Signed-off-by: Claudiu Beznea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 41358bbc6246..b26d09ff840c 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -8,7 +8,7 @@ { USB_DEVICE(vid, pid), \ .driver_info = (unsigned long)name } -static struct usb_device_id usb_prism_tbl[] = { +static const struct usb_device_id usb_prism_tbl[] = { PRISM_DEV(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS"), PRISM_DEV(0x07aa, 0x0012, "Corega Wireless LAN USB Stick-11"), PRISM_DEV(0x09aa, 0x3642, "Prism2.x 11Mbps WLAN USB Adapter"), -- GitLab From 686855e033faf191b499315758ae2c40f230a3bc Mon Sep 17 00:00:00 2001 From: Ben Marsh Date: Fri, 25 Mar 2016 22:44:48 +0100 Subject: [PATCH 0687/9938] Staging: gs_fpgaboot: remove blank line in io.c Removes a blank line in order to silence a checkpatch.pl warning. Signed-off-by: Ben Marsh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/io.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c index 819db53da64d..c9391198fbfb 100644 --- a/drivers/staging/gs_fpgaboot/io.c +++ b/drivers/staging/gs_fpgaboot/io.c @@ -35,7 +35,6 @@ static inline void byte0_out(unsigned char data); static inline void byte1_out(unsigned char data); static inline void xl_cclk_b(int32_t i); - /* Assert and Deassert CCLK */ void xl_shift_cclk(int count) { -- GitLab From 3cb61bdf14af55e71095f4d11187a79116b30e3f Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 26 Mar 2016 12:42:43 +0530 Subject: [PATCH 0688/9938] Staging: rts5208: Remove unused functions The functions rtsx_disable_card_int, rtsx_undo_delink, rtsx_check_link_ready are not used anywhere in the kernel. So,remove their definition and prototype. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_chip.c | 35 ----------------------------- drivers/staging/rts5208/rtsx_chip.h | 3 --- 2 files changed, 38 deletions(-) diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index c0ce659a5aa6..bcc4b666d79f 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -43,14 +43,6 @@ static void rtsx_calibration(struct rtsx_chip *chip) rtsx_write_phy_register(chip, 0x00, 0x0288); } -void rtsx_disable_card_int(struct rtsx_chip *chip) -{ - u32 reg = rtsx_readl(chip, RTSX_BIER); - - reg &= ~(XD_INT_EN | SD_INT_EN | MS_INT_EN); - rtsx_writel(chip, RTSX_BIER, reg); -} - void rtsx_enable_card_int(struct rtsx_chip *chip) { u32 reg = rtsx_readl(chip, RTSX_BIER); @@ -1447,12 +1439,6 @@ void rtsx_polling_func(struct rtsx_chip *chip) rtsx_delink_stage(chip); } -void rtsx_undo_delink(struct rtsx_chip *chip) -{ - chip->auto_delink_allowed = 0; - rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x00); -} - /** * rtsx_stop_cmd - stop command transfer and DMA transfer * @chip: Realtek's card reader chip @@ -2000,27 +1986,6 @@ int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit) return STATUS_SUCCESS; } -int rtsx_check_link_ready(struct rtsx_chip *chip) -{ - int retval; - u8 val; - - retval = rtsx_read_register(chip, IRQSTAT0, &val); - if (retval) { - rtsx_trace(chip); - return retval; - } - - dev_dbg(rtsx_dev(chip), "IRQSTAT0: 0x%x\n", val); - if (val & LINK_RDY_INT) { - dev_dbg(rtsx_dev(chip), "Delinked!\n"); - rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate) { u32 ultmp; diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index c295b1eedb44..c08164f3247e 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -950,7 +950,6 @@ do { \ int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl); int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl); -void rtsx_disable_card_int(struct rtsx_chip *chip); void rtsx_enable_card_int(struct rtsx_chip *chip); void rtsx_enable_bus_int(struct rtsx_chip *chip); void rtsx_disable_bus_int(struct rtsx_chip *chip); @@ -958,7 +957,6 @@ int rtsx_reset_chip(struct rtsx_chip *chip); int rtsx_init_chip(struct rtsx_chip *chip); void rtsx_release_chip(struct rtsx_chip *chip); void rtsx_polling_func(struct rtsx_chip *chip); -void rtsx_undo_delink(struct rtsx_chip *chip); void rtsx_stop_cmd(struct rtsx_chip *chip, int card); int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data); int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data); @@ -975,7 +973,6 @@ int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val); int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val); int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit); int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit); -int rtsx_check_link_ready(struct rtsx_chip *chip); void rtsx_enter_ss(struct rtsx_chip *chip); void rtsx_exit_ss(struct rtsx_chip *chip); int rtsx_pre_handle_interrupt(struct rtsx_chip *chip); -- GitLab From 143b3bf6d3f7e14945af589414f1bd29efe36a72 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 26 Mar 2016 12:52:28 +0530 Subject: [PATCH 0689/9938] Staging: rts5208: rtsx_card.c: Remove unused function The functions double_depth, check_card_fail, check_card_ejected are not used anywhere in the kernel. So, remove their prototype and definition. Grepped to find occurences. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_card.c | 21 --------------------- drivers/staging/rts5208/rtsx_card.h | 2 -- 2 files changed, 23 deletions(-) diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 437436f5dbdd..231833a3045e 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -628,11 +628,6 @@ void rtsx_init_cards(struct rtsx_chip *chip) } } -static inline u8 double_depth(u8 depth) -{ - return (depth > 1) ? (depth - 1) : depth; -} - int switch_ssc_clock(struct rtsx_chip *chip, int clk) { int retval; @@ -1184,22 +1179,6 @@ int check_card_wp(struct rtsx_chip *chip, unsigned int lun) return 0; } -int check_card_fail(struct rtsx_chip *chip, unsigned int lun) -{ - if (chip->card_fail & chip->lun2card[lun]) - return 1; - - return 0; -} - -int check_card_ejected(struct rtsx_chip *chip, unsigned int lun) -{ - if (chip->card_ejected & chip->lun2card[lun]) - return 1; - - return 0; -} - u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun) { if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) diff --git a/drivers/staging/rts5208/rtsx_card.h b/drivers/staging/rts5208/rtsx_card.h index 8f2cf9a4ec69..56df9a431d6d 100644 --- a/drivers/staging/rts5208/rtsx_card.h +++ b/drivers/staging/rts5208/rtsx_card.h @@ -1024,8 +1024,6 @@ int detect_card_cd(struct rtsx_chip *chip, int card); int check_card_exist(struct rtsx_chip *chip, unsigned int lun); int check_card_ready(struct rtsx_chip *chip, unsigned int lun); int check_card_wp(struct rtsx_chip *chip, unsigned int lun); -int check_card_fail(struct rtsx_chip *chip, unsigned int lun); -int check_card_ejected(struct rtsx_chip *chip, unsigned int lun); void eject_card(struct rtsx_chip *chip, unsigned int lun); u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun); -- GitLab From ae6b08672fd1802abbdd12dcda7553a7f1f009ad Mon Sep 17 00:00:00 2001 From: Aniket Sharma Date: Sun, 27 Mar 2016 10:52:19 -0700 Subject: [PATCH 0690/9938] Staging: comedi: Fix 'unsigned' warning style This patch fixes the checkpatch.pl warning: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' + unsigned runflags; WARNING: Prefer 'unsigned int' to bare use of 'unsigned' +struct comedi_device *comedi_dev_get_from_minor(unsigned minor); Signed-off-by: Aniket Sharma Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 115807215484..dcb637665eb7 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -173,7 +173,7 @@ struct comedi_subdevice { void *lock; void *busy; - unsigned runflags; + unsigned int runflags; spinlock_t spin_lock; /* generic spin-lock for COMEDI and drivers */ unsigned int io_bits; @@ -566,7 +566,7 @@ struct comedi_device { void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); -struct comedi_device *comedi_dev_get_from_minor(unsigned minor); +struct comedi_device *comedi_dev_get_from_minor(unsigned int minor); int comedi_dev_put(struct comedi_device *dev); bool comedi_is_subdevice_running(struct comedi_subdevice *s); -- GitLab From b2073dcb80b61043f6ae6aeb2311907b0418392a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 29 Mar 2016 10:49:04 +0100 Subject: [PATCH 0691/9938] staging: comedi: comedi_fops.c: fix lines over 80 characters Fix checkpatch.pl warnings about lines over 80 characters in "comedi_fops.c". Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 4bdea202c46c..629080f39db0 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -209,8 +209,8 @@ static void comedi_free_board_dev(struct comedi_device *dev) } } -static struct comedi_subdevice -*comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor) +static struct comedi_subdevice * +comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor) { struct comedi_subdevice *s; unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; @@ -233,7 +233,8 @@ static struct comedi_device *comedi_dev_get_from_board_minor(unsigned int minor) return dev; } -static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned int minor) +static struct comedi_device * +comedi_dev_get_from_subdevice_minor(unsigned int minor) { struct comedi_device *dev; struct comedi_subdevice *s; @@ -342,7 +343,8 @@ static struct comedi_subdevice *comedi_file_write_subdevice(struct file *file) } static int resize_async_buffer(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int new_size) + struct comedi_subdevice *s, + unsigned int new_size) { struct comedi_async *async = s->async; int retval; @@ -628,7 +630,8 @@ static void __comedi_set_subdevice_runflags(struct comedi_subdevice *s, } static void comedi_update_subdevice_runflags(struct comedi_subdevice *s, - unsigned int mask, unsigned int bits) + unsigned int mask, + unsigned int bits) { unsigned long flags; @@ -2485,7 +2488,8 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, n = min_t(size_t, m, nbytes); if (n == 0) { - unsigned int runflags = comedi_get_subdevice_runflags(s); + unsigned int runflags = + comedi_get_subdevice_runflags(s); if (!comedi_is_runflags_running(runflags)) { if (comedi_is_runflags_in_error(runflags)) -- GitLab From 246fee6cb7a1d2a283e1e16e77e783300574d0b5 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Thu, 2 Apr 2015 05:32:34 +0200 Subject: [PATCH 0692/9938] ARM: dts: lpc18xx: add rtc node Add node for the internal RTC found on all lpc18xx SoCs. Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc18xx.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index 0b59eae1608d..e27029425d18 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -215,6 +215,14 @@ }; }; + rtc: rtc@40046000 { + compatible = "nxp,lpc1850-rtc", "nxp,lpc1788-rtc"; + reg = <0x40046000 0x1000>; + interrupts = <47>; + clocks = <&creg_clk 0>, <&ccu1 CLK_CPU_BUS>; + clock-names = "rtc", "reg"; + }; + cgu: clock-controller@40050000 { compatible = "nxp,lpc1850-cgu"; reg = <0x40050000 0x1000>; -- GitLab From e162f9c2c65f8178420abb70ebbfc19ea0c51b52 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sun, 28 Feb 2016 20:20:54 +0100 Subject: [PATCH 0693/9938] ARM: dts: lpc18xx: add adc nodes Add nodes for the two 10-bit ADCs found on all lpc18xx SoCs. Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc18xx.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index e27029425d18..88d27ae32dfb 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -453,6 +453,24 @@ status = "disabled"; }; + adc0: adc@400e3000 { + compatible = "nxp,lpc1850-adc"; + reg = <0x400e3000 0x1000>; + interrupts = <17>; + clocks = <&ccu1 CLK_APB3_ADC0>; + resets = <&rgu 40>; + status = "disabled"; + }; + + adc1: adc@400e4000 { + compatible = "nxp,lpc1850-adc"; + reg = <0x400e4000 0x1000>; + interrupts = <21>; + clocks = <&ccu1 CLK_APB3_ADC1>; + resets = <&rgu 41>; + status = "disabled"; + }; + gpio: gpio@400f4000 { compatible = "nxp,lpc1850-gpio"; reg = <0x400f4000 0x4000>; -- GitLab From 8c938004f529b954db1d8e7b2800d728f4de8667 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sun, 28 Feb 2016 23:48:18 +0100 Subject: [PATCH 0694/9938] ARM: dts: lpc18xx: add dac node Add node for the 10-bit DAC found on all lpc18xx SoCs. Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc18xx.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index 88d27ae32dfb..fdc991bedd37 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -444,6 +444,15 @@ status = "disabled"; }; + dac: dac@400e1000 { + compatible = "nxp,lpc1850-dac"; + reg = <0x400e1000 0x1000>; + interrupts = <0>; + clocks = <&ccu1 CLK_APB3_DAC>; + resets = <&rgu 42>; + status = "disabled"; + }; + can0: can@400e2000 { compatible = "bosch,c_can"; reg = <0x400e2000 0x1000>; -- GitLab From 5f2d9d18b2400590ffa1253a689fc22c87e58302 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sun, 28 Feb 2016 20:47:20 +0100 Subject: [PATCH 0695/9938] ARM: dts: lpc4357-ea4357: add adc0 Enable adc0 on EA4357 dev kit. This kit has a 22k potentiometer (R94) connected on ADC0 channel 3. Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc4357-ea4357-devkit.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts b/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts index 079d3cf8c00b..bbc70b94d1c3 100644 --- a/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts +++ b/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts @@ -38,6 +38,13 @@ reg = <0x28000000 0x2000000>; /* 32 MB */ }; + vcc: vcc_fixed { + compatible = "regulator-fixed"; + regulator-name = "3v3-supply"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + /* vmmc is controlled by sdmmc host internally */ vmmc: vmmc_fixed { compatible = "regulator-fixed"; @@ -461,6 +468,11 @@ }; }; +&adc0 { + status = "okay"; + vref-supply = <&vcc>; +}; + &i2c0 { status = "okay"; pinctrl-names = "default"; -- GitLab From 31b8f1af5a055a968999e88cdb16622f7bbf38df Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Mon, 29 Feb 2016 07:07:15 +0100 Subject: [PATCH 0696/9938] ARM: dts: lpc4357-ea4357: add dac Enable the DAC on the EA4357 dev kit. Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc4357-ea4357-devkit.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts b/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts index bbc70b94d1c3..a211b6ef538d 100644 --- a/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts +++ b/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts @@ -495,6 +495,11 @@ }; }; +&dac { + status = "okay"; + vref-supply = <&vcc>; +}; + &emc { status = "okay"; pinctrl-names = "default"; -- GitLab From 7e7a3e9c892ab798da2be67fe842b77f3bdee317 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Tue, 1 Mar 2016 16:53:06 +0100 Subject: [PATCH 0697/9938] ARM: dts: lpc4350-hitex-eval: add adc1 Enable adc1 on LPC4350 Hitex Evalution board. This board has a 10k potensiometer (R26) connected to ADC1 channel 2. Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc4350-hitex-eval.dts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/boot/dts/lpc4350-hitex-eval.dts b/arch/arm/boot/dts/lpc4350-hitex-eval.dts index 022d495432c1..6d0c698a6d94 100644 --- a/arch/arm/boot/dts/lpc4350-hitex-eval.dts +++ b/arch/arm/boot/dts/lpc4350-hitex-eval.dts @@ -119,9 +119,25 @@ gpios = <&pca_gpio 3 GPIO_ACTIVE_LOW>; }; }; + + vcc: vcc_fixed { + compatible = "regulator-fixed"; + regulator-name = "3v3io"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; }; &pinctrl { + adc1_pins: adc1-pins { + adc1_pins_cfg { + pins = "pf_9"; + function = "adc"; + input-disable; + bias-disable; + }; + }; + emc_pins: emc-pins { emc_addr0_23_cfg { pins = "p2_9", "p2_10", "p2_11", "p2_12", @@ -325,6 +341,13 @@ }; }; +&adc1 { + status = "okay"; + vref-supply = <&vcc>; + pinctrl-names = "default"; + pinctrl-0 = <&adc1_pins>; +}; + &emc { status = "okay"; pinctrl-names = "default"; -- GitLab From f235541699bcf14fb8be797c6bc1d7106df0eb64 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 22 Jan 2016 01:32:26 -0500 Subject: [PATCH 0698/9938] export.h: allow for per-symbol configurable EXPORT_SYMBOL() Similar to include/generated/autoconf.h, include/generated/autoksyms.h will contain a list of defines for each EXPORT_SYMBOL() that we want active. The format is: #define __KSYM_ 1 This list will be auto-generated with another patch. For now we only include the preprocessor magic to automatically create or omit the corresponding struct kernel_symbol declaration. Given the content of include/generated/autoksyms.h may not be known in advance, an empty file is created early on to let the build proceed. Signed-off-by: Nicolas Pitre Acked-by: Rusty Russell --- Makefile | 2 ++ include/linux/export.h | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 916b26e999d8..451acbebee97 100644 --- a/Makefile +++ b/Makefile @@ -998,6 +998,8 @@ prepare2: prepare3 outputmakefile asm-generic prepare1: prepare2 $(version_h) include/generated/utsrelease.h \ include/config/auto.conf $(cmd_crmodverdir) + $(Q)test -e include/generated/autoksyms.h || \ + touch include/generated/autoksyms.h archprepare: archheaders archscripts prepare1 scripts_basic diff --git a/include/linux/export.h b/include/linux/export.h index 96e45ea463e7..77afdb2a2506 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -38,7 +38,7 @@ extern struct module __this_module; #ifdef CONFIG_MODULES -#ifndef __GENKSYMS__ +#if defined(__KERNEL__) && !defined(__GENKSYMS__) #ifdef CONFIG_MODVERSIONS /* Mark the CRC weak since genksyms apparently decides not to * generate a checksums for some symbols */ @@ -53,7 +53,7 @@ extern struct module __this_module; #endif /* For every exported symbol, place a struct in the __ksymtab section */ -#define __EXPORT_SYMBOL(sym, sec) \ +#define ___EXPORT_SYMBOL(sym, sec) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ static const char __kstrtab_##sym[] \ @@ -65,6 +65,24 @@ extern struct module __this_module; __attribute__((section("___ksymtab" sec "+" #sym), unused)) \ = { (unsigned long)&sym, __kstrtab_##sym } +#ifdef CONFIG_TRIM_UNUSED_KSYMS + +#include +#include + +#define __EXPORT_SYMBOL(sym, sec) \ + __cond_export_sym(sym, sec, config_enabled(__KSYM_##sym)) +#define __cond_export_sym(sym, sec, conf) \ + ___cond_export_sym(sym, sec, conf) +#define ___cond_export_sym(sym, sec, enabled) \ + __cond_export_sym_##enabled(sym, sec) +#define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec) +#define __cond_export_sym_0(sym, sec) /* nothing */ + +#else +#define __EXPORT_SYMBOL ___EXPORT_SYMBOL +#endif + #define EXPORT_SYMBOL(sym) \ __EXPORT_SYMBOL(sym, "") -- GitLab From d8329e35cc08e07a3250b3873325d300c1e91c81 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 12 Feb 2016 15:00:50 -0500 Subject: [PATCH 0699/9938] fixdep: accept extra dependencies on stdin ... and merge them in the list of parsed dependencies. Signed-off-by: Nicolas Pitre --- scripts/basic/fixdep.c | 60 +++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index caef815d1743..7e90a1f7de0f 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -120,13 +120,15 @@ #define INT_NFIG ntohl(0x4e464947) #define INT_FIG_ ntohl(0x4649475f) +int insert_extra_deps; char *target; char *depfile; char *cmdline; static void usage(void) { - fprintf(stderr, "Usage: fixdep \n"); + fprintf(stderr, "Usage: fixdep [-e] \n"); + fprintf(stderr, " -e insert extra dependencies given on stdin\n"); exit(1); } @@ -138,6 +140,40 @@ static void print_cmdline(void) printf("cmd_%s := %s\n\n", target, cmdline); } +/* + * Print out a dependency path from a symbol name + */ +static void print_config(const char *m, int slen) +{ + int c, i; + + printf(" $(wildcard include/config/"); + for (i = 0; i < slen; i++) { + c = m[i]; + if (c == '_') + c = '/'; + else + c = tolower(c); + putchar(c); + } + printf(".h) \\\n"); +} + +static void do_extra_deps(void) +{ + if (insert_extra_deps) { + char buf[80]; + while(fgets(buf, sizeof(buf), stdin)) { + int len = strlen(buf); + if (len < 2 || buf[len-1] != '\n') { + fprintf(stderr, "fixdep: bad data on stdin\n"); + exit(1); + } + print_config(buf, len-1); + } + } +} + struct item { struct item *next; unsigned int len; @@ -197,23 +233,12 @@ static void define_config(const char *name, int len, unsigned int hash) static void use_config(const char *m, int slen) { unsigned int hash = strhash(m, slen); - int c, i; if (is_defined_config(m, slen, hash)) return; define_config(m, slen, hash); - - printf(" $(wildcard include/config/"); - for (i = 0; i < slen; i++) { - c = m[i]; - if (c == '_') - c = '/'; - else - c = tolower(c); - putchar(c); - } - printf(".h) \\\n"); + print_config(m, slen); } static void parse_config_file(const char *map, size_t len) @@ -250,7 +275,7 @@ static void parse_config_file(const char *map, size_t len) } } -/* test is s ends in sub */ +/* test if s ends in sub */ static int strrcmp(const char *s, const char *sub) { int slen = strlen(s); @@ -378,6 +403,8 @@ static void parse_dep_file(void *map, size_t len) exit(1); } + do_extra_deps(); + printf("\n%s: $(deps_%s)\n\n", target, target); printf("$(deps_%s):\n", target); } @@ -434,7 +461,10 @@ int main(int argc, char *argv[]) { traps(); - if (argc != 4) + if (argc == 5 && !strcmp(argv[1], "-e")) { + insert_extra_deps = 1; + argv++; + } else if (argc != 4) usage(); depfile = argv[1]; -- GitLab From e4aca45950050fc584e036bb1b266ce1264a6daf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 17 Feb 2016 15:50:06 -0500 Subject: [PATCH 0700/9938] kbuild: de-duplicate fixdep usage The generation and postprocessing of automatic dependency rules is duplicated in rule_cc_o_c, rule_as_o_S and if_changed_dep. Since this is not a trivial one-liner action, it is now abstracted under cmd_and_fixdep to simplify things and make future changes in this area easier. In the rule_cc_o_c and rule_as_o_S cases that means the order of some commands has been altered, namely fixdep and related file manipulations are executed earlier, but they didn't depend on those commands that now execute later. Signed-off-by: Nicolas Pitre --- scripts/Kbuild.include | 5 ++++- scripts/Makefile.build | 19 +++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index b2ab2a92a375..80ca538bfba9 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -256,10 +256,13 @@ if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ # Execute the command and also postprocess generated .d dependencies file. if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ @set -e; \ + $(cmd_and_fixdep), @:) + +cmd_and_fixdep = \ $(echo-cmd) $(cmd_$(1)); \ scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\ rm -f $(depfile); \ - mv -f $(dot-target).tmp $(dot-target).cmd, @:) + mv -f $(dot-target).tmp $(dot-target).cmd; # Usage: $(call if_changed_rule,foo) # Will check if $(cmd_foo) or any of the prerequisites changed, diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 74556e5e4ec0..12821d9eae85 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -266,24 +266,15 @@ endif # CONFIG_STACK_VALIDATION define rule_cc_o_c $(call echo-cmd,checksrc) $(cmd_checksrc) \ - $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ + $(call cmd_and_fixdep,cc_o_c) \ $(cmd_modversions) \ - $(cmd_objtool) \ - $(call echo-cmd,record_mcount) \ - $(cmd_record_mcount) \ - scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \ - $(dot-target).tmp; \ - rm -f $(depfile); \ - mv -f $(dot-target).tmp $(dot-target).cmd + $(cmd_objtool) \ + $(call echo-cmd,record_mcount) $(cmd_record_mcount) endef define rule_as_o_S - $(call echo-cmd,as_o_S) $(cmd_as_o_S); \ - $(cmd_objtool) \ - scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,as_o_S)' > \ - $(dot-target).tmp; \ - rm -f $(depfile); \ - mv -f $(dot-target).tmp $(dot-target).cmd + $(call cmd_and_fixdep,as_o_S) \ + $(cmd_objtool) endef # List module undefined symbols (or empty line if not enabled) -- GitLab From c1a95fda2a40ae8c7aad3fa44fa7718a3710eb2d Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 22 Jan 2016 13:41:57 -0500 Subject: [PATCH 0701/9938] kbuild: add fine grained build dependencies for exported symbols Like with kconfig options, we now have the ability to compile in and out individual EXPORT_SYMBOL() declarations based on the content of include/generated/autoksyms.h. However we don't want the entire world to be rebuilt whenever that file is touched. Let's apply the same build dependency trick used for CONFIG_* symbols where the time stamp of empty files whose paths matching those symbols is used to trigger fine grained rebuilds. In our case the key is the symbol name passed to EXPORT_SYMBOL(). However, unlike config options, we cannot just use fixdep to parse the source code for EXPORT_SYMBOL(ksym) because several variants exist and parsing them all in a separate tool, and keeping it in synch, is not trivially maintainable. Furthermore, there are variants such as EXPORT_SYMBOL_GPL(pci_user_read_config_##size); that are instanciated via a macro for which we can't easily determine the actual exported symbol name(s) short of actually running the preprocessor on them. Storing the symbol name string in a special ELF section doesn't work for targets that output assembly or preprocessed source. So the best way is really to leverage the preprocessor by having it output actual symbol names anchored by a special sequence that can be easily filtered out. Then the list of symbols is simply fed to fixdep to be merged with the other dependencies. That implies the preprocessor is executed twice for each source file. A previous attempt relied on a warning pragma for each EXPORT_SYMBOL() instance that was filtered apart from stderr by the build system with a sed script during the actual compilation pass. Unfortunately the preprocessor/compiler diagnostic output isn't stable between versions and this solution, although more efficient, was deemed too fragile. Because of the lowercasing performed by fixdep, there might be name collisions triggering spurious rebuilds for similar symbols. But this shouldn't be a big issue in practice. (This is the case for CONFIG_* symbols and I didn't want to be different here, whatever the original reason for doing so.) To avoid needless build overhead, the exported symbol name gathering is performed only when CONFIG_TRIM_UNUSED_KSYMS is selected. Signed-off-by: Nicolas Pitre Acked-by: Rusty Russell --- include/linux/export.h | 13 ++++++++++++- scripts/Kbuild.include | 27 +++++++++++++++++++++++++++ scripts/basic/fixdep.c | 1 + 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/linux/export.h b/include/linux/export.h index 77afdb2a2506..2f9ccbe6a639 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -65,7 +65,18 @@ extern struct module __this_module; __attribute__((section("___ksymtab" sec "+" #sym), unused)) \ = { (unsigned long)&sym, __kstrtab_##sym } -#ifdef CONFIG_TRIM_UNUSED_KSYMS +#if defined(__KSYM_DEPS__) + +/* + * For fine grained build dependencies, we want to tell the build system + * about each possible exported symbol even if they're not actually exported. + * We use a string pattern that is unlikely to be valid code that the build + * system filters out from the preprocessor output (see ksym_dep_filter + * in scripts/Kbuild.include). + */ +#define __EXPORT_SYMBOL(sym, sec) === __KSYM_##sym === + +#elif defined(CONFIG_TRIM_UNUSED_KSYMS) #include #include diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 80ca538bfba9..a09927e02713 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -258,12 +258,39 @@ if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ @set -e; \ $(cmd_and_fixdep), @:) +ifndef CONFIG_TRIM_UNUSED_KSYMS + cmd_and_fixdep = \ $(echo-cmd) $(cmd_$(1)); \ scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\ rm -f $(depfile); \ mv -f $(dot-target).tmp $(dot-target).cmd; +else + +# Filter out exported kernel symbol names from the preprocessor output. +# See also __KSYM_DEPS__ in include/linux/export.h. +# We disable the depfile generation here, so as not to overwrite the existing +# depfile while fixdep is parsing it. +flags_nodeps = $(filter-out -Wp$(comma)-M%, $($(1))) +ksym_dep_filter = \ + case "$(1)" in \ + cc_*_c) $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ + as_*_S) $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ + boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ + *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ + esac | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' + +cmd_and_fixdep = \ + $(echo-cmd) $(cmd_$(1)); \ + $(ksym_dep_filter) | \ + scripts/basic/fixdep -e $(depfile) $@ '$(make-cmd)' \ + > $(dot-target).tmp; \ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd; + +endif + # Usage: $(call if_changed_rule,foo) # Will check if $(cmd_foo) or any of the prerequisites changed, # and if so will execute $(rule_foo). diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 7e90a1f7de0f..746ec1ece614 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -358,6 +358,7 @@ static void parse_dep_file(void *map, size_t len) /* Ignore certain dependencies */ if (strrcmp(s, "include/generated/autoconf.h") && + strrcmp(s, "include/generated/autoksyms.h") && strrcmp(s, "arch/um/include/uml-config.h") && strrcmp(s, "include/linux/kconfig.h") && strrcmp(s, ".ver")) { -- GitLab From 23121ca2b56b583c43512e4d7a926343be937714 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 Jan 2016 21:50:18 -0500 Subject: [PATCH 0702/9938] kbuild: create/adjust generated/autoksyms.h Given the list of exported symbols needed by all modules, we can create a header file containing preprocessor defines for each of those symbols. Also, when some symbols are added and/or removed from the list, we can update the time on the corresponding files used as build dependencies for those symbols. And finally, if any symbol did change state, the corresponding source files must be rebuilt. The insertion or removal of an EXPORT_SYMBOL() entry within a module may create or remove the need for another exported symbol. This is why this operation has to be repeated until the list of needed exported symbols becomes stable. Only then the final kernel and modules link take place. Signed-off-by: Nicolas Pitre Acked-by: Rusty Russell --- Makefile | 13 +++++ scripts/adjust_autoksyms.sh | 101 ++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100755 scripts/adjust_autoksyms.sh diff --git a/Makefile b/Makefile index 451acbebee97..9f93d2595d25 100644 --- a/Makefile +++ b/Makefile @@ -933,6 +933,10 @@ quiet_cmd_link-vmlinux = LINK $@ # Include targets which we want to # execute if the rest of the kernel build went well. vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE +ifdef CONFIG_TRIM_UNUSED_KSYMS + $(Q)$(CONFIG_SHELL) scripts/adjust_autoksyms.sh \ + "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile autoksyms_recursive" +endif ifdef CONFIG_HEADERS_CHECK $(Q)$(MAKE) -f $(srctree)/Makefile headers_check endif @@ -947,6 +951,15 @@ ifdef CONFIG_GDB_SCRIPTS endif +$(call if_changed,link-vmlinux) +autoksyms_recursive: $(vmlinux-deps) + $(Q)$(CONFIG_SHELL) scripts/adjust_autoksyms.sh \ + "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile autoksyms_recursive" +PHONY += autoksyms_recursive + +# standalone target for easier testing +include/generated/autoksyms.h: FORCE + $(Q)$(CONFIG_SHELL) scripts/adjust_autoksyms.sh true + # The actual objects are generated when descending, # make sure no implicit rule kicks in $(sort $(vmlinux-deps)): $(vmlinux-dirs) ; diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh new file mode 100755 index 000000000000..5bf538f1ed79 --- /dev/null +++ b/scripts/adjust_autoksyms.sh @@ -0,0 +1,101 @@ +#!/bin/sh + +# Script to create/update include/generated/autoksyms.h and dependency files +# +# Copyright: (C) 2016 Linaro Limited +# Created by: Nicolas Pitre, January 2016 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. + +# Create/update the include/generated/autoksyms.h file from the list +# of all module's needed symbols as recorded on the third line of +# .tmp_versions/*.mod files. +# +# For each symbol being added or removed, the corresponding dependency +# file's timestamp is updated to force a rebuild of the affected source +# file. All arguments passed to this script are assumed to be a command +# to be exec'd to trigger a rebuild of those files. + +set -e + +cur_ksyms_file="include/generated/autoksyms.h" +new_ksyms_file="include/generated/autoksyms.h.tmpnew" + +info() { + if [ "$quiet" != "silent_" ]; then + printf " %-7s %s\n" "$1" "$2" + fi +} + +info "CHK" "$cur_ksyms_file" + +# Use "make V=1" to debug this script. +case "$KBUILD_VERBOSE" in +*1*) + set -x + ;; +esac + +# We need access to CONFIG_ symbols +case "${KCONFIG_CONFIG}" in +*/*) + . "${KCONFIG_CONFIG}" + ;; +*) + # Force using a file from the current directory + . "./${KCONFIG_CONFIG}" +esac + +# In case it doesn't exist yet... +if [ -e "$cur_ksyms_file" ]; then touch "$cur_ksyms_file"; fi + +# Generate a new ksym list file with symbols needed by the current +# set of modules. +cat > "$new_ksyms_file" << EOT +/* + * Automatically generated file; DO NOT EDIT. + */ + +EOT +sed -ns -e '3s/ /\n/gp' "$MODVERDIR"/*.mod | sort -u | +while read sym; do + if [ -n "$CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX" ]; then + sym="${sym#_}" + fi + echo "#define __KSYM_${sym} 1" +done >> "$new_ksyms_file" + +# Special case for modversions (see modpost.c) +if [ -n "$CONFIG_MODVERSIONS" ]; then + echo "#define __KSYM_module_layout 1" >> "$new_ksyms_file" +fi + +# Extract changes between old and new list and touch corresponding +# dependency files. +changed=$( +count=0 +sort "$cur_ksyms_file" "$new_ksyms_file" | uniq -u | +sed -n 's/^#define __KSYM_\(.*\) 1/\1/p' | tr "A-Z_" "a-z/" | +while read sympath; do + if [ -z "$sympath" ]; then continue; fi + depfile="include/config/ksym/${sympath}.h" + mkdir -p "$(dirname "$depfile")" + touch "$depfile" + echo $((count += 1)) +done | tail -1 ) +changed=${changed:-0} + +if [ $changed -gt 0 ]; then + # Replace the old list with tne new one + old=$(grep -c "^#define __KSYM_" "$cur_ksyms_file" || true) + new=$(grep -c "^#define __KSYM_" "$new_ksyms_file" || true) + info "KSYMS" "symbols: before=$old, after=$new, changed=$changed" + info "UPD" "$cur_ksyms_file" + mv -f "$new_ksyms_file" "$cur_ksyms_file" + # Then trigger a rebuild of affected source files + exec $@ +else + rm -f "$new_ksyms_file" +fi -- GitLab From dd92478a15fa3bfd746ee08b4ef59401c1537804 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 28 Feb 2016 22:00:00 -0500 Subject: [PATCH 0703/9938] kbuild: build sample modules along with the rest of the kernel Make sample modules in parallel with the rest of the kernel rather than having them built from the vmlinux target. This makes the build slightly faster, and those modules are properly considered when adjust_autoksyms.sh is executed. Signed-off-by: Nicolas Pitre --- Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9f93d2595d25..cec9539d3082 100644 --- a/Makefile +++ b/Makefile @@ -940,9 +940,6 @@ endif ifdef CONFIG_HEADERS_CHECK $(Q)$(MAKE) -f $(srctree)/Makefile headers_check endif -ifdef CONFIG_SAMPLES - $(Q)$(MAKE) $(build)=samples -endif ifdef CONFIG_BUILD_DOCSRC $(Q)$(MAKE) $(build)=Documentation endif @@ -960,6 +957,11 @@ PHONY += autoksyms_recursive include/generated/autoksyms.h: FORCE $(Q)$(CONFIG_SHELL) scripts/adjust_autoksyms.sh true +# Build samples along the rest of the kernel +ifdef CONFIG_SAMPLES +vmlinux-dirs += samples +endif + # The actual objects are generated when descending, # make sure no implicit rule kicks in $(sort $(vmlinux-deps)): $(vmlinux-dirs) ; -- GitLab From dbacb0ef670d057a2c52c0e1e642bab727f6b4cb Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 Jan 2016 21:51:05 -0500 Subject: [PATCH 0704/9938] kconfig option for TRIM_UNUSED_KSYMS The config option to enable it all. Signed-off-by: Nicolas Pitre Acked-by: Rusty Russell --- init/Kconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/init/Kconfig b/init/Kconfig index e0d26162432e..29d74d3f8044 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -2012,6 +2012,22 @@ config MODULE_COMPRESS_XZ endchoice +config TRIM_UNUSED_KSYMS + bool "Trim unused exported kernel symbols" + depends on MODULES && !UNUSED_SYMBOLS + help + The kernel and some modules make many symbols available for + other modules to use via EXPORT_SYMBOL() and variants. Depending + on the set of modules being selected in your kernel configuration, + many of those exported symbols might never be used. + + This option allows for unused exported symbols to be dropped from + the build. In turn, this provides the compiler more opportunities + (especially when using LTO) for optimizing the code and reducing + binary size. This might have some security advantages as well. + + If unsure say N. + endif # MODULES config MODULES_TREE_LOOKUP -- GitLab From eeb6f1ba921d413157282a573290c0eb57d549d7 Mon Sep 17 00:00:00 2001 From: Dominique van den Broeck Date: Tue, 29 Mar 2016 19:14:20 +0200 Subject: [PATCH 0705/9938] staging: fwserial: (coding style) Turning every "unsigned" into "unsigned int" Coding-style-only modifications to remove every warning saying: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Compiled against revision "next-20160327". (checkpatch.pl was updated to treat "UNSPECIFIED_INT" warnings as of commit a1ce18e4f941d20 ) Signed-off-by: Dominique van den Broeck Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/dma_fifo.c | 8 +++--- drivers/staging/fwserial/dma_fifo.h | 16 +++++------ drivers/staging/fwserial/fwserial.c | 38 +++++++++++++------------- drivers/staging/fwserial/fwserial.h | 42 ++++++++++++++--------------- 4 files changed, 53 insertions(+), 51 deletions(-) diff --git a/drivers/staging/fwserial/dma_fifo.c b/drivers/staging/fwserial/dma_fifo.c index 4cd3ed3ee141..8b23a553fd4a 100644 --- a/drivers/staging/fwserial/dma_fifo.c +++ b/drivers/staging/fwserial/dma_fifo.c @@ -35,7 +35,7 @@ /* * private helper fn to determine if check is in open interval (lo,hi) */ -static bool addr_check(unsigned check, unsigned lo, unsigned hi) +static bool addr_check(unsigned int check, unsigned int lo, unsigned int hi) { return check - (lo + 1) < (hi - 1) - lo; } @@ -64,7 +64,7 @@ void dma_fifo_init(struct dma_fifo *fifo) * The 'apparent' size will be rounded up to next greater aligned size. * Returns 0 if no error, otherwise an error code */ -int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned align, +int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned int align, int tx_limit, int open_limit, gfp_t gfp_mask) { int capacity; @@ -190,7 +190,7 @@ int dma_fifo_in(struct dma_fifo *fifo, const void *src, int n) */ int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended) { - unsigned len, n, ofs, l, limit; + unsigned int len, n, ofs, l, limit; if (!fifo->data) return -ENOENT; @@ -210,7 +210,7 @@ int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended) n = len; ofs = fifo->out % fifo->capacity; l = fifo->capacity - ofs; - limit = min_t(unsigned, l, fifo->tx_limit); + limit = min_t(unsigned int, l, fifo->tx_limit); if (n > limit) { n = limit; fifo->out += limit; diff --git a/drivers/staging/fwserial/dma_fifo.h b/drivers/staging/fwserial/dma_fifo.h index 410988224f89..37a91c6a1709 100644 --- a/drivers/staging/fwserial/dma_fifo.h +++ b/drivers/staging/fwserial/dma_fifo.h @@ -45,9 +45,9 @@ #define DMA_FIFO_GUARD 3 /* # of cache lines to reserve for the guard area */ struct dma_fifo { - unsigned in; - unsigned out; /* updated when dma is pended */ - unsigned done; /* updated upon dma completion */ + unsigned int in; + unsigned int out; /* updated when dma is pended */ + unsigned int done; /* updated upon dma completion */ struct { unsigned corrupt:1; }; @@ -55,7 +55,7 @@ struct dma_fifo { int guard; /* ofs of guard area */ int capacity; /* size + reserved */ int avail; /* # of unused bytes in fifo */ - unsigned align; /* must be power of 2 */ + unsigned int align; /* must be power of 2 */ int tx_limit; /* max # of bytes per dma transaction */ int open_limit; /* max # of outstanding allowed */ int open; /* # of outstanding dma transactions */ @@ -66,9 +66,9 @@ struct dma_fifo { struct dma_pending { struct list_head link; void *data; - unsigned len; - unsigned next; - unsigned out; + unsigned int len; + unsigned int next; + unsigned int out; }; static inline void dp_mark_completed(struct dma_pending *dp) @@ -82,7 +82,7 @@ static inline bool dp_is_completed(struct dma_pending *dp) } void dma_fifo_init(struct dma_fifo *fifo); -int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned align, +int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned int align, int tx_limit, int open_limit, gfp_t gfp_mask); void dma_fifo_free(struct dma_fifo *fifo); void dma_fifo_reset(struct dma_fifo *fifo); diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 9b23b5c95f5e..66e54e767c98 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -132,7 +132,7 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card, #ifdef FWTTY_PROFILING -static void fwtty_profile_fifo(struct fwtty_port *port, unsigned *stat) +static void fwtty_profile_fifo(struct fwtty_port *port, unsigned int *stat) { spin_lock_bh(&port->lock); fwtty_profile_data(stat, dma_fifo_avail(&port->tx_fifo)); @@ -143,7 +143,7 @@ static void fwtty_dump_profile(struct seq_file *m, struct stats *stats) { /* for each stat, print sum of 0 to 2^k, then individually */ int k = 4; - unsigned sum; + unsigned int sum; int j; char t[10]; @@ -303,9 +303,10 @@ static void fwtty_restart_tx(struct fwtty_port *port) * Note: in loopback, the port->lock is being held. Only use functions that * don't attempt to reclaim the port->lock. */ -static void fwtty_update_port_status(struct fwtty_port *port, unsigned status) +static void fwtty_update_port_status(struct fwtty_port *port, + unsigned int status) { - unsigned delta; + unsigned int delta; struct tty_struct *tty; /* simulated LSR/MSR status from remote */ @@ -396,9 +397,9 @@ static void fwtty_update_port_status(struct fwtty_port *port, unsigned status) * * Note: caller must be holding port lock */ -static unsigned __fwtty_port_line_status(struct fwtty_port *port) +static unsigned int __fwtty_port_line_status(struct fwtty_port *port) { - unsigned status = 0; + unsigned int status = 0; /* TODO: add module param to tie RNG to DTR as well */ @@ -424,7 +425,7 @@ static int __fwtty_write_port_status(struct fwtty_port *port) { struct fwtty_peer *peer; int err = -ENOENT; - unsigned status = __fwtty_port_line_status(port); + unsigned int status = __fwtty_port_line_status(port); rcu_read_lock(); peer = rcu_dereference(port->peer); @@ -454,7 +455,7 @@ static int fwtty_write_port_status(struct fwtty_port *port) static void fwtty_throttle_port(struct fwtty_port *port) { struct tty_struct *tty; - unsigned old; + unsigned int old; tty = tty_port_tty_get(&port->port); if (!tty) @@ -540,7 +541,7 @@ static void fwtty_emit_breaks(struct work_struct *work) static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len) { int c, n = len; - unsigned lsr; + unsigned int lsr; int err = 0; fwtty_dbg(port, "%d\n", n); @@ -635,7 +636,7 @@ static void fwtty_port_handler(struct fw_card *card, if (addr != port->rx_handler.offset || len != 4) { rcode = RCODE_ADDRESS_ERROR; } else { - fwtty_update_port_status(port, *(unsigned *)data); + fwtty_update_port_status(port, *(unsigned int *)data); rcode = RCODE_COMPLETE; } break; @@ -828,7 +829,7 @@ static void fwtty_write_xchar(struct fwtty_port *port, char ch) rcu_read_unlock(); } -static struct fwtty_port *fwtty_port_get(unsigned index) +static struct fwtty_port *fwtty_port_get(unsigned int index) { struct fwtty_port *port; @@ -934,9 +935,9 @@ static int fwtty_port_carrier_raised(struct tty_port *tty_port) return rc; } -static unsigned set_termios(struct fwtty_port *port, struct tty_struct *tty) +static unsigned int set_termios(struct fwtty_port *port, struct tty_struct *tty) { - unsigned baud, frame; + unsigned int baud, frame; baud = tty_termios_baud_rate(&tty->termios); tty_termios_encode_baud_rate(&tty->termios, baud, baud); @@ -988,7 +989,7 @@ static int fwtty_port_activate(struct tty_port *tty_port, struct tty_struct *tty) { struct fwtty_port *port = to_port(tty_port, port); - unsigned baud; + unsigned int baud; int err; set_bit(TTY_IO_ERROR, &tty->flags); @@ -1264,7 +1265,7 @@ static int set_serial_info(struct fwtty_port *port, return 0; } -static int fwtty_ioctl(struct tty_struct *tty, unsigned cmd, +static int fwtty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct fwtty_port *port = tty->driver_data; @@ -1297,7 +1298,7 @@ static int fwtty_ioctl(struct tty_struct *tty, unsigned cmd, static void fwtty_set_termios(struct tty_struct *tty, struct ktermios *old) { struct fwtty_port *port = tty->driver_data; - unsigned baud; + unsigned int baud; spin_lock_bh(&port->lock); baud = set_termios(port, tty); @@ -1369,7 +1370,7 @@ static int fwtty_break_ctl(struct tty_struct *tty, int state) static int fwtty_tiocmget(struct tty_struct *tty) { struct fwtty_port *port = tty->driver_data; - unsigned tiocm; + unsigned int tiocm; spin_lock_bh(&port->lock); tiocm = (port->mctrl & MCTRL_MASK) | (port->mstatus & ~MCTRL_MASK); @@ -1380,7 +1381,8 @@ static int fwtty_tiocmget(struct tty_struct *tty) return tiocm; } -static int fwtty_tiocmset(struct tty_struct *tty, unsigned set, unsigned clear) +static int fwtty_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct fwtty_port *port = tty->driver_data; diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index 6fa936501b3f..30b2481fe32b 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h @@ -22,7 +22,7 @@ #ifdef FWTTY_PROFILING #define DISTRIBUTION_MAX_SIZE 8192 #define DISTRIBUTION_MAX_INDEX (ilog2(DISTRIBUTION_MAX_SIZE) + 1) -static inline void fwtty_profile_data(unsigned stat[], unsigned val) +static inline void fwtty_profile_data(unsigned int stat[], unsigned int val) { int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0; ++stat[n]; @@ -78,7 +78,7 @@ struct fwtty_peer { u64 guid; int generation; int node_id; - unsigned speed; + unsigned int speed; int max_payload; u64 mgmt_addr; @@ -160,17 +160,17 @@ struct fwserial_mgmt_pkt { #define VIRT_CABLE_PLUG_TIMEOUT (60 * HZ) struct stats { - unsigned xchars; - unsigned dropped; - unsigned tx_stall; - unsigned fifo_errs; - unsigned sent; - unsigned lost; - unsigned throttled; - unsigned reads[DISTRIBUTION_MAX_INDEX + 1]; - unsigned writes[DISTRIBUTION_MAX_INDEX + 1]; - unsigned txns[DISTRIBUTION_MAX_INDEX + 1]; - unsigned unthrottle[DISTRIBUTION_MAX_INDEX + 1]; + unsigned int xchars; + unsigned int dropped; + unsigned int tx_stall; + unsigned int fifo_errs; + unsigned int sent; + unsigned int lost; + unsigned int throttled; + unsigned int reads[DISTRIBUTION_MAX_INDEX + 1]; + unsigned int writes[DISTRIBUTION_MAX_INDEX + 1]; + unsigned int txns[DISTRIBUTION_MAX_INDEX + 1]; + unsigned int unthrottle[DISTRIBUTION_MAX_INDEX + 1]; }; struct fwconsole_ops { @@ -237,7 +237,7 @@ struct fwconsole_ops { struct fwtty_port { struct tty_port port; struct device *device; - unsigned index; + unsigned int index; struct fw_serial *serial; struct fw_address_handler rx_handler; @@ -246,21 +246,21 @@ struct fwtty_port { wait_queue_head_t wait_tx; struct delayed_work emit_breaks; - unsigned cps; + unsigned int cps; unsigned long break_last; struct work_struct hangup; - unsigned mstatus; + unsigned int mstatus; spinlock_t lock; - unsigned mctrl; + unsigned int mctrl; struct delayed_work drain; struct dma_fifo tx_fifo; int max_payload; - unsigned status_mask; - unsigned ignore_mask; - unsigned break_ctl:1, + unsigned int status_mask; + unsigned int ignore_mask; + unsigned int break_ctl:1, write_only:1, overrun:1, loopback:1; @@ -349,7 +349,7 @@ extern struct tty_driver *fwtty_driver; * being used for isochronous traffic) * 2) isochronous arbitration always wins. */ -static inline int link_speed_to_max_payload(unsigned speed) +static inline int link_speed_to_max_payload(unsigned int speed) { /* Max async payload is 4096 - see IEEE 1394-2008 tables 6-4, 16-18 */ return min(512 << speed, 4096); -- GitLab From 7d47383dcb3f5867de56ac04ce46db06ac47ad0b Mon Sep 17 00:00:00 2001 From: Dominique van den Broeck Date: Tue, 29 Mar 2016 19:14:21 +0200 Subject: [PATCH 0706/9938] staging: fwserial: (coding style) removing "!= NULL" to comply with checkpatch.pl Removing two "!= NULL" from fwserial.c as suggested by checkpatch.pl. Note that the associated expression "port->port.console" is a 1-bit-field that is already assumed as an implicit boolean (that is: without comparison) Signed-off-by: Dominique van den Broeck Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 66e54e767c98..4dd5304cb718 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -1701,7 +1701,7 @@ static void fwserial_virt_plug_complete(struct fwtty_peer *peer, dma_fifo_change_tx_limit(&port->tx_fifo, port->max_payload); spin_unlock_bh(&peer->port->lock); - if (port->port.console && port->fwcon_ops->notify != NULL) + if (port->port.console && port->fwcon_ops->notify) (*port->fwcon_ops->notify)(FWCON_NOTIFY_ATTACH, port->con_data); fwtty_info(&peer->unit, "peer (guid:%016llx) connected on %s\n", @@ -1808,7 +1808,7 @@ static void fwserial_release_port(struct fwtty_port *port, bool reset) RCU_INIT_POINTER(port->peer, NULL); spin_unlock_bh(&port->lock); - if (port->port.console && port->fwcon_ops->notify != NULL) + if (port->port.console && port->fwcon_ops->notify) (*port->fwcon_ops->notify)(FWCON_NOTIFY_DETACH, port->con_data); } -- GitLab From f0e00da2db61c9052fbc07edf2b2bf615b7a4bbe Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 29 Mar 2016 17:53:23 +0100 Subject: [PATCH 0707/9938] staging: sm750fb: initialize max_d to maximum D value of 6 max_d is not initialized and should be set to the largest D value of 6. Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 95f7cae3cc23..f80ee776677f 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -306,7 +306,7 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) unsigned int input, request; unsigned int tmpClock, ret; const int max_OD = 3; - int max_d; + int max_d = 6; if (getChipType() == SM750LE) { /* SM750LE don't have prgrammable PLL and M/N values to work on. -- GitLab From 9fca845577c07e7bbd659625e03dfda8ebda4b91 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Sat, 26 Mar 2016 10:54:13 +0200 Subject: [PATCH 0708/9938] Staging: wlan-ng: removed "next" member of wlandevice_t since it is not used anywhere in code. This patch removes "next" member of wlandevice_t since it is not used anywhere in the wlan-ng code. Signed-off-by: Claudiu Beznea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211netdev.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 810ee68aa18e..820a0e20a941 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -158,7 +158,6 @@ extern int wlan_wext_write; /* WLAN device type */ typedef struct wlandevice { - struct wlandevice *next; /* link for list of devices */ void *priv; /* private data for MSD */ /* Subsystem State */ -- GitLab From 45a91e8f767afbbffff46bf7251f81d15d121136 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Mar 2016 16:33:42 -0700 Subject: [PATCH 0709/9938] regulator: core: Log when we bring constraints into range This aids in debugging problems triggered by the regulator core applying its constraints, we could potentially crash immediately after updating the voltage if the constraints are buggy. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 881c37e61f75..18dd7ee61455 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -935,6 +935,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, } if (target_min != current_uV || target_max != current_uV) { + rdev_info(rdev, "Bringing %duV into %d-%duV\n", + current_uV, target_min, target_max); ret = _regulator_do_set_voltage( rdev, target_min, target_max); if (ret < 0) { -- GitLab From 86d3f367686852cde028cf6c12cb0e944f28a784 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 9 Mar 2016 20:39:57 +0800 Subject: [PATCH 0710/9938] gpio: menz127: Drop *mdev field from struct men_z127_gpio No need to store *medv in struct men_z127_gpio. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-menz127.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index a68e199d579d..8c1ab8e1974f 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -35,7 +35,6 @@ struct men_z127_gpio { struct gpio_chip gc; void __iomem *reg_base; - struct mcb_device *mdev; struct resource *mem; spinlock_t lock; }; @@ -44,7 +43,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, unsigned debounce) { struct men_z127_gpio *priv = gpiochip_get_data(gc); - struct device *dev = &priv->mdev->dev; + struct device *dev = gc->parent; unsigned int rnd; u32 db_en, db_cnt; @@ -136,7 +135,6 @@ static int men_z127_probe(struct mcb_device *mdev, goto err_release; } - men_z127_gpio->mdev = mdev; mcb_set_drvdata(mdev, men_z127_gpio); ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4, -- GitLab From f85834229b1808781b0b56a9d637e19312916300 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 9 Mar 2016 20:48:15 +0800 Subject: [PATCH 0711/9938] gpio: mb86s7x: Remove redundant platform_set_drvdata() call Set it once is enough, so remove the second platform_set_drvdata() call. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mb86s7x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index 7fffc1d6c055..d23a94231a20 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -185,8 +185,6 @@ static int mb86s70_gpio_probe(struct platform_device *pdev) gchip->gc.parent = &pdev->dev; gchip->gc.base = -1; - platform_set_drvdata(pdev, gchip); - ret = gpiochip_add_data(&gchip->gc, gchip); if (ret) { dev_err(&pdev->dev, "couldn't register gpio driver\n"); -- GitLab From dbb763b8ea5d8eb0ce3e45e289969f6f1f418921 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:21:44 +0100 Subject: [PATCH 0712/9938] gpio: rcar: Implement gpiochip.set_multiple() This allows to set multiple outputs using a single register write. Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d9ab0cd1d205..3fe8e773d95c 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -336,6 +336,25 @@ static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value) spin_unlock_irqrestore(&p->lock, flags); } +static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct gpio_rcar_priv *p = gpiochip_get_data(chip); + unsigned long flags; + u32 val, bankmask; + + bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); + if (!bankmask) + return; + + spin_lock_irqsave(&p->lock, flags); + val = gpio_rcar_read(p, OUTDT); + val &= ~bankmask; + val |= (bankmask & bits[0]); + gpio_rcar_write(p, OUTDT, val); + spin_unlock_irqrestore(&p->lock, flags); +} + static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -476,6 +495,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) gpio_chip->get = gpio_rcar_get; gpio_chip->direction_output = gpio_rcar_direction_output; gpio_chip->set = gpio_rcar_set; + gpio_chip->set_multiple = gpio_rcar_set_multiple; gpio_chip->label = name; gpio_chip->parent = dev; gpio_chip->owner = THIS_MODULE; -- GitLab From d46ab6823963de2165f5a2af7600ce830e990e53 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:19:18 +0100 Subject: [PATCH 0713/9938] gpio: 74x164: Implement gpiochip.set_multiple() This allows to set multiple outputs using a single SPI transfer. Signed-off-by: Geert Uytterhoeven Reviewed-by: Phil Reid Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74x164.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index c81224ff2dca..62291a81c97f 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -75,6 +75,29 @@ static void gen_74x164_set_value(struct gpio_chip *gc, mutex_unlock(&chip->lock); } +static void gen_74x164_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + struct gen_74x164_chip *chip = gpiochip_get_data(gc); + unsigned int i, idx, shift; + u8 bank, bankmask; + + mutex_lock(&chip->lock); + for (i = 0, bank = chip->registers - 1; i < chip->registers; + i++, bank--) { + idx = i / sizeof(*mask); + shift = i % sizeof(*mask) * BITS_PER_BYTE; + bankmask = mask[idx] >> shift; + if (!bankmask) + continue; + + chip->buffer[bank] &= ~bankmask; + chip->buffer[bank] |= bankmask & (bits[idx] >> shift); + } + __gen_74x164_write_config(chip); + mutex_unlock(&chip->lock); +} + static int gen_74x164_direction_output(struct gpio_chip *gc, unsigned offset, int val) { @@ -114,6 +137,7 @@ static int gen_74x164_probe(struct spi_device *spi) chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; + chip->gpio_chip.set_multiple = gen_74x164_set_multiple; chip->gpio_chip.base = -1; chip->registers = nregs; -- GitLab From dad3d272957b006b9069486597610840f7063350 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Fri, 18 Mar 2016 16:07:06 +0800 Subject: [PATCH 0714/9938] gpio: mcp23s08: switch to use gpiolib irqchip helpers This switches the mcp23s08 driver to use the gpiolib irqchip helpers. Signed-off-by: Phil Reid Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mcp23s08.c | 85 +++++++++++++----------------------- 2 files changed, 31 insertions(+), 55 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5f3429f0bf46..927be87f2284 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1091,6 +1091,7 @@ menu "SPI or I2C GPIO expanders" config GPIO_MCP23S08 tristate "Microchip MCP23xxx I/O expander" + select GPIOLIB_IRQCHIP help SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 I/O expanders. diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 47e486910aab..ae61bc2d9d25 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -77,7 +77,6 @@ struct mcp23s08 { /* lock protects the cached values */ struct mutex lock; struct mutex irq_lock; - struct irq_domain *irq_domain; struct gpio_chip chip; @@ -96,11 +95,6 @@ struct mcp23s08_driver_data { struct mcp23s08 chip[]; }; -/* This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - /*----------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_I2C) @@ -369,7 +363,7 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) if ((BIT(i) & mcp->cache[MCP_INTF]) && ((BIT(i) & intcap & mcp->irq_rise) || (mcp->irq_fall & ~intcap & BIT(i)))) { - child_irq = irq_find_mapping(mcp->irq_domain, i); + child_irq = irq_find_mapping(mcp->chip.irqdomain, i); handle_nested_irq(child_irq); } } @@ -377,16 +371,10 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) return IRQ_HANDLED; } -static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct mcp23s08 *mcp = gpiochip_get_data(chip); - - return irq_find_mapping(mcp->irq_domain, offset); -} - static void mcp23s08_irq_mask(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; mcp->cache[MCP_GPINTEN] &= ~BIT(pos); @@ -394,7 +382,8 @@ static void mcp23s08_irq_mask(struct irq_data *data) static void mcp23s08_irq_unmask(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; mcp->cache[MCP_GPINTEN] |= BIT(pos); @@ -402,7 +391,8 @@ static void mcp23s08_irq_unmask(struct irq_data *data) static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; int status = 0; @@ -426,14 +416,16 @@ static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) static void mcp23s08_irq_bus_lock(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); mutex_lock(&mcp->irq_lock); } static void mcp23s08_irq_bus_unlock(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); mutex_lock(&mcp->lock); mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]); @@ -445,7 +437,8 @@ static void mcp23s08_irq_bus_unlock(struct irq_data *data) static int mcp23s08_irq_reqres(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) { dev_err(mcp->chip.parent, @@ -459,7 +452,8 @@ static int mcp23s08_irq_reqres(struct irq_data *data) static void mcp23s08_irq_relres(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); gpiochip_unlock_as_irq(&mcp->chip, data->hwirq); } @@ -478,17 +472,11 @@ static struct irq_chip mcp23s08_irq_chip = { static int mcp23s08_irq_setup(struct mcp23s08 *mcp) { struct gpio_chip *chip = &mcp->chip; - int err, irq, j; + int err; unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED; mutex_init(&mcp->irq_lock); - mcp->irq_domain = irq_domain_add_linear(chip->parent->of_node, - chip->ngpio, - &irq_domain_simple_ops, mcp); - if (!mcp->irq_domain) - return -ENODEV; - if (mcp->irq_active_high) irqflags |= IRQF_TRIGGER_HIGH; else @@ -503,30 +491,23 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) return err; } - chip->to_irq = mcp23s08_gpio_to_irq; - - for (j = 0; j < mcp->chip.ngpio; j++) { - irq = irq_create_mapping(mcp->irq_domain, j); - irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_data(irq, mcp); - irq_set_chip(irq, &mcp23s08_irq_chip); - irq_set_nested_thread(irq, true); - irq_set_noprobe(irq); + err = gpiochip_irqchip_add(chip, + &mcp23s08_irq_chip, + 0, + handle_simple_irq, + IRQ_TYPE_NONE); + if (err) { + dev_err(chip->parent, + "could not connect irqchip to gpiochip: %d\n", err); + return err; } - return 0; -} -static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) -{ - unsigned int irq, i; + gpiochip_set_chained_irqchip(chip, + &mcp23s08_irq_chip, + mcp->irq, + NULL); - for (i = 0; i < mcp->chip.ngpio; i++) { - irq = irq_find_mapping(mcp->irq_domain, i); - if (irq > 0) - irq_dispose_mapping(irq); - } - - irq_domain_remove(mcp->irq_domain); + return 0; } /*----------------------------------------------------------------------*/ @@ -721,7 +702,6 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, if (mcp->irq && mcp->irq_controller) { status = mcp23s08_irq_setup(mcp); if (status) { - mcp23s08_irq_teardown(mcp); goto fail; } } @@ -847,9 +827,6 @@ static int mcp230xx_remove(struct i2c_client *client) { struct mcp23s08 *mcp = i2c_get_clientdata(client); - if (client->irq && mcp->irq_controller) - mcp23s08_irq_teardown(mcp); - gpiochip_remove(&mcp->chip); kfree(mcp); @@ -1017,8 +994,6 @@ static int mcp23s08_remove(struct spi_device *spi) if (!data->mcp[addr]) continue; - if (spi->irq && data->mcp[addr]->irq_controller) - mcp23s08_irq_teardown(data->mcp[addr]); gpiochip_remove(&data->mcp[addr]->chip); } -- GitLab From f7aed67d632f6e316b9a9e2fe2818a07bfa42e81 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 22 Mar 2016 14:28:34 +0100 Subject: [PATCH 0715/9938] gpio: mcp23s08: delete req/rel_resource callbacks When using the GPIOLIB_IRQCHIP the gpiolib provides a straight-forward implementation of request/release resources, rely on that instead. Cc: Phil Reid Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mcp23s08.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index ae61bc2d9d25..c882c2be5a0e 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -435,29 +435,6 @@ static void mcp23s08_irq_bus_unlock(struct irq_data *data) mutex_unlock(&mcp->irq_lock); } -static int mcp23s08_irq_reqres(struct irq_data *data) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(data); - struct mcp23s08 *mcp = gpiochip_get_data(gc); - - if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) { - dev_err(mcp->chip.parent, - "unable to lock HW IRQ %lu for IRQ usage\n", - data->hwirq); - return -EINVAL; - } - - return 0; -} - -static void mcp23s08_irq_relres(struct irq_data *data) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(data); - struct mcp23s08 *mcp = gpiochip_get_data(gc); - - gpiochip_unlock_as_irq(&mcp->chip, data->hwirq); -} - static struct irq_chip mcp23s08_irq_chip = { .name = "gpio-mcp23xxx", .irq_mask = mcp23s08_irq_mask, @@ -465,8 +442,6 @@ static struct irq_chip mcp23s08_irq_chip = { .irq_set_type = mcp23s08_irq_set_type, .irq_bus_lock = mcp23s08_irq_bus_lock, .irq_bus_sync_unlock = mcp23s08_irq_bus_unlock, - .irq_request_resources = mcp23s08_irq_reqres, - .irq_release_resources = mcp23s08_irq_relres, }; static int mcp23s08_irq_setup(struct mcp23s08 *mcp) -- GitLab From 574b782e7b632974e85e8629842746d0229c4aed Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 29 Feb 2016 22:00:01 +0800 Subject: [PATCH 0716/9938] gpio: amdpt: Convert to use gpio-generic Use gpio-generic to simplify this driver. Signed-off-by: Axel Lin Tested-by: YD Tseng Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-amdpt.c | 122 +++++--------------------------------- 2 files changed, 15 insertions(+), 108 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 927be87f2284..6d6015f7aeed 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -122,6 +122,7 @@ config GPIO_ALTERA config GPIO_AMDPT tristate "AMD Promontory GPIO support" depends on ACPI + select GPIO_GENERIC help driver for GPIO functionality on Promontory IOHub Require ACPI ASL code to enumerate as a platform device. diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index c2484046e8e9..569b424efb5a 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -28,7 +28,6 @@ struct pt_gpio_chip { struct gpio_chip gc; void __iomem *reg_base; - spinlock_t lock; }; static int pt_gpio_request(struct gpio_chip *gc, unsigned offset) @@ -39,19 +38,19 @@ static int pt_gpio_request(struct gpio_chip *gc, unsigned offset) dev_dbg(gc->parent, "pt_gpio_request offset=%x\n", offset); - spin_lock_irqsave(&pt_gpio->lock, flags); + spin_lock_irqsave(&gc->bgpio_lock, flags); using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); if (using_pins & BIT(offset)) { dev_warn(gc->parent, "PT GPIO pin %x reconfigured\n", offset); - spin_unlock_irqrestore(&pt_gpio->lock, flags); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); return -EINVAL; } writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG); - spin_unlock_irqrestore(&pt_gpio->lock, flags); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); return 0; } @@ -62,111 +61,17 @@ static void pt_gpio_free(struct gpio_chip *gc, unsigned offset) unsigned long flags; u32 using_pins; - spin_lock_irqsave(&pt_gpio->lock, flags); + spin_lock_irqsave(&gc->bgpio_lock, flags); using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); using_pins &= ~BIT(offset); writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG); - spin_unlock_irqrestore(&pt_gpio->lock, flags); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); dev_dbg(gc->parent, "pt_gpio_free offset=%x\n", offset); } -static void pt_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - dev_dbg(gc->parent, "pt_gpio_set_value offset=%x, value=%x\n", - offset, value); - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); - data &= ~BIT(offset); - if (value) - data |= BIT(offset); - writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); -} - -static int pt_gpio_get_value(struct gpio_chip *gc, unsigned offset) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); - - /* configure as output */ - if (data & BIT(offset)) - data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); - else /* configure as input */ - data = readl(pt_gpio->reg_base + PT_INPUTDATA_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); - - data >>= offset; - data &= 1; - - dev_dbg(gc->parent, "pt_gpio_get_value offset=%x, value=%x\n", - offset, data); - - return data; -} - -static int pt_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - dev_dbg(gc->parent, "pt_gpio_dirction_input offset=%x\n", offset); - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); - data &= ~BIT(offset); - writel(data, pt_gpio->reg_base + PT_DIRECTION_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); - - return 0; -} - -static int pt_gpio_direction_output(struct gpio_chip *gc, - unsigned offset, int value) -{ - struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); - unsigned long flags; - u32 data; - - dev_dbg(gc->parent, "pt_gpio_direction_output offset=%x, value=%x\n", - offset, value); - - spin_lock_irqsave(&pt_gpio->lock, flags); - - data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG); - if (value) - data |= BIT(offset); - else - data &= ~BIT(offset); - writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG); - - data = readl(pt_gpio->reg_base + PT_DIRECTION_REG); - data |= BIT(offset); - writel(data, pt_gpio->reg_base + PT_DIRECTION_REG); - - spin_unlock_irqrestore(&pt_gpio->lock, flags); - - return 0; -} - static int pt_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -196,18 +101,19 @@ static int pt_gpio_probe(struct platform_device *pdev) return PTR_ERR(pt_gpio->reg_base); } - spin_lock_init(&pt_gpio->lock); + ret = bgpio_init(&pt_gpio->gc, dev, 4, + pt_gpio->reg_base + PT_INPUTDATA_REG, + pt_gpio->reg_base + PT_OUTPUTDATA_REG, NULL, + pt_gpio->reg_base + PT_DIRECTION_REG, NULL, + BGPIOF_READ_OUTPUT_REG_SET); + if (ret) { + dev_err(&pdev->dev, "bgpio_init failed\n"); + return ret; + } - pt_gpio->gc.label = pdev->name; pt_gpio->gc.owner = THIS_MODULE; - pt_gpio->gc.parent = dev; pt_gpio->gc.request = pt_gpio_request; pt_gpio->gc.free = pt_gpio_free; - pt_gpio->gc.direction_input = pt_gpio_direction_input; - pt_gpio->gc.direction_output = pt_gpio_direction_output; - pt_gpio->gc.get = pt_gpio_get_value; - pt_gpio->gc.set = pt_gpio_set_value; - pt_gpio->gc.base = -1; pt_gpio->gc.ngpio = PT_TOTAL_GPIO; #if defined(CONFIG_OF_GPIO) pt_gpio->gc.of_node = pdev->dev.of_node; -- GitLab From 592569de4c247fe4f25db8369dc0c63860f9560b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 18 Mar 2016 21:05:16 +0800 Subject: [PATCH 0717/9938] gpio: octeon: Convert to use devm_ioremap_resource Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-octeon.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 47aead1ed1cc..9373d4e09185 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -83,6 +83,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) struct octeon_gpio *gpio; struct gpio_chip *chip; struct resource *res_mem; + void __iomem *reg_base; int err = 0; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -91,21 +92,11 @@ static int octeon_gpio_probe(struct platform_device *pdev) chip = &gpio->chip; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res_mem == NULL) { - dev_err(&pdev->dev, "found no memory resource\n"); - err = -ENXIO; - goto out; - } - if (!devm_request_mem_region(&pdev->dev, res_mem->start, - resource_size(res_mem), - res_mem->name)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - err = -ENXIO; - goto out; - } - gpio->register_base = (u64)devm_ioremap(&pdev->dev, res_mem->start, - resource_size(res_mem)); + reg_base = devm_ioremap_resource(&pdev->dev, res_mem); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + gpio->register_base = (u64)reg_base; pdev->dev.platform_data = chip; chip->label = "octeon-gpio"; chip->parent = &pdev->dev; @@ -119,11 +110,10 @@ static int octeon_gpio_probe(struct platform_device *pdev) chip->set = octeon_gpio_set; err = devm_gpiochip_add_data(&pdev->dev, chip, gpio); if (err) - goto out; + return err; dev_info(&pdev->dev, "OCTEON GPIO driver probed.\n"); -out: - return err; + return 0; } static struct of_device_id octeon_gpio_match[] = { -- GitLab From b6d055b198b70c430a0b7e78280e8ef35e44f319 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 18 Mar 2016 21:06:06 +0800 Subject: [PATCH 0718/9938] gpio: octeon: Constify octeon_gpio_match table Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-octeon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 9373d4e09185..96a8a8cb2729 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -116,7 +116,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) return 0; } -static struct of_device_id octeon_gpio_match[] = { +static const struct of_device_id octeon_gpio_match[] = { { .compatible = "cavium,octeon-3860-gpio", }, -- GitLab From ca27379f5d2956e08558fbfc0d35b3ba64abbe0c Mon Sep 17 00:00:00 2001 From: YD Tseng Date: Thu, 17 Mar 2016 11:35:57 +0800 Subject: [PATCH 0719/9938] gpio: amdpt: Add a new ACPI HID This patch adds a new ACPI HID, AMDIF030, in the pt_gpio_acpi_match. Signed-off-by: YD Tseng Signed-off-by: Linus Walleij --- drivers/gpio/gpio-amdpt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index 569b424efb5a..9b78dc837603 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -145,6 +145,7 @@ static int pt_gpio_remove(struct platform_device *pdev) static const struct acpi_device_id pt_gpio_acpi_match[] = { { "AMDF030", 0 }, + { "AMDIF030", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match); -- GitLab From e99190cea39022690193938ff3e80d2faa98f389 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 14:49:42 +0100 Subject: [PATCH 0720/9938] powerpc: mpc52xx_gpt: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index 3048e34db6d8..22645a7c6b8a 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -278,14 +278,9 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) * GPIOLIB hooks */ #if defined(CONFIG_GPIOLIB) -static inline struct mpc52xx_gpt_priv *gc_to_mpc52xx_gpt(struct gpio_chip *gc) -{ - return container_of(gc, struct mpc52xx_gpt_priv, gc); -} - static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio) { - struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc); + struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc); return (in_be32(&gpt->regs->status) >> 8) & 1; } @@ -293,7 +288,7 @@ static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio) static void mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v) { - struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc); + struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc); unsigned long flags; u32 r; @@ -307,7 +302,7 @@ mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v) static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { - struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc); + struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc); unsigned long flags; dev_dbg(gpt->dev, "%s: gpio:%d\n", __func__, gpio); @@ -354,9 +349,9 @@ mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK, MPC52xx_GPT_MODE_MS_GPIO); - rc = gpiochip_add(&gpt->gc); + rc = gpiochip_add_data(&gpt->gc, gpt); if (rc) - dev_err(gpt->dev, "gpiochip_add() failed; rc=%i\n", rc); + dev_err(gpt->dev, "gpiochip_add_data() failed; rc=%i\n", rc); dev_dbg(gpt->dev, "%s() complete.\n", __func__); } -- GitLab From da5f767ef66a4c71109fdb8577b36864abc3263c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 14:54:45 +0100 Subject: [PATCH 0721/9938] powerpc: mpc8349emitx: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c index 15e8021ddef9..dbcd0303afed 100644 --- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c +++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -99,7 +99,7 @@ static void mcu_power_off(void) static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { - struct mcu *mcu = container_of(gc, struct mcu, gc); + struct mcu *mcu = gpiochip_get_data(gc); u8 bit = 1 << (4 + gpio); mutex_lock(&mcu->lock); @@ -136,7 +136,7 @@ static int mcu_gpiochip_add(struct mcu *mcu) gc->direction_output = mcu_gpio_dir_out; gc->of_node = np; - return gpiochip_add(gc); + return gpiochip_add_data(gc, mcu); } static int mcu_gpiochip_remove(struct mcu *mcu) -- GitLab From e65078f1f3490c753f8c223b088e8a482968b891 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:00:49 +0100 Subject: [PATCH 0722/9938] powerpc: sysdev: cpm1: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- arch/powerpc/sysdev/cpm1.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 8ed65365be50..6c110994d902 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -532,15 +532,9 @@ struct cpm1_gpio16_chip { u16 cpdata; }; -static inline struct cpm1_gpio16_chip * -to_cpm1_gpio16_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct cpm1_gpio16_chip, mm_gc); -} - static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; cpm1_gc->cpdata = in_be16(&iop->dat); @@ -560,7 +554,7 @@ static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio) static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, int value) { - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; if (value) @@ -574,7 +568,7 @@ static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); unsigned long flags; u16 pin_mask = 1 << (15 - gpio); @@ -588,7 +582,7 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; unsigned long flags; u16 pin_mask = 1 << (15 - gpio); @@ -606,7 +600,7 @@ static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport16 __iomem *iop = mm_gc->regs; unsigned long flags; u16 pin_mask = 1 << (15 - gpio); @@ -642,7 +636,7 @@ int cpm1_gpiochip_add16(struct device_node *np) gc->get = cpm1_gpio16_get; gc->set = cpm1_gpio16_set; - return of_mm_gpiochip_add(np, mm_gc); + return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc); } struct cpm1_gpio32_chip { @@ -653,15 +647,9 @@ struct cpm1_gpio32_chip { u32 cpdata; }; -static inline struct cpm1_gpio32_chip * -to_cpm1_gpio32_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct cpm1_gpio32_chip, mm_gc); -} - static void cpm1_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; cpm1_gc->cpdata = in_be32(&iop->dat); @@ -681,7 +669,7 @@ static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio) static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, int value) { - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; if (value) @@ -695,7 +683,7 @@ static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -709,7 +697,7 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -727,7 +715,7 @@ static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); + struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); struct cpm_ioport32b __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -763,7 +751,7 @@ int cpm1_gpiochip_add32(struct device_node *np) gc->get = cpm1_gpio32_get; gc->set = cpm1_gpio32_set; - return of_mm_gpiochip_add(np, mm_gc); + return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc); } static int cpm_init_par_io(void) -- GitLab From a14a2d484b386972f9027246dbe5d066519edb9f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:05:43 +0100 Subject: [PATCH 0723/9938] powerpc: cpm_common: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- arch/powerpc/sysdev/cpm_common.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index 9d32465eddb1..0ac12e5fd8ab 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c @@ -80,15 +80,9 @@ struct cpm2_gpio32_chip { u32 cpdata; }; -static inline struct cpm2_gpio32_chip * -to_cpm2_gpio32_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct cpm2_gpio32_chip, mm_gc); -} - static void cpm2_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(&mm_gc->gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; cpm2_gc->cpdata = in_be32(&iop->dat); @@ -108,7 +102,7 @@ static int cpm2_gpio32_get(struct gpio_chip *gc, unsigned int gpio) static void __cpm2_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, int value) { - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(&mm_gc->gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; if (value) @@ -122,7 +116,7 @@ static void __cpm2_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc); unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -136,7 +130,7 @@ static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -154,7 +148,7 @@ static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); + struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc); struct cpm2_ioports __iomem *iop = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (31 - gpio); @@ -190,6 +184,6 @@ int cpm2_gpiochip_add32(struct device_node *np) gc->get = cpm2_gpio32_get; gc->set = cpm2_gpio32_set; - return of_mm_gpiochip_add(np, mm_gc); + return of_mm_gpiochip_add_data(np, mm_gc, cpm2_gc); } #endif /* CONFIG_CPM2 || CONFIG_8xx_GPIO */ -- GitLab From 0d36fe65f58391712e11a6621075f373216e5f00 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:34:12 +0100 Subject: [PATCH 0724/9938] powerpc: ppc4xx: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- arch/powerpc/sysdev/ppc4xx_gpio.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/sysdev/ppc4xx_gpio.c b/arch/powerpc/sysdev/ppc4xx_gpio.c index d7a7ef135b9f..4ab83cd04785 100644 --- a/arch/powerpc/sysdev/ppc4xx_gpio.c +++ b/arch/powerpc/sysdev/ppc4xx_gpio.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include @@ -67,12 +67,6 @@ struct ppc4xx_gpio_chip { * There are a maximum of 32 gpios in each gpio controller. */ -static inline struct ppc4xx_gpio_chip * -to_ppc4xx_gpiochip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct ppc4xx_gpio_chip, mm_gc); -} - static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); @@ -97,7 +91,7 @@ static void ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); + struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&chip->lock, flags); @@ -112,7 +106,7 @@ ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); + struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); struct ppc4xx_gpio __iomem *regs = mm_gc->regs; unsigned long flags; @@ -142,7 +136,7 @@ static int ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); + struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); struct ppc4xx_gpio __iomem *regs = mm_gc->regs; unsigned long flags; @@ -200,7 +194,7 @@ static int __init ppc4xx_add_gpiochips(void) gc->get = ppc4xx_gpio_get; gc->set = ppc4xx_gpio_set; - ret = of_mm_gpiochip_add(np, mm_gc); + ret = of_mm_gpiochip_add_data(np, mm_gc, ppc4xx_gc); if (ret) goto err; continue; -- GitLab From 1e714e54b5ca5bfc75bc43ed41f8217242e831fe Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:49:10 +0100 Subject: [PATCH 0725/9938] powerpc: qe_lib-gpio: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- drivers/soc/fsl/qe/gpio.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 65845712571c..333eb2215a57 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -18,6 +18,8 @@ #include #include #include +#include +/* FIXME: needed for gpio_to_chip() get rid of this */ #include #include #include @@ -37,15 +39,9 @@ struct qe_gpio_chip { struct qe_pio_regs saved_regs; }; -static inline struct qe_gpio_chip * -to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct qe_gpio_chip, mm_gc); -} - static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(&mm_gc->gc); struct qe_pio_regs __iomem *regs = mm_gc->regs; qe_gc->cpdata = in_be32(®s->cpdata); @@ -69,7 +65,7 @@ static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); struct qe_pio_regs __iomem *regs = mm_gc->regs; unsigned long flags; u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); @@ -89,7 +85,7 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&qe_gc->lock, flags); @@ -104,7 +100,7 @@ static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; qe_gpio_set(gc, gpio, val); @@ -165,7 +161,7 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) } mm_gc = to_of_mm_gpio_chip(gc); - qe_gc = to_qe_gpio_chip(mm_gc); + qe_gc = gpiochip_get_data(gc); spin_lock_irqsave(&qe_gc->lock, flags); @@ -302,7 +298,7 @@ static int __init qe_add_gpiochips(void) gc->get = qe_gpio_get; gc->set = qe_gpio_set; - ret = of_mm_gpiochip_add(np, mm_gc); + ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc); if (ret) goto err; continue; -- GitLab From 937daafca774b05633f436c19885c8cb3cbdcc8a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:53:29 +0100 Subject: [PATCH 0726/9938] powerpc: simple-gpio: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Anton Vorontsov Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- arch/powerpc/sysdev/simple_gpio.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c index 56ce8ca3281b..ef470b470b04 100644 --- a/arch/powerpc/sysdev/simple_gpio.c +++ b/arch/powerpc/sysdev/simple_gpio.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include "simple_gpio.h" @@ -32,11 +32,6 @@ struct u8_gpio_chip { u8 data; }; -static struct u8_gpio_chip *to_u8_gpio_chip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct u8_gpio_chip, mm_gc); -} - static u8 u8_pin2mask(unsigned int pin) { return 1 << (8 - 1 - pin); @@ -52,7 +47,7 @@ static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio) static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); + struct u8_gpio_chip *u8_gc = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&u8_gc->lock, flags); @@ -80,7 +75,7 @@ static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc); + struct u8_gpio_chip *u8_gc = gpiochip_get_data(&mm_gc->gc); u8_gc->data = in_8(mm_gc->regs); } @@ -108,7 +103,7 @@ static int __init u8_simple_gpiochip_add(struct device_node *np) gc->get = u8_gpio_get; gc->set = u8_gpio_set; - ret = of_mm_gpiochip_add(np, mm_gc); + ret = of_mm_gpiochip_add_data(np, mm_gc, u8_gc); if (ret) goto err; return 0; -- GitLab From a8cb826aeab84553a30af22ca6d6b95a6513adb2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 15:58:33 +0100 Subject: [PATCH 0727/9938] sh: sdk7786-gpio: switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Cc: Paul Mundt Cc: linux-sh@vger.kernel.org Signed-off-by: Linus Walleij --- arch/sh/boards/mach-sdk7786/gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/boards/mach-sdk7786/gpio.c b/arch/sh/boards/mach-sdk7786/gpio.c index f71ce09d4e15..47997010b77a 100644 --- a/arch/sh/boards/mach-sdk7786/gpio.c +++ b/arch/sh/boards/mach-sdk7786/gpio.c @@ -9,7 +9,7 @@ */ #include #include -#include +#include #include #include #include @@ -44,6 +44,6 @@ static struct gpio_chip usrgpir_gpio_chip = { static int __init usrgpir_gpio_setup(void) { - return gpiochip_add(&usrgpir_gpio_chip); + return gpiochip_add_data(&usrgpir_gpio_chip, NULL); } device_initcall(usrgpir_gpio_setup); -- GitLab From efed58f1c574a31c03447afffe69440e83fdf84d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:02:00 +0100 Subject: [PATCH 0728/9938] sh: x3proto-gpio: switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Cc: Paul Mundt Cc: linux-sh@vger.kernel.org Signed-off-by: Linus Walleij --- arch/sh/boards/mach-x3proto/gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c index 1fb2cbee25f2..cea88b0effa2 100644 --- a/arch/sh/boards/mach-x3proto/gpio.c +++ b/arch/sh/boards/mach-x3proto/gpio.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include @@ -107,7 +107,7 @@ int __init x3proto_gpio_setup(void) if (unlikely(ilsel < 0)) return ilsel; - ret = gpiochip_add(&x3proto_gpio_chip); + ret = gpiochip_add_data(&x3proto_gpio_chip, NULL); if (unlikely(ret)) goto err_gpio; -- GitLab From fd19f534ab7660883191d5f3c9d01f0c6f444aea Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:07:09 +0100 Subject: [PATCH 0729/9938] unicore32: gpio: switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Acked-by: Guan Xuetao Signed-off-by: Linus Walleij --- arch/unicore32/kernel/gpio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c index 5ab23794ea17..49347a0e9288 100644 --- a/arch/unicore32/kernel/gpio.c +++ b/arch/unicore32/kernel/gpio.c @@ -14,6 +14,8 @@ #include #include +#include +/* FIXME: needed for gpio_set_value() - convert to use descriptors or hogs */ #include #include @@ -118,5 +120,5 @@ void __init puv3_init_gpio(void) * gpio_set_value(GPO_SET_V2, 1); */ #endif - gpiochip_add(&puv3_gpio_chip); + gpiochip_add_data(&puv3_gpio_chip, NULL); } -- GitLab From 839850f4fb76b56fcad3cabe27fc9f1a03821a2c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:32:08 +0100 Subject: [PATCH 0730/9938] input: adp5589-keys: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Acked-by: Michael Hennerich Acked-by: Dmitry Torokhov Signed-off-by: Linus Walleij --- drivers/input/keyboard/adp5589-keys.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index c01a1d648f9f..32d94c63dc33 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -387,7 +387,7 @@ static int adp5589_write(struct i2c_client *client, u8 reg, u8 val) #ifdef CONFIG_GPIOLIB static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); @@ -399,7 +399,7 @@ static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) static void adp5589_gpio_set_value(struct gpio_chip *chip, unsigned off, int val) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); @@ -418,7 +418,7 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip, static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); int ret; @@ -438,7 +438,7 @@ static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) static int adp5589_gpio_direction_output(struct gpio_chip *chip, unsigned off, int val) { - struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); + struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); int ret; @@ -525,9 +525,9 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad) mutex_init(&kpad->gpio_lock); - error = gpiochip_add(&kpad->gc); + error = gpiochip_add_data(&kpad->gc, kpad); if (error) { - dev_err(dev, "gpiochip_add failed, err: %d\n", error); + dev_err(dev, "gpiochip_add_data() failed, err: %d\n", error); return error; } -- GitLab From d94780444bf3da8fc35e281aec6bbffa54a4a01a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:35:27 +0100 Subject: [PATCH 0731/9938] input: ad7879: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Acked-by: Michael Hennerich Acked-by: Dmitry Torokhov Signed-off-by: Linus Walleij --- drivers/input/touchscreen/ad7879.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 69d299d5dd00..e4bf1103e6f8 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -379,7 +379,7 @@ static const struct attribute_group ad7879_attr_group = { static int ad7879_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); int err; mutex_lock(&ts->mutex); @@ -393,7 +393,7 @@ static int ad7879_gpio_direction_input(struct gpio_chip *chip, static int ad7879_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); int err; mutex_lock(&ts->mutex); @@ -412,7 +412,7 @@ static int ad7879_gpio_direction_output(struct gpio_chip *chip, static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); u16 val; mutex_lock(&ts->mutex); @@ -425,7 +425,7 @@ static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio) static void ad7879_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) { - struct ad7879 *ts = container_of(chip, struct ad7879, gc); + struct ad7879 *ts = gpiochip_get_data(chip); mutex_lock(&ts->mutex); if (value) @@ -456,7 +456,7 @@ static int ad7879_gpio_add(struct ad7879 *ts, ts->gc.owner = THIS_MODULE; ts->gc.parent = ts->dev; - ret = gpiochip_add(&ts->gc); + ret = gpiochip_add_data(&ts->gc, ts); if (ret) dev_err(ts->dev, "failed to register gpio %d\n", ts->gc.base); -- GitLab From 916fe619951f41b55d4f2b9f26d64ad981bc0dfa Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 29 Mar 2016 17:35:47 -0300 Subject: [PATCH 0732/9938] leds: trigger: Introduce a kernel panic LED trigger This commit introduces a new LED trigger which allows to configure a LED to blink on a kernel panic (through panic_blink). Notice that currently the Openmoko FreeRunner (GTA02) mach code sets panic_blink to blink a hard-coded LED. The new trigger is meant to introduce a generic mechanism to achieve this. Signed-off-by: Ezequiel Garcia Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/Kconfig | 7 +++++++ drivers/leds/trigger/Makefile | 1 + drivers/leds/trigger/ledtrig-panic.c | 30 ++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 drivers/leds/trigger/ledtrig-panic.c diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 5bda6a9b56bb..554f5bfbeced 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -108,4 +108,11 @@ config LEDS_TRIGGER_CAMERA This enables direct flash/torch on/off by the driver, kernel space. If unsure, say Y. +config LEDS_TRIGGER_PANIC + bool "LED Panic Trigger" + depends on LEDS_TRIGGERS + help + This allows LEDs to be configured to blink on a kernel panic. + If unsure, say Y. + endif # LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 1abf48dacf7e..547bf5c80e52 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o diff --git a/drivers/leds/trigger/ledtrig-panic.c b/drivers/leds/trigger/ledtrig-panic.c new file mode 100644 index 000000000000..627b350c5ec3 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-panic.c @@ -0,0 +1,30 @@ +/* + * Kernel Panic LED Trigger + * + * Copyright 2016 Ezequiel Garcia + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include + +static struct led_trigger *trigger; + +static long led_panic_blink(int state) +{ + led_trigger_event(trigger, state ? LED_FULL : LED_OFF); + return 0; +} + +static int __init ledtrig_panic_init(void) +{ + led_trigger_register_simple("panic", &trigger); + panic_blink = led_panic_blink; + return 0; +} +device_initcall(ledtrig_panic_init); -- GitLab From 9800917cf92f5b5fe5cae706cb70db8d014f663c Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Fri, 31 Jul 2015 20:42:00 +0200 Subject: [PATCH 0733/9938] ARM: mvebu: fix GPIO config on the Linksys boards Some of the GPIO configs were wrong in the submitted DTS files, this patch fixes all affected boards. Signed-off-by: Imre Kaloz Cc: # v4.1 + Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/armada-385-linksys.dtsi | 6 +++--- arch/arm/boot/dts/armada-xp-linksys-mamba.dts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/armada-385-linksys.dtsi index 3710755c6d76..6ebe9a78fc65 100644 --- a/arch/arm/boot/dts/armada-385-linksys.dtsi +++ b/arch/arm/boot/dts/armada-385-linksys.dtsi @@ -245,7 +245,7 @@ button@2 { label = "Factory Reset Button"; linux,code = ; - gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; }; }; @@ -260,7 +260,7 @@ }; sata { - gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; default-state = "off"; }; }; @@ -313,7 +313,7 @@ &pinctrl { keys_pin: keys-pin { - marvell,pins = "mpp24", "mpp47"; + marvell,pins = "mpp24", "mpp29"; marvell,function = "gpio"; }; diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts index b89e6cf1271a..7a461541ce50 100644 --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts @@ -304,13 +304,13 @@ button@1 { label = "WPS"; linux,code = ; - gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; }; button@2 { label = "Factory Reset Button"; linux,code = ; - gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; }; }; -- GitLab From fc5c796e12511a7c027b5a4438719dde2f796208 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 28 Mar 2016 10:03:48 +0200 Subject: [PATCH 0734/9938] ARM: dts: kirkwood: add kirkwood-ds112.dtb to Makefile Commit 2d0a7addbd10 ("ARM: Kirkwood: Add support for many Synology NAS devices") created the new file kirkwood-ds112.dts but did not add it to the Makefile. Fixes: 2d0a7addbd10 ("ARM: Kirkwood: Add support for many Synology NAS devices") Signed-off-by: Heinrich Schuchardt Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..67d5368a185a 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -177,6 +177,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \ kirkwood-ds109.dtb \ kirkwood-ds110jv10.dtb \ kirkwood-ds111.dtb \ + kirkwood-ds112.dtb \ kirkwood-ds209.dtb \ kirkwood-ds210.dtb \ kirkwood-ds212.dtb \ -- GitLab From 9ec423ed62b8278412400fae6c064edb6ce1bb51 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 28 Mar 2016 10:38:31 +0200 Subject: [PATCH 0735/9938] ARM: dts: kirkwood: add kirkwood-nsa320.dtb to Makefile Commit be3d7d023b87 ("ARM: kirkwood: Add DTS file for NSA320") created the new file kirkwood-nsa320.dts but did not add it to the Makefile. Fixes: be3d7d023b87 ("ARM: kirkwood: Add DTS file for NSA320") Signed-off-by: Heinrich Schuchardt Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 67d5368a185a..e9083a95a7cc 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -215,6 +215,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \ kirkwood-ns2mini.dtb \ kirkwood-nsa310.dtb \ kirkwood-nsa310a.dtb \ + kirkwood-nsa320.dtb \ kirkwood-nsa325.dtb \ kirkwood-openblocks_a6.dtb \ kirkwood-openblocks_a7.dtb \ -- GitLab From 03098268a30d75188f15dd8fda8f0c896d2846e5 Mon Sep 17 00:00:00 2001 From: Aviya Erenfeld Date: Thu, 18 Feb 2016 14:09:33 +0200 Subject: [PATCH 0736/9938] iwlwifi: mvm: add LQM vendor command and notification LQM stands for Link Quality Measurement. The firmware will collect a defined set of statitics (see the notification for details) that allow to know how busy the medium is. The driver issues a request to the firmware that includes the duration of the measurement (the firmware needs to be on channel for that amount of time) and the timeout (in case the firmware has a lot of offchannel activities). If the timeout elapses, the firmware will send partial results which are still valuable. In case of disassociation / channel switch and alike, the driver is in charge of stopping the measurements and the firmware will reply with partial results. The user space API for now is debugfs only and will be implmemented in an upcoming patch. Signed-off-by: Aviya Erenfeld Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 + .../net/wireless/intel/iwlwifi/mvm/fw-api.h | 62 ++++++++++++++++ .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 10 +++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 12 ++++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 9 +++ .../net/wireless/intel/iwlwifi/mvm/utils.c | 71 +++++++++++++++++++ 6 files changed, 166 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 3a72b9715930..c82b94167ac6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -326,6 +326,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * regular image. * @IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG: support getting more shared * memory addresses from the firmware. + * @IWL_UCODE_TLV_CAPA_LQM_SUPPORT: supports Link Quality Measurement * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -364,6 +365,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_CTDP_SUPPORT = (__force iwl_ucode_tlv_capa_t)76, IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED = (__force iwl_ucode_tlv_capa_t)77, IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG = (__force iwl_ucode_tlv_capa_t)80, + IWL_UCODE_TLV_CAPA_LQM_SUPPORT = (__force iwl_ucode_tlv_capa_t)81, NUM_IWL_UCODE_TLV_CAPA #ifdef __CHECKER__ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 61711b10ff82..e6bd0c8d4cc0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -279,6 +279,11 @@ enum { /* Please keep this enum *SORTED* by hex value. * Needed for binary search, otherwise a warning will be triggered. */ +enum iwl_mac_conf_subcmd_ids { + LINK_QUALITY_MEASUREMENT_CMD = 0x1, + LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF = 0xFE, +}; + enum iwl_phy_ops_subcmd_ids { CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0, CTDP_CONFIG_CMD = 0x03, @@ -307,6 +312,7 @@ enum { LEGACY_GROUP = 0x0, LONG_GROUP = 0x1, SYSTEM_GROUP = 0x2, + MAC_CONF_GROUP = 0x3, PHY_OPS_GROUP = 0x4, DATA_PATH_GROUP = 0x5, PROT_OFFLOAD_GROUP = 0xb, @@ -2017,4 +2023,60 @@ struct iwl_stored_beacon_notif { u8 data[MAX_STORED_BEACON_SIZE]; } __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_1 */ +#define LQM_NUMBER_OF_STATIONS_IN_REPORT 16 + +enum iwl_lqm_cmd_operatrions { + LQM_CMD_OPERATION_START_MEASUREMENT = 0x01, + LQM_CMD_OPERATION_STOP_MEASUREMENT = 0x02, +}; + +enum iwl_lqm_status { + LQM_STATUS_SUCCESS = 0, + LQM_STATUS_TIMEOUT = 1, + LQM_STATUS_ABORT = 2, +}; + +/** + * Link Quality Measurement command + * @cmd_operatrion: command operation to be performed (start or stop) + * as defined above. + * @mac_id: MAC ID the measurement applies to. + * @measurement_time: time of the total measurement to be performed, in uSec. + * @timeout: maximum time allowed until a response is sent, in uSec. + */ +struct iwl_link_qual_msrmnt_cmd { + __le32 cmd_operation; + __le32 mac_id; + __le32 measurement_time; + __le32 timeout; +} __packed /* LQM_CMD_API_S_VER_1 */; + +/** + * Link Quality Measurement notification + * + * @frequent_stations_air_time: an array containing the total air time + * (in uSec) used by the most frequently transmitting stations. + * @number_of_stations: the number of uniqe stations included in the array + * (a number between 0 to 16) + * @total_air_time_other_stations: the total air time (uSec) used by all the + * stations which are not included in the above report. + * @time_in_measurement_window: the total time in uSec in which a measurement + * took place. + * @tx_frame_dropped: the number of TX frames dropped due to retry limit during + * measurement + * @mac_id: MAC ID the measurement applies to. + * @status: return status. may be one of the LQM_STATUS_* defined above. + * @reserved: reserved. + */ +struct iwl_link_qual_msrmnt_notif { + __le32 frequent_stations_air_time[LQM_NUMBER_OF_STATIONS_IN_REPORT]; + __le32 number_of_stations; + __le32 total_air_time_other_stations; + __le32 time_in_measurement_window; + __le32 tx_frame_dropped; + __le32 mac_id; + __le32 status; + __le32 reserved[3]; +} __packed; /* LQM_MEASUREMENT_COMPLETE_NTF_API_S_VER1 */ + #endif /* __fw_api_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 76e649c680a1..cff9c16e4920 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1821,6 +1821,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); + if (changes & BSS_CHANGED_ASSOC && !bss_conf->assoc && + mvmvif->lqm_active) + iwl_mvm_send_lqm_cmd(vif, LQM_CMD_OPERATION_STOP_MEASUREMENT, + 0, 0); + /* * If we're not associated yet, take the (new) BSSID before associating * so the firmware knows. If we're already associated, then use the old @@ -3628,6 +3633,11 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, break; case NL80211_IFTYPE_STATION: + if (mvmvif->lqm_active) + iwl_mvm_send_lqm_cmd(vif, + LQM_CMD_OPERATION_STOP_MEASUREMENT, + 0, 0); + /* Schedule the time event to a bit before beacon 1, * to make sure we're in the new channel when the * GO/AP arrives. diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 6c67c0f631c5..0668601f377c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -453,6 +453,12 @@ struct iwl_mvm_vif { /* TCP Checksum Offload */ netdev_features_t features; + + /* + * link quality measurement - used to check whether this interface + * is in the middle of a link quality measurement + */ + bool lqm_active; }; static inline struct iwl_mvm_vif * @@ -1637,4 +1643,10 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm, void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif, const char *errmsg); +/* Link Quality Measurement */ +int iwl_mvm_send_lqm_cmd(struct ieee80211_vif *vif, + enum iwl_lqm_cmd_operatrions operation, + u32 duration, u32 timeout); +bool iwl_mvm_lqm_active(struct iwl_mvm *mvm); + #endif /* __IWL_MVM_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index ccf6ecd21b18..46a22fd9f0d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -425,6 +425,14 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = { HCMD_NAME(SHARED_MEM_CFG_CMD), }; +/* Please keep this array *SORTED* by hex value. + * Access is done through binary search + */ +static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = { + HCMD_NAME(LINK_QUALITY_MEASUREMENT_CMD), + HCMD_NAME(LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF), +}; + /* Please keep this array *SORTED* by hex value. * Access is done through binary search */ @@ -457,6 +465,7 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = { [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), [SYSTEM_GROUP] = HCMD_ARR(iwl_mvm_system_names), + [MAC_CONF_GROUP] = HCMD_ARR(iwl_mvm_mac_conf_names), [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), [DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names), [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 53cdc5760f68..2440248c8e69 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1079,3 +1079,74 @@ void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif, out: ieee80211_connection_loss(vif); } + +int iwl_mvm_send_lqm_cmd(struct ieee80211_vif *vif, + enum iwl_lqm_cmd_operatrions operation, + u32 duration, u32 timeout) +{ + struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_link_qual_msrmnt_cmd cmd = { + .cmd_operation = cpu_to_le32(operation), + .mac_id = cpu_to_le32(mvm_vif->id), + .measurement_time = cpu_to_le32(duration), + .timeout = cpu_to_le32(timeout), + }; + u32 cmdid = + iwl_cmd_id(LINK_QUALITY_MEASUREMENT_CMD, MAC_CONF_GROUP, 0); + int ret; + + if (!fw_has_capa(&mvm_vif->mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_LQM_SUPPORT)) + return -EOPNOTSUPP; + + if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) + return -EINVAL; + + switch (operation) { + case LQM_CMD_OPERATION_START_MEASUREMENT: + if (iwl_mvm_lqm_active(mvm_vif->mvm)) + return -EBUSY; + if (!vif->bss_conf.assoc) + return -EINVAL; + mvm_vif->lqm_active = true; + break; + case LQM_CMD_OPERATION_STOP_MEASUREMENT: + if (!iwl_mvm_lqm_active(mvm_vif->mvm)) + return -EINVAL; + break; + default: + return -EINVAL; + } + + ret = iwl_mvm_send_cmd_pdu(mvm_vif->mvm, cmdid, 0, sizeof(cmd), + &cmd); + + /* command failed - roll back lqm_active state */ + if (ret) { + mvm_vif->lqm_active = + operation == LQM_CMD_OPERATION_STOP_MEASUREMENT; + } + + return ret; +} + +static void iwl_mvm_lqm_active_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif); + bool *lqm_active = _data; + + *lqm_active = *lqm_active || mvm_vif->lqm_active; +} + +bool iwl_mvm_lqm_active(struct iwl_mvm *mvm) +{ + bool ret = false; + + lockdep_assert_held(&mvm->mutex); + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_lqm_active_iterator, &ret); + + return ret; +} -- GitLab From dedfc0f3dba0713734d42efb8300760b27c5a54a Mon Sep 17 00:00:00 2001 From: Aviya Erenfeld Date: Sun, 13 Mar 2016 15:58:59 +0200 Subject: [PATCH 0737/9938] iwlwifi: add a debugfs hook for LQM Add debugfs entry named lqm_send_cmd for kicking a measurement. This hook takes the duration and the timeout as parameter. Signed-off-by: Aviya Erenfeld Signed-off-by: Emmanuel Grumbach --- .../wireless/intel/iwlwifi/mvm/debugfs-vif.c | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 14004456bf55..3a279d3403ef 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -1425,6 +1425,89 @@ static ssize_t iwl_dbgfs_quota_min_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, len); } +static const char * const chanwidths[] = { + [NL80211_CHAN_WIDTH_20_NOHT] = "noht", + [NL80211_CHAN_WIDTH_20] = "ht20", + [NL80211_CHAN_WIDTH_40] = "ht40", + [NL80211_CHAN_WIDTH_80] = "vht80", + [NL80211_CHAN_WIDTH_80P80] = "vht80p80", + [NL80211_CHAN_WIDTH_160] = "vht160", +}; + +static bool iwl_mvm_lqm_notif_wait(struct iwl_notif_wait_data *notif_wait, + struct iwl_rx_packet *pkt, void *data) +{ + struct ieee80211_vif *vif = data; + struct iwl_mvm *mvm = + container_of(notif_wait, struct iwl_mvm, notif_wait); + struct iwl_link_qual_msrmnt_notif *report = (void *)pkt->data; + u32 num_of_stations = le32_to_cpu(report->number_of_stations); + int i; + + IWL_INFO(mvm, "LQM report:\n"); + IWL_INFO(mvm, "\tstatus: %d\n", report->status); + IWL_INFO(mvm, "\tmacID: %d\n", le32_to_cpu(report->mac_id)); + IWL_INFO(mvm, "\ttx_frame_dropped: %d\n", + le32_to_cpu(report->tx_frame_dropped)); + IWL_INFO(mvm, "\ttime_in_measurement_window: %d us\n", + le32_to_cpu(report->time_in_measurement_window)); + IWL_INFO(mvm, "\ttotal_air_time_other_stations: %d\n", + le32_to_cpu(report->total_air_time_other_stations)); + IWL_INFO(mvm, "\tchannel_freq: %d\n", + vif->bss_conf.chandef.center_freq1); + IWL_INFO(mvm, "\tchannel_width: %s\n", + chanwidths[vif->bss_conf.chandef.width]); + IWL_INFO(mvm, "\tnumber_of_stations: %d\n", num_of_stations); + for (i = 0; i < num_of_stations; i++) + IWL_INFO(mvm, "\t\tsta[%d]: %d\n", i, + report->frequent_stations_air_time[i]); + + return true; +} + +static ssize_t iwl_dbgfs_lqm_send_cmd_write(struct ieee80211_vif *vif, + char *buf, size_t count, + loff_t *ppos) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = mvmvif->mvm; + struct iwl_notification_wait wait_lqm_notif; + static u16 lqm_notif[] = { + WIDE_ID(MAC_CONF_GROUP, + LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF) + }; + int err; + u32 duration; + u32 timeout; + + if (sscanf(buf, "%d,%d", &duration, &timeout) != 2) + return -EINVAL; + + iwl_init_notification_wait(&mvm->notif_wait, &wait_lqm_notif, + lqm_notif, ARRAY_SIZE(lqm_notif), + iwl_mvm_lqm_notif_wait, vif); + mutex_lock(&mvm->mutex); + err = iwl_mvm_send_lqm_cmd(vif, LQM_CMD_OPERATION_START_MEASUREMENT, + duration, timeout); + mutex_unlock(&mvm->mutex); + + if (err) { + IWL_ERR(mvm, "Failed to send lqm cmdf(err=%d)\n", err); + iwl_remove_notification(&mvm->notif_wait, &wait_lqm_notif); + return err; + } + + /* wait for 2 * timeout (safety guard) and convert to jiffies*/ + timeout = msecs_to_jiffies((timeout * 2) / 1000); + + err = iwl_wait_notification(&mvm->notif_wait, &wait_lqm_notif, + timeout); + if (err) + IWL_ERR(mvm, "Getting lqm notif timed out\n"); + + return count; +} + #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ @@ -1449,6 +1532,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32); MVM_DEBUGFS_READ_FILE_OPS(tof_range_response); MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32); MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32); +MVM_DEBUGFS_WRITE_FILE_OPS(lqm_send_cmd, 64); void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -1488,6 +1572,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, S_IRUSR | S_IWUSR); + MVM_DEBUGFS_ADD_FILE_VIF(lqm_send_cmd, mvmvif->dbgfs_dir, S_IWUSR); if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && mvmvif == mvm->bf_allowed_vif) -- GitLab From 431469259df6ebc8e022b268bbb2d9bc5562f920 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 14 Mar 2016 13:11:47 +0200 Subject: [PATCH 0738/9938] iwlwifi: pcie: fix global table size My patch resized the pool size, but neglected to resize the global table, which is obviously wrong since the global table maps the pool's rxb to vid one to one. This results in a panic in 9000 devices. Add a build bug to avoid such a case in the future. Fixes: 7b5424361ec9 ("iwlwifi: pcie: fine tune number of rxbs") Reported-by: Haim Dreyfuss Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index dadafbdef9d9..34bf7cede7f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -348,7 +348,7 @@ struct iwl_tso_hdr_page { struct iwl_trans_pcie { struct iwl_rxq *rxq; struct iwl_rx_mem_buffer rx_pool[RX_POOL_SIZE]; - struct iwl_rx_mem_buffer *global_table[MQ_RX_TABLE_SIZE]; + struct iwl_rx_mem_buffer *global_table[RX_POOL_SIZE]; struct iwl_rb_allocator rba; struct iwl_trans *trans; struct iwl_drv *drv; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 4be3c35afd19..e379dbab685a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -908,6 +908,8 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) allocator_pool_size = trans->num_rx_queues * (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC); num_alloc = queue_size + allocator_pool_size; + BUILD_BUG_ON(ARRAY_SIZE(trans_pcie->global_table) != + ARRAY_SIZE(trans_pcie->rx_pool)); for (i = 0; i < num_alloc; i++) { struct iwl_rx_mem_buffer *rxb = &trans_pcie->rx_pool[i]; -- GitLab From 18dcb9a90cd5c49ec23130d64dd7921998068002 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Sun, 13 Mar 2016 21:48:35 +0200 Subject: [PATCH 0739/9938] iwlwifi: pcie: enable interrupts explicitly on resume When entering suspend the driver calls iwl_disable_interrupts() and then iwl_pcie_disable_ict(). On resume the driver calls only iwl_pcie_reset_ict() without calling explicitly to iwl_enable_interrupts(). This mostly works since iwl_pcie_reset_ict is calling to iwl_enable_interrupts, but it doesn't work when there is no ict_table in MSIx mode. The result is that driver tries to resume but fails since it doesn't get the RX interrupt from FW indicating that d0i3 exit was completed. Fix it by adding an explicit call to enable interrupts. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index eb39c7e09781..d4306e23e286 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1321,6 +1321,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, * after this call. */ iwl_pcie_reset_ict(trans); + iwl_enable_interrupts(trans); iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); -- GitLab From 5d93f3a278b387e3a2ec568c1f03d236bfdbef81 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 4 Mar 2016 15:25:47 +0200 Subject: [PATCH 0740/9938] iwlwifi: pcie: refcounting is not necessary anymore We don't use the refcount value anymore, all the refcounting is done in the runtime PM usage_count value. Remove it. Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 +-- .../wireless/intel/iwlwifi/pcie/internal.h | 4 --- .../net/wireless/intel/iwlwifi/pcie/trans.c | 25 +++++++------------ 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 05b968506836..34566691f90e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -651,10 +651,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* The PCI device starts with a reference taken and we are * supposed to release it here. But to simplify the * interaction with the opmode, we don't do it now, but let - * the opmode release it when it's ready. To account for this - * reference, we start with ref_count set to 1. + * the opmode release it when it's ready. */ - trans_pcie->ref_count = 1; return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 34bf7cede7f4..9ce4ec6cab2f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -403,10 +403,6 @@ struct iwl_trans_pcie { bool cmd_hold_nic_awake; bool ref_cmd_in_flight; - /* protect ref counter */ - spinlock_t ref_lock; - u32 ref_count; - dma_addr_t fw_mon_phys; struct page *fw_mon_page; u32 fw_mon_size; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index d4306e23e286..007bcb594946 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2015,38 +2015,32 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, void iwl_trans_pcie_ref(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - unsigned long flags; if (iwlwifi_mod_params.d0i3_disable) return; - spin_lock_irqsave(&trans_pcie->ref_lock, flags); - IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count); - trans_pcie->ref_count++; pm_runtime_get(&trans_pcie->pci_dev->dev); - spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); + +#ifdef CONFIG_PM + IWL_DEBUG_RPM(trans, "runtime usage count: %d\n", + atomic_read(&trans_pcie->pci_dev->dev.power.usage_count)); +#endif /* CONFIG_PM */ } void iwl_trans_pcie_unref(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - unsigned long flags; if (iwlwifi_mod_params.d0i3_disable) return; - spin_lock_irqsave(&trans_pcie->ref_lock, flags); - IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count); - if (WARN_ON_ONCE(trans_pcie->ref_count == 0)) { - spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); - return; - } - trans_pcie->ref_count--; - pm_runtime_mark_last_busy(&trans_pcie->pci_dev->dev); pm_runtime_put_autosuspend(&trans_pcie->pci_dev->dev); - spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); +#ifdef CONFIG_PM + IWL_DEBUG_RPM(trans, "runtime usage count: %d\n", + atomic_read(&trans_pcie->pci_dev->dev.power.usage_count)); +#endif /* CONFIG_PM */ } static const char *get_csr_string(int cmd) @@ -2794,7 +2788,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->trans = trans; spin_lock_init(&trans_pcie->irq_lock); spin_lock_init(&trans_pcie->reg_lock); - spin_lock_init(&trans_pcie->ref_lock); mutex_init(&trans_pcie->mutex); init_waitqueue_head(&trans_pcie->ucode_write_waitq); trans_pcie->tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); -- GitLab From ec77a33ee59723613d1e3ed6f02e5f9a1c898ce1 Mon Sep 17 00:00:00 2001 From: Chaya Rachel Ivgi Date: Sun, 13 Mar 2016 11:39:53 +0200 Subject: [PATCH 0741/9938] iwlwifi: mvm: handle async temperature notification with unlocked mutex Use RX_HANDLER_ASYNC_UNLOCKED instead of unlock and re-lock the mutex independently. Signed-off-by: Chaya Rachel Ivgi Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 46a22fd9f0d6..6153c8e86c53 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -292,7 +292,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, RX_HANDLER_ASYNC_LOCKED), RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE, - iwl_mvm_temp_notif, RX_HANDLER_ASYNC_LOCKED), + iwl_mvm_temp_notif, RX_HANDLER_ASYNC_UNLOCKED), RX_HANDLER_GRP(PHY_OPS_GROUP, CT_KILL_NOTIFICATION, iwl_mvm_ct_kill_notif, RX_HANDLER_SYNC), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index f1f28255a3a6..8d27137a9284 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -204,20 +204,11 @@ void iwl_mvm_temp_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) if (WARN_ON(ths_crossed >= IWL_MAX_DTS_TRIPS)) return; - /* - * We are now handling a temperature notification from the firmware - * in ASYNC and hold the mutex. thermal_notify_framework will call - * us back through get_temp() which ought to send a SYNC command to - * the firmware and hence to take the mutex. - * Avoid the deadlock by unlocking the mutex here. - */ if (mvm->tz_device.tzone) { struct iwl_mvm_thermal_device *tz_dev = &mvm->tz_device; - mutex_unlock(&mvm->mutex); thermal_notify_framework(tz_dev->tzone, tz_dev->fw_trips_index[ths_crossed]); - mutex_lock(&mvm->mutex); } #endif /* CONFIG_THERMAL */ } -- GitLab From 6ed5e4d64a5020ac7535762bdb1c840baeb5b5ff Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 14 Mar 2016 19:53:57 +0200 Subject: [PATCH 0742/9938] iwlwifi: pcie: print error value as signed int Bjorn pointed out that printing an error value as an hexadecimal isn't very convenient. Change that. Reported-by: Bjorn Helgaas Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 007bcb594946..28fe22097d52 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1466,7 +1466,7 @@ static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev, ret = pci_enable_msi(pdev); if (ret) { - dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", ret); + dev_err(&pdev->dev, "pci_enable_msi failed - %d\n", ret); /* enable rfkill interrupt: hw bug w/a */ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { -- GitLab From 6e2611f324a51dc63a8afa9ced58723e498bbf16 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 15 Mar 2016 11:12:20 +0200 Subject: [PATCH 0743/9938] iwlwifi: mvm: modify the max SP to infinite This makes u-APSD work with more peers. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/power.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 0668601f377c..2e0a8824aaba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -208,7 +208,7 @@ enum iwl_power_scheme { }; #define IWL_CONN_MAX_LISTEN_INTERVAL 10 -#define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_2 +#define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL #ifdef CONFIG_IWLWIFI_DEBUGFS enum iwl_dbgfs_pm_mask { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index f313910cd026..7b1f6ad6062b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -227,7 +227,7 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW); } - cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; + cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len; if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { -- GitLab From c772a3d3fa01048ae7992663e877e0a5f05a6d36 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Sun, 13 Mar 2016 17:19:38 +0200 Subject: [PATCH 0744/9938] iwlwifi: pcie: do not pad QoS AMSDU We insert padding if the MAC header's size is not a multiple of 4 to ensure that the SNAP header is DWORD aligned. When we do so, we let the firmware know by setting a bit in Tx command (TX_CMD_FLG_MH_PAD) which will instruct the firmware to drop those 2 bytes before sending the frame. However, this is not needed for AMSDU as the sub frame header (14B) complements the MAC header (26B) so that the SNAP header is DWORD aligned without adding any pad. Until 9000, the firmware didn't check the TX_CMD_FLG_MH_PAD bit but rather checked the length of the MAC header itself and assumed the entity that enqueued the frame (driver or internal firmware code) added the pad. Since the driver inserted the pad even for AMSDU this logic applied. Note that the padding is a DMA optimization but it's not strictly needed, so we could pad even if it was not needed. However, the CSUM hardware introduced for the 9000 devices requires to not pad AMSDU as it is not needed, and will fail if such a pad exists. Due to older FW not checking the padding bit but checking the mac header size itself - we cannot do this adjustments for older generations. Do not align the size if it is an AMSDU and HW checksum is enabled - which will only happen on 9000 devices and on. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 21 +++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index cc6fa00d350b..e1f7a3febb50 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -2210,6 +2210,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, __le16 fc; u8 hdr_len; u16 wifi_seq; + bool amsdu; txq = &trans_pcie->txq[txq_id]; q = &txq->q; @@ -2301,11 +2302,18 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, */ len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) + hdr_len - IWL_HCMD_SCRATCHBUF_SIZE; - tb1_len = ALIGN(len, 4); - - /* Tell NIC about any 2-byte padding after MAC header */ - if (tb1_len != len) - tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; + /* do not align A-MSDU to dword as the subframe header aligns it */ + amsdu = ieee80211_is_data_qos(fc) && + (*ieee80211_get_qos_ctl(hdr) & + IEEE80211_QOS_CTL_A_MSDU_PRESENT); + if (trans_pcie->sw_csum_tx || !amsdu) { + tb1_len = ALIGN(len, 4); + /* Tell NIC about any 2-byte padding after MAC header */ + if (tb1_len != len) + tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; + } else { + tb1_len = len; + } /* The first TB points to the scratchbuf data - min_copy bytes */ memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr, @@ -2323,8 +2331,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, goto out_err; iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false); - if (ieee80211_is_data_qos(fc) && - (*ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_A_MSDU_PRESENT)) { + if (amsdu) { if (unlikely(iwl_fill_data_tbs_amsdu(trans, skb, txq, hdr_len, out_meta, dev_cmd, tb1_len))) -- GitLab From d8fe484470dd72638613c42df3008ec118f24de9 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 9 Mar 2016 10:12:45 +0200 Subject: [PATCH 0745/9938] iwlwifi: mvm: add support for new TX CMD API TX CMD API has changed to support offload assist. Currently we do not enable checksum yet, but must set the padding indication, to avoid FW errors. Set other amsdu flag as well. The rest of the flags will be configured only if HW csum is enabled and will be set in future patches. This change is backward compatible. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- .../wireless/intel/iwlwifi/mvm/fw-api-tx.h | 35 +++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 9 ++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h index ba3f0bbddde8..dadcccd88255 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h @@ -6,6 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -193,11 +194,41 @@ enum iwl_tx_pm_timeouts { #define IWL_BAR_DFAULT_RETRY_LIMIT 60 #define IWL_LOW_RETRY_LIMIT 7 +/** + * enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd offload_assist values + * @TX_CMD_OFFLD_IP_HDR_OFFSET: offset to start of IP header (in words) + * from mac header end. For normal case it is 4 words for SNAP. + * note: tx_cmd, mac header and pad are not counted in the offset. + * This is used to help the offload in case there is tunneling such as + * IPv6 in IPv4, in such case the ip header offset should point to the + * inner ip header and IPv4 checksum of the external header should be + * calculated by driver. + * @TX_CMD_OFFLD_L4_EN: enable TCP/UDP checksum + * @TX_CMD_OFFLD_L3_EN: enable IP header checksum + * @TX_CMD_OFFLD_MH_SIZE: size of the mac header in words. Includes the IV + * field. Doesn't include the pad. + * @TX_CMD_OFFLD_PAD: mark 2-byte pad was inserted after the mac header for + * alignment + * @TX_CMD_OFFLD_AMSDU: mark TX command is A-MSDU + */ +enum iwl_tx_offload_assist_flags_pos { + TX_CMD_OFFLD_IP_HDR = 0, + TX_CMD_OFFLD_L4_EN = 6, + TX_CMD_OFFLD_L3_EN = 7, + TX_CMD_OFFLD_MH_SIZE = 8, + TX_CMD_OFFLD_PAD = 13, + TX_CMD_OFFLD_AMSDU = 14, +}; + +#define IWL_TX_CMD_OFFLD_MH_MASK 0x1f +#define IWL_TX_CMD_OFFLD_IP_HDR_MASK 0x3f + /* TODO: complete documentation for try_cnt and btkill_cnt */ /** * struct iwl_tx_cmd - TX command struct to FW * ( TX_CMD = 0x1c ) * @len: in bytes of the payload, see below for details + * @offload_assist: TX offload configuration * @tx_flags: combination of TX_CMD_FLG_* * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is * cleared. Combination of RATE_MCS_* @@ -231,7 +262,7 @@ enum iwl_tx_pm_timeouts { */ struct iwl_tx_cmd { __le16 len; - __le16 next_frame_len; + __le16 offload_assist; __le32 tx_flags; struct { u8 try_cnt; @@ -255,7 +286,7 @@ struct iwl_tx_cmd { __le16 reserved4; u8 payload[0]; struct ieee80211_hdr hdr[0]; -} __packed; /* TX_CMD_API_S_VER_3 */ +} __packed; /* TX_CMD_API_S_VER_6 */ /* * TX response related data diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 75870e68a7c3..138d64d2fc7a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -126,6 +126,9 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, u8 *qc = ieee80211_get_qos_ctl(hdr); tx_cmd->tid_tspec = qc[0] & 0xf; tx_flags &= ~TX_CMD_FLG_SEQ_CTL; + if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) + tx_cmd->offload_assist |= + cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU)); } else if (ieee80211_is_back_req(fc)) { struct ieee80211_bar *bar = (void *)skb->data; u16 control = le16_to_cpu(bar->control); @@ -186,9 +189,13 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, /* Total # bytes to be transmitted */ tx_cmd->len = cpu_to_le16((u16)skb->len + (uintptr_t)info->driver_data[0]); - tx_cmd->next_frame_len = 0; tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); tx_cmd->sta_id = sta_id; + + /* padding is inserted later in transport */ + if (ieee80211_hdrlen(fc) % 4 && + !(tx_cmd->offload_assist & cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU)))) + tx_cmd->offload_assist |= cpu_to_le16(BIT(TX_CMD_OFFLD_PAD)); } /* -- GitLab From a2a57a3548b94222e36a01db893b8f4788501150 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 15 Mar 2016 15:36:36 +0200 Subject: [PATCH 0746/9938] iwlwifi: add missing mutex_destroy statements iwlwifi / iwlmvm didn't destroy their mutexes. Fix that. Signed-off-by: Emmanuel Grumbach Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 6153c8e86c53..d4b71a7d0645 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -782,6 +782,9 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) iwl_mvm_tof_clean(mvm); + mutex_destroy(&mvm->mutex); + mutex_destroy(&mvm->d0i3_suspend_mutex); + ieee80211_free_hw(mvm->hw); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 28fe22097d52..0c40209bd718 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1695,6 +1695,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) } free_percpu(trans_pcie->tso_hdr_page); + mutex_destroy(&trans_pcie->mutex); iwl_trans_free(trans); } -- GitLab From 11dee0b4946bc8b0b4adc804f2110361fed81f08 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 15 Mar 2016 11:04:29 +0200 Subject: [PATCH 0747/9938] iwlwifi: make uapsd_disable module param a bitmap This allows to disable uapsd for BSS only, or P2P client separately. Remove the now unneeded IWL_MVM_P2P_UAPSD_STANDALONE constant. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 10 ++++++---- drivers/net/wireless/intel/iwlwifi/iwl-modparams.h | 10 ++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 1 - drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 3 ++- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 ++- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index f899666acb41..2cd9c3139a1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1561,7 +1561,7 @@ struct iwl_mod_params iwlwifi_mod_params = { .d0i3_disable = true, .d0i3_entry_delay = 1000, #ifndef CONFIG_IWLWIFI_UAPSD - .uapsd_disable = true, + .uapsd_disable = IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT, #endif /* CONFIG_IWLWIFI_UAPSD */ /* the rest are 0 by default */ }; @@ -1681,11 +1681,13 @@ module_param_named(lar_disable, iwlwifi_mod_params.lar_disable, MODULE_PARM_DESC(lar_disable, "disable LAR functionality (default: N)"); module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, - bool, S_IRUGO | S_IWUSR); + uint, S_IRUGO | S_IWUSR); #ifdef CONFIG_IWLWIFI_UAPSD -MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: N)"); +MODULE_PARM_DESC(uapsd_disable, + "disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 0)"); #else -MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: Y)"); +MODULE_PARM_DESC(uapsd_disable, + "disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 3)"); #endif /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h index d1a5dd1602f5..6c5c2f9f73a2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h @@ -92,6 +92,11 @@ enum iwl_amsdu_size { IWL_AMSDU_12K = 2, }; +enum iwl_uapsd_disable { + IWL_DISABLE_UAPSD_BSS = BIT(0), + IWL_DISABLE_UAPSD_P2P_CLIENT = BIT(1), +}; + /** * struct iwl_mod_params * @@ -109,7 +114,8 @@ enum iwl_amsdu_size { * @debug_level: levels are IWL_DL_* * @ant_coupling: antenna coupling in dB, default = 0 * @nvm_file: specifies a external NVM file - * @uapsd_disable: disable U-APSD, default = 1 + * @uapsd_disable: disable U-APSD, see %enum iwl_uapsd_disable, default = + * IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT * @d0i3_disable: disable d0i3, default = 1, * @d0i3_entry_delay: time to wait after no refs are taken before * entering D0i3 (in msecs) @@ -131,7 +137,7 @@ struct iwl_mod_params { #endif int ant_coupling; char *nvm_file; - bool uapsd_disable; + u32 uapsd_disable; bool d0i3_disable; unsigned int d0i3_entry_delay; bool lar_disable; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 4b560e4417ee..b96b1c6a97fa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -75,7 +75,6 @@ #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) #define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */ #define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */ -#define IWL_MVM_P2P_UAPSD_STANDALONE 0 #define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0 #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index cff9c16e4920..1a3481ba1446 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -2345,7 +2345,8 @@ static void iwl_mvm_check_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return; } - if (iwlwifi_mod_params.uapsd_disable) { + if (!vif->p2p && + (iwlwifi_mod_params.uapsd_disable & IWL_DISABLE_UAPSD_BSS)) { vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD; return; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 2e0a8824aaba..02ef1d91478c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1072,7 +1072,8 @@ bool iwl_mvm_is_p2p_standalone_uapsd_supported(struct iwl_mvm *mvm) { return fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD) && - IWL_MVM_P2P_UAPSD_STANDALONE; + !(iwlwifi_mod_params.uapsd_disable & + IWL_DISABLE_UAPSD_P2P_CLIENT); } static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) -- GitLab From 2d3d31b562dd060cbc7a163fd824421d0ebeaadf Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Tue, 15 Mar 2016 10:51:40 +0200 Subject: [PATCH 0748/9938] iwlwifi: 9000: update device id and FW serial number Update device id and FW serial number for 2X2 antenna devices in 9000 generation product. These will not be available on the market in the coming year. Signed-off-by: Haim Dreyfuss Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 8 ++++---- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index 318b1dc171f2..642fc92d7788 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015-2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -18,7 +18,7 @@ * * BSD LICENSE * - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015-2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -143,8 +143,8 @@ static const struct iwl_tt_params iwl9000_tt_params = { .vht_mu_mimo_supported = true, \ .mac_addr_from_csr = true -const struct iwl_cfg iwl9260_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC 9260", +const struct iwl_cfg iwl9560_2ac_cfg = { + .name = "Intel(R) Dual Band Wireless AC 9560", .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .ht_params = &iwl9000_ht_params, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 3e4d346be350..8cbd24875ffc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -439,7 +439,7 @@ extern const struct iwl_cfg iwl8265_2ac_cfg; extern const struct iwl_cfg iwl4165_2ac_cfg; extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; extern const struct iwl_cfg iwl4165_2ac_sdio_cfg; -extern const struct iwl_cfg iwl9260_2ac_cfg; +extern const struct iwl_cfg iwl9560_2ac_cfg; extern const struct iwl_cfg iwl5165_2ac_cfg; #endif /* CONFIG_IWLMVM */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 34566691f90e..fb8b5ecd6abb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -485,15 +485,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = { /* 9000 Series */ {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x2010, iwl5165_2ac_cfg)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0A10, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0A10, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0310, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0510, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0710, iwl5165_2ac_cfg)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0410, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0610, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0210, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0410, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0610, iwl9560_2ac_cfg)}, #endif /* CONFIG_IWLMVM */ {0} -- GitLab From 7ec54716e71a846dddf6aa1e33a12e1dcca6d276 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Mar 2016 09:29:48 +0100 Subject: [PATCH 0749/9938] iwlwifi: mvm: remove is_data_qos variable in TX "is_data_qos == true" is equivalent to "tid < IWL_MAX_TID_COUNT" since tid is only assigned (and range-checked) in that case. This removes a (harmless) smatch warning that occurs because it can't seem to follow the above logic from the code. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 138d64d2fc7a..c7c3d7bd38ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -654,7 +654,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, u16 seq_number = 0; u8 tid = IWL_MAX_TID_COUNT; u8 txq_id = info->hw_queue; - bool is_data_qos = false, is_ampdu = false; + bool is_ampdu = false; int hdrlen; mvmsta = iwl_mvm_sta_from_mac80211(sta); @@ -694,7 +694,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, seq_number &= IEEE80211_SCTL_SEQ; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(seq_number); - is_data_qos = true; is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU; } @@ -722,7 +721,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) goto drop_unlock_sta; - if (is_data_qos && !ieee80211_has_morefrags(fc)) + if (tid < IWL_MAX_TID_COUNT && !ieee80211_has_morefrags(fc)) mvmsta->tid_data[tid].seq_number = seq_number + 0x10; spin_unlock(&mvmsta->lock); -- GitLab From 24afba7690e49714795a1e8ee25e617ea0fb566b Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 28 Jul 2015 18:56:08 +0300 Subject: [PATCH 0750/9938] iwlwifi: mvm: support bss dynamic alloc/dealloc of queues "DQA" is shorthand for "dynamic queue allocation". This enables on-demand allocation of queues per RA/TID rather than statically allocating per vif, thus allowing a potential benefit of various factors. Please refer to the DOC section this patch adds to sta.h to see a more in-depth explanation of this feature. There are many things to take into consideration when working in DQA mode, and this patch is only one in a series. Note that default operation mode is non-DQA mode, unless the FW indicates that it supports DQA mode. This patch enables support of DQA for a station connected to an AP, and works in a non-aggregated mode. When a frame for an unused RA/TID arrives at the driver, it isn't TXed immediately, but deferred first until a suitable queue is first allocated for it, and then TXed by a worker that both allocates the queues and TXes deferred traffic. When a STA is removed, its queues goes back into the queue pools for reuse as needed. Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/fw-api.h | 22 +- .../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 21 +- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 49 ++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 7 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 254 +++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 87 +++++- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 54 ++++ 9 files changed, 481 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index c1a313149eed..e3561bbc2468 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -723,7 +723,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return -EIO; } - ret = iwl_mvm_sta_send_to_fw(mvm, ap_sta, false); + ret = iwl_mvm_sta_send_to_fw(mvm, ap_sta, false, 0); if (ret) return ret; rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index e6bd0c8d4cc0..8217eb25b090 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -80,12 +80,32 @@ #include "fw-api-stats.h" #include "fw-api-tof.h" -/* Tx queue numbers */ +/* Tx queue numbers for non-DQA mode */ enum { IWL_MVM_OFFCHANNEL_QUEUE = 8, IWL_MVM_CMD_QUEUE = 9, }; +/* + * DQA queue numbers + * + * @IWL_MVM_DQA_MIN_MGMT_QUEUE: first TXQ in pool for MGMT and non-QOS frames. + * Each MGMT queue is mapped to a single STA + * MGMT frames are frames that return true on ieee80211_is_mgmt() + * @IWL_MVM_DQA_MAX_MGMT_QUEUE: last TXQ in pool for MGMT frames + * @IWL_MVM_DQA_MIN_DATA_QUEUE: first TXQ in pool for DATA frames. + * DATA frames are intended for !ieee80211_is_mgmt() frames, but if + * the MGMT TXQ pool is exhausted, mgmt frames can be sent on DATA queues + * as well + * @IWL_MVM_DQA_MAX_DATA_QUEUE: last TXQ in pool for DATA frames + */ +enum iwl_mvm_dqa_txq { + IWL_MVM_DQA_MIN_MGMT_QUEUE = 5, + IWL_MVM_DQA_MAX_MGMT_QUEUE = 8, + IWL_MVM_DQA_MIN_DATA_QUEUE = 10, + IWL_MVM_DQA_MAX_DATA_QUEUE = 31, +}; + enum iwl_mvm_tx_fifo { IWL_MVM_TX_FIFO_BK = 0, IWL_MVM_TX_FIFO_BE, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index e885db3464b0..c02c1055d534 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -425,12 +425,17 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, return 0; } - /* Find available queues, and allocate them to the ACs */ + /* + * Find available queues, and allocate them to the ACs. When in + * DQA-mode they aren't really used, and this is done only so the + * mac80211 ieee80211_check_queues() function won't fail + */ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { u8 queue = find_first_zero_bit(&used_hw_queues, mvm->first_agg_queue); - if (queue >= mvm->first_agg_queue) { + if (!iwl_mvm_is_dqa_supported(mvm) && + queue >= mvm->first_agg_queue) { IWL_ERR(mvm, "Failed to allocate queue\n"); ret = -EIO; goto exit_fail; @@ -495,6 +500,10 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); /* fall through */ default: + /* If DQA is supported - queues will be enabled when needed */ + if (iwl_mvm_is_dqa_supported(mvm)) + break; + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], vif->hw_queue[ac], @@ -523,6 +532,14 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) IWL_MAX_TID_COUNT, 0); /* fall through */ default: + /* + * If DQA is supported - queues were already disabled, since in + * DQA-mode the queues are a property of the STA and not of the + * vif, and at this point the STA was already deleted + */ + if (iwl_mvm_is_dqa_supported(mvm)) + break; + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], vif->hw_queue[ac], diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 1a3481ba1446..115d7aa5e720 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -992,6 +992,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) iwl_mvm_reset_phy_ctxts(mvm); memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); + memset(mvm->sta_deferred_frames, 0, sizeof(mvm->sta_deferred_frames)); memset(mvm->tfd_drained, 0, sizeof(mvm->tfd_drained)); memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); @@ -1178,6 +1179,7 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) flush_work(&mvm->d0i3_exit_work); flush_work(&mvm->async_handlers_wk); + flush_work(&mvm->add_stream_wk); cancel_delayed_work_sync(&mvm->fw_dump_wk); iwl_mvm_free_fw_dump_desc(mvm); @@ -2382,6 +2384,22 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm, peer_addr, action); } +static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm, + struct iwl_mvm_sta *mvm_sta) +{ + struct iwl_mvm_tid_data *tid_data; + struct sk_buff *skb; + int i; + + spin_lock_bh(&mvm_sta->lock); + for (i = 0; i <= IWL_MAX_TID_COUNT; i++) { + tid_data = &mvm_sta->tid_data[i]; + while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames))) + ieee80211_free_txskb(mvm->hw, skb); + } + spin_unlock_bh(&mvm_sta->lock); +} + static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -2402,6 +2420,33 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, /* if a STA is being removed, reuse its ID */ flush_work(&mvm->sta_drained_wk); + /* + * If we are in a STA removal flow and in DQA mode: + * + * This is after the sync_rcu part, so the queues have already been + * flushed. No more TXs on their way in mac80211's path, and no more in + * the queues. + * Also, we won't be getting any new TX frames for this station. + * What we might have are deferred TX frames that need to be taken care + * of. + * + * Drop any still-queued deferred-frame before removing the STA, and + * make sure the worker is no longer handling frames for this STA. + */ + if (old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST && + iwl_mvm_is_dqa_supported(mvm)) { + struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); + + iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta); + flush_work(&mvm->add_stream_wk); + + /* + * No need to make sure deferred TX indication is off since the + * worker will already remove it if it was on + */ + } + mutex_lock(&mvm->mutex); if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { @@ -3738,6 +3783,10 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, if (!vif || vif->type != NL80211_IFTYPE_STATION) return; + /* Make sure we're done with the deferred traffic before flushing */ + if (iwl_mvm_is_dqa_supported(mvm)) + flush_work(&mvm->add_stream_wk); + mutex_lock(&mvm->mutex); mvmvif = iwl_mvm_vif_from_mac80211(vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 02ef1d91478c..f9430ee8f96b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -665,10 +665,16 @@ struct iwl_mvm { /* Map to HW queue */ u32 hw_queue_to_mac80211; u8 hw_queue_refcount; + /* + * This is to mark that queue is reserved for a STA but not yet + * allocated. This is needed to make sure we have at least one + * available queue to use when adding a new STA + */ bool setup_reserved; u16 tid_bitmap; /* Bitmap of the TIDs mapped to this queue */ } queue_info[IWL_MAX_HW_QUEUES]; spinlock_t queue_info_lock; /* For syncing queue mgmt operations */ + struct work_struct add_stream_wk; /* To add streams to queues */ atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES]; const char *nvm_file_name; @@ -688,6 +694,7 @@ struct iwl_mvm { struct iwl_rx_phy_info last_phy_info; struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT]; struct work_struct sta_drained_wk; + unsigned long sta_deferred_frames[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; atomic_t pending_frames[IWL_MVM_STATION_COUNT]; u32 tfd_drained[IWL_MVM_STATION_COUNT]; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index d4b71a7d0645..9fc705ca5841 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -579,6 +579,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work); INIT_DELAYED_WORK(&mvm->fw_dump_wk, iwl_mvm_fw_error_dump_wk); INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work); + INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk); spin_lock_init(&mvm->d0i3_tx_lock); spin_lock_init(&mvm->refs_lock); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index ef99942d7169..3f36a661ec96 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -111,7 +111,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, /* send station add/update command to firmware */ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - bool update) + bool update, unsigned int flags) { struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_add_sta_cmd add_sta_cmd = { @@ -126,9 +126,12 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, u32 status; u32 agg_size = 0, mpdu_dens = 0; - if (!update) { + if (!update || (flags & STA_MODIFY_QUEUES)) { add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk); memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN); + + if (flags & STA_MODIFY_QUEUES) + add_sta_cmd.modify_mask |= STA_MODIFY_QUEUES; } switch (sta->bandwidth) { @@ -274,6 +277,204 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm, iwl_mvm_disable_txq(mvm, i, i, IWL_MAX_TID_COUNT, 0); } +static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, u8 ac, int tid, + struct ieee80211_hdr *hdr) +{ + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct iwl_trans_txq_scd_cfg cfg = { + .fifo = iwl_mvm_ac_to_tx_fifo[ac], + .sta_id = mvmsta->sta_id, + .tid = tid, + .frame_limit = IWL_FRAME_LIMIT, + }; + unsigned int wdg_timeout = + iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false); + u8 mac_queue = mvmsta->vif->hw_queue[ac]; + int queue = -1; + int ssn; + + lockdep_assert_held(&mvm->mutex); + + spin_lock(&mvm->queue_info_lock); + + /* + * Non-QoS, QoS NDP and MGMT frames should go to a MGMT queue, if one + * exists + */ + if (!ieee80211_is_data_qos(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control)) { + queue = iwl_mvm_find_free_queue(mvm, IWL_MVM_DQA_MIN_MGMT_QUEUE, + IWL_MVM_DQA_MAX_MGMT_QUEUE); + if (queue >= IWL_MVM_DQA_MIN_MGMT_QUEUE) + IWL_DEBUG_TX_QUEUES(mvm, "Found free MGMT queue #%d\n", + queue); + + /* If no such queue is found, we'll use a DATA queue instead */ + } + + if (queue < 0 && mvmsta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) { + queue = mvmsta->reserved_queue; + IWL_DEBUG_TX_QUEUES(mvm, "Using reserved queue #%d\n", queue); + } + + if (queue < 0) + queue = iwl_mvm_find_free_queue(mvm, IWL_MVM_DQA_MIN_DATA_QUEUE, + IWL_MVM_DQA_MAX_DATA_QUEUE); + if (queue >= 0) + mvm->queue_info[queue].setup_reserved = false; + + spin_unlock(&mvm->queue_info_lock); + + /* TODO: support shared queues for same RA */ + if (queue < 0) + return -ENOSPC; + + /* + * Actual en/disablement of aggregations is through the ADD_STA HCMD, + * but for configuring the SCD to send A-MPDUs we need to mark the queue + * as aggregatable. + * Mark all DATA queues as allowing to be aggregated at some point + */ + cfg.aggregate = (queue >= IWL_MVM_DQA_MIN_DATA_QUEUE); + + IWL_DEBUG_TX_QUEUES(mvm, "Allocating queue #%d to sta %d on tid %d\n", + queue, mvmsta->sta_id, tid); + + ssn = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + iwl_mvm_enable_txq(mvm, queue, mac_queue, ssn, &cfg, + wdg_timeout); + + spin_lock_bh(&mvmsta->lock); + mvmsta->tid_data[tid].txq_id = queue; + mvmsta->tfd_queue_msk |= BIT(queue); + + if (mvmsta->reserved_queue == queue) + mvmsta->reserved_queue = IEEE80211_INVAL_HW_QUEUE; + spin_unlock_bh(&mvmsta->lock); + + return iwl_mvm_sta_send_to_fw(mvm, sta, true, STA_MODIFY_QUEUES); +} + +static inline u8 iwl_mvm_tid_to_ac_queue(int tid) +{ + if (tid == IWL_MAX_TID_COUNT) + return IEEE80211_AC_VO; /* MGMT */ + + return tid_to_mac80211_ac[tid]; +} + +static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, int tid) +{ + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + struct sk_buff_head deferred_tx; + u8 mac_queue; + bool no_queue = false; /* Marks if there is a problem with the queue */ + u8 ac; + + lockdep_assert_held(&mvm->mutex); + + skb = skb_peek(&tid_data->deferred_tx_frames); + if (!skb) + return; + hdr = (void *)skb->data; + + ac = iwl_mvm_tid_to_ac_queue(tid); + mac_queue = IEEE80211_SKB_CB(skb)->hw_queue; + + if (tid_data->txq_id == IEEE80211_INVAL_HW_QUEUE && + iwl_mvm_sta_alloc_queue(mvm, sta, ac, tid, hdr)) { + IWL_ERR(mvm, + "Can't alloc TXQ for sta %d tid %d - dropping frame\n", + mvmsta->sta_id, tid); + + /* + * Mark queue as problematic so later the deferred traffic is + * freed, as we can do nothing with it + */ + no_queue = true; + } + + __skb_queue_head_init(&deferred_tx); + + spin_lock(&mvmsta->lock); + skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx); + spin_unlock(&mvmsta->lock); + + /* Disable bottom-halves when entering TX path */ + local_bh_disable(); + while ((skb = __skb_dequeue(&deferred_tx))) + if (no_queue || iwl_mvm_tx_skb(mvm, skb, sta)) + ieee80211_free_txskb(mvm->hw, skb); + local_bh_enable(); + + /* Wake queue */ + iwl_mvm_start_mac_queues(mvm, BIT(mac_queue)); +} + +void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) +{ + struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, + add_stream_wk); + struct ieee80211_sta *sta; + struct iwl_mvm_sta *mvmsta; + unsigned long deferred_tid_traffic; + int sta_id, tid; + + mutex_lock(&mvm->mutex); + + /* Go over all stations with deferred traffic */ + for_each_set_bit(sta_id, mvm->sta_deferred_frames, + IWL_MVM_STATION_COUNT) { + clear_bit(sta_id, mvm->sta_deferred_frames); + sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], + lockdep_is_held(&mvm->mutex)); + if (IS_ERR_OR_NULL(sta)) + continue; + + mvmsta = iwl_mvm_sta_from_mac80211(sta); + deferred_tid_traffic = mvmsta->deferred_traffic_tid_map; + + for_each_set_bit(tid, &deferred_tid_traffic, + IWL_MAX_TID_COUNT + 1) + iwl_mvm_tx_deferred_stream(mvm, sta, tid); + } + + mutex_unlock(&mvm->mutex); +} + +static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, + struct ieee80211_sta *sta) +{ + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + int queue; + + spin_lock_bh(&mvm->queue_info_lock); + + /* Make sure we have free resources for this STA */ + queue = iwl_mvm_find_free_queue(mvm, IWL_MVM_DQA_MIN_DATA_QUEUE, + IWL_MVM_DQA_MAX_DATA_QUEUE); + if (queue < 0) { + spin_unlock_bh(&mvm->queue_info_lock); + IWL_ERR(mvm, "No available queues for new station\n"); + return -ENOSPC; + } + mvm->queue_info[queue].setup_reserved = true; + + spin_unlock_bh(&mvm->queue_info_lock); + + mvmsta->reserved_queue = queue; + + IWL_DEBUG_TX_QUEUES(mvm, "Reserving data queue #%d for sta_id %d\n", + queue, mvmsta->sta_id); + + return 0; +} + int iwl_mvm_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -314,18 +515,29 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, ret = iwl_mvm_tdls_sta_init(mvm, sta); if (ret) return ret; - } else { + } else if (!iwl_mvm_is_dqa_supported(mvm)) { for (i = 0; i < IEEE80211_NUM_ACS; i++) if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]); } /* for HW restart - reset everything but the sequence number */ - for (i = 0; i < IWL_MAX_TID_COUNT; i++) { + for (i = 0; i <= IWL_MAX_TID_COUNT; i++) { u16 seq = mvm_sta->tid_data[i].seq_number; memset(&mvm_sta->tid_data[i], 0, sizeof(mvm_sta->tid_data[i])); mvm_sta->tid_data[i].seq_number = seq; + + if (!iwl_mvm_is_dqa_supported(mvm)) + continue; + + /* + * Mark all queues for this STA as unallocated and defer TX + * frames until the queue is allocated + */ + mvm_sta->tid_data[i].txq_id = IEEE80211_INVAL_HW_QUEUE; + skb_queue_head_init(&mvm_sta->tid_data[i].deferred_tx_frames); } + mvm_sta->deferred_traffic_tid_map = 0; mvm_sta->agg_tids = 0; if (iwl_mvm_has_new_rx_api(mvm) && @@ -338,7 +550,13 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, mvm_sta->dup_data = dup_data; } - ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); + if (iwl_mvm_is_dqa_supported(mvm)) { + ret = iwl_mvm_reserve_sta_stream(mvm, sta); + if (ret) + goto err; + } + + ret = iwl_mvm_sta_send_to_fw(mvm, sta, false, 0); if (ret) goto err; @@ -364,7 +582,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - return iwl_mvm_sta_send_to_fw(mvm, sta, true); + return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0); } int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, @@ -509,6 +727,26 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) mutex_unlock(&mvm->mutex); } +static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct iwl_mvm_sta *mvm_sta) +{ + int ac; + int i; + + lockdep_assert_held(&mvm->mutex); + + for (i = 0; i < ARRAY_SIZE(mvm_sta->tid_data); i++) { + if (mvm_sta->tid_data[i].txq_id == IEEE80211_INVAL_HW_QUEUE) + continue; + + ac = iwl_mvm_tid_to_ac_queue(i); + iwl_mvm_disable_txq(mvm, mvm_sta->tid_data[i].txq_id, + vif->hw_queue[ac], i, 0); + mvm_sta->tid_data[i].txq_id = IEEE80211_INVAL_HW_QUEUE; + } +} + int iwl_mvm_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -537,6 +775,10 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, return ret; ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); + /* If DQA is supported - the queues can be disabled now */ + if (iwl_mvm_is_dqa_supported(mvm)) + iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta); + /* if we are associated - we can't remove the AP STA now */ if (vif->bss_conf.assoc) return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 1a8f69a41405..e3efdcd900f0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -7,7 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -34,7 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +79,60 @@ struct iwl_mvm; struct iwl_mvm_vif; +/** + * DOC: DQA - Dynamic Queue Allocation -introduction + * + * Dynamic Queue Allocation (AKA "DQA") is a feature implemented in iwlwifi + * driver to allow dynamic allocation of queues on-demand, rather than allocate + * them statically ahead of time. Ideally, we would like to allocate one queue + * per RA/TID, thus allowing an AP - for example - to send BE traffic to STA2 + * even if it also needs to send traffic to a sleeping STA1, without being + * blocked by the sleeping station. + * + * Although the queues in DQA mode are dynamically allocated, there are still + * some queues that are statically allocated: + * TXQ #0 - command queue + * TXQ #1 - aux frames + * TXQ #2 - P2P device frames + * TXQ #3 - P2P GO/SoftAP GCAST/BCAST frames + * TXQ #4 - BSS DATA frames queue + * TXQ #5-8 - Non-QoS and MGMT frames queue pool + * TXQ #9 - P2P GO/SoftAP probe responses + * TXQ #10-31 - DATA frames queue pool + * The queues are dynamically taken from either the MGMT frames queue pool or + * the DATA frames one. See the %iwl_mvm_dqa_txq for more information on every + * queue. + * + * When a frame for a previously unseen RA/TID comes in, it needs to be deferred + * until a queue is allocated for it, and only then can be TXed. Therefore, it + * is placed into %iwl_mvm_tid_data.deferred_tx_frames, and a worker called + * %mvm->add_stream_wk later allocates the queues and TXes the deferred frames. + * + * For convenience, MGMT is considered as if it has TID=8, and go to the MGMT + * queues in the pool. If there is no longer a free MGMT queue to allocate, a + * queue will be allocated from the DATA pool instead. Since QoS NDPs can create + * a problem for aggregations, they too will use a MGMT queue. + * + * When adding a STA, a DATA queue is reserved for it so that it can TX from + * it. If no such free queue exists for reserving, the STA addition will fail. + * + * If the DATA queue pool gets exhausted, no new STA will be accepted, and if a + * new RA/TID comes in for an existing STA, one of the STA's queues will become + * shared and will serve more than the single TID (but always for the same RA!). + * + * When a RA/TID needs to become aggregated, no new queue is required to be + * allocated, only mark the queue as aggregated via the ADD_STA command. Note, + * however, that a shared queue cannot be aggregated, and only after the other + * TIDs become inactive and are removed - only then can the queue be + * reconfigured and become aggregated. + * + * When removing a station, its queues are returned to the pool for reuse. Here + * we also need to make sure that we are synced with the worker thread that TXes + * the deferred frames so we don't get into a situation where the queues are + * removed and then the worker puts deferred frames onto the released queues or + * tries to allocate new queues for a STA we don't need anymore. + */ + /** * DOC: station table - introduction * @@ -253,6 +307,7 @@ enum iwl_mvm_agg_state { /** * struct iwl_mvm_tid_data - holds the states for each RA / TID + * @deferred_tx_frames: deferred TX frames for this RA/TID * @seq_number: the next WiFi sequence number to use * @next_reclaimed: the WiFi sequence number of the next packet to be acked. * This is basically (last acked packet++). @@ -260,7 +315,7 @@ enum iwl_mvm_agg_state { * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). * @amsdu_in_ampdu_allowed: true if A-MSDU in A-MPDU is allowed. * @state: state of the BA agreement establishment / tear down. - * @txq_id: Tx queue used by the BA session + * @txq_id: Tx queue used by the BA session / DQA * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or * the first packet to be sent in legacy HW queue in Tx AGG stop flow. * Basically when next_reclaimed reaches ssn, we can tell mac80211 that @@ -268,6 +323,7 @@ enum iwl_mvm_agg_state { * @tx_time: medium time consumed by this A-MPDU */ struct iwl_mvm_tid_data { + struct sk_buff_head deferred_tx_frames; u16 seq_number; u16 next_reclaimed; /* The rest is Tx AGG related */ @@ -316,7 +372,10 @@ struct iwl_mvm_rxq_dup_data { * we need to signal the EOSP * @lock: lock to protect the whole struct. Since %tid_data is access from Tx * and from Tx response flow, it needs a spinlock. - * @tid_data: per tid data. Look at %iwl_mvm_tid_data. + * @tid_data: per tid data + mgmt. Look at %iwl_mvm_tid_data. + * @reserved_queue: the queue reserved for this STA for DQA purposes + * Every STA has is given one reserved queue to allow it to operate. If no + * such queue can be guaranteed, the STA addition will fail. * @tx_protection: reference counter for controlling the Tx protection. * @tt_tx_protection: is thermal throttling enable Tx protection? * @disable_tx: is tx to this STA disabled? @@ -329,6 +388,7 @@ struct iwl_mvm_rxq_dup_data { * the BA window. To be used for UAPSD only. * @ptk_pn: per-queue PTK PN data structures * @dup_data: per queue duplicate packet detection data + * @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID * * When mac80211 creates a station it reserves some space (hw->sta_data_size) * in the structure for use by driver. This structure is placed in that @@ -345,12 +405,16 @@ struct iwl_mvm_sta { bool bt_reduced_txpower; bool next_status_eosp; spinlock_t lock; - struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; + struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT + 1]; struct iwl_lq_sta lq_sta; struct ieee80211_vif *vif; struct iwl_mvm_key_pn __rcu *ptk_pn[4]; struct iwl_mvm_rxq_dup_data *dup_data; + u16 deferred_traffic_tid_map; + + u8 reserved_queue; + /* Temporary, until the new TLC will control the Tx protection */ s8 tx_protection; bool tt_tx_protection; @@ -378,8 +442,18 @@ struct iwl_mvm_int_sta { u32 tfd_queue_msk; }; +/** + * Send the STA info to the FW. + * + * @mvm: the iwl_mvm* to use + * @sta: the STA + * @update: this is true if the FW is being updated about a STA it already knows + * about. Otherwise (if this is a new STA), this should be false. + * @flags: if update==true, this marks what is being changed via ORs of values + * from enum iwl_sta_modify_flag. Otherwise, this is ignored. + */ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - bool update); + bool update, unsigned int flags); int iwl_mvm_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -459,5 +533,6 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif, bool disable); void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk); #endif /* __sta_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index c7c3d7bd38ba..24cff98ecca0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -639,6 +639,35 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, } #endif +static void iwl_mvm_tx_add_stream(struct iwl_mvm *mvm, + struct iwl_mvm_sta *mvm_sta, u8 tid, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u8 mac_queue = info->hw_queue; + struct sk_buff_head *deferred_tx_frames; + + lockdep_assert_held(&mvm_sta->lock); + + mvm_sta->deferred_traffic_tid_map |= BIT(tid); + set_bit(mvm_sta->sta_id, mvm->sta_deferred_frames); + + deferred_tx_frames = &mvm_sta->tid_data[tid].deferred_tx_frames; + + skb_queue_tail(deferred_tx_frames, skb); + + /* + * The first deferred frame should've stopped the MAC queues, so we + * should never get a second deferred frame for the RA/TID. + */ + if (!WARN(skb_queue_len(deferred_tx_frames) != 1, + "RATID %d/%d has %d deferred frames\n", mvm_sta->sta_id, tid, + skb_queue_len(deferred_tx_frames))) { + iwl_mvm_stop_mac_queues(mvm, BIT(mac_queue)); + schedule_work(&mvm->add_stream_wk); + } +} + /* * Sets the fields in the Tx cmd that are crypto related */ @@ -695,6 +724,14 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(seq_number); is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU; + } else if (iwl_mvm_is_dqa_supported(mvm) && + (ieee80211_is_qos_nullfunc(fc) || + ieee80211_is_nullfunc(fc))) { + /* + * nullfunc frames should go to the MGMT queue regardless of QOS + */ + tid = IWL_MAX_TID_COUNT; + txq_id = mvmsta->tid_data[tid].txq_id; } /* Copy MAC header from skb into command buffer */ @@ -715,6 +752,23 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, txq_id = mvmsta->tid_data[tid].txq_id; } + if (iwl_mvm_is_dqa_supported(mvm)) { + if (unlikely(mvmsta->tid_data[tid].txq_id == + IEEE80211_INVAL_HW_QUEUE)) { + iwl_mvm_tx_add_stream(mvm, mvmsta, tid, skb); + + /* + * The frame is now deferred, and the worker scheduled + * will re-allocate it, so we can free it for now. + */ + iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); + spin_unlock(&mvmsta->lock); + return 0; + } + + txq_id = mvmsta->tid_data[tid].txq_id; + } + IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id, tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number)); -- GitLab From 0f851bbc28c3752440b9db334d65511909a4d427 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 16 Mar 2016 16:28:42 +0200 Subject: [PATCH 0751/9938] iwlwifi: pcie: write to legacy register also in MQ Due to hardware bug, upon any shadow free-queue register write access, a legacy RBD shadow register must be written as well. This is required in order to trigger a copy of the shadow registers values after MAC exits sleep state. Specifically, the driver has to write (any value) to the legacy RBD register each time FRBDCB is accessed. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index e379dbab685a..59a7e45b12df 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -210,8 +210,12 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, if (trans->cfg->mq_rx_supported) iwl_write_prph(trans, RFH_Q_FRBDCB_WIDX(rxq->id), rxq->write_actual); - else - iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); + /* + * write to FH_RSCSR_CHNL0_WPTR register even in MQ as a W/A to + * hardware shadow registers bug - writing to RFH_Q_FRBDCB_WIDX will + * not wake the NIC. + */ + iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); } static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) -- GitLab From 3a171386f9f1bdbe0d9835c4e68dcaadefdc872a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 14 Mar 2016 15:21:06 +0200 Subject: [PATCH 0752/9938] iwlwifi: remove IWLWIFI_UAPSD Kconfig We have a module parameter, this is enough. per platform customizations will be done through the init script of the platform. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/Kconfig | 10 ---------- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 7 ------- 2 files changed, 17 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 16c4f383488f..492035f406e9 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig @@ -88,16 +88,6 @@ config IWLWIFI_BCAST_FILTERING If unsure, don't enable this option, as some programs might expect incoming broadcasts for their normal operations. -config IWLWIFI_UAPSD - bool "enable U-APSD by default" - depends on IWLMVM - help - Say Y here to enable U-APSD by default. This may cause - interoperability problems with some APs, manifesting in lower than - expected throughput due to those APs not enabling aggregation - - If unsure, say N. - config IWLWIFI_PCIE_RTPM bool "Enable runtime power management mode for PCIe devices" depends on IWLMVM && PM diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 2cd9c3139a1c..9c2a2fd0f40c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1560,9 +1560,7 @@ struct iwl_mod_params iwlwifi_mod_params = { .power_level = IWL_POWER_INDEX_1, .d0i3_disable = true, .d0i3_entry_delay = 1000, -#ifndef CONFIG_IWLWIFI_UAPSD .uapsd_disable = IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT, -#endif /* CONFIG_IWLWIFI_UAPSD */ /* the rest are 0 by default */ }; IWL_EXPORT_SYMBOL(iwlwifi_mod_params); @@ -1682,13 +1680,8 @@ MODULE_PARM_DESC(lar_disable, "disable LAR functionality (default: N)"); module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, uint, S_IRUGO | S_IWUSR); -#ifdef CONFIG_IWLWIFI_UAPSD -MODULE_PARM_DESC(uapsd_disable, - "disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 0)"); -#else MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 3)"); -#endif /* * set bt_coex_active to true, uCode will do kill/defer -- GitLab From a0b09f13036cedfd67c9cb4b9d05138e7022723d Mon Sep 17 00:00:00 2001 From: Ayala Beker Date: Wed, 3 Feb 2016 15:36:52 +0200 Subject: [PATCH 0753/9938] iwlwifi: mvm: update GSCAN capabilities Gscan capabilities were updated with new capabilities supported by the device. Update GSCAN capabilities TLV. Signed-off-by: Ayala Beker Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 9c2a2fd0f40c..7cd17f0e45e8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1060,11 +1060,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, return -EINVAL; } - if (WARN(fw_has_capa(capa, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT) && - !gscan_capa, - "GSCAN is supported but capabilities TLV is unavailable\n")) + /* + * If ucode advertises that it supports GSCAN but GSCAN + * capabilities TLV is not present, or if it has an old format, + * warn and continue without GSCAN. + */ + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT) && + !gscan_capa) { + IWL_DEBUG_INFO(drv, + "GSCAN is supported but capabilities TLV is unavailable\n"); __clear_bit((__force long)IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT, capa->_capa); + } return 0; -- GitLab From 97f95c93c8ed5177371e75275f236513152fa308 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 7 Mar 2016 16:55:20 +0200 Subject: [PATCH 0754/9938] iwlwifi: remove support for fw older than -16.ucode API version lower than 16 is not supported anymore - don't load older ucode. Remove code handling older versions. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-7000.c | 12 +- drivers/net/wireless/intel/iwlwifi/iwl-8000.c | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 5 +- .../net/wireless/intel/iwlwifi/iwl-fw-file.h | 4 - .../net/wireless/intel/iwlwifi/mvm/Makefile | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 42 - .../wireless/intel/iwlwifi/mvm/coex_legacy.c | 1315 ----------------- .../net/wireless/intel/iwlwifi/mvm/debugfs.c | 164 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 16 - drivers/net/wireless/intel/iwlwifi/mvm/sf.c | 8 +- .../net/wireless/intel/iwlwifi/mvm/utils.c | 86 -- 12 files changed, 41 insertions(+), 1621 deletions(-) delete mode 100644 drivers/net/wireless/intel/iwlwifi/mvm/coex_legacy.c diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index fc475ce59b47..f4012a3f4d06 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c @@ -77,15 +77,15 @@ #define IWL3168_UCODE_API_MAX 21 /* Oldest version we won't warn about */ -#define IWL7260_UCODE_API_OK 13 -#define IWL7265_UCODE_API_OK 13 -#define IWL7265D_UCODE_API_OK 13 +#define IWL7260_UCODE_API_OK 16 +#define IWL7265_UCODE_API_OK 16 +#define IWL7265D_UCODE_API_OK 16 #define IWL3168_UCODE_API_OK 20 /* Lowest firmware API version supported */ -#define IWL7260_UCODE_API_MIN 13 -#define IWL7265_UCODE_API_MIN 13 -#define IWL7265D_UCODE_API_MIN 13 +#define IWL7260_UCODE_API_MIN 16 +#define IWL7265_UCODE_API_MIN 16 +#define IWL7265D_UCODE_API_MIN 16 #define IWL3168_UCODE_API_MIN 20 /* NVM versions */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index 97be104d1203..49bb2a5f9dcf 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -74,11 +74,11 @@ #define IWL8265_UCODE_API_MAX 21 /* Oldest version we won't warn about */ -#define IWL8000_UCODE_API_OK 13 +#define IWL8000_UCODE_API_OK 16 #define IWL8265_UCODE_API_OK 20 /* Lowest firmware API version supported */ -#define IWL8000_UCODE_API_MIN 13 +#define IWL8000_UCODE_API_MIN 16 #define IWL8265_UCODE_API_MIN 20 /* NVM versions */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index 642fc92d7788..277396a30713 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -58,10 +58,10 @@ #define IWL9000_UCODE_API_MAX 21 /* Oldest version we won't warn about */ -#define IWL9000_UCODE_API_OK 13 +#define IWL9000_UCODE_API_OK 16 /* Lowest firmware API version supported */ -#define IWL9000_UCODE_API_MIN 13 +#define IWL9000_UCODE_API_MIN 16 /* NVM versions */ #define IWL9000_NVM_VERSION 0x0a1d diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 7cd17f0e45e8..9a680ac48820 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1255,10 +1255,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) if (err) goto try_again; - if (fw_has_api(&drv->fw.ucode_capa, IWL_UCODE_TLV_API_NEW_VERSION)) - api_ver = drv->fw.ucode_ver; - else - api_ver = IWL_UCODE_API(drv->fw.ucode_ver); + api_ver = drv->fw.ucode_ver; /* * api_ver should match the api version forming part of the diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index c82b94167ac6..a6e8826c61db 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -245,13 +245,11 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; /** * enum iwl_ucode_tlv_api - ucode api - * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time * longer than the passive one, which is essential for fragmented scan. * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params - * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format * @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority * instead of 3. * @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size @@ -260,12 +258,10 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * @NUM_IWL_UCODE_TLV_API: number of bits used */ enum iwl_ucode_tlv_api { - IWL_UCODE_TLV_API_BT_COEX_SPLIT = (__force iwl_ucode_tlv_api_t)3, IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8, IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, - IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20, IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24, IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile index 23e7e2937566..2e06dfc1c477 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o iwlmvm-y += scan.o time-event.o rs.o -iwlmvm-y += power.o coex.o coex_legacy.o +iwlmvm-y += power.o coex.o iwlmvm-y += tt.o offloading.o tdls.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 2e098f8e0f83..35cdeca3d61e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c @@ -411,9 +411,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) struct iwl_bt_coex_cmd bt_cmd = {}; u32 mode; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT)) - return iwl_send_bt_init_conf_old(mvm); - lockdep_assert_held(&mvm->mutex); if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) { @@ -728,12 +725,6 @@ void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data; - if (!fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_BT_COEX_SPLIT)) { - iwl_mvm_rx_bt_coex_notif_old(mvm, rxb); - return; - } - IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n", @@ -755,12 +746,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int ret; - if (!fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_BT_COEX_SPLIT)) { - iwl_mvm_bt_rssi_event_old(mvm, vif, rssi_event); - return; - } - lockdep_assert_held(&mvm->mutex); /* Ignore updates if we are in force mode */ @@ -807,9 +792,6 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt; enum iwl_bt_coex_lut_type lut_type; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT)) - return iwl_mvm_coex_agg_time_limit_old(mvm, sta); - if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id)) return LINK_QUAL_AGG_TIME_LIMIT_DEF; @@ -834,9 +816,6 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt; enum iwl_bt_coex_lut_type lut_type; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT)) - return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta); - if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id)) return true; @@ -864,9 +843,6 @@ bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant) if (ant & mvm->cfg->non_shared_ant) return true; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT)) - return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm); - return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC; } @@ -877,9 +853,6 @@ bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm) if (mvm->cfg->bt_shared_single_ant) return true; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT)) - return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm); - return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC; } @@ -888,9 +861,6 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, { u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading); - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT)) - return iwl_mvm_bt_coex_is_tpc_allowed_old(mvm, band); - if (band != IEEE80211_BAND_2GHZ) return false; @@ -937,12 +907,6 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) { - if (!fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_BT_COEX_SPLIT)) { - iwl_mvm_bt_coex_vif_change_old(mvm); - return; - } - iwl_mvm_bt_coex_notif_handle(mvm); } @@ -955,12 +919,6 @@ void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, u8 __maybe_unused lower_bound, upper_bound; u8 lut; - if (!fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_BT_COEX_SPLIT)) { - iwl_mvm_rx_ant_coupling_notif_old(mvm, rxb); - return; - } - if (!iwl_mvm_bt_is_plcr_supported(mvm)) return; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex_legacy.c deleted file mode 100644 index 015045733444..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex_legacy.c +++ /dev/null @@ -1,1315 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include -#include -#include - -#include "fw-api-coex.h" -#include "iwl-modparams.h" -#include "mvm.h" -#include "iwl-debug.h" - -#define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant) \ - [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) | \ - ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS)) - -static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1, - BT_COEX_PRIO_TBL_PRIO_BYPASS, 0), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2, - BT_COEX_PRIO_TBL_PRIO_BYPASS, 1), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1, - BT_COEX_PRIO_TBL_PRIO_LOW, 0), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2, - BT_COEX_PRIO_TBL_PRIO_LOW, 1), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1, - BT_COEX_PRIO_TBL_PRIO_HIGH, 0), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2, - BT_COEX_PRIO_TBL_PRIO_HIGH, 1), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM, - BT_COEX_PRIO_TBL_DISABLED, 0), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52, - BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24, - BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0), - EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE, - BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0), - 0, 0, 0, 0, 0, 0, -}; - -#undef EVENT_PRIO_ANT - -static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) -{ - if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) - return 0; - - return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0, - sizeof(struct iwl_bt_coex_prio_tbl_cmd), - &iwl_bt_prio_tbl); -} - -static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { - cpu_to_le32(0xf0f0f0f0), /* 50% */ - cpu_to_le32(0xc0c0c0c0), /* 25% */ - cpu_to_le32(0xfcfcfcfc), /* 75% */ - cpu_to_le32(0xfefefefe), /* 87.5% */ -}; - -static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { - { - cpu_to_le32(0x40000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x44000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x40000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x44000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xf0005000), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xf0005000), - }, - { - cpu_to_le32(0x40000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x44000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x40000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x44000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xf0005000), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xf0005000), - }, - { - cpu_to_le32(0x40000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x44000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x40000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0x44000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xf0005000), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xf0005000), - }, -}; - -static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { - { - /* Tight */ - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaeaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xcc00ff28), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xcc00aaaa), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xc0004000), - cpu_to_le32(0x00004000), - cpu_to_le32(0xf0005000), - cpu_to_le32(0xf0005000), - }, - { - /* Loose */ - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xcc00ff28), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xcc00aaaa), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), - cpu_to_le32(0xf0005000), - cpu_to_le32(0xf0005000), - }, - { - /* Tx Tx disabled */ - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xeeaaaaaa), - cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xcc00ff28), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xcc00aaaa), - cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xc0004000), - cpu_to_le32(0xf0005000), - cpu_to_le32(0xf0005000), - }, -}; - -/* 20MHz / 40MHz below / 40Mhz above*/ -static const __le64 iwl_ci_mask[][3] = { - /* dummy entry for channel 0 */ - {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)}, - { - cpu_to_le64(0x0000001FFFULL), - cpu_to_le64(0x0ULL), - cpu_to_le64(0x00007FFFFFULL), - }, - { - cpu_to_le64(0x000000FFFFULL), - cpu_to_le64(0x0ULL), - cpu_to_le64(0x0003FFFFFFULL), - }, - { - cpu_to_le64(0x000003FFFCULL), - cpu_to_le64(0x0ULL), - cpu_to_le64(0x000FFFFFFCULL), - }, - { - cpu_to_le64(0x00001FFFE0ULL), - cpu_to_le64(0x0ULL), - cpu_to_le64(0x007FFFFFE0ULL), - }, - { - cpu_to_le64(0x00007FFF80ULL), - cpu_to_le64(0x00007FFFFFULL), - cpu_to_le64(0x01FFFFFF80ULL), - }, - { - cpu_to_le64(0x0003FFFC00ULL), - cpu_to_le64(0x0003FFFFFFULL), - cpu_to_le64(0x0FFFFFFC00ULL), - }, - { - cpu_to_le64(0x000FFFF000ULL), - cpu_to_le64(0x000FFFFFFCULL), - cpu_to_le64(0x3FFFFFF000ULL), - }, - { - cpu_to_le64(0x007FFF8000ULL), - cpu_to_le64(0x007FFFFFE0ULL), - cpu_to_le64(0xFFFFFF8000ULL), - }, - { - cpu_to_le64(0x01FFFE0000ULL), - cpu_to_le64(0x01FFFFFF80ULL), - cpu_to_le64(0xFFFFFE0000ULL), - }, - { - cpu_to_le64(0x0FFFF00000ULL), - cpu_to_le64(0x0FFFFFFC00ULL), - cpu_to_le64(0x0ULL), - }, - { - cpu_to_le64(0x3FFFC00000ULL), - cpu_to_le64(0x3FFFFFF000ULL), - cpu_to_le64(0x0) - }, - { - cpu_to_le64(0xFFFE000000ULL), - cpu_to_le64(0xFFFFFF8000ULL), - cpu_to_le64(0x0) - }, - { - cpu_to_le64(0xFFF8000000ULL), - cpu_to_le64(0xFFFFFE0000ULL), - cpu_to_le64(0x0) - }, - { - cpu_to_le64(0xFFC0000000ULL), - cpu_to_le64(0x0ULL), - cpu_to_le64(0x0ULL) - }, -}; - -enum iwl_bt_kill_msk { - BT_KILL_MSK_DEFAULT, - BT_KILL_MSK_NEVER, - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_MAX, -}; - -static const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { - [BT_KILL_MSK_DEFAULT] = 0xfffffc00, - [BT_KILL_MSK_NEVER] = 0xffffffff, - [BT_KILL_MSK_ALWAYS] = 0, -}; - -static const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { - { - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - }, - { - BT_KILL_MSK_NEVER, - BT_KILL_MSK_NEVER, - BT_KILL_MSK_NEVER, - }, - { - BT_KILL_MSK_NEVER, - BT_KILL_MSK_NEVER, - BT_KILL_MSK_NEVER, - }, - { - BT_KILL_MSK_DEFAULT, - BT_KILL_MSK_NEVER, - BT_KILL_MSK_DEFAULT, - }, -}; - -static const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { - { - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - }, - { - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - }, - { - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_ALWAYS, - }, - { - BT_KILL_MSK_DEFAULT, - BT_KILL_MSK_ALWAYS, - BT_KILL_MSK_DEFAULT, - }, -}; - -struct corunning_block_luts { - u8 range; - __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; -}; - -/* - * Ranges for the antenna coupling calibration / co-running block LUT: - * LUT0: [ 0, 12[ - * LUT1: [12, 20[ - * LUT2: [20, 21[ - * LUT3: [21, 23[ - * LUT4: [23, 27[ - * LUT5: [27, 30[ - * LUT6: [30, 32[ - * LUT7: [32, 33[ - * LUT8: [33, - [ - */ -static const struct corunning_block_luts antenna_coupling_ranges[] = { - { - .range = 0, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 12, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 20, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 21, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 23, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 27, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 30, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 32, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, - { - .range = 33, - .lut20 = { - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), - }, - }, -}; - -static enum iwl_bt_coex_lut_type -iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) -{ - struct ieee80211_chanctx_conf *chanctx_conf; - enum iwl_bt_coex_lut_type ret; - u16 phy_ctx_id; - - /* - * Checking that we hold mvm->mutex is a good idea, but the rate - * control can't acquire the mutex since it runs in Tx path. - * So this is racy in that case, but in the worst case, the AMPDU - * size limit will be wrong for a short time which is not a big - * issue. - */ - - rcu_read_lock(); - - chanctx_conf = rcu_dereference(vif->chanctx_conf); - - if (!chanctx_conf || - chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { - rcu_read_unlock(); - return BT_COEX_INVALID_LUT; - } - - ret = BT_COEX_TX_DIS_LUT; - - if (mvm->cfg->bt_shared_single_ant) { - rcu_read_unlock(); - return ret; - } - - phy_ctx_id = *((u16 *)chanctx_conf->drv_priv); - - if (mvm->last_bt_ci_cmd_old.primary_ch_phy_id == phy_ctx_id) - ret = le32_to_cpu(mvm->last_bt_notif_old.primary_ch_lut); - else if (mvm->last_bt_ci_cmd_old.secondary_ch_phy_id == phy_ctx_id) - ret = le32_to_cpu(mvm->last_bt_notif_old.secondary_ch_lut); - /* else - default = TX TX disallowed */ - - rcu_read_unlock(); - - return ret; -} - -int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) -{ - struct iwl_bt_coex_cmd_old *bt_cmd; - struct iwl_host_cmd cmd = { - .id = BT_CONFIG, - .len = { sizeof(*bt_cmd), }, - .dataflags = { IWL_HCMD_DFL_NOCOPY, }, - }; - int ret; - u32 flags; - - ret = iwl_send_bt_prio_tbl(mvm); - if (ret) - return ret; - - bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); - if (!bt_cmd) - return -ENOMEM; - cmd.data[0] = bt_cmd; - - lockdep_assert_held(&mvm->mutex); - - if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) { - switch (mvm->bt_force_ant_mode) { - case BT_FORCE_ANT_AUTO: - flags = BT_COEX_AUTO_OLD; - break; - case BT_FORCE_ANT_BT: - flags = BT_COEX_BT_OLD; - break; - case BT_FORCE_ANT_WIFI: - flags = BT_COEX_WIFI_OLD; - break; - default: - WARN_ON(1); - flags = 0; - } - - bt_cmd->flags = cpu_to_le32(flags); - bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE); - goto send_cmd; - } - - bt_cmd->max_kill = 5; - bt_cmd->bt4_antenna_isolation_thr = - IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS; - bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; - bt_cmd->bt4_tx_tx_delta_freq_thr = 15; - bt_cmd->bt4_tx_rx_max_freq0 = 15; - bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT; - bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT; - - flags = iwlwifi_mod_params.bt_coex_active ? - BT_COEX_NW_OLD : BT_COEX_DISABLE_OLD; - bt_cmd->flags = cpu_to_le32(flags); - - bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE | - BT_VALID_BT_PRIO_BOOST | - BT_VALID_MAX_KILL | - BT_VALID_3W_TMRS | - BT_VALID_KILL_ACK | - BT_VALID_KILL_CTS | - BT_VALID_REDUCED_TX_POWER | - BT_VALID_LUT | - BT_VALID_WIFI_RX_SW_PRIO_BOOST | - BT_VALID_WIFI_TX_SW_PRIO_BOOST | - BT_VALID_ANT_ISOLATION | - BT_VALID_ANT_ISOLATION_THRS | - BT_VALID_TXTX_DELTA_FREQ_THRS | - BT_VALID_TXRX_MAX_FREQ_0 | - BT_VALID_SYNC_TO_SCO | - BT_VALID_TTC | - BT_VALID_RRC); - - if (IWL_MVM_BT_COEX_SYNC2SCO) - bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO); - - if (iwl_mvm_bt_is_plcr_supported(mvm)) { - bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 | - BT_VALID_CORUN_LUT_40); - bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING); - } - - if (IWL_MVM_BT_COEX_MPLUT) { - bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT); - bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT); - } - - if (IWL_MVM_BT_COEX_TTC) - bt_cmd->flags |= cpu_to_le32(BT_COEX_TTC); - - if (iwl_mvm_bt_is_rrc_supported(mvm)) - bt_cmd->flags |= cpu_to_le32(BT_COEX_RRC); - - if (mvm->cfg->bt_shared_single_ant) - memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, - sizeof(iwl_single_shared_ant)); - else - memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, - sizeof(iwl_combined_lookup)); - - /* Take first Co-running block LUT to get started */ - memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20, - sizeof(bt_cmd->bt4_corun_lut20)); - memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20, - sizeof(bt_cmd->bt4_corun_lut40)); - - memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, - sizeof(iwl_bt_prio_boost)); - bt_cmd->bt4_multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0); - bt_cmd->bt4_multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1); - -send_cmd: - memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); - memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old)); - - ret = iwl_mvm_send_cmd(mvm, &cmd); - - kfree(bt_cmd); - return ret; -} - -static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm) -{ - struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old; - u32 primary_lut = le32_to_cpu(notif->primary_ch_lut); - u32 ag = le32_to_cpu(notif->bt_activity_grading); - struct iwl_bt_coex_cmd_old *bt_cmd; - u8 ack_kill_msk, cts_kill_msk; - struct iwl_host_cmd cmd = { - .id = BT_CONFIG, - .data[0] = &bt_cmd, - .len = { sizeof(*bt_cmd), }, - .dataflags = { IWL_HCMD_DFL_NOCOPY, }, - }; - int ret = 0; - - lockdep_assert_held(&mvm->mutex); - - ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut]; - cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut]; - - if (mvm->bt_ack_kill_msk[0] == ack_kill_msk && - mvm->bt_cts_kill_msk[0] == cts_kill_msk) - return 0; - - mvm->bt_ack_kill_msk[0] = ack_kill_msk; - mvm->bt_cts_kill_msk[0] = cts_kill_msk; - - bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); - if (!bt_cmd) - return -ENOMEM; - cmd.data[0] = bt_cmd; - bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD); - - bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]); - bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]); - bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | - BT_VALID_KILL_ACK | - BT_VALID_KILL_CTS); - - ret = iwl_mvm_send_cmd(mvm, &cmd); - - kfree(bt_cmd); - return ret; -} - -static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, - bool enable) -{ - struct iwl_bt_coex_cmd_old *bt_cmd; - /* Send ASYNC since this can be sent from an atomic context */ - struct iwl_host_cmd cmd = { - .id = BT_CONFIG, - .len = { sizeof(*bt_cmd), }, - .dataflags = { IWL_HCMD_DFL_DUP, }, - .flags = CMD_ASYNC, - }; - struct iwl_mvm_sta *mvmsta; - int ret; - - mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id); - if (!mvmsta) - return 0; - - /* nothing to do */ - if (mvmsta->bt_reduced_txpower == enable) - return 0; - - bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC); - if (!bt_cmd) - return -ENOMEM; - cmd.data[0] = bt_cmd; - bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD); - - bt_cmd->valid_bit_msk = - cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER); - bt_cmd->bt_reduced_tx_power = sta_id; - - if (enable) - bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT; - - IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n", - enable ? "en" : "dis", sta_id); - - mvmsta->bt_reduced_txpower = enable; - - ret = iwl_mvm_send_cmd(mvm, &cmd); - - kfree(bt_cmd); - return ret; -} - -struct iwl_bt_iterator_data { - struct iwl_bt_coex_profile_notif_old *notif; - struct iwl_mvm *mvm; - struct ieee80211_chanctx_conf *primary; - struct ieee80211_chanctx_conf *secondary; - bool primary_ll; -}; - -static inline -void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - bool enable, int rssi) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - - mvmvif->bf_data.last_bt_coex_event = rssi; - mvmvif->bf_data.bt_coex_max_thold = - enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0; - mvmvif->bf_data.bt_coex_min_thold = - enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0; -} - -/* must be called under rcu_read_lock */ -static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_bt_iterator_data *data = _data; - struct iwl_mvm *mvm = data->mvm; - struct ieee80211_chanctx_conf *chanctx_conf; - enum ieee80211_smps_mode smps_mode; - u32 bt_activity_grading; - int ave_rssi; - - lockdep_assert_held(&mvm->mutex); - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - /* default smps_mode for BSS / P2P client is AUTOMATIC */ - smps_mode = IEEE80211_SMPS_AUTOMATIC; - break; - case NL80211_IFTYPE_AP: - if (!mvmvif->ap_ibss_active) - return; - break; - default: - return; - } - - chanctx_conf = rcu_dereference(vif->chanctx_conf); - - /* If channel context is invalid or not on 2.4GHz .. */ - if ((!chanctx_conf || - chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { - if (vif->type == NL80211_IFTYPE_STATION) { - /* ... relax constraints and disable rssi events */ - iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, - smps_mode); - iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, - false); - iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); - } - return; - } - - bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading); - if (bt_activity_grading >= BT_HIGH_TRAFFIC) - smps_mode = IEEE80211_SMPS_STATIC; - else if (bt_activity_grading >= BT_LOW_TRAFFIC) - smps_mode = vif->type == NL80211_IFTYPE_AP ? - IEEE80211_SMPS_OFF : - IEEE80211_SMPS_DYNAMIC; - - /* relax SMPS contraints for next association */ - if (!vif->bss_conf.assoc) - smps_mode = IEEE80211_SMPS_AUTOMATIC; - - if (mvmvif->phy_ctxt && - data->notif->rrc_enabled & BIT(mvmvif->phy_ctxt->id)) - smps_mode = IEEE80211_SMPS_AUTOMATIC; - - IWL_DEBUG_COEX(data->mvm, - "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n", - mvmvif->id, data->notif->bt_status, bt_activity_grading, - smps_mode); - - if (vif->type == NL80211_IFTYPE_STATION) - iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, - smps_mode); - - /* low latency is always primary */ - if (iwl_mvm_vif_low_latency(mvmvif)) { - data->primary_ll = true; - - data->secondary = data->primary; - data->primary = chanctx_conf; - } - - if (vif->type == NL80211_IFTYPE_AP) { - if (!mvmvif->ap_ibss_active) - return; - - if (chanctx_conf == data->primary) - return; - - if (!data->primary_ll) { - /* - * downgrade the current primary no matter what its - * type is. - */ - data->secondary = data->primary; - data->primary = chanctx_conf; - } else { - /* there is low latency vif - we will be secondary */ - data->secondary = chanctx_conf; - } - return; - } - - /* - * STA / P2P Client, try to be primary if first vif. If we are in low - * latency mode, we are already in primary and just don't do much - */ - if (!data->primary || data->primary == chanctx_conf) - data->primary = chanctx_conf; - else if (!data->secondary) - /* if secondary is not NULL, it might be a GO */ - data->secondary = chanctx_conf; - - /* - * don't reduce the Tx power if one of these is true: - * we are in LOOSE - * single share antenna product - * BT is active - * we are associated - */ - if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || - mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || - !data->notif->bt_status) { - iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); - iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); - return; - } - - /* try to get the avg rssi from fw */ - ave_rssi = mvmvif->bf_data.ave_beacon_signal; - - /* if the RSSI isn't valid, fake it is very low */ - if (!ave_rssi) - ave_rssi = -100; - if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { - if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) - IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); - } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { - if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) - IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); - } - - /* Begin to monitor the RSSI: it may influence the reduced Tx power */ - iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi); -} - -static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) -{ - struct iwl_bt_iterator_data data = { - .mvm = mvm, - .notif = &mvm->last_bt_notif_old, - }; - struct iwl_bt_coex_ci_cmd_old cmd = {}; - u8 ci_bw_idx; - - /* Ignore updates if we are in force mode */ - if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) - return; - - rcu_read_lock(); - ieee80211_iterate_active_interfaces_atomic( - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_bt_notif_iterator, &data); - - if (data.primary) { - struct ieee80211_chanctx_conf *chan = data.primary; - - if (WARN_ON(!chan->def.chan)) { - rcu_read_unlock(); - return; - } - - if (chan->def.width < NL80211_CHAN_WIDTH_40) { - ci_bw_idx = 0; - cmd.co_run_bw_primary = 0; - } else { - cmd.co_run_bw_primary = 1; - if (chan->def.center_freq1 > - chan->def.chan->center_freq) - ci_bw_idx = 2; - else - ci_bw_idx = 1; - } - - cmd.bt_primary_ci = - iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; - cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv); - } - - if (data.secondary) { - struct ieee80211_chanctx_conf *chan = data.secondary; - - if (WARN_ON(!data.secondary->def.chan)) { - rcu_read_unlock(); - return; - } - - if (chan->def.width < NL80211_CHAN_WIDTH_40) { - ci_bw_idx = 0; - cmd.co_run_bw_secondary = 0; - } else { - cmd.co_run_bw_secondary = 1; - if (chan->def.center_freq1 > - chan->def.chan->center_freq) - ci_bw_idx = 2; - else - ci_bw_idx = 1; - } - - cmd.bt_secondary_ci = - iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; - cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv); - } - - rcu_read_unlock(); - - /* Don't spam the fw with the same command over and over */ - if (memcmp(&cmd, &mvm->last_bt_ci_cmd_old, sizeof(cmd))) { - if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0, - sizeof(cmd), &cmd)) - IWL_ERR(mvm, "Failed to send BT_CI cmd\n"); - memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd)); - } - - if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm)) - IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); -} - -void iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_bt_coex_profile_notif_old *notif = (void *)pkt->data; - - IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); - IWL_DEBUG_COEX(mvm, "\tBT status: %s\n", - notif->bt_status ? "ON" : "OFF"); - IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); - IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); - IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n", - le32_to_cpu(notif->primary_ch_lut)); - IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n", - le32_to_cpu(notif->secondary_ch_lut)); - IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n", - le32_to_cpu(notif->bt_activity_grading)); - IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", - notif->bt_agg_traffic_load); - - /* remember this notification for future use: rssi fluctuations */ - memcpy(&mvm->last_bt_notif_old, notif, sizeof(mvm->last_bt_notif_old)); - - iwl_mvm_bt_coex_notif_handle(mvm); -} - -static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_bt_iterator_data *data = _data; - struct iwl_mvm *mvm = data->mvm; - - struct ieee80211_sta *sta; - struct iwl_mvm_sta *mvmsta; - - struct ieee80211_chanctx_conf *chanctx_conf; - - rcu_read_lock(); - chanctx_conf = rcu_dereference(vif->chanctx_conf); - /* If channel context is invalid or not on 2.4GHz - don't count it */ - if (!chanctx_conf || - chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { - rcu_read_unlock(); - return; - } - rcu_read_unlock(); - - if (vif->type != NL80211_IFTYPE_STATION || - mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) - return; - - sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], - lockdep_is_held(&mvm->mutex)); - - /* This can happen if the station has been removed right now */ - if (IS_ERR_OR_NULL(sta)) - return; - - mvmsta = iwl_mvm_sta_from_mac80211(sta); -} - -void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - enum ieee80211_rssi_event_data rssi_event) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_bt_iterator_data data = { - .mvm = mvm, - }; - int ret; - - lockdep_assert_held(&mvm->mutex); - - /* Ignore updates if we are in force mode */ - if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) - return; - - /* - * Rssi update while not associated - can happen since the statistics - * are handled asynchronously - */ - if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) - return; - - /* No BT - reports should be disabled */ - if (!mvm->last_bt_notif_old.bt_status) - return; - - IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, - rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); - - /* - * Check if rssi is good enough for reduced Tx power, but not in loose - * scheme. - */ - if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant || - iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT) - ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, - false); - else - ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true); - - if (ret) - IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n"); - - ieee80211_iterate_active_interfaces_atomic( - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_bt_rssi_iterator, &data); - - if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm)) - IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); -} - -#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) -#define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200) - -u16 iwl_mvm_coex_agg_time_limit_old(struct iwl_mvm *mvm, - struct ieee80211_sta *sta) -{ - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - enum iwl_bt_coex_lut_type lut_type; - - if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) < - BT_HIGH_TRAFFIC) - return LINK_QUAL_AGG_TIME_LIMIT_DEF; - - if (mvm->last_bt_notif_old.ttc_enabled) - return LINK_QUAL_AGG_TIME_LIMIT_DEF; - - lut_type = iwl_get_coex_type(mvm, mvmsta->vif); - - if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT) - return LINK_QUAL_AGG_TIME_LIMIT_DEF; - - /* tight coex, high bt traffic, reduce AGG time limit */ - return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT; -} - -bool iwl_mvm_bt_coex_is_mimo_allowed_old(struct iwl_mvm *mvm, - struct ieee80211_sta *sta) -{ - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - enum iwl_bt_coex_lut_type lut_type; - - if (mvm->last_bt_notif_old.ttc_enabled) - return true; - - if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) < - BT_HIGH_TRAFFIC) - return true; - - /* - * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas - * since BT is already killed. - * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while - * we Tx. - * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO. - */ - lut_type = iwl_get_coex_type(mvm, mvmsta->vif); - return lut_type != BT_COEX_LOOSE_LUT; -} - -bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm) -{ - u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading); - return ag < BT_HIGH_TRAFFIC; -} - -bool iwl_mvm_bt_coex_is_tpc_allowed_old(struct iwl_mvm *mvm, - enum ieee80211_band band) -{ - u32 bt_activity = - le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading); - - if (band != IEEE80211_BAND_2GHZ) - return false; - - return bt_activity >= BT_LOW_TRAFFIC; -} - -void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm) -{ - iwl_mvm_bt_coex_notif_handle(mvm); -} - -void iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - u32 ant_isolation = le32_to_cpup((void *)pkt->data); - u8 __maybe_unused lower_bound, upper_bound; - u8 lut; - - struct iwl_bt_coex_cmd_old *bt_cmd; - struct iwl_host_cmd cmd = { - .id = BT_CONFIG, - .len = { sizeof(*bt_cmd), }, - .dataflags = { IWL_HCMD_DFL_NOCOPY, }, - }; - - if (!iwl_mvm_bt_is_plcr_supported(mvm)) - return; - - lockdep_assert_held(&mvm->mutex); - - /* Ignore updates if we are in force mode */ - if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) - return; - - if (ant_isolation == mvm->last_ant_isol) - return; - - for (lut = 0; lut < ARRAY_SIZE(antenna_coupling_ranges) - 1; lut++) - if (ant_isolation < antenna_coupling_ranges[lut + 1].range) - break; - - lower_bound = antenna_coupling_ranges[lut].range; - - if (lut < ARRAY_SIZE(antenna_coupling_ranges) - 1) - upper_bound = antenna_coupling_ranges[lut + 1].range; - else - upper_bound = antenna_coupling_ranges[lut].range; - - IWL_DEBUG_COEX(mvm, "Antenna isolation=%d in range [%d,%d[, lut=%d\n", - ant_isolation, lower_bound, upper_bound, lut); - - mvm->last_ant_isol = ant_isolation; - - if (mvm->last_corun_lut == lut) - return; - - mvm->last_corun_lut = lut; - - bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); - if (!bt_cmd) - return; - cmd.data[0] = bt_cmd; - - bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD); - bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | - BT_VALID_CORUN_LUT_20 | - BT_VALID_CORUN_LUT_40); - - /* For the moment, use the same LUT for 20GHz and 40GHz */ - memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20, - sizeof(bt_cmd->bt4_corun_lut20)); - - memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, - sizeof(bt_cmd->bt4_corun_lut40)); - - if (iwl_mvm_send_cmd(mvm, &cmd)) - IWL_ERR(mvm, "failed to send BT_CONFIG command\n"); - - kfree(bt_cmd); -} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index a43b3921c4c1..abc16f73f07b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -463,69 +463,11 @@ int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf, return pos; } -static -int iwl_mvm_coex_dump_mbox_old(struct iwl_bt_coex_profile_notif_old *notif, - char *buf, int pos, int bufsz) -{ - pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n"); - - BT_MBOX_PRINT(0, LE_SLAVE_LAT, false); - BT_MBOX_PRINT(0, LE_PROF1, false); - BT_MBOX_PRINT(0, LE_PROF2, false); - BT_MBOX_PRINT(0, LE_PROF_OTHER, false); - BT_MBOX_PRINT(0, CHL_SEQ_N, false); - BT_MBOX_PRINT(0, INBAND_S, false); - BT_MBOX_PRINT(0, LE_MIN_RSSI, false); - BT_MBOX_PRINT(0, LE_SCAN, false); - BT_MBOX_PRINT(0, LE_ADV, false); - BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false); - BT_MBOX_PRINT(0, OPEN_CON_1, true); - - pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n"); - - BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false); - BT_MBOX_PRINT(1, IP_SR, false); - BT_MBOX_PRINT(1, LE_MSTR, false); - BT_MBOX_PRINT(1, AGGR_TRFC_LD, false); - BT_MBOX_PRINT(1, MSG_TYPE, false); - BT_MBOX_PRINT(1, SSN, true); - - pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n"); - - BT_MBOX_PRINT(2, SNIFF_ACT, false); - BT_MBOX_PRINT(2, PAG, false); - BT_MBOX_PRINT(2, INQUIRY, false); - BT_MBOX_PRINT(2, CONN, false); - BT_MBOX_PRINT(2, SNIFF_INTERVAL, false); - BT_MBOX_PRINT(2, DISC, false); - BT_MBOX_PRINT(2, SCO_TX_ACT, false); - BT_MBOX_PRINT(2, SCO_RX_ACT, false); - BT_MBOX_PRINT(2, ESCO_RE_TX, false); - BT_MBOX_PRINT(2, SCO_DURATION, true); - - pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n"); - - BT_MBOX_PRINT(3, SCO_STATE, false); - BT_MBOX_PRINT(3, SNIFF_STATE, false); - BT_MBOX_PRINT(3, A2DP_STATE, false); - BT_MBOX_PRINT(3, ACL_STATE, false); - BT_MBOX_PRINT(3, MSTR_STATE, false); - BT_MBOX_PRINT(3, OBX_STATE, false); - BT_MBOX_PRINT(3, OPEN_CON_2, false); - BT_MBOX_PRINT(3, TRAFFIC_LOAD, false); - BT_MBOX_PRINT(3, CHL_SEQN_LSB, false); - BT_MBOX_PRINT(3, INBAND_P, false); - BT_MBOX_PRINT(3, MSG_TYPE_2, false); - BT_MBOX_PRINT(3, SSN_2, false); - BT_MBOX_PRINT(3, UPDATE_REQUEST, true); - - return pos; -} - static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_mvm *mvm = file->private_data; + struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; char *buf; int ret, pos = 0, bufsz = sizeof(char) * 1024; @@ -535,52 +477,24 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, mutex_lock(&mvm->mutex); - if (!fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_BT_COEX_SPLIT)) { - struct iwl_bt_coex_profile_notif_old *notif = - &mvm->last_bt_notif_old; - - pos += iwl_mvm_coex_dump_mbox_old(notif, buf, pos, bufsz); - - pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", - notif->bt_ci_compliance); - pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n", - le32_to_cpu(notif->primary_ch_lut)); - pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n", - le32_to_cpu(notif->secondary_ch_lut)); - pos += scnprintf(buf+pos, - bufsz-pos, "bt_activity_grading = %d\n", - le32_to_cpu(notif->bt_activity_grading)); - pos += scnprintf(buf+pos, bufsz-pos, - "antenna isolation = %d CORUN LUT index = %d\n", - mvm->last_ant_isol, mvm->last_corun_lut); - pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n", - notif->rrc_enabled); - pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n", - notif->ttc_enabled); - } else { - struct iwl_bt_coex_profile_notif *notif = - &mvm->last_bt_notif; - - pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz); - - pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", - notif->bt_ci_compliance); - pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n", - le32_to_cpu(notif->primary_ch_lut)); - pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n", - le32_to_cpu(notif->secondary_ch_lut)); - pos += scnprintf(buf+pos, - bufsz-pos, "bt_activity_grading = %d\n", - le32_to_cpu(notif->bt_activity_grading)); - pos += scnprintf(buf+pos, bufsz-pos, - "antenna isolation = %d CORUN LUT index = %d\n", - mvm->last_ant_isol, mvm->last_corun_lut); - pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n", - (notif->ttc_rrc_status >> 4) & 0xF); - pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n", - notif->ttc_rrc_status & 0xF); - } + pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz); + + pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n", + notif->bt_ci_compliance); + pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n", + le32_to_cpu(notif->primary_ch_lut)); + pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n", + le32_to_cpu(notif->secondary_ch_lut)); + pos += scnprintf(buf + pos, + bufsz - pos, "bt_activity_grading = %d\n", + le32_to_cpu(notif->bt_activity_grading)); + pos += scnprintf(buf + pos, bufsz - pos, + "antenna isolation = %d CORUN LUT index = %d\n", + mvm->last_ant_isol, mvm->last_corun_lut); + pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n", + (notif->ttc_rrc_status >> 4) & 0xF); + pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n", + notif->ttc_rrc_status & 0xF); pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n", IWL_MVM_BT_COEX_SYNC2SCO); @@ -602,44 +516,20 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_mvm *mvm = file->private_data; + struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; char buf[256]; int bufsz = sizeof(buf); int pos = 0; mutex_lock(&mvm->mutex); - if (!fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_BT_COEX_SPLIT)) { - struct iwl_bt_coex_ci_cmd_old *cmd = &mvm->last_bt_ci_cmd_old; - - pos += scnprintf(buf+pos, bufsz-pos, - "Channel inhibition CMD\n"); - pos += scnprintf(buf+pos, bufsz-pos, - "\tPrimary Channel Bitmap 0x%016llx\n", - le64_to_cpu(cmd->bt_primary_ci)); - pos += scnprintf(buf+pos, bufsz-pos, - "\tSecondary Channel Bitmap 0x%016llx\n", - le64_to_cpu(cmd->bt_secondary_ci)); - - pos += scnprintf(buf+pos, bufsz-pos, - "BT Configuration CMD - 0=default, 1=never, 2=always\n"); - pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill msk idx %d\n", - mvm->bt_ack_kill_msk[0]); - pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill msk idx %d\n", - mvm->bt_cts_kill_msk[0]); - - } else { - struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; - - pos += scnprintf(buf+pos, bufsz-pos, - "Channel inhibition CMD\n"); - pos += scnprintf(buf+pos, bufsz-pos, - "\tPrimary Channel Bitmap 0x%016llx\n", - le64_to_cpu(cmd->bt_primary_ci)); - pos += scnprintf(buf+pos, bufsz-pos, - "\tSecondary Channel Bitmap 0x%016llx\n", - le64_to_cpu(cmd->bt_secondary_ci)); - } + pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "\tPrimary Channel Bitmap 0x%016llx\n", + le64_to_cpu(cmd->bt_primary_ci)); + pos += scnprintf(buf + pos, bufsz - pos, + "\tSecondary Channel Bitmap 0x%016llx\n", + le64_to_cpu(cmd->bt_secondary_ci)); mutex_unlock(&mvm->mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f9430ee8f96b..f0e25971424e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1470,22 +1470,6 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *info, u8 ac); -bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm); -void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm); -int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm); -void iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb); -void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - enum ieee80211_rssi_event_data); -u16 iwl_mvm_coex_agg_time_limit_old(struct iwl_mvm *mvm, - struct ieee80211_sta *sta); -bool iwl_mvm_bt_coex_is_mimo_allowed_old(struct iwl_mvm *mvm, - struct ieee80211_sta *sta); -bool iwl_mvm_bt_coex_is_tpc_allowed_old(struct iwl_mvm *mvm, - enum ieee80211_band band); -void iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb); - /* beacon filtering */ #ifdef CONFIG_IWLWIFI_DEBUGFS void diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c index c2def1232a8c..443a42855c9e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c @@ -193,7 +193,7 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm, } } - if (sta || IWL_UCODE_API(mvm->fw->ucode_ver) < 13) { + if (sta) { BUILD_BUG_ON(sizeof(sf_full_timeout) != sizeof(__le32) * SF_NUM_SCENARIO * SF_NUM_TIMEOUT_TYPES); @@ -220,9 +220,6 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, struct ieee80211_sta *sta; int ret = 0; - if (IWL_UCODE_API(mvm->fw->ucode_ver) < 13) - sf_cmd.state = cpu_to_le32(new_state); - if (mvm->cfg->disable_dummy_notification) sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF); @@ -235,8 +232,7 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, switch (new_state) { case SF_UNINIT: - if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 13) - iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL); + iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL); break; case SF_FULL_ON: if (sta_id == IWL_MVM_STATION_COUNT) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 2440248c8e69..76866b9e5686 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -491,98 +491,12 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref); } -static void iwl_mvm_dump_nic_error_log_old(struct iwl_mvm *mvm) -{ - struct iwl_trans *trans = mvm->trans; - struct iwl_error_event_table_v1 table; - u32 base; - - base = mvm->error_event_table; - if (mvm->cur_ucode == IWL_UCODE_INIT) { - if (!base) - base = mvm->fw->init_errlog_ptr; - } else { - if (!base) - base = mvm->fw->inst_errlog_ptr; - } - - if (base < 0x800000) { - IWL_ERR(mvm, - "Not valid error log pointer 0x%08X for %s uCode\n", - base, - (mvm->cur_ucode == IWL_UCODE_INIT) - ? "Init" : "RT"); - return; - } - - iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); - - if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { - IWL_ERR(trans, "Start IWL Error Log Dump:\n"); - IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", - mvm->status, table.valid); - } - - /* Do not change this output - scripts rely on it */ - - IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); - - trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, - table.data1, table.data2, table.data3, - table.blink2, table.ilink1, table.ilink2, - table.bcon_time, table.gp1, table.gp2, - table.gp3, table.ucode_ver, 0, - table.hw_ver, table.brd_ver); - IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, - desc_lookup(table.error_id)); - IWL_ERR(mvm, "0x%08X | uPc\n", table.pc); - IWL_ERR(mvm, "0x%08X | branchlink1\n", table.blink1); - IWL_ERR(mvm, "0x%08X | branchlink2\n", table.blink2); - IWL_ERR(mvm, "0x%08X | interruptlink1\n", table.ilink1); - IWL_ERR(mvm, "0x%08X | interruptlink2\n", table.ilink2); - IWL_ERR(mvm, "0x%08X | data1\n", table.data1); - IWL_ERR(mvm, "0x%08X | data2\n", table.data2); - IWL_ERR(mvm, "0x%08X | data3\n", table.data3); - IWL_ERR(mvm, "0x%08X | beacon time\n", table.bcon_time); - IWL_ERR(mvm, "0x%08X | tsf low\n", table.tsf_low); - IWL_ERR(mvm, "0x%08X | tsf hi\n", table.tsf_hi); - IWL_ERR(mvm, "0x%08X | time gp1\n", table.gp1); - IWL_ERR(mvm, "0x%08X | time gp2\n", table.gp2); - IWL_ERR(mvm, "0x%08X | time gp3\n", table.gp3); - IWL_ERR(mvm, "0x%08X | uCode version\n", table.ucode_ver); - IWL_ERR(mvm, "0x%08X | hw version\n", table.hw_ver); - IWL_ERR(mvm, "0x%08X | board version\n", table.brd_ver); - IWL_ERR(mvm, "0x%08X | hcmd\n", table.hcmd); - IWL_ERR(mvm, "0x%08X | isr0\n", table.isr0); - IWL_ERR(mvm, "0x%08X | isr1\n", table.isr1); - IWL_ERR(mvm, "0x%08X | isr2\n", table.isr2); - IWL_ERR(mvm, "0x%08X | isr3\n", table.isr3); - IWL_ERR(mvm, "0x%08X | isr4\n", table.isr4); - IWL_ERR(mvm, "0x%08X | isr_pref\n", table.isr_pref); - IWL_ERR(mvm, "0x%08X | wait_event\n", table.wait_event); - IWL_ERR(mvm, "0x%08X | l2p_control\n", table.l2p_control); - IWL_ERR(mvm, "0x%08X | l2p_duration\n", table.l2p_duration); - IWL_ERR(mvm, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid); - IWL_ERR(mvm, "0x%08X | l2p_addr_match\n", table.l2p_addr_match); - IWL_ERR(mvm, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel); - IWL_ERR(mvm, "0x%08X | timestamp\n", table.u_timestamp); - IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); - - if (mvm->support_umac_log) - iwl_mvm_dump_umac_error_log(mvm); -} - void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) { struct iwl_trans *trans = mvm->trans; struct iwl_error_event_table table; u32 base; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_NEW_VERSION)) { - iwl_mvm_dump_nic_error_log_old(mvm); - return; - } - base = mvm->error_event_table; if (mvm->cur_ucode == IWL_UCODE_INIT) { if (!base) -- GitLab From b429a773c193ee7cb752144e590181a1b8cc8fb5 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Sat, 19 Mar 2016 05:15:47 +0000 Subject: [PATCH 0755/9938] iwlwifi: dvm: use alloc_ordered_workqueue() Use alloc_ordered_workqueue() to allocate the workqueue instead of create_singlethread_workqueue() since the latter is deprecated and is scheduled for removal. There are work items doing related operations that shouldn't be swapped when queued in a certain order hence preserve the strict execution ordering of a single threaded (ST) workqueue by switching to alloc_ordered_workqueue(). WQ_MEM_RECLAIM flag is not needed since the worker is not depended during memory reclaim. Signed-off-by: Eva Rachel Retuya Acked-by: Tejun Heo Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 85628127947f..614716251c39 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -1071,7 +1071,7 @@ static void iwl_bg_restart(struct work_struct *data) static void iwl_setup_deferred_work(struct iwl_priv *priv) { - priv->workqueue = create_singlethread_workqueue(DRV_NAME); + priv->workqueue = alloc_ordered_workqueue(DRV_NAME, 0); INIT_WORK(&priv->restart, iwl_bg_restart); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); -- GitLab From b238be07375e1d3aa976564397109fe9898d6123 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 16 Mar 2016 13:57:50 +0200 Subject: [PATCH 0756/9938] iwlwifi: mvm: report checksum is done also for IPv6 packets Currently the code checks if hardware reported both L4 and L3 checksums as valid, and only then reports it as validated to the stack. However, IPv6 does not have checksum at all and the L3 checksum valid bit is always off for IPv6 packets, with the result of the stack re-validating L4 checksum. Fix code to set CHECKSUM_UNNECESSARY also for IPv6 packets whose TCP/UDP checksum was verified. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 15 ++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 9 +++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h index 7a16e55df012..4c086d048097 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -268,12 +268,25 @@ enum iwl_rx_mpdu_amsdu_info { IWL_RX_MPDU_AMSDU_LAST_SUBFRAME = 0x80, }; +enum iwl_rx_l3_proto_values { + IWL_RX_L3_TYPE_NONE, + IWL_RX_L3_TYPE_IPV4, + IWL_RX_L3_TYPE_IPV4_FRAG, + IWL_RX_L3_TYPE_IPV6_FRAG, + IWL_RX_L3_TYPE_IPV6, + IWL_RX_L3_TYPE_IPV6_IN_IPV4, + IWL_RX_L3_TYPE_ARP, + IWL_RX_L3_TYPE_EAPOL, +}; + +#define IWL_RX_L3_PROTO_POS 4 + enum iwl_rx_l3l4_flags { IWL_RX_L3L4_IP_HDR_CSUM_OK = BIT(0), IWL_RX_L3L4_TCP_UDP_CSUM_OK = BIT(1), IWL_RX_L3L4_TCP_FIN_SYN_RST_PSH = BIT(2), IWL_RX_L3L4_TCP_ACK = BIT(3), - IWL_RX_L3L4_L3_PROTO_MASK = 0xf << 4, + IWL_RX_L3L4_L3_PROTO_MASK = 0xf << IWL_RX_L3_PROTO_POS, IWL_RX_L3L4_L4_PROTO_MASK = 0xf << 8, IWL_RX_L3L4_RSS_HASH_MASK = 0xf << 12, }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 9a54f2d2a66b..b2bc3d96a13f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -294,10 +294,15 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta, { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); + u16 flags = le16_to_cpu(desc->l3l4_flags); + u8 l3_prot = (u8)((flags & IWL_RX_L3L4_L3_PROTO_MASK) >> + IWL_RX_L3_PROTO_POS); if (mvmvif->features & NETIF_F_RXCSUM && - desc->l3l4_flags & cpu_to_le16(IWL_RX_L3L4_IP_HDR_CSUM_OK) && - desc->l3l4_flags & cpu_to_le16(IWL_RX_L3L4_TCP_UDP_CSUM_OK)) + flags & IWL_RX_L3L4_TCP_UDP_CSUM_OK && + (flags & IWL_RX_L3L4_IP_HDR_CSUM_OK || + l3_prot == IWL_RX_L3_TYPE_IPV6 || + l3_prot == IWL_RX_L3_TYPE_IPV6_FRAG)) skb->ip_summed = CHECKSUM_UNNECESSARY; } -- GitLab From 5db81fd401bd8bba4bcc4a615c60961a792d4df9 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Sun, 20 Mar 2016 10:35:10 +0200 Subject: [PATCH 0757/9938] iwlwifi: mvm: set aux STA ID in scan config Auxilary station ID in flag in scan config command wasn't set although we set the station ID. Add the flag. Signed-off-by: David Spinadel Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 09eb72c4ae43..25b007cf7db7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -961,6 +961,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS | SCAN_CONFIG_FLAG_SET_TX_CHAINS | SCAN_CONFIG_FLAG_SET_RX_CHAINS | + SCAN_CONFIG_FLAG_SET_AUX_STA_ID | SCAN_CONFIG_FLAG_SET_ALL_TIMES | SCAN_CONFIG_FLAG_SET_LEGACY_RATES | SCAN_CONFIG_FLAG_SET_MAC_ADDR | -- GitLab From 2a2e9d100739d79531d1109d7b768b3aaf681c06 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Thu, 17 Mar 2016 10:13:57 +0200 Subject: [PATCH 0758/9938] iwlwifi: trans: fix iwl_trans_txq_scd_cfg.sta_id sign For some reason, this was defined as a signed variable. Make it unsigned. Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 91d74b3f666b..fa4ab4b9436f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -7,6 +7,7 @@ * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -33,6 +34,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -519,7 +521,7 @@ struct iwl_trans; struct iwl_trans_txq_scd_cfg { u8 fifo; - s8 sta_id; + u8 sta_id; u8 tid; bool aggregate; int frame_limit; -- GitLab From 0df1391feee699a79b36f284fa6e19ab26344d25 Mon Sep 17 00:00:00 2001 From: Chaya Rachel Ivgi Date: Thu, 17 Mar 2016 13:01:37 +0200 Subject: [PATCH 0759/9938] iwlwifi: mvm: remove uneeded D0I3 checking The driver can read the current state during D0I3, therefore there is no reason not to do it. Signed-off-by: Chaya Rachel Ivgi Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index 8d27137a9284..3f5df76f65a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -787,9 +787,6 @@ static int iwl_mvm_tcool_get_cur_state(struct thermal_cooling_device *cdev, { struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata); - if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) - return -EBUSY; - *state = mvm->cooling_dev.cur_state; return 0; -- GitLab From 013a67ea69d7caac094e6d144507246f10f24d9a Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 22 Mar 2016 16:04:53 +0200 Subject: [PATCH 0760/9938] iwlwifi: pcie: request one more interrupt vector We want to request an interrupt vector for RSS queue per CPU, one vector for fallback queue, and one for non-rx interrupts. Future patch will make sure that no RSS traffic is directed to fallback queue. This will enable us to enable fast path on traffic that otherwise would have been received on the fallback queue. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 0c40209bd718..f1a506b609d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1435,7 +1435,7 @@ static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev, int ret, i; if (trans->cfg->mq_rx_supported) { - max_vector = min_t(u32, (num_possible_cpus() + 1), + max_vector = min_t(u32, (num_possible_cpus() + 2), IWL_MAX_RX_HW_QUEUES); for (i = 0; i < max_vector; i++) trans_pcie->msix_entries[i].entry = i; -- GitLab From 854d773e4ab5869200004af4ca5d851730849903 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 22 Mar 2016 15:55:58 +0200 Subject: [PATCH 0761/9938] iwlwifi: mvm: improve RSS configuration Improve current RSS configuration: * Use netdev_rss_key instead of keeping a local copy. * Configure also UDP hashing to have UDP traffic spread across queues. * Do not direct RSS traffic to our fallback queue. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 9 +++++++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 - drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 --- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index abc16f73f07b..362a54601a80 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -65,6 +65,7 @@ *****************************************************************************/ #include #include +#include #include "mvm.h" #include "fw-dbg.h" @@ -880,8 +881,10 @@ static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm, struct iwl_rss_config_cmd cmd = { .flags = cpu_to_le32(IWL_RSS_ENABLE), .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | + IWL_RSS_HASH_TYPE_IPV4_UDP | IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | IWL_RSS_HASH_TYPE_IPV6_TCP | + IWL_RSS_HASH_TYPE_IPV6_UDP | IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, }; int ret, i, num_repeats, nbytes = count / 2; @@ -905,7 +908,7 @@ static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm, memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table, ARRAY_SIZE(cmd.indirection_table) % nbytes); - memcpy(cmd.secret_key, mvm->secret_key, sizeof(cmd.secret_key)); + netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key)); mutex_lock(&mvm->mutex); ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index f375275ee98e..2dc97a19246a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -64,6 +64,7 @@ * *****************************************************************************/ #include +#include #include "iwl-trans.h" #include "iwl-op-mode.h" @@ -114,14 +115,18 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) struct iwl_rss_config_cmd cmd = { .flags = cpu_to_le32(IWL_RSS_ENABLE), .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | + IWL_RSS_HASH_TYPE_IPV4_UDP | IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | IWL_RSS_HASH_TYPE_IPV6_TCP | + IWL_RSS_HASH_TYPE_IPV6_UDP | IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, }; + /* Do not direct RSS traffic to Q 0 which is our fallback queue */ for (i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++) - cmd.indirection_table[i] = i % mvm->trans->num_rx_queues; - memcpy(cmd.secret_key, mvm->secret_key, sizeof(cmd.secret_key)); + cmd.indirection_table[i] = + 1 + (i % (mvm->trans->num_rx_queues - 1)); + netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key)); return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f0e25971424e..a9de2ad642bc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -699,7 +699,6 @@ struct iwl_mvm { atomic_t pending_frames[IWL_MVM_STATION_COUNT]; u32 tfd_drained[IWL_MVM_STATION_COUNT]; u8 rx_ba_sessions; - u32 secret_key[IWL_RSS_HASH_KEY_CNT]; /* configured by mac80211 */ u32 rts_threshold; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 9fc705ca5841..e36bcade69d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -725,9 +725,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, iwl_mvm_tof_init(mvm); - /* init RSS hash key */ - get_random_bytes(mvm->secret_key, sizeof(mvm->secret_key)); - return op_mode; out_unregister: -- GitLab From 0e32d5904ccad13a8fb6a5b0519ae43eef0e0a75 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Thu, 24 Mar 2016 10:20:28 +0200 Subject: [PATCH 0762/9938] iwlwifi: edit the 9000 series PCI IDs Edit some of the 9560 series and 5165 series PCI IDs. These devices do not exist yet. Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index fb8b5ecd6abb..41c6dd5b9ccc 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -483,17 +483,19 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x24FD, 0x0810, iwl8265_2ac_cfg)}, /* 9000 Series */ + {IWL_PCI_DEVICE(0x9DF0, 0x0A10, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x2010, iwl5165_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0A10, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x1420, iwl5165_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0010, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0310, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0510, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x0710, iwl5165_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0210, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0410, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0610, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x9DF0, 0x0210, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x9DF0, 0x0410, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x9DF0, 0x0610, iwl9560_2ac_cfg)}, #endif /* CONFIG_IWLMVM */ {0} -- GitLab From d5216a28936add0a9c34bdc7d4f03c2e0a2261c2 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 9 Aug 2015 15:50:51 +0300 Subject: [PATCH 0763/9938] iwlwifi: mvm: use bss client queue for bss station Use the reserved BSS Client queue when connecting to an AP in DQA mode. Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/mvm/fw-api.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 18 +++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 8217eb25b090..965268766ac2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -89,6 +89,8 @@ enum { /* * DQA queue numbers * + * @IWL_MVM_DQA_BSS_CLIENT_QUEUE: a queue reserved for BSS activity, to ensure + * that we are never left without the possibility to connect to an AP. * @IWL_MVM_DQA_MIN_MGMT_QUEUE: first TXQ in pool for MGMT and non-QOS frames. * Each MGMT queue is mapped to a single STA * MGMT frames are frames that return true on ieee80211_is_mgmt() @@ -100,6 +102,7 @@ enum { * @IWL_MVM_DQA_MAX_DATA_QUEUE: last TXQ in pool for DATA frames */ enum iwl_mvm_dqa_txq { + IWL_MVM_DQA_BSS_CLIENT_QUEUE = 4, IWL_MVM_DQA_MIN_MGMT_QUEUE = 5, IWL_MVM_DQA_MAX_MGMT_QUEUE = 8, IWL_MVM_DQA_MIN_DATA_QUEUE = 10, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 3f36a661ec96..e157bd5a2204 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -336,7 +336,8 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, * as aggregatable. * Mark all DATA queues as allowing to be aggregated at some point */ - cfg.aggregate = (queue >= IWL_MVM_DQA_MIN_DATA_QUEUE); + cfg.aggregate = (queue >= IWL_MVM_DQA_MIN_DATA_QUEUE || + queue == IWL_MVM_DQA_BSS_CLIENT_QUEUE); IWL_DEBUG_TX_QUEUES(mvm, "Allocating queue #%d to sta %d on tid %d\n", queue, mvmsta->sta_id, tid); @@ -448,7 +449,8 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) } static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, + enum nl80211_iftype vif_type) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); int queue; @@ -456,8 +458,13 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, spin_lock_bh(&mvm->queue_info_lock); /* Make sure we have free resources for this STA */ - queue = iwl_mvm_find_free_queue(mvm, IWL_MVM_DQA_MIN_DATA_QUEUE, - IWL_MVM_DQA_MAX_DATA_QUEUE); + if (vif_type == NL80211_IFTYPE_STATION && !sta->tdls && + !mvm->queue_info[IWL_MVM_DQA_BSS_CLIENT_QUEUE].hw_queue_refcount && + !mvm->queue_info[IWL_MVM_DQA_BSS_CLIENT_QUEUE].setup_reserved) + queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE; + else + queue = iwl_mvm_find_free_queue(mvm, IWL_MVM_DQA_MIN_DATA_QUEUE, + IWL_MVM_DQA_MAX_DATA_QUEUE); if (queue < 0) { spin_unlock_bh(&mvm->queue_info_lock); IWL_ERR(mvm, "No available queues for new station\n"); @@ -551,7 +558,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, } if (iwl_mvm_is_dqa_supported(mvm)) { - ret = iwl_mvm_reserve_sta_stream(mvm, sta); + ret = iwl_mvm_reserve_sta_stream(mvm, sta, + ieee80211_vif_type_p2p(vif)); if (ret) goto err; } -- GitLab From f02669be45b44ffbb70d2f721f47544629f7a9a4 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 28 Feb 2016 16:15:07 +0200 Subject: [PATCH 0764/9938] iwlwifi: mvm: set sta_id in SCD_QUEUE_CONFIG cmd Set the correct sta_id in the SCD_QUEUE_CONFIG command sent to the FW when enabling/disabling queues. This is needed in DQA-mode to allow the FW to associate between queue and STA. Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index a9de2ad642bc..cd5f16e9cab4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -665,6 +665,7 @@ struct iwl_mvm { /* Map to HW queue */ u32 hw_queue_to_mac80211; u8 hw_queue_refcount; + u8 ra_sta_id; /* The RA this queue is mapped to, if exists */ /* * This is to mark that queue is reserved for a STA but not yet * allocated. This is needed to make sure we have at least one diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 76866b9e5686..486c98541afc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -608,6 +608,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, mvm->queue_info[queue].hw_queue_refcount++; if (mvm->queue_info[queue].hw_queue_refcount > 1) enable_queue = false; + else + mvm->queue_info[queue].ra_sta_id = cfg->sta_id; mvm->queue_info[queue].tid_bitmap |= BIT(cfg->tid); IWL_DEBUG_TX_QUEUES(mvm, @@ -693,6 +695,8 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, return; } + cmd.sta_id = mvm->queue_info[queue].ra_sta_id; + /* Make sure queue info is correct even though we overwrite it */ WARN(mvm->queue_info[queue].hw_queue_refcount || mvm->queue_info[queue].tid_bitmap || -- GitLab From 0e0e44205c14b557606b498ff0fcad53c7c2430a Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 4 Aug 2015 15:13:38 +0300 Subject: [PATCH 0765/9938] iwlwifi: mvm: allocate dedicated queue for cab in dqa mode In DQA mode, allocate a dedicated queue (#3) for content after beacon (AKA "CaB"). Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/mvm/fw-api.h | 2 ++ .../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 965268766ac2..b38cb03ec086 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -89,6 +89,7 @@ enum { /* * DQA queue numbers * + * @IWL_MVM_DQA_GCAST_QUEUE: a queue reserved for P2P GO/SoftAP GCAST frames * @IWL_MVM_DQA_BSS_CLIENT_QUEUE: a queue reserved for BSS activity, to ensure * that we are never left without the possibility to connect to an AP. * @IWL_MVM_DQA_MIN_MGMT_QUEUE: first TXQ in pool for MGMT and non-QOS frames. @@ -102,6 +103,7 @@ enum { * @IWL_MVM_DQA_MAX_DATA_QUEUE: last TXQ in pool for DATA frames */ enum iwl_mvm_dqa_txq { + IWL_MVM_DQA_GCAST_QUEUE = 3, IWL_MVM_DQA_BSS_CLIENT_QUEUE = 4, IWL_MVM_DQA_MIN_MGMT_QUEUE = 5, IWL_MVM_DQA_MAX_MGMT_QUEUE = 8, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index c02c1055d534..43fd85725d45 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -447,13 +447,19 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, /* Allocate the CAB queue for softAP and GO interfaces */ if (vif->type == NL80211_IFTYPE_AP) { - u8 queue = find_first_zero_bit(&used_hw_queues, - mvm->first_agg_queue); + u8 queue; - if (queue >= mvm->first_agg_queue) { - IWL_ERR(mvm, "Failed to allocate cab queue\n"); - ret = -EIO; - goto exit_fail; + if (!iwl_mvm_is_dqa_supported(mvm)) { + queue = find_first_zero_bit(&used_hw_queues, + mvm->first_agg_queue); + + if (queue >= mvm->first_agg_queue) { + IWL_ERR(mvm, "Failed to allocate cab queue\n"); + ret = -EIO; + goto exit_fail; + } + } else { + queue = IWL_MVM_DQA_GCAST_QUEUE; } vif->cab_queue = queue; -- GitLab From 097129c9e62540122b63cba79c1843a2602bec37 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 9 Aug 2015 18:28:43 +0300 Subject: [PATCH 0766/9938] iwlwifi: mvm: move cmd queue to be #0 in dqa mode Change the CMD queue to be queue #0 (rather than queue #9) when working in DQA mode. Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 8 ++++++-- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index b38cb03ec086..60eed8485aba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -89,6 +89,7 @@ enum { /* * DQA queue numbers * + * @IWL_MVM_DQA_CMD_QUEUE: a queue reserved for sending HCMDs to the FW * @IWL_MVM_DQA_GCAST_QUEUE: a queue reserved for P2P GO/SoftAP GCAST frames * @IWL_MVM_DQA_BSS_CLIENT_QUEUE: a queue reserved for BSS activity, to ensure * that we are never left without the possibility to connect to an AP. @@ -103,6 +104,7 @@ enum { * @IWL_MVM_DQA_MAX_DATA_QUEUE: last TXQ in pool for DATA frames */ enum iwl_mvm_dqa_txq { + IWL_MVM_DQA_CMD_QUEUE = 0, IWL_MVM_DQA_GCAST_QUEUE = 3, IWL_MVM_DQA_BSS_CLIENT_QUEUE = 4, IWL_MVM_DQA_MIN_MGMT_QUEUE = 5, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 2dc97a19246a..6ad5c602e84c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -652,7 +652,10 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, */ memset(&mvm->queue_info, 0, sizeof(mvm->queue_info)); - mvm->queue_info[IWL_MVM_CMD_QUEUE].hw_queue_refcount = 1; + if (iwl_mvm_is_dqa_supported(mvm)) + mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].hw_queue_refcount = 1; + else + mvm->queue_info[IWL_MVM_CMD_QUEUE].hw_queue_refcount = 1; for (i = 0; i < IEEE80211_MAX_QUEUES; i++) atomic_set(&mvm->mac80211_queue_stop_count[i], 0); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 43fd85725d45..5f950568e92c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -252,10 +252,14 @@ unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, .exclude_vif = exclude_vif, .used_hw_queues = BIT(IWL_MVM_OFFCHANNEL_QUEUE) | - BIT(mvm->aux_queue) | - BIT(IWL_MVM_CMD_QUEUE), + BIT(mvm->aux_queue), }; + if (iwl_mvm_is_dqa_supported(mvm)) + data.used_hw_queues |= BIT(IWL_MVM_DQA_CMD_QUEUE); + else + data.used_hw_queues |= BIT(IWL_MVM_CMD_QUEUE); + lockdep_assert_held(&mvm->mutex); /* mark all VIF used hw queues */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index e36bcade69d1..cb0092609595 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -619,7 +619,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, trans_cfg.command_groups = iwl_mvm_groups; trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups); - trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE; + if (iwl_mvm_is_dqa_supported(mvm)) + trans_cfg.cmd_queue = IWL_MVM_DQA_CMD_QUEUE; + else + trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE; trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD; trans_cfg.scd_set_active = true; -- GitLab From 728e825f81b1fe29eb177148fcabfa55a7f4c1bb Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 11 Mar 2016 09:20:37 +0200 Subject: [PATCH 0767/9938] iwlwifi: mvm: add a scan timeout for regular scans If something goes wrong with the firmware and we never get a scan complete notification, we stay stuck forever. In order to avoid this situation, add a timeout and trigger an NMI if it expires before receiving the notification., so we can clean things up. Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 +++++ drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 21 +++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index cd5f16e9cab4..2d685e02d488 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -710,6 +710,7 @@ struct iwl_mvm { struct iwl_mcast_filter_cmd *mcast_filter_cmd; enum iwl_mvm_scan_type scan_type; enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all; + struct timer_list scan_timer; /* max number of simultaneous scans the FW supports */ unsigned int max_scans; @@ -1314,6 +1315,7 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm); int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify); int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm); void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm); +void iwl_mvm_scan_timeout(unsigned long data); /* Scheduled scan */ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index cb0092609595..656541c5360a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -728,6 +728,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, iwl_mvm_tof_init(mvm); + setup_timer(&mvm->scan_timer, iwl_mvm_scan_timeout, + (unsigned long)mvm); + return op_mode; out_unregister: @@ -783,6 +786,8 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) iwl_mvm_tof_clean(mvm); + del_timer_sync(&mvm->scan_timer); + mutex_destroy(&mvm->mutex); mutex_destroy(&mvm->d0i3_suspend_mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 25b007cf7db7..c1d1be9c5d01 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -70,6 +70,7 @@ #include "mvm.h" #include "fw-api-scan.h" +#include "iwl-io.h" #define IWL_DENSE_EBS_SCAN_RATIO 5 #define IWL_SPARSE_EBS_SCAN_RATIO 1 @@ -398,6 +399,10 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, ieee80211_scan_completed(mvm->hw, scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED); iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); + del_timer(&mvm->scan_timer); + } else { + IWL_ERR(mvm, + "got scan complete notification but no scan is running\n"); } mvm->last_ebs_successful = @@ -1217,6 +1222,18 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type) return -EIO; } +#define SCAN_TIMEOUT (16 * HZ) + +void iwl_mvm_scan_timeout(unsigned long data) +{ + struct iwl_mvm *mvm = (struct iwl_mvm *)data; + + IWL_ERR(mvm, "regular scan timed out\n"); + + del_timer(&mvm->scan_timer); + iwl_force_nmi(mvm->trans); +} + int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_scan_request *req, struct ieee80211_scan_ies *ies) @@ -1296,6 +1313,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvm->scan_status |= IWL_MVM_SCAN_REGULAR; iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); + mod_timer(&mvm->scan_timer, jiffies + SCAN_TIMEOUT); + return 0; } @@ -1413,6 +1432,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) { ieee80211_scan_completed(mvm->hw, aborted); iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); + del_timer(&mvm->scan_timer); } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { ieee80211_sched_scan_stopped(mvm->hw); mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; @@ -1608,6 +1628,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify) * to release the scan reference here. */ iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); + del_timer(&mvm->scan_timer); if (notify) ieee80211_scan_completed(mvm->hw, true); } else if (notify) { -- GitLab From 5e6a98dc4863e50a010ebdf09fa63c1e11929a85 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 10 Mar 2016 17:40:56 +0200 Subject: [PATCH 0768/9938] iwlwifi: mvm: enable TCP/UDP checksum support for 9000 family Declare and enable support of RX and TX checksum for 9000 family. Configure offload_assist in the TX cmd accordingly to support TX csum. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 1 + .../net/wireless/intel/iwlwifi/iwl-config.h | 2 + .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 13 +- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 124 +++++++++++++++++- 4 files changed, 133 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index 277396a30713..1f25ba69516f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -137,6 +137,7 @@ static const struct iwl_tt_params iwl9000_tt_params = { .dccm2_len = IWL9000_DCCM2_LEN, \ .smem_offset = IWL9000_SMEM_OFFSET, \ .smem_len = IWL9000_SMEM_LEN, \ + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \ .thermal_params = &iwl9000_tt_params, \ .apmg_not_supported = true, \ .mq_rx_supported = true, \ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 8cbd24875ffc..b0025570c7bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -131,6 +131,8 @@ enum iwl_led_mode { #define IWL_MAX_WD_TIMEOUT 120000 #define IWL_DEFAULT_MAX_TX_POWER 22 +#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\ + NETIF_F_TSO | NETIF_F_TSO6) /* Antenna presence definitions */ #define ANT_NONE 0x0 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 115d7aa5e720..4f5ec495b460 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -665,12 +665,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) } hw->netdev_features |= mvm->cfg->features; - if (!iwl_mvm_is_csum_supported(mvm)) - hw->netdev_features &= ~NETIF_F_RXCSUM; - - if (IWL_MVM_SW_TX_CSUM_OFFLOAD) - hw->netdev_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_TSO | NETIF_F_TSO6; + if (!iwl_mvm_is_csum_supported(mvm)) { + hw->netdev_features &= ~(IWL_TX_CSUM_NETIF_FLAGS | + NETIF_F_RXCSUM); + /* We may support SW TX CSUM */ + if (IWL_MVM_SW_TX_CSUM_OFFLOAD) + hw->netdev_features |= IWL_TX_CSUM_NETIF_FLAGS; + } ret = ieee80211_register_hw(mvm->hw); if (ret) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 24cff98ecca0..efb9b98c4c98 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -67,6 +67,7 @@ #include #include #include +#include #include "iwl-trans.h" #include "iwl-eeprom-parse.h" @@ -98,6 +99,111 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr, addr, tid, ssn); } +#define OPT_HDR(type, skb, off) \ + (type *)(skb_network_header(skb) + (off)) + +static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, + struct ieee80211_hdr *hdr, + struct ieee80211_tx_info *info, + struct iwl_tx_cmd *tx_cmd) +{ +#if IS_ENABLED(CONFIG_INET) + u16 mh_len = ieee80211_hdrlen(hdr->frame_control); + u16 offload_assist = le16_to_cpu(tx_cmd->offload_assist); + u8 protocol = 0; + + /* + * Do not compute checksum if already computed or if transport will + * compute it + */ + if (skb->ip_summed != CHECKSUM_PARTIAL || IWL_MVM_SW_TX_CSUM_OFFLOAD) + return; + + /* We do not expect to be requested to csum stuff we do not support */ + if (WARN_ONCE(!(mvm->hw->netdev_features & IWL_TX_CSUM_NETIF_FLAGS) || + (skb->protocol != htons(ETH_P_IP) && + skb->protocol != htons(ETH_P_IPV6)), + "No support for requested checksum\n")) { + skb_checksum_help(skb); + return; + } + + if (skb->protocol == htons(ETH_P_IP)) { + protocol = ip_hdr(skb)->protocol; + } else { +#if IS_ENABLED(CONFIG_IPV6) + struct ipv6hdr *ipv6h = + (struct ipv6hdr *)skb_network_header(skb); + unsigned int off = sizeof(*ipv6h); + + protocol = ipv6h->nexthdr; + while (protocol != NEXTHDR_NONE && ipv6_ext_hdr(protocol)) { + /* only supported extension headers */ + if (protocol != NEXTHDR_ROUTING && + protocol != NEXTHDR_HOP && + protocol != NEXTHDR_DEST && + protocol != NEXTHDR_FRAGMENT) { + skb_checksum_help(skb); + return; + } + + if (protocol == NEXTHDR_FRAGMENT) { + struct frag_hdr *hp = + OPT_HDR(struct frag_hdr, skb, off); + + protocol = hp->nexthdr; + off += sizeof(struct frag_hdr); + } else { + struct ipv6_opt_hdr *hp = + OPT_HDR(struct ipv6_opt_hdr, skb, off); + + protocol = hp->nexthdr; + off += ipv6_optlen(hp); + } + } + /* if we get here - protocol now should be TCP/UDP */ +#endif + } + + if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) { + WARN_ON_ONCE(1); + skb_checksum_help(skb); + return; + } + + /* enable L4 csum */ + offload_assist |= BIT(TX_CMD_OFFLD_L4_EN); + + /* + * Set offset to IP header (snap). + * We don't support tunneling so no need to take care of inner header. + * Size is in words. + */ + offload_assist |= (4 << TX_CMD_OFFLD_IP_HDR); + + /* Do IPv4 csum for AMSDU only (no IP csum for Ipv6) */ + if (skb->protocol == htons(ETH_P_IP) && + (offload_assist & BIT(TX_CMD_OFFLD_AMSDU))) { + ip_hdr(skb)->check = 0; + offload_assist |= BIT(TX_CMD_OFFLD_L3_EN); + } + + /* reset UDP/TCP header csum */ + if (protocol == IPPROTO_TCP) + tcp_hdr(skb)->check = 0; + else + udp_hdr(skb)->check = 0; + + /* mac header len should include IV, size is in words */ + if (info->control.hw_key) + mh_len += info->control.hw_key->iv_len; + mh_len /= 2; + offload_assist |= mh_len << TX_CMD_OFFLD_MH_SIZE; + + tx_cmd->offload_assist = cpu_to_le16(offload_assist); +#endif +} + /* * Sets most of the Tx cmd's fields */ @@ -196,6 +302,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, if (ieee80211_hdrlen(fc) % 4 && !(tx_cmd->offload_assist & cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU)))) tx_cmd->offload_assist |= cpu_to_le16(BIT(TX_CMD_OFFLD_PAD)); + + iwl_mvm_tx_csum(mvm, skb, hdr, info, tx_cmd); } /* @@ -466,6 +574,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; u16 amsdu_add, snap_ip_tcp, pad, i = 0; unsigned int dbg_max_amsdu_len; + netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG; u8 *qc, tid, txf; snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) + @@ -484,6 +593,19 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, goto segment; } + /* + * Do not build AMSDU for IPv6 with extension headers. + * ask stack to segment and checkum the generated MPDUs for us. + */ + if (skb->protocol == htons(ETH_P_IPV6) && + ((struct ipv6hdr *)skb_network_header(skb))->nexthdr != + IPPROTO_TCP) { + num_subframes = 1; + pad = 0; + netdev_features &= ~NETIF_F_CSUM_MASK; + goto segment; + } + /* * No need to lock amsdu_in_ampdu_allowed since it can't be modified * during an BA session. @@ -577,7 +699,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, skb_shinfo(skb)->gso_size = num_subframes * mss; memcpy(cb, skb->cb, sizeof(cb)); - next = skb_gso_segment(skb, NETIF_F_CSUM_MASK | NETIF_F_SG); + next = skb_gso_segment(skb, netdev_features); skb_shinfo(skb)->gso_size = mss; if (WARN_ON_ONCE(IS_ERR(next))) return -EINVAL; -- GitLab From 9d9b21d1b61647d5a37241571c0e3eb7cc04b348 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 24 Mar 2016 08:44:57 +0200 Subject: [PATCH 0769/9938] iwlwifi: remove IWL_*_UCODE_API_OK _UCODE_API_OK was a intermediate version between MIN and MAX. If a user had a firmware below _OK but above _MIN, the driver would work but the user would get a warning in the kernel log telling him to update his firmware. This is not needed since most users won't look for these messages in the kernel log if their wifi is working. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-1000.c | 10 ++------ drivers/net/wireless/intel/iwlwifi/iwl-2000.c | 18 ++++---------- drivers/net/wireless/intel/iwlwifi/iwl-5000.c | 11 ++------- drivers/net/wireless/intel/iwlwifi/iwl-6000.c | 20 ++++------------ drivers/net/wireless/intel/iwlwifi/iwl-7000.c | 20 ++++------------ drivers/net/wireless/intel/iwlwifi/iwl-8000.c | 11 ++------- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 6 +---- .../net/wireless/intel/iwlwifi/iwl-config.h | 3 --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 24 +------------------ 9 files changed, 21 insertions(+), 102 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-1000.c b/drivers/net/wireless/intel/iwlwifi/iwl-1000.c index a90dbab6bbbe..ef22c3d168fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-1000.c @@ -34,10 +34,6 @@ #define IWL1000_UCODE_API_MAX 5 #define IWL100_UCODE_API_MAX 5 -/* Oldest version we won't warn about */ -#define IWL1000_UCODE_API_OK 5 -#define IWL100_UCODE_API_OK 5 - /* Lowest firmware API version supported */ #define IWL1000_UCODE_API_MIN 1 #define IWL100_UCODE_API_MIN 5 @@ -86,7 +82,6 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = { #define IWL_DEVICE_1000 \ .fw_name_pre = IWL1000_FW_PRE, \ .ucode_api_max = IWL1000_UCODE_API_MAX, \ - .ucode_api_ok = IWL1000_UCODE_API_OK, \ .ucode_api_min = IWL1000_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_1000, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \ @@ -112,7 +107,6 @@ const struct iwl_cfg iwl1000_bg_cfg = { #define IWL_DEVICE_100 \ .fw_name_pre = IWL100_FW_PRE, \ .ucode_api_max = IWL100_UCODE_API_MAX, \ - .ucode_api_ok = IWL100_UCODE_API_OK, \ .ucode_api_min = IWL100_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_100, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \ @@ -136,5 +130,5 @@ const struct iwl_cfg iwl100_bg_cfg = { IWL_DEVICE_100, }; -MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_OK)); -MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_OK)); +MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-2000.c b/drivers/net/wireless/intel/iwlwifi/iwl-2000.c index a6da9594c4a5..dc246c997084 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-2000.c @@ -36,12 +36,6 @@ #define IWL105_UCODE_API_MAX 6 #define IWL135_UCODE_API_MAX 6 -/* Oldest version we won't warn about */ -#define IWL2030_UCODE_API_OK 6 -#define IWL2000_UCODE_API_OK 6 -#define IWL105_UCODE_API_OK 6 -#define IWL135_UCODE_API_OK 6 - /* Lowest firmware API version supported */ #define IWL2030_UCODE_API_MIN 5 #define IWL2000_UCODE_API_MIN 5 @@ -114,7 +108,6 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = { #define IWL_DEVICE_2000 \ .fw_name_pre = IWL2000_FW_PRE, \ .ucode_api_max = IWL2000_UCODE_API_MAX, \ - .ucode_api_ok = IWL2000_UCODE_API_OK, \ .ucode_api_min = IWL2000_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_2000, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -142,7 +135,6 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { #define IWL_DEVICE_2030 \ .fw_name_pre = IWL2030_FW_PRE, \ .ucode_api_max = IWL2030_UCODE_API_MAX, \ - .ucode_api_ok = IWL2030_UCODE_API_OK, \ .ucode_api_min = IWL2030_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_2030, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -163,7 +155,6 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { #define IWL_DEVICE_105 \ .fw_name_pre = IWL105_FW_PRE, \ .ucode_api_max = IWL105_UCODE_API_MAX, \ - .ucode_api_ok = IWL105_UCODE_API_OK, \ .ucode_api_min = IWL105_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_105, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -191,7 +182,6 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { #define IWL_DEVICE_135 \ .fw_name_pre = IWL135_FW_PRE, \ .ucode_api_max = IWL135_UCODE_API_MAX, \ - .ucode_api_ok = IWL135_UCODE_API_OK, \ .ucode_api_min = IWL135_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_135, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -210,7 +200,7 @@ const struct iwl_cfg iwl135_bgn_cfg = { .ht_params = &iwl2000_ht_params, }; -MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_OK)); -MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_OK)); -MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_OK)); -MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_OK)); +MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-5000.c b/drivers/net/wireless/intel/iwlwifi/iwl-5000.c index 8b5afdef2d83..4dcdab6781cc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-5000.c @@ -34,10 +34,6 @@ #define IWL5000_UCODE_API_MAX 5 #define IWL5150_UCODE_API_MAX 2 -/* Oldest version we won't warn about */ -#define IWL5000_UCODE_API_OK 5 -#define IWL5150_UCODE_API_OK 2 - /* Lowest firmware API version supported */ #define IWL5000_UCODE_API_MIN 1 #define IWL5150_UCODE_API_MIN 1 @@ -84,7 +80,6 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = { #define IWL_DEVICE_5000 \ .fw_name_pre = IWL5000_FW_PRE, \ .ucode_api_max = IWL5000_UCODE_API_MAX, \ - .ucode_api_ok = IWL5000_UCODE_API_OK, \ .ucode_api_min = IWL5000_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_5000, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \ @@ -132,7 +127,6 @@ const struct iwl_cfg iwl5350_agn_cfg = { .name = "Intel(R) WiMAX/WiFi Link 5350 AGN", .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_ok = IWL5000_UCODE_API_OK, .ucode_api_min = IWL5000_UCODE_API_MIN, .device_family = IWL_DEVICE_FAMILY_5000, .max_inst_size = IWLAGN_RTC_INST_SIZE, @@ -149,7 +143,6 @@ const struct iwl_cfg iwl5350_agn_cfg = { #define IWL_DEVICE_5150 \ .fw_name_pre = IWL5150_FW_PRE, \ .ucode_api_max = IWL5150_UCODE_API_MAX, \ - .ucode_api_ok = IWL5150_UCODE_API_OK, \ .ucode_api_min = IWL5150_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_5150, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \ @@ -174,5 +167,5 @@ const struct iwl_cfg iwl5150_abg_cfg = { IWL_DEVICE_5150, }; -MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_OK)); -MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_OK)); +MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c index 0b4ba781b631..9938f5340ac0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c @@ -36,13 +36,6 @@ #define IWL6000G2_UCODE_API_MAX 6 #define IWL6035_UCODE_API_MAX 6 -/* Oldest version we won't warn about */ -#define IWL6000_UCODE_API_OK 4 -#define IWL6000G2_UCODE_API_OK 5 -#define IWL6050_UCODE_API_OK 5 -#define IWL6000G2B_UCODE_API_OK 6 -#define IWL6035_UCODE_API_OK 6 - /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 @@ -136,7 +129,6 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = { #define IWL_DEVICE_6005 \ .fw_name_pre = IWL6005_FW_PRE, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ - .ucode_api_ok = IWL6000G2_UCODE_API_OK, \ .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_6005, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -191,7 +183,6 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { #define IWL_DEVICE_6030 \ .fw_name_pre = IWL6030_FW_PRE, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ - .ucode_api_ok = IWL6000G2B_UCODE_API_OK, \ .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_6030, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -228,7 +219,6 @@ const struct iwl_cfg iwl6030_2bg_cfg = { #define IWL_DEVICE_6035 \ .fw_name_pre = IWL6030_FW_PRE, \ .ucode_api_max = IWL6035_UCODE_API_MAX, \ - .ucode_api_ok = IWL6035_UCODE_API_OK, \ .ucode_api_min = IWL6035_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_6030, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -282,7 +272,6 @@ const struct iwl_cfg iwl130_bg_cfg = { #define IWL_DEVICE_6000i \ .fw_name_pre = IWL6000_FW_PRE, \ .ucode_api_max = IWL6000_UCODE_API_MAX, \ - .ucode_api_ok = IWL6000_UCODE_API_OK, \ .ucode_api_min = IWL6000_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_6000i, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -370,7 +359,6 @@ const struct iwl_cfg iwl6000_3agn_cfg = { .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_ok = IWL6000_UCODE_API_OK, .ucode_api_min = IWL6000_UCODE_API_MIN, .device_family = IWL_DEVICE_FAMILY_6000, .max_inst_size = IWL60_RTC_INST_SIZE, @@ -383,7 +371,7 @@ const struct iwl_cfg iwl6000_3agn_cfg = { .led_mode = IWL_LED_BLINK, }; -MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_OK)); -MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_OK)); -MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_OK)); -MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_OK)); +MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index f4012a3f4d06..b6283c881d42 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c @@ -76,12 +76,6 @@ #define IWL7265D_UCODE_API_MAX 21 #define IWL3168_UCODE_API_MAX 21 -/* Oldest version we won't warn about */ -#define IWL7260_UCODE_API_OK 16 -#define IWL7265_UCODE_API_OK 16 -#define IWL7265D_UCODE_API_OK 16 -#define IWL3168_UCODE_API_OK 20 - /* Lowest firmware API version supported */ #define IWL7260_UCODE_API_MIN 16 #define IWL7265_UCODE_API_MIN 16 @@ -179,25 +173,21 @@ static const struct iwl_ht_params iwl7000_ht_params = { #define IWL_DEVICE_7000 \ IWL_DEVICE_7000_COMMON, \ .ucode_api_max = IWL7260_UCODE_API_MAX, \ - .ucode_api_ok = IWL7260_UCODE_API_OK, \ .ucode_api_min = IWL7260_UCODE_API_MIN #define IWL_DEVICE_7005 \ IWL_DEVICE_7000_COMMON, \ .ucode_api_max = IWL7265_UCODE_API_MAX, \ - .ucode_api_ok = IWL7265_UCODE_API_OK, \ .ucode_api_min = IWL7265_UCODE_API_MIN #define IWL_DEVICE_3008 \ IWL_DEVICE_7000_COMMON, \ .ucode_api_max = IWL3168_UCODE_API_MAX, \ - .ucode_api_ok = IWL3168_UCODE_API_OK, \ .ucode_api_min = IWL3168_UCODE_API_MIN #define IWL_DEVICE_7005D \ IWL_DEVICE_7000_COMMON, \ .ucode_api_max = IWL7265D_UCODE_API_MAX, \ - .ucode_api_ok = IWL7265D_UCODE_API_OK, \ .ucode_api_min = IWL7265D_UCODE_API_MIN const struct iwl_cfg iwl7260_2ac_cfg = { @@ -388,8 +378,8 @@ const struct iwl_cfg iwl7265d_n_cfg = { .dccm_len = IWL7265_DCCM_LEN, }; -MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); -MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); -MODULE_FIRMWARE(IWL3168_MODULE_FIRMWARE(IWL3168_UCODE_API_OK)); -MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK)); -MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK)); +MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL3168_MODULE_FIRMWARE(IWL3168_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index 49bb2a5f9dcf..0728a288aa3d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -73,10 +73,6 @@ #define IWL8000_UCODE_API_MAX 21 #define IWL8265_UCODE_API_MAX 21 -/* Oldest version we won't warn about */ -#define IWL8000_UCODE_API_OK 16 -#define IWL8265_UCODE_API_OK 20 - /* Lowest firmware API version supported */ #define IWL8000_UCODE_API_MIN 16 #define IWL8265_UCODE_API_MIN 20 @@ -175,19 +171,16 @@ static const struct iwl_tt_params iwl8000_tt_params = { #define IWL_DEVICE_8000 \ IWL_DEVICE_8000_COMMON, \ .ucode_api_max = IWL8000_UCODE_API_MAX, \ - .ucode_api_ok = IWL8000_UCODE_API_OK, \ .ucode_api_min = IWL8000_UCODE_API_MIN \ #define IWL_DEVICE_8260 \ IWL_DEVICE_8000_COMMON, \ .ucode_api_max = IWL8000_UCODE_API_MAX, \ - .ucode_api_ok = IWL8000_UCODE_API_OK, \ .ucode_api_min = IWL8000_UCODE_API_MIN \ #define IWL_DEVICE_8265 \ IWL_DEVICE_8000_COMMON, \ .ucode_api_max = IWL8265_UCODE_API_MAX, \ - .ucode_api_ok = IWL8265_UCODE_API_OK, \ .ucode_api_min = IWL8265_UCODE_API_MIN \ const struct iwl_cfg iwl8260_2n_cfg = { @@ -259,5 +252,5 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = { .max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO, }; -MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); -MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_OK)); +MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index 1f25ba69516f..a3d35aa291a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -57,9 +57,6 @@ /* Highest firmware API version supported */ #define IWL9000_UCODE_API_MAX 21 -/* Oldest version we won't warn about */ -#define IWL9000_UCODE_API_OK 16 - /* Lowest firmware API version supported */ #define IWL9000_UCODE_API_MIN 16 @@ -122,7 +119,6 @@ static const struct iwl_tt_params iwl9000_tt_params = { #define IWL_DEVICE_9000 \ .ucode_api_max = IWL9000_UCODE_API_MAX, \ - .ucode_api_ok = IWL9000_UCODE_API_OK, \ .ucode_api_min = IWL9000_UCODE_API_MIN, \ .device_family = IWL_DEVICE_FAMILY_8000, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ @@ -164,4 +160,4 @@ const struct iwl_cfg iwl5165_2ac_cfg = { .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, }; -MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_OK)); +MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index b0025570c7bb..08bb4f4e424a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -279,8 +279,6 @@ struct iwl_pwr_tx_backoff { * (.ucode) will be added to filename before loading from disk. The * filename is constructed as fw_name_pre.ucode. * @ucode_api_max: Highest version of uCode API supported by driver. - * @ucode_api_ok: oldest version of the uCode API that is OK to load - * without a warning, for use in transitions * @ucode_api_min: Lowest version of uCode API supported by driver. * @max_inst_size: The maximal length of the fw inst section * @max_data_size: The maximal length of the fw data section @@ -326,7 +324,6 @@ struct iwl_cfg { const char *name; const char *fw_name_pre; const unsigned int ucode_api_max; - const unsigned int ucode_api_ok; const unsigned int ucode_api_min; const enum iwl_device_family device_family; const u32 max_data_size; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 9a680ac48820..605910f71037 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1206,7 +1206,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) int err; struct iwl_firmware_pieces *pieces; const unsigned int api_max = drv->cfg->ucode_api_max; - unsigned int api_ok = drv->cfg->ucode_api_ok; const unsigned int api_min = drv->cfg->ucode_api_min; size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX]; u32 api_ver; @@ -1219,20 +1218,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS; - if (!api_ok) - api_ok = api_max; - pieces = kzalloc(sizeof(*pieces), GFP_KERNEL); if (!pieces) return; - if (!ucode_raw) { - if (drv->fw_index <= api_ok) - IWL_ERR(drv, - "request for firmware file '%s' failed.\n", - drv->firmware_name); + if (!ucode_raw) goto try_again; - } IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n", drv->firmware_name, ucode_raw->size); @@ -1271,19 +1262,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) api_max, api_ver); goto try_again; } - - if (api_ver < api_ok) { - if (api_ok != api_max) - IWL_ERR(drv, "Firmware has old API version, " - "expected v%u through v%u, got v%u.\n", - api_ok, api_max, api_ver); - else - IWL_ERR(drv, "Firmware has old API version, " - "expected v%u, got v%u.\n", - api_max, api_ver); - IWL_ERR(drv, "New firmware can be obtained from " - "http://www.intellinuxwireless.org/.\n"); - } } /* -- GitLab From 8d80717a12c138f3d765d91feab0c08190a21d85 Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Sun, 27 Mar 2016 12:56:13 +0300 Subject: [PATCH 0770/9938] iwlwifi: pcie: Fix index iteration on free_irq in MSIX mode In MSIX mode we iterate over the allocated interrupt vectors and register them to an handler. In case of registration failure, we free all the allocated irq. we use the outer index mistakenly instead of the inner one. Signed-off-by: Haim Dreyfuss Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f1a506b609d7..5e1a13e82d60 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1500,8 +1500,8 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev, IWL_ERR(trans_pcie->trans, "Error allocating IRQ %d\n", i); for (j = 0; j < i; j++) - free_irq(trans_pcie->msix_entries[i].vector, - &trans_pcie->msix_entries[i]); + free_irq(trans_pcie->msix_entries[j].vector, + &trans_pcie->msix_entries[j]); pci_disable_msix(pdev); return ret; } -- GitLab From a6017b9030f280ced61b825757b26f042e0785da Mon Sep 17 00:00:00 2001 From: Golan Ben-Ami Date: Mon, 14 Mar 2016 12:24:20 +0200 Subject: [PATCH 0771/9938] iwlwifi: store fw memory segments length and addresses in run-time Currently reading the fw memory segments is done according to addresses and data length that are hard-coded. Lately a new tlv was appended to the ucode, that contains the data type, length and address. Parse this tlv, and in run-time store the memory segments length and addresses that would be dumped upon a fw error. Signed-off-by: Golan Ben-Ami Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 45 ++++++++++++++ .../net/wireless/intel/iwlwifi/iwl-fw-file.h | 32 ++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-fw.h | 2 + .../net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 61 ++++++++++++++----- 4 files changed, 125 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 605910f71037..48e873732d4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -179,6 +179,8 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) kfree(drv->fw.dbg_conf_tlv[i]); for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) kfree(drv->fw.dbg_trigger_tlv[i]); + for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_mem_tlv); i++) + kfree(drv->fw.dbg_mem_tlv[i]); for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) iwl_free_fw_img(drv, drv->fw.img + i); @@ -297,6 +299,7 @@ struct iwl_firmware_pieces { size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX]; struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX]; + struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv[FW_DBG_MEM_MAX]; }; /* @@ -1041,6 +1044,37 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, iwl_store_gscan_capa(&drv->fw, tlv_data, tlv_len); gscan_capa = true; break; + case IWL_UCODE_TLV_FW_MEM_SEG: { + struct iwl_fw_dbg_mem_seg_tlv *dbg_mem = + (void *)tlv_data; + u32 type; + + if (tlv_len != (sizeof(*dbg_mem))) + goto invalid_tlv_len; + + type = le32_to_cpu(dbg_mem->data_type); + drv->fw.dbg_dynamic_mem = true; + + if (type >= ARRAY_SIZE(drv->fw.dbg_mem_tlv)) { + IWL_ERR(drv, + "Skip unknown dbg mem segment: %u\n", + dbg_mem->data_type); + break; + } + + if (pieces->dbg_mem_tlv[type]) { + IWL_ERR(drv, + "Ignore duplicate mem segment: %u\n", + dbg_mem->data_type); + break; + } + + IWL_DEBUG_INFO(drv, "Found debug memory segment: %u\n", + dbg_mem->data_type); + + pieces->dbg_mem_tlv[type] = dbg_mem; + break; + } default: IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); break; @@ -1350,6 +1384,17 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) } } + for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_mem_tlv); i++) { + if (pieces->dbg_mem_tlv[i]) { + drv->fw.dbg_mem_tlv[i] = + kmemdup(pieces->dbg_mem_tlv[i], + sizeof(*drv->fw.dbg_mem_tlv[i]), + GFP_KERNEL); + if (!drv->fw.dbg_mem_tlv[i]) + goto out_free_fw; + } + } + /* Now that we can no longer fail, copy information */ /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index a6e8826c61db..843232bd8bbe 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -142,6 +142,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_FW_DBG_CONF = 39, IWL_UCODE_TLV_FW_DBG_TRIGGER = 40, IWL_UCODE_TLV_FW_GSCAN_CAPA = 50, + IWL_UCODE_TLV_FW_MEM_SEG = 51, }; struct iwl_ucode_tlv { @@ -491,6 +492,37 @@ enum iwl_fw_dbg_monitor_mode { MIPI_MODE = 3, }; +/** + * enum iwl_fw_mem_seg_type - data types for dumping on error + * + * @FW_DBG_MEM_SMEM: the data type is SMEM + * @FW_DBG_MEM_DCCM_LMAC: the data type is DCCM_LMAC + * @FW_DBG_MEM_DCCM_UMAC: the data type is DCCM_UMAC + */ +enum iwl_fw_dbg_mem_seg_type { + FW_DBG_MEM_DCCM_LMAC = 0, + FW_DBG_MEM_DCCM_UMAC, + FW_DBG_MEM_SMEM, + + /* Must be last */ + FW_DBG_MEM_MAX, +}; + +/** + * struct iwl_fw_dbg_mem_seg_tlv - configures the debug data memory segments + * + * @data_type: enum %iwl_fw_mem_seg_type + * @ofs: the memory segment offset + * @len: the memory segment length, in bytes + * + * This parses IWL_UCODE_TLV_FW_MEM_SEG + */ +struct iwl_fw_dbg_mem_seg_tlv { + __le32 data_type; + __le32 ofs; + __le32 len; +} __packed; + /** * struct iwl_fw_dbg_dest_tlv - configures the destination of the debug data * diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw.h index 2942571c613f..e461d631893a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw.h @@ -286,6 +286,8 @@ struct iwl_fw { struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX]; struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; + struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv[FW_DBG_MEM_MAX]; + bool dbg_dynamic_mem; size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX]; u8 dbg_dest_reg_num; struct iwl_gscan_capabilities gscan_capa; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 6ef706c13cda..cbb5947b3fab 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -488,9 +488,11 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) struct iwl_fw_error_dump_trigger_desc *dump_trig; struct iwl_mvm_dump_ptrs *fw_error_dump; u32 sram_len, sram_ofs; + struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem = + mvm->fw->dbg_mem_tlv; u32 file_len, fifo_data_len = 0, prph_len = 0, radio_len = 0; - u32 smem_len = mvm->cfg->smem_len; - u32 sram2_len = mvm->cfg->dccm2_len; + u32 smem_len = mvm->fw->dbg_dynamic_mem ? 0 : mvm->cfg->smem_len; + u32 sram2_len = mvm->fw->dbg_dynamic_mem ? 0 : mvm->cfg->dccm2_len; bool monitor_dump_only = false; int i; @@ -586,7 +588,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 + - sram_len + sizeof(*dump_mem) + fifo_data_len + prph_len + radio_len + @@ -600,6 +601,13 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) if (sram2_len) file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; + /* Make room for MEM segments */ + for (i = 0; i < ARRAY_SIZE(mvm->fw->dbg_mem_tlv); i++) { + if (fw_dbg_mem[i]) + file_len += sizeof(*dump_data) + sizeof(*dump_mem) + + le32_to_cpu(fw_dbg_mem[i]->len); + } + /* Make room for fw's virtual image pages, if it exists */ if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) file_len += mvm->num_of_paging_blk * @@ -625,6 +633,9 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) file_len += sizeof(*dump_data) + sizeof(*dump_trig) + mvm->fw_dump_desc->len; + if (!mvm->fw->dbg_dynamic_mem) + file_len += sram_len + sizeof(*dump_mem); + dump_file = vzalloc(file_len); if (!dump_file) { kfree(fw_error_dump); @@ -674,16 +685,36 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) if (monitor_dump_only) goto dump_trans_data; - dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); - dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem)); - dump_mem = (void *)dump_data->data; - dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM); - dump_mem->offset = cpu_to_le32(sram_ofs); - iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_mem->data, - sram_len); + if (!mvm->fw->dbg_dynamic_mem) { + dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); + dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem)); + dump_mem = (void *)dump_data->data; + dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM); + dump_mem->offset = cpu_to_le32(sram_ofs); + iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_mem->data, + sram_len); + dump_data = iwl_fw_error_next_data(dump_data); + } + + for (i = 0; i < ARRAY_SIZE(mvm->fw->dbg_mem_tlv); i++) { + if (fw_dbg_mem[i]) { + u32 len = le32_to_cpu(fw_dbg_mem[i]->len); + u32 ofs = le32_to_cpu(fw_dbg_mem[i]->ofs); + + dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); + dump_data->len = cpu_to_le32(len + + sizeof(*dump_mem)); + dump_mem = (void *)dump_data->data; + dump_mem->type = fw_dbg_mem[i]->data_type; + dump_mem->offset = cpu_to_le32(ofs); + iwl_trans_read_mem_bytes(mvm->trans, ofs, + dump_mem->data, + len); + dump_data = iwl_fw_error_next_data(dump_data); + } + } if (smem_len) { - dump_data = iwl_fw_error_next_data(dump_data); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); dump_data->len = cpu_to_le32(smem_len + sizeof(*dump_mem)); dump_mem = (void *)dump_data->data; @@ -691,10 +722,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) dump_mem->offset = cpu_to_le32(mvm->cfg->smem_offset); iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->smem_offset, dump_mem->data, smem_len); + dump_data = iwl_fw_error_next_data(dump_data); } if (sram2_len) { - dump_data = iwl_fw_error_next_data(dump_data); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); dump_data->len = cpu_to_le32(sram2_len + sizeof(*dump_mem)); dump_mem = (void *)dump_data->data; @@ -702,11 +733,11 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) dump_mem->offset = cpu_to_le32(mvm->cfg->dccm2_offset); iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->dccm2_offset, dump_mem->data, sram2_len); + dump_data = iwl_fw_error_next_data(dump_data); } if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 && CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP) { - dump_data = iwl_fw_error_next_data(dump_data); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); dump_data->len = cpu_to_le32(IWL8260_ICCM_LEN + sizeof(*dump_mem)); @@ -715,6 +746,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) dump_mem->offset = cpu_to_le32(IWL8260_ICCM_OFFSET); iwl_trans_read_mem_bytes(mvm->trans, IWL8260_ICCM_OFFSET, dump_mem->data, IWL8260_ICCM_LEN); + dump_data = iwl_fw_error_next_data(dump_data); } /* Dump fw's virtual image */ @@ -724,7 +756,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) struct page *pages = mvm->fw_paging_db[i].fw_paging_block; - dump_data = iwl_fw_error_next_data(dump_data); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); dump_data->len = cpu_to_le32(sizeof(*paging) + PAGING_BLOCK_SIZE); @@ -732,10 +763,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) paging->index = cpu_to_le32(i); memcpy(paging->data, page_address(pages), PAGING_BLOCK_SIZE); + dump_data = iwl_fw_error_next_data(dump_data); } } - dump_data = iwl_fw_error_next_data(dump_data); if (prph_len) iwl_dump_prph(mvm->trans, &dump_data); -- GitLab From d2515a99b2da2bf08d5a1decb7b365e25adbccea Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Wed, 23 Mar 2016 16:31:08 +0200 Subject: [PATCH 0772/9938] iwlwifi: mvm: fix inconsistent lock in dqa mode When working in DQA mode, there is a lockdep log warning about an inconsistent state of the mvmsta->lock and the mvm->queue_info_lock. Fix this. This mode is not activated for now. Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index e157bd5a2204..12614b7b7fe7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -296,7 +296,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, lockdep_assert_held(&mvm->mutex); - spin_lock(&mvm->queue_info_lock); + spin_lock_bh(&mvm->queue_info_lock); /* * Non-QoS, QoS NDP and MGMT frames should go to a MGMT queue, if one @@ -324,7 +324,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, if (queue >= 0) mvm->queue_info[queue].setup_reserved = false; - spin_unlock(&mvm->queue_info_lock); + spin_unlock_bh(&mvm->queue_info_lock); /* TODO: support shared queues for same RA */ if (queue < 0) @@ -402,12 +402,12 @@ static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm, __skb_queue_head_init(&deferred_tx); + /* Disable bottom-halves when entering TX path */ + local_bh_disable(); spin_lock(&mvmsta->lock); skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx); spin_unlock(&mvmsta->lock); - /* Disable bottom-halves when entering TX path */ - local_bh_disable(); while ((skb = __skb_dequeue(&deferred_tx))) if (no_queue || iwl_mvm_tx_skb(mvm, skb, sta)) ieee80211_free_txskb(mvm->hw, skb); -- GitLab From 489c546dcecbddbadcbef25472d8fb4d693850e2 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 24 Mar 2016 11:10:12 +0200 Subject: [PATCH 0773/9938] iwlwifi: mvm: allow setting the thermal state in D0i3 We were not allowing the thermal state to be set when we were in D0i3 mode. It was not very clearly specified how it should work, but now a decision was made to allow the state to be set in D0i3 (which will cause a brief wake up). Remove the check in the set_cur_state operation. Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index 3f5df76f65a4..eb3f460ce1b6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -801,9 +801,6 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev, if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) return -EIO; - if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) - return -EBUSY; - mutex_lock(&mvm->mutex); if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) { -- GitLab From 46167a8fd4248533ad15867e6988ff20e76de641 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 28 Mar 2016 12:33:44 +0100 Subject: [PATCH 0774/9938] iwlwifi: pcie: remove duplicate assignment of variable isr_stats isr_stats is written twice with the same value, remove one of the redundant assignments to isr_stats. Signed-off-by: Colin Ian King Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 59a7e45b12df..7f8a2322cda2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1811,7 +1811,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) struct msix_entry *entry = dev_id; struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry); struct iwl_trans *trans = trans_pcie->trans; - struct isr_statistics *isr_stats = isr_stats = &trans_pcie->isr_stats; + struct isr_statistics *isr_stats = &trans_pcie->isr_stats; u32 inta_fh, inta_hw; lock_map_acquire(&trans->sync_cmd_lockdep_map); -- GitLab From 6c96f05c8bb8bc4177613ef3c23a56b455e75887 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 23 Feb 2016 18:46:24 +0100 Subject: [PATCH 0775/9938] reset: Make [of_]reset_control_get[_foo] functions wrappers With both the regular, _by_index and _optional variants we already have quite a few variants of [of_]reset_control_get[_foo], the upcoming addition of shared reset lines support makes this worse. This commit changes all the variants into wrappers around common core functions. For completeness sake this commit also adds a new devm_get_reset_control_by_index wrapper. Signed-off-by: Hans de Goede Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 84 ++++++---------------------- include/linux/reset.h | 126 ++++++++++++++++++++++++++++++------------ 2 files changed, 107 insertions(+), 103 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index f15f150b79da..bdf1763da87a 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -136,18 +136,8 @@ int reset_control_status(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_status); -/** - * of_reset_control_get_by_index - Lookup and obtain a reference to a reset - * controller by index. - * @node: device to be reset by the controller - * @index: index of the reset controller - * - * This is to be used to perform a list of resets for a device or power domain - * in whatever order. Returns a struct reset_control or IS_ERR() condition - * containing errno. - */ -struct reset_control *of_reset_control_get_by_index(struct device_node *node, - int index) +struct reset_control *__of_reset_control_get(struct device_node *node, + const char *id, int index) { struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; @@ -155,6 +145,16 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node, int rstc_id; int ret; + if (!node) + return ERR_PTR(-EINVAL); + + if (id) { + index = of_property_match_string(node, + "reset-names", id); + if (index < 0) + return ERR_PTR(-ENOENT); + } + ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", index, &args); if (ret) @@ -200,49 +200,7 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node, return rstc; } -EXPORT_SYMBOL_GPL(of_reset_control_get_by_index); - -/** - * of_reset_control_get - Lookup and obtain a reference to a reset controller. - * @node: device to be reset by the controller - * @id: reset line name - * - * Returns a struct reset_control or IS_ERR() condition containing errno. - * - * Use of id names is optional. - */ -struct reset_control *of_reset_control_get(struct device_node *node, - const char *id) -{ - int index = 0; - - if (id) { - index = of_property_match_string(node, - "reset-names", id); - if (index < 0) - return ERR_PTR(-ENOENT); - } - return of_reset_control_get_by_index(node, index); -} -EXPORT_SYMBOL_GPL(of_reset_control_get); - -/** - * reset_control_get - Lookup and obtain a reference to a reset controller. - * @dev: device to be reset by the controller - * @id: reset line name - * - * Returns a struct reset_control or IS_ERR() condition containing errno. - * - * Use of id names is optional. - */ -struct reset_control *reset_control_get(struct device *dev, const char *id) -{ - if (!dev) - return ERR_PTR(-EINVAL); - - return of_reset_control_get(dev->of_node, id); -} -EXPORT_SYMBOL_GPL(reset_control_get); +EXPORT_SYMBOL_GPL(__of_reset_control_get); /** * reset_control_put - free the reset controller @@ -264,16 +222,8 @@ static void devm_reset_control_release(struct device *dev, void *res) reset_control_put(*(struct reset_control **)res); } -/** - * devm_reset_control_get - resource managed reset_control_get() - * @dev: device to be reset by the controller - * @id: reset line name - * - * Managed reset_control_get(). For reset controllers returned from this - * function, reset_control_put() is called automatically on driver detach. - * See reset_control_get() for more information. - */ -struct reset_control *devm_reset_control_get(struct device *dev, const char *id) +struct reset_control *__devm_reset_control_get(struct device *dev, + const char *id, int index) { struct reset_control **ptr, *rstc; @@ -282,7 +232,7 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id) if (!ptr) return ERR_PTR(-ENOMEM); - rstc = reset_control_get(dev, id); + rstc = __of_reset_control_get(dev ? dev->of_node : NULL, id, index); if (!IS_ERR(rstc)) { *ptr = rstc; devres_add(dev, ptr); @@ -292,7 +242,7 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id) return rstc; } -EXPORT_SYMBOL_GPL(devm_reset_control_get); +EXPORT_SYMBOL_GPL(__devm_reset_control_get); /** * device_reset - find reset controller associated with the device diff --git a/include/linux/reset.h b/include/linux/reset.h index c4c097de0ba9..1bb69a29d6db 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -1,8 +1,8 @@ #ifndef _LINUX_RESET_H_ #define _LINUX_RESET_H_ -struct device; -struct device_node; +#include + struct reset_control; #ifdef CONFIG_RESET_CONTROLLER @@ -12,9 +12,11 @@ int reset_control_assert(struct reset_control *rstc); int reset_control_deassert(struct reset_control *rstc); int reset_control_status(struct reset_control *rstc); -struct reset_control *reset_control_get(struct device *dev, const char *id); +struct reset_control *__of_reset_control_get(struct device_node *node, + const char *id, int index); void reset_control_put(struct reset_control *rstc); -struct reset_control *devm_reset_control_get(struct device *dev, const char *id); +struct reset_control *__devm_reset_control_get(struct device *dev, + const char *id, int index); int __must_check device_reset(struct device *dev); @@ -23,24 +25,6 @@ static inline int device_reset_optional(struct device *dev) return device_reset(dev); } -static inline struct reset_control *reset_control_get_optional( - struct device *dev, const char *id) -{ - return reset_control_get(dev, id); -} - -static inline struct reset_control *devm_reset_control_get_optional( - struct device *dev, const char *id) -{ - return devm_reset_control_get(dev, id); -} - -struct reset_control *of_reset_control_get(struct device_node *node, - const char *id); - -struct reset_control *of_reset_control_get_by_index( - struct device_node *node, int index); - #else static inline int reset_control_reset(struct reset_control *rstc) @@ -77,44 +61,114 @@ static inline int device_reset_optional(struct device *dev) return -ENOTSUPP; } -static inline struct reset_control *__must_check reset_control_get( - struct device *dev, const char *id) +static inline struct reset_control *__of_reset_control_get( + struct device_node *node, + const char *id, int index) { - WARN_ON(1); return ERR_PTR(-EINVAL); } -static inline struct reset_control *__must_check devm_reset_control_get( - struct device *dev, const char *id) +static inline struct reset_control *__devm_reset_control_get( + struct device *dev, + const char *id, int index) { - WARN_ON(1); return ERR_PTR(-EINVAL); } -static inline struct reset_control *reset_control_get_optional( +#endif /* CONFIG_RESET_CONTROLLER */ + +/** + * reset_control_get - Lookup and obtain a reference to a reset controller. + * @dev: device to be reset by the controller + * @id: reset line name + * + * Returns a struct reset_control or IS_ERR() condition containing errno. + * + * Use of id names is optional. + */ +static inline struct reset_control *__must_check reset_control_get( struct device *dev, const char *id) { - return ERR_PTR(-ENOTSUPP); +#ifndef CONFIG_RESET_CONTROLLER + WARN_ON(1); +#endif + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0); } -static inline struct reset_control *devm_reset_control_get_optional( +static inline struct reset_control *reset_control_get_optional( struct device *dev, const char *id) { - return ERR_PTR(-ENOTSUPP); + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0); } +/** + * of_reset_control_get - Lookup and obtain a reference to a reset controller. + * @node: device to be reset by the controller + * @id: reset line name + * + * Returns a struct reset_control or IS_ERR() condition containing errno. + * + * Use of id names is optional. + */ static inline struct reset_control *of_reset_control_get( struct device_node *node, const char *id) { - return ERR_PTR(-ENOTSUPP); + return __of_reset_control_get(node, id, 0); } +/** + * of_reset_control_get_by_index - Lookup and obtain a reference to a reset + * controller by index. + * @node: device to be reset by the controller + * @index: index of the reset controller + * + * This is to be used to perform a list of resets for a device or power domain + * in whatever order. Returns a struct reset_control or IS_ERR() condition + * containing errno. + */ static inline struct reset_control *of_reset_control_get_by_index( - struct device_node *node, int index) + struct device_node *node, int index) { - return ERR_PTR(-ENOTSUPP); + return __of_reset_control_get(node, NULL, index); } -#endif /* CONFIG_RESET_CONTROLLER */ +/** + * devm_reset_control_get - resource managed reset_control_get() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed reset_control_get(). For reset controllers returned from this + * function, reset_control_put() is called automatically on driver detach. + * See reset_control_get() for more information. + */ +static inline struct reset_control *__must_check devm_reset_control_get( + struct device *dev, const char *id) +{ +#ifndef CONFIG_RESET_CONTROLLER + WARN_ON(1); +#endif + return __devm_reset_control_get(dev, id, 0); +} + +static inline struct reset_control *devm_reset_control_get_optional( + struct device *dev, const char *id) +{ + return __devm_reset_control_get(dev, id, 0); +} + +/** + * devm_reset_control_get_by_index - resource managed reset_control_get + * @dev: device to be reset by the controller + * @index: index of the reset controller + * + * Managed reset_control_get(). For reset controllers returned from this + * function, reset_control_put() is called automatically on driver detach. + * See reset_control_get() for more information. + */ +static inline struct reset_control *devm_reset_control_get_by_index( + struct device *dev, int index) +{ + return __devm_reset_control_get(dev, NULL, index); +} #endif -- GitLab From c15ddec2ca06076a11195313aa1fce47d2a28c5d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 23 Feb 2016 18:46:25 +0100 Subject: [PATCH 0776/9938] reset: Share struct reset_control between reset_control_get calls Now that struct reset_control no longer stores the device pointer for the device calling reset_control_get we can share a single struct reset_control when multiple calls to reset_control_get are made for the same reset line (same id / index). This is a preparation patch for adding support for shared reset lines. Signed-off-by: Hans de Goede Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 84 ++++++++++++++++++++++++-------- include/linux/reset-controller.h | 2 + 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index bdf1763da87a..957750600ff3 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -18,19 +18,23 @@ #include #include -static DEFINE_MUTEX(reset_controller_list_mutex); +static DEFINE_MUTEX(reset_list_mutex); static LIST_HEAD(reset_controller_list); /** * struct reset_control - a reset control * @rcdev: a pointer to the reset controller device * this reset control belongs to + * @list: list entry for the rcdev's reset controller list * @id: ID of the reset controller in the reset * controller device + * @refcnt: Number of gets of this reset_control */ struct reset_control { struct reset_controller_dev *rcdev; + struct list_head list; unsigned int id; + unsigned int refcnt; }; /** @@ -62,9 +66,11 @@ int reset_controller_register(struct reset_controller_dev *rcdev) rcdev->of_xlate = of_reset_simple_xlate; } - mutex_lock(&reset_controller_list_mutex); + INIT_LIST_HEAD(&rcdev->reset_control_head); + + mutex_lock(&reset_list_mutex); list_add(&rcdev->list, &reset_controller_list); - mutex_unlock(&reset_controller_list_mutex); + mutex_unlock(&reset_list_mutex); return 0; } @@ -76,9 +82,9 @@ EXPORT_SYMBOL_GPL(reset_controller_register); */ void reset_controller_unregister(struct reset_controller_dev *rcdev) { - mutex_lock(&reset_controller_list_mutex); + mutex_lock(&reset_list_mutex); list_del(&rcdev->list); - mutex_unlock(&reset_controller_list_mutex); + mutex_unlock(&reset_list_mutex); } EXPORT_SYMBOL_GPL(reset_controller_unregister); @@ -136,6 +142,48 @@ int reset_control_status(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_status); +static struct reset_control *__reset_control_get( + struct reset_controller_dev *rcdev, + unsigned int index) +{ + struct reset_control *rstc; + + lockdep_assert_held(&reset_list_mutex); + + list_for_each_entry(rstc, &rcdev->reset_control_head, list) { + if (rstc->id == index) { + rstc->refcnt++; + return rstc; + } + } + + rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); + if (!rstc) + return ERR_PTR(-ENOMEM); + + try_module_get(rcdev->owner); + + rstc->rcdev = rcdev; + list_add(&rstc->list, &rcdev->reset_control_head); + rstc->id = index; + rstc->refcnt = 1; + + return rstc; +} + +static void __reset_control_put(struct reset_control *rstc) +{ + lockdep_assert_held(&reset_list_mutex); + + if (--rstc->refcnt) + return; + + module_put(rstc->rcdev->owner); + + list_del(&rstc->list); + kfree(rstc); +} + struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index) { @@ -160,7 +208,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (ret) return ERR_PTR(ret); - mutex_lock(&reset_controller_list_mutex); + mutex_lock(&reset_list_mutex); rcdev = NULL; list_for_each_entry(r, &reset_controller_list, list) { if (args.np == r->of_node) { @@ -171,32 +219,25 @@ struct reset_control *__of_reset_control_get(struct device_node *node, of_node_put(args.np); if (!rcdev) { - mutex_unlock(&reset_controller_list_mutex); + mutex_unlock(&reset_list_mutex); return ERR_PTR(-EPROBE_DEFER); } if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { - mutex_unlock(&reset_controller_list_mutex); + mutex_unlock(&reset_list_mutex); return ERR_PTR(-EINVAL); } rstc_id = rcdev->of_xlate(rcdev, &args); if (rstc_id < 0) { - mutex_unlock(&reset_controller_list_mutex); + mutex_unlock(&reset_list_mutex); return ERR_PTR(rstc_id); } - try_module_get(rcdev->owner); - mutex_unlock(&reset_controller_list_mutex); - - rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); - if (!rstc) { - module_put(rcdev->owner); - return ERR_PTR(-ENOMEM); - } + /* reset_list_mutex also protects the rcdev's reset_control list */ + rstc = __reset_control_get(rcdev, rstc_id); - rstc->rcdev = rcdev; - rstc->id = rstc_id; + mutex_unlock(&reset_list_mutex); return rstc; } @@ -212,8 +253,9 @@ void reset_control_put(struct reset_control *rstc) if (IS_ERR(rstc)) return; - module_put(rstc->rcdev->owner); - kfree(rstc); + mutex_lock(&reset_list_mutex); + __reset_control_put(rstc); + mutex_unlock(&reset_list_mutex); } EXPORT_SYMBOL_GPL(reset_control_put); diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index a3a5bcdb1d02..b91ba932bbd4 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -31,6 +31,7 @@ struct of_phandle_args; * @ops: a pointer to device specific struct reset_control_ops * @owner: kernel module of the reset controller driver * @list: internal list of reset controller devices + * @reset_control_head: head of internal list of requested reset controls * @of_node: corresponding device tree node as phandle target * @of_reset_n_cells: number of cells in reset line specifiers * @of_xlate: translation function to translate from specifier as found in the @@ -41,6 +42,7 @@ struct reset_controller_dev { const struct reset_control_ops *ops; struct module *owner; struct list_head list; + struct list_head reset_control_head; struct device_node *of_node; int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, -- GitLab From 0b52297f2288ca239e598afe6c92db83d8d2bfcd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 23 Feb 2016 18:46:26 +0100 Subject: [PATCH 0777/9938] reset: Add support for shared reset controls In some SoCs some hw-blocks share a reset control. Add support for this setup by adding new: reset_control_get_shared() devm_reset_control_get_shared() devm_reset_control_get_shared_by_index() methods to get a reset_control. Note that this patch omits adding of_ variants, if these are needed later they can be easily added. This patch also changes the behavior of the existing exclusive reset_control_get() variants, if these are now called more then once for the same reset_control they will return -EBUSY. To catch existing drivers triggering this error (there should not be any) a WARN_ON(1) is added in this path. When a reset_control is shared, the behavior of reset_control_assert / deassert is changed, for shared reset_controls these will work like the clock-enable/disable and regulator-on/off functions. They will keep a deassert_count, and only (re-)assert the reset after reset_control_assert has been called as many times as reset_control_deassert was called. Calling reset_control_assert without first calling reset_control_deassert is not allowed on a shared reset control. Calling reset_control_reset is also not allowed on a shared reset control. Signed-off-by: Hans de Goede Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 59 +++++++++++++++++++++----- include/linux/reset.h | 96 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 129 insertions(+), 26 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 957750600ff3..72b32bd15549 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -8,6 +8,7 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ +#include #include #include #include @@ -29,12 +30,16 @@ static LIST_HEAD(reset_controller_list); * @id: ID of the reset controller in the reset * controller device * @refcnt: Number of gets of this reset_control + * @shared: Is this a shared (1), or an exclusive (0) reset_control? + * @deassert_cnt: Number of times this reset line has been deasserted */ struct reset_control { struct reset_controller_dev *rcdev; struct list_head list; unsigned int id; unsigned int refcnt; + int shared; + atomic_t deassert_count; }; /** @@ -91,9 +96,14 @@ EXPORT_SYMBOL_GPL(reset_controller_unregister); /** * reset_control_reset - reset the controlled device * @rstc: reset controller + * + * Calling this on a shared reset controller is an error. */ int reset_control_reset(struct reset_control *rstc) { + if (WARN_ON(rstc->shared)) + return -EINVAL; + if (rstc->rcdev->ops->reset) return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); @@ -104,26 +114,48 @@ EXPORT_SYMBOL_GPL(reset_control_reset); /** * reset_control_assert - asserts the reset line * @rstc: reset controller + * + * Calling this on an exclusive reset controller guarantees that the reset + * will be asserted. When called on a shared reset controller the line may + * still be deasserted, as long as other users keep it so. + * + * For shared reset controls a driver cannot expect the hw's registers and + * internal state to be reset, but must be prepared for this to happen. */ int reset_control_assert(struct reset_control *rstc) { - if (rstc->rcdev->ops->assert) - return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); + if (!rstc->rcdev->ops->assert) + return -ENOTSUPP; - return -ENOTSUPP; + if (rstc->shared) { + if (WARN_ON(atomic_read(&rstc->deassert_count) == 0)) + return -EINVAL; + + if (atomic_dec_return(&rstc->deassert_count) != 0) + return 0; + } + + return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); } EXPORT_SYMBOL_GPL(reset_control_assert); /** * reset_control_deassert - deasserts the reset line * @rstc: reset controller + * + * After calling this function, the reset is guaranteed to be deasserted. */ int reset_control_deassert(struct reset_control *rstc) { - if (rstc->rcdev->ops->deassert) - return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); + if (!rstc->rcdev->ops->deassert) + return -ENOTSUPP; - return -ENOTSUPP; + if (rstc->shared) { + if (atomic_inc_return(&rstc->deassert_count) != 1) + return 0; + } + + return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); } EXPORT_SYMBOL_GPL(reset_control_deassert); @@ -144,7 +176,7 @@ EXPORT_SYMBOL_GPL(reset_control_status); static struct reset_control *__reset_control_get( struct reset_controller_dev *rcdev, - unsigned int index) + unsigned int index, int shared) { struct reset_control *rstc; @@ -152,6 +184,9 @@ static struct reset_control *__reset_control_get( list_for_each_entry(rstc, &rcdev->reset_control_head, list) { if (rstc->id == index) { + if (WARN_ON(!rstc->shared || !shared)) + return ERR_PTR(-EBUSY); + rstc->refcnt++; return rstc; } @@ -167,6 +202,7 @@ static struct reset_control *__reset_control_get( list_add(&rstc->list, &rcdev->reset_control_head); rstc->id = index; rstc->refcnt = 1; + rstc->shared = shared; return rstc; } @@ -185,7 +221,7 @@ static void __reset_control_put(struct reset_control *rstc) } struct reset_control *__of_reset_control_get(struct device_node *node, - const char *id, int index) + const char *id, int index, int shared) { struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; @@ -235,7 +271,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, } /* reset_list_mutex also protects the rcdev's reset_control list */ - rstc = __reset_control_get(rcdev, rstc_id); + rstc = __reset_control_get(rcdev, rstc_id, shared); mutex_unlock(&reset_list_mutex); @@ -265,7 +301,7 @@ static void devm_reset_control_release(struct device *dev, void *res) } struct reset_control *__devm_reset_control_get(struct device *dev, - const char *id, int index) + const char *id, int index, int shared) { struct reset_control **ptr, *rstc; @@ -274,7 +310,8 @@ struct reset_control *__devm_reset_control_get(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); - rstc = __of_reset_control_get(dev ? dev->of_node : NULL, id, index); + rstc = __of_reset_control_get(dev ? dev->of_node : NULL, + id, index, shared); if (!IS_ERR(rstc)) { *ptr = rstc; devres_add(dev, ptr); diff --git a/include/linux/reset.h b/include/linux/reset.h index 1bb69a29d6db..a552134a209e 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -13,10 +13,10 @@ int reset_control_deassert(struct reset_control *rstc); int reset_control_status(struct reset_control *rstc); struct reset_control *__of_reset_control_get(struct device_node *node, - const char *id, int index); + const char *id, int index, int shared); void reset_control_put(struct reset_control *rstc); struct reset_control *__devm_reset_control_get(struct device *dev, - const char *id, int index); + const char *id, int index, int shared); int __must_check device_reset(struct device *dev); @@ -63,14 +63,14 @@ static inline int device_reset_optional(struct device *dev) static inline struct reset_control *__of_reset_control_get( struct device_node *node, - const char *id, int index) + const char *id, int index, int shared) { return ERR_PTR(-EINVAL); } static inline struct reset_control *__devm_reset_control_get( struct device *dev, - const char *id, int index) + const char *id, int index, int shared) { return ERR_PTR(-EINVAL); } @@ -78,11 +78,17 @@ static inline struct reset_control *__devm_reset_control_get( #endif /* CONFIG_RESET_CONTROLLER */ /** - * reset_control_get - Lookup and obtain a reference to a reset controller. + * reset_control_get - Lookup and obtain an exclusive reference to a + * reset controller. * @dev: device to be reset by the controller * @id: reset line name * * Returns a struct reset_control or IS_ERR() condition containing errno. + * If this function is called more then once for the same reset_control it will + * return -EBUSY. + * + * See reset_control_get_shared for details on shared references to + * reset-controls. * * Use of id names is optional. */ @@ -92,17 +98,46 @@ static inline struct reset_control *__must_check reset_control_get( #ifndef CONFIG_RESET_CONTROLLER WARN_ON(1); #endif - return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0); + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0); } static inline struct reset_control *reset_control_get_optional( struct device *dev, const char *id) { - return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0); + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0); } /** - * of_reset_control_get - Lookup and obtain a reference to a reset controller. + * reset_control_get_shared - Lookup and obtain a shared reference to a + * reset controller. + * @dev: device to be reset by the controller + * @id: reset line name + * + * Returns a struct reset_control or IS_ERR() condition containing errno. + * This function is intended for use with reset-controls which are shared + * between hardware-blocks. + * + * When a reset-control is shared, the behavior of reset_control_assert / + * deassert is changed, the reset-core will keep track of a deassert_count + * and only (re-)assert the reset after reset_control_assert has been called + * as many times as reset_control_deassert was called. Also see the remark + * about shared reset-controls in the reset_control_assert docs. + * + * Calling reset_control_assert without first calling reset_control_deassert + * is not allowed on a shared reset control. Calling reset_control_reset is + * also not allowed on a shared reset control. + * + * Use of id names is optional. + */ +static inline struct reset_control *reset_control_get_shared( + struct device *dev, const char *id) +{ + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1); +} + +/** + * of_reset_control_get - Lookup and obtain an exclusive reference to a + * reset controller. * @node: device to be reset by the controller * @id: reset line name * @@ -113,12 +148,12 @@ static inline struct reset_control *reset_control_get_optional( static inline struct reset_control *of_reset_control_get( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0); + return __of_reset_control_get(node, id, 0, 0); } /** - * of_reset_control_get_by_index - Lookup and obtain a reference to a reset - * controller by index. + * of_reset_control_get_by_index - Lookup and obtain an exclusive reference to + * a reset controller by index. * @node: device to be reset by the controller * @index: index of the reset controller * @@ -129,7 +164,7 @@ static inline struct reset_control *of_reset_control_get( static inline struct reset_control *of_reset_control_get_by_index( struct device_node *node, int index) { - return __of_reset_control_get(node, NULL, index); + return __of_reset_control_get(node, NULL, index, 0); } /** @@ -147,13 +182,13 @@ static inline struct reset_control *__must_check devm_reset_control_get( #ifndef CONFIG_RESET_CONTROLLER WARN_ON(1); #endif - return __devm_reset_control_get(dev, id, 0); + return __devm_reset_control_get(dev, id, 0, 0); } static inline struct reset_control *devm_reset_control_get_optional( struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0); + return __devm_reset_control_get(dev, id, 0, 0); } /** @@ -168,7 +203,38 @@ static inline struct reset_control *devm_reset_control_get_optional( static inline struct reset_control *devm_reset_control_get_by_index( struct device *dev, int index) { - return __devm_reset_control_get(dev, NULL, index); + return __devm_reset_control_get(dev, NULL, index, 0); +} + +/** + * devm_reset_control_get_shared - resource managed reset_control_get_shared() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed reset_control_get_shared(). For reset controllers returned from + * this function, reset_control_put() is called automatically on driver detach. + * See reset_control_get_shared() for more information. + */ +static inline struct reset_control *devm_reset_control_get_shared( + struct device *dev, const char *id) +{ + return __devm_reset_control_get(dev, id, 0, 1); +} + +/** + * devm_reset_control_get_shared_by_index - resource managed + * reset_control_get_shared + * @dev: device to be reset by the controller + * @index: index of the reset controller + * + * Managed reset_control_get_shared(). For reset controllers returned from + * this function, reset_control_put() is called automatically on driver detach. + * See reset_control_get_shared() for more information. + */ +static inline struct reset_control *devm_reset_control_get_shared_by_index( + struct device *dev, int index) +{ + return __devm_reset_control_get(dev, NULL, index, 1); } #endif -- GitLab From 773fe72630c8aca874ec8a07ebacace4ae305a02 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sat, 20 Feb 2016 20:06:49 +0100 Subject: [PATCH 0778/9938] reset: lpc18xx: get rid of global variables for restart notifier Moving the notifier_block into the drivers priv struct allows us to retrive the priv struct with container_of and remove the global variables. Signed-off-by: Joachim Eastwood Signed-off-by: Philipp Zabel --- drivers/reset/reset-lpc18xx.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c index 3b8a4f5a1ff6..54cca0055171 100644 --- a/drivers/reset/reset-lpc18xx.c +++ b/drivers/reset/reset-lpc18xx.c @@ -35,6 +35,7 @@ struct lpc18xx_rgu_data { struct reset_controller_dev rcdev; + struct notifier_block restart_nb; struct clk *clk_delay; struct clk *clk_reg; void __iomem *base; @@ -44,12 +45,13 @@ struct lpc18xx_rgu_data { #define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev) -static void __iomem *rgu_base; - -static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode, +static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode, void *cmd) { - writel(BIT(LPC18XX_RGU_CORE_RST), rgu_base + LPC18XX_RGU_CTRL0); + struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data, + restart_nb); + + writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0); mdelay(2000); pr_emerg("%s: unable to restart system\n", __func__); @@ -57,11 +59,6 @@ static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode, return NOTIFY_DONE; } -static struct notifier_block lpc18xx_rgu_restart_nb = { - .notifier_call = lpc18xx_rgu_restart, - .priority = 192, -}; - /* * The LPC18xx RGU has mostly self-deasserting resets except for the * two reset lines going to the internal Cortex-M0 cores. @@ -205,8 +202,9 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev) goto dis_clks; } - rgu_base = rc->base; - ret = register_restart_handler(&lpc18xx_rgu_restart_nb); + rc->restart_nb.priority = 192, + rc->restart_nb.notifier_call = lpc18xx_rgu_restart, + ret = register_restart_handler(&rc->restart_nb); if (ret) dev_warn(&pdev->dev, "failed to register restart handler\n"); @@ -225,7 +223,7 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev) struct lpc18xx_rgu_data *rc = platform_get_drvdata(pdev); int ret; - ret = unregister_restart_handler(&lpc18xx_rgu_restart_nb); + ret = unregister_restart_handler(&rc->restart_nb); if (ret) dev_warn(&pdev->dev, "failed to unregister restart handler\n"); -- GitLab From 5cc52a6d75468830fd26703728675d17f86a5864 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Tue, 8 Mar 2016 10:25:38 +0800 Subject: [PATCH 0779/9938] Documentation: DT: Add entry for Freescale LS1043a-QDS board Signed-off-by: Hou Zhiqiang Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt index 752a685d926f..dbbc0952021c 100644 --- a/Documentation/devicetree/bindings/arm/fsl.txt +++ b/Documentation/devicetree/bindings/arm/fsl.txt @@ -135,6 +135,10 @@ LS1043A ARMv8 based RDB Board Required root node properties: - compatible = "fsl,ls1043a-rdb", "fsl,ls1043a"; +LS1043A ARMv8 based QDS Board +Required root node properties: + - compatible = "fsl,ls1043a-qds", "fsl,ls1043a"; + LS2080A ARMv8 based Simulator model Required root node properties: - compatible = "fsl,ls2080a-simu", "fsl,ls2080a"; -- GitLab From ec05e9cc6a6e9679ea536934d2566ac9c209eece Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Tue, 8 Mar 2016 10:25:39 +0800 Subject: [PATCH 0780/9938] arm64: dts: add LS1043a-QDS board support The LS1043a-QDS board is a high-performance computing, evaluation, development, and test platform supporting the LS1043a SoC. shawn.guo: sort the entries in Makefile alphabetcially Signed-off-by: Shaohui Xie Signed-off-by: Mingkai Hu Signed-off-by: Hou Zhiqiang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 3 +- .../boot/dts/freescale/fsl-ls1043a-qds.dts | 168 ++++++++++++++++++ 2 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index f3c25165dad3..1b7783db7de4 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -1,7 +1,8 @@ +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb -dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts new file mode 100644 index 000000000000..80688acb73a3 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts @@ -0,0 +1,168 @@ +/* + * Device Tree Include file for Freescale Layerscape-1043A family SoC. + * + * Copyright 2014-2015, Freescale Semiconductor + * + * Mingkai Hu + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +/include/ "fsl-ls1043a.dtsi" + +/ { + model = "LS1043A QDS Board"; + compatible = "fsl,ls1043a-qds", "fsl,ls1043a"; + + aliases { + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + serial0 = &lpuart0; + serial1 = &lpuart1; + serial2 = &lpuart2; + serial3 = &lpuart3; + serial4 = &lpuart4; + serial5 = &lpuart5; + }; +}; + +&duart0 { + status = "okay"; +}; + +&duart1 { + status = "okay"; +}; + +&ifc { + #address-cells = <2>; + #size-cells = <1>; + /* NOR, NAND Flashes and FPGA on board */ + ranges = <0x0 0x0 0x0 0x60000000 0x08000000 + 0x1 0x0 0x0 0x7e800000 0x00010000 + 0x2 0x0 0x0 0x7fb00000 0x00000100>; + status = "okay"; + + nor@0,0 { + compatible = "cfi-flash"; + reg = <0x0 0x0 0x8000000>; + bank-width = <2>; + device-width = <1>; + }; + + nand@1,0 { + compatible = "fsl,ifc-nand"; + reg = <0x1 0x0 0x10000>; + }; + + fpga: board-control@2,0 { + compatible = "fsl,ls1043aqds-fpga", "fsl,fpga-qixis"; + reg = <0x2 0x0 0x0000100>; + }; +}; + +&i2c0 { + status = "okay"; + + pca9547@77 { + compatible = "nxp,pca9547"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + rtc@68 { + compatible = "dallas,ds3232"; + reg = <0x68>; + /* IRQ10_B */ + interrupts = <0 150 0x4>; + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + + ina220@40 { + compatible = "ti,ina220"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + ina220@41 { + compatible = "ti,ina220"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + eeprom@56 { + compatible = "atmel,24c512"; + reg = <0x56>; + }; + + eeprom@57 { + compatible = "atmel,24c512"; + reg = <0x57>; + }; + + temp-sensor@4c { + compatible = "adi,adt7461a"; + reg = <0x4c>; + }; + }; + }; +}; + +&lpuart0 { + status = "okay"; +}; -- GitLab From ad16511b0e404652331a5350c522d0824f8209de Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 24 Mar 2016 13:52:16 +0100 Subject: [PATCH 0781/9938] perf mem: Add -U/-K (--all-user/--all-kernel) options Add -U/-K (--all-user/--all-kernel) options to use the perf record --all-user/--all-kernel options. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1458823940-24583-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-mem.txt | 8 ++++++++ tools/perf/builtin-mem.c | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt index 43310d8661fe..1d6092c460dd 100644 --- a/tools/perf/Documentation/perf-mem.txt +++ b/tools/perf/Documentation/perf-mem.txt @@ -48,6 +48,14 @@ OPTIONS option can be passed in record mode. It will be interpreted the same way as perf record. +-K:: +--all-kernel:: + Configure all used events to run in kernel space. + +-U:: +--all-user:: + Configure all used events to run in user space. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 85db3be4b3cb..1dc140c5481d 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -62,19 +62,22 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) int rec_argc, i = 0, j; const char **rec_argv; int ret; + bool all_user = false, all_kernel = false; struct option options[] = { OPT_CALLBACK('e', "event", &mem, "event", "event selector. use 'perf mem record -e list' to list available events", parse_record_events), OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), + OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"), + OPT_BOOLEAN('K', "--all-kernel", &all_kernel, "collect only kernel level data"), OPT_END() }; argc = parse_options(argc, argv, options, record_mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); - rec_argc = argc + 7; /* max number of arguments */ + rec_argc = argc + 9; /* max number of arguments */ rec_argv = calloc(rec_argc + 1, sizeof(char *)); if (!rec_argv) return -1; @@ -103,6 +106,12 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) rec_argv[i++] = perf_mem_events__name(j); }; + if (all_user) + rec_argv[i++] = "--all-user"; + + if (all_kernel) + rec_argv[i++] = "--all-kernel"; + for (j = 0; j < argc; j++, i++) rec_argv[i] = argv[j]; -- GitLab From 592dac6f35cf222a7687d4ff1ea7df0e6ef722e0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 24 Mar 2016 13:52:17 +0100 Subject: [PATCH 0782/9938] perf tools: Make hists__collapse_insert_entry static No need to export hists__collapse_insert_entry function. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1458823940-24583-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 5 +++-- tools/perf/util/hist.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 31c4641fe5ff..3d34c57dfbe2 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1295,8 +1295,9 @@ static int hists__hierarchy_insert_entry(struct hists *hists, return ret; } -int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, - struct hist_entry *he) +static int hists__collapse_insert_entry(struct hists *hists, + struct rb_root *root, + struct hist_entry *he) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index bec0cd660fbd..588596561cb3 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -199,8 +199,6 @@ int hists__init(void); int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); struct rb_root *hists__get_rotate_entries_in(struct hists *hists); -int hists__collapse_insert_entry(struct hists *hists, - struct rb_root *root, struct hist_entry *he); struct perf_hpp { char *buf; -- GitLab From e0be62cc0325d65e1b7ae55d23e3d224638c20a6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 24 Mar 2016 13:52:19 +0100 Subject: [PATCH 0783/9938] perf tools: Make -f/--force option documentation consistent across tools Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1458823940-24583-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-annotate.txt | 2 +- tools/perf/Documentation/perf-diff.txt | 2 +- tools/perf/Documentation/perf-report.txt | 2 +- tools/perf/Documentation/perf-script.txt | 4 ++++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index e9cd39a92dc2..778f54d4d0bd 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -33,7 +33,7 @@ OPTIONS -f:: --force:: - Don't complain, do it. + Don't do ownership validation. -v:: --verbose:: diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index d1deb573877f..3e9490b9c533 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -75,7 +75,7 @@ OPTIONS -f:: --force:: - Don't complain, do it. + Don't do ownership validation. --symfs=:: Look for files with symbols relative to this directory. diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 12113992ac9d..496d42cdf02b 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -285,7 +285,7 @@ OPTIONS -f:: --force:: - Don't complain, do it. + Don't do ownership validation. --symfs=:: Look for files with symbols relative to this directory. diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 382ddfb45d1d..22ef3933342a 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -262,6 +262,10 @@ include::itrace.txt[] --ns:: Use 9 decimal places when displaying time (i.e. show the nanoseconds) +-f:: +--force:: + Don't do ownership validation. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-script-perl[1], -- GitLab From b31d660df37c1701fd18d526faeb9a86f0fc7dd2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 24 Mar 2016 13:52:20 +0100 Subject: [PATCH 0784/9938] perf tests: Add test to check for event times This test creates software event 'cpu-clock' attaches it in several ways and checks that enabled and running times match. Committer notes: Testing it: [acme@jouet linux]$ perf test -v times 44: Test events times : --- start --- test child forked, pid 27170 attaching to spawned child, enable on exec OK : ena 307328, run 307328 attaching to current thread as enabled OK : ena 7826, run 7826 attaching to current thread as disabled OK : ena 738, run 738 attaching to CPU 0 as enabled SKIP : not enough rights attaching to CPU 0 as enabled SKIP : not enough rights test child finished with -2 ---- end ---- Test events times: Skip [acme@jouet linux]$ [root@jouet ~]# perf test times 44: Test events times : Ok [root@jouet ~]# perf test -v times 44: Test events times : --- start --- test child forked, pid 27306 attaching to spawned child, enable on exec OK : ena 479290, run 479290 attaching to current thread as enabled OK : ena 11356, run 11356 attaching to current thread as disabled OK : ena 987, run 987 attaching to CPU 0 as enabled OK : ena 3717, run 3717 attaching to CPU 0 as enabled OK : ena 2323, run 2323 test child finished with 0 ---- end ---- Test events times: Ok [root@jouet ~]# Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1458823940-24583-7-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 + tools/perf/tests/event-times.c | 236 ++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 242 insertions(+) create mode 100644 tools/perf/tests/event-times.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 1ba628ed049a..449fe97a555f 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -37,6 +37,7 @@ perf-y += topology.o perf-y += cpumap.o perf-y += stat.o perf-y += event_update.o +perf-y += event-times.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index f2b1dcac45d3..93c467015e71 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -203,6 +203,10 @@ static struct test generic_tests[] = { .desc = "Test attr update synthesize", .func = test__event_update, }, + { + .desc = "Test events times", + .func = test__event_times, + }, { .func = NULL, }, diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c new file mode 100644 index 000000000000..95fb744f6628 --- /dev/null +++ b/tools/perf/tests/event-times.c @@ -0,0 +1,236 @@ +#include +#include +#include "tests.h" +#include "evlist.h" +#include "evsel.h" +#include "util.h" +#include "debug.h" +#include "thread_map.h" +#include "target.h" + +static int attach__enable_on_exec(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = perf_evlist__last(evlist); + struct target target = { + .uid = UINT_MAX, + }; + const char *argv[] = { "true", NULL, }; + char sbuf[STRERR_BUFSIZE]; + int err; + + pr_debug("attaching to spawned child, enable on exec\n"); + + err = perf_evlist__create_maps(evlist, &target); + if (err < 0) { + pr_debug("Not enough memory to create thread/cpu maps\n"); + return err; + } + + err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL); + if (err < 0) { + pr_debug("Couldn't run the workload!\n"); + return err; + } + + evsel->attr.enable_on_exec = 1; + + err = perf_evlist__open(evlist); + if (err < 0) { + pr_debug("perf_evlist__open: %s\n", + strerror_r(errno, sbuf, sizeof(sbuf))); + return err; + } + + return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL; +} + +static int detach__enable_on_exec(struct perf_evlist *evlist) +{ + waitpid(evlist->workload.pid, NULL, 0); + return 0; +} + +static int attach__current_disabled(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = perf_evlist__last(evlist); + struct thread_map *threads; + int err; + + pr_debug("attaching to current thread as disabled\n"); + + threads = thread_map__new(-1, getpid(), UINT_MAX); + if (threads == NULL) { + pr_debug("thread_map__new\n"); + return -1; + } + + evsel->attr.disabled = 1; + + err = perf_evsel__open_per_thread(evsel, threads); + if (err) { + pr_debug("Failed to open event cpu-clock:u\n"); + return err; + } + + thread_map__put(threads); + return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL; +} + +static int attach__current_enabled(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = perf_evlist__last(evlist); + struct thread_map *threads; + int err; + + pr_debug("attaching to current thread as enabled\n"); + + threads = thread_map__new(-1, getpid(), UINT_MAX); + if (threads == NULL) { + pr_debug("failed to call thread_map__new\n"); + return -1; + } + + err = perf_evsel__open_per_thread(evsel, threads); + + thread_map__put(threads); + return err == 0 ? TEST_OK : TEST_FAIL; +} + +static int detach__disable(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = perf_evlist__last(evlist); + + return perf_evsel__enable(evsel); +} + +static int attach__cpu_disabled(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = perf_evlist__last(evlist); + struct cpu_map *cpus; + int err; + + pr_debug("attaching to CPU 0 as enabled\n"); + + cpus = cpu_map__new("0"); + if (cpus == NULL) { + pr_debug("failed to call cpu_map__new\n"); + return -1; + } + + evsel->attr.disabled = 1; + + err = perf_evsel__open_per_cpu(evsel, cpus); + if (err) { + if (err == -EACCES) + return TEST_SKIP; + + pr_debug("Failed to open event cpu-clock:u\n"); + return err; + } + + cpu_map__put(cpus); + return perf_evsel__enable(evsel); +} + +static int attach__cpu_enabled(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = perf_evlist__last(evlist); + struct cpu_map *cpus; + int err; + + pr_debug("attaching to CPU 0 as enabled\n"); + + cpus = cpu_map__new("0"); + if (cpus == NULL) { + pr_debug("failed to call cpu_map__new\n"); + return -1; + } + + err = perf_evsel__open_per_cpu(evsel, cpus); + if (err == -EACCES) + return TEST_SKIP; + + cpu_map__put(cpus); + return err ? TEST_FAIL : TEST_OK; +} + +static int test_times(int (attach)(struct perf_evlist *), + int (detach)(struct perf_evlist *)) +{ + struct perf_counts_values count; + struct perf_evlist *evlist = NULL; + struct perf_evsel *evsel; + int err = -1, i; + + evlist = perf_evlist__new(); + if (!evlist) { + pr_debug("failed to create event list\n"); + goto out_err; + } + + err = parse_events(evlist, "cpu-clock:u", NULL); + if (err) { + pr_debug("failed to parse event cpu-clock:u\n"); + goto out_err; + } + + evsel = perf_evlist__last(evlist); + evsel->attr.read_format |= + PERF_FORMAT_TOTAL_TIME_ENABLED | + PERF_FORMAT_TOTAL_TIME_RUNNING; + + err = attach(evlist); + if (err == TEST_SKIP) { + pr_debug(" SKIP : not enough rights\n"); + return err; + } + + TEST_ASSERT_VAL("failed to attach", !err); + + for (i = 0; i < 100000000; i++) { } + + TEST_ASSERT_VAL("failed to detach", !detach(evlist)); + + perf_evsel__read(evsel, 0, 0, &count); + + err = !(count.ena == count.run); + + pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n", + !err ? "OK " : "FAILED", + count.ena, count.run); + +out_err: + if (evlist) + perf_evlist__delete(evlist); + return !err ? TEST_OK : TEST_FAIL; +} + +/* + * This test creates software event 'cpu-clock' + * attaches it in several ways (explained below) + * and checks that enabled and running times + * match. + */ +int test__event_times(int subtest __maybe_unused) +{ + int err, ret = 0; + +#define _T(attach, detach) \ + err = test_times(attach, detach); \ + if (err && (ret == TEST_OK || ret == TEST_SKIP)) \ + ret = err; + + /* attach on newly spawned process after exec */ + _T(attach__enable_on_exec, detach__enable_on_exec) + /* attach on current process as enabled */ + _T(attach__current_enabled, detach__disable) + /* attach on current process as disabled */ + _T(attach__current_disabled, detach__disable) + /* attach on cpu as disabled */ + _T(attach__cpu_disabled, detach__disable) + /* attach on cpu as enabled */ + _T(attach__cpu_enabled, detach__disable) + +#undef _T + return ret; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 82b2b5e6ba7c..0fc946989cf0 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -85,6 +85,7 @@ int test__synthesize_stat_config(int subtest); int test__synthesize_stat(int subtest); int test__synthesize_stat_round(int subtest); int test__event_update(int subtest); +int test__event_times(int subtest); #if defined(__arm__) || defined(__aarch64__) #ifdef HAVE_DWARF_UNWIND_SUPPORT -- GitLab From 58cb9d650be45100bf53ddf9e00351391de3d735 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Mon, 28 Mar 2016 02:22:18 +0900 Subject: [PATCH 0785/9938] perf config: Remove duplicated set_buildid_dir calls Signed-off-by: Taeung Song Acked-by: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1459099340-16911-1-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/perf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/perf/perf.c b/tools/perf/perf.c index aaee0a782747..7b2df2b46525 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -549,6 +549,7 @@ int main(int argc, const char **argv) srandom(time(NULL)); perf_config(perf_default_config, NULL); + set_buildid_dir(NULL); /* get debugfs/tracefs mount point from /proc/mounts */ tracing_path_mount(); @@ -572,7 +573,6 @@ int main(int argc, const char **argv) } if (!prefixcmp(cmd, "trace")) { #ifdef HAVE_LIBAUDIT_SUPPORT - set_buildid_dir(NULL); setup_path(); argv[0] = "trace"; return cmd_trace(argc, argv, NULL); @@ -587,7 +587,6 @@ int main(int argc, const char **argv) argc--; handle_options(&argv, &argc, NULL); commit_pager_choice(); - set_buildid_dir(NULL); if (argc > 0) { if (!prefixcmp(argv[0], "--")) -- GitLab From 9cb5987c822714352e3eb46806fc260b3cb4ff0d Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Mon, 28 Mar 2016 02:22:19 +0900 Subject: [PATCH 0786/9938] perf config: Rework buildid_dir_command_config to perf_buildid_config To avoid repeated calling perf_config() remove buildid_dir_command_config() and add new perf_buildid_config into perf_default_config. Because perf_config() is already called with perf_default_config at main(). Signed-off-by: Taeung Song Acked-by: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1459099340-16911-2-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/config.c | 50 +++++++++++++++------------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 4e727635476e..2dd78f4c97a0 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -377,6 +377,21 @@ const char *perf_config_dirname(const char *name, const char *value) return value; } +static int perf_buildid_config(const char *var, const char *value) +{ + /* same dir for all commands */ + if (!strcmp(var, "buildid.dir")) { + const char *dirname = perf_config_dirname(var, value); + + if (!dirname) + return -1; + strncpy(buildid_dir, dirname, MAXPATHLEN-1); + buildid_dir[MAXPATHLEN-1] = '\0'; + } + + return 0; +} + static int perf_default_core_config(const char *var __maybe_unused, const char *value __maybe_unused) { @@ -412,6 +427,9 @@ int perf_default_config(const char *var, const char *value, if (!prefixcmp(var, "llvm.")) return perf_llvm_config(var, value); + if (!prefixcmp(var, "buildid.")) + return perf_buildid_config(var, value); + /* Add other config variables here. */ return 0; } @@ -515,43 +533,11 @@ int config_error_nonbool(const char *var) return error("Missing value for '%s'", var); } -struct buildid_dir_config { - char *dir; -}; - -static int buildid_dir_command_config(const char *var, const char *value, - void *data) -{ - struct buildid_dir_config *c = data; - const char *v; - - /* same dir for all commands */ - if (!strcmp(var, "buildid.dir")) { - v = perf_config_dirname(var, value); - if (!v) - return -1; - strncpy(c->dir, v, MAXPATHLEN-1); - c->dir[MAXPATHLEN-1] = '\0'; - } - return 0; -} - -static void check_buildid_dir_config(void) -{ - struct buildid_dir_config c; - c.dir = buildid_dir; - perf_config(buildid_dir_command_config, &c); -} - void set_buildid_dir(const char *dir) { if (dir) scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); - /* try config file */ - if (buildid_dir[0] == '\0') - check_buildid_dir_config(); - /* default to $HOME/.debug */ if (buildid_dir[0] == '\0') { char *v = getenv("HOME"); -- GitLab From 37194f443a5a7157866ba68b04827e111100167b Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Mon, 28 Mar 2016 02:22:20 +0900 Subject: [PATCH 0787/9938] perf config: Rename 'v' to 'home' in set_buildid_dir() Change the variable name 'v' to 'home' to make it more readable. Signed-off-by: Taeung Song Acked-by: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1459099340-16911-3-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/config.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 2dd78f4c97a0..5c20d783423b 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -540,10 +540,11 @@ void set_buildid_dir(const char *dir) /* default to $HOME/.debug */ if (buildid_dir[0] == '\0') { - char *v = getenv("HOME"); - if (v) { + char *home = getenv("HOME"); + + if (home) { snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", - v, DEBUG_CACHE_DIR); + home, DEBUG_CACHE_DIR); } else { strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); } -- GitLab From f7380c12ec6cfd69f274ba6181cd01c764f877bb Mon Sep 17 00:00:00 2001 From: Dima Kogan Date: Tue, 29 Mar 2016 12:47:53 -0300 Subject: [PATCH 0788/9938] perf script perl: Perl scripts now get a backtrace, like the python ones We have some infrastructure to use perl or python to analyze logs generated by perf. Prior to this patch, only the python tools had access to backtrace information. This patch makes this information available to perl scripts as well. Example: Let's look at malloc() calls made by the seq utility. First we create a probe point: $ perf probe -x /lib/x86_64-linux-gnu/libc.so.6 malloc Added new events: ... Now we run seq, while monitoring malloc() calls with perf $ perf record --call-graph=dwarf -e probe_libc:malloc seq 5 1 2 3 4 5 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.064 MB perf.data (6 samples) ] We can use perf to look at its log to see the malloc calls and the backtrace $ perf script seq 14195 [000] 1927993.748254: probe_libc:malloc: (7f9ff8edd320) bytes=0x22 7f9ff8edd320 malloc (/lib/x86_64-linux-gnu/libc-2.22.so) 7f9ff8e8eab0 set_binding_values.part.0 (/lib/x86_64-linux-gnu/libc-2.22.so) 7f9ff8e8eda1 __bindtextdomain (/lib/x86_64-linux-gnu/libc-2.22.so) 401b22 main (/usr/bin/seq) 7f9ff8e82610 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.22.so) 402799 _start (/usr/bin/seq) ... We can also use the scripting facilities. We create a skeleton perl script that simply prints out the events $ perf script -g perl generated Perl script: perf-script.pl We can then use this script to see the malloc() calls with a backtrace. Prior to this patch, the backtrace was not available to the perl scripts. $ perf script -s perf-script.pl probe_libc::malloc 0 1927993.748254260 14195 seq __probe_ip=140325052863264, bytes=34 [7f9ff8edd320] malloc [7f9ff8e8eab0] set_binding_values.part.0 [7f9ff8e8eda1] __bindtextdomain [401b22] main [7f9ff8e82610] __libc_start_main [402799] _start ... Tested-by: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/87mvphzld0.fsf@secretsauce.net Signed-off-by: Dima Kogan --- .../util/scripting-engines/trace-event-perl.c | 114 ++++++++++++++++-- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index b3aabc0d4eb0..1d160855cda9 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -31,6 +31,8 @@ #include #include "../../perf.h" +#include "../callchain.h" +#include "../machine.h" #include "../thread.h" #include "../event.h" #include "../trace-event.h" @@ -248,10 +250,78 @@ static void define_event_symbols(struct event_format *event, define_event_symbols(event, ev_name, args->next); } +static SV *perl_process_callchain(struct perf_sample *sample, + struct perf_evsel *evsel, + struct addr_location *al) +{ + AV *list; + + list = newAV(); + if (!list) + goto exit; + + if (!symbol_conf.use_callchain || !sample->callchain) + goto exit; + + if (thread__resolve_callchain(al->thread, evsel, + sample, NULL, NULL, + PERF_MAX_STACK_DEPTH) != 0) { + pr_err("Failed to resolve callchain. Skipping\n"); + goto exit; + } + callchain_cursor_commit(&callchain_cursor); + + + while (1) { + HV *elem; + struct callchain_cursor_node *node; + node = callchain_cursor_current(&callchain_cursor); + if (!node) + break; + + elem = newHV(); + if (!elem) + goto exit; + + hv_stores(elem, "ip", newSVuv(node->ip)); + + if (node->sym) { + HV *sym = newHV(); + if (!sym) + goto exit; + hv_stores(sym, "start", newSVuv(node->sym->start)); + hv_stores(sym, "end", newSVuv(node->sym->end)); + hv_stores(sym, "binding", newSVuv(node->sym->binding)); + hv_stores(sym, "name", newSVpvn(node->sym->name, + node->sym->namelen)); + hv_stores(elem, "sym", newRV_noinc((SV*)sym)); + } + + if (node->map) { + struct map *map = node->map; + const char *dsoname = "[unknown]"; + if (map && map->dso && (map->dso->name || map->dso->long_name)) { + if (symbol_conf.show_kernel_path && map->dso->long_name) + dsoname = map->dso->long_name; + else if (map->dso->name) + dsoname = map->dso->name; + } + hv_stores(elem, "dso", newSVpv(dsoname,0)); + } + + callchain_cursor_advance(&callchain_cursor); + av_push(list, newRV_noinc((SV*)elem)); + } + +exit: + return newRV_noinc((SV*)list); +} + static void perl_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, - struct thread *thread) + struct addr_location *al) { + struct thread *thread = al->thread; struct event_format *event = evsel->tp_format; struct format_field *field; static char handler[256]; @@ -295,6 +365,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, XPUSHs(sv_2mortal(newSVuv(ns))); XPUSHs(sv_2mortal(newSViv(pid))); XPUSHs(sv_2mortal(newSVpv(comm, 0))); + XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al))); /* common fields other than pid can be accessed via xsub fns */ @@ -329,6 +400,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, XPUSHs(sv_2mortal(newSVuv(nsecs))); XPUSHs(sv_2mortal(newSViv(pid))); XPUSHs(sv_2mortal(newSVpv(comm, 0))); + XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al))); call_pv("main::trace_unhandled", G_SCALAR); } SPAGAIN; @@ -366,7 +438,7 @@ static void perl_process_event(union perf_event *event, struct perf_evsel *evsel, struct addr_location *al) { - perl_process_tracepoint(sample, evsel, al->thread); + perl_process_tracepoint(sample, evsel, al); perl_process_event_generic(event, sample, evsel); } @@ -490,7 +562,27 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) fprintf(ofp, "use Perf::Trace::Util;\n\n"); fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n"); - fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n"); + fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n"); + + + fprintf(ofp, "\n\ +sub print_backtrace\n\ +{\n\ + my $callchain = shift;\n\ + for my $node (@$callchain)\n\ + {\n\ + if(exists $node->{sym})\n\ + {\n\ + printf( \"\\t[\\%%x] \\%%s\\n\", $node->{ip}, $node->{sym}{name});\n\ + }\n\ + else\n\ + {\n\ + printf( \"\\t[\\%%x]\\n\", $node{ip});\n\ + }\n\ + }\n\ +}\n\n\ +"); + while ((event = trace_find_next_event(pevent, event))) { fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); @@ -502,7 +594,8 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) fprintf(ofp, "$common_secs, "); fprintf(ofp, "$common_nsecs,\n"); fprintf(ofp, "\t $common_pid, "); - fprintf(ofp, "$common_comm,\n\t "); + fprintf(ofp, "$common_comm, "); + fprintf(ofp, "$common_callchain,\n\t "); not_first = 0; count = 0; @@ -519,7 +612,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) fprintf(ofp, "\tprint_header($event_name, $common_cpu, " "$common_secs, $common_nsecs,\n\t " - "$common_pid, $common_comm);\n\n"); + "$common_pid, $common_comm, $common_callchain);\n\n"); fprintf(ofp, "\tprintf(\""); @@ -581,17 +674,22 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) fprintf(ofp, "$%s", f->name); } - fprintf(ofp, ");\n"); + fprintf(ofp, ");\n\n"); + + fprintf(ofp, "\tprint_backtrace($common_callchain);\n"); + fprintf(ofp, "}\n\n"); } fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, " "$common_cpu, $common_secs, $common_nsecs,\n\t " - "$common_pid, $common_comm) = @_;\n\n"); + "$common_pid, $common_comm, $common_callchain) = @_;\n\n"); fprintf(ofp, "\tprint_header($event_name, $common_cpu, " "$common_secs, $common_nsecs,\n\t $common_pid, " - "$common_comm);\n}\n\n"); + "$common_comm, $common_callchain);\n"); + fprintf(ofp, "\tprint_backtrace($common_callchain);\n"); + fprintf(ofp, "}\n\n"); fprintf(ofp, "sub print_header\n{\n" "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" -- GitLab From d1706b39f0af6901ab2a5e2ebb210b53c1a5bdc7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 28 Mar 2016 10:45:38 -0700 Subject: [PATCH 0789/9938] perf tools: Add support for skipping itrace instructions When using 'perf script' to look at PT traces it is often useful to ignore the initialization code at the beginning. On larger traces which may have many millions of instructions in initialization code doing that in a pipeline can be very slow, with perf script spending a lot of CPU time calling printf and writing data. This patch adds an extension to the --itrace argument that skips 'n' events (instructions, branches or transactions) at the beginning. This is much more efficient. v2: Add support for BTS (Adrian Hunter) Document in itrace.txt Fix branch check Check transactions and instructions too Committer note: To test intel_pt one needs to make sure VT-x isn't active, i.e. stopping KVM guests on the test machine, as described by Andi Kleen at http://lkml.kernel.org/r/20160301234953.GD23621@tassilo.jf.intel.com Signed-off-by: Andi Kleen Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Jiri Olsa Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1459187142-20035-1-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/intel-pt.txt | 7 +++++++ tools/perf/Documentation/itrace.txt | 8 ++++++++ tools/perf/util/auxtrace.c | 7 +++++++ tools/perf/util/auxtrace.h | 2 ++ tools/perf/util/intel-bts.c | 5 +++++ tools/perf/util/intel-pt.c | 22 ++++++++++++++++++++-- 6 files changed, 49 insertions(+), 2 deletions(-) diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt index be764f9ec769..c6c8318e38a2 100644 --- a/tools/perf/Documentation/intel-pt.txt +++ b/tools/perf/Documentation/intel-pt.txt @@ -672,6 +672,7 @@ The letters are: d create a debug log g synthesize a call chain (use with i or x) l synthesize last branch entries (use with i or x) + s skip initial number of events "Instructions" events look like they were recorded by "perf record -e instructions". @@ -730,6 +731,12 @@ from one sample to the next. To disable trace decoding entirely, use the option --no-itrace. +It is also possible to skip events generated (instructions, branches, transactions) +at the beginning. This is useful to ignore initialization code. + + --itrace=i0nss1000000 + +skips the first million instructions. dump option ----------- diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt index 65453f4c7006..e2a4c5e0dbe5 100644 --- a/tools/perf/Documentation/itrace.txt +++ b/tools/perf/Documentation/itrace.txt @@ -7,6 +7,7 @@ d create a debug log g synthesize a call chain (use with i or x) l synthesize last branch entries (use with i or x) + s skip initial number of events The default is all events i.e. the same as --itrace=ibxe @@ -24,3 +25,10 @@ Also the number of last branch entries (default 64, max. 1024) for instructions or transactions events can be specified. + + It is also possible to skip events generated (instructions, branches, transactions) + at the beginning. This is useful to ignore initialization code. + + --itrace=i0nss1000000 + + skips the first million instructions. diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index ec164fe70718..c9169011e55e 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -940,6 +940,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; + synth_opts->initial_skip = 0; } /* @@ -1064,6 +1065,12 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, synth_opts->last_branch_sz = val; } break; + case 's': + synth_opts->initial_skip = strtoul(p, &endptr, 10); + if (p == endptr) + goto out_err; + p = endptr; + break; case ' ': case ',': break; diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 57ff31ecb8e4..767989e0e312 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -68,6 +68,7 @@ enum itrace_period_type { * @last_branch_sz: branch context size * @period: 'instructions' events period * @period_type: 'instructions' events period type + * @initial_skip: skip N events at the beginning. */ struct itrace_synth_opts { bool set; @@ -86,6 +87,7 @@ struct itrace_synth_opts { unsigned int last_branch_sz; unsigned long long period; enum itrace_period_type period_type; + unsigned long initial_skip; }; /** diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index abf1366e2a24..9df996085563 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c @@ -66,6 +66,7 @@ struct intel_bts { u64 branches_id; size_t branches_event_size; bool synth_needs_swap; + unsigned long num_events; }; struct intel_bts_queue { @@ -275,6 +276,10 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq, union perf_event event; struct perf_sample sample = { .ip = 0, }; + if (bts->synth_opts.initial_skip && + bts->num_events++ <= bts->synth_opts.initial_skip) + return 0; + event.sample.header.type = PERF_RECORD_SAMPLE; event.sample.header.misc = PERF_RECORD_MISC_USER; event.sample.header.size = sizeof(struct perf_event_header); diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 407f11b97c8d..ddec87f6e616 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -100,6 +100,8 @@ struct intel_pt { u64 cyc_bit; u64 noretcomp_bit; unsigned max_non_turbo_ratio; + + unsigned long num_events; }; enum switch_state { @@ -972,6 +974,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) return 0; + if (pt->synth_opts.initial_skip && + pt->num_events++ < pt->synth_opts.initial_skip) + return 0; + event->sample.header.type = PERF_RECORD_SAMPLE; event->sample.header.misc = PERF_RECORD_MISC_USER; event->sample.header.size = sizeof(struct perf_event_header); @@ -1029,6 +1035,10 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) union perf_event *event = ptq->event_buf; struct perf_sample sample = { .ip = 0, }; + if (pt->synth_opts.initial_skip && + pt->num_events++ < pt->synth_opts.initial_skip) + return 0; + event->sample.header.type = PERF_RECORD_SAMPLE; event->sample.header.misc = PERF_RECORD_MISC_USER; event->sample.header.size = sizeof(struct perf_event_header); @@ -1087,6 +1097,10 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) union perf_event *event = ptq->event_buf; struct perf_sample sample = { .ip = 0, }; + if (pt->synth_opts.initial_skip && + pt->num_events++ < pt->synth_opts.initial_skip) + return 0; + event->sample.header.type = PERF_RECORD_SAMPLE; event->sample.header.misc = PERF_RECORD_MISC_USER; event->sample.header.size = sizeof(struct perf_event_header); @@ -1199,14 +1213,18 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) ptq->have_sample = false; if (pt->sample_instructions && - (state->type & INTEL_PT_INSTRUCTION)) { + (state->type & INTEL_PT_INSTRUCTION) && + (!pt->synth_opts.initial_skip || + pt->num_events++ >= pt->synth_opts.initial_skip)) { err = intel_pt_synth_instruction_sample(ptq); if (err) return err; } if (pt->sample_transactions && - (state->type & INTEL_PT_TRANSACTION)) { + (state->type & INTEL_PT_TRANSACTION) && + (!pt->synth_opts.initial_skip || + pt->num_events++ >= pt->synth_opts.initial_skip)) { err = intel_pt_synth_transaction_sample(ptq); if (err) return err; -- GitLab From 45fa2038cf7820ecfcca8793b81e656ca3caaf0f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 30 Mar 2016 08:26:09 -0700 Subject: [PATCH 0790/9938] regulator: of: Don't flag voltage change as possible for exact voltages Flagging voltage changes as possible for exactly specified voltages appears to be triggering bugs in the SDHCI code (it should be able to handle the case where only one voltage it wants is in the range it is allowed to set) so make sure we only set the flag in cases where there's genuine variability. Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index f45106a44635..cd828dbf9d52 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -43,10 +43,12 @@ static void of_get_regulation_constraints(struct device_node *np, constraints->max_uV = pval; /* Voltage change possible? */ - if (constraints->min_uV && constraints->max_uV) { + if (constraints->min_uV != constraints->max_uV) constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + + /* Do we have a voltage range, if so try to apply it? */ + if (constraints->min_uV && constraints->max_uV) constraints->apply_uV = true; - } if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval)) constraints->uV_offset = pval; -- GitLab From 4f7d6dd4df8b388e2056c89b528254cdd79dea2a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Mar 2016 12:28:33 -0700 Subject: [PATCH 0791/9938] regmap: Fix implicit inclusion of device.h internal.h is using dev_name() but doesn't include device.h which defines it. Add an explicit include to avoid build problems due to this. Tested-by: Alexander Stein Signed-off-by: Mark Brown --- drivers/base/regmap/internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 5c79526245c2..a0380338946a 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -13,6 +13,7 @@ #ifndef _REGMAP_INTERNAL_H #define _REGMAP_INTERNAL_H +#include #include #include #include -- GitLab From 0dbdb76c0ca8e7caf27c9a210f64c4359e2974a4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Mar 2016 12:30:44 -0700 Subject: [PATCH 0792/9938] regmap: mmio: Parse endianness definitions from DT Since we changed to do formatting in the bus we now skip all the format parsing that the core does for its data marshalling code. This means that we skip the DT parsing it does which breaks some systems, we need to add an explict call in the MMIO code to do this. Reported-by: Alexander Stein Tested-by: Alexander Stein Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-mmio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index b27573c69af7..7132a662c80d 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -23,6 +23,8 @@ #include #include +#include "internal.h" + struct regmap_mmio_context { void __iomem *regs; unsigned val_bytes; @@ -245,7 +247,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, ctx->val_bytes = config->val_bits / 8; ctx->clk = ERR_PTR(-ENODEV); - switch (config->val_format_endian) { + switch (regmap_get_val_endian(dev, ®map_mmio, config)) { case REGMAP_ENDIAN_DEFAULT: case REGMAP_ENDIAN_LITTLE: #ifdef __LITTLE_ENDIAN -- GitLab From b18db6de2ce2a6ca7f5da03701a2aa8c63b31b74 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 Mar 2016 05:23:16 -0700 Subject: [PATCH 0793/9938] jfs: Remove terminating newlines from jfs_info, jfs_warn, jfs_err uses These macros add the newline so these cause extra blank lines in logging output. Signed-off-by: Joe Perches Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_inode.c | 2 +- fs/jfs/jfs_logmgr.c | 4 ++-- fs/jfs/jfs_txnmgr.c | 4 ++-- fs/jfs/super.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c index cf7936fe2e68..5e33cb9a190d 100644 --- a/fs/jfs/jfs_inode.c +++ b/fs/jfs/jfs_inode.c @@ -151,7 +151,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode) jfs_inode->xtlid = 0; jfs_set_inode_flags(inode); - jfs_info("ialloc returns inode = 0x%p\n", inode); + jfs_info("ialloc returns inode = 0x%p", inode); return inode; diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index a270cb7ff4e0..7638355addcc 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1094,7 +1094,7 @@ int lmLogOpen(struct super_block *sb) if (log->bdev->bd_dev == sbi->logdev) { if (memcmp(log->uuid, sbi->loguuid, sizeof(log->uuid))) { - jfs_warn("wrong uuid on JFS journal\n"); + jfs_warn("wrong uuid on JFS journal"); mutex_unlock(&jfs_log_mutex); return -EINVAL; } @@ -2136,7 +2136,7 @@ static void lbmStartIO(struct lbuf * bp) struct bio *bio; struct jfs_log *log = bp->l_log; - jfs_info("lbmStartIO\n"); + jfs_info("lbmStartIO"); bio = bio_alloc(GFP_NOFS, 1); bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize - 9); diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index d595856453b2..51421a84f45e 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -1764,7 +1764,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, if (lwm == next) goto out; if (lwm > next) { - jfs_err("xtLog: lwm > next\n"); + jfs_err("xtLog: lwm > next"); goto out; } tlck->flag |= tlckUPDATEMAP; @@ -2814,7 +2814,7 @@ int jfs_lazycommit(void *arg) if (!list_empty(&TxAnchor.unlock_queue)) jfs_err("jfs_lazycommit being killed w/pending transactions!"); else - jfs_info("jfs_lazycommit being killed\n"); + jfs_info("jfs_lazycommit being killed"); return 0; } diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 4f5d85ba8e23..f908012b101a 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -84,7 +84,7 @@ static void jfs_handle_error(struct super_block *sb) panic("JFS (device %s): panic forced after error\n", sb->s_id); else if (sbi->flag & JFS_ERR_REMOUNT_RO) { - jfs_err("ERROR: (device %s): remounting filesystem as read-only\n", + jfs_err("ERROR: (device %s): remounting filesystem as read-only", sb->s_id); sb->s_flags |= MS_RDONLY; } @@ -641,7 +641,7 @@ static int jfs_freeze(struct super_block *sb) } rc = updateSuper(sb, FM_CLEAN); if (rc) { - jfs_err("jfs_freeze: updateSuper failed\n"); + jfs_err("jfs_freeze: updateSuper failed"); /* * Don't fail here. Everything succeeded except * marking the superblock clean, so there's really -- GitLab From aa575749f4356d68bc2973f213e7d28cc146ebce Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 Mar 2016 05:23:17 -0700 Subject: [PATCH 0794/9938] jfs: Remove unnecessary line continuations and terminating newlines These jfs_ uses need neither a line continuation to assemble the format strings nor newline terminations in the formats. Signed-off-by: Joe Perches Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_discard.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/jfs/jfs_discard.c b/fs/jfs/jfs_discard.c index dfcd50304559..f76ff0a46444 100644 --- a/fs/jfs/jfs_discard.c +++ b/fs/jfs/jfs_discard.c @@ -49,14 +49,12 @@ void jfs_issue_discard(struct inode *ip, u64 blkno, u64 nblocks) r = sb_issue_discard(sb, blkno, nblocks, GFP_NOFS, 0); if (unlikely(r != 0)) { - jfs_err("JFS: sb_issue_discard" \ - "(%p, %llu, %llu, GFP_NOFS, 0) = %d => failed!\n", + jfs_err("JFS: sb_issue_discard(%p, %llu, %llu, GFP_NOFS, 0) = %d => failed!", sb, (unsigned long long)blkno, (unsigned long long)nblocks, r); } - jfs_info("JFS: sb_issue_discard" \ - "(%p, %llu, %llu, GFP_NOFS, 0) = %d\n", + jfs_info("JFS: sb_issue_discard(%p, %llu, %llu, GFP_NOFS, 0) = %d", sb, (unsigned long long)blkno, (unsigned long long)nblocks, r); -- GitLab From 6ed71e9819ac3412fc6a3495f5ce141df274c916 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 Mar 2016 05:23:18 -0700 Subject: [PATCH 0795/9938] jfs: Coalesce some formats Formats are better kept as a single line for easier grep. Signed-off-by: Joe Perches Signed-off-by: Dave Kleikamp --- fs/jfs/inode.c | 4 ++-- fs/jfs/jfs_dtree.c | 10 ++++------ fs/jfs/jfs_imap.c | 3 +-- fs/jfs/jfs_logmgr.c | 10 ++++------ fs/jfs/jfs_txnmgr.c | 17 +++++++---------- fs/jfs/namei.c | 4 ++-- 6 files changed, 20 insertions(+), 28 deletions(-) diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 9d9bae63ae2a..da1d02116a19 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -102,8 +102,8 @@ int jfs_commit_inode(struct inode *inode, int wait) * partitions and may think inode is dirty */ if (!special_file(inode->i_mode) && noisy) { - jfs_err("jfs_commit_inode(0x%p) called on " - "read-only volume", inode); + jfs_err("jfs_commit_inode(0x%p) called on read-only volume", + inode); jfs_err("Is remount racy?"); noisy--; } diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index d88576e23fe4..de2bcb36e079 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -3072,8 +3072,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) } if (dirtab_slot.flag == DIR_INDEX_FREE) { if (loop_count++ > JFS_IP(ip)->next_index) { - jfs_err("jfs_readdir detected " - "infinite loop!"); + jfs_err("jfs_readdir detected infinite loop!"); ctx->pos = DIREND; return 0; } @@ -3151,8 +3150,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR)) return 0; } else { - jfs_err("jfs_readdir called with " - "invalid offset!"); + jfs_err("jfs_readdir called with invalid offset!"); } dtoffset->pn = 1; dtoffset->index = 0; @@ -3165,8 +3163,8 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) } if ((rc = dtReadNext(ip, &ctx->pos, &btstack))) { - jfs_err("jfs_readdir: unexpected rc = %d " - "from dtReadNext", rc); + jfs_err("jfs_readdir: unexpected rc = %d from dtReadNext", + rc); ctx->pos = DIREND; return 0; } diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index f321986e73d2..6aca224a5d68 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -534,8 +534,7 @@ void diWriteSpecial(struct inode *ip, int secondary) /* read the page of fixed disk inode (AIT) in raw mode */ mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1); if (mp == NULL) { - jfs_err("diWriteSpecial: failed to read aggregate inode " - "extent!"); + jfs_err("diWriteSpecial: failed to read aggregate inode extent!"); return; } diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 7638355addcc..63759d723920 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1333,9 +1333,8 @@ int lmLogInit(struct jfs_log * log) rc = -EINVAL; goto errout20; } - jfs_info("lmLogInit: inline log:0x%p base:0x%Lx " - "size:0x%x", log, - (unsigned long long) log->base, log->size); + jfs_info("lmLogInit: inline log:0x%p base:0x%Lx size:0x%x", + log, (unsigned long long)log->base, log->size); } else { if (memcmp(logsuper->uuid, log->uuid, 16)) { jfs_warn("wrong uuid on JFS log device"); @@ -1343,9 +1342,8 @@ int lmLogInit(struct jfs_log * log) } log->size = le32_to_cpu(logsuper->size); log->l2bsize = le32_to_cpu(logsuper->l2bsize); - jfs_info("lmLogInit: external log:0x%p base:0x%Lx " - "size:0x%x", log, - (unsigned long long) log->base, log->size); + jfs_info("lmLogInit: external log:0x%p base:0x%Lx size:0x%x", + log, (unsigned long long)log->base, log->size); } log->page = le32_to_cpu(logsuper->end) / LOGPSIZE; diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 51421a84f45e..eddf2b6eda85 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -1798,8 +1798,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, xadlock->xdlist = &p->xad[lwm]; tblk->xflag &= ~COMMIT_LAZY; } - jfs_info("xtLog: alloc ip:0x%p mp:0x%p tlck:0x%p lwm:%d " - "count:%d", tlck->ip, mp, tlck, lwm, xadlock->count); + jfs_info("xtLog: alloc ip:0x%p mp:0x%p tlck:0x%p lwm:%d count:%d", + tlck->ip, mp, tlck, lwm, xadlock->count); maplock->index = 1; @@ -2025,8 +2025,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, xadlock->count = next - lwm; xadlock->xdlist = &p->xad[lwm]; - jfs_info("xtLog: alloc ip:0x%p mp:0x%p count:%d " - "lwm:%d next:%d", + jfs_info("xtLog: alloc ip:0x%p mp:0x%p count:%d lwm:%d next:%d", tlck->ip, mp, xadlock->count, lwm, next); maplock->index++; xadlock++; @@ -2047,8 +2046,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, pxdlock->count = 1; pxdlock->pxd = pxd; - jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d " - "hwm:%d", ip, mp, pxdlock->count, hwm); + jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d hwm:%d", + ip, mp, pxdlock->count, hwm); maplock->index++; xadlock++; } @@ -2066,8 +2065,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, xadlock->count = hwm - next + 1; xadlock->xdlist = &p->xad[next]; - jfs_info("xtLog: free ip:0x%p mp:0x%p count:%d " - "next:%d hwm:%d", + jfs_info("xtLog: free ip:0x%p mp:0x%p count:%d next:%d hwm:%d", tlck->ip, mp, xadlock->count, next, hwm); maplock->index++; } @@ -2523,8 +2521,7 @@ void txFreeMap(struct inode *ip, xlen = lengthXAD(xad); dbUpdatePMap(ipbmap, true, xaddr, (s64) xlen, tblk); - jfs_info("freePMap: xaddr:0x%lx " - "xlen:%d", + jfs_info("freePMap: xaddr:0x%lx xlen:%d", (ulong) xaddr, xlen); } } diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 701f89370de7..211796a4baf2 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1225,8 +1225,8 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_CREATE); if (rc) { - jfs_err("jfs_rename didn't expect dtSearch to fail " - "w/rc = %d", rc); + jfs_err("jfs_rename didn't expect dtSearch to fail w/rc = %d", + rc); goto out_tx; } -- GitLab From d991c872ac7ffaacc4df93efbfbcb4189cee6440 Mon Sep 17 00:00:00 2001 From: Sander Eikelenboom Date: Sun, 20 Mar 2016 22:27:06 +0100 Subject: [PATCH 0796/9938] libata: Fixup awkward whitespace in warning by removing line continuation. Signed-off-by: Sander Eikelenboom Signed-off-by: Tejun Heo --- drivers/ata/libahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 3982054060b8..e13ba72234dc 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2549,8 +2549,8 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht) if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) { if (hpriv->irq_handler) - dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set \ - and custom irq handler implemented\n"); + dev_warn(host->dev, + "both AHCI_HFLAG_MULTI_MSI flag set and custom irq handler implemented\n"); rc = ahci_host_activate_multi_irqs(host, sht); } else { -- GitLab From 2dfadff69e8b1da8f8661e9edb131b208cc389b7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 30 Mar 2016 18:25:07 +0800 Subject: [PATCH 0797/9938] ASoC: rt5677: Avoid duplicate the same test in each switch case Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 33e290b703df..b3f1db5bae4a 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -1241,60 +1241,46 @@ static int rt5677_dmic_use_asrc(struct snd_soc_dapm_widget *source, regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); asrc_setting = (asrc_setting & RT5677_AD_STO1_CLK_SEL_MASK) >> RT5677_AD_STO1_CLK_SEL_SFT; - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) - return 1; break; case 10: regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); asrc_setting = (asrc_setting & RT5677_AD_STO2_CLK_SEL_MASK) >> RT5677_AD_STO2_CLK_SEL_SFT; - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) - return 1; break; case 9: regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); asrc_setting = (asrc_setting & RT5677_AD_STO3_CLK_SEL_MASK) >> RT5677_AD_STO3_CLK_SEL_SFT; - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) - return 1; break; case 8: regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); asrc_setting = (asrc_setting & RT5677_AD_STO4_CLK_SEL_MASK) >> RT5677_AD_STO4_CLK_SEL_SFT; - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) - return 1; break; case 7: regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); asrc_setting = (asrc_setting & RT5677_AD_MONOL_CLK_SEL_MASK) >> RT5677_AD_MONOL_CLK_SEL_SFT; - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) - return 1; break; case 6: regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); asrc_setting = (asrc_setting & RT5677_AD_MONOR_CLK_SEL_MASK) >> RT5677_AD_MONOR_CLK_SEL_SFT; - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) - return 1; break; default: - break; + return 0; } + if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && + asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) + return 1; + return 0; } -- GitLab From 97d8eb16aa84eb48466f34c3ec0f492f34b85a04 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 23 Mar 2016 11:49:53 -0700 Subject: [PATCH 0798/9938] arm64: defconfig: enable basic boot for Amlogic meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enables basic arch and serial console support for Amlogic meson family SoCs. Tested with Amlogic P200 and Hardkernel ODROID-C2 boards. Signed-off-by: Kevin Hilman Reviewed-by: Andreas Färber --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f70505186820..71c9d21c06ca 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -38,6 +38,7 @@ CONFIG_ARCH_EXYNOS=y CONFIG_ARCH_LAYERSCAPE=y CONFIG_ARCH_HISI=y CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MESON=y CONFIG_ARCH_MVEBU=y CONFIG_ARCH_QCOM=y CONFIG_ARCH_ROCKCHIP=y @@ -137,6 +138,8 @@ CONFIG_SERIAL_TEGRA=y CONFIG_SERIAL_SH_SCI=y CONFIG_SERIAL_SH_SCI_NR_UARTS=11 CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_MESON=y +CONFIG_SERIAL_MESON_CONSOLE=y CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y CONFIG_SERIAL_XILINX_PS_UART=y -- GitLab From 65eb22ea1da80eb12f2cc10f397f28193b1dfb91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 17 Mar 2016 00:10:53 +0100 Subject: [PATCH 0799/9938] ARM64: dts: amlogic: Clean up Vega S95 /memory nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve the following warnings from new dtc by adding the unit address: DTC arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dtb Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name DTC arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dtb Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name DTC arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dtb Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name Fixes: cc733bc90636 ("ARM64: dts: amlogic: Add Tronsmart Vega S95 configs") Signed-off-by: Andreas Färber --- arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts | 2 +- arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts | 2 +- arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts index 399aff9e7975..62fb4968d680 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts @@ -48,7 +48,7 @@ compatible = "tronsmart,vega-s95-meta", "tronsmart,vega-s95", "amlogic,meson-gxbb"; model = "Tronsmart Vega S95 Meta"; - memory { + memory@0 { device_type = "memory"; reg = <0x0 0x0 0x0 0x80000000>; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts index ac5a241b5ec2..9a9663abdf5c 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts @@ -48,7 +48,7 @@ compatible = "tronsmart,vega-s95-pro", "tronsmart,vega-s95", "amlogic,meson-gxbb"; model = "Tronsmart Vega S95 Pro"; - memory { + memory@0 { device_type = "memory"; reg = <0x0 0x0 0x0 0x40000000>; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts index fff7bfa2aa39..2fe167b2609d 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts @@ -48,7 +48,7 @@ compatible = "tronsmart,vega-s95-telos", "tronsmart,vega-s95", "amlogic,meson-gxbb"; model = "Tronsmart Vega S95 Telos"; - memory { + memory@0 { device_type = "memory"; reg = <0x0 0x0 0x0 0x80000000>; }; -- GitLab From 962f271ec9463648ea52c13bb51bcc46afde0396 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 24 Mar 2016 11:05:12 -0700 Subject: [PATCH 0800/9938] ARM64: dts: amlogic: update serial aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently, it's not valid to have an alias point to a disabled device. Fix this by moving the aliases that are used (serial0) into the files that use them, and remove aliases to disabled devices (serial1). Suggested-by: Arnd Bergmann Signed-off-by: Kevin Hilman Reviewed-by: Andreas Färber Acked-by: Arnd Bergmann --- arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 4 ++++ arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 5 ----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi index c1fa2667ec5c..012cdccc8a35 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi @@ -45,6 +45,10 @@ / { compatible = "tronsmart,vega-s95", "amlogic,meson-gxbb"; + aliases { + serial0 = &uart_AO; + }; + chosen { stdout-path = "serial0:115200n8"; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi index eaa0a4553734..832815d80462 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi @@ -50,11 +50,6 @@ #address-cells = <2>; #size-cells = <2>; - aliases { - serial0 = &uart_AO; - serial1 = &uart_A; - }; - cpus { #address-cells = <0x2>; #size-cells = <0x0>; -- GitLab From a426e1dee661f41e330f73b1e8a301618e12eb98 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 24 Mar 2016 11:05:13 -0700 Subject: [PATCH 0801/9938] Documentation: devicetree: amlogic: Document P20x and ODROID-C2 boards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add compatible strings for Amlogic S905/GXBB based boards: Hardkernel ODROID-C2, Amlogic P200 and Amlogic P201. Cc: devicetree@vger.kernel.org Reviewed-by: Andreas Färber Signed-off-by: Kevin Hilman Acked-by: Rob Herring Acked-by: Arnd Bergmann --- Documentation/devicetree/bindings/arm/amlogic.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/amlogic.txt b/Documentation/devicetree/bindings/arm/amlogic.txt index 8a5122ab19b0..fcc6f6c10803 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.txt +++ b/Documentation/devicetree/bindings/arm/amlogic.txt @@ -25,3 +25,6 @@ Board compatible values: - "tronsmart,vega-s95-pro", "tronsmart,vega-s95" (Meson gxbb) - "tronsmart,vega-s95-meta", "tronsmart,vega-s95" (Meson gxbb) - "tronsmart,vega-s95-telos", "tronsmart,vega-s95" (Meson gxbb) + - "hardkernel,odroid-c2" (Meson gxbb) + - "amlogic,p200" (Meson gxbb) + - "amlogic,p201" (Meson gxbb) -- GitLab From 855960342d1e777e5d1ff37a9ca8b4f22a7d53b4 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 24 Mar 2016 11:05:14 -0700 Subject: [PATCH 0802/9938] ARM64: dts: amlogic: add Hardkernel ODROID-C2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add minimal DT files for the Hardkernel ODROID-C2 board based on the Amlogic S905/GXBB SoC. Used the other gxbb boards from Andreas Färber as a starting point. Cc: Andreas Färber Cc: Carlo Caione Signed-off-by: Kevin Hilman Reviewed-by: Andreas Färber Acked-by: Arnd Bergmann --- arch/arm64/boot/dts/amlogic/Makefile | 1 + .../boot/dts/amlogic/meson-gxbb-odroidc2.dts | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index eb672f38f89e..a595752459e8 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -1,3 +1,4 @@ +dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts new file mode 100644 index 000000000000..7f2c6747a71e --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 Andreas Färber + * Copyright (c) 2016 BayLibre, Inc. + * Author: Kevin Hilman + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "meson-gxbb.dtsi" + +/ { + compatible = "hardkernel,odroid-c2", "amlogic,meson-gxbb"; + model = "Hardkernel ODROID-C2"; + + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; +}; + +&uart_AO { + status = "okay"; +}; -- GitLab From ac40004db3fbea89c50083c6f9015ac7061e77b4 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 24 Mar 2016 11:05:15 -0700 Subject: [PATCH 0803/9938] ARM64: dts: amlogic: Add P200/P201 boards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add minimal DT files for the Amlogic P20x development boards, based on the Amlogic S905/GXBB SoC. Cc: Andreas Färber Cc: Carlo Caione Signed-off-by: Kevin Hilman Reviewed-by: Andreas Färber Acked-by: Arnd Bergmann --- arch/arm64/boot/dts/amlogic/Makefile | 2 + .../boot/dts/amlogic/meson-gxbb-p200.dts | 52 +++++++++++++++ .../boot/dts/amlogic/meson-gxbb-p201.dts | 52 +++++++++++++++ .../boot/dts/amlogic/meson-gxbb-p20x.dtsi | 65 +++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index a595752459e8..47ec703cb230 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -1,4 +1,6 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p200.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts new file mode 100644 index 000000000000..62979076e250 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Andreas Färber + * Copyright (c) 2016 BayLibre, Inc. + * Author: Kevin Hilman + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "meson-gxbb-p20x.dtsi" + +/ { + compatible = "amlogic,p200", "amlogic,meson-gxbb"; + model = "Amlogic Meson GXBB P200 Development Board"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts new file mode 100644 index 000000000000..39bb037a3e47 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Andreas Färber + * Copyright (c) 2016 BayLibre, Inc. + * Author: Kevin Hilman + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "meson-gxbb-p20x.dtsi" + +/ { + compatible = "amlogic,p201", "amlogic,meson-gxbb"; + model = "Amlogic Meson GXBB P201 Development Board"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi new file mode 100644 index 000000000000..bf7ff1d41851 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016 Andreas Färber + * Copyright (c) 2016 BayLibre, Inc. + * Author: Kevin Hilman + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "meson-gxbb.dtsi" + +/ { + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x40000000>; + }; +}; + +/* This UART is brought out to the DB9 connector */ +&uart_AO { + status = "okay"; +}; -- GitLab From 3fcdfc9dad07c2a6ea19dfb98a2151cd86d06c6a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 30 Mar 2016 11:02:49 -0700 Subject: [PATCH 0804/9938] ASoC: wm8960: Depends on I2C Now that this is directly user selectable it needs to care about its dependencies. Reported-by: kbuild test robot Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 196101b2eab5..3ebf29bc87d3 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -910,6 +910,7 @@ config SND_SOC_WM8955 config SND_SOC_WM8960 tristate "Wolfson Microelectronics WM8960 CODEC" + depends on I2C config SND_SOC_WM8961 tristate -- GitLab From a2151374230820a3a6e654f2998b2a44dbfae4e1 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 30 Mar 2016 17:09:13 +0100 Subject: [PATCH 0805/9938] regulator: Fix deadlock during regulator registration Commit 5e3ca2b349b1 ("regulator: Try to resolve regulators supplies on registration") added a call to regulator_resolve_supply() within regulator_register() where the regulator_list_mutex is held. This causes a deadlock to occur on the Tegra114 Dalmore board when the palmas PMIC is registered because regulator_register_resolve_supply() calls regulator_dev_lookup() which may try to acquire the regulator_list_mutex again. Fix this by releasing the mutex before calling regulator_register_resolve_supply() and update the error exit path to ensure the mutex is released on an error. [Made commit message more legible -- broonie] Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- drivers/regulator/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ab1838138877..fd0e4e37f4e1 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3991,12 +3991,11 @@ regulator_register(const struct regulator_desc *regulator_desc, } rdev_init_debugfs(rdev); + mutex_unlock(®ulator_list_mutex); /* try to resolve regulators supply since a new one was registered */ class_for_each_device(®ulator_class, NULL, NULL, regulator_register_resolve_supply); -out: - mutex_unlock(®ulator_list_mutex); kfree(config); return rdev; @@ -4007,15 +4006,16 @@ regulator_register(const struct regulator_desc *regulator_desc, regulator_ena_gpio_free(rdev); device_unregister(&rdev->dev); /* device core frees rdev */ - rdev = ERR_PTR(ret); goto out; wash: regulator_ena_gpio_free(rdev); clean: kfree(rdev); - rdev = ERR_PTR(ret); - goto out; +out: + mutex_unlock(®ulator_list_mutex); + kfree(config); + return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(regulator_register); -- GitLab From 6a0028b3dd67b86d7265ed873c8738743adec855 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 30 Mar 2016 12:04:30 -0700 Subject: [PATCH 0806/9938] regulator: Deprecate regulator_can_change_voltage() All current users of regulator_can_change_voltage() are abusing it, using it to wrap a call to regulator_set_voltage() on probe without any alternative handling for fixed voltages. Drivers should only be using regulator_set_voltage() if they need to vary voltages at runtime, fixed voltages should normally be set via machine constraints, and calling regulator_set_voltage() on a regulator which can't be varied will succeed if the current voltage is within the range requested so users shouldn't worry if they have permission to vary normally. Deprecate the API to try to stop any new users appearing while we fix the current callers. Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 48603506f8de..80dc4e51d14a 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -224,7 +224,7 @@ int regulator_bulk_force_disable(int num_consumers, void regulator_bulk_free(int num_consumers, struct regulator_bulk_data *consumers); -int regulator_can_change_voltage(struct regulator *regulator); +int __deprecated regulator_can_change_voltage(struct regulator *regulator); int regulator_count_voltages(struct regulator *regulator); int regulator_list_voltage(struct regulator *regulator, unsigned selector); int regulator_is_supported_voltage(struct regulator *regulator, @@ -436,7 +436,7 @@ static inline void regulator_bulk_free(int num_consumers, { } -static inline int regulator_can_change_voltage(struct regulator *regulator) +static inline int __deprecated regulator_can_change_voltage(struct regulator *regulator) { return 0; } -- GitLab From 5482cefaca89995c75f2ad507dd7810b0b1079c5 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 21 Jan 2016 18:35:13 +0000 Subject: [PATCH 0807/9938] MAINTAINERS: add qcom i2c and spi drivers to list This patch adds i2c-qup and spi-qup drivers in to the qualcomm maintainer list, so that get maintainers scripts can get correct people to send patch to. Signed-off-by: Srinivas Kandagatla Acked-by: Ivan T. Ivanov Signed-off-by: Andy Gross --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..fcbd452ab62b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1470,7 +1470,9 @@ F: arch/arm/boot/dts/qcom-*.dts F: arch/arm/boot/dts/qcom-*.dtsi F: arch/arm/mach-qcom/ F: arch/arm64/boot/dts/qcom/* +F: drivers/i2c/busses/i2c-qup.c F: drivers/soc/qcom/ +F: drivers/spi/spi-qup.c F: drivers/tty/serial/msm_serial.h F: drivers/tty/serial/msm_serial.c F: drivers/*/pm8???-* -- GitLab From 39a3366a31386eb58f6e5857cd49cebad3253ab8 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 22 Feb 2016 11:55:26 +0000 Subject: [PATCH 0808/9938] MAINTAINERS: add qcom clocks to the maintainers list This patch adds qcom clock drivers to the QCOM/MSM support list so that get_maintainer.pl can pick up correct cc list. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index fcbd452ab62b..ce1769341475 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1471,6 +1471,7 @@ F: arch/arm/boot/dts/qcom-*.dtsi F: arch/arm/mach-qcom/ F: arch/arm64/boot/dts/qcom/* F: drivers/i2c/busses/i2c-qup.c +F: drivers/clk/qcom/ F: drivers/soc/qcom/ F: drivers/spi/spi-qup.c F: drivers/tty/serial/msm_serial.h -- GitLab From e8b123e6008480b2b8d80dae060315d84b79f4bb Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 24 Dec 2015 00:28:38 -0800 Subject: [PATCH 0809/9938] soc: qcom: smem_state: Add stubs for disabled smem_state Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- include/linux/soc/qcom/smem_state.h | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/include/linux/soc/qcom/smem_state.h b/include/linux/soc/qcom/smem_state.h index f35e1512fcaa..7b88697929e9 100644 --- a/include/linux/soc/qcom/smem_state.h +++ b/include/linux/soc/qcom/smem_state.h @@ -1,12 +1,17 @@ #ifndef __QCOM_SMEM_STATE__ #define __QCOM_SMEM_STATE__ +#include + +struct device_node; struct qcom_smem_state; struct qcom_smem_state_ops { int (*update_bits)(void *, u32, u32); }; +#ifdef CONFIG_QCOM_SMEM_STATE + struct qcom_smem_state *qcom_smem_state_get(struct device *dev, const char *con_id, unsigned *bit); void qcom_smem_state_put(struct qcom_smem_state *); @@ -15,4 +20,34 @@ int qcom_smem_state_update_bits(struct qcom_smem_state *state, u32 mask, u32 val struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node, const struct qcom_smem_state_ops *ops, void *data); void qcom_smem_state_unregister(struct qcom_smem_state *state); +#else + +static inline struct qcom_smem_state *qcom_smem_state_get(struct device *dev, + const char *con_id, unsigned *bit) +{ + return ERR_PTR(-EINVAL); +} + +static inline void qcom_smem_state_put(struct qcom_smem_state *state) +{ +} + +static inline int qcom_smem_state_update_bits(struct qcom_smem_state *state, + u32 mask, u32 value) +{ + return -EINVAL; +} + +static inline struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node, + const struct qcom_smem_state_ops *ops, void *data) +{ + return ERR_PTR(-EINVAL); +} + +static inline void qcom_smem_state_unregister(struct qcom_smem_state *state) +{ +} + +#endif + #endif -- GitLab From 3b904b046c7adfbadb124851c7a23276f7187ddb Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Mon, 4 Jan 2016 10:58:28 -0700 Subject: [PATCH 0810/9938] drivers: qcom: spm: avoid module usage in non-modular SPM driver SPM driver provides cpuidle support on some QC SoC's. The functionality is non-modular and there is no need for module support. Convert module platform init to builtin platform driver init. The driver functionality is not affected by this change. Cc: Paul Gortmaker Signed-off-by: Lina Iyer Acked-by: Daniel Lezcano Signed-off-by: Andy Gross --- drivers/soc/qcom/spm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index 5548a31e1a39..f324451e0940 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -2,6 +2,8 @@ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. * Copyright (c) 2014,2015, Linaro Ltd. * + * SAW power controller driver + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. @@ -12,7 +14,6 @@ * GNU General Public License for more details. */ -#include #include #include #include @@ -378,8 +379,5 @@ static struct platform_driver spm_driver = { .of_match_table = spm_match_table, }, }; -module_platform_driver(spm_driver); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("SAW power controller driver"); -MODULE_ALIAS("platform:saw"); +builtin_platform_driver(spm_driver); -- GitLab From 39f0db298e7c02a29371fb39cabdd5d76e6b726c Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 17 Feb 2016 22:39:02 -0800 Subject: [PATCH 0811/9938] soc: qcom: smd: Introduce callback setter Introduce a setter for the callback function pointer to clarify the locking around the operation and to reduce some duplication. Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 25 +++++++++++++++++-------- include/linux/soc/qcom/smd.h | 4 +++- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index 498fd0581a45..c357842b92e1 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -186,7 +186,7 @@ struct qcom_smd_channel { int fifo_size; void *bounce_buffer; - int (*cb)(struct qcom_smd_device *, const void *, size_t); + qcom_smd_cb_t cb; spinlock_t recv_lock; @@ -377,6 +377,19 @@ static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) channel->pkt_size = 0; } +/* + * Set the callback for a channel, with appropriate locking + */ +static void qcom_smd_channel_set_callback(struct qcom_smd_channel *channel, + qcom_smd_cb_t cb) +{ + unsigned long flags; + + spin_lock_irqsave(&channel->recv_lock, flags); + channel->cb = cb; + spin_unlock_irqrestore(&channel->recv_lock, flags); +}; + /* * Calculate the amount of data available in the rx fifo */ @@ -814,8 +827,7 @@ static int qcom_smd_dev_probe(struct device *dev) if (!channel->bounce_buffer) return -ENOMEM; - channel->cb = qsdrv->callback; - + qcom_smd_channel_set_callback(channel, qsdrv->callback); qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING); qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED); @@ -831,7 +843,7 @@ static int qcom_smd_dev_probe(struct device *dev) err: dev_err(&qsdev->dev, "probe failed\n"); - channel->cb = NULL; + qcom_smd_channel_set_callback(channel, NULL); kfree(channel->bounce_buffer); channel->bounce_buffer = NULL; @@ -850,16 +862,13 @@ static int qcom_smd_dev_remove(struct device *dev) struct qcom_smd_device *qsdev = to_smd_device(dev); struct qcom_smd_driver *qsdrv = to_smd_driver(dev); struct qcom_smd_channel *channel = qsdev->channel; - unsigned long flags; qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSING); /* * Make sure we don't race with the code receiving data. */ - spin_lock_irqsave(&channel->recv_lock, flags); - channel->cb = NULL; - spin_unlock_irqrestore(&channel->recv_lock, flags); + qcom_smd_channel_set_callback(channel, NULL); /* Wake up any sleepers in qcom_smd_send() */ wake_up_interruptible(&channel->fblockread_event); diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h index d0cb6d189a0a..65a64fcdb1aa 100644 --- a/include/linux/soc/qcom/smd.h +++ b/include/linux/soc/qcom/smd.h @@ -26,6 +26,8 @@ struct qcom_smd_device { struct qcom_smd_channel *channel; }; +typedef int (*qcom_smd_cb_t)(struct qcom_smd_device *, const void *, size_t); + /** * struct qcom_smd_driver - smd driver struct * @driver: underlying device driver @@ -42,7 +44,7 @@ struct qcom_smd_driver { int (*probe)(struct qcom_smd_device *dev); void (*remove)(struct qcom_smd_device *dev); - int (*callback)(struct qcom_smd_device *, const void *, size_t); + qcom_smd_cb_t callback; }; int qcom_smd_driver_register(struct qcom_smd_driver *drv); -- GitLab From 995b170aeaef4afe0c3469d14b9c80ff2e8a98d7 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 17 Feb 2016 22:39:03 -0800 Subject: [PATCH 0812/9938] soc: qcom: smd: Split discovery and state change work Split the two steps of channel discovery and state change handling into two different workers. This allows for new channels to be found while we're are probing, which is required as we introduce multi-channel support. Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 58 ++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index c357842b92e1..e8972ddfee85 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -106,9 +106,9 @@ static const struct { * @channels: list of all channels detected on this edge * @channels_lock: guard for modifications of @channels * @allocated: array of bitmaps representing already allocated channels - * @need_rescan: flag that the @work needs to scan smem for new channels * @smem_available: last available amount of smem triggering a channel scan - * @work: work item for edge house keeping + * @scan_work: work item for discovering new channels + * @state_work: work item for edge state changes */ struct qcom_smd_edge { struct qcom_smd *smd; @@ -127,10 +127,10 @@ struct qcom_smd_edge { DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE); - bool need_rescan; unsigned smem_available; - struct work_struct work; + struct work_struct scan_work; + struct work_struct state_work; }; /* @@ -614,7 +614,8 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data) struct qcom_smd_edge *edge = data; struct qcom_smd_channel *channel; unsigned available; - bool kick_worker = false; + bool kick_scanner = false; + bool kick_state = false; /* * Handle state changes or data on each of the channels on this edge @@ -622,7 +623,7 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data) spin_lock(&edge->channels_lock); list_for_each_entry(channel, &edge->channels, list) { spin_lock(&channel->recv_lock); - kick_worker |= qcom_smd_channel_intr(channel); + kick_state |= qcom_smd_channel_intr(channel); spin_unlock(&channel->recv_lock); } spin_unlock(&edge->channels_lock); @@ -635,12 +636,13 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data) available = qcom_smem_get_free_space(edge->remote_pid); if (available != edge->smem_available) { edge->smem_available = available; - edge->need_rescan = true; - kick_worker = true; + kick_scanner = true; } - if (kick_worker) - schedule_work(&edge->work); + if (kick_scanner) + schedule_work(&edge->scan_work); + if (kick_state) + schedule_work(&edge->state_work); return IRQ_HANDLED; } @@ -1098,8 +1100,9 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed * qcom_smd_create_channel() to create representations of these and add * them to the edge's list of channels. */ -static void qcom_discover_channels(struct qcom_smd_edge *edge) +static void qcom_channel_scan_worker(struct work_struct *work) { + struct qcom_smd_edge *edge = container_of(work, struct qcom_smd_edge, scan_work); struct qcom_smd_alloc_entry *alloc_tbl; struct qcom_smd_alloc_entry *entry; struct qcom_smd_channel *channel; @@ -1152,7 +1155,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge) } } - schedule_work(&edge->work); + schedule_work(&edge->state_work); } /* @@ -1160,29 +1163,23 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge) * then scans all registered channels for state changes that should be handled * by creating or destroying smd client devices for the registered channels. * - * LOCKING: edge->channels_lock is not needed to be held during the traversal - * of the channels list as it's done synchronously with the only writer. + * LOCKING: edge->channels_lock only needs to cover the list operations, as the + * worker is killed before any channels are deallocated */ static void qcom_channel_state_worker(struct work_struct *work) { struct qcom_smd_channel *channel; struct qcom_smd_edge *edge = container_of(work, struct qcom_smd_edge, - work); + state_work); unsigned remote_state; - - /* - * Rescan smem if we have reason to belive that there are new channels. - */ - if (edge->need_rescan) { - edge->need_rescan = false; - qcom_discover_channels(edge); - } + unsigned long flags; /* * Register a device for any closed channel where the remote processor * is showing interest in opening the channel. */ + spin_lock_irqsave(&edge->channels_lock, flags); list_for_each_entry(channel, &edge->channels, list) { if (channel->state != SMD_CHANNEL_CLOSED) continue; @@ -1192,7 +1189,9 @@ static void qcom_channel_state_worker(struct work_struct *work) remote_state != SMD_CHANNEL_OPENED) continue; + spin_unlock_irqrestore(&edge->channels_lock, flags); qcom_smd_create_device(channel); + spin_lock_irqsave(&edge->channels_lock, flags); } /* @@ -1209,8 +1208,11 @@ static void qcom_channel_state_worker(struct work_struct *work) remote_state == SMD_CHANNEL_OPENED) continue; + spin_unlock_irqrestore(&edge->channels_lock, flags); qcom_smd_destroy_device(channel); + spin_lock_irqsave(&edge->channels_lock, flags); } + spin_unlock_irqrestore(&edge->channels_lock, flags); } /* @@ -1228,7 +1230,8 @@ static int qcom_smd_parse_edge(struct device *dev, INIT_LIST_HEAD(&edge->channels); spin_lock_init(&edge->channels_lock); - INIT_WORK(&edge->work, qcom_channel_state_worker); + INIT_WORK(&edge->scan_work, qcom_channel_scan_worker); + INIT_WORK(&edge->state_work, qcom_channel_state_worker); edge->of_node = of_node_get(node); @@ -1317,8 +1320,7 @@ static int qcom_smd_probe(struct platform_device *pdev) if (ret) continue; - edge->need_rescan = true; - schedule_work(&edge->work); + schedule_work(&edge->scan_work); } platform_set_drvdata(pdev, smd); @@ -1341,8 +1343,10 @@ static int qcom_smd_remove(struct platform_device *pdev) edge = &smd->edges[i]; disable_irq(edge->irq); - cancel_work_sync(&edge->work); + cancel_work_sync(&edge->scan_work); + cancel_work_sync(&edge->state_work); + /* No need to lock here, because the writer is gone */ list_for_each_entry(channel, &edge->channels, list) { if (!channel->qsdev) continue; -- GitLab From 3fd3f2fd86478614fecbe261b201779b4fc6abd2 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 17 Feb 2016 22:39:04 -0800 Subject: [PATCH 0813/9938] soc: qcom: smd: Refactor channel open and close handling Refactor opening and closing of channels into two separate functions instead of open coding this in the various places. Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 62 +++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index e8972ddfee85..d253e5cc233f 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -808,18 +808,12 @@ static int qcom_smd_dev_match(struct device *dev, struct device_driver *drv) } /* - * Probe the smd client. - * - * The remote side have indicated that it want the channel to be opened, so - * complete the state handshake and probe our client driver. + * Helper for opening a channel */ -static int qcom_smd_dev_probe(struct device *dev) +static int qcom_smd_channel_open(struct qcom_smd_channel *channel, + qcom_smd_cb_t cb) { - struct qcom_smd_device *qsdev = to_smd_device(dev); - struct qcom_smd_driver *qsdrv = to_smd_driver(dev); - struct qcom_smd_channel *channel = qsdev->channel; size_t bb_size; - int ret; /* * Packets are maximum 4k, but reduce if the fifo is smaller @@ -829,11 +823,44 @@ static int qcom_smd_dev_probe(struct device *dev) if (!channel->bounce_buffer) return -ENOMEM; - qcom_smd_channel_set_callback(channel, qsdrv->callback); + qcom_smd_channel_set_callback(channel, cb); qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING); - qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED); + return 0; +} + +/* + * Helper for closing and resetting a channel + */ +static void qcom_smd_channel_close(struct qcom_smd_channel *channel) +{ + qcom_smd_channel_set_callback(channel, NULL); + + kfree(channel->bounce_buffer); + channel->bounce_buffer = NULL; + + qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED); + qcom_smd_channel_reset(channel); +} + +/* + * Probe the smd client. + * + * The remote side have indicated that it want the channel to be opened, so + * complete the state handshake and probe our client driver. + */ +static int qcom_smd_dev_probe(struct device *dev) +{ + struct qcom_smd_device *qsdev = to_smd_device(dev); + struct qcom_smd_driver *qsdrv = to_smd_driver(dev); + struct qcom_smd_channel *channel = qsdev->channel; + int ret; + + ret = qcom_smd_channel_open(channel, qsdrv->callback); + if (ret) + return ret; + ret = qsdrv->probe(qsdev); if (ret) goto err; @@ -845,11 +872,7 @@ static int qcom_smd_dev_probe(struct device *dev) err: dev_err(&qsdev->dev, "probe failed\n"); - qcom_smd_channel_set_callback(channel, NULL); - kfree(channel->bounce_buffer); - channel->bounce_buffer = NULL; - - qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED); + qcom_smd_channel_close(channel); return ret; } @@ -886,12 +909,7 @@ static int qcom_smd_dev_remove(struct device *dev) * The client is now gone, cleanup and reset the channel state. */ channel->qsdev = NULL; - kfree(channel->bounce_buffer); - channel->bounce_buffer = NULL; - - qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED); - - qcom_smd_channel_reset(channel); + qcom_smd_channel_close(channel); return 0; } -- GitLab From d5933855c0eb0a4103cf5db784cfdd4d7a85cd56 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 17 Feb 2016 22:39:05 -0800 Subject: [PATCH 0814/9938] soc: qcom: smd: Support multiple channels per sdev This patch allows chaining additional channels to a SMD device, enabling implementation of multi-channel SMD devies - like Bluetooth. Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index d253e5cc233f..c3fa0fd724f7 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -193,6 +193,7 @@ struct qcom_smd_channel { int pkt_size; struct list_head list; + struct list_head dev_list; }; /** @@ -887,6 +888,8 @@ static int qcom_smd_dev_remove(struct device *dev) struct qcom_smd_device *qsdev = to_smd_device(dev); struct qcom_smd_driver *qsdrv = to_smd_driver(dev); struct qcom_smd_channel *channel = qsdev->channel; + struct qcom_smd_channel *tmp; + struct qcom_smd_channel *ch; qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSING); @@ -906,10 +909,14 @@ static int qcom_smd_dev_remove(struct device *dev) qsdrv->remove(qsdev); /* - * The client is now gone, cleanup and reset the channel state. + * The client is now gone, close and release all channels associated + * with this sdev */ - channel->qsdev = NULL; - qcom_smd_channel_close(channel); + list_for_each_entry_safe(ch, tmp, &channel->dev_list, dev_list) { + qcom_smd_channel_close(ch); + list_del(&ch->dev_list); + ch->qsdev = NULL; + } return 0; } @@ -1056,6 +1063,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed if (!channel) return ERR_PTR(-ENOMEM); + INIT_LIST_HEAD(&channel->dev_list); channel->edge = edge; channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL); if (!channel->name) -- GitLab From 028021d29ea069390e1f60c6aa5b3511d218454b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 17 Feb 2016 22:39:06 -0800 Subject: [PATCH 0815/9938] soc: qcom: smd: Support opening additional channels With the qcom_smd_open_channel() API we allow SMD devices to open additional SMD channels, to allow implementation of multi-channel SMD devices - like Bluetooth. Channels are opened from the same edge as the calling SMD device is tied to. Signed-off-by: Bjorn Andersson Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 76 ++++++++++++++++++++++++++++++++++++ include/linux/soc/qcom/smd.h | 4 ++ 2 files changed, 80 insertions(+) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index c3fa0fd724f7..b6434c4be86a 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -129,6 +129,8 @@ struct qcom_smd_edge { unsigned smem_available; + wait_queue_head_t new_channel_event; + struct work_struct scan_work; struct work_struct state_work; }; @@ -1042,6 +1044,77 @@ void qcom_smd_driver_unregister(struct qcom_smd_driver *qsdrv) } EXPORT_SYMBOL(qcom_smd_driver_unregister); +static struct qcom_smd_channel * +qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name) +{ + struct qcom_smd_channel *channel; + struct qcom_smd_channel *ret = NULL; + unsigned long flags; + unsigned state; + + spin_lock_irqsave(&edge->channels_lock, flags); + list_for_each_entry(channel, &edge->channels, list) { + if (strcmp(channel->name, name)) + continue; + + state = GET_RX_CHANNEL_INFO(channel, state); + if (state != SMD_CHANNEL_OPENING && + state != SMD_CHANNEL_OPENED) + continue; + + ret = channel; + break; + } + spin_unlock_irqrestore(&edge->channels_lock, flags); + + return ret; +} + +/** + * qcom_smd_open_channel() - claim additional channels on the same edge + * @sdev: smd_device handle + * @name: channel name + * @cb: callback method to use for incoming data + * + * Returns a channel handle on success, or -EPROBE_DEFER if the channel isn't + * ready. + */ +struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_device *sdev, + const char *name, + qcom_smd_cb_t cb) +{ + struct qcom_smd_channel *channel; + struct qcom_smd_edge *edge = sdev->channel->edge; + int ret; + + /* Wait up to HZ for the channel to appear */ + ret = wait_event_interruptible_timeout(edge->new_channel_event, + (channel = qcom_smd_find_channel(edge, name)) != NULL, + HZ); + if (!ret) + return ERR_PTR(-ETIMEDOUT); + + if (channel->state != SMD_CHANNEL_CLOSED) { + dev_err(&sdev->dev, "channel %s is busy\n", channel->name); + return ERR_PTR(-EBUSY); + } + + channel->qsdev = sdev; + ret = qcom_smd_channel_open(channel, cb); + if (ret) { + channel->qsdev = NULL; + return ERR_PTR(ret); + } + + /* + * Append the list of channel to the channels associated with the sdev + */ + list_add_tail(&channel->dev_list, &sdev->channel->dev_list); + + return channel; +} +EXPORT_SYMBOL(qcom_smd_open_channel); + /* * Allocate the qcom_smd_channel object for a newly found smd channel, * retrieving and validating the smem items involved. @@ -1178,6 +1251,8 @@ static void qcom_channel_scan_worker(struct work_struct *work) dev_dbg(smd->dev, "new channel found: '%s'\n", channel->name); set_bit(i, edge->allocated[tbl]); + + wake_up_interruptible(&edge->new_channel_event); } } @@ -1341,6 +1416,7 @@ static int qcom_smd_probe(struct platform_device *pdev) for_each_available_child_of_node(pdev->dev.of_node, node) { edge = &smd->edges[i++]; edge->smd = smd; + init_waitqueue_head(&edge->new_channel_event); ret = qcom_smd_parse_edge(&pdev->dev, node, edge); if (ret) diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h index 65a64fcdb1aa..bd51c8a9d807 100644 --- a/include/linux/soc/qcom/smd.h +++ b/include/linux/soc/qcom/smd.h @@ -56,4 +56,8 @@ void qcom_smd_driver_unregister(struct qcom_smd_driver *drv); int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len); +struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_device *sdev, + const char *name, + qcom_smd_cb_t cb); + #endif -- GitLab From f17131a93f43665a76ae1f6aebdbb3e41674137c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 29 Mar 2016 09:45:00 -0700 Subject: [PATCH 0816/9938] ASoC: intel: add function stub when ACPI is not enabled Add function stub for "sst_acpi_find_name_from_hid()" when CONFIG_ACPI is not enabled so that the driver will build successfully. This fixes the following build errors: (loadable module) ERROR: "sst_acpi_find_name_from_hid" [sound/soc/intel/boards/snd-soc-sst-bytcr-rt5640.ko] undefined! (or built-in) bytcr_rt5640.c:(.text+0x26fc52): undefined reference to `sst_acpi_find_name_from_hid' Reported-by: Borislav Petkov Signed-off-by: Randy Dunlap Signed-off-by: Mark Brown --- sound/soc/intel/common/sst-acpi.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h index 4dcfb7e5ed70..8398cb227ba9 100644 --- a/sound/soc/intel/common/sst-acpi.h +++ b/sound/soc/intel/common/sst-acpi.h @@ -12,10 +12,19 @@ * */ +#include +#include #include /* translation fron HID to I2C name, needed for DAI codec_name */ +#if IS_ENABLED(CONFIG_ACPI) const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]); +#else +inline const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]) +{ + return NULL; +} +#endif /* acpi match */ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines); -- GitLab From 92eb4f62cbac0211e43ee4a6715ee2ea43167e88 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Fri, 11 Mar 2016 10:12:56 +0530 Subject: [PATCH 0817/9938] ASoC: Intel: Bxtn: Add Broxton DSP support Broxton DSP is mostly similar to Skylake one but with subtle differences like no Code Load DMA and uses HDA DMA for code loading, DSP D0 and D3 sequences are different. These changes are comprehended by adding different DSP power up and down handlers, and new loader ops and also adding prepare and trigger which HDA DSP DMA requires Signed-off-by: Jeeja KP Signed-off-by: Jayachandran B Signed-off-by: GuruprasadX Pawse Signed-off-by: Kranthi G Signed-off-by: Dharageswari R Signed-off-by: Ramesh Babu Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 1 + sound/soc/intel/skylake/Makefile | 2 +- sound/soc/intel/skylake/bxt-sst.c | 328 +++++++++++++++++++++++++ sound/soc/intel/skylake/skl-messages.c | 120 +++++++++ sound/soc/intel/skylake/skl-sst-dsp.h | 13 + 5 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/skylake/bxt-sst.c diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index b3e6c2300457..5a94f74d31dd 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -162,6 +162,7 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH config SND_SOC_INTEL_SKYLAKE tristate select SND_HDA_EXT_CORE + select SND_HDA_DSP_LOADER select SND_SOC_TOPOLOGY select SND_HDA_I915 select SND_SOC_INTEL_SST diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 914b6dab9bea..c28f5d0e1d99 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -5,6 +5,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o # Skylake IPC Support snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ - skl-sst.o + skl-sst.o bxt-sst.o obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c new file mode 100644 index 000000000000..965ce40ce752 --- /dev/null +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -0,0 +1,328 @@ +/* + * bxt-sst.c - DSP library functions for BXT platform + * + * Copyright (C) 2015-16 Intel Corp + * Author:Rafal Redzimski + * Jeeja KP + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include + +#include "../common/sst-dsp.h" +#include "../common/sst-dsp-priv.h" +#include "skl-sst-ipc.h" + +#define BXT_BASEFW_TIMEOUT 3000 +#define BXT_INIT_TIMEOUT 500 +#define BXT_IPC_PURGE_FW 0x01004000 + +#define BXT_ROM_INIT 0x5 +#define BXT_ADSP_SRAM0_BASE 0x80000 + +/* Firmware status window */ +#define BXT_ADSP_FW_STATUS BXT_ADSP_SRAM0_BASE +#define BXT_ADSP_ERROR_CODE (BXT_ADSP_FW_STATUS + 0x4) + +#define BXT_ADSP_SRAM1_BASE 0xA0000 + +static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); +} + +static int sst_bxt_prepare_fw(struct sst_dsp *ctx, + const void *fwdata, u32 fwsize) +{ + int stream_tag, ret, i; + u32 reg; + + stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); + if (stream_tag < 0) { + dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n", + stream_tag); + return stream_tag; + } + + ctx->dsp_ops.stream_tag = stream_tag; + memcpy(ctx->dmab.area, fwdata, fwsize); + + /* Purge FW request */ + sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | + BXT_IPC_PURGE_FW | (stream_tag - 1)); + + ret = skl_dsp_enable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); + ret = -EIO; + goto base_fw_load_failed; + } + + for (i = BXT_INIT_TIMEOUT; i > 0; --i) { + reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); + + if (reg & SKL_ADSP_REG_HIPCIE_DONE) { + sst_dsp_shim_update_bits_forced(ctx, + SKL_ADSP_REG_HIPCIE, + SKL_ADSP_REG_HIPCIE_DONE, + SKL_ADSP_REG_HIPCIE_DONE); + break; + } + mdelay(1); + } + if (!i) { + dev_info(ctx->dev, "Waiting for HIPCIE done, reg: 0x%x\n", reg); + sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCIE, + SKL_ADSP_REG_HIPCIE_DONE, + SKL_ADSP_REG_HIPCIE_DONE); + } + + /* enable Interrupt */ + skl_ipc_int_enable(ctx); + skl_ipc_op_int_enable(ctx); + + for (i = BXT_INIT_TIMEOUT; i > 0; --i) { + if (SKL_FW_INIT == + (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & + SKL_FW_STS_MASK)) { + + dev_info(ctx->dev, "ROM loaded, continue FW loading\n"); + break; + } + mdelay(1); + } + if (!i) { + dev_err(ctx->dev, "Timeout for ROM init, HIPCIE: 0x%x\n", reg); + ret = -EIO; + goto base_fw_load_failed; + } + + return ret; + +base_fw_load_failed: + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); + skl_dsp_disable_core(ctx); + return ret; +} + +static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) +{ + int ret; + + ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); + ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, + BXT_ROM_INIT, BXT_BASEFW_TIMEOUT, "Firmware boot"); + + ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); + + return ret; +} + +static int bxt_load_base_firmware(struct sst_dsp *ctx) +{ + const struct firmware *fw = NULL; + struct skl_sst *skl = ctx->thread_context; + int ret; + + ret = request_firmware(&fw, ctx->fw_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "Request firmware failed %d\n", ret); + goto sst_load_base_firmware_failed; + } + + ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); + /* Retry Enabling core and ROM load. Retry seemed to help */ + if (ret < 0) { + ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); + if (ret < 0) { + dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); + goto sst_load_base_firmware_failed; + } + } + + ret = sst_transfer_fw_host_dma(ctx); + if (ret < 0) { + dev_err(ctx->dev, "Transfer firmware failed %d\n", ret); + dev_info(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), + sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); + + skl_dsp_disable_core(ctx); + } else { + dev_dbg(ctx->dev, "Firmware download successful\n"); + ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); + skl_dsp_disable_core(ctx); + ret = -EIO; + } else { + skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + ret = 0; + } + } + +sst_load_base_firmware_failed: + release_firmware(fw); + return ret; +} + +static int bxt_set_dsp_D0(struct sst_dsp *ctx) +{ + struct skl_sst *skl = ctx->thread_context; + int ret; + + skl->boot_complete = false; + + ret = skl_dsp_enable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret); + return ret; + } + + /* enable interrupt */ + skl_ipc_int_enable(ctx); + skl_ipc_op_int_enable(ctx); + + ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "ipc: error DSP boot timeout\n"); + dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), + sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); + return -EIO; + } + + skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + return 0; +} + +static int bxt_set_dsp_D3(struct sst_dsp *ctx) +{ + struct skl_ipc_dxstate_info dx; + struct skl_sst *skl = ctx->thread_context; + int ret = 0; + + if (!is_skl_dsp_running(ctx)) + return ret; + + dx.core_mask = SKL_DSP_CORE0_MASK; + dx.dx_mask = SKL_IPC_D3_MASK; + + ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, + SKL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "Failed to set DSP to D3 state: %d\n", ret); + return ret; + } + + ret = skl_dsp_disable_core(ctx); + if (ret < 0) { + dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret); + ret = -EIO; + } + + skl_dsp_set_state_locked(ctx, SKL_DSP_RESET); + return 0; +} + +static struct skl_dsp_fw_ops bxt_fw_ops = { + .set_state_D0 = bxt_set_dsp_D0, + .set_state_D3 = bxt_set_dsp_D3, + .load_fw = bxt_load_base_firmware, + .get_fw_errcode = bxt_get_errorcode, +}; + +static struct sst_ops skl_ops = { + .irq_handler = skl_dsp_sst_interrupt, + .write = sst_shim32_write, + .read = sst_shim32_read, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .free = skl_dsp_free, +}; + +static struct sst_dsp_device skl_dev = { + .thread = skl_dsp_irq_thread_handler, + .ops = &skl_ops, +}; + +int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp) +{ + struct skl_sst *skl; + struct sst_dsp *sst; + int ret; + + skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); + if (skl == NULL) + return -ENOMEM; + + skl->dev = dev; + skl_dev.thread_context = skl; + + skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); + if (!skl->dsp) { + dev_err(skl->dev, "skl_dsp_ctx_init failed\n"); + return -ENODEV; + } + + sst = skl->dsp; + sst->fw_name = fw_name; + sst->dsp_ops = dsp_ops; + sst->fw_ops = bxt_fw_ops; + sst->addr.lpe = mmio_base; + sst->addr.shim = mmio_base; + + sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), + SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); + + ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + + skl->boot_complete = false; + init_waitqueue_head(&skl->boot_wait); + + ret = sst->fw_ops.load_fw(sst); + if (ret < 0) { + dev_err(dev, "Load base fw failed: %x", ret); + return ret; + } + + if (dsp) + *dsp = skl; + + return 0; +} +EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); + + +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +{ + skl_ipc_free(&ctx->ipc); + ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); + + if (ctx->dsp->addr.lpe) + iounmap(ctx->dsp->addr.lpe); + + ctx->dsp->ops->free(ctx->dsp); +} +EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Broxton IPC driver"); diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 79c5089b85d6..e3d149c68bbf 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -72,6 +72,105 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); } +static int skl_dsp_setup_spib(struct device *dev, unsigned int size, + int stream_tag, int enable) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_stream *stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + struct hdac_ext_stream *estream; + + if (!stream) + return -EINVAL; + + estream = stream_to_hdac_ext_stream(stream); + /* enable/disable SPIB for this hdac stream */ + snd_hdac_ext_stream_spbcap_enable(ebus, enable, stream->index); + + /* set the spib value */ + snd_hdac_ext_stream_set_spib(ebus, estream, size); + + return 0; +} + +static int skl_dsp_prepare(struct device *dev, unsigned int format, + unsigned int size, struct snd_dma_buffer *dmab) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_ext_stream *estream; + struct hdac_stream *stream; + struct snd_pcm_substream substream; + int ret; + + if (!bus) + return -ENODEV; + + memset(&substream, 0, sizeof(substream)); + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + + estream = snd_hdac_ext_stream_assign(ebus, &substream, + HDAC_EXT_STREAM_TYPE_HOST); + if (!estream) + return -ENODEV; + + stream = hdac_stream(estream); + + /* assign decouple host dma channel */ + ret = snd_hdac_dsp_prepare(stream, format, size, dmab); + if (ret < 0) + return ret; + + skl_dsp_setup_spib(dev, size, stream->stream_tag, true); + + return stream->stream_tag; +} + +static int skl_dsp_trigger(struct device *dev, bool start, int stream_tag) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_stream *stream; + struct hdac_bus *bus = ebus_to_hbus(ebus); + + if (!bus) + return -ENODEV; + + stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + if (!stream) + return -EINVAL; + + snd_hdac_dsp_trigger(stream, start); + + return 0; +} + +static int skl_dsp_cleanup(struct device *dev, + struct snd_dma_buffer *dmab, int stream_tag) +{ + struct hdac_ext_bus *ebus = dev_get_drvdata(dev); + struct hdac_stream *stream; + struct hdac_ext_stream *estream; + struct hdac_bus *bus = ebus_to_hbus(ebus); + + if (!bus) + return -ENODEV; + + stream = snd_hdac_get_stream(bus, + SNDRV_PCM_STREAM_PLAYBACK, stream_tag); + if (!stream) + return -EINVAL; + + estream = stream_to_hdac_ext_stream(stream); + skl_dsp_setup_spib(dev, 0, stream_tag, false); + snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST); + + snd_hdac_dsp_cleanup(stream, dmab); + + return 0; +} + static struct skl_dsp_loader_ops skl_get_loader_ops(void) { struct skl_dsp_loader_ops loader_ops; @@ -84,6 +183,21 @@ static struct skl_dsp_loader_ops skl_get_loader_ops(void) return loader_ops; }; +static struct skl_dsp_loader_ops bxt_get_loader_ops(void) +{ + struct skl_dsp_loader_ops loader_ops; + + memset(&loader_ops, 0, sizeof(loader_ops)); + + loader_ops.alloc_dma_buf = skl_alloc_dma_buf; + loader_ops.free_dma_buf = skl_free_dma_buf; + loader_ops.prepare = skl_dsp_prepare; + loader_ops.trigger = skl_dsp_trigger; + loader_ops.cleanup = skl_dsp_cleanup; + + return loader_ops; +}; + static const struct skl_dsp_ops dsp_ops[] = { { .id = 0x9d70, @@ -91,6 +205,12 @@ static const struct skl_dsp_ops dsp_ops[] = { .init = skl_sst_dsp_init, .cleanup = skl_sst_dsp_cleanup }, + { + .id = 0x5a98, + .loader_ops = bxt_get_loader_ops, + .init = bxt_sst_dsp_init, + .cleanup = bxt_sst_dsp_cleanup + }, }; static int skl_get_dsp_ops(int pci_id) diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index b6e310d49dd6..ff31e6615251 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -124,10 +124,19 @@ struct skl_dsp_fw_ops { }; struct skl_dsp_loader_ops { + int stream_tag; + int (*alloc_dma_buf)(struct device *dev, struct snd_dma_buffer *dmab, size_t size); int (*free_dma_buf)(struct device *dev, struct snd_dma_buffer *dmab); + int (*prepare)(struct device *dev, unsigned int format, + unsigned int byte_size, + struct snd_dma_buffer *bufp); + int (*trigger)(struct device *dev, bool start, int stream_tag); + + int (*cleanup)(struct device *dev, struct snd_dma_buffer *dmab, + int stream_tag); }; struct skl_load_module_info { @@ -160,6 +169,10 @@ int skl_dsp_boot(struct sst_dsp *ctx); int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp); +int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); +void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); #endif /*__SKL_SST_DSP_H__*/ -- GitLab From 630e413dc24da0c2373fd7592aeb0e08cea71cd1 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Tue, 29 Mar 2016 09:39:35 +0200 Subject: [PATCH 0818/9938] ASoC: tas571x: chip type detection via I2C name The chip selection was relying only on DT. It was not possible to use the driver without DT. This adds the chip type detection from the I2C name, which allows to use the driver from the platform driver without DT. Signed-off-by: Petr Kulhavy Reviewed-by: Kevin Cernekee Signed-off-by: Mark Brown --- sound/soc/codecs/tas571x.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index d003c6ce0794..aafee9bbe01a 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -404,11 +404,10 @@ static int tas571x_i2c_probe(struct i2c_client *client, i2c_set_clientdata(client, priv); of_id = of_match_device(tas571x_of_match, dev); - if (!of_id) { - dev_err(dev, "Unknown device type\n"); - return -EINVAL; - } - priv->chip = of_id->data; + if (of_id) + priv->chip = of_id->data; + else + priv->chip = (void *) id->driver_data; priv->mclk = devm_clk_get(dev, "mclk"); if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) { @@ -505,9 +504,9 @@ static const struct of_device_id tas571x_of_match[] = { MODULE_DEVICE_TABLE(of, tas571x_of_match); static const struct i2c_device_id tas571x_i2c_id[] = { - { "tas5711", 0 }, - { "tas5717", 0 }, - { "tas5719", 0 }, + { "tas5711", (kernel_ulong_t) &tas5711_chip }, + { "tas5717", (kernel_ulong_t) &tas5717_chip }, + { "tas5719", (kernel_ulong_t) &tas5717_chip }, { } }; MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); -- GitLab From a0fcb63586a57560de28c333127bb0e36c01c70c Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 30 Mar 2016 10:41:42 -0400 Subject: [PATCH 0819/9938] staging: unisys: removed unused switch/port info from visorbus.h The fields 'switch_no' and 'internal_port_no' were originally added to the visor_device struct in preparation of removing the 'device_info' struct in the now removed 'uislib' library. After the refactoring was complete, these attributes are not referenced anywhere, and there are no plans to use them. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/visorbus.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 9c47a138e748..25ffdc03f020 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -155,8 +155,6 @@ struct visor_device { u8 *description; struct controlvm_message_header *pending_msg_hdr; void *vbus_hdr_info; - u32 switch_no; - u32 internal_port_no; uuid_le partition_uuid; }; -- GitLab From 378d638a89b67bf2bb2de34786f3a27b41203357 Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 30 Mar 2016 10:41:43 -0400 Subject: [PATCH 0820/9938] staging: unisys: include: removed unused 'visor_device.description' The 'description' variable in visor_device was added in preparation for removing the 'device_info' struct when the uislib files were removed. That attribute is never accessed nor set, and the 'name' attribute provides enough information to correctly identify the driver, it is not needed. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/visorbus.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 25ffdc03f020..f7e753f2ba6c 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -152,7 +152,6 @@ struct visor_device { uuid_le type; uuid_le inst; u8 *name; - u8 *description; struct controlvm_message_header *pending_msg_hdr; void *vbus_hdr_info; uuid_le partition_uuid; -- GitLab From 240f7ec1f49aef8fe28d13ad52ced6c28ccc8f02 Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 30 Mar 2016 10:41:44 -0400 Subject: [PATCH 0821/9938] staging: unisys: removed unused visor_device.type field The visor_device.type field was included when preparing to remove the device_info struct. However, it's not used at all, and was already redundant by the existence of the 'visor_device.channel_type_guid' field. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/visorbus.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index f7e753f2ba6c..729ca7e51d17 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -149,7 +149,6 @@ struct visor_device { u32 chipset_bus_no; u32 chipset_dev_no; struct visorchipset_state state; - uuid_le type; uuid_le inst; u8 *name; struct controlvm_message_header *pending_msg_hdr; -- GitLab From 03d0d045c8884df5e0576d3eb7dbf53fa95fe7ce Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 30 Mar 2016 10:41:45 -0400 Subject: [PATCH 0822/9938] staging: unisys: removed 'visor_device.devnodes' field The 'visor_device.devnodes' field was used for displaying driver version information through the devmajorminor sysfs attribute, which has recently been removed, rendering the field unnecessary. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/visorbus.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 729ca7e51d17..cbc6d8f06c9b 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -136,12 +136,6 @@ struct visor_device { struct periodic_work *periodic_work; bool being_removed; bool responded_to_device_create; - struct { - int major, minor; - void *attr; /* private use by devmajorminor_attr.c you can - * change this constant to whatever you want - */ - } devnodes[5]; /* the code will detect and behave appropriately) */ struct semaphore visordriver_callback_lock; bool pausing; -- GitLab From 527486ee8fbb28fabd8fa51ddd4339a37ee15c5c Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 30 Mar 2016 10:41:46 -0400 Subject: [PATCH 0823/9938] staging: unisys: removed unused channel_bytes attribute The channel_bytes attribute in the visor_device struct was meant to keep track of the number of bytes in the associated channel of the device. Not only is the variable never set nor used, but the information can already be accessed by referencing visor_device->visorchannel->nbytes. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/visorbus.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index cbc6d8f06c9b..3788d167b3c6 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -124,7 +124,6 @@ struct visor_device { */ struct visorchannel *visorchannel; uuid_le channel_type_guid; - u64 channel_bytes; /** These fields are for private use by the bus driver only. * A notable exception is that the visor driver can use -- GitLab From 64938182e7836650feeb9b2b9dadd510ed4b0dad Mon Sep 17 00:00:00 2001 From: David Kershner Date: Wed, 30 Mar 2016 20:38:49 -0400 Subject: [PATCH 0824/9938] staging: unisys: remove wmb() in visordriver_remove_device Don't need to have a wmb() in visordriver_remove_device. Also removed an unnecessary check for drv being null. Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 1fcb1775bb59..547be8b50956 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -613,20 +613,12 @@ visordriver_remove_device(struct device *xdev) drv = to_visor_driver(xdev->driver); down(&dev->visordriver_callback_lock); dev->being_removed = true; - /* - * ensure that the dev->being_removed flag is set before we start the - * actual removal - */ - wmb(); - if (drv) { - if (drv->remove) - drv->remove(dev); - } + if (drv->remove) + drv->remove(dev); up(&dev->visordriver_callback_lock); dev_stop_periodic_work(dev); put_device(&dev->device); - return 0; } -- GitLab From 9f6b68774f29692f3e5b87e8eae29da61c3b1171 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 24 Mar 2016 15:58:17 -0500 Subject: [PATCH 0825/9938] android: remove timed output/gpio driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit timed_output was only used by the Android vibrator HAL which has now learned how to use LED triggers instead[1]. Any users of it in AOSP are on ancient kernels. Adding support for LED triggers is purely DT changes and proper kernel config. [1] https://android.googlesource.com/platform%2Fhardware%2Flibhardware/+/61701df363310a5cbd95e3e1638baa9526e42c9b Cc: John Stultz Cc: "Arve Hjønnevåg" Cc: Riley Andrews Signed-off-by: Rob Herring Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/Kconfig | 14 --- drivers/staging/android/Makefile | 2 - drivers/staging/android/timed_gpio.c | 166 ------------------------- drivers/staging/android/timed_gpio.h | 33 ----- drivers/staging/android/timed_output.c | 110 ---------------- drivers/staging/android/timed_output.h | 37 ------ 6 files changed, 362 deletions(-) delete mode 100644 drivers/staging/android/timed_gpio.c delete mode 100644 drivers/staging/android/timed_gpio.h delete mode 100644 drivers/staging/android/timed_output.c delete mode 100644 drivers/staging/android/timed_output.h diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index bd90d2002afb..4244821e32fc 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -14,20 +14,6 @@ config ASHMEM It is, in theory, a good memory allocator for low-memory devices, because it can discard shared memory units when under memory pressure. -config ANDROID_TIMED_OUTPUT - bool "Timed output class driver" - default y - -config ANDROID_TIMED_GPIO - tristate "Android timed gpio driver" - depends on GPIOLIB || COMPILE_TEST - depends on ANDROID_TIMED_OUTPUT - default n - ---help--- - Unlike generic gpio is to allow programs to access and manipulate gpio - registers from user space, timed output/gpio is a system to allow changing - a gpio pin and restore it automatically after a specified timeout. - config ANDROID_LOW_MEMORY_KILLER bool "Android Low Memory Killer" ---help--- diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index c7b6c99cc5ce..980d6dc4b265 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -3,8 +3,6 @@ ccflags-y += -I$(src) # needed for trace events obj-y += ion/ obj-$(CONFIG_ASHMEM) += ashmem.o -obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o -obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o obj-$(CONFIG_SYNC) += sync.o sync_debug.o obj-$(CONFIG_SW_SYNC) += sw_sync.o diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c deleted file mode 100644 index 914fd1005467..000000000000 --- a/drivers/staging/android/timed_gpio.c +++ /dev/null @@ -1,166 +0,0 @@ -/* drivers/misc/timed_gpio.c - * - * Copyright (C) 2008 Google, Inc. - * Author: Mike Lockwood - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "timed_output.h" -#include "timed_gpio.h" - -struct timed_gpio_data { - struct timed_output_dev dev; - struct hrtimer timer; - spinlock_t lock; - unsigned gpio; - int max_timeout; - u8 active_low; -}; - -static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer) -{ - struct timed_gpio_data *data = - container_of(timer, struct timed_gpio_data, timer); - - gpio_direction_output(data->gpio, data->active_low ? 1 : 0); - return HRTIMER_NORESTART; -} - -static int gpio_get_time(struct timed_output_dev *dev) -{ - struct timed_gpio_data *data; - ktime_t t; - - data = container_of(dev, struct timed_gpio_data, dev); - - if (!hrtimer_active(&data->timer)) - return 0; - - t = hrtimer_get_remaining(&data->timer); - - return ktime_to_ms(t); -} - -static void gpio_enable(struct timed_output_dev *dev, int value) -{ - struct timed_gpio_data *data = - container_of(dev, struct timed_gpio_data, dev); - unsigned long flags; - - spin_lock_irqsave(&data->lock, flags); - - /* cancel previous timer and set GPIO according to value */ - hrtimer_cancel(&data->timer); - gpio_direction_output(data->gpio, data->active_low ? !value : !!value); - - if (value > 0) { - if (value > data->max_timeout) - value = data->max_timeout; - - hrtimer_start(&data->timer, - ktime_set(value / 1000, (value % 1000) * 1000000), - HRTIMER_MODE_REL); - } - - spin_unlock_irqrestore(&data->lock, flags); -} - -static int timed_gpio_probe(struct platform_device *pdev) -{ - struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; - struct timed_gpio *cur_gpio; - struct timed_gpio_data *gpio_data, *gpio_dat; - int i, ret; - - if (!pdata) - return -EBUSY; - - gpio_data = devm_kcalloc(&pdev->dev, pdata->num_gpios, - sizeof(*gpio_data), GFP_KERNEL); - if (!gpio_data) - return -ENOMEM; - - for (i = 0; i < pdata->num_gpios; i++) { - cur_gpio = &pdata->gpios[i]; - gpio_dat = &gpio_data[i]; - - hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - gpio_dat->timer.function = gpio_timer_func; - spin_lock_init(&gpio_dat->lock); - - gpio_dat->dev.name = cur_gpio->name; - gpio_dat->dev.get_time = gpio_get_time; - gpio_dat->dev.enable = gpio_enable; - ret = gpio_request(cur_gpio->gpio, cur_gpio->name); - if (ret < 0) - goto err_out; - ret = timed_output_dev_register(&gpio_dat->dev); - if (ret < 0) { - gpio_free(cur_gpio->gpio); - goto err_out; - } - - gpio_dat->gpio = cur_gpio->gpio; - gpio_dat->max_timeout = cur_gpio->max_timeout; - gpio_dat->active_low = cur_gpio->active_low; - gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low); - } - - platform_set_drvdata(pdev, gpio_data); - - return 0; - -err_out: - while (--i >= 0) { - timed_output_dev_unregister(&gpio_data[i].dev); - gpio_free(gpio_data[i].gpio); - } - - return ret; -} - -static int timed_gpio_remove(struct platform_device *pdev) -{ - struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; - struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < pdata->num_gpios; i++) { - timed_output_dev_unregister(&gpio_data[i].dev); - gpio_free(gpio_data[i].gpio); - } - - return 0; -} - -static struct platform_driver timed_gpio_driver = { - .probe = timed_gpio_probe, - .remove = timed_gpio_remove, - .driver = { - .name = TIMED_GPIO_NAME, - }, -}; - -module_platform_driver(timed_gpio_driver); - -MODULE_AUTHOR("Mike Lockwood "); -MODULE_DESCRIPTION("timed gpio driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/android/timed_gpio.h b/drivers/staging/android/timed_gpio.h deleted file mode 100644 index d29e169d7ebe..000000000000 --- a/drivers/staging/android/timed_gpio.h +++ /dev/null @@ -1,33 +0,0 @@ -/* include/linux/timed_gpio.h - * - * Copyright (C) 2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * -*/ - -#ifndef _LINUX_TIMED_GPIO_H -#define _LINUX_TIMED_GPIO_H - -#define TIMED_GPIO_NAME "timed-gpio" - -struct timed_gpio { - const char *name; - unsigned gpio; - int max_timeout; - u8 active_low; -}; - -struct timed_gpio_platform_data { - int num_gpios; - struct timed_gpio *gpios; -}; - -#endif diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c deleted file mode 100644 index aff9cdb007e5..000000000000 --- a/drivers/staging/android/timed_output.c +++ /dev/null @@ -1,110 +0,0 @@ -/* drivers/misc/timed_output.c - * - * Copyright (C) 2009 Google, Inc. - * Author: Mike Lockwood - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#define pr_fmt(fmt) "timed_output: " fmt - -#include -#include -#include -#include -#include -#include - -#include "timed_output.h" - -static struct class *timed_output_class; -static atomic_t device_count; - -static ssize_t enable_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct timed_output_dev *tdev = dev_get_drvdata(dev); - int remaining = tdev->get_time(tdev); - - return sprintf(buf, "%d\n", remaining); -} - -static ssize_t enable_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t size) -{ - struct timed_output_dev *tdev = dev_get_drvdata(dev); - int value; - int rc; - - rc = kstrtoint(buf, 0, &value); - if (rc != 0) - return -EINVAL; - - tdev->enable(tdev, value); - - return size; -} -static DEVICE_ATTR_RW(enable); - -static struct attribute *timed_output_attrs[] = { - &dev_attr_enable.attr, - NULL, -}; -ATTRIBUTE_GROUPS(timed_output); - -static int create_timed_output_class(void) -{ - if (!timed_output_class) { - timed_output_class = class_create(THIS_MODULE, "timed_output"); - if (IS_ERR(timed_output_class)) - return PTR_ERR(timed_output_class); - atomic_set(&device_count, 0); - timed_output_class->dev_groups = timed_output_groups; - } - - return 0; -} - -int timed_output_dev_register(struct timed_output_dev *tdev) -{ - int ret; - - if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time) - return -EINVAL; - - ret = create_timed_output_class(); - if (ret < 0) - return ret; - - tdev->index = atomic_inc_return(&device_count); - tdev->dev = device_create(timed_output_class, NULL, - MKDEV(0, tdev->index), NULL, "%s", tdev->name); - if (IS_ERR(tdev->dev)) - return PTR_ERR(tdev->dev); - - dev_set_drvdata(tdev->dev, tdev); - tdev->state = 0; - return 0; -} -EXPORT_SYMBOL_GPL(timed_output_dev_register); - -void timed_output_dev_unregister(struct timed_output_dev *tdev) -{ - tdev->enable(tdev, 0); - device_destroy(timed_output_class, MKDEV(0, tdev->index)); -} -EXPORT_SYMBOL_GPL(timed_output_dev_unregister); - -static int __init timed_output_init(void) -{ - return create_timed_output_class(); -} -device_initcall(timed_output_init); diff --git a/drivers/staging/android/timed_output.h b/drivers/staging/android/timed_output.h deleted file mode 100644 index 13d2ca51cbe8..000000000000 --- a/drivers/staging/android/timed_output.h +++ /dev/null @@ -1,37 +0,0 @@ -/* include/linux/timed_output.h - * - * Copyright (C) 2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * -*/ - -#ifndef _LINUX_TIMED_OUTPUT_H -#define _LINUX_TIMED_OUTPUT_H - -struct timed_output_dev { - const char *name; - - /* enable the output and set the timer */ - void (*enable)(struct timed_output_dev *sdev, int timeout); - - /* returns the current number of milliseconds remaining on the timer */ - int (*get_time)(struct timed_output_dev *sdev); - - /* private data */ - struct device *dev; - int index; - int state; -}; - -int timed_output_dev_register(struct timed_output_dev *dev); -void timed_output_dev_unregister(struct timed_output_dev *dev); - -#endif -- GitLab From 411059f701f0e8d23b5b5a94f9e43df7e32251f8 Mon Sep 17 00:00:00 2001 From: Ben Marsh Date: Mon, 28 Mar 2016 19:26:19 +0200 Subject: [PATCH 0826/9938] Staging: android: change memory allocation style in ion.c Chnages memory allocation style in order to silence a checkpatch.pl warning. Signed-off-by: Ben Marsh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 85365672c931..d4c6207ca2c1 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -184,7 +184,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct scatterlist *sg; int i, ret; - buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL); + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) return ERR_PTR(-ENOMEM); @@ -341,7 +341,7 @@ static struct ion_handle *ion_handle_create(struct ion_client *client, { struct ion_handle *handle; - handle = kzalloc(sizeof(struct ion_handle), GFP_KERNEL); + handle = kzalloc(sizeof(*handle), GFP_KERNEL); if (!handle) return ERR_PTR(-ENOMEM); kref_init(&handle->ref); @@ -827,7 +827,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, } task_unlock(current->group_leader); - client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); + client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) goto err_put_task_struct; @@ -1035,7 +1035,7 @@ static void ion_vm_open(struct vm_area_struct *vma) struct ion_buffer *buffer = vma->vm_private_data; struct ion_vma_list *vma_list; - vma_list = kmalloc(sizeof(struct ion_vma_list), GFP_KERNEL); + vma_list = kmalloc(sizeof(*vma_list), GFP_KERNEL); if (!vma_list) return; vma_list->vma = vma; @@ -1650,7 +1650,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) struct ion_device *idev; int ret; - idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL); + idev = kzalloc(sizeof(*idev), GFP_KERNEL); if (!idev) return ERR_PTR(-ENOMEM); -- GitLab From 9f37d399f19f9efbcecafe647ba3cf3c9653bb05 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:36:57 -0700 Subject: [PATCH 0827/9938] staging: comedi: amplc_pc263: tidy up digital output subdevice init For aesthetics, add some whitespace to the digital output subdevice initialization. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index b1946ce6ecc1..13d8ed204fbe 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -80,14 +80,15 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; + /* Digital Output subdevice */ s = &dev->subdevices[0]; - /* digital output subdevice */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pc263_do_insn_bits; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pc263_do_insn_bits; + /* read initial relay state */ s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); -- GitLab From d69917a64ae78c27348164e7cabc03a838df3e40 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:36:56 -0700 Subject: [PATCH 0828/9938] staging: comedi: amplc_pc263: tidy up comedi_driver definition For aesthetics, add some whitespace to the comedi_driver definition. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 13d8ed204fbe..eb447e5df2f3 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -96,13 +96,13 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) } static struct comedi_driver amplc_pc263_driver = { - .driver_name = "amplc_pc263", - .module = THIS_MODULE, - .attach = pc263_attach, - .detach = comedi_legacy_detach, - .board_name = &pc263_boards[0].name, - .offset = sizeof(struct pc263_board), - .num_names = ARRAY_SIZE(pc263_boards), + .driver_name = "amplc_pc263", + .module = THIS_MODULE, + .attach = pc263_attach, + .detach = comedi_legacy_detach, + .board_name = &pc263_boards[0].name, + .offset = sizeof(struct pc263_board), + .num_names = ARRAY_SIZE(pc263_boards), }; module_comedi_driver(amplc_pc263_driver); -- GitLab From 1b50167146139402be0924aab55062b391cb8956 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:36:58 -0700 Subject: [PATCH 0829/9938] staging: comedi: amplc_pc263: define the register map For completeness, define the registers used by this driver and remove the magic numbers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index eb447e5df2f3..fc075ed7962e 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -37,10 +37,8 @@ The state of the outputs can be read. #include "../comedidev.h" /* PC263 registers */ - -/* - * Board descriptions for Amplicon PC263. - */ +#define PC263_DO_0_7_REG 0x00 +#define PC263_DO_8_15_REG 0x01 struct pc263_board { const char *name; @@ -58,8 +56,8 @@ static int pc263_do_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) { - outb(s->state & 0xff, dev->iobase); - outb((s->state >> 8) & 0xff, dev->iobase + 1); + outb(s->state & 0xff, dev->iobase + PC263_DO_0_7_REG); + outb((s->state >> 8) & 0xff, dev->iobase + PC263_DO_8_15_REG); } data[1] = s->state; @@ -90,7 +88,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = pc263_do_insn_bits; /* read initial relay state */ - s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); + s->state = inb(dev->iobase + PC263_DO_0_7_REG) | + (inb(dev->iobase + PC263_DO_8_15_REG) << 8); return 0; } -- GitLab From 05380cde47247daec0956fb818c63093a92d5585 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:36:55 -0700 Subject: [PATCH 0830/9938] staging: comedi: amplc_pc263: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 62 ++++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index fc075ed7962e..58b0b6b1a693 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -1,37 +1,37 @@ /* - comedi/drivers/amplc_pc263.c - Driver for Amplicon PC263 and PCI263 relay boards. + * Driver for Amplicon PC263 relay board. + * + * Copyright (C) 2002 MEV Ltd. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - Copyright (C) 2002 MEV Ltd. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: amplc_pc263 -Description: Amplicon PC263 -Author: Ian Abbott -Devices: [Amplicon] PC263 (pc263) -Updated: Fri, 12 Apr 2013 15:19:36 +0100 -Status: works - -Configuration options: - [0] - I/O port base address - -The board appears as one subdevice, with 16 digital outputs, each -connected to a reed-relay. Relay contacts are closed when output is 1. -The state of the outputs can be read. -*/ + * Driver: amplc_pc263 + * Description: Amplicon PC263 + * Author: Ian Abbott + * Devices: [Amplicon] PC263 (pc263) + * Updated: Fri, 12 Apr 2013 15:19:36 +0100 + * Status: works + * + * Configuration options: + * [0] - I/O port base address + * + * The board appears as one subdevice, with 16 digital outputs, each + * connected to a reed-relay. Relay contacts are closed when output is 1. + * The state of the outputs can be read. + */ #include #include "../comedidev.h" -- GitLab From eecbf23476d33c79c9315277ed2b2e17ef34a955 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:09:48 -0700 Subject: [PATCH 0831/9938] staging: comedi: amplc_dio200_common: Prefer 'unsigned int' to bare use of 'unsigned' Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200_common.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index d1539e798ffd..071d2fb4d7d0 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -221,7 +221,7 @@ static void dio200_start_intr(struct comedi_device *dev, struct dio200_subdev_intr *subpriv = s->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int n; - unsigned isn_bits; + unsigned int isn_bits; /* Determine interrupt sources to enable. */ isn_bits = 0; @@ -284,9 +284,9 @@ static int dio200_handle_read_intr(struct comedi_device *dev, { const struct dio200_board *board = dev->board_ptr; struct dio200_subdev_intr *subpriv = s->private; - unsigned triggered; - unsigned intstat; - unsigned cur_enabled; + unsigned int triggered; + unsigned int intstat; + unsigned int cur_enabled; unsigned long flags; triggered = 0; @@ -439,7 +439,7 @@ static int dio200_subdev_intr_cmd(struct comedi_device *dev, static int dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int offset, - unsigned valid_isns) + unsigned int valid_isns) { const struct dio200_board *board = dev->board_ptr; struct dio200_subdev_intr *subpriv; -- GitLab From 6050b1cfc66c421546880c0219cbce9102800099 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:09:49 -0700 Subject: [PATCH 0832/9938] staging: comedi: amplc_dio200_common: document spinlock definition Fix the checkpatch.pl issue: CHECK: spinlock_t definition without comment Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 071d2fb4d7d0..f6e4e984235d 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -101,7 +101,7 @@ struct dio200_subdev_8255 { }; struct dio200_subdev_intr { - spinlock_t spinlock; + spinlock_t spinlock; /* protects the 'active' flag */ unsigned int ofs; unsigned int valid_isns; unsigned int enabled_isns; -- GitLab From 61ac7ccfb5cbe59ee940f0a7b3ad4fd3e3ce8c37 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 12:19:21 -0700 Subject: [PATCH 0833/9938] staging: comedi: amplc_pci230: Prefer using the BIT macro Fix the checkpatch.pl issues by using the BIT macro and defining some macros for the multi-bit fields. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 141 +++++++++--------- 1 file changed, 74 insertions(+), 67 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index cf5ac8aad236..5d0cb37c4e0e 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -237,47 +237,50 @@ /* * DACCON read-write values. */ -#define PCI230_DAC_OR_UNI (0 << 0) /* Output range unipolar */ -#define PCI230_DAC_OR_BIP (1 << 0) /* Output range bipolar */ -#define PCI230_DAC_OR_MASK (1 << 0) +#define PCI230_DAC_OR(x) (((x) & 0x1) << 0) +#define PCI230_DAC_OR_UNI PCI230_DAC_OR(0) /* Output unipolar */ +#define PCI230_DAC_OR_BIP PCI230_DAC_OR(1) /* Output bipolar */ +#define PCI230_DAC_OR_MASK PCI230_DAC_OR(1) /* * The following applies only if DAC FIFO support is enabled in the EXTFUNC * register (and only for PCI230+ hardware version 2 onwards). */ -#define PCI230P2_DAC_FIFO_EN (1 << 8) /* FIFO enable */ +#define PCI230P2_DAC_FIFO_EN BIT(8) /* FIFO enable */ /* * The following apply only if the DAC FIFO is enabled (and only for PCI230+ * hardware version 2 onwards). */ -#define PCI230P2_DAC_TRIG_NONE (0 << 2) /* No trigger */ -#define PCI230P2_DAC_TRIG_SW (1 << 2) /* Software trigger trigger */ -#define PCI230P2_DAC_TRIG_EXTP (2 << 2) /* EXTTRIG +ve edge trigger */ -#define PCI230P2_DAC_TRIG_EXTN (3 << 2) /* EXTTRIG -ve edge trigger */ -#define PCI230P2_DAC_TRIG_Z2CT0 (4 << 2) /* CT0-OUT +ve edge trigger */ -#define PCI230P2_DAC_TRIG_Z2CT1 (5 << 2) /* CT1-OUT +ve edge trigger */ -#define PCI230P2_DAC_TRIG_Z2CT2 (6 << 2) /* CT2-OUT +ve edge trigger */ -#define PCI230P2_DAC_TRIG_MASK (7 << 2) -#define PCI230P2_DAC_FIFO_WRAP (1 << 7) /* FIFO wraparound mode */ -#define PCI230P2_DAC_INT_FIFO_EMPTY (0 << 9) /* FIFO interrupt empty */ -#define PCI230P2_DAC_INT_FIFO_NEMPTY (1 << 9) -#define PCI230P2_DAC_INT_FIFO_NHALF (2 << 9) /* FIFO intr not half full */ -#define PCI230P2_DAC_INT_FIFO_HALF (3 << 9) -#define PCI230P2_DAC_INT_FIFO_NFULL (4 << 9) /* FIFO interrupt not full */ -#define PCI230P2_DAC_INT_FIFO_FULL (5 << 9) -#define PCI230P2_DAC_INT_FIFO_MASK (7 << 9) +#define PCI230P2_DAC_TRIG(x) (((x) & 0x7) << 2) +#define PCI230P2_DAC_TRIG_NONE PCI230P2_DAC_TRIG(0) /* none */ +#define PCI230P2_DAC_TRIG_SW PCI230P2_DAC_TRIG(1) /* soft trig */ +#define PCI230P2_DAC_TRIG_EXTP PCI230P2_DAC_TRIG(2) /* ext + edge */ +#define PCI230P2_DAC_TRIG_EXTN PCI230P2_DAC_TRIG(3) /* ext - edge */ +#define PCI230P2_DAC_TRIG_Z2CT0 PCI230P2_DAC_TRIG(4) /* Z2 CT0 out */ +#define PCI230P2_DAC_TRIG_Z2CT1 PCI230P2_DAC_TRIG(5) /* Z2 CT1 out */ +#define PCI230P2_DAC_TRIG_Z2CT2 PCI230P2_DAC_TRIG(6) /* Z2 CT2 out */ +#define PCI230P2_DAC_TRIG_MASK PCI230P2_DAC_TRIG(7) +#define PCI230P2_DAC_FIFO_WRAP BIT(7) /* FIFO wraparound mode */ +#define PCI230P2_DAC_INT_FIFO(x) (((x) & 7) << 9) +#define PCI230P2_DAC_INT_FIFO_EMPTY PCI230P2_DAC_INT_FIFO(0) /* empty */ +#define PCI230P2_DAC_INT_FIFO_NEMPTY PCI230P2_DAC_INT_FIFO(1) /* !empty */ +#define PCI230P2_DAC_INT_FIFO_NHALF PCI230P2_DAC_INT_FIFO(2) /* !half */ +#define PCI230P2_DAC_INT_FIFO_HALF PCI230P2_DAC_INT_FIFO(3) /* half */ +#define PCI230P2_DAC_INT_FIFO_NFULL PCI230P2_DAC_INT_FIFO(4) /* !full */ +#define PCI230P2_DAC_INT_FIFO_FULL PCI230P2_DAC_INT_FIFO(5) /* full */ +#define PCI230P2_DAC_INT_FIFO_MASK PCI230P2_DAC_INT_FIFO(7) /* * DACCON read-only values. */ -#define PCI230_DAC_BUSY (1 << 1) /* DAC busy. */ +#define PCI230_DAC_BUSY BIT(1) /* DAC busy. */ /* * The following apply only if the DAC FIFO is enabled (and only for PCI230+ * hardware version 2 onwards). */ -#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1 << 5) /* Underrun error */ -#define PCI230P2_DAC_FIFO_EMPTY (1 << 13) /* FIFO empty */ -#define PCI230P2_DAC_FIFO_FULL (1 << 14) /* FIFO full */ -#define PCI230P2_DAC_FIFO_HALF (1 << 15) /* FIFO half full */ +#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED BIT(5) /* Underrun error */ +#define PCI230P2_DAC_FIFO_EMPTY BIT(13) /* FIFO empty */ +#define PCI230P2_DAC_FIFO_FULL BIT(14) /* FIFO full */ +#define PCI230P2_DAC_FIFO_HALF BIT(15) /* FIFO half full */ /* * DACCON write-only, transient values. @@ -286,8 +289,8 @@ * The following apply only if the DAC FIFO is enabled (and only for PCI230+ * hardware version 2 onwards). */ -#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1 << 5) /* Clear underrun */ -#define PCI230P2_DAC_FIFO_RESET (1 << 12) /* FIFO reset */ +#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR BIT(5) /* Clear underrun */ +#define PCI230P2_DAC_FIFO_RESET BIT(12) /* FIFO reset */ /* * PCI230+ hardware version 2 DAC FIFO levels. @@ -304,44 +307,48 @@ /* * ADCCON read/write values. */ -#define PCI230_ADC_TRIG_NONE (0 << 0) /* No trigger */ -#define PCI230_ADC_TRIG_SW (1 << 0) /* Software trigger trigger */ -#define PCI230_ADC_TRIG_EXTP (2 << 0) /* EXTTRIG +ve edge trigger */ -#define PCI230_ADC_TRIG_EXTN (3 << 0) /* EXTTRIG -ve edge trigger */ -#define PCI230_ADC_TRIG_Z2CT0 (4 << 0) /* CT0-OUT +ve edge trigger */ -#define PCI230_ADC_TRIG_Z2CT1 (5 << 0) /* CT1-OUT +ve edge trigger */ -#define PCI230_ADC_TRIG_Z2CT2 (6 << 0) /* CT2-OUT +ve edge trigger */ -#define PCI230_ADC_TRIG_MASK (7 << 0) -#define PCI230_ADC_IR_UNI (0 << 3) /* Input range unipolar */ -#define PCI230_ADC_IR_BIP (1 << 3) /* Input range bipolar */ -#define PCI230_ADC_IR_MASK (1 << 3) -#define PCI230_ADC_IM_SE (0 << 4) /* Input mode single ended */ -#define PCI230_ADC_IM_DIF (1 << 4) /* Input mode differential */ -#define PCI230_ADC_IM_MASK (1 << 4) -#define PCI230_ADC_FIFO_EN (1 << 8) /* FIFO enable */ -#define PCI230_ADC_INT_FIFO_EMPTY (0 << 9) -#define PCI230_ADC_INT_FIFO_NEMPTY (1 << 9) /* FIFO interrupt not empty */ -#define PCI230_ADC_INT_FIFO_NHALF (2 << 9) -#define PCI230_ADC_INT_FIFO_HALF (3 << 9) /* FIFO interrupt half full */ -#define PCI230_ADC_INT_FIFO_NFULL (4 << 9) -#define PCI230_ADC_INT_FIFO_FULL (5 << 9) /* FIFO interrupt full */ -#define PCI230P_ADC_INT_FIFO_THRESH (7 << 9) /* FIFO interrupt threshold */ -#define PCI230_ADC_INT_FIFO_MASK (7 << 9) +#define PCI230_ADC_TRIG(x) (((x) & 0x7) << 0) +#define PCI230_ADC_TRIG_NONE PCI230_ADC_TRIG(0) /* none */ +#define PCI230_ADC_TRIG_SW PCI230_ADC_TRIG(1) /* soft trig */ +#define PCI230_ADC_TRIG_EXTP PCI230_ADC_TRIG(2) /* ext + edge */ +#define PCI230_ADC_TRIG_EXTN PCI230_ADC_TRIG(3) /* ext - edge */ +#define PCI230_ADC_TRIG_Z2CT0 PCI230_ADC_TRIG(4) /* Z2 CT0 out*/ +#define PCI230_ADC_TRIG_Z2CT1 PCI230_ADC_TRIG(5) /* Z2 CT1 out */ +#define PCI230_ADC_TRIG_Z2CT2 PCI230_ADC_TRIG(6) /* Z2 CT2 out */ +#define PCI230_ADC_TRIG_MASK PCI230_ADC_TRIG(7) +#define PCI230_ADC_IR(x) (((x) & 0x1) << 3) +#define PCI230_ADC_IR_UNI PCI230_ADC_IR(0) /* Input unipolar */ +#define PCI230_ADC_IR_BIP PCI230_ADC_IR(1) /* Input bipolar */ +#define PCI230_ADC_IR_MASK PCI230_ADC_IR(1) +#define PCI230_ADC_IM(x) (((x) & 0x1) << 4) +#define PCI230_ADC_IM_SE PCI230_ADC_IM(0) /* single ended */ +#define PCI230_ADC_IM_DIF PCI230_ADC_IM(1) /* differential */ +#define PCI230_ADC_IM_MASK PCI230_ADC_IM(1) +#define PCI230_ADC_FIFO_EN BIT(8) /* FIFO enable */ +#define PCI230_ADC_INT_FIFO(x) (((x) & 0x7) << 9) +#define PCI230_ADC_INT_FIFO_EMPTY PCI230_ADC_INT_FIFO(0) /* empty */ +#define PCI230_ADC_INT_FIFO_NEMPTY PCI230_ADC_INT_FIFO(1) /* !empty */ +#define PCI230_ADC_INT_FIFO_NHALF PCI230_ADC_INT_FIFO(2) /* !half */ +#define PCI230_ADC_INT_FIFO_HALF PCI230_ADC_INT_FIFO(3) /* half */ +#define PCI230_ADC_INT_FIFO_NFULL PCI230_ADC_INT_FIFO(4) /* !full */ +#define PCI230_ADC_INT_FIFO_FULL PCI230_ADC_INT_FIFO(5) /* full */ +#define PCI230P_ADC_INT_FIFO_THRESH PCI230_ADC_INT_FIFO(7) /* threshold */ +#define PCI230_ADC_INT_FIFO_MASK PCI230_ADC_INT_FIFO(7) /* * ADCCON write-only, transient values. */ -#define PCI230_ADC_FIFO_RESET (1 << 12) /* FIFO reset */ -#define PCI230_ADC_GLOB_RESET (1 << 13) /* Global reset */ +#define PCI230_ADC_FIFO_RESET BIT(12) /* FIFO reset */ +#define PCI230_ADC_GLOB_RESET BIT(13) /* Global reset */ /* * ADCCON read-only values. */ -#define PCI230_ADC_BUSY (1 << 15) /* ADC busy */ -#define PCI230_ADC_FIFO_EMPTY (1 << 12) /* FIFO empty */ -#define PCI230_ADC_FIFO_FULL (1 << 13) /* FIFO full */ -#define PCI230_ADC_FIFO_HALF (1 << 14) /* FIFO half full */ -#define PCI230_ADC_FIFO_FULL_LATCHED (1 << 5) /* FIFO overrun occurred */ +#define PCI230_ADC_BUSY BIT(15) /* ADC busy */ +#define PCI230_ADC_FIFO_EMPTY BIT(12) /* FIFO empty */ +#define PCI230_ADC_FIFO_FULL BIT(13) /* FIFO full */ +#define PCI230_ADC_FIFO_HALF BIT(14) /* FIFO half full */ +#define PCI230_ADC_FIFO_FULL_LATCHED BIT(5) /* FIFO overrun occurred */ /* * PCI230 ADC FIFO levels. @@ -353,10 +360,10 @@ * PCI230+ EXTFUNC values. */ /* Route EXTTRIG pin to external gate inputs. */ -#define PCI230P_EXTFUNC_GAT_EXTTRIG (1 << 0) +#define PCI230P_EXTFUNC_GAT_EXTTRIG BIT(0) /* PCI230+ hardware version 2 values. */ /* Allow DAC FIFO to be enabled. */ -#define PCI230P2_EXTFUNC_DACFIFO (1 << 1) +#define PCI230P2_EXTFUNC_DACFIFO BIT(1) /* * Counter/timer clock input configuration sources. @@ -402,20 +409,20 @@ static inline unsigned int pci230_gat_config(unsigned int chan, * Interrupt enables/status register values. */ #define PCI230_INT_DISABLE 0 -#define PCI230_INT_PPI_C0 (1 << 0) -#define PCI230_INT_PPI_C3 (1 << 1) -#define PCI230_INT_ADC (1 << 2) -#define PCI230_INT_ZCLK_CT1 (1 << 5) +#define PCI230_INT_PPI_C0 BIT(0) +#define PCI230_INT_PPI_C3 BIT(1) +#define PCI230_INT_ADC BIT(2) +#define PCI230_INT_ZCLK_CT1 BIT(5) /* For PCI230+ hardware version 2 when DAC FIFO enabled. */ -#define PCI230P2_INT_DAC (1 << 4) +#define PCI230P2_INT_DAC BIT(4) /* * (Potentially) shared resources and their owners */ enum { - RES_Z2CT0 = (1U << 0), /* Z2-CT0 */ - RES_Z2CT1 = (1U << 1), /* Z2-CT1 */ - RES_Z2CT2 = (1U << 2) /* Z2-CT2 */ + RES_Z2CT0 = BIT(0), /* Z2-CT0 */ + RES_Z2CT1 = BIT(1), /* Z2-CT1 */ + RES_Z2CT2 = BIT(2) /* Z2-CT2 */ }; enum { -- GitLab From e76415f47f9f4ec4f0289f8194eae0726dc27dfd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 12:19:22 -0700 Subject: [PATCH 0834/9938] staging: comedi: amplc_pci230: Prefer kernel type 'u64' over 'uint64_t' Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 5d0cb37c4e0e..42945de31fe2 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -637,10 +637,10 @@ static void pci230_release_all_resources(struct comedi_device *dev, pci230_release_shared(dev, (unsigned char)~0, owner); } -static unsigned int pci230_divide_ns(uint64_t ns, unsigned int timebase, +static unsigned int pci230_divide_ns(u64 ns, unsigned int timebase, unsigned int flags) { - uint64_t div; + u64 div; unsigned int rem; div = ns; @@ -663,7 +663,7 @@ static unsigned int pci230_divide_ns(uint64_t ns, unsigned int timebase, * Given desired period in ns, returns the required internal clock source * and gets the initial count. */ -static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count, +static unsigned int pci230_choose_clk_count(u64 ns, unsigned int *count, unsigned int flags) { unsigned int clk_src, cnt; @@ -687,7 +687,7 @@ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int flags) } static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, - unsigned int mode, uint64_t ns, + unsigned int mode, u64 ns, unsigned int flags) { unsigned int clk_src; @@ -2250,7 +2250,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) zgat = pci230_gat_config(0, GAT_VCC); outb(zgat, dev->iobase + PCI230_ZGAT_SCE); pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1, - ((uint64_t)cmd->convert_arg * + ((u64)cmd->convert_arg * cmd->scan_end_arg), CMDF_ROUND_UP); if (cmd->scan_begin_src == TRIG_TIMER) { -- GitLab From 9bc9e60e4f48b2917718d0dcf8a3cbb9f7687dd7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 12:34:53 -0700 Subject: [PATCH 0835/9938] staging: comedi: c6xdigio: Prefer using the BIT macro Fix the checkpatch.pl issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/c6xdigio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 1a109e30d8ff..8ee732571588 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -47,8 +47,8 @@ */ #define C6XDIGIO_DATA_REG 0x00 #define C6XDIGIO_DATA_CHAN(x) (((x) + 1) << 4) -#define C6XDIGIO_DATA_PWM (1 << 5) -#define C6XDIGIO_DATA_ENCODER (1 << 6) +#define C6XDIGIO_DATA_PWM BIT(5) +#define C6XDIGIO_DATA_ENCODER BIT(6) #define C6XDIGIO_STATUS_REG 0x01 #define C6XDIGIO_CTRL_REG 0x02 -- GitLab From f91852ce61339ca0ca557c7ce5838f3a774a1bf5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 10:47:24 -0700 Subject: [PATCH 0836/9938] staging: comedi: drivers: tidy up insn_rw_emulate_bits() Tidy up this function and fix the checkpatch.pl issues: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 35 +++++++++++++++----------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index b63dd2ef78b5..e3bbc8f724ba 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -575,38 +575,35 @@ EXPORT_SYMBOL_GPL(comedi_handle_events); static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct comedi_insn new_insn; + struct comedi_insn _insn; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int base_chan = (chan < 32) ? 0 : chan; + unsigned int _data[2]; int ret; - static const unsigned channels_per_bitfield = 32; - - unsigned chan = CR_CHAN(insn->chanspec); - const unsigned base_bitfield_channel = - (chan < channels_per_bitfield) ? 0 : chan; - unsigned int new_data[2]; - memset(new_data, 0, sizeof(new_data)); - memset(&new_insn, 0, sizeof(new_insn)); - new_insn.insn = INSN_BITS; - new_insn.chanspec = base_bitfield_channel; - new_insn.n = 2; - new_insn.subdev = insn->subdev; + memset(_data, 0, sizeof(_data)); + memset(&_insn, 0, sizeof(_insn)); + _insn.insn = INSN_BITS; + _insn.chanspec = base_chan; + _insn.n = 2; + _insn.subdev = insn->subdev; if (insn->insn == INSN_WRITE) { if (!(s->subdev_flags & SDF_WRITABLE)) return -EINVAL; - new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */ - new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel)) - : 0; /* bits */ + _data[0] = 1 << (chan - base_chan); /* mask */ + _data[1] = data[0] ? (1 << (chan - base_chan)) : 0; /* bits */ } - ret = s->insn_bits(dev, s, &new_insn, new_data); + ret = s->insn_bits(dev, s, &_insn, _data); if (ret < 0) return ret; if (insn->insn == INSN_READ) - data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1; + data[0] = (_data[1] >> (chan - base_chan)) & 1; return 1; } -- GitLab From 7be7cd10ade121cd5363c5f8790638b177b5e9dd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 10:47:25 -0700 Subject: [PATCH 0837/9938] staging: comedi: drivers: fix possible bug in comedi_handle_events() This function assumes that the async subdevice has a cancel() function. It looks like all the current comedi drivers implement a cancel() for the async subdevices except for the dt2814 analog input usbdevice. Fix comedi_handle_events() so it does not try to call a non-existent cancel() function. Add a dev_warn() to __comedi_device_postconfig_async() so that any new driver authors will be reminded to implement the cancel(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index e3bbc8f724ba..44511d729450 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -564,7 +564,7 @@ unsigned int comedi_handle_events(struct comedi_device *dev, if (events == 0) return events; - if (events & COMEDI_CB_CANCEL_MASK) + if ((events & COMEDI_CB_CANCEL_MASK) && s->cancel) s->cancel(dev, s); comedi_event(dev, s); @@ -625,6 +625,9 @@ static int __comedi_device_postconfig_async(struct comedi_device *dev, "async subdevices must have a do_cmdtest() function\n"); return -EINVAL; } + if (!s->cancel) + dev_warn(dev->class_dev, + "async subdevices should have a cancel() function\n"); async = kzalloc(sizeof(*async), GFP_KERNEL); if (!async) -- GitLab From db94bfad3b05c9a3cd5c151018db142b07486d02 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:45:17 -0700 Subject: [PATCH 0838/9938] staging: comedi: amplc_pci263: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci263.c | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index b6768aa90547..fa36bd5587d4 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -1,36 +1,36 @@ /* - comedi/drivers/amplc_pci263.c - Driver for Amplicon PCI263 relay board. + * Driver for Amplicon PCI263 relay board. + * + * Copyright (C) 2002 MEV Ltd. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - Copyright (C) 2002 MEV Ltd. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: amplc_pci263 -Description: Amplicon PCI263 -Author: Ian Abbott -Devices: [Amplicon] PCI263 (amplc_pci263) -Updated: Fri, 12 Apr 2013 15:19:36 +0100 -Status: works - -Configuration options: not applicable, uses PCI auto config - -The board appears as one subdevice, with 16 digital outputs, each -connected to a reed-relay. Relay contacts are closed when output is 1. -The state of the outputs can be read. -*/ + * Driver: amplc_pci263 + * Description: Amplicon PCI263 + * Author: Ian Abbott + * Devices: [Amplicon] PCI263 (amplc_pci263) + * Updated: Fri, 12 Apr 2013 15:19:36 +0100 + * Status: works + * + * Configuration options: not applicable, uses PCI auto config + * + * The board appears as one subdevice, with 16 digital outputs, each + * connected to a reed-relay. Relay contacts are closed when output is 1. + * The state of the outputs can be read. + */ #include -- GitLab From 1ee79c8ee88e74fdd778c024caf84d741a134409 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:45:18 -0700 Subject: [PATCH 0839/9938] staging: comedi: amplc_pci263: tidy up digital output subdevice init For aesthetics, add some whitespace to the digital output subdevice initialization. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci263.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index fa36bd5587d4..c47f042465e7 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -67,14 +67,15 @@ static int pci263_auto_attach(struct comedi_device *dev, if (ret) return ret; + /* Digital Output subdevice */ s = &dev->subdevices[0]; - /* digital output subdevice */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pci263_do_insn_bits; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci263_do_insn_bits; + /* read initial relay state */ s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); -- GitLab From 623211de9a3bfd0fabc81f8bff8c79fd9e4944ba Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 11:45:19 -0700 Subject: [PATCH 0840/9938] staging: comedi: amplc_pci263: define the register map For completeness, define the registers used by this driver and remove the magic numbers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci263.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index c47f042465e7..8d4069bc5716 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -36,14 +36,18 @@ #include "../comedi_pci.h" +/* PCI263 registers */ +#define PCI263_DO_0_7_REG 0x00 +#define PCI263_DO_8_15_REG 0x01 + static int pci263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { if (comedi_dio_update_state(s, data)) { - outb(s->state & 0xff, dev->iobase); - outb((s->state >> 8) & 0xff, dev->iobase + 1); + outb(s->state & 0xff, dev->iobase + PCI263_DO_0_7_REG); + outb((s->state >> 8) & 0xff, dev->iobase + PCI263_DO_8_15_REG); } data[1] = s->state; @@ -77,7 +81,8 @@ static int pci263_auto_attach(struct comedi_device *dev, s->insn_bits = pci263_do_insn_bits; /* read initial relay state */ - s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); + s->state = inb(dev->iobase + PCI263_DO_0_7_REG) | + (inb(dev->iobase + PCI263_DO_8_15_REG) << 8); return 0; } -- GitLab From e078cb2a64fd588557ef2dec573622699a05d642 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 30 Mar 2016 12:00:29 -0700 Subject: [PATCH 0841/9938] staging: comedi: amplc_pci224: Prefer using the BIT macro Fix the checkpatch.pl issues by using the BIT macro and defining some macros for the multi-bit fields. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 71 ++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index cac011fdd375..2e6decf1b69d 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -132,48 +132,53 @@ * DACCON values. */ /* (r/w) Scan trigger. */ -#define PCI224_DACCON_TRIG_MASK (7 << 0) -#define PCI224_DACCON_TRIG_NONE (0 << 0) /* none */ -#define PCI224_DACCON_TRIG_SW (1 << 0) /* software trig */ -#define PCI224_DACCON_TRIG_EXTP (2 << 0) /* ext +ve edge */ -#define PCI224_DACCON_TRIG_EXTN (3 << 0) /* ext -ve edge */ -#define PCI224_DACCON_TRIG_Z2CT0 (4 << 0) /* Z2 CT0 out */ -#define PCI224_DACCON_TRIG_Z2CT1 (5 << 0) /* Z2 CT1 out */ -#define PCI224_DACCON_TRIG_Z2CT2 (6 << 0) /* Z2 CT2 out */ +#define PCI224_DACCON_TRIG(x) (((x) & 0x7) << 0) +#define PCI224_DACCON_TRIG_MASK PCI224_DACCON_TRIG(7) +#define PCI224_DACCON_TRIG_NONE PCI224_DACCON_TRIG(0) /* none */ +#define PCI224_DACCON_TRIG_SW PCI224_DACCON_TRIG(1) /* soft trig */ +#define PCI224_DACCON_TRIG_EXTP PCI224_DACCON_TRIG(2) /* ext + edge */ +#define PCI224_DACCON_TRIG_EXTN PCI224_DACCON_TRIG(3) /* ext - edge */ +#define PCI224_DACCON_TRIG_Z2CT0 PCI224_DACCON_TRIG(4) /* Z2 CT0 out */ +#define PCI224_DACCON_TRIG_Z2CT1 PCI224_DACCON_TRIG(5) /* Z2 CT1 out */ +#define PCI224_DACCON_TRIG_Z2CT2 PCI224_DACCON_TRIG(6) /* Z2 CT2 out */ /* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */ -#define PCI224_DACCON_POLAR_MASK (1 << 3) -#define PCI224_DACCON_POLAR_UNI (0 << 3) /* range [0,Vref] */ -#define PCI224_DACCON_POLAR_BI (1 << 3) /* range [-Vref,Vref] */ +#define PCI224_DACCON_POLAR(x) (((x) & 0x1) << 3) +#define PCI224_DACCON_POLAR_MASK PCI224_DACCON_POLAR(1) +#define PCI224_DACCON_POLAR_UNI PCI224_DACCON_POLAR(0) /* [0,+V] */ +#define PCI224_DACCON_POLAR_BI PCI224_DACCON_POLAR(1) /* [-V,+V] */ /* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */ -#define PCI224_DACCON_VREF_MASK (3 << 4) -#define PCI224_DACCON_VREF_1_25 (0 << 4) /* Vref = 1.25V */ -#define PCI224_DACCON_VREF_2_5 (1 << 4) /* Vref = 2.5V */ -#define PCI224_DACCON_VREF_5 (2 << 4) /* Vref = 5V */ -#define PCI224_DACCON_VREF_10 (3 << 4) /* Vref = 10V */ +#define PCI224_DACCON_VREF(x) (((x) & 0x3) << 4) +#define PCI224_DACCON_VREF_MASK PCI224_DACCON_VREF(3) +#define PCI224_DACCON_VREF_1_25 PCI224_DACCON_VREF(0) /* 1.25V */ +#define PCI224_DACCON_VREF_2_5 PCI224_DACCON_VREF(1) /* 2.5V */ +#define PCI224_DACCON_VREF_5 PCI224_DACCON_VREF(2) /* 5V */ +#define PCI224_DACCON_VREF_10 PCI224_DACCON_VREF(3) /* 10V */ /* (r/w) Wraparound mode enable (to play back stored waveform). */ -#define PCI224_DACCON_FIFOWRAP (1 << 7) +#define PCI224_DACCON_FIFOWRAP BIT(7) /* (r/w) FIFO enable. It MUST be set! */ -#define PCI224_DACCON_FIFOENAB (1 << 8) +#define PCI224_DACCON_FIFOENAB BIT(8) /* (r/w) FIFO interrupt trigger level (most values are not very useful). */ -#define PCI224_DACCON_FIFOINTR_MASK (7 << 9) -#define PCI224_DACCON_FIFOINTR_EMPTY (0 << 9) /* when empty */ -#define PCI224_DACCON_FIFOINTR_NEMPTY (1 << 9) /* when not empty */ -#define PCI224_DACCON_FIFOINTR_NHALF (2 << 9) /* when not half full */ -#define PCI224_DACCON_FIFOINTR_HALF (3 << 9) /* when half full */ -#define PCI224_DACCON_FIFOINTR_NFULL (4 << 9) /* when not full */ -#define PCI224_DACCON_FIFOINTR_FULL (5 << 9) /* when full */ +#define PCI224_DACCON_FIFOINTR(x) (((x) & 0x7) << 9) +#define PCI224_DACCON_FIFOINTR_MASK PCI224_DACCON_FIFOINTR(7) +#define PCI224_DACCON_FIFOINTR_EMPTY PCI224_DACCON_FIFOINTR(0) /* empty */ +#define PCI224_DACCON_FIFOINTR_NEMPTY PCI224_DACCON_FIFOINTR(1) /* !empty */ +#define PCI224_DACCON_FIFOINTR_NHALF PCI224_DACCON_FIFOINTR(2) /* !half */ +#define PCI224_DACCON_FIFOINTR_HALF PCI224_DACCON_FIFOINTR(3) /* half */ +#define PCI224_DACCON_FIFOINTR_NFULL PCI224_DACCON_FIFOINTR(4) /* !full */ +#define PCI224_DACCON_FIFOINTR_FULL PCI224_DACCON_FIFOINTR(5) /* full */ /* (r-o) FIFO fill level. */ -#define PCI224_DACCON_FIFOFL_MASK (7 << 12) -#define PCI224_DACCON_FIFOFL_EMPTY (1 << 12) /* 0 */ -#define PCI224_DACCON_FIFOFL_ONETOHALF (0 << 12) /* [1,2048] */ -#define PCI224_DACCON_FIFOFL_HALFTOFULL (4 << 12) /* [2049,4095] */ -#define PCI224_DACCON_FIFOFL_FULL (6 << 12) /* 4096 */ +#define PCI224_DACCON_FIFOFL(x) (((x) & 0x7) << 12) +#define PCI224_DACCON_FIFOFL_MASK PCI224_DACCON_FIFOFL(7) +#define PCI224_DACCON_FIFOFL_EMPTY PCI224_DACCON_FIFOFL(1) /* 0 */ +#define PCI224_DACCON_FIFOFL_ONETOHALF PCI224_DACCON_FIFOFL(0) /* 1-2048 */ +#define PCI224_DACCON_FIFOFL_HALFTOFULL PCI224_DACCON_FIFOFL(4) /* 2049-4095 */ +#define PCI224_DACCON_FIFOFL_FULL PCI224_DACCON_FIFOFL(6) /* 4096 */ /* (r-o) DAC busy flag. */ -#define PCI224_DACCON_BUSY (1 << 15) +#define PCI224_DACCON_BUSY BIT(15) /* (w-o) FIFO reset. */ -#define PCI224_DACCON_FIFORESET (1 << 12) +#define PCI224_DACCON_FIFORESET BIT(12) /* (w-o) Global reset (not sure what it does). */ -#define PCI224_DACCON_GLOBALRESET (1 << 13) +#define PCI224_DACCON_GLOBALRESET BIT(13) /* * DAC FIFO size. -- GitLab From d8bf4bee49728e31b1d225630c39714a6c42648c Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Mon, 28 Mar 2016 13:54:15 +0900 Subject: [PATCH 0842/9938] staging: dgnc: replace dgnc_offset_table with bit shift. the dgnc_offset_table has a same value with (1 << port). So I tried to replace dgnc_offset_table array with 1 << port. And also there are redundant assignments(tmp and current_port) inside while loop for checking uart port, and remove them. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_neo.c | 44 +++++++++------------------------ 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index d732e6e99408..6b57c441859d 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -77,9 +77,6 @@ struct board_ops dgnc_neo_ops = { .send_immediate_char = neo_send_immediate_char }; -static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x80 }; - /* * This function allows calls to ensure that all outstanding * PCI writes have been completed, by doing a PCI read against @@ -923,9 +920,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) struct dgnc_board *brd = voidbrd; struct channel_t *ch; int port = 0; - int type = 0; - int current_port; - u32 tmp; + int type; u32 uart_poll; unsigned long flags; unsigned long flags2; @@ -960,29 +955,12 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* At this point, we have at least SOMETHING to service, dig further... */ - current_port = 0; - /* Loop on each port */ while ((uart_poll & 0xff) != 0) { - tmp = uart_poll; - - /* Check current port to see if it has interrupt pending */ - if ((tmp & dgnc_offset_table[current_port]) != 0) { - port = current_port; - type = tmp >> (8 + (port * 3)); - type &= 0x7; - } else { - current_port++; - continue; - } - - /* Remove this port + type from uart_poll */ - uart_poll &= ~(dgnc_offset_table[port]); + type = uart_poll >> (8 + (port * 3)); + type &= 0x7; - if (!type) { - /* If no type, just ignore it, and move onto next port */ - continue; - } + uart_poll &= ~(0x01 << port); /* Switch on type of interrupt we have */ switch (type) { @@ -994,7 +972,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* Verify the port is in range. */ if (port >= brd->nasync) - continue; + break; ch = brd->channels[port]; neo_copy_data_from_uart_to_queue(ch); @@ -1004,14 +982,14 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, flags2); - continue; + break; case UART_17158_RX_LINE_STATUS: /* * RXRDY and RX LINE Status (logic OR of LSR[4:1]) */ neo_parse_lsr(brd, port); - continue; + break; case UART_17158_TXRDY: /* @@ -1027,14 +1005,14 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * it should be, I was getting things like RXDY too. Weird. */ neo_parse_isr(brd, port); - continue; + break; case UART_17158_MSR: /* * MSR or flow control was seen. */ neo_parse_isr(brd, port); - continue; + break; default: /* @@ -1043,8 +1021,10 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * these once and awhile. * Its harmless, just ignore it and move on. */ - continue; + break; } + + port++; } /* -- GitLab From a1115c9f7826143600d12f72cda7bb0be404c842 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Tue, 29 Mar 2016 13:47:59 +0900 Subject: [PATCH 0843/9938] staging: dgnc: remove parenthesis around the CONST | remove parenthesis around the CONST | CONST. It will be also fixed checkpatch.pl warning about "Alignment should match open parenthesis" becasue parenthesis were removed by this patch. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_neo.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 6b57c441859d..ee7f2da7df48 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -114,8 +114,8 @@ static inline void neo_set_cts_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), - &ch->ch_neo_uart->fctr); + writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY, + &ch->ch_neo_uart->fctr); /* Feed the UART our trigger levels */ writeb(8, &ch->ch_neo_uart->tfifo); @@ -149,8 +149,8 @@ static inline void neo_set_rts_flow_control(struct channel_t *ch) /* Turn on UART enhanced bits */ writeb(efr, &ch->ch_neo_uart->efr); - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), - &ch->ch_neo_uart->fctr); + writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY, + &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 4; writeb(32, &ch->ch_neo_uart->rfifo); @@ -187,7 +187,7 @@ static inline void neo_set_ixon_flow_control(struct channel_t *ch) /* Turn on UART enhanced bits */ writeb(efr, &ch->ch_neo_uart->efr); - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), + writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY, &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 4; @@ -226,8 +226,8 @@ static inline void neo_set_ixoff_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), - &ch->ch_neo_uart->fctr); + writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY, + &ch->ch_neo_uart->fctr); writeb(8, &ch->ch_neo_uart->tfifo); ch->ch_t_tlevel = 8; @@ -267,8 +267,8 @@ static inline void neo_set_no_input_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), - &ch->ch_neo_uart->fctr); + writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY, + &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 0; @@ -305,8 +305,8 @@ static inline void neo_set_no_output_flow_control(struct channel_t *ch) writeb(efr, &ch->ch_neo_uart->efr); /* Turn on table D, with 8 char hi/low watermarks */ - writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), - &ch->ch_neo_uart->fctr); + writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY, + &ch->ch_neo_uart->fctr); ch->ch_r_watermark = 0; @@ -1353,7 +1353,7 @@ static void neo_flush_uart_read(struct channel_t *ch) if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), + writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR, &ch->ch_neo_uart->isr_fcr); neo_pci_posting_flush(ch->ch_bd); @@ -1628,7 +1628,7 @@ static void neo_uart_init(struct channel_t *ch) /* Clear out UART and FIFO */ readb(&ch->ch_neo_uart->txrx); - writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, &ch->ch_neo_uart->isr_fcr); readb(&ch->ch_neo_uart->lsr); readb(&ch->ch_neo_uart->msr); -- GitLab From ffe4f329460ded65b339522abcbdc7aa18021dc9 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Tue, 29 Mar 2016 13:48:31 +0900 Subject: [PATCH 0844/9938] staging: dgnc: fix 'line over 80 characters' fix checkpatch.pl warning about 'line over 80 characters'. I just moved all line comment to above if statement. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_neo.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index ee7f2da7df48..6105ccb99d34 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -1785,9 +1785,15 @@ static void neo_vpd(struct dgnc_board *brd) brd->vpd[(i * 2) + 1] = (a >> 8) & 0xff; } - if (((brd->vpd[0x08] != 0x82) /* long resource name tag */ - && (brd->vpd[0x10] != 0x82)) /* long resource name tag (PCI-66 files)*/ - || (brd->vpd[0x7F] != 0x78)) { /* small resource end tag */ + /* + * brd->vpd has different name tags by below index. + * 0x08 : long resource name tag + * 0x10 : long resource name tage (PCI-66 files) + * 0x7F : small resource end tag + */ + if (((brd->vpd[0x08] != 0x82) + && (brd->vpd[0x10] != 0x82)) + || (brd->vpd[0x7F] != 0x78)) { memset(brd->vpd, '\0', NEO_VPD_IMAGESIZE); } else { -- GitLab From 3996ae3482935fb531e522b3f23248a6581015a8 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Tue, 29 Mar 2016 13:48:57 +0900 Subject: [PATCH 0845/9938] staging: dgnc: fix Logical continuations. fix checkpatch.pl warning about 'Logical continuations should be on the previous line' Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_neo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 6105ccb99d34..2da6a72fc61d 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -1791,9 +1791,9 @@ static void neo_vpd(struct dgnc_board *brd) * 0x10 : long resource name tage (PCI-66 files) * 0x7F : small resource end tag */ - if (((brd->vpd[0x08] != 0x82) - && (brd->vpd[0x10] != 0x82)) - || (brd->vpd[0x7F] != 0x78)) { + if (((brd->vpd[0x08] != 0x82) && + (brd->vpd[0x10] != 0x82)) || + (brd->vpd[0x7F] != 0x78)) { memset(brd->vpd, '\0', NEO_VPD_IMAGESIZE); } else { -- GitLab From b1168a928277149e1c606763d76ff5c728988755 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 28 Mar 2016 00:30:35 -0400 Subject: [PATCH 0846/9938] ecryptfs: avoid multiple aliases for directories ecryptfs_lookup_interpose should use d_splice_alias(), not d_add() (and return struct dentry * rather than int). Get rid of redundant dir_inode argument, while we are touching it... Signed-off-by: Al Viro --- fs/ecryptfs/inode.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 121114e9a464..91ebc8f18e20 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -324,9 +324,8 @@ static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode) /** * ecryptfs_lookup_interpose - Dentry interposition for a lookup */ -static int ecryptfs_lookup_interpose(struct dentry *dentry, - struct dentry *lower_dentry, - struct inode *dir_inode) +static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry, + struct dentry *lower_dentry) { struct inode *inode, *lower_inode = d_inode(lower_dentry); struct ecryptfs_dentry_info *dentry_info; @@ -339,11 +338,12 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry, "to allocate ecryptfs_dentry_info struct\n", __func__); dput(lower_dentry); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); - fsstack_copy_attr_atime(dir_inode, d_inode(lower_dentry->d_parent)); + fsstack_copy_attr_atime(d_inode(dentry->d_parent), + d_inode(lower_dentry->d_parent)); BUG_ON(!d_count(lower_dentry)); ecryptfs_set_dentry_private(dentry, dentry_info); @@ -353,27 +353,25 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry, if (d_really_is_negative(lower_dentry)) { /* We want to add because we couldn't find in lower */ d_add(dentry, NULL); - return 0; + return NULL; } - inode = __ecryptfs_get_inode(lower_inode, dir_inode->i_sb); + inode = __ecryptfs_get_inode(lower_inode, dentry->d_sb); if (IS_ERR(inode)) { printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n", __func__, PTR_ERR(inode)); - return PTR_ERR(inode); + return ERR_CAST(inode); } if (S_ISREG(inode->i_mode)) { rc = ecryptfs_i_size_read(dentry, inode); if (rc) { make_bad_inode(inode); - return rc; + return ERR_PTR(rc); } } if (inode->i_state & I_NEW) unlock_new_inode(inode); - d_add(dentry, inode); - - return rc; + return d_splice_alias(inode, dentry); } /** @@ -393,6 +391,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, size_t encrypted_and_encoded_name_size; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; struct dentry *lower_dir_dentry, *lower_dentry; + struct dentry *res; int rc = 0; lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); @@ -400,10 +399,10 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, lower_dir_dentry, ecryptfs_dentry->d_name.len); if (IS_ERR(lower_dentry)) { - rc = PTR_ERR(lower_dentry); ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " - "[%d] on lower_dentry = [%pd]\n", __func__, rc, - ecryptfs_dentry); + "[%ld] on lower_dentry = [%pd]\n", __func__, + PTR_ERR(lower_dentry), ecryptfs_dentry); + res = ERR_CAST(lower_dentry); goto out; } if (d_really_is_positive(lower_dentry)) @@ -421,24 +420,25 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, if (rc) { printk(KERN_ERR "%s: Error attempting to encrypt and encode " "filename; rc = [%d]\n", __func__, rc); + res = ERR_PTR(rc); goto out; } lower_dentry = lookup_one_len_unlocked(encrypted_and_encoded_name, lower_dir_dentry, encrypted_and_encoded_name_size); if (IS_ERR(lower_dentry)) { - rc = PTR_ERR(lower_dentry); ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " - "[%d] on lower_dentry = [%s]\n", __func__, rc, + "[%ld] on lower_dentry = [%s]\n", __func__, + PTR_ERR(lower_dentry), encrypted_and_encoded_name); + res = ERR_CAST(lower_dentry); goto out; } interpose: - rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry, - ecryptfs_dir_inode); + res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry); out: kfree(encrypted_and_encoded_name); - return ERR_PTR(rc); + return res; } static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, -- GitLab From 88ae4ab9802eaa8e400e611f85883143d89d6b61 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 28 Mar 2016 00:43:29 -0400 Subject: [PATCH 0847/9938] ecryptfs_lookup(): try either only encrypted or plaintext name Signed-off-by: Al Viro --- fs/ecryptfs/inode.c | 55 +++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 91ebc8f18e20..2b8fc9b6b570 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -388,55 +388,40 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, unsigned int flags) { char *encrypted_and_encoded_name = NULL; - size_t encrypted_and_encoded_name_size; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; struct dentry *lower_dir_dentry, *lower_dentry; + const char *name = ecryptfs_dentry->d_name.name; + size_t len = ecryptfs_dentry->d_name.len; struct dentry *res; int rc = 0; lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); - lower_dentry = lookup_one_len_unlocked(ecryptfs_dentry->d_name.name, - lower_dir_dentry, - ecryptfs_dentry->d_name.len); - if (IS_ERR(lower_dentry)) { - ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " - "[%ld] on lower_dentry = [%pd]\n", __func__, - PTR_ERR(lower_dentry), ecryptfs_dentry); - res = ERR_CAST(lower_dentry); - goto out; - } - if (d_really_is_positive(lower_dentry)) - goto interpose; + mount_crypt_stat = &ecryptfs_superblock_to_private( ecryptfs_dentry->d_sb)->mount_crypt_stat; - if (!(mount_crypt_stat - && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) - goto interpose; - dput(lower_dentry); - rc = ecryptfs_encrypt_and_encode_filename( - &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, - mount_crypt_stat, ecryptfs_dentry->d_name.name, - ecryptfs_dentry->d_name.len); - if (rc) { - printk(KERN_ERR "%s: Error attempting to encrypt and encode " - "filename; rc = [%d]\n", __func__, rc); - res = ERR_PTR(rc); - goto out; + if (mount_crypt_stat + && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { + rc = ecryptfs_encrypt_and_encode_filename( + &encrypted_and_encoded_name, &len, + mount_crypt_stat, name, len); + if (rc) { + printk(KERN_ERR "%s: Error attempting to encrypt and encode " + "filename; rc = [%d]\n", __func__, rc); + return ERR_PTR(rc); + } + name = encrypted_and_encoded_name; } - lower_dentry = lookup_one_len_unlocked(encrypted_and_encoded_name, - lower_dir_dentry, - encrypted_and_encoded_name_size); + + lower_dentry = lookup_one_len_unlocked(name, lower_dir_dentry, len); if (IS_ERR(lower_dentry)) { ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " "[%ld] on lower_dentry = [%s]\n", __func__, PTR_ERR(lower_dentry), - encrypted_and_encoded_name); + name); res = ERR_CAST(lower_dentry); - goto out; + } else { + res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry); } -interpose: - res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry); -out: kfree(encrypted_and_encoded_name); return res; } -- GitLab From b8a7a3a6674725d7ca0ff6e322f6c1cab6e6a11d Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 24 Mar 2016 14:38:37 +0100 Subject: [PATCH 0848/9938] posix_acl: Inode acl caching fixes When get_acl() is called for an inode whose ACL is not cached yet, the get_acl inode operation is called to fetch the ACL from the filesystem. The inode operation is responsible for updating the cached acl with set_cached_acl(). This is done without locking at the VFS level, so another task can call set_cached_acl() or forget_cached_acl() before the get_acl inode operation gets to calling set_cached_acl(), and then get_acl's call to set_cached_acl() results in caching an outdate ACL. Prevent this from happening by setting the cached ACL pointer to a task-specific sentinel value before calling the get_acl inode operation. Move the responsibility for updating the cached ACL from the get_acl inode operations to get_acl(). There, only set the cached ACL if the sentinel value hasn't changed. The sentinel values are chosen to have odd values. Likewise, the value of ACL_NOT_CACHED is odd. In contrast, ACL object pointers always have an even value (ACLs are aligned in memory). This allows to distinguish uncached ACLs values from ACL objects. In addition, switch from guarding inode->i_acl and inode->i_default_acl upates by the inode->i_lock spinlock to using xchg() and cmpxchg(). Filesystems that do not want ACLs returned from their get_acl inode operations to be cached must call forget_cached_acl() to prevent the VFS from doing so. (Patch written by Al Viro and Andreas Gruenbacher.) Signed-off-by: Andreas Gruenbacher Signed-off-by: Al Viro --- fs/9p/acl.c | 2 +- fs/btrfs/acl.c | 3 -- fs/ceph/acl.c | 2 + fs/ext2/acl.c | 3 -- fs/ext4/acl.c | 3 -- fs/f2fs/acl.c | 3 -- fs/hfsplus/posix_acl.c | 3 -- fs/inode.c | 4 +- fs/jffs2/acl.c | 2 - fs/jfs/acl.c | 2 - fs/namei.c | 2 +- fs/nfs/nfs3acl.c | 43 ++++++++++++++++- fs/ocfs2/dlmglue.c | 3 ++ fs/posix_acl.c | 103 +++++++++++++++++++++++++++------------- fs/reiserfs/xattr_acl.c | 6 +-- fs/xfs/xfs_acl.c | 20 +++----- include/linux/fs.h | 12 +++++ 17 files changed, 138 insertions(+), 78 deletions(-) diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 9da967f38387..2d94e94b6b59 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -93,7 +93,7 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) * instantiating the inode (v9fs_inode_from_fid) */ acl = get_cached_acl(inode, type); - BUG_ON(acl == ACL_NOT_CACHED); + BUG_ON(is_uncached_acl(acl)); return acl; } diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 6d263bb1621c..67a607709d4f 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -63,9 +63,6 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type) } kfree(value); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); - return acl; } diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index f19708487e2f..5457f216e2e5 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -37,6 +37,8 @@ static inline void ceph_set_cached_acl(struct inode *inode, spin_lock(&ci->i_ceph_lock); if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0)) set_cached_acl(inode, type, acl); + else + forget_cached_acl(inode, type); spin_unlock(&ci->i_ceph_lock); } diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 27695e6f4e46..42f1d1814083 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -172,9 +172,6 @@ ext2_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); - return acl; } diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 69b1e73026a5..c6601a476c02 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -172,9 +172,6 @@ ext4_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); - return acl; } diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index c8f25f7241f0..6f1fdda977b3 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -190,9 +190,6 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); - return acl; } diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c index afb33eda6d7d..ab7ea2506b4d 100644 --- a/fs/hfsplus/posix_acl.c +++ b/fs/hfsplus/posix_acl.c @@ -48,9 +48,6 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type) hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); - return acl; } diff --git a/fs/inode.c b/fs/inode.c index 69b8b526c194..4202aac99464 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -238,9 +238,9 @@ void __destroy_inode(struct inode *inode) } #ifdef CONFIG_FS_POSIX_ACL - if (inode->i_acl && inode->i_acl != ACL_NOT_CACHED) + if (inode->i_acl && !is_uncached_acl(inode->i_acl)) posix_acl_release(inode->i_acl); - if (inode->i_default_acl && inode->i_default_acl != ACL_NOT_CACHED) + if (inode->i_default_acl && !is_uncached_acl(inode->i_default_acl)) posix_acl_release(inode->i_default_acl); #endif this_cpu_dec(nr_inodes); diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 2f7a3c090489..bc2693d56298 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -203,8 +203,6 @@ struct posix_acl *jffs2_get_acl(struct inode *inode, int type) acl = ERR_PTR(rc); } kfree(value); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); return acl; } diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index ab4882801b24..21fa92ba2c19 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -63,8 +63,6 @@ struct posix_acl *jfs_get_acl(struct inode *inode, int type) acl = posix_acl_from_xattr(&init_user_ns, value, size); } kfree(value); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); return acl; } diff --git a/fs/namei.c b/fs/namei.c index 794f81dce766..3498d53de26f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -265,7 +265,7 @@ static int check_acl(struct inode *inode, int mask) if (!acl) return -EAGAIN; /* no ->get_acl() calls in RCU mode... */ - if (acl == ACL_NOT_CACHED) + if (is_uncached_acl(acl)) return -ECHILD; return posix_acl_permission(inode, acl, mask & ~MAY_NOT_BLOCK); } diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 17c0fa1eccfa..720d92f5abfb 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c @@ -11,6 +11,38 @@ #define NFSDBG_FACILITY NFSDBG_PROC +/* + * nfs3_prepare_get_acl, nfs3_complete_get_acl, nfs3_abort_get_acl: Helpers for + * caching get_acl results in a race-free way. See fs/posix_acl.c:get_acl() + * for explanations. + */ +static void nfs3_prepare_get_acl(struct posix_acl **p) +{ + struct posix_acl *sentinel = uncached_acl_sentinel(current); + + if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) { + /* Not the first reader or sentinel already in place. */ + } +} + +static void nfs3_complete_get_acl(struct posix_acl **p, struct posix_acl *acl) +{ + struct posix_acl *sentinel = uncached_acl_sentinel(current); + + /* Only cache the ACL if our sentinel is still in place. */ + posix_acl_dup(acl); + if (cmpxchg(p, sentinel, acl) != sentinel) + posix_acl_release(acl); +} + +static void nfs3_abort_get_acl(struct posix_acl **p) +{ + struct posix_acl *sentinel = uncached_acl_sentinel(current); + + /* Remove our sentinel upon failure. */ + cmpxchg(p, sentinel, ACL_NOT_CACHED); +} + struct posix_acl *nfs3_get_acl(struct inode *inode, int type) { struct nfs_server *server = NFS_SERVER(inode); @@ -55,6 +87,11 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type) if (res.fattr == NULL) return ERR_PTR(-ENOMEM); + if (args.mask & NFS_ACL) + nfs3_prepare_get_acl(&inode->i_acl); + if (args.mask & NFS_DFACL) + nfs3_prepare_get_acl(&inode->i_default_acl); + status = rpc_call_sync(server->client_acl, &msg, 0); dprintk("NFS reply getacl: %d\n", status); @@ -89,12 +126,12 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type) } if (res.mask & NFS_ACL) - set_cached_acl(inode, ACL_TYPE_ACCESS, res.acl_access); + nfs3_complete_get_acl(&inode->i_acl, res.acl_access); else forget_cached_acl(inode, ACL_TYPE_ACCESS); if (res.mask & NFS_DFACL) - set_cached_acl(inode, ACL_TYPE_DEFAULT, res.acl_default); + nfs3_complete_get_acl(&inode->i_default_acl, res.acl_default); else forget_cached_acl(inode, ACL_TYPE_DEFAULT); @@ -108,6 +145,8 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type) } getout: + nfs3_abort_get_acl(&inode->i_acl); + nfs3_abort_get_acl(&inode->i_default_acl); posix_acl_release(res.acl_access); posix_acl_release(res.acl_default); nfs_free_fattr(res.fattr); diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 474e57f834e6..1eaa9100c889 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -54,6 +54,7 @@ #include "uptodate.h" #include "quota.h" #include "refcounttree.h" +#include "acl.h" #include "buffer_head_io.h" @@ -3623,6 +3624,8 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, filemap_fdatawait(mapping); } + forget_all_cached_acls(inode); + out: return UNBLOCK_CONTINUE; } diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 711dd5170376..bc6736d60786 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -37,14 +37,18 @@ EXPORT_SYMBOL(acl_by_type); struct posix_acl *get_cached_acl(struct inode *inode, int type) { struct posix_acl **p = acl_by_type(inode, type); - struct posix_acl *acl = ACCESS_ONCE(*p); - if (acl) { - spin_lock(&inode->i_lock); - acl = *p; - if (acl != ACL_NOT_CACHED) - acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); + struct posix_acl *acl; + + for (;;) { + rcu_read_lock(); + acl = rcu_dereference(*p); + if (!acl || is_uncached_acl(acl) || + atomic_inc_not_zero(&acl->a_refcount)) + break; + rcu_read_unlock(); + cpu_relax(); } + rcu_read_unlock(); return acl; } EXPORT_SYMBOL(get_cached_acl); @@ -59,58 +63,72 @@ void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl) { struct posix_acl **p = acl_by_type(inode, type); struct posix_acl *old; - spin_lock(&inode->i_lock); - old = *p; - rcu_assign_pointer(*p, posix_acl_dup(acl)); - spin_unlock(&inode->i_lock); - if (old != ACL_NOT_CACHED) + + old = xchg(p, posix_acl_dup(acl)); + if (!is_uncached_acl(old)) posix_acl_release(old); } EXPORT_SYMBOL(set_cached_acl); -void forget_cached_acl(struct inode *inode, int type) +static void __forget_cached_acl(struct posix_acl **p) { - struct posix_acl **p = acl_by_type(inode, type); struct posix_acl *old; - spin_lock(&inode->i_lock); - old = *p; - *p = ACL_NOT_CACHED; - spin_unlock(&inode->i_lock); - if (old != ACL_NOT_CACHED) + + old = xchg(p, ACL_NOT_CACHED); + if (!is_uncached_acl(old)) posix_acl_release(old); } + +void forget_cached_acl(struct inode *inode, int type) +{ + __forget_cached_acl(acl_by_type(inode, type)); +} EXPORT_SYMBOL(forget_cached_acl); void forget_all_cached_acls(struct inode *inode) { - struct posix_acl *old_access, *old_default; - spin_lock(&inode->i_lock); - old_access = inode->i_acl; - old_default = inode->i_default_acl; - inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; - spin_unlock(&inode->i_lock); - if (old_access != ACL_NOT_CACHED) - posix_acl_release(old_access); - if (old_default != ACL_NOT_CACHED) - posix_acl_release(old_default); + __forget_cached_acl(&inode->i_acl); + __forget_cached_acl(&inode->i_default_acl); } EXPORT_SYMBOL(forget_all_cached_acls); struct posix_acl *get_acl(struct inode *inode, int type) { + void *sentinel; + struct posix_acl **p; struct posix_acl *acl; + /* + * The sentinel is used to detect when another operation like + * set_cached_acl() or forget_cached_acl() races with get_acl(). + * It is guaranteed that is_uncached_acl(sentinel) is true. + */ + acl = get_cached_acl(inode, type); - if (acl != ACL_NOT_CACHED) + if (!is_uncached_acl(acl)) return acl; if (!IS_POSIXACL(inode)) return NULL; + sentinel = uncached_acl_sentinel(current); + p = acl_by_type(inode, type); + /* - * A filesystem can force a ACL callback by just never filling the - * ACL cache. But normally you'd fill the cache either at inode - * instantiation time, or on the first ->get_acl call. + * If the ACL isn't being read yet, set our sentinel. Otherwise, the + * current value of the ACL will not be ACL_NOT_CACHED and so our own + * sentinel will not be set; another task will update the cache. We + * could wait for that other task to complete its job, but it's easier + * to just call ->get_acl to fetch the ACL ourself. (This is going to + * be an unlikely race.) + */ + if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) + /* fall through */ ; + + /* + * Normally, the ACL returned by ->get_acl will be cached. + * A filesystem can prevent that by calling + * forget_cached_acl(inode, type) in ->get_acl. * * If the filesystem doesn't have a get_acl() function at all, we'll * just create the negative cache entry. @@ -119,7 +137,24 @@ struct posix_acl *get_acl(struct inode *inode, int type) set_cached_acl(inode, type, NULL); return NULL; } - return inode->i_op->get_acl(inode, type); + acl = inode->i_op->get_acl(inode, type); + + if (IS_ERR(acl)) { + /* + * Remove our sentinel so that we don't block future attempts + * to cache the ACL. + */ + cmpxchg(p, sentinel, ACL_NOT_CACHED); + return acl; + } + + /* + * Cache the result, but only if our sentinel is still in place. + */ + posix_acl_dup(acl); + if (unlikely(cmpxchg(p, sentinel, acl) != sentinel)) + posix_acl_release(acl); + return acl; } EXPORT_SYMBOL(get_acl); diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index ec74bbedc873..dbed42f755e0 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -197,10 +197,8 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) size = reiserfs_xattr_get(inode, name, NULL, 0); if (size < 0) { - if (size == -ENODATA || size == -ENOSYS) { - set_cached_acl(inode, type, NULL); + if (size == -ENODATA || size == -ENOSYS) return NULL; - } return ERR_PTR(size); } @@ -220,8 +218,6 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) } else { acl = reiserfs_posix_acl_from_disk(value, retval); } - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); kfree(value); return acl; diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 2d5df1f23bbc..b6e527b8eccb 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -158,22 +158,14 @@ xfs_get_acl(struct inode *inode, int type) if (error) { /* * If the attribute doesn't exist make sure we have a negative - * cache entry, for any other error assume it is transient and - * leave the cache entry as ACL_NOT_CACHED. + * cache entry, for any other error assume it is transient. */ - if (error == -ENOATTR) - goto out_update_cache; - acl = ERR_PTR(error); - goto out; + if (error != -ENOATTR) + acl = ERR_PTR(error); + } else { + acl = xfs_acl_from_disk(xfs_acl, len, + XFS_ACL_MAX_ENTRIES(ip->i_mount)); } - - acl = xfs_acl_from_disk(xfs_acl, len, XFS_ACL_MAX_ENTRIES(ip->i_mount)); - if (IS_ERR(acl)) - goto out; - -out_update_cache: - set_cached_acl(inode, type, acl); -out: kmem_free(xfs_acl); return acl; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 14a97194b34b..329ed372d708 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -577,6 +577,18 @@ static inline void mapping_allow_writable(struct address_space *mapping) struct posix_acl; #define ACL_NOT_CACHED ((void *)(-1)) +static inline struct posix_acl * +uncached_acl_sentinel(struct task_struct *task) +{ + return (void *)task + 1; +} + +static inline bool +is_uncached_acl(struct posix_acl *acl) +{ + return (long)acl & 1; +} + #define IOP_FASTPERM 0x0001 #define IOP_LOOKUP 0x0002 #define IOP_NOFOLLOW 0x0004 -- GitLab From 04c57f4501909b60353031cfe5b991751d745658 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 24 Mar 2016 14:38:38 +0100 Subject: [PATCH 0849/9938] posix_acl: Unexport acl_by_type and make it static acl_by_type(inode, type) returns a pointer to either inode->i_acl or inode->i_default_acl depending on type. This is useful in fs/posix_acl.c, but should never have been visible outside that file. Signed-off-by: Andreas Gruenbacher Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/posix_acl.c | 3 +-- include/linux/posix_acl.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/posix_acl.c b/fs/posix_acl.c index bc6736d60786..db1fb0f5d9ff 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -21,7 +21,7 @@ #include #include -struct posix_acl **acl_by_type(struct inode *inode, int type) +static struct posix_acl **acl_by_type(struct inode *inode, int type) { switch (type) { case ACL_TYPE_ACCESS: @@ -32,7 +32,6 @@ struct posix_acl **acl_by_type(struct inode *inode, int type) BUG(); } } -EXPORT_SYMBOL(acl_by_type); struct posix_acl *get_cached_acl(struct inode *inode, int type) { diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 3e96a6a76103..5b5a80cc5926 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -99,7 +99,6 @@ extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, extern int simple_set_acl(struct inode *, struct posix_acl *, int); extern int simple_acl_create(struct inode *, struct inode *); -struct posix_acl **acl_by_type(struct inode *inode, int type); struct posix_acl *get_cached_acl(struct inode *inode, int type); struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type); void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl); -- GitLab From 56e18f8cdf057a8c6e68906ff584cf655ea1e328 Mon Sep 17 00:00:00 2001 From: Clifton Barnes Date: Tue, 29 Mar 2016 18:12:40 -0400 Subject: [PATCH 0850/9938] staging: xgifb: fix block comments fix checkpatch.pl warning about 'Block comments use a trailing */ on a separate line' and 'Block comments use * on subsequent lines' Signed-off-by: Clifton Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 13 +-- drivers/staging/xgifb/vb_setmode.c | 3 +- drivers/staging/xgifb/vb_table.h | 135 +++++++++++++++++------------ 3 files changed, 88 insertions(+), 63 deletions(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 29da955493c1..062ece22ed84 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -355,7 +355,8 @@ static void XGINew_DDR2_DefaultRegister( unsigned long P3d4 = Port, P3c4 = Port - 0x10; /* keep following setting sequence, each setting in - * the same reg insert idle */ + * the same reg insert idle + */ xgifb_reg_set(P3d4, 0x82, 0x77); xgifb_reg_set(P3d4, 0x86, 0x00); xgifb_reg_get(P3d4, 0x86); /* Insert read command for delay */ @@ -700,11 +701,11 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension, break; case XG42: /* - XG42 SR14 D[3] Reserve - D[2] = 1, Dual Channel - = 0, Single Channel - - It's Different from Other XG40 Series. + * XG42 SR14 D[3] Reserve + * D[2] = 1, Dual Channel + * = 0, Single Channel + * + * It's Different from Other XG40 Series. */ if (XGINew_CheckFrequence(pVBInfo) == 1) { /* DDRII, DDR2x */ pVBInfo->ram_bus = 32; /* 32 bits */ diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index cc1ad768918a..50c8ea4f5ab7 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1992,7 +1992,8 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, } /* LCD+TV can't support in slave mode - * (Force LCDA+TV->LCDB) */ + * (Force LCDA+TV->LCDB) + */ if ((tempbx & SetInSlaveMode) && (tempbx & XGI_SetCRT2ToLCDA)) { tempbx ^= (SetCRT2ToLCD | XGI_SetCRT2ToLCDA | SetCRT2ToDualEdge); diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 45f2c992cd44..c801deb142f6 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -58,8 +58,9 @@ static const unsigned char XGI27_cr41[24][3] = { {0xC4, 0x40, 0x84}, /* 1 CR8A */ {0xC4, 0x40, 0x84}, /* 2 CR8B */ {0xB3, 0x13, 0xa4}, /* 3 CR40[7], - CR99[2:0], - CR45[3:0]*/ + * CR99[2:0], + * CR45[3:0] + */ {0xf0, 0xf5, 0xf0}, /* 4 CR59 */ {0x90, 0x90, 0x24}, /* 5 CR68 */ {0x77, 0x67, 0x44}, /* 6 CR69 */ @@ -101,9 +102,11 @@ const struct XGI_ExtStruct XGI330_EModeIDTable[] = { {0x38, 0x0a1b, 0x0508, 0x08, 0x00, 0x16}, {0x3a, 0x0e3b, 0x0609, 0x09, 0x00, 0x1e}, {0x3c, 0x0e3b, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200 - add CRT2MODE [2003/10/07] */ + * add CRT2MODE [2003/10/07] + */ {0x3d, 0x0e7d, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200 - add CRT2MODE */ + * add CRT2MODE + */ {0x40, 0x9a1c, 0x0000, 0x00, 0x04, 0x00}, {0x41, 0x9a1d, 0x0000, 0x00, 0x04, 0x00}, {0x43, 0x0a1c, 0x0306, 0x06, 0x05, 0x06}, @@ -129,7 +132,8 @@ const struct XGI_ExtStruct XGI330_EModeIDTable[] = { {0x64, 0x0a7f, 0x0508, 0x08, 0x00, 0x16}, {0x65, 0x0eff, 0x0609, 0x09, 0x00, 0x1e}, {0x66, 0x0eff, 0x070a, 0x0a, 0x00, 0x22}, /* mode 1600x1200 - add CRT2MODE */ + * add CRT2MODE + */ {0x68, 0x067b, 0x080b, 0x0b, 0x00, 0x29}, {0x69, 0x06fd, 0x080b, 0x0b, 0x00, 0x29}, {0x6b, 0x07ff, 0x080b, 0x0b, 0x00, 0x29}, @@ -223,38 +227,38 @@ const struct XGI_CRT1TableStruct XGI_CRT1Table[] = { 0x0D, 0x3E, 0xE0, 0x83, 0xDF, 0x0E, 0x90} }, /* 0xb */ { {0x65, 0x4F, 0x89, 0x57, 0x9F, 0x00, 0x01, 0x00, 0xFB, 0x1F, 0xE6, 0x8A, 0xDF, 0xFC, 0x10} }, /* 0xc */ - { {0x7B, 0x63, 0x9F, 0x6A, 0x93, 0x00, 0x05, 0x00, /* ; - 0D (800x600,56Hz) */ - 0x6F, 0xF0, 0x58, 0x8A, 0x57, 0x70, 0xA0} }, /* ; - (VCLK 36.0MHz) */ - { {0x7F, 0x63, 0x83, 0x6C, 0x1C, 0x00, 0x06, 0x00, /* ; - 0E (800x600,60Hz) */ - 0x72, 0xF0, 0x58, 0x8C, 0x57, 0x73, 0xA0} }, /* ; - (VCLK 40.0MHz) */ - { {0x7D, 0x63, 0x81, 0x6E, 0x1D, 0x00, 0x06, 0x00, /* ; - 0F (800x600,72Hz) */ - 0x98, 0xF0, 0x7C, 0x82, 0x57, 0x99, 0x80} }, /* ; - (VCLK 50.0MHz) */ - { {0x7F, 0x63, 0x83, 0x69, 0x13, 0x00, 0x06, 0x00, /* ; - 10 (800x600,75Hz) */ - 0x6F, 0xF0, 0x58, 0x8B, 0x57, 0x70, 0xA0} }, /* ; - (VCLK 49.5MHz) */ - { {0x7E, 0x63, 0x82, 0x6B, 0x13, 0x00, 0x06, 0x00, /* ; - 11 (800x600,85Hz) */ - 0x75, 0xF0, 0x58, 0x8B, 0x57, 0x76, 0xA0} }, /* ; - (VCLK 56.25MHz) */ - { {0x81, 0x63, 0x85, 0x6D, 0x18, 0x00, 0x06, 0x60, /* ; - 12 (800x600,100Hz) */ - 0x7A, 0xF0, 0x58, 0x8B, 0x57, 0x7B, 0xA0} }, /* ; - (VCLK 75.8MHz) */ - { {0x83, 0x63, 0x87, 0x6E, 0x19, 0x00, 0x06, 0x60, /* ; - 13 (800x600,120Hz) */ - 0x81, 0xF0, 0x58, 0x8B, 0x57, 0x82, 0xA0} }, /* ; - (VCLK 79.411MHz) */ - { {0x85, 0x63, 0x89, 0x6F, 0x1A, 0x00, 0x06, 0x60, /* ; - 14 (800x600,160Hz) */ - 0x91, 0xF0, 0x58, 0x8B, 0x57, 0x92, 0xA0} }, /* ; - (VCLK 105.822MHz) */ + /* 0D (800x600,56Hz) */ + { {0x7B, 0x63, 0x9F, 0x6A, 0x93, 0x00, 0x05, 0x00, + /* (VCLK 36.0MHz) */ + 0x6F, 0xF0, 0x58, 0x8A, 0x57, 0x70, 0xA0} }, + /* 0E (800x600,60Hz) */ + { {0x7F, 0x63, 0x83, 0x6C, 0x1C, 0x00, 0x06, 0x00, + /* (VCLK 40.0MHz) */ + 0x72, 0xF0, 0x58, 0x8C, 0x57, 0x73, 0xA0} }, + /* 0F (800x600,72Hz) */ + { {0x7D, 0x63, 0x81, 0x6E, 0x1D, 0x00, 0x06, 0x00, + /* (VCLK 50.0MHz) */ + 0x98, 0xF0, 0x7C, 0x82, 0x57, 0x99, 0x80} }, + /* 10 (800x600,75Hz) */ + { {0x7F, 0x63, 0x83, 0x69, 0x13, 0x00, 0x06, 0x00, + /* (VCLK 49.5MHz) */ + 0x6F, 0xF0, 0x58, 0x8B, 0x57, 0x70, 0xA0} }, + /* 11 (800x600,85Hz) */ + { {0x7E, 0x63, 0x82, 0x6B, 0x13, 0x00, 0x06, 0x00, + /* (VCLK 56.25MHz) */ + 0x75, 0xF0, 0x58, 0x8B, 0x57, 0x76, 0xA0} }, + /* 12 (800x600,100Hz) */ + { {0x81, 0x63, 0x85, 0x6D, 0x18, 0x00, 0x06, 0x60, + /* (VCLK 75.8MHz) */ + 0x7A, 0xF0, 0x58, 0x8B, 0x57, 0x7B, 0xA0} }, + /* 13 (800x600,120Hz) */ + { {0x83, 0x63, 0x87, 0x6E, 0x19, 0x00, 0x06, 0x60, + /* (VCLK 79.411MHz) */ + 0x81, 0xF0, 0x58, 0x8B, 0x57, 0x82, 0xA0} }, + /* 14 (800x600,160Hz) */ + { {0x85, 0x63, 0x89, 0x6F, 0x1A, 0x00, 0x06, 0x60, + /* (VCLK 105.822MHz) */ + 0x91, 0xF0, 0x58, 0x8B, 0x57, 0x92, 0xA0} }, { {0x99, 0x7F, 0x9D, 0x84, 0x1A, 0x00, 0x02, 0x00, 0x96, 0x1F, 0x7F, 0x83, 0x7F, 0x97, 0x10} }, /* 0x15 */ { {0xA3, 0x7F, 0x87, 0x86, 0x97, 0x00, 0x02, 0x00, @@ -388,7 +392,8 @@ static const struct SiS_LCDData XGI_ExtLCD1024x768Data[] = { static const struct SiS_LCDData XGI_CetLCD1024x768Data[] = { {1, 1, 1344, 806, 1344, 806}, /* ; 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {1, 1, 1344, 806, 1344, 806}, /* 01 (320x350,640x350) */ {1, 1, 1344, 806, 1344, 806}, /* 02 (360x400,720x400) */ {1, 1, 1344, 806, 1344, 806}, /* 03 (720x350) */ @@ -421,7 +426,8 @@ static const struct SiS_LCDData XGI_ExtLCD1280x1024Data[] = { static const struct SiS_LCDData XGI_CetLCD1280x1024Data[] = { {1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {1, 1, 1688, 1066, 1688, 1066}, /* 01 (320x350,640x350) */ {1, 1, 1688, 1066, 1688, 1066}, /* 02 (360x400,720x400) */ {1, 1, 1688, 1066, 1688, 1066}, /* 03 (720x350) */ @@ -434,7 +440,8 @@ static const struct SiS_LCDData XGI_CetLCD1280x1024Data[] = { static const struct SiS_LCDData xgifb_lcd_1400x1050[] = { {211, 100, 2100, 408, 1688, 1066}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {211, 64, 1536, 358, 1688, 1066}, /* 01 (320x350,640x350) */ {211, 100, 2100, 408, 1688, 1066}, /* 02 (360x400,720x400) */ {211, 64, 1536, 358, 1688, 1066}, /* 03 (720x350) */ @@ -442,13 +449,15 @@ static const struct SiS_LCDData xgifb_lcd_1400x1050[] = { {211, 72, 1008, 609, 1688, 1066}, /* 05 (800x600x60Hz) */ {211, 128, 1400, 776, 1688, 1066}, /* 06 (1024x768x60Hz) */ {1, 1, 1688, 1066, 1688, 1066}, /* 07 (1280x1024x60Hz - w/o Scaling) */ + * w/o Scaling) + */ {1, 1, 1688, 1066, 1688, 1066} /* 08 (1400x1050x60Hz) */ }; static const struct SiS_LCDData XGI_ExtLCD1600x1200Data[] = { {4, 1, 1620, 420, 2160, 1250}, /* 00 (320x200,320x400, - 640x200,640x400)*/ + * 640x200,640x400) + */ {27, 7, 1920, 375, 2160, 1250}, /* 01 (320x350,640x350) */ {4, 1, 1620, 420, 2160, 1250}, /* 02 (360x400,720x400)*/ {27, 7, 1920, 375, 2160, 1250}, /* 03 (720x350) */ @@ -462,7 +471,8 @@ static const struct SiS_LCDData XGI_ExtLCD1600x1200Data[] = { static const struct SiS_LCDData XGI_StLCD1600x1200Data[] = { {27, 4, 800, 500, 2160, 1250}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {27, 4, 800, 500, 2160, 1250}, /* 01 (320x350,640x350) */ {27, 4, 800, 500, 2160, 1250}, /* 02 (360x400,720x400) */ {27, 4, 800, 500, 2160, 1250}, /* 03 (720x350) */ @@ -489,7 +499,8 @@ static const struct SiS_LCDData XGI_NoScalingData[] = { static const struct SiS_LCDData XGI_ExtLCD1024x768x75Data[] = { {42, 25, 1536, 419, 1344, 806}, /* ; 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {48, 25, 1536, 369, 1344, 806}, /* ; 01 (320x350,640x350) */ {42, 25, 1536, 419, 1344, 806}, /* ; 02 (360x400,720x400) */ {48, 25, 1536, 369, 1344, 806}, /* ; 03 (720x350) */ @@ -500,7 +511,8 @@ static const struct SiS_LCDData XGI_ExtLCD1024x768x75Data[] = { static const struct SiS_LCDData XGI_CetLCD1024x768x75Data[] = { {1, 1, 1312, 800, 1312, 800}, /* ; 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {1, 1, 1312, 800, 1312, 800}, /* ; 01 (320x350,640x350) */ {1, 1, 1312, 800, 1312, 800}, /* ; 02 (360x400,720x400) */ {1, 1, 1312, 800, 1312, 800}, /* ; 03 (720x350) */ @@ -511,7 +523,8 @@ static const struct SiS_LCDData XGI_CetLCD1024x768x75Data[] = { static const struct SiS_LCDData xgifb_lcd_1280x1024x75[] = { {211, 60, 1024, 501, 1688, 1066}, /* ; 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {211, 60, 1024, 508, 1688, 1066}, /* ; 01 (320x350,640x350) */ {211, 60, 1024, 501, 1688, 1066}, /* ; 02 (360x400,720x400) */ {211, 60, 1024, 508, 1688, 1066}, /* ; 03 (720x350) */ @@ -525,7 +538,8 @@ static const struct SiS_LCDData xgifb_lcd_1280x1024x75[] = { static const struct SiS_LCDData XGI_NoScalingDatax75[] = { {1, 1, 800, 449, 800, 449}, /* ; 00 (320x200, 320x400, - 640x200, 640x400) */ + * 640x200, 640x400) + */ {1, 1, 800, 449, 800, 449}, /* ; 01 (320x350, 640x350) */ {1, 1, 900, 449, 900, 449}, /* ; 02 (360x400, 720x400) */ {1, 1, 900, 449, 900, 449}, /* ; 03 (720x350) */ @@ -732,7 +746,8 @@ static const struct XGI_LCDDesStruct XGI_StLCDDes1600x1200Data[] = { static const struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[] = { {9, 657, 448, 405, 96, 2}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {9, 657, 448, 355, 96, 2}, /* 01 (320x350,640x350) */ {9, 657, 448, 405, 96, 2}, /* 02 (360x400,720x400) */ {9, 657, 448, 355, 96, 2}, /* 03 (720x350) */ @@ -818,7 +833,8 @@ static const struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024x75Data[] = { /* Scaling LCD 75Hz */ static const struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[] = { {9, 657, 448, 405, 96, 2}, /* ; 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {9, 657, 448, 355, 96, 2}, /* ; 01 (320x350,640x350) */ {9, 738, 448, 405, 108, 2}, /* ; 02 (360x400,720x400) */ {9, 738, 448, 355, 108, 2}, /* ; 03 (720x350) */ @@ -873,7 +889,8 @@ static const struct SiS_TVData XGI_ExtNTSCData[] = { static const struct SiS_TVData XGI_St1HiTVData[] = { {1, 1, 892, 563, 690, 800, 0, 0, 0}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {1, 1, 892, 563, 690, 700, 0, 0, 0}, /* 01 (320x350,640x350) */ {1, 1, 1000, 563, 785, 800, 0, 0, 0}, /* 02 (360x400,720x400) */ {1, 1, 1000, 563, 785, 700, 0, 0, 0}, /* 03 (720x350) */ @@ -883,7 +900,8 @@ static const struct SiS_TVData XGI_St1HiTVData[] = { static const struct SiS_TVData XGI_St2HiTVData[] = { {3, 1, 840, 483, 1648, 960, 0x032, 0, 0}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {1, 1, 892, 563, 690, 700, 0, 0, 0}, /* 01 (320x350,640x350) */ {3, 1, 840, 483, 1648, 960, 0x032, 0, 0}, /* 02 (360x400,720x400) */ {1, 1, 1000, 563, 785, 700, 0, 0, 0}, /* 03 (720x350) */ @@ -893,7 +911,8 @@ static const struct SiS_TVData XGI_St2HiTVData[] = { static const struct SiS_TVData XGI_ExtHiTVData[] = { {6, 1, 840, 563, 1632, 960, 0, 0, 0}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {3, 1, 960, 563, 1632, 960, 0, 0, 0}, /* 01 (320x350,640x350) */ {3, 1, 840, 483, 1632, 960, 0, 0, 0}, /* 02 (360x400,720x400) */ {3, 1, 960, 563, 1632, 960, 0, 0, 0}, /* 03 (720x350) */ @@ -948,7 +967,8 @@ static const struct SiS_TVData XGI_StYPbPr525pData[] = { static const struct SiS_TVData XGI_ExtYPbPr750pData[] = { { 3, 1, 935, 470, 1130, 680, 50, 0, 0}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {24, 7, 935, 420, 1130, 680, 50, 0, 0}, /* 01 (320x350,640x350) */ { 3, 1, 935, 470, 1130, 680, 50, 0, 0}, /* 02 (360x400,720x400) */ {24, 7, 935, 420, 1130, 680, 50, 0, 0}, /* 03 (720x350) */ @@ -1269,7 +1289,8 @@ static const struct SiS_LVDSData XGI_LVDSNoScalingDatax75[] = { {1312, 800, 1312, 800}, /* ; 06 (1024x768x75Hz) */ {1688, 1066, 1688, 1066}, /* ; 07 (1280x1024x75Hz) */ {1688, 1066, 1688, 1066}, /* ; 08 (1400x1050x75Hz) - ;;[ycchen] 12/19/02 */ + * ;;[ycchen] 12/19/02 + */ {2160, 1250, 2160, 1250}, /* ; 09 (1600x1200x75Hz) */ {1688, 806, 1688, 806}, /* ; 0A (1280x768x75Hz) */ }; @@ -1364,7 +1385,8 @@ static const struct SiS_LVDSData XGI_LVDS1600x1200Des_1[] = { static const struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesData[] = { {0, 648, 448, 405, 96, 2}, /* 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {0, 648, 448, 355, 96, 2}, /* 01 (320x350,640x350) */ {0, 648, 448, 405, 96, 2}, /* 02 (360x400,720x400) */ {0, 648, 448, 355, 96, 2}, /* 03 (720x350) */ @@ -1435,7 +1457,8 @@ static const struct SiS_LVDSData XGI_LVDS1280x1024Des_2x75[] = { /* Scaling LCD 75Hz */ static const struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = { {0, 648, 448, 405, 96, 2}, /* ; 00 (320x200,320x400, - 640x200,640x400) */ + * 640x200,640x400) + */ {0, 648, 448, 355, 96, 2}, /* ; 01 (320x350,640x350) */ {0, 729, 448, 405, 108, 2}, /* ; 02 (360x400,720x400) */ {0, 729, 448, 355, 108, 2}, /* ; 03 (720x350) */ -- GitLab From 81108182bba96fcc738ddc912e9fcbb5afe01ef0 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 30 Mar 2016 19:48:22 -0400 Subject: [PATCH 0851/9938] staging/lustre/obdclass: limit lu_site hash table size Allocating a big hash table using the formula for osd does not really work for clients. We will create new hash table for each mount on a single client which is a lot of memory more than expected. This patch limits the hash table up to 8M which has 524288 entries Signed-off-by: Li Dongyang Reviewed-on: http://review.whamcloud.com/18048 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7689 Reviewed-by: Fan Yong Reviewed-by: Alex Zhuravlev Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 65a4746c89ca..69fdcee0ac52 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -935,7 +935,7 @@ static void lu_dev_add_linkage(struct lu_site *s, struct lu_device *d) * Initialize site \a s, with \a d as the top level device. */ #define LU_SITE_BITS_MIN 12 -#define LU_SITE_BITS_MAX 24 +#define LU_SITE_BITS_MAX 19 /** * total 256 buckets, we don't want too many buckets because: * - consume too much memory -- GitLab From 616387e86d531d1d29173aabb8adefb20d316d96 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 30 Mar 2016 19:48:23 -0400 Subject: [PATCH 0852/9938] staging/lustre: Get rid of CFS_PAGE_MASK CFS_PAGE_MASK is the same as PAGE_MASK, so get rid of it. We are replacing it with PAGE_MASK instead of PAGE_CACHE_MASK because PAGE_CACHE_* stuff is apparently going away. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/linux/linux-mem.h | 1 - .../lustre/lnet/libcfs/linux/linux-crypto.c | 2 +- .../staging/lustre/lnet/selftest/brw_test.c | 2 +- .../staging/lustre/lustre/llite/llite_mmap.c | 4 ++-- drivers/staging/lustre/lustre/llite/rw26.c | 8 +++---- drivers/staging/lustre/lustre/llite/vvp_io.c | 6 ++--- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 2 +- .../lustre/lustre/obdclass/class_obd.c | 2 +- .../lustre/lustre/obdecho/echo_client.c | 6 ++--- drivers/staging/lustre/lustre/osc/osc_cache.c | 4 ++-- .../staging/lustre/lustre/osc/osc_request.c | 24 +++++++++---------- .../staging/lustre/lustre/ptlrpc/sec_bulk.c | 2 +- .../staging/lustre/lustre/ptlrpc/sec_plain.c | 2 +- 13 files changed, 32 insertions(+), 33 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h index 0f2fd79e5ec8..448379b2a01e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h @@ -57,7 +57,6 @@ #include "../libcfs_cpu.h" #endif -#define CFS_PAGE_MASK (~((__u64)PAGE_CACHE_SIZE-1)) #define page_index(p) ((p)->index) #define memory_pressure_get() (current->flags & PF_MEMALLOC) diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 0715101c577c..84f9b7b47581 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -227,7 +227,7 @@ int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *hdesc, struct scatterlist sl; sg_init_table(&sl, 1); - sg_set_page(&sl, page, len, offset & ~CFS_PAGE_MASK); + sg_set_page(&sl, page, len, offset & ~PAGE_MASK); ahash_request_set_crypt(req, &sl, NULL, sl.length); return crypto_ahash_update(req); diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index b33c35694eb1..1988cee36751 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -457,7 +457,7 @@ brw_server_handle(struct srpc_server_rpc *rpc) if (!(reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN)) { /* compat with old version */ - if (reqst->brw_len & ~CFS_PAGE_MASK) { + if (reqst->brw_len & ~PAGE_MASK) { reply->brw_status = EINVAL; return 0; } diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 69445a9f2011..baccf9379ca7 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -57,10 +57,10 @@ void policy_from_vma(ldlm_policy_data_t *policy, struct vm_area_struct *vma, unsigned long addr, size_t count) { - policy->l_extent.start = ((addr - vma->vm_start) & CFS_PAGE_MASK) + + policy->l_extent.start = ((addr - vma->vm_start) & PAGE_MASK) + (vma->vm_pgoff << PAGE_CACHE_SHIFT); policy->l_extent.end = (policy->l_extent.start + count - 1) | - ~CFS_PAGE_MASK; + ~PAGE_MASK; } struct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr, diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 7a5db67bc680..3d7e64ee9824 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -376,7 +376,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, return -EBADF; /* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */ - if ((file_offset & ~CFS_PAGE_MASK) || (count & ~CFS_PAGE_MASK)) + if ((file_offset & ~PAGE_MASK) || (count & ~PAGE_MASK)) return -EINVAL; CDEBUG(D_VFSTRACE, @@ -386,7 +386,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, MAX_DIO_SIZE >> PAGE_CACHE_SHIFT); /* Check that all user buffers are aligned as well */ - if (iov_iter_alignment(iter) & ~CFS_PAGE_MASK) + if (iov_iter_alignment(iter) & ~PAGE_MASK) return -EINVAL; env = cl_env_get(&refcheck); @@ -435,8 +435,8 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, size > (PAGE_CACHE_SIZE / sizeof(*pages)) * PAGE_CACHE_SIZE) { size = ((((size / 2) - 1) | - ~CFS_PAGE_MASK) + 1) & - CFS_PAGE_MASK; + ~PAGE_MASK) + 1) & + PAGE_MASK; CDEBUG(D_VFSTRACE, "DIO size now %lu\n", size); continue; diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index fb0c26ee7ff3..984699a32c69 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -234,8 +234,8 @@ static int vvp_mmap_locks(const struct lu_env *env, if (count == 0) continue; - count += addr & (~CFS_PAGE_MASK); - addr &= CFS_PAGE_MASK; + count += addr & (~PAGE_MASK); + addr &= PAGE_MASK; down_read(&mm->mmap_sem); while ((vma = our_vma(mm, addr, count)) != NULL) { @@ -1043,7 +1043,7 @@ static int vvp_io_commit_write(const struct lu_env *env, to = PAGE_CACHE_SIZE; need_clip = false; } else if (last_index == pg->cp_index) { - int size_to = i_size_read(inode) & ~CFS_PAGE_MASK; + int size_to = i_size_read(inode) & ~PAGE_MASK; if (to < size_to) to = size_to; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 0f776cf8a5aa..e3a721670ca1 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2071,7 +2071,7 @@ static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs) dp = (struct lu_dirpage *)((char *)dp + LU_PAGE_SIZE); /* Check if we've reached the end of the CFS_PAGE. */ - if (!((unsigned long)dp & ~CFS_PAGE_MASK)) + if (!((unsigned long)dp & ~PAGE_MASK)) break; /* Save the hash and flags of this lu_dirpage. */ diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 1a938e1376f9..d9844ba8b9be 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -461,7 +461,7 @@ static int obd_init_checks(void) CWARN("LPD64 wrong length! strlen(%s)=%d != 2\n", buf, len); ret = -EINVAL; } - if ((u64val & ~CFS_PAGE_MASK) >= PAGE_CACHE_SIZE) { + if ((u64val & ~PAGE_MASK) >= PAGE_CACHE_SIZE) { CWARN("mask failed: u64val %llu >= %llu\n", u64val, (__u64)PAGE_CACHE_SIZE); ret = -EINVAL; diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 64ffe243f870..33ce0c80e4b2 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1119,7 +1119,7 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, int rc; int i; - LASSERT((offset & ~CFS_PAGE_MASK) == 0); + LASSERT((offset & ~PAGE_MASK) == 0); LASSERT(ed->ed_next); env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -1387,7 +1387,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, LASSERT(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ); if (count <= 0 || - (count & (~CFS_PAGE_MASK)) != 0) + (count & (~PAGE_MASK)) != 0) return -EINVAL; /* XXX think again with misaligned I/O */ @@ -1470,7 +1470,7 @@ static int echo_client_prep_commit(const struct lu_env *env, u64 npages, tot_pages; int i, ret = 0, brw_flags = 0; - if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0) + if (count <= 0 || (count & (~PAGE_MASK)) != 0) return -EINVAL; npages = batch >> PAGE_CACHE_SHIFT; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 63363111380c..3cfd2b09f760 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -877,7 +877,7 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, * span a whole chunk on the OST side, or our accounting goes * wrong. Should match the code in filter_grant_check. */ - int offset = oap->oap_page_off & ~CFS_PAGE_MASK; + int offset = oap->oap_page_off & ~PAGE_MASK; int count = oap->oap_count + (offset & (blocksize - 1)); int end = (offset + oap->oap_count) & (blocksize - 1); @@ -2238,7 +2238,7 @@ int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops, oap->oap_page = page; oap->oap_obj_off = offset; - LASSERT(!(offset & ~CFS_PAGE_MASK)); + LASSERT(!(offset & ~PAGE_MASK)); if (!client_is_remote(exp) && capable(CFS_CAP_SYS_RESOURCE)) oap->oap_brw_flags = OBD_BRW_NOQUOTA; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index ec0287feb3ce..850d5dd49831 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1082,7 +1082,7 @@ static void handle_short_read(int nob_read, u32 page_count, if (pga[i]->count > nob_read) { /* EOF inside this page */ ptr = kmap(pga[i]->pg) + - (pga[i]->off & ~CFS_PAGE_MASK); + (pga[i]->off & ~PAGE_MASK); memset(ptr + nob_read, 0, pga[i]->count - nob_read); kunmap(pga[i]->pg); page_count--; @@ -1097,7 +1097,7 @@ static void handle_short_read(int nob_read, u32 page_count, /* zero remaining pages */ while (page_count-- > 0) { - ptr = kmap(pga[i]->pg) + (pga[i]->off & ~CFS_PAGE_MASK); + ptr = kmap(pga[i]->pg) + (pga[i]->off & ~PAGE_MASK); memset(ptr, 0, pga[i]->count); kunmap(pga[i]->pg); i++; @@ -1188,20 +1188,20 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, if (i == 0 && opc == OST_READ && OBD_FAIL_CHECK(OBD_FAIL_OSC_CHECKSUM_RECEIVE)) { unsigned char *ptr = kmap(pga[i]->pg); - int off = pga[i]->off & ~CFS_PAGE_MASK; + int off = pga[i]->off & ~PAGE_MASK; memcpy(ptr + off, "bad1", min(4, nob)); kunmap(pga[i]->pg); } cfs_crypto_hash_update_page(hdesc, pga[i]->pg, - pga[i]->off & ~CFS_PAGE_MASK, + pga[i]->off & ~PAGE_MASK, count); CDEBUG(D_PAGE, "page %p map %p index %lu flags %lx count %u priv %0lx: off %d\n", pga[i]->pg, pga[i]->pg->mapping, pga[i]->pg->index, (long)pga[i]->pg->flags, page_count(pga[i]->pg), page_private(pga[i]->pg), - (int)(pga[i]->off & ~CFS_PAGE_MASK)); + (int)(pga[i]->off & ~PAGE_MASK)); nob -= pga[i]->count; pg_count--; @@ -1309,7 +1309,7 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli, pg_prev = pga[0]; for (requested_nob = i = 0; i < page_count; i++, niobuf++) { struct brw_page *pg = pga[i]; - int poff = pg->off & ~CFS_PAGE_MASK; + int poff = pg->off & ~PAGE_MASK; LASSERT(pg->count > 0); /* make sure there is no gap in the middle of page array */ @@ -2227,8 +2227,8 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, /* Filesystem lock extents are extended to page boundaries so that * dealing with the page cache is a little smoother. */ - policy->l_extent.start -= policy->l_extent.start & ~CFS_PAGE_MASK; - policy->l_extent.end |= ~CFS_PAGE_MASK; + policy->l_extent.start -= policy->l_extent.start & ~PAGE_MASK; + policy->l_extent.end |= ~PAGE_MASK; /* * kms is not valid when either object is completely fresh (so that no @@ -2378,8 +2378,8 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, /* Filesystem lock extents are extended to page boundaries so that * dealing with the page cache is a little smoother */ - policy->l_extent.start -= policy->l_extent.start & ~CFS_PAGE_MASK; - policy->l_extent.end |= ~CFS_PAGE_MASK; + policy->l_extent.start -= policy->l_extent.start & ~PAGE_MASK; + policy->l_extent.end |= ~PAGE_MASK; /* Next, search for already existing extent locks that will cover us */ /* If we're trying to read, we also search for an existing PW lock. The @@ -2784,7 +2784,7 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp, goto skip_locking; policy.l_extent.start = fm_key->fiemap.fm_start & - CFS_PAGE_MASK; + PAGE_MASK; if (OBD_OBJECT_EOF - fm_key->fiemap.fm_length <= fm_key->fiemap.fm_start + PAGE_CACHE_SIZE - 1) @@ -2792,7 +2792,7 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp, else policy.l_extent.end = (fm_key->fiemap.fm_start + fm_key->fiemap.fm_length + - PAGE_CACHE_SIZE - 1) & CFS_PAGE_MASK; + PAGE_CACHE_SIZE - 1) & PAGE_MASK; ostid_build_res_name(&fm_key->oa.o_oi, &res_id); mode = ldlm_lock_match(exp->exp_obd->obd_namespace, diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 54a0c1ff7b20..33d141149afd 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -527,7 +527,7 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, for (i = 0; i < desc->bd_iov_count; i++) { cfs_crypto_hash_update_page(hdesc, desc->bd_iov[i].kiov_page, - desc->bd_iov[i].kiov_offset & ~CFS_PAGE_MASK, + desc->bd_iov[i].kiov_offset & ~PAGE_MASK, desc->bd_iov[i].kiov_len); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index 6276bf59c3aa..37c9f4c453de 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -162,7 +162,7 @@ static void corrupt_bulk_data(struct ptlrpc_bulk_desc *desc) continue; ptr = kmap(desc->bd_iov[i].kiov_page); - off = desc->bd_iov[i].kiov_offset & ~CFS_PAGE_MASK; + off = desc->bd_iov[i].kiov_offset & ~PAGE_MASK; ptr[off] ^= 0x1; kunmap(desc->bd_iov[i].kiov_page); return; -- GitLab From a7d516d6e9b5ac2db87f5b98c67e599f95d3e512 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:24 -0400 Subject: [PATCH 0853/9938] staging/lustre: merge lclient/*.c into llite/ Separate lclient was necessary to be shared between different client implementations, make no sense to have them separate in Linux kernel. Signed-off-by: John L. Hammond Based-on: http://review.whamcloud.com/10171 Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/Makefile | 2 +- .../lustre/{lclient => llite}/glimpse.c | 15 ++-- .../lustre/{lclient => llite}/lcommon_cl.c | 72 ++++++++++--------- .../lustre/{lclient => llite}/lcommon_misc.c | 0 4 files changed, 49 insertions(+), 40 deletions(-) rename drivers/staging/lustre/lustre/{lclient => llite}/glimpse.c (98%) rename drivers/staging/lustre/lustre/{lclient => llite}/lcommon_cl.c (96%) rename drivers/staging/lustre/lustre/{lclient => llite}/lcommon_misc.c (100%) diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index 9ac29e718da3..24085e2624b4 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -4,7 +4,7 @@ lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ rw.o namei.o symlink.o llite_mmap.o \ xattr.o xattr_cache.o remote_perm.o llite_rmtacl.o \ rw26.o super25.o statahead.o \ - ../lclient/glimpse.o ../lclient/lcommon_cl.o ../lclient/lcommon_misc.o \ + glimpse.o lcommon_cl.o lcommon_misc.o \ vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o lproc_llite.o llite_lloop-y := lloop.o diff --git a/drivers/staging/lustre/lustre/lclient/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c similarity index 98% rename from drivers/staging/lustre/lustre/lclient/glimpse.c rename to drivers/staging/lustre/lustre/llite/glimpse.c index c4e8a0878ac8..f235f3557e2a 100644 --- a/drivers/staging/lustre/lustre/lclient/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -95,7 +95,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, result = 0; if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) { - CDEBUG(D_DLMTRACE, "Glimpsing inode "DFID"\n", PFID(fid)); + CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid)); if (lli->lli_has_smd) { /* NOTE: this looks like DLM lock request, but it may * not be one. Due to CEF_ASYNC flag (translated @@ -179,10 +179,12 @@ static int cl_io_get(struct inode *inode, struct lu_env **envout, *envout = env; *ioout = io; result = 1; - } else + } else { result = PTR_ERR(env); - } else + } + } else { result = 0; + } return result; } @@ -247,9 +249,9 @@ int cl_local_size(struct inode *inode) clob = io->ci_obj; result = cl_io_init(env, io, CIT_MISC, clob); - if (result > 0) + if (result > 0) { result = io->ci_result; - else if (result == 0) { + } else if (result == 0) { cti = ccc_env_info(env); descr = &cti->cti_descr; @@ -261,8 +263,9 @@ int cl_local_size(struct inode *inode) cl_unuse(env, lock); cl_lock_release(env, lock, "localsize", current); result = 0; - } else + } else { result = -ENODATA; + } } cl_io_fini(env, io); cl_env_put(env, &refcheck); diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c similarity index 96% rename from drivers/staging/lustre/lustre/lclient/lcommon_cl.c rename to drivers/staging/lustre/lustre/llite/lcommon_cl.c index aced41ab93a1..065b0f20e95d 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -123,7 +123,7 @@ void *ccc_key_init(const struct lu_context *ctx, struct lu_context_key *key) } void ccc_key_fini(const struct lu_context *ctx, - struct lu_context_key *key, void *data) + struct lu_context_key *key, void *data) { struct ccc_thread_info *info = data; @@ -131,7 +131,7 @@ void ccc_key_fini(const struct lu_context *ctx, } void *ccc_session_key_init(const struct lu_context *ctx, - struct lu_context_key *key) + struct lu_context_key *key) { struct ccc_session *session; @@ -142,7 +142,7 @@ void *ccc_session_key_init(const struct lu_context *ctx, } void ccc_session_key_fini(const struct lu_context *ctx, - struct lu_context_key *key, void *data) + struct lu_context_key *key, void *data) { struct ccc_session *session = data; @@ -165,7 +165,7 @@ struct lu_context_key ccc_session_key = { /* LU_TYPE_INIT_FINI(ccc, &ccc_key, &ccc_session_key); */ int ccc_device_init(const struct lu_env *env, struct lu_device *d, - const char *name, struct lu_device *next) + const char *name, struct lu_device *next) { struct ccc_device *vdv; int rc; @@ -185,7 +185,7 @@ int ccc_device_init(const struct lu_env *env, struct lu_device *d, } struct lu_device *ccc_device_fini(const struct lu_env *env, - struct lu_device *d) + struct lu_device *d) { return cl2lu_dev(lu2ccc_dev(d)->cdv_next); } @@ -213,15 +213,16 @@ struct lu_device *ccc_device_alloc(const struct lu_env *env, site = kzalloc(sizeof(*site), GFP_NOFS); if (site) { rc = cl_site_init(site, &vdv->cdv_cl); - if (rc == 0) + if (rc == 0) { rc = lu_site_init_finish(&site->cs_lu); - else { + } else { LASSERT(!lud->ld_site); CERROR("Cannot init lu_site, rc %d.\n", rc); kfree(site); } - } else + } else { rc = -ENOMEM; + } if (rc != 0) { ccc_device_free(env, lud); lud = ERR_PTR(rc); @@ -230,7 +231,7 @@ struct lu_device *ccc_device_alloc(const struct lu_env *env, } struct lu_device *ccc_device_free(const struct lu_env *env, - struct lu_device *d) + struct lu_device *d) { struct ccc_device *vdv = lu2ccc_dev(d); struct cl_site *site = lu2cl_site(d->ld_site); @@ -246,7 +247,7 @@ struct lu_device *ccc_device_free(const struct lu_env *env, } int ccc_req_init(const struct lu_env *env, struct cl_device *dev, - struct cl_req *req) + struct cl_req *req) { struct ccc_req *vrq; int result; @@ -255,8 +256,9 @@ int ccc_req_init(const struct lu_env *env, struct cl_device *dev, if (vrq) { cl_req_slice_add(req, &vrq->crq_cl, dev, &ccc_req_ops); result = 0; - } else + } else { result = -ENOMEM; + } return result; } @@ -287,7 +289,7 @@ int ccc_global_init(struct lu_device_type *device_type) goto out_kmem; ccc_inode_fini_env = cl_env_alloc(&dummy_refcheck, - LCT_REMEMBER|LCT_NOREF); + LCT_REMEMBER | LCT_NOREF); if (IS_ERR(ccc_inode_fini_env)) { result = PTR_ERR(ccc_inode_fini_env); goto out_device; @@ -339,14 +341,15 @@ struct lu_object *ccc_object_alloc(const struct lu_env *env, vob->cob_cl.co_ops = clops; obj->lo_ops = luops; - } else + } else { obj = NULL; + } return obj; } int ccc_object_init0(const struct lu_env *env, - struct ccc_object *vob, - const struct cl_object_conf *conf) + struct ccc_object *vob, + const struct cl_object_conf *conf) { vob->cob_inode = conf->coc_inode; vob->cob_transient_pages = 0; @@ -355,7 +358,7 @@ int ccc_object_init0(const struct lu_env *env, } int ccc_object_init(const struct lu_env *env, struct lu_object *obj, - const struct lu_object_conf *conf) + const struct lu_object_conf *conf) { struct ccc_device *dev = lu2ccc_dev(obj->lo_dev); struct ccc_object *vob = lu2ccc(obj); @@ -372,8 +375,9 @@ int ccc_object_init(const struct lu_env *env, struct lu_object *obj, INIT_LIST_HEAD(&vob->cob_pending_list); lu_object_add(obj, below); result = ccc_object_init0(env, vob, cconf); - } else + } else { result = -ENOMEM; + } return result; } @@ -400,8 +404,9 @@ int ccc_lock_init(const struct lu_env *env, if (clk) { cl_lock_slice_add(lock, &clk->clk_cl, obj, lkops); result = 0; - } else + } else { result = -ENOMEM; + } return result; } @@ -446,7 +451,7 @@ static void ccc_object_size_unlock(struct cl_object *obj) */ struct page *ccc_page_vmpage(const struct lu_env *env, - const struct cl_page_slice *slice) + const struct cl_page_slice *slice) { return cl2vm_page(slice); } @@ -463,9 +468,9 @@ int ccc_page_is_under_lock(const struct lu_env *env, if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE || io->ci_type == CIT_FAULT) { - if (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED) + if (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED) { result = -EBUSY; - else { + } else { desc->cld_start = page->cp_index; desc->cld_end = page->cp_index; desc->cld_obj = page->cp_obj; @@ -473,8 +478,9 @@ int ccc_page_is_under_lock(const struct lu_env *env, result = cl_queue_match(&io->ci_lockset.cls_done, desc) ? -EBUSY : 0; } - } else + } else { result = 0; + } return result; } @@ -488,8 +494,8 @@ int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice) } int ccc_transient_page_prep(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *unused) + const struct cl_page_slice *slice, + struct cl_io *unused) { /* transient page should always be sent. */ return 0; @@ -780,11 +786,9 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, */ if (cl_isize_read(inode) < kms) { cl_isize_write_nolock(inode, kms); - CDEBUG(D_VFSTRACE, - DFID" updating i_size %llu\n", - PFID(lu_object_fid(&obj->co_lu)), - (__u64)cl_isize_read(inode)); - + CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n", + PFID(lu_object_fid(&obj->co_lu)), + (__u64)cl_isize_read(inode)); } } ccc_object_size_unlock(obj); @@ -1044,8 +1048,9 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) lli->lli_clob = clob; lli->lli_has_smd = lsm_has_objects(md->lsm); lu_object_ref_add(&clob->co_lu, "inode", inode); - } else + } else { result = PTR_ERR(clob); + } } else { result = cl_conf_set(env, lli->lli_clob, &conf); } @@ -1053,7 +1058,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) cl_env_put(env, &refcheck); if (result != 0) - CERROR("Failure to initialize cl object "DFID": %d\n", + CERROR("Failure to initialize cl object " DFID ": %d\n", PFID(fid), result); return result; } @@ -1127,8 +1132,9 @@ void cl_inode_fini(struct inode *inode) if (emergency) { cl_env_unplant(ccc_inode_fini_env, &refcheck); mutex_unlock(&ccc_inode_fini_guard); - } else + } else { cl_env_put(env, &refcheck); + } cl_env_reexit(cookie); } } @@ -1145,7 +1151,7 @@ __u16 ll_dirent_type_get(struct lu_dirent *ent) int len = 0; if (le32_to_cpu(ent->lde_attrs) & LUDA_TYPE) { - const unsigned align = sizeof(struct luda_type) - 1; + const unsigned int align = sizeof(struct luda_type) - 1; len = le16_to_cpu(ent->lde_namelen); len = (len + align) & ~align; diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c similarity index 100% rename from drivers/staging/lustre/lustre/lclient/lcommon_misc.c rename to drivers/staging/lustre/lustre/llite/lcommon_misc.c -- GitLab From 26f98e82e7ef3e1ecad0a0b83020dd19fc9ff822 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:25 -0400 Subject: [PATCH 0854/9938] staging/lustre: Reintroduce global env list This reverts a patch that was merged before lustre client was introduced into the stagign tree, so it's not in the history. The performance dropped a lot when memory reclaim process kicked in as ll_releasepage() was called to destroy lustre pages. It turned out that big overhead to allocate cl_env and keys on the fly so we have to revert this patch. The original problem for the reverted patch would be solved in a follow on patch instead. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/7888 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Niu Yawei Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 1 + .../lustre/lustre/llite/lcommon_misc.c | 3 +- .../staging/lustre/lustre/llite/llite_lib.c | 2 + .../lustre/lustre/obdclass/cl_object.c | 90 +++++++++++++++++-- .../lustre/lustre/obdclass/lu_object.c | 2 + 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index fb971ded5a1b..e611f790285a 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -3241,6 +3241,7 @@ void *cl_env_reenter(void); void cl_env_reexit(void *cookie); void cl_env_implant(struct lu_env *env, int *refcheck); void cl_env_unplant(struct lu_env *env, int *refcheck); +unsigned int cl_env_cache_purge(unsigned int nr); /** @} cl_env */ diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index d80bcedd78d1..f68c3687b1d9 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -146,10 +146,11 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, rc = cl_io_init(env, io, CIT_MISC, io->ci_obj); if (rc) { + cl_io_fini(env, io); + cl_env_put(env, &refcheck); /* Does not make sense to take GL for released layout */ if (rc > 0) rc = -ENOTSUPP; - cl_env_put(env, &refcheck); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 6d6bb33e3655..673d31e044dd 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -999,6 +999,8 @@ void ll_put_super(struct super_block *sb) lustre_common_put_super(sb); + cl_env_cache_purge(~0); + module_put(THIS_MODULE); } /* client_put_super */ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 43e299d4d416..0772706dbffc 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -492,6 +492,13 @@ EXPORT_SYMBOL(cl_site_stats_print); * bz20044, bz22683. */ +static LIST_HEAD(cl_envs); +static unsigned int cl_envs_cached_nr; +static unsigned int cl_envs_cached_max = 128; /* XXX: prototype: arbitrary limit + * for now. + */ +static DEFINE_SPINLOCK(cl_envs_guard); + struct cl_env { void *ce_magic; struct lu_env ce_lu; @@ -697,6 +704,39 @@ static void cl_env_fini(struct cl_env *cle) kmem_cache_free(cl_env_kmem, cle); } +static struct lu_env *cl_env_obtain(void *debug) +{ + struct cl_env *cle; + struct lu_env *env; + + spin_lock(&cl_envs_guard); + LASSERT(equi(cl_envs_cached_nr == 0, list_empty(&cl_envs))); + if (cl_envs_cached_nr > 0) { + int rc; + + cle = container_of(cl_envs.next, struct cl_env, ce_linkage); + list_del_init(&cle->ce_linkage); + cl_envs_cached_nr--; + spin_unlock(&cl_envs_guard); + + env = &cle->ce_lu; + rc = lu_env_refill(env); + if (rc == 0) { + cl_env_init0(cle, debug); + lu_context_enter(&env->le_ctx); + lu_context_enter(&cle->ce_ses); + } else { + cl_env_fini(cle); + env = ERR_PTR(rc); + } + } else { + spin_unlock(&cl_envs_guard); + env = cl_env_new(lu_context_tags_default, + lu_session_tags_default, debug); + } + return env; +} + static inline struct cl_env *cl_env_container(struct lu_env *env) { return container_of(env, struct cl_env, ce_lu); @@ -727,6 +767,8 @@ static struct lu_env *cl_env_peek(int *refcheck) * Returns lu_env: if there already is an environment associated with the * current thread, it is returned, otherwise, new environment is allocated. * + * Allocations are amortized through the global cache of environments. + * * \param refcheck pointer to a counter used to detect environment leaks. In * the usual case cl_env_get() and cl_env_put() are called in the same lexical * scope and pointer to the same integer is passed as \a refcheck. This is @@ -740,10 +782,7 @@ struct lu_env *cl_env_get(int *refcheck) env = cl_env_peek(refcheck); if (!env) { - env = cl_env_new(lu_context_tags_default, - lu_session_tags_default, - __builtin_return_address(0)); - + env = cl_env_obtain(__builtin_return_address(0)); if (!IS_ERR(env)) { struct cl_env *cle; @@ -786,6 +825,32 @@ static void cl_env_exit(struct cl_env *cle) lu_context_exit(&cle->ce_ses); } +/** + * Finalizes and frees a given number of cached environments. This is done to + * (1) free some memory (not currently hooked into VM), or (2) release + * references to modules. + */ +unsigned int cl_env_cache_purge(unsigned int nr) +{ + struct cl_env *cle; + + spin_lock(&cl_envs_guard); + for (; !list_empty(&cl_envs) && nr > 0; --nr) { + cle = container_of(cl_envs.next, struct cl_env, ce_linkage); + list_del_init(&cle->ce_linkage); + LASSERT(cl_envs_cached_nr > 0); + cl_envs_cached_nr--; + spin_unlock(&cl_envs_guard); + + cl_env_fini(cle); + spin_lock(&cl_envs_guard); + } + LASSERT(equi(cl_envs_cached_nr == 0, list_empty(&cl_envs))); + spin_unlock(&cl_envs_guard); + return nr; +} +EXPORT_SYMBOL(cl_env_cache_purge); + /** * Release an environment. * @@ -808,7 +873,22 @@ void cl_env_put(struct lu_env *env, int *refcheck) cl_env_detach(cle); cle->ce_debug = NULL; cl_env_exit(cle); - cl_env_fini(cle); + /* + * Don't bother to take a lock here. + * + * Return environment to the cache only when it was allocated + * with the standard tags. + */ + if (cl_envs_cached_nr < cl_envs_cached_max && + (env->le_ctx.lc_tags & ~LCT_HAS_EXIT) == LCT_CL_THREAD && + (env->le_ses->lc_tags & ~LCT_HAS_EXIT) == LCT_SESSION) { + spin_lock(&cl_envs_guard); + list_add(&cle->ce_linkage, &cl_envs); + cl_envs_cached_nr++; + spin_unlock(&cl_envs_guard); + } else { + cl_env_fini(cle); + } } } EXPORT_SYMBOL(cl_env_put); diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 69fdcee0ac52..770d5bd742d8 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -55,6 +55,7 @@ #include "../include/lustre_disk.h" #include "../include/lustre_fid.h" #include "../include/lu_object.h" +#include "../include/cl_object.h" #include "../include/lu_ref.h" #include @@ -1468,6 +1469,7 @@ void lu_context_key_quiesce(struct lu_context_key *key) /* * XXX layering violation. */ + cl_env_cache_purge(~0); key->lct_tags |= LCT_QUIESCENT; /* * XXX memory barrier has to go here. -- GitLab From 5196e42c372fc33551c836d9d6d0a0883b4d2d19 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:26 -0400 Subject: [PATCH 0855/9938] staging/lustre/osc: Adjustment on osc LRU for performance Add and discard pages from LRU in batch. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/7890 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Niu Yawei Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/llite/llite_lib.c | 5 +- drivers/staging/lustre/lustre/osc/lproc_osc.c | 2 +- drivers/staging/lustre/lustre/osc/osc_cache.c | 2 + .../lustre/lustre/osc/osc_cl_internal.h | 26 +- .../staging/lustre/lustre/osc/osc_internal.h | 3 +- drivers/staging/lustre/lustre/osc/osc_io.c | 51 +++ drivers/staging/lustre/lustre/osc/osc_page.c | 301 ++++++++++-------- .../staging/lustre/lustre/osc/osc_request.c | 2 +- 8 files changed, 235 insertions(+), 157 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 673d31e044dd..a4401f297d1c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -85,10 +85,7 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb) si_meminfo(&si); pages = si.totalram - si.totalhigh; - if (pages >> (20 - PAGE_CACHE_SHIFT) < 512) - lru_page_max = pages / 2; - else - lru_page_max = (pages / 4) * 3; + lru_page_max = pages / 2; /* initialize lru data */ atomic_set(&sbi->ll_cache.ccc_users, 0); diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 57c43c506ef2..3eff12c073d3 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -223,7 +223,7 @@ static ssize_t osc_cached_mb_seq_write(struct file *file, rc = atomic_read(&cli->cl_lru_in_list) - pages_number; if (rc > 0) - (void)osc_lru_shrink(cli, rc); + (void)osc_lru_shrink(cli, rc, true); return count; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 3cfd2b09f760..6196c3bc2da7 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -856,6 +856,8 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, ext->oe_rc = rc ?: ext->oe_nr_pages; EASSERT(ergo(rc == 0, ext->oe_state == OES_RPC), ext); + + osc_lru_add_batch(cli, &ext->oe_pages); list_for_each_entry_safe(oap, tmp, &ext->oe_pages, oap_pending_item) { list_del_init(&oap->oap_rpc_item); list_del_init(&oap->oap_pending_item); diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index d55d04d0428b..f5168486e1d9 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -77,6 +77,8 @@ struct osc_io { */ struct osc_extent *oi_trunc; + int oi_lru_reserved; + struct obd_info oi_info; struct obdo oi_oa; struct osc_async_cbargs { @@ -100,7 +102,7 @@ struct osc_session { struct osc_io os_io; }; -#define OTI_PVEC_SIZE 64 +#define OTI_PVEC_SIZE 256 struct osc_thread_info { struct ldlm_res_id oti_resname; ldlm_policy_data_t oti_policy; @@ -369,18 +371,15 @@ struct osc_page { * Set if the page must be transferred with OBD_BRW_SRVLOCK. */ ops_srvlock:1; - union { - /** - * lru page list. ops_inflight and ops_lru are exclusive so - * that they can share the same data. - */ - struct list_head ops_lru; - /** - * Linkage into a per-osc_object list of pages in flight. For - * debugging. - */ - struct list_head ops_inflight; - }; + /** + * lru page list. See osc_lru_{del|use}() in osc_page.c for usage. + */ + struct list_head ops_lru; + /** + * Linkage into a per-osc_object list of pages in flight. For + * debugging. + */ + struct list_head ops_inflight; /** * Thread that submitted this page for transfer. For debugging. */ @@ -432,6 +431,7 @@ void osc_index2policy (ldlm_policy_data_t *policy, const struct cl_object *obj, int osc_lvb_print (const struct lu_env *env, void *cookie, lu_printer_t p, const struct ost_lvb *lvb); +void osc_lru_add_batch(struct client_obd *cli, struct list_head *list); void osc_page_submit(const struct lu_env *env, struct osc_page *opg, enum cl_req_type crt, int brw_flags); int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops); diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index ea695c2099ee..ec12962d8dcc 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -130,7 +130,8 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *cfg); int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, struct list_head *ext_list, int cmd); -int osc_lru_shrink(struct client_obd *cli, int target); +int osc_lru_shrink(struct client_obd *cli, int target, bool force); +int osc_lru_reclaim(struct client_obd *cli); extern spinlock_t osc_ast_guard; diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 6bd0a45d8b06..a0fa5339c4d3 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -308,6 +308,55 @@ static int osc_io_commit_write(const struct lu_env *env, return 0; } +static int osc_io_rw_iter_init(const struct lu_env *env, + const struct cl_io_slice *ios) +{ + struct cl_io *io = ios->cis_io; + struct osc_io *oio = osc_env_io(env); + struct osc_object *osc = cl2osc(ios->cis_obj); + struct client_obd *cli = osc_cli(osc); + unsigned long c; + unsigned int npages; + unsigned int max_pages; + + if (cl_io_is_append(io)) + return 0; + + npages = io->u.ci_rw.crw_count >> PAGE_CACHE_SHIFT; + if (io->u.ci_rw.crw_pos & ~PAGE_MASK) + ++npages; + + max_pages = cli->cl_max_pages_per_rpc * cli->cl_max_rpcs_in_flight; + if (npages > max_pages) + npages = max_pages; + + c = atomic_read(cli->cl_lru_left); + if (c < npages && osc_lru_reclaim(cli) > 0) + c = atomic_read(cli->cl_lru_left); + while (c >= npages) { + if (c == atomic_cmpxchg(cli->cl_lru_left, c, c - npages)) { + oio->oi_lru_reserved = npages; + break; + } + c = atomic_read(cli->cl_lru_left); + } + + return 0; +} + +static void osc_io_rw_iter_fini(const struct lu_env *env, + const struct cl_io_slice *ios) +{ + struct osc_io *oio = osc_env_io(env); + struct osc_object *osc = cl2osc(ios->cis_obj); + struct client_obd *cli = osc_cli(osc); + + if (oio->oi_lru_reserved > 0) { + atomic_add(oio->oi_lru_reserved, cli->cl_lru_left); + oio->oi_lru_reserved = 0; + } +} + static int osc_io_fault_start(const struct lu_env *env, const struct cl_io_slice *ios) { @@ -650,6 +699,8 @@ static const struct cl_io_operations osc_io_ops = { .cio_fini = osc_io_fini }, [CIT_WRITE] = { + .cio_iter_init = osc_io_rw_iter_init, + .cio_iter_fini = osc_io_rw_iter_fini, .cio_start = osc_io_write_start, .cio_end = osc_io_end, .cio_fini = osc_io_fini diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index d720b1a1c18c..a60b783a761e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -42,8 +42,8 @@ #include "osc_cl_internal.h" -static void osc_lru_del(struct client_obd *cli, struct osc_page *opg, bool del); -static void osc_lru_add(struct client_obd *cli, struct osc_page *opg); +static void osc_lru_del(struct client_obd *cli, struct osc_page *opg); +static void osc_lru_use(struct client_obd *cli, struct osc_page *opg); static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, struct osc_page *opg); @@ -104,10 +104,7 @@ static void osc_page_transfer_add(const struct lu_env *env, { struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj); - /* ops_lru and ops_inflight share the same field, so take it from LRU - * first and then use it as inflight. - */ - osc_lru_del(osc_cli(obj), opg, false); + osc_lru_use(osc_cli(obj), opg); spin_lock(&obj->oo_seatbelt); list_add(&opg->ops_inflight, &obj->oo_inflight[crt]); @@ -222,21 +219,15 @@ static void osc_page_completion_read(const struct lu_env *env, int ioret) { struct osc_page *opg = cl2osc_page(slice); - struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj); if (likely(opg->ops_lock)) osc_page_putref_lock(env, opg); - osc_lru_add(osc_cli(obj), opg); } static void osc_page_completion_write(const struct lu_env *env, const struct cl_page_slice *slice, int ioret) { - struct osc_page *opg = cl2osc_page(slice); - struct osc_object *obj = cl2osc(slice->cpl_obj); - - osc_lru_add(osc_cli(obj), opg); } static int osc_page_fail(const struct lu_env *env, @@ -334,7 +325,7 @@ static void osc_page_delete(const struct lu_env *env, } spin_unlock(&obj->oo_seatbelt); - osc_lru_del(osc_cli(obj), opg, true); + osc_lru_del(osc_cli(obj), opg); } static void osc_page_clip(const struct lu_env *env, @@ -483,13 +474,12 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg, */ static DECLARE_WAIT_QUEUE_HEAD(osc_lru_waitq); -static atomic_t osc_lru_waiters = ATOMIC_INIT(0); /* LRU pages are freed in batch mode. OSC should at least free this * number of pages to avoid running out of LRU budget, and.. */ static const int lru_shrink_min = 2 << (20 - PAGE_CACHE_SHIFT); /* 2M */ /* free this number at most otherwise it will take too long time to finish. */ -static const int lru_shrink_max = 32 << (20 - PAGE_CACHE_SHIFT); /* 32M */ +static const int lru_shrink_max = 8 << (20 - PAGE_CACHE_SHIFT); /* 8M */ /* Check if we can free LRU slots from this OSC. If there exists LRU waiters, * we should free slots aggressively. In this way, slots are freed in a steady @@ -500,62 +490,127 @@ static const int lru_shrink_max = 32 << (20 - PAGE_CACHE_SHIFT); /* 32M */ static int osc_cache_too_much(struct client_obd *cli) { struct cl_client_cache *cache = cli->cl_cache; - int pages = atomic_read(&cli->cl_lru_in_list) >> 1; + int pages = atomic_read(&cli->cl_lru_in_list); + unsigned long budget; - if (atomic_read(&osc_lru_waiters) > 0 && - atomic_read(cli->cl_lru_left) < lru_shrink_max) - /* drop lru pages aggressively */ - return min(pages, lru_shrink_max); + budget = cache->ccc_lru_max / atomic_read(&cache->ccc_users); /* if it's going to run out LRU slots, we should free some, but not * too much to maintain fairness among OSCs. */ if (atomic_read(cli->cl_lru_left) < cache->ccc_lru_max >> 4) { - unsigned long tmp; + if (pages >= budget) + return lru_shrink_max; + else if (pages >= budget / 2) + return lru_shrink_min; + } else if (pages >= budget * 2) + return lru_shrink_min; + return 0; +} - tmp = cache->ccc_lru_max / atomic_read(&cache->ccc_users); - if (pages > tmp) - return min(pages, lru_shrink_max); +void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) +{ + LIST_HEAD(lru); + struct osc_async_page *oap; + int npages = 0; + + list_for_each_entry(oap, plist, oap_pending_item) { + struct osc_page *opg = oap2osc_page(oap); + + if (!opg->ops_in_lru) + continue; - return pages > lru_shrink_min ? lru_shrink_min : 0; + ++npages; + LASSERT(list_empty(&opg->ops_lru)); + list_add(&opg->ops_lru, &lru); } - return 0; + if (npages > 0) { + client_obd_list_lock(&cli->cl_lru_list_lock); + list_splice_tail(&lru, &cli->cl_lru_list); + atomic_sub(npages, &cli->cl_lru_busy); + atomic_add(npages, &cli->cl_lru_in_list); + client_obd_list_unlock(&cli->cl_lru_list_lock); + + /* XXX: May set force to be true for better performance */ + osc_lru_shrink(cli, osc_cache_too_much(cli), false); + } } -/* Return how many pages are not discarded in @pvec. */ -static int discard_pagevec(const struct lu_env *env, struct cl_io *io, - struct cl_page **pvec, int max_index) +static void __osc_lru_del(struct client_obd *cli, struct osc_page *opg) +{ + LASSERT(atomic_read(&cli->cl_lru_in_list) > 0); + list_del_init(&opg->ops_lru); + atomic_dec(&cli->cl_lru_in_list); +} + +/** + * Page is being destroyed. The page may be not in LRU list, if the transfer + * has never finished(error occurred). + */ +static void osc_lru_del(struct client_obd *cli, struct osc_page *opg) +{ + if (opg->ops_in_lru) { + client_obd_list_lock(&cli->cl_lru_list_lock); + if (!list_empty(&opg->ops_lru)) { + __osc_lru_del(cli, opg); + } else { + LASSERT(atomic_read(&cli->cl_lru_busy) > 0); + atomic_dec(&cli->cl_lru_busy); + } + client_obd_list_unlock(&cli->cl_lru_list_lock); + + atomic_inc(cli->cl_lru_left); + /* this is a great place to release more LRU pages if + * this osc occupies too many LRU pages and kernel is + * stealing one of them. + */ + if (!memory_pressure_get()) + osc_lru_shrink(cli, osc_cache_too_much(cli), false); + wake_up(&osc_lru_waitq); + } else { + LASSERT(list_empty(&opg->ops_lru)); + } +} + +/** + * Delete page from LRUlist for redirty. + */ +static void osc_lru_use(struct client_obd *cli, struct osc_page *opg) +{ + /* If page is being transferred for the first time, + * ops_lru should be empty + */ + if (opg->ops_in_lru && !list_empty(&opg->ops_lru)) { + client_obd_list_lock(&cli->cl_lru_list_lock); + __osc_lru_del(cli, opg); + client_obd_list_unlock(&cli->cl_lru_list_lock); + atomic_inc(&cli->cl_lru_busy); + } +} + +static void discard_pagevec(const struct lu_env *env, struct cl_io *io, + struct cl_page **pvec, int max_index) { - int count; int i; - for (count = 0, i = 0; i < max_index; i++) { + for (i = 0; i < max_index; i++) { struct cl_page *page = pvec[i]; - if (cl_page_own_try(env, io, page) == 0) { - /* free LRU page only if nobody is using it. - * This check is necessary to avoid freeing the pages - * having already been removed from LRU and pinned - * for IO. - */ - if (!cl_page_in_use(page)) { - cl_page_unmap(env, io, page); - cl_page_discard(env, io, page); - ++count; - } - cl_page_disown(env, io, page); - } + LASSERT(cl_page_is_owned(page, io)); + cl_page_unmap(env, io, page); + cl_page_discard(env, io, page); + cl_page_disown(env, io, page); cl_page_put(env, page); + pvec[i] = NULL; } - return max_index - count; } /** * Drop @target of pages from LRU at most. */ -int osc_lru_shrink(struct client_obd *cli, int target) +int osc_lru_shrink(struct client_obd *cli, int target, bool force) { struct cl_env_nest nest; struct lu_env *env; @@ -573,18 +628,32 @@ int osc_lru_shrink(struct client_obd *cli, int target) if (atomic_read(&cli->cl_lru_in_list) == 0 || target <= 0) return 0; + if (!force) { + if (atomic_read(&cli->cl_lru_shrinkers) > 0) + return -EBUSY; + + if (atomic_inc_return(&cli->cl_lru_shrinkers) > 1) { + atomic_dec(&cli->cl_lru_shrinkers); + return -EBUSY; + } + } else { + atomic_inc(&cli->cl_lru_shrinkers); + } + env = cl_env_nested_get(&nest); - if (IS_ERR(env)) - return PTR_ERR(env); + if (IS_ERR(env)) { + rc = PTR_ERR(env); + goto out; + } pvec = osc_env_info(env)->oti_pvec; io = &osc_env_info(env)->oti_io; client_obd_list_lock(&cli->cl_lru_list_lock); - atomic_inc(&cli->cl_lru_shrinkers); maxscan = min(target << 1, atomic_read(&cli->cl_lru_in_list)); list_for_each_entry_safe(opg, temp, &cli->cl_lru_list, ops_lru) { struct cl_page *page; + bool will_free = false; if (--maxscan < 0) break; @@ -603,7 +672,7 @@ int osc_lru_shrink(struct client_obd *cli, int target) client_obd_list_unlock(&cli->cl_lru_list_lock); if (clobj) { - count -= discard_pagevec(env, io, pvec, index); + discard_pagevec(env, io, pvec, index); index = 0; cl_io_fini(env, io); @@ -625,98 +694,56 @@ int osc_lru_shrink(struct client_obd *cli, int target) continue; } - /* move this page to the end of list as it will be discarded - * soon. The page will be finally removed from LRU list in - * osc_page_delete(). - */ - list_move_tail(&opg->ops_lru, &cli->cl_lru_list); + if (cl_page_own_try(env, io, page) == 0) { + if (!cl_page_in_use_noref(page)) { + /* remove it from lru list earlier to avoid + * lock contention + */ + __osc_lru_del(cli, opg); + opg->ops_in_lru = 0; /* will be discarded */ + + cl_page_get(page); + will_free = true; + } else { + cl_page_disown(env, io, page); + } + } - /* it's okay to grab a refcount here w/o holding lock because - * it has to grab cl_lru_list_lock to delete the page. - */ - cl_page_get(page); - pvec[index++] = page; - if (++count >= target) - break; + if (!will_free) { + list_move_tail(&opg->ops_lru, &cli->cl_lru_list); + continue; + } + /* Don't discard and free the page with cl_lru_list held */ + pvec[index++] = page; if (unlikely(index == OTI_PVEC_SIZE)) { client_obd_list_unlock(&cli->cl_lru_list_lock); - count -= discard_pagevec(env, io, pvec, index); + discard_pagevec(env, io, pvec, index); index = 0; client_obd_list_lock(&cli->cl_lru_list_lock); } + + if (++count >= target) + break; } client_obd_list_unlock(&cli->cl_lru_list_lock); if (clobj) { - count -= discard_pagevec(env, io, pvec, index); + discard_pagevec(env, io, pvec, index); cl_io_fini(env, io); cl_object_put(env, clobj); } cl_env_nested_put(&nest, env); +out: atomic_dec(&cli->cl_lru_shrinkers); - return count > 0 ? count : rc; -} - -static void osc_lru_add(struct client_obd *cli, struct osc_page *opg) -{ - bool wakeup = false; - - if (!opg->ops_in_lru) - return; - - atomic_dec(&cli->cl_lru_busy); - client_obd_list_lock(&cli->cl_lru_list_lock); - if (list_empty(&opg->ops_lru)) { - list_move_tail(&opg->ops_lru, &cli->cl_lru_list); - atomic_inc_return(&cli->cl_lru_in_list); - wakeup = atomic_read(&osc_lru_waiters) > 0; - } - client_obd_list_unlock(&cli->cl_lru_list_lock); - - if (wakeup) { - osc_lru_shrink(cli, osc_cache_too_much(cli)); + if (count > 0) { + atomic_add(count, cli->cl_lru_left); wake_up_all(&osc_lru_waitq); } -} - -/* delete page from LRUlist. The page can be deleted from LRUlist for two - * reasons: redirtied or deleted from page cache. - */ -static void osc_lru_del(struct client_obd *cli, struct osc_page *opg, bool del) -{ - if (opg->ops_in_lru) { - client_obd_list_lock(&cli->cl_lru_list_lock); - if (!list_empty(&opg->ops_lru)) { - LASSERT(atomic_read(&cli->cl_lru_in_list) > 0); - list_del_init(&opg->ops_lru); - atomic_dec(&cli->cl_lru_in_list); - if (!del) - atomic_inc(&cli->cl_lru_busy); - } else if (del) { - LASSERT(atomic_read(&cli->cl_lru_busy) > 0); - atomic_dec(&cli->cl_lru_busy); - } - client_obd_list_unlock(&cli->cl_lru_list_lock); - if (del) { - atomic_inc(cli->cl_lru_left); - /* this is a great place to release more LRU pages if - * this osc occupies too many LRU pages and kernel is - * stealing one of them. - * cl_lru_shrinkers is to avoid recursive call in case - * we're already in the context of osc_lru_shrink(). - */ - if (atomic_read(&cli->cl_lru_shrinkers) == 0 && - !memory_pressure_get()) - osc_lru_shrink(cli, osc_cache_too_much(cli)); - wake_up(&osc_lru_waitq); - } - } else { - LASSERT(list_empty(&opg->ops_lru)); - } + return count > 0 ? count : rc; } static inline int max_to_shrink(struct client_obd *cli) @@ -724,16 +751,19 @@ static inline int max_to_shrink(struct client_obd *cli) return min(atomic_read(&cli->cl_lru_in_list) >> 1, lru_shrink_max); } -static int osc_lru_reclaim(struct client_obd *cli) +int osc_lru_reclaim(struct client_obd *cli) { struct cl_client_cache *cache = cli->cl_cache; int max_scans; - int rc; + int rc = 0; LASSERT(cache); - rc = osc_lru_shrink(cli, lru_shrink_min); + rc = osc_lru_shrink(cli, lru_shrink_min, false); if (rc != 0) { + if (rc == -EBUSY) + rc = 0; + CDEBUG(D_CACHE, "%s: Free %d pages from own LRU: %p.\n", cli->cl_import->imp_obd->obd_name, rc, cli); return rc; @@ -764,10 +794,10 @@ static int osc_lru_reclaim(struct client_obd *cli) atomic_read(&cli->cl_lru_busy)); list_move_tail(&cli->cl_lru_osc, &cache->ccc_lru); - if (atomic_read(&cli->cl_lru_in_list) > 0) { + if (osc_cache_too_much(cli) > 0) { spin_unlock(&cache->ccc_lru_lock); - rc = osc_lru_shrink(cli, max_to_shrink(cli)); + rc = osc_lru_shrink(cli, osc_cache_too_much(cli), true); spin_lock(&cache->ccc_lru_lock); if (rc != 0) break; @@ -784,15 +814,20 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, struct osc_page *opg) { struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + struct osc_io *oio = osc_env_io(env); struct client_obd *cli = osc_cli(obj); int rc = 0; if (!cli->cl_cache) /* shall not be in LRU */ return 0; + if (oio->oi_lru_reserved > 0) { + --oio->oi_lru_reserved; + goto out; + } + LASSERT(atomic_read(cli->cl_lru_left) >= 0); while (!atomic_add_unless(cli->cl_lru_left, -1, 0)) { - int gen; /* run out of LRU spaces, try to drop some by itself */ rc = osc_lru_reclaim(cli); @@ -803,23 +838,15 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, cond_resched(); - /* slowest case, all of caching pages are busy, notifying - * other OSCs that we're lack of LRU slots. - */ - atomic_inc(&osc_lru_waiters); - - gen = atomic_read(&cli->cl_lru_in_list); rc = l_wait_event(osc_lru_waitq, - atomic_read(cli->cl_lru_left) > 0 || - (atomic_read(&cli->cl_lru_in_list) > 0 && - gen != atomic_read(&cli->cl_lru_in_list)), + atomic_read(cli->cl_lru_left) > 0, &lwi); - atomic_dec(&osc_lru_waiters); if (rc < 0) break; } +out: if (rc >= 0) { atomic_inc(&cli->cl_lru_busy); opg->ops_in_lru = 1; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 850d5dd49831..6dadda4da5b4 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2910,7 +2910,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp, int nr = atomic_read(&cli->cl_lru_in_list) >> 1; int target = *(int *)val; - nr = osc_lru_shrink(cli, min(nr, target)); + nr = osc_lru_shrink(cli, min(nr, target), true); *(int *)val -= nr; return 0; } -- GitLab From 2579d8d01759aae407d3645be5125f8dd436757c Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:27 -0400 Subject: [PATCH 0856/9938] staging/lustre/osc: to drop LRU pages with cl_lru_work This way we can drop it async. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/7891 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Lai Siyao Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 1 + .../staging/lustre/lustre/llite/lproc_llite.c | 9 +++- drivers/staging/lustre/lustre/osc/lproc_osc.c | 12 ++++- .../lustre/lustre/osc/osc_cl_internal.h | 1 + .../staging/lustre/lustre/osc/osc_internal.h | 3 +- drivers/staging/lustre/lustre/osc/osc_page.c | 45 ++++++++++++------- .../staging/lustre/lustre/osc/osc_request.c | 23 +++++++++- .../staging/lustre/lustre/ptlrpc/ptlrpcd.c | 16 +++++-- 8 files changed, 85 insertions(+), 25 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 4a0f2e8b19f6..26182ca8f518 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -364,6 +364,7 @@ struct client_obd { /* ptlrpc work for writeback in ptlrpcd context */ void *cl_writeback_work; + void *cl_lru_work; /* hash tables for osc_quota_info */ struct cfs_hash *cl_quota_hash[MAXQUOTAS]; }; diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 45941a6600fe..9e8e61a730b7 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -393,6 +393,8 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, struct super_block *sb = ((struct seq_file *)file->private_data)->private; struct ll_sb_info *sbi = ll_s2sbi(sb); struct cl_client_cache *cache = &sbi->ll_cache; + struct lu_env *env; + int refcheck; int mult, rc, pages_number; int diff = 0; int nrpages = 0; @@ -430,6 +432,10 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, goto out; } + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return 0; + diff = -diff; while (diff > 0) { int tmp; @@ -461,13 +467,14 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, /* difficult - have to ask OSCs to drop LRU slots. */ tmp = diff << 1; - rc = obd_set_info_async(NULL, sbi->ll_dt_exp, + rc = obd_set_info_async(env, sbi->ll_dt_exp, sizeof(KEY_CACHE_LRU_SHRINK), KEY_CACHE_LRU_SHRINK, sizeof(tmp), &tmp, NULL); if (rc < 0) break; } + cl_env_put(env, &refcheck); out: if (rc >= 0) { diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 3eff12c073d3..e6e2029289f9 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -222,8 +222,16 @@ static ssize_t osc_cached_mb_seq_write(struct file *file, return -ERANGE; rc = atomic_read(&cli->cl_lru_in_list) - pages_number; - if (rc > 0) - (void)osc_lru_shrink(cli, rc, true); + if (rc > 0) { + struct lu_env *env; + int refcheck; + + env = cl_env_get(&refcheck); + if (!IS_ERR(env)) { + (void)osc_lru_shrink(env, cli, rc, true); + cl_env_put(env, &refcheck); + } + } return count; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index f5168486e1d9..b6325f5c3542 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -457,6 +457,7 @@ int osc_cache_wait_range(const struct lu_env *env, struct osc_object *obj, pgoff_t start, pgoff_t end); void osc_io_unplug(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc); +int lru_queue_work(const struct lu_env *env, void *data); void osc_object_set_contended (struct osc_object *obj); void osc_object_clear_contended(struct osc_object *obj); diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index ec12962d8dcc..b3b15d4c99e3 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -130,7 +130,8 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *cfg); int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, struct list_head *ext_list, int cmd); -int osc_lru_shrink(struct client_obd *cli, int target, bool force); +int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, + int target, bool force); int osc_lru_reclaim(struct client_obd *cli); extern spinlock_t osc_ast_guard; diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index a60b783a761e..f0a9870846d7 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -508,6 +508,18 @@ static int osc_cache_too_much(struct client_obd *cli) return 0; } +int lru_queue_work(const struct lu_env *env, void *data) +{ + struct client_obd *cli = data; + + CDEBUG(D_CACHE, "Run LRU work for client obd %p.\n", cli); + + if (osc_cache_too_much(cli)) + osc_lru_shrink(env, cli, lru_shrink_max, true); + + return 0; +} + void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) { LIST_HEAD(lru); @@ -533,7 +545,8 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) client_obd_list_unlock(&cli->cl_lru_list_lock); /* XXX: May set force to be true for better performance */ - osc_lru_shrink(cli, osc_cache_too_much(cli), false); + if (osc_cache_too_much(cli)) + (void)ptlrpcd_queue_work(cli->cl_lru_work); } } @@ -566,7 +579,7 @@ static void osc_lru_del(struct client_obd *cli, struct osc_page *opg) * stealing one of them. */ if (!memory_pressure_get()) - osc_lru_shrink(cli, osc_cache_too_much(cli), false); + (void)ptlrpcd_queue_work(cli->cl_lru_work); wake_up(&osc_lru_waitq); } else { LASSERT(list_empty(&opg->ops_lru)); @@ -610,10 +623,9 @@ static void discard_pagevec(const struct lu_env *env, struct cl_io *io, /** * Drop @target of pages from LRU at most. */ -int osc_lru_shrink(struct client_obd *cli, int target, bool force) +int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, + int target, bool force) { - struct cl_env_nest nest; - struct lu_env *env; struct cl_io *io; struct cl_object *clobj = NULL; struct cl_page **pvec; @@ -640,12 +652,6 @@ int osc_lru_shrink(struct client_obd *cli, int target, bool force) atomic_inc(&cli->cl_lru_shrinkers); } - env = cl_env_nested_get(&nest); - if (IS_ERR(env)) { - rc = PTR_ERR(env); - goto out; - } - pvec = osc_env_info(env)->oti_pvec; io = &osc_env_info(env)->oti_io; @@ -735,9 +741,7 @@ int osc_lru_shrink(struct client_obd *cli, int target, bool force) cl_io_fini(env, io); cl_object_put(env, clobj); } - cl_env_nested_put(&nest, env); -out: atomic_dec(&cli->cl_lru_shrinkers); if (count > 0) { atomic_add(count, cli->cl_lru_left); @@ -753,20 +757,26 @@ static inline int max_to_shrink(struct client_obd *cli) int osc_lru_reclaim(struct client_obd *cli) { + struct cl_env_nest nest; + struct lu_env *env; struct cl_client_cache *cache = cli->cl_cache; int max_scans; int rc = 0; LASSERT(cache); - rc = osc_lru_shrink(cli, lru_shrink_min, false); + env = cl_env_nested_get(&nest); + if (IS_ERR(env)) + return 0; + + rc = osc_lru_shrink(env, cli, osc_cache_too_much(cli), false); if (rc != 0) { if (rc == -EBUSY) rc = 0; CDEBUG(D_CACHE, "%s: Free %d pages from own LRU: %p.\n", cli->cl_import->imp_obd->obd_name, rc, cli); - return rc; + goto out; } CDEBUG(D_CACHE, "%s: cli %p no free slots, pages: %d, busy: %d.\n", @@ -797,7 +807,8 @@ int osc_lru_reclaim(struct client_obd *cli) if (osc_cache_too_much(cli) > 0) { spin_unlock(&cache->ccc_lru_lock); - rc = osc_lru_shrink(cli, osc_cache_too_much(cli), true); + rc = osc_lru_shrink(env, cli, osc_cache_too_much(cli), + true); spin_lock(&cache->ccc_lru_lock); if (rc != 0) break; @@ -805,6 +816,8 @@ int osc_lru_reclaim(struct client_obd *cli) } spin_unlock(&cache->ccc_lru_lock); +out: + cl_env_nested_put(&nest, env); CDEBUG(D_CACHE, "%s: cli %p freed %d pages.\n", cli->cl_import->imp_obd->obd_name, cli, rc); return rc; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 6dadda4da5b4..c055511b321a 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2910,7 +2910,7 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp, int nr = atomic_read(&cli->cl_lru_in_list) >> 1; int target = *(int *)val; - nr = osc_lru_shrink(cli, min(nr, target), true); + nr = osc_lru_shrink(env, cli, min(nr, target), true); *(int *)val -= nr; return 0; } @@ -3167,6 +3167,14 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) } cli->cl_writeback_work = handler; + handler = ptlrpcd_alloc_work(cli->cl_import, lru_queue_work, cli); + if (IS_ERR(handler)) { + rc = PTR_ERR(handler); + goto out_ptlrpcd_work; + } + + cli->cl_lru_work = handler; + rc = osc_quota_setup(obd); if (rc) goto out_ptlrpcd_work; @@ -3199,7 +3207,14 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) return rc; out_ptlrpcd_work: - ptlrpcd_destroy_work(handler); + if (cli->cl_writeback_work) { + ptlrpcd_destroy_work(cli->cl_writeback_work); + cli->cl_writeback_work = NULL; + } + if (cli->cl_lru_work) { + ptlrpcd_destroy_work(cli->cl_lru_work); + cli->cl_lru_work = NULL; + } out_client_setup: client_obd_cleanup(obd); out_ptlrpcd: @@ -3238,6 +3253,10 @@ static int osc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) ptlrpcd_destroy_work(cli->cl_writeback_work); cli->cl_writeback_work = NULL; } + if (cli->cl_lru_work) { + ptlrpcd_destroy_work(cli->cl_lru_work); + cli->cl_lru_work = NULL; + } obd_cleanup_client_import(obd); ptlrpc_lprocfs_unregister_obd(obd); lprocfs_obd_cleanup(obd); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index db003f5da09e..dbc3376328cd 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -387,7 +387,8 @@ static int ptlrpcd(void *arg) { struct ptlrpcd_ctl *pc = arg; struct ptlrpc_request_set *set; - struct lu_env env = { .le_ses = NULL }; + struct lu_context ses = { 0 }; + struct lu_env env = { .le_ses = &ses }; int rc = 0; int exit = 0; @@ -416,6 +417,13 @@ static int ptlrpcd(void *arg) */ rc = lu_context_init(&env.le_ctx, LCT_CL_THREAD|LCT_REMEMBER|LCT_NOREF); + if (rc == 0) { + rc = lu_context_init(env.le_ses, + LCT_SESSION | LCT_REMEMBER | LCT_NOREF); + if (rc != 0) + lu_context_fini(&env.le_ctx); + } + if (rc != 0) goto failed; @@ -436,9 +444,10 @@ static int ptlrpcd(void *arg) ptlrpc_expired_set, set); lu_context_enter(&env.le_ctx); - l_wait_event(set->set_waitq, - ptlrpcd_check(&env, pc), &lwi); + lu_context_enter(env.le_ses); + l_wait_event(set->set_waitq, ptlrpcd_check(&env, pc), &lwi); lu_context_exit(&env.le_ctx); + lu_context_exit(env.le_ses); /* * Abort inflight rpcs for forced stop case. @@ -461,6 +470,7 @@ static int ptlrpcd(void *arg) if (!list_empty(&set->set_requests)) ptlrpc_set_wait(set); lu_context_fini(&env.le_ctx); + lu_context_fini(env.le_ses); complete(&pc->pc_finishing); -- GitLab From d9d47901dfbec3f7e057c4d31ecbe39c8eaec991 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:28 -0400 Subject: [PATCH 0857/9938] staging/lustre/clio: collapse layer of cl_page Move radix tree to osc layer to for performance improvement. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/7892 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Lai Siyao Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 36 +- drivers/staging/lustre/lustre/llite/rw.c | 2 +- drivers/staging/lustre/lustre/llite/rw26.c | 4 - drivers/staging/lustre/lustre/llite/vvp_dev.c | 47 +-- drivers/staging/lustre/lustre/llite/vvp_io.c | 1 - .../staging/lustre/lustre/llite/vvp_object.c | 13 + .../staging/lustre/lustre/llite/vvp_page.c | 36 +- .../staging/lustre/lustre/lov/lov_object.c | 9 +- drivers/staging/lustre/lustre/lov/lov_page.c | 29 +- .../staging/lustre/lustre/obdclass/cl_io.c | 1 + .../staging/lustre/lustre/obdclass/cl_lock.c | 131 +------ .../lustre/lustre/obdclass/cl_object.c | 47 ++- .../staging/lustre/lustre/obdclass/cl_page.c | 354 ++---------------- drivers/staging/lustre/lustre/osc/osc_cache.c | 207 +++++++++- .../lustre/lustre/osc/osc_cl_internal.h | 27 +- drivers/staging/lustre/lustre/osc/osc_io.c | 14 +- drivers/staging/lustre/lustre/osc/osc_lock.c | 10 +- .../staging/lustre/lustre/osc/osc_object.c | 2 + drivers/staging/lustre/lustre/osc/osc_page.c | 28 +- 19 files changed, 394 insertions(+), 604 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index e611f790285a..5daf68815949 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -388,6 +388,12 @@ struct cl_object_operations { */ int (*coo_glimpse)(const struct lu_env *env, const struct cl_object *obj, struct ost_lvb *lvb); + /** + * Object prune method. Called when the layout is going to change on + * this object, therefore each layer has to clean up their cache, + * mainly pages and locks. + */ + int (*coo_prune)(const struct lu_env *env, struct cl_object *obj); }; /** @@ -403,15 +409,9 @@ struct cl_object_header { * mostly useless otherwise. */ /** @{ */ - /** Lock protecting page tree. */ - spinlock_t coh_page_guard; /** Lock protecting lock list. */ spinlock_t coh_lock_guard; /** @} locks */ - /** Radix tree of cl_page's, cached for this object. */ - struct radix_tree_root coh_tree; - /** # of pages in radix tree. */ - unsigned long coh_pages; /** List of cl_lock's granted for this object. */ struct list_head coh_locks; @@ -896,14 +896,6 @@ struct cl_page_operations { */ void (*cpo_export)(const struct lu_env *env, const struct cl_page_slice *slice, int uptodate); - /** - * Unmaps page from the user space (if it is mapped). - * - * \see cl_page_unmap() - * \see vvp_page_unmap() - */ - int (*cpo_unmap)(const struct lu_env *env, - const struct cl_page_slice *slice, struct cl_io *io); /** * Checks whether underlying VM page is locked (in the suitable * sense). Used for assertions. @@ -2794,19 +2786,13 @@ enum { }; /* callback of cl_page_gang_lookup() */ -typedef int (*cl_page_gang_cb_t) (const struct lu_env *, struct cl_io *, - struct cl_page *, void *); -int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj, - struct cl_io *io, pgoff_t start, pgoff_t end, - cl_page_gang_cb_t cb, void *cbdata); -struct cl_page *cl_page_lookup(struct cl_object_header *hdr, pgoff_t index); struct cl_page *cl_page_find(const struct lu_env *env, struct cl_object *obj, pgoff_t idx, struct page *vmpage, enum cl_page_type type); -struct cl_page *cl_page_find_sub(const struct lu_env *env, - struct cl_object *obj, - pgoff_t idx, struct page *vmpage, - struct cl_page *parent); +struct cl_page *cl_page_alloc(const struct lu_env *env, + struct cl_object *o, pgoff_t ind, + struct page *vmpage, + enum cl_page_type type); void cl_page_get(struct cl_page *page); void cl_page_put(const struct lu_env *env, struct cl_page *page); void cl_page_print(const struct lu_env *env, void *cookie, lu_printer_t printer, @@ -2872,8 +2858,6 @@ int cl_page_flush(const struct lu_env *env, struct cl_io *io, void cl_page_discard(const struct lu_env *env, struct cl_io *io, struct cl_page *pg); void cl_page_delete(const struct lu_env *env, struct cl_page *pg); -int cl_page_unmap(const struct lu_env *env, struct cl_io *io, - struct cl_page *pg); int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg); void cl_page_export(const struct lu_env *env, struct cl_page *pg, int uptodate); int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 34614acf3f8e..01b8365c1dda 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -442,7 +442,7 @@ static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, cl_page_list_add(queue, page); rc = 1; } else { - cl_page_delete(env, page); + cl_page_discard(env, io, page); rc = -ENOLCK; } } else { diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 3d7e64ee9824..b5335de216be 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -95,11 +95,7 @@ static void ll_invalidatepage(struct page *vmpage, unsigned int offset, if (obj) { page = cl_vmpage_page(vmpage, obj); if (page) { - lu_ref_add(&page->cp_reference, - "delete", vmpage); cl_page_delete(env, page); - lu_ref_del(&page->cp_reference, - "delete", vmpage); cl_page_put(env, page); } } else diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 282b70b776da..29d24c98d259 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -36,6 +36,7 @@ * cl_device and cl_device_type implementation for VVP layer. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_LLITE @@ -356,23 +357,18 @@ static loff_t vvp_pgcache_find(const struct lu_env *env, return ~0ULL; clob = vvp_pgcache_obj(env, dev, &id); if (clob) { - struct cl_object_header *hdr; - int nr; - struct cl_page *pg; + struct inode *inode = ccc_object_inode(clob); + struct page *vmpage; + int nr; - /* got an object. Find next page. */ - hdr = cl_object_header(clob); - - spin_lock(&hdr->coh_page_guard); - nr = radix_tree_gang_lookup(&hdr->coh_tree, - (void **)&pg, - id.vpi_index, 1); + nr = find_get_pages_contig(inode->i_mapping, + id.vpi_index, 1, &vmpage); if (nr > 0) { - id.vpi_index = pg->cp_index; + id.vpi_index = vmpage->index; /* Cant support over 16T file */ - nr = !(pg->cp_index > 0xffffffff); + nr = !(vmpage->index > 0xffffffff); + page_cache_release(vmpage); } - spin_unlock(&hdr->coh_page_guard); lu_object_ref_del(&clob->co_lu, "dump", current); cl_object_put(env, clob); @@ -431,8 +427,6 @@ static int vvp_pgcache_show(struct seq_file *f, void *v) struct ll_sb_info *sbi; struct cl_object *clob; struct lu_env *env; - struct cl_page *page; - struct cl_object_header *hdr; struct vvp_pgcache_id id; int refcheck; int result; @@ -444,14 +438,23 @@ static int vvp_pgcache_show(struct seq_file *f, void *v) sbi = f->private; clob = vvp_pgcache_obj(env, &sbi->ll_cl->cd_lu_dev, &id); if (clob) { - hdr = cl_object_header(clob); - - spin_lock(&hdr->coh_page_guard); - page = cl_page_lookup(hdr, id.vpi_index); - spin_unlock(&hdr->coh_page_guard); + struct inode *inode = ccc_object_inode(clob); + struct cl_page *page = NULL; + struct page *vmpage; + + result = find_get_pages_contig(inode->i_mapping, + id.vpi_index, 1, + &vmpage); + if (result > 0) { + lock_page(vmpage); + page = cl_vmpage_page(vmpage, clob); + unlock_page(vmpage); + + page_cache_release(vmpage); + } - seq_printf(f, "%8x@"DFID": ", - id.vpi_index, PFID(&hdr->coh_lu.loh_fid)); + seq_printf(f, "%8x@" DFID ": ", id.vpi_index, + PFID(lu_object_fid(&clob->co_lu))); if (page) { vvp_pgcache_page_show(env, f, page); cl_page_put(env, page); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 984699a32c69..ffe301b6f453 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -763,7 +763,6 @@ static int vvp_io_fault_start(const struct lu_env *env, vmpage = NULL; if (result < 0) { - cl_page_unmap(env, io, page); cl_page_discard(env, io, page); cl_page_disown(env, io, page); diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 03c887d8ed83..b9a1d01a9bd3 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -165,6 +165,18 @@ static int vvp_conf_set(const struct lu_env *env, struct cl_object *obj, return 0; } +static int vvp_prune(const struct lu_env *env, struct cl_object *obj) +{ + struct inode *inode = ccc_object_inode(obj); + int rc; + + rc = cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_ALL, 1); + if (rc == 0) + truncate_inode_pages(inode->i_mapping, 0); + + return rc; +} + static const struct cl_object_operations vvp_ops = { .coo_page_init = vvp_page_init, .coo_lock_init = vvp_lock_init, @@ -172,6 +184,7 @@ static const struct cl_object_operations vvp_ops = { .coo_attr_get = vvp_attr_get, .coo_attr_set = vvp_attr_set, .coo_conf_set = vvp_conf_set, + .coo_prune = vvp_prune, .coo_glimpse = ccc_object_glimpse }; diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 850bae734075..11e609ebbe3e 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -138,6 +138,7 @@ static void vvp_page_discard(const struct lu_env *env, struct page *vmpage = cl2vm_page(slice); struct address_space *mapping; struct ccc_page *cpg = cl2ccc_page(slice); + __u64 offset; LASSERT(vmpage); LASSERT(PageLocked(vmpage)); @@ -147,6 +148,9 @@ static void vvp_page_discard(const struct lu_env *env, if (cpg->cpg_defer_uptodate && !cpg->cpg_ra_used) ll_ra_stats_inc(mapping, RA_STAT_DISCARDED); + offset = vmpage->index << PAGE_SHIFT; + ll_teardown_mmaps(vmpage->mapping, offset, offset + PAGE_SIZE); + /* * truncate_complete_page() calls * a_ops->invalidatepage()->cl_page_delete()->vvp_page_delete(). @@ -154,37 +158,26 @@ static void vvp_page_discard(const struct lu_env *env, truncate_complete_page(mapping, vmpage); } -static int vvp_page_unmap(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *unused) -{ - struct page *vmpage = cl2vm_page(slice); - __u64 offset; - - LASSERT(vmpage); - LASSERT(PageLocked(vmpage)); - - offset = vmpage->index << PAGE_CACHE_SHIFT; - - /* - * XXX is it safe to call this with the page lock held? - */ - ll_teardown_mmaps(vmpage->mapping, offset, offset + PAGE_CACHE_SIZE); - return 0; -} - static void vvp_page_delete(const struct lu_env *env, const struct cl_page_slice *slice) { struct page *vmpage = cl2vm_page(slice); struct inode *inode = vmpage->mapping->host; struct cl_object *obj = slice->cpl_obj; + struct cl_page *page = slice->cpl_page; + int refc; LASSERT(PageLocked(vmpage)); - LASSERT((struct cl_page *)vmpage->private == slice->cpl_page); + LASSERT((struct cl_page *)vmpage->private == page); LASSERT(inode == ccc_object_inode(obj)); vvp_write_complete(cl2ccc(obj), cl2ccc_page(slice)); + + /* Drop the reference count held in vvp_page_init */ + refc = atomic_dec_return(&page->cp_ref); + LASSERTF(refc >= 1, "page = %p, refc = %d\n", page, refc); + + ClearPageUptodate(vmpage); ClearPagePrivate(vmpage); vmpage->private = 0; /* @@ -404,7 +397,6 @@ static const struct cl_page_operations vvp_page_ops = { .cpo_vmpage = ccc_page_vmpage, .cpo_discard = vvp_page_discard, .cpo_delete = vvp_page_delete, - .cpo_unmap = vvp_page_unmap, .cpo_export = vvp_page_export, .cpo_is_vmlocked = vvp_page_is_vmlocked, .cpo_fini = vvp_page_fini, @@ -541,6 +533,8 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, INIT_LIST_HEAD(&cpg->cpg_pending_linkage); if (page->cp_type == CPT_CACHEABLE) { + /* in cache, decref in vvp_page_delete */ + atomic_inc(&page->cp_ref); SetPagePrivate(vmpage); vmpage->private = (unsigned long)page; cl_page_slice_add(page, &cpg->cpg_cl, obj, &vvp_page_ops); diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 1f8ed95a6d89..5d8a2b64ce21 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -287,7 +287,7 @@ static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov, lov_layout_wait(env, lov); - cl_object_prune(env, &lov->lo_cl); + cl_locks_prune(env, &lov->lo_cl, 0); return 0; } @@ -364,7 +364,7 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov, } } } - cl_object_prune(env, &lov->lo_cl); + cl_locks_prune(env, &lov->lo_cl, 0); return 0; } @@ -666,7 +666,6 @@ static int lov_layout_change(const struct lu_env *unused, const struct lov_layout_operations *old_ops; const struct lov_layout_operations *new_ops; - struct cl_object_header *hdr = cl_object_header(&lov->lo_cl); void *cookie; struct lu_env *env; int refcheck; @@ -691,13 +690,13 @@ static int lov_layout_change(const struct lu_env *unused, old_ops = &lov_dispatch[lov->lo_type]; new_ops = &lov_dispatch[llt]; + cl_object_prune(env, &lov->lo_cl); + result = old_ops->llo_delete(env, lov, &lov->u); if (result == 0) { old_ops->llo_fini(env, lov, &lov->u); LASSERT(atomic_read(&lov->lo_active_ios) == 0); - LASSERT(!hdr->coh_tree.rnode); - LASSERT(hdr->coh_pages == 0); lov->lo_type = LLT_EMPTY; result = new_ops->llo_init(env, diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index fdcaf8047ad8..9728da245a68 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -36,6 +36,7 @@ * Implementation of cl_page for LOV layer. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_LOV @@ -179,31 +180,21 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_page_ops); sub = lov_sub_get(env, lio, stripe); - if (IS_ERR(sub)) { - rc = PTR_ERR(sub); - goto out; - } + if (IS_ERR(sub)) + return PTR_ERR(sub); subobj = lovsub2cl(r0->lo_sub[stripe]); - subpage = cl_page_find_sub(sub->sub_env, subobj, - cl_index(subobj, suboff), vmpage, page); - lov_sub_put(sub); - if (IS_ERR(subpage)) { - rc = PTR_ERR(subpage); - goto out; - } - - if (likely(subpage->cp_parent == page)) { - lu_ref_add(&subpage->cp_reference, "lov", page); + subpage = cl_page_alloc(sub->sub_env, subobj, cl_index(subobj, suboff), + vmpage, page->cp_type); + if (!IS_ERR(subpage)) { + subpage->cp_parent = page; + page->cp_child = subpage; lpg->lps_invalid = 0; - rc = 0; } else { - CL_PAGE_DEBUG(D_ERROR, env, page, "parent page\n"); - CL_PAGE_DEBUG(D_ERROR, env, subpage, "child page\n"); - LASSERT(0); + rc = PTR_ERR(subpage); } + lov_sub_put(sub); -out: return rc; } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index f5128b4f176f..cf9428428d06 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -36,6 +36,7 @@ * Client IO. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_CLASS diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index f952c1cb0761..32ecc5ad0a3e 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -36,6 +36,7 @@ * Client Extent Lock. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_CLASS @@ -1815,128 +1816,6 @@ struct cl_lock *cl_lock_at_pgoff(const struct lu_env *env, } EXPORT_SYMBOL(cl_lock_at_pgoff); -/** - * Calculate the page offset at the layer of @lock. - * At the time of this writing, @page is top page and @lock is sub lock. - */ -static pgoff_t pgoff_at_lock(struct cl_page *page, struct cl_lock *lock) -{ - struct lu_device_type *dtype; - const struct cl_page_slice *slice; - - dtype = lock->cll_descr.cld_obj->co_lu.lo_dev->ld_type; - slice = cl_page_at(page, dtype); - return slice->cpl_page->cp_index; -} - -/** - * Check if page @page is covered by an extra lock or discard it. - */ -static int check_and_discard_cb(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, void *cbdata) -{ - struct cl_thread_info *info = cl_env_info(env); - struct cl_lock *lock = cbdata; - pgoff_t index = pgoff_at_lock(page, lock); - - if (index >= info->clt_fn_index) { - struct cl_lock *tmp; - - /* refresh non-overlapped index */ - tmp = cl_lock_at_pgoff(env, lock->cll_descr.cld_obj, index, - lock, 1, 0); - if (tmp) { - /* Cache the first-non-overlapped index so as to skip - * all pages within [index, clt_fn_index). This - * is safe because if tmp lock is canceled, it will - * discard these pages. - */ - info->clt_fn_index = tmp->cll_descr.cld_end + 1; - if (tmp->cll_descr.cld_end == CL_PAGE_EOF) - info->clt_fn_index = CL_PAGE_EOF; - cl_lock_put(env, tmp); - } else if (cl_page_own(env, io, page) == 0) { - /* discard the page */ - cl_page_unmap(env, io, page); - cl_page_discard(env, io, page); - cl_page_disown(env, io, page); - } else { - LASSERT(page->cp_state == CPS_FREEING); - } - } - - info->clt_next_index = index + 1; - return CLP_GANG_OKAY; -} - -static int discard_cb(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, void *cbdata) -{ - struct cl_thread_info *info = cl_env_info(env); - struct cl_lock *lock = cbdata; - - LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE); - KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, - !PageWriteback(cl_page_vmpage(env, page)))); - KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, - !PageDirty(cl_page_vmpage(env, page)))); - - info->clt_next_index = pgoff_at_lock(page, lock) + 1; - if (cl_page_own(env, io, page) == 0) { - /* discard the page */ - cl_page_unmap(env, io, page); - cl_page_discard(env, io, page); - cl_page_disown(env, io, page); - } else { - LASSERT(page->cp_state == CPS_FREEING); - } - - return CLP_GANG_OKAY; -} - -/** - * Discard pages protected by the given lock. This function traverses radix - * tree to find all covering pages and discard them. If a page is being covered - * by other locks, it should remain in cache. - * - * If error happens on any step, the process continues anyway (the reasoning - * behind this being that lock cancellation cannot be delayed indefinitely). - */ -int cl_lock_discard_pages(const struct lu_env *env, struct cl_lock *lock) -{ - struct cl_thread_info *info = cl_env_info(env); - struct cl_io *io = &info->clt_io; - struct cl_lock_descr *descr = &lock->cll_descr; - cl_page_gang_cb_t cb; - int res; - int result; - - LINVRNT(cl_lock_invariant(env, lock)); - - io->ci_obj = cl_object_top(descr->cld_obj); - io->ci_ignore_layout = 1; - result = cl_io_init(env, io, CIT_MISC, io->ci_obj); - if (result != 0) - goto out; - - cb = descr->cld_mode == CLM_READ ? check_and_discard_cb : discard_cb; - info->clt_fn_index = info->clt_next_index = descr->cld_start; - do { - res = cl_page_gang_lookup(env, descr->cld_obj, io, - info->clt_next_index, descr->cld_end, - cb, (void *)lock); - if (info->clt_next_index > descr->cld_end) - break; - - if (res == CLP_GANG_RESCHED) - cond_resched(); - } while (res != CLP_GANG_OKAY); -out: - cl_io_fini(env, io); - return result; -} -EXPORT_SYMBOL(cl_lock_discard_pages); - /** * Eliminate all locks for a given object. * @@ -1951,12 +1830,6 @@ void cl_locks_prune(const struct lu_env *env, struct cl_object *obj, int cancel) struct cl_lock *lock; head = cl_object_header(obj); - /* - * If locks are destroyed without cancellation, all pages must be - * already destroyed (as otherwise they will be left unprotected). - */ - LASSERT(ergo(!cancel, - !head->coh_tree.rnode && head->coh_pages == 0)); spin_lock(&head->coh_lock_guard); while (!list_empty(&head->coh_locks)) { @@ -2095,8 +1968,8 @@ void cl_lock_hold_add(const struct lu_env *env, struct cl_lock *lock, LINVRNT(cl_lock_invariant(env, lock)); LASSERT(lock->cll_state != CLS_FREEING); - cl_lock_hold_mod(env, lock, 1); cl_lock_get(lock); + cl_lock_hold_mod(env, lock, 1); lu_ref_add(&lock->cll_holders, scope, source); lu_ref_add(&lock->cll_reference, scope, source); } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 0772706dbffc..65b640223e8f 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -36,6 +36,7 @@ * Client Lustre Object. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ /* @@ -43,7 +44,6 @@ * * i_mutex * PG_locked - * ->coh_page_guard * ->coh_lock_guard * ->coh_attr_guard * ->ls_guard @@ -63,8 +63,6 @@ static struct kmem_cache *cl_env_kmem; -/** Lock class of cl_object_header::coh_page_guard */ -static struct lock_class_key cl_page_guard_class; /** Lock class of cl_object_header::coh_lock_guard */ static struct lock_class_key cl_lock_guard_class; /** Lock class of cl_object_header::coh_attr_guard */ @@ -81,15 +79,10 @@ int cl_object_header_init(struct cl_object_header *h) result = lu_object_header_init(&h->coh_lu); if (result == 0) { - spin_lock_init(&h->coh_page_guard); spin_lock_init(&h->coh_lock_guard); spin_lock_init(&h->coh_attr_guard); - lockdep_set_class(&h->coh_page_guard, &cl_page_guard_class); lockdep_set_class(&h->coh_lock_guard, &cl_lock_guard_class); lockdep_set_class(&h->coh_attr_guard, &cl_attr_guard_class); - h->coh_pages = 0; - /* XXX hard coded GFP_* mask. */ - INIT_RADIX_TREE(&h->coh_tree, GFP_ATOMIC); INIT_LIST_HEAD(&h->coh_locks); h->coh_page_bufsize = ALIGN(sizeof(struct cl_page), 8); } @@ -314,6 +307,32 @@ int cl_conf_set(const struct lu_env *env, struct cl_object *obj, } EXPORT_SYMBOL(cl_conf_set); +/** + * Prunes caches of pages and locks for this object. + */ +void cl_object_prune(const struct lu_env *env, struct cl_object *obj) +{ + struct lu_object_header *top; + struct cl_object *o; + int result; + + top = obj->co_lu.lo_header; + result = 0; + list_for_each_entry(o, &top->loh_layers, co_lu.lo_linkage) { + if (o->co_ops->coo_prune) { + result = o->co_ops->coo_prune(env, o); + if (result != 0) + break; + } + } + + /* TODO: pruning locks will be moved into layers after cl_lock + * simplification is done + */ + cl_locks_prune(env, obj, 1); +} +EXPORT_SYMBOL(cl_object_prune); + /** * Helper function removing all object locks, and marking object for * deletion. All object pages must have been deleted at this point. @@ -326,8 +345,6 @@ void cl_object_kill(const struct lu_env *env, struct cl_object *obj) struct cl_object_header *hdr; hdr = cl_object_header(obj); - LASSERT(!hdr->coh_tree.rnode); - LASSERT(hdr->coh_pages == 0); set_bit(LU_OBJECT_HEARD_BANSHEE, &hdr->coh_lu.loh_flags); /* @@ -341,16 +358,6 @@ void cl_object_kill(const struct lu_env *env, struct cl_object *obj) } EXPORT_SYMBOL(cl_object_kill); -/** - * Prunes caches of pages and locks for this object. - */ -void cl_object_prune(const struct lu_env *env, struct cl_object *obj) -{ - cl_pages_prune(env, obj); - cl_locks_prune(env, obj, 1); -} -EXPORT_SYMBOL(cl_object_prune); - void cache_stats_init(struct cache_stats *cs, const char *name) { int i; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 231a2f26c693..816983678a03 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -36,6 +36,7 @@ * Client Lustre Page. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_CLASS @@ -48,8 +49,7 @@ #include "../include/cl_object.h" #include "cl_internal.h" -static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, - int radix); +static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg); # define PASSERT(env, page, expr) \ do { \ @@ -79,8 +79,7 @@ static struct cl_page *cl_page_top_trusted(struct cl_page *page) * * This function can be used to obtain initial reference to previously * unreferenced cached object. It can be called only if concurrent page - * reclamation is somehow prevented, e.g., by locking page radix-tree - * (cl_object_header::hdr->coh_page_guard), or by keeping a lock on a VM page, + * reclamation is somehow prevented, e.g., by keeping a lock on a VM page, * associated with \a page. * * Use with care! Not exported. @@ -114,132 +113,6 @@ cl_page_at_trusted(const struct cl_page *page, return NULL; } -/** - * Returns a page with given index in the given object, or NULL if no page is - * found. Acquires a reference on \a page. - * - * Locking: called under cl_object_header::coh_page_guard spin-lock. - */ -struct cl_page *cl_page_lookup(struct cl_object_header *hdr, pgoff_t index) -{ - struct cl_page *page; - - assert_spin_locked(&hdr->coh_page_guard); - - page = radix_tree_lookup(&hdr->coh_tree, index); - if (page) - cl_page_get_trust(page); - return page; -} -EXPORT_SYMBOL(cl_page_lookup); - -/** - * Returns a list of pages by a given [start, end] of \a obj. - * - * \param resched If not NULL, then we give up before hogging CPU for too - * long and set *resched = 1, in that case caller should implement a retry - * logic. - * - * Gang tree lookup (radix_tree_gang_lookup()) optimization is absolutely - * crucial in the face of [offset, EOF] locks. - * - * Return at least one page in @queue unless there is no covered page. - */ -int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj, - struct cl_io *io, pgoff_t start, pgoff_t end, - cl_page_gang_cb_t cb, void *cbdata) -{ - struct cl_object_header *hdr; - struct cl_page *page; - struct cl_page **pvec; - const struct cl_page_slice *slice; - const struct lu_device_type *dtype; - pgoff_t idx; - unsigned int nr; - unsigned int i; - unsigned int j; - int res = CLP_GANG_OKAY; - int tree_lock = 1; - - idx = start; - hdr = cl_object_header(obj); - pvec = cl_env_info(env)->clt_pvec; - dtype = cl_object_top(obj)->co_lu.lo_dev->ld_type; - spin_lock(&hdr->coh_page_guard); - while ((nr = radix_tree_gang_lookup(&hdr->coh_tree, (void **)pvec, - idx, CLT_PVEC_SIZE)) > 0) { - int end_of_region = 0; - - idx = pvec[nr - 1]->cp_index + 1; - for (i = 0, j = 0; i < nr; ++i) { - page = pvec[i]; - pvec[i] = NULL; - - LASSERT(page->cp_type == CPT_CACHEABLE); - if (page->cp_index > end) { - end_of_region = 1; - break; - } - if (page->cp_state == CPS_FREEING) - continue; - - slice = cl_page_at_trusted(page, dtype); - /* - * Pages for lsm-less file has no underneath sub-page - * for osc, in case of ... - */ - PASSERT(env, page, slice); - - page = slice->cpl_page; - /* - * Can safely call cl_page_get_trust() under - * radix-tree spin-lock. - * - * XXX not true, because @page is from object another - * than @hdr and protected by different tree lock. - */ - cl_page_get_trust(page); - lu_ref_add_atomic(&page->cp_reference, - "gang_lookup", current); - pvec[j++] = page; - } - - /* - * Here a delicate locking dance is performed. Current thread - * holds a reference to a page, but has to own it before it - * can be placed into queue. Owning implies waiting, so - * radix-tree lock is to be released. After a wait one has to - * check that pages weren't truncated (cl_page_own() returns - * error in the latter case). - */ - spin_unlock(&hdr->coh_page_guard); - tree_lock = 0; - - for (i = 0; i < j; ++i) { - page = pvec[i]; - if (res == CLP_GANG_OKAY) - res = (*cb)(env, io, page, cbdata); - lu_ref_del(&page->cp_reference, - "gang_lookup", current); - cl_page_put(env, page); - } - if (nr < CLT_PVEC_SIZE || end_of_region) - break; - - if (res == CLP_GANG_OKAY && need_resched()) - res = CLP_GANG_RESCHED; - if (res != CLP_GANG_OKAY) - break; - - spin_lock(&hdr->coh_page_guard); - tree_lock = 1; - } - if (tree_lock) - spin_unlock(&hdr->coh_page_guard); - return res; -} -EXPORT_SYMBOL(cl_page_gang_lookup); - static void cl_page_free(const struct lu_env *env, struct cl_page *page) { struct cl_object *obj = page->cp_obj; @@ -276,10 +149,10 @@ static inline void cl_page_state_set_trust(struct cl_page *page, *(enum cl_page_state *)&page->cp_state = state; } -static struct cl_page *cl_page_alloc(const struct lu_env *env, - struct cl_object *o, pgoff_t ind, - struct page *vmpage, - enum cl_page_type type) +struct cl_page *cl_page_alloc(const struct lu_env *env, + struct cl_object *o, pgoff_t ind, + struct page *vmpage, + enum cl_page_type type) { struct cl_page *page; struct lu_object_header *head; @@ -289,8 +162,6 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env, int result = 0; atomic_set(&page->cp_ref, 1); - if (type == CPT_CACHEABLE) /* for radix tree */ - atomic_inc(&page->cp_ref); page->cp_obj = o; cl_object_get(o); lu_object_ref_add_at(&o->co_lu, &page->cp_obj_ref, "cl_page", @@ -309,7 +180,7 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env, result = o->co_ops->coo_page_init(env, o, page, vmpage); if (result != 0) { - cl_page_delete0(env, page, 0); + cl_page_delete0(env, page); cl_page_free(env, page); page = ERR_PTR(result); break; @@ -321,6 +192,7 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env, } return page; } +EXPORT_SYMBOL(cl_page_alloc); /** * Returns a cl_page with index \a idx at the object \a o, and associated with @@ -333,16 +205,13 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env, * * \see cl_object_find(), cl_lock_find() */ -static struct cl_page *cl_page_find0(const struct lu_env *env, - struct cl_object *o, - pgoff_t idx, struct page *vmpage, - enum cl_page_type type, - struct cl_page *parent) +struct cl_page *cl_page_find(const struct lu_env *env, + struct cl_object *o, + pgoff_t idx, struct page *vmpage, + enum cl_page_type type) { struct cl_page *page = NULL; - struct cl_page *ghost = NULL; struct cl_object_header *hdr; - int err; LASSERT(type == CPT_CACHEABLE || type == CPT_TRANSIENT); might_sleep(); @@ -368,90 +237,19 @@ static struct cl_page *cl_page_find0(const struct lu_env *env, * reference on it. */ page = cl_vmpage_page(vmpage, o); - PINVRNT(env, page, - ergo(page, - cl_page_vmpage(env, page) == vmpage && - (void *)radix_tree_lookup(&hdr->coh_tree, - idx) == page)); - } - if (page) - return page; + if (page) + return page; + } /* allocate and initialize cl_page */ page = cl_page_alloc(env, o, idx, vmpage, type); - if (IS_ERR(page)) - return page; - - if (type == CPT_TRANSIENT) { - if (parent) { - LASSERT(!page->cp_parent); - page->cp_parent = parent; - parent->cp_child = page; - } - return page; - } - - /* - * XXX optimization: use radix_tree_preload() here, and change tree - * gfp mask to GFP_KERNEL in cl_object_header_init(). - */ - spin_lock(&hdr->coh_page_guard); - err = radix_tree_insert(&hdr->coh_tree, idx, page); - if (err != 0) { - ghost = page; - /* - * Noted by Jay: a lock on \a vmpage protects cl_page_find() - * from this race, but - * - * 0. it's better to have cl_page interface "locally - * consistent" so that its correctness can be reasoned - * about without appealing to the (obscure world of) VM - * locking. - * - * 1. handling this race allows ->coh_tree to remain - * consistent even when VM locking is somehow busted, - * which is very useful during diagnosing and debugging. - */ - page = ERR_PTR(err); - CL_PAGE_DEBUG(D_ERROR, env, ghost, - "fail to insert into radix tree: %d\n", err); - } else { - if (parent) { - LASSERT(!page->cp_parent); - page->cp_parent = parent; - parent->cp_child = page; - } - hdr->coh_pages++; - } - spin_unlock(&hdr->coh_page_guard); - - if (unlikely(ghost)) { - cl_page_delete0(env, ghost, 0); - cl_page_free(env, ghost); - } return page; } - -struct cl_page *cl_page_find(const struct lu_env *env, struct cl_object *o, - pgoff_t idx, struct page *vmpage, - enum cl_page_type type) -{ - return cl_page_find0(env, o, idx, vmpage, type, NULL); -} EXPORT_SYMBOL(cl_page_find); -struct cl_page *cl_page_find_sub(const struct lu_env *env, struct cl_object *o, - pgoff_t idx, struct page *vmpage, - struct cl_page *parent) -{ - return cl_page_find0(env, o, idx, vmpage, parent->cp_type, parent); -} -EXPORT_SYMBOL(cl_page_find_sub); - static inline int cl_page_invariant(const struct cl_page *pg) { - struct cl_object_header *header; struct cl_page *parent; struct cl_page *child; struct cl_io *owner; @@ -461,7 +259,6 @@ static inline int cl_page_invariant(const struct cl_page *pg) */ LINVRNT(cl_page_is_vmlocked(NULL, pg)); - header = cl_object_header(pg->cp_obj); parent = pg->cp_parent; child = pg->cp_child; owner = pg->cp_owner; @@ -473,15 +270,7 @@ static inline int cl_page_invariant(const struct cl_page *pg) ergo(parent, pg->cp_obj != parent->cp_obj) && ergo(owner && parent, parent->cp_owner == pg->cp_owner->ci_parent) && - ergo(owner && child, child->cp_owner->ci_parent == owner) && - /* - * Either page is early in initialization (has neither child - * nor parent yet), or it is in the object radix tree. - */ - ergo(pg->cp_state < CPS_FREEING && pg->cp_type == CPT_CACHEABLE, - (void *)radix_tree_lookup(&header->coh_tree, - pg->cp_index) == pg || - (!child && !parent)); + ergo(owner && child, child->cp_owner->ci_parent == owner); } static void cl_page_state_set0(const struct lu_env *env, @@ -1001,11 +790,8 @@ EXPORT_SYMBOL(cl_page_discard); * pages, e.g,. in a error handling cl_page_find()->cl_page_delete0() * path. Doesn't check page invariant. */ -static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, - int radix) +static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg) { - struct cl_page *tmp = pg; - PASSERT(env, pg, pg == cl_page_top(pg)); PASSERT(env, pg, pg->cp_state != CPS_FREEING); @@ -1014,41 +800,11 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, */ cl_page_owner_clear(pg); - /* - * unexport the page firstly before freeing it so that - * the page content is considered to be invalid. - * We have to do this because a CPS_FREEING cl_page may - * be NOT under the protection of a cl_lock. - * Afterwards, if this page is found by other threads, then this - * page will be forced to reread. - */ - cl_page_export(env, pg, 0); cl_page_state_set0(env, pg, CPS_FREEING); - CL_PAGE_INVOID(env, pg, CL_PAGE_OP(cpo_delete), - (const struct lu_env *, const struct cl_page_slice *)); - - if (tmp->cp_type == CPT_CACHEABLE) { - if (!radix) - /* !radix means that @pg is not yet in the radix tree, - * skip removing it. - */ - tmp = pg->cp_child; - for (; tmp; tmp = tmp->cp_child) { - void *value; - struct cl_object_header *hdr; - - hdr = cl_object_header(tmp->cp_obj); - spin_lock(&hdr->coh_page_guard); - value = radix_tree_delete(&hdr->coh_tree, - tmp->cp_index); - PASSERT(env, tmp, value == tmp); - PASSERT(env, tmp, hdr->coh_pages > 0); - hdr->coh_pages--; - spin_unlock(&hdr->coh_page_guard); - cl_page_put(env, tmp); - } - } + CL_PAGE_INVOID_REVERSE(env, pg, CL_PAGE_OP(cpo_delete), + (const struct lu_env *, + const struct cl_page_slice *)); } /** @@ -1079,29 +835,10 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, void cl_page_delete(const struct lu_env *env, struct cl_page *pg) { PINVRNT(env, pg, cl_page_invariant(pg)); - cl_page_delete0(env, pg, 1); + cl_page_delete0(env, pg); } EXPORT_SYMBOL(cl_page_delete); -/** - * Unmaps page from user virtual memory. - * - * Calls cl_page_operations::cpo_unmap() through all layers top-to-bottom. The - * layer responsible for VM interaction has to unmap page from user space - * virtual memory. - * - * \see cl_page_operations::cpo_unmap() - */ -int cl_page_unmap(const struct lu_env *env, - struct cl_io *io, struct cl_page *pg) -{ - PINVRNT(env, pg, cl_page_is_owned(pg, io)); - PINVRNT(env, pg, cl_page_invariant(pg)); - - return cl_page_invoke(env, io, pg, CL_PAGE_OP(cpo_unmap)); -} -EXPORT_SYMBOL(cl_page_unmap); - /** * Marks page up-to-date. * @@ -1359,53 +1096,6 @@ int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, } EXPORT_SYMBOL(cl_page_is_under_lock); -static int page_prune_cb(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, void *cbdata) -{ - cl_page_own(env, io, page); - cl_page_unmap(env, io, page); - cl_page_discard(env, io, page); - cl_page_disown(env, io, page); - return CLP_GANG_OKAY; -} - -/** - * Purges all cached pages belonging to the object \a obj. - */ -int cl_pages_prune(const struct lu_env *env, struct cl_object *clobj) -{ - struct cl_thread_info *info; - struct cl_object *obj = cl_object_top(clobj); - struct cl_io *io; - int result; - - info = cl_env_info(env); - io = &info->clt_io; - - /* - * initialize the io. This is ugly since we never do IO in this - * function, we just make cl_page_list functions happy. -jay - */ - io->ci_obj = obj; - io->ci_ignore_layout = 1; - result = cl_io_init(env, io, CIT_MISC, obj); - if (result != 0) { - cl_io_fini(env, io); - return io->ci_result; - } - - do { - result = cl_page_gang_lookup(env, obj, io, 0, CL_PAGE_EOF, - page_prune_cb, NULL); - if (result == CLP_GANG_RESCHED) - cond_resched(); - } while (result != CLP_GANG_OKAY); - - cl_io_fini(env, io); - return result; -} -EXPORT_SYMBOL(cl_pages_prune); - /** * Tells transfer engine that only part of a page is to be transmitted. * diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 6196c3bc2da7..c9d4e3ca6caa 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1015,7 +1015,6 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index, lu_ref_add(&page->cp_reference, "truncate", current); if (cl_page_own(env, io, page) == 0) { - cl_page_unmap(env, io, page); cl_page_discard(env, io, page); cl_page_disown(env, io, page); } else { @@ -2136,8 +2135,7 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli) cl_object_get(obj); client_obd_list_unlock(&cli->cl_loi_list_lock); - lu_object_ref_add_at(&obj->co_lu, &link, "check", - current); + lu_object_ref_add_at(&obj->co_lu, &link, "check", current); /* attempt some read/write balancing by alternating between * reads and writes in an object. The makes_rpc checks here @@ -2180,8 +2178,7 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli) osc_object_unlock(osc); osc_list_maint(cli, osc); - lu_object_ref_del_at(&obj->co_lu, &link, "check", - current); + lu_object_ref_del_at(&obj->co_lu, &link, "check", current); cl_object_put(env, obj); client_obd_list_lock(&cli->cl_loi_list_lock); @@ -2994,4 +2991,204 @@ int osc_cache_writeback_range(const struct lu_env *env, struct osc_object *obj, return result; } +/** + * Returns a list of pages by a given [start, end] of \a obj. + * + * \param resched If not NULL, then we give up before hogging CPU for too + * long and set *resched = 1, in that case caller should implement a retry + * logic. + * + * Gang tree lookup (radix_tree_gang_lookup()) optimization is absolutely + * crucial in the face of [offset, EOF] locks. + * + * Return at least one page in @queue unless there is no covered page. + */ +int osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io, + struct osc_object *osc, pgoff_t start, pgoff_t end, + osc_page_gang_cbt cb, void *cbdata) +{ + struct osc_page *ops; + void **pvec; + pgoff_t idx; + unsigned int nr; + unsigned int i; + unsigned int j; + int res = CLP_GANG_OKAY; + bool tree_lock = true; + + idx = start; + pvec = osc_env_info(env)->oti_pvec; + spin_lock(&osc->oo_tree_lock); + while ((nr = radix_tree_gang_lookup(&osc->oo_tree, pvec, + idx, OTI_PVEC_SIZE)) > 0) { + struct cl_page *page; + bool end_of_region = false; + + for (i = 0, j = 0; i < nr; ++i) { + ops = pvec[i]; + pvec[i] = NULL; + + idx = osc_index(ops); + if (idx > end) { + end_of_region = true; + break; + } + + page = cl_page_top(ops->ops_cl.cpl_page); + LASSERT(page->cp_type == CPT_CACHEABLE); + if (page->cp_state == CPS_FREEING) + continue; + + cl_page_get(page); + lu_ref_add_atomic(&page->cp_reference, + "gang_lookup", current); + pvec[j++] = ops; + } + ++idx; + + /* + * Here a delicate locking dance is performed. Current thread + * holds a reference to a page, but has to own it before it + * can be placed into queue. Owning implies waiting, so + * radix-tree lock is to be released. After a wait one has to + * check that pages weren't truncated (cl_page_own() returns + * error in the latter case). + */ + spin_unlock(&osc->oo_tree_lock); + tree_lock = false; + + for (i = 0; i < j; ++i) { + ops = pvec[i]; + if (res == CLP_GANG_OKAY) + res = (*cb)(env, io, ops, cbdata); + + page = cl_page_top(ops->ops_cl.cpl_page); + lu_ref_del(&page->cp_reference, "gang_lookup", current); + cl_page_put(env, page); + } + if (nr < OTI_PVEC_SIZE || end_of_region) + break; + + if (res == CLP_GANG_OKAY && need_resched()) + res = CLP_GANG_RESCHED; + if (res != CLP_GANG_OKAY) + break; + + spin_lock(&osc->oo_tree_lock); + tree_lock = true; + } + if (tree_lock) + spin_unlock(&osc->oo_tree_lock); + return res; +} + +/** + * Check if page @page is covered by an extra lock or discard it. + */ +static int check_and_discard_cb(const struct lu_env *env, struct cl_io *io, + struct osc_page *ops, void *cbdata) +{ + struct osc_thread_info *info = osc_env_info(env); + struct cl_lock *lock = cbdata; + pgoff_t index; + + index = osc_index(ops); + if (index >= info->oti_fn_index) { + struct cl_lock *tmp; + struct cl_page *page = cl_page_top(ops->ops_cl.cpl_page); + + /* refresh non-overlapped index */ + tmp = cl_lock_at_pgoff(env, lock->cll_descr.cld_obj, index, + lock, 1, 0); + if (tmp) { + /* Cache the first-non-overlapped index so as to skip + * all pages within [index, oti_fn_index). This + * is safe because if tmp lock is canceled, it will + * discard these pages. + */ + info->oti_fn_index = tmp->cll_descr.cld_end + 1; + if (tmp->cll_descr.cld_end == CL_PAGE_EOF) + info->oti_fn_index = CL_PAGE_EOF; + cl_lock_put(env, tmp); + } else if (cl_page_own(env, io, page) == 0) { + /* discard the page */ + cl_page_discard(env, io, page); + cl_page_disown(env, io, page); + } else { + LASSERT(page->cp_state == CPS_FREEING); + } + } + + info->oti_next_index = index + 1; + return CLP_GANG_OKAY; +} + +static int discard_cb(const struct lu_env *env, struct cl_io *io, + struct osc_page *ops, void *cbdata) +{ + struct osc_thread_info *info = osc_env_info(env); + struct cl_lock *lock = cbdata; + struct cl_page *page = cl_page_top(ops->ops_cl.cpl_page); + + LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE); + KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, + !PageWriteback(cl_page_vmpage(env, page)))); + KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, + !PageDirty(cl_page_vmpage(env, page)))); + + /* page is top page. */ + info->oti_next_index = osc_index(ops) + 1; + if (cl_page_own(env, io, page) == 0) { + /* discard the page */ + cl_page_discard(env, io, page); + cl_page_disown(env, io, page); + } else { + LASSERT(page->cp_state == CPS_FREEING); + } + + return CLP_GANG_OKAY; +} + +/** + * Discard pages protected by the given lock. This function traverses radix + * tree to find all covering pages and discard them. If a page is being covered + * by other locks, it should remain in cache. + * + * If error happens on any step, the process continues anyway (the reasoning + * behind this being that lock cancellation cannot be delayed indefinitely). + */ +int osc_lock_discard_pages(const struct lu_env *env, struct osc_lock *ols) +{ + struct osc_thread_info *info = osc_env_info(env); + struct cl_io *io = &info->oti_io; + struct cl_object *osc = ols->ols_cl.cls_obj; + struct cl_lock *lock = ols->ols_cl.cls_lock; + struct cl_lock_descr *descr = &lock->cll_descr; + osc_page_gang_cbt cb; + int res; + int result; + + io->ci_obj = cl_object_top(osc); + io->ci_ignore_layout = 1; + result = cl_io_init(env, io, CIT_MISC, io->ci_obj); + if (result != 0) + goto out; + + cb = descr->cld_mode == CLM_READ ? check_and_discard_cb : discard_cb; + info->oti_fn_index = info->oti_next_index = descr->cld_start; + do { + res = osc_page_gang_lookup(env, io, cl2osc(osc), + info->oti_next_index, descr->cld_end, + cb, (void *)lock); + if (info->oti_next_index > descr->cld_end) + break; + + if (res == CLP_GANG_RESCHED) + cond_resched(); + } while (res != CLP_GANG_OKAY); +out: + cl_io_fini(env, io); + return result; +} + /** @} osc */ diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index b6325f5c3542..e70f06ccd095 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -111,7 +111,12 @@ struct osc_thread_info { struct lustre_handle oti_handle; struct cl_page_list oti_plist; struct cl_io oti_io; - struct cl_page *oti_pvec[OTI_PVEC_SIZE]; + void *oti_pvec[OTI_PVEC_SIZE]; + /** + * Fields used by cl_lock_discard_pages(). + */ + pgoff_t oti_next_index; + pgoff_t oti_fn_index; /* first non-overlapped index */ }; struct osc_object { @@ -161,6 +166,13 @@ struct osc_object { * oo_{read|write}_pages soon. */ spinlock_t oo_lock; + + /** + * Radix tree for caching pages + */ + struct radix_tree_root oo_tree; + spinlock_t oo_tree_lock; + unsigned long oo_npages; }; static inline void osc_object_lock(struct osc_object *obj) @@ -569,6 +581,11 @@ static inline struct osc_page *oap2osc_page(struct osc_async_page *oap) return (struct osc_page *)container_of(oap, struct osc_page, ops_oap); } +static inline pgoff_t osc_index(struct osc_page *opg) +{ + return opg->ops_cl.cpl_page->cp_index; +} + static inline struct osc_lock *cl2osc_lock(const struct cl_lock_slice *slice) { LINVRNT(osc_is_object(&slice->cls_obj->co_lu)); @@ -691,6 +708,14 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, int sent, int rc); void osc_extent_release(const struct lu_env *env, struct osc_extent *ext); +int osc_lock_discard_pages(const struct lu_env *env, struct osc_lock *lock); + +typedef int (*osc_page_gang_cbt)(const struct lu_env *, struct cl_io *, + struct osc_page *, void *); +int osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io, + struct osc_object *osc, pgoff_t start, pgoff_t end, + osc_page_gang_cbt cb, void *cbdata); + /** @} osc */ #endif /* OSC_CL_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index a0fa5339c4d3..1536d31fd108 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -391,18 +391,13 @@ static int osc_async_upcall(void *a, int rc) * Checks that there are no pages being written in the extent being truncated. */ static int trunc_check_cb(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, void *cbdata) + struct osc_page *ops, void *cbdata) { - const struct cl_page_slice *slice; - struct osc_page *ops; + struct cl_page *page = ops->ops_cl.cpl_page; struct osc_async_page *oap; __u64 start = *(__u64 *)cbdata; - slice = cl_page_at(page, &osc_device_type); - LASSERT(slice); - ops = cl2osc_page(slice); oap = &ops->ops_oap; - if (oap->oap_cmd & OBD_BRW_WRITE && !list_empty(&oap->oap_pending_item)) CL_PAGE_DEBUG(D_ERROR, env, page, "exists %llu/%s.\n", @@ -434,8 +429,9 @@ static void osc_trunc_check(const struct lu_env *env, struct cl_io *io, /* * Complain if there are pages in the truncated region. */ - cl_page_gang_lookup(env, clob, io, start + partial, CL_PAGE_EOF, - trunc_check_cb, (void *)&size); + osc_page_gang_lookup(env, io, cl2osc(clob), + start + partial, CL_PAGE_EOF, + trunc_check_cb, (void *)&size); } static int osc_io_setattr_start(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 013df9787f3e..3a8a6d129377 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -36,6 +36,7 @@ * Implementation of cl_lock for OSC layer. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_OSC @@ -897,11 +898,8 @@ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) static unsigned long osc_lock_weigh(const struct lu_env *env, const struct cl_lock_slice *slice) { - /* - * don't need to grab coh_page_guard since we don't care the exact # - * of pages.. - */ - return cl_object_header(slice->cls_obj)->coh_pages; + /* TODO: check how many pages are covered by this lock */ + return cl2osc(slice->cls_obj)->oo_npages; } static void osc_lock_build_einfo(const struct lu_env *env, @@ -1276,7 +1274,7 @@ static int osc_lock_flush(struct osc_lock *ols, int discard) result = 0; } - rc = cl_lock_discard_pages(env, lock); + rc = osc_lock_discard_pages(env, ols); if (result == 0 && rc < 0) result = rc; diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index 9d474fcdd9a7..2d2d39a82982 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -36,6 +36,7 @@ * Implementation of cl_object for OSC layer. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_OSC @@ -94,6 +95,7 @@ static int osc_object_init(const struct lu_env *env, struct lu_object *obj, atomic_set(&osc->oo_nr_reads, 0); atomic_set(&osc->oo_nr_writes, 0); spin_lock_init(&osc->oo_lock); + spin_lock_init(&osc->oo_tree_lock); cl_object_page_init(lu2cl(obj), sizeof(struct osc_page)); diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index f0a9870846d7..91ff6070a28d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -36,6 +36,7 @@ * Implementation of cl_page for OSC layer. * * Author: Nikita Danilov + * Author: Jinshan Xiong */ #define DEBUG_SUBSYSTEM S_OSC @@ -326,6 +327,18 @@ static void osc_page_delete(const struct lu_env *env, spin_unlock(&obj->oo_seatbelt); osc_lru_del(osc_cli(obj), opg); + + if (slice->cpl_page->cp_type == CPT_CACHEABLE) { + void *value; + + spin_lock(&obj->oo_tree_lock); + value = radix_tree_delete(&obj->oo_tree, osc_index(opg)); + if (value) + --obj->oo_npages; + spin_unlock(&obj->oo_tree_lock); + + LASSERT(ergo(value, value == opg)); + } } static void osc_page_clip(const struct lu_env *env, @@ -422,8 +435,18 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj, INIT_LIST_HEAD(&opg->ops_lru); /* reserve an LRU space for this page */ - if (page->cp_type == CPT_CACHEABLE && result == 0) + if (page->cp_type == CPT_CACHEABLE && result == 0) { result = osc_lru_reserve(env, osc, opg); + if (result == 0) { + spin_lock(&osc->oo_tree_lock); + result = radix_tree_insert(&osc->oo_tree, + page->cp_index, opg); + if (result == 0) + ++osc->oo_npages; + spin_unlock(&osc->oo_tree_lock); + LASSERT(result == 0); + } + } return result; } @@ -611,7 +634,6 @@ static void discard_pagevec(const struct lu_env *env, struct cl_io *io, struct cl_page *page = pvec[i]; LASSERT(cl_page_is_owned(page, io)); - cl_page_unmap(env, io, page); cl_page_discard(env, io, page); cl_page_disown(env, io, page); cl_page_put(env, page); @@ -652,7 +674,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, atomic_inc(&cli->cl_lru_shrinkers); } - pvec = osc_env_info(env)->oti_pvec; + pvec = (struct cl_page **)osc_env_info(env)->oti_pvec; io = &osc_env_info(env)->oti_io; client_obd_list_lock(&cli->cl_lru_list_lock); -- GitLab From 3c361c1c6f64a675ced590df4a68956020de4a93 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:29 -0400 Subject: [PATCH 0858/9938] staging/lustre/obdclass: Add a preallocated percpu cl_env This change adds support for a single preallocated cl_env per CPU which can be used in circumstances where reschedule is not possible. Currently this interface is only used by the ll_releasepage function. Signed-off-by: Jinshan Xiong Signed-off-by: Prakash Surya Reviewed-on: http://review.whamcloud.com/8174 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Lai Siyao Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 12 ++ drivers/staging/lustre/lustre/llite/rw26.c | 54 +++++---- .../staging/lustre/lustre/obdclass/cl_lock.c | 1 - .../lustre/lustre/obdclass/cl_object.c | 107 ++++++++++++++++++ .../staging/lustre/lustre/obdclass/cl_page.c | 1 - 5 files changed, 152 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 5daf68815949..e8455dc1ce5d 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -2773,6 +2773,16 @@ static inline void *cl_object_page_slice(struct cl_object *clob, return (void *)((char *)page + clob->co_slice_off); } +/** + * Return refcount of cl_object. + */ +static inline int cl_object_refc(struct cl_object *clob) +{ + struct lu_object_header *header = clob->co_lu.lo_header; + + return atomic_read(&header->loh_ref); +} + /** @} cl_object */ /** \defgroup cl_page cl_page @@ -3226,6 +3236,8 @@ void cl_env_reexit(void *cookie); void cl_env_implant(struct lu_env *env, int *refcheck); void cl_env_unplant(struct lu_env *env, int *refcheck); unsigned int cl_env_cache_purge(unsigned int nr); +struct lu_env *cl_env_percpu_get(void); +void cl_env_percpu_put(struct lu_env *env); /** @} cl_env */ diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index b5335de216be..cc49c21cfb8c 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -107,12 +107,12 @@ static void ll_invalidatepage(struct page *vmpage, unsigned int offset, static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask) { - struct cl_env_nest nest; struct lu_env *env; + void *cookie; struct cl_object *obj; struct cl_page *page; struct address_space *mapping; - int result; + int result = 0; LASSERT(PageLocked(vmpage)); if (PageWriteback(vmpage) || PageDirty(vmpage)) @@ -126,30 +126,42 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask) if (!obj) return 1; - /* 1 for page allocator, 1 for cl_page and 1 for page cache */ + /* 1 for caller, 1 for cl_page and 1 for page cache */ if (page_count(vmpage) > 3) return 0; - /* TODO: determine what gfp should be used by @gfp_mask. */ - env = cl_env_nested_get(&nest); - if (IS_ERR(env)) - /* If we can't allocate an env we won't call cl_page_put() - * later on which further means it's impossible to drop - * page refcount by cl_page, so ask kernel to not free - * this page. - */ - return 0; - page = cl_vmpage_page(vmpage, obj); - result = !page; - if (page) { - if (!cl_page_in_use(page)) { - result = 1; - cl_page_delete(env, page); - } - cl_page_put(env, page); + if (!page) + return 1; + + cookie = cl_env_reenter(); + env = cl_env_percpu_get(); + LASSERT(!IS_ERR(env)); + + if (!cl_page_in_use(page)) { + result = 1; + cl_page_delete(env, page); } - cl_env_nested_put(&nest, env); + + /* To use percpu env array, the call path can not be rescheduled; + * otherwise percpu array will be messed if ll_releaspage() called + * again on the same CPU. + * + * If this page holds the last refc of cl_object, the following + * call path may cause reschedule: + * cl_page_put -> cl_page_free -> cl_object_put -> + * lu_object_put -> lu_object_free -> lov_delete_raid0 -> + * cl_locks_prune. + * + * However, the kernel can't get rid of this inode until all pages have + * been cleaned up. Now that we hold page lock here, it's pretty safe + * that we won't get into object delete path. + */ + LASSERT(cl_object_refc(obj) > 1); + cl_page_put(env, page); + + cl_env_percpu_put(env); + cl_env_reexit(cookie); return result; } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index 32ecc5ad0a3e..fe8059a0ce5d 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -255,7 +255,6 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock) LINVRNT(!cl_lock_is_mutexed(lock)); cl_lock_trace(D_DLMTRACE, env, "free lock", lock); - might_sleep(); while (!list_empty(&lock->cll_layers)) { struct cl_lock_slice *slice; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 65b640223e8f..fa9b083915d9 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -390,6 +390,8 @@ static int cache_stats_print(const struct cache_stats *cs, return 0; } +static void cl_env_percpu_refill(void); + /** * Initialize client site. * @@ -409,6 +411,7 @@ int cl_site_init(struct cl_site *s, struct cl_device *d) atomic_set(&s->cs_pages_state[0], 0); for (i = 0; i < ARRAY_SIZE(s->cs_locks_state); ++i) atomic_set(&s->cs_locks_state[i], 0); + cl_env_percpu_refill(); } return result; } @@ -1001,6 +1004,104 @@ void cl_lvb2attr(struct cl_attr *attr, const struct ost_lvb *lvb) } EXPORT_SYMBOL(cl_lvb2attr); +static struct cl_env cl_env_percpu[NR_CPUS]; + +static int cl_env_percpu_init(void) +{ + struct cl_env *cle; + int tags = LCT_REMEMBER | LCT_NOREF; + int i, j; + int rc = 0; + + for_each_possible_cpu(i) { + struct lu_env *env; + + cle = &cl_env_percpu[i]; + env = &cle->ce_lu; + + INIT_LIST_HEAD(&cle->ce_linkage); + cle->ce_magic = &cl_env_init0; + rc = lu_env_init(env, LCT_CL_THREAD | tags); + if (rc == 0) { + rc = lu_context_init(&cle->ce_ses, LCT_SESSION | tags); + if (rc == 0) { + lu_context_enter(&cle->ce_ses); + env->le_ses = &cle->ce_ses; + } else { + lu_env_fini(env); + } + } + if (rc != 0) + break; + } + if (rc != 0) { + /* Indices 0 to i (excluding i) were correctly initialized, + * thus we must uninitialize up to i, the rest are undefined. + */ + for (j = 0; j < i; j++) { + cle = &cl_env_percpu[i]; + lu_context_exit(&cle->ce_ses); + lu_context_fini(&cle->ce_ses); + lu_env_fini(&cle->ce_lu); + } + } + + return rc; +} + +static void cl_env_percpu_fini(void) +{ + int i; + + for_each_possible_cpu(i) { + struct cl_env *cle = &cl_env_percpu[i]; + + lu_context_exit(&cle->ce_ses); + lu_context_fini(&cle->ce_ses); + lu_env_fini(&cle->ce_lu); + } +} + +static void cl_env_percpu_refill(void) +{ + int i; + + for_each_possible_cpu(i) + lu_env_refill(&cl_env_percpu[i].ce_lu); +} + +void cl_env_percpu_put(struct lu_env *env) +{ + struct cl_env *cle; + int cpu; + + cpu = smp_processor_id(); + cle = cl_env_container(env); + LASSERT(cle == &cl_env_percpu[cpu]); + + cle->ce_ref--; + LASSERT(cle->ce_ref == 0); + + CL_ENV_DEC(busy); + cl_env_detach(cle); + cle->ce_debug = NULL; + + put_cpu(); +} +EXPORT_SYMBOL(cl_env_percpu_put); + +struct lu_env *cl_env_percpu_get() +{ + struct cl_env *cle; + + cle = &cl_env_percpu[get_cpu()]; + cl_env_init0(cle, __builtin_return_address(0)); + + cl_env_attach(cle); + return &cle->ce_lu; +} +EXPORT_SYMBOL(cl_env_percpu_get); + /***************************************************************************** * * Temporary prototype thing: mirror obd-devices into cl devices. @@ -1154,6 +1255,11 @@ int cl_global_init(void) if (result) goto out_lock; + result = cl_env_percpu_init(); + if (result) + /* no cl_env_percpu_fini on error */ + goto out_lock; + return 0; out_lock: cl_lock_fini(); @@ -1171,6 +1277,7 @@ int cl_global_init(void) */ void cl_global_fini(void) { + cl_env_percpu_fini(); cl_lock_fini(); cl_page_fini(); lu_context_key_degister(&cl_key); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 816983678a03..bab8a74b78ae 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -123,7 +123,6 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page) PASSERT(env, page, !page->cp_parent); PASSERT(env, page, page->cp_state == CPS_FREEING); - might_sleep(); while (!list_empty(&page->cp_layers)) { struct cl_page_slice *slice; -- GitLab From 77605e41a26f22343db90d6434970a1800e5e8b5 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:30 -0400 Subject: [PATCH 0859/9938] staging/lustre/clio: add pages into writeback cache in batches in ll_write_end(), instead of adding the page into writeback cache directly, it will be held in a page list. After enough pages have been collected, issue them all with cio_commit_async(). Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/7893 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 77 +-- .../staging/lustre/lustre/include/lclient.h | 6 + drivers/staging/lustre/lustre/llite/file.c | 11 +- .../lustre/lustre/llite/llite_internal.h | 8 +- drivers/staging/lustre/lustre/llite/rw.c | 186 ++----- drivers/staging/lustre/lustre/llite/rw26.c | 210 +++++++- .../lustre/lustre/llite/vvp_internal.h | 10 +- drivers/staging/lustre/lustre/llite/vvp_io.c | 490 +++++++++--------- .../lustre/lustre/lov/lov_cl_internal.h | 2 + drivers/staging/lustre/lustre/lov/lov_io.c | 219 ++++---- drivers/staging/lustre/lustre/lov/lov_page.c | 28 - .../staging/lustre/lustre/obdclass/cl_io.c | 108 ++-- .../staging/lustre/lustre/obdclass/cl_page.c | 38 -- .../lustre/lustre/obdecho/echo_client.c | 25 +- drivers/staging/lustre/lustre/osc/osc_cache.c | 14 +- .../lustre/lustre/osc/osc_cl_internal.h | 2 + .../staging/lustre/lustre/osc/osc_internal.h | 6 + drivers/staging/lustre/lustre/osc/osc_io.c | 160 +++--- drivers/staging/lustre/lustre/osc/osc_page.c | 32 +- .../staging/lustre/lustre/osc/osc_request.c | 56 +- 20 files changed, 792 insertions(+), 896 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index e8455dc1ce5d..c3865ec49769 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1019,26 +1019,6 @@ struct cl_page_operations { */ int (*cpo_make_ready)(const struct lu_env *env, const struct cl_page_slice *slice); - /** - * Announce that this page is to be written out - * opportunistically, that is, page is dirty, it is not - * necessary to start write-out transfer right now, but - * eventually page has to be written out. - * - * Main caller of this is the write path (see - * vvp_io_commit_write()), using this method to build a - * "transfer cache" from which large transfers are then - * constructed by the req-formation engine. - * - * \todo XXX it would make sense to add page-age tracking - * semantics here, and to oblige the req-formation engine to - * send the page out not later than it is too old. - * - * \see cl_page_cache_add() - */ - int (*cpo_cache_add)(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io); } io[CRT_NR]; /** * Tell transfer engine that only [to, from] part of a page should be @@ -2023,6 +2003,8 @@ struct cl_io_slice { struct list_head cis_linkage; }; +typedef void (*cl_commit_cbt)(const struct lu_env *, struct cl_io *, + struct cl_page *); /** * Per-layer io operations. * \see vvp_io_ops, lov_io_ops, lovsub_io_ops, osc_io_ops @@ -2106,7 +2088,7 @@ struct cl_io_operations { void (*cio_fini)(const struct lu_env *env, const struct cl_io_slice *slice); } op[CIT_OP_NR]; - struct { + /** * Submit pages from \a queue->c2_qin for IO, and move * successfully submitted pages into \a queue->c2_qout. Return @@ -2119,7 +2101,15 @@ struct cl_io_operations { const struct cl_io_slice *slice, enum cl_req_type crt, struct cl_2queue *queue); - } req_op[CRT_NR]; + /** + * Queue async page for write. + * The difference between cio_submit and cio_queue is that + * cio_submit is for urgent request. + */ + int (*cio_commit_async)(const struct lu_env *env, + const struct cl_io_slice *slice, + struct cl_page_list *queue, int from, int to, + cl_commit_cbt cb); /** * Read missing page. * @@ -2131,31 +2121,6 @@ struct cl_io_operations { int (*cio_read_page)(const struct lu_env *env, const struct cl_io_slice *slice, const struct cl_page_slice *page); - /** - * Prepare write of a \a page. Called bottom-to-top by a top-level - * cl_io_operations::op[CIT_WRITE]::cio_start() to prepare page for - * get data from user-level buffer. - * - * \pre io->ci_type == CIT_WRITE - * - * \see vvp_io_prepare_write(), lov_io_prepare_write(), - * osc_io_prepare_write(). - */ - int (*cio_prepare_write)(const struct lu_env *env, - const struct cl_io_slice *slice, - const struct cl_page_slice *page, - unsigned from, unsigned to); - /** - * - * \pre io->ci_type == CIT_WRITE - * - * \see vvp_io_commit_write(), lov_io_commit_write(), - * osc_io_commit_write(). - */ - int (*cio_commit_write)(const struct lu_env *env, - const struct cl_io_slice *slice, - const struct cl_page_slice *page, - unsigned from, unsigned to); /** * Optional debugging helper. Print given io slice. */ @@ -3044,15 +3009,14 @@ int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io, struct cl_lock_descr *descr); int cl_io_read_page(const struct lu_env *env, struct cl_io *io, struct cl_page *page); -int cl_io_prepare_write(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, unsigned from, unsigned to); -int cl_io_commit_write(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, unsigned from, unsigned to); int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io, enum cl_req_type iot, struct cl_2queue *queue); int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, enum cl_req_type iot, struct cl_2queue *queue, long timeout); +int cl_io_commit_async(const struct lu_env *env, struct cl_io *io, + struct cl_page_list *queue, int from, int to, + cl_commit_cbt cb); int cl_io_is_going(const struct lu_env *env); /** @@ -3108,6 +3072,12 @@ static inline struct cl_page *cl_page_list_last(struct cl_page_list *plist) return list_entry(plist->pl_pages.prev, struct cl_page, cp_batch); } +static inline struct cl_page *cl_page_list_first(struct cl_page_list *plist) +{ + LASSERT(plist->pl_nr > 0); + return list_entry(plist->pl_pages.next, struct cl_page, cp_batch); +} + /** * Iterate over pages in a page list. */ @@ -3124,9 +3094,14 @@ void cl_page_list_init(struct cl_page_list *plist); void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page); void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src, struct cl_page *page); +void cl_page_list_move_head(struct cl_page_list *dst, struct cl_page_list *src, + struct cl_page *page); void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head); +void cl_page_list_del(const struct lu_env *env, struct cl_page_list *plist, + struct cl_page *page); void cl_page_list_disown(const struct lu_env *env, struct cl_io *io, struct cl_page_list *plist); +void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist); void cl_2queue_init(struct cl_2queue *queue); void cl_2queue_disown(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index 5d839a9f789f..6c3a30af0727 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -91,6 +91,12 @@ struct ccc_io { struct { enum ccc_setattr_lock_type cui_local_lock; } setattr; + struct { + struct cl_page_list cui_queue; + unsigned long cui_written; + int cui_from; + int cui_to; + } write; } u; /** * True iff io is processing glimpse right now. diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index cf619af3caf5..127fff6ebe44 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1120,6 +1120,9 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, struct cl_io *io; ssize_t result; + CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: %llu, count: %zd\n", + file->f_path.dentry->d_name.name, iot, *ppos, count); + restart: io = ccc_env_thread_io(env); ll_io_init(io, file, iot == CIT_WRITE); @@ -1144,9 +1147,8 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, goto out; } write_mutex_locked = 1; - } else if (iot == CIT_READ) { - down_read(&lli->lli_trunc_sem); } + down_read(&lli->lli_trunc_sem); break; case IO_SPLICE: vio->u.splice.cui_pipe = args->u.splice.via_pipe; @@ -1157,10 +1159,10 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, LBUG(); } result = cl_io_loop(env, io); + if (args->via_io_subtype == IO_NORMAL) + up_read(&lli->lli_trunc_sem); if (write_mutex_locked) mutex_unlock(&lli->lli_write_mutex); - else if (args->via_io_subtype == IO_NORMAL && iot == CIT_READ) - up_read(&lli->lli_trunc_sem); } else { /* cl_io_rw_init() handled IO */ result = io->ci_result; @@ -1197,6 +1199,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, fd->fd_write_failed = true; } } + CDEBUG(D_VFSTRACE, "iot: %d, result: %zd\n", iot, result); return result; } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 3e1572cb457b..08fe0ea5ee8f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -697,8 +697,6 @@ int ll_md_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *, struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de); /* llite/rw.c */ -int ll_prepare_write(struct file *, struct page *, unsigned from, unsigned to); -int ll_commit_write(struct file *, struct page *, unsigned from, unsigned to); int ll_writepage(struct page *page, struct writeback_control *wbc); int ll_writepages(struct address_space *, struct writeback_control *wbc); int ll_readpage(struct file *file, struct page *page); @@ -706,6 +704,9 @@ void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras); int ll_readahead(const struct lu_env *env, struct cl_io *io, struct ll_readahead_state *ras, struct address_space *mapping, struct cl_page_list *queue, int flags); +int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io); +struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage); +void ll_cl_fini(struct ll_cl_context *lcc); extern const struct address_space_operations ll_aops; @@ -1476,4 +1477,7 @@ int ll_layout_restore(struct inode *inode); int ll_xattr_init(void); void ll_xattr_fini(void); +int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, + struct cl_page *page, enum cl_req_type crt); + #endif /* LLITE_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 01b8365c1dda..dcccdecbad00 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -63,7 +63,7 @@ * Finalizes cl-data before exiting typical address_space operation. Dual to * ll_cl_init(). */ -static void ll_cl_fini(struct ll_cl_context *lcc) +void ll_cl_fini(struct ll_cl_context *lcc) { struct lu_env *env = lcc->lcc_env; struct cl_io *io = lcc->lcc_io; @@ -84,8 +84,7 @@ static void ll_cl_fini(struct ll_cl_context *lcc) * Initializes common cl-data at the typical address_space operation entry * point. */ -static struct ll_cl_context *ll_cl_init(struct file *file, - struct page *vmpage, int create) +struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) { struct ll_cl_context *lcc; struct lu_env *env; @@ -96,7 +95,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file, int refcheck; int result = 0; - clob = ll_i2info(vmpage->mapping->host)->lli_clob; + clob = ll_i2info(file_inode(file))->lli_clob; LASSERT(clob); env = cl_env_get(&refcheck); @@ -111,62 +110,18 @@ static struct ll_cl_context *ll_cl_init(struct file *file, cio = ccc_env_io(env); io = cio->cui_cl.cis_io; - if (!io && create) { - struct inode *inode = vmpage->mapping->host; - loff_t pos; + lcc->lcc_io = io; + if (!io) { + struct inode *inode = file_inode(file); - if (inode_trylock(inode)) { - inode_unlock((inode)); + CERROR("%s: " DFID " no active IO, please file a ticket.\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(ll_inode2fid(inode))); + dump_stack(); - /* this is too bad. Someone is trying to write the - * page w/o holding inode mutex. This means we can - * add dirty pages into cache during truncate - */ - CERROR("Proc %s is dirtying page w/o inode lock, this will break truncate\n", - current->comm); - dump_stack(); - LBUG(); - return ERR_PTR(-EIO); - } - - /* - * Loop-back driver calls ->prepare_write(). - * methods directly, bypassing file system ->write() operation, - * so cl_io has to be created here. - */ - io = ccc_env_thread_io(env); - ll_io_init(io, file, 1); - - /* No lock at all for this kind of IO - we can't do it because - * we have held page lock, it would cause deadlock. - * XXX: This causes poor performance to loop device - One page - * per RPC. - * In order to get better performance, users should use - * lloop driver instead. - */ - io->ci_lockreq = CILR_NEVER; - - pos = vmpage->index << PAGE_CACHE_SHIFT; - - /* Create a temp IO to serve write. */ - result = cl_io_rw_init(env, io, CIT_WRITE, pos, PAGE_CACHE_SIZE); - if (result == 0) { - cio->cui_fd = LUSTRE_FPRIVATE(file); - cio->cui_iter = NULL; - result = cl_io_iter_init(env, io); - if (result == 0) { - result = cl_io_lock(env, io); - if (result == 0) - result = cl_io_start(env, io); - } - } else - result = io->ci_result; - } - - lcc->lcc_io = io; - if (!io) result = -EIO; - if (result == 0) { + } + if (result == 0 && vmpage) { struct cl_page *page; LASSERT(io->ci_state == CIS_IO_GOING); @@ -185,99 +140,9 @@ static struct ll_cl_context *ll_cl_init(struct file *file, lcc = ERR_PTR(result); } - CDEBUG(D_VFSTRACE, "%lu@"DFID" -> %d %p %p\n", - vmpage->index, PFID(lu_object_fid(&clob->co_lu)), result, - env, io); return lcc; } -static struct ll_cl_context *ll_cl_get(void) -{ - struct ll_cl_context *lcc; - struct lu_env *env; - int refcheck; - - env = cl_env_get(&refcheck); - LASSERT(!IS_ERR(env)); - lcc = &vvp_env_info(env)->vti_io_ctx; - LASSERT(env == lcc->lcc_env); - LASSERT(current == lcc->lcc_cookie); - cl_env_put(env, &refcheck); - - /* env has got in ll_cl_init, so it is still usable. */ - return lcc; -} - -/** - * ->prepare_write() address space operation called by generic_file_write() - * for every page during write. - */ -int ll_prepare_write(struct file *file, struct page *vmpage, unsigned from, - unsigned to) -{ - struct ll_cl_context *lcc; - int result; - - lcc = ll_cl_init(file, vmpage, 1); - if (!IS_ERR(lcc)) { - struct lu_env *env = lcc->lcc_env; - struct cl_io *io = lcc->lcc_io; - struct cl_page *page = lcc->lcc_page; - - cl_page_assume(env, io, page); - - result = cl_io_prepare_write(env, io, page, from, to); - if (result == 0) { - /* - * Add a reference, so that page is not evicted from - * the cache until ->commit_write() is called. - */ - cl_page_get(page); - lu_ref_add(&page->cp_reference, "prepare_write", - current); - } else { - cl_page_unassume(env, io, page); - ll_cl_fini(lcc); - } - /* returning 0 in prepare assumes commit must be called - * afterwards - */ - } else { - result = PTR_ERR(lcc); - } - return result; -} - -int ll_commit_write(struct file *file, struct page *vmpage, unsigned from, - unsigned to) -{ - struct ll_cl_context *lcc; - struct lu_env *env; - struct cl_io *io; - struct cl_page *page; - int result = 0; - - lcc = ll_cl_get(); - env = lcc->lcc_env; - page = lcc->lcc_page; - io = lcc->lcc_io; - - LASSERT(cl_page_is_owned(page, io)); - LASSERT(from <= to); - if (from != to) /* handle short write case. */ - result = cl_io_commit_write(env, io, page, from, to); - if (cl_page_is_owned(page, io)) - cl_page_unassume(env, io, page); - - /* - * Release reference acquired by ll_prepare_write(). - */ - lu_ref_del(&page->cp_reference, "prepare_write", current); - cl_page_put(env, page); - ll_cl_fini(lcc); - return result; -} - static void ll_ra_stats_inc_sbi(struct ll_sb_info *sbi, enum ra_stat which); /** @@ -1251,7 +1116,7 @@ int ll_readpage(struct file *file, struct page *vmpage) struct ll_cl_context *lcc; int result; - lcc = ll_cl_init(file, vmpage, 0); + lcc = ll_cl_init(file, vmpage); if (!IS_ERR(lcc)) { struct lu_env *env = lcc->lcc_env; struct cl_io *io = lcc->lcc_io; @@ -1273,3 +1138,28 @@ int ll_readpage(struct file *file, struct page *vmpage) } return result; } + +int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, + struct cl_page *page, enum cl_req_type crt) +{ + struct cl_2queue *queue; + int result; + + LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); + + queue = &io->ci_queue; + cl_2queue_init_page(queue, page); + + result = cl_io_submit_sync(env, io, crt, queue, 0); + LASSERT(cl_page_is_owned(page, io)); + + if (crt == CRT_READ) + /* + * in CRT_WRITE case page is left locked even in case of + * error. + */ + cl_page_list_disown(env, io, &queue->c2_qin); + cl_2queue_fini(env, queue); + + return result; +} diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index cc49c21cfb8c..e8d29e1fb691 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -462,57 +462,211 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, inode_unlock(inode); if (tot_bytes > 0) { - if (iov_iter_rw(iter) == WRITE) { - struct lov_stripe_md *lsm; - - lsm = ccc_inode_lsm_get(inode); - LASSERT(lsm); - lov_stripe_lock(lsm); - obd_adjust_kms(ll_i2dtexp(inode), lsm, file_offset, 0); - lov_stripe_unlock(lsm); - ccc_inode_lsm_put(inode, lsm); - } + struct ccc_io *cio = ccc_env_io(env); + + /* no commit async for direct IO */ + cio->u.write.cui_written += tot_bytes; } cl_env_put(env, &refcheck); return tot_bytes ? : result; } +/** + * Prepare partially written-to page for a write. + */ +static int ll_prepare_partial_page(const struct lu_env *env, struct cl_io *io, + struct cl_page *pg) +{ + struct cl_object *obj = io->ci_obj; + struct cl_attr *attr = ccc_env_thread_attr(env); + loff_t offset = cl_offset(obj, pg->cp_index); + int result; + + cl_object_attr_lock(obj); + result = cl_object_attr_get(env, obj, attr); + cl_object_attr_unlock(obj); + if (result == 0) { + struct ccc_page *cp; + + cp = cl2ccc_page(cl_page_at(pg, &vvp_device_type)); + + /* + * If are writing to a new page, no need to read old data. + * The extent locking will have updated the KMS, and for our + * purposes here we can treat it like i_size. + */ + if (attr->cat_kms <= offset) { + char *kaddr = kmap_atomic(cp->cpg_page); + + memset(kaddr, 0, cl_page_size(obj)); + kunmap_atomic(kaddr); + } else if (cp->cpg_defer_uptodate) { + cp->cpg_ra_used = 1; + } else { + result = ll_page_sync_io(env, io, pg, CRT_READ); + } + } + return result; +} + static int ll_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { + struct ll_cl_context *lcc; + struct lu_env *env; + struct cl_io *io; + struct cl_page *page; + struct cl_object *clob = ll_i2info(mapping->host)->lli_clob; pgoff_t index = pos >> PAGE_CACHE_SHIFT; - struct page *page; - int rc; - unsigned from = pos & (PAGE_CACHE_SIZE - 1); + struct page *vmpage = NULL; + unsigned int from = pos & (PAGE_CACHE_SIZE - 1); + unsigned int to = from + len; + int result = 0; - page = grab_cache_page_write_begin(mapping, index, flags); - if (!page) - return -ENOMEM; + CDEBUG(D_VFSTRACE, "Writing %lu of %d to %d bytes\n", index, from, len); + + lcc = ll_cl_init(file, NULL); + if (IS_ERR(lcc)) { + result = PTR_ERR(lcc); + goto out; + } + + env = lcc->lcc_env; + io = lcc->lcc_io; + + /* To avoid deadlock, try to lock page first. */ + vmpage = grab_cache_page_nowait(mapping, index); + if (unlikely(!vmpage || PageDirty(vmpage))) { + struct ccc_io *cio = ccc_env_io(env); + struct cl_page_list *plist = &cio->u.write.cui_queue; + + /* if the page is already in dirty cache, we have to commit + * the pages right now; otherwise, it may cause deadlock + * because it holds page lock of a dirty page and request for + * more grants. It's okay for the dirty page to be the first + * one in commit page list, though. + */ + if (vmpage && PageDirty(vmpage) && plist->pl_nr > 0) { + unlock_page(vmpage); + page_cache_release(vmpage); + vmpage = NULL; + } - *pagep = page; + /* commit pages and then wait for page lock */ + result = vvp_io_write_commit(env, io); + if (result < 0) + goto out; - rc = ll_prepare_write(file, page, from, from + len); - if (rc) { - unlock_page(page); - page_cache_release(page); + if (!vmpage) { + vmpage = grab_cache_page_write_begin(mapping, index, + flags); + if (!vmpage) { + result = -ENOMEM; + goto out; + } + } } - return rc; + + page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE); + if (IS_ERR(page)) { + result = PTR_ERR(page); + goto out; + } + + lcc->lcc_page = page; + lu_ref_add(&page->cp_reference, "cl_io", io); + + cl_page_assume(env, io, page); + if (!PageUptodate(vmpage)) { + /* + * We're completely overwriting an existing page, + * so _don't_ set it up to date until commit_write + */ + if (from == 0 && to == PAGE_SIZE) { + CL_PAGE_HEADER(D_PAGE, env, page, "full page write\n"); + POISON_PAGE(vmpage, 0x11); + } else { + /* TODO: can be optimized at OSC layer to check if it + * is a lockless IO. In that case, it's not necessary + * to read the data. + */ + result = ll_prepare_partial_page(env, io, page); + if (result == 0) + SetPageUptodate(vmpage); + } + } + if (result < 0) + cl_page_unassume(env, io, page); +out: + if (result < 0) { + if (vmpage) { + unlock_page(vmpage); + page_cache_release(vmpage); + } + if (!IS_ERR(lcc)) + ll_cl_fini(lcc); + } else { + *pagep = vmpage; + *fsdata = lcc; + } + return result; } static int ll_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) + struct page *vmpage, void *fsdata) { + struct ll_cl_context *lcc = fsdata; + struct lu_env *env; + struct cl_io *io; + struct ccc_io *cio; + struct cl_page *page; unsigned from = pos & (PAGE_CACHE_SIZE - 1); - int rc; + bool unplug = false; + int result = 0; + + page_cache_release(vmpage); + + env = lcc->lcc_env; + page = lcc->lcc_page; + io = lcc->lcc_io; + cio = ccc_env_io(env); + + LASSERT(cl_page_is_owned(page, io)); + if (copied > 0) { + struct cl_page_list *plist = &cio->u.write.cui_queue; + + lcc->lcc_page = NULL; /* page will be queued */ + + /* Add it into write queue */ + cl_page_list_add(plist, page); + if (plist->pl_nr == 1) /* first page */ + cio->u.write.cui_from = from; + else + LASSERT(from == 0); + cio->u.write.cui_to = from + copied; + + /* We may have one full RPC, commit it soon */ + if (plist->pl_nr >= PTLRPC_MAX_BRW_PAGES) + unplug = true; + + CL_PAGE_DEBUG(D_VFSTRACE, env, page, + "queued page: %d.\n", plist->pl_nr); + } else { + cl_page_disown(env, io, page); + + /* page list is not contiguous now, commit it now */ + unplug = true; + } - rc = ll_commit_write(file, page, from, from + copied); - unlock_page(page); - page_cache_release(page); + if (unplug || + file->f_flags & O_SYNC || IS_SYNC(file_inode(file))) + result = vvp_io_write_commit(env, io); - return rc ?: copied; + ll_cl_fini(lcc); + return result >= 0 ? copied : result; } #ifdef CONFIG_MIGRATION diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index bb393378c9bb..9abde114ba16 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -44,17 +44,15 @@ #include "../include/cl_object.h" #include "llite_internal.h" -int vvp_io_init(const struct lu_env *env, - struct cl_object *obj, struct cl_io *io); -int vvp_lock_init(const struct lu_env *env, - struct cl_object *obj, struct cl_lock *lock, - const struct cl_io *io); +int vvp_io_init(const struct lu_env *env, struct cl_object *obj, + struct cl_io *io); +int vvp_lock_init(const struct lu_env *env, struct cl_object *obj, + struct cl_lock *lock, const struct cl_io *io); int vvp_page_init(const struct lu_env *env, struct cl_object *obj, struct cl_page *page, struct page *vmpage); struct lu_object *vvp_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); - struct ccc_object *cl_inode2ccc(struct inode *inode); extern const struct file_operations vvp_dump_pgcache_file_ops; diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index ffe301b6f453..f4a1384730fa 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -101,6 +101,27 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, * */ +static int vvp_io_write_iter_init(const struct lu_env *env, + const struct cl_io_slice *ios) +{ + struct ccc_io *cio = cl2ccc_io(env, ios); + + cl_page_list_init(&cio->u.write.cui_queue); + cio->u.write.cui_written = 0; + cio->u.write.cui_from = 0; + cio->u.write.cui_to = PAGE_SIZE; + + return 0; +} + +static void vvp_io_write_iter_fini(const struct lu_env *env, + const struct cl_io_slice *ios) +{ + struct ccc_io *cio = cl2ccc_io(env, ios); + + LASSERT(cio->u.write.cui_queue.pl_nr == 0); +} + static int vvp_io_fault_iter_init(const struct lu_env *env, const struct cl_io_slice *ios) { @@ -563,6 +584,183 @@ static void vvp_io_read_fini(const struct lu_env *env, const struct cl_io_slice vvp_io_fini(env, ios); } +static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, + struct cl_page_list *plist, int from, int to) +{ + struct cl_2queue *queue = &io->ci_queue; + struct cl_page *page; + unsigned int bytes = 0; + int rc = 0; + + if (plist->pl_nr == 0) + return 0; + + if (from != 0) { + page = cl_page_list_first(plist); + cl_page_clip(env, page, from, + plist->pl_nr == 1 ? to : PAGE_SIZE); + } + if (to != PAGE_SIZE && plist->pl_nr > 1) { + page = cl_page_list_last(plist); + cl_page_clip(env, page, 0, to); + } + + cl_2queue_init(queue); + cl_page_list_splice(plist, &queue->c2_qin); + rc = cl_io_submit_sync(env, io, CRT_WRITE, queue, 0); + + /* plist is not sorted any more */ + cl_page_list_splice(&queue->c2_qin, plist); + cl_page_list_splice(&queue->c2_qout, plist); + cl_2queue_fini(env, queue); + + if (rc == 0) { + /* calculate bytes */ + bytes = plist->pl_nr << PAGE_SHIFT; + bytes -= from + PAGE_SIZE - to; + + while (plist->pl_nr > 0) { + page = cl_page_list_first(plist); + cl_page_list_del(env, plist, page); + + cl_page_clip(env, page, 0, PAGE_SIZE); + + SetPageUptodate(cl_page_vmpage(env, page)); + cl_page_disown(env, io, page); + + /* held in ll_cl_init() */ + lu_ref_del(&page->cp_reference, "cl_io", io); + cl_page_put(env, page); + } + } + + return bytes > 0 ? bytes : rc; +} + +static void write_commit_callback(const struct lu_env *env, struct cl_io *io, + struct cl_page *page) +{ + const struct cl_page_slice *slice; + struct ccc_page *cp; + struct page *vmpage; + + slice = cl_page_at(page, &vvp_device_type); + cp = cl2ccc_page(slice); + vmpage = cp->cpg_page; + + SetPageUptodate(vmpage); + set_page_dirty(vmpage); + vvp_write_pending(cl2ccc(slice->cpl_obj), cp); + + cl_page_disown(env, io, page); + + /* held in ll_cl_init() */ + lu_ref_del(&page->cp_reference, "cl_io", io); + cl_page_put(env, page); +} + +/* make sure the page list is contiguous */ +static bool page_list_sanity_check(struct cl_page_list *plist) +{ + struct cl_page *page; + pgoff_t index = CL_PAGE_EOF; + + cl_page_list_for_each(page, plist) { + if (index == CL_PAGE_EOF) { + index = page->cp_index; + continue; + } + + ++index; + if (index == page->cp_index) + continue; + + return false; + } + return true; +} + +/* Return how many bytes have queued or written */ +int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) +{ + struct cl_object *obj = io->ci_obj; + struct inode *inode = ccc_object_inode(obj); + struct ccc_io *cio = ccc_env_io(env); + struct cl_page_list *queue = &cio->u.write.cui_queue; + struct cl_page *page; + int rc = 0; + int bytes = 0; + unsigned int npages = cio->u.write.cui_queue.pl_nr; + + if (npages == 0) + return 0; + + CDEBUG(D_VFSTRACE, "commit async pages: %d, from %d, to %d\n", + npages, cio->u.write.cui_from, cio->u.write.cui_to); + + LASSERT(page_list_sanity_check(queue)); + + /* submit IO with async write */ + rc = cl_io_commit_async(env, io, queue, + cio->u.write.cui_from, cio->u.write.cui_to, + write_commit_callback); + npages -= queue->pl_nr; /* already committed pages */ + if (npages > 0) { + /* calculate how many bytes were written */ + bytes = npages << PAGE_SHIFT; + + /* first page */ + bytes -= cio->u.write.cui_from; + if (queue->pl_nr == 0) /* last page */ + bytes -= PAGE_SIZE - cio->u.write.cui_to; + LASSERTF(bytes > 0, "bytes = %d, pages = %d\n", bytes, npages); + + cio->u.write.cui_written += bytes; + + CDEBUG(D_VFSTRACE, "Committed %d pages %d bytes, tot: %ld\n", + npages, bytes, cio->u.write.cui_written); + + /* the first page must have been written. */ + cio->u.write.cui_from = 0; + } + LASSERT(page_list_sanity_check(queue)); + LASSERT(ergo(rc == 0, queue->pl_nr == 0)); + + /* out of quota, try sync write */ + if (rc == -EDQUOT && !cl_io_is_mkwrite(io)) { + rc = vvp_io_commit_sync(env, io, queue, + cio->u.write.cui_from, + cio->u.write.cui_to); + if (rc > 0) { + cio->u.write.cui_written += rc; + rc = 0; + } + } + + /* update inode size */ + ll_merge_lvb(env, inode); + + /* Now the pages in queue were failed to commit, discard them + * unless they were dirtied before. + */ + while (queue->pl_nr > 0) { + page = cl_page_list_first(queue); + cl_page_list_del(env, queue, page); + + if (!PageDirty(cl_page_vmpage(env, page))) + cl_page_discard(env, io, page); + + cl_page_disown(env, io, page); + + /* held in ll_cl_init() */ + lu_ref_del(&page->cp_reference, "cl_io", io); + cl_page_put(env, page); + } + cl_page_list_fini(env, queue); + + return rc; +} + static int vvp_io_write_start(const struct lu_env *env, const struct cl_io_slice *ios) { @@ -596,9 +794,24 @@ static int vvp_io_write_start(const struct lu_env *env, result = generic_file_write_iter(cio->cui_iocb, cio->cui_iter); if (result > 0) { + result = vvp_io_write_commit(env, io); + if (cio->u.write.cui_written > 0) { + result = cio->u.write.cui_written; + io->ci_nob += result; + + CDEBUG(D_VFSTRACE, "write: nob %zd, result: %zd\n", + io->ci_nob, result); + } + } + if (result > 0) { + struct ll_inode_info *lli = ll_i2info(inode); + + spin_lock(&lli->lli_lock); + lli->lli_flags |= LLIF_DATA_MODIFIED; + spin_unlock(&lli->lli_lock); + if (result < cnt) io->ci_continue = 0; - io->ci_nob += result; ll_rw_stats_tally(ll_i2sbi(inode), current->pid, cio->cui_fd, pos, result, WRITE); result = 0; @@ -645,6 +858,21 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) return -EINVAL; } +static void mkwrite_commit_callback(const struct lu_env *env, struct cl_io *io, + struct cl_page *page) +{ + const struct cl_page_slice *slice; + struct ccc_page *cp; + struct page *vmpage; + + slice = cl_page_at(page, &vvp_device_type); + cp = cl2ccc_page(slice); + vmpage = cp->cpg_page; + + set_page_dirty(vmpage); + vvp_write_pending(cl2ccc(slice->cpl_obj), cp); +} + static int vvp_io_fault_start(const struct lu_env *env, const struct cl_io_slice *ios) { @@ -659,7 +887,7 @@ static int vvp_io_fault_start(const struct lu_env *env, struct page *vmpage = NULL; struct cl_page *page; loff_t size; - pgoff_t last; /* last page in a file data region */ + pgoff_t last_index; if (fio->ft_executable && inode->i_mtime.tv_sec != vio->u.fault.ft_mtime) @@ -705,15 +933,15 @@ static int vvp_io_fault_start(const struct lu_env *env, goto out; } + last_index = cl_index(obj, size - 1); + if (fio->ft_mkwrite) { - pgoff_t last_index; /* * Capture the size while holding the lli_trunc_sem from above * we want to make sure that we complete the mkwrite action * while holding this lock. We need to make sure that we are * not past the end of the file. */ - last_index = cl_index(obj, size - 1); if (last_index < fio->ft_index) { CDEBUG(D_PAGE, "llite: mkwrite and truncate race happened: %p: 0x%lx 0x%lx\n", @@ -745,21 +973,28 @@ static int vvp_io_fault_start(const struct lu_env *env, */ if (fio->ft_mkwrite) { wait_on_page_writeback(vmpage); - if (set_page_dirty(vmpage)) { - struct ccc_page *cp; + if (!PageDirty(vmpage)) { + struct cl_page_list *plist = &io->ci_queue.c2_qin; + int to = PAGE_SIZE; /* vvp_page_assume() calls wait_on_page_writeback(). */ cl_page_assume(env, io, page); - cp = cl2ccc_page(cl_page_at(page, &vvp_device_type)); - vvp_write_pending(cl2ccc(obj), cp); + cl_page_list_init(plist); + cl_page_list_add(plist, page); + + /* size fixup */ + if (last_index == page->cp_index) + to = size & ~PAGE_MASK; /* Do not set Dirty bit here so that in case IO is * started before the page is really made dirty, we * still have chance to detect it. */ - result = cl_page_cache_add(env, io, page, CRT_WRITE); + result = cl_io_commit_async(env, io, plist, 0, to, + mkwrite_commit_callback); LASSERT(cl_page_is_owned(page, io)); + cl_page_list_fini(env, plist); vmpage = NULL; if (result < 0) { @@ -777,15 +1012,14 @@ static int vvp_io_fault_start(const struct lu_env *env, } } - last = cl_index(obj, size - 1); /* * The ft_index is only used in the case of * a mkwrite action. We need to check * our assertions are correct, since * we should have caught this above */ - LASSERT(!fio->ft_mkwrite || fio->ft_index <= last); - if (fio->ft_index == last) + LASSERT(!fio->ft_mkwrite || fio->ft_index <= last_index); + if (fio->ft_index == last_index) /* * Last page is mapped partially. */ @@ -865,234 +1099,6 @@ static int vvp_io_read_page(const struct lu_env *env, return 0; } -static int vvp_page_sync_io(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, struct ccc_page *cp, - enum cl_req_type crt) -{ - struct cl_2queue *queue; - int result; - - LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); - - queue = &io->ci_queue; - cl_2queue_init_page(queue, page); - - result = cl_io_submit_sync(env, io, crt, queue, 0); - LASSERT(cl_page_is_owned(page, io)); - - if (crt == CRT_READ) - /* - * in CRT_WRITE case page is left locked even in case of - * error. - */ - cl_page_list_disown(env, io, &queue->c2_qin); - cl_2queue_fini(env, queue); - - return result; -} - -/** - * Prepare partially written-to page for a write. - */ -static int vvp_io_prepare_partial(const struct lu_env *env, struct cl_io *io, - struct cl_object *obj, struct cl_page *pg, - struct ccc_page *cp, - unsigned from, unsigned to) -{ - struct cl_attr *attr = ccc_env_thread_attr(env); - loff_t offset = cl_offset(obj, pg->cp_index); - int result; - - cl_object_attr_lock(obj); - result = cl_object_attr_get(env, obj, attr); - cl_object_attr_unlock(obj); - if (result == 0) { - /* - * If are writing to a new page, no need to read old data. - * The extent locking will have updated the KMS, and for our - * purposes here we can treat it like i_size. - */ - if (attr->cat_kms <= offset) { - char *kaddr = kmap_atomic(cp->cpg_page); - - memset(kaddr, 0, cl_page_size(obj)); - kunmap_atomic(kaddr); - } else if (cp->cpg_defer_uptodate) - cp->cpg_ra_used = 1; - else - result = vvp_page_sync_io(env, io, pg, cp, CRT_READ); - /* - * In older implementations, obdo_refresh_inode is called here - * to update the inode because the write might modify the - * object info at OST. However, this has been proven useless, - * since LVB functions will be called when user space program - * tries to retrieve inode attribute. Also, see bug 15909 for - * details. -jay - */ - if (result == 0) - cl_page_export(env, pg, 1); - } - return result; -} - -static int vvp_io_prepare_write(const struct lu_env *env, - const struct cl_io_slice *ios, - const struct cl_page_slice *slice, - unsigned from, unsigned to) -{ - struct cl_object *obj = slice->cpl_obj; - struct ccc_page *cp = cl2ccc_page(slice); - struct cl_page *pg = slice->cpl_page; - struct page *vmpage = cp->cpg_page; - - int result; - - LINVRNT(cl_page_is_vmlocked(env, pg)); - LASSERT(vmpage->mapping->host == ccc_object_inode(obj)); - - result = 0; - - CL_PAGE_HEADER(D_PAGE, env, pg, "preparing: [%d, %d]\n", from, to); - if (!PageUptodate(vmpage)) { - /* - * We're completely overwriting an existing page, so _don't_ - * set it up to date until commit_write - */ - if (from == 0 && to == PAGE_CACHE_SIZE) { - CL_PAGE_HEADER(D_PAGE, env, pg, "full page write\n"); - POISON_PAGE(page, 0x11); - } else - result = vvp_io_prepare_partial(env, ios->cis_io, obj, - pg, cp, from, to); - } else - CL_PAGE_HEADER(D_PAGE, env, pg, "uptodate\n"); - return result; -} - -static int vvp_io_commit_write(const struct lu_env *env, - const struct cl_io_slice *ios, - const struct cl_page_slice *slice, - unsigned from, unsigned to) -{ - struct cl_object *obj = slice->cpl_obj; - struct cl_io *io = ios->cis_io; - struct ccc_page *cp = cl2ccc_page(slice); - struct cl_page *pg = slice->cpl_page; - struct inode *inode = ccc_object_inode(obj); - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ll_inode_info *lli = ll_i2info(inode); - struct page *vmpage = cp->cpg_page; - - int result; - int tallyop; - loff_t size; - - LINVRNT(cl_page_is_vmlocked(env, pg)); - LASSERT(vmpage->mapping->host == inode); - - LU_OBJECT_HEADER(D_INODE, env, &obj->co_lu, "committing page write\n"); - CL_PAGE_HEADER(D_PAGE, env, pg, "committing: [%d, %d]\n", from, to); - - /* - * queue a write for some time in the future the first time we - * dirty the page. - * - * This is different from what other file systems do: they usually - * just mark page (and some of its buffers) dirty and rely on - * balance_dirty_pages() to start a write-back. Lustre wants write-back - * to be started earlier for the following reasons: - * - * (1) with a large number of clients we need to limit the amount - * of cached data on the clients a lot; - * - * (2) large compute jobs generally want compute-only then io-only - * and the IO should complete as quickly as possible; - * - * (3) IO is batched up to the RPC size and is async until the - * client max cache is hit - * (/sys/fs/lustre/osc/OSC.../max_dirty_mb) - * - */ - if (!PageDirty(vmpage)) { - tallyop = LPROC_LL_DIRTY_MISSES; - result = cl_page_cache_add(env, io, pg, CRT_WRITE); - if (result == 0) { - /* page was added into cache successfully. */ - set_page_dirty(vmpage); - vvp_write_pending(cl2ccc(obj), cp); - } else if (result == -EDQUOT) { - pgoff_t last_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; - bool need_clip = true; - - /* - * Client ran out of disk space grant. Possible - * strategies are: - * - * (a) do a sync write, renewing grant; - * - * (b) stop writing on this stripe, switch to the - * next one. - * - * (b) is a part of "parallel io" design that is the - * ultimate goal. (a) is what "old" client did, and - * what the new code continues to do for the time - * being. - */ - if (last_index > pg->cp_index) { - to = PAGE_CACHE_SIZE; - need_clip = false; - } else if (last_index == pg->cp_index) { - int size_to = i_size_read(inode) & ~PAGE_MASK; - - if (to < size_to) - to = size_to; - } - if (need_clip) - cl_page_clip(env, pg, 0, to); - result = vvp_page_sync_io(env, io, pg, cp, CRT_WRITE); - if (result) - CERROR("Write page %lu of inode %p failed %d\n", - pg->cp_index, inode, result); - } - } else { - tallyop = LPROC_LL_DIRTY_HITS; - result = 0; - } - ll_stats_ops_tally(sbi, tallyop, 1); - - /* Inode should be marked DIRTY even if no new page was marked DIRTY - * because page could have been not flushed between 2 modifications. - * It is important the file is marked DIRTY as soon as the I/O is done - * Indeed, when cache is flushed, file could be already closed and it - * is too late to warn the MDT. - * It is acceptable that file is marked DIRTY even if I/O is dropped - * for some reasons before being flushed to OST. - */ - if (result == 0) { - spin_lock(&lli->lli_lock); - lli->lli_flags |= LLIF_DATA_MODIFIED; - spin_unlock(&lli->lli_lock); - } - - size = cl_offset(obj, pg->cp_index) + to; - - ll_inode_size_lock(inode); - if (result == 0) { - if (size > i_size_read(inode)) { - cl_isize_write_nolock(inode, size); - CDEBUG(D_VFSTRACE, DFID" updating i_size %lu\n", - PFID(lu_object_fid(&obj->co_lu)), - (unsigned long)size); - } - cl_page_export(env, pg, 1); - } else { - if (size > i_size_read(inode)) - cl_page_discard(env, io, pg); - } - ll_inode_size_unlock(inode); - return result; -} - static const struct cl_io_operations vvp_io_ops = { .op = { [CIT_READ] = { @@ -1103,6 +1109,8 @@ static const struct cl_io_operations vvp_io_ops = { }, [CIT_WRITE] = { .cio_fini = vvp_io_fini, + .cio_iter_init = vvp_io_write_iter_init, + .cio_iter_fini = vvp_io_write_iter_fini, .cio_lock = vvp_io_write_lock, .cio_start = vvp_io_write_start, .cio_advance = ccc_io_advance @@ -1130,8 +1138,6 @@ static const struct cl_io_operations vvp_io_ops = { } }, .cio_read_page = vvp_io_read_page, - .cio_prepare_write = vvp_io_prepare_write, - .cio_commit_write = vvp_io_commit_write }; int vvp_io_init(const struct lu_env *env, struct cl_object *obj, diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 7dd3162b51e9..3d568fc62adc 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -444,8 +444,10 @@ struct lov_thread_info { struct cl_lock_descr lti_ldescr; struct ost_lvb lti_lvb; struct cl_2queue lti_cl2q; + struct cl_page_list lti_plist; struct cl_lock_closure lti_closure; wait_queue_t lti_waiter; + struct cl_attr lti_attr; }; /** diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 4296aacd84fc..c60649032e59 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -543,13 +543,6 @@ static void lov_io_unlock(const struct lu_env *env, LASSERT(rc == 0); } -static struct cl_page_list *lov_io_submit_qin(struct lov_device *ld, - struct cl_page_list *qin, - int idx, int alloc) -{ - return alloc ? &qin[idx] : &ld->ld_emrg[idx]->emrg_page_list; -} - /** * lov implementation of cl_operations::cio_submit() method. It takes a list * of pages in \a queue, splits it into per-stripe sub-lists, invokes @@ -569,25 +562,17 @@ static int lov_io_submit(const struct lu_env *env, const struct cl_io_slice *ios, enum cl_req_type crt, struct cl_2queue *queue) { - struct lov_io *lio = cl2lov_io(env, ios); - struct lov_object *obj = lio->lis_object; - struct lov_device *ld = lu2lov_dev(lov2cl(obj)->co_lu.lo_dev); - struct cl_page_list *qin = &queue->c2_qin; - struct cl_2queue *cl2q = &lov_env_info(env)->lti_cl2q; - struct cl_page_list *stripes_qin = NULL; + struct cl_page_list *qin = &queue->c2_qin; + struct lov_io *lio = cl2lov_io(env, ios); + struct lov_io_sub *sub; + struct cl_page_list *plist = &lov_env_info(env)->lti_plist; struct cl_page *page; - struct cl_page *tmp; int stripe; -#define QIN(stripe) lov_io_submit_qin(ld, stripes_qin, stripe, alloc) - int rc = 0; - int alloc = - !(current->flags & PF_MEMALLOC); if (lio->lis_active_subios == 1) { int idx = lio->lis_single_subio_index; - struct lov_io_sub *sub; LASSERT(idx < lio->lis_nr_subios); sub = lov_sub_get(env, lio, idx); @@ -600,119 +585,120 @@ static int lov_io_submit(const struct lu_env *env, } LASSERT(lio->lis_subs); - if (alloc) { - stripes_qin = - libcfs_kvzalloc(sizeof(*stripes_qin) * - lio->lis_nr_subios, - GFP_NOFS); - if (!stripes_qin) - return -ENOMEM; - - for (stripe = 0; stripe < lio->lis_nr_subios; stripe++) - cl_page_list_init(&stripes_qin[stripe]); - } else { - /* - * If we get here, it means pageout & swap doesn't help. - * In order to not make things worse, even don't try to - * allocate the memory with __GFP_NOWARN. -jay - */ - mutex_lock(&ld->ld_mutex); - lio->lis_mem_frozen = 1; - } - cl_2queue_init(cl2q); - cl_page_list_for_each_safe(page, tmp, qin) { - stripe = lov_page_stripe(page); - cl_page_list_move(QIN(stripe), qin, page); - } + cl_page_list_init(plist); + while (qin->pl_nr > 0) { + struct cl_2queue *cl2q = &lov_env_info(env)->lti_cl2q; - for (stripe = 0; stripe < lio->lis_nr_subios; stripe++) { - struct lov_io_sub *sub; - struct cl_page_list *sub_qin = QIN(stripe); + cl_2queue_init(cl2q); - if (list_empty(&sub_qin->pl_pages)) - continue; + page = cl_page_list_first(qin); + cl_page_list_move(&cl2q->c2_qin, qin, page); + + stripe = lov_page_stripe(page); + while (qin->pl_nr > 0) { + page = cl_page_list_first(qin); + if (stripe != lov_page_stripe(page)) + break; + + cl_page_list_move(&cl2q->c2_qin, qin, page); + } - cl_page_list_splice(sub_qin, &cl2q->c2_qin); sub = lov_sub_get(env, lio, stripe); if (!IS_ERR(sub)) { rc = cl_io_submit_rw(sub->sub_env, sub->sub_io, crt, cl2q); lov_sub_put(sub); - } else + } else { rc = PTR_ERR(sub); - cl_page_list_splice(&cl2q->c2_qin, &queue->c2_qin); + } + + cl_page_list_splice(&cl2q->c2_qin, plist); cl_page_list_splice(&cl2q->c2_qout, &queue->c2_qout); + cl_2queue_fini(env, cl2q); + if (rc != 0) break; } - for (stripe = 0; stripe < lio->lis_nr_subios; stripe++) { - struct cl_page_list *sub_qin = QIN(stripe); + cl_page_list_splice(plist, qin); + cl_page_list_fini(env, plist); - if (list_empty(&sub_qin->pl_pages)) - continue; + return rc; +} + +static int lov_io_commit_async(const struct lu_env *env, + const struct cl_io_slice *ios, + struct cl_page_list *queue, int from, int to, + cl_commit_cbt cb) +{ + struct cl_page_list *plist = &lov_env_info(env)->lti_plist; + struct lov_io *lio = cl2lov_io(env, ios); + struct lov_io_sub *sub; + struct cl_page *page; + int rc = 0; - cl_page_list_splice(sub_qin, qin); + if (lio->lis_active_subios == 1) { + int idx = lio->lis_single_subio_index; + + LASSERT(idx < lio->lis_nr_subios); + sub = lov_sub_get(env, lio, idx); + LASSERT(!IS_ERR(sub)); + LASSERT(sub->sub_io == &lio->lis_single_subio); + rc = cl_io_commit_async(sub->sub_env, sub->sub_io, queue, + from, to, cb); + lov_sub_put(sub); + return rc; } - if (alloc) { - kvfree(stripes_qin); - } else { - int i; + LASSERT(lio->lis_subs); - for (i = 0; i < lio->lis_nr_subios; i++) { - struct cl_io *cio = lio->lis_subs[i].sub_io; + cl_page_list_init(plist); + while (queue->pl_nr > 0) { + int stripe_to = to; + int stripe; - if (cio && cio == &ld->ld_emrg[i]->emrg_subio) - lov_io_sub_fini(env, lio, &lio->lis_subs[i]); + LASSERT(plist->pl_nr == 0); + page = cl_page_list_first(queue); + cl_page_list_move(plist, queue, page); + + stripe = lov_page_stripe(page); + while (queue->pl_nr > 0) { + page = cl_page_list_first(queue); + if (stripe != lov_page_stripe(page)) + break; + + cl_page_list_move(plist, queue, page); } - lio->lis_mem_frozen = 0; - mutex_unlock(&ld->ld_mutex); - } - return rc; -#undef QIN -} + if (queue->pl_nr > 0) /* still has more pages */ + stripe_to = PAGE_SIZE; -static int lov_io_prepare_write(const struct lu_env *env, - const struct cl_io_slice *ios, - const struct cl_page_slice *slice, - unsigned from, unsigned to) -{ - struct lov_io *lio = cl2lov_io(env, ios); - struct cl_page *sub_page = lov_sub_page(slice); - struct lov_io_sub *sub; - int result; + sub = lov_sub_get(env, lio, stripe); + if (!IS_ERR(sub)) { + rc = cl_io_commit_async(sub->sub_env, sub->sub_io, + plist, from, stripe_to, cb); + lov_sub_put(sub); + } else { + rc = PTR_ERR(sub); + break; + } - sub = lov_page_subio(env, lio, slice); - if (!IS_ERR(sub)) { - result = cl_io_prepare_write(sub->sub_env, sub->sub_io, - sub_page, from, to); - lov_sub_put(sub); - } else - result = PTR_ERR(sub); - return result; -} + if (plist->pl_nr > 0) /* short write */ + break; -static int lov_io_commit_write(const struct lu_env *env, - const struct cl_io_slice *ios, - const struct cl_page_slice *slice, - unsigned from, unsigned to) -{ - struct lov_io *lio = cl2lov_io(env, ios); - struct cl_page *sub_page = lov_sub_page(slice); - struct lov_io_sub *sub; - int result; + from = 0; + } - sub = lov_page_subio(env, lio, slice); - if (!IS_ERR(sub)) { - result = cl_io_commit_write(sub->sub_env, sub->sub_io, - sub_page, from, to); - lov_sub_put(sub); - } else - result = PTR_ERR(sub); - return result; + /* for error case, add the page back into the qin list */ + LASSERT(ergo(rc == 0, plist->pl_nr == 0)); + while (plist->pl_nr > 0) { + /* error occurred, add the uncommitted pages back into queue */ + page = cl_page_list_last(plist); + cl_page_list_move_head(queue, plist, page); + } + + return rc; } static int lov_io_fault_start(const struct lu_env *env, @@ -803,16 +789,8 @@ static const struct cl_io_operations lov_io_ops = { .cio_fini = lov_io_fini } }, - .req_op = { - [CRT_READ] = { - .cio_submit = lov_io_submit - }, - [CRT_WRITE] = { - .cio_submit = lov_io_submit - } - }, - .cio_prepare_write = lov_io_prepare_write, - .cio_commit_write = lov_io_commit_write + .cio_submit = lov_io_submit, + .cio_commit_async = lov_io_commit_async, }; /***************************************************************************** @@ -880,15 +858,8 @@ static const struct cl_io_operations lov_empty_io_ops = { .cio_fini = lov_empty_io_fini } }, - .req_op = { - [CRT_READ] = { - .cio_submit = LOV_EMPTY_IMPOSSIBLE - }, - [CRT_WRITE] = { - .cio_submit = LOV_EMPTY_IMPOSSIBLE - } - }, - .cio_commit_write = LOV_EMPTY_IMPOSSIBLE + .cio_submit = LOV_EMPTY_IMPOSSIBLE, + .cio_commit_async = LOV_EMPTY_IMPOSSIBLE }; int lov_io_init_raid0(const struct lu_env *env, struct cl_object *obj, diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index 9728da245a68..5d9b355fc608 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -105,29 +105,6 @@ static void lov_page_assume(const struct lu_env *env, lov_page_own(env, slice, io, 0); } -static int lov_page_cache_add(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io) -{ - struct lov_io *lio = lov_env_io(env); - struct lov_io_sub *sub; - int rc = 0; - - LINVRNT(lov_page_invariant(slice)); - LINVRNT(!cl2lov_page(slice)->lps_invalid); - - sub = lov_page_subio(env, lio, slice); - if (!IS_ERR(sub)) { - rc = cl_page_cache_add(sub->sub_env, sub->sub_io, - slice->cpl_page->cp_child, CRT_WRITE); - lov_sub_put(sub); - } else { - rc = PTR_ERR(sub); - CL_PAGE_DEBUG(D_ERROR, env, slice->cpl_page, "rc = %d\n", rc); - } - return rc; -} - static int lov_page_print(const struct lu_env *env, const struct cl_page_slice *slice, void *cookie, lu_printer_t printer) @@ -141,11 +118,6 @@ static const struct cl_page_operations lov_page_ops = { .cpo_fini = lov_page_fini, .cpo_own = lov_page_own, .cpo_assume = lov_page_assume, - .io = { - [CRT_WRITE] = { - .cpo_cache_add = lov_page_cache_add - } - }, .cpo_print = lov_page_print }; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index cf9428428d06..9b3c5c1f26e3 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -782,77 +782,29 @@ int cl_io_read_page(const struct lu_env *env, struct cl_io *io, EXPORT_SYMBOL(cl_io_read_page); /** - * Called by write io to prepare page to receive data from user buffer. + * Commit a list of contiguous pages into writeback cache. * - * \see cl_io_operations::cio_prepare_write() + * \returns 0 if all pages committed, or errcode if error occurred. + * \see cl_io_operations::cio_commit_async() */ -int cl_io_prepare_write(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, unsigned from, unsigned to) +int cl_io_commit_async(const struct lu_env *env, struct cl_io *io, + struct cl_page_list *queue, int from, int to, + cl_commit_cbt cb) { const struct cl_io_slice *scan; int result = 0; - LINVRNT(io->ci_type == CIT_WRITE); - LINVRNT(cl_page_is_owned(page, io)); - LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED); - LINVRNT(cl_io_invariant(io)); - LASSERT(cl_page_in_io(page, io)); - - cl_io_for_each_reverse(scan, io) { - if (scan->cis_iop->cio_prepare_write) { - const struct cl_page_slice *slice; - - slice = cl_io_slice_page(scan, page); - result = scan->cis_iop->cio_prepare_write(env, scan, - slice, - from, to); - if (result != 0) - break; - } - } - return result; -} -EXPORT_SYMBOL(cl_io_prepare_write); - -/** - * Called by write io after user data were copied into a page. - * - * \see cl_io_operations::cio_commit_write() - */ -int cl_io_commit_write(const struct lu_env *env, struct cl_io *io, - struct cl_page *page, unsigned from, unsigned to) -{ - const struct cl_io_slice *scan; - int result = 0; - - LINVRNT(io->ci_type == CIT_WRITE); - LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED); - LINVRNT(cl_io_invariant(io)); - /* - * XXX Uh... not nice. Top level cl_io_commit_write() call (vvp->lov) - * already called cl_page_cache_add(), moving page into CPS_CACHED - * state. Better (and more general) way of dealing with such situation - * is needed. - */ - LASSERT(cl_page_is_owned(page, io) || page->cp_parent); - LASSERT(cl_page_in_io(page, io)); - cl_io_for_each(scan, io) { - if (scan->cis_iop->cio_commit_write) { - const struct cl_page_slice *slice; - - slice = cl_io_slice_page(scan, page); - result = scan->cis_iop->cio_commit_write(env, scan, - slice, - from, to); - if (result != 0) - break; - } + if (!scan->cis_iop->cio_commit_async) + continue; + result = scan->cis_iop->cio_commit_async(env, scan, queue, + from, to, cb); + if (result != 0) + break; } - LINVRNT(result <= 0); return result; } -EXPORT_SYMBOL(cl_io_commit_write); +EXPORT_SYMBOL(cl_io_commit_async); /** * Submits a list of pages for immediate io. @@ -870,13 +822,10 @@ int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io, const struct cl_io_slice *scan; int result = 0; - LINVRNT(crt < ARRAY_SIZE(scan->cis_iop->req_op)); - cl_io_for_each(scan, io) { - if (!scan->cis_iop->req_op[crt].cio_submit) + if (!scan->cis_iop->cio_submit) continue; - result = scan->cis_iop->req_op[crt].cio_submit(env, scan, crt, - queue); + result = scan->cis_iop->cio_submit(env, scan, crt, queue); if (result != 0) break; } @@ -1073,8 +1022,8 @@ EXPORT_SYMBOL(cl_page_list_add); /** * Removes a page from a page list. */ -static void cl_page_list_del(const struct lu_env *env, - struct cl_page_list *plist, struct cl_page *page) +void cl_page_list_del(const struct lu_env *env, struct cl_page_list *plist, + struct cl_page *page) { LASSERT(plist->pl_nr > 0); LINVRNT(plist->pl_owner == current); @@ -1087,6 +1036,7 @@ static void cl_page_list_del(const struct lu_env *env, lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist); cl_page_put(env, page); } +EXPORT_SYMBOL(cl_page_list_del); /** * Moves a page from one page list to another. @@ -1106,6 +1056,24 @@ void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src, } EXPORT_SYMBOL(cl_page_list_move); +/** + * Moves a page from one page list to the head of another list. + */ +void cl_page_list_move_head(struct cl_page_list *dst, struct cl_page_list *src, + struct cl_page *page) +{ + LASSERT(src->pl_nr > 0); + LINVRNT(dst->pl_owner == current); + LINVRNT(src->pl_owner == current); + + list_move(&page->cp_batch, &dst->pl_pages); + --src->pl_nr; + ++dst->pl_nr; + lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue", + src, dst); +} +EXPORT_SYMBOL(cl_page_list_move_head); + /** * splice the cl_page_list, just as list head does */ @@ -1163,8 +1131,7 @@ EXPORT_SYMBOL(cl_page_list_disown); /** * Releases pages from queue. */ -static void cl_page_list_fini(const struct lu_env *env, - struct cl_page_list *plist) +void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist) { struct cl_page *page; struct cl_page *temp; @@ -1175,6 +1142,7 @@ static void cl_page_list_fini(const struct lu_env *env, cl_page_list_del(env, plist, page); LASSERT(plist->pl_nr == 0); } +EXPORT_SYMBOL(cl_page_list_fini); /** * Assumes all pages in a queue. diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index bab8a74b78ae..0844a97c3258 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -1011,44 +1011,6 @@ int cl_page_make_ready(const struct lu_env *env, struct cl_page *pg, } EXPORT_SYMBOL(cl_page_make_ready); -/** - * Notify layers that high level io decided to place this page into a cache - * for future transfer. - * - * The layer implementing transfer engine (osc) has to register this page in - * its queues. - * - * \pre cl_page_is_owned(pg, io) - * \post cl_page_is_owned(pg, io) - * - * \see cl_page_operations::cpo_cache_add() - */ -int cl_page_cache_add(const struct lu_env *env, struct cl_io *io, - struct cl_page *pg, enum cl_req_type crt) -{ - const struct cl_page_slice *scan; - int result = 0; - - PINVRNT(env, pg, crt < CRT_NR); - PINVRNT(env, pg, cl_page_is_owned(pg, io)); - PINVRNT(env, pg, cl_page_invariant(pg)); - - if (crt >= CRT_NR) - return -EINVAL; - - list_for_each_entry(scan, &pg->cp_layers, cpl_linkage) { - if (!scan->cpl_ops->io[crt].cpo_cache_add) - continue; - - result = scan->cpl_ops->io[crt].cpo_cache_add(env, scan, io); - if (result != 0) - break; - } - CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result); - return result; -} -EXPORT_SYMBOL(cl_page_cache_add); - /** * Called if a pge is being written back by kernel's intention. * diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 33ce0c80e4b2..6c205f9cad9f 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1085,22 +1085,17 @@ static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed, return 0; } -static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io, - enum cl_req_type unused, struct cl_2queue *queue) +static void echo_commit_callback(const struct lu_env *env, struct cl_io *io, + struct cl_page *page) { - struct cl_page *clp; - struct cl_page *temp; - int result = 0; + struct echo_thread_info *info; + struct cl_2queue *queue; - cl_page_list_for_each_safe(clp, temp, &queue->c2_qin) { - int rc; + info = echo_env_info(env); + LASSERT(io == &info->eti_io); - rc = cl_page_cache_add(env, io, clp, CRT_WRITE); - if (rc == 0) - continue; - result = result ?: rc; - } - return result; + queue = &info->eti_queue; + cl_page_list_add(&queue->c2_qout, page); } static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, @@ -1179,7 +1174,9 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, async = async && (typ == CRT_WRITE); if (async) - rc = cl_echo_async_brw(env, io, typ, queue); + rc = cl_io_commit_async(env, io, &queue->c2_qin, + 0, PAGE_SIZE, + echo_commit_callback); else rc = cl_io_submit_sync(env, io, typ, queue, 0); CDEBUG(D_INFO, "echo_client %s write returns %d\n", diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index c9d4e3ca6caa..3be4b1f11767 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -879,10 +879,9 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, * span a whole chunk on the OST side, or our accounting goes * wrong. Should match the code in filter_grant_check. */ - int offset = oap->oap_page_off & ~PAGE_MASK; - int count = oap->oap_count + (offset & (blocksize - 1)); - int end = (offset + oap->oap_count) & (blocksize - 1); - + int offset = last_off & ~PAGE_MASK; + int count = last_count + (offset & (blocksize - 1)); + int end = (offset + last_count) & (blocksize - 1); if (end) count += blocksize - end; @@ -3131,14 +3130,13 @@ static int discard_cb(const struct lu_env *env, struct cl_io *io, struct cl_page *page = cl_page_top(ops->ops_cl.cpl_page); LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE); - KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, - !PageWriteback(cl_page_vmpage(env, page)))); - KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, - !PageDirty(cl_page_vmpage(env, page)))); /* page is top page. */ info->oti_next_index = osc_index(ops) + 1; if (cl_page_own(env, io, page) == 0) { + KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, + !PageDirty(cl_page_vmpage(env, page)))); + /* discard the page */ cl_page_discard(env, io, page); cl_page_disown(env, io, page); diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index e70f06ccd095..0e06bedeb0dd 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -453,6 +453,8 @@ int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops, struct page *page, loff_t offset); int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, struct osc_page *ops); +int osc_page_cache_add(const struct lu_env *env, + const struct cl_page_slice *slice, struct cl_io *io); int osc_teardown_async_page(const struct lu_env *env, struct osc_object *obj, struct osc_page *ops); int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index b3b15d4c99e3..906225c520d6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -83,6 +83,12 @@ struct osc_async_page { #define oap_count oap_brw_page.count #define oap_brw_flags oap_brw_page.flag +static inline struct osc_async_page *brw_page2oap(struct brw_page *pga) +{ + return (struct osc_async_page *)container_of(pga, struct osc_async_page, + oap_brw_page); +} + struct osc_cache_waiter { struct list_head ocw_entry; wait_queue_head_t ocw_waitq; diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 1536d31fd108..e9e18a1085e2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -185,6 +185,13 @@ static int osc_io_submit(const struct lu_env *env, return qout->pl_nr > 0 ? 0 : result; } +/** + * This is called when a page is accessed within file in a way that creates + * new page, if one were missing (i.e., if there were a hole at that place in + * the file, or accessed page is beyond the current file size). + * + * Expand stripe KMS if necessary. + */ static void osc_page_touch_at(const struct lu_env *env, struct cl_object *obj, pgoff_t idx, unsigned to) { @@ -208,7 +215,8 @@ static void osc_page_touch_at(const struct lu_env *env, kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms, loi->loi_lvb.lvb_size); - valid = 0; + attr->cat_mtime = attr->cat_ctime = LTIME_S(CURRENT_TIME); + valid = CAT_MTIME | CAT_CTIME; if (kms > loi->loi_kms) { attr->cat_kms = kms; valid |= CAT_KMS; @@ -221,91 +229,83 @@ static void osc_page_touch_at(const struct lu_env *env, cl_object_attr_unlock(obj); } -/** - * This is called when a page is accessed within file in a way that creates - * new page, if one were missing (i.e., if there were a hole at that place in - * the file, or accessed page is beyond the current file size). Examples: - * ->commit_write() and ->nopage() methods. - * - * Expand stripe KMS if necessary. - */ -static void osc_page_touch(const struct lu_env *env, - struct osc_page *opage, unsigned to) -{ - struct cl_page *page = opage->ops_cl.cpl_page; - struct cl_object *obj = opage->ops_cl.cpl_obj; - - osc_page_touch_at(env, obj, page->cp_index, to); -} - -/** - * Implements cl_io_operations::cio_prepare_write() method for osc layer. - * - * \retval -EIO transfer initiated against this osc will most likely fail - * \retval 0 transfer initiated against this osc will most likely succeed. - * - * The reason for this check is to immediately return an error to the caller - * in the case of a deactivated import. Note, that import can be deactivated - * later, while pages, dirtied by this IO, are still in the cache, but this is - * irrelevant, because that would still return an error to the application (if - * it does fsync), but many applications don't do fsync because of performance - * issues, and we wanted to return an -EIO at write time to notify the - * application. - */ -static int osc_io_prepare_write(const struct lu_env *env, - const struct cl_io_slice *ios, - const struct cl_page_slice *slice, - unsigned from, unsigned to) +static int osc_io_commit_async(const struct lu_env *env, + const struct cl_io_slice *ios, + struct cl_page_list *qin, int from, int to, + cl_commit_cbt cb) { - struct osc_device *dev = lu2osc_dev(slice->cpl_obj->co_lu.lo_dev); - struct obd_import *imp = class_exp2cliimp(dev->od_exp); + struct cl_io *io = ios->cis_io; struct osc_io *oio = cl2osc_io(env, ios); + struct osc_object *osc = cl2osc(ios->cis_obj); + struct cl_page *page; + struct cl_page *last_page; + struct osc_page *opg; int result = 0; + LASSERT(qin->pl_nr > 0); + + /* Handle partial page cases */ + last_page = cl_page_list_last(qin); + if (oio->oi_lockless) { + page = cl_page_list_first(qin); + if (page == last_page) { + cl_page_clip(env, page, from, to); + } else { + if (from != 0) + cl_page_clip(env, page, from, PAGE_SIZE); + if (to != PAGE_SIZE) + cl_page_clip(env, last_page, 0, to); + } + } + /* - * This implements OBD_BRW_CHECK logic from old client. + * NOTE: here @page is a top-level page. This is done to avoid + * creation of sub-page-list. */ + while (qin->pl_nr > 0) { + struct osc_async_page *oap; - if (!imp || imp->imp_invalid) - result = -EIO; - if (result == 0 && oio->oi_lockless) - /* this page contains `invalid' data, but who cares? - * nobody can access the invalid data. - * in osc_io_commit_write(), we're going to write exact - * [from, to) bytes of this page to OST. -jay - */ - cl_page_export(env, slice->cpl_page, 1); + page = cl_page_list_first(qin); + opg = osc_cl_page_osc(page); + oap = &opg->ops_oap; - return result; -} + if (!list_empty(&oap->oap_rpc_item)) { + CDEBUG(D_CACHE, "Busy oap %p page %p for submit.\n", + oap, opg); + result = -EBUSY; + break; + } -static int osc_io_commit_write(const struct lu_env *env, - const struct cl_io_slice *ios, - const struct cl_page_slice *slice, - unsigned from, unsigned to) -{ - struct osc_io *oio = cl2osc_io(env, ios); - struct osc_page *opg = cl2osc_page(slice); - struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj); - struct osc_async_page *oap = &opg->ops_oap; + /* The page may be already in dirty cache. */ + if (list_empty(&oap->oap_pending_item)) { + result = osc_page_cache_add(env, &opg->ops_cl, io); + if (result != 0) + break; + } - LASSERT(to > 0); - /* - * XXX instead of calling osc_page_touch() here and in - * osc_io_fault_start() it might be more logical to introduce - * cl_page_touch() method, that generic cl_io_commit_write() and page - * fault code calls. - */ - osc_page_touch(env, cl2osc_page(slice), to); - if (!client_is_remote(osc_export(obj)) && - capable(CFS_CAP_SYS_RESOURCE)) - oap->oap_brw_flags |= OBD_BRW_NOQUOTA; + osc_page_touch_at(env, osc2cl(osc), + opg->ops_cl.cpl_page->cp_index, + page == last_page ? to : PAGE_SIZE); - if (oio->oi_lockless) - /* see osc_io_prepare_write() for lockless io handling. */ - cl_page_clip(env, slice->cpl_page, from, to); + cl_page_list_del(env, qin, page); - return 0; + (*cb)(env, io, page); + /* Can't access page any more. Page can be in transfer and + * complete at any time. + */ + } + + /* for sync write, kernel will wait for this page to be flushed before + * osc_io_end() is called, so release it earlier. + * for mkwrite(), it's known there is no further pages. + */ + if (cl_io_is_sync_write(io) && oio->oi_active) { + osc_extent_release(env, oio->oi_active); + oio->oi_active = NULL; + } + + CDEBUG(D_INFO, "%d %d\n", qin->pl_nr, result); + return result; } static int osc_io_rw_iter_init(const struct lu_env *env, @@ -719,16 +719,8 @@ static const struct cl_io_operations osc_io_ops = { .cio_fini = osc_io_fini } }, - .req_op = { - [CRT_READ] = { - .cio_submit = osc_io_submit - }, - [CRT_WRITE] = { - .cio_submit = osc_io_submit - } - }, - .cio_prepare_write = osc_io_prepare_write, - .cio_commit_write = osc_io_commit_write + .cio_submit = osc_io_submit, + .cio_commit_async = osc_io_commit_async }; /***************************************************************************** diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 91ff6070a28d..eff3b4b3b2b3 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -89,8 +89,8 @@ static void osc_page_transfer_put(const struct lu_env *env, struct cl_page *page = cl_page_top(opg->ops_cl.cpl_page); if (opg->ops_transfer_pinned) { - lu_ref_del(&page->cp_reference, "transfer", page); opg->ops_transfer_pinned = 0; + lu_ref_del(&page->cp_reference, "transfer", page); cl_page_put(env, page); } } @@ -113,11 +113,9 @@ static void osc_page_transfer_add(const struct lu_env *env, spin_unlock(&obj->oo_seatbelt); } -static int osc_page_cache_add(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io) +int osc_page_cache_add(const struct lu_env *env, + const struct cl_page_slice *slice, struct cl_io *io) { - struct osc_io *oio = osc_env_io(env); struct osc_page *opg = cl2osc_page(slice); int result; @@ -130,17 +128,6 @@ static int osc_page_cache_add(const struct lu_env *env, else osc_page_transfer_add(env, opg, CRT_WRITE); - /* for sync write, kernel will wait for this page to be flushed before - * osc_io_end() is called, so release it earlier. - * for mkwrite(), it's known there is no further pages. - */ - if (cl_io_is_sync_write(io) || cl_io_is_mkwrite(io)) { - if (oio->oi_active) { - osc_extent_release(env, oio->oi_active); - oio->oi_active = NULL; - } - } - return result; } @@ -231,17 +218,6 @@ static void osc_page_completion_write(const struct lu_env *env, { } -static int osc_page_fail(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *unused) -{ - /* - * Cached read? - */ - LBUG(); - return 0; -} - static const char *osc_list(struct list_head *head) { return list_empty(head) ? "-" : "+"; @@ -393,11 +369,9 @@ static const struct cl_page_operations osc_page_ops = { .cpo_disown = osc_page_disown, .io = { [CRT_READ] = { - .cpo_cache_add = osc_page_fail, .cpo_completion = osc_page_completion_read }, [CRT_WRITE] = { - .cpo_cache_add = osc_page_cache_add, .cpo_completion = osc_page_completion_write } }, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index c055511b321a..1ff497f05b2f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1734,7 +1734,6 @@ static int brw_interpret(const struct lu_env *env, struct osc_brw_async_args *aa = data; struct osc_extent *ext; struct osc_extent *tmp; - struct cl_object *obj = NULL; struct client_obd *cli = aa->aa_cli; rc = osc_brw_fini_request(req, rc); @@ -1763,24 +1762,17 @@ static int brw_interpret(const struct lu_env *env, rc = -EIO; } - list_for_each_entry_safe(ext, tmp, &aa->aa_exts, oe_link) { - if (!obj && rc == 0) { - obj = osc2cl(ext->oe_obj); - cl_object_get(obj); - } - - list_del_init(&ext->oe_link); - osc_extent_finish(env, ext, 1, rc); - } - LASSERT(list_empty(&aa->aa_exts)); - LASSERT(list_empty(&aa->aa_oaps)); - - if (obj) { + if (rc == 0) { struct obdo *oa = aa->aa_oa; struct cl_attr *attr = &osc_env_info(env)->oti_attr; unsigned long valid = 0; + struct cl_object *obj; + struct osc_async_page *last; + + last = brw_page2oap(aa->aa_ppga[aa->aa_page_count - 1]); + obj = osc2cl(last->oap_obj); - LASSERT(rc == 0); + cl_object_attr_lock(obj); if (oa->o_valid & OBD_MD_FLBLOCKS) { attr->cat_blocks = oa->o_blocks; valid |= CAT_BLOCKS; @@ -1797,15 +1789,39 @@ static int brw_interpret(const struct lu_env *env, attr->cat_ctime = oa->o_ctime; valid |= CAT_CTIME; } - if (valid != 0) { - cl_object_attr_lock(obj); - cl_object_attr_set(env, obj, attr, valid); - cl_object_attr_unlock(obj); + + if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE) { + struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo; + loff_t last_off = last->oap_count + last->oap_obj_off; + + /* Change file size if this is an out of quota or + * direct IO write and it extends the file size + */ + if (loi->loi_lvb.lvb_size < last_off) { + attr->cat_size = last_off; + valid |= CAT_SIZE; + } + /* Extend KMS if it's not a lockless write */ + if (loi->loi_kms < last_off && + oap2osc_page(last)->ops_srvlock == 0) { + attr->cat_kms = last_off; + valid |= CAT_KMS; + } } - cl_object_put(env, obj); + + if (valid != 0) + cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_unlock(obj); } kmem_cache_free(obdo_cachep, aa->aa_oa); + list_for_each_entry_safe(ext, tmp, &aa->aa_exts, oe_link) { + list_del_init(&ext->oe_link); + osc_extent_finish(env, ext, 1, rc); + } + LASSERT(list_empty(&aa->aa_exts)); + LASSERT(list_empty(&aa->aa_oaps)); + cl_req_completion(env, aa->aa_clerq, rc < 0 ? rc : req->rq_bulk->bd_nob_transferred); osc_release_ppga(aa->aa_ppga, aa->aa_page_count); -- GitLab From f56b355ca8ae0a2312da094630790b923b00d8b4 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:31 -0400 Subject: [PATCH 0860/9938] staging/lustre/osc: add weight function for DLM lock Use weigh_ast to decide if a lock covers any pages. In recovery, weigh_ast will be used to decide if a DLM read lock covers any locked pages, or it will be canceled instead being recovered. The problem with the original implementation is that it attached each osc_page to an osc_lock also changed lock state to add every pages for readahead. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/7894 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/ldlm/ldlm_request.c | 9 +- .../lustre/lustre/osc/osc_cl_internal.h | 20 ---- .../staging/lustre/lustre/osc/osc_internal.h | 3 +- drivers/staging/lustre/lustre/osc/osc_lock.c | 113 +++++++++++++----- drivers/staging/lustre/lustre/osc/osc_page.c | 78 +----------- .../staging/lustre/lustre/osc/osc_request.c | 5 +- 6 files changed, 89 insertions(+), 139 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index c7904a96f9af..d5968e01edd8 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1139,10 +1139,10 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, ldlm_policy_res_t result = LDLM_POLICY_CANCEL_LOCK; ldlm_cancel_for_recovery cb = ns->ns_cancel_for_recovery; - lock_res_and_lock(lock); - /* don't check added & count since we want to process all locks - * from unused list + * from unused list. + * It's fine to not take lock to access lock->l_resource since + * the lock has already been granted so it won't change. */ switch (lock->l_resource->lr_type) { case LDLM_EXTENT: @@ -1151,11 +1151,12 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, break; default: result = LDLM_POLICY_SKIP_LOCK; + lock_res_and_lock(lock); lock->l_flags |= LDLM_FL_SKIPPED; + unlock_res_and_lock(lock); break; } - unlock_res_and_lock(lock); return result; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index 0e06bedeb0dd..cf87043ce4b8 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -274,16 +274,6 @@ struct osc_lock { struct ldlm_enqueue_info ols_einfo; enum osc_lock_state ols_state; - /** - * How many pages are using this lock for io, currently only used by - * read-ahead. If non-zero, the underlying dlm lock won't be cancelled - * during recovery to avoid deadlock. see bz16774. - * - * \see osc_page::ops_lock - * \see osc_page_addref_lock(), osc_page_putref_lock() - */ - atomic_t ols_pageref; - /** * true, if ldlm_lock_addref() was called against * osc_lock::ols_lock. This is used for sanity checking. @@ -400,16 +390,6 @@ struct osc_page { * Submit time - the time when the page is starting RPC. For debugging. */ unsigned long ops_submit_time; - - /** - * A lock of which we hold a reference covers this page. Only used by - * read-ahead: for a readahead page, we hold it's covering lock to - * prevent it from being canceled during recovery. - * - * \see osc_lock::ols_pageref - * \see osc_page_addref_lock(), osc_page_putref_lock(). - */ - struct cl_lock *ops_lock; }; extern struct kmem_cache *osc_lock_kmem; diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 906225c520d6..b7fb01ad60a6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -141,6 +141,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, int osc_lru_reclaim(struct client_obd *cli); extern spinlock_t osc_ast_guard; +unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock); int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg); @@ -181,8 +182,6 @@ static inline struct osc_device *obd2osc_dev(const struct obd_device *d) return container_of0(d->obd_lu_dev, struct osc_device, od_cl.cd_lu_dev); } -int osc_dlm_lock_pageref(struct ldlm_lock *dlm); - extern struct kmem_cache *osc_quota_kmem; struct osc_quota_info { /** linkage for quota hash table */ diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 3a8a6d129377..978b6ea67107 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -51,8 +51,6 @@ * @{ */ -#define _PAGEREF_MAGIC (-10000000) - /***************************************************************************** * * Type conversions. @@ -248,8 +246,6 @@ static void osc_lock_fini(const struct lu_env *env, */ osc_lock_unhold(ols); LASSERT(!ols->ols_lock); - LASSERT(atomic_read(&ols->ols_pageref) == 0 || - atomic_read(&ols->ols_pageref) == _PAGEREF_MAGIC); kmem_cache_free(osc_lock_kmem, ols); } @@ -895,11 +891,88 @@ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) return result; } -static unsigned long osc_lock_weigh(const struct lu_env *env, - const struct cl_lock_slice *slice) +static int weigh_cb(const struct lu_env *env, struct cl_io *io, + struct osc_page *ops, void *cbdata) { - /* TODO: check how many pages are covered by this lock */ - return cl2osc(slice->cls_obj)->oo_npages; + struct cl_page *page = ops->ops_cl.cpl_page; + + if (cl_page_is_vmlocked(env, page)) { + (*(unsigned long *)cbdata)++; + return CLP_GANG_ABORT; + } + + return CLP_GANG_OKAY; +} + +static unsigned long osc_lock_weight(const struct lu_env *env, + const struct osc_lock *ols) +{ + struct cl_io *io = &osc_env_info(env)->oti_io; + struct cl_lock_descr *descr = &ols->ols_cl.cls_lock->cll_descr; + struct cl_object *obj = ols->ols_cl.cls_obj; + unsigned long npages = 0; + int result; + + io->ci_obj = cl_object_top(obj); + io->ci_ignore_layout = 1; + result = cl_io_init(env, io, CIT_MISC, io->ci_obj); + if (result != 0) + return result; + + do { + result = osc_page_gang_lookup(env, io, cl2osc(obj), + descr->cld_start, descr->cld_end, + weigh_cb, (void *)&npages); + if (result == CLP_GANG_ABORT) + break; + if (result == CLP_GANG_RESCHED) + cond_resched(); + } while (result != CLP_GANG_OKAY); + cl_io_fini(env, io); + + return npages; +} + +/** + * Get the weight of dlm lock for early cancellation. + */ +unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock) +{ + struct cl_env_nest nest; + struct lu_env *env; + struct osc_lock *lock; + unsigned long weight; + + might_sleep(); + /* + * osc_ldlm_weigh_ast has a complex context since it might be called + * because of lock canceling, or from user's input. We have to make + * a new environment for it. Probably it is implementation safe to use + * the upper context because cl_lock_put don't modify environment + * variables. But just in case .. + */ + env = cl_env_nested_get(&nest); + if (IS_ERR(env)) + /* Mostly because lack of memory, do not eliminate this lock */ + return 1; + + LASSERT(dlmlock->l_resource->lr_type == LDLM_EXTENT); + lock = osc_ast_data_get(dlmlock); + if (!lock) { + /* cl_lock was destroyed because of memory pressure. + * It is much reasonable to assign this type of lock + * a lower cost. + */ + weight = 0; + goto out; + } + + weight = osc_lock_weight(env, lock); + osc_ast_data_put(env, lock); + +out: + cl_env_nested_put(&nest, env); + return weight; } static void osc_lock_build_einfo(const struct lu_env *env, @@ -1468,7 +1541,6 @@ static const struct cl_lock_operations osc_lock_ops = { .clo_delete = osc_lock_delete, .clo_state = osc_lock_state, .clo_cancel = osc_lock_cancel, - .clo_weigh = osc_lock_weigh, .clo_print = osc_lock_print, .clo_fits_into = osc_lock_fits_into, }; @@ -1570,7 +1642,6 @@ int osc_lock_init(const struct lu_env *env, __u32 enqflags = lock->cll_descr.cld_enq_flags; osc_lock_build_einfo(env, lock, clk, &clk->ols_einfo); - atomic_set(&clk->ols_pageref, 0); clk->ols_state = OLS_NEW; clk->ols_flags = osc_enq2ldlm_flags(enqflags); @@ -1597,26 +1668,4 @@ int osc_lock_init(const struct lu_env *env, return result; } -int osc_dlm_lock_pageref(struct ldlm_lock *dlm) -{ - struct osc_lock *olock; - int rc = 0; - - spin_lock(&osc_ast_guard); - olock = dlm->l_ast_data; - /* - * there's a very rare race with osc_page_addref_lock(), but that - * doesn't matter because in the worst case we don't cancel a lock - * which we actually can, that's no harm. - */ - if (olock && - atomic_add_return(_PAGEREF_MAGIC, - &olock->ols_pageref) != _PAGEREF_MAGIC) { - atomic_sub(_PAGEREF_MAGIC, &olock->ols_pageref); - rc = 1; - } - spin_unlock(&osc_ast_guard); - return rc; -} - /** @} osc */ diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index eff3b4b3b2b3..8dc62fa04300 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -67,10 +67,6 @@ static int osc_page_protected(const struct lu_env *env, static void osc_page_fini(const struct lu_env *env, struct cl_page_slice *slice) { - struct osc_page *opg = cl2osc_page(slice); - - CDEBUG(D_TRACE, "%p\n", opg); - LASSERT(!opg->ops_lock); } static void osc_page_transfer_get(struct osc_page *opg, const char *label) @@ -139,42 +135,6 @@ void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj, policy->l_extent.end = cl_offset(obj, end + 1) - 1; } -static int osc_page_addref_lock(const struct lu_env *env, - struct osc_page *opg, - struct cl_lock *lock) -{ - struct osc_lock *olock; - int rc; - - LASSERT(!opg->ops_lock); - - olock = osc_lock_at(lock); - if (atomic_inc_return(&olock->ols_pageref) <= 0) { - atomic_dec(&olock->ols_pageref); - rc = -ENODATA; - } else { - cl_lock_get(lock); - opg->ops_lock = lock; - rc = 0; - } - return rc; -} - -static void osc_page_putref_lock(const struct lu_env *env, - struct osc_page *opg) -{ - struct cl_lock *lock = opg->ops_lock; - struct osc_lock *olock; - - LASSERT(lock); - olock = osc_lock_at(lock); - - atomic_dec(&olock->ols_pageref); - opg->ops_lock = NULL; - - cl_lock_put(env, lock); -} - static int osc_page_is_under_lock(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) @@ -185,39 +145,12 @@ static int osc_page_is_under_lock(const struct lu_env *env, lock = cl_lock_at_page(env, slice->cpl_obj, slice->cpl_page, NULL, 1, 0); if (lock) { - if (osc_page_addref_lock(env, cl2osc_page(slice), lock) == 0) - result = -EBUSY; cl_lock_put(env, lock); + result = -EBUSY; } return result; } -static void osc_page_disown(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io) -{ - struct osc_page *opg = cl2osc_page(slice); - - if (unlikely(opg->ops_lock)) - osc_page_putref_lock(env, opg); -} - -static void osc_page_completion_read(const struct lu_env *env, - const struct cl_page_slice *slice, - int ioret) -{ - struct osc_page *opg = cl2osc_page(slice); - - if (likely(opg->ops_lock)) - osc_page_putref_lock(env, opg); -} - -static void osc_page_completion_write(const struct lu_env *env, - const struct cl_page_slice *slice, - int ioret) -{ -} - static const char *osc_list(struct list_head *head) { return list_empty(head) ? "-" : "+"; @@ -366,15 +299,6 @@ static const struct cl_page_operations osc_page_ops = { .cpo_print = osc_page_print, .cpo_delete = osc_page_delete, .cpo_is_under_lock = osc_page_is_under_lock, - .cpo_disown = osc_page_disown, - .io = { - [CRT_READ] = { - .cpo_completion = osc_page_completion_read - }, - [CRT_WRITE] = { - .cpo_completion = osc_page_completion_write - } - }, .cpo_clip = osc_page_clip, .cpo_cancel = osc_page_cancel, .cpo_flush = osc_page_flush diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 1ff497f05b2f..1e378e6c1a70 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -3131,8 +3131,6 @@ static int osc_import_event(struct obd_device *obd, */ static int osc_cancel_for_recovery(struct ldlm_lock *lock) { - check_res_locked(lock->l_resource); - /* * Cancel all unused extent lock in granted mode LCK_PR or LCK_CR. * @@ -3141,8 +3139,7 @@ static int osc_cancel_for_recovery(struct ldlm_lock *lock) */ if (lock->l_resource->lr_type == LDLM_EXTENT && (lock->l_granted_mode == LCK_PR || - lock->l_granted_mode == LCK_CR) && - (osc_dlm_lock_pageref(lock) == 0)) + lock->l_granted_mode == LCK_CR) && osc_ldlm_weigh_ast(lock) == 0) return 1; return 0; -- GitLab From 7addf402c1171e875109bb1567171c4c3f8f8229 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:32 -0400 Subject: [PATCH 0861/9938] staging/lustre/clio: remove stackable cl_page completely >From now on, cl_page becomes one to one mapping of vmpage. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/7895 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 43 +--- .../staging/lustre/lustre/include/lclient.h | 7 +- .../staging/lustre/lustre/llite/lcommon_cl.c | 12 +- .../lustre/lustre/llite/llite_internal.h | 4 + drivers/staging/lustre/lustre/llite/rw.c | 7 +- drivers/staging/lustre/lustre/llite/rw26.c | 35 +-- .../lustre/lustre/llite/vvp_internal.h | 2 +- drivers/staging/lustre/lustre/llite/vvp_io.c | 45 ++-- .../staging/lustre/lustre/llite/vvp_page.c | 23 +- .../lustre/lustre/lov/lov_cl_internal.h | 14 +- drivers/staging/lustre/lustre/lov/lov_io.c | 8 +- .../staging/lustre/lustre/lov/lov_object.c | 32 ++- drivers/staging/lustre/lustre/lov/lov_page.c | 104 ++------- .../staging/lustre/lustre/lov/lovsub_page.c | 2 +- .../staging/lustre/lustre/obdclass/cl_io.c | 63 +----- .../lustre/lustre/obdclass/cl_object.c | 4 +- .../staging/lustre/lustre/obdclass/cl_page.c | 213 ++++-------------- .../lustre/lustre/obdecho/echo_client.c | 22 +- drivers/staging/lustre/lustre/osc/osc_cache.c | 59 +++-- .../lustre/lustre/osc/osc_cl_internal.h | 12 +- drivers/staging/lustre/lustre/osc/osc_io.c | 41 ++-- drivers/staging/lustre/lustre/osc/osc_page.c | 33 ++- 22 files changed, 257 insertions(+), 528 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index c3865ec49769..5b65854834f5 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -322,7 +322,7 @@ struct cl_object_operations { * to be used instead of newly created. */ int (*coo_page_init)(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage); + struct cl_page *page, pgoff_t index); /** * Initialize lock slice for this layer. Called top-to-bottom through * every object layer when a new cl_lock is instantiated. Layer @@ -460,10 +460,6 @@ struct cl_object_header { co_lu.lo_linkage) /** @} cl_object */ -#ifndef pgoff_t -#define pgoff_t unsigned long -#endif - #define CL_PAGE_EOF ((pgoff_t)~0ull) /** \addtogroup cl_page cl_page @@ -727,16 +723,10 @@ struct cl_page { atomic_t cp_ref; /** An object this page is a part of. Immutable after creation. */ struct cl_object *cp_obj; - /** Logical page index within the object. Immutable after creation. */ - pgoff_t cp_index; /** List of slices. Immutable after creation. */ struct list_head cp_layers; - /** Parent page, NULL for top-level page. Immutable after creation. */ - struct cl_page *cp_parent; - /** Lower-layer page. NULL for bottommost page. Immutable after - * creation. - */ - struct cl_page *cp_child; + /** vmpage */ + struct page *cp_vmpage; /** * Page state. This field is const to avoid accidental update, it is * modified only internally within cl_page.c. Protected by a VM lock. @@ -791,6 +781,7 @@ struct cl_page { */ struct cl_page_slice { struct cl_page *cpl_page; + pgoff_t cpl_index; /** * Object slice corresponding to this page slice. Immutable after * creation. @@ -845,11 +836,6 @@ struct cl_page_operations { * provided by the topmost layer, see cl_page_disown0() as an example. */ - /** - * \return the underlying VM page. Optional. - */ - struct page *(*cpo_vmpage)(const struct lu_env *env, - const struct cl_page_slice *slice); /** * Called when \a io acquires this page into the exclusive * ownership. When this method returns, it is guaranteed that the is @@ -1102,6 +1088,12 @@ static inline int __page_in_use(const struct cl_page *page, int refc) #define cl_page_in_use(pg) __page_in_use(pg, 1) #define cl_page_in_use_noref(pg) __page_in_use(pg, 0) +static inline struct page *cl_page_vmpage(struct cl_page *page) +{ + LASSERT(page->cp_vmpage); + return page->cp_vmpage; +} + /** @} cl_page */ /** \addtogroup cl_lock cl_lock @@ -2729,7 +2721,7 @@ static inline int cl_object_same(struct cl_object *o0, struct cl_object *o1) static inline void cl_object_page_init(struct cl_object *clob, int size) { clob->co_slice_off = cl_object_header(clob)->coh_page_bufsize; - cl_object_header(clob)->coh_page_bufsize += ALIGN(size, 8); + cl_object_header(clob)->coh_page_bufsize += cfs_size_round(size); } static inline void *cl_object_page_slice(struct cl_object *clob, @@ -2774,9 +2766,7 @@ void cl_page_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_page *pg); void cl_page_header_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_page *pg); -struct page *cl_page_vmpage(const struct lu_env *env, struct cl_page *page); struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj); -struct cl_page *cl_page_top(struct cl_page *page); const struct cl_page_slice *cl_page_at(const struct cl_page *page, const struct lu_device_type *dtype); @@ -2868,17 +2858,6 @@ struct cl_lock *cl_lock_at_pgoff(const struct lu_env *env, struct cl_object *obj, pgoff_t index, struct cl_lock *except, int pending, int canceld); -static inline struct cl_lock *cl_lock_at_page(const struct lu_env *env, - struct cl_object *obj, - struct cl_page *page, - struct cl_lock *except, - int pending, int canceld) -{ - LASSERT(cl_object_header(obj) == cl_object_header(page->cp_obj)); - return cl_lock_at_pgoff(env, obj, page->cp_index, except, - pending, canceld); -} - const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock, const struct lu_device_type *dtype); diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index 6c3a30af0727..c91fb0151a52 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -238,6 +238,11 @@ static inline struct ccc_page *cl2ccc_page(const struct cl_page_slice *slice) return container_of(slice, struct ccc_page, cpg_cl); } +static inline pgoff_t ccc_index(struct ccc_page *ccc) +{ + return ccc->cpg_cl.cpl_index; +} + struct ccc_device { struct cl_device cdv_cl; struct super_block *cdv_sb; @@ -294,8 +299,6 @@ int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, const struct cl_lock_operations *lkops); int ccc_object_glimpse(const struct lu_env *env, const struct cl_object *obj, struct ost_lvb *lvb); -struct page *ccc_page_vmpage(const struct lu_env *env, - const struct cl_page_slice *slice); int ccc_page_is_under_lock(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *io); int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 065b0f20e95d..55fa0da80b81 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -336,6 +336,8 @@ struct lu_object *ccc_object_alloc(const struct lu_env *env, obj = ccc2lu(vob); hdr = &vob->cob_header; cl_object_header_init(hdr); + hdr->coh_page_bufsize = cfs_size_round(sizeof(struct cl_page)); + lu_object_init(obj, &hdr->coh_lu, dev); lu_object_add_top(&hdr->coh_lu, obj); @@ -450,12 +452,6 @@ static void ccc_object_size_unlock(struct cl_object *obj) * */ -struct page *ccc_page_vmpage(const struct lu_env *env, - const struct cl_page_slice *slice) -{ - return cl2vm_page(slice); -} - int ccc_page_is_under_lock(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *io) @@ -471,8 +467,8 @@ int ccc_page_is_under_lock(const struct lu_env *env, if (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED) { result = -EBUSY; } else { - desc->cld_start = page->cp_index; - desc->cld_end = page->cp_index; + desc->cld_start = ccc_index(cl2ccc_page(slice)); + desc->cld_end = ccc_index(cl2ccc_page(slice)); desc->cld_obj = page->cp_obj; desc->cld_mode = CLM_READ; result = cl_queue_match(&io->ci_lockset.cls_done, diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 08fe0ea5ee8f..bc831472b3ed 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -982,6 +982,10 @@ static inline void ll_invalidate_page(struct page *vmpage) if (!mapping) return; + /* + * truncate_complete_page() calls + * a_ops->invalidatepage()->cl_page_delete()->vvp_page_delete(). + */ ll_teardown_mmaps(mapping, offset, offset + PAGE_CACHE_SIZE); truncate_complete_page(mapping, vmpage); } diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index dcccdecbad00..b1375f1719e7 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -290,15 +290,16 @@ void ll_ra_read_ex(struct file *f, struct ll_ra_read *rar) static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, struct cl_page *page, - struct page *vmpage) + struct cl_object *clob) { + struct page *vmpage = page->cp_vmpage; struct ccc_page *cp; int rc; rc = 0; cl_page_assume(env, io, page); lu_ref_add(&page->cp_reference, "ra", current); - cp = cl2ccc_page(cl_page_at(page, &vvp_device_type)); + cp = cl2ccc_page(cl_object_page_slice(clob, page)); if (!cp->cpg_defer_uptodate && !PageUptodate(vmpage)) { rc = cl_page_is_under_lock(env, io, page); if (rc == -EBUSY) { @@ -348,7 +349,7 @@ static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io, vmpage, CPT_CACHEABLE); if (!IS_ERR(page)) { rc = cl_read_ahead_page(env, io, queue, - page, vmpage); + page, clob); if (rc == -ENOLCK) { which = RA_STAT_FAILED_MATCH; msg = "lock match failed"; diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index e8d29e1fb691..e2fea8c7a4fe 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -165,28 +165,6 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask) return result; } -static int ll_set_page_dirty(struct page *vmpage) -{ -#if 0 - struct cl_page *page = vvp_vmpage_page_transient(vmpage); - struct vvp_object *obj = cl_inode2vvp(vmpage->mapping->host); - struct vvp_page *cpg; - - /* - * XXX should page method be called here? - */ - LASSERT(&obj->co_cl == page->cp_obj); - cpg = cl2vvp_page(cl_page_at(page, &vvp_device_type)); - /* - * XXX cannot do much here, because page is possibly not locked: - * sys_munmap()->... - * ->unmap_page_range()->zap_pte_range()->set_page_dirty(). - */ - vvp_write_pending(obj, cpg); -#endif - return __set_page_dirty_nobuffers(vmpage); -} - #define MAX_DIRECTIO_SIZE (2*1024*1024*1024UL) static inline int ll_get_user_pages(int rw, unsigned long user_addr, @@ -274,7 +252,7 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, * write directly */ if (clp->cp_type == CPT_CACHEABLE) { - struct page *vmpage = cl_page_vmpage(env, clp); + struct page *vmpage = cl_page_vmpage(clp); struct page *src_page; struct page *dst_page; void *src; @@ -478,19 +456,16 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, static int ll_prepare_partial_page(const struct lu_env *env, struct cl_io *io, struct cl_page *pg) { - struct cl_object *obj = io->ci_obj; struct cl_attr *attr = ccc_env_thread_attr(env); - loff_t offset = cl_offset(obj, pg->cp_index); + struct cl_object *obj = io->ci_obj; + struct ccc_page *cp = cl_object_page_slice(obj, pg); + loff_t offset = cl_offset(obj, ccc_index(cp)); int result; cl_object_attr_lock(obj); result = cl_object_attr_get(env, obj, attr); cl_object_attr_unlock(obj); if (result == 0) { - struct ccc_page *cp; - - cp = cl2ccc_page(cl_page_at(pg, &vvp_device_type)); - /* * If are writing to a new page, no need to read old data. * The extent locking will have updated the KMS, and for our @@ -685,7 +660,7 @@ const struct address_space_operations ll_aops = { .direct_IO = ll_direct_IO_26, .writepage = ll_writepage, .writepages = ll_writepages, - .set_page_dirty = ll_set_page_dirty, + .set_page_dirty = __set_page_dirty_nobuffers, .write_begin = ll_write_begin, .write_end = ll_write_end, .invalidatepage = ll_invalidatepage, diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 9abde114ba16..aa06f4031311 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -49,7 +49,7 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, int vvp_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io); int vvp_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage); + struct cl_page *page, pgoff_t index); struct lu_object *vvp_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index f4a1384730fa..ac9d615b78d9 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -625,7 +625,7 @@ static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, cl_page_clip(env, page, 0, PAGE_SIZE); - SetPageUptodate(cl_page_vmpage(env, page)); + SetPageUptodate(cl_page_vmpage(page)); cl_page_disown(env, io, page); /* held in ll_cl_init() */ @@ -640,17 +640,15 @@ static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, static void write_commit_callback(const struct lu_env *env, struct cl_io *io, struct cl_page *page) { - const struct cl_page_slice *slice; struct ccc_page *cp; - struct page *vmpage; - - slice = cl_page_at(page, &vvp_device_type); - cp = cl2ccc_page(slice); - vmpage = cp->cpg_page; + struct page *vmpage = page->cp_vmpage; + struct cl_object *clob = cl_io_top(io)->ci_obj; SetPageUptodate(vmpage); set_page_dirty(vmpage); - vvp_write_pending(cl2ccc(slice->cpl_obj), cp); + + cp = cl2ccc_page(cl_object_page_slice(clob, page)); + vvp_write_pending(cl2ccc(clob), cp); cl_page_disown(env, io, page); @@ -660,19 +658,22 @@ static void write_commit_callback(const struct lu_env *env, struct cl_io *io, } /* make sure the page list is contiguous */ -static bool page_list_sanity_check(struct cl_page_list *plist) +static bool page_list_sanity_check(struct cl_object *obj, + struct cl_page_list *plist) { struct cl_page *page; pgoff_t index = CL_PAGE_EOF; cl_page_list_for_each(page, plist) { + struct ccc_page *cp = cl_object_page_slice(obj, page); + if (index == CL_PAGE_EOF) { - index = page->cp_index; + index = ccc_index(cp); continue; } ++index; - if (index == page->cp_index) + if (index == ccc_index(cp)) continue; return false; @@ -698,7 +699,7 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) CDEBUG(D_VFSTRACE, "commit async pages: %d, from %d, to %d\n", npages, cio->u.write.cui_from, cio->u.write.cui_to); - LASSERT(page_list_sanity_check(queue)); + LASSERT(page_list_sanity_check(obj, queue)); /* submit IO with async write */ rc = cl_io_commit_async(env, io, queue, @@ -723,7 +724,7 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) /* the first page must have been written. */ cio->u.write.cui_from = 0; } - LASSERT(page_list_sanity_check(queue)); + LASSERT(page_list_sanity_check(obj, queue)); LASSERT(ergo(rc == 0, queue->pl_nr == 0)); /* out of quota, try sync write */ @@ -747,7 +748,7 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) page = cl_page_list_first(queue); cl_page_list_del(env, queue, page); - if (!PageDirty(cl_page_vmpage(env, page))) + if (!PageDirty(cl_page_vmpage(page))) cl_page_discard(env, io, page); cl_page_disown(env, io, page); @@ -861,16 +862,13 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) static void mkwrite_commit_callback(const struct lu_env *env, struct cl_io *io, struct cl_page *page) { - const struct cl_page_slice *slice; struct ccc_page *cp; - struct page *vmpage; + struct cl_object *clob = cl_io_top(io)->ci_obj; - slice = cl_page_at(page, &vvp_device_type); - cp = cl2ccc_page(slice); - vmpage = cp->cpg_page; + set_page_dirty(page->cp_vmpage); - set_page_dirty(vmpage); - vvp_write_pending(cl2ccc(slice->cpl_obj), cp); + cp = cl2ccc_page(cl_object_page_slice(clob, page)); + vvp_write_pending(cl2ccc(clob), cp); } static int vvp_io_fault_start(const struct lu_env *env, @@ -975,6 +973,7 @@ static int vvp_io_fault_start(const struct lu_env *env, wait_on_page_writeback(vmpage); if (!PageDirty(vmpage)) { struct cl_page_list *plist = &io->ci_queue.c2_qin; + struct ccc_page *cp = cl_object_page_slice(obj, page); int to = PAGE_SIZE; /* vvp_page_assume() calls wait_on_page_writeback(). */ @@ -984,7 +983,7 @@ static int vvp_io_fault_start(const struct lu_env *env, cl_page_list_add(plist, page); /* size fixup */ - if (last_index == page->cp_index) + if (last_index == ccc_index(cp)) to = size & ~PAGE_MASK; /* Do not set Dirty bit here so that in case IO is @@ -1069,7 +1068,7 @@ static int vvp_io_read_page(const struct lu_env *env, if (sbi->ll_ra_info.ra_max_pages_per_file && sbi->ll_ra_info.ra_max_pages) - ras_update(sbi, inode, ras, page->cp_index, + ras_update(sbi, inode, ras, ccc_index(cp), cp->cpg_defer_uptodate); /* Sanity check whether the page is protected by a lock. */ diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 11e609ebbe3e..d9f13c31091a 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -136,26 +136,15 @@ static void vvp_page_discard(const struct lu_env *env, struct cl_io *unused) { struct page *vmpage = cl2vm_page(slice); - struct address_space *mapping; struct ccc_page *cpg = cl2ccc_page(slice); - __u64 offset; LASSERT(vmpage); LASSERT(PageLocked(vmpage)); - mapping = vmpage->mapping; - if (cpg->cpg_defer_uptodate && !cpg->cpg_ra_used) - ll_ra_stats_inc(mapping, RA_STAT_DISCARDED); - - offset = vmpage->index << PAGE_SHIFT; - ll_teardown_mmaps(vmpage->mapping, offset, offset + PAGE_SIZE); + ll_ra_stats_inc(vmpage->mapping, RA_STAT_DISCARDED); - /* - * truncate_complete_page() calls - * a_ops->invalidatepage()->cl_page_delete()->vvp_page_delete(). - */ - truncate_complete_page(mapping, vmpage); + ll_invalidate_page(vmpage); } static void vvp_page_delete(const struct lu_env *env, @@ -269,7 +258,7 @@ static void vvp_page_completion_read(const struct lu_env *env, { struct ccc_page *cp = cl2ccc_page(slice); struct page *vmpage = cp->cpg_page; - struct cl_page *page = cl_page_top(slice->cpl_page); + struct cl_page *page = slice->cpl_page; struct inode *inode = ccc_object_inode(page->cp_obj); LASSERT(PageLocked(vmpage)); @@ -394,7 +383,6 @@ static const struct cl_page_operations vvp_page_ops = { .cpo_assume = vvp_page_assume, .cpo_unassume = vvp_page_unassume, .cpo_disown = vvp_page_disown, - .cpo_vmpage = ccc_page_vmpage, .cpo_discard = vvp_page_discard, .cpo_delete = vvp_page_delete, .cpo_export = vvp_page_export, @@ -504,7 +492,6 @@ static const struct cl_page_operations vvp_transient_page_ops = { .cpo_unassume = vvp_transient_page_unassume, .cpo_disown = vvp_transient_page_disown, .cpo_discard = vvp_transient_page_discard, - .cpo_vmpage = ccc_page_vmpage, .cpo_fini = vvp_transient_page_fini, .cpo_is_vmlocked = vvp_transient_page_is_vmlocked, .cpo_print = vvp_page_print, @@ -522,12 +509,14 @@ static const struct cl_page_operations vvp_transient_page_ops = { }; int vvp_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage) + struct cl_page *page, pgoff_t index) { struct ccc_page *cpg = cl_object_page_slice(obj, page); + struct page *vmpage = page->cp_vmpage; CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + cpg->cpg_cl.cpl_index = index; cpg->cpg_page = vmpage; page_cache_get(vmpage); diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 3d568fc62adc..b8e2315d5216 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -613,14 +613,13 @@ int lov_sublock_modify(const struct lu_env *env, struct lov_lock *lov, const struct cl_lock_descr *d, int idx); int lov_page_init(const struct lu_env *env, struct cl_object *ob, - struct cl_page *page, struct page *vmpage); + struct cl_page *page, pgoff_t index); int lovsub_page_init(const struct lu_env *env, struct cl_object *ob, - struct cl_page *page, struct page *vmpage); - + struct cl_page *page, pgoff_t index); int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage); + struct cl_page *page, pgoff_t index); int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage); + struct cl_page *page, pgoff_t index); struct lu_object *lov_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); @@ -791,11 +790,6 @@ static inline struct lovsub_req *cl2lovsub_req(const struct cl_req_slice *slice) return container_of0(slice, struct lovsub_req, lsrq_cl); } -static inline struct cl_page *lov_sub_page(const struct cl_page_slice *slice) -{ - return slice->cpl_page->cp_child; -} - static inline struct lov_io *cl2lov_io(const struct lu_env *env, const struct cl_io_slice *ios) { diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index c60649032e59..e5b2cfc5b662 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -248,10 +248,12 @@ void lov_sub_put(struct lov_io_sub *sub) static int lov_page_stripe(const struct cl_page *page) { struct lovsub_object *subobj; + const struct cl_page_slice *slice; - subobj = lu2lovsub( - lu_object_locate(page->cp_child->cp_obj->co_lu.lo_header, - &lovsub_device_type)); + slice = cl_page_at(page, &lovsub_device_type); + LASSERT(slice->cpl_obj); + + subobj = cl2lovsub(slice->cpl_obj); return subobj->lso_index; } diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 5d8a2b64ce21..0159b6f1e5c3 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -67,7 +67,7 @@ struct lov_layout_operations { int (*llo_print)(const struct lu_env *env, void *cookie, lu_printer_t p, const struct lu_object *o); int (*llo_page_init)(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage); + struct cl_page *page, pgoff_t index); int (*llo_lock_init)(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io); @@ -193,6 +193,18 @@ static int lov_init_sub(const struct lu_env *env, struct lov_object *lov, return result; } +static int lov_page_slice_fixup(struct lov_object *lov, + struct cl_object *stripe) +{ + struct cl_object_header *hdr = cl_object_header(&lov->lo_cl); + struct cl_object *o; + + cl_object_for_each(o, stripe) + o->co_slice_off += hdr->coh_page_bufsize; + + return cl_object_header(stripe)->coh_page_bufsize; +} + static int lov_init_raid0(const struct lu_env *env, struct lov_device *dev, struct lov_object *lov, const struct cl_object_conf *conf, @@ -222,6 +234,8 @@ static int lov_init_raid0(const struct lu_env *env, r0->lo_sub = libcfs_kvzalloc(r0->lo_nr * sizeof(r0->lo_sub[0]), GFP_NOFS); if (r0->lo_sub) { + int psz = 0; + result = 0; subconf->coc_inode = conf->coc_inode; spin_lock_init(&r0->lo_sub_lock); @@ -254,11 +268,21 @@ static int lov_init_raid0(const struct lu_env *env, if (result == -EAGAIN) { /* try again */ --i; result = 0; + continue; } } else { result = PTR_ERR(stripe); } + + if (result == 0) { + int sz = lov_page_slice_fixup(lov, stripe); + + LASSERT(ergo(psz > 0, psz == sz)); + psz = sz; + } } + if (result == 0) + cl_object_header(&lov->lo_cl)->coh_page_bufsize += psz; } else result = -ENOMEM; out: @@ -824,10 +848,10 @@ static int lov_object_print(const struct lu_env *env, void *cookie, } int lov_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage) + struct cl_page *page, pgoff_t index) { - return LOV_2DISPATCH_NOLOCK(cl2lov(obj), - llo_page_init, env, obj, page, vmpage); + return LOV_2DISPATCH_NOLOCK(cl2lov(obj), llo_page_init, env, obj, page, + index); } /** diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index 5d9b355fc608..0c508bd0f8ad 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -52,59 +52,6 @@ * Lov page operations. * */ - -static int lov_page_invariant(const struct cl_page_slice *slice) -{ - const struct cl_page *page = slice->cpl_page; - const struct cl_page *sub = lov_sub_page(slice); - - return ergo(sub, - page->cp_child == sub && - sub->cp_parent == page && - page->cp_state == sub->cp_state); -} - -static void lov_page_fini(const struct lu_env *env, - struct cl_page_slice *slice) -{ - struct cl_page *sub = lov_sub_page(slice); - - LINVRNT(lov_page_invariant(slice)); - - if (sub) { - LASSERT(sub->cp_state == CPS_FREEING); - lu_ref_del(&sub->cp_reference, "lov", sub->cp_parent); - sub->cp_parent = NULL; - slice->cpl_page->cp_child = NULL; - cl_page_put(env, sub); - } -} - -static int lov_page_own(const struct lu_env *env, - const struct cl_page_slice *slice, struct cl_io *io, - int nonblock) -{ - struct lov_io *lio = lov_env_io(env); - struct lov_io_sub *sub; - - LINVRNT(lov_page_invariant(slice)); - LINVRNT(!cl2lov_page(slice)->lps_invalid); - - sub = lov_page_subio(env, lio, slice); - if (!IS_ERR(sub)) { - lov_sub_page(slice)->cp_owner = sub->sub_io; - lov_sub_put(sub); - } else - LBUG(); /* Arrgh */ - return 0; -} - -static void lov_page_assume(const struct lu_env *env, - const struct cl_page_slice *slice, struct cl_io *io) -{ - lov_page_own(env, slice, io, 0); -} - static int lov_page_print(const struct lu_env *env, const struct cl_page_slice *slice, void *cookie, lu_printer_t printer) @@ -115,26 +62,17 @@ static int lov_page_print(const struct lu_env *env, } static const struct cl_page_operations lov_page_ops = { - .cpo_fini = lov_page_fini, - .cpo_own = lov_page_own, - .cpo_assume = lov_page_assume, .cpo_print = lov_page_print }; -static void lov_empty_page_fini(const struct lu_env *env, - struct cl_page_slice *slice) -{ - LASSERT(!slice->cpl_page->cp_child); -} - int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage) + struct cl_page *page, pgoff_t index) { struct lov_object *loo = cl2lov(obj); struct lov_layout_raid0 *r0 = lov_r0(loo); struct lov_io *lio = lov_env_io(env); - struct cl_page *subpage; struct cl_object *subobj; + struct cl_object *o; struct lov_io_sub *sub; struct lov_page *lpg = cl_object_page_slice(obj, page); loff_t offset; @@ -142,13 +80,12 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, int stripe; int rc; - offset = cl_offset(obj, page->cp_index); + offset = cl_offset(obj, index); stripe = lov_stripe_number(loo->lo_lsm, offset); LASSERT(stripe < r0->lo_nr); rc = lov_stripe_offset(loo->lo_lsm, offset, stripe, &suboff); LASSERT(rc == 0); - lpg->lps_invalid = 1; cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_page_ops); sub = lov_sub_get(env, lio, stripe); @@ -156,35 +93,44 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, return PTR_ERR(sub); subobj = lovsub2cl(r0->lo_sub[stripe]); - subpage = cl_page_alloc(sub->sub_env, subobj, cl_index(subobj, suboff), - vmpage, page->cp_type); - if (!IS_ERR(subpage)) { - subpage->cp_parent = page; - page->cp_child = subpage; - lpg->lps_invalid = 0; - } else { - rc = PTR_ERR(subpage); + list_for_each_entry(o, &subobj->co_lu.lo_header->loh_layers, + co_lu.lo_linkage) { + if (o->co_ops->coo_page_init) { + rc = o->co_ops->coo_page_init(sub->sub_env, o, page, + cl_index(subobj, suboff)); + if (rc != 0) + break; + } } lov_sub_put(sub); return rc; } +static int lov_page_empty_print(const struct lu_env *env, + const struct cl_page_slice *slice, + void *cookie, lu_printer_t printer) +{ + struct lov_page *lp = cl2lov_page(slice); + + return (*printer)(env, cookie, LUSTRE_LOV_NAME "-page@%p, empty.\n", + lp); +} + static const struct cl_page_operations lov_empty_page_ops = { - .cpo_fini = lov_empty_page_fini, - .cpo_print = lov_page_print + .cpo_print = lov_page_empty_print }; int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage) + struct cl_page *page, pgoff_t index) { struct lov_page *lpg = cl_object_page_slice(obj, page); void *addr; cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_empty_page_ops); - addr = kmap(vmpage); + addr = kmap(page->cp_vmpage); memset(addr, 0, cl_page_size(obj)); - kunmap(vmpage); + kunmap(page->cp_vmpage); cl_page_export(env, page, 1); return 0; } diff --git a/drivers/staging/lustre/lustre/lov/lovsub_page.c b/drivers/staging/lustre/lustre/lov/lovsub_page.c index 2d945532b78e..fb4c0ccee30c 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_page.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_page.c @@ -60,7 +60,7 @@ static const struct cl_page_operations lovsub_page_ops = { }; int lovsub_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *unused) + struct cl_page *page, pgoff_t ind) { struct lovsub_page *lsb = cl_object_page_slice(obj, page); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 9b3c5c1f26e3..86591ceac9c1 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -692,42 +692,6 @@ cl_io_slice_page(const struct cl_io_slice *ios, struct cl_page *page) return slice; } -/** - * True iff \a page is within \a io range. - */ -static int cl_page_in_io(const struct cl_page *page, const struct cl_io *io) -{ - int result = 1; - loff_t start; - loff_t end; - pgoff_t idx; - - idx = page->cp_index; - switch (io->ci_type) { - case CIT_READ: - case CIT_WRITE: - /* - * check that [start, end) and [pos, pos + count) extents - * overlap. - */ - if (!cl_io_is_append(io)) { - const struct cl_io_rw_common *crw = &(io->u.ci_rw); - - start = cl_offset(page->cp_obj, idx); - end = cl_offset(page->cp_obj, idx + 1); - result = crw->crw_pos < end && - start < crw->crw_pos + crw->crw_count; - } - break; - case CIT_FAULT: - result = io->u.ci_fault.ft_index == idx; - break; - default: - LBUG(); - } - return result; -} - /** * Called by read io, when page has to be read from the server. * @@ -743,7 +707,6 @@ int cl_io_read_page(const struct lu_env *env, struct cl_io *io, LINVRNT(io->ci_type == CIT_READ || io->ci_type == CIT_FAULT); LINVRNT(cl_page_is_owned(page, io)); LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED); - LINVRNT(cl_page_in_io(page, io)); LINVRNT(cl_io_invariant(io)); queue = &io->ci_queue; @@ -893,7 +856,6 @@ static int cl_io_cancel(const struct lu_env *env, struct cl_io *io, cl_page_list_for_each(page, queue) { int rc; - LINVRNT(cl_page_in_io(page, io)); rc = cl_page_cancel(env, page); result = result ?: rc; } @@ -1229,7 +1191,7 @@ EXPORT_SYMBOL(cl_2queue_init_page); /** * Returns top-level io. * - * \see cl_object_top(), cl_page_top(). + * \see cl_object_top() */ struct cl_io *cl_io_top(struct cl_io *io) { @@ -1292,19 +1254,14 @@ static int cl_req_init(const struct lu_env *env, struct cl_req *req, int result; result = 0; - page = cl_page_top(page); - do { - list_for_each_entry(slice, &page->cp_layers, cpl_linkage) { - dev = lu2cl_dev(slice->cpl_obj->co_lu.lo_dev); - if (dev->cd_ops->cdo_req_init) { - result = dev->cd_ops->cdo_req_init(env, - dev, req); - if (result != 0) - break; - } + list_for_each_entry(slice, &page->cp_layers, cpl_linkage) { + dev = lu2cl_dev(slice->cpl_obj->co_lu.lo_dev); + if (dev->cd_ops->cdo_req_init) { + result = dev->cd_ops->cdo_req_init(env, dev, req); + if (result != 0) + break; } - page = page->cp_child; - } while (page && result == 0); + } return result; } @@ -1375,8 +1332,6 @@ void cl_req_page_add(const struct lu_env *env, struct cl_req_obj *rqo; int i; - page = cl_page_top(page); - LASSERT(list_empty(&page->cp_flight)); LASSERT(!page->cp_req); @@ -1407,8 +1362,6 @@ void cl_req_page_done(const struct lu_env *env, struct cl_page *page) { struct cl_req *req = page->cp_req; - page = cl_page_top(page); - LASSERT(!list_empty(&page->cp_flight)); LASSERT(req->crq_nrpages > 0); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index fa9b083915d9..72e6333220ea 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -84,7 +84,7 @@ int cl_object_header_init(struct cl_object_header *h) lockdep_set_class(&h->coh_lock_guard, &cl_lock_guard_class); lockdep_set_class(&h->coh_attr_guard, &cl_attr_guard_class); INIT_LIST_HEAD(&h->coh_locks); - h->coh_page_bufsize = ALIGN(sizeof(struct cl_page), 8); + h->coh_page_bufsize = 0; } return result; } @@ -138,7 +138,7 @@ EXPORT_SYMBOL(cl_object_get); /** * Returns the top-object for a given \a o. * - * \see cl_page_top(), cl_io_top() + * \see cl_io_top() */ struct cl_object *cl_object_top(struct cl_object *o) { diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 0844a97c3258..cb156739b254 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -62,18 +62,6 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg); # define PINVRNT(env, page, exp) \ ((void)sizeof(env), (void)sizeof(page), (void)sizeof !!(exp)) -/** - * Internal version of cl_page_top, it should be called if the page is - * known to be not freed, says with page referenced, or radix tree lock held, - * or page owned. - */ -static struct cl_page *cl_page_top_trusted(struct cl_page *page) -{ - while (page->cp_parent) - page = page->cp_parent; - return page; -} - /** * Internal version of cl_page_get(). * @@ -102,14 +90,10 @@ cl_page_at_trusted(const struct cl_page *page, { const struct cl_page_slice *slice; - page = cl_page_top_trusted((struct cl_page *)page); - do { - list_for_each_entry(slice, &page->cp_layers, cpl_linkage) { - if (slice->cpl_obj->co_lu.lo_dev->ld_type == dtype) - return slice; - } - page = page->cp_child; - } while (page); + list_for_each_entry(slice, &page->cp_layers, cpl_linkage) { + if (slice->cpl_obj->co_lu.lo_dev->ld_type == dtype) + return slice; + } return NULL; } @@ -120,7 +104,6 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page) PASSERT(env, page, list_empty(&page->cp_batch)); PASSERT(env, page, !page->cp_owner); PASSERT(env, page, !page->cp_req); - PASSERT(env, page, !page->cp_parent); PASSERT(env, page, page->cp_state == CPS_FREEING); while (!list_empty(&page->cp_layers)) { @@ -129,7 +112,8 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page) slice = list_entry(page->cp_layers.next, struct cl_page_slice, cpl_linkage); list_del_init(page->cp_layers.next); - slice->cpl_ops->cpo_fini(env, slice); + if (unlikely(slice->cpl_ops->cpo_fini)) + slice->cpl_ops->cpo_fini(env, slice); } lu_object_ref_del_at(&obj->co_lu, &page->cp_obj_ref, "cl_page", page); cl_object_put(env, obj); @@ -165,7 +149,7 @@ struct cl_page *cl_page_alloc(const struct lu_env *env, cl_object_get(o); lu_object_ref_add_at(&o->co_lu, &page->cp_obj_ref, "cl_page", page); - page->cp_index = ind; + page->cp_vmpage = vmpage; cl_page_state_set_trust(page, CPS_CACHED); page->cp_type = type; INIT_LIST_HEAD(&page->cp_layers); @@ -176,8 +160,8 @@ struct cl_page *cl_page_alloc(const struct lu_env *env, head = o->co_lu.lo_header; list_for_each_entry(o, &head->loh_layers, co_lu.lo_linkage) { if (o->co_ops->coo_page_init) { - result = o->co_ops->coo_page_init(env, o, - page, vmpage); + result = o->co_ops->coo_page_init(env, o, page, + ind); if (result != 0) { cl_page_delete0(env, page); cl_page_free(env, page); @@ -249,27 +233,12 @@ EXPORT_SYMBOL(cl_page_find); static inline int cl_page_invariant(const struct cl_page *pg) { - struct cl_page *parent; - struct cl_page *child; - struct cl_io *owner; - /* * Page invariant is protected by a VM lock. */ LINVRNT(cl_page_is_vmlocked(NULL, pg)); - parent = pg->cp_parent; - child = pg->cp_child; - owner = pg->cp_owner; - - return cl_page_in_use(pg) && - ergo(parent, parent->cp_child == pg) && - ergo(child, child->cp_parent == pg) && - ergo(child, pg->cp_obj != child->cp_obj) && - ergo(parent, pg->cp_obj != parent->cp_obj) && - ergo(owner && parent, - parent->cp_owner == pg->cp_owner->ci_parent) && - ergo(owner && child, child->cp_owner->ci_parent == owner); + return cl_page_in_use_noref(pg); } static void cl_page_state_set0(const struct lu_env *env, @@ -322,13 +291,9 @@ static void cl_page_state_set0(const struct lu_env *env, old = page->cp_state; PASSERT(env, page, allowed_transitions[old][state]); CL_PAGE_HEADER(D_TRACE, env, page, "%d -> %d\n", old, state); - for (; page; page = page->cp_child) { - PASSERT(env, page, page->cp_state == old); - PASSERT(env, page, - equi(state == CPS_OWNED, page->cp_owner)); - - cl_page_state_set_trust(page, state); - } + PASSERT(env, page, page->cp_state == old); + PASSERT(env, page, equi(state == CPS_OWNED, page->cp_owner)); + cl_page_state_set_trust(page, state); } static void cl_page_state_set(const struct lu_env *env, @@ -362,8 +327,6 @@ EXPORT_SYMBOL(cl_page_get); */ void cl_page_put(const struct lu_env *env, struct cl_page *page) { - PASSERT(env, page, atomic_read(&page->cp_ref) > !!page->cp_parent); - CL_PAGE_HEADER(D_TRACE, env, page, "%d\n", atomic_read(&page->cp_ref)); @@ -382,35 +345,11 @@ void cl_page_put(const struct lu_env *env, struct cl_page *page) } EXPORT_SYMBOL(cl_page_put); -/** - * Returns a VM page associated with a given cl_page. - */ -struct page *cl_page_vmpage(const struct lu_env *env, struct cl_page *page) -{ - const struct cl_page_slice *slice; - - /* - * Find uppermost layer with ->cpo_vmpage() method, and return its - * result. - */ - page = cl_page_top(page); - do { - list_for_each_entry(slice, &page->cp_layers, cpl_linkage) { - if (slice->cpl_ops->cpo_vmpage) - return slice->cpl_ops->cpo_vmpage(env, slice); - } - page = page->cp_child; - } while (page); - LBUG(); /* ->cpo_vmpage() has to be defined somewhere in the stack */ -} -EXPORT_SYMBOL(cl_page_vmpage); - /** * Returns a cl_page associated with a VM page, and given cl_object. */ struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj) { - struct cl_page *top; struct cl_page *page; KLASSERT(PageLocked(vmpage)); @@ -421,36 +360,15 @@ struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj) * bottom-to-top pass. */ - /* - * This loop assumes that ->private points to the top-most page. This - * can be rectified easily. - */ - top = (struct cl_page *)vmpage->private; - if (!top) - return NULL; - - for (page = top; page; page = page->cp_child) { - if (cl_object_same(page->cp_obj, obj)) { - cl_page_get_trust(page); - break; - } + page = (struct cl_page *)vmpage->private; + if (page) { + cl_page_get_trust(page); + LASSERT(page->cp_type == CPT_CACHEABLE); } - LASSERT(ergo(page, page->cp_type == CPT_CACHEABLE)); return page; } EXPORT_SYMBOL(cl_vmpage_page); -/** - * Returns the top-page for a given page. - * - * \see cl_object_top(), cl_io_top() - */ -struct cl_page *cl_page_top(struct cl_page *page) -{ - return cl_page_top_trusted(page); -} -EXPORT_SYMBOL(cl_page_top); - const struct cl_page_slice *cl_page_at(const struct cl_page *page, const struct lu_device_type *dtype) { @@ -470,21 +388,14 @@ EXPORT_SYMBOL(cl_page_at); int (*__method)_proto; \ \ __result = 0; \ - __page = cl_page_top(__page); \ - do { \ - list_for_each_entry(__scan, &__page->cp_layers, \ - cpl_linkage) { \ - __method = *(void **)((char *)__scan->cpl_ops + \ - __op); \ - if (__method) { \ - __result = (*__method)(__env, __scan, \ - ## __VA_ARGS__); \ - if (__result != 0) \ - break; \ - } \ - } \ - __page = __page->cp_child; \ - } while (__page && __result == 0); \ + list_for_each_entry(__scan, &__page->cp_layers, cpl_linkage) { \ + __method = *(void **)((char *)__scan->cpl_ops + __op); \ + if (__method) { \ + __result = (*__method)(__env, __scan, ## __VA_ARGS__); \ + if (__result != 0) \ + break; \ + } \ + } \ if (__result > 0) \ __result = 0; \ __result; \ @@ -498,18 +409,11 @@ do { \ ptrdiff_t __op = (_op); \ void (*__method)_proto; \ \ - __page = cl_page_top(__page); \ - do { \ - list_for_each_entry(__scan, &__page->cp_layers, \ - cpl_linkage) { \ - __method = *(void **)((char *)__scan->cpl_ops + \ - __op); \ - if (__method) \ - (*__method)(__env, __scan, \ - ## __VA_ARGS__); \ - } \ - __page = __page->cp_child; \ - } while (__page); \ + list_for_each_entry(__scan, &__page->cp_layers, cpl_linkage) { \ + __method = *(void **)((char *)__scan->cpl_ops + __op); \ + if (__method) \ + (*__method)(__env, __scan, ## __VA_ARGS__); \ + } \ } while (0) #define CL_PAGE_INVOID_REVERSE(_env, _page, _op, _proto, ...) \ @@ -520,20 +424,11 @@ do { \ ptrdiff_t __op = (_op); \ void (*__method)_proto; \ \ - /* get to the bottom page. */ \ - while (__page->cp_child) \ - __page = __page->cp_child; \ - do { \ - list_for_each_entry_reverse(__scan, &__page->cp_layers, \ - cpl_linkage) { \ - __method = *(void **)((char *)__scan->cpl_ops + \ - __op); \ - if (__method) \ - (*__method)(__env, __scan, \ - ## __VA_ARGS__); \ - } \ - __page = __page->cp_parent; \ - } while (__page); \ + list_for_each_entry_reverse(__scan, &__page->cp_layers, cpl_linkage) { \ + __method = *(void **)((char *)__scan->cpl_ops + __op); \ + if (__method) \ + (*__method)(__env, __scan, ## __VA_ARGS__); \ + } \ } while (0) static int cl_page_invoke(const struct lu_env *env, @@ -559,20 +454,17 @@ static void cl_page_invoid(const struct lu_env *env, static void cl_page_owner_clear(struct cl_page *page) { - for (page = cl_page_top(page); page; page = page->cp_child) { - if (page->cp_owner) { - LASSERT(page->cp_owner->ci_owned_nr > 0); - page->cp_owner->ci_owned_nr--; - page->cp_owner = NULL; - page->cp_task = NULL; - } + if (page->cp_owner) { + LASSERT(page->cp_owner->ci_owned_nr > 0); + page->cp_owner->ci_owned_nr--; + page->cp_owner = NULL; + page->cp_task = NULL; } } static void cl_page_owner_set(struct cl_page *page) { - for (page = cl_page_top(page); page; page = page->cp_child) - page->cp_owner->ci_owned_nr++; + page->cp_owner->ci_owned_nr++; } void cl_page_disown0(const struct lu_env *env, @@ -603,8 +495,9 @@ void cl_page_disown0(const struct lu_env *env, */ int cl_page_is_owned(const struct cl_page *pg, const struct cl_io *io) { + struct cl_io *top = cl_io_top((struct cl_io *)io); LINVRNT(cl_object_same(pg->cp_obj, io->ci_obj)); - return pg->cp_state == CPS_OWNED && pg->cp_owner == io; + return pg->cp_state == CPS_OWNED && pg->cp_owner == top; } EXPORT_SYMBOL(cl_page_is_owned); @@ -635,7 +528,6 @@ static int cl_page_own0(const struct lu_env *env, struct cl_io *io, PINVRNT(env, pg, !cl_page_is_owned(pg, io)); - pg = cl_page_top(pg); io = cl_io_top(io); if (pg->cp_state == CPS_FREEING) { @@ -649,7 +541,7 @@ static int cl_page_own0(const struct lu_env *env, struct cl_io *io, if (result == 0) { PASSERT(env, pg, !pg->cp_owner); PASSERT(env, pg, !pg->cp_req); - pg->cp_owner = io; + pg->cp_owner = cl_io_top(io); pg->cp_task = current; cl_page_owner_set(pg); if (pg->cp_state != CPS_FREEING) { @@ -702,12 +594,11 @@ void cl_page_assume(const struct lu_env *env, { PINVRNT(env, pg, cl_object_same(pg->cp_obj, io->ci_obj)); - pg = cl_page_top(pg); io = cl_io_top(io); cl_page_invoid(env, io, pg, CL_PAGE_OP(cpo_assume)); PASSERT(env, pg, !pg->cp_owner); - pg->cp_owner = io; + pg->cp_owner = cl_io_top(io); pg->cp_task = current; cl_page_owner_set(pg); cl_page_state_set(env, pg, CPS_OWNED); @@ -731,7 +622,6 @@ void cl_page_unassume(const struct lu_env *env, PINVRNT(env, pg, cl_page_is_owned(pg, io)); PINVRNT(env, pg, cl_page_invariant(pg)); - pg = cl_page_top(pg); io = cl_io_top(io); cl_page_owner_clear(pg); cl_page_state_set(env, pg, CPS_CACHED); @@ -758,7 +648,6 @@ void cl_page_disown(const struct lu_env *env, { PINVRNT(env, pg, cl_page_is_owned(pg, io)); - pg = cl_page_top(pg); io = cl_io_top(io); cl_page_disown0(env, io, pg); } @@ -791,7 +680,6 @@ EXPORT_SYMBOL(cl_page_discard); */ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg) { - PASSERT(env, pg, pg == cl_page_top(pg)); PASSERT(env, pg, pg->cp_state != CPS_FREEING); /* @@ -825,7 +713,6 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg) * Once page reaches cl_page_state::CPS_FREEING, all remaining references will * drain after some time, at which point page will be recycled. * - * \pre pg == cl_page_top(pg) * \pre VM page is locked * \post pg->cp_state == CPS_FREEING * @@ -865,7 +752,6 @@ int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg) int result; const struct cl_page_slice *slice; - pg = cl_page_top_trusted((struct cl_page *)pg); slice = container_of(pg->cp_layers.next, const struct cl_page_slice, cpl_linkage); PASSERT(env, pg, slice->cpl_ops->cpo_is_vmlocked); @@ -1082,9 +968,8 @@ void cl_page_header_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_page *pg) { (*printer)(env, cookie, - "page@%p[%d %p:%lu ^%p_%p %d %d %d %p %p %#x]\n", + "page@%p[%d %p %d %d %d %p %p %#x]\n", pg, atomic_read(&pg->cp_ref), pg->cp_obj, - pg->cp_index, pg->cp_parent, pg->cp_child, pg->cp_state, pg->cp_error, pg->cp_type, pg->cp_owner, pg->cp_req, pg->cp_flags); } @@ -1096,11 +981,7 @@ EXPORT_SYMBOL(cl_page_header_print); void cl_page_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_page *pg) { - struct cl_page *scan; - - for (scan = cl_page_top((struct cl_page *)pg); scan; - scan = scan->cp_child) - cl_page_header_print(env, cookie, printer, scan); + cl_page_header_print(env, cookie, printer, pg); CL_PAGE_INVOKE(env, (struct cl_page *)pg, CL_PAGE_OP(cpo_print), (const struct lu_env *env, const struct cl_page_slice *slice, diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 6c205f9cad9f..db56081330e9 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -81,7 +81,6 @@ struct echo_object_conf { struct echo_page { struct cl_page_slice ep_cl; struct mutex ep_lock; - struct page *ep_vmpage; }; struct echo_lock { @@ -219,12 +218,6 @@ static struct lu_kmem_descr echo_caches[] = { * * @{ */ -static struct page *echo_page_vmpage(const struct lu_env *env, - const struct cl_page_slice *slice) -{ - return cl2echo_page(slice)->ep_vmpage; -} - static int echo_page_own(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *io, int nonblock) @@ -273,12 +266,10 @@ static void echo_page_completion(const struct lu_env *env, static void echo_page_fini(const struct lu_env *env, struct cl_page_slice *slice) { - struct echo_page *ep = cl2echo_page(slice); struct echo_object *eco = cl2echo_obj(slice->cpl_obj); - struct page *vmpage = ep->ep_vmpage; atomic_dec(&eco->eo_npages); - page_cache_release(vmpage); + page_cache_release(slice->cpl_page->cp_vmpage); } static int echo_page_prep(const struct lu_env *env, @@ -295,7 +286,8 @@ static int echo_page_print(const struct lu_env *env, struct echo_page *ep = cl2echo_page(slice); (*printer)(env, cookie, LUSTRE_ECHO_CLIENT_NAME"-page@%p %d vm@%p\n", - ep, mutex_is_locked(&ep->ep_lock), ep->ep_vmpage); + ep, mutex_is_locked(&ep->ep_lock), + slice->cpl_page->cp_vmpage); return 0; } @@ -303,7 +295,6 @@ static const struct cl_page_operations echo_page_ops = { .cpo_own = echo_page_own, .cpo_disown = echo_page_disown, .cpo_discard = echo_page_discard, - .cpo_vmpage = echo_page_vmpage, .cpo_fini = echo_page_fini, .cpo_print = echo_page_print, .cpo_is_vmlocked = echo_page_is_vmlocked, @@ -367,13 +358,12 @@ static struct cl_lock_operations echo_lock_ops = { * @{ */ static int echo_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage) + struct cl_page *page, pgoff_t index) { struct echo_page *ep = cl_object_page_slice(obj, page); struct echo_object *eco = cl2echo_obj(obj); - ep->ep_vmpage = vmpage; - page_cache_get(vmpage); + page_cache_get(page->cp_vmpage); mutex_init(&ep->ep_lock); cl_page_slice_add(page, &ep->ep_cl, obj, &echo_page_ops); atomic_inc(&eco->eo_npages); @@ -568,6 +558,8 @@ static struct lu_object *echo_object_alloc(const struct lu_env *env, obj = &echo_obj2cl(eco)->co_lu; cl_object_header_init(hdr); + hdr->coh_page_bufsize = cfs_size_round(sizeof(struct cl_page)); + lu_object_init(obj, &hdr->coh_lu, dev); lu_object_add_top(&hdr->coh_lu, obj); diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 3be4b1f11767..7460793324d6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -276,7 +276,7 @@ static int osc_extent_sanity_check0(struct osc_extent *ext, page_count = 0; list_for_each_entry(oap, &ext->oe_pages, oap_pending_item) { - pgoff_t index = oap2cl_page(oap)->cp_index; + pgoff_t index = osc_index(oap2osc(oap)); ++page_count; if (index > ext->oe_end || index < ext->oe_start) { rc = 110; @@ -991,19 +991,19 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index, /* discard all pages with index greater then trunc_index */ list_for_each_entry_safe(oap, tmp, &ext->oe_pages, oap_pending_item) { - struct cl_page *sub = oap2cl_page(oap); - struct cl_page *page = cl_page_top(sub); + pgoff_t index = osc_index(oap2osc(oap)); + struct cl_page *page = oap2cl_page(oap); LASSERT(list_empty(&oap->oap_rpc_item)); /* only discard the pages with their index greater than * trunc_index, and ... */ - if (sub->cp_index < trunc_index || - (sub->cp_index == trunc_index && partial)) { + if (index < trunc_index || + (index == trunc_index && partial)) { /* accounting how many pages remaining in the chunk * so that we can calculate grants correctly. */ - if (sub->cp_index >> ppc_bits == trunc_chunk) + if (index >> ppc_bits == trunc_chunk) ++pages_in_chunk; continue; } @@ -1256,7 +1256,7 @@ static int osc_make_ready(const struct lu_env *env, struct osc_async_page *oap, int cmd) { struct osc_page *opg = oap2osc_page(oap); - struct cl_page *page = cl_page_top(oap2cl_page(oap)); + struct cl_page *page = oap2cl_page(oap); int result; LASSERT(cmd == OBD_BRW_WRITE); /* no cached reads */ @@ -1271,7 +1271,7 @@ static int osc_refresh_count(const struct lu_env *env, struct osc_async_page *oap, int cmd) { struct osc_page *opg = oap2osc_page(oap); - struct cl_page *page = oap2cl_page(oap); + pgoff_t index = osc_index(oap2osc(oap)); struct cl_object *obj; struct cl_attr *attr = &osc_env_info(env)->oti_attr; @@ -1288,10 +1288,10 @@ static int osc_refresh_count(const struct lu_env *env, if (result < 0) return result; kms = attr->cat_kms; - if (cl_offset(obj, page->cp_index) >= kms) + if (cl_offset(obj, index) >= kms) /* catch race with truncate */ return 0; - else if (cl_offset(obj, page->cp_index + 1) > kms) + else if (cl_offset(obj, index + 1) > kms) /* catch sub-page write at end of file */ return kms % PAGE_CACHE_SIZE; else @@ -1302,7 +1302,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, int cmd, int rc) { struct osc_page *opg = oap2osc_page(oap); - struct cl_page *page = cl_page_top(oap2cl_page(oap)); + struct cl_page *page = oap2cl_page(oap); struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj); enum cl_req_type crt; int srvlock; @@ -2313,7 +2313,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, OSC_IO_DEBUG(osc, "oap %p page %p added for cmd %d\n", oap, oap->oap_page, oap->oap_cmd & OBD_BRW_RWMASK); - index = oap2cl_page(oap)->cp_index; + index = osc_index(oap2osc(oap)); /* Add this page into extent by the following steps: * 1. if there exists an active extent for this IO, mostly this page @@ -2425,21 +2425,21 @@ int osc_teardown_async_page(const struct lu_env *env, LASSERT(oap->oap_magic == OAP_MAGIC); CDEBUG(D_INFO, "teardown oap %p page %p at index %lu.\n", - oap, ops, oap2cl_page(oap)->cp_index); + oap, ops, osc_index(oap2osc(oap))); osc_object_lock(obj); if (!list_empty(&oap->oap_rpc_item)) { CDEBUG(D_CACHE, "oap %p is not in cache.\n", oap); rc = -EBUSY; } else if (!list_empty(&oap->oap_pending_item)) { - ext = osc_extent_lookup(obj, oap2cl_page(oap)->cp_index); + ext = osc_extent_lookup(obj, osc_index(oap2osc(oap))); /* only truncated pages are allowed to be taken out. * See osc_extent_truncate() and osc_cache_truncate_start() * for details. */ if (ext && ext->oe_state != OES_TRUNC) { OSC_EXTENT_DUMP(D_ERROR, ext, "trunc at %lu.\n", - oap2cl_page(oap)->cp_index); + osc_index(oap2osc(oap))); rc = -EBUSY; } } @@ -2462,7 +2462,7 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, struct osc_extent *ext = NULL; struct osc_object *obj = cl2osc(ops->ops_cl.cpl_obj); struct cl_page *cp = ops->ops_cl.cpl_page; - pgoff_t index = cp->cp_index; + pgoff_t index = osc_index(ops); struct osc_async_page *oap = &ops->ops_oap; bool unplug = false; int rc = 0; @@ -2477,8 +2477,7 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, switch (ext->oe_state) { case OES_RPC: case OES_LOCK_DONE: - CL_PAGE_DEBUG(D_ERROR, env, cl_page_top(cp), - "flush an in-rpc page?\n"); + CL_PAGE_DEBUG(D_ERROR, env, cp, "flush an in-rpc page?\n"); LASSERT(0); break; case OES_LOCKING: @@ -2504,7 +2503,7 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, break; } - rc = cl_page_prep(env, io, cl_page_top(cp), CRT_WRITE); + rc = cl_page_prep(env, io, cp, CRT_WRITE); if (rc) goto out; @@ -2548,7 +2547,7 @@ int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops) struct osc_extent *ext; struct osc_extent *found = NULL; struct list_head *plist; - pgoff_t index = oap2cl_page(oap)->cp_index; + pgoff_t index = osc_index(ops); int rc = -EBUSY; int cmd; @@ -2611,12 +2610,12 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, pgoff_t end = 0; list_for_each_entry(oap, list, oap_pending_item) { - struct cl_page *cp = oap2cl_page(oap); + pgoff_t index = osc_index(oap2osc(oap)); - if (cp->cp_index > end) - end = cp->cp_index; - if (cp->cp_index < start) - start = cp->cp_index; + if (index > end) + end = index; + if (index < start) + start = index; ++page_count; mppr <<= (page_count > mppr); } @@ -3033,7 +3032,7 @@ int osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io, break; } - page = cl_page_top(ops->ops_cl.cpl_page); + page = ops->ops_cl.cpl_page; LASSERT(page->cp_type == CPT_CACHEABLE); if (page->cp_state == CPS_FREEING) continue; @@ -3061,7 +3060,7 @@ int osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io, if (res == CLP_GANG_OKAY) res = (*cb)(env, io, ops, cbdata); - page = cl_page_top(ops->ops_cl.cpl_page); + page = ops->ops_cl.cpl_page; lu_ref_del(&page->cp_reference, "gang_lookup", current); cl_page_put(env, page); } @@ -3094,7 +3093,7 @@ static int check_and_discard_cb(const struct lu_env *env, struct cl_io *io, index = osc_index(ops); if (index >= info->oti_fn_index) { struct cl_lock *tmp; - struct cl_page *page = cl_page_top(ops->ops_cl.cpl_page); + struct cl_page *page = ops->ops_cl.cpl_page; /* refresh non-overlapped index */ tmp = cl_lock_at_pgoff(env, lock->cll_descr.cld_obj, index, @@ -3127,7 +3126,7 @@ static int discard_cb(const struct lu_env *env, struct cl_io *io, { struct osc_thread_info *info = osc_env_info(env); struct cl_lock *lock = cbdata; - struct cl_page *page = cl_page_top(ops->ops_cl.cpl_page); + struct cl_page *page = ops->ops_cl.cpl_page; LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE); @@ -3135,7 +3134,7 @@ static int discard_cb(const struct lu_env *env, struct cl_io *io, info->oti_next_index = osc_index(ops) + 1; if (cl_page_own(env, io, page) == 0) { KLASSERT(ergo(page->cp_type == CPT_CACHEABLE, - !PageDirty(cl_page_vmpage(env, page)))); + !PageDirty(cl_page_vmpage(page)))); /* discard the page */ cl_page_discard(env, io, page); diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index cf87043ce4b8..89552d73c497 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -416,7 +416,7 @@ struct lu_object *osc_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); int osc_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage); + struct cl_page *page, pgoff_t ind); void osc_index2policy (ldlm_policy_data_t *policy, const struct cl_object *obj, pgoff_t start, pgoff_t end); @@ -553,6 +553,11 @@ static inline struct osc_page *oap2osc(struct osc_async_page *oap) return container_of0(oap, struct osc_page, ops_oap); } +static inline pgoff_t osc_index(struct osc_page *opg) +{ + return opg->ops_cl.cpl_index; +} + static inline struct cl_page *oap2cl_page(struct osc_async_page *oap) { return oap2osc(oap)->ops_cl.cpl_page; @@ -563,11 +568,6 @@ static inline struct osc_page *oap2osc_page(struct osc_async_page *oap) return (struct osc_page *)container_of(oap, struct osc_page, ops_oap); } -static inline pgoff_t osc_index(struct osc_page *opg) -{ - return opg->ops_cl.cpl_page->cp_index; -} - static inline struct osc_lock *cl2osc_lock(const struct cl_lock_slice *slice) { LINVRNT(osc_is_object(&slice->cls_obj->co_lu)); diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index e9e18a1085e2..1ae8a227ad3d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -68,11 +68,15 @@ static struct osc_io *cl2osc_io(const struct lu_env *env, return oio; } -static struct osc_page *osc_cl_page_osc(struct cl_page *page) +static struct osc_page *osc_cl_page_osc(struct cl_page *page, + struct osc_object *osc) { const struct cl_page_slice *slice; - slice = cl_page_at(page, &osc_device_type); + if (osc) + slice = cl_object_page_slice(&osc->oo_cl, page); + else + slice = cl_page_at(page, &osc_device_type); LASSERT(slice); return cl2osc_page(slice); @@ -137,7 +141,7 @@ static int osc_io_submit(const struct lu_env *env, io = page->cp_owner; LASSERT(io); - opg = osc_cl_page_osc(page); + opg = osc_cl_page_osc(page, osc); oap = &opg->ops_oap; LASSERT(osc == oap->oap_obj); @@ -258,15 +262,11 @@ static int osc_io_commit_async(const struct lu_env *env, } } - /* - * NOTE: here @page is a top-level page. This is done to avoid - * creation of sub-page-list. - */ while (qin->pl_nr > 0) { struct osc_async_page *oap; page = cl_page_list_first(qin); - opg = osc_cl_page_osc(page); + opg = osc_cl_page_osc(page, osc); oap = &opg->ops_oap; if (!list_empty(&oap->oap_rpc_item)) { @@ -283,8 +283,7 @@ static int osc_io_commit_async(const struct lu_env *env, break; } - osc_page_touch_at(env, osc2cl(osc), - opg->ops_cl.cpl_page->cp_index, + osc_page_touch_at(env, osc2cl(osc), osc_index(opg), page == last_page ? to : PAGE_SIZE); cl_page_list_del(env, qin, page); @@ -403,14 +402,9 @@ static int trunc_check_cb(const struct lu_env *env, struct cl_io *io, CL_PAGE_DEBUG(D_ERROR, env, page, "exists %llu/%s.\n", start, current->comm); - { - struct page *vmpage = cl_page_vmpage(env, page); - - if (PageLocked(vmpage)) - CDEBUG(D_CACHE, "page %p index %lu locked for %d.\n", - ops, page->cp_index, - (oap->oap_cmd & OBD_BRW_RWMASK)); - } + if (PageLocked(page->cp_vmpage)) + CDEBUG(D_CACHE, "page %p index %lu locked for %d.\n", + ops, osc_index(ops), oap->oap_cmd & OBD_BRW_RWMASK); return CLP_GANG_OKAY; } @@ -788,18 +782,21 @@ static void osc_req_attr_set(const struct lu_env *env, oa->o_valid |= OBD_MD_FLID; } if (flags & OBD_MD_FLHANDLE) { + struct cl_object *subobj; + clerq = slice->crs_req; LASSERT(!list_empty(&clerq->crq_pages)); apage = container_of(clerq->crq_pages.next, struct cl_page, cp_flight); - opg = osc_cl_page_osc(apage); - apage = opg->ops_cl.cpl_page; /* now apage is a sub-page */ - lock = cl_lock_at_page(env, apage->cp_obj, apage, NULL, 1, 1); + opg = osc_cl_page_osc(apage, NULL); + subobj = opg->ops_cl.cpl_obj; + lock = cl_lock_at_pgoff(env, subobj, osc_index(opg), + NULL, 1, 1); if (!lock) { struct cl_object_header *head; struct cl_lock *scan; - head = cl_object_header(apage->cp_obj); + head = cl_object_header(subobj); list_for_each_entry(scan, &head->coh_locks, cll_linkage) CL_LOCK_DEBUG(D_ERROR, env, scan, "no cover page!\n"); diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 8dc62fa04300..3e0a8c3f4844 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -64,14 +64,9 @@ static int osc_page_protected(const struct lu_env *env, * Page operations. * */ -static void osc_page_fini(const struct lu_env *env, - struct cl_page_slice *slice) -{ -} - static void osc_page_transfer_get(struct osc_page *opg, const char *label) { - struct cl_page *page = cl_page_top(opg->ops_cl.cpl_page); + struct cl_page *page = opg->ops_cl.cpl_page; LASSERT(!opg->ops_transfer_pinned); cl_page_get(page); @@ -82,7 +77,7 @@ static void osc_page_transfer_get(struct osc_page *opg, const char *label) static void osc_page_transfer_put(const struct lu_env *env, struct osc_page *opg) { - struct cl_page *page = cl_page_top(opg->ops_cl.cpl_page); + struct cl_page *page = opg->ops_cl.cpl_page; if (opg->ops_transfer_pinned) { opg->ops_transfer_pinned = 0; @@ -139,11 +134,12 @@ static int osc_page_is_under_lock(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { + struct osc_page *opg = cl2osc_page(slice); struct cl_lock *lock; int result = -ENODATA; - lock = cl_lock_at_page(env, slice->cpl_obj, slice->cpl_page, - NULL, 1, 0); + lock = cl_lock_at_pgoff(env, slice->cpl_obj, osc_index(opg), + NULL, 1, 0); if (lock) { cl_lock_put(env, lock); result = -EBUSY; @@ -173,8 +169,8 @@ static int osc_page_print(const struct lu_env *env, struct osc_object *obj = cl2osc(slice->cpl_obj); struct client_obd *cli = &osc_export(obj)->exp_obd->u.cli; - return (*printer)(env, cookie, LUSTRE_OSC_NAME "-page@%p: 1< %#x %d %u %s %s > 2< %llu %u %u %#x %#x | %p %p %p > 3< %s %p %d %lu %d > 4< %d %d %d %lu %s | %s %s %s %s > 5< %s %s %s %s | %d %s | %d %s %s>\n", - opg, + return (*printer)(env, cookie, LUSTRE_OSC_NAME "-page@%p %lu: 1< %#x %d %u %s %s > 2< %llu %u %u %#x %#x | %p %p %p > 3< %s %p %d %lu %d > 4< %d %d %d %lu %s | %s %s %s %s > 5< %s %s %s %s | %d %s | %d %s %s>\n", + opg, osc_index(opg), /* 1 */ oap->oap_magic, oap->oap_cmd, oap->oap_interrupted, @@ -222,7 +218,7 @@ static void osc_page_delete(const struct lu_env *env, osc_page_transfer_put(env, opg); rc = osc_teardown_async_page(env, obj, opg); if (rc) { - CL_PAGE_DEBUG(D_ERROR, env, cl_page_top(slice->cpl_page), + CL_PAGE_DEBUG(D_ERROR, env, slice->cpl_page, "Trying to teardown failed: %d\n", rc); LASSERT(0); } @@ -295,7 +291,6 @@ static int osc_page_flush(const struct lu_env *env, } static const struct cl_page_operations osc_page_ops = { - .cpo_fini = osc_page_fini, .cpo_print = osc_page_print, .cpo_delete = osc_page_delete, .cpo_is_under_lock = osc_page_is_under_lock, @@ -305,7 +300,7 @@ static const struct cl_page_operations osc_page_ops = { }; int osc_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, struct page *vmpage) + struct cl_page *page, pgoff_t index) { struct osc_object *osc = cl2osc(obj); struct osc_page *opg = cl_object_page_slice(obj, page); @@ -313,9 +308,10 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj, opg->ops_from = 0; opg->ops_to = PAGE_CACHE_SIZE; + opg->ops_cl.cpl_index = index; - result = osc_prep_async_page(osc, opg, vmpage, - cl_offset(obj, page->cp_index)); + result = osc_prep_async_page(osc, opg, page->cp_vmpage, + cl_offset(obj, index)); if (result == 0) { struct osc_io *oio = osc_env_io(env); @@ -337,8 +333,7 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj, result = osc_lru_reserve(env, osc, opg); if (result == 0) { spin_lock(&osc->oo_tree_lock); - result = radix_tree_insert(&osc->oo_tree, - page->cp_index, opg); + result = radix_tree_insert(&osc->oo_tree, index, opg); if (result == 0) ++osc->oo_npages; spin_unlock(&osc->oo_tree_lock); @@ -584,7 +579,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, if (--maxscan < 0) break; - page = cl_page_top(opg->ops_cl.cpl_page); + page = opg->ops_cl.cpl_page; if (cl_page_in_use_noref(page)) { list_move_tail(&opg->ops_lru, &cli->cl_lru_list); continue; -- GitLab From fd7444fecaa0c4516d68fdbedf570b8bded60bc1 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:33 -0400 Subject: [PATCH 0862/9938] staging/lustre/clio: optimize read ahead code It used to check each page in the readahead window is covered by a lock underneath, now cpo_page_is_under_lock() provides @max_index to help decide the maximum ra window. @max_index can be modified by OSC to extend the maximum lock region, to align stripe boundary at LOV, and to make sure the readahead region at least covers read region at LLITE layer. After this is done, usually readahead code calls cpo_page_is_under_lock() for each stripe. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/8523 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321 Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 6 +- .../staging/lustre/lustre/include/lclient.h | 2 - .../staging/lustre/lustre/llite/lcommon_cl.c | 28 ----- .../lustre/lustre/llite/llite_internal.h | 7 +- .../staging/lustre/lustre/llite/lproc_llite.c | 1 + drivers/staging/lustre/lustre/llite/rw.c | 103 ++++++++++++------ drivers/staging/lustre/lustre/llite/vvp_io.c | 23 +--- .../staging/lustre/lustre/llite/vvp_page.c | 26 ++++- .../lustre/lustre/lov/lov_cl_internal.h | 1 + .../staging/lustre/lustre/lov/lov_internal.h | 2 + drivers/staging/lustre/lustre/lov/lov_io.c | 2 +- .../staging/lustre/lustre/lov/lov_offset.c | 13 +++ drivers/staging/lustre/lustre/lov/lov_page.c | 60 ++++++++-- .../staging/lustre/lustre/lov/lovsub_page.c | 4 +- .../staging/lustre/lustre/obdclass/cl_io.c | 2 +- .../staging/lustre/lustre/obdclass/cl_page.c | 39 +++++-- .../lustre/lustre/obdecho/echo_client.c | 2 +- drivers/staging/lustre/lustre/osc/osc_page.c | 10 +- 18 files changed, 208 insertions(+), 123 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 5b65854834f5..69b40f50df70 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -935,7 +935,7 @@ struct cl_page_operations { */ int (*cpo_is_under_lock)(const struct lu_env *env, const struct cl_page_slice *slice, - struct cl_io *io); + struct cl_io *io, pgoff_t *max); /** * Optional debugging helper. Prints given page slice. @@ -2674,7 +2674,7 @@ static inline void cl_device_fini(struct cl_device *d) } void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice, - struct cl_object *obj, + struct cl_object *obj, pgoff_t index, const struct cl_page_operations *ops); void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice, struct cl_object *obj, @@ -2826,7 +2826,7 @@ void cl_page_delete(const struct lu_env *env, struct cl_page *pg); int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg); void cl_page_export(const struct lu_env *env, struct cl_page *pg, int uptodate); int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, - struct cl_page *page); + struct cl_page *page, pgoff_t *max_index); loff_t cl_offset(const struct cl_object *obj, pgoff_t idx); pgoff_t cl_index(const struct cl_object *obj, loff_t offset); int cl_page_size(const struct cl_object *obj); diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index c91fb0151a52..a8c8788ebc07 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -299,8 +299,6 @@ int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, const struct cl_lock_operations *lkops); int ccc_object_glimpse(const struct lu_env *env, const struct cl_object *obj, struct ost_lvb *lvb); -int ccc_page_is_under_lock(const struct lu_env *env, - const struct cl_page_slice *slice, struct cl_io *io); int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice); int ccc_transient_page_prep(const struct lu_env *env, const struct cl_page_slice *slice, diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 55fa0da80b81..e34d8323944d 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -452,34 +452,6 @@ static void ccc_object_size_unlock(struct cl_object *obj) * */ -int ccc_page_is_under_lock(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io) -{ - struct ccc_io *cio = ccc_env_io(env); - struct cl_lock_descr *desc = &ccc_env_info(env)->cti_descr; - struct cl_page *page = slice->cpl_page; - - int result; - - if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE || - io->ci_type == CIT_FAULT) { - if (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED) { - result = -EBUSY; - } else { - desc->cld_start = ccc_index(cl2ccc_page(slice)); - desc->cld_end = ccc_index(cl2ccc_page(slice)); - desc->cld_obj = page->cp_obj; - desc->cld_mode = CLM_READ; - result = cl_queue_match(&io->ci_lockset.cls_done, - desc) ? -EBUSY : 0; - } - } else { - result = 0; - } - return result; -} - int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice) { /* diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index bc831472b3ed..cd691734f242 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -328,6 +328,7 @@ enum ra_stat { RA_STAT_EOF, RA_STAT_MAX_IN_FLIGHT, RA_STAT_WRONG_GRAB_PAGE, + RA_STAT_FAILED_REACH_END, _NR_RA_STAT, }; @@ -702,8 +703,8 @@ int ll_writepages(struct address_space *, struct writeback_control *wbc); int ll_readpage(struct file *file, struct page *page); void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras); int ll_readahead(const struct lu_env *env, struct cl_io *io, - struct ll_readahead_state *ras, struct address_space *mapping, - struct cl_page_list *queue, int flags); + struct cl_page_list *queue, struct ll_readahead_state *ras, + bool hit); int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io); struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage); void ll_cl_fini(struct ll_cl_context *lcc); @@ -1074,7 +1075,7 @@ void ras_update(struct ll_sb_info *sbi, struct inode *inode, struct ll_readahead_state *ras, unsigned long index, unsigned hit); void ll_ra_count_put(struct ll_sb_info *sbi, unsigned long len); -void ll_ra_stats_inc(struct address_space *mapping, enum ra_stat which); +void ll_ra_stats_inc(struct inode *inode, enum ra_stat which); /* llite/llite_rmtacl.c */ #ifdef CONFIG_FS_POSIX_ACL diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 9e8e61a730b7..091144fa97dd 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -960,6 +960,7 @@ static const char *ra_stat_string[] = { [RA_STAT_EOF] = "read-ahead to EOF", [RA_STAT_MAX_IN_FLIGHT] = "hit max r-a issue", [RA_STAT_WRONG_GRAB_PAGE] = "wrong page from grab_cache_page", + [RA_STAT_FAILED_REACH_END] = "failed to reach end" }; int ldebugfs_register_mountpoint(struct dentry *parent, diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index b1375f1719e7..ad15058c2ddb 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -166,7 +166,7 @@ static void ll_ra_stats_inc_sbi(struct ll_sb_info *sbi, enum ra_stat which); */ static unsigned long ll_ra_count_get(struct ll_sb_info *sbi, struct ra_io_arg *ria, - unsigned long pages) + unsigned long pages, unsigned long min) { struct ll_ra_info *ra = &sbi->ll_ra_info; long ret; @@ -206,6 +206,11 @@ static unsigned long ll_ra_count_get(struct ll_sb_info *sbi, } out: + if (ret < min) { + /* override ra limit for maximum performance */ + atomic_add(min - ret, &ra->ra_cur_pages); + ret = min; + } return ret; } @@ -222,9 +227,9 @@ static void ll_ra_stats_inc_sbi(struct ll_sb_info *sbi, enum ra_stat which) lprocfs_counter_incr(sbi->ll_ra_stats, which); } -void ll_ra_stats_inc(struct address_space *mapping, enum ra_stat which) +void ll_ra_stats_inc(struct inode *inode, enum ra_stat which) { - struct ll_sb_info *sbi = ll_i2sbi(mapping->host); + struct ll_sb_info *sbi = ll_i2sbi(inode); ll_ra_stats_inc_sbi(sbi, which); } @@ -290,7 +295,7 @@ void ll_ra_read_ex(struct file *f, struct ll_ra_read *rar) static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, struct cl_page *page, - struct cl_object *clob) + struct cl_object *clob, pgoff_t *max_index) { struct page *vmpage = page->cp_vmpage; struct ccc_page *cp; @@ -301,8 +306,11 @@ static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, lu_ref_add(&page->cp_reference, "ra", current); cp = cl2ccc_page(cl_object_page_slice(clob, page)); if (!cp->cpg_defer_uptodate && !PageUptodate(vmpage)) { - rc = cl_page_is_under_lock(env, io, page); - if (rc == -EBUSY) { + CDEBUG(D_READA, "page index %lu, max_index: %lu\n", + ccc_index(cp), *max_index); + if (*max_index == 0 || ccc_index(cp) > *max_index) + rc = cl_page_is_under_lock(env, io, page, max_index); + if (rc == 0) { cp->cpg_defer_uptodate = 1; cp->cpg_ra_used = 0; cl_page_list_add(queue, page); @@ -332,24 +340,25 @@ static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, */ static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, - pgoff_t index, struct address_space *mapping) + pgoff_t index, pgoff_t *max_index) { + struct cl_object *clob = io->ci_obj; + struct inode *inode = ccc_object_inode(clob); struct page *vmpage; - struct cl_object *clob = ll_i2info(mapping->host)->lli_clob; struct cl_page *page; enum ra_stat which = _NR_RA_STAT; /* keep gcc happy */ int rc = 0; const char *msg = NULL; - vmpage = grab_cache_page_nowait(mapping, index); + vmpage = grab_cache_page_nowait(inode->i_mapping, index); if (vmpage) { /* Check if vmpage was truncated or reclaimed */ - if (vmpage->mapping == mapping) { + if (vmpage->mapping == inode->i_mapping) { page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE); if (!IS_ERR(page)) { rc = cl_read_ahead_page(env, io, queue, - page, clob); + page, clob, max_index); if (rc == -ENOLCK) { which = RA_STAT_FAILED_MATCH; msg = "lock match failed"; @@ -370,7 +379,7 @@ static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io, msg = "g_c_p_n failed"; } if (msg) { - ll_ra_stats_inc(mapping, which); + ll_ra_stats_inc(inode, which); CDEBUG(D_READA, "%s\n", msg); } return rc; @@ -482,11 +491,12 @@ static int ll_read_ahead_pages(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, struct ra_io_arg *ria, unsigned long *reserved_pages, - struct address_space *mapping, unsigned long *ra_end) { - int rc, count = 0, stride_ria; - unsigned long page_idx; + int rc, count = 0; + bool stride_ria; + pgoff_t page_idx; + pgoff_t max_index = 0; LASSERT(ria); RIA_DEBUG(ria); @@ -497,7 +507,7 @@ static int ll_read_ahead_pages(const struct lu_env *env, if (ras_inside_ra_window(page_idx, ria)) { /* If the page is inside the read-ahead window*/ rc = ll_read_ahead_page(env, io, queue, - page_idx, mapping); + page_idx, &max_index); if (rc == 1) { (*reserved_pages)--; count++; @@ -532,25 +542,23 @@ static int ll_read_ahead_pages(const struct lu_env *env, } int ll_readahead(const struct lu_env *env, struct cl_io *io, - struct ll_readahead_state *ras, struct address_space *mapping, - struct cl_page_list *queue, int flags) + struct cl_page_list *queue, struct ll_readahead_state *ras, + bool hit) { struct vvp_io *vio = vvp_env_io(env); struct vvp_thread_info *vti = vvp_env_info(env); struct cl_attr *attr = ccc_env_thread_attr(env); unsigned long start = 0, end = 0, reserved; - unsigned long ra_end, len; + unsigned long ra_end, len, mlen = 0; struct inode *inode; struct ll_ra_read *bead; struct ra_io_arg *ria = &vti->vti_ria; - struct ll_inode_info *lli; struct cl_object *clob; int ret = 0; __u64 kms; - inode = mapping->host; - lli = ll_i2info(inode); - clob = lli->lli_clob; + clob = io->ci_obj; + inode = ccc_object_inode(clob); memset(ria, 0, sizeof(*ria)); @@ -562,7 +570,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, return ret; kms = attr->cat_kms; if (kms == 0) { - ll_ra_stats_inc(mapping, RA_STAT_ZERO_LEN); + ll_ra_stats_inc(inode, RA_STAT_ZERO_LEN); return 0; } @@ -621,29 +629,48 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, spin_unlock(&ras->ras_lock); if (end == 0) { - ll_ra_stats_inc(mapping, RA_STAT_ZERO_WINDOW); + ll_ra_stats_inc(inode, RA_STAT_ZERO_WINDOW); return 0; } len = ria_page_count(ria); - if (len == 0) + if (len == 0) { + ll_ra_stats_inc(inode, RA_STAT_ZERO_WINDOW); return 0; + } + + CDEBUG(D_READA, DFID ": ria: %lu/%lu, bead: %lu/%lu, hit: %d\n", + PFID(lu_object_fid(&clob->co_lu)), + ria->ria_start, ria->ria_end, + !bead ? 0 : bead->lrr_start, + !bead ? 0 : bead->lrr_count, + hit); + + /* at least to extend the readahead window to cover current read */ + if (!hit && bead && + bead->lrr_start + bead->lrr_count > ria->ria_start) { + /* to the end of current read window. */ + mlen = bead->lrr_start + bead->lrr_count - ria->ria_start; + /* trim to RPC boundary */ + start = ria->ria_start & (PTLRPC_MAX_BRW_PAGES - 1); + mlen = min(mlen, PTLRPC_MAX_BRW_PAGES - start); + } - reserved = ll_ra_count_get(ll_i2sbi(inode), ria, len); + reserved = ll_ra_count_get(ll_i2sbi(inode), ria, len, mlen); if (reserved < len) - ll_ra_stats_inc(mapping, RA_STAT_MAX_IN_FLIGHT); + ll_ra_stats_inc(inode, RA_STAT_MAX_IN_FLIGHT); - CDEBUG(D_READA, "reserved page %lu ra_cur %d ra_max %lu\n", reserved, + CDEBUG(D_READA, "reserved pages %lu/%lu/%lu, ra_cur %d, ra_max %lu\n", + reserved, len, mlen, atomic_read(&ll_i2sbi(inode)->ll_ra_info.ra_cur_pages), ll_i2sbi(inode)->ll_ra_info.ra_max_pages); - ret = ll_read_ahead_pages(env, io, queue, - ria, &reserved, mapping, &ra_end); + ret = ll_read_ahead_pages(env, io, queue, ria, &reserved, &ra_end); if (reserved != 0) ll_ra_count_put(ll_i2sbi(inode), reserved); if (ra_end == end + 1 && ra_end == (kms >> PAGE_CACHE_SHIFT)) - ll_ra_stats_inc(mapping, RA_STAT_EOF); + ll_ra_stats_inc(inode, RA_STAT_EOF); /* if we didn't get to the end of the region we reserved from * the ras we need to go back and update the ras so that the @@ -655,6 +682,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, ra_end, end, ria->ria_end); if (ra_end != end + 1) { + ll_ra_stats_inc(inode, RA_STAT_FAILED_REACH_END); spin_lock(&ras->ras_lock); if (ra_end < ras->ras_next_readahead && index_in_window(ra_end, ras->ras_window_start, 0, @@ -925,15 +953,18 @@ void ras_update(struct ll_sb_info *sbi, struct inode *inode, ras->ras_last_readpage = index; ras_set_start(inode, ras, index); - if (stride_io_mode(ras)) + if (stride_io_mode(ras)) { /* Since stride readahead is sensitive to the offset * of read-ahead, so we use original offset here, * instead of ras_window_start, which is RPC aligned */ ras->ras_next_readahead = max(index, ras->ras_next_readahead); - else - ras->ras_next_readahead = max(ras->ras_window_start, - ras->ras_next_readahead); + } else { + if (ras->ras_next_readahead < ras->ras_window_start) + ras->ras_next_readahead = ras->ras_window_start; + if (!hit) + ras->ras_next_readahead = index + 1; + } RAS_CDEBUG(ras); /* Trigger RA in the mmap case where ras_consecutive_requests diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index ac9d615b78d9..18127d3dc493 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -1052,35 +1052,19 @@ static int vvp_io_read_page(const struct lu_env *env, const struct cl_page_slice *slice) { struct cl_io *io = ios->cis_io; - struct cl_object *obj = slice->cpl_obj; struct ccc_page *cp = cl2ccc_page(slice); struct cl_page *page = slice->cpl_page; - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = ccc_object_inode(slice->cpl_obj); struct ll_sb_info *sbi = ll_i2sbi(inode); struct ll_file_data *fd = cl2ccc_io(env, ios)->cui_fd; struct ll_readahead_state *ras = &fd->fd_ras; - struct page *vmpage = cp->cpg_page; struct cl_2queue *queue = &io->ci_queue; - int rc; - - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); - LASSERT(slice->cpl_obj == obj); if (sbi->ll_ra_info.ra_max_pages_per_file && sbi->ll_ra_info.ra_max_pages) ras_update(sbi, inode, ras, ccc_index(cp), cp->cpg_defer_uptodate); - /* Sanity check whether the page is protected by a lock. */ - rc = cl_page_is_under_lock(env, io, page); - if (rc != -EBUSY) { - CL_PAGE_HEADER(D_WARNING, env, page, "%s: %d\n", - rc == -ENODATA ? "without a lock" : - "match failed", rc); - if (rc != -ENODATA) - return rc; - } - if (cp->cpg_defer_uptodate) { cp->cpg_ra_used = 1; cl_page_export(env, page, 1); @@ -1089,11 +1073,12 @@ static int vvp_io_read_page(const struct lu_env *env, * Add page into the queue even when it is marked uptodate above. * this will unlock it automatically as part of cl_page_list_disown(). */ + cl_page_list_add(&queue->c2_qin, page); if (sbi->ll_ra_info.ra_max_pages_per_file && sbi->ll_ra_info.ra_max_pages) - ll_readahead(env, io, ras, - vmpage->mapping, &queue->c2_qin, fd->fd_flags); + ll_readahead(env, io, &queue->c2_qin, ras, + cp->cpg_defer_uptodate); return 0; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index d9f13c31091a..3c6b72398d62 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -142,7 +142,7 @@ static void vvp_page_discard(const struct lu_env *env, LASSERT(PageLocked(vmpage)); if (cpg->cpg_defer_uptodate && !cpg->cpg_ra_used) - ll_ra_stats_inc(vmpage->mapping, RA_STAT_DISCARDED); + ll_ra_stats_inc(vmpage->mapping->host, RA_STAT_DISCARDED); ll_invalidate_page(vmpage); } @@ -357,6 +357,20 @@ static int vvp_page_make_ready(const struct lu_env *env, return result; } +static int vvp_page_is_under_lock(const struct lu_env *env, + const struct cl_page_slice *slice, + struct cl_io *io, pgoff_t *max_index) +{ + if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE || + io->ci_type == CIT_FAULT) { + struct ccc_io *cio = ccc_env_io(env); + + if (unlikely(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) + *max_index = CL_PAGE_EOF; + } + return 0; +} + static int vvp_page_print(const struct lu_env *env, const struct cl_page_slice *slice, void *cookie, lu_printer_t printer) @@ -389,7 +403,7 @@ static const struct cl_page_operations vvp_page_ops = { .cpo_is_vmlocked = vvp_page_is_vmlocked, .cpo_fini = vvp_page_fini, .cpo_print = vvp_page_print, - .cpo_is_under_lock = ccc_page_is_under_lock, + .cpo_is_under_lock = vvp_page_is_under_lock, .io = { [CRT_READ] = { .cpo_prep = vvp_page_prep_read, @@ -495,7 +509,7 @@ static const struct cl_page_operations vvp_transient_page_ops = { .cpo_fini = vvp_transient_page_fini, .cpo_is_vmlocked = vvp_transient_page_is_vmlocked, .cpo_print = vvp_page_print, - .cpo_is_under_lock = ccc_page_is_under_lock, + .cpo_is_under_lock = vvp_page_is_under_lock, .io = { [CRT_READ] = { .cpo_prep = ccc_transient_page_prep, @@ -516,7 +530,6 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, CLOBINVRNT(env, obj, ccc_object_invariant(obj)); - cpg->cpg_cl.cpl_index = index; cpg->cpg_page = vmpage; page_cache_get(vmpage); @@ -526,12 +539,13 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, atomic_inc(&page->cp_ref); SetPagePrivate(vmpage); vmpage->private = (unsigned long)page; - cl_page_slice_add(page, &cpg->cpg_cl, obj, &vvp_page_ops); + cl_page_slice_add(page, &cpg->cpg_cl, obj, index, + &vvp_page_ops); } else { struct ccc_object *clobj = cl2ccc(obj); LASSERT(!inode_trylock(clobj->cob_inode)); - cl_page_slice_add(page, &cpg->cpg_cl, obj, + cl_page_slice_add(page, &cpg->cpg_cl, obj, index, &vvp_transient_page_ops); clobj->cob_transient_pages++; } diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index b8e2315d5216..9b3d13bf2a46 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -632,6 +632,7 @@ struct lov_lock_link *lov_lock_link_find(const struct lu_env *env, struct lovsub_lock *sub); struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio, const struct cl_page_slice *slice); +int lov_page_stripe(const struct cl_page *page); #define lov_foreach_target(lov, var) \ for (var = 0; var < lov_targets_nr(lov); ++var) diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 590f9326af37..9985855c4e06 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -146,6 +146,8 @@ int lov_stripe_intersects(struct lov_stripe_md *lsm, int stripeno, u64 start, u64 end, u64 *obd_start, u64 *obd_end); int lov_stripe_number(struct lov_stripe_md *lsm, u64 lov_off); +pgoff_t lov_stripe_pgoff(struct lov_stripe_md *lsm, pgoff_t stripe_index, + int stripe); /* lov_qos.c */ #define LOV_USES_ASSIGNED_STRIPE 0 diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index e5b2cfc5b662..ba79955f54bb 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -245,7 +245,7 @@ void lov_sub_put(struct lov_io_sub *sub) * */ -static int lov_page_stripe(const struct cl_page *page) +int lov_page_stripe(const struct cl_page *page) { struct lovsub_object *subobj; const struct cl_page_slice *slice; diff --git a/drivers/staging/lustre/lustre/lov/lov_offset.c b/drivers/staging/lustre/lustre/lov/lov_offset.c index ae83eb0f6f36..cb7b51617498 100644 --- a/drivers/staging/lustre/lustre/lov/lov_offset.c +++ b/drivers/staging/lustre/lustre/lov/lov_offset.c @@ -66,6 +66,19 @@ u64 lov_stripe_size(struct lov_stripe_md *lsm, u64 ost_size, int stripeno) return lov_size; } +/** + * Compute file level page index by stripe level page offset + */ +pgoff_t lov_stripe_pgoff(struct lov_stripe_md *lsm, pgoff_t stripe_index, + int stripe) +{ + loff_t offset; + + offset = lov_stripe_size(lsm, stripe_index << PAGE_CACHE_SHIFT, + stripe); + return offset >> PAGE_CACHE_SHIFT; +} + /* we have an offset in file backed by an lov and want to find out where * that offset lands in our given stripe of the file. for the easy * case where the offset is within the stripe, we just have to scale the diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index 0c508bd0f8ad..9634c13a574d 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -52,17 +52,57 @@ * Lov page operations. * */ -static int lov_page_print(const struct lu_env *env, - const struct cl_page_slice *slice, - void *cookie, lu_printer_t printer) + +/** + * Adjust the stripe index by layout of raid0. @max_index is the maximum + * page index covered by an underlying DLM lock. + * This function converts max_index from stripe level to file level, and make + * sure it's not beyond one stripe. + */ +static int lov_raid0_page_is_under_lock(const struct lu_env *env, + const struct cl_page_slice *slice, + struct cl_io *unused, + pgoff_t *max_index) +{ + struct lov_object *loo = cl2lov(slice->cpl_obj); + struct lov_layout_raid0 *r0 = lov_r0(loo); + pgoff_t index = *max_index; + unsigned int pps; /* pages per stripe */ + + CDEBUG(D_READA, "*max_index = %lu, nr = %d\n", index, r0->lo_nr); + if (index == 0) /* the page is not covered by any lock */ + return 0; + + if (r0->lo_nr == 1) /* single stripe file */ + return 0; + + /* max_index is stripe level, convert it into file level */ + if (index != CL_PAGE_EOF) { + int stripeno = lov_page_stripe(slice->cpl_page); + *max_index = lov_stripe_pgoff(loo->lo_lsm, index, stripeno); + } + + /* calculate the end of current stripe */ + pps = loo->lo_lsm->lsm_stripe_size >> PAGE_CACHE_SHIFT; + index = ((slice->cpl_index + pps) & ~(pps - 1)) - 1; + + /* never exceed the end of the stripe */ + *max_index = min_t(pgoff_t, *max_index, index); + return 0; +} + +static int lov_raid0_page_print(const struct lu_env *env, + const struct cl_page_slice *slice, + void *cookie, lu_printer_t printer) { struct lov_page *lp = cl2lov_page(slice); - return (*printer)(env, cookie, LUSTRE_LOV_NAME"-page@%p\n", lp); + return (*printer)(env, cookie, LUSTRE_LOV_NAME "-page@%p, raid0\n", lp); } -static const struct cl_page_operations lov_page_ops = { - .cpo_print = lov_page_print +static const struct cl_page_operations lov_raid0_page_ops = { + .cpo_is_under_lock = lov_raid0_page_is_under_lock, + .cpo_print = lov_raid0_page_print }; int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, @@ -86,7 +126,7 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, rc = lov_stripe_offset(loo->lo_lsm, offset, stripe, &suboff); LASSERT(rc == 0); - cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_page_ops); + cl_page_slice_add(page, &lpg->lps_cl, obj, index, &lov_raid0_page_ops); sub = lov_sub_get(env, lio, stripe); if (IS_ERR(sub)) @@ -107,7 +147,7 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, return rc; } -static int lov_page_empty_print(const struct lu_env *env, +static int lov_empty_page_print(const struct lu_env *env, const struct cl_page_slice *slice, void *cookie, lu_printer_t printer) { @@ -118,7 +158,7 @@ static int lov_page_empty_print(const struct lu_env *env, } static const struct cl_page_operations lov_empty_page_ops = { - .cpo_print = lov_page_empty_print + .cpo_print = lov_empty_page_print }; int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj, @@ -127,7 +167,7 @@ int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj, struct lov_page *lpg = cl_object_page_slice(obj, page); void *addr; - cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_empty_page_ops); + cl_page_slice_add(page, &lpg->lps_cl, obj, index, &lov_empty_page_ops); addr = kmap(page->cp_vmpage); memset(addr, 0, cl_page_size(obj)); kunmap(page->cp_vmpage); diff --git a/drivers/staging/lustre/lustre/lov/lovsub_page.c b/drivers/staging/lustre/lustre/lov/lovsub_page.c index fb4c0ccee30c..9badedcce2bf 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_page.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_page.c @@ -60,11 +60,11 @@ static const struct cl_page_operations lovsub_page_ops = { }; int lovsub_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, pgoff_t ind) + struct cl_page *page, pgoff_t index) { struct lovsub_page *lsb = cl_object_page_slice(obj, page); - cl_page_slice_add(page, &lsb->lsb_cl, obj, &lovsub_page_ops); + cl_page_slice_add(page, &lsb->lsb_cl, obj, index, &lovsub_page_ops); return 0; } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 86591ceac9c1..65d6cee5232b 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -733,7 +733,7 @@ int cl_io_read_page(const struct lu_env *env, struct cl_io *io, break; } } - if (result == 0) + if (result == 0 && queue->c2_qin.pl_nr > 0) result = cl_io_submit_rw(env, io, CRT_READ, queue); /* * Unlock unsent pages in case of error. diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index cb156739b254..506a9f94e5ba 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -401,6 +401,30 @@ EXPORT_SYMBOL(cl_page_at); __result; \ }) +#define CL_PAGE_INVOKE_REVERSE(_env, _page, _op, _proto, ...) \ +({ \ + const struct lu_env *__env = (_env); \ + struct cl_page *__page = (_page); \ + const struct cl_page_slice *__scan; \ + int __result; \ + ptrdiff_t __op = (_op); \ + int (*__method)_proto; \ + \ + __result = 0; \ + list_for_each_entry_reverse(__scan, &__page->cp_layers, \ + cpl_linkage) { \ + __method = *(void **)((char *)__scan->cpl_ops + __op); \ + if (__method) { \ + __result = (*__method)(__env, __scan, ## __VA_ARGS__); \ + if (__result != 0) \ + break; \ + } \ + } \ + if (__result > 0) \ + __result = 0; \ + __result; \ +}) + #define CL_PAGE_INVOID(_env, _page, _op, _proto, ...) \ do { \ const struct lu_env *__env = (_env); \ @@ -928,17 +952,17 @@ EXPORT_SYMBOL(cl_page_flush); * \see cl_page_operations::cpo_is_under_lock() */ int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, - struct cl_page *page) + struct cl_page *page, pgoff_t *max_index) { int rc; PINVRNT(env, page, cl_page_invariant(page)); - rc = CL_PAGE_INVOKE(env, page, CL_PAGE_OP(cpo_is_under_lock), - (const struct lu_env *, - const struct cl_page_slice *, struct cl_io *), - io); - PASSERT(env, page, rc != 0); + rc = CL_PAGE_INVOKE_REVERSE(env, page, CL_PAGE_OP(cpo_is_under_lock), + (const struct lu_env *, + const struct cl_page_slice *, + struct cl_io *, pgoff_t *), + io, max_index); return rc; } EXPORT_SYMBOL(cl_page_is_under_lock); @@ -1041,11 +1065,12 @@ EXPORT_SYMBOL(cl_page_size); * \see cl_lock_slice_add(), cl_req_slice_add(), cl_io_slice_add() */ void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice, - struct cl_object *obj, + struct cl_object *obj, pgoff_t index, const struct cl_page_operations *ops) { list_add_tail(&slice->cpl_linkage, &page->cp_layers); slice->cpl_obj = obj; + slice->cpl_index = index; slice->cpl_ops = ops; slice->cpl_page = page; } diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index db56081330e9..0d84d04c12de 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -365,7 +365,7 @@ static int echo_page_init(const struct lu_env *env, struct cl_object *obj, page_cache_get(page->cp_vmpage); mutex_init(&ep->ep_lock); - cl_page_slice_add(page, &ep->ep_cl, obj, &echo_page_ops); + cl_page_slice_add(page, &ep->ep_cl, obj, index, &echo_page_ops); atomic_inc(&eco->eo_npages); return 0; } diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 3e0a8c3f4844..e02dd33b637c 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -132,17 +132,19 @@ void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj, static int osc_page_is_under_lock(const struct lu_env *env, const struct cl_page_slice *slice, - struct cl_io *unused) + struct cl_io *unused, pgoff_t *max_index) { struct osc_page *opg = cl2osc_page(slice); struct cl_lock *lock; int result = -ENODATA; + *max_index = 0; lock = cl_lock_at_pgoff(env, slice->cpl_obj, osc_index(opg), NULL, 1, 0); if (lock) { + *max_index = lock->cll_descr.cld_end; cl_lock_put(env, lock); - result = -EBUSY; + result = 0; } return result; } @@ -308,7 +310,6 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj, opg->ops_from = 0; opg->ops_to = PAGE_CACHE_SIZE; - opg->ops_cl.cpl_index = index; result = osc_prep_async_page(osc, opg, page->cp_vmpage, cl_offset(obj, index)); @@ -316,7 +317,8 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj, struct osc_io *oio = osc_env_io(env); opg->ops_srvlock = osc_io_srvlock(oio); - cl_page_slice_add(page, &opg->ops_cl, obj, &osc_page_ops); + cl_page_slice_add(page, &opg->ops_cl, obj, index, + &osc_page_ops); } /* * Cannot assert osc_page_protected() here as read-ahead -- GitLab From d2995737bb6da9fcb9f84bf820322e351df2813b Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:34 -0400 Subject: [PATCH 0863/9938] staging/lustre/llite: remove lli_lvb In struct ll_inode_info remove the struct ost_lvb lli_lvb member and replace it with obd_time lli_{a,m,c}time. Rename ll_merge_lvb() to ll_merge_attr(). Remove cl_merge_lvb() and replace calls to it with calls to ll_merge_attr(). Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/12849 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 65 ++++++++++--------- drivers/staging/lustre/lustre/llite/glimpse.c | 6 +- .../staging/lustre/lustre/llite/lcommon_cl.c | 2 +- .../lustre/lustre/llite/llite_internal.h | 11 ++-- .../staging/lustre/lustre/llite/llite_lib.c | 6 +- drivers/staging/lustre/lustre/llite/vvp_io.c | 2 +- 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 127fff6ebe44..8fc9da00278e 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -994,50 +994,57 @@ int ll_inode_getattr(struct inode *inode, struct obdo *obdo, return rc; } -int ll_merge_lvb(const struct lu_env *env, struct inode *inode) +int ll_merge_attr(const struct lu_env *env, struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct cl_object *obj = lli->lli_clob; struct cl_attr *attr = ccc_env_thread_attr(env); - struct ost_lvb lvb; + s64 atime; + s64 mtime; + s64 ctime; int rc = 0; ll_inode_size_lock(inode); + /* merge timestamps the most recently obtained from mds with * timestamps obtained from osts */ - LTIME_S(inode->i_atime) = lli->lli_lvb.lvb_atime; - LTIME_S(inode->i_mtime) = lli->lli_lvb.lvb_mtime; - LTIME_S(inode->i_ctime) = lli->lli_lvb.lvb_ctime; + LTIME_S(inode->i_atime) = lli->lli_atime; + LTIME_S(inode->i_mtime) = lli->lli_mtime; + LTIME_S(inode->i_ctime) = lli->lli_ctime; - lvb.lvb_size = i_size_read(inode); - lvb.lvb_blocks = inode->i_blocks; - lvb.lvb_mtime = LTIME_S(inode->i_mtime); - lvb.lvb_atime = LTIME_S(inode->i_atime); - lvb.lvb_ctime = LTIME_S(inode->i_ctime); + mtime = LTIME_S(inode->i_mtime); + atime = LTIME_S(inode->i_atime); + ctime = LTIME_S(inode->i_ctime); cl_object_attr_lock(obj); rc = cl_object_attr_get(env, obj, attr); cl_object_attr_unlock(obj); - if (rc == 0) { - if (lvb.lvb_atime < attr->cat_atime) - lvb.lvb_atime = attr->cat_atime; - if (lvb.lvb_ctime < attr->cat_ctime) - lvb.lvb_ctime = attr->cat_ctime; - if (lvb.lvb_mtime < attr->cat_mtime) - lvb.lvb_mtime = attr->cat_mtime; + if (rc != 0) + goto out_size_unlock; - CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n", - PFID(&lli->lli_fid), attr->cat_size); - cl_isize_write_nolock(inode, attr->cat_size); + if (atime < attr->cat_atime) + atime = attr->cat_atime; - inode->i_blocks = attr->cat_blocks; + if (ctime < attr->cat_ctime) + ctime = attr->cat_ctime; - LTIME_S(inode->i_mtime) = lvb.lvb_mtime; - LTIME_S(inode->i_atime) = lvb.lvb_atime; - LTIME_S(inode->i_ctime) = lvb.lvb_ctime; - } + if (mtime < attr->cat_mtime) + mtime = attr->cat_mtime; + + CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n", + PFID(&lli->lli_fid), attr->cat_size); + + cl_isize_write_nolock(inode, attr->cat_size); + + inode->i_blocks = attr->cat_blocks; + + LTIME_S(inode->i_mtime) = mtime; + LTIME_S(inode->i_atime) = atime; + LTIME_S(inode->i_ctime) = ctime; + +out_size_unlock: ll_inode_size_unlock(inode); return rc; @@ -1936,7 +1943,7 @@ int ll_hsm_release(struct inode *inode) goto out; } - ll_merge_lvb(env, inode); + ll_merge_attr(env, inode); cl_env_nested_put(&nest, env); /* Release the file. @@ -3001,9 +3008,9 @@ static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits) /* if object isn't regular file, don't validate size */ if (!S_ISREG(inode->i_mode)) { - LTIME_S(inode->i_atime) = ll_i2info(inode)->lli_lvb.lvb_atime; - LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_lvb.lvb_mtime; - LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_lvb.lvb_ctime; + LTIME_S(inode->i_atime) = ll_i2info(inode)->lli_atime; + LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_mtime; + LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_ctime; } else { /* In case of restore, the MDT has the right size and has * already send it back without granting the layout lock, diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index f235f3557e2a..88bc7c9918e5 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -139,7 +139,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, LASSERT(agl == 0); result = cl_wait(env, lock); if (result == 0) { - cl_merge_lvb(env, inode); + ll_merge_attr(env, inode); if (cl_isize_read(inode) > 0 && inode->i_blocks == 0) { /* @@ -155,7 +155,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, cl_lock_release(env, lock, "glimpse", current); } else { CDEBUG(D_DLMTRACE, "No objects for inode\n"); - cl_merge_lvb(env, inode); + ll_merge_attr(env, inode); } } @@ -259,7 +259,7 @@ int cl_local_size(struct inode *inode) descr->cld_obj = clob; lock = cl_lock_peek(env, io, descr, "localsize", current); if (lock) { - cl_merge_lvb(env, inode); + ll_merge_attr(env, inode); cl_unuse(env, lock); cl_lock_release(env, lock, "localsize", current); result = 0; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index e34d8323944d..4871d0feeb1c 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -591,7 +591,7 @@ void ccc_lock_state(const struct lu_env *env, */ if (lock->cll_descr.cld_start == 0 && lock->cll_descr.cld_end == CL_PAGE_EOF) - cl_merge_lvb(env, inode); + ll_merge_attr(env, inode); } } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index cd691734f242..c1d747a1e962 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -161,7 +161,9 @@ struct ll_inode_info { struct inode lli_vfs_inode; /* the most recent timestamps obtained from mds */ - struct ost_lvb lli_lvb; + s64 lli_atime; + s64 lli_mtime; + s64 lli_ctime; spinlock_t lli_agl_lock; /* Try to make the d::member and f::member are aligned. Before using @@ -752,7 +754,7 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, int *lmm_size, struct ptlrpc_request **request); int ll_fsync(struct file *file, loff_t start, loff_t end, int data); -int ll_merge_lvb(const struct lu_env *env, struct inode *inode); +int ll_merge_attr(const struct lu_env *env, struct inode *inode); int ll_fid2path(struct inode *inode, void __user *arg); int ll_data_version(struct inode *inode, __u64 *data_version, int extent_lock); int ll_hsm_release(struct inode *inode); @@ -1319,11 +1321,6 @@ static inline void cl_isize_write(struct inode *inode, loff_t kms) #define cl_isize_read(inode) i_size_read(inode) -static inline int cl_merge_lvb(const struct lu_env *env, struct inode *inode) -{ - return ll_merge_lvb(env, inode); -} - #define cl_inode_atime(inode) LTIME_S((inode)->i_atime) #define cl_inode_ctime(inode) LTIME_S((inode)->i_ctime) #define cl_inode_mtime(inode) LTIME_S((inode)->i_mtime) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index a4401f297d1c..0b4e0dbfc130 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1551,7 +1551,7 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) if (body->valid & OBD_MD_FLATIME) { if (body->atime > LTIME_S(inode->i_atime)) LTIME_S(inode->i_atime) = body->atime; - lli->lli_lvb.lvb_atime = body->atime; + lli->lli_atime = body->atime; } if (body->valid & OBD_MD_FLMTIME) { if (body->mtime > LTIME_S(inode->i_mtime)) { @@ -1560,12 +1560,12 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) body->mtime); LTIME_S(inode->i_mtime) = body->mtime; } - lli->lli_lvb.lvb_mtime = body->mtime; + lli->lli_mtime = body->mtime; } if (body->valid & OBD_MD_FLCTIME) { if (body->ctime > LTIME_S(inode->i_ctime)) LTIME_S(inode->i_ctime) = body->ctime; - lli->lli_lvb.lvb_ctime = body->ctime; + lli->lli_ctime = body->ctime; } if (body->valid & OBD_MD_FLMODE) inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 18127d3dc493..c7db318b8ece 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -739,7 +739,7 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) } /* update inode size */ - ll_merge_lvb(env, inode); + ll_merge_attr(env, inode); /* Now the pages in queue were failed to commit, discard them * unless they were dirtied before. -- GitLab From 019e93516dcfc98efda51ccb8f7e0e758fda8ded Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:35 -0400 Subject: [PATCH 0864/9938] staging/lustre/lmv: remove lmv_init_{lock,unlock}() In struct lmv_obd rename the init_mutex member to lmv_init_mutex. Remove the compat macros lmv_init_{lock,unlock}() and use mutex_{lock,unlock}(&lmv->lmv_init_mutex) instead. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/12115 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 2 +- .../staging/lustre/lustre/lmv/lmv_internal.h | 3 --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 24 +++++++++---------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 26182ca8f518..15c514c9d0ca 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -512,7 +512,7 @@ struct lmv_obd { struct obd_uuid cluuid; struct obd_export *exp; - struct mutex init_mutex; + struct mutex lmv_init_mutex; int connected; int max_easize; int max_def_easize; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 8a0087190e23..7007e4c48035 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -42,9 +42,6 @@ #define LMV_MAX_TGT_COUNT 128 -#define lmv_init_lock(lmv) mutex_lock(&lmv->init_mutex) -#define lmv_init_unlock(lmv) mutex_unlock(&lmv->init_mutex) - #define LL_IT2STR(it) \ ((it) ? ldlm_it2str((it)->it_op) : "0") diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index e3a721670ca1..8bd2dc577bf8 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -425,7 +425,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, CDEBUG(D_CONFIG, "Target uuid: %s. index %d\n", uuidp->uuid, index); - lmv_init_lock(lmv); + mutex_lock(&lmv->lmv_init_mutex); if (lmv->desc.ld_tgt_count == 0) { struct obd_device *mdc_obd; @@ -433,7 +433,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, mdc_obd = class_find_client_obd(uuidp, LUSTRE_MDC_NAME, &obd->obd_uuid); if (!mdc_obd) { - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); CERROR("%s: Target %s not attached: rc = %d\n", obd->obd_name, uuidp->uuid, -EINVAL); return -EINVAL; @@ -445,7 +445,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, CERROR("%s: UUID %s already assigned at LOV target index %d: rc = %d\n", obd->obd_name, obd_uuid2str(&tgt->ltd_uuid), index, -EEXIST); - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); return -EEXIST; } @@ -459,7 +459,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, newsize <<= 1; newtgts = kcalloc(newsize, sizeof(*newtgts), GFP_NOFS); if (!newtgts) { - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); return -ENOMEM; } @@ -481,7 +481,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, tgt = kzalloc(sizeof(*tgt), GFP_NOFS); if (!tgt) { - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); return -ENOMEM; } @@ -507,7 +507,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, } } - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); return rc; } @@ -522,14 +522,14 @@ int lmv_check_connect(struct obd_device *obd) if (lmv->connected) return 0; - lmv_init_lock(lmv); + mutex_lock(&lmv->lmv_init_mutex); if (lmv->connected) { - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); return 0; } if (lmv->desc.ld_tgt_count == 0) { - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); CERROR("%s: no targets configured.\n", obd->obd_name); return -EINVAL; } @@ -551,7 +551,7 @@ int lmv_check_connect(struct obd_device *obd) lmv->connected = 1; easize = lmv_get_easize(lmv); lmv_init_ea_size(obd->obd_self_export, easize, 0, 0, 0); - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); return 0; out_disc: @@ -572,7 +572,7 @@ int lmv_check_connect(struct obd_device *obd) } } class_disconnect(lmv->exp); - lmv_init_unlock(lmv); + mutex_unlock(&lmv->lmv_init_mutex); return rc; } @@ -1269,7 +1269,7 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg) lmv->lmv_placement = PLACEMENT_CHAR_POLICY; spin_lock_init(&lmv->lmv_lock); - mutex_init(&lmv->init_mutex); + mutex_init(&lmv->lmv_init_mutex); lprocfs_lmv_init_vars(&lvars); -- GitLab From 7d53d8f426cacdb7352e91957721b4a9962b222a Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:36 -0400 Subject: [PATCH 0865/9938] staging/lustre/obd: remove struct client_obd_lock Remove the definition of struct client_obd_lock and the functions client_obd_list_{init,lock,unlock,done}(). Use spinlock_t for the cl_{loi,lru}_list_lock members of struct client_obd and call spin_{lock,unlock}() directly. Signed-off-by: John L. Hammond Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/fld/fld_request.c | 14 ++-- .../staging/lustre/lustre/include/linux/obd.h | 67 ------------------- drivers/staging/lustre/lustre/include/obd.h | 9 +-- drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 4 +- drivers/staging/lustre/lustre/mdc/lproc_mdc.c | 8 +-- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 18 ++--- drivers/staging/lustre/lustre/osc/lproc_osc.c | 38 +++++------ drivers/staging/lustre/lustre/osc/osc_cache.c | 50 +++++++------- .../lustre/lustre/osc/osc_cl_internal.h | 2 +- drivers/staging/lustre/lustre/osc/osc_page.c | 24 +++---- .../staging/lustre/lustre/osc/osc_request.c | 46 ++++++------- 11 files changed, 105 insertions(+), 175 deletions(-) diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index a3d122d85c8d..2dfdb51445df 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -64,9 +64,9 @@ static int fld_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) { int rc; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); rc = list_empty(&mcw->mcw_entry); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return rc; }; @@ -75,15 +75,15 @@ static void fld_enter_request(struct client_obd *cli) struct mdc_cache_waiter mcw; struct l_wait_info lwi = { 0 }; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { list_add_tail(&mcw.mcw_entry, &cli->cl_cache_waiters); init_waitqueue_head(&mcw.mcw_waitq); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); l_wait_event(mcw.mcw_waitq, fld_req_avail(cli, &mcw), &lwi); } else { cli->cl_r_in_flight++; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } } @@ -92,7 +92,7 @@ static void fld_exit_request(struct client_obd *cli) struct list_head *l, *tmp; struct mdc_cache_waiter *mcw; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_r_in_flight--; list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { @@ -106,7 +106,7 @@ static void fld_exit_request(struct client_obd *cli) cli->cl_r_in_flight++; wake_up(&mcw->mcw_waitq); } - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } static int fld_rrb_hash(struct lu_client_fld *fld, u64 seq) diff --git a/drivers/staging/lustre/lustre/include/linux/obd.h b/drivers/staging/lustre/lustre/include/linux/obd.h index 3907bf4ce07c..e1063e828229 100644 --- a/drivers/staging/lustre/lustre/include/linux/obd.h +++ b/drivers/staging/lustre/lustre/include/linux/obd.h @@ -55,71 +55,4 @@ struct ll_iattr { unsigned int ia_attr_flags; }; -#define CLIENT_OBD_LIST_LOCK_DEBUG 1 - -struct client_obd_lock { - spinlock_t lock; - - unsigned long time; - struct task_struct *task; - const char *func; - int line; -}; - -static inline void __client_obd_list_lock(struct client_obd_lock *lock, - const char *func, int line) -{ - unsigned long cur = jiffies; - - while (1) { - if (spin_trylock(&lock->lock)) { - LASSERT(!lock->task); - lock->task = current; - lock->func = func; - lock->line = line; - lock->time = jiffies; - break; - } - - if (time_before(cur + 5 * HZ, jiffies) && - time_before(lock->time + 5 * HZ, jiffies)) { - struct task_struct *task = lock->task; - - if (!task) - continue; - - LCONSOLE_WARN("%s:%d: lock %p was acquired by <%s:%d:%s:%d> for %lu seconds.\n", - current->comm, current->pid, - lock, task->comm, task->pid, - lock->func, lock->line, - (jiffies - lock->time) / HZ); - LCONSOLE_WARN("====== for current process =====\n"); - dump_stack(); - LCONSOLE_WARN("====== end =======\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1000 * HZ); - } - cpu_relax(); - } -} - -#define client_obd_list_lock(lock) \ - __client_obd_list_lock(lock, __func__, __LINE__) - -static inline void client_obd_list_unlock(struct client_obd_lock *lock) -{ - LASSERT(lock->task); - lock->task = NULL; - lock->time = jiffies; - spin_unlock(&lock->lock); -} - -static inline void client_obd_list_lock_init(struct client_obd_lock *lock) -{ - spin_lock_init(&lock->lock); -} - -static inline void client_obd_list_lock_done(struct client_obd_lock *lock) -{} - #endif /* __LINUX_OBD_H */ diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 15c514c9d0ca..84cc001e152e 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -37,6 +37,7 @@ #ifndef __OBD_H #define __OBD_H +#include #include "linux/obd.h" #define IOC_OSC_TYPE 'h' @@ -293,14 +294,10 @@ struct client_obd { * blocking everywhere, but we don't want to slow down fast-path of * our main platform.) * - * Exact type of ->cl_loi_list_lock is defined in arch/obd.h together - * with client_obd_list_{un,}lock() and - * client_obd_list_lock_{init,done}() functions. - * * NB by Jinshan: though field names are still _loi_, but actually * osc_object{}s are in the list. */ - struct client_obd_lock cl_loi_list_lock; + spinlock_t cl_loi_list_lock; struct list_head cl_loi_ready_list; struct list_head cl_loi_hp_ready_list; struct list_head cl_loi_write_list; @@ -327,7 +324,7 @@ struct client_obd { atomic_t cl_lru_shrinkers; atomic_t cl_lru_in_list; struct list_head cl_lru_list; /* lru page list */ - struct client_obd_lock cl_lru_list_lock; /* page list protector */ + spinlock_t cl_lru_list_lock; /* page list protector */ /* number of in flight destroy rpcs is limited to max_rpcs_in_flight */ atomic_t cl_destroy_in_flight; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index b586d5a88d00..b497ce4f844a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -314,7 +314,7 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) INIT_LIST_HEAD(&cli->cl_loi_hp_ready_list); INIT_LIST_HEAD(&cli->cl_loi_write_list); INIT_LIST_HEAD(&cli->cl_loi_read_list); - client_obd_list_lock_init(&cli->cl_loi_list_lock); + spin_lock_init(&cli->cl_loi_list_lock); atomic_set(&cli->cl_pending_w_pages, 0); atomic_set(&cli->cl_pending_r_pages, 0); cli->cl_r_in_flight = 0; @@ -333,7 +333,7 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) atomic_set(&cli->cl_lru_busy, 0); atomic_set(&cli->cl_lru_in_list, 0); INIT_LIST_HEAD(&cli->cl_lru_list); - client_obd_list_lock_init(&cli->cl_lru_list_lock); + spin_lock_init(&cli->cl_lru_list_lock); init_waitqueue_head(&cli->cl_destroy_waitq); atomic_set(&cli->cl_destroy_in_flight, 0); diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 38f267a60f59..5c7a15dd7bd2 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -49,9 +49,9 @@ static ssize_t max_rpcs_in_flight_show(struct kobject *kobj, obd_kobj); struct client_obd *cli = &dev->u.cli; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); len = sprintf(buf, "%u\n", cli->cl_max_rpcs_in_flight); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return len; } @@ -74,9 +74,9 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, if (val < 1 || val > MDC_MAX_RIF_MAX) return -ERANGE; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_max_rpcs_in_flight = val; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return count; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index b3bfdcb73670..bd29eb7db4f0 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -481,9 +481,9 @@ static int mdc_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) { int rc; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); rc = list_empty(&mcw->mcw_entry); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return rc; }; @@ -497,23 +497,23 @@ int mdc_enter_request(struct client_obd *cli) struct mdc_cache_waiter mcw; struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { list_add_tail(&mcw.mcw_entry, &cli->cl_cache_waiters); init_waitqueue_head(&mcw.mcw_waitq); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); rc = l_wait_event(mcw.mcw_waitq, mdc_req_avail(cli, &mcw), &lwi); if (rc) { - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); if (list_empty(&mcw.mcw_entry)) cli->cl_r_in_flight--; list_del_init(&mcw.mcw_entry); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } } else { cli->cl_r_in_flight++; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } return rc; } @@ -523,7 +523,7 @@ void mdc_exit_request(struct client_obd *cli) struct list_head *l, *tmp; struct mdc_cache_waiter *mcw; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_r_in_flight--; list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { @@ -538,5 +538,5 @@ void mdc_exit_request(struct client_obd *cli) } /* Empty waiting list? Decrease reqs in-flight number */ - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index e6e2029289f9..911e5054a9c4 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -121,9 +121,9 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, atomic_add(added, &osc_pool_req_count); } - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_max_rpcs_in_flight = val; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return count; } @@ -139,9 +139,9 @@ static ssize_t max_dirty_mb_show(struct kobject *kobj, long val; int mult; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); val = cli->cl_dirty_max; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); mult = 1 << 20; return lprocfs_read_frac_helper(buf, PAGE_SIZE, val, mult); @@ -169,10 +169,10 @@ static ssize_t max_dirty_mb_store(struct kobject *kobj, pages_number > totalram_pages / 4) /* 1/4 of RAM */ return -ERANGE; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_dirty_max = (u32)(pages_number << PAGE_CACHE_SHIFT); osc_wake_cache_waiters(cli); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return count; } @@ -247,9 +247,9 @@ static ssize_t cur_dirty_bytes_show(struct kobject *kobj, struct client_obd *cli = &dev->u.cli; int len; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); len = sprintf(buf, "%lu\n", cli->cl_dirty); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return len; } @@ -264,9 +264,9 @@ static ssize_t cur_grant_bytes_show(struct kobject *kobj, struct client_obd *cli = &dev->u.cli; int len; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); len = sprintf(buf, "%lu\n", cli->cl_avail_grant); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return len; } @@ -287,12 +287,12 @@ static ssize_t cur_grant_bytes_store(struct kobject *kobj, return rc; /* this is only for shrinking grant */ - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); if (val >= cli->cl_avail_grant) { - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return -EINVAL; } - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); if (cli->cl_import->imp_state == LUSTRE_IMP_FULL) rc = osc_shrink_grant_to_target(cli, val); @@ -311,9 +311,9 @@ static ssize_t cur_lost_grant_bytes_show(struct kobject *kobj, struct client_obd *cli = &dev->u.cli; int len; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); len = sprintf(buf, "%lu\n", cli->cl_lost_grant); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return len; } @@ -585,9 +585,9 @@ static ssize_t max_pages_per_rpc_store(struct kobject *kobj, if (val == 0 || val > ocd->ocd_brw_size >> PAGE_CACHE_SHIFT) { return -ERANGE; } - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_max_pages_per_rpc = val; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return count; } @@ -631,7 +631,7 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) ktime_get_real_ts64(&now); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); seq_printf(seq, "snapshot_time: %llu.%9lu (secs.usecs)\n", (s64)now.tv_sec, (unsigned long)now.tv_nsec); @@ -715,7 +715,7 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) break; } - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return 0; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 7460793324d6..c5106592b3e4 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1373,7 +1373,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, static void osc_consume_write_grant(struct client_obd *cli, struct brw_page *pga) { - assert_spin_locked(&cli->cl_loi_list_lock.lock); + assert_spin_locked(&cli->cl_loi_list_lock); LASSERT(!(pga->flag & OBD_BRW_FROM_GRANT)); atomic_inc(&obd_dirty_pages); cli->cl_dirty += PAGE_CACHE_SIZE; @@ -1389,7 +1389,7 @@ static void osc_consume_write_grant(struct client_obd *cli, static void osc_release_write_grant(struct client_obd *cli, struct brw_page *pga) { - assert_spin_locked(&cli->cl_loi_list_lock.lock); + assert_spin_locked(&cli->cl_loi_list_lock); if (!(pga->flag & OBD_BRW_FROM_GRANT)) { return; } @@ -1408,7 +1408,7 @@ static void osc_release_write_grant(struct client_obd *cli, * To avoid sleeping with object lock held, it's good for us allocate enough * grants before entering into critical section. * - * client_obd_list_lock held by caller + * spin_lock held by caller */ static int osc_reserve_grant(struct client_obd *cli, unsigned int bytes) { @@ -1442,11 +1442,11 @@ static void __osc_unreserve_grant(struct client_obd *cli, static void osc_unreserve_grant(struct client_obd *cli, unsigned int reserved, unsigned int unused) { - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); __osc_unreserve_grant(cli, reserved, unused); if (unused > 0) osc_wake_cache_waiters(cli); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } /** @@ -1467,7 +1467,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, { int grant = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); atomic_sub(nr_pages, &obd_dirty_pages); cli->cl_dirty -= nr_pages << PAGE_CACHE_SHIFT; cli->cl_lost_grant += lost_grant; @@ -1479,7 +1479,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, cli->cl_avail_grant += grant; } osc_wake_cache_waiters(cli); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); CDEBUG(D_CACHE, "lost %u grant: %lu avail: %lu dirty: %lu\n", lost_grant, cli->cl_lost_grant, cli->cl_avail_grant, cli->cl_dirty); @@ -1491,9 +1491,9 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, */ static void osc_exit_cache(struct client_obd *cli, struct osc_async_page *oap) { - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); osc_release_write_grant(cli, &oap->oap_brw_page); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } /** @@ -1532,9 +1532,9 @@ static int ocw_granted(struct client_obd *cli, struct osc_cache_waiter *ocw) { int rc; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); rc = list_empty(&ocw->ocw_entry); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return rc; } @@ -1556,7 +1556,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, OSC_DUMP_GRANT(cli, "need:%d.\n", bytes); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); /* force the caller to try sync io. this can jump the list * of queued writes and create a discontiguous rpc stream @@ -1587,7 +1587,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, while (cli->cl_dirty > 0 || cli->cl_w_in_flight > 0) { list_add_tail(&ocw.ocw_entry, &cli->cl_cache_waiters); ocw.ocw_rc = 0; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); osc_io_unplug_async(env, cli, NULL); @@ -1596,7 +1596,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, rc = l_wait_event(ocw.ocw_waitq, ocw_granted(cli, &ocw), &lwi); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); /* l_wait_event is interrupted by signal */ if (rc < 0) { @@ -1615,7 +1615,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, } } out: - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); OSC_DUMP_GRANT(cli, "returned %d.\n", rc); return rc; } @@ -1776,9 +1776,9 @@ static int osc_list_maint(struct client_obd *cli, struct osc_object *osc) { int is_ready; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); is_ready = __osc_list_maint(cli, osc); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return is_ready; } @@ -1829,10 +1829,10 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, oap->oap_interrupted = 0; if (oap->oap_cmd & OBD_BRW_WRITE && xid > 0) { - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); osc_process_ar(&cli->cl_ar, xid, rc); osc_process_ar(&loi->loi_ar, xid, rc); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } rc = osc_completion(env, oap, oap->oap_cmd, rc); @@ -2133,7 +2133,7 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli) } cl_object_get(obj); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); lu_object_ref_add_at(&obj->co_lu, &link, "check", current); /* attempt some read/write balancing by alternating between @@ -2180,7 +2180,7 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli) lu_object_ref_del_at(&obj->co_lu, &link, "check", current); cl_object_put(env, obj); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); } } @@ -2197,9 +2197,9 @@ static int osc_io_unplug0(const struct lu_env *env, struct client_obd *cli, * potential stack overrun problem. LU-2859 */ atomic_inc(&cli->cl_lru_shrinkers); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); osc_check_rpcs(env, cli); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); atomic_dec(&cli->cl_lru_shrinkers); } else { CDEBUG(D_CACHE, "Queue writeback work for client %p.\n", cli); @@ -2332,9 +2332,9 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, grants = 0; /* it doesn't need any grant to dirty this page */ - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); rc = osc_enter_cache_try(cli, oap, grants, 0); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); if (rc == 0) { /* try failed */ grants = 0; need_release = 1; diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index 89552d73c497..bb34b53aead6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -608,7 +608,7 @@ enum osc_extent_state { * * LOCKING ORDER * ============= - * page lock -> client_obd_list_lock -> object lock(osc_object::oo_lock) + * page lock -> cl_loi_list_lock -> object lock(osc_object::oo_lock) */ struct osc_extent { /** red-black tree node */ diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index e02dd33b637c..5b313519637c 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -456,11 +456,11 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) } if (npages > 0) { - client_obd_list_lock(&cli->cl_lru_list_lock); + spin_lock(&cli->cl_lru_list_lock); list_splice_tail(&lru, &cli->cl_lru_list); atomic_sub(npages, &cli->cl_lru_busy); atomic_add(npages, &cli->cl_lru_in_list); - client_obd_list_unlock(&cli->cl_lru_list_lock); + spin_unlock(&cli->cl_lru_list_lock); /* XXX: May set force to be true for better performance */ if (osc_cache_too_much(cli)) @@ -482,14 +482,14 @@ static void __osc_lru_del(struct client_obd *cli, struct osc_page *opg) static void osc_lru_del(struct client_obd *cli, struct osc_page *opg) { if (opg->ops_in_lru) { - client_obd_list_lock(&cli->cl_lru_list_lock); + spin_lock(&cli->cl_lru_list_lock); if (!list_empty(&opg->ops_lru)) { __osc_lru_del(cli, opg); } else { LASSERT(atomic_read(&cli->cl_lru_busy) > 0); atomic_dec(&cli->cl_lru_busy); } - client_obd_list_unlock(&cli->cl_lru_list_lock); + spin_unlock(&cli->cl_lru_list_lock); atomic_inc(cli->cl_lru_left); /* this is a great place to release more LRU pages if @@ -513,9 +513,9 @@ static void osc_lru_use(struct client_obd *cli, struct osc_page *opg) * ops_lru should be empty */ if (opg->ops_in_lru && !list_empty(&opg->ops_lru)) { - client_obd_list_lock(&cli->cl_lru_list_lock); + spin_lock(&cli->cl_lru_list_lock); __osc_lru_del(cli, opg); - client_obd_list_unlock(&cli->cl_lru_list_lock); + spin_unlock(&cli->cl_lru_list_lock); atomic_inc(&cli->cl_lru_busy); } } @@ -572,7 +572,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, pvec = (struct cl_page **)osc_env_info(env)->oti_pvec; io = &osc_env_info(env)->oti_io; - client_obd_list_lock(&cli->cl_lru_list_lock); + spin_lock(&cli->cl_lru_list_lock); maxscan = min(target << 1, atomic_read(&cli->cl_lru_in_list)); list_for_each_entry_safe(opg, temp, &cli->cl_lru_list, ops_lru) { struct cl_page *page; @@ -592,7 +592,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, struct cl_object *tmp = page->cp_obj; cl_object_get(tmp); - client_obd_list_unlock(&cli->cl_lru_list_lock); + spin_unlock(&cli->cl_lru_list_lock); if (clobj) { discard_pagevec(env, io, pvec, index); @@ -608,7 +608,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, io->ci_ignore_layout = 1; rc = cl_io_init(env, io, CIT_MISC, clobj); - client_obd_list_lock(&cli->cl_lru_list_lock); + spin_lock(&cli->cl_lru_list_lock); if (rc != 0) break; @@ -640,17 +640,17 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, /* Don't discard and free the page with cl_lru_list held */ pvec[index++] = page; if (unlikely(index == OTI_PVEC_SIZE)) { - client_obd_list_unlock(&cli->cl_lru_list_lock); + spin_unlock(&cli->cl_lru_list_lock); discard_pagevec(env, io, pvec, index); index = 0; - client_obd_list_lock(&cli->cl_lru_list_lock); + spin_lock(&cli->cl_lru_list_lock); } if (++count >= target) break; } - client_obd_list_unlock(&cli->cl_lru_list_lock); + spin_unlock(&cli->cl_lru_list_lock); if (clobj) { discard_pagevec(env, io, pvec, index); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 1e378e6c1a70..372bd26b07c8 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -801,7 +801,7 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, LASSERT(!(oa->o_valid & bits)); oa->o_valid |= bits; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); oa->o_dirty = cli->cl_dirty; if (unlikely(cli->cl_dirty - cli->cl_dirty_transit > cli->cl_dirty_max)) { @@ -833,7 +833,7 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, oa->o_grant = cli->cl_avail_grant + cli->cl_reserved_grant; oa->o_dropped = cli->cl_lost_grant; cli->cl_lost_grant = 0; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); CDEBUG(D_CACHE, "dirty: %llu undirty: %u dropped %u grant: %llu\n", oa->o_dirty, oa->o_undirty, oa->o_dropped, oa->o_grant); @@ -849,9 +849,9 @@ void osc_update_next_shrink(struct client_obd *cli) static void __osc_update_grant(struct client_obd *cli, u64 grant) { - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_avail_grant += grant; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); } static void osc_update_grant(struct client_obd *cli, struct ost_body *body) @@ -889,10 +889,10 @@ static int osc_shrink_grant_interpret(const struct lu_env *env, static void osc_shrink_grant_local(struct client_obd *cli, struct obdo *oa) { - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); oa->o_grant = cli->cl_avail_grant / 4; cli->cl_avail_grant -= oa->o_grant; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); if (!(oa->o_valid & OBD_MD_FLFLAGS)) { oa->o_valid |= OBD_MD_FLFLAGS; oa->o_flags = 0; @@ -911,10 +911,10 @@ static int osc_shrink_grant(struct client_obd *cli) __u64 target_bytes = (cli->cl_max_rpcs_in_flight + 1) * (cli->cl_max_pages_per_rpc << PAGE_CACHE_SHIFT); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); if (cli->cl_avail_grant <= target_bytes) target_bytes = cli->cl_max_pages_per_rpc << PAGE_CACHE_SHIFT; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return osc_shrink_grant_to_target(cli, target_bytes); } @@ -924,7 +924,7 @@ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes) int rc = 0; struct ost_body *body; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); /* Don't shrink if we are already above or below the desired limit * We don't want to shrink below a single RPC, as that will negatively * impact block allocation and long-term performance. @@ -933,10 +933,10 @@ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes) target_bytes = cli->cl_max_pages_per_rpc << PAGE_CACHE_SHIFT; if (target_bytes >= cli->cl_avail_grant) { - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); return 0; } - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); body = kzalloc(sizeof(*body), GFP_NOFS); if (!body) @@ -944,10 +944,10 @@ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes) osc_announce_cached(cli, &body->oa, 0); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); body->oa.o_grant = cli->cl_avail_grant - target_bytes; cli->cl_avail_grant = target_bytes; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); if (!(body->oa.o_valid & OBD_MD_FLFLAGS)) { body->oa.o_valid |= OBD_MD_FLFLAGS; body->oa.o_flags = 0; @@ -1035,7 +1035,7 @@ static void osc_init_grant(struct client_obd *cli, struct obd_connect_data *ocd) * race is tolerable here: if we're evicted, but imp_state already * left EVICTED state, then cl_dirty must be 0 already. */ - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); if (cli->cl_import->imp_state == LUSTRE_IMP_EVICTED) cli->cl_avail_grant = ocd->ocd_grant; else @@ -1053,7 +1053,7 @@ static void osc_init_grant(struct client_obd *cli, struct obd_connect_data *ocd) /* determine the appropriate chunk size used by osc_extent. */ cli->cl_chunkbits = max_t(int, PAGE_CACHE_SHIFT, ocd->ocd_blocksize); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); CDEBUG(D_CACHE, "%s, setting cl_avail_grant: %ld cl_lost_grant: %ld chunk bits: %d\n", cli->cl_import->imp_obd->obd_name, @@ -1827,7 +1827,7 @@ static int brw_interpret(const struct lu_env *env, osc_release_ppga(aa->aa_ppga, aa->aa_page_count); ptlrpc_lprocfs_brw(req, req->rq_bulk->bd_nob_transferred); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); /* We need to decrement before osc_ap_completion->osc_wake_cache_waiters * is called so we know whether to go to sync BRWs or wait for more * RPCs to complete @@ -1837,7 +1837,7 @@ static int brw_interpret(const struct lu_env *env, else cli->cl_r_in_flight--; osc_wake_cache_waiters(cli); - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); osc_io_unplug(env, cli, NULL); return rc; @@ -2005,7 +2005,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, if (tmp) tmp->oap_request = ptlrpc_request_addref(req); - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); starting_offset >>= PAGE_CACHE_SHIFT; if (cmd == OBD_BRW_READ) { cli->cl_r_in_flight++; @@ -2020,7 +2020,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, lprocfs_oh_tally_log2(&cli->cl_write_offset_hist, starting_offset + 1); } - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); DEBUG_REQ(D_INODE, req, "%d pages, aa %p. now %dr/%dw in flight", page_count, aa, cli->cl_r_in_flight, @@ -3005,12 +3005,12 @@ static int osc_reconnect(const struct lu_env *env, if (data && (data->ocd_connect_flags & OBD_CONNECT_GRANT)) { long lost_grant; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); data->ocd_grant = (cli->cl_avail_grant + cli->cl_dirty) ?: 2 * cli_brw_size(obd); lost_grant = cli->cl_lost_grant; cli->cl_lost_grant = 0; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); CDEBUG(D_RPCTRACE, "ocd_connect_flags: %#llx ocd_version: %d ocd_grant: %d, lost: %ld.\n", data->ocd_connect_flags, @@ -3060,10 +3060,10 @@ static int osc_import_event(struct obd_device *obd, switch (event) { case IMP_EVENT_DISCON: { cli = &obd->u.cli; - client_obd_list_lock(&cli->cl_loi_list_lock); + spin_lock(&cli->cl_loi_list_lock); cli->cl_avail_grant = 0; cli->cl_lost_grant = 0; - client_obd_list_unlock(&cli->cl_loi_list_lock); + spin_unlock(&cli->cl_loi_list_lock); break; } case IMP_EVENT_INACTIVE: { -- GitLab From 1929c433854c7673fd2d983ef8cf15cf13306d5c Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:37 -0400 Subject: [PATCH 0866/9938] staging/lustre/llite: remove some cl wrappers In llite remove the wrapper functions and macros: cl_i2info() cl_i2sbi() cl_iattr2fd() cl_inode_info cl_inode_mode() cl_inode_{a,m,c}time() cl_isize_{read,write,write_nolock}() Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/12850 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-by: James Simmons Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 +- drivers/staging/lustre/lustre/llite/file.c | 8 ++-- drivers/staging/lustre/lustre/llite/glimpse.c | 10 ++--- .../staging/lustre/lustre/llite/lcommon_cl.c | 45 +++++++++---------- .../lustre/lustre/llite/llite_internal.h | 32 ------------- .../staging/lustre/lustre/llite/llite_lib.c | 2 +- .../staging/lustre/lustre/llite/vvp_object.c | 4 +- 7 files changed, 35 insertions(+), 68 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 4e0a3e583330..2ca4b0ef82ad 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -191,7 +191,7 @@ static int ll_dir_filler(void *_hash, struct page *page0) body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); /* Checked by mdc_readpage() */ if (body->valid & OBD_MD_FLSIZE) - cl_isize_write(inode, body->size); + i_size_write(inode, body->size); nrdpgs = (request->rq_bulk->bd_nob_transferred+PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 8fc9da00278e..c3c258f93817 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1036,7 +1036,7 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode) CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n", PFID(&lli->lli_fid), attr->cat_size); - cl_isize_write_nolock(inode, attr->cat_size); + i_size_write(inode, attr->cat_size); inode->i_blocks = attr->cat_blocks; @@ -1592,7 +1592,7 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) LASSERT(!fd->fd_grouplock.cg_lock); spin_unlock(&lli->lli_lock); - rc = cl_get_grouplock(cl_i2info(inode)->lli_clob, + rc = cl_get_grouplock(ll_i2info(inode)->lli_clob, arg, (file->f_flags & O_NONBLOCK), &grouplock); if (rc) return rc; @@ -2614,7 +2614,7 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, return PTR_ERR(env); io = ccc_env_thread_io(env); - io->ci_obj = cl_i2info(inode)->lli_clob; + io->ci_obj = ll_i2info(inode)->lli_clob; io->ci_ignore_layout = ignore_layout; /* initialize parameters for sync */ @@ -3629,7 +3629,7 @@ int ll_layout_restore(struct inode *inode) sizeof(hur->hur_user_item[0].hui_fid)); hur->hur_user_item[0].hui_extent.length = -1; hur->hur_request.hr_itemcount = 1; - rc = obd_iocontrol(LL_IOC_HSM_REQUEST, cl_i2sbi(inode)->ll_md_exp, + rc = obd_iocontrol(LL_IOC_HSM_REQUEST, ll_i2sbi(inode)->ll_md_exp, len, hur, NULL); kfree(hur); return rc; diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index 88bc7c9918e5..9b0e2ec0cf05 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -87,7 +87,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, struct inode *inode, struct cl_object *clob, int agl) { struct cl_lock_descr *descr = &ccc_env_info(env)->cti_descr; - struct cl_inode_info *lli = cl_i2info(inode); + struct ll_inode_info *lli = ll_i2info(inode); const struct lu_fid *fid = lu_object_fid(&clob->co_lu); struct ccc_io *cio = ccc_env_io(env); struct cl_lock *lock; @@ -140,7 +140,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, result = cl_wait(env, lock); if (result == 0) { ll_merge_attr(env, inode); - if (cl_isize_read(inode) > 0 && + if (i_size_read(inode) > 0 && inode->i_blocks == 0) { /* * LU-417: Add dirty pages block count @@ -167,11 +167,11 @@ static int cl_io_get(struct inode *inode, struct lu_env **envout, { struct lu_env *env; struct cl_io *io; - struct cl_inode_info *lli = cl_i2info(inode); + struct ll_inode_info *lli = ll_i2info(inode); struct cl_object *clob = lli->lli_clob; int result; - if (S_ISREG(cl_inode_mode(inode))) { + if (S_ISREG(inode->i_mode)) { env = cl_env_get(refcheck); if (!IS_ERR(env)) { io = ccc_env_thread_io(env); @@ -240,7 +240,7 @@ int cl_local_size(struct inode *inode) int result; int refcheck; - if (!cl_i2info(inode)->lli_has_smd) + if (!ll_i2info(inode)->lli_has_smd) return 0; result = cl_io_get(inode, &env, &io, &refcheck); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 4871d0feeb1c..fde96d374f49 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -417,9 +417,9 @@ int ccc_object_glimpse(const struct lu_env *env, { struct inode *inode = ccc_object_inode(obj); - lvb->lvb_mtime = cl_inode_mtime(inode); - lvb->lvb_atime = cl_inode_atime(inode); - lvb->lvb_ctime = cl_inode_ctime(inode); + lvb->lvb_mtime = LTIME_S(inode->i_mtime); + lvb->lvb_atime = LTIME_S(inode->i_atime); + lvb->lvb_ctime = LTIME_S(inode->i_ctime); /* * LU-417: Add dirty pages block count lest i_blocks reports 0, some * "cp" or "tar" on remote node may think it's a completely sparse file @@ -731,7 +731,7 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, * linux-2.6.18-128.1.1 miss to do that. * --bug 17336 */ - loff_t size = cl_isize_read(inode); + loff_t size = i_size_read(inode); loff_t cur_index = start >> PAGE_CACHE_SHIFT; loff_t size_index = (size - 1) >> PAGE_CACHE_SHIFT; @@ -752,11 +752,11 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, * which will always be >= the kms value here. * b=11081 */ - if (cl_isize_read(inode) < kms) { - cl_isize_write_nolock(inode, kms); + if (i_size_read(inode) < kms) { + i_size_write(inode, kms); CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n", PFID(lu_object_fid(&obj->co_lu)), - (__u64)cl_isize_read(inode)); + (__u64)i_size_read(inode)); } } ccc_object_size_unlock(obj); @@ -816,14 +816,14 @@ void ccc_req_attr_set(const struct lu_env *env, if (slice->crs_req->crq_type == CRT_WRITE) { if (flags & OBD_MD_FLEPOCH) { oa->o_valid |= OBD_MD_FLEPOCH; - oa->o_ioepoch = cl_i2info(inode)->lli_ioepoch; + oa->o_ioepoch = ll_i2info(inode)->lli_ioepoch; valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLUID | OBD_MD_FLGID; } } obdo_from_inode(oa, inode, valid_flags & flags); - obdo_set_parent_fid(oa, &cl_i2info(inode)->lli_fid); - memcpy(attr->cra_jobid, cl_i2info(inode)->lli_jobid, + obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); + memcpy(attr->cra_jobid, ll_i2info(inode)->lli_jobid, JOBSTATS_JOBID_SIZE); } @@ -844,7 +844,7 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) return PTR_ERR(env); io = ccc_env_thread_io(env); - io->ci_obj = cl_i2info(inode)->lli_clob; + io->ci_obj = ll_i2info(inode)->lli_clob; io->u.ci_setattr.sa_attr.lvb_atime = LTIME_S(attr->ia_atime); io->u.ci_setattr.sa_attr.lvb_mtime = LTIME_S(attr->ia_mtime); @@ -860,7 +860,7 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) /* populate the file descriptor for ftruncate to honor * group lock - see LU-787 */ - cio->cui_fd = cl_iattr2fd(inode, attr); + cio->cui_fd = LUSTRE_FPRIVATE(attr->ia_file); result = cl_io_loop(env, io); } else { @@ -949,11 +949,10 @@ struct page *cl2vm_page(const struct cl_page_slice *slice) int ccc_object_invariant(const struct cl_object *obj) { struct inode *inode = ccc_object_inode(obj); - struct cl_inode_info *lli = cl_i2info(inode); + struct ll_inode_info *lli = ll_i2info(inode); - return (S_ISREG(cl_inode_mode(inode)) || - /* i_mode of unlinked inode is zeroed. */ - cl_inode_mode(inode) == 0) && lli->lli_clob == obj; + return (S_ISREG(inode->i_mode) || inode->i_mode == 0) && + lli->lli_clob == obj; } struct inode *ccc_object_inode(const struct cl_object *obj) @@ -973,7 +972,7 @@ struct inode *ccc_object_inode(const struct cl_object *obj) int cl_file_inode_init(struct inode *inode, struct lustre_md *md) { struct lu_env *env; - struct cl_inode_info *lli; + struct ll_inode_info *lli; struct cl_object *clob; struct lu_site *site; struct lu_fid *fid; @@ -987,14 +986,14 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) int refcheck; LASSERT(md->body->valid & OBD_MD_FLID); - LASSERT(S_ISREG(cl_inode_mode(inode))); + LASSERT(S_ISREG(inode->i_mode)); env = cl_env_get(&refcheck); if (IS_ERR(env)) return PTR_ERR(env); - site = cl_i2sbi(inode)->ll_site; - lli = cl_i2info(inode); + site = ll_i2sbi(inode)->ll_site; + lli = ll_i2info(inode); fid = &lli->lli_fid; LASSERT(fid_is_sane(fid)); @@ -1071,7 +1070,7 @@ static void cl_object_put_last(struct lu_env *env, struct cl_object *obj) void cl_inode_fini(struct inode *inode) { struct lu_env *env; - struct cl_inode_info *lli = cl_i2info(inode); + struct ll_inode_info *lli = ll_i2info(inode); struct cl_object *clob = lli->lli_clob; int refcheck; int emergency; @@ -1168,10 +1167,10 @@ __u32 cl_fid_build_gen(const struct lu_fid *fid) */ struct lov_stripe_md *ccc_inode_lsm_get(struct inode *inode) { - return lov_lsm_get(cl_i2info(inode)->lli_clob); + return lov_lsm_get(ll_i2info(inode)->lli_clob); } inline void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm) { - lov_lsm_put(cl_i2info(inode)->lli_clob, lsm); + lov_lsm_put(ll_i2info(inode)->lli_clob, lsm); } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index c1d747a1e962..ffed507da069 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1293,38 +1293,6 @@ typedef enum llioc_iter (*llioc_callback_t)(struct inode *inode, void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd); void ll_iocontrol_unregister(void *magic); -/* lclient compat stuff */ -#define cl_inode_info ll_inode_info -#define cl_i2info(info) ll_i2info(info) -#define cl_inode_mode(inode) ((inode)->i_mode) -#define cl_i2sbi ll_i2sbi - -static inline struct ll_file_data *cl_iattr2fd(struct inode *inode, - const struct iattr *attr) -{ - LASSERT(attr->ia_valid & ATTR_FILE); - return LUSTRE_FPRIVATE(attr->ia_file); -} - -static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms) -{ - LASSERT(mutex_is_locked(&ll_i2info(inode)->lli_size_mutex)); - i_size_write(inode, kms); -} - -static inline void cl_isize_write(struct inode *inode, loff_t kms) -{ - ll_inode_size_lock(inode); - i_size_write(inode, kms); - ll_inode_size_unlock(inode); -} - -#define cl_isize_read(inode) i_size_read(inode) - -#define cl_inode_atime(inode) LTIME_S((inode)->i_atime) -#define cl_inode_ctime(inode) LTIME_S((inode)->i_ctime) -#define cl_inode_mtime(inode) LTIME_S((inode)->i_mtime) - int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, enum cl_fsync_mode mode, int ignore_layout); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 0b4e0dbfc130..041d22150973 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1698,7 +1698,7 @@ void ll_read_inode2(struct inode *inode, void *opaque) void ll_delete_inode(struct inode *inode) { - struct cl_inode_info *lli = cl_i2info(inode); + struct ll_inode_info *lli = ll_i2info(inode); if (S_ISREG(inode->i_mode) && lli->lli_clob) /* discard all dirty pages before truncating them, required by diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index b9a1d01a9bd3..d03eb2b59de7 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -112,7 +112,7 @@ static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, if (valid & CAT_CTIME) inode->i_ctime.tv_sec = attr->cat_ctime; if (0 && valid & CAT_SIZE) - cl_isize_write_nolock(inode, attr->cat_size); + i_size_write(inode, attr->cat_size); /* not currently necessary */ if (0 && valid & (CAT_UID|CAT_GID|CAT_SIZE)) mark_inode_dirty(inode); @@ -196,7 +196,7 @@ static const struct lu_object_operations vvp_lu_obj_ops = { struct ccc_object *cl_inode2ccc(struct inode *inode) { - struct cl_inode_info *lli = cl_i2info(inode); + struct ll_inode_info *lli = ll_i2info(inode); struct cl_object *obj = lli->lli_clob; struct lu_object *lu; -- GitLab From bb41292b4c4e956b5b776970d28630f04c4dd609 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 30 Mar 2016 19:48:38 -0400 Subject: [PATCH 0867/9938] staging/lustre: Remove struct ll_iattr This was a compat code from the time it had ia_attr_flags. Instead convert all the cryptic callers that did ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags into direct access to op_data->op_attr_flags This also makes lustre/include/linux/obd.h not needed anymore, so remove it. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/linux/obd.h | 58 ------------------- drivers/staging/lustre/lustre/include/obd.h | 2 +- drivers/staging/lustre/lustre/llite/file.c | 4 +- .../staging/lustre/lustre/llite/llite_lib.c | 2 +- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 3 +- drivers/staging/lustre/lustre/obdclass/obdo.c | 3 +- 6 files changed, 6 insertions(+), 66 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/include/linux/obd.h diff --git a/drivers/staging/lustre/lustre/include/linux/obd.h b/drivers/staging/lustre/lustre/include/linux/obd.h deleted file mode 100644 index e1063e828229..000000000000 --- a/drivers/staging/lustre/lustre/include/linux/obd.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef __LINUX_OBD_H -#define __LINUX_OBD_H - -#ifndef __OBD_H -#error Do not #include this file directly. #include instead -#endif - -#include "../obd_support.h" - -#include -#include -#include /* for struct task_struct, for current.h */ -#include - -#include "../lustre_intent.h" - -struct ll_iattr { - struct iattr iattr; - unsigned int ia_attr_flags; -}; - -#endif /* __LINUX_OBD_H */ diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 84cc001e152e..ded7b106ac8a 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -38,7 +38,6 @@ #define __OBD_H #include -#include "linux/obd.h" #define IOC_OSC_TYPE 'h' #define IOC_OSC_MIN_NR 20 @@ -55,6 +54,7 @@ #include "lustre_export.h" #include "lustre_fid.h" #include "lustre_fld.h" +#include "lustre_intent.h" #define MAX_OBD_DEVICES 8192 diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index c3c258f93817..bf2a5ee1e687 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -45,6 +45,7 @@ #include "../include/lustre_lite.h" #include #include +#include #include "llite_internal.h" #include "../include/lustre/ll_fiemap.h" @@ -87,8 +88,7 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, op_data->op_attr.ia_ctime = inode->i_ctime; op_data->op_attr.ia_size = i_size_read(inode); op_data->op_attr_blocks = inode->i_blocks; - ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags = - ll_inode_to_ext_flags(inode->i_flags); + op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags); op_data->op_ioepoch = ll_i2info(inode)->lli_ioepoch; if (fh) op_data->op_handle = *fh; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 041d22150973..0f01cfc14b72 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1771,7 +1771,7 @@ int ll_iocontrol(struct inode *inode, struct file *file, if (IS_ERR(op_data)) return PTR_ERR(op_data); - ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags = flags; + op_data->op_attr_flags = flags; op_data->op_attr.ia_valid |= ATTR_ATTR_FLAG; rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, NULL, 0, &req, NULL); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index bd29eb7db4f0..be0acf7feee3 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -279,8 +279,7 @@ static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec, rec->sa_atime = LTIME_S(op_data->op_attr.ia_atime); rec->sa_mtime = LTIME_S(op_data->op_attr.ia_mtime); rec->sa_ctime = LTIME_S(op_data->op_attr.ia_ctime); - rec->sa_attr_flags = - ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags; + rec->sa_attr_flags = op_data->op_attr_flags; if ((op_data->op_attr.ia_valid & ATTR_GID) && in_group_p(op_data->op_attr.ia_gid)) rec->sa_suppgid = diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c index e6436cb4ac62..748e33f017d5 100644 --- a/drivers/staging/lustre/lustre/obdclass/obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/obdo.c @@ -185,8 +185,7 @@ void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid) op_data->op_attr.ia_valid |= ATTR_BLOCKS; } if (valid & OBD_MD_FLFLAGS) { - ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags = - oa->o_flags; + op_data->op_attr_flags = oa->o_flags; op_data->op_attr.ia_valid |= ATTR_ATTR_FLAG; } } -- GitLab From e5c4e635c36354c0f4aa6a00b1787d15ee689528 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:39 -0400 Subject: [PATCH 0868/9938] staging/lustre/clio: generalize cl_sync_io To make cl_sync_io interfaces not just wait for pages, but to be a generic synchronization mechanism. Also remove cl_io_cancel that became not used. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/8656 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4198 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 13 +++- .../staging/lustre/lustre/obdclass/cl_io.c | 74 +++++++++---------- .../staging/lustre/lustre/obdclass/cl_page.c | 2 +- 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 69b40f50df70..91261b1972af 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -3125,13 +3125,18 @@ struct cl_sync_io { atomic_t csi_barrier; /** completion to be signaled when transfer is complete. */ wait_queue_head_t csi_waitq; + /** callback to invoke when this IO is finished */ + void (*csi_end_io)(const struct lu_env *, + struct cl_sync_io *); }; -void cl_sync_io_init(struct cl_sync_io *anchor, int nrpages); -int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io, - struct cl_page_list *queue, struct cl_sync_io *anchor, +void cl_sync_io_init(struct cl_sync_io *anchor, int nr, + void (*end)(const struct lu_env *, struct cl_sync_io *)); +int cl_sync_io_wait(const struct lu_env *env, struct cl_sync_io *anchor, long timeout); -void cl_sync_io_note(struct cl_sync_io *anchor, int ioret); +void cl_sync_io_note(const struct lu_env *env, struct cl_sync_io *anchor, + int ioret); +void cl_sync_io_end(const struct lu_env *env, struct cl_sync_io *anchor); /** @} cl_sync_io */ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 65d6cee5232b..6a8dd9faafca 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -800,6 +800,9 @@ int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io, } EXPORT_SYMBOL(cl_io_submit_rw); +static void cl_page_list_assume(const struct lu_env *env, + struct cl_io *io, struct cl_page_list *plist); + /** * Submit a sync_io and wait for the IO to be finished, or error happens. * If \a timeout is zero, it means to wait for the IO unconditionally. @@ -817,7 +820,7 @@ int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, pg->cp_sync_io = anchor; } - cl_sync_io_init(anchor, queue->c2_qin.pl_nr); + cl_sync_io_init(anchor, queue->c2_qin.pl_nr, &cl_sync_io_end); rc = cl_io_submit_rw(env, io, iot, queue); if (rc == 0) { /* @@ -828,12 +831,12 @@ int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, */ cl_page_list_for_each(pg, &queue->c2_qin) { pg->cp_sync_io = NULL; - cl_sync_io_note(anchor, 1); + cl_sync_io_note(env, anchor, 1); } /* wait for the IO to be finished. */ - rc = cl_sync_io_wait(env, io, &queue->c2_qout, - anchor, timeout); + rc = cl_sync_io_wait(env, anchor, timeout); + cl_page_list_assume(env, io, &queue->c2_qout); } else { LASSERT(list_empty(&queue->c2_qout.pl_pages)); cl_page_list_for_each(pg, &queue->c2_qin) @@ -843,25 +846,6 @@ int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, } EXPORT_SYMBOL(cl_io_submit_sync); -/** - * Cancel an IO which has been submitted by cl_io_submit_rw. - */ -static int cl_io_cancel(const struct lu_env *env, struct cl_io *io, - struct cl_page_list *queue) -{ - struct cl_page *page; - int result = 0; - - CERROR("Canceling ongoing page transmission\n"); - cl_page_list_for_each(page, queue) { - int rc; - - rc = cl_page_cancel(env, page); - result = result ?: rc; - } - return result; -} - /** * Main io loop. * @@ -1433,25 +1417,38 @@ void cl_req_attr_set(const struct lu_env *env, struct cl_req *req, } EXPORT_SYMBOL(cl_req_attr_set); +/* cl_sync_io_callback assumes the caller must call cl_sync_io_wait() to + * wait for the IO to finish. + */ +void cl_sync_io_end(const struct lu_env *env, struct cl_sync_io *anchor) +{ + wake_up_all(&anchor->csi_waitq); + + /* it's safe to nuke or reuse anchor now */ + atomic_set(&anchor->csi_barrier, 0); +} +EXPORT_SYMBOL(cl_sync_io_end); /** - * Initialize synchronous io wait anchor, for transfer of \a nrpages pages. + * Initialize synchronous io wait anchor */ -void cl_sync_io_init(struct cl_sync_io *anchor, int nrpages) +void cl_sync_io_init(struct cl_sync_io *anchor, int nr, + void (*end)(const struct lu_env *, struct cl_sync_io *)) { init_waitqueue_head(&anchor->csi_waitq); - atomic_set(&anchor->csi_sync_nr, nrpages); - atomic_set(&anchor->csi_barrier, nrpages > 0); + atomic_set(&anchor->csi_sync_nr, nr); + atomic_set(&anchor->csi_barrier, nr > 0); anchor->csi_sync_rc = 0; + anchor->csi_end_io = end; + LASSERT(end); } EXPORT_SYMBOL(cl_sync_io_init); /** - * Wait until all transfer completes. Transfer completion routine has to call - * cl_sync_io_note() for every page. + * Wait until all IO completes. Transfer completion routine has to call + * cl_sync_io_note() for every entity. */ -int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io, - struct cl_page_list *queue, struct cl_sync_io *anchor, +int cl_sync_io_wait(const struct lu_env *env, struct cl_sync_io *anchor, long timeout) { struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(timeout), @@ -1464,11 +1461,9 @@ int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io, atomic_read(&anchor->csi_sync_nr) == 0, &lwi); if (rc < 0) { - CERROR("SYNC IO failed with error: %d, try to cancel %d remaining pages\n", + CERROR("IO failed: %d, still wait for %d remaining entries\n", rc, atomic_read(&anchor->csi_sync_nr)); - (void)cl_io_cancel(env, io, queue); - lwi = (struct l_wait_info) { 0 }; (void)l_wait_event(anchor->csi_waitq, atomic_read(&anchor->csi_sync_nr) == 0, @@ -1477,14 +1472,12 @@ int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io, rc = anchor->csi_sync_rc; } LASSERT(atomic_read(&anchor->csi_sync_nr) == 0); - cl_page_list_assume(env, io, queue); /* wait until cl_sync_io_note() has done wakeup */ while (unlikely(atomic_read(&anchor->csi_barrier) != 0)) { cpu_relax(); } - POISON(anchor, 0x5a, sizeof(*anchor)); return rc; } EXPORT_SYMBOL(cl_sync_io_wait); @@ -1492,7 +1485,8 @@ EXPORT_SYMBOL(cl_sync_io_wait); /** * Indicate that transfer of a single page completed. */ -void cl_sync_io_note(struct cl_sync_io *anchor, int ioret) +void cl_sync_io_note(const struct lu_env *env, struct cl_sync_io *anchor, + int ioret) { if (anchor->csi_sync_rc == 0 && ioret < 0) anchor->csi_sync_rc = ioret; @@ -1503,9 +1497,9 @@ void cl_sync_io_note(struct cl_sync_io *anchor, int ioret) */ LASSERT(atomic_read(&anchor->csi_sync_nr) > 0); if (atomic_dec_and_test(&anchor->csi_sync_nr)) { - wake_up_all(&anchor->csi_waitq); - /* it's safe to nuke or reuse anchor now */ - atomic_set(&anchor->csi_barrier, 0); + LASSERT(anchor->csi_end_io); + anchor->csi_end_io(env, anchor); + /* Can't access anchor any more */ } } EXPORT_SYMBOL(cl_sync_io_note); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 506a9f94e5ba..ad7f0aec605b 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -887,7 +887,7 @@ void cl_page_completion(const struct lu_env *env, cl_page_put(env, pg); if (anchor) - cl_sync_io_note(anchor, ioret); + cl_sync_io_note(env, anchor, ioret); } EXPORT_SYMBOL(cl_page_completion); -- GitLab From 06563b5606da7635b1fd5d121e7bd6d221e23db4 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:40 -0400 Subject: [PATCH 0869/9938] staging/lustre/clio: cl_lock simplification In this patch, the cl_lock cache is eliminated. cl_lock is turned into a cacheless data container for the requirements of locks to complete the IO. cl_lock is created before I/O starts and destroyed when the I/O is complete. cl_lock depends on LDLM lock to fulfill lock semantics. LDLM lock is attached to cl_lock at OSC layer. LDLM lock is still cacheable. Two major methods are supported for cl_lock: clo_enqueue and clo_cancel. A cl_lock is enqueued by cl_lock_request(), which will call clo_enqueue() methods for each layer to enqueue the lock. At the LOV layer, if a cl_lock consists of multiple sub cl_locks, each sub locks will be enqueued correspondingly. At OSC layer, the lock enqueue request will tend to reuse cached LDLM lock; otherwise a new LDLM lock will have to be requested from OST side. cl_lock_cancel() must be called to release a cl_lock after use. clo_cancel() method will be called for each layer to release the resource held by this lock. At OSC layer, the reference count of LDLM lock, which is held at clo_enqueue time, is released. LDLM lock can only be canceled if there is no cl_lock using it. Signed-off-by: Bobi Jam Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/10858 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3259 Reviewed-by: John L. Hammond Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 590 +---- .../staging/lustre/lustre/include/lclient.h | 26 +- .../lustre/lustre/include/lustre/lustre_idl.h | 2 + .../lustre/lustre/include/lustre_dlm.h | 1 + drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 1 + .../staging/lustre/lustre/ldlm/ldlm_lock.c | 3 +- .../staging/lustre/lustre/ldlm/ldlm_request.c | 16 +- .../lustre/lustre/ldlm/ldlm_resource.c | 1 + drivers/staging/lustre/lustre/llite/glimpse.c | 49 +- .../staging/lustre/lustre/llite/lcommon_cl.c | 107 +- .../lustre/lustre/llite/lcommon_misc.c | 14 +- drivers/staging/lustre/lustre/llite/rw26.c | 3 +- drivers/staging/lustre/lustre/llite/vvp_io.c | 19 +- .../staging/lustre/lustre/llite/vvp_lock.c | 25 +- .../staging/lustre/lustre/llite/vvp_object.c | 12 +- .../lustre/lustre/lov/lov_cl_internal.h | 75 +- drivers/staging/lustre/lustre/lov/lov_dev.c | 5 +- drivers/staging/lustre/lustre/lov/lov_lock.c | 996 +------- .../staging/lustre/lustre/lov/lov_object.c | 13 +- .../staging/lustre/lustre/lov/lovsub_lock.c | 383 ---- .../staging/lustre/lustre/obdclass/cl_io.c | 168 +- .../staging/lustre/lustre/obdclass/cl_lock.c | 2026 +---------------- .../lustre/lustre/obdclass/cl_object.c | 64 +- .../staging/lustre/lustre/obdclass/cl_page.c | 9 - .../lustre/lustre/obdecho/echo_client.c | 60 +- drivers/staging/lustre/lustre/osc/osc_cache.c | 110 +- .../lustre/lustre/osc/osc_cl_internal.h | 62 +- .../staging/lustre/lustre/osc/osc_internal.h | 10 +- drivers/staging/lustre/lustre/osc/osc_io.c | 41 +- drivers/staging/lustre/lustre/osc/osc_lock.c | 1618 +++++-------- .../staging/lustre/lustre/osc/osc_object.c | 33 +- drivers/staging/lustre/lustre/osc/osc_page.c | 14 +- .../staging/lustre/lustre/osc/osc_request.c | 207 +- 33 files changed, 1203 insertions(+), 5560 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 91261b1972af..8f9512ef3942 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -82,7 +82,6 @@ * - i_mutex * - PG_locked * - cl_object_header::coh_page_guard - * - cl_object_header::coh_lock_guard * - lu_site::ls_guard * * See the top comment in cl_object.c for the description of overall locking and @@ -404,16 +403,6 @@ struct cl_object_header { * here. */ struct lu_object_header coh_lu; - /** \name locks - * \todo XXX move locks below to the separate cache-lines, they are - * mostly useless otherwise. - */ - /** @{ */ - /** Lock protecting lock list. */ - spinlock_t coh_lock_guard; - /** @} locks */ - /** List of cl_lock's granted for this object. */ - struct list_head coh_locks; /** * Parent object. It is assumed that an object has a well-defined @@ -795,16 +784,9 @@ struct cl_page_slice { /** * Lock mode. For the client extent locks. * - * \warning: cl_lock_mode_match() assumes particular ordering here. * \ingroup cl_lock */ enum cl_lock_mode { - /** - * Mode of a lock that protects no data, and exists only as a - * placeholder. This is used for `glimpse' requests. A phantom lock - * might get promoted to real lock at some point. - */ - CLM_PHANTOM, CLM_READ, CLM_WRITE, CLM_GROUP @@ -1114,12 +1096,6 @@ static inline struct page *cl_page_vmpage(struct cl_page *page) * (struct cl_lock) and a list of layers (struct cl_lock_slice), linked to * cl_lock::cll_layers list through cl_lock_slice::cls_linkage. * - * All locks for a given object are linked into cl_object_header::coh_locks - * list (protected by cl_object_header::coh_lock_guard spin-lock) through - * cl_lock::cll_linkage. Currently this list is not sorted in any way. We can - * sort it in starting lock offset, or use altogether different data structure - * like a tree. - * * Typical cl_lock consists of the two layers: * * - vvp_lock (vvp specific data), and @@ -1320,289 +1296,21 @@ struct cl_lock_descr { __u32 cld_enq_flags; }; -#define DDESCR "%s(%d):[%lu, %lu]" +#define DDESCR "%s(%d):[%lu, %lu]:%x" #define PDESCR(descr) \ cl_lock_mode_name((descr)->cld_mode), (descr)->cld_mode, \ - (descr)->cld_start, (descr)->cld_end + (descr)->cld_start, (descr)->cld_end, (descr)->cld_enq_flags const char *cl_lock_mode_name(const enum cl_lock_mode mode); -/** - * Lock state-machine states. - * - * \htmlonly - *
- *
- * Possible state transitions:
- *
- *	      +------------------>NEW
- *	      |		    |
- *	      |		    | cl_enqueue_try()
- *	      |		    |
- *	      |    cl_unuse_try()  V
- *	      |  +--------------QUEUING (*)
- *	      |  |		 |
- *	      |  |		 | cl_enqueue_try()
- *	      |  |		 |
- *	      |  | cl_unuse_try()  V
- *    sub-lock  |  +-------------ENQUEUED (*)
- *    canceled  |  |		 |
- *	      |  |		 | cl_wait_try()
- *	      |  |		 |
- *	      |  |		(R)
- *	      |  |		 |
- *	      |  |		 V
- *	      |  |		HELD<---------+
- *	      |  |		 |	    |
- *	      |  |		 |	    | cl_use_try()
- *	      |  |  cl_unuse_try() |	    |
- *	      |  |		 |	    |
- *	      |  |		 V	 ---+
- *	      |  +------------>INTRANSIT (D) <--+
- *	      |		    |	    |
- *	      |     cl_unuse_try() |	    | cached lock found
- *	      |		    |	    | cl_use_try()
- *	      |		    |	    |
- *	      |		    V	    |
- *	      +------------------CACHED---------+
- *				   |
- *				  (C)
- *				   |
- *				   V
- *				FREEING
- *
- * Legend:
- *
- *	 In states marked with (*) transition to the same state (i.e., a loop
- *	 in the diagram) is possible.
- *
- *	 (R) is the point where Receive call-back is invoked: it allows layers
- *	 to handle arrival of lock reply.
- *
- *	 (C) is the point where Cancellation call-back is invoked.
- *
- *	 (D) is the transit state which means the lock is changing.
- *
- *	 Transition to FREEING state is possible from any other state in the
- *	 diagram in case of unrecoverable error.
- * 
- * \endhtmlonly - * - * These states are for individual cl_lock object. Top-lock and its sub-locks - * can be in the different states. Another way to say this is that we have - * nested state-machines. - * - * Separate QUEUING and ENQUEUED states are needed to support non-blocking - * operation for locks with multiple sub-locks. Imagine lock on a file F, that - * intersects 3 stripes S0, S1, and S2. To enqueue F client has to send - * enqueue to S0, wait for its completion, then send enqueue for S1, wait for - * its completion and at last enqueue lock for S2, and wait for its - * completion. In that case, top-lock is in QUEUING state while S0, S1 are - * handled, and is in ENQUEUED state after enqueue to S2 has been sent (note - * that in this case, sub-locks move from state to state, and top-lock remains - * in the same state). - */ -enum cl_lock_state { - /** - * Lock that wasn't yet enqueued - */ - CLS_NEW, - /** - * Enqueue is in progress, blocking for some intermediate interaction - * with the other side. - */ - CLS_QUEUING, - /** - * Lock is fully enqueued, waiting for server to reply when it is - * granted. - */ - CLS_ENQUEUED, - /** - * Lock granted, actively used by some IO. - */ - CLS_HELD, - /** - * This state is used to mark the lock is being used, or unused. - * We need this state because the lock may have several sublocks, - * so it's impossible to have an atomic way to bring all sublocks - * into CLS_HELD state at use case, or all sublocks to CLS_CACHED - * at unuse case. - * If a thread is referring to a lock, and it sees the lock is in this - * state, it must wait for the lock. - * See state diagram for details. - */ - CLS_INTRANSIT, - /** - * Lock granted, not used. - */ - CLS_CACHED, - /** - * Lock is being destroyed. - */ - CLS_FREEING, - CLS_NR -}; - -enum cl_lock_flags { - /** - * lock has been cancelled. This flag is never cleared once set (by - * cl_lock_cancel0()). - */ - CLF_CANCELLED = 1 << 0, - /** cancellation is pending for this lock. */ - CLF_CANCELPEND = 1 << 1, - /** destruction is pending for this lock. */ - CLF_DOOMED = 1 << 2, - /** from enqueue RPC reply upcall. */ - CLF_FROM_UPCALL = 1 << 3, -}; - -/** - * Lock closure. - * - * Lock closure is a collection of locks (both top-locks and sub-locks) that - * might be updated in a result of an operation on a certain lock (which lock - * this is a closure of). - * - * Closures are needed to guarantee dead-lock freedom in the presence of - * - * - nested state-machines (top-lock state-machine composed of sub-lock - * state-machines), and - * - * - shared sub-locks. - * - * Specifically, many operations, such as lock enqueue, wait, unlock, - * etc. start from a top-lock, and then operate on a sub-locks of this - * top-lock, holding a top-lock mutex. When sub-lock state changes as a result - * of such operation, this change has to be propagated to all top-locks that - * share this sub-lock. Obviously, no natural lock ordering (e.g., - * top-to-bottom or bottom-to-top) captures this scenario, so try-locking has - * to be used. Lock closure systematizes this try-and-repeat logic. - */ -struct cl_lock_closure { - /** - * Lock that is mutexed when closure construction is started. When - * closure in is `wait' mode (cl_lock_closure::clc_wait), mutex on - * origin is released before waiting. - */ - struct cl_lock *clc_origin; - /** - * List of enclosed locks, so far. Locks are linked here through - * cl_lock::cll_inclosure. - */ - struct list_head clc_list; - /** - * True iff closure is in a `wait' mode. This determines what - * cl_lock_enclosure() does when a lock L to be added to the closure - * is currently mutexed by some other thread. - * - * If cl_lock_closure::clc_wait is not set, then closure construction - * fails with CLO_REPEAT immediately. - * - * In wait mode, cl_lock_enclosure() waits until next attempt to build - * a closure might succeed. To this end it releases an origin mutex - * (cl_lock_closure::clc_origin), that has to be the only lock mutex - * owned by the current thread, and then waits on L mutex (by grabbing - * it and immediately releasing), before returning CLO_REPEAT to the - * caller. - */ - int clc_wait; - /** Number of locks in the closure. */ - int clc_nr; -}; - /** * Layered client lock. */ struct cl_lock { - /** Reference counter. */ - atomic_t cll_ref; /** List of slices. Immutable after creation. */ struct list_head cll_layers; - /** - * Linkage into cl_lock::cll_descr::cld_obj::coh_locks list. Protected - * by cl_lock::cll_descr::cld_obj::coh_lock_guard. - */ - struct list_head cll_linkage; - /** - * Parameters of this lock. Protected by - * cl_lock::cll_descr::cld_obj::coh_lock_guard nested within - * cl_lock::cll_guard. Modified only on lock creation and in - * cl_lock_modify(). - */ + /** lock attribute, extent, cl_object, etc. */ struct cl_lock_descr cll_descr; - /** Protected by cl_lock::cll_guard. */ - enum cl_lock_state cll_state; - /** signals state changes. */ - wait_queue_head_t cll_wq; - /** - * Recursive lock, most fields in cl_lock{} are protected by this. - * - * Locking rules: this mutex is never held across network - * communication, except when lock is being canceled. - * - * Lock ordering: a mutex of a sub-lock is taken first, then a mutex - * on a top-lock. Other direction is implemented through a - * try-lock-repeat loop. Mutices of unrelated locks can be taken only - * by try-locking. - * - * \see osc_lock_enqueue_wait(), lov_lock_cancel(), lov_sublock_wait(). - */ - struct mutex cll_guard; - struct task_struct *cll_guarder; - int cll_depth; - - /** - * the owner for INTRANSIT state - */ - struct task_struct *cll_intransit_owner; - int cll_error; - /** - * Number of holds on a lock. A hold prevents a lock from being - * canceled and destroyed. Protected by cl_lock::cll_guard. - * - * \see cl_lock_hold(), cl_lock_unhold(), cl_lock_release() - */ - int cll_holds; - /** - * Number of lock users. Valid in cl_lock_state::CLS_HELD state - * only. Lock user pins lock in CLS_HELD state. Protected by - * cl_lock::cll_guard. - * - * \see cl_wait(), cl_unuse(). - */ - int cll_users; - /** - * Flag bit-mask. Values from enum cl_lock_flags. Updates are - * protected by cl_lock::cll_guard. - */ - unsigned long cll_flags; - /** - * A linkage into a list of locks in a closure. - * - * \see cl_lock_closure - */ - struct list_head cll_inclosure; - /** - * Confict lock at queuing time. - */ - struct cl_lock *cll_conflict; - /** - * A list of references to this lock, for debugging. - */ - struct lu_ref cll_reference; - /** - * A list of holds on this lock, for debugging. - */ - struct lu_ref cll_holders; - /** - * A reference for cl_lock::cll_descr::cld_obj. For debugging. - */ - struct lu_ref_link cll_obj_ref; -#ifdef CONFIG_LOCKDEP - /* "dep_map" name is assumed by lockdep.h macros. */ - struct lockdep_map dep_map; -#endif }; /** @@ -1621,171 +1329,33 @@ struct cl_lock_slice { struct list_head cls_linkage; }; -/** - * Possible (non-error) return values of ->clo_{enqueue,wait,unlock}(). - * - * NOTE: lov_subresult() depends on ordering here. - */ -enum cl_lock_transition { - /** operation cannot be completed immediately. Wait for state change. */ - CLO_WAIT = 1, - /** operation had to release lock mutex, restart. */ - CLO_REPEAT = 2, - /** lower layer re-enqueued. */ - CLO_REENQUEUED = 3, -}; - /** * * \see vvp_lock_ops, lov_lock_ops, lovsub_lock_ops, osc_lock_ops */ struct cl_lock_operations { - /** - * \name statemachine - * - * State machine transitions. These 3 methods are called to transfer - * lock from one state to another, as described in the commentary - * above enum #cl_lock_state. - * - * \retval 0 this layer has nothing more to do to before - * transition to the target state happens; - * - * \retval CLO_REPEAT method had to release and re-acquire cl_lock - * mutex, repeat invocation of transition method - * across all layers; - * - * \retval CLO_WAIT this layer cannot move to the target state - * immediately, as it has to wait for certain event - * (e.g., the communication with the server). It - * is guaranteed, that when the state transfer - * becomes possible, cl_lock::cll_wq wait-queue - * is signaled. Caller can wait for this event by - * calling cl_lock_state_wait(); - * - * \retval -ve failure, abort state transition, move the lock - * into cl_lock_state::CLS_FREEING state, and set - * cl_lock::cll_error. - * - * Once all layers voted to agree to transition (by returning 0), lock - * is moved into corresponding target state. All state transition - * methods are optional. - */ /** @{ */ /** * Attempts to enqueue the lock. Called top-to-bottom. * + * \retval 0 this layer has enqueued the lock successfully + * \retval >0 this layer has enqueued the lock, but need to wait on + * @anchor for resources + * \retval -ve failure + * * \see ccc_lock_enqueue(), lov_lock_enqueue(), lovsub_lock_enqueue(), * \see osc_lock_enqueue() */ int (*clo_enqueue)(const struct lu_env *env, const struct cl_lock_slice *slice, - struct cl_io *io, __u32 enqflags); - /** - * Attempts to wait for enqueue result. Called top-to-bottom. - * - * \see ccc_lock_wait(), lov_lock_wait(), osc_lock_wait() - */ - int (*clo_wait)(const struct lu_env *env, - const struct cl_lock_slice *slice); - /** - * Attempts to unlock the lock. Called bottom-to-top. In addition to - * usual return values of lock state-machine methods, this can return - * -ESTALE to indicate that lock cannot be returned to the cache, and - * has to be re-initialized. - * unuse is a one-shot operation, so it must NOT return CLO_WAIT. - * - * \see ccc_lock_unuse(), lov_lock_unuse(), osc_lock_unuse() - */ - int (*clo_unuse)(const struct lu_env *env, - const struct cl_lock_slice *slice); - /** - * Notifies layer that cached lock is started being used. - * - * \pre lock->cll_state == CLS_CACHED - * - * \see lov_lock_use(), osc_lock_use() - */ - int (*clo_use)(const struct lu_env *env, - const struct cl_lock_slice *slice); - /** @} statemachine */ - /** - * A method invoked when lock state is changed (as a result of state - * transition). This is used, for example, to track when the state of - * a sub-lock changes, to propagate this change to the corresponding - * top-lock. Optional - * - * \see lovsub_lock_state() - */ - void (*clo_state)(const struct lu_env *env, - const struct cl_lock_slice *slice, - enum cl_lock_state st); - /** - * Returns true, iff given lock is suitable for the given io, idea - * being, that there are certain "unsafe" locks, e.g., ones acquired - * for O_APPEND writes, that we don't want to re-use for a normal - * write, to avoid the danger of cascading evictions. Optional. Runs - * under cl_object_header::coh_lock_guard. - * - * XXX this should take more information about lock needed by - * io. Probably lock description or something similar. - * - * \see lov_fits_into() - */ - int (*clo_fits_into)(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *need, - const struct cl_io *io); - /** - * \name ast - * Asynchronous System Traps. All of then are optional, all are - * executed bottom-to-top. - */ - /** @{ */ - + struct cl_io *io, struct cl_sync_io *anchor); /** - * Cancellation callback. Cancel a lock voluntarily, or under - * the request of server. + * Cancel a lock, release its DLM lock ref, while does not cancel the + * DLM lock */ void (*clo_cancel)(const struct lu_env *env, const struct cl_lock_slice *slice); - /** - * Lock weighting ast. Executed to estimate how precious this lock - * is. The sum of results across all layers is used to determine - * whether lock worth keeping in cache given present memory usage. - * - * \see osc_lock_weigh(), vvp_lock_weigh(), lovsub_lock_weigh(). - */ - unsigned long (*clo_weigh)(const struct lu_env *env, - const struct cl_lock_slice *slice); - /** @} ast */ - - /** - * \see lovsub_lock_closure() - */ - int (*clo_closure)(const struct lu_env *env, - const struct cl_lock_slice *slice, - struct cl_lock_closure *closure); - /** - * Executed bottom-to-top when lock description changes (e.g., as a - * result of server granting more generous lock than was requested). - * - * \see lovsub_lock_modify() - */ - int (*clo_modify)(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *updated); - /** - * Notifies layers (bottom-to-top) that lock is going to be - * destroyed. Responsibility of layers is to prevent new references on - * this lock from being acquired once this method returns. - * - * This can be called multiple times due to the races. - * - * \see cl_lock_delete() - * \see osc_lock_delete(), lovsub_lock_delete() - */ - void (*clo_delete)(const struct lu_env *env, - const struct cl_lock_slice *slice); + /** @} */ /** * Destructor. Frees resources and the slice. * @@ -2164,10 +1734,14 @@ enum cl_enq_flags { * for async glimpse lock. */ CEF_AGL = 0x00000020, + /** + * enqueue a lock to test DLM lock existence. + */ + CEF_PEEK = 0x00000040, /** * mask of enq_flags. */ - CEF_MASK = 0x0000003f, + CEF_MASK = 0x0000007f, }; /** @@ -2177,12 +1751,12 @@ enum cl_enq_flags { struct cl_io_lock_link { /** linkage into one of cl_lockset lists. */ struct list_head cill_linkage; - struct cl_lock_descr cill_descr; - struct cl_lock *cill_lock; + struct cl_lock cill_lock; /** optional destructor */ void (*cill_fini)(const struct lu_env *env, struct cl_io_lock_link *link); }; +#define cill_descr cill_lock.cll_descr /** * Lock-set represents a collection of locks, that io needs at a @@ -2216,8 +1790,6 @@ struct cl_io_lock_link { struct cl_lockset { /** locks to be acquired. */ struct list_head cls_todo; - /** locks currently being processed. */ - struct list_head cls_curr; /** locks acquired. */ struct list_head cls_done; }; @@ -2581,9 +2153,7 @@ struct cl_site { * and top-locks (and top-pages) are accounted here. */ struct cache_stats cs_pages; - struct cache_stats cs_locks; atomic_t cs_pages_state[CPS_NR]; - atomic_t cs_locks_state[CLS_NR]; }; int cl_site_init(struct cl_site *s, struct cl_device *top); @@ -2707,7 +2277,7 @@ int cl_object_glimpse(const struct lu_env *env, struct cl_object *obj, struct ost_lvb *lvb); int cl_conf_set(const struct lu_env *env, struct cl_object *obj, const struct cl_object_conf *conf); -void cl_object_prune(const struct lu_env *env, struct cl_object *obj); +int cl_object_prune(const struct lu_env *env, struct cl_object *obj); void cl_object_kill(const struct lu_env *env, struct cl_object *obj); /** @@ -2845,121 +2415,17 @@ void cl_lock_descr_print(const struct lu_env *env, void *cookie, * @{ */ -struct cl_lock *cl_lock_hold(const struct lu_env *env, const struct cl_io *io, - const struct cl_lock_descr *need, - const char *scope, const void *source); -struct cl_lock *cl_lock_peek(const struct lu_env *env, const struct cl_io *io, - const struct cl_lock_descr *need, - const char *scope, const void *source); -struct cl_lock *cl_lock_request(const struct lu_env *env, struct cl_io *io, - const struct cl_lock_descr *need, - const char *scope, const void *source); -struct cl_lock *cl_lock_at_pgoff(const struct lu_env *env, - struct cl_object *obj, pgoff_t index, - struct cl_lock *except, int pending, - int canceld); +int cl_lock_request(const struct lu_env *env, struct cl_io *io, + struct cl_lock *lock); +int cl_lock_init(const struct lu_env *env, struct cl_lock *lock, + const struct cl_io *io); +void cl_lock_fini(const struct lu_env *env, struct cl_lock *lock); const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock, const struct lu_device_type *dtype); - -void cl_lock_get(struct cl_lock *lock); -void cl_lock_get_trust(struct cl_lock *lock); -void cl_lock_put(const struct lu_env *env, struct cl_lock *lock); -void cl_lock_hold_add(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source); -void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source); -void cl_lock_unhold(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source); -void cl_lock_release(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source); -void cl_lock_user_add(const struct lu_env *env, struct cl_lock *lock); -void cl_lock_user_del(const struct lu_env *env, struct cl_lock *lock); - -int cl_lock_is_intransit(struct cl_lock *lock); - -int cl_lock_enqueue_wait(const struct lu_env *env, struct cl_lock *lock, - int keep_mutex); - -/** \name statemachine statemachine - * Interface to lock state machine consists of 3 parts: - * - * - "try" functions that attempt to effect a state transition. If state - * transition is not possible right now (e.g., if it has to wait for some - * asynchronous event to occur), these functions return - * cl_lock_transition::CLO_WAIT. - * - * - "non-try" functions that implement synchronous blocking interface on - * top of non-blocking "try" functions. These functions repeatedly call - * corresponding "try" versions, and if state transition is not possible - * immediately, wait for lock state change. - * - * - methods from cl_lock_operations, called by "try" functions. Lock can - * be advanced to the target state only when all layers voted that they - * are ready for this transition. "Try" functions call methods under lock - * mutex. If a layer had to release a mutex, it re-acquires it and returns - * cl_lock_transition::CLO_REPEAT, causing "try" function to call all - * layers again. - * - * TRY NON-TRY METHOD FINAL STATE - * - * cl_enqueue_try() cl_enqueue() cl_lock_operations::clo_enqueue() CLS_ENQUEUED - * - * cl_wait_try() cl_wait() cl_lock_operations::clo_wait() CLS_HELD - * - * cl_unuse_try() cl_unuse() cl_lock_operations::clo_unuse() CLS_CACHED - * - * cl_use_try() NONE cl_lock_operations::clo_use() CLS_HELD - * - * @{ - */ - -int cl_wait(const struct lu_env *env, struct cl_lock *lock); -void cl_unuse(const struct lu_env *env, struct cl_lock *lock); -int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock, - struct cl_io *io, __u32 flags); -int cl_unuse_try(const struct lu_env *env, struct cl_lock *lock); -int cl_wait_try(const struct lu_env *env, struct cl_lock *lock); -int cl_use_try(const struct lu_env *env, struct cl_lock *lock, int atomic); - -/** @} statemachine */ - -void cl_lock_signal(const struct lu_env *env, struct cl_lock *lock); -int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock); -void cl_lock_state_set(const struct lu_env *env, struct cl_lock *lock, - enum cl_lock_state state); -int cl_queue_match(const struct list_head *queue, - const struct cl_lock_descr *need); - -void cl_lock_mutex_get(const struct lu_env *env, struct cl_lock *lock); -void cl_lock_mutex_put(const struct lu_env *env, struct cl_lock *lock); -int cl_lock_is_mutexed(struct cl_lock *lock); -int cl_lock_nr_mutexed(const struct lu_env *env); -int cl_lock_discard_pages(const struct lu_env *env, struct cl_lock *lock); -int cl_lock_ext_match(const struct cl_lock_descr *has, - const struct cl_lock_descr *need); -int cl_lock_descr_match(const struct cl_lock_descr *has, - const struct cl_lock_descr *need); -int cl_lock_mode_match(enum cl_lock_mode has, enum cl_lock_mode need); -int cl_lock_modify(const struct lu_env *env, struct cl_lock *lock, - const struct cl_lock_descr *desc); - -void cl_lock_closure_init(const struct lu_env *env, - struct cl_lock_closure *closure, - struct cl_lock *origin, int wait); -void cl_lock_closure_fini(struct cl_lock_closure *closure); -int cl_lock_closure_build(const struct lu_env *env, struct cl_lock *lock, - struct cl_lock_closure *closure); -void cl_lock_disclosure(const struct lu_env *env, - struct cl_lock_closure *closure); -int cl_lock_enclosure(const struct lu_env *env, struct cl_lock *lock, - struct cl_lock_closure *closure); - +void cl_lock_release(const struct lu_env *env, struct cl_lock *lock); +int cl_lock_enqueue(const struct lu_env *env, struct cl_io *io, + struct cl_lock *lock, struct cl_sync_io *anchor); void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock); -void cl_lock_delete(const struct lu_env *env, struct cl_lock *lock); -void cl_lock_error(const struct lu_env *env, struct cl_lock *lock, int error); -void cl_locks_prune(const struct lu_env *env, struct cl_object *obj, int wait); - -unsigned long cl_lock_weigh(const struct lu_env *env, struct cl_lock *lock); /** @} cl_lock */ diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index a8c8788ebc07..82af8aeb7212 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -98,10 +98,6 @@ struct ccc_io { int cui_to; } write; } u; - /** - * True iff io is processing glimpse right now. - */ - int cui_glimpse; /** * Layout version when this IO is initialized */ @@ -123,6 +119,7 @@ extern struct lu_context_key ccc_key; extern struct lu_context_key ccc_session_key; struct ccc_thread_info { + struct cl_lock cti_lock; struct cl_lock_descr cti_descr; struct cl_io cti_io; struct cl_attr cti_attr; @@ -137,6 +134,14 @@ static inline struct ccc_thread_info *ccc_env_info(const struct lu_env *env) return info; } +static inline struct cl_lock *ccc_env_lock(const struct lu_env *env) +{ + struct cl_lock *lock = &ccc_env_info(env)->cti_lock; + + memset(lock, 0, sizeof(*lock)); + return lock; +} + static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) { struct cl_attr *attr = &ccc_env_info(env)->cti_attr; @@ -308,18 +313,7 @@ void ccc_lock_delete(const struct lu_env *env, void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); int ccc_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, - struct cl_io *io, __u32 enqflags); -int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice); -int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice); -int ccc_lock_wait(const struct lu_env *env, const struct cl_lock_slice *slice); -int ccc_lock_fits_into(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *need, - const struct cl_io *io); -void ccc_lock_state(const struct lu_env *env, - const struct cl_lock_slice *slice, - enum cl_lock_state state); - + struct cl_io *io, struct cl_sync_io *anchor); int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, __u32 enqflags, enum cl_lock_mode mode, pgoff_t start, pgoff_t end); diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index da8bc6eadd13..4318511de0c9 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2582,6 +2582,8 @@ struct ldlm_extent { __u64 gid; }; +#define LDLM_GID_ANY ((__u64)-1) + static inline int ldlm_extent_overlap(struct ldlm_extent *ex1, struct ldlm_extent *ex2) { diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index 8b0364f71129..b1abdc28b261 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -71,6 +71,7 @@ struct obd_device; */ enum ldlm_error { ELDLM_OK = 0, + ELDLM_LOCK_MATCHED = 1, ELDLM_LOCK_CHANGED = 300, ELDLM_LOCK_ABORTED = 301, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index b497ce4f844a..7fedbec43ebf 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -748,6 +748,7 @@ int ldlm_error2errno(enum ldlm_error error) switch (error) { case ELDLM_OK: + case ELDLM_LOCK_MATCHED: result = 0; break; case ELDLM_LOCK_CHANGED: diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index ecd65a7a3dc9..27a051b085b5 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -657,7 +657,7 @@ void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode) struct ldlm_lock *lock; lock = ldlm_handle2lock(lockh); - LASSERT(lock); + LASSERTF(lock, "Non-existing lock: %llx\n", lockh->cookie); ldlm_lock_addref_internal(lock, mode); LDLM_LOCK_PUT(lock); } @@ -1092,6 +1092,7 @@ static struct ldlm_lock *search_queue(struct list_head *queue, if (unlikely(match == LCK_GROUP) && lock->l_resource->lr_type == LDLM_EXTENT && + policy->l_extent.gid != LDLM_GID_ANY && lock->l_policy_data.l_extent.gid != policy->l_extent.gid) continue; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index d5968e01edd8..42925ac3331c 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -347,7 +347,6 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, struct ldlm_lock *lock; struct ldlm_reply *reply; int cleanup_phase = 1; - int size = 0; lock = ldlm_handle2lock(lockh); /* ldlm_cli_enqueue is holding a reference on this lock. */ @@ -375,8 +374,8 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, goto cleanup; } - if (lvb_len != 0) { - LASSERT(lvb); + if (lvb_len > 0) { + int size = 0; size = req_capsule_get_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER); @@ -390,12 +389,13 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, rc = -EINVAL; goto cleanup; } + lvb_len = size; } if (rc == ELDLM_LOCK_ABORTED) { - if (lvb_len != 0) + if (lvb_len > 0 && lvb) rc = ldlm_fill_lvb(lock, &req->rq_pill, RCL_SERVER, - lvb, size); + lvb, lvb_len); if (rc == 0) rc = ELDLM_LOCK_ABORTED; goto cleanup; @@ -489,7 +489,7 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, /* If the lock has already been granted by a completion AST, don't * clobber the LVB with an older one. */ - if (lvb_len != 0) { + if (lvb_len > 0) { /* We must lock or a racing completion might update lvb without * letting us know and we'll clobber the correct value. * Cannot unlock after the check either, as that still leaves @@ -498,7 +498,7 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, lock_res_and_lock(lock); if (lock->l_req_mode != lock->l_granted_mode) rc = ldlm_fill_lvb(lock, &req->rq_pill, RCL_SERVER, - lock->l_lvb_data, size); + lock->l_lvb_data, lvb_len); unlock_res_and_lock(lock); if (rc < 0) { cleanup_phase = 1; @@ -518,7 +518,7 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, } } - if (lvb_len && lvb) { + if (lvb_len > 0 && lvb) { /* Copy the LVB here, and not earlier, because the completion * AST (if any) can override what we got in the reply */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 9dede87ad0a3..242a6640bff6 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -1400,3 +1400,4 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res) LDLM_DEBUG_LIMIT(level, lock, "###"); } } +EXPORT_SYMBOL(ldlm_resource_dump); diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index 9b0e2ec0cf05..0759dfc1995a 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -86,17 +86,17 @@ blkcnt_t dirty_cnt(struct inode *inode) int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, struct inode *inode, struct cl_object *clob, int agl) { - struct cl_lock_descr *descr = &ccc_env_info(env)->cti_descr; struct ll_inode_info *lli = ll_i2info(inode); const struct lu_fid *fid = lu_object_fid(&clob->co_lu); - struct ccc_io *cio = ccc_env_io(env); - struct cl_lock *lock; int result; result = 0; if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) { CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid)); if (lli->lli_has_smd) { + struct cl_lock *lock = ccc_env_lock(env); + struct cl_lock_descr *descr = &lock->cll_descr; + /* NOTE: this looks like DLM lock request, but it may * not be one. Due to CEF_ASYNC flag (translated * to LDLM_FL_HAS_INTENT by osc), this is @@ -113,11 +113,10 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, */ *descr = whole_file; descr->cld_obj = clob; - descr->cld_mode = CLM_PHANTOM; + descr->cld_mode = CLM_READ; descr->cld_enq_flags = CEF_ASYNC | CEF_MUST; if (agl) descr->cld_enq_flags |= CEF_AGL; - cio->cui_glimpse = 1; /* * CEF_ASYNC is used because glimpse sub-locks cannot * deadlock (because they never conflict with other @@ -126,19 +125,11 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, * CEF_MUST protects glimpse lock from conversion into * a lockless mode. */ - lock = cl_lock_request(env, io, descr, "glimpse", - current); - cio->cui_glimpse = 0; - - if (!lock) - return 0; + result = cl_lock_request(env, io, lock); + if (result < 0) + return result; - if (IS_ERR(lock)) - return PTR_ERR(lock); - - LASSERT(agl == 0); - result = cl_wait(env, lock); - if (result == 0) { + if (!agl) { ll_merge_attr(env, inode); if (i_size_read(inode) > 0 && inode->i_blocks == 0) { @@ -150,9 +141,8 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, */ inode->i_blocks = dirty_cnt(inode); } - cl_unuse(env, lock); } - cl_lock_release(env, lock, "glimpse", current); + cl_lock_release(env, lock); } else { CDEBUG(D_DLMTRACE, "No objects for inode\n"); ll_merge_attr(env, inode); @@ -233,10 +223,7 @@ int cl_local_size(struct inode *inode) { struct lu_env *env = NULL; struct cl_io *io = NULL; - struct ccc_thread_info *cti; struct cl_object *clob; - struct cl_lock_descr *descr; - struct cl_lock *lock; int result; int refcheck; @@ -252,19 +239,15 @@ int cl_local_size(struct inode *inode) if (result > 0) { result = io->ci_result; } else if (result == 0) { - cti = ccc_env_info(env); - descr = &cti->cti_descr; + struct cl_lock *lock = ccc_env_lock(env); - *descr = whole_file; - descr->cld_obj = clob; - lock = cl_lock_peek(env, io, descr, "localsize", current); - if (lock) { + lock->cll_descr = whole_file; + lock->cll_descr.cld_enq_flags = CEF_PEEK; + lock->cll_descr.cld_obj = clob; + result = cl_lock_request(env, io, lock); + if (result == 0) { ll_merge_attr(env, inode); - cl_unuse(env, lock); - cl_lock_release(env, lock, "localsize", current); - result = 0; - } else { - result = -ENODATA; + cl_lock_release(env, lock); } } cl_io_fini(env, io); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index fde96d374f49..b339d1bfc5c4 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -475,12 +475,6 @@ int ccc_transient_page_prep(const struct lu_env *env, * */ -void ccc_lock_delete(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); -} - void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice) { struct ccc_lock *clk = cl2ccc_lock(slice); @@ -490,111 +484,12 @@ void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice) int ccc_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, - struct cl_io *unused, __u32 enqflags) -{ - CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); - return 0; -} - -int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice) -{ - CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); - return 0; -} - -int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice) + struct cl_io *unused, struct cl_sync_io *anchor) { CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); return 0; } -int ccc_lock_wait(const struct lu_env *env, const struct cl_lock_slice *slice) -{ - CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); - return 0; -} - -/** - * Implementation of cl_lock_operations::clo_fits_into() methods for ccc - * layer. This function is executed every time io finds an existing lock in - * the lock cache while creating new lock. This function has to decide whether - * cached lock "fits" into io. - * - * \param slice lock to be checked - * \param io IO that wants a lock. - * - * \see lov_lock_fits_into(). - */ -int ccc_lock_fits_into(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *need, - const struct cl_io *io) -{ - const struct cl_lock *lock = slice->cls_lock; - const struct cl_lock_descr *descr = &lock->cll_descr; - const struct ccc_io *cio = ccc_env_io(env); - int result; - - /* - * Work around DLM peculiarity: it assumes that glimpse - * (LDLM_FL_HAS_INTENT) lock is always LCK_PR, and returns reads lock - * when asked for LCK_PW lock with LDLM_FL_HAS_INTENT flag set. Make - * sure that glimpse doesn't get CLM_WRITE top-lock, so that it - * doesn't enqueue CLM_WRITE sub-locks. - */ - if (cio->cui_glimpse) - result = descr->cld_mode != CLM_WRITE; - - /* - * Also, don't match incomplete write locks for read, otherwise read - * would enqueue missing sub-locks in the write mode. - */ - else if (need->cld_mode != descr->cld_mode) - result = lock->cll_state >= CLS_ENQUEUED; - else - result = 1; - return result; -} - -/** - * Implements cl_lock_operations::clo_state() method for ccc layer, invoked - * whenever lock state changes. Transfers object attributes, that might be - * updated as a result of lock acquiring into inode. - */ -void ccc_lock_state(const struct lu_env *env, - const struct cl_lock_slice *slice, - enum cl_lock_state state) -{ - struct cl_lock *lock = slice->cls_lock; - - /* - * Refresh inode attributes when the lock is moving into CLS_HELD - * state, and only when this is a result of real enqueue, rather than - * of finding lock in the cache. - */ - if (state == CLS_HELD && lock->cll_state < CLS_HELD) { - struct cl_object *obj; - struct inode *inode; - - obj = slice->cls_obj; - inode = ccc_object_inode(obj); - - /* vmtruncate() sets the i_size - * under both a DLM lock and the - * ll_inode_size_lock(). If we don't get the - * ll_inode_size_lock() here we can match the DLM lock and - * reset i_size. generic_file_write can then trust the - * stale i_size when doing appending writes and effectively - * cancel the result of the truncate. Getting the - * ll_inode_size_lock() after the enqueue maintains the DLM - * -> ll_inode_size_lock() acquiring order. - */ - if (lock->cll_descr.cld_start == 0 && - lock->cll_descr.cld_end == CL_PAGE_EOF) - ll_merge_attr(env, inode); - } -} - /***************************************************************************** * * io operations. diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index f68c3687b1d9..4c12e219ffcc 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -145,7 +145,7 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, io->ci_ignore_layout = 1; rc = cl_io_init(env, io, CIT_MISC, io->ci_obj); - if (rc) { + if (rc != 0) { cl_io_fini(env, io); cl_env_put(env, &refcheck); /* Does not make sense to take GL for released layout */ @@ -154,7 +154,8 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, return rc; } - descr = &ccc_env_info(env)->cti_descr; + lock = ccc_env_lock(env); + descr = &lock->cll_descr; descr->cld_obj = obj; descr->cld_start = 0; descr->cld_end = CL_PAGE_EOF; @@ -164,11 +165,11 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, enqflags = CEF_MUST | (nonblock ? CEF_NONBLOCK : 0); descr->cld_enq_flags = enqflags; - lock = cl_lock_request(env, io, descr, GROUPLOCK_SCOPE, current); - if (IS_ERR(lock)) { + rc = cl_lock_request(env, io, lock); + if (rc < 0) { cl_io_fini(env, io); cl_env_put(env, &refcheck); - return PTR_ERR(lock); + return rc; } cg->cg_env = cl_env_get(&refcheck); @@ -194,8 +195,7 @@ void cl_put_grouplock(struct ccc_grouplock *cg) cl_env_implant(env, &refcheck); cl_env_put(env, &refcheck); - cl_unuse(env, lock); - cl_lock_release(env, lock, GROUPLOCK_SCOPE, current); + cl_lock_release(env, lock); cl_io_fini(env, io); cl_env_put(env, NULL); } diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index e2fea8c7a4fe..50d8289afe06 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -150,8 +150,7 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask) * If this page holds the last refc of cl_object, the following * call path may cause reschedule: * cl_page_put -> cl_page_free -> cl_object_put -> - * lu_object_put -> lu_object_free -> lov_delete_raid0 -> - * cl_locks_prune. + * lu_object_put -> lu_object_free -> lov_delete_raid0. * * However, the kernel can't get rid of this inode until all pages have * been cleaned up. Now that we hold page lock here, it's pretty safe diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index c7db318b8ece..fb6f93225b99 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -233,7 +233,7 @@ static int vvp_mmap_locks(const struct lu_env *env, ldlm_policy_data_t policy; unsigned long addr; ssize_t count; - int result; + int result = 0; struct iov_iter i; struct iovec iov; @@ -265,10 +265,10 @@ static int vvp_mmap_locks(const struct lu_env *env, if (ll_file_nolock(vma->vm_file)) { /* - * For no lock case, a lockless lock will be - * generated. + * For no lock case is not allowed for mmap */ - flags = CEF_NEVER; + result = -EINVAL; + break; } /* @@ -290,10 +290,8 @@ static int vvp_mmap_locks(const struct lu_env *env, descr->cld_mode, descr->cld_start, descr->cld_end); - if (result < 0) { - up_read(&mm->mmap_sem); - return result; - } + if (result < 0) + break; if (vma->vm_end - addr >= count) break; @@ -302,8 +300,10 @@ static int vvp_mmap_locks(const struct lu_env *env, addr = vma->vm_end; } up_read(&mm->mmap_sem); + if (result < 0) + break; } - return 0; + return result; } static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, @@ -781,6 +781,7 @@ static int vvp_io_write_start(const struct lu_env *env, * PARALLEL IO This has to be changed for parallel IO doing * out-of-order writes. */ + ll_merge_attr(env, inode); pos = io->u.ci_wr.wr.crw_pos = i_size_read(inode); cio->cui_iocb->ki_pos = pos; } else { diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index ff0948043c7a..8c505a6052b2 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -51,32 +51,9 @@ * */ -/** - * Estimates lock value for the purpose of managing the lock cache during - * memory shortages. - * - * Locks for memory mapped files are almost infinitely precious, others are - * junk. "Mapped locks" are heavy, but not infinitely heavy, so that they are - * ordered within themselves by weights assigned from other layers. - */ -static unsigned long vvp_lock_weigh(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct ccc_object *cob = cl2ccc(slice->cls_obj); - - return atomic_read(&cob->cob_mmap_cnt) > 0 ? ~0UL >> 2 : 0; -} - static const struct cl_lock_operations vvp_lock_ops = { - .clo_delete = ccc_lock_delete, .clo_fini = ccc_lock_fini, - .clo_enqueue = ccc_lock_enqueue, - .clo_wait = ccc_lock_wait, - .clo_use = ccc_lock_use, - .clo_unuse = ccc_lock_unuse, - .clo_fits_into = ccc_lock_fits_into, - .clo_state = ccc_lock_state, - .clo_weigh = vvp_lock_weigh + .clo_enqueue = ccc_lock_enqueue }; int vvp_lock_init(const struct lu_env *env, struct cl_object *obj, diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index d03eb2b59de7..34210dbc8cd2 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -170,11 +170,15 @@ static int vvp_prune(const struct lu_env *env, struct cl_object *obj) struct inode *inode = ccc_object_inode(obj); int rc; - rc = cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_ALL, 1); - if (rc == 0) - truncate_inode_pages(inode->i_mapping, 0); + rc = cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_LOCAL, 1); + if (rc < 0) { + CDEBUG(D_VFSTRACE, DFID ": writeback failed: %d\n", + PFID(lu_object_fid(&obj->co_lu)), rc); + return rc; + } - return rc; + truncate_inode_pages(inode->i_mapping, 0); + return 0; } static const struct cl_object_operations vvp_ops = { diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 9b3d13bf2a46..dfe41a82bdd2 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -280,25 +280,18 @@ struct lov_object { struct task_struct *lo_owner; }; -/** - * Flags that top-lock can set on each of its sub-locks. - */ -enum lov_sub_flags { - /** Top-lock acquired a hold (cl_lock_hold()) on a sub-lock. */ - LSF_HELD = 1 << 0 -}; - /** * State lov_lock keeps for each sub-lock. */ struct lov_lock_sub { /** sub-lock itself */ - struct lovsub_lock *sub_lock; - /** An array of per-sub-lock flags, taken from enum lov_sub_flags */ - unsigned sub_flags; + struct cl_lock sub_lock; + /** Set if the sublock has ever been enqueued, meaning it may + * hold resources of underlying layers + */ + unsigned int sub_is_enqueued:1, + sub_initialized:1; int sub_stripe; - struct cl_lock_descr sub_descr; - struct cl_lock_descr sub_got; }; /** @@ -308,59 +301,8 @@ struct lov_lock { struct cl_lock_slice lls_cl; /** Number of sub-locks in this lock */ int lls_nr; - /** - * Number of existing sub-locks. - */ - unsigned lls_nr_filled; - /** - * Set when sub-lock was canceled, while top-lock was being - * used, or unused. - */ - unsigned int lls_cancel_race:1; - /** - * An array of sub-locks - * - * There are two issues with managing sub-locks: - * - * - sub-locks are concurrently canceled, and - * - * - sub-locks are shared with other top-locks. - * - * To manage cancellation, top-lock acquires a hold on a sublock - * (lov_sublock_adopt()) when the latter is inserted into - * lov_lock::lls_sub[]. This hold is released (lov_sublock_release()) - * when top-lock is going into CLS_CACHED state or destroyed. Hold - * prevents sub-lock from cancellation. - * - * Sub-lock sharing means, among other things, that top-lock that is - * in the process of creation (i.e., not yet inserted into lock list) - * is already accessible to other threads once at least one of its - * sub-locks is created, see lov_lock_sub_init(). - * - * Sub-lock can be in one of the following states: - * - * - doesn't exist, lov_lock::lls_sub[]::sub_lock == NULL. Such - * sub-lock was either never created (top-lock is in CLS_NEW - * state), or it was created, then canceled, then destroyed - * (lov_lock_unlink() cleared sub-lock pointer in the top-lock). - * - * - sub-lock exists and is on - * hold. (lov_lock::lls_sub[]::sub_flags & LSF_HELD). This is a - * normal state of a sub-lock in CLS_HELD and CLS_CACHED states - * of a top-lock. - * - * - sub-lock exists, but is not held by the top-lock. This - * happens after top-lock released a hold on sub-locks before - * going into cache (lov_lock_unuse()). - * - * \todo To support wide-striping, array has to be replaced with a set - * of queues to avoid scanning. - */ - struct lov_lock_sub *lls_sub; - /** - * Original description with which lock was enqueued. - */ - struct cl_lock_descr lls_orig; + /** sublock array */ + struct lov_lock_sub lls_sub[0]; }; struct lov_page { @@ -445,7 +387,6 @@ struct lov_thread_info { struct ost_lvb lti_lvb; struct cl_2queue lti_cl2q; struct cl_page_list lti_plist; - struct cl_lock_closure lti_closure; wait_queue_t lti_waiter; struct cl_attr lti_attr; }; diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index 532ef87dfb44..dccc63496982 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -143,9 +143,7 @@ static void *lov_key_init(const struct lu_context *ctx, struct lov_thread_info *info; info = kmem_cache_zalloc(lov_thread_kmem, GFP_NOFS); - if (info) - INIT_LIST_HEAD(&info->lti_closure.clc_list); - else + if (!info) info = ERR_PTR(-ENOMEM); return info; } @@ -155,7 +153,6 @@ static void lov_key_fini(const struct lu_context *ctx, { struct lov_thread_info *info = data; - LINVRNT(list_empty(&info->lti_closure.clc_list)); kmem_cache_free(lov_thread_kmem, info); } diff --git a/drivers/staging/lustre/lustre/lov/lov_lock.c b/drivers/staging/lustre/lustre/lov/lov_lock.c index ae854bc25dbe..1b203d18c6e9 100644 --- a/drivers/staging/lustre/lustre/lov/lov_lock.c +++ b/drivers/staging/lustre/lustre/lov/lov_lock.c @@ -46,11 +46,6 @@ * @{ */ -static struct cl_lock_closure *lov_closure_get(const struct lu_env *env, - struct cl_lock *parent); - -static int lov_lock_unuse(const struct lu_env *env, - const struct cl_lock_slice *slice); /***************************************************************************** * * Lov lock operations. @@ -58,7 +53,7 @@ static int lov_lock_unuse(const struct lu_env *env, */ static struct lov_sublock_env *lov_sublock_env_get(const struct lu_env *env, - struct cl_lock *parent, + const struct cl_lock *parent, struct lov_lock_sub *lls) { struct lov_sublock_env *subenv; @@ -100,184 +95,25 @@ static void lov_sublock_env_put(struct lov_sublock_env *subenv) lov_sub_put(subenv->lse_sub); } -static void lov_sublock_adopt(const struct lu_env *env, struct lov_lock *lck, - struct cl_lock *sublock, int idx, - struct lov_lock_link *link) +static int lov_sublock_init(const struct lu_env *env, + const struct cl_lock *parent, + struct lov_lock_sub *lls) { - struct lovsub_lock *lsl; - struct cl_lock *parent = lck->lls_cl.cls_lock; - int rc; - - LASSERT(cl_lock_is_mutexed(parent)); - LASSERT(cl_lock_is_mutexed(sublock)); - - lsl = cl2sub_lock(sublock); - /* - * check that sub-lock doesn't have lock link to this top-lock. - */ - LASSERT(!lov_lock_link_find(env, lck, lsl)); - LASSERT(idx < lck->lls_nr); - - lck->lls_sub[idx].sub_lock = lsl; - lck->lls_nr_filled++; - LASSERT(lck->lls_nr_filled <= lck->lls_nr); - list_add_tail(&link->lll_list, &lsl->lss_parents); - link->lll_idx = idx; - link->lll_super = lck; - cl_lock_get(parent); - lu_ref_add(&parent->cll_reference, "lov-child", sublock); - lck->lls_sub[idx].sub_flags |= LSF_HELD; - cl_lock_user_add(env, sublock); - - rc = lov_sublock_modify(env, lck, lsl, &sublock->cll_descr, idx); - LASSERT(rc == 0); /* there is no way this can fail, currently */ -} - -static struct cl_lock *lov_sublock_alloc(const struct lu_env *env, - const struct cl_io *io, - struct lov_lock *lck, - int idx, struct lov_lock_link **out) -{ - struct cl_lock *sublock; - struct cl_lock *parent; - struct lov_lock_link *link; - - LASSERT(idx < lck->lls_nr); - - link = kmem_cache_zalloc(lov_lock_link_kmem, GFP_NOFS); - if (link) { - struct lov_sublock_env *subenv; - struct lov_lock_sub *lls; - struct cl_lock_descr *descr; - - parent = lck->lls_cl.cls_lock; - lls = &lck->lls_sub[idx]; - descr = &lls->sub_got; - - subenv = lov_sublock_env_get(env, parent, lls); - if (!IS_ERR(subenv)) { - /* CAVEAT: Don't try to add a field in lov_lock_sub - * to remember the subio. This is because lock is able - * to be cached, but this is not true for IO. This - * further means a sublock might be referenced in - * different io context. -jay - */ - - sublock = cl_lock_hold(subenv->lse_env, subenv->lse_io, - descr, "lov-parent", parent); - lov_sublock_env_put(subenv); - } else { - /* error occurs. */ - sublock = (void *)subenv; - } - - if (!IS_ERR(sublock)) - *out = link; - else - kmem_cache_free(lov_lock_link_kmem, link); - } else - sublock = ERR_PTR(-ENOMEM); - return sublock; -} - -static void lov_sublock_unlock(const struct lu_env *env, - struct lovsub_lock *lsl, - struct cl_lock_closure *closure, - struct lov_sublock_env *subenv) -{ - lov_sublock_env_put(subenv); - lsl->lss_active = NULL; - cl_lock_disclosure(env, closure); -} - -static int lov_sublock_lock(const struct lu_env *env, - struct lov_lock *lck, - struct lov_lock_sub *lls, - struct cl_lock_closure *closure, - struct lov_sublock_env **lsep) -{ - struct lovsub_lock *sublock; - struct cl_lock *child; - int result = 0; - - LASSERT(list_empty(&closure->clc_list)); - - sublock = lls->sub_lock; - child = sublock->lss_cl.cls_lock; - result = cl_lock_closure_build(env, child, closure); - if (result == 0) { - struct cl_lock *parent = closure->clc_origin; - - LASSERT(cl_lock_is_mutexed(child)); - sublock->lss_active = parent; - - if (unlikely((child->cll_state == CLS_FREEING) || - (child->cll_flags & CLF_CANCELLED))) { - struct lov_lock_link *link; - /* - * we could race with lock deletion which temporarily - * put the lock in freeing state, bug 19080. - */ - LASSERT(!(lls->sub_flags & LSF_HELD)); - - link = lov_lock_link_find(env, lck, sublock); - LASSERT(link); - lov_lock_unlink(env, link, sublock); - lov_sublock_unlock(env, sublock, closure, NULL); - lck->lls_cancel_race = 1; - result = CLO_REPEAT; - } else if (lsep) { - struct lov_sublock_env *subenv; + struct lov_sublock_env *subenv; + int result; - subenv = lov_sublock_env_get(env, parent, lls); - if (IS_ERR(subenv)) { - lov_sublock_unlock(env, sublock, - closure, NULL); - result = PTR_ERR(subenv); - } else { - *lsep = subenv; - } - } + subenv = lov_sublock_env_get(env, parent, lls); + if (!IS_ERR(subenv)) { + result = cl_lock_init(subenv->lse_env, &lls->sub_lock, + subenv->lse_io); + lov_sublock_env_put(subenv); + } else { + /* error occurs. */ + result = PTR_ERR(subenv); } return result; } -/** - * Updates the result of a top-lock operation from a result of sub-lock - * sub-operations. Top-operations like lov_lock_{enqueue,use,unuse}() iterate - * over sub-locks and lov_subresult() is used to calculate return value of a - * top-operation. To this end, possible return values of sub-operations are - * ordered as - * - * - 0 success - * - CLO_WAIT wait for event - * - CLO_REPEAT repeat top-operation - * - -ne fundamental error - * - * Top-level return code can only go down through this list. CLO_REPEAT - * overwrites CLO_WAIT, because lock mutex was released and sleeping condition - * has to be rechecked by the upper layer. - */ -static int lov_subresult(int result, int rc) -{ - int result_rank; - int rc_rank; - - LASSERTF(result <= 0 || result == CLO_REPEAT || result == CLO_WAIT, - "result = %d\n", result); - LASSERTF(rc <= 0 || rc == CLO_REPEAT || rc == CLO_WAIT, - "rc = %d\n", rc); - CLASSERT(CLO_WAIT < CLO_REPEAT); - - /* calculate ranks in the ordering above */ - result_rank = result < 0 ? 1 + CLO_REPEAT : result; - rc_rank = rc < 0 ? 1 + CLO_REPEAT : rc; - - if (result_rank < rc_rank) - result = rc; - return result; -} - /** * Creates sub-locks for a given lov_lock for the first time. * @@ -286,8 +122,9 @@ static int lov_subresult(int result, int rc) * fact that top-lock (that is being created) can be accessed concurrently * through already created sub-locks (possibly shared with other top-locks). */ -static int lov_lock_sub_init(const struct lu_env *env, - struct lov_lock *lck, const struct cl_io *io) +static struct lov_lock *lov_lock_sub_init(const struct lu_env *env, + const struct cl_object *obj, + struct cl_lock *lock) { int result = 0; int i; @@ -297,241 +134,86 @@ static int lov_lock_sub_init(const struct lu_env *env, u64 file_start; u64 file_end; - struct lov_object *loo = cl2lov(lck->lls_cl.cls_obj); + struct lov_object *loo = cl2lov(obj); struct lov_layout_raid0 *r0 = lov_r0(loo); - struct cl_lock *parent = lck->lls_cl.cls_lock; + struct lov_lock *lovlck; - lck->lls_orig = parent->cll_descr; - file_start = cl_offset(lov2cl(loo), parent->cll_descr.cld_start); - file_end = cl_offset(lov2cl(loo), parent->cll_descr.cld_end + 1) - 1; + file_start = cl_offset(lov2cl(loo), lock->cll_descr.cld_start); + file_end = cl_offset(lov2cl(loo), lock->cll_descr.cld_end + 1) - 1; for (i = 0, nr = 0; i < r0->lo_nr; i++) { /* * XXX for wide striping smarter algorithm is desirable, * breaking out of the loop, early. */ - if (likely(r0->lo_sub[i]) && + if (likely(r0->lo_sub[i]) && /* spare layout */ lov_stripe_intersects(loo->lo_lsm, i, file_start, file_end, &start, &end)) nr++; } LASSERT(nr > 0); - lck->lls_sub = libcfs_kvzalloc(nr * sizeof(lck->lls_sub[0]), GFP_NOFS); - if (!lck->lls_sub) - return -ENOMEM; + lovlck = libcfs_kvzalloc(offsetof(struct lov_lock, lls_sub[nr]), + GFP_NOFS); + if (!lovlck) + return ERR_PTR(-ENOMEM); - lck->lls_nr = nr; - /* - * First, fill in sub-lock descriptions in - * lck->lls_sub[].sub_descr. They are used by lov_sublock_alloc() - * (called below in this function, and by lov_lock_enqueue()) to - * create sub-locks. At this moment, no other thread can access - * top-lock. - */ + lovlck->lls_nr = nr; for (i = 0, nr = 0; i < r0->lo_nr; ++i) { if (likely(r0->lo_sub[i]) && lov_stripe_intersects(loo->lo_lsm, i, file_start, file_end, &start, &end)) { + struct lov_lock_sub *lls = &lovlck->lls_sub[nr]; struct cl_lock_descr *descr; - descr = &lck->lls_sub[nr].sub_descr; + descr = &lls->sub_lock.cll_descr; LASSERT(!descr->cld_obj); descr->cld_obj = lovsub2cl(r0->lo_sub[i]); descr->cld_start = cl_index(descr->cld_obj, start); descr->cld_end = cl_index(descr->cld_obj, end); - descr->cld_mode = parent->cll_descr.cld_mode; - descr->cld_gid = parent->cll_descr.cld_gid; - descr->cld_enq_flags = parent->cll_descr.cld_enq_flags; - /* XXX has no effect */ - lck->lls_sub[nr].sub_got = *descr; - lck->lls_sub[nr].sub_stripe = i; + descr->cld_mode = lock->cll_descr.cld_mode; + descr->cld_gid = lock->cll_descr.cld_gid; + descr->cld_enq_flags = lock->cll_descr.cld_enq_flags; + lls->sub_stripe = i; + + /* initialize sub lock */ + result = lov_sublock_init(env, lock, lls); + if (result < 0) + break; + + lls->sub_initialized = 1; nr++; } } - LASSERT(nr == lck->lls_nr); - - /* - * Some sub-locks can be missing at this point. This is not a problem, - * because enqueue will create them anyway. Main duty of this function - * is to fill in sub-lock descriptions in a race free manner. - */ - return result; -} + LASSERT(ergo(result == 0, nr == lovlck->lls_nr)); -static int lov_sublock_release(const struct lu_env *env, struct lov_lock *lck, - int i, int deluser, int rc) -{ - struct cl_lock *parent = lck->lls_cl.cls_lock; - - LASSERT(cl_lock_is_mutexed(parent)); - - if (lck->lls_sub[i].sub_flags & LSF_HELD) { - struct cl_lock *sublock; - int dying; - - sublock = lck->lls_sub[i].sub_lock->lss_cl.cls_lock; - LASSERT(cl_lock_is_mutexed(sublock)); + if (result != 0) { + for (i = 0; i < nr; ++i) { + if (!lovlck->lls_sub[i].sub_initialized) + break; - lck->lls_sub[i].sub_flags &= ~LSF_HELD; - if (deluser) - cl_lock_user_del(env, sublock); - /* - * If the last hold is released, and cancellation is pending - * for a sub-lock, release parent mutex, to avoid keeping it - * while sub-lock is being paged out. - */ - dying = (sublock->cll_descr.cld_mode == CLM_PHANTOM || - sublock->cll_descr.cld_mode == CLM_GROUP || - (sublock->cll_flags & (CLF_CANCELPEND|CLF_DOOMED))) && - sublock->cll_holds == 1; - if (dying) - cl_lock_mutex_put(env, parent); - cl_lock_unhold(env, sublock, "lov-parent", parent); - if (dying) { - cl_lock_mutex_get(env, parent); - rc = lov_subresult(rc, CLO_REPEAT); + cl_lock_fini(env, &lovlck->lls_sub[i].sub_lock); } - /* - * From now on lck->lls_sub[i].sub_lock is a "weak" pointer, - * not backed by a reference on a - * sub-lock. lovsub_lock_delete() will clear - * lck->lls_sub[i].sub_lock under semaphores, just before - * sub-lock is destroyed. - */ + kvfree(lovlck); + lovlck = ERR_PTR(result); } - return rc; -} - -static void lov_sublock_hold(const struct lu_env *env, struct lov_lock *lck, - int i) -{ - struct cl_lock *parent = lck->lls_cl.cls_lock; - - LASSERT(cl_lock_is_mutexed(parent)); - - if (!(lck->lls_sub[i].sub_flags & LSF_HELD)) { - struct cl_lock *sublock; - - sublock = lck->lls_sub[i].sub_lock->lss_cl.cls_lock; - LASSERT(cl_lock_is_mutexed(sublock)); - LASSERT(sublock->cll_state != CLS_FREEING); - lck->lls_sub[i].sub_flags |= LSF_HELD; - - cl_lock_get_trust(sublock); - cl_lock_hold_add(env, sublock, "lov-parent", parent); - cl_lock_user_add(env, sublock); - cl_lock_put(env, sublock); - } + return lovlck; } static void lov_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice) { - struct lov_lock *lck; + struct lov_lock *lovlck; int i; - lck = cl2lov_lock(slice); - LASSERT(lck->lls_nr_filled == 0); - if (lck->lls_sub) { - for (i = 0; i < lck->lls_nr; ++i) - /* - * No sub-locks exists at this point, as sub-lock has - * a reference on its parent. - */ - LASSERT(!lck->lls_sub[i].sub_lock); - kvfree(lck->lls_sub); + lovlck = cl2lov_lock(slice); + for (i = 0; i < lovlck->lls_nr; ++i) { + LASSERT(!lovlck->lls_sub[i].sub_is_enqueued); + if (lovlck->lls_sub[i].sub_initialized) + cl_lock_fini(env, &lovlck->lls_sub[i].sub_lock); } - kmem_cache_free(lov_lock_kmem, lck); -} - -static int lov_lock_enqueue_wait(const struct lu_env *env, - struct lov_lock *lck, - struct cl_lock *sublock) -{ - struct cl_lock *lock = lck->lls_cl.cls_lock; - int result; - - LASSERT(cl_lock_is_mutexed(lock)); - - cl_lock_mutex_put(env, lock); - result = cl_lock_enqueue_wait(env, sublock, 0); - cl_lock_mutex_get(env, lock); - return result ?: CLO_REPEAT; -} - -/** - * Tries to advance a state machine of a given sub-lock toward enqueuing of - * the top-lock. - * - * \retval 0 if state-transition can proceed - * \retval -ve otherwise. - */ -static int lov_lock_enqueue_one(const struct lu_env *env, struct lov_lock *lck, - struct cl_lock *sublock, - struct cl_io *io, __u32 enqflags, int last) -{ - int result; - - /* first, try to enqueue a sub-lock ... */ - result = cl_enqueue_try(env, sublock, io, enqflags); - if ((sublock->cll_state == CLS_ENQUEUED) && !(enqflags & CEF_AGL)) { - /* if it is enqueued, try to `wait' on it---maybe it's already - * granted - */ - result = cl_wait_try(env, sublock); - if (result == CLO_REENQUEUED) - result = CLO_WAIT; - } - /* - * If CEF_ASYNC flag is set, then all sub-locks can be enqueued in - * parallel, otherwise---enqueue has to wait until sub-lock is granted - * before proceeding to the next one. - */ - if ((result == CLO_WAIT) && (sublock->cll_state <= CLS_HELD) && - (enqflags & CEF_ASYNC) && (!last || (enqflags & CEF_AGL))) - result = 0; - return result; -} - -/** - * Helper function for lov_lock_enqueue() that creates missing sub-lock. - */ -static int lov_sublock_fill(const struct lu_env *env, struct cl_lock *parent, - struct cl_io *io, struct lov_lock *lck, int idx) -{ - struct lov_lock_link *link = NULL; - struct cl_lock *sublock; - int result; - - LASSERT(parent->cll_depth == 1); - cl_lock_mutex_put(env, parent); - sublock = lov_sublock_alloc(env, io, lck, idx, &link); - if (!IS_ERR(sublock)) - cl_lock_mutex_get(env, sublock); - cl_lock_mutex_get(env, parent); - - if (!IS_ERR(sublock)) { - cl_lock_get_trust(sublock); - if (parent->cll_state == CLS_QUEUING && - !lck->lls_sub[idx].sub_lock) { - lov_sublock_adopt(env, lck, sublock, idx, link); - } else { - kmem_cache_free(lov_lock_link_kmem, link); - /* other thread allocated sub-lock, or enqueue is no - * longer going on - */ - cl_lock_mutex_put(env, parent); - cl_lock_unhold(env, sublock, "lov-parent", parent); - cl_lock_mutex_get(env, parent); - } - cl_lock_mutex_put(env, sublock); - cl_lock_put(env, sublock); - result = CLO_REPEAT; - } else - result = PTR_ERR(sublock); - return result; + kvfree(lovlck); } /** @@ -543,529 +225,59 @@ static int lov_sublock_fill(const struct lu_env *env, struct cl_lock *parent, */ static int lov_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, - struct cl_io *io, __u32 enqflags) + struct cl_io *io, struct cl_sync_io *anchor) { - struct cl_lock *lock = slice->cls_lock; - struct lov_lock *lck = cl2lov_lock(slice); - struct cl_lock_closure *closure = lov_closure_get(env, lock); + struct cl_lock *lock = slice->cls_lock; + struct lov_lock *lovlck = cl2lov_lock(slice); int i; - int result; - enum cl_lock_state minstate; + int rc = 0; - for (result = 0, minstate = CLS_FREEING, i = 0; i < lck->lls_nr; ++i) { - int rc; - struct lovsub_lock *sub; - struct lov_lock_sub *lls; - struct cl_lock *sublock; + for (i = 0; i < lovlck->lls_nr; ++i) { + struct lov_lock_sub *lls = &lovlck->lls_sub[i]; struct lov_sublock_env *subenv; - if (lock->cll_state != CLS_QUEUING) { - /* - * Lock might have left QUEUING state if previous - * iteration released its mutex. Stop enqueing in this - * case and let the upper layer to decide what to do. - */ - LASSERT(i > 0 && result != 0); - break; - } - - lls = &lck->lls_sub[i]; - sub = lls->sub_lock; - /* - * Sub-lock might have been canceled, while top-lock was - * cached. - */ - if (!sub) { - result = lov_sublock_fill(env, lock, io, lck, i); - /* lov_sublock_fill() released @lock mutex, - * restart. - */ + subenv = lov_sublock_env_get(env, lock, lls); + if (IS_ERR(subenv)) { + rc = PTR_ERR(subenv); break; } - sublock = sub->lss_cl.cls_lock; - rc = lov_sublock_lock(env, lck, lls, closure, &subenv); - if (rc == 0) { - lov_sublock_hold(env, lck, i); - rc = lov_lock_enqueue_one(subenv->lse_env, lck, sublock, - subenv->lse_io, enqflags, - i == lck->lls_nr - 1); - minstate = min(minstate, sublock->cll_state); - if (rc == CLO_WAIT) { - switch (sublock->cll_state) { - case CLS_QUEUING: - /* take recursive mutex, the lock is - * released in lov_lock_enqueue_wait. - */ - cl_lock_mutex_get(env, sublock); - lov_sublock_unlock(env, sub, closure, - subenv); - rc = lov_lock_enqueue_wait(env, lck, - sublock); - break; - case CLS_CACHED: - cl_lock_get(sublock); - /* take recursive mutex of sublock */ - cl_lock_mutex_get(env, sublock); - /* need to release all locks in closure - * otherwise it may deadlock. LU-2683. - */ - lov_sublock_unlock(env, sub, closure, - subenv); - /* sublock and parent are held. */ - rc = lov_sublock_release(env, lck, i, - 1, rc); - cl_lock_mutex_put(env, sublock); - cl_lock_put(env, sublock); - break; - default: - lov_sublock_unlock(env, sub, closure, - subenv); - break; - } - } else { - LASSERT(!sublock->cll_conflict); - lov_sublock_unlock(env, sub, closure, subenv); - } - } - result = lov_subresult(result, rc); - if (result != 0) + rc = cl_lock_enqueue(subenv->lse_env, subenv->lse_io, + &lls->sub_lock, anchor); + lov_sublock_env_put(subenv); + if (rc != 0) break; - } - cl_lock_closure_fini(closure); - return result ?: minstate >= CLS_ENQUEUED ? 0 : CLO_WAIT; -} - -static int lov_lock_unuse(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct lov_lock *lck = cl2lov_lock(slice); - struct cl_lock_closure *closure = lov_closure_get(env, slice->cls_lock); - int i; - int result; - - for (result = 0, i = 0; i < lck->lls_nr; ++i) { - int rc; - struct lovsub_lock *sub; - struct cl_lock *sublock; - struct lov_lock_sub *lls; - struct lov_sublock_env *subenv; - /* top-lock state cannot change concurrently, because single - * thread (one that released the last hold) carries unlocking - * to the completion. - */ - LASSERT(slice->cls_lock->cll_state == CLS_INTRANSIT); - lls = &lck->lls_sub[i]; - sub = lls->sub_lock; - if (!sub) - continue; - - sublock = sub->lss_cl.cls_lock; - rc = lov_sublock_lock(env, lck, lls, closure, &subenv); - if (rc == 0) { - if (lls->sub_flags & LSF_HELD) { - LASSERT(sublock->cll_state == CLS_HELD || - sublock->cll_state == CLS_ENQUEUED); - rc = cl_unuse_try(subenv->lse_env, sublock); - rc = lov_sublock_release(env, lck, i, 0, rc); - } - lov_sublock_unlock(env, sub, closure, subenv); - } - result = lov_subresult(result, rc); + lls->sub_is_enqueued = 1; } - - if (result == 0 && lck->lls_cancel_race) { - lck->lls_cancel_race = 0; - result = -ESTALE; - } - cl_lock_closure_fini(closure); - return result; + return rc; } static void lov_lock_cancel(const struct lu_env *env, const struct cl_lock_slice *slice) { - struct lov_lock *lck = cl2lov_lock(slice); - struct cl_lock_closure *closure = lov_closure_get(env, slice->cls_lock); + struct cl_lock *lock = slice->cls_lock; + struct lov_lock *lovlck = cl2lov_lock(slice); int i; - int result; - for (result = 0, i = 0; i < lck->lls_nr; ++i) { - int rc; - struct lovsub_lock *sub; - struct cl_lock *sublock; - struct lov_lock_sub *lls; + for (i = 0; i < lovlck->lls_nr; ++i) { + struct lov_lock_sub *lls = &lovlck->lls_sub[i]; + struct cl_lock *sublock = &lls->sub_lock; struct lov_sublock_env *subenv; - /* top-lock state cannot change concurrently, because single - * thread (one that released the last hold) carries unlocking - * to the completion. - */ - lls = &lck->lls_sub[i]; - sub = lls->sub_lock; - if (!sub) - continue; - - sublock = sub->lss_cl.cls_lock; - rc = lov_sublock_lock(env, lck, lls, closure, &subenv); - if (rc == 0) { - if (!(lls->sub_flags & LSF_HELD)) { - lov_sublock_unlock(env, sub, closure, subenv); - continue; - } - - switch (sublock->cll_state) { - case CLS_HELD: - rc = cl_unuse_try(subenv->lse_env, sublock); - lov_sublock_release(env, lck, i, 0, 0); - break; - default: - lov_sublock_release(env, lck, i, 1, 0); - break; - } - lov_sublock_unlock(env, sub, closure, subenv); - } - - if (rc == CLO_REPEAT) { - --i; - continue; - } - - result = lov_subresult(result, rc); - } - - if (result) - CL_LOCK_DEBUG(D_ERROR, env, slice->cls_lock, - "lov_lock_cancel fails with %d.\n", result); - - cl_lock_closure_fini(closure); -} - -static int lov_lock_wait(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct lov_lock *lck = cl2lov_lock(slice); - struct cl_lock_closure *closure = lov_closure_get(env, slice->cls_lock); - enum cl_lock_state minstate; - int reenqueued; - int result; - int i; - -again: - for (result = 0, minstate = CLS_FREEING, i = 0, reenqueued = 0; - i < lck->lls_nr; ++i) { - int rc; - struct lovsub_lock *sub; - struct cl_lock *sublock; - struct lov_lock_sub *lls; - struct lov_sublock_env *subenv; - - lls = &lck->lls_sub[i]; - sub = lls->sub_lock; - sublock = sub->lss_cl.cls_lock; - rc = lov_sublock_lock(env, lck, lls, closure, &subenv); - if (rc == 0) { - LASSERT(sublock->cll_state >= CLS_ENQUEUED); - if (sublock->cll_state < CLS_HELD) - rc = cl_wait_try(env, sublock); - - minstate = min(minstate, sublock->cll_state); - lov_sublock_unlock(env, sub, closure, subenv); - } - if (rc == CLO_REENQUEUED) { - reenqueued++; - rc = 0; - } - result = lov_subresult(result, rc); - if (result != 0) - break; - } - /* Each sublock only can be reenqueued once, so will not loop - * forever. - */ - if (result == 0 && reenqueued != 0) - goto again; - cl_lock_closure_fini(closure); - return result ?: minstate >= CLS_HELD ? 0 : CLO_WAIT; -} - -static int lov_lock_use(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct lov_lock *lck = cl2lov_lock(slice); - struct cl_lock_closure *closure = lov_closure_get(env, slice->cls_lock); - int result; - int i; - - LASSERT(slice->cls_lock->cll_state == CLS_INTRANSIT); - - for (result = 0, i = 0; i < lck->lls_nr; ++i) { - int rc; - struct lovsub_lock *sub; - struct cl_lock *sublock; - struct lov_lock_sub *lls; - struct lov_sublock_env *subenv; - - LASSERT(slice->cls_lock->cll_state == CLS_INTRANSIT); - - lls = &lck->lls_sub[i]; - sub = lls->sub_lock; - if (!sub) { - /* - * Sub-lock might have been canceled, while top-lock was - * cached. - */ - result = -ESTALE; - break; - } - - sublock = sub->lss_cl.cls_lock; - rc = lov_sublock_lock(env, lck, lls, closure, &subenv); - if (rc == 0) { - LASSERT(sublock->cll_state != CLS_FREEING); - lov_sublock_hold(env, lck, i); - if (sublock->cll_state == CLS_CACHED) { - rc = cl_use_try(subenv->lse_env, sublock, 0); - if (rc != 0) - rc = lov_sublock_release(env, lck, - i, 1, rc); - } else if (sublock->cll_state == CLS_NEW) { - /* Sub-lock might have been canceled, while - * top-lock was cached. - */ - result = -ESTALE; - lov_sublock_release(env, lck, i, 1, result); - } - lov_sublock_unlock(env, sub, closure, subenv); - } - result = lov_subresult(result, rc); - if (result != 0) - break; - } - - if (lck->lls_cancel_race) { - /* - * If there is unlocking happened at the same time, then - * sublock_lock state should be FREEING, and lov_sublock_lock - * should return CLO_REPEAT. In this case, it should return - * ESTALE, and up layer should reset the lock state to be NEW. - */ - lck->lls_cancel_race = 0; - LASSERT(result != 0); - result = -ESTALE; - } - cl_lock_closure_fini(closure); - return result; -} - -/** - * Check if the extent region \a descr is covered by \a child against the - * specific \a stripe. - */ -static int lov_lock_stripe_is_matching(const struct lu_env *env, - struct lov_object *lov, int stripe, - const struct cl_lock_descr *child, - const struct cl_lock_descr *descr) -{ - struct lov_stripe_md *lsm = lov->lo_lsm; - u64 start; - u64 end; - int result; - - if (lov_r0(lov)->lo_nr == 1) - return cl_lock_ext_match(child, descr); - - /* - * For a multi-stripes object: - * - make sure the descr only covers child's stripe, and - * - check if extent is matching. - */ - start = cl_offset(&lov->lo_cl, descr->cld_start); - end = cl_offset(&lov->lo_cl, descr->cld_end + 1) - 1; - result = 0; - /* glimpse should work on the object with LOV EA hole. */ - if (end - start <= lsm->lsm_stripe_size) { - int idx; - - idx = lov_stripe_number(lsm, start); - if (idx == stripe || - unlikely(!lov_r0(lov)->lo_sub[idx])) { - idx = lov_stripe_number(lsm, end); - if (idx == stripe || - unlikely(!lov_r0(lov)->lo_sub[idx])) - result = 1; - } - } - - if (result != 0) { - struct cl_lock_descr *subd = &lov_env_info(env)->lti_ldescr; - u64 sub_start; - u64 sub_end; - - subd->cld_obj = NULL; /* don't need sub object at all */ - subd->cld_mode = descr->cld_mode; - subd->cld_gid = descr->cld_gid; - result = lov_stripe_intersects(lsm, stripe, start, end, - &sub_start, &sub_end); - LASSERT(result); - subd->cld_start = cl_index(child->cld_obj, sub_start); - subd->cld_end = cl_index(child->cld_obj, sub_end); - result = cl_lock_ext_match(child, subd); - } - return result; -} - -/** - * An implementation of cl_lock_operations::clo_fits_into() method. - * - * Checks whether a lock (given by \a slice) is suitable for \a - * io. Multi-stripe locks can be used only for "quick" io, like truncate, or - * O_APPEND write. - * - * \see ccc_lock_fits_into(). - */ -static int lov_lock_fits_into(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *need, - const struct cl_io *io) -{ - struct lov_lock *lov = cl2lov_lock(slice); - struct lov_object *obj = cl2lov(slice->cls_obj); - int result; - - LASSERT(cl_object_same(need->cld_obj, slice->cls_obj)); - LASSERT(lov->lls_nr > 0); - - /* for top lock, it's necessary to match enq flags otherwise it will - * run into problem if a sublock is missing and reenqueue. - */ - if (need->cld_enq_flags != lov->lls_orig.cld_enq_flags) - return 0; - - if (need->cld_mode == CLM_GROUP) - /* - * always allow to match group lock. - */ - result = cl_lock_ext_match(&lov->lls_orig, need); - else if (lov->lls_nr == 1) { - struct cl_lock_descr *got = &lov->lls_sub[0].sub_got; - - result = lov_lock_stripe_is_matching(env, - cl2lov(slice->cls_obj), - lov->lls_sub[0].sub_stripe, - got, need); - } else if (io->ci_type != CIT_SETATTR && io->ci_type != CIT_MISC && - !cl_io_is_append(io) && need->cld_mode != CLM_PHANTOM) - /* - * Multi-stripe locks are only suitable for `quick' IO and for - * glimpse. - */ - result = 0; - else - /* - * Most general case: multi-stripe existing lock, and - * (potentially) multi-stripe @need lock. Check that @need is - * covered by @lov's sub-locks. - * - * For now, ignore lock expansions made by the server, and - * match against original lock extent. - */ - result = cl_lock_ext_match(&lov->lls_orig, need); - CDEBUG(D_DLMTRACE, DDESCR"/"DDESCR" %d %d/%d: %d\n", - PDESCR(&lov->lls_orig), PDESCR(&lov->lls_sub[0].sub_got), - lov->lls_sub[0].sub_stripe, lov->lls_nr, lov_r0(obj)->lo_nr, - result); - return result; -} - -void lov_lock_unlink(const struct lu_env *env, - struct lov_lock_link *link, struct lovsub_lock *sub) -{ - struct lov_lock *lck = link->lll_super; - struct cl_lock *parent = lck->lls_cl.cls_lock; - - LASSERT(cl_lock_is_mutexed(parent)); - LASSERT(cl_lock_is_mutexed(sub->lss_cl.cls_lock)); - - list_del_init(&link->lll_list); - LASSERT(lck->lls_sub[link->lll_idx].sub_lock == sub); - /* yank this sub-lock from parent's array */ - lck->lls_sub[link->lll_idx].sub_lock = NULL; - LASSERT(lck->lls_nr_filled > 0); - lck->lls_nr_filled--; - lu_ref_del(&parent->cll_reference, "lov-child", sub->lss_cl.cls_lock); - cl_lock_put(env, parent); - kmem_cache_free(lov_lock_link_kmem, link); -} - -struct lov_lock_link *lov_lock_link_find(const struct lu_env *env, - struct lov_lock *lck, - struct lovsub_lock *sub) -{ - struct lov_lock_link *scan; - - LASSERT(cl_lock_is_mutexed(sub->lss_cl.cls_lock)); - - list_for_each_entry(scan, &sub->lss_parents, lll_list) { - if (scan->lll_super == lck) - return scan; - } - return NULL; -} - -/** - * An implementation of cl_lock_operations::clo_delete() method. This is - * invoked for "top-to-bottom" delete, when lock destruction starts from the - * top-lock, e.g., as a result of inode destruction. - * - * Unlinks top-lock from all its sub-locks. Sub-locks are not deleted there: - * this is done separately elsewhere: - * - * - for inode destruction, lov_object_delete() calls cl_object_kill() for - * each sub-object, purging its locks; - * - * - in other cases (e.g., a fatal error with a top-lock) sub-locks are - * left in the cache. - */ -static void lov_lock_delete(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct lov_lock *lck = cl2lov_lock(slice); - struct cl_lock_closure *closure = lov_closure_get(env, slice->cls_lock); - struct lov_lock_link *link; - int rc; - int i; - - LASSERT(slice->cls_lock->cll_state == CLS_FREEING); - - for (i = 0; i < lck->lls_nr; ++i) { - struct lov_lock_sub *lls = &lck->lls_sub[i]; - struct lovsub_lock *lsl = lls->sub_lock; - - if (!lsl) /* already removed */ + if (!lls->sub_is_enqueued) continue; - rc = lov_sublock_lock(env, lck, lls, closure, NULL); - if (rc == CLO_REPEAT) { - --i; - continue; + lls->sub_is_enqueued = 0; + subenv = lov_sublock_env_get(env, lock, lls); + if (!IS_ERR(subenv)) { + cl_lock_cancel(subenv->lse_env, sublock); + lov_sublock_env_put(subenv); + } else { + CL_LOCK_DEBUG(D_ERROR, env, slice->cls_lock, + "lov_lock_cancel fails with %ld.\n", + PTR_ERR(subenv)); } - - LASSERT(rc == 0); - LASSERT(lsl->lss_cl.cls_lock->cll_state < CLS_FREEING); - - if (lls->sub_flags & LSF_HELD) - lov_sublock_release(env, lck, i, 1, 0); - - link = lov_lock_link_find(env, lck, lsl); - LASSERT(link); - lov_lock_unlink(env, link, lsl); - LASSERT(!lck->lls_sub[i].sub_lock); - - lov_sublock_unlock(env, lsl, closure, NULL); } - - cl_lock_closure_fini(closure); } static int lov_lock_print(const struct lu_env *env, void *cookie, @@ -1079,12 +291,8 @@ static int lov_lock_print(const struct lu_env *env, void *cookie, struct lov_lock_sub *sub; sub = &lck->lls_sub[i]; - (*p)(env, cookie, " %d %x: ", i, sub->sub_flags); - if (sub->sub_lock) - cl_lock_print(env, cookie, p, - sub->sub_lock->lss_cl.cls_lock); - else - (*p)(env, cookie, "---\n"); + (*p)(env, cookie, " %d %x: ", i, sub->sub_is_enqueued); + cl_lock_print(env, cookie, p, &sub->sub_lock); } return 0; } @@ -1092,12 +300,7 @@ static int lov_lock_print(const struct lu_env *env, void *cookie, static const struct cl_lock_operations lov_lock_ops = { .clo_fini = lov_lock_fini, .clo_enqueue = lov_lock_enqueue, - .clo_wait = lov_lock_wait, - .clo_use = lov_lock_use, - .clo_unuse = lov_lock_unuse, .clo_cancel = lov_lock_cancel, - .clo_fits_into = lov_lock_fits_into, - .clo_delete = lov_lock_delete, .clo_print = lov_lock_print }; @@ -1105,14 +308,13 @@ int lov_lock_init_raid0(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io) { struct lov_lock *lck; - int result; + int result = 0; - lck = kmem_cache_zalloc(lov_lock_kmem, GFP_NOFS); - if (lck) { + lck = lov_lock_sub_init(env, obj, lock); + if (!IS_ERR(lck)) cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_lock_ops); - result = lov_lock_sub_init(env, lck, io); - } else - result = -ENOMEM; + else + result = PTR_ERR(lck); return result; } @@ -1147,21 +349,9 @@ int lov_lock_init_empty(const struct lu_env *env, struct cl_object *obj, lck = kmem_cache_zalloc(lov_lock_kmem, GFP_NOFS); if (lck) { cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_empty_lock_ops); - lck->lls_orig = lock->cll_descr; result = 0; } return result; } -static struct cl_lock_closure *lov_closure_get(const struct lu_env *env, - struct cl_lock *parent) -{ - struct cl_lock_closure *closure; - - closure = &lov_env_info(env)->lti_closure; - LASSERT(list_empty(&closure->clc_list)); - cl_lock_closure_init(env, closure, parent, 1); - return closure; -} - /** @} lov */ diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 0159b6f1e5c3..6a353d18eefe 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -310,8 +310,6 @@ static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov, LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED); lov_layout_wait(env, lov); - - cl_locks_prune(env, &lov->lo_cl, 0); return 0; } @@ -379,7 +377,7 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov, struct lovsub_object *los = r0->lo_sub[i]; if (los) { - cl_locks_prune(env, &los->lso_cl, 1); + cl_object_prune(env, &los->lso_cl); /* * If top-level object is to be evicted from * the cache, so are its sub-objects. @@ -388,7 +386,6 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov, } } } - cl_locks_prune(env, &lov->lo_cl, 0); return 0; } @@ -714,7 +711,9 @@ static int lov_layout_change(const struct lu_env *unused, old_ops = &lov_dispatch[lov->lo_type]; new_ops = &lov_dispatch[llt]; - cl_object_prune(env, &lov->lo_cl); + result = cl_object_prune(env, &lov->lo_cl); + if (result != 0) + goto out; result = old_ops->llo_delete(env, lov, &lov->u); if (result == 0) { @@ -736,6 +735,7 @@ static int lov_layout_change(const struct lu_env *unused, } } +out: cl_env_put(env, &refcheck); cl_env_reexit(cookie); return result; @@ -816,7 +816,8 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, goto out; } - lov->lo_layout_invalid = lov_layout_change(env, lov, conf); + result = lov_layout_change(env, lov, conf); + lov->lo_layout_invalid = result != 0; out: lov_conf_unlock(lov); diff --git a/drivers/staging/lustre/lustre/lov/lovsub_lock.c b/drivers/staging/lustre/lustre/lov/lovsub_lock.c index 3bb0c9068a90..670d203ab77e 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_lock.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_lock.c @@ -62,391 +62,8 @@ static void lovsub_lock_fini(const struct lu_env *env, kmem_cache_free(lovsub_lock_kmem, lsl); } -static void lovsub_parent_lock(const struct lu_env *env, struct lov_lock *lov) -{ - struct cl_lock *parent; - - parent = lov->lls_cl.cls_lock; - cl_lock_get(parent); - lu_ref_add(&parent->cll_reference, "lovsub-parent", current); - cl_lock_mutex_get(env, parent); -} - -static void lovsub_parent_unlock(const struct lu_env *env, struct lov_lock *lov) -{ - struct cl_lock *parent; - - parent = lov->lls_cl.cls_lock; - cl_lock_mutex_put(env, lov->lls_cl.cls_lock); - lu_ref_del(&parent->cll_reference, "lovsub-parent", current); - cl_lock_put(env, parent); -} - -/** - * Implements cl_lock_operations::clo_state() method for lovsub layer, which - * method is called whenever sub-lock state changes. Propagates state change - * to the top-locks. - */ -static void lovsub_lock_state(const struct lu_env *env, - const struct cl_lock_slice *slice, - enum cl_lock_state state) -{ - struct lovsub_lock *sub = cl2lovsub_lock(slice); - struct lov_lock_link *scan; - - LASSERT(cl_lock_is_mutexed(slice->cls_lock)); - - list_for_each_entry(scan, &sub->lss_parents, lll_list) { - struct lov_lock *lov = scan->lll_super; - struct cl_lock *parent = lov->lls_cl.cls_lock; - - if (sub->lss_active != parent) { - lovsub_parent_lock(env, lov); - cl_lock_signal(env, parent); - lovsub_parent_unlock(env, lov); - } - } -} - -/** - * Implementation of cl_lock_operation::clo_weigh() estimating lock weight by - * asking parent lock. - */ -static unsigned long lovsub_lock_weigh(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct lovsub_lock *lock = cl2lovsub_lock(slice); - struct lov_lock *lov; - unsigned long dumbbell; - - LASSERT(cl_lock_is_mutexed(slice->cls_lock)); - - if (!list_empty(&lock->lss_parents)) { - /* - * It is not clear whether all parents have to be asked and - * their estimations summed, or it is enough to ask one. For - * the current usages, one is always enough. - */ - lov = container_of(lock->lss_parents.next, - struct lov_lock_link, lll_list)->lll_super; - - lovsub_parent_lock(env, lov); - dumbbell = cl_lock_weigh(env, lov->lls_cl.cls_lock); - lovsub_parent_unlock(env, lov); - } else - dumbbell = 0; - - return dumbbell; -} - -/** - * Maps start/end offsets within a stripe, to offsets within a file. - */ -static void lovsub_lock_descr_map(const struct cl_lock_descr *in, - struct lov_object *lov, - int stripe, struct cl_lock_descr *out) -{ - pgoff_t size; /* stripe size in pages */ - pgoff_t skip; /* how many pages in every stripe are occupied by - * "other" stripes - */ - pgoff_t start; - pgoff_t end; - - start = in->cld_start; - end = in->cld_end; - - if (lov->lo_lsm->lsm_stripe_count > 1) { - size = cl_index(lov2cl(lov), lov->lo_lsm->lsm_stripe_size); - skip = (lov->lo_lsm->lsm_stripe_count - 1) * size; - - /* XXX overflow check here? */ - start += start/size * skip + stripe * size; - - if (end != CL_PAGE_EOF) { - end += end/size * skip + stripe * size; - /* - * And check for overflow... - */ - if (end < in->cld_end) - end = CL_PAGE_EOF; - } - } - out->cld_start = start; - out->cld_end = end; -} - -/** - * Adjusts parent lock extent when a sub-lock is attached to a parent. This is - * called in two ways: - * - * - as part of receive call-back, when server returns granted extent to - * the client, and - * - * - when top-lock finds existing sub-lock in the cache. - * - * Note, that lock mode is not propagated to the parent: i.e., if CLM_READ - * top-lock matches CLM_WRITE sub-lock, top-lock is still CLM_READ. - */ -int lov_sublock_modify(const struct lu_env *env, struct lov_lock *lov, - struct lovsub_lock *sublock, - const struct cl_lock_descr *d, int idx) -{ - struct cl_lock *parent; - struct lovsub_object *subobj; - struct cl_lock_descr *pd; - struct cl_lock_descr *parent_descr; - int result; - - parent = lov->lls_cl.cls_lock; - parent_descr = &parent->cll_descr; - LASSERT(cl_lock_mode_match(d->cld_mode, parent_descr->cld_mode)); - - subobj = cl2lovsub(sublock->lss_cl.cls_obj); - pd = &lov_env_info(env)->lti_ldescr; - - pd->cld_obj = parent_descr->cld_obj; - pd->cld_mode = parent_descr->cld_mode; - pd->cld_gid = parent_descr->cld_gid; - lovsub_lock_descr_map(d, subobj->lso_super, subobj->lso_index, pd); - lov->lls_sub[idx].sub_got = *d; - /* - * Notify top-lock about modification, if lock description changes - * materially. - */ - if (!cl_lock_ext_match(parent_descr, pd)) - result = cl_lock_modify(env, parent, pd); - else - result = 0; - return result; -} - -static int lovsub_lock_modify(const struct lu_env *env, - const struct cl_lock_slice *s, - const struct cl_lock_descr *d) -{ - struct lovsub_lock *lock = cl2lovsub_lock(s); - struct lov_lock_link *scan; - struct lov_lock *lov; - int result = 0; - - LASSERT(cl_lock_mode_match(d->cld_mode, - s->cls_lock->cll_descr.cld_mode)); - list_for_each_entry(scan, &lock->lss_parents, lll_list) { - int rc; - - lov = scan->lll_super; - lovsub_parent_lock(env, lov); - rc = lov_sublock_modify(env, lov, lock, d, scan->lll_idx); - lovsub_parent_unlock(env, lov); - result = result ?: rc; - } - return result; -} - -static int lovsub_lock_closure(const struct lu_env *env, - const struct cl_lock_slice *slice, - struct cl_lock_closure *closure) -{ - struct lovsub_lock *sub; - struct cl_lock *parent; - struct lov_lock_link *scan; - int result; - - LASSERT(cl_lock_is_mutexed(slice->cls_lock)); - - sub = cl2lovsub_lock(slice); - result = 0; - - list_for_each_entry(scan, &sub->lss_parents, lll_list) { - parent = scan->lll_super->lls_cl.cls_lock; - result = cl_lock_closure_build(env, parent, closure); - if (result != 0) - break; - } - return result; -} - -/** - * A helper function for lovsub_lock_delete() that deals with a given parent - * top-lock. - */ -static int lovsub_lock_delete_one(const struct lu_env *env, - struct cl_lock *child, struct lov_lock *lov) -{ - struct cl_lock *parent; - int result; - - parent = lov->lls_cl.cls_lock; - if (parent->cll_error) - return 0; - - result = 0; - switch (parent->cll_state) { - case CLS_ENQUEUED: - /* See LU-1355 for the case that a glimpse lock is - * interrupted by signal - */ - LASSERT(parent->cll_flags & CLF_CANCELLED); - break; - case CLS_QUEUING: - case CLS_FREEING: - cl_lock_signal(env, parent); - break; - case CLS_INTRANSIT: - /* - * Here lies a problem: a sub-lock is canceled while top-lock - * is being unlocked. Top-lock cannot be moved into CLS_NEW - * state, because unlocking has to succeed eventually by - * placing lock into CLS_CACHED (or failing it), see - * cl_unuse_try(). Nor can top-lock be left in CLS_CACHED - * state, because lov maintains an invariant that all - * sub-locks exist in CLS_CACHED (this allows cached top-lock - * to be reused immediately). Nor can we wait for top-lock - * state to change, because this can be synchronous to the - * current thread. - * - * We know for sure that lov_lock_unuse() will be called at - * least one more time to finish un-using, so leave a mark on - * the top-lock, that will be seen by the next call to - * lov_lock_unuse(). - */ - if (cl_lock_is_intransit(parent)) - lov->lls_cancel_race = 1; - break; - case CLS_CACHED: - /* - * if a sub-lock is canceled move its top-lock into CLS_NEW - * state to preserve an invariant that a top-lock in - * CLS_CACHED is immediately ready for re-use (i.e., has all - * sub-locks), and so that next attempt to re-use the top-lock - * enqueues missing sub-lock. - */ - cl_lock_state_set(env, parent, CLS_NEW); - /* fall through */ - case CLS_NEW: - /* - * if last sub-lock is canceled, destroy the top-lock (which - * is now `empty') proactively. - */ - if (lov->lls_nr_filled == 0) { - /* ... but unfortunately, this cannot be done easily, - * as cancellation of a top-lock might acquire mutices - * of its other sub-locks, violating lock ordering, - * see cl_lock_{cancel,delete}() preconditions. - * - * To work around this, the mutex of this sub-lock is - * released, top-lock is destroyed, and sub-lock mutex - * acquired again. The list of parents has to be - * re-scanned from the beginning after this. - * - * Only do this if no mutices other than on @child and - * @parent are held by the current thread. - * - * TODO: The lock modal here is too complex, because - * the lock may be canceled and deleted by voluntarily: - * cl_lock_request - * -> osc_lock_enqueue_wait - * -> osc_lock_cancel_wait - * -> cl_lock_delete - * -> lovsub_lock_delete - * -> cl_lock_cancel/delete - * -> ... - * - * The better choice is to spawn a kernel thread for - * this purpose. -jay - */ - if (cl_lock_nr_mutexed(env) == 2) { - cl_lock_mutex_put(env, child); - cl_lock_cancel(env, parent); - cl_lock_delete(env, parent); - result = 1; - } - } - break; - case CLS_HELD: - CL_LOCK_DEBUG(D_ERROR, env, parent, "Delete CLS_HELD lock\n"); - default: - CERROR("Impossible state: %d\n", parent->cll_state); - LBUG(); - break; - } - - return result; -} - -/** - * An implementation of cl_lock_operations::clo_delete() method. This is - * invoked in "bottom-to-top" delete, when lock destruction starts from the - * sub-lock (e.g, as a result of ldlm lock LRU policy). - */ -static void lovsub_lock_delete(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct cl_lock *child = slice->cls_lock; - struct lovsub_lock *sub = cl2lovsub_lock(slice); - int restart; - - LASSERT(cl_lock_is_mutexed(child)); - - /* - * Destruction of a sub-lock might take multiple iterations, because - * when the last sub-lock of a given top-lock is deleted, top-lock is - * canceled proactively, and this requires to release sub-lock - * mutex. Once sub-lock mutex has been released, list of its parents - * has to be re-scanned from the beginning. - */ - do { - struct lov_lock *lov; - struct lov_lock_link *scan; - struct lov_lock_link *temp; - struct lov_lock_sub *subdata; - - restart = 0; - list_for_each_entry_safe(scan, temp, - &sub->lss_parents, lll_list) { - lov = scan->lll_super; - subdata = &lov->lls_sub[scan->lll_idx]; - lovsub_parent_lock(env, lov); - subdata->sub_got = subdata->sub_descr; - lov_lock_unlink(env, scan, sub); - restart = lovsub_lock_delete_one(env, child, lov); - lovsub_parent_unlock(env, lov); - - if (restart) { - cl_lock_mutex_get(env, child); - break; - } - } - } while (restart); -} - -static int lovsub_lock_print(const struct lu_env *env, void *cookie, - lu_printer_t p, const struct cl_lock_slice *slice) -{ - struct lovsub_lock *sub = cl2lovsub_lock(slice); - struct lov_lock *lov; - struct lov_lock_link *scan; - - list_for_each_entry(scan, &sub->lss_parents, lll_list) { - lov = scan->lll_super; - (*p)(env, cookie, "[%d %p ", scan->lll_idx, lov); - if (lov) - cl_lock_descr_print(env, cookie, p, - &lov->lls_cl.cls_lock->cll_descr); - (*p)(env, cookie, "] "); - } - return 0; -} - static const struct cl_lock_operations lovsub_lock_ops = { .clo_fini = lovsub_lock_fini, - .clo_state = lovsub_lock_state, - .clo_delete = lovsub_lock_delete, - .clo_modify = lovsub_lock_modify, - .clo_closure = lovsub_lock_closure, - .clo_weigh = lovsub_lock_weigh, - .clo_print = lovsub_lock_print }; int lovsub_lock_init(const struct lu_env *env, struct cl_object *obj, diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 6a8dd9faafca..7655dc485fef 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -160,7 +160,6 @@ static int cl_io_init0(const struct lu_env *env, struct cl_io *io, io->ci_type = iot; INIT_LIST_HEAD(&io->ci_lockset.cls_todo); - INIT_LIST_HEAD(&io->ci_lockset.cls_curr); INIT_LIST_HEAD(&io->ci_lockset.cls_done); INIT_LIST_HEAD(&io->ci_layers); @@ -242,37 +241,7 @@ static int cl_lock_descr_sort(const struct cl_lock_descr *d0, const struct cl_lock_descr *d1) { return lu_fid_cmp(lu_object_fid(&d0->cld_obj->co_lu), - lu_object_fid(&d1->cld_obj->co_lu)) ?: - __diff_normalize(d0->cld_start, d1->cld_start); -} - -static int cl_lock_descr_cmp(const struct cl_lock_descr *d0, - const struct cl_lock_descr *d1) -{ - int ret; - - ret = lu_fid_cmp(lu_object_fid(&d0->cld_obj->co_lu), - lu_object_fid(&d1->cld_obj->co_lu)); - if (ret) - return ret; - if (d0->cld_end < d1->cld_start) - return -1; - if (d0->cld_start > d0->cld_end) - return 1; - return 0; -} - -static void cl_lock_descr_merge(struct cl_lock_descr *d0, - const struct cl_lock_descr *d1) -{ - d0->cld_start = min(d0->cld_start, d1->cld_start); - d0->cld_end = max(d0->cld_end, d1->cld_end); - - if (d1->cld_mode == CLM_WRITE && d0->cld_mode != CLM_WRITE) - d0->cld_mode = CLM_WRITE; - - if (d1->cld_mode == CLM_GROUP && d0->cld_mode != CLM_GROUP) - d0->cld_mode = CLM_GROUP; + lu_object_fid(&d1->cld_obj->co_lu)); } /* @@ -321,33 +290,35 @@ static void cl_io_locks_sort(struct cl_io *io) } while (!done); } -/** - * Check whether \a queue contains locks matching \a need. - * - * \retval +ve there is a matching lock in the \a queue - * \retval 0 there are no matching locks in the \a queue - */ -int cl_queue_match(const struct list_head *queue, - const struct cl_lock_descr *need) +static void cl_lock_descr_merge(struct cl_lock_descr *d0, + const struct cl_lock_descr *d1) { - struct cl_io_lock_link *scan; + d0->cld_start = min(d0->cld_start, d1->cld_start); + d0->cld_end = max(d0->cld_end, d1->cld_end); - list_for_each_entry(scan, queue, cill_linkage) { - if (cl_lock_descr_match(&scan->cill_descr, need)) - return 1; - } - return 0; + if (d1->cld_mode == CLM_WRITE && d0->cld_mode != CLM_WRITE) + d0->cld_mode = CLM_WRITE; + + if (d1->cld_mode == CLM_GROUP && d0->cld_mode != CLM_GROUP) + d0->cld_mode = CLM_GROUP; } -EXPORT_SYMBOL(cl_queue_match); -static int cl_queue_merge(const struct list_head *queue, - const struct cl_lock_descr *need) +static int cl_lockset_merge(const struct cl_lockset *set, + const struct cl_lock_descr *need) { struct cl_io_lock_link *scan; - list_for_each_entry(scan, queue, cill_linkage) { - if (cl_lock_descr_cmp(&scan->cill_descr, need)) + list_for_each_entry(scan, &set->cls_todo, cill_linkage) { + if (!cl_object_same(scan->cill_descr.cld_obj, need->cld_obj)) continue; + + /* Merge locks for the same object because ldlm lock server + * may expand the lock extent, otherwise there is a deadlock + * case if two conflicted locks are queueud for the same object + * and lock server expands one lock to overlap the another. + * The side effect is that it can generate a multi-stripe lock + * that may cause casacading problem + */ cl_lock_descr_merge(&scan->cill_descr, need); CDEBUG(D_VFSTRACE, "lock: %d: [%lu, %lu]\n", scan->cill_descr.cld_mode, scan->cill_descr.cld_start, @@ -357,87 +328,20 @@ static int cl_queue_merge(const struct list_head *queue, return 0; } -static int cl_lockset_match(const struct cl_lockset *set, - const struct cl_lock_descr *need) -{ - return cl_queue_match(&set->cls_curr, need) || - cl_queue_match(&set->cls_done, need); -} - -static int cl_lockset_merge(const struct cl_lockset *set, - const struct cl_lock_descr *need) -{ - return cl_queue_merge(&set->cls_todo, need) || - cl_lockset_match(set, need); -} - -static int cl_lockset_lock_one(const struct lu_env *env, - struct cl_io *io, struct cl_lockset *set, - struct cl_io_lock_link *link) -{ - struct cl_lock *lock; - int result; - - lock = cl_lock_request(env, io, &link->cill_descr, "io", io); - - if (!IS_ERR(lock)) { - link->cill_lock = lock; - list_move(&link->cill_linkage, &set->cls_curr); - if (!(link->cill_descr.cld_enq_flags & CEF_ASYNC)) { - result = cl_wait(env, lock); - if (result == 0) - list_move(&link->cill_linkage, &set->cls_done); - } else - result = 0; - } else - result = PTR_ERR(lock); - return result; -} - -static void cl_lock_link_fini(const struct lu_env *env, struct cl_io *io, - struct cl_io_lock_link *link) -{ - struct cl_lock *lock = link->cill_lock; - - list_del_init(&link->cill_linkage); - if (lock) { - cl_lock_release(env, lock, "io", io); - link->cill_lock = NULL; - } - if (link->cill_fini) - link->cill_fini(env, link); -} - static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io, struct cl_lockset *set) { struct cl_io_lock_link *link; struct cl_io_lock_link *temp; - struct cl_lock *lock; int result; result = 0; list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) { - if (!cl_lockset_match(set, &link->cill_descr)) { - /* XXX some locking to guarantee that locks aren't - * expanded in between. - */ - result = cl_lockset_lock_one(env, io, set, link); - if (result != 0) - break; - } else - cl_lock_link_fini(env, io, link); - } - if (result == 0) { - list_for_each_entry_safe(link, temp, - &set->cls_curr, cill_linkage) { - lock = link->cill_lock; - result = cl_wait(env, lock); - if (result == 0) - list_move(&link->cill_linkage, &set->cls_done); - else - break; - } + result = cl_lock_request(env, io, &link->cill_lock); + if (result < 0) + break; + + list_move(&link->cill_linkage, &set->cls_done); } return result; } @@ -493,16 +397,19 @@ void cl_io_unlock(const struct lu_env *env, struct cl_io *io) set = &io->ci_lockset; - list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) - cl_lock_link_fini(env, io, link); - - list_for_each_entry_safe(link, temp, &set->cls_curr, cill_linkage) - cl_lock_link_fini(env, io, link); + list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) { + list_del_init(&link->cill_linkage); + if (link->cill_fini) + link->cill_fini(env, link); + } list_for_each_entry_safe(link, temp, &set->cls_done, cill_linkage) { - cl_unuse(env, link->cill_lock); - cl_lock_link_fini(env, io, link); + list_del_init(&link->cill_linkage); + cl_lock_release(env, &link->cill_lock); + if (link->cill_fini) + link->cill_fini(env, link); } + cl_io_for_each_reverse(scan, io) { if (scan->cis_iop->op[io->ci_type].cio_unlock) scan->cis_iop->op[io->ci_type].cio_unlock(env, scan); @@ -1435,6 +1342,7 @@ EXPORT_SYMBOL(cl_sync_io_end); void cl_sync_io_init(struct cl_sync_io *anchor, int nr, void (*end)(const struct lu_env *, struct cl_sync_io *)) { + memset(anchor, 0, sizeof(*anchor)); init_waitqueue_head(&anchor->csi_waitq); atomic_set(&anchor->csi_sync_nr, nr); atomic_set(&anchor->csi_barrier, nr > 0); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index fe8059a0ce5d..26a576b63a72 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -48,1987 +48,187 @@ #include "../include/cl_object.h" #include "cl_internal.h" -/** Lock class of cl_lock::cll_guard */ -static struct lock_class_key cl_lock_guard_class; -static struct kmem_cache *cl_lock_kmem; - -static struct lu_kmem_descr cl_lock_caches[] = { - { - .ckd_cache = &cl_lock_kmem, - .ckd_name = "cl_lock_kmem", - .ckd_size = sizeof (struct cl_lock) - }, - { - .ckd_cache = NULL - } -}; - -#define CS_LOCK_INC(o, item) -#define CS_LOCK_DEC(o, item) -#define CS_LOCKSTATE_INC(o, state) -#define CS_LOCKSTATE_DEC(o, state) - -/** - * Basic lock invariant that is maintained at all times. Caller either has a - * reference to \a lock, or somehow assures that \a lock cannot be freed. - * - * \see cl_lock_invariant() - */ -static int cl_lock_invariant_trusted(const struct lu_env *env, - const struct cl_lock *lock) -{ - return ergo(lock->cll_state == CLS_FREEING, lock->cll_holds == 0) && - atomic_read(&lock->cll_ref) >= lock->cll_holds && - lock->cll_holds >= lock->cll_users && - lock->cll_holds >= 0 && - lock->cll_users >= 0 && - lock->cll_depth >= 0; -} - -/** - * Stronger lock invariant, checking that caller has a reference on a lock. - * - * \see cl_lock_invariant_trusted() - */ -static int cl_lock_invariant(const struct lu_env *env, - const struct cl_lock *lock) -{ - int result; - - result = atomic_read(&lock->cll_ref) > 0 && - cl_lock_invariant_trusted(env, lock); - if (!result && env) - CL_LOCK_DEBUG(D_ERROR, env, lock, "invariant broken\n"); - return result; -} - -/** - * Returns lock "nesting": 0 for a top-lock and 1 for a sub-lock. - */ -static enum clt_nesting_level cl_lock_nesting(const struct cl_lock *lock) -{ - return cl_object_header(lock->cll_descr.cld_obj)->coh_nesting; -} - -/** - * Returns a set of counters for this lock, depending on a lock nesting. - */ -static struct cl_thread_counters *cl_lock_counters(const struct lu_env *env, - const struct cl_lock *lock) -{ - struct cl_thread_info *info; - enum clt_nesting_level nesting; - - info = cl_env_info(env); - nesting = cl_lock_nesting(lock); - LASSERT(nesting < ARRAY_SIZE(info->clt_counters)); - return &info->clt_counters[nesting]; -} - -static void cl_lock_trace0(int level, const struct lu_env *env, - const char *prefix, const struct cl_lock *lock, - const char *func, const int line) -{ - struct cl_object_header *h = cl_object_header(lock->cll_descr.cld_obj); - - CDEBUG(level, "%s: %p@(%d %p %d %d %d %d %d %lx)(%p/%d/%d) at %s():%d\n", - prefix, lock, atomic_read(&lock->cll_ref), - lock->cll_guarder, lock->cll_depth, - lock->cll_state, lock->cll_error, lock->cll_holds, - lock->cll_users, lock->cll_flags, - env, h->coh_nesting, cl_lock_nr_mutexed(env), - func, line); -} - -#define cl_lock_trace(level, env, prefix, lock) \ - cl_lock_trace0(level, env, prefix, lock, __func__, __LINE__) - -#define RETIP ((unsigned long)__builtin_return_address(0)) - -#ifdef CONFIG_LOCKDEP -static struct lock_class_key cl_lock_key; - -static void cl_lock_lockdep_init(struct cl_lock *lock) -{ - lockdep_set_class_and_name(lock, &cl_lock_key, "EXT"); -} - -static void cl_lock_lockdep_acquire(const struct lu_env *env, - struct cl_lock *lock, __u32 enqflags) -{ - cl_lock_counters(env, lock)->ctc_nr_locks_acquired++; - lock_map_acquire(&lock->dep_map); -} - -static void cl_lock_lockdep_release(const struct lu_env *env, - struct cl_lock *lock) -{ - cl_lock_counters(env, lock)->ctc_nr_locks_acquired--; - lock_release(&lock->dep_map, 0, RETIP); -} - -#else /* !CONFIG_LOCKDEP */ - -static void cl_lock_lockdep_init(struct cl_lock *lock) -{} -static void cl_lock_lockdep_acquire(const struct lu_env *env, - struct cl_lock *lock, __u32 enqflags) -{} -static void cl_lock_lockdep_release(const struct lu_env *env, - struct cl_lock *lock) -{} - -#endif /* !CONFIG_LOCKDEP */ - -/** - * Adds lock slice to the compound lock. - * - * This is called by cl_object_operations::coo_lock_init() methods to add a - * per-layer state to the lock. New state is added at the end of - * cl_lock::cll_layers list, that is, it is at the bottom of the stack. - * - * \see cl_req_slice_add(), cl_page_slice_add(), cl_io_slice_add() - */ -void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice, - struct cl_object *obj, - const struct cl_lock_operations *ops) -{ - slice->cls_lock = lock; - list_add_tail(&slice->cls_linkage, &lock->cll_layers); - slice->cls_obj = obj; - slice->cls_ops = ops; -} -EXPORT_SYMBOL(cl_lock_slice_add); - -/** - * Returns true iff a lock with the mode \a has provides at least the same - * guarantees as a lock with the mode \a need. - */ -int cl_lock_mode_match(enum cl_lock_mode has, enum cl_lock_mode need) -{ - LINVRNT(need == CLM_READ || need == CLM_WRITE || - need == CLM_PHANTOM || need == CLM_GROUP); - LINVRNT(has == CLM_READ || has == CLM_WRITE || - has == CLM_PHANTOM || has == CLM_GROUP); - CLASSERT(CLM_PHANTOM < CLM_READ); - CLASSERT(CLM_READ < CLM_WRITE); - CLASSERT(CLM_WRITE < CLM_GROUP); - - if (has != CLM_GROUP) - return need <= has; - else - return need == has; -} -EXPORT_SYMBOL(cl_lock_mode_match); - -/** - * Returns true iff extent portions of lock descriptions match. - */ -int cl_lock_ext_match(const struct cl_lock_descr *has, - const struct cl_lock_descr *need) -{ - return - has->cld_start <= need->cld_start && - has->cld_end >= need->cld_end && - cl_lock_mode_match(has->cld_mode, need->cld_mode) && - (has->cld_mode != CLM_GROUP || has->cld_gid == need->cld_gid); -} -EXPORT_SYMBOL(cl_lock_ext_match); - -/** - * Returns true iff a lock with the description \a has provides at least the - * same guarantees as a lock with the description \a need. - */ -int cl_lock_descr_match(const struct cl_lock_descr *has, - const struct cl_lock_descr *need) -{ - return - cl_object_same(has->cld_obj, need->cld_obj) && - cl_lock_ext_match(has, need); -} -EXPORT_SYMBOL(cl_lock_descr_match); - -static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock) -{ - struct cl_object *obj = lock->cll_descr.cld_obj; - - LINVRNT(!cl_lock_is_mutexed(lock)); - - cl_lock_trace(D_DLMTRACE, env, "free lock", lock); - while (!list_empty(&lock->cll_layers)) { - struct cl_lock_slice *slice; - - slice = list_entry(lock->cll_layers.next, - struct cl_lock_slice, cls_linkage); - list_del_init(lock->cll_layers.next); - slice->cls_ops->clo_fini(env, slice); - } - CS_LOCK_DEC(obj, total); - CS_LOCKSTATE_DEC(obj, lock->cll_state); - lu_object_ref_del_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock", lock); - cl_object_put(env, obj); - lu_ref_fini(&lock->cll_reference); - lu_ref_fini(&lock->cll_holders); - mutex_destroy(&lock->cll_guard); - kmem_cache_free(cl_lock_kmem, lock); -} - -/** - * Releases a reference on a lock. - * - * When last reference is released, lock is returned to the cache, unless it - * is in cl_lock_state::CLS_FREEING state, in which case it is destroyed - * immediately. - * - * \see cl_object_put(), cl_page_put() - */ -void cl_lock_put(const struct lu_env *env, struct cl_lock *lock) -{ - struct cl_object *obj; - - LINVRNT(cl_lock_invariant(env, lock)); - obj = lock->cll_descr.cld_obj; - LINVRNT(obj); - - CDEBUG(D_TRACE, "releasing reference: %d %p %lu\n", - atomic_read(&lock->cll_ref), lock, RETIP); - - if (atomic_dec_and_test(&lock->cll_ref)) { - if (lock->cll_state == CLS_FREEING) { - LASSERT(list_empty(&lock->cll_linkage)); - cl_lock_free(env, lock); - } - CS_LOCK_DEC(obj, busy); - } -} -EXPORT_SYMBOL(cl_lock_put); - -/** - * Acquires an additional reference to a lock. - * - * This can be called only by caller already possessing a reference to \a - * lock. - * - * \see cl_object_get(), cl_page_get() - */ -void cl_lock_get(struct cl_lock *lock) -{ - LINVRNT(cl_lock_invariant(NULL, lock)); - CDEBUG(D_TRACE, "acquiring reference: %d %p %lu\n", - atomic_read(&lock->cll_ref), lock, RETIP); - atomic_inc(&lock->cll_ref); -} -EXPORT_SYMBOL(cl_lock_get); - -/** - * Acquires a reference to a lock. - * - * This is much like cl_lock_get(), except that this function can be used to - * acquire initial reference to the cached lock. Caller has to deal with all - * possible races. Use with care! - * - * \see cl_page_get_trust() - */ -void cl_lock_get_trust(struct cl_lock *lock) -{ - CDEBUG(D_TRACE, "acquiring trusted reference: %d %p %lu\n", - atomic_read(&lock->cll_ref), lock, RETIP); - if (atomic_inc_return(&lock->cll_ref) == 1) - CS_LOCK_INC(lock->cll_descr.cld_obj, busy); -} -EXPORT_SYMBOL(cl_lock_get_trust); - -/** - * Helper function destroying the lock that wasn't completely initialized. - * - * Other threads can acquire references to the top-lock through its - * sub-locks. Hence, it cannot be cl_lock_free()-ed immediately. - */ -static void cl_lock_finish(const struct lu_env *env, struct cl_lock *lock) -{ - cl_lock_mutex_get(env, lock); - cl_lock_cancel(env, lock); - cl_lock_delete(env, lock); - cl_lock_mutex_put(env, lock); - cl_lock_put(env, lock); -} - -static struct cl_lock *cl_lock_alloc(const struct lu_env *env, - struct cl_object *obj, - const struct cl_io *io, - const struct cl_lock_descr *descr) -{ - struct cl_lock *lock; - struct lu_object_header *head; - - lock = kmem_cache_zalloc(cl_lock_kmem, GFP_NOFS); - if (lock) { - atomic_set(&lock->cll_ref, 1); - lock->cll_descr = *descr; - lock->cll_state = CLS_NEW; - cl_object_get(obj); - lu_object_ref_add_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock", - lock); - INIT_LIST_HEAD(&lock->cll_layers); - INIT_LIST_HEAD(&lock->cll_linkage); - INIT_LIST_HEAD(&lock->cll_inclosure); - lu_ref_init(&lock->cll_reference); - lu_ref_init(&lock->cll_holders); - mutex_init(&lock->cll_guard); - lockdep_set_class(&lock->cll_guard, &cl_lock_guard_class); - init_waitqueue_head(&lock->cll_wq); - head = obj->co_lu.lo_header; - CS_LOCKSTATE_INC(obj, CLS_NEW); - CS_LOCK_INC(obj, total); - CS_LOCK_INC(obj, create); - cl_lock_lockdep_init(lock); - list_for_each_entry(obj, &head->loh_layers, co_lu.lo_linkage) { - int err; - - err = obj->co_ops->coo_lock_init(env, obj, lock, io); - if (err != 0) { - cl_lock_finish(env, lock); - lock = ERR_PTR(err); - break; - } - } - } else - lock = ERR_PTR(-ENOMEM); - return lock; -} - -/** - * Transfer the lock into INTRANSIT state and return the original state. - * - * \pre state: CLS_CACHED, CLS_HELD or CLS_ENQUEUED - * \post state: CLS_INTRANSIT - * \see CLS_INTRANSIT - */ -static enum cl_lock_state cl_lock_intransit(const struct lu_env *env, - struct cl_lock *lock) -{ - enum cl_lock_state state = lock->cll_state; - - LASSERT(cl_lock_is_mutexed(lock)); - LASSERT(state != CLS_INTRANSIT); - LASSERTF(state >= CLS_ENQUEUED && state <= CLS_CACHED, - "Malformed lock state %d.\n", state); - - cl_lock_state_set(env, lock, CLS_INTRANSIT); - lock->cll_intransit_owner = current; - cl_lock_hold_add(env, lock, "intransit", current); - return state; -} - -/** - * Exit the intransit state and restore the lock state to the original state - */ -static void cl_lock_extransit(const struct lu_env *env, struct cl_lock *lock, - enum cl_lock_state state) -{ - LASSERT(cl_lock_is_mutexed(lock)); - LASSERT(lock->cll_state == CLS_INTRANSIT); - LASSERT(state != CLS_INTRANSIT); - LASSERT(lock->cll_intransit_owner == current); - - lock->cll_intransit_owner = NULL; - cl_lock_state_set(env, lock, state); - cl_lock_unhold(env, lock, "intransit", current); -} - -/** - * Checking whether the lock is intransit state - */ -int cl_lock_is_intransit(struct cl_lock *lock) -{ - LASSERT(cl_lock_is_mutexed(lock)); - return lock->cll_state == CLS_INTRANSIT && - lock->cll_intransit_owner != current; -} -EXPORT_SYMBOL(cl_lock_is_intransit); -/** - * Returns true iff lock is "suitable" for given io. E.g., locks acquired by - * truncate and O_APPEND cannot be reused for read/non-append-write, as they - * cover multiple stripes and can trigger cascading timeouts. - */ -static int cl_lock_fits_into(const struct lu_env *env, - const struct cl_lock *lock, - const struct cl_lock_descr *need, - const struct cl_io *io) -{ - const struct cl_lock_slice *slice; - - LINVRNT(cl_lock_invariant_trusted(env, lock)); - list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_ops->clo_fits_into && - !slice->cls_ops->clo_fits_into(env, slice, need, io)) - return 0; - } - return 1; -} - -static struct cl_lock *cl_lock_lookup(const struct lu_env *env, - struct cl_object *obj, - const struct cl_io *io, - const struct cl_lock_descr *need) -{ - struct cl_lock *lock; - struct cl_object_header *head; - - head = cl_object_header(obj); - assert_spin_locked(&head->coh_lock_guard); - CS_LOCK_INC(obj, lookup); - list_for_each_entry(lock, &head->coh_locks, cll_linkage) { - int matched; - - matched = cl_lock_ext_match(&lock->cll_descr, need) && - lock->cll_state < CLS_FREEING && - lock->cll_error == 0 && - !(lock->cll_flags & CLF_CANCELLED) && - cl_lock_fits_into(env, lock, need, io); - CDEBUG(D_DLMTRACE, "has: "DDESCR"(%d) need: "DDESCR": %d\n", - PDESCR(&lock->cll_descr), lock->cll_state, PDESCR(need), - matched); - if (matched) { - cl_lock_get_trust(lock); - CS_LOCK_INC(obj, hit); - return lock; - } - } - return NULL; -} - -/** - * Returns a lock matching description \a need. - * - * This is the main entry point into the cl_lock caching interface. First, a - * cache (implemented as a per-object linked list) is consulted. If lock is - * found there, it is returned immediately. Otherwise new lock is allocated - * and returned. In any case, additional reference to lock is acquired. - * - * \see cl_object_find(), cl_page_find() - */ -static struct cl_lock *cl_lock_find(const struct lu_env *env, - const struct cl_io *io, - const struct cl_lock_descr *need) -{ - struct cl_object_header *head; - struct cl_object *obj; - struct cl_lock *lock; - - obj = need->cld_obj; - head = cl_object_header(obj); - - spin_lock(&head->coh_lock_guard); - lock = cl_lock_lookup(env, obj, io, need); - spin_unlock(&head->coh_lock_guard); - - if (!lock) { - lock = cl_lock_alloc(env, obj, io, need); - if (!IS_ERR(lock)) { - struct cl_lock *ghost; - - spin_lock(&head->coh_lock_guard); - ghost = cl_lock_lookup(env, obj, io, need); - if (!ghost) { - cl_lock_get_trust(lock); - list_add_tail(&lock->cll_linkage, - &head->coh_locks); - spin_unlock(&head->coh_lock_guard); - CS_LOCK_INC(obj, busy); - } else { - spin_unlock(&head->coh_lock_guard); - /* - * Other threads can acquire references to the - * top-lock through its sub-locks. Hence, it - * cannot be cl_lock_free()-ed immediately. - */ - cl_lock_finish(env, lock); - lock = ghost; - } - } - } - return lock; -} - -/** - * Returns existing lock matching given description. This is similar to - * cl_lock_find() except that no new lock is created, and returned lock is - * guaranteed to be in enum cl_lock_state::CLS_HELD state. - */ -struct cl_lock *cl_lock_peek(const struct lu_env *env, const struct cl_io *io, - const struct cl_lock_descr *need, - const char *scope, const void *source) -{ - struct cl_object_header *head; - struct cl_object *obj; - struct cl_lock *lock; - - obj = need->cld_obj; - head = cl_object_header(obj); - - do { - spin_lock(&head->coh_lock_guard); - lock = cl_lock_lookup(env, obj, io, need); - spin_unlock(&head->coh_lock_guard); - if (!lock) - return NULL; - - cl_lock_mutex_get(env, lock); - if (lock->cll_state == CLS_INTRANSIT) - /* Don't care return value. */ - cl_lock_state_wait(env, lock); - if (lock->cll_state == CLS_FREEING) { - cl_lock_mutex_put(env, lock); - cl_lock_put(env, lock); - lock = NULL; - } - } while (!lock); - - cl_lock_hold_add(env, lock, scope, source); - cl_lock_user_add(env, lock); - if (lock->cll_state == CLS_CACHED) - cl_use_try(env, lock, 1); - if (lock->cll_state == CLS_HELD) { - cl_lock_mutex_put(env, lock); - cl_lock_lockdep_acquire(env, lock, 0); - cl_lock_put(env, lock); - } else { - cl_unuse_try(env, lock); - cl_lock_unhold(env, lock, scope, source); - cl_lock_mutex_put(env, lock); - cl_lock_put(env, lock); - lock = NULL; - } - - return lock; -} -EXPORT_SYMBOL(cl_lock_peek); - -/** - * Returns a slice within a lock, corresponding to the given layer in the - * device stack. - * - * \see cl_page_at() - */ -const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock, - const struct lu_device_type *dtype) -{ - const struct cl_lock_slice *slice; - - LINVRNT(cl_lock_invariant_trusted(NULL, lock)); - - list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_obj->co_lu.lo_dev->ld_type == dtype) - return slice; - } - return NULL; -} -EXPORT_SYMBOL(cl_lock_at); - -static void cl_lock_mutex_tail(const struct lu_env *env, struct cl_lock *lock) -{ - struct cl_thread_counters *counters; - - counters = cl_lock_counters(env, lock); - lock->cll_depth++; - counters->ctc_nr_locks_locked++; - lu_ref_add(&counters->ctc_locks_locked, "cll_guard", lock); - cl_lock_trace(D_TRACE, env, "got mutex", lock); -} - -/** - * Locks cl_lock object. - * - * This is used to manipulate cl_lock fields, and to serialize state - * transitions in the lock state machine. - * - * \post cl_lock_is_mutexed(lock) - * - * \see cl_lock_mutex_put() - */ -void cl_lock_mutex_get(const struct lu_env *env, struct cl_lock *lock) -{ - LINVRNT(cl_lock_invariant(env, lock)); - - if (lock->cll_guarder == current) { - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(lock->cll_depth > 0); - } else { - struct cl_object_header *hdr; - struct cl_thread_info *info; - int i; - - LINVRNT(lock->cll_guarder != current); - hdr = cl_object_header(lock->cll_descr.cld_obj); - /* - * Check that mutices are taken in the bottom-to-top order. - */ - info = cl_env_info(env); - for (i = 0; i < hdr->coh_nesting; ++i) - LASSERT(info->clt_counters[i].ctc_nr_locks_locked == 0); - mutex_lock_nested(&lock->cll_guard, hdr->coh_nesting); - lock->cll_guarder = current; - LINVRNT(lock->cll_depth == 0); - } - cl_lock_mutex_tail(env, lock); -} -EXPORT_SYMBOL(cl_lock_mutex_get); - -/** - * Try-locks cl_lock object. - * - * \retval 0 \a lock was successfully locked - * - * \retval -EBUSY \a lock cannot be locked right now - * - * \post ergo(result == 0, cl_lock_is_mutexed(lock)) - * - * \see cl_lock_mutex_get() - */ -static int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock) -{ - int result; - - LINVRNT(cl_lock_invariant_trusted(env, lock)); - - result = 0; - if (lock->cll_guarder == current) { - LINVRNT(lock->cll_depth > 0); - cl_lock_mutex_tail(env, lock); - } else if (mutex_trylock(&lock->cll_guard)) { - LINVRNT(lock->cll_depth == 0); - lock->cll_guarder = current; - cl_lock_mutex_tail(env, lock); - } else - result = -EBUSY; - return result; -} - -/** - {* Unlocks cl_lock object. - * - * \pre cl_lock_is_mutexed(lock) - * - * \see cl_lock_mutex_get() - */ -void cl_lock_mutex_put(const struct lu_env *env, struct cl_lock *lock) -{ - struct cl_thread_counters *counters; - - LINVRNT(cl_lock_invariant(env, lock)); - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(lock->cll_guarder == current); - LINVRNT(lock->cll_depth > 0); - - counters = cl_lock_counters(env, lock); - LINVRNT(counters->ctc_nr_locks_locked > 0); - - cl_lock_trace(D_TRACE, env, "put mutex", lock); - lu_ref_del(&counters->ctc_locks_locked, "cll_guard", lock); - counters->ctc_nr_locks_locked--; - if (--lock->cll_depth == 0) { - lock->cll_guarder = NULL; - mutex_unlock(&lock->cll_guard); - } -} -EXPORT_SYMBOL(cl_lock_mutex_put); - -/** - * Returns true iff lock's mutex is owned by the current thread. - */ -int cl_lock_is_mutexed(struct cl_lock *lock) -{ - return lock->cll_guarder == current; -} -EXPORT_SYMBOL(cl_lock_is_mutexed); - -/** - * Returns number of cl_lock mutices held by the current thread (environment). - */ -int cl_lock_nr_mutexed(const struct lu_env *env) -{ - struct cl_thread_info *info; - int i; - int locked; - - /* - * NOTE: if summation across all nesting levels (currently 2) proves - * too expensive, a summary counter can be added to - * struct cl_thread_info. - */ - info = cl_env_info(env); - for (i = 0, locked = 0; i < ARRAY_SIZE(info->clt_counters); ++i) - locked += info->clt_counters[i].ctc_nr_locks_locked; - return locked; -} -EXPORT_SYMBOL(cl_lock_nr_mutexed); - -static void cl_lock_cancel0(const struct lu_env *env, struct cl_lock *lock) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - if (!(lock->cll_flags & CLF_CANCELLED)) { - const struct cl_lock_slice *slice; - - lock->cll_flags |= CLF_CANCELLED; - list_for_each_entry_reverse(slice, &lock->cll_layers, - cls_linkage) { - if (slice->cls_ops->clo_cancel) - slice->cls_ops->clo_cancel(env, slice); - } - } -} - -static void cl_lock_delete0(const struct lu_env *env, struct cl_lock *lock) -{ - struct cl_object_header *head; - const struct cl_lock_slice *slice; - - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - - if (lock->cll_state < CLS_FREEING) { - bool in_cache; - - LASSERT(lock->cll_state != CLS_INTRANSIT); - cl_lock_state_set(env, lock, CLS_FREEING); - - head = cl_object_header(lock->cll_descr.cld_obj); - - spin_lock(&head->coh_lock_guard); - in_cache = !list_empty(&lock->cll_linkage); - if (in_cache) - list_del_init(&lock->cll_linkage); - spin_unlock(&head->coh_lock_guard); - - if (in_cache) /* coh_locks cache holds a refcount. */ - cl_lock_put(env, lock); - - /* - * From now on, no new references to this lock can be acquired - * by cl_lock_lookup(). - */ - list_for_each_entry_reverse(slice, &lock->cll_layers, - cls_linkage) { - if (slice->cls_ops->clo_delete) - slice->cls_ops->clo_delete(env, slice); - } - /* - * From now on, no new references to this lock can be acquired - * by layer-specific means (like a pointer from struct - * ldlm_lock in osc, or a pointer from top-lock to sub-lock in - * lov). - * - * Lock will be finally freed in cl_lock_put() when last of - * existing references goes away. - */ - } -} - -/** - * Mod(ifie)s cl_lock::cll_holds counter for a given lock. Also, for a - * top-lock (nesting == 0) accounts for this modification in the per-thread - * debugging counters. Sub-lock holds can be released by a thread different - * from one that acquired it. - */ -static void cl_lock_hold_mod(const struct lu_env *env, struct cl_lock *lock, - int delta) -{ - struct cl_thread_counters *counters; - enum clt_nesting_level nesting; - - lock->cll_holds += delta; - nesting = cl_lock_nesting(lock); - if (nesting == CNL_TOP) { - counters = &cl_env_info(env)->clt_counters[CNL_TOP]; - counters->ctc_nr_held += delta; - LASSERT(counters->ctc_nr_held >= 0); - } -} - -/** - * Mod(ifie)s cl_lock::cll_users counter for a given lock. See - * cl_lock_hold_mod() for the explanation of the debugging code. - */ -static void cl_lock_used_mod(const struct lu_env *env, struct cl_lock *lock, - int delta) -{ - struct cl_thread_counters *counters; - enum clt_nesting_level nesting; - - lock->cll_users += delta; - nesting = cl_lock_nesting(lock); - if (nesting == CNL_TOP) { - counters = &cl_env_info(env)->clt_counters[CNL_TOP]; - counters->ctc_nr_used += delta; - LASSERT(counters->ctc_nr_used >= 0); - } -} - -void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERT(lock->cll_holds > 0); - - cl_lock_trace(D_DLMTRACE, env, "hold release lock", lock); - lu_ref_del(&lock->cll_holders, scope, source); - cl_lock_hold_mod(env, lock, -1); - if (lock->cll_holds == 0) { - CL_LOCK_ASSERT(lock->cll_state != CLS_HELD, env, lock); - if (lock->cll_descr.cld_mode == CLM_PHANTOM || - lock->cll_descr.cld_mode == CLM_GROUP || - lock->cll_state != CLS_CACHED) - /* - * If lock is still phantom or grouplock when user is - * done with it---destroy the lock. - */ - lock->cll_flags |= CLF_CANCELPEND|CLF_DOOMED; - if (lock->cll_flags & CLF_CANCELPEND) { - lock->cll_flags &= ~CLF_CANCELPEND; - cl_lock_cancel0(env, lock); - } - if (lock->cll_flags & CLF_DOOMED) { - /* no longer doomed: it's dead... Jim. */ - lock->cll_flags &= ~CLF_DOOMED; - cl_lock_delete0(env, lock); - } - } -} -EXPORT_SYMBOL(cl_lock_hold_release); - -/** - * Waits until lock state is changed. - * - * This function is called with cl_lock mutex locked, atomically releases - * mutex and goes to sleep, waiting for a lock state change (signaled by - * cl_lock_signal()), and re-acquires the mutex before return. - * - * This function is used to wait until lock state machine makes some progress - * and to emulate synchronous operations on top of asynchronous lock - * interface. - * - * \retval -EINTR wait was interrupted - * - * \retval 0 wait wasn't interrupted - * - * \pre cl_lock_is_mutexed(lock) - * - * \see cl_lock_signal() - */ -int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock) -{ - wait_queue_t waiter; - sigset_t blocked; - int result; - - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERT(lock->cll_depth == 1); - LASSERT(lock->cll_state != CLS_FREEING); /* too late to wait */ - - cl_lock_trace(D_DLMTRACE, env, "state wait lock", lock); - result = lock->cll_error; - if (result == 0) { - /* To avoid being interrupted by the 'non-fatal' signals - * (SIGCHLD, for instance), we'd block them temporarily. - * LU-305 - */ - blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); - - init_waitqueue_entry(&waiter, current); - add_wait_queue(&lock->cll_wq, &waiter); - set_current_state(TASK_INTERRUPTIBLE); - cl_lock_mutex_put(env, lock); - - LASSERT(cl_lock_nr_mutexed(env) == 0); - - /* Returning ERESTARTSYS instead of EINTR so syscalls - * can be restarted if signals are pending here - */ - result = -ERESTARTSYS; - if (likely(!OBD_FAIL_CHECK(OBD_FAIL_LOCK_STATE_WAIT_INTR))) { - schedule(); - if (!signal_pending(current)) - result = 0; - } - - cl_lock_mutex_get(env, lock); - set_current_state(TASK_RUNNING); - remove_wait_queue(&lock->cll_wq, &waiter); - - /* Restore old blocked signals */ - cfs_restore_sigs(blocked); - } - return result; -} -EXPORT_SYMBOL(cl_lock_state_wait); - -static void cl_lock_state_signal(const struct lu_env *env, struct cl_lock *lock, - enum cl_lock_state state) -{ - const struct cl_lock_slice *slice; - - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - - list_for_each_entry(slice, &lock->cll_layers, cls_linkage) - if (slice->cls_ops->clo_state) - slice->cls_ops->clo_state(env, slice, state); - wake_up_all(&lock->cll_wq); -} - -/** - * Notifies waiters that lock state changed. - * - * Wakes up all waiters sleeping in cl_lock_state_wait(), also notifies all - * layers about state change by calling cl_lock_operations::clo_state() - * top-to-bottom. - */ -void cl_lock_signal(const struct lu_env *env, struct cl_lock *lock) -{ - cl_lock_trace(D_DLMTRACE, env, "state signal lock", lock); - cl_lock_state_signal(env, lock, lock->cll_state); -} -EXPORT_SYMBOL(cl_lock_signal); - -/** - * Changes lock state. - * - * This function is invoked to notify layers that lock state changed, possible - * as a result of an asynchronous event such as call-back reception. - * - * \post lock->cll_state == state - * - * \see cl_lock_operations::clo_state() - */ -void cl_lock_state_set(const struct lu_env *env, struct cl_lock *lock, - enum cl_lock_state state) -{ - LASSERT(lock->cll_state <= state || - (lock->cll_state == CLS_CACHED && - (state == CLS_HELD || /* lock found in cache */ - state == CLS_NEW || /* sub-lock canceled */ - state == CLS_INTRANSIT)) || - /* lock is in transit state */ - lock->cll_state == CLS_INTRANSIT); - - if (lock->cll_state != state) { - CS_LOCKSTATE_DEC(lock->cll_descr.cld_obj, lock->cll_state); - CS_LOCKSTATE_INC(lock->cll_descr.cld_obj, state); - - cl_lock_state_signal(env, lock, state); - lock->cll_state = state; - } -} -EXPORT_SYMBOL(cl_lock_state_set); - -static int cl_unuse_try_internal(const struct lu_env *env, struct cl_lock *lock) -{ - const struct cl_lock_slice *slice; - int result; - - do { - result = 0; - - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERT(lock->cll_state == CLS_INTRANSIT); - - result = -ENOSYS; - list_for_each_entry_reverse(slice, &lock->cll_layers, - cls_linkage) { - if (slice->cls_ops->clo_unuse) { - result = slice->cls_ops->clo_unuse(env, slice); - if (result != 0) - break; - } - } - LASSERT(result != -ENOSYS); - } while (result == CLO_REPEAT); - - return result; -} - -/** - * Yanks lock from the cache (cl_lock_state::CLS_CACHED state) by calling - * cl_lock_operations::clo_use() top-to-bottom to notify layers. - * @atomic = 1, it must unuse the lock to recovery the lock to keep the - * use process atomic - */ -int cl_use_try(const struct lu_env *env, struct cl_lock *lock, int atomic) -{ - const struct cl_lock_slice *slice; - int result; - enum cl_lock_state state; - - cl_lock_trace(D_DLMTRACE, env, "use lock", lock); - - LASSERT(lock->cll_state == CLS_CACHED); - if (lock->cll_error) - return lock->cll_error; - - result = -ENOSYS; - state = cl_lock_intransit(env, lock); - list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_ops->clo_use) { - result = slice->cls_ops->clo_use(env, slice); - if (result != 0) - break; - } - } - LASSERT(result != -ENOSYS); - - LASSERTF(lock->cll_state == CLS_INTRANSIT, "Wrong state %d.\n", - lock->cll_state); - - if (result == 0) { - state = CLS_HELD; - } else { - if (result == -ESTALE) { - /* - * ESTALE means sublock being cancelled - * at this time, and set lock state to - * be NEW here and ask the caller to repeat. - */ - state = CLS_NEW; - result = CLO_REPEAT; - } - - /* @atomic means back-off-on-failure. */ - if (atomic) { - int rc; - - rc = cl_unuse_try_internal(env, lock); - /* Vet the results. */ - if (rc < 0 && result > 0) - result = rc; - } - - } - cl_lock_extransit(env, lock, state); - return result; -} -EXPORT_SYMBOL(cl_use_try); - -/** - * Helper for cl_enqueue_try() that calls ->clo_enqueue() across all layers - * top-to-bottom. - */ -static int cl_enqueue_kick(const struct lu_env *env, - struct cl_lock *lock, - struct cl_io *io, __u32 flags) -{ - int result; - const struct cl_lock_slice *slice; - - result = -ENOSYS; - list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_ops->clo_enqueue) { - result = slice->cls_ops->clo_enqueue(env, - slice, io, flags); - if (result != 0) - break; - } - } - LASSERT(result != -ENOSYS); - return result; -} - -/** - * Tries to enqueue a lock. - * - * This function is called repeatedly by cl_enqueue() until either lock is - * enqueued, or error occurs. This function does not block waiting for - * networking communication to complete. - * - * \post ergo(result == 0, lock->cll_state == CLS_ENQUEUED || - * lock->cll_state == CLS_HELD) - * - * \see cl_enqueue() cl_lock_operations::clo_enqueue() - * \see cl_lock_state::CLS_ENQUEUED - */ -int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock, - struct cl_io *io, __u32 flags) -{ - int result; - - cl_lock_trace(D_DLMTRACE, env, "enqueue lock", lock); - do { - LINVRNT(cl_lock_is_mutexed(lock)); - - result = lock->cll_error; - if (result != 0) - break; - - switch (lock->cll_state) { - case CLS_NEW: - cl_lock_state_set(env, lock, CLS_QUEUING); - /* fall-through */ - case CLS_QUEUING: - /* kick layers. */ - result = cl_enqueue_kick(env, lock, io, flags); - /* For AGL case, the cl_lock::cll_state may - * become CLS_HELD already. - */ - if (result == 0 && lock->cll_state == CLS_QUEUING) - cl_lock_state_set(env, lock, CLS_ENQUEUED); - break; - case CLS_INTRANSIT: - LASSERT(cl_lock_is_intransit(lock)); - result = CLO_WAIT; - break; - case CLS_CACHED: - /* yank lock from the cache. */ - result = cl_use_try(env, lock, 0); - break; - case CLS_ENQUEUED: - case CLS_HELD: - result = 0; - break; - default: - case CLS_FREEING: - /* - * impossible, only held locks with increased - * ->cll_holds can be enqueued, and they cannot be - * freed. - */ - LBUG(); - } - } while (result == CLO_REPEAT); - return result; -} -EXPORT_SYMBOL(cl_enqueue_try); - -/** - * Cancel the conflicting lock found during previous enqueue. - * - * \retval 0 conflicting lock has been canceled. - * \retval -ve error code. - */ -int cl_lock_enqueue_wait(const struct lu_env *env, - struct cl_lock *lock, - int keep_mutex) -{ - struct cl_lock *conflict; - int rc = 0; - - LASSERT(cl_lock_is_mutexed(lock)); - LASSERT(lock->cll_state == CLS_QUEUING); - LASSERT(lock->cll_conflict); - - conflict = lock->cll_conflict; - lock->cll_conflict = NULL; - - cl_lock_mutex_put(env, lock); - LASSERT(cl_lock_nr_mutexed(env) == 0); - - cl_lock_mutex_get(env, conflict); - cl_lock_trace(D_DLMTRACE, env, "enqueue wait", conflict); - cl_lock_cancel(env, conflict); - cl_lock_delete(env, conflict); - - while (conflict->cll_state != CLS_FREEING) { - rc = cl_lock_state_wait(env, conflict); - if (rc != 0) - break; - } - cl_lock_mutex_put(env, conflict); - lu_ref_del(&conflict->cll_reference, "cancel-wait", lock); - cl_lock_put(env, conflict); - - if (keep_mutex) - cl_lock_mutex_get(env, lock); - - LASSERT(rc <= 0); - return rc; -} -EXPORT_SYMBOL(cl_lock_enqueue_wait); - -static int cl_enqueue_locked(const struct lu_env *env, struct cl_lock *lock, - struct cl_io *io, __u32 enqflags) +static void cl_lock_trace0(int level, const struct lu_env *env, + const char *prefix, const struct cl_lock *lock, + const char *func, const int line) { - int result; - - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERT(lock->cll_holds > 0); + struct cl_object_header *h = cl_object_header(lock->cll_descr.cld_obj); - cl_lock_user_add(env, lock); - do { - result = cl_enqueue_try(env, lock, io, enqflags); - if (result == CLO_WAIT) { - if (lock->cll_conflict) - result = cl_lock_enqueue_wait(env, lock, 1); - else - result = cl_lock_state_wait(env, lock); - if (result == 0) - continue; - } - break; - } while (1); - if (result != 0) - cl_unuse_try(env, lock); - LASSERT(ergo(result == 0 && !(enqflags & CEF_AGL), - lock->cll_state == CLS_ENQUEUED || - lock->cll_state == CLS_HELD)); - return result; + CDEBUG(level, "%s: %p (%p/%d) at %s():%d\n", + prefix, lock, env, h->coh_nesting, func, line); } +#define cl_lock_trace(level, env, prefix, lock) \ + cl_lock_trace0(level, env, prefix, lock, __func__, __LINE__) /** - * Tries to unlock a lock. - * - * This function is called to release underlying resource: - * 1. for top lock, the resource is sublocks it held; - * 2. for sublock, the resource is the reference to dlmlock. + * Adds lock slice to the compound lock. * - * cl_unuse_try is a one-shot operation, so it must NOT return CLO_WAIT. + * This is called by cl_object_operations::coo_lock_init() methods to add a + * per-layer state to the lock. New state is added at the end of + * cl_lock::cll_layers list, that is, it is at the bottom of the stack. * - * \see cl_unuse() cl_lock_operations::clo_unuse() - * \see cl_lock_state::CLS_CACHED + * \see cl_req_slice_add(), cl_page_slice_add(), cl_io_slice_add() */ -int cl_unuse_try(const struct lu_env *env, struct cl_lock *lock) +void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice, + struct cl_object *obj, + const struct cl_lock_operations *ops) { - int result; - enum cl_lock_state state = CLS_NEW; - - cl_lock_trace(D_DLMTRACE, env, "unuse lock", lock); - - if (lock->cll_users > 1) { - cl_lock_user_del(env, lock); - return 0; - } - - /* Only if the lock is in CLS_HELD or CLS_ENQUEUED state, it can hold - * underlying resources. - */ - if (!(lock->cll_state == CLS_HELD || lock->cll_state == CLS_ENQUEUED)) { - cl_lock_user_del(env, lock); - return 0; - } - - /* - * New lock users (->cll_users) are not protecting unlocking - * from proceeding. From this point, lock eventually reaches - * CLS_CACHED, is reinitialized to CLS_NEW or fails into - * CLS_FREEING. - */ - state = cl_lock_intransit(env, lock); - - result = cl_unuse_try_internal(env, lock); - LASSERT(lock->cll_state == CLS_INTRANSIT); - LASSERT(result != CLO_WAIT); - cl_lock_user_del(env, lock); - if (result == 0 || result == -ESTALE) { - /* - * Return lock back to the cache. This is the only - * place where lock is moved into CLS_CACHED state. - * - * If one of ->clo_unuse() methods returned -ESTALE, lock - * cannot be placed into cache and has to be - * re-initialized. This happens e.g., when a sub-lock was - * canceled while unlocking was in progress. - */ - if (state == CLS_HELD && result == 0) - state = CLS_CACHED; - else - state = CLS_NEW; - cl_lock_extransit(env, lock, state); - - /* - * Hide -ESTALE error. - * If the lock is a glimpse lock, and it has multiple - * stripes. Assuming that one of its sublock returned -ENAVAIL, - * and other sublocks are matched write locks. In this case, - * we can't set this lock to error because otherwise some of - * its sublocks may not be canceled. This causes some dirty - * pages won't be written to OSTs. -jay - */ - result = 0; - } else { - CERROR("result = %d, this is unlikely!\n", result); - state = CLS_NEW; - cl_lock_extransit(env, lock, state); - } - return result ?: lock->cll_error; + slice->cls_lock = lock; + list_add_tail(&slice->cls_linkage, &lock->cll_layers); + slice->cls_obj = obj; + slice->cls_ops = ops; } -EXPORT_SYMBOL(cl_unuse_try); +EXPORT_SYMBOL(cl_lock_slice_add); -static void cl_unuse_locked(const struct lu_env *env, struct cl_lock *lock) +void cl_lock_fini(const struct lu_env *env, struct cl_lock *lock) { - int result; + cl_lock_trace(D_DLMTRACE, env, "destroy lock", lock); - result = cl_unuse_try(env, lock); - if (result) - CL_LOCK_DEBUG(D_ERROR, env, lock, "unuse return %d\n", result); -} + while (!list_empty(&lock->cll_layers)) { + struct cl_lock_slice *slice; -/** - * Unlocks a lock. - */ -void cl_unuse(const struct lu_env *env, struct cl_lock *lock) -{ - cl_lock_mutex_get(env, lock); - cl_unuse_locked(env, lock); - cl_lock_mutex_put(env, lock); - cl_lock_lockdep_release(env, lock); + slice = list_entry(lock->cll_layers.next, + struct cl_lock_slice, cls_linkage); + list_del_init(lock->cll_layers.next); + slice->cls_ops->clo_fini(env, slice); + } + POISON(lock, 0x5a, sizeof(*lock)); } -EXPORT_SYMBOL(cl_unuse); +EXPORT_SYMBOL(cl_lock_fini); -/** - * Tries to wait for a lock. - * - * This function is called repeatedly by cl_wait() until either lock is - * granted, or error occurs. This function does not block waiting for network - * communication to complete. - * - * \see cl_wait() cl_lock_operations::clo_wait() - * \see cl_lock_state::CLS_HELD - */ -int cl_wait_try(const struct lu_env *env, struct cl_lock *lock) +int cl_lock_init(const struct lu_env *env, struct cl_lock *lock, + const struct cl_io *io) { - const struct cl_lock_slice *slice; - int result; - - cl_lock_trace(D_DLMTRACE, env, "wait lock try", lock); - do { - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERTF(lock->cll_state == CLS_QUEUING || - lock->cll_state == CLS_ENQUEUED || - lock->cll_state == CLS_HELD || - lock->cll_state == CLS_INTRANSIT, - "lock state: %d\n", lock->cll_state); - LASSERT(lock->cll_users > 0); - LASSERT(lock->cll_holds > 0); + struct cl_object *obj = lock->cll_descr.cld_obj; + struct cl_object *scan; + int result = 0; - result = lock->cll_error; - if (result != 0) - break; + /* Make sure cl_lock::cll_descr is initialized. */ + LASSERT(obj); - if (cl_lock_is_intransit(lock)) { - result = CLO_WAIT; + INIT_LIST_HEAD(&lock->cll_layers); + list_for_each_entry(scan, &obj->co_lu.lo_header->loh_layers, + co_lu.lo_linkage) { + result = scan->co_ops->coo_lock_init(env, scan, lock, io); + if (result != 0) { + cl_lock_fini(env, lock); break; } + } - if (lock->cll_state == CLS_HELD) - /* nothing to do */ - break; - - result = -ENOSYS; - list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_ops->clo_wait) { - result = slice->cls_ops->clo_wait(env, slice); - if (result != 0) - break; - } - } - LASSERT(result != -ENOSYS); - if (result == 0) { - LASSERT(lock->cll_state != CLS_INTRANSIT); - cl_lock_state_set(env, lock, CLS_HELD); - } - } while (result == CLO_REPEAT); return result; } -EXPORT_SYMBOL(cl_wait_try); +EXPORT_SYMBOL(cl_lock_init); /** - * Waits until enqueued lock is granted. - * - * \pre current thread or io owns a hold on the lock - * \pre ergo(result == 0, lock->cll_state == CLS_ENQUEUED || - * lock->cll_state == CLS_HELD) + * Returns a slice with a lock, corresponding to the given layer in the + * device stack. * - * \post ergo(result == 0, lock->cll_state == CLS_HELD) - */ -int cl_wait(const struct lu_env *env, struct cl_lock *lock) -{ - int result; - - cl_lock_mutex_get(env, lock); - - LINVRNT(cl_lock_invariant(env, lock)); - LASSERTF(lock->cll_state == CLS_ENQUEUED || lock->cll_state == CLS_HELD, - "Wrong state %d\n", lock->cll_state); - LASSERT(lock->cll_holds > 0); - - do { - result = cl_wait_try(env, lock); - if (result == CLO_WAIT) { - result = cl_lock_state_wait(env, lock); - if (result == 0) - continue; - } - break; - } while (1); - if (result < 0) { - cl_unuse_try(env, lock); - cl_lock_lockdep_release(env, lock); - } - cl_lock_trace(D_DLMTRACE, env, "wait lock", lock); - cl_lock_mutex_put(env, lock); - LASSERT(ergo(result == 0, lock->cll_state == CLS_HELD)); - return result; -} -EXPORT_SYMBOL(cl_wait); - -/** - * Executes cl_lock_operations::clo_weigh(), and sums results to estimate lock - * value. + * \see cl_page_at() */ -unsigned long cl_lock_weigh(const struct lu_env *env, struct cl_lock *lock) +const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock, + const struct lu_device_type *dtype) { const struct cl_lock_slice *slice; - unsigned long pound; - unsigned long ounce; - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - - pound = 0; - list_for_each_entry_reverse(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_ops->clo_weigh) { - ounce = slice->cls_ops->clo_weigh(env, slice); - pound += ounce; - if (pound < ounce) /* over-weight^Wflow */ - pound = ~0UL; - } + list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { + if (slice->cls_obj->co_lu.lo_dev->ld_type == dtype) + return slice; } - return pound; + return NULL; } -EXPORT_SYMBOL(cl_lock_weigh); +EXPORT_SYMBOL(cl_lock_at); -/** - * Notifies layers that lock description changed. - * - * The server can grant client a lock different from one that was requested - * (e.g., larger in extent). This method is called when actually granted lock - * description becomes known to let layers to accommodate for changed lock - * description. - * - * \see cl_lock_operations::clo_modify() - */ -int cl_lock_modify(const struct lu_env *env, struct cl_lock *lock, - const struct cl_lock_descr *desc) +void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock) { const struct cl_lock_slice *slice; - struct cl_object *obj = lock->cll_descr.cld_obj; - struct cl_object_header *hdr = cl_object_header(obj); - int result; - - cl_lock_trace(D_DLMTRACE, env, "modify lock", lock); - /* don't allow object to change */ - LASSERT(obj == desc->cld_obj); - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); + cl_lock_trace(D_DLMTRACE, env, "cancel lock", lock); list_for_each_entry_reverse(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_ops->clo_modify) { - result = slice->cls_ops->clo_modify(env, slice, desc); - if (result != 0) - return result; - } - } - CL_LOCK_DEBUG(D_DLMTRACE, env, lock, " -> "DDESCR"@"DFID"\n", - PDESCR(desc), PFID(lu_object_fid(&desc->cld_obj->co_lu))); - /* - * Just replace description in place. Nothing more is needed for - * now. If locks were indexed according to their extent and/or mode, - * that index would have to be updated here. - */ - spin_lock(&hdr->coh_lock_guard); - lock->cll_descr = *desc; - spin_unlock(&hdr->coh_lock_guard); - return 0; -} -EXPORT_SYMBOL(cl_lock_modify); - -/** - * Initializes lock closure with a given origin. - * - * \see cl_lock_closure - */ -void cl_lock_closure_init(const struct lu_env *env, - struct cl_lock_closure *closure, - struct cl_lock *origin, int wait) -{ - LINVRNT(cl_lock_is_mutexed(origin)); - LINVRNT(cl_lock_invariant(env, origin)); - - INIT_LIST_HEAD(&closure->clc_list); - closure->clc_origin = origin; - closure->clc_wait = wait; - closure->clc_nr = 0; -} -EXPORT_SYMBOL(cl_lock_closure_init); - -/** - * Builds a closure of \a lock. - * - * Building of a closure consists of adding initial lock (\a lock) into it, - * and calling cl_lock_operations::clo_closure() methods of \a lock. These - * methods might call cl_lock_closure_build() recursively again, adding more - * locks to the closure, etc. - * - * \see cl_lock_closure - */ -int cl_lock_closure_build(const struct lu_env *env, struct cl_lock *lock, - struct cl_lock_closure *closure) -{ - const struct cl_lock_slice *slice; - int result; - - LINVRNT(cl_lock_is_mutexed(closure->clc_origin)); - LINVRNT(cl_lock_invariant(env, closure->clc_origin)); - - result = cl_lock_enclosure(env, lock, closure); - if (result == 0) { - list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { - if (slice->cls_ops->clo_closure) { - result = slice->cls_ops->clo_closure(env, slice, - closure); - if (result != 0) - break; - } - } - } - if (result != 0) - cl_lock_disclosure(env, closure); - return result; -} -EXPORT_SYMBOL(cl_lock_closure_build); - -/** - * Adds new lock to a closure. - * - * Try-locks \a lock and if succeeded, adds it to the closure (never more than - * once). If try-lock failed, returns CLO_REPEAT, after optionally waiting - * until next try-lock is likely to succeed. - */ -int cl_lock_enclosure(const struct lu_env *env, struct cl_lock *lock, - struct cl_lock_closure *closure) -{ - int result = 0; - - cl_lock_trace(D_DLMTRACE, env, "enclosure lock", lock); - if (!cl_lock_mutex_try(env, lock)) { - /* - * If lock->cll_inclosure is not empty, lock is already in - * this closure. - */ - if (list_empty(&lock->cll_inclosure)) { - cl_lock_get_trust(lock); - lu_ref_add(&lock->cll_reference, "closure", closure); - list_add(&lock->cll_inclosure, &closure->clc_list); - closure->clc_nr++; - } else - cl_lock_mutex_put(env, lock); - result = 0; - } else { - cl_lock_disclosure(env, closure); - if (closure->clc_wait) { - cl_lock_get_trust(lock); - lu_ref_add(&lock->cll_reference, "closure-w", closure); - cl_lock_mutex_put(env, closure->clc_origin); - - LASSERT(cl_lock_nr_mutexed(env) == 0); - cl_lock_mutex_get(env, lock); - cl_lock_mutex_put(env, lock); - - cl_lock_mutex_get(env, closure->clc_origin); - lu_ref_del(&lock->cll_reference, "closure-w", closure); - cl_lock_put(env, lock); - } - result = CLO_REPEAT; - } - return result; -} -EXPORT_SYMBOL(cl_lock_enclosure); - -/** Releases mutices of enclosed locks. */ -void cl_lock_disclosure(const struct lu_env *env, - struct cl_lock_closure *closure) -{ - struct cl_lock *scan; - struct cl_lock *temp; - - cl_lock_trace(D_DLMTRACE, env, "disclosure lock", closure->clc_origin); - list_for_each_entry_safe(scan, temp, &closure->clc_list, - cll_inclosure) { - list_del_init(&scan->cll_inclosure); - cl_lock_mutex_put(env, scan); - lu_ref_del(&scan->cll_reference, "closure", closure); - cl_lock_put(env, scan); - closure->clc_nr--; - } - LASSERT(closure->clc_nr == 0); -} -EXPORT_SYMBOL(cl_lock_disclosure); - -/** Finalizes a closure. */ -void cl_lock_closure_fini(struct cl_lock_closure *closure) -{ - LASSERT(closure->clc_nr == 0); - LASSERT(list_empty(&closure->clc_list)); -} -EXPORT_SYMBOL(cl_lock_closure_fini); - -/** - * Destroys this lock. Notifies layers (bottom-to-top) that lock is being - * destroyed, then destroy the lock. If there are holds on the lock, postpone - * destruction until all holds are released. This is called when a decision is - * made to destroy the lock in the future. E.g., when a blocking AST is - * received on it, or fatal communication error happens. - * - * Caller must have a reference on this lock to prevent a situation, when - * deleted lock lingers in memory for indefinite time, because nobody calls - * cl_lock_put() to finish it. - * - * \pre atomic_read(&lock->cll_ref) > 0 - * \pre ergo(cl_lock_nesting(lock) == CNL_TOP, - * cl_lock_nr_mutexed(env) == 1) - * [i.e., if a top-lock is deleted, mutices of no other locks can be - * held, as deletion of sub-locks might require releasing a top-lock - * mutex] - * - * \see cl_lock_operations::clo_delete() - * \see cl_lock::cll_holds - */ -void cl_lock_delete(const struct lu_env *env, struct cl_lock *lock) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERT(ergo(cl_lock_nesting(lock) == CNL_TOP, - cl_lock_nr_mutexed(env) == 1)); - - cl_lock_trace(D_DLMTRACE, env, "delete lock", lock); - if (lock->cll_holds == 0) - cl_lock_delete0(env, lock); - else - lock->cll_flags |= CLF_DOOMED; -} -EXPORT_SYMBOL(cl_lock_delete); - -/** - * Mark lock as irrecoverably failed, and mark it for destruction. This - * happens when, e.g., server fails to grant a lock to us, or networking - * time-out happens. - * - * \pre atomic_read(&lock->cll_ref) > 0 - * - * \see clo_lock_delete() - * \see cl_lock::cll_holds - */ -void cl_lock_error(const struct lu_env *env, struct cl_lock *lock, int error) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - - if (lock->cll_error == 0 && error != 0) { - cl_lock_trace(D_DLMTRACE, env, "set lock error", lock); - lock->cll_error = error; - cl_lock_signal(env, lock); - cl_lock_cancel(env, lock); - cl_lock_delete(env, lock); + if (slice->cls_ops->clo_cancel) + slice->cls_ops->clo_cancel(env, slice); } } -EXPORT_SYMBOL(cl_lock_error); - -/** - * Cancels this lock. Notifies layers - * (bottom-to-top) that lock is being cancelled, then destroy the lock. If - * there are holds on the lock, postpone cancellation until - * all holds are released. - * - * Cancellation notification is delivered to layers at most once. - * - * \see cl_lock_operations::clo_cancel() - * \see cl_lock::cll_holds - */ -void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - - cl_lock_trace(D_DLMTRACE, env, "cancel lock", lock); - if (lock->cll_holds == 0) - cl_lock_cancel0(env, lock); - else - lock->cll_flags |= CLF_CANCELPEND; -} EXPORT_SYMBOL(cl_lock_cancel); /** - * Finds an existing lock covering given index and optionally different from a - * given \a except lock. + * Enqueue a lock. + * \param anchor: if we need to wait for resources before getting the lock, + * use @anchor for the purpose. + * \retval 0 enqueue successfully + * \retval <0 error code */ -struct cl_lock *cl_lock_at_pgoff(const struct lu_env *env, - struct cl_object *obj, pgoff_t index, - struct cl_lock *except, - int pending, int canceld) +int cl_lock_enqueue(const struct lu_env *env, struct cl_io *io, + struct cl_lock *lock, struct cl_sync_io *anchor) { - struct cl_object_header *head; - struct cl_lock *scan; - struct cl_lock *lock; - struct cl_lock_descr *need; - - head = cl_object_header(obj); - need = &cl_env_info(env)->clt_descr; - lock = NULL; + const struct cl_lock_slice *slice; + int rc = -ENOSYS; - need->cld_mode = CLM_READ; /* CLM_READ matches both READ & WRITE, but - * not PHANTOM - */ - need->cld_start = need->cld_end = index; - need->cld_enq_flags = 0; + list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { + if (!slice->cls_ops->clo_enqueue) + continue; - spin_lock(&head->coh_lock_guard); - /* It is fine to match any group lock since there could be only one - * with a uniq gid and it conflicts with all other lock modes too - */ - list_for_each_entry(scan, &head->coh_locks, cll_linkage) { - if (scan != except && - (scan->cll_descr.cld_mode == CLM_GROUP || - cl_lock_ext_match(&scan->cll_descr, need)) && - scan->cll_state >= CLS_HELD && - scan->cll_state < CLS_FREEING && - /* - * This check is racy as the lock can be canceled right - * after it is done, but this is fine, because page exists - * already. - */ - (canceld || !(scan->cll_flags & CLF_CANCELLED)) && - (pending || !(scan->cll_flags & CLF_CANCELPEND))) { - /* Don't increase cs_hit here since this - * is just a helper function. - */ - cl_lock_get_trust(scan); - lock = scan; + rc = slice->cls_ops->clo_enqueue(env, slice, io, anchor); + if (rc != 0) break; } - } - spin_unlock(&head->coh_lock_guard); - return lock; + return rc; } -EXPORT_SYMBOL(cl_lock_at_pgoff); +EXPORT_SYMBOL(cl_lock_enqueue); /** - * Eliminate all locks for a given object. - * - * Caller has to guarantee that no lock is in active use. - * - * \param cancel when this is set, cl_locks_prune() cancels locks before - * destroying. + * Main high-level entry point of cl_lock interface that finds existing or + * enqueues new lock matching given description. */ -void cl_locks_prune(const struct lu_env *env, struct cl_object *obj, int cancel) +int cl_lock_request(const struct lu_env *env, struct cl_io *io, + struct cl_lock *lock) { - struct cl_object_header *head; - struct cl_lock *lock; - - head = cl_object_header(obj); - - spin_lock(&head->coh_lock_guard); - while (!list_empty(&head->coh_locks)) { - lock = container_of(head->coh_locks.next, - struct cl_lock, cll_linkage); - cl_lock_get_trust(lock); - spin_unlock(&head->coh_lock_guard); - lu_ref_add(&lock->cll_reference, "prune", current); - -again: - cl_lock_mutex_get(env, lock); - if (lock->cll_state < CLS_FREEING) { - LASSERT(lock->cll_users <= 1); - if (unlikely(lock->cll_users == 1)) { - struct l_wait_info lwi = { 0 }; - - cl_lock_mutex_put(env, lock); - l_wait_event(lock->cll_wq, - lock->cll_users == 0, - &lwi); - goto again; - } - - if (cancel) - cl_lock_cancel(env, lock); - cl_lock_delete(env, lock); - } - cl_lock_mutex_put(env, lock); - lu_ref_del(&lock->cll_reference, "prune", current); - cl_lock_put(env, lock); - spin_lock(&head->coh_lock_guard); - } - spin_unlock(&head->coh_lock_guard); -} -EXPORT_SYMBOL(cl_locks_prune); + struct cl_sync_io *anchor = NULL; + __u32 enq_flags = lock->cll_descr.cld_enq_flags; + int rc; -static struct cl_lock *cl_lock_hold_mutex(const struct lu_env *env, - const struct cl_io *io, - const struct cl_lock_descr *need, - const char *scope, const void *source) -{ - struct cl_lock *lock; + rc = cl_lock_init(env, lock, io); + if (rc < 0) + return rc; - while (1) { - lock = cl_lock_find(env, io, need); - if (IS_ERR(lock)) - break; - cl_lock_mutex_get(env, lock); - if (lock->cll_state < CLS_FREEING && - !(lock->cll_flags & CLF_CANCELLED)) { - cl_lock_hold_mod(env, lock, 1); - lu_ref_add(&lock->cll_holders, scope, source); - lu_ref_add(&lock->cll_reference, scope, source); - break; - } - cl_lock_mutex_put(env, lock); - cl_lock_put(env, lock); + if ((enq_flags & CEF_ASYNC) && !(enq_flags & CEF_AGL)) { + anchor = &cl_env_info(env)->clt_anchor; + cl_sync_io_init(anchor, 1, cl_sync_io_end); } - return lock; -} -/** - * Returns a lock matching \a need description with a reference and a hold on - * it. - * - * This is much like cl_lock_find(), except that cl_lock_hold() additionally - * guarantees that lock is not in the CLS_FREEING state on return. - */ -struct cl_lock *cl_lock_hold(const struct lu_env *env, const struct cl_io *io, - const struct cl_lock_descr *need, - const char *scope, const void *source) -{ - struct cl_lock *lock; + rc = cl_lock_enqueue(env, io, lock, anchor); - lock = cl_lock_hold_mutex(env, io, need, scope, source); - if (!IS_ERR(lock)) - cl_lock_mutex_put(env, lock); - return lock; -} -EXPORT_SYMBOL(cl_lock_hold); + if (anchor) { + int rc2; -/** - * Main high-level entry point of cl_lock interface that finds existing or - * enqueues new lock matching given description. - */ -struct cl_lock *cl_lock_request(const struct lu_env *env, struct cl_io *io, - const struct cl_lock_descr *need, - const char *scope, const void *source) -{ - struct cl_lock *lock; - int rc; - __u32 enqflags = need->cld_enq_flags; + /* drop the reference count held at initialization time */ + cl_sync_io_note(env, anchor, 0); + rc2 = cl_sync_io_wait(env, anchor, 0); + if (rc2 < 0 && rc == 0) + rc = rc2; + } - do { - lock = cl_lock_hold_mutex(env, io, need, scope, source); - if (IS_ERR(lock)) - break; + if (rc < 0) + cl_lock_release(env, lock); - rc = cl_enqueue_locked(env, lock, io, enqflags); - if (rc == 0) { - if (cl_lock_fits_into(env, lock, need, io)) { - if (!(enqflags & CEF_AGL)) { - cl_lock_mutex_put(env, lock); - cl_lock_lockdep_acquire(env, lock, - enqflags); - break; - } - rc = 1; - } - cl_unuse_locked(env, lock); - } - cl_lock_trace(D_DLMTRACE, env, - rc <= 0 ? "enqueue failed" : "agl succeed", lock); - cl_lock_hold_release(env, lock, scope, source); - cl_lock_mutex_put(env, lock); - lu_ref_del(&lock->cll_reference, scope, source); - cl_lock_put(env, lock); - if (rc > 0) { - LASSERT(enqflags & CEF_AGL); - lock = NULL; - } else if (rc != 0) { - lock = ERR_PTR(rc); - } - } while (rc == 0); - return lock; + return rc; } EXPORT_SYMBOL(cl_lock_request); -/** - * Adds a hold to a known lock. - */ -void cl_lock_hold_add(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERT(lock->cll_state != CLS_FREEING); - - cl_lock_get(lock); - cl_lock_hold_mod(env, lock, 1); - lu_ref_add(&lock->cll_holders, scope, source); - lu_ref_add(&lock->cll_reference, scope, source); -} -EXPORT_SYMBOL(cl_lock_hold_add); - -/** - * Releases a hold and a reference on a lock, on which caller acquired a - * mutex. - */ -void cl_lock_unhold(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source) -{ - LINVRNT(cl_lock_invariant(env, lock)); - cl_lock_hold_release(env, lock, scope, source); - lu_ref_del(&lock->cll_reference, scope, source); - cl_lock_put(env, lock); -} -EXPORT_SYMBOL(cl_lock_unhold); - /** * Releases a hold and a reference on a lock, obtained by cl_lock_hold(). */ -void cl_lock_release(const struct lu_env *env, struct cl_lock *lock, - const char *scope, const void *source) +void cl_lock_release(const struct lu_env *env, struct cl_lock *lock) { - LINVRNT(cl_lock_invariant(env, lock)); cl_lock_trace(D_DLMTRACE, env, "release lock", lock); - cl_lock_mutex_get(env, lock); - cl_lock_hold_release(env, lock, scope, source); - cl_lock_mutex_put(env, lock); - lu_ref_del(&lock->cll_reference, scope, source); - cl_lock_put(env, lock); + cl_lock_cancel(env, lock); + cl_lock_fini(env, lock); } EXPORT_SYMBOL(cl_lock_release); -void cl_lock_user_add(const struct lu_env *env, struct cl_lock *lock) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - - cl_lock_used_mod(env, lock, 1); -} -EXPORT_SYMBOL(cl_lock_user_add); - -void cl_lock_user_del(const struct lu_env *env, struct cl_lock *lock) -{ - LINVRNT(cl_lock_is_mutexed(lock)); - LINVRNT(cl_lock_invariant(env, lock)); - LASSERT(lock->cll_users > 0); - - cl_lock_used_mod(env, lock, -1); - if (lock->cll_users == 0) - wake_up_all(&lock->cll_wq); -} -EXPORT_SYMBOL(cl_lock_user_del); - const char *cl_lock_mode_name(const enum cl_lock_mode mode) { static const char *names[] = { - [CLM_PHANTOM] = "P", [CLM_READ] = "R", [CLM_WRITE] = "W", [CLM_GROUP] = "G" @@ -2061,10 +261,8 @@ void cl_lock_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_lock *lock) { const struct cl_lock_slice *slice; - (*printer)(env, cookie, "lock@%p[%d %d %d %d %d %08lx] ", - lock, atomic_read(&lock->cll_ref), - lock->cll_state, lock->cll_error, lock->cll_holds, - lock->cll_users, lock->cll_flags); + + (*printer)(env, cookie, "lock@%p", lock); cl_lock_descr_print(env, cookie, printer, &lock->cll_descr); (*printer)(env, cookie, " {\n"); @@ -2079,13 +277,3 @@ void cl_lock_print(const struct lu_env *env, void *cookie, (*printer)(env, cookie, "} lock@%p\n", lock); } EXPORT_SYMBOL(cl_lock_print); - -int cl_lock_init(void) -{ - return lu_kmem_init(cl_lock_caches); -} - -void cl_lock_fini(void) -{ - lu_kmem_fini(cl_lock_caches); -} diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 72e6333220ea..395b92c6480d 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -44,7 +44,6 @@ * * i_mutex * PG_locked - * ->coh_lock_guard * ->coh_attr_guard * ->ls_guard */ @@ -63,8 +62,6 @@ static struct kmem_cache *cl_env_kmem; -/** Lock class of cl_object_header::coh_lock_guard */ -static struct lock_class_key cl_lock_guard_class; /** Lock class of cl_object_header::coh_attr_guard */ static struct lock_class_key cl_attr_guard_class; @@ -79,11 +76,8 @@ int cl_object_header_init(struct cl_object_header *h) result = lu_object_header_init(&h->coh_lu); if (result == 0) { - spin_lock_init(&h->coh_lock_guard); spin_lock_init(&h->coh_attr_guard); - lockdep_set_class(&h->coh_lock_guard, &cl_lock_guard_class); lockdep_set_class(&h->coh_attr_guard, &cl_attr_guard_class); - INIT_LIST_HEAD(&h->coh_locks); h->coh_page_bufsize = 0; } return result; @@ -310,7 +304,7 @@ EXPORT_SYMBOL(cl_conf_set); /** * Prunes caches of pages and locks for this object. */ -void cl_object_prune(const struct lu_env *env, struct cl_object *obj) +int cl_object_prune(const struct lu_env *env, struct cl_object *obj) { struct lu_object_header *top; struct cl_object *o; @@ -326,10 +320,7 @@ void cl_object_prune(const struct lu_env *env, struct cl_object *obj) } } - /* TODO: pruning locks will be moved into layers after cl_lock - * simplification is done - */ - cl_locks_prune(env, obj, 1); + return result; } EXPORT_SYMBOL(cl_object_prune); @@ -342,19 +333,9 @@ EXPORT_SYMBOL(cl_object_prune); */ void cl_object_kill(const struct lu_env *env, struct cl_object *obj) { - struct cl_object_header *hdr; - - hdr = cl_object_header(obj); + struct cl_object_header *hdr = cl_object_header(obj); set_bit(LU_OBJECT_HEARD_BANSHEE, &hdr->coh_lu.loh_flags); - /* - * Destroy all locks. Object destruction (including cl_inode_fini()) - * cannot cancel the locks, because in the case of a local client, - * where client and server share the same thread running - * prune_icache(), this can dead-lock with ldlm_cancel_handler() - * waiting on __wait_on_freeing_inode(). - */ - cl_locks_prune(env, obj, 0); } EXPORT_SYMBOL(cl_object_kill); @@ -406,11 +387,8 @@ int cl_site_init(struct cl_site *s, struct cl_device *d) result = lu_site_init(&s->cs_lu, &d->cd_lu_dev); if (result == 0) { cache_stats_init(&s->cs_pages, "pages"); - cache_stats_init(&s->cs_locks, "locks"); for (i = 0; i < ARRAY_SIZE(s->cs_pages_state); ++i) atomic_set(&s->cs_pages_state[0], 0); - for (i = 0; i < ARRAY_SIZE(s->cs_locks_state); ++i) - atomic_set(&s->cs_locks_state[i], 0); cl_env_percpu_refill(); } return result; @@ -445,15 +423,6 @@ int cl_site_stats_print(const struct cl_site *site, struct seq_file *m) [CPS_PAGEIN] = "r", [CPS_FREEING] = "f" }; - static const char *lstate[] = { - [CLS_NEW] = "n", - [CLS_QUEUING] = "q", - [CLS_ENQUEUED] = "e", - [CLS_HELD] = "h", - [CLS_INTRANSIT] = "t", - [CLS_CACHED] = "c", - [CLS_FREEING] = "f" - }; /* lookup hit total busy create pages: ...... ...... ...... ...... ...... [...... ...... ...... ......] @@ -467,12 +436,6 @@ locks: ...... ...... ...... ...... ...... [...... ...... ...... ...... ......] seq_printf(m, "%s: %u ", pstate[i], atomic_read(&site->cs_pages_state[i])); seq_printf(m, "]\n"); - cache_stats_print(&site->cs_locks, m, 0); - seq_printf(m, " ["); - for (i = 0; i < ARRAY_SIZE(site->cs_locks_state); ++i) - seq_printf(m, "%s: %u ", lstate[i], - atomic_read(&site->cs_locks_state[i])); - seq_printf(m, "]\n"); cache_stats_print(&cl_env_stats, m, 0); seq_printf(m, "\n"); return 0; @@ -1147,12 +1110,6 @@ void cl_stack_fini(const struct lu_env *env, struct cl_device *cl) } EXPORT_SYMBOL(cl_stack_fini); -int cl_lock_init(void); -void cl_lock_fini(void); - -int cl_page_init(void); -void cl_page_fini(void); - static struct lu_context_key cl_key; struct cl_thread_info *cl_env_info(const struct lu_env *env) @@ -1247,22 +1204,13 @@ int cl_global_init(void) if (result) goto out_kmem; - result = cl_lock_init(); - if (result) - goto out_context; - - result = cl_page_init(); - if (result) - goto out_lock; - result = cl_env_percpu_init(); if (result) /* no cl_env_percpu_fini on error */ - goto out_lock; + goto out_context; return 0; -out_lock: - cl_lock_fini(); + out_context: lu_context_key_degister(&cl_key); out_kmem: @@ -1278,8 +1226,6 @@ int cl_global_init(void) void cl_global_fini(void) { cl_env_percpu_fini(); - cl_lock_fini(); - cl_page_fini(); lu_context_key_degister(&cl_key); lu_kmem_fini(cl_object_caches); cl_env_store_fini(); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index ad7f0aec605b..8df39ced1725 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -1075,12 +1075,3 @@ void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice, slice->cpl_page = page; } EXPORT_SYMBOL(cl_page_slice_add); - -int cl_page_init(void) -{ - return 0; -} - -void cl_page_fini(void) -{ -} diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 0d84d04c12de..a752bb4e946b 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -171,7 +171,7 @@ struct echo_thread_info { struct cl_2queue eti_queue; struct cl_io eti_io; - struct cl_lock_descr eti_descr; + struct cl_lock eti_lock; struct lu_fid eti_fid; struct lu_fid eti_fid2; }; @@ -327,26 +327,8 @@ static void echo_lock_fini(const struct lu_env *env, kmem_cache_free(echo_lock_kmem, ecl); } -static void echo_lock_delete(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct echo_lock *ecl = cl2echo_lock(slice); - - LASSERT(list_empty(&ecl->el_chain)); -} - -static int echo_lock_fits_into(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *need, - const struct cl_io *unused) -{ - return 1; -} - static struct cl_lock_operations echo_lock_ops = { .clo_fini = echo_lock_fini, - .clo_delete = echo_lock_delete, - .clo_fits_into = echo_lock_fits_into }; /** @} echo_lock */ @@ -811,16 +793,7 @@ static void echo_lock_release(const struct lu_env *env, { struct cl_lock *clk = echo_lock2cl(ecl); - cl_lock_get(clk); - cl_unuse(env, clk); - cl_lock_release(env, clk, "ec enqueue", ecl->el_object); - if (!still_used) { - cl_lock_mutex_get(env, clk); - cl_lock_cancel(env, clk); - cl_lock_delete(env, clk); - cl_lock_mutex_put(env, clk); - } - cl_lock_put(env, clk); + cl_lock_release(env, clk); } static struct lu_device *echo_device_free(const struct lu_env *env, @@ -1014,9 +987,11 @@ static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco, info = echo_env_info(env); io = &info->eti_io; - descr = &info->eti_descr; + lck = &info->eti_lock; obj = echo_obj2cl(eco); + memset(lck, 0, sizeof(*lck)); + descr = &lck->cll_descr; descr->cld_obj = obj; descr->cld_start = cl_index(obj, start); descr->cld_end = cl_index(obj, end); @@ -1024,25 +999,20 @@ static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco, descr->cld_enq_flags = enqflags; io->ci_obj = obj; - lck = cl_lock_request(env, io, descr, "ec enqueue", eco); - if (lck) { + rc = cl_lock_request(env, io, lck); + if (rc == 0) { struct echo_client_obd *ec = eco->eo_dev->ed_ec; struct echo_lock *el; - rc = cl_wait(env, lck); - if (rc == 0) { - el = cl2echo_lock(cl_lock_at(lck, &echo_device_type)); - spin_lock(&ec->ec_lock); - if (list_empty(&el->el_chain)) { - list_add(&el->el_chain, &ec->ec_locks); - el->el_cookie = ++ec->ec_unique; - } - atomic_inc(&el->el_refcount); - *cookie = el->el_cookie; - spin_unlock(&ec->ec_lock); - } else { - cl_lock_release(env, lck, "ec enqueue", current); + el = cl2echo_lock(cl_lock_at(lck, &echo_device_type)); + spin_lock(&ec->ec_lock); + if (list_empty(&el->el_chain)) { + list_add(&el->el_chain, &ec->ec_locks); + el->el_cookie = ++ec->ec_unique; } + atomic_inc(&el->el_refcount); + *cookie = el->el_cookie; + spin_unlock(&ec->ec_lock); } return rc; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index c5106592b3e4..d01f2a207a91 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -76,6 +76,8 @@ static inline char *ext_flags(struct osc_extent *ext, char *flags) *buf++ = ext->oe_rw ? 'r' : 'w'; if (ext->oe_intree) *buf++ = 'i'; + if (ext->oe_sync) + *buf++ = 'S'; if (ext->oe_srvlock) *buf++ = 's'; if (ext->oe_hp) @@ -121,9 +123,13 @@ static const char *oes_strings[] = { __ext->oe_grants, __ext->oe_nr_pages, \ list_empty_marker(&__ext->oe_pages), \ waitqueue_active(&__ext->oe_waitq) ? '+' : '-', \ - __ext->oe_osclock, __ext->oe_mppr, __ext->oe_owner, \ + __ext->oe_dlmlock, __ext->oe_mppr, __ext->oe_owner, \ /* ----- part 4 ----- */ \ ## __VA_ARGS__); \ + if (lvl == D_ERROR && __ext->oe_dlmlock) \ + LDLM_ERROR(__ext->oe_dlmlock, "extent: %p\n", __ext); \ + else \ + LDLM_DEBUG(__ext->oe_dlmlock, "extent: %p\n", __ext); \ } while (0) #undef EASSERTF @@ -240,20 +246,25 @@ static int osc_extent_sanity_check0(struct osc_extent *ext, goto out; } - if (!ext->oe_osclock && ext->oe_grants > 0) { + if (ext->oe_sync && ext->oe_grants > 0) { rc = 90; goto out; } - if (ext->oe_osclock) { - struct cl_lock_descr *descr; + if (ext->oe_dlmlock) { + struct ldlm_extent *extent; - descr = &ext->oe_osclock->cll_descr; - if (!(descr->cld_start <= ext->oe_start && - descr->cld_end >= ext->oe_max_end)) { + extent = &ext->oe_dlmlock->l_policy_data.l_extent; + if (!(extent->start <= cl_offset(osc2cl(obj), ext->oe_start) && + extent->end >= cl_offset(osc2cl(obj), ext->oe_max_end))) { rc = 100; goto out; } + + if (!(ext->oe_dlmlock->l_granted_mode & (LCK_PW | LCK_GROUP))) { + rc = 102; + goto out; + } } if (ext->oe_nr_pages > ext->oe_mppr) { @@ -359,7 +370,7 @@ static struct osc_extent *osc_extent_alloc(struct osc_object *obj) ext->oe_state = OES_INV; INIT_LIST_HEAD(&ext->oe_pages); init_waitqueue_head(&ext->oe_waitq); - ext->oe_osclock = NULL; + ext->oe_dlmlock = NULL; return ext; } @@ -385,9 +396,11 @@ static void osc_extent_put(const struct lu_env *env, struct osc_extent *ext) LASSERT(ext->oe_state == OES_INV); LASSERT(!ext->oe_intree); - if (ext->oe_osclock) { - cl_lock_put(env, ext->oe_osclock); - ext->oe_osclock = NULL; + if (ext->oe_dlmlock) { + lu_ref_add(&ext->oe_dlmlock->l_reference, + "osc_extent", ext); + LDLM_LOCK_PUT(ext->oe_dlmlock); + ext->oe_dlmlock = NULL; } osc_extent_free(ext); } @@ -543,7 +556,7 @@ static int osc_extent_merge(const struct lu_env *env, struct osc_extent *cur, if (cur->oe_max_end != victim->oe_max_end) return -ERANGE; - LASSERT(cur->oe_osclock == victim->oe_osclock); + LASSERT(cur->oe_dlmlock == victim->oe_dlmlock); ppc_bits = osc_cli(obj)->cl_chunkbits - PAGE_CACHE_SHIFT; chunk_start = cur->oe_start >> ppc_bits; chunk_end = cur->oe_end >> ppc_bits; @@ -624,10 +637,10 @@ static inline int overlapped(struct osc_extent *ex1, struct osc_extent *ex2) static struct osc_extent *osc_extent_find(const struct lu_env *env, struct osc_object *obj, pgoff_t index, int *grants) - { struct client_obd *cli = osc_cli(obj); - struct cl_lock *lock; + struct osc_lock *olck; + struct cl_lock_descr *descr; struct osc_extent *cur; struct osc_extent *ext; struct osc_extent *conflict = NULL; @@ -644,8 +657,12 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env, if (!cur) return ERR_PTR(-ENOMEM); - lock = cl_lock_at_pgoff(env, osc2cl(obj), index, NULL, 1, 0); - LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE); + olck = osc_env_io(env)->oi_write_osclock; + LASSERTF(olck, "page %lu is not covered by lock\n", index); + LASSERT(olck->ols_state == OLS_GRANTED); + + descr = &olck->ols_cl.cls_lock->cll_descr; + LASSERT(descr->cld_mode >= CLM_WRITE); LASSERT(cli->cl_chunkbits >= PAGE_CACHE_SHIFT); ppc_bits = cli->cl_chunkbits - PAGE_CACHE_SHIFT; @@ -657,19 +674,23 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env, max_pages = cli->cl_max_pages_per_rpc; LASSERT((max_pages & ~chunk_mask) == 0); max_end = index - (index % max_pages) + max_pages - 1; - max_end = min_t(pgoff_t, max_end, lock->cll_descr.cld_end); + max_end = min_t(pgoff_t, max_end, descr->cld_end); /* initialize new extent by parameters so far */ cur->oe_max_end = max_end; cur->oe_start = index & chunk_mask; cur->oe_end = ((index + ~chunk_mask + 1) & chunk_mask) - 1; - if (cur->oe_start < lock->cll_descr.cld_start) - cur->oe_start = lock->cll_descr.cld_start; + if (cur->oe_start < descr->cld_start) + cur->oe_start = descr->cld_start; if (cur->oe_end > max_end) cur->oe_end = max_end; - cur->oe_osclock = lock; cur->oe_grants = 0; cur->oe_mppr = max_pages; + if (olck->ols_dlmlock) { + LASSERT(olck->ols_hold); + cur->oe_dlmlock = LDLM_LOCK_GET(olck->ols_dlmlock); + lu_ref_add(&olck->ols_dlmlock->l_reference, "osc_extent", cur); + } /* grants has been allocated by caller */ LASSERTF(*grants >= chunksize + cli->cl_extent_tax, @@ -691,7 +712,7 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env, break; /* if covering by different locks, no chance to match */ - if (lock != ext->oe_osclock) { + if (olck->ols_dlmlock != ext->oe_dlmlock) { EASSERTF(!overlapped(ext, cur), ext, EXTSTR"\n", EXTPARA(cur)); @@ -795,7 +816,7 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env, if (found) { LASSERT(!conflict); if (!IS_ERR(found)) { - LASSERT(found->oe_osclock == cur->oe_osclock); + LASSERT(found->oe_dlmlock == cur->oe_dlmlock); OSC_EXTENT_DUMP(D_CACHE, found, "found caching ext for %lu.\n", index); } @@ -810,7 +831,7 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env, found = osc_extent_hold(cur); osc_extent_insert(obj, cur); OSC_EXTENT_DUMP(D_CACHE, cur, "add into tree %lu/%lu.\n", - index, lock->cll_descr.cld_end); + index, descr->cld_end); } osc_object_unlock(obj); @@ -2630,6 +2651,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, } ext->oe_rw = !!(cmd & OBD_BRW_READ); + ext->oe_sync = 1; ext->oe_urgent = 1; ext->oe_start = start; ext->oe_end = ext->oe_max_end = end; @@ -3087,27 +3109,27 @@ static int check_and_discard_cb(const struct lu_env *env, struct cl_io *io, struct osc_page *ops, void *cbdata) { struct osc_thread_info *info = osc_env_info(env); - struct cl_lock *lock = cbdata; + struct osc_object *osc = cbdata; pgoff_t index; index = osc_index(ops); if (index >= info->oti_fn_index) { - struct cl_lock *tmp; + struct ldlm_lock *tmp; struct cl_page *page = ops->ops_cl.cpl_page; /* refresh non-overlapped index */ - tmp = cl_lock_at_pgoff(env, lock->cll_descr.cld_obj, index, - lock, 1, 0); + tmp = osc_dlmlock_at_pgoff(env, osc, index, 0, 0); if (tmp) { + __u64 end = tmp->l_policy_data.l_extent.end; /* Cache the first-non-overlapped index so as to skip - * all pages within [index, oti_fn_index). This - * is safe because if tmp lock is canceled, it will - * discard these pages. + * all pages within [index, oti_fn_index). This is safe + * because if tmp lock is canceled, it will discard + * these pages. */ - info->oti_fn_index = tmp->cll_descr.cld_end + 1; - if (tmp->cll_descr.cld_end == CL_PAGE_EOF) + info->oti_fn_index = cl_index(osc2cl(osc), end + 1); + if (end == OBD_OBJECT_EOF) info->oti_fn_index = CL_PAGE_EOF; - cl_lock_put(env, tmp); + LDLM_LOCK_PUT(tmp); } else if (cl_page_own(env, io, page) == 0) { /* discard the page */ cl_page_discard(env, io, page); @@ -3125,11 +3147,8 @@ static int discard_cb(const struct lu_env *env, struct cl_io *io, struct osc_page *ops, void *cbdata) { struct osc_thread_info *info = osc_env_info(env); - struct cl_lock *lock = cbdata; struct cl_page *page = ops->ops_cl.cpl_page; - LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE); - /* page is top page. */ info->oti_next_index = osc_index(ops) + 1; if (cl_page_own(env, io, page) == 0) { @@ -3154,30 +3173,27 @@ static int discard_cb(const struct lu_env *env, struct cl_io *io, * If error happens on any step, the process continues anyway (the reasoning * behind this being that lock cancellation cannot be delayed indefinitely). */ -int osc_lock_discard_pages(const struct lu_env *env, struct osc_lock *ols) +int osc_lock_discard_pages(const struct lu_env *env, struct osc_object *osc, + pgoff_t start, pgoff_t end, enum cl_lock_mode mode) { struct osc_thread_info *info = osc_env_info(env); struct cl_io *io = &info->oti_io; - struct cl_object *osc = ols->ols_cl.cls_obj; - struct cl_lock *lock = ols->ols_cl.cls_lock; - struct cl_lock_descr *descr = &lock->cll_descr; osc_page_gang_cbt cb; int res; int result; - io->ci_obj = cl_object_top(osc); + io->ci_obj = cl_object_top(osc2cl(osc)); io->ci_ignore_layout = 1; result = cl_io_init(env, io, CIT_MISC, io->ci_obj); if (result != 0) goto out; - cb = descr->cld_mode == CLM_READ ? check_and_discard_cb : discard_cb; - info->oti_fn_index = info->oti_next_index = descr->cld_start; + cb = mode == CLM_READ ? check_and_discard_cb : discard_cb; + info->oti_fn_index = info->oti_next_index = start; do { - res = osc_page_gang_lookup(env, io, cl2osc(osc), - info->oti_next_index, descr->cld_end, - cb, (void *)lock); - if (info->oti_next_index > descr->cld_end) + res = osc_page_gang_lookup(env, io, osc, + info->oti_next_index, end, cb, osc); + if (info->oti_next_index > end) break; if (res == CLP_GANG_RESCHED) diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index bb34b53aead6..c7a69e4cd944 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -68,6 +68,9 @@ struct osc_io { struct cl_io_slice oi_cl; /** true if this io is lockless. */ int oi_lockless; + /** how many LRU pages are reserved for this IO */ + int oi_lru_reserved; + /** active extents, we know how many bytes is going to be written, * so having an active extent will prevent it from being fragmented */ @@ -77,8 +80,8 @@ struct osc_io { */ struct osc_extent *oi_trunc; - int oi_lru_reserved; - + /** write osc_lock for this IO, used by osc_extent_find(). */ + struct osc_lock *oi_write_osclock; struct obd_info oi_info; struct obdo oi_oa; struct osc_async_cbargs { @@ -117,6 +120,7 @@ struct osc_thread_info { */ pgoff_t oti_next_index; pgoff_t oti_fn_index; /* first non-overlapped index */ + struct cl_sync_io oti_anchor; }; struct osc_object { @@ -173,6 +177,10 @@ struct osc_object { struct radix_tree_root oo_tree; spinlock_t oo_tree_lock; unsigned long oo_npages; + + /* Protect osc_lock this osc_object has */ + spinlock_t oo_ol_spin; + struct list_head oo_ol_list; }; static inline void osc_object_lock(struct osc_object *obj) @@ -212,8 +220,6 @@ enum osc_lock_state { OLS_ENQUEUED, OLS_UPCALL_RECEIVED, OLS_GRANTED, - OLS_RELEASED, - OLS_BLOCKED, OLS_CANCELLED }; @@ -222,10 +228,8 @@ enum osc_lock_state { * * Interaction with DLM. * - * CLIO enqueues all DLM locks through ptlrpcd (that is, in "async" mode). - * * Once receive upcall is invoked, osc_lock remembers a handle of DLM lock in - * osc_lock::ols_handle and a pointer to that lock in osc_lock::ols_lock. + * osc_lock::ols_handle and a pointer to that lock in osc_lock::ols_dlmlock. * * This pointer is protected through a reference, acquired by * osc_lock_upcall0(). Also, an additional reference is acquired by @@ -263,16 +267,27 @@ enum osc_lock_state { */ struct osc_lock { struct cl_lock_slice ols_cl; + /** Internal lock to protect states, etc. */ + spinlock_t ols_lock; + /** Owner sleeps on this channel for state change */ + struct cl_sync_io *ols_owner; + /** waiting list for this lock to be cancelled */ + struct list_head ols_waiting_list; + /** wait entry of ols_waiting_list */ + struct list_head ols_wait_entry; + /** list entry for osc_object::oo_ol_list */ + struct list_head ols_nextlock_oscobj; + /** underlying DLM lock */ - struct ldlm_lock *ols_lock; - /** lock value block */ - struct ost_lvb ols_lvb; + struct ldlm_lock *ols_dlmlock; /** DLM flags with which osc_lock::ols_lock was enqueued */ __u64 ols_flags; /** osc_lock::ols_lock handle */ struct lustre_handle ols_handle; struct ldlm_enqueue_info ols_einfo; enum osc_lock_state ols_state; + /** lock value block */ + struct ost_lvb ols_lvb; /** * true, if ldlm_lock_addref() was called against @@ -302,16 +317,6 @@ struct osc_lock { * If true, osc_lock_enqueue is able to tolerate the -EUSERS error. */ ols_locklessable:1, - /** - * set by osc_lock_use() to wait until blocking AST enters into - * osc_ldlm_blocking_ast0(), so that cl_lock mutex can be used for - * further synchronization. - */ - ols_ast_wait:1, - /** - * If the data of this lock has been flushed to server side. - */ - ols_flush:1, /** * if set, the osc_lock is a glimpse lock. For glimpse locks, we treat * the EVAVAIL error as tolerable, this will make upper logic happy @@ -325,15 +330,6 @@ struct osc_lock { * For async glimpse lock. */ ols_agl:1; - /** - * IO that owns this lock. This field is used for a dead-lock - * avoidance by osc_lock_enqueue_wait(). - * - * XXX: unfortunately, the owner of a osc_lock is not unique, - * the lock may have multiple users, if the lock is granted and - * then matched. - */ - struct osc_io *ols_owner; }; /** @@ -627,6 +623,8 @@ struct osc_extent { unsigned int oe_intree:1, /** 0 is write, 1 is read */ oe_rw:1, + /** sync extent, queued by osc_queue_sync_pages() */ + oe_sync:1, oe_srvlock:1, oe_memalloc:1, /** an ACTIVE extent is going to be truncated, so when this extent @@ -675,7 +673,7 @@ struct osc_extent { */ wait_queue_head_t oe_waitq; /** lock covering this extent */ - struct cl_lock *oe_osclock; + struct ldlm_lock *oe_dlmlock; /** terminator of this extent. Must be true if this extent is in IO. */ struct task_struct *oe_owner; /** return value of writeback. If somebody is waiting for this extent, @@ -690,14 +688,14 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, int sent, int rc); void osc_extent_release(const struct lu_env *env, struct osc_extent *ext); -int osc_lock_discard_pages(const struct lu_env *env, struct osc_lock *lock); +int osc_lock_discard_pages(const struct lu_env *env, struct osc_object *osc, + pgoff_t start, pgoff_t end, enum cl_lock_mode mode); typedef int (*osc_page_gang_cbt)(const struct lu_env *, struct cl_io *, struct osc_page *, void *); int osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io, struct osc_object *osc, pgoff_t start, pgoff_t end, osc_page_gang_cbt cb, void *cbdata); - /** @} osc */ #endif /* OSC_CL_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index b7fb01ad60a6..cf9f8b792f07 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -108,12 +108,14 @@ void osc_update_next_shrink(struct client_obd *cli); extern struct ptlrpc_request_set *PTLRPCD_SET; +typedef int (*osc_enqueue_upcall_f)(void *cookie, struct lustre_handle *lockh, + int rc); + int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, __u64 *flags, ldlm_policy_data_t *policy, struct ost_lvb *lvb, int kms_valid, - obd_enqueue_update_f upcall, + osc_enqueue_upcall_f upcall, void *cookie, struct ldlm_enqueue_info *einfo, - struct lustre_handle *lockh, struct ptlrpc_request_set *rqset, int async, int agl); int osc_cancel_base(struct lustre_handle *lockh, __u32 mode); @@ -140,7 +142,6 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, int target, bool force); int osc_lru_reclaim(struct client_obd *cli); -extern spinlock_t osc_ast_guard; unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock); int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg); @@ -199,5 +200,8 @@ int osc_quotactl(struct obd_device *unused, struct obd_export *exp, int osc_quotacheck(struct obd_device *unused, struct obd_export *exp, struct obd_quotactl *oqctl); int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk); +struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, + struct osc_object *obj, pgoff_t index, + int pending, int canceling); #endif /* OSC_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 1ae8a227ad3d..cf7743d2f148 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -354,6 +354,7 @@ static void osc_io_rw_iter_fini(const struct lu_env *env, atomic_add(oio->oi_lru_reserved, cli->cl_lru_left); oio->oi_lru_reserved = 0; } + oio->oi_write_osclock = NULL; } static int osc_io_fault_start(const struct lu_env *env, @@ -751,8 +752,7 @@ static void osc_req_attr_set(const struct lu_env *env, struct lov_oinfo *oinfo; struct cl_req *clerq; struct cl_page *apage; /* _some_ page in @clerq */ - struct cl_lock *lock; /* _some_ lock protecting @apage */ - struct osc_lock *olck; + struct ldlm_lock *lock; /* _some_ lock protecting @apage */ struct osc_page *opg; struct obdo *oa; struct ost_lvb *lvb; @@ -782,38 +782,37 @@ static void osc_req_attr_set(const struct lu_env *env, oa->o_valid |= OBD_MD_FLID; } if (flags & OBD_MD_FLHANDLE) { - struct cl_object *subobj; clerq = slice->crs_req; LASSERT(!list_empty(&clerq->crq_pages)); apage = container_of(clerq->crq_pages.next, struct cl_page, cp_flight); opg = osc_cl_page_osc(apage, NULL); - subobj = opg->ops_cl.cpl_obj; - lock = cl_lock_at_pgoff(env, subobj, osc_index(opg), - NULL, 1, 1); - if (!lock) { - struct cl_object_header *head; - struct cl_lock *scan; - - head = cl_object_header(subobj); - list_for_each_entry(scan, &head->coh_locks, cll_linkage) - CL_LOCK_DEBUG(D_ERROR, env, scan, - "no cover page!\n"); - CL_PAGE_DEBUG(D_ERROR, env, apage, - "dump uncover page!\n"); + lock = osc_dlmlock_at_pgoff(env, cl2osc(obj), osc_index(opg), + 1, 1); + if (!lock && !opg->ops_srvlock) { + struct ldlm_resource *res; + struct ldlm_res_id *resname; + + CL_PAGE_DEBUG(D_ERROR, env, apage, "uncovered page!\n"); + + resname = &osc_env_info(env)->oti_resname; + ostid_build_res_name(&oinfo->loi_oi, resname); + res = ldlm_resource_get( + osc_export(cl2osc(obj))->exp_obd->obd_namespace, + NULL, resname, LDLM_EXTENT, 0); + ldlm_resource_dump(D_ERROR, res); + dump_stack(); LBUG(); } - olck = osc_lock_at(lock); - LASSERT(ergo(opg->ops_srvlock, !olck->ols_lock)); /* check for lockless io. */ - if (olck->ols_lock) { - oa->o_handle = olck->ols_lock->l_remote_handle; + if (lock) { + oa->o_handle = lock->l_remote_handle; oa->o_valid |= OBD_MD_FLHANDLE; + LDLM_LOCK_PUT(lock); } - cl_lock_put(env, lock); } } diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 978b6ea67107..68c5013fdc3e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -61,7 +61,6 @@ static const struct cl_lock_operations osc_lock_ops; static const struct cl_lock_operations osc_lock_lockless_ops; static void osc_lock_to_lockless(const struct lu_env *env, struct osc_lock *ols, int force); -static int osc_lock_has_pages(struct osc_lock *olck); int osc_lock_is_lockless(const struct osc_lock *olck) { @@ -89,11 +88,11 @@ static struct ldlm_lock *osc_handle_ptr(struct lustre_handle *handle) static int osc_lock_invariant(struct osc_lock *ols) { struct ldlm_lock *lock = osc_handle_ptr(&ols->ols_handle); - struct ldlm_lock *olock = ols->ols_lock; + struct ldlm_lock *olock = ols->ols_dlmlock; int handle_used = lustre_handle_is_used(&ols->ols_handle); if (ergo(osc_lock_is_lockless(ols), - ols->ols_locklessable && !ols->ols_lock)) + ols->ols_locklessable && !ols->ols_dlmlock)) return 1; /* @@ -110,7 +109,7 @@ static int osc_lock_invariant(struct osc_lock *ols) ergo(!lock, !olock))) return 0; /* - * Check that ->ols_handle and ->ols_lock are consistent, but + * Check that ->ols_handle and ->ols_dlmlock are consistent, but * take into account that they are set at the different time. */ if (!ergo(ols->ols_state == OLS_CANCELLED, @@ -137,115 +136,13 @@ static int osc_lock_invariant(struct osc_lock *ols) * */ -/** - * Breaks a link between osc_lock and dlm_lock. - */ -static void osc_lock_detach(const struct lu_env *env, struct osc_lock *olck) -{ - struct ldlm_lock *dlmlock; - - spin_lock(&osc_ast_guard); - dlmlock = olck->ols_lock; - if (!dlmlock) { - spin_unlock(&osc_ast_guard); - return; - } - - olck->ols_lock = NULL; - /* wb(); --- for all who checks (ols->ols_lock != NULL) before - * call to osc_lock_detach() - */ - dlmlock->l_ast_data = NULL; - olck->ols_handle.cookie = 0ULL; - spin_unlock(&osc_ast_guard); - - lock_res_and_lock(dlmlock); - if (dlmlock->l_granted_mode == dlmlock->l_req_mode) { - struct cl_object *obj = olck->ols_cl.cls_obj; - struct cl_attr *attr = &osc_env_info(env)->oti_attr; - __u64 old_kms; - - cl_object_attr_lock(obj); - /* Must get the value under the lock to avoid possible races. */ - old_kms = cl2osc(obj)->oo_oinfo->loi_kms; - /* Update the kms. Need to loop all granted locks. - * Not a problem for the client - */ - attr->cat_kms = ldlm_extent_shift_kms(dlmlock, old_kms); - - cl_object_attr_set(env, obj, attr, CAT_KMS); - cl_object_attr_unlock(obj); - } - unlock_res_and_lock(dlmlock); - - /* release a reference taken in osc_lock_upcall0(). */ - LASSERT(olck->ols_has_ref); - lu_ref_del(&dlmlock->l_reference, "osc_lock", olck); - LDLM_LOCK_RELEASE(dlmlock); - olck->ols_has_ref = 0; -} - -static int osc_lock_unhold(struct osc_lock *ols) -{ - int result = 0; - - if (ols->ols_hold) { - ols->ols_hold = 0; - result = osc_cancel_base(&ols->ols_handle, - ols->ols_einfo.ei_mode); - } - return result; -} - -static int osc_lock_unuse(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct osc_lock *ols = cl2osc_lock(slice); - - LINVRNT(osc_lock_invariant(ols)); - - switch (ols->ols_state) { - case OLS_NEW: - LASSERT(!ols->ols_hold); - LASSERT(ols->ols_agl); - return 0; - case OLS_UPCALL_RECEIVED: - osc_lock_unhold(ols); - case OLS_ENQUEUED: - LASSERT(!ols->ols_hold); - osc_lock_detach(env, ols); - ols->ols_state = OLS_NEW; - return 0; - case OLS_GRANTED: - LASSERT(!ols->ols_glimpse); - LASSERT(ols->ols_hold); - /* - * Move lock into OLS_RELEASED state before calling - * osc_cancel_base() so that possible synchronous cancellation - * sees that lock is released. - */ - ols->ols_state = OLS_RELEASED; - return osc_lock_unhold(ols); - default: - CERROR("Impossible state: %d\n", ols->ols_state); - LBUG(); - } -} - static void osc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice) { struct osc_lock *ols = cl2osc_lock(slice); LINVRNT(osc_lock_invariant(ols)); - /* - * ->ols_hold can still be true at this point if, for example, a - * thread that requested a lock was killed (and released a reference - * to the lock), before reply from a server was received. In this case - * lock is destroyed immediately after upcall. - */ - osc_lock_unhold(ols); - LASSERT(!ols->ols_lock); + LASSERT(!ols->ols_dlmlock); kmem_cache_free(osc_lock_kmem, ols); } @@ -272,54 +169,11 @@ static __u64 osc_enq2ldlm_flags(__u32 enqflags) result |= LDLM_FL_HAS_INTENT; if (enqflags & CEF_DISCARD_DATA) result |= LDLM_FL_AST_DISCARD_DATA; + if (enqflags & CEF_PEEK) + result |= LDLM_FL_TEST_LOCK; return result; } -/** - * Global spin-lock protecting consistency of ldlm_lock::l_ast_data - * pointers. Initialized in osc_init(). - */ -spinlock_t osc_ast_guard; - -static struct osc_lock *osc_ast_data_get(struct ldlm_lock *dlm_lock) -{ - struct osc_lock *olck; - - lock_res_and_lock(dlm_lock); - spin_lock(&osc_ast_guard); - olck = dlm_lock->l_ast_data; - if (olck) { - struct cl_lock *lock = olck->ols_cl.cls_lock; - /* - * If osc_lock holds a reference on ldlm lock, return it even - * when cl_lock is in CLS_FREEING state. This way - * - * osc_ast_data_get(dlmlock) == NULL - * - * guarantees that all osc references on dlmlock were - * released. osc_dlm_blocking_ast0() relies on that. - */ - if (lock->cll_state < CLS_FREEING || olck->ols_has_ref) { - cl_lock_get_trust(lock); - lu_ref_add_atomic(&lock->cll_reference, - "ast", current); - } else - olck = NULL; - } - spin_unlock(&osc_ast_guard); - unlock_res_and_lock(dlm_lock); - return olck; -} - -static void osc_ast_data_put(const struct lu_env *env, struct osc_lock *olck) -{ - struct cl_lock *lock; - - lock = olck->ols_cl.cls_lock; - lu_ref_del(&lock->cll_reference, "ast", current); - cl_lock_put(env, lock); -} - /** * Updates object attributes from a lock value block (lvb) received together * with the DLM lock reply from the server. Copy of osc_update_enqueue() @@ -330,35 +184,30 @@ static void osc_ast_data_put(const struct lu_env *env, struct osc_lock *olck) * * Called under lock and resource spin-locks. */ -static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck, - int rc) +static void osc_lock_lvb_update(const struct lu_env *env, + struct osc_object *osc, + struct ldlm_lock *dlmlock, + struct ost_lvb *lvb) { - struct ost_lvb *lvb; - struct cl_object *obj; - struct lov_oinfo *oinfo; - struct cl_attr *attr; + struct cl_object *obj = osc2cl(osc); + struct lov_oinfo *oinfo = osc->oo_oinfo; + struct cl_attr *attr = &osc_env_info(env)->oti_attr; unsigned valid; - if (!(olck->ols_flags & LDLM_FL_LVB_READY)) - return; - - lvb = &olck->ols_lvb; - obj = olck->ols_cl.cls_obj; - oinfo = cl2osc(obj)->oo_oinfo; - attr = &osc_env_info(env)->oti_attr; valid = CAT_BLOCKS | CAT_ATIME | CAT_CTIME | CAT_MTIME | CAT_SIZE; + if (!lvb) + lvb = dlmlock->l_lvb_data; + cl_lvb2attr(attr, lvb); cl_object_attr_lock(obj); - if (rc == 0) { - struct ldlm_lock *dlmlock; + if (dlmlock) { __u64 size; - dlmlock = olck->ols_lock; - - /* re-grab LVB from a dlm lock under DLM spin-locks. */ - *lvb = *(struct ost_lvb *)dlmlock->l_lvb_data; + check_res_locked(dlmlock->l_resource); + LASSERT(lvb == dlmlock->l_lvb_data); size = lvb->lvb_size; + /* Extend KMS up to the end of this lock and no further * A lock on [x,y] means a KMS of up to y + 1 bytes! */ @@ -375,102 +224,67 @@ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck, dlmlock->l_policy_data.l_extent.end); } ldlm_lock_allow_match_locked(dlmlock); - } else if (rc == -ENAVAIL && olck->ols_glimpse) { - CDEBUG(D_INODE, "glimpsed, setting rss=%llu; leaving kms=%llu\n", - lvb->lvb_size, oinfo->loi_kms); - } else - valid = 0; - - if (valid != 0) - cl_object_attr_set(env, obj, attr, valid); + } + cl_object_attr_set(env, obj, attr, valid); cl_object_attr_unlock(obj); } -/** - * Called when a lock is granted, from an upcall (when server returned a - * granted lock), or from completion AST, when server returned a blocked lock. - * - * Called under lock and resource spin-locks, that are released temporarily - * here. - */ -static void osc_lock_granted(const struct lu_env *env, struct osc_lock *olck, - struct ldlm_lock *dlmlock, int rc) +static void osc_lock_granted(const struct lu_env *env, struct osc_lock *oscl, + struct lustre_handle *lockh, bool lvb_update) { - struct ldlm_extent *ext; - struct cl_lock *lock; - struct cl_lock_descr *descr; + struct ldlm_lock *dlmlock; - LASSERT(dlmlock->l_granted_mode == dlmlock->l_req_mode); + dlmlock = ldlm_handle2lock_long(lockh, 0); + LASSERT(dlmlock); + + /* lock reference taken by ldlm_handle2lock_long() is + * owned by osc_lock and released in osc_lock_detach() + */ + lu_ref_add(&dlmlock->l_reference, "osc_lock", oscl); + oscl->ols_has_ref = 1; - if (olck->ols_state < OLS_GRANTED) { - lock = olck->ols_cl.cls_lock; - ext = &dlmlock->l_policy_data.l_extent; - descr = &osc_env_info(env)->oti_descr; - descr->cld_obj = lock->cll_descr.cld_obj; + LASSERT(!oscl->ols_dlmlock); + oscl->ols_dlmlock = dlmlock; - /* XXX check that ->l_granted_mode is valid. */ - descr->cld_mode = osc_ldlm2cl_lock(dlmlock->l_granted_mode); - descr->cld_start = cl_index(descr->cld_obj, ext->start); - descr->cld_end = cl_index(descr->cld_obj, ext->end); - descr->cld_gid = ext->gid; - /* - * tell upper layers the extent of the lock that was actually - * granted - */ - olck->ols_state = OLS_GRANTED; - osc_lock_lvb_update(env, olck, rc); - - /* release DLM spin-locks to allow cl_lock_{modify,signal}() - * to take a semaphore on a parent lock. This is safe, because - * spin-locks are needed to protect consistency of - * dlmlock->l_*_mode and LVB, and we have finished processing - * them. + /* This may be a matched lock for glimpse request, do not hold + * lock reference in that case. + */ + if (!oscl->ols_glimpse) { + /* hold a refc for non glimpse lock which will + * be released in osc_lock_cancel() */ - unlock_res_and_lock(dlmlock); - cl_lock_modify(env, lock, descr); - cl_lock_signal(env, lock); - LINVRNT(osc_lock_invariant(olck)); - lock_res_and_lock(dlmlock); + lustre_handle_copy(&oscl->ols_handle, lockh); + ldlm_lock_addref(lockh, oscl->ols_einfo.ei_mode); + oscl->ols_hold = 1; } -} - -static void osc_lock_upcall0(const struct lu_env *env, struct osc_lock *olck) - -{ - struct ldlm_lock *dlmlock; - - dlmlock = ldlm_handle2lock_long(&olck->ols_handle, 0); - LASSERT(dlmlock); + /* Lock must have been granted. */ lock_res_and_lock(dlmlock); - spin_lock(&osc_ast_guard); - LASSERT(dlmlock->l_ast_data == olck); - LASSERT(!olck->ols_lock); - olck->ols_lock = dlmlock; - spin_unlock(&osc_ast_guard); + if (dlmlock->l_granted_mode == dlmlock->l_req_mode) { + struct ldlm_extent *ext = &dlmlock->l_policy_data.l_extent; + struct cl_lock_descr *descr = &oscl->ols_cl.cls_lock->cll_descr; - /* - * Lock might be not yet granted. In this case, completion ast - * (osc_ldlm_completion_ast()) comes later and finishes lock - * granting. - */ - if (dlmlock->l_granted_mode == dlmlock->l_req_mode) - osc_lock_granted(env, olck, dlmlock, 0); - unlock_res_and_lock(dlmlock); + /* extend the lock extent, otherwise it will have problem when + * we decide whether to grant a lockless lock. + */ + descr->cld_mode = osc_ldlm2cl_lock(dlmlock->l_granted_mode); + descr->cld_start = cl_index(descr->cld_obj, ext->start); + descr->cld_end = cl_index(descr->cld_obj, ext->end); + descr->cld_gid = ext->gid; - /* - * osc_enqueue_interpret() decrefs asynchronous locks, counter - * this. - */ - ldlm_lock_addref(&olck->ols_handle, olck->ols_einfo.ei_mode); - olck->ols_hold = 1; + /* no lvb update for matched lock */ + if (lvb_update) { + LASSERT(oscl->ols_flags & LDLM_FL_LVB_READY); + osc_lock_lvb_update(env, cl2osc(oscl->ols_cl.cls_obj), + dlmlock, NULL); + } + LINVRNT(osc_lock_invariant(oscl)); + } + unlock_res_and_lock(dlmlock); - /* lock reference taken by ldlm_handle2lock_long() is owned by - * osc_lock and released in osc_lock_detach() - */ - lu_ref_add(&dlmlock->l_reference, "osc_lock", olck); - olck->ols_has_ref = 1; + LASSERT(oscl->ols_state != OLS_GRANTED); + oscl->ols_state = OLS_GRANTED; } /** @@ -478,143 +292,124 @@ static void osc_lock_upcall0(const struct lu_env *env, struct osc_lock *olck) * received from a server, or after osc_enqueue_base() matched a local DLM * lock. */ -static int osc_lock_upcall(void *cookie, int errcode) +static int osc_lock_upcall(void *cookie, struct lustre_handle *lockh, + int errcode) { - struct osc_lock *olck = cookie; - struct cl_lock_slice *slice = &olck->ols_cl; - struct cl_lock *lock = slice->cls_lock; + struct osc_lock *oscl = cookie; + struct cl_lock_slice *slice = &oscl->ols_cl; struct lu_env *env; struct cl_env_nest nest; + int rc; env = cl_env_nested_get(&nest); - if (!IS_ERR(env)) { - int rc; - - cl_lock_mutex_get(env, lock); + /* should never happen, similar to osc_ldlm_blocking_ast(). */ + LASSERT(!IS_ERR(env)); + + rc = ldlm_error2errno(errcode); + if (oscl->ols_state == OLS_ENQUEUED) { + oscl->ols_state = OLS_UPCALL_RECEIVED; + } else if (oscl->ols_state == OLS_CANCELLED) { + rc = -EIO; + } else { + CERROR("Impossible state: %d\n", oscl->ols_state); + LBUG(); + } - LASSERT(lock->cll_state >= CLS_QUEUING); - if (olck->ols_state == OLS_ENQUEUED) { - olck->ols_state = OLS_UPCALL_RECEIVED; - rc = ldlm_error2errno(errcode); - } else if (olck->ols_state == OLS_CANCELLED) { - rc = -EIO; - } else { - CERROR("Impossible state: %d\n", olck->ols_state); - LBUG(); - } - if (rc) { - struct ldlm_lock *dlmlock; - - dlmlock = ldlm_handle2lock(&olck->ols_handle); - if (dlmlock) { - lock_res_and_lock(dlmlock); - spin_lock(&osc_ast_guard); - LASSERT(!olck->ols_lock); - dlmlock->l_ast_data = NULL; - olck->ols_handle.cookie = 0ULL; - spin_unlock(&osc_ast_guard); - ldlm_lock_fail_match_locked(dlmlock); - unlock_res_and_lock(dlmlock); - LDLM_LOCK_PUT(dlmlock); - } - } else { - if (olck->ols_glimpse) - olck->ols_glimpse = 0; - osc_lock_upcall0(env, olck); - } + if (rc == 0) + osc_lock_granted(env, oscl, lockh, errcode == ELDLM_OK); - /* Error handling, some errors are tolerable. */ - if (olck->ols_locklessable && rc == -EUSERS) { - /* This is a tolerable error, turn this lock into - * lockless lock. - */ - osc_object_set_contended(cl2osc(slice->cls_obj)); - LASSERT(slice->cls_ops == &osc_lock_ops); + /* Error handling, some errors are tolerable. */ + if (oscl->ols_locklessable && rc == -EUSERS) { + /* This is a tolerable error, turn this lock into + * lockless lock. + */ + osc_object_set_contended(cl2osc(slice->cls_obj)); + LASSERT(slice->cls_ops == &osc_lock_ops); + + /* Change this lock to ldlmlock-less lock. */ + osc_lock_to_lockless(env, oscl, 1); + oscl->ols_state = OLS_GRANTED; + rc = 0; + } else if (oscl->ols_glimpse && rc == -ENAVAIL) { + LASSERT(oscl->ols_flags & LDLM_FL_LVB_READY); + osc_lock_lvb_update(env, cl2osc(slice->cls_obj), + NULL, &oscl->ols_lvb); + /* Hide the error. */ + rc = 0; + } - /* Change this lock to ldlmlock-less lock. */ - osc_lock_to_lockless(env, olck, 1); - olck->ols_state = OLS_GRANTED; - rc = 0; - } else if (olck->ols_glimpse && rc == -ENAVAIL) { - osc_lock_lvb_update(env, olck, rc); - cl_lock_delete(env, lock); - /* Hide the error. */ - rc = 0; - } + if (oscl->ols_owner) + cl_sync_io_note(env, oscl->ols_owner, rc); + cl_env_nested_put(&nest, env); - if (rc == 0) { - /* For AGL case, the RPC sponsor may exits the cl_lock - * processing without wait() called before related OSC - * lock upcall(). So update the lock status according - * to the enqueue result inside AGL upcall(). - */ - if (olck->ols_agl) { - lock->cll_flags |= CLF_FROM_UPCALL; - cl_wait_try(env, lock); - lock->cll_flags &= ~CLF_FROM_UPCALL; - if (!olck->ols_glimpse) - olck->ols_agl = 0; - } - cl_lock_signal(env, lock); - /* del user for lock upcall cookie */ - cl_unuse_try(env, lock); - } else { - /* del user for lock upcall cookie */ - cl_lock_user_del(env, lock); - cl_lock_error(env, lock, rc); - } + return rc; +} - /* release cookie reference, acquired by osc_lock_enqueue() */ - cl_lock_hold_release(env, lock, "upcall", lock); - cl_lock_mutex_put(env, lock); +static int osc_lock_upcall_agl(void *cookie, struct lustre_handle *lockh, + int errcode) +{ + struct osc_object *osc = cookie; + struct ldlm_lock *dlmlock; + struct lu_env *env; + struct cl_env_nest nest; - lu_ref_del(&lock->cll_reference, "upcall", lock); - /* This maybe the last reference, so must be called after - * cl_lock_mutex_put(). - */ - cl_lock_put(env, lock); + env = cl_env_nested_get(&nest); + LASSERT(!IS_ERR(env)); - cl_env_nested_put(&nest, env); - } else { - /* should never happen, similar to osc_ldlm_blocking_ast(). */ - LBUG(); + if (errcode == ELDLM_LOCK_MATCHED) { + errcode = ELDLM_OK; + goto out; } - return errcode; + + if (errcode != ELDLM_OK) + goto out; + + dlmlock = ldlm_handle2lock(lockh); + LASSERT(dlmlock); + + lock_res_and_lock(dlmlock); + LASSERT(dlmlock->l_granted_mode == dlmlock->l_req_mode); + + /* there is no osc_lock associated with AGL lock */ + osc_lock_lvb_update(env, osc, dlmlock, NULL); + + unlock_res_and_lock(dlmlock); + LDLM_LOCK_PUT(dlmlock); + +out: + cl_object_put(env, osc2cl(osc)); + cl_env_nested_put(&nest, env); + return ldlm_error2errno(errcode); } -/** - * Core of osc_dlm_blocking_ast() logic. - */ -static void osc_lock_blocking(const struct lu_env *env, - struct ldlm_lock *dlmlock, - struct osc_lock *olck, int blocking) +static int osc_lock_flush(struct osc_object *obj, pgoff_t start, pgoff_t end, + enum cl_lock_mode mode, int discard) { - struct cl_lock *lock = olck->ols_cl.cls_lock; + struct lu_env *env; + struct cl_env_nest nest; + int rc = 0; + int rc2 = 0; - LASSERT(olck->ols_lock == dlmlock); - CLASSERT(OLS_BLOCKED < OLS_CANCELLED); - LASSERT(!osc_lock_is_lockless(olck)); + env = cl_env_nested_get(&nest); + if (IS_ERR(env)) + return PTR_ERR(env); + + if (mode == CLM_WRITE) { + rc = osc_cache_writeback_range(env, obj, start, end, 1, + discard); + CDEBUG(D_CACHE, "object %p: [%lu -> %lu] %d pages were %s.\n", + obj, start, end, rc, + discard ? "discarded" : "written back"); + if (rc > 0) + rc = 0; + } - /* - * Lock might be still addref-ed here, if e.g., blocking ast - * is sent for a failed lock. - */ - osc_lock_unhold(olck); + rc2 = osc_lock_discard_pages(env, obj, start, end, mode); + if (rc == 0 && rc2 < 0) + rc = rc2; - if (blocking && olck->ols_state < OLS_BLOCKED) - /* - * Move osc_lock into OLS_BLOCKED before canceling the lock, - * because it recursively re-enters osc_lock_blocking(), with - * the state set to OLS_CANCELLED. - */ - olck->ols_state = OLS_BLOCKED; - /* - * cancel and destroy lock at least once no matter how blocking ast is - * entered (see comment above osc_ldlm_blocking_ast() for use - * cases). cl_lock_cancel() and cl_lock_delete() are idempotent. - */ - cl_lock_cancel(env, lock); - cl_lock_delete(env, lock); + cl_env_nested_put(&nest, env); + return rc; } /** @@ -625,65 +420,63 @@ static int osc_dlm_blocking_ast0(const struct lu_env *env, struct ldlm_lock *dlmlock, void *data, int flag) { - struct osc_lock *olck; - struct cl_lock *lock; - int result; - int cancel; - - LASSERT(flag == LDLM_CB_BLOCKING || flag == LDLM_CB_CANCELING); - - cancel = 0; - olck = osc_ast_data_get(dlmlock); - if (olck) { - lock = olck->ols_cl.cls_lock; - cl_lock_mutex_get(env, lock); - LINVRNT(osc_lock_invariant(olck)); - if (olck->ols_ast_wait) { - /* wake up osc_lock_use() */ - cl_lock_signal(env, lock); - olck->ols_ast_wait = 0; - } - /* - * Lock might have been canceled while this thread was - * sleeping for lock mutex, but olck is pinned in memory. - */ - if (olck == dlmlock->l_ast_data) { - /* - * NOTE: DLM sends blocking AST's for failed locks - * (that are still in pre-OLS_GRANTED state) - * too, and they have to be canceled otherwise - * DLM lock is never destroyed and stuck in - * the memory. - * - * Alternatively, ldlm_cli_cancel() can be - * called here directly for osc_locks with - * ols_state < OLS_GRANTED to maintain an - * invariant that ->clo_cancel() is only called - * for locks that were granted. - */ - LASSERT(data == olck); - osc_lock_blocking(env, dlmlock, - olck, flag == LDLM_CB_BLOCKING); - } else - cancel = 1; - cl_lock_mutex_put(env, lock); - osc_ast_data_put(env, olck); - } else - /* - * DLM lock exists, but there is no cl_lock attached to it. - * This is a `normal' race. cl_object and its cl_lock's can be - * removed by memory pressure, together with all pages. + struct cl_object *obj = NULL; + int result = 0; + int discard; + enum cl_lock_mode mode = CLM_READ; + + LASSERT(flag == LDLM_CB_CANCELING); + + lock_res_and_lock(dlmlock); + if (dlmlock->l_granted_mode != dlmlock->l_req_mode) { + dlmlock->l_ast_data = NULL; + unlock_res_and_lock(dlmlock); + return 0; + } + + discard = ldlm_is_discard_data(dlmlock); + if (dlmlock->l_granted_mode & (LCK_PW | LCK_GROUP)) + mode = CLM_WRITE; + + if (dlmlock->l_ast_data) { + obj = osc2cl(dlmlock->l_ast_data); + dlmlock->l_ast_data = NULL; + + cl_object_get(obj); + } + + unlock_res_and_lock(dlmlock); + + /* if l_ast_data is NULL, the dlmlock was enqueued by AGL or + * the object has been destroyed. + */ + if (obj) { + struct ldlm_extent *extent = &dlmlock->l_policy_data.l_extent; + struct cl_attr *attr = &osc_env_info(env)->oti_attr; + __u64 old_kms; + + /* Destroy pages covered by the extent of the DLM lock */ + result = osc_lock_flush(cl2osc(obj), + cl_index(obj, extent->start), + cl_index(obj, extent->end), + mode, discard); + + /* losing a lock, update kms */ + lock_res_and_lock(dlmlock); + cl_object_attr_lock(obj); + /* Must get the value under the lock to avoid race. */ + old_kms = cl2osc(obj)->oo_oinfo->loi_kms; + /* Update the kms. Need to loop all granted locks. + * Not a problem for the client */ - cancel = (flag == LDLM_CB_BLOCKING); + attr->cat_kms = ldlm_extent_shift_kms(dlmlock, old_kms); - if (cancel) { - struct lustre_handle *lockh; + cl_object_attr_set(env, obj, attr, CAT_KMS); + cl_object_attr_unlock(obj); + unlock_res_and_lock(dlmlock); - lockh = &osc_env_info(env)->oti_handle; - ldlm_lock2handle(dlmlock, lockh); - result = ldlm_cli_cancel(lockh, LCF_ASYNC); - } else - result = 0; + cl_object_put(env, obj); + } return result; } @@ -733,107 +526,52 @@ static int osc_ldlm_blocking_ast(struct ldlm_lock *dlmlock, struct ldlm_lock_desc *new, void *data, int flag) { - struct lu_env *env; - struct cl_env_nest nest; - int result; + int result = 0; - /* - * This can be called in the context of outer IO, e.g., - * - * cl_enqueue()->... - * ->osc_enqueue_base()->... - * ->ldlm_prep_elc_req()->... - * ->ldlm_cancel_callback()->... - * ->osc_ldlm_blocking_ast() - * - * new environment has to be created to not corrupt outer context. - */ - env = cl_env_nested_get(&nest); - if (!IS_ERR(env)) { - result = osc_dlm_blocking_ast0(env, dlmlock, data, flag); - cl_env_nested_put(&nest, env); - } else { - result = PTR_ERR(env); - /* - * XXX This should never happen, as cl_lock is - * stuck. Pre-allocated environment a la vvp_inode_fini_env - * should be used. - */ - LBUG(); - } - if (result != 0) { + switch (flag) { + case LDLM_CB_BLOCKING: { + struct lustre_handle lockh; + + ldlm_lock2handle(dlmlock, &lockh); + result = ldlm_cli_cancel(&lockh, LCF_ASYNC); if (result == -ENODATA) result = 0; - else - CERROR("BAST failed: %d\n", result); + break; } - return result; -} - -static int osc_ldlm_completion_ast(struct ldlm_lock *dlmlock, - __u64 flags, void *data) -{ - struct cl_env_nest nest; - struct lu_env *env; - struct osc_lock *olck; - struct cl_lock *lock; - int result; - int dlmrc; + case LDLM_CB_CANCELING: { + struct lu_env *env; + struct cl_env_nest nest; - /* first, do dlm part of the work */ - dlmrc = ldlm_completion_ast_async(dlmlock, flags, data); - /* then, notify cl_lock */ - env = cl_env_nested_get(&nest); - if (!IS_ERR(env)) { - olck = osc_ast_data_get(dlmlock); - if (olck) { - lock = olck->ols_cl.cls_lock; - cl_lock_mutex_get(env, lock); - /* - * ldlm_handle_cp_callback() copied LVB from request - * to lock->l_lvb_data, store it in osc_lock. - */ - LASSERT(dlmlock->l_lvb_data); - lock_res_and_lock(dlmlock); - olck->ols_lvb = *(struct ost_lvb *)dlmlock->l_lvb_data; - if (!olck->ols_lock) { - /* - * upcall (osc_lock_upcall()) hasn't yet been - * called. Do nothing now, upcall will bind - * olck to dlmlock and signal the waiters. - * - * This maintains an invariant that osc_lock - * and ldlm_lock are always bound when - * osc_lock is in OLS_GRANTED state. - */ - } else if (dlmlock->l_granted_mode == - dlmlock->l_req_mode) { - osc_lock_granted(env, olck, dlmlock, dlmrc); - } - unlock_res_and_lock(dlmlock); + /* + * This can be called in the context of outer IO, e.g., + * + * osc_enqueue_base()->... + * ->ldlm_prep_elc_req()->... + * ->ldlm_cancel_callback()->... + * ->osc_ldlm_blocking_ast() + * + * new environment has to be created to not corrupt outer + * context. + */ + env = cl_env_nested_get(&nest); + if (IS_ERR(env)) { + result = PTR_ERR(env); + break; + } - if (dlmrc != 0) { - CL_LOCK_DEBUG(D_ERROR, env, lock, - "dlmlock returned %d\n", dlmrc); - cl_lock_error(env, lock, dlmrc); - } - cl_lock_mutex_put(env, lock); - osc_ast_data_put(env, olck); - result = 0; - } else - result = -ELDLM_NO_LOCK_DATA; + result = osc_dlm_blocking_ast0(env, dlmlock, data, flag); cl_env_nested_put(&nest, env); - } else - result = PTR_ERR(env); - return dlmrc ?: result; + break; + } + default: + LBUG(); + } + return result; } static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) { struct ptlrpc_request *req = data; - struct osc_lock *olck; - struct cl_lock *lock; - struct cl_object *obj; struct cl_env_nest nest; struct lu_env *env; struct ost_lvb *lvb; @@ -844,14 +582,16 @@ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) env = cl_env_nested_get(&nest); if (!IS_ERR(env)) { - /* osc_ast_data_get() has to go after environment is - * allocated, because osc_ast_data() acquires a - * reference to a lock, and it can only be released in - * environment. - */ - olck = osc_ast_data_get(dlmlock); - if (olck) { - lock = olck->ols_cl.cls_lock; + struct cl_object *obj = NULL; + + lock_res_and_lock(dlmlock); + if (dlmlock->l_ast_data) { + obj = osc2cl(dlmlock->l_ast_data); + cl_object_get(obj); + } + unlock_res_and_lock(dlmlock); + + if (obj) { /* Do not grab the mutex of cl_lock for glimpse. * See LU-1274 for details. * BTW, it's okay for cl_lock to be cancelled during @@ -866,7 +606,6 @@ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) result = req_capsule_server_pack(cap); if (result == 0) { lvb = req_capsule_server_get(cap, &RMF_DLM_LVB); - obj = lock->cll_descr.cld_obj; result = cl_object_glimpse(env, obj, lvb); } if (!exp_connect_lvb_type(req->rq_export)) @@ -874,7 +613,7 @@ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) &RMF_DLM_LVB, sizeof(struct ost_lvb_v1), RCL_SERVER); - osc_ast_data_put(env, olck); + cl_object_put(env, obj); } else { /* * These errors are normal races, so we don't want to @@ -905,23 +644,24 @@ static int weigh_cb(const struct lu_env *env, struct cl_io *io, } static unsigned long osc_lock_weight(const struct lu_env *env, - const struct osc_lock *ols) + struct osc_object *oscobj, + struct ldlm_extent *extent) { struct cl_io *io = &osc_env_info(env)->oti_io; - struct cl_lock_descr *descr = &ols->ols_cl.cls_lock->cll_descr; - struct cl_object *obj = ols->ols_cl.cls_obj; + struct cl_object *obj = cl_object_top(&oscobj->oo_cl); unsigned long npages = 0; int result; - io->ci_obj = cl_object_top(obj); + io->ci_obj = obj; io->ci_ignore_layout = 1; result = cl_io_init(env, io, CIT_MISC, io->ci_obj); if (result != 0) return result; do { - result = osc_page_gang_lookup(env, io, cl2osc(obj), - descr->cld_start, descr->cld_end, + result = osc_page_gang_lookup(env, io, oscobj, + cl_index(obj, extent->start), + cl_index(obj, extent->end), weigh_cb, (void *)&npages); if (result == CLP_GANG_ABORT) break; @@ -940,8 +680,10 @@ unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock) { struct cl_env_nest nest; struct lu_env *env; - struct osc_lock *lock; + struct osc_object *obj; + struct osc_lock *oscl; unsigned long weight; + bool found = false; might_sleep(); /* @@ -957,18 +699,28 @@ unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock) return 1; LASSERT(dlmlock->l_resource->lr_type == LDLM_EXTENT); - lock = osc_ast_data_get(dlmlock); - if (!lock) { - /* cl_lock was destroyed because of memory pressure. - * It is much reasonable to assign this type of lock - * a lower cost. + obj = dlmlock->l_ast_data; + if (obj) { + weight = 1; + goto out; + } + + spin_lock(&obj->oo_ol_spin); + list_for_each_entry(oscl, &obj->oo_ol_list, ols_nextlock_oscobj) { + if (oscl->ols_dlmlock && oscl->ols_dlmlock != dlmlock) + continue; + found = true; + } + spin_unlock(&obj->oo_ol_spin); + if (found) { + /* + * If the lock is being used by an IO, definitely not cancel it. */ - weight = 0; + weight = 1; goto out; } - weight = osc_lock_weight(env, lock); - osc_ast_data_put(env, lock); + weight = osc_lock_weight(env, obj, &dlmlock->l_policy_data.l_extent); out: cl_env_nested_put(&nest, env); @@ -976,27 +728,16 @@ unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock) } static void osc_lock_build_einfo(const struct lu_env *env, - const struct cl_lock *clock, - struct osc_lock *lock, + const struct cl_lock *lock, + struct osc_object *osc, struct ldlm_enqueue_info *einfo) { - enum cl_lock_mode mode; - - mode = clock->cll_descr.cld_mode; - if (mode == CLM_PHANTOM) - /* - * For now, enqueue all glimpse locks in read mode. In the - * future, client might choose to enqueue LCK_PW lock for - * glimpse on a file opened for write. - */ - mode = CLM_READ; - einfo->ei_type = LDLM_EXTENT; - einfo->ei_mode = osc_cl_lock2ldlm(mode); + einfo->ei_mode = osc_cl_lock2ldlm(lock->cll_descr.cld_mode); einfo->ei_cb_bl = osc_ldlm_blocking_ast; - einfo->ei_cb_cp = osc_ldlm_completion_ast; + einfo->ei_cb_cp = ldlm_completion_ast; einfo->ei_cb_gl = osc_ldlm_glimpse_ast; - einfo->ei_cbdata = lock; /* value to be put into ->l_ast_data */ + einfo->ei_cbdata = osc; /* value to be put into ->l_ast_data */ } /** @@ -1052,113 +793,100 @@ static void osc_lock_to_lockless(const struct lu_env *env, LASSERT(ergo(ols->ols_glimpse, !osc_lock_is_lockless(ols))); } -static int osc_lock_compatible(const struct osc_lock *qing, - const struct osc_lock *qed) +static bool osc_lock_compatible(const struct osc_lock *qing, + const struct osc_lock *qed) { - enum cl_lock_mode qing_mode; - enum cl_lock_mode qed_mode; + struct cl_lock_descr *qed_descr = &qed->ols_cl.cls_lock->cll_descr; + struct cl_lock_descr *qing_descr = &qing->ols_cl.cls_lock->cll_descr; - qing_mode = qing->ols_cl.cls_lock->cll_descr.cld_mode; - if (qed->ols_glimpse && - (qed->ols_state >= OLS_UPCALL_RECEIVED || qing_mode == CLM_READ)) - return 1; + if (qed->ols_glimpse) + return true; + + if (qing_descr->cld_mode == CLM_READ && qed_descr->cld_mode == CLM_READ) + return true; + + if (qed->ols_state < OLS_GRANTED) + return true; + + if (qed_descr->cld_mode >= qing_descr->cld_mode && + qed_descr->cld_start <= qing_descr->cld_start && + qed_descr->cld_end >= qing_descr->cld_end) + return true; - qed_mode = qed->ols_cl.cls_lock->cll_descr.cld_mode; - return ((qing_mode == CLM_READ) && (qed_mode == CLM_READ)); + return false; } -/** - * Cancel all conflicting locks and wait for them to be destroyed. - * - * This function is used for two purposes: - * - * - early cancel all conflicting locks before starting IO, and - * - * - guarantee that pages added to the page cache by lockless IO are never - * covered by locks other than lockless IO lock, and, hence, are not - * visible to other threads. - */ -static int osc_lock_enqueue_wait(const struct lu_env *env, - const struct osc_lock *olck) +static void osc_lock_wake_waiters(const struct lu_env *env, + struct osc_object *osc, + struct osc_lock *oscl) { - struct cl_lock *lock = olck->ols_cl.cls_lock; - struct cl_lock_descr *descr = &lock->cll_descr; - struct cl_object_header *hdr = cl_object_header(descr->cld_obj); - struct cl_lock *scan; - struct cl_lock *conflict = NULL; - int lockless = osc_lock_is_lockless(olck); - int rc = 0; + spin_lock(&osc->oo_ol_spin); + list_del_init(&oscl->ols_nextlock_oscobj); + spin_unlock(&osc->oo_ol_spin); - LASSERT(cl_lock_is_mutexed(lock)); + spin_lock(&oscl->ols_lock); + while (!list_empty(&oscl->ols_waiting_list)) { + struct osc_lock *scan; - /* make it enqueue anyway for glimpse lock, because we actually - * don't need to cancel any conflicting locks. - */ - if (olck->ols_glimpse) - return 0; + scan = list_entry(oscl->ols_waiting_list.next, struct osc_lock, + ols_wait_entry); + list_del_init(&scan->ols_wait_entry); + + cl_sync_io_note(env, scan->ols_owner, 0); + } + spin_unlock(&oscl->ols_lock); +} - spin_lock(&hdr->coh_lock_guard); - list_for_each_entry(scan, &hdr->coh_locks, cll_linkage) { - struct cl_lock_descr *cld = &scan->cll_descr; - const struct osc_lock *scan_ols; +static void osc_lock_enqueue_wait(const struct lu_env *env, + struct osc_object *obj, + struct osc_lock *oscl) +{ + struct osc_lock *tmp_oscl; + struct cl_lock_descr *need = &oscl->ols_cl.cls_lock->cll_descr; + struct cl_sync_io *waiter = &osc_env_info(env)->oti_anchor; + + spin_lock(&obj->oo_ol_spin); + list_add_tail(&oscl->ols_nextlock_oscobj, &obj->oo_ol_list); - if (scan == lock) +restart: + list_for_each_entry(tmp_oscl, &obj->oo_ol_list, + ols_nextlock_oscobj) { + struct cl_lock_descr *descr; + + if (tmp_oscl == oscl) break; - if (scan->cll_state < CLS_QUEUING || - scan->cll_state == CLS_FREEING || - cld->cld_start > descr->cld_end || - cld->cld_end < descr->cld_start) + descr = &tmp_oscl->ols_cl.cls_lock->cll_descr; + if (descr->cld_start > need->cld_end || + descr->cld_end < need->cld_start) continue; - /* overlapped and living locks. */ + /* We're not supposed to give up group lock */ + if (descr->cld_mode == CLM_GROUP) + break; - /* We're not supposed to give up group lock. */ - if (scan->cll_descr.cld_mode == CLM_GROUP) { - LASSERT(descr->cld_mode != CLM_GROUP || - descr->cld_gid != scan->cll_descr.cld_gid); + if (!osc_lock_is_lockless(oscl) && + osc_lock_compatible(oscl, tmp_oscl)) continue; - } - scan_ols = osc_lock_at(scan); + /* wait for conflicting lock to be canceled */ + cl_sync_io_init(waiter, 1, cl_sync_io_end); + oscl->ols_owner = waiter; - /* We need to cancel the compatible locks if we're enqueuing - * a lockless lock, for example: - * imagine that client has PR lock on [0, 1000], and thread T0 - * is doing lockless IO in [500, 1500] region. Concurrent - * thread T1 can see lockless data in [500, 1000], which is - * wrong, because these data are possibly stale. - */ - if (!lockless && osc_lock_compatible(olck, scan_ols)) - continue; + spin_lock(&tmp_oscl->ols_lock); + /* add oscl into tmp's ols_waiting list */ + list_add_tail(&oscl->ols_wait_entry, + &tmp_oscl->ols_waiting_list); + spin_unlock(&tmp_oscl->ols_lock); - cl_lock_get_trust(scan); - conflict = scan; - break; - } - spin_unlock(&hdr->coh_lock_guard); + spin_unlock(&obj->oo_ol_spin); + (void)cl_sync_io_wait(env, waiter, 0); - if (conflict) { - if (lock->cll_descr.cld_mode == CLM_GROUP) { - /* we want a group lock but a previous lock request - * conflicts, we do not wait but return 0 so the - * request is send to the server - */ - CDEBUG(D_DLMTRACE, "group lock %p is conflicted with %p, no wait, send to server\n", - lock, conflict); - cl_lock_put(env, conflict); - rc = 0; - } else { - CDEBUG(D_DLMTRACE, "lock %p is conflicted with %p, will wait\n", - lock, conflict); - LASSERT(!lock->cll_conflict); - lu_ref_add(&conflict->cll_reference, "cancel-wait", - lock); - lock->cll_conflict = conflict; - rc = CLO_WAIT; - } + spin_lock(&obj->oo_ol_spin); + oscl->ols_owner = NULL; + goto restart; } - return rc; + spin_unlock(&obj->oo_ol_spin); } /** @@ -1177,188 +905,122 @@ static int osc_lock_enqueue_wait(const struct lu_env *env, */ static int osc_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, - struct cl_io *unused, __u32 enqflags) + struct cl_io *unused, struct cl_sync_io *anchor) { - struct osc_lock *ols = cl2osc_lock(slice); - struct cl_lock *lock = ols->ols_cl.cls_lock; + struct osc_thread_info *info = osc_env_info(env); + struct osc_io *oio = osc_env_io(env); + struct osc_object *osc = cl2osc(slice->cls_obj); + struct osc_lock *oscl = cl2osc_lock(slice); + struct cl_lock *lock = slice->cls_lock; + struct ldlm_res_id *resname = &info->oti_resname; + ldlm_policy_data_t *policy = &info->oti_policy; + osc_enqueue_upcall_f upcall = osc_lock_upcall; + void *cookie = oscl; + bool async = false; int result; - LASSERT(cl_lock_is_mutexed(lock)); - LASSERTF(ols->ols_state == OLS_NEW, - "Impossible state: %d\n", ols->ols_state); - - LASSERTF(ergo(ols->ols_glimpse, lock->cll_descr.cld_mode <= CLM_READ), - "lock = %p, ols = %p\n", lock, ols); + LASSERTF(ergo(oscl->ols_glimpse, lock->cll_descr.cld_mode <= CLM_READ), + "lock = %p, ols = %p\n", lock, oscl); - result = osc_lock_enqueue_wait(env, ols); - if (result == 0) { - if (!osc_lock_is_lockless(ols)) { - struct osc_object *obj = cl2osc(slice->cls_obj); - struct osc_thread_info *info = osc_env_info(env); - struct ldlm_res_id *resname = &info->oti_resname; - ldlm_policy_data_t *policy = &info->oti_policy; - struct ldlm_enqueue_info *einfo = &ols->ols_einfo; + if (oscl->ols_state == OLS_GRANTED) + return 0; - /* lock will be passed as upcall cookie, - * hold ref to prevent to be released. - */ - cl_lock_hold_add(env, lock, "upcall", lock); - /* a user for lock also */ - cl_lock_user_add(env, lock); - ols->ols_state = OLS_ENQUEUED; + if (oscl->ols_flags & LDLM_FL_TEST_LOCK) + goto enqueue_base; - /* - * XXX: this is possible blocking point as - * ldlm_lock_match(LDLM_FL_LVB_READY) waits for - * LDLM_CP_CALLBACK. - */ - ostid_build_res_name(&obj->oo_oinfo->loi_oi, resname); - osc_lock_build_policy(env, lock, policy); - result = osc_enqueue_base(osc_export(obj), resname, - &ols->ols_flags, policy, - &ols->ols_lvb, - obj->oo_oinfo->loi_kms_valid, - osc_lock_upcall, - ols, einfo, &ols->ols_handle, - PTLRPCD_SET, 1, ols->ols_agl); - if (result != 0) { - cl_lock_user_del(env, lock); - cl_lock_unhold(env, lock, "upcall", lock); - if (unlikely(result == -ECANCELED)) { - ols->ols_state = OLS_NEW; - result = 0; - } - } - } else { - ols->ols_state = OLS_GRANTED; - ols->ols_owner = osc_env_io(env); - } + if (oscl->ols_glimpse) { + LASSERT(equi(oscl->ols_agl, !anchor)); + async = true; + goto enqueue_base; } - LASSERT(ergo(ols->ols_glimpse, !osc_lock_is_lockless(ols))); - return result; -} -static int osc_lock_wait(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct osc_lock *olck = cl2osc_lock(slice); - struct cl_lock *lock = olck->ols_cl.cls_lock; - - LINVRNT(osc_lock_invariant(olck)); - - if (olck->ols_glimpse && olck->ols_state >= OLS_UPCALL_RECEIVED) { - if (olck->ols_flags & LDLM_FL_LVB_READY) { - return 0; - } else if (olck->ols_agl) { - if (lock->cll_flags & CLF_FROM_UPCALL) - /* It is from enqueue RPC reply upcall for - * updating state. Do not re-enqueue. - */ - return -ENAVAIL; - olck->ols_state = OLS_NEW; - } else { - LASSERT(lock->cll_error); - return lock->cll_error; - } + osc_lock_enqueue_wait(env, osc, oscl); + + /* we can grant lockless lock right after all conflicting locks + * are canceled. + */ + if (osc_lock_is_lockless(oscl)) { + oscl->ols_state = OLS_GRANTED; + oio->oi_lockless = 1; + return 0; } - if (olck->ols_state == OLS_NEW) { - int rc; - - LASSERT(olck->ols_agl); - olck->ols_agl = 0; - olck->ols_flags &= ~LDLM_FL_BLOCK_NOWAIT; - rc = osc_lock_enqueue(env, slice, NULL, CEF_ASYNC | CEF_MUST); - if (rc != 0) - return rc; - else - return CLO_REENQUEUED; +enqueue_base: + oscl->ols_state = OLS_ENQUEUED; + if (anchor) { + atomic_inc(&anchor->csi_sync_nr); + oscl->ols_owner = anchor; } - LASSERT(equi(olck->ols_state >= OLS_UPCALL_RECEIVED && - lock->cll_error == 0, olck->ols_lock)); + /** + * DLM lock's ast data must be osc_object; + * if glimpse or AGL lock, async of osc_enqueue_base() must be true, + * DLM's enqueue callback set to osc_lock_upcall() with cookie as + * osc_lock. + */ + ostid_build_res_name(&osc->oo_oinfo->loi_oi, resname); + osc_lock_build_einfo(env, lock, osc, &oscl->ols_einfo); + osc_lock_build_policy(env, lock, policy); + if (oscl->ols_agl) { + oscl->ols_einfo.ei_cbdata = NULL; + /* hold a reference for callback */ + cl_object_get(osc2cl(osc)); + upcall = osc_lock_upcall_agl; + cookie = osc; + } + result = osc_enqueue_base(osc_export(osc), resname, &oscl->ols_flags, + policy, &oscl->ols_lvb, + osc->oo_oinfo->loi_kms_valid, + upcall, cookie, + &oscl->ols_einfo, PTLRPCD_SET, async, + oscl->ols_agl); + if (result != 0) { + oscl->ols_state = OLS_CANCELLED; + osc_lock_wake_waiters(env, osc, oscl); - return lock->cll_error ?: olck->ols_state >= OLS_GRANTED ? 0 : CLO_WAIT; + /* hide error for AGL lock. */ + if (oscl->ols_agl) { + cl_object_put(env, osc2cl(osc)); + result = 0; + } + if (anchor) + cl_sync_io_note(env, anchor, result); + } else { + if (osc_lock_is_lockless(oscl)) { + oio->oi_lockless = 1; + } else if (!async) { + LASSERT(oscl->ols_state == OLS_GRANTED); + LASSERT(oscl->ols_hold); + LASSERT(oscl->ols_dlmlock); + } + } + return result; } /** - * An implementation of cl_lock_operations::clo_use() method that pins cached - * lock. + * Breaks a link between osc_lock and dlm_lock. */ -static int osc_lock_use(const struct lu_env *env, - const struct cl_lock_slice *slice) +static void osc_lock_detach(const struct lu_env *env, struct osc_lock *olck) { - struct osc_lock *olck = cl2osc_lock(slice); - int rc; - - LASSERT(!olck->ols_hold); + struct ldlm_lock *dlmlock; - /* - * Atomically check for LDLM_FL_CBPENDING and addref a lock if this - * flag is not set. This protects us from a concurrent blocking ast. - */ - rc = ldlm_lock_addref_try(&olck->ols_handle, olck->ols_einfo.ei_mode); - if (rc == 0) { - olck->ols_hold = 1; - olck->ols_state = OLS_GRANTED; - } else { - struct cl_lock *lock; + dlmlock = olck->ols_dlmlock; + if (!dlmlock) + return; - /* - * Lock is being cancelled somewhere within - * ldlm_handle_bl_callback(): LDLM_FL_CBPENDING is already - * set, but osc_ldlm_blocking_ast() hasn't yet acquired - * cl_lock mutex. - */ - lock = slice->cls_lock; - LASSERT(lock->cll_state == CLS_INTRANSIT); - LASSERT(lock->cll_users > 0); - /* set a flag for osc_dlm_blocking_ast0() to signal the - * lock. - */ - olck->ols_ast_wait = 1; - rc = CLO_WAIT; + if (olck->ols_hold) { + olck->ols_hold = 0; + osc_cancel_base(&olck->ols_handle, olck->ols_einfo.ei_mode); + olck->ols_handle.cookie = 0ULL; } - return rc; -} -static int osc_lock_flush(struct osc_lock *ols, int discard) -{ - struct cl_lock *lock = ols->ols_cl.cls_lock; - struct cl_env_nest nest; - struct lu_env *env; - int result = 0; + olck->ols_dlmlock = NULL; - env = cl_env_nested_get(&nest); - if (!IS_ERR(env)) { - struct osc_object *obj = cl2osc(ols->ols_cl.cls_obj); - struct cl_lock_descr *descr = &lock->cll_descr; - int rc = 0; - - if (descr->cld_mode >= CLM_WRITE) { - result = osc_cache_writeback_range(env, obj, - descr->cld_start, - descr->cld_end, - 1, discard); - LDLM_DEBUG(ols->ols_lock, - "lock %p: %d pages were %s.\n", lock, result, - discard ? "discarded" : "written"); - if (result > 0) - result = 0; - } - - rc = osc_lock_discard_pages(env, ols); - if (result == 0 && rc < 0) - result = rc; - - cl_env_nested_put(&nest, env); - } else - result = PTR_ERR(env); - if (result == 0) { - ols->ols_flush = 1; - LINVRNT(!osc_lock_has_pages(ols)); - } - return result; + /* release a reference taken in osc_lock_upcall(). */ + LASSERT(olck->ols_has_ref); + lu_ref_del(&dlmlock->l_reference, "osc_lock", olck); + LDLM_LOCK_RELEASE(dlmlock); + olck->ols_has_ref = 0; } /** @@ -1378,96 +1040,16 @@ static int osc_lock_flush(struct osc_lock *ols, int discard) static void osc_lock_cancel(const struct lu_env *env, const struct cl_lock_slice *slice) { - struct cl_lock *lock = slice->cls_lock; - struct osc_lock *olck = cl2osc_lock(slice); - struct ldlm_lock *dlmlock = olck->ols_lock; - int result = 0; - int discard; - - LASSERT(cl_lock_is_mutexed(lock)); - LINVRNT(osc_lock_invariant(olck)); - - if (dlmlock) { - int do_cancel; - - discard = !!(dlmlock->l_flags & LDLM_FL_DISCARD_DATA); - if (olck->ols_state >= OLS_GRANTED) - result = osc_lock_flush(olck, discard); - osc_lock_unhold(olck); - - lock_res_and_lock(dlmlock); - /* Now that we're the only user of dlm read/write reference, - * mostly the ->l_readers + ->l_writers should be zero. - * However, there is a corner case. - * See bug 18829 for details. - */ - do_cancel = (dlmlock->l_readers == 0 && - dlmlock->l_writers == 0); - dlmlock->l_flags |= LDLM_FL_CBPENDING; - unlock_res_and_lock(dlmlock); - if (do_cancel) - result = ldlm_cli_cancel(&olck->ols_handle, LCF_ASYNC); - if (result < 0) - CL_LOCK_DEBUG(D_ERROR, env, lock, - "lock %p cancel failure with error(%d)\n", - lock, result); - } - olck->ols_state = OLS_CANCELLED; - olck->ols_flags &= ~LDLM_FL_LVB_READY; - osc_lock_detach(env, olck); -} - -static int osc_lock_has_pages(struct osc_lock *olck) -{ - return 0; -} - -static void osc_lock_delete(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct osc_lock *olck; - - olck = cl2osc_lock(slice); - if (olck->ols_glimpse) { - LASSERT(!olck->ols_hold); - LASSERT(!olck->ols_lock); - return; - } - - LINVRNT(osc_lock_invariant(olck)); - LINVRNT(!osc_lock_has_pages(olck)); - - osc_lock_unhold(olck); - osc_lock_detach(env, olck); -} + struct osc_object *obj = cl2osc(slice->cls_obj); + struct osc_lock *oscl = cl2osc_lock(slice); -/** - * Implements cl_lock_operations::clo_state() method for osc layer. - * - * Maintains osc_lock::ols_owner field. - * - * This assumes that lock always enters CLS_HELD (from some other state) in - * the same IO context as one that requested the lock. This should not be a - * problem, because context is by definition shared by all activity pertaining - * to the same high-level IO. - */ -static void osc_lock_state(const struct lu_env *env, - const struct cl_lock_slice *slice, - enum cl_lock_state state) -{ - struct osc_lock *lock = cl2osc_lock(slice); + LINVRNT(osc_lock_invariant(oscl)); - /* - * XXX multiple io contexts can use the lock at the same time. - */ - LINVRNT(osc_lock_invariant(lock)); - if (state == CLS_HELD && slice->cls_lock->cll_state != CLS_HELD) { - struct osc_io *oio = osc_env_io(env); + osc_lock_detach(env, oscl); + oscl->ols_state = OLS_CANCELLED; + oscl->ols_flags &= ~LDLM_FL_LVB_READY; - LASSERT(!lock->ols_owner); - lock->ols_owner = oio; - } else if (state != CLS_HELD) - lock->ols_owner = NULL; + osc_lock_wake_waiters(env, obj, oscl); } static int osc_lock_print(const struct lu_env *env, void *cookie, @@ -1475,197 +1057,161 @@ static int osc_lock_print(const struct lu_env *env, void *cookie, { struct osc_lock *lock = cl2osc_lock(slice); - /* - * XXX print ldlm lock and einfo properly. - */ (*p)(env, cookie, "%p %#16llx %#llx %d %p ", - lock->ols_lock, lock->ols_flags, lock->ols_handle.cookie, + lock->ols_dlmlock, lock->ols_flags, lock->ols_handle.cookie, lock->ols_state, lock->ols_owner); osc_lvb_print(env, cookie, p, &lock->ols_lvb); return 0; } -static int osc_lock_fits_into(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *need, - const struct cl_io *io) -{ - struct osc_lock *ols = cl2osc_lock(slice); - - if (need->cld_enq_flags & CEF_NEVER) - return 0; - - if (ols->ols_state >= OLS_CANCELLED) - return 0; - - if (need->cld_mode == CLM_PHANTOM) { - if (ols->ols_agl) - return !(ols->ols_state > OLS_RELEASED); - - /* - * Note: the QUEUED lock can't be matched here, otherwise - * it might cause the deadlocks. - * In read_process, - * P1: enqueued read lock, create sublock1 - * P2: enqueued write lock, create sublock2(conflicted - * with sublock1). - * P1: Grant read lock. - * P1: enqueued glimpse lock(with holding sublock1_read), - * matched with sublock2, waiting sublock2 to be granted. - * But sublock2 can not be granted, because P1 - * will not release sublock1. Bang! - */ - if (ols->ols_state < OLS_GRANTED || - ols->ols_state > OLS_RELEASED) - return 0; - } else if (need->cld_enq_flags & CEF_MUST) { - /* - * If the lock hasn't ever enqueued, it can't be matched - * because enqueue process brings in many information - * which can be used to determine things such as lockless, - * CEF_MUST, etc. - */ - if (ols->ols_state < OLS_UPCALL_RECEIVED && - ols->ols_locklessable) - return 0; - } - return 1; -} - static const struct cl_lock_operations osc_lock_ops = { .clo_fini = osc_lock_fini, .clo_enqueue = osc_lock_enqueue, - .clo_wait = osc_lock_wait, - .clo_unuse = osc_lock_unuse, - .clo_use = osc_lock_use, - .clo_delete = osc_lock_delete, - .clo_state = osc_lock_state, .clo_cancel = osc_lock_cancel, .clo_print = osc_lock_print, - .clo_fits_into = osc_lock_fits_into, }; -static int osc_lock_lockless_unuse(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct osc_lock *ols = cl2osc_lock(slice); - struct cl_lock *lock = slice->cls_lock; - - LASSERT(ols->ols_state == OLS_GRANTED); - LINVRNT(osc_lock_invariant(ols)); - - cl_lock_cancel(env, lock); - cl_lock_delete(env, lock); - return 0; -} - static void osc_lock_lockless_cancel(const struct lu_env *env, const struct cl_lock_slice *slice) { struct osc_lock *ols = cl2osc_lock(slice); + struct osc_object *osc = cl2osc(slice->cls_obj); + struct cl_lock_descr *descr = &slice->cls_lock->cll_descr; int result; - result = osc_lock_flush(ols, 0); + LASSERT(!ols->ols_dlmlock); + result = osc_lock_flush(osc, descr->cld_start, descr->cld_end, + descr->cld_mode, 0); if (result) CERROR("Pages for lockless lock %p were not purged(%d)\n", ols, result); - ols->ols_state = OLS_CANCELLED; -} -static int osc_lock_lockless_wait(const struct lu_env *env, - const struct cl_lock_slice *slice) -{ - struct osc_lock *olck = cl2osc_lock(slice); - struct cl_lock *lock = olck->ols_cl.cls_lock; - - LINVRNT(osc_lock_invariant(olck)); - LASSERT(olck->ols_state >= OLS_UPCALL_RECEIVED); - - return lock->cll_error; + osc_lock_wake_waiters(env, osc, ols); } -static void osc_lock_lockless_state(const struct lu_env *env, - const struct cl_lock_slice *slice, - enum cl_lock_state state) -{ - struct osc_lock *lock = cl2osc_lock(slice); +static const struct cl_lock_operations osc_lock_lockless_ops = { + .clo_fini = osc_lock_fini, + .clo_enqueue = osc_lock_enqueue, + .clo_cancel = osc_lock_lockless_cancel, + .clo_print = osc_lock_print +}; - LINVRNT(osc_lock_invariant(lock)); - if (state == CLS_HELD) { - struct osc_io *oio = osc_env_io(env); +static void osc_lock_set_writer(const struct lu_env *env, + const struct cl_io *io, + struct cl_object *obj, struct osc_lock *oscl) +{ + struct cl_lock_descr *descr = &oscl->ols_cl.cls_lock->cll_descr; + pgoff_t io_start; + pgoff_t io_end; - LASSERT(ergo(lock->ols_owner, lock->ols_owner == oio)); - lock->ols_owner = oio; + if (!cl_object_same(io->ci_obj, obj)) + return; - /* set the io to be lockless if this lock is for io's - * host object - */ - if (cl_object_same(oio->oi_cl.cis_obj, slice->cls_obj)) - oio->oi_lockless = 1; + if (likely(io->ci_type == CIT_WRITE)) { + io_start = cl_index(obj, io->u.ci_rw.crw_pos); + io_end = cl_index(obj, io->u.ci_rw.crw_pos + + io->u.ci_rw.crw_count - 1); + if (cl_io_is_append(io)) { + io_start = 0; + io_end = CL_PAGE_EOF; + } + } else { + LASSERT(cl_io_is_mkwrite(io)); + io_start = io_end = io->u.ci_fault.ft_index; } -} -static int osc_lock_lockless_fits_into(const struct lu_env *env, - const struct cl_lock_slice *slice, - const struct cl_lock_descr *need, - const struct cl_io *io) -{ - struct osc_lock *lock = cl2osc_lock(slice); - - if (!(need->cld_enq_flags & CEF_NEVER)) - return 0; + if (descr->cld_mode >= CLM_WRITE && + descr->cld_start <= io_start && descr->cld_end >= io_end) { + struct osc_io *oio = osc_env_io(env); - /* lockless lock should only be used by its owning io. b22147 */ - return (lock->ols_owner == osc_env_io(env)); + /* There must be only one lock to match the write region */ + LASSERT(!oio->oi_write_osclock); + oio->oi_write_osclock = oscl; + } } -static const struct cl_lock_operations osc_lock_lockless_ops = { - .clo_fini = osc_lock_fini, - .clo_enqueue = osc_lock_enqueue, - .clo_wait = osc_lock_lockless_wait, - .clo_unuse = osc_lock_lockless_unuse, - .clo_state = osc_lock_lockless_state, - .clo_fits_into = osc_lock_lockless_fits_into, - .clo_cancel = osc_lock_lockless_cancel, - .clo_print = osc_lock_print -}; - int osc_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, - const struct cl_io *unused) + const struct cl_io *io) { - struct osc_lock *clk; - int result; + struct osc_lock *oscl; + __u32 enqflags = lock->cll_descr.cld_enq_flags; + + oscl = kmem_cache_zalloc(osc_lock_kmem, GFP_NOFS); + if (!oscl) + return -ENOMEM; + + oscl->ols_state = OLS_NEW; + spin_lock_init(&oscl->ols_lock); + INIT_LIST_HEAD(&oscl->ols_waiting_list); + INIT_LIST_HEAD(&oscl->ols_wait_entry); + INIT_LIST_HEAD(&oscl->ols_nextlock_oscobj); + + oscl->ols_flags = osc_enq2ldlm_flags(enqflags); + oscl->ols_agl = !!(enqflags & CEF_AGL); + if (oscl->ols_agl) + oscl->ols_flags |= LDLM_FL_BLOCK_NOWAIT; + if (oscl->ols_flags & LDLM_FL_HAS_INTENT) { + oscl->ols_flags |= LDLM_FL_BLOCK_GRANTED; + oscl->ols_glimpse = 1; + } - clk = kmem_cache_zalloc(osc_lock_kmem, GFP_NOFS); - if (clk) { - __u32 enqflags = lock->cll_descr.cld_enq_flags; + cl_lock_slice_add(lock, &oscl->ols_cl, obj, &osc_lock_ops); - osc_lock_build_einfo(env, lock, clk, &clk->ols_einfo); - clk->ols_state = OLS_NEW; + if (!(enqflags & CEF_MUST)) + /* try to convert this lock to a lockless lock */ + osc_lock_to_lockless(env, oscl, (enqflags & CEF_NEVER)); + if (oscl->ols_locklessable && !(enqflags & CEF_DISCARD_DATA)) + oscl->ols_flags |= LDLM_FL_DENY_ON_CONTENTION; - clk->ols_flags = osc_enq2ldlm_flags(enqflags); - clk->ols_agl = !!(enqflags & CEF_AGL); - if (clk->ols_agl) - clk->ols_flags |= LDLM_FL_BLOCK_NOWAIT; - if (clk->ols_flags & LDLM_FL_HAS_INTENT) - clk->ols_glimpse = 1; + if (io->ci_type == CIT_WRITE || cl_io_is_mkwrite(io)) + osc_lock_set_writer(env, io, obj, oscl); - cl_lock_slice_add(lock, &clk->ols_cl, obj, &osc_lock_ops); - if (!(enqflags & CEF_MUST)) - /* try to convert this lock to a lockless lock */ - osc_lock_to_lockless(env, clk, (enqflags & CEF_NEVER)); - if (clk->ols_locklessable && !(enqflags & CEF_DISCARD_DATA)) - clk->ols_flags |= LDLM_FL_DENY_ON_CONTENTION; + LDLM_DEBUG_NOLOCK("lock %p, osc lock %p, flags %llx\n", + lock, oscl, oscl->ols_flags); - LDLM_DEBUG_NOLOCK("lock %p, osc lock %p, flags %llx", - lock, clk, clk->ols_flags); + return 0; +} - result = 0; - } else - result = -ENOMEM; - return result; +/** + * Finds an existing lock covering given index and optionally different from a + * given \a except lock. + */ +struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, + struct osc_object *obj, pgoff_t index, + int pending, int canceling) +{ + struct osc_thread_info *info = osc_env_info(env); + struct ldlm_res_id *resname = &info->oti_resname; + ldlm_policy_data_t *policy = &info->oti_policy; + struct lustre_handle lockh; + struct ldlm_lock *lock = NULL; + enum ldlm_mode mode; + __u64 flags; + + ostid_build_res_name(&obj->oo_oinfo->loi_oi, resname); + osc_index2policy(policy, osc2cl(obj), index, index); + policy->l_extent.gid = LDLM_GID_ANY; + + flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK; + if (pending) + flags |= LDLM_FL_CBPENDING; + /* + * It is fine to match any group lock since there could be only one + * with a uniq gid and it conflicts with all other lock modes too + */ +again: + mode = ldlm_lock_match(osc_export(obj)->exp_obd->obd_namespace, + flags, resname, LDLM_EXTENT, policy, + LCK_PR | LCK_PW | LCK_GROUP, &lockh, canceling); + if (mode != 0) { + lock = ldlm_handle2lock(&lockh); + /* RACE: the lock is cancelled so let's try again */ + if (unlikely(!lock)) + goto again; + } + return lock; } /** @} osc */ diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index 2d2d39a82982..a06bdf10b6ff 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -96,6 +96,8 @@ static int osc_object_init(const struct lu_env *env, struct lu_object *obj, atomic_set(&osc->oo_nr_writes, 0); spin_lock_init(&osc->oo_lock); spin_lock_init(&osc->oo_tree_lock); + spin_lock_init(&osc->oo_ol_spin); + INIT_LIST_HEAD(&osc->oo_ol_list); cl_object_page_init(lu2cl(obj), sizeof(struct osc_page)); @@ -122,6 +124,7 @@ static void osc_object_free(const struct lu_env *env, struct lu_object *obj) LASSERT(list_empty(&osc->oo_reading_exts)); LASSERT(atomic_read(&osc->oo_nr_reads) == 0); LASSERT(atomic_read(&osc->oo_nr_writes) == 0); + LASSERT(list_empty(&osc->oo_ol_list)); lu_object_fini(obj); kmem_cache_free(osc_object_kmem, osc); @@ -194,6 +197,32 @@ static int osc_object_glimpse(const struct lu_env *env, return 0; } +static int osc_object_ast_clear(struct ldlm_lock *lock, void *data) +{ + LASSERT(lock->l_granted_mode == lock->l_req_mode); + if (lock->l_ast_data == data) + lock->l_ast_data = NULL; + return LDLM_ITER_CONTINUE; +} + +static int osc_object_prune(const struct lu_env *env, struct cl_object *obj) +{ + struct osc_object *osc = cl2osc(obj); + struct ldlm_res_id *resname = &osc_env_info(env)->oti_resname; + + LASSERTF(osc->oo_npages == 0, + DFID "still have %lu pages, obj: %p, osc: %p\n", + PFID(lu_object_fid(&obj->co_lu)), osc->oo_npages, obj, osc); + + /* DLM locks don't hold a reference of osc_object so we have to + * clear it before the object is being destroyed. + */ + ostid_build_res_name(&osc->oo_oinfo->loi_oi, resname); + ldlm_resource_iterate(osc_export(osc)->exp_obd->obd_namespace, resname, + osc_object_ast_clear, osc); + return 0; +} + void osc_object_set_contended(struct osc_object *obj) { obj->oo_contention_time = cfs_time_current(); @@ -238,12 +267,12 @@ static const struct cl_object_operations osc_ops = { .coo_io_init = osc_io_init, .coo_attr_get = osc_attr_get, .coo_attr_set = osc_attr_set, - .coo_glimpse = osc_object_glimpse + .coo_glimpse = osc_object_glimpse, + .coo_prune = osc_object_prune }; static const struct lu_object_operations osc_lu_obj_ops = { .loo_object_init = osc_object_init, - .loo_object_delete = NULL, .loo_object_release = NULL, .loo_object_free = osc_object_free, .loo_object_print = osc_object_print, diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 5b313519637c..82979f4039c1 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -135,15 +135,15 @@ static int osc_page_is_under_lock(const struct lu_env *env, struct cl_io *unused, pgoff_t *max_index) { struct osc_page *opg = cl2osc_page(slice); - struct cl_lock *lock; + struct ldlm_lock *dlmlock; int result = -ENODATA; - *max_index = 0; - lock = cl_lock_at_pgoff(env, slice->cpl_obj, osc_index(opg), - NULL, 1, 0); - if (lock) { - *max_index = lock->cll_descr.cld_end; - cl_lock_put(env, lock); + dlmlock = osc_dlmlock_at_pgoff(env, cl2osc(slice->cpl_obj), + osc_index(opg), 1, 0); + if (dlmlock) { + *max_index = cl_index(slice->cpl_obj, + dlmlock->l_policy_data.l_extent.end); + LDLM_LOCK_PUT(dlmlock); result = 0; } return result; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 372bd26b07c8..368b99719d48 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -92,12 +92,13 @@ struct osc_fsync_args { struct osc_enqueue_args { struct obd_export *oa_exp; + enum ldlm_type oa_type; + enum ldlm_mode oa_mode; __u64 *oa_flags; - obd_enqueue_update_f oa_upcall; + osc_enqueue_upcall_f oa_upcall; void *oa_cookie; struct ost_lvb *oa_lvb; - struct lustre_handle *oa_lockh; - struct ldlm_enqueue_info *oa_ei; + struct lustre_handle oa_lockh; unsigned int oa_agl:1; }; @@ -2068,14 +2069,12 @@ static int osc_set_lock_data_with_check(struct ldlm_lock *lock, LASSERT(lock->l_glimpse_ast == einfo->ei_cb_gl); lock_res_and_lock(lock); - spin_lock(&osc_ast_guard); if (!lock->l_ast_data) lock->l_ast_data = data; if (lock->l_ast_data == data) set = 1; - spin_unlock(&osc_ast_guard); unlock_res_and_lock(lock); return set; @@ -2117,36 +2116,38 @@ static int osc_find_cbdata(struct obd_export *exp, struct lov_stripe_md *lsm, return rc; } -static int osc_enqueue_fini(struct ptlrpc_request *req, struct ost_lvb *lvb, - obd_enqueue_update_f upcall, void *cookie, - __u64 *flags, int agl, int rc) +static int osc_enqueue_fini(struct ptlrpc_request *req, + osc_enqueue_upcall_f upcall, void *cookie, + struct lustre_handle *lockh, enum ldlm_mode mode, + __u64 *flags, int agl, int errcode) { - int intent = *flags & LDLM_FL_HAS_INTENT; - - if (intent) { - /* The request was created before ldlm_cli_enqueue call. */ - if (rc == ELDLM_LOCK_ABORTED) { - struct ldlm_reply *rep; + bool intent = *flags & LDLM_FL_HAS_INTENT; + int rc; - rep = req_capsule_server_get(&req->rq_pill, - &RMF_DLM_REP); + /* The request was created before ldlm_cli_enqueue call. */ + if (intent && errcode == ELDLM_LOCK_ABORTED) { + struct ldlm_reply *rep; - rep->lock_policy_res1 = - ptlrpc_status_ntoh(rep->lock_policy_res1); - if (rep->lock_policy_res1) - rc = rep->lock_policy_res1; - } - } + rep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP); - if ((intent != 0 && rc == ELDLM_LOCK_ABORTED && agl == 0) || - (rc == 0)) { + rep->lock_policy_res1 = + ptlrpc_status_ntoh(rep->lock_policy_res1); + if (rep->lock_policy_res1) + errcode = rep->lock_policy_res1; + if (!agl) + *flags |= LDLM_FL_LVB_READY; + } else if (errcode == ELDLM_OK) { *flags |= LDLM_FL_LVB_READY; - CDEBUG(D_INODE, "got kms %llu blocks %llu mtime %llu\n", - lvb->lvb_size, lvb->lvb_blocks, lvb->lvb_mtime); } /* Call the update callback. */ - rc = (*upcall)(cookie, rc); + rc = (*upcall)(cookie, lockh, errcode); + /* release the reference taken in ldlm_cli_enqueue() */ + if (errcode == ELDLM_LOCK_MATCHED) + errcode = ELDLM_OK; + if (errcode == ELDLM_OK && lustre_handle_is_used(lockh)) + ldlm_lock_decref(lockh, mode); + return rc; } @@ -2155,62 +2156,47 @@ static int osc_enqueue_interpret(const struct lu_env *env, struct osc_enqueue_args *aa, int rc) { struct ldlm_lock *lock; - struct lustre_handle handle; - __u32 mode; - struct ost_lvb *lvb; - __u32 lvb_len; - __u64 *flags = aa->oa_flags; - - /* Make a local copy of a lock handle and a mode, because aa->oa_* - * might be freed anytime after lock upcall has been called. - */ - lustre_handle_copy(&handle, aa->oa_lockh); - mode = aa->oa_ei->ei_mode; + struct lustre_handle *lockh = &aa->oa_lockh; + enum ldlm_mode mode = aa->oa_mode; + struct ost_lvb *lvb = aa->oa_lvb; + __u32 lvb_len = sizeof(*lvb); + __u64 flags = 0; + /* ldlm_cli_enqueue is holding a reference on the lock, so it must * be valid. */ - lock = ldlm_handle2lock(&handle); + lock = ldlm_handle2lock(lockh); + LASSERTF(lock, "lockh %llx, req %p, aa %p - client evicted?\n", + lockh->cookie, req, aa); /* Take an additional reference so that a blocking AST that * ldlm_cli_enqueue_fini() might post for a failed lock, is guaranteed * to arrive after an upcall has been executed by * osc_enqueue_fini(). */ - ldlm_lock_addref(&handle, mode); + ldlm_lock_addref(lockh, mode); /* Let CP AST to grant the lock first. */ OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_CP_ENQ_RACE, 1); - if (aa->oa_agl && rc == ELDLM_LOCK_ABORTED) { - lvb = NULL; - lvb_len = 0; - } else { - lvb = aa->oa_lvb; - lvb_len = sizeof(*aa->oa_lvb); + if (aa->oa_agl) { + LASSERT(!aa->oa_lvb); + LASSERT(!aa->oa_flags); + aa->oa_flags = &flags; } /* Complete obtaining the lock procedure. */ - rc = ldlm_cli_enqueue_fini(aa->oa_exp, req, aa->oa_ei->ei_type, 1, - mode, flags, lvb, lvb_len, &handle, rc); + rc = ldlm_cli_enqueue_fini(aa->oa_exp, req, aa->oa_type, 1, + aa->oa_mode, aa->oa_flags, lvb, lvb_len, + lockh, rc); /* Complete osc stuff. */ - rc = osc_enqueue_fini(req, aa->oa_lvb, aa->oa_upcall, aa->oa_cookie, - flags, aa->oa_agl, rc); + rc = osc_enqueue_fini(req, aa->oa_upcall, aa->oa_cookie, lockh, mode, + aa->oa_flags, aa->oa_agl, rc); OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_CP_CANCEL_RACE, 10); - /* Release the lock for async request. */ - if (lustre_handle_is_used(&handle) && rc == ELDLM_OK) - /* - * Releases a reference taken by ldlm_cli_enqueue(), if it is - * not already released by - * ldlm_cli_enqueue_fini()->failed_lock_cleanup() - */ - ldlm_lock_decref(&handle, mode); - - LASSERTF(lock, "lockh %p, req %p, aa %p - client evicted?\n", - aa->oa_lockh, req, aa); - ldlm_lock_decref(&handle, mode); + ldlm_lock_decref(lockh, mode); LDLM_LOCK_PUT(lock); return rc; } @@ -2222,21 +2208,21 @@ struct ptlrpc_request_set *PTLRPCD_SET = (void *)1; * other synchronous requests, however keeping some locks and trying to obtain * others may take a considerable amount of time in a case of ost failure; and * when other sync requests do not get released lock from a client, the client - * is excluded from the cluster -- such scenarious make the life difficult, so + * is evicted from the cluster -- such scenaries make the life difficult, so * release locks just after they are obtained. */ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, __u64 *flags, ldlm_policy_data_t *policy, struct ost_lvb *lvb, int kms_valid, - obd_enqueue_update_f upcall, void *cookie, + osc_enqueue_upcall_f upcall, void *cookie, struct ldlm_enqueue_info *einfo, - struct lustre_handle *lockh, struct ptlrpc_request_set *rqset, int async, int agl) { struct obd_device *obd = exp->exp_obd; + struct lustre_handle lockh = { 0 }; struct ptlrpc_request *req = NULL; int intent = *flags & LDLM_FL_HAS_INTENT; - __u64 match_lvb = (agl != 0 ? 0 : LDLM_FL_LVB_READY); + __u64 match_lvb = agl ? 0 : LDLM_FL_LVB_READY; enum ldlm_mode mode; int rc; @@ -2272,55 +2258,39 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, if (einfo->ei_mode == LCK_PR) mode |= LCK_PW; mode = ldlm_lock_match(obd->obd_namespace, *flags | match_lvb, res_id, - einfo->ei_type, policy, mode, lockh, 0); + einfo->ei_type, policy, mode, &lockh, 0); if (mode) { - struct ldlm_lock *matched = ldlm_handle2lock(lockh); + struct ldlm_lock *matched; - if ((agl != 0) && !(matched->l_flags & LDLM_FL_LVB_READY)) { - /* For AGL, if enqueue RPC is sent but the lock is not - * granted, then skip to process this strpe. - * Return -ECANCELED to tell the caller. + if (*flags & LDLM_FL_TEST_LOCK) + return ELDLM_OK; + + matched = ldlm_handle2lock(&lockh); + if (agl) { + /* AGL enqueues DLM locks speculatively. Therefore if + * it already exists a DLM lock, it wll just inform the + * caller to cancel the AGL process for this stripe. */ - ldlm_lock_decref(lockh, mode); + ldlm_lock_decref(&lockh, mode); LDLM_LOCK_PUT(matched); return -ECANCELED; - } - - if (osc_set_lock_data_with_check(matched, einfo)) { + } else if (osc_set_lock_data_with_check(matched, einfo)) { *flags |= LDLM_FL_LVB_READY; - /* addref the lock only if not async requests and PW - * lock is matched whereas we asked for PR. - */ - if (!rqset && einfo->ei_mode != mode) - ldlm_lock_addref(lockh, LCK_PR); - if (intent) { - /* I would like to be able to ASSERT here that - * rss <= kms, but I can't, for reasons which - * are explained in lov_enqueue() - */ - } - - /* We already have a lock, and it's referenced. - * - * At this point, the cl_lock::cll_state is CLS_QUEUING, - * AGL upcall may change it to CLS_HELD directly. - */ - (*upcall)(cookie, ELDLM_OK); + /* We already have a lock, and it's referenced. */ + (*upcall)(cookie, &lockh, ELDLM_LOCK_MATCHED); - if (einfo->ei_mode != mode) - ldlm_lock_decref(lockh, LCK_PW); - else if (rqset) - /* For async requests, decref the lock. */ - ldlm_lock_decref(lockh, einfo->ei_mode); + ldlm_lock_decref(&lockh, mode); LDLM_LOCK_PUT(matched); return ELDLM_OK; + } else { + ldlm_lock_decref(&lockh, mode); + LDLM_LOCK_PUT(matched); } - - ldlm_lock_decref(lockh, mode); - LDLM_LOCK_PUT(matched); } - no_match: +no_match: + if (*flags & LDLM_FL_TEST_LOCK) + return -ENOLCK; if (intent) { LIST_HEAD(cancels); @@ -2344,21 +2314,31 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, *flags &= ~LDLM_FL_BLOCK_GRANTED; rc = ldlm_cli_enqueue(exp, &req, einfo, res_id, policy, flags, lvb, - sizeof(*lvb), LVB_T_OST, lockh, async); - if (rqset) { + sizeof(*lvb), LVB_T_OST, &lockh, async); + if (async) { if (!rc) { struct osc_enqueue_args *aa; - CLASSERT (sizeof(*aa) <= sizeof(req->rq_async_args)); + CLASSERT(sizeof(*aa) <= sizeof(req->rq_async_args)); aa = ptlrpc_req_async_args(req); - aa->oa_ei = einfo; aa->oa_exp = exp; - aa->oa_flags = flags; + aa->oa_mode = einfo->ei_mode; + aa->oa_type = einfo->ei_type; + lustre_handle_copy(&aa->oa_lockh, &lockh); aa->oa_upcall = upcall; aa->oa_cookie = cookie; - aa->oa_lvb = lvb; - aa->oa_lockh = lockh; aa->oa_agl = !!agl; + if (!agl) { + aa->oa_flags = flags; + aa->oa_lvb = lvb; + } else { + /* AGL is essentially to enqueue an DLM lock + * in advance, so we don't care about the + * result of AGL enqueue. + */ + aa->oa_lvb = NULL; + aa->oa_flags = NULL; + } req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_enqueue_interpret; @@ -2372,7 +2352,8 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, return rc; } - rc = osc_enqueue_fini(req, lvb, upcall, cookie, flags, agl, rc); + rc = osc_enqueue_fini(req, upcall, cookie, &lockh, einfo->ei_mode, + flags, agl, rc); if (intent) ptlrpc_req_finished(req); @@ -3359,7 +3340,6 @@ static struct obd_ops osc_obd_ops = { }; extern struct lu_kmem_descr osc_caches[]; -extern spinlock_t osc_ast_guard; extern struct lock_class_key osc_ast_guard_class; static int __init osc_init(void) @@ -3386,9 +3366,6 @@ static int __init osc_init(void) if (rc) goto out_kmem; - spin_lock_init(&osc_ast_guard); - lockdep_set_class(&osc_ast_guard, &osc_ast_guard_class); - /* This is obviously too much memory, only prevent overflow here */ if (osc_reqpool_mem_max >= 1 << 12 || osc_reqpool_mem_max == 0) { rc = -EINVAL; -- GitLab From 71a96a0539a8ebd8273bf627222e260968b82a16 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Wed, 30 Mar 2016 19:48:41 -0400 Subject: [PATCH 0870/9938] staging/lustre: update comments after cl_lock simplification Update comments to reflect current cl_lock situations. Signed-off-by: Bobi Jam Reviewed-on: http://review.whamcloud.com/13137 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6046 Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 130 +++--------------- .../lustre/lustre/lov/lov_cl_internal.h | 13 -- 2 files changed, 19 insertions(+), 124 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 8f9512ef3942..e613007683ae 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1117,111 +1117,29 @@ static inline struct page *cl_page_vmpage(struct cl_page *page) * * LIFE CYCLE * - * cl_lock is reference counted. When reference counter drops to 0, lock is - * placed in the cache, except when lock is in CLS_FREEING state. CLS_FREEING - * lock is destroyed when last reference is released. Referencing between - * top-lock and its sub-locks is described in the lov documentation module. - * - * STATE MACHINE - * - * Also, cl_lock is a state machine. This requires some clarification. One of - * the goals of client IO re-write was to make IO path non-blocking, or at - * least to make it easier to make it non-blocking in the future. Here - * `non-blocking' means that when a system call (read, write, truncate) - * reaches a situation where it has to wait for a communication with the - * server, it should --instead of waiting-- remember its current state and - * switch to some other work. E.g,. instead of waiting for a lock enqueue, - * client should proceed doing IO on the next stripe, etc. Obviously this is - * rather radical redesign, and it is not planned to be fully implemented at - * this time, instead we are putting some infrastructure in place, that would - * make it easier to do asynchronous non-blocking IO easier in the - * future. Specifically, where old locking code goes to sleep (waiting for - * enqueue, for example), new code returns cl_lock_transition::CLO_WAIT. When - * enqueue reply comes, its completion handler signals that lock state-machine - * is ready to transit to the next state. There is some generic code in - * cl_lock.c that sleeps, waiting for these signals. As a result, for users of - * this cl_lock.c code, it looks like locking is done in normal blocking - * fashion, and it the same time it is possible to switch to the non-blocking - * locking (simply by returning cl_lock_transition::CLO_WAIT from cl_lock.c - * functions). - * - * For a description of state machine states and transitions see enum - * cl_lock_state. - * - * There are two ways to restrict a set of states which lock might move to: - * - * - placing a "hold" on a lock guarantees that lock will not be moved - * into cl_lock_state::CLS_FREEING state until hold is released. Hold - * can be only acquired on a lock that is not in - * cl_lock_state::CLS_FREEING. All holds on a lock are counted in - * cl_lock::cll_holds. Hold protects lock from cancellation and - * destruction. Requests to cancel and destroy a lock on hold will be - * recorded, but only honored when last hold on a lock is released; - * - * - placing a "user" on a lock guarantees that lock will not leave - * cl_lock_state::CLS_NEW, cl_lock_state::CLS_QUEUING, - * cl_lock_state::CLS_ENQUEUED and cl_lock_state::CLS_HELD set of - * states, once it enters this set. That is, if a user is added onto a - * lock in a state not from this set, it doesn't immediately enforce - * lock to move to this set, but once lock enters this set it will - * remain there until all users are removed. Lock users are counted in - * cl_lock::cll_users. - * - * User is used to assure that lock is not canceled or destroyed while - * it is being enqueued, or actively used by some IO. - * - * Currently, a user always comes with a hold (cl_lock_invariant() - * checks that a number of holds is not less than a number of users). - * - * CONCURRENCY - * - * This is how lock state-machine operates. struct cl_lock contains a mutex - * cl_lock::cll_guard that protects struct fields. - * - * - mutex is taken, and cl_lock::cll_state is examined. - * - * - for every state there are possible target states where lock can move - * into. They are tried in order. Attempts to move into next state are - * done by _try() functions in cl_lock.c:cl_{enqueue,unlock,wait}_try(). - * - * - if the transition can be performed immediately, state is changed, - * and mutex is released. - * - * - if the transition requires blocking, _try() function returns - * cl_lock_transition::CLO_WAIT. Caller unlocks mutex and goes to - * sleep, waiting for possibility of lock state change. It is woken - * up when some event occurs, that makes lock state change possible - * (e.g., the reception of the reply from the server), and repeats - * the loop. - * - * Top-lock and sub-lock has separate mutexes and the latter has to be taken - * first to avoid dead-lock. - * - * To see an example of interaction of all these issues, take a look at the - * lov_cl.c:lov_lock_enqueue() function. It is called as a part of - * cl_enqueue_try(), and tries to advance top-lock to ENQUEUED state, by - * advancing state-machines of its sub-locks (lov_lock_enqueue_one()). Note - * also, that it uses trylock to grab sub-lock mutex to avoid dead-lock. It - * also has to handle CEF_ASYNC enqueue, when sub-locks enqueues have to be - * done in parallel, rather than one after another (this is used for glimpse - * locks, that cannot dead-lock). + * cl_lock is a cacheless data container for the requirements of locks to + * complete the IO. cl_lock is created before I/O starts and destroyed when the + * I/O is complete. + * + * cl_lock depends on LDLM lock to fulfill lock semantics. LDLM lock is attached + * to cl_lock at OSC layer. LDLM lock is still cacheable. * * INTERFACE AND USAGE * - * struct cl_lock_operations provide a number of call-backs that are invoked - * when events of interest occurs. Layers can intercept and handle glimpse, - * blocking, cancel ASTs and a reception of the reply from the server. + * Two major methods are supported for cl_lock: clo_enqueue and clo_cancel. A + * cl_lock is enqueued by cl_lock_request(), which will call clo_enqueue() + * methods for each layer to enqueue the lock. At the LOV layer, if a cl_lock + * consists of multiple sub cl_locks, each sub locks will be enqueued + * correspondingly. At OSC layer, the lock enqueue request will tend to reuse + * cached LDLM lock; otherwise a new LDLM lock will have to be requested from + * OST side. * - * One important difference with the old client locking model is that new - * client has a representation for the top-lock, whereas in the old code only - * sub-locks existed as real data structures and file-level locks are - * represented by "request sets" that are created and destroyed on each and - * every lock creation. + * cl_lock_cancel() must be called to release a cl_lock after use. clo_cancel() + * method will be called for each layer to release the resource held by this + * lock. At OSC layer, the reference count of LDLM lock, which is held at + * clo_enqueue time, is released. * - * Top-locks are cached, and can be found in the cache by the system calls. It - * is possible that top-lock is in cache, but some of its sub-locks were - * canceled and destroyed. In that case top-lock has to be enqueued again - * before it can be used. + * LDLM lock can only be canceled if there is no cl_lock using it. * * Overall process of the locking during IO operation is as following: * @@ -1234,7 +1152,7 @@ static inline struct page *cl_page_vmpage(struct cl_page *page) * * - when all locks are acquired, IO is performed; * - * - locks are released into cache. + * - locks are released after IO is complete. * * Striping introduces major additional complexity into locking. The * fundamental problem is that it is generally unsafe to actively use (hold) @@ -1256,16 +1174,6 @@ static inline struct page *cl_page_vmpage(struct cl_page *page) * buf is a part of memory mapped Lustre file, a lock or locks protecting buf * has to be held together with the usual lock on [offset, offset + count]. * - * As multi-stripe locks have to be allowed, it makes sense to cache them, so - * that, for example, a sequence of O_APPEND writes can proceed quickly - * without going down to the individual stripes to do lock matching. On the - * other hand, multi-stripe locks shouldn't be used by normal read/write - * calls. To achieve this, every layer can implement ->clo_fits_into() method, - * that is called by lock matching code (cl_lock_lookup()), and that can be - * used to selectively disable matching of certain locks for certain IOs. For - * example, lov layer implements lov_lock_fits_into() that allow multi-stripe - * locks to be matched only for truncates and O_APPEND writes. - * * Interaction with DLM * * In the expected setup, cl_lock is ultimately backed up by a collection of diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index dfe41a82bdd2..ac9744e887ae 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -73,19 +73,6 @@ * - top-page keeps a reference to its sub-page, and destroys it when it * is destroyed. * - * - sub-lock keep a reference to its top-locks. Top-lock keeps a - * reference (and a hold, see cl_lock_hold()) on its sub-locks when it - * actively using them (that is, in cl_lock_state::CLS_QUEUING, - * cl_lock_state::CLS_ENQUEUED, cl_lock_state::CLS_HELD states). When - * moving into cl_lock_state::CLS_CACHED state, top-lock releases a - * hold. From this moment top-lock has only a 'weak' reference to its - * sub-locks. This reference is protected by top-lock - * cl_lock::cll_guard, and will be automatically cleared by the sub-lock - * when the latter is destroyed. When a sub-lock is canceled, a - * reference to it is removed from the top-lock array, and top-lock is - * moved into CLS_NEW state. It is guaranteed that all sub-locks exist - * while their top-lock is in CLS_HELD or CLS_CACHED states. - * * - IO's are not reference counted. * * To implement a connection between top and sub entities, lov layer is split -- GitLab From c11599b8d52d353f45b2dc05d58c48f9812ce6e9 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:42 -0400 Subject: [PATCH 0871/9938] staging/lustre/llite: clip page correctly for vvp_io_commit_sync The original code was wrong which clipped page incorrectly for partial pages started with zero. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/8531 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4201 Reviewed-by: Andreas Dilger Reviewed-by: wangdi Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/vvp_io.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index fb6f93225b99..e44ef21b795e 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -595,15 +595,17 @@ static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, if (plist->pl_nr == 0) return 0; - if (from != 0) { + if (from > 0 || to != PAGE_SIZE) { page = cl_page_list_first(plist); - cl_page_clip(env, page, from, - plist->pl_nr == 1 ? to : PAGE_SIZE); - } - if (to != PAGE_SIZE && plist->pl_nr > 1) { + if (plist->pl_nr == 1) { + cl_page_clip(env, page, from, to); + } else if (from > 0) { + cl_page_clip(env, page, from, PAGE_SIZE); + } else { page = cl_page_list_last(plist); cl_page_clip(env, page, 0, to); } + } cl_2queue_init(queue); cl_page_list_splice(plist, &queue->c2_qin); -- GitLab From d37dd10b71fd304289560901e81eddbe7defb351 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:48:43 -0400 Subject: [PATCH 0872/9938] staging/lustre/llite: deadlock for page write Writing thread already locked page #1, and then wait for the Writeback bit of page #2; Ptlrpc thread is composing a write RPC, so it sets Writeback on page #2 and tries to lock page #1 to make it ready. Deadlocked. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/9036 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4540 Reviewed-by: wangdi Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/rw26.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 50d8289afe06..f87238b3373c 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -512,7 +512,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, /* To avoid deadlock, try to lock page first. */ vmpage = grab_cache_page_nowait(mapping, index); - if (unlikely(!vmpage || PageDirty(vmpage))) { + if (unlikely(!vmpage || PageDirty(vmpage) || PageWriteback(vmpage))) { struct ccc_io *cio = ccc_env_io(env); struct cl_page_list *plist = &cio->u.write.cui_queue; @@ -522,7 +522,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, * more grants. It's okay for the dirty page to be the first * one in commit page list, though. */ - if (vmpage && PageDirty(vmpage) && plist->pl_nr > 0) { + if (vmpage && plist->pl_nr > 0) { unlock_page(vmpage); page_cache_release(vmpage); vmpage = NULL; -- GitLab From 902a34ad7242bb50e467a24855b544148989daf4 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Wed, 30 Mar 2016 19:48:44 -0400 Subject: [PATCH 0873/9938] staging/lustre/llite: make sure we do cl_page_clip on the last page When we are doing a partial IO on both first and last page, the logic currently only call cl_page_clip on the first page, which will end up with a incorrect i_size. Signed-off-by: Li Dongyang Reviewed-on: http://review.whamcloud.com/11630 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5552 Reviewed-by: Ian Costello Reviewed-by: Niu Yawei Reviewed-by: Li Xi Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/vvp_io.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index e44ef21b795e..1d2fc3bf9487 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -599,12 +599,14 @@ static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, page = cl_page_list_first(plist); if (plist->pl_nr == 1) { cl_page_clip(env, page, from, to); - } else if (from > 0) { - cl_page_clip(env, page, from, PAGE_SIZE); } else { - page = cl_page_list_last(plist); - cl_page_clip(env, page, 0, to); - } + if (from > 0) + cl_page_clip(env, page, from, PAGE_SIZE); + if (to != PAGE_SIZE) { + page = cl_page_list_last(plist); + cl_page_clip(env, page, 0, to); + } + } } cl_2queue_init(queue); -- GitLab From 0d345656ea4221cec2dd34a0c7a7ba3f0a8e9047 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:45 -0400 Subject: [PATCH 0874/9938] staging/lustre/llite: merge lclient.h into llite/vvp_internal.h Move the definition of struct cl_client_cache to lustre/include/cl_object.h and move the rest of lustre/include/lclient.h in to lustre/llite/vvp_internal.h. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/12592 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Jinshan Xiong Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 36 ++ .../staging/lustre/lustre/include/lclient.h | 409 ------------------ drivers/staging/lustre/lustre/llite/glimpse.c | 1 - .../staging/lustre/lustre/llite/lcommon_cl.c | 2 - .../lustre/lustre/llite/lcommon_misc.c | 2 +- .../lustre/lustre/llite/llite_internal.h | 2 +- .../lustre/lustre/llite/vvp_internal.h | 368 +++++++++++++++- drivers/staging/lustre/lustre/llite/vvp_io.c | 1 + .../staging/lustre/lustre/llite/vvp_object.c | 1 + .../staging/lustre/lustre/llite/vvp_page.c | 1 + drivers/staging/lustre/lustre/lov/lov_obd.c | 1 - .../lustre/lustre/osc/osc_cl_internal.h | 1 - 12 files changed, 408 insertions(+), 417 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/include/lclient.h diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index e613007683ae..f2bb8f8637cf 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -97,9 +97,12 @@ * super-class definitions. */ #include "lu_object.h" +#include #include "linux/lustre_compat25.h" #include #include +#include +#include struct inode; @@ -2317,6 +2320,39 @@ void cl_lock_descr_print(const struct lu_env *env, void *cookie, const struct cl_lock_descr *descr); /* @} helper */ +/** + * Data structure managing a client's cached pages. A count of + * "unstable" pages is maintained, and an LRU of clean pages is + * maintained. "unstable" pages are pages pinned by the ptlrpc + * layer for recovery purposes. + */ +struct cl_client_cache { + /** + * # of users (OSCs) + */ + atomic_t ccc_users; + /** + * # of threads are doing shrinking + */ + unsigned int ccc_lru_shrinkers; + /** + * # of LRU entries available + */ + atomic_t ccc_lru_left; + /** + * List of entities(OSCs) for this LRU cache + */ + struct list_head ccc_lru; + /** + * Max # of LRU entries + */ + unsigned long ccc_lru_max; + /** + * Lock to protect ccc_lru list + */ + spinlock_t ccc_lru_lock; +}; + /** @} cl_page */ /** \defgroup cl_lock cl_lock diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h deleted file mode 100644 index 82af8aeb7212..000000000000 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * Definitions shared between vvp and liblustre, and other clients in the - * future. - * - * Author: Oleg Drokin - * Author: Nikita Danilov - */ - -#ifndef LCLIENT_H -#define LCLIENT_H - -blkcnt_t dirty_cnt(struct inode *inode); - -int cl_glimpse_size0(struct inode *inode, int agl); -int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, - struct inode *inode, struct cl_object *clob, int agl); - -static inline int cl_glimpse_size(struct inode *inode) -{ - return cl_glimpse_size0(inode, 0); -} - -static inline int cl_agl(struct inode *inode) -{ - return cl_glimpse_size0(inode, 1); -} - -/** - * Locking policy for setattr. - */ -enum ccc_setattr_lock_type { - /** Locking is done by server */ - SETATTR_NOLOCK, - /** Extent lock is enqueued */ - SETATTR_EXTENT_LOCK, - /** Existing local extent lock is used */ - SETATTR_MATCH_LOCK -}; - -/** - * IO state private to vvp or slp layers. - */ -struct ccc_io { - /** super class */ - struct cl_io_slice cui_cl; - struct cl_io_lock_link cui_link; - /** - * I/O vector information to or from which read/write is going. - */ - struct iov_iter *cui_iter; - /** - * Total size for the left IO. - */ - size_t cui_tot_count; - - union { - struct { - enum ccc_setattr_lock_type cui_local_lock; - } setattr; - struct { - struct cl_page_list cui_queue; - unsigned long cui_written; - int cui_from; - int cui_to; - } write; - } u; - /** - * Layout version when this IO is initialized - */ - __u32 cui_layout_gen; - /** - * File descriptor against which IO is done. - */ - struct ll_file_data *cui_fd; - struct kiocb *cui_iocb; -}; - -/** - * True, if \a io is a normal io, False for splice_{read,write}. - * must be implemented in arch specific code. - */ -int cl_is_normalio(const struct lu_env *env, const struct cl_io *io); - -extern struct lu_context_key ccc_key; -extern struct lu_context_key ccc_session_key; - -struct ccc_thread_info { - struct cl_lock cti_lock; - struct cl_lock_descr cti_descr; - struct cl_io cti_io; - struct cl_attr cti_attr; -}; - -static inline struct ccc_thread_info *ccc_env_info(const struct lu_env *env) -{ - struct ccc_thread_info *info; - - info = lu_context_key_get(&env->le_ctx, &ccc_key); - LASSERT(info); - return info; -} - -static inline struct cl_lock *ccc_env_lock(const struct lu_env *env) -{ - struct cl_lock *lock = &ccc_env_info(env)->cti_lock; - - memset(lock, 0, sizeof(*lock)); - return lock; -} - -static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) -{ - struct cl_attr *attr = &ccc_env_info(env)->cti_attr; - - memset(attr, 0, sizeof(*attr)); - return attr; -} - -static inline struct cl_io *ccc_env_thread_io(const struct lu_env *env) -{ - struct cl_io *io = &ccc_env_info(env)->cti_io; - - memset(io, 0, sizeof(*io)); - return io; -} - -struct ccc_session { - struct ccc_io cs_ios; -}; - -static inline struct ccc_session *ccc_env_session(const struct lu_env *env) -{ - struct ccc_session *ses; - - ses = lu_context_key_get(env->le_ses, &ccc_session_key); - LASSERT(ses); - return ses; -} - -static inline struct ccc_io *ccc_env_io(const struct lu_env *env) -{ - return &ccc_env_session(env)->cs_ios; -} - -/** - * ccc-private object state. - */ -struct ccc_object { - struct cl_object_header cob_header; - struct cl_object cob_cl; - struct inode *cob_inode; - - /** - * A list of dirty pages pending IO in the cache. Used by - * SOM. Protected by ll_inode_info::lli_lock. - * - * \see ccc_page::cpg_pending_linkage - */ - struct list_head cob_pending_list; - - /** - * Access this counter is protected by inode->i_sem. Now that - * the lifetime of transient pages must be covered by inode sem, - * we don't need to hold any lock.. - */ - int cob_transient_pages; - /** - * Number of outstanding mmaps on this file. - * - * \see ll_vm_open(), ll_vm_close(). - */ - atomic_t cob_mmap_cnt; - - /** - * various flags - * cob_discard_page_warned - * if pages belonging to this object are discarded when a client - * is evicted, some debug info will be printed, this flag will be set - * during processing the first discarded page, then avoid flooding - * debug message for lots of discarded pages. - * - * \see ll_dirty_page_discard_warn. - */ - unsigned int cob_discard_page_warned:1; -}; - -/** - * ccc-private page state. - */ -struct ccc_page { - struct cl_page_slice cpg_cl; - int cpg_defer_uptodate; - int cpg_ra_used; - int cpg_write_queued; - /** - * Non-empty iff this page is already counted in - * ccc_object::cob_pending_list. Protected by - * ccc_object::cob_pending_guard. This list is only used as a flag, - * that is, never iterated through, only checked for list_empty(), but - * having a list is useful for debugging. - */ - struct list_head cpg_pending_linkage; - /** VM page */ - struct page *cpg_page; -}; - -static inline struct ccc_page *cl2ccc_page(const struct cl_page_slice *slice) -{ - return container_of(slice, struct ccc_page, cpg_cl); -} - -static inline pgoff_t ccc_index(struct ccc_page *ccc) -{ - return ccc->cpg_cl.cpl_index; -} - -struct ccc_device { - struct cl_device cdv_cl; - struct super_block *cdv_sb; - struct cl_device *cdv_next; -}; - -struct ccc_lock { - struct cl_lock_slice clk_cl; -}; - -struct ccc_req { - struct cl_req_slice crq_cl; -}; - -void *ccc_key_init (const struct lu_context *ctx, - struct lu_context_key *key); -void ccc_key_fini (const struct lu_context *ctx, - struct lu_context_key *key, void *data); -void *ccc_session_key_init(const struct lu_context *ctx, - struct lu_context_key *key); -void ccc_session_key_fini(const struct lu_context *ctx, - struct lu_context_key *key, void *data); - -int ccc_device_init (const struct lu_env *env, - struct lu_device *d, - const char *name, struct lu_device *next); -struct lu_device *ccc_device_fini (const struct lu_env *env, - struct lu_device *d); -struct lu_device *ccc_device_alloc(const struct lu_env *env, - struct lu_device_type *t, - struct lustre_cfg *cfg, - const struct lu_device_operations *luops, - const struct cl_device_operations *clops); -struct lu_device *ccc_device_free (const struct lu_env *env, - struct lu_device *d); -struct lu_object *ccc_object_alloc(const struct lu_env *env, - const struct lu_object_header *hdr, - struct lu_device *dev, - const struct cl_object_operations *clops, - const struct lu_object_operations *luops); - -int ccc_req_init(const struct lu_env *env, struct cl_device *dev, - struct cl_req *req); -void ccc_umount(const struct lu_env *env, struct cl_device *dev); -int ccc_global_init(struct lu_device_type *device_type); -void ccc_global_fini(struct lu_device_type *device_type); -int ccc_object_init0(const struct lu_env *env, struct ccc_object *vob, - const struct cl_object_conf *conf); -int ccc_object_init(const struct lu_env *env, struct lu_object *obj, - const struct lu_object_conf *conf); -void ccc_object_free(const struct lu_env *env, struct lu_object *obj); -int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, - struct cl_lock *lock, const struct cl_io *io, - const struct cl_lock_operations *lkops); -int ccc_object_glimpse(const struct lu_env *env, - const struct cl_object *obj, struct ost_lvb *lvb); -int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice); -int ccc_transient_page_prep(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io); -void ccc_lock_delete(const struct lu_env *env, - const struct cl_lock_slice *slice); -void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); -int ccc_lock_enqueue(const struct lu_env *env, - const struct cl_lock_slice *slice, - struct cl_io *io, struct cl_sync_io *anchor); -int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, - __u32 enqflags, enum cl_lock_mode mode, - pgoff_t start, pgoff_t end); -int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io, - __u32 enqflags, enum cl_lock_mode mode, - loff_t start, loff_t end); -void ccc_io_end(const struct lu_env *env, const struct cl_io_slice *ios); -void ccc_io_advance(const struct lu_env *env, const struct cl_io_slice *ios, - size_t nob); -void ccc_io_update_iov(const struct lu_env *env, struct ccc_io *cio, - struct cl_io *io); -int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, - struct cl_io *io, loff_t start, size_t count, int *exceed); -void ccc_req_completion(const struct lu_env *env, - const struct cl_req_slice *slice, int ioret); -void ccc_req_attr_set(const struct lu_env *env, - const struct cl_req_slice *slice, - const struct cl_object *obj, - struct cl_req_attr *oa, u64 flags); - -struct lu_device *ccc2lu_dev (struct ccc_device *vdv); -struct lu_object *ccc2lu (struct ccc_object *vob); -struct ccc_device *lu2ccc_dev (const struct lu_device *d); -struct ccc_device *cl2ccc_dev (const struct cl_device *d); -struct ccc_object *lu2ccc (const struct lu_object *obj); -struct ccc_object *cl2ccc (const struct cl_object *obj); -struct ccc_lock *cl2ccc_lock (const struct cl_lock_slice *slice); -struct ccc_io *cl2ccc_io (const struct lu_env *env, - const struct cl_io_slice *slice); -struct ccc_req *cl2ccc_req (const struct cl_req_slice *slice); -struct page *cl2vm_page (const struct cl_page_slice *slice); -struct inode *ccc_object_inode(const struct cl_object *obj); -struct ccc_object *cl_inode2ccc (struct inode *inode); - -int cl_setattr_ost(struct inode *inode, const struct iattr *attr); - -int ccc_object_invariant(const struct cl_object *obj); -int cl_file_inode_init(struct inode *inode, struct lustre_md *md); -void cl_inode_fini(struct inode *inode); -int cl_local_size(struct inode *inode); - -__u16 ll_dirent_type_get(struct lu_dirent *ent); -__u64 cl_fid_build_ino(const struct lu_fid *fid, int api32); -__u32 cl_fid_build_gen(const struct lu_fid *fid); - -# define CLOBINVRNT(env, clob, expr) \ - ((void)sizeof(env), (void)sizeof(clob), (void)sizeof(!!(expr))) - -int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp); -int cl_ocd_update(struct obd_device *host, - struct obd_device *watched, - enum obd_notify_event ev, void *owner, void *data); - -struct ccc_grouplock { - struct lu_env *cg_env; - struct cl_io *cg_io; - struct cl_lock *cg_lock; - unsigned long cg_gid; -}; - -int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, - struct ccc_grouplock *cg); -void cl_put_grouplock(struct ccc_grouplock *cg); - -/** - * New interfaces to get and put lov_stripe_md from lov layer. This violates - * layering because lov_stripe_md is supposed to be a private data in lov. - * - * NB: If you find you have to use these interfaces for your new code, please - * think about it again. These interfaces may be removed in the future for - * better layering. - */ -struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj); -void lov_lsm_put(struct cl_object *clobj, struct lov_stripe_md *lsm); -int lov_read_and_clear_async_rc(struct cl_object *clob); - -struct lov_stripe_md *ccc_inode_lsm_get(struct inode *inode); -void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm); - -/** - * Data structure managing a client's cached clean pages. An LRU of - * pages is maintained, along with other statistics. - */ -struct cl_client_cache { - atomic_t ccc_users; /* # of users (OSCs) of this data */ - struct list_head ccc_lru; /* LRU list of cached clean pages */ - spinlock_t ccc_lru_lock; /* lock for list */ - atomic_t ccc_lru_left; /* # of LRU entries available */ - unsigned long ccc_lru_max; /* Max # of LRU entries possible */ - unsigned int ccc_lru_shrinkers; /* # of threads reclaiming */ -}; - -#endif /*LCLIENT_H */ diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index 0759dfc1995a..a6346339042f 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -52,7 +52,6 @@ #include #include "../include/cl_object.h" -#include "../include/lclient.h" #include "../llite/llite_internal.h" static const struct cl_lock_descr whole_file = { diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index b339d1bfc5c4..79cdf83c9c16 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -59,8 +59,6 @@ #include "../include/lustre_mdc.h" #include "../include/cl_object.h" -#include "../include/lclient.h" - #include "../llite/llite_internal.h" static const struct cl_req_operations ccc_req_ops; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index 4c12e219ffcc..68e3db1f1b4c 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -41,8 +41,8 @@ #include "../include/obd_support.h" #include "../include/obd.h" #include "../include/cl_object.h" -#include "../include/lclient.h" +#include "vvp_internal.h" #include "../include/lustre_lite.h" /* Initialize the default and maximum LOV EA and cookie sizes. This allows diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index ffed507da069..5686b94030d9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -43,11 +43,11 @@ /* for struct cl_lock_descr and struct cl_io */ #include "../include/cl_object.h" -#include "../include/lclient.h" #include "../include/lustre_mdc.h" #include "../include/lustre_intent.h" #include #include +#include "vvp_internal.h" #ifndef FMODE_EXEC #define FMODE_EXEC 0 diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index aa06f4031311..d4fe61147232 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -41,8 +41,374 @@ #ifndef VVP_INTERNAL_H #define VVP_INTERNAL_H +#include "../include/lustre/lustre_idl.h" #include "../include/cl_object.h" -#include "llite_internal.h" + +enum obd_notify_event; +struct inode; +struct lov_stripe_md; +struct lustre_md; +struct obd_capa; +struct obd_device; +struct obd_export; +struct page; + +blkcnt_t dirty_cnt(struct inode *inode); + +int cl_glimpse_size0(struct inode *inode, int agl); +int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, + struct inode *inode, struct cl_object *clob, int agl); + +static inline int cl_glimpse_size(struct inode *inode) +{ + return cl_glimpse_size0(inode, 0); +} + +static inline int cl_agl(struct inode *inode) +{ + return cl_glimpse_size0(inode, 1); +} + +/** + * Locking policy for setattr. + */ +enum ccc_setattr_lock_type { + /** Locking is done by server */ + SETATTR_NOLOCK, + /** Extent lock is enqueued */ + SETATTR_EXTENT_LOCK, + /** Existing local extent lock is used */ + SETATTR_MATCH_LOCK +}; + +/** + * IO state private to vvp or slp layers. + */ +struct ccc_io { + /** super class */ + struct cl_io_slice cui_cl; + struct cl_io_lock_link cui_link; + /** + * I/O vector information to or from which read/write is going. + */ + struct iov_iter *cui_iter; + /** + * Total size for the left IO. + */ + size_t cui_tot_count; + + union { + struct { + enum ccc_setattr_lock_type cui_local_lock; + } setattr; + struct { + struct cl_page_list cui_queue; + unsigned long cui_written; + int cui_from; + int cui_to; + } write; + } u; + /** + * Layout version when this IO is initialized + */ + __u32 cui_layout_gen; + /** + * File descriptor against which IO is done. + */ + struct ll_file_data *cui_fd; + struct kiocb *cui_iocb; +}; + +/** + * True, if \a io is a normal io, False for other splice_{read,write}. + * must be implemented in arch specific code. + */ +int cl_is_normalio(const struct lu_env *env, const struct cl_io *io); + +extern struct lu_context_key ccc_key; +extern struct lu_context_key ccc_session_key; + +struct ccc_thread_info { + struct cl_lock cti_lock; + struct cl_lock_descr cti_descr; + struct cl_io cti_io; + struct cl_attr cti_attr; +}; + +static inline struct ccc_thread_info *ccc_env_info(const struct lu_env *env) +{ + struct ccc_thread_info *info; + + info = lu_context_key_get(&env->le_ctx, &ccc_key); + LASSERT(info); + + return info; +} + +static inline struct cl_lock *ccc_env_lock(const struct lu_env *env) +{ + struct cl_lock *lock = &ccc_env_info(env)->cti_lock; + + memset(lock, 0, sizeof(*lock)); + return lock; +} + +static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) +{ + struct cl_attr *attr = &ccc_env_info(env)->cti_attr; + + memset(attr, 0, sizeof(*attr)); + + return attr; +} + +static inline struct cl_io *ccc_env_thread_io(const struct lu_env *env) +{ + struct cl_io *io = &ccc_env_info(env)->cti_io; + + memset(io, 0, sizeof(*io)); + + return io; +} + +struct ccc_session { + struct ccc_io cs_ios; +}; + +static inline struct ccc_session *ccc_env_session(const struct lu_env *env) +{ + struct ccc_session *ses; + + ses = lu_context_key_get(env->le_ses, &ccc_session_key); + LASSERT(ses); + + return ses; +} + +static inline struct ccc_io *ccc_env_io(const struct lu_env *env) +{ + return &ccc_env_session(env)->cs_ios; +} + +/** + * ccc-private object state. + */ +struct ccc_object { + struct cl_object_header cob_header; + struct cl_object cob_cl; + struct inode *cob_inode; + + /** + * A list of dirty pages pending IO in the cache. Used by + * SOM. Protected by ll_inode_info::lli_lock. + * + * \see ccc_page::cpg_pending_linkage + */ + struct list_head cob_pending_list; + + /** + * Access this counter is protected by inode->i_sem. Now that + * the lifetime of transient pages must be covered by inode sem, + * we don't need to hold any lock.. + */ + int cob_transient_pages; + /** + * Number of outstanding mmaps on this file. + * + * \see ll_vm_open(), ll_vm_close(). + */ + atomic_t cob_mmap_cnt; + + /** + * various flags + * cob_discard_page_warned + * if pages belonging to this object are discarded when a client + * is evicted, some debug info will be printed, this flag will be set + * during processing the first discarded page, then avoid flooding + * debug message for lots of discarded pages. + * + * \see ll_dirty_page_discard_warn. + */ + unsigned int cob_discard_page_warned:1; +}; + +/** + * ccc-private page state. + */ +struct ccc_page { + struct cl_page_slice cpg_cl; + int cpg_defer_uptodate; + int cpg_ra_used; + int cpg_write_queued; + /** + * Non-empty iff this page is already counted in + * ccc_object::cob_pending_list. Protected by + * ccc_object::cob_pending_guard. This list is only used as a flag, + * that is, never iterated through, only checked for list_empty(), but + * having a list is useful for debugging. + */ + struct list_head cpg_pending_linkage; + /** VM page */ + struct page *cpg_page; +}; + +static inline struct ccc_page *cl2ccc_page(const struct cl_page_slice *slice) +{ + return container_of(slice, struct ccc_page, cpg_cl); +} + +static inline pgoff_t ccc_index(struct ccc_page *ccc) +{ + return ccc->cpg_cl.cpl_index; +} + +struct cl_page *ccc_vmpage_page_transient(struct page *vmpage); + +struct ccc_device { + struct cl_device cdv_cl; + struct super_block *cdv_sb; + struct cl_device *cdv_next; +}; + +struct ccc_lock { + struct cl_lock_slice clk_cl; +}; + +struct ccc_req { + struct cl_req_slice crq_cl; +}; + +void *ccc_key_init(const struct lu_context *ctx, + struct lu_context_key *key); +void ccc_key_fini(const struct lu_context *ctx, + struct lu_context_key *key, void *data); +void *ccc_session_key_init(const struct lu_context *ctx, + struct lu_context_key *key); +void ccc_session_key_fini(const struct lu_context *ctx, + struct lu_context_key *key, void *data); + +int ccc_device_init(const struct lu_env *env, + struct lu_device *d, + const char *name, struct lu_device *next); +struct lu_device *ccc_device_fini(const struct lu_env *env, + struct lu_device *d); +struct lu_device *ccc_device_alloc(const struct lu_env *env, + struct lu_device_type *t, + struct lustre_cfg *cfg, + const struct lu_device_operations *luops, + const struct cl_device_operations *clops); +struct lu_device *ccc_device_free(const struct lu_env *env, + struct lu_device *d); +struct lu_object *ccc_object_alloc(const struct lu_env *env, + const struct lu_object_header *hdr, + struct lu_device *dev, + const struct cl_object_operations *clops, + const struct lu_object_operations *luops); + +int ccc_req_init(const struct lu_env *env, struct cl_device *dev, + struct cl_req *req); +void ccc_umount(const struct lu_env *env, struct cl_device *dev); +int ccc_global_init(struct lu_device_type *device_type); +void ccc_global_fini(struct lu_device_type *device_type); +int ccc_object_init0(const struct lu_env *env, struct ccc_object *vob, + const struct cl_object_conf *conf); +int ccc_object_init(const struct lu_env *env, struct lu_object *obj, + const struct lu_object_conf *conf); +void ccc_object_free(const struct lu_env *env, struct lu_object *obj); +int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, + struct cl_lock *lock, const struct cl_io *io, + const struct cl_lock_operations *lkops); +int ccc_object_glimpse(const struct lu_env *env, + const struct cl_object *obj, struct ost_lvb *lvb); +int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice); +int ccc_transient_page_prep(const struct lu_env *env, + const struct cl_page_slice *slice, + struct cl_io *io); +void ccc_lock_delete(const struct lu_env *env, + const struct cl_lock_slice *slice); +void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); +int ccc_lock_enqueue(const struct lu_env *env, + const struct cl_lock_slice *slice, + struct cl_io *io, struct cl_sync_io *anchor); + +int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, + __u32 enqflags, enum cl_lock_mode mode, + pgoff_t start, pgoff_t end); +int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io, + __u32 enqflags, enum cl_lock_mode mode, + loff_t start, loff_t end); +void ccc_io_end(const struct lu_env *env, const struct cl_io_slice *ios); +void ccc_io_advance(const struct lu_env *env, const struct cl_io_slice *ios, + size_t nob); +void ccc_io_update_iov(const struct lu_env *env, struct ccc_io *cio, + struct cl_io *io); +int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, + struct cl_io *io, loff_t start, size_t count, int *exceed); +void ccc_req_completion(const struct lu_env *env, + const struct cl_req_slice *slice, int ioret); +void ccc_req_attr_set(const struct lu_env *env, + const struct cl_req_slice *slice, + const struct cl_object *obj, + struct cl_req_attr *oa, u64 flags); + +struct lu_device *ccc2lu_dev(struct ccc_device *vdv); +struct lu_object *ccc2lu(struct ccc_object *vob); +struct ccc_device *lu2ccc_dev(const struct lu_device *d); +struct ccc_device *cl2ccc_dev(const struct cl_device *d); +struct ccc_object *lu2ccc(const struct lu_object *obj); +struct ccc_object *cl2ccc(const struct cl_object *obj); +struct ccc_lock *cl2ccc_lock(const struct cl_lock_slice *slice); +struct ccc_io *cl2ccc_io(const struct lu_env *env, + const struct cl_io_slice *slice); +struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice); +struct page *cl2vm_page(const struct cl_page_slice *slice); +struct inode *ccc_object_inode(const struct cl_object *obj); +struct ccc_object *cl_inode2ccc(struct inode *inode); + +int cl_setattr_ost(struct inode *inode, const struct iattr *attr); + +int ccc_object_invariant(const struct cl_object *obj); +int cl_file_inode_init(struct inode *inode, struct lustre_md *md); +void cl_inode_fini(struct inode *inode); +int cl_local_size(struct inode *inode); + +__u16 ll_dirent_type_get(struct lu_dirent *ent); +__u64 cl_fid_build_ino(const struct lu_fid *fid, int api32); +__u32 cl_fid_build_gen(const struct lu_fid *fid); + +# define CLOBINVRNT(env, clob, expr) \ + ((void)sizeof(env), (void)sizeof(clob), (void)sizeof(!!(expr))) + +int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp); +int cl_ocd_update(struct obd_device *host, + struct obd_device *watched, + enum obd_notify_event ev, void *owner, void *data); + +struct ccc_grouplock { + struct lu_env *cg_env; + struct cl_io *cg_io; + struct cl_lock *cg_lock; + unsigned long cg_gid; +}; + +int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, + struct ccc_grouplock *cg); +void cl_put_grouplock(struct ccc_grouplock *cg); + +/** + * New interfaces to get and put lov_stripe_md from lov layer. This violates + * layering because lov_stripe_md is supposed to be a private data in lov. + * + * NB: If you find you have to use these interfaces for your new code, please + * think about it again. These interfaces may be removed in the future for + * better layering. + */ +struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj); +void lov_lsm_put(struct cl_object *clobj, struct lov_stripe_md *lsm); +int lov_read_and_clear_async_rc(struct cl_object *clob); + +struct lov_stripe_md *ccc_inode_lsm_get(struct inode *inode); +void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm); int vvp_io_init(const struct lu_env *env, struct cl_object *obj, struct cl_io *io); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 1d2fc3bf9487..fcf0cfe070ab 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -44,6 +44,7 @@ #include "../include/obd.h" #include "../include/lustre_lite.h" +#include "llite_internal.h" #include "vvp_internal.h" static struct vvp_io *cl2vvp_io(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 34210dbc8cd2..45fac697cd3d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -45,6 +45,7 @@ #include "../include/obd.h" #include "../include/lustre_lite.h" +#include "llite_internal.h" #include "vvp_internal.h" /***************************************************************************** diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 3c6b72398d62..66a4f9b0aa0b 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -44,6 +44,7 @@ #include "../include/obd.h" #include "../include/lustre_lite.h" +#include "llite_internal.h" #include "vvp_internal.h" /***************************************************************************** diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 5daa7faf4dda..1a9e3e8cdda9 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -54,7 +54,6 @@ #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" #include "../include/cl_object.h" -#include "../include/lclient.h" /* for cl_client_lru */ #include "../include/lustre/ll_fiemap.h" #include "../include/lustre_fid.h" diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index c7a69e4cd944..d6d7661ab5ad 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -51,7 +51,6 @@ #include "../include/obd.h" /* osc_build_res_name() */ #include "../include/cl_object.h" -#include "../include/lclient.h" #include "osc_internal.h" /** \defgroup osc osc -- GitLab From 3c95b8396758428405b445fe1faca936f1fe7dc5 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:46 -0400 Subject: [PATCH 0875/9938] staging/lustre/llite: rename ccc_device to vvp_device Rename struct ccc_device to struct vvp_device and merge the CCC device methods into the VVP device methods. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13075 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Lai Siyao Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 2 +- .../staging/lustre/lustre/llite/lcommon_cl.c | 104 +----------------- .../lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/llite/vvp_dev.c | 84 +++++++++++++- .../lustre/lustre/llite/vvp_internal.h | 38 +++---- 5 files changed, 102 insertions(+), 128 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index f2bb8f8637cf..f2a242b74220 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -149,7 +149,7 @@ struct cl_device_operations { /** * Device in the client stack. * - * \see ccc_device, lov_device, lovsub_device, osc_device + * \see vvp_device, lov_device, lovsub_device, osc_device */ struct cl_device { /** Super-class. */ diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 79cdf83c9c16..b0d4a3de8ff0 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -159,91 +159,6 @@ struct lu_context_key ccc_session_key = { .lct_fini = ccc_session_key_fini }; -/* type constructor/destructor: ccc_type_{init,fini,start,stop}(). */ -/* LU_TYPE_INIT_FINI(ccc, &ccc_key, &ccc_session_key); */ - -int ccc_device_init(const struct lu_env *env, struct lu_device *d, - const char *name, struct lu_device *next) -{ - struct ccc_device *vdv; - int rc; - - vdv = lu2ccc_dev(d); - vdv->cdv_next = lu2cl_dev(next); - - LASSERT(d->ld_site && next->ld_type); - next->ld_site = d->ld_site; - rc = next->ld_type->ldt_ops->ldto_device_init( - env, next, next->ld_type->ldt_name, NULL); - if (rc == 0) { - lu_device_get(next); - lu_ref_add(&next->ld_reference, "lu-stack", &lu_site_init); - } - return rc; -} - -struct lu_device *ccc_device_fini(const struct lu_env *env, - struct lu_device *d) -{ - return cl2lu_dev(lu2ccc_dev(d)->cdv_next); -} - -struct lu_device *ccc_device_alloc(const struct lu_env *env, - struct lu_device_type *t, - struct lustre_cfg *cfg, - const struct lu_device_operations *luops, - const struct cl_device_operations *clops) -{ - struct ccc_device *vdv; - struct lu_device *lud; - struct cl_site *site; - int rc; - - vdv = kzalloc(sizeof(*vdv), GFP_NOFS); - if (!vdv) - return ERR_PTR(-ENOMEM); - - lud = &vdv->cdv_cl.cd_lu_dev; - cl_device_init(&vdv->cdv_cl, t); - ccc2lu_dev(vdv)->ld_ops = luops; - vdv->cdv_cl.cd_ops = clops; - - site = kzalloc(sizeof(*site), GFP_NOFS); - if (site) { - rc = cl_site_init(site, &vdv->cdv_cl); - if (rc == 0) { - rc = lu_site_init_finish(&site->cs_lu); - } else { - LASSERT(!lud->ld_site); - CERROR("Cannot init lu_site, rc %d.\n", rc); - kfree(site); - } - } else { - rc = -ENOMEM; - } - if (rc != 0) { - ccc_device_free(env, lud); - lud = ERR_PTR(rc); - } - return lud; -} - -struct lu_device *ccc_device_free(const struct lu_env *env, - struct lu_device *d) -{ - struct ccc_device *vdv = lu2ccc_dev(d); - struct cl_site *site = lu2cl_site(d->ld_site); - struct lu_device *next = cl2lu_dev(vdv->cdv_next); - - if (d->ld_site) { - cl_site_fini(site); - kfree(site); - } - cl_device_fini(lu2cl_dev(d)); - kfree(vdv); - return next; -} - int ccc_req_init(const struct lu_env *env, struct cl_device *dev, struct cl_req *req) { @@ -360,13 +275,13 @@ int ccc_object_init0(const struct lu_env *env, int ccc_object_init(const struct lu_env *env, struct lu_object *obj, const struct lu_object_conf *conf) { - struct ccc_device *dev = lu2ccc_dev(obj->lo_dev); + struct vvp_device *dev = lu2vvp_dev(obj->lo_dev); struct ccc_object *vob = lu2ccc(obj); struct lu_object *below; struct lu_device *under; int result; - under = &dev->cdv_next->cd_lu_dev; + under = &dev->vdv_next->cd_lu_dev; below = under->ld_ops->ldo_object_alloc(env, obj->lo_header, under); if (below) { const struct cl_object_conf *cconf; @@ -779,21 +694,6 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) * */ -struct lu_device *ccc2lu_dev(struct ccc_device *vdv) -{ - return &vdv->cdv_cl.cd_lu_dev; -} - -struct ccc_device *lu2ccc_dev(const struct lu_device *d) -{ - return container_of0(d, struct ccc_device, cdv_cl.cd_lu_dev); -} - -struct ccc_device *cl2ccc_dev(const struct cl_device *d) -{ - return container_of0(d, struct ccc_device, cdv_cl); -} - struct lu_object *ccc2lu(struct ccc_object *vob) { return &vob->cob_cl.co_lu; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 5686b94030d9..1e9e41b225aa 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1321,7 +1321,7 @@ static inline void cl_stats_tally(struct cl_device *dev, enum cl_req_type crt, int opc = (crt == CRT_READ) ? LPROC_LL_OSC_READ : LPROC_LL_OSC_WRITE; - ll_stats_ops_tally(ll_s2sbi(cl2ccc_dev(dev)->cdv_sb), opc, rc); + ll_stats_ops_tally(ll_s2sbi(cl2vvp_dev(dev)->vdv_sb), opc, rc); } ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 29d24c98d259..e934ec87cf60 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -136,11 +136,85 @@ static const struct cl_device_operations vvp_cl_ops = { .cdo_req_init = ccc_req_init }; +static struct lu_device *vvp_device_free(const struct lu_env *env, + struct lu_device *d) +{ + struct vvp_device *vdv = lu2vvp_dev(d); + struct cl_site *site = lu2cl_site(d->ld_site); + struct lu_device *next = cl2lu_dev(vdv->vdv_next); + + if (d->ld_site) { + cl_site_fini(site); + kfree(site); + } + cl_device_fini(lu2cl_dev(d)); + kfree(vdv); + return next; +} + static struct lu_device *vvp_device_alloc(const struct lu_env *env, struct lu_device_type *t, struct lustre_cfg *cfg) { - return ccc_device_alloc(env, t, cfg, &vvp_lu_ops, &vvp_cl_ops); + struct vvp_device *vdv; + struct lu_device *lud; + struct cl_site *site; + int rc; + + vdv = kzalloc(sizeof(*vdv), GFP_NOFS); + if (!vdv) + return ERR_PTR(-ENOMEM); + + lud = &vdv->vdv_cl.cd_lu_dev; + cl_device_init(&vdv->vdv_cl, t); + vvp2lu_dev(vdv)->ld_ops = &vvp_lu_ops; + vdv->vdv_cl.cd_ops = &vvp_cl_ops; + + site = kzalloc(sizeof(*site), GFP_NOFS); + if (site) { + rc = cl_site_init(site, &vdv->vdv_cl); + if (rc == 0) { + rc = lu_site_init_finish(&site->cs_lu); + } else { + LASSERT(!lud->ld_site); + CERROR("Cannot init lu_site, rc %d.\n", rc); + kfree(site); + } + } else { + rc = -ENOMEM; + } + if (rc != 0) { + vvp_device_free(env, lud); + lud = ERR_PTR(rc); + } + return lud; +} + +static int vvp_device_init(const struct lu_env *env, struct lu_device *d, + const char *name, struct lu_device *next) +{ + struct vvp_device *vdv; + int rc; + + vdv = lu2vvp_dev(d); + vdv->vdv_next = lu2cl_dev(next); + + LASSERT(d->ld_site && next->ld_type); + next->ld_site = d->ld_site; + rc = next->ld_type->ldt_ops->ldto_device_init(env, next, + next->ld_type->ldt_name, + NULL); + if (rc == 0) { + lu_device_get(next); + lu_ref_add(&next->ld_reference, "lu-stack", &lu_site_init); + } + return rc; +} + +static struct lu_device *vvp_device_fini(const struct lu_env *env, + struct lu_device *d) +{ + return cl2lu_dev(lu2vvp_dev(d)->vdv_next); } static const struct lu_device_type_operations vvp_device_type_ops = { @@ -151,9 +225,9 @@ static const struct lu_device_type_operations vvp_device_type_ops = { .ldto_stop = vvp_type_stop, .ldto_device_alloc = vvp_device_alloc, - .ldto_device_free = ccc_device_free, - .ldto_device_init = ccc_device_init, - .ldto_device_fini = ccc_device_fini + .ldto_device_free = vvp_device_free, + .ldto_device_init = vvp_device_init, + .ldto_device_fini = vvp_device_fini, }; struct lu_device_type vvp_device_type = { @@ -206,7 +280,7 @@ int cl_sb_init(struct super_block *sb) cl = cl_type_setup(env, NULL, &vvp_device_type, sbi->ll_dt_exp->exp_obd->obd_lu_dev); if (!IS_ERR(cl)) { - cl2ccc_dev(cl)->cdv_sb = sb; + cl2vvp_dev(cl)->vdv_sb = sb; sbi->ll_cl = cl; sbi->ll_site = cl2lu_dev(cl)->ld_site; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index d4fe61147232..34509f9d889f 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -264,10 +264,10 @@ static inline pgoff_t ccc_index(struct ccc_page *ccc) struct cl_page *ccc_vmpage_page_transient(struct page *vmpage); -struct ccc_device { - struct cl_device cdv_cl; - struct super_block *cdv_sb; - struct cl_device *cdv_next; +struct vvp_device { + struct cl_device vdv_cl; + struct super_block *vdv_sb; + struct cl_device *vdv_next; }; struct ccc_lock { @@ -287,18 +287,6 @@ void *ccc_session_key_init(const struct lu_context *ctx, void ccc_session_key_fini(const struct lu_context *ctx, struct lu_context_key *key, void *data); -int ccc_device_init(const struct lu_env *env, - struct lu_device *d, - const char *name, struct lu_device *next); -struct lu_device *ccc_device_fini(const struct lu_env *env, - struct lu_device *d); -struct lu_device *ccc_device_alloc(const struct lu_env *env, - struct lu_device_type *t, - struct lustre_cfg *cfg, - const struct lu_device_operations *luops, - const struct cl_device_operations *clops); -struct lu_device *ccc_device_free(const struct lu_env *env, - struct lu_device *d); struct lu_object *ccc_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev, @@ -351,10 +339,22 @@ void ccc_req_attr_set(const struct lu_env *env, const struct cl_object *obj, struct cl_req_attr *oa, u64 flags); -struct lu_device *ccc2lu_dev(struct ccc_device *vdv); +static inline struct lu_device *vvp2lu_dev(struct vvp_device *vdv) +{ + return &vdv->vdv_cl.cd_lu_dev; +} + +static inline struct vvp_device *lu2vvp_dev(const struct lu_device *d) +{ + return container_of0(d, struct vvp_device, vdv_cl.cd_lu_dev); +} + +static inline struct vvp_device *cl2vvp_dev(const struct cl_device *d) +{ + return container_of0(d, struct vvp_device, vdv_cl); +} + struct lu_object *ccc2lu(struct ccc_object *vob); -struct ccc_device *lu2ccc_dev(const struct lu_device *d); -struct ccc_device *cl2ccc_dev(const struct cl_device *d); struct ccc_object *lu2ccc(const struct lu_object *obj); struct ccc_object *cl2ccc(const struct cl_object *obj); struct ccc_lock *cl2ccc_lock(const struct cl_lock_slice *slice); -- GitLab From 8c7b0e1a67471b621b2200eced63ec2ea6f3b8fa Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:47 -0400 Subject: [PATCH 0876/9938] staging/lustre/llite: rename ccc_object to vvp_object Rename struct ccc_object to struct vvp_object and merge the CCC object methods into the VVP object methods. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13077 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 4 +- drivers/staging/lustre/lustre/llite/glimpse.c | 4 +- .../staging/lustre/lustre/llite/lcommon_cl.c | 166 ++---------------- .../staging/lustre/lustre/llite/llite_close.c | 22 +-- .../lustre/lustre/llite/llite_internal.h | 6 +- .../staging/lustre/lustre/llite/llite_lib.c | 4 +- .../staging/lustre/lustre/llite/llite_mmap.c | 16 +- drivers/staging/lustre/lustre/llite/rw.c | 4 +- drivers/staging/lustre/lustre/llite/rw26.c | 6 +- drivers/staging/lustre/lustre/llite/vvp_dev.c | 10 +- .../lustre/lustre/llite/vvp_internal.h | 61 ++++--- drivers/staging/lustre/lustre/llite/vvp_io.c | 36 ++-- .../staging/lustre/lustre/llite/vvp_object.c | 121 +++++++++++-- .../staging/lustre/lustre/llite/vvp_page.c | 40 ++--- .../lustre/lustre/osc/osc_cl_internal.h | 2 +- 15 files changed, 231 insertions(+), 271 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index f2a242b74220..d3271ffe17da 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -245,7 +245,7 @@ enum cl_attr_valid { * be discarded from the memory, all its sub-objects are torn-down and * destroyed too. * - * \see ccc_object, lov_object, lovsub_object, osc_object + * \see vvp_object, lov_object, lovsub_object, osc_object */ struct cl_object { /** super class */ @@ -385,7 +385,7 @@ struct cl_object_operations { * object. Layers are supposed to fill parts of \a lvb that will be * shipped to the glimpse originator as a glimpse result. * - * \see ccc_object_glimpse(), lovsub_object_glimpse(), + * \see vvp_object_glimpse(), lovsub_object_glimpse(), * \see osc_object_glimpse() */ int (*coo_glimpse)(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index a6346339042f..d76fa163c362 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -69,14 +69,14 @@ static const struct cl_lock_descr whole_file = { blkcnt_t dirty_cnt(struct inode *inode) { blkcnt_t cnt = 0; - struct ccc_object *vob = cl_inode2ccc(inode); + struct vvp_object *vob = cl_inode2vvp(inode); void *results[1]; if (inode->i_mapping) cnt += radix_tree_gang_lookup_tag(&inode->i_mapping->page_tree, results, 0, 1, PAGECACHE_TAG_DIRTY); - if (cnt == 0 && atomic_read(&vob->cob_mmap_cnt) > 0) + if (cnt == 0 && atomic_read(&vob->vob_mmap_cnt) > 0) cnt = 1; return (cnt > 0) ? 1 : 0; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index b0d4a3de8ff0..9db0510d2693 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -68,7 +68,6 @@ static const struct cl_req_operations ccc_req_ops; */ static struct kmem_cache *ccc_lock_kmem; -static struct kmem_cache *ccc_object_kmem; static struct kmem_cache *ccc_thread_kmem; static struct kmem_cache *ccc_session_kmem; static struct kmem_cache *ccc_req_kmem; @@ -79,11 +78,6 @@ static struct lu_kmem_descr ccc_caches[] = { .ckd_name = "ccc_lock_kmem", .ckd_size = sizeof(struct ccc_lock) }, - { - .ckd_cache = &ccc_object_kmem, - .ckd_name = "ccc_object_kmem", - .ckd_size = sizeof(struct ccc_object) - }, { .ckd_cache = &ccc_thread_kmem, .ckd_name = "ccc_thread_kmem", @@ -227,84 +221,6 @@ void ccc_global_fini(struct lu_device_type *device_type) lu_kmem_fini(ccc_caches); } -/***************************************************************************** - * - * Object operations. - * - */ - -struct lu_object *ccc_object_alloc(const struct lu_env *env, - const struct lu_object_header *unused, - struct lu_device *dev, - const struct cl_object_operations *clops, - const struct lu_object_operations *luops) -{ - struct ccc_object *vob; - struct lu_object *obj; - - vob = kmem_cache_zalloc(ccc_object_kmem, GFP_NOFS); - if (vob) { - struct cl_object_header *hdr; - - obj = ccc2lu(vob); - hdr = &vob->cob_header; - cl_object_header_init(hdr); - hdr->coh_page_bufsize = cfs_size_round(sizeof(struct cl_page)); - - lu_object_init(obj, &hdr->coh_lu, dev); - lu_object_add_top(&hdr->coh_lu, obj); - - vob->cob_cl.co_ops = clops; - obj->lo_ops = luops; - } else { - obj = NULL; - } - return obj; -} - -int ccc_object_init0(const struct lu_env *env, - struct ccc_object *vob, - const struct cl_object_conf *conf) -{ - vob->cob_inode = conf->coc_inode; - vob->cob_transient_pages = 0; - cl_object_page_init(&vob->cob_cl, sizeof(struct ccc_page)); - return 0; -} - -int ccc_object_init(const struct lu_env *env, struct lu_object *obj, - const struct lu_object_conf *conf) -{ - struct vvp_device *dev = lu2vvp_dev(obj->lo_dev); - struct ccc_object *vob = lu2ccc(obj); - struct lu_object *below; - struct lu_device *under; - int result; - - under = &dev->vdv_next->cd_lu_dev; - below = under->ld_ops->ldo_object_alloc(env, obj->lo_header, under); - if (below) { - const struct cl_object_conf *cconf; - - cconf = lu2cl_conf(conf); - INIT_LIST_HEAD(&vob->cob_pending_list); - lu_object_add(obj, below); - result = ccc_object_init0(env, vob, cconf); - } else { - result = -ENOMEM; - } - return result; -} - -void ccc_object_free(const struct lu_env *env, struct lu_object *obj) -{ - struct ccc_object *vob = lu2ccc(obj); - - lu_object_fini(obj); - lu_object_header_fini(obj->lo_header); - kmem_cache_free(ccc_object_kmem, vob); -} - int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *unused, @@ -313,7 +229,7 @@ int ccc_lock_init(const struct lu_env *env, struct ccc_lock *clk; int result; - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); clk = kmem_cache_zalloc(ccc_lock_kmem, GFP_NOFS); if (clk) { @@ -325,35 +241,17 @@ int ccc_lock_init(const struct lu_env *env, return result; } -int ccc_object_glimpse(const struct lu_env *env, - const struct cl_object *obj, struct ost_lvb *lvb) -{ - struct inode *inode = ccc_object_inode(obj); - - lvb->lvb_mtime = LTIME_S(inode->i_mtime); - lvb->lvb_atime = LTIME_S(inode->i_atime); - lvb->lvb_ctime = LTIME_S(inode->i_ctime); - /* - * LU-417: Add dirty pages block count lest i_blocks reports 0, some - * "cp" or "tar" on remote node may think it's a completely sparse file - * and skip it. - */ - if (lvb->lvb_size > 0 && lvb->lvb_blocks == 0) - lvb->lvb_blocks = dirty_cnt(inode); - return 0; -} - -static void ccc_object_size_lock(struct cl_object *obj) +static void vvp_object_size_lock(struct cl_object *obj) { - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); ll_inode_size_lock(inode); cl_object_attr_lock(obj); } -static void ccc_object_size_unlock(struct cl_object *obj) +static void vvp_object_size_unlock(struct cl_object *obj) { - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); cl_object_attr_unlock(obj); ll_inode_size_unlock(inode); @@ -399,7 +297,7 @@ int ccc_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, struct cl_io *unused, struct cl_sync_io *anchor) { - CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); + CLOBINVRNT(env, slice->cls_obj, vvp_object_invariant(slice->cls_obj)); return 0; } @@ -417,7 +315,7 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, struct cl_lock_descr *descr = &cio->cui_link.cill_descr; struct cl_object *obj = io->ci_obj; - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end); @@ -462,7 +360,7 @@ int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io, void ccc_io_end(const struct lu_env *env, const struct cl_io_slice *ios) { CLOBINVRNT(env, ios->cis_io->ci_obj, - ccc_object_invariant(ios->cis_io->ci_obj)); + vvp_object_invariant(ios->cis_io->ci_obj)); } void ccc_io_advance(const struct lu_env *env, @@ -473,7 +371,7 @@ void ccc_io_advance(const struct lu_env *env, struct cl_io *io = ios->cis_io; struct cl_object *obj = ios->cis_io->ci_obj; - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); if (!cl_is_normalio(env, io)) return; @@ -496,7 +394,7 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, struct cl_io *io, loff_t start, size_t count, int *exceed) { struct cl_attr *attr = ccc_env_thread_attr(env); - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); loff_t pos = start + count - 1; loff_t kms; int result; @@ -520,7 +418,7 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, * ll_inode_size_lock(). This guarantees that short reads are handled * correctly in the face of concurrent writes and truncates. */ - ccc_object_size_lock(obj); + vvp_object_size_lock(obj); result = cl_object_attr_get(env, obj, attr); if (result == 0) { kms = attr->cat_kms; @@ -530,7 +428,7 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, * return a short read (B) or some zeroes at the end * of the buffer (C) */ - ccc_object_size_unlock(obj); + vvp_object_size_unlock(obj); result = cl_glimpse_lock(env, io, inode, obj, 0); if (result == 0 && exceed) { /* If objective page index exceed end-of-file @@ -567,7 +465,9 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, (__u64)i_size_read(inode)); } } - ccc_object_size_unlock(obj); + + vvp_object_size_unlock(obj); + return result; } @@ -618,7 +518,7 @@ void ccc_req_attr_set(const struct lu_env *env, u32 valid_flags; oa = attr->cra_oa; - inode = ccc_object_inode(obj); + inode = vvp_object_inode(obj); valid_flags = OBD_MD_FLTYPE; if (slice->crs_req->crq_type == CRT_WRITE) { @@ -694,21 +594,6 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) * */ -struct lu_object *ccc2lu(struct ccc_object *vob) -{ - return &vob->cob_cl.co_lu; -} - -struct ccc_object *lu2ccc(const struct lu_object *obj) -{ - return container_of0(obj, struct ccc_object, cob_cl.co_lu); -} - -struct ccc_object *cl2ccc(const struct cl_object *obj) -{ - return container_of0(obj, struct ccc_object, cob_cl); -} - struct ccc_lock *cl2ccc_lock(const struct cl_lock_slice *slice) { return container_of(slice, struct ccc_lock, clk_cl); @@ -734,25 +619,6 @@ struct page *cl2vm_page(const struct cl_page_slice *slice) return cl2ccc_page(slice)->cpg_page; } -/***************************************************************************** - * - * Accessors. - * - */ -int ccc_object_invariant(const struct cl_object *obj) -{ - struct inode *inode = ccc_object_inode(obj); - struct ll_inode_info *lli = ll_i2info(inode); - - return (S_ISREG(inode->i_mode) || inode->i_mode == 0) && - lli->lli_clob == obj; -} - -struct inode *ccc_object_inode(const struct cl_object *obj) -{ - return cl2ccc(obj)->cob_inode; -} - /** * Initialize or update CLIO structures for regular files when new * meta-data arrives from the server. diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index a55ac4dccd90..6e99d341112f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -46,21 +46,21 @@ #include "llite_internal.h" /** records that a write is in flight */ -void vvp_write_pending(struct ccc_object *club, struct ccc_page *page) +void vvp_write_pending(struct vvp_object *club, struct ccc_page *page) { - struct ll_inode_info *lli = ll_i2info(club->cob_inode); + struct ll_inode_info *lli = ll_i2info(club->vob_inode); spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_SOM_DIRTY; if (page && list_empty(&page->cpg_pending_linkage)) - list_add(&page->cpg_pending_linkage, &club->cob_pending_list); + list_add(&page->cpg_pending_linkage, &club->vob_pending_list); spin_unlock(&lli->lli_lock); } /** records that a write has completed */ -void vvp_write_complete(struct ccc_object *club, struct ccc_page *page) +void vvp_write_complete(struct vvp_object *club, struct ccc_page *page) { - struct ll_inode_info *lli = ll_i2info(club->cob_inode); + struct ll_inode_info *lli = ll_i2info(club->vob_inode); int rc = 0; spin_lock(&lli->lli_lock); @@ -70,7 +70,7 @@ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page) } spin_unlock(&lli->lli_lock); if (rc) - ll_queue_done_writing(club->cob_inode, 0); + ll_queue_done_writing(club->vob_inode, 0); } /** Queues DONE_WRITING if @@ -80,13 +80,13 @@ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page) void ll_queue_done_writing(struct inode *inode, unsigned long flags) { struct ll_inode_info *lli = ll_i2info(inode); - struct ccc_object *club = cl2ccc(ll_i2info(inode)->lli_clob); + struct vvp_object *club = cl2vvp(ll_i2info(inode)->lli_clob); spin_lock(&lli->lli_lock); lli->lli_flags |= flags; if ((lli->lli_flags & LLIF_DONE_WRITING) && - list_empty(&club->cob_pending_list)) { + list_empty(&club->vob_pending_list)) { struct ll_close_queue *lcq = ll_i2sbi(inode)->ll_lcq; if (lli->lli_flags & LLIF_MDS_SIZE_LOCK) @@ -140,10 +140,10 @@ void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data, struct obd_client_handle **och, unsigned long flags) { struct ll_inode_info *lli = ll_i2info(inode); - struct ccc_object *club = cl2ccc(ll_i2info(inode)->lli_clob); + struct vvp_object *club = cl2vvp(ll_i2info(inode)->lli_clob); spin_lock(&lli->lli_lock); - if (!(list_empty(&club->cob_pending_list))) { + if (!(list_empty(&club->vob_pending_list))) { if (!(lli->lli_flags & LLIF_EPOCH_PENDING)) { LASSERT(*och); LASSERT(!lli->lli_pending_och); @@ -198,7 +198,7 @@ void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data, } } - LASSERT(list_empty(&club->cob_pending_list)); + LASSERT(list_empty(&club->vob_pending_list)); lli->lli_flags &= ~LLIF_SOM_DIRTY; spin_unlock(&lli->lli_lock); ll_done_writing_attr(inode, op_data); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 1e9e41b225aa..1c39d15f34f5 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -828,10 +828,8 @@ struct ll_close_queue { atomic_t lcq_stop; }; -struct ccc_object *cl_inode2ccc(struct inode *inode); - -void vvp_write_pending (struct ccc_object *club, struct ccc_page *page); -void vvp_write_complete(struct ccc_object *club, struct ccc_page *page); +void vvp_write_pending(struct vvp_object *club, struct ccc_page *page); +void vvp_write_complete(struct vvp_object *club, struct ccc_page *page); /* specific architecture can implement only part of this list */ enum vvp_io_subtype { diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 0f01cfc14b72..95c55c316ec0 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2270,7 +2270,7 @@ void ll_dirty_page_discard_warn(struct page *page, int ioret) { char *buf, *path = NULL; struct dentry *dentry = NULL; - struct ccc_object *obj = cl_inode2ccc(page->mapping->host); + struct vvp_object *obj = cl_inode2vvp(page->mapping->host); /* this can be called inside spin lock so use GFP_ATOMIC. */ buf = (char *)__get_free_page(GFP_ATOMIC); @@ -2284,7 +2284,7 @@ void ll_dirty_page_discard_warn(struct page *page, int ioret) "%s: dirty page discard: %s/fid: " DFID "/%s may get corrupted (rc %d)\n", ll_get_fsname(page->mapping->host->i_sb, NULL, 0), s2lsi(page->mapping->host->i_sb)->lsi_lmd->lmd_dev, - PFID(&obj->cob_header.coh_lu.loh_fid), + PFID(&obj->vob_header.coh_lu.loh_fid), (path && !IS_ERR(path)) ? path : "", ioret); if (dentry) diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index baccf9379ca7..1263da85dd7f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -200,7 +200,7 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, * Otherwise, we could add dirty pages into osc cache * while truncate is on-going. */ - inode = ccc_object_inode(io->ci_obj); + inode = vvp_object_inode(io->ci_obj); lli = ll_i2info(inode); down_read(&lli->lli_trunc_sem); @@ -422,16 +422,16 @@ static int ll_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) /** * To avoid cancel the locks covering mmapped region for lock cache pressure, - * we track the mapped vma count in ccc_object::cob_mmap_cnt. + * we track the mapped vma count in vvp_object::vob_mmap_cnt. */ static void ll_vm_open(struct vm_area_struct *vma) { struct inode *inode = file_inode(vma->vm_file); - struct ccc_object *vob = cl_inode2ccc(inode); + struct vvp_object *vob = cl_inode2vvp(inode); LASSERT(vma->vm_file); - LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0); - atomic_inc(&vob->cob_mmap_cnt); + LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0); + atomic_inc(&vob->vob_mmap_cnt); } /** @@ -440,11 +440,11 @@ static void ll_vm_open(struct vm_area_struct *vma) static void ll_vm_close(struct vm_area_struct *vma) { struct inode *inode = file_inode(vma->vm_file); - struct ccc_object *vob = cl_inode2ccc(inode); + struct vvp_object *vob = cl_inode2vvp(inode); LASSERT(vma->vm_file); - atomic_dec(&vob->cob_mmap_cnt); - LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0); + atomic_dec(&vob->vob_mmap_cnt); + LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0); } /* XXX put nice comment here. talk about __free_pte -> dirty pages and diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index ad15058c2ddb..5ae0993c23dd 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -343,7 +343,7 @@ static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io, pgoff_t index, pgoff_t *max_index) { struct cl_object *clob = io->ci_obj; - struct inode *inode = ccc_object_inode(clob); + struct inode *inode = vvp_object_inode(clob); struct page *vmpage; struct cl_page *page; enum ra_stat which = _NR_RA_STAT; /* keep gcc happy */ @@ -558,7 +558,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, __u64 kms; clob = io->ci_obj; - inode = ccc_object_inode(clob); + inode = vvp_object_inode(clob); memset(ria, 0, sizeof(*ria)); diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index f87238b3373c..ec114bc1c2af 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -350,7 +350,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, struct cl_io *io; struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - struct ccc_object *obj = cl_inode2ccc(inode); + struct vvp_object *obj = cl_inode2vvp(inode); ssize_t count = iov_iter_count(iter); ssize_t tot_bytes = 0, result = 0; struct ll_inode_info *lli = ll_i2info(inode); @@ -386,7 +386,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, if (iov_iter_rw(iter) == READ) inode_lock(inode); - LASSERT(obj->cob_transient_pages == 0); + LASSERT(obj->vob_transient_pages == 0); while (iov_iter_count(iter)) { struct page **pages; size_t offs; @@ -434,7 +434,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, file_offset += result; } out: - LASSERT(obj->cob_transient_pages == 0); + LASSERT(obj->vob_transient_pages == 0); if (iov_iter_rw(iter) == READ) inode_unlock(inode); diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index e934ec87cf60..45c549cb4e53 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -57,9 +57,15 @@ * "llite_" (var. "ll_") prefix. */ +struct kmem_cache *vvp_object_kmem; static struct kmem_cache *vvp_thread_kmem; static struct kmem_cache *vvp_session_kmem; static struct lu_kmem_descr vvp_caches[] = { + { + .ckd_cache = &vvp_object_kmem, + .ckd_name = "vvp_object_kmem", + .ckd_size = sizeof(struct vvp_object), + }, { .ckd_cache = &vvp_thread_kmem, .ckd_name = "vvp_thread_kmem", @@ -431,7 +437,7 @@ static loff_t vvp_pgcache_find(const struct lu_env *env, return ~0ULL; clob = vvp_pgcache_obj(env, dev, &id); if (clob) { - struct inode *inode = ccc_object_inode(clob); + struct inode *inode = vvp_object_inode(clob); struct page *vmpage; int nr; @@ -512,7 +518,7 @@ static int vvp_pgcache_show(struct seq_file *f, void *v) sbi = f->private; clob = vvp_pgcache_obj(env, &sbi->ll_cl->cd_lu_dev, &id); if (clob) { - struct inode *inode = ccc_object_inode(clob); + struct inode *inode = vvp_object_inode(clob); struct cl_page *page = NULL; struct page *vmpage; diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 34509f9d889f..76e7b4c30af0 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -128,6 +128,8 @@ int cl_is_normalio(const struct lu_env *env, const struct cl_io *io); extern struct lu_context_key ccc_key; extern struct lu_context_key ccc_session_key; +extern struct kmem_cache *vvp_object_kmem; + struct ccc_thread_info { struct cl_lock cti_lock; struct cl_lock_descr cti_descr; @@ -193,10 +195,10 @@ static inline struct ccc_io *ccc_env_io(const struct lu_env *env) /** * ccc-private object state. */ -struct ccc_object { - struct cl_object_header cob_header; - struct cl_object cob_cl; - struct inode *cob_inode; +struct vvp_object { + struct cl_object_header vob_header; + struct cl_object vob_cl; + struct inode *vob_inode; /** * A list of dirty pages pending IO in the cache. Used by @@ -204,24 +206,24 @@ struct ccc_object { * * \see ccc_page::cpg_pending_linkage */ - struct list_head cob_pending_list; + struct list_head vob_pending_list; /** * Access this counter is protected by inode->i_sem. Now that * the lifetime of transient pages must be covered by inode sem, * we don't need to hold any lock.. */ - int cob_transient_pages; + int vob_transient_pages; /** * Number of outstanding mmaps on this file. * * \see ll_vm_open(), ll_vm_close(). */ - atomic_t cob_mmap_cnt; + atomic_t vob_mmap_cnt; /** * various flags - * cob_discard_page_warned + * vob_discard_page_warned * if pages belonging to this object are discarded when a client * is evicted, some debug info will be printed, this flag will be set * during processing the first discarded page, then avoid flooding @@ -229,7 +231,7 @@ struct ccc_object { * * \see ll_dirty_page_discard_warn. */ - unsigned int cob_discard_page_warned:1; + unsigned int vob_discard_page_warned:1; }; /** @@ -242,8 +244,7 @@ struct ccc_page { int cpg_write_queued; /** * Non-empty iff this page is already counted in - * ccc_object::cob_pending_list. Protected by - * ccc_object::cob_pending_guard. This list is only used as a flag, + * vvp_object::vob_pending_list. This list is only used as a flag, * that is, never iterated through, only checked for list_empty(), but * having a list is useful for debugging. */ @@ -287,27 +288,14 @@ void *ccc_session_key_init(const struct lu_context *ctx, void ccc_session_key_fini(const struct lu_context *ctx, struct lu_context_key *key, void *data); -struct lu_object *ccc_object_alloc(const struct lu_env *env, - const struct lu_object_header *hdr, - struct lu_device *dev, - const struct cl_object_operations *clops, - const struct lu_object_operations *luops); - int ccc_req_init(const struct lu_env *env, struct cl_device *dev, struct cl_req *req); void ccc_umount(const struct lu_env *env, struct cl_device *dev); int ccc_global_init(struct lu_device_type *device_type); void ccc_global_fini(struct lu_device_type *device_type); -int ccc_object_init0(const struct lu_env *env, struct ccc_object *vob, - const struct cl_object_conf *conf); -int ccc_object_init(const struct lu_env *env, struct lu_object *obj, - const struct lu_object_conf *conf); -void ccc_object_free(const struct lu_env *env, struct lu_object *obj); int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io, const struct cl_lock_operations *lkops); -int ccc_object_glimpse(const struct lu_env *env, - const struct cl_object *obj, struct ost_lvb *lvb); int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice); int ccc_transient_page_prep(const struct lu_env *env, const struct cl_page_slice *slice, @@ -354,20 +342,32 @@ static inline struct vvp_device *cl2vvp_dev(const struct cl_device *d) return container_of0(d, struct vvp_device, vdv_cl); } -struct lu_object *ccc2lu(struct ccc_object *vob); -struct ccc_object *lu2ccc(const struct lu_object *obj); -struct ccc_object *cl2ccc(const struct cl_object *obj); +static inline struct vvp_object *cl2vvp(const struct cl_object *obj) +{ + return container_of0(obj, struct vvp_object, vob_cl); +} + +static inline struct vvp_object *lu2vvp(const struct lu_object *obj) +{ + return container_of0(obj, struct vvp_object, vob_cl.co_lu); +} + +static inline struct inode *vvp_object_inode(const struct cl_object *obj) +{ + return cl2vvp(obj)->vob_inode; +} + +int vvp_object_invariant(const struct cl_object *obj); +struct vvp_object *cl_inode2vvp(struct inode *inode); + struct ccc_lock *cl2ccc_lock(const struct cl_lock_slice *slice); struct ccc_io *cl2ccc_io(const struct lu_env *env, const struct cl_io_slice *slice); struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice); struct page *cl2vm_page(const struct cl_page_slice *slice); -struct inode *ccc_object_inode(const struct cl_object *obj); -struct ccc_object *cl_inode2ccc(struct inode *inode); int cl_setattr_ost(struct inode *inode, const struct iattr *attr); -int ccc_object_invariant(const struct cl_object *obj); int cl_file_inode_init(struct inode *inode, struct lustre_md *md); void cl_inode_fini(struct inode *inode); int cl_local_size(struct inode *inode); @@ -419,7 +419,6 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, struct lu_object *vvp_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); -struct ccc_object *cl_inode2ccc(struct inode *inode); extern const struct file_operations vvp_dump_pgcache_file_ops; diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index fcf0cfe070ab..1773cb24f7b3 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -127,7 +127,7 @@ static int vvp_io_fault_iter_init(const struct lu_env *env, const struct cl_io_slice *ios) { struct vvp_io *vio = cl2vvp_io(env, ios); - struct inode *inode = ccc_object_inode(ios->cis_obj); + struct inode *inode = vvp_object_inode(ios->cis_obj); LASSERT(inode == file_inode(cl2ccc_io(env, ios)->cui_fd->fd_file)); @@ -141,7 +141,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) struct cl_object *obj = io->ci_obj; struct ccc_io *cio = cl2ccc_io(env, ios); - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); CDEBUG(D_VFSTRACE, DFID " ignore/verify layout %d/%d, layout version %d restore needed %d\n", @@ -155,7 +155,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) /* file was detected release, we need to restore it * before finishing the io */ - rc = ll_layout_restore(ccc_object_inode(obj)); + rc = ll_layout_restore(vvp_object_inode(obj)); /* if restore registration failed, no restart, * we will return -ENODATA */ @@ -181,7 +181,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) __u32 gen = 0; /* check layout version */ - ll_layout_refresh(ccc_object_inode(obj), &gen); + ll_layout_refresh(vvp_object_inode(obj), &gen); io->ci_need_restart = cio->cui_layout_gen != gen; if (io->ci_need_restart) { CDEBUG(D_VFSTRACE, @@ -190,7 +190,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) cio->cui_layout_gen, gen); /* today successful restore is the only possible case */ /* restore was done, clear restoring state */ - ll_i2info(ccc_object_inode(obj))->lli_flags &= + ll_i2info(vvp_object_inode(obj))->lli_flags &= ~LLIF_FILE_RESTORING; } } @@ -202,7 +202,7 @@ static void vvp_io_fault_fini(const struct lu_env *env, struct cl_io *io = ios->cis_io; struct cl_page *page = io->u.ci_fault.ft_page; - CLOBINVRNT(env, io->ci_obj, ccc_object_invariant(io->ci_obj)); + CLOBINVRNT(env, io->ci_obj, vvp_object_invariant(io->ci_obj)); if (page) { lu_ref_del(&page->cp_reference, "fault", io); @@ -459,7 +459,7 @@ static int vvp_io_setattr_start(const struct lu_env *env, const struct cl_io_slice *ios) { struct cl_io *io = ios->cis_io; - struct inode *inode = ccc_object_inode(io->ci_obj); + struct inode *inode = vvp_object_inode(io->ci_obj); int result = 0; inode_lock(inode); @@ -475,7 +475,7 @@ static void vvp_io_setattr_end(const struct lu_env *env, const struct cl_io_slice *ios) { struct cl_io *io = ios->cis_io; - struct inode *inode = ccc_object_inode(io->ci_obj); + struct inode *inode = vvp_object_inode(io->ci_obj); if (cl_io_is_trunc(io)) /* Truncate in memory pages - they must be clean pages @@ -499,7 +499,7 @@ static int vvp_io_read_start(const struct lu_env *env, struct ccc_io *cio = cl2ccc_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); struct ll_ra_read *bead = &vio->cui_bead; struct file *file = cio->cui_fd->fd_file; @@ -509,7 +509,7 @@ static int vvp_io_read_start(const struct lu_env *env, long tot = cio->cui_tot_count; int exceed = 0; - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); CDEBUG(D_VFSTRACE, "read: -> [%lli, %lli)\n", pos, pos + cnt); @@ -653,7 +653,7 @@ static void write_commit_callback(const struct lu_env *env, struct cl_io *io, set_page_dirty(vmpage); cp = cl2ccc_page(cl_object_page_slice(clob, page)); - vvp_write_pending(cl2ccc(clob), cp); + vvp_write_pending(cl2vvp(clob), cp); cl_page_disown(env, io, page); @@ -690,7 +690,7 @@ static bool page_list_sanity_check(struct cl_object *obj, int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) { struct cl_object *obj = io->ci_obj; - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); struct ccc_io *cio = ccc_env_io(env); struct cl_page_list *queue = &cio->u.write.cui_queue; struct cl_page *page; @@ -773,7 +773,7 @@ static int vvp_io_write_start(const struct lu_env *env, struct ccc_io *cio = cl2ccc_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); ssize_t result = 0; loff_t pos = io->u.ci_wr.wr.crw_pos; size_t cnt = io->u.ci_wr.wr.crw_count; @@ -874,7 +874,7 @@ static void mkwrite_commit_callback(const struct lu_env *env, struct cl_io *io, set_page_dirty(page->cp_vmpage); cp = cl2ccc_page(cl_object_page_slice(clob, page)); - vvp_write_pending(cl2ccc(clob), cp); + vvp_write_pending(cl2vvp(clob), cp); } static int vvp_io_fault_start(const struct lu_env *env, @@ -883,7 +883,7 @@ static int vvp_io_fault_start(const struct lu_env *env, struct vvp_io *vio = cl2vvp_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); struct cl_fault_io *fio = &io->u.ci_fault; struct vvp_fault_io *cfio = &vio->u.fault; loff_t offset; @@ -1060,7 +1060,7 @@ static int vvp_io_read_page(const struct lu_env *env, struct cl_io *io = ios->cis_io; struct ccc_page *cp = cl2ccc_page(slice); struct cl_page *page = slice->cpl_page; - struct inode *inode = ccc_object_inode(slice->cpl_obj); + struct inode *inode = vvp_object_inode(slice->cpl_obj); struct ll_sb_info *sbi = ll_i2sbi(inode); struct ll_file_data *fd = cl2ccc_io(env, ios)->cui_fd; struct ll_readahead_state *ras = &fd->fd_ras; @@ -1135,10 +1135,10 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, { struct vvp_io *vio = vvp_env_io(env); struct ccc_io *cio = ccc_env_io(env); - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); int result; - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); CDEBUG(D_VFSTRACE, DFID " ignore/verify layout %d/%d, layout version %d restore needed %d\n", diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 45fac697cd3d..9f5e6a6a8f57 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -54,16 +54,25 @@ * */ +int vvp_object_invariant(const struct cl_object *obj) +{ + struct inode *inode = vvp_object_inode(obj); + struct ll_inode_info *lli = ll_i2info(inode); + + return (S_ISREG(inode->i_mode) || inode->i_mode == 0) && + lli->lli_clob == obj; +} + static int vvp_object_print(const struct lu_env *env, void *cookie, lu_printer_t p, const struct lu_object *o) { - struct ccc_object *obj = lu2ccc(o); - struct inode *inode = obj->cob_inode; + struct vvp_object *obj = lu2vvp(o); + struct inode *inode = obj->vob_inode; struct ll_inode_info *lli; (*p)(env, cookie, "(%s %d %d) inode: %p ", - list_empty(&obj->cob_pending_list) ? "-" : "+", - obj->cob_transient_pages, atomic_read(&obj->cob_mmap_cnt), + list_empty(&obj->vob_pending_list) ? "-" : "+", + obj->vob_transient_pages, atomic_read(&obj->vob_mmap_cnt), inode); if (inode) { lli = ll_i2info(inode); @@ -78,7 +87,7 @@ static int vvp_object_print(const struct lu_env *env, void *cookie, static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj, struct cl_attr *attr) { - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); /* * lov overwrites most of these fields in @@ -100,7 +109,7 @@ static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj, static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, const struct cl_attr *attr, unsigned valid) { - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); if (valid & CAT_UID) inode->i_uid = make_kuid(&init_user_ns, attr->cat_uid); @@ -168,7 +177,7 @@ static int vvp_conf_set(const struct lu_env *env, struct cl_object *obj, static int vvp_prune(const struct lu_env *env, struct cl_object *obj) { - struct inode *inode = ccc_object_inode(obj); + struct inode *inode = vvp_object_inode(obj); int rc; rc = cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_LOCAL, 1); @@ -182,6 +191,24 @@ static int vvp_prune(const struct lu_env *env, struct cl_object *obj) return 0; } +static int vvp_object_glimpse(const struct lu_env *env, + const struct cl_object *obj, struct ost_lvb *lvb) +{ + struct inode *inode = vvp_object_inode(obj); + + lvb->lvb_mtime = LTIME_S(inode->i_mtime); + lvb->lvb_atime = LTIME_S(inode->i_atime); + lvb->lvb_ctime = LTIME_S(inode->i_ctime); + /* + * LU-417: Add dirty pages block count lest i_blocks reports 0, some + * "cp" or "tar" on remote node may think it's a completely sparse file + * and skip it. + */ + if (lvb->lvb_size > 0 && lvb->lvb_blocks == 0) + lvb->lvb_blocks = dirty_cnt(inode); + return 0; +} + static const struct cl_object_operations vvp_ops = { .coo_page_init = vvp_page_init, .coo_lock_init = vvp_lock_init, @@ -190,16 +217,60 @@ static const struct cl_object_operations vvp_ops = { .coo_attr_set = vvp_attr_set, .coo_conf_set = vvp_conf_set, .coo_prune = vvp_prune, - .coo_glimpse = ccc_object_glimpse + .coo_glimpse = vvp_object_glimpse }; +static int vvp_object_init0(const struct lu_env *env, + struct vvp_object *vob, + const struct cl_object_conf *conf) +{ + vob->vob_inode = conf->coc_inode; + vob->vob_transient_pages = 0; + cl_object_page_init(&vob->vob_cl, sizeof(struct ccc_page)); + return 0; +} + +static int vvp_object_init(const struct lu_env *env, struct lu_object *obj, + const struct lu_object_conf *conf) +{ + struct vvp_device *dev = lu2vvp_dev(obj->lo_dev); + struct vvp_object *vob = lu2vvp(obj); + struct lu_object *below; + struct lu_device *under; + int result; + + under = &dev->vdv_next->cd_lu_dev; + below = under->ld_ops->ldo_object_alloc(env, obj->lo_header, under); + if (below) { + const struct cl_object_conf *cconf; + + cconf = lu2cl_conf(conf); + INIT_LIST_HEAD(&vob->vob_pending_list); + lu_object_add(obj, below); + result = vvp_object_init0(env, vob, cconf); + } else { + result = -ENOMEM; + } + + return result; +} + +static void vvp_object_free(const struct lu_env *env, struct lu_object *obj) +{ + struct vvp_object *vob = lu2vvp(obj); + + lu_object_fini(obj); + lu_object_header_fini(obj->lo_header); + kmem_cache_free(vvp_object_kmem, vob); +} + static const struct lu_object_operations vvp_lu_obj_ops = { - .loo_object_init = ccc_object_init, - .loo_object_free = ccc_object_free, - .loo_object_print = vvp_object_print + .loo_object_init = vvp_object_init, + .loo_object_free = vvp_object_free, + .loo_object_print = vvp_object_print, }; -struct ccc_object *cl_inode2ccc(struct inode *inode) +struct vvp_object *cl_inode2vvp(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct cl_object *obj = lli->lli_clob; @@ -207,12 +278,32 @@ struct ccc_object *cl_inode2ccc(struct inode *inode) lu = lu_object_locate(obj->co_lu.lo_header, &vvp_device_type); LASSERT(lu); - return lu2ccc(lu); + return lu2vvp(lu); } struct lu_object *vvp_object_alloc(const struct lu_env *env, - const struct lu_object_header *hdr, + const struct lu_object_header *unused, struct lu_device *dev) { - return ccc_object_alloc(env, hdr, dev, &vvp_ops, &vvp_lu_obj_ops); + struct vvp_object *vob; + struct lu_object *obj; + + vob = kmem_cache_zalloc(vvp_object_kmem, GFP_NOFS); + if (vob) { + struct cl_object_header *hdr; + + obj = &vob->vob_cl.co_lu; + hdr = &vob->vob_header; + cl_object_header_init(hdr); + hdr->coh_page_bufsize = cfs_size_round(sizeof(struct cl_page)); + + lu_object_init(obj, &hdr->coh_lu, dev); + lu_object_add_top(&hdr->coh_lu, obj); + + vob->vob_cl.co_ops = &vvp_ops; + obj->lo_ops = &vvp_lu_obj_ops; + } else { + obj = NULL; + } + return obj; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 66a4f9b0aa0b..419a535c79c9 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -159,9 +159,9 @@ static void vvp_page_delete(const struct lu_env *env, LASSERT(PageLocked(vmpage)); LASSERT((struct cl_page *)vmpage->private == page); - LASSERT(inode == ccc_object_inode(obj)); + LASSERT(inode == vvp_object_inode(obj)); - vvp_write_complete(cl2ccc(obj), cl2ccc_page(slice)); + vvp_write_complete(cl2vvp(obj), cl2ccc_page(slice)); /* Drop the reference count held in vvp_page_init */ refc = atomic_dec_return(&page->cp_ref); @@ -220,7 +220,7 @@ static int vvp_page_prep_write(const struct lu_env *env, if (!pg->cp_sync_io) set_page_writeback(vmpage); - vvp_write_pending(cl2ccc(slice->cpl_obj), cl2ccc_page(slice)); + vvp_write_pending(cl2vvp(slice->cpl_obj), cl2ccc_page(slice)); return 0; } @@ -233,11 +233,11 @@ static int vvp_page_prep_write(const struct lu_env *env, */ static void vvp_vmpage_error(struct inode *inode, struct page *vmpage, int ioret) { - struct ccc_object *obj = cl_inode2ccc(inode); + struct vvp_object *obj = cl_inode2vvp(inode); if (ioret == 0) { ClearPageError(vmpage); - obj->cob_discard_page_warned = 0; + obj->vob_discard_page_warned = 0; } else { SetPageError(vmpage); if (ioret == -ENOSPC) @@ -246,8 +246,8 @@ static void vvp_vmpage_error(struct inode *inode, struct page *vmpage, int ioret set_bit(AS_EIO, &inode->i_mapping->flags); if ((ioret == -ESHUTDOWN || ioret == -EINTR) && - obj->cob_discard_page_warned == 0) { - obj->cob_discard_page_warned = 1; + obj->vob_discard_page_warned == 0) { + obj->vob_discard_page_warned = 1; ll_dirty_page_discard_warn(vmpage, ioret); } } @@ -260,7 +260,7 @@ static void vvp_page_completion_read(const struct lu_env *env, struct ccc_page *cp = cl2ccc_page(slice); struct page *vmpage = cp->cpg_page; struct cl_page *page = slice->cpl_page; - struct inode *inode = ccc_object_inode(page->cp_obj); + struct inode *inode = vvp_object_inode(page->cp_obj); LASSERT(PageLocked(vmpage)); CL_PAGE_HEADER(D_PAGE, env, page, "completing READ with %d\n", ioret); @@ -299,7 +299,7 @@ static void vvp_page_completion_write(const struct lu_env *env, */ cp->cpg_write_queued = 0; - vvp_write_complete(cl2ccc(slice->cpl_obj), cp); + vvp_write_complete(cl2vvp(slice->cpl_obj), cp); if (pg->cp_sync_io) { LASSERT(PageLocked(vmpage)); @@ -310,7 +310,7 @@ static void vvp_page_completion_write(const struct lu_env *env, * Only mark the page error only when it's an async write * because applications won't wait for IO to finish. */ - vvp_vmpage_error(ccc_object_inode(pg->cp_obj), vmpage, ioret); + vvp_vmpage_error(vvp_object_inode(pg->cp_obj), vmpage, ioret); end_page_writeback(vmpage); } @@ -342,7 +342,7 @@ static int vvp_page_make_ready(const struct lu_env *env, LASSERT(pg->cp_state == CPS_CACHED); /* This actually clears the dirty bit in the radix tree. */ set_page_writeback(vmpage); - vvp_write_pending(cl2ccc(slice->cpl_obj), cl2ccc_page(slice)); + vvp_write_pending(cl2vvp(slice->cpl_obj), cl2ccc_page(slice)); CL_PAGE_HEADER(D_PAGE, env, pg, "readied\n"); } else if (pg->cp_state == CPS_PAGEOUT) { /* is it possible for osc_flush_async_page() to already @@ -421,7 +421,7 @@ static const struct cl_page_operations vvp_page_ops = { static void vvp_transient_page_verify(const struct cl_page *page) { - struct inode *inode = ccc_object_inode(page->cp_obj); + struct inode *inode = vvp_object_inode(page->cp_obj); LASSERT(!inode_trylock(inode)); } @@ -472,7 +472,7 @@ static void vvp_transient_page_discard(const struct lu_env *env, static int vvp_transient_page_is_vmlocked(const struct lu_env *env, const struct cl_page_slice *slice) { - struct inode *inode = ccc_object_inode(slice->cpl_obj); + struct inode *inode = vvp_object_inode(slice->cpl_obj); int locked; locked = !inode_trylock(inode); @@ -494,11 +494,11 @@ static void vvp_transient_page_fini(const struct lu_env *env, { struct ccc_page *cp = cl2ccc_page(slice); struct cl_page *clp = slice->cpl_page; - struct ccc_object *clobj = cl2ccc(clp->cp_obj); + struct vvp_object *clobj = cl2vvp(clp->cp_obj); vvp_page_fini_common(cp); - LASSERT(!inode_trylock(clobj->cob_inode)); - clobj->cob_transient_pages--; + LASSERT(!inode_trylock(clobj->vob_inode)); + clobj->vob_transient_pages--; } static const struct cl_page_operations vvp_transient_page_ops = { @@ -529,7 +529,7 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, struct ccc_page *cpg = cl_object_page_slice(obj, page); struct page *vmpage = page->cp_vmpage; - CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); cpg->cpg_page = vmpage; page_cache_get(vmpage); @@ -543,12 +543,12 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, cl_page_slice_add(page, &cpg->cpg_cl, obj, index, &vvp_page_ops); } else { - struct ccc_object *clobj = cl2ccc(obj); + struct vvp_object *clobj = cl2vvp(obj); - LASSERT(!inode_trylock(clobj->cob_inode)); + LASSERT(!inode_trylock(clobj->vob_inode)); cl_page_slice_add(page, &cpg->cpg_cl, obj, index, &vvp_transient_page_ops); - clobj->cob_transient_pages++; + clobj->vob_transient_pages++; } return 0; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index d6d7661ab5ad..aba646956900 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -135,7 +135,7 @@ struct osc_object { */ struct list_head oo_inflight[CRT_NR]; /** - * Lock, protecting ccc_object::cob_inflight, because a seat-belt is + * Lock, protecting osc_page::ops_inflight, because a seat-belt is * locked during take-off and landing. */ spinlock_t oo_seatbelt; -- GitLab From 3a52f803382541569f30f225d6f868a36b4c3014 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:48 -0400 Subject: [PATCH 0877/9938] staging/lustre/llite: rename ccc_page to vvp_page Rename struct ccc_page to struct vvp_page and remove obsolete CCC page methods. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13086 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: James Simmons Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 2 +- .../staging/lustre/lustre/llite/lcommon_cl.c | 28 ----- .../staging/lustre/lustre/llite/llite_close.c | 12 +- .../lustre/lustre/llite/llite_internal.h | 4 +- drivers/staging/lustre/lustre/llite/rw.c | 14 +-- drivers/staging/lustre/lustre/llite/rw26.c | 10 +- drivers/staging/lustre/lustre/llite/vvp_dev.c | 12 +- .../lustre/lustre/llite/vvp_internal.h | 38 +++---- drivers/staging/lustre/lustre/llite/vvp_io.c | 34 +++--- .../staging/lustre/lustre/llite/vvp_object.c | 2 +- .../staging/lustre/lustre/llite/vvp_page.c | 107 +++++++++++------- 11 files changed, 131 insertions(+), 132 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index d3271ffe17da..3488349d8087 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -769,7 +769,7 @@ struct cl_page { /** * Per-layer part of cl_page. * - * \see ccc_page, lov_page, osc_page + * \see vvp_page, lov_page, osc_page */ struct cl_page_slice { struct cl_page *cpl_page; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 9db0510d2693..07620326081d 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -257,29 +257,6 @@ static void vvp_object_size_unlock(struct cl_object *obj) ll_inode_size_unlock(inode); } -/***************************************************************************** - * - * Page operations. - * - */ - -int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice) -{ - /* - * Cached read? - */ - LBUG(); - return 0; -} - -int ccc_transient_page_prep(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *unused) -{ - /* transient page should always be sent. */ - return 0; -} - /***************************************************************************** * * Lock operations. @@ -614,11 +591,6 @@ struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice) return container_of0(slice, struct ccc_req, crq_cl); } -struct page *cl2vm_page(const struct cl_page_slice *slice) -{ - return cl2ccc_page(slice)->cpg_page; -} - /** * Initialize or update CLIO structures for regular files when new * meta-data arrives from the server. diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index 6e99d341112f..8d2398003c5a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -46,26 +46,26 @@ #include "llite_internal.h" /** records that a write is in flight */ -void vvp_write_pending(struct vvp_object *club, struct ccc_page *page) +void vvp_write_pending(struct vvp_object *club, struct vvp_page *page) { struct ll_inode_info *lli = ll_i2info(club->vob_inode); spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_SOM_DIRTY; - if (page && list_empty(&page->cpg_pending_linkage)) - list_add(&page->cpg_pending_linkage, &club->vob_pending_list); + if (page && list_empty(&page->vpg_pending_linkage)) + list_add(&page->vpg_pending_linkage, &club->vob_pending_list); spin_unlock(&lli->lli_lock); } /** records that a write has completed */ -void vvp_write_complete(struct vvp_object *club, struct ccc_page *page) +void vvp_write_complete(struct vvp_object *club, struct vvp_page *page) { struct ll_inode_info *lli = ll_i2info(club->vob_inode); int rc = 0; spin_lock(&lli->lli_lock); - if (page && !list_empty(&page->cpg_pending_linkage)) { - list_del_init(&page->cpg_pending_linkage); + if (page && !list_empty(&page->vpg_pending_linkage)) { + list_del_init(&page->vpg_pending_linkage); rc = 1; } spin_unlock(&lli->lli_lock); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 1c39d15f34f5..78b3eddcc715 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -828,8 +828,8 @@ struct ll_close_queue { atomic_t lcq_stop; }; -void vvp_write_pending(struct vvp_object *club, struct ccc_page *page); -void vvp_write_complete(struct vvp_object *club, struct ccc_page *page); +void vvp_write_pending(struct vvp_object *club, struct vvp_page *page); +void vvp_write_complete(struct vvp_object *club, struct vvp_page *page); /* specific architecture can implement only part of this list */ enum vvp_io_subtype { diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 5ae0993c23dd..2c4d4c40b407 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -298,21 +298,21 @@ static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, struct cl_object *clob, pgoff_t *max_index) { struct page *vmpage = page->cp_vmpage; - struct ccc_page *cp; + struct vvp_page *vpg; int rc; rc = 0; cl_page_assume(env, io, page); lu_ref_add(&page->cp_reference, "ra", current); - cp = cl2ccc_page(cl_object_page_slice(clob, page)); - if (!cp->cpg_defer_uptodate && !PageUptodate(vmpage)) { + vpg = cl2vvp_page(cl_object_page_slice(clob, page)); + if (!vpg->vpg_defer_uptodate && !PageUptodate(vmpage)) { CDEBUG(D_READA, "page index %lu, max_index: %lu\n", - ccc_index(cp), *max_index); - if (*max_index == 0 || ccc_index(cp) > *max_index) + vvp_index(vpg), *max_index); + if (*max_index == 0 || vvp_index(vpg) > *max_index) rc = cl_page_is_under_lock(env, io, page, max_index); if (rc == 0) { - cp->cpg_defer_uptodate = 1; - cp->cpg_ra_used = 0; + vpg->vpg_defer_uptodate = 1; + vpg->vpg_ra_used = 0; cl_page_list_add(queue, page); rc = 1; } else { diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index ec114bc1c2af..bb85629dd105 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -457,8 +457,8 @@ static int ll_prepare_partial_page(const struct lu_env *env, struct cl_io *io, { struct cl_attr *attr = ccc_env_thread_attr(env); struct cl_object *obj = io->ci_obj; - struct ccc_page *cp = cl_object_page_slice(obj, pg); - loff_t offset = cl_offset(obj, ccc_index(cp)); + struct vvp_page *vpg = cl_object_page_slice(obj, pg); + loff_t offset = cl_offset(obj, vvp_index(vpg)); int result; cl_object_attr_lock(obj); @@ -471,12 +471,12 @@ static int ll_prepare_partial_page(const struct lu_env *env, struct cl_io *io, * purposes here we can treat it like i_size. */ if (attr->cat_kms <= offset) { - char *kaddr = kmap_atomic(cp->cpg_page); + char *kaddr = kmap_atomic(vpg->vpg_page); memset(kaddr, 0, cl_page_size(obj)); kunmap_atomic(kaddr); - } else if (cp->cpg_defer_uptodate) { - cp->cpg_ra_used = 1; + } else if (vpg->vpg_defer_uptodate) { + vpg->vpg_ra_used = 1; } else { result = ll_page_sync_io(env, io, pg, CRT_READ); } diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 45c549cb4e53..3891b0d694a6 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -474,18 +474,18 @@ static loff_t vvp_pgcache_find(const struct lu_env *env, static void vvp_pgcache_page_show(const struct lu_env *env, struct seq_file *seq, struct cl_page *page) { - struct ccc_page *cpg; + struct vvp_page *vpg; struct page *vmpage; int has_flags; - cpg = cl2ccc_page(cl_page_at(page, &vvp_device_type)); - vmpage = cpg->cpg_page; + vpg = cl2vvp_page(cl_page_at(page, &vvp_device_type)); + vmpage = vpg->vpg_page; seq_printf(seq, " %5i | %p %p %s %s %s %s | %p %lu/%u(%p) %lu %u [", 0 /* gen */, - cpg, page, + vpg, page, "none", - cpg->cpg_write_queued ? "wq" : "- ", - cpg->cpg_defer_uptodate ? "du" : "- ", + vpg->vpg_write_queued ? "wq" : "- ", + vpg->vpg_defer_uptodate ? "du" : "- ", PageWriteback(vmpage) ? "wb" : "-", vmpage, vmpage->mapping->host->i_ino, vmpage->mapping->host->i_generation, diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 76e7b4c30af0..4991ce75e590 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -204,7 +204,7 @@ struct vvp_object { * A list of dirty pages pending IO in the cache. Used by * SOM. Protected by ll_inode_info::lli_lock. * - * \see ccc_page::cpg_pending_linkage + * \see vvp_page::vpg_pending_linkage */ struct list_head vob_pending_list; @@ -235,36 +235,34 @@ struct vvp_object { }; /** - * ccc-private page state. + * VVP-private page state. */ -struct ccc_page { - struct cl_page_slice cpg_cl; - int cpg_defer_uptodate; - int cpg_ra_used; - int cpg_write_queued; +struct vvp_page { + struct cl_page_slice vpg_cl; + int vpg_defer_uptodate; + int vpg_ra_used; + int vpg_write_queued; /** * Non-empty iff this page is already counted in * vvp_object::vob_pending_list. This list is only used as a flag, * that is, never iterated through, only checked for list_empty(), but * having a list is useful for debugging. */ - struct list_head cpg_pending_linkage; + struct list_head vpg_pending_linkage; /** VM page */ - struct page *cpg_page; + struct page *vpg_page; }; -static inline struct ccc_page *cl2ccc_page(const struct cl_page_slice *slice) +static inline struct vvp_page *cl2vvp_page(const struct cl_page_slice *slice) { - return container_of(slice, struct ccc_page, cpg_cl); + return container_of(slice, struct vvp_page, vpg_cl); } -static inline pgoff_t ccc_index(struct ccc_page *ccc) +static inline pgoff_t vvp_index(struct vvp_page *vvp) { - return ccc->cpg_cl.cpl_index; + return vvp->vpg_cl.cpl_index; } -struct cl_page *ccc_vmpage_page_transient(struct page *vmpage); - struct vvp_device { struct cl_device vdv_cl; struct super_block *vdv_sb; @@ -296,10 +294,6 @@ void ccc_global_fini(struct lu_device_type *device_type); int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io, const struct cl_lock_operations *lkops); -int ccc_fail(const struct lu_env *env, const struct cl_page_slice *slice); -int ccc_transient_page_prep(const struct lu_env *env, - const struct cl_page_slice *slice, - struct cl_io *io); void ccc_lock_delete(const struct lu_env *env, const struct cl_lock_slice *slice); void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); @@ -360,11 +354,15 @@ static inline struct inode *vvp_object_inode(const struct cl_object *obj) int vvp_object_invariant(const struct cl_object *obj); struct vvp_object *cl_inode2vvp(struct inode *inode); +static inline struct page *cl2vm_page(const struct cl_page_slice *slice) +{ + return cl2vvp_page(slice)->vpg_page; +} + struct ccc_lock *cl2ccc_lock(const struct cl_lock_slice *slice); struct ccc_io *cl2ccc_io(const struct lu_env *env, const struct cl_io_slice *slice); struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice); -struct page *cl2vm_page(const struct cl_page_slice *slice); int cl_setattr_ost(struct inode *inode, const struct iattr *attr); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 1773cb24f7b3..eb6ce1c68fd0 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -645,15 +645,15 @@ static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, static void write_commit_callback(const struct lu_env *env, struct cl_io *io, struct cl_page *page) { - struct ccc_page *cp; + struct vvp_page *vpg; struct page *vmpage = page->cp_vmpage; struct cl_object *clob = cl_io_top(io)->ci_obj; SetPageUptodate(vmpage); set_page_dirty(vmpage); - cp = cl2ccc_page(cl_object_page_slice(clob, page)); - vvp_write_pending(cl2vvp(clob), cp); + vpg = cl2vvp_page(cl_object_page_slice(clob, page)); + vvp_write_pending(cl2vvp(clob), vpg); cl_page_disown(env, io, page); @@ -670,15 +670,15 @@ static bool page_list_sanity_check(struct cl_object *obj, pgoff_t index = CL_PAGE_EOF; cl_page_list_for_each(page, plist) { - struct ccc_page *cp = cl_object_page_slice(obj, page); + struct vvp_page *vpg = cl_object_page_slice(obj, page); if (index == CL_PAGE_EOF) { - index = ccc_index(cp); + index = vvp_index(vpg); continue; } ++index; - if (index == ccc_index(cp)) + if (index == vvp_index(vpg)) continue; return false; @@ -868,13 +868,13 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) static void mkwrite_commit_callback(const struct lu_env *env, struct cl_io *io, struct cl_page *page) { - struct ccc_page *cp; + struct vvp_page *vpg; struct cl_object *clob = cl_io_top(io)->ci_obj; set_page_dirty(page->cp_vmpage); - cp = cl2ccc_page(cl_object_page_slice(clob, page)); - vvp_write_pending(cl2vvp(clob), cp); + vpg = cl2vvp_page(cl_object_page_slice(clob, page)); + vvp_write_pending(cl2vvp(clob), vpg); } static int vvp_io_fault_start(const struct lu_env *env, @@ -979,7 +979,7 @@ static int vvp_io_fault_start(const struct lu_env *env, wait_on_page_writeback(vmpage); if (!PageDirty(vmpage)) { struct cl_page_list *plist = &io->ci_queue.c2_qin; - struct ccc_page *cp = cl_object_page_slice(obj, page); + struct vvp_page *vpg = cl_object_page_slice(obj, page); int to = PAGE_SIZE; /* vvp_page_assume() calls wait_on_page_writeback(). */ @@ -989,7 +989,7 @@ static int vvp_io_fault_start(const struct lu_env *env, cl_page_list_add(plist, page); /* size fixup */ - if (last_index == ccc_index(cp)) + if (last_index == vvp_index(vpg)) to = size & ~PAGE_MASK; /* Do not set Dirty bit here so that in case IO is @@ -1058,7 +1058,7 @@ static int vvp_io_read_page(const struct lu_env *env, const struct cl_page_slice *slice) { struct cl_io *io = ios->cis_io; - struct ccc_page *cp = cl2ccc_page(slice); + struct vvp_page *vpg = cl2vvp_page(slice); struct cl_page *page = slice->cpl_page; struct inode *inode = vvp_object_inode(slice->cpl_obj); struct ll_sb_info *sbi = ll_i2sbi(inode); @@ -1068,11 +1068,11 @@ static int vvp_io_read_page(const struct lu_env *env, if (sbi->ll_ra_info.ra_max_pages_per_file && sbi->ll_ra_info.ra_max_pages) - ras_update(sbi, inode, ras, ccc_index(cp), - cp->cpg_defer_uptodate); + ras_update(sbi, inode, ras, vvp_index(vpg), + vpg->vpg_defer_uptodate); - if (cp->cpg_defer_uptodate) { - cp->cpg_ra_used = 1; + if (vpg->vpg_defer_uptodate) { + vpg->vpg_ra_used = 1; cl_page_export(env, page, 1); } /* @@ -1084,7 +1084,7 @@ static int vvp_io_read_page(const struct lu_env *env, if (sbi->ll_ra_info.ra_max_pages_per_file && sbi->ll_ra_info.ra_max_pages) ll_readahead(env, io, &queue->c2_qin, ras, - cp->cpg_defer_uptodate); + vpg->vpg_defer_uptodate); return 0; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 9f5e6a6a8f57..18c9df7ebdda 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -226,7 +226,7 @@ static int vvp_object_init0(const struct lu_env *env, { vob->vob_inode = conf->coc_inode; vob->vob_transient_pages = 0; - cl_object_page_init(&vob->vob_cl, sizeof(struct ccc_page)); + cl_object_page_init(&vob->vob_cl, sizeof(struct vvp_page)); return 0; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 419a535c79c9..5ebbe27104f1 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -41,7 +41,13 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/obd.h" +#include +#include +#include +#include +#include +#include + #include "../include/lustre_lite.h" #include "llite_internal.h" @@ -53,9 +59,9 @@ * */ -static void vvp_page_fini_common(struct ccc_page *cp) +static void vvp_page_fini_common(struct vvp_page *vpg) { - struct page *vmpage = cp->cpg_page; + struct page *vmpage = vpg->vpg_page; LASSERT(vmpage); page_cache_release(vmpage); @@ -64,23 +70,23 @@ static void vvp_page_fini_common(struct ccc_page *cp) static void vvp_page_fini(const struct lu_env *env, struct cl_page_slice *slice) { - struct ccc_page *cp = cl2ccc_page(slice); - struct page *vmpage = cp->cpg_page; + struct vvp_page *vpg = cl2vvp_page(slice); + struct page *vmpage = vpg->vpg_page; /* * vmpage->private was already cleared when page was moved into * VPG_FREEING state. */ LASSERT((struct cl_page *)vmpage->private != slice->cpl_page); - vvp_page_fini_common(cp); + vvp_page_fini_common(vpg); } static int vvp_page_own(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *io, int nonblock) { - struct ccc_page *vpg = cl2ccc_page(slice); - struct page *vmpage = vpg->cpg_page; + struct vvp_page *vpg = cl2vvp_page(slice); + struct page *vmpage = vpg->vpg_page; LASSERT(vmpage); if (nonblock) { @@ -97,6 +103,7 @@ static int vvp_page_own(const struct lu_env *env, lock_page(vmpage); wait_on_page_writeback(vmpage); + return 0; } @@ -137,12 +144,12 @@ static void vvp_page_discard(const struct lu_env *env, struct cl_io *unused) { struct page *vmpage = cl2vm_page(slice); - struct ccc_page *cpg = cl2ccc_page(slice); + struct vvp_page *vpg = cl2vvp_page(slice); LASSERT(vmpage); LASSERT(PageLocked(vmpage)); - if (cpg->cpg_defer_uptodate && !cpg->cpg_ra_used) + if (vpg->vpg_defer_uptodate && !vpg->vpg_ra_used) ll_ra_stats_inc(vmpage->mapping->host, RA_STAT_DISCARDED); ll_invalidate_page(vmpage); @@ -161,7 +168,7 @@ static void vvp_page_delete(const struct lu_env *env, LASSERT((struct cl_page *)vmpage->private == page); LASSERT(inode == vvp_object_inode(obj)); - vvp_write_complete(cl2vvp(obj), cl2ccc_page(slice)); + vvp_write_complete(cl2vvp(obj), cl2vvp_page(slice)); /* Drop the reference count held in vvp_page_init */ refc = atomic_dec_return(&page->cp_ref); @@ -220,7 +227,7 @@ static int vvp_page_prep_write(const struct lu_env *env, if (!pg->cp_sync_io) set_page_writeback(vmpage); - vvp_write_pending(cl2vvp(slice->cpl_obj), cl2ccc_page(slice)); + vvp_write_pending(cl2vvp(slice->cpl_obj), cl2vvp_page(slice)); return 0; } @@ -257,22 +264,23 @@ static void vvp_page_completion_read(const struct lu_env *env, const struct cl_page_slice *slice, int ioret) { - struct ccc_page *cp = cl2ccc_page(slice); - struct page *vmpage = cp->cpg_page; + struct vvp_page *vpg = cl2vvp_page(slice); + struct page *vmpage = vpg->vpg_page; struct cl_page *page = slice->cpl_page; struct inode *inode = vvp_object_inode(page->cp_obj); LASSERT(PageLocked(vmpage)); CL_PAGE_HEADER(D_PAGE, env, page, "completing READ with %d\n", ioret); - if (cp->cpg_defer_uptodate) + if (vpg->vpg_defer_uptodate) ll_ra_count_put(ll_i2sbi(inode), 1); if (ioret == 0) { - if (!cp->cpg_defer_uptodate) + if (!vpg->vpg_defer_uptodate) cl_page_export(env, page, 1); - } else - cp->cpg_defer_uptodate = 0; + } else { + vpg->vpg_defer_uptodate = 0; + } if (!page->cp_sync_io) unlock_page(vmpage); @@ -282,9 +290,9 @@ static void vvp_page_completion_write(const struct lu_env *env, const struct cl_page_slice *slice, int ioret) { - struct ccc_page *cp = cl2ccc_page(slice); + struct vvp_page *vpg = cl2vvp_page(slice); struct cl_page *pg = slice->cpl_page; - struct page *vmpage = cp->cpg_page; + struct page *vmpage = vpg->vpg_page; CL_PAGE_HEADER(D_PAGE, env, pg, "completing WRITE with %d\n", ioret); @@ -298,8 +306,8 @@ static void vvp_page_completion_write(const struct lu_env *env, * and then re-add the page into pending transfer queue. -jay */ - cp->cpg_write_queued = 0; - vvp_write_complete(cl2vvp(slice->cpl_obj), cp); + vpg->vpg_write_queued = 0; + vvp_write_complete(cl2vvp(slice->cpl_obj), vpg); if (pg->cp_sync_io) { LASSERT(PageLocked(vmpage)); @@ -342,7 +350,7 @@ static int vvp_page_make_ready(const struct lu_env *env, LASSERT(pg->cp_state == CPS_CACHED); /* This actually clears the dirty bit in the radix tree. */ set_page_writeback(vmpage); - vvp_write_pending(cl2vvp(slice->cpl_obj), cl2ccc_page(slice)); + vvp_write_pending(cl2vvp(slice->cpl_obj), cl2vvp_page(slice)); CL_PAGE_HEADER(D_PAGE, env, pg, "readied\n"); } else if (pg->cp_state == CPS_PAGEOUT) { /* is it possible for osc_flush_async_page() to already @@ -376,12 +384,12 @@ static int vvp_page_print(const struct lu_env *env, const struct cl_page_slice *slice, void *cookie, lu_printer_t printer) { - struct ccc_page *vp = cl2ccc_page(slice); - struct page *vmpage = vp->cpg_page; + struct vvp_page *vpg = cl2vvp_page(slice); + struct page *vmpage = vpg->vpg_page; (*printer)(env, cookie, LUSTRE_VVP_NAME "-page@%p(%d:%d:%d) vm@%p ", - vp, vp->cpg_defer_uptodate, vp->cpg_ra_used, - vp->cpg_write_queued, vmpage); + vpg, vpg->vpg_defer_uptodate, vpg->vpg_ra_used, + vpg->vpg_write_queued, vmpage); if (vmpage) { (*printer)(env, cookie, "%lx %d:%d %lx %lu %slru", (long)vmpage->flags, page_count(vmpage), @@ -389,7 +397,20 @@ static int vvp_page_print(const struct lu_env *env, page_index(vmpage), list_empty(&vmpage->lru) ? "not-" : ""); } + (*printer)(env, cookie, "\n"); + + return 0; +} + +static int vvp_page_fail(const struct lu_env *env, + const struct cl_page_slice *slice) +{ + /* + * Cached read? + */ + LBUG(); + return 0; } @@ -409,16 +430,24 @@ static const struct cl_page_operations vvp_page_ops = { [CRT_READ] = { .cpo_prep = vvp_page_prep_read, .cpo_completion = vvp_page_completion_read, - .cpo_make_ready = ccc_fail, + .cpo_make_ready = vvp_page_fail, }, [CRT_WRITE] = { .cpo_prep = vvp_page_prep_write, .cpo_completion = vvp_page_completion_write, .cpo_make_ready = vvp_page_make_ready, - } - } + }, + }, }; +static int vvp_transient_page_prep(const struct lu_env *env, + const struct cl_page_slice *slice, + struct cl_io *unused) +{ + /* transient page should always be sent. */ + return 0; +} + static void vvp_transient_page_verify(const struct cl_page *page) { struct inode *inode = vvp_object_inode(page->cp_obj); @@ -492,11 +521,11 @@ vvp_transient_page_completion(const struct lu_env *env, static void vvp_transient_page_fini(const struct lu_env *env, struct cl_page_slice *slice) { - struct ccc_page *cp = cl2ccc_page(slice); + struct vvp_page *vpg = cl2vvp_page(slice); struct cl_page *clp = slice->cpl_page; struct vvp_object *clobj = cl2vvp(clp->cp_obj); - vvp_page_fini_common(cp); + vvp_page_fini_common(vpg); LASSERT(!inode_trylock(clobj->vob_inode)); clobj->vob_transient_pages--; } @@ -513,11 +542,11 @@ static const struct cl_page_operations vvp_transient_page_ops = { .cpo_is_under_lock = vvp_page_is_under_lock, .io = { [CRT_READ] = { - .cpo_prep = ccc_transient_page_prep, + .cpo_prep = vvp_transient_page_prep, .cpo_completion = vvp_transient_page_completion, }, [CRT_WRITE] = { - .cpo_prep = ccc_transient_page_prep, + .cpo_prep = vvp_transient_page_prep, .cpo_completion = vvp_transient_page_completion, } } @@ -526,27 +555,27 @@ static const struct cl_page_operations vvp_transient_page_ops = { int vvp_page_init(const struct lu_env *env, struct cl_object *obj, struct cl_page *page, pgoff_t index) { - struct ccc_page *cpg = cl_object_page_slice(obj, page); + struct vvp_page *vpg = cl_object_page_slice(obj, page); struct page *vmpage = page->cp_vmpage; CLOBINVRNT(env, obj, vvp_object_invariant(obj)); - cpg->cpg_page = vmpage; + vpg->vpg_page = vmpage; page_cache_get(vmpage); - INIT_LIST_HEAD(&cpg->cpg_pending_linkage); + INIT_LIST_HEAD(&vpg->vpg_pending_linkage); if (page->cp_type == CPT_CACHEABLE) { /* in cache, decref in vvp_page_delete */ atomic_inc(&page->cp_ref); SetPagePrivate(vmpage); vmpage->private = (unsigned long)page; - cl_page_slice_add(page, &cpg->cpg_cl, obj, index, + cl_page_slice_add(page, &vpg->vpg_cl, obj, index, &vvp_page_ops); } else { struct vvp_object *clobj = cl2vvp(obj); LASSERT(!inode_trylock(clobj->vob_inode)); - cl_page_slice_add(page, &cpg->cpg_cl, obj, index, + cl_page_slice_add(page, &vpg->vpg_cl, obj, index, &vvp_transient_page_ops); clobj->vob_transient_pages++; } -- GitLab From 4a4eee07f3f579e9ebc5b5db35214c3ada5c1378 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:49 -0400 Subject: [PATCH 0878/9938] staging/lustre/llite: rename ccc_lock to vvp_lock Rename struct ccc_lock to struct vvp_lock and merge the CCC lock methods into the VVP lock methods. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13088 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: James Simmons Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 6 +-- .../staging/lustre/lustre/llite/lcommon_cl.c | 52 ------------------- drivers/staging/lustre/lustre/llite/vvp_dev.c | 6 +++ .../lustre/lustre/llite/vvp_internal.h | 20 +++---- .../staging/lustre/lustre/llite/vvp_lock.c | 38 ++++++++++++-- 5 files changed, 50 insertions(+), 72 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 3488349d8087..d509f9407abc 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1227,7 +1227,7 @@ struct cl_lock { /** * Per-layer part of cl_lock * - * \see ccc_lock, lov_lock, lovsub_lock, osc_lock + * \see vvp_lock, lov_lock, lovsub_lock, osc_lock */ struct cl_lock_slice { struct cl_lock *cls_lock; @@ -1254,7 +1254,7 @@ struct cl_lock_operations { * @anchor for resources * \retval -ve failure * - * \see ccc_lock_enqueue(), lov_lock_enqueue(), lovsub_lock_enqueue(), + * \see vvp_lock_enqueue(), lov_lock_enqueue(), lovsub_lock_enqueue(), * \see osc_lock_enqueue() */ int (*clo_enqueue)(const struct lu_env *env, @@ -1270,7 +1270,7 @@ struct cl_lock_operations { /** * Destructor. Frees resources and the slice. * - * \see ccc_lock_fini(), lov_lock_fini(), lovsub_lock_fini(), + * \see vvp_lock_fini(), lov_lock_fini(), lovsub_lock_fini(), * \see osc_lock_fini() */ void (*clo_fini)(const struct lu_env *env, struct cl_lock_slice *slice); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 07620326081d..88843170b3e6 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -67,17 +67,11 @@ static const struct cl_req_operations ccc_req_ops; * ccc_ prefix stands for "Common Client Code". */ -static struct kmem_cache *ccc_lock_kmem; static struct kmem_cache *ccc_thread_kmem; static struct kmem_cache *ccc_session_kmem; static struct kmem_cache *ccc_req_kmem; static struct lu_kmem_descr ccc_caches[] = { - { - .ckd_cache = &ccc_lock_kmem, - .ckd_name = "ccc_lock_kmem", - .ckd_size = sizeof(struct ccc_lock) - }, { .ckd_cache = &ccc_thread_kmem, .ckd_name = "ccc_thread_kmem", @@ -221,26 +215,6 @@ void ccc_global_fini(struct lu_device_type *device_type) lu_kmem_fini(ccc_caches); } -int ccc_lock_init(const struct lu_env *env, - struct cl_object *obj, struct cl_lock *lock, - const struct cl_io *unused, - const struct cl_lock_operations *lkops) -{ - struct ccc_lock *clk; - int result; - - CLOBINVRNT(env, obj, vvp_object_invariant(obj)); - - clk = kmem_cache_zalloc(ccc_lock_kmem, GFP_NOFS); - if (clk) { - cl_lock_slice_add(lock, &clk->clk_cl, obj, lkops); - result = 0; - } else { - result = -ENOMEM; - } - return result; -} - static void vvp_object_size_lock(struct cl_object *obj) { struct inode *inode = vvp_object_inode(obj); @@ -257,27 +231,6 @@ static void vvp_object_size_unlock(struct cl_object *obj) ll_inode_size_unlock(inode); } -/***************************************************************************** - * - * Lock operations. - * - */ - -void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice) -{ - struct ccc_lock *clk = cl2ccc_lock(slice); - - kmem_cache_free(ccc_lock_kmem, clk); -} - -int ccc_lock_enqueue(const struct lu_env *env, - const struct cl_lock_slice *slice, - struct cl_io *unused, struct cl_sync_io *anchor) -{ - CLOBINVRNT(env, slice->cls_obj, vvp_object_invariant(slice->cls_obj)); - return 0; -} - /***************************************************************************** * * io operations. @@ -571,11 +524,6 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) * */ -struct ccc_lock *cl2ccc_lock(const struct cl_lock_slice *slice) -{ - return container_of(slice, struct ccc_lock, clk_cl); -} - struct ccc_io *cl2ccc_io(const struct lu_env *env, const struct cl_io_slice *slice) { diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 3891b0d694a6..4b77db34f516 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -57,10 +57,16 @@ * "llite_" (var. "ll_") prefix. */ +struct kmem_cache *vvp_lock_kmem; struct kmem_cache *vvp_object_kmem; static struct kmem_cache *vvp_thread_kmem; static struct kmem_cache *vvp_session_kmem; static struct lu_kmem_descr vvp_caches[] = { + { + .ckd_cache = &vvp_lock_kmem, + .ckd_name = "vvp_lock_kmem", + .ckd_size = sizeof(struct vvp_lock), + }, { .ckd_cache = &vvp_object_kmem, .ckd_name = "vvp_object_kmem", diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 4991ce75e590..403d2a7ba0af 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -128,6 +128,7 @@ int cl_is_normalio(const struct lu_env *env, const struct cl_io *io); extern struct lu_context_key ccc_key; extern struct lu_context_key ccc_session_key; +extern struct kmem_cache *vvp_lock_kmem; extern struct kmem_cache *vvp_object_kmem; struct ccc_thread_info { @@ -269,8 +270,8 @@ struct vvp_device { struct cl_device *vdv_next; }; -struct ccc_lock { - struct cl_lock_slice clk_cl; +struct vvp_lock { + struct cl_lock_slice vlk_cl; }; struct ccc_req { @@ -291,15 +292,6 @@ int ccc_req_init(const struct lu_env *env, struct cl_device *dev, void ccc_umount(const struct lu_env *env, struct cl_device *dev); int ccc_global_init(struct lu_device_type *device_type); void ccc_global_fini(struct lu_device_type *device_type); -int ccc_lock_init(const struct lu_env *env, struct cl_object *obj, - struct cl_lock *lock, const struct cl_io *io, - const struct cl_lock_operations *lkops); -void ccc_lock_delete(const struct lu_env *env, - const struct cl_lock_slice *slice); -void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); -int ccc_lock_enqueue(const struct lu_env *env, - const struct cl_lock_slice *slice, - struct cl_io *io, struct cl_sync_io *anchor); int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, __u32 enqflags, enum cl_lock_mode mode, @@ -359,7 +351,11 @@ static inline struct page *cl2vm_page(const struct cl_page_slice *slice) return cl2vvp_page(slice)->vpg_page; } -struct ccc_lock *cl2ccc_lock(const struct cl_lock_slice *slice); +static inline struct vvp_lock *cl2vvp_lock(const struct cl_lock_slice *slice) +{ + return container_of(slice, struct vvp_lock, vlk_cl); +} + struct ccc_io *cl2ccc_io(const struct lu_env *env, const struct cl_io_slice *slice); struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice); diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index 8c505a6052b2..f5bd6c22e112 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -40,7 +40,7 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/obd.h" +#include "../include/obd_support.h" #include "../include/lustre_lite.h" #include "vvp_internal.h" @@ -51,13 +51,41 @@ * */ +static void vvp_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice) +{ + struct vvp_lock *vlk = cl2vvp_lock(slice); + + kmem_cache_free(vvp_lock_kmem, vlk); +} + +static int vvp_lock_enqueue(const struct lu_env *env, + const struct cl_lock_slice *slice, + struct cl_io *unused, struct cl_sync_io *anchor) +{ + CLOBINVRNT(env, slice->cls_obj, vvp_object_invariant(slice->cls_obj)); + + return 0; +} + static const struct cl_lock_operations vvp_lock_ops = { - .clo_fini = ccc_lock_fini, - .clo_enqueue = ccc_lock_enqueue + .clo_fini = vvp_lock_fini, + .clo_enqueue = vvp_lock_enqueue, }; int vvp_lock_init(const struct lu_env *env, struct cl_object *obj, - struct cl_lock *lock, const struct cl_io *io) + struct cl_lock *lock, const struct cl_io *unused) { - return ccc_lock_init(env, obj, lock, io, &vvp_lock_ops); + struct vvp_lock *vlk; + int result; + + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); + + vlk = kmem_cache_zalloc(vvp_lock_kmem, GFP_NOFS); + if (vlk) { + cl_lock_slice_add(lock, &vlk->vlk_cl, obj, &vvp_lock_ops); + result = 0; + } else { + result = -ENOMEM; + } + return result; } -- GitLab From bc4320a9186ccace8887eac930b574491ae886c0 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:50 -0400 Subject: [PATCH 0879/9938] staging/lustre:llite: remove struct ll_ra_read Ever since removal of the the unused function ll_ra_read_get(), the struct ll_ra_read members lrr_reader and lrr_linkage and the struct ll_readahead_state member ras_read_beads unnecessary so remove them. In struct vvp_io replace the struct ll_ra_read cui_bead member with cui_ra_start and cui_ra_count. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13347 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/llite/llite_internal.h | 30 +++-------- drivers/staging/lustre/lustre/llite/rw.c | 53 +++++-------------- drivers/staging/lustre/lustre/llite/vvp_io.c | 31 +++-------- 3 files changed, 28 insertions(+), 86 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 78b3eddcc715..9dd4325e8e00 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -528,13 +528,6 @@ struct ll_sb_info { struct completion ll_kobj_unregister; }; -struct ll_ra_read { - pgoff_t lrr_start; - pgoff_t lrr_count; - struct task_struct *lrr_reader; - struct list_head lrr_linkage; -}; - /* * per file-descriptor read-ahead data. */ @@ -592,12 +585,6 @@ struct ll_readahead_state { * will not be accurate when dealing with reads issued via mmap. */ unsigned long ras_request_index; - /* - * list of struct ll_ra_read's one per read(2) call current in - * progress against this file descriptor. Used by read-ahead code, - * protected by ->ras_lock. - */ - struct list_head ras_read_beads; /* * The following 3 items are used for detecting the stride I/O * mode. @@ -666,8 +653,7 @@ static inline int ll_need_32bit_api(struct ll_sb_info *sbi) #endif } -void ll_ra_read_in(struct file *f, struct ll_ra_read *rar); -void ll_ra_read_ex(struct file *f, struct ll_ra_read *rar); +void ll_ras_enter(struct file *f); /* llite/lproc_llite.c */ int ldebugfs_register_mountpoint(struct dentry *parent, @@ -876,14 +862,12 @@ struct vvp_io { } fault; } fault; } u; - /** - * Read-ahead state used by read and page-fault IO contexts. - */ - struct ll_ra_read cui_bead; - /** - * Set when cui_bead has been initialized. - */ - int cui_ra_window_set; + + /* Readahead state. */ + pgoff_t cui_ra_start; + pgoff_t cui_ra_count; + /* Set when cui_ra_{start,count} have been initialized. */ + bool cui_ra_valid; }; /** diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 2c4d4c40b407..f06d8be2c9ea 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -258,38 +258,15 @@ static int index_in_window(unsigned long index, unsigned long point, return start <= index && index <= end; } -static struct ll_readahead_state *ll_ras_get(struct file *f) +void ll_ras_enter(struct file *f) { - struct ll_file_data *fd; - - fd = LUSTRE_FPRIVATE(f); - return &fd->fd_ras; -} - -void ll_ra_read_in(struct file *f, struct ll_ra_read *rar) -{ - struct ll_readahead_state *ras; - - ras = ll_ras_get(f); + struct ll_file_data *fd = LUSTRE_FPRIVATE(f); + struct ll_readahead_state *ras = &fd->fd_ras; spin_lock(&ras->ras_lock); ras->ras_requests++; ras->ras_request_index = 0; ras->ras_consecutive_requests++; - rar->lrr_reader = current; - - list_add(&rar->lrr_linkage, &ras->ras_read_beads); - spin_unlock(&ras->ras_lock); -} - -void ll_ra_read_ex(struct file *f, struct ll_ra_read *rar) -{ - struct ll_readahead_state *ras; - - ras = ll_ras_get(f); - - spin_lock(&ras->ras_lock); - list_del_init(&rar->lrr_linkage); spin_unlock(&ras->ras_lock); } @@ -551,7 +528,6 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, unsigned long start = 0, end = 0, reserved; unsigned long ra_end, len, mlen = 0; struct inode *inode; - struct ll_ra_read *bead; struct ra_io_arg *ria = &vti->vti_ria; struct cl_object *clob; int ret = 0; @@ -575,17 +551,15 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, } spin_lock(&ras->ras_lock); - if (vio->cui_ra_window_set) - bead = &vio->cui_bead; - else - bead = NULL; /* Enlarge the RA window to encompass the full read */ - if (bead && ras->ras_window_start + ras->ras_window_len < - bead->lrr_start + bead->lrr_count) { - ras->ras_window_len = bead->lrr_start + bead->lrr_count - + if (vio->cui_ra_valid && + ras->ras_window_start + ras->ras_window_len < + vio->cui_ra_start + vio->cui_ra_count) { + ras->ras_window_len = vio->cui_ra_start + vio->cui_ra_count - ras->ras_window_start; } + /* Reserve a part of the read-ahead window that we'll be issuing */ if (ras->ras_window_len) { start = ras->ras_next_readahead; @@ -641,15 +615,15 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, CDEBUG(D_READA, DFID ": ria: %lu/%lu, bead: %lu/%lu, hit: %d\n", PFID(lu_object_fid(&clob->co_lu)), ria->ria_start, ria->ria_end, - !bead ? 0 : bead->lrr_start, - !bead ? 0 : bead->lrr_count, + vio->cui_ra_valid ? vio->cui_ra_start : 0, + vio->cui_ra_valid ? vio->cui_ra_count : 0, hit); /* at least to extend the readahead window to cover current read */ - if (!hit && bead && - bead->lrr_start + bead->lrr_count > ria->ria_start) { + if (!hit && vio->cui_ra_valid && + vio->cui_ra_start + vio->cui_ra_count > ria->ria_start) { /* to the end of current read window. */ - mlen = bead->lrr_start + bead->lrr_count - ria->ria_start; + mlen = vio->cui_ra_start + vio->cui_ra_count - ria->ria_start; /* trim to RPC boundary */ start = ria->ria_start & (PTLRPC_MAX_BRW_PAGES - 1); mlen = min(mlen, PTLRPC_MAX_BRW_PAGES - start); @@ -730,7 +704,6 @@ void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras) spin_lock_init(&ras->ras_lock); ras_reset(inode, ras, 0); ras->ras_requests = 0; - INIT_LIST_HEAD(&ras->ras_read_beads); } /* diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index eb6ce1c68fd0..86e73d512a91 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -500,7 +500,6 @@ static int vvp_io_read_start(const struct lu_env *env, struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; struct inode *inode = vvp_object_inode(obj); - struct ll_ra_read *bead = &vio->cui_bead; struct file *file = cio->cui_fd->fd_file; int result; @@ -530,14 +529,11 @@ static int vvp_io_read_start(const struct lu_env *env, cio->cui_fd->fd_file->f_ra.ra_pages = 0; /* initialize read-ahead window once per syscall */ - if (!vio->cui_ra_window_set) { - vio->cui_ra_window_set = 1; - bead->lrr_start = cl_index(obj, pos); - /* - * XXX: explicit PAGE_CACHE_SIZE - */ - bead->lrr_count = cl_index(obj, tot + PAGE_CACHE_SIZE - 1); - ll_ra_read_in(file, bead); + if (!vio->cui_ra_valid) { + vio->cui_ra_valid = true; + vio->cui_ra_start = cl_index(obj, pos); + vio->cui_ra_count = cl_index(obj, tot + PAGE_CACHE_SIZE - 1); + ll_ras_enter(file); } /* BUG: 5972 */ @@ -574,17 +570,6 @@ static int vvp_io_read_start(const struct lu_env *env, return result; } -static void vvp_io_read_fini(const struct lu_env *env, const struct cl_io_slice *ios) -{ - struct vvp_io *vio = cl2vvp_io(env, ios); - struct ccc_io *cio = cl2ccc_io(env, ios); - - if (vio->cui_ra_window_set) - ll_ra_read_ex(cio->cui_fd->fd_file, &vio->cui_bead); - - vvp_io_fini(env, ios); -} - static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io, struct cl_page_list *plist, int from, int to) { @@ -1092,10 +1077,10 @@ static int vvp_io_read_page(const struct lu_env *env, static const struct cl_io_operations vvp_io_ops = { .op = { [CIT_READ] = { - .cio_fini = vvp_io_read_fini, + .cio_fini = vvp_io_fini, .cio_lock = vvp_io_read_lock, .cio_start = vvp_io_read_start, - .cio_advance = ccc_io_advance + .cio_advance = ccc_io_advance, }, [CIT_WRITE] = { .cio_fini = vvp_io_fini, @@ -1148,7 +1133,7 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, CL_IO_SLICE_CLEAN(cio, cui_cl); cl_io_slice_add(io, &cio->cui_cl, obj, &vvp_io_ops); - vio->cui_ra_window_set = 0; + vio->cui_ra_valid = false; result = 0; if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE) { size_t count; -- GitLab From 10cdef73396c816e9844e467558c2f87776fc11f Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:51 -0400 Subject: [PATCH 0880/9938] staging/lustre/llite: merge ccc_io and vvp_io Move the contents of struct vvp_io into struct ccc_io, delete the former, and rename the latter to struct vvp_io. Rename various ccc_io related functions to use vvp rather than ccc. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13351 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Lai Siyao Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 2 +- drivers/staging/lustre/lustre/llite/file.c | 13 ++- .../staging/lustre/lustre/llite/lcommon_cl.c | 60 +++-------- .../lustre/lustre/llite/llite_internal.h | 72 ------------- .../staging/lustre/lustre/llite/llite_mmap.c | 12 +-- drivers/staging/lustre/lustre/llite/rw.c | 4 +- drivers/staging/lustre/lustre/llite/rw26.c | 10 +- drivers/staging/lustre/lustre/llite/vvp_dev.c | 2 +- .../lustre/lustre/llite/vvp_internal.h | 81 ++++++++++---- drivers/staging/lustre/lustre/llite/vvp_io.c | 101 ++++++++---------- .../staging/lustre/lustre/llite/vvp_page.c | 2 +- 11 files changed, 144 insertions(+), 215 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index d509f9407abc..104dc9f15efb 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1461,7 +1461,7 @@ enum cl_io_state { * This is usually embedded into layer session data, rather than allocated * dynamically. * - * \see vvp_io, lov_io, osc_io, ccc_io + * \see vvp_io, lov_io, osc_io */ struct cl_io_slice { struct cl_io *cis_io; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index bf2a5ee1e687..27e7e65b3a98 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1135,14 +1135,13 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, ll_io_init(io, file, iot == CIT_WRITE); if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { - struct vvp_io *vio = vvp_env_io(env); - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); int write_mutex_locked = 0; cio->cui_fd = LUSTRE_FPRIVATE(file); - vio->cui_io_subtype = args->via_io_subtype; + cio->cui_io_subtype = args->via_io_subtype; - switch (vio->cui_io_subtype) { + switch (cio->cui_io_subtype) { case IO_NORMAL: cio->cui_iter = args->u.normal.via_iter; cio->cui_iocb = args->u.normal.via_iocb; @@ -1158,11 +1157,11 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, down_read(&lli->lli_trunc_sem); break; case IO_SPLICE: - vio->u.splice.cui_pipe = args->u.splice.via_pipe; - vio->u.splice.cui_flags = args->u.splice.via_flags; + cio->u.splice.cui_pipe = args->u.splice.via_pipe; + cio->u.splice.cui_flags = args->u.splice.via_flags; break; default: - CERROR("Unknown IO type - %u\n", vio->cui_io_subtype); + CERROR("Unknown IO type - %u\n", cio->cui_io_subtype); LBUG(); } result = cl_io_loop(env, io); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 88843170b3e6..9a9d7061fff0 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -68,7 +68,6 @@ static const struct cl_req_operations ccc_req_ops; */ static struct kmem_cache *ccc_thread_kmem; -static struct kmem_cache *ccc_session_kmem; static struct kmem_cache *ccc_req_kmem; static struct lu_kmem_descr ccc_caches[] = { @@ -77,11 +76,6 @@ static struct lu_kmem_descr ccc_caches[] = { .ckd_name = "ccc_thread_kmem", .ckd_size = sizeof(struct ccc_thread_info), }, - { - .ckd_cache = &ccc_session_kmem, - .ckd_name = "ccc_session_kmem", - .ckd_size = sizeof(struct ccc_session) - }, { .ckd_cache = &ccc_req_kmem, .ckd_name = "ccc_req_kmem", @@ -116,37 +110,12 @@ void ccc_key_fini(const struct lu_context *ctx, kmem_cache_free(ccc_thread_kmem, info); } -void *ccc_session_key_init(const struct lu_context *ctx, - struct lu_context_key *key) -{ - struct ccc_session *session; - - session = kmem_cache_zalloc(ccc_session_kmem, GFP_NOFS); - if (!session) - session = ERR_PTR(-ENOMEM); - return session; -} - -void ccc_session_key_fini(const struct lu_context *ctx, - struct lu_context_key *key, void *data) -{ - struct ccc_session *session = data; - - kmem_cache_free(ccc_session_kmem, session); -} - struct lu_context_key ccc_key = { .lct_tags = LCT_CL_THREAD, .lct_init = ccc_key_init, .lct_fini = ccc_key_fini }; -struct lu_context_key ccc_session_key = { - .lct_tags = LCT_SESSION, - .lct_init = ccc_session_key_init, - .lct_fini = ccc_session_key_fini -}; - int ccc_req_init(const struct lu_env *env, struct cl_device *dev, struct cl_req *req) { @@ -237,11 +206,11 @@ static void vvp_object_size_unlock(struct cl_object *obj) * */ -int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, +int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, __u32 enqflags, enum cl_lock_mode mode, pgoff_t start, pgoff_t end) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); struct cl_lock_descr *descr = &cio->cui_link.cill_descr; struct cl_object *obj = io->ci_obj; @@ -266,8 +235,8 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, return 0; } -void ccc_io_update_iov(const struct lu_env *env, - struct ccc_io *cio, struct cl_io *io) +void vvp_io_update_iov(const struct lu_env *env, + struct vvp_io *cio, struct cl_io *io) { size_t size = io->u.ci_rw.crw_count; @@ -277,27 +246,27 @@ void ccc_io_update_iov(const struct lu_env *env, iov_iter_truncate(cio->cui_iter, size); } -int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io, +int vvp_io_one_lock(const struct lu_env *env, struct cl_io *io, __u32 enqflags, enum cl_lock_mode mode, loff_t start, loff_t end) { struct cl_object *obj = io->ci_obj; - return ccc_io_one_lock_index(env, io, enqflags, mode, + return vvp_io_one_lock_index(env, io, enqflags, mode, cl_index(obj, start), cl_index(obj, end)); } -void ccc_io_end(const struct lu_env *env, const struct cl_io_slice *ios) +void vvp_io_end(const struct lu_env *env, const struct cl_io_slice *ios) { CLOBINVRNT(env, ios->cis_io->ci_obj, vvp_object_invariant(ios->cis_io->ci_obj)); } -void ccc_io_advance(const struct lu_env *env, +void vvp_io_advance(const struct lu_env *env, const struct cl_io_slice *ios, size_t nob) { - struct ccc_io *cio = cl2ccc_io(env, ios); + struct vvp_io *cio = cl2vvp_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = ios->cis_io->ci_obj; @@ -492,7 +461,7 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) again: if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); if (attr->ia_valid & ATTR_FILE) /* populate the file descriptor for ftruncate to honor @@ -524,13 +493,14 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) * */ -struct ccc_io *cl2ccc_io(const struct lu_env *env, +struct vvp_io *cl2vvp_io(const struct lu_env *env, const struct cl_io_slice *slice) { - struct ccc_io *cio; + struct vvp_io *cio; + + cio = container_of(slice, struct vvp_io, cui_cl); + LASSERT(cio == vvp_env_io(env)); - cio = container_of(slice, struct ccc_io, cui_cl); - LASSERT(cio == ccc_env_io(env)); return cio; } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 9dd4325e8e00..9856bb6daf15 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -817,59 +817,6 @@ struct ll_close_queue { void vvp_write_pending(struct vvp_object *club, struct vvp_page *page); void vvp_write_complete(struct vvp_object *club, struct vvp_page *page); -/* specific architecture can implement only part of this list */ -enum vvp_io_subtype { - /** normal IO */ - IO_NORMAL, - /** io started from splice_{read|write} */ - IO_SPLICE -}; - -/* IO subtypes */ -struct vvp_io { - /** io subtype */ - enum vvp_io_subtype cui_io_subtype; - - union { - struct { - struct pipe_inode_info *cui_pipe; - unsigned int cui_flags; - } splice; - struct vvp_fault_io { - /** - * Inode modification time that is checked across DLM - * lock request. - */ - time64_t ft_mtime; - struct vm_area_struct *ft_vma; - /** - * locked page returned from vvp_io - */ - struct page *ft_vmpage; - struct vm_fault_api { - /** - * kernel fault info - */ - struct vm_fault *ft_vmf; - /** - * fault API used bitflags for return code. - */ - unsigned int ft_flags; - /** - * check that flags are from filemap_fault - */ - bool ft_flags_valid; - } fault; - } fault; - } u; - - /* Readahead state. */ - pgoff_t cui_ra_start; - pgoff_t cui_ra_count; - /* Set when cui_ra_{start,count} have been initialized. */ - bool cui_ra_valid; -}; - /** * IO arguments for various VFS I/O interfaces. */ @@ -923,25 +870,6 @@ static inline struct vvp_io_args *vvp_env_args(const struct lu_env *env, return ret; } -struct vvp_session { - struct vvp_io vs_ios; -}; - -static inline struct vvp_session *vvp_env_session(const struct lu_env *env) -{ - extern struct lu_context_key vvp_session_key; - struct vvp_session *ses; - - ses = lu_context_key_get(env->le_ses, &vvp_session_key); - LASSERT(ses); - return ses; -} - -static inline struct vvp_io *vvp_env_io(const struct lu_env *env) -{ - return &vvp_env_session(env)->vs_ios; -} - int vvp_global_init(void); void vvp_global_fini(void); diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 1263da85dd7f..7c214f8a1e71 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -146,7 +146,7 @@ ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret, rc = cl_io_init(env, io, CIT_FAULT, io->ci_obj); if (rc == 0) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); LASSERT(cio->cui_cl.cis_io == io); @@ -307,17 +307,17 @@ static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf) vio = vvp_env_io(env); vio->u.fault.ft_vma = vma; vio->u.fault.ft_vmpage = NULL; - vio->u.fault.fault.ft_vmf = vmf; - vio->u.fault.fault.ft_flags = 0; - vio->u.fault.fault.ft_flags_valid = false; + vio->u.fault.ft_vmf = vmf; + vio->u.fault.ft_flags = 0; + vio->u.fault.ft_flags_valid = false; result = cl_io_loop(env, io); /* ft_flags are only valid if we reached * the call to filemap_fault */ - if (vio->u.fault.fault.ft_flags_valid) - fault_ret = vio->u.fault.fault.ft_flags; + if (vio->u.fault.ft_flags_valid) + fault_ret = vio->u.fault.ft_flags; vmpage = vio->u.fault.ft_vmpage; if (result != 0 && vmpage) { diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index f06d8be2c9ea..da4410712f83 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -90,7 +90,7 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) struct lu_env *env; struct cl_io *io; struct cl_object *clob; - struct ccc_io *cio; + struct vvp_io *cio; int refcheck; int result = 0; @@ -108,7 +108,7 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) lcc->lcc_refcheck = refcheck; lcc->lcc_cookie = current; - cio = ccc_env_io(env); + cio = vvp_env_io(env); io = cio->cui_cl.cis_io; lcc->lcc_io = io; if (!io) { diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index bb85629dd105..2f69634376f9 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -376,7 +376,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, env = cl_env_get(&refcheck); LASSERT(!IS_ERR(env)); - io = ccc_env_io(env)->cui_cl.cis_io; + io = vvp_env_io(env)->cui_cl.cis_io; LASSERT(io); /* 0. Need locking between buffered and direct access. and race with @@ -439,7 +439,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, inode_unlock(inode); if (tot_bytes > 0) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); /* no commit async for direct IO */ cio->u.write.cui_written += tot_bytes; @@ -513,7 +513,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, /* To avoid deadlock, try to lock page first. */ vmpage = grab_cache_page_nowait(mapping, index); if (unlikely(!vmpage || PageDirty(vmpage) || PageWriteback(vmpage))) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); struct cl_page_list *plist = &cio->u.write.cui_queue; /* if the page is already in dirty cache, we have to commit @@ -595,7 +595,7 @@ static int ll_write_end(struct file *file, struct address_space *mapping, struct ll_cl_context *lcc = fsdata; struct lu_env *env; struct cl_io *io; - struct ccc_io *cio; + struct vvp_io *cio; struct cl_page *page; unsigned from = pos & (PAGE_CACHE_SIZE - 1); bool unplug = false; @@ -606,7 +606,7 @@ static int ll_write_end(struct file *file, struct address_space *mapping, env = lcc->lcc_env; page = lcc->lcc_page; io = lcc->lcc_io; - cio = ccc_env_io(env); + cio = vvp_env_io(env); LASSERT(cl_page_is_owned(page, io)); if (copied > 0) { diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 4b77db34f516..030a2460cf24 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -138,7 +138,7 @@ struct lu_context_key vvp_session_key = { }; /* type constructor/destructor: vvp_type_{init,fini,start,stop}(). */ -LU_TYPE_INIT_FINI(vvp, &ccc_key, &ccc_session_key, &vvp_key, &vvp_session_key); +LU_TYPE_INIT_FINI(vvp, &ccc_key, &vvp_key, &vvp_session_key); static const struct lu_device_operations vvp_lu_ops = { .ldo_object_alloc = vvp_object_alloc diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 403d2a7ba0af..443485c8c3ee 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -81,10 +81,18 @@ enum ccc_setattr_lock_type { SETATTR_MATCH_LOCK }; +/* specific architecture can implement only part of this list */ +enum vvp_io_subtype { + /** normal IO */ + IO_NORMAL, + /** io started from splice_{read|write} */ + IO_SPLICE +}; + /** - * IO state private to vvp or slp layers. + * IO state private to IO state private to VVP layer. */ -struct ccc_io { +struct vvp_io { /** super class */ struct cl_io_slice cui_cl; struct cl_io_lock_link cui_link; @@ -98,9 +106,37 @@ struct ccc_io { size_t cui_tot_count; union { + struct vvp_fault_io { + /** + * Inode modification time that is checked across DLM + * lock request. + */ + time64_t ft_mtime; + struct vm_area_struct *ft_vma; + /** + * locked page returned from vvp_io + */ + struct page *ft_vmpage; + /** + * kernel fault info + */ + struct vm_fault *ft_vmf; + /** + * fault API used bitflags for return code. + */ + unsigned int ft_flags; + /** + * check that flags are from filemap_fault + */ + bool ft_flags_valid; + } fault; struct { enum ccc_setattr_lock_type cui_local_lock; } setattr; + struct { + struct pipe_inode_info *cui_pipe; + unsigned int cui_flags; + } splice; struct { struct cl_page_list cui_queue; unsigned long cui_written; @@ -108,6 +144,9 @@ struct ccc_io { int cui_to; } write; } u; + + enum vvp_io_subtype cui_io_subtype; + /** * Layout version when this IO is initialized */ @@ -117,6 +156,12 @@ struct ccc_io { */ struct ll_file_data *cui_fd; struct kiocb *cui_iocb; + + /* Readahead state. */ + pgoff_t cui_ra_start; + pgoff_t cui_ra_count; + /* Set when cui_ra_{start,count} have been initialized. */ + bool cui_ra_valid; }; /** @@ -126,7 +171,7 @@ struct ccc_io { int cl_is_normalio(const struct lu_env *env, const struct cl_io *io); extern struct lu_context_key ccc_key; -extern struct lu_context_key ccc_session_key; +extern struct lu_context_key vvp_session_key; extern struct kmem_cache *vvp_lock_kmem; extern struct kmem_cache *vvp_object_kmem; @@ -174,23 +219,23 @@ static inline struct cl_io *ccc_env_thread_io(const struct lu_env *env) return io; } -struct ccc_session { - struct ccc_io cs_ios; +struct vvp_session { + struct vvp_io cs_ios; }; -static inline struct ccc_session *ccc_env_session(const struct lu_env *env) +static inline struct vvp_session *vvp_env_session(const struct lu_env *env) { - struct ccc_session *ses; + struct vvp_session *ses; - ses = lu_context_key_get(env->le_ses, &ccc_session_key); + ses = lu_context_key_get(env->le_ses, &vvp_session_key); LASSERT(ses); return ses; } -static inline struct ccc_io *ccc_env_io(const struct lu_env *env) +static inline struct vvp_io *vvp_env_io(const struct lu_env *env) { - return &ccc_env_session(env)->cs_ios; + return &vvp_env_session(env)->cs_ios; } /** @@ -282,10 +327,6 @@ void *ccc_key_init(const struct lu_context *ctx, struct lu_context_key *key); void ccc_key_fini(const struct lu_context *ctx, struct lu_context_key *key, void *data); -void *ccc_session_key_init(const struct lu_context *ctx, - struct lu_context_key *key); -void ccc_session_key_fini(const struct lu_context *ctx, - struct lu_context_key *key, void *data); int ccc_req_init(const struct lu_env *env, struct cl_device *dev, struct cl_req *req); @@ -293,16 +334,16 @@ void ccc_umount(const struct lu_env *env, struct cl_device *dev); int ccc_global_init(struct lu_device_type *device_type); void ccc_global_fini(struct lu_device_type *device_type); -int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, +int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, __u32 enqflags, enum cl_lock_mode mode, pgoff_t start, pgoff_t end); -int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io, +int vvp_io_one_lock(const struct lu_env *env, struct cl_io *io, __u32 enqflags, enum cl_lock_mode mode, loff_t start, loff_t end); -void ccc_io_end(const struct lu_env *env, const struct cl_io_slice *ios); -void ccc_io_advance(const struct lu_env *env, const struct cl_io_slice *ios, +void vvp_io_end(const struct lu_env *env, const struct cl_io_slice *ios); +void vvp_io_advance(const struct lu_env *env, const struct cl_io_slice *ios, size_t nob); -void ccc_io_update_iov(const struct lu_env *env, struct ccc_io *cio, +void vvp_io_update_iov(const struct lu_env *env, struct vvp_io *cio, struct cl_io *io); int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, struct cl_io *io, loff_t start, size_t count, int *exceed); @@ -356,7 +397,7 @@ static inline struct vvp_lock *cl2vvp_lock(const struct cl_lock_slice *slice) return container_of(slice, struct vvp_lock, vlk_cl); } -struct ccc_io *cl2ccc_io(const struct lu_env *env, +struct vvp_io *cl2vvp_io(const struct lu_env *env, const struct cl_io_slice *slice); struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 86e73d512a91..1059c6353327 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -47,9 +47,6 @@ #include "llite_internal.h" #include "vvp_internal.h" -static struct vvp_io *cl2vvp_io(const struct lu_env *env, - const struct cl_io_slice *slice); - /** * True, if \a io is a normal io, False for splice_{read,write} */ @@ -72,7 +69,7 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); bool rc = true; switch (io->ci_type) { @@ -105,7 +102,7 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, static int vvp_io_write_iter_init(const struct lu_env *env, const struct cl_io_slice *ios) { - struct ccc_io *cio = cl2ccc_io(env, ios); + struct vvp_io *cio = cl2vvp_io(env, ios); cl_page_list_init(&cio->u.write.cui_queue); cio->u.write.cui_written = 0; @@ -118,7 +115,7 @@ static int vvp_io_write_iter_init(const struct lu_env *env, static void vvp_io_write_iter_fini(const struct lu_env *env, const struct cl_io_slice *ios) { - struct ccc_io *cio = cl2ccc_io(env, ios); + struct vvp_io *cio = cl2vvp_io(env, ios); LASSERT(cio->u.write.cui_queue.pl_nr == 0); } @@ -129,8 +126,7 @@ static int vvp_io_fault_iter_init(const struct lu_env *env, struct vvp_io *vio = cl2vvp_io(env, ios); struct inode *inode = vvp_object_inode(ios->cis_obj); - LASSERT(inode == - file_inode(cl2ccc_io(env, ios)->cui_fd->fd_file)); + LASSERT(inode == file_inode(vio->cui_fd->fd_file)); vio->u.fault.ft_mtime = inode->i_mtime.tv_sec; return 0; } @@ -139,7 +135,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) { struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; - struct ccc_io *cio = cl2ccc_io(env, ios); + struct vvp_io *cio = cl2vvp_io(env, ios); CLOBINVRNT(env, obj, vvp_object_invariant(obj)); @@ -225,7 +221,7 @@ static enum cl_lock_mode vvp_mode_from_vma(struct vm_area_struct *vma) } static int vvp_mmap_locks(const struct lu_env *env, - struct ccc_io *vio, struct cl_io *io) + struct vvp_io *vio, struct cl_io *io) { struct ccc_thread_info *cti = ccc_env_info(env); struct mm_struct *mm = current->mm; @@ -310,19 +306,19 @@ static int vvp_mmap_locks(const struct lu_env *env, static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, enum cl_lock_mode mode, loff_t start, loff_t end) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); int result; int ast_flags = 0; LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); - ccc_io_update_iov(env, cio, io); + vvp_io_update_iov(env, cio, io); if (io->u.ci_rw.crw_nonblock) ast_flags |= CEF_NONBLOCK; result = vvp_mmap_locks(env, cio, io); if (result == 0) - result = ccc_io_one_lock(env, io, ast_flags, mode, start, end); + result = vvp_io_one_lock(env, io, ast_flags, mode, start, end); return result; } @@ -347,9 +343,11 @@ static int vvp_io_fault_lock(const struct lu_env *env, /* * XXX LDLM_FL_CBPENDING */ - return ccc_io_one_lock_index - (env, io, 0, vvp_mode_from_vma(vio->u.fault.ft_vma), - io->u.ci_fault.ft_index, io->u.ci_fault.ft_index); + return vvp_io_one_lock_index(env, + io, 0, + vvp_mode_from_vma(vio->u.fault.ft_vma), + io->u.ci_fault.ft_index, + io->u.ci_fault.ft_index); } static int vvp_io_write_lock(const struct lu_env *env, @@ -383,7 +381,7 @@ static int vvp_io_setattr_iter_init(const struct lu_env *env, static int vvp_io_setattr_lock(const struct lu_env *env, const struct cl_io_slice *ios) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); struct cl_io *io = ios->cis_io; __u64 new_size; __u32 enqflags = 0; @@ -401,7 +399,8 @@ static int vvp_io_setattr_lock(const struct lu_env *env, new_size = 0; } cio->u.setattr.cui_local_lock = SETATTR_EXTENT_LOCK; - return ccc_io_one_lock(env, io, enqflags, CLM_WRITE, + + return vvp_io_one_lock(env, io, enqflags, CLM_WRITE, new_size, OBD_OBJECT_EOF); } @@ -496,16 +495,15 @@ static int vvp_io_read_start(const struct lu_env *env, const struct cl_io_slice *ios) { struct vvp_io *vio = cl2vvp_io(env, ios); - struct ccc_io *cio = cl2ccc_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; struct inode *inode = vvp_object_inode(obj); - struct file *file = cio->cui_fd->fd_file; + struct file *file = vio->cui_fd->fd_file; int result; loff_t pos = io->u.ci_rd.rd.crw_pos; long cnt = io->u.ci_rd.rd.crw_count; - long tot = cio->cui_tot_count; + long tot = vio->cui_tot_count; int exceed = 0; CLOBINVRNT(env, obj, vvp_object_invariant(obj)); @@ -526,7 +524,7 @@ static int vvp_io_read_start(const struct lu_env *env, inode->i_ino, cnt, pos, i_size_read(inode)); /* turn off the kernel's read-ahead */ - cio->cui_fd->fd_file->f_ra.ra_pages = 0; + vio->cui_fd->fd_file->f_ra.ra_pages = 0; /* initialize read-ahead window once per syscall */ if (!vio->cui_ra_valid) { @@ -540,8 +538,8 @@ static int vvp_io_read_start(const struct lu_env *env, file_accessed(file); switch (vio->cui_io_subtype) { case IO_NORMAL: - LASSERT(cio->cui_iocb->ki_pos == pos); - result = generic_file_read_iter(cio->cui_iocb, cio->cui_iter); + LASSERT(vio->cui_iocb->ki_pos == pos); + result = generic_file_read_iter(vio->cui_iocb, vio->cui_iter); break; case IO_SPLICE: result = generic_file_splice_read(file, &pos, @@ -564,7 +562,7 @@ static int vvp_io_read_start(const struct lu_env *env, io->ci_continue = 0; io->ci_nob += result; ll_rw_stats_tally(ll_i2sbi(inode), current->pid, - cio->cui_fd, pos, result, READ); + vio->cui_fd, pos, result, READ); result = 0; } return result; @@ -676,7 +674,7 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) { struct cl_object *obj = io->ci_obj; struct inode *inode = vvp_object_inode(obj); - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); struct cl_page_list *queue = &cio->u.write.cui_queue; struct cl_page *page; int rc = 0; @@ -755,7 +753,7 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) static int vvp_io_write_start(const struct lu_env *env, const struct cl_io_slice *ios) { - struct ccc_io *cio = cl2ccc_io(env, ios); + struct vvp_io *cio = cl2vvp_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; struct inode *inode = vvp_object_inode(obj); @@ -813,10 +811,10 @@ static int vvp_io_write_start(const struct lu_env *env, static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) { - struct vm_fault *vmf = cfio->fault.ft_vmf; + struct vm_fault *vmf = cfio->ft_vmf; - cfio->fault.ft_flags = filemap_fault(cfio->ft_vma, vmf); - cfio->fault.ft_flags_valid = 1; + cfio->ft_flags = filemap_fault(cfio->ft_vma, vmf); + cfio->ft_flags_valid = 1; if (vmf->page) { CDEBUG(D_PAGE, @@ -824,29 +822,29 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) vmf->page, vmf->page->mapping, vmf->page->index, (long)vmf->page->flags, page_count(vmf->page), page_private(vmf->page), vmf->virtual_address); - if (unlikely(!(cfio->fault.ft_flags & VM_FAULT_LOCKED))) { + if (unlikely(!(cfio->ft_flags & VM_FAULT_LOCKED))) { lock_page(vmf->page); - cfio->fault.ft_flags |= VM_FAULT_LOCKED; + cfio->ft_flags |= VM_FAULT_LOCKED; } cfio->ft_vmpage = vmf->page; return 0; } - if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) { + if (cfio->ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) { CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address); return -EFAULT; } - if (cfio->fault.ft_flags & VM_FAULT_OOM) { + if (cfio->ft_flags & VM_FAULT_OOM) { CDEBUG(D_PAGE, "got addr %p - OOM\n", vmf->virtual_address); return -ENOMEM; } - if (cfio->fault.ft_flags & VM_FAULT_RETRY) + if (cfio->ft_flags & VM_FAULT_RETRY) return -EAGAIN; - CERROR("Unknown error in page fault %d!\n", cfio->fault.ft_flags); + CERROR("Unknown error in page fault %d!\n", cfio->ft_flags); return -EINVAL; } @@ -1024,7 +1022,9 @@ static int vvp_io_fault_start(const struct lu_env *env, /* return unlocked vmpage to avoid deadlocking */ if (vmpage) unlock_page(vmpage); - cfio->fault.ft_flags &= ~VM_FAULT_LOCKED; + + cfio->ft_flags &= ~VM_FAULT_LOCKED; + return result; } @@ -1047,7 +1047,7 @@ static int vvp_io_read_page(const struct lu_env *env, struct cl_page *page = slice->cpl_page; struct inode *inode = vvp_object_inode(slice->cpl_obj); struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ll_file_data *fd = cl2ccc_io(env, ios)->cui_fd; + struct ll_file_data *fd = cl2vvp_io(env, ios)->cui_fd; struct ll_readahead_state *ras = &fd->fd_ras; struct cl_2queue *queue = &io->ci_queue; @@ -1080,7 +1080,7 @@ static const struct cl_io_operations vvp_io_ops = { .cio_fini = vvp_io_fini, .cio_lock = vvp_io_read_lock, .cio_start = vvp_io_read_start, - .cio_advance = ccc_io_advance, + .cio_advance = vvp_io_advance, }, [CIT_WRITE] = { .cio_fini = vvp_io_fini, @@ -1088,7 +1088,7 @@ static const struct cl_io_operations vvp_io_ops = { .cio_iter_fini = vvp_io_write_iter_fini, .cio_lock = vvp_io_write_lock, .cio_start = vvp_io_write_start, - .cio_advance = ccc_io_advance + .cio_advance = vvp_io_advance, }, [CIT_SETATTR] = { .cio_fini = vvp_io_setattr_fini, @@ -1102,7 +1102,7 @@ static const struct cl_io_operations vvp_io_ops = { .cio_iter_init = vvp_io_fault_iter_init, .cio_lock = vvp_io_fault_lock, .cio_start = vvp_io_fault_start, - .cio_end = ccc_io_end + .cio_end = vvp_io_end, }, [CIT_FSYNC] = { .cio_start = vvp_io_fsync_start, @@ -1119,7 +1119,6 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, struct cl_io *io) { struct vvp_io *vio = vvp_env_io(env); - struct ccc_io *cio = ccc_env_io(env); struct inode *inode = vvp_object_inode(obj); int result; @@ -1129,10 +1128,10 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, " ignore/verify layout %d/%d, layout version %d restore needed %d\n", PFID(lu_object_fid(&obj->co_lu)), io->ci_ignore_layout, io->ci_verify_layout, - cio->cui_layout_gen, io->ci_restore_needed); + vio->cui_layout_gen, io->ci_restore_needed); - CL_IO_SLICE_CLEAN(cio, cui_cl); - cl_io_slice_add(io, &cio->cui_cl, obj, &vvp_io_ops); + CL_IO_SLICE_CLEAN(vio, cui_cl); + cl_io_slice_add(io, &vio->cui_cl, obj, &vvp_io_ops); vio->cui_ra_valid = false; result = 0; if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE) { @@ -1146,7 +1145,7 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, if (count == 0) result = 1; else - cio->cui_tot_count = count; + vio->cui_tot_count = count; /* for read/write, we store the jobid in the inode, and * it'll be fetched by osc when building RPC. @@ -1172,7 +1171,7 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, * because it might not grant layout lock in IT_OPEN. */ if (result == 0 && !io->ci_ignore_layout) { - result = ll_layout_refresh(inode, &cio->cui_layout_gen); + result = ll_layout_refresh(inode, &vio->cui_layout_gen); if (result == -ENOENT) /* If the inode on MDS has been removed, but the objects * on OSTs haven't been destroyed (async unlink), layout @@ -1188,11 +1187,3 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, return result; } - -static struct vvp_io *cl2vvp_io(const struct lu_env *env, - const struct cl_io_slice *slice) -{ - /* Calling just for assertion */ - cl2ccc_io(env, slice); - return vvp_env_io(env); -} diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 5ebbe27104f1..4f7dfe221544 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -372,7 +372,7 @@ static int vvp_page_is_under_lock(const struct lu_env *env, { if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE || io->ci_type == CIT_FAULT) { - struct ccc_io *cio = ccc_env_io(env); + struct vvp_io *cio = vvp_env_io(env); if (unlikely(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) *max_index = CL_PAGE_EOF; -- GitLab From e0a8144b8c32031d37ff849fc07e6c5646e61198 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:52 -0400 Subject: [PATCH 0881/9938] staging/lustre/llite: use vui prefix for struct vvp_io members Rename members of struct vvp_io to used to start with vui_ rather than cui_. Rename several instances of struct vvp_io * from cio to vio. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13363 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 20 +-- .../staging/lustre/lustre/llite/lcommon_cl.c | 34 ++--- .../staging/lustre/lustre/llite/llite_mmap.c | 6 +- drivers/staging/lustre/lustre/llite/rw.c | 24 ++-- drivers/staging/lustre/lustre/llite/rw26.c | 20 +-- .../lustre/lustre/llite/vvp_internal.h | 38 ++--- drivers/staging/lustre/lustre/llite/vvp_io.c | 131 +++++++++--------- .../staging/lustre/lustre/llite/vvp_page.c | 4 +- 8 files changed, 139 insertions(+), 138 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 27e7e65b3a98..63aa080785d4 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1135,18 +1135,18 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, ll_io_init(io, file, iot == CIT_WRITE); if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); int write_mutex_locked = 0; - cio->cui_fd = LUSTRE_FPRIVATE(file); - cio->cui_io_subtype = args->via_io_subtype; + vio->vui_fd = LUSTRE_FPRIVATE(file); + vio->vui_io_subtype = args->via_io_subtype; - switch (cio->cui_io_subtype) { + switch (vio->vui_io_subtype) { case IO_NORMAL: - cio->cui_iter = args->u.normal.via_iter; - cio->cui_iocb = args->u.normal.via_iocb; + vio->vui_iter = args->u.normal.via_iter; + vio->vui_iocb = args->u.normal.via_iocb; if ((iot == CIT_WRITE) && - !(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { + !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { if (mutex_lock_interruptible(&lli-> lli_write_mutex)) { result = -ERESTARTSYS; @@ -1157,11 +1157,11 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, down_read(&lli->lli_trunc_sem); break; case IO_SPLICE: - cio->u.splice.cui_pipe = args->u.splice.via_pipe; - cio->u.splice.cui_flags = args->u.splice.via_flags; + vio->u.splice.vui_pipe = args->u.splice.via_pipe; + vio->u.splice.vui_flags = args->u.splice.via_flags; break; default: - CERROR("Unknown IO type - %u\n", cio->cui_io_subtype); + CERROR("Unknown IO type - %u\n", vio->vui_io_subtype); LBUG(); } result = cl_io_loop(env, io); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 9a9d7061fff0..630c37142d31 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -210,19 +210,19 @@ int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, __u32 enqflags, enum cl_lock_mode mode, pgoff_t start, pgoff_t end) { - struct vvp_io *cio = vvp_env_io(env); - struct cl_lock_descr *descr = &cio->cui_link.cill_descr; + struct vvp_io *vio = vvp_env_io(env); + struct cl_lock_descr *descr = &vio->vui_link.cill_descr; struct cl_object *obj = io->ci_obj; CLOBINVRNT(env, obj, vvp_object_invariant(obj)); CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end); - memset(&cio->cui_link, 0, sizeof(cio->cui_link)); + memset(&vio->vui_link, 0, sizeof(vio->vui_link)); - if (cio->cui_fd && (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { + if (vio->vui_fd && (vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { descr->cld_mode = CLM_GROUP; - descr->cld_gid = cio->cui_fd->fd_grouplock.cg_gid; + descr->cld_gid = vio->vui_fd->fd_grouplock.cg_gid; } else { descr->cld_mode = mode; } @@ -231,19 +231,19 @@ int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, descr->cld_end = end; descr->cld_enq_flags = enqflags; - cl_io_lock_add(env, io, &cio->cui_link); + cl_io_lock_add(env, io, &vio->vui_link); return 0; } void vvp_io_update_iov(const struct lu_env *env, - struct vvp_io *cio, struct cl_io *io) + struct vvp_io *vio, struct cl_io *io) { size_t size = io->u.ci_rw.crw_count; - if (!cl_is_normalio(env, io) || !cio->cui_iter) + if (!cl_is_normalio(env, io) || !vio->vui_iter) return; - iov_iter_truncate(cio->cui_iter, size); + iov_iter_truncate(vio->vui_iter, size); } int vvp_io_one_lock(const struct lu_env *env, struct cl_io *io, @@ -266,7 +266,7 @@ void vvp_io_advance(const struct lu_env *env, const struct cl_io_slice *ios, size_t nob) { - struct vvp_io *cio = cl2vvp_io(env, ios); + struct vvp_io *vio = cl2vvp_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = ios->cis_io->ci_obj; @@ -275,7 +275,7 @@ void vvp_io_advance(const struct lu_env *env, if (!cl_is_normalio(env, io)) return; - iov_iter_reexpand(cio->cui_iter, cio->cui_tot_count -= nob); + iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count -= nob); } /** @@ -461,13 +461,13 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) again: if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) { - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); if (attr->ia_valid & ATTR_FILE) /* populate the file descriptor for ftruncate to honor * group lock - see LU-787 */ - cio->cui_fd = LUSTRE_FPRIVATE(attr->ia_file); + vio->vui_fd = LUSTRE_FPRIVATE(attr->ia_file); result = cl_io_loop(env, io); } else { @@ -496,12 +496,12 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) struct vvp_io *cl2vvp_io(const struct lu_env *env, const struct cl_io_slice *slice) { - struct vvp_io *cio; + struct vvp_io *vio; - cio = container_of(slice, struct vvp_io, cui_cl); - LASSERT(cio == vvp_env_io(env)); + vio = container_of(slice, struct vvp_io, vui_cl); + LASSERT(vio == vvp_env_io(env)); - return cio; + return vio; } struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice) diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 7c214f8a1e71..a7693c55cc46 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -146,14 +146,14 @@ ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret, rc = cl_io_init(env, io, CIT_FAULT, io->ci_obj); if (rc == 0) { - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); - LASSERT(cio->cui_cl.cis_io == io); + LASSERT(vio->vui_cl.cis_io == io); /* mmap lock must be MANDATORY it has to cache pages. */ io->ci_lockreq = CILR_MANDATORY; - cio->cui_fd = fd; + vio->vui_fd = fd; } else { LASSERT(rc < 0); cl_io_fini(env, io); diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index da4410712f83..634f0bb355e3 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -90,7 +90,7 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) struct lu_env *env; struct cl_io *io; struct cl_object *clob; - struct vvp_io *cio; + struct vvp_io *vio; int refcheck; int result = 0; @@ -108,8 +108,8 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) lcc->lcc_refcheck = refcheck; lcc->lcc_cookie = current; - cio = vvp_env_io(env); - io = cio->cui_cl.cis_io; + vio = vvp_env_io(env); + io = vio->vui_cl.cis_io; lcc->lcc_io = io; if (!io) { struct inode *inode = file_inode(file); @@ -125,7 +125,7 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) struct cl_page *page; LASSERT(io->ci_state == CIS_IO_GOING); - LASSERT(cio->cui_fd == LUSTRE_FPRIVATE(file)); + LASSERT(vio->vui_fd == LUSTRE_FPRIVATE(file)); page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE); if (!IS_ERR(page)) { @@ -553,10 +553,10 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, spin_lock(&ras->ras_lock); /* Enlarge the RA window to encompass the full read */ - if (vio->cui_ra_valid && + if (vio->vui_ra_valid && ras->ras_window_start + ras->ras_window_len < - vio->cui_ra_start + vio->cui_ra_count) { - ras->ras_window_len = vio->cui_ra_start + vio->cui_ra_count - + vio->vui_ra_start + vio->vui_ra_count) { + ras->ras_window_len = vio->vui_ra_start + vio->vui_ra_count - ras->ras_window_start; } @@ -615,15 +615,15 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, CDEBUG(D_READA, DFID ": ria: %lu/%lu, bead: %lu/%lu, hit: %d\n", PFID(lu_object_fid(&clob->co_lu)), ria->ria_start, ria->ria_end, - vio->cui_ra_valid ? vio->cui_ra_start : 0, - vio->cui_ra_valid ? vio->cui_ra_count : 0, + vio->vui_ra_valid ? vio->vui_ra_start : 0, + vio->vui_ra_valid ? vio->vui_ra_count : 0, hit); /* at least to extend the readahead window to cover current read */ - if (!hit && vio->cui_ra_valid && - vio->cui_ra_start + vio->cui_ra_count > ria->ria_start) { + if (!hit && vio->vui_ra_valid && + vio->vui_ra_start + vio->vui_ra_count > ria->ria_start) { /* to the end of current read window. */ - mlen = vio->cui_ra_start + vio->cui_ra_count - ria->ria_start; + mlen = vio->vui_ra_start + vio->vui_ra_count - ria->ria_start; /* trim to RPC boundary */ start = ria->ria_start & (PTLRPC_MAX_BRW_PAGES - 1); mlen = min(mlen, PTLRPC_MAX_BRW_PAGES - start); diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 2f69634376f9..106473eb4117 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -376,7 +376,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, env = cl_env_get(&refcheck); LASSERT(!IS_ERR(env)); - io = vvp_env_io(env)->cui_cl.cis_io; + io = vvp_env_io(env)->vui_cl.cis_io; LASSERT(io); /* 0. Need locking between buffered and direct access. and race with @@ -439,10 +439,10 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, inode_unlock(inode); if (tot_bytes > 0) { - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); /* no commit async for direct IO */ - cio->u.write.cui_written += tot_bytes; + vio->u.write.vui_written += tot_bytes; } cl_env_put(env, &refcheck); @@ -513,8 +513,8 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, /* To avoid deadlock, try to lock page first. */ vmpage = grab_cache_page_nowait(mapping, index); if (unlikely(!vmpage || PageDirty(vmpage) || PageWriteback(vmpage))) { - struct vvp_io *cio = vvp_env_io(env); - struct cl_page_list *plist = &cio->u.write.cui_queue; + struct vvp_io *vio = vvp_env_io(env); + struct cl_page_list *plist = &vio->u.write.vui_queue; /* if the page is already in dirty cache, we have to commit * the pages right now; otherwise, it may cause deadlock @@ -595,7 +595,7 @@ static int ll_write_end(struct file *file, struct address_space *mapping, struct ll_cl_context *lcc = fsdata; struct lu_env *env; struct cl_io *io; - struct vvp_io *cio; + struct vvp_io *vio; struct cl_page *page; unsigned from = pos & (PAGE_CACHE_SIZE - 1); bool unplug = false; @@ -606,21 +606,21 @@ static int ll_write_end(struct file *file, struct address_space *mapping, env = lcc->lcc_env; page = lcc->lcc_page; io = lcc->lcc_io; - cio = vvp_env_io(env); + vio = vvp_env_io(env); LASSERT(cl_page_is_owned(page, io)); if (copied > 0) { - struct cl_page_list *plist = &cio->u.write.cui_queue; + struct cl_page_list *plist = &vio->u.write.vui_queue; lcc->lcc_page = NULL; /* page will be queued */ /* Add it into write queue */ cl_page_list_add(plist, page); if (plist->pl_nr == 1) /* first page */ - cio->u.write.cui_from = from; + vio->u.write.vui_from = from; else LASSERT(from == 0); - cio->u.write.cui_to = from + copied; + vio->u.write.vui_to = from + copied; /* We may have one full RPC, commit it soon */ if (plist->pl_nr >= PTLRPC_MAX_BRW_PAGES) diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 443485c8c3ee..e04f23ea403e 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -94,16 +94,16 @@ enum vvp_io_subtype { */ struct vvp_io { /** super class */ - struct cl_io_slice cui_cl; - struct cl_io_lock_link cui_link; + struct cl_io_slice vui_cl; + struct cl_io_lock_link vui_link; /** * I/O vector information to or from which read/write is going. */ - struct iov_iter *cui_iter; + struct iov_iter *vui_iter; /** * Total size for the left IO. */ - size_t cui_tot_count; + size_t vui_tot_count; union { struct vvp_fault_io { @@ -131,37 +131,37 @@ struct vvp_io { bool ft_flags_valid; } fault; struct { - enum ccc_setattr_lock_type cui_local_lock; + enum ccc_setattr_lock_type vui_local_lock; } setattr; struct { - struct pipe_inode_info *cui_pipe; - unsigned int cui_flags; + struct pipe_inode_info *vui_pipe; + unsigned int vui_flags; } splice; struct { - struct cl_page_list cui_queue; - unsigned long cui_written; - int cui_from; - int cui_to; + struct cl_page_list vui_queue; + unsigned long vui_written; + int vui_from; + int vui_to; } write; } u; - enum vvp_io_subtype cui_io_subtype; + enum vvp_io_subtype vui_io_subtype; /** * Layout version when this IO is initialized */ - __u32 cui_layout_gen; + __u32 vui_layout_gen; /** * File descriptor against which IO is done. */ - struct ll_file_data *cui_fd; - struct kiocb *cui_iocb; + struct ll_file_data *vui_fd; + struct kiocb *vui_iocb; /* Readahead state. */ - pgoff_t cui_ra_start; - pgoff_t cui_ra_count; - /* Set when cui_ra_{start,count} have been initialized. */ - bool cui_ra_valid; + pgoff_t vui_ra_start; + pgoff_t vui_ra_count; + /* Set when vui_ra_{start,count} have been initialized. */ + bool vui_ra_valid; }; /** diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 1059c6353327..53cf2be0e152 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -56,7 +56,7 @@ int cl_is_normalio(const struct lu_env *env, const struct cl_io *io) LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); - return vio->cui_io_subtype == IO_NORMAL; + return vio->vui_io_subtype == IO_NORMAL; } /** @@ -69,7 +69,7 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); bool rc = true; switch (io->ci_type) { @@ -78,7 +78,7 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, /* don't need lock here to check lli_layout_gen as we have held * extent lock and GROUP lock has to hold to swap layout */ - if (ll_layout_version_get(lli) != cio->cui_layout_gen) { + if (ll_layout_version_get(lli) != vio->vui_layout_gen) { io->ci_need_restart = 1; /* this will return application a short read/write */ io->ci_continue = 0; @@ -102,12 +102,12 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, static int vvp_io_write_iter_init(const struct lu_env *env, const struct cl_io_slice *ios) { - struct vvp_io *cio = cl2vvp_io(env, ios); + struct vvp_io *vio = cl2vvp_io(env, ios); - cl_page_list_init(&cio->u.write.cui_queue); - cio->u.write.cui_written = 0; - cio->u.write.cui_from = 0; - cio->u.write.cui_to = PAGE_SIZE; + cl_page_list_init(&vio->u.write.vui_queue); + vio->u.write.vui_written = 0; + vio->u.write.vui_from = 0; + vio->u.write.vui_to = PAGE_SIZE; return 0; } @@ -115,9 +115,9 @@ static int vvp_io_write_iter_init(const struct lu_env *env, static void vvp_io_write_iter_fini(const struct lu_env *env, const struct cl_io_slice *ios) { - struct vvp_io *cio = cl2vvp_io(env, ios); + struct vvp_io *vio = cl2vvp_io(env, ios); - LASSERT(cio->u.write.cui_queue.pl_nr == 0); + LASSERT(vio->u.write.vui_queue.pl_nr == 0); } static int vvp_io_fault_iter_init(const struct lu_env *env, @@ -126,7 +126,7 @@ static int vvp_io_fault_iter_init(const struct lu_env *env, struct vvp_io *vio = cl2vvp_io(env, ios); struct inode *inode = vvp_object_inode(ios->cis_obj); - LASSERT(inode == file_inode(vio->cui_fd->fd_file)); + LASSERT(inode == file_inode(vio->vui_fd->fd_file)); vio->u.fault.ft_mtime = inode->i_mtime.tv_sec; return 0; } @@ -135,7 +135,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) { struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; - struct vvp_io *cio = cl2vvp_io(env, ios); + struct vvp_io *vio = cl2vvp_io(env, ios); CLOBINVRNT(env, obj, vvp_object_invariant(obj)); @@ -143,7 +143,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) " ignore/verify layout %d/%d, layout version %d restore needed %d\n", PFID(lu_object_fid(&obj->co_lu)), io->ci_ignore_layout, io->ci_verify_layout, - cio->cui_layout_gen, io->ci_restore_needed); + vio->vui_layout_gen, io->ci_restore_needed); if (io->ci_restore_needed == 1) { int rc; @@ -178,12 +178,12 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) /* check layout version */ ll_layout_refresh(vvp_object_inode(obj), &gen); - io->ci_need_restart = cio->cui_layout_gen != gen; + io->ci_need_restart = vio->vui_layout_gen != gen; if (io->ci_need_restart) { CDEBUG(D_VFSTRACE, DFID" layout changed from %d to %d.\n", PFID(lu_object_fid(&obj->co_lu)), - cio->cui_layout_gen, gen); + vio->vui_layout_gen, gen); /* today successful restore is the only possible case */ /* restore was done, clear restoring state */ ll_i2info(vvp_object_inode(obj))->lli_flags &= @@ -239,14 +239,14 @@ static int vvp_mmap_locks(const struct lu_env *env, if (!cl_is_normalio(env, io)) return 0; - if (!vio->cui_iter) /* nfs or loop back device write */ + if (!vio->vui_iter) /* nfs or loop back device write */ return 0; /* No MM (e.g. NFS)? No vmas too. */ if (!mm) return 0; - iov_for_each(iov, i, *(vio->cui_iter)) { + iov_for_each(iov, i, *vio->vui_iter) { addr = (unsigned long)iov.iov_base; count = iov.iov_len; if (count == 0) @@ -306,17 +306,17 @@ static int vvp_mmap_locks(const struct lu_env *env, static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, enum cl_lock_mode mode, loff_t start, loff_t end) { - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); int result; int ast_flags = 0; LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); - vvp_io_update_iov(env, cio, io); + vvp_io_update_iov(env, vio, io); if (io->u.ci_rw.crw_nonblock) ast_flags |= CEF_NONBLOCK; - result = vvp_mmap_locks(env, cio, io); + result = vvp_mmap_locks(env, vio, io); if (result == 0) result = vvp_io_one_lock(env, io, ast_flags, mode, start, end); return result; @@ -374,14 +374,14 @@ static int vvp_io_setattr_iter_init(const struct lu_env *env, } /** - * Implementation of cl_io_operations::cio_lock() method for CIT_SETATTR io. + * Implementation of cl_io_operations::vio_lock() method for CIT_SETATTR io. * * Handles "lockless io" mode when extent locking is done by server. */ static int vvp_io_setattr_lock(const struct lu_env *env, const struct cl_io_slice *ios) { - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); struct cl_io *io = ios->cis_io; __u64 new_size; __u32 enqflags = 0; @@ -398,7 +398,8 @@ static int vvp_io_setattr_lock(const struct lu_env *env, return 0; new_size = 0; } - cio->u.setattr.cui_local_lock = SETATTR_EXTENT_LOCK; + + vio->u.setattr.vui_local_lock = SETATTR_EXTENT_LOCK; return vvp_io_one_lock(env, io, enqflags, CLM_WRITE, new_size, OBD_OBJECT_EOF); @@ -498,12 +499,12 @@ static int vvp_io_read_start(const struct lu_env *env, struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; struct inode *inode = vvp_object_inode(obj); - struct file *file = vio->cui_fd->fd_file; + struct file *file = vio->vui_fd->fd_file; int result; loff_t pos = io->u.ci_rd.rd.crw_pos; long cnt = io->u.ci_rd.rd.crw_count; - long tot = vio->cui_tot_count; + long tot = vio->vui_tot_count; int exceed = 0; CLOBINVRNT(env, obj, vvp_object_invariant(obj)); @@ -524,27 +525,27 @@ static int vvp_io_read_start(const struct lu_env *env, inode->i_ino, cnt, pos, i_size_read(inode)); /* turn off the kernel's read-ahead */ - vio->cui_fd->fd_file->f_ra.ra_pages = 0; + vio->vui_fd->fd_file->f_ra.ra_pages = 0; /* initialize read-ahead window once per syscall */ - if (!vio->cui_ra_valid) { - vio->cui_ra_valid = true; - vio->cui_ra_start = cl_index(obj, pos); - vio->cui_ra_count = cl_index(obj, tot + PAGE_CACHE_SIZE - 1); + if (!vio->vui_ra_valid) { + vio->vui_ra_valid = true; + vio->vui_ra_start = cl_index(obj, pos); + vio->vui_ra_count = cl_index(obj, tot + PAGE_CACHE_SIZE - 1); ll_ras_enter(file); } /* BUG: 5972 */ file_accessed(file); - switch (vio->cui_io_subtype) { + switch (vio->vui_io_subtype) { case IO_NORMAL: - LASSERT(vio->cui_iocb->ki_pos == pos); - result = generic_file_read_iter(vio->cui_iocb, vio->cui_iter); + LASSERT(vio->vui_iocb->ki_pos == pos); + result = generic_file_read_iter(vio->vui_iocb, vio->vui_iter); break; case IO_SPLICE: result = generic_file_splice_read(file, &pos, - vio->u.splice.cui_pipe, cnt, - vio->u.splice.cui_flags); + vio->u.splice.vui_pipe, cnt, + vio->u.splice.vui_flags); /* LU-1109: do splice read stripe by stripe otherwise if it * may make nfsd stuck if this read occupied all internal pipe * buffers. @@ -552,7 +553,7 @@ static int vvp_io_read_start(const struct lu_env *env, io->ci_continue = 0; break; default: - CERROR("Wrong IO type %u\n", vio->cui_io_subtype); + CERROR("Wrong IO type %u\n", vio->vui_io_subtype); LBUG(); } @@ -562,7 +563,7 @@ static int vvp_io_read_start(const struct lu_env *env, io->ci_continue = 0; io->ci_nob += result; ll_rw_stats_tally(ll_i2sbi(inode), current->pid, - vio->cui_fd, pos, result, READ); + vio->vui_fd, pos, result, READ); result = 0; } return result; @@ -674,24 +675,24 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) { struct cl_object *obj = io->ci_obj; struct inode *inode = vvp_object_inode(obj); - struct vvp_io *cio = vvp_env_io(env); - struct cl_page_list *queue = &cio->u.write.cui_queue; + struct vvp_io *vio = vvp_env_io(env); + struct cl_page_list *queue = &vio->u.write.vui_queue; struct cl_page *page; int rc = 0; int bytes = 0; - unsigned int npages = cio->u.write.cui_queue.pl_nr; + unsigned int npages = vio->u.write.vui_queue.pl_nr; if (npages == 0) return 0; CDEBUG(D_VFSTRACE, "commit async pages: %d, from %d, to %d\n", - npages, cio->u.write.cui_from, cio->u.write.cui_to); + npages, vio->u.write.vui_from, vio->u.write.vui_to); LASSERT(page_list_sanity_check(obj, queue)); /* submit IO with async write */ rc = cl_io_commit_async(env, io, queue, - cio->u.write.cui_from, cio->u.write.cui_to, + vio->u.write.vui_from, vio->u.write.vui_to, write_commit_callback); npages -= queue->pl_nr; /* already committed pages */ if (npages > 0) { @@ -699,18 +700,18 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) bytes = npages << PAGE_SHIFT; /* first page */ - bytes -= cio->u.write.cui_from; + bytes -= vio->u.write.vui_from; if (queue->pl_nr == 0) /* last page */ - bytes -= PAGE_SIZE - cio->u.write.cui_to; + bytes -= PAGE_SIZE - vio->u.write.vui_to; LASSERTF(bytes > 0, "bytes = %d, pages = %d\n", bytes, npages); - cio->u.write.cui_written += bytes; + vio->u.write.vui_written += bytes; CDEBUG(D_VFSTRACE, "Committed %d pages %d bytes, tot: %ld\n", - npages, bytes, cio->u.write.cui_written); + npages, bytes, vio->u.write.vui_written); /* the first page must have been written. */ - cio->u.write.cui_from = 0; + vio->u.write.vui_from = 0; } LASSERT(page_list_sanity_check(obj, queue)); LASSERT(ergo(rc == 0, queue->pl_nr == 0)); @@ -718,10 +719,10 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) /* out of quota, try sync write */ if (rc == -EDQUOT && !cl_io_is_mkwrite(io)) { rc = vvp_io_commit_sync(env, io, queue, - cio->u.write.cui_from, - cio->u.write.cui_to); + vio->u.write.vui_from, + vio->u.write.vui_to); if (rc > 0) { - cio->u.write.cui_written += rc; + vio->u.write.vui_written += rc; rc = 0; } } @@ -753,7 +754,7 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io) static int vvp_io_write_start(const struct lu_env *env, const struct cl_io_slice *ios) { - struct vvp_io *cio = cl2vvp_io(env, ios); + struct vvp_io *vio = cl2vvp_io(env, ios); struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; struct inode *inode = vvp_object_inode(obj); @@ -771,22 +772,22 @@ static int vvp_io_write_start(const struct lu_env *env, */ ll_merge_attr(env, inode); pos = io->u.ci_wr.wr.crw_pos = i_size_read(inode); - cio->cui_iocb->ki_pos = pos; + vio->vui_iocb->ki_pos = pos; } else { - LASSERT(cio->cui_iocb->ki_pos == pos); + LASSERT(vio->vui_iocb->ki_pos == pos); } CDEBUG(D_VFSTRACE, "write: [%lli, %lli)\n", pos, pos + (long long)cnt); - if (!cio->cui_iter) /* from a temp io in ll_cl_init(). */ + if (!vio->vui_iter) /* from a temp io in ll_cl_init(). */ result = 0; else - result = generic_file_write_iter(cio->cui_iocb, cio->cui_iter); + result = generic_file_write_iter(vio->vui_iocb, vio->vui_iter); if (result > 0) { result = vvp_io_write_commit(env, io); - if (cio->u.write.cui_written > 0) { - result = cio->u.write.cui_written; + if (vio->u.write.vui_written > 0) { + result = vio->u.write.vui_written; io->ci_nob += result; CDEBUG(D_VFSTRACE, "write: nob %zd, result: %zd\n", @@ -803,7 +804,7 @@ static int vvp_io_write_start(const struct lu_env *env, if (result < cnt) io->ci_continue = 0; ll_rw_stats_tally(ll_i2sbi(inode), current->pid, - cio->cui_fd, pos, result, WRITE); + vio->vui_fd, pos, result, WRITE); result = 0; } return result; @@ -1047,7 +1048,7 @@ static int vvp_io_read_page(const struct lu_env *env, struct cl_page *page = slice->cpl_page; struct inode *inode = vvp_object_inode(slice->cpl_obj); struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ll_file_data *fd = cl2vvp_io(env, ios)->cui_fd; + struct ll_file_data *fd = cl2vvp_io(env, ios)->vui_fd; struct ll_readahead_state *ras = &fd->fd_ras; struct cl_2queue *queue = &io->ci_queue; @@ -1128,11 +1129,11 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, " ignore/verify layout %d/%d, layout version %d restore needed %d\n", PFID(lu_object_fid(&obj->co_lu)), io->ci_ignore_layout, io->ci_verify_layout, - vio->cui_layout_gen, io->ci_restore_needed); + vio->vui_layout_gen, io->ci_restore_needed); - CL_IO_SLICE_CLEAN(vio, cui_cl); - cl_io_slice_add(io, &vio->cui_cl, obj, &vvp_io_ops); - vio->cui_ra_valid = false; + CL_IO_SLICE_CLEAN(vio, vui_cl); + cl_io_slice_add(io, &vio->vui_cl, obj, &vvp_io_ops); + vio->vui_ra_valid = false; result = 0; if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE) { size_t count; @@ -1145,7 +1146,7 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, if (count == 0) result = 1; else - vio->cui_tot_count = count; + vio->vui_tot_count = count; /* for read/write, we store the jobid in the inode, and * it'll be fetched by osc when building RPC. @@ -1171,7 +1172,7 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, * because it might not grant layout lock in IT_OPEN. */ if (result == 0 && !io->ci_ignore_layout) { - result = ll_layout_refresh(inode, &vio->cui_layout_gen); + result = ll_layout_refresh(inode, &vio->vui_layout_gen); if (result == -ENOENT) /* If the inode on MDS has been removed, but the objects * on OSTs haven't been destroyed (async unlink), layout diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 4f7dfe221544..69316c191de6 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -372,9 +372,9 @@ static int vvp_page_is_under_lock(const struct lu_env *env, { if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE || io->ci_type == CIT_FAULT) { - struct vvp_io *cio = vvp_env_io(env); + struct vvp_io *vio = vvp_env_io(env); - if (unlikely(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) + if (unlikely(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) *max_index = CL_PAGE_EOF; } return 0; -- GitLab From fee6eb5052fc394c6f40316052033cd69ee4ebc5 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:53 -0400 Subject: [PATCH 0882/9938] staging/lustre/llite: move vvp_io functions to vvp_io.c Move all vvp_io related functions from lustre/llite/lcommon_cl.c to the sole file where they are used lustre/llite/vvp_io.c. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13376 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Jinshan Xiong Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/llite/lcommon_cl.c | 197 ----------------- .../lustre/lustre/llite/llite_internal.h | 1 - .../lustre/lustre/llite/vvp_internal.h | 22 +- drivers/staging/lustre/lustre/llite/vvp_io.c | 198 +++++++++++++++++- 4 files changed, 196 insertions(+), 222 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 630c37142d31..1b1110349312 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -184,192 +184,6 @@ void ccc_global_fini(struct lu_device_type *device_type) lu_kmem_fini(ccc_caches); } -static void vvp_object_size_lock(struct cl_object *obj) -{ - struct inode *inode = vvp_object_inode(obj); - - ll_inode_size_lock(inode); - cl_object_attr_lock(obj); -} - -static void vvp_object_size_unlock(struct cl_object *obj) -{ - struct inode *inode = vvp_object_inode(obj); - - cl_object_attr_unlock(obj); - ll_inode_size_unlock(inode); -} - -/***************************************************************************** - * - * io operations. - * - */ - -int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, - __u32 enqflags, enum cl_lock_mode mode, - pgoff_t start, pgoff_t end) -{ - struct vvp_io *vio = vvp_env_io(env); - struct cl_lock_descr *descr = &vio->vui_link.cill_descr; - struct cl_object *obj = io->ci_obj; - - CLOBINVRNT(env, obj, vvp_object_invariant(obj)); - - CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end); - - memset(&vio->vui_link, 0, sizeof(vio->vui_link)); - - if (vio->vui_fd && (vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { - descr->cld_mode = CLM_GROUP; - descr->cld_gid = vio->vui_fd->fd_grouplock.cg_gid; - } else { - descr->cld_mode = mode; - } - descr->cld_obj = obj; - descr->cld_start = start; - descr->cld_end = end; - descr->cld_enq_flags = enqflags; - - cl_io_lock_add(env, io, &vio->vui_link); - return 0; -} - -void vvp_io_update_iov(const struct lu_env *env, - struct vvp_io *vio, struct cl_io *io) -{ - size_t size = io->u.ci_rw.crw_count; - - if (!cl_is_normalio(env, io) || !vio->vui_iter) - return; - - iov_iter_truncate(vio->vui_iter, size); -} - -int vvp_io_one_lock(const struct lu_env *env, struct cl_io *io, - __u32 enqflags, enum cl_lock_mode mode, - loff_t start, loff_t end) -{ - struct cl_object *obj = io->ci_obj; - - return vvp_io_one_lock_index(env, io, enqflags, mode, - cl_index(obj, start), cl_index(obj, end)); -} - -void vvp_io_end(const struct lu_env *env, const struct cl_io_slice *ios) -{ - CLOBINVRNT(env, ios->cis_io->ci_obj, - vvp_object_invariant(ios->cis_io->ci_obj)); -} - -void vvp_io_advance(const struct lu_env *env, - const struct cl_io_slice *ios, - size_t nob) -{ - struct vvp_io *vio = cl2vvp_io(env, ios); - struct cl_io *io = ios->cis_io; - struct cl_object *obj = ios->cis_io->ci_obj; - - CLOBINVRNT(env, obj, vvp_object_invariant(obj)); - - if (!cl_is_normalio(env, io)) - return; - - iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count -= nob); -} - -/** - * Helper function that if necessary adjusts file size (inode->i_size), when - * position at the offset \a pos is accessed. File size can be arbitrary stale - * on a Lustre client, but client at least knows KMS. If accessed area is - * inside [0, KMS], set file size to KMS, otherwise glimpse file size. - * - * Locking: cl_isize_lock is used to serialize changes to inode size and to - * protect consistency between inode size and cl_object - * attributes. cl_object_size_lock() protects consistency between cl_attr's of - * top-object and sub-objects. - */ -int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, - struct cl_io *io, loff_t start, size_t count, int *exceed) -{ - struct cl_attr *attr = ccc_env_thread_attr(env); - struct inode *inode = vvp_object_inode(obj); - loff_t pos = start + count - 1; - loff_t kms; - int result; - - /* - * Consistency guarantees: following possibilities exist for the - * relation between region being accessed and real file size at this - * moment: - * - * (A): the region is completely inside of the file; - * - * (B-x): x bytes of region are inside of the file, the rest is - * outside; - * - * (C): the region is completely outside of the file. - * - * This classification is stable under DLM lock already acquired by - * the caller, because to change the class, other client has to take - * DLM lock conflicting with our lock. Also, any updates to ->i_size - * by other threads on this client are serialized by - * ll_inode_size_lock(). This guarantees that short reads are handled - * correctly in the face of concurrent writes and truncates. - */ - vvp_object_size_lock(obj); - result = cl_object_attr_get(env, obj, attr); - if (result == 0) { - kms = attr->cat_kms; - if (pos > kms) { - /* - * A glimpse is necessary to determine whether we - * return a short read (B) or some zeroes at the end - * of the buffer (C) - */ - vvp_object_size_unlock(obj); - result = cl_glimpse_lock(env, io, inode, obj, 0); - if (result == 0 && exceed) { - /* If objective page index exceed end-of-file - * page index, return directly. Do not expect - * kernel will check such case correctly. - * linux-2.6.18-128.1.1 miss to do that. - * --bug 17336 - */ - loff_t size = i_size_read(inode); - loff_t cur_index = start >> PAGE_CACHE_SHIFT; - loff_t size_index = (size - 1) >> - PAGE_CACHE_SHIFT; - - if ((size == 0 && cur_index != 0) || - size_index < cur_index) - *exceed = 1; - } - return result; - } - /* - * region is within kms and, hence, within real file - * size (A). We need to increase i_size to cover the - * read region so that generic_file_read() will do its - * job, but that doesn't mean the kms size is - * _correct_, it is only the _minimum_ size. If - * someone does a stat they will get the correct size - * which will always be >= the kms value here. - * b=11081 - */ - if (i_size_read(inode) < kms) { - i_size_write(inode, kms); - CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n", - PFID(lu_object_fid(&obj->co_lu)), - (__u64)i_size_read(inode)); - } - } - - vvp_object_size_unlock(obj); - - return result; -} - /***************************************************************************** * * Transfer operations. @@ -493,17 +307,6 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) * */ -struct vvp_io *cl2vvp_io(const struct lu_env *env, - const struct cl_io_slice *slice) -{ - struct vvp_io *vio; - - vio = container_of(slice, struct vvp_io, vui_cl); - LASSERT(vio == vvp_env_io(env)); - - return vio; -} - struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice) { return container_of0(slice, struct ccc_req, crq_cl); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 9856bb6daf15..86e93c04b12c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -693,7 +693,6 @@ void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras); int ll_readahead(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, struct ll_readahead_state *ras, bool hit); -int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io); struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage); void ll_cl_fini(struct ll_cl_context *lcc); diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index e04f23ea403e..7af8c445be77 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -164,12 +164,6 @@ struct vvp_io { bool vui_ra_valid; }; -/** - * True, if \a io is a normal io, False for other splice_{read,write}. - * must be implemented in arch specific code. - */ -int cl_is_normalio(const struct lu_env *env, const struct cl_io *io); - extern struct lu_context_key ccc_key; extern struct lu_context_key vvp_session_key; @@ -334,19 +328,6 @@ void ccc_umount(const struct lu_env *env, struct cl_device *dev); int ccc_global_init(struct lu_device_type *device_type); void ccc_global_fini(struct lu_device_type *device_type); -int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, - __u32 enqflags, enum cl_lock_mode mode, - pgoff_t start, pgoff_t end); -int vvp_io_one_lock(const struct lu_env *env, struct cl_io *io, - __u32 enqflags, enum cl_lock_mode mode, - loff_t start, loff_t end); -void vvp_io_end(const struct lu_env *env, const struct cl_io_slice *ios); -void vvp_io_advance(const struct lu_env *env, const struct cl_io_slice *ios, - size_t nob); -void vvp_io_update_iov(const struct lu_env *env, struct vvp_io *cio, - struct cl_io *io); -int ccc_prep_size(const struct lu_env *env, struct cl_object *obj, - struct cl_io *io, loff_t start, size_t count, int *exceed); void ccc_req_completion(const struct lu_env *env, const struct cl_req_slice *slice, int ioret); void ccc_req_attr_set(const struct lu_env *env, @@ -397,8 +378,6 @@ static inline struct vvp_lock *cl2vvp_lock(const struct cl_lock_slice *slice) return container_of(slice, struct vvp_lock, vlk_cl); } -struct vvp_io *cl2vvp_io(const struct lu_env *env, - const struct cl_io_slice *slice); struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice); int cl_setattr_ost(struct inode *inode, const struct iattr *attr); @@ -447,6 +426,7 @@ void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm); int vvp_io_init(const struct lu_env *env, struct cl_object *obj, struct cl_io *io); +int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io); int vvp_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io); int vvp_page_init(const struct lu_env *env, struct cl_object *obj, diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 53cf2be0e152..48b0693edb1f 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -47,10 +47,21 @@ #include "llite_internal.h" #include "vvp_internal.h" +struct vvp_io *cl2vvp_io(const struct lu_env *env, + const struct cl_io_slice *slice) +{ + struct vvp_io *vio; + + vio = container_of(slice, struct vvp_io, vui_cl); + LASSERT(vio == vvp_env_io(env)); + + return vio; +} + /** * True, if \a io is a normal io, False for splice_{read,write} */ -int cl_is_normalio(const struct lu_env *env, const struct cl_io *io) +static int cl_is_normalio(const struct lu_env *env, const struct cl_io *io) { struct vvp_io *vio = vvp_env_io(env); @@ -93,12 +104,160 @@ static bool can_populate_pages(const struct lu_env *env, struct cl_io *io, return rc; } +static void vvp_object_size_lock(struct cl_object *obj) +{ + struct inode *inode = vvp_object_inode(obj); + + ll_inode_size_lock(inode); + cl_object_attr_lock(obj); +} + +static void vvp_object_size_unlock(struct cl_object *obj) +{ + struct inode *inode = vvp_object_inode(obj); + + cl_object_attr_unlock(obj); + ll_inode_size_unlock(inode); +} + +/** + * Helper function that if necessary adjusts file size (inode->i_size), when + * position at the offset \a pos is accessed. File size can be arbitrary stale + * on a Lustre client, but client at least knows KMS. If accessed area is + * inside [0, KMS], set file size to KMS, otherwise glimpse file size. + * + * Locking: cl_isize_lock is used to serialize changes to inode size and to + * protect consistency between inode size and cl_object + * attributes. cl_object_size_lock() protects consistency between cl_attr's of + * top-object and sub-objects. + */ +static int vvp_prep_size(const struct lu_env *env, struct cl_object *obj, + struct cl_io *io, loff_t start, size_t count, + int *exceed) +{ + struct cl_attr *attr = ccc_env_thread_attr(env); + struct inode *inode = vvp_object_inode(obj); + loff_t pos = start + count - 1; + loff_t kms; + int result; + + /* + * Consistency guarantees: following possibilities exist for the + * relation between region being accessed and real file size at this + * moment: + * + * (A): the region is completely inside of the file; + * + * (B-x): x bytes of region are inside of the file, the rest is + * outside; + * + * (C): the region is completely outside of the file. + * + * This classification is stable under DLM lock already acquired by + * the caller, because to change the class, other client has to take + * DLM lock conflicting with our lock. Also, any updates to ->i_size + * by other threads on this client are serialized by + * ll_inode_size_lock(). This guarantees that short reads are handled + * correctly in the face of concurrent writes and truncates. + */ + vvp_object_size_lock(obj); + result = cl_object_attr_get(env, obj, attr); + if (result == 0) { + kms = attr->cat_kms; + if (pos > kms) { + /* + * A glimpse is necessary to determine whether we + * return a short read (B) or some zeroes at the end + * of the buffer (C) + */ + vvp_object_size_unlock(obj); + result = cl_glimpse_lock(env, io, inode, obj, 0); + if (result == 0 && exceed) { + /* If objective page index exceed end-of-file + * page index, return directly. Do not expect + * kernel will check such case correctly. + * linux-2.6.18-128.1.1 miss to do that. + * --bug 17336 + */ + loff_t size = i_size_read(inode); + loff_t cur_index = start >> PAGE_CACHE_SHIFT; + loff_t size_index = (size - 1) >> + PAGE_CACHE_SHIFT; + + if ((size == 0 && cur_index != 0) || + size_index < cur_index) + *exceed = 1; + } + return result; + } + /* + * region is within kms and, hence, within real file + * size (A). We need to increase i_size to cover the + * read region so that generic_file_read() will do its + * job, but that doesn't mean the kms size is + * _correct_, it is only the _minimum_ size. If + * someone does a stat they will get the correct size + * which will always be >= the kms value here. + * b=11081 + */ + if (i_size_read(inode) < kms) { + i_size_write(inode, kms); + CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n", + PFID(lu_object_fid(&obj->co_lu)), + (__u64)i_size_read(inode)); + } + } + + vvp_object_size_unlock(obj); + + return result; +} + /***************************************************************************** * * io operations. * */ +static int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, + __u32 enqflags, enum cl_lock_mode mode, + pgoff_t start, pgoff_t end) +{ + struct vvp_io *vio = vvp_env_io(env); + struct cl_lock_descr *descr = &vio->vui_link.cill_descr; + struct cl_object *obj = io->ci_obj; + + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); + + CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end); + + memset(&vio->vui_link, 0, sizeof(vio->vui_link)); + + if (vio->vui_fd && (vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { + descr->cld_mode = CLM_GROUP; + descr->cld_gid = vio->vui_fd->fd_grouplock.cg_gid; + } else { + descr->cld_mode = mode; + } + descr->cld_obj = obj; + descr->cld_start = start; + descr->cld_end = end; + descr->cld_enq_flags = enqflags; + + cl_io_lock_add(env, io, &vio->vui_link); + return 0; +} + +static int vvp_io_one_lock(const struct lu_env *env, struct cl_io *io, + __u32 enqflags, enum cl_lock_mode mode, + loff_t start, loff_t end) +{ + struct cl_object *obj = io->ci_obj; + + return vvp_io_one_lock_index(env, io, enqflags, mode, + cl_index(obj, start), cl_index(obj, end)); +} + static int vvp_io_write_iter_init(const struct lu_env *env, const struct cl_io_slice *ios) { @@ -303,6 +462,33 @@ static int vvp_mmap_locks(const struct lu_env *env, return result; } +static void vvp_io_advance(const struct lu_env *env, + const struct cl_io_slice *ios, + size_t nob) +{ + struct vvp_io *vio = cl2vvp_io(env, ios); + struct cl_io *io = ios->cis_io; + struct cl_object *obj = ios->cis_io->ci_obj; + + CLOBINVRNT(env, obj, vvp_object_invariant(obj)); + + if (!cl_is_normalio(env, io)) + return; + + iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count -= nob); +} + +static void vvp_io_update_iov(const struct lu_env *env, + struct vvp_io *vio, struct cl_io *io) +{ + size_t size = io->u.ci_rw.crw_count; + + if (!cl_is_normalio(env, io) || !vio->vui_iter) + return; + + iov_iter_truncate(vio->vui_iter, size); +} + static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, enum cl_lock_mode mode, loff_t start, loff_t end) { @@ -514,7 +700,7 @@ static int vvp_io_read_start(const struct lu_env *env, if (!can_populate_pages(env, io, inode)) return 0; - result = ccc_prep_size(env, obj, io, pos, tot, &exceed); + result = vvp_prep_size(env, obj, io, pos, tot, &exceed); if (result != 0) return result; else if (exceed != 0) @@ -886,7 +1072,7 @@ static int vvp_io_fault_start(const struct lu_env *env, /* offset of the last byte on the page */ offset = cl_offset(obj, fio->ft_index + 1) - 1; LASSERT(cl_index(obj, offset) == fio->ft_index); - result = ccc_prep_size(env, obj, io, 0, offset + 1, NULL); + result = vvp_prep_size(env, obj, io, 0, offset + 1, NULL); if (result != 0) return result; @@ -1075,6 +1261,12 @@ static int vvp_io_read_page(const struct lu_env *env, return 0; } +void vvp_io_end(const struct lu_env *env, const struct cl_io_slice *ios) +{ + CLOBINVRNT(env, ios->cis_io->ci_obj, + vvp_object_invariant(ios->cis_io->ci_obj)); +} + static const struct cl_io_operations vvp_io_ops = { .op = { [CIT_READ] = { -- GitLab From 103b8bda3e4be03e3d05ccb3c2ae5bb4a9182067 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Wed, 30 Mar 2016 19:48:54 -0400 Subject: [PATCH 0883/9938] staging/lustre/llite: rename ccc_req to vvp_req Rename struct ccc_req to struct vvp_req and move related functions from lustre/llite/lcommon_cl.c to the new file lustre/llite/vvp_req.c. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/13377 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Jinshan Xiong Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 2 +- drivers/staging/lustre/lustre/llite/Makefile | 3 +- .../staging/lustre/lustre/llite/lcommon_cl.c | 104 --------------- drivers/staging/lustre/lustre/llite/vvp_dev.c | 8 +- .../lustre/lustre/llite/vvp_internal.h | 18 +-- drivers/staging/lustre/lustre/llite/vvp_req.c | 121 ++++++++++++++++++ 6 files changed, 136 insertions(+), 120 deletions(-) create mode 100644 drivers/staging/lustre/lustre/llite/vvp_req.c diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 104dc9f15efb..918be65acdaf 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -140,7 +140,7 @@ struct cl_device_operations { * cl_req_slice_add(). * * \see osc_req_init(), lov_req_init(), lovsub_req_init() - * \see ccc_req_init() + * \see vvp_req_init() */ int (*cdo_req_init)(const struct lu_env *env, struct cl_device *dev, struct cl_req *req); diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index 24085e2624b4..2ce10ff01b80 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -5,6 +5,7 @@ lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ xattr.o xattr_cache.o remote_perm.o llite_rmtacl.o \ rw26.o super25.o statahead.o \ glimpse.o lcommon_cl.o lcommon_misc.o \ - vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o lproc_llite.o + vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o vvp_req.o \ + lproc_llite.o llite_lloop-y := lloop.o diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 1b1110349312..d28546a1728e 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -61,14 +61,11 @@ #include "../llite/llite_internal.h" -static const struct cl_req_operations ccc_req_ops; - /* * ccc_ prefix stands for "Common Client Code". */ static struct kmem_cache *ccc_thread_kmem; -static struct kmem_cache *ccc_req_kmem; static struct lu_kmem_descr ccc_caches[] = { { @@ -76,11 +73,6 @@ static struct lu_kmem_descr ccc_caches[] = { .ckd_name = "ccc_thread_kmem", .ckd_size = sizeof(struct ccc_thread_info), }, - { - .ckd_cache = &ccc_req_kmem, - .ckd_name = "ccc_req_kmem", - .ckd_size = sizeof(struct ccc_req) - }, { .ckd_cache = NULL } @@ -116,22 +108,6 @@ struct lu_context_key ccc_key = { .lct_fini = ccc_key_fini }; -int ccc_req_init(const struct lu_env *env, struct cl_device *dev, - struct cl_req *req) -{ - struct ccc_req *vrq; - int result; - - vrq = kmem_cache_zalloc(ccc_req_kmem, GFP_NOFS); - if (vrq) { - cl_req_slice_add(req, &vrq->crq_cl, dev, &ccc_req_ops); - result = 0; - } else { - result = -ENOMEM; - } - return result; -} - /** * An `emergency' environment used by ccc_inode_fini() when cl_env_get() * fails. Access to this environment is serialized by ccc_inode_fini_guard @@ -184,75 +160,6 @@ void ccc_global_fini(struct lu_device_type *device_type) lu_kmem_fini(ccc_caches); } -/***************************************************************************** - * - * Transfer operations. - * - */ - -void ccc_req_completion(const struct lu_env *env, - const struct cl_req_slice *slice, int ioret) -{ - struct ccc_req *vrq; - - if (ioret > 0) - cl_stats_tally(slice->crs_dev, slice->crs_req->crq_type, ioret); - - vrq = cl2ccc_req(slice); - kmem_cache_free(ccc_req_kmem, vrq); -} - -/** - * Implementation of struct cl_req_operations::cro_attr_set() for ccc - * layer. ccc is responsible for - * - * - o_[mac]time - * - * - o_mode - * - * - o_parent_seq - * - * - o_[ug]id - * - * - o_parent_oid - * - * - o_parent_ver - * - * - o_ioepoch, - * - */ -void ccc_req_attr_set(const struct lu_env *env, - const struct cl_req_slice *slice, - const struct cl_object *obj, - struct cl_req_attr *attr, u64 flags) -{ - struct inode *inode; - struct obdo *oa; - u32 valid_flags; - - oa = attr->cra_oa; - inode = vvp_object_inode(obj); - valid_flags = OBD_MD_FLTYPE; - - if (slice->crs_req->crq_type == CRT_WRITE) { - if (flags & OBD_MD_FLEPOCH) { - oa->o_valid |= OBD_MD_FLEPOCH; - oa->o_ioepoch = ll_i2info(inode)->lli_ioepoch; - valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME | - OBD_MD_FLUID | OBD_MD_FLGID; - } - } - obdo_from_inode(oa, inode, valid_flags & flags); - obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); - memcpy(attr->cra_jobid, ll_i2info(inode)->lli_jobid, - JOBSTATS_JOBID_SIZE); -} - -static const struct cl_req_operations ccc_req_ops = { - .cro_attr_set = ccc_req_attr_set, - .cro_completion = ccc_req_completion -}; - int cl_setattr_ost(struct inode *inode, const struct iattr *attr) { struct lu_env *env; @@ -301,17 +208,6 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) return result; } -/***************************************************************************** - * - * Type conversions. - * - */ - -struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice) -{ - return container_of0(slice, struct ccc_req, crq_cl); -} - /** * Initialize or update CLIO structures for regular files when new * meta-data arrives from the server. diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 030a2460cf24..5d3beb62423c 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -59,6 +59,7 @@ struct kmem_cache *vvp_lock_kmem; struct kmem_cache *vvp_object_kmem; +struct kmem_cache *vvp_req_kmem; static struct kmem_cache *vvp_thread_kmem; static struct kmem_cache *vvp_session_kmem; static struct lu_kmem_descr vvp_caches[] = { @@ -72,6 +73,11 @@ static struct lu_kmem_descr vvp_caches[] = { .ckd_name = "vvp_object_kmem", .ckd_size = sizeof(struct vvp_object), }, + { + .ckd_cache = &vvp_req_kmem, + .ckd_name = "vvp_req_kmem", + .ckd_size = sizeof(struct vvp_req), + }, { .ckd_cache = &vvp_thread_kmem, .ckd_name = "vvp_thread_kmem", @@ -145,7 +151,7 @@ static const struct lu_device_operations vvp_lu_ops = { }; static const struct cl_device_operations vvp_cl_ops = { - .cdo_req_init = ccc_req_init + .cdo_req_init = vvp_req_init }; static struct lu_device *vvp_device_free(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 7af8c445be77..99e7ef347069 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -169,6 +169,7 @@ extern struct lu_context_key vvp_session_key; extern struct kmem_cache *vvp_lock_kmem; extern struct kmem_cache *vvp_object_kmem; +extern struct kmem_cache *vvp_req_kmem; struct ccc_thread_info { struct cl_lock cti_lock; @@ -313,8 +314,8 @@ struct vvp_lock { struct cl_lock_slice vlk_cl; }; -struct ccc_req { - struct cl_req_slice crq_cl; +struct vvp_req { + struct cl_req_slice vrq_cl; }; void *ccc_key_init(const struct lu_context *ctx, @@ -322,19 +323,10 @@ void *ccc_key_init(const struct lu_context *ctx, void ccc_key_fini(const struct lu_context *ctx, struct lu_context_key *key, void *data); -int ccc_req_init(const struct lu_env *env, struct cl_device *dev, - struct cl_req *req); void ccc_umount(const struct lu_env *env, struct cl_device *dev); int ccc_global_init(struct lu_device_type *device_type); void ccc_global_fini(struct lu_device_type *device_type); -void ccc_req_completion(const struct lu_env *env, - const struct cl_req_slice *slice, int ioret); -void ccc_req_attr_set(const struct lu_env *env, - const struct cl_req_slice *slice, - const struct cl_object *obj, - struct cl_req_attr *oa, u64 flags); - static inline struct lu_device *vvp2lu_dev(struct vvp_device *vdv) { return &vdv->vdv_cl.cd_lu_dev; @@ -378,8 +370,6 @@ static inline struct vvp_lock *cl2vvp_lock(const struct cl_lock_slice *slice) return container_of(slice, struct vvp_lock, vlk_cl); } -struct ccc_req *cl2ccc_req(const struct cl_req_slice *slice); - int cl_setattr_ost(struct inode *inode, const struct iattr *attr); int cl_file_inode_init(struct inode *inode, struct lustre_md *md); @@ -431,6 +421,8 @@ int vvp_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io); int vvp_page_init(const struct lu_env *env, struct cl_object *obj, struct cl_page *page, pgoff_t index); +int vvp_req_init(const struct lu_env *env, struct cl_device *dev, + struct cl_req *req); struct lu_object *vvp_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); diff --git a/drivers/staging/lustre/lustre/llite/vvp_req.c b/drivers/staging/lustre/lustre/llite/vvp_req.c new file mode 100644 index 000000000000..fb886291a4e2 --- /dev/null +++ b/drivers/staging/lustre/lustre/llite/vvp_req.c @@ -0,0 +1,121 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2014, Intel Corporation. + */ + +#define DEBUG_SUBSYSTEM S_LLITE + +#include "../include/lustre/lustre_idl.h" +#include "../include/cl_object.h" +#include "../include/obd.h" +#include "../include/obd_support.h" +#include "../include/lustre_lite.h" +#include "llite_internal.h" +#include "vvp_internal.h" + +static inline struct vvp_req *cl2vvp_req(const struct cl_req_slice *slice) +{ + return container_of0(slice, struct vvp_req, vrq_cl); +} + +/** + * Implementation of struct cl_req_operations::cro_attr_set() for VVP + * layer. VVP is responsible for + * + * - o_[mac]time + * + * - o_mode + * + * - o_parent_seq + * + * - o_[ug]id + * + * - o_parent_oid + * + * - o_parent_ver + * + * - o_ioepoch, + * + */ +void vvp_req_attr_set(const struct lu_env *env, + const struct cl_req_slice *slice, + const struct cl_object *obj, + struct cl_req_attr *attr, u64 flags) +{ + struct inode *inode; + struct obdo *oa; + u32 valid_flags; + + oa = attr->cra_oa; + inode = vvp_object_inode(obj); + valid_flags = OBD_MD_FLTYPE; + + if (slice->crs_req->crq_type == CRT_WRITE) { + if (flags & OBD_MD_FLEPOCH) { + oa->o_valid |= OBD_MD_FLEPOCH; + oa->o_ioepoch = ll_i2info(inode)->lli_ioepoch; + valid_flags |= OBD_MD_FLMTIME | OBD_MD_FLCTIME | + OBD_MD_FLUID | OBD_MD_FLGID; + } + } + obdo_from_inode(oa, inode, valid_flags & flags); + obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); + memcpy(attr->cra_jobid, ll_i2info(inode)->lli_jobid, + JOBSTATS_JOBID_SIZE); +} + +void vvp_req_completion(const struct lu_env *env, + const struct cl_req_slice *slice, int ioret) +{ + struct vvp_req *vrq; + + if (ioret > 0) + cl_stats_tally(slice->crs_dev, slice->crs_req->crq_type, ioret); + + vrq = cl2vvp_req(slice); + kmem_cache_free(vvp_req_kmem, vrq); +} + +static const struct cl_req_operations vvp_req_ops = { + .cro_attr_set = vvp_req_attr_set, + .cro_completion = vvp_req_completion +}; + +int vvp_req_init(const struct lu_env *env, struct cl_device *dev, + struct cl_req *req) +{ + struct vvp_req *vrq; + int result; + + vrq = kmem_cache_zalloc(vvp_req_kmem, GFP_NOFS); + if (vrq) { + cl_req_slice_add(req, &vrq->vrq_cl, dev, &vvp_req_ops); + result = 0; + } else { + result = -ENOMEM; + } + return result; +} -- GitLab From 98eae5e71cdcf2954f9b022a78d0507878410df6 Mon Sep 17 00:00:00 2001 From: John Hammond Date: Wed, 30 Mar 2016 19:48:55 -0400 Subject: [PATCH 0884/9938] staging/lustre/llite: Rename struct ccc_grouplock to ll_grouplock And move the definition from vvp_internal.h to llite_internal.h. Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/13714 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Bobi Jam Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 16 ++++++------ .../lustre/lustre/llite/lcommon_misc.c | 26 +++++++++---------- .../lustre/lustre/llite/llite_internal.h | 14 +++++++++- .../lustre/lustre/llite/vvp_internal.h | 11 -------- drivers/staging/lustre/lustre/llite/vvp_io.c | 2 +- 5 files changed, 35 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 63aa080785d4..210d1e22660a 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -278,7 +278,7 @@ static int ll_md_close(struct obd_export *md_exp, struct inode *inode, /* clear group lock, if present */ if (unlikely(fd->fd_flags & LL_FILE_GROUP_LOCKED)) - ll_put_grouplock(inode, file, fd->fd_grouplock.cg_gid); + ll_put_grouplock(inode, file, fd->fd_grouplock.lg_gid); if (fd->fd_lease_och) { bool lease_broken; @@ -1570,7 +1570,7 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) { struct ll_inode_info *lli = ll_i2info(inode); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); - struct ccc_grouplock grouplock; + struct ll_grouplock grouplock; int rc; if (arg == 0) { @@ -1584,11 +1584,11 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) spin_lock(&lli->lli_lock); if (fd->fd_flags & LL_FILE_GROUP_LOCKED) { CWARN("group lock already existed with gid %lu\n", - fd->fd_grouplock.cg_gid); + fd->fd_grouplock.lg_gid); spin_unlock(&lli->lli_lock); return -EINVAL; } - LASSERT(!fd->fd_grouplock.cg_lock); + LASSERT(!fd->fd_grouplock.lg_lock); spin_unlock(&lli->lli_lock); rc = cl_get_grouplock(ll_i2info(inode)->lli_clob, @@ -1617,7 +1617,7 @@ static int ll_put_grouplock(struct inode *inode, struct file *file, { struct ll_inode_info *lli = ll_i2info(inode); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); - struct ccc_grouplock grouplock; + struct ll_grouplock grouplock; spin_lock(&lli->lli_lock); if (!(fd->fd_flags & LL_FILE_GROUP_LOCKED)) { @@ -1625,11 +1625,11 @@ static int ll_put_grouplock(struct inode *inode, struct file *file, CWARN("no group lock held\n"); return -EINVAL; } - LASSERT(fd->fd_grouplock.cg_lock); + LASSERT(fd->fd_grouplock.lg_lock); - if (fd->fd_grouplock.cg_gid != arg) { + if (fd->fd_grouplock.lg_gid != arg) { CWARN("group lock %lu doesn't match current id %lu\n", - arg, fd->fd_grouplock.cg_gid); + arg, fd->fd_grouplock.lg_gid); spin_unlock(&lli->lli_lock); return -EINVAL; } diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index 68e3db1f1b4c..5e3e43fe9550 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -42,8 +42,8 @@ #include "../include/obd.h" #include "../include/cl_object.h" -#include "vvp_internal.h" #include "../include/lustre_lite.h" +#include "llite_internal.h" /* Initialize the default and maximum LOV EA and cookie sizes. This allows * us to make MDS RPCs with large enough reply buffers to hold the @@ -126,7 +126,7 @@ int cl_ocd_update(struct obd_device *host, #define GROUPLOCK_SCOPE "grouplock" int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, - struct ccc_grouplock *cg) + struct ll_grouplock *cg) { struct lu_env *env; struct cl_io *io; @@ -172,25 +172,25 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, return rc; } - cg->cg_env = cl_env_get(&refcheck); - cg->cg_io = io; - cg->cg_lock = lock; - cg->cg_gid = gid; - LASSERT(cg->cg_env == env); + cg->lg_env = cl_env_get(&refcheck); + cg->lg_io = io; + cg->lg_lock = lock; + cg->lg_gid = gid; + LASSERT(cg->lg_env == env); cl_env_unplant(env, &refcheck); return 0; } -void cl_put_grouplock(struct ccc_grouplock *cg) +void cl_put_grouplock(struct ll_grouplock *cg) { - struct lu_env *env = cg->cg_env; - struct cl_io *io = cg->cg_io; - struct cl_lock *lock = cg->cg_lock; + struct lu_env *env = cg->lg_env; + struct cl_io *io = cg->lg_io; + struct cl_lock *lock = cg->lg_lock; int refcheck; - LASSERT(cg->cg_env); - LASSERT(cg->cg_gid); + LASSERT(cg->lg_env); + LASSERT(cg->lg_gid); cl_env_implant(env, &refcheck); cl_env_put(env, &refcheck); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 86e93c04b12c..8b943df111e1 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -99,6 +99,13 @@ struct ll_remote_perm { */ }; +struct ll_grouplock { + struct lu_env *lg_env; + struct cl_io *lg_io; + struct cl_lock *lg_lock; + unsigned long lg_gid; +}; + enum lli_flags { /* MDS has an authority for the Size-on-MDS attributes. */ LLIF_MDS_SIZE_LOCK = (1 << 0), @@ -612,7 +619,7 @@ extern struct kmem_cache *ll_file_data_slab; struct lustre_handle; struct ll_file_data { struct ll_readahead_state fd_ras; - struct ccc_grouplock fd_grouplock; + struct ll_grouplock fd_grouplock; __u64 lfd_pos; __u32 fd_flags; fmode_t fd_omode; @@ -655,6 +662,11 @@ static inline int ll_need_32bit_api(struct ll_sb_info *sbi) void ll_ras_enter(struct file *f); +/* llite/lcommon_misc.c */ +int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, + struct ll_grouplock *cg); +void cl_put_grouplock(struct ll_grouplock *cg); + /* llite/lproc_llite.c */ int ldebugfs_register_mountpoint(struct dentry *parent, struct super_block *sb, char *osc, char *mdc); diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 99e7ef347069..4740ff51a2b7 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -388,17 +388,6 @@ int cl_ocd_update(struct obd_device *host, struct obd_device *watched, enum obd_notify_event ev, void *owner, void *data); -struct ccc_grouplock { - struct lu_env *cg_env; - struct cl_io *cg_io; - struct cl_lock *cg_lock; - unsigned long cg_gid; -}; - -int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, - struct ccc_grouplock *cg); -void cl_put_grouplock(struct ccc_grouplock *cg); - /** * New interfaces to get and put lov_stripe_md from lov layer. This violates * layering because lov_stripe_md is supposed to be a private data in lov. diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 48b0693edb1f..18bc71b8777d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -235,7 +235,7 @@ static int vvp_io_one_lock_index(const struct lu_env *env, struct cl_io *io, if (vio->vui_fd && (vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { descr->cld_mode = CLM_GROUP; - descr->cld_gid = vio->vui_fd->fd_grouplock.cg_gid; + descr->cld_gid = vio->vui_fd->fd_grouplock.lg_gid; } else { descr->cld_mode = mode; } -- GitLab From 9989a58ee1b1e47008870e60583cefc105402cfa Mon Sep 17 00:00:00 2001 From: John Hammond Date: Wed, 30 Mar 2016 19:48:56 -0400 Subject: [PATCH 0885/9938] staging/lustre/llite: Rename struct vvp_thread_info to ll_thread_info struct vvp_thread_info is used in the non-VVP parts of llite so rename it struct ll_thread_info. Rename supporting functions accordingly. Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/13714 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Bobi Jam Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 6 +-- .../lustre/lustre/llite/llite_internal.h | 30 +++++++-------- drivers/staging/lustre/lustre/llite/rw.c | 6 +-- drivers/staging/lustre/lustre/llite/vvp_dev.c | 38 +++++++++---------- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 210d1e22660a..f7aabacb1f5c 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1221,7 +1221,7 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) if (IS_ERR(env)) return PTR_ERR(env); - args = vvp_env_args(env, IO_NORMAL); + args = ll_env_args(env, IO_NORMAL); args->u.normal.via_iter = to; args->u.normal.via_iocb = iocb; @@ -1245,7 +1245,7 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (IS_ERR(env)) return PTR_ERR(env); - args = vvp_env_args(env, IO_NORMAL); + args = ll_env_args(env, IO_NORMAL); args->u.normal.via_iter = from; args->u.normal.via_iocb = iocb; @@ -1271,7 +1271,7 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, if (IS_ERR(env)) return PTR_ERR(env); - args = vvp_env_args(env, IO_SPLICE); + args = ll_env_args(env, IO_SPLICE); args->u.splice.via_pipe = pipe; args->u.splice.via_flags = flags; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 8b943df111e1..a6ee2fe31fdc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -855,30 +855,30 @@ struct ll_cl_context { int lcc_refcheck; }; -struct vvp_thread_info { - struct vvp_io_args vti_args; - struct ra_io_arg vti_ria; - struct ll_cl_context vti_io_ctx; +struct ll_thread_info { + struct vvp_io_args lti_args; + struct ra_io_arg lti_ria; + struct ll_cl_context lti_io_ctx; }; -static inline struct vvp_thread_info *vvp_env_info(const struct lu_env *env) +extern struct lu_context_key ll_thread_key; +static inline struct ll_thread_info *ll_env_info(const struct lu_env *env) { - extern struct lu_context_key vvp_key; - struct vvp_thread_info *info; + struct ll_thread_info *lti; - info = lu_context_key_get(&env->le_ctx, &vvp_key); - LASSERT(info); - return info; + lti = lu_context_key_get(&env->le_ctx, &ll_thread_key); + LASSERT(lti); + return lti; } -static inline struct vvp_io_args *vvp_env_args(const struct lu_env *env, - enum vvp_io_subtype type) +static inline struct vvp_io_args *ll_env_args(const struct lu_env *env, + enum vvp_io_subtype type) { - struct vvp_io_args *ret = &vvp_env_info(env)->vti_args; + struct vvp_io_args *via = &ll_env_info(env)->lti_args; - ret->via_io_subtype = type; + via->via_io_subtype = type; - return ret; + return via; } int vvp_global_init(void); diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 634f0bb355e3..f9bc3e44b072 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -102,7 +102,7 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) if (IS_ERR(env)) return ERR_CAST(env); - lcc = &vvp_env_info(env)->vti_io_ctx; + lcc = &ll_env_info(env)->lti_io_ctx; memset(lcc, 0, sizeof(*lcc)); lcc->lcc_env = env; lcc->lcc_refcheck = refcheck; @@ -523,12 +523,12 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, bool hit) { struct vvp_io *vio = vvp_env_io(env); - struct vvp_thread_info *vti = vvp_env_info(env); + struct ll_thread_info *lti = ll_env_info(env); struct cl_attr *attr = ccc_env_thread_attr(env); unsigned long start = 0, end = 0, reserved; unsigned long ra_end, len, mlen = 0; struct inode *inode; - struct ra_io_arg *ria = &vti->vti_ria; + struct ra_io_arg *ria = <i->lti_ria; struct cl_object *clob; int ret = 0; __u64 kms; diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 5d3beb62423c..227843327f09 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -57,12 +57,17 @@ * "llite_" (var. "ll_") prefix. */ +static struct kmem_cache *ll_thread_kmem; struct kmem_cache *vvp_lock_kmem; struct kmem_cache *vvp_object_kmem; struct kmem_cache *vvp_req_kmem; -static struct kmem_cache *vvp_thread_kmem; static struct kmem_cache *vvp_session_kmem; static struct lu_kmem_descr vvp_caches[] = { + { + .ckd_cache = &ll_thread_kmem, + .ckd_name = "ll_thread_kmem", + .ckd_size = sizeof(struct ll_thread_info), + }, { .ckd_cache = &vvp_lock_kmem, .ckd_name = "vvp_lock_kmem", @@ -78,11 +83,6 @@ static struct lu_kmem_descr vvp_caches[] = { .ckd_name = "vvp_req_kmem", .ckd_size = sizeof(struct vvp_req), }, - { - .ckd_cache = &vvp_thread_kmem, - .ckd_name = "vvp_thread_kmem", - .ckd_size = sizeof(struct vvp_thread_info), - }, { .ckd_cache = &vvp_session_kmem, .ckd_name = "vvp_session_kmem", @@ -93,25 +93,31 @@ static struct lu_kmem_descr vvp_caches[] = { } }; -static void *vvp_key_init(const struct lu_context *ctx, - struct lu_context_key *key) +static void *ll_thread_key_init(const struct lu_context *ctx, + struct lu_context_key *key) { struct vvp_thread_info *info; - info = kmem_cache_zalloc(vvp_thread_kmem, GFP_NOFS); + info = kmem_cache_zalloc(ll_thread_kmem, GFP_NOFS); if (!info) info = ERR_PTR(-ENOMEM); return info; } -static void vvp_key_fini(const struct lu_context *ctx, - struct lu_context_key *key, void *data) +static void ll_thread_key_fini(const struct lu_context *ctx, + struct lu_context_key *key, void *data) { struct vvp_thread_info *info = data; - kmem_cache_free(vvp_thread_kmem, info); + kmem_cache_free(ll_thread_kmem, info); } +struct lu_context_key ll_thread_key = { + .lct_tags = LCT_CL_THREAD, + .lct_init = ll_thread_key_init, + .lct_fini = ll_thread_key_fini +}; + static void *vvp_session_key_init(const struct lu_context *ctx, struct lu_context_key *key) { @@ -131,12 +137,6 @@ static void vvp_session_key_fini(const struct lu_context *ctx, kmem_cache_free(vvp_session_kmem, session); } -struct lu_context_key vvp_key = { - .lct_tags = LCT_CL_THREAD, - .lct_init = vvp_key_init, - .lct_fini = vvp_key_fini -}; - struct lu_context_key vvp_session_key = { .lct_tags = LCT_SESSION, .lct_init = vvp_session_key_init, @@ -144,7 +144,7 @@ struct lu_context_key vvp_session_key = { }; /* type constructor/destructor: vvp_type_{init,fini,start,stop}(). */ -LU_TYPE_INIT_FINI(vvp, &ccc_key, &vvp_key, &vvp_session_key); +LU_TYPE_INIT_FINI(vvp, &ccc_key, &ll_thread_key, &vvp_session_key); static const struct lu_device_operations vvp_lu_ops = { .ldo_object_alloc = vvp_object_alloc -- GitLab From 9acc4500b44723d12bec63519038ef820479eaad Mon Sep 17 00:00:00 2001 From: John Hammond Date: Wed, 30 Mar 2016 19:48:57 -0400 Subject: [PATCH 0886/9938] staging/lustre/llite: rename struct ccc_thread_info to vvp_thread_info struct ccc_thread_info is used in the VVP parts of llite so rename it struct vvp_thread_info. Rename supporting functions accordingly. Move init code from lcommon_cl.c to vvp_dev.c Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/13714 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Bobi Jam Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 6 +-- drivers/staging/lustre/lustre/llite/glimpse.c | 6 +-- .../staging/lustre/lustre/llite/lcommon_cl.c | 48 +------------------ .../lustre/lustre/llite/lcommon_misc.c | 4 +- .../staging/lustre/lustre/llite/llite_mmap.c | 2 +- drivers/staging/lustre/lustre/llite/rw.c | 4 +- drivers/staging/lustre/lustre/llite/rw26.c | 2 +- drivers/staging/lustre/lustre/llite/vvp_dev.c | 34 ++++++++++++- .../lustre/lustre/llite/vvp_internal.h | 34 ++++++------- drivers/staging/lustre/lustre/llite/vvp_io.c | 8 ++-- 10 files changed, 68 insertions(+), 80 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index f7aabacb1f5c..69b56a816fcb 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -998,7 +998,7 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct cl_object *obj = lli->lli_clob; - struct cl_attr *attr = ccc_env_thread_attr(env); + struct cl_attr *attr = vvp_env_thread_attr(env); s64 atime; s64 mtime; s64 ctime; @@ -1131,7 +1131,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, file->f_path.dentry->d_name.name, iot, *ppos, count); restart: - io = ccc_env_thread_io(env); + io = vvp_env_thread_io(env); ll_io_init(io, file, iot == CIT_WRITE); if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { @@ -2612,7 +2612,7 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, if (IS_ERR(env)) return PTR_ERR(env); - io = ccc_env_thread_io(env); + io = vvp_env_thread_io(env); io->ci_obj = ll_i2info(inode)->lli_clob; io->ci_ignore_layout = ignore_layout; diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index d76fa163c362..d8ea75424e2f 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -93,7 +93,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) { CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid)); if (lli->lli_has_smd) { - struct cl_lock *lock = ccc_env_lock(env); + struct cl_lock *lock = vvp_env_lock(env); struct cl_lock_descr *descr = &lock->cll_descr; /* NOTE: this looks like DLM lock request, but it may @@ -163,7 +163,7 @@ static int cl_io_get(struct inode *inode, struct lu_env **envout, if (S_ISREG(inode->i_mode)) { env = cl_env_get(refcheck); if (!IS_ERR(env)) { - io = ccc_env_thread_io(env); + io = vvp_env_thread_io(env); io->ci_obj = clob; *envout = env; *ioout = io; @@ -238,7 +238,7 @@ int cl_local_size(struct inode *inode) if (result > 0) { result = io->ci_result; } else if (result == 0) { - struct cl_lock *lock = ccc_env_lock(env); + struct cl_lock *lock = vvp_env_lock(env); lock->cll_descr = whole_file; lock->cll_descr.cld_enq_flags = CEF_PEEK; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index d28546a1728e..5b523e338119 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -65,49 +65,12 @@ * ccc_ prefix stands for "Common Client Code". */ -static struct kmem_cache *ccc_thread_kmem; - -static struct lu_kmem_descr ccc_caches[] = { - { - .ckd_cache = &ccc_thread_kmem, - .ckd_name = "ccc_thread_kmem", - .ckd_size = sizeof(struct ccc_thread_info), - }, - { - .ckd_cache = NULL - } -}; - /***************************************************************************** * * Vvp device and device type functions. * */ -void *ccc_key_init(const struct lu_context *ctx, struct lu_context_key *key) -{ - struct ccc_thread_info *info; - - info = kmem_cache_zalloc(ccc_thread_kmem, GFP_NOFS); - if (!info) - info = ERR_PTR(-ENOMEM); - return info; -} - -void ccc_key_fini(const struct lu_context *ctx, - struct lu_context_key *key, void *data) -{ - struct ccc_thread_info *info = data; - - kmem_cache_free(ccc_thread_kmem, info); -} - -struct lu_context_key ccc_key = { - .lct_tags = LCT_CL_THREAD, - .lct_init = ccc_key_init, - .lct_fini = ccc_key_fini -}; - /** * An `emergency' environment used by ccc_inode_fini() when cl_env_get() * fails. Access to this environment is serialized by ccc_inode_fini_guard @@ -126,13 +89,9 @@ int ccc_global_init(struct lu_device_type *device_type) { int result; - result = lu_kmem_init(ccc_caches); - if (result) - return result; - result = lu_device_type_init(device_type); if (result) - goto out_kmem; + return result; ccc_inode_fini_env = cl_env_alloc(&dummy_refcheck, LCT_REMEMBER | LCT_NOREF); @@ -145,8 +104,6 @@ int ccc_global_init(struct lu_device_type *device_type) return 0; out_device: lu_device_type_fini(device_type); -out_kmem: - lu_kmem_fini(ccc_caches); return result; } @@ -157,7 +114,6 @@ void ccc_global_fini(struct lu_device_type *device_type) ccc_inode_fini_env = NULL; } lu_device_type_fini(device_type); - lu_kmem_fini(ccc_caches); } int cl_setattr_ost(struct inode *inode, const struct iattr *attr) @@ -171,7 +127,7 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) if (IS_ERR(env)) return PTR_ERR(env); - io = ccc_env_thread_io(env); + io = vvp_env_thread_io(env); io->ci_obj = ll_i2info(inode)->lli_clob; io->u.ci_setattr.sa_attr.lvb_atime = LTIME_S(attr->ia_atime); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index 5e3e43fe9550..12f3e71f48c2 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -140,7 +140,7 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, if (IS_ERR(env)) return PTR_ERR(env); - io = ccc_env_thread_io(env); + io = vvp_env_thread_io(env); io->ci_obj = obj; io->ci_ignore_layout = 1; @@ -154,7 +154,7 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, return rc; } - lock = ccc_env_lock(env); + lock = vvp_env_lock(env); descr = &lock->cll_descr; descr->cld_obj = obj; descr->cld_start = 0; diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index a7693c55cc46..83d7006546dc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -123,7 +123,7 @@ ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret, *env_ret = env; - io = ccc_env_thread_io(env); + io = vvp_env_thread_io(env); io->ci_obj = ll_i2info(inode)->lli_clob; LASSERT(io->ci_obj); diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index f9bc3e44b072..7d5dd3848552 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -524,7 +524,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, { struct vvp_io *vio = vvp_env_io(env); struct ll_thread_info *lti = ll_env_info(env); - struct cl_attr *attr = ccc_env_thread_attr(env); + struct cl_attr *attr = vvp_env_thread_attr(env); unsigned long start = 0, end = 0, reserved; unsigned long ra_end, len, mlen = 0; struct inode *inode; @@ -999,7 +999,7 @@ int ll_writepage(struct page *vmpage, struct writeback_control *wbc) clob = ll_i2info(inode)->lli_clob; LASSERT(clob); - io = ccc_env_thread_io(env); + io = vvp_env_thread_io(env); io->ci_obj = clob; io->ci_ignore_layout = 1; result = cl_io_init(env, io, CIT_MISC, clob); diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 106473eb4117..65baeebead72 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -455,7 +455,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, static int ll_prepare_partial_page(const struct lu_env *env, struct cl_io *io, struct cl_page *pg) { - struct cl_attr *attr = ccc_env_thread_attr(env); + struct cl_attr *attr = vvp_env_thread_attr(env); struct cl_object *obj = io->ci_obj; struct vvp_page *vpg = cl_object_page_slice(obj, pg); loff_t offset = cl_offset(obj, vvp_index(vpg)); diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 227843327f09..b33cd3502d8c 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -62,6 +62,8 @@ struct kmem_cache *vvp_lock_kmem; struct kmem_cache *vvp_object_kmem; struct kmem_cache *vvp_req_kmem; static struct kmem_cache *vvp_session_kmem; +static struct kmem_cache *vvp_thread_kmem; + static struct lu_kmem_descr vvp_caches[] = { { .ckd_cache = &ll_thread_kmem, @@ -88,6 +90,11 @@ static struct lu_kmem_descr vvp_caches[] = { .ckd_name = "vvp_session_kmem", .ckd_size = sizeof(struct vvp_session) }, + { + .ckd_cache = &vvp_thread_kmem, + .ckd_name = "vvp_thread_kmem", + .ckd_size = sizeof(struct vvp_thread_info), + }, { .ckd_cache = NULL } @@ -143,8 +150,33 @@ struct lu_context_key vvp_session_key = { .lct_fini = vvp_session_key_fini }; +void *vvp_thread_key_init(const struct lu_context *ctx, + struct lu_context_key *key) +{ + struct vvp_thread_info *vti; + + vti = kmem_cache_zalloc(vvp_thread_kmem, GFP_NOFS); + if (!vti) + vti = ERR_PTR(-ENOMEM); + return vti; +} + +void vvp_thread_key_fini(const struct lu_context *ctx, + struct lu_context_key *key, void *data) +{ + struct vvp_thread_info *vti = data; + + kmem_cache_free(vvp_thread_kmem, vti); +} + +struct lu_context_key vvp_thread_key = { + .lct_tags = LCT_CL_THREAD, + .lct_init = vvp_thread_key_init, + .lct_fini = vvp_thread_key_fini +}; + /* type constructor/destructor: vvp_type_{init,fini,start,stop}(). */ -LU_TYPE_INIT_FINI(vvp, &ccc_key, &ll_thread_key, &vvp_session_key); +LU_TYPE_INIT_FINI(vvp, &vvp_thread_key, &ll_thread_key, &vvp_session_key); static const struct lu_device_operations vvp_lu_ops = { .ldo_object_alloc = vvp_object_alloc diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 4740ff51a2b7..0e15202a0789 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -164,50 +164,50 @@ struct vvp_io { bool vui_ra_valid; }; -extern struct lu_context_key ccc_key; extern struct lu_context_key vvp_session_key; +extern struct lu_context_key vvp_thread_key; extern struct kmem_cache *vvp_lock_kmem; extern struct kmem_cache *vvp_object_kmem; extern struct kmem_cache *vvp_req_kmem; -struct ccc_thread_info { - struct cl_lock cti_lock; - struct cl_lock_descr cti_descr; - struct cl_io cti_io; - struct cl_attr cti_attr; +struct vvp_thread_info { + struct cl_lock vti_lock; + struct cl_lock_descr vti_descr; + struct cl_io vti_io; + struct cl_attr vti_attr; }; -static inline struct ccc_thread_info *ccc_env_info(const struct lu_env *env) +static inline struct vvp_thread_info *vvp_env_info(const struct lu_env *env) { - struct ccc_thread_info *info; + struct vvp_thread_info *vti; - info = lu_context_key_get(&env->le_ctx, &ccc_key); - LASSERT(info); + vti = lu_context_key_get(&env->le_ctx, &vvp_thread_key); + LASSERT(vti); - return info; + return vti; } -static inline struct cl_lock *ccc_env_lock(const struct lu_env *env) +static inline struct cl_lock *vvp_env_lock(const struct lu_env *env) { - struct cl_lock *lock = &ccc_env_info(env)->cti_lock; + struct cl_lock *lock = &vvp_env_info(env)->vti_lock; memset(lock, 0, sizeof(*lock)); return lock; } -static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) +static inline struct cl_attr *vvp_env_thread_attr(const struct lu_env *env) { - struct cl_attr *attr = &ccc_env_info(env)->cti_attr; + struct cl_attr *attr = &vvp_env_info(env)->vti_attr; memset(attr, 0, sizeof(*attr)); return attr; } -static inline struct cl_io *ccc_env_thread_io(const struct lu_env *env) +static inline struct cl_io *vvp_env_thread_io(const struct lu_env *env) { - struct cl_io *io = &ccc_env_info(env)->cti_io; + struct cl_io *io = &vvp_env_info(env)->vti_io; memset(io, 0, sizeof(*io)); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 18bc71b8777d..366ac1cc0e77 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -135,7 +135,7 @@ static int vvp_prep_size(const struct lu_env *env, struct cl_object *obj, struct cl_io *io, loff_t start, size_t count, int *exceed) { - struct cl_attr *attr = ccc_env_thread_attr(env); + struct cl_attr *attr = vvp_env_thread_attr(env); struct inode *inode = vvp_object_inode(obj); loff_t pos = start + count - 1; loff_t kms; @@ -382,10 +382,10 @@ static enum cl_lock_mode vvp_mode_from_vma(struct vm_area_struct *vma) static int vvp_mmap_locks(const struct lu_env *env, struct vvp_io *vio, struct cl_io *io) { - struct ccc_thread_info *cti = ccc_env_info(env); + struct vvp_thread_info *cti = vvp_env_info(env); struct mm_struct *mm = current->mm; struct vm_area_struct *vma; - struct cl_lock_descr *descr = &cti->cti_descr; + struct cl_lock_descr *descr = &cti->vti_descr; ldlm_policy_data_t policy; unsigned long addr; ssize_t count; @@ -621,7 +621,7 @@ static int vvp_io_setattr_time(const struct lu_env *env, { struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; - struct cl_attr *attr = ccc_env_thread_attr(env); + struct cl_attr *attr = vvp_env_thread_attr(env); int result; unsigned valid = CAT_CTIME; -- GitLab From a37bec74c4aa12849c0e4733c86d9377ad15e58a Mon Sep 17 00:00:00 2001 From: John Hammond Date: Wed, 30 Mar 2016 19:48:58 -0400 Subject: [PATCH 0887/9938] staging/lustre/llite: Remove ccc_global_{init, fini}() Merge their contents into vvp_global_{init,fini}() and {init,exit}_lustre_lite(). Rename ccc_inode_fini_* to cl_inode_fini_*. Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/13714 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Bobi Jam Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/llite/lcommon_cl.c | 53 ++++--------------- .../lustre/lustre/llite/llite_internal.h | 7 +-- drivers/staging/lustre/lustre/llite/super25.c | 14 ++++- drivers/staging/lustre/lustre/llite/vvp_dev.c | 25 +++++---- .../lustre/lustre/llite/vvp_internal.h | 4 +- 5 files changed, 46 insertions(+), 57 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 5b523e338119..164737a16865 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -72,49 +72,18 @@ */ /** - * An `emergency' environment used by ccc_inode_fini() when cl_env_get() - * fails. Access to this environment is serialized by ccc_inode_fini_guard + * An `emergency' environment used by cl_inode_fini() when cl_env_get() + * fails. Access to this environment is serialized by cl_inode_fini_guard * mutex. */ -static struct lu_env *ccc_inode_fini_env; +struct lu_env *cl_inode_fini_env; +int cl_inode_fini_refcheck; /** * A mutex serializing calls to slp_inode_fini() under extreme memory * pressure, when environments cannot be allocated. */ -static DEFINE_MUTEX(ccc_inode_fini_guard); -static int dummy_refcheck; - -int ccc_global_init(struct lu_device_type *device_type) -{ - int result; - - result = lu_device_type_init(device_type); - if (result) - return result; - - ccc_inode_fini_env = cl_env_alloc(&dummy_refcheck, - LCT_REMEMBER | LCT_NOREF); - if (IS_ERR(ccc_inode_fini_env)) { - result = PTR_ERR(ccc_inode_fini_env); - goto out_device; - } - - ccc_inode_fini_env->le_ctx.lc_cookie = 0x4; - return 0; -out_device: - lu_device_type_fini(device_type); - return result; -} - -void ccc_global_fini(struct lu_device_type *device_type) -{ - if (ccc_inode_fini_env) { - cl_env_put(ccc_inode_fini_env, &dummy_refcheck); - ccc_inode_fini_env = NULL; - } - lu_device_type_fini(device_type); -} +static DEFINE_MUTEX(cl_inode_fini_guard); int cl_setattr_ost(struct inode *inode, const struct iattr *attr) { @@ -286,10 +255,10 @@ void cl_inode_fini(struct inode *inode) env = cl_env_get(&refcheck); emergency = IS_ERR(env); if (emergency) { - mutex_lock(&ccc_inode_fini_guard); - LASSERT(ccc_inode_fini_env); - cl_env_implant(ccc_inode_fini_env, &refcheck); - env = ccc_inode_fini_env; + mutex_lock(&cl_inode_fini_guard); + LASSERT(cl_inode_fini_env); + cl_env_implant(cl_inode_fini_env, &refcheck); + env = cl_inode_fini_env; } /* * cl_object cache is a slave to inode cache (which, in turn @@ -301,8 +270,8 @@ void cl_inode_fini(struct inode *inode) cl_object_put_last(env, clob); lli->lli_clob = NULL; if (emergency) { - cl_env_unplant(ccc_inode_fini_env, &refcheck); - mutex_unlock(&ccc_inode_fini_guard); + cl_env_unplant(cl_inode_fini_env, &refcheck); + mutex_unlock(&cl_inode_fini_guard); } else { cl_env_put(env, &refcheck); } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index a6ee2fe31fdc..993cee818dc2 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -984,9 +984,6 @@ void free_rmtperm_hash(struct hlist_head *hash); int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm); int lustre_check_remote_perm(struct inode *inode, int mask); -/* llite/llite_cl.c */ -extern struct lu_device_type vvp_device_type; - /** * Common IO arguments for various VFS I/O interfaces. */ @@ -1371,4 +1368,8 @@ void ll_xattr_fini(void); int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, struct cl_page *page, enum cl_req_type crt); +/* lcommon_cl.c */ +extern struct lu_env *cl_inode_fini_env; +extern int cl_inode_fini_refcheck; + #endif /* LLITE_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 61856d37afc5..415750b0bff4 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -164,9 +164,18 @@ static int __init lustre_init(void) if (rc != 0) goto out_sysfs; + cl_inode_fini_env = cl_env_alloc(&cl_inode_fini_refcheck, + LCT_REMEMBER | LCT_NOREF); + if (IS_ERR(cl_inode_fini_env)) { + rc = PTR_ERR(cl_inode_fini_env); + goto out_vvp; + } + + cl_inode_fini_env->le_ctx.lc_cookie = 0x4; + rc = ll_xattr_init(); if (rc != 0) - goto out_vvp; + goto out_inode_fini_env; lustre_register_client_fill_super(ll_fill_super); lustre_register_kill_super_cb(ll_kill_super); @@ -174,6 +183,8 @@ static int __init lustre_init(void) return 0; +out_inode_fini_env: + cl_env_put(cl_inode_fini_env, &cl_inode_fini_refcheck); out_vvp: vvp_global_fini(); out_sysfs: @@ -198,6 +209,7 @@ static void __exit lustre_exit(void) kset_unregister(llite_kset); ll_xattr_fini(); + cl_env_put(cl_inode_fini_env, &cl_inode_fini_refcheck); vvp_global_fini(); kmem_cache_destroy(ll_inode_cachep); diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index b33cd3502d8c..e35c1a1f272e 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -293,20 +293,27 @@ struct lu_device_type vvp_device_type = { */ int vvp_global_init(void) { - int result; + int rc; - result = lu_kmem_init(vvp_caches); - if (result == 0) { - result = ccc_global_init(&vvp_device_type); - if (result != 0) - lu_kmem_fini(vvp_caches); - } - return result; + rc = lu_kmem_init(vvp_caches); + if (rc != 0) + return rc; + + rc = lu_device_type_init(&vvp_device_type); + if (rc != 0) + goto out_kmem; + + return 0; + +out_kmem: + lu_kmem_fini(vvp_caches); + + return rc; } void vvp_global_fini(void) { - ccc_global_fini(&vvp_device_type); + lu_device_type_fini(&vvp_device_type); lu_kmem_fini(vvp_caches); } diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 0e15202a0789..fe29fb53832c 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -164,6 +164,8 @@ struct vvp_io { bool vui_ra_valid; }; +extern struct lu_device_type vvp_device_type; + extern struct lu_context_key vvp_session_key; extern struct lu_context_key vvp_thread_key; @@ -324,8 +326,6 @@ void ccc_key_fini(const struct lu_context *ctx, struct lu_context_key *key, void *data); void ccc_umount(const struct lu_env *env, struct cl_device *dev); -int ccc_global_init(struct lu_device_type *device_type); -void ccc_global_fini(struct lu_device_type *device_type); static inline struct lu_device *vvp2lu_dev(struct vvp_device *vdv) { -- GitLab From 0097dcabe6d8f91d85f59b442cd162c02b8827f4 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 30 Mar 2016 19:48:59 -0400 Subject: [PATCH 0888/9938] staging/lustre/llite: Move ll_dirent_type_get and make it static ll_dirent_type_get is only used in one place in llite/dir.c, so move it there. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 22 +++++++++++++++++++ .../staging/lustre/lustre/llite/lcommon_cl.c | 22 ------------------- .../lustre/lustre/llite/vvp_internal.h | 1 - 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 2ca4b0ef82ad..b085fb4ffc56 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -469,6 +469,28 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash, goto out_unlock; } +/** + * return IF_* type for given lu_dirent entry. + * IF_* flag shld be converted to particular OS file type in + * platform llite module. + */ +static __u16 ll_dirent_type_get(struct lu_dirent *ent) +{ + __u16 type = 0; + struct luda_type *lt; + int len = 0; + + if (le32_to_cpu(ent->lde_attrs) & LUDA_TYPE) { + const unsigned int align = sizeof(struct luda_type) - 1; + + len = le16_to_cpu(ent->lde_namelen); + len = (len + align) & ~align; + lt = (void *)ent->lde_name + len; + type = IFTODT(le16_to_cpu(lt->lt_type)); + } + return type; +} + int ll_dir_read(struct inode *inode, struct dir_context *ctx) { struct ll_inode_info *info = ll_i2info(inode); diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 164737a16865..6c00715b438f 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -279,28 +279,6 @@ void cl_inode_fini(struct inode *inode) } } -/** - * return IF_* type for given lu_dirent entry. - * IF_* flag shld be converted to particular OS file type in - * platform llite module. - */ -__u16 ll_dirent_type_get(struct lu_dirent *ent) -{ - __u16 type = 0; - struct luda_type *lt; - int len = 0; - - if (le32_to_cpu(ent->lde_attrs) & LUDA_TYPE) { - const unsigned int align = sizeof(struct luda_type) - 1; - - len = le16_to_cpu(ent->lde_namelen); - len = (len + align) & ~align; - lt = (void *)ent->lde_name + len; - type = IFTODT(le16_to_cpu(lt->lt_type)); - } - return type; -} - /** * build inode number from passed @fid */ diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index fe29fb53832c..06e2726a472f 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -376,7 +376,6 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md); void cl_inode_fini(struct inode *inode); int cl_local_size(struct inode *inode); -__u16 ll_dirent_type_get(struct lu_dirent *ent); __u64 cl_fid_build_ino(const struct lu_fid *fid, int api32); __u32 cl_fid_build_gen(const struct lu_fid *fid); -- GitLab From 5c5af0fce77e480930fbb17de458c327f405b965 Mon Sep 17 00:00:00 2001 From: John Hammond Date: Wed, 30 Mar 2016 19:49:00 -0400 Subject: [PATCH 0889/9938] staging/lustre/llite: Move several declarations to llite_internal.h Move several declarations between llite_internal.h and vvp_internal.h with the goal of reserving the latter header for functions that pertain to vvp_{device,object,page,...}. Signed-off-by: John L. Hammond Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/13714 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5971 Reviewed-by: Bobi Jam Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/llite/llite_internal.h | 32 +++++++++++++++-- .../lustre/lustre/llite/vvp_internal.h | 36 ++----------------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 993cee818dc2..ba24f09ba1f9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -663,6 +663,10 @@ static inline int ll_need_32bit_api(struct ll_sb_info *sbi) void ll_ras_enter(struct file *f); /* llite/lcommon_misc.c */ +int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp); +int cl_ocd_update(struct obd_device *host, + struct obd_device *watched, + enum obd_notify_event ev, void *owner, void *data); int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, struct ll_grouplock *cg); void cl_put_grouplock(struct ll_grouplock *cg); @@ -881,9 +885,6 @@ static inline struct vvp_io_args *ll_env_args(const struct lu_env *env, return via; } -int vvp_global_init(void); -void vvp_global_fini(void); - void ll_queue_done_writing(struct inode *inode, unsigned long flags); void ll_close_thread_shutdown(struct ll_close_queue *lcq); int ll_close_thread_start(struct ll_close_queue **lcq_ret); @@ -1089,6 +1090,22 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentry, int only_unplug); void ll_stop_statahead(struct inode *dir, void *key); +blkcnt_t dirty_cnt(struct inode *inode); + +int cl_glimpse_size0(struct inode *inode, int agl); +int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, + struct inode *inode, struct cl_object *clob, int agl); + +static inline int cl_glimpse_size(struct inode *inode) +{ + return cl_glimpse_size0(inode, 0); +} + +static inline int cl_agl(struct inode *inode) +{ + return cl_glimpse_size0(inode, 1); +} + static inline int ll_glimpse_size(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1369,7 +1386,16 @@ int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, struct cl_page *page, enum cl_req_type crt); /* lcommon_cl.c */ +int cl_setattr_ost(struct inode *inode, const struct iattr *attr); + extern struct lu_env *cl_inode_fini_env; extern int cl_inode_fini_refcheck; +int cl_file_inode_init(struct inode *inode, struct lustre_md *md); +void cl_inode_fini(struct inode *inode); +int cl_local_size(struct inode *inode); + +__u64 cl_fid_build_ino(const struct lu_fid *fid, int api32); +__u32 cl_fid_build_gen(const struct lu_fid *fid); + #endif /* LLITE_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 06e2726a472f..ce4aeca1b0fb 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -53,25 +53,6 @@ struct obd_device; struct obd_export; struct page; -blkcnt_t dirty_cnt(struct inode *inode); - -int cl_glimpse_size0(struct inode *inode, int agl); -int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, - struct inode *inode, struct cl_object *clob, int agl); - -static inline int cl_glimpse_size(struct inode *inode) -{ - return cl_glimpse_size0(inode, 0); -} - -static inline int cl_agl(struct inode *inode) -{ - return cl_glimpse_size0(inode, 1); -} - -/** - * Locking policy for setattr. - */ enum ccc_setattr_lock_type { /** Locking is done by server */ SETATTR_NOLOCK, @@ -370,23 +351,9 @@ static inline struct vvp_lock *cl2vvp_lock(const struct cl_lock_slice *slice) return container_of(slice, struct vvp_lock, vlk_cl); } -int cl_setattr_ost(struct inode *inode, const struct iattr *attr); - -int cl_file_inode_init(struct inode *inode, struct lustre_md *md); -void cl_inode_fini(struct inode *inode); -int cl_local_size(struct inode *inode); - -__u64 cl_fid_build_ino(const struct lu_fid *fid, int api32); -__u32 cl_fid_build_gen(const struct lu_fid *fid); - # define CLOBINVRNT(env, clob, expr) \ ((void)sizeof(env), (void)sizeof(clob), (void)sizeof(!!(expr))) -int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp); -int cl_ocd_update(struct obd_device *host, - struct obd_device *watched, - enum obd_notify_event ev, void *owner, void *data); - /** * New interfaces to get and put lov_stripe_md from lov layer. This violates * layering because lov_stripe_md is supposed to be a private data in lov. @@ -415,6 +382,9 @@ struct lu_object *vvp_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); +int vvp_global_init(void); +void vvp_global_fini(void); + extern const struct file_operations vvp_dump_pgcache_file_ops; #endif /* VVP_INTERNAL_H */ -- GitLab From 047d41bd71c5553bdd5bda56edbc77b8cbc1ae87 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 30 Mar 2016 19:49:01 -0400 Subject: [PATCH 0890/9938] staging/lustre/llite: Remove unused vui_local_lock field vvp_io_setattr_lock is the only user that sets it, but it's never checked anywhere, so could go away. Also get rid of enum ccc_setattr_lock_type that becomes unused. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/vvp_internal.h | 12 ------------ drivers/staging/lustre/lustre/llite/vvp_io.c | 3 --- 2 files changed, 15 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index ce4aeca1b0fb..27b9b0a01f32 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -53,15 +53,6 @@ struct obd_device; struct obd_export; struct page; -enum ccc_setattr_lock_type { - /** Locking is done by server */ - SETATTR_NOLOCK, - /** Extent lock is enqueued */ - SETATTR_EXTENT_LOCK, - /** Existing local extent lock is used */ - SETATTR_MATCH_LOCK -}; - /* specific architecture can implement only part of this list */ enum vvp_io_subtype { /** normal IO */ @@ -111,9 +102,6 @@ struct vvp_io { */ bool ft_flags_valid; } fault; - struct { - enum ccc_setattr_lock_type vui_local_lock; - } setattr; struct { struct pipe_inode_info *vui_pipe; unsigned int vui_flags; diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 366ac1cc0e77..aed7b8e41a51 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -567,7 +567,6 @@ static int vvp_io_setattr_iter_init(const struct lu_env *env, static int vvp_io_setattr_lock(const struct lu_env *env, const struct cl_io_slice *ios) { - struct vvp_io *vio = vvp_env_io(env); struct cl_io *io = ios->cis_io; __u64 new_size; __u32 enqflags = 0; @@ -585,8 +584,6 @@ static int vvp_io_setattr_lock(const struct lu_env *env, new_size = 0; } - vio->u.setattr.vui_local_lock = SETATTR_EXTENT_LOCK; - return vvp_io_one_lock(env, io, enqflags, CLM_WRITE, new_size, OBD_OBJECT_EOF); } -- GitLab From 7d44333467a949b6ea4e21b5fb7618f97cc10ce0 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Wed, 30 Mar 2016 19:49:02 -0400 Subject: [PATCH 0891/9938] staging/lustre/ldlm: ELC picks locks in a safer policy Change the policy of ELC to pick locks that have no dirty pages, no page in writeback state, and no locked pages. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/9175 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4300 Reviewed-by: Andreas Dilger Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_dlm.h | 13 +++++---- .../staging/lustre/lustre/ldlm/ldlm_request.c | 28 +++++++++++++------ .../staging/lustre/lustre/mdc/mdc_request.c | 4 +-- drivers/staging/lustre/lustre/osc/osc_lock.c | 4 ++- .../staging/lustre/lustre/osc/osc_request.c | 19 +++++-------- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index b1abdc28b261..9cade144faca 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -270,7 +270,7 @@ struct ldlm_pool { struct completion pl_kobj_unregister; }; -typedef int (*ldlm_cancel_for_recovery)(struct ldlm_lock *lock); +typedef int (*ldlm_cancel_cbt)(struct ldlm_lock *lock); /** * LVB operations. @@ -447,8 +447,11 @@ struct ldlm_namespace { /** Limit of parallel AST RPC count. */ unsigned ns_max_parallel_ast; - /** Callback to cancel locks before replaying it during recovery. */ - ldlm_cancel_for_recovery ns_cancel_for_recovery; + /** + * Callback to check if a lock is good to be canceled by ELC or + * during recovery. + */ + ldlm_cancel_cbt ns_cancel; /** LDLM lock stats */ struct lprocfs_stats *ns_stats; @@ -480,9 +483,9 @@ static inline int ns_connect_lru_resize(struct ldlm_namespace *ns) } static inline void ns_register_cancel(struct ldlm_namespace *ns, - ldlm_cancel_for_recovery arg) + ldlm_cancel_cbt arg) { - ns->ns_cancel_for_recovery = arg; + ns->ns_cancel = arg; } struct ldlm_lock; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 42925ac3331c..2f12194aa6df 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1137,7 +1137,6 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, int count) { ldlm_policy_res_t result = LDLM_POLICY_CANCEL_LOCK; - ldlm_cancel_for_recovery cb = ns->ns_cancel_for_recovery; /* don't check added & count since we want to process all locks * from unused list. @@ -1147,7 +1146,7 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, switch (lock->l_resource->lr_type) { case LDLM_EXTENT: case LDLM_IBITS: - if (cb && cb(lock)) + if (ns->ns_cancel && ns->ns_cancel(lock) != 0) break; default: result = LDLM_POLICY_SKIP_LOCK; @@ -1197,8 +1196,13 @@ static ldlm_policy_res_t ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, /* Stop when SLV is not yet come from server or lv is smaller than * it is. */ - return (slv == 0 || lv < slv) ? - LDLM_POLICY_KEEP_LOCK : LDLM_POLICY_CANCEL_LOCK; + if (slv == 0 || lv < slv) + return LDLM_POLICY_KEEP_LOCK; + + if (ns->ns_cancel && ns->ns_cancel(lock) == 0) + return LDLM_POLICY_KEEP_LOCK; + + return LDLM_POLICY_CANCEL_LOCK; } /** @@ -1236,11 +1240,17 @@ static ldlm_policy_res_t ldlm_cancel_aged_policy(struct ldlm_namespace *ns, int unused, int added, int count) { - /* Stop LRU processing if young lock is found and we reach past count */ - return ((added >= count) && - time_before(cfs_time_current(), - cfs_time_add(lock->l_last_used, ns->ns_max_age))) ? - LDLM_POLICY_KEEP_LOCK : LDLM_POLICY_CANCEL_LOCK; + if (added >= count) + return LDLM_POLICY_KEEP_LOCK; + + if (time_before(cfs_time_current(), + cfs_time_add(lock->l_last_used, ns->ns_max_age))) + return LDLM_POLICY_KEEP_LOCK; + + if (ns->ns_cancel && ns->ns_cancel(lock) == 0) + return LDLM_POLICY_KEEP_LOCK; + + return LDLM_POLICY_CANCEL_LOCK; } /** diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 55dd8ef9525b..98b27f1f9915 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2249,7 +2249,7 @@ static struct obd_uuid *mdc_get_uuid(struct obd_export *exp) * recovery, non zero value will be return if the lock can be canceled, * or zero returned for not */ -static int mdc_cancel_for_recovery(struct ldlm_lock *lock) +static int mdc_cancel_weight(struct ldlm_lock *lock) { if (lock->l_resource->lr_type != LDLM_IBITS) return 0; @@ -2331,7 +2331,7 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg) sptlrpc_lprocfs_cliobd_attach(obd); ptlrpc_lprocfs_register_obd(obd); - ns_register_cancel(obd->obd_namespace, mdc_cancel_for_recovery); + ns_register_cancel(obd->obd_namespace, mdc_cancel_weight); obd->obd_namespace->ns_lvbo = &inode_lvbo; diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 68c5013fdc3e..49dfe9f8bc4b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -635,7 +635,9 @@ static int weigh_cb(const struct lu_env *env, struct cl_io *io, { struct cl_page *page = ops->ops_cl.cpl_page; - if (cl_page_is_vmlocked(env, page)) { + if (cl_page_is_vmlocked(env, page) || + PageDirty(page->cp_vmpage) || PageWriteback(page->cp_vmpage) + ) { (*(unsigned long *)cbdata)++; return CLP_GANG_ABORT; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 368b99719d48..a6dc517d178b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2292,15 +2292,13 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, if (*flags & LDLM_FL_TEST_LOCK) return -ENOLCK; if (intent) { - LIST_HEAD(cancels); - req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_ENQUEUE_LVB); if (!req) return -ENOMEM; - rc = ldlm_prep_enqueue_req(exp, req, &cancels, 0); - if (rc) { + rc = ptlrpc_request_pack(req, LUSTRE_DLM_VERSION, LDLM_ENQUEUE); + if (rc < 0) { ptlrpc_request_free(req); return rc; } @@ -3110,17 +3108,14 @@ static int osc_import_event(struct obd_device *obd, * \retval zero the lock can't be canceled * \retval other ok to cancel */ -static int osc_cancel_for_recovery(struct ldlm_lock *lock) +static int osc_cancel_weight(struct ldlm_lock *lock) { /* - * Cancel all unused extent lock in granted mode LCK_PR or LCK_CR. - * - * XXX as a future improvement, we can also cancel unused write lock - * if it doesn't have dirty data and active mmaps. + * Cancel all unused and granted extent lock. */ if (lock->l_resource->lr_type == LDLM_EXTENT && - (lock->l_granted_mode == LCK_PR || - lock->l_granted_mode == LCK_CR) && osc_ldlm_weigh_ast(lock) == 0) + lock->l_granted_mode == lock->l_req_mode && + osc_ldlm_weigh_ast(lock) == 0) return 1; return 0; @@ -3197,7 +3192,7 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) } INIT_LIST_HEAD(&cli->cl_grant_shrink_list); - ns_register_cancel(obd->obd_namespace, osc_cancel_for_recovery); + ns_register_cancel(obd->obd_namespace, osc_cancel_weight); return rc; out_ptlrpcd_work: -- GitLab From 7b2d26b0af8bcc44fb3a279f28f380010890c4a4 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Wed, 30 Mar 2016 19:49:03 -0400 Subject: [PATCH 0892/9938] staging/lustre/ldlm: revert changes to ldlm_cancel_aged_policy() The changes to ldlm_cancel_aged_policy() introduced from LU-4300 was incorrect. This patch revert this part of changes. Signed-off-by: Niu Yawei Reviewed-on: http://review.whamcloud.com/12448 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5727 Reviewed-by: Bobi Jam Reviewed-by: Jinshan Xiong Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 2f12194aa6df..48e982867db3 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1240,10 +1240,8 @@ static ldlm_policy_res_t ldlm_cancel_aged_policy(struct ldlm_namespace *ns, int unused, int added, int count) { - if (added >= count) - return LDLM_POLICY_KEEP_LOCK; - - if (time_before(cfs_time_current(), + if ((added >= count) && + time_before(cfs_time_current(), cfs_time_add(lock->l_last_used, ns->ns_max_age))) return LDLM_POLICY_KEEP_LOCK; -- GitLab From 2640256e388f8f5dd2f9fdbb034b3c0332e10e41 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman Date: Wed, 30 Mar 2016 19:49:04 -0400 Subject: [PATCH 0893/9938] staging/lustre/ldlm: restore the ELC for enqueue after LU-4300 enqueue does not ELC anymore, however if enqueue is agressive (ls -la of a large dir) we may exceed lru-resize limit quickly because LRUR shrinker and recalc are called not so often. ELC is to be restored in enqueue. ELC also should check for the lock weight, in addition to LRUR. ELC can also keep "skipped" locks, i.e. once checked for the weight and left in the lru - let LRUR take care about them later. LRUR is to be left untouched, no weight logic, otherwise LU-5727 appears and OPEN locks do not get canceled. Xyratex-bug-id: MRP-2550 Signed-off-by: Vitaly Fertman Reviewed-on: http://review.whamcloud.com/14342 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6390 Reviewed-by: Jinshan Xiong Reviewed-by: Niu Yawei Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/ldlm/ldlm_internal.h | 7 +++--- .../staging/lustre/lustre/ldlm/ldlm_request.c | 25 ++++++++++++++++--- .../staging/lustre/lustre/osc/osc_request.c | 4 +-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index e21373e7306f..e31d84aad4e4 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -95,9 +95,10 @@ enum { LDLM_CANCEL_PASSED = 1 << 1, /* Cancel passed number of locks. */ LDLM_CANCEL_SHRINK = 1 << 2, /* Cancel locks from shrinker. */ LDLM_CANCEL_LRUR = 1 << 3, /* Cancel locks from lru resize. */ - LDLM_CANCEL_NO_WAIT = 1 << 4 /* Cancel locks w/o blocking (neither - * sending nor waiting for any rpcs) - */ + LDLM_CANCEL_NO_WAIT = 1 << 4, /* Cancel locks w/o blocking (neither + * sending nor waiting for any rpcs) + */ + LDLM_CANCEL_LRUR_NO_WAIT = 1 << 5, /* LRUR + NO_WAIT */ }; int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 48e982867db3..9aa4c2dfe143 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -601,7 +601,7 @@ int ldlm_prep_elc_req(struct obd_export *exp, struct ptlrpc_request *req, avail = ldlm_capsule_handles_avail(pill, RCL_CLIENT, canceloff); flags = ns_connect_lru_resize(ns) ? - LDLM_CANCEL_LRUR : LDLM_CANCEL_AGED; + LDLM_CANCEL_LRUR_NO_WAIT : LDLM_CANCEL_AGED; to_free = !ns_connect_lru_resize(ns) && opc == LDLM_ENQUEUE ? 1 : 0; @@ -1146,7 +1146,7 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, switch (lock->l_resource->lr_type) { case LDLM_EXTENT: case LDLM_IBITS: - if (ns->ns_cancel && ns->ns_cancel(lock) != 0) + if (ns->ns_cancel && ns->ns_cancel(lock) != 0) break; default: result = LDLM_POLICY_SKIP_LOCK; @@ -1251,6 +1251,21 @@ static ldlm_policy_res_t ldlm_cancel_aged_policy(struct ldlm_namespace *ns, return LDLM_POLICY_CANCEL_LOCK; } +static ldlm_policy_res_t +ldlm_cancel_lrur_no_wait_policy(struct ldlm_namespace *ns, + struct ldlm_lock *lock, + int unused, int added, + int count) +{ + ldlm_policy_res_t result; + + result = ldlm_cancel_lrur_policy(ns, lock, unused, added, count); + if (result == LDLM_POLICY_KEEP_LOCK) + return result; + + return ldlm_cancel_no_wait_policy(ns, lock, unused, added, count); +} + /** * Callback function for default policy. Makes decision whether to keep \a lock * in LRU for current LRU size \a unused, added in current scan \a added and @@ -1290,6 +1305,8 @@ ldlm_cancel_lru_policy(struct ldlm_namespace *ns, int flags) return ldlm_cancel_lrur_policy; else if (flags & LDLM_CANCEL_PASSED) return ldlm_cancel_passed_policy; + else if (flags & LDLM_CANCEL_LRUR_NO_WAIT) + return ldlm_cancel_lrur_no_wait_policy; } else { if (flags & LDLM_CANCEL_AGED) return ldlm_cancel_aged_policy; @@ -1338,6 +1355,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, ldlm_cancel_lru_policy_t pf; struct ldlm_lock *lock, *next; int added = 0, unused, remained; + int no_wait = flags & (LDLM_CANCEL_NO_WAIT | LDLM_CANCEL_LRUR_NO_WAIT); spin_lock(&ns->ns_lock); unused = ns->ns_nr_unused; @@ -1365,8 +1383,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, /* No locks which got blocking requests. */ LASSERT(!(lock->l_flags & LDLM_FL_BL_AST)); - if (flags & LDLM_CANCEL_NO_WAIT && - lock->l_flags & LDLM_FL_SKIPPED) + if (no_wait && lock->l_flags & LDLM_FL_SKIPPED) /* already processed */ continue; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index a6dc517d178b..5b9f72c909b7 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2297,8 +2297,8 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, if (!req) return -ENOMEM; - rc = ptlrpc_request_pack(req, LUSTRE_DLM_VERSION, LDLM_ENQUEUE); - if (rc < 0) { + rc = ldlm_prep_enqueue_req(exp, req, NULL, 0); + if (rc) { ptlrpc_request_free(req); return rc; } -- GitLab From e9570b490ba209220b43530ca250060035d6bcba Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 30 Mar 2016 19:49:05 -0400 Subject: [PATCH 0894/9938] staging/lustre: Fix spacing style before open parenthesis This fixes the remaining occurences of checkpatch warnings of the form of WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/lu_object.h | 64 +++++++++---------- .../lustre/lustre/include/lustre/lustre_idl.h | 2 +- .../lustre/include/lustre/lustre_user.h | 36 +++++------ .../lustre/lustre/include/lustre_cfg.h | 2 +- .../lustre/lustre/include/lustre_import.h | 2 +- .../lustre/lustre/include/lustre_lib.h | 36 +++++------ .../staging/lustre/lustre/obdclass/debug.c | 4 +- .../lustre/lustre/osc/osc_cl_internal.h | 22 +++---- .../staging/lustre/lustre/osc/osc_request.c | 2 +- 9 files changed, 85 insertions(+), 85 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index b5088b13a305..fcb9db6e1f1a 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -656,21 +656,21 @@ static inline struct seq_server_site *lu_site2seq(const struct lu_site *s) * @{ */ -int lu_site_init (struct lu_site *s, struct lu_device *d); -void lu_site_fini (struct lu_site *s); -int lu_site_init_finish (struct lu_site *s); -void lu_stack_fini (const struct lu_env *env, struct lu_device *top); -void lu_device_get (struct lu_device *d); -void lu_device_put (struct lu_device *d); -int lu_device_init (struct lu_device *d, struct lu_device_type *t); -void lu_device_fini (struct lu_device *d); -int lu_object_header_init(struct lu_object_header *h); +int lu_site_init(struct lu_site *s, struct lu_device *d); +void lu_site_fini(struct lu_site *s); +int lu_site_init_finish(struct lu_site *s); +void lu_stack_fini(const struct lu_env *env, struct lu_device *top); +void lu_device_get(struct lu_device *d); +void lu_device_put(struct lu_device *d); +int lu_device_init(struct lu_device *d, struct lu_device_type *t); +void lu_device_fini(struct lu_device *d); +int lu_object_header_init(struct lu_object_header *h); void lu_object_header_fini(struct lu_object_header *h); -int lu_object_init (struct lu_object *o, - struct lu_object_header *h, struct lu_device *d); -void lu_object_fini (struct lu_object *o); -void lu_object_add_top (struct lu_object_header *h, struct lu_object *o); -void lu_object_add (struct lu_object *before, struct lu_object *o); +int lu_object_init(struct lu_object *o, + struct lu_object_header *h, struct lu_device *d); +void lu_object_fini(struct lu_object *o); +void lu_object_add_top(struct lu_object_header *h, struct lu_object *o); +void lu_object_add(struct lu_object *before, struct lu_object *o); /** * Helpers to initialize and finalize device types. @@ -1118,7 +1118,7 @@ struct lu_context_key { { \ type *value; \ \ - CLASSERT(PAGE_CACHE_SIZE >= sizeof (*value)); \ + CLASSERT(PAGE_CACHE_SIZE >= sizeof(*value)); \ \ value = kzalloc(sizeof(*value), GFP_NOFS); \ if (!value) \ @@ -1154,12 +1154,12 @@ do { \ (key)->lct_owner = THIS_MODULE; \ } while (0) -int lu_context_key_register(struct lu_context_key *key); -void lu_context_key_degister(struct lu_context_key *key); -void *lu_context_key_get (const struct lu_context *ctx, - const struct lu_context_key *key); -void lu_context_key_quiesce (struct lu_context_key *key); -void lu_context_key_revive (struct lu_context_key *key); +int lu_context_key_register(struct lu_context_key *key); +void lu_context_key_degister(struct lu_context_key *key); +void *lu_context_key_get(const struct lu_context *ctx, + const struct lu_context_key *key); +void lu_context_key_quiesce(struct lu_context_key *key); +void lu_context_key_revive(struct lu_context_key *key); /* * LU_KEY_INIT_GENERIC() has to be a macro to correctly determine an @@ -1216,21 +1216,21 @@ void lu_context_key_revive (struct lu_context_key *key); LU_TYPE_START(mod, __VA_ARGS__); \ LU_TYPE_STOP(mod, __VA_ARGS__) -int lu_context_init (struct lu_context *ctx, __u32 tags); -void lu_context_fini (struct lu_context *ctx); -void lu_context_enter (struct lu_context *ctx); -void lu_context_exit (struct lu_context *ctx); -int lu_context_refill(struct lu_context *ctx); +int lu_context_init(struct lu_context *ctx, __u32 tags); +void lu_context_fini(struct lu_context *ctx); +void lu_context_enter(struct lu_context *ctx); +void lu_context_exit(struct lu_context *ctx); +int lu_context_refill(struct lu_context *ctx); /* * Helper functions to operate on multiple keys. These are used by the default * device type operations, defined by LU_TYPE_INIT_FINI(). */ -int lu_context_key_register_many(struct lu_context_key *k, ...); +int lu_context_key_register_many(struct lu_context_key *k, ...); void lu_context_key_degister_many(struct lu_context_key *k, ...); -void lu_context_key_revive_many (struct lu_context_key *k, ...); -void lu_context_key_quiesce_many (struct lu_context_key *k, ...); +void lu_context_key_revive_many(struct lu_context_key *k, ...); +void lu_context_key_quiesce_many(struct lu_context_key *k, ...); /** * Environment. @@ -1246,9 +1246,9 @@ struct lu_env { struct lu_context *le_ses; }; -int lu_env_init (struct lu_env *env, __u32 tags); -void lu_env_fini (struct lu_env *env); -int lu_env_refill(struct lu_env *env); +int lu_env_init(struct lu_env *env, __u32 tags); +void lu_env_fini(struct lu_env *env); +int lu_env_refill(struct lu_env *env); /** @} lu_context */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 4318511de0c9..12e6718f2adb 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -3306,7 +3306,7 @@ struct getinfo_fid2path { char gf_path[0]; } __packed; -void lustre_swab_fid2path (struct getinfo_fid2path *gf); +void lustre_swab_fid2path(struct getinfo_fid2path *gf); enum { LAYOUT_INTENT_ACCESS = 0, diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 276906e646f5..19f2271cc6b9 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -193,37 +193,37 @@ struct ost_id { * *INFO - set/get lov_user_mds_data */ /* see for ioctl numberss 101-150 */ -#define LL_IOC_GETFLAGS _IOR ('f', 151, long) -#define LL_IOC_SETFLAGS _IOW ('f', 152, long) -#define LL_IOC_CLRFLAGS _IOW ('f', 153, long) +#define LL_IOC_GETFLAGS _IOR('f', 151, long) +#define LL_IOC_SETFLAGS _IOW('f', 152, long) +#define LL_IOC_CLRFLAGS _IOW('f', 153, long) /* LL_IOC_LOV_SETSTRIPE: See also OBD_IOC_LOV_SETSTRIPE */ -#define LL_IOC_LOV_SETSTRIPE _IOW ('f', 154, long) +#define LL_IOC_LOV_SETSTRIPE _IOW('f', 154, long) /* LL_IOC_LOV_GETSTRIPE: See also OBD_IOC_LOV_GETSTRIPE */ -#define LL_IOC_LOV_GETSTRIPE _IOW ('f', 155, long) +#define LL_IOC_LOV_GETSTRIPE _IOW('f', 155, long) /* LL_IOC_LOV_SETEA: See also OBD_IOC_LOV_SETEA */ -#define LL_IOC_LOV_SETEA _IOW ('f', 156, long) -#define LL_IOC_RECREATE_OBJ _IOW ('f', 157, long) -#define LL_IOC_RECREATE_FID _IOW ('f', 157, struct lu_fid) -#define LL_IOC_GROUP_LOCK _IOW ('f', 158, long) -#define LL_IOC_GROUP_UNLOCK _IOW ('f', 159, long) +#define LL_IOC_LOV_SETEA _IOW('f', 156, long) +#define LL_IOC_RECREATE_OBJ _IOW('f', 157, long) +#define LL_IOC_RECREATE_FID _IOW('f', 157, struct lu_fid) +#define LL_IOC_GROUP_LOCK _IOW('f', 158, long) +#define LL_IOC_GROUP_UNLOCK _IOW('f', 159, long) /* LL_IOC_QUOTACHECK: See also OBD_IOC_QUOTACHECK */ -#define LL_IOC_QUOTACHECK _IOW ('f', 160, int) +#define LL_IOC_QUOTACHECK _IOW('f', 160, int) /* LL_IOC_POLL_QUOTACHECK: See also OBD_IOC_POLL_QUOTACHECK */ -#define LL_IOC_POLL_QUOTACHECK _IOR ('f', 161, struct if_quotacheck *) +#define LL_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) /* LL_IOC_QUOTACTL: See also OBD_IOC_QUOTACTL */ #define LL_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) #define IOC_OBD_STATFS _IOWR('f', 164, struct obd_statfs *) #define IOC_LOV_GETINFO _IOWR('f', 165, struct lov_user_mds_data *) -#define LL_IOC_FLUSHCTX _IOW ('f', 166, long) -#define LL_IOC_RMTACL _IOW ('f', 167, long) -#define LL_IOC_GETOBDCOUNT _IOR ('f', 168, long) +#define LL_IOC_FLUSHCTX _IOW('f', 166, long) +#define LL_IOC_RMTACL _IOW('f', 167, long) +#define LL_IOC_GETOBDCOUNT _IOR('f', 168, long) #define LL_IOC_LLOOP_ATTACH _IOWR('f', 169, long) #define LL_IOC_LLOOP_DETACH _IOWR('f', 170, long) #define LL_IOC_LLOOP_INFO _IOWR('f', 171, struct lu_fid) #define LL_IOC_LLOOP_DETACH_BYDEV _IOWR('f', 172, long) -#define LL_IOC_PATH2FID _IOR ('f', 173, long) +#define LL_IOC_PATH2FID _IOR('f', 173, long) #define LL_IOC_GET_CONNECT_FLAGS _IOWR('f', 174, __u64 *) -#define LL_IOC_GET_MDTIDX _IOR ('f', 175, int) +#define LL_IOC_GET_MDTIDX _IOR('f', 175, int) /* see for ioctl numbers 177-210 */ @@ -1100,7 +1100,7 @@ struct hsm_action_list { } __packed; #ifndef HAVE_CFS_SIZE_ROUND -static inline int cfs_size_round (int val) +static inline int cfs_size_round(int val) { return (val + 7) & (~0x7); } diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index bb16ae980b98..e229e91f7f56 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -161,7 +161,7 @@ static inline void *lustre_cfg_buf(struct lustre_cfg *lcfg, int index) int offset; int bufcount; - LASSERT (index >= 0); + LASSERT(index >= 0); bufcount = lcfg->lcfg_bufcount; if (index >= bufcount) diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h index dac2d84d8266..8325c82b3ebf 100644 --- a/drivers/staging/lustre/lustre/include/lustre_import.h +++ b/drivers/staging/lustre/lustre/include/lustre_import.h @@ -109,7 +109,7 @@ static inline char *ptlrpc_import_state_name(enum lustre_imp_state state) "RECOVER", "FULL", "EVICTED", }; - LASSERT (state <= LUSTRE_IMP_EVICTED); + LASSERT(state <= LUSTRE_IMP_EVICTED); return import_state_names[state]; } diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index c5713d74486a..2e66b271b6e9 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -280,16 +280,16 @@ static inline void obd_ioctl_freedata(char *buf, int len) #define OBD_IOC_DATA_TYPE long #define OBD_IOC_CREATE _IOWR('f', 101, OBD_IOC_DATA_TYPE) -#define OBD_IOC_DESTROY _IOW ('f', 104, OBD_IOC_DATA_TYPE) +#define OBD_IOC_DESTROY _IOW('f', 104, OBD_IOC_DATA_TYPE) #define OBD_IOC_PREALLOCATE _IOWR('f', 105, OBD_IOC_DATA_TYPE) -#define OBD_IOC_SETATTR _IOW ('f', 107, OBD_IOC_DATA_TYPE) +#define OBD_IOC_SETATTR _IOW('f', 107, OBD_IOC_DATA_TYPE) #define OBD_IOC_GETATTR _IOWR ('f', 108, OBD_IOC_DATA_TYPE) #define OBD_IOC_READ _IOWR('f', 109, OBD_IOC_DATA_TYPE) #define OBD_IOC_WRITE _IOWR('f', 110, OBD_IOC_DATA_TYPE) #define OBD_IOC_STATFS _IOWR('f', 113, OBD_IOC_DATA_TYPE) -#define OBD_IOC_SYNC _IOW ('f', 114, OBD_IOC_DATA_TYPE) +#define OBD_IOC_SYNC _IOW('f', 114, OBD_IOC_DATA_TYPE) #define OBD_IOC_READ2 _IOWR('f', 115, OBD_IOC_DATA_TYPE) #define OBD_IOC_FORMAT _IOWR('f', 116, OBD_IOC_DATA_TYPE) #define OBD_IOC_PARTITION _IOWR('f', 117, OBD_IOC_DATA_TYPE) @@ -308,13 +308,13 @@ static inline void obd_ioctl_freedata(char *buf, int len) #define OBD_IOC_GETDTNAME OBD_IOC_GETNAME #define OBD_IOC_LOV_GET_CONFIG _IOWR('f', 132, OBD_IOC_DATA_TYPE) -#define OBD_IOC_CLIENT_RECOVER _IOW ('f', 133, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PING_TARGET _IOW ('f', 136, OBD_IOC_DATA_TYPE) +#define OBD_IOC_CLIENT_RECOVER _IOW('f', 133, OBD_IOC_DATA_TYPE) +#define OBD_IOC_PING_TARGET _IOW('f', 136, OBD_IOC_DATA_TYPE) #define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 139) -#define OBD_IOC_NO_TRANSNO _IOW ('f', 140, OBD_IOC_DATA_TYPE) -#define OBD_IOC_SET_READONLY _IOW ('f', 141, OBD_IOC_DATA_TYPE) -#define OBD_IOC_ABORT_RECOVERY _IOR ('f', 142, OBD_IOC_DATA_TYPE) +#define OBD_IOC_NO_TRANSNO _IOW('f', 140, OBD_IOC_DATA_TYPE) +#define OBD_IOC_SET_READONLY _IOW('f', 141, OBD_IOC_DATA_TYPE) +#define OBD_IOC_ABORT_RECOVERY _IOR('f', 142, OBD_IOC_DATA_TYPE) #define OBD_IOC_ROOT_SQUASH _IOWR('f', 143, OBD_IOC_DATA_TYPE) @@ -324,27 +324,27 @@ static inline void obd_ioctl_freedata(char *buf, int len) #define OBD_IOC_CLOSE_UUID _IOWR ('f', 147, OBD_IOC_DATA_TYPE) -#define OBD_IOC_CHANGELOG_SEND _IOW ('f', 148, OBD_IOC_DATA_TYPE) +#define OBD_IOC_CHANGELOG_SEND _IOW('f', 148, OBD_IOC_DATA_TYPE) #define OBD_IOC_GETDEVICE _IOWR ('f', 149, OBD_IOC_DATA_TYPE) #define OBD_IOC_FID2PATH _IOWR ('f', 150, OBD_IOC_DATA_TYPE) /* see also for ioctls 151-153 */ /* OBD_IOC_LOV_SETSTRIPE: See also LL_IOC_LOV_SETSTRIPE */ -#define OBD_IOC_LOV_SETSTRIPE _IOW ('f', 154, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LOV_SETSTRIPE _IOW('f', 154, OBD_IOC_DATA_TYPE) /* OBD_IOC_LOV_GETSTRIPE: See also LL_IOC_LOV_GETSTRIPE */ -#define OBD_IOC_LOV_GETSTRIPE _IOW ('f', 155, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LOV_GETSTRIPE _IOW('f', 155, OBD_IOC_DATA_TYPE) /* OBD_IOC_LOV_SETEA: See also LL_IOC_LOV_SETEA */ -#define OBD_IOC_LOV_SETEA _IOW ('f', 156, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LOV_SETEA _IOW('f', 156, OBD_IOC_DATA_TYPE) /* see for ioctls 157-159 */ /* OBD_IOC_QUOTACHECK: See also LL_IOC_QUOTACHECK */ -#define OBD_IOC_QUOTACHECK _IOW ('f', 160, int) +#define OBD_IOC_QUOTACHECK _IOW('f', 160, int) /* OBD_IOC_POLL_QUOTACHECK: See also LL_IOC_POLL_QUOTACHECK */ -#define OBD_IOC_POLL_QUOTACHECK _IOR ('f', 161, struct if_quotacheck *) +#define OBD_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) /* OBD_IOC_QUOTACTL: See also LL_IOC_QUOTACTL */ #define OBD_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) /* see also for ioctls 163-176 */ -#define OBD_IOC_CHANGELOG_REG _IOW ('f', 177, struct obd_ioctl_data) -#define OBD_IOC_CHANGELOG_DEREG _IOW ('f', 178, struct obd_ioctl_data) -#define OBD_IOC_CHANGELOG_CLEAR _IOW ('f', 179, struct obd_ioctl_data) +#define OBD_IOC_CHANGELOG_REG _IOW('f', 177, struct obd_ioctl_data) +#define OBD_IOC_CHANGELOG_DEREG _IOW('f', 178, struct obd_ioctl_data) +#define OBD_IOC_CHANGELOG_CLEAR _IOW('f', 179, struct obd_ioctl_data) #define OBD_IOC_RECORD _IOWR('f', 180, OBD_IOC_DATA_TYPE) #define OBD_IOC_ENDRECORD _IOWR('f', 181, OBD_IOC_DATA_TYPE) #define OBD_IOC_PARSE _IOWR('f', 182, OBD_IOC_DATA_TYPE) @@ -352,7 +352,7 @@ static inline void obd_ioctl_freedata(char *buf, int len) #define OBD_IOC_PROCESS_CFG _IOWR('f', 184, OBD_IOC_DATA_TYPE) #define OBD_IOC_DUMP_LOG _IOWR('f', 185, OBD_IOC_DATA_TYPE) #define OBD_IOC_CLEAR_LOG _IOWR('f', 186, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PARAM _IOW ('f', 187, OBD_IOC_DATA_TYPE) +#define OBD_IOC_PARAM _IOW('f', 187, OBD_IOC_DATA_TYPE) #define OBD_IOC_POOL _IOWR('f', 188, OBD_IOC_DATA_TYPE) #define OBD_IOC_REPLACE_NIDS _IOWR('f', 189, OBD_IOC_DATA_TYPE) diff --git a/drivers/staging/lustre/lustre/obdclass/debug.c b/drivers/staging/lustre/lustre/obdclass/debug.c index 43a7f7a79b35..e4edfb2c0a20 100644 --- a/drivers/staging/lustre/lustre/obdclass/debug.c +++ b/drivers/staging/lustre/lustre/obdclass/debug.c @@ -68,8 +68,8 @@ int block_debug_check(char *who, void *addr, int end, __u64 off, __u64 id) LASSERT(addr); - ne_off = le64_to_cpu (off); - id = le64_to_cpu (id); + ne_off = le64_to_cpu(off); + id = le64_to_cpu(id); if (memcmp(addr, (char *)&ne_off, LPDS)) { CDEBUG(D_ERROR, "%s: id %#llx offset %llu off: %#llx != %#llx\n", who, id, off, *(__u64 *)addr, ne_off); diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index aba646956900..ae19d396b537 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -403,20 +403,20 @@ extern struct lu_context_key osc_session_key; int osc_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, const struct cl_io *io); -int osc_io_init (const struct lu_env *env, - struct cl_object *obj, struct cl_io *io); -int osc_req_init (const struct lu_env *env, struct cl_device *dev, - struct cl_req *req); +int osc_io_init(const struct lu_env *env, + struct cl_object *obj, struct cl_io *io); +int osc_req_init(const struct lu_env *env, struct cl_device *dev, + struct cl_req *req); struct lu_object *osc_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *dev); int osc_page_init(const struct lu_env *env, struct cl_object *obj, struct cl_page *page, pgoff_t ind); -void osc_index2policy (ldlm_policy_data_t *policy, const struct cl_object *obj, - pgoff_t start, pgoff_t end); -int osc_lvb_print (const struct lu_env *env, void *cookie, - lu_printer_t p, const struct ost_lvb *lvb); +void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj, + pgoff_t start, pgoff_t end); +int osc_lvb_print(const struct lu_env *env, void *cookie, + lu_printer_t p, const struct ost_lvb *lvb); void osc_lru_add_batch(struct client_obd *cli, struct list_head *list); void osc_page_submit(const struct lu_env *env, struct osc_page *opg, @@ -448,11 +448,11 @@ void osc_io_unplug(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc); int lru_queue_work(const struct lu_env *env, void *data); -void osc_object_set_contended (struct osc_object *obj); +void osc_object_set_contended(struct osc_object *obj); void osc_object_clear_contended(struct osc_object *obj); -int osc_object_is_contended (struct osc_object *obj); +int osc_object_is_contended(struct osc_object *obj); -int osc_lock_is_lockless (const struct osc_lock *olck); +int osc_lock_is_lockless(const struct osc_lock *olck); /***************************************************************************** * diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 5b9f72c909b7..4d3eed6ee3f7 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2485,7 +2485,7 @@ static int osc_statfs_async(struct obd_export *exp, } req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_statfs_interpret; - CLASSERT (sizeof(*aa) <= sizeof(req->rq_async_args)); + CLASSERT(sizeof(*aa) <= sizeof(req->rq_async_args)); aa = ptlrpc_req_async_args(req); aa->aa_oi = oinfo; -- GitLab From 6cead36d284f230d29c2500c774180b8c716d4e6 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman Date: Wed, 30 Mar 2016 19:49:06 -0400 Subject: [PATCH 0895/9938] staging/lustre/ldlm: Solve a race for LRU lock cancel This patch solves a race condition that the lock may be used again after LRU cancellation policy check. In that case, the lock may have locked or dirty pages that makes the policy check totally useless. The problem is solved by checking l_last_used at cancellation time therefore it can make sure that the lock has not been used. Signed-off-by: Jinshan Xiong Signed-off-by: Vitaly Fertman Reviewed-on: http://review.whamcloud.com/12603 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5781 Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/ldlm/ldlm_internal.h | 3 ++- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 16 +++++++++++++--- .../staging/lustre/lustre/ldlm/ldlm_request.c | 11 +++++++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index e31d84aad4e4..351f8b44947f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -146,7 +146,8 @@ void ldlm_lock_decref_internal(struct ldlm_lock *, __u32 mode); void ldlm_lock_decref_internal_nolock(struct ldlm_lock *, __u32 mode); int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list, enum ldlm_desc_ast_t ast_type); -int ldlm_lock_remove_from_lru(struct ldlm_lock *lock); +int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, time_t last_use); +#define ldlm_lock_remove_from_lru(lock) ldlm_lock_remove_from_lru_check(lock, 0) int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock); void ldlm_lock_destroy_nolock(struct ldlm_lock *lock); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 27a051b085b5..3f9b85262770 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -229,15 +229,25 @@ int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock) /** * Removes LDLM lock \a lock from LRU. Obtains the LRU lock first. + * + * If \a last_use is non-zero, it will remove the lock from LRU only if + * it matches lock's l_last_used. + * + * \retval 0 if \a last_use is set, the lock is not in LRU list or \a last_use + * doesn't match lock's l_last_used; + * otherwise, the lock hasn't been in the LRU list. + * \retval 1 the lock was in LRU list and removed. */ -int ldlm_lock_remove_from_lru(struct ldlm_lock *lock) +int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, time_t last_use) { struct ldlm_namespace *ns = ldlm_lock_to_ns(lock); - int rc; + int rc = 0; spin_lock(&ns->ns_lock); - rc = ldlm_lock_remove_from_lru_nolock(lock); + if (last_use == 0 || last_use == lock->l_last_used) + rc = ldlm_lock_remove_from_lru_nolock(lock); spin_unlock(&ns->ns_lock); + return rc; } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 9aa4c2dfe143..5b0e396a9908 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1369,6 +1369,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, while (!list_empty(&ns->ns_unused_list)) { ldlm_policy_res_t result; + time_t last_use = 0; /* all unused locks */ if (remained-- <= 0) @@ -1387,6 +1388,10 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, /* already processed */ continue; + last_use = lock->l_last_used; + if (last_use == cfs_time_current()) + continue; + /* Somebody is already doing CANCEL. No need for this * lock in LRU, do not traverse it again. */ @@ -1434,11 +1439,13 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, lock_res_and_lock(lock); /* Check flags again under the lock. */ if ((lock->l_flags & LDLM_FL_CANCELING) || - (ldlm_lock_remove_from_lru(lock) == 0)) { + (ldlm_lock_remove_from_lru_check(lock, last_use) == 0)) { /* Another thread is removing lock from LRU, or * somebody is already doing CANCEL, or there * is a blocking request which will send cancel - * by itself, or the lock is no longer unused. + * by itself, or the lock is no longer unused or + * the lock has been used since the pf() call and + * pages could be put under it. */ unlock_res_and_lock(lock); lu_ref_del(&lock->l_reference, -- GitLab From 30889c72a9fe53b3d4303464fc688497cbb14219 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Wed, 30 Mar 2016 19:49:07 -0400 Subject: [PATCH 0896/9938] staging/lustre: lov_io_init() should return error code lov_io_init_empty/release() should returns error code instead of true on error case. Fault IO needs to handle restart in the case of accessing HSM released file Signed-off-by: Bobi Jam Reviewed-on: http://review.whamcloud.com/17240 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7446 Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_mmap.c | 4 ++++ drivers/staging/lustre/lustre/lov/lov_io.c | 4 ++-- drivers/staging/lustre/lustre/obdclass/cl_io.c | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 83d7006546dc..5b4382cca0d7 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -123,6 +123,7 @@ ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret, *env_ret = env; +restart: io = vvp_env_thread_io(env); io->ci_obj = ll_i2info(inode)->lli_clob; LASSERT(io->ci_obj); @@ -157,6 +158,9 @@ ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret, } else { LASSERT(rc < 0); cl_io_fini(env, io); + if (io->ci_need_restart) + goto restart; + cl_env_nested_put(nest, env); io = ERR_PTR(rc); } diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index ba79955f54bb..41512372c472 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -916,7 +916,7 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj, } io->ci_result = result < 0 ? result : 0; - return result != 0; + return result; } int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, @@ -959,7 +959,7 @@ int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, } io->ci_result = result < 0 ? result : 0; - return result != 0; + return result; } /** @} lov */ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 7655dc485fef..f4b3178ec043 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -133,6 +133,7 @@ void cl_io_fini(const struct lu_env *env, struct cl_io *io) case CIT_WRITE: break; case CIT_FAULT: + break; case CIT_FSYNC: LASSERT(!io->ci_need_restart); break; -- GitLab From 83d26b63268faf9137878e34f7e8cfda8a089124 Mon Sep 17 00:00:00 2001 From: Dave Anderson Date: Mon, 28 Mar 2016 14:56:47 -0700 Subject: [PATCH 0897/9938] bpf: doc: "neg" opcode has no operands Fixes a copy-paste-o in the BPF opcode table: "neg" takes no arguments and thus has no addressing modes. Signed-off-by: Dave Anderson Signed-off-by: Kees Cook Acked-by: Alexei Starovoitov Acked-by: Daniel Borkmann Signed-off-by: Jonathan Corbet --- Documentation/networking/filter.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt index 96da119a47e7..11f67f181d39 100644 --- a/Documentation/networking/filter.txt +++ b/Documentation/networking/filter.txt @@ -230,7 +230,7 @@ opcodes as defined in linux/filter.h stand for: mul 0, 4 A * div 0, 4 A / mod 0, 4 A % - neg 0, 4 !A + neg !A and 0, 4 A & or 0, 4 A | xor 0, 4 A ^ -- GitLab From dbe7fcdaf94052faf65172bb91d4266d20b5458b Mon Sep 17 00:00:00 2001 From: Jianyu Zhan Date: Sun, 27 Mar 2016 11:51:20 +0800 Subject: [PATCH 0898/9938] Documentation/IRQ-domain.txt: Document irq_domain_create_{linear, tree} They have the same functionalities as irq_domain_add_{linear, tree}, except fro accepting different first argument. Signed-off-by: Jianyu Zhan Acked-by: Marc Zyngier Signed-off-by: Jonathan Corbet --- Documentation/IRQ-domain.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt index 8d990bde8693..82001a25a14b 100644 --- a/Documentation/IRQ-domain.txt +++ b/Documentation/IRQ-domain.txt @@ -70,6 +70,7 @@ of the reverse map types are described below: ==== Linear ==== irq_domain_add_linear() +irq_domain_create_linear() The linear reverse map maintains a fixed size table indexed by the hwirq number. When a hwirq is mapped, an irq_desc is allocated for @@ -81,10 +82,16 @@ map are fixed time lookup for IRQ numbers, and irq_descs are only allocated for in-use IRQs. The disadvantage is that the table must be as large as the largest possible hwirq number. +irq_domain_add_linear() and irq_domain_create_linear() are functionally +equivalent, except for the first argument is different - the former +accepts an Open Firmware specific 'struct device_node', while the latter +accepts a more general abstraction 'struct fwnode_handle'. + The majority of drivers should use the linear map. ==== Tree ==== irq_domain_add_tree() +irq_domain_create_tree() The irq_domain maintains a radix tree map from hwirq numbers to Linux IRQs. When an hwirq is mapped, an irq_desc is allocated and the @@ -95,6 +102,11 @@ since it doesn't need to allocate a table as large as the largest hwirq number. The disadvantage is that hwirq to IRQ number lookup is dependent on how many entries are in the table. +irq_domain_add_tree() and irq_domain_create_tree() are functionally +equivalent, except for the first argument is different - the former +accepts an Open Firmware specific 'struct device_node', while the latter +accepts a more general abstraction 'struct fwnode_handle'. + Very few drivers should need this mapping. ==== No Map ===- -- GitLab From 0b55257ebc66d333e86415b0fdf46450ca807059 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 8 Mar 2016 09:33:39 -0300 Subject: [PATCH 0899/9938] clk: imx6sx: Register SAI clocks as shared clocks SAIx and SAIx_IPG share the same bit fields in the CCM registers, so we should better register them via imx_clk_gate2_shared(). Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx6sx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index fea125eb4330..97e742a8be17 100644 --- a/drivers/clk/imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c @@ -134,6 +134,8 @@ static u32 share_count_esai; static u32 share_count_ssi1; static u32 share_count_ssi2; static u32 share_count_ssi3; +static u32 share_count_sai1; +static u32 share_count_sai2; static struct clk ** const uart_clks[] __initconst = { &clks[IMX6SX_CLK_UART_IPG], @@ -469,10 +471,10 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) clks[IMX6SX_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3); clks[IMX6SX_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); clks[IMX6SX_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_podf", base + 0x7c, 26); - clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2("sai1_ipg", "ipg", base + 0x7c, 28); - clks[IMX6SX_CLK_SAI2_IPG] = imx_clk_gate2("sai2_ipg", "ipg", base + 0x7c, 30); - clks[IMX6SX_CLK_SAI1] = imx_clk_gate2("sai1", "ssi1_podf", base + 0x7c, 28); - clks[IMX6SX_CLK_SAI2] = imx_clk_gate2("sai2", "ssi2_podf", base + 0x7c, 30); + clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2_shared("sai1_ipg", "ipg", base + 0x7c, 28, &share_count_sai1); + clks[IMX6SX_CLK_SAI2_IPG] = imx_clk_gate2_shared("sai2_ipg", "ipg", base + 0x7c, 30, &share_count_sai2); + clks[IMX6SX_CLK_SAI1] = imx_clk_gate2_shared("sai1", "ssi1_podf", base + 0x7c, 28, &share_count_sai1); + clks[IMX6SX_CLK_SAI2] = imx_clk_gate2_shared("sai2", "ssi2_podf", base + 0x7c, 30, &share_count_sai2); /* CCGR6 */ clks[IMX6SX_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); -- GitLab From 5408e5a4552b8e33a65127944bec21dd3d9258c1 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Mon, 21 Mar 2016 19:42:19 +0800 Subject: [PATCH 0900/9938] Documentation: update missing index files in block/00-INDEX Update missing index files in block/00-INDEX. Signed-off-by: Wei Fang Signed-off-by: Jonathan Corbet --- Documentation/block/00-INDEX | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX index e840b47613f7..e55103ace382 100644 --- a/Documentation/block/00-INDEX +++ b/Documentation/block/00-INDEX @@ -2,6 +2,8 @@ - This file biodoc.txt - Notes on the Generic Block Layer Rewrite in Linux 2.5 +biovecs.txt + - Immutable biovecs and biovec iterators capability.txt - Generic Block Device Capability (/sys/block//capability) cfq-iosched.txt @@ -14,6 +16,8 @@ deadline-iosched.txt - Deadline IO scheduler tunables ioprio.txt - Block io priorities (in CFQ scheduler) +pr.txt + - Block layer support for Persistent Reservations null_blk.txt - Null block for block-layer benchmarking. queue-sysfs.txt -- GitLab From a06bdd49c98c6a538890650bac9a0173cbc644b2 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Sat, 19 Mar 2016 12:51:20 +0000 Subject: [PATCH 0901/9938] Documentation: add Linux Kernel Development book The Linux Kernel Development book by Robert Love has been recommended to me by multiple kernel hackers. Worth having in the list of books in kernel-docs.txt for newbies looking for good learning resources. Signed-off-by: Luis de Bethencourt Signed-off-by: Jonathan Corbet --- Documentation/kernel-docs.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt index fe217c1c2f7f..b2503602134f 100644 --- a/Documentation/kernel-docs.txt +++ b/Documentation/kernel-docs.txt @@ -609,6 +609,13 @@ Pages: 432. ISBN: 0-201-63338-8 + * Title: "Linux Kernel Development, 3rd Edition" + Author: Robert Love + Publisher: Addison-Wesley. + Date: July, 2010 + Pages: 440 + ISBN: 978-0672329463 + MISCELLANEOUS: * Name: linux/Documentation -- GitLab From dc831ab3cc7f22ae500872e54cd85317e766c156 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Sat, 19 Mar 2016 12:51:22 +0000 Subject: [PATCH 0902/9938] Documentation: update URL of Analysis of the Ext2fs structure The current URL has been down for some time, updating it to a working one. Signed-off-by: Luis de Bethencourt Signed-off-by: Jonathan Corbet --- Documentation/kernel-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt index b2503602134f..b92449feea23 100644 --- a/Documentation/kernel-docs.txt +++ b/Documentation/kernel-docs.txt @@ -250,7 +250,7 @@ * Title: "Analysis of the Ext2fs structure" Author: Louis-Dominique Dubeau. - URL: http://www.nondot.org/sabre/os/files/FileSystems/ext2fs/ + URL: http://teaching.csse.uwa.edu.au/units/CITS2002/fs-ext2/ Keywords: ext2, filesystem, ext2fs. Description: Description of ext2's blocks, directories, inodes, bitmaps, invariants... -- GitLab From f7ca20deee2b2eac0a43e1dcf75d5d3ee2c6c81e Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Sat, 19 Mar 2016 12:51:23 +0000 Subject: [PATCH 0903/9938] Documentation: update URLs for Richard Gooch's articles Current URL for "Kernel API changes from 2.0 to 2.2" hasn't been available for some time, updating. The second article about changes from 2.2 to 2.4 is missing a URL, adding it. Signed-off-by: Luis de Bethencourt Signed-off-by: Jonathan Corbet --- Documentation/kernel-docs.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt index b92449feea23..3aecbac1cb01 100644 --- a/Documentation/kernel-docs.txt +++ b/Documentation/kernel-docs.txt @@ -266,14 +266,14 @@ * Title: "Kernel API changes from 2.0 to 2.2" Author: Richard Gooch. - URL: - http://www.linuxhq.com/guides/LKMPG/node28.html + URL: http://www.safe-mbox.com/~rgooch/linux/docs/porting-to-2.2.html Keywords: 2.2, changes. Description: Kernel functions/structures/variables which changed from 2.0.x to 2.2.x. * Title: "Kernel API changes from 2.2 to 2.4" Author: Richard Gooch. + URL: http://www.safe-mbox.com/~rgooch/linux/docs/porting-to-2.4.html Keywords: 2.4, changes. Description: Kernel functions/structures/variables which changed from 2.2.x to 2.4.x. -- GitLab From f3e27a80b782b9b9857157e0a104a8757e72d166 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Wed, 16 Mar 2016 20:02:49 +0800 Subject: [PATCH 0904/9938] Documentation: mmc: Add the introduction for mmc-utils This patch introduces one mmc test tools called mmc-utils, which is convenient if someone wants to exercise and test MMC/SD devices from userspace. Signed-off-by: Baolin Wang Signed-off-by: Jonathan Corbet --- Documentation/mmc/00-INDEX | 2 ++ Documentation/mmc/mmc-tools.txt | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 Documentation/mmc/mmc-tools.txt diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX index a9ba6720ffdf..4623bc0aa0bb 100644 --- a/Documentation/mmc/00-INDEX +++ b/Documentation/mmc/00-INDEX @@ -6,3 +6,5 @@ mmc-dev-parts.txt - info on SD and MMC device partitions mmc-async-req.txt - info on mmc asynchronous requests +mmc-tools.txt + - info on mmc-utils tools diff --git a/Documentation/mmc/mmc-tools.txt b/Documentation/mmc/mmc-tools.txt new file mode 100644 index 000000000000..735509c165d5 --- /dev/null +++ b/Documentation/mmc/mmc-tools.txt @@ -0,0 +1,34 @@ +MMC tools introduction +====================== + +There is one MMC test tools called mmc-utils, which is maintained by Chris Ball, +you can find it at the below public git repository: +http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git/ + +Functions +========= + +The mmc-utils tools can do the following: + - Print and parse extcsd data. + - Determine the eMMC writeprotect status. + - Set the eMMC writeprotect status. + - Set the eMMC data sector size to 4KB by disabling emulation. + - Create general purpose partition. + - Enable the enhanced user area. + - Enable write reliability per partition. + - Print the response to STATUS_SEND (CMD13). + - Enable the boot partition. + - Set Boot Bus Conditions. + - Enable the eMMC BKOPS feature. + - Permanently enable the eMMC H/W Reset feature. + - Permanently disable the eMMC H/W Reset feature. + - Send Sanitize command. + - Program authentication key for the device. + - Counter value for the rpmb device will be read to stdout. + - Read from rpmb device to output. + - Write to rpmb device from data file. + - Enable the eMMC cache feature. + - Disable the eMMC cache feature. + - Print and parse CID data. + - Print and parse CSD data. + - Print and parse SCR data. -- GitLab From 834392a7d92677ff2bdc1c709b1171ee585b55c9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:09 +0100 Subject: [PATCH 0905/9938] serial: doc: Un-document non-existing uart_write_console() uart_write_console() never existed, not even when the "new uart_write_console function" was documented. Fixes: 67ab7f596b6adbae ("[SERIAL] Update serial driver documentation") Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 379468e12680..e7c6f86ee06f 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -28,11 +28,6 @@ The serial core provides a few helper functions. This includes identifing the correct port structure (via uart_get_console) and decoding command line arguments (uart_parse_options). -There is also a helper function (uart_write_console) which performs a -character by character write, translating newlines to CRLF sequences. -Driver writers are recommended to use this function rather than implementing -their own version. - Locking ------- -- GitLab From 4895b1d72117efea48ff51e94a26ce3cbde4d1a1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:10 +0100 Subject: [PATCH 0906/9938] serial: doc: Un-document obsolete tmpbuf_sem uart_info.tmpbuf and uart_info.tmpbuf_sem were removed in v2.6.10, in full-history-linux commit a797ad7e3ae9cad4 ("[SERIAL] Clean up serial_core.c write functions."). Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index e7c6f86ee06f..61d520dea4c6 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -36,8 +36,7 @@ It is the responsibility of the low level hardware driver to perform the necessary locking using port->lock. There are some exceptions (which are described in the uart_ops listing below.) -There are three locks. A per-port spinlock, a per-port tmpbuf semaphore, -and an overall semaphore. +There are two locks. A per-port spinlock, and an overall semaphore. From the core driver perspective, the port->lock locks the following data: @@ -50,9 +49,6 @@ data: The low level driver is free to use this lock to provide any additional locking. -The core driver uses the info->tmpbuf_sem lock to prevent multi-threaded -access to the info->tmpbuf bouncebuffer used for port writes. - The port_sem semaphore is used to protect against ports being added/ removed or reconfigured at inappropriate times. Since v2.6.27, this semaphore has been the 'mutex' member of the tty_port struct, and -- GitLab From 39c5144e5f0bc2dec9ebe3613d5f9c0f0b0bdc72 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:11 +0100 Subject: [PATCH 0907/9938] serial: doc: Document .throttle() Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 61d520dea4c6..50f3d94ed50b 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -126,6 +126,13 @@ hardware. Interrupts: locally disabled. This call must not sleep + throttle(port) + Notify the serial driver that input buffers for the line discipline are + close to full, and it should somehow signal that no more characters + should be sent to the serial port. + + Locking: none. + send_xchar(port,ch) Transmit a high priority character, even if the port is stopped. This is used to implement XON/XOFF flow control and tcflow(). If -- GitLab From e27585c7970decd26113ca036a1cb5678d88ee5a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:12 +0100 Subject: [PATCH 0908/9938] serial: doc: Document .unthrottle() Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 50f3d94ed50b..3b2a97d5ecc7 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -133,6 +133,13 @@ hardware. Locking: none. + unthrottle(port) + Notify the serial driver that characters can now be sent to the serial + port without fear of overrunning the input buffers of the line + disciplines. + + Locking: none. + send_xchar(port,ch) Transmit a high priority character, even if the port is stopped. This is used to implement XON/XOFF flow control and tcflow(). If -- GitLab From 0adc301e7b3c098744d0098008b1aa31041e220b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:13 +0100 Subject: [PATCH 0909/9938] serial: doc: Document .set_ldisc() Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 3b2a97d5ecc7..3b08df5bcc17 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -259,6 +259,11 @@ hardware. Interrupts: caller dependent. This call must not sleep + set_ldisc(port,termios) + Notifier for discipline change. See Documentation/serial/tty.txt. + + Locking: caller holds port->mutex + pm(port,state,oldstate) Perform any power management related activities on the specified port. State indicates the new state (defined by -- GitLab From fbe3128bcf87723bbbaa2de26f5d1c1122c66b54 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:14 +0100 Subject: [PATCH 0910/9938] serial: doc: .break_ctl() is called with port->mutex() held Note that mutex_lock() should not be called with interrupts disabled. Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 3b08df5bcc17..09e73e061fcf 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -177,8 +177,7 @@ hardware. should be terminated when another call is made with a zero ctl. - Locking: none. - Interrupts: caller dependent. + Locking: caller holds port->mutex This call must not sleep startup(port) -- GitLab From 93a2f6329f40d951101ab8ab160f24680f1c122a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:15 +0100 Subject: [PATCH 0911/9938] serial: doc: Spelling s/divsor/divisor/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 09e73e061fcf..3706a465fe2d 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -380,7 +380,7 @@ uart_get_baud_rate(port,termios,old,min,max) Interrupts: n/a uart_get_divisor(port,baud) - Return the divsor (baud_base / baud) for the specified baud + Return the divisor (baud_base / baud) for the specified baud rate, appropriately rounded. If 38400 baud and custom divisor is selected, return the -- GitLab From d886e7ce157373773254f5c1e7f011cd9d3ec558 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:16 +0100 Subject: [PATCH 0912/9938] serial: doc: Grammar s/function are/functions are/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 3706a465fe2d..ba84d1f38ca1 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -458,7 +458,7 @@ mctrl_gpio_init(port, idx): mctrl_gpio_free(dev, gpios): This will free the requested gpios in mctrl_gpio_init(). - As devm_* function are used, there's generally no need to call + As devm_* functions are used, there's generally no need to call this function. mctrl_gpio_to_gpiod(gpios, gidx) -- GitLab From 4817ebb144ffa5a1a2bc84b89ed9655dbe6c4502 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:16:17 +0100 Subject: [PATCH 0913/9938] serial: doc: Correct return type of mctrl_gpio_to_gpiod() Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index ba84d1f38ca1..65de49a4b39e 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -462,7 +462,8 @@ mctrl_gpio_free(dev, gpios): this function. mctrl_gpio_to_gpiod(gpios, gidx) - This returns the gpio structure associated to the modem line index. + This returns the gpio_desc structure associated to the modem line + index. mctrl_gpio_set(gpios, mctrl): This will sets the gpios according to the mctrl state. -- GitLab From d6af1a31cc72fbd558c7eddbc36f61bf09d1cf6a Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 16 Mar 2016 10:17:37 +0100 Subject: [PATCH 0914/9938] vti: Add pmtu handling to vti_xmit. We currently rely on the PMTU discovery of xfrm. However if a packet is locally sent, the PMTU mechanism of xfrm tries to do local socket notification what might not work for applications like ping that don't check for this. So add pmtu handling to vti_xmit to report MTU changes immediately. Reported-by: Mark McKinstry Signed-off-by: Steffen Klassert --- net/ipv4/ip_vti.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 5cf10b777b7e..a917903d5e97 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -156,6 +156,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, struct dst_entry *dst = skb_dst(skb); struct net_device *tdev; /* Device to other host */ int err; + int mtu; if (!dst) { dev->stats.tx_carrier_errors++; @@ -192,6 +193,23 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, tunnel->err_count = 0; } + mtu = dst_mtu(dst); + if (skb->len > mtu) { + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + if (skb->protocol == htons(ETH_P_IP)) { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + } else { + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + } + + dst_release(dst); + goto tx_error; + } + skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); skb_dst_set(skb, dst); skb->dev = skb_dst(skb)->dev; -- GitLab From ab503238ff6974b9a51d328c2a55c505064c64f7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 31 Mar 2016 09:09:12 +0200 Subject: [PATCH 0915/9938] powerpc: ppc4xx: drop unused variable commit 0d36fe65f58391712e11a6621075f373216e5f00 "powerpc: ppc4xx: use gpiochip data pointer" made the mm_gc local variable in ppc4xx_gpio_set() redundant, and when GCC treats warnings as errors this happens: arch/powerpc/sysdev/ppc4xx_gpio.c: In function 'ppc4xx_gpio_set': arch/powerpc/sysdev/ppc4xx_gpio.c:93:26: error: unused variable 'mm_gc' [-Werror=unused-variable] struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); ^ cc1: all warnings being treated as errors Reported-by: kbuild test robot Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Linus Walleij --- arch/powerpc/sysdev/ppc4xx_gpio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/sysdev/ppc4xx_gpio.c b/arch/powerpc/sysdev/ppc4xx_gpio.c index 4ab83cd04785..5382d04dd872 100644 --- a/arch/powerpc/sysdev/ppc4xx_gpio.c +++ b/arch/powerpc/sysdev/ppc4xx_gpio.c @@ -90,7 +90,6 @@ __ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static void ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc); unsigned long flags; -- GitLab From 42a44402ecb78e87eecf7ccad8099287e660ec36 Mon Sep 17 00:00:00 2001 From: Wang Hongcheng Date: Fri, 11 Mar 2016 10:58:42 +0800 Subject: [PATCH 0916/9938] pinctrl: amd:Add device HID for future AMD GPIO controller Add device HID AMDI0030 to match the AMD ACPI Vendor ID (AMDI) as registered in http://www.uefi.org/acpi_id_list, and the GPIO controller on future AMD paltform will use the HID instead of AMD0030. Signed-off-by: Wang Hongcheng Acked-by: Ken Xue Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-amd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 5c025f5b5048..cc44ae8c8758 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -844,6 +844,7 @@ static int amd_gpio_remove(struct platform_device *pdev) static const struct acpi_device_id amd_gpio_acpi_match[] = { { "AMD0030", 0 }, + { "AMDI0030", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match); -- GitLab From 63cc787e71ae12976b2116f09677d1f2805df83e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 Mar 2016 12:00:31 +0800 Subject: [PATCH 0917/9938] irqdomain: Export irq_domain_free_irqs_common Export irq_domain_free_irqs_common so it can be used by modules. Signed-off-by: Axel Lin Acked-by: Thomas Gleixner Acked-by: Marc Zyngier Signed-off-by: Linus Walleij --- kernel/irq/irqdomain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 3a519a01118b..245a485ffb61 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1099,6 +1099,7 @@ void irq_domain_free_irqs_common(struct irq_domain *domain, unsigned int virq, } irq_domain_free_irqs_parent(domain, virq, nr_irqs); } +EXPORT_SYMBOL_GPL(irq_domain_free_irqs_common); /** * irq_domain_free_irqs_top - Clear handler and handler data, clear irqdata and free parent -- GitLab From c6cc75fec020eda0df04aff21f6cd6f4bfc1eea5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 Mar 2016 12:01:43 +0800 Subject: [PATCH 0918/9938] gpio: xgene-sb: Use irq_domain_free_irqs_common() Current code calls irq_domain_alloc_irqs_parent() in .alloc, so it should call irq_domain_free_irqs_parent() accordingly in .free. Fix it by switching to use irq_domain_free_irqs_common() instead. Signed-off-by: Axel Lin Acked-by: Marc Zyngier Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xgene-sb.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index 31cbcb84cfaf..033258634b8c 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -216,23 +216,10 @@ static int xgene_gpio_sb_domain_alloc(struct irq_domain *domain, &parent_fwspec); } -static void xgene_gpio_sb_domain_free(struct irq_domain *domain, - unsigned int virq, - unsigned int nr_irqs) -{ - struct irq_data *d; - unsigned int i; - - for (i = 0; i < nr_irqs; i++) { - d = irq_domain_get_irq_data(domain, virq + i); - irq_domain_reset_irq_data(d); - } -} - static const struct irq_domain_ops xgene_gpio_sb_domain_ops = { .translate = xgene_gpio_sb_domain_translate, .alloc = xgene_gpio_sb_domain_alloc, - .free = xgene_gpio_sb_domain_free, + .free = irq_domain_free_irqs_common, .activate = xgene_gpio_sb_domain_activate, .deactivate = xgene_gpio_sb_domain_deactivate, }; -- GitLab From 80018bd9cb590c3d7fea9b51730e4a251cb1bb42 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Mon, 14 Mar 2016 23:32:10 +0000 Subject: [PATCH 0919/9938] gpio: 74x164: add dt support for nxp's 74x594 The chip is also an 8 bit shift register which works out of the box as a GPO expander with this patch Signed-off-by: Nicolas Saenz Julienne Acked-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-74x164.txt | 4 +++- drivers/gpio/gpio-74x164.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-74x164.txt b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt index cc2608021f26..ce1b2231bf5d 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-74x164.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt @@ -1,7 +1,9 @@ * Generic 8-bits shift register GPIO driver Required properties: -- compatible : Should be "fairchild,74hc595" +- compatible: Should contain one of the following: + "fairchild,74hc595" + "nxp,74lvc594" - reg : chip select number - gpio-controller : Marks the device node as a gpio controller. - #gpio-cells : Should be two. The first cell is the pin number and diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 62291a81c97f..80f9ddf13343 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -177,6 +177,7 @@ static int gen_74x164_remove(struct spi_device *spi) static const struct of_device_id gen_74x164_dt_ids[] = { { .compatible = "fairchild,74hc595" }, + { .compatible = "nxp,74lvc594" }, {}, }; MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids); -- GitLab From 1418f9e6e02da2ad0a6aacc8645e6ad7496105e9 Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Wed, 23 Mar 2016 17:47:19 +0800 Subject: [PATCH 0920/9938] gpio: mpc8xxx: Add new platforms GPIO DT node description Update the NXP GPIO node dt-binding file for QorIQ and Layerscape platforms, and add one more example with ls2080a GPIO node. Signed-off-by: Liu Gang Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-mpc8xxx.txt | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt index 120bc4971cf3..4b6cc632ca5c 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt @@ -1,9 +1,10 @@ -* Freescale MPC512x/MPC8xxx/Layerscape GPIO controller +* Freescale MPC512x/MPC8xxx/QorIQ/Layerscape GPIO controller Required properties: - compatible : Should be "fsl,-gpio" The following s are known to be supported: - mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq. + mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq, + ls1021a, ls1043a, ls2080a. - reg : Address and length of the register set for the device - interrupts : Should be the port interrupt shared by all 32 pins. - #gpio-cells : Should be two. The first cell is the pin number and @@ -15,7 +16,7 @@ Optional properties: - little-endian : GPIO registers are used as little endian. If not present registers are used as big endian by default. -Example: +Example of gpio-controller node for a mpc5125 SoC: gpio0: gpio@1100 { compatible = "fsl,mpc5125-gpio"; @@ -24,3 +25,16 @@ gpio0: gpio@1100 { interrupts = <78 0x8>; status = "okay"; }; + +Example of gpio-controller node for a ls2080a SoC: + +gpio0: gpio@2300000 { + compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = <0 36 0x4>; /* Level high type */ + gpio-controller; + little-endian; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +}; -- GitLab From e633c65a1d5859da170a83d537d9762c07d12213 Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Sun, 20 Mar 2016 01:33:36 -0700 Subject: [PATCH 0921/9938] x86/perf/intel/uncore: Make the Intel uncore PMU driver modular By default, the uncore driver will be built into the kernel. If it is configured as a module, the supported CPU model can be auto loaded. This patch also cleans up the code of uncore_cpu_init() and uncore_pci_init(). Based-on-a-patch-by: Thomas Gleixner Signed-off-by: Kan Liang Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Thomas Gleixner Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Link: http://lkml.kernel.org/r/1458462817-2475-1-git-send-email-kan.liang@intel.com Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 6 +- arch/x86/Kconfig.perf | 11 ++ arch/x86/events/Makefile | 9 +- arch/x86/events/intel/Makefile | 6 + arch/x86/events/intel/uncore.c | 216 +++++++++++++++++++-------------- 5 files changed, 148 insertions(+), 100 deletions(-) create mode 100644 arch/x86/Kconfig.perf create mode 100644 arch/x86/events/intel/Makefile diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a313c0e7e165..496218b8236b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -160,10 +160,6 @@ config INSTRUCTION_DECODER def_bool y depends on KPROBES || PERF_EVENTS || UPROBES -config PERF_EVENTS_INTEL_UNCORE - def_bool y - depends on PERF_EVENTS && CPU_SUP_INTEL && PCI - config OUTPUT_FORMAT string default "elf32-i386" if X86_32 @@ -1042,6 +1038,8 @@ config X86_THERMAL_VECTOR def_bool y depends on X86_MCE_INTEL +source "arch/x86/Kconfig.perf" + config X86_LEGACY_VM86 bool "Legacy VM86 support" default n diff --git a/arch/x86/Kconfig.perf b/arch/x86/Kconfig.perf new file mode 100644 index 000000000000..90b7f5878c96 --- /dev/null +++ b/arch/x86/Kconfig.perf @@ -0,0 +1,11 @@ +menu "Performance monitoring" + +config PERF_EVENTS_INTEL_UNCORE + tristate "Intel uncore performance events" + depends on PERF_EVENTS && CPU_SUP_INTEL && PCI + default y + ---help--- + Include support for Intel uncore performance events. These are + available on NehalemEX and more modern processors. + +endmenu diff --git a/arch/x86/events/Makefile b/arch/x86/events/Makefile index f59618a39990..1d392c39fe56 100644 --- a/arch/x86/events/Makefile +++ b/arch/x86/events/Makefile @@ -6,9 +6,6 @@ obj-$(CONFIG_X86_LOCAL_APIC) += amd/ibs.o msr.o ifdef CONFIG_AMD_IOMMU obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o endif -obj-$(CONFIG_CPU_SUP_INTEL) += intel/core.o intel/bts.o intel/cqm.o -obj-$(CONFIG_CPU_SUP_INTEL) += intel/cstate.o intel/ds.o intel/knc.o -obj-$(CONFIG_CPU_SUP_INTEL) += intel/lbr.o intel/p4.o intel/p6.o intel/pt.o -obj-$(CONFIG_CPU_SUP_INTEL) += intel/rapl.o msr.o -obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore.o intel/uncore_nhmex.o -obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore_snb.o intel/uncore_snbep.o + +obj-$(CONFIG_CPU_SUP_INTEL) += msr.o +obj-$(CONFIG_CPU_SUP_INTEL) += intel/ diff --git a/arch/x86/events/intel/Makefile b/arch/x86/events/intel/Makefile new file mode 100644 index 000000000000..a6c744871a73 --- /dev/null +++ b/arch/x86/events/intel/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_CPU_SUP_INTEL) += core.o bts.o cqm.o +obj-$(CONFIG_CPU_SUP_INTEL) += cstate.o ds.o knc.o +obj-$(CONFIG_CPU_SUP_INTEL) += lbr.o p4.o p6.o pt.o +obj-$(CONFIG_CPU_SUP_INTEL) += rapl.o +obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o +intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index 7012d18bb293..17734a6ef474 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -1,3 +1,4 @@ +#include #include "uncore.h" static struct intel_uncore_type *empty_uncore[] = { NULL, }; @@ -21,6 +22,8 @@ static struct event_constraint uncore_constraint_fixed = struct event_constraint uncore_constraint_empty = EVENT_CONSTRAINT(0, 0, 0); +MODULE_LICENSE("GPL"); + static int uncore_pcibus_to_physid(struct pci_bus *bus) { struct pci2phy_map *map; @@ -754,7 +757,7 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu) pmu->registered = false; } -static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu) +static void __uncore_exit_boxes(struct intel_uncore_type *type, int cpu) { struct intel_uncore_pmu *pmu = type->pmus; struct intel_uncore_box *box; @@ -770,7 +773,7 @@ static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu) } } -static void __init uncore_exit_boxes(void *dummy) +static void uncore_exit_boxes(void *dummy) { struct intel_uncore_type **types; @@ -787,7 +790,7 @@ static void uncore_free_boxes(struct intel_uncore_pmu *pmu) kfree(pmu->boxes); } -static void __init uncore_type_exit(struct intel_uncore_type *type) +static void uncore_type_exit(struct intel_uncore_type *type) { struct intel_uncore_pmu *pmu = type->pmus; int i; @@ -804,7 +807,7 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) type->events_group = NULL; } -static void __init uncore_types_exit(struct intel_uncore_type **types) +static void uncore_types_exit(struct intel_uncore_type **types) { for (; *types; types++) uncore_type_exit(*types); @@ -989,46 +992,6 @@ static int __init uncore_pci_init(void) size_t size; int ret; - switch (boot_cpu_data.x86_model) { - case 45: /* Sandy Bridge-EP */ - ret = snbep_uncore_pci_init(); - break; - case 62: /* Ivy Bridge-EP */ - ret = ivbep_uncore_pci_init(); - break; - case 63: /* Haswell-EP */ - ret = hswep_uncore_pci_init(); - break; - case 79: /* BDX-EP */ - case 86: /* BDX-DE */ - ret = bdx_uncore_pci_init(); - break; - case 42: /* Sandy Bridge */ - ret = snb_uncore_pci_init(); - break; - case 58: /* Ivy Bridge */ - ret = ivb_uncore_pci_init(); - break; - case 60: /* Haswell */ - case 69: /* Haswell Celeron */ - ret = hsw_uncore_pci_init(); - break; - case 61: /* Broadwell */ - ret = bdw_uncore_pci_init(); - break; - case 87: /* Knights Landing */ - ret = knl_uncore_pci_init(); - break; - case 94: /* SkyLake */ - ret = skl_uncore_pci_init(); - break; - default: - return -ENODEV; - } - - if (ret) - return ret; - size = max_packages * sizeof(struct pci_extra_dev); uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL); if (!uncore_extra_pci_dev) { @@ -1060,7 +1023,7 @@ static int __init uncore_pci_init(void) return ret; } -static void __init uncore_pci_exit(void) +static void uncore_pci_exit(void) { if (pcidrv_registered) { pcidrv_registered = false; @@ -1287,46 +1250,6 @@ static int __init uncore_cpu_init(void) { int ret; - switch (boot_cpu_data.x86_model) { - case 26: /* Nehalem */ - case 30: - case 37: /* Westmere */ - case 44: - nhm_uncore_cpu_init(); - break; - case 42: /* Sandy Bridge */ - case 58: /* Ivy Bridge */ - case 60: /* Haswell */ - case 69: /* Haswell */ - case 70: /* Haswell */ - case 61: /* Broadwell */ - case 71: /* Broadwell */ - snb_uncore_cpu_init(); - break; - case 45: /* Sandy Bridge-EP */ - snbep_uncore_cpu_init(); - break; - case 46: /* Nehalem-EX */ - case 47: /* Westmere-EX aka. Xeon E7 */ - nhmex_uncore_cpu_init(); - break; - case 62: /* Ivy Bridge-EP */ - ivbep_uncore_cpu_init(); - break; - case 63: /* Haswell-EP */ - hswep_uncore_cpu_init(); - break; - case 79: /* BDX-EP */ - case 86: /* BDX-DE */ - bdx_uncore_cpu_init(); - break; - case 87: /* Knights Landing */ - knl_uncore_cpu_init(); - break; - default: - return -ENODEV; - } - ret = uncore_types_init(uncore_msr_uncores, true); if (ret) goto err; @@ -1376,11 +1299,105 @@ static int __init uncore_cpumask_init(bool msr) return 0; } +#define X86_UNCORE_MODEL_MATCH(model, init) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init } + +struct intel_uncore_init_fun { + void (*cpu_init)(void); + int (*pci_init)(void); +}; + +static const struct intel_uncore_init_fun nhm_uncore_init __initconst = { + .cpu_init = nhm_uncore_cpu_init, +}; + +static const struct intel_uncore_init_fun snb_uncore_init __initconst = { + .cpu_init = snb_uncore_cpu_init, + .pci_init = snb_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun ivb_uncore_init __initconst = { + .cpu_init = snb_uncore_cpu_init, + .pci_init = ivb_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun hsw_uncore_init __initconst = { + .cpu_init = snb_uncore_cpu_init, + .pci_init = hsw_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun bdw_uncore_init __initconst = { + .cpu_init = snb_uncore_cpu_init, + .pci_init = bdw_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun snbep_uncore_init __initconst = { + .cpu_init = snbep_uncore_cpu_init, + .pci_init = snbep_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun nhmex_uncore_init __initconst = { + .cpu_init = nhmex_uncore_cpu_init, +}; + +static const struct intel_uncore_init_fun ivbep_uncore_init __initconst = { + .cpu_init = ivbep_uncore_cpu_init, + .pci_init = ivbep_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun hswep_uncore_init __initconst = { + .cpu_init = hswep_uncore_cpu_init, + .pci_init = hswep_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun bdx_uncore_init __initconst = { + .cpu_init = bdx_uncore_cpu_init, + .pci_init = bdx_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun knl_uncore_init __initconst = { + .cpu_init = knl_uncore_cpu_init, + .pci_init = knl_uncore_pci_init, +}; + +static const struct intel_uncore_init_fun skl_uncore_init __initconst = { + .pci_init = skl_uncore_pci_init, +}; + +static const struct x86_cpu_id intel_uncore_match[] __initconst = { + X86_UNCORE_MODEL_MATCH(26, nhm_uncore_init), /* Nehalem */ + X86_UNCORE_MODEL_MATCH(30, nhm_uncore_init), + X86_UNCORE_MODEL_MATCH(37, nhm_uncore_init), /* Westmere */ + X86_UNCORE_MODEL_MATCH(44, nhm_uncore_init), + X86_UNCORE_MODEL_MATCH(42, snb_uncore_init), /* Sandy Bridge */ + X86_UNCORE_MODEL_MATCH(58, ivb_uncore_init), /* Ivy Bridge */ + X86_UNCORE_MODEL_MATCH(60, hsw_uncore_init), /* Haswell */ + X86_UNCORE_MODEL_MATCH(69, hsw_uncore_init), /* Haswell Celeron */ + X86_UNCORE_MODEL_MATCH(70, hsw_uncore_init), /* Haswell */ + X86_UNCORE_MODEL_MATCH(61, bdw_uncore_init), /* Broadwell */ + X86_UNCORE_MODEL_MATCH(71, bdw_uncore_init), /* Broadwell */ + X86_UNCORE_MODEL_MATCH(45, snbep_uncore_init), /* Sandy Bridge-EP */ + X86_UNCORE_MODEL_MATCH(46, nhmex_uncore_init), /* Nehalem-EX */ + X86_UNCORE_MODEL_MATCH(47, nhmex_uncore_init), /* Westmere-EX aka. Xeon E7 */ + X86_UNCORE_MODEL_MATCH(62, ivbep_uncore_init), /* Ivy Bridge-EP */ + X86_UNCORE_MODEL_MATCH(63, hswep_uncore_init), /* Haswell-EP */ + X86_UNCORE_MODEL_MATCH(79, bdx_uncore_init), /* BDX-EP */ + X86_UNCORE_MODEL_MATCH(86, bdx_uncore_init), /* BDX-DE */ + X86_UNCORE_MODEL_MATCH(87, knl_uncore_init), /* Knights Landing */ + X86_UNCORE_MODEL_MATCH(94, skl_uncore_init), /* SkyLake */ + {}, +}; + +MODULE_DEVICE_TABLE(x86cpu, intel_uncore_match); + static int __init intel_uncore_init(void) { - int pret, cret, ret; + const struct x86_cpu_id *id; + struct intel_uncore_init_fun *uncore_init; + int pret = 0, cret = 0, ret; - if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) + id = x86_match_cpu(intel_uncore_match); + if (!id) return -ENODEV; if (cpu_has_hypervisor) @@ -1388,8 +1405,17 @@ static int __init intel_uncore_init(void) max_packages = topology_max_packages(); - pret = uncore_pci_init(); - cret = uncore_cpu_init(); + uncore_init = (struct intel_uncore_init_fun *)id->driver_data; + if (uncore_init->pci_init) { + pret = uncore_init->pci_init(); + if (!pret) + pret = uncore_pci_init(); + } + + if (uncore_init->cpu_init) { + uncore_init->cpu_init(); + cret = uncore_cpu_init(); + } if (cret && pret) return -ENODEV; @@ -1409,4 +1435,14 @@ static int __init intel_uncore_init(void) cpu_notifier_register_done(); return ret; } -device_initcall(intel_uncore_init); +module_init(intel_uncore_init); + +static void __exit intel_uncore_exit(void) +{ + cpu_notifier_register_begin(); + __unregister_cpu_notifier(&uncore_cpu_nb); + uncore_types_exit(uncore_msr_uncores); + uncore_pci_exit(); + cpu_notifier_register_done(); +} +module_exit(intel_uncore_exit); -- GitLab From 4b6e2571bf00019e016255ad62b56feb9f498db7 Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Sat, 19 Mar 2016 00:20:50 -0700 Subject: [PATCH 0922/9938] x86/perf/intel/rapl: Make the Intel RAPL PMU driver modular By default, the RAPL driver will be built into the kernel. If it is configured as a module, the supported CPU model can be auto loaded. Also clean up the code of rapl_pmu_init(). Based-on-a-patch-by: Thomas Gleixner Signed-off-by: Kan Liang Signed-off-by: Thomas Gleixner Reviewed-by: Thomas Gleixner Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Link: http://lkml.kernel.org/r/1458372050-2420-2-git-send-email-kan.liang@intel.com Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.perf | 8 +++ arch/x86/events/intel/Makefile | 3 +- arch/x86/events/intel/rapl.c | 121 ++++++++++++++++++++++----------- 3 files changed, 92 insertions(+), 40 deletions(-) diff --git a/arch/x86/Kconfig.perf b/arch/x86/Kconfig.perf index 90b7f5878c96..b239ad5d0a4e 100644 --- a/arch/x86/Kconfig.perf +++ b/arch/x86/Kconfig.perf @@ -8,4 +8,12 @@ config PERF_EVENTS_INTEL_UNCORE Include support for Intel uncore performance events. These are available on NehalemEX and more modern processors. +config PERF_EVENTS_INTEL_RAPL + tristate "Intel rapl performance events" + depends on PERF_EVENTS && CPU_SUP_INTEL && PCI + default y + ---help--- + Include support for Intel rapl performance events for power + monitoring on modern processors. + endmenu diff --git a/arch/x86/events/intel/Makefile b/arch/x86/events/intel/Makefile index a6c744871a73..27adbbab9910 100644 --- a/arch/x86/events/intel/Makefile +++ b/arch/x86/events/intel/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_CPU_SUP_INTEL) += core.o bts.o cqm.o obj-$(CONFIG_CPU_SUP_INTEL) += cstate.o ds.o knc.o obj-$(CONFIG_CPU_SUP_INTEL) += lbr.o p4.o p6.o pt.o -obj-$(CONFIG_CPU_SUP_INTEL) += rapl.o +obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl.o +intel-rapl-objs := rapl.o obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 70c93f9b03ac..e657de1923c2 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -53,6 +53,8 @@ #include #include "../perf_event.h" +MODULE_LICENSE("GPL"); + /* * RAPL energy status counters */ @@ -592,6 +594,11 @@ static int rapl_cpu_notifier(struct notifier_block *self, return NOTIFY_OK; } +static struct notifier_block rapl_cpu_nb = { + .notifier_call = rapl_cpu_notifier, + .priority = CPU_PRI_PERF + 1, +}; + static int rapl_check_hw_unit(bool apply_quirk) { u64 msr_rapl_power_unit_bits; @@ -660,7 +667,7 @@ static int __init rapl_prepare_cpus(void) return 0; } -static void __init cleanup_rapl_pmus(void) +static void cleanup_rapl_pmus(void) { int i; @@ -691,51 +698,77 @@ static int __init init_rapl_pmus(void) return 0; } +#define X86_RAPL_MODEL_MATCH(model, init) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init } + +struct intel_rapl_init_fun { + bool apply_quirk; + int cntr_mask; + struct attribute **attrs; +}; + +static const struct intel_rapl_init_fun snb_rapl_init __initconst = { + .apply_quirk = false, + .cntr_mask = RAPL_IDX_CLN, + .attrs = rapl_events_cln_attr, +}; + +static const struct intel_rapl_init_fun hsx_rapl_init __initconst = { + .apply_quirk = true, + .cntr_mask = RAPL_IDX_SRV, + .attrs = rapl_events_srv_attr, +}; + +static const struct intel_rapl_init_fun hsw_rapl_init __initconst = { + .apply_quirk = false, + .cntr_mask = RAPL_IDX_HSW, + .attrs = rapl_events_hsw_attr, +}; + +static const struct intel_rapl_init_fun snbep_rapl_init __initconst = { + .apply_quirk = false, + .cntr_mask = RAPL_IDX_SRV, + .attrs = rapl_events_srv_attr, +}; + +static const struct intel_rapl_init_fun knl_rapl_init __initconst = { + .apply_quirk = true, + .cntr_mask = RAPL_IDX_KNL, + .attrs = rapl_events_knl_attr, +}; + static const struct x86_cpu_id rapl_cpu_match[] __initconst = { - [0] = { .vendor = X86_VENDOR_INTEL, .family = 6 }, - [1] = {}, + X86_RAPL_MODEL_MATCH(42, snb_rapl_init), /* Sandy Bridge */ + X86_RAPL_MODEL_MATCH(58, snb_rapl_init), /* Ivy Bridge */ + X86_RAPL_MODEL_MATCH(63, hsx_rapl_init), /* Haswell-Server */ + X86_RAPL_MODEL_MATCH(79, hsx_rapl_init), /* Broadwell-Server */ + X86_RAPL_MODEL_MATCH(60, hsw_rapl_init), /* Haswell */ + X86_RAPL_MODEL_MATCH(69, hsw_rapl_init), /* Haswell-Celeron */ + X86_RAPL_MODEL_MATCH(61, hsw_rapl_init), /* Broadwell */ + X86_RAPL_MODEL_MATCH(71, hsw_rapl_init), /* Broadwell-H */ + X86_RAPL_MODEL_MATCH(45, snbep_rapl_init), /* Sandy Bridge-EP */ + X86_RAPL_MODEL_MATCH(62, snbep_rapl_init), /* IvyTown */ + X86_RAPL_MODEL_MATCH(87, knl_rapl_init), /* Knights Landing */ + {}, }; +MODULE_DEVICE_TABLE(x86cpu, rapl_cpu_match); + static int __init rapl_pmu_init(void) { - bool apply_quirk = false; + const struct x86_cpu_id *id; + struct intel_rapl_init_fun *rapl_init; + bool apply_quirk; int ret; - if (!x86_match_cpu(rapl_cpu_match)) + id = x86_match_cpu(rapl_cpu_match); + if (!id) return -ENODEV; - switch (boot_cpu_data.x86_model) { - case 42: /* Sandy Bridge */ - case 58: /* Ivy Bridge */ - rapl_cntr_mask = RAPL_IDX_CLN; - rapl_pmu_events_group.attrs = rapl_events_cln_attr; - break; - case 63: /* Haswell-Server */ - case 79: /* Broadwell-Server */ - apply_quirk = true; - rapl_cntr_mask = RAPL_IDX_SRV; - rapl_pmu_events_group.attrs = rapl_events_srv_attr; - break; - case 60: /* Haswell */ - case 69: /* Haswell-Celeron */ - case 61: /* Broadwell */ - case 71: /* Broadwell-H */ - rapl_cntr_mask = RAPL_IDX_HSW; - rapl_pmu_events_group.attrs = rapl_events_hsw_attr; - break; - case 45: /* Sandy Bridge-EP */ - case 62: /* IvyTown */ - rapl_cntr_mask = RAPL_IDX_SRV; - rapl_pmu_events_group.attrs = rapl_events_srv_attr; - break; - case 87: /* Knights Landing */ - apply_quirk = true; - rapl_cntr_mask = RAPL_IDX_KNL; - rapl_pmu_events_group.attrs = rapl_events_knl_attr; - break; - default: - return -ENODEV; - } + rapl_init = (struct intel_rapl_init_fun *)id->driver_data; + apply_quirk = rapl_init->apply_quirk; + rapl_cntr_mask = rapl_init->cntr_mask; + rapl_pmu_events_group.attrs = rapl_init->attrs; ret = rapl_check_hw_unit(apply_quirk); if (ret) @@ -755,7 +788,7 @@ static int __init rapl_pmu_init(void) if (ret) goto out; - __perf_cpu_notifier(rapl_cpu_notifier); + __register_cpu_notifier(&rapl_cpu_nb); cpu_notifier_register_done(); rapl_advertise(); return 0; @@ -766,4 +799,14 @@ static int __init rapl_pmu_init(void) cpu_notifier_register_done(); return ret; } -device_initcall(rapl_pmu_init); +module_init(rapl_pmu_init); + +static void __exit intel_rapl_exit(void) +{ + cpu_notifier_register_begin(); + __unregister_cpu_notifier(&rapl_cpu_nb); + perf_pmu_unregister(&rapl_pmus->pmu); + cleanup_rapl_pmus(); + cpu_notifier_register_done(); +} +module_exit(intel_rapl_exit); -- GitLab From 49de0493e5f67a8023fa6fa5c89097c1f77de74e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 20 Mar 2016 18:59:02 +0000 Subject: [PATCH 0923/9938] x86/perf/intel/cstate: Make cstate hotplug handling actually work The current implementation aside of being an incomprehensible mess is broken. # cat /sys/bus/event_source/devices/cstate_core/cpumask 0-17 That's on a quad socket machine with 72 physical cores! Qualitee stuff. So it's not a surprise that event migration in case of CPU hotplug does not work either. # perf stat -e cstate_core/c6-residency/ -C 1 sleep 60 & # echo 0 >/sys/devices/system/cpu/cpu1/online Tracing cstate_pmu_event_update gives me: [001] cstate_pmu_event_update <-event_sched_out After the fix it properly moves the event: [001] cstate_pmu_event_update <-event_sched_out [073] cstate_pmu_event_update <-__perf_event_read [073] cstate_pmu_event_update <-event_sched_out The migration of pkg events does not work either. Not that I'm surprised. I really could not be bothered to decode that loop mess and simply replaced it by querying the proper cpumasks which give us the answer in a comprehensible way. This also requires to direct the event to the current active reader CPU in cstate_pmu_event_init() otherwise the hotplug logic can't work. Signed-off-by: Thomas Gleixner [ Added event->cpu < 0 test to not explode] Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Link: http://lkml.kernel.org/r/20160320185623.422519970@linutronix.de Signed-off-by: Ingo Molnar --- arch/x86/events/intel/cstate.c | 122 ++++++++++++++------------------- 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 7946c4231169..5c2f55fe142a 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -385,7 +385,7 @@ static ssize_t cstate_get_attr_cpumask(struct device *dev, static int cstate_pmu_event_init(struct perf_event *event) { u64 cfg = event->attr.config; - int ret = 0; + int cpu; if (event->attr.type != event->pmu->type) return -ENOENT; @@ -400,26 +400,36 @@ static int cstate_pmu_event_init(struct perf_event *event) event->attr.sample_period) /* no sampling */ return -EINVAL; + if (event->cpu < 0) + return -EINVAL; + if (event->pmu == &cstate_core_pmu) { if (cfg >= PERF_CSTATE_CORE_EVENT_MAX) return -EINVAL; if (!core_msr[cfg].attr) return -EINVAL; event->hw.event_base = core_msr[cfg].msr; + cpu = cpumask_any_and(&cstate_core_cpu_mask, + topology_sibling_cpumask(event->cpu)); } else if (event->pmu == &cstate_pkg_pmu) { if (cfg >= PERF_CSTATE_PKG_EVENT_MAX) return -EINVAL; if (!pkg_msr[cfg].attr) return -EINVAL; event->hw.event_base = pkg_msr[cfg].msr; - } else + cpu = cpumask_any_and(&cstate_pkg_cpu_mask, + topology_core_cpumask(event->cpu)); + } else { return -ENOENT; + } - /* must be done before validate_group */ + if (cpu >= nr_cpu_ids) + return -ENODEV; + + event->cpu = cpu; event->hw.config = cfg; event->hw.idx = -1; - - return ret; + return 0; } static inline u64 cstate_pmu_read_counter(struct perf_event *event) @@ -469,102 +479,76 @@ static int cstate_pmu_event_add(struct perf_event *event, int mode) return 0; } +/* + * Check if exiting cpu is the designated reader. If so migrate the + * events when there is a valid target available + */ static void cstate_cpu_exit(int cpu) { - int i, id, target; + unsigned int target; - /* cpu exit for cstate core */ - if (has_cstate_core) { - id = topology_core_id(cpu); - target = -1; - - for_each_online_cpu(i) { - if (i == cpu) - continue; - if (id == topology_core_id(i)) { - target = i; - break; - } - } - if (cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask) && target >= 0) + if (has_cstate_core && + cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask)) { + + target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); + /* Migrate events if there is a valid target */ + if (target < nr_cpu_ids) { cpumask_set_cpu(target, &cstate_core_cpu_mask); - WARN_ON(cpumask_empty(&cstate_core_cpu_mask)); - if (target >= 0) perf_pmu_migrate_context(&cstate_core_pmu, cpu, target); + } } - /* cpu exit for cstate pkg */ - if (has_cstate_pkg) { - id = topology_physical_package_id(cpu); - target = -1; - - for_each_online_cpu(i) { - if (i == cpu) - continue; - if (id == topology_physical_package_id(i)) { - target = i; - break; - } - } - if (cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask) && target >= 0) + if (has_cstate_pkg && + cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) { + + target = cpumask_any_but(topology_core_cpumask(cpu), cpu); + /* Migrate events if there is a valid target */ + if (target < nr_cpu_ids) { cpumask_set_cpu(target, &cstate_pkg_cpu_mask); - WARN_ON(cpumask_empty(&cstate_pkg_cpu_mask)); - if (target >= 0) perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target); + } } } static void cstate_cpu_init(int cpu) { - int i, id; + unsigned int target; - /* cpu init for cstate core */ - if (has_cstate_core) { - id = topology_core_id(cpu); - for_each_cpu(i, &cstate_core_cpu_mask) { - if (id == topology_core_id(i)) - break; - } - if (i >= nr_cpu_ids) - cpumask_set_cpu(cpu, &cstate_core_cpu_mask); - } + /* + * If this is the first online thread of that core, set it in + * the core cpu mask as the designated reader. + */ + target = cpumask_any_and(&cstate_core_cpu_mask, + topology_sibling_cpumask(cpu)); - /* cpu init for cstate pkg */ - if (has_cstate_pkg) { - id = topology_physical_package_id(cpu); - for_each_cpu(i, &cstate_pkg_cpu_mask) { - if (id == topology_physical_package_id(i)) - break; - } - if (i >= nr_cpu_ids) - cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask); - } + if (has_cstate_core && target >= nr_cpu_ids) + cpumask_set_cpu(cpu, &cstate_core_cpu_mask); + + /* + * If this is the first online thread of that package, set it + * in the package cpu mask as the designated reader. + */ + target = cpumask_any_and(&cstate_pkg_cpu_mask, + topology_core_cpumask(cpu)); + if (has_cstate_pkg && target >= nr_cpu_ids) + cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask); } static int cstate_cpu_notifier(struct notifier_block *self, - unsigned long action, void *hcpu) + unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; switch (action & ~CPU_TASKS_FROZEN) { - case CPU_UP_PREPARE: - break; case CPU_STARTING: cstate_cpu_init(cpu); break; - case CPU_UP_CANCELED: - case CPU_DYING: - break; - case CPU_ONLINE: - case CPU_DEAD: - break; case CPU_DOWN_PREPARE: cstate_cpu_exit(cpu); break; default: break; } - return NOTIFY_OK; } -- GitLab From 424646eeadab64da959f960928804e5289417819 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 20 Mar 2016 18:59:03 +0000 Subject: [PATCH 0924/9938] x86/perf/intel/cstate: Sanitize probing The whole probing functionality can simply be expressed with model matching and a bunch of structures describing the variants. This is a first step to make that driver modular. While at it, get rid of completely pointless comments and name the enums so they are self explaining. Signed-off-by: Thomas Gleixner [ Reworked probing to clear msr[].attr for all !present msrs. ] Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Link: http://lkml.kernel.org/r/20160320185623.500381872@linutronix.de Signed-off-by: Ingo Molnar --- arch/x86/events/intel/cstate.c | 359 +++++++++++++++------------------ 1 file changed, 160 insertions(+), 199 deletions(-) diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 5c2f55fe142a..1aac40f1e4fe 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -106,22 +106,27 @@ static ssize_t cstate_get_attr_cpumask(struct device *dev, struct device_attribute *attr, char *buf); +/* Model -> events mapping */ +struct cstate_model { + unsigned long core_events; + unsigned long pkg_events; + unsigned long quirks; +}; + +/* Quirk flags */ +#define SLM_PKG_C6_USE_C7_MSR (1UL << 0) + struct perf_cstate_msr { u64 msr; struct perf_pmu_events_attr *attr; - bool (*test)(int idx); }; /* cstate_core PMU */ - static struct pmu cstate_core_pmu; static bool has_cstate_core; -enum perf_cstate_core_id { - /* - * cstate_core events - */ +enum perf_cstate_core_events { PERF_CSTATE_CORE_C1_RES = 0, PERF_CSTATE_CORE_C3_RES, PERF_CSTATE_CORE_C6_RES, @@ -130,69 +135,16 @@ enum perf_cstate_core_id { PERF_CSTATE_CORE_EVENT_MAX, }; -bool test_core(int idx) -{ - if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || - boot_cpu_data.x86 != 6) - return false; - - switch (boot_cpu_data.x86_model) { - case 30: /* 45nm Nehalem */ - case 26: /* 45nm Nehalem-EP */ - case 46: /* 45nm Nehalem-EX */ - - case 37: /* 32nm Westmere */ - case 44: /* 32nm Westmere-EP */ - case 47: /* 32nm Westmere-EX */ - if (idx == PERF_CSTATE_CORE_C3_RES || - idx == PERF_CSTATE_CORE_C6_RES) - return true; - break; - case 42: /* 32nm SandyBridge */ - case 45: /* 32nm SandyBridge-E/EN/EP */ - - case 58: /* 22nm IvyBridge */ - case 62: /* 22nm IvyBridge-EP/EX */ - - case 60: /* 22nm Haswell Core */ - case 63: /* 22nm Haswell Server */ - case 69: /* 22nm Haswell ULT */ - case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */ - - case 61: /* 14nm Broadwell Core-M */ - case 86: /* 14nm Broadwell Xeon D */ - case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */ - case 79: /* 14nm Broadwell Server */ - - case 78: /* 14nm Skylake Mobile */ - case 94: /* 14nm Skylake Desktop */ - if (idx == PERF_CSTATE_CORE_C3_RES || - idx == PERF_CSTATE_CORE_C6_RES || - idx == PERF_CSTATE_CORE_C7_RES) - return true; - break; - case 55: /* 22nm Atom "Silvermont" */ - case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */ - case 76: /* 14nm Atom "Airmont" */ - if (idx == PERF_CSTATE_CORE_C1_RES || - idx == PERF_CSTATE_CORE_C6_RES) - return true; - break; - } - - return false; -} - PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00"); PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01"); PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02"); PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03"); static struct perf_cstate_msr core_msr[] = { - [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &evattr_cstate_core_c1, test_core, }, - [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &evattr_cstate_core_c3, test_core, }, - [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &evattr_cstate_core_c6, test_core, }, - [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &evattr_cstate_core_c7, test_core, }, + [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &evattr_cstate_core_c1 }, + [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &evattr_cstate_core_c3 }, + [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &evattr_cstate_core_c6 }, + [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &evattr_cstate_core_c7 }, }; static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = { @@ -234,18 +186,11 @@ static const struct attribute_group *core_attr_groups[] = { NULL, }; -/* cstate_core PMU end */ - - /* cstate_pkg PMU */ - static struct pmu cstate_pkg_pmu; static bool has_cstate_pkg; -enum perf_cstate_pkg_id { - /* - * cstate_pkg events - */ +enum perf_cstate_pkg_events { PERF_CSTATE_PKG_C2_RES = 0, PERF_CSTATE_PKG_C3_RES, PERF_CSTATE_PKG_C6_RES, @@ -257,69 +202,6 @@ enum perf_cstate_pkg_id { PERF_CSTATE_PKG_EVENT_MAX, }; -bool test_pkg(int idx) -{ - if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || - boot_cpu_data.x86 != 6) - return false; - - switch (boot_cpu_data.x86_model) { - case 30: /* 45nm Nehalem */ - case 26: /* 45nm Nehalem-EP */ - case 46: /* 45nm Nehalem-EX */ - - case 37: /* 32nm Westmere */ - case 44: /* 32nm Westmere-EP */ - case 47: /* 32nm Westmere-EX */ - if (idx == PERF_CSTATE_CORE_C3_RES || - idx == PERF_CSTATE_CORE_C6_RES || - idx == PERF_CSTATE_CORE_C7_RES) - return true; - break; - case 42: /* 32nm SandyBridge */ - case 45: /* 32nm SandyBridge-E/EN/EP */ - - case 58: /* 22nm IvyBridge */ - case 62: /* 22nm IvyBridge-EP/EX */ - - case 60: /* 22nm Haswell Core */ - case 63: /* 22nm Haswell Server */ - case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */ - - case 61: /* 14nm Broadwell Core-M */ - case 86: /* 14nm Broadwell Xeon D */ - case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */ - case 79: /* 14nm Broadwell Server */ - - case 78: /* 14nm Skylake Mobile */ - case 94: /* 14nm Skylake Desktop */ - if (idx == PERF_CSTATE_PKG_C2_RES || - idx == PERF_CSTATE_PKG_C3_RES || - idx == PERF_CSTATE_PKG_C6_RES || - idx == PERF_CSTATE_PKG_C7_RES) - return true; - break; - case 55: /* 22nm Atom "Silvermont" */ - case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */ - case 76: /* 14nm Atom "Airmont" */ - if (idx == PERF_CSTATE_CORE_C6_RES) - return true; - break; - case 69: /* 22nm Haswell ULT */ - if (idx == PERF_CSTATE_PKG_C2_RES || - idx == PERF_CSTATE_PKG_C3_RES || - idx == PERF_CSTATE_PKG_C6_RES || - idx == PERF_CSTATE_PKG_C7_RES || - idx == PERF_CSTATE_PKG_C8_RES || - idx == PERF_CSTATE_PKG_C9_RES || - idx == PERF_CSTATE_PKG_C10_RES) - return true; - break; - } - - return false; -} - PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00"); PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01"); PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02"); @@ -329,13 +211,13 @@ PMU_EVENT_ATTR_STRING(c9-residency, evattr_cstate_pkg_c9, "event=0x05"); PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06"); static struct perf_cstate_msr pkg_msr[] = { - [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &evattr_cstate_pkg_c2, test_pkg, }, - [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &evattr_cstate_pkg_c3, test_pkg, }, - [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &evattr_cstate_pkg_c6, test_pkg, }, - [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &evattr_cstate_pkg_c7, test_pkg, }, - [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &evattr_cstate_pkg_c8, test_pkg, }, - [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &evattr_cstate_pkg_c9, test_pkg, }, - [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &evattr_cstate_pkg_c10, test_pkg, }, + [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &evattr_cstate_pkg_c2 }, + [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &evattr_cstate_pkg_c3 }, + [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &evattr_cstate_pkg_c6 }, + [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &evattr_cstate_pkg_c7 }, + [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &evattr_cstate_pkg_c8 }, + [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &evattr_cstate_pkg_c9 }, + [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &evattr_cstate_pkg_c10 }, }; static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = { @@ -366,8 +248,6 @@ static const struct attribute_group *pkg_attr_groups[] = { NULL, }; -/* cstate_pkg PMU end*/ - static ssize_t cstate_get_attr_cpumask(struct device *dev, struct device_attribute *attr, char *buf) @@ -552,48 +432,151 @@ static int cstate_cpu_notifier(struct notifier_block *self, return NOTIFY_OK; } +static struct pmu cstate_core_pmu = { + .attr_groups = core_attr_groups, + .name = "cstate_core", + .task_ctx_nr = perf_invalid_context, + .event_init = cstate_pmu_event_init, + .add = cstate_pmu_event_add, + .del = cstate_pmu_event_del, + .start = cstate_pmu_event_start, + .stop = cstate_pmu_event_stop, + .read = cstate_pmu_event_update, + .capabilities = PERF_PMU_CAP_NO_INTERRUPT, +}; + +static struct pmu cstate_pkg_pmu = { + .attr_groups = pkg_attr_groups, + .name = "cstate_pkg", + .task_ctx_nr = perf_invalid_context, + .event_init = cstate_pmu_event_init, + .add = cstate_pmu_event_add, + .del = cstate_pmu_event_del, + .start = cstate_pmu_event_start, + .stop = cstate_pmu_event_stop, + .read = cstate_pmu_event_update, + .capabilities = PERF_PMU_CAP_NO_INTERRUPT, +}; + +static const struct cstate_model nhm_cstates __initconst = { + .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | + BIT(PERF_CSTATE_CORE_C6_RES), + + .pkg_events = BIT(PERF_CSTATE_PKG_C3_RES) | + BIT(PERF_CSTATE_PKG_C6_RES) | + BIT(PERF_CSTATE_PKG_C7_RES), +}; + +static const struct cstate_model snb_cstates __initconst = { + .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | + BIT(PERF_CSTATE_CORE_C6_RES) | + BIT(PERF_CSTATE_CORE_C7_RES), + + .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | + BIT(PERF_CSTATE_PKG_C3_RES) | + BIT(PERF_CSTATE_PKG_C6_RES) | + BIT(PERF_CSTATE_PKG_C7_RES), +}; + +static const struct cstate_model hswult_cstates __initconst = { + .core_events = BIT(PERF_CSTATE_CORE_C3_RES) | + BIT(PERF_CSTATE_CORE_C6_RES) | + BIT(PERF_CSTATE_CORE_C7_RES), + + .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | + BIT(PERF_CSTATE_PKG_C3_RES) | + BIT(PERF_CSTATE_PKG_C6_RES) | + BIT(PERF_CSTATE_PKG_C7_RES) | + BIT(PERF_CSTATE_PKG_C8_RES) | + BIT(PERF_CSTATE_PKG_C9_RES) | + BIT(PERF_CSTATE_PKG_C10_RES), +}; + +static const struct cstate_model slm_cstates __initconst = { + .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | + BIT(PERF_CSTATE_CORE_C6_RES), + + .pkg_events = BIT(PERF_CSTATE_PKG_C6_RES), + .quirks = SLM_PKG_C6_USE_C7_MSR, +}; + +#define X86_CSTATES_MODEL(model, states) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long) &(states) } + +static const struct x86_cpu_id intel_cstates_match[] __initconst = { + X86_CSTATES_MODEL(30, nhm_cstates), /* 45nm Nehalem */ + X86_CSTATES_MODEL(26, nhm_cstates), /* 45nm Nehalem-EP */ + X86_CSTATES_MODEL(46, nhm_cstates), /* 45nm Nehalem-EX */ + + X86_CSTATES_MODEL(37, nhm_cstates), /* 32nm Westmere */ + X86_CSTATES_MODEL(44, nhm_cstates), /* 32nm Westmere-EP */ + X86_CSTATES_MODEL(47, nhm_cstates), /* 32nm Westmere-EX */ + + X86_CSTATES_MODEL(42, snb_cstates), /* 32nm SandyBridge */ + X86_CSTATES_MODEL(45, snb_cstates), /* 32nm SandyBridge-E/EN/EP */ + + X86_CSTATES_MODEL(58, snb_cstates), /* 22nm IvyBridge */ + X86_CSTATES_MODEL(62, snb_cstates), /* 22nm IvyBridge-EP/EX */ + + X86_CSTATES_MODEL(60, snb_cstates), /* 22nm Haswell Core */ + X86_CSTATES_MODEL(63, snb_cstates), /* 22nm Haswell Server */ + X86_CSTATES_MODEL(70, snb_cstates), /* 22nm Haswell + GT3e */ + + X86_CSTATES_MODEL(69, hswult_cstates), /* 22nm Haswell ULT */ + + X86_CSTATES_MODEL(55, slm_cstates), /* 22nm Atom Silvermont */ + X86_CSTATES_MODEL(77, slm_cstates), /* 22nm Atom Avoton/Rangely */ + X86_CSTATES_MODEL(76, slm_cstates), /* 22nm Atom Airmont */ + + X86_CSTATES_MODEL(61, snb_cstates), /* 14nm Broadwell Core-M */ + X86_CSTATES_MODEL(86, snb_cstates), /* 14nm Broadwell Xeon D */ + X86_CSTATES_MODEL(71, snb_cstates), /* 14nm Broadwell + GT3e */ + X86_CSTATES_MODEL(79, snb_cstates), /* 14nm Broadwell Server */ + + X86_CSTATES_MODEL(78, snb_cstates), /* 14nm Skylake Mobile */ + X86_CSTATES_MODEL(94, snb_cstates), /* 14nm Skylake Desktop */ + { }, +}; +MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match); + /* * Probe the cstate events and insert the available one into sysfs attrs - * Return false if there is no available events. + * Return false if there are no available events. */ -static bool cstate_probe_msr(struct perf_cstate_msr *msr, - struct attribute **events_attrs, - int max_event_nr) +static bool __init cstate_probe_msr(const unsigned long evmsk, int max, + struct perf_cstate_msr *msr, + struct attribute **attrs) { - int i, j = 0; + bool found = false; + unsigned int bit; u64 val; - /* Probe the cstate events. */ - for (i = 0; i < max_event_nr; i++) { - if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val)) - msr[i].attr = NULL; - } - - /* List remaining events in the sysfs attrs. */ - for (i = 0; i < max_event_nr; i++) { - if (msr[i].attr) - events_attrs[j++] = &msr[i].attr->attr.attr; + for (bit = 0; bit < max; bit++) { + if (test_bit(bit, &evmsk) && !rdmsrl_safe(msr[bit].msr, &val)) { + *attrs++ = &msr[bit].attr->attr.attr; + found = true; + } else { + msr[bit].attr = NULL; + } } - events_attrs[j] = NULL; + *attrs = NULL; - return (j > 0) ? true : false; + return found; } -static int __init cstate_init(void) +static int __init cstate_probe(const struct cstate_model *cm) { /* SLM has different MSR for PKG C6 */ - switch (boot_cpu_data.x86_model) { - case 55: - case 76: - case 77: + if (cm->quirks & SLM_PKG_C6_USE_C7_MSR) pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY; - } - if (cstate_probe_msr(core_msr, core_events_attrs, PERF_CSTATE_CORE_EVENT_MAX)) - has_cstate_core = true; + has_cstate_core = cstate_probe_msr(cm->core_events, + PERF_CSTATE_CORE_EVENT_MAX, + core_msr, core_events_attrs); - if (cstate_probe_msr(pkg_msr, pkg_events_attrs, PERF_CSTATE_PKG_EVENT_MAX)) - has_cstate_pkg = true; + has_cstate_pkg = cstate_probe_msr(cm->pkg_events, + PERF_CSTATE_PKG_EVENT_MAX, + pkg_msr, pkg_events_attrs); return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV; } @@ -612,32 +595,6 @@ static void __init cstate_cpumask_init(void) cpu_notifier_register_done(); } -static struct pmu cstate_core_pmu = { - .attr_groups = core_attr_groups, - .name = "cstate_core", - .task_ctx_nr = perf_invalid_context, - .event_init = cstate_pmu_event_init, - .add = cstate_pmu_event_add, /* must have */ - .del = cstate_pmu_event_del, /* must have */ - .start = cstate_pmu_event_start, - .stop = cstate_pmu_event_stop, - .read = cstate_pmu_event_update, - .capabilities = PERF_PMU_CAP_NO_INTERRUPT, -}; - -static struct pmu cstate_pkg_pmu = { - .attr_groups = pkg_attr_groups, - .name = "cstate_pkg", - .task_ctx_nr = perf_invalid_context, - .event_init = cstate_pmu_event_init, - .add = cstate_pmu_event_add, /* must have */ - .del = cstate_pmu_event_del, /* must have */ - .start = cstate_pmu_event_start, - .stop = cstate_pmu_event_stop, - .read = cstate_pmu_event_update, - .capabilities = PERF_PMU_CAP_NO_INTERRUPT, -}; - static void __init cstate_pmus_register(void) { int err; @@ -659,12 +616,17 @@ static void __init cstate_pmus_register(void) static int __init cstate_pmu_init(void) { + const struct x86_cpu_id *id; int err; - if (cpu_has_hypervisor) + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) return -ENODEV; - err = cstate_init(); + id = x86_match_cpu(intel_cstates_match); + if (!id) + return -ENODEV; + + err = cstate_probe((const struct cstate_model *) id->driver_data); if (err) return err; @@ -674,5 +636,4 @@ static int __init cstate_pmu_init(void) return 0; } - device_initcall(cstate_pmu_init); -- GitLab From d29859e7777ebc2c8e2db6e4d8e299f50fc26414 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 20 Mar 2016 18:59:03 +0000 Subject: [PATCH 0925/9938] x86/perf/intel/cstate: Sanitize error handling There is no point in WARN_ON() inside of a well known init function. We already know the call stack and it's really not of critical importance whether the registration of a PMU fails. Aside of that for consistency reasons it's just pointless to try to register another PMU if the first register attempt failed. There is also no value in keeping one PMU if the second one can not be registered. Make it consistent so we can finaly modularize the driver. Signed-off-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Link: http://lkml.kernel.org/r/20160320185623.579794064@linutronix.de Signed-off-by: Ingo Molnar --- arch/x86/events/intel/cstate.c | 50 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 1aac40f1e4fe..e90ec9e73ac7 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -581,37 +581,45 @@ static int __init cstate_probe(const struct cstate_model *cm) return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV; } -static void __init cstate_cpumask_init(void) +static void __init cstate_cleanup(void) { - int cpu; - - cpu_notifier_register_begin(); - - for_each_online_cpu(cpu) - cstate_cpu_init(cpu); + if (has_cstate_core) + perf_pmu_unregister(&cstate_core_pmu); - __perf_cpu_notifier(cstate_cpu_notifier); - - cpu_notifier_register_done(); + if (has_cstate_pkg) + perf_pmu_unregister(&cstate_pkg_pmu); } -static void __init cstate_pmus_register(void) +static int __init cstate_init(void) { - int err; + int cpu, err; + + cpu_notifier_register_begin(); + for_each_online_cpu(cpu) + cstate_cpu_init(cpu); if (has_cstate_core) { err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1); - if (WARN_ON(err)) - pr_info("Failed to register PMU %s error %d\n", - cstate_core_pmu.name, err); + if (err) { + has_cstate_core = false; + pr_info("Failed to register cstate core pmu\n"); + goto out; + } } if (has_cstate_pkg) { err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1); - if (WARN_ON(err)) - pr_info("Failed to register PMU %s error %d\n", - cstate_pkg_pmu.name, err); + if (err) { + has_cstate_pkg = false; + pr_info("Failed to register cstate pkg pmu\n"); + cstate_cleanup(); + goto out; + } } + __perf_cpu_notifier(cstate_cpu_notifier); +out: + cpu_notifier_register_done(); + return err; } static int __init cstate_pmu_init(void) @@ -630,10 +638,6 @@ static int __init cstate_pmu_init(void) if (err) return err; - cstate_cpumask_init(); - - cstate_pmus_register(); - - return 0; + return cstate_init(); } device_initcall(cstate_pmu_init); -- GitLab From c7afba320e91cca46fdf078798002b9ec84be8d3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 20 Mar 2016 18:59:04 +0000 Subject: [PATCH 0926/9938] x86/perf/intel/cstate: Modularize driver Add the exit function and allow the driver to be built as a module. Signed-off-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Link: http://lkml.kernel.org/r/20160320185623.658869675@linutronix.de Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.perf | 8 ++++++++ arch/x86/events/intel/Makefile | 4 +++- arch/x86/events/intel/cstate.c | 22 +++++++++++++++++++--- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/arch/x86/Kconfig.perf b/arch/x86/Kconfig.perf index b239ad5d0a4e..7d29dd75d07b 100644 --- a/arch/x86/Kconfig.perf +++ b/arch/x86/Kconfig.perf @@ -16,4 +16,12 @@ config PERF_EVENTS_INTEL_RAPL Include support for Intel rapl performance events for power monitoring on modern processors. +config PERF_EVENTS_INTEL_CSTATE + tristate "Intel cstate performance events" + depends on PERF_EVENTS && CPU_SUP_INTEL && PCI + default y + ---help--- + Include support for Intel cstate performance events for power + monitoring on modern processors. + endmenu diff --git a/arch/x86/events/intel/Makefile b/arch/x86/events/intel/Makefile index 27adbbab9910..3660b2cf245a 100644 --- a/arch/x86/events/intel/Makefile +++ b/arch/x86/events/intel/Makefile @@ -1,7 +1,9 @@ obj-$(CONFIG_CPU_SUP_INTEL) += core.o bts.o cqm.o -obj-$(CONFIG_CPU_SUP_INTEL) += cstate.o ds.o knc.o +obj-$(CONFIG_CPU_SUP_INTEL) += ds.o knc.o obj-$(CONFIG_CPU_SUP_INTEL) += lbr.o p4.o p6.o pt.o obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl.o intel-rapl-objs := rapl.o obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o +obj-$(CONFIG_PERF_EVENTS_INTEL_CSTATE) += intel-cstate.o +intel-cstate-objs := cstate.o diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index e90ec9e73ac7..9ba4e4136a15 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -91,6 +91,8 @@ #include #include "../perf_event.h" +MODULE_LICENSE("GPL"); + #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \ static ssize_t __cstate_##_var##_show(struct kobject *kobj, \ struct kobj_attribute *attr, \ @@ -432,6 +434,11 @@ static int cstate_cpu_notifier(struct notifier_block *self, return NOTIFY_OK; } +static struct notifier_block cstate_cpu_nb = { + .notifier_call = cstate_cpu_notifier, + .priority = CPU_PRI_PERF + 1, +}; + static struct pmu cstate_core_pmu = { .attr_groups = core_attr_groups, .name = "cstate_core", @@ -581,7 +588,7 @@ static int __init cstate_probe(const struct cstate_model *cm) return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV; } -static void __init cstate_cleanup(void) +static inline void cstate_cleanup(void) { if (has_cstate_core) perf_pmu_unregister(&cstate_core_pmu); @@ -616,7 +623,7 @@ static int __init cstate_init(void) goto out; } } - __perf_cpu_notifier(cstate_cpu_notifier); + __register_cpu_notifier(&cstate_cpu_nb); out: cpu_notifier_register_done(); return err; @@ -640,4 +647,13 @@ static int __init cstate_pmu_init(void) return cstate_init(); } -device_initcall(cstate_pmu_init); +module_init(cstate_pmu_init); + +static void __exit cstate_pmu_exit(void) +{ + cpu_notifier_register_begin(); + __unregister_cpu_notifier(&cstate_cpu_nb); + cstate_cleanup(); + cpu_notifier_register_done(); +} +module_exit(cstate_pmu_exit); -- GitLab From 8a22426184774d7ced9c1d3aa4d95d34101fb3be Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 29 Jan 2016 16:29:56 +0800 Subject: [PATCH 0927/9938] perf/x86/msr: Add AMD PTSC (Performance Time-Stamp Counter) support AMD Carrizo (Family 15h, Model 60h) introduces a time-stamp counter which is indicated by CPUID.8000_0001H:ECX[27]. It increments at a 100 MHz rate in all P-states, and C states, S0, or S1. The frequency is about 100MHz. This counter will be used to calculate processor power and other parts. So add an interface into the MSR PMU to get the PTSC counter value. Signed-off-by: Huang Rui Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Andy Lutomirski Cc: Aravind Gopalakrishnan Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Borislav Petkov Cc: Fengguang Wu Cc: Jacob Shin Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Cc: Suravee Suthikulpanit Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1454056197-5893-2-git-send-email-ray.huang@amd.com Signed-off-by: Ingo Molnar --- arch/x86/events/msr.c | 8 ++++++++ arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/msr-index.h | 1 + 3 files changed, 10 insertions(+) diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c index ec863b9a9f78..6f6772f273aa 100644 --- a/arch/x86/events/msr.c +++ b/arch/x86/events/msr.c @@ -6,6 +6,7 @@ enum perf_msr_id { PERF_MSR_MPERF = 2, PERF_MSR_PPERF = 3, PERF_MSR_SMI = 4, + PERF_MSR_PTSC = 5, PERF_MSR_EVENT_MAX, }; @@ -15,6 +16,11 @@ static bool test_aperfmperf(int idx) return boot_cpu_has(X86_FEATURE_APERFMPERF); } +static bool test_ptsc(int idx) +{ + return boot_cpu_has(X86_FEATURE_PTSC); +} + static bool test_intel(int idx) { if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || @@ -74,6 +80,7 @@ PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01"); PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02"); PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03"); PMU_EVENT_ATTR_STRING(smi, evattr_smi, "event=0x04"); +PMU_EVENT_ATTR_STRING(ptsc, evattr_ptsc, "event=0x05"); static struct perf_msr msr[] = { [PERF_MSR_TSC] = { 0, &evattr_tsc, NULL, }, @@ -81,6 +88,7 @@ static struct perf_msr msr[] = { [PERF_MSR_MPERF] = { MSR_IA32_MPERF, &evattr_mperf, test_aperfmperf, }, [PERF_MSR_PPERF] = { MSR_PPERF, &evattr_pperf, test_intel, }, [PERF_MSR_SMI] = { MSR_SMI_COUNT, &evattr_smi, test_intel, }, + [PERF_MSR_PTSC] = { MSR_F15H_PTSC, &evattr_ptsc, test_ptsc, }, }; static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = { diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 44ebd04878eb..bdf9042f0295 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -177,6 +177,7 @@ #define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */ #define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */ #define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */ +#define X86_FEATURE_PTSC ( 6*32+27) /* performance time-stamp counter */ #define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ #define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 984ab75bf621..6e6a5ccfb3f5 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -326,6 +326,7 @@ #define MSR_F15H_PERF_CTR 0xc0010201 #define MSR_F15H_NB_PERF_CTL 0xc0010240 #define MSR_F15H_NB_PERF_CTR 0xc0010241 +#define MSR_F15H_PTSC 0xc0010280 #define MSR_F15H_IC_CFG 0xc0011021 /* Fam 10h MSRs */ -- GitLab From aaf248848db503927644d28e239bc399ed45959f Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 29 Jan 2016 16:29:57 +0800 Subject: [PATCH 0928/9938] perf/x86/msr: Add AMD IRPERF (Instructions Retired) performance counter AMD Zeppelin (Family 17h, Model 00h) introduces an instructions retired performance counter which is indicated by CPUID.8000_0008H:EBX[1]. A dedicated Instructions Retired MSR register (MSR 0xC000_000E9) increments once for every instruction retired. Signed-off-by: Huang Rui Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Andy Lutomirski Cc: Aravind Gopalakrishnan Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Borislav Petkov Cc: Fengguang Wu Cc: Jacob Shin Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Cc: Suravee Suthikulpanit Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1454056197-5893-3-git-send-email-ray.huang@amd.com Signed-off-by: Ingo Molnar --- arch/x86/events/msr.c | 30 +++++++++++++++++++----------- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/msr-index.h | 3 +++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c index 6f6772f273aa..7111400a1f9a 100644 --- a/arch/x86/events/msr.c +++ b/arch/x86/events/msr.c @@ -7,6 +7,7 @@ enum perf_msr_id { PERF_MSR_PPERF = 3, PERF_MSR_SMI = 4, PERF_MSR_PTSC = 5, + PERF_MSR_IRPERF = 6, PERF_MSR_EVENT_MAX, }; @@ -21,6 +22,11 @@ static bool test_ptsc(int idx) return boot_cpu_has(X86_FEATURE_PTSC); } +static bool test_irperf(int idx) +{ + return boot_cpu_has(X86_FEATURE_IRPERF); +} + static bool test_intel(int idx) { if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || @@ -75,20 +81,22 @@ struct perf_msr { bool (*test)(int idx); }; -PMU_EVENT_ATTR_STRING(tsc, evattr_tsc, "event=0x00"); -PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01"); -PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02"); -PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03"); -PMU_EVENT_ATTR_STRING(smi, evattr_smi, "event=0x04"); -PMU_EVENT_ATTR_STRING(ptsc, evattr_ptsc, "event=0x05"); +PMU_EVENT_ATTR_STRING(tsc, evattr_tsc, "event=0x00"); +PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01"); +PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02"); +PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03"); +PMU_EVENT_ATTR_STRING(smi, evattr_smi, "event=0x04"); +PMU_EVENT_ATTR_STRING(ptsc, evattr_ptsc, "event=0x05"); +PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06"); static struct perf_msr msr[] = { - [PERF_MSR_TSC] = { 0, &evattr_tsc, NULL, }, - [PERF_MSR_APERF] = { MSR_IA32_APERF, &evattr_aperf, test_aperfmperf, }, - [PERF_MSR_MPERF] = { MSR_IA32_MPERF, &evattr_mperf, test_aperfmperf, }, - [PERF_MSR_PPERF] = { MSR_PPERF, &evattr_pperf, test_intel, }, - [PERF_MSR_SMI] = { MSR_SMI_COUNT, &evattr_smi, test_intel, }, + [PERF_MSR_TSC] = { 0, &evattr_tsc, NULL, }, + [PERF_MSR_APERF] = { MSR_IA32_APERF, &evattr_aperf, test_aperfmperf, }, + [PERF_MSR_MPERF] = { MSR_IA32_MPERF, &evattr_mperf, test_aperfmperf, }, + [PERF_MSR_PPERF] = { MSR_PPERF, &evattr_pperf, test_intel, }, + [PERF_MSR_SMI] = { MSR_SMI_COUNT, &evattr_smi, test_intel, }, [PERF_MSR_PTSC] = { MSR_F15H_PTSC, &evattr_ptsc, test_ptsc, }, + [PERF_MSR_IRPERF] = { MSR_F17H_IRPERF, &evattr_irperf, test_irperf, }, }; static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = { diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index bdf9042f0295..dd448a91182e 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -251,6 +251,7 @@ /* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ #define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ +#define X86_FEATURE_IRPERF (13*32+1) /* Instructions Retired Count */ /* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */ #define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 6e6a5ccfb3f5..e0e2f7dfbd36 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -313,6 +313,9 @@ #define MSR_AMD64_IBSOPDATA4 0xc001103d #define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */ +/* Fam 17h MSRs */ +#define MSR_F17H_IRPERF 0xc00000e9 + /* Fam 16h MSRs */ #define MSR_F16H_L2I_PERF_CTL 0xc0010230 #define MSR_F16H_L2I_PERF_CTR 0xc0010231 -- GitLab From 07dc900e17a94681877b5797ce62ba97fa170400 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 29 Mar 2016 14:30:35 +0200 Subject: [PATCH 0929/9938] perf/x86: Move Kconfig.perf and other perf configuration bits to events/Kconfig Ingo says: "If we do a separate file we should have it in arch/x86/events/Kconfig (not in arch/x86/Kconfig.perf), and also move some of the other bits, such as PERF_EVENTS_AMD_POWER?" Suggested-by: Ingo Molnar Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 11 +---------- arch/x86/{Kconfig.perf => events/Kconfig} | 9 +++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) rename arch/x86/{Kconfig.perf => events/Kconfig} (68%) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 496218b8236b..c2d34578a0a4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1038,7 +1038,7 @@ config X86_THERMAL_VECTOR def_bool y depends on X86_MCE_INTEL -source "arch/x86/Kconfig.perf" +source "arch/x86/events/Kconfig" config X86_LEGACY_VM86 bool "Legacy VM86 support" @@ -1204,15 +1204,6 @@ config MICROCODE_OLD_INTERFACE def_bool y depends on MICROCODE -config PERF_EVENTS_AMD_POWER - depends on PERF_EVENTS && CPU_SUP_AMD - tristate "AMD Processor Power Reporting Mechanism" - ---help--- - Provide power reporting mechanism support for AMD processors. - Currently, it leverages X86_FEATURE_ACC_POWER - (CPUID Fn8000_0007_EDX[12]) interface to calculate the - average power consumption on Family 15h processors. - config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" ---help--- diff --git a/arch/x86/Kconfig.perf b/arch/x86/events/Kconfig similarity index 68% rename from arch/x86/Kconfig.perf rename to arch/x86/events/Kconfig index 7d29dd75d07b..98397db5ceae 100644 --- a/arch/x86/Kconfig.perf +++ b/arch/x86/events/Kconfig @@ -24,4 +24,13 @@ config PERF_EVENTS_INTEL_CSTATE Include support for Intel cstate performance events for power monitoring on modern processors. +config PERF_EVENTS_AMD_POWER + depends on PERF_EVENTS && CPU_SUP_AMD + tristate "AMD Processor Power Reporting Mechanism" + ---help--- + Provide power reporting mechanism support for AMD processors. + Currently, it leverages X86_FEATURE_ACC_POWER + (CPUID Fn8000_0007_EDX[12]) interface to calculate the + average power consumption on Family 15h processors. + endmenu -- GitLab From 26657848502b78474a5f17f9ce2ae6dc8d8d6262 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 22 Mar 2016 22:09:18 +0100 Subject: [PATCH 0930/9938] perf/core: Verify we have a single perf_hw_context PMU There should (and can) only be a single PMU for perf_hw_context events. This is because of how we schedule events: once a hardware event fails to schedule (the PMU is 'full') we stop trying to add more. The trivial 'fix' would break the Round-Robin scheduling we do. Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Signed-off-by: Ingo Molnar --- kernel/events/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 52bedc5a5aaa..525d11c59287 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7693,6 +7693,15 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type) } skip_type: + if (pmu->task_ctx_nr == perf_hw_context) { + static int hw_context_taken = 0; + + if (WARN_ON_ONCE(hw_context_taken)) + pmu->task_ctx_nr = perf_invalid_context; + + hw_context_taken = 1; + } + pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr); if (pmu->pmu_cpu_context) goto got_cpu_context; -- GitLab From dcb10a967ce82d5ad20570693091139ae716ff76 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 15:42:45 +0200 Subject: [PATCH 0931/9938] perf/ring_buffer: Refuse to begin AUX transaction after rb->aux_mmap_count drops When ring buffer's AUX area is unmapped and rb->aux_mmap_count drops to zero, new AUX transactions into this buffer can still be started, even though the buffer in en route to deallocation. This patch adds a check to perf_aux_output_begin() for rb->aux_mmap_count being zero, in which case there is no point starting new transactions, in other words, the ring buffers that pass a certain point in perf_mmap_close will not have their events sending new data, which clears path for freeing those buffers' pages right there and then, provided that no active transactions are holding the AUX reference. Signed-off-by: Alexander Shishkin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: vince@deater.net Link: http://lkml.kernel.org/r/1457098969-21595-2-git-send-email-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar --- kernel/events/ring_buffer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index c61f0cbd308b..89abf623e93c 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -287,6 +287,13 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, if (!rb_has_aux(rb) || !atomic_inc_not_zero(&rb->aux_refcount)) goto err; + /* + * If rb::aux_mmap_count is zero (and rb_has_aux() above went through), + * the aux buffer is in perf_mmap_close(), about to get freed. + */ + if (!atomic_read(&rb->aux_mmap_count)) + goto err; + /* * Nesting is not supported for AUX area, make sure nested * writers are caught early -- GitLab From 95ff4ca26c492fc1ed7751f5dd7ab7674b54f4e0 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 2 Dec 2015 18:41:11 +0200 Subject: [PATCH 0932/9938] perf/core: Free AUX pages in unmap path Now that we can ensure that when ring buffer's AUX area is on the way to getting unmapped new transactions won't start, we only need to stop all events that can potentially be writing aux data to our ring buffer. Having done that, we can safely free the AUX pages and corresponding PMU data, as this time it is guaranteed to be the last aux reference holder. This partially reverts: 57ffc5ca679 ("perf: Fix AUX buffer refcounting") ... which was made to defer deallocation that was otherwise possible from an NMI context. Now it is no longer the case; the last call to rb_free_aux() that drops the last AUX reference has to happen in perf_mmap_close() on that AUX area. Signed-off-by: Alexander Shishkin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: vince@deater.net Link: http://lkml.kernel.org/r/87d1qtz23d.fsf@ashishki-desk.ger.corp.intel.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 120 +++++++++++++++++++++++++++++++++++- kernel/events/internal.h | 1 - kernel/events/ring_buffer.c | 37 ++++------- 3 files changed, 129 insertions(+), 29 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 525d11c59287..243df4b62870 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1925,8 +1925,13 @@ event_sched_in(struct perf_event *event, if (event->state <= PERF_EVENT_STATE_OFF) return 0; - event->state = PERF_EVENT_STATE_ACTIVE; - event->oncpu = smp_processor_id(); + WRITE_ONCE(event->oncpu, smp_processor_id()); + /* + * Order event::oncpu write to happen before the ACTIVE state + * is visible. + */ + smp_wmb(); + WRITE_ONCE(event->state, PERF_EVENT_STATE_ACTIVE); /* * Unthrottle events, since we scheduled we might have missed several @@ -2358,6 +2363,29 @@ void perf_event_enable(struct perf_event *event) } EXPORT_SYMBOL_GPL(perf_event_enable); +static int __perf_event_stop(void *info) +{ + struct perf_event *event = info; + + /* for AUX events, our job is done if the event is already inactive */ + if (READ_ONCE(event->state) != PERF_EVENT_STATE_ACTIVE) + return 0; + + /* matches smp_wmb() in event_sched_in() */ + smp_rmb(); + + /* + * There is a window with interrupts enabled before we get here, + * so we need to check again lest we try to stop another CPU's event. + */ + if (READ_ONCE(event->oncpu) != smp_processor_id()) + return -EAGAIN; + + event->pmu->stop(event, PERF_EF_UPDATE); + + return 0; +} + static int _perf_event_refresh(struct perf_event *event, int refresh) { /* @@ -4667,6 +4695,8 @@ static void perf_mmap_open(struct vm_area_struct *vma) event->pmu->event_mapped(event); } +static void perf_pmu_output_stop(struct perf_event *event); + /* * A buffer can be mmap()ed multiple times; either directly through the same * event, or through other events by use of perf_event_set_output(). @@ -4694,10 +4724,22 @@ static void perf_mmap_close(struct vm_area_struct *vma) */ if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff && atomic_dec_and_mutex_lock(&rb->aux_mmap_count, &event->mmap_mutex)) { + /* + * Stop all AUX events that are writing to this buffer, + * so that we can free its AUX pages and corresponding PMU + * data. Note that after rb::aux_mmap_count dropped to zero, + * they won't start any more (see perf_aux_output_begin()). + */ + perf_pmu_output_stop(event); + + /* now it's safe to free the pages */ atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm); vma->vm_mm->pinned_vm -= rb->aux_mmap_locked; + /* this has to be the last one */ rb_free_aux(rb); + WARN_ON_ONCE(atomic_read(&rb->aux_refcount)); + mutex_unlock(&event->mmap_mutex); } @@ -5768,6 +5810,80 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, rcu_read_unlock(); } +struct remote_output { + struct ring_buffer *rb; + int err; +}; + +static void __perf_event_output_stop(struct perf_event *event, void *data) +{ + struct perf_event *parent = event->parent; + struct remote_output *ro = data; + struct ring_buffer *rb = ro->rb; + + if (!has_aux(event)) + return; + + if (!parent) + parent = event; + + /* + * In case of inheritance, it will be the parent that links to the + * ring-buffer, but it will be the child that's actually using it: + */ + if (rcu_dereference(parent->rb) == rb) + ro->err = __perf_event_stop(event); +} + +static int __perf_pmu_output_stop(void *info) +{ + struct perf_event *event = info; + struct pmu *pmu = event->pmu; + struct perf_cpu_context *cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); + struct remote_output ro = { + .rb = event->rb, + }; + + rcu_read_lock(); + perf_event_aux_ctx(&cpuctx->ctx, __perf_event_output_stop, &ro); + if (cpuctx->task_ctx) + perf_event_aux_ctx(cpuctx->task_ctx, __perf_event_output_stop, + &ro); + rcu_read_unlock(); + + return ro.err; +} + +static void perf_pmu_output_stop(struct perf_event *event) +{ + struct perf_event *iter; + int err, cpu; + +restart: + rcu_read_lock(); + list_for_each_entry_rcu(iter, &event->rb->event_list, rb_entry) { + /* + * For per-CPU events, we need to make sure that neither they + * nor their children are running; for cpu==-1 events it's + * sufficient to stop the event itself if it's active, since + * it can't have children. + */ + cpu = iter->cpu; + if (cpu == -1) + cpu = READ_ONCE(iter->oncpu); + + if (cpu == -1) + continue; + + err = cpu_function_call(cpu, __perf_pmu_output_stop, event); + if (err == -EAGAIN) { + rcu_read_unlock(); + goto restart; + } + } + rcu_read_unlock(); +} + /* * task tracking -- fork/exit * diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 2bbad9c1274c..2b229fdcfc09 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -11,7 +11,6 @@ struct ring_buffer { atomic_t refcount; struct rcu_head rcu_head; - struct irq_work irq_work; #ifdef CONFIG_PERF_USE_VMALLOC struct work_struct work; int page_order; /* allocation order */ diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 89abf623e93c..367e9c56ec0b 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -221,8 +221,6 @@ void perf_output_end(struct perf_output_handle *handle) rcu_read_unlock(); } -static void rb_irq_work(struct irq_work *work); - static void ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) { @@ -243,16 +241,6 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) INIT_LIST_HEAD(&rb->event_list); spin_lock_init(&rb->event_lock); - init_irq_work(&rb->irq_work, rb_irq_work); -} - -static void ring_buffer_put_async(struct ring_buffer *rb) -{ - if (!atomic_dec_and_test(&rb->refcount)) - return; - - rb->rcu_head.next = (void *)rb; - irq_work_queue(&rb->irq_work); } /* @@ -292,7 +280,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, * the aux buffer is in perf_mmap_close(), about to get freed. */ if (!atomic_read(&rb->aux_mmap_count)) - goto err; + goto err_put; /* * Nesting is not supported for AUX area, make sure nested @@ -338,7 +326,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, rb_free_aux(rb); err: - ring_buffer_put_async(rb); + ring_buffer_put(rb); handle->event = NULL; return NULL; @@ -389,7 +377,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, local_set(&rb->aux_nest, 0); rb_free_aux(rb); - ring_buffer_put_async(rb); + ring_buffer_put(rb); } /* @@ -470,6 +458,14 @@ static void __rb_free_aux(struct ring_buffer *rb) { int pg; + /* + * Should never happen, the last reference should be dropped from + * perf_mmap_close() path, which first stops aux transactions (which + * in turn are the atomic holders of aux_refcount) and then does the + * last rb_free_aux(). + */ + WARN_ON_ONCE(in_atomic()); + if (rb->aux_priv) { rb->free_aux(rb->aux_priv); rb->free_aux = NULL; @@ -581,18 +577,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event, void rb_free_aux(struct ring_buffer *rb) { if (atomic_dec_and_test(&rb->aux_refcount)) - irq_work_queue(&rb->irq_work); -} - -static void rb_irq_work(struct irq_work *work) -{ - struct ring_buffer *rb = container_of(work, struct ring_buffer, irq_work); - - if (!atomic_read(&rb->aux_refcount)) __rb_free_aux(rb); - - if (rb->rcu_head.next == (void *)rb) - call_rcu(&rb->rcu_head, rb_free_rcu); } #ifndef CONFIG_PERF_USE_VMALLOC -- GitLab From af5bb4ed1254a378b6028c09e58bdcc1cd9bf5b3 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 15:42:47 +0200 Subject: [PATCH 0933/9938] perf/ring_buffer: Document AUX API usage In order to ensure safe AUX buffer management, we rely on the assumption that pmu::stop() stops its ongoing AUX transaction and not just the hw. This patch documents this requirement for the perf_aux_output_{begin,end}() APIs. Signed-off-by: Alexander Shishkin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: vince@deater.net Link: http://lkml.kernel.org/r/1457098969-21595-4-git-send-email-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar --- kernel/events/ring_buffer.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 367e9c56ec0b..0ed4555309bd 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -252,6 +252,10 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) * The ordering is similar to that of perf_output_{begin,end}, with * the exception of (B), which should be taken care of by the pmu * driver, since ordering rules will differ depending on hardware. + * + * Call this from pmu::start(); see the comment in perf_aux_output_end() + * about its use in pmu callbacks. Both can also be called from the PMI + * handler if needed. */ void *perf_aux_output_begin(struct perf_output_handle *handle, struct perf_event *event) @@ -323,6 +327,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, return handle->rb->aux_priv; err_put: + /* can't be last */ rb_free_aux(rb); err: @@ -337,6 +342,10 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, * aux_head and posting a PERF_RECORD_AUX into the perf buffer. It is the * pmu driver's responsibility to observe ordering rules of the hardware, * so that all the data is externally visible before this is called. + * + * Note: this has to be called from pmu::stop() callback, as the assumption + * of the AUX buffer management code is that after pmu::stop(), the AUX + * transaction must be stopped and therefore drop the AUX reference count. */ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, bool truncated) @@ -376,6 +385,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, handle->event = NULL; local_set(&rb->aux_nest, 0); + /* can't be last */ rb_free_aux(rb); ring_buffer_put(rb); } -- GitLab From 66d219014a4ee47ad4ca2b9db5fe6547353e2a56 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 15:42:48 +0200 Subject: [PATCH 0934/9938] perf/x86/intel/pt: Move transaction start/stop to PMU start/stop callbacks As per AUX buffer management requirement, AUX output has to happen between pmu::start and pmu::stop calls so that perf_event_stop() actually stops it and therefore perf can free the AUX data after it has called pmu::stop. This patch moves perf_aux_output_{begin,end} from pt_event_{add,del} to pt_event_{start,stop}. As a bonus, we get rid of pt_buffer_is_full(), which is already taken care of by perf_aux_output_begin() anyway. Signed-off-by: Alexander Shishkin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: vince@deater.net Link: http://lkml.kernel.org/r/1457098969-21595-5-git-send-email-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/pt.c | 85 ++++++++++++-------------------------- 1 file changed, 27 insertions(+), 58 deletions(-) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index 6af7cf71d6b2..127f58c17976 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -905,26 +905,6 @@ static void pt_buffer_free_aux(void *data) kfree(buf); } -/** - * pt_buffer_is_full() - check if the buffer is full - * @buf: PT buffer. - * @pt: Per-cpu pt handle. - * - * If the user hasn't read data from the output region that aux_head - * points to, the buffer is considered full: the user needs to read at - * least this region and update aux_tail to point past it. - */ -static bool pt_buffer_is_full(struct pt_buffer *buf, struct pt *pt) -{ - if (buf->snapshot) - return false; - - if (local_read(&buf->data_size) >= pt->handle.size) - return true; - - return false; -} - /** * intel_pt_interrupt() - PT PMI handler */ @@ -989,20 +969,33 @@ void intel_pt_interrupt(void) static void pt_event_start(struct perf_event *event, int mode) { + struct hw_perf_event *hwc = &event->hw; struct pt *pt = this_cpu_ptr(&pt_ctx); - struct pt_buffer *buf = perf_get_aux(&pt->handle); + struct pt_buffer *buf; - if (!buf || pt_buffer_is_full(buf, pt)) { - event->hw.state = PERF_HES_STOPPED; - return; + buf = perf_aux_output_begin(&pt->handle, event); + if (!buf) + goto fail_stop; + + pt_buffer_reset_offsets(buf, pt->handle.head); + if (!buf->snapshot) { + if (pt_buffer_reset_markers(buf, &pt->handle)) + goto fail_end_stop; } ACCESS_ONCE(pt->handle_nmi) = 1; - event->hw.state = 0; + hwc->state = 0; pt_config_buffer(buf->cur->table, buf->cur_idx, buf->output_off); pt_config(event); + + return; + +fail_end_stop: + perf_aux_output_end(&pt->handle, 0, true); +fail_stop: + hwc->state = PERF_HES_STOPPED; } static void pt_event_stop(struct perf_event *event, int mode) @@ -1035,19 +1028,7 @@ static void pt_event_stop(struct perf_event *event, int mode) pt_handle_status(pt); pt_update_head(pt); - } -} -static void pt_event_del(struct perf_event *event, int mode) -{ - struct pt *pt = this_cpu_ptr(&pt_ctx); - struct pt_buffer *buf; - - pt_event_stop(event, PERF_EF_UPDATE); - - buf = perf_get_aux(&pt->handle); - - if (buf) { if (buf->snapshot) pt->handle.head = local_xchg(&buf->data_size, @@ -1057,9 +1038,13 @@ static void pt_event_del(struct perf_event *event, int mode) } } +static void pt_event_del(struct perf_event *event, int mode) +{ + pt_event_stop(event, PERF_EF_UPDATE); +} + static int pt_event_add(struct perf_event *event, int mode) { - struct pt_buffer *buf; struct pt *pt = this_cpu_ptr(&pt_ctx); struct hw_perf_event *hwc = &event->hw; int ret = -EBUSY; @@ -1067,34 +1052,18 @@ static int pt_event_add(struct perf_event *event, int mode) if (pt->handle.event) goto fail; - buf = perf_aux_output_begin(&pt->handle, event); - ret = -EINVAL; - if (!buf) - goto fail_stop; - - pt_buffer_reset_offsets(buf, pt->handle.head); - if (!buf->snapshot) { - ret = pt_buffer_reset_markers(buf, &pt->handle); - if (ret) - goto fail_end_stop; - } - if (mode & PERF_EF_START) { pt_event_start(event, 0); - ret = -EBUSY; + ret = -EINVAL; if (hwc->state == PERF_HES_STOPPED) - goto fail_end_stop; + goto fail; } else { hwc->state = PERF_HES_STOPPED; } - return 0; - -fail_end_stop: - perf_aux_output_end(&pt->handle, 0, true); -fail_stop: - hwc->state = PERF_HES_STOPPED; + ret = 0; fail: + return ret; } -- GitLab From 981a4cb380d3dff7010ce9f89618064a254eab8c Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 15:42:49 +0200 Subject: [PATCH 0935/9938] perf/x86/intel/bts: Move transaction start/stop to start/stop callbacks As per AUX buffer management requirement, AUX output has to happen between pmu::start and pmu::stop calls so that perf_event_stop() actually stops it and therefore perf can free the AUX data after it has called pmu::stop. This patch moves perf_aux_output_{begin,end} from bts_event_{add,del} to bts_event_{start,stop}. As a bonus, we get rid of bts_buffer_is_full(), which is already taken care of by perf_aux_output_begin() anyway. Signed-off-by: Alexander Shishkin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: vince@deater.net Link: http://lkml.kernel.org/r/1457098969-21595-6-git-send-email-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/bts.c | 105 +++++++++++++++++------------------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c index b99dc9258c0f..0a6e393a2e62 100644 --- a/arch/x86/events/intel/bts.c +++ b/arch/x86/events/intel/bts.c @@ -171,18 +171,6 @@ static void bts_buffer_pad_out(struct bts_phys *phys, unsigned long head) memset(page_address(phys->page) + index, 0, phys->size - index); } -static bool bts_buffer_is_full(struct bts_buffer *buf, struct bts_ctx *bts) -{ - if (buf->snapshot) - return false; - - if (local_read(&buf->data_size) >= bts->handle.size || - bts->handle.size - local_read(&buf->data_size) < BTS_RECORD_SIZE) - return true; - - return false; -} - static void bts_update(struct bts_ctx *bts) { int cpu = raw_smp_processor_id(); @@ -213,18 +201,15 @@ static void bts_update(struct bts_ctx *bts) } } +static int +bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle); + static void __bts_event_start(struct perf_event *event) { struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); struct bts_buffer *buf = perf_get_aux(&bts->handle); u64 config = 0; - if (!buf || bts_buffer_is_full(buf, bts)) - return; - - event->hw.itrace_started = 1; - event->hw.state = 0; - if (!buf->snapshot) config |= ARCH_PERFMON_EVENTSEL_INT; if (!event->attr.exclude_kernel) @@ -241,16 +226,41 @@ static void __bts_event_start(struct perf_event *event) wmb(); intel_pmu_enable_bts(config); + } static void bts_event_start(struct perf_event *event, int flags) { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); + struct bts_buffer *buf; + + buf = perf_aux_output_begin(&bts->handle, event); + if (!buf) + goto fail_stop; + + if (bts_buffer_reset(buf, &bts->handle)) + goto fail_end_stop; + + bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base; + bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum; + bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold; + + event->hw.itrace_started = 1; + event->hw.state = 0; __bts_event_start(event); /* PMI handler: this counter is running and likely generating PMIs */ ACCESS_ONCE(bts->started) = 1; + + return; + +fail_end_stop: + perf_aux_output_end(&bts->handle, 0, false); + +fail_stop: + event->hw.state = PERF_HES_STOPPED; } static void __bts_event_stop(struct perf_event *event) @@ -269,15 +279,32 @@ static void __bts_event_stop(struct perf_event *event) static void bts_event_stop(struct perf_event *event, int flags) { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); + struct bts_buffer *buf = perf_get_aux(&bts->handle); /* PMI handler: don't restart this counter */ ACCESS_ONCE(bts->started) = 0; __bts_event_stop(event); - if (flags & PERF_EF_UPDATE) + if (flags & PERF_EF_UPDATE) { bts_update(bts); + + if (buf) { + if (buf->snapshot) + bts->handle.head = + local_xchg(&buf->data_size, + buf->nr_pages << PAGE_SHIFT); + perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), + !!local_xchg(&buf->lost, 0)); + } + + cpuc->ds->bts_index = bts->ds_back.bts_buffer_base; + cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base; + cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum; + cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold; + } } void intel_bts_enable_local(void) @@ -417,34 +444,14 @@ int intel_bts_interrupt(void) static void bts_event_del(struct perf_event *event, int mode) { - struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); - struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); - struct bts_buffer *buf = perf_get_aux(&bts->handle); - bts_event_stop(event, PERF_EF_UPDATE); - - if (buf) { - if (buf->snapshot) - bts->handle.head = - local_xchg(&buf->data_size, - buf->nr_pages << PAGE_SHIFT); - perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), - !!local_xchg(&buf->lost, 0)); - } - - cpuc->ds->bts_index = bts->ds_back.bts_buffer_base; - cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base; - cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum; - cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold; } static int bts_event_add(struct perf_event *event, int mode) { - struct bts_buffer *buf; struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); struct hw_perf_event *hwc = &event->hw; - int ret = -EBUSY; event->hw.state = PERF_HES_STOPPED; @@ -454,26 +461,10 @@ static int bts_event_add(struct perf_event *event, int mode) if (bts->handle.event) return -EBUSY; - buf = perf_aux_output_begin(&bts->handle, event); - if (!buf) - return -EINVAL; - - ret = bts_buffer_reset(buf, &bts->handle); - if (ret) { - perf_aux_output_end(&bts->handle, 0, false); - return ret; - } - - bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base; - bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum; - bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold; - if (mode & PERF_EF_START) { bts_event_start(event, 0); - if (hwc->state & PERF_HES_STOPPED) { - bts_event_del(event, 0); - return -EBUSY; - } + if (hwc->state & PERF_HES_STOPPED) + return -EINVAL; } return 0; -- GitLab From 0a74c5b3d20d2a8693848b6ae4f1a97624f5b781 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 16 Mar 2016 15:34:29 +0100 Subject: [PATCH 0936/9938] ftrace/perf: Check sample types only for sampling events Currently we check sample type for ftrace:function events even if it's not created as a sampling event. That prevents creating ftrace_function event in counting mode. Make sure we check sample types only for sampling events. Before: $ sudo perf stat -e ftrace:function ls ... Performance counter stats for 'ls': ftrace:function 0.001983662 seconds time elapsed After: $ sudo perf stat -e ftrace:function ls ... Performance counter stats for 'ls': 44,498 ftrace:function 0.037534722 seconds time elapsed Suggested-by: Namhyung Kim Signed-off-by: Jiri Olsa Signed-off-by: Peter Zijlstra (Intel) Acked-by: Steven Rostedt Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1458138873-1553-2-git-send-email-jolsa@kernel.org Signed-off-by: Ingo Molnar --- kernel/trace/trace_event_perf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 00df25fd86ef..e11108f1d197 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -47,6 +47,9 @@ static int perf_trace_event_perm(struct trace_event_call *tp_event, if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN)) return -EPERM; + if (!is_sampling_event(p_event)) + return 0; + /* * We don't allow user space callchains for function trace * event, due to issues with page faults while tracing page -- GitLab From 86e7972f690c1017fd086cdfe53d8524e68c661c Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 28 Mar 2016 06:41:29 +0000 Subject: [PATCH 0937/9938] perf/ring_buffer: Introduce new ioctl options to pause and resume the ring-buffer Add new ioctl() to pause/resume ring-buffer output. In some situations we want to read from the ring-buffer only when we ensure nothing can write to the ring-buffer during reading. Without this patch we have to turn off all events attached to this ring-buffer to achieve this. This patch is a prerequisite to enable overwrite support for the perf ring-buffer support. Following commits will introduce new methods support reading from overwrite ring buffer. Before reading, caller must ensure the ring buffer is frozen, or the reading is unreliable. Signed-off-by: Wang Nan Signed-off-by: Peter Zijlstra (Intel) Cc: Cc: Alexander Shishkin Cc: Alexei Starovoitov Cc: Arnaldo Carvalho de Melo Cc: Brendan Gregg Cc: He Kuang Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: Zefan Li Link: http://lkml.kernel.org/r/1459147292-239310-2-git-send-email-wangnan0@huawei.com Signed-off-by: Ingo Molnar --- include/uapi/linux/perf_event.h | 1 + kernel/events/core.c | 13 +++++++++++++ kernel/events/internal.h | 9 +++++++++ kernel/events/ring_buffer.c | 12 +++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 1afe9623c1a7..a3c19034d5f8 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -401,6 +401,7 @@ struct perf_event_attr { #define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) #define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) #define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) +#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) enum perf_event_ioc_flags { PERF_IOC_FLAG_GROUP = 1U << 0, diff --git a/kernel/events/core.c b/kernel/events/core.c index 243df4b62870..51386e84293e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4379,6 +4379,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon case PERF_EVENT_IOC_SET_BPF: return perf_event_set_bpf_prog(event, arg); + case PERF_EVENT_IOC_PAUSE_OUTPUT: { + struct ring_buffer *rb; + + rcu_read_lock(); + rb = rcu_dereference(event->rb); + if (!rb || !rb->nr_pages) { + rcu_read_unlock(); + return -EINVAL; + } + rb_toggle_paused(rb, !!arg); + rcu_read_unlock(); + return 0; + } default: return -ENOTTY; } diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 2b229fdcfc09..2d67327d9ad9 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -17,6 +17,7 @@ struct ring_buffer { #endif int nr_pages; /* nr of data pages */ int overwrite; /* can overwrite itself */ + int paused; /* can write into ring buffer */ atomic_t poll; /* POLL_ for wakeups */ @@ -64,6 +65,14 @@ static inline void rb_free_rcu(struct rcu_head *rcu_head) rb_free(rb); } +static inline void rb_toggle_paused(struct ring_buffer *rb, bool pause) +{ + if (!pause && rb->nr_pages) + rb->paused = 0; + else + rb->paused = 1; +} + extern struct ring_buffer * rb_alloc(int nr_pages, long watermark, int cpu, int flags); extern void perf_event_wakeup(struct perf_event *event); diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 0ed4555309bd..72d8127bb8fd 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -125,8 +125,11 @@ int perf_output_begin(struct perf_output_handle *handle, if (unlikely(!rb)) goto out; - if (unlikely(!rb->nr_pages)) + if (unlikely(rb->paused)) { + if (rb->nr_pages) + local_inc(&rb->lost); goto out; + } handle->rb = rb; handle->event = event; @@ -241,6 +244,13 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) INIT_LIST_HEAD(&rb->event_list); spin_lock_init(&rb->event_lock); + + /* + * perf_output_begin() only checks rb->paused, therefore + * rb->paused must be true if we have no pages for output. + */ + if (!rb->nr_pages) + rb->paused = 1; } /* -- GitLab From 1879445dfa7bbd6fe21b09c5cc72f4934798afed Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 28 Mar 2016 06:41:30 +0000 Subject: [PATCH 0938/9938] perf/core: Set event's default ::overflow_handler() Set a default event->overflow_handler in perf_event_alloc() so don't need to check event->overflow_handler in __perf_event_overflow(). Following commits can give a different default overflow_handler. Initial idea comes from Peter: http://lkml.kernel.org/r/20130708121557.GA17211@twins.programming.kicks-ass.net Since the default value of event->overflow_handler is not NULL, existing 'if (!overflow_handler)' checks need to be changed. is_default_overflow_handler() is introduced for this. No extra performance overhead is introduced into the hot path because in the original code we still need to read this handler from memory. A conditional branch is avoided so actually we remove some instructions. Signed-off-by: Wang Nan Signed-off-by: Peter Zijlstra (Intel) Cc: Cc: Alexander Shishkin Cc: Alexei Starovoitov Cc: Arnaldo Carvalho de Melo Cc: Brendan Gregg Cc: He Kuang Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: Zefan Li Link: http://lkml.kernel.org/r/1459147292-239310-3-git-send-email-wangnan0@huawei.com Signed-off-by: Ingo Molnar --- arch/arm/kernel/hw_breakpoint.c | 4 ++-- arch/arm64/kernel/hw_breakpoint.c | 4 ++-- include/linux/perf_event.h | 6 ++++++ kernel/events/core.c | 14 ++++++++------ 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 6284779d64ee..b8df45883cf7 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -631,7 +631,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) info->address &= ~alignment_mask; info->ctrl.len <<= offset; - if (!bp->overflow_handler) { + if (is_default_overflow_handler(bp)) { /* * Mismatch breakpoints are required for single-stepping * breakpoints. @@ -754,7 +754,7 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, * mismatch breakpoint so we can single-step over the * watchpoint trigger. */ - if (!wp->overflow_handler) + if (is_default_overflow_handler(wp)) enable_single_step(wp, instruction_pointer(regs)); unlock: diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index b45c95d34b83..4ef5373f9a76 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -616,7 +616,7 @@ static int breakpoint_handler(unsigned long unused, unsigned int esr, perf_bp_event(bp, regs); /* Do we need to handle the stepping? */ - if (!bp->overflow_handler) + if (is_default_overflow_handler(bp)) step = 1; unlock: rcu_read_unlock(); @@ -712,7 +712,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr, perf_bp_event(wp, regs); /* Do we need to handle the stepping? */ - if (!wp->overflow_handler) + if (is_default_overflow_handler(wp)) step = 1; unlock: diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 15588d4c581d..4065ca2d7149 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -838,6 +838,12 @@ extern void perf_event_output(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs); +static inline bool +is_default_overflow_handler(struct perf_event *event) +{ + return (event->overflow_handler == perf_event_output); +} + extern void perf_event_header__init_id(struct perf_event_header *header, struct perf_sample_data *data, diff --git a/kernel/events/core.c b/kernel/events/core.c index 51386e84293e..8c3b35f2a269 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6628,10 +6628,7 @@ static int __perf_event_overflow(struct perf_event *event, irq_work_queue(&event->pending); } - if (event->overflow_handler) - event->overflow_handler(event, data, regs); - else - perf_event_output(event, data, regs); + event->overflow_handler(event, data, regs); if (*perf_event_fasync(event) && event->pending_kill) { event->pending_wakeup = 1; @@ -8152,8 +8149,13 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, context = parent_event->overflow_handler_context; } - event->overflow_handler = overflow_handler; - event->overflow_handler_context = context; + if (overflow_handler) { + event->overflow_handler = overflow_handler; + event->overflow_handler_context = context; + } else { + event->overflow_handler = perf_event_output; + event->overflow_handler_context = NULL; + } perf_event__state_init(event); -- GitLab From d1b26c70246bc72922ae61d9f972d5c2588409e7 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 28 Mar 2016 06:41:31 +0000 Subject: [PATCH 0939/9938] perf/ring_buffer: Prepare writing into the ring-buffer from the end Convert perf_output_begin() to __perf_output_begin() and make the later function able to write records from the end of the ring-buffer. Following commits will utilize the 'backward' flag. This is the core patch to support writing to the ring-buffer backwards, which will be introduced by upcoming patches to support reading from overwritable ring-buffers. In theory, this patch should not introduce any extra performance overhead since we use always_inline, but it does not hurt to double check that assumption: When CONFIG_OPTIMIZE_INLINING is disabled, the output object is nearly identical to original one. See: http://lkml.kernel.org/g/56F52E83.70409@huawei.com When CONFIG_OPTIMIZE_INLINING is enabled, the resuling object file becomes smaller: $ size kernel/events/ring_buffer.o* text data bss dec hex filename 4641 4 8 4653 122d kernel/events/ring_buffer.o.old 4545 4 8 4557 11cd kernel/events/ring_buffer.o.new Performance testing results: Calling 3000000 times of 'close(-1)', use gettimeofday() to check duration. Use 'perf record -o /dev/null -e raw_syscalls:*' to capture system calls. In ns. Testing environment: CPU : Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz Kernel : v4.5.0 MEAN STDVAR BASE 800214.950 2853.083 PRE 2253846.700 9997.014 POST 2257495.540 8516.293 Where 'BASE' is pure performance without capturing. 'PRE' is test result of pure 'v4.5.0' kernel. 'POST' is test result after this patch. Considering the stdvar, this patch doesn't hurt performance, within noise margin. For testing details, see: http://lkml.kernel.org/g/56F89DCD.1040202@huawei.com Signed-off-by: Wang Nan Signed-off-by: Peter Zijlstra (Intel) Cc: Cc: Alexander Shishkin Cc: Alexei Starovoitov Cc: Arnaldo Carvalho de Melo Cc: Brendan Gregg Cc: He Kuang Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: Zefan Li Link: http://lkml.kernel.org/r/1459147292-239310-4-git-send-email-wangnan0@huawei.com Signed-off-by: Ingo Molnar --- kernel/events/ring_buffer.c | 42 +++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 72d8127bb8fd..60be55a64040 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -102,8 +102,21 @@ static void perf_output_put_handle(struct perf_output_handle *handle) preempt_enable(); } -int perf_output_begin(struct perf_output_handle *handle, - struct perf_event *event, unsigned int size) +static bool __always_inline +ring_buffer_has_space(unsigned long head, unsigned long tail, + unsigned long data_size, unsigned int size, + bool backward) +{ + if (!backward) + return CIRC_SPACE(head, tail, data_size) >= size; + else + return CIRC_SPACE(tail, head, data_size) >= size; +} + +static int __always_inline +__perf_output_begin(struct perf_output_handle *handle, + struct perf_event *event, unsigned int size, + bool backward) { struct ring_buffer *rb; unsigned long tail, offset, head; @@ -146,9 +159,12 @@ int perf_output_begin(struct perf_output_handle *handle, do { tail = READ_ONCE(rb->user_page->data_tail); offset = head = local_read(&rb->head); - if (!rb->overwrite && - unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size)) - goto fail; + if (!rb->overwrite) { + if (unlikely(!ring_buffer_has_space(head, tail, + perf_data_size(rb), + size, backward))) + goto fail; + } /* * The above forms a control dependency barrier separating the @@ -162,9 +178,17 @@ int perf_output_begin(struct perf_output_handle *handle, * See perf_output_put_handle(). */ - head += size; + if (!backward) + head += size; + else + head -= size; } while (local_cmpxchg(&rb->head, offset, head) != offset); + if (backward) { + offset = head; + head = (u64)(-head); + } + /* * We rely on the implied barrier() by local_cmpxchg() to ensure * none of the data stores below can be lifted up by the compiler. @@ -206,6 +230,12 @@ int perf_output_begin(struct perf_output_handle *handle, return -ENOSPC; } +int perf_output_begin(struct perf_output_handle *handle, + struct perf_event *event, unsigned int size) +{ + return __perf_output_begin(handle, event, size, false); +} + unsigned int perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len) { -- GitLab From 16fe1ad289019d78a8f8fdb65f08d298ee921cb3 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 23 Mar 2016 18:01:27 +0100 Subject: [PATCH 0940/9938] gpio: mcp23s08: Add support for level triggered interrupts The interrupt for the corresponding pin is configured to trigger when the pin state changes compared to a preconfigured state (Bit set in INTCON). This state is set by setting/clearing the bit in DEFVAL. In the interrupt handler we need also to check if the bit in INTCON is set for level triggered interrupts. Signed-off-by: Alexander Stein Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mcp23s08.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index c882c2be5a0e..ac22efc1840e 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -362,7 +362,8 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) for (i = 0; i < mcp->chip.ngpio; i++) { if ((BIT(i) & mcp->cache[MCP_INTF]) && ((BIT(i) & intcap & mcp->irq_rise) || - (mcp->irq_fall & ~intcap & BIT(i)))) { + (mcp->irq_fall & ~intcap & BIT(i)) || + (BIT(i) & mcp->cache[MCP_INTCON]))) { child_irq = irq_find_mapping(mcp->chip.irqdomain, i); handle_nested_irq(child_irq); } @@ -408,6 +409,12 @@ static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) mcp->cache[MCP_INTCON] &= ~BIT(pos); mcp->irq_rise &= ~BIT(pos); mcp->irq_fall |= BIT(pos); + } else if (type & IRQ_TYPE_LEVEL_HIGH) { + mcp->cache[MCP_INTCON] |= BIT(pos); + mcp->cache[MCP_DEFVAL] &= ~BIT(pos); + } else if (type & IRQ_TYPE_LEVEL_LOW) { + mcp->cache[MCP_INTCON] |= BIT(pos); + mcp->cache[MCP_DEFVAL] |= BIT(pos); } else return -EINVAL; -- GitLab From dd98756d78153dbb43685f0f0e618dda235aee00 Mon Sep 17 00:00:00 2001 From: Kamlakant Patel Date: Thu, 24 Mar 2016 15:01:40 +0530 Subject: [PATCH 0941/9938] gpio: xlp: Add GPIO driver support for Broadcom Vulcan ARM64 - Add GPIO support for Broadcom Vulcan ARM64. - Add depends on ARCH_VULCAN to Kconfig to enable gpio controller driver for Broadcom Vulcan ARM64 SoCs. Signed-off-by: Kamlakant Patel Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-xlp.txt | 3 +++ drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-xlp.c | 25 +++++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-xlp.txt b/Documentation/devicetree/bindings/gpio/gpio-xlp.txt index 262ee4ddf2cb..28662d83a43e 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-xlp.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-xlp.txt @@ -3,6 +3,8 @@ Netlogic XLP Family GPIO This GPIO driver is used for following Netlogic XLP SoCs: XLP832, XLP316, XLP208, XLP980, XLP532 +This GPIO driver is also compatible with GPIO controller found on +Broadcom Vulcan ARM64. Required properties: ------------------- @@ -13,6 +15,7 @@ Required properties: - "netlogic,xlp208-gpio": For Netlogic XLP208 - "netlogic,xlp980-gpio": For Netlogic XLP980 - "netlogic,xlp532-gpio": For Netlogic XLP532 + - "brcm,vulcan-gpio": For Broadcom Vulcan ARM64 - reg: Physical base address and length of the controller's registers. - #gpio-cells: Should be two. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6d6015f7aeed..78898367b34e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -474,7 +474,7 @@ config GPIO_XILINX config GPIO_XLP tristate "Netlogic XLP GPIO support" - depends on CPU_XLP && OF_GPIO + depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || COMPILE_TEST) select GPIOLIB_IRQCHIP help This driver provides support for GPIO interface on Netlogic XLP MIPS64 diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index aa5813d2deb1..08897dc11915 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -85,7 +85,8 @@ enum { XLP_GPIO_VARIANT_XLP316, XLP_GPIO_VARIANT_XLP208, XLP_GPIO_VARIANT_XLP980, - XLP_GPIO_VARIANT_XLP532 + XLP_GPIO_VARIANT_XLP532, + GPIO_VARIANT_VULCAN }; struct xlp_gpio_priv { @@ -285,6 +286,10 @@ static const struct of_device_id xlp_gpio_of_ids[] = { .compatible = "netlogic,xlp532-gpio", .data = (void *)XLP_GPIO_VARIANT_XLP532, }, + { + .compatible = "brcm,vulcan-gpio", + .data = (void *)GPIO_VARIANT_VULCAN, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids); @@ -347,6 +352,7 @@ static int xlp_gpio_probe(struct platform_device *pdev) break; case XLP_GPIO_VARIANT_XLP980: case XLP_GPIO_VARIANT_XLP532: + case GPIO_VARIANT_VULCAN: priv->gpio_out_en = gpio_base + GPIO_9XX_OUTPUT_EN; priv->gpio_paddrv = gpio_base + GPIO_9XX_PADDRV; priv->gpio_intr_stat = gpio_base + GPIO_9XX_INT_STAT; @@ -354,7 +360,12 @@ static int xlp_gpio_probe(struct platform_device *pdev) priv->gpio_intr_pol = gpio_base + GPIO_9XX_INT_POL; priv->gpio_intr_en = gpio_base + GPIO_9XX_INT_EN00; - ngpio = (soc_type == XLP_GPIO_VARIANT_XLP980) ? 66 : 67; + if (soc_type == XLP_GPIO_VARIANT_XLP980) + ngpio = 66; + else if (soc_type == XLP_GPIO_VARIANT_XLP532) + ngpio = 67; + else + ngpio = 70; break; default: dev_err(&pdev->dev, "Unknown Processor type!\n"); @@ -377,10 +388,14 @@ static int xlp_gpio_probe(struct platform_device *pdev) gc->get = xlp_gpio_get; spin_lock_init(&priv->lock); - irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); - if (irq_base < 0) { + /* XLP has fixed IRQ range for GPIO interrupts */ + if (soc_type == GPIO_VARIANT_VULCAN) + irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0); + else + irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); + if (IS_ERR_VALUE(irq_base)) { dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); - return -ENODEV; + return irq_base; } err = gpiochip_add_data(gc, priv); -- GitLab From 5ca3726af7f66a8cc71ce4414cfeb86deb784491 Mon Sep 17 00:00:00 2001 From: Zhao Lei Date: Tue, 22 Mar 2016 16:37:07 +0800 Subject: [PATCH 0942/9938] sched/cpuacct: Show all possible CPUs in cpuacct output Current code show stats of online CPUs in cpuacct.statcpus, show stats of present cpus in cpuacct.usage(_percpu), and using present CPUs for setting cpuacct.usage. It will cause inconsistent result when a CPU is online or offline or hotpluged. We should always use possible CPUs to avoid above problem. Here are the contents of a cpuacct.usage_percpu sysfs file, on a 4 CPU system with maxcpus=32: Before the patch: # cat cpuacct.usage_percpu 2456565 411435 1052897 832584 After the patch: # cat cpuacct.usage_percpu 2456565 411435 1052897 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Suggested-by: Peter Zijlstra Signed-off-by: Zhao Lei Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Tejun Heo Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/a11d56cef12d0b4807f8be3a46bf9798c3014d59.1458635566.git.zhaolei@cn.fujitsu.com Signed-off-by: Ingo Molnar --- kernel/sched/cpuacct.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c index 4a811203c04a..e39bd4faf2a8 100644 --- a/kernel/sched/cpuacct.c +++ b/kernel/sched/cpuacct.c @@ -138,7 +138,7 @@ static u64 cpuusage_read(struct cgroup_subsys_state *css, struct cftype *cft) u64 totalcpuusage = 0; int i; - for_each_present_cpu(i) + for_each_possible_cpu(i) totalcpuusage += cpuacct_cpuusage_read(ca, i); return totalcpuusage; @@ -159,7 +159,7 @@ static int cpuusage_write(struct cgroup_subsys_state *css, struct cftype *cft, goto out; } - for_each_present_cpu(i) + for_each_possible_cpu(i) cpuacct_cpuusage_write(ca, i, 0); out: @@ -172,7 +172,7 @@ static int cpuacct_percpu_seq_show(struct seq_file *m, void *V) u64 percpu; int i; - for_each_present_cpu(i) { + for_each_possible_cpu(i) { percpu = cpuacct_cpuusage_read(ca, i); seq_printf(m, "%llu ", (unsigned long long) percpu); } @@ -191,7 +191,7 @@ static int cpuacct_stats_show(struct seq_file *sf, void *v) int cpu; s64 val = 0; - for_each_online_cpu(cpu) { + for_each_possible_cpu(cpu) { struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu); val += kcpustat->cpustat[CPUTIME_USER]; val += kcpustat->cpustat[CPUTIME_NICE]; @@ -200,7 +200,7 @@ static int cpuacct_stats_show(struct seq_file *sf, void *v) seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val); val = 0; - for_each_online_cpu(cpu) { + for_each_possible_cpu(cpu) { struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu); val += kcpustat->cpustat[CPUTIME_SYSTEM]; val += kcpustat->cpustat[CPUTIME_IRQ]; -- GitLab From d740037fac7052e49450f6fa1454f1144a103b55 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Tue, 22 Mar 2016 16:37:08 +0800 Subject: [PATCH 0943/9938] sched/cpuacct: Split usage accounting into user_usage and sys_usage Sometimes, cpuacct.usage is not detailed enough to see how much CPU usage a group had. We want to know how much time it used in user mode and how much in kernel mode. This patch introduces more files to give this information: # ls /sys/fs/cgroup/cpuacct/cpuacct.usage* /sys/fs/cgroup/cpuacct/cpuacct.usage /sys/fs/cgroup/cpuacct/cpuacct.usage_percpu /sys/fs/cgroup/cpuacct/cpuacct.usage_user /sys/fs/cgroup/cpuacct/cpuacct.usage_percpu_user /sys/fs/cgroup/cpuacct/cpuacct.usage_sys /sys/fs/cgroup/cpuacct/cpuacct.usage_percpu_sys ... while keeping the ABI with the existing counter. Signed-off-by: Dongsheng Yang [ Ported to newer kernels. ] Signed-off-by: Zhao Lei Signed-off-by: Peter Zijlstra (Intel) Acked-by: Tejun Heo Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Tejun Heo Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/aa171da036b520b51c79549e9b3215d29473f19d.1458635566.git.zhaolei@cn.fujitsu.com Signed-off-by: Ingo Molnar --- kernel/sched/cpuacct.c | 140 +++++++++++++++++++++++++++++++++-------- 1 file changed, 113 insertions(+), 27 deletions(-) diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c index e39bd4faf2a8..df947e07aac1 100644 --- a/kernel/sched/cpuacct.c +++ b/kernel/sched/cpuacct.c @@ -25,11 +25,22 @@ enum cpuacct_stat_index { CPUACCT_STAT_NSTATS, }; +enum cpuacct_usage_index { + CPUACCT_USAGE_USER, /* ... user mode */ + CPUACCT_USAGE_SYSTEM, /* ... kernel mode */ + + CPUACCT_USAGE_NRUSAGE, +}; + +struct cpuacct_usage { + u64 usages[CPUACCT_USAGE_NRUSAGE]; +}; + /* track cpu usage of a group of tasks and its child groups */ struct cpuacct { struct cgroup_subsys_state css; /* cpuusage holds pointer to a u64-type object on every cpu */ - u64 __percpu *cpuusage; + struct cpuacct_usage __percpu *cpuusage; struct kernel_cpustat __percpu *cpustat; }; @@ -49,7 +60,7 @@ static inline struct cpuacct *parent_ca(struct cpuacct *ca) return css_ca(ca->css.parent); } -static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage); +static DEFINE_PER_CPU(struct cpuacct_usage, root_cpuacct_cpuusage); static struct cpuacct root_cpuacct = { .cpustat = &kernel_cpustat, .cpuusage = &root_cpuacct_cpuusage, @@ -68,7 +79,7 @@ cpuacct_css_alloc(struct cgroup_subsys_state *parent_css) if (!ca) goto out; - ca->cpuusage = alloc_percpu(u64); + ca->cpuusage = alloc_percpu(struct cpuacct_usage); if (!ca->cpuusage) goto out_free_ca; @@ -96,20 +107,37 @@ static void cpuacct_css_free(struct cgroup_subsys_state *css) kfree(ca); } -static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu) +static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu, + enum cpuacct_usage_index index) { - u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); + struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); u64 data; + /* + * We allow index == CPUACCT_USAGE_NRUSAGE here to read + * the sum of suages. + */ + BUG_ON(index > CPUACCT_USAGE_NRUSAGE); + #ifndef CONFIG_64BIT /* * Take rq->lock to make 64-bit read safe on 32-bit platforms. */ raw_spin_lock_irq(&cpu_rq(cpu)->lock); - data = *cpuusage; +#endif + + if (index == CPUACCT_USAGE_NRUSAGE) { + int i = 0; + + data = 0; + for (i = 0; i < CPUACCT_USAGE_NRUSAGE; i++) + data += cpuusage->usages[i]; + } else { + data = cpuusage->usages[index]; + } + +#ifndef CONFIG_64BIT raw_spin_unlock_irq(&cpu_rq(cpu)->lock); -#else - data = *cpuusage; #endif return data; @@ -117,69 +145,103 @@ static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu) static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) { - u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); + struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); + int i; #ifndef CONFIG_64BIT /* * Take rq->lock to make 64-bit write safe on 32-bit platforms. */ raw_spin_lock_irq(&cpu_rq(cpu)->lock); - *cpuusage = val; +#endif + + for (i = 0; i < CPUACCT_USAGE_NRUSAGE; i++) + cpuusage->usages[i] = val; + +#ifndef CONFIG_64BIT raw_spin_unlock_irq(&cpu_rq(cpu)->lock); -#else - *cpuusage = val; #endif } /* return total cpu usage (in nanoseconds) of a group */ -static u64 cpuusage_read(struct cgroup_subsys_state *css, struct cftype *cft) +static u64 __cpuusage_read(struct cgroup_subsys_state *css, + enum cpuacct_usage_index index) { struct cpuacct *ca = css_ca(css); u64 totalcpuusage = 0; int i; for_each_possible_cpu(i) - totalcpuusage += cpuacct_cpuusage_read(ca, i); + totalcpuusage += cpuacct_cpuusage_read(ca, i, index); return totalcpuusage; } +static u64 cpuusage_user_read(struct cgroup_subsys_state *css, + struct cftype *cft) +{ + return __cpuusage_read(css, CPUACCT_USAGE_USER); +} + +static u64 cpuusage_sys_read(struct cgroup_subsys_state *css, + struct cftype *cft) +{ + return __cpuusage_read(css, CPUACCT_USAGE_SYSTEM); +} + +static u64 cpuusage_read(struct cgroup_subsys_state *css, struct cftype *cft) +{ + return __cpuusage_read(css, CPUACCT_USAGE_NRUSAGE); +} + static int cpuusage_write(struct cgroup_subsys_state *css, struct cftype *cft, u64 val) { struct cpuacct *ca = css_ca(css); - int err = 0; - int i; + int cpu; /* * Only allow '0' here to do a reset. */ - if (val) { - err = -EINVAL; - goto out; - } + if (val) + return -EINVAL; - for_each_possible_cpu(i) - cpuacct_cpuusage_write(ca, i, 0); + for_each_possible_cpu(cpu) + cpuacct_cpuusage_write(ca, cpu, 0); -out: - return err; + return 0; } -static int cpuacct_percpu_seq_show(struct seq_file *m, void *V) +static int __cpuacct_percpu_seq_show(struct seq_file *m, + enum cpuacct_usage_index index) { struct cpuacct *ca = css_ca(seq_css(m)); u64 percpu; int i; for_each_possible_cpu(i) { - percpu = cpuacct_cpuusage_read(ca, i); + percpu = cpuacct_cpuusage_read(ca, i, index); seq_printf(m, "%llu ", (unsigned long long) percpu); } seq_printf(m, "\n"); return 0; } +static int cpuacct_percpu_user_seq_show(struct seq_file *m, void *V) +{ + return __cpuacct_percpu_seq_show(m, CPUACCT_USAGE_USER); +} + +static int cpuacct_percpu_sys_seq_show(struct seq_file *m, void *V) +{ + return __cpuacct_percpu_seq_show(m, CPUACCT_USAGE_SYSTEM); +} + +static int cpuacct_percpu_seq_show(struct seq_file *m, void *V) +{ + return __cpuacct_percpu_seq_show(m, CPUACCT_USAGE_NRUSAGE); +} + static const char * const cpuacct_stat_desc[] = { [CPUACCT_STAT_USER] = "user", [CPUACCT_STAT_SYSTEM] = "system", @@ -219,10 +281,26 @@ static struct cftype files[] = { .read_u64 = cpuusage_read, .write_u64 = cpuusage_write, }, + { + .name = "usage_user", + .read_u64 = cpuusage_user_read, + }, + { + .name = "usage_sys", + .read_u64 = cpuusage_sys_read, + }, { .name = "usage_percpu", .seq_show = cpuacct_percpu_seq_show, }, + { + .name = "usage_percpu_user", + .seq_show = cpuacct_percpu_user_seq_show, + }, + { + .name = "usage_percpu_sys", + .seq_show = cpuacct_percpu_sys_seq_show, + }, { .name = "stat", .seq_show = cpuacct_stats_show, @@ -238,10 +316,18 @@ static struct cftype files[] = { void cpuacct_charge(struct task_struct *tsk, u64 cputime) { struct cpuacct *ca; + int index; + + if (user_mode(task_pt_regs(tsk))) + index = CPUACCT_USAGE_USER; + else + index = CPUACCT_USAGE_SYSTEM; rcu_read_lock(); + for (ca = task_ca(tsk); ca; ca = parent_ca(ca)) - *this_cpu_ptr(ca->cpuusage) += cputime; + this_cpu_ptr(ca->cpuusage)->usages[index] += cputime; + rcu_read_unlock(); } -- GitLab From d02c071183e1c01a76811c878c8a52322201f81f Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 23 Mar 2016 17:54:44 +0530 Subject: [PATCH 0944/9938] sched/fair: Reset nr_balance_failed after active balancing To force a task migration during active balancing, nr_balance_failed is set to cache_nice_tries + 1. However nr_balance_failed is not reset. As a side effect, the next regular load balance under the same sd, a cache hot task might be migrated, just because nr_balance_failed count is high. Resetting nr_balance_failed after a successful active balance ensures that a hot task is not unreasonably migrated. This can be verified by looking at othe number of hot task migrations reported by /proc/schedstat. Signed-off-by: Srikar Dronamraju Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1458735884-30105-1-git-send-email-srikar@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 0fe30e66aff1..cbb075e46b2c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7399,10 +7399,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, &busiest->active_balance_work); } - /* - * We've kicked active balancing, reset the failure - * counter. - */ + /* We've kicked active balancing, force task migration. */ sd->nr_balance_failed = sd->cache_nice_tries+1; } } else @@ -7637,10 +7634,13 @@ static int active_load_balance_cpu_stop(void *data) schedstat_inc(sd, alb_count); p = detach_one_task(&env); - if (p) + if (p) { schedstat_inc(sd, alb_pushed); - else + /* Active balancing done, reset the failure counter. */ + sd->nr_balance_failed = 0; + } else { schedstat_inc(sd, alb_failed); + } } rcu_read_unlock(); out_unlock: -- GitLab From bfdb198ccd99472c5bded689699eb30dd06316bb Mon Sep 17 00:00:00 2001 From: Tim Chen Date: Mon, 1 Feb 2016 14:47:59 -0800 Subject: [PATCH 0945/9938] sched/numa: Remove unnecessary NUMA dequeue update from non-SMP kernels In account_entity_enqueue(), we do not do account_numa_enqueue() as NUMA balancing is not needed for UP kernels. Hence, we should remove the account_numa_dequeue() call from account_entity_dequeue() for UP kernels. Signed-off-by: Tim Chen Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Cc: Rik van Riel Cc: Mel Gorman Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1454366879.21738.29.camel@schen9-desk2.jf.intel.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index cbb075e46b2c..1fe9916b4557 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2437,10 +2437,12 @@ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se) update_load_sub(&cfs_rq->load, se->load.weight); if (!parent_entity(se)) update_load_sub(&rq_of(cfs_rq)->load, se->load.weight); +#ifdef CONFIG_SMP if (entity_is_task(se)) { account_numa_dequeue(rq_of(cfs_rq), task_of(se)); list_del_init(&se->group_node); } +#endif cfs_rq->nr_running--; } -- GitLab From 47252cfbac03644ee4a3adfa50c77896aa94f2bb Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 21 Mar 2016 11:23:39 -0400 Subject: [PATCH 0946/9938] sched/core: Add preempt checks in preempt_schedule() code While testing the tracer preemptoff, I hit this strange trace: <...>-259 0...1 0us : schedule <-worker_thread <...>-259 0d..1 0us : rcu_note_context_switch <-__schedule <...>-259 0d..1 0us : rcu_sched_qs <-rcu_note_context_switch <...>-259 0d..1 0us : rcu_preempt_qs <-rcu_note_context_switch <...>-259 0d..1 0us : _raw_spin_lock <-__schedule <...>-259 0d..1 0us : preempt_count_add <-_raw_spin_lock <...>-259 0d..2 0us : do_raw_spin_lock <-_raw_spin_lock <...>-259 0d..2 1us : deactivate_task <-__schedule <...>-259 0d..2 1us : update_rq_clock.part.84 <-deactivate_task <...>-259 0d..2 1us : dequeue_task_fair <-deactivate_task <...>-259 0d..2 1us : dequeue_entity <-dequeue_task_fair <...>-259 0d..2 1us : update_curr <-dequeue_entity <...>-259 0d..2 1us : update_min_vruntime <-update_curr <...>-259 0d..2 1us : cpuacct_charge <-update_curr <...>-259 0d..2 1us : __rcu_read_lock <-cpuacct_charge <...>-259 0d..2 1us : __rcu_read_unlock <-cpuacct_charge <...>-259 0d..2 1us : clear_buddies <-dequeue_entity <...>-259 0d..2 1us : account_entity_dequeue <-dequeue_entity <...>-259 0d..2 2us : update_min_vruntime <-dequeue_entity <...>-259 0d..2 2us : update_cfs_shares <-dequeue_entity <...>-259 0d..2 2us : hrtick_update <-dequeue_task_fair <...>-259 0d..2 2us : wq_worker_sleeping <-__schedule <...>-259 0d..2 2us : kthread_data <-wq_worker_sleeping <...>-259 0d..2 2us : pick_next_task_fair <-__schedule <...>-259 0d..2 2us : check_cfs_rq_runtime <-pick_next_task_fair <...>-259 0d..2 2us : pick_next_entity <-pick_next_task_fair <...>-259 0d..2 2us : clear_buddies <-pick_next_entity <...>-259 0d..2 2us : pick_next_entity <-pick_next_task_fair <...>-259 0d..2 2us : clear_buddies <-pick_next_entity <...>-259 0d..2 2us : set_next_entity <-pick_next_task_fair <...>-259 0d..2 3us : put_prev_entity <-pick_next_task_fair <...>-259 0d..2 3us : check_cfs_rq_runtime <-put_prev_entity <...>-259 0d..2 3us : set_next_entity <-pick_next_task_fair gnome-sh-1031 0d..2 3us : finish_task_switch <-__schedule gnome-sh-1031 0d..2 3us : _raw_spin_unlock_irq <-finish_task_switch gnome-sh-1031 0d..2 3us : do_raw_spin_unlock <-_raw_spin_unlock_irq gnome-sh-1031 0...2 3us!: preempt_count_sub <-_raw_spin_unlock_irq gnome-sh-1031 0...1 582us : do_raw_spin_lock <-_raw_spin_lock gnome-sh-1031 0...1 583us : _raw_spin_unlock <-drm_gem_object_lookup gnome-sh-1031 0...1 583us : do_raw_spin_unlock <-_raw_spin_unlock gnome-sh-1031 0...1 583us : preempt_count_sub <-_raw_spin_unlock gnome-sh-1031 0...1 584us : _raw_spin_unlock <-drm_gem_object_lookup gnome-sh-1031 0...1 584us+: trace_preempt_on <-drm_gem_object_lookup gnome-sh-1031 0...1 603us : => preempt_count_sub => _raw_spin_unlock => drm_gem_object_lookup => i915_gem_madvise_ioctl => drm_ioctl => do_vfs_ioctl => SyS_ioctl => entry_SYSCALL_64_fastpath As I'm tracing preemption disabled, it seemed incorrect that the trace would go across a schedule and report not being in the scheduler. Looking into this I discovered the problem. schedule() calls preempt_disable() but the preempt_schedule() calls preempt_enable_notrace(). What happened above was that the gnome-shell task was preempted on another CPU, migrated over to the idle cpu. The tracer stared with idle calling schedule(), which called preempt_disable(), but then gnome-shell finished, and it enabled preemption with preempt_enable_notrace() that does stop the trace, even though preemption was enabled. The purpose of the preempt_disable_notrace() in the preempt_schedule() is to prevent function tracing from going into an infinite loop. Because function tracing can trace the preempt_enable/disable() calls that are traced. The problem with function tracing is: NEED_RESCHED set preempt_schedule() preempt_disable() preempt_count_inc() function trace (before incrementing preempt count) preempt_disable_notrace() preempt_enable_notrace() sees NEED_RESCHED set preempt_schedule() (repeat) Now by breaking out the preempt off/on tracing into their own code: preempt_disable_check() and preempt_enable_check(), we can add these to the preempt_schedule() code. As preemption would then be disabled, even if they were to be traced by the function tracer, the disabled preemption would prevent the recursion. Signed-off-by: Steven Rostedt Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160321112339.6dc78ad6@gandalf.local.home Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 68 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8b489fcac37b..b5cf01d2368e 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2958,6 +2958,20 @@ u64 scheduler_tick_max_deferment(void) #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ defined(CONFIG_PREEMPT_TRACER)) +/* + * If the value passed in is equal to the current preempt count + * then we just disabled preemption. Start timing the latency. + */ +static inline void preempt_latency_start(int val) +{ + if (preempt_count() == val) { + unsigned long ip = get_lock_parent_ip(); +#ifdef CONFIG_DEBUG_PREEMPT + current->preempt_disable_ip = ip; +#endif + trace_preempt_off(CALLER_ADDR0, ip); + } +} void preempt_count_add(int val) { @@ -2976,17 +2990,21 @@ void preempt_count_add(int val) DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= PREEMPT_MASK - 10); #endif - if (preempt_count() == val) { - unsigned long ip = get_lock_parent_ip(); -#ifdef CONFIG_DEBUG_PREEMPT - current->preempt_disable_ip = ip; -#endif - trace_preempt_off(CALLER_ADDR0, ip); - } + preempt_latency_start(val); } EXPORT_SYMBOL(preempt_count_add); NOKPROBE_SYMBOL(preempt_count_add); +/* + * If the value passed in equals to the current preempt count + * then we just enabled preemption. Stop timing the latency. + */ +static inline void preempt_latency_stop(int val) +{ + if (preempt_count() == val) + trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip()); +} + void preempt_count_sub(int val) { #ifdef CONFIG_DEBUG_PREEMPT @@ -3003,13 +3021,15 @@ void preempt_count_sub(int val) return; #endif - if (preempt_count() == val) - trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip()); + preempt_latency_stop(val); __preempt_count_sub(val); } EXPORT_SYMBOL(preempt_count_sub); NOKPROBE_SYMBOL(preempt_count_sub); +#else +static inline void preempt_latency_start(int val) { } +static inline void preempt_latency_stop(int val) { } #endif /* @@ -3284,8 +3304,23 @@ void __sched schedule_preempt_disabled(void) static void __sched notrace preempt_schedule_common(void) { do { + /* + * Because the function tracer can trace preempt_count_sub() + * and it also uses preempt_enable/disable_notrace(), if + * NEED_RESCHED is set, the preempt_enable_notrace() called + * by the function tracer will call this function again and + * cause infinite recursion. + * + * Preemption must be disabled here before the function + * tracer can trace. Break up preempt_disable() into two + * calls. One to disable preemption without fear of being + * traced. The other to still record the preemption latency, + * which can also be traced by the function tracer. + */ preempt_disable_notrace(); + preempt_latency_start(1); __schedule(true); + preempt_latency_stop(1); preempt_enable_no_resched_notrace(); /* @@ -3337,7 +3372,21 @@ asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) return; do { + /* + * Because the function tracer can trace preempt_count_sub() + * and it also uses preempt_enable/disable_notrace(), if + * NEED_RESCHED is set, the preempt_enable_notrace() called + * by the function tracer will call this function again and + * cause infinite recursion. + * + * Preemption must be disabled here before the function + * tracer can trace. Break up preempt_disable() into two + * calls. One to disable preemption without fear of being + * traced. The other to still record the preemption latency, + * which can also be traced by the function tracer. + */ preempt_disable_notrace(); + preempt_latency_start(1); /* * Needs preempt disabled in case user_exit() is traced * and the tracer calls preempt_enable_notrace() causing @@ -3347,6 +3396,7 @@ asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) __schedule(true); exception_exit(prev_ctx); + preempt_latency_stop(1); preempt_enable_no_resched_notrace(); } while (need_resched()); } -- GitLab From 1c3de5e19fc96206dd086e634129d08e5f7b1000 Mon Sep 17 00:00:00 2001 From: Yuyang Du Date: Wed, 30 Mar 2016 07:07:51 +0800 Subject: [PATCH 0947/9938] sched/fair: Update comments after a variable rename The following commit: ed82b8a1ff76 ("sched/core: Move the sched_to_prio[] arrays out of line") renamed prio_to_weight to sched_prio_to_weight, but the old name was not updated in comments. Signed-off-by: Yuyang Du Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459292871-22531-1-git-send-email-yuyang.du@intel.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 1fe9916b4557..4bb5ace60dc8 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -204,7 +204,7 @@ static void __update_inv_weight(struct load_weight *lw) * OR * (delta_exec * (weight * lw->inv_weight)) >> WMULT_SHIFT * - * Either weight := NICE_0_LOAD and lw \e prio_to_wmult[], in which case + * Either weight := NICE_0_LOAD and lw \e sched_prio_to_wmult[], in which case * we're guaranteed shift stays positive because inv_weight is guaranteed to * fit 32 bits, and NICE_0_LOAD gives another 10 bits; therefore shift >= 22. * @@ -5656,7 +5656,7 @@ static bool yield_to_task_fair(struct rq *rq, struct task_struct *p, bool preemp * W_i,0 = \Sum_j w_i,j (2) * * Where w_i,j is the weight of the j-th runnable task on cpu i. This weight - * is derived from the nice value as per prio_to_weight[]. + * is derived from the nice value as per sched_prio_to_weight[]. * * The weight average is an exponential decay average of the instantaneous * weight: -- GitLab From 2b8c41daba327c633228169e8bd8ec067ab443f8 Mon Sep 17 00:00:00 2001 From: Yuyang Du Date: Wed, 30 Mar 2016 04:30:56 +0800 Subject: [PATCH 0948/9938] sched/fair: Initiate a new task's util avg to a bounded value A new task's util_avg is set to full utilization of a CPU (100% time running). This accelerates a new task's utilization ramp-up, useful to boost its execution in early time. However, it may result in (insanely) high utilization for a transient time period when a flood of tasks are spawned. Importantly, it violates the "fundamentally bounded" CPU utilization, and its side effect is negative if we don't take any measure to bound it. This patch proposes an algorithm to address this issue. It has two methods to approach a sensible initial util_avg: (1) An expected (or average) util_avg based on its cfs_rq's util_avg: util_avg = cfs_rq->util_avg / (cfs_rq->load_avg + 1) * se.load.weight (2) A trajectory of how successive new tasks' util develops, which gives 1/2 of the left utilization budget to a new task such that the additional util is noticeably large (when overall util is low) or unnoticeably small (when overall util is high enough). In the meantime, the aggregate utilization is well bounded: util_avg_cap = (1024 - cfs_rq->avg.util_avg) / 2^n where n denotes the nth task. If util_avg is larger than util_avg_cap, then the effective util is clamped to the util_avg_cap. Reported-by: Andrey Ryabinin Signed-off-by: Yuyang Du Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bsegall@google.com Cc: morten.rasmussen@arm.com Cc: pjt@google.com Cc: steve.muckle@linaro.org Link: http://lkml.kernel.org/r/1459283456-21682-1-git-send-email-yuyang.du@intel.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 2 ++ kernel/sched/fair.c | 56 ++++++++++++++++++++++++++++++++++++++++++-- kernel/sched/sched.h | 1 + 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b5cf01d2368e..11594230ef4d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2431,6 +2431,8 @@ void wake_up_new_task(struct task_struct *p) */ set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0)); #endif + /* Post initialize new task's util average when its cfs_rq is set */ + post_init_entity_util_avg(&p->se); rq = __task_rq_lock(p); activate_task(rq, p, 0); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 4bb5ace60dc8..b8cc1c35cd7c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -682,17 +682,68 @@ void init_entity_runnable_average(struct sched_entity *se) sa->period_contrib = 1023; sa->load_avg = scale_load_down(se->load.weight); sa->load_sum = sa->load_avg * LOAD_AVG_MAX; - sa->util_avg = scale_load_down(SCHED_LOAD_SCALE); - sa->util_sum = sa->util_avg * LOAD_AVG_MAX; + /* + * At this point, util_avg won't be used in select_task_rq_fair anyway + */ + sa->util_avg = 0; + sa->util_sum = 0; /* when this task enqueue'ed, it will contribute to its cfs_rq's load_avg */ } +/* + * With new tasks being created, their initial util_avgs are extrapolated + * based on the cfs_rq's current util_avg: + * + * util_avg = cfs_rq->util_avg / (cfs_rq->load_avg + 1) * se.load.weight + * + * However, in many cases, the above util_avg does not give a desired + * value. Moreover, the sum of the util_avgs may be divergent, such + * as when the series is a harmonic series. + * + * To solve this problem, we also cap the util_avg of successive tasks to + * only 1/2 of the left utilization budget: + * + * util_avg_cap = (1024 - cfs_rq->avg.util_avg) / 2^n + * + * where n denotes the nth task. + * + * For example, a simplest series from the beginning would be like: + * + * task util_avg: 512, 256, 128, 64, 32, 16, 8, ... + * cfs_rq util_avg: 512, 768, 896, 960, 992, 1008, 1016, ... + * + * Finally, that extrapolated util_avg is clamped to the cap (util_avg_cap) + * if util_avg > util_avg_cap. + */ +void post_init_entity_util_avg(struct sched_entity *se) +{ + struct cfs_rq *cfs_rq = cfs_rq_of(se); + struct sched_avg *sa = &se->avg; + long cap = (long)(scale_load_down(SCHED_LOAD_SCALE) - cfs_rq->avg.util_avg) / 2; + + if (cap > 0) { + if (cfs_rq->avg.util_avg != 0) { + sa->util_avg = cfs_rq->avg.util_avg * se->load.weight; + sa->util_avg /= (cfs_rq->avg.load_avg + 1); + + if (sa->util_avg > cap) + sa->util_avg = cap; + } else { + sa->util_avg = cap; + } + sa->util_sum = sa->util_avg * LOAD_AVG_MAX; + } +} + static inline unsigned long cfs_rq_runnable_load_avg(struct cfs_rq *cfs_rq); static inline unsigned long cfs_rq_load_avg(struct cfs_rq *cfs_rq); #else void init_entity_runnable_average(struct sched_entity *se) { } +void post_init_entity_util_avg(struct sched_entity *se) +{ +} #endif /* @@ -8384,6 +8435,7 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) init_cfs_rq(cfs_rq); init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]); init_entity_runnable_average(se); + post_init_entity_util_avg(se); } return 1; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index ec2e8d23527e..a7cbad7b3ad2 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1313,6 +1313,7 @@ extern void init_dl_task_timer(struct sched_dl_entity *dl_se); unsigned long to_ratio(u64 period, u64 runtime); extern void init_entity_runnable_average(struct sched_entity *se); +extern void post_init_entity_util_avg(struct sched_entity *se); #ifdef CONFIG_NO_HZ_FULL extern bool sched_can_stop_tick(struct rq *rq); -- GitLab From 456829228f96702ca281b65e11d11e8c09ca9da0 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 9 Mar 2016 18:16:47 -0800 Subject: [PATCH 0949/9938] clk: imx: clk-gate2: allow custom gate configuration The 2-bit gates found i.MX and Vybrid SoC support different clock configuration: 0b00: clk disabled 0b01: clk enabled in RUN mode but disabled in WAIT and STOP mode 0b10: clk enabled in RUN, WAIT and STOP mode (only Vybrid) 0b11: clk enabled in RUN and WAIT mode For some clocks, we might want to configure different behaviour, e.g. a memory clock should be on even in STOP mode. Add a new function imx_clk_gate2_cgr which allow to configure specific gate values through the cgr_val parameter. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-gate2.c | 7 +++++-- drivers/clk/imx/clk.h | 13 ++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index 8935bff99fe7..db44a198a0d9 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -31,6 +31,7 @@ struct clk_gate2 { struct clk_hw hw; void __iomem *reg; u8 bit_idx; + u8 cgr_val; u8 flags; spinlock_t *lock; unsigned int *share_count; @@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_hw *hw) goto out; reg = readl(gate->reg); - reg |= 3 << gate->bit_idx; + reg &= ~(3 << gate->bit_idx); + reg |= gate->cgr_val << gate->bit_idx; writel(reg, gate->reg); out: @@ -125,7 +127,7 @@ static struct clk_ops clk_gate2_ops = { struct clk *clk_register_gate2(struct device *dev, const char *name, const char *parent_name, unsigned long flags, - void __iomem *reg, u8 bit_idx, + void __iomem *reg, u8 bit_idx, u8 cgr_val, u8 clk_gate2_flags, spinlock_t *lock, unsigned int *share_count) { @@ -140,6 +142,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name, /* struct clk_gate2 assignments */ gate->reg = reg; gate->bit_idx = bit_idx; + gate->cgr_val = cgr_val; gate->flags = clk_gate2_flags; gate->lock = lock; gate->share_count = share_count; diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index d942f5748d08..508d0fad84cf 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -41,7 +41,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, struct clk *clk_register_gate2(struct device *dev, const char *name, const char *parent_name, unsigned long flags, - void __iomem *reg, u8 bit_idx, + void __iomem *reg, u8 bit_idx, u8 cgr_val, u8 clk_gate_flags, spinlock_t *lock, unsigned int *share_count); @@ -55,7 +55,7 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent, void __iomem *reg, u8 shift) { return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, - shift, 0, &imx_ccm_lock, NULL); + shift, 0x3, 0, &imx_ccm_lock, NULL); } static inline struct clk *imx_clk_gate2_shared(const char *name, @@ -63,7 +63,14 @@ static inline struct clk *imx_clk_gate2_shared(const char *name, unsigned int *share_count) { return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, - shift, 0, &imx_ccm_lock, share_count); + shift, 0x3, 0, &imx_ccm_lock, share_count); +} + +static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 cgr_val) +{ + return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, + shift, cgr_val, 0, &imx_ccm_lock, NULL); } struct clk *imx_clk_pfd(const char *name, const char *parent_name, -- GitLab From 0da15d36a90f405541773e884b3264e0f94debd3 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 9 Mar 2016 18:16:48 -0800 Subject: [PATCH 0950/9938] clk: imx: vf610: leave DDR clock on To use STOP mode without putting DDR3 into self-refresh mode, we need to keep the DDR clock enabled. Use the new gate configuration with a value of 2 to make sure that the clock is enabled in RUN, WAIT and STOP mode. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-vf610.c | 3 +++ include/dt-bindings/clock/vf610-clock.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 0a94d9661d91..f0ff45811e76 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -119,6 +119,7 @@ static unsigned int const clks_init_on[] __initconst = { VF610_CLK_SYS_BUS, VF610_CLK_DDR_SEL, VF610_CLK_DAP, + VF610_CLK_DDRMC, }; static struct clk * __init vf610_get_fixed_clock( @@ -233,6 +234,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock); clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1); + clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2); + clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6); clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6); diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index 56c16aaea112..cf2c00a06d10 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h @@ -195,6 +195,7 @@ #define VF610_CLK_SNVS 182 #define VF610_CLK_DAP 183 #define VF610_CLK_OCOTP 184 -#define VF610_CLK_END 185 +#define VF610_CLK_DDRMC 185 +#define VF610_CLK_END 186 #endif /* __DT_BINDINGS_CLOCK_VF610_H */ -- GitLab From 349efbeedb2b79292eee12cf6b9a2422ef93853d Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 9 Mar 2016 18:16:49 -0800 Subject: [PATCH 0951/9938] clk: imx: vf610: add WKPU unit Signed-off-by: Stefan Agner Acked-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-vf610.c | 2 ++ include/dt-bindings/clock/vf610-clock.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index f0ff45811e76..610a72464f1e 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -120,6 +120,7 @@ static unsigned int const clks_init_on[] __initconst = { VF610_CLK_DDR_SEL, VF610_CLK_DAP, VF610_CLK_DDRMC, + VF610_CLK_WKPU, }; static struct clk * __init vf610_get_fixed_clock( @@ -235,6 +236,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1); clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2); + clk[VF610_CLK_WKPU] = imx_clk_gate2_cgr("wkpu", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(10), 0x2); clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6); clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6); diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index cf2c00a06d10..7dc1b84fde07 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h @@ -196,6 +196,7 @@ #define VF610_CLK_DAP 183 #define VF610_CLK_OCOTP 184 #define VF610_CLK_DDRMC 185 -#define VF610_CLK_END 186 +#define VF610_CLK_WKPU 186 +#define VF610_CLK_END 187 #endif /* __DT_BINDINGS_CLOCK_VF610_H */ -- GitLab From 4cfe6aebb272d7c75a2c21ce5db3a9e10f57901a Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 9 Mar 2016 18:16:50 -0800 Subject: [PATCH 0952/9938] clk: imx: vf610: add suspend/resume support The clock register are lost when enterying LPSTOPx, hence provide suspend/resume functions restoring them. The clock gates get restored by the individual driver, hence we do not need to restore them here. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-vf610.c | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 610a72464f1e..66e6faede8e5 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "clk.h" @@ -40,6 +41,7 @@ #define CCM_CCGR9 (ccm_base + 0x64) #define CCM_CCGR10 (ccm_base + 0x68) #define CCM_CCGR11 (ccm_base + 0x6c) +#define CCM_CCGRx(x) (CCM_CCGR0 + (x) * 4) #define CCM_CMEOR0 (ccm_base + 0x70) #define CCM_CMEOR1 (ccm_base + 0x74) #define CCM_CMEOR2 (ccm_base + 0x78) @@ -115,6 +117,13 @@ static struct clk_div_table pll4_audio_div_table[] = { static struct clk *clk[VF610_CLK_END]; static struct clk_onecell_data clk_data; +static u32 cscmr1; +static u32 cscmr2; +static u32 cscdr1; +static u32 cscdr2; +static u32 cscdr3; +static u32 ccgr[12]; + static unsigned int const clks_init_on[] __initconst = { VF610_CLK_SYS_BUS, VF610_CLK_DDR_SEL, @@ -134,6 +143,43 @@ static struct clk * __init vf610_get_fixed_clock( return clk; }; +static int vf610_clk_suspend(void) +{ + int i; + + cscmr1 = readl_relaxed(CCM_CSCMR1); + cscmr2 = readl_relaxed(CCM_CSCMR2); + + cscdr1 = readl_relaxed(CCM_CSCDR1); + cscdr2 = readl_relaxed(CCM_CSCDR2); + cscdr3 = readl_relaxed(CCM_CSCDR3); + + for (i = 0; i < 12; i++) + ccgr[i] = readl_relaxed(CCM_CCGRx(i)); + + return 0; +} + +static void vf610_clk_resume(void) +{ + int i; + + writel_relaxed(cscmr1, CCM_CSCMR1); + writel_relaxed(cscmr2, CCM_CSCMR2); + + writel_relaxed(cscdr1, CCM_CSCDR1); + writel_relaxed(cscdr2, CCM_CSCDR2); + writel_relaxed(cscdr3, CCM_CSCDR3); + + for (i = 0; i < 12; i++) + writel_relaxed(ccgr[i], CCM_CCGRx(i)); +} + +static struct syscore_ops vf610_clk_syscore_ops = { + .suspend = vf610_clk_suspend, + .resume = vf610_clk_resume, +}; + static void __init vf610_clocks_init(struct device_node *ccm_node) { struct device_node *np; @@ -414,6 +460,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) clk_prepare_enable(clk[clks_init_on[i]]); + register_syscore_ops(&vf610_clk_syscore_ops); + /* Add the clocks to provider list */ clk_data.clks = clk; clk_data.clk_num = ARRAY_SIZE(clk); -- GitLab From 75c004df525e3bda38dfac1f0e8eff7fe515a0ab Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 31 Mar 2016 11:09:11 +0200 Subject: [PATCH 0953/9938] gpio: dt-bindings: document the concept of GPIO banks Cc: devicetree@vger.kernel.org Cc: Neil Armstrong Cc: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 069cdf6f9dac..f509ecf03ece 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -131,6 +131,19 @@ Every GPIO controller node must contain both an empty "gpio-controller" property, and a #gpio-cells integer property, which indicates the number of cells in a gpio-specifier. +Some system-on-chips (SoCs) use the concept of GPIO banks. A GPIO bank is an +instance of a hardware IP core on a silicon die, usually exposed to the +programmer as a coherent range of I/O addresses. Usually each such bank is +exposed in the device tree as an individual gpio-controller node, reflecting +the fact that the hardware was synthesized by reusing the same IP block a +few times over. + +A GPIO controller may specify a bank ID. This is a hardware index that +indicate the logical order of the GPIO controller in the hardware architecture, +usually in the sequence 0, 1, 2 .. n. The hardware index may be different +from the order of register ranges and related to the backplane of how this +one bank is connected to the outside through a pin controller for example. + Optionally, a GPIO controller may have a "ngpios" property. This property indicates the number of in-use slots of available slots for GPIOs. The typical example is something like this: the hardware register is 32 bits @@ -152,6 +165,7 @@ gpio-controller@00000000 { reg = <0x00000000 0x1000>; gpio-controller; #gpio-cells = <2>; + gpio-bank = <0>; ngpios = <18>; } -- GitLab From f6a49e5a3f5562855f9e4b9b81916b06ef673771 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 25 Mar 2016 13:36:29 +0100 Subject: [PATCH 0954/9938] tools/gpio: Enable compiler optimization to catch more bugs Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- tools/gpio/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index 4d198d5c4203..c155d6bc47a7 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile @@ -1,5 +1,5 @@ CC = $(CROSS_COMPILE)gcc -CFLAGS += -Wall -g -D_GNU_SOURCE +CFLAGS += -O2 -Wall -g -D_GNU_SOURCE all: lsgpio -- GitLab From 691998fac6f50c9117e279c3fbfa63a23cf7ce2e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 25 Mar 2016 13:36:30 +0100 Subject: [PATCH 0955/9938] tools/gpio: Add missing initialization of device_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lsgpio.c: In function ‘main’: lsgpio.c:166:7: warning: ‘device_name’ may be used uninitialized in this functio n [-Wmaybe-uninitialized] ret = list_device(device_name); ^ Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- tools/gpio/lsgpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c index 1124da375942..eb3f56efd215 100644 --- a/tools/gpio/lsgpio.c +++ b/tools/gpio/lsgpio.c @@ -147,7 +147,7 @@ void print_usage(void) int main(int argc, char **argv) { - const char *device_name; + const char *device_name = NULL; int ret; int c; -- GitLab From 8fccdb580ebec0f5b081d824797911a4c5d91891 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 27 Mar 2016 17:43:02 +0200 Subject: [PATCH 0956/9938] gpio: gpio-it87: Add support for IT8620 and IT8628 These chips seem to have a 9th GPIO block (thus supporting 72 GPIOs) which is configured through SuperIO register 0xd2 (output enable) and 0xd3 (simple I/O). This is also the reason why io_size is larger than on IT8728 / IT8732. Unfortunately I don't have hardware to test this 9th GPIO block. I am also not sure about not configuring the Simple I/O registers as the hardware I have only uses GPIO block 8. Reading back the values of 0xc0-0xc7 (as configured by the BIOS/EFI on my board) shows that all have 0xff set. Signed-off-by: Martin Blumenstingl Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-it87.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 78898367b34e..08a93e0b35c5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -558,7 +558,7 @@ config GPIO_IT87 Say yes here to support GPIO functionality of IT87xx Super I/O chips. This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and - supports the IT8761E Super I/O chip as well. + supports the IT8761E, IT8620E and IT8628E Super I/O chip as well. To compile this driver as a module, choose M here: the module will be called gpio_it87 diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c index b219c82414bf..63a962d18cd6 100644 --- a/drivers/gpio/gpio-it87.c +++ b/drivers/gpio/gpio-it87.c @@ -34,6 +34,8 @@ /* Chip Id numbers */ #define NO_DEV_ID 0xffff +#define IT8620_ID 0x8620 +#define IT8628_ID 0x8628 #define IT8728_ID 0x8728 #define IT8732_ID 0x8732 #define IT8761_ID 0x8761 @@ -302,6 +304,14 @@ static int __init it87_gpio_init(void) it87_gpio->chip = it87_template_chip; switch (chip_type) { + case IT8620_ID: + case IT8628_ID: + gpio_ba_reg = 0x62; + it87_gpio->io_size = 11; + it87_gpio->output_base = 0xc8; + it87_gpio->simple_size = 0; + it87_gpio->chip.ngpio = 64; + break; case IT8728_ID: case IT8732_ID: gpio_ba_reg = 0x62; -- GitLab From 8f3e19fae04a0c85d137dbb6f3c49de63b60cfc2 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:41 -0400 Subject: [PATCH 0957/9938] gpio: bcm-kona: make explicitly non-modular The Kconfig currently controlling compilation of this code is: config GPIO_BCM_KONA bool "Broadcom Kona GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Ray Jui Cc: Alexandre Courbot Cc: bcm-kernel-feedback-list@broadcom.com Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bcm-kona.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 2fd38d598f3d..9aabc48ff5de 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -1,4 +1,7 @@ /* + * Broadcom Kona GPIO Driver + * + * Author: Broadcom Corporation * Copyright (C) 2012-2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or @@ -17,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -502,8 +505,6 @@ static struct of_device_id const bcm_kona_gpio_of_match[] = { {} }; -MODULE_DEVICE_TABLE(of, bcm_kona_gpio_of_match); - /* * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. @@ -659,9 +660,4 @@ static struct platform_driver bcm_kona_gpio_driver = { }, .probe = bcm_kona_gpio_probe, }; - -module_platform_driver(bcm_kona_gpio_driver); - -MODULE_AUTHOR("Broadcom Corporation "); -MODULE_DESCRIPTION("Broadcom Kona GPIO Driver"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(bcm_kona_gpio_driver); -- GitLab From fd00bbcddb59c4866e7c985e30f663b62cfc2588 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 31 Mar 2016 11:47:58 +0900 Subject: [PATCH 0958/9938] dt-bindings: Add the clock id of UART2 and MMC2 for Exynos3250 This patch adds the new clock id for both UART2 and MM2 device for Exynos3250 SoC. Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos3250.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/exynos3250.h b/include/dt-bindings/clock/exynos3250.h index 63d01c15d2b3..c796ff02ceeb 100644 --- a/include/dt-bindings/clock/exynos3250.h +++ b/include/dt-bindings/clock/exynos3250.h @@ -79,6 +79,8 @@ #define CLK_MOUT_CORE 58 #define CLK_MOUT_APLL 59 #define CLK_MOUT_ACLK_266_SUB 60 +#define CLK_MOUT_UART2 61 +#define CLK_MOUT_MMC2 62 /* Dividers */ #define CLK_DIV_GPL 64 @@ -127,6 +129,9 @@ #define CLK_DIV_CORE 107 #define CLK_DIV_HPM 108 #define CLK_DIV_COPY 109 +#define CLK_DIV_UART2 110 +#define CLK_DIV_MMC2_PRE 111 +#define CLK_DIV_MMC2 112 /* Gates */ #define CLK_ASYNC_G3D 128 @@ -223,6 +228,8 @@ #define CLK_BLOCK_MFC 219 #define CLK_BLOCK_CAM 220 #define CLK_SMIES 221 +#define CLK_UART2 222 +#define CLK_SDMMC2 223 /* Special clocks */ #define CLK_SCLK_JPEG 224 @@ -249,12 +256,14 @@ #define CLK_SCLK_SPI0 245 #define CLK_SCLK_UART1 246 #define CLK_SCLK_UART0 247 +#define CLK_SCLK_UART2 248 +#define CLK_SCLK_MMC2 249 /* * Total number of clocks of main CMU. * NOTE: Must be equal to last clock ID increased by one. */ -#define CLK_NR_CLKS 248 +#define CLK_NR_CLKS 250 /* * CMU DMC -- GitLab From 27c0efedcf1be044dd638784189de816382f3f43 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Thu, 31 Mar 2016 11:47:59 +0900 Subject: [PATCH 0959/9938] clk: samsung: exynos3250: Add UART2 clock This patch add the UART2 clocks (mux, divider, gate) of Exynos3250 SoC. Signed-off-by: Pankaj Dubey Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index fdd41b17a24f..bc60e399d1bc 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -306,6 +306,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = { MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 4), /* SRC_PERIL0 */ + MUX(CLK_MOUT_UART2, "mout_uart2", group_sclk_p, SRC_PERIL0, 8, 4), MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4), MUX(CLK_MOUT_UART0, "mout_uart0", group_sclk_p, SRC_PERIL0, 0, 4), @@ -390,6 +391,7 @@ static struct samsung_div_clock div_clks[] __initdata = { DIV(CLK_DIV_MMC0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), /* DIV_PERIL0 */ + DIV(CLK_DIV_UART2, "div_uart2", "mout_uart2", DIV_PERIL0, 8, 4), DIV(CLK_DIV_UART1, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4), DIV(CLK_DIV_UART0, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4), @@ -552,6 +554,9 @@ static struct samsung_gate_clock gate_clks[] __initdata = { GATE_SCLK_PERIL, 7, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi0_pre", GATE_SCLK_PERIL, 6, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2", + GATE_SCLK_PERIL, 2, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1", GATE_SCLK_PERIL, 1, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", @@ -649,6 +654,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = { GATE(CLK_I2C2, "i2c2", "div_aclk_100", GATE_IP_PERIL, 8, 0, 0), GATE(CLK_I2C1, "i2c1", "div_aclk_100", GATE_IP_PERIL, 7, 0, 0), GATE(CLK_I2C0, "i2c0", "div_aclk_100", GATE_IP_PERIL, 6, 0, 0), + GATE(CLK_UART2, "uart2", "div_aclk_100", GATE_IP_PERIL, 2, 0, 0), GATE(CLK_UART1, "uart1", "div_aclk_100", GATE_IP_PERIL, 1, 0, 0), GATE(CLK_UART0, "uart0", "div_aclk_100", GATE_IP_PERIL, 0, 0, 0), }; -- GitLab From f6764714afdde1f0f511bb0e2d531593c3bec827 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 31 Mar 2016 11:48:00 +0900 Subject: [PATCH 0960/9938] clk: samsung: exynos3250: Add MMC2 clock This patch add the MMC2 clocks (mux, divider, gate) of Exynos3250 SoC. Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index bc60e399d1bc..16575ee874cb 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -302,6 +302,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = { /* SRC_FSYS */ MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4), + MUX(CLK_MOUT_MMC2, "mout_mmc2", group_sclk_p, SRC_FSYS, 8, 4), MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 4), MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 4), @@ -390,6 +391,11 @@ static struct samsung_div_clock div_clks[] __initdata = { CLK_SET_RATE_PARENT, 0), DIV(CLK_DIV_MMC0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), + /* DIV_FSYS2 */ + DIV_F(CLK_DIV_MMC2_PRE, "div_mmc2_pre", "div_mmc2", DIV_FSYS2, 8, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_MMC2, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4), + /* DIV_PERIL0 */ DIV(CLK_DIV_UART2, "div_uart2", "mout_uart2", DIV_PERIL0, 8, 4), DIV(CLK_DIV_UART1, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4), @@ -540,6 +546,8 @@ static struct samsung_gate_clock gate_clks[] __initdata = { GATE_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_EBI, "sclk_ebi", "div_ebi", GATE_SCLK_FSYS, 6, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc2_pre", + GATE_SCLK_FSYS, 2, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc1_pre", GATE_SCLK_FSYS, 1, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc0_pre", @@ -635,6 +643,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = { GATE(CLK_USBOTG, "usbotg", "div_aclk_200", GATE_IP_FSYS, 13, 0, 0), GATE(CLK_USBHOST, "usbhost", "div_aclk_200", GATE_IP_FSYS, 12, 0, 0), GATE(CLK_SROMC, "sromc", "div_aclk_200", GATE_IP_FSYS, 11, 0, 0), + GATE(CLK_SDMMC2, "sdmmc2", "div_aclk_200", GATE_IP_FSYS, 7, 0, 0), GATE(CLK_SDMMC1, "sdmmc1", "div_aclk_200", GATE_IP_FSYS, 6, 0, 0), GATE(CLK_SDMMC0, "sdmmc0", "div_aclk_200", GATE_IP_FSYS, 5, 0, 0), GATE(CLK_PDMA1, "pdma1", "div_aclk_200", GATE_IP_FSYS, 1, 0, 0), -- GitLab From 568a58e5dfbcb88011cad7f87ed046aa00f19d1a Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:42:01 +0200 Subject: [PATCH 0961/9938] x86/mm/pat, x86/cpufeature: Remove cpu_has_pat Signed-off-by: Borislav Petkov Acked-by: Daniel Vetter Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: intel-gfx@lists.freedesktop.org Link: http://lkml.kernel.org/r/1459266123-21878-9-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - drivers/gpu/drm/i915/i915_gem.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3636ec06c887..7a3fa7d70bd7 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -132,7 +132,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLUSH) #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) -#define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3d31d3ac589e..aaec8aef9fd4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1732,7 +1732,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, if (args->flags & ~(I915_MMAP_WC)) return -EINVAL; - if (args->flags & I915_MMAP_WC && !cpu_has_pat) + if (args->flags & I915_MMAP_WC && !boot_cpu_has(X86_FEATURE_PAT)) return -ENODEV; obj = drm_gem_object_lookup(dev, file, args->handle); -- GitLab From 7b5e74e637e4a977c7cf40fd7de332f60b68180e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:41:54 +0200 Subject: [PATCH 0962/9938] x86/cpufeature: Remove cpu_has_arch_perfmon Use boot_cpu_has() instead. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: oprofile-list@lists.sf.net Link: http://lkml.kernel.org/r/1459266123-21878-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/oprofile/nmi_int.c | 4 ++-- arch/x86/oprofile/op_model_ppro.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3636ec06c887..fee7a6efcd2d 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -131,7 +131,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2) #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLUSH) #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) -#define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 0e07e0968c3a..25171e9595f7 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -636,7 +636,7 @@ static int __init ppro_init(char **cpu_type) __u8 cpu_model = boot_cpu_data.x86_model; struct op_x86_model_spec *spec = &op_ppro_spec; /* default */ - if (force_cpu_type == arch_perfmon && cpu_has_arch_perfmon) + if (force_cpu_type == arch_perfmon && boot_cpu_has(X86_FEATURE_ARCH_PERFMON)) return 0; /* @@ -761,7 +761,7 @@ int __init op_nmi_init(struct oprofile_operations *ops) if (cpu_type) break; - if (!cpu_has_arch_perfmon) + if (!boot_cpu_has(X86_FEATURE_ARCH_PERFMON)) return -ENODEV; /* use arch perfmon as fallback */ diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index d90528ea5412..350f7096baac 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -75,7 +75,7 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model, u64 val; int i; - if (cpu_has_arch_perfmon) { + if (boot_cpu_has(X86_FEATURE_ARCH_PERFMON)) { union cpuid10_eax eax; eax.full = cpuid_eax(0xa); -- GitLab From 0c9f3536cc712dfd5ec3127d55cd7b807cc0adb5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:41:55 +0200 Subject: [PATCH 0963/9938] x86/cpufeature: Remove cpu_has_hypervisor Use boot_cpu_has() instead. Tested-by: David Kershner Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: sparmaintainer@unisys.com Cc: virtualization@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1459266123-21878-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/events/intel/uncore.c | 2 +- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kernel/cpu/vmware.c | 2 +- arch/x86/kernel/kvm.c | 2 +- drivers/staging/unisys/visorbus/visorchipset.c | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index 7012d18bb293..3f6d8b5672d5 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -1383,7 +1383,7 @@ static int __init intel_uncore_init(void) if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) return -ENODEV; - if (cpu_has_hypervisor) + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) return -ENODEV; max_packages = topology_max_packages(); diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index fee7a6efcd2d..3aea54ecabfd 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -136,7 +136,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) #define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) -#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) /* * Do not add any more of those clumsy macros - use static_cpu_has() for * fast paths and boot_cpu_has() otherwise! diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 364e58346897..8cac429b6a1d 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -94,7 +94,7 @@ static void __init vmware_platform_setup(void) */ static uint32_t __init vmware_platform(void) { - if (cpu_has_hypervisor) { + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) { unsigned int eax; unsigned int hyper_vendor_id[3]; diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 807950860fb7..dc1207e2f193 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -522,7 +522,7 @@ static noinline uint32_t __kvm_cpuid_base(void) if (boot_cpu_data.cpuid_level < 0) return 0; /* So we don't blow up on old processors */ - if (cpu_has_hypervisor) + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) return hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0); return 0; diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 5fbda7b218c7..9cf4f8463c4e 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2425,7 +2425,7 @@ static __init uint32_t visorutil_spar_detect(void) { unsigned int eax, ebx, ecx, edx; - if (cpu_has_hypervisor) { + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) { /* check the ID */ cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx); return (ebx == UNISYS_SPAR_ID_EBX) && -- GitLab From ab4a56fa2c6ce9384ca077b6570c56fe18361f17 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:41:56 +0200 Subject: [PATCH 0964/9938] x86/cpufeature: Remove cpu_has_osxsave Use boot_cpu_has() instead. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-crypto@vger.kernel.org Link: http://lkml.kernel.org/r/1459266123-21878-4-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/crypto/camellia_aesni_avx2_glue.c | 3 ++- arch/x86/crypto/camellia_aesni_avx_glue.c | 2 +- arch/x86/crypto/serpent_avx2_glue.c | 2 +- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/include/asm/xor_avx.h | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c index d84456924563..c37f7028c85a 100644 --- a/arch/x86/crypto/camellia_aesni_avx2_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c @@ -562,7 +562,8 @@ static int __init camellia_aesni_init(void) { const char *feature_name; - if (!cpu_has_avx2 || !cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) { + if (!cpu_has_avx2 || !cpu_has_avx || !cpu_has_aes || + !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX2 or AES-NI instructions are not detected.\n"); return -ENODEV; } diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c index 93d8f295784e..65f64556725b 100644 --- a/arch/x86/crypto/camellia_aesni_avx_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx_glue.c @@ -554,7 +554,7 @@ static int __init camellia_aesni_init(void) { const char *feature_name; - if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) { + if (!cpu_has_avx || !cpu_has_aes || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX or AES-NI instructions are not detected.\n"); return -ENODEV; } diff --git a/arch/x86/crypto/serpent_avx2_glue.c b/arch/x86/crypto/serpent_avx2_glue.c index 6d198342e2de..408cae2b3543 100644 --- a/arch/x86/crypto/serpent_avx2_glue.c +++ b/arch/x86/crypto/serpent_avx2_glue.c @@ -538,7 +538,7 @@ static int __init init(void) { const char *feature_name; - if (!cpu_has_avx2 || !cpu_has_osxsave) { + if (!cpu_has_avx2 || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX2 instructions are not detected.\n"); return -ENODEV; } diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3aea54ecabfd..33c29aabc9aa 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -135,7 +135,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) -#define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) /* * Do not add any more of those clumsy macros - use static_cpu_has() for * fast paths and boot_cpu_has() otherwise! diff --git a/arch/x86/include/asm/xor_avx.h b/arch/x86/include/asm/xor_avx.h index 7c0a517ec751..e45e556140af 100644 --- a/arch/x86/include/asm/xor_avx.h +++ b/arch/x86/include/asm/xor_avx.h @@ -167,12 +167,12 @@ static struct xor_block_template xor_block_avx = { #define AVX_XOR_SPEED \ do { \ - if (cpu_has_avx && cpu_has_osxsave) \ + if (cpu_has_avx && boot_cpu_has(X86_FEATURE_OSXSAVE)) \ xor_speed(&xor_block_avx); \ } while (0) #define AVX_SELECT(FASTEST) \ - (cpu_has_avx && cpu_has_osxsave ? &xor_block_avx : FASTEST) + (cpu_has_avx && boot_cpu_has(X86_FEATURE_OSXSAVE) ? &xor_block_avx : FASTEST) #else -- GitLab From 62436a4d36c94d202784cd8a997ff8bb4b880237 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:41:57 +0200 Subject: [PATCH 0965/9938] x86/cpufeature: Remove cpu_has_x2apic Signed-off-by: Borislav Petkov Acked-by: Tony Luck Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459266123-21878-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/ia64/include/asm/iommu.h | 1 - arch/x86/include/asm/apic.h | 4 ++-- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kernel/apic/apic.c | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h index 105c93b00b1b..1d1212901ae7 100644 --- a/arch/ia64/include/asm/iommu.h +++ b/arch/ia64/include/asm/iommu.h @@ -1,7 +1,6 @@ #ifndef _ASM_IA64_IOMMU_H #define _ASM_IA64_IOMMU_H 1 -#define cpu_has_x2apic 0 /* 10 seconds */ #define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 98f25bbafac4..bc27611fa58f 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -239,10 +239,10 @@ extern void __init check_x2apic(void); extern void x2apic_setup(void); static inline int x2apic_enabled(void) { - return cpu_has_x2apic && apic_is_x2apic_enabled(); + return boot_cpu_has(X86_FEATURE_X2APIC) && apic_is_x2apic_enabled(); } -#define x2apic_supported() (cpu_has_x2apic) +#define x2apic_supported() (boot_cpu_has(X86_FEATURE_X2APIC)) #else /* !CONFIG_X86_X2APIC */ static inline void check_x2apic(void) { } static inline void x2apic_setup(void) { } diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 33c29aabc9aa..3da7aec9fca1 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -132,7 +132,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLUSH) #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) -#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) /* diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index d356987a04e9..d7867c885bf8 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1561,7 +1561,7 @@ void __init check_x2apic(void) pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n"); x2apic_mode = 1; x2apic_state = X2APIC_ON; - } else if (!cpu_has_x2apic) { + } else if (!boot_cpu_has(X86_FEATURE_X2APIC)) { x2apic_state = X2APIC_DISABLED; } } -- GitLab From b8291adc191abec2095f03a130ac91506d345cae Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:41:58 +0200 Subject: [PATCH 0966/9938] x86/cpufeature: Remove cpu_has_gbpages Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459266123-21878-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kvm/mmu.c | 3 ++- arch/x86/mm/hugetlbpage.c | 4 ++-- arch/x86/mm/init.c | 2 +- arch/x86/mm/ioremap.c | 2 +- arch/x86/mm/pageattr.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3da7aec9fca1..693b4aa43908 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -130,7 +130,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) #define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2) #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLUSH) -#define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 70e95d097ef1..bc1e0b65909e 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3836,7 +3836,8 @@ reset_tdp_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check, boot_cpu_data.x86_phys_bits, context->shadow_root_level, false, - cpu_has_gbpages, true, true); + boot_cpu_has(X86_FEATURE_GBPAGES), + true, true); else __reset_rsvds_bits_mask_ept(&context->shadow_zero_check, boot_cpu_data.x86_phys_bits, diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 740d7ac03a55..14a95054d4e0 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -162,7 +162,7 @@ static __init int setup_hugepagesz(char *opt) unsigned long ps = memparse(opt, &opt); if (ps == PMD_SIZE) { hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT); - } else if (ps == PUD_SIZE && cpu_has_gbpages) { + } else if (ps == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES)) { hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); } else { printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n", @@ -177,7 +177,7 @@ __setup("hugepagesz=", setup_hugepagesz); static __init int gigantic_pages_init(void) { /* With compaction or CMA we can allocate gigantic pages at runtime */ - if (cpu_has_gbpages && !size_to_hstate(1UL << PUD_SHIFT)) + if (boot_cpu_has(X86_FEATURE_GBPAGES) && !size_to_hstate(1UL << PUD_SHIFT)) hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); return 0; } diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 9d56f271d519..14377e98f279 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -173,7 +173,7 @@ static void __init probe_page_size_mask(void) __supported_pte_mask &= ~_PAGE_GLOBAL; /* Enable 1 GB linear kernel mappings if available: */ - if (direct_gbpages && cpu_has_gbpages) { + if (direct_gbpages && boot_cpu_has(X86_FEATURE_GBPAGES)) { printk(KERN_INFO "Using GB pages for direct mapping\n"); page_size_mask |= 1 << PG_LEVEL_1G; } else { diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 0d8d53d1f5cc..5a116ace9cbb 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -378,7 +378,7 @@ EXPORT_SYMBOL(iounmap); int __init arch_ioremap_pud_supported(void) { #ifdef CONFIG_X86_64 - return cpu_has_gbpages; + return boot_cpu_has(X86_FEATURE_GBPAGES); #else return 0; #endif diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 01be9ec3bf79..fb20c2ee0092 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -1055,7 +1055,7 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd, /* * Map everything starting from the Gb boundary, possibly with 1G pages */ - while (cpu_has_gbpages && end - start >= PUD_SIZE) { + while (boot_cpu_has(X86_FEATURE_GBPAGES) && end - start >= PUD_SIZE) { set_pud(pud, __pud(cpa->pfn << PAGE_SHIFT | _PAGE_PSE | massage_pgprot(pud_pgprot))); -- GitLab From 906bf7fda2c9cf5c1762ec607943ed54b6c5b203 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:41:59 +0200 Subject: [PATCH 0967/9938] x86/cpufeature: Remove cpu_has_clflush Use the fast variant in the DRM code. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: dri-devel@lists.freedesktop.org Cc: intel-gfx@lists.freedesktop.org Link: http://lkml.kernel.org/r/1459266123-21878-7-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/tce_64.c | 2 +- arch/x86/mm/pageattr.c | 2 +- drivers/gpu/drm/drm_cache.c | 6 +++--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 693b4aa43908..a75154232db5 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -129,7 +129,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_aes boot_cpu_has(X86_FEATURE_AES) #define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) #define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2) -#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLUSH) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 1f7fdb91a818..628a9f853b84 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -468,7 +468,7 @@ static void init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_PEBS); } - if (c->x86 == 6 && cpu_has_clflush && + if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_CLFLUSH) && (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47)) set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR); diff --git a/arch/x86/kernel/tce_64.c b/arch/x86/kernel/tce_64.c index ab40954e113e..f386bad0984e 100644 --- a/arch/x86/kernel/tce_64.c +++ b/arch/x86/kernel/tce_64.c @@ -40,7 +40,7 @@ static inline void flush_tce(void* tceaddr) { /* a single tce can't cross a cache line */ - if (cpu_has_clflush) + if (boot_cpu_has(X86_FEATURE_CLFLUSH)) clflush(tceaddr); else wbinvd(); diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index fb20c2ee0092..bbf462ff9745 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -1460,7 +1460,7 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, * error case we fall back to cpa_flush_all (which uses * WBINVD): */ - if (!ret && cpu_has_clflush) { + if (!ret && boot_cpu_has(X86_FEATURE_CLFLUSH)) { if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { cpa_flush_array(addr, numpages, cache, cpa.flags, pages); diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index 6743ff7dccfa..059f7c39c582 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -72,7 +72,7 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages) { #if defined(CONFIG_X86) - if (cpu_has_clflush) { + if (static_cpu_has(X86_FEATURE_CLFLUSH)) { drm_cache_flush_clflush(pages, num_pages); return; } @@ -105,7 +105,7 @@ void drm_clflush_sg(struct sg_table *st) { #if defined(CONFIG_X86) - if (cpu_has_clflush) { + if (static_cpu_has(X86_FEATURE_CLFLUSH)) { struct sg_page_iter sg_iter; mb(); @@ -129,7 +129,7 @@ void drm_clflush_virt_range(void *addr, unsigned long length) { #if defined(CONFIG_X86) - if (cpu_has_clflush) { + if (static_cpu_has(X86_FEATURE_CLFLUSH)) { const int size = boot_cpu_data.x86_clflush_size; void *end = addr + length; addr = (void *)(((unsigned long)addr) & -size); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 1328bc5021b4..b845f468dd74 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -488,7 +488,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, ret = relocate_entry_cpu(obj, reloc, target_offset); else if (obj->map_and_fenceable) ret = relocate_entry_gtt(obj, reloc, target_offset); - else if (cpu_has_clflush) + else if (static_cpu_has(X86_FEATURE_CLFLUSH)) ret = relocate_entry_clflush(obj, reloc, target_offset); else { WARN_ONCE(1, "Impossible case in relocation handling\n"); -- GitLab From 054efb6467f84490bdf92afab6d9dbd5102e620a Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:42:00 +0200 Subject: [PATCH 0968/9938] x86/cpufeature: Remove cpu_has_xmm2 Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-crypto@vger.kernel.org Link: http://lkml.kernel.org/r/1459266123-21878-8-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/crypto/poly1305_glue.c | 2 +- arch/x86/crypto/serpent_sse2_glue.c | 2 +- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kernel/cpu/amd.c | 2 +- arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/lib/usercopy_32.c | 4 ++-- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c index 4264a3d59589..b283868acdf8 100644 --- a/arch/x86/crypto/poly1305_glue.c +++ b/arch/x86/crypto/poly1305_glue.c @@ -179,7 +179,7 @@ static struct shash_alg alg = { static int __init poly1305_simd_mod_init(void) { - if (!cpu_has_xmm2) + if (!boot_cpu_has(X86_FEATURE_XMM2)) return -ENODEV; #ifdef CONFIG_AS_AVX2 diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 8943407e8917..644f97ab8cac 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c @@ -600,7 +600,7 @@ static struct crypto_alg serpent_algs[10] = { { static int __init serpent_sse2_init(void) { - if (!cpu_has_xmm2) { + if (!boot_cpu_has(X86_FEATURE_XMM2)) { printk(KERN_INFO "SSE2 instructions are not detected.\n"); return -ENODEV; } diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index a75154232db5..5e02bc2e8444 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -125,7 +125,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) -#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2) #define cpu_has_aes boot_cpu_has(X86_FEATURE_AES) #define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) #define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 6e47e3a916f1..ea8f88a2a688 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -750,7 +750,7 @@ static void init_amd(struct cpuinfo_x86 *c) if (c->x86 >= 0xf) set_cpu_cap(c, X86_FEATURE_K8); - if (cpu_has_xmm2) { + if (cpu_has(c, X86_FEATURE_XMM2)) { /* MFENCE stops RDTSC speculation */ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); } diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 628a9f853b84..1dba36fe73e5 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -456,7 +456,7 @@ static void init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); } - if (cpu_has_xmm2) + if (cpu_has(c, X86_FEATURE_XMM2)) set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); if (boot_cpu_has(X86_FEATURE_DS)) { diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 91d93b95bd86..b559d9238781 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -612,7 +612,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from, { stac(); #ifdef CONFIG_X86_INTEL_USERCOPY - if (n > 64 && cpu_has_xmm2) + if (n > 64 && static_cpu_has(X86_FEATURE_XMM2)) n = __copy_user_zeroing_intel_nocache(to, from, n); else __copy_user_zeroing(to, from, n); @@ -629,7 +629,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr { stac(); #ifdef CONFIG_X86_INTEL_USERCOPY - if (n > 64 && cpu_has_xmm2) + if (n > 64 && static_cpu_has(X86_FEATURE_XMM2)) n = __copy_user_intel_nocache(to, from, n); else __copy_user(to, from, n); -- GitLab From c109bf95992b391bb40bc37c5d309d13fead99b5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:42:02 +0200 Subject: [PATCH 0969/9938] x86/cpufeature: Remove cpu_has_pge Use static_cpu_has() in __flush_tlb_all() due to the time-sensitivity of this one. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459266123-21878-10-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/include/asm/tlbflush.h | 2 +- arch/x86/kernel/cpu/intel.c | 6 +++--- arch/x86/kernel/cpu/mtrr/cyrix.c | 4 ++-- arch/x86/kernel/cpu/mtrr/generic.c | 4 ++-- arch/x86/mm/init.c | 2 +- arch/x86/xen/enlighten.c | 2 +- drivers/lguest/x86/core.c | 2 +- 8 files changed, 11 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 5e02bc2e8444..f97b53417d44 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -121,7 +121,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU) #define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) #define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) -#define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index c24b4224d439..3628e6c5ebf4 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -181,7 +181,7 @@ static inline void __native_flush_tlb_single(unsigned long addr) static inline void __flush_tlb_all(void) { - if (cpu_has_pge) + if (static_cpu_has(X86_FEATURE_PGE)) __flush_tlb_global(); else __flush_tlb(); diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 1dba36fe73e5..f71a34944b56 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -152,9 +152,9 @@ static void early_init_intel(struct cpuinfo_x86 *c) * the TLB when any changes are made to any of the page table entries. * The operating system must reload CR3 to cause the TLB to be flushed" * - * As a result cpu_has_pge() in arch/x86/include/asm/tlbflush.h should - * be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE - * to be modified + * As a result, boot_cpu_has(X86_FEATURE_PGE) in arch/x86/include/asm/tlbflush.h + * should be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE + * to be modified. */ if (c->x86 == 5 && c->x86_model == 9) { pr_info("Disabling PGE capability bit\n"); diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index f8c81ba0b465..b1086f79e57e 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c @@ -137,7 +137,7 @@ static void prepare_set(void) u32 cr0; /* Save value of CR4 and clear Page Global Enable (bit 7) */ - if (cpu_has_pge) { + if (boot_cpu_has(X86_FEATURE_PGE)) { cr4 = __read_cr4(); __write_cr4(cr4 & ~X86_CR4_PGE); } @@ -170,7 +170,7 @@ static void post_set(void) write_cr0(read_cr0() & ~X86_CR0_CD); /* Restore value of CR4 */ - if (cpu_has_pge) + if (boot_cpu_has(X86_FEATURE_PGE)) __write_cr4(cr4); } diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 19f57360dfd2..f1bed301bdb2 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -741,7 +741,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) wbinvd(); /* Save value of CR4 and clear Page Global Enable (bit 7) */ - if (cpu_has_pge) { + if (boot_cpu_has(X86_FEATURE_PGE)) { cr4 = __read_cr4(); __write_cr4(cr4 & ~X86_CR4_PGE); } @@ -771,7 +771,7 @@ static void post_set(void) __releases(set_atomicity_lock) write_cr0(read_cr0() & ~X86_CR0_CD); /* Restore value of CR4 */ - if (cpu_has_pge) + if (boot_cpu_has(X86_FEATURE_PGE)) __write_cr4(cr4); raw_spin_unlock(&set_atomicity_lock); } diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 14377e98f279..05ff46a9c261 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -166,7 +166,7 @@ static void __init probe_page_size_mask(void) cr4_set_bits_and_update_boot(X86_CR4_PSE); /* Enable PGE if available */ - if (cpu_has_pge) { + if (boot_cpu_has(X86_FEATURE_PGE)) { cr4_set_bits_and_update_boot(X86_CR4_PGE); __supported_pte_mask |= _PAGE_GLOBAL; } else diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 880862c7d9dd..055f48ddb03c 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1472,7 +1472,7 @@ static void xen_pvh_set_cr_flags(int cpu) if (cpu_has_pse) cr4_set_bits_and_update_boot(X86_CR4_PSE); - if (cpu_has_pge) + if (boot_cpu_has(X86_FEATURE_PGE)) cr4_set_bits_and_update_boot(X86_CR4_PGE); } diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 6a4cd771a2be..65f22debf3c6 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -599,7 +599,7 @@ void __init lguest_arch_host_init(void) * doing this. */ get_online_cpus(); - if (cpu_has_pge) { /* We have a broader idea of "global". */ + if (boot_cpu_has(X86_FEATURE_PGE)) { /* We have a broader idea of "global". */ /* Remember that this was originally set (for cleanup). */ cpu_had_pge = 1; /* -- GitLab From 16bf92261b1b6cb1a1c0671b445a2fcb5a1ecc96 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 29 Mar 2016 17:42:03 +0200 Subject: [PATCH 0970/9938] x86/cpufeature: Remove cpu_has_pse Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459266123-21878-11-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/include/asm/pgtable.h | 2 +- arch/x86/mm/init.c | 4 ++-- arch/x86/mm/init_32.c | 2 +- arch/x86/mm/init_64.c | 4 ++-- arch/x86/mm/ioremap.c | 2 +- arch/x86/power/hibernate_32.c | 2 +- arch/x86/xen/enlighten.c | 2 +- 8 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index f97b53417d44..97e5f13ea471 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -119,7 +119,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; } while (0) #define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU) -#define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) #define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 97f3242e133c..f86491a7bc9d 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -183,7 +183,7 @@ static inline int pmd_trans_huge(pmd_t pmd) static inline int has_transparent_hugepage(void) { - return cpu_has_pse; + return boot_cpu_has(X86_FEATURE_PSE); } #ifdef __HAVE_ARCH_PTE_DEVMAP diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 05ff46a9c261..372aad2b3291 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -157,12 +157,12 @@ static void __init probe_page_size_mask(void) * This will simplify cpa(), which otherwise needs to support splitting * large pages into small in interrupt context, etc. */ - if (cpu_has_pse && !debug_pagealloc_enabled()) + if (boot_cpu_has(X86_FEATURE_PSE) && !debug_pagealloc_enabled()) page_size_mask |= 1 << PG_LEVEL_2M; #endif /* Enable PSE if available */ - if (cpu_has_pse) + if (boot_cpu_has(X86_FEATURE_PSE)) cr4_set_bits_and_update_boot(X86_CR4_PSE); /* Enable PGE if available */ diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index bd7a9b9e2e14..85af914e3d27 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -284,7 +284,7 @@ kernel_physical_mapping_init(unsigned long start, */ mapping_iter = 1; - if (!cpu_has_pse) + if (!boot_cpu_has(X86_FEATURE_PSE)) use_pse = 0; repeat: diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 214afda97911..89d97477c1d9 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -1295,7 +1295,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node) struct vmem_altmap *altmap = to_vmem_altmap(start); int err; - if (cpu_has_pse) + if (boot_cpu_has(X86_FEATURE_PSE)) err = vmemmap_populate_hugepages(start, end, node, altmap); else if (altmap) { pr_err_once("%s: no cpu support for altmap allocations\n", @@ -1338,7 +1338,7 @@ void register_page_bootmem_memmap(unsigned long section_nr, } get_page_bootmem(section_nr, pud_page(*pud), MIX_SECTION_INFO); - if (!cpu_has_pse) { + if (!boot_cpu_has(X86_FEATURE_PSE)) { next = (addr + PAGE_SIZE) & PAGE_MASK; pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 5a116ace9cbb..f0894910bdd7 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -386,7 +386,7 @@ int __init arch_ioremap_pud_supported(void) int __init arch_ioremap_pmd_supported(void) { - return cpu_has_pse; + return boot_cpu_has(X86_FEATURE_PSE); } /* diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c index 291226b952a9..9f14bd34581d 100644 --- a/arch/x86/power/hibernate_32.c +++ b/arch/x86/power/hibernate_32.c @@ -106,7 +106,7 @@ static int resume_physical_mapping_init(pgd_t *pgd_base) * normal page tables. * NOTE: We can mark everything as executable here */ - if (cpu_has_pse) { + if (boot_cpu_has(X86_FEATURE_PSE)) { set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC)); pfn += PTRS_PER_PTE; } else { diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 055f48ddb03c..ff2a2e6ef7af 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1469,7 +1469,7 @@ static void xen_pvh_set_cr_flags(int cpu) * For BSP, PSE PGE are set in probe_page_size_mask(), for APs * set them here. For all, OSFXSR OSXMMEXCPT are set in fpu__init_cpu(). */ - if (cpu_has_pse) + if (boot_cpu_has(X86_FEATURE_PSE)) cr4_set_bits_and_update_boot(X86_CR4_PSE); if (boot_cpu_has(X86_FEATURE_PGE)) -- GitLab From d5610e514e92144d19bd5e39e5cf3804bbf85f3e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:42 -0400 Subject: [PATCH 0971/9938] gpio: mb86s7x: make explicitly non-modular The Kconfig for this driver is currently: config GPIO_MB86S7X bool "GPIO support for Fujitsu MB86S7x Platforms" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mb86s7x.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index d23a94231a20..d55af50e7034 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -208,7 +207,6 @@ static const struct of_device_id mb86s70_gpio_dt_ids[] = { { .compatible = "fujitsu,mb86s70-gpio" }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids); static struct platform_driver mb86s70_gpio_driver = { .driver = { @@ -223,8 +221,4 @@ static int __init mb86s70_gpio_init(void) { return platform_driver_register(&mb86s70_gpio_driver); } -module_init(mb86s70_gpio_init); - -MODULE_DESCRIPTION("MB86S7x GPIO Driver"); -MODULE_ALIAS("platform:mb86s70-gpio"); -MODULE_LICENSE("GPL"); +device_initcall(mb86s70_gpio_init); -- GitLab From 0de6a80de1425905f9fe8f3df8c455ec56250107 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:43 -0400 Subject: [PATCH 0972/9938] gpio: mc9s08dz60: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_MC9S08DZ60 drivers/gpio/Kconfig: bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_i2c_driver() uses the same init level priority as builtin_i2c_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: Wu Guoxing Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mc9s08dz60.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c index 14f252f9eb29..2fcad5b9cca5 100644 --- a/drivers/gpio/gpio-mc9s08dz60.c +++ b/drivers/gpio/gpio-mc9s08dz60.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include #include @@ -111,8 +111,6 @@ static const struct i2c_device_id mc9s08dz60_id[] = { {}, }; -MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id); - static struct i2c_driver mc9s08dz60_i2c_driver = { .driver = { .name = "mc9s08dz60", @@ -120,10 +118,4 @@ static struct i2c_driver mc9s08dz60_i2c_driver = { .probe = mc9s08dz60_probe, .id_table = mc9s08dz60_id, }; - -module_i2c_driver(mc9s08dz60_i2c_driver); - -MODULE_AUTHOR("Freescale Semiconductor, Inc. " - "Wu Guoxing "); -MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board"); -MODULE_LICENSE("GPL v2"); +builtin_i2c_driver(mc9s08dz60_i2c_driver); -- GitLab From 4bb9f7251cf2c922e46a9059dc4d70028469275a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:44 -0400 Subject: [PATCH 0973/9938] gpio: moxart: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_MOXART drivers/gpio/Kconfig: bool "MOXART GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modular references so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. We don't replace module.h with init.h since the file already has that. Cc: Jonas Jensen Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-moxart.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c index f02d0b490978..d58d38906ba6 100644 --- a/drivers/gpio/gpio-moxart.c +++ b/drivers/gpio/gpio-moxart.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -82,8 +81,4 @@ static struct platform_driver moxart_gpio_driver = { }, .probe = moxart_gpio_probe, }; -module_platform_driver(moxart_gpio_driver); - -MODULE_DESCRIPTION("MOXART GPIO chip driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jonas Jensen "); +builtin_platform_driver(moxart_gpio_driver); -- GitLab From ed329f3a6483ad4825be2f731aa08b34731ecfcb Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:45 -0400 Subject: [PATCH 0974/9938] gpio: mvebu: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_MVEBU drivers/gpio/Kconfig: def_bool y ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 11c6582ef0a6..cd5dc27320a2 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -34,7 +34,7 @@ */ #include -#include +#include #include #include #include @@ -557,7 +557,6 @@ static const struct of_device_id mvebu_gpio_of_match[] = { /* sentinel */ }, }; -MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match); static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state) { @@ -838,4 +837,4 @@ static struct platform_driver mvebu_gpio_driver = { .suspend = mvebu_gpio_suspend, .resume = mvebu_gpio_resume, }; -module_platform_driver(mvebu_gpio_driver); +builtin_platform_driver(mvebu_gpio_driver); -- GitLab From ef3e7100e06a8788d89555e0a4926ab85f689583 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:46 -0400 Subject: [PATCH 0975/9938] gpio: pl061: make explicitly non-modular The Kconfig for this driver is currently: config GPIO_PL061 bool "PrimeCell PL061 GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Acked-by: Baruch Siach Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pl061.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 5cb38212bbc0..9afb415a5d24 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -1,6 +1,8 @@ /* * Copyright (C) 2008, 2009 Provigent Ltd. * + * Author: Baruch Siach + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -11,7 +13,7 @@ */ #include #include -#include +#include #include #include #include @@ -429,8 +431,6 @@ static struct amba_id pl061_ids[] = { { 0, 0 }, }; -MODULE_DEVICE_TABLE(amba, pl061_ids); - static struct amba_driver pl061_gpio_driver = { .drv = { .name = "pl061_gpio", @@ -446,8 +446,4 @@ static int __init pl061_gpio_init(void) { return amba_driver_register(&pl061_gpio_driver); } -module_init(pl061_gpio_init); - -MODULE_AUTHOR("Baruch Siach "); -MODULE_DESCRIPTION("PL061 GPIO driver"); -MODULE_LICENSE("GPL"); +device_initcall(pl061_gpio_init); -- GitLab From 3c90c6d60b4184cd08bc2b8c1db0b507c3a1c84e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:47 -0400 Subject: [PATCH 0976/9938] gpio: sta2x11: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_STA2X11 drivers/gpio/Kconfig: bool "STA2x11/ConneXt GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sta2x11.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 0d5b8c525dd9..853ca23cad88 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -20,7 +20,7 @@ * */ -#include +#include #include #include #include @@ -432,8 +432,4 @@ static struct platform_driver sta2x11_gpio_platform_driver = { }, .probe = gsta_probe, }; - -module_platform_driver(sta2x11_gpio_platform_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("sta2x11_gpio GPIO driver"); +builtin_platform_driver(sta2x11_gpio_platform_driver); -- GitLab From b33d12d3d72df3272c9c017cd93577ba1c9b24bb Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:48 -0400 Subject: [PATCH 0977/9938] gpio: xgene: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_XGENE drivers/gpio/Kconfig: bool "APM X-Gene GPIO controller support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Feng Kan Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xgene.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index c0aa387664bf..4193502fe3be 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -17,7 +17,6 @@ * along with this program. If not, see . */ -#include #include #include #include @@ -211,7 +210,6 @@ static const struct of_device_id xgene_gpio_of_match[] = { { .compatible = "apm,xgene-gpio", }, {}, }; -MODULE_DEVICE_TABLE(of, xgene_gpio_of_match); static struct platform_driver xgene_gpio_driver = { .driver = { @@ -221,9 +219,4 @@ static struct platform_driver xgene_gpio_driver = { }, .probe = xgene_gpio_probe, }; - -module_platform_driver(xgene_gpio_driver); - -MODULE_AUTHOR("Feng Kan "); -MODULE_DESCRIPTION("APM X-Gene GPIO driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(xgene_gpio_driver); -- GitLab From 18fb0a981e18b91c6eb1a00f8b06f2fb5be2e9aa Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 11:44:49 -0400 Subject: [PATCH 0978/9938] gpio: zx: make explicitly non-modular The Kconfig currently controlling compilation of this code is: config GPIO_ZX bool "ZTE ZX GPIO support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: Jun Nie Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zx.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 47c79fa65670..93de8be0d885 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -1,4 +1,8 @@ /* + * ZTE ZX296702 GPIO driver + * + * Author: Jun Nie + * * Copyright (C) 2015 Linaro Ltd. * * This program is free software; you can redistribute it and/or modify @@ -10,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -282,7 +286,6 @@ static const struct of_device_id zx_gpio_match[] = { }, { }, }; -MODULE_DEVICE_TABLE(of, zx_gpio_match); static struct platform_driver zx_gpio_driver = { .probe = zx_gpio_probe, @@ -291,9 +294,4 @@ static struct platform_driver zx_gpio_driver = { .of_match_table = of_match_ptr(zx_gpio_match), }, }; - -module_platform_driver(zx_gpio_driver) - -MODULE_AUTHOR("Jun Nie "); -MODULE_DESCRIPTION("ZTE ZX296702 GPIO driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(zx_gpio_driver) -- GitLab From 6e66a6599a813abfc9ebe2e295c9d557c434812a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 23 Mar 2016 19:49:41 +0800 Subject: [PATCH 0979/9938] gpio: tpic2810: Make sure cached buffer has consistent status with h/w status i2c_smbus_write_byte_data() can fail. To ensure the cached buffer has consistent status with h/w status, don't update the cached gpio->buffer if write fails. Also refactor the code a bit by adding a tpic2810_set_mask_bits() helper and use it to simplify the code. Signed-off-by: Axel Lin Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tpic2810.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/drivers/gpio/gpio-tpic2810.c b/drivers/gpio/gpio-tpic2810.c index 9f020aa4b067..cace79c1b70a 100644 --- a/drivers/gpio/gpio-tpic2810.c +++ b/drivers/gpio/gpio-tpic2810.c @@ -57,39 +57,34 @@ static int tpic2810_direction_output(struct gpio_chip *chip, return 0; } -static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value) +static void tpic2810_set_mask_bits(struct gpio_chip *chip, u8 mask, u8 bits) { struct tpic2810 *gpio = gpiochip_get_data(chip); + u8 buffer; + int err; mutex_lock(&gpio->lock); - if (value) - gpio->buffer |= BIT(offset); - else - gpio->buffer &= ~BIT(offset); + buffer = gpio->buffer & ~mask; + buffer |= (mask & bits); - i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, - gpio->buffer); + err = i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, + buffer); + if (!err) + gpio->buffer = buffer; mutex_unlock(&gpio->lock); } +static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value) +{ + tpic2810_set_mask_bits(chip, BIT(offset), value ? BIT(offset) : 0); +} + static void tpic2810_set_multiple(struct gpio_chip *chip, unsigned long *mask, unsigned long *bits) { - struct tpic2810 *gpio = gpiochip_get_data(chip); - - mutex_lock(&gpio->lock); - - /* clear bits under mask */ - gpio->buffer &= ~(*mask); - /* set bits under mask */ - gpio->buffer |= ((*mask) & (*bits)); - - i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, - gpio->buffer); - - mutex_unlock(&gpio->lock); + tpic2810_set_mask_bits(chip, *mask, *bits); } static struct gpio_chip template_chip = { -- GitLab From 8fad7ec51e1b9e262e0bdd34e800ac1ea5e84dec Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Sat, 26 Mar 2016 21:40:16 +0100 Subject: [PATCH 0980/9938] x86/dumpstack: Combine some printk()s Long ago, Jiri Slaby noted that the subsequent printk()s should be pr_cont(). Let's instead get rid of the multiple printk calls. Signed-off-by: Rasmus Villemoes Cc: Jiri Slaby Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459024817-27122-1-git-send-email-linux@rasmusvillemoes.dk Signed-off-by: Ingo Molnar --- arch/x86/kernel/dumpstack.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 8efa57a5f29e..2bb25c3fe2e8 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -260,19 +260,12 @@ int __die(const char *str, struct pt_regs *regs, long err) unsigned long sp; #endif printk(KERN_DEFAULT - "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); -#ifdef CONFIG_PREEMPT - printk("PREEMPT "); -#endif -#ifdef CONFIG_SMP - printk("SMP "); -#endif - if (debug_pagealloc_enabled()) - printk("DEBUG_PAGEALLOC "); -#ifdef CONFIG_KASAN - printk("KASAN"); -#endif - printk("\n"); + "%s: %04lx [#%d]%s%s%s%s\n", str, err & 0xffff, ++die_counter, + IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "", + IS_ENABLED(CONFIG_SMP) ? " SMP" : "", + debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "", + IS_ENABLED(CONFIG_KASAN) ? " KASAN" : ""); + if (notify_die(DIE_OOPS, str, regs, err, current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP) return 1; -- GitLab From e787bc463cc1fe3f51b0cd7bf540236318f69cf1 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Thu, 31 Mar 2016 16:30:15 +0300 Subject: [PATCH 0981/9938] MAINTAINERS: Add a git tree for the stm class So that people know where their patches go. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..4b511b25d179 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9742,6 +9742,7 @@ F: drivers/mmc/host/dw_mmc* SYSTEM TRACE MODULE CLASS M: Alexander Shishkin S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ash/stm.git F: Documentation/trace/stm.txt F: drivers/hwtracing/stm/ F: include/linux/stm.h -- GitLab From 44c376b9596ca00d1bdee37e716d1bd4dd36c955 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:02 +0900 Subject: [PATCH 0982/9938] ALSA: firewire-lib: suppress kernel warnings when releasing uninitialized stream data When any of AMDTP stream data are not initialized and private data is going to be released, WARN_ON() in amdtp_stream_destroy() is hit and dump messages. This may take users irritated. This commit fixes the bug to skip releasing when it's not initialized. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/amdtp-stream.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index ed2902609a4c..4484242da0e6 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -102,6 +102,10 @@ EXPORT_SYMBOL(amdtp_stream_init); */ void amdtp_stream_destroy(struct amdtp_stream *s) { + /* Not initialized. */ + if (s->protocol == NULL) + return; + WARN_ON(amdtp_stream_running(s)); kfree(s->protocol); mutex_destroy(&s->mutex); -- GitLab From 0eced45ca60666aff4c12f31fef4005ae37e859e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:03 +0900 Subject: [PATCH 0983/9938] ALSA: dice: simplify unit probe processing In former commit, ALSA dice driver doesn't generate kernel warnings when unplugging units before initializing stream data. This commit moves the initialization to delayed registration of sound card, to simplify unit probe processing. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 8b64aef31a86..53ca441ea9b9 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -201,6 +201,10 @@ static void do_registration(struct work_struct *work) dice_card_strings(dice); + err = snd_dice_stream_init_duplex(dice); + if (err < 0) + goto error; + snd_dice_create_proc(dice); err = snd_dice_create_pcm(dice); @@ -229,6 +233,7 @@ static void do_registration(struct work_struct *work) return; error: + snd_dice_stream_destroy_duplex(dice); snd_dice_transaction_destroy(dice); snd_card_free(dice->card); dev_info(&dice->unit->device, @@ -273,12 +278,6 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) init_completion(&dice->clock_accepted); init_waitqueue_head(&dice->hwdep_wait); - err = snd_dice_stream_init_duplex(dice); - if (err < 0) { - dice_free(dice); - return err; - } - /* Allocate and register this sound card later. */ INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); schedule_registration(dice); -- GitLab From 923f92ebb43e7a09915a5708d4805c1e099db46c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:04 +0900 Subject: [PATCH 0984/9938] ALSA: firewire-lib: add new function to schedule a work for sound card registration In former commit, ALSA dice driver postpone sound card registration after IEEE 1394 bus is calm. This idea has advantages for the other drivers. This commit adds a helper function for it to firewire-lib module. The function is really for the specific purpose. Callers should initialize delayed work structure with callback function. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice.c | 23 +++-------------------- sound/firewire/lib.c | 32 ++++++++++++++++++++++++++++++++ sound/firewire/lib.h | 3 +++ 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 53ca441ea9b9..96fe68f42e5d 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -20,8 +20,6 @@ MODULE_LICENSE("GPL v2"); #define WEISS_CATEGORY_ID 0x00 #define LOUD_CATEGORY_ID 0x10 -#define PROBE_DELAY_MS (2 * MSEC_PER_SEC) - /* * Some models support several isochronous channels, while these streams are not * always available. In this case, add the model name to this list. @@ -235,27 +233,12 @@ static void do_registration(struct work_struct *work) error: snd_dice_stream_destroy_duplex(dice); snd_dice_transaction_destroy(dice); + snd_dice_stream_destroy_duplex(dice); snd_card_free(dice->card); dev_info(&dice->unit->device, "Sound card registration failed: %d\n", err); } -static void schedule_registration(struct snd_dice *dice) -{ - struct fw_card *fw_card = fw_parent_device(dice->unit)->card; - u64 now, delay; - - now = get_jiffies_64(); - delay = fw_card->reset_jiffies + msecs_to_jiffies(PROBE_DELAY_MS); - - if (time_after64(delay, now)) - delay -= now; - else - delay = 0; - - mod_delayed_work(system_wq, &dice->dwork, delay); -} - static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) { struct snd_dice *dice; @@ -280,7 +263,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) /* Allocate and register this sound card later. */ INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); - schedule_registration(dice); + snd_fw_schedule_registration(unit, &dice->dwork); return 0; } @@ -311,7 +294,7 @@ static void dice_bus_reset(struct fw_unit *unit) /* Postpone a workqueue for deferred registration. */ if (!dice->registered) - schedule_registration(dice); + snd_fw_schedule_registration(unit, &dice->dwork); /* The handler address register becomes initialized. */ snd_dice_transaction_reinit(dice); diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c index f80aafa44c89..ca4dfcf43175 100644 --- a/sound/firewire/lib.c +++ b/sound/firewire/lib.c @@ -67,6 +67,38 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode, } EXPORT_SYMBOL(snd_fw_transaction); +#define PROBE_DELAY_MS (2 * MSEC_PER_SEC) + +/** + * snd_fw_schedule_registration - schedule work for sound card registration + * @unit: an instance for unit on IEEE 1394 bus + * @dwork: delayed work with callback function + * + * This function is not designed for general purposes. When new unit is + * connected to IEEE 1394 bus, the bus is under bus-reset state because of + * topological change. In this state, units tend to fail both of asynchronous + * and isochronous communication. To avoid this problem, this function is used + * to postpone sound card registration after the state. The callers must + * set up instance of delayed work in advance. + */ +void snd_fw_schedule_registration(struct fw_unit *unit, + struct delayed_work *dwork) +{ + u64 now, delay; + + now = get_jiffies_64(); + delay = fw_parent_device(unit)->card->reset_jiffies + + msecs_to_jiffies(PROBE_DELAY_MS); + + if (time_after64(delay, now)) + delay -= now; + else + delay = 0; + + mod_delayed_work(system_wq, dwork, delay); +} +EXPORT_SYMBOL(snd_fw_schedule_registration); + static void async_midi_port_callback(struct fw_card *card, int rcode, void *data, size_t length, void *callback_data) diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h index f3f6f84c48d6..f6769312ebfc 100644 --- a/sound/firewire/lib.h +++ b/sound/firewire/lib.h @@ -22,6 +22,9 @@ static inline bool rcode_is_permanent_error(int rcode) return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR; } +void snd_fw_schedule_registration(struct fw_unit *unit, + struct delayed_work *dwork); + struct snd_fw_async_midi_port; typedef int (*snd_fw_async_midi_port_fill)( struct snd_rawmidi_substream *substream, -- GitLab From 04a2c73c97ebb224dfb411ab35bb18d7b8245e39 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:05 +0900 Subject: [PATCH 0985/9938] ALSA: bebob: delayed registration of sound card Some bebob based units tends to fail asynchronous communication when IEEE 1394 bus is under bus-reset state. When registering sound card instance at unit probe callback, userspace applications can be involved to the state. This commit postpones the registration till the bus is calm. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.c | 215 +++++++++++++++++++++-------------- sound/firewire/bebob/bebob.h | 5 +- 2 files changed, 131 insertions(+), 89 deletions(-) diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 932901de255f..f7e2cbd2a313 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -126,6 +126,17 @@ name_device(struct snd_bebob *bebob) return err; } +static void bebob_free(struct snd_bebob *bebob) +{ + snd_bebob_stream_destroy_duplex(bebob); + fw_unit_put(bebob->unit); + + kfree(bebob->maudio_special_quirk); + + mutex_destroy(&bebob->mutex); + kfree(bebob); +} + /* * This module releases the FireWire unit data after all ALSA character devices * are released by applications. This is for releasing stream data or finishing @@ -137,18 +148,11 @@ bebob_card_free(struct snd_card *card) { struct snd_bebob *bebob = card->private_data; - snd_bebob_stream_destroy_duplex(bebob); - fw_unit_put(bebob->unit); - - kfree(bebob->maudio_special_quirk); - - if (bebob->card_index >= 0) { - mutex_lock(&devices_mutex); - clear_bit(bebob->card_index, devices_used); - mutex_unlock(&devices_mutex); - } + mutex_lock(&devices_mutex); + clear_bit(bebob->card_index, devices_used); + mutex_unlock(&devices_mutex); - mutex_destroy(&bebob->mutex); + bebob_free(card->private_data); } static const struct snd_bebob_spec * @@ -176,16 +180,17 @@ check_audiophile_booted(struct fw_unit *unit) return strncmp(name, "FW Audiophile Bootloader", 15) != 0; } -static int -bebob_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) +static void +do_registration(struct work_struct *work) { - struct snd_card *card; - struct snd_bebob *bebob; - const struct snd_bebob_spec *spec; + struct snd_bebob *bebob = + container_of(work, struct snd_bebob, dwork.work); unsigned int card_index; int err; + if (bebob->registered) + return; + mutex_lock(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { @@ -193,64 +198,39 @@ bebob_probe(struct fw_unit *unit, break; } if (card_index >= SNDRV_CARDS) { - err = -ENOENT; - goto end; + mutex_unlock(&devices_mutex); + return; } - if ((entry->vendor_id == VEN_FOCUSRITE) && - (entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)) - spec = get_saffire_spec(unit); - else if ((entry->vendor_id == VEN_MAUDIO1) && - (entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH) && - !check_audiophile_booted(unit)) - spec = NULL; - else - spec = (const struct snd_bebob_spec *)entry->driver_data; - - if (spec == NULL) { - if ((entry->vendor_id == VEN_MAUDIO1) || - (entry->vendor_id == VEN_MAUDIO2)) - err = snd_bebob_maudio_load_firmware(unit); - else - err = -ENOSYS; - goto end; + err = snd_card_new(&bebob->unit->device, index[card_index], + id[card_index], THIS_MODULE, 0, &bebob->card); + if (err < 0) { + mutex_unlock(&devices_mutex); + return; } - err = snd_card_new(&unit->device, index[card_index], id[card_index], - THIS_MODULE, sizeof(struct snd_bebob), &card); - if (err < 0) - goto end; - bebob = card->private_data; - bebob->card_index = card_index; - set_bit(card_index, devices_used); - card->private_free = bebob_card_free; - - bebob->card = card; - bebob->unit = fw_unit_get(unit); - bebob->spec = spec; - mutex_init(&bebob->mutex); - spin_lock_init(&bebob->lock); - init_waitqueue_head(&bebob->hwdep_wait); - err = name_device(bebob); if (err < 0) goto error; - if ((entry->vendor_id == VEN_MAUDIO1) && - (entry->model_id == MODEL_MAUDIO_FW1814)) - err = snd_bebob_maudio_special_discover(bebob, true); - else if ((entry->vendor_id == VEN_MAUDIO1) && - (entry->model_id == MODEL_MAUDIO_PROJECTMIX)) - err = snd_bebob_maudio_special_discover(bebob, false); - else + if (bebob->spec == &maudio_special_spec) { + if (bebob->entry->model_id == MODEL_MAUDIO_FW1814) + err = snd_bebob_maudio_special_discover(bebob, true); + else + err = snd_bebob_maudio_special_discover(bebob, false); + } else { err = snd_bebob_stream_discover(bebob); + } + if (err < 0) + goto error; + + err = snd_bebob_stream_init_duplex(bebob); if (err < 0) goto error; snd_bebob_proc_init(bebob); - if ((bebob->midi_input_ports > 0) || - (bebob->midi_output_ports > 0)) { + if (bebob->midi_input_ports > 0 || bebob->midi_output_ports > 0) { err = snd_bebob_create_midi_devices(bebob); if (err < 0) goto error; @@ -264,16 +244,75 @@ bebob_probe(struct fw_unit *unit, if (err < 0) goto error; - err = snd_bebob_stream_init_duplex(bebob); + err = snd_card_register(bebob->card); if (err < 0) goto error; - if (!bebob->maudio_special_quirk) { - err = snd_card_register(card); - if (err < 0) { - snd_bebob_stream_destroy_duplex(bebob); - goto error; - } + set_bit(card_index, devices_used); + mutex_unlock(&devices_mutex); + + /* + * After registered, bebob instance can be released corresponding to + * releasing the sound card instance. + */ + bebob->card->private_free = bebob_card_free; + bebob->card->private_data = bebob; + bebob->registered = true; + + return; +error: + mutex_unlock(&devices_mutex); + snd_bebob_stream_destroy_duplex(bebob); + snd_card_free(bebob->card); + dev_info(&bebob->unit->device, + "Sound card registration failed: %d\n", err); +} + +static int +bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) +{ + struct snd_bebob *bebob; + const struct snd_bebob_spec *spec; + + if (entry->vendor_id == VEN_FOCUSRITE && + entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH) + spec = get_saffire_spec(unit); + else if (entry->vendor_id == VEN_MAUDIO1 && + entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH && + !check_audiophile_booted(unit)) + spec = NULL; + else + spec = (const struct snd_bebob_spec *)entry->driver_data; + + if (spec == NULL) { + if (entry->vendor_id == VEN_MAUDIO1 || + entry->vendor_id == VEN_MAUDIO2) + return snd_bebob_maudio_load_firmware(unit); + else + return -ENODEV; + } + + /* Allocate this independent of sound card instance. */ + bebob = kzalloc(sizeof(struct snd_bebob), GFP_KERNEL); + if (bebob == NULL) + return -ENOMEM; + + bebob->unit = fw_unit_get(unit); + bebob->entry = entry; + bebob->spec = spec; + dev_set_drvdata(&unit->device, bebob); + + mutex_init(&bebob->mutex); + spin_lock_init(&bebob->lock); + init_waitqueue_head(&bebob->hwdep_wait); + + /* Allocate and register this sound card later. */ + INIT_DEFERRABLE_WORK(&bebob->dwork, do_registration); + + if (entry->vendor_id != VEN_MAUDIO1 || + (entry->model_id != MODEL_MAUDIO_FW1814 && + entry->model_id != MODEL_MAUDIO_PROJECTMIX)) { + snd_fw_schedule_registration(unit, &bebob->dwork); } else { /* * This is a workaround. This bus reset seems to have an effect @@ -285,19 +324,11 @@ bebob_probe(struct fw_unit *unit, * signals from dbus and starts I/Os. To avoid I/Os till the * future bus reset, registration is done in next update(). */ - bebob->deferred_registration = true; fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, false, true); } - dev_set_drvdata(&unit->device, bebob); -end: - mutex_unlock(&devices_mutex); - return err; -error: - mutex_unlock(&devices_mutex); - snd_card_free(card); - return err; + return 0; } /* @@ -324,15 +355,11 @@ bebob_update(struct fw_unit *unit) if (bebob == NULL) return; - fcp_bus_reset(bebob->unit); - - if (bebob->deferred_registration) { - if (snd_card_register(bebob->card) < 0) { - snd_bebob_stream_destroy_duplex(bebob); - snd_card_free(bebob->card); - } - bebob->deferred_registration = false; - } + /* Postpone a workqueue for deferred registration. */ + if (!bebob->registered) + snd_fw_schedule_registration(unit, &bebob->dwork); + else + fcp_bus_reset(bebob->unit); } static void bebob_remove(struct fw_unit *unit) @@ -342,8 +369,20 @@ static void bebob_remove(struct fw_unit *unit) if (bebob == NULL) return; - /* No need to wait for releasing card object in this context. */ - snd_card_free_when_closed(bebob->card); + /* + * Confirm to stop the work for registration before the sound card is + * going to be released. The work is not scheduled again because bus + * reset handler is not called anymore. + */ + cancel_delayed_work_sync(&bebob->dwork); + + if (bebob->registered) { + /* No need to wait for releasing card object in this context. */ + snd_card_free_when_closed(bebob->card); + } else { + /* Don't forget this case. */ + bebob_free(bebob); + } } static const struct snd_bebob_rate_spec normal_rate_spec = { diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index b50bb33d9d46..2a442a7a2119 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -83,6 +83,10 @@ struct snd_bebob { struct mutex mutex; spinlock_t lock; + bool registered; + struct delayed_work dwork; + + const struct ieee1394_device_id *entry; const struct snd_bebob_spec *spec; unsigned int midi_input_ports; @@ -111,7 +115,6 @@ struct snd_bebob { /* for M-Audio special devices */ void *maudio_special_quirk; - bool deferred_registration; /* For BeBoB version quirk. */ unsigned int version; -- GitLab From 7d3c1d5901aac873d13c0a03b29ee2bda183383f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:06 +0900 Subject: [PATCH 0986/9938] ALSA: fireworks: delayed registration of sound card When some fireworks units are connected sequentially, userspace applications are involved at bus-reset state on IEEE 1394 bus. In the state, any communications can be canceled. Therefore, sound card registration should be delayed till the bus gets calm. This commit achieves it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireworks/fireworks.c | 147 ++++++++++++++++++--------- sound/firewire/fireworks/fireworks.h | 3 + 2 files changed, 103 insertions(+), 47 deletions(-) diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c index 8380fb572202..71a0613d3da0 100644 --- a/sound/firewire/fireworks/fireworks.c +++ b/sound/firewire/fireworks/fireworks.c @@ -184,6 +184,18 @@ get_hardware_info(struct snd_efw *efw) return err; } +static void efw_free(struct snd_efw *efw) +{ + snd_efw_stream_destroy_duplex(efw); + snd_efw_transaction_remove_instance(efw); + fw_unit_put(efw->unit); + + kfree(efw->resp_buf); + + mutex_destroy(&efw->mutex); + kfree(efw); +} + /* * This module releases the FireWire unit data after all ALSA character devices * are released by applications. This is for releasing stream data or finishing @@ -195,28 +207,24 @@ efw_card_free(struct snd_card *card) { struct snd_efw *efw = card->private_data; - snd_efw_stream_destroy_duplex(efw); - snd_efw_transaction_remove_instance(efw); - fw_unit_put(efw->unit); - - kfree(efw->resp_buf); - if (efw->card_index >= 0) { mutex_lock(&devices_mutex); clear_bit(efw->card_index, devices_used); mutex_unlock(&devices_mutex); } - mutex_destroy(&efw->mutex); + efw_free(card->private_data); } -static int -efw_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) +static void +do_registration(struct work_struct *work) { - struct snd_card *card; - struct snd_efw *efw; - int card_index, err; + struct snd_efw *efw = container_of(work, struct snd_efw, dwork.work); + unsigned int card_index; + int err; + + if (efw->registered) + return; mutex_lock(&devices_mutex); @@ -226,24 +234,16 @@ efw_probe(struct fw_unit *unit, break; } if (card_index >= SNDRV_CARDS) { - err = -ENOENT; - goto end; + mutex_unlock(&devices_mutex); + return; } - err = snd_card_new(&unit->device, index[card_index], id[card_index], - THIS_MODULE, sizeof(struct snd_efw), &card); - if (err < 0) - goto end; - efw = card->private_data; - efw->card_index = card_index; - set_bit(card_index, devices_used); - card->private_free = efw_card_free; - - efw->card = card; - efw->unit = fw_unit_get(unit); - mutex_init(&efw->mutex); - spin_lock_init(&efw->lock); - init_waitqueue_head(&efw->hwdep_wait); + err = snd_card_new(&efw->unit->device, index[card_index], + id[card_index], THIS_MODULE, 0, &efw->card); + if (err < 0) { + mutex_unlock(&devices_mutex); + return; + } /* prepare response buffer */ snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, @@ -260,6 +260,10 @@ efw_probe(struct fw_unit *unit, if (err < 0) goto error; + err = snd_efw_stream_init_duplex(efw); + if (err < 0) + goto error; + snd_efw_proc_init(efw); if (efw->midi_out_ports || efw->midi_in_ports) { @@ -276,44 +280,93 @@ efw_probe(struct fw_unit *unit, if (err < 0) goto error; - err = snd_efw_stream_init_duplex(efw); + err = snd_card_register(efw->card); if (err < 0) goto error; - err = snd_card_register(card); - if (err < 0) { - snd_efw_stream_destroy_duplex(efw); - goto error; - } - - dev_set_drvdata(&unit->device, efw); -end: + set_bit(card_index, devices_used); mutex_unlock(&devices_mutex); - return err; + + /* + * After registered, efw instance can be released corresponding to + * releasing the sound card instance. + */ + efw->card->private_free = efw_card_free; + efw->card->private_data = efw; + efw->registered = true; + + return; error: - snd_efw_transaction_remove_instance(efw); mutex_unlock(&devices_mutex); - snd_card_free(card); - return err; + snd_efw_transaction_remove_instance(efw); + snd_efw_stream_destroy_duplex(efw); + snd_card_free(efw->card); + dev_info(&efw->unit->device, + "Sound card registration failed: %d\n", err); +} + +static int +efw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) +{ + struct snd_efw *efw; + + efw = kzalloc(sizeof(struct snd_efw), GFP_KERNEL); + if (efw == NULL) + return -ENOMEM; + + efw->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, efw); + + mutex_init(&efw->mutex); + spin_lock_init(&efw->lock); + init_waitqueue_head(&efw->hwdep_wait); + + /* Allocate and register this sound card later. */ + INIT_DEFERRABLE_WORK(&efw->dwork, do_registration); + snd_fw_schedule_registration(unit, &efw->dwork); + + return 0; } static void efw_update(struct fw_unit *unit) { struct snd_efw *efw = dev_get_drvdata(&unit->device); + /* Postpone a workqueue for deferred registration. */ + if (!efw->registered) + snd_fw_schedule_registration(unit, &efw->dwork); + snd_efw_transaction_bus_reset(efw->unit); - mutex_lock(&efw->mutex); - snd_efw_stream_update_duplex(efw); - mutex_unlock(&efw->mutex); + /* + * After registration, userspace can start packet streaming, then this + * code block works fine. + */ + if (efw->registered) { + mutex_lock(&efw->mutex); + snd_efw_stream_update_duplex(efw); + mutex_unlock(&efw->mutex); + } } static void efw_remove(struct fw_unit *unit) { struct snd_efw *efw = dev_get_drvdata(&unit->device); - /* No need to wait for releasing card object in this context. */ - snd_card_free_when_closed(efw->card); + /* + * Confirm to stop the work for registration before the sound card is + * going to be released. The work is not scheduled again because bus + * reset handler is not called anymore. + */ + cancel_delayed_work_sync(&efw->dwork); + + if (efw->registered) { + /* No need to wait for releasing card object in this context. */ + snd_card_free_when_closed(efw->card); + } else { + /* Don't forget this case. */ + efw_free(efw); + } } static const struct ieee1394_device_id efw_id_table[] = { diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 96c4e0c6a9bd..471c77254dfd 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -65,6 +65,9 @@ struct snd_efw { struct mutex mutex; spinlock_t lock; + bool registered; + struct delayed_work dwork; + /* for transaction */ u32 seqnum; bool resp_addr_changable; -- GitLab From 6c29230e2a5ff84df2b1358681414bad3e4bd220 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:07 +0900 Subject: [PATCH 0987/9938] ALSA: oxfw: delayed registration of sound card Some oxfw based units tends to fail asynchronous communication when IEEE 1394 bus is under bus-reset state. When registering sound card instance at unit probe callback, userspace applications can be involved to the state. This commit postpones the registration till the bus is calm. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw.c | 151 ++++++++++++++++++++++++------------- sound/firewire/oxfw/oxfw.h | 3 + 2 files changed, 101 insertions(+), 53 deletions(-) diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index abedc2207261..e629b88f7d93 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -118,15 +118,8 @@ static int name_card(struct snd_oxfw *oxfw) return err; } -/* - * This module releases the FireWire unit data after all ALSA character devices - * are released by applications. This is for releasing stream data or finishing - * transactions safely. Thus at returning from .remove(), this module still keep - * references for the unit. - */ -static void oxfw_card_free(struct snd_card *card) +static void oxfw_free(struct snd_oxfw *oxfw) { - struct snd_oxfw *oxfw = card->private_data; unsigned int i; snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); @@ -144,6 +137,17 @@ static void oxfw_card_free(struct snd_card *card) mutex_destroy(&oxfw->mutex); } +/* + * This module releases the FireWire unit data after all ALSA character devices + * are released by applications. This is for releasing stream data or finishing + * transactions safely. Thus at returning from .remove(), this module still keep + * references for the unit. + */ +static void oxfw_card_free(struct snd_card *card) +{ + oxfw_free(card->private_data); +} + static int detect_quirks(struct snd_oxfw *oxfw) { struct fw_device *fw_dev = fw_parent_device(oxfw->unit); @@ -205,41 +209,39 @@ static int detect_quirks(struct snd_oxfw *oxfw) return 0; } -static int oxfw_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) +static void do_registration(struct work_struct *work) { - struct snd_card *card; - struct snd_oxfw *oxfw; + struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work); int err; - if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit)) - return -ENODEV; + if (oxfw->registered) + return; - err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, - sizeof(*oxfw), &card); + err = snd_card_new(&oxfw->unit->device, -1, NULL, THIS_MODULE, 0, + &oxfw->card); if (err < 0) - return err; + return; - card->private_free = oxfw_card_free; - oxfw = card->private_data; - oxfw->card = card; - mutex_init(&oxfw->mutex); - oxfw->unit = fw_unit_get(unit); - oxfw->entry = entry; - spin_lock_init(&oxfw->lock); - init_waitqueue_head(&oxfw->hwdep_wait); + err = name_card(oxfw); + if (err < 0) + goto error; - err = snd_oxfw_stream_discover(oxfw); + err = detect_quirks(oxfw); if (err < 0) goto error; - err = name_card(oxfw); + err = snd_oxfw_stream_discover(oxfw); if (err < 0) goto error; - err = detect_quirks(oxfw); + err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream); if (err < 0) goto error; + if (oxfw->has_output) { + err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream); + if (err < 0) + goto error; + } err = snd_oxfw_create_pcm(oxfw); if (err < 0) @@ -255,54 +257,97 @@ static int oxfw_probe(struct fw_unit *unit, if (err < 0) goto error; - err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream); + err = snd_card_register(oxfw->card); if (err < 0) goto error; - if (oxfw->has_output) { - err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream); - if (err < 0) - goto error; - } - err = snd_card_register(card); - if (err < 0) { - snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); - if (oxfw->has_output) - snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); - goto error; - } + /* + * After registered, oxfw instance can be released corresponding to + * releasing the sound card instance. + */ + oxfw->card->private_free = oxfw_card_free; + oxfw->card->private_data = oxfw; + oxfw->registered = true; + + return; +error: + snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); + if (oxfw->has_output) + snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); + snd_card_free(oxfw->card); + dev_info(&oxfw->unit->device, + "Sound card registration failed: %d\n", err); +} + +static int oxfw_probe(struct fw_unit *unit, + const struct ieee1394_device_id *entry) +{ + struct snd_oxfw *oxfw; + + if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit)) + return -ENODEV; + + /* Allocate this independent of sound card instance. */ + oxfw = kzalloc(sizeof(struct snd_oxfw), GFP_KERNEL); + if (oxfw == NULL) + return -ENOMEM; + + oxfw->entry = entry; + oxfw->unit = fw_unit_get(unit); dev_set_drvdata(&unit->device, oxfw); + mutex_init(&oxfw->mutex); + spin_lock_init(&oxfw->lock); + init_waitqueue_head(&oxfw->hwdep_wait); + + /* Allocate and register this sound card later. */ + INIT_DEFERRABLE_WORK(&oxfw->dwork, do_registration); + snd_fw_schedule_registration(unit, &oxfw->dwork); + return 0; -error: - snd_card_free(card); - return err; } static void oxfw_bus_reset(struct fw_unit *unit) { struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); + if (!oxfw->registered) + snd_fw_schedule_registration(unit, &oxfw->dwork); + fcp_bus_reset(oxfw->unit); - mutex_lock(&oxfw->mutex); + if (oxfw->registered) { + mutex_lock(&oxfw->mutex); - snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream); - if (oxfw->has_output) - snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream); + snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream); + if (oxfw->has_output) + snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream); - mutex_unlock(&oxfw->mutex); + mutex_unlock(&oxfw->mutex); - if (oxfw->entry->vendor_id == OUI_STANTON) - snd_oxfw_scs1x_update(oxfw); + if (oxfw->entry->vendor_id == OUI_STANTON) + snd_oxfw_scs1x_update(oxfw); + } } static void oxfw_remove(struct fw_unit *unit) { struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); - /* No need to wait for releasing card object in this context. */ - snd_card_free_when_closed(oxfw->card); + /* + * Confirm to stop the work for registration before the sound card is + * going to be released. The work is not scheduled again because bus + * reset handler is not called anymore. + */ + cancel_delayed_work_sync(&oxfw->dwork); + + if (oxfw->registered) { + /* No need to wait for releasing card object in this context. */ + snd_card_free_when_closed(oxfw->card); + } else { + /* Don't forget this case. */ + oxfw_free(oxfw); + } } static const struct compat_info griffin_firewave = { diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index 2c84714e9bbd..2047dcb27625 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -39,6 +39,9 @@ struct snd_oxfw { struct mutex mutex; spinlock_t lock; + bool registered; + struct delayed_work dwork; + bool wrong_dbs; bool has_output; u8 *tx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES]; -- GitLab From 86c8dd7f4da3fb3f92fc5ab5144c971639d39745 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:08 +0900 Subject: [PATCH 0988/9938] ALSA: firewire-digi00x: delayed registration of sound card When some digi00x units are connected sequentially, userspace applications are involved at bus-reset state on IEEE 1394 bus. In the state, any communications can be canceled. Therefore, sound card registration should be delayed till the bus gets calm. This commit achieves it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/digi00x/digi00x-transaction.c | 7 +- sound/firewire/digi00x/digi00x.c | 107 +++++++++++++------ sound/firewire/digi00x/digi00x.h | 3 + 3 files changed, 85 insertions(+), 32 deletions(-) diff --git a/sound/firewire/digi00x/digi00x-transaction.c b/sound/firewire/digi00x/digi00x-transaction.c index 554324d8c602..735d35640807 100644 --- a/sound/firewire/digi00x/digi00x-transaction.c +++ b/sound/firewire/digi00x/digi00x-transaction.c @@ -126,12 +126,17 @@ int snd_dg00x_transaction_register(struct snd_dg00x *dg00x) return err; error: fw_core_remove_address_handler(&dg00x->async_handler); - dg00x->async_handler.address_callback = NULL; + dg00x->async_handler.callback_data = NULL; return err; } void snd_dg00x_transaction_unregister(struct snd_dg00x *dg00x) { + if (dg00x->async_handler.callback_data == NULL) + return; + snd_fw_async_midi_port_destroy(&dg00x->out_control); fw_core_remove_address_handler(&dg00x->async_handler); + + dg00x->async_handler.callback_data = NULL; } diff --git a/sound/firewire/digi00x/digi00x.c b/sound/firewire/digi00x/digi00x.c index 1f33b7a1fca4..cc4776c6ded3 100644 --- a/sound/firewire/digi00x/digi00x.c +++ b/sound/firewire/digi00x/digi00x.c @@ -40,10 +40,8 @@ static int name_card(struct snd_dg00x *dg00x) return 0; } -static void dg00x_card_free(struct snd_card *card) +static void dg00x_free(struct snd_dg00x *dg00x) { - struct snd_dg00x *dg00x = card->private_data; - snd_dg00x_stream_destroy_duplex(dg00x); snd_dg00x_transaction_unregister(dg00x); @@ -52,28 +50,24 @@ static void dg00x_card_free(struct snd_card *card) mutex_destroy(&dg00x->mutex); } -static int snd_dg00x_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) +static void dg00x_card_free(struct snd_card *card) { - struct snd_card *card; - struct snd_dg00x *dg00x; - int err; + dg00x_free(card->private_data); +} - /* create card */ - err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, - sizeof(struct snd_dg00x), &card); - if (err < 0) - return err; - card->private_free = dg00x_card_free; +static void do_registration(struct work_struct *work) +{ + struct snd_dg00x *dg00x = + container_of(work, struct snd_dg00x, dwork.work); + int err; - /* initialize myself */ - dg00x = card->private_data; - dg00x->card = card; - dg00x->unit = fw_unit_get(unit); + if (dg00x->registered) + return; - mutex_init(&dg00x->mutex); - spin_lock_init(&dg00x->lock); - init_waitqueue_head(&dg00x->hwdep_wait); + err = snd_card_new(&dg00x->unit->device, -1, NULL, THIS_MODULE, 0, + &dg00x->card); + if (err < 0) + return; err = name_card(dg00x); if (err < 0) @@ -101,35 +95,86 @@ static int snd_dg00x_probe(struct fw_unit *unit, if (err < 0) goto error; - err = snd_card_register(card); + err = snd_card_register(dg00x->card); if (err < 0) goto error; - dev_set_drvdata(&unit->device, dg00x); + dg00x->card->private_free = dg00x_card_free; + dg00x->card->private_data = dg00x; + dg00x->registered = true; - return err; + return; error: - snd_card_free(card); - return err; + snd_dg00x_transaction_unregister(dg00x); + snd_dg00x_stream_destroy_duplex(dg00x); + snd_card_free(dg00x->card); + dev_info(&dg00x->unit->device, + "Sound card registration failed: %d\n", err); +} + +static int snd_dg00x_probe(struct fw_unit *unit, + const struct ieee1394_device_id *entry) +{ + struct snd_dg00x *dg00x; + + /* Allocate this independent of sound card instance. */ + dg00x = kzalloc(sizeof(struct snd_dg00x), GFP_KERNEL); + if (dg00x == NULL) + return -ENOMEM; + + dg00x->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, dg00x); + + mutex_init(&dg00x->mutex); + spin_lock_init(&dg00x->lock); + init_waitqueue_head(&dg00x->hwdep_wait); + + /* Allocate and register this sound card later. */ + INIT_DEFERRABLE_WORK(&dg00x->dwork, do_registration); + snd_fw_schedule_registration(unit, &dg00x->dwork); + + return 0; } static void snd_dg00x_update(struct fw_unit *unit) { struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device); + /* Postpone a workqueue for deferred registration. */ + if (!dg00x->registered) + snd_fw_schedule_registration(unit, &dg00x->dwork); + snd_dg00x_transaction_reregister(dg00x); - mutex_lock(&dg00x->mutex); - snd_dg00x_stream_update_duplex(dg00x); - mutex_unlock(&dg00x->mutex); + /* + * After registration, userspace can start packet streaming, then this + * code block works fine. + */ + if (dg00x->registered) { + mutex_lock(&dg00x->mutex); + snd_dg00x_stream_update_duplex(dg00x); + mutex_unlock(&dg00x->mutex); + } } static void snd_dg00x_remove(struct fw_unit *unit) { struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device); - /* No need to wait for releasing card object in this context. */ - snd_card_free_when_closed(dg00x->card); + /* + * Confirm to stop the work for registration before the sound card is + * going to be released. The work is not scheduled again because bus + * reset handler is not called anymore. + */ + cancel_delayed_work_sync(&dg00x->dwork); + + if (dg00x->registered) { + /* No need to wait for releasing card object in this context. */ + snd_card_free_when_closed(dg00x->card); + } else { + /* Don't forget this case. */ + dg00x_free(dg00x); + } } static const struct ieee1394_device_id snd_dg00x_id_table[] = { diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 907e73993677..2cd465c0caae 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h @@ -37,6 +37,9 @@ struct snd_dg00x { struct mutex mutex; spinlock_t lock; + bool registered; + struct delayed_work dwork; + struct amdtp_stream tx_stream; struct fw_iso_resources tx_resources; -- GitLab From 3ed5ca2efff70e9f589087c2013789572901112d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 30 Mar 2016 16:51:17 -0300 Subject: [PATCH 0989/9938] perf trace: Do not process PERF_RECORD_LOST twice We catch this record to provide a visual indication that events are getting lost, then call the default method to allow extra logging shared with the other tools to take place. This extra logging was done twice because we were continuing to the "default" clause where machine__process_event() will end up calling machine__process_lost_event() again, fix it. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-wus2zlhw3qo24ye84ewu4aqw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 93ac724fb635..6485576f3337 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1618,6 +1618,7 @@ static int trace__process_event(struct trace *trace, struct machine *machine, color_fprintf(trace->output, PERF_COLOR_RED, "LOST %" PRIu64 " events!\n", event->lost.lost); ret = machine__process_lost_event(machine, event, sample); + break; default: ret = machine__process_event(machine, event, sample); break; -- GitLab From 997bba8cf1875d9715e792c445e1a9c7a4c365e2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 30 Mar 2016 19:43:32 -0300 Subject: [PATCH 0990/9938] perf trace: Pretty print seccomp() args E.g: # trace -e seccomp 200.061 (0.009 ms): :2441/2441 seccomp(op: FILTER, flags: TSYNC ) = -1 EFAULT Bad address 200.910 (0.121 ms): :2441/2441 seccomp(op: FILTER, flags: TSYNC, uargs: 0x7fff57479fe0) = 0 Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-t369uckshlwp4evkks4bcoo7@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6485576f3337..0c8bcb94934e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -40,6 +40,10 @@ #include #include #include +#include +#include +#include +#include /* For older distros: */ #ifndef MAP_STACK @@ -1001,6 +1005,46 @@ static const char *tioctls[] = { static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401); #endif /* defined(__i386__) || defined(__x86_64__) */ +static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg) +{ + int op = arg->val; + size_t printed = 0; + + switch (op) { +#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break + P_SECCOMP_SET_MODE_OP(STRICT); + P_SECCOMP_SET_MODE_OP(FILTER); +#undef P_SECCOMP_SET_MODE_OP + default: printed = scnprintf(bf, size, "%#x", op); break; + } + + return printed; +} + +#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op + +static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, + struct syscall_arg *arg) +{ + int printed = 0, flags = arg->val; + +#define P_FLAG(n) \ + if (flags & SECCOMP_FILTER_FLAG_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + flags &= ~SECCOMP_FILTER_FLAG_##n; \ + } + + P_FLAG(TSYNC); +#undef P_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); + + return printed; +} + +#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags + #define STRARRAY(arg, name, array) \ .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ .arg_parm = { [arg] = &strarray__##array, } @@ -1234,6 +1278,9 @@ static struct syscall_fmt { .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, { .name = "rt_tgsigqueueinfo", .errmsg = true, .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, + { .name = "seccomp", .errmsg = true, + .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */ + [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, { .name = "select", .errmsg = true, .timeout = true, }, { .name = "sendmmsg", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ -- GitLab From 39878d492c049796202b70dc0ef14449cafa3cb4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 30 Mar 2016 20:02:15 -0300 Subject: [PATCH 0991/9938] perf trace: Pretty print getrandom() args # trace -e getrandom 35622.560 ( 0.023 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 35622.585 ( 0.006 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 35622.594 ( 0.004 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 35627.395 ( 0.010 ms): libvirtd/1353 getrandom(buf: 0x7f7a1bfa35c0, count: 16, flags: NONBLOCK ) = 16 35630.940 ( 0.013 ms): fwupd/16120 getrandom(buf: 0x7f63243aa5c0, count: 16, flags: NONBLOCK ) = 16 35718.613 ( 0.015 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 35718.629 ( 0.005 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 35718.637 ( 0.004 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 35719.355 ( 0.010 ms): libvirtd/1353 getrandom(buf: 0x7f7a1bfa35c0, count: 16, flags: NONBLOCK ) = 16 35721.042 ( 0.030 ms): fwupd/16120 getrandom(buf: 0x7f63243aa5c0, count: 16, flags: NONBLOCK ) = 16 41090.830 ( 0.012 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 41090.845 ( 0.004 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 41090.851 ( 0.004 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 41091.750 ( 0.010 ms): libvirtd/1353 getrandom(buf: 0x7f7a1bfa35c0, count: 16, flags: NONBLOCK ) = 16 41091.823 ( 0.006 ms): fwupd/16120 getrandom(buf: 0x7f63243aa5c0, count: 16, flags: NONBLOCK ) = 16 41122.078 ( 0.053 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 41122.129 ( 0.009 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 41122.139 ( 0.004 ms): systemd-udevd/631 getrandom(buf: 0x55621e3c18f0, count: 16, flags: NONBLOCK) = 16 41124.492 ( 0.007 ms): libvirtd/1353 getrandom(buf: 0x7f7a1bfa35c0, count: 16, flags: NONBLOCK ) = 16 41124.470 ( 0.013 ms): fwupd/16120 getrandom(buf: 0x7f63243aa5c0, count: 16, flags: NONBLOCK ) = 16 41590.832 ( 0.014 ms): chrome/5957 getrandom(buf: 0x7fabac7b15b0, count: 16, flags: NONBLOCK ) = 16 41590.884 ( 0.004 ms): chrome/5957 getrandom(buf: 0x7fabac7b15c0, count: 16, flags: NONBLOCK ) = 16 Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-gca0n1p3aca3depey703ph2q@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0c8bcb94934e..c45c1cfeb866 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -44,6 +44,7 @@ #include #include #include +#include /* For older distros: */ #ifndef MAP_STACK @@ -1045,6 +1046,29 @@ static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, #define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags +static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, + struct syscall_arg *arg) +{ + int printed = 0, flags = arg->val; + +#define P_FLAG(n) \ + if (flags & GRND_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + flags &= ~GRND_##n; \ + } + + P_FLAG(RANDOM); + P_FLAG(NONBLOCK); +#undef P_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); + + return printed; +} + +#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags + #define STRARRAY(arg, name, array) \ .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ .arg_parm = { [arg] = &strarray__##array, } @@ -1137,6 +1161,8 @@ static struct syscall_fmt { { .name = "getdents64", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, + { .name = "getrandom", .errmsg = true, + .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, { .name = "getxattr", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, -- GitLab From 46bc29b970f0011a9099077f1db8f3540aa829fe Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Mar 2016 10:38:44 +0200 Subject: [PATCH 0992/9938] perf tools: Add time conversion event Intel PT uses the time members from the perf_event_mmap_page to convert between TSC and perf time. Due to a lack of foresight when Intel PT was implemented, those time members were recorded in the (implementation dependent) AUXTRACE_INFO event, the structure of which is generally inaccessible outside of the Intel PT decoder. However now the conversion between TSC and perf time is needed when processing a jitdump file when Intel PT has been used for tracing. So add a user event to record the time members. 'perf record' will synthesize the event if the information is available. And session processing will put a copy of the event on the session so that tools like 'perf inject' can easily access it. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1457426324-30158-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/tsc.c | 31 +++++++++++++++++++++++++++++++ tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 15 +++++++++++++++ tools/perf/util/event.c | 1 + tools/perf/util/event.h | 9 +++++++++ tools/perf/util/session.c | 6 ++++++ tools/perf/util/session.h | 1 + tools/perf/util/tool.h | 1 + tools/perf/util/tsc.h | 10 ++++++++++ 9 files changed, 75 insertions(+) diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c index fd2868490d00..70ff7c14bea6 100644 --- a/tools/perf/arch/x86/util/tsc.c +++ b/tools/perf/arch/x86/util/tsc.c @@ -46,3 +46,34 @@ u64 rdtsc(void) return low | ((u64)high) << 32; } + +int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc, + struct perf_tool *tool, + perf_event__handler_t process, + struct machine *machine) +{ + union perf_event event = { + .time_conv = { + .header = { + .type = PERF_RECORD_TIME_CONV, + .size = sizeof(struct time_conv_event), + }, + }, + }; + struct perf_tsc_conversion tc; + int err; + + err = perf_read_tsc_conversion(pc, &tc); + if (err == -EOPNOTSUPP) + return 0; + if (err) + return err; + + pr_debug2("Synthesizing TSC conversion information\n"); + + event.time_conv.time_mult = tc.time_mult; + event.time_conv.time_shift = tc.time_shift; + event.time_conv.time_zero = tc.time_zero; + + return process(tool, &event, NULL, machine); +} diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index d1a2d104f2bc..e5afa8fe1bf1 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -748,6 +748,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__repipe_op2_synth, .auxtrace = perf_event__repipe_auxtrace, .auxtrace_error = perf_event__repipe_op2_synth, + .time_conv = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth, diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 515510ecc76a..410035c6e300 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -29,6 +29,7 @@ #include "util/data.h" #include "util/perf_regs.h" #include "util/auxtrace.h" +#include "util/tsc.h" #include "util/parse-branch-options.h" #include "util/parse-regs-options.h" #include "util/llvm-utils.h" @@ -512,6 +513,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused, static void snapshot_sig_handler(int sig); +int __weak +perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, + struct perf_tool *tool __maybe_unused, + perf_event__handler_t process __maybe_unused, + struct machine *machine __maybe_unused) +{ + return 0; +} + static int record__synthesize(struct record *rec) { struct perf_session *session = rec->session; @@ -549,6 +559,11 @@ static int record__synthesize(struct record *rec) } } + err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool, + process_synthesized_event, machine); + if (err) + goto out; + if (rec->opts.full_auxtrace) { err = perf_event__synthesize_auxtrace_info(rec->itr, tool, session, process_synthesized_event); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index dad55d04ffdd..b68959037688 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -45,6 +45,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", + [PERF_RECORD_TIME_CONV] = "TIME_CONV", }; const char *perf_event__name(unsigned int id) diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 6bb1c928350d..8d363d5e65a2 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -233,6 +233,7 @@ enum perf_user_event_type { /* above any possible kernel type */ PERF_RECORD_STAT = 76, PERF_RECORD_STAT_ROUND = 77, PERF_RECORD_EVENT_UPDATE = 78, + PERF_RECORD_TIME_CONV = 79, PERF_RECORD_HEADER_MAX }; @@ -469,6 +470,13 @@ struct stat_round_event { u64 time; }; +struct time_conv_event { + struct perf_event_header header; + u64 time_shift; + u64 time_mult; + u64 time_zero; +}; + union perf_event { struct perf_event_header header; struct mmap_event mmap; @@ -497,6 +505,7 @@ union perf_event { struct stat_config_event stat_config; struct stat_event stat; struct stat_round_event stat_round; + struct time_conv_event time_conv; }; void perf_event__print_totals(void); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 4abd85c6346d..ef370557fb9a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->stat = process_stat_stub; if (tool->stat_round == NULL) tool->stat_round = process_stat_round_stub; + if (tool->time_conv == NULL) + tool->time_conv = process_event_op2_stub; } static void swap_sample_id_all(union perf_event *event, void *data) @@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, + [PERF_RECORD_TIME_CONV] = perf_event__all64_swap, [PERF_RECORD_HEADER_MAX] = NULL, }; @@ -1341,6 +1344,9 @@ static s64 perf_session__process_user_event(struct perf_session *session, return tool->stat(tool, event, session); case PERF_RECORD_STAT_ROUND: return tool->stat_round(tool, event, session); + case PERF_RECORD_TIME_CONV: + session->time_conv = event->time_conv; + return tool->time_conv(tool, event, session); default: return -EINVAL; } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 5f792e35d4c1..f96fc9e8c52e 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -26,6 +26,7 @@ struct perf_session { struct itrace_synth_opts *itrace_synth_opts; struct list_head auxtrace_index; struct trace_event tevent; + struct time_conv_event time_conv; bool repipe; bool one_mmap; void *one_mmap_addr; diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 55de4cffcd4e..ac2590a3de2d 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -57,6 +57,7 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, + time_conv, thread_map, cpu_map, stat_config, diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h index a8b78f1b3243..280ddc067556 100644 --- a/tools/perf/util/tsc.h +++ b/tools/perf/util/tsc.h @@ -3,10 +3,20 @@ #include +#include "event.h" #include "../arch/x86/util/tsc.h" u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); u64 rdtsc(void); +struct perf_event_mmap_page; +struct perf_tool; +struct machine; + +int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc, + struct perf_tool *tool, + perf_event__handler_t process, + struct machine *machine); + #endif -- GitLab From bc553986a2f7c56d0de811485d5312ea29692d5d Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 24 Mar 2016 10:52:42 -0500 Subject: [PATCH 0993/9938] dtc: turn off dtc unit address warnings by default The newly added dtc warning to check DT unit-address without reg property and vice-versa generates lots of warnings. Turn off the check unless building with W=1 or W=2. Signed-off-by: Rob Herring Cc: Michal Marek Cc: linux-kbuild@vger.kernel.org --- scripts/Makefile.lib | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index ddf83d0181e7..ed1b7c4fb674 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -277,6 +277,11 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ # --------------------------------------------------------------------------- DTC ?= $(objtree)/scripts/dtc/dtc +# Disable noisy checks by default +ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),) +DTC_FLAGS += -Wno-unit_address_vs_reg +endif + # Generate an assembly file to wrap the output of the device tree compiler quiet_cmd_dt_S_dtb= DTB $@ cmd_dt_S_dtb= \ -- GitLab From fd7b980c9e1e52d41589c41ae166b0cfae32b210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 16 Mar 2016 14:58:42 +0100 Subject: [PATCH 0994/9938] arm64: dts: rockchip: Add rk3368 GeekBox dts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GeekBox contains an MXM3 module with a Rockchip RK3368 SoC. Some connectors are available directly on the module. This adds initial support, namely serial, USB, GMAC, eMMC, IR and TSADC. Signed-off-by: Andreas Färber Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../boot/dts/rockchip/rk3368-geekbox.dts | 319 ++++++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index e3f0b5f4ba4e..df37865e8ced 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -1,4 +1,5 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb always := $(dtb-y) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts b/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts new file mode 100644 index 000000000000..46cdddfcea6c --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2016 Andreas Färber + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "rk3368.dtsi" +#include + +/ { + model = "GeekBox"; + compatible = "geekbuying,geekbox", "rockchip,rk3368"; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + ext_gmac: gmac-clk { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "ext_gmac"; + #clock-cells = <0>; + }; + + ir: ir-receiver { + compatible = "gpio-ir-receiver"; + gpios = <&gpio3 30 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&ir_int>; + }; + + keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_key>; + + power { + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + label = "GPIO Power"; + linux,code = ; + wakeup-source; + }; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + + blue { + gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; + label = "geekbox:blue:led"; + default-state = "on"; + }; + + red { + gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + label = "geekbox:red:led"; + default-state = "off"; + }; + }; + + vcc_sys: vcc-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&emmc { + status = "okay"; + bus-width = <8>; + cap-mmc-highspeed; + clock-frequency = <150000000>; + disable-wp; + keep-power-in-suspend; + non-removable; + num-slots = <1>; + vmmc-supply = <&vcc_io>; + vqmmc-supply = <&vcc18_flash>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>; +}; + +&gmac { + status = "okay"; + phy-supply = <&vcc_lan>; + phy-mode = "rgmii"; + clock_in_out = "input"; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + tx_delay = <0x30>; + rx_delay = <0x10>; +}; + +&i2c0 { + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&pmic_sleep>; + interrupt-parent = <&gpio0>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; + rockchip,system-power-controller; + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc_io>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc_io>; + clock-output-names = "xin32k", "rk808-clkout2"; + #clock-cells = <1>; + + regulators { + vdd_cpu: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd_cpu"; + }; + + vdd_log: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd_log"; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + }; + + vcc_io: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_io"; + }; + + vcc18_flash: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_flash"; + }; + + vcc33_lcd: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc33_lcd"; + }; + + vdd_10: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd_10"; + }; + + vcca_18: LDO_REG4 { + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca_18"; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + }; + + vdd10_lcd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd10_lcd"; + }; + + vcc_18: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_18"; + }; + + vcc18_lcd: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_lcd"; + }; + + vcc_sd: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_sd"; + }; + + vcc_lan: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_lan"; + }; + }; + }; +}; + +&pinctrl { + ir { + ir_int: ir-int { + rockchip,pins = <3 30 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + keys { + pwr_key: pwr-key { + rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_sleep: pmic-sleep { + rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&tsadc { + status = "okay"; + rockchip,hw-tshut-mode = <0>; /* CRU */ + rockchip,hw-tshut-polarity = <1>; /* high */ +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_otg { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; -- GitLab From 40ac568d0ef07b60ba8cc0f2e88ccdd4dd0e176a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 16 Mar 2016 14:58:41 +0100 Subject: [PATCH 0995/9938] Documentation: devicetree: rockchip: Document rk3368-GeekBox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use "geekbuying,geekbox" compatible string. Signed-off-by: Andreas Färber Acked-by: Rob Herring Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/arm/rockchip.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt index 078c14fcdaaa..25495190db23 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.txt +++ b/Documentation/devicetree/bindings/arm/rockchip.txt @@ -39,6 +39,10 @@ Rockchip platforms device tree bindings Required root node properties: - compatible = "netxeon,r89", "rockchip,rk3288"; +- GeekBuying GeekBox: + Required root node properties: + - compatible = "geekbuying,geekbox", "rockchip,rk3368"; + - Google Brain (dev-board): Required root node properties: - compatible = "google,veyron-brain-rev0", "google,veyron-brain", -- GitLab From a593ed09040fa611f37953afe455e64c7653160d Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Thu, 31 Mar 2016 18:41:25 +0200 Subject: [PATCH 0996/9938] ASoC: tas571x: added missing register literals The list of TAS571x registers was incomplete. Added the missing register definitions up to the register 0x25. Added volatile and read-only register tables into tas5711_regmap_config and tas5717_regmap_config. The chip has 256 registers in total. But from address 0x29 on (0x26 to 0x28 are reserved) the register width varies between 20, 12 and 8 bytes, which the register map cannot represent. Signed-off-by: Petr Kulhavy Signed-off-by: Mark Brown --- sound/soc/codecs/tas571x.c | 28 ++++++++++++++++++++++++++++ sound/soc/codecs/tas571x.h | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index aafee9bbe01a..ef6c8d9b251a 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -57,6 +57,10 @@ static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg) case TAS571X_CH1_VOL_REG: case TAS571X_CH2_VOL_REG: return priv->chip->vol_reg_size; + case TAS571X_INPUT_MUX_REG: + case TAS571X_CH4_SRC_SELECT_REG: + case TAS571X_PWM_MUX_REG: + return 4; default: return 1; } @@ -259,6 +263,26 @@ static const struct snd_kcontrol_new tas5711_controls[] = { 1, 1), }; +static const struct regmap_range tas571x_readonly_regs_range[] = { + regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_DEV_ID_REG), +}; + +static const struct regmap_range tas571x_volatile_regs_range[] = { + regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG), + regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG), +}; + +static const struct regmap_access_table tas571x_write_regs = { + .no_ranges = tas571x_readonly_regs_range, + .n_no_ranges = ARRAY_SIZE(tas571x_readonly_regs_range), +}; + +static const struct regmap_access_table tas571x_volatile_regs = { + .yes_ranges = tas571x_volatile_regs_range, + .n_yes_ranges = ARRAY_SIZE(tas571x_volatile_regs_range), + +}; + static const struct reg_default tas5711_reg_defaults[] = { { 0x04, 0x05 }, { 0x05, 0x40 }, @@ -278,6 +302,8 @@ static const struct regmap_config tas5711_regmap_config = { .reg_defaults = tas5711_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults), .cache_type = REGCACHE_RBTREE, + .wr_table = &tas571x_write_regs, + .volatile_table = &tas571x_volatile_regs, }; static const struct tas571x_chip tas5711_chip = { @@ -332,6 +358,8 @@ static const struct regmap_config tas5717_regmap_config = { .reg_defaults = tas5717_reg_defaults, .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults), .cache_type = REGCACHE_RBTREE, + .wr_table = &tas571x_write_regs, + .volatile_table = &tas571x_volatile_regs, }; /* This entry is reused for tas5719 as the software interface is identical. */ diff --git a/sound/soc/codecs/tas571x.h b/sound/soc/codecs/tas571x.h index 0aee471232cd..cf800c364f0f 100644 --- a/sound/soc/codecs/tas571x.h +++ b/sound/soc/codecs/tas571x.h @@ -13,6 +13,10 @@ #define _TAS571X_H /* device registers */ +#define TAS571X_CLK_CTRL_REG 0x00 +#define TAS571X_DEV_ID_REG 0x01 +#define TAS571X_ERR_STATUS_REG 0x02 +#define TAS571X_SYS_CTRL_1_REG 0x03 #define TAS571X_SDI_REG 0x04 #define TAS571X_SDI_FMT_MASK 0x0f @@ -27,7 +31,25 @@ #define TAS571X_MVOL_REG 0x07 #define TAS571X_CH1_VOL_REG 0x08 #define TAS571X_CH2_VOL_REG 0x09 +#define TAS571X_CH3_VOL_REG 0x0a +#define TAS571X_VOL_CFG_REG 0x0e +#define TAS571X_MODULATION_LIMIT_REG 0x10 +#define TAS571X_IC_DELAY_CH1_REG 0x11 +#define TAS571X_IC_DELAY_CH2_REG 0x12 +#define TAS571X_IC_DELAY_CH3_REG 0x13 +#define TAS571X_IC_DELAY_CH4_REG 0x14 +#define TAS571X_PWM_CH_SDN_GROUP_REG 0x19 /* N/A on TAS5717, TAS5719 */ +#define TAS571X_PWM_CH1_SDN_MASK (1<<0) +#define TAS571X_PWM_CH2_SDN_SHIFT (1<<1) +#define TAS571X_PWM_CH3_SDN_SHIFT (1<<2) +#define TAS571X_PWM_CH4_SDN_SHIFT (1<<3) + +#define TAS571X_START_STOP_PERIOD_REG 0x1a #define TAS571X_OSC_TRIM_REG 0x1b +#define TAS571X_BKND_ERR_REG 0x1c +#define TAS571X_INPUT_MUX_REG 0x20 +#define TAS571X_CH4_SRC_SELECT_REG 0x21 +#define TAS571X_PWM_MUX_REG 0x25 #endif /* _TAS571X_H */ -- GitLab From 23a282c4f088efb337957ffa21c677d30eda0784 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Thu, 31 Mar 2016 18:41:26 +0200 Subject: [PATCH 0997/9938] ASoC: tas571x: added support for TAS5721 This adds support for TAS5721. Signed-off-by: Petr Kulhavy Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 2 +- sound/soc/codecs/tas571x.c | 76 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 649e92a252ae..c011f076d58b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -737,7 +737,7 @@ config SND_SOC_TAS5086 depends on I2C config SND_SOC_TAS571X - tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers" + tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers" depends on I2C config SND_SOC_TFA9879 diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index ef6c8d9b251a..b8d19b77bde9 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -4,6 +4,9 @@ * Copyright (C) 2015 Google, Inc. * Copyright (c) 2013 Daniel Mack * + * TAS5721 support: + * Copyright (C) 2016 Petr Kulhavy, Barix AG + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -372,6 +375,77 @@ static const struct tas571x_chip tas5717_chip = { .vol_reg_size = 2, }; +static const char *const tas5721_supply_names[] = { + "AVDD", + "DVDD", + "DRVDD", + "PVDD", +}; + +static const struct snd_kcontrol_new tas5721_controls[] = { + SOC_SINGLE_TLV("Master Volume", + TAS571X_MVOL_REG, + 0, 0xff, 1, tas5711_volume_tlv), + SOC_DOUBLE_R_TLV("Speaker Volume", + TAS571X_CH1_VOL_REG, + TAS571X_CH2_VOL_REG, + 0, 0xff, 1, tas5711_volume_tlv), + SOC_DOUBLE("Speaker Switch", + TAS571X_SOFT_MUTE_REG, + TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, + 1, 1), +}; + +static const struct reg_default tas5721_reg_defaults[] = { + {TAS571X_CLK_CTRL_REG, 0x6c}, + {TAS571X_DEV_ID_REG, 0x00}, + {TAS571X_ERR_STATUS_REG, 0x00}, + {TAS571X_SYS_CTRL_1_REG, 0xa0}, + {TAS571X_SDI_REG, 0x05}, + {TAS571X_SYS_CTRL_2_REG, 0x40}, + {TAS571X_SOFT_MUTE_REG, 0x00}, + {TAS571X_MVOL_REG, 0xff}, + {TAS571X_CH1_VOL_REG, 0x30}, + {TAS571X_CH2_VOL_REG, 0x30}, + {TAS571X_CH3_VOL_REG, 0x30}, + {TAS571X_VOL_CFG_REG, 0x91}, + {TAS571X_MODULATION_LIMIT_REG, 0x02}, + {TAS571X_IC_DELAY_CH1_REG, 0xac}, + {TAS571X_IC_DELAY_CH2_REG, 0x54}, + {TAS571X_IC_DELAY_CH3_REG, 0xac}, + {TAS571X_IC_DELAY_CH4_REG, 0x54}, + {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30}, + {TAS571X_START_STOP_PERIOD_REG, 0x0f}, + {TAS571X_OSC_TRIM_REG, 0x82}, + {TAS571X_BKND_ERR_REG, 0x02}, + {TAS571X_INPUT_MUX_REG, 0x17772}, + {TAS571X_CH4_SRC_SELECT_REG, 0x4303}, + {TAS571X_PWM_MUX_REG, 0x1021345}, +}; + +static const struct regmap_config tas5721_regmap_config = { + .reg_bits = 8, + .val_bits = 32, + .max_register = 0xff, + .reg_read = tas571x_reg_read, + .reg_write = tas571x_reg_write, + .reg_defaults = tas5721_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tas5721_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .wr_table = &tas571x_write_regs, + .volatile_table = &tas571x_volatile_regs, +}; + + +static const struct tas571x_chip tas5721_chip = { + .supply_names = tas5721_supply_names, + .num_supply_names = ARRAY_SIZE(tas5721_supply_names), + .controls = tas5711_controls, + .num_controls = ARRAY_SIZE(tas5711_controls), + .regmap_config = &tas5721_regmap_config, + .vol_reg_size = 1, +}; + static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = { SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), @@ -527,6 +601,7 @@ static const struct of_device_id tas571x_of_match[] = { { .compatible = "ti,tas5711", .data = &tas5711_chip, }, { .compatible = "ti,tas5717", .data = &tas5717_chip, }, { .compatible = "ti,tas5719", .data = &tas5717_chip, }, + { .compatible = "ti,tas5721", .data = &tas5721_chip, }, { } }; MODULE_DEVICE_TABLE(of, tas571x_of_match); @@ -535,6 +610,7 @@ static const struct i2c_device_id tas571x_i2c_id[] = { { "tas5711", (kernel_ulong_t) &tas5711_chip }, { "tas5717", (kernel_ulong_t) &tas5717_chip }, { "tas5719", (kernel_ulong_t) &tas5717_chip }, + { "tas5721", (kernel_ulong_t) &tas5721_chip }, { } }; MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); -- GitLab From a42121b7a1d80a0eaac9ed1442760bf4e65f5352 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Thu, 31 Mar 2016 18:41:27 +0200 Subject: [PATCH 0998/9938] ASoC: tas571x: new chip added into TAS571x binding This adds the TAS5721 into the TAS571x binding. Signed-off-by: Petr Kulhavy Reviewed-by: Kevin Cernekee Acked-by: Rob Herring Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/tas571x.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt b/Documentation/devicetree/bindings/sound/tas571x.txt index 0ac31d8d5ac4..b4959f10b74b 100644 --- a/Documentation/devicetree/bindings/sound/tas571x.txt +++ b/Documentation/devicetree/bindings/sound/tas571x.txt @@ -1,4 +1,4 @@ -Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers +Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 stereo power amplifiers The codec is controlled through an I2C interface. It also has two other signals that can be wired up to GPIOs: reset (strongly recommended), and @@ -6,7 +6,11 @@ powerdown (optional). Required properties: -- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719" +- compatible: should be one of the following: + - "ti,tas5711", + - "ti,tas5717", + - "ti,tas5719", + - "ti,tas5721" - reg: The I2C address of the device - #sound-dai-cells: must be equal to 0 @@ -25,6 +29,8 @@ Optional properties: - PVDD_B-supply: regulator phandle for the PVDD_B supply (5711) - PVDD_C-supply: regulator phandle for the PVDD_C supply (5711) - PVDD_D-supply: regulator phandle for the PVDD_D supply (5711) +- DRVDD-supply: regulator phandle for the DRVDD supply (5721) +- PVDD-supply: regulator phandle for the PVDD supply (5721) Example: -- GitLab From 2cf7b99cf74b435f27e48aa2829300c4d0aa65a0 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 30 Mar 2016 18:57:49 -0700 Subject: [PATCH 0999/9938] regulator: qcom_spmi: Add slewing delays for all SMPS types Only the FT SMPS type regulators have slewing supported in the driver, but all types of SMPS regulators need the same support. The only difference is that some SMPS regulators don't have a step size and the step delay is typically 20, not 8. Luckily, the step size reads as 0 for the non-FT types, so we can always read that, but we need to detect which type of regulator we're using to figure out what step delay to use. Make these minor adjustments to the slew rate calculations and add support for the delay function to the appropriate regulator ops. Reported-by: Georgi Djakov Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 29 ++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 3550f7f7c2eb..fdea94c5a016 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -246,6 +246,7 @@ enum spmi_common_control_register_index { /* Minimum voltage stepper delay for each step. */ #define SPMI_FTSMPS_STEP_DELAY 8 +#define SPMI_DEFAULT_STEP_DELAY 20 /* * The ratio SPMI_FTSMPS_STEP_MARGIN_NUM/SPMI_FTSMPS_STEP_MARGIN_DEN is used to @@ -1008,6 +1009,7 @@ static struct regulator_ops spmi_smps_ops = { .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, .set_voltage = spmi_regulator_common_set_voltage, + .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, .get_voltage = spmi_regulator_common_get_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, @@ -1081,6 +1083,7 @@ static struct regulator_ops spmi_ult_lo_smps_ops = { .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, .set_voltage = spmi_regulator_ult_lo_smps_set_voltage, + .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, .get_voltage = spmi_regulator_ult_lo_smps_get_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, @@ -1094,6 +1097,7 @@ static struct regulator_ops spmi_ult_ho_smps_ops = { .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, .set_voltage = spmi_regulator_single_range_set_voltage, + .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, .get_voltage = spmi_regulator_single_range_get_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, @@ -1245,11 +1249,11 @@ static int spmi_regulator_match(struct spmi_regulator *vreg, u16 force_type) return 0; } -static int spmi_regulator_ftsmps_init_slew_rate(struct spmi_regulator *vreg) +static int spmi_regulator_init_slew_rate(struct spmi_regulator *vreg) { int ret; u8 reg = 0; - int step, delay, slew_rate; + int step, delay, slew_rate, step_delay; const struct spmi_voltage_range *range; ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, ®, 1); @@ -1262,6 +1266,15 @@ static int spmi_regulator_ftsmps_init_slew_rate(struct spmi_regulator *vreg) if (!range) return -EINVAL; + switch (vreg->logical_type) { + case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS: + step_delay = SPMI_FTSMPS_STEP_DELAY; + break; + default: + step_delay = SPMI_DEFAULT_STEP_DELAY; + break; + } + step = reg & SPMI_FTSMPS_STEP_CTRL_STEP_MASK; step >>= SPMI_FTSMPS_STEP_CTRL_STEP_SHIFT; @@ -1270,7 +1283,7 @@ static int spmi_regulator_ftsmps_init_slew_rate(struct spmi_regulator *vreg) /* slew_rate has units of uV/us */ slew_rate = SPMI_FTSMPS_CLOCK_RATE * range->step_uV * (1 << step); - slew_rate /= 1000 * (SPMI_FTSMPS_STEP_DELAY << delay); + slew_rate /= 1000 * (step_delay << delay); slew_rate *= SPMI_FTSMPS_STEP_MARGIN_NUM; slew_rate /= SPMI_FTSMPS_STEP_MARGIN_DEN; @@ -1411,10 +1424,16 @@ static int spmi_regulator_of_parse(struct device_node *node, return ret; } - if (vreg->logical_type == SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS) { - ret = spmi_regulator_ftsmps_init_slew_rate(vreg); + switch (vreg->logical_type) { + case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: + ret = spmi_regulator_init_slew_rate(vreg); if (ret) return ret; + default: + break; } if (vreg->logical_type != SPMI_REGULATOR_LOGICAL_TYPE_VS) -- GitLab From 1b5b19689278069844f0f65bba8ea55facad90f9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 30 Mar 2016 18:57:50 -0700 Subject: [PATCH 1000/9938] regulator: qcom_spmi: Only use selector based regulator ops Mixing raw voltage and selector based regulator ops is inconsistent. This driver already supports some selector based ops via the list_voltage and set_voltage_time_sel ops but it uses raw voltage ops for get_voltage and set_voltage. This causes problems for regulator_set_voltage() and automatic insertion of slewing delays because set_voltage_time_sel() is only used if the regulator ops are all selector based. Put another way, delays aren't happening at all right now when we should be waiting for voltages to settle. Let's move to pure selector based regulator ops so that the delays are inserted properly. Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 189 ++++++++++++++---------- 1 file changed, 113 insertions(+), 76 deletions(-) diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index fdea94c5a016..f502f2cc65d8 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -255,13 +255,6 @@ enum spmi_common_control_register_index { #define SPMI_FTSMPS_STEP_MARGIN_NUM 4 #define SPMI_FTSMPS_STEP_MARGIN_DEN 5 -/* - * This voltage in uV is returned by get_voltage functions when there is no way - * to determine the current voltage level. It is needed because the regulator - * framework treats a 0 uV voltage as an error. - */ -#define VOLTAGE_UNKNOWN 1 - /* VSET value to decide the range of ULT SMPS */ #define ULT_SMPS_RANGE_SPLIT 0x60 @@ -540,12 +533,12 @@ static int spmi_regulator_common_disable(struct regulator_dev *rdev) } static int spmi_regulator_select_voltage(struct spmi_regulator *vreg, - int min_uV, int max_uV, u8 *range_sel, u8 *voltage_sel, - unsigned *selector) + int min_uV, int max_uV) { const struct spmi_voltage_range *range; int uV = min_uV; int lim_min_uV, lim_max_uV, i, range_id, range_max_uV; + int selector, voltage_sel; /* Check if request voltage is outside of physically settable range. */ lim_min_uV = vreg->set_points->range[0].set_point_min_uV; @@ -571,14 +564,13 @@ static int spmi_regulator_select_voltage(struct spmi_regulator *vreg, range_id = i; range = &vreg->set_points->range[range_id]; - *range_sel = range->range_sel; /* * Force uV to be an allowed set point by applying a ceiling function to * the uV value. */ - *voltage_sel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); - uV = *voltage_sel * range->step_uV + range->min_uV; + voltage_sel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); + uV = voltage_sel * range->step_uV + range->min_uV; if (uV > max_uV) { dev_err(vreg->dev, @@ -588,12 +580,48 @@ static int spmi_regulator_select_voltage(struct spmi_regulator *vreg, return -EINVAL; } - *selector = 0; + selector = 0; for (i = 0; i < range_id; i++) - *selector += vreg->set_points->range[i].n_voltages; - *selector += (uV - range->set_point_min_uV) / range->step_uV; + selector += vreg->set_points->range[i].n_voltages; + selector += (uV - range->set_point_min_uV) / range->step_uV; - return 0; + return selector; +} + +static int spmi_sw_selector_to_hw(struct spmi_regulator *vreg, + unsigned selector, u8 *range_sel, + u8 *voltage_sel) +{ + const struct spmi_voltage_range *range, *end; + + range = vreg->set_points->range; + end = range + vreg->set_points->count; + + for (; range < end; range++) { + if (selector < range->n_voltages) { + *voltage_sel = selector; + *range_sel = range->range_sel; + return 0; + } + + selector -= range->n_voltages; + } + + return -EINVAL; +} + +static int spmi_hw_selector_to_sw(struct spmi_regulator *vreg, u8 hw_sel, + const struct spmi_voltage_range *range) +{ + int sw_sel = hw_sel; + const struct spmi_voltage_range *r = vreg->set_points->range; + + while (r != range) { + sw_sel += r->n_voltages; + r++; + } + + return sw_sel; } static const struct spmi_voltage_range * @@ -615,12 +643,11 @@ spmi_regulator_find_range(struct spmi_regulator *vreg) } static int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, - int min_uV, int max_uV, u8 *range_sel, u8 *voltage_sel, - unsigned *selector) + int min_uV, int max_uV) { const struct spmi_voltage_range *range; int uV = min_uV; - int i; + int i, selector; range = spmi_regulator_find_range(vreg); if (!range) @@ -638,8 +665,8 @@ static int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, * Force uV to be an allowed set point by applying a ceiling function to * the uV value. */ - *voltage_sel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); - uV = *voltage_sel * range->step_uV + range->min_uV; + uV = DIV_ROUND_UP(uV - range->min_uV, range->step_uV); + uV = uV * range->step_uV + range->min_uV; if (uV > max_uV) { /* @@ -649,43 +676,49 @@ static int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, goto different_range; } - *selector = 0; + selector = 0; for (i = 0; i < vreg->set_points->count; i++) { if (uV >= vreg->set_points->range[i].set_point_min_uV && uV <= vreg->set_points->range[i].set_point_max_uV) { - *selector += + selector += (uV - vreg->set_points->range[i].set_point_min_uV) / vreg->set_points->range[i].step_uV; break; } - *selector += vreg->set_points->range[i].n_voltages; + selector += vreg->set_points->range[i].n_voltages; } - if (*selector >= vreg->set_points->n_voltages) + if (selector >= vreg->set_points->n_voltages) goto different_range; return 0; different_range: - return spmi_regulator_select_voltage(vreg, min_uV, max_uV, - range_sel, voltage_sel, selector); + return spmi_regulator_select_voltage(vreg, min_uV, max_uV); } -static int spmi_regulator_common_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int spmi_regulator_common_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); - int ret; - u8 buf[2]; - u8 range_sel, voltage_sel; /* * Favor staying in the current voltage range if possible. This avoids * voltage spikes that occur when changing the voltage range. */ - ret = spmi_regulator_select_voltage_same_range(vreg, min_uV, max_uV, - &range_sel, &voltage_sel, selector); + return spmi_regulator_select_voltage_same_range(vreg, min_uV, max_uV); +} + +static int +spmi_regulator_common_set_voltage(struct regulator_dev *rdev, unsigned selector) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + int ret; + u8 buf[2]; + u8 range_sel, voltage_sel; + + ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); if (ret) return ret; @@ -720,24 +753,24 @@ static int spmi_regulator_common_get_voltage(struct regulator_dev *rdev) range = spmi_regulator_find_range(vreg); if (!range) - return VOLTAGE_UNKNOWN; + return -EINVAL; - return range->step_uV * voltage_sel + range->min_uV; + return spmi_hw_selector_to_sw(vreg, voltage_sel, range); } -static int spmi_regulator_single_range_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int spmi_regulator_single_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); - int ret; - u8 range_sel, sel; - ret = spmi_regulator_select_voltage(vreg, min_uV, max_uV, &range_sel, - &sel, selector); - if (ret) { - dev_err(vreg->dev, "could not set voltage, ret=%d\n", ret); - return ret; - } + return spmi_regulator_select_voltage(vreg, min_uV, max_uV); +} + +static int spmi_regulator_single_range_set_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + u8 sel = selector; /* * Certain types of regulators do not have a range select register so @@ -749,27 +782,24 @@ static int spmi_regulator_single_range_set_voltage(struct regulator_dev *rdev, static int spmi_regulator_single_range_get_voltage(struct regulator_dev *rdev) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); - const struct spmi_voltage_range *range = vreg->set_points->range; - u8 voltage_sel; + u8 selector; + int ret; - spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &voltage_sel, 1); + ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_SET, &selector, 1); + if (ret) + return ret; - return range->step_uV * voltage_sel + range->min_uV; + return selector; } static int spmi_regulator_ult_lo_smps_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + unsigned selector) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); int ret; u8 range_sel, voltage_sel; - /* - * Favor staying in the current voltage range if possible. This avoids - * voltage spikes that occur when changing the voltage range. - */ - ret = spmi_regulator_select_voltage_same_range(vreg, min_uV, max_uV, - &range_sel, &voltage_sel, selector); + ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); if (ret) return ret; @@ -784,7 +814,7 @@ static int spmi_regulator_ult_lo_smps_set_voltage(struct regulator_dev *rdev, voltage_sel |= ULT_SMPS_RANGE_SPLIT; return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_VOLTAGE_SET, - voltage_sel, 0xff); + voltage_sel, 0xff); } static int spmi_regulator_ult_lo_smps_get_voltage(struct regulator_dev *rdev) @@ -797,12 +827,12 @@ static int spmi_regulator_ult_lo_smps_get_voltage(struct regulator_dev *rdev) range = spmi_regulator_find_range(vreg); if (!range) - return VOLTAGE_UNKNOWN; + return -EINVAL; if (range->range_sel == 1) voltage_sel &= ~ULT_SMPS_RANGE_SPLIT; - return range->step_uV * voltage_sel + range->min_uV; + return spmi_hw_selector_to_sw(vreg, voltage_sel, range); } static int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, @@ -1008,9 +1038,10 @@ static struct regulator_ops spmi_smps_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_common_set_voltage, + .set_voltage_sel = spmi_regulator_common_set_voltage, .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, - .get_voltage = spmi_regulator_common_get_voltage, + .get_voltage_sel = spmi_regulator_common_get_voltage, + .map_voltage = spmi_regulator_common_map_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, .get_mode = spmi_regulator_common_get_mode, @@ -1022,8 +1053,9 @@ static struct regulator_ops spmi_ldo_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_common_set_voltage, - .get_voltage = spmi_regulator_common_get_voltage, + .set_voltage_sel = spmi_regulator_common_set_voltage, + .get_voltage_sel = spmi_regulator_common_get_voltage, + .map_voltage = spmi_regulator_common_map_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, .get_mode = spmi_regulator_common_get_mode, @@ -1038,8 +1070,9 @@ static struct regulator_ops spmi_ln_ldo_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_common_set_voltage, - .get_voltage = spmi_regulator_common_get_voltage, + .set_voltage_sel = spmi_regulator_common_set_voltage, + .get_voltage_sel = spmi_regulator_common_get_voltage, + .map_voltage = spmi_regulator_common_map_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_bypass = spmi_regulator_common_set_bypass, .get_bypass = spmi_regulator_common_get_bypass, @@ -1058,8 +1091,9 @@ static struct regulator_ops spmi_boost_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_single_range_set_voltage, - .get_voltage = spmi_regulator_single_range_get_voltage, + .set_voltage_sel = spmi_regulator_single_range_set_voltage, + .get_voltage_sel = spmi_regulator_single_range_get_voltage, + .map_voltage = spmi_regulator_single_map_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_input_current_limit = spmi_regulator_set_ilim, }; @@ -1068,9 +1102,10 @@ static struct regulator_ops spmi_ftsmps_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_common_set_voltage, + .set_voltage_sel = spmi_regulator_common_set_voltage, .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, - .get_voltage = spmi_regulator_common_get_voltage, + .get_voltage_sel = spmi_regulator_common_get_voltage, + .map_voltage = spmi_regulator_common_map_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, .get_mode = spmi_regulator_common_get_mode, @@ -1082,9 +1117,9 @@ static struct regulator_ops spmi_ult_lo_smps_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_ult_lo_smps_set_voltage, + .set_voltage_sel = spmi_regulator_ult_lo_smps_set_voltage, .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, - .get_voltage = spmi_regulator_ult_lo_smps_get_voltage, + .get_voltage_sel = spmi_regulator_ult_lo_smps_get_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, .get_mode = spmi_regulator_common_get_mode, @@ -1096,9 +1131,10 @@ static struct regulator_ops spmi_ult_ho_smps_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_single_range_set_voltage, + .set_voltage_sel = spmi_regulator_single_range_set_voltage, .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, - .get_voltage = spmi_regulator_single_range_get_voltage, + .get_voltage_sel = spmi_regulator_single_range_get_voltage, + .map_voltage = spmi_regulator_single_map_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, .get_mode = spmi_regulator_common_get_mode, @@ -1110,8 +1146,9 @@ static struct regulator_ops spmi_ult_ldo_ops = { .enable = spmi_regulator_common_enable, .disable = spmi_regulator_common_disable, .is_enabled = spmi_regulator_common_is_enabled, - .set_voltage = spmi_regulator_single_range_set_voltage, - .get_voltage = spmi_regulator_single_range_get_voltage, + .set_voltage_sel = spmi_regulator_single_range_set_voltage, + .get_voltage_sel = spmi_regulator_single_range_get_voltage, + .map_voltage = spmi_regulator_single_map_voltage, .list_voltage = spmi_regulator_common_list_voltage, .set_mode = spmi_regulator_common_set_mode, .get_mode = spmi_regulator_common_get_mode, -- GitLab From ea4d25d5a3709cba0d3df2195edffc400170394f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 31 Mar 2016 19:23:14 +0100 Subject: [PATCH 1001/9938] ASoC: qcom: Fix uninitialized symbol warning. This patch fixes following static checker warning, by initializing the ret to -EINVAL, as one of the code path in lpass_platform_pcm_new() uses this variable uninitialized. sound/soc/qcom/lpass-platform.c:555 lpass_platform_pcm_new() error: uninitialized symbol 'ret'. Reported-by: Dan Carpenter Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 6e8665430bd5..f5cae01d18bd 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -474,7 +474,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; - int ret; + int ret = -EINVAL; struct lpass_pcm_data *data; size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; -- GitLab From cef794f76485f4a4e6affd851ae9f9d0eb4287a5 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 31 Mar 2016 19:23:15 +0100 Subject: [PATCH 1002/9938] ASoC: qcom: remove IS_ERR_VALUE usage on int. IS_ERR_VALUE should be used only with unsigned long type, signed types should use comparison 'ret < 0' This patch removes such usages. Reported-by: Dan Carpenter Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-platform.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index f5cae01d18bd..db000c6987a1 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -491,7 +491,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) data->rdma_ch = v->alloc_dma_channel(drvdata, SNDRV_PCM_STREAM_PLAYBACK); - if (IS_ERR_VALUE(data->rdma_ch)) + if (data->rdma_ch < 0) return data->rdma_ch; drvdata->substream[data->rdma_ch] = psubstream; @@ -518,8 +518,10 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) data->wrdma_ch = v->alloc_dma_channel(drvdata, SNDRV_PCM_STREAM_CAPTURE); - if (IS_ERR_VALUE(data->wrdma_ch)) + if (data->wrdma_ch < 0) { + ret = data->wrdma_ch; goto capture_alloc_err; + } drvdata->substream[data->wrdma_ch] = csubstream; -- GitLab From 564f5d6e92d16ad893b4b5bad520bba6a3008b09 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 31 Mar 2016 10:18:35 -0400 Subject: [PATCH 1003/9938] staging: lustre: libcfs: move add_wait_queue_exclusive_head to lustre layer Only lustre client uses add_wait_queue_exclusive_head() so move it from libcfs layer to lustre_lib.h where it is needed. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13874 Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_prim.h | 2 -- .../lustre/lnet/libcfs/linux/linux-prim.c | 24 ------------------- .../lustre/lustre/include/lustre_lib.h | 22 +++++++++++++++++ 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h index 082fe6de90e4..d7846e86f925 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h @@ -40,8 +40,6 @@ #ifndef __LIBCFS_PRIM_H__ #define __LIBCFS_PRIM_H__ -void add_wait_queue_exclusive_head(wait_queue_head_t *, wait_queue_t *); - /* * Memory */ diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c index 7e5ef0a20f93..bbe19a684c81 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-prim.c @@ -46,30 +46,6 @@ #include #endif -/** - * wait_queue_t of Linux (version < 2.6.34) is a FIFO list for exclusively - * waiting threads, which is not always desirable because all threads will - * be waken up again and again, even user only needs a few of them to be - * active most time. This is not good for performance because cache can - * be polluted by different threads. - * - * LIFO list can resolve this problem because we always wakeup the most - * recent active thread by default. - * - * NB: please don't call non-exclusive & exclusive wait on the same - * waitq if add_wait_queue_exclusive_head is used. - */ -void -add_wait_queue_exclusive_head(wait_queue_head_t *waitq, wait_queue_t *link) -{ - unsigned long flags; - - spin_lock_irqsave(&waitq->lock, flags); - __add_wait_queue_exclusive(waitq, link); - spin_unlock_irqrestore(&waitq->lock, flags); -} -EXPORT_SYMBOL(add_wait_queue_exclusive_head); - sigset_t cfs_block_allsigs(void) { diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 2e66b271b6e9..00b976766aef 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -522,6 +522,28 @@ struct l_wait_info { sigmask(SIGTERM) | sigmask(SIGQUIT) | \ sigmask(SIGALRM)) +/** + * wait_queue_t of Linux (version < 2.6.34) is a FIFO list for exclusively + * waiting threads, which is not always desirable because all threads will + * be waken up again and again, even user only needs a few of them to be + * active most time. This is not good for performance because cache can + * be polluted by different threads. + * + * LIFO list can resolve this problem because we always wakeup the most + * recent active thread by default. + * + * NB: please don't call non-exclusive & exclusive wait on the same + * waitq if add_wait_queue_exclusive_head is used. + */ +#define add_wait_queue_exclusive_head(waitq, link) \ +{ \ + unsigned long flags; \ + \ + spin_lock_irqsave(&((waitq)->lock), flags); \ + __add_wait_queue_exclusive(waitq, link); \ + spin_unlock_irqrestore(&((waitq)->lock), flags); \ +} + /* * wait for @condition to become true, but no longer than timeout, specified * by @info. -- GitLab From bd6e2c5067ad6ead097ada26e899ba97266a8bf0 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 31 Mar 2016 10:18:36 -0400 Subject: [PATCH 1004/9938] staging: lustre: libcfs: move memory_pressure functions to libcfs_prim.h Long ago libcfs_prim.h was used for userland code which is why memory_pressure_*() handling is in both libcfs_prim.h and linux-mem.h headers. So lets just move the memory_pressure_*() to libcfs_prim.h. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13841 Reviewed-by: frank zago Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_prim.h | 23 +++++++++++-------- .../include/linux/libcfs/linux/linux-mem.h | 4 ---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h index d7846e86f925..d97060b8be74 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h @@ -43,15 +43,20 @@ /* * Memory */ -#ifndef memory_pressure_get -#define memory_pressure_get() (0) -#endif -#ifndef memory_pressure_set -#define memory_pressure_set() do {} while (0) -#endif -#ifndef memory_pressure_clr -#define memory_pressure_clr() do {} while (0) -#endif +static inline unsigned int memory_pressure_get(void) +{ + return current->flags & PF_MEMALLOC; +} + +static inline void memory_pressure_set(void) +{ + current->flags |= PF_MEMALLOC; +} + +static inline void memory_pressure_clr(void) +{ + current->flags &= ~PF_MEMALLOC; +} static inline int cfs_memory_pressure_get_and_set(void) { diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h index 448379b2a01e..c50ef8352b10 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h @@ -59,10 +59,6 @@ #define page_index(p) ((p)->index) -#define memory_pressure_get() (current->flags & PF_MEMALLOC) -#define memory_pressure_set() do { current->flags |= PF_MEMALLOC; } while (0) -#define memory_pressure_clr() do { current->flags &= ~PF_MEMALLOC; } while (0) - #if BITS_PER_LONG == 32 /* limit to lowmem on 32-bit systems */ #define NUM_CACHEPAGES \ -- GitLab From badc9feddfd30096666e22afbda028971a49bfa9 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 31 Mar 2016 10:18:37 -0400 Subject: [PATCH 1005/9938] staging: lustre: libcfs: remove page_index() macro Just use the index field directly for struct page. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13841 Reviewed-by: frank zago Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h | 2 -- drivers/staging/lustre/lustre/llite/vvp_page.c | 2 +- drivers/staging/lustre/lustre/osc/osc_request.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h index c50ef8352b10..12fde3ca5b7b 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h @@ -57,8 +57,6 @@ #include "../libcfs_cpu.h" #endif -#define page_index(p) ((p)->index) - #if BITS_PER_LONG == 32 /* limit to lowmem on 32-bit systems */ #define NUM_CACHEPAGES \ diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 69316c191de6..0c92293dbf2e 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -394,7 +394,7 @@ static int vvp_page_print(const struct lu_env *env, (*printer)(env, cookie, "%lx %d:%d %lx %lu %slru", (long)vmpage->flags, page_count(vmpage), page_mapcount(vmpage), vmpage->private, - page_index(vmpage), + vmpage->index, list_empty(&vmpage->lru) ? "not-" : ""); } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 4d3eed6ee3f7..547539c74a7b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1934,7 +1934,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, pga[i] = &oap->oap_brw_page; pga[i]->off = oap->oap_obj_off + oap->oap_page_off; CDEBUG(0, "put page %p index %lu oap %p flg %x to pga\n", - pga[i]->pg, page_index(oap->oap_page), oap, + pga[i]->pg, oap->oap_page->index, oap, pga[i]->flag); i++; cl_req_page_add(env, clerq, page); -- GitLab From e3e30e10c5d72844f020fe42e62066e9fd1b051c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 31 Mar 2016 10:18:38 -0400 Subject: [PATCH 1006/9938] staging: lustre: libcfs: remove MMSPACE macros Another abstraction that is not needed. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13841 Reviewed-by: frank zago Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/linux/linux-mem.h | 5 ----- drivers/staging/lustre/lnet/libcfs/tracefile.c | 17 ++++++++--------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h index 12fde3ca5b7b..c4b428478c73 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h @@ -65,9 +65,4 @@ #define NUM_CACHEPAGES totalram_pages #endif -#define DECL_MMSPACE mm_segment_t __oldfs -#define MMSPACE_OPEN \ - do { __oldfs = get_fs(); set_fs(get_ds()); } while (0) -#define MMSPACE_CLOSE set_fs(__oldfs) - #endif /* __LINUX_CFS_MEM_H__ */ diff --git a/drivers/staging/lustre/lnet/libcfs/tracefile.c b/drivers/staging/lustre/lnet/libcfs/tracefile.c index ec3bc04bd89f..5169597e2c34 100644 --- a/drivers/staging/lustre/lnet/libcfs/tracefile.c +++ b/drivers/staging/lustre/lnet/libcfs/tracefile.c @@ -707,10 +707,9 @@ int cfs_tracefile_dump_all_pages(char *filename) struct cfs_trace_page *tage; struct cfs_trace_page *tmp; char *buf; + mm_segment_t __oldfs; int rc; - DECL_MMSPACE; - cfs_tracefile_write_lock(); filp = filp_open(filename, O_CREAT | O_EXCL | O_WRONLY | O_LARGEFILE, @@ -729,11 +728,12 @@ int cfs_tracefile_dump_all_pages(char *filename) rc = 0; goto close; } + __oldfs = get_fs(); + set_fs(get_ds()); /* ok, for now, just write the pages. in the future we'll be building * iobufs with the pages and calling generic_direct_IO */ - MMSPACE_OPEN; list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { __LASSERT_TAGE_INVARIANT(tage); @@ -752,7 +752,7 @@ int cfs_tracefile_dump_all_pages(char *filename) list_del(&tage->linkage); cfs_tage_free(tage); } - MMSPACE_CLOSE; + set_fs(__oldfs); rc = vfs_fsync(filp, 1); if (rc) pr_err("sync returns %d\n", rc); @@ -986,13 +986,12 @@ static int tracefiled(void *arg) struct tracefiled_ctl *tctl = arg; struct cfs_trace_page *tage; struct cfs_trace_page *tmp; + mm_segment_t __oldfs; struct file *filp; char *buf; int last_loop = 0; int rc; - DECL_MMSPACE; - /* we're started late enough that we pick up init's fs context */ /* this is so broken in uml? what on earth is going on? */ @@ -1025,8 +1024,8 @@ static int tracefiled(void *arg) __LASSERT(list_empty(&pc.pc_pages)); goto end_loop; } - - MMSPACE_OPEN; + __oldfs = get_fs(); + set_fs(get_ds()); list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { static loff_t f_pos; @@ -1051,7 +1050,7 @@ static int tracefiled(void *arg) break; } } - MMSPACE_CLOSE; + set_fs(__oldfs); filp_close(filp, NULL); put_pages_on_daemon_list(&pc); -- GitLab From 5c89dc06eb45bebe4dcc59205ac0ed3fe3c44c34 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 31 Mar 2016 10:18:39 -0400 Subject: [PATCH 1007/9938] staging: lustre: libcfs: move NUM_CACHEPAGES to libcfs_prim.h We don't really need linux specific headers anymore so move NUM_CACHEPAGES macro to libcfs_prim.h. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13841 Reviewed-by: frank zago Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h | 8 ++++++++ .../staging/lustre/include/linux/libcfs/linux/linux-mem.h | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h index d97060b8be74..6f7a276b87b7 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h @@ -43,6 +43,14 @@ /* * Memory */ +#if BITS_PER_LONG == 32 +/* limit to lowmem on 32-bit systems */ +#define NUM_CACHEPAGES \ + min(totalram_pages, 1UL << (30 - PAGE_CACHE_SHIFT) * 3 / 4) +#else +#define NUM_CACHEPAGES totalram_pages +#endif + static inline unsigned int memory_pressure_get(void) { return current->flags & PF_MEMALLOC; diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h index c4b428478c73..9285fefcdf79 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h @@ -57,12 +57,4 @@ #include "../libcfs_cpu.h" #endif -#if BITS_PER_LONG == 32 -/* limit to lowmem on 32-bit systems */ -#define NUM_CACHEPAGES \ - min(totalram_pages, 1UL << (30 - PAGE_CACHE_SHIFT) * 3 / 4) -#else -#define NUM_CACHEPAGES totalram_pages -#endif - #endif /* __LINUX_CFS_MEM_H__ */ -- GitLab From 899e1a31ffc0cf01b1ca7512e079721b79803929 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 31 Mar 2016 10:18:40 -0400 Subject: [PATCH 1008/9938] staging: lustre: libcfs: delete linux-mem.h The header linux-mem.h is no longer needed. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/13841 Reviewed-by: frank zago Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/linux/libcfs.h | 2 +- .../include/linux/libcfs/linux/linux-cpu.h | 2 +- .../include/linux/libcfs/linux/linux-mem.h | 60 ------------------- 3 files changed, 2 insertions(+), 62 deletions(-) delete mode 100644 drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h index d94b2661658a..a268ef7aa19d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,6 @@ #include #include "linux-cpu.h" #include "linux-time.h" -#include "linux-mem.h" #define LUSTRE_TRACE_SIZE (THREAD_SIZE >> 5) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h index c04979ae0a38..f63cb47bc309 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h @@ -23,7 +23,7 @@ * This file is part of Lustre, http://www.lustre.org/ * Lustre is a trademark of Sun Microsystems, Inc. * - * libcfs/include/libcfs/linux/linux-mem.h + * libcfs/include/libcfs/linux/linux-cpu.h * * Basic library routines. * diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h deleted file mode 100644 index 9285fefcdf79..000000000000 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * libcfs/include/libcfs/linux/linux-mem.h - * - * Basic library routines. - */ - -#ifndef __LIBCFS_LINUX_CFS_MEM_H__ -#define __LIBCFS_LINUX_CFS_MEM_H__ - -#ifndef __LIBCFS_LIBCFS_H__ -#error Do not #include this file directly. #include instead -#endif - -#include -#include -#include -#include -#include -#include - -#ifndef HAVE_LIBCFS_CPT -/* Need this for cfs_cpt_table */ -#include "../libcfs_cpu.h" -#endif - -#endif /* __LINUX_CFS_MEM_H__ */ -- GitLab From 1f2f03c201d4df0035268f8cbecb31bf58f59355 Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Wed, 30 Mar 2016 23:06:08 -0400 Subject: [PATCH 1009/9938] staging: unisys: visorbus: remove unnecessary poll_count logic The use of poll_count is a vestige from long-ago testing, which is no longer needed. It is removed by this patch. Signed-off-by: Tim Sell Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 17bedbc6761d..61877722b1da 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1868,18 +1868,11 @@ controlvm_periodic_work(struct work_struct *work) struct controlvm_message inmsg; bool got_command = false; bool handle_command_failed = false; - static u64 poll_count; /* make sure visorbus server is registered for controlvm callbacks */ if (visorchipset_visorbusregwait && !visorbusregistered) goto cleanup; - poll_count++; - if (poll_count >= 250) - ; /* keep going */ - else - goto cleanup; - /* Check events to determine if response to CHIPSET_READY * should be sent */ -- GitLab From e491e716dc6a8f43cec7353e5a89e19058f3a48a Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Thu, 31 Mar 2016 17:03:35 +0900 Subject: [PATCH 1010/9938] staging: dgnc: remove useless variables for saving tty's It doesn't need to save major number with variable. And there are no use of these variables(dgnc_serial_major and dgnc_transparent_print_major) Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_driver.h | 3 --- drivers/staging/dgnc/dgnc_tty.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 44216aede109..6609ba5f3e7f 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -210,9 +210,6 @@ struct dgnc_board { bool dgnc_major_serial_registered; bool dgnc_major_transparent_print_registered; - uint dgnc_serial_major; - uint dgnc_transparent_print_major; - u16 dpatype; /* The board "type", * as defined by DPA */ diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 98b88d1a5f04..5097208e6a4d 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -286,8 +286,6 @@ int dgnc_tty_register(struct dgnc_board *brd) } dgnc_BoardsByMajor[brd->serial_driver.major] = brd; - brd->dgnc_serial_major = brd->serial_driver.major; - brd->dgnc_transparent_print_major = brd->print_driver.major; return rc; } @@ -409,7 +407,6 @@ void dgnc_tty_uninit(struct dgnc_board *brd) if (brd->dgnc_major_serial_registered) { dgnc_BoardsByMajor[brd->serial_driver.major] = NULL; - brd->dgnc_serial_major = 0; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> @@ -422,7 +419,6 @@ void dgnc_tty_uninit(struct dgnc_board *brd) if (brd->dgnc_major_transparent_print_registered) { dgnc_BoardsByMajor[brd->print_driver.major] = NULL; - brd->dgnc_transparent_print_major = 0; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> -- GitLab From 56d118c243fbc62d95a79183bb6bcfc38a398da5 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Thu, 31 Mar 2016 17:03:59 +0900 Subject: [PATCH 1011/9938] staging: dgnc: clean up dgnc_input function This is for fixing checkpatch.pl warning about "Alignment should match open parenthesis" but if that is fixed, code line is over 80 characters. I think "ch->ch_rqueue + tail + i" could be declared once in the begining of loop. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_tty.c | 35 +++++++++++++-------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 5097208e6a4d..d617fca682dc 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -602,6 +602,8 @@ void dgnc_input(struct channel_t *ch) * or the amount of data the card actually has pending... */ while (n) { + unsigned char *ch_pos = ch->ch_equeue + tail; + s = ((head >= tail) ? head : RQUEUESIZE) - tail; s = min(s, n); @@ -616,29 +618,20 @@ void dgnc_input(struct channel_t *ch) */ if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { for (i = 0; i < s; i++) { - if (*(ch->ch_equeue + tail + i) & UART_LSR_BI) - tty_insert_flip_char(tp->port, - *(ch->ch_rqueue + tail + i), - TTY_BREAK); - else if (*(ch->ch_equeue + tail + i) & - UART_LSR_PE) - tty_insert_flip_char(tp->port, - *(ch->ch_rqueue + tail + i), - TTY_PARITY); - else if (*(ch->ch_equeue + tail + i) & - UART_LSR_FE) - tty_insert_flip_char(tp->port, - *(ch->ch_rqueue + tail + i), - TTY_FRAME); - else - tty_insert_flip_char(tp->port, - *(ch->ch_rqueue + tail + i), - TTY_NORMAL); + unsigned char ch = *(ch_pos + i); + char flag = TTY_NORMAL; + + if (ch & UART_LSR_BI) + flag = TTY_BREAK; + else if (ch & UART_LSR_PE) + flag = TTY_PARITY; + else if (ch & UART_LSR_FE) + flag = TTY_FRAME; + + tty_insert_flip_char(tp->port, ch, flag); } } else { - tty_insert_flip_string(tp->port, - ch->ch_rqueue + tail, - s); + tty_insert_flip_string(tp->port, ch_pos, s); } tail += s; -- GitLab From 7edf2c9c08dccbad9134b89c2252594d9659b59e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 31 Mar 2016 10:59:41 -0700 Subject: [PATCH 1012/9938] Input: acecad - stop saving struct usb_device The device can now easily be derived from the interface. Stop leaving a private copy. Signed-off-by: Oliver Neukum Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/acecad.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 889f6b77e8cb..e86e377a90f5 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -49,7 +49,6 @@ MODULE_LICENSE(DRIVER_LICENSE); struct usb_acecad { char name[128]; char phys[64]; - struct usb_device *usbdev; struct usb_interface *intf; struct input_dev *input; struct urb *irq; @@ -64,6 +63,7 @@ static void usb_acecad_irq(struct urb *urb) unsigned char *data = acecad->data; struct input_dev *dev = acecad->input; struct usb_interface *intf = acecad->intf; + struct usb_device *udev = interface_to_usbdev(intf); int prox, status; switch (urb->status) { @@ -110,15 +110,15 @@ static void usb_acecad_irq(struct urb *urb) if (status) dev_err(&intf->dev, "can't resubmit intr, %s-%s/input0, status %d\n", - acecad->usbdev->bus->bus_name, - acecad->usbdev->devpath, status); + udev->bus->bus_name, + udev->devpath, status); } static int usb_acecad_open(struct input_dev *dev) { struct usb_acecad *acecad = input_get_drvdata(dev); - acecad->irq->dev = acecad->usbdev; + acecad->irq->dev = interface_to_usbdev(acecad->intf); if (usb_submit_urb(acecad->irq, GFP_KERNEL)) return -EIO; @@ -172,7 +172,6 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ goto fail2; } - acecad->usbdev = dev; acecad->intf = intf; acecad->input = input_dev; @@ -251,12 +250,13 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ static void usb_acecad_disconnect(struct usb_interface *intf) { struct usb_acecad *acecad = usb_get_intfdata(intf); + struct usb_device *udev = interface_to_usbdev(intf); usb_set_intfdata(intf, NULL); input_unregister_device(acecad->input); usb_free_urb(acecad->irq); - usb_free_coherent(acecad->usbdev, 8, acecad->data, acecad->data_dma); + usb_free_coherent(udev, 8, acecad->data, acecad->data_dma); kfree(acecad); } -- GitLab From c630901860c3b8ecc22097269fd4605cf584126c Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 31 Mar 2016 10:59:59 -0700 Subject: [PATCH 1013/9938] Input: aiptek - stop saving struct usb_device The device can now easily be derived from the interface. Stop leaving a private copy. Signed-off-by: Oliver Neukum Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/aiptek.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 78ca44840d60..4613f0aefd08 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -307,7 +307,6 @@ struct aiptek_settings { struct aiptek { struct input_dev *inputdev; /* input device struct */ - struct usb_device *usbdev; /* usb device struct */ struct usb_interface *intf; /* usb interface struct */ struct urb *urb; /* urb for incoming reports */ dma_addr_t data_dma; /* our dma stuffage */ @@ -847,7 +846,7 @@ static int aiptek_open(struct input_dev *inputdev) { struct aiptek *aiptek = input_get_drvdata(inputdev); - aiptek->urb->dev = aiptek->usbdev; + aiptek->urb->dev = interface_to_usbdev(aiptek->intf); if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) return -EIO; @@ -873,8 +872,10 @@ aiptek_set_report(struct aiptek *aiptek, unsigned char report_type, unsigned char report_id, void *buffer, int size) { - return usb_control_msg(aiptek->usbdev, - usb_sndctrlpipe(aiptek->usbdev, 0), + struct usb_device *udev = interface_to_usbdev(aiptek->intf); + + return usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, (report_type << 8) + report_id, @@ -886,8 +887,10 @@ aiptek_get_report(struct aiptek *aiptek, unsigned char report_type, unsigned char report_id, void *buffer, int size) { - return usb_control_msg(aiptek->usbdev, - usb_rcvctrlpipe(aiptek->usbdev, 0), + struct usb_device *udev = interface_to_usbdev(aiptek->intf); + + return usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, (report_type << 8) + report_id, @@ -1729,7 +1732,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) } aiptek->inputdev = inputdev; - aiptek->usbdev = usbdev; aiptek->intf = intf; aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber; aiptek->inDelay = 0; @@ -1833,8 +1835,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) * input. */ usb_fill_int_urb(aiptek->urb, - aiptek->usbdev, - usb_rcvintpipe(aiptek->usbdev, + usbdev, + usb_rcvintpipe(usbdev, endpoint->bEndpointAddress), aiptek->data, 8, aiptek_irq, aiptek, endpoint->bInterval); -- GitLab From ed752e5ddedb68c9d69484baa1a712cf966e1f22 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 31 Mar 2016 11:01:07 -0700 Subject: [PATCH 1014/9938] Input: gtco - stop saving struct usb_device The device can now easily be derived from the interface. Stop leaving a private copy. Signed-off-by: Oliver Neukum Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/gtco.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 3a7f3a4a4396..362ae3b5e188 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -104,7 +104,6 @@ MODULE_DEVICE_TABLE (usb, gtco_usbid_table); struct gtco { struct input_dev *inputdevice; /* input device struct pointer */ - struct usb_device *usbdev; /* the usb device for this device */ struct usb_interface *intf; /* the usb interface for this device */ struct urb *urbinfo; /* urb for incoming reports */ dma_addr_t buf_dma; /* dma addr of the data buffer*/ @@ -540,7 +539,7 @@ static int gtco_input_open(struct input_dev *inputdev) { struct gtco *device = input_get_drvdata(inputdev); - device->urbinfo->dev = device->usbdev; + device->urbinfo->dev = interface_to_usbdev(device->intf); if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) return -EIO; @@ -824,6 +823,7 @@ static int gtco_probe(struct usb_interface *usbinterface, int result = 0, retry; int error; struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev = interface_to_usbdev(usbinterface); /* Allocate memory for device structure */ gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL); @@ -838,11 +838,10 @@ static int gtco_probe(struct usb_interface *usbinterface, gtco->inputdevice = input_dev; /* Save interface information */ - gtco->usbdev = interface_to_usbdev(usbinterface); gtco->intf = usbinterface; /* Allocate some data for incoming reports */ - gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE, + gtco->buffer = usb_alloc_coherent(udev, REPORT_MAX_SIZE, GFP_KERNEL, >co->buf_dma); if (!gtco->buffer) { dev_err(&usbinterface->dev, "No more memory for us buffers\n"); @@ -899,8 +898,8 @@ static int gtco_probe(struct usb_interface *usbinterface, /* Couple of tries to get reply */ for (retry = 0; retry < 3; retry++) { - result = usb_control_msg(gtco->usbdev, - usb_rcvctrlpipe(gtco->usbdev, 0), + result = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, REPORT_DEVICE_TYPE << 8, @@ -928,7 +927,7 @@ static int gtco_probe(struct usb_interface *usbinterface, } /* Create a device file node */ - usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath)); + usb_make_path(udev, gtco->usbpath, sizeof(gtco->usbpath)); strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath)); /* Set Input device functions */ @@ -945,15 +944,15 @@ static int gtco_probe(struct usb_interface *usbinterface, gtco_setup_caps(input_dev); /* Set input device required ID information */ - usb_to_input_id(gtco->usbdev, &input_dev->id); + usb_to_input_id(udev, &input_dev->id); input_dev->dev.parent = &usbinterface->dev; /* Setup the URB, it will be posted later on open of input device */ endpoint = &usbinterface->altsetting[0].endpoint[0].desc; usb_fill_int_urb(gtco->urbinfo, - gtco->usbdev, - usb_rcvintpipe(gtco->usbdev, + udev, + usb_rcvintpipe(udev, endpoint->bEndpointAddress), gtco->buffer, REPORT_MAX_SIZE, @@ -977,7 +976,7 @@ static int gtco_probe(struct usb_interface *usbinterface, err_free_urb: usb_free_urb(gtco->urbinfo); err_free_buf: - usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, + usb_free_coherent(udev, REPORT_MAX_SIZE, gtco->buffer, gtco->buf_dma); err_free_devs: input_free_device(input_dev); @@ -994,13 +993,14 @@ static void gtco_disconnect(struct usb_interface *interface) { /* Grab private device ptr */ struct gtco *gtco = usb_get_intfdata(interface); + struct usb_device *udev = interface_to_usbdev(interface); /* Now reverse all the registration stuff */ if (gtco) { input_unregister_device(gtco->inputdevice); usb_kill_urb(gtco->urbinfo); usb_free_urb(gtco->urbinfo); - usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, + usb_free_coherent(udev, REPORT_MAX_SIZE, gtco->buffer, gtco->buf_dma); kfree(gtco); } -- GitLab From 8f7292ed88c0a87e4173c5a97fae444ed8b2f05b Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 31 Mar 2016 11:01:48 -0700 Subject: [PATCH 1015/9938] Input: kbtab - stop saving struct usb_device The device can now easily be derived from the interface. Stop leaving a private copy. Signed-off-by: Oliver Neukum Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/kbtab.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index d2ac7c2b5b82..e850d7e8afbc 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -31,7 +31,6 @@ struct kbtab { unsigned char *data; dma_addr_t data_dma; struct input_dev *dev; - struct usb_device *usbdev; struct usb_interface *intf; struct urb *irq; char phys[32]; @@ -99,8 +98,9 @@ MODULE_DEVICE_TABLE(usb, kbtab_ids); static int kbtab_open(struct input_dev *dev) { struct kbtab *kbtab = input_get_drvdata(dev); + struct usb_device *udev = interface_to_usbdev(kbtab->intf); - kbtab->irq->dev = kbtab->usbdev; + kbtab->irq->dev = udev; if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) return -EIO; @@ -135,7 +135,6 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i if (!kbtab->irq) goto fail2; - kbtab->usbdev = dev; kbtab->intf = intf; kbtab->dev = input_dev; @@ -188,12 +187,13 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i static void kbtab_disconnect(struct usb_interface *intf) { struct kbtab *kbtab = usb_get_intfdata(intf); + struct usb_device *udev = interface_to_usbdev(intf); usb_set_intfdata(intf, NULL); input_unregister_device(kbtab->dev); usb_free_urb(kbtab->irq); - usb_free_coherent(kbtab->usbdev, 8, kbtab->data, kbtab->data_dma); + usb_free_coherent(udev, 8, kbtab->data, kbtab->data_dma); kfree(kbtab); } -- GitLab From 7d8d86252307ce34925c5ddec4ef1b32670353b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 31 Mar 2016 13:08:06 -0700 Subject: [PATCH 1016/9938] Input: gpio-keys - clean up device tree binding example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop #address-cells and #size-cells, which are not required by the gpio-keys binding documentation, as button sub-nodes are not devices. Rename sub-nodes to avoid new dtc unit address warnings when copied. While at it, adopt the dashes convention for the node name. Reported-by: Julien Chauveau Signed-off-by: Andreas Färber Reviewed-by: Javier Martinez Canillas Reviewed-by: Julien Chauveau Signed-off-by: Dmitry Torokhov --- Documentation/devicetree/bindings/input/gpio-keys.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt b/Documentation/devicetree/bindings/input/gpio-keys.txt index 21641236c095..a94940481e55 100644 --- a/Documentation/devicetree/bindings/input/gpio-keys.txt +++ b/Documentation/devicetree/bindings/input/gpio-keys.txt @@ -32,17 +32,17 @@ Optional subnode-properties: Example nodes: - gpio_keys { + gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; autorepeat; - button@21 { + + up { label = "GPIO Key UP"; linux,code = <103>; gpios = <&gpio1 0 1>; }; - button@22 { + + down { label = "GPIO Key DOWN"; linux,code = <108>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; -- GitLab From 274529ba9bda86c91c2c06da3a641aaf617dd30f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 21 Mar 2016 19:46:04 -0700 Subject: [PATCH 1017/9938] rcu: Consolidate dumping of ftrace buffer This commit consolidates a couple definitions and several calls for single-shot ftrace-buffer dumping. Signed-off-by: Paul E. McKenney --- include/linux/rcupdate.h | 13 +++++++++++++ kernel/rcu/rcutorture.c | 17 +++-------------- kernel/rcu/tree.c | 4 ++-- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 2657aff2725b..45de591657a6 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -1144,4 +1144,17 @@ static inline void rcu_sysidle_force_exit(void) #endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ +/* + * Dump the ftrace buffer, but only one time per callsite per boot. + */ +#define rcu_ftrace_dump(oops_dump_mode) \ +do { \ + static atomic_t ___rfd_beenhere = ATOMIC_INIT(0); \ + \ + if (!atomic_read(&___rfd_beenhere) && \ + !atomic_xchg(&___rfd_beenhere, 1)) \ + ftrace_dump(oops_dump_mode); \ +} while (0) + + #endif /* __LINUX_RCUPDATE_H */ diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 250ea67c1615..463867c43221 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -1082,17 +1082,6 @@ rcu_torture_fakewriter(void *arg) return 0; } -static void rcutorture_trace_dump(void) -{ - static atomic_t beenhere = ATOMIC_INIT(0); - - if (atomic_read(&beenhere)) - return; - if (atomic_xchg(&beenhere, 1) != 0) - return; - ftrace_dump(DUMP_ALL); -} - /* * RCU torture reader from timer handler. Dereferences rcu_torture_current, * incrementing the corresponding element of the pipeline array. The @@ -1142,7 +1131,7 @@ static void rcu_torture_timer(unsigned long unused) if (pipe_count > 1) { do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts, started, completed); - rcutorture_trace_dump(); + rcu_ftrace_dump(DUMP_ALL); } __this_cpu_inc(rcu_torture_count[pipe_count]); completed = completed - started; @@ -1215,7 +1204,7 @@ rcu_torture_reader(void *arg) if (pipe_count > 1) { do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts, started, completed); - rcutorture_trace_dump(); + rcu_ftrace_dump(DUMP_ALL); } __this_cpu_inc(rcu_torture_count[pipe_count]); completed = completed - started; @@ -1333,7 +1322,7 @@ rcu_torture_stats_print(void) rcu_torture_writer_state, gpnum, completed, flags); show_rcu_gp_kthreads(); - rcutorture_trace_dump(); + rcu_ftrace_dump(DUMP_ALL); } rtcv_snap = rcu_torture_current_version; } diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 9a535a86e732..531a328076bd 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -637,7 +637,7 @@ static void rcu_eqs_enter_common(long long oldval, bool user) idle_task(smp_processor_id()); trace_rcu_dyntick(TPS("Error on entry: not idle task"), oldval, 0); - ftrace_dump(DUMP_ORIG); + rcu_ftrace_dump(DUMP_ORIG); WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", current->pid, current->comm, idle->pid, idle->comm); /* must be idle task! */ @@ -799,7 +799,7 @@ static void rcu_eqs_exit_common(long long oldval, int user) trace_rcu_dyntick(TPS("Error on exit: not idle task"), oldval, rdtp->dynticks_nesting); - ftrace_dump(DUMP_ORIG); + rcu_ftrace_dump(DUMP_ORIG); WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", current->pid, current->comm, idle->pid, idle->comm); /* must be idle task! */ -- GitLab From 70946a44deec299ef54c0ec933e8d82ddd4bcc6a Mon Sep 17 00:00:00 2001 From: Yao Dongdong Date: Mon, 7 Mar 2016 16:02:14 +0800 Subject: [PATCH 1018/9938] documentation: Make sample code and documentation consistent In the chapter 'analogy with reader-writer locking', the sample code uses spinlock_t in reader-writer case. Just correct it so that we can read the document easily. Signed-off-by: Yao Dongdong Signed-off-by: Paul E. McKenney --- Documentation/RCU/whatisRCU.txt | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index dc49c6712b17..111770ffa10e 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -681,22 +681,30 @@ Although RCU can be used in many different ways, a very common use of RCU is analogous to reader-writer locking. The following unified diff shows how closely related RCU and reader-writer locking can be. + @@ -5,5 +5,5 @@ struct el { + int data; + /* Other data fields */ + }; + -rwlock_t listmutex; + +spinlock_t listmutex; + struct el head; + @@ -13,15 +14,15 @@ struct list_head *lp; struct el *p; - - read_lock(); + - read_lock(&listmutex); - list_for_each_entry(p, head, lp) { + rcu_read_lock(); + list_for_each_entry_rcu(p, head, lp) { if (p->key == key) { *result = p->data; - - read_unlock(); + - read_unlock(&listmutex); + rcu_read_unlock(); return 1; } } - - read_unlock(); + - read_unlock(&listmutex); + rcu_read_unlock(); return 0; } @@ -732,7 +740,7 @@ Or, for those who prefer a side-by-side listing: 5 int data; 5 int data; 6 /* Other data fields */ 6 /* Other data fields */ 7 }; 7 }; - 8 spinlock_t listmutex; 8 spinlock_t listmutex; + 8 rwlock_t listmutex; 8 spinlock_t listmutex; 9 struct el head; 9 struct el head; 1 int search(long key, int *result) 1 int search(long key, int *result) @@ -740,15 +748,15 @@ Or, for those who prefer a side-by-side listing: 3 struct list_head *lp; 3 struct list_head *lp; 4 struct el *p; 4 struct el *p; 5 5 - 6 read_lock(); 6 rcu_read_lock(); + 6 read_lock(&listmutex); 6 rcu_read_lock(); 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, head, lp) { 8 if (p->key == key) { 8 if (p->key == key) { 9 *result = p->data; 9 *result = p->data; -10 read_unlock(); 10 rcu_read_unlock(); +10 read_unlock(&listmutex); 10 rcu_read_unlock(); 11 return 1; 11 return 1; 12 } 12 } 13 } 13 } -14 read_unlock(); 14 rcu_read_unlock(); +14 read_unlock(&listmutex); 14 rcu_read_unlock(); 15 return 0; 15 return 0; 16 } 16 } -- GitLab From 41abcf321d447b9987f6b7d1a9bb65831e786daf Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 11 Dec 2015 16:18:22 -0800 Subject: [PATCH 1019/9938] documentation: Add real-time requirements from CPU-bound workloads This commit records RCU's responsibility to avoid degrading latencies of CPUs running tight loops within properly configured workloads, both in kernel and in userspace. Signed-off-by: Paul E. McKenney --- .../RCU/Design/Requirements/Requirements.html | 10 +++++++++- .../RCU/Design/Requirements/Requirements.htmlx | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index a725f9900ec8..3004baa71bcc 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -1,5 +1,5 @@ - + @@ -2170,6 +2170,14 @@ up to and including systems with 4096 CPUs. This real-time requirement motivated the grace-period kthread, which also simplified handling of a number of race conditions. +

+RCU must avoid degrading real-time response for CPU-bound threads, whether +executing in usermode (which is one use case for +CONFIG_NO_HZ_FULL=y) or in the kernel. +That said, CPU-bound loops in the kernel must execute +cond_resched_rcu_qs() at least once per few tens of milliseconds +in order to avoid receiving an IPI from RCU. +

Finally, RCU's status as a synchronization primitive means that any RCU failure can result in arbitrary memory corruption that can be diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx index 3a97ba490c42..61caffc86823 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.htmlx +++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx @@ -2337,6 +2337,14 @@ up to and including systems with 4096 CPUs. This real-time requirement motivated the grace-period kthread, which also simplified handling of a number of race conditions. +

+RCU must avoid degrading real-time response for CPU-bound threads, whether +executing in usermode (which is one use case for +CONFIG_NO_HZ_FULL=y) or in the kernel. +That said, CPU-bound loops in the kernel must execute +cond_resched_rcu_qs() at least once per few tens of milliseconds +in order to avoid receiving an IPI from RCU. +

Finally, RCU's status as a synchronization primitive means that any RCU failure can result in arbitrary memory corruption that can be -- GitLab From f43b62542eb61a52d97d6b82a786a912fa5e6c51 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 7 Jan 2016 09:12:43 -0800 Subject: [PATCH 1020/9938] documentation: Add synchronize_rcu_mult() to the requirements Signed-off-by: Paul E. McKenney --- .../RCU/Design/Requirements/Requirements.html | 92 +++++++++++++++++++ .../Design/Requirements/Requirements.htmlx | 82 +++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 3004baa71bcc..59acd82e67d4 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -2231,6 +2231,8 @@ described in a separate section.

  • Sched Flavor
  • Sleepable RCU
  • Tasks RCU +
  • + Waiting for Multiple Grace Periods

    Bottom-Half Flavor

    @@ -2480,6 +2482,81 @@ The tasks-RCU API is quite compact, consisting only of synchronize_rcu_tasks(), and rcu_barrier_tasks(). +

    +Waiting for Multiple Grace Periods

    + +

    +Perhaps you have an RCU protected data structure that is accessed from +RCU read-side critical sections, from softirq handlers, and from +hardware interrupt handlers. +That is three flavors of RCU, the normal flavor, the bottom-half flavor, +and the sched flavor. +How to wait for a compound grace period? + +

    +The best approach is usually to “just say no!” and +insert rcu_read_lock() and rcu_read_unlock() +around each RCU read-side critical section, regardless of what +environment it happens to be in. +But suppose that some of the RCU read-side critical sections are +on extremely hot code paths, and that use of CONFIG_PREEMPT=n +is not a viable option, so that rcu_read_lock() and +rcu_read_unlock() are not free. +What then? + +

    +You could wait on all three grace periods in succession, as follows: + +

    +
    + 1 synchronize_rcu();
    + 2 synchronize_rcu_bh();
    + 3 synchronize_sched();
    +
    +
    + +

    +This works, but triples the update-side latency penalty. +In cases where this is not acceptable, synchronize_rcu_mult() +may be used to wait on all three flavors of grace period concurrently: + +

    +
    + 1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
    +
    +
    + +

    +But what if it is necessary to also wait on SRCU? +This can be done as follows: + +

    +
    + 1 static void call_my_srcu(struct rcu_head *head,
    + 2        void (*func)(struct rcu_head *head))
    + 3 {
    + 4   call_srcu(&my_srcu, head, func);
    + 5 }
    + 6
    + 7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
    +
    +
    + +

    +If you needed to wait on multiple different flavors of SRCU +(but why???), you would need to create a wrapper function resembling +call_my_srcu() for each SRCU flavor. + +

    Quick Quiz 15: +But what if I need to wait for multiple RCU flavors, but I also need +the grace periods to be expedited? +
    Answer + +

    +Again, it is usually better to adjust the RCU read-side critical sections +to use a single flavor of RCU, but when this is not feasible, you can use +synchronize_rcu_mult(). +

    Possible Future Changes

    @@ -2901,5 +2978,20 @@ during scheduler initialization.

    Back to Quick Quiz 14. + +

    Quick Quiz 15: +But what if I need to wait for multiple RCU flavors, but I also need +the grace periods to be expedited? + + +

    Answer: +If you are using expedited grace periods, there should be less penalty +for waiting on them in succession. +But if that is nevertheless a problem, you can use workqueues or multiple +kthreads to wait on the various expedited grace periods concurrently. + + +

    Back to Quick Quiz 15. + diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx index 61caffc86823..6ff4966672e2 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.htmlx +++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx @@ -2398,6 +2398,8 @@ described in a separate section.

  • Sched Flavor
  • Sleepable RCU
  • Tasks RCU +
  • + Waiting for Multiple Grace Periods

    Bottom-Half Flavor

    @@ -2647,6 +2649,86 @@ The tasks-RCU API is quite compact, consisting only of synchronize_rcu_tasks(), and rcu_barrier_tasks(). +

    +Waiting for Multiple Grace Periods

    + +

    +Perhaps you have an RCU protected data structure that is accessed from +RCU read-side critical sections, from softirq handlers, and from +hardware interrupt handlers. +That is three flavors of RCU, the normal flavor, the bottom-half flavor, +and the sched flavor. +How to wait for a compound grace period? + +

    +The best approach is usually to “just say no!” and +insert rcu_read_lock() and rcu_read_unlock() +around each RCU read-side critical section, regardless of what +environment it happens to be in. +But suppose that some of the RCU read-side critical sections are +on extremely hot code paths, and that use of CONFIG_PREEMPT=n +is not a viable option, so that rcu_read_lock() and +rcu_read_unlock() are not free. +What then? + +

    +You could wait on all three grace periods in succession, as follows: + +

    +
    + 1 synchronize_rcu();
    + 2 synchronize_rcu_bh();
    + 3 synchronize_sched();
    +
    +
    + +

    +This works, but triples the update-side latency penalty. +In cases where this is not acceptable, synchronize_rcu_mult() +may be used to wait on all three flavors of grace period concurrently: + +

    +
    + 1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
    +
    +
    + +

    +But what if it is necessary to also wait on SRCU? +This can be done as follows: + +

    +
    + 1 static void call_my_srcu(struct rcu_head *head,
    + 2        void (*func)(struct rcu_head *head))
    + 3 {
    + 4   call_srcu(&my_srcu, head, func);
    + 5 }
    + 6
    + 7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
    +
    +
    + +

    +If you needed to wait on multiple different flavors of SRCU +(but why???), you would need to create a wrapper function resembling +call_my_srcu() for each SRCU flavor. + +

    @@QQ@@ +But what if I need to wait for multiple RCU flavors, but I also need +the grace periods to be expedited? +

    @@QQA@@ +If you are using expedited grace periods, there should be less penalty +for waiting on them in succession. +But if that is nevertheless a problem, you can use workqueues or multiple +kthreads to wait on the various expedited grace periods concurrently. +

    @@QQE@@ + +

    +Again, it is usually better to adjust the RCU read-side critical sections +to use a single flavor of RCU, but when this is not feasible, you can use +synchronize_rcu_mult(). +

    Possible Future Changes

    -- GitLab From d8936c0b7e29510ce8f5c85ff5fcc592a938e860 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 15 Feb 2016 17:29:47 -0800 Subject: [PATCH 1021/9938] documentation: Explain why rcu_read_lock() needs no barrier() This commit adds a Quick Quiz whose answer explains why the compiler code reordering enabled by CONFIG_PREEMPT=n's empty rcu_read_lock() and rcu_read_unlock() functions does not hinder RCU's ability to figure out which RCU read-side critical sections have completed and not. Signed-off-by: Paul E. McKenney --- .../RCU/Design/Requirements/Requirements.html | 130 ++++++++++++------ .../Design/Requirements/Requirements.htmlx | 28 ++++ 2 files changed, 115 insertions(+), 43 deletions(-) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 59acd82e67d4..2a56031bfdd4 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -583,6 +583,17 @@ The first and second guarantees require unbelievably strict ordering! Are all these memory barriers really required?
    Answer +

    Quick Quiz 7: +You claim that rcu_read_lock() and rcu_read_unlock() +generate absolutely no code in some kernel builds. +This means that the compiler might arbitrarily rearrange consecutive +RCU read-side critical sections. +Given such rearrangement, if a given RCU read-side critical section +is done, how can you be sure that all prior RCU read-side critical +sections are done? +Won't the compiler rearrangements make that impossible to determine? +
    Answer +

    Note that these memory-barrier requirements do not replace the fundamental RCU requirement that a grace period wait for all pre-existing readers. @@ -626,9 +637,9 @@ inconvenience can be avoided through use of the call_rcu() and kfree_rcu() API members described later in this document. -

    Quick Quiz 7: +

    Quick Quiz 8: But how does the upgrade-to-write operation exclude other readers? -
    Answer +
    Answer

    This guarantee allows lookup code to be shared between read-side @@ -714,9 +725,9 @@ to do significant reordering. This is by design: Any significant ordering constraints would slow down these fast-path APIs. -

    Quick Quiz 8: +

    Quick Quiz 9: Can't the compiler also reorder this code? -
    Answer +
    Answer

    Readers Do Not Exclude Updaters

    @@ -769,10 +780,10 @@ new readers can start immediately after synchronize_rcu() starts, and synchronize_rcu() is under no obligation to wait for these new readers. -

    Quick Quiz 9: +

    Quick Quiz 10: Suppose that synchronize_rcu() did wait until all readers had completed. Would the updater be able to rely on this? -
    Answer +
    Answer

    Grace Periods Don't Partition Read-Side Critical Sections

    @@ -969,11 +980,11 @@ grace period. As a result, an RCU read-side critical section cannot partition a pair of RCU grace periods. -

    Quick Quiz 10: +

    Quick Quiz 11: How long a sequence of grace periods, each separated by an RCU read-side critical section, would be required to partition the RCU read-side critical sections at the beginning and end of the chain? -
    Answer +
    Answer

    Disabling Preemption Does Not Block Grace Periods

    @@ -1127,9 +1138,9 @@ synchronization primitives be legal within RCU read-side critical sections, including spinlocks, sequence locks, atomic operations, reference counters, and memory barriers. -

    Quick Quiz 11: +

    Quick Quiz 12: What about sleeping locks? -
    Answer +
    Answer

    It often comes as a surprise that many algorithms do not require a @@ -1354,12 +1365,12 @@ write an RCU callback function that takes too long. Long-running operations should be relegated to separate threads or (in the Linux kernel) workqueues. -

    Quick Quiz 12: +

    Quick Quiz 13: Why does line 19 use rcu_access_pointer()? After all, call_rcu() on line 25 stores into the structure, which would interact badly with concurrent insertions. Doesn't this mean that rcu_dereference() is required? -
    Answer +
    Answer

    However, all that remove_gp_cb() is doing is @@ -1406,14 +1417,14 @@ This was due to the fact that RCU was not heavily used within DYNIX/ptx, so the very few places that needed something like synchronize_rcu() simply open-coded it. -

    Quick Quiz 13: +

    Quick Quiz 14: Earlier it was claimed that call_rcu() and kfree_rcu() allowed updaters to avoid being blocked by readers. But how can that be correct, given that the invocation of the callback and the freeing of the memory (respectively) must still wait for a grace period to elapse? -
    Answer +
    Answer

    But what if the updater must wait for the completion of code to be @@ -1838,11 +1849,11 @@ kthreads to be spawned. Therefore, invoking synchronize_rcu() during scheduler initialization can result in deadlock. -

    Quick Quiz 14: +

    Quick Quiz 15: So what happens with synchronize_rcu() during scheduler initialization for CONFIG_PREEMPT=n kernels? -
    Answer +
    Answer

    I learned of these boot-time requirements as a result of a series of @@ -2547,10 +2558,10 @@ If you needed to wait on multiple different flavors of SRCU (but why???), you would need to create a wrapper function resembling call_my_srcu() for each SRCU flavor. -

    Quick Quiz 15: +

    Quick Quiz 16: But what if I need to wait for multiple RCU flavors, but I also need the grace periods to be expedited? -
    Answer +
    Answer

    Again, it is usually better to adjust the RCU read-side critical sections @@ -2827,18 +2838,51 @@ adhered to the as-if rule than it is to actually adhere to it!

    Quick Quiz 7: -But how does the upgrade-to-write operation exclude other readers? +You claim that rcu_read_lock() and rcu_read_unlock() +generate absolutely no code in some kernel builds. +This means that the compiler might arbitrarily rearrange consecutive +RCU read-side critical sections. +Given such rearrangement, if a given RCU read-side critical section +is done, how can you be sure that all prior RCU read-side critical +sections are done? +Won't the compiler rearrangements make that impossible to determine?

    Answer: -It doesn't, just like normal RCU updates, which also do not exclude -RCU readers. +In cases where rcu_read_lock() and rcu_read_unlock() +generate absolutely no code, RCU infers quiescent states only at +special locations, for example, within the scheduler. +Because calls to schedule() had better prevent calling-code +accesses to shared variables from being rearranged across the call to +schedule(), if RCU detects the end of a given RCU read-side +critical section, it will necessarily detect the end of all prior +RCU read-side critical sections, no matter how aggressively the +compiler scrambles the code. + +

    +Again, this all assumes that the compiler cannot scramble code across +calls to the scheduler, out of interrupt handlers, into the idle loop, +into user-mode code, and so on. +But if your kernel build allows that sort of scrambling, you have broken +far more than just RCU!

    Back to Quick Quiz 7.

    Quick Quiz 8: +But how does the upgrade-to-write operation exclude other readers? + + +

    Answer: +It doesn't, just like normal RCU updates, which also do not exclude +RCU readers. + + +

    Back to Quick Quiz 8. + + +

    Quick Quiz 9: Can't the compiler also reorder this code? @@ -2848,10 +2892,10 @@ No, the volatile casts in READ_ONCE() and this particular case. -

    Back to Quick Quiz 8. +

    Back to Quick Quiz 9. - -

    Quick Quiz 9: + +

    Quick Quiz 10: Suppose that synchronize_rcu() did wait until all readers had completed. Would the updater be able to rely on this? @@ -2866,10 +2910,10 @@ Therefore, the code following in any case. -

    Back to Quick Quiz 9. +

    Back to Quick Quiz 10. - -

    Quick Quiz 10: + +

    Quick Quiz 11: How long a sequence of grace periods, each separated by an RCU read-side critical section, would be required to partition the RCU read-side critical sections at the beginning and end of the chain? @@ -2883,10 +2927,10 @@ Therefore, even in practice, RCU users must abide by the theoretical rather than the practical answer. -

    Back to Quick Quiz 10. +

    Back to Quick Quiz 11. - -

    Quick Quiz 11: + +

    Quick Quiz 12: What about sleeping locks? @@ -2914,10 +2958,10 @@ the mutex was not immediately available. Either way, mutex_trylock() returns immediately without sleeping. -

    Back to Quick Quiz 11. +

    Back to Quick Quiz 12. - -

    Quick Quiz 12: + +

    Quick Quiz 13: Why does line 19 use rcu_access_pointer()? After all, call_rcu() on line 25 stores into the structure, which would interact badly with concurrent insertions. @@ -2933,10 +2977,10 @@ is released on line 25, which in turn means that rcu_access_pointer() suffices. -

    Back to Quick Quiz 12. +

    Back to Quick Quiz 13. - -

    Quick Quiz 13: + +

    Quick Quiz 14: Earlier it was claimed that call_rcu() and kfree_rcu() allowed updaters to avoid being blocked by readers. @@ -2957,10 +3001,10 @@ next update as soon as it has invoked call_rcu() or grace period. -

    Back to Quick Quiz 13. +

    Back to Quick Quiz 14. - -

    Quick Quiz 14: + +

    Quick Quiz 15: So what happens with synchronize_rcu() during scheduler initialization for CONFIG_PREEMPT=n kernels? @@ -2976,10 +3020,10 @@ so it is still necessary to avoid invoking synchronize_rcu() during scheduler initialization. -

    Back to Quick Quiz 14. +

    Back to Quick Quiz 15. - -

    Quick Quiz 15: + +

    Quick Quiz 16: But what if I need to wait for multiple RCU flavors, but I also need the grace periods to be expedited? @@ -2991,7 +3035,7 @@ But if that is nevertheless a problem, you can use workqueues or multiple kthreads to wait on the various expedited grace periods concurrently. -

    Back to Quick Quiz 15. +

    Back to Quick Quiz 16. diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx index 6ff4966672e2..98da30ca84c4 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.htmlx +++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx @@ -682,6 +682,34 @@ That said, it is much easier to fool yourself into believing that you have adhered to the as-if rule than it is to actually adhere to it!

    @@QQE@@ +

    @@QQ@@ +You claim that rcu_read_lock() and rcu_read_unlock() +generate absolutely no code in some kernel builds. +This means that the compiler might arbitrarily rearrange consecutive +RCU read-side critical sections. +Given such rearrangement, if a given RCU read-side critical section +is done, how can you be sure that all prior RCU read-side critical +sections are done? +Won't the compiler rearrangements make that impossible to determine? +

    @@QQA@@ +In cases where rcu_read_lock() and rcu_read_unlock() +generate absolutely no code, RCU infers quiescent states only at +special locations, for example, within the scheduler. +Because calls to schedule() had better prevent calling-code +accesses to shared variables from being rearranged across the call to +schedule(), if RCU detects the end of a given RCU read-side +critical section, it will necessarily detect the end of all prior +RCU read-side critical sections, no matter how aggressively the +compiler scrambles the code. + +

    +Again, this all assumes that the compiler cannot scramble code across +calls to the scheduler, out of interrupt handlers, into the idle loop, +into user-mode code, and so on. +But if your kernel build allows that sort of scrambling, you have broken +far more than just RCU! +

    @@QQE@@ +

    Note that these memory-barrier requirements do not replace the fundamental RCU requirement that a grace period wait for all pre-existing readers. -- GitLab From 514f1eb5f44520d5255b927ad5aabc00db5bc73d Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 15 Feb 2016 16:52:35 -0800 Subject: [PATCH 1022/9938] documentation: Document illegality of call_rcu() from offline CPUs There is already a blanket statement about no member of RCU's API being legal from an offline CPU, but add an explicit note where it states that it is illegal to invoke call_rcu() from an NMI handler. Signed-off-by: Paul E. McKenney --- Documentation/RCU/Design/Requirements/Requirements.html | 3 ++- Documentation/RCU/Design/Requirements/Requirements.htmlx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 2a56031bfdd4..01e12b86e81f 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -1354,7 +1354,8 @@ situations where neither synchronize_rcu() nor synchronize_rcu_expedited() would be legal, including within preempt-disable code, local_bh_disable() code, interrupt-disable code, and interrupt handlers. -However, even call_rcu() is illegal within NMI handlers. +However, even call_rcu() is illegal within NMI handlers +and from offline CPUs. The callback function (remove_gp_cb() in this case) will be executed within softirq (software interrupt) environment within the Linux kernel, diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx index 98da30ca84c4..3355f1f9384c 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.htmlx +++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx @@ -1513,7 +1513,8 @@ situations where neither synchronize_rcu() nor synchronize_rcu_expedited() would be legal, including within preempt-disable code, local_bh_disable() code, interrupt-disable code, and interrupt handlers. -However, even call_rcu() is illegal within NMI handlers. +However, even call_rcu() is illegal within NMI handlers +and from offline CPUs. The callback function (remove_gp_cb() in this case) will be executed within softirq (software interrupt) environment within the Linux kernel, -- GitLab From 11a65df5732167519937eabf16a870f5f8bde5ee Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 15 Mar 2016 11:03:36 -0700 Subject: [PATCH 1023/9938] documentation: Remove unnecessary images from requirements This commit removes a cutesy cartoon and also a diagram that can just as easily be represented by text. Reported-by: Linus Torvalds Signed-off-by: Paul E. McKenney --- .../Requirements/2013-08-is-it-dead.png | Bin 100825 -> 0 bytes .../Design/Requirements/RCUApplicability.svg | 237 ------------------ .../RCU/Design/Requirements/Requirements.html | 28 ++- .../Design/Requirements/Requirements.htmlx | 28 ++- 4 files changed, 40 insertions(+), 253 deletions(-) delete mode 100644 Documentation/RCU/Design/Requirements/2013-08-is-it-dead.png delete mode 100644 Documentation/RCU/Design/Requirements/RCUApplicability.svg diff --git a/Documentation/RCU/Design/Requirements/2013-08-is-it-dead.png b/Documentation/RCU/Design/Requirements/2013-08-is-it-dead.png deleted file mode 100644 index 7496a55e4e7b41becdb658a2bd34765fbe80013f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100825 zcmeAS@N?(olHy`uVBq!ia0y~yV2)>CV9MoSV_;x7*?g*+fq{XsILO_JVcj{ImkbOH zY)RhkE)4%caKYZ?lNlHoI14-?iy0VruY)k7lg8`{1_lQ95>H=O_Pbny!hG!ao@wwg zFeos1x;TbZ+FstBg+nb&{3c1Pa1n)$`~=d|Y+ z+sm`MxHK>=uwuw(_{zA0setXlmlONVbVNmiUos>yxG;8@{VcaNEvo4B@C+7?ii%nkvNEWksHkb}T3v1TqsEm>mn*BOu>}SO zPMR@e#?|-dOcOt?@nn~fEqfUfRxHx6b$Q~-P*7Mn@!j3s+PSy3G%jDR ze&_DpNYzC(6K2flFit=B;Kjwo5qqml|NZ@bzbAfM*CZXK*^Ga967;oQU5-p=>-GElu3QO`u_{@?(hxq;(4yFCwKF)z&WC%u28Qk0u|wncx3|Gw)Ai1F z35d3umz|zwQTxkeUEJPZObta0|B^yGI=cAko_DYKP#7TcblS|BGdItlKmXG)>HG~! zF0LLmH8ydTPepeYJZxfGVBKK4hD$K;V!|;Y0Z}Vv*CR)-U!Q)kdj&^PLBWAnS67R= z1~Me*Xgj%tlziCcyy(!;puj0xuU)&QdTnj=@*B5rZ&q?~4VY<^dgV6%X(kI!g@#Z? zC9OXb>^!^mM$u%y(n@dAWVUU4qTut4qV0J31bAcg&OJXIK%oHmdRVhKq~c z7sv0fi`cA|Z<`dqqd@WY{Qv)czqhFTq*C?u)z>@UKK}UlxZ?HN?H5)CFJHdt&+)4X zcXyRq6h309`u65zxszeihq~_xrX3v;`#N6ST*)W#S9Q;U9ksvB7!-7Mb+3Qci`>M* zD{Xe<++6F;bDrJXTg|{=ZN2;Xw*K$$?mAahS-rcrclP_!aochvrA#s!)<$m^dm(jU zbNI$2*NEuo?DzFb;B=aPSeD_`RPFEwW;%w3f(!}S*|T3)rk|hJyJd@sj9rbz>C8ii z4>K~TdQCZT`PK+Ox64H{v$M1B6YjdKpJ{A7 zMK@ZkYtfDkQZ6p7^I5$eLNYWMJ`_B-$|SijCnx7qN#Rcme<7PmlO`EtUD050cz$kf z;Lf6_Hg6Yq*j(j)bDWc#yLu6WSL=`7^&66tl$6@^l@_JT?E55Sqobqq;Ne3?c6Rn1 zyLLURl%Jn=diu_tm3`RSbvd`)l2eXf&gMk%hYee{9C>DkX2yj&pp$7RWqB@7H})~uQ5^`WD`zkbn!#I&?&i@&D0FTb2xlM(gg z|M4_GrWH}l+iC;_1x4fD6f}3ti>RuyYUl}Dwp`FgNJwa&M$OEqdArX1;h2$iI)0vg z$9zWy-M$hl*+q*M^~7=W@?Jd`uB5amy;nEhWlH`-ZS%EG$;WyQHna0z*qrXqBVoWW zapJ@oMyXt0Q?*#t)zznHg>uPSl{Czp8M!QMeoG6>kDosi@9(RnA6x2X4=cy>auVqM{;W>FaB)OP8wt`}tgcP4srY>3XqF0RaMc z?%w_QZuk2~U$4iX-=e>A?(WP z#c%&dATTg6iua0pJD+SqUfw*-1~oOcr1SG^Z*0$(|MvEF`-Tk$7FJe=E?*WdetxcX z_UzdwOV!lWK=sdZ|M|ymZccyr@@3~d+v-IrCnx#W$jz}VW?LP$_R!wy?+Y%!ys)D% zx#Z0a!`lx9ot&LPSt({;jbvhC;)?kFc6;{jefae0)TcI#jEoi)9~AWB_w}^2uz>2o z%*)GGL~dSou|zj&%Yj~L^MW@w3}g0G2*%fb74@5E(|KvB_hSF~b~B9A`K&i9C@Co^ zP2R_>@caAw=}pJ3UJYe9admZgvB}?WZ*Q|UFic23-q+c2;>*j+Td!X^-YKl^;&SBF zDKCZ->GNyVl8^NWs;e*exxA`>Q|f82nwmY^)~$`+&c(1Ya`Uo|jw8p8aWSln+q=so z^U{$gMpC9(Dx930Zntg9-^DO0tl#sg>)WkYS66S%T^+G8XhF2Ewe5VeLV^<` zH>aiEnx^dD*U{0jckf>aub(-NBeP$RqUb=jF>q}|VEER?&(cANq($c17&U<-zxp(4+N8S2ei!>Jg;ZRZ1`crXR zQP6hdoozL)E-nXd-I98GYU<&;yUPoooDf{HY}ulsr>6=E3mca%Rb3UfcGcEmT zGsDn%_uO?pGmRuH3KZ1*=5$z=smety@U-Q8PlzN_SA(}@!vH*Viv9Jx8|#iga)+xS<9uXo#B_O{2$ zYNmOy#-XJ9g|?5V|_-#g&!9TH)(>1P^|BdD*b!ML=%VR#hKccDp|xoOAB( z5@lxRV`1=_Wx~nMC-XphMn^|Shmqz6-FQ{+X(9|oudl6@@m+uY_15QSXPF8!80Fou zSe$u9jAw70K7)#tRg~TTKgEm+adB~*s=j7<`ubj7w!h@%q-%>V?ys+3d`*+#(X(gE z_NHZKYKE=~nRwp*f6Ti(JCnEEYvmTtI?c(&bt!JXMd6}|=xFcL({y{I?!CIQQdwLt z=0xdPp6n0Dr1Lo#em?5f_qpcaa^%jPm_vsS9l3rzJbP~R)~u;ZmMqD*9J9O3_x8Gb zd#kh8%iGmNh`3G^QuR7PL_M>Od`ZAoDWtv^Iho709Z%WqHRVRBSjaeGD zWMB7N7r#Hx#Mi~8<;tp1Z-x`g=hv;;dv8Z!GNZ!NQ&T5vhp&@3ySe0LP_BL5->>0< zf}Q>S(~VM3W&D@^_xr33J9h8RUTsm zdNq8~j2SK_mdhI*g zOqAi%aryd`oqz7v{q|+>`1|W?@t(VLtx7L7-Mg_d**9;p)IWxf=H_ML51&6D{`vX2 zpr~l;f&~f;4y|0G7uLmEPyTIJ^P`|g(%5bH)C)(CvN8yWiKP|EzS%Y(+`?LMAy9u= z@#orw?#=FH551RPPJDG`WyFqx#BE@|mXvJyCOiMlA@L9Q4;<|es`d`qufD8p{p;)N zL4hV=U8dv0A}A;ru{|$#nVi69>xNfft2#K;d}p=D*Zp|7(UgOm`*N0mgan7Wy84!^ zt6cB*evj+h_Wayj>z!Qjk*#i17inn3@3V1oauSe}TPHhtlB##wtC>Mp7dSG%{h_L= zs;HvE!Vs`E>#EM~XW`EScmE5oE-8{PB8x{lmHC_YOWgJA3Qj6WzyI z0}kib-`SComzQTz{!V7nq)7{|zZR5|>Y6Y?K*p{{qM4ol+{JHCOng?|y|?=Ahje$| zjLgi;Tc0*_=Vr01zxuY~xQhDc6{o}dYr{%aAePQBp&wp{O9v|`&-4*($XebS2!37K0b1FadA0t^{VOV%AA~> zo_`V(rrUD~2nyQrzR8-`F>l7NyOM|39ht9Eac4&%vvV7dV@OEIx~BHT13`!9RPCPi zP~lLPgW(^)>55;IVtJ=v4kf6}U zC)?H0!J*N$sCC)#t^aJJn4_bkO>%FETwfo5d`;x$PhWSe){Sr5UTOF0-QC?k9yIea zFohL`V?SuL<1975^$Cj-5}&!NY^&Sg&;Zt*zO~4-d6UnCHz2d{7nh z!64^qp!12j*5wQbUhH_MWcKab$I#%~EtdH4(b39P z^LOvIW_a-6U^6HKwr~mutPa!t^X0O?gmGF=;D2JA6aVO(Rfa`0MNI$2TS) zPsq#b%e=fS)3NB$kxqt&;N^Y~@0Q;`dUCS5ps485zwvJkQht1R$k5<5RcoRDd^?7Q zr>CbUe|T_kN5w}aC1vG}_xECF=e@bHk;!4t-o3th&##8Zi!yvVt-n8G{mq*zlPWNB- zaaT=E4NJp~n>SBBJw3fRwt2@6i^8(9b0N(7`ud$69Rh+EhA9CX8RMv zUmb4ay&U)b!-om_`~L))<=#>;PCGN9{C;it>pJ;{k{1^g-EZ$LeC)=k5V|_->NC@? z1!ZMo_V)XIO0#co%iZ?5^z}8};JG$7Hk;&s+y|7*uswa?tRY9k05T?$|J zah^}_{wcz*5_Y^=9J{+rNM1f)WK~RT?9+F5ci+@o?%pqV%jn9%c6J_#37Ik**G6ye z+PQP*mb|;So)oe1%jtxLg%v$I!ufXVx3{;wpPri9%l17~RZXpH`t<1x6J{ExKU>Kb zU;lS&AaB(6yj+oaRo~y~o;!E0U-rbV{QLWE8S!MV=&N4Z<`LZg>FMdy?ecXq9v7cE zf8L+LfDdN`U@1|T_ z?0)*>WOZM@1#jNJ|9>NOh2!Z{r@VF-`1|@!HO;=3vTK5U(G!ntx1~iyQoj73GG$86 z;rNJ%8EYapyS=-=fBti+H~02N*VNYbI?aFh%lGQDK<73dL58HvOwE%gPpU=V{PyOi zGAOoY8mFI{r0SjW`Ptc`kB^SV-P5i>A}nWJQETYoGeXO zH8l;@i`%0Sy)9>A@$++@Sy``=pL=?EOsN0=H+);pO{MGWVow(}JZEO-^Qfw_IxG%~ zMbX|5p#evZ9rODA?QQDUS67d2WBd5=ijmtNeS6T`wpo zXkNyIOsMdpoQSBXq`$wu78DjHt_C>*Y^<+o)|CXoj*gC^j%FQUkkdeg4hk&@QV0@3 zrwu_pYC&)*1(F7he8Oo_J5bNB{$I_++w1H9{}tb!fBzYy+SysA*#++Bal zC2T4T;%dK!{`mb{d}i&X*I!@U-EA&qp4W5WfP-8L69bRDos92nGgl`krfx?Um&&Ar zLIQzd`+mLBHp#faAZt}(@UvL(;Qjjly<4`JfC~C~^X9oG?RR!|E_``OmEpkO-`@jw z7NySPVG(q6a$=e^X;MOd{{JJVcNahBV`63&6cwHNQczl&Tab~##l^+JMTT)rW!vuA zdoS$bq!z5Ga&D*zv^78pbvu4bYSh92}BZG{L%%?5$ zPMq-Av15nGiduet{_FFmYXml_A2tpVIL|(HX5_K6N>+3Au77@2Vg>3%yZ6f-ov7?y z@a09|o!#a7=G_|@FRX2t;>7C*{ zJv}ZVAydBPXJlyj&9O)<`}O4|+sl_Pc^P=>Ely`L+*e#&sy8*=7#!PAA37N?S5(!1 z`1;w|*#d$rEG!}`YST|&|12mX(sJcWNX-7ay$*Tte$o4af`dOEm#Z@5L>d!BK)C($Sl0;yhSL>k!h(O>_sR-Qe97M~^C$G)husO4oSIX$ zLJxg;dHLas7ZD4-#opB~E-t=to2HGjm7fXSH*4ER#1`|6CKb@86%#{#RB8vx7RZ zhue4yKRxl(iQ2N_K--DsD}81f&9Exf@|$nBcF&(rrx`9d2Tn0&u&Hbl6#Tf&S*gm! z%ZqE#;>8nZ&Fb2ediv0vJ2IM@nj5xlJ7=^+qbupk*RrZAtABsL$Aem98#Zoi?C$2i zSNHqvakgFA*ViTf`}0%6JWuA%-MbU#&Fg#cAmPZ-qYKl{&WbE^DER&^c8*mk*Y)-B z?my&*sgWHxJ&u>od!} zm9kT2Z(RR}4+Sl4ZHrtwg+P-iIyyz)H?F?^T2M%c$=lm|ie9W$e1B;`fWWC~y4jmT zpB-#w|MBbf`inb@(@pa3SloWf!oqUk(j_5KIypJtzTyMJ!i5Vjye#?f;lqhS?SPyd zon^kW+w@|0E%2PI25K3#@k$pwJj4oWgyi1ZQu$`nrrYjQJ09H5-+y#Z<>xK8S#@=E z9=v?nnRvMEVKcv7Lu+g6$!Y83>;H<%*Z(nGvu2G!@-dzsIa{mi$9HI~3S7+ACu`lt zDXa$SNUdC>aVkzQv#TfX6{tPKwdXy+9!(#>>x~J-hYi>8aZ4&TTvsZ`_E;{nygM^77{9 z+iiXa9UYw`moEoz%e_7A?XTwM=BKCi_fN^Xx~g;P)Tw6s=gys5 z^5#b1p+kp0mE>H$eEI3}`E`@R)<$)9cXu;PxU|%}d;R+LcXpMY&bYPz|G(%nXU-hC zcQ5YS+uPHh8co-W)q3{q*`^t z3KVhmnx>-(8l^DGy|~Dg$w9<*C-(vw`%|E3eE3@NYtz=?<$i7tPk*?$EjLC|1NuTRa+->11Ydiyjf(=3U8a%Jr>|c(KP`}*m!}6BY>JMKUi|ZTzkI%tOzpp)&y#X<=RWD1)oeUfL5v#;qeDs0=f?a}k+(=%rlKR+kx8hGUD)lep8=B?M2m6TFm zTv+I4TJ)I>uGKRAp4K zE`OKu;ndQ?$H!J~wP9}f{#gjr@SR@e`1kMk`={UB-2C+I_WRSe->dSzwkA@!TU>vd zW%08UPfku&wXleAaoP9d5x1me(GnJRcInuV@2{`>`^~XXFNTC2{_vn>v3es_2G={=R7pIliP?51mWxSfAGs1+C#G%03B zfuq+{EmejkNk_Y8PMbJmhDKdooshiz`mGys?(d7`Zh7|XnVX}-`s>*bnHzrm_yKat zlQ%av7ybWN%gMzx>Gt;g?9-=vuUrWM4Om~BwY~0d6(BjZ=`n6l1y}i3Ty!!8jh0d4u)mATFaD8>SKFBvJYHFv}MsH8Kw8S$h zFHbKmEp1c!dAZy;Q=jiIFT1bqT)TFyg|&6}^y$-m=G(BWBY)U%HHF@jr zuh-+Zifz}8-gbgpe~-fd-}nD-2{`*;YVqExuR-TKTmM+7D=E3I@fL=y1yE|!XTH5X zUz`Cn#QoG{v0Lw?latj?@2&oRH*%X=>5B`FeKMAdbT8k(Z-2Ws^VXJ?*P12?$L=nhI=}v3WS_jf9v>f{ zQSGmi&hGBhCb6^4a<}9fd@T-s^ytx&qNk^r9Mt^ht=U`m=SN{~WPI({(0y{JC5_WK z7&5P|nYm=yvRQM|PE1gY3aB#Ku{GnO6ZeAW=jTuV`T2SF^JAx`YWFUCe`n|B88c^| z?6?1?v2NYE$a(8QK4)nF4QEuZjo)9#v7!Dmel#rf2J=2m`%7lS|g^f+B zl=1(LKAS5~pO<{N_vK5;joY`CH8eP`uZwNoy?gh`mpt+NtG;SUnPx5d`~Sto#TEq* z7|zYN@Bi|pBqA#6(6wt~Q?){!c9*>c&GFpXR~tP$PPQa`{q^MIeX<`ud}wHHW(L*q zj~+3FhlhhE1XrH^^z`)f!^e)Xy}q{gbkRRW=e7sS=hq#YWt#or@AvzMZ{Cz-NXX3W z=Bb>{ci*USIb-`teCVdKVwx3*?) ze)A#e#015NEg6D!|NoZPe7{@n;pcbmqUDwC`SCfows2}{YI5-NAHTc1{Nhq?@sc+; zCd!NK{IDTdXleHKb?U`C5Y5rx^yWaHFav{tSwti&djrw{`Tz~2M^Dg zqR6&~rwbS!uQ?PR6BD!TG$%K=b1RqVmh1X4I~K5Rc2`wXdvs@KvD-sk^@p!FpSN>9 zJIi#l><9DJe?iUOXXob5ep<7)`unk$mzNtR9pQLu%FfQdCU&od0rsVByxrc9T zO#XP7-#+2NfyNvA>+RWirKV(BzM7G1HCONSgQaa-c9p&c%@L~m%{gIIv+{Og#C`Xr z%a$n_7zq6R{oVccw%p=9{k>AAhq(3kG%Q%402+BbJInNR(Y=2Ae-h>I?ttb^K%>(? zKR^HMti*q>{(o&nb@k&XCnw7??qPdiu-XZ{GUAP7ne6(@FMZnd1sy9YEWD=a%zV3v zC%S{@xPR4`r0Bf`{asx~J7r33Po6xf5xdLe&fU9$GBQ0E7rQTx-Cb5tT6)&xy#D?_ zi&}U7`uh5L#{H{*R|PNk+jd#9O}}*iy7>Klm7kw6GFX+p;n3IDzp^%3oIyZJs_Vjq z02LJ#1zTI$<$iOGqT;6O#eO)Yy*}aYu2N7d8`No(l6s z)5vGG8Smrc{q=A5fx4mFwr%U^>^yjLb9(WX|K;!QG)|vB{i8lNH@8L?lWX9H>hF0m zyUWf#+4IWK$Je*^P1T$^bG8_yysBYXz+0G*bw@YU!GQrZTrVp-cXjQTFJD|h&bV8C zKk?n2oj2P+eT+A^wsL!Vdd@J-o_2BL@;fula%cT&Z`j8Z5ALk8Jf61Roqek59tG1s z=Gv*Jr=1P_5fp8C=+Ge_J@@t3nNMWQWNHvpc6-pRzYjF77_}{@)2{Z{g4*BTRzz-A zd-UkhhLn>+J#w~Dv-ijBob$D4?Y*R*J3h|h(LW$8EWCAtx>ClC4T_+adC|W8|Nlvg zYK2_*c0Azcr>DJ9N91^Uw8PdMSmHU^An_1O$eIYjz182(l}X3O#0ZFsw?}W!Q?#(K zaR2>3V}_rHhr@Eexu7wD9XoeEY?rTNU@*zQcjv`5`@75Vq1=+S?;YCUTL$Go0oRh{4A2OsSubpZQ6^Ai`nfJ<{g-w zzmL=1-MzE7w|4ebg+-5!^{6T=y3?}$$&-||sane)p8oJV($mxPR`J(ro2=Juw}d`D zILN$Y$&!?)zAD9aaZCE8Ou6jr>=+t8KR=)R<;BGnp{vC}3m9I!=nzzP%UG+`-*(`Q z&B?lzuP?kTiM*$ko}1hI;6Z}!hNmG%yF?A^{#1a5Lm4(?TwHYgT=1@v%qy$I`Tza< z$HC3rJbU)-WcgQb=dS|IV?IAO*SVcf)*%0$&6l^g#T|})-=-I5B4->fd*)Z+?{CND z>lIW~SkltcZoQq*Kaaodc+6k()dlhE<80^HR0=(O_;BYf_ww@cwM#eU-`{6Z@*-f_ z)B4|Uw}VPRCnu*1t3tJR?AY;v`4MMCM8tyJ+uOK|j{RA6z6)G9iB`95mvwV-VPFVb zAJ;2on)P6A`8`K3uP!k^x$90THzM0_tr8R#UVN7?VpmBfgTb$P6IWi-|H>4@+m@D= z7O}t17BrhzQBjdHi;p2{OUA;x-)3BnK3XKTk0&}KWUf_d(;|%>1rM3-)qM7yJhx`W zSA){*dzY4aZ%jVkmvh+7!-J!t=Y8i>Py(MYZ(iTIxz@@iCMKs}y0A>wk2lLo{q?Y2 z{=;$k`UQ!H+oICNxW)Bc7Q6L=*0;&oR!Oj?n%3Cfa%|JGu#k9sy#IPsf7F(YM)9}` zMhCak^B(?O!1mF-d7b85>+);g3|CLPyyn}+{QLVrWuK6c5NMrS;-e#-pp{eq{{7DX z@#DvV>(|3)Z;RfZ_ov_l`};kg`+iMX3z~5ZQLw$d?wP9#XwlT#-+5bi7cyL0;wjwO z*Eh{D`Ph>c+}}Z?eY49?P0>_RD*E>3rqA8;_xIPwSHHcoGI-{+&8erw7!{^!g`O%> zcnF#(Jk~F-AH2+GVz0D$m)~;X@bK$8(=)yL+$uOw|A$U6k2@! z>cLfv9&@cqQ{LRzxT)@M6{t0rb8CwysKe8>NJ3X%L&M|DnKLX6Q}pBG?0&y7zPTZ> zd5(R3+`9PvdUbVmw<03C7M=L@^>y(U`;#Y62CWX$WmGtK?i{E!(b?B`jjhbC{N0>0 zb1Z{bg|F9RSmN3(rlj=gy#4={QS%}caG^{$7SaE_tx;T{XMBZ z|HK4E=O>T*?WghE{ZP2vaP{mg)5#k)805x%wfOtvasRFC(A8n044?jfzn{LlAC%Q1 z()9H7!1i`_Ufi|RzWUo5kiD;W{p&Tqcf#br*Tv0c(spOgo^=fr$({KnWnKLKb=S&t z?QeBkZicJHro97?+G(zXo!i4F*&@uw|Dm9O1qy=Ci^`0 zow=yZk>S(p_50Jfn7ya#O`WD2-PPOM8^{}9|F^WWw^x*5=CQlKo=%THa`&$7X@Q1z zX6et!(d#Jc_c^>r&_3$MIw)t3qE{BjwNuCgq@17BZXfBo2RtD+|z9UX6O zZ}(^DXm59)b~}D$km^i>#HNe;)Ya9q?f*aSx8HL8>f7oP8^hpp^X=EOZaDt-@#4ob zS2E_jyR$QBS4n2Bm9epL<@>$gm&EKW3ffijGX2}V=)F~?(@N{V`~d~Y(|><||J-!% z#0ig^TeGhR-`~GuhsD-o>_0C0xwyEn2KqA?rJtLV{!9GT#l`O3bLY+tSry``=08tI zQ&ZE8`9s;88-aSUyQaJ~;)&k5%zyqm-W|90)mH!f@wnf0{dH;HjN3bl( zx0r{6LqkVLOKYnqs0LzdGD|(uA^7PKxBiKJwZC0lKz%bNhgBgfl}xj)2m+ycuVHxC6%9_&HQ%p z_;GhJod^Z5erxsOpmMb3|kwe%E-t#Y2G}&g9i^@THwgc zsL(5Adg}Ww7FJfzudl8yb?FoWPg|UwJ#XH>nEcz~P*dP|zr6eBXJ_?G2~G;^Q`R{g#)mxv<=Se$9ICpP!x<{`pZDv%8FUYxebX zSNF8donXVi%!<2m%F?Azh39I6R%FdxA#$Yl4Chwn{&drA({DLH-={WT-EC)UsDrNL0>{q3Q46zpigpHyCW( zy7j1Z{+@~NPp=JKEp~2>W%ER3cd4)crcau*h;@D5-Cc=4K0NeK-9KmU+>1**h3Cy> zOLXAPZ9B{*lJ=_d%NnN5R$C6=+gm+x&YT|2;AJT{y_ZVulQUlz%yL)!+*L&wRMWZo)|6eg-HJ=0PVs{rjI>M=DQkb_E-mp?J6;<6 z|G@-#-FOGL*WpP?N!y%d1we}%#g~e@dKQ(JUw^*kGlx=@(Q^O!VhlzZ7Z#*%+E@De zTIT(|v+V2lF$j2jd+#iL9kwhJG!Db4ka}v$$?2um*4Eq%FYoO99DM)$v0mxbzdc<- za=`0-RbyPHv9YsjpPsItZrahMa5!v@oNd*Cqeoe-=JFY*ojGB$*6KiI-PW3w&5`!+ z->V3LrjP<1Kk734ZQ&Gta&K?-8n!^e@0jO`!hWe9e1b{3VFpP&BeXoXVMw}+>X9b@ZSlV_l!MjLFV&9dp6{n_ZFHSz*$I#HqEiUy{ zY2`P+8KFPAIy(>k`}_OjWqBSU|;ZSQ|jqg;cFrUgO~fA-Co$+@#1G-^F*mN3<*a%1aIspR8~?_+EDg3>dWiv z=YKFe8hwxc_}|J%(gaqyIEB%Zy`^-i;F*KEj-tH76w^S zSI&R0R<8#w5?8jfn-{96rS$Ohhim(<$5r#rn>UZ4A-?XX>Sde$w)H0`s~SG79FvpVBy8rIX}SxuxQO)F+qQZOG`XKVO&*Z1!_se?5~TR zJq@(ziYMM>%HH1$Q4Bx6K04a{;memP^Xvc3Y+fQHy79x+t=ZvIw8QxrHl&=Kq;vTC zm6gF;Q$fXf#Et^RS?2kDpPrsxoOyZK46D*rX7yQFT5f$ZE6=X3%bTJTIf=aqyzqL{ z1f~bd42P4GlfN>v^SLy$@ovbzt{2v}VnW+`_iC9fTeci&U}R=s&<u zQ9)BvQ%T7v`4~^`?Aa!nN`-}mGoQ`3t=?wl+bdD)+mL&GUF@^X>F4VnwMu@O@Kdf~MpE4EEQY$ewEPpt zx708;%$_X`8jFaIj^6YAUUkH#l+J6POpBg){P}oX9@Iktjb%k`&3brRf4|G#s;>gF zvb|?#n zI!wg1Gs%;Y;VZ)l(E41TsFqvXa00iH>-02T(5#=ddES9@=lIgn{{Qt_AGg

    @6o}0ICzh;bi@)ESR%%#;- zt8M=D5}2a?SzgMF9ZZR_tgI0 zwqmaSlUB!c={;{h*gH;~II*MaQEbuAhwtw0es$R(tQoWyq+`W~T~jAbTGZ0gVw3s9 zi#?yyxP*z}xZP>>>hJGD=l?sL1@4#&ir)Ib%CJ4}?y1XXs`ko>>%|B#TxU?(JZDxY z!-ll8QejH+Z*FXKuH7~Fssd<-g_72lhp)fAy?P zme!AcJJl!7n$@+p`a4&Hb;4^cP$exGs3^wD0NQDB`ONckb1%=^G-c+WdGqG=rJkO) zQOG~x^fX-$AD@r|VfvuGCQ6GIeb||2@hmuR!{*)`-B1zLx>r|L7Ck>F8>Y;E>GEa6 z!bdI&iGGOtb{)h}I(TsHMY8Zj5hG^~l*+QnSsm0VmxN}lX|`ufAe!yVn-!7eH4r)Q|zHZXQAT2lMvqI=SX zRIAi*lf81bRbLL=-CZs!_*3wJZ&)idIySR1Xlt*IIlm+Kw%OO0VbctwpSv!p_VVi5 zSNr?hqvy|$ci9{}F;RJA=4CYo3$_FqZSeLt*MsH^DgXcd-MLS9P1@O6ObWaW!l!2_ z$BMXmZr---TK@fgbH9tGC4PHzlL<6S$ai4sa$ZoD6cw#!m>_MQ_v97R&ttvPO+9ii z_%^ldt^qWM{4Be!ljSY#QVT-SS1R16?@-QYGzueHF zVaz?Pp<~5~3`Pdss4XY1`rO{0A3lFm_s>5I**83XxR|M-@#M*q@^A0$yh_yN&eC2`T6;v=>^6E{0>~Fe}u5w)T}YENDG~4xNeqkLlE0} zZ-x`AUaq!k*nWLoY3QR#!@5*2M zKy9!&GX1~6+mV=8c$R&l> zC{J_op=4QxHL<(R{EctlzP;N2rnVwDsPfh=Wn6M?Ww3hq_IX<~FT3siy2j8u;>8X| zkM*Ie!{+5#-`Scyz3NT+#wji?=lP=db#!p;4`+;cw(P35f&xQbT^&P#)B(&2cZ+ruJap>dV9-hV$+h+}Xk>rZYf1k(7e19S zob~|ahbi6JnXZ8AvON&ho?<##QAS$|4A$iYAmT4Oz^X5*x$Xo8X-?mzV0kjRpqTqo;U)l`I;$^?C z$n)n%E^#_3&7c*&Zq8%Lw6n8XQ%_H0JiyG5&h_!5I78uy7fX$~B$=JK{W+DiUWiO< z=;&JbiD8di+@31N6(0<8EF0^mEOJs)RAekG>wj-p_xah`4RL1E$M7cVkCzj%=`{l$xn z=QnQL$YPka^0H=^kgC#h1{szOQVt5|Wt6JoDncDyT&K!5^f6R1W;D0g=V*nlno?0! zr8RHfya0LqeLs{|yN0;5w6`C=e_wvN-`uAC`|bby{VOOVv*up}gAC&aAxY-Y;(|hO zbyUSPmBA-OWa;V-3kHX^QClzUF3$&T5xTlMJiWD}Yi9NLcZr{$osHO-#M&osKd+E+ ziH4QnO{N4Zxw6~-;AxU6#!DG`!bP423vMhbEuH%A?r!bcUtd7`s8>6?Fc`5(#BWSu z4OguwO{eyi<$vwzg!juJE4ZaMoZr;4vxqkh6qpB|%78Vv8 zj9jKDXJ%&pcsf1aAoY|8CogZPh%2YCpnOV=c~6H%JZKkmh{x6-k)!+vx@&)ZIXF!> zdJ3Pc)qzu|x~3{Fk})o=z%wxn`Ak3T!&*B&F-Py~Sg|2voyMtqK})@6{`~!0J9O1IQHkrY zwE!WBt{pE{R(*KDxM%O)r?<9db2T(F)TM=jb5YkWaZ%Tg;UY&sS{=4FLQttn zZC%`6uKfJ`&hBn+;fc=}`Zj90ObG`y%($BW3kzP)-}kfaV0Xv7m7w{J@AvD&MO-(A zh@^_%2sRP4Wvpuu2y_hRKJcAa$|Ruf_gnL@=8k!m{QUf&4UOV@F$GKok_T8pPH)nU zcL}*r%jh6!oW`T==yLvj^NVhM9{b519iLk6|5RGk^oG?nkV!jyT~6KGTc$_v%<28= z^5xH#yt`7>-`+4bY-1?ftmHB!ItQe5&HRpt9x2lKIhSpYAhAU~N5YJ2T7Z(?Ytc#gBRbkQdbB7Kwg{}%|T%;klrwyDYwSq)k zKdy+_sI+Fyng|{xEdd)F8wDjZ2CYp};Pmd=I=jOnWPRM+sS1mjMEA)(Y8M8z)B-04 zaxu)AGw0Kuh9yf>jvPJuwDMo|_jj4+*T?S%t>JfcsYuzhq4agwnz+5QS~VVky3$LQ zsE8@`dri?;Xty;T;<^_LPfk`}T=@7H2N&0=uX|R9t#x{OYU;*{k4X#->(}e6`OoXA z{QOMxbd;L9x_#NKh0g7Z-23G~n^FDuF=ahJHy1RgC}oy&A_=^sTkz@p+TY(EetLTP z#$N01hd<`r+aqZ;*H88``*i(yHUL{|GKyQ za^L|5m!ldrFH5Z6KDu@A;KCbM4b`{Hh+Y3+nto2Ex!o}f(T(&~D3Rp@7#eTx@#{5L=hSdEF(@m` z{p*;le@r6zR>4{EFI^eGF!TQ zd3U|Fm6ej3n%kfHr%`iXyvP7es6Ib8x7kIhapg+QW&ZQ|>g)eYZP(V;<`xtb^zipT zK0(oWi&}~IbiJbw54Ufu{+{>Z)vHJC@^uID_y1)}PfzcWx0ic-ynp?+KWEPPxVX4H zIM~cCVU*(0JbB@b8xb+PN;oAYB_)j0c$Nfd_Q_haadUIem_7UOojWqqrcImRwNyh# zhlN2xQnJ(h2Ujc8biLR^Cnu{53JNkZGc(_~apS?>@AsM)FHY`#4LZcY#f3$Licf9&CmA9ST-Fv;NUaYN_214*Hzp8ELoxgTI{Yg zaY6n6e-pf<|CL5WMRC>E)~Z-DK0ZF~?C#DUy*Ubb;x zPY;iayZhsNd#gSC{o6NgG`w^7?!(8AnX|KBTOBpg*5+R9-tTsMTkgiJt6HF`gYEhE z-MqZGY;0^m8}eVgeEE^J-|(13@*BY|Y!1oCdKS8W{B&Ahn1PFv^WuzsRbR7|ly=qs zubZ0s@7HU6CI>Y&H5ZpH$;bJa92hjz)Y`(|srDMI)Tk}rOv#nl{ zdU~4FXK6{vi&s_#zdYE?F7^4_tE=4%7uG~>K5_Nx)>Bn=zg{ladYXTGTkoAacTAoc z8yYU0X`CLEmzTFU`TExEa3%*~H6I0~MR)Gp(Yg&};#bPbpJNbMNh$ zxo6LwEyos=zP|P~>U4LeujpIrCRB~zrAH?ICJ)F=F3Y zI5~@ghMwNuqvzjTT^-KJaP!8E3r9MIS5HYzN^&|qO?UC~r%Kz%%}uRq)~w0+`s!**diwIh z$LSdv9&c}NU%p_0LgB2%ix;~s3W$pG0`0)^u&b%9J$d-B^PFc-pSqU6zb86;AN=}0k>bainN5DW|q6#V-7y1&lpLx-CF{Q0xOwOj1b7PH)2 z0bX8Sdy|&$+gbN^>-AN>`|ee})>TrPWnHdUSygrE)z#IW;o;%Qa@yM3uP!WXc2l~v zJwLv;bm@{M0l&Y!H5FR-?d|Q!&CSggpw)j<=FivHySy>ky;tJr&z~3fRDM2j`}S;x z3Ekb@6*=$k>~yZHt4oS3D=QNb5Lhtr1+TPOPghshD^cb8`g$gZ`*pw9TD-lsHac`t zv9-1Jr!QYr%FD~M?(MPkooBN%?)A=!k4h&~jI!?TG6m@bH3KKQSXo(xc|O>Bb8odd zFH@s23A(q&W|h(ptQI$#EZd0Y2t*XOP9L!fHrvf?UMjS^}N(iUqQzlnD5UzdGe$R z2UG3GqvBU~m1alnC|G#RNIPte0s|=NDJk9Bk}1q9Yc-{#!^hW`lK~Xw+wa$TTUuH^ zDq6qq*QyHTil3iS3x8c&>dnbuX>EOZ{r-PmUQ2^&^o@)rRegJ-spgS&zxMmw9lVc^ z^)9}2DadeQ@O_i|&u7hDT)td%mltFxDlT4J`}IyEOJhl2sM(AmWWloOa7WUWdrtPl*=5Gi?bLa?a3T%F;| zx7+#GwcTF*joh5ZD=2t(Z*};Zl_jO6OXKT)wqCk)N$#}o|HGY$k&%+MpU;{nZL%(Y zb|&idkN5Tey%}CK^V==xxBJz>Cu8BDs;V0Gy!OKb#;tjGXE9uOc(}c@Bje4DjVuju zbw5+1_SNjP$WKaIG=s-B=JAgYW$EeZmw$YGeDrh5`+Iw(-q-*Adi~KxB_%H}FQLhg z%ii9)7+?QaHLo}(M&|3=+tV2)?A^Qf$IV?eKaFzl?wWdSZM6IS`v10n|9n1Q^7)xB zEGeXX`uco+eV2LVt6B3+v#$v-eERrNv9`9>$lUyT#=kH3s^1GTRQ>&W{is^}<72(b zN{goHMqgUyJNw9z#YUw&88VLd$tEoV6$EZ>ZY7V8@vglc5fr3!@6Z2_$K|C=MRIR# zx#)52%IEnOg-u*sTpD_MeP6zOIdSGpPu~4~Yq$PsYGNuXE4$|5_R6{Ta9&DE$XgrZ z^m9u@wZlMLLVo`EabaWf@h#`fGcTzax?Q|@QR=Ks^p*_An>TMpP2XMpT~AU%VnT@4 z(v}t$C8b~2_y2Qc$hfq`GxXW{vuBqscJJ>xdm|ulcf`(TYc@r1&zrbzo!-e5qh00i z-|>ty0H%8UB8~9`Cb*B_-emRfHhU${Dwikp=W2MoAOja4pV(vvhLo%9C&cB zdE&&0jb~?@KRzyBf23W$j>F;VP38r!bOjksoj$#A_3G}_)6*1fZ1&t@EPea-?a}?o z$;pfi|NngE@9OIMa8iB#fr}RfEiEmhroX+hQ5m#?F!#0@kCX|=v}w~A8m?Rk>6LrM z5c>Vu-s(#&$F}9(zOdN6zv}3P3l{_$Rvm7A zr6IyKW!ki)@9*yJsQQ|<)mFvI!Xo3yiqhBDEb9JPs0eZH`}4`0;leKdWy_X*`0&9Y zB}D}^9ryF|^TVf3aWNFUzh}Gl^Y_=+`56lS{3v|!;>Cm4>-W1=R_?s^DK{tQ!kS3q zJNs&-e}8*>_;&vO*yT4?R38nIU;N-f!i!h07Oh#s6THml-~>hIgp3RhWo6}v=;*_@ zZb_Y;W$Ii|P_Vb};JdrKH)dbgb8&G|(AVd$s;ath`Ev8(#mb=bdOjYPfBfd==B?9$ zcTVn~)weuqciCG8(8xSPK=PThXV04Mx;y>!(}=BEqM+4hpoR=rE7PuBy9^8rK(j%& zw&iv&SfKFa`Sa}FmAi@szB*j1tgO_~(pt4CE;>5;#p~CLw`>tvxpL))PoEB@&#!Ge zZ}+=LzoEwvl(XJsZrZ-Red$uwO`A3q{QQ*qB^PIId@lnR*S2CYbs+=z|bwOzpk`e zSV)M$!Drv5O`9BCLWK;r&Nk0adUa(bXc|&XCnDhar}-|QwiY~e`tjq(gT?)JtHOI0 zEnfWbr26~^z2^5ot(?8dUmhH6mU`ab*LUps{Q5pYWjBX~0XEkpZ0FSM+_ej|-dV!F z&L$}-X+z#!tF@WW`(SM{o~E%^B;abpPya({@vZ(9bH{cetvv*|9&Jd zS+?xjjmarbpRCr4J-fPE=FI8S%nTpf+t;jF6E*$q)z#B~L{>+{#K@dEdls~{+-IK6 z&SNu9r5JHEF(|E?v|{DWn>Q5=4FzY;oLO@*xu@{cQHkX9lh&`-2dxnCp04MpG_j%M z!Gi}44<00NG&O)0rh_&qzFa=vApM-o#%rhU-regJY1&&EYPm7szf=A1Z@EW~9b2?x zhs4^bt*c6-uim}4y8dgphDd;h$knpey5HY&H zbkCzlk0#8V$!TtG{_)suy(@-Vy1Hu%_wCqWF=fh>1*xZ}m1>2r3^B9#8KfQt8jMLv zQF-+E@x%!e8s5Cg5fKx6bg-G-qV$!BUhJ-x@VLsQ*Z%5iX&stnn$5s)d71Cw6@iN% zynoNn&CR`J`Eq4jTUpQn2B00ZM~=9pq^4fA{JF~eY&|+QCIXwp&nUBW*ym~VHY0IKd z7M}c@w{8{vAJ$*}^zGZ;+}qm{Ute2W@%QWX*L%)R&Cba3+P7!#-i`JD>)zbmz1?rC z2Jgas8$<8k$@1QC<#LwyzE#~9=h;>ZNJ?tnTX0?7ZR^#v%IfOJkXa$&Y-4%x+>_I- zI^SJb$ZS>eVnON5zrVjC+7JPtm-HXk+T z%uLOD)$jL8oeoxy4_dj!&osXN|KIIDBv;A2z9ke=dih=>Gy9{v<@c{voIi7hXWqPd z0xXPnc6On&K4x{VT)I@XsJPhl*n{j7I}b=CpP$tN>dW5S`{j~1!-9`zu6}rU*mTn7 ze}8`~D=RY_r=4L~P<8Ie$&;SS3s>YS+&lGtb$0TV^J%qzzg|z;6nOv1>SfZgr9b2A zex}Zy^~TiYspBl|>pC$zi&(F(i>=Nv{PpFs|Ld)>PoF+5^{Lv&E9hJ)mxP^{JEB zk8}zP3J8Fb!k1T9y_4tZ@B6{jqySneK^fW(w7OXN9~qHsoq$ zV&{`NFweF+ASNbe{g0V5W_0{6eteAg&i;D&;AK9J4h{@#yizT5=FDL`>hbsciHXXI zsj01he}7k2QCV_pS@O}NM{n$_weFL%?fUeo=wqb5u<&H5>y~L}BxcN-mGt}D+lVb0 zfm^pKx3;$aIA8y-+5Z2Z&3>jDs;a6E;* z*Zf!e`x~p^!?)Y-A8TUeKC-M~>dNfytn8+h>wao!Y98E}d>nL+&7b@K|IWWwDXtgO z@#s;K&ulZ_JNBh#dV71bW6nP~*qoS~+dF5D%$Jv!+3o*+37#6I{ngBVPK~OXT3F}G zUqAP~%G!73WJ2wvgkzwV^f&wdrK>AV&CShEoj9?em0P^4naw`uPzxuhJ9}$O=Hz2D zJVCCvSWuMv*kIwJ)2}xsAMd)nK4zy<-%(JnQ#)+Uf)y(?c9p-E`}=+W|D_Wq2ox0- z3QoVfJzpNwQ)HOX+v~gbciF!`m6JSF9vwIYDglljITGOI#r5{~_I}XjjiQngk<;Pj z2jk>Hx%;?~vAMbU>7a7qf9I^<3oyL8v$J?@a{J2ZYi<0le0zKQ=*zmgx-E%^*}S~G z7VX$!acf_#_1PJQ&dGZ}e*9>XeokgBvsw1$#KUZbH^05TeR-MhYzL1%dbbJ`S|o)E4;gC(IO84mO_IE)8nc-ot&I9?(QnxQux@d>iypD zM;vF&ojdon$p7+tmF+z}Jx9K7&AB;gneS}3`8A(7*G6ye163YbH#e!u+Sl#zyZz?< zdw*rO9t8#!4yMw#x2D$pc*wr1^tIUE&*$w;^6%Mv{NwHAB{Y4$U9AbSm*%^t7H)6;Z?@8921sLZ&){C>^mV?~D!9Xj$f zd|k}SkN2LPoqh7iktN4!4UCKyH8QgYd3ti5ong56)Pd8cKOeTspSW;g!?91jy}g+) zE-VZ^7IyjBr>CbM6-^ZuQCf6)xqtBWb+Oqo;m7-AUtU`3U24Z>X=(Z8alieg4ngH3 zjJ;RaZ`x$U#ls_VymPgtVvs)QG_YCr^>!~`zRbL9CoC+ytK#FLYlXMc&ddmW{dwx$pU-gN!NKOO>lUY;o~FXV zT_LUund5_)Tet5V1zH3g7&aW>on-3gtSo_(++FIGzSlGXm!$~-@(iMT+7PL?p3{BD|PzfHIv}nPft!({CqmS5WHfeRngQ` z^xCy+AglN8wcSXR%(}a)^zcmMbOCw!{?E_PE8Ez}q^71C zn3{r4oNVKjX7l$yUnR?IY;1gHj-{}1`ni^%l}A8lG`_uM8neGn_UF%^pwsVaYHG4{ zK!@dln&6;PbZ7DNLnlsfTwd;fyp2~{KuoNyTU`IpjT;hwe|j#<{uH z?rXGm#`s-c=BpeY9`5Dm_pHIhXz9|WO9C`31Y$lPm8f>w@vPhMnB3y;_v_`?@Be4D zX6;%_i73!G?(+F{PHAas$5#kuov9Hs20OjFPB&@`$L6%Nhc>02UN!gmzrVj37=(p| z`6Q~}fEtlaO-y%o7PmJag!u2qXVB6?76uh{^>Ax{H#ath12=B`XzezW(Pxf zc(`5UJb~KUT80%HUur|ccFoDj9$EPs6KBrkd~kI2&smnmYD!8<1_cis>;mU0toxY+ z^=)gw^jYiw{HbBkk2`zaUB32+`ibBJrtv)+pEKHjJ}QyC=9_-E)s-4i5s^I;PKsAs zT``RZc^e!<-(psKpPg>?^U}392G-Wn7cXA)@bqkq(W}q7{q^_z{oST{3<8ppop*Pa zE9>j`^WQ42;=A@VCIu9$63J^iXPD(mfeNeTmHjf7O?7{NJ$!d}_oFROPfuT5{r%mC zFJD@A?zFsf_wL2z{_>!s?V=_(J$jV1CVs!%!-o%}t{WyCU;tJ0mX?-Mmz9;3H-h%u zNttrJd-qPlFo}gv-tNzhEH)7?)~YWr8n3O5PChk7v!k!CZTfWaUFGll5)Zc}URvT= z@%?W3#JO{M89*}!ANJ2$?>$`)ble;xBjbi`+uF8oHwUd{-&0xq=il%5SJ!>NwKe-u z-PW9&LdtGE2NpWFud;c)Isd*L=%^j%c0N}hAD%yd|6W|?E8Qb$%(iXYwusGXz1KeJ z$M5R_HRqJwdKz}`wsz~6>wSE@-&`Y)tCi{hzwi4Czq|-s`#wD-CE?^GRSDZFlcuJo z3wtVyL33b})qD^2N}EfS#DI1O*Zuvq(08`khRvIs=gyV2DtptR8NBSludlCpwTi#K zx+-B;v*X8|INwE!7hl|6p5M~inkmzLZ*TSCEzO+uQY@ote4#>)#6(0=~Sy&JQ{UB02WwpCoX`>-W!QFiATjQFUvUX|@}KhN9xa zYnAT3Qmzay-rU>_9_1BaSgW6%oz2C|dsQR(`@6d=4KlK_E0-*BdA!%U{9VWCWlNR_ z2nHr5DxRHf-d|EuvSr=k;N^axeyn@n;fIIYj~emITDiEm*#G(9JoPJRNVTIQCpXtq zfMu3RrcmkodwXw5tcV8}nwHk}xxKwzm?7)-Hr<)C zXNS*>*P43i<>lo^e}4Y_`Q_a5dy1Vdi?;rev#kp7^Yh!ARPy&%Y2nYF9-hKqe}8{} z`F8t#HD>1Ktnc*~7C7=+>7AagzkZufr;F44nopj4PssoURw^#gK7! zmg%D{Cnu|i@AfsC*;DuL=X0&6E6y)n=-i$ad!Ajs#(^Q@+nbv%E+Qf#E(|7pFE@X9 zxqSYr@44WC`maZ2^9+vNaIUGT0UhZQv$sn0>@3sOg>hdS)=zzYdrze?s1bi|t~Kbu z^P4ws-q>4hUia&zdP-Va(xDd49aUdf{ot;L3qy~DA=B}G`SyML>_AIm8X6dG+_<4&Vj>c~Eypn;Lc*&2UC)IJ z0TEGAW)^&6Vq&1=prfl>`1F)0sAIHr>CzcSsa&5veVQGH;wPzPn=yO5}-&iJ-aJ*VooEG8FBUS+;E1i)(A8L8DUh^o^;f#X#d@vAfG$ zGcq#fW`}op{D~G|VOXU$4Ycax>gsSs4kl=mrlPXa(cPWhYpIY>CyTOMPsWA9%I9;- zK|Zaoudk@6a99}d;Qjvp$F|?E>z*=2L?>>K1nAtQ{dIp|m7aTlf4_YA`na{FySL2! ze0rL0^WMF-R;904($mwYOqufF!^6W7o6~qdefngOeNCt2%?-h|QCo$kcXoC%GE`Jn zX2zaBd^Tbys4kUAesi)i%`{$7QIVx#-;YP#QO~z-*r2d7#OvwPr(4fee|qA%ahq3c z^b)h$UnNYS#X6T}+*=*4&*UIq^P$mAcjoHV+IM#rFF$2fR8+Jg`}#WY{L+^jNk%n4 z3YZ*>)6cCblQT9p_VVypaNhp^oFze;d;fmBEg~+y+|a+UaASlrXx^pp*F4*54u+jO zb_CSa)J)w}TwJ^|dV3y=!{W5#w{Fc+5#s#&;V}P_5UryxzrVY?m{VA-#2RkhX$*X7Y+;=H#eo0_IanIEZJfI>ejJ~i`|78KrA6{^+|p(_4n96S|9(D~2X&$|Gc!TMLJSE%3a-}P3y-g5?R06{TmAje*|Td; zZJRxFX5z_7sxR*CwZ674wwsk(tYhyHTP|m3X9kDJ$jGgqHAJ{1q@@qvy(>F$;>4(I zlN6(w5z-Z(pZOMocE=p~n{{tb<zP_MZtmO4I-#hxu%*+vyk&4E~!q=`{OFApe zaO3vv$J68ME^5Swhl~II_O^NR=HjWJbaiz<{(L?^`9K3>#NH}XyB`mjJ(g~*cgrh|F8PYY;%6lq{`{IT_u{JjnQkOwt6L3%{I$DvaD&gS+3J`z1R)u z=jAk}dVx-pE`EM4Kx=A8U!U9me}6%{8FKFLi+ycXR9wusV%Gkn$B!Sref#%H)%f*$ zze$1G03RP854WDbcdzZH&6_9Anx&;?5EvNv;`(}d(AF1O>#{35;w>#LJG#4@*RNlH zW6h_7&Foj#`Rh$rHZubq2_ZDwCTp=CXw1*k(=%%Ffn6%`ph1xLfG+24;GahWk=Mu)wVjCC2$WHn!>s;XVr zHo5moweHztQ}gTPa;eMR-QA1~*REZQnjT#K;Luqa_4cyL?>-s4evI(NR$I>&%%mt5iTW>kQj!Gll~_Tkh1DAz`fa(lL8}3Oe7WooI-Kyx@#D&- zrlL!iE(I-=C@L}n?IA0C?A9Y~&L?f2C&DhU?(7uJ;DXQ3d_no{{CWPmx;g`6V`q@B zE?+ME{x0@JiqVs&PeI*8Jw3frt#E&T{(1A}b#!$(xwx=^T8OUQVxav_5xYt>LA#{N z-riEQw3JLuP5toYi-_=w!pFxHwY9mYO`G=N`}g+w^W{rQOONJiX=pTbc6v^oCvnw2 zAjJHO!~VLz1&@w!ew5Ij>hGuz&x#5wKl9w)D78Dc=eE#X~-Mg<%=5Kq#9bh^+ zW^dKjAN5OvIu9Lk0+p-v8-N=ix!988A}AKq&A zddlgiFRrc@pEP;$>b13N{o46t1w=(#H>aO>ijSASzCQl=mzS3(PM+MX>OC#t{=VAK zb3bEumnmv%d;c*!bmhtxubqK`ff9B#7VBbmE;77(^e8LntlX=s!$GIg6;=fX3O+kG zxBKPg<<9>8{yskKe6mr?mo0#H6ip35g9u8>%7xF)NP^ZSF+6zqQ1P4A_jkMBckO?& zdVYJLddRU3Jy6rxq`B?ybEK%e)~0R)_}a}*vw{o zEiHTL(xv}@JFQhToZz8iU})Ib+1YtR`@x39!vYc#9iWENtu2`^Zf;KReH~=py=C*} z)!!^NZEbDmSe0_QguFkvCcf&WYR=6~tm)_GI2ILcs#r5;?p)9a{+%6#&Nk1ln#RA% z{q*5OLt~@k*5|ENG22i1D()_M+4SK<0jT(J@0WAEzpr-U?AhI4Utd?Yw3Ph&`#U?s zi&w9h7{v7BVxCJm9h1mjQ!yd+n8f8p!OQ&^8t&KsmlfBGVPH5j)0kaY&Bq}vO)YF) zj3%Fvw1fo5gZjBifBt+v5866;t>~)xq^ox&{O4E*GJLq1KHpJ*rAO8}?D1dFc)Y#6 zys*08l@+BcL3^qW-@GXax)kDvjc@GA*|K5ld~a^gm#?X*5s;FKTK~jb>F53M{wn!j z-{1E)H8J_jFjyG(J2WIDsvdCAhH51&qt7h~UEH^Yi^%^Znq&*$u~`Dp}Nn#!>1`POIW z=kqHaa+j|Sd23n!@sTU&n3n9KxXSxl`IkWxYM>iCcI=Q~=a)M&$FdkS%A%sKo_t|} zBWUtWVfyK#Pc1)!dq&ko^CH7PySQ|Ab|#r$cXM-l^8USk+1#~@7d!Lu@m*OJs%>Ou zrq=4@=;8tz`~H4|;l$<3lb@ZP?Vf&q-qJU3a+H*QeZ3xk^1y+HS?2lcO80s#opk5U z9S^;o8e%tfzt_nJ~v-o+&sVSN%+1cLj_kN#earf+5 z-#gn*oH$W+^zn;}i<7>;tp4^!aJMwO!(?@TH6ZCQ}_MW6BOLJYnKp1)c(5K-q$_-{p!lf z%1jQmzrL)zG%$|d#xezvRm&T`qdZQGWFgH2XPQ?ITHO}hSn>e+d=(K1#KR7thW%KbpvrlbieU-{0S*QTO{~tv%Ex3o;lP8!x^dSKSM$<-I&T1>3DJ zT)nCq8yjm?{w`*3-^QSoD$&u=RbQ`$zg#*!PKlYB`PBLI%O5>T+O&PUIQt?t2lM=U zBGW-*TbxY}3@7g0n+G}~<=5kW`xpQI{$3KG0a|L3VkF7gq)^AF#m&#Ze8L2QSr&y# zXXjc^KR3_T+iU5hTif&f8D6a4|8G%K6Vt1Ed#&Hz+S)zO^j+3G(Ad+Q8e7JD_wG%Z zGsma)_qV0``~L*Z`S)yg{-p_u&M$6kOun+W`n%TYxfX>@ZhbPIyLRnLn#9=f~d3}BT!_f~JOVAkVcVr65ybZ2LA=79#rB&H>G zUteGE@920^v~!2;yLa!TIvrwH=C^6@kE{P%s->;1tfUkj9nIt*ZI-iQ!M@q zOie?R*R0?5ZhBRZL2YdF6Pzk?dxa! zSQ)SE*0Unm=h?Zr-V7QF3J%Ft5fKuWmX?`QG7}OU%F4=8l9QGFE?>R6^zw55>#r?T zR8%gs%hzcfi~c*wLnS3Y-`~~M^~$!~+f~!OT|kEsT9v#I`1?Bk|DwRfZk?B}uaEcl z^YbhD{w}ttpx}Z;aBs(pS65e?Bp>53GBmt+Lv3Y<*IcVorJXT;Ml*XZUB3K!kM1kO z(^pQ;*tzp(u&jA6XbucCa`jaNG^^0n)s^w!Kx4`8Z@G|O`f2_BOV;oIH*4R|XS1`W z>uYE%SnS?^>Cey4E33c1OG!<2oviM^j9Xl9!sgAzTTi>Xy9fLD@XWO;U3IH6@6Ha# zy;Wa@CU>6F*VfjSGEU>ky|tw?C@83-0~C*se)F!iwW#~EW5$vhGiF>kE?>WR%z`b&d6A0O{m_xJZ-%dDPV{PdLQt7~hc zryh|2uhQF5_&DSAG~JT-_x4&%E&uT$@zUkX!r71He!S9XA-`(*%dGe%)kdPDTkPnO4 zg#j0uSh+KPe|u|E{q0TG^y#OcibzR$f#yv9{rx?8^Je3%nU~u{xL9AlcyYyY-79%} zh6_JGKR?>IS(+KNvH?^(UKb7u2v9J4zG}^qB`xpn>C>lA8is}&uSuW0bSY@< z>#N&jpP!$oP9Lyu8dd$fl^M=*5GB%^@KnOTO0To;@YE zt?X?Slf$%W)27Uy|KH>H(h#lHx{KA09z7}|Cguh*3UpZIEQ4zOX6|&$q9+`T z3eL`l*<|BE-sqirKrx}mG$@UsXjkd$w#&=?i%sMh1rMG($5&TZXHoJ(AjRmW@%?3A zUteGBJKOBVjg89k3&cYrBPFk`i{*}ujb&kFJ$U2@i=?FFkGI?JZzz21CL%7L{OQR_ zQ@)wJ(Aeurmm~YJKHSx(7M>&6DCe<+_T3dApvTp1xXmeZ9rUq#j!?Sw6<(HJldA2`{EKw2ehJ*T zaU%y8*P=apY*YpJ@;nf6Z#Dd;vE!y<@|u+$>WeOVEe*0Pdg5VK_=v^5#qiq^&{`r; zk$>k-Ok>Br$49yizgZN3jW1$%2+GWSIU)Dc%(b1k%bHXhIV{_d`XQ3^+D zN(u+VH0Fp?fr;SZ^=iRb#saAW6CNM$m%g{Fl$)82r(xYXJ@+=lZyq9Cte`^|zu&9o zfBN)k5koM;nnx!Lz{~yjo_NP}gLT32udlDmetUD1SzKIvOWxgC%7-PgCwNcSOMG)< zk^n zc3SGdYKAyA0fqx|4S7q?%V+-d2|DV{sUUm6bj7^lT?`M{8nztYQ7gpomf;6u0c!%A z0;5C3(WS%TUI`cTCnEFcg6-@hJC9e(vz1nC&)CMWT;{gC@Cqqu-sq1N6M7z;K75SE^r^8 z{ijnmKKFGL{Qj2P(%$~~KqIq7!2^b=Q>Ls~Up}2NhjoLXgP?miI3xOYvm9Vyn9q>$ zQ{?*UH5IXp8~6@5GDKcIvzk4Dv4Njq#uek2!3-908|$af4iK_oJmA8RlrO`^#wH>l zpuob)s;HsCu{L^p+tQ_~IyyQDSy`vjjgozR0s{p%ZQ3+p>eN>2@^=powQ_^b%xvWr z*HBkq{%NltS3@pCUE?ZI#$-@(ixBqNbQDAPdTOfn z#iicU-SyJHzPfs2YqmK1mWiiNpLQ-QGuyOjlfv}y+g4V*2aa}Kms~L`U;A}|Z#nA) zE{Dxt*Tbq_yg%i8__6l7twnZ5-~z9@XqUs)oTaYHckNtVn@ZRmx7v{yvwosin#d8+H{(eOQwwEoKSD$MVf zO71bdX3)lPEv)9|CGJ03&9A1XB-^RpFy6w-;Og#vd2!U%tf{~5#2rtp&D+YjVTY39 zs&Bv4CVF_dySJ+dadI{VJodI--`D3?`gAHY2m1%phJQ6@Q{Egsy8n$~SbZZy8FR+D zg$!DGI+GTzV)c1aup#{cLxbYWmoGPL-I`mVn3|fJad8prq{)*-1FqJo6lBa_{ra1> zsD62`w4!5!0*8Xqi&w8e{o%H@Hqg>VAGKy5wbfgHZVX!Kl9{>khnAk6o2Mt|lOoG0 zUaBfWofh(f3zZ~yGdy_T6)v%*{MSQ<(A+uJ4NfbvzP@AhU=29XK6T?V_fv`qYvQUL zOxbz_+aJ|`*9$Pcy_@l>ap*%Cp>I%7;dWowli)-#k` zpH|?xG-%^ySx{BG-bHDmgVxkTCr)@|C#g+89T*kWwP%mblV{JI^rm~O3VFIO4Z1n8 z!>;L7*zmcIftuSkHZ=M zI~4PH9s>=tm};(Py1}v4?siT}IvleMMv$FQE8iz^@`gvC+d%E<_!hERrm?AO~MrNbE!27AY=e+^bY-s^JI z_l-7#m!-@b&eNYheAuv~^mSM>w}efF0iUcD%ZgcI^Pf#H^IXsTLvR(}M1~bvy*#|U z4<9}H&saE);+Lnq`s?*@1O15AuEtoHiH=gl$N8FTN!Io5M?t(X7%Y}3BU zQ#fWK@;juG6O_D(C z59XQHuGsa;^kIO_w`|{f2J3@oEp9#zj|vOB_Mo-6xcF+l-Gcx#&cBRr99`e`x+sCJ zp0Tm9S+IEVCvL)jp)46l!{BvT>%*;Sj-+g_4(vAX23_Cu)JOWC` zw%*!|TOJ$OYTzXdWgE6{&!1#HdFIT{8#f{> zEG-Y-yeS#<@^ZCKn7==NTwI)iiOCdCl}W|{U%gI)gMaxk-UDiUhl3XePkd6;uJ)#I z=WmUZ)2C0L{>xvUFLm)#mQZ&=w^v6_U%MvO*XNs`!l2}olmt2y9W(_V5gBPan|os) zpN*|;Vq)S#<%u4C&ZZ8g$!|Cx-#ac5Y-_%O`_G4um;Da>V^xqpP{hYx?ZVkVsiv~J zy1TweL;CIBQ+f<$ua2BPb&AW+&(Al{-OJniC|}&3y?Ym~|DWUjP=JLoFE1}ZLu6NF zWu>6k(o3Qadh?5VY%M`;)DNN!d@^n6Mb2AA4(RZ)R=aFxP%tw36gXLb-OsE!``9i- z&eZ|Ufb7^|vU7>Ht}d^6{=Jr&GbN+8W_>*)y#7?wmJHC=!(c~&b&b0hroZWY6nFea zx1NB5MZMU(l|>A}jDOml4@%8C!QC|B@slShQ>IJ_dEeT}p{Ay$p`+8o{@~ohoDesM zt9Jw%R;`@V-_KuCDqUaa;Bw;hY3Ia5#!HtjEnL2wJ3U=|#%%L*Zem=mOo4%c8rs^s z9bEo2tAJ(!zPZe4eWjT9?Tzq;jSSz4G$NQ~Sug18>GA1CUHN};>VgFdF?%WkIjxcU$}T`mT;$ux1TUYisL-(@z65L?(E&Xl=K3@e){hYV{w` z*0xWRJXB28!o8LXc`X&@sU^ zY;;`Awxt8+-Rm3`KYji@aqi^qJ$GuJJbAK6VZT7D ztE+;N#EBHp4g?qXrca-Wrkp$-a&m4EXKk(R)deTm*bGce8kX;tuKNC}%}<|oVQqB% zliIe!%} z&z{41V>QFS(+d;6{;})6eD!Lnx3910nzd_R#~uJ3;8Xv%hL}!EaRW)Bj4oW zP+9r&b5X1mtAgNxP`lVjTM5mnr|y-NmA$yKGI+0e-nBK7X1TXm82T8t6 zoRX5VL-=Cpil{DwV{*s;%CtA^ZMeofI9=h((16a zODY^1ZIJW2Abz1)} zw&2f&d1@Pt4Y%hdU%z+1@In9L9fGpV#l^)lX3jL7Ico!GH@2bS#*mdEQH&Z-E>8yS zTv@Ge&mfr5vUOk3N|9?}(`Nj=7SbbOC2%iptyD;#)4~G_mFts^zItEy@>A#(Z4nLa z>Mv@)U&$R5;bQHWck8ji(}3Q?+dBMX!`y!}^xWB)%zms-Hu`-lzpPcu!De>mRcY&$ zE#~;&4G-Wwz}M-*l%Ae`cz2i2N`g%!-R_%ea{F0BKbZ@MZ;CYacd_zE1R<@#QNAkVhn+={#eQ020RI}*y zFMo<4mp8NI=%cW-!SvgjOS_T!tc})Kb-h@;?%juy?dQ| zle=uQSFT*?;qTwS%HsgI>l~)-&hVf8z|Wa=4_FuvxAPpBbY9G4N94oByM!ub|KIx| zKgUkE>-I-Z4SoIgzCJ!3-7|)DZ?r3t4`qM&{&`(+q~uKg3#b08rldc&TYGl8b13&W zUG>B@Y|ok$?p(Wkc{2|;xA3j)>+5?z&9klk@M`sXCxI3TB`ya0_n(%$WZV&4xVFtj z$#J$>uEInQ0eN};WMyZSV{SI(*0E7q$In=PE_l$NTu@Nb;-i*5<@U-DEkQ|1&Q_<3 zyayufV!@FxOM=OQS>ZusZi9=GV}OITjP(xgw6tZtued|^*78oBJe&Ldw%7^N=JhTA zt|1}9P{uUlz;g4|$5u0x?cBBN(o*l~QdhqISrfVW!{dH?rUPaS!j?L{_F8j4KQEIR(mDN?+VjBKyJpOu`Oxdf{SDhU zSI@eu@tPsy_;T~r2lE)Tg@lD$ug6vUW*gtWwI*(_RPOC+$uVv8Atdc7gHn z^1I95w{6^L$l0_(?mz+GOJPG9QD!afCeU5u8_f^*^zhVdt$4^S*b-;EE9qQx@WitB zagWbTU}Zda?%aio7k^HK*zYrYWyOo@SC;=&P0dMZ`MZ02(yb@ri&N)po~(SxPqyvn z<<)nsPc64t-O9A;VAbL8Z*De&PBz)GV@DioMMXuz`+IwvKu78+a8xt=v9JCvdoSds zUBRE(SIu57($&?~UHoS6at&t}Gp17luG4r9?k(86qcZ;Mb1~7t5C=g)QP-4{6ZWP~ zjlC7L>*bk@S%r1=OM2IeXvhZK{#_g!bJp|Rsk!Zw?>x78UiWU&hH1NRw)W3mxNu>^ z>Q75<=A^xey{i7aHuYSN((CJrs;Wza-o+;*C`k3H3A|7~8^+-M;?q=2mmp{raO3 zy!z+M-|G#ficg$8xpK;H2`Q;nmoiN9y)TO{Dp~TNZAI5CChNuq>5oSxqqJM@Mqd{Y zjN2W=uBm?9qsU9k^Q5MV>hc8|T>t9oe*FCT=>7BA|F84s=N~pLSG}|Qze4S={sSpS z;aA>0XR6A4^+>AX;V%B16$cXno}HV!y6VNk_H{4k9X~tU+_>UH!qFTv>qgE4=0ewu zeoy?f?qSx}S<8H92N{^nKALne$xNuWCVngTsbBWn42sUUNSWsKxGi28^7~nVg+d#oip1*O+Ne1CqQ?CZ=M3;yx?uHc%q>d6zQ{@|F)o+mYz zELpbj`zIw6la?q&#VcH#$MUvMo;ugJtc)-6re#WM>g1_&dk;Tcko~)cQrd6et#@yTgZ{yJD3z~W4$dL*2=GnyuPLaIS1M*c!{`Uu~@+$6DR!iU5@yvZ!$*Y3c z?bZL8`!^PT4x1DlbT|Coo&Qd;_1Uc~@kX(i*4bEEx_x_Ned65R>YF>O<#(68KYsuI z^x3;gPx_y*y1Xp3JL&v6z5gG@)%Wex0$_>|6u9W)pdV=v9SEPoA~fhYsIs@ z-|gM*8SaQ;dw%9-@s_ujK=ZjFyH>}Gb+-zu`#rIm>z98((>IdCbDzuCCG37o*K2u% znhze>bacL9%7wSr|N73isFdR8=g(?odHgna#fP_=U58Evr{CCF9sh6t-Zjx%=WMv} z==?c5^XH{@KPnt6%N%XEO{U53USu<=Vyf5IiHkH8*G6v-10^phlZ=4QT}q()1Qeay zG%_~vMlg{K5T}46+dw6}AR>be$2Rfnl>J-i39k&jg`S|f;kCbUw?C!FKK`YN` zbr}g+=qTz=oOU3vK=c*|2Zw@@(WSphZfE~fqd4c zBy@Q#t#SyQvWwyE?d|E$&dltQv7B_^z=0(3s67>imzVp8>xgx8{Sc{OIWf6F%$s=* z`yqxcQM$Rex0UYC*c#Q@-K}bA#-*=+K1+U$ar*g-`);o_$-A?}#xG&&>c_|XwbM3N zT72j>$yW4oTUWyw=(TU3-JTzRCJS{4tqM193XiX1%g=v*XqiuJF@5P3Niad{R==w%_i|xz_oEoAdgv44n(I9#b^Bq!$>jd)MOJ@Qu~q z&CSgy<%B>RpDgG+-VYx>C}?YUdrnpZ9g@BKZxMZ+VHWh|?tf zKweh{{l~keFK~MA^X=oeXIrPwdpePQdFZVK3mHD6&6_;^&nws}8~@K|>teE+D>m1! z-Ea2)@a4aMTh0|*8`kZ&`tbex(?8rwyl!*ilc@0%Q)vm~IxV;4&fW5947LrAFCB4J z72xAxYg-Yr>b8jMMdpg?YS4jxfnQ%-Y@TOZUG(gXq+I=PxP_?(W$C5|q-OD_ea2ZPZURia0Q_!@z_Mn14ZF4Cb-wAcq7M1u# zRarf+>$)HQw4ZWn?(*g8ordllD*_ig-E#;k;(DI+XhVcfgwD+ zQKXxamNt3bM8~QsHSx=rJ^jxg$uN5O{Iz#N0&f!&GY1ck!U8wmD_Npuvt?(WZ96;f z|Mj%rzb$9W?!Mc1Ht%qX(d072xxc=?y0F4grB}-B(vCppsI57E&->nb+2~!e|GFnv z!n*wZ;k@nfxz}tSm?f+>$qwYKWZeE}my(&piq~}qPkU!xSuyd|i;IijeO5eReLzNG zyVUU;)>U0y8NA#h^rW(T--m1U@sA$P{OL0E@T(LUr;huZv=G*&c zWxZ1GT6AWLzbB~Wu;snq&-ib`n#ZeUW}9a_T{)O5y6thie&n&`-1`nC7%aG6z3}^| zLkSlaUw?hEx^m%lai8kM3(_CHe^)h7P_VzqrDCvw?O$Ep(@UzCvd%uv`C{oexAWPR zmz(EU)lREr|EKgTM#pwn`NM1Xwijf-pPhMsTWRNZ@zOsk=3nJ}!pgo~O^fC0nYK*l zpQ;q2ZDaJO|7JU$ELajWH%R2E-UAQQ-iwT%cIW*o&RM@^jZRWhlEJd04_>}hT>DZ! zY;D}}E0O*Ja&mzyziC@r&n|v`Ztm9GZ+o8v3pq{FSLE8lbdUMhv{KiowQbAg>pQN; z*R6|U|B_V2Hv9jbbIWvZ-`J9B-Pw6^P2A2Yd9hY;r8lQsF-f!eqLO_*|4`1hn9OVT zjd7Q1j_wbsSm^RbEG9Xc(d4+PLQUyq!5h=(w+Kl{c>MkK^{)Oro61QSq7Kfn+Z7$< zXP9FqZK^ygaDQFO%4*q=D|NEARac&sSg9t9EmGO9tje-zmPOZUiQ{T9-}$G`a?DS- z&~STItwS>t^N!*l0`Fw(SQ?&83Heh~>%Aq%qrmr>&36@P^IYb2GipqyEYtpXRPVv6 z3y}d!jRi7deTDTIzWZ*{n%XsCg1~p~ojZ5VIGeW2cUs~lJ@@684J#b%%ii3JU%5-} zRf$!I)>Nq#&Dk7`ibq5}W|{@gz0qJ4ziv~6PRXkaev5wcZ*^+A_}V+}!>OEY0ZmqN zrYf5jae1-}+0AGIlu% zWxLm2dOJOCeK@o1ll?mcCe?6$^sj%U6&;rqHP`Q*y9T@3WXY$mHhV5;T_JUhY2Slg z*H?$Fjd~}pBgQQ$DS2hBuwV0us-^cFzUR&Tk#LXc7w^9A%@++*Z$+*)?SCJ>Cgs2e z!#)3w?VhUEvHk9?$zQ(kh`6o{kzd!}-|w|F=tCz0nakz#y2AEt9mW8Qqz ziF1>FuZvfQ*1{7zWEvYA-yPq$apQ`sS<8I(EccPlxWCPG_x5#(7aDHAxR(UzsSl<2?TetH+TzGtb^1IpZFD{Ig-c|b2o$Djm{JHE8FTJ#qbhO@DvC|I(Z4d*k{S zX-vFy1=RTKcr@kZrO=9q87>=aCh2cxUH*90$>}NSPJe!&)&U^*Bw4= z+_=$VuHP${mf-zybBk^#+_e&16SJ>lj*N2kclng>_n2#TW@sAA)lB-*-+nw`AdW= zN`L$M^`w0F2eI$Pe#?apV_ zRf~hZU%imE^~(D2aHR;oGh*JJ?~b3C;K3QFdPLmj#M!f|dU|}DZ}u$GSYeuVtWT=& zZ{3d-|L@w@nn>}+?k-VLS6{yA?Q~&|3CqA~=}&M`rudgnpH#Mlb+~MhdGhq>!yUh- zu8-)PA`p7$S`&NP=9yoy#=1k6t%t-g^7a1j`FAOWw_Xr~PQNkW+}3Kf~b$|2clo^;tWohpkS$aw1V^ zZgxrb`q>*J&P>gkza>g{%EsvZpxmT*GF;Ga`DB^J8-w5 z0B1W{#dSVhc^sbm)-~QuQ#UsLz3W|0TA0}FZST{LuiGnQCv|k@=I1*mOz?=C$Lktc zU^Vy3YUzV7tluYmYAH0yyRyLP+u^j$8*`86)y4djer=Yc_O8Z8YbuvNzrW5-v8?vi zqU#+Cd8CaR-o;wSeqA-qZ?&%Hr>&v0RttoBF+6yeoN@B((&*`au4xw1vd%$8TwhoK3*6X*CXXL{l#EDkE#|7ot<8~cfWi53I4J(;@|td z{XZW(X0`eLWwFiYCx=yEUJ6&b_&n+7`P2U&FORQtUVSymXlD1D_M?w}t+N#uK3*+f zd+d+C*uw$~39||YeY^iEzOzlV?0#N)84$m7N%1a~c&89cbMbi@R~Fc@HOm!*I_%B9 zlVbLNr>wre{+h}#Df6rY#{PC^R!lt1wQK9tn+uhX&oKF#$oKBvkM(>{E;#&PjIc(75GX!p0B<6%9ie@n}pl@T{eFCEg!kNPB>8A@6pSbFa3@b6|Z#_ zl3D%rmFV@iW!7c8=kCnk=U(KcCBMgZdyZq*{sYCuap_0TuikL;jp|CDjVjb#(iQU!^PK*YnlY?RzS9!ftQXhd6{{8ReX%5Sda>3wgdKYaS6Go>c>wgbE%AfxE_%i#z)mJl2q(W8%1Qb}vyqg@#s(w{x zTFjOx-o%AlGj1%fE9a3s(P7OdC>FK)%I}MNB8AJDA|!VOSk3h_UB|e!6_k|&TSPrr zy+V!c-X>M8G~1Q(lHcafkK%~WYi69C##P&_HhJdudw*AioV=bMuk&c*^8dk$YC~3r zR8&iMy?wMogDY)ww$6HC_45XKhf2a~zN@bK)8f7S@-BICWxfp_!J>;^sl{8(o%Z0t zEQTH_%N}0o|0yRgJzWu^wX5viiDG~IF1N+cI&bP1y*d+F-nh_Ttmb4ox458KRQJcn zZiXA`v-L0sqnl!ie zYvDGobq{tTmj%AI;*Vk8fK1=xa=3?*R<9lSh@zuf7! z+MQ#TqVDyf%D+*JPEt-8roN=jRpQ1a+t$zJA?&`Q;Mt<$NWt zE=;?&HtNETKxP};|8}3VwmuUSmOj37hQ*@3`A2TwcG$mf@5bA2UzF_nBOkX*TQ%O^ zQ&@D7*Q&4OpPo7fJh-3ysqWXq=r6mLTCa^VS?>E{xA9JiLQ@yc5_Rq9{emYj<{fy(WL|CdzXIX>$UpPZGGhsRl^@Ht73A4P6Y z6uxO``A+Xzr{~Ex_5~fm%NHBYJS*{~O2&`f($ej_;XAJ{Rr*_^bh{QUxR{}5*(RgP-EhKRq$lzqqkBdSBEB#kEmp+Jy$~JiF%pt(V>TP=3|fH0QNp(Q~KoHjD&S zG%LRS@!p+~_H66i8>_?3n|N2(KX7sam2Q^ekG;G?v_$Rf?o~+h{P^`Nz*u9#g9i#( z&*mRIbMBnt@eCDZ<;l+OeV}0>zJH}6lW(?6pDwO8dFPGa8?I!TvNg{G_0;~{vzxJ< zVe-rO8$C6c=32*mEDirudUN{H(+dSc zCzl^&b`9)OG1QvcRhaxv=i8F=e<#0Nn%bSlBVpDyM@G48(T@5r;wq+^D>Ikm+&s3A zx&Gs)*ZCix-4U0x&kLD2*=F{(oaN=`7cG4|zrIk<{?8X~zvZi|)?9vBvVOlqT-?cB zt>PtX_f>!Km{*k}7PWTTV|BkmlUFR&-({aXdAT{p!{bPbQL@2{LJOHEPj5;TUoVK8 zX*^r4S2`}(;P;nZGndb+{@GT)LTxhV)~MQmB5j+NlU zFT0*D%Z{u2aG(xUcdUE6e95Nr`;MT&vSqrrJ34Lqk0u?QHNE}t!-O9f9Buxc;IS&r zC_j6<&|=QJYWBRB7pG)0Zcc`Ohc3dh+oK&#&Eosu#CSQWR$oop8g=*k^t&84Z{F-W{4hfAY;?!!U{4Mg(jmWXj-za4U2x#?(BMV!$*I&-q}8BVcTS8x2&+c$0nygBjf5OOZRWN zJGZ^jRh&3)JMUvBr$?c?|9{=H(>nUv`V#;9b}1t9x<4k|N_2fyXHfXcxn_UT(&`sI zLiIB%q%-bpU|hfViw^Ve@46>%v_8$d(;}I3e{27P2M?sbEtIpZx{|jwYBv-6l1}cz z)GW@%6>V8lQxo^z>%N@6cy&sGQ+8|2^dsCS_PhHO=_sz6xwuvR+>}QVQgPNj%+~)G zzW|}4!O?-ZBZB(7-BUXd=d(BrojQ_+Z$kse>mSbbh$CuSIclJ&^ z$o%{6gd^Mux2AlY;d4y-TjQ=>e$O%+oG#|+OwB;&EK!phn%t( zUayY*xFglzMdhQ3Gmp&u*WDmxTJekRe(}}U(`H|Ixn+jWvZDBM&vy?`ojd2Y_~MEN z>!p?4g{4L3r?2Ri zU0iqAYE|{)9n+^T|6R8#bMo=eFPtymJ^uLq^?!~50S9<_S9mR5bY0hcWA=H+J$v__ zR(%LMdRTY%j8YNUS^!<%*=O6fZ#SPfapLs7@69zeI~OcaxOC}KT)BnJeQ#)UZ)I`h z{u%$QYQF4x`({!8w2!xE@&5UA_>r{KmTEP-1C#sD>U^B}WVKqnoZR#f5$z?~8zN_| z5(xFv`@r`>YloKHyZ^5Rs=vuD@Lv8%d&#P+S+B0IZsrn|>SgP7JG^s7L|xR*SDP(5;Mm8?{6+nYHudwAKTOmhxgIr)9s zssllpFKqX&E3wfv+zykNmgPqDLt&*Vn{)csw~TrY)cjw{qt+IeS!Q`GJJvPHT9(NyzkKomwkRS7T9nx)uyUa zWrm8M_M7h>pQqLYbc^HqCkYWkE^F zmv!sP-rfRlF+N#xa_ZKW7M4SY4`0mMnz1!%>e;mH-aEfRgLh6MmxK+bl&XFd7xMbA z`tqgc;S;~!8Slv2ddhS`(LejuSH050%;al-u?8OZ-}vl$>Xz)wuiDu2&K3I?yl$BI zq9n@3#^%M1eZ14|#H868&F*}B+$i~#i_+`sx*vbp*p!6t{-oNnV%Da{^2X^0OTWH8 z5Z`WD_ekXIY}3N?SL$y>oJr%}n$>z?U95Fo^!Ay`?tK%cPIX;9?d;Ct9|CIrJ8s8n zI4`~!WA>5h!A|K02y>hCLO=~LG z|35#ZdDu2>+7#vW2@)jNcG-kIDzG?t;*81yx8CfyZD|1t{O4y?UHzG6|53ni`RBIK z3%{1X{O+G{V!`b|k=Bk6x86NZe*7qMLxJJlYThR^m&-l7$i95K1!t+%oT40|MO9Vu z*RSf^7nDB#_jLQ#cTZkVKEF>%Q&V#GS+}w>Gj+c?Dd*?eZppmd*3-koCu4D7dc59~ ztaQTz)ed|=-)d&^e|25&q5AH2FHzzSNvw_y}zr4KsNA2JF zbF6B+rc4QG<9&Jlis$!D#h>4cR>_#pJR@UO)bs4@?CF)UX0v(MhDGOm5)~D7b#YG+dF?f|Gs^8KYssy__Xw? zafj91X=l#7>H5#VYF*5K*TdQEqMmygUR~{duyy*p)brc6*8D&0RrX#t@~M$OKflcM z^-ENnb+`k!rZQ%8sp(9M+4uXO`uFbqeV-N6HcQSv`|RKEFPHt91q1{f?(eIO-1J0x z(V{+Kp|I(8%x<4frpL#c{ycS7_xIHGlKgh(PEKC#;pv%pyiaz|w_DkF%J0|K{CMcT zCUW<*7cYuqb`&(qZNGC$+5haq*z3`iukTi-q=ud;KPEr>-;%cd^*d|gQ&LkC4QF@S z*UwwB#O2bZOB+CKSgV@aT2EhJRde&{#_8t**2nEt3O^*n*FNe0PA#kp%ODYpMsUzH1qiR!EXvroIc&%({sk?ZNZnF5qz?iulydZ z3DeHnI&1sAs_yIY^>=OO@855~IqhuHwKb7%?(Cdg`Ppt!?Dgo#Jq2>+_e1vWT^0W4 zkMyq7Axe9$y`Ot0hFiMsKjYRY=Q}?urs@8lxmDUsFvfVsh7AUO^X+_#ii{pUeE9BN z8*7f)Y^EjNo5esw3|%$*8H5?)72MW_UEUhpt`z%pmU;G}1OI9(-z?|h-hs)}#AAYZ9>J!;! z3CkJ-+1uN7FIw5!+HSZl`|h~b)UIv0QH5V_6t9pEq=Iv{l0)VhRfI7 z<-2Tbq_^|Xl_Z8L*D?#`|n@fuPlIoF}HF zr3LMei>)dte;fUM-CR(M+Q`Uw<^3(n`|9c>c-U%cYdN{Nv^K4|nsxMH!Hu8C6>d3o zczbSl4ve*BV|lfAPsR7O*Y&J}BQkXBB6dwMf4=WU-MNGdpPwl6Pl=xHu=(a8WBomD z@Bb-hT-hS}e$Q{a>}zY5*8b+xiQ3X3svY*>Zuw~mivofF)sKBm=I#3;Y0&iD{@0pA z%_UD>6jpteKKK9LJomk9zLk$w-u!d_|K8q%56-^2x;k=y9rNGc{0~+xPk$UzZTRb6 zrq8Tz9BH4guIE}6qGcil>g3q%&3kra;oLX3K3OXsGz~qV3u>N!3epUj7W44^x@-D& z|3zf2w>U4pxZv_j&{+a|tGZCwFw(#_KWK zl>CsWG_#J2i%X5_Km1TZS9j|9XM1Z;W;2>*85G}AF)}vp?CDt&wl-?|naL9;GH&20 z@YpQ&=+u)_(^vFmG4!v#n)U0;zL{ogqhm@N8>IfN2+`tUv%S3h&haeQph{r1m}bP9uRD)pIV(%Hz&E+8cp^rph> zsp3B;roF%UpD&#rmv(JUh)t<>Y? zXOfOyY7M{J=C=6h#rCuhr|RdG{hzV3`isZc|9iiGe6nZH9{VLLxdNB2Y}mh9g4IMS z{F7*mamUot`_q1(vz4)^=tw^9|M5q1|AdJXJ>AmO!m{NAA8yUOvx3ogwn@rQbM6;c z7Ty&#PdmH$(aXSZT@CkZzG^bJ^*;SF)3~Dg_l2$5;-GWteSCO)XPGQaJls}MRh6{) zriZVus-j|J=<2YI6(5y&s`S(BKVC>>ui6(Tf95w&eEfZ*wTEApOqx*87^vKSadGwZ zr011i7QU?c@$vcen2%Z!cB-mJ-<4SHpP;7ea+0scDa2f#QUBM^Uz@6)UOHWOQ)FB6 z^|*WgUl^zP%ypO_XFmOQ-yEyjX|sRxJ^k@f_?`aN`}P0lIySS#md#8)-gj}4D>vvU zfPbG470cY%xiIG2)4%<8$wy?H?>xSE$M_|qlu6dP)$8}Ynz!7!olnLlqDHqTeSYn< zoyE_Swnk;%*uc2D{@1rvoomYjY(Yao%)jows>}O+kNJyqO?aALpP>V&6+CO6)76h( zs%)3{z1g#5g@0w`*Zuj)n{QU8o_k}o-aAm_k-kd7s}hst=Us|_00-)w>SOY-`m?g$M?^V$NlSfoKc@&a|m=mjNkIZ=g)7y^X=*E_hA>d zcq+fT*69!^Qups^c~X*H;r@MD;_|^H{EMXaqjwo$J?rF+=N9 z%=5mt0dud_ zzV)zR!raNhs}_2!J3764`lIL1%a0z>R#s*P&08-mLQc4eOuDpRXyMkKI!-@y(kzCd)5ZP6sWyaC`St=&G;51+E3j?c0{xMMuO{ z-MceaH+mcB@>d_VaG^`9u1;kS$-BBrR8msX=G%?MJ^Oe6+4nx{Dwmq2>eau8A3dAB z>(j$_`CaTzdh2$3PL%iCx9>%X6(|F)xfUa3o>lPmiT7&N*Yc{ruV$G(e7G=c!BUfO z#Z_Alwoab;uXSBRc#F(p!TC;0FKTzWEnfNI2={}x-|Y|H|NrUs#;CO_s;ZA(FFrnF zvg?s@EQdD3koAiy1nfVw{|s?!GMPWAnK*r&U98 z=O@)wv!fZOE?=&GxQ$1ntnEt=4-@k`|Nia2zP|c!RQ>&@GjEn#l>X8=c+hlZ{QA0w zlU}=4R8@UCeQN5NnV;q5W>`(s6n?L{y_S=6-AliH4Ez4Psm+r&npJ+kcKWeisf%kW zjipR797;+`Hl8-mywoyL*?mLx_q=U+Kc22iUfTHj)b;lHHRq1}J|_0^-6Z=mpV-WG zP9d3xx#WKQ{AEz_AXjvk;o^%e>(~2F<+#(TXKtE?p$vr`0&Q3919sf6DeLx zOG^uxzL12?CaH>`0qmk*3>6hGIym^XKRK0^@m-d$nKX5E-SWW09`~wWo94ZZ{pk9= zjc3;5_x+`3qYL-9W zKUrNCq2d1hf9K7dhfiJ_%h(rk9i11Q^J(eTtc;5)lk#G%KYiT2erm;i8=I0Dx?=Z! zXYBj^X7wVCIo9Ib6V%Rzc4(cJ&ImF{-1;o^$H!|KCJ!G!j#X{?{<3MkfyBB$aXMng zbN?BBad*5F`eE+%`WG1@t`Dz@&tK}8VtZ}P?Gw4p?^2%fck92*S|7BMgPZ$k*488g z2@fx?A`6+m@Fn1dO##vJXG&Pv4Ms*Ujyo;f$4&kB7fdI9;lADDvy?UEcG| zCBAIQzdh?)ZnSaUnYnvDoDr`1^)tL?a|!FggN{BkEBGg?_bg7+e7E$&h0224Yi%pP zH~+LT%9e^+JMAw!|HA?+#zjkaas{T|by^rLpVi(f6l1)?$$Un#iBQ1d|MBt`?S~KU zvNsc!y!oK(b4q%;@vn8(UA3`+B5HU3E6lap_W1Ar>btRz>aX>jys}pK+>MWyEy@yJ ztA=w0U%r%aVS%FAY~IBeGuXwvgTXDtbw{`lq?m24J)Y;*Tk^H)=g;f+Po6pRZ2SCu zuB)#a<(y!M^Yu!*w)p&p!n6J6Dekwo=bqj3{oane+tOA)%H*nlu^MgOwBlj?Pk9a9 zXp^Uh%m1CW&fgRCt@>HWg93|i6= z_V4KruiyXl_|*Lw1@9%ke-1qE|ER?3;>(gH%a$z)T6sm4XkqzPz*1*8cye>dt5S{Yk2om6a{m zxSriOnEUQkhvdweH{O1$h)G_@rMOD1yp&fypV>C=RnS7|%{OyYmM;m*Fg^O(HBe+- zh|jmAC@HC}UEBZt4%)chUDp0&{r#HxuJLEIKg|uFv46k(?r(3jH=X?$oF*tE^Tx_A zJ;g$X?|4w=G0?p7k*jO;D<;hP_FdQY>@1Tq{&$fUJ0(h=8|;hSw&)g1`kC0nk>3uV zzn)uNS!u?@#;kbI^zQl8w6w&n&tj)6({h>m@9o2P&Tk7WUS3$|+nV;pW;b5$TjrmC zb64|>8=tSNk?dKd!5Yec-3yvJj>R55lytJx{^vJoeNb|qe#R#2i9y|;pWCy9=LDAX zC10MF8{>0+huz8PXWO>pJp%de+ao6TOkV2urf=E_VNs~VmqB^w1oBX=JX?v-+zmJ#r6lSSz> zonEPs-Y2IME)-|HSNnDUTK9(y0=r7GPOmObD^|JJN+&#(EWstt8^ zFeo3&-dynScTU`Q02Zqwm--N>?=lGoSWKe8x)-}Bz<&qG!-@V>b(&d<+Z z_cu4THUD(p_Q#K3d+jqaGOm0*w=zO!+S(Hm@lGMBa;@rnY;3hllKqxX){QQ|u>AU2 zp`SHcQ@c+5DqVl$s{m-3W9H_03MM){Q@uh9)`v40iFAOb2n%`Zv?@OQzQwyFU8KJL z^7DAThhL}9U;SZYy4K_ApFlzJZ_oL4&YzwhIDY)9>$Cm&`{E0>zLm{fh-3w zvNH6=F+N#Kx3{+zUVRr)XIi!QUsvq=$&-S2EPWrq#N2%0b?o-6ZVlGW1~XBE7c;FGmGHgWNBZG(@S76+}oP+d7` zR@uaUyVwp@^X~#5x=jKVS8Y*x98ysg`ey2Sd$ZiBtKkN1v@Op}Mfy9AHvroIvuX8Lb^P4DHRJ?Xc ztdF{q&6+5-6A2fL3;#qsJG*{I^{TbkY)qth=gH06^XFHzg)Co#`qE0Sz`c|7=lVr2 zl#bq1VyWE5J81>;%*e=|*#^zupVuCn6+i9a^XJtkZ6s&TymKd=!)*6u+jZg&IXP<< zX`HftQhrz53A9edQ}aN~_m<#?&HdscGY_6VJ$ae0)TiqY7hg5=5Pm0nc+*q+AH*fU@-naLv8M;-c-?Oa_`Msci zcMj`Xt1l`V8V$9#%`dFUeC*wSI*r@*H{aould38zNB-7?g^9T>HjE9NVtJ_sG|t;` zDS~efo59Spd%nK20nPTON!XPLtpET1ZkF@{v$fFy`{QKmVq*;-XB?Z`@4o!f4X687eml5_HRtBG=BR}Wr|(JIe*5Zy`9iLsHq;^=vBz37z01n@PS@*1 zJqN9lYW;lw`Nx~Zt8%{|E=+!xa`>3;l2{-8@1@6&&2?XVZ9~~#wFcEoGOa7jxZ;YP^uF>skzeT|D~8ihq4xj#s9i&P;Zdd?&1Z`*xb?| zk`IcXUcY~>?vJLz*LODB&ae5PCgz>Dl_$WXz;~8;?xBCo?Wbz*E(JW_tnBQChI{|4ubFEl+k5z-%I&L9KddluRa`YS znU&v1t#~J2_QZJ;4^ENn|8#El`UHa)s+YnGUwkkGEn!%&VAj!n^JdTPc3XUMf(IvP z68&kS@dVz4jZZ#3KEL17<)5O4!Gvz{)Bmf@_4MYgd7~rZ`qOWbj?31^``&v8iiEBE zwKpbg*7WJePZ&<#k$i&Tos?n7q8d@Z<&&$`&o4NUHj&9^ZNLWX2V#23Mg}#Z_~aj!GvbJ?_{)A>i3mzqvmx z92*(;SblfyEZ_tUh^<^HewSHOTwPn+yU;==TO|sd;VL5|KPXtL_TJc0(dnTGTJpBL zVq?tpnX|Kx=4_jgzIkS2GuZ6V9e#C;3od5-_<4O(?BA-l_3sP*9Lbzk^Ydh?_ODR& z<$m*zrfrV>_Vx2e@rsXE%{lZ;=3QTU{8h}RO`ASVn4AK(%QDLOU+O^wksE9SD-w!HgCAN!ww*ndAfKwBkZ(X93P^XHYkzBI8=c-iE+bDgK3lYMb( zr!rrAbN=+T3dY8>tG>RD-!x~DhKh>Hgh`W_Hh2b3DOa84G(~==o_@>e&j+#@=FOXz zvV6|b!-t(0HLZSq%6BjO#IlDeKmTe-SWNPb-nLkyi*JMXl-3o~vY0=z?su)Jt)21x zo^+4A`KwuBMk!Bh@7PwceDB%otrXR9Gv{E!h0Uq2`P_PEH}$WVudECUIB@*BxV-#) z?`efrb3qqHO+Hz2@MXz8#y8VFxB~YrxxG+8Z#B1EMa7FB$(OHrr=2)+YFCQPhF1&X z?piHLPf0SFbt<)%ue~{T_xHsbUb9rPPT`Dy>WL4oW+Y z&5^8q|F>puisbF`cZr|p->!UH|Nhd3O7VSBF_o(qsjDvE@aTEyn#k=NW3In``O+~W zV{OsvsvYkSD3-`sHLPE9lQZz`-;jz&=hs?$*DQK|<>ls*x0Vd{_VTZ;_U?FR{qI5Y z`48vV=O=7^7W#@I|IQv!e*W{T&rP2*$0siCp5yY%mJ*hRYM>%E#Gv)hq|biKg%@8u za=73A_yobn5{6Yw`Fnp0%I~wD-ud`=*r~bqH+=M;we96O>-Y7CUTu{=Rr|N}bxX0` zKc}5*vhTL}M(FHh$oJeVyy({NogYA@^`XD~ait5B1Jz$v-Zqe{&am3N%>UtDe(i7H zEXnqV=ofSrL0AW!Nj?fozue1W=7tO(Ag!?TKxaF-&JaNtlQqsu6x|P{rR-t zzuuOyTg_b;bM5P8{naN=pFYhNwB#gb;M=)}Ld)bByz}&4o8>%v{F7UM_ko{3xOw&@ z>%8ChRqOJyJI96lZ4NwK9JuG}yFFaDPx9OUn^S)8|B@5Mz0#%+mcQShc6ZfNnQkk` z!(wwmOZ2oYc7|9sRsYhF>V4LAJl{32qpz<_tLqa}f#0kp;C9pAIjnhyOy_xWP4KPb zteSoH*e3b9Ra>m37*_6f0+36{|>ED_+Ie-4toZ2I|`KHsAkCPd0FWJed_{o>y z5tmwzny|m^Z=>J*a$0523Wd`?JYWvqQT@f^K5HxY_;K&2jn;~ajH|C!c?3=| zU#iIkDzUH6w*24jpnE{RV%>w*D_go{x~(EL%YU7F=)9x&M?lp*vo&{4A7V~PO?~|S zdHA!hIsb~StMv6J{NCFlQ18v|7MyV*)jLnGxxN2zijnxt!oTv-Cr+GsvhsMEXr-OX z4z=0W|DI{w&v$uOu>Zf`*M2`O(~0?iT$t*wyGoTJK0Q6Y=i@J#cQV$U zQ}?gi`LOZspXc9_x+iLMfv-*JlT|h~H9h*UfalQFzi}La2UF(gE3SLP{eYKY_StjR z@->IV=kE*GEdTP>JnqZ{@E}_R2>SXHLJH zkrZU~Jn0b!=Q_{3Ru5g71_r(^@%S@5%Q0`*c4_Bq_J?E{eO$!NxD&K7T%c zZPneH!%e@Qe~Wc}_x;q_v#NG>^XANv3DKH*@?pUq#ywhR{X1T}ANwiv=v2v$b#0l9 zU#e_94c$L}{=9aJ^_+PV4<0*v`^JWk{yApSUteEc7Am%r(-&plUTQAp{mybhqlvDf zi{Um#TQ0R(rnzT6?%&2-pr_V%&i2>DqJI`yU$0ufJ96yk<(=;KVKv`Xw|{x@tnS~B z&S0I$U(EMwzB5-=nn{^wIV1%c8E$<3@$=V(Wp4u}O%A^Jdhd>(%ks|DKDB&xZRfYF zuKjDG4r>?RPrKju)m&vlWaQ13Yx%C-V!8ns?U?}gEI2EhhCieT+gT}uM*DIp;uZuhGKELMN zo9FSVkA7^lG00W&l`_{c`hWbhxKWPBe8bXE&I`edg!r{?H!^@1NB zBDqo96?UWvTwZo3e9;l^1#x#d_Wk>#eC&?()NQ#@lcrAf{nP3aq9t11FL!Xg_P&Ls ztDn95De9{DHp%Mb$(1Z@*A|pTWX!yG;=;kdmA`(5-`G*9z5Uz1r@PpTuFw0+!p0`z zx5vkC`Dd{Q3rvg^^JI2@Qav*DFCWi^tgScRu1oYkl-*wV?@avEZJ!b|=U7zEs{Aaz z>BsG-C2#LEMqXAoPPyh#pq&1Hwxvf5jNw)DjiyX`(yPpW&g{oT#M8E=9k=M zwtPPI|HrG7-hceQ-Z3O(%H5YG+nD=2g@r-0kXoC$9o`-~Ieqp8NOhU3F)+ zsg$qIuV>ZI&c=KA^-X*;M@H;i{rrjLJbIU_^5u=Xe51D|ZnwV2FmGa-YRitM?G5VO zYI}IuHU%&Ct~t8eXlMQ@onK$yp8Zj{c-`-9)n6oiyrS4VJw5#N;=cjbT5 z=~0_3%E9DwX-kVh_ysA87=wq;U!OjwyE^mYo|pUI^{)9-%IiDZWJ%=ZW7kV}`z;r~ z|A5UT<3dC7@xGfPt{<6;mS%DmKK5K$si?O;@L=0NaHLEwzD z)3km+%YR$zJyUr7nl(A^>K_>Ps0km)@!ZoQpjxoz!^T4^EpFC-_^|&|?;XRE1Ev0Z z7#8)-cY6P{^GtMdC0*Ro zmbtt#T4w(x#j&Z1ts-7YsYQcP{X_V{mWvrl&)4l0nwq`g#q87JllQr} zfX%$F63^D$I88VD(aV=7&)fg^ad2RGAjR_K$jQqkFUq9Fg@jb2{%`nn-E_^bT-lvF zcXAoHC@Hn z2g_#XCB443wxzwDIbrKF!Ft8UZ+CwceYzsq8L@9m_e-BSzXa4aOFqbbu*AicBk2CV}bKC1OGsbE(HMl)k=}dV5Te(qoIAJB|Nq24Ti$5r?O$8ImG{>6({(AIuf2^}Tj}?}43rF(3a~~L_Wo}5 zTATF$pmVtIzAIU#adGpG99J)T@}khl$k@~Wyo$2%rTdb zcsy}(5`t{!IndhTQdHFQ<3|N(mCAa^DwT@r;PrX3R;4-K3IG0PiK-fE&Rn*3_vB;~ zradfsbbLKI0==pm&M|0B?P{0XG5`Dhy1i$#w?=*bGC{V?6e#SC9xUw?jQXYus87t=NyCLUs$rWYHf!uUJuV0+KL&wWC< zXY#feKYAkh&#Gq1em>c!>kqsCczq#oO=TquE1Q6bghxOCgK5@}%~@ZqwnXWcDjn+N z;6MF8dbX9|){mb)si+@!>ATo*F+)lHxJTc`6EBS~%Gi{&EI7bmRhr?xyzlLcD+_gH zZ*5-)TK>Yi*8l&*oclY)XP+$-%1}G&!4b$dpXoBU+O6%`XB+3%hx~9WE?zswrnGH^ zu=>r--xc<+jqE=<>GXrfzY;bN%zk})*?Dlm`jEz|@6A8|Jb(KCQOKM(w>B;F*ktkg z;!T}Dziy}Q+<9%|r6u5Tuv4qJH%Kq2{QS(tHFoFjJ&QDKe!W;+^Wh+StB`^1ecf5- zHz+de&HVphp>odsjmPKa%(ba)JMpVD^ZGK;+}m50#Lm99CHpp)zQ4cTvgM$yo?Et* z_|5N3J2<_2?_vYTk^> zef9!&fi03V9AnPE-}S60lgR7GUrH}Hmvn!zOsE4yQ%5AE1lK_FC^6bXLt8zPhVJnf8NtN4<)A`pT&2`{}TBA z&i=@ZiOzw?H*Guf(Pe*^Yi)ISN=gdTfe?o52+<@13DF~r4ilU8?dG?;moo?6zVl|b znwF_4@AP#s$7dE#FZlOJG$Lxo<7-!qr_Sq}Gbe^e_9OSXIlqM^XU>!`I>B6Bo~QLO z>NK05$Va71vIj)N)=KcG?UU$P<)O}y&bYv}TWm+&-(6Q2)6dLk6x9xUaGCM&%g4Vb zPMOo>8T@=fc>lSGT?KqCPL8cY7OB5%Y^voNiy7JXXSxXr&Y4|);O_-@f$pRH3^z8u zI-Fqeq(Q2oq{f7A*+Rub>(;)$usr>`)?|lHm!=ad!l&wS+&^~o@ZRG1Jv}{6VPR&s zwiF#+nf!bIF4>~5zjPxuR2=R7@});?O_ZU;eX(cHyANv2REj?0v@l>(>42ky+71;)mvL8V z9h+ByT;;;opx*lb-V?6U$}3t^t@Jg1#NBV$;bK+wFb9) z+qRo+h}VDeygQcR3gd&;rn$1e8F|eDH{P^T)NCLGDTuJ)RwSeSQ7$7Z+Kd zAE~q{?UA>Z>3!xH>UoUn`5&{{G6{;{be4Z?xQcR-WQI%d6VITd4uelTLuz5mcmRAo*(-E z=d;S2_R|a-BYMu>E=%5aJ_vM|i@Lh_RbJkLPbcCmEN^+sp5GBT?}zytNh9OU3IZIU zgY2}mwOd+RW@u<@|DQc^Vj_>i>`+TK=Zzbt>a#uec47EcxHD$Os#Q+WZucX0?%es| ziwxU;<~k0}eM;gFON})o%FeAV{Qa)>k8H)e+1&aJKT2O_x$N(1bWu9#c2Lrit@&U; z%MUFzmw%O?zO+~Vkly~UEtNU_%&h$^FJDTYIC;{w`g_=p@7L!Waq2Uy2)xVS0=lSP zFJ?yrzr3A-h6cy``}^B>?%dh8YuB&Bu)7jGM-PYXljwOgS#X{VU%F}k@yl;+ZPk8t zeSQ3@{`KcQJvu<-^sgr`m~H~`zB1Ec(J3a zuJz0ros_gxMRRk0tE*cAFCUTky7u)c)5T8mcE?tg&Ia8P$uN&$Qsmb}0|_pncufWq zMv)yiEsB`D#m@cnxBs&BK=g;mEli3F`zHimIDcr*G|g-4B0^qOFHo5@Y4StcYC*lY zeQkTIzb^`3A9u7)oP%XY$xER#XUUMGcxG6iC#AIcAr|Cu?C@!c!Gy7?1V!TQ9AHKwEdyY!jY|yWH z=F{$QK>zEntO5y-XD2LdLa(|x78R_fuyZ8NPobReFApd{e z2OZrXHF9ZwvpZe}A9Ie4^<8H1UEYT6z2*Kz@%#UQuC-ptwuFseu1DFu@6EZhXJyZ= zk^yJ4g&J9mA4EA=WPjG!ndRPM;pgv966cXLVgX&1YgPIxT)Fc9KiintScA+v96hq8 zYn(W{y8REFD2%K4tj1Semg91mEljja-`JRYzg}!>V)O6Caj~blj;c=dxUkDv|IWT* z`O2R^1vpszgMx$W83j(P5^6peAP~zqN9#|&!-3;(rNy7_Tl9aeho|S!XK(i>UyX`? z^6Z&trygH>^F7;L312_8uEI+q;j zFfuZ_u(MeG%lpfF4;^~_qBD3yaaQlKGP51EpPgD;#RCkof8BmmDJmAnU~n*7>|Lu( zLxd9OUaV_tB7^r=eSH;fVrqJraZCEuu7e304c;0zsyG%Tv}Qb?_xJu^XIIzb31?a| zS0vsO=$^LLEh)(8lCjZ(Wyg+wNNoOa{;#yftNq?;52sF=)MaVseeup->#FZ>+xP$H zo90!)*wEX{+v2p)s=;l|DMJaL8bgUsYd$Mm$oTQhKmYyJ&CSb;TwGW{_rR2veidSV z@%pv0wYBu~^Yi~d+WzNH&6k&#rN5bd-I(z1OOd*krln+aTW{<6MWPn9N%mrA=Kc%4 zd@x?Pu`BI(p8cEK^(>N-Ge3O&+B$i%Fz8CN88akOpL*tR=vS^2xx2bD*>TkPu_pXrG2rEv0VXUJ%Hfy<*j>Q?`%I^6oXxEEZQb*5=O2%BuMP@2_||dk4qye);2X zZf-tWSXjuJnVA{K(8n-g!>Z#623j7r4E&4*jZDvv^}dyQcy6uteb+~w9QAW{HvHVL zcl`7Tjg+*s#tsICX=2Z27$x$w{k!6yrtDi;S$SjMX@2jpHO`yU&Th!Km=qB?wf^`K z(2Y>5!`HV=nIgg*_7u`w_!LyK&Rans;qo%y7q_?PuVj4m=#fFv5e^j<70^{vD?(R` z`S|)4etzZ~5ha#$KYCk^re3T?KlgGzN8jG)buFrUs`;~{!&6ez7rK3YmGLNpfBwz5 z8ylVHOc;ov6fjSX;m{zV_>EZpq-u%U_Gn~Qd{m$FZy-j^LUsZ_no4idMYj^meO@6XE zk()&L_(aRIC(WPF@9XR9nU=Q9uwgqWtMITni@7jdE7*CbrqRKHTU>9+nl(CF-G|%x zCof#6s2j6m!lzH4y8hXvpOcwok|`u8xVP$S*OxCPn%|B(FIv-5R2w85H>q=@;Le>E zlf8r0nH;2)1T#BYp1d`kx9G5QN}sXuN71{xs@krtjqyo#<6C-7_wI=!H#%6D?7qIa z*2(uXcX<#0#h{~8f0)ggWobRh;ea|rN^-LE$&)8dvaV>{+L|ryd3dS!^b>dQ#-4fn zvB=ca^gMG0^R~M)4<=0EFJ%y9Sn)wwi0kFIv)oVLwTpiB?5uY@Ep}ElSJzjFi`DgI zXjqt9|Gm4X=cX09$;jG&v5t(sx_FuI+?ThuW~<~^eS72S<>i$fQJQQZ!PB-yWZrA9 zho665*N?`}_VMwrXl^B_$;qwzhMBef_*(>Hc$? z-@7eeMRG)5UG2QMjep_NZt+PT8cU+mOf!E!Go3Q?hu1si#wR;CZf!q3eOF1AyV%z3 zi@R?uUm9nfe=S6ai*?DeWo`^7jvj5jbm>w@N5pjX;_($uM; z`y3QbJox-`HbcbbRi_dRQkL9Z{)n65<4>Dg+cHC^3dH6w{-?O!Gucz&f$;qE+S878 z?(bQ0V)^&eqVMg$=U?hsDSYzAi4GZASLm9WWWG-2}c=Gy{D}P2sM&9IZkXyZrht1jR+2RK} znSu7I0v|Fz9N0Hyve0i|m+&8t6QqnzG*`TO65~G%URoF~_D>kYCP5 zhwJyFquijgzH5JfJ33L>Js~Hjhmo0WLHz!@6>)oaUCEr_p|Ydyuhq7kn@;KH=S^L) za^>I2bLQ-kJK)K1a*dalz0tLTh{`~2G`0eiR7Z(?^xA91JiRnf)9A3Fc@%H8A{tur#X}NOc%1MT6 zn_nFRcQZwlm^Mr}{nRfcG&FRcVKUn?|M~wyH-DU8^!l1EkE|8wCZ}V!wr20&a4%fw z^|iH!S2jG}QT4Fp4Cho2l^1vK3tL%T-B5h`R{pHa>Fe(~+;3#P))IXAQuoaD;+-us z49ZxR`N?trcUJ%K)dq|~RwP@*Sj14{v4gKH_nt3bN)%UTfpT8}lfk6J50`MT zFul6J-+piH@32*GMQ+}_X_9-(#K_2Kk#YJtkG;Ifhue5VE+3f@*LGL?`nD;YkKF>= z%hqb@zddViKYhaVZ*43!bsLL?ofbBv`OS{VsXpV+Y?JZ)+}!vlt!-^=s_N?EzoY&9 z_*hw30`}Ma_3-xY23;`M&L_L5r-x_ew%tpXF1>iLnSEvK?lPg$(yukSxo_JUY#1{( zW}Qzkuybx;nl5Jf` zoY&v+?sD$U*7;(2XJ5n|I4Jb{_K)!Ym*&YzXMX8ecx7+4dQsLRhh?U|9*DrHvh&Fu?>)U- zL4<3Si`qBI55{tKRZRVMcP}1VD;YD(tkL0sep&C%smgwH?V8zmr9^)3?(F1jYHA7q z)x?ke{QZy1*Z*Oxudn~}_xt@9S5^wM@yT$MmzU4{GhylS<&V$IGei@#etu&ktX}?zXG_`k7mKqK84=9gCK>JBM#hW?!&6*!P*se5+!{Wc8}Y_u}gp z?OOQfPuR2P&y_VTSvxyD=l_}Avu96@g!EMhUt#4L64H&wwJW)w$?bREQSefW?`N+5 z$M37J=Oonn~OUw+~AQi_4xUu&<7V5I!l;liCnsL=|ytaSD-S(=_AKebf<_O| zUk$?Tb^6!4u5SLov19AYF8jWp3s(mJludZ{?AfDNU!yH5U&-jj^ST_`{r$wbbB)`k zscqT1HNZET`|7Gp=V)(kEv-`>wSU>xC&ekNeKT!gV$7N)A>Lsqym--jrG)~Mmz{O| z@%Vv0YjBd#9qaE$k9Y==kMQ-@9tWE zd4FG?nT=;c)zeKAe*CET@$=`w>(|5o{QLX+%bq9_d~ezrW9NbNZuOt&blR?G)%fdg88wrx4K$hEs}#hJ+- zDxjO&ot&6Jrw|$$DNOYE#2E8K zd3UWYUB0|{ZS?k2Th7~>nof<{p6B}a*EgN*FCR_$As(`Ro$A{gdzRgK$p15Ud0lPQ zgl*Hrw&uKZ0<|>K`~NMQ@2DT^Ih{-!9O< zJWglboh#S36rMFQGBHt*m!H4>ng8!^Z(siT`B~J;TR=?A?ep{V>fYYotD?8-=|*g5 zICS`MYM;7_N{d^+oUhVEjrizjYn}rMHA#%U2NV8WxO4n?aU>rf-_mcY-qUp!dOmia zexv`}n|rNHOiVA_RSXO!tO{T6SN;9n(ne->q50?4d3k#eea@3)_{RK##i2FSoUQrb zkGhQv1R~Kkm;KbFdwf9zhbXvB7lauqxj*Yf|jnXVSjUSy- zoue}I{8ZQGtML)l`Pzn_cZC!%4NQ>R$CXxMqi)$N@So@Z%5+f7;C~{|vHlJzhH3_7h9}}(>kX5SO}W+H zaWpCG-kn~(d3K*%<1I5B;y-==zFc0^-rj!Gh7Aj@TnRaK?%cA+$NPiZ`D8%_yo*xc zLIH1v4U(+s?`Jfpfx^QtfPI5YXsD^bg209R{eRsmD=Urms+7II=UY`(wI%5&mr(an zqwZ~1r8=1p_ehEgnQ}j`oIJbR`028J(=_kcf6t#Zd9m%*+`D`3go&p9?2)vba;*20 zO8c?0Cof(&gs+dAsx{xON5b*;_WbF;x#M)iE?-?8p84dhRtJAoU0vN*mzHw>{QdiMO4rY?udkaF zJ@I(-v0`V9UA-}b@wGD&J@4gA8P+oBFcwHR{3zad^kIRAiqJ$46(zmt-f3xRCGYRq zuKd-z)O-4cYrWdtU#Ct!*1zcM>+An7Jj#A>pm9s~^>yq2{d;y+I%Z){9X$;j|1es*Tz zojWlz4?lnQY|`r0+`2Pf$0`~c=U)riv~895MtwOiSvBL2qFeJ`x`7h^_Q3xktM;$| zT_3NOovl6dbN0a|R+IXFf4r(+E?>UjRb^Yin| z-@M708OP!2>1mR2L19(!az0je_UXTm8f9Jacy)QTw5QSI)3wL4|J-=^Bq2ZgjAvow z{54A?vTpCPc_9tpzjb&wZb^T<=1MU3s8LzLcy|T!a z`_jdW3nwbOU%I+F-1~0Qt5>hQZg0l%(aWL{Q7f2kap7KB@QbT0YtXWbsXU)2_qww*IJ3EV2*Yzx4x^!Z1Z?Df^pW1Bg zQ{L6VSHkr^&GamOe(rDL(eUYdu^De~ZGFl$d)hR&c7FL~da=6%`j0F7`uaX9uwZd$ zYMSc(zJKxtaO+oLEu#xJ3sct3O{#lqeg-|``}^omq5tmZSJ%5AesO>OPTYs(Z< zYdZ9%H=OjYc5Y_>wshLrSPj#MOMMQlj=eqY%6k9)e5E}a+KvBs_qwVbJ7)C!=BcUL znYXrN-mh^G5Egb`9ky1fy1IH*;9@r4nMSSe?(L0!Gt0eSZsN+7nTCa8l9HZ(e|??I z!P2y(zd83dpAJq57czQBEV0LIu4PBbdpP=0kGNmBTTR~t#Umss(Ma6{u z`}c=v8~*%En%t!JN`XY0+( z&Zjcb!)4a2SxeTeiP1Qcw=lugXTB*jTl2vQ@>dz>Jo)@{$@1mldYAXUeEHI(>`la~ z$jxf8`)YPN={GG{pkTBraPFeR&Zl$}w&lfmg0jP!B@!zSKUuziY2Vx10r%tXcAZ@p z_U(E9;@>N(N}XqZ&i(r8YG|Iqr#Cl^KYjeT(5m#+gr!SW&(61>AGfE%G5L7k-&bV| zi=Uqh+?sXuQ;XBXFcFFB#6RU1*$ku(yzGDU>hx5R#)d5>rXIo0%`U9ZLmwSTd!o&( z*bvC@Zehz+UAy`Ixwp41Jv-a{^5^I0Q{PEjmAr8H|L^yDpF|m1De>7pxA)Ys_R3m6 zYZs2Qw6qLa?kBse=xNuT$LG$UU;g^~`pYv6lUGD-&04Z>p`(|VR|^yO)aeWrOczql zHXlqdIAwqN&C)e%<{W+e5j09LW#Ys@y^Se}iH^?gd`q7^dBPQaZS%%Vmr`9_EtLe7 znIDa~HS*Vgys|F$biUS}cXxJqu>Go15#f4qcDA|E)4Q`wvolUj(F`p+Q1Jeq?JTQO zEm^CQj*`++O-03rtFNo6sRgZ%+pFTV@Plr{uQeS2*m6WcU=y1S4)%YWqv*>{<=Z|ja>f-wNvnK1x z3c;U0e+Gtyh3)*^^y9}5qrcTtU4qk>CyDWI&y8|j?AH6|;gRbtoWds#A9jBDeWHg7 zsO$Ra%NI}*k&=>XjTSCuU}1Q{o@P4nV1mJtWs(igofb}*Gk5OGmzS46omD&AFqutK zO6tib^wmd3bhuQK$bTNq6Wh~e|h!ug-d^FREz(f($kxDVWu#9#)$=WpcdN9PkGnYM20^4u+v3JbF1CmJ(ZJZ zndj?;#?;l-9eMtFb3lS?@5kEY_NKMjo%6Z%czFdmS(#qlIXHLQ?{&*M)XTl@O1-(X zh4W*@tNh4mr{?l8%zLysRIky&A^CXUQg#1%Czkf#*iopwHe#dGvx2@pzN0$V-rd;K z=GG(e&zVy{KR>^ytZdnpD_6Ys=Eud!&9$$e_v_nRZyUMy#qHagk`2nCp`ni$jyx^$)Bt5`vruyr1!rbkp-z@7%R-B1 znP+Rw<+g~(5!+tOUOvmTRwyuxY3~2W0+!a+C#TdqxA7?2+wa%fsOqL7R9h-qa=4Ax zB=eHW%E#P1JSr1CrmSAG#%6};{r5uI495cs>Xu{#=s)=E8SC47Yiq72qx-j$PwMsG z#;ROho$aZmrPUt!?G!6F!}1R|BlUQBd2emW3~mkE>2>JjNzb(HsxIKm*WX;<>H0O{ z`LwMjH9yYV_k5UTU9M-EcW1{TYacDIurM)M`?@(+Wp94$bbemWAjWVZ*|+Opf&qgn zL-LdsJjeEw5KLIhU95#_ld#>%}8<=kDE? z{r3MfKAQXc``_A}-tY6VwY7C(W22*9|MA&}XMHL+U2wnO|Br2VY#(8*S4~X@Avucb$9N>fQGY8v#xlgJ^$9FW@G*ndUxS^ zNzcame}S*c4qdX_xpMu>ybG$c%qnHh&b8cnBmc46f1lIS|ErbCMMXqRIqkGmDPmjB z&G7K;Agd2Hvl|_k6c=|_Q&X#4wQAM8HJ;&_K8$Z%8s9HiG*v{d-~H?yS1OZ7M(bE zZdz5zYnN!VbxY>gNqw0w78e*8_~gkGm%UYAgE}OpslUI!fBF5o-@PRzC0yH8y%^>& zUuZKm1%=K6)`aD=X3cVOc5W_vd&^a*b4kqVAZfE4h1l5GTRRGqcRrfHrmO4g)z_^d z6~TIcheI3NuaaLs>RLPW*LNnbEOsxS*%JJwyZy?-Sm~mY4U5zJ|4s9@Dhi4d4iEj> zy?=eou7)*hmK1NBGkdmojotiDpFgiY;%#AJF+<8EoWZ*rwC^`2gyk|q8=Y5t{Srl(irt`>V@nUc`?usAq=^1gX`j4uvt ziceE}IC<>?rpAVv+FH?T>Mm|>lh&@)jon|jH|F8<^Yi_!%id_ba!)%q$8*;%tCaNg z-}6Oc4Gj%JeH9}UlO?^<=5^tj=TDzjuCK3O6~11s(`AuUc4t2W52LmCu>^yEhj|_r zSZLbF^|$d#yLEPUK7Hj9zqiUY_tq9gb#?WsZ*OKgS?8putN*h8P_yyi)#lsRS1juk z{QCWc=fff)>nT$m_UGSs`1&d;$mvgJ7!E3agNd3exq`l z;bI%l`1tu1HuFMm`y4uSXhq!Ks?cXoXV0JSKWo;k_#eMHd3jZYtxdAASD$-xAU!3STc*xHD$cwr$JiT9;2dEmRo#;8?Hpm36V!k3RoA^0bIM z*7XciK(DDYTl2^Gg^UfqnHn2F2mF-3yQ5jYd}sQ3xl5NXFFx8W9)7B;Yx#47TYGbB zJDE34JuL<*nRMqok4@ZI{PIko(S_@aKO8?8)NWaNra$Y7!Ian2R{GEP_wDsQXs&nR zLt?XsxA){*rLTOB>;3UOr?;-;$A^bTpY;?J8g`Yw4qFHKycmE2t2qWs&F zzPrLS$=ce9$9>uq_S>}X*Gu(V z+j66K9+tN(YEko_7xO6J&CN|jTKe~Vf!O*#AK5J}EGG2!@`B3uPoF=(JTuey%Fg2S zRbgwTd}kOq=836m&whS>{^b>ci#yIg7oW#{nrXw!$47XZ4<^)X|G{wL`NxVag^%5Y zx{p4!tG~L~oj>cs0>;+1wy>z@duo0b&9Zy?`uX}p^6bIB!i%}A4X$0kymUc!`cgjO zAJ65NtY7c_{r|o-6W;dcE6GouB{lubnKLh*Z`^;O(f-_ppV0?P{)HLz&a;?V_wQ%= z%1?Q(uB;4wmAX6atdx}HrXBqAIEB?tFU}RQdYD{3y{&s)LEe4?voveqK`SE@E z^;CJKj@Y|<+vZ8#z8xTY`qq}BmHsmys?7YjrQjaVrOQ_p@0XtL-o_(uxnZ)4QlgP| zpOGL_$3gYyAM|2(E%~rdK}o6U&D*z`r>1C@yuPM;>h$T!nl-D#*6!Q&d6DmIvyzXG zj=m2o@Kh19DtyFp^XAQobLYy=wW-{6WbNO;z(AAqb26Yj{Os)P$@}-)KYj9~ru_Wu z88bY*r|an!J>Yr3%iw&?M3U#&cMt0t8-u;IzrPig_o(~LQE+y4{`BqJvNvzuc)gwC zKiA4N)@rMM>4(&W1@47`|EGCB`SJd)7u&C@lK1QFm+}b<)wF*3TJrMN(aBtbag)we zNPP;n&$_p&bmD_wUp8MoKfkA^_w_Dw!Hhwvu(pOg&zPr2o^0TwEU*6qazO=3S(-Y2}yLZ=r{eHAt{PK^F zkM~;(PMSH>^WVRJS5^cnXWiNHF?{XeXv)NOvUaSf{JV7YwP>PtPwb}ZGQdfCje%vb^)b82WyC7)t5<~#6>B<;BzoSr`u@mR>m{~7p!Lts=krsNlAMx{^(_4Ihs;=fLwI_twE6BnhKe=AJObG=GmN1Vu+Tkyewf0jXB#ZLCN!i)YdKKzq4$@_9X zO$9Wi>LtC#uqN|`QM7rXnysj1p4J0}b4Ms5AJ`q1k?YZG2wSeiXE`spsfY;5M}=;}Vz`;e2Hd-T+)Q;Q?b16F1{5DxxSs*@djto=n$jMkoo zbEZVJu8~te?iz6Z-P{#RXLHY-c}<1kaKy(c9)}No3JMEb7P#1L>dk#kO-&~*T?$GR z%j4$cLgJmVbXAXu9pomoE!eujaP3 zwY{<`l)JC5??HjZi8E(fwr@9QVq)4*{M@hP#f68n?K(DXGBPo7@$mC(T)69>`2O^i zv?l!txk*0W!NQyOsvq9#%dMfQ=_&iJ;(+9xz4BcX_OCzjN9H*5xdZ7Jx%TvSx6hs} z9knf|bz-vGg1o!C9(?RtUjKAe=!)3oek(uTw6J(|=jUe$`?{LW{rhWwiwSkIxVgE7 zt}B`~d-mg}r>8SCT(}T$ulP1(KA zB_~H`TmJn%vs|v2hPyionaj$`#6EufDE{g5=i8f}ol1Dr9T*zOzQNnmvvcv1B`u$y zpMQLEvbuq(sq5KUrWZFPIxkti{PEx4-z)z8v21E?{`ldcvx=J9qV)6g3JMAwva+<~ z?CW@P->%w!H){DTvwQpfSp-jhQObOO&uiK5J(be!AA{2#efjwJ!N)60`M$sSxPOLC zt=y!bppA8h)wX0^T@`Zh`@g@{Po6(@+&#;0<;PprW{vM(O+9h?bn~iJuf+G;*ZdIJ zwryMJrZZVrSGArv;lbblI-2wPI^FNpJ9h1I3J(vTGH>2Ju>IQD`wIL8&O|Xb8{hL;5pk&MYV>(D?dj$r6=0R;664 z!`H9d!ZK^ttVfrYdKZ+GxKvbFFf7Quz3s!-ueu+99q*SveEc}Ou$s?-OG~{cPMpZt z=Cl&#mlv*C6Z2*Fym@j>O-%{O$(Pks zRZ}e*V%MBBn(-qk#I=q!;pF3w0#Z_1Uk{imDKRlJGTzvj%$}5-T=?}>=$ChQcb~Ff zvuc%=l<9_J+vZjqraduey_t%N*Nczp)+tJEhfAqZlf1RsZ zw->wj2kiE{Yqb9Ig)2=PJ2{)0n;$-V_U-67zq=;wF)%lGFDNKzTv7X(t@KpH zQ*Hgr%Y1`pnPy*Gv}KEl+CHuJYpwBHOiUA#Vobwge}8|=_&Lh-;xgy=YA+=v?HI&1 zE&3Hy^YZ1(#?!iYufN?_`}@MmVD%TTUWH{TnVOm!rk#;sVPkvr;^Jc0N3&j>Zas5* zd;VhQcD@;g$!tu_%z^>}4UWxhp;=YJ!or1bZWzi~6fh(vCce15oZl?(4u`n-^!#17 zR7AK8tG;CP$k|FAJa`avzoCwl_du zz$a(JAulgq^6JXUjOvKcWBJ?l!`9yAIe$@j;)i#8?>x4zdL*J0=aTsDjAl@*{9i3G z-{_Ji2WNKw`F4jp1eKTEyZ7V8MdcaSjHbVentiNqN5#ja&i$dKA44P7-`iK)EoGXe z@x;!#jmNRBZXYv)@-HK?p4n8|O`{AosQK{R0GB#}9Z2axb&E^v)JS;3M5}urx zxFUYPomt+Ujww?_TJKKp*iiV`&BD@hVf6OA9hINcW|ppZ@0ZKCy=|>l|M6tuOwi_q z(7slNDO0CRG048QrpW!$nn>f8wzflO&+_*5^;wj^iV3=oD-S;eacjB#*{54Tqxs)d6{Ht?za!yoR znz5}or|Gk}-jpA=54ZELUi0Hu$?b=;&GSXn_PHnt{`&TI^_oSCjOLZ{cFCW9xVY4l zcOplu)z;Nf`T?q{8QGbP4B}@v%N1`i@Nl*IL`L)F-`m5`i?!rYuTg~+{v$K;=P0_6Q^+nSx_f|{v_Pm2<&hRL^^&Hq+{rySR`W-tg zN?u*zbnlZn`1ba8!^%%7E7jG?-`(LfHQlPlz_w}GX>iHBf%U@l^UsrCU0Eq=w|?oW zRb7#r(;j|$dRoG=NQH@sY1Nm*+$=RZ(I)KQ|L^L#aeaN@{d=O{d~YA9{^oS&*K5B{ z<0Y32a*r{6d390p>>SzCd(4bpiAI&aXuUse{ecyMi%*sAZ|9d^IIVSQ$n|UaH#i=i zpQos)x$?$+V`JlwzrJQ)SsT6GYueOp+svj+nKEIVNSsCQy*cHfwAkm<|Y z+v3-*UAu7YTHEyL;*%y%HcULk;^OZ9_+T@8#Qr+ls;{rU`ktQ=+7h-l>fwinhe1Jp z=Iq&v%l+j+iTL`u*b`^YtO>ZY+<(5?<72%KU%l!&aKPcps!;D`AFQmbZfwmKZ*h9) z$8c)RPa`envS;0aV%-b{At50KxwlMqx@M)Pw{wf@EpTq z=DT`h>S3=t+?5TV#n&g@QOQ@S^El+s{QJ@MpZ9{!&SN^T^+5EFnzwBKcGhn`lWlCg z`NHP=24`j%3Ny3uXoTN7nq(N~;<8}b%9$l|n^tK_-MaPg)Ku*kmzVorywBYmaU$vD z#!IJ9-jLY1abrh!xAWImUAI}EJ$lr1=8Vtc{@M(?*J>he7vpZec_VYhWaTVtTk|z> zUB=J#BvVsT_!u|5XV>4nXm6aCm)C|(o3y?@`u+WV@`D4b_P!{1eoodT@6L{h`^TRa zZLIv97PF&(v7Jx$P!lV6LQW13H#hf-SFfDH!^Nefq&)on-LtZ^f`Wr5&Y01$+<*R~ zr>Ccb+6K*RyaD^`YAY%#7S#RywIX=A-_-bvt2o%$*k;&Po28wb)5$HamvDNT?uT#R zjvZ)ZHcUG+L#a@k_vOo%Ad#us;Q|5z4DRm7iETP~?sgnavZ?$8 z+8YtNivMTL)7RhL-gb@VvtRDq&Ua&TI{&?WwcPRX@n7ED6ux%tT0l^cR?*qO#crU{ zbe6xrzqjw-Z$D}B-$vue!f3; zK3OgC!-ql+i=b~yzW1yYUeZODO(uJHLK#fQ7ZSxa89W5BIaPOgCm+RQmDb zhk}9vL-h7MP{bPM+%V{ov)whLaeYSzM~}R{+{TR?KYah*zIyfQJC`o5i8Q{lK0f~M zxw+PxJ2M2eCEJ|T6(Yn8_BmxUtYu|ltf{HlS8zky|IXdJ7Z*CS`^+?2dPz>t%1TP@ zm|M|I&+xD?x8!K)kjs1S7Nt(j(d zZ*O&bOH0dpubR%Ik4}liU$}JX)u~-vt^4Mm;rbtZe^uY1d=HlsXV2=!CrzD_kg-6Y zG2u`1^yrB{v`*hW+|16uFMc$ zA|fmsBY4u&(_?m*@j5hGGpVbqZ^^pKwQ%9WBGI_knwY<{c(?sJn((OmWABVGi;Dk0 zpU)Sq+YH)Ec&u02qWGE5Qk$5R6qT%*Gf%1Nb-FagR`V~2p3Ya~eSb}*_k%~T+6o^Z zOMH84t3dbBr(MtQ?X7;m%@QuTjy_)!kV2HS5TcBL~i& z<=wY$-wf+=P=#!ee2izssST}hVt4M`30UqYTgspup=khWH=Cs~+|t(8UR?hE-h~Sn z0)FuRtg+jccb7|Fe|-@*@6DsrJ7XSMl|MB4QDawC@>*m1kG%W52XAsuFZ}Sp@y^a- z_UU@DO_L`J%h^;Y6vy<-**2xdt}a@-IQ)NO#O5^KO`A4Nm^0^0*gm_(X=i7hIDPst z(}jfCwxlj$2dRJ!N?#QXJr^$8o4Q->hxQM>yn9@F;WG8C_m8$8S(3s~|NlVhvS5pK z0l~q|t*x#r#g{KzwkXQ<<+i%{7KKcEtG}=N!mjmpkGS*36{}Y#KRq=yVso1BO1{ZY zPp*mFykO-@%jr+;nmhH~QjM7!Chgi))yiXg!fSQd+JL=Pr7~6}D}s(ppSiN;$o2Lk zDo>t0dlc%kCg#!Sd7rhX>Hg+bn#i$i*)ogze>Qve>;bjME2^tcr_B2P@$qp3Lu2i5 zE1&F{hfgd~YvYw>Q*ug5Qu6WjU0rf?s)ve)hsO$$k4GOCB;@6tb8NI`YfJLb`?H9{ z{dwz~Tg43T@6|T!nk6;M%5uu;duL~SUag|7UCqewtMRn=@(mTf{_-yu%d-Eq|cD^HzkM~cUFd-mCHAw2+oxR+}r$5b~DruG`lXrJl z>z+L}I`R8r5^vi+(cE`$Z*{olqt}xUF0g)WCgOIn=sLTlrN#d_Jv}}Z=YNX6l#~p3 zy6VtH$8U`PzTD*g_~PUKi9dh-w66Q`Y1Oxt8??M@3U|h=RGaKK$D%QAZ&mGN_NrfB zG}o+M8|l3!<=kBB_Pe{wAOHILdg`_L;@3_l9&RhVa^=dj4MCu_<|}k|F&l_*uoQiL zt*W~=dV5=6A77um{knvYs{4)OnHc4{pI1JfKVf#j<5h?6tu%etZl@C-;~l={_?MUW z0>b`%+Oxi|j}KIs=ic6y_~ypO7uVOzzq`Nx|J5Da^6qxE^UE#h3;oH?cQso=QC*$= z*RNj^=6Nww*Y8Q%D8b3eIko5+H-n6cWpKHe_ zCMHhZbhr0oJ*cDe@NoO%1C7iVu3umO<#)fVwb-dsr)&@MW3l_EK0ZA& z(|BXz;WjUU_)n&>v3D;poSuH>@aYZJ8@A`F6#sDV|L^+Z@No&Nl8lwtx8~j!>zB80 z+q~KM*SELa;o;#j)@5sMe4D#sg~p#xr}YiYRz~J|PjzY0eI2$qbamK?vu9l^Dk`R~ z-y_t?^6}%xsb;~q7C15&?2IwfU1!lH5?)la>W;F%kJq89`?4p_oMD=OzWMu<_>`!- zduz>ElGS|9pFeRThwXu^_PYPw`Wqu+o}CK6y)9QzLZai(pY^{r>wkUGoHTjz#Wj(e zy~N`!EiFN<-K?vtj(Tkq`u*WxGkfxz8ygFXi+`(SZrHTRX>HWj5XO=e)k6u7x))|- zF=m{8Sa4x$_Vu8@n>8kVdwW~i#zto1#ED#;_PV;fk&!nqT)!OZ@kdH(kFNSU(AiKgH>`6`6j@ud zblK9Awx2dX*LU_@xnOP4frC3PUWzWO{rgPUs`S17xie?pFh7tF3t_Oc{5*B~^zdh= zruX&nZP~I#Kvwqe)$Bfb`#w3_swu1e*J_-fZ}0y0)>iL3od*JV_U+pz(0z1<_4nJi z_I&vAIs0-P(Oq`*wt&Q#1_xJzL3N2i;h>4${U&f-qLGh!w#O)PPe9_5C z@sH1IH%b_%_2lqIcyiiSe{)GlP+($W`f%R<|A8Y%SfaP*wN9EObjP|>vwYSf<;4dc ze_XI?RhMHko1=+fc(Jy|}#?ht4$QElIoy-znRT62F3^SpWX&MHDvt@*62t>4_;{r#~+D|4vc zcBjopx37yoxWscZgGhwl?xLq$pv=B9c=@B3mzRfbVtW4kxpQ#v=AiePnVBaUFSL}( zb1DA3+&FX3&RX>)FMe;)yfinnMp~S|J?&jbohWx`=+#*6P zLQpU$C}_dj*iFs9R;d)1ycqagYRrJ*7^T)|F&3JS~}{8J$`t&y{Lcps?POSu9&>JSZ052iX&+PECtGBGkzuDIb10YnH@fx38PT^%ut47Jz&&$phErle_UDXBE^#p>FtCnu|4TpMk^V#SJ(Tg)~4J{>(0{&d2` ziH%dW!;|jqsSH)~ZD!|x_TlFr%{3*UeYGO4=?tfw778@8@vai$e05`^G7~eisLDQ{ zRX)e^@4s#DleIo{Bf>7(oR^pP$y4yEd&`@jq}LQ#$lSPf>(QH=n?W}a`^~rGb$54{ zu`FWw|L=GH)Dx%ItXZ@E+#+qR>gwu@j0}_H*p8&5;?qyN7I}5uQS$TjZM}4Ss^ns+ z)cJxu_5Yaq^xk#!*Rz|N>RnqK)3a4u?BV*?&mUaeZ9V!AUS*+>l>2oX!nbybc{iXJE#=Loap`lm3#N&CTOd2Lln#B6rNyO>m zHfK@MR2B8p{xzA|nG3z$%R&3cw03>5s{WnF0Xn$iH-G1YqR_%G2lRSA{8^b1^l1Ch z&j%RqFi8A)@HBMG^YB?^KOP=#UmxYt)7^de@$vqL@8WhQ-#@hWmP^a?^Ya(y-QD#+ z`Td^9i&tH;`!_f461S%Z!{mU;0ZxKU9t@0uv$#Bh1vH(mOsx&PUs`%swDkU3vz*mC z^z;-~mv?9f9-P{uS)O+8`{##;r<~cl{7&_|pL3sE zo>zY7#BWgjEoYhk^st)lu(eTwf`SVf--+6)2t4wBkhSFiGbj(JnuSSyZvXvmcfap! zvz>7@o+sXZ_%Ja!Volg|wat8-oQ%8gzOA0`$?^tWwzQ+OQ_KI0 zxv$pRIQ`s{$^Lc^r-sLYM!e)QPlINSqwUdr2`i4}Z5Ni2IkJBK zY^TVZYb}o->#OWpuwa29&idNG3*j% z?^xPq!}@Ay}kJI%P*p$qL~i+UKlodKg(Ri$>LyT@vXY_#RbP8*5a+N z6CE8HPkMGvS~2@%$l-N&f4{hSdF#X+Z7r>i{(f~^+qt^0uV4Lbq24FEFm`vDU9sTw zY10;kXxZldWO6U@+Zl7un@3e|`K;IL+ON7Pr=J(y`Bdd2?_0j?%aW!j} zS?;M@TeI_j)m&WU$|GfR;;~-4dC|K&mO?^8M`T~5ndRJYh>4lAWNnYKd*77RSF;4a z1}GeveqiYq_Ty~H;gK_9T))4&8>_XCi<{fiZ_=@>XX|W#d-(bmRz}qCjqCSOTbz4) zTa50y`Ln}(eR)}r_g`M>Ek1u|hkneC2c{pV&YI;_P*6~9IAurc=dF(~f1KQ!XB)V^ zr~2phbYo4+`kwl;vpnbDv%QeHRb#5xs@|(dj+rcok8eK~x4G=G?tXdWA_+ysgTl;P z=6~5*+_mdYd;QF~h7iKmq=aMjJ*S^V5f?a-(5AAdaV zUwkpct?Qo94z7n~8Xc@sOp|z4-riN3eQv(}`K{U4|E-oj{o&!^&W?@+si&uvyuCH` z%a<>=ckP*LUEX($^W&ryx1X)G-tm5)+`9RUFTdV+TL#)C@bKiX%7ZhreKe+OnMn1X zk2wL_N4)-e_0hKmhK7QzP8TD1)boVnGZ~iq&;NRY(^SgTSzhkMg?9FPpXQ!TQ`X$b zxxcdXnC|_rd-toWP1a;|Kk;=E!)x{Brx$uH-SxQTBQqP%gSXr7FY}*o_vZe7`Kew< z8=2W(+~2=H{OI+a#m`%Q6fuhH#UwmGH+TD8|2z|^$Xz9x`Fp=kTk`tCQg895rluw> zEiEgi-LC7o-iamt6xy=B_Cd*OwY?#(MLR*u4K}2no;LsQ>_2~M#B`&MJfB~G?tT6L z>Z_v!JqXDdAY z{oPjv1?C#C9BJKC{XH*4YihVod}n9pjI+-I4Cm}@H=Nqw%xKXNG~}vdb^ygl)Az)s4|dQ4tZ9Nb$|_ zx4xU!|Eqca`oo8UbMtIZUyrXp`{m{3&hGBylao|IM~#`}-spglA$E-Xbm=kUo|O{iBmpItkB&YUyXD%XYD5zvZ5NR;!cA)T`t9PEFy;|BKJ({meUaV&SF>6DDvv z)m+tGG4Wu6!}{x=-)_HOWqNAihMJvq8y`Kt)O%*Ox&J4<_N}0EK4$uSn;`L+b)CZw zS*|(1LvC%K{%qRRYipxFzg#~5-=ZHutFPL8y%K!n*s)9d>;KQb6UM{FTv=K9=I-w4 zZ*OnkT>HChU+f;9tx>&EYt>9tW?ai$`{L?i>DqVaRdkoCW^KKdTWVGIM`hu{g-4Da z-TCK+*3_;oTTB?(cx6s(%Z+|{MfGqt|C-w0-**1BY3GwwGBlj{=~L1A9kQ#gW;r=I zY3S>rxv+l9&bh;<>L+*!2gq*@( zk)p*7EBk+F>FYm#aIo3t!vW^FwH-HemMvS>b|E0~Oxg4wt5&T_`ugf>&CjRP?E?F! z=|)eQFkyjJ-Jc)K2l^MKvzC{}cc^hxTw?T5o2>G^rcwE0v7_U`-2Jz=<<9z zj>5-zzssxk&g<#n*|cdBXy_fZ?PS-kS+dq;A0D>Le|m8tF=l7fv7Z0cv)9?O3sn1O zKbm}d!p(9H{r~TLujSq-xqZj(YwE%6-jyE?vfovH(h=4I_T}B!kU00yRV@*&px|Ih<20W4`+n+{$1%1>mNe7v|k{==Q({YBo@Q>RS1ux+g~ z^PTGVd*@iz&dOE|e{FVq>#YeVYo0sl>FcW-8(&`iXm#f0W#^9aG*%y(9_sXnd%>bj zLNjB&34avrJ(&`8)h_vJ*4Nz!_A@`IlrCQEv2U_X{C`Q|-V76|^}A*6Y3yq`y)YZJ z1myeO^832;pFeqWVY$Ej{8guC7$$Fs(1~T-`XaJXAin9>B|i5&G0%39>#x7MxVQv_ zgnSWhOn5pwe;=d6^2;B;T=w7nq^4KOH0ih6 z8macq`8r$DHjhj5<#)lU7rMl9jVj)J?EI5_EvHY$_FsJX3;UU0^>1y@e;?+Z{Pu{u z-gIFpA+K}&_E%nhXI1Z;IBC)=WARU0GA~y=>Qvuw`)%B5-YJtNHO1)piyrPey>eY` zqTy`S&<)f7J-1ZznO8PBG-mnbMH8%r*w|TF4eS0?e5v{yp&;&VQC6?I?OW@~lvR_x zw;oJzSbeqV$A`pU-`>9d+BId`G_KRrxsQhT%h~>Msxi&EF~KbNmPUghC=WE>_$+#3 z%X(4spq`Qn<*n=5&DXiDi`_lVd%B+G{eDT~W4X`yxw(~%jVGTu<1?@RU*&;~`U>{; z^J{;9+n9WuZ(GjILtXO!8hq4>-!O9VEebuImU8d<)VkWLOWR7NZkN4zwElgKOWr%R z{;hX!Z1mrdcsZ@Dzw%LE{p9)6-QVBaTk|SuU99bQv6ClHvaqslU9)0^fO2=XW$^Ds zdloUxKKra>^;ffgp1O{@@84b4U%&gMG9!cIsp!-%@9)p|xBok3WAbsMf(HlkrcRy8 zo@*8z{$P^)x5>e|SFgUkP++T+{r}(Jz?C6!YhBhp^Q>{B>qRo#o2{_S+`&x$LZ+;@fuUTPO{zpvGT{RiPEur(Oa{g zew^wx)yuW2%Ifj){^yVT?bGh>tCiqkWmp3UQ2~e zKVA3yO7HhOt=*R{={h?0EqP|X=xP=RFYnWC{e28Fg3;w~Z@K2= z#YD_;ui!L&#eD`6Jm+kk_9^Y_aZ~OV*WYLNlQZenm6ek;vx9AwqfxU74QES!A%%=IxwK7aOF=2MybFQfEd1o&kZr__^ z$id6IbjcCpoinqtviAHk@b~dKlC`z1JMn1kBk#3g#lOy23O!mnTl_^-rsh-8P@U*) zZMQfmUiz`Y)Od;sO0pYZ?|f}f(7!8>3;)ju9~*G zt-ZZ)`?u_S>ugFnC6s=oek@hqr?Zd2tzS-;n~$$9>dQKZ4t>Yi%(B=9K}ku?pNGtH zZ%vu3?r(Mf{)?g+6DK|tF8!ftHMg(&{od)z=hw~B-}j^G&z~A0A)z})j2GEi6OCrt z#2v4Gx0C(Bv;@s}2U3hGLu)d(Mt!NWbznB!vtx>q0{?_ZWpP{f^>q{Hz1!WG$j&dy{C4#|hDVPdr~Y_eCzt=( z^=DaXl9^SPmp@G)Oriu>Yk<^TB}U zPnMMb+OVVMBbnec2F|Snx)7Og_ zSKJV;`SH+w$+CMpzs<8M)#?`4SJTi~vEN7ScC>avjX-*d+}g0{^zDZ~KR=&rHd}Ra z^y)>6oI3Q)JJ*A58{Ji!J%9c63k#i}YE6BmdGRol;y#wrOU7IEA3c6tyZFGxi*xMj z=l%TroVic*)W5&KukWh*X#>9U?uFRLt4j)#*NMe{ob}_@*6eVHj`dTfh@==rX0xnY zCh_CmMu)(&*2eY+v$lFIN^o1;*)A`Ae96hlueW~RQvd&7&dp7&Cr+FQSsGL+;_>a^ zzrt0zTccvrKW?r6UpHyeq&;~%|M}0Cy8Eb6;fT11nAoH#Q=afY;-2eg?(<~>DE-bo z+OaZ34z?Cxy4TWAoTovzH|ezV%d4rYvlr};@tb9GGT&;+rcFX?!(LD8XzA?ijM@1_ z_Vo0y)k~KxJNEYZ$8YoW3*MAod|9G<^ur^ue=Ii`y1Ko8Ja~M5Z=AyJyXS&~=Ph?V zEfQDx^lFv-^4#0oo;-azamth{4vQ~7VZK|lCO@gpD(rgel`A1^JQ50>T{C>toSd9$ zZt42HdgRR&sQZ3e-rZe^8zYn$CQfz$C4xLqS#{k~XM_3C>*e=rpT~UMb~6Xm$gI1p z`1I-1yl$(Tn^L{c&9{AR>R6P#L8M%<)i(a(#fvLKR!JD{+0lCUKs!Sy8}s^o|LW)L zFSxjxwd(KM{edM9xi+WW-7C=3-=BVdo^47>O2*f!TD=cD_`mjkR!rI$(b2i`wr+xf zgv#TC2}Uzt%~|eK@chy01q%-7>%@C4opf(+_36fki>9+W)o{L2**C>&sXxn|6{7L4 zudOZSdvUmp*Li8sPv7>CkdPg@OrXVKUFYWR)qFK&`HNdywSRwmyLi{GTW=qozCCUI zix(MBiYjMF#N9dezQD!)NRFAYW%jP?Tt@i^ou1Y1opH2#`i?idxcT_h)YaPsmEBH! zt@<1Dz&Bnv-qh5zv~F2QXsD-K&DAScI6gjA`%)!e$SEnix z6prWkz2gPrv$oDUbjazsO6sE{opo110m#D2y7TFcs=acv&$ivn`Bt&_OO168)6b@HJ3ZKD%Jm?e?_+9W?K`o$6X!lwC>C9N`svW=^_y#ca!v1_&(+!l>ZXHQ zW-q?}y3g4E^U~)dSzGT-iTUL>Vb)V`mfHpWKeTjop3JL$_fdNKxpuiKj>Q*ma0&dB z1%=ph9?gB7cYY{bGgpG zSC5q*>3(~2vv~4^7k73VSM8mbc6OFw(G!n*)$eVut&8<8EZpc{=22O>)BDKut68oK z1MXN^cXcj&va0-6+J^@R|9m*ipJ&@1q7$z+*;BDieEVma0M>xWz?0d=|DH^oyzWP$ zslVSp(bLmv{lCAvd$(@i-sGr~l8DD0ydd5FER=9J~qC>hD zYxbTzF;O|yYHnWFi%d|FZY>s{w)v*|pWEl>ST>(bDcZMw&6*{fHi5SDpPO&*@8iS6 z%F4Ru<1y(i85f&&?6COt<>g^+{XGZn>?}Tc`t)ayBYSs?#;@bZkBN!#2?@EPJKww~ z`^47O;d_J3=lVTAbN1Q!N8anND;NK`!g1Z%oS*Z+dq$qCS8G1q%;A%_e0EJ(@9#f$ zHCyAkPfv$~1|+tJUr5`0RnH>#TjReS+U8}NJ7s@eYFeTn5E=P0CS=W;HD9bhe*JKm ze{q0@oPe#az$5Pu-NlIx{C#_a_dTe;yTnu2EdQQQQj*f^Yil2G-~V^*XX{p{gVyi& z96mGCIC6iTt*WZ(n_FAE#p5a(*?6Tk6g~Ai)+6a$QDKpLYs8Z&qtgMAUKc(&$kAG0ITWGWS_s@0(A_p>z zK7Pv1-}%;sdwR`zKUighUp*_3l!AmAKfgSHd8H0hBu9Yrl%J^UE#SvSo^8@v{s2>+9FW>^!vl{XXyG zeX^ZhU5m=!-}9Mm)?5GY^L)?&yUhn5eEc+O?+iu?9#exCi| z!NHvS`|hrFG+(meIrp5r@Xn+eh1OvY^tTE>yK4DbQ^V%%r^z*6zbY-;`@=eHZIo|S z)vn`O+Y=A7tqFVGzwevR%JcK&G{wT~Vh?Uu2tnGqgeJGJ`V&h|TZVwU;LbZTbf&A7QqwcqxeME<^?YWHiu z%eJ<*=EZK+*3{g&cK3qS9oZ7@o*T>W@NJFK6%-T<2?^QpRwiw8q|i$Cb-Q&`I}?v7 zpLtyMqO$wwq1p9S$5Yw2-F|!K$K(4y-@gCfZ<<|{ad+2NckOLOPrbCXw66Vhkk4pL zC}0U+(f?!8q}vP6rcL&V{L^@EZ?$pyIT?nityxE>YKQMAdfF9#_2b6la>^hevSHvRbVxc}ys%*n-}{;wXb4s>F=?zOIJ?fW}# zzh!K{t@_ZZ+V)_Mu;H1C7O4lZ?LW4C_`2QOBE00^I{v7*xP!{d^HkCgi8YQUnVFiEm6cDPKHZpq-|pYv_w|$K&-V`r5y`#1ZSTwY&(F@jzOwK7y4d2? z(kp^i9?3GOTKir{jN5DJe}2pB!X0WIiN})vFuQ*_?9zSp)D6z_oAjzZ_wtv0xxpzX z`BCNj_m`&+eZTj;%k=AM{rxJ&#*>xZ`&8!GR+sHQn)H&vqjYmmaLvk)RaNYFCY*9w za5bxR_U(sDJSX4SS8ILpkxbuW*37k%tJs60tKEA{;M$H&L3zx;Xl@L@_? z+N7B?U;Y7I&hY7p=W>nc4GE0v_k7|K*Nah5RedTJ_^o)daJZ}Wlua6%8X5|gmN#{e zPw#rFZD%L9Ge++H+6QWk9-;=E5y@t=Z|!uTc6?b^7VoqRV2vs`u%Lb>BYq z>74cZf=^F8xwyGCH8dW4czAeC#KxwkCZ=<9ES*zQmIU|w4Vj~=qVgl9=+UuW>EgGy zOw%1e+up9NkAGj@d|`%Ra?0;-Z)ZmZ1}Ywz4l1W|3uh(Qoc)w)A~pA*!7TH9zst*f z_r|Hs^l{sqb~fYM8cFANzP*`Fg%1ueF4u_OQ(*{N|GoV3#bv(ILBYWhc zI&8}H>Azzo?n%GAxmjJ>EN4Of{e5+{#ikh-80Pwkhlhr$x=Ed%$b5!LEj(1R;@kE8 z3+wmaJ7TiKSi9$B$YJUK-^>5~y}Df|`rBT2r<4C>R)?*1S{ZU_xxYMvS>7Fw>3Xqp zTKf9`c`Bk#JvyDX`KosfYuD|>j0}ypx3@2^{rzowP5S1W8d_S57A$CJYGUHz=8oK3 zwe@ptWTfQxJH_XHo8GuJs$ETQkI_?CRc$@o&VPAbtaVUu@Xr^E`~T!INLdspTwd<~ zz9+dbdd(hAP}#QU$0t+s4aLvTG4|Df)^knL%MJ(-kd&0%{>Ia~_!-aU^z+aB>witY zy!2#-Nz&$t`8I!OuU%!Xyx+x=|?B6ulwjOU9{cc z>CWjH)90OA7rXnlsMg)7XXaQ=&b++L^8WU$t6gv2f)_UivRj+hDEDJdr?(6G2 z_vrMydB;eesSUBV@Hl2)#T#lwr2jfb)_$8 z4#@QJp5WG>6P~_)b#?U|n@XXA9c?`_mY39}_j^uOn{hVnOxkDP&UWkacRr`5=^nir z>A&PrnS`utua6qHsO_V|Q-u+2VYAMrUCY07X3^5qlHX1&xc#s2`oMx zulpg$%+B|vinUMP{@l5_){$E>F8a<-Pf0PT|5xMIEA_SQV1fnvAMaI}+#Tna#z`y|d({P_LBfuC><5 zMMayUnQa+uKAlkB^Yhtk&_H@iYpbBBsB2>4LKU0vn3EqK9)9|M|NnoNO-)UmYCv&) zr^$bpY~AOx<`HZAY(j0Tz7+gsK0J3#)Yh(-mzQ7Ol+M0KW9;m|-?}aj zTA3#_`=3`yiHX^4-xlxBeD(~R8$Yr+n+h-gH!E)D-OjE(mi71cuyR+voN6v%TgAi9 z|IAzM#^KlN_n(`h8Jwr>#>OvqruzNf&#H9Q zd9!_I(?ILgKvO_pxlaG_KEAKw%r`}JyrKz!Qf$le3dfA~Kz2*k&} z6-e;j|5Ir4%C`0U;*RW=ujvX~p8oTbXvvEUjz+C<8yXWWT zPTu?X+imStt5#Vt{a&iFZ=Jft`prKk1)Z8aYnIf0ZqxN)t1~YyV%3e>vg7UdcX1+< zPp15N$X}mutVa^$mn~aN_++h)Oi*af)tBXr`{R##M5TwfRa`Son?wPDxUf;gQYcxg5GH@t6% zdB9M>=f2{n_ko}X<_`Q0x|2`JFy^Efnd}m{mVX1ZWcmC3`u$I|zFqRxzqr5tzjYsr zRrWOQbXae&VDFg2a(+|Kti)z-aN z%C(~6N6N*=P5;{ptVJH3R_BU&U9{rz%NO_d?oL@F^EL78EYs~@Pp?0kVN&$-Q>tF< zt|x!Y^X}}h_WHK!`s={eSLfJNeiEzyb>TulPwVn`A3Qb7->olJm9;KQ`Tp+imb|;S z*5_}ya3Nq_%uXThDV-0GrAjpLTEuW&d|9&MYF3Joq}goV)mOW`mL5tlm@r|2!})o( zFR!i^2en0)sP33HXO2wRx|ov(o7vz0FfZCUXQ}t}OM9!oe`sdsmou2@bCz-P_M_o3 zF?0O8*Uy?I^`vO$`K1XTMU9M&SFT$1>2^mu!{6WEm+#uOOLf7=N4A;*kGvI9KR)Ho zYrnlc|M`!PkNrM=ecW&VYt08H&{Rfz-A~p0eLtW1GOhkL|7MPwnc20SjaGVkeS*qv zcP9P_T7A{U%`M4ncD^=8&(*8tA;*q9S@!0}#=}ob-(OtJKHEJ1*-7>JB|kSVRXL%o zq_m^xsh3fK50AN?>h7?bnP=0&*2ndpOnG!`Yxb0>Qzy=t0UGM>VZxy#MXt?1Pi%}J9d|6SDw8lqjc?9}&ncW<*tXja97h6lvvbD7$wpOaa>VTM6s zlRx+R?Ca|SV`6;z(+6uY|Nf-~ zc01W8XFDs^Kmt@bfA`#>u;7E_>FGCfp1oebzbs}=k>%s#{oh}<-QQPh&B@8R;%e5t zs@J;ns^3|*@ynm9{eIW|^Ru&e)%F}nG&Py|?hLn*iO!U+F0R7mS0=xneBsz4)tGaR z4>TNHU0LPp|7`RRJCwKGxbjnqmbUgx)9h=pvf6fb^LnMtg@lAI$^W=>I5e|h@sCy6 zO{pt8^;bTX`JDd8^aY!R)9ceuKmB&q2X&5qEcpRCD|5#Vi2@aMKTpq(FWc^K$(&sN zI$`_ox30RX+YkTvQPEIgcx6ZH{;S{0{rvdU{pNhw$>lTOZti0D{!JAhldinlectQB zs!;7sn>Sy4{Z+WpzQVcYix}jM2<}-I zc<-;a{&iPB5S&kIthR^it`1w9bfAHevHGED-klkHtH1A3ozXs}qrcyMWr&%Gb8mGU z>$>L`3}>G`GsE!ka<2c!r1LkFy^RW66Y(&p+uzNNjay8|Vg2>}d_Etx{9vlN_epi@ ziSBy|LMbF{?npdM=K!1CtEGf%D?klS78q71m)Z`IC6m6ySp#UX7@I; z^MAUL+&G(QN%i-4GtQ>X-x78ObYM}5RjdwEc>wbs#=fJAUAx6LW?$Evukqu|Oyilx z>3lbD-u&w2@yDA-&Su87s-?sRVFTX_BTYg5NUR->73`u6f& zmC_aKzNz~tW^Gt~YWK>88q`X%Y- z=gsh0R=;tNb zziYjgE{g1)mUDZX?;YK*BJoBubzHWz+}^+(oOOKD=jZ1?Z{PpdcM|K`RjZP|ytsH~ zp6zU2X|oEIgTHztjU_CLmN>1yp3gX|!l_1c>Zz*MOmhjINw+?$9-039L;7`4|9pGi z-6sbQFIo;7hRYL*587G-S`fo4ZN|V?KFwXO^2l@Pztbma@9vs0W5(@uYHBJf1zUfd zl9gYc*)8_u>C>Hc7bc#5Z}Do8ez*SWt6F96c2BQ)uzu_0XXf{7CLcQF9Y6SG$92THD%w?Rg-W*FNv){N_A{9y!}t z7cN{_331c`_B(vf&(3Z?o93)G8Fa3|{tAV>dwXV1RCeF>*XHEOlQDZLK2AF?o7Z0c z?w$Jd({~^B|9`Q#-->zV4xyDhWv^YivO;jj?ClN0Ta#}J``akaYyw?)apsKAGXMGK z#N%roe*6)6=hHUS7ug{M_8n zudUo%T?2!ImBo|S+%{wiJ}5XP{r|te=QbXWj?fW{t9Zy-_j&gH33KP3J<=(>H%tst zuyb;9_D=D7%4Z(a@AonE{@yh~+@|_dH?eg6_>_J+JSIlQceYt5lhSig|E+P0Zv5|W zZ$alLG$hMA&bO`Yz{(Zm2ZoLyuAJrA-&=Bdm^;bV}k?9>jz7PGkI{z4-w{Z>( zoEXlvsqAf(Rr$L!A0HpTxwqQdMx5eH3@|BNWHt%b4 z_sVNO^y#T(P;jti(UXp7CIipb!pFx>HZ?WX=~hL9`VW~ujb@*nq#g72)K;&hNpEg! ztW%6ADlYc)_5HfisNLPo(shG=K=^jAa$zAMCWWHf$~N(x@9H9AW6vh{+djLP4cZdL zBVo`0YGA!uy?#^9O{48Clh*5h{P;2F&W?!_CQPV1Ag*V#+CdGX%KbV%J|J-ylr{?R`@P@;$p88Ig4d0Y@R*H>J z=0$MozWx85b)vSM&{aAqTYYkh*U}}2dfQuD8CAL-9#alsOlDktG)YlkzkjB2`mVoA zTwPs#=2%Ru`}@nV;DG~ZyO({l=O6A5s@z<4_2MIvTMGM*_FMIRm8IHU9SGj zBwK&~`_wsee0+R*q+aNN0w_G;aY#(i>E6kcCm(L*7H4q3vajszt)Df?w{y(+WGoJR zczC#W)t#udY^$$+Ra)seSxv^a>dMpOp({fsZF&;N?{I;oarq6lKRe5u{=Ztie%Dhg z<`pYeJSgA)TlVG4mnJzkCL|y4`}k(_`9(o1Rqi@SN=oWPY+%?M_rE&fQ>>gHom?qrdcZ+xUV;c-J3ros`$^Jza0}!_okhd z+Ex1c*~ZVUEiD0|p{1vvgN7_a!;-c}?Y*a_HTBff-}{y*>1Ai$*q~@MQzwkaT<*ER z^~Ipo$e&)VULO<~82H@tM|gbgQD=Tzm#i!;c0QR0bIb2Nys|R*&&U4yC6%9_+1>Y8 zzyF_=vU?w>=b?M$yzMu&kEQ0*^dFW<>|k*^;@mJ%+5J?g)>Y$0$63K8RZm$(a^Cti zYjpN!=J>0I|2sN6R!`kVsp-?EOV+~1S-fSt&+6*+^h%pATd?53(?{N3*NaO^OrqAB zx$&6CJ>*>=BeU*m{@$i;IsKI>LjXBS`dkrgyz`|;z)Gjpw{7d}1~7!qC4Tq9lTVAL=|nnZWo4~!TWra3 z#g)}k+D&cp)zx#CJbRXIG_&Q$C#J>??^kDEU&rvUgJTD{q?y$9BWgneW7ulZnLcj& z>;7`^@_y}ZySFWOw!eCKUuX79;xwb{&Y`!#;<#y|w7#Zs;vrL~Lq~&(1N6R{9|EA^(BF2Z0TD z^R@>^MS*rT#=Mi$c0F|H(228WRh5($ZS_$*z3=e+oku>YE?siWsiv~sfnyirhaZpo zg{7o^O#wTRQE%Upgr8PLPdIj$zc1TY|KT9}-(?HK*T=mrJ~=giNp2OpS>Bx&!l_fE z4)mTl;jt!c^^B91(<>eF6)xp%cW1P1++NVKc>mp_L3}nGZ?@gc0UhTsapJ@8zXL&w z7*3u&tE!^1ME^r->=E$*{g0|kJ=z)E76h}4+kMHj3d-Uq6(0sx8piMQduC9q@v!`6DG& zpK|S?`O*W-2lh#`-nh9r{qMewQQLAn%gW5E_SVUKcs937fA?LzJAABP)l5yN9&YFV zU3PDMqf<%GxiV=*2c z9zSk&E}GApJ$cKIu8xic%a*zE{U}`hTUXV={=tH)Sx;YGU0w3>QtRjE=YQ88H8wK( z@oaYfh1XyAGtb*63|bh|a(m%|dsn8bPI(Vo3*csBQ~PVn{p+P~ZftC6Z%^-x6My6_ zP~max)7H$(YR?;_#l+NRu4q`7@cPYNUHr#JW_F|EXFgx5{@OP1b2Ch&)cohY3GaRL^2w=kC!b~sFYl!f z-Cksg3$N_dFHqUT_UOoj$D3o=-m&*Z>WJyZ?eTDPW1FrY|Lu2|{~U{n)8nc>e z@m}fY;k|oOPm6h~gzuZU;)TYk)2Ci5WL$~RNt@n1EA8y8oqrrbwT);2v&^*^1y3GJ zyR%1MGrd`IH0j}=pPxZ1%pW~U+Q0q>Xuxkp;9`-gy>-IdpQ#tk>R1z&y;sLAsMvbV z%9VnTPJ6R-J>^dL^W$Snd%M5*UcDpJ6*f#bGH<=8c342vs~hb17rAn;-|=E+_v-NV zK~Yg!mgZhNWBT^;)vmji;o;+#_WayjJze+T-`-kQf74M_UAOs==fzK@wfp0f4WIn5 zakW^aHqU7G**VtbeR+3x?fmj$qU+4a}q$lHI%(l##)TKP(K-;yLy z15RVASBlX_*WeEQ@1I^Q?oTqBIg9z?qUWtYgjo3ePEYqy`y91yebn^B3l=EMt9&N8 zKkLET=1}p zGz+F6A7(ptGp1IrrJI6QUzIYI^6d>-+S?MCCg9j~mL)8E0Hj*y*%T;M#fy*A_><0?;hW#;CO# zBJ<|{pE6|%XlnVu#zz)OM>zIpCFHAx_x1NLU$TUy`{<)d8~z5BJpU~EQB+!*d*9yY z-i&v;mB0LIcIa|j%sKgFiqYnqJx&W1EG%YpbZ|(SWH^+Rm^^&=u%)dnY5Q%%*=Hkk z#Gd~*-;-DR^3u{eb^m#PYF%AhW7meso6q#Qe=BF3=${%sJdOnzq9#t>ulN6cmg;RY&AxVFp>z8W=TG@Vi1nMx2XoS>F3IoD-086&V2c?;LW?V zv$IT7QY+PG<@osY96!26Ab$Ju#KUbTQZ`A*N1yfGqqmKXsdkE2>Vz0Q_k{ry=FIU~ z9kv#t2w(UH#Z)2C0r&D#3Qp|tdC`vIW`vyR+) z{-l&~+r1PcQ=7s^EHh`$%(=Ct^TC6J{d@OAYYAIh+qbW-uFlReyZuRezVg?NHIh7R zhYlZBRo>U~^z`m4YSDZwAFr+s*ALMOwYVU5LU^zKk?9BiZ+uuFIkD2a=IXO=T%4RA zXL%IP-n2E!vgE}CfA#QhClC6poHFM}S6`po;)_S5dfhxz;Sfo0GGz= z-AR?^B4T2jDnF+!50JDdSP*aerjeO_j;Hd{wz%cTQ;dE-WnCMzQsudvq@-kL)Y`sD zD}Hn_FJp*wSmUs^y%qSzSVGUcYZ%<)~r*@d}lK)+b68+3YHEQpZBFn?={NHz9J+?M_`=lua=h{;^DTGw6sfGGJ`!`t1oAmY{|afSN8UnCJ!5PJHPz9t?B3I$xYXb z-K077l&Ra|kI4z50gsm|$+7%m%Ig&Yc1C7l4+y6C5cy)UXXp>s@vQwu|OLNs|uWLBq=wi(i6Y_vV@Qv=rrPp82 zG|8NF-}KEa(`?Yt_jK1VX1$ml1*e~1ym&EW+Vtx$BfO@bQdipLX>nzb$h2>!2P_iQ zH-xSY>knLg^;Dm%^`xm&kG60MXIxt|bIIYH*I%nZ>nfg{oGc1DZ0_s3yT2FSxN$?( zYw0GZ)mQbH+ZYw&G;Y<&OqBOty?XV{-R1iHc0U#r`>)<_RPewd?cAKsxb@$=GuoYM zD(7Fh62d2MCnF%ppI!NG=W`Bj?%#V~)GF>{`Pa`jfl;rsEnK|p&5eT_laDjBS6{6C ze)oBK@9xyoVs5>k@;?1q<~zIS*O!;kcGq8)%*cB6tZc@;mB!uEbp#)+o(CFYtGGN} zQ=)>|ea07kQz_r&A3hZP`uh5KxBk8p2O61cjc)jQcyPq-DpAzd_WpUN`25Q1udhrk z6crz4w>lO2F2DTrbjqf9W?$QgCAJpd&PGF43fU3SQ_soj!RUo&sXwO32SR)c2F@2hUn z(bHSDW=)UZTr1CQJ*BxHuUyNusCv@zh25Bw?M_Em*P$G<>g+kPe0$hcR$R?$YHE_O zsn`&&YRt~T&#$hm+}zW{(|R)H(UX&tSGM!XR)L25>)E~5hP}Qn*8Ma)f%_eA;(q1| zjuU1QJO`t<nDTw)@_CQ}1)GpTFp0hKH|j z>W>c(H%*VPi!>~Ib7MtMPfxm%l2XwWuhgk-iz9h^81JOMyUoPIu!@I`dFRfZpmpTg zoo{SCYuAAG(5B^s8&(yEg^4X(xbS@EJ${*%r`iS=?^#5C1l>^>v$Ke` zLCts8g-xm6`?GJ{xf2t$Jx_O?fxg0iJ)vB)*`K#wXOCDav^A>tVg?WE9od&I%zJA7 z&JSA~HhIR36AK)h|5!18IIkylBE=-@N{3so)Wz-j@u`)SmdE>KUsr#4aPar}dA8Z% zD??hIt70e#hm+0IT*pu^>okM(eRJS??#a&~@sWu@@rWRxeCL6)07EcRNuDrjX$JTvpo#D%Nm*08lPnTCdjf>wtV zK0e0DSjG%$Zco#HKY7-yQxlclncmsWG|3by+W9BZP+$C!_k;Zvcit9UT;v)OZe6sf z?B%7_88amIXJ6T~$L7%C!`bS$<5bnu+PtUh-ThRVl9Dpl`Rs3@tgTT+iu=~P3+KFP zb53Xc-EdK=mu+v{`6HdeFYoT&9?xD;V7m2PC%?@HhRe(S!~N!3gCap(_ zYhUDCTGGiSu+G@2hVxHs&C3$2{y7Eb=2$i;yKLFN3v{+ks1YNtkdTl?{l7oD^W9xt z10x^qf8@RVvZd?3kdE$d=7Q1}>s}r>?ohln%6E6!ThKuw8#iv`c-OaLg~qP(_vehy z+bo`8SG#Ld{r`V6J3Bi!i*g-J?R6`bm=We~_}A8eYePs_*r&JK?;DlAy3&xJzWQp{ z)vT{8Uhfu&-{+{nc9)^z+s*XUg$ozf3xqca#4{=GdpB#*BBg8VZJ!hXMPU3>YZfdtPat;?m3@4P;KWq*)c5V7v^<;#)=2@N-H zKV@rbYI<>DVRP~P8_NAQm$Xbxzs7EjstsCw_1%HQtGk51Zjh*u*$@^MW|V)=W?ucj zpAC7@nyL|O$LHxkEYpzvD4Owm9|P#j+>mCZ+XL!sIotmop z|JU{X6(5g^GjFryWou6PR^7OvhV$doS|w#=Nz<$;KFcrbiiS7VD+~K7WQrVkU9@x0 z`lz*Kk>84U-<9JsVR2X4_Txvz_OM4+Rt8_Waz$bK>CXQC@7|ylZkiez3o1W9o1}66 z>gsUDcJ8aa61{GEaeG{vckJ4^d}{3Owy?!3@9uxH>9vxb-MyuG?&;^|D5|Ns1!><9 z6%~!yRdO%MV&`1OJ_e`nyO(^IBS-B|rSuk7uu)a^HO#8zL8 zQks7HbgI$Jx9N34Y1?l*f1eA4vk>=sR3B`+>Cvdh;5nDn%4xcwH?EKEMm2il|U>ABE*x}J)< z`tQ(7rHu{>cMV^xum8Jx@0KlJd{hl@+y2IP~WI=n6GbA{JV`F{e;^aWPomYl@+I|0TAE*QoR1@I1bL!+| z^_N#yPZvl4EquSI{y#uN#NXZBeRJkzH6bA(m(?6Bj3?s%eG*SQGvlF1+}qpR#l`gH z7q3{+admaLu!zVJcKI3yH@CJ7kw%9HVT{){r~6k&M$QBq_ih5eDA&==6DLl5^6VMg zlJlD#6dFK#%l`kI|DSQs^Q;U52@Ornhp(=#KKFlp+}^H(2?x?PCvJ^mbkCdj;X{Fv zl2XR4Et;O5o*E)t7dy=hUR+QtDk^$$bF+H=&(rZo7R_={5Mc7@&~Id^2-lnb-^$2n zQm?f6q!}|bqFfX>9G;z-dHBl8;ElK6$_d9kefku%iGy2Qui)RG%C4@i4N+@B6Wsq@ z-Q0vkMO_OD42pKjv^q83&0D@^4QQ*(y12ckI)&ADl)Mx=JIi!&^!B_w{uhtEBXq<- zTl3!C-96JRS4w~Hmq`LEnHmq=WqQNA`s%M;8G?%YShjx(-x>2SsG`CGv}`W(^0Gy) zEKG`fUfkHYIQn~qZuGXEL0oy-~$tUAD zxw(`7{`$HlO9H-odoZl`a*Gb8M@pO_(5X=_KV6GO_kH#cp5zu7D&8pn{Bn3#9Eds%>nhnLr)z{PH$J#9;tEUAjV{D*g@ zkK1H5Uk?wD2l@5CrCnWJzr4E}y+e_Ug=xBwq~yuN{PsH08xkD-C!cJ&n|EI!>gegm z`!kr=o7LO{s+@y@ga2;Y_xs!1#~)6bhCzRNqb8yjL;GrDMIrqxy#OrlzKdty!X=OrxtL zz#_49>Czq<%Sm_c#5^go%-TBZxP1MbW4+S9OZSTF$N7Nn8@RaG-QoNGqe+Pen^@;q z7PHOtaf^wOQFiM|`2X*(j7`M^`MMvC&(6;7mUdMT;9z`~e!^9_V$SodR?rT-)(=7) zOcOu@3}0Wl=H=;mEuHk>LBhPcUzz*G;~2i*ueZOwEqC#*T~-Od|9^UVde8rVzhicl zbZ$&O{^?4ve_&|n(K9oRLF+%i->cRKDX;$iPSm{HL7_nN>?~7Is@nA7!-wlni+;X$ z?XHm9xcT~KA4a=NufJ{rZSY^}Eq+mn$*}>nd6kVv;=s+#>47UlKm}B%u)2_xl$5~N z>sebvLP9{7AUF7|Of-@D`DC*Hh1XwGQd0#bB|QrY40xr@Qtt1oWdMz~UAPdCc4mg- zbiLRe&*xPi=~Wish;d6vQE_hLnW!7FVZrp1DVw?#Waha>?6Wz}@<4cRoPPAK5=}`- zNpQ*p9~$uEL9>Xs_~NkDo_>C5kB)S{`1-3MtNqLwpKtH)`$tAb9*AYO|Mx>VZ1vQ{ z!)*&MX3Uvyo_A-)j~^A=a&9(V%urEPZB=w`GbnoE@#)j2BWFQQ=-SZ0`SI!d9_F-{ zB~~{Vxpx22>ze7H@FR8Kk4N0|Djsq6xGgrG@@GZh;sC9wjMv4g_RjO0YqhcT^|gjo z-**;2KXLv%XmzVe&W#H{e=hZ&z9DMuxhqVw&GXq7WL{qO<@NP`Md!AHUtcl{g*jQ6 z%DFaN2c^@e`aNv_mR^4O9hTrB-um{{8v+<>h5}Q2CNj z^XKF7Jzp+)AE+;?=ya9n=<0G>eKjZ~L`2~0-Cd>HQ>RV^E!nb&A$&)wbS|Ld#E<-$wnzAyY!8fMY{bi?}vI!y{4yO&MgIboJ=Sl=}B z&1*8RY`Yzjy!rf{nR#b@&gw?H&A#Nr?JDbgIi~Rbg(*i^0~{R!9VYlbJP=v;o&T#3 z%e$OM&wo~Y>Dc`D-23mg_vPES-@pI;bLpOK_5c61w6uJ<;LLybVyjn+fbL@N>3TW$ z_CzwxXjy;zp7H^v=7S67+1J~F+CgH1kN7sHpO>rqx;mb5!PTtJ{{HEw`|1_U%%*`x zTz))WvvzIj=Vxbs{Q4y%E6dxkNMp)8+tZu-?Y!RS-Svpx(9qM&&dJGn@aWOjEnBv* zEp7sBB?}Y*jkCVAaN^)h5ZZU7--biSNP=h9dHer!E-rTW?&c_LU%6sM!lfmi5o^Oj zv_#b=cm96AKVIq?`>wLLUTJA*?e^z#Z*OBPxL^C-^4;lk=awy6(<9i-#+VQ;5;Far zyhVXR+UA*a=ExlX9I7P>%E_6TnQP+qMp^X>I5Ev=(Jwq%dtg5=Tl2U0|G&gROS!gm z2$U~~|NrZ{h=>S-xcgo;pBV-2V%K-fI&i>2#P#8snZ~l;B+k#b2QAn=c<>*&49*!s>n>u7=0Q{!v{Wc6q6{cuh^slEhg8 zl9DH1US4kf=40-yEu2%mt|naJRxnp@Z_$gDy7T?P1jUf>@MN>uFE1_SKHe`6TJ?9Z zSV>9g!{^VB*KWTz>6~&)#zlr_@811O2Zi;m%?l53H6MInl6;IuuKrJ9rl8`xfcpQx z?{AD+%aCCrrMazGR8CGVBqXHdMDpqtD;|LATq7f)`uh6gf4deTy6&7Lyl$eWv+Po6q8iBF{^<0Heeu+{b2x=IgM@7*aK zk!m0@=YH+?ST(;n8oEkHWM4fwIk_)Tf2xq@=XrW{!+))s~CJF|n~PZ*SLszyJR}aOkodOg{NV z9PG)-jR&Nf4<=One!G39P30y~=x%uOB<1*u>2d3q=ilFVN#i<4{L`mTW#8@SlehOP zD>Gwe<2i8p^y-7jHzOlggsxJ%Ug<4m&>*btx8VBgj~_oOnwww0IKNIqQL*vq>FLQE zBbEqrDn^+!#743EfO1XQLir8X5)35%|9Niz`Sbk$F;OlZ)^`@UcFWjncR9JZw3wVS zJrwRP{d3j2b!jIjss8x=+r08*=Eawn_x!pN?AxXvudl!B_>l=SXL>q0F){r7`LlOk zy3x!JA3r7@ZsWbw*&?8;Wo30s@PLU_FN*8dEP1>HvyDQ%RfAD zbbnbg)ywtzy4b+gPp`kZx?|U_pz!ePPhOmRyJFwIc{_`rF9MG=IZb948JY$@pC1rsUW<9)KbAIZC%Jb4mi?OL$|ckbR*ZMdtnvbv_Yib1-^ZSn6f zFE3X(*Is}9^5*7d-|x$}Z4=vkvuFA8^xgT^yYIgHQSa!;SXo&q zA}X3_Hak#+6(q)gAi?0l!-tLi{rq)xbu6GBqtxv$5|=Jtj@+InyKdb&pLsTt)774p zfNqKoZf(6X<81hyb1x1y7gl|b&C1H!5TP^2rgGEC=SPnoHO#)Ila-xqD8W<2#HARe z+Q2Jo^+i84H1tN!w*OPZCVsdoCDahI_~MI?-SK~#US3}A-OZu6AwowdX2%A{AFuB0 zES~-D^7Z)o-u3JCJv}|&niaggy`6ve-E(UqHyg}8JL7EHoVjy9e)^=OpwIw1dp^rF zYpYbR+hYmOHS5-a#_62f`2u5O&$e=lU&t`ov2*9c=g-|^Vr1^_Ds^6bks%;5($me2 zZRygbSFTC@Kj+s&)?{@c~JaM2=A*L1?%xuBJ? z&h31u2O1c|Wj@*z|1z=v{nDTF%h$b+%tEz9nXA7nShGtiJUqOsyE{;1=|zoMvu8`+ zyLV5D(~~yOOZoZfsYI{anlSCJU%&qN_3P2=*WJ5!TeCGYZjJISEj0yo zIjl;%X3dg1lV)66S}ML@Ve2in|1V3dOr&_lx?6w!syhC^xvA;J?d|#-H*TEavrPLP zXaTale!soVUz5bf#&FwdKUQd@#mzD=dvn9^++6GHDOY{?`T0M6`lM3Bsd!7PLDOuu zubAAF4_B3v8qT^czWDsP{eMf)MkG+;WVn%I_U~hVy+z*Zl3ixMlW*j0-<*0{?9%1S zmA_stmsPgUUAt}Dw5O-1Po6y4xuC$HnVnxvNr|bv{Ciq8|KyV{PEJjW16pt9JiD?o z7!+^s-`6{T2JHY#+kCU|<+G>%uV20T@Xec^?rv^9J-r{le#MnbKY#M%!P95QY_A70 zeioms_VIixcVTI{`_iDmn3y{$KZ?rB)%ErL{hSnCX0vQibZ*-d85_IyM$WeFOG8y^ zOqZ|lK6pC+)02~XzD{GQQ9M$w6S=8n&K#Ksk5*itpy+&S$%SJ(i=RjAD$&%_(*vDx ze$vuCH}z?(PAN$dT~H*Y}OUw!w6Ex)|*^2>ta;_PjIHTATT?sN#g zs599V9u?PjzW>?Nl_6SJvP|dAoA;u`%FD~Eqq{qMi?6@Gf1kX)p87(8MZQcoo}HZ? z>fFZj^Zu(>St<>&@|uTBb01D`3O{h9Q@HZ^+;UJb^PZV&ef{I+yLsw%cKbr_#|MgB zx^!uVaXO!E^|zEmEu3$)Dk9g0xjWq0Q)%q#>dGs(e%-od`}XZS{C)DJNkYH=t;nyL zJIm|DhQyq|@2rp4if3iZ&R=~oqa;S|rij14zxxMqr;cqL3A4>|gLdxR`FFkB;-6c$ zoY;Eu#PzGKjL|)A$sdyYZIAtazh7ThsU_n;(#8$x=RfA%NrSBgkUO5+eDK1msn5^N zu{>;kzoyx5dGek&>8x zoX_?f5lV{|b#!&TnsD{^udgqgZ)K=#-yvZ?xzoP>kKyO=bt)U(`P*zi^W^XQWAt+7 z%r*D6^*W!PZoDMkUTke-^CFFKo_Ie$zmU+-lbsqZ8ODZ&hSQ%noaC6%vOZdv_YL@DWltugY%&D*YW61dLUqw|_(x(p!c8U*I zwd&-F&)r>;_D=V+@9s{SI@K`umWicg zt3d9l}-eV0yovE8jTzj*PY>^l3IXVXfo zWI+etBxh+ooNHbD>Pu!;R@RTd@9Xcs_^qL=+&tI1eA4XM+Uko17R8=8cP{P4g@sNT1Dr(4Bd0(=$wDimj!{%47 zvX=SHt-8&&{>_`5X}ZzJPE1q=jgZf^DlKBs=|1Xo_2=gl8C$P@cloFN^7TDC*YQpD za$Uc};$FqK$bH_P598~9Ft>kupMEZV{>J3veQfg&zCCyIrev?1^Z$Q;CFe~!(wuzk z!J|h-M=Rq40|Vz+m-Ed&s|I%TjvCHIvuEFqmg;>Leo2Y<8l0m1?eDzyA56yZpn)j}IT|6wW_=-}mRwpEcj_md~*&?E;Mw zfXuU5vQpkdZ5DIGCxu?Kh0+oxYU)cU9HmdQJLn;9Rx*Gn1}C@8b> zrQAI?*Tx`M>f*(VKYslxTT!<(XyuFh`|S$~b=OatB(!SvYU#7J#!|gAeAJALjq`6i z=(W7q!I<;n!ovL6Slb zG2^1rnlSCh$9l8N_s`DC$~tl4gv0X73$MSv`1{e7ppsDd-V2AUw6M>u{|Q~G z?{_G-xSoujtA$Dp;||8xJZ#SQ@9nMLT=Vmj+kYkP7J=~1+1K^Hy}!>NBlEMUv~+3q z^>t^r{awHB7gu_Ex?8W*)x6sZ1_l%U{{C)U_{gQ|%L~V(B&EB%N|lwAnhqRrxO3-D zUd3#;#S>4Q@L=PSXqZ1=UR*EcK~ART&*lD`>#pnVJAZ1?rd3?}`R~gly=G6IJXyG~ zun=@yL-O%HK}pGzi(I=U3=$Zs_R2LMbnx=x(%=7QQ_NPymW=m|XVz$(>a*Ty`|e4W z(7FRz>FLk^b#`{HiP#9b=EKstMZo;YanbKx-QBZuZ;N%ee){yOZ2yA|^XJQN+_-Vg z&MgWB#g{TnjvPM@+ODJKJF8{>etYq(tQBk49n0Dr7#COP{>7M|pC7cL(aXy#VqcBr z-{0SlU%e{I;P3DM=g*&rtyxp&OmONbTbX@*9cTf^(`V1VZF5^(>3rz=+~XW;O3KRQ zMC9equL@nAGSN%XWpm5=OP4OCt+ojd2x#zI{`kyHW8P=ewz?l~=U={RRTnF_*p`T| z2Rk}AKzoml^~?9qo-JLqci++LA=&;_UtTnZt$uoCWpMAcKd-K>mEN3wewuI)N8xUk z4KIcEy^~>kAg!*xygDg4IdX4R>F)pGsfsSY{~2X|@D5%3?8U{!XE(iFwMy$j($n3g zudi)=T~<(3^r%yP-hso1n=Ol<1q1|KP

    OXk|xt_u;c=c~@Vpa&Oh|b!+bL=ij(- zWA8Jy<42E9oHorZFmU3WDNY@?6&wD3_2W$_kNQ!>w6CnFNJ>mr_Ux^#*@cCL6OA1? z3NM4^Mept1{kSYP7E}i3PRrfBYuBPM(7r^_M7WGa!GhZQg)6T1$l1wP|M~GTtzLfiS+~GIK|en~iQZ$@tM<>eub(&1w%Tl0{QB#{!or8A$Jc49F9nY= ztS@uq*SY%otFn@^a^(KHy^pIZ6s#RKN z(l#e2zLNL$@OaRzzi$FK)LA#gd;NG-QF0(@Z=AiAjm?}ZS3>UGy}R@|x8kg$$^Ew1 z7Mz+Bwf5PCh0fde#KyIO!qcECf!<8!`Q)kbQr+#^R`};KJo~X5;c6XnWT-olqpP!%KT>rnWtGk<%i!1B;=de&M zQ9C<3P_su~UjEygn}?_AMqkL<`s3%%yC0-t+xcW4Jvi8`qN*w=B~|7Ab@Q7yIa{K1 z0|NuYb6$V?RHP%uZU6J6|C1vkPFt$??c3KQXB)M(;Nc;a?xR7AHBR|)#&7@sv3BX@ zm&aJy*+E@~J$v>nSwU`{(b+tuPfh_few3E zaWzY>_RGcFNrg{0r=JfB3Uc!Fvw!t>FXIr zsam}1P1w0}=ZmkuR=4SwmzSI6+&FM!WAeu@U#18Lb0{+U9133@ zz*xK`>a9wBef_rF+immb&;OF6=+b>LYwMF|&p!SAe&6~ZgT9s)Xs_mrufL*iZQH)x z+-h#$+uPeWm%WYRVPj_JlPOs9x74x)bnf-u>hD33k)93?4!h+!i%UzFMsLq^ad$6% zazb!h?rpb{l9I{4bGJr$`uVx7ziym%W`_2;>MSo`U*6Bp&#T+n{oCbsBd_&r+T+hh z=TENFlPzwPtX?JiI)81%{0&KSb6hK(58B)~GxKe_#fE1Lf(r$&$CjF#n~Tr&bB~C) zF?Ii+5Uq1_t=qkpg0>|VC2=X{U1um;xR`B2Uqpd3>mTpM7j53Yetr7d+USqpzfYIb zZOJI~xBVKj*#5}%HIbKfZoj*^S>4dkkVoEb&WRHqpgrQB&)eTmm~uL8v*oEv^*aQZ+R-64qrpwZFeTz3gwlbi;-X7mL5Wz1@B^De=jPiG3H9Tmx@x zNBVZPFA;dOO;}pGdMC&6`=MG_vt>U@SU);(-QHB{tVn)- zJ}6)d3O0O6QFK|&!O01_$uA`})$*T&zP|o)@9BCwcJ93U>D%E$hdB88pLgr;OL%!{ zDQHKi`MrwfTeqV4FU_=ic6Sw{Yr) z7J=OL{`2k5%(LBnP_?nOwe`!(%gZCTy?^z}t6$D`L)6+mU#~@rh>3k_xBt_q8N4hY zJpA~_$H!$qpVMO(nSJ)yOyl$$+wj#CSN87C$&-`S zSFT&9W^Fxto^7>|tnAy0bx~{8w6wa;&9&Z~c$m$|*qD=>yO`z7tXWcGIuRGNKF`lF zljfeTza+0vmW9Ff!1M-I3$~v8U!`8NoE~&KC>>T_|5Gk%t(a@zi4!LlL~qXvubCIO zKK=W4ueke%FELO?L~icbF%~wn~jZ4UIt&NH#Z+&+WUKZXPiwtb^7$l)2E#mUjz;C zn_4!#c=pU~ecaw11rM3x>;IY-6p9ob?GgnYKD0V~z1aQd&h2~?-%jey{dH88QG@9j zlj-!jy2YL1YuW$mf9;Vm`n1d4?QNNLJD=>Xv>EngZzMniJt`_LeqM@4a%B&Q>BUs! z*Vfjyb0)~9p1XcqYw9c0$tRC2^PSDX&p%yGyCuVT{r-Pd%~>^HzkXd4we^&t)U}v7 zbLZ}Szwb9_dzFTs9;klTCVfs1>}+ z_Ufuo-*a2DxTDri3ta5>@X3>wMH)A9%;wCQvo7jkz}hg-Qf^Q~tEjjbbcl{cVS^?Vg{TyZarJ-t_Bj z!cHBxLvwO;q|Ng}cJAK2e{s;txTznm+Wm=K8ua&6iqXcx$H%nw>@-^h)*d~2wAK86 z&E|u(V%@E0XPa+7@msRj?cL7ja{qqs|1a(D??12Vm8O%k^GwTPHGca)2FLqkAA|Do zi3y6lZaYL=7p_~!xB2FoeYL-5nCHvA-}hT@<;s;)rcK+HDP8vV)>g-b6JEzIzIgfa z@$C-?u0>38=)5ic(+F@%H%+05_%h&zbrMKGO z-#`7$jg3JiUK|${fBgDY^#AYo)na-v7K`@n+c)d>4PDkrbM`dam-%-Yb<@J{LV*tJ&e8RzHOg6^Ag4czhj-R||-N7Rjt zC-X|1fo`jE&-^K@?g!dk@aON}^%nVW!a$2mZfb6}oL?b#I*0pDK~}uziu6?%&s})* z_}O9Gz3&y()Sh+Swkm$cQ(0O0ucM(H#01Y)m~p;KYg`h zi-4?GTAJG7Hs0V>t5(H@i#+|WQnPj5^@j4;*jP{icXoDOl5Q1vd+E$fh42GLF(K8P078R7M;H2XyoGVT3mjAHzx;2#;2{S zs;V+pB^{t``avr@Iyx4By!`6Q%Vn!Y_kBKR{p87$2k+j2hFw7ulodA`te3`|JIjvSFc~6Jbk)*S(%xorR9ycWo&#h z9^c>HwJdr9TBnk0kX3&3>BS8>*;&;*gSZYI_L4R-rcW0Utb&D zem5`u%8J178b41@PFGjglK1!ax_;ZaXV0AGcK)Eq=+5?o>%l%p@0NWoQ3j56 zoh=I=xitSwoWAmE)|Mz;J3G4`Ion;4`kp#kT1nsD-0b`C{MD;duh;LdyLvrlo!ZS? zpD*WKIXPK9a#x9FU|=99Dt|8pT?nJ1pwJMxIql?0^_CYK`eZB*eRy~{e>X#!b?f@) z4gNiDi(k#o-!1e3X4;?zh7RvF^e!2=9JG*h#6^%cC|K`8kE9#o~?99wLw$);;fij6- zKOUD?S5jJZvUcstl?#_GW7~YQ=VZ#EyLb1-u8l2=tg5n_ZI%lLtecxs@6>+3d+BzI!1lRUu7n)xk-V(1=S7JX z8?O}TM4?+>_l1XtgW9`BMn)Ri+Rn=_2gb(U)o97w8kLlkRPmsZy`ZdY-^1@KSFcu9 zRXw^D)ZqVwQB}-biY%#HX2pTk2sku9)^MJV9 z;=sKrCnuHtXYUeliaD!3zvj^D_4{5)Tx{%KYz5l0y0Bd?Yx-hSU)GI>+xaI?o933A zt6N%H%G>9@`s$*~FDsr*bnocv+xPCRn7H`lIdjgma*J<>T3b<30Xm3tMlzd#hzO_@ zQ&d!}sH{vhkSHiC%e#_ST3Y(#>C=tr=jG1Lv-J)N3Yy)|vUJ%pP&W+}YD%~Db#zkh z?E$U*y>sDLq7%43ay_-5@g!TbGq5F?Ymbv-*36H zj!qA!u-ca2mfrSLX3sv|Cu^;tp>ZH@d-CR+QZm6lK0Jrpcz3_LmBz}-3fkp==#bN# zIdd%P|Lu8fxHal5r~~x<`|;bie=j@q64X}QQ(;(GSg4|^8e1yewaCKlDibsF#}6M0 zZ2o^*bj93w5&MUm>GKVfj&!(9m6)w9Q2*(q`ksHkUi-|qi}f>7JTh12KwPNE(^}4W z^E{miNd^)oCr_U2k+BS_nkum9@Qq!i+K-R-FJHClRN?%v)kkmNp6xkV?ct+GMbWbU zuCA=0m2UU<)kdrhJMJ+fY_;pspofnhIr;eT`1$!|Y>jeXdi2qwq!2ApvF=tm+bVmq%9dA+CU9LzBJbb0>2Ef*iR^UFVbaIpEwvuBHfRtBsL zx$(A4#P#6ayRyA*&c439ii(Oh|9(6+-^veKyz~ES{Qs+Ox^u$A!axU5U0fe;zwhTW zY0I6UPcp&nmlBmfYaV*6e7Vf6wOK?)P>teVsb^mIg2P0}a!Jt`4(& z=6CaL*_kxs>hJH4rWoBVdf0XC33wVz1T^HQuFk&tYS-Dc!+G1S`&Mt*FyYUinoplT zf!bD}$>O(VckbS;{CYJU)WkV>@L{Dx z6z1Qz`}O7J-Ybg zWt@JFL0sROhmTLqz~IBQ@4jopF0Tw$pQan_784WGe45=CJZ*C%Yim$gSlc2E9tnd3 zg8SyonKQ#E^;D^DRL#3PmX|JFirARM8W|Z`^8Vi36)QA8eg0fnR(9yt`rp)9%Q-#?W5RyI-$IM%m1ZIm+Hjr znNj@w+{OL%_0#m@`wk{d5ccFytOK1|siLa7b+@;`?aL>w7d((|KKS6vMR$2nCGELh z(CLogoVjx)t;=*cIXOWm+6ERp`lJz2S7$eK=FFD1wtJuMEWaiqBXee5>~0S)ucTL3 zR{nXSZvSxI?srNyHh)$vu59O*PrJP>x9|4Wty{mmzP|qEH*E!lhS1evg0ixAQ>s^m zXw8{BH&CSY&!3vEuC5bj&p!R~^0JGotEpB;P<;IPYipw;Hzu(L1_u85vfN(P#%9i` zQ(k=Xc4t5md#g-$?%X+L+O$bCW>f?(4k_C`7c{(5@-k@E>eZFcW~R@uE??JE!KvsX z{O8Y~TTeM6s(+?mscyK+)_m~8z3TUdnU_>v8aj1Y2c@Q}=I{B)_W9Y_Y!QwvQMv~Y z9t4fS2?-TN%lH=-8ft24%2*aX*`;@r88m7wtmad2=i2M9ppNI+D7(M+|Nk?;dGjWZ zoXreIW;PS95LZ{%n!jJKXKamX*y>zD`wJyIan-NFAhHa~3eOL9CJj|$4k`9(!Z?Jj$pbfiO2MNN$a#7UEcbi}yJcHjLt^Tyk6Y^T{{I{lU}j^AH*r~3Wg@Y;EI^VF@aXRnRk9uyVT zbv7;e)|Sja=l}oVcUv6jC#2Z2<0Heju0;j! z|Ibr>UZ&ID`g=?6E>6D=+WB{CsTdcw79*EZ$fw<~*hr}Jvo z(tZ2p>Ba5>RWzXNYiZab@W_lWAy;zWFQ%1j%?IE5*Z&d*tvdh0rPz`II-nV}4Fh!2 ztZb-Yz04s7At9j`S67QWIy%11`d|L`R_lCCEwy|G29A@SE{-Ad<>%LYI$64Z*_JI+ z^kR2ec%92Ok^1%R?dcVPi)W?IzjXO>%E`&eBWpFquJ+f288dDy z;5cS}zvl2{f4iF*iEmHOk4{KXDBC^v@^b&;A0HBr-%7W$v-6p0)OtOx+V@!*r=klx zM?$XXzAC2KJ#LF%n(zO~yMEuVRbSW?TXwYFx)o*j|4%U}61cdzrETkWS}oeV*?4dD zcQr%9kJGLn&*GbHmaAlFIC1~Kuj|df>{=PT+-%10WtU%qHsnaJy;y4e?A%=My1ISI zhA&lR_R5tjCco~ONbzACF02;%*Um z#CGNSbx`YTPvz$ud#lSQpTC%4vf^r%jg3u5Z?CGA)vN^z7MSfcDg5{6=bxwg^$#Dm z%kNuwUDl>z!oR=2&3BwXdbCwMuHxaeXEt-~YG*xpl5(%+v+tQSV?RH?8E4aMY-|i> z`dC<7CmTo@NcC1!RV}*w^26uP+0%;Nfews0YkoiF>#M7v%+Q~?HR@Q8kj{ZzyH3%0tp^A z&=T@Jd-vv7RHvqkqpz>u54wJ?=!u7zPK1K28;7Dw!`3Q>?6n`RvffBDk@`Eo`km#yy5G4! zx3mf@YK_nl1J%iGywW!|Br>z}$?SM_M{R3Vuix^+X`2^b%=qy6v$BcFlm`zIK=(3# z`m}4ErLX<8$&(L1I@*2mIDS=cXv6r?=$g>(|~95fX)k zg}hwB5jtXATwI_-yg^%&^z{0!TnW*~R7uVNW|VLvj8(0jDh+_w2DT zGBP@G;>3dkjm#-2DFvUNoP1riHg3K9(x8PJTn`^UJaX)qkd#!{&75VMHcjg4;<|L{ z(u%cfpMJd_pZ{&=-rL*r(~tE?`iiaDA!KiFU-y0YeZ$I6DJD|AB@Bu!0=Z%bqKs-< zeL?~yxt^r(z|-JCspY{J&Zojo;GTYAmHr*Gc)+}~F#X_&+kyv!%_+s+&(4n-@_ zDfdP1_kQ1&!H~W3gJ_LrMXUXv4~Icl)#`p@)oBq}lzQdr)rm7_o@``hwNXUfw^ZU=HIj;>9mX_8AWxke-a>g~PLV*n8tEI{+ zA2hQ6`1AR^DyXr*Uij-vrdjT-BgcBBfByUZ{^Q4wg=bh_Ut24ke7tX}_wN<~Cl7|~ zr5~OiKU%tHSD%Do6KDqASL}<36Nh38s7w+&Fw3~+C&TPsx8&`KhubzL9Ax@=-5(^! zq1eK*A&oCS?tohJ!3%%qRliHTxX3kQYt+vpEdpTe+iMxD>;L`nF5CV0@i&2eHVq-o z2QOqlIMApQyX(rv4@)7coJv|4!eV3pE?T7VKj-v^r+hgE5J?%cWTUtV1W9Yo<78ISBFy#t{6{@udD!jXHcOwXM= z_o)-?9Z;S$P5xoTuzJp%Ic>*|9|z4}^|&pr5dyo{sl!^cVebNsQ)i~}#GgB0?&s&{ z30e&hzh6#VT>K{s)LTLaW*OF4GRD9D`YZ6_#fwXpEqnCrnVPOXM0x_lwVsFG?4W69 zeit{lO_`U~Ky$xGq23TWu+F$4*8j&PrtYs*e-F>KE>Al>O?QTmT4pB12S;SzA82F- z^&Kti|NY@E+x>SHqfc#bZe~NuT)*!H85tV0&2lF_P=(kgFkMAWZByCXsHv-0zdoL| zwd&T@d8>E1eVDZ#G#kmzzB%`{*`B?7mzF}Uf8<_g!1Qg;-Msl%uN1E{`LvYH?t0c% zVJ0S~8=F$QS@a=pXxY&u-_!6ncx{;f-g_UGGTB|t+Uo!7_ixZNY)x(LQd5{|VoWo3 zbv`f+UVPE!@#Dv!31AKmjtOC~)Dz8uOD16)K;7Huuh%&$oW3)s>Y(CS=1fg-CR?a1{is>KI zpLbmTLF+zzK5Mt^4%_YNkEg)lo|(CzWE5Wf=|AJ~bk6WJ-<_ol3=9mOu6{1-oD!M< Dt#!WM diff --git a/Documentation/RCU/Design/Requirements/RCUApplicability.svg b/Documentation/RCU/Design/Requirements/RCUApplicability.svg deleted file mode 100644 index ebcbeee391ed..000000000000 --- a/Documentation/RCU/Design/Requirements/RCUApplicability.svg +++ /dev/null @@ -1,237 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - Read-Mostly, Stale & - - Inconsistent Data OK - - (RCU Works Great!!!) - - (RCU Works Well) - - Read-Mostly, Need Consistent Data - - Read-Write, Need Consistent Data - - Update-Mostly, Need Consistent Data - - (RCU Might Be OK...) - - (1) Provide Existence Guarantees For Update-Friendly Mechanisms - - (2) Provide Wait-Free Read-Side Primitives for Real-Time Use) - - (RCU is Very Unlikely to be the Right Tool For The Job, But it Can: - - diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 01e12b86e81f..c67a96a2a389 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -1120,12 +1120,27 @@ These classes is covered in the following sections.

    Specialization

    -RCU is and always has been intended primarily for read-mostly situations, as -illustrated by the following figure. -This means that RCU's read-side primitives are optimized, often at the +RCU is and always has been intended primarily for read-mostly situations, +which means that RCU's read-side primitives are optimized, often at the expense of its update-side primitives. +Experience thus far is captured by the following list of situations: -

    RCUApplicability.svg

    +
      +
    1. Read-mostly data, where stale and inconsistent data is not + a problem: RCU works great! +
    2. Read-mostly data, where data must be consistent: + RCU works well. +
    3. Read-write data, where data must be consistent: + RCU might work OK. + Or not. +
    4. Write-mostly data, where data must be consistent: + RCU is very unlikely to be the right tool for the job, + with the following exceptions, where RCU can provide: +
        +
      1. Existence guarantees for update-friendly mechanisms. +
      2. Wait-free read-side primitives for real-time use. +
      +

    This focus on read-mostly situations means that RCU must interoperate @@ -1171,10 +1186,7 @@ some period of time, so the exact wait period is a judgment call. One of our pair of veternarians might wait 30 seconds before pronouncing the cat dead, while the other might insist on waiting a full minute. The two veternarians would then disagree on the state of the cat during -the final 30 seconds of the minute following the last heartbeat, as -fancifully illustrated below: - -

    2013-08-is-it-dead.png

    +the final 30 seconds of the minute following the last heartbeat.

    Interestingly enough, this same situation applies to hardware. diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx index 3355f1f9384c..d6a84f3e0451 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.htmlx +++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx @@ -1257,12 +1257,27 @@ These classes is covered in the following sections.

    Specialization

    -RCU is and always has been intended primarily for read-mostly situations, as -illustrated by the following figure. -This means that RCU's read-side primitives are optimized, often at the +RCU is and always has been intended primarily for read-mostly situations, +which means that RCU's read-side primitives are optimized, often at the expense of its update-side primitives. +Experience thus far is captured by the following list of situations: -

    RCUApplicability.svg

    +
      +
    1. Read-mostly data, where stale and inconsistent data is not + a problem: RCU works great! +
    2. Read-mostly data, where data must be consistent: + RCU works well. +
    3. Read-write data, where data must be consistent: + RCU might work OK. + Or not. +
    4. Write-mostly data, where data must be consistent: + RCU is very unlikely to be the right tool for the job, + with the following exceptions, where RCU can provide: +
        +
      1. Existence guarantees for update-friendly mechanisms. +
      2. Wait-free read-side primitives for real-time use. +
      +

    This focus on read-mostly situations means that RCU must interoperate @@ -1330,10 +1345,7 @@ some period of time, so the exact wait period is a judgment call. One of our pair of veternarians might wait 30 seconds before pronouncing the cat dead, while the other might insist on waiting a full minute. The two veternarians would then disagree on the state of the cat during -the final 30 seconds of the minute following the last heartbeat, as -fancifully illustrated below: - -

    2013-08-is-it-dead.png

    +the final 30 seconds of the minute following the last heartbeat.

    Interestingly enough, this same situation applies to hardware. -- GitLab From 6146f8df48cb52c46c256424bd03b567b889b7bb Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 15 Mar 2016 13:25:20 -0700 Subject: [PATCH 1024/9938] documentation: Get rid of duplicate .htmlx file This commit uses colors to obscure the quick-quiz answers, thus getting rid of the .htmlx file. Use your mouse to select the answer in order to see the text. Alternatively, use your favorite scripting language to remove all occurences of "" from the file. Reported-by: Linus Torvalds Signed-off-by: Paul E. McKenney --- .../RCU/Design/Requirements/Requirements.html | 889 +++-- .../Design/Requirements/Requirements.htmlx | 2872 ----------------- Documentation/RCU/Design/htmlqqz.sh | 108 - 3 files changed, 428 insertions(+), 3441 deletions(-) delete mode 100644 Documentation/RCU/Design/Requirements/Requirements.htmlx delete mode 100755 Documentation/RCU/Design/htmlqqz.sh diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index c67a96a2a389..acdad96f78e9 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -1,5 +1,3 @@ - - @@ -65,8 +63,8 @@ All that aside, here are the categories of currently known RCU requirements:

    This is followed by a summary, -which is in turn followed by the inevitable -answers to the quick quizzes. +however, the answers to each quick quiz immediately follows the quiz. +Select the big white space with your mouse to see the answer.

    Fundamental Requirements

    @@ -153,13 +151,27 @@ Therefore, the outcome: cannot happen. -

    Quick Quiz 1: -Wait a minute! -You said that updaters can make useful forward progress concurrently -with readers, but pre-existing readers will block -synchronize_rcu()!!! -Just who are you trying to fool??? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Wait a minute! + You said that updaters can make useful forward progress concurrently + with readers, but pre-existing readers will block + synchronize_rcu()!!! + Just who are you trying to fool??? +
    Answer:
    + First, if updaters do not wish to be blocked by readers, they can use + call_rcu() or kfree_rcu(), which will + be discussed later. + Second, even when using synchronize_rcu(), the other + update-side code does run concurrently with readers, whether + pre-existing or not. +
     

    This scenario resembles one of the first uses of RCU in @@ -210,9 +222,20 @@ to guarantee that do_something() never runs concurrently with recovery(), but with little or no synchronization overhead in do_something_dlm(). -

    Quick Quiz 2: -Why is the synchronize_rcu() on line 28 needed? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Why is the synchronize_rcu() on line 28 needed? +
    Answer:
    + Without that extra grace period, memory reordering could result in + do_something_dlm() executing do_something() + concurrently with the last bits of recovery(). +
     

    In order to avoid fatal problems such as deadlocks, @@ -332,12 +355,27 @@ It also prevents any number of “interesting” compiler optimizations, for example, the use of gp as a scratch location immediately preceding the assignment. -

    Quick Quiz 3: -But rcu_assign_pointer() does nothing to prevent the -two assignments to p->a and p->b -from being reordered. -Can't that also cause problems? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + But rcu_assign_pointer() does nothing to prevent the + two assignments to p->a and p->b + from being reordered. + Can't that also cause problems? +
    Answer:
    + No, it cannot. + The readers cannot see either of these two fields until + the assignment to gp, by which time both fields are + fully initialized. + So reordering the assignments + to p->a and p->b cannot possibly + cause any problems. +
     

    It is tempting to assume that the reader need not do anything special @@ -494,11 +532,42 @@ The rcu_access_pointer() on line 6 is similar to code protected by the corresponding update-side lock. -

    Quick Quiz 4: -Without the rcu_dereference() or the -rcu_access_pointer(), what destructive optimizations -might the compiler make use of? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Without the rcu_dereference() or the + rcu_access_pointer(), what destructive optimizations + might the compiler make use of? +
    Answer:
    + Let's start with what happens to do_something_gp() + if it fails to use rcu_dereference(). + It could reuse a value formerly fetched from this same pointer. + It could also fetch the pointer from gp in a byte-at-a-time + manner, resulting in load tearing, in turn resulting a bytewise + mash-up of two distince pointer values. + It might even use value-speculation optimizations, where it makes + a wrong guess, but by the time it gets around to checking the + value, an update has changed the pointer to match the wrong guess. + Too bad about any dereferences that returned pre-initialization garbage + in the meantime! + + +

    + For remove_gp_synchronous(), as long as all modifications + to gp are carried out while holding gp_lock, + the above optimizations are harmless. + However, + with CONFIG_SPARSE_RCU_POINTER=y, + sparse will complain if you + define gp with __rcu and then + access it without using + either rcu_access_pointer() or rcu_dereference(). +

     

    In short, RCU's publish-subscribe guarantee is provided by the combination @@ -571,28 +640,156 @@ systems with more than one CPU: synchronize_rcu() migrates in the meantime. -

    Quick Quiz 5: -Given that multiple CPUs can start RCU read-side critical sections -at any time without any ordering whatsoever, how can RCU possibly tell whether -or not a given RCU read-side critical section starts before a -given instance of synchronize_rcu()? -
    Answer - -

    Quick Quiz 6: -The first and second guarantees require unbelievably strict ordering! -Are all these memory barriers really required? -
    Answer - -

    Quick Quiz 7: -You claim that rcu_read_lock() and rcu_read_unlock() -generate absolutely no code in some kernel builds. -This means that the compiler might arbitrarily rearrange consecutive -RCU read-side critical sections. -Given such rearrangement, if a given RCU read-side critical section -is done, how can you be sure that all prior RCU read-side critical -sections are done? -Won't the compiler rearrangements make that impossible to determine? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Given that multiple CPUs can start RCU read-side critical sections + at any time without any ordering whatsoever, how can RCU possibly + tell whether or not a given RCU read-side critical section starts + before a given instance of synchronize_rcu()? +
    Answer:
    + If RCU cannot tell whether or not a given + RCU read-side critical section starts before a + given instance of synchronize_rcu(), + then it must assume that the RCU read-side critical section + started first. + In other words, a given instance of synchronize_rcu() + can avoid waiting on a given RCU read-side critical section only + if it can prove that synchronize_rcu() started first. +
     
    + + + + + + + + +
     
    Quick Quiz:
    + The first and second guarantees require unbelievably strict ordering! + Are all these memory barriers really required? +
    Answer:
    + Yes, they really are required. + To see why the first guarantee is required, consider the following + sequence of events: + + +
      +
    1. + CPU 1: rcu_read_lock() + +
    2. + CPU 1: q = rcu_dereference(gp); + /* Very likely to return p. */ + +
    3. + CPU 0: list_del_rcu(p); + +
    4. + CPU 0: synchronize_rcu() starts. + +
    5. + CPU 1: do_something_with(q->a); + /* No smp_mb(), so might happen after kfree(). */ + +
    6. + CPU 1: rcu_read_unlock() + +
    7. + CPU 0: synchronize_rcu() returns. + +
    8. + CPU 0: kfree(p); + +
    + +

    + Therefore, there absolutely must be a full memory barrier between the + end of the RCU read-side critical section and the end of the + grace period. + + +

    + The sequence of events demonstrating the necessity of the second rule + is roughly similar: + + +

      +
    1. CPU 0: list_del_rcu(p); + +
    2. CPU 0: synchronize_rcu() starts. + +
    3. CPU 1: rcu_read_lock() + +
    4. CPU 1: q = rcu_dereference(gp); + /* Might return p if no memory barrier. */ + +
    5. CPU 0: synchronize_rcu() returns. + +
    6. CPU 0: kfree(p); + +
    7. + CPU 1: do_something_with(q->a); /* Boom!!! */ + +
    8. CPU 1: rcu_read_unlock() + +
    + +

    + And similarly, without a memory barrier between the beginning of the + grace period and the beginning of the RCU read-side critical section, + CPU 1 might end up accessing the freelist. + + +

    + The “as if” rule of course applies, so that any + implementation that acts as if the appropriate memory barriers + were in place is a correct implementation. + That said, it is much easier to fool yourself into believing + that you have adhered to the as-if rule than it is to actually + adhere to it! +

     
    + + + + + + + + +
     
    Quick Quiz:
    + You claim that rcu_read_lock() and rcu_read_unlock() + generate absolutely no code in some kernel builds. + This means that the compiler might arbitrarily rearrange consecutive + RCU read-side critical sections. + Given such rearrangement, if a given RCU read-side critical section + is done, how can you be sure that all prior RCU read-side critical + sections are done? + Won't the compiler rearrangements make that impossible to determine? +
    Answer:
    + In cases where rcu_read_lock() and rcu_read_unlock() + generate absolutely no code, RCU infers quiescent states only at + special locations, for example, within the scheduler. + Because calls to schedule() had better prevent calling-code + accesses to shared variables from being rearranged across the call to + schedule(), if RCU detects the end of a given RCU read-side + critical section, it will necessarily detect the end of all prior + RCU read-side critical sections, no matter how aggressively the + compiler scrambles the code. + + +

    + Again, this all assumes that the compiler cannot scramble code across + calls to the scheduler, out of interrupt handlers, into the idle loop, + into user-mode code, and so on. + But if your kernel build allows that sort of scrambling, you have broken + far more than just RCU! +

     

    Note that these memory-barrier requirements do not replace the fundamental @@ -637,9 +834,19 @@ inconvenience can be avoided through use of the call_rcu() and kfree_rcu() API members described later in this document. -

    Quick Quiz 8: -But how does the upgrade-to-write operation exclude other readers? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + But how does the upgrade-to-write operation exclude other readers? +
    Answer:
    + It doesn't, just like normal RCU updates, which also do not exclude + RCU readers. +
     

    This guarantee allows lookup code to be shared between read-side @@ -725,9 +932,20 @@ to do significant reordering. This is by design: Any significant ordering constraints would slow down these fast-path APIs. -

    Quick Quiz 9: -Can't the compiler also reorder this code? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Can't the compiler also reorder this code? +
    Answer:
    + No, the volatile casts in READ_ONCE() and + WRITE_ONCE() prevent the compiler from reordering in + this particular case. +
     

    Readers Do Not Exclude Updaters

    @@ -780,10 +998,25 @@ new readers can start immediately after synchronize_rcu() starts, and synchronize_rcu() is under no obligation to wait for these new readers. -

    Quick Quiz 10: -Suppose that synchronize_rcu() did wait until all readers had completed. -Would the updater be able to rely on this? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Suppose that synchronize_rcu() did wait until all readers had completed. + Would the updater be able to rely on this? +
    Answer:
    + No. + Even if synchronize_rcu() were to wait until + all readers had completed, a new reader might start immediately after + synchronize_rcu() completed. + Therefore, the code following + synchronize_rcu() cannot rely on there being no readers + in any case. +
     

    Grace Periods Don't Partition Read-Side Critical Sections

    @@ -980,11 +1213,24 @@ grace period. As a result, an RCU read-side critical section cannot partition a pair of RCU grace periods. -

    Quick Quiz 11: -How long a sequence of grace periods, each separated by an RCU read-side -critical section, would be required to partition the RCU read-side -critical sections at the beginning and end of the chain? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + How long a sequence of grace periods, each separated by an RCU + read-side critical section, would be required to partition the RCU + read-side critical sections at the beginning and end of the chain? +
    Answer:
    + In theory, an infinite number. + In practice, an unknown number that is sensitive to both implementation + details and timing considerations. + Therefore, even in practice, RCU users must abide by the + theoretical rather than the practical answer. +
     

    Disabling Preemption Does Not Block Grace Periods

    @@ -1153,9 +1399,43 @@ synchronization primitives be legal within RCU read-side critical sections, including spinlocks, sequence locks, atomic operations, reference counters, and memory barriers. -

    Quick Quiz 12: -What about sleeping locks? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + What about sleeping locks? +
    Answer:
    + These are forbidden within Linux-kernel RCU read-side critical + sections because it is not legal to place a quiescent state + (in this case, voluntary context switch) within an RCU read-side + critical section. + However, sleeping locks may be used within userspace RCU read-side + critical sections, and also within Linux-kernel sleepable RCU + (SRCU) + read-side critical sections. + In addition, the -rt patchset turns spinlocks into a + sleeping locks so that the corresponding critical sections + can be preempted, which also means that these sleeplockified + spinlocks (but not other sleeping locks!) may be acquire within + -rt-Linux-kernel RCU read-side critical sections. + + +

    + Note that it is legal for a normal RCU read-side + critical section to conditionally acquire a sleeping locks + (as in mutex_trylock()), but only as long as it does + not loop indefinitely attempting to conditionally acquire that + sleeping locks. + The key point is that things like mutex_trylock() + either return with the mutex held, or return an error indication if + the mutex was not immediately available. + Either way, mutex_trylock() returns immediately without + sleeping. +

     

    It often comes as a surprise that many algorithms do not require a @@ -1378,12 +1658,27 @@ write an RCU callback function that takes too long. Long-running operations should be relegated to separate threads or (in the Linux kernel) workqueues. -

    Quick Quiz 13: -Why does line 19 use rcu_access_pointer()? -After all, call_rcu() on line 25 stores into the -structure, which would interact badly with concurrent insertions. -Doesn't this mean that rcu_dereference() is required? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Why does line 19 use rcu_access_pointer()? + After all, call_rcu() on line 25 stores into the + structure, which would interact badly with concurrent insertions. + Doesn't this mean that rcu_dereference() is required? +
    Answer:
    + Presumably the ->gp_lock acquired on line 18 excludes + any changes, including any insertions that rcu_dereference() + would protect against. + Therefore, any insertions will be delayed until after + ->gp_lock + is released on line 25, which in turn means that + rcu_access_pointer() suffices. +
     

    However, all that remove_gp_cb() is doing is @@ -1430,14 +1725,31 @@ This was due to the fact that RCU was not heavily used within DYNIX/ptx, so the very few places that needed something like synchronize_rcu() simply open-coded it. -

    Quick Quiz 14: -Earlier it was claimed that call_rcu() and -kfree_rcu() allowed updaters to avoid being blocked -by readers. -But how can that be correct, given that the invocation of the callback -and the freeing of the memory (respectively) must still wait for -a grace period to elapse? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + Earlier it was claimed that call_rcu() and + kfree_rcu() allowed updaters to avoid being blocked + by readers. + But how can that be correct, given that the invocation of the callback + and the freeing of the memory (respectively) must still wait for + a grace period to elapse? +
    Answer:
    + We could define things this way, but keep in mind that this sort of + definition would say that updates in garbage-collected languages + cannot complete until the next time the garbage collector runs, + which does not seem at all reasonable. + The key point is that in most cases, an updater using either + call_rcu() or kfree_rcu() can proceed to the + next update as soon as it has invoked call_rcu() or + kfree_rcu(), without having to wait for a subsequent + grace period. +
     

    But what if the updater must wait for the completion of code to be @@ -1862,11 +2174,26 @@ kthreads to be spawned. Therefore, invoking synchronize_rcu() during scheduler initialization can result in deadlock. -

    Quick Quiz 15: -So what happens with synchronize_rcu() during -scheduler initialization for CONFIG_PREEMPT=n -kernels? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + So what happens with synchronize_rcu() during + scheduler initialization for CONFIG_PREEMPT=n + kernels? +
    Answer:
    + In CONFIG_PREEMPT=n kernel, synchronize_rcu() + maps directly to synchronize_sched(). + Therefore, synchronize_rcu() works normally throughout + boot in CONFIG_PREEMPT=n kernels. + However, your code must also work in CONFIG_PREEMPT=y kernels, + so it is still necessary to avoid invoking synchronize_rcu() + during scheduler initialization. +
     

    I learned of these boot-time requirements as a result of a series of @@ -2571,10 +2898,23 @@ If you needed to wait on multiple different flavors of SRCU (but why???), you would need to create a wrapper function resembling call_my_srcu() for each SRCU flavor. -

    Quick Quiz 16: -But what if I need to wait for multiple RCU flavors, but I also need -the grace periods to be expedited? -
    Answer + + + + + + + +
     
    Quick Quiz:
    + But what if I need to wait for multiple RCU flavors, but I also need + the grace periods to be expedited? +
    Answer:
    + If you are using expedited grace periods, there should be less penalty + for waiting on them in succession. + But if that is nevertheless a problem, you can use workqueues + or multiple kthreads to wait on the various expedited grace + periods concurrently. +
     

    Again, it is usually better to adjust the RCU read-side critical sections @@ -2678,377 +3018,4 @@ and is provided under the terms of the Creative Commons Attribution-Share Alike 3.0 United States license. -

    -Answers to Quick Quizzes

    - - -

    Quick Quiz 1: -Wait a minute! -You said that updaters can make useful forward progress concurrently -with readers, but pre-existing readers will block -synchronize_rcu()!!! -Just who are you trying to fool??? - - -

    Answer: -First, if updaters do not wish to be blocked by readers, they can use -call_rcu() or kfree_rcu(), which will -be discussed later. -Second, even when using synchronize_rcu(), the other -update-side code does run concurrently with readers, whether pre-existing -or not. - - -

    Back to Quick Quiz 1. - - -

    Quick Quiz 2: -Why is the synchronize_rcu() on line 28 needed? - - -

    Answer: -Without that extra grace period, memory reordering could result in -do_something_dlm() executing do_something() -concurrently with the last bits of recovery(). - - -

    Back to Quick Quiz 2. - - -

    Quick Quiz 3: -But rcu_assign_pointer() does nothing to prevent the -two assignments to p->a and p->b -from being reordered. -Can't that also cause problems? - - -

    Answer: -No, it cannot. -The readers cannot see either of these two fields until -the assignment to gp, by which time both fields are -fully initialized. -So reordering the assignments -to p->a and p->b cannot possibly -cause any problems. - - -

    Back to Quick Quiz 3. - - -

    Quick Quiz 4: -Without the rcu_dereference() or the -rcu_access_pointer(), what destructive optimizations -might the compiler make use of? - - -

    Answer: -Let's start with what happens to do_something_gp() -if it fails to use rcu_dereference(). -It could reuse a value formerly fetched from this same pointer. -It could also fetch the pointer from gp in a byte-at-a-time -manner, resulting in load tearing, in turn resulting a bytewise -mash-up of two distince pointer values. -It might even use value-speculation optimizations, where it makes a wrong -guess, but by the time it gets around to checking the value, an update -has changed the pointer to match the wrong guess. -Too bad about any dereferences that returned pre-initialization garbage -in the meantime! - -

    -For remove_gp_synchronous(), as long as all modifications -to gp are carried out while holding gp_lock, -the above optimizations are harmless. -However, -with CONFIG_SPARSE_RCU_POINTER=y, -sparse will complain if you -define gp with __rcu and then -access it without using -either rcu_access_pointer() or rcu_dereference(). - - -

    Back to Quick Quiz 4. - - -

    Quick Quiz 5: -Given that multiple CPUs can start RCU read-side critical sections -at any time without any ordering whatsoever, how can RCU possibly tell whether -or not a given RCU read-side critical section starts before a -given instance of synchronize_rcu()? - - -

    Answer: -If RCU cannot tell whether or not a given -RCU read-side critical section starts before a -given instance of synchronize_rcu(), -then it must assume that the RCU read-side critical section -started first. -In other words, a given instance of synchronize_rcu() -can avoid waiting on a given RCU read-side critical section only -if it can prove that synchronize_rcu() started first. - - -

    Back to Quick Quiz 5. - - -

    Quick Quiz 6: -The first and second guarantees require unbelievably strict ordering! -Are all these memory barriers really required? - - -

    Answer: -Yes, they really are required. -To see why the first guarantee is required, consider the following -sequence of events: - -

      -
    1. CPU 1: rcu_read_lock() -
    2. CPU 1: q = rcu_dereference(gp); - /* Very likely to return p. */ -
    3. CPU 0: list_del_rcu(p); -
    4. CPU 0: synchronize_rcu() starts. -
    5. CPU 1: do_something_with(q->a); - /* No smp_mb(), so might happen after kfree(). */ -
    6. CPU 1: rcu_read_unlock() -
    7. CPU 0: synchronize_rcu() returns. -
    8. CPU 0: kfree(p); -
    - -

    -Therefore, there absolutely must be a full memory barrier between the -end of the RCU read-side critical section and the end of the -grace period. - -

    -The sequence of events demonstrating the necessity of the second rule -is roughly similar: - -

      -
    1. CPU 0: list_del_rcu(p); -
    2. CPU 0: synchronize_rcu() starts. -
    3. CPU 1: rcu_read_lock() -
    4. CPU 1: q = rcu_dereference(gp); - /* Might return p if no memory barrier. */ -
    5. CPU 0: synchronize_rcu() returns. -
    6. CPU 0: kfree(p); -
    7. CPU 1: do_something_with(q->a); /* Boom!!! */ -
    8. CPU 1: rcu_read_unlock() -
    - -

    -And similarly, without a memory barrier between the beginning of the -grace period and the beginning of the RCU read-side critical section, -CPU 1 might end up accessing the freelist. - -

    -The “as if” rule of course applies, so that any implementation -that acts as if the appropriate memory barriers were in place is a -correct implementation. -That said, it is much easier to fool yourself into believing that you have -adhered to the as-if rule than it is to actually adhere to it! - - -

    Back to Quick Quiz 6. - - -

    Quick Quiz 7: -You claim that rcu_read_lock() and rcu_read_unlock() -generate absolutely no code in some kernel builds. -This means that the compiler might arbitrarily rearrange consecutive -RCU read-side critical sections. -Given such rearrangement, if a given RCU read-side critical section -is done, how can you be sure that all prior RCU read-side critical -sections are done? -Won't the compiler rearrangements make that impossible to determine? - - -

    Answer: -In cases where rcu_read_lock() and rcu_read_unlock() -generate absolutely no code, RCU infers quiescent states only at -special locations, for example, within the scheduler. -Because calls to schedule() had better prevent calling-code -accesses to shared variables from being rearranged across the call to -schedule(), if RCU detects the end of a given RCU read-side -critical section, it will necessarily detect the end of all prior -RCU read-side critical sections, no matter how aggressively the -compiler scrambles the code. - -

    -Again, this all assumes that the compiler cannot scramble code across -calls to the scheduler, out of interrupt handlers, into the idle loop, -into user-mode code, and so on. -But if your kernel build allows that sort of scrambling, you have broken -far more than just RCU! - - -

    Back to Quick Quiz 7. - - -

    Quick Quiz 8: -But how does the upgrade-to-write operation exclude other readers? - - -

    Answer: -It doesn't, just like normal RCU updates, which also do not exclude -RCU readers. - - -

    Back to Quick Quiz 8. - - -

    Quick Quiz 9: -Can't the compiler also reorder this code? - - -

    Answer: -No, the volatile casts in READ_ONCE() and -WRITE_ONCE() prevent the compiler from reordering in -this particular case. - - -

    Back to Quick Quiz 9. - - -

    Quick Quiz 10: -Suppose that synchronize_rcu() did wait until all readers had completed. -Would the updater be able to rely on this? - - -

    Answer: -No. -Even if synchronize_rcu() were to wait until -all readers had completed, a new reader might start immediately after -synchronize_rcu() completed. -Therefore, the code following -synchronize_rcu() cannot rely on there being no readers -in any case. - - -

    Back to Quick Quiz 10. - - -

    Quick Quiz 11: -How long a sequence of grace periods, each separated by an RCU read-side -critical section, would be required to partition the RCU read-side -critical sections at the beginning and end of the chain? - - -

    Answer: -In theory, an infinite number. -In practice, an unknown number that is sensitive to both implementation -details and timing considerations. -Therefore, even in practice, RCU users must abide by the theoretical rather -than the practical answer. - - -

    Back to Quick Quiz 11. - - -

    Quick Quiz 12: -What about sleeping locks? - - -

    Answer: -These are forbidden within Linux-kernel RCU read-side critical sections -because it is not legal to place a quiescent state (in this case, -voluntary context switch) within an RCU read-side critical section. -However, sleeping locks may be used within userspace RCU read-side critical -sections, and also within Linux-kernel sleepable RCU -(SRCU) -read-side critical sections. -In addition, the -rt patchset turns spinlocks into a sleeping locks so -that the corresponding critical sections can be preempted, which -also means that these sleeplockified spinlocks (but not other sleeping locks!) -may be acquire within -rt-Linux-kernel RCU read-side critical sections. - -

    -Note that it is legal for a normal RCU read-side critical section -to conditionally acquire a sleeping locks (as in mutex_trylock()), -but only as long as it does not loop indefinitely attempting to -conditionally acquire that sleeping locks. -The key point is that things like mutex_trylock() -either return with the mutex held, or return an error indication if -the mutex was not immediately available. -Either way, mutex_trylock() returns immediately without sleeping. - - -

    Back to Quick Quiz 12. - - -

    Quick Quiz 13: -Why does line 19 use rcu_access_pointer()? -After all, call_rcu() on line 25 stores into the -structure, which would interact badly with concurrent insertions. -Doesn't this mean that rcu_dereference() is required? - - -

    Answer: -Presumably the ->gp_lock acquired on line 18 excludes -any changes, including any insertions that rcu_dereference() -would protect against. -Therefore, any insertions will be delayed until after ->gp_lock -is released on line 25, which in turn means that -rcu_access_pointer() suffices. - - -

    Back to Quick Quiz 13. - - -

    Quick Quiz 14: -Earlier it was claimed that call_rcu() and -kfree_rcu() allowed updaters to avoid being blocked -by readers. -But how can that be correct, given that the invocation of the callback -and the freeing of the memory (respectively) must still wait for -a grace period to elapse? - - -

    Answer: -We could define things this way, but keep in mind that this sort of -definition would say that updates in garbage-collected languages -cannot complete until the next time the garbage collector runs, -which does not seem at all reasonable. -The key point is that in most cases, an updater using either -call_rcu() or kfree_rcu() can proceed to the -next update as soon as it has invoked call_rcu() or -kfree_rcu(), without having to wait for a subsequent -grace period. - - -

    Back to Quick Quiz 14. - - -

    Quick Quiz 15: -So what happens with synchronize_rcu() during -scheduler initialization for CONFIG_PREEMPT=n -kernels? - - -

    Answer: -In CONFIG_PREEMPT=n kernel, synchronize_rcu() -maps directly to synchronize_sched(). -Therefore, synchronize_rcu() works normally throughout -boot in CONFIG_PREEMPT=n kernels. -However, your code must also work in CONFIG_PREEMPT=y kernels, -so it is still necessary to avoid invoking synchronize_rcu() -during scheduler initialization. - - -

    Back to Quick Quiz 15. - - -

    Quick Quiz 16: -But what if I need to wait for multiple RCU flavors, but I also need -the grace periods to be expedited? - - -

    Answer: -If you are using expedited grace periods, there should be less penalty -for waiting on them in succession. -But if that is nevertheless a problem, you can use workqueues or multiple -kthreads to wait on the various expedited grace periods concurrently. - - -

    Back to Quick Quiz 16. - - diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx deleted file mode 100644 index d6a84f3e0451..000000000000 --- a/Documentation/RCU/Design/Requirements/Requirements.htmlx +++ /dev/null @@ -1,2872 +0,0 @@ - - - A Tour Through RCU's Requirements [LWN.net] - - -

    A Tour Through RCU's Requirements

    - -

    Copyright IBM Corporation, 2015

    -

    Author: Paul E. McKenney

    -

    The initial version of this document appeared in the -LWN articles -here, -here, and -here.

    - -

    Introduction

    - -

    -Read-copy update (RCU) is a synchronization mechanism that is often -used as a replacement for reader-writer locking. -RCU is unusual in that updaters do not block readers, -which means that RCU's read-side primitives can be exceedingly fast -and scalable. -In addition, updaters can make useful forward progress concurrently -with readers. -However, all this concurrency between RCU readers and updaters does raise -the question of exactly what RCU readers are doing, which in turn -raises the question of exactly what RCU's requirements are. - -

    -This document therefore summarizes RCU's requirements, and can be thought -of as an informal, high-level specification for RCU. -It is important to understand that RCU's specification is primarily -empirical in nature; -in fact, I learned about many of these requirements the hard way. -This situation might cause some consternation, however, not only -has this learning process been a lot of fun, but it has also been -a great privilege to work with so many people willing to apply -technologies in interesting new ways. - -

    -All that aside, here are the categories of currently known RCU requirements: -

    - -
      -
    1. - Fundamental Requirements -
    2. Fundamental Non-Requirements -
    3. - Parallelism Facts of Life -
    4. - Quality-of-Implementation Requirements -
    5. - Linux Kernel Complications -
    6. - Software-Engineering Requirements -
    7. - Other RCU Flavors -
    8. - Possible Future Changes -
    - -

    -This is followed by a summary, -which is in turn followed by the inevitable -answers to the quick quizzes. - -

    Fundamental Requirements

    - -

    -RCU's fundamental requirements are the closest thing RCU has to hard -mathematical requirements. -These are: - -

      -
    1. - Grace-Period Guarantee -
    2. - Publish-Subscribe Guarantee -
    3. - Memory-Barrier Guarantees -
    4. - RCU Primitives Guaranteed to Execute Unconditionally -
    5. - Guaranteed Read-to-Write Upgrade -
    - -

    Grace-Period Guarantee

    - -

    -RCU's grace-period guarantee is unusual in being premeditated: -Jack Slingwine and I had this guarantee firmly in mind when we started -work on RCU (then called “rclock”) in the early 1990s. -That said, the past two decades of experience with RCU have produced -a much more detailed understanding of this guarantee. - -

    -RCU's grace-period guarantee allows updaters to wait for the completion -of all pre-existing RCU read-side critical sections. -An RCU read-side critical section -begins with the marker rcu_read_lock() and ends with -the marker rcu_read_unlock(). -These markers may be nested, and RCU treats a nested set as one -big RCU read-side critical section. -Production-quality implementations of rcu_read_lock() and -rcu_read_unlock() are extremely lightweight, and in -fact have exactly zero overhead in Linux kernels built for production -use with CONFIG_PREEMPT=n. - -

    -This guarantee allows ordering to be enforced with extremely low -overhead to readers, for example: - -

    -
    - 1 int x, y;
    - 2
    - 3 void thread0(void)
    - 4 {
    - 5   rcu_read_lock();
    - 6   r1 = READ_ONCE(x);
    - 7   r2 = READ_ONCE(y);
    - 8   rcu_read_unlock();
    - 9 }
    -10
    -11 void thread1(void)
    -12 {
    -13   WRITE_ONCE(x, 1);
    -14   synchronize_rcu();
    -15   WRITE_ONCE(y, 1);
    -16 }
    -
    -
    - -

    -Because the synchronize_rcu() on line 14 waits for -all pre-existing readers, any instance of thread0() that -loads a value of zero from x must complete before -thread1() stores to y, so that instance must -also load a value of zero from y. -Similarly, any instance of thread0() that loads a value of -one from y must have started after the -synchronize_rcu() started, and must therefore also load -a value of one from x. -Therefore, the outcome: -

    -
    -(r1 == 0 && r2 == 1)
    -
    -
    -cannot happen. - -

    @@QQ@@ -Wait a minute! -You said that updaters can make useful forward progress concurrently -with readers, but pre-existing readers will block -synchronize_rcu()!!! -Just who are you trying to fool??? -

    @@QQA@@ -First, if updaters do not wish to be blocked by readers, they can use -call_rcu() or kfree_rcu(), which will -be discussed later. -Second, even when using synchronize_rcu(), the other -update-side code does run concurrently with readers, whether pre-existing -or not. -

    @@QQE@@ - -

    -This scenario resembles one of the first uses of RCU in -DYNIX/ptx, -which managed a distributed lock manager's transition into -a state suitable for handling recovery from node failure, -more or less as follows: - -

    -
    - 1 #define STATE_NORMAL        0
    - 2 #define STATE_WANT_RECOVERY 1
    - 3 #define STATE_RECOVERING    2
    - 4 #define STATE_WANT_NORMAL   3
    - 5
    - 6 int state = STATE_NORMAL;
    - 7
    - 8 void do_something_dlm(void)
    - 9 {
    -10   int state_snap;
    -11
    -12   rcu_read_lock();
    -13   state_snap = READ_ONCE(state);
    -14   if (state_snap == STATE_NORMAL)
    -15     do_something();
    -16   else
    -17     do_something_carefully();
    -18   rcu_read_unlock();
    -19 }
    -20
    -21 void start_recovery(void)
    -22 {
    -23   WRITE_ONCE(state, STATE_WANT_RECOVERY);
    -24   synchronize_rcu();
    -25   WRITE_ONCE(state, STATE_RECOVERING);
    -26   recovery();
    -27   WRITE_ONCE(state, STATE_WANT_NORMAL);
    -28   synchronize_rcu();
    -29   WRITE_ONCE(state, STATE_NORMAL);
    -30 }
    -
    -
    - -

    -The RCU read-side critical section in do_something_dlm() -works with the synchronize_rcu() in start_recovery() -to guarantee that do_something() never runs concurrently -with recovery(), but with little or no synchronization -overhead in do_something_dlm(). - -

    @@QQ@@ -Why is the synchronize_rcu() on line 28 needed? -

    @@QQA@@ -Without that extra grace period, memory reordering could result in -do_something_dlm() executing do_something() -concurrently with the last bits of recovery(). -

    @@QQE@@ - -

    -In order to avoid fatal problems such as deadlocks, -an RCU read-side critical section must not contain calls to -synchronize_rcu(). -Similarly, an RCU read-side critical section must not -contain anything that waits, directly or indirectly, on completion of -an invocation of synchronize_rcu(). - -

    -Although RCU's grace-period guarantee is useful in and of itself, with -quite a few use cases, -it would be good to be able to use RCU to coordinate read-side -access to linked data structures. -For this, the grace-period guarantee is not sufficient, as can -be seen in function add_gp_buggy() below. -We will look at the reader's code later, but in the meantime, just think of -the reader as locklessly picking up the gp pointer, -and, if the value loaded is non-NULL, locklessly accessing the -->a and ->b fields. - -

    -
    - 1 bool add_gp_buggy(int a, int b)
    - 2 {
    - 3   p = kmalloc(sizeof(*p), GFP_KERNEL);
    - 4   if (!p)
    - 5     return -ENOMEM;
    - 6   spin_lock(&gp_lock);
    - 7   if (rcu_access_pointer(gp)) {
    - 8     spin_unlock(&gp_lock);
    - 9     return false;
    -10   }
    -11   p->a = a;
    -12   p->b = a;
    -13   gp = p; /* ORDERING BUG */
    -14   spin_unlock(&gp_lock);
    -15   return true;
    -16 }
    -
    -
    - -

    -The problem is that both the compiler and weakly ordered CPUs are within -their rights to reorder this code as follows: - -

    -
    - 1 bool add_gp_buggy_optimized(int a, int b)
    - 2 {
    - 3   p = kmalloc(sizeof(*p), GFP_KERNEL);
    - 4   if (!p)
    - 5     return -ENOMEM;
    - 6   spin_lock(&gp_lock);
    - 7   if (rcu_access_pointer(gp)) {
    - 8     spin_unlock(&gp_lock);
    - 9     return false;
    -10   }
    -11   gp = p; /* ORDERING BUG */
    -12   p->a = a;
    -13   p->b = a;
    -14   spin_unlock(&gp_lock);
    -15   return true;
    -16 }
    -
    -
    - -

    -If an RCU reader fetches gp just after -add_gp_buggy_optimized executes line 11, -it will see garbage in the ->a and ->b -fields. -And this is but one of many ways in which compiler and hardware optimizations -could cause trouble. -Therefore, we clearly need some way to prevent the compiler and the CPU from -reordering in this manner, which brings us to the publish-subscribe -guarantee discussed in the next section. - -

    Publish/Subscribe Guarantee

    - -

    -RCU's publish-subscribe guarantee allows data to be inserted -into a linked data structure without disrupting RCU readers. -The updater uses rcu_assign_pointer() to insert the -new data, and readers use rcu_dereference() to -access data, whether new or old. -The following shows an example of insertion: - -

    -
    - 1 bool add_gp(int a, int b)
    - 2 {
    - 3   p = kmalloc(sizeof(*p), GFP_KERNEL);
    - 4   if (!p)
    - 5     return -ENOMEM;
    - 6   spin_lock(&gp_lock);
    - 7   if (rcu_access_pointer(gp)) {
    - 8     spin_unlock(&gp_lock);
    - 9     return false;
    -10   }
    -11   p->a = a;
    -12   p->b = a;
    -13   rcu_assign_pointer(gp, p);
    -14   spin_unlock(&gp_lock);
    -15   return true;
    -16 }
    -
    -
    - -

    -The rcu_assign_pointer() on line 13 is conceptually -equivalent to a simple assignment statement, but also guarantees -that its assignment will -happen after the two assignments in lines 11 and 12, -similar to the C11 memory_order_release store operation. -It also prevents any number of “interesting” compiler -optimizations, for example, the use of gp as a scratch -location immediately preceding the assignment. - -

    @@QQ@@ -But rcu_assign_pointer() does nothing to prevent the -two assignments to p->a and p->b -from being reordered. -Can't that also cause problems? -

    @@QQA@@ -No, it cannot. -The readers cannot see either of these two fields until -the assignment to gp, by which time both fields are -fully initialized. -So reordering the assignments -to p->a and p->b cannot possibly -cause any problems. -

    @@QQE@@ - -

    -It is tempting to assume that the reader need not do anything special -to control its accesses to the RCU-protected data, -as shown in do_something_gp_buggy() below: - -

    -
    - 1 bool do_something_gp_buggy(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   p = gp;  /* OPTIMIZATIONS GALORE!!! */
    - 5   if (p) {
    - 6     do_something(p->a, p->b);
    - 7     rcu_read_unlock();
    - 8     return true;
    - 9   }
    -10   rcu_read_unlock();
    -11   return false;
    -12 }
    -
    -
    - -

    -However, this temptation must be resisted because there are a -surprisingly large number of ways that the compiler -(to say nothing of -DEC Alpha CPUs) -can trip this code up. -For but one example, if the compiler were short of registers, it -might choose to refetch from gp rather than keeping -a separate copy in p as follows: - -

    -
    - 1 bool do_something_gp_buggy_optimized(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   if (gp) { /* OPTIMIZATIONS GALORE!!! */
    - 5     do_something(gp->a, gp->b);
    - 6     rcu_read_unlock();
    - 7     return true;
    - 8   }
    - 9   rcu_read_unlock();
    -10   return false;
    -11 }
    -
    -
    - -

    -If this function ran concurrently with a series of updates that -replaced the current structure with a new one, -the fetches of gp->a -and gp->b might well come from two different structures, -which could cause serious confusion. -To prevent this (and much else besides), do_something_gp() uses -rcu_dereference() to fetch from gp: - -

    -
    - 1 bool do_something_gp(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   p = rcu_dereference(gp);
    - 5   if (p) {
    - 6     do_something(p->a, p->b);
    - 7     rcu_read_unlock();
    - 8     return true;
    - 9   }
    -10   rcu_read_unlock();
    -11   return false;
    -12 }
    -
    -
    - -

    -The rcu_dereference() uses volatile casts and (for DEC Alpha) -memory barriers in the Linux kernel. -Should a -high-quality implementation of C11 memory_order_consume [PDF] -ever appear, then rcu_dereference() could be implemented -as a memory_order_consume load. -Regardless of the exact implementation, a pointer fetched by -rcu_dereference() may not be used outside of the -outermost RCU read-side critical section containing that -rcu_dereference(), unless protection of -the corresponding data element has been passed from RCU to some -other synchronization mechanism, most commonly locking or -reference counting. - -

    -In short, updaters use rcu_assign_pointer() and readers -use rcu_dereference(), and these two RCU API elements -work together to ensure that readers have a consistent view of -newly added data elements. - -

    -Of course, it is also necessary to remove elements from RCU-protected -data structures, for example, using the following process: - -

      -
    1. Remove the data element from the enclosing structure. -
    2. Wait for all pre-existing RCU read-side critical sections - to complete (because only pre-existing readers can possibly have - a reference to the newly removed data element). -
    3. At this point, only the updater has a reference to the - newly removed data element, so it can safely reclaim - the data element, for example, by passing it to kfree(). -
    - -This process is implemented by remove_gp_synchronous(): - -
    -
    - 1 bool remove_gp_synchronous(void)
    - 2 {
    - 3   struct foo *p;
    - 4
    - 5   spin_lock(&gp_lock);
    - 6   p = rcu_access_pointer(gp);
    - 7   if (!p) {
    - 8     spin_unlock(&gp_lock);
    - 9     return false;
    -10   }
    -11   rcu_assign_pointer(gp, NULL);
    -12   spin_unlock(&gp_lock);
    -13   synchronize_rcu();
    -14   kfree(p);
    -15   return true;
    -16 }
    -
    -
    - -

    -This function is straightforward, with line 13 waiting for a grace -period before line 14 frees the old data element. -This waiting ensures that readers will reach line 7 of -do_something_gp() before the data element referenced by -p is freed. -The rcu_access_pointer() on line 6 is similar to -rcu_dereference(), except that: - -

      -
    1. The value returned by rcu_access_pointer() - cannot be dereferenced. - If you want to access the value pointed to as well as - the pointer itself, use rcu_dereference() - instead of rcu_access_pointer(). -
    2. The call to rcu_access_pointer() need not be - protected. - In contrast, rcu_dereference() must either be - within an RCU read-side critical section or in a code - segment where the pointer cannot change, for example, in - code protected by the corresponding update-side lock. -
    - -

    @@QQ@@ -Without the rcu_dereference() or the -rcu_access_pointer(), what destructive optimizations -might the compiler make use of? -

    @@QQA@@ -Let's start with what happens to do_something_gp() -if it fails to use rcu_dereference(). -It could reuse a value formerly fetched from this same pointer. -It could also fetch the pointer from gp in a byte-at-a-time -manner, resulting in load tearing, in turn resulting a bytewise -mash-up of two distince pointer values. -It might even use value-speculation optimizations, where it makes a wrong -guess, but by the time it gets around to checking the value, an update -has changed the pointer to match the wrong guess. -Too bad about any dereferences that returned pre-initialization garbage -in the meantime! - -

    -For remove_gp_synchronous(), as long as all modifications -to gp are carried out while holding gp_lock, -the above optimizations are harmless. -However, -with CONFIG_SPARSE_RCU_POINTER=y, -sparse will complain if you -define gp with __rcu and then -access it without using -either rcu_access_pointer() or rcu_dereference(). -

    @@QQE@@ - -

    -In short, RCU's publish-subscribe guarantee is provided by the combination -of rcu_assign_pointer() and rcu_dereference(). -This guarantee allows data elements to be safely added to RCU-protected -linked data structures without disrupting RCU readers. -This guarantee can be used in combination with the grace-period -guarantee to also allow data elements to be removed from RCU-protected -linked data structures, again without disrupting RCU readers. - -

    -This guarantee was only partially premeditated. -DYNIX/ptx used an explicit memory barrier for publication, but had nothing -resembling rcu_dereference() for subscription, nor did it -have anything resembling the smp_read_barrier_depends() -that was later subsumed into rcu_dereference(). -The need for these operations made itself known quite suddenly at a -late-1990s meeting with the DEC Alpha architects, back in the days when -DEC was still a free-standing company. -It took the Alpha architects a good hour to convince me that any sort -of barrier would ever be needed, and it then took me a good two hours -to convince them that their documentation did not make this point clear. -More recent work with the C and C++ standards committees have provided -much education on tricks and traps from the compiler. -In short, compilers were much less tricky in the early 1990s, but in -2015, don't even think about omitting rcu_dereference()! - -

    Memory-Barrier Guarantees

    - -

    -The previous section's simple linked-data-structure scenario clearly -demonstrates the need for RCU's stringent memory-ordering guarantees on -systems with more than one CPU: - -

      -
    1. Each CPU that has an RCU read-side critical section that - begins before synchronize_rcu() starts is - guaranteed to execute a full memory barrier between the time - that the RCU read-side critical section ends and the time that - synchronize_rcu() returns. - Without this guarantee, a pre-existing RCU read-side critical section - might hold a reference to the newly removed struct foo - after the kfree() on line 14 of - remove_gp_synchronous(). -
    2. Each CPU that has an RCU read-side critical section that ends - after synchronize_rcu() returns is guaranteed - to execute a full memory barrier between the time that - synchronize_rcu() begins and the time that the RCU - read-side critical section begins. - Without this guarantee, a later RCU read-side critical section - running after the kfree() on line 14 of - remove_gp_synchronous() might - later run do_something_gp() and find the - newly deleted struct foo. -
    3. If the task invoking synchronize_rcu() remains - on a given CPU, then that CPU is guaranteed to execute a full - memory barrier sometime during the execution of - synchronize_rcu(). - This guarantee ensures that the kfree() on - line 14 of remove_gp_synchronous() really does - execute after the removal on line 11. -
    4. If the task invoking synchronize_rcu() migrates - among a group of CPUs during that invocation, then each of the - CPUs in that group is guaranteed to execute a full memory barrier - sometime during the execution of synchronize_rcu(). - This guarantee also ensures that the kfree() on - line 14 of remove_gp_synchronous() really does - execute after the removal on - line 11, but also in the case where the thread executing the - synchronize_rcu() migrates in the meantime. -
    - -

    @@QQ@@ -Given that multiple CPUs can start RCU read-side critical sections -at any time without any ordering whatsoever, how can RCU possibly tell whether -or not a given RCU read-side critical section starts before a -given instance of synchronize_rcu()? -

    @@QQA@@ -If RCU cannot tell whether or not a given -RCU read-side critical section starts before a -given instance of synchronize_rcu(), -then it must assume that the RCU read-side critical section -started first. -In other words, a given instance of synchronize_rcu() -can avoid waiting on a given RCU read-side critical section only -if it can prove that synchronize_rcu() started first. -

    @@QQE@@ - -

    @@QQ@@ -The first and second guarantees require unbelievably strict ordering! -Are all these memory barriers really required? -

    @@QQA@@ -Yes, they really are required. -To see why the first guarantee is required, consider the following -sequence of events: - -

      -
    1. CPU 1: rcu_read_lock() -
    2. CPU 1: q = rcu_dereference(gp); - /* Very likely to return p. */ -
    3. CPU 0: list_del_rcu(p); -
    4. CPU 0: synchronize_rcu() starts. -
    5. CPU 1: do_something_with(q->a); - /* No smp_mb(), so might happen after kfree(). */ -
    6. CPU 1: rcu_read_unlock() -
    7. CPU 0: synchronize_rcu() returns. -
    8. CPU 0: kfree(p); -
    - -

    -Therefore, there absolutely must be a full memory barrier between the -end of the RCU read-side critical section and the end of the -grace period. - -

    -The sequence of events demonstrating the necessity of the second rule -is roughly similar: - -

      -
    1. CPU 0: list_del_rcu(p); -
    2. CPU 0: synchronize_rcu() starts. -
    3. CPU 1: rcu_read_lock() -
    4. CPU 1: q = rcu_dereference(gp); - /* Might return p if no memory barrier. */ -
    5. CPU 0: synchronize_rcu() returns. -
    6. CPU 0: kfree(p); -
    7. CPU 1: do_something_with(q->a); /* Boom!!! */ -
    8. CPU 1: rcu_read_unlock() -
    - -

    -And similarly, without a memory barrier between the beginning of the -grace period and the beginning of the RCU read-side critical section, -CPU 1 might end up accessing the freelist. - -

    -The “as if” rule of course applies, so that any implementation -that acts as if the appropriate memory barriers were in place is a -correct implementation. -That said, it is much easier to fool yourself into believing that you have -adhered to the as-if rule than it is to actually adhere to it! -

    @@QQE@@ - -

    @@QQ@@ -You claim that rcu_read_lock() and rcu_read_unlock() -generate absolutely no code in some kernel builds. -This means that the compiler might arbitrarily rearrange consecutive -RCU read-side critical sections. -Given such rearrangement, if a given RCU read-side critical section -is done, how can you be sure that all prior RCU read-side critical -sections are done? -Won't the compiler rearrangements make that impossible to determine? -

    @@QQA@@ -In cases where rcu_read_lock() and rcu_read_unlock() -generate absolutely no code, RCU infers quiescent states only at -special locations, for example, within the scheduler. -Because calls to schedule() had better prevent calling-code -accesses to shared variables from being rearranged across the call to -schedule(), if RCU detects the end of a given RCU read-side -critical section, it will necessarily detect the end of all prior -RCU read-side critical sections, no matter how aggressively the -compiler scrambles the code. - -

    -Again, this all assumes that the compiler cannot scramble code across -calls to the scheduler, out of interrupt handlers, into the idle loop, -into user-mode code, and so on. -But if your kernel build allows that sort of scrambling, you have broken -far more than just RCU! -

    @@QQE@@ - -

    -Note that these memory-barrier requirements do not replace the fundamental -RCU requirement that a grace period wait for all pre-existing readers. -On the contrary, the memory barriers called out in this section must operate in -such a way as to enforce this fundamental requirement. -Of course, different implementations enforce this requirement in different -ways, but enforce it they must. - -

    RCU Primitives Guaranteed to Execute Unconditionally

    - -

    -The common-case RCU primitives are unconditional. -They are invoked, they do their job, and they return, with no possibility -of error, and no need to retry. -This is a key RCU design philosophy. - -

    -However, this philosophy is pragmatic rather than pigheaded. -If someone comes up with a good justification for a particular conditional -RCU primitive, it might well be implemented and added. -After all, this guarantee was reverse-engineered, not premeditated. -The unconditional nature of the RCU primitives was initially an -accident of implementation, and later experience with synchronization -primitives with conditional primitives caused me to elevate this -accident to a guarantee. -Therefore, the justification for adding a conditional primitive to -RCU would need to be based on detailed and compelling use cases. - -

    Guaranteed Read-to-Write Upgrade

    - -

    -As far as RCU is concerned, it is always possible to carry out an -update within an RCU read-side critical section. -For example, that RCU read-side critical section might search for -a given data element, and then might acquire the update-side -spinlock in order to update that element, all while remaining -in that RCU read-side critical section. -Of course, it is necessary to exit the RCU read-side critical section -before invoking synchronize_rcu(), however, this -inconvenience can be avoided through use of the -call_rcu() and kfree_rcu() API members -described later in this document. - -

    @@QQ@@ -But how does the upgrade-to-write operation exclude other readers? -

    @@QQA@@ -It doesn't, just like normal RCU updates, which also do not exclude -RCU readers. -

    @@QQE@@ - -

    -This guarantee allows lookup code to be shared between read-side -and update-side code, and was premeditated, appearing in the earliest -DYNIX/ptx RCU documentation. - -

    Fundamental Non-Requirements

    - -

    -RCU provides extremely lightweight readers, and its read-side guarantees, -though quite useful, are correspondingly lightweight. -It is therefore all too easy to assume that RCU is guaranteeing more -than it really is. -Of course, the list of things that RCU does not guarantee is infinitely -long, however, the following sections list a few non-guarantees that -have caused confusion. -Except where otherwise noted, these non-guarantees were premeditated. - -

      -
    1. - Readers Impose Minimal Ordering -
    2. - Readers Do Not Exclude Updaters -
    3. - Updaters Only Wait For Old Readers -
    4. - Grace Periods Don't Partition Read-Side Critical Sections -
    5. - Read-Side Critical Sections Don't Partition Grace Periods -
    6. - Disabling Preemption Does Not Block Grace Periods -
    - -

    Readers Impose Minimal Ordering

    - -

    -Reader-side markers such as rcu_read_lock() and -rcu_read_unlock() provide absolutely no ordering guarantees -except through their interaction with the grace-period APIs such as -synchronize_rcu(). -To see this, consider the following pair of threads: - -

    -
    - 1 void thread0(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   WRITE_ONCE(x, 1);
    - 5   rcu_read_unlock();
    - 6   rcu_read_lock();
    - 7   WRITE_ONCE(y, 1);
    - 8   rcu_read_unlock();
    - 9 }
    -10
    -11 void thread1(void)
    -12 {
    -13   rcu_read_lock();
    -14   r1 = READ_ONCE(y);
    -15   rcu_read_unlock();
    -16   rcu_read_lock();
    -17   r2 = READ_ONCE(x);
    -18   rcu_read_unlock();
    -19 }
    -
    -
    - -

    -After thread0() and thread1() execute -concurrently, it is quite possible to have - -

    -
    -(r1 == 1 && r2 == 0)
    -
    -
    - -(that is, y appears to have been assigned before x), -which would not be possible if rcu_read_lock() and -rcu_read_unlock() had much in the way of ordering -properties. -But they do not, so the CPU is within its rights -to do significant reordering. -This is by design: Any significant ordering constraints would slow down -these fast-path APIs. - -

    @@QQ@@ -Can't the compiler also reorder this code? -

    @@QQA@@ -No, the volatile casts in READ_ONCE() and -WRITE_ONCE() prevent the compiler from reordering in -this particular case. -

    @@QQE@@ - -

    Readers Do Not Exclude Updaters

    - -

    -Neither rcu_read_lock() nor rcu_read_unlock() -exclude updates. -All they do is to prevent grace periods from ending. -The following example illustrates this: - -

    -
    - 1 void thread0(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   r1 = READ_ONCE(y);
    - 5   if (r1) {
    - 6     do_something_with_nonzero_x();
    - 7     r2 = READ_ONCE(x);
    - 8     WARN_ON(!r2); /* BUG!!! */
    - 9   }
    -10   rcu_read_unlock();
    -11 }
    -12
    -13 void thread1(void)
    -14 {
    -15   spin_lock(&my_lock);
    -16   WRITE_ONCE(x, 1);
    -17   WRITE_ONCE(y, 1);
    -18   spin_unlock(&my_lock);
    -19 }
    -
    -
    - -

    -If the thread0() function's rcu_read_lock() -excluded the thread1() function's update, -the WARN_ON() could never fire. -But the fact is that rcu_read_lock() does not exclude -much of anything aside from subsequent grace periods, of which -thread1() has none, so the -WARN_ON() can and does fire. - -

    Updaters Only Wait For Old Readers

    - -

    -It might be tempting to assume that after synchronize_rcu() -completes, there are no readers executing. -This temptation must be avoided because -new readers can start immediately after synchronize_rcu() -starts, and synchronize_rcu() is under no -obligation to wait for these new readers. - -

    @@QQ@@ -Suppose that synchronize_rcu() did wait until all readers had completed. -Would the updater be able to rely on this? -

    @@QQA@@ -No. -Even if synchronize_rcu() were to wait until -all readers had completed, a new reader might start immediately after -synchronize_rcu() completed. -Therefore, the code following -synchronize_rcu() cannot rely on there being no readers -in any case. -

    @@QQE@@ - -

    -Grace Periods Don't Partition Read-Side Critical Sections

    - -

    -It is tempting to assume that if any part of one RCU read-side critical -section precedes a given grace period, and if any part of another RCU -read-side critical section follows that same grace period, then all of -the first RCU read-side critical section must precede all of the second. -However, this just isn't the case: A single grace period does not -partition the set of RCU read-side critical sections. -An example of this situation can be illustrated as follows, where -x, y, and z are initially all zero: - -

    -
    - 1 void thread0(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   WRITE_ONCE(a, 1);
    - 5   WRITE_ONCE(b, 1);
    - 6   rcu_read_unlock();
    - 7 }
    - 8
    - 9 void thread1(void)
    -10 {
    -11   r1 = READ_ONCE(a);
    -12   synchronize_rcu();
    -13   WRITE_ONCE(c, 1);
    -14 }
    -15
    -16 void thread2(void)
    -17 {
    -18   rcu_read_lock();
    -19   r2 = READ_ONCE(b);
    -20   r3 = READ_ONCE(c);
    -21   rcu_read_unlock();
    -22 }
    -
    -
    - -

    -It turns out that the outcome: - -

    -
    -(r1 == 1 && r2 == 0 && r3 == 1)
    -
    -
    - -is entirely possible. -The following figure show how this can happen, with each circled -QS indicating the point at which RCU recorded a -quiescent state for each thread, that is, a state in which -RCU knows that the thread cannot be in the midst of an RCU read-side -critical section that started before the current grace period: - -

    GPpartitionReaders1.svg

    - -

    -If it is necessary to partition RCU read-side critical sections in this -manner, it is necessary to use two grace periods, where the first -grace period is known to end before the second grace period starts: - -

    -
    - 1 void thread0(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   WRITE_ONCE(a, 1);
    - 5   WRITE_ONCE(b, 1);
    - 6   rcu_read_unlock();
    - 7 }
    - 8
    - 9 void thread1(void)
    -10 {
    -11   r1 = READ_ONCE(a);
    -12   synchronize_rcu();
    -13   WRITE_ONCE(c, 1);
    -14 }
    -15
    -16 void thread2(void)
    -17 {
    -18   r2 = READ_ONCE(c);
    -19   synchronize_rcu();
    -20   WRITE_ONCE(d, 1);
    -21 }
    -22
    -23 void thread3(void)
    -24 {
    -25   rcu_read_lock();
    -26   r3 = READ_ONCE(b);
    -27   r4 = READ_ONCE(d);
    -28   rcu_read_unlock();
    -29 }
    -
    -
    - -

    -Here, if (r1 == 1), then -thread0()'s write to b must happen -before the end of thread1()'s grace period. -If in addition (r4 == 1), then -thread3()'s read from b must happen -after the beginning of thread2()'s grace period. -If it is also the case that (r2 == 1), then the -end of thread1()'s grace period must precede the -beginning of thread2()'s grace period. -This mean that the two RCU read-side critical sections cannot overlap, -guaranteeing that (r3 == 1). -As a result, the outcome: - -

    -
    -(r1 == 1 && r2 == 1 && r3 == 0 && r4 == 1)
    -
    -
    - -cannot happen. - -

    -This non-requirement was also non-premeditated, but became apparent -when studying RCU's interaction with memory ordering. - -

    -Read-Side Critical Sections Don't Partition Grace Periods

    - -

    -It is also tempting to assume that if an RCU read-side critical section -happens between a pair of grace periods, then those grace periods cannot -overlap. -However, this temptation leads nowhere good, as can be illustrated by -the following, with all variables initially zero: - -

    -
    - 1 void thread0(void)
    - 2 {
    - 3   rcu_read_lock();
    - 4   WRITE_ONCE(a, 1);
    - 5   WRITE_ONCE(b, 1);
    - 6   rcu_read_unlock();
    - 7 }
    - 8
    - 9 void thread1(void)
    -10 {
    -11   r1 = READ_ONCE(a);
    -12   synchronize_rcu();
    -13   WRITE_ONCE(c, 1);
    -14 }
    -15
    -16 void thread2(void)
    -17 {
    -18   rcu_read_lock();
    -19   WRITE_ONCE(d, 1);
    -20   r2 = READ_ONCE(c);
    -21   rcu_read_unlock();
    -22 }
    -23
    -24 void thread3(void)
    -25 {
    -26   r3 = READ_ONCE(d);
    -27   synchronize_rcu();
    -28   WRITE_ONCE(e, 1);
    -29 }
    -30
    -31 void thread4(void)
    -32 {
    -33   rcu_read_lock();
    -34   r4 = READ_ONCE(b);
    -35   r5 = READ_ONCE(e);
    -36   rcu_read_unlock();
    -37 }
    -
    -
    - -

    -In this case, the outcome: - -

    -
    -(r1 == 1 && r2 == 1 && r3 == 1 && r4 == 0 && r5 == 1)
    -
    -
    - -is entirely possible, as illustrated below: - -

    ReadersPartitionGP1.svg

    - -

    -Again, an RCU read-side critical section can overlap almost all of a -given grace period, just so long as it does not overlap the entire -grace period. -As a result, an RCU read-side critical section cannot partition a pair -of RCU grace periods. - -

    @@QQ@@ -How long a sequence of grace periods, each separated by an RCU read-side -critical section, would be required to partition the RCU read-side -critical sections at the beginning and end of the chain? -

    @@QQA@@ -In theory, an infinite number. -In practice, an unknown number that is sensitive to both implementation -details and timing considerations. -Therefore, even in practice, RCU users must abide by the theoretical rather -than the practical answer. -

    @@QQE@@ - -

    -Disabling Preemption Does Not Block Grace Periods

    - -

    -There was a time when disabling preemption on any given CPU would block -subsequent grace periods. -However, this was an accident of implementation and is not a requirement. -And in the current Linux-kernel implementation, disabling preemption -on a given CPU in fact does not block grace periods, as Oleg Nesterov -demonstrated. - -

    -If you need a preempt-disable region to block grace periods, you need to add -rcu_read_lock() and rcu_read_unlock(), for example -as follows: - -

    -
    - 1 preempt_disable();
    - 2 rcu_read_lock();
    - 3 do_something();
    - 4 rcu_read_unlock();
    - 5 preempt_enable();
    - 6
    - 7 /* Spinlocks implicitly disable preemption. */
    - 8 spin_lock(&mylock);
    - 9 rcu_read_lock();
    -10 do_something();
    -11 rcu_read_unlock();
    -12 spin_unlock(&mylock);
    -
    -
    - -

    -In theory, you could enter the RCU read-side critical section first, -but it is more efficient to keep the entire RCU read-side critical -section contained in the preempt-disable region as shown above. -Of course, RCU read-side critical sections that extend outside of -preempt-disable regions will work correctly, but such critical sections -can be preempted, which forces rcu_read_unlock() to do -more work. -And no, this is not an invitation to enclose all of your RCU -read-side critical sections within preempt-disable regions, because -doing so would degrade real-time response. - -

    -This non-requirement appeared with preemptible RCU. -If you need a grace period that waits on non-preemptible code regions, use -RCU-sched. - -

    Parallelism Facts of Life

    - -

    -These parallelism facts of life are by no means specific to RCU, but -the RCU implementation must abide by them. -They therefore bear repeating: - -

      -
    1. Any CPU or task may be delayed at any time, - and any attempts to avoid these delays by disabling - preemption, interrupts, or whatever are completely futile. - This is most obvious in preemptible user-level - environments and in virtualized environments (where - a given guest OS's VCPUs can be preempted at any time by - the underlying hypervisor), but can also happen in bare-metal - environments due to ECC errors, NMIs, and other hardware - events. - Although a delay of more than about 20 seconds can result - in splats, the RCU implementation is obligated to use - algorithms that can tolerate extremely long delays, but where - “extremely long” is not long enough to allow - wrap-around when incrementing a 64-bit counter. -
    2. Both the compiler and the CPU can reorder memory accesses. - Where it matters, RCU must use compiler directives and - memory-barrier instructions to preserve ordering. -
    3. Conflicting writes to memory locations in any given cache line - will result in expensive cache misses. - Greater numbers of concurrent writes and more-frequent - concurrent writes will result in more dramatic slowdowns. - RCU is therefore obligated to use algorithms that have - sufficient locality to avoid significant performance and - scalability problems. -
    4. As a rough rule of thumb, only one CPU's worth of processing - may be carried out under the protection of any given exclusive - lock. - RCU must therefore use scalable locking designs. -
    5. Counters are finite, especially on 32-bit systems. - RCU's use of counters must therefore tolerate counter wrap, - or be designed such that counter wrap would take way more - time than a single system is likely to run. - An uptime of ten years is quite possible, a runtime - of a century much less so. - As an example of the latter, RCU's dyntick-idle nesting counter - allows 54 bits for interrupt nesting level (this counter - is 64 bits even on a 32-bit system). - Overflowing this counter requires 254 - half-interrupts on a given CPU without that CPU ever going idle. - If a half-interrupt happened every microsecond, it would take - 570 years of runtime to overflow this counter, which is currently - believed to be an acceptably long time. -
    6. Linux systems can have thousands of CPUs running a single - Linux kernel in a single shared-memory environment. - RCU must therefore pay close attention to high-end scalability. -
    - -

    -This last parallelism fact of life means that RCU must pay special -attention to the preceding facts of life. -The idea that Linux might scale to systems with thousands of CPUs would -have been met with some skepticism in the 1990s, but these requirements -would have otherwise have been unsurprising, even in the early 1990s. - -

    Quality-of-Implementation Requirements

    - -

    -These sections list quality-of-implementation requirements. -Although an RCU implementation that ignores these requirements could -still be used, it would likely be subject to limitations that would -make it inappropriate for industrial-strength production use. -Classes of quality-of-implementation requirements are as follows: - -

      -
    1. Specialization -
    2. Performance and Scalability -
    3. Composability -
    4. Corner Cases -
    - -

    -These classes is covered in the following sections. - -

    Specialization

    - -

    -RCU is and always has been intended primarily for read-mostly situations, -which means that RCU's read-side primitives are optimized, often at the -expense of its update-side primitives. -Experience thus far is captured by the following list of situations: - -

      -
    1. Read-mostly data, where stale and inconsistent data is not - a problem: RCU works great! -
    2. Read-mostly data, where data must be consistent: - RCU works well. -
    3. Read-write data, where data must be consistent: - RCU might work OK. - Or not. -
    4. Write-mostly data, where data must be consistent: - RCU is very unlikely to be the right tool for the job, - with the following exceptions, where RCU can provide: -
        -
      1. Existence guarantees for update-friendly mechanisms. -
      2. Wait-free read-side primitives for real-time use. -
      -
    - -

    -This focus on read-mostly situations means that RCU must interoperate -with other synchronization primitives. -For example, the add_gp() and remove_gp_synchronous() -examples discussed earlier use RCU to protect readers and locking to -coordinate updaters. -However, the need extends much farther, requiring that a variety of -synchronization primitives be legal within RCU read-side critical sections, -including spinlocks, sequence locks, atomic operations, reference -counters, and memory barriers. - -

    @@QQ@@ -What about sleeping locks? -

    @@QQA@@ -These are forbidden within Linux-kernel RCU read-side critical sections -because it is not legal to place a quiescent state (in this case, -voluntary context switch) within an RCU read-side critical section. -However, sleeping locks may be used within userspace RCU read-side critical -sections, and also within Linux-kernel sleepable RCU -(SRCU) -read-side critical sections. -In addition, the -rt patchset turns spinlocks into a sleeping locks so -that the corresponding critical sections can be preempted, which -also means that these sleeplockified spinlocks (but not other sleeping locks!) -may be acquire within -rt-Linux-kernel RCU read-side critical sections. - -

    -Note that it is legal for a normal RCU read-side critical section -to conditionally acquire a sleeping locks (as in mutex_trylock()), -but only as long as it does not loop indefinitely attempting to -conditionally acquire that sleeping locks. -The key point is that things like mutex_trylock() -either return with the mutex held, or return an error indication if -the mutex was not immediately available. -Either way, mutex_trylock() returns immediately without sleeping. -

    @@QQE@@ - -

    -It often comes as a surprise that many algorithms do not require a -consistent view of data, but many can function in that mode, -with network routing being the poster child. -Internet routing algorithms take significant time to propagate -updates, so that by the time an update arrives at a given system, -that system has been sending network traffic the wrong way for -a considerable length of time. -Having a few threads continue to send traffic the wrong way for a -few more milliseconds is clearly not a problem: In the worst case, -TCP retransmissions will eventually get the data where it needs to go. -In general, when tracking the state of the universe outside of the -computer, some level of inconsistency must be tolerated due to -speed-of-light delays if nothing else. - -

    -Furthermore, uncertainty about external state is inherent in many cases. -For example, a pair of veternarians might use heartbeat to determine -whether or not a given cat was alive. -But how long should they wait after the last heartbeat to decide that -the cat is in fact dead? -Waiting less than 400 milliseconds makes no sense because this would -mean that a relaxed cat would be considered to cycle between death -and life more than 100 times per minute. -Moreover, just as with human beings, a cat's heart might stop for -some period of time, so the exact wait period is a judgment call. -One of our pair of veternarians might wait 30 seconds before pronouncing -the cat dead, while the other might insist on waiting a full minute. -The two veternarians would then disagree on the state of the cat during -the final 30 seconds of the minute following the last heartbeat. - -

    -Interestingly enough, this same situation applies to hardware. -When push comes to shove, how do we tell whether or not some -external server has failed? -We send messages to it periodically, and declare it failed if we -don't receive a response within a given period of time. -Policy decisions can usually tolerate short -periods of inconsistency. -The policy was decided some time ago, and is only now being put into -effect, so a few milliseconds of delay is normally inconsequential. - -

    -However, there are algorithms that absolutely must see consistent data. -For example, the translation between a user-level SystemV semaphore -ID to the corresponding in-kernel data structure is protected by RCU, -but it is absolutely forbidden to update a semaphore that has just been -removed. -In the Linux kernel, this need for consistency is accommodated by acquiring -spinlocks located in the in-kernel data structure from within -the RCU read-side critical section, and this is indicated by the -green box in the figure above. -Many other techniques may be used, and are in fact used within the -Linux kernel. - -

    -In short, RCU is not required to maintain consistency, and other -mechanisms may be used in concert with RCU when consistency is required. -RCU's specialization allows it to do its job extremely well, and its -ability to interoperate with other synchronization mechanisms allows -the right mix of synchronization tools to be used for a given job. - -

    Performance and Scalability

    - -

    -Energy efficiency is a critical component of performance today, -and Linux-kernel RCU implementations must therefore avoid unnecessarily -awakening idle CPUs. -I cannot claim that this requirement was premeditated. -In fact, I learned of it during a telephone conversation in which I -was given “frank and open” feedback on the importance -of energy efficiency in battery-powered systems and on specific -energy-efficiency shortcomings of the Linux-kernel RCU implementation. -In my experience, the battery-powered embedded community will consider -any unnecessary wakeups to be extremely unfriendly acts. -So much so that mere Linux-kernel-mailing-list posts are -insufficient to vent their ire. - -

    -Memory consumption is not particularly important for in most -situations, and has become decreasingly -so as memory sizes have expanded and memory -costs have plummeted. -However, as I learned from Matt Mackall's -bloatwatch -efforts, memory footprint is critically important on single-CPU systems with -non-preemptible (CONFIG_PREEMPT=n) kernels, and thus -tiny RCU -was born. -Josh Triplett has since taken over the small-memory banner with his -Linux kernel tinification -project, which resulted in -SRCU -becoming optional for those kernels not needing it. - -

    -The remaining performance requirements are, for the most part, -unsurprising. -For example, in keeping with RCU's read-side specialization, -rcu_dereference() should have negligible overhead (for -example, suppression of a few minor compiler optimizations). -Similarly, in non-preemptible environments, rcu_read_lock() and -rcu_read_unlock() should have exactly zero overhead. - -

    -In preemptible environments, in the case where the RCU read-side -critical section was not preempted (as will be the case for the -highest-priority real-time process), rcu_read_lock() and -rcu_read_unlock() should have minimal overhead. -In particular, they should not contain atomic read-modify-write -operations, memory-barrier instructions, preemption disabling, -interrupt disabling, or backwards branches. -However, in the case where the RCU read-side critical section was preempted, -rcu_read_unlock() may acquire spinlocks and disable interrupts. -This is why it is better to nest an RCU read-side critical section -within a preempt-disable region than vice versa, at least in cases -where that critical section is short enough to avoid unduly degrading -real-time latencies. - -

    -The synchronize_rcu() grace-period-wait primitive is -optimized for throughput. -It may therefore incur several milliseconds of latency in addition to -the duration of the longest RCU read-side critical section. -On the other hand, multiple concurrent invocations of -synchronize_rcu() are required to use batching optimizations -so that they can be satisfied by a single underlying grace-period-wait -operation. -For example, in the Linux kernel, it is not unusual for a single -grace-period-wait operation to serve more than -1,000 separate invocations -of synchronize_rcu(), thus amortizing the per-invocation -overhead down to nearly zero. -However, the grace-period optimization is also required to avoid -measurable degradation of real-time scheduling and interrupt latencies. - -

    -In some cases, the multi-millisecond synchronize_rcu() -latencies are unacceptable. -In these cases, synchronize_rcu_expedited() may be used -instead, reducing the grace-period latency down to a few tens of -microseconds on small systems, at least in cases where the RCU read-side -critical sections are short. -There are currently no special latency requirements for -synchronize_rcu_expedited() on large systems, but, -consistent with the empirical nature of the RCU specification, -that is subject to change. -However, there most definitely are scalability requirements: -A storm of synchronize_rcu_expedited() invocations on 4096 -CPUs should at least make reasonable forward progress. -In return for its shorter latencies, synchronize_rcu_expedited() -is permitted to impose modest degradation of real-time latency -on non-idle online CPUs. -That said, it will likely be necessary to take further steps to reduce this -degradation, hopefully to roughly that of a scheduling-clock interrupt. - -

    -There are a number of situations where even -synchronize_rcu_expedited()'s reduced grace-period -latency is unacceptable. -In these situations, the asynchronous call_rcu() can be -used in place of synchronize_rcu() as follows: - -

    -
    - 1 struct foo {
    - 2   int a;
    - 3   int b;
    - 4   struct rcu_head rh;
    - 5 };
    - 6
    - 7 static void remove_gp_cb(struct rcu_head *rhp)
    - 8 {
    - 9   struct foo *p = container_of(rhp, struct foo, rh);
    -10
    -11   kfree(p);
    -12 }
    -13
    -14 bool remove_gp_asynchronous(void)
    -15 {
    -16   struct foo *p;
    -17
    -18   spin_lock(&gp_lock);
    -19   p = rcu_dereference(gp);
    -20   if (!p) {
    -21     spin_unlock(&gp_lock);
    -22     return false;
    -23   }
    -24   rcu_assign_pointer(gp, NULL);
    -25   call_rcu(&p->rh, remove_gp_cb);
    -26   spin_unlock(&gp_lock);
    -27   return true;
    -28 }
    -
    -
    - -

    -A definition of struct foo is finally needed, and appears -on lines 1-5. -The function remove_gp_cb() is passed to call_rcu() -on line 25, and will be invoked after the end of a subsequent -grace period. -This gets the same effect as remove_gp_synchronous(), -but without forcing the updater to wait for a grace period to elapse. -The call_rcu() function may be used in a number of -situations where neither synchronize_rcu() nor -synchronize_rcu_expedited() would be legal, -including within preempt-disable code, local_bh_disable() code, -interrupt-disable code, and interrupt handlers. -However, even call_rcu() is illegal within NMI handlers -and from offline CPUs. -The callback function (remove_gp_cb() in this case) will be -executed within softirq (software interrupt) environment within the -Linux kernel, -either within a real softirq handler or under the protection -of local_bh_disable(). -In both the Linux kernel and in userspace, it is bad practice to -write an RCU callback function that takes too long. -Long-running operations should be relegated to separate threads or -(in the Linux kernel) workqueues. - -

    @@QQ@@ -Why does line 19 use rcu_access_pointer()? -After all, call_rcu() on line 25 stores into the -structure, which would interact badly with concurrent insertions. -Doesn't this mean that rcu_dereference() is required? -

    @@QQA@@ -Presumably the ->gp_lock acquired on line 18 excludes -any changes, including any insertions that rcu_dereference() -would protect against. -Therefore, any insertions will be delayed until after ->gp_lock -is released on line 25, which in turn means that -rcu_access_pointer() suffices. -

    @@QQE@@ - -

    -However, all that remove_gp_cb() is doing is -invoking kfree() on the data element. -This is a common idiom, and is supported by kfree_rcu(), -which allows “fire and forget” operation as shown below: - -

    -
    - 1 struct foo {
    - 2   int a;
    - 3   int b;
    - 4   struct rcu_head rh;
    - 5 };
    - 6
    - 7 bool remove_gp_faf(void)
    - 8 {
    - 9   struct foo *p;
    -10
    -11   spin_lock(&gp_lock);
    -12   p = rcu_dereference(gp);
    -13   if (!p) {
    -14     spin_unlock(&gp_lock);
    -15     return false;
    -16   }
    -17   rcu_assign_pointer(gp, NULL);
    -18   kfree_rcu(p, rh);
    -19   spin_unlock(&gp_lock);
    -20   return true;
    -21 }
    -
    -
    - -

    -Note that remove_gp_faf() simply invokes -kfree_rcu() and proceeds, without any need to pay any -further attention to the subsequent grace period and kfree(). -It is permissible to invoke kfree_rcu() from the same -environments as for call_rcu(). -Interestingly enough, DYNIX/ptx had the equivalents of -call_rcu() and kfree_rcu(), but not -synchronize_rcu(). -This was due to the fact that RCU was not heavily used within DYNIX/ptx, -so the very few places that needed something like -synchronize_rcu() simply open-coded it. - -

    @@QQ@@ -Earlier it was claimed that call_rcu() and -kfree_rcu() allowed updaters to avoid being blocked -by readers. -But how can that be correct, given that the invocation of the callback -and the freeing of the memory (respectively) must still wait for -a grace period to elapse? -

    @@QQA@@ -We could define things this way, but keep in mind that this sort of -definition would say that updates in garbage-collected languages -cannot complete until the next time the garbage collector runs, -which does not seem at all reasonable. -The key point is that in most cases, an updater using either -call_rcu() or kfree_rcu() can proceed to the -next update as soon as it has invoked call_rcu() or -kfree_rcu(), without having to wait for a subsequent -grace period. -

    @@QQE@@ - -

    -But what if the updater must wait for the completion of code to be -executed after the end of the grace period, but has other tasks -that can be carried out in the meantime? -The polling-style get_state_synchronize_rcu() and -cond_synchronize_rcu() functions may be used for this -purpose, as shown below: - -

    -
    - 1 bool remove_gp_poll(void)
    - 2 {
    - 3   struct foo *p;
    - 4   unsigned long s;
    - 5
    - 6   spin_lock(&gp_lock);
    - 7   p = rcu_access_pointer(gp);
    - 8   if (!p) {
    - 9     spin_unlock(&gp_lock);
    -10     return false;
    -11   }
    -12   rcu_assign_pointer(gp, NULL);
    -13   spin_unlock(&gp_lock);
    -14   s = get_state_synchronize_rcu();
    -15   do_something_while_waiting();
    -16   cond_synchronize_rcu(s);
    -17   kfree(p);
    -18   return true;
    -19 }
    -
    -
    - -

    -On line 14, get_state_synchronize_rcu() obtains a -“cookie” from RCU, -then line 15 carries out other tasks, -and finally, line 16 returns immediately if a grace period has -elapsed in the meantime, but otherwise waits as required. -The need for get_state_synchronize_rcu and -cond_synchronize_rcu() has appeared quite recently, -so it is too early to tell whether they will stand the test of time. - -

    -RCU thus provides a range of tools to allow updaters to strike the -required tradeoff between latency, flexibility and CPU overhead. - -

    Composability

    - -

    -Composability has received much attention in recent years, perhaps in part -due to the collision of multicore hardware with object-oriented techniques -designed in single-threaded environments for single-threaded use. -And in theory, RCU read-side critical sections may be composed, and in -fact may be nested arbitrarily deeply. -In practice, as with all real-world implementations of composable -constructs, there are limitations. - -

    -Implementations of RCU for which rcu_read_lock() -and rcu_read_unlock() generate no code, such as -Linux-kernel RCU when CONFIG_PREEMPT=n, can be -nested arbitrarily deeply. -After all, there is no overhead. -Except that if all these instances of rcu_read_lock() -and rcu_read_unlock() are visible to the compiler, -compilation will eventually fail due to exhausting memory, -mass storage, or user patience, whichever comes first. -If the nesting is not visible to the compiler, as is the case with -mutually recursive functions each in its own translation unit, -stack overflow will result. -If the nesting takes the form of loops, either the control variable -will overflow or (in the Linux kernel) you will get an RCU CPU stall warning. -Nevertheless, this class of RCU implementations is one -of the most composable constructs in existence. - -

    -RCU implementations that explicitly track nesting depth -are limited by the nesting-depth counter. -For example, the Linux kernel's preemptible RCU limits nesting to -INT_MAX. -This should suffice for almost all practical purposes. -That said, a consecutive pair of RCU read-side critical sections -between which there is an operation that waits for a grace period -cannot be enclosed in another RCU read-side critical section. -This is because it is not legal to wait for a grace period within -an RCU read-side critical section: To do so would result either -in deadlock or -in RCU implicitly splitting the enclosing RCU read-side critical -section, neither of which is conducive to a long-lived and prosperous -kernel. - -

    -It is worth noting that RCU is not alone in limiting composability. -For example, many transactional-memory implementations prohibit -composing a pair of transactions separated by an irrevocable -operation (for example, a network receive operation). -For another example, lock-based critical sections can be composed -surprisingly freely, but only if deadlock is avoided. - -

    -In short, although RCU read-side critical sections are highly composable, -care is required in some situations, just as is the case for any other -composable synchronization mechanism. - -

    Corner Cases

    - -

    -A given RCU workload might have an endless and intense stream of -RCU read-side critical sections, perhaps even so intense that there -was never a point in time during which there was not at least one -RCU read-side critical section in flight. -RCU cannot allow this situation to block grace periods: As long as -all the RCU read-side critical sections are finite, grace periods -must also be finite. - -

    -That said, preemptible RCU implementations could potentially result -in RCU read-side critical sections being preempted for long durations, -which has the effect of creating a long-duration RCU read-side -critical section. -This situation can arise only in heavily loaded systems, but systems using -real-time priorities are of course more vulnerable. -Therefore, RCU priority boosting is provided to help deal with this -case. -That said, the exact requirements on RCU priority boosting will likely -evolve as more experience accumulates. - -

    -Other workloads might have very high update rates. -Although one can argue that such workloads should instead use -something other than RCU, the fact remains that RCU must -handle such workloads gracefully. -This requirement is another factor driving batching of grace periods, -but it is also the driving force behind the checks for large numbers -of queued RCU callbacks in the call_rcu() code path. -Finally, high update rates should not delay RCU read-side critical -sections, although some read-side delays can occur when using -synchronize_rcu_expedited(), courtesy of this function's use -of try_stop_cpus(). -(In the future, synchronize_rcu_expedited() will be -converted to use lighter-weight inter-processor interrupts (IPIs), -but this will still disturb readers, though to a much smaller degree.) - -

    -Although all three of these corner cases were understood in the early -1990s, a simple user-level test consisting of close(open(path)) -in a tight loop -in the early 2000s suddenly provided a much deeper appreciation of the -high-update-rate corner case. -This test also motivated addition of some RCU code to react to high update -rates, for example, if a given CPU finds itself with more than 10,000 -RCU callbacks queued, it will cause RCU to take evasive action by -more aggressively starting grace periods and more aggressively forcing -completion of grace-period processing. -This evasive action causes the grace period to complete more quickly, -but at the cost of restricting RCU's batching optimizations, thus -increasing the CPU overhead incurred by that grace period. - -

    -Software-Engineering Requirements

    - -

    -Between Murphy's Law and “To err is human”, it is necessary to -guard against mishaps and misuse: - -

      -
    1. It is all too easy to forget to use rcu_read_lock() - everywhere that it is needed, so kernels built with - CONFIG_PROVE_RCU=y will spat if - rcu_dereference() is used outside of an - RCU read-side critical section. - Update-side code can use rcu_dereference_protected(), - which takes a - lockdep expression - to indicate what is providing the protection. - If the indicated protection is not provided, a lockdep splat - is emitted. - -

      - Code shared between readers and updaters can use - rcu_dereference_check(), which also takes a - lockdep expression, and emits a lockdep splat if neither - rcu_read_lock() nor the indicated protection - is in place. - In addition, rcu_dereference_raw() is used in those - (hopefully rare) cases where the required protection cannot - be easily described. - Finally, rcu_read_lock_held() is provided to - allow a function to verify that it has been invoked within - an RCU read-side critical section. - I was made aware of this set of requirements shortly after Thomas - Gleixner audited a number of RCU uses. -

    2. A given function might wish to check for RCU-related preconditions - upon entry, before using any other RCU API. - The rcu_lockdep_assert() does this job, - asserting the expression in kernels having lockdep enabled - and doing nothing otherwise. -
    3. It is also easy to forget to use rcu_assign_pointer() - and rcu_dereference(), perhaps (incorrectly) - substituting a simple assignment. - To catch this sort of error, a given RCU-protected pointer may be - tagged with __rcu, after which running sparse - with CONFIG_SPARSE_RCU_POINTER=y will complain - about simple-assignment accesses to that pointer. - Arnd Bergmann made me aware of this requirement, and also - supplied the needed - patch series. -
    4. Kernels built with CONFIG_DEBUG_OBJECTS_RCU_HEAD=y - will splat if a data element is passed to call_rcu() - twice in a row, without a grace period in between. - (This error is similar to a double free.) - The corresponding rcu_head structures that are - dynamically allocated are automatically tracked, but - rcu_head structures allocated on the stack - must be initialized with init_rcu_head_on_stack() - and cleaned up with destroy_rcu_head_on_stack(). - Similarly, statically allocated non-stack rcu_head - structures must be initialized with init_rcu_head() - and cleaned up with destroy_rcu_head(). - Mathieu Desnoyers made me aware of this requirement, and also - supplied the needed - patch. -
    5. An infinite loop in an RCU read-side critical section will - eventually trigger an RCU CPU stall warning splat, with - the duration of “eventually” being controlled by the - RCU_CPU_STALL_TIMEOUT Kconfig option, or, - alternatively, by the - rcupdate.rcu_cpu_stall_timeout boot/sysfs - parameter. - However, RCU is not obligated to produce this splat - unless there is a grace period waiting on that particular - RCU read-side critical section. -

      - Some extreme workloads might intentionally delay - RCU grace periods, and systems running those workloads can - be booted with rcupdate.rcu_cpu_stall_suppress - to suppress the splats. - This kernel parameter may also be set via sysfs. - Furthermore, RCU CPU stall warnings are counter-productive - during sysrq dumps and during panics. - RCU therefore supplies the rcu_sysrq_start() and - rcu_sysrq_end() API members to be called before - and after long sysrq dumps. - RCU also supplies the rcu_panic() notifier that is - automatically invoked at the beginning of a panic to suppress - further RCU CPU stall warnings. - -

      - This requirement made itself known in the early 1990s, pretty - much the first time that it was necessary to debug a CPU stall. - That said, the initial implementation in DYNIX/ptx was quite - generic in comparison with that of Linux. -

    6. Although it would be very good to detect pointers leaking out - of RCU read-side critical sections, there is currently no - good way of doing this. - One complication is the need to distinguish between pointers - leaking and pointers that have been handed off from RCU to - some other synchronization mechanism, for example, reference - counting. -
    7. In kernels built with CONFIG_RCU_TRACE=y, RCU-related - information is provided via both debugfs and event tracing. -
    8. Open-coded use of rcu_assign_pointer() and - rcu_dereference() to create typical linked - data structures can be surprisingly error-prone. - Therefore, RCU-protected - linked lists - and, more recently, RCU-protected - hash tables - are available. - Many other special-purpose RCU-protected data structures are - available in the Linux kernel and the userspace RCU library. -
    9. Some linked structures are created at compile time, but still - require __rcu checking. - The RCU_POINTER_INITIALIZER() macro serves this - purpose. -
    10. It is not necessary to use rcu_assign_pointer() - when creating linked structures that are to be published via - a single external pointer. - The RCU_INIT_POINTER() macro is provided for - this task and also for assigning NULL pointers - at runtime. -
    - -

    -This not a hard-and-fast list: RCU's diagnostic capabilities will -continue to be guided by the number and type of usage bugs found -in real-world RCU usage. - -

    Linux Kernel Complications

    - -

    -The Linux kernel provides an interesting environment for all kinds of -software, including RCU. -Some of the relevant points of interest are as follows: - -

      -
    1. Configuration. -
    2. Firmware Interface. -
    3. Early Boot. -
    4. - Interrupts and non-maskable interrupts (NMIs). -
    5. Loadable Modules. -
    6. Hotplug CPU. -
    7. Scheduler and RCU. -
    8. Tracing and RCU. -
    9. Energy Efficiency. -
    10. Memory Efficiency. -
    11. - Performance, Scalability, Response Time, and Reliability. -
    - -

    -This list is probably incomplete, but it does give a feel for the -most notable Linux-kernel complications. -Each of the following sections covers one of the above topics. - -

    Configuration

    - -

    -RCU's goal is automatic configuration, so that almost nobody -needs to worry about RCU's Kconfig options. -And for almost all users, RCU does in fact work well -“out of the box.” - -

    -However, there are specialized use cases that are handled by -kernel boot parameters and Kconfig options. -Unfortunately, the Kconfig system will explicitly ask users -about new Kconfig options, which requires almost all of them -be hidden behind a CONFIG_RCU_EXPERT Kconfig option. - -

    -This all should be quite obvious, but the fact remains that -Linus Torvalds recently had to -remind -me of this requirement. - -

    Firmware Interface

    - -

    -In many cases, kernel obtains information about the system from the -firmware, and sometimes things are lost in translation. -Or the translation is accurate, but the original message is bogus. - -

    -For example, some systems' firmware overreports the number of CPUs, -sometimes by a large factor. -If RCU naively believed the firmware, as it used to do, -it would create too many per-CPU kthreads. -Although the resulting system will still run correctly, the extra -kthreads needlessly consume memory and can cause confusion -when they show up in ps listings. - -

    -RCU must therefore wait for a given CPU to actually come online before -it can allow itself to believe that the CPU actually exists. -The resulting “ghost CPUs” (which are never going to -come online) cause a number of -interesting complications. - -

    Early Boot

    - -

    -The Linux kernel's boot sequence is an interesting process, -and RCU is used early, even before rcu_init() -is invoked. -In fact, a number of RCU's primitives can be used as soon as the -initial task's task_struct is available and the -boot CPU's per-CPU variables are set up. -The read-side primitives (rcu_read_lock(), -rcu_read_unlock(), rcu_dereference(), -and rcu_access_pointer()) will operate normally very early on, -as will rcu_assign_pointer(). - -

    -Although call_rcu() may be invoked at any -time during boot, callbacks are not guaranteed to be invoked until after -the scheduler is fully up and running. -This delay in callback invocation is due to the fact that RCU does not -invoke callbacks until it is fully initialized, and this full initialization -cannot occur until after the scheduler has initialized itself to the -point where RCU can spawn and run its kthreads. -In theory, it would be possible to invoke callbacks earlier, -however, this is not a panacea because there would be severe restrictions -on what operations those callbacks could invoke. - -

    -Perhaps surprisingly, synchronize_rcu(), -synchronize_rcu_bh() -(discussed below), -and -synchronize_sched() -will all operate normally -during very early boot, the reason being that there is only one CPU -and preemption is disabled. -This means that the call synchronize_rcu() (or friends) -itself is a quiescent -state and thus a grace period, so the early-boot implementation can -be a no-op. - -

    -Both synchronize_rcu_bh() and synchronize_sched() -continue to operate normally through the remainder of boot, courtesy -of the fact that preemption is disabled across their RCU read-side -critical sections and also courtesy of the fact that there is still -only one CPU. -However, once the scheduler starts initializing, preemption is enabled. -There is still only a single CPU, but the fact that preemption is enabled -means that the no-op implementation of synchronize_rcu() no -longer works in CONFIG_PREEMPT=y kernels. -Therefore, as soon as the scheduler starts initializing, the early-boot -fastpath is disabled. -This means that synchronize_rcu() switches to its runtime -mode of operation where it posts callbacks, which in turn means that -any call to synchronize_rcu() will block until the corresponding -callback is invoked. -Unfortunately, the callback cannot be invoked until RCU's runtime -grace-period machinery is up and running, which cannot happen until -the scheduler has initialized itself sufficiently to allow RCU's -kthreads to be spawned. -Therefore, invoking synchronize_rcu() during scheduler -initialization can result in deadlock. - -

    @@QQ@@ -So what happens with synchronize_rcu() during -scheduler initialization for CONFIG_PREEMPT=n -kernels? -

    @@QQA@@ -In CONFIG_PREEMPT=n kernel, synchronize_rcu() -maps directly to synchronize_sched(). -Therefore, synchronize_rcu() works normally throughout -boot in CONFIG_PREEMPT=n kernels. -However, your code must also work in CONFIG_PREEMPT=y kernels, -so it is still necessary to avoid invoking synchronize_rcu() -during scheduler initialization. -

    @@QQE@@ - -

    -I learned of these boot-time requirements as a result of a series of -system hangs. - -

    Interrupts and NMIs

    - -

    -The Linux kernel has interrupts, and RCU read-side critical sections are -legal within interrupt handlers and within interrupt-disabled regions -of code, as are invocations of call_rcu(). - -

    -Some Linux-kernel architectures can enter an interrupt handler from -non-idle process context, and then just never leave it, instead stealthily -transitioning back to process context. -This trick is sometimes used to invoke system calls from inside the kernel. -These “half-interrupts” mean that RCU has to be very careful -about how it counts interrupt nesting levels. -I learned of this requirement the hard way during a rewrite -of RCU's dyntick-idle code. - -

    -The Linux kernel has non-maskable interrupts (NMIs), and -RCU read-side critical sections are legal within NMI handlers. -Thankfully, RCU update-side primitives, including -call_rcu(), are prohibited within NMI handlers. - -

    -The name notwithstanding, some Linux-kernel architectures -can have nested NMIs, which RCU must handle correctly. -Andy Lutomirski -surprised me -with this requirement; -he also kindly surprised me with -an algorithm -that meets this requirement. - -

    Loadable Modules

    - -

    -The Linux kernel has loadable modules, and these modules can -also be unloaded. -After a given module has been unloaded, any attempt to call -one of its functions results in a segmentation fault. -The module-unload functions must therefore cancel any -delayed calls to loadable-module functions, for example, -any outstanding mod_timer() must be dealt with -via del_timer_sync() or similar. - -

    -Unfortunately, there is no way to cancel an RCU callback; -once you invoke call_rcu(), the callback function is -going to eventually be invoked, unless the system goes down first. -Because it is normally considered socially irresponsible to crash the system -in response to a module unload request, we need some other way -to deal with in-flight RCU callbacks. - -

    -RCU therefore provides -rcu_barrier(), -which waits until all in-flight RCU callbacks have been invoked. -If a module uses call_rcu(), its exit function should therefore -prevent any future invocation of call_rcu(), then invoke -rcu_barrier(). -In theory, the underlying module-unload code could invoke -rcu_barrier() unconditionally, but in practice this would -incur unacceptable latencies. - -

    -Nikita Danilov noted this requirement for an analogous filesystem-unmount -situation, and Dipankar Sarma incorporated rcu_barrier() into RCU. -The need for rcu_barrier() for module unloading became -apparent later. - -

    Hotplug CPU

    - -

    -The Linux kernel supports CPU hotplug, which means that CPUs -can come and go. -It is of course illegal to use any RCU API member from an offline CPU. -This requirement was present from day one in DYNIX/ptx, but -on the other hand, the Linux kernel's CPU-hotplug implementation -is “interesting.” - -

    -The Linux-kernel CPU-hotplug implementation has notifiers that -are used to allow the various kernel subsystems (including RCU) -to respond appropriately to a given CPU-hotplug operation. -Most RCU operations may be invoked from CPU-hotplug notifiers, -including even normal synchronous grace-period operations -such as synchronize_rcu(). -However, expedited grace-period operations such as -synchronize_rcu_expedited() are not supported, -due to the fact that current implementations block CPU-hotplug -operations, which could result in deadlock. - -

    -In addition, all-callback-wait operations such as -rcu_barrier() are also not supported, due to the -fact that there are phases of CPU-hotplug operations where -the outgoing CPU's callbacks will not be invoked until after -the CPU-hotplug operation ends, which could also result in deadlock. - -

    Scheduler and RCU

    - -

    -RCU depends on the scheduler, and the scheduler uses RCU to -protect some of its data structures. -This means the scheduler is forbidden from acquiring -the runqueue locks and the priority-inheritance locks -in the middle of an outermost RCU read-side critical section unless either -(1) it releases them before exiting that same -RCU read-side critical section, or -(2) interrupts are disabled across -that entire RCU read-side critical section. -This same prohibition also applies (recursively!) to any lock that is acquired -while holding any lock to which this prohibition applies. -Adhering to this rule prevents preemptible RCU from invoking -rcu_read_unlock_special() while either runqueue or -priority-inheritance locks are held, thus avoiding deadlock. - -

    -Prior to v4.4, it was only necessary to disable preemption across -RCU read-side critical sections that acquired scheduler locks. -In v4.4, expedited grace periods started using IPIs, and these -IPIs could force a rcu_read_unlock() to take the slowpath. -Therefore, this expedited-grace-period change required disabling of -interrupts, not just preemption. - -

    -For RCU's part, the preemptible-RCU rcu_read_unlock() -implementation must be written carefully to avoid similar deadlocks. -In particular, rcu_read_unlock() must tolerate an -interrupt where the interrupt handler invokes both -rcu_read_lock() and rcu_read_unlock(). -This possibility requires rcu_read_unlock() to use -negative nesting levels to avoid destructive recursion via -interrupt handler's use of RCU. - -

    -This pair of mutual scheduler-RCU requirements came as a -complete surprise. - -

    -As noted above, RCU makes use of kthreads, and it is necessary to -avoid excessive CPU-time accumulation by these kthreads. -This requirement was no surprise, but RCU's violation of it -when running context-switch-heavy workloads when built with -CONFIG_NO_HZ_FULL=y -did come as a surprise [PDF]. -RCU has made good progress towards meeting this requirement, even -for context-switch-have CONFIG_NO_HZ_FULL=y workloads, -but there is room for further improvement. - -

    Tracing and RCU

    - -

    -It is possible to use tracing on RCU code, but tracing itself -uses RCU. -For this reason, rcu_dereference_raw_notrace() -is provided for use by tracing, which avoids the destructive -recursion that could otherwise ensue. -This API is also used by virtualization in some architectures, -where RCU readers execute in environments in which tracing -cannot be used. -The tracing folks both located the requirement and provided the -needed fix, so this surprise requirement was relatively painless. - -

    Energy Efficiency

    - -

    -Interrupting idle CPUs is considered socially unacceptable, -especially by people with battery-powered embedded systems. -RCU therefore conserves energy by detecting which CPUs are -idle, including tracking CPUs that have been interrupted from idle. -This is a large part of the energy-efficiency requirement, -so I learned of this via an irate phone call. - -

    -Because RCU avoids interrupting idle CPUs, it is illegal to -execute an RCU read-side critical section on an idle CPU. -(Kernels built with CONFIG_PROVE_RCU=y will splat -if you try it.) -The RCU_NONIDLE() macro and _rcuidle -event tracing is provided to work around this restriction. -In addition, rcu_is_watching() may be used to -test whether or not it is currently legal to run RCU read-side -critical sections on this CPU. -I learned of the need for diagnostics on the one hand -and RCU_NONIDLE() on the other while inspecting -idle-loop code. -Steven Rostedt supplied _rcuidle event tracing, -which is used quite heavily in the idle loop. - -

    -It is similarly socially unacceptable to interrupt an -nohz_full CPU running in userspace. -RCU must therefore track nohz_full userspace -execution. -And in -CONFIG_NO_HZ_FULL_SYSIDLE=y -kernels, RCU must separately track idle CPUs on the one hand and -CPUs that are either idle or executing in userspace on the other. -In both cases, RCU must be able to sample state at two points in -time, and be able to determine whether or not some other CPU spent -any time idle and/or executing in userspace. - -

    -These energy-efficiency requirements have proven quite difficult to -understand and to meet, for example, there have been more than five -clean-sheet rewrites of RCU's energy-efficiency code, the last of -which was finally able to demonstrate -real energy savings running on real hardware [PDF]. -As noted earlier, -I learned of many of these requirements via angry phone calls: -Flaming me on the Linux-kernel mailing list was apparently not -sufficient to fully vent their ire at RCU's energy-efficiency bugs! - -

    Memory Efficiency

    - -

    -Although small-memory non-realtime systems can simply use Tiny RCU, -code size is only one aspect of memory efficiency. -Another aspect is the size of the rcu_head structure -used by call_rcu() and kfree_rcu(). -Although this structure contains nothing more than a pair of pointers, -it does appear in many RCU-protected data structures, including -some that are size critical. -The page structure is a case in point, as evidenced by -the many occurrences of the union keyword within that structure. - -

    -This need for memory efficiency is one reason that RCU uses hand-crafted -singly linked lists to track the rcu_head structures that -are waiting for a grace period to elapse. -It is also the reason why rcu_head structures do not contain -debug information, such as fields tracking the file and line of the -call_rcu() or kfree_rcu() that posted them. -Although this information might appear in debug-only kernel builds at some -point, in the meantime, the ->func field will often provide -the needed debug information. - -

    -However, in some cases, the need for memory efficiency leads to even -more extreme measures. -Returning to the page structure, the rcu_head field -shares storage with a great many other structures that are used at -various points in the corresponding page's lifetime. -In order to correctly resolve certain -race conditions, -the Linux kernel's memory-management subsystem needs a particular bit -to remain zero during all phases of grace-period processing, -and that bit happens to map to the bottom bit of the -rcu_head structure's ->next field. -RCU makes this guarantee as long as call_rcu() -is used to post the callback, as opposed to kfree_rcu() -or some future “lazy” -variant of call_rcu() that might one day be created for -energy-efficiency purposes. - -

    -Performance, Scalability, Response Time, and Reliability

    - -

    -Expanding on the -earlier discussion, -RCU is used heavily by hot code paths in performance-critical -portions of the Linux kernel's networking, security, virtualization, -and scheduling code paths. -RCU must therefore use efficient implementations, especially in its -read-side primitives. -To that end, it would be good if preemptible RCU's implementation -of rcu_read_lock() could be inlined, however, doing -this requires resolving #include issues with the -task_struct structure. - -

    -The Linux kernel supports hardware configurations with up to -4096 CPUs, which means that RCU must be extremely scalable. -Algorithms that involve frequent acquisitions of global locks or -frequent atomic operations on global variables simply cannot be -tolerated within the RCU implementation. -RCU therefore makes heavy use of a combining tree based on the -rcu_node structure. -RCU is required to tolerate all CPUs continuously invoking any -combination of RCU's runtime primitives with minimal per-operation -overhead. -In fact, in many cases, increasing load must decrease the -per-operation overhead, witness the batching optimizations for -synchronize_rcu(), call_rcu(), -synchronize_rcu_expedited(), and rcu_barrier(). -As a general rule, RCU must cheerfully accept whatever the -rest of the Linux kernel decides to throw at it. - -

    -The Linux kernel is used for real-time workloads, especially -in conjunction with the --rt patchset. -The real-time-latency response requirements are such that the -traditional approach of disabling preemption across RCU -read-side critical sections is inappropriate. -Kernels built with CONFIG_PREEMPT=y therefore -use an RCU implementation that allows RCU read-side critical -sections to be preempted. -This requirement made its presence known after users made it -clear that an earlier -real-time patch -did not meet their needs, in conjunction with some -RCU issues -encountered by a very early version of the -rt patchset. - -

    -In addition, RCU must make do with a sub-100-microsecond real-time latency -budget. -In fact, on smaller systems with the -rt patchset, the Linux kernel -provides sub-20-microsecond real-time latencies for the whole kernel, -including RCU. -RCU's scalability and latency must therefore be sufficient for -these sorts of configurations. -To my surprise, the sub-100-microsecond real-time latency budget - -applies to even the largest systems [PDF], -up to and including systems with 4096 CPUs. -This real-time requirement motivated the grace-period kthread, which -also simplified handling of a number of race conditions. - -

    -RCU must avoid degrading real-time response for CPU-bound threads, whether -executing in usermode (which is one use case for -CONFIG_NO_HZ_FULL=y) or in the kernel. -That said, CPU-bound loops in the kernel must execute -cond_resched_rcu_qs() at least once per few tens of milliseconds -in order to avoid receiving an IPI from RCU. - -

    -Finally, RCU's status as a synchronization primitive means that -any RCU failure can result in arbitrary memory corruption that can be -extremely difficult to debug. -This means that RCU must be extremely reliable, which in -practice also means that RCU must have an aggressive stress-test -suite. -This stress-test suite is called rcutorture. - -

    -Although the need for rcutorture was no surprise, -the current immense popularity of the Linux kernel is posing -interesting—and perhaps unprecedented—validation -challenges. -To see this, keep in mind that there are well over one billion -instances of the Linux kernel running today, given Android -smartphones, Linux-powered televisions, and servers. -This number can be expected to increase sharply with the advent of -the celebrated Internet of Things. - -

    -Suppose that RCU contains a race condition that manifests on average -once per million years of runtime. -This bug will be occurring about three times per day across -the installed base. -RCU could simply hide behind hardware error rates, given that no one -should really expect their smartphone to last for a million years. -However, anyone taking too much comfort from this thought should -consider the fact that in most jurisdictions, a successful multi-year -test of a given mechanism, which might include a Linux kernel, -suffices for a number of types of safety-critical certifications. -In fact, rumor has it that the Linux kernel is already being used -in production for safety-critical applications. -I don't know about you, but I would feel quite bad if a bug in RCU -killed someone. -Which might explain my recent focus on validation and verification. - -

    Other RCU Flavors

    - -

    -One of the more surprising things about RCU is that there are now -no fewer than five flavors, or API families. -In addition, the primary flavor that has been the sole focus up to -this point has two different implementations, non-preemptible and -preemptible. -The other four flavors are listed below, with requirements for each -described in a separate section. - -

      -
    1. Bottom-Half Flavor -
    2. Sched Flavor -
    3. Sleepable RCU -
    4. Tasks RCU -
    5. - Waiting for Multiple Grace Periods -
    - -

    Bottom-Half Flavor

    - -

    -The softirq-disable (AKA “bottom-half”, -hence the “_bh” abbreviations) -flavor of RCU, or RCU-bh, was developed by -Dipankar Sarma to provide a flavor of RCU that could withstand the -network-based denial-of-service attacks researched by Robert -Olsson. -These attacks placed so much networking load on the system -that some of the CPUs never exited softirq execution, -which in turn prevented those CPUs from ever executing a context switch, -which, in the RCU implementation of that time, prevented grace periods -from ever ending. -The result was an out-of-memory condition and a system hang. - -

    -The solution was the creation of RCU-bh, which does -local_bh_disable() -across its read-side critical sections, and which uses the transition -from one type of softirq processing to another as a quiescent state -in addition to context switch, idle, user mode, and offline. -This means that RCU-bh grace periods can complete even when some of -the CPUs execute in softirq indefinitely, thus allowing algorithms -based on RCU-bh to withstand network-based denial-of-service attacks. - -

    -Because -rcu_read_lock_bh() and rcu_read_unlock_bh() -disable and re-enable softirq handlers, any attempt to start a softirq -handlers during the -RCU-bh read-side critical section will be deferred. -In this case, rcu_read_unlock_bh() -will invoke softirq processing, which can take considerable time. -One can of course argue that this softirq overhead should be associated -with the code following the RCU-bh read-side critical section rather -than rcu_read_unlock_bh(), but the fact -is that most profiling tools cannot be expected to make this sort -of fine distinction. -For example, suppose that a three-millisecond-long RCU-bh read-side -critical section executes during a time of heavy networking load. -There will very likely be an attempt to invoke at least one softirq -handler during that three milliseconds, but any such invocation will -be delayed until the time of the rcu_read_unlock_bh(). -This can of course make it appear at first glance as if -rcu_read_unlock_bh() was executing very slowly. - -

    -The -RCU-bh API -includes -rcu_read_lock_bh(), -rcu_read_unlock_bh(), -rcu_dereference_bh(), -rcu_dereference_bh_check(), -synchronize_rcu_bh(), -synchronize_rcu_bh_expedited(), -call_rcu_bh(), -rcu_barrier_bh(), and -rcu_read_lock_bh_held(). - -

    Sched Flavor

    - -

    -Before preemptible RCU, waiting for an RCU grace period had the -side effect of also waiting for all pre-existing interrupt -and NMI handlers. -However, there are legitimate preemptible-RCU implementations that -do not have this property, given that any point in the code outside -of an RCU read-side critical section can be a quiescent state. -Therefore, RCU-sched was created, which follows “classic” -RCU in that an RCU-sched grace period waits for for pre-existing -interrupt and NMI handlers. -In kernels built with CONFIG_PREEMPT=n, the RCU and RCU-sched -APIs have identical implementations, while kernels built with -CONFIG_PREEMPT=y provide a separate implementation for each. - -

    -Note well that in CONFIG_PREEMPT=y kernels, -rcu_read_lock_sched() and rcu_read_unlock_sched() -disable and re-enable preemption, respectively. -This means that if there was a preemption attempt during the -RCU-sched read-side critical section, rcu_read_unlock_sched() -will enter the scheduler, with all the latency and overhead entailed. -Just as with rcu_read_unlock_bh(), this can make it look -as if rcu_read_unlock_sched() was executing very slowly. -However, the highest-priority task won't be preempted, so that task -will enjoy low-overhead rcu_read_unlock_sched() invocations. - -

    -The -RCU-sched API -includes -rcu_read_lock_sched(), -rcu_read_unlock_sched(), -rcu_read_lock_sched_notrace(), -rcu_read_unlock_sched_notrace(), -rcu_dereference_sched(), -rcu_dereference_sched_check(), -synchronize_sched(), -synchronize_rcu_sched_expedited(), -call_rcu_sched(), -rcu_barrier_sched(), and -rcu_read_lock_sched_held(). -However, anything that disables preemption also marks an RCU-sched -read-side critical section, including -preempt_disable() and preempt_enable(), -local_irq_save() and local_irq_restore(), -and so on. - -

    Sleepable RCU

    - -

    -For well over a decade, someone saying “I need to block within -an RCU read-side critical section” was a reliable indication -that this someone did not understand RCU. -After all, if you are always blocking in an RCU read-side critical -section, you can probably afford to use a higher-overhead synchronization -mechanism. -However, that changed with the advent of the Linux kernel's notifiers, -whose RCU read-side critical -sections almost never sleep, but sometimes need to. -This resulted in the introduction of -sleepable RCU, -or SRCU. - -

    -SRCU allows different domains to be defined, with each such domain -defined by an instance of an srcu_struct structure. -A pointer to this structure must be passed in to each SRCU function, -for example, synchronize_srcu(&ss), where -ss is the srcu_struct structure. -The key benefit of these domains is that a slow SRCU reader in one -domain does not delay an SRCU grace period in some other domain. -That said, one consequence of these domains is that read-side code -must pass a “cookie” from srcu_read_lock() -to srcu_read_unlock(), for example, as follows: - -

    -
    - 1 int idx;
    - 2
    - 3 idx = srcu_read_lock(&ss);
    - 4 do_something();
    - 5 srcu_read_unlock(&ss, idx);
    -
    -
    - -

    -As noted above, it is legal to block within SRCU read-side critical sections, -however, with great power comes great responsibility. -If you block forever in one of a given domain's SRCU read-side critical -sections, then that domain's grace periods will also be blocked forever. -Of course, one good way to block forever is to deadlock, which can -happen if any operation in a given domain's SRCU read-side critical -section can block waiting, either directly or indirectly, for that domain's -grace period to elapse. -For example, this results in a self-deadlock: - -

    -
    - 1 int idx;
    - 2
    - 3 idx = srcu_read_lock(&ss);
    - 4 do_something();
    - 5 synchronize_srcu(&ss);
    - 6 srcu_read_unlock(&ss, idx);
    -
    -
    - -

    -However, if line 5 acquired a mutex that was held across -a synchronize_srcu() for domain ss, -deadlock would still be possible. -Furthermore, if line 5 acquired a mutex that was held across -a synchronize_srcu() for some other domain ss1, -and if an ss1-domain SRCU read-side critical section -acquired another mutex that was held across as ss-domain -synchronize_srcu(), -deadlock would again be possible. -Such a deadlock cycle could extend across an arbitrarily large number -of different SRCU domains. -Again, with great power comes great responsibility. - -

    -Unlike the other RCU flavors, SRCU read-side critical sections can -run on idle and even offline CPUs. -This ability requires that srcu_read_lock() and -srcu_read_unlock() contain memory barriers, which means -that SRCU readers will run a bit slower than would RCU readers. -It also motivates the smp_mb__after_srcu_read_unlock() -API, which, in combination with srcu_read_unlock(), -guarantees a full memory barrier. - -

    -The -SRCU API -includes -srcu_read_lock(), -srcu_read_unlock(), -srcu_dereference(), -srcu_dereference_check(), -synchronize_srcu(), -synchronize_srcu_expedited(), -call_srcu(), -srcu_barrier(), and -srcu_read_lock_held(). -It also includes -DEFINE_SRCU(), -DEFINE_STATIC_SRCU(), and -init_srcu_struct() -APIs for defining and initializing srcu_struct structures. - -

    Tasks RCU

    - -

    -Some forms of tracing use “tramopolines” to handle the -binary rewriting required to install different types of probes. -It would be good to be able to free old trampolines, which sounds -like a job for some form of RCU. -However, because it is necessary to be able to install a trace -anywhere in the code, it is not possible to use read-side markers -such as rcu_read_lock() and rcu_read_unlock(). -In addition, it does not work to have these markers in the trampoline -itself, because there would need to be instructions following -rcu_read_unlock(). -Although synchronize_rcu() would guarantee that execution -reached the rcu_read_unlock(), it would not be able to -guarantee that execution had completely left the trampoline. - -

    -The solution, in the form of -Tasks RCU, -is to have implicit -read-side critical sections that are delimited by voluntary context -switches, that is, calls to schedule(), -cond_resched_rcu_qs(), and -synchronize_rcu_tasks(). -In addition, transitions to and from userspace execution also delimit -tasks-RCU read-side critical sections. - -

    -The tasks-RCU API is quite compact, consisting only of -call_rcu_tasks(), -synchronize_rcu_tasks(), and -rcu_barrier_tasks(). - -

    -Waiting for Multiple Grace Periods

    - -

    -Perhaps you have an RCU protected data structure that is accessed from -RCU read-side critical sections, from softirq handlers, and from -hardware interrupt handlers. -That is three flavors of RCU, the normal flavor, the bottom-half flavor, -and the sched flavor. -How to wait for a compound grace period? - -

    -The best approach is usually to “just say no!” and -insert rcu_read_lock() and rcu_read_unlock() -around each RCU read-side critical section, regardless of what -environment it happens to be in. -But suppose that some of the RCU read-side critical sections are -on extremely hot code paths, and that use of CONFIG_PREEMPT=n -is not a viable option, so that rcu_read_lock() and -rcu_read_unlock() are not free. -What then? - -

    -You could wait on all three grace periods in succession, as follows: - -

    -
    - 1 synchronize_rcu();
    - 2 synchronize_rcu_bh();
    - 3 synchronize_sched();
    -
    -
    - -

    -This works, but triples the update-side latency penalty. -In cases where this is not acceptable, synchronize_rcu_mult() -may be used to wait on all three flavors of grace period concurrently: - -

    -
    - 1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
    -
    -
    - -

    -But what if it is necessary to also wait on SRCU? -This can be done as follows: - -

    -
    - 1 static void call_my_srcu(struct rcu_head *head,
    - 2        void (*func)(struct rcu_head *head))
    - 3 {
    - 4   call_srcu(&my_srcu, head, func);
    - 5 }
    - 6
    - 7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
    -
    -
    - -

    -If you needed to wait on multiple different flavors of SRCU -(but why???), you would need to create a wrapper function resembling -call_my_srcu() for each SRCU flavor. - -

    @@QQ@@ -But what if I need to wait for multiple RCU flavors, but I also need -the grace periods to be expedited? -

    @@QQA@@ -If you are using expedited grace periods, there should be less penalty -for waiting on them in succession. -But if that is nevertheless a problem, you can use workqueues or multiple -kthreads to wait on the various expedited grace periods concurrently. -

    @@QQE@@ - -

    -Again, it is usually better to adjust the RCU read-side critical sections -to use a single flavor of RCU, but when this is not feasible, you can use -synchronize_rcu_mult(). - -

    Possible Future Changes

    - -

    -One of the tricks that RCU uses to attain update-side scalability is -to increase grace-period latency with increasing numbers of CPUs. -If this becomes a serious problem, it will be necessary to rework the -grace-period state machine so as to avoid the need for the additional -latency. - -

    -Expedited grace periods scan the CPUs, so their latency and overhead -increases with increasing numbers of CPUs. -If this becomes a serious problem on large systems, it will be necessary -to do some redesign to avoid this scalability problem. - -

    -RCU disables CPU hotplug in a few places, perhaps most notably in the -expedited grace-period and rcu_barrier() operations. -If there is a strong reason to use expedited grace periods in CPU-hotplug -notifiers, it will be necessary to avoid disabling CPU hotplug. -This would introduce some complexity, so there had better be a very -good reason. - -

    -The tradeoff between grace-period latency on the one hand and interruptions -of other CPUs on the other hand may need to be re-examined. -The desire is of course for zero grace-period latency as well as zero -interprocessor interrupts undertaken during an expedited grace period -operation. -While this ideal is unlikely to be achievable, it is quite possible that -further improvements can be made. - -

    -The multiprocessor implementations of RCU use a combining tree that -groups CPUs so as to reduce lock contention and increase cache locality. -However, this combining tree does not spread its memory across NUMA -nodes nor does it align the CPU groups with hardware features such -as sockets or cores. -Such spreading and alignment is currently believed to be unnecessary -because the hotpath read-side primitives do not access the combining -tree, nor does call_rcu() in the common case. -If you believe that your architecture needs such spreading and alignment, -then your architecture should also benefit from the -rcutree.rcu_fanout_leaf boot parameter, which can be set -to the number of CPUs in a socket, NUMA node, or whatever. -If the number of CPUs is too large, use a fraction of the number of -CPUs. -If the number of CPUs is a large prime number, well, that certainly -is an “interesting” architectural choice! -More flexible arrangements might be considered, but only if -rcutree.rcu_fanout_leaf has proven inadequate, and only -if the inadequacy has been demonstrated by a carefully run and -realistic system-level workload. - -

    -Please note that arrangements that require RCU to remap CPU numbers will -require extremely good demonstration of need and full exploration of -alternatives. - -

    -There is an embarrassingly large number of flavors of RCU, and this -number has been increasing over time. -Perhaps it will be possible to combine some at some future date. - -

    -RCU's various kthreads are reasonably recent additions. -It is quite likely that adjustments will be required to more gracefully -handle extreme loads. -It might also be necessary to be able to relate CPU utilization by -RCU's kthreads and softirq handlers to the code that instigated this -CPU utilization. -For example, RCU callback overhead might be charged back to the -originating call_rcu() instance, though probably not -in production kernels. - -

    Summary

    - -

    -This document has presented more than two decade's worth of RCU -requirements. -Given that the requirements keep changing, this will not be the last -word on this subject, but at least it serves to get an important -subset of the requirements set forth. - -

    Acknowledgments

    - -I am grateful to Steven Rostedt, Lai Jiangshan, Ingo Molnar, -Oleg Nesterov, Borislav Petkov, Peter Zijlstra, Boqun Feng, and -Andy Lutomirski for their help in rendering -this article human readable, and to Michelle Rankin for her support -of this effort. -Other contributions are acknowledged in the Linux kernel's git archive. -The cartoon is copyright (c) 2013 by Melissa Broussard, -and is provided -under the terms of the Creative Commons Attribution-Share Alike 3.0 -United States license. - -

    @@QQAL@@ - - diff --git a/Documentation/RCU/Design/htmlqqz.sh b/Documentation/RCU/Design/htmlqqz.sh deleted file mode 100755 index d354f069559b..000000000000 --- a/Documentation/RCU/Design/htmlqqz.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/sh -# -# Usage: sh htmlqqz.sh file -# -# Extracts and converts quick quizzes in a proto-HTML document file.htmlx. -# Commands, all of which must be on a line by themselves: -# -# "

    @@QQ@@": Start of a quick quiz. -# "

    @@QQA@@": Start of a quick-quiz answer. -# "

    @@QQE@@": End of a quick-quiz answer, and thus of the quick quiz. -# "

    @@QQAL@@": Place to put quick-quiz answer list. -# -# Places the result in file.html. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, you can access it online at -# http://www.gnu.org/licenses/gpl-2.0.html. -# -# Copyright (c) 2013 Paul E. McKenney, IBM Corporation. - -fn=$1 -if test ! -r $fn.htmlx -then - echo "Error: $fn.htmlx unreadable." - exit 1 -fi - -echo "" > $fn.html -echo "" >> $fn.html -awk < $fn.htmlx >> $fn.html ' - -state == "" && $1 != "

    @@QQ@@" && $1 != "

    @@QQAL@@" { - print $0; - if ($0 ~ /^

    @@QQ/) - print "Bad Quick Quiz command: " NR " (expected

    @@QQ@@ or

    @@QQAL@@)." > "/dev/stderr" - next; -} - -state == "" && $1 == "

    @@QQ@@" { - qqn++; - qqlineno = NR; - haveqq = 1; - state = "qq"; - print "

    Quick Quiz " qqn ":" - next; -} - -state == "qq" && $1 != "

    @@QQA@@" { - qq[qqn] = qq[qqn] $0 "\n"; - print $0 - if ($0 ~ /^

    @@QQ/) - print "Bad Quick Quiz command: " NR ". (expected

    @@QQA@@)" > "/dev/stderr" - next; -} - -state == "qq" && $1 == "

    @@QQA@@" { - state = "qqa"; - print "
    Answer" - next; -} - -state == "qqa" && $1 != "

    @@QQE@@" { - qqa[qqn] = qqa[qqn] $0 "\n"; - if ($0 ~ /^

    @@QQ/) - print "Bad Quick Quiz command: " NR " (expected

    @@QQE@@)." > "/dev/stderr" - next; -} - -state == "qqa" && $1 == "

    @@QQE@@" { - state = ""; - next; -} - -state == "" && $1 == "

    @@QQAL@@" { - haveqq = ""; - print "

    " - print "Answers to Quick Quizzes

    " - print ""; - for (i = 1; i <= qqn; i++) { - print "" - print "

    Quick Quiz " i ":" - print qq[i]; - print ""; - print "

    Answer:" - print qqa[i]; - print ""; - print "

    Back to Quick Quiz " i "." - print ""; - } - next; -} - -END { - if (state != "") - print "Unterminated Quick Quiz: " qqlineno "." > "/dev/stderr" - else if (haveqq) - print "Missing \"

    @@QQAL@@\", no Quick Quiz." > "/dev/stderr" -}' -- GitLab From 5413e24c943da33306047fc091fa34fa4f261b3b Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 15 Mar 2016 13:40:28 -0700 Subject: [PATCH 1025/9938] documentation: Sharpen up the no-readers quick quiz Signed-off-by: Paul E. McKenney --- .../RCU/Design/Requirements/Requirements.html | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index acdad96f78e9..85cf2238fd08 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -1002,18 +1002,21 @@ obligation to wait for these new readers.   Quick Quiz: - Suppose that synchronize_rcu() did wait until all readers had completed. - Would the updater be able to rely on this? + Suppose that synchronize_rcu() did wait until all + readers had completed instead of waiting only on + pre-existing readers. + For how long would the updater be able to rely on there + being no readers? Answer: - No. + For no time at all. Even if synchronize_rcu() were to wait until all readers had completed, a new reader might start immediately after synchronize_rcu() completed. Therefore, the code following - synchronize_rcu() cannot rely on there being no readers - in any case. + synchronize_rcu() can never rely on there being + no readers.   -- GitLab From 0c7d10e4b998b2f751cebf98435f1ec2dd312c87 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 31 Mar 2016 11:00:08 -0700 Subject: [PATCH 1026/9938] documentation: Emphasize the call_rcu() is illegal from idle Although call_rcu()'s fastpath works just fine on an idle CPU, some branches of the slowpath invoke the scheduler, which uses RCU. Therefore, this commit emphasizes the fact that call_rcu() must not be invoked from an idle CPU. Signed-off-by: Paul E. McKenney --- Documentation/RCU/Design/Requirements/Requirements.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 85cf2238fd08..e7e24b3e86e2 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -1650,7 +1650,7 @@ situations where neither synchronize_rcu() nor including within preempt-disable code, local_bh_disable() code, interrupt-disable code, and interrupt handlers. However, even call_rcu() is illegal within NMI handlers -and from offline CPUs. +and from idle and offline CPUs. The callback function (remove_gp_cb() in this case) will be executed within softirq (software interrupt) environment within the Linux kernel, -- GitLab From 28728dd310d48834cd486dac3cac9ae96b9deb96 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 Jan 2016 08:33:37 -0800 Subject: [PATCH 1027/9938] rcu: Make expedited RCU-sched grace period immediately detect idle Currently, sync_sched_exp_handler() will force a reschedule unless this CPU has already checked in or unless a reschedule has already been called for. This is clearly wasteful if sync_sched_exp_handler() interrupted an idle CPU, so this commit immediately reports the quiescent state in that case. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 531a328076bd..5f4336fadc28 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3649,6 +3649,11 @@ static void sync_sched_exp_handler(void *data) if (!(READ_ONCE(rnp->expmask) & rdp->grpmask) || __this_cpu_read(rcu_sched_data.cpu_no_qs.b.exp)) return; + if (rcu_is_cpu_rrupt_from_idle()) { + rcu_report_exp_rdp(&rcu_sched_state, + this_cpu_ptr(&rcu_sched_data), true); + return; + } __this_cpu_write(rcu_sched_data.cpu_no_qs.b.exp, true); resched_cpu(smp_processor_id()); } -- GitLab From 251c617c75f48e03523c43c4ce1dff44bc3ae2bd Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 13 Jan 2016 10:52:35 -0800 Subject: [PATCH 1028/9938] rcu: Make expedited RCU-preempt stall warnings count accurately Currently, synchronize_sched_expedited_wait() simply sets the ndetected variable to the rcu_print_task_exp_stall() return value. This means that if the last rcu_node structure has no stalled tasks, record of any stalled tasks in previous rcu_node structures is lost, which can in turn result in failure to dump out the blocking rcu_node structures. Or could, had the test been correct. This commit therefore adds the return value of rcu_print_task_exp_stall() to ndetected and corrects the later test for ndetected. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 5f4336fadc28..687d8a5f35c7 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3778,7 +3778,7 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp) rsp->name); ndetected = 0; rcu_for_each_leaf_node(rsp, rnp) { - ndetected = rcu_print_task_exp_stall(rnp); + ndetected += rcu_print_task_exp_stall(rnp); mask = 1; for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask <<= 1) { struct rcu_data *rdp; @@ -3797,7 +3797,7 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp) pr_cont(" } %lu jiffies s: %lu root: %#lx/%c\n", jiffies - jiffies_start, rsp->expedited_sequence, rnp_root->expmask, ".T"[!!rnp_root->exp_tasks]); - if (!ndetected) { + if (ndetected) { pr_err("blocking rcu_node structures:"); rcu_for_each_node_breadth_first(rsp, rnp) { if (rnp == rnp_root) -- GitLab From a1e1224849d9610b50fd1dd7d6f44308a59e46af Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 13 Jan 2016 13:57:54 -0800 Subject: [PATCH 1029/9938] rcu: Make cond_resched_rcu_qs() supply RCU-sched expedited QS Although cond_resched_rcu_qs() supplies quiescent states to all flavors of normal RCU grace periods, it does nothing for expedited RCU-sched grace periods. This commit therefore adds a check for a need for a quiescent state from the current CPU by an expedited RCU-sched grace period, and invokes rcu_sched_qs() to supply that quiescent state if so. Note that the check is racy in that we might be migrated to some other CPU just after checking the per-CPU variable. This is OK because the act of migration will do a context switch, which will supply the needed quiescent state. The only downside is that we might do an unnecessary call to rcu_sched_qs(), but the probability is low and the overhead is small. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 687d8a5f35c7..178575c01d09 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -370,6 +370,21 @@ void rcu_all_qs(void) rcu_momentary_dyntick_idle(); local_irq_restore(flags); } + if (unlikely(raw_cpu_read(rcu_sched_data.cpu_no_qs.b.exp))) { + /* + * Yes, we just checked a per-CPU variable with preemption + * enabled, so we might be migrated to some other CPU at + * this point. That is OK because in that case, the + * migration will supply the needed quiescent state. + * We might end up needlessly disabling preemption and + * invoking rcu_sched_qs() on the destination CPU, but + * the probability and cost are both quite low, so this + * should not be a problem in practice. + */ + preempt_disable(); + rcu_sched_qs(); + preempt_enable(); + } this_cpu_inc(rcu_qs_ctr); barrier(); /* Avoid RCU read-side critical sections leaking up. */ } -- GitLab From 26ece8ef6eca97f19eb5ad5186b8c1a29ab25d76 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 28 Jan 2016 18:48:37 -0800 Subject: [PATCH 1030/9938] rcu: Fix synchronize_rcu_expedited() header comment This commit brings the synchronize_rcu_expedited() function's header comment into line with the new implementation. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree_plugin.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index efdf7b61ce12..a2ac2628ef8e 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -722,13 +722,19 @@ static void sync_rcu_exp_handler(void *info) * synchronize_rcu_expedited - Brute-force RCU grace period * * Wait for an RCU-preempt grace period, but expedite it. The basic - * idea is to invoke synchronize_sched_expedited() to push all the tasks to - * the ->blkd_tasks lists and wait for this list to drain. This consumes - * significant time on all CPUs and is unfriendly to real-time workloads, - * so is thus not recommended for any sort of common-case code. - * In fact, if you are using synchronize_rcu_expedited() in a loop, - * please restructure your code to batch your updates, and then Use a - * single synchronize_rcu() instead. + * idea is to IPI all non-idle non-nohz online CPUs. The IPI handler + * checks whether the CPU is in an RCU-preempt critical section, and + * if so, it sets a flag that causes the outermost rcu_read_unlock() + * to report the quiescent state. On the other hand, if the CPU is + * not in an RCU read-side critical section, the IPI handler reports + * the quiescent state immediately. + * + * Although this is a greate improvement over previous expedited + * implementations, it is still unfriendly to real-time workloads, so is + * thus not recommended for any sort of common-case code. In fact, if + * you are using synchronize_rcu_expedited() in a loop, please restructure + * your code to batch your updates, and then Use a single synchronize_rcu() + * instead. */ void synchronize_rcu_expedited(void) { -- GitLab From e087816db9423fdc49302d3cd7ec01e487477a71 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 28 Jan 2016 20:25:09 -0800 Subject: [PATCH 1031/9938] rcu: Add event tracing definitions for expedited grace periods Signed-off-by: Paul E. McKenney --- include/trace/events/rcu.h | 78 +++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index ef72c4aada56..aacc172eba7e 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -171,6 +171,76 @@ TRACE_EVENT(rcu_grace_period_init, __entry->grplo, __entry->grphi, __entry->qsmask) ); +/* + * Tracepoint for expedited grace-period events. Takes a string identifying + * the RCU flavor, the expedited grace-period sequence number, and a string + * identifying the grace-period-related event as follows: + * + * "snap": Captured snapshot of expedited grace period sequence number. + * "start": Started a real expedited grace period. + * "end": Ended a real expedited grace period. + * "done": Someone else did the expedited grace period for us. + */ +TRACE_EVENT(rcu_exp_grace_period, + + TP_PROTO(const char *rcuname, unsigned long gpseq, const char *gpevent), + + TP_ARGS(rcuname, gpseq, gpevent), + + TP_STRUCT__entry( + __field(const char *, rcuname) + __field(unsigned long, gpseq) + __field(const char *, gpevent) + ), + + TP_fast_assign( + __entry->rcuname = rcuname; + __entry->gpseq = gpseq; + __entry->gpevent = gpevent; + ), + + TP_printk("%s %lu %s", + __entry->rcuname, __entry->gpseq, __entry->gpevent) +); + +/* + * Tracepoint for expedited grace-period funnel-locking events. Takes a + * string identifying the RCU flavor, an integer identifying the rcu_node + * combining-tree level, another pair of integers identifying the lowest- + * and highest-numbered CPU associated with the current rcu_node structure, + * and a string. identifying the grace-period-related event as follows: + * + * "acq": Acquired a level of funnel lock + * "rel": Released a level of funnel lock + */ +TRACE_EVENT(rcu_exp_funnel_lock, + + TP_PROTO(const char *rcuname, u8 level, int grplo, int grphi, + const char *gpevent), + + TP_ARGS(rcuname, level, grplo, grphi, gpevent), + + TP_STRUCT__entry( + __field(const char *, rcuname) + __field(u8, level) + __field(int, grplo) + __field(int, grphi) + __field(const char *, gpevent) + ), + + TP_fast_assign( + __entry->rcuname = rcuname; + __entry->level = level; + __entry->grplo = grplo; + __entry->grphi = grphi; + __entry->gpevent = gpevent; + ), + + TP_printk("%s %d %d %d %s", + __entry->rcuname, __entry->level, __entry->grplo, + __entry->grphi, __entry->gpevent) +); + /* * Tracepoint for RCU no-CBs CPU callback handoffs. This event is intended * to assist debugging of these handoffs. @@ -704,11 +774,15 @@ TRACE_EVENT(rcu_barrier, #else /* #ifdef CONFIG_RCU_TRACE */ #define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0) -#define trace_rcu_grace_period_init(rcuname, gpnum, level, grplo, grphi, \ - qsmask) do { } while (0) #define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \ level, grplo, grphi, event) \ do { } while (0) +#define trace_rcu_grace_period_init(rcuname, gpnum, level, grplo, grphi, \ + qsmask) do { } while (0) +#define trace_rcu_exp_grace_period(rcuname, gqseq, gpevent) \ + do { } while (0) +#define trace_rcu_exp_funnel_lock(rcuname, level, grplo, grphi, gpevent) \ + do { } while (0) #define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0) #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0) #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0) -- GitLab From bea2de44ae647698dc848a671fdee6e53c192423 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 28 Jan 2016 20:30:06 -0800 Subject: [PATCH 1032/9938] rcu: Add funnel-locking tracing for expedited grace periods Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 31 +++++++++++++++++++++++++++---- kernel/rcu/tree_plugin.h | 3 +++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 178575c01d09..79e9206a7b11 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3584,10 +3584,18 @@ static bool sync_exp_work_done(struct rcu_state *rsp, struct rcu_node *rnp, atomic_long_t *stat, unsigned long s) { if (rcu_exp_gp_seq_done(rsp, s)) { - if (rnp) + if (rnp) { mutex_unlock(&rnp->exp_funnel_mutex); - else if (rdp) + trace_rcu_exp_funnel_lock(rsp->name, rnp->level, + rnp->grplo, rnp->grphi, + TPS("rel")); + } else if (rdp) { mutex_unlock(&rdp->exp_funnel_mutex); + trace_rcu_exp_funnel_lock(rsp->name, + rdp->mynode->level + 1, + rdp->cpu, rdp->cpu, + TPS("rel")); + } /* Ensure test happens before caller kfree(). */ smp_mb__before_atomic(); /* ^^^ */ atomic_long_inc(stat); @@ -3619,6 +3627,9 @@ static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) if (sync_exp_work_done(rsp, rnp0, NULL, &rdp->expedited_workdone0, s)) return NULL; + trace_rcu_exp_funnel_lock(rsp->name, rnp0->level, + rnp0->grplo, rnp0->grphi, + TPS("acq")); return rnp0; } } @@ -3634,16 +3645,28 @@ static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) if (sync_exp_work_done(rsp, NULL, NULL, &rdp->expedited_workdone1, s)) return NULL; mutex_lock(&rdp->exp_funnel_mutex); + trace_rcu_exp_funnel_lock(rsp->name, rdp->mynode->level + 1, + rdp->cpu, rdp->cpu, TPS("acq")); rnp0 = rdp->mynode; for (; rnp0 != NULL; rnp0 = rnp0->parent) { if (sync_exp_work_done(rsp, rnp1, rdp, &rdp->expedited_workdone2, s)) return NULL; mutex_lock(&rnp0->exp_funnel_mutex); - if (rnp1) + trace_rcu_exp_funnel_lock(rsp->name, rnp0->level, + rnp0->grplo, rnp0->grphi, TPS("acq")); + if (rnp1) { mutex_unlock(&rnp1->exp_funnel_mutex); - else + trace_rcu_exp_funnel_lock(rsp->name, rnp1->level, + rnp1->grplo, rnp1->grphi, + TPS("rel")); + } else { mutex_unlock(&rdp->exp_funnel_mutex); + trace_rcu_exp_funnel_lock(rsp->name, + rdp->mynode->level + 1, + rdp->cpu, rdp->cpu, + TPS("rel")); + } rnp1 = rnp0; } if (sync_exp_work_done(rsp, rnp1, rdp, diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index a2ac2628ef8e..cd2dae43ff48 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -767,6 +767,9 @@ void synchronize_rcu_expedited(void) /* Clean up and exit. */ rcu_exp_gp_seq_end(rsp); mutex_unlock(&rnp_unlock->exp_funnel_mutex); + trace_rcu_exp_funnel_lock(rsp->name, rnp_unlock->level, + rnp_unlock->grplo, rnp_unlock->grphi, + TPS("rel")); } EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); -- GitLab From 4f41530245c7fd4837152e264d120d05ae940eb0 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 28 Jan 2016 20:49:49 -0800 Subject: [PATCH 1033/9938] rcu: Add expedited-grace-period event tracing Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 20 +++++++++++++------- kernel/rcu/tree_plugin.h | 3 +++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 79e9206a7b11..524026fd9dd7 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3584,17 +3584,18 @@ static bool sync_exp_work_done(struct rcu_state *rsp, struct rcu_node *rnp, atomic_long_t *stat, unsigned long s) { if (rcu_exp_gp_seq_done(rsp, s)) { + trace_rcu_exp_grace_period(rsp->name, s, TPS("done")); if (rnp) { - mutex_unlock(&rnp->exp_funnel_mutex); trace_rcu_exp_funnel_lock(rsp->name, rnp->level, rnp->grplo, rnp->grphi, TPS("rel")); + mutex_unlock(&rnp->exp_funnel_mutex); } else if (rdp) { - mutex_unlock(&rdp->exp_funnel_mutex); trace_rcu_exp_funnel_lock(rsp->name, rdp->mynode->level + 1, rdp->cpu, rdp->cpu, TPS("rel")); + mutex_unlock(&rdp->exp_funnel_mutex); } /* Ensure test happens before caller kfree(). */ smp_mb__before_atomic(); /* ^^^ */ @@ -3624,12 +3625,12 @@ static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) rnp0 = rcu_get_root(rsp); if (!mutex_is_locked(&rnp0->exp_funnel_mutex)) { if (mutex_trylock(&rnp0->exp_funnel_mutex)) { - if (sync_exp_work_done(rsp, rnp0, NULL, - &rdp->expedited_workdone0, s)) - return NULL; trace_rcu_exp_funnel_lock(rsp->name, rnp0->level, rnp0->grplo, rnp0->grphi, TPS("acq")); + if (sync_exp_work_done(rsp, rnp0, NULL, + &rdp->expedited_workdone0, s)) + return NULL; return rnp0; } } @@ -3656,16 +3657,16 @@ static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) trace_rcu_exp_funnel_lock(rsp->name, rnp0->level, rnp0->grplo, rnp0->grphi, TPS("acq")); if (rnp1) { - mutex_unlock(&rnp1->exp_funnel_mutex); trace_rcu_exp_funnel_lock(rsp->name, rnp1->level, rnp1->grplo, rnp1->grphi, TPS("rel")); + mutex_unlock(&rnp1->exp_funnel_mutex); } else { - mutex_unlock(&rdp->exp_funnel_mutex); trace_rcu_exp_funnel_lock(rsp->name, rdp->mynode->level + 1, rdp->cpu, rdp->cpu, TPS("rel")); + mutex_unlock(&rdp->exp_funnel_mutex); } rnp1 = rnp0; } @@ -3895,16 +3896,21 @@ void synchronize_sched_expedited(void) /* Take a snapshot of the sequence number. */ s = rcu_exp_gp_seq_snap(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("snap")); rnp = exp_funnel_lock(rsp, s); if (rnp == NULL) return; /* Someone else did our work for us. */ rcu_exp_gp_seq_start(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("start")); sync_rcu_exp_select_cpus(rsp, sync_sched_exp_handler); synchronize_sched_expedited_wait(rsp); rcu_exp_gp_seq_end(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); + trace_rcu_exp_funnel_lock(rsp->name, rnp->level, + rnp->grplo, rnp->grphi, TPS("rel")); mutex_unlock(&rnp->exp_funnel_mutex); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index cd2dae43ff48..36e94aed38a7 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -750,12 +750,14 @@ void synchronize_rcu_expedited(void) } s = rcu_exp_gp_seq_snap(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("snap")); rnp_unlock = exp_funnel_lock(rsp, s); if (rnp_unlock == NULL) return; /* Someone else did our work for us. */ rcu_exp_gp_seq_start(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("start")); /* Initialize the rcu_node tree in preparation for the wait. */ sync_rcu_exp_select_cpus(rsp, sync_rcu_exp_handler); @@ -766,6 +768,7 @@ void synchronize_rcu_expedited(void) /* Clean up and exit. */ rcu_exp_gp_seq_end(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); mutex_unlock(&rnp_unlock->exp_funnel_mutex); trace_rcu_exp_funnel_lock(rsp->name, rnp_unlock->level, rnp_unlock->grplo, rnp_unlock->grphi, -- GitLab From e2fd9d35847d1936398d44c4df68dceb3d7f64e7 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 30 Jan 2016 17:23:19 -0800 Subject: [PATCH 1034/9938] rcu: Remove expedited GP funnel-lock bypass Commit #cdacbe1f91264 ("rcu: Add fastpath bypassing funnel locking") turns out to be a pessimization at high load because it forces a tree full of tasks to wait for an expedited grace period that they probably do not need. This commit therefore removes this optimization. Signed-off-by: Paul E. McKenney --- Documentation/RCU/trace.txt | 10 +++++----- kernel/rcu/tree.c | 19 ------------------- kernel/rcu/tree.h | 1 - kernel/rcu/tree_trace.c | 7 +++---- 4 files changed, 8 insertions(+), 29 deletions(-) diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt index ec6998b1b6d0..00a3a38b375a 100644 --- a/Documentation/RCU/trace.txt +++ b/Documentation/RCU/trace.txt @@ -237,17 +237,17 @@ o "ktl" is the low-order 16 bits (in hexadecimal) of the count of The output of "cat rcu/rcu_preempt/rcuexp" looks as follows: -s=21872 wd0=0 wd1=0 wd2=0 wd3=5 n=0 enq=0 sc=21872 +s=21872 wd1=0 wd2=0 wd3=5 n=0 enq=0 sc=21872 These fields are as follows: o "s" is the sequence number, with an odd number indicating that an expedited grace period is in progress. -o "wd0", "wd1", "wd2", and "wd3" are the number of times that an - attempt to start an expedited grace period found that someone - else had completed an expedited grace period that satisfies the - attempted request. "Our work is done." +o "wd1", "wd2", and "wd3" are the number of times that an attempt + to start an expedited grace period found that someone else had + completed an expedited grace period that satisfies the attempted + request. "Our work is done." o "n" is number of times that a concurrent CPU-hotplug operation forced a fallback to a normal grace period. diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 524026fd9dd7..62e73e0a929f 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3616,25 +3616,6 @@ static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) struct rcu_node *rnp0; struct rcu_node *rnp1 = NULL; - /* - * First try directly acquiring the root lock in order to reduce - * latency in the common case where expedited grace periods are - * rare. We check mutex_is_locked() to avoid pathological levels of - * memory contention on ->exp_funnel_mutex in the heavy-load case. - */ - rnp0 = rcu_get_root(rsp); - if (!mutex_is_locked(&rnp0->exp_funnel_mutex)) { - if (mutex_trylock(&rnp0->exp_funnel_mutex)) { - trace_rcu_exp_funnel_lock(rsp->name, rnp0->level, - rnp0->grplo, rnp0->grphi, - TPS("acq")); - if (sync_exp_work_done(rsp, rnp0, NULL, - &rdp->expedited_workdone0, s)) - return NULL; - return rnp0; - } - } - /* * Each pass through the following loop works its way * up the rcu_node tree, returning if others have done the diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index df668c0f9e64..ac9a7b0c36ae 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -388,7 +388,6 @@ struct rcu_data { struct rcu_head oom_head; #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ struct mutex exp_funnel_mutex; - atomic_long_t expedited_workdone0; /* # done by others #0. */ atomic_long_t expedited_workdone1; /* # done by others #1. */ atomic_long_t expedited_workdone2; /* # done by others #2. */ atomic_long_t expedited_workdone3; /* # done by others #3. */ diff --git a/kernel/rcu/tree_trace.c b/kernel/rcu/tree_trace.c index 1088e64f01ad..d149c412a4e5 100644 --- a/kernel/rcu/tree_trace.c +++ b/kernel/rcu/tree_trace.c @@ -185,17 +185,16 @@ static int show_rcuexp(struct seq_file *m, void *v) int cpu; struct rcu_state *rsp = (struct rcu_state *)m->private; struct rcu_data *rdp; - unsigned long s0 = 0, s1 = 0, s2 = 0, s3 = 0; + unsigned long s1 = 0, s2 = 0, s3 = 0; for_each_possible_cpu(cpu) { rdp = per_cpu_ptr(rsp->rda, cpu); - s0 += atomic_long_read(&rdp->expedited_workdone0); s1 += atomic_long_read(&rdp->expedited_workdone1); s2 += atomic_long_read(&rdp->expedited_workdone2); s3 += atomic_long_read(&rdp->expedited_workdone3); } - seq_printf(m, "s=%lu wd0=%lu wd1=%lu wd2=%lu wd3=%lu n=%lu enq=%d sc=%lu\n", - rsp->expedited_sequence, s0, s1, s2, s3, + seq_printf(m, "s=%lu wd1=%lu wd2=%lu wd3=%lu n=%lu enq=%d sc=%lu\n", + rsp->expedited_sequence, s1, s2, s3, atomic_long_read(&rsp->expedited_normal), atomic_read(&rsp->expedited_need_qs), rsp->expedited_sequence / 2); -- GitLab From ec3833ed02ae6ef2a933ece9de7cbab0c64c699e Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 11 Jan 2016 16:29:29 -0800 Subject: [PATCH 1035/9938] rcu: Force boolean subscript for expedited stall warnings The cpu_online() function can return values other than 0 and 1, which can result in subscript overflow when applied to a two-element array. This commit allows for this behavior by using "!!" on the return value from cpu_online() when used as a subscript. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 62e73e0a929f..64c2e3288551 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3808,7 +3808,7 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp) ndetected++; rdp = per_cpu_ptr(rsp->rda, cpu); pr_cont(" %d-%c%c%c", cpu, - "O."[cpu_online(cpu)], + "O."[!!cpu_online(cpu)], "o."[!!(rdp->grpmask & rnp->expmaskinit)], "N."[!!(rdp->grpmask & rnp->expmaskinitnext)]); } -- GitLab From d40a4f09a448382961fa9b1a2f7d4f34813f0273 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 8 Mar 2016 14:43:44 -0800 Subject: [PATCH 1036/9938] rcu: Shorten expedited_workdone* to exp_workdone* Just a name change to save a few lines and a bit of typing. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 8 +++----- kernel/rcu/tree.h | 6 +++--- kernel/rcu/tree_trace.c | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 64c2e3288551..89f028767765 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3624,15 +3624,14 @@ static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) * can be inexact, as it is just promoting locality and is not * strictly needed for correctness. */ - if (sync_exp_work_done(rsp, NULL, NULL, &rdp->expedited_workdone1, s)) + if (sync_exp_work_done(rsp, NULL, NULL, &rdp->exp_workdone1, s)) return NULL; mutex_lock(&rdp->exp_funnel_mutex); trace_rcu_exp_funnel_lock(rsp->name, rdp->mynode->level + 1, rdp->cpu, rdp->cpu, TPS("acq")); rnp0 = rdp->mynode; for (; rnp0 != NULL; rnp0 = rnp0->parent) { - if (sync_exp_work_done(rsp, rnp1, rdp, - &rdp->expedited_workdone2, s)) + if (sync_exp_work_done(rsp, rnp1, rdp, &rdp->exp_workdone2, s)) return NULL; mutex_lock(&rnp0->exp_funnel_mutex); trace_rcu_exp_funnel_lock(rsp->name, rnp0->level, @@ -3651,8 +3650,7 @@ static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) } rnp1 = rnp0; } - if (sync_exp_work_done(rsp, rnp1, rdp, - &rdp->expedited_workdone3, s)) + if (sync_exp_work_done(rsp, rnp1, rdp, &rdp->exp_workdone3, s)) return NULL; return rnp1; } diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index ac9a7b0c36ae..6a8f09446924 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -388,9 +388,9 @@ struct rcu_data { struct rcu_head oom_head; #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ struct mutex exp_funnel_mutex; - atomic_long_t expedited_workdone1; /* # done by others #1. */ - atomic_long_t expedited_workdone2; /* # done by others #2. */ - atomic_long_t expedited_workdone3; /* # done by others #3. */ + atomic_long_t exp_workdone1; /* # done by others #1. */ + atomic_long_t exp_workdone2; /* # done by others #2. */ + atomic_long_t exp_workdone3; /* # done by others #3. */ /* 7) Callback offloading. */ #ifdef CONFIG_RCU_NOCB_CPU diff --git a/kernel/rcu/tree_trace.c b/kernel/rcu/tree_trace.c index d149c412a4e5..86782f9a4604 100644 --- a/kernel/rcu/tree_trace.c +++ b/kernel/rcu/tree_trace.c @@ -189,9 +189,9 @@ static int show_rcuexp(struct seq_file *m, void *v) for_each_possible_cpu(cpu) { rdp = per_cpu_ptr(rsp->rda, cpu); - s1 += atomic_long_read(&rdp->expedited_workdone1); - s2 += atomic_long_read(&rdp->expedited_workdone2); - s3 += atomic_long_read(&rdp->expedited_workdone3); + s1 += atomic_long_read(&rdp->exp_workdone1); + s2 += atomic_long_read(&rdp->exp_workdone2); + s3 += atomic_long_read(&rdp->exp_workdone3); } seq_printf(m, "s=%lu wd1=%lu wd2=%lu wd3=%lu n=%lu enq=%d sc=%lu\n", rsp->expedited_sequence, s1, s2, s3, -- GitLab From f6a12f34a448cc8a624070fd365c29c890138a48 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 30 Jan 2016 17:57:35 -0800 Subject: [PATCH 1037/9938] rcu: Enforce expedited-GP fairness via funnel wait queue The current mutex-based funnel-locking approach used by expedited grace periods is subject to severe unfairness. The problem arises when a few tasks, making a path from leaves to root, all wake up before other tasks do. A new task can then follow this path all the way to the root, which needlessly delays tasks whose grace period is done, but who do not happen to acquire the lock quickly enough. This commit avoids this problem by maintaining per-rcu_node wait queues, along with a per-rcu_node counter that tracks the latest grace period sought by an earlier task to visit this node. If that grace period would satisfy the current task, instead of proceeding up the tree, it waits on the current rcu_node structure using a pair of wait queues provided for that purpose. This decouples awakening of old tasks from the arrival of new tasks. If the wakeups prove to be a bottleneck, additional kthreads can be brought to bear for that purpose. Signed-off-by: Paul E. McKenney --- include/trace/events/rcu.h | 5 +- kernel/rcu/tree.c | 155 +++++++++++++++++++------------------ kernel/rcu/tree.h | 10 +-- kernel/rcu/tree_plugin.h | 16 ++-- 4 files changed, 93 insertions(+), 93 deletions(-) diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index aacc172eba7e..d3e756539d44 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -179,6 +179,7 @@ TRACE_EVENT(rcu_grace_period_init, * "snap": Captured snapshot of expedited grace period sequence number. * "start": Started a real expedited grace period. * "end": Ended a real expedited grace period. + * "endwake": Woke piggybackers up. * "done": Someone else did the expedited grace period for us. */ TRACE_EVENT(rcu_exp_grace_period, @@ -210,8 +211,8 @@ TRACE_EVENT(rcu_exp_grace_period, * and highest-numbered CPU associated with the current rcu_node structure, * and a string. identifying the grace-period-related event as follows: * - * "acq": Acquired a level of funnel lock - * "rel": Released a level of funnel lock + * "nxtlvl": Advance to next level of rcu_node funnel + * "wait": Wait for someone else to do expedited GP */ TRACE_EVENT(rcu_exp_funnel_lock, diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 89f028767765..bd2658edce00 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -102,6 +102,7 @@ struct rcu_state sname##_state = { \ .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \ .name = RCU_STATE_NAME(sname), \ .abbr = sabbr, \ + .exp_mutex = __MUTEX_INITIALIZER(sname##_state.exp_mutex), \ } RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched); @@ -3484,7 +3485,7 @@ static void __maybe_unused sync_exp_reset_tree(struct rcu_state *rsp) * for the current expedited grace period. Works only for preemptible * RCU -- other RCU implementation use other means. * - * Caller must hold the root rcu_node's exp_funnel_mutex. + * Caller must hold the rcu_state's exp_mutex. */ static int sync_rcu_preempt_exp_done(struct rcu_node *rnp) { @@ -3500,8 +3501,8 @@ static int sync_rcu_preempt_exp_done(struct rcu_node *rnp) * recursively up the tree. (Calm down, calm down, we do the recursion * iteratively!) * - * Caller must hold the root rcu_node's exp_funnel_mutex and the - * specified rcu_node structure's ->lock. + * Caller must hold the rcu_state's exp_mutex and the specified rcu_node + * structure's ->lock. */ static void __rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, bool wake, unsigned long flags) @@ -3538,7 +3539,7 @@ static void __rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, * Report expedited quiescent state for specified node. This is a * lock-acquisition wrapper function for __rcu_report_exp_rnp(). * - * Caller must hold the root rcu_node's exp_funnel_mutex. + * Caller must hold the rcu_state's exp_mutex. */ static void __maybe_unused rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, bool wake) @@ -3551,8 +3552,8 @@ static void __maybe_unused rcu_report_exp_rnp(struct rcu_state *rsp, /* * Report expedited quiescent state for multiple CPUs, all covered by the - * specified leaf rcu_node structure. Caller must hold the root - * rcu_node's exp_funnel_mutex. + * specified leaf rcu_node structure. Caller must hold the rcu_state's + * exp_mutex. */ static void rcu_report_exp_cpu_mult(struct rcu_state *rsp, struct rcu_node *rnp, unsigned long mask, bool wake) @@ -3570,7 +3571,6 @@ static void rcu_report_exp_cpu_mult(struct rcu_state *rsp, struct rcu_node *rnp, /* * Report expedited quiescent state for specified rcu_data (CPU). - * Caller must hold the root rcu_node's exp_funnel_mutex. */ static void rcu_report_exp_rdp(struct rcu_state *rsp, struct rcu_data *rdp, bool wake) @@ -3579,24 +3579,11 @@ static void rcu_report_exp_rdp(struct rcu_state *rsp, struct rcu_data *rdp, } /* Common code for synchronize_{rcu,sched}_expedited() work-done checking. */ -static bool sync_exp_work_done(struct rcu_state *rsp, struct rcu_node *rnp, - struct rcu_data *rdp, - atomic_long_t *stat, unsigned long s) +static bool sync_exp_work_done(struct rcu_state *rsp, atomic_long_t *stat, + unsigned long s) { if (rcu_exp_gp_seq_done(rsp, s)) { trace_rcu_exp_grace_period(rsp->name, s, TPS("done")); - if (rnp) { - trace_rcu_exp_funnel_lock(rsp->name, rnp->level, - rnp->grplo, rnp->grphi, - TPS("rel")); - mutex_unlock(&rnp->exp_funnel_mutex); - } else if (rdp) { - trace_rcu_exp_funnel_lock(rsp->name, - rdp->mynode->level + 1, - rdp->cpu, rdp->cpu, - TPS("rel")); - mutex_unlock(&rdp->exp_funnel_mutex); - } /* Ensure test happens before caller kfree(). */ smp_mb__before_atomic(); /* ^^^ */ atomic_long_inc(stat); @@ -3606,53 +3593,53 @@ static bool sync_exp_work_done(struct rcu_state *rsp, struct rcu_node *rnp, } /* - * Funnel-lock acquisition for expedited grace periods. Returns a - * pointer to the root rcu_node structure, or NULL if some other - * task did the expedited grace period for us. + * Funnel-lock acquisition for expedited grace periods. Returns true + * if some other task completed an expedited grace period that this task + * can piggy-back on, and with no mutex held. Otherwise, returns false + * with the mutex held, indicating that the caller must actually do the + * expedited grace period. */ -static struct rcu_node *exp_funnel_lock(struct rcu_state *rsp, unsigned long s) +static bool exp_funnel_lock(struct rcu_state *rsp, unsigned long s) { struct rcu_data *rdp = per_cpu_ptr(rsp->rda, raw_smp_processor_id()); - struct rcu_node *rnp0; - struct rcu_node *rnp1 = NULL; + struct rcu_node *rnp = rdp->mynode; /* - * Each pass through the following loop works its way - * up the rcu_node tree, returning if others have done the - * work or otherwise falls through holding the root rnp's - * ->exp_funnel_mutex. The mapping from CPU to rcu_node structure - * can be inexact, as it is just promoting locality and is not - * strictly needed for correctness. + * Each pass through the following loop works its way up + * the rcu_node tree, returning if others have done the work or + * otherwise falls through to acquire rsp->exp_mutex. The mapping + * from CPU to rcu_node structure can be inexact, as it is just + * promoting locality and is not strictly needed for correctness. */ - if (sync_exp_work_done(rsp, NULL, NULL, &rdp->exp_workdone1, s)) - return NULL; - mutex_lock(&rdp->exp_funnel_mutex); - trace_rcu_exp_funnel_lock(rsp->name, rdp->mynode->level + 1, - rdp->cpu, rdp->cpu, TPS("acq")); - rnp0 = rdp->mynode; - for (; rnp0 != NULL; rnp0 = rnp0->parent) { - if (sync_exp_work_done(rsp, rnp1, rdp, &rdp->exp_workdone2, s)) - return NULL; - mutex_lock(&rnp0->exp_funnel_mutex); - trace_rcu_exp_funnel_lock(rsp->name, rnp0->level, - rnp0->grplo, rnp0->grphi, TPS("acq")); - if (rnp1) { - trace_rcu_exp_funnel_lock(rsp->name, rnp1->level, - rnp1->grplo, rnp1->grphi, - TPS("rel")); - mutex_unlock(&rnp1->exp_funnel_mutex); - } else { - trace_rcu_exp_funnel_lock(rsp->name, - rdp->mynode->level + 1, - rdp->cpu, rdp->cpu, - TPS("rel")); - mutex_unlock(&rdp->exp_funnel_mutex); + for (; rnp != NULL; rnp = rnp->parent) { + if (sync_exp_work_done(rsp, &rdp->exp_workdone1, s)) + return true; + + /* Work not done, either wait here or go up. */ + spin_lock(&rnp->exp_lock); + if (ULONG_CMP_GE(rnp->exp_seq_rq, s)) { + + /* Someone else doing GP, so wait for them. */ + spin_unlock(&rnp->exp_lock); + trace_rcu_exp_funnel_lock(rsp->name, rnp->level, + rnp->grplo, rnp->grphi, + TPS("wait")); + wait_event(rnp->exp_wq[(s >> 1) & 0x1], + sync_exp_work_done(rsp, + &rdp->exp_workdone2, s)); + return true; } - rnp1 = rnp0; + rnp->exp_seq_rq = s; /* Followers can wait on us. */ + spin_unlock(&rnp->exp_lock); + trace_rcu_exp_funnel_lock(rsp->name, rnp->level, rnp->grplo, + rnp->grphi, TPS("nxtlvl")); } - if (sync_exp_work_done(rsp, rnp1, rdp, &rdp->exp_workdone3, s)) - return NULL; - return rnp1; + mutex_lock(&rsp->exp_mutex); + if (sync_exp_work_done(rsp, &rdp->exp_workdone3, s)) { + mutex_unlock(&rsp->exp_mutex); + return true; + } + return false; } /* Invoked on each online non-idle CPU for expedited quiescent state. */ @@ -3841,6 +3828,27 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp) } } +/* + * Wake up everyone who piggybacked on the just-completed expedited + * grace period. Also update all the ->exp_seq_rq counters as needed + * in order to avoid counter-wrap problems. + */ +static void rcu_exp_wake(struct rcu_state *rsp, unsigned long s) +{ + struct rcu_node *rnp; + + rcu_for_each_node_breadth_first(rsp, rnp) { + if (ULONG_CMP_LT(READ_ONCE(rnp->exp_seq_rq), s)) { + spin_lock(&rnp->exp_lock); + /* Recheck, avoid hang in case someone just arrived. */ + if (ULONG_CMP_LT(rnp->exp_seq_rq, s)) + rnp->exp_seq_rq = s; + spin_unlock(&rnp->exp_lock); + } + wake_up_all(&rnp->exp_wq[(rsp->expedited_sequence >> 1) & 0x1]); + } +} + /** * synchronize_sched_expedited - Brute-force RCU-sched grace period * @@ -3860,7 +3868,6 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp) void synchronize_sched_expedited(void) { unsigned long s; - struct rcu_node *rnp; struct rcu_state *rsp = &rcu_sched_state; /* If only one CPU, this is automatically a grace period. */ @@ -3877,20 +3884,23 @@ void synchronize_sched_expedited(void) s = rcu_exp_gp_seq_snap(rsp); trace_rcu_exp_grace_period(rsp->name, s, TPS("snap")); - rnp = exp_funnel_lock(rsp, s); - if (rnp == NULL) + if (exp_funnel_lock(rsp, s)) return; /* Someone else did our work for us. */ rcu_exp_gp_seq_start(rsp); trace_rcu_exp_grace_period(rsp->name, s, TPS("start")); + + /* Initialize the rcu_node tree in preparation for the wait. */ sync_rcu_exp_select_cpus(rsp, sync_sched_exp_handler); - synchronize_sched_expedited_wait(rsp); + /* Wait and clean up, including waking everyone. */ + synchronize_sched_expedited_wait(rsp); rcu_exp_gp_seq_end(rsp); trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); - trace_rcu_exp_funnel_lock(rsp->name, rnp->level, - rnp->grplo, rnp->grphi, TPS("rel")); - mutex_unlock(&rnp->exp_funnel_mutex); + rcu_exp_wake(rsp, s); + + trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake")); + mutex_unlock(&rsp->exp_mutex); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); @@ -4190,7 +4200,6 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp) WARN_ON_ONCE(atomic_read(&rdp->dynticks->dynticks) != 1); rdp->cpu = cpu; rdp->rsp = rsp; - mutex_init(&rdp->exp_funnel_mutex); rcu_boot_init_nocb_percpu_data(rdp); raw_spin_unlock_irqrestore_rcu_node(rnp, flags); } @@ -4448,10 +4457,8 @@ static void __init rcu_init_one(struct rcu_state *rsp) { static const char * const buf[] = RCU_NODE_NAME_INIT; static const char * const fqs[] = RCU_FQS_NAME_INIT; - static const char * const exp[] = RCU_EXP_NAME_INIT; static struct lock_class_key rcu_node_class[RCU_NUM_LVLS]; static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS]; - static struct lock_class_key rcu_exp_class[RCU_NUM_LVLS]; static u8 fl_mask = 0x1; int levelcnt[RCU_NUM_LVLS]; /* # nodes in each level. */ @@ -4510,9 +4517,9 @@ static void __init rcu_init_one(struct rcu_state *rsp) rnp->level = i; INIT_LIST_HEAD(&rnp->blkd_tasks); rcu_init_one_nocb(rnp); - mutex_init(&rnp->exp_funnel_mutex); - lockdep_set_class_and_name(&rnp->exp_funnel_mutex, - &rcu_exp_class[i], exp[i]); + init_waitqueue_head(&rnp->exp_wq[0]); + init_waitqueue_head(&rnp->exp_wq[1]); + spin_lock_init(&rnp->exp_lock); } } diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index 6a8f09446924..f9d4fbb1e014 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -70,7 +70,6 @@ # define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0 } # define RCU_NODE_NAME_INIT { "rcu_node_0" } # define RCU_FQS_NAME_INIT { "rcu_node_fqs_0" } -# define RCU_EXP_NAME_INIT { "rcu_node_exp_0" } #elif NR_CPUS <= RCU_FANOUT_2 # define RCU_NUM_LVLS 2 # define NUM_RCU_LVL_0 1 @@ -79,7 +78,6 @@ # define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1 } # define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1" } # define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1" } -# define RCU_EXP_NAME_INIT { "rcu_node_exp_0", "rcu_node_exp_1" } #elif NR_CPUS <= RCU_FANOUT_3 # define RCU_NUM_LVLS 3 # define NUM_RCU_LVL_0 1 @@ -89,7 +87,6 @@ # define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 } # define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1", "rcu_node_2" } # define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" } -# define RCU_EXP_NAME_INIT { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2" } #elif NR_CPUS <= RCU_FANOUT_4 # define RCU_NUM_LVLS 4 # define NUM_RCU_LVL_0 1 @@ -100,7 +97,6 @@ # define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 } # define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" } # define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" } -# define RCU_EXP_NAME_INIT { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2", "rcu_node_exp_3" } #else # error "CONFIG_RCU_FANOUT insufficient for NR_CPUS" #endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */ @@ -252,7 +248,9 @@ struct rcu_node { /* Counts of upcoming no-CB GP requests. */ raw_spinlock_t fqslock ____cacheline_internodealigned_in_smp; - struct mutex exp_funnel_mutex ____cacheline_internodealigned_in_smp; + spinlock_t exp_lock ____cacheline_internodealigned_in_smp; + unsigned long exp_seq_rq; + wait_queue_head_t exp_wq[2]; } ____cacheline_internodealigned_in_smp; /* @@ -387,7 +385,6 @@ struct rcu_data { #ifdef CONFIG_RCU_FAST_NO_HZ struct rcu_head oom_head; #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ - struct mutex exp_funnel_mutex; atomic_long_t exp_workdone1; /* # done by others #1. */ atomic_long_t exp_workdone2; /* # done by others #2. */ atomic_long_t exp_workdone3; /* # done by others #3. */ @@ -504,6 +501,7 @@ struct rcu_state { /* _rcu_barrier(). */ /* End of fields guarded by barrier_mutex. */ + struct mutex exp_mutex; /* Serialize expedited GP. */ unsigned long expedited_sequence; /* Take a ticket. */ atomic_long_t expedited_normal; /* # fallbacks to normal. */ atomic_t expedited_need_qs; /* # CPUs left to check in. */ diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 36e94aed38a7..c82c3640493f 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -738,8 +738,6 @@ static void sync_rcu_exp_handler(void *info) */ void synchronize_rcu_expedited(void) { - struct rcu_node *rnp; - struct rcu_node *rnp_unlock; struct rcu_state *rsp = rcu_state_p; unsigned long s; @@ -752,8 +750,7 @@ void synchronize_rcu_expedited(void) s = rcu_exp_gp_seq_snap(rsp); trace_rcu_exp_grace_period(rsp->name, s, TPS("snap")); - rnp_unlock = exp_funnel_lock(rsp, s); - if (rnp_unlock == NULL) + if (exp_funnel_lock(rsp, s)) return; /* Someone else did our work for us. */ rcu_exp_gp_seq_start(rsp); @@ -763,16 +760,13 @@ void synchronize_rcu_expedited(void) sync_rcu_exp_select_cpus(rsp, sync_rcu_exp_handler); /* Wait for snapshotted ->blkd_tasks lists to drain. */ - rnp = rcu_get_root(rsp); synchronize_sched_expedited_wait(rsp); - - /* Clean up and exit. */ rcu_exp_gp_seq_end(rsp); trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); - mutex_unlock(&rnp_unlock->exp_funnel_mutex); - trace_rcu_exp_funnel_lock(rsp->name, rnp_unlock->level, - rnp_unlock->grplo, rnp_unlock->grphi, - TPS("rel")); + rcu_exp_wake(rsp, s); + + trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake")); + mutex_unlock(&rsp->exp_mutex); } EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); -- GitLab From 356051e1de3cf65575da4ee92d1f5cee86677ee2 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 16 Mar 2016 13:22:53 -0700 Subject: [PATCH 1038/9938] rcu: Add exp_funnel_lock() fastpath This commit speeds up the low-contention case, especially for systems with large rcu_node trees, by attempting to directly acquire the ->exp_mutex. This fastpath checks the leaves and root first in order to avoid excessive memory contention on the mutex itself. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index bd2658edce00..892a140ae7b6 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3603,6 +3603,15 @@ static bool exp_funnel_lock(struct rcu_state *rsp, unsigned long s) { struct rcu_data *rdp = per_cpu_ptr(rsp->rda, raw_smp_processor_id()); struct rcu_node *rnp = rdp->mynode; + struct rcu_node *rnp_root = rcu_get_root(rsp); + + /* Low-contention fastpath. */ + if (ULONG_CMP_LT(READ_ONCE(rnp->exp_seq_rq), s) && + (rnp == rnp_root || + ULONG_CMP_LT(READ_ONCE(rnp_root->exp_seq_rq), s)) && + !mutex_is_locked(&rsp->exp_mutex) && + mutex_trylock(&rsp->exp_mutex)) + goto fastpath; /* * Each pass through the following loop works its way up @@ -3635,6 +3644,7 @@ static bool exp_funnel_lock(struct rcu_state *rsp, unsigned long s) rnp->grphi, TPS("nxtlvl")); } mutex_lock(&rsp->exp_mutex); +fastpath: if (sync_exp_work_done(rsp, &rdp->exp_workdone3, s)) { mutex_unlock(&rsp->exp_mutex); return true; -- GitLab From 4ea3e85b113ab37a2d55cfabf0d709ddec088bb3 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 16 Mar 2016 16:22:25 -0700 Subject: [PATCH 1039/9938] rcu: Consolidate expedited GP code into rcu_exp_wait_wake() Currently, synchronize_rcu_expedited() and rcu_sched_expedited() have significant duplicate code. This commit therefore consolidates some of this code into rcu_exp_wake(), which is now renamed to rcu_exp_wait_wake() in recognition of its added responsibilities. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 18 +++++++++--------- kernel/rcu/tree_plugin.h | 10 ++-------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 892a140ae7b6..fd86eca9478e 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3839,14 +3839,18 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp) } /* - * Wake up everyone who piggybacked on the just-completed expedited + * Wait for the current expedited grace period to complete, and then + * wake up everyone who piggybacked on the just-completed expedited * grace period. Also update all the ->exp_seq_rq counters as needed * in order to avoid counter-wrap problems. */ -static void rcu_exp_wake(struct rcu_state *rsp, unsigned long s) +static void rcu_exp_wait_wake(struct rcu_state *rsp, unsigned long s) { struct rcu_node *rnp; + synchronize_sched_expedited_wait(rsp); + rcu_exp_gp_seq_end(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); rcu_for_each_node_breadth_first(rsp, rnp) { if (ULONG_CMP_LT(READ_ONCE(rnp->exp_seq_rq), s)) { spin_lock(&rnp->exp_lock); @@ -3857,6 +3861,8 @@ static void rcu_exp_wake(struct rcu_state *rsp, unsigned long s) } wake_up_all(&rnp->exp_wq[(rsp->expedited_sequence >> 1) & 0x1]); } + trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake")); + mutex_unlock(&rsp->exp_mutex); } /** @@ -3904,13 +3910,7 @@ void synchronize_sched_expedited(void) sync_rcu_exp_select_cpus(rsp, sync_sched_exp_handler); /* Wait and clean up, including waking everyone. */ - synchronize_sched_expedited_wait(rsp); - rcu_exp_gp_seq_end(rsp); - trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); - rcu_exp_wake(rsp, s); - - trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake")); - mutex_unlock(&rsp->exp_mutex); + rcu_exp_wait_wake(rsp, s); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index c82c3640493f..b6d5dde6eab9 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -759,14 +759,8 @@ void synchronize_rcu_expedited(void) /* Initialize the rcu_node tree in preparation for the wait. */ sync_rcu_exp_select_cpus(rsp, sync_rcu_exp_handler); - /* Wait for snapshotted ->blkd_tasks lists to drain. */ - synchronize_sched_expedited_wait(rsp); - rcu_exp_gp_seq_end(rsp); - trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); - rcu_exp_wake(rsp, s); - - trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake")); - mutex_unlock(&rsp->exp_mutex); + /* Wait for ->blkd_tasks lists to drain, then wake everyone up. */ + rcu_exp_wait_wake(rsp, s); } EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); -- GitLab From 179e5dcd1e5bdfac1128431d131b31322aedd2bc Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 16 Mar 2016 16:27:44 -0700 Subject: [PATCH 1040/9938] rcu: Consolidate expedited GP tracing into rcu_exp_gp_seq_snap() This commit moves some duplicate code from synchronize_rcu_expedited() and synchronize_sched_expedited() into rcu_exp_gp_seq_snap(). This doesn't save lines of code, but does eliminate a "tell me twice" issue. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 8 +++++--- kernel/rcu/tree_plugin.h | 2 -- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index fd86eca9478e..5b1c8fd89af0 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3392,8 +3392,12 @@ static void rcu_exp_gp_seq_end(struct rcu_state *rsp) } static unsigned long rcu_exp_gp_seq_snap(struct rcu_state *rsp) { + unsigned long s; + smp_mb(); /* Caller's modifications seen first by other CPUs. */ - return rcu_seq_snap(&rsp->expedited_sequence); + s = rcu_seq_snap(&rsp->expedited_sequence); + trace_rcu_exp_grace_period(rsp->name, s, TPS("snap")); + return s; } static bool rcu_exp_gp_seq_done(struct rcu_state *rsp, unsigned long s) { @@ -3898,8 +3902,6 @@ void synchronize_sched_expedited(void) /* Take a snapshot of the sequence number. */ s = rcu_exp_gp_seq_snap(rsp); - trace_rcu_exp_grace_period(rsp->name, s, TPS("snap")); - if (exp_funnel_lock(rsp, s)) return; /* Someone else did our work for us. */ diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index b6d5dde6eab9..529a44085a63 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -748,8 +748,6 @@ void synchronize_rcu_expedited(void) } s = rcu_exp_gp_seq_snap(rsp); - trace_rcu_exp_grace_period(rsp->name, s, TPS("snap")); - if (exp_funnel_lock(rsp, s)) return; /* Someone else did our work for us. */ -- GitLab From aff12cdf86e6fa891d1c30c0fad112d138bd7b10 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 16 Mar 2016 16:32:24 -0700 Subject: [PATCH 1041/9938] rcu: Consolidate expedited GP code into exp_funnel_lock() This commit pulls the grace-period-start counter adjustment and tracing from synchronize_rcu_expedited() and synchronize_sched_expedited() into exp_funnel_lock(), thus eliminating some code duplication. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 5 ++--- kernel/rcu/tree_plugin.h | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 5b1c8fd89af0..e8fff14e417b 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3653,6 +3653,8 @@ static bool exp_funnel_lock(struct rcu_state *rsp, unsigned long s) mutex_unlock(&rsp->exp_mutex); return true; } + rcu_exp_gp_seq_start(rsp); + trace_rcu_exp_grace_period(rsp->name, s, TPS("start")); return false; } @@ -3905,9 +3907,6 @@ void synchronize_sched_expedited(void) if (exp_funnel_lock(rsp, s)) return; /* Someone else did our work for us. */ - rcu_exp_gp_seq_start(rsp); - trace_rcu_exp_grace_period(rsp->name, s, TPS("start")); - /* Initialize the rcu_node tree in preparation for the wait. */ sync_rcu_exp_select_cpus(rsp, sync_sched_exp_handler); diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 529a44085a63..ff1cd4e1188d 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -751,9 +751,6 @@ void synchronize_rcu_expedited(void) if (exp_funnel_lock(rsp, s)) return; /* Someone else did our work for us. */ - rcu_exp_gp_seq_start(rsp); - trace_rcu_exp_grace_period(rsp->name, s, TPS("start")); - /* Initialize the rcu_node tree in preparation for the wait. */ sync_rcu_exp_select_cpus(rsp, sync_rcu_exp_handler); -- GitLab From 3b5f668e715bc19610ad967ef97a7e8c55a186ec Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 16 Mar 2016 16:47:55 -0700 Subject: [PATCH 1042/9938] rcu: Overlap wakeups with next expedited grace period The current expedited grace-period implementation makes subsequent grace periods wait on wakeups for the prior grace period. This does not fit the dictionary definition of "expedited", so this commit allows these two phases to overlap. Doing this requires four waitqueues rather than two because tasks can now be waiting on the previous, current, and next grace periods. The fourth waitqueue makes the bit masking work out nicely. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 17 ++++++++++++++--- kernel/rcu/tree.h | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index e8fff14e417b..1df100cb7a62 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -103,6 +103,7 @@ struct rcu_state sname##_state = { \ .name = RCU_STATE_NAME(sname), \ .abbr = sabbr, \ .exp_mutex = __MUTEX_INITIALIZER(sname##_state.exp_mutex), \ + .exp_wake_mutex = __MUTEX_INITIALIZER(sname##_state.exp_wake_mutex), \ } RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched); @@ -3637,7 +3638,7 @@ static bool exp_funnel_lock(struct rcu_state *rsp, unsigned long s) trace_rcu_exp_funnel_lock(rsp->name, rnp->level, rnp->grplo, rnp->grphi, TPS("wait")); - wait_event(rnp->exp_wq[(s >> 1) & 0x1], + wait_event(rnp->exp_wq[(s >> 1) & 0x3], sync_exp_work_done(rsp, &rdp->exp_workdone2, s)); return true; @@ -3857,6 +3858,14 @@ static void rcu_exp_wait_wake(struct rcu_state *rsp, unsigned long s) synchronize_sched_expedited_wait(rsp); rcu_exp_gp_seq_end(rsp); trace_rcu_exp_grace_period(rsp->name, s, TPS("end")); + + /* + * Switch over to wakeup mode, allowing the next GP, but -only- the + * next GP, to proceed. + */ + mutex_lock(&rsp->exp_wake_mutex); + mutex_unlock(&rsp->exp_mutex); + rcu_for_each_node_breadth_first(rsp, rnp) { if (ULONG_CMP_LT(READ_ONCE(rnp->exp_seq_rq), s)) { spin_lock(&rnp->exp_lock); @@ -3865,10 +3874,10 @@ static void rcu_exp_wait_wake(struct rcu_state *rsp, unsigned long s) rnp->exp_seq_rq = s; spin_unlock(&rnp->exp_lock); } - wake_up_all(&rnp->exp_wq[(rsp->expedited_sequence >> 1) & 0x1]); + wake_up_all(&rnp->exp_wq[(rsp->expedited_sequence >> 1) & 0x3]); } trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake")); - mutex_unlock(&rsp->exp_mutex); + mutex_unlock(&rsp->exp_wake_mutex); } /** @@ -4530,6 +4539,8 @@ static void __init rcu_init_one(struct rcu_state *rsp) rcu_init_one_nocb(rnp); init_waitqueue_head(&rnp->exp_wq[0]); init_waitqueue_head(&rnp->exp_wq[1]); + init_waitqueue_head(&rnp->exp_wq[2]); + init_waitqueue_head(&rnp->exp_wq[3]); spin_lock_init(&rnp->exp_lock); } } diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index f9d4fbb1e014..1194ab0da56a 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -250,7 +250,7 @@ struct rcu_node { spinlock_t exp_lock ____cacheline_internodealigned_in_smp; unsigned long exp_seq_rq; - wait_queue_head_t exp_wq[2]; + wait_queue_head_t exp_wq[4]; } ____cacheline_internodealigned_in_smp; /* @@ -502,6 +502,7 @@ struct rcu_state { /* End of fields guarded by barrier_mutex. */ struct mutex exp_mutex; /* Serialize expedited GP. */ + struct mutex exp_wake_mutex; /* Serialize wakeup. */ unsigned long expedited_sequence; /* Take a ticket. */ atomic_long_t expedited_normal; /* # fallbacks to normal. */ atomic_t expedited_need_qs; /* # CPUs left to check in. */ -- GitLab From 86057b80ae31d37fcbdb5f57d15aaf1148c69f96 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 31 Dec 2015 08:48:36 -0800 Subject: [PATCH 1043/9938] rcu: Awaken grace-period kthread when stalled Recent kernels can fail to awaken the grace-period kthread for quiescent-state forcing. This commit is a crude hack that does a wakeup any time a stall is detected. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 531a328076bd..a327a253c178 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -1224,8 +1224,10 @@ static void rcu_check_gp_kthread_starvation(struct rcu_state *rsp) rsp->gp_flags, gp_state_getname(rsp->gp_state), rsp->gp_state, rsp->gp_kthread ? rsp->gp_kthread->state : ~0); - if (rsp->gp_kthread) + if (rsp->gp_kthread) { sched_show_task(rsp->gp_kthread); + wake_up_process(rsp->gp_kthread); + } } } -- GitLab From fcfd0a237bfcf0c314005007e9d76e55a25e2bad Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 3 Jan 2016 16:42:18 -0800 Subject: [PATCH 1044/9938] rcu: Make FQS schedule advance only if FQS happened Currently, the force-quiescent-state (FQS) code in rcu_gp_kthread() can advance the next FQS even if one was not executed last time. This can happen due timeout-duration uncertainty. This commit therefore avoids advancing the FQS schedule unless an FQS was just executed. In the corner case where an FQS was not executed, but is due now, the code does a one-jiffy wait. This change prepares for kthread kicking. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index a327a253c178..6116cfad18ff 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -2146,6 +2146,15 @@ static int __noreturn rcu_gp_kthread(void *arg) TPS("fqsend")); cond_resched_rcu_qs(); WRITE_ONCE(rsp->gp_activity, jiffies); + ret = 0; /* Force full wait till next FQS. */ + j = jiffies_till_next_fqs; + if (j > HZ) { + j = HZ; + jiffies_till_next_fqs = HZ; + } else if (j < 1) { + j = 1; + jiffies_till_next_fqs = 1; + } } else { /* Deal with stray signal. */ cond_resched_rcu_qs(); @@ -2154,14 +2163,12 @@ static int __noreturn rcu_gp_kthread(void *arg) trace_rcu_grace_period(rsp->name, READ_ONCE(rsp->gpnum), TPS("fqswaitsig")); - } - j = jiffies_till_next_fqs; - if (j > HZ) { - j = HZ; - jiffies_till_next_fqs = HZ; - } else if (j < 1) { - j = 1; - jiffies_till_next_fqs = 1; + ret = 1; /* Keep old FQS timing. */ + j = jiffies; + if (time_after(jiffies, rsp->jiffies_force_qs)) + j = 1; + else + j = rsp->jiffies_force_qs - j; } } -- GitLab From 8c7c4829a81c1838f18c12ce5a3a5c29a08bf0a8 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 3 Jan 2016 20:29:57 -0800 Subject: [PATCH 1045/9938] rcu: Awaken grace-period kthread if too long since FQS Recent kernels can fail to awaken the grace-period kthread for quiescent-state forcing. This commit is a crude hack that does a wakeup if a scheduling-clock interrupt sees that it has been too long since force-quiescent-state (FQS) processing. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 39 +++++++++++++++++++++++++++++++++++++-- kernel/rcu/tree.h | 2 ++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 6116cfad18ff..a739292be605 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -385,9 +385,11 @@ module_param(qlowmark, long, 0444); static ulong jiffies_till_first_fqs = ULONG_MAX; static ulong jiffies_till_next_fqs = ULONG_MAX; +static bool rcu_kick_kthreads; module_param(jiffies_till_first_fqs, ulong, 0644); module_param(jiffies_till_next_fqs, ulong, 0644); +module_param(rcu_kick_kthreads, bool, 0644); /* * How long the grace period must be before we start recruiting @@ -1251,6 +1253,24 @@ static void rcu_dump_cpu_stacks(struct rcu_state *rsp) } } +/* + * If too much time has passed in the current grace period, and if + * so configured, go kick the relevant kthreads. + */ +static void rcu_stall_kick_kthreads(struct rcu_state *rsp) +{ + unsigned long j; + + if (!rcu_kick_kthreads) + return; + j = READ_ONCE(rsp->jiffies_kick_kthreads); + if (time_after(jiffies, j) && rsp->gp_kthread) { + WARN_ONCE(1, "Kicking %s grace-period kthread\n", rsp->name); + wake_up_process(rsp->gp_kthread); + WRITE_ONCE(rsp->jiffies_kick_kthreads, j + HZ); + } +} + static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) { int cpu; @@ -1262,6 +1282,11 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) struct rcu_node *rnp = rcu_get_root(rsp); long totqlen = 0; + /* Kick and suppress, if so configured. */ + rcu_stall_kick_kthreads(rsp); + if (rcu_cpu_stall_suppress) + return; + /* Only let one CPU complain about others per time interval. */ raw_spin_lock_irqsave_rcu_node(rnp, flags); @@ -1335,6 +1360,11 @@ static void print_cpu_stall(struct rcu_state *rsp) struct rcu_node *rnp = rcu_get_root(rsp); long totqlen = 0; + /* Kick and suppress, if so configured. */ + rcu_stall_kick_kthreads(rsp); + if (rcu_cpu_stall_suppress) + return; + /* * OK, time to rat on ourselves... * See Documentation/RCU/stallwarn.txt for info on how to debug @@ -1379,8 +1409,10 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) unsigned long js; struct rcu_node *rnp; - if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp)) + if ((rcu_cpu_stall_suppress && !rcu_kick_kthreads) || + !rcu_gp_in_progress(rsp)) return; + rcu_stall_kick_kthreads(rsp); j = jiffies; /* @@ -2119,8 +2151,11 @@ static int __noreturn rcu_gp_kthread(void *arg) } ret = 0; for (;;) { - if (!ret) + if (!ret) { rsp->jiffies_force_qs = jiffies + j; + WRITE_ONCE(rsp->jiffies_kick_kthreads, + jiffies + 3 * j); + } trace_rcu_grace_period(rsp->name, READ_ONCE(rsp->gpnum), TPS("fqswait")); diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index df668c0f9e64..34d3973f7223 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -513,6 +513,8 @@ struct rcu_state { unsigned long jiffies_force_qs; /* Time at which to invoke */ /* force_quiescent_state(). */ + unsigned long jiffies_kick_kthreads; /* Time at which to kick */ + /* kthreads, if configured. */ unsigned long n_force_qs; /* Number of calls to */ /* force_quiescent_state(). */ unsigned long n_force_qs_lh; /* ~Number of calls leaving */ -- GitLab From 293e2421fe25839500207eda123cc4475f8d17b8 Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Wed, 23 Mar 2016 23:11:48 +0800 Subject: [PATCH 1046/9938] rcu: Remove superfluous versions of rcu_read_lock_sched_held() Currently, we have four versions of rcu_read_lock_sched_held(), depending on the combined choices on PREEMPT_COUNT and DEBUG_LOCK_ALLOC. However, there is an existing function preemptible() that already distinguishes between the PREEMPT_COUNT=y and PREEMPT_COUNT=n cases, and allows these four implementations to be consolidated down to two. This commit therefore uses preemptible() to achieve this consolidation. Note that there could be a small performance regression in the case of CONFIG_DEBUG_LOCK_ALLOC=y && PREEMPT_COUNT=n. However, given the overhead associated with CONFIG_DEBUG_LOCK_ALLOC=y, this should be down in the noise. Signed-off-by: Boqun Feng Signed-off-by: Paul E. McKenney --- include/linux/rcupdate.h | 17 +---------------- kernel/rcu/update.c | 4 ++-- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 45de591657a6..5f1533e3d032 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -508,14 +508,7 @@ int rcu_read_lock_bh_held(void); * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side * critical section unless it can prove otherwise. */ -#ifdef CONFIG_PREEMPT_COUNT int rcu_read_lock_sched_held(void); -#else /* #ifdef CONFIG_PREEMPT_COUNT */ -static inline int rcu_read_lock_sched_held(void) -{ - return 1; -} -#endif /* #else #ifdef CONFIG_PREEMPT_COUNT */ #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ @@ -532,18 +525,10 @@ static inline int rcu_read_lock_bh_held(void) return 1; } -#ifdef CONFIG_PREEMPT_COUNT static inline int rcu_read_lock_sched_held(void) { - return preempt_count() != 0 || irqs_disabled(); + return !preemptible(); } -#else /* #ifdef CONFIG_PREEMPT_COUNT */ -static inline int rcu_read_lock_sched_held(void) -{ - return 1; -} -#endif /* #else #ifdef CONFIG_PREEMPT_COUNT */ - #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ #ifdef CONFIG_PROVE_RCU diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index ca828b41c938..3ccdc8eebc5a 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -67,7 +67,7 @@ static int rcu_normal_after_boot; module_param(rcu_normal_after_boot, int, 0); #endif /* #ifndef CONFIG_TINY_RCU */ -#if defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_PREEMPT_COUNT) +#ifdef CONFIG_DEBUG_LOCK_ALLOC /** * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? * @@ -111,7 +111,7 @@ int rcu_read_lock_sched_held(void) return 0; if (debug_locks) lockdep_opinion = lock_is_held(&rcu_sched_lock_map); - return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); + return lockdep_opinion || !preemptible(); } EXPORT_SYMBOL(rcu_read_lock_sched_held); #endif -- GitLab From 5dffed1e5721f6deae4fd67d32386ef037c5fc56 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 17 Feb 2016 11:54:28 -0800 Subject: [PATCH 1047/9938] rcu: Dump ftrace buffer when kicking grace-period kthread If it is necessary to kick the grace-period kthread, that is a good time to dump the trace buffer in order to learn why kicking was needed. This commit therefore does the dump. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index a739292be605..86edb92276d3 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -1266,6 +1266,7 @@ static void rcu_stall_kick_kthreads(struct rcu_state *rsp) j = READ_ONCE(rsp->jiffies_kick_kthreads); if (time_after(jiffies, j) && rsp->gp_kthread) { WARN_ONCE(1, "Kicking %s grace-period kthread\n", rsp->name); + rcu_ftrace_dump(DUMP_ALL); wake_up_process(rsp->gp_kthread); WRITE_ONCE(rsp->jiffies_kick_kthreads, j + HZ); } -- GitLab From fd35be623a1534bde57029c429b206d6c22a1ef6 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 11 Jan 2016 13:13:12 -0800 Subject: [PATCH 1048/9938] rcutorture: Update scripting to accommodate rcuperf This commit adds the scripting changes to add support for the shiny new rcuperf kernel module. Signed-off-by: Paul E. McKenney --- .../rcutorture/bin/kvm-recheck-rcuperf.sh | 82 +++++++++++++++++++ .../selftests/rcutorture/bin/kvm-recheck.sh | 5 +- tools/testing/selftests/rcutorture/bin/kvm.sh | 2 +- .../rcutorture/configs/rcuperf/CFLIST | 1 + .../rcutorture/configs/rcuperf/CFcommon | 2 + .../selftests/rcutorture/configs/rcuperf/TREE | 19 +++++ .../configs/rcuperf/ver_functions.sh | 52 ++++++++++++ 7 files changed, 161 insertions(+), 2 deletions(-) create mode 100755 tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/TREE create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh new file mode 100755 index 000000000000..e5b28174fda0 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Analyze a given results directory for rcuperf performance measurements. +# +# Usage: kvm-recheck-rcuperf.sh resdir +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2016 +# +# Authors: Paul E. McKenney + +i="$1" +if test -d $i +then + : +else + echo Unreadable results directory: $i + exit 1 +fi +. tools/testing/selftests/rcutorture/bin/functions.sh + +configfile=`echo $i | sed -e 's/^.*\///'` + +grep -e '-perf:.*writer-duration' $i/console.log | sed -e 's/^\[[^]]*]//' | +awk ' +{ + gptimes[++n] = $5 / 1000.; + sum += $5 / 1000.; +} + +END { + if (NR <= 0) { + print "No rcuperf records found???" + exit; + } + asort(gptimes); + pct50 = int(NR * 50 / 100); + if (pct50 < 1) + pct50 = 1; + pct90 = int(NR * 90 / 100); + if (pct90 < 1) + pct90 = 1; + pct99 = int(NR * 99 / 100); + if (pct99 < 1) + pct99 = 1; + div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100; + print "Histogram bucket size: " div; + last = gptimes[1] - 10; + count = 0; + for (i = 1; i <= NR; i++) { + current = div * int(gptimes[i] / div); + if (last == current) { + count++; + } else { + if (count > 0) + print last, count; + count = 1; + last = current; + } + } + if (count > 0) + print last, count; + print "Average grace-period duration: " sum / NR " microseconds"; + print "Minimum grace-period duration: " gptimes[1]; + print "50th percentile grace-period duration: " gptimes[pct50]; + print "90th percentile grace-period duration: " gptimes[pct90]; + print "99th percentile grace-period duration: " gptimes[pct99]; + print "Maximum grace-period duration: " gptimes[NR]; +}' diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh index d86bdd6b6cc2..f659346d3358 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh @@ -48,7 +48,10 @@ do cat $i/Make.oldconfig.err fi parse-build.sh $i/Make.out $configfile - parse-torture.sh $i/console.log $configfile + if test "$TORTURE_SUITE" != rcuperf + then + parse-torture.sh $i/console.log $configfile + fi parse-console.sh $i/console.log $configfile if test -r $i/Warnings then diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh index 4a431767f77a..c33cb582b3dc 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm.sh @@ -156,7 +156,7 @@ do shift ;; --torture) - checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--' + checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--' TORTURE_SUITE=$2 shift ;; diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST b/tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST new file mode 100644 index 000000000000..c9f56cf20775 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST @@ -0,0 +1 @@ +TREE diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon b/tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon new file mode 100644 index 000000000000..a09816b8c0f3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon @@ -0,0 +1,2 @@ +CONFIG_RCU_PERF_TEST=y +CONFIG_PRINTK_TIME=y diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE new file mode 100644 index 000000000000..614e107f6db5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE @@ -0,0 +1,19 @@ +CONFIG_SMP=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_LOCKING=n +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n +CONFIG_RCU_EXPERT=y diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh new file mode 100644 index 000000000000..34f2a1b35ee5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# +# Torture-suite-dependent shell functions for the rest of the scripts. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2015 +# +# Authors: Paul E. McKenney + +# rcuperf_param_nreaders bootparam-string +# +# Adds nreaders rcuperf module parameter if not already specified. +rcuperf_param_nreaders () { + if ! echo "$1" | grep -q "rcuperf.nreaders" + then + echo rcuperf.nreaders=-1 + fi +} + +# rcuperf_param_nwriters bootparam-string +# +# Adds nwriters rcuperf module parameter if not already specified. +rcuperf_param_nwriters () { + if ! echo "$1" | grep -q "rcuperf.nwriters" + then + echo rcuperf.nwriters=-1 + fi +} + +# per_version_boot_params bootparam-string config-file seconds +# +# Adds per-version torture-module parameters to kernels supporting them. +per_version_boot_params () { + echo $1 `rcuperf_param_nreaders "$1"` \ + `rcuperf_param_nwriters "$1"` \ + rcuperf.perf_runnable=1 \ + rcuperf.shutdown=1 \ + rcuperf.verbose=1 +} -- GitLab From 9efafb8849f732a3497f46f178b350c9ff7cfe27 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 31 Dec 2015 18:11:47 -0800 Subject: [PATCH 1049/9938] rcutorture: Allow for rcupdate.rcu_normal Currently, rcu_torture_writer() checks only for rcu_gp_is_expedited() when deciding whether or not to do dynamic control of RCU expediting. This means that if rcupdate.rcu_normal is specified, rcu_torture_writer() will attempt to dynamically control RCU expediting, but will nonetheless only test normal RCU grace periods. This commit therefore adds a check for !rcu_gp_is_normal(), and prints a message and desists from testing dynamic control of RCU expediting when doing so is futile. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcutorture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 463867c43221..9234e75b106a 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -916,7 +916,7 @@ rcu_torture_fqs(void *arg) static int rcu_torture_writer(void *arg) { - bool can_expedite = !rcu_gp_is_expedited(); + bool can_expedite = !rcu_gp_is_expedited() && !rcu_gp_is_normal(); int expediting = 0; unsigned long gp_snap; bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal; @@ -932,7 +932,7 @@ rcu_torture_writer(void *arg) VERBOSE_TOROUT_STRING("rcu_torture_writer task started"); if (!can_expedite) { pr_alert("%s" TORTURE_FLAG - " Grace periods expedited from boot/sysfs for %s,\n", + " GP expediting controlled from boot/sysfs for %s,\n", torture_type, cur_ops->name); pr_alert("%s" TORTURE_FLAG " Disabled dynamic grace-period expediting.\n", -- GitLab From 291783b8ad77a83a6fdf91d55eee7f1ad72ed4d1 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 Jan 2016 13:43:30 -0800 Subject: [PATCH 1050/9938] rcutorture: Expedited-GP batch progress access to torturing This commit provides rcu_exp_batches_completed() and rcu_exp_batches_completed_sched() functions to allow torture-test modules to check how many expedited grace period batches have completed. These are analogous to the existing rcu_batches_completed(), rcu_batches_completed_bh(), and rcu_batches_completed_sched() functions. Signed-off-by: Paul E. McKenney --- include/linux/rcutiny.h | 16 ++++++++++++++++ include/linux/rcutree.h | 2 ++ kernel/rcu/tree.c | 22 ++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index 64809aea661c..93aea75029fb 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -149,6 +149,22 @@ static inline unsigned long rcu_batches_completed_sched(void) return 0; } +/* + * Return the number of expedited grace periods completed. + */ +static inline unsigned long rcu_exp_batches_completed(void) +{ + return 0; +} + +/* + * Return the number of expedited sched grace periods completed. + */ +static inline unsigned long rcu_exp_batches_completed_sched(void) +{ + return 0; +} + static inline void rcu_force_quiescent_state(void) { } diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index ad1eda9fa4da..5043cb823fb2 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -87,6 +87,8 @@ unsigned long rcu_batches_started_sched(void); unsigned long rcu_batches_completed(void); unsigned long rcu_batches_completed_bh(void); unsigned long rcu_batches_completed_sched(void); +unsigned long rcu_exp_batches_completed(void); +unsigned long rcu_exp_batches_completed_sched(void); void show_rcu_gp_kthreads(void); void rcu_force_quiescent_state(void); diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 531a328076bd..88df64087dfe 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -459,6 +459,28 @@ unsigned long rcu_batches_completed_bh(void) } EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); +/* + * Return the number of RCU expedited batches completed thus far for + * debug & stats. Odd numbers mean that a batch is in progress, even + * numbers mean idle. The value returned will thus be roughly double + * the cumulative batches since boot. + */ +unsigned long rcu_exp_batches_completed(void) +{ + return rcu_state_p->expedited_sequence; +} +EXPORT_SYMBOL_GPL(rcu_exp_batches_completed); + +/* + * Return the number of RCU-sched expedited batches completed thus far + * for debug & stats. Similar to rcu_exp_batches_completed(). + */ +unsigned long rcu_exp_batches_completed_sched(void) +{ + return rcu_sched_state.expedited_sequence; +} +EXPORT_SYMBOL_GPL(rcu_exp_batches_completed_sched); + /* * Force a quiescent state. */ -- GitLab From 8704baab9bc848b58c129fed6b591bb84ec02f41 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 31 Dec 2015 18:33:22 -0800 Subject: [PATCH 1051/9938] rcutorture: Add RCU grace-period performance tests This commit adds a new rcuperf module that carries out simple performance tests of RCU grace periods. Signed-off-by: Paul E. McKenney --- kernel/rcu/Makefile | 1 + kernel/rcu/rcuperf.c | 637 +++++++++++++++++++++++++++++++++++++++++++ lib/Kconfig.debug | 33 +++ 3 files changed, 671 insertions(+) create mode 100644 kernel/rcu/rcuperf.c diff --git a/kernel/rcu/Makefile b/kernel/rcu/Makefile index 032b2c015beb..18dfc485225c 100644 --- a/kernel/rcu/Makefile +++ b/kernel/rcu/Makefile @@ -5,6 +5,7 @@ KCOV_INSTRUMENT := n obj-y += update.o sync.o obj-$(CONFIG_SRCU) += srcu.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o +obj-$(CONFIG_RCU_PERF_TEST) += rcuperf.o obj-$(CONFIG_TREE_RCU) += tree.o obj-$(CONFIG_PREEMPT_RCU) += tree.o obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c new file mode 100644 index 000000000000..9d54a57bee7d --- /dev/null +++ b/kernel/rcu/rcuperf.c @@ -0,0 +1,637 @@ +/* + * Read-Copy Update module-based performance-test facility + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. + * + * Copyright (C) IBM Corporation, 2015 + * + * Authors: Paul E. McKenney + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Paul E. McKenney "); + +#define PERF_FLAG "-perf:" +#define PERFOUT_STRING(s) \ + pr_alert("%s" PERF_FLAG s "\n", perf_type) +#define VERBOSE_PERFOUT_STRING(s) \ + do { if (verbose) pr_alert("%s" PERF_FLAG " %s\n", perf_type, s); } while (0) +#define VERBOSE_PERFOUT_ERRSTRING(s) \ + do { if (verbose) pr_alert("%s" PERF_FLAG "!!! %s\n", perf_type, s); } while (0) + +torture_param(bool, gp_exp, true, "Use expedited GP wait primitives"); +torture_param(int, nreaders, -1, "Number of RCU reader threads"); +torture_param(int, nwriters, -1, "Number of RCU updater threads"); +torture_param(bool, shutdown, false, "Shutdown at end of performance tests."); +torture_param(bool, verbose, true, "Enable verbose debugging printk()s"); + +static char *perf_type = "rcu"; +module_param(perf_type, charp, 0444); +MODULE_PARM_DESC(perf_type, "Type of RCU to performance-test (rcu, rcu_bh, ...)"); + +static int nrealreaders; +static int nrealwriters; +static struct task_struct **writer_tasks; +static struct task_struct **reader_tasks; +static struct task_struct *shutdown_task; + +static u64 **writer_durations; +static int *writer_n_durations; +static atomic_t n_rcu_perf_reader_started; +static atomic_t n_rcu_perf_writer_started; +static atomic_t n_rcu_perf_writer_finished; +static wait_queue_head_t shutdown_wq; +static u64 t_rcu_perf_writer_started; +static u64 t_rcu_perf_writer_finished; +static unsigned long b_rcu_perf_writer_started; +static unsigned long b_rcu_perf_writer_finished; + +static int rcu_perf_writer_state; +#define RTWS_INIT 0 +#define RTWS_EXP_SYNC 1 +#define RTWS_SYNC 2 +#define RTWS_IDLE 2 +#define RTWS_STOPPING 3 + +#define MAX_MEAS 10000 +#define MIN_MEAS 100 + +#if defined(MODULE) || defined(CONFIG_RCU_PERF_TEST_RUNNABLE) +#define RCUPERF_RUNNABLE_INIT 1 +#else +#define RCUPERF_RUNNABLE_INIT 0 +#endif +static int perf_runnable = RCUPERF_RUNNABLE_INIT; +module_param(perf_runnable, int, 0444); +MODULE_PARM_DESC(perf_runnable, "Start rcuperf at boot"); + +/* + * Operations vector for selecting different types of tests. + */ + +struct rcu_perf_ops { + int ptype; + void (*init)(void); + void (*cleanup)(void); + int (*readlock)(void); + void (*readunlock)(int idx); + unsigned long (*started)(void); + unsigned long (*completed)(void); + unsigned long (*exp_completed)(void); + void (*sync)(void); + void (*exp_sync)(void); + const char *name; +}; + +static struct rcu_perf_ops *cur_ops; + +/* + * Definitions for rcu perf testing. + */ + +static int rcu_perf_read_lock(void) __acquires(RCU) +{ + rcu_read_lock(); + return 0; +} + +static void rcu_perf_read_unlock(int idx) __releases(RCU) +{ + rcu_read_unlock(); +} + +static unsigned long __maybe_unused rcu_no_completed(void) +{ + return 0; +} + +static void rcu_sync_perf_init(void) +{ +} + +static struct rcu_perf_ops rcu_ops = { + .ptype = RCU_FLAVOR, + .init = rcu_sync_perf_init, + .readlock = rcu_perf_read_lock, + .readunlock = rcu_perf_read_unlock, + .started = rcu_batches_started, + .completed = rcu_batches_completed, + .exp_completed = rcu_exp_batches_completed, + .sync = synchronize_rcu, + .exp_sync = synchronize_rcu_expedited, + .name = "rcu" +}; + +/* + * Definitions for rcu_bh perf testing. + */ + +static int rcu_bh_perf_read_lock(void) __acquires(RCU_BH) +{ + rcu_read_lock_bh(); + return 0; +} + +static void rcu_bh_perf_read_unlock(int idx) __releases(RCU_BH) +{ + rcu_read_unlock_bh(); +} + +static struct rcu_perf_ops rcu_bh_ops = { + .ptype = RCU_BH_FLAVOR, + .init = rcu_sync_perf_init, + .readlock = rcu_bh_perf_read_lock, + .readunlock = rcu_bh_perf_read_unlock, + .started = rcu_batches_started_bh, + .completed = rcu_batches_completed_bh, + .exp_completed = rcu_exp_batches_completed_sched, + .sync = synchronize_rcu_bh, + .exp_sync = synchronize_rcu_bh_expedited, + .name = "rcu_bh" +}; + +/* + * Definitions for srcu perf testing. + */ + +DEFINE_STATIC_SRCU(srcu_ctl_perf); +static struct srcu_struct *srcu_ctlp = &srcu_ctl_perf; + +static int srcu_perf_read_lock(void) __acquires(srcu_ctlp) +{ + return srcu_read_lock(srcu_ctlp); +} + +static void srcu_perf_read_unlock(int idx) __releases(srcu_ctlp) +{ + srcu_read_unlock(srcu_ctlp, idx); +} + +static unsigned long srcu_perf_completed(void) +{ + return srcu_batches_completed(srcu_ctlp); +} + +static void srcu_perf_synchronize(void) +{ + synchronize_srcu(srcu_ctlp); +} + +static void srcu_perf_synchronize_expedited(void) +{ + synchronize_srcu_expedited(srcu_ctlp); +} + +static struct rcu_perf_ops srcu_ops = { + .ptype = SRCU_FLAVOR, + .init = rcu_sync_perf_init, + .readlock = srcu_perf_read_lock, + .readunlock = srcu_perf_read_unlock, + .started = NULL, + .completed = srcu_perf_completed, + .exp_completed = srcu_perf_completed, + .sync = srcu_perf_synchronize, + .exp_sync = srcu_perf_synchronize_expedited, + .name = "srcu" +}; + +/* + * Definitions for sched perf testing. + */ + +static int sched_perf_read_lock(void) +{ + preempt_disable(); + return 0; +} + +static void sched_perf_read_unlock(int idx) +{ + preempt_enable(); +} + +static struct rcu_perf_ops sched_ops = { + .ptype = RCU_SCHED_FLAVOR, + .init = rcu_sync_perf_init, + .readlock = sched_perf_read_lock, + .readunlock = sched_perf_read_unlock, + .started = rcu_batches_started_sched, + .completed = rcu_batches_completed_sched, + .exp_completed = rcu_exp_batches_completed_sched, + .sync = synchronize_sched, + .exp_sync = synchronize_sched_expedited, + .name = "sched" +}; + +#ifdef CONFIG_TASKS_RCU + +/* + * Definitions for RCU-tasks perf testing. + */ + +static int tasks_perf_read_lock(void) +{ + return 0; +} + +static void tasks_perf_read_unlock(int idx) +{ +} + +static struct rcu_perf_ops tasks_ops = { + .ptype = RCU_TASKS_FLAVOR, + .init = rcu_sync_perf_init, + .readlock = tasks_perf_read_lock, + .readunlock = tasks_perf_read_unlock, + .started = rcu_no_completed, + .completed = rcu_no_completed, + .sync = synchronize_rcu_tasks, + .exp_sync = synchronize_rcu_tasks, + .name = "tasks" +}; + +#define RCUPERF_TASKS_OPS &tasks_ops, + +static bool __maybe_unused torturing_tasks(void) +{ + return cur_ops == &tasks_ops; +} + +#else /* #ifdef CONFIG_TASKS_RCU */ + +#define RCUPERF_TASKS_OPS + +static bool __maybe_unused torturing_tasks(void) +{ + return false; +} + +#endif /* #else #ifdef CONFIG_TASKS_RCU */ + +/* + * If performance tests complete, wait for shutdown to commence. + */ +static void rcu_perf_wait_shutdown(void) +{ + cond_resched_rcu_qs(); + if (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters) + return; + while (!torture_must_stop()) + schedule_timeout_uninterruptible(1); +} + +/* + * RCU perf reader kthread. Repeatedly does empty RCU read-side + * critical section, minimizing update-side interference. + */ +static int +rcu_perf_reader(void *arg) +{ + unsigned long flags; + int idx; + + VERBOSE_PERFOUT_STRING("rcu_perf_reader task started"); + set_user_nice(current, MAX_NICE); + atomic_inc(&n_rcu_perf_reader_started); + + do { + local_irq_save(flags); + idx = cur_ops->readlock(); + cur_ops->readunlock(idx); + local_irq_restore(flags); + rcu_perf_wait_shutdown(); + } while (!torture_must_stop()); + torture_kthread_stopping("rcu_perf_reader"); + return 0; +} + +/* + * RCU perf writer kthread. Repeatedly does a grace period. + */ +static int +rcu_perf_writer(void *arg) +{ + int i = 0; + int i_max; + long me = (long)arg; + bool started = false, done = false, alldone = false; + u64 t; + u64 *wdp; + u64 *wdpp = writer_durations[me]; + + VERBOSE_PERFOUT_STRING("rcu_perf_writer task started"); + WARN_ON(rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp); + WARN_ON(rcu_gp_is_normal() && gp_exp); + WARN_ON(!wdpp); + t = ktime_get_mono_fast_ns(); + if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) { + t_rcu_perf_writer_started = t; + if (gp_exp) { + b_rcu_perf_writer_started = + cur_ops->exp_completed() / 2; + } else { + b_rcu_perf_writer_started = + cur_ops->completed(); + } + } + + do { + wdp = &wdpp[i]; + *wdp = ktime_get_mono_fast_ns(); + if (gp_exp) { + rcu_perf_writer_state = RTWS_EXP_SYNC; + cur_ops->exp_sync(); + } else { + rcu_perf_writer_state = RTWS_SYNC; + cur_ops->sync(); + } + rcu_perf_writer_state = RTWS_IDLE; + t = ktime_get_mono_fast_ns(); + *wdp = t - *wdp; + i_max = i; + if (!started && + atomic_read(&n_rcu_perf_writer_started) >= nrealwriters) + started = true; + if (!done && i >= MIN_MEAS) { + done = true; + pr_alert("%s" PERF_FLAG + "rcu_perf_writer %ld has %d measurements\n", + perf_type, me, MIN_MEAS); + if (atomic_inc_return(&n_rcu_perf_writer_finished) >= + nrealwriters) { + PERFOUT_STRING("Test complete"); + t_rcu_perf_writer_finished = t; + if (gp_exp) { + b_rcu_perf_writer_finished = + cur_ops->exp_completed() / 2; + } else { + b_rcu_perf_writer_finished = + cur_ops->completed(); + } + smp_mb(); /* Assign before wake. */ + wake_up(&shutdown_wq); + } + } + if (done && !alldone && + atomic_read(&n_rcu_perf_writer_finished) >= nrealwriters) + alldone = true; + if (started && !alldone && i < MAX_MEAS - 1) + i++; + rcu_perf_wait_shutdown(); + } while (!torture_must_stop()); + rcu_perf_writer_state = RTWS_STOPPING; + writer_n_durations[me] = i_max; + torture_kthread_stopping("rcu_perf_writer"); + return 0; +} + +static inline void +rcu_perf_print_module_parms(struct rcu_perf_ops *cur_ops, const char *tag) +{ + pr_alert("%s" PERF_FLAG + "--- %s: nreaders=%d nwriters=%d verbose=%d shutdown=%d\n", + perf_type, tag, nrealreaders, nrealwriters, verbose, shutdown); +} + +static void +rcu_perf_cleanup(void) +{ + int i; + int j; + int ngps = 0; + u64 *wdp; + u64 *wdpp; + + if (torture_cleanup_begin()) + return; + + if (reader_tasks) { + for (i = 0; i < nrealreaders; i++) + torture_stop_kthread(rcu_perf_reader, + reader_tasks[i]); + kfree(reader_tasks); + } + + if (writer_tasks) { + for (i = 0; i < nrealwriters; i++) { + torture_stop_kthread(rcu_perf_writer, + writer_tasks[i]); + if (!writer_n_durations) + continue; + j = writer_n_durations[i]; + pr_alert("%s%s writer %d gps: %d\n", + perf_type, PERF_FLAG, i, j); + ngps += j; + } + pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n", + perf_type, PERF_FLAG, + t_rcu_perf_writer_started, t_rcu_perf_writer_finished, + t_rcu_perf_writer_finished - + t_rcu_perf_writer_started, + ngps, + b_rcu_perf_writer_finished - + b_rcu_perf_writer_started); + for (i = 0; i < nrealwriters; i++) { + if (!writer_durations) + break; + if (!writer_n_durations) + continue; + wdpp = writer_durations[i]; + if (!wdpp) + continue; + for (j = 0; j <= writer_n_durations[i]; j++) { + wdp = &wdpp[j]; + pr_alert("%s%s %4d writer-duration: %5d %llu\n", + perf_type, PERF_FLAG, + i, j, *wdp); + if (j % 100 == 0) + schedule_timeout_uninterruptible(1); + } + kfree(writer_durations[i]); + } + kfree(writer_tasks); + kfree(writer_durations); + kfree(writer_n_durations); + } + + /* Do flavor-specific cleanup operations. */ + if (cur_ops->cleanup != NULL) + cur_ops->cleanup(); + + torture_cleanup_end(); +} + +/* + * Return the number if non-negative. If -1, the number of CPUs. + * If less than -1, that much less than the number of CPUs, but + * at least one. + */ +static int compute_real(int n) +{ + int nr; + + if (n >= 0) { + nr = n; + } else { + nr = num_online_cpus() + 1 + n; + if (nr <= 0) + nr = 1; + } + return nr; +} + +/* + * RCU perf shutdown kthread. Just waits to be awakened, then shuts + * down system. + */ +static int +rcu_perf_shutdown(void *arg) +{ + do { + wait_event(shutdown_wq, + atomic_read(&n_rcu_perf_writer_finished) >= + nrealwriters); + } while (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters); + smp_mb(); /* Wake before output. */ + rcu_perf_cleanup(); + kernel_power_off(); + return -EINVAL; +} + +static int __init +rcu_perf_init(void) +{ + long i; + int firsterr = 0; + static struct rcu_perf_ops *perf_ops[] = { + &rcu_ops, &rcu_bh_ops, &srcu_ops, &sched_ops, + RCUPERF_TASKS_OPS + }; + + if (!torture_init_begin(perf_type, verbose, &perf_runnable)) + return -EBUSY; + + /* Process args and tell the world that the perf'er is on the job. */ + for (i = 0; i < ARRAY_SIZE(perf_ops); i++) { + cur_ops = perf_ops[i]; + if (strcmp(perf_type, cur_ops->name) == 0) + break; + } + if (i == ARRAY_SIZE(perf_ops)) { + pr_alert("rcu-perf: invalid perf type: \"%s\"\n", + perf_type); + pr_alert("rcu-perf types:"); + for (i = 0; i < ARRAY_SIZE(perf_ops); i++) + pr_alert(" %s", perf_ops[i]->name); + pr_alert("\n"); + firsterr = -EINVAL; + goto unwind; + } + if (cur_ops->init) + cur_ops->init(); + + nrealwriters = compute_real(nwriters); + nrealreaders = compute_real(nreaders); + atomic_set(&n_rcu_perf_reader_started, 0); + atomic_set(&n_rcu_perf_writer_started, 0); + atomic_set(&n_rcu_perf_writer_finished, 0); + rcu_perf_print_module_parms(cur_ops, "Start of test"); + + /* Start up the kthreads. */ + + if (shutdown) { + init_waitqueue_head(&shutdown_wq); + firsterr = torture_create_kthread(rcu_perf_shutdown, NULL, + shutdown_task); + if (firsterr) + goto unwind; + schedule_timeout_uninterruptible(1); + } + reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]), + GFP_KERNEL); + if (reader_tasks == NULL) { + VERBOSE_PERFOUT_ERRSTRING("out of memory"); + firsterr = -ENOMEM; + goto unwind; + } + for (i = 0; i < nrealreaders; i++) { + firsterr = torture_create_kthread(rcu_perf_reader, NULL, + reader_tasks[i]); + if (firsterr) + goto unwind; + } + while (atomic_read(&n_rcu_perf_reader_started) < nrealreaders) + schedule_timeout_uninterruptible(1); + writer_tasks = kcalloc(nrealwriters, sizeof(reader_tasks[0]), + GFP_KERNEL); + writer_durations = kcalloc(nrealwriters, sizeof(*writer_durations), + GFP_KERNEL); + writer_n_durations = + kcalloc(nrealwriters, sizeof(*writer_n_durations), + GFP_KERNEL); + if (!writer_tasks || !writer_durations || !writer_n_durations) { + VERBOSE_PERFOUT_ERRSTRING("out of memory"); + firsterr = -ENOMEM; + goto unwind; + } + for (i = 0; i < nrealwriters; i++) { + writer_durations[i] = + kcalloc(MAX_MEAS, sizeof(*writer_durations[i]), + GFP_KERNEL); + if (!writer_durations[i]) + goto unwind; + firsterr = torture_create_kthread(rcu_perf_writer, (void *)i, + writer_tasks[i]); + if (firsterr) + goto unwind; + } + torture_init_end(); + return 0; + +unwind: + torture_init_end(); + rcu_perf_cleanup(); + return firsterr; +} + +module_init(rcu_perf_init); +module_exit(rcu_perf_cleanup); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1e9a607534ca..f4b797a690ba 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1289,6 +1289,39 @@ config TORTURE_TEST tristate default n +config RCU_PERF_TEST + tristate "performance tests for RCU" + depends on DEBUG_KERNEL + select TORTURE_TEST + select SRCU + select TASKS_RCU + default n + help + This option provides a kernel module that runs performance + tests on the RCU infrastructure. The kernel module may be built + after the fact on the running kernel to be tested, if desired. + + Say Y here if you want RCU performance tests to be built into + the kernel. + Say M if you want the RCU performance tests to build as a module. + Say N if you are unsure. + +config RCU_PERF_TEST_RUNNABLE + bool "performance tests for RCU runnable by default" + depends on RCU_PERF_TEST = y + default n + help + This option provides a way to build the RCU performance tests + directly into the kernel without them starting up at boot time. + You can use /sys/module to manually override this setting. + This /proc file is available only when the RCU performance + tests have been built into the kernel. + + Say Y here if you want the RCU performance tests to start during + boot (you probably don't). + Say N here if you want the RCU performance tests to start only + after being manually enabled via /sys/module. + config RCU_TORTURE_TEST tristate "torture tests for RCU" depends on DEBUG_KERNEL -- GitLab From bdea9e347783c2724997db7c5d5b45a301e2dc90 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 1 Jan 2016 13:47:19 -0800 Subject: [PATCH 1052/9938] rcutorture: Documentation for rcuperf kernel parameters This commit adds documentation for the new rcuperf module's kernel boot parameters. Signed-off-by: Paul E. McKenney --- Documentation/kernel-parameters.txt | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ecc74fa4bfde..951af481da5a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -3284,6 +3284,38 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Lazy RCU callbacks are those which RCU can prove do nothing more than free memory. + rcuperf.gp_exp= [KNL] + Measure performance of expedited synchronous + grace-period primitives. + + rcuperf.nreaders= [KNL] + Set number of RCU readers. The value -1 selects + N, where N is the number of CPUs. A value + "n" less than -1 selects N-n+1, where N is again + the number of CPUs. For example, -2 selects N + (the number of CPUs), -3 selects N+1, and so on. + A value of "n" less than or equal to -N selects + a single reader. + + rcuperf.nwriters= [KNL] + Set number of RCU writers. The values operate + the same as for rcuperf.nreaders. + N, where N is the number of CPUs + + rcuperf.perf_runnable= [BOOT] + Start rcuperf running at boot time. + + rcuperf.shutdown= [KNL] + Shut the system down after performance tests + complete. This is useful for hands-off automated + testing. + + rcuperf.perf_type= [KNL] + Specify the RCU implementation to test. + + rcuperf.verbose= [KNL] + Enable additional printk() statements. + rcutorture.cbflood_inter_holdoff= [KNL] Set holdoff time (jiffies) between successive callback-flood tests. -- GitLab From 6b558c4c7a4ba410e39dbcb9d4c2b6e928c09308 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 Jan 2016 14:15:40 -0800 Subject: [PATCH 1053/9938] rcutorture: Bind rcuperf reader/writer kthreads to CPUs This commit forces more deterministic behavior by binding rcuperf's rcu_perf_reader() and rcu_perf_writer() kthreads to their respective CPUs. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcuperf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 9d54a57bee7d..7a1edf417d18 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -328,8 +328,10 @@ rcu_perf_reader(void *arg) { unsigned long flags; int idx; + long me = (long)arg; VERBOSE_PERFOUT_STRING("rcu_perf_reader task started"); + set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids)); set_user_nice(current, MAX_NICE); atomic_inc(&n_rcu_perf_reader_started); @@ -362,6 +364,7 @@ rcu_perf_writer(void *arg) WARN_ON(rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp); WARN_ON(rcu_gp_is_normal() && gp_exp); WARN_ON(!wdpp); + set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids)); t = ktime_get_mono_fast_ns(); if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) { t_rcu_perf_writer_started = t; @@ -594,7 +597,7 @@ rcu_perf_init(void) goto unwind; } for (i = 0; i < nrealreaders; i++) { - firsterr = torture_create_kthread(rcu_perf_reader, NULL, + firsterr = torture_create_kthread(rcu_perf_reader, (void *)i, reader_tasks[i]); if (firsterr) goto unwind; -- GitLab From 2094c99558d9e9374210898f65f5862f7a2e8bed Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 Jan 2016 15:17:21 -0800 Subject: [PATCH 1054/9938] rcutorture: Set rcuperf writer kthreads to real-time priority This commit forces more deterministic update-side behavior by setting rcuperf's rcu_perf_writer() kthreads to real-time priority. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcuperf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 7a1edf417d18..e18d016a9888 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -355,6 +355,7 @@ rcu_perf_writer(void *arg) int i = 0; int i_max; long me = (long)arg; + struct sched_param sp; bool started = false, done = false, alldone = false; u64 t; u64 *wdp; @@ -365,6 +366,8 @@ rcu_perf_writer(void *arg) WARN_ON(rcu_gp_is_normal() && gp_exp); WARN_ON(!wdpp); set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids)); + sp.sched_priority = 1; + sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); t = ktime_get_mono_fast_ns(); if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) { t_rcu_perf_writer_started = t; -- GitLab From e588f35492227cc4ab2cbfe95fd5f993a5086f9f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 Jan 2016 17:26:35 -0800 Subject: [PATCH 1055/9938] rcutorture: Print measure of batching efficiency This commit adds a line giving the number of grace periods, the number of batches, and the ratio. The larger the ratio, the greater the batching efficiency. Signed-off-by: Paul E. McKenney --- .../rcutorture/bin/kvm-recheck-rcuperf.sh | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh index e5b28174fda0..1f72df8eedc7 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh @@ -34,33 +34,38 @@ fi configfile=`echo $i | sed -e 's/^.*\///'` -grep -e '-perf:.*writer-duration' $i/console.log | sed -e 's/^\[[^]]*]//' | +sed -e 's/^\[[^]]*]//' < $i/console.log | awk ' -{ +/-perf: .* gps: .* batches:/ { + ngps = $9; + nbatches = $11; +} + +/-perf: .*writer-duration/ { gptimes[++n] = $5 / 1000.; sum += $5 / 1000.; } END { - if (NR <= 0) { + newNR = asort(gptimes); + if (newNR <= 0) { print "No rcuperf records found???" exit; } - asort(gptimes); - pct50 = int(NR * 50 / 100); + pct50 = int(newNR * 50 / 100); if (pct50 < 1) pct50 = 1; - pct90 = int(NR * 90 / 100); + pct90 = int(newNR * 90 / 100); if (pct90 < 1) pct90 = 1; - pct99 = int(NR * 99 / 100); + pct99 = int(newNR * 99 / 100); if (pct99 < 1) pct99 = 1; div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100; print "Histogram bucket size: " div; last = gptimes[1] - 10; count = 0; - for (i = 1; i <= NR; i++) { + for (i = 1; i <= newNR; i++) { current = div * int(gptimes[i] / div); if (last == current) { count++; @@ -73,10 +78,11 @@ END { } if (count > 0) print last, count; - print "Average grace-period duration: " sum / NR " microseconds"; + print "Average grace-period duration: " sum / newNR " microseconds"; print "Minimum grace-period duration: " gptimes[1]; print "50th percentile grace-period duration: " gptimes[pct50]; print "90th percentile grace-period duration: " gptimes[pct90]; print "99th percentile grace-period duration: " gptimes[pct99]; - print "Maximum grace-period duration: " gptimes[NR]; + print "Maximum grace-period duration: " gptimes[newNR]; + print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches; }' -- GitLab From ac2bb275e8e5abddb0815ff2b7aa383ed6d007a4 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 29 Jan 2016 14:58:17 -0800 Subject: [PATCH 1056/9938] rcutorture: Make rcuperf collect expedited event-trace data This commit enables ftrace in the rcuperf TREE kernel build and adds an ftrace_dump() at the end of rcuperf processing. This data will be used to measure the actual durations of the expedited grace periods without the added delays inherent in the kernel-module measurements. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcuperf.c | 1 + tools/testing/selftests/rcutorture/configs/rcuperf/TREE | 1 + 2 files changed, 2 insertions(+) diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index e18d016a9888..12561f96f0a2 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -404,6 +404,7 @@ rcu_perf_writer(void *arg) perf_type, me, MIN_MEAS); if (atomic_inc_return(&n_rcu_perf_writer_finished) >= nrealwriters) { + rcu_ftrace_dump(DUMP_ALL); PERFOUT_STRING("Test complete"); t_rcu_perf_writer_finished = t; if (gp_exp) { diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE index 614e107f6db5..a312f671a29a 100644 --- a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE +++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE @@ -17,3 +17,4 @@ CONFIG_PROVE_LOCKING=n CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y +CONFIG_RCU_TRACE=y -- GitLab From 2b03d038457fc8d694d34981cb0a2f1702ba35d6 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 30 Jan 2016 16:51:36 -0800 Subject: [PATCH 1057/9938] rcutorture: Make scripts analyze rcuperf trace data, if present The rcuperf event-trace data is more accurate than are the rcuperf printk()s because locking keeps things ordered. This commit therefore parses and analyzes this event-trace data if present, and falls back on the printk()s otherwise. Signed-off-by: Paul E. McKenney --- .../bin/kvm-recheck-rcuperf-ftrace.sh | 121 ++++++++++++++++++ .../rcutorture/bin/kvm-recheck-rcuperf.sh | 8 ++ 2 files changed, 129 insertions(+) create mode 100755 tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh new file mode 100755 index 000000000000..f79b0e9e84fc --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# +# Analyze a given results directory for rcuperf performance measurements, +# looking for ftrace data. Exits with 0 if data was found, analyzed, and +# printed. Intended to be invoked from kvm-recheck-rcuperf.sh after +# argument checking. +# +# Usage: kvm-recheck-rcuperf-ftrace.sh resdir +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2016 +# +# Authors: Paul E. McKenney + +i="$1" +. tools/testing/selftests/rcutorture/bin/functions.sh + +if test "`grep -c 'rcu_exp_grace_period.*start' < $i/console.log`" -lt 100 +then + exit 10 +fi + +sed -e 's/^\[[^]]*]//' < $i/console.log | +grep 'us : rcu_exp_grace_period' | +sed -e 's/us : / : /' | +tr -d '\015' | +awk ' +$8 == "start" { + if (starttask != "") + nlost++; + starttask = $1; + starttime = $3; + startseq = $7; +} + +$8 == "end" { + if (starttask == $1 && startseq == $7) { + curgpdur = $3 - starttime; + gptimes[++n] = curgpdur; + gptaskcnt[starttask]++; + sum += curgpdur; + if (curgpdur > 1000) + print "Long GP " starttime "us to " $3 "us (" curgpdur "us)"; + starttask = ""; + } else { + # Lost a message or some such, reset. + starttask = ""; + nlost++; + } +} + +$8 == "done" { + piggybackcnt[$1]++; +} + +END { + newNR = asort(gptimes); + if (newNR <= 0) { + print "No ftrace records found???" + exit 10; + } + pct50 = int(newNR * 50 / 100); + if (pct50 < 1) + pct50 = 1; + pct90 = int(newNR * 90 / 100); + if (pct90 < 1) + pct90 = 1; + pct99 = int(newNR * 99 / 100); + if (pct99 < 1) + pct99 = 1; + div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100; + print "Histogram bucket size: " div; + last = gptimes[1] - 10; + count = 0; + for (i = 1; i <= newNR; i++) { + current = div * int(gptimes[i] / div); + if (last == current) { + count++; + } else { + if (count > 0) + print last, count; + count = 1; + last = current; + } + } + if (count > 0) + print last, count; + print "Distribution of grace periods across tasks:"; + for (i in gptaskcnt) { + print "\t" i, gptaskcnt[i]; + nbatches += gptaskcnt[i]; + } + ngps = nbatches; + print "Distribution of piggybacking across tasks:"; + for (i in piggybackcnt) { + print "\t" i, piggybackcnt[i]; + ngps += piggybackcnt[i]; + } + print "Average grace-period duration: " sum / newNR " microseconds"; + print "Minimum grace-period duration: " gptimes[1]; + print "50th percentile grace-period duration: " gptimes[pct50]; + print "90th percentile grace-period duration: " gptimes[pct90]; + print "99th percentile grace-period duration: " gptimes[pct99]; + print "Maximum grace-period duration: " gptimes[newNR]; + print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches " Lost: " nlost + 0; + print "Computed from ftrace data."; +}' +exit 0 diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh index 1f72df8eedc7..8f3121afc716 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh @@ -30,8 +30,15 @@ else echo Unreadable results directory: $i exit 1 fi +PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH . tools/testing/selftests/rcutorture/bin/functions.sh +if kvm-recheck-rcuperf-ftrace.sh $i +then + # ftrace data was successfully analyzed, call it good! + exit 0 +fi + configfile=`echo $i | sed -e 's/^.*\///'` sed -e 's/^\[[^]]*]//' < $i/console.log | @@ -85,4 +92,5 @@ END { print "99th percentile grace-period duration: " gptimes[pct99]; print "Maximum grace-period duration: " gptimes[newNR]; print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches; + print "Computed from rcuperf printk output."; }' -- GitLab From df37e66bfdbb57e8cae7dbf39a0c66b1b8701338 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 30 Jan 2016 20:56:38 -0800 Subject: [PATCH 1058/9938] rcutorture: Add rcuperf holdoff boot parameter to reduce interference Boot-time activity can legitimately grab CPUs for extended time periods, so the commit adds a boot parameter to delay the start of the performance test until boot has completed. Defaults to 10 seconds. Signed-off-by: Paul E. McKenney --- Documentation/kernel-parameters.txt | 6 ++++++ kernel/rcu/rcuperf.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 951af481da5a..da9ee466789b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -3288,6 +3288,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Measure performance of expedited synchronous grace-period primitives. + rcuperf.holdoff= [KNL] + Set test-start holdoff period. The purpose of + this parameter is to delay the start of the + test until boot completes in order to avoid + interference. + rcuperf.nreaders= [KNL] Set number of RCU readers. The value -1 selects N, where N is the number of CPUs. A value diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 12561f96f0a2..278600143bb6 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -59,6 +59,7 @@ MODULE_AUTHOR("Paul E. McKenney "); do { if (verbose) pr_alert("%s" PERF_FLAG "!!! %s\n", perf_type, s); } while (0) torture_param(bool, gp_exp, true, "Use expedited GP wait primitives"); +torture_param(int, holdoff, 10, "Holdoff time before test start (s)"); torture_param(int, nreaders, -1, "Number of RCU reader threads"); torture_param(int, nwriters, -1, "Number of RCU updater threads"); torture_param(bool, shutdown, false, "Shutdown at end of performance tests."); @@ -368,6 +369,10 @@ rcu_perf_writer(void *arg) set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids)); sp.sched_priority = 1; sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); + + if (holdoff) + schedule_timeout_uninterruptible(holdoff * HZ); + t = ktime_get_mono_fast_ns(); if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) { t_rcu_perf_writer_started = t; -- GitLab From 620316e52a923811fe9a77ceb43eebf5f507d375 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 30 Jan 2016 21:32:09 -0800 Subject: [PATCH 1059/9938] rcutorture: Avoid RCU CPU stall warning and RT throttling Running rcuperf can result in RCU CPU stall warnings and RT throttling. These occur because on of the real-time writer processes does ftrace_dump() while still running at real-time priority. This commit therefore prevents these problems by setting the writer thread back to SCHED_NORMAL (AKA SCHED_OTHER) before doing ftrace_dump(). In addition, this commit adds a small fixed delay before dumping ftrace buffer in order to decrease the probability that this dumping will interfere with other writers' grace periods. Signed-off-by: Paul E. McKenney --- kernel/rcu/rcuperf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 278600143bb6..4c0572859ff0 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -404,11 +404,15 @@ rcu_perf_writer(void *arg) started = true; if (!done && i >= MIN_MEAS) { done = true; + sp.sched_priority = 0; + sched_setscheduler_nocheck(current, + SCHED_NORMAL, &sp); pr_alert("%s" PERF_FLAG "rcu_perf_writer %ld has %d measurements\n", perf_type, me, MIN_MEAS); if (atomic_inc_return(&n_rcu_perf_writer_finished) >= nrealwriters) { + schedule_timeout_interruptible(10); rcu_ftrace_dump(DUMP_ALL); PERFOUT_STRING("Test complete"); t_rcu_perf_writer_finished = t; -- GitLab From dba6f1bab8920a6f78b0dc21976afdecf82fba3f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 1 Feb 2016 16:39:38 -0800 Subject: [PATCH 1060/9938] rcutorture: Add largish-system rcuperf scenario This commit adds an rcuperf scenario named TREE54 that uses 54 CPUs and provides a four-level rcu_node combining tree. Signed-off-by: Paul E. McKenney --- .../rcutorture/configs/rcuperf/TREE54 | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tools/testing/selftests/rcutorture/configs/rcuperf/TREE54 diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54 b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54 new file mode 100644 index 000000000000..985fb170d13c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54 @@ -0,0 +1,23 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=54 +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_FAST_NO_HZ=n +CONFIG_RCU_TRACE=n +CONFIG_HOTPLUG_CPU=n +CONFIG_SUSPEND=n +CONFIG_HIBERNATION=n +CONFIG_RCU_FANOUT=3 +CONFIG_RCU_FANOUT_LEAF=2 +CONFIG_RCU_NOCB_CPU=n +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_PROVE_LOCKING=n +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n +CONFIG_RCU_EXPERT=y +CONFIG_RCU_TRACE=y -- GitLab From e6fb1fc1085e5b5155bc8f3d3385c48b8bdde95e Mon Sep 17 00:00:00 2001 From: Artem Savkov Date: Sun, 7 Feb 2016 13:31:39 +0100 Subject: [PATCH 1061/9938] rcuperf: Do not wake up shutdown wait queue if "shutdown" is false. After finishing its tests rcuperf tries to wake up shutdown_wq even if "shutdown" param is set to false, resulting in a wake_up() call on an unitialized wait_queue_head_t which leads to "BUG: spinlock bad magic" and "BUG: unable to handle kernel NULL pointer dereference". Fix by checking "shutdown" param before waking up the queue. Signed-off-by: Artem Savkov --- kernel/rcu/rcuperf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 4c0572859ff0..3cee0d8393ed 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -423,8 +423,10 @@ rcu_perf_writer(void *arg) b_rcu_perf_writer_finished = cur_ops->completed(); } - smp_mb(); /* Assign before wake. */ - wake_up(&shutdown_wq); + if (shutdown) { + smp_mb(); /* Assign before wake. */ + wake_up(&shutdown_wq); + } } } if (done && !alldone && -- GitLab From 67522beecfc75d133514dda64107ee19125a74b9 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 1 Mar 2016 08:52:19 -0800 Subject: [PATCH 1062/9938] rcutorture: Remove redundant initialization to zero The current code initializes the global per-CPU variables rcu_torture_count and rcu_torture_batch to zero. However, C does this initialization by default, and explicit initialization of per-CPU variables now needs a different syntax if "make tags" is to work. This commit therefore removes the initialization. Reported-by: Peter Zijlstra Signed-off-by: Paul E. McKenney --- kernel/rcu/rcutorture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 9234e75b106a..52b49fe90919 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -130,8 +130,8 @@ static struct rcu_torture __rcu *rcu_torture_current; static unsigned long rcu_torture_current_version; static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN]; static DEFINE_SPINLOCK(rcu_torture_lock); -static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) = { 0 }; -static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) = { 0 }; +static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count); +static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch); static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1]; static atomic_t n_rcu_torture_alloc; static atomic_t n_rcu_torture_alloc_fail; -- GitLab From de26ca19a530d2d822a6816834d22022e94b2e53 Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Thu, 17 Mar 2016 11:14:35 +0100 Subject: [PATCH 1063/9938] rcutorture: Consider FROZEN hotplug notifier transitions The hotplug notifier rcutorture_cpu_notify() doesn't consider the corresponding CPU_XXX_FROZEN transitions. They occur on suspend/resume and are usually handled the same way as the corresponding non frozen transitions. Mask the switch case action argument with '~CPU_TASKS_FROZEN' to map CPU_XXX_FROZEN hotplug transitions on corresponding non-frozen transitions. Cc: Josh Triplett Cc: "Paul E. McKenney" Signed-off-by: Anna-Maria Gleixner Signed-off-by: Paul E. McKenney --- kernel/rcu/rcutorture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 52b49fe90919..633a68a09440 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -1585,7 +1585,7 @@ static int rcutorture_cpu_notify(struct notifier_block *self, { long cpu = (long)hcpu; - switch (action) { + switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: case CPU_DOWN_FAILED: (void)rcutorture_booster_init(cpu); -- GitLab From 9eb5188a0704bd21eb7e4aef83b904fad43d3ec8 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 21 Mar 2016 15:36:40 -0700 Subject: [PATCH 1064/9938] torture: Clarify refusal to run more than one torture test This commit clarifies error messages -- you only get to run one torture test at a time! Signed-off-by: Paul E. McKenney --- kernel/torture.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/torture.c b/kernel/torture.c index 44aa462d033f..e912ccd960f0 100644 --- a/kernel/torture.c +++ b/kernel/torture.c @@ -602,8 +602,9 @@ bool torture_init_begin(char *ttype, bool v, int *runnable) { mutex_lock(&fullstop_mutex); if (torture_type != NULL) { - pr_alert("torture_init_begin: refusing %s init: %s running", + pr_alert("torture_init_begin: Refusing %s init: %s running.\n", ttype, torture_type); + pr_alert("torture_init_begin: One torture test at a time!\n"); mutex_unlock(&fullstop_mutex); return false; } -- GitLab From fb2c66af10f92bc83659c4d8a32e02287f0e5dda Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 28 Mar 2016 14:44:42 -0700 Subject: [PATCH 1065/9938] torture: Kill qemu, not parent process The current hang-check machinery in the rcutorture scripts uses "$!" of a parenthesized bash statement to capture the pid. Unfortunately, this captures not qemu's pid, but rather that of its parent that implements the parenthesized statement. This commit therefore adjusts things so as to capture qemu's actual pid, which then allows the script to actually kill qemu in event of a kernel hang. Signed-off-by: Paul E. McKenney --- .../rcutorture/bin/kvm-test-1-run.sh | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh index 0f80eefb0bfd..2eb8fefbe7d9 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh @@ -168,14 +168,25 @@ then fi echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd -( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) & -qemu_pid=$! +( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) & commandcompleted=0 -echo Monitoring qemu job at pid $qemu_pid +sleep 10 # Give qemu's pid a chance to reach the file +if test -s "$resdir/qemu_pid" +then + qemu_pid=`cat "$resdir/qemu_pid"` + echo Monitoring qemu job at pid $qemu_pid +else + qemu_pid="" + echo Monitoring qemu job at yet-as-unknown pid +fi while : do + if test -z "$qemu_pid" -a -s "$resdir/qemu_pid" + then + qemu_pid=`cat "$resdir/qemu_pid"` + fi kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` - if kill -0 $qemu_pid > /dev/null 2>&1 + if test -z "$qemu_pid" || kill -0 "$qemu_pid" > /dev/null 2>&1 then if test $kruntime -ge $seconds then @@ -195,12 +206,16 @@ do ps -fp $killpid >> $resdir/Warnings 2>&1 fi else - echo ' ---' `date`: Kernel done + echo ' ---' `date`: "Kernel done" fi break fi done -if test $commandcompleted -eq 0 +if test -z "$qemu_pid" -a -s "$resdir/qemu_pid" +then + qemu_pid=`cat "$resdir/qemu_pid"` +fi +if test $commandcompleted -eq 0 -a -n "$qemu_pid" then echo Grace period for qemu job at pid $qemu_pid while : @@ -220,6 +235,9 @@ then fi sleep 1 done +elif test -z "$qemu_pid" +then + echo Unknown PID, cannot kill qemu command fi parse-torture.sh $resdir/console.log $title -- GitLab From 480b1eb659f65be8ed039f1a9db3f762c41c9770 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 29 Mar 2016 10:50:38 -0700 Subject: [PATCH 1066/9938] rcutorture: Convert test duration to seconds early This commit converts test duration from minutes to seconds early on in order to prepare for upcoming OS-jitter-injection changes. Signed-off-by: Paul E. McKenney --- tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh | 5 ++--- tools/testing/selftests/rcutorture/bin/kvm.sh | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh index 2eb8fefbe7d9..73a265668421 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh @@ -6,7 +6,7 @@ # Execute this in the source tree. Do not run it as a background task # because qemu does not seem to like that much. # -# Usage: kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args +# Usage: kvm-test-1-run.sh config builddir resdir seconds qemu-args boot_args # # qemu-args defaults to "-enable-kvm -soundhw pcspk -nographic", along with # arguments specifying the number of CPUs and other @@ -123,8 +123,7 @@ while test -f $builddir.ready do sleep 1 done -minutes=$4 -seconds=$(($minutes * 60)) +seconds=$4 qemu_args=$5 boot_args=$6 diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh index c33cb582b3dc..704e219f67a7 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm.sh @@ -34,7 +34,7 @@ T=/tmp/kvm.sh.$$ trap 'rm -rf $T' 0 mkdir $T -dur=30 +dur=$((30*60)) dryrun="" KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM PATH=${KVM}/bin:$PATH; export PATH @@ -116,7 +116,7 @@ do ;; --duration) checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error' - dur=$2 + dur=$(($2*60)) shift ;; --interactive) -- GitLab From 2ed94f6fde066fb37bc3553b786edb805561699e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 31 Mar 2016 10:18:09 -0700 Subject: [PATCH 1067/9938] regmap: mmio: Explicitly say little endian is the defualt in the bus config Otherwise the DT parsing will default to big endian if nothing is specified. Reported-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-mmio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 7526906ca080..1aa26aa31f6a 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -212,6 +212,7 @@ static const struct regmap_bus regmap_mmio = { .reg_write = regmap_mmio_write, .reg_read = regmap_mmio_read, .free_context = regmap_mmio_free_context, + .val_format_endian_default = REGMAP_ENDIAN_LITTLE, }; static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, -- GitLab From 5ba10dd4a1727714faaac9a48f6aa69d8ee33248 Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 31 Mar 2016 18:00:55 +0200 Subject: [PATCH 1068/9938] ASoC: sti: correct typo errors Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- .../bindings/sound/st,sti-asoc-card.txt | 4 ++-- sound/soc/sti/uniperif.h | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt index 028fa1c82f50..f546dd914812 100644 --- a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt @@ -65,7 +65,7 @@ Example: reg = <0x8D82000 0x158>; interrupts = ; dmas = <&fdma0 4 0 1>; - dai-name = "Uni Player #1 (DAC)"; + dai-name = "Uni Player #2 (DAC)"; dma-names = "tx"; uniperiph-id = <2>; version = <5>; @@ -82,7 +82,7 @@ Example: interrupts = ; dmas = <&fdma0 7 0 1>; dma-names = "tx"; - dai-name = "Uni Player #1 (PIO)"; + dai-name = "Uni Player #3 (SPDIF)"; uniperiph-id = <3>; version = <5>; mode = "SPDIF"; diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index f0fd5a9944e9..1f82faafb869 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -25,7 +25,7 @@ writel_relaxed((((value) & mask) << shift), ip->base + offset) /* - * AUD_UNIPERIF_SOFT_RST reg + * UNIPERIF_SOFT_RST reg */ #define UNIPERIF_SOFT_RST_OFFSET(ip) 0x0000 @@ -50,7 +50,7 @@ UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip)) /* - * AUD_UNIPERIF_FIFO_DATA reg + * UNIPERIF_FIFO_DATA reg */ #define UNIPERIF_FIFO_DATA_OFFSET(ip) 0x0004 @@ -58,7 +58,7 @@ writel_relaxed(value, ip->base + UNIPERIF_FIFO_DATA_OFFSET(ip)) /* - * AUD_UNIPERIF_CHANNEL_STA_REGN reg + * UNIPERIF_CHANNEL_STA_REGN reg */ #define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) @@ -105,7 +105,7 @@ writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip)) /* - * AUD_UNIPERIF_ITS reg + * UNIPERIF_ITS reg */ #define UNIPERIF_ITS_OFFSET(ip) 0x000C @@ -143,7 +143,7 @@ 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip)))) /* - * AUD_UNIPERIF_ITS_BCLR reg + * UNIPERIF_ITS_BCLR reg */ /* FIFO_ERROR */ @@ -160,7 +160,7 @@ writel_relaxed(value, ip->base + UNIPERIF_ITS_BCLR_OFFSET(ip)) /* - * AUD_UNIPERIF_ITM reg + * UNIPERIF_ITM reg */ #define UNIPERIF_ITM_OFFSET(ip) 0x0018 @@ -188,7 +188,7 @@ 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip)))) /* - * AUD_UNIPERIF_ITM_BCLR reg + * UNIPERIF_ITM_BCLR reg */ #define UNIPERIF_ITM_BCLR_OFFSET(ip) 0x001c @@ -213,7 +213,7 @@ UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip)) /* - * AUD_UNIPERIF_ITM_BSET reg + * UNIPERIF_ITM_BSET reg */ #define UNIPERIF_ITM_BSET_OFFSET(ip) 0x0020 @@ -767,7 +767,7 @@ SET_UNIPERIF_REG(ip, \ UNIPERIF_CTRL_OFFSET(ip), \ UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \ - CORAUD_UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1) + UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1) /* UNDERFLOW_REC_WINDOW */ #define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip) 20 @@ -1046,7 +1046,7 @@ UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip), value) /* - * AUD_UNIPERIF_CHANNEL_STA_REGN reg + * UNIPERIF_CHANNEL_STA_REGN reg */ #define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) @@ -1057,7 +1057,7 @@ UNIPERIF_CHANNEL_STA_REGN(ip, n)) /* - * AUD_UNIPERIF_USER_VALIDITY reg + * UNIPERIF_USER_VALIDITY reg */ #define UNIPERIF_USER_VALIDITY_OFFSET(ip) 0x0090 -- GitLab From 423de92f56bdfc3e68503af31e6ec041d59a6a25 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 24 Mar 2016 10:38:04 +0200 Subject: [PATCH 1069/9938] mei: bus: use scnprintf in *_show There's no reason to duplicate the logic provided by scnprintf(). Signed-off-by: Rasmus Villemoes Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 5d5996e39a67..04dc05150898 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -634,11 +634,8 @@ static ssize_t name_show(struct device *dev, struct device_attribute *a, char *buf) { struct mei_cl_device *cldev = to_mei_cl_device(dev); - size_t len; - len = snprintf(buf, PAGE_SIZE, "%s", cldev->name); - - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; + return scnprintf(buf, PAGE_SIZE, "%s", cldev->name); } static DEVICE_ATTR_RO(name); @@ -647,11 +644,8 @@ static ssize_t uuid_show(struct device *dev, struct device_attribute *a, { struct mei_cl_device *cldev = to_mei_cl_device(dev); const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); - size_t len; - - len = snprintf(buf, PAGE_SIZE, "%pUl", uuid); - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; + return scnprintf(buf, PAGE_SIZE, "%pUl", uuid); } static DEVICE_ATTR_RO(uuid); @@ -660,11 +654,8 @@ static ssize_t version_show(struct device *dev, struct device_attribute *a, { struct mei_cl_device *cldev = to_mei_cl_device(dev); u8 version = mei_me_cl_ver(cldev->me_cl); - size_t len; - - len = snprintf(buf, PAGE_SIZE, "%02X", version); - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; + return scnprintf(buf, PAGE_SIZE, "%02X", version); } static DEVICE_ATTR_RO(version); @@ -673,10 +664,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, { struct mei_cl_device *cldev = to_mei_cl_device(dev); const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); - size_t len; - len = snprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid); - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; + return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid); } static DEVICE_ATTR_RO(modalias); -- GitLab From 40bbd191fc808dcd0ef154a6c8af8dd66d3c1270 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 31 Mar 2016 11:47:57 +0900 Subject: [PATCH 1070/9938] ARM: dts: exynos: Add initial pin configuration for exynos3250-rinato This patch adds initial pin configuration using pinctrl subsystem to reduce leakage power-consumption of gpio pins in normal state. All pins included in this patch are NC (not connected) pin. Signed-off-by: Chanwoo Choi Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos3250-pinctrl.dtsi | 38 ++++++++++++ arch/arm/boot/dts/exynos3250-rinato.dts | 71 ++++++++++++++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi b/arch/arm/boot/dts/exynos3250-pinctrl.dtsi index 5ab81c39e2c9..ecf79386e891 100644 --- a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos3250-pinctrl.dtsi @@ -16,11 +16,49 @@ #define PIN_PULL_DOWN 1 #define PIN_PULL_UP 3 +#define PIN_DRV_LV1 0 +#define PIN_DRV_LV2 2 +#define PIN_DRV_LV3 1 +#define PIN_DRV_LV4 3 + #define PIN_PDN_OUT0 0 #define PIN_PDN_OUT1 1 #define PIN_PDN_INPUT 2 #define PIN_PDN_PREV 3 +#define PIN_IN(_pin, _pull, _drv) \ + _pin { \ + samsung,pins = #_pin; \ + samsung,pin-function = <0>; \ + samsung,pin-pud = ; \ + samsung,pin-drv = ; \ + } + +#define PIN_OUT(_pin, _drv) \ + _pin { \ + samsung,pins = #_pin; \ + samsung,pin-function = <1>; \ + samsung,pin-pud = <0>; \ + samsung,pin-drv = ; \ + } + +#define PIN_OUT_SET(_pin, _val, _drv) \ + _pin { \ + samsung,pins = #_pin; \ + samsung,pin-function = <1>; \ + samsung,pin-pud = <0>; \ + samsung,pin-drv = ; \ + samsung,pin-val = <_val>; \ + } + +#define PIN_CFG(_pin, _sel, _pull, _drv) \ + _pin { \ + samsung,pins = #_pin; \ + samsung,pin-function = <_sel>; \ + samsung,pin-pud = ; \ + samsung,pin-drv = ; \ + } + #define PIN_SLP(_pin, _mode, _pull) \ _pin { \ samsung,pins = #_pin; \ diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index 1f102f3a1ab1..31eb09bae0a2 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -681,7 +681,21 @@ &pinctrl_0 { pinctrl-names = "default"; - pinctrl-0 = <&sleep0>; + pinctrl-0 = <&initial0 &sleep0>; + + initial0: initial-state { + PIN_IN(gpa1-4, DOWN, LV1); + PIN_IN(gpa1-5, DOWN, LV1); + + PIN_IN(gpc0-0, DOWN, LV1); + PIN_IN(gpc0-1, DOWN, LV1); + PIN_IN(gpc0-2, DOWN, LV1); + PIN_IN(gpc0-3, DOWN, LV1); + PIN_IN(gpc0-4, DOWN, LV1); + + PIN_IN(gpd0-0, DOWN, LV1); + PIN_IN(gpd0-1, DOWN, LV1); + }; sleep0: sleep-state { PIN_SLP(gpa0-0, INPUT, DOWN); @@ -735,7 +749,60 @@ &pinctrl_1 { pinctrl-names = "default"; - pinctrl-0 = <&sleep1>; + pinctrl-0 = <&initial1 &sleep1>; + + initial1: initial-state { + PIN_IN(gpe0-6, DOWN, LV1); + PIN_IN(gpe0-7, DOWN, LV1); + + PIN_IN(gpe1-0, DOWN, LV1); + PIN_IN(gpe1-3, DOWN, LV1); + PIN_IN(gpe1-4, DOWN, LV1); + PIN_IN(gpe1-5, DOWN, LV1); + PIN_IN(gpe1-6, DOWN, LV1); + + PIN_IN(gpk2-0, DOWN, LV1); + PIN_IN(gpk2-1, DOWN, LV1); + PIN_IN(gpk2-2, DOWN, LV1); + PIN_IN(gpk2-3, DOWN, LV1); + PIN_IN(gpk2-4, DOWN, LV1); + PIN_IN(gpk2-5, DOWN, LV1); + PIN_IN(gpk2-6, DOWN, LV1); + + PIN_IN(gpm0-0, DOWN, LV1); + PIN_IN(gpm0-1, DOWN, LV1); + PIN_IN(gpm0-2, DOWN, LV1); + PIN_IN(gpm0-3, DOWN, LV1); + PIN_IN(gpm0-4, DOWN, LV1); + PIN_IN(gpm0-5, DOWN, LV1); + PIN_IN(gpm0-6, DOWN, LV1); + PIN_IN(gpm0-7, DOWN, LV1); + + PIN_IN(gpm1-0, DOWN, LV1); + PIN_IN(gpm1-1, DOWN, LV1); + PIN_IN(gpm1-2, DOWN, LV1); + PIN_IN(gpm1-3, DOWN, LV1); + PIN_IN(gpm1-4, DOWN, LV1); + PIN_IN(gpm1-5, DOWN, LV1); + PIN_IN(gpm1-6, DOWN, LV1); + + PIN_IN(gpm2-0, DOWN, LV1); + PIN_IN(gpm2-1, DOWN, LV1); + + PIN_IN(gpm3-0, DOWN, LV1); + PIN_IN(gpm3-1, DOWN, LV1); + PIN_IN(gpm3-2, DOWN, LV1); + PIN_IN(gpm3-3, DOWN, LV1); + PIN_IN(gpm3-4, DOWN, LV1); + + PIN_IN(gpm4-1, DOWN, LV1); + PIN_IN(gpm4-2, DOWN, LV1); + PIN_IN(gpm4-3, DOWN, LV1); + PIN_IN(gpm4-4, DOWN, LV1); + PIN_IN(gpm4-5, DOWN, LV1); + PIN_IN(gpm4-6, DOWN, LV1); + PIN_IN(gpm4-7, DOWN, LV1); + }; sleep1: sleep-state { PIN_SLP(gpe0-0, PREV, NONE); -- GitLab From d278c808f52a5fdbdd93deb3636ea9558e56ffb7 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 31 Mar 2016 11:48:02 +0900 Subject: [PATCH 1071/9938] ARM: dts: exynos: Add initial gpio setting of MMC2 device for exynos3250-monk This patch adds initial pin configuration of MMC2 device on exynos3250-monk board because the MMC2 gpio pin (gpk2[0-6]) are NC (not connected) state. Suggested-by: Krzysztof Kozlowski Signed-off-by: Chanwoo Choi Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos3250-monk.dts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/exynos3250-monk.dts index 9e2840b59ae8..267f81adb42f 100644 --- a/arch/arm/boot/dts/exynos3250-monk.dts +++ b/arch/arm/boot/dts/exynos3250-monk.dts @@ -558,7 +558,17 @@ &pinctrl_1 { pinctrl-names = "default"; - pinctrl-0 = <&sleep1>; + pinctrl-0 = <&initial1 &sleep1>; + + initial1: initial-state { + PIN_IN(gpk2-0, DOWN, LV1); + PIN_IN(gpk2-1, DOWN, LV1); + PIN_IN(gpk2-2, DOWN, LV1); + PIN_IN(gpk2-3, DOWN, LV1); + PIN_IN(gpk2-4, DOWN, LV1); + PIN_IN(gpk2-5, DOWN, LV1); + PIN_IN(gpk2-6, DOWN, LV1); + }; sleep1: sleep-state { PIN_SLP(gpe0-0, PREV, NONE); -- GitLab From ecaba514f4cb74fb076ac99be4719fb8cd9d584a Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Thu, 31 Mar 2016 11:48:01 +0900 Subject: [PATCH 1072/9938] ARM: dts: exynos: Add UART2 DT node for Exynos3250 SoC This patch add the UART2 Device Tree node for Exynos3250 SoC. Signed-off-by: Pankaj Dubey Signed-off-by: Chanwoo Choi Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos3250-pinctrl.dtsi | 7 +++++++ arch/arm/boot/dts/exynos3250.dtsi | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi b/arch/arm/boot/dts/exynos3250-pinctrl.dtsi index ecf79386e891..54c587f27265 100644 --- a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos3250-pinctrl.dtsi @@ -158,6 +158,13 @@ samsung,pin-drv = <0>; }; + uart2_data: uart2-data { + samsung,pins = "gpa1-0", "gpa1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + i2c3_bus: i2c3-bus { samsung,pins = "gpa1-2", "gpa1-3"; samsung,pin-function = <3>; diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi index 137f9015d4e8..030ce800f748 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/exynos3250.dtsi @@ -43,6 +43,7 @@ i2c7 = &i2c_7; serial0 = &serial_0; serial1 = &serial_1; + serial2 = &serial_2; }; cpus { @@ -452,6 +453,17 @@ status = "disabled"; }; + serial_2: serial@13820000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13820000 0x100>; + interrupts = <0 111 0>; + clocks = <&cmu CLK_UART2>, <&cmu CLK_SCLK_UART2>; + clock-names = "uart", "clk_uart_baud0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_data>; + status = "disabled"; + }; + i2c_0: i2c@13860000 { #address-cells = <1>; #size-cells = <0>; -- GitLab From 92173e6ac26272b84dd275ca2c8ad357bdbfe6db Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 31 Mar 2016 11:48:03 +0900 Subject: [PATCH 1073/9938] ARM: dts: exynos: Add MSHC2 DT node for Exynos3250 SoC This patch adds the MSHC2 (Mobile Storage Host Controller) Device Tree node for Exynos3250 SoC. Signed-off-by: Chanwoo Choi Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos3250-pinctrl.dtsi | 35 +++++++++++++++++++++++ arch/arm/boot/dts/exynos3250.dtsi | 13 +++++++++ 2 files changed, 48 insertions(+) diff --git a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi b/arch/arm/boot/dts/exynos3250-pinctrl.dtsi index 54c587f27265..40ea7de44933 100644 --- a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos3250-pinctrl.dtsi @@ -490,6 +490,41 @@ samsung,pin-drv = <3>; }; + sd2_clk: sd2-clk { + samsung,pins = "gpk2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cmd: sd2-cmd { + samsung,pins = "gpk2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cd: sd2-cd { + samsung,pins = "gpk2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus1: sd2-bus-width1 { + samsung,pins = "gpk2-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus4: sd2-bus-width4 { + samsung,pins = "gpk2-4", "gpk2-5", "gpk2-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + cam_port_b_io: cam-port-b-io { samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3", "gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7", diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi index 030ce800f748..13d00f94cb81 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/exynos3250.dtsi @@ -31,6 +31,7 @@ pinctrl1 = &pinctrl_1; mshc0 = &mshc_0; mshc1 = &mshc_1; + mshc2 = &mshc_2; spi0 = &spi_0; spi1 = &spi_1; i2c0 = &i2c_0; @@ -358,6 +359,18 @@ status = "disabled"; }; + mshc_2: mshc@12530000 { + compatible = "samsung,exynos5250-dw-mshc"; + reg = <0x12530000 0x1000>; + interrupts = <0 144 0>; + clocks = <&cmu CLK_SDMMC2>, <&cmu CLK_SCLK_MMC2>; + clock-names = "biu", "ciu"; + fifo-depth = <0x80>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + exynos_usbphy: exynos-usbphy@125B0000 { compatible = "samsung,exynos3250-usb2-phy"; reg = <0x125B0000 0x100>; -- GitLab From b004a34bd0ffefdccc5a57a8d8075a760a63c81e Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 31 Mar 2016 11:48:04 +0900 Subject: [PATCH 1074/9938] ARM: dts: exynos: Add exynos3250-artik5 dtsi file for ARTIK5 module This patch adds the Device Tree source for Samsung ARTIK5 module[1] based on Exynos3250 SoC. The ARTIK5 module includes the following devices: - Application Processor (Samsung Exynos3250) - WiFi/BT Combo chip (Broadcom4354) - PMIC (Samsung S2MPS14) - eMMC (4GB) - DRAM LPDDR3 (512MB) - Connectors pin (60 Pins x 3 set) Also, this patch adds the ARTIK5 evaluation board[2] dts file which includes the ARTIK5 module[1] and have the devices such as sound codec, sd card port, ethernet port, uart port and so on. [1] https://www.artik.io/hardware/artik-5 [2] http://www.digikey.com/product-search/en?FV=ffecca14 Signed-off-by: Chanwoo Choi Signed-off-by: Jaehoon Chung Signed-off-by: Andi Shyti Acked-by: Rob Herring Signed-off-by: Krzysztof Kozlowski --- .../bindings/arm/samsung/samsung-boards.txt | 2 + arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/exynos3250-artik5-eval.dts | 26 ++ arch/arm/boot/dts/exynos3250-artik5.dtsi | 334 ++++++++++++++++++ 4 files changed, 363 insertions(+) create mode 100644 arch/arm/boot/dts/exynos3250-artik5-eval.dts create mode 100644 arch/arm/boot/dts/exynos3250-artik5.dtsi diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt index 12129c011c8f..f5deace2b380 100644 --- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt +++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt @@ -2,6 +2,8 @@ Required root node properties: - compatible = should be one or more of the following. + - "samsung,artik5" - for Exynos3250-based Samsung ARTIK5 module. + - "samsung,artik5-eval" - for Exynos3250-based Samsung ARTIK5 eval board. - "samsung,monk" - for Exynos3250-based Samsung Simband board. - "samsung,rinato" - for Exynos3250-based Samsung Gear2 board. - "samsung,smdkv310" - for Exynos4210-based Samsung SMDKV310 eval board. diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..bf49774d4908 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -112,6 +112,7 @@ dtb-$(CONFIG_ARCH_DIGICOLOR) += \ dtb-$(CONFIG_ARCH_EFM32) += \ efm32gg-dk3750.dtb dtb-$(CONFIG_ARCH_EXYNOS3) += \ + exynos3250-artik5-eval.dtb \ exynos3250-monk.dtb \ exynos3250-rinato.dtb dtb-$(CONFIG_ARCH_EXYNOS4) += \ diff --git a/arch/arm/boot/dts/exynos3250-artik5-eval.dts b/arch/arm/boot/dts/exynos3250-artik5-eval.dts new file mode 100644 index 000000000000..b476154590a5 --- /dev/null +++ b/arch/arm/boot/dts/exynos3250-artik5-eval.dts @@ -0,0 +1,26 @@ +/* + * Samsung's Exynos3250 based ARTIK5 evaluation board device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Device tree source file for Samsung's ARTIK5 evaluation board + * which is based on Samsung Exynos3250 SoC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; +#include "exynos3250-artik5.dtsi" + +/ { + model = "Samsung ARTIK5 evaluation board"; + compatible = "samsung,artik5-eval", "samsung,artik5", + "samsung,exynos3250", "samsung,exynos3"; +}; + +&serial_2 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/exynos3250-artik5.dtsi b/arch/arm/boot/dts/exynos3250-artik5.dtsi new file mode 100644 index 000000000000..130e946f1414 --- /dev/null +++ b/arch/arm/boot/dts/exynos3250-artik5.dtsi @@ -0,0 +1,334 @@ +/* + * Samsung's Exynos3250 based ARTIK5 module device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Device tree source file for Samsung's ARTIK5 module which is based on + * Samsung Exynos3250 SoC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "exynos3250.dtsi" +#include +#include +#include + +/ { + compatible = "samsung,artik5", "samsung,exynos3250", "samsung,exynos3"; + + chosen { + stdout-path = &serial_2; + }; + + memory { + reg = <0x40000000 0x1ff00000>; + }; + + firmware@0205f000 { + compatible = "samsung,secure-firmware"; + reg = <0x0205f000 0x1000>; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + cooling-maps { + map0 { + /* Corresponds to 500MHz */ + cooling-device = <&cpu0 5 5>; + }; + map1 { + /* Corresponds to 200MHz */ + cooling-device = <&cpu0 8 8>; + }; + }; + }; + }; +}; + +&adc { + vdd-supply = <&ldo7_reg>; + assigned-clocks = <&cmu CLK_SCLK_TSADC>; + assigned-clock-rates = <6000000>; +}; + +&cpu0 { + cpu0-supply = <&buck2_reg>; +}; + +&i2c_0 { + #address-cells = <1>; + #size-cells = <0>; + samsung,i2c-sda-delay = <100>; + samsung,i2c-slave-addr = <0x10>; + samsung,i2c-max-bus-freq = <100000>; + status = "okay"; + + s2mps14_pmic@66 { + compatible = "samsung,s2mps14-pmic"; + interrupt-parent = <&gpx3>; + interrupts = <5 IRQ_TYPE_NONE>; + reg = <0x66>; + + s2mps14_osc: clocks { + compatible = "samsung,s2mps14-clk"; + #clock-cells = <1>; + clock-output-names = "s2mps14_ap", "unused", + "s2mps14_bt"; + }; + + regulators { + ldo1_reg: LDO1 { + /* VDD_ALIVE15x */ + regulator-name = "VLDO1_1.0V"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo2_reg: LDO2 { + /* VDDQM176 ~ VDDQM185 */ + regulator-name = "VLDO2_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + ldo3_reg: LDO3 { + /* + * VDD1_E106 ~ VDD1_E111 + * DVDD_RTC_AP, DVDD_MMC2_AP + */ + regulator-name = "VLDO3_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo4_reg: LDO4 { + /* AVDD_PLL1120 ~ AVDD_PLL11201 */ + regulator-name = "VLDO4_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo5_reg: LDO5 { + /* VDDI_PLL_ISO141 ~ VDDI_PLL_ISO142 */ + regulator-name = "VLDO5_1.0V"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo6_reg: LDO6 { + /* VDD_USB, VDD10_HSIC */ + regulator-name = "VLDO6_1.0V"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo7_reg: LDO7 { + /* + * VDD18P, AVDD18_TS, AVDD18_HSIC, AVDD_PLL2, + * AVDD_ADC, AVDD_ABB_0, M4S_VDD18 + */ + regulator-name = "VLDO7_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo8_reg: LDO8 { + /* AVDD33_UOTG */ + regulator-name = "VLDO8_3.0V"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + }; + + ldo9_reg: LDO9 { + /* VDDQ_E86 ~ VDDQ_E105*/ + regulator-name = "VLDO9_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + ldo10_reg: LDO10 { + regulator-name = "VLDO10_1.0V"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + + ldo11_reg: LDO11 { + /* VDD74 ~ VDD75 */ + regulator-name = "VLDO11_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + samsung,ext-control-gpios = <&gpk0 2 GPIO_ACTIVE_HIGH>; + }; + + ldo12_reg: LDO12 { + /* VDD72 ~ VDD73 */ + regulator-name = "VLDO12_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + samsung,ext-control-gpios = <&gpk0 2 GPIO_ACTIVE_HIGH>; + }; + + ldo13_reg: LDO13 { + regulator-name = "VLDO13_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo14_reg: LDO14 { + regulator-name = "VLDO14_2.7V"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2700000>; + }; + + ldo15_reg: LDO15 { + regulator-name = "VLDO_3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo16_reg: LDO16 { + regulator-name = "VLDO16_3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo17_reg: LDO17 { + regulator-name = "VLDO17_3.0V"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + ldo18_reg: LDO18 { + /* DVDD_MMC2_AP */ + regulator-name = "VLDO18_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo19_reg: LDO19 { + regulator-name = "VLDO19_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo20_reg: LDO20 { + regulator-name = "VLDO20_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo21_reg: LDO21 { + regulator-name = "VLDO21_1.25V"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + }; + + ldo22_reg: LDO22 { + regulator-name = "VLDO22_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + ldo23_reg: LDO23 { + /* Xi2c3_SDA/SCL, Xi2c7_SDA/SCL, WLAN_SDIO */ + regulator-name = "VLDO23_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo24_reg: LDO24 { + regulator-name = "VLDO24_3.0V"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + ldo25_reg: LDO25 { + regulator-name = "VLDO25_3.0V"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + buck1_reg: BUCK1 { + /* VDD_MIF */ + regulator-name = "VBUCK1_1.0V"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + buck2_reg: BUCK2 { + /* VDD_CPU */ + regulator-name = "VBUCK2_1.2V"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + buck3_reg: BUCK3 { + /* VDD_G3D */ + regulator-name = "VBUCK3_1.0V"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + buck4_reg: BUCK4 { + regulator-name = "VBUCK4_1.95V"; + regulator-min-microvolt = <1950000>; + regulator-max-microvolt = <1950000>; + regulator-always-on; + }; + + buck5_reg: BUCK5 { + regulator-name = "VBUCK5_1.35V"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + }; + }; + }; +}; + +&mshc_0 { + num-slots = <1>; + non-removable; + cap-mmc-highspeed; + card-detect-delay = <200>; + vmmc-supply = <&ldo12_reg>; + clock-frequency = <100000000>; + clock-freq-min-max = <400000 100000000>; + samsung,dw-mshc-ciu-div = <1>; + samsung,dw-mshc-sdr-timing = <0 1>; + samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8>; + bus-width = <8>; + status = "okay"; +}; + +&rtc { + clocks = <&cmu CLK_RTC>, <&s2mps14_osc S2MPS11_CLK_AP>; + clock-names = "rtc", "rtc_src"; + status = "okay"; +}; + +&tmu { + status = "okay"; +}; + +&xusbxti { + clock-frequency = <24000000>; +}; -- GitLab From e70c7ae1c594300660a552773c12aa9945770ae6 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 31 Mar 2016 11:48:05 +0900 Subject: [PATCH 1075/9938] ARM: dts: exynos: Add MSHC2 DT node for SD card for exynos3250-artik5-eval board This patch adds MSHC (Mobile Storage Host Controller) DT node for Exynos3250 SoC. MSHC is an interface between the system and the SD card. Signed-off-by: Jaehoon Chung Signed-off-by: Chanwoo Choi Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos3250-artik5-eval.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/exynos3250-artik5-eval.dts b/arch/arm/boot/dts/exynos3250-artik5-eval.dts index b476154590a5..be4d6aa379f3 100644 --- a/arch/arm/boot/dts/exynos3250-artik5-eval.dts +++ b/arch/arm/boot/dts/exynos3250-artik5-eval.dts @@ -21,6 +21,23 @@ "samsung,exynos3250", "samsung,exynos3"; }; +&mshc_2 { + num-slots = <1>; + cap-sd-highspeed; + disable-wp; + vqmmc-supply = <&ldo3_reg>; + card-detect-delay = <200>; + clock-frequency = <100000000>; + clock-freq-min-max = <400000 100000000>; + samsung,dw-mshc-ciu-div = <1>; + samsung,dw-mshc-sdr-timing = <0 1>; + samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_cmd &sd2_clk &sd2_cd &sd2_bus1 &sd2_bus4>; + bus-width = <4>; + status = "okay"; +}; + &serial_2 { status = "okay"; }; -- GitLab From d18d12d0ff07c47fb913f297c174f30a3f96042d Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Thu, 31 Mar 2016 15:51:32 +0200 Subject: [PATCH 1076/9938] lib/proportions: Remove unused code By accident I stumbled across code that is no longer used. According to git grep, the global functions in lib/proportions.c are not used anywhere. This patch removes the old, unused code. Peter Zijlstra further commented: "Ah indeed, that got replaced with the flex proportion code a while back." Signed-off-by: Richard Cochran Acked-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/4265b49bed713fbe3faaf8c05da0e1792f09c0b3.1459432020.git.rcochran@linutronix.de Signed-off-by: Ingo Molnar --- include/linux/proportions.h | 137 ------------ include/linux/sched.h | 1 - lib/Makefile | 2 +- lib/proportions.c | 407 ------------------------------------ 4 files changed, 1 insertion(+), 546 deletions(-) delete mode 100644 include/linux/proportions.h delete mode 100644 lib/proportions.c diff --git a/include/linux/proportions.h b/include/linux/proportions.h deleted file mode 100644 index 21221338ad18..000000000000 --- a/include/linux/proportions.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * FLoating proportions - * - * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra - * - * This file contains the public data structure and API definitions. - */ - -#ifndef _LINUX_PROPORTIONS_H -#define _LINUX_PROPORTIONS_H - -#include -#include -#include -#include - -struct prop_global { - /* - * The period over which we differentiate - * - * period = 2^shift - */ - int shift; - /* - * The total event counter aka 'time'. - * - * Treated as an unsigned long; the lower 'shift - 1' bits are the - * counter bits, the remaining upper bits the period counter. - */ - struct percpu_counter events; -}; - -/* - * global proportion descriptor - * - * this is needed to consistently flip prop_global structures. - */ -struct prop_descriptor { - int index; - struct prop_global pg[2]; - struct mutex mutex; /* serialize the prop_global switch */ -}; - -int prop_descriptor_init(struct prop_descriptor *pd, int shift, gfp_t gfp); -void prop_change_shift(struct prop_descriptor *pd, int new_shift); - -/* - * ----- PERCPU ------ - */ - -struct prop_local_percpu { - /* - * the local events counter - */ - struct percpu_counter events; - - /* - * snapshot of the last seen global state - */ - int shift; - unsigned long period; - raw_spinlock_t lock; /* protect the snapshot state */ -}; - -int prop_local_init_percpu(struct prop_local_percpu *pl, gfp_t gfp); -void prop_local_destroy_percpu(struct prop_local_percpu *pl); -void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl); -void prop_fraction_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl, - long *numerator, long *denominator); - -static inline -void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl) -{ - unsigned long flags; - - local_irq_save(flags); - __prop_inc_percpu(pd, pl); - local_irq_restore(flags); -} - -/* - * Limit the time part in order to ensure there are some bits left for the - * cycle counter and fraction multiply. - */ -#if BITS_PER_LONG == 32 -#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4) -#else -#define PROP_MAX_SHIFT (BITS_PER_LONG/2) -#endif - -#define PROP_FRAC_SHIFT (BITS_PER_LONG - PROP_MAX_SHIFT - 1) -#define PROP_FRAC_BASE (1UL << PROP_FRAC_SHIFT) - -void __prop_inc_percpu_max(struct prop_descriptor *pd, - struct prop_local_percpu *pl, long frac); - - -/* - * ----- SINGLE ------ - */ - -struct prop_local_single { - /* - * the local events counter - */ - unsigned long events; - - /* - * snapshot of the last seen global state - * and a lock protecting this state - */ - unsigned long period; - int shift; - raw_spinlock_t lock; /* protect the snapshot state */ -}; - -#define INIT_PROP_LOCAL_SINGLE(name) \ -{ .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ -} - -int prop_local_init_single(struct prop_local_single *pl); -void prop_local_destroy_single(struct prop_local_single *pl); -void __prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl); -void prop_fraction_single(struct prop_descriptor *pd, struct prop_local_single *pl, - long *numerator, long *denominator); - -static inline -void prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl) -{ - unsigned long flags; - - local_irq_save(flags); - __prop_inc_single(pd, pl); - local_irq_restore(flags); -} - -#endif /* _LINUX_PROPORTIONS_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 60bba7e032dc..6dd25d1869b5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -40,7 +40,6 @@ struct sched_param { #include #include #include -#include #include #include #include diff --git a/lib/Makefile b/lib/Makefile index 7bd6fd436c97..a65e9a861535 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -23,7 +23,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o timerqueue.o\ idr.o int_sqrt.o extable.o \ sha1.o md5.o irq_regs.o argv_split.o \ - proportions.o flex_proportions.o ratelimit.o show_mem.o \ + flex_proportions.o ratelimit.o show_mem.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ earlycpio.o seq_buf.o nmi_backtrace.o diff --git a/lib/proportions.c b/lib/proportions.c deleted file mode 100644 index efa54f259ea9..000000000000 --- a/lib/proportions.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Floating proportions - * - * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra - * - * Description: - * - * The floating proportion is a time derivative with an exponentially decaying - * history: - * - * p_{j} = \Sum_{i=0} (dx_{j}/dt_{-i}) / 2^(1+i) - * - * Where j is an element from {prop_local}, x_{j} is j's number of events, - * and i the time period over which the differential is taken. So d/dt_{-i} is - * the differential over the i-th last period. - * - * The decaying history gives smooth transitions. The time differential carries - * the notion of speed. - * - * The denominator is 2^(1+i) because we want the series to be normalised, ie. - * - * \Sum_{i=0} 1/2^(1+i) = 1 - * - * Further more, if we measure time (t) in the same events as x; so that: - * - * t = \Sum_{j} x_{j} - * - * we get that: - * - * \Sum_{j} p_{j} = 1 - * - * Writing this in an iterative fashion we get (dropping the 'd's): - * - * if (++x_{j}, ++t > period) - * t /= 2; - * for_each (j) - * x_{j} /= 2; - * - * so that: - * - * p_{j} = x_{j} / t; - * - * We optimize away the '/= 2' for the global time delta by noting that: - * - * if (++t > period) t /= 2: - * - * Can be approximated by: - * - * period/2 + (++t % period/2) - * - * [ Furthermore, when we choose period to be 2^n it can be written in terms of - * binary operations and wraparound artefacts disappear. ] - * - * Also note that this yields a natural counter of the elapsed periods: - * - * c = t / (period/2) - * - * [ Its monotonic increasing property can be applied to mitigate the wrap- - * around issue. ] - * - * This allows us to do away with the loop over all prop_locals on each period - * expiration. By remembering the period count under which it was last accessed - * as c_{j}, we can obtain the number of 'missed' cycles from: - * - * c - c_{j} - * - * We can then lazily catch up to the global period count every time we are - * going to use x_{j}, by doing: - * - * x_{j} /= 2^(c - c_{j}), c_{j} = c - */ - -#include -#include - -int prop_descriptor_init(struct prop_descriptor *pd, int shift, gfp_t gfp) -{ - int err; - - if (shift > PROP_MAX_SHIFT) - shift = PROP_MAX_SHIFT; - - pd->index = 0; - pd->pg[0].shift = shift; - mutex_init(&pd->mutex); - err = percpu_counter_init(&pd->pg[0].events, 0, gfp); - if (err) - goto out; - - err = percpu_counter_init(&pd->pg[1].events, 0, gfp); - if (err) - percpu_counter_destroy(&pd->pg[0].events); - -out: - return err; -} - -/* - * We have two copies, and flip between them to make it seem like an atomic - * update. The update is not really atomic wrt the events counter, but - * it is internally consistent with the bit layout depending on shift. - * - * We copy the events count, move the bits around and flip the index. - */ -void prop_change_shift(struct prop_descriptor *pd, int shift) -{ - int index; - int offset; - u64 events; - unsigned long flags; - - if (shift > PROP_MAX_SHIFT) - shift = PROP_MAX_SHIFT; - - mutex_lock(&pd->mutex); - - index = pd->index ^ 1; - offset = pd->pg[pd->index].shift - shift; - if (!offset) - goto out; - - pd->pg[index].shift = shift; - - local_irq_save(flags); - events = percpu_counter_sum(&pd->pg[pd->index].events); - if (offset < 0) - events <<= -offset; - else - events >>= offset; - percpu_counter_set(&pd->pg[index].events, events); - - /* - * ensure the new pg is fully written before the switch - */ - smp_wmb(); - pd->index = index; - local_irq_restore(flags); - - synchronize_rcu(); - -out: - mutex_unlock(&pd->mutex); -} - -/* - * wrap the access to the data in an rcu_read_lock() section; - * this is used to track the active references. - */ -static struct prop_global *prop_get_global(struct prop_descriptor *pd) -__acquires(RCU) -{ - int index; - - rcu_read_lock(); - index = pd->index; - /* - * match the wmb from vcd_flip() - */ - smp_rmb(); - return &pd->pg[index]; -} - -static void prop_put_global(struct prop_descriptor *pd, struct prop_global *pg) -__releases(RCU) -{ - rcu_read_unlock(); -} - -static void -prop_adjust_shift(int *pl_shift, unsigned long *pl_period, int new_shift) -{ - int offset = *pl_shift - new_shift; - - if (!offset) - return; - - if (offset < 0) - *pl_period <<= -offset; - else - *pl_period >>= offset; - - *pl_shift = new_shift; -} - -/* - * PERCPU - */ - -#define PROP_BATCH (8*(1+ilog2(nr_cpu_ids))) - -int prop_local_init_percpu(struct prop_local_percpu *pl, gfp_t gfp) -{ - raw_spin_lock_init(&pl->lock); - pl->shift = 0; - pl->period = 0; - return percpu_counter_init(&pl->events, 0, gfp); -} - -void prop_local_destroy_percpu(struct prop_local_percpu *pl) -{ - percpu_counter_destroy(&pl->events); -} - -/* - * Catch up with missed period expirations. - * - * until (c_{j} == c) - * x_{j} -= x_{j}/2; - * c_{j}++; - */ -static -void prop_norm_percpu(struct prop_global *pg, struct prop_local_percpu *pl) -{ - unsigned long period = 1UL << (pg->shift - 1); - unsigned long period_mask = ~(period - 1); - unsigned long global_period; - unsigned long flags; - - global_period = percpu_counter_read(&pg->events); - global_period &= period_mask; - - /* - * Fast path - check if the local and global period count still match - * outside of the lock. - */ - if (pl->period == global_period) - return; - - raw_spin_lock_irqsave(&pl->lock, flags); - prop_adjust_shift(&pl->shift, &pl->period, pg->shift); - - /* - * For each missed period, we half the local counter. - * basically: - * pl->events >> (global_period - pl->period); - */ - period = (global_period - pl->period) >> (pg->shift - 1); - if (period < BITS_PER_LONG) { - s64 val = percpu_counter_read(&pl->events); - - if (val < (nr_cpu_ids * PROP_BATCH)) - val = percpu_counter_sum(&pl->events); - - __percpu_counter_add(&pl->events, -val + (val >> period), - PROP_BATCH); - } else - percpu_counter_set(&pl->events, 0); - - pl->period = global_period; - raw_spin_unlock_irqrestore(&pl->lock, flags); -} - -/* - * ++x_{j}, ++t - */ -void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl) -{ - struct prop_global *pg = prop_get_global(pd); - - prop_norm_percpu(pg, pl); - __percpu_counter_add(&pl->events, 1, PROP_BATCH); - percpu_counter_add(&pg->events, 1); - prop_put_global(pd, pg); -} - -/* - * identical to __prop_inc_percpu, except that it limits this pl's fraction to - * @frac/PROP_FRAC_BASE by ignoring events when this limit has been exceeded. - */ -void __prop_inc_percpu_max(struct prop_descriptor *pd, - struct prop_local_percpu *pl, long frac) -{ - struct prop_global *pg = prop_get_global(pd); - - prop_norm_percpu(pg, pl); - - if (unlikely(frac != PROP_FRAC_BASE)) { - unsigned long period_2 = 1UL << (pg->shift - 1); - unsigned long counter_mask = period_2 - 1; - unsigned long global_count; - long numerator, denominator; - - numerator = percpu_counter_read_positive(&pl->events); - global_count = percpu_counter_read(&pg->events); - denominator = period_2 + (global_count & counter_mask); - - if (numerator > ((denominator * frac) >> PROP_FRAC_SHIFT)) - goto out_put; - } - - percpu_counter_add(&pl->events, 1); - percpu_counter_add(&pg->events, 1); - -out_put: - prop_put_global(pd, pg); -} - -/* - * Obtain a fraction of this proportion - * - * p_{j} = x_{j} / (period/2 + t % period/2) - */ -void prop_fraction_percpu(struct prop_descriptor *pd, - struct prop_local_percpu *pl, - long *numerator, long *denominator) -{ - struct prop_global *pg = prop_get_global(pd); - unsigned long period_2 = 1UL << (pg->shift - 1); - unsigned long counter_mask = period_2 - 1; - unsigned long global_count; - - prop_norm_percpu(pg, pl); - *numerator = percpu_counter_read_positive(&pl->events); - - global_count = percpu_counter_read(&pg->events); - *denominator = period_2 + (global_count & counter_mask); - - prop_put_global(pd, pg); -} - -/* - * SINGLE - */ - -int prop_local_init_single(struct prop_local_single *pl) -{ - raw_spin_lock_init(&pl->lock); - pl->shift = 0; - pl->period = 0; - pl->events = 0; - return 0; -} - -void prop_local_destroy_single(struct prop_local_single *pl) -{ -} - -/* - * Catch up with missed period expirations. - */ -static -void prop_norm_single(struct prop_global *pg, struct prop_local_single *pl) -{ - unsigned long period = 1UL << (pg->shift - 1); - unsigned long period_mask = ~(period - 1); - unsigned long global_period; - unsigned long flags; - - global_period = percpu_counter_read(&pg->events); - global_period &= period_mask; - - /* - * Fast path - check if the local and global period count still match - * outside of the lock. - */ - if (pl->period == global_period) - return; - - raw_spin_lock_irqsave(&pl->lock, flags); - prop_adjust_shift(&pl->shift, &pl->period, pg->shift); - /* - * For each missed period, we half the local counter. - */ - period = (global_period - pl->period) >> (pg->shift - 1); - if (likely(period < BITS_PER_LONG)) - pl->events >>= period; - else - pl->events = 0; - pl->period = global_period; - raw_spin_unlock_irqrestore(&pl->lock, flags); -} - -/* - * ++x_{j}, ++t - */ -void __prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl) -{ - struct prop_global *pg = prop_get_global(pd); - - prop_norm_single(pg, pl); - pl->events++; - percpu_counter_add(&pg->events, 1); - prop_put_global(pd, pg); -} - -/* - * Obtain a fraction of this proportion - * - * p_{j} = x_{j} / (period/2 + t % period/2) - */ -void prop_fraction_single(struct prop_descriptor *pd, - struct prop_local_single *pl, - long *numerator, long *denominator) -{ - struct prop_global *pg = prop_get_global(pd); - unsigned long period_2 = 1UL << (pg->shift - 1); - unsigned long counter_mask = period_2 - 1; - unsigned long global_count; - - prop_norm_single(pg, pl); - *numerator = pl->events; - - global_count = percpu_counter_read(&pg->events); - *denominator = period_2 + (global_count & counter_mask); - - prop_put_global(pd, pg); -} -- GitLab From d7847a7017b2a2759dd5590c0cffdbdf2994918e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 1 Apr 2016 09:00:35 +0200 Subject: [PATCH 1077/9938] x86/cpufeature: Fix build bug caused by merge artifact with the removal of cpu_has_hypervisor The 0-day build robot by Fengguang Wu reported a build failure: arch/x86/events//intel/cstate.c: In function 'cstate_pmu_init': arch/x86/events//intel/cstate.c:680:6: error: 'cpu_has_hypervisor' undeclared (first use in this function) ... which was caused by a merge mistake I made when applying the following patch: 0c9f3536cc71 ("x86/cpufeature: Remove cpu_has_hypervisor") apply the missing hunk as well. Reported-by: kbuild test robot Cc: David Kershner Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: sparmaintainer@unisys.com Cc: virtualization@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1459266123-21878-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/events/intel/cstate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 7946c4231169..d5045c8e2e63 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -677,7 +677,7 @@ static int __init cstate_pmu_init(void) { int err; - if (cpu_has_hypervisor) + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) return -ENODEV; err = cstate_init(); -- GitLab From 1c532e00a0c649ac6f0703e8c2e095c9c1d30625 Mon Sep 17 00:00:00 2001 From: Alex Thorlton Date: Thu, 31 Mar 2016 14:18:29 -0500 Subject: [PATCH 1078/9938] x86/platform/uv: Disable UV BAU by default For several years, the common practice has been to boot UVs with the "nobau" parameter on the command line, to disable the BAU. We've decided that it makes more sense to just disable the BAU by default in the kernel, and provide the option to turn it on, if desired. For now, having the on/off switch doesn't buy us any more than just reversing the logic would, but we're working towards having the BAU enabled by default on UV4. When those changes are in place, having the on/off switch will make more sense than an enable flag, since the default behavior will be different depending on the system version. I've also added a bit of documentation for the new parameter to Documentation/kernel-parameters.txt. Signed-off-by: Alex Thorlton Reviewed-by: Hedi Berriche Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459451909-121845-1-git-send-email-athorlton@sgi.com Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 8 +++++++ arch/x86/include/asm/uv/uv_bau.h | 2 +- arch/x86/platform/uv/tlb_uv.c | 35 ++++++++++++++++++++--------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ecc74fa4bfde..893a70907f15 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -131,6 +131,7 @@ parameter is applicable: More X86-64 boot options can be found in Documentation/x86/x86_64/boot-options.txt . X86 Either 32-bit or 64-bit x86 (same as X86-32+X86-64) + X86_UV SGI UV support is enabled. XEN Xen support is enabled In addition, the following text indicates that the option: @@ -542,6 +543,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Format: (must be >=0) Default: 64 + bau= [X86_UV] Enable the BAU on SGI UV. The default + behavior is to disable the BAU (i.e. bau=0). + Format: { "0" | "1" } + 0 - Disable the BAU. + 1 - Enable the BAU. + unset - Disable the BAU. + baycom_epp= [HW,AX25] Format: , diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index fc808b83fccb..cc44d926c17e 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -598,7 +598,7 @@ struct bau_control { int timeout_tries; int ipi_attempts; int conseccompletes; - short nobau; + bool nobau; short baudisabled; short cpu; short osnode; diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 3b6ec42718e4..534ab944b947 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -37,7 +37,7 @@ static int timeout_base_ns[] = { }; static int timeout_us; -static int nobau; +static bool nobau = true; static int nobau_perm; static cycles_t congested_cycles; @@ -106,13 +106,28 @@ static char *stat_description[] = { "enable: number times use of the BAU was re-enabled" }; -static int __init -setup_nobau(char *arg) +static int __init setup_bau(char *arg) { - nobau = 1; + int result; + + if (!arg) + return -EINVAL; + + result = strtobool(arg, &nobau); + if (result) + return result; + + /* we need to flip the logic here, so that bau=y sets nobau to false */ + nobau = !nobau; + + if (!nobau) + pr_info("UV BAU Enabled\n"); + else + pr_info("UV BAU Disabled\n"); + return 0; } -early_param("nobau", setup_nobau); +early_param("bau", setup_bau); /* base pnode in this partition */ static int uv_base_pnode __read_mostly; @@ -131,10 +146,10 @@ set_bau_on(void) pr_info("BAU not initialized; cannot be turned on\n"); return; } - nobau = 0; + nobau = false; for_each_present_cpu(cpu) { bcp = &per_cpu(bau_control, cpu); - bcp->nobau = 0; + bcp->nobau = false; } pr_info("BAU turned on\n"); return; @@ -146,10 +161,10 @@ set_bau_off(void) int cpu; struct bau_control *bcp; - nobau = 1; + nobau = true; for_each_present_cpu(cpu) { bcp = &per_cpu(bau_control, cpu); - bcp->nobau = 1; + bcp->nobau = true; } pr_info("BAU turned off\n"); return; @@ -1886,7 +1901,7 @@ static void __init init_per_cpu_tunables(void) bcp = &per_cpu(bau_control, cpu); bcp->baudisabled = 0; if (nobau) - bcp->nobau = 1; + bcp->nobau = true; bcp->statp = &per_cpu(ptcstats, cpu); /* time interval to catch a hardware stay-busy bug */ bcp->timeout_interval = usec_2_cycles(2*timeout_us); -- GitLab From eeb01a57921a5e373302733d7cdf1ca87da5375a Mon Sep 17 00:00:00 2001 From: Yusuke Fujimaki Date: Mon, 21 Mar 2016 16:18:42 +0900 Subject: [PATCH 1079/9938] HID: Asus X205TA keyboard driver Asus X205TA built-in keyboard contains wrong logical maximum value in report descriptor. 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x06, // Usage (Keyboard) 0xa1, 0x01, // Collection (Application) 0x85, 0x01, // Report ID (1) 0x05, 0x07, // Usage Page (Keyboard/Keypad) 0x19, 0xe0, // Usage Minimum (224) 0x29, 0xe7, // Usage Maximum (231) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x08, // Report Count (8) 0x81, 0x02, // Input (Data,Array,Abs) 0x95, 0x01, // Report Count (1) 0x75, 0x08, // Report Size (8) 0x81, 0x03, // Input (Const,Var,Abs) 0x95, 0x05, // Report Count (5) 0x75, 0x01, // Report Size (1) 0x05, 0x08, // Usage (LED) 0x19, 0x01, // Usage Minimum (1) 0x29, 0x05, // Usage Maximum (5) 0x91, 0x02, // Output (Data,Var,Abs) 0x95, 0x01, // Report Count (1) 0x75, 0x03, // Report Size (3) 0x91, 0x03, // Output (Const,Var,Abs) 0x95, 0x06, // Report Count (6) 0x75, 0x08, // Report Size (8) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x65, // Logical Maximum (101) * too small * 0x05, 0x07, // Usage Page (Keyboard/Keypad) 0x19, 0x00, // Usage Minimum (0) 0x29, 0xdd, // Usage Maximum (221) 0x81, 0x00, // Input(Data,Array,Abs) In Asus X205TA japanese keyboard model,there are language specific keys over usage id 101. This patch correct wrong logical maximum in report descriptor. Signed-off-by: Yusuke Fujimaki Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 ++++++ drivers/hid/Makefile | 1 + drivers/hid/hid-asus.c | 48 ++++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + 5 files changed, 57 insertions(+) create mode 100644 drivers/hid/hid-asus.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 411722570035..513c93e2c650 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -134,6 +134,12 @@ config HID_APPLEIR Say Y here if you want support for Apple infrared remote control. +config HID_ASUS + tristate "Asus" + depends on I2C_HID + ---help--- + Support for Asus X205TA built-in keyboard via i2c. + config HID_AUREAL tristate "Aureal" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index be56ab6f75a8..a2fb562de748 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_ACRUX) += hid-axff.o obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o +obj-$(CONFIG_HID_ASUS) += hid-asus.o obj-$(CONFIG_HID_AUREAL) += hid-aureal.o obj-$(CONFIG_HID_BELKIN) += hid-belkin.o obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c new file mode 100644 index 000000000000..1734e11298ed --- /dev/null +++ b/drivers/hid/hid-asus.c @@ -0,0 +1,48 @@ +/* + * HID driver for Asus X205TA built-in keyboard. + * Fixes small logical maximum to match usage maximum. + * + * Copyright (c) 2016 Yusuke Fujimaki + * + * This module based on hid-ortek by + * Copyright (c) 2010 Johnathon Harris + * Copyright (c) 2011 Jiri Kosina + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include +#include +#include + +#include "hid-ids.h" + +static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + if (*rsize >= 180 && rdesc[54] == 0x25 && rdesc[55] == 0x65) { + hid_info(hdev, "Fixing up Asus X205TA report descriptor\n"); + rdesc[55] = 0xdd; + } + return rdesc; +} + +static const struct hid_device_id asus_devices[] = { + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_X205TA_KEYBOARD) }, + { } +}; +MODULE_DEVICE_TABLE(hid, asus_devices); + +static struct hid_driver asus_driver = { + .name = "asus", + .id_table = asus_devices, + .report_fixup = asus_report_fixup +}; +module_hid_driver(asus_driver); + +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bdb8cc89cacc..7426b5aabf27 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1856,6 +1856,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_X205TA_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5c0e43ed5c53..f83e7fd0626b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -163,6 +163,7 @@ #define USB_VENDOR_ID_ASUSTEK 0x0b05 #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b +#define USB_DEVICE_ID_ASUSTEK_X205TA_KEYBOARD 0x8585 #define USB_VENDOR_ID_ATEN 0x0557 #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 -- GitLab From 20b3d2a79f0f9ff1ac189f43df7598d0e968210a Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 28 Mar 2016 14:58:24 +0000 Subject: [PATCH 1080/9938] pinctrl: bcm2835: Implement get_direction callback Implement gpio_chip's get_direction() callback, that lets other drivers get particular GPIOs direction using gpiod_get_direction(). Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Reviewed-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 08b1d93da9fe..57e7d21d526b 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -342,6 +342,18 @@ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset) return bcm2835_gpio_get_bit(pc, GPLEV0, offset); } +static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); + enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset); + + /* Alternative function doesn't clearly provide a direction */ + if (fsel > BCM2835_FSEL_GPIO_OUT) + return -EINVAL; + + return (fsel == BCM2835_FSEL_GPIO_IN); +} + static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); @@ -370,6 +382,7 @@ static struct gpio_chip bcm2835_gpio_chip = { .free = gpiochip_generic_free, .direction_input = bcm2835_gpio_direction_input, .direction_output = bcm2835_gpio_direction_output, + .get_direction = bcm2835_gpio_get_direction, .get = bcm2835_gpio_get, .set = bcm2835_gpio_set, .to_irq = bcm2835_gpio_to_irq, -- GitLab From 8d98e96b345e13659aa42bdc611368863ce65cbe Mon Sep 17 00:00:00 2001 From: Jessica Yu Date: Tue, 22 Mar 2016 20:03:15 -0400 Subject: [PATCH 1081/9938] Elf: add livepatch-specific Elf constants Livepatch manages its own relocation sections and symbols in order to be able to reuse module loader code to write relocations. This removes livepatch's dependence on separate "dynrela" sections to write relocations and also allows livepatch to patch modules that are not yet loaded. The livepatch Elf relocation section flag (SHF_RELA_LIVEPATCH), and symbol section index (SHN_LIVEPATCH) allow both livepatch and the module loader to identity livepatch relocation sections and livepatch symbols. Livepatch relocation sections are marked with SHF_RELA_LIVEPATCH to indicate to the module loader that it should not apply that relocation section and that livepatch will handle them. The SHN_LIVEPATCH shndx marks symbols that will be resolved by livepatch. The module loader ignores these symbols and does not attempt to resolve them. The values of these Elf constants were selected from OS-specific ranges according to the definitions from glibc. Signed-off-by: Jessica Yu Reviewed-by: Miroslav Benes Acked-by: Josh Poimboeuf Signed-off-by: Jiri Kosina --- include/uapi/linux/elf.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index 71e1d0ed92f7..cb4a72f888d5 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -282,16 +282,18 @@ typedef struct elf64_phdr { #define SHT_HIUSER 0xffffffff /* sh_flags */ -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_RELA_LIVEPATCH 0x00100000 +#define SHF_MASKPROC 0xf0000000 /* special section indexes */ #define SHN_UNDEF 0 #define SHN_LORESERVE 0xff00 #define SHN_LOPROC 0xff00 #define SHN_HIPROC 0xff1f +#define SHN_LIVEPATCH 0xff20 #define SHN_ABS 0xfff1 #define SHN_COMMON 0xfff2 #define SHN_HIRESERVE 0xffff -- GitLab From 1ce15ef4f60529cf1313f80f4338c88bd65cc572 Mon Sep 17 00:00:00 2001 From: Jessica Yu Date: Tue, 22 Mar 2016 20:03:16 -0400 Subject: [PATCH 1082/9938] module: preserve Elf information for livepatch modules For livepatch modules, copy Elf section, symbol, and string information from the load_info struct in the module loader. Persist copies of the original symbol table and string table. Livepatch manages its own relocation sections in order to reuse module loader code to write relocations. Livepatch modules must preserve Elf information such as section indices in order to apply livepatch relocation sections using the module loader's apply_relocate_add() function. In order to apply livepatch relocation sections, livepatch modules must keep a complete copy of their original symbol table in memory. Normally, a stripped down copy of a module's symbol table (containing only "core" symbols) is made available through module->core_symtab. But for livepatch modules, the symbol table copied into memory on module load must be exactly the same as the symbol table produced when the patch module was compiled. This is because the relocations in each livepatch relocation section refer to their respective symbols with their symbol indices, and the original symbol indices (and thus the symtab ordering) must be preserved in order for apply_relocate_add() to find the right symbol. Signed-off-by: Jessica Yu Reviewed-by: Miroslav Benes Acked-by: Josh Poimboeuf Acked-by: Rusty Russell Reviewed-by: Rusty Russell Signed-off-by: Jiri Kosina --- include/linux/module.h | 25 +++++++++ kernel/module.c | 125 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/include/linux/module.h b/include/linux/module.h index 2bb0c3085706..3daf2b3a09d2 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -330,6 +330,15 @@ struct mod_kallsyms { char *strtab; }; +#ifdef CONFIG_LIVEPATCH +struct klp_modinfo { + Elf_Ehdr hdr; + Elf_Shdr *sechdrs; + char *secstrings; + unsigned int symndx; +}; +#endif + struct module { enum module_state state; @@ -456,7 +465,11 @@ struct module { #endif #ifdef CONFIG_LIVEPATCH + bool klp; /* Is this a livepatch module? */ bool klp_alive; + + /* Elf information */ + struct klp_modinfo *klp_info; #endif #ifdef CONFIG_MODULE_UNLOAD @@ -630,6 +643,18 @@ static inline bool module_requested_async_probing(struct module *module) return module && module->async_probe_requested; } +#ifdef CONFIG_LIVEPATCH +static inline bool is_livepatch_module(struct module *mod) +{ + return mod->klp; +} +#else /* !CONFIG_LIVEPATCH */ +static inline bool is_livepatch_module(struct module *mod) +{ + return false; +} +#endif /* CONFIG_LIVEPATCH */ + #else /* !CONFIG_MODULES... */ /* Given an address, look for it in the exception tables. */ diff --git a/kernel/module.c b/kernel/module.c index 041200ca4a2d..5f71aa63ed2a 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1973,6 +1973,83 @@ static void module_enable_nx(const struct module *mod) { } static void module_disable_nx(const struct module *mod) { } #endif +#ifdef CONFIG_LIVEPATCH +/* + * Persist Elf information about a module. Copy the Elf header, + * section header table, section string table, and symtab section + * index from info to mod->klp_info. + */ +static int copy_module_elf(struct module *mod, struct load_info *info) +{ + unsigned int size, symndx; + int ret; + + size = sizeof(*mod->klp_info); + mod->klp_info = kmalloc(size, GFP_KERNEL); + if (mod->klp_info == NULL) + return -ENOMEM; + + /* Elf header */ + size = sizeof(mod->klp_info->hdr); + memcpy(&mod->klp_info->hdr, info->hdr, size); + + /* Elf section header table */ + size = sizeof(*info->sechdrs) * info->hdr->e_shnum; + mod->klp_info->sechdrs = kmalloc(size, GFP_KERNEL); + if (mod->klp_info->sechdrs == NULL) { + ret = -ENOMEM; + goto free_info; + } + memcpy(mod->klp_info->sechdrs, info->sechdrs, size); + + /* Elf section name string table */ + size = info->sechdrs[info->hdr->e_shstrndx].sh_size; + mod->klp_info->secstrings = kmalloc(size, GFP_KERNEL); + if (mod->klp_info->secstrings == NULL) { + ret = -ENOMEM; + goto free_sechdrs; + } + memcpy(mod->klp_info->secstrings, info->secstrings, size); + + /* Elf symbol section index */ + symndx = info->index.sym; + mod->klp_info->symndx = symndx; + + /* + * For livepatch modules, core_kallsyms.symtab is a complete + * copy of the original symbol table. Adjust sh_addr to point + * to core_kallsyms.symtab since the copy of the symtab in module + * init memory is freed at the end of do_init_module(). + */ + mod->klp_info->sechdrs[symndx].sh_addr = \ + (unsigned long) mod->core_kallsyms.symtab; + + return 0; + +free_sechdrs: + kfree(mod->klp_info->sechdrs); +free_info: + kfree(mod->klp_info); + return ret; +} + +static void free_module_elf(struct module *mod) +{ + kfree(mod->klp_info->sechdrs); + kfree(mod->klp_info->secstrings); + kfree(mod->klp_info); +} +#else /* !CONFIG_LIVEPATCH */ +static int copy_module_elf(struct module *mod, struct load_info *info) +{ + return 0; +} + +static void free_module_elf(struct module *mod) +{ +} +#endif /* CONFIG_LIVEPATCH */ + void __weak module_memfree(void *module_region) { vfree(module_region); @@ -2011,6 +2088,9 @@ static void free_module(struct module *mod) /* Free any allocated parameters. */ destroy_params(mod->kp, mod->num_kp); + if (is_livepatch_module(mod)) + free_module_elf(mod); + /* Now we can delete it from the lists */ mutex_lock(&module_mutex); /* Unlink carefully: kallsyms could be walking list. */ @@ -2126,6 +2206,10 @@ static int simplify_symbols(struct module *mod, const struct load_info *info) (long)sym[i].st_value); break; + case SHN_LIVEPATCH: + /* Livepatch symbols are resolved by livepatch */ + break; + case SHN_UNDEF: ksym = resolve_symbol_wait(mod, info, name); /* Ok if resolved. */ @@ -2174,6 +2258,10 @@ static int apply_relocations(struct module *mod, const struct load_info *info) if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC)) continue; + /* Livepatch relocation sections are applied by livepatch */ + if (info->sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH) + continue; + if (info->sechdrs[i].sh_type == SHT_REL) err = apply_relocate(info->sechdrs, info->strtab, info->index.sym, i, mod); @@ -2469,7 +2557,7 @@ static void layout_symtab(struct module *mod, struct load_info *info) /* Compute total space required for the core symbols' strtab. */ for (ndst = i = 0; i < nsrc; i++) { - if (i == 0 || + if (i == 0 || is_livepatch_module(mod) || is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum, info->index.pcpu)) { strtab_size += strlen(&info->strtab[src[i].st_name])+1; @@ -2528,7 +2616,7 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs; src = mod->kallsyms->symtab; for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) { - if (i == 0 || + if (i == 0 || is_livepatch_module(mod) || is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum, info->index.pcpu)) { dst[ndst] = src[i]; @@ -2667,6 +2755,26 @@ static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned l return 0; } +#ifdef CONFIG_LIVEPATCH +static int find_livepatch_modinfo(struct module *mod, struct load_info *info) +{ + mod->klp = get_modinfo(info, "livepatch") ? true : false; + + return 0; +} +#else /* !CONFIG_LIVEPATCH */ +static int find_livepatch_modinfo(struct module *mod, struct load_info *info) +{ + if (get_modinfo(info, "livepatch")) { + pr_err("%s: module is marked as livepatch module, but livepatch support is disabled", + mod->name); + return -ENOEXEC; + } + + return 0; +} +#endif /* CONFIG_LIVEPATCH */ + /* Sets info->hdr and info->len. */ static int copy_module_from_user(const void __user *umod, unsigned long len, struct load_info *info) @@ -2821,6 +2929,10 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags) "is unknown, you have been warned.\n", mod->name); } + err = find_livepatch_modinfo(mod, info); + if (err) + return err; + /* Set up license info based on the info section */ set_license(mod, get_modinfo(info, "license")); @@ -3494,6 +3606,12 @@ static int load_module(struct load_info *info, const char __user *uargs, if (err < 0) goto coming_cleanup; + if (is_livepatch_module(mod)) { + err = copy_module_elf(mod, info); + if (err < 0) + goto sysfs_cleanup; + } + /* Get rid of temporary copy. */ free_copy(info); @@ -3502,11 +3620,12 @@ static int load_module(struct load_info *info, const char __user *uargs, return do_init_module(mod); + sysfs_cleanup: + mod_sysfs_teardown(mod); coming_cleanup: blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, mod); klp_module_going(mod); - bug_cleanup: /* module_bug_cleanup needs module_mutex protection */ mutex_lock(&module_mutex); -- GitLab From f31e0960f395df0c9197de53674365e2a28a129b Mon Sep 17 00:00:00 2001 From: Jessica Yu Date: Tue, 22 Mar 2016 20:03:17 -0400 Subject: [PATCH 1083/9938] module: s390: keep mod_arch_specific for livepatch modules Livepatch needs to utilize the symbol information contained in the mod_arch_specific struct in order to be able to call the s390 apply_relocate_add() function to apply relocations. Keep a reference to syminfo if the module is a livepatch module. Remove the redundant vfree() in module_finalize() since module_arch_freeing_init() (which also frees those structures) is called in do_init_module(). If the module isn't a livepatch module, we free the structures in module_arch_freeing_init() as usual. Signed-off-by: Jessica Yu Reviewed-by: Miroslav Benes Acked-by: Josh Poimboeuf Acked-by: Heiko Carstens Signed-off-by: Jiri Kosina --- arch/s390/kernel/module.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 7873e171457c..fbc07891f9e7 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -51,6 +51,10 @@ void *module_alloc(unsigned long size) void module_arch_freeing_init(struct module *mod) { + if (is_livepatch_module(mod) && + mod->state == MODULE_STATE_LIVE) + return; + vfree(mod->arch.syminfo); mod->arch.syminfo = NULL; } @@ -425,7 +429,5 @@ int module_finalize(const Elf_Ehdr *hdr, struct module *me) { jump_label_apply_nops(me); - vfree(me->arch.syminfo); - me->arch.syminfo = NULL; return 0; } -- GitLab From 425595a7fc2096ab46c741b5ed5372c5ab5bbeac Mon Sep 17 00:00:00 2001 From: Jessica Yu Date: Tue, 22 Mar 2016 20:03:18 -0400 Subject: [PATCH 1084/9938] livepatch: reuse module loader code to write relocations Reuse module loader code to write relocations, thereby eliminating the need for architecture specific relocation code in livepatch. Specifically, reuse the apply_relocate_add() function in the module loader to write relocations instead of duplicating functionality in livepatch's arch-dependent klp_write_module_reloc() function. In order to accomplish this, livepatch modules manage their own relocation sections (marked with the SHF_RELA_LIVEPATCH section flag) and livepatch-specific symbols (marked with SHN_LIVEPATCH symbol section index). To apply livepatch relocation sections, livepatch symbols referenced by relocs are resolved and then apply_relocate_add() is called to apply those relocations. In addition, remove x86 livepatch relocation code and the s390 klp_write_module_reloc() function stub. They are no longer needed since relocation work has been offloaded to module loader. Lastly, mark the module as a livepatch module so that the module loader canappropriately identify and initialize it. Signed-off-by: Jessica Yu Reviewed-by: Miroslav Benes Acked-by: Josh Poimboeuf Acked-by: Heiko Carstens # for s390 changes Signed-off-by: Jiri Kosina --- arch/s390/include/asm/livepatch.h | 7 -- arch/x86/include/asm/livepatch.h | 2 - arch/x86/kernel/Makefile | 1 - arch/x86/kernel/livepatch.c | 70 ------------- include/linux/livepatch.h | 20 ---- kernel/livepatch/core.c | 148 +++++++++++++++++---------- samples/livepatch/livepatch-sample.c | 1 + 7 files changed, 95 insertions(+), 154 deletions(-) delete mode 100644 arch/x86/kernel/livepatch.c diff --git a/arch/s390/include/asm/livepatch.h b/arch/s390/include/asm/livepatch.h index d5427c78b1b3..2c1213785892 100644 --- a/arch/s390/include/asm/livepatch.h +++ b/arch/s390/include/asm/livepatch.h @@ -24,13 +24,6 @@ static inline int klp_check_compiler_support(void) return 0; } -static inline int klp_write_module_reloc(struct module *mod, unsigned long - type, unsigned long loc, unsigned long value) -{ - /* not supported yet */ - return -ENOSYS; -} - static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) { regs->psw.addr = ip; diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h index 7e68f9558552..a7f9181f63f3 100644 --- a/arch/x86/include/asm/livepatch.h +++ b/arch/x86/include/asm/livepatch.h @@ -32,8 +32,6 @@ static inline int klp_check_compiler_support(void) #endif return 0; } -int klp_write_module_reloc(struct module *mod, unsigned long type, - unsigned long loc, unsigned long value); static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) { diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index b1b78ffe01d0..c5e9a5cf976b 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -67,7 +67,6 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-y += apic/ obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o -obj-$(CONFIG_LIVEPATCH) += livepatch.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_X86_TSC) += trace_clock.o diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c deleted file mode 100644 index 92fc1a51f994..000000000000 --- a/arch/x86/kernel/livepatch.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * livepatch.c - x86-specific Kernel Live Patching Core - * - * Copyright (C) 2014 Seth Jennings - * Copyright (C) 2014 SUSE - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include -#include -#include -#include - -/** - * klp_write_module_reloc() - write a relocation in a module - * @mod: module in which the section to be modified is found - * @type: ELF relocation type (see asm/elf.h) - * @loc: address that the relocation should be written to - * @value: relocation value (sym address + addend) - * - * This function writes a relocation to the specified location for - * a particular module. - */ -int klp_write_module_reloc(struct module *mod, unsigned long type, - unsigned long loc, unsigned long value) -{ - size_t size = 4; - unsigned long val; - unsigned long core = (unsigned long)mod->core_layout.base; - unsigned long core_size = mod->core_layout.size; - - switch (type) { - case R_X86_64_NONE: - return 0; - case R_X86_64_64: - val = value; - size = 8; - break; - case R_X86_64_32: - val = (u32)value; - break; - case R_X86_64_32S: - val = (s32)value; - break; - case R_X86_64_PC32: - val = (u32)(value - loc); - break; - default: - /* unsupported relocation type */ - return -EINVAL; - } - - if (loc < core || loc >= core + core_size) - /* loc does not point to any symbol inside the module */ - return -EINVAL; - - return probe_kernel_write((void *)loc, &val, size); -} diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index bd830d590465..0933ca47791c 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h @@ -64,28 +64,9 @@ struct klp_func { struct list_head stack_node; }; -/** - * struct klp_reloc - relocation structure for live patching - * @loc: address where the relocation will be written - * @sympos: position in kallsyms to disambiguate symbols (optional) - * @type: ELF relocation type - * @name: name of the referenced symbol (for lookup/verification) - * @addend: offset from the referenced symbol - * @external: symbol is either exported or within the live patch module itself - */ -struct klp_reloc { - unsigned long loc; - unsigned long sympos; - unsigned long type; - const char *name; - int addend; - int external; -}; - /** * struct klp_object - kernel object structure for live patching * @name: module name (or NULL for vmlinux) - * @relocs: relocation entries to be applied at load time * @funcs: function entries for functions to be patched in the object * @kobj: kobject for sysfs resources * @mod: kernel module associated with the patched object @@ -95,7 +76,6 @@ struct klp_reloc { struct klp_object { /* external */ const char *name; - struct klp_reloc *relocs; struct klp_func *funcs; /* internal */ diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index d68fbf63b083..eb5db6e837aa 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include /** @@ -204,75 +206,109 @@ static int klp_find_object_symbol(const char *objname, const char *name, return -EINVAL; } -/* - * external symbols are located outside the parent object (where the parent - * object is either vmlinux or the kmod being patched). - */ -static int klp_find_external_symbol(struct module *pmod, const char *name, - unsigned long *addr) +static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod) { - const struct kernel_symbol *sym; - - /* first, check if it's an exported symbol */ - preempt_disable(); - sym = find_symbol(name, NULL, NULL, true, true); - if (sym) { - *addr = sym->value; - preempt_enable(); - return 0; - } - preempt_enable(); + int i, cnt, vmlinux, ret; + char objname[MODULE_NAME_LEN]; + char symname[KSYM_NAME_LEN]; + char *strtab = pmod->core_kallsyms.strtab; + Elf_Rela *relas; + Elf_Sym *sym; + unsigned long sympos, addr; /* - * Check if it's in another .o within the patch module. This also - * checks that the external symbol is unique. + * Since the field widths for objname and symname in the sscanf() + * call are hard-coded and correspond to MODULE_NAME_LEN and + * KSYM_NAME_LEN respectively, we must make sure that MODULE_NAME_LEN + * and KSYM_NAME_LEN have the values we expect them to have. + * + * Because the value of MODULE_NAME_LEN can differ among architectures, + * we use the smallest/strictest upper bound possible (56, based on + * the current definition of MODULE_NAME_LEN) to prevent overflows. */ - return klp_find_object_symbol(pmod->name, name, 0, addr); + BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128); + + relas = (Elf_Rela *) relasec->sh_addr; + /* For each rela in this klp relocation section */ + for (i = 0; i < relasec->sh_size / sizeof(Elf_Rela); i++) { + sym = pmod->core_kallsyms.symtab + ELF_R_SYM(relas[i].r_info); + if (sym->st_shndx != SHN_LIVEPATCH) { + pr_err("symbol %s is not marked as a livepatch symbol", + strtab + sym->st_name); + return -EINVAL; + } + + /* Format: .klp.sym.objname.symname,sympos */ + cnt = sscanf(strtab + sym->st_name, + ".klp.sym.%55[^.].%127[^,],%lu", + objname, symname, &sympos); + if (cnt != 3) { + pr_err("symbol %s has an incorrectly formatted name", + strtab + sym->st_name); + return -EINVAL; + } + + /* klp_find_object_symbol() treats a NULL objname as vmlinux */ + vmlinux = !strcmp(objname, "vmlinux"); + ret = klp_find_object_symbol(vmlinux ? NULL : objname, + symname, sympos, &addr); + if (ret) + return ret; + + sym->st_value = addr; + } + + return 0; } static int klp_write_object_relocations(struct module *pmod, struct klp_object *obj) { - int ret = 0; - unsigned long val; - struct klp_reloc *reloc; + int i, cnt, ret = 0; + const char *objname, *secname; + char sec_objname[MODULE_NAME_LEN]; + Elf_Shdr *sec; if (WARN_ON(!klp_is_object_loaded(obj))) return -EINVAL; - if (WARN_ON(!obj->relocs)) - return -EINVAL; + objname = klp_is_module(obj) ? obj->name : "vmlinux"; module_disable_ro(pmod); + /* For each klp relocation section */ + for (i = 1; i < pmod->klp_info->hdr.e_shnum; i++) { + sec = pmod->klp_info->sechdrs + i; + secname = pmod->klp_info->secstrings + sec->sh_name; + if (!(sec->sh_flags & SHF_RELA_LIVEPATCH)) + continue; - for (reloc = obj->relocs; reloc->name; reloc++) { - /* discover the address of the referenced symbol */ - if (reloc->external) { - if (reloc->sympos > 0) { - pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n", - reloc->name); - ret = -EINVAL; - goto out; - } - ret = klp_find_external_symbol(pmod, reloc->name, &val); - } else - ret = klp_find_object_symbol(obj->name, - reloc->name, - reloc->sympos, - &val); + /* + * Format: .klp.rela.sec_objname.section_name + * See comment in klp_resolve_symbols() for an explanation + * of the selected field width value. + */ + cnt = sscanf(secname, ".klp.rela.%55[^.]", sec_objname); + if (cnt != 1) { + pr_err("section %s has an incorrectly formatted name", + secname); + ret = -EINVAL; + break; + } + + if (strcmp(objname, sec_objname)) + continue; + + ret = klp_resolve_symbols(sec, pmod); if (ret) - goto out; + break; - ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc, - val + reloc->addend); - if (ret) { - pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n", - reloc->name, val, ret); - goto out; - } + ret = apply_relocate_add(pmod->klp_info->sechdrs, + pmod->core_kallsyms.strtab, + pmod->klp_info->symndx, i, pmod); + if (ret) + break; } -out: module_enable_ro(pmod); return ret; } @@ -703,11 +739,9 @@ static int klp_init_object_loaded(struct klp_patch *patch, struct klp_func *func; int ret; - if (obj->relocs) { - ret = klp_write_object_relocations(patch->mod, obj); - if (ret) - return ret; - } + ret = klp_write_object_relocations(patch->mod, obj); + if (ret) + return ret; klp_for_each_func(obj, func) { ret = klp_find_object_symbol(obj->name, func->old_name, @@ -842,6 +876,12 @@ int klp_register_patch(struct klp_patch *patch) { int ret; + if (!is_livepatch_module(patch->mod)) { + pr_err("module %s is not marked as a livepatch module", + patch->mod->name); + return -EINVAL; + } + if (!klp_initialized()) return -ENODEV; diff --git a/samples/livepatch/livepatch-sample.c b/samples/livepatch/livepatch-sample.c index fb8c8614e728..e34f871e69b1 100644 --- a/samples/livepatch/livepatch-sample.c +++ b/samples/livepatch/livepatch-sample.c @@ -89,3 +89,4 @@ static void livepatch_exit(void) module_init(livepatch_init); module_exit(livepatch_exit); MODULE_LICENSE("GPL"); +MODULE_INFO(livepatch, "Y"); -- GitLab From 3b812ecce736432e6b55e77028ea387eb1517d24 Mon Sep 17 00:00:00 2001 From: Jessica Yu Date: Tue, 22 Mar 2016 20:03:19 -0400 Subject: [PATCH 1085/9938] Documentation: livepatch: outline Elf format and requirements for patch modules Document livepatch module requirements and the special Elf constants patch modules use. Signed-off-by: Jessica Yu Acked-by: Miroslav Benes Acked-by: Josh Poimboeuf Signed-off-by: Jiri Kosina --- Documentation/livepatch/module-elf-format.txt | 311 ++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 Documentation/livepatch/module-elf-format.txt diff --git a/Documentation/livepatch/module-elf-format.txt b/Documentation/livepatch/module-elf-format.txt new file mode 100644 index 000000000000..eedbdcf8ba50 --- /dev/null +++ b/Documentation/livepatch/module-elf-format.txt @@ -0,0 +1,311 @@ +=========================== +Livepatch module Elf format +=========================== + +This document outlines the Elf format requirements that livepatch modules must follow. + +----------------- +Table of Contents +----------------- +0. Background and motivation +1. Livepatch modinfo field +2. Livepatch relocation sections + 2.1 What are livepatch relocation sections? + 2.2 Livepatch relocation section format + 2.2.1 Required flags + 2.2.2 Required name format + 2.2.3 Example livepatch relocation section names + 2.2.4 Example `readelf --sections` output + 2.2.5 Example `readelf --relocs` output +3. Livepatch symbols + 3.1 What are livepatch symbols? + 3.2 A livepatch module's symbol table + 3.3 Livepatch symbol format + 3.3.1 Required flags + 3.3.2 Required name format + 3.3.3 Example livepatch symbol names + 3.3.4 Example `readelf --symbols` output +4. Symbol table and Elf section access + +---------------------------- +0. Background and motivation +---------------------------- + +Formerly, livepatch required separate architecture-specific code to write +relocations. However, arch-specific code to write relocations already +exists in the module loader, so this former approach produced redundant +code. So, instead of duplicating code and re-implementing what the module +loader can already do, livepatch leverages existing code in the module +loader to perform the all the arch-specific relocation work. Specifically, +livepatch reuses the apply_relocate_add() function in the module loader to +write relocations. The patch module Elf format described in this document +enables livepatch to be able to do this. The hope is that this will make +livepatch more easily portable to other architectures and reduce the amount +of arch-specific code required to port livepatch to a particular +architecture. + +Since apply_relocate_add() requires access to a module's section header +table, symbol table, and relocation section indices, Elf information is +preserved for livepatch modules (see section 4). Livepatch manages its own +relocation sections and symbols, which are described in this document. The +Elf constants used to mark livepatch symbols and relocation sections were +selected from OS-specific ranges according to the definitions from glibc. + +0.1 Why does livepatch need to write its own relocations? +--------------------------------------------------------- +A typical livepatch module contains patched versions of functions that can +reference non-exported global symbols and non-included local symbols. +Relocations referencing these types of symbols cannot be left in as-is +since the kernel module loader cannot resolve them and will therefore +reject the livepatch module. Furthermore, we cannot apply relocations that +affect modules not yet loaded at patch module load time (e.g. a patch to a +driver that is not loaded). Formerly, livepatch solved this problem by +embedding special "dynrela" (dynamic rela) sections in the resulting patch +module Elf output. Using these dynrela sections, livepatch could resolve +symbols while taking into account its scope and what module the symbol +belongs to, and then manually apply the dynamic relocations. However this +approach required livepatch to supply arch-specific code in order to write +these relocations. In the new format, livepatch manages its own SHT_RELA +relocation sections in place of dynrela sections, and the symbols that the +relas reference are special livepatch symbols (see section 2 and 3). The +arch-specific livepatch relocation code is replaced by a call to +apply_relocate_add(). + +================================ +PATCH MODULE FORMAT REQUIREMENTS +================================ + +-------------------------- +1. Livepatch modinfo field +-------------------------- + +Livepatch modules are required to have the "livepatch" modinfo attribute. +See the sample livepatch module in samples/livepatch/ for how this is done. + +Livepatch modules can be identified by users by using the 'modinfo' command +and looking for the presence of the "livepatch" field. This field is also +used by the kernel module loader to identify livepatch modules. + +Example modinfo output: +----------------------- +% modinfo livepatch-meminfo.ko +filename: livepatch-meminfo.ko +livepatch: Y +license: GPL +depends: +vermagic: 4.3.0+ SMP mod_unload + +-------------------------------- +2. Livepatch relocation sections +-------------------------------- + +------------------------------------------- +2.1 What are livepatch relocation sections? +------------------------------------------- +A livepatch module manages its own Elf relocation sections to apply +relocations to modules as well as to the kernel (vmlinux) at the +appropriate time. For example, if a patch module patches a driver that is +not currently loaded, livepatch will apply the corresponding livepatch +relocation section(s) to the driver once it loads. + +Each "object" (e.g. vmlinux, or a module) within a patch module may have +multiple livepatch relocation sections associated with it (e.g. patches to +multiple functions within the same object). There is a 1-1 correspondence +between a livepatch relocation section and the target section (usually the +text section of a function) to which the relocation(s) apply. It is +also possible for a livepatch module to have no livepatch relocation +sections, as in the case of the sample livepatch module (see +samples/livepatch). + +Since Elf information is preserved for livepatch modules (see Section 4), a +livepatch relocation section can be applied simply by passing in the +appropriate section index to apply_relocate_add(), which then uses it to +access the relocation section and apply the relocations. + +Every symbol referenced by a rela in a livepatch relocation section is a +livepatch symbol. These must be resolved before livepatch can call +apply_relocate_add(). See Section 3 for more information. + +--------------------------------------- +2.2 Livepatch relocation section format +--------------------------------------- + +2.2.1 Required flags +-------------------- +Livepatch relocation sections must be marked with the SHF_RELA_LIVEPATCH +section flag. See include/uapi/linux/elf.h for the definition. The module +loader recognizes this flag and will avoid applying those relocation sections +at patch module load time. These sections must also be marked with SHF_ALLOC, +so that the module loader doesn't discard them on module load (i.e. they will +be copied into memory along with the other SHF_ALLOC sections). + +2.2.2 Required name format +-------------------------- +The name of a livepatch relocation section must conform to the following format: + +.klp.rela.objname.section_name +^ ^^ ^ ^ ^ +|________||_____| |__________| + [A] [B] [C] + +[A] The relocation section name is prefixed with the string ".klp.rela." +[B] The name of the object (i.e. "vmlinux" or name of module) to + which the relocation section belongs follows immediately after the prefix. +[C] The actual name of the section to which this relocation section applies. + +2.2.3 Example livepatch relocation section names: +------------------------------------------------- +.klp.rela.ext4.text.ext4_attr_store +.klp.rela.vmlinux.text.cmdline_proc_show + +2.2.4 Example `readelf --sections` output for a patch +module that patches vmlinux and modules 9p, btrfs, ext4: +-------------------------------------------------------- + Section Headers: + [Nr] Name Type Address Off Size ES Flg Lk Inf Al + [ snip ] + [29] .klp.rela.9p.text.caches.show RELA 0000000000000000 002d58 0000c0 18 AIo 64 9 8 + [30] .klp.rela.btrfs.text.btrfs.feature.attr.show RELA 0000000000000000 002e18 000060 18 AIo 64 11 8 + [ snip ] + [34] .klp.rela.ext4.text.ext4.attr.store RELA 0000000000000000 002fd8 0000d8 18 AIo 64 13 8 + [35] .klp.rela.ext4.text.ext4.attr.show RELA 0000000000000000 0030b0 000150 18 AIo 64 15 8 + [36] .klp.rela.vmlinux.text.cmdline.proc.show RELA 0000000000000000 003200 000018 18 AIo 64 17 8 + [37] .klp.rela.vmlinux.text.meminfo.proc.show RELA 0000000000000000 003218 0000f0 18 AIo 64 19 8 + [ snip ] ^ ^ + | | + [*] [*] +[*] Livepatch relocation sections are SHT_RELA sections but with a few special +characteristics. Notice that they are marked SHF_ALLOC ("A") so that they will +not be discarded when the module is loaded into memory, as well as with the +SHF_RELA_LIVEPATCH flag ("o" - for OS-specific). + +2.2.5 Example `readelf --relocs` output for a patch module: +----------------------------------------------------------- +Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries: + Offset Info Type Symbol's Value Symbol's Name + Addend +000000000000001f 0000005e00000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.printk,0 - 4 +0000000000000028 0000003d0000000b R_X86_64_32S 0000000000000000 .klp.sym.btrfs.btrfs_ktype,0 + 0 +0000000000000036 0000003b00000002 R_X86_64_PC32 0000000000000000 .klp.sym.btrfs.can_modify_feature.isra.3,0 - 4 +000000000000004c 0000004900000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.snprintf,0 - 4 +[ snip ] ^ + | + [*] +[*] Every symbol referenced by a relocation is a livepatch symbol. + +-------------------- +3. Livepatch symbols +-------------------- + +------------------------------- +3.1 What are livepatch symbols? +------------------------------- +Livepatch symbols are symbols referred to by livepatch relocation sections. +These are symbols accessed from new versions of functions for patched +objects, whose addresses cannot be resolved by the module loader (because +they are local or unexported global syms). Since the module loader only +resolves exported syms, and not every symbol referenced by the new patched +functions is exported, livepatch symbols were introduced. They are used +also in cases where we cannot immediately know the address of a symbol when +a patch module loads. For example, this is the case when livepatch patches +a module that is not loaded yet. In this case, the relevant livepatch +symbols are resolved simply when the target module loads. In any case, for +any livepatch relocation section, all livepatch symbols referenced by that +section must be resolved before livepatch can call apply_relocate_add() for +that reloc section. + +Livepatch symbols must be marked with SHN_LIVEPATCH so that the module +loader can identify and ignore them. Livepatch modules keep these symbols +in their symbol tables, and the symbol table is made accessible through +module->symtab. + +------------------------------------- +3.2 A livepatch module's symbol table +------------------------------------- +Normally, a stripped down copy of a module's symbol table (containing only +"core" symbols) is made available through module->symtab (See layout_symtab() +in kernel/module.c). For livepatch modules, the symbol table copied into memory +on module load must be exactly the same as the symbol table produced when the +patch module was compiled. This is because the relocations in each livepatch +relocation section refer to their respective symbols with their symbol indices, +and the original symbol indices (and thus the symtab ordering) must be +preserved in order for apply_relocate_add() to find the right symbol. + +For example, take this particular rela from a livepatch module: +Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries: + Offset Info Type Symbol's Value Symbol's Name + Addend +000000000000001f 0000005e00000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.printk,0 - 4 + +This rela refers to the symbol '.klp.sym.vmlinux.printk,0', and the symbol index is encoded +in 'Info'. Here its symbol index is 0x5e, which is 94 in decimal, which refers to the +symbol index 94. +And in this patch module's corresponding symbol table, symbol index 94 refers to that very symbol: +[ snip ] +94: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.printk,0 +[ snip ] + +--------------------------- +3.3 Livepatch symbol format +--------------------------- + +3.3.1 Required flags +-------------------- +Livepatch symbols must have their section index marked as SHN_LIVEPATCH, so +that the module loader can identify them and not attempt to resolve them. +See include/uapi/linux/elf.h for the actual definitions. + +3.3.2 Required name format +-------------------------- +Livepatch symbol names must conform to the following format: + +.klp.sym.objname.symbol_name,sympos +^ ^^ ^ ^ ^ ^ +|_______||_____| |_________| | + [A] [B] [C] [D] + +[A] The symbol name is prefixed with the string ".klp.sym." +[B] The name of the object (i.e. "vmlinux" or name of module) to + which the symbol belongs follows immediately after the prefix. +[C] The actual name of the symbol. +[D] The position of the symbol in the object (as according to kallsyms) + This is used to differentiate duplicate symbols within the same + object. The symbol position is expressed numerically (0, 1, 2...). + The symbol position of a unique symbol is 0. + +3.3.3 Example livepatch symbol names: +------------------------------------- +.klp.sym.vmlinux.snprintf,0 +.klp.sym.vmlinux.printk,0 +.klp.sym.btrfs.btrfs_ktype,0 + +3.3.4 Example `readelf --symbols` output for a patch module: +------------------------------------------------------------ +Symbol table '.symtab' contains 127 entries: + Num: Value Size Type Bind Vis Ndx Name + [ snip ] + 73: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.snprintf,0 + 74: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.capable,0 + 75: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.find_next_bit,0 + 76: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.si_swapinfo,0 + [ snip ] ^ + | + [*] +[*] Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20). + "OS" means OS-specific. + +-------------------------------------- +4. Symbol table and Elf section access +-------------------------------------- +A livepatch module's symbol table is accessible through module->symtab. + +Since apply_relocate_add() requires access to a module's section headers, +symbol table, and relocation section indices, Elf information is preserved for +livepatch modules and is made accessible by the module loader through +module->klp_info, which is a klp_modinfo struct. When a livepatch module loads, +this struct is filled in by the module loader. Its fields are documented below: + +struct klp_modinfo { + Elf_Ehdr hdr; /* Elf header */ + Elf_Shdr *sechdrs; /* Section header table */ + char *secstrings; /* String table for the section headers */ + unsigned int symndx; /* The symbol table section index */ +}; -- GitLab From d32f7fd3bbc32732b094d938b95169521503a9fb Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 31 Mar 2016 14:44:42 +0300 Subject: [PATCH 1086/9938] pinctrl: Rename pinctrl_utils_dt_free_map to pinctrl_utils_free_map Rename pinctrl_utils_dt_free_map to pinctrl_utils_free_map, since it does not depend on device tree despite the current name. This will enforce a consistent naming in pinctr-utils.c and will make it clear it can be called from outside device tree (e.g. from ACPI handling code). Signed-off-by: Irina Tirdea Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 2 +- drivers/pinctrl/bcm/pinctrl-cygnus-mux.c | 2 +- drivers/pinctrl/bcm/pinctrl-iproc-gpio.c | 2 +- drivers/pinctrl/bcm/pinctrl-nsp-gpio.c | 2 +- drivers/pinctrl/berlin/berlin.c | 2 +- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 4 ++-- drivers/pinctrl/meson/pinctrl-meson.c | 2 +- drivers/pinctrl/nomadik/pinctrl-abx500.c | 4 ++-- drivers/pinctrl/nomadik/pinctrl-nomadik.c | 4 ++-- drivers/pinctrl/pinconf-generic.c | 2 +- drivers/pinctrl/pinctrl-amd.c | 2 +- drivers/pinctrl/pinctrl-as3722.c | 2 +- drivers/pinctrl/pinctrl-at91-pio4.c | 4 ++-- drivers/pinctrl/pinctrl-digicolor.c | 2 +- drivers/pinctrl/pinctrl-lpc18xx.c | 2 +- drivers/pinctrl/pinctrl-palmas.c | 2 +- drivers/pinctrl/pinctrl-pic32.c | 2 +- drivers/pinctrl/pinctrl-pistachio.c | 2 +- drivers/pinctrl/pinctrl-tb10x.c | 2 +- drivers/pinctrl/pinctrl-utils.c | 4 ++-- drivers/pinctrl/pinctrl-utils.h | 2 +- drivers/pinctrl/pinctrl-zynq.c | 2 +- drivers/pinctrl/pxa/pinctrl-pxa2xx.c | 2 +- drivers/pinctrl/qcom/pinctrl-msm.c | 2 +- drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 2 +- drivers/pinctrl/qcom/pinctrl-spmi-mpp.c | 2 +- drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c | 2 +- drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c | 2 +- drivers/pinctrl/stm32/pinctrl-stm32.c | 4 ++-- drivers/pinctrl/tegra/pinctrl-tegra-xusb.c | 2 +- drivers/pinctrl/tegra/pinctrl-tegra.c | 4 ++-- drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 2 +- 32 files changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c index c3c692e508e8..f043b83b18f0 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c @@ -1024,7 +1024,7 @@ static struct pinctrl_ops bcm281xx_pinctrl_ops = { .get_group_pins = bcm281xx_pinctrl_get_group_pins, .pin_dbg_show = bcm281xx_pinctrl_pin_dbg_show, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c index 9728f3db9126..f0184dc16730 100644 --- a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c @@ -737,7 +737,7 @@ static const struct pinctrl_ops cygnus_pinctrl_ops = { .get_group_pins = cygnus_get_group_pins, .pin_dbg_show = cygnus_pin_dbg_show, .dt_node_to_map = pinconf_generic_dt_node_to_map_group, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int cygnus_get_functions_count(struct pinctrl_dev *pctrl_dev) diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index d530ab4b9d85..9ed98813c7d0 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -379,7 +379,7 @@ static const struct pinctrl_ops iproc_pctrl_ops = { .get_groups_count = iproc_get_groups_count, .get_group_name = iproc_get_group_name, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio, diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c index ac900435dc39..6c7d5f500f35 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c @@ -363,7 +363,7 @@ static const struct pinctrl_ops nsp_pctrl_ops = { .get_groups_count = nsp_get_groups_count, .get_group_name = nsp_get_group_name, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u16 slew) diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c index 46f2b4818da3..87b17b77df02 100644 --- a/drivers/pinctrl/berlin/berlin.c +++ b/drivers/pinctrl/berlin/berlin.c @@ -104,7 +104,7 @@ static const struct pinctrl_ops berlin_pinctrl_ops = { .get_groups_count = &berlin_pinctrl_get_group_count, .get_group_name = &berlin_pinctrl_get_group_name, .dt_node_to_map = &berlin_pinctrl_dt_node_to_map, - .dt_free_map = &pinctrl_utils_dt_free_map, + .dt_free_map = &pinctrl_utils_free_map, }; static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 2bbe6f7964a7..8ca82c134260 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -605,7 +605,7 @@ static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_free_map(pctldev, *map, *num_maps); of_node_put(np); return ret; } @@ -644,7 +644,7 @@ static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev, static const struct pinctrl_ops mtk_pctrl_ops = { .dt_node_to_map = mtk_pctrl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, .get_groups_count = mtk_pctrl_get_groups_count, .get_group_name = mtk_pctrl_get_group_name, .get_group_pins = mtk_pctrl_get_group_pins, diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index 0bdb8fd3afd1..5bcbd3ee758c 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -171,7 +171,7 @@ static const struct pinctrl_ops meson_pctrl_ops = { .get_group_name = meson_get_group_name, .get_group_pins = meson_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_all, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, .pin_dbg_show = meson_pin_dbg_show, }; diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 1f7469c9857d..532356823eea 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -937,7 +937,7 @@ static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev, ret = abx500_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_free_map(pctldev, *map, *num_maps); return ret; } } @@ -951,7 +951,7 @@ static const struct pinctrl_ops abx500_pinctrl_ops = { .get_group_pins = abx500_get_group_pins, .pin_dbg_show = abx500_pin_dbg_show, .dt_node_to_map = abx500_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int abx500_pin_config_get(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 352406108fa0..c9c8c17678d7 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -1612,7 +1612,7 @@ static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_free_map(pctldev, *map, *num_maps); return ret; } } @@ -1626,7 +1626,7 @@ static const struct pinctrl_ops nmk_pinctrl_ops = { .get_group_pins = nmk_get_group_pins, .pin_dbg_show = nmk_pin_dbg_show, .dt_node_to_map = nmk_pinctrl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 79e6159712c2..d5bf9fae2ddd 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -386,7 +386,7 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev, return 0; exit: - pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_free_map(pctldev, *map, *num_maps); return ret; } EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map); diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index cc44ae8c8758..b0e2ec0daed3 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -580,7 +580,7 @@ static const struct pinctrl_ops amd_pinctrl_ops = { .get_group_pins = amd_get_group_pins, #ifdef CONFIG_OF .dt_node_to_map = pinconf_generic_dt_node_to_map_group, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, #endif }; diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c index e844fdc6d3a8..1070bb9fa99d 100644 --- a/drivers/pinctrl/pinctrl-as3722.c +++ b/drivers/pinctrl/pinctrl-as3722.c @@ -201,7 +201,7 @@ static const struct pinctrl_ops as3722_pinctrl_ops = { .get_group_name = as3722_pinctrl_get_group_name, .get_group_pins = as3722_pinctrl_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int as3722_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 4429312e848d..629b6fefa8e0 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -579,7 +579,7 @@ static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_free_map(pctldev, *map, *num_maps); dev_err(pctldev->dev, "can't create maps for node %s\n", np_config->full_name); } @@ -592,7 +592,7 @@ static const struct pinctrl_ops atmel_pctlops = { .get_group_name = atmel_pctl_get_group_name, .get_group_pins = atmel_pctl_get_group_pins, .dt_node_to_map = atmel_pctl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c index f1343d6ca823..b347806215e7 100644 --- a/drivers/pinctrl/pinctrl-digicolor.c +++ b/drivers/pinctrl/pinctrl-digicolor.c @@ -84,7 +84,7 @@ static struct pinctrl_ops dc_pinctrl_ops = { .get_group_name = dc_get_group_name, .get_group_pins = dc_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static const char *const dc_functions[] = { diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c index b1767f7e45d1..e897b63bd1bb 100644 --- a/drivers/pinctrl/pinctrl-lpc18xx.c +++ b/drivers/pinctrl/pinctrl-lpc18xx.c @@ -1252,7 +1252,7 @@ static const struct pinctrl_ops lpc18xx_pctl_ops = { .get_group_name = lpc18xx_pctl_get_group_name, .get_group_pins = lpc18xx_pctl_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static struct pinctrl_desc lpc18xx_scu_desc = { diff --git a/drivers/pinctrl/pinctrl-palmas.c b/drivers/pinctrl/pinctrl-palmas.c index f7e168044baf..8f0163feda28 100644 --- a/drivers/pinctrl/pinctrl-palmas.c +++ b/drivers/pinctrl/pinctrl-palmas.c @@ -656,7 +656,7 @@ static const struct pinctrl_ops palmas_pinctrl_ops = { .get_group_name = palmas_pinctrl_get_group_name, .get_group_pins = palmas_pinctrl_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int palmas_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c index 0b07d4bdab95..87ee1c4e70a7 100644 --- a/drivers/pinctrl/pinctrl-pic32.c +++ b/drivers/pinctrl/pinctrl-pic32.c @@ -1743,7 +1743,7 @@ static const struct pinctrl_ops pic32_pinctrl_ops = { .get_group_name = pic32_pinctrl_get_group_name, .get_group_pins = pic32_pinctrl_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int pic32_pinmux_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c index 856f736cb1a6..846fe91aa155 100644 --- a/drivers/pinctrl/pinctrl-pistachio.c +++ b/drivers/pinctrl/pinctrl-pistachio.c @@ -913,7 +913,7 @@ static const struct pinctrl_ops pistachio_pinctrl_ops = { .get_group_name = pistachio_pinctrl_get_group_name, .get_group_pins = pistachio_pinctrl_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int pistachio_pinmux_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c index 6546b9bb2e06..620af57f10ad 100644 --- a/drivers/pinctrl/pinctrl-tb10x.c +++ b/drivers/pinctrl/pinctrl-tb10x.c @@ -582,7 +582,7 @@ static struct pinctrl_ops tb10x_pinctrl_ops = { .get_group_name = tb10x_get_group_name, .get_group_pins = tb10x_get_group_pins, .dt_node_to_map = tb10x_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int tb10x_get_functions_count(struct pinctrl_dev *pctl) diff --git a/drivers/pinctrl/pinctrl-utils.c b/drivers/pinctrl/pinctrl-utils.c index d77693f2cc1b..9189fbafb102 100644 --- a/drivers/pinctrl/pinctrl-utils.c +++ b/drivers/pinctrl/pinctrl-utils.c @@ -122,7 +122,7 @@ int pinctrl_utils_add_config(struct pinctrl_dev *pctldev, } EXPORT_SYMBOL_GPL(pinctrl_utils_add_config); -void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev, +void pinctrl_utils_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps) { int i; @@ -139,4 +139,4 @@ void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev, } kfree(map); } -EXPORT_SYMBOL_GPL(pinctrl_utils_dt_free_map); +EXPORT_SYMBOL_GPL(pinctrl_utils_free_map); diff --git a/drivers/pinctrl/pinctrl-utils.h b/drivers/pinctrl/pinctrl-utils.h index d0ffe1ce200f..8f9f2d28c5b8 100644 --- a/drivers/pinctrl/pinctrl-utils.h +++ b/drivers/pinctrl/pinctrl-utils.h @@ -37,7 +37,7 @@ int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev, int pinctrl_utils_add_config(struct pinctrl_dev *pctldev, unsigned long **configs, unsigned *num_configs, unsigned long config); -void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev, +void pinctrl_utils_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps); #endif /* __PINCTRL_UTILS_H__ */ diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c index 76f1abd71e31..3f1b55f675a5 100644 --- a/drivers/pinctrl/pinctrl-zynq.c +++ b/drivers/pinctrl/pinctrl-zynq.c @@ -862,7 +862,7 @@ static const struct pinctrl_ops zynq_pctrl_ops = { .get_group_name = zynq_pctrl_get_group_name, .get_group_pins = zynq_pctrl_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_all, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; /* pinmux */ diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c index f553313bc2ef..6098685f0116 100644 --- a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c @@ -57,7 +57,7 @@ static int pxa2xx_pctrl_get_group_pins(struct pinctrl_dev *pctldev, static const struct pinctrl_ops pxa2xx_pctl_ops = { #ifdef CONFIG_OF .dt_node_to_map = pinconf_generic_dt_node_to_map_all, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, #endif .get_groups_count = pxa2xx_pctrl_get_groups_count, .get_group_name = pxa2xx_pctrl_get_group_name, diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 8777cf083eef..f9322d4c2294 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -101,7 +101,7 @@ static const struct pinctrl_ops msm_pinctrl_ops = { .get_group_name = msm_get_group_name, .get_group_pins = msm_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_group, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int msm_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 4e12ded3c773..857ccfa67986 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -212,7 +212,7 @@ static const struct pinctrl_ops pmic_gpio_pinctrl_ops = { .get_group_name = pmic_gpio_get_group_name, .get_group_pins = pmic_gpio_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_group, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int pmic_gpio_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c index 2a3e5490a483..469660055809 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c @@ -235,7 +235,7 @@ static const struct pinctrl_ops pmic_mpp_pinctrl_ops = { .get_group_name = pmic_mpp_get_group_name, .get_group_pins = pmic_mpp_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_group, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int pmic_mpp_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c index cd8580d9741d..ecd784b6c743 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c @@ -200,7 +200,7 @@ static const struct pinctrl_ops pm8xxx_pinctrl_ops = { .get_group_name = pm8xxx_get_group_name, .get_group_pins = pm8xxx_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_group, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c index 54a5402a9079..ac79021eb261 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c @@ -277,7 +277,7 @@ static const struct pinctrl_ops pm8xxx_pinctrl_ops = { .get_group_name = pm8xxx_get_group_name, .get_group_pins = pm8xxx_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_group, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 8deb566ed4cd..b97b7c01f942 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -358,7 +358,7 @@ static int stm32_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, ret = stm32_pctrl_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_free_map(pctldev, *map, *num_maps); return ret; } } @@ -396,7 +396,7 @@ static int stm32_pctrl_get_group_pins(struct pinctrl_dev *pctldev, static const struct pinctrl_ops stm32_pctrl_ops = { .dt_node_to_map = stm32_pctrl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, .get_groups_count = stm32_pctrl_get_groups_count, .get_group_name = stm32_pctrl_get_group_name, .get_group_pins = stm32_pctrl_get_group_pins, diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c index 2f06029c9405..e58b5f344b34 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c @@ -267,7 +267,7 @@ static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = { .get_group_name = tegra_xusb_padctl_get_group_name, .get_group_pins = tegra_xusb_padctl_get_group_pins, .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl) diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index 49388822c0e9..3f7fce9075ab 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -215,7 +215,7 @@ static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, + pinctrl_utils_free_map(pctldev, *map, *num_maps); of_node_put(np); return ret; @@ -233,7 +233,7 @@ static const struct pinctrl_ops tegra_pinctrl_ops = { .pin_dbg_show = tegra_pinctrl_pin_dbg_show, #endif .dt_node_to_map = tegra_pinctrl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index 589872cc8adb..c9e4a852afa5 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -115,7 +115,7 @@ static const struct pinctrl_ops uniphier_pctlops = { .pin_dbg_show = uniphier_pctl_pin_dbg_show, #endif .dt_node_to_map = pinconf_generic_dt_node_to_map_all, - .dt_free_map = pinctrl_utils_dt_free_map, + .dt_free_map = pinctrl_utils_free_map, }; static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev, -- GitLab From 6e667fac8259d0dd2cf883fa3c51c0b8b8c89a90 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 1 Apr 2016 16:16:13 +0200 Subject: [PATCH 1087/9938] reset: Add Oxford Semiconductor Reset Controller driver Add System reset controller driver for Oxford Semiconductor OXNAS SoC Family. CC: Ma Haijun Signed-off-by: Neil Armstrong Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 3 + drivers/reset/Makefile | 1 + drivers/reset/reset-oxnas.c | 136 ++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 drivers/reset/reset-oxnas.c diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index df37212a5cbd..0b2733db0e9e 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -12,5 +12,8 @@ menuconfig RESET_CONTROLLER If unsure, say no. +config RESET_OXNAS + bool + source "drivers/reset/sti/Kconfig" source "drivers/reset/hisilicon/Kconfig" diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index a1fc8eda79f3..f173fc3847b4 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_ARCH_STI) += sti/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o obj-$(CONFIG_ATH79) += reset-ath79.o +obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c new file mode 100644 index 000000000000..c60fb2dace3e --- /dev/null +++ b/drivers/reset/reset-oxnas.c @@ -0,0 +1,136 @@ +/* + * drivers/reset/reset-oxnas.c + * + * Copyright (C) 2016 Neil Armstrong + * Copyright (C) 2014 Ma Haijun + * Copyright (C) 2009 Oxford Semiconductor Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Regmap offsets */ +#define RST_SET_REGOFFSET 0x34 +#define RST_CLR_REGOFFSET 0x38 + +struct oxnas_reset { + struct regmap *regmap; + struct reset_controller_dev rcdev; +}; + +static int oxnas_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct oxnas_reset *data = + container_of(rcdev, struct oxnas_reset, rcdev); + + regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); + msleep(50); + regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); + + return 0; +} + +static int oxnas_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct oxnas_reset *data = + container_of(rcdev, struct oxnas_reset, rcdev); + + regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); + + return 0; +} + +static int oxnas_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct oxnas_reset *data = + container_of(rcdev, struct oxnas_reset, rcdev); + + regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); + + return 0; +} + +static const struct reset_control_ops oxnas_reset_ops = { + .reset = oxnas_reset_reset, + .assert = oxnas_reset_assert, + .deassert = oxnas_reset_deassert, +}; + +static const struct of_device_id oxnas_reset_dt_ids[] = { + { .compatible = "oxsemi,ox810se-reset", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids); + +static int oxnas_reset_probe(struct platform_device *pdev) +{ + struct oxnas_reset *data; + struct device *parent; + + parent = pdev->dev.parent; + if (!parent) { + dev_err(&pdev->dev, "no parent\n"); + return -ENODEV; + } + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->regmap = syscon_node_to_regmap(parent->of_node); + if (IS_ERR(data->regmap)) { + dev_err(&pdev->dev, "failed to get parent regmap\n"); + return PTR_ERR(data->regmap); + } + + platform_set_drvdata(pdev, data); + + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = 32; + data->rcdev.ops = &oxnas_reset_ops; + data->rcdev.of_node = pdev->dev.of_node; + + return reset_controller_register(&data->rcdev); +} + +static int oxnas_reset_remove(struct platform_device *pdev) +{ + struct oxnas_reset *data = platform_get_drvdata(pdev); + + reset_controller_unregister(&data->rcdev); + + return 0; +} + +static struct platform_driver oxnas_reset_driver = { + .probe = oxnas_reset_probe, + .remove = oxnas_reset_remove, + .driver = { + .name = "oxnas-reset", + .of_match_table = oxnas_reset_dt_ids, + }, +}; + +module_platform_driver(oxnas_reset_driver); -- GitLab From 6cf151fc53aeaa7757d3b9ab608bb7e51154de06 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 1 Apr 2016 16:16:14 +0200 Subject: [PATCH 1088/9938] dt-bindings: Add Oxford Semiconductor Reset Controller bindings Add bindings for the Oxford Semiconductor OXNAS reset controller. Acked-by: Rob Herring Signed-off-by: Neil Armstrong Signed-off-by: Philipp Zabel --- .../devicetree/bindings/reset/oxnas,reset.txt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/oxnas,reset.txt diff --git a/Documentation/devicetree/bindings/reset/oxnas,reset.txt b/Documentation/devicetree/bindings/reset/oxnas,reset.txt new file mode 100644 index 000000000000..6f06db930030 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/oxnas,reset.txt @@ -0,0 +1,58 @@ +Oxford Semiconductor OXNAS SoC Family RESET Controller +================================================ + +Please also refer to reset.txt in this directory for common reset +controller binding usage. + +Required properties: +- compatible: Should be "oxsemi,ox810se-reset" +- #reset-cells: 1, see below + +Parent node should have the following properties : +- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd" + +For OX810SE, the indices are : + - 0 : ARM + - 1 : COPRO + - 2 : Reserved + - 3 : Reserved + - 4 : USBHS + - 5 : USBHSPHY + - 6 : MAC + - 7 : PCI + - 8 : DMA + - 9 : DPE + - 10 : DDR + - 11 : SATA + - 12 : SATA_LINK + - 13 : SATA_PHY + - 14 : Reserved + - 15 : NAND + - 16 : GPIO + - 17 : UART1 + - 18 : UART2 + - 19 : MISC + - 20 : I2S + - 21 : AHB_MON + - 22 : UART3 + - 23 : UART4 + - 24 : SGDMA + - 25 : Reserved + - 26 : Reserved + - 27 : Reserved + - 28 : Reserved + - 29 : Reserved + - 30 : Reserved + - 31 : BUS + +example: + +sys: sys-ctrl@000000 { + compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"; + reg = <0x000000 0x100000>; + + reset: reset-controller { + compatible = "oxsemi,ox810se-reset"; + #reset-cells = <1>; + }; +}; -- GitLab From 1ab0c304a029fe3f2338c505b81df02d4220dbc7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 6 Aug 2015 22:57:08 +0200 Subject: [PATCH 1089/9938] ARM: dts: rockchip: update rk3288-veyron cpu operating points The generic operating points specified in rk3288.dtsi are specified by Rockchip as conservative and for all cases. In contrast the Veyron ChromeOS devices are supposed to use a special chip variant often called rk3288-c and use different operating points in their kernel also including a higher max frequency. So override the operating points for veyron devices. Signed-off-by: Heiko Stuebner Reviewed-by: Douglas Anderson --- arch/arm/boot/dts/rk3288-veyron.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi index bfb20c878384..b2557bf5a58f 100644 --- a/arch/arm/boot/dts/rk3288-veyron.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi @@ -141,6 +141,22 @@ &cpu0 { cpu0-supply = <&vdd_cpu>; + operating-points = < + /* KHz uV */ + 1800000 1400000 + 1704000 1350000 + 1608000 1300000 + 1512000 1250000 + 1416000 1200000 + 1200000 1100000 + 1008000 1050000 + 816000 1000000 + 696000 950000 + 600000 900000 + 408000 900000 + 216000 900000 + 126000 900000 + >; }; &emmc { -- GitLab From 2a28e23049af99e1c810111ef5e56455cafeda45 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Mar 2016 10:38:50 +0200 Subject: [PATCH 1090/9938] perf jit: Add support for using TSC as a timestamp Intel PT uses TSC as a timestamp, so add support for using TSC instead of the monotonic clock. Use of TSC is selected by an environment variable "JITDUMP_USE_ARCH_TIMESTAMP" and flagged in the jitdump file with flag JITDUMP_FLAGS_ARCH_TIMESTAMP. Signed-off-by: Adrian Hunter Cc: Alexander Shishkin Cc: He Kuang Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Sukadev Bhattiprolu Cc: Wang Nan Link: http://lkml.kernel.org/r/1457426330-30226-1-git-send-email-adrian.hunter@intel.com [ Added the fixup from He Kuang to make it build on other arches, ] [ such as aarch64, to avoid inserting this bisectiong breakage upstream ] Link: http://lkml.kernel.org/r/1459482572-129494-1-git-send-email-hekuang@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/tsc.c | 1 - tools/perf/arch/x86/util/tsc.h | 17 -------------- tools/perf/jvmti/jvmti_agent.c | 43 ++++++++++++++++++++++++++++++++-- tools/perf/util/Build | 3 +-- tools/perf/util/jitdump.c | 37 +++++++++++++++++++++++++---- tools/perf/util/jitdump.h | 3 +++ tools/perf/util/tsc.h | 11 ++++++++- 7 files changed, 87 insertions(+), 28 deletions(-) delete mode 100644 tools/perf/arch/x86/util/tsc.h diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c index 70ff7c14bea6..357f1b13b5ae 100644 --- a/tools/perf/arch/x86/util/tsc.c +++ b/tools/perf/arch/x86/util/tsc.c @@ -7,7 +7,6 @@ #include #include "../../util/debug.h" #include "../../util/tsc.h" -#include "tsc.h" int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, struct perf_tsc_conversion *tc) diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h deleted file mode 100644 index 2edc4d31065c..000000000000 --- a/tools/perf/arch/x86/util/tsc.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ -#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ - -#include - -struct perf_tsc_conversion { - u16 time_shift; - u32 time_mult; - u64 time_zero; -}; - -struct perf_event_mmap_page; - -int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, - struct perf_tsc_conversion *tc); - -#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */ diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c index 6461e02ab940..3573f315f955 100644 --- a/tools/perf/jvmti/jvmti_agent.c +++ b/tools/perf/jvmti/jvmti_agent.c @@ -92,6 +92,22 @@ static int get_e_machine(struct jitheader *hdr) return ret; } +static int use_arch_timestamp; + +static inline uint64_t +get_arch_timestamp(void) +{ +#if defined(__i386__) || defined(__x86_64__) + unsigned int low, high; + + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + + return low | ((uint64_t)high) << 32; +#else + return 0; +#endif +} + #define NSEC_PER_SEC 1000000000 static int perf_clk_id = CLOCK_MONOTONIC; @@ -107,6 +123,9 @@ perf_get_timestamp(void) struct timespec ts; int ret; + if (use_arch_timestamp) + return get_arch_timestamp(); + ret = clock_gettime(perf_clk_id, &ts); if (ret) return 0; @@ -203,6 +222,17 @@ perf_close_marker_file(void) munmap(marker_addr, pgsz); } +static void +init_arch_timestamp(void) +{ + char *str = getenv("JITDUMP_USE_ARCH_TIMESTAMP"); + + if (!str || !*str || !strcmp(str, "0")) + return; + + use_arch_timestamp = 1; +} + void *jvmti_open(void) { int pad_cnt; @@ -211,11 +241,17 @@ void *jvmti_open(void) int fd; FILE *fp; + init_arch_timestamp(); + /* * check if clockid is supported */ - if (!perf_get_timestamp()) - warnx("jvmti: kernel does not support %d clock id", perf_clk_id); + if (!perf_get_timestamp()) { + if (use_arch_timestamp) + warnx("jvmti: arch timestamp not supported"); + else + warnx("jvmti: kernel does not support %d clock id", perf_clk_id); + } memset(&header, 0, sizeof(header)); @@ -263,6 +299,9 @@ void *jvmti_open(void) header.timestamp = perf_get_timestamp(); + if (use_arch_timestamp) + header.flags |= JITDUMP_FLAGS_ARCH_TIMESTAMP; + if (!fwrite(&header, sizeof(header), 1, fp)) { warn("jvmti: cannot write dumpfile header"); goto error; diff --git a/tools/perf/util/Build b/tools/perf/util/Build index da48fd843438..85ceff357769 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -69,8 +69,7 @@ libperf-y += stat-shadow.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o -libperf-$(CONFIG_X86) += tsc.o -libperf-$(CONFIG_AUXTRACE) += tsc.o +libperf-y += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o libperf-$(CONFIG_AUXTRACE) += auxtrace.o diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index ad0c0bb1fbc7..52fcef3074fe 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -17,6 +17,7 @@ #include "strlist.h" #include +#include "tsc.h" #include "session.h" #include "jit.h" #include "jitdump.h" @@ -33,6 +34,7 @@ struct jit_buf_desc { size_t bufsize; FILE *in; bool needs_bswap; /* handles cross-endianess */ + bool use_arch_timestamp; void *debug_data; size_t nr_debug_entries; uint32_t code_load_count; @@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name) header.flags = bswap_64(header.flags); } + jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP; + if (verbose > 2) - pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n", + pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n", header.version, header.total_size, (unsigned long long)header.timestamp, header.pid, - header.elf_mach); + header.elf_mach, + jd->use_arch_timestamp); if (header.flags & JITDUMP_FLAGS_RESERVED) { pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n", @@ -172,10 +177,15 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } + if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) { + pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n"); + goto error; + } + /* * validate event is using the correct clockid */ - if (jit_validate_events(jd->session)) { + if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) { pr_err("error, jitted code must be sampled with perf record -k 1\n"); goto error; } @@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event) return 0; } +static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp) +{ + struct perf_tsc_conversion tc; + + if (!jd->use_arch_timestamp) + return timestamp; + + tc.time_shift = jd->session->time_conv.time_shift; + tc.time_mult = jd->session->time_conv.time_mult; + tc.time_zero = jd->session->time_conv.time_zero; + + if (!tc.time_mult) + return 0; + + return tsc_to_perf_time(timestamp, &tc); +} + static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) { struct perf_sample sample; @@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; } if (jd->sample_type & PERF_SAMPLE_TIME) - id->time = jr->load.p.timestamp; + id->time = convert_timestamp(jd, jr->load.p.timestamp); /* * create pseudo sample to induce dso hit increment @@ -499,7 +526,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; } if (jd->sample_type & PERF_SAMPLE_TIME) - id->time = jr->load.p.timestamp; + id->time = convert_timestamp(jd, jr->load.p.timestamp); /* * create pseudo sample to induce dso hit increment diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h index b66c1f503d9e..bcacd20d0c1c 100644 --- a/tools/perf/util/jitdump.h +++ b/tools/perf/util/jitdump.h @@ -23,9 +23,12 @@ #define JITHEADER_VERSION 1 enum jitdump_flags_bits { + JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT, JITDUMP_FLAGS_MAX_BIT, }; +#define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT) + #define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \ (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0) diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h index 280ddc067556..d5b11e2b85e0 100644 --- a/tools/perf/util/tsc.h +++ b/tools/perf/util/tsc.h @@ -4,7 +4,16 @@ #include #include "event.h" -#include "../arch/x86/util/tsc.h" + +struct perf_tsc_conversion { + u16 time_shift; + u32 time_mult; + u64 time_zero; +}; +struct perf_event_mmap_page; + +int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, + struct perf_tsc_conversion *tc); u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); -- GitLab From bd0c7a54219cc3745ce7f36970d8e5ffb3f8d80e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 8 Mar 2016 10:38:53 +0200 Subject: [PATCH 1091/9938] perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP For Intel PT / BTS, define the environment variable that selects TSC timestamps in the jitdump file. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1457426333-30260-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/intel-bts.c | 5 +++++ tools/perf/arch/x86/util/intel-pt.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index d66f9ad4df2e..7dc30637cf66 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -438,6 +438,11 @@ struct auxtrace_record *intel_bts_recording_init(int *err) if (!intel_bts_pmu) return NULL; + if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) { + *err = -errno; + return NULL; + } + btsr = zalloc(sizeof(struct intel_bts_recording)); if (!btsr) { *err = -ENOMEM; diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index a3395179c9ee..a07b9605e93b 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -1027,6 +1027,11 @@ struct auxtrace_record *intel_pt_recording_init(int *err) if (!intel_pt_pmu) return NULL; + if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) { + *err = -errno; + return NULL; + } + ptr = zalloc(sizeof(struct intel_pt_recording)); if (!ptr) { *err = -ENOMEM; -- GitLab From ac0e2cd555373ae6f8f3a3ad3fbbf5b6d1e7aaaa Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 30 Mar 2016 12:16:15 -0700 Subject: [PATCH 1092/9938] perf tools: Fix PMU term format max value calculation Currently the max value of format is calculated by the bits number. It relies on the continuity of the format. However, uncore event format is not continuous. E.g. uncore qpi event format can be 0-7,21. If bit 21 is set, there is parsing issues as below. $ perf stat -a -e uncore_qpi_0/event=0x200002,umask=0x8/ event syntax error: '..pi_0/event=0x200002,umask=0x8/' \___ value too big for format, maximum is 511 This patch return the real max value by setting all possible bits to 1. Signed-off-by: Kan Liang Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1459365375-14285-1-git-send-email-kan.liang@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index adef23b1352e..bf34468a99cb 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -602,14 +602,13 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, static __u64 pmu_format_max_value(const unsigned long *format) { - int w; + __u64 w = 0; + int fbit; - w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); - if (!w) - return 0; - if (w < 64) - return (1ULL << w) - 1; - return -1; + for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS) + w |= (1ULL << fbit); + + return w; } /* -- GitLab From e6001980c61b45ef090e2b4c9c1953ef897cdeb0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 31 Mar 2016 15:16:28 -0300 Subject: [PATCH 1093/9938] perf trace: Introduce function to set the base timestamp That is used in both live runs, i.e.: # trace ls As when processing events recorded in a perf.data file: # trace -i perf.data Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-901l6yebnzeqg7z8mbaf49xb@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c45c1cfeb866..99daeed55a9b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2400,6 +2400,14 @@ static bool skip_sample(struct trace *trace, struct perf_sample *sample) return false; } +static void trace__set_base_time(struct trace *trace, + struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + if (trace->base_time == 0 && !trace->full_time) + trace->base_time = sample->time; +} + static int trace__process_sample(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, @@ -2414,8 +2422,7 @@ static int trace__process_sample(struct perf_tool *tool, if (skip_sample(trace, sample)) return 0; - if (!trace->full_time && trace->base_time == 0) - trace->base_time = sample->time; + trace__set_base_time(trace, evsel, sample); if (handler) { ++trace->nr_events; @@ -2553,9 +2560,6 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st const u32 type = event->header.type; struct perf_evsel *evsel; - if (!trace->full_time && trace->base_time == 0) - trace->base_time = sample->time; - if (type != PERF_RECORD_SAMPLE) { trace__process_event(trace, trace->host, event, sample); return; @@ -2567,6 +2571,8 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st return; } + trace__set_base_time(trace, evsel, sample); + if (evsel->attr.type == PERF_TYPE_TRACEPOINT && sample->raw_data == NULL) { fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", -- GitLab From 8a07a8094b6b6c3e195885ec31f4bd0be54aafaf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 31 Mar 2016 15:19:39 -0300 Subject: [PATCH 1094/9938] perf trace: Don't set the base timestamp using events without PERF_SAMPLE_TIME This was causing bogus values to be shown at the timestamp column: Before: # trace --ev bpf-output/no-inherit,name=evt/ --ev /home/acme/bpf/test_bpf_trace.c/map:channel.event=evt/ usleep 10 94631143.385 ( 0.001 ms): brk( ) = 0x555555757000 94631143.398 ( 0.003 ms): mmap(len: 4096, prot: READ|WRITE, flags: PRIVATE|ANONYMOUS, fd: -1) = 0x7ffff7ff6000 94631143.406 ( 0.004 ms): access(filename: 0xf7df9e10, mode: R ) = -1 ENOENT No such file or directory 94631143.412 ( 0.004 ms): open(filename: 0xf7df8761, flags: CLOEXEC) = 3 94631143.415 ( 0.002 ms): fstat(fd: 3, statbuf: 0x7fffffffd6b0 ) = 0 94631143.419 ( 0.003 ms): mmap(len: 106798, prot: READ, flags: PRIVATE, fd: 3) = 0x7ffff7fdb000 94631143.420 ( 0.001 ms): close(fd: 3 ) = 0 94631143.432 ( 0.004 ms): open(filename: 0xf7ff6640, flags: CLOEXEC) = 3 After: # trace --ev bpf-output/no-inherit,name=evt/ --ev /home/acme/bpf/test_bpf_trace.c/map:channel.event=evt/ usleep 10 0.022 ( 0.001 ms): brk( ) = 0x55d7668a6000 0.037 ( 0.003 ms): mmap(len: 4096, prot: READ|WRITE, flags: PRIVATE|ANONYMOUS, fd: -1) = 0x7f8fbeb97000 0.123 ( 0.083 ms): access(filename: 0xbe995e10, mode: R ) = -1 ENOENT No such file or directory 0.130 ( 0.004 ms): open(filename: 0xbe994761, flags: CLOEXEC) = 3 0.133 ( 0.002 ms): fstat(fd: 3, statbuf: 0x7fff6487a890 ) = 0 0.138 ( 0.003 ms): mmap(len: 106798, prot: READ, flags: PRIVATE, fd: 3) = 0x7f8fbeb7c000 0.140 ( 0.001 ms): close(fd: 3 ) = 0 0.151 ( 0.004 ms): open(filename: 0xbeb97640, flags: CLOEXEC) = 3 Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-p7m8llv81iv55ekxexdp5n57@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 99daeed55a9b..d309f4535a45 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2401,10 +2401,19 @@ static bool skip_sample(struct trace *trace, struct perf_sample *sample) } static void trace__set_base_time(struct trace *trace, - struct perf_evsel *evsel __maybe_unused, + struct perf_evsel *evsel, struct perf_sample *sample) { - if (trace->base_time == 0 && !trace->full_time) + /* + * BPF events were not setting PERF_SAMPLE_TIME, so be more robust + * and don't use sample->time unconditionally, we may end up having + * some other event in the future without PERF_SAMPLE_TIME for good + * reason, i.e. we may not be interested in its timestamps, just in + * it taking place, picking some piece of information when it + * appears in our event stream (vfs_getname comes to mind). + */ + if (trace->base_time == 0 && !trace->full_time && + (evsel->attr.sample_type & PERF_SAMPLE_TIME)) trace->base_time = sample->time; } -- GitLab From d37ba880598654fda10b312331377cdca3edd574 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 1 Apr 2016 13:26:42 +0000 Subject: [PATCH 1095/9938] perf bpf: Add sample types for 'bpf-output' event Before this patch we can see very large time in the events before the 'bpf-output' event. For example: # perf trace -vv -T --ev sched:sched_switch \ --ev bpf-output/no-inherit,name=evt/ \ --ev ./test_bpf_trace.c/map:channel.event=evt/ \ usleep 10 ... 18446744073709.551 (18446564645918.480 ms): usleep/4157 nanosleep(rqtp: 0x7ffd3f0dc4e0) ... 18446744073709.551 ( ): evt:Raise a BPF event!..) 179427791.076 ( ): perf_bpf_probe:func_begin:(ffffffff810eb9a0)) 179427791.081 ( ): sched:sched_switch:usleep:4157 [120] S ==> swapper/2:0 [120]) ... We can also see the differences between bpf-output events and breakpoint events: For bpf output event: sample_type IP|TID|RAW|IDENTIFIER For tracepoint events: sample_type IP|TID|TIME|CPU|PERIOD|RAW|IDENTIFIER This patch fix this differences by adding more sample type for bpf-output events. After this patch: # perf trace -vv -T --ev sched:sched_switch \ --ev bpf-output/no-inherit,name=evt/ \ --ev ./test_bpf_trace.c/map:channel.event=evt/ \ usleep 10 ... 179877370.878 ( 0.003 ms): usleep/5336 nanosleep(rqtp: 0x7ffff866c450) ... 179877370.878 ( ): evt:Raise a BPF event!..) 179877370.878 ( ): perf_bpf_probe:func_begin:(ffffffff810eb9a0)) 179877370.882 ( ): sched:sched_switch:usleep:5336 [120] S ==> swapper/4:0 [120]) 179877370.945 ( ): evt:Raise a BPF event!..) ... # ./perf trace -vv -T --ev sched:sched_switch \ --ev bpf-output/no-inherit,name=evt/ \ --ev ./test_bpf_trace.c/map:channel.event=evt/ \ usleep 10 2>&1 | grep sample_type sample_type IP|TID|TIME|ID|CPU|PERIOD|RAW sample_type IP|TID|TIME|ID|CPU|PERIOD|RAW sample_type IP|TID|TIME|ID|CPU|PERIOD|RAW sample_type IP|TID|TIME|ID|CPU|PERIOD|RAW sample_type IP|TID|TIME|ID|CPU|PERIOD|RAW sample_type IP|TID|TIME|ID|CPU|PERIOD|RAW The 'IDENTIFIER' info is not required because all events have the same sample_type. Committer notes: Further testing, on top of the changes making 'perf trace' avoid samples from events without PERF_SAMPLE_TIME: Before: # trace --ev bpf-output/no-inherit,name=evt/ --ev /home/acme/bpf/test_bpf_trace.c/map:channel.event=evt/ usleep 10 0.560 ( 0.001 ms): brk( ) = 0x55e5a1df8000 18446640227439.430 (18446640227438.859 ms): nanosleep(rqtp: 0x7ffc96643370) ... 18446640227439.430 ( ): evt:Raise a BPF event!..) 0.576 ( ): perf_bpf_probe:func_begin:(ffffffff81112460)) 18446640227439.430 ( ): evt:Raise a BPF event!..) 0.645 ( ): perf_bpf_probe:func_end:(ffffffff81112460 <- ffffffff81003d92)) 0.646 ( 0.076 ms): ... [continued]: nanosleep()) = 0 # After: # trace --ev bpf-output/no-inherit,name=evt/ --ev /home/acme/bpf/test_bpf_trace.c/map:channel.event=evt/ usleep 10 0.292 ( 0.001 ms): brk( ) = 0x55c7cd6e1000 0.302 ( 0.004 ms): nanosleep(rqtp: 0x7ffedd8bc0f0) ... 0.302 ( ): evt:Raise a BPF event!..) 0.303 ( ): perf_bpf_probe:func_begin:(ffffffff81112460)) 0.397 ( ): evt:Raise a BPF event!..) 0.397 ( ): perf_bpf_probe:func_end:(ffffffff81112460 <- ffffffff81003d92)) 0.398 ( 0.100 ms): ... [continued]: nanosleep()) = 0 Signed-off-by: Wang Nan Reported-and-Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1459517202-42320-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 738ce226002b..3fd7c2c72f4a 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -226,7 +226,8 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) perf_evsel__init(evsel, attr, idx); if (perf_evsel__is_bpf_output(evsel)) { - evsel->attr.sample_type |= PERF_SAMPLE_RAW; + evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | + PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), evsel->attr.sample_period = 1; } -- GitLab From 0bed612be638e41456cd8cb270a2b411a5b43d63 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 2 Apr 2016 01:08:43 +0200 Subject: [PATCH 1096/9938] cpufreq: sched: Helpers to add and remove update_util hooks Replace the single helper for adding and removing cpufreq utilization update hooks, cpufreq_set_update_util_data(), with a pair of helpers, cpufreq_add_update_util_hook() and cpufreq_remove_update_util_hook(), and modify the users of cpufreq_set_update_util_data() accordingly. With the new helpers, the code using them doesn't need to worry about the internals of struct update_util_data and in particular it doesn't need to worry about populating the func field in it properly upfront. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar Acked-by: Peter Zijlstra (Intel) --- drivers/cpufreq/cpufreq_governor.c | 76 +++++++++++++++--------------- drivers/cpufreq/intel_pstate.c | 7 ++- include/linux/sched.h | 5 +- kernel/sched/cpufreq.c | 48 ++++++++++++++----- 4 files changed, 82 insertions(+), 54 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 10a5cfeae8c5..3a0312f46027 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -258,43 +258,6 @@ unsigned int dbs_update(struct cpufreq_policy *policy) } EXPORT_SYMBOL_GPL(dbs_update); -static void gov_set_update_util(struct policy_dbs_info *policy_dbs, - unsigned int delay_us) -{ - struct cpufreq_policy *policy = policy_dbs->policy; - int cpu; - - gov_update_sample_delay(policy_dbs, delay_us); - policy_dbs->last_sample_time = 0; - - for_each_cpu(cpu, policy->cpus) { - struct cpu_dbs_info *cdbs = &per_cpu(cpu_dbs, cpu); - - cpufreq_set_update_util_data(cpu, &cdbs->update_util); - } -} - -static inline void gov_clear_update_util(struct cpufreq_policy *policy) -{ - int i; - - for_each_cpu(i, policy->cpus) - cpufreq_set_update_util_data(i, NULL); - - synchronize_sched(); -} - -static void gov_cancel_work(struct cpufreq_policy *policy) -{ - struct policy_dbs_info *policy_dbs = policy->governor_data; - - gov_clear_update_util(policy_dbs->policy); - irq_work_sync(&policy_dbs->irq_work); - cancel_work_sync(&policy_dbs->work); - atomic_set(&policy_dbs->work_count, 0); - policy_dbs->work_in_progress = false; -} - static void dbs_work_handler(struct work_struct *work) { struct policy_dbs_info *policy_dbs; @@ -382,6 +345,44 @@ static void dbs_update_util_handler(struct update_util_data *data, u64 time, irq_work_queue(&policy_dbs->irq_work); } +static void gov_set_update_util(struct policy_dbs_info *policy_dbs, + unsigned int delay_us) +{ + struct cpufreq_policy *policy = policy_dbs->policy; + int cpu; + + gov_update_sample_delay(policy_dbs, delay_us); + policy_dbs->last_sample_time = 0; + + for_each_cpu(cpu, policy->cpus) { + struct cpu_dbs_info *cdbs = &per_cpu(cpu_dbs, cpu); + + cpufreq_add_update_util_hook(cpu, &cdbs->update_util, + dbs_update_util_handler); + } +} + +static inline void gov_clear_update_util(struct cpufreq_policy *policy) +{ + int i; + + for_each_cpu(i, policy->cpus) + cpufreq_remove_update_util_hook(i); + + synchronize_sched(); +} + +static void gov_cancel_work(struct cpufreq_policy *policy) +{ + struct policy_dbs_info *policy_dbs = policy->governor_data; + + gov_clear_update_util(policy_dbs->policy); + irq_work_sync(&policy_dbs->irq_work); + cancel_work_sync(&policy_dbs->work); + atomic_set(&policy_dbs->work_count, 0); + policy_dbs->work_in_progress = false; +} + static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy, struct dbs_governor *gov) { @@ -404,7 +405,6 @@ static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *poli struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j); j_cdbs->policy_dbs = policy_dbs; - j_cdbs->update_util.func = dbs_update_util_handler; } return policy_dbs; } diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 9ae159631f52..a38219527637 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1107,8 +1107,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) intel_pstate_busy_pid_reset(cpu); - cpu->update_util.func = intel_pstate_update_util; - pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); return 0; @@ -1132,12 +1130,13 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num) /* Prevent intel_pstate_update_util() from using stale data. */ cpu->sample.time = 0; - cpufreq_set_update_util_data(cpu_num, &cpu->update_util); + cpufreq_add_update_util_hook(cpu_num, &cpu->update_util, + intel_pstate_update_util); } static void intel_pstate_clear_update_util_hook(unsigned int cpu) { - cpufreq_set_update_util_data(cpu, NULL); + cpufreq_remove_update_util_hook(cpu); synchronize_sched(); } diff --git a/include/linux/sched.h b/include/linux/sched.h index 60bba7e032dc..1b8825922597 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -3240,7 +3240,10 @@ struct update_util_data { u64 time, unsigned long util, unsigned long max); }; -void cpufreq_set_update_util_data(int cpu, struct update_util_data *data); +void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data, + void (*func)(struct update_util_data *data, u64 time, + unsigned long util, unsigned long max)); +void cpufreq_remove_update_util_hook(int cpu); #endif /* CONFIG_CPU_FREQ */ #endif diff --git a/kernel/sched/cpufreq.c b/kernel/sched/cpufreq.c index 928c4ba32f68..1141954e73b4 100644 --- a/kernel/sched/cpufreq.c +++ b/kernel/sched/cpufreq.c @@ -14,24 +14,50 @@ DEFINE_PER_CPU(struct update_util_data *, cpufreq_update_util_data); /** - * cpufreq_set_update_util_data - Populate the CPU's update_util_data pointer. + * cpufreq_add_update_util_hook - Populate the CPU's update_util_data pointer. * @cpu: The CPU to set the pointer for. * @data: New pointer value. + * @func: Callback function to set for the CPU. * - * Set and publish the update_util_data pointer for the given CPU. That pointer - * points to a struct update_util_data object containing a callback function - * to call from cpufreq_update_util(). That function will be called from an RCU - * read-side critical section, so it must not sleep. + * Set and publish the update_util_data pointer for the given CPU. * - * Callers must use RCU-sched callbacks to free any memory that might be - * accessed via the old update_util_data pointer or invoke synchronize_sched() - * right after this function to avoid use-after-free. + * The update_util_data pointer of @cpu is set to @data and the callback + * function pointer in the target struct update_util_data is set to @func. + * That function will be called by cpufreq_update_util() from RCU-sched + * read-side critical sections, so it must not sleep. @data will always be + * passed to it as the first argument which allows the function to get to the + * target update_util_data structure and its container. + * + * The update_util_data pointer of @cpu must be NULL when this function is + * called or it will WARN() and return with no effect. */ -void cpufreq_set_update_util_data(int cpu, struct update_util_data *data) +void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data, + void (*func)(struct update_util_data *data, u64 time, + unsigned long util, unsigned long max)) { - if (WARN_ON(data && !data->func)) + if (WARN_ON(!data || !func)) return; + if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu))) + return; + + data->func = func; rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data); } -EXPORT_SYMBOL_GPL(cpufreq_set_update_util_data); +EXPORT_SYMBOL_GPL(cpufreq_add_update_util_hook); + +/** + * cpufreq_remove_update_util_hook - Clear the CPU's update_util_data pointer. + * @cpu: The CPU to clear the pointer for. + * + * Clear the update_util_data pointer for the given CPU. + * + * Callers must use RCU-sched callbacks to free any memory that might be + * accessed via the old update_util_data pointer or invoke synchronize_sched() + * right after this function to avoid use-after-free. + */ +void cpufreq_remove_update_util_hook(int cpu) +{ + rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), NULL); +} +EXPORT_SYMBOL_GPL(cpufreq_remove_update_util_hook); -- GitLab From 0dd3c1d678aa219a7332984fcedbdd8970e92d5b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 22 Mar 2016 02:47:51 +0100 Subject: [PATCH 1097/9938] cpufreq: governor: New data type for management part of dbs_data In addition to fields representing governor tunables, struct dbs_data contains some fields needed for the management of objects of that type. As it turns out, that part of struct dbs_data may be shared with (future) governors that won't use the common code used by "ondemand" and "conservative", so move it to a separate struct type and modify the code using struct dbs_data to follow. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq_conservative.c | 25 ++++--- drivers/cpufreq/cpufreq_governor.c | 90 ++++++++++++++++---------- drivers/cpufreq/cpufreq_governor.h | 35 +++++----- drivers/cpufreq/cpufreq_ondemand.c | 29 +++++---- 4 files changed, 107 insertions(+), 72 deletions(-) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index bf4913f6453b..316df247e00d 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -129,9 +129,10 @@ static struct notifier_block cs_cpufreq_notifier_block = { /************************** sysfs interface ************************/ static struct dbs_governor cs_dbs_gov; -static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, - const char *buf, size_t count) +static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); unsigned int input; int ret; ret = sscanf(buf, "%u", &input); @@ -143,9 +144,10 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, return count; } -static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, - size_t count) +static ssize_t store_up_threshold(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; unsigned int input; int ret; @@ -158,9 +160,10 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, return count; } -static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, - size_t count) +static ssize_t store_down_threshold(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; unsigned int input; int ret; @@ -175,9 +178,10 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, return count; } -static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, - const char *buf, size_t count) +static ssize_t store_ignore_nice_load(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); unsigned int input; int ret; @@ -199,9 +203,10 @@ static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, return count; } -static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf, - size_t count) +static ssize_t store_freq_step(struct gov_attr_set *attr_set, const char *buf, + size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; unsigned int input; int ret; diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 3a0312f46027..6a565e248ad3 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -43,9 +43,10 @@ static DEFINE_MUTEX(gov_dbs_data_mutex); * This must be called with dbs_data->mutex held, otherwise traversing * policy_dbs_list isn't safe. */ -ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, +ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); struct policy_dbs_info *policy_dbs; unsigned int rate; int ret; @@ -59,7 +60,7 @@ ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, * We are operating under dbs_data->mutex and so the list and its * entries can't be freed concurrently. */ - list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) { + list_for_each_entry(policy_dbs, &attr_set->policy_list, list) { mutex_lock(&policy_dbs->timer_mutex); /* * On 32-bit architectures this may race with the @@ -96,7 +97,7 @@ void gov_update_cpu_data(struct dbs_data *dbs_data) { struct policy_dbs_info *policy_dbs; - list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) { + list_for_each_entry(policy_dbs, &dbs_data->attr_set.policy_list, list) { unsigned int j; for_each_cpu(j, policy_dbs->policy->cpus) { @@ -111,9 +112,9 @@ void gov_update_cpu_data(struct dbs_data *dbs_data) } EXPORT_SYMBOL_GPL(gov_update_cpu_data); -static inline struct dbs_data *to_dbs_data(struct kobject *kobj) +static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj) { - return container_of(kobj, struct dbs_data, kobj); + return container_of(kobj, struct gov_attr_set, kobj); } static inline struct governor_attr *to_gov_attr(struct attribute *attr) @@ -124,25 +125,24 @@ static inline struct governor_attr *to_gov_attr(struct attribute *attr) static ssize_t governor_show(struct kobject *kobj, struct attribute *attr, char *buf) { - struct dbs_data *dbs_data = to_dbs_data(kobj); struct governor_attr *gattr = to_gov_attr(attr); - return gattr->show(dbs_data, buf); + return gattr->show(to_gov_attr_set(kobj), buf); } static ssize_t governor_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { - struct dbs_data *dbs_data = to_dbs_data(kobj); + struct gov_attr_set *attr_set = to_gov_attr_set(kobj); struct governor_attr *gattr = to_gov_attr(attr); int ret = -EBUSY; - mutex_lock(&dbs_data->mutex); + mutex_lock(&attr_set->update_lock); - if (dbs_data->usage_count) - ret = gattr->store(dbs_data, buf, count); + if (attr_set->usage_count) + ret = gattr->store(attr_set, buf, count); - mutex_unlock(&dbs_data->mutex); + mutex_unlock(&attr_set->update_lock); return ret; } @@ -425,6 +425,41 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, gov->free(policy_dbs); } +static void gov_attr_set_init(struct gov_attr_set *attr_set, + struct list_head *list_node) +{ + INIT_LIST_HEAD(&attr_set->policy_list); + mutex_init(&attr_set->update_lock); + attr_set->usage_count = 1; + list_add(list_node, &attr_set->policy_list); +} + +static void gov_attr_set_get(struct gov_attr_set *attr_set, + struct list_head *list_node) +{ + mutex_lock(&attr_set->update_lock); + attr_set->usage_count++; + list_add(list_node, &attr_set->policy_list); + mutex_unlock(&attr_set->update_lock); +} + +static unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, + struct list_head *list_node) +{ + unsigned int count; + + mutex_lock(&attr_set->update_lock); + list_del(list_node); + count = --attr_set->usage_count; + mutex_unlock(&attr_set->update_lock); + if (count) + return count; + + kobject_put(&attr_set->kobj); + mutex_destroy(&attr_set->update_lock); + return 0; +} + static int cpufreq_governor_init(struct cpufreq_policy *policy) { struct dbs_governor *gov = dbs_governor_of(policy); @@ -453,10 +488,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) policy_dbs->dbs_data = dbs_data; policy->governor_data = policy_dbs; - mutex_lock(&dbs_data->mutex); - dbs_data->usage_count++; - list_add(&policy_dbs->list, &dbs_data->policy_dbs_list); - mutex_unlock(&dbs_data->mutex); + gov_attr_set_get(&dbs_data->attr_set, &policy_dbs->list); goto out; } @@ -466,8 +498,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) goto free_policy_dbs_info; } - INIT_LIST_HEAD(&dbs_data->policy_dbs_list); - mutex_init(&dbs_data->mutex); + gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list); ret = gov->init(dbs_data, !policy->governor->initialized); if (ret) @@ -487,14 +518,11 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) if (!have_governor_per_policy()) gov->gdbs_data = dbs_data; - policy->governor_data = policy_dbs; - policy_dbs->dbs_data = dbs_data; - dbs_data->usage_count = 1; - list_add(&policy_dbs->list, &dbs_data->policy_dbs_list); + policy->governor_data = policy_dbs; gov->kobj_type.sysfs_ops = &governor_sysfs_ops; - ret = kobject_init_and_add(&dbs_data->kobj, &gov->kobj_type, + ret = kobject_init_and_add(&dbs_data->attr_set.kobj, &gov->kobj_type, get_governor_parent_kobj(policy), "%s", gov->gov.name); if (!ret) @@ -523,29 +551,21 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy) struct dbs_governor *gov = dbs_governor_of(policy); struct policy_dbs_info *policy_dbs = policy->governor_data; struct dbs_data *dbs_data = policy_dbs->dbs_data; - int count; + unsigned int count; /* Protect gov->gdbs_data against concurrent updates. */ mutex_lock(&gov_dbs_data_mutex); - mutex_lock(&dbs_data->mutex); - list_del(&policy_dbs->list); - count = --dbs_data->usage_count; - mutex_unlock(&dbs_data->mutex); + count = gov_attr_set_put(&dbs_data->attr_set, &policy_dbs->list); - if (!count) { - kobject_put(&dbs_data->kobj); - - policy->governor_data = NULL; + policy->governor_data = NULL; + if (!count) { if (!have_governor_per_policy()) gov->gdbs_data = NULL; gov->exit(dbs_data, policy->governor->initialized == 1); - mutex_destroy(&dbs_data->mutex); kfree(dbs_data); - } else { - policy->governor_data = NULL; } free_policy_dbs_info(policy_dbs, gov); diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 61ff82fe0613..f4ad431130b8 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -41,6 +41,13 @@ /* Ondemand Sampling types */ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; +struct gov_attr_set { + struct kobject kobj; + struct list_head policy_list; + struct mutex update_lock; + int usage_count; +}; + /* * Abbreviations: * dbs: used as a shortform for demand based switching It helps to keep variable @@ -52,7 +59,7 @@ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; /* Governor demand based switching data (per-policy or global). */ struct dbs_data { - int usage_count; + struct gov_attr_set attr_set; void *tuners; unsigned int min_sampling_rate; unsigned int ignore_nice_load; @@ -60,37 +67,35 @@ struct dbs_data { unsigned int sampling_down_factor; unsigned int up_threshold; unsigned int io_is_busy; - - struct kobject kobj; - struct list_head policy_dbs_list; - /* - * Protect concurrent updates to governor tunables from sysfs, - * policy_dbs_list and usage_count. - */ - struct mutex mutex; }; +static inline struct dbs_data *to_dbs_data(struct gov_attr_set *attr_set) +{ + return container_of(attr_set, struct dbs_data, attr_set); +} + /* Governor's specific attributes */ -struct dbs_data; struct governor_attr { struct attribute attr; - ssize_t (*show)(struct dbs_data *dbs_data, char *buf); - ssize_t (*store)(struct dbs_data *dbs_data, const char *buf, + ssize_t (*show)(struct gov_attr_set *attr_set, char *buf); + ssize_t (*store)(struct gov_attr_set *attr_set, const char *buf, size_t count); }; #define gov_show_one(_gov, file_name) \ static ssize_t show_##file_name \ -(struct dbs_data *dbs_data, char *buf) \ +(struct gov_attr_set *attr_set, char *buf) \ { \ + struct dbs_data *dbs_data = to_dbs_data(attr_set); \ struct _gov##_dbs_tuners *tuners = dbs_data->tuners; \ return sprintf(buf, "%u\n", tuners->file_name); \ } #define gov_show_one_common(file_name) \ static ssize_t show_##file_name \ -(struct dbs_data *dbs_data, char *buf) \ +(struct gov_attr_set *attr_set, char *buf) \ { \ + struct dbs_data *dbs_data = to_dbs_data(attr_set); \ return sprintf(buf, "%u\n", dbs_data->file_name); \ } @@ -184,7 +189,7 @@ void od_register_powersave_bias_handler(unsigned int (*f) (struct cpufreq_policy *, unsigned int, unsigned int), unsigned int powersave_bias); void od_unregister_powersave_bias_handler(void); -ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, +ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf, size_t count); void gov_update_cpu_data(struct dbs_data *dbs_data); #endif /* _CPUFREQ_GOVERNOR_H */ diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index acd80272ded6..300163430516 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -207,9 +207,10 @@ static unsigned int od_dbs_timer(struct cpufreq_policy *policy) /************************** sysfs interface ************************/ static struct dbs_governor od_dbs_gov; -static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf, - size_t count) +static ssize_t store_io_is_busy(struct gov_attr_set *attr_set, const char *buf, + size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); unsigned int input; int ret; @@ -224,9 +225,10 @@ static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf, return count; } -static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, - size_t count) +static ssize_t store_up_threshold(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); unsigned int input; int ret; ret = sscanf(buf, "%u", &input); @@ -240,9 +242,10 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, return count; } -static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, - const char *buf, size_t count) +static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); struct policy_dbs_info *policy_dbs; unsigned int input; int ret; @@ -254,7 +257,7 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, dbs_data->sampling_down_factor = input; /* Reset down sampling multiplier in case it was active */ - list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) { + list_for_each_entry(policy_dbs, &attr_set->policy_list, list) { /* * Doing this without locking might lead to using different * rate_mult values in od_update() and od_dbs_timer(). @@ -267,9 +270,10 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, return count; } -static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, - const char *buf, size_t count) +static ssize_t store_ignore_nice_load(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); unsigned int input; int ret; @@ -291,9 +295,10 @@ static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, return count; } -static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf, - size_t count) +static ssize_t store_powersave_bias(struct gov_attr_set *attr_set, + const char *buf, size_t count) { + struct dbs_data *dbs_data = to_dbs_data(attr_set); struct od_dbs_tuners *od_tuners = dbs_data->tuners; struct policy_dbs_info *policy_dbs; unsigned int input; @@ -308,7 +313,7 @@ static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf, od_tuners->powersave_bias = input; - list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) + list_for_each_entry(policy_dbs, &attr_set->policy_list, list) ondemand_powersave_bias_init(policy_dbs->policy); return count; -- GitLab From 2d0c58ad60376160ee8b535e570a38b9a349b6a4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 22 Mar 2016 02:49:15 +0100 Subject: [PATCH 1098/9938] cpufreq: governor: Move abstract gov_attr_set code to seperate file Move abstract code related to struct gov_attr_set to a separate (new) file so it can be shared with (future) goverernors that won't share more code with "ondemand" and "conservative". No intentional functional changes. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/Kconfig | 4 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq_governor.c | 82 -------------------- drivers/cpufreq/cpufreq_governor.h | 6 ++ drivers/cpufreq/cpufreq_governor_attr_set.c | 84 +++++++++++++++++++++ 5 files changed, 95 insertions(+), 82 deletions(-) create mode 100644 drivers/cpufreq/cpufreq_governor_attr_set.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index a7f45853c103..7fd87106ba46 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -18,7 +18,11 @@ config CPU_FREQ if CPU_FREQ +config CPU_FREQ_GOV_ATTR_SET + bool + config CPU_FREQ_GOV_COMMON + select CPU_FREQ_GOV_ATTR_SET select IRQ_WORK bool diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 9e63fb1b09f8..6d1186701a9c 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o +obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 6a565e248ad3..20f0a4e114d1 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -112,53 +112,6 @@ void gov_update_cpu_data(struct dbs_data *dbs_data) } EXPORT_SYMBOL_GPL(gov_update_cpu_data); -static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj) -{ - return container_of(kobj, struct gov_attr_set, kobj); -} - -static inline struct governor_attr *to_gov_attr(struct attribute *attr) -{ - return container_of(attr, struct governor_attr, attr); -} - -static ssize_t governor_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct governor_attr *gattr = to_gov_attr(attr); - - return gattr->show(to_gov_attr_set(kobj), buf); -} - -static ssize_t governor_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct gov_attr_set *attr_set = to_gov_attr_set(kobj); - struct governor_attr *gattr = to_gov_attr(attr); - int ret = -EBUSY; - - mutex_lock(&attr_set->update_lock); - - if (attr_set->usage_count) - ret = gattr->store(attr_set, buf, count); - - mutex_unlock(&attr_set->update_lock); - - return ret; -} - -/* - * Sysfs Ops for accessing governor attributes. - * - * All show/store invocations for governor specific sysfs attributes, will first - * call the below show/store callbacks and the attribute specific callback will - * be called from within it. - */ -static const struct sysfs_ops governor_sysfs_ops = { - .show = governor_show, - .store = governor_store, -}; - unsigned int dbs_update(struct cpufreq_policy *policy) { struct policy_dbs_info *policy_dbs = policy->governor_data; @@ -425,41 +378,6 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, gov->free(policy_dbs); } -static void gov_attr_set_init(struct gov_attr_set *attr_set, - struct list_head *list_node) -{ - INIT_LIST_HEAD(&attr_set->policy_list); - mutex_init(&attr_set->update_lock); - attr_set->usage_count = 1; - list_add(list_node, &attr_set->policy_list); -} - -static void gov_attr_set_get(struct gov_attr_set *attr_set, - struct list_head *list_node) -{ - mutex_lock(&attr_set->update_lock); - attr_set->usage_count++; - list_add(list_node, &attr_set->policy_list); - mutex_unlock(&attr_set->update_lock); -} - -static unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, - struct list_head *list_node) -{ - unsigned int count; - - mutex_lock(&attr_set->update_lock); - list_del(list_node); - count = --attr_set->usage_count; - mutex_unlock(&attr_set->update_lock); - if (count) - return count; - - kobject_put(&attr_set->kobj); - mutex_destroy(&attr_set->update_lock); - return 0; -} - static int cpufreq_governor_init(struct cpufreq_policy *policy) { struct dbs_governor *gov = dbs_governor_of(policy); diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index f4ad431130b8..ccdd0814efbc 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -48,6 +48,12 @@ struct gov_attr_set { int usage_count; }; +extern const struct sysfs_ops governor_sysfs_ops; + +void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node); +void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node); +unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node); + /* * Abbreviations: * dbs: used as a shortform for demand based switching It helps to keep variable diff --git a/drivers/cpufreq/cpufreq_governor_attr_set.c b/drivers/cpufreq/cpufreq_governor_attr_set.c new file mode 100644 index 000000000000..52841f807a7e --- /dev/null +++ b/drivers/cpufreq/cpufreq_governor_attr_set.c @@ -0,0 +1,84 @@ +/* + * Abstract code for CPUFreq governor tunable sysfs attributes. + * + * Copyright (C) 2016, Intel Corporation + * Author: Rafael J. Wysocki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "cpufreq_governor.h" + +static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj) +{ + return container_of(kobj, struct gov_attr_set, kobj); +} + +static inline struct governor_attr *to_gov_attr(struct attribute *attr) +{ + return container_of(attr, struct governor_attr, attr); +} + +static ssize_t governor_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct governor_attr *gattr = to_gov_attr(attr); + + return gattr->show(to_gov_attr_set(kobj), buf); +} + +static ssize_t governor_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct gov_attr_set *attr_set = to_gov_attr_set(kobj); + struct governor_attr *gattr = to_gov_attr(attr); + int ret; + + mutex_lock(&attr_set->update_lock); + ret = attr_set->usage_count ? gattr->store(attr_set, buf, count) : -EBUSY; + mutex_unlock(&attr_set->update_lock); + return ret; +} + +const struct sysfs_ops governor_sysfs_ops = { + .show = governor_show, + .store = governor_store, +}; +EXPORT_SYMBOL_GPL(governor_sysfs_ops); + +void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node) +{ + INIT_LIST_HEAD(&attr_set->policy_list); + mutex_init(&attr_set->update_lock); + attr_set->usage_count = 1; + list_add(list_node, &attr_set->policy_list); +} +EXPORT_SYMBOL_GPL(gov_attr_set_init); + +void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node) +{ + mutex_lock(&attr_set->update_lock); + attr_set->usage_count++; + list_add(list_node, &attr_set->policy_list); + mutex_unlock(&attr_set->update_lock); +} +EXPORT_SYMBOL_GPL(gov_attr_set_get); + +unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node) +{ + unsigned int count; + + mutex_lock(&attr_set->update_lock); + list_del(list_node); + count = --attr_set->usage_count; + mutex_unlock(&attr_set->update_lock); + if (count) + return count; + + kobject_put(&attr_set->kobj); + mutex_destroy(&attr_set->update_lock); + return 0; +} +EXPORT_SYMBOL_GPL(gov_attr_set_put); -- GitLab From 66893b6ac9952ec9d9409e9d85eaacf37bba8d15 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 22 Mar 2016 02:50:45 +0100 Subject: [PATCH 1099/9938] cpufreq: Move governor attribute set headers to cpufreq.h Move definitions and function headers related to struct gov_attr_set to include/linux/cpufreq.h so they can be used by (future) goverernors located outside of drivers/cpufreq/. No functional changes. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq_governor.h | 21 --------------------- include/linux/cpufreq.h | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index ccdd0814efbc..181a43058ece 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -41,19 +41,6 @@ /* Ondemand Sampling types */ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; -struct gov_attr_set { - struct kobject kobj; - struct list_head policy_list; - struct mutex update_lock; - int usage_count; -}; - -extern const struct sysfs_ops governor_sysfs_ops; - -void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node); -void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node); -unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node); - /* * Abbreviations: * dbs: used as a shortform for demand based switching It helps to keep variable @@ -80,14 +67,6 @@ static inline struct dbs_data *to_dbs_data(struct gov_attr_set *attr_set) return container_of(attr_set, struct dbs_data, attr_set); } -/* Governor's specific attributes */ -struct governor_attr { - struct attribute attr; - ssize_t (*show)(struct gov_attr_set *attr_set, char *buf); - ssize_t (*store)(struct gov_attr_set *attr_set, const char *buf, - size_t count); -}; - #define gov_show_one(_gov, file_name) \ static ssize_t show_##file_name \ (struct gov_attr_set *attr_set, char *buf) \ diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 718e8725de8a..74f5cfff2b52 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -462,6 +462,29 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor); struct cpufreq_governor *cpufreq_default_governor(void); struct cpufreq_governor *cpufreq_fallback_governor(void); +/* Governor attribute set */ +struct gov_attr_set { + struct kobject kobj; + struct list_head policy_list; + struct mutex update_lock; + int usage_count; +}; + +/* sysfs ops for cpufreq governors */ +extern const struct sysfs_ops governor_sysfs_ops; + +void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node); +void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node); +unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node); + +/* Governor sysfs attribute */ +struct governor_attr { + struct attribute attr; + ssize_t (*show)(struct gov_attr_set *attr_set, char *buf); + ssize_t (*store)(struct gov_attr_set *attr_set, const char *buf, + size_t count); +}; + /********************************************************************* * FREQUENCY TABLE HELPERS * *********************************************************************/ -- GitLab From 379480d8258056bfdbaa65e4d3f024bb5b34b52b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 22 Mar 2016 02:51:56 +0100 Subject: [PATCH 1100/9938] cpufreq: Move governor symbols to cpufreq.h Move definitions of symbols related to transition latency and sampling rate to include/linux/cpufreq.h so they can be used by (future) goverernors located outside of drivers/cpufreq/. No functional changes. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq_governor.h | 14 -------------- include/linux/cpufreq.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 181a43058ece..3e0eb7c54903 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -24,20 +24,6 @@ #include #include -/* - * The polling frequency depends on the capability of the processor. Default - * polling frequency is 1000 times the transition latency of the processor. The - * governor will work on any processor with transition latency <= 10ms, using - * appropriate sampling rate. - * - * For CPUs with transition latency > 10ms (mostly drivers with CPUFREQ_ETERNAL) - * this governor will not work. All times here are in us (micro seconds). - */ -#define MIN_SAMPLING_RATE_RATIO (2) -#define LATENCY_MULTIPLIER (1000) -#define MIN_LATENCY_MULTIPLIER (20) -#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) - /* Ondemand Sampling types */ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 74f5cfff2b52..2b4f248b8ef1 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -426,6 +426,20 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, #define CPUFREQ_POLICY_POWERSAVE (1) #define CPUFREQ_POLICY_PERFORMANCE (2) +/* + * The polling frequency depends on the capability of the processor. Default + * polling frequency is 1000 times the transition latency of the processor. The + * ondemand governor will work on any processor with transition latency <= 10ms, + * using appropriate sampling rate. + * + * For CPUs with transition latency > 10ms (mostly drivers with CPUFREQ_ETERNAL) + * the ondemand governor will not work. All times here are in us (microseconds). + */ +#define MIN_SAMPLING_RATE_RATIO (2) +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (20) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + /* Governor Events */ #define CPUFREQ_GOV_START 1 #define CPUFREQ_GOV_STOP 2 -- GitLab From b7898fda5bc7e786e76ce24fbd2ec993b08ec518 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Mar 2016 03:47:49 +0200 Subject: [PATCH 1101/9938] cpufreq: Support for fast frequency switching Modify the ACPI cpufreq driver to provide a method for switching CPU frequencies from interrupt context and update the cpufreq core to support that method if available. Introduce a new cpufreq driver callback, ->fast_switch, to be invoked for frequency switching from interrupt context by (future) governors supporting that feature via (new) helper function cpufreq_driver_fast_switch(). Add two new policy flags, fast_switch_possible, to be set by the cpufreq driver if fast frequency switching can be used for the given policy and fast_switch_enabled, to be set by the governor if it is going to use fast frequency switching for the given policy. Also add a helper for setting the latter. Since fast frequency switching is inherently incompatible with cpufreq transition notifiers, make it possible to set the fast_switch_enabled only if there are no transition notifiers already registered and make the registration of new transition notifiers fail if fast_switch_enabled is set for at least one policy. Implement the ->fast_switch callback in the ACPI cpufreq driver and make it set fast_switch_possible during policy initialization as appropriate. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/acpi-cpufreq.c | 42 +++++++++++ drivers/cpufreq/cpufreq.c | 130 +++++++++++++++++++++++++++++++-- include/linux/cpufreq.h | 16 ++++ 3 files changed, 183 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index fb5712141040..7f38fb55f223 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -458,6 +458,43 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, return result; } +unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy, + unsigned int target_freq) +{ + struct acpi_cpufreq_data *data = policy->driver_data; + struct acpi_processor_performance *perf; + struct cpufreq_frequency_table *entry; + unsigned int next_perf_state, next_freq, freq; + + /* + * Find the closest frequency above target_freq. + * + * The table is sorted in the reverse order with respect to the + * frequency and all of the entries are valid (see the initialization). + */ + entry = data->freq_table; + do { + entry++; + freq = entry->frequency; + } while (freq >= target_freq && freq != CPUFREQ_TABLE_END); + entry--; + next_freq = entry->frequency; + next_perf_state = entry->driver_data; + + perf = to_perf_data(data); + if (perf->state == next_perf_state) { + if (unlikely(data->resume)) + data->resume = 0; + else + return next_freq; + } + + data->cpu_freq_write(&perf->control_register, + perf->states[next_perf_state].control); + perf->state = next_perf_state; + return next_freq; +} + static unsigned long acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) { @@ -821,6 +858,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) */ data->resume = 1; + policy->fast_switch_possible = !acpi_pstate_strict && + !(policy_is_shared(policy) && policy->shared_type != CPUFREQ_SHARED_TYPE_ANY); + return result; err_freqfree: @@ -843,6 +883,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) pr_debug("acpi_cpufreq_cpu_exit\n"); if (data) { + policy->fast_switch_possible = false; policy->driver_data = NULL; acpi_processor_unregister_performance(data->acpi_perf_cpu); free_cpumask_var(data->freqdomain_cpus); @@ -876,6 +917,7 @@ static struct freq_attr *acpi_cpufreq_attr[] = { static struct cpufreq_driver acpi_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = acpi_cpufreq_target, + .fast_switch = acpi_cpufreq_fast_switch, .bios_limit = acpi_processor_get_bios_limit, .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b87596b591b3..a5b7d77d4816 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -77,6 +77,7 @@ static inline bool has_target(void) static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static unsigned int __cpufreq_get(struct cpufreq_policy *policy); static int cpufreq_start_governor(struct cpufreq_policy *policy); +static int cpufreq_exit_governor(struct cpufreq_policy *policy); /** * Two notifier lists: the "policy" list is involved in the @@ -429,6 +430,68 @@ void cpufreq_freq_transition_end(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end); +/* + * Fast frequency switching status count. Positive means "enabled", negative + * means "disabled" and 0 means "not decided yet". + */ +static int cpufreq_fast_switch_count; +static DEFINE_MUTEX(cpufreq_fast_switch_lock); + +static void cpufreq_list_transition_notifiers(void) +{ + struct notifier_block *nb; + + pr_info("Registered transition notifiers:\n"); + + mutex_lock(&cpufreq_transition_notifier_list.mutex); + + for (nb = cpufreq_transition_notifier_list.head; nb; nb = nb->next) + pr_info("%pF\n", nb->notifier_call); + + mutex_unlock(&cpufreq_transition_notifier_list.mutex); +} + +/** + * cpufreq_enable_fast_switch - Enable fast frequency switching for policy. + * @policy: cpufreq policy to enable fast frequency switching for. + * + * Try to enable fast frequency switching for @policy. + * + * The attempt will fail if there is at least one transition notifier registered + * at this point, as fast frequency switching is quite fundamentally at odds + * with transition notifiers. Thus if successful, it will make registration of + * transition notifiers fail going forward. + */ +void cpufreq_enable_fast_switch(struct cpufreq_policy *policy) +{ + lockdep_assert_held(&policy->rwsem); + + if (!policy->fast_switch_possible) + return; + + mutex_lock(&cpufreq_fast_switch_lock); + if (cpufreq_fast_switch_count >= 0) { + cpufreq_fast_switch_count++; + policy->fast_switch_enabled = true; + } else { + pr_warn("CPU%u: Fast frequency switching not enabled\n", + policy->cpu); + cpufreq_list_transition_notifiers(); + } + mutex_unlock(&cpufreq_fast_switch_lock); +} +EXPORT_SYMBOL_GPL(cpufreq_enable_fast_switch); + +static void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) +{ + mutex_lock(&cpufreq_fast_switch_lock); + if (policy->fast_switch_enabled) { + policy->fast_switch_enabled = false; + if (!WARN_ON(cpufreq_fast_switch_count <= 0)) + cpufreq_fast_switch_count--; + } + mutex_unlock(&cpufreq_fast_switch_lock); +} /********************************************************************* * SYSFS INTERFACE * @@ -1319,7 +1382,7 @@ static void cpufreq_offline(unsigned int cpu) /* If cpu is last user of policy, free policy */ if (has_target()) { - ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); + ret = cpufreq_exit_governor(policy); if (ret) pr_err("%s: Failed to exit governor\n", __func__); } @@ -1447,8 +1510,12 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy) ret_freq = cpufreq_driver->get(policy->cpu); - /* Updating inactive policies is invalid, so avoid doing that. */ - if (unlikely(policy_is_inactive(policy))) + /* + * Updating inactive policies is invalid, so avoid doing that. Also + * if fast frequency switching is used with the given policy, the check + * against policy->cur is pointless, so skip it in that case too. + */ + if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled) return ret_freq; if (ret_freq && policy->cur && @@ -1672,8 +1739,18 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) switch (list) { case CPUFREQ_TRANSITION_NOTIFIER: + mutex_lock(&cpufreq_fast_switch_lock); + + if (cpufreq_fast_switch_count > 0) { + mutex_unlock(&cpufreq_fast_switch_lock); + return -EBUSY; + } ret = srcu_notifier_chain_register( &cpufreq_transition_notifier_list, nb); + if (!ret) + cpufreq_fast_switch_count--; + + mutex_unlock(&cpufreq_fast_switch_lock); break; case CPUFREQ_POLICY_NOTIFIER: ret = blocking_notifier_chain_register( @@ -1706,8 +1783,14 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) switch (list) { case CPUFREQ_TRANSITION_NOTIFIER: + mutex_lock(&cpufreq_fast_switch_lock); + ret = srcu_notifier_chain_unregister( &cpufreq_transition_notifier_list, nb); + if (!ret && !WARN_ON(cpufreq_fast_switch_count >= 0)) + cpufreq_fast_switch_count++; + + mutex_unlock(&cpufreq_fast_switch_lock); break; case CPUFREQ_POLICY_NOTIFIER: ret = blocking_notifier_chain_unregister( @@ -1726,6 +1809,37 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier); * GOVERNORS * *********************************************************************/ +/** + * cpufreq_driver_fast_switch - Carry out a fast CPU frequency switch. + * @policy: cpufreq policy to switch the frequency for. + * @target_freq: New frequency to set (may be approximate). + * + * Carry out a fast frequency switch without sleeping. + * + * The driver's ->fast_switch() callback invoked by this function must be + * suitable for being called from within RCU-sched read-side critical sections + * and it is expected to select the minimum available frequency greater than or + * equal to @target_freq (CPUFREQ_RELATION_L). + * + * This function must not be called if policy->fast_switch_enabled is unset. + * + * Governors calling this function must guarantee that it will never be invoked + * twice in parallel for the same policy and that it will never be called in + * parallel with either ->target() or ->target_index() for the same policy. + * + * If CPUFREQ_ENTRY_INVALID is returned by the driver's ->fast_switch() + * callback to indicate an error condition, the hardware configuration must be + * preserved. + */ +unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, + unsigned int target_freq) +{ + clamp_val(target_freq, policy->min, policy->max); + + return cpufreq_driver->fast_switch(policy, target_freq); +} +EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch); + /* Must set freqs->new to intermediate frequency */ static int __target_intermediate(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs, int index) @@ -1946,6 +2060,12 @@ static int cpufreq_start_governor(struct cpufreq_policy *policy) return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); } +static int cpufreq_exit_governor(struct cpufreq_policy *policy) +{ + cpufreq_disable_fast_switch(policy); + return cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); +} + int cpufreq_register_governor(struct cpufreq_governor *governor) { int err; @@ -2101,7 +2221,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, return ret; } - ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); + ret = cpufreq_exit_governor(policy); if (ret) { pr_err("%s: Failed to Exit Governor: %s (%d)\n", __func__, old_gov->name, ret); @@ -2118,7 +2238,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, pr_debug("cpufreq: governor change\n"); return 0; } - cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); + cpufreq_exit_governor(policy); } /* new governor failed, so re-start old one */ diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 2b4f248b8ef1..55e69ebb035c 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -102,6 +102,17 @@ struct cpufreq_policy { */ struct rw_semaphore rwsem; + /* + * Fast switch flags: + * - fast_switch_possible should be set by the driver if it can + * guarantee that frequency can be changed on any CPU sharing the + * policy and that the change will affect all of the policy CPUs then. + * - fast_switch_enabled is to be set by governors that support fast + * freqnency switching with the help of cpufreq_enable_fast_switch(). + */ + bool fast_switch_possible; + bool fast_switch_enabled; + /* Synchronization for frequency transitions */ bool transition_ongoing; /* Tracks transition status */ spinlock_t transition_lock; @@ -156,6 +167,7 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); int cpufreq_update_policy(unsigned int cpu); bool have_governor_per_policy(void); struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); +void cpufreq_enable_fast_switch(struct cpufreq_policy *policy); #else static inline unsigned int cpufreq_get(unsigned int cpu) { @@ -236,6 +248,8 @@ struct cpufreq_driver { unsigned int relation); /* Deprecated */ int (*target_index)(struct cpufreq_policy *policy, unsigned int index); + unsigned int (*fast_switch)(struct cpufreq_policy *policy, + unsigned int target_freq); /* * Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION * unset. @@ -464,6 +478,8 @@ struct cpufreq_governor { }; /* Pass a target to the cpufreq driver */ +unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, + unsigned int target_freq); int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); -- GitLab From 9bdcb44e391da5c41b98573bf0305a0e0b1c9569 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 2 Apr 2016 01:09:12 +0200 Subject: [PATCH 1102/9938] cpufreq: schedutil: New governor based on scheduler utilization data Add a new cpufreq scaling governor, called "schedutil", that uses scheduler-provided CPU utilization information as input for making its decisions. Doing that is possible after commit 34e2c555f3e1 (cpufreq: Add mechanism for registering utilization update callbacks) that introduced cpufreq_update_util() called by the scheduler on utilization changes (from CFS) and RT/DL task status updates. In particular, CPU frequency scaling decisions may be based on the the utilization data passed to cpufreq_update_util() by CFS. The new governor is relatively simple. The frequency selection formula used by it depends on whether or not the utilization is frequency-invariant. In the frequency-invariant case the new CPU frequency is given by next_freq = 1.25 * max_freq * util / max where util and max are the last two arguments of cpufreq_update_util(). In turn, if util is not frequency-invariant, the maximum frequency in the above formula is replaced with the current frequency of the CPU: next_freq = 1.25 * curr_freq * util / max The coefficient 1.25 corresponds to the frequency tipping point at (util / max) = 0.8. All of the computations are carried out in the utilization update handlers provided by the new governor. One of those handlers is used for cpufreq policies shared between multiple CPUs and the other one is for policies with one CPU only (and therefore it doesn't need to use any extra synchronization means). The governor supports fast frequency switching if that is supported by the cpufreq driver in use and possible for the given policy. In the fast switching case, all operations of the governor take place in its utilization update handlers. If fast switching cannot be used, the frequency switch operations are carried out with the help of a work item which only calls __cpufreq_driver_target() (under a mutex) to trigger a frequency update (to a value already computed beforehand in one of the utilization update handlers). Currently, the governor treats all of the RT and DL tasks as "unknown utilization" and sets the frequency to the allowed maximum when updated from the RT or DL sched classes. That heavy-handed approach should be replaced with something more subtle and specifically targeted at RT and DL tasks. The governor shares some tunables management code with the "ondemand" and "conservative" governors and uses some common definitions from cpufreq_governor.h, but apart from that it is stand-alone. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar Acked-by: Peter Zijlstra (Intel) --- drivers/cpufreq/Kconfig | 30 ++ kernel/sched/Makefile | 1 + kernel/sched/cpufreq_schedutil.c | 528 +++++++++++++++++++++++++++++++ kernel/sched/sched.h | 8 + kernel/trace/power-traces.c | 1 + 5 files changed, 568 insertions(+) create mode 100644 kernel/sched/cpufreq_schedutil.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 7fd87106ba46..5d74826d75be 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -107,6 +107,16 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE Be aware that not all cpufreq drivers support the conservative governor. If unsure have a look at the help section of the driver. Fallback governor will be the performance governor. + +config CPU_FREQ_DEFAULT_GOV_SCHEDUTIL + bool "schedutil" + select CPU_FREQ_GOV_SCHEDUTIL + select CPU_FREQ_GOV_PERFORMANCE + help + Use the 'schedutil' CPUFreq governor by default. If unsure, + have a look at the help section of that governor. The fallback + governor will be 'performance'. + endchoice config CPU_FREQ_GOV_PERFORMANCE @@ -188,6 +198,26 @@ config CPU_FREQ_GOV_CONSERVATIVE If in doubt, say N. +config CPU_FREQ_GOV_SCHEDUTIL + tristate "'schedutil' cpufreq policy governor" + depends on CPU_FREQ + select CPU_FREQ_GOV_ATTR_SET + select IRQ_WORK + help + This governor makes decisions based on the utilization data provided + by the scheduler. It sets the CPU frequency to be proportional to + the utilization/capacity ratio coming from the scheduler. If the + utilization is frequency-invariant, the new frequency is also + proportional to the maximum available frequency. If that is not the + case, it is proportional to the current frequency of the CPU. The + frequency tipping point is at utilization/capacity equal to 80% in + both cases. + + To compile this driver as a module, choose M here: the module will + be called cpufreq_schedutil. + + If in doubt, say N. + comment "CPU frequency scaling drivers" config CPUFREQ_DT diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile index 414d9c16da42..5e59b832ae2b 100644 --- a/kernel/sched/Makefile +++ b/kernel/sched/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_SCHEDSTATS) += stats.o obj-$(CONFIG_SCHED_DEBUG) += debug.o obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) += cpufreq_schedutil.o diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c new file mode 100644 index 000000000000..d27ae064b476 --- /dev/null +++ b/kernel/sched/cpufreq_schedutil.c @@ -0,0 +1,528 @@ +/* + * CPUFreq governor based on scheduler-provided CPU utilization data. + * + * Copyright (C) 2016, Intel Corporation + * Author: Rafael J. Wysocki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "sched.h" + +struct sugov_tunables { + struct gov_attr_set attr_set; + unsigned int rate_limit_us; +}; + +struct sugov_policy { + struct cpufreq_policy *policy; + + struct sugov_tunables *tunables; + struct list_head tunables_hook; + + raw_spinlock_t update_lock; /* For shared policies */ + u64 last_freq_update_time; + s64 freq_update_delay_ns; + unsigned int next_freq; + + /* The next fields are only needed if fast switch cannot be used. */ + struct irq_work irq_work; + struct work_struct work; + struct mutex work_lock; + bool work_in_progress; + + bool need_freq_update; +}; + +struct sugov_cpu { + struct update_util_data update_util; + struct sugov_policy *sg_policy; + + /* The fields below are only needed when sharing a policy. */ + unsigned long util; + unsigned long max; + u64 last_update; +}; + +static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu); + +/************************ Governor internals ***********************/ + +static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) +{ + s64 delta_ns; + + if (sg_policy->work_in_progress) + return false; + + if (unlikely(sg_policy->need_freq_update)) { + sg_policy->need_freq_update = false; + /* + * This happens when limits change, so forget the previous + * next_freq value and force an update. + */ + sg_policy->next_freq = UINT_MAX; + return true; + } + + delta_ns = time - sg_policy->last_freq_update_time; + return delta_ns >= sg_policy->freq_update_delay_ns; +} + +static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, + unsigned int next_freq) +{ + struct cpufreq_policy *policy = sg_policy->policy; + + sg_policy->last_freq_update_time = time; + + if (policy->fast_switch_enabled) { + if (sg_policy->next_freq == next_freq) { + trace_cpu_frequency(policy->cur, smp_processor_id()); + return; + } + sg_policy->next_freq = next_freq; + next_freq = cpufreq_driver_fast_switch(policy, next_freq); + if (next_freq == CPUFREQ_ENTRY_INVALID) + return; + + policy->cur = next_freq; + trace_cpu_frequency(next_freq, smp_processor_id()); + } else if (sg_policy->next_freq != next_freq) { + sg_policy->next_freq = next_freq; + sg_policy->work_in_progress = true; + irq_work_queue(&sg_policy->irq_work); + } +} + +/** + * get_next_freq - Compute a new frequency for a given cpufreq policy. + * @policy: cpufreq policy object to compute the new frequency for. + * @util: Current CPU utilization. + * @max: CPU capacity. + * + * If the utilization is frequency-invariant, choose the new frequency to be + * proportional to it, that is + * + * next_freq = C * max_freq * util / max + * + * Otherwise, approximate the would-be frequency-invariant utilization by + * util_raw * (curr_freq / max_freq) which leads to + * + * next_freq = C * curr_freq * util_raw / max + * + * Take C = 1.25 for the frequency tipping point at (util / max) = 0.8. + */ +static unsigned int get_next_freq(struct cpufreq_policy *policy, + unsigned long util, unsigned long max) +{ + unsigned int freq = arch_scale_freq_invariant() ? + policy->cpuinfo.max_freq : policy->cur; + + return (freq + (freq >> 2)) * util / max; +} + +static void sugov_update_single(struct update_util_data *hook, u64 time, + unsigned long util, unsigned long max) +{ + struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); + struct sugov_policy *sg_policy = sg_cpu->sg_policy; + struct cpufreq_policy *policy = sg_policy->policy; + unsigned int next_f; + + if (!sugov_should_update_freq(sg_policy, time)) + return; + + next_f = util == ULONG_MAX ? policy->cpuinfo.max_freq : + get_next_freq(policy, util, max); + sugov_update_commit(sg_policy, time, next_f); +} + +static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy, + unsigned long util, unsigned long max) +{ + struct cpufreq_policy *policy = sg_policy->policy; + unsigned int max_f = policy->cpuinfo.max_freq; + u64 last_freq_update_time = sg_policy->last_freq_update_time; + unsigned int j; + + if (util == ULONG_MAX) + return max_f; + + for_each_cpu(j, policy->cpus) { + struct sugov_cpu *j_sg_cpu; + unsigned long j_util, j_max; + s64 delta_ns; + + if (j == smp_processor_id()) + continue; + + j_sg_cpu = &per_cpu(sugov_cpu, j); + /* + * If the CPU utilization was last updated before the previous + * frequency update and the time elapsed between the last update + * of the CPU utilization and the last frequency update is long + * enough, don't take the CPU into account as it probably is + * idle now. + */ + delta_ns = last_freq_update_time - j_sg_cpu->last_update; + if (delta_ns > TICK_NSEC) + continue; + + j_util = j_sg_cpu->util; + if (j_util == ULONG_MAX) + return max_f; + + j_max = j_sg_cpu->max; + if (j_util * max > j_max * util) { + util = j_util; + max = j_max; + } + } + + return get_next_freq(policy, util, max); +} + +static void sugov_update_shared(struct update_util_data *hook, u64 time, + unsigned long util, unsigned long max) +{ + struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); + struct sugov_policy *sg_policy = sg_cpu->sg_policy; + unsigned int next_f; + + raw_spin_lock(&sg_policy->update_lock); + + sg_cpu->util = util; + sg_cpu->max = max; + sg_cpu->last_update = time; + + if (sugov_should_update_freq(sg_policy, time)) { + next_f = sugov_next_freq_shared(sg_policy, util, max); + sugov_update_commit(sg_policy, time, next_f); + } + + raw_spin_unlock(&sg_policy->update_lock); +} + +static void sugov_work(struct work_struct *work) +{ + struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work); + + mutex_lock(&sg_policy->work_lock); + __cpufreq_driver_target(sg_policy->policy, sg_policy->next_freq, + CPUFREQ_RELATION_L); + mutex_unlock(&sg_policy->work_lock); + + sg_policy->work_in_progress = false; +} + +static void sugov_irq_work(struct irq_work *irq_work) +{ + struct sugov_policy *sg_policy; + + sg_policy = container_of(irq_work, struct sugov_policy, irq_work); + schedule_work_on(smp_processor_id(), &sg_policy->work); +} + +/************************** sysfs interface ************************/ + +static struct sugov_tunables *global_tunables; +static DEFINE_MUTEX(global_tunables_lock); + +static inline struct sugov_tunables *to_sugov_tunables(struct gov_attr_set *attr_set) +{ + return container_of(attr_set, struct sugov_tunables, attr_set); +} + +static ssize_t rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return sprintf(buf, "%u\n", tunables->rate_limit_us); +} + +static ssize_t rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, + size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + struct sugov_policy *sg_policy; + unsigned int rate_limit_us; + + if (kstrtouint(buf, 10, &rate_limit_us)) + return -EINVAL; + + tunables->rate_limit_us = rate_limit_us; + + list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) + sg_policy->freq_update_delay_ns = rate_limit_us * NSEC_PER_USEC; + + return count; +} + +static struct governor_attr rate_limit_us = __ATTR_RW(rate_limit_us); + +static struct attribute *sugov_attributes[] = { + &rate_limit_us.attr, + NULL +}; + +static struct kobj_type sugov_tunables_ktype = { + .default_attrs = sugov_attributes, + .sysfs_ops = &governor_sysfs_ops, +}; + +/********************** cpufreq governor interface *********************/ + +static struct cpufreq_governor schedutil_gov; + +static struct sugov_policy *sugov_policy_alloc(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy; + + sg_policy = kzalloc(sizeof(*sg_policy), GFP_KERNEL); + if (!sg_policy) + return NULL; + + sg_policy->policy = policy; + init_irq_work(&sg_policy->irq_work, sugov_irq_work); + INIT_WORK(&sg_policy->work, sugov_work); + mutex_init(&sg_policy->work_lock); + raw_spin_lock_init(&sg_policy->update_lock); + return sg_policy; +} + +static void sugov_policy_free(struct sugov_policy *sg_policy) +{ + mutex_destroy(&sg_policy->work_lock); + kfree(sg_policy); +} + +static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_policy) +{ + struct sugov_tunables *tunables; + + tunables = kzalloc(sizeof(*tunables), GFP_KERNEL); + if (tunables) { + gov_attr_set_init(&tunables->attr_set, &sg_policy->tunables_hook); + if (!have_governor_per_policy()) + global_tunables = tunables; + } + return tunables; +} + +static void sugov_tunables_free(struct sugov_tunables *tunables) +{ + if (!have_governor_per_policy()) + global_tunables = NULL; + + kfree(tunables); +} + +static int sugov_init(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy; + struct sugov_tunables *tunables; + unsigned int lat; + int ret = 0; + + /* State should be equivalent to EXIT */ + if (policy->governor_data) + return -EBUSY; + + sg_policy = sugov_policy_alloc(policy); + if (!sg_policy) + return -ENOMEM; + + mutex_lock(&global_tunables_lock); + + if (global_tunables) { + if (WARN_ON(have_governor_per_policy())) { + ret = -EINVAL; + goto free_sg_policy; + } + policy->governor_data = sg_policy; + sg_policy->tunables = global_tunables; + + gov_attr_set_get(&global_tunables->attr_set, &sg_policy->tunables_hook); + goto out; + } + + tunables = sugov_tunables_alloc(sg_policy); + if (!tunables) { + ret = -ENOMEM; + goto free_sg_policy; + } + + tunables->rate_limit_us = LATENCY_MULTIPLIER; + lat = policy->cpuinfo.transition_latency / NSEC_PER_USEC; + if (lat) + tunables->rate_limit_us *= lat; + + policy->governor_data = sg_policy; + sg_policy->tunables = tunables; + + ret = kobject_init_and_add(&tunables->attr_set.kobj, &sugov_tunables_ktype, + get_governor_parent_kobj(policy), "%s", + schedutil_gov.name); + if (ret) + goto fail; + + out: + mutex_unlock(&global_tunables_lock); + + cpufreq_enable_fast_switch(policy); + return 0; + + fail: + policy->governor_data = NULL; + sugov_tunables_free(tunables); + + free_sg_policy: + mutex_unlock(&global_tunables_lock); + + sugov_policy_free(sg_policy); + pr_err("cpufreq: schedutil governor initialization failed (error %d)\n", ret); + return ret; +} + +static int sugov_exit(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + struct sugov_tunables *tunables = sg_policy->tunables; + unsigned int count; + + mutex_lock(&global_tunables_lock); + + count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook); + policy->governor_data = NULL; + if (!count) + sugov_tunables_free(tunables); + + mutex_unlock(&global_tunables_lock); + + sugov_policy_free(sg_policy); + return 0; +} + +static int sugov_start(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + unsigned int cpu; + + sg_policy->freq_update_delay_ns = sg_policy->tunables->rate_limit_us * NSEC_PER_USEC; + sg_policy->last_freq_update_time = 0; + sg_policy->next_freq = UINT_MAX; + sg_policy->work_in_progress = false; + sg_policy->need_freq_update = false; + + for_each_cpu(cpu, policy->cpus) { + struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); + + sg_cpu->sg_policy = sg_policy; + if (policy_is_shared(policy)) { + sg_cpu->util = ULONG_MAX; + sg_cpu->max = 0; + sg_cpu->last_update = 0; + cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, + sugov_update_shared); + } else { + cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, + sugov_update_single); + } + } + return 0; +} + +static int sugov_stop(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + unsigned int cpu; + + for_each_cpu(cpu, policy->cpus) + cpufreq_remove_update_util_hook(cpu); + + synchronize_sched(); + + irq_work_sync(&sg_policy->irq_work); + cancel_work_sync(&sg_policy->work); + return 0; +} + +static int sugov_limits(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + + if (!policy->fast_switch_enabled) { + mutex_lock(&sg_policy->work_lock); + + if (policy->max < policy->cur) + __cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_H); + else if (policy->min > policy->cur) + __cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_L); + + mutex_unlock(&sg_policy->work_lock); + } + + sg_policy->need_freq_update = true; + return 0; +} + +int sugov_governor(struct cpufreq_policy *policy, unsigned int event) +{ + if (event == CPUFREQ_GOV_POLICY_INIT) { + return sugov_init(policy); + } else if (policy->governor_data) { + switch (event) { + case CPUFREQ_GOV_POLICY_EXIT: + return sugov_exit(policy); + case CPUFREQ_GOV_START: + return sugov_start(policy); + case CPUFREQ_GOV_STOP: + return sugov_stop(policy); + case CPUFREQ_GOV_LIMITS: + return sugov_limits(policy); + } + } + return -EINVAL; +} + +static struct cpufreq_governor schedutil_gov = { + .name = "schedutil", + .governor = sugov_governor, + .owner = THIS_MODULE, +}; + +static int __init sugov_module_init(void) +{ + return cpufreq_register_governor(&schedutil_gov); +} + +static void __exit sugov_module_exit(void) +{ + cpufreq_unregister_governor(&schedutil_gov); +} + +MODULE_AUTHOR("Rafael J. Wysocki "); +MODULE_DESCRIPTION("Utilization-based CPU frequency selection"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &schedutil_gov; +} + +fs_initcall(sugov_module_init); +#else +module_init(sugov_module_init); +#endif +module_exit(sugov_module_exit); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index ec2e8d23527e..921d6e5d33b7 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1842,6 +1842,14 @@ static inline void cpufreq_update_util(u64 time, unsigned long util, unsigned lo static inline void cpufreq_trigger_update(u64 time) {} #endif /* CONFIG_CPU_FREQ */ +#ifdef arch_scale_freq_capacity +#ifndef arch_scale_freq_invariant +#define arch_scale_freq_invariant() (true) +#endif +#else /* arch_scale_freq_capacity */ +#define arch_scale_freq_invariant() (false) +#endif + static inline void account_reset_rq(struct rq *rq) { #ifdef CONFIG_IRQ_TIME_ACCOUNTING diff --git a/kernel/trace/power-traces.c b/kernel/trace/power-traces.c index 81b87451c0ea..0c7dee221dca 100644 --- a/kernel/trace/power-traces.c +++ b/kernel/trace/power-traces.c @@ -15,5 +15,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(suspend_resume); EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle); +EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_frequency); EXPORT_TRACEPOINT_SYMBOL_GPL(powernv_throttle); -- GitLab From a454018505f2e875441603b18dbbb912d422f7d1 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Sun, 27 Mar 2016 11:26:13 +0200 Subject: [PATCH 1103/9938] clk: unconditionally recurse into clk/mvebu/ The drivers/clk/mvebu directory is only being built when CONFIG_PLAT_ORION=y. As we are going to support additional mvebu platforms in drivers/clk/mvebu, which don't have CONFIG_PLAT_ORION=y, we need to recurse into this directory regardless of the value of CONFIG_PLAT_ORION. Since all files in drivers/clk/mvebu/ are already conditionally compiled depending on various Kconfig options, we can recurse unconditionally into drivers/clk/mvebu without any other change. Signed-off-by: Thomas Petazzoni Signed-off-by: Stephen Boyd --- drivers/clk/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 46869d696e4d..f9ad66e60b48 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -61,7 +61,7 @@ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ endif -obj-$(CONFIG_PLAT_ORION) += mvebu/ +obj-y += mvebu/ obj-$(CONFIG_ARCH_MESON) += meson/ obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ -- GitLab From c0553d04f8d35bf9706e20ba392ffa61ab2b6f5c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Sun, 27 Mar 2016 11:26:14 +0200 Subject: [PATCH 1104/9938] dt-bindings: arm: add DT binding for Marvell AP806 system controller This commit adds the Device Tree binding documentation for the system controller found in Marvell AP806 HW block, which is one of the core HW blocks of the 64-bits Marvell Armada 7K/8K family. Signed-off-by: Thomas Petazzoni Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../arm/marvell/ap806-system-controller.txt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt diff --git a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt new file mode 100644 index 000000000000..8968371d84e2 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt @@ -0,0 +1,35 @@ +Marvell Armada AP806 System Controller +====================================== + +The AP806 is one of the two core HW blocks of the Marvell Armada 7K/8K +SoCs. It contains a system controller, which provides a number +registers giving access to numerous features: clocks, pin-muxing and +many other SoC configuration items. This DT binding allows to describe +this system controller. + +The Device Tree node representing the AP806 system controller provides +a number of clocks: + + - 0: clock of CPU cluster 0 + - 1: clock of CPU cluster 1 + - 2: fixed PLL at 1200 Mhz + - 3: MSS clock, derived from the fixed PLL + +Required properties: + + - compatible: must be: + "marvell,ap806-system-controller", "syscon" + - reg: register area of the AP806 system controller + - #clock-cells: must be set to 1 + - clock-output-names: must be defined to: + "ap-cpu-cluster-0", "ap-cpu-cluster-1", "ap-fixed", "ap-mss" + +Example: + + syscon: system-controller@6f4000 { + compatible = "marvell,ap806-system-controller", "syscon"; + #clock-cells = <1>; + clock-output-names = "ap-cpu-cluster-0", "ap-cpu-cluster-1", + "ap-fixed", "ap-mss"; + reg = <0x6f4000 0x1000>; + }; -- GitLab From e17ced2cb61ac63efb5ab54fee8e45aaa437c874 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 31 Mar 2016 13:48:01 -0500 Subject: [PATCH 1105/9938] EDAC, altera: Extract error inject operations to a struct fops In preparation for the Arria10 peripheral ECCs, extract the inject file operations because the Arria10 IRQ trigger mechanism is different than Cyclone5/Arria5 and Arria10 L2 cache. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1459450087-24792-2-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 5 ++++- drivers/edac/altera_edac.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 0afdc582766e..fb6fe568d0dc 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -668,7 +668,7 @@ static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci, if (!edac_debugfs_create_file(priv->dbgfs_name, S_IWUSR, drvdata->debugfs_dir, edac_dci, - &altr_edac_device_inject_fops)) + priv->inject_fops)) debugfs_remove_recursive(drvdata->debugfs_dir); } @@ -886,6 +886,7 @@ const struct edac_device_prv_data ocramecc_data = { .ue_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJD), .set_err_ofst = ALTR_OCR_ECC_REG_OFFSET, .trig_alloc_sz = ALTR_TRIG_OCRAM_BYTE_SIZE, + .inject_fops = &altr_edac_device_inject_fops, }; #endif /* CONFIG_EDAC_ALTERA_OCRAM */ @@ -975,6 +976,7 @@ const struct edac_device_prv_data l2ecc_data = { .ue_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJD), .set_err_ofst = ALTR_L2_ECC_REG_OFFSET, .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE, + .inject_fops = &altr_edac_device_inject_fops, }; const struct edac_device_prv_data a10_l2ecc_data = { @@ -991,6 +993,7 @@ const struct edac_device_prv_data a10_l2ecc_data = { .set_err_ofst = ALTR_A10_L2_ECC_INJ_OFST, .ecc_irq_handler = altr_edac_a10_l2_irq, .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE, + .inject_fops = &altr_edac_device_inject_fops, }; #endif /* CONFIG_EDAC_ALTERA_L2C */ diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index b0a17d03c715..c995388b415b 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -262,6 +262,7 @@ struct edac_device_prv_data { irqreturn_t (*ecc_irq_handler)(struct altr_edac_device_dev *dci, bool sb); int trig_alloc_sz; + const struct file_operations *inject_fops; }; struct altr_edac_device_dev { -- GitLab From 943ad9179836b12433beadfde2d03b215c4367d6 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 31 Mar 2016 13:48:02 -0500 Subject: [PATCH 1106/9938] EDAC, altera: Add register offset for ECC Enable In preparation for the Arria10 peripheral ECCs, add a register offset from the ECC base to index to the ECC enable register. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1459450087-24792-3-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 3 ++- drivers/edac/altera_edac.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index fb6fe568d0dc..f0a6de748fae 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -866,7 +866,7 @@ static int altr_ocram_check_deps(struct altr_edac_device_dev *device) void __iomem *base = device->base; const struct edac_device_prv_data *prv = device->data; - if (readl(base) & prv->ecc_enable_mask) + if (readl(base + prv->ecc_en_ofst) & prv->ecc_enable_mask) return 0; edac_printk(KERN_ERR, EDAC_DEVICE, @@ -882,6 +882,7 @@ const struct edac_device_prv_data ocramecc_data = { .alloc_mem = ocram_alloc_mem, .free_mem = ocram_free_mem, .ecc_enable_mask = ALTR_OCR_ECC_EN, + .ecc_en_ofst = ALTR_OCR_ECC_REG_OFFSET, .ce_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJS), .ue_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJD), .set_err_ofst = ALTR_OCR_ECC_REG_OFFSET, diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index c995388b415b..cb6b2b9079e8 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -256,6 +256,7 @@ struct edac_device_prv_data { void * (*alloc_mem)(size_t size, void **other); void (*free_mem)(void *p, size_t size, void *other); int ecc_enable_mask; + int ecc_en_ofst; int ce_set_mask; int ue_set_mask; int set_err_ofst; -- GitLab From aa1f06dcc0e58e1a1b5118fc265418a2970e11aa Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 31 Mar 2016 13:48:03 -0500 Subject: [PATCH 1107/9938] EDAC, altera: Make OCRAM ECC dependency check generic In preparation for the Arria10 peripheral ECCs, move the OCRAM ECC dependency check into the general ECC area since this same function can be used by other memories. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1459450087-24792-4-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 43 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index f0a6de748fae..f7ffc77998a4 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -648,6 +648,26 @@ static ssize_t altr_edac_device_trig(struct file *file, return count; } +/* + * Test for memory's ECC dependencies upon entry because platform specific + * startup should have initialized the memory and enabled the ECC. + * Can't turn on ECC here because accessing un-initialized memory will + * cause CE/UE errors possibly causing an ABORT. + */ +static int altr_check_ecc_deps(struct altr_edac_device_dev *device) +{ + void __iomem *base = device->base; + const struct edac_device_prv_data *prv = device->data; + + if (readl(base + prv->ecc_en_ofst) & prv->ecc_enable_mask) + return 0; + + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s: No ECC present or ECC disabled.\n", + device->edac_dev_name); + return -ENODEV; +} + static const struct file_operations altr_edac_device_inject_fops = { .open = simple_open, .write = altr_edac_device_trig, @@ -853,29 +873,8 @@ static void ocram_free_mem(void *p, size_t size, void *other) gen_pool_free((struct gen_pool *)other, (u32)p, size); } -/* - * altr_ocram_check_deps() - * Test for OCRAM cache ECC dependencies upon entry because - * platform specific startup should have initialized the - * On-Chip RAM memory and enabled the ECC. - * Can't turn on ECC here because accessing un-initialized - * memory will cause CE/UE errors possibly causing an ABORT. - */ -static int altr_ocram_check_deps(struct altr_edac_device_dev *device) -{ - void __iomem *base = device->base; - const struct edac_device_prv_data *prv = device->data; - - if (readl(base + prv->ecc_en_ofst) & prv->ecc_enable_mask) - return 0; - - edac_printk(KERN_ERR, EDAC_DEVICE, - "OCRAM: No ECC present or ECC disabled.\n"); - return -ENODEV; -} - const struct edac_device_prv_data ocramecc_data = { - .setup = altr_ocram_check_deps, + .setup = altr_check_ecc_deps, .ce_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_SERR), .ue_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_DERR), .dbgfs_name = "altr_ocram_trigger", -- GitLab From abd56b3c8483ca73413ade0e7c7a0d13b9870016 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 31 Mar 2016 13:48:04 -0500 Subject: [PATCH 1108/9938] Documentation: dt: socfpga: Add Altera Arria10 OCRAM binding Add the device tree bindings needed to support the Altera On-Chip RAM ECC on the Arria10 chip. Signed-off-by: Thor Thayer Acked-by: Rob Herring Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1459450087-24792-5-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- .../devicetree/bindings/arm/altera/socfpga-eccmgr.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt index 37ff9bfea5f4..5a6b16070a33 100644 --- a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt +++ b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt @@ -71,6 +71,11 @@ Required Properties: - compatible : Should be "altr,socfpga-a10-l2-ecc" - reg : Address and size for ECC error interrupt clear registers. +On-Chip RAM ECC +Required Properties: +- compatible : Should be "altr,socfpga-a10-ocram-ecc" +- reg : Address and size for ECC block registers. + Example: eccmgr: eccmgr@ffd06000 { @@ -86,4 +91,9 @@ Example: compatible = "altr,socfpga-a10-l2-ecc"; reg = <0xffd06010 0x4>; }; + + ocram-ecc@ff8c3000 { + compatible = "altr,socfpga-a10-ocram-ecc"; + reg = <0xff8c3000 0x90>; + }; }; -- GitLab From 2349262397b89a421adfd142aad2a7dd33710f26 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Wed, 30 Mar 2016 14:54:20 -0700 Subject: [PATCH 1109/9938] tcp: remove cwnd moderation after recovery For non-SACK connections, cwnd is lowered to inflight plus 3 packets when the recovery ends. This is an optional feature in the NewReno RFC 2582 to reduce the potential burst when cwnd is "re-opened" after recovery and inflight is low. This feature is questionably effective because of PRR: when the recovery ends (i.e., snd_una == high_seq) NewReno holds the CA_Recovery state for another round trip to prevent false fast retransmits. But if the inflight is low, PRR will overwrite the moderated cwnd in tcp_cwnd_reduction() later regardlessly. So if a receiver responds bogus ACKs (i.e., acking future data) to speed up transfer after recovery, it can only induce a burst up to a window worth of data packets by acking up to SND.NXT. A restart from (short) idle or receiving streched ACKs can both cause such bursts as well. On the other hand, if the recovery ends because the sender detects the losses were spurious (e.g., reordering). This feature unconditionally lowers a reverted cwnd even though nothing was lost. By principle loss recovery module should not update cwnd. Further pacing is much more effective to reduce burst. Hence this patch removes the cwnd moderation feature. v2 changes: revised commit message on bogus ACKs and burst, and missing signature Signed-off-by: Matt Mathis Signed-off-by: Neal Cardwell Signed-off-by: Soheil Hassas Yeganeh Signed-off-by: Yuchung Cheng Signed-off-by: David S. Miller --- include/net/tcp.h | 11 ----------- net/ipv4/tcp_input.c | 11 ----------- 2 files changed, 22 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index b91370f61be6..f8bb4a4ed3d1 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1039,17 +1039,6 @@ static inline __u32 tcp_max_tso_deferred_mss(const struct tcp_sock *tp) return 3; } -/* Slow start with delack produces 3 packets of burst, so that - * it is safe "de facto". This will be the default - same as - * the default reordering threshold - but if reordering increases, - * we must be able to allow cwnd to burst at least this much in order - * to not pull it back when holes are filled. - */ -static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp) -{ - return tp->reordering; -} - /* Returns end sequence number of the receiver's advertised window */ static inline u32 tcp_wnd_end(const struct tcp_sock *tp) { diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e6e65f79ade8..f87b84a75691 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2252,16 +2252,6 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit) } } -/* CWND moderation, preventing bursts due to too big ACKs - * in dubious situations. - */ -static inline void tcp_moderate_cwnd(struct tcp_sock *tp) -{ - tp->snd_cwnd = min(tp->snd_cwnd, - tcp_packets_in_flight(tp) + tcp_max_burst(tp)); - tp->snd_cwnd_stamp = tcp_time_stamp; -} - static bool tcp_tsopt_ecr_before(const struct tcp_sock *tp, u32 when) { return tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && @@ -2410,7 +2400,6 @@ static bool tcp_try_undo_recovery(struct sock *sk) /* Hold old state until something *above* high_seq * is ACKed. For Reno it is MUST to prevent false * fast retransmits (RFC2582). SACK TCP is safe. */ - tcp_moderate_cwnd(tp); if (!tcp_any_retrans_done(sk)) tp->retrans_stamp = 0; return true; -- GitLab From 7822ce73e659ab0c5dd8289f077efbcc4cd03164 Mon Sep 17 00:00:00 2001 From: Haishuang Yan Date: Thu, 31 Mar 2016 18:21:38 +0800 Subject: [PATCH 1110/9938] netlink: use nla_get_in_addr and nla_put_in_addr for ipv4 address Since nla_get_in_addr and nla_put_in_addr were implemented, so use them appropriately. Signed-off-by: Haishuang Yan Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 6165f30c4d72..b3ab1205dfdf 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -247,10 +247,10 @@ static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr, tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP_ID]); if (tb[LWTUNNEL_IP_DST]) - tun_info->key.u.ipv4.dst = nla_get_be32(tb[LWTUNNEL_IP_DST]); + tun_info->key.u.ipv4.dst = nla_get_in_addr(tb[LWTUNNEL_IP_DST]); if (tb[LWTUNNEL_IP_SRC]) - tun_info->key.u.ipv4.src = nla_get_be32(tb[LWTUNNEL_IP_SRC]); + tun_info->key.u.ipv4.src = nla_get_in_addr(tb[LWTUNNEL_IP_SRC]); if (tb[LWTUNNEL_IP_TTL]) tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP_TTL]); @@ -275,8 +275,8 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb, struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate); if (nla_put_be64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id) || - nla_put_be32(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) || - nla_put_be32(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) || + nla_put_in_addr(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) || + nla_put_in_addr(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) || nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.tos) || nla_put_u8(skb, LWTUNNEL_IP_TTL, tun_info->key.ttl) || nla_put_be16(skb, LWTUNNEL_IP_FLAGS, tun_info->key.tun_flags)) -- GitLab From 5ada37b53ea2b310df143b2c7d6c48fbf14d5cb8 Mon Sep 17 00:00:00 2001 From: Lisheng Date: Thu, 31 Mar 2016 21:00:09 +0800 Subject: [PATCH 1111/9938] net: hns: add support of pause frame ctrl for HNS V2 The patch adds support of pause ctrl for HNS V2, and this feature is lost by HNS V1: 1) service ports can disable rx pause frame, 2) debug ports can open tx/rx pause frame. And this patch updates the REGs about the pause ctrl when updated status function called by upper layer routine. Signed-off-by: Lisheng Signed-off-by: Yisen Zhuang Reviewed-by: Andy Shevchenko Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 20 ++++- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 30 ++------ .../ethernet/hisilicon/hns/hns_dsaf_main.c | 75 ++++++++++++++++--- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 5 ++ .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 6 +- .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 6 ++ 6 files changed, 104 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index a1cb461ac45f..159142272afb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -399,11 +399,16 @@ static void hns_ae_get_ring_bdnum_limit(struct hnae_queue *queue, static void hns_ae_get_pauseparam(struct hnae_handle *handle, u32 *auto_neg, u32 *rx_en, u32 *tx_en) { - assert(handle); + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; - hns_mac_get_autoneg(hns_get_mac_cb(handle), auto_neg); + hns_mac_get_autoneg(mac_cb, auto_neg); - hns_mac_get_pauseparam(hns_get_mac_cb(handle), rx_en, tx_en); + hns_mac_get_pauseparam(mac_cb, rx_en, tx_en); + + /* Service port's pause feature is provided by DSAF, not mac */ + if (handle->port_type == HNAE_PORT_SERVICE) + hns_dsaf_get_rx_mac_pause_en(dsaf_dev, mac_cb->mac_id, rx_en); } static int hns_ae_set_autoneg(struct hnae_handle *handle, u8 enable) @@ -436,12 +441,21 @@ static int hns_ae_set_pauseparam(struct hnae_handle *handle, u32 autoneg, u32 rx_en, u32 tx_en) { struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; int ret; ret = hns_mac_set_autoneg(mac_cb, autoneg); if (ret) return ret; + /* Service port's pause feature is provided by DSAF, not mac */ + if (handle->port_type == HNAE_PORT_SERVICE) { + ret = hns_dsaf_set_rx_mac_pause_en(dsaf_dev, + mac_cb->mac_id, rx_en); + if (ret) + return ret; + rx_en = 0; + } return hns_mac_set_pauseparam(mac_cb, rx_en, tx_en); } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index a38084a22bf2..10c367d20955 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -439,9 +439,8 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable) void hns_mac_reset(struct hns_mac_cb *mac_cb) { - struct mac_driver *drv; - - drv = hns_mac_get_drv(mac_cb); + struct mac_driver *drv = hns_mac_get_drv(mac_cb); + bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); drv->mac_init(drv); @@ -456,7 +455,7 @@ void hns_mac_reset(struct hns_mac_cb *mac_cb) if (drv->mac_pausefrm_cfg) { if (mac_cb->mac_type == HNAE_PORT_DEBUG) - drv->mac_pausefrm_cfg(drv, 0, 0); + drv->mac_pausefrm_cfg(drv, !is_ver1, !is_ver1); else /* mac rx must disable, dsaf pfc close instead of it*/ drv->mac_pausefrm_cfg(drv, 0, 1); } @@ -561,14 +560,6 @@ void hns_mac_get_pauseparam(struct hns_mac_cb *mac_cb, u32 *rx_en, u32 *tx_en) *rx_en = 0; *tx_en = 0; } - - /* Due to the chip defect, the service mac's rx pause CAN'T be enabled. - * We set the rx pause frm always be true (1), because DSAF deals with - * the rx pause frm instead of service mac. After all, we still support - * rx pause frm. - */ - if (mac_cb->mac_type == HNAE_PORT_SERVICE) - *rx_en = 1; } /** @@ -602,20 +593,13 @@ int hns_mac_set_autoneg(struct hns_mac_cb *mac_cb, u8 enable) int hns_mac_set_pauseparam(struct hns_mac_cb *mac_cb, u32 rx_en, u32 tx_en) { struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); - if (mac_cb->mac_type == HNAE_PORT_SERVICE) { - if (!rx_en) { - dev_err(mac_cb->dev, "disable rx_pause is not allowed!"); + if (mac_cb->mac_type == HNAE_PORT_DEBUG) { + if (is_ver1 && (tx_en || rx_en)) { + dev_err(mac_cb->dev, "macv1 cann't enable tx/rx_pause!"); return -EINVAL; } - } else if (mac_cb->mac_type == HNAE_PORT_DEBUG) { - if (tx_en || rx_en) { - dev_err(mac_cb->dev, "enable tx_pause or enable rx_pause are not allowed!"); - return -EINVAL; - } - } else { - dev_err(mac_cb->dev, "Unsupport this operation!"); - return -EINVAL; } if (mac_ctrl_drv->mac_pausefrm_cfg) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 5978a5c8ef35..8439f6d8e360 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1022,12 +1022,52 @@ static void hns_dsaf_tbl_tcam_init(struct dsaf_device *dsaf_dev) * @mac_cb: mac contrl block */ static void hns_dsaf_pfc_en_cfg(struct dsaf_device *dsaf_dev, - int mac_id, int en) + int mac_id, int tc_en) { - if (!en) - dsaf_write_dev(dsaf_dev, DSAF_PFC_EN_0_REG + mac_id * 4, 0); + dsaf_write_dev(dsaf_dev, DSAF_PFC_EN_0_REG + mac_id * 4, tc_en); +} + +static void hns_dsaf_set_pfc_pause(struct dsaf_device *dsaf_dev, + int mac_id, int tx_en, int rx_en) +{ + if (AE_IS_VER1(dsaf_dev->dsaf_ver)) { + if (!tx_en || !rx_en) + dev_err(dsaf_dev->dev, "dsaf v1 can not close pfc!\n"); + + return; + } + + dsaf_set_dev_bit(dsaf_dev, DSAF_PAUSE_CFG_REG + mac_id * 4, + DSAF_PFC_PAUSE_RX_EN_B, !!rx_en); + dsaf_set_dev_bit(dsaf_dev, DSAF_PAUSE_CFG_REG + mac_id * 4, + DSAF_PFC_PAUSE_TX_EN_B, !!tx_en); +} + +int hns_dsaf_set_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, + u32 en) +{ + if (AE_IS_VER1(dsaf_dev->dsaf_ver)) { + if (!en) + dev_err(dsaf_dev->dev, "dsafv1 can't close rx_pause!\n"); + + return -EINVAL; + } + + dsaf_set_dev_bit(dsaf_dev, DSAF_PAUSE_CFG_REG + mac_id * 4, + DSAF_MAC_PAUSE_RX_EN_B, !!en); + + return 0; +} + +void hns_dsaf_get_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, + u32 *en) +{ + if (AE_IS_VER1(dsaf_dev->dsaf_ver)) + *en = 1; else - dsaf_write_dev(dsaf_dev, DSAF_PFC_EN_0_REG + mac_id * 4, 0xff); + *en = dsaf_get_dev_bit(dsaf_dev, + DSAF_PAUSE_CFG_REG + mac_id * 4, + DSAF_MAC_PAUSE_RX_EN_B); } /** @@ -1039,6 +1079,7 @@ static void hns_dsaf_comm_init(struct dsaf_device *dsaf_dev) { u32 i; u32 o_dsaf_cfg; + bool is_ver1 = AE_IS_VER1(dsaf_dev->dsaf_ver); o_dsaf_cfg = dsaf_read_dev(dsaf_dev, DSAF_CFG_0_REG); dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_EN_S, dsaf_dev->dsaf_en); @@ -1064,8 +1105,10 @@ static void hns_dsaf_comm_init(struct dsaf_device *dsaf_dev) hns_dsaf_sw_port_type_cfg(dsaf_dev, DSAF_SW_PORT_TYPE_NON_VLAN); /*set dsaf pfc to 0 for parseing rx pause*/ - for (i = 0; i < DSAF_COMM_CHN; i++) + for (i = 0; i < DSAF_COMM_CHN; i++) { hns_dsaf_pfc_en_cfg(dsaf_dev, i, 0); + hns_dsaf_set_pfc_pause(dsaf_dev, i, is_ver1, is_ver1); + } /*msk and clr exception irqs */ for (i = 0; i < DSAF_COMM_CHN; i++) { @@ -2013,6 +2056,8 @@ void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 node_num) { struct dsaf_hw_stats *hw_stats = &dsaf_dev->hw_stats[node_num]; + bool is_ver1 = AE_IS_VER1(dsaf_dev->dsaf_ver); + u32 reg_tmp; hw_stats->pad_drop += dsaf_read_dev(dsaf_dev, DSAF_INODE_PAD_DISCARD_NUM_0_REG + 0x80 * (u64)node_num); @@ -2022,8 +2067,12 @@ void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 node_num) DSAF_INODE_FINAL_IN_PKT_NUM_0_REG + 0x80 * (u64)node_num); hw_stats->rx_pkt_id += dsaf_read_dev(dsaf_dev, DSAF_INODE_SBM_PID_NUM_0_REG + 0x80 * (u64)node_num); - hw_stats->rx_pause_frame += dsaf_read_dev(dsaf_dev, - DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG + 0x80 * (u64)node_num); + + reg_tmp = is_ver1 ? DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG : + DSAFV2_INODE_FINAL_IN_PAUSE_NUM_0_REG; + hw_stats->rx_pause_frame += + dsaf_read_dev(dsaf_dev, reg_tmp + 0x80 * (u64)node_num); + hw_stats->release_buf_num += dsaf_read_dev(dsaf_dev, DSAF_INODE_SBM_RELS_NUM_0_REG + 0x80 * (u64)node_num); hw_stats->sbm_drop += dsaf_read_dev(dsaf_dev, @@ -2056,6 +2105,8 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data) u32 i = 0; u32 j; u32 *p = data; + u32 reg_tmp; + bool is_ver1 = AE_IS_VER1(ddev->dsaf_ver); /* dsaf common registers */ p[0] = dsaf_read_dev(ddev, DSAF_SRAM_INIT_OVER_0_REG); @@ -2120,8 +2171,9 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data) DSAF_INODE_FINAL_IN_PKT_NUM_0_REG + j * 0x80); p[190 + i] = dsaf_read_dev(ddev, DSAF_INODE_SBM_PID_NUM_0_REG + j * 0x80); - p[193 + i] = dsaf_read_dev(ddev, - DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG + j * 0x80); + reg_tmp = is_ver1 ? DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG : + DSAFV2_INODE_FINAL_IN_PAUSE_NUM_0_REG; + p[193 + i] = dsaf_read_dev(ddev, reg_tmp + j * 0x80); p[196 + i] = dsaf_read_dev(ddev, DSAF_INODE_SBM_RELS_NUM_0_REG + j * 0x80); p[199 + i] = dsaf_read_dev(ddev, @@ -2368,8 +2420,11 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data) p[496] = dsaf_read_dev(ddev, DSAF_NETPORT_CTRL_SIG_0_REG + port * 0x4); p[497] = dsaf_read_dev(ddev, DSAF_XGE_CTRL_SIG_CFG_0_REG + port * 0x4); + if (!is_ver1) + p[498] = dsaf_read_dev(ddev, DSAF_PAUSE_CFG_REG + port * 0x4); + /* mark end of dsaf regs */ - for (i = 498; i < 504; i++) + for (i = 499; i < 504; i++) p[i] = 0xdddddddd; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 5fea226efaf3..e8eedc571296 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -417,6 +417,11 @@ void hns_dsaf_get_strings(int stringset, u8 *data, int port); void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data); int hns_dsaf_get_regs_count(void); void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en); + +void hns_dsaf_get_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, + u32 *en); +int hns_dsaf_set_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, + u32 en); void hns_dsaf_set_inner_lb(struct dsaf_device *dsaf_dev, u32 mac_id, u32 en); #endif /* __HNS_DSAF_MAIN_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c index 5b7ae5ff43e8..ab27b3b14ca3 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -332,10 +332,12 @@ static void hns_ppe_init_hw(struct hns_ppe_cb *ppe_cb) /* clr and msk except irq*/ hns_ppe_exc_irq_en(ppe_cb, 0); - if (ppe_common_cb->ppe_mode == PPE_COMMON_MODE_DEBUG) + if (ppe_common_cb->ppe_mode == PPE_COMMON_MODE_DEBUG) { hns_ppe_set_port_mode(ppe_cb, PPE_MODE_GE); - else + dsaf_write_dev(ppe_cb, PPE_CFG_PAUSE_IDLE_CNT_REG, 0); + } else { hns_ppe_set_port_mode(ppe_cb, PPE_MODE_XGE); + } hns_ppe_checksum_hw(ppe_cb, 0xffffffff); hns_ppe_cnt_clr_ce(ppe_cb); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 7d7204f45e78..7ff195e60b02 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -137,6 +137,7 @@ #define DSAF_PPE_INT_STS_0_REG 0x1E0 #define DSAF_ROCEE_INT_STS_0_REG 0x200 #define DSAFV2_SERDES_LBK_0_REG 0x220 +#define DSAF_PAUSE_CFG_REG 0x240 #define DSAF_PPE_QID_CFG_0_REG 0x300 #define DSAF_SW_PORT_TYPE_0_REG 0x320 #define DSAF_STP_PORT_TYPE_0_REG 0x340 @@ -155,6 +156,7 @@ #define DSAF_INODE_FINAL_IN_PKT_NUM_0_REG 0x1030 #define DSAF_INODE_SBM_PID_NUM_0_REG 0x1038 #define DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG 0x103C +#define DSAFV2_INODE_FINAL_IN_PAUSE_NUM_0_REG 0x1024 #define DSAF_INODE_SBM_RELS_NUM_0_REG 0x104C #define DSAF_INODE_SBM_DROP_NUM_0_REG 0x1050 #define DSAF_INODE_CRC_FALSE_NUM_0_REG 0x1054 @@ -711,6 +713,10 @@ #define DSAF_PFC_UNINT_CNT_M ((1ULL << 9) - 1) #define DSAF_PFC_UNINT_CNT_S 0 +#define DSAF_MAC_PAUSE_RX_EN_B 2 +#define DSAF_PFC_PAUSE_RX_EN_B 1 +#define DSAF_PFC_PAUSE_TX_EN_B 0 + #define DSAF_PPE_QID_CFG_M 0xFF #define DSAF_PPE_QID_CFG_S 0 -- GitLab From f10a6a3541b4f79f6a4d9f0d4f8f16b92f8f1cfc Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:25 +0200 Subject: [PATCH 1112/9938] stmmac: rework get_hw_feature function On next GMAC IP generation (4.xx), the way to get hw feature is not the same than on previous 3.xx. As it is hardware dependent, the way to get hw capabilities should be defined in dma ops of each MAC IP. It will avoid also a huge computation of hw capabilities in stmmac_main. Signed-off-by: Alexandre TORGUE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 3 +- .../ethernet/stmicro/stmmac/dwmac1000_dma.c | 35 ++++++++++++- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 50 +++---------------- 3 files changed, 42 insertions(+), 46 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index f96d257308b0..797a913ef618 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -412,7 +412,8 @@ struct stmmac_dma_ops { int (*dma_interrupt) (void __iomem *ioaddr, struct stmmac_extra_stats *x); /* If supported then get the optional core features */ - unsigned int (*get_hw_feature) (void __iomem *ioaddr); + void (*get_hw_feature)(void __iomem *ioaddr, + struct dma_features *dma_cap); /* Program the HW RX Watchdog */ void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt); }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index da32d6037e3e..990746955216 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -215,9 +215,40 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr) } } -static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr) +static void dwmac1000_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) { - return readl(ioaddr + DMA_HW_FEATURE); + u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE); + + dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL); + dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1; + dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2; + dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4; + dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5; + dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6; + dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8; + dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9; + dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10; + /* MMC */ + dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11; + /* IEEE 1588-2002 */ + dma_cap->time_stamp = + (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12; + /* IEEE 1588-2008 */ + dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13; + /* 802.3az - Energy-Efficient Ethernet (EEE) */ + dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14; + dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15; + /* TX and RX csum */ + dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16; + dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17; + dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18; + dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19; + /* TX and RX number of channels */ + dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20; + dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22; + /* Alternate (enhanced) DESC mode */ + dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; } static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 78464fa7fe1f..b5db7513f36f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1552,51 +1552,15 @@ static void stmmac_selec_desc_mode(struct stmmac_priv *priv) */ static int stmmac_get_hw_features(struct stmmac_priv *priv) { - u32 hw_cap = 0; + u32 ret = 0; if (priv->hw->dma->get_hw_feature) { - hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr); - - priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL); - priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1; - priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2; - priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4; - priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5; - priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6; - priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8; - priv->dma_cap.pmt_remote_wake_up = - (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9; - priv->dma_cap.pmt_magic_frame = - (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10; - /* MMC */ - priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11; - /* IEEE 1588-2002 */ - priv->dma_cap.time_stamp = - (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12; - /* IEEE 1588-2008 */ - priv->dma_cap.atime_stamp = - (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13; - /* 802.3az - Energy-Efficient Ethernet (EEE) */ - priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14; - priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15; - /* TX and RX csum */ - priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16; - priv->dma_cap.rx_coe_type1 = - (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17; - priv->dma_cap.rx_coe_type2 = - (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18; - priv->dma_cap.rxfifo_over_2048 = - (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19; - /* TX and RX number of channels */ - priv->dma_cap.number_rx_channel = - (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20; - priv->dma_cap.number_tx_channel = - (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22; - /* Alternate (enhanced) DESC mode */ - priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; - } - - return hw_cap; + priv->hw->dma->get_hw_feature(priv->ioaddr, + &priv->dma_cap); + ret = 1; + } + + return ret; } /** -- GitLab From d0225e7de6229068df99ba8dacebc826d27e1cd5 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:26 +0200 Subject: [PATCH 1113/9938] stmmac: rework the routines to show the ring status To avoid lot of check in stmmac_main for display ring management and support the GMAC4 chip, the display_ring function is moved into dedicated descriptor file. Signed-off-by: Alexandre TORGUE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 2 + .../net/ethernet/stmicro/stmmac/enh_desc.c | 21 ++++++ .../net/ethernet/stmicro/stmmac/norm_desc.c | 21 ++++++ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 73 ++++++------------- 4 files changed, 67 insertions(+), 50 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 797a913ef618..6cea61bc5de9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -380,6 +380,8 @@ struct stmmac_desc_ops { u64(*get_timestamp) (void *desc, u32 ats); /* get rx timestamp status */ int (*get_rx_timestamp_status) (void *desc, u32 ats); + /* Display ring */ + void (*display_ring)(void *head, unsigned int size, bool rx); }; extern const struct stmmac_desc_ops enh_desc_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index cfb018c7c5eb..38f19c99cf59 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -411,6 +411,26 @@ static int enh_desc_get_rx_timestamp_status(void *desc, u32 ats) } } +static void enh_desc_display_ring(void *head, unsigned int size, bool rx) +{ + struct dma_extended_desc *ep = (struct dma_extended_desc *)head; + int i; + + pr_info("Extended %s descriptor ring:\n", rx ? "RX" : "TX"); + + for (i = 0; i < size; i++) { + u64 x; + + x = *(u64 *)ep; + pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", + i, (unsigned int)virt_to_phys(ep), + (unsigned int)x, (unsigned int)(x >> 32), + ep->basic.des2, ep->basic.des3); + ep++; + } + pr_info("\n"); +} + const struct stmmac_desc_ops enh_desc_ops = { .tx_status = enh_desc_get_tx_status, .rx_status = enh_desc_get_rx_status, @@ -430,4 +450,5 @@ const struct stmmac_desc_ops enh_desc_ops = { .get_tx_timestamp_status = enh_desc_get_tx_timestamp_status, .get_timestamp = enh_desc_get_timestamp, .get_rx_timestamp_status = enh_desc_get_rx_timestamp_status, + .display_ring = enh_desc_display_ring, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index 011386f6f24d..2beacd0d3043 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -279,6 +279,26 @@ static int ndesc_get_rx_timestamp_status(void *desc, u32 ats) return 1; } +static void ndesc_display_ring(void *head, unsigned int size, bool rx) +{ + struct dma_desc *p = (struct dma_desc *)head; + int i; + + pr_info("%s descriptor ring:\n", rx ? "RX" : "TX"); + + for (i = 0; i < size; i++) { + u64 x; + + x = *(u64 *)p; + pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x", + i, (unsigned int)virt_to_phys(p), + (unsigned int)x, (unsigned int)(x >> 32), + p->des2, p->des3); + p++; + } + pr_info("\n"); +} + const struct stmmac_desc_ops ndesc_ops = { .tx_status = ndesc_get_tx_status, .rx_status = ndesc_get_rx_status, @@ -297,4 +317,5 @@ const struct stmmac_desc_ops ndesc_ops = { .get_tx_timestamp_status = ndesc_get_tx_timestamp_status, .get_timestamp = ndesc_get_timestamp, .get_rx_timestamp_status = ndesc_get_rx_timestamp_status, + .display_ring = ndesc_display_ring, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index b5db7513f36f..0c9a2b9450d3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -877,53 +877,22 @@ static int stmmac_init_phy(struct net_device *dev) return 0; } -/** - * stmmac_display_ring - display ring - * @head: pointer to the head of the ring passed. - * @size: size of the ring. - * @extend_desc: to verify if extended descriptors are used. - * Description: display the control/status and buffer descriptors. - */ -static void stmmac_display_ring(void *head, int size, int extend_desc) -{ - int i; - struct dma_extended_desc *ep = (struct dma_extended_desc *)head; - struct dma_desc *p = (struct dma_desc *)head; - - for (i = 0; i < size; i++) { - u64 x; - if (extend_desc) { - x = *(u64 *) ep; - pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", - i, (unsigned int)virt_to_phys(ep), - (unsigned int)x, (unsigned int)(x >> 32), - ep->basic.des2, ep->basic.des3); - ep++; - } else { - x = *(u64 *) p; - pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x", - i, (unsigned int)virt_to_phys(p), - (unsigned int)x, (unsigned int)(x >> 32), - p->des2, p->des3); - p++; - } - pr_info("\n"); - } -} - static void stmmac_display_rings(struct stmmac_priv *priv) { + void *head_rx, *head_tx; + if (priv->extend_desc) { - pr_info("Extended RX descriptor ring:\n"); - stmmac_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1); - pr_info("Extended TX descriptor ring:\n"); - stmmac_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1); + head_rx = (void *)priv->dma_erx; + head_tx = (void *)priv->dma_etx; } else { - pr_info("RX descriptor ring:\n"); - stmmac_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0); - pr_info("TX descriptor ring:\n"); - stmmac_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0); + head_rx = (void *)priv->dma_rx; + head_tx = (void *)priv->dma_tx; } + + /* Display Rx ring */ + priv->hw->desc->display_ring(head_rx, DMA_RX_SIZE, true); + /* Display Tx ring */ + priv->hw->desc->display_ring(head_tx, DMA_TX_SIZE, false); } static int stmmac_set_bfsize(int mtu, int bufsize) @@ -1990,16 +1959,18 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) priv->cur_tx = entry; if (netif_msg_pktdata(priv)) { + void *tx_head; + pr_debug("%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d", __func__, priv->cur_tx, priv->dirty_tx, first_entry, entry, first, nfrags); if (priv->extend_desc) - stmmac_display_ring((void *)priv->dma_etx, - DMA_TX_SIZE, 1); + tx_head = (void *)priv->dma_etx; else - stmmac_display_ring((void *)priv->dma_tx, - DMA_TX_SIZE, 0); + tx_head = (void *)priv->dma_tx; + + priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false); pr_debug(">>> frame to be transmitted: "); print_pkt(skb->data, skb->len); @@ -2184,13 +2155,15 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) int coe = priv->hw->rx_csum; if (netif_msg_rx_status(priv)) { + void *rx_head; + pr_debug("%s: descriptor ring:\n", __func__); if (priv->extend_desc) - stmmac_display_ring((void *)priv->dma_erx, - DMA_RX_SIZE, 1); + rx_head = (void *)priv->dma_erx; else - stmmac_display_ring((void *)priv->dma_rx, - DMA_RX_SIZE, 0); + rx_head = (void *)priv->dma_rx; + + priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true); } while (count < limit) { int status; -- GitLab From c623d149b18cbdb7e9f782ced0c859b1836ef3cd Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:27 +0200 Subject: [PATCH 1114/9938] stmmac: rework synopsys id read, moved to dwmac setup synopsys_uid is only used once after setup, to get synopsys_id by using shitf/mask operation. It's no longer used then. So, remove this temporary variable and directly compute synopsys_id from setup routine. Acked-by: Giuseppe Cavallaro Signed-off-by: Fabrice Gasnier Signed-off-by: Alexandre TORGUE Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 27 ++++++++++++++-- .../ethernet/stmicro/stmmac/dwmac1000_core.c | 7 +++-- .../ethernet/stmicro/stmmac/dwmac100_core.c | 5 +-- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 31 ++----------------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 6cea61bc5de9..66e132f84aa8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -498,7 +498,6 @@ struct mac_device_info { const struct stmmac_hwtimestamp *ptp; struct mii_regs mii; /* MII register Addresses */ struct mac_link link; - unsigned int synopsys_uid; void __iomem *pcsr; /* vpointer to device CSRs */ int multicast_filter_bins; int unicast_filter_entries; @@ -507,8 +506,10 @@ struct mac_device_info { }; struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, - int perfect_uc_entries); -struct mac_device_info *dwmac100_setup(void __iomem *ioaddr); + int perfect_uc_entries, + int *synopsys_id); +struct mac_device_info *dwmac100_setup(void __iomem *ioaddr, int *synopsys_id); + void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], unsigned int high, unsigned int low); @@ -521,4 +522,24 @@ void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); extern const struct stmmac_mode_ops ring_mode_ops; extern const struct stmmac_mode_ops chain_mode_ops; +/** + * stmmac_get_synopsys_id - return the SYINID. + * @priv: driver private structure + * Description: this simple function is to decode and return the SYINID + * starting from the HW core register. + */ +static inline u32 stmmac_get_synopsys_id(u32 hwid) +{ + /* Check Synopsys Id (not available on old chips) */ + if (likely(hwid)) { + u32 uid = ((hwid & 0x0000ff00) >> 8); + u32 synid = (hwid & 0x000000ff); + + pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n", + uid, synid); + + return synid; + } + return 0; +} #endif /* __COMMON_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index c2941172f6d1..fb1eb578e34e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -491,7 +491,8 @@ static const struct stmmac_ops dwmac1000_ops = { }; struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, - int perfect_uc_entries) + int perfect_uc_entries, + int *synopsys_id) { struct mac_device_info *mac; u32 hwid = readl(ioaddr + GMAC_VERSION); @@ -516,7 +517,9 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, mac->link.speed = GMAC_CONTROL_FES; mac->mii.addr = GMAC_MII_ADDR; mac->mii.data = GMAC_MII_DATA; - mac->synopsys_uid = hwid; + + /* Get and dump the chip ID */ + *synopsys_id = stmmac_get_synopsys_id(hwid); return mac; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index f8dd773f246c..6418b2e07619 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -173,7 +173,7 @@ static const struct stmmac_ops dwmac100_ops = { .get_umac_addr = dwmac100_get_umac_addr, }; -struct mac_device_info *dwmac100_setup(void __iomem *ioaddr) +struct mac_device_info *dwmac100_setup(void __iomem *ioaddr, int *synopsys_id) { struct mac_device_info *mac; @@ -192,7 +192,8 @@ struct mac_device_info *dwmac100_setup(void __iomem *ioaddr) mac->link.speed = 0; mac->mii.addr = MAC_MII_ADDR; mac->mii.data = MAC_MII_DATA; - mac->synopsys_uid = 0; + /* Synopsys Id is not available on old chips */ + *synopsys_id = 0; return mac; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 0c9a2b9450d3..1186ac902bec 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1461,29 +1461,6 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv) pr_info(" No MAC Management Counters available\n"); } -/** - * stmmac_get_synopsys_id - return the SYINID. - * @priv: driver private structure - * Description: this simple function is to decode and return the SYINID - * starting from the HW core register. - */ -static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) -{ - u32 hwid = priv->hw->synopsys_uid; - - /* Check Synopsys Id (not available on old chips) */ - if (likely(hwid)) { - u32 uid = ((hwid & 0x0000ff00) >> 8); - u32 synid = (hwid & 0x000000ff); - - pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n", - uid, synid); - - return synid; - } - return 0; -} - /** * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors * @priv: driver private structure @@ -2757,18 +2734,16 @@ static int stmmac_hw_init(struct stmmac_priv *priv) priv->dev->priv_flags |= IFF_UNICAST_FLT; mac = dwmac1000_setup(priv->ioaddr, priv->plat->multicast_filter_bins, - priv->plat->unicast_filter_entries); + priv->plat->unicast_filter_entries, + &priv->synopsys_id); } else { - mac = dwmac100_setup(priv->ioaddr); + mac = dwmac100_setup(priv->ioaddr, &priv->synopsys_id); } if (!mac) return -ENOMEM; priv->hw = mac; - /* Get and dump the chip ID */ - priv->synopsys_id = stmmac_get_synopsys_id(priv); - /* To use the chained or ring mode */ if (chain_mode) { priv->hw->mode = &chain_mode_ops; -- GitLab From 753a71090f3325b4c34622daccbb71ed574cca73 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:28 +0200 Subject: [PATCH 1115/9938] stmmac: add descriptors function for GMAC 4.xx One of main changes of GMAC 4.xx IP is descriptors management. -descriptors are only used in ring mode. -A descriptor is composed of 4 32bits registers (no more extended descriptors) -descriptor mechanism (Tx for example, but it is exactly the same for RX): -useful registers: -DMA_CH#_TxDesc_Ring_Len: length of transmit descriptor ring -DMA_CH#_TxDesc_List_Address: start address of the ring -DMA_CH#_TxDesc_Tail_Pointer: address of the last descriptor to send + 1. -DMA_CH#_TxDesc_Current_App_TxDesc: address of the current descriptor -The descriptor Tail Pointer register contains the pointer to the descriptor address (N). The base address and the current descriptor decide the address of the current descriptor that the DMA can process. The descriptors up to one location less than the one indicated by the descriptor tail pointer (N-1) are owned by the DMA. The DMA continues to process the descriptors until the following condition occurs: "current descriptor pointer == Descriptor Tail pointer" Then the DMA goes into suspend mode. The application must perform a write to descriptor tail pointer register and update the tail pointer to have the following condition and to start a new transfer: "current descriptor pointer < Descriptor tail pointer" The DMA automatically wraps around the base address when the end of ring is reached. -New features are available on IP: -TSO (TCP Segmentation Offload) for TX only -Split header: to have header and payload in 2 different buffers Signed-off-by: Alexandre TORGUE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/Makefile | 3 +- drivers/net/ethernet/stmicro/stmmac/common.h | 7 + .../ethernet/stmicro/stmmac/dwmac4_descs.c | 396 ++++++++++++++++++ .../ethernet/stmicro/stmmac/dwmac4_descs.h | 129 ++++++ 4 files changed, 534 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index b3901616f4f6..fa000fd36efc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -2,7 +2,8 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ - mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y) + mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ + $(stmmac-y) # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 66e132f84aa8..ea7eb0d5ce98 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -243,6 +243,7 @@ enum rx_frame_status { csum_none = 0x2, llc_snap = 0x4, dma_own = 0x8, + rx_not_ls = 0x10, }; /* Tx status */ @@ -348,6 +349,10 @@ struct stmmac_desc_ops { void (*prepare_tx_desc) (struct dma_desc *p, int is_fs, int len, bool csum_flag, int mode, bool tx_own, bool ls); + void (*prepare_tso_tx_desc)(struct dma_desc *p, int is_fs, int len1, + int len2, bool tx_own, bool ls, + unsigned int tcphdrlen, + unsigned int tcppayloadlen); /* Set/get the owner of the descriptor */ void (*set_tx_owner) (struct dma_desc *p); int (*get_tx_owner) (struct dma_desc *p); @@ -382,6 +387,8 @@ struct stmmac_desc_ops { int (*get_rx_timestamp_status) (void *desc, u32 ats); /* Display ring */ void (*display_ring)(void *head, unsigned int size, bool rx); + /* set MSS via context descriptor */ + void (*set_mss)(struct dma_desc *p, unsigned int mss); }; extern const struct stmmac_desc_ops enh_desc_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c new file mode 100644 index 000000000000..d4952c7a836d --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -0,0 +1,396 @@ +/* + * This contains the functions to handle the descriptors for DesignWare databook + * 4.xx. + * + * Copyright (C) 2015 STMicroelectronics Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Author: Alexandre Torgue + */ + +#include +#include "common.h" +#include "dwmac4_descs.h" + +static int dwmac4_wrback_get_tx_status(void *data, struct stmmac_extra_stats *x, + struct dma_desc *p, + void __iomem *ioaddr) +{ + struct net_device_stats *stats = (struct net_device_stats *)data; + unsigned int tdes3; + int ret = tx_done; + + tdes3 = p->des3; + + /* Get tx owner first */ + if (unlikely(tdes3 & TDES3_OWN)) + return tx_dma_own; + + /* Verify tx error by looking at the last segment. */ + if (likely(!(tdes3 & TDES3_LAST_DESCRIPTOR))) + return tx_not_ls; + + if (unlikely(tdes3 & TDES3_ERROR_SUMMARY)) { + if (unlikely(tdes3 & TDES3_JABBER_TIMEOUT)) + x->tx_jabber++; + if (unlikely(tdes3 & TDES3_PACKET_FLUSHED)) + x->tx_frame_flushed++; + if (unlikely(tdes3 & TDES3_LOSS_CARRIER)) { + x->tx_losscarrier++; + stats->tx_carrier_errors++; + } + if (unlikely(tdes3 & TDES3_NO_CARRIER)) { + x->tx_carrier++; + stats->tx_carrier_errors++; + } + if (unlikely((tdes3 & TDES3_LATE_COLLISION) || + (tdes3 & TDES3_EXCESSIVE_COLLISION))) + stats->collisions += + (tdes3 & TDES3_COLLISION_COUNT_MASK) + >> TDES3_COLLISION_COUNT_SHIFT; + + if (unlikely(tdes3 & TDES3_EXCESSIVE_DEFERRAL)) + x->tx_deferred++; + + if (unlikely(tdes3 & TDES3_UNDERFLOW_ERROR)) + x->tx_underflow++; + + if (unlikely(tdes3 & TDES3_IP_HDR_ERROR)) + x->tx_ip_header_error++; + + if (unlikely(tdes3 & TDES3_PAYLOAD_ERROR)) + x->tx_payload_error++; + + ret = tx_err; + } + + if (unlikely(tdes3 & TDES3_DEFERRED)) + x->tx_deferred++; + + return ret; +} + +static int dwmac4_wrback_get_rx_status(void *data, struct stmmac_extra_stats *x, + struct dma_desc *p) +{ + struct net_device_stats *stats = (struct net_device_stats *)data; + unsigned int rdes1 = p->des1; + unsigned int rdes2 = p->des2; + unsigned int rdes3 = p->des3; + int message_type; + int ret = good_frame; + + if (unlikely(rdes3 & RDES3_OWN)) + return dma_own; + + /* Verify rx error by looking at the last segment. */ + if (likely(!(rdes3 & RDES3_LAST_DESCRIPTOR))) + return discard_frame; + + if (unlikely(rdes3 & RDES3_ERROR_SUMMARY)) { + if (unlikely(rdes3 & RDES3_GIANT_PACKET)) + stats->rx_length_errors++; + if (unlikely(rdes3 & RDES3_OVERFLOW_ERROR)) + x->rx_gmac_overflow++; + + if (unlikely(rdes3 & RDES3_RECEIVE_WATCHDOG)) + x->rx_watchdog++; + + if (unlikely(rdes3 & RDES3_RECEIVE_ERROR)) + x->rx_mii++; + + if (unlikely(rdes3 & RDES3_CRC_ERROR)) { + x->rx_crc++; + stats->rx_crc_errors++; + } + + if (unlikely(rdes3 & RDES3_DRIBBLE_ERROR)) + x->dribbling_bit++; + + ret = discard_frame; + } + + message_type = (rdes1 & ERDES4_MSG_TYPE_MASK) >> 8; + + if (rdes1 & RDES1_IP_HDR_ERROR) + x->ip_hdr_err++; + if (rdes1 & RDES1_IP_CSUM_BYPASSED) + x->ip_csum_bypassed++; + if (rdes1 & RDES1_IPV4_HEADER) + x->ipv4_pkt_rcvd++; + if (rdes1 & RDES1_IPV6_HEADER) + x->ipv6_pkt_rcvd++; + if (message_type == RDES_EXT_SYNC) + x->rx_msg_type_sync++; + else if (message_type == RDES_EXT_FOLLOW_UP) + x->rx_msg_type_follow_up++; + else if (message_type == RDES_EXT_DELAY_REQ) + x->rx_msg_type_delay_req++; + else if (message_type == RDES_EXT_DELAY_RESP) + x->rx_msg_type_delay_resp++; + else if (message_type == RDES_EXT_PDELAY_REQ) + x->rx_msg_type_pdelay_req++; + else if (message_type == RDES_EXT_PDELAY_RESP) + x->rx_msg_type_pdelay_resp++; + else if (message_type == RDES_EXT_PDELAY_FOLLOW_UP) + x->rx_msg_type_pdelay_follow_up++; + else + x->rx_msg_type_ext_no_ptp++; + + if (rdes1 & RDES1_PTP_PACKET_TYPE) + x->ptp_frame_type++; + if (rdes1 & RDES1_PTP_VER) + x->ptp_ver++; + if (rdes1 & RDES1_TIMESTAMP_DROPPED) + x->timestamp_dropped++; + + if (unlikely(rdes2 & RDES2_SA_FILTER_FAIL)) { + x->sa_rx_filter_fail++; + ret = discard_frame; + } + if (unlikely(rdes2 & RDES2_DA_FILTER_FAIL)) { + x->da_rx_filter_fail++; + ret = discard_frame; + } + + if (rdes2 & RDES2_L3_FILTER_MATCH) + x->l3_filter_match++; + if (rdes2 & RDES2_L4_FILTER_MATCH) + x->l4_filter_match++; + if ((rdes2 & RDES2_L3_L4_FILT_NB_MATCH_MASK) + >> RDES2_L3_L4_FILT_NB_MATCH_SHIFT) + x->l3_l4_filter_no_match++; + + return ret; +} + +static int dwmac4_rd_get_tx_len(struct dma_desc *p) +{ + return (p->des2 & TDES2_BUFFER1_SIZE_MASK); +} + +static int dwmac4_get_tx_owner(struct dma_desc *p) +{ + return (p->des3 & TDES3_OWN) >> TDES3_OWN_SHIFT; +} + +static void dwmac4_set_tx_owner(struct dma_desc *p) +{ + p->des3 |= TDES3_OWN; +} + +static void dwmac4_set_rx_owner(struct dma_desc *p) +{ + p->des3 |= RDES3_OWN; +} + +static int dwmac4_get_tx_ls(struct dma_desc *p) +{ + return (p->des3 & TDES3_LAST_DESCRIPTOR) >> TDES3_LAST_DESCRIPTOR_SHIFT; +} + +static int dwmac4_wrback_get_rx_frame_len(struct dma_desc *p, int rx_coe) +{ + return (p->des3 & RDES3_PACKET_SIZE_MASK); +} + +static void dwmac4_rd_enable_tx_timestamp(struct dma_desc *p) +{ + p->des2 |= TDES2_TIMESTAMP_ENABLE; +} + +static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p) +{ + return (p->des3 & TDES3_TIMESTAMP_STATUS) + >> TDES3_TIMESTAMP_STATUS_SHIFT; +} + +/* NOTE: For RX CTX bit has to be checked before + * HAVE a specific function for TX and another one for RX + */ +static u64 dwmac4_wrback_get_timestamp(void *desc, u32 ats) +{ + struct dma_desc *p = (struct dma_desc *)desc; + u64 ns; + + ns = p->des0; + /* convert high/sec time stamp value to nanosecond */ + ns += p->des1 * 1000000000ULL; + + return ns; +} + +static int dwmac4_context_get_rx_timestamp_status(void *desc, u32 ats) +{ + struct dma_desc *p = (struct dma_desc *)desc; + + return (p->des1 & RDES1_TIMESTAMP_AVAILABLE) + >> RDES1_TIMESTAMP_AVAILABLE_SHIFT; +} + +static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, + int mode, int end) +{ + p->des3 = RDES3_OWN | RDES3_BUFFER1_VALID_ADDR; + + if (!disable_rx_ic) + p->des3 |= RDES3_INT_ON_COMPLETION_EN; +} + +static void dwmac4_rd_init_tx_desc(struct dma_desc *p, int mode, int end) +{ + p->des0 = 0; + p->des1 = 0; + p->des2 = 0; + p->des3 = 0; +} + +static void dwmac4_rd_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, + bool csum_flag, int mode, bool tx_own, + bool ls) +{ + unsigned int tdes3 = p->des3; + + if (unlikely(len > BUF_SIZE_16KiB)) { + p->des2 |= (((len - BUF_SIZE_16KiB) << + TDES2_BUFFER2_SIZE_MASK_SHIFT) + & TDES2_BUFFER2_SIZE_MASK) + | (BUF_SIZE_16KiB & TDES2_BUFFER1_SIZE_MASK); + } else { + p->des2 |= (len & TDES2_BUFFER1_SIZE_MASK); + } + + if (is_fs) + tdes3 |= TDES3_FIRST_DESCRIPTOR; + else + tdes3 &= ~TDES3_FIRST_DESCRIPTOR; + + if (likely(csum_flag)) + tdes3 |= (TX_CIC_FULL << TDES3_CHECKSUM_INSERTION_SHIFT); + else + tdes3 &= ~(TX_CIC_FULL << TDES3_CHECKSUM_INSERTION_SHIFT); + + if (ls) + tdes3 |= TDES3_LAST_DESCRIPTOR; + else + tdes3 &= ~TDES3_LAST_DESCRIPTOR; + + /* Finally set the OWN bit. Later the DMA will start! */ + if (tx_own) + tdes3 |= TDES3_OWN; + + if (is_fs & tx_own) + /* When the own bit, for the first frame, has to be set, all + * descriptors for the same frame has to be set before, to + * avoid race condition. + */ + wmb(); + + p->des3 = tdes3; +} + +static void dwmac4_rd_prepare_tso_tx_desc(struct dma_desc *p, int is_fs, + int len1, int len2, bool tx_own, + bool ls, unsigned int tcphdrlen, + unsigned int tcppayloadlen) +{ + unsigned int tdes3 = p->des3; + + if (len1) + p->des2 |= (len1 & TDES2_BUFFER1_SIZE_MASK); + + if (len2) + p->des2 |= (len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT) + & TDES2_BUFFER2_SIZE_MASK; + + if (is_fs) { + tdes3 |= TDES3_FIRST_DESCRIPTOR | + TDES3_TCP_SEGMENTATION_ENABLE | + ((tcphdrlen << TDES3_HDR_LEN_SHIFT) & + TDES3_SLOT_NUMBER_MASK) | + ((tcppayloadlen & TDES3_TCP_PKT_PAYLOAD_MASK)); + } else { + tdes3 &= ~TDES3_FIRST_DESCRIPTOR; + } + + if (ls) + tdes3 |= TDES3_LAST_DESCRIPTOR; + else + tdes3 &= ~TDES3_LAST_DESCRIPTOR; + + /* Finally set the OWN bit. Later the DMA will start! */ + if (tx_own) + tdes3 |= TDES3_OWN; + + if (is_fs & tx_own) + /* When the own bit, for the first frame, has to be set, all + * descriptors for the same frame has to be set before, to + * avoid race condition. + */ + wmb(); + + p->des3 = tdes3; +} + +static void dwmac4_release_tx_desc(struct dma_desc *p, int mode) +{ + p->des2 = 0; + p->des3 = 0; +} + +static void dwmac4_rd_set_tx_ic(struct dma_desc *p) +{ + p->des2 |= TDES2_INTERRUPT_ON_COMPLETION; +} + +static void dwmac4_display_ring(void *head, unsigned int size, bool rx) +{ + struct dma_desc *p = (struct dma_desc *)head; + int i; + + pr_info("%s descriptor ring:\n", rx ? "RX" : "TX"); + + for (i = 0; i < size; i++) { + if (p->des0) + pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", + i, (unsigned int)virt_to_phys(p), + p->des0, p->des1, p->des2, p->des3); + p++; + } +} + +static void dwmac4_set_mss_ctxt(struct dma_desc *p, unsigned int mss) +{ + p->des0 = 0; + p->des1 = 0; + p->des2 = mss; + p->des3 = TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV; +} + +const struct stmmac_desc_ops dwmac4_desc_ops = { + .tx_status = dwmac4_wrback_get_tx_status, + .rx_status = dwmac4_wrback_get_rx_status, + .get_tx_len = dwmac4_rd_get_tx_len, + .get_tx_owner = dwmac4_get_tx_owner, + .set_tx_owner = dwmac4_set_tx_owner, + .set_rx_owner = dwmac4_set_rx_owner, + .get_tx_ls = dwmac4_get_tx_ls, + .get_rx_frame_len = dwmac4_wrback_get_rx_frame_len, + .enable_tx_timestamp = dwmac4_rd_enable_tx_timestamp, + .get_tx_timestamp_status = dwmac4_wrback_get_tx_timestamp_status, + .get_timestamp = dwmac4_wrback_get_timestamp, + .get_rx_timestamp_status = dwmac4_context_get_rx_timestamp_status, + .set_tx_ic = dwmac4_rd_set_tx_ic, + .prepare_tx_desc = dwmac4_rd_prepare_tx_desc, + .prepare_tso_tx_desc = dwmac4_rd_prepare_tso_tx_desc, + .release_tx_desc = dwmac4_release_tx_desc, + .init_rx_desc = dwmac4_rd_init_rx_desc, + .init_tx_desc = dwmac4_rd_init_tx_desc, + .display_ring = dwmac4_display_ring, + .set_mss = dwmac4_set_mss_ctxt, +}; + +const struct stmmac_mode_ops dwmac4_ring_mode_ops = { }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h new file mode 100644 index 000000000000..0902a2edeaa9 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h @@ -0,0 +1,129 @@ +/* + * Header File to describe the DMA descriptors and related definitions specific + * for DesignWare databook 4.xx. + * + * Copyright (C) 2015 STMicroelectronics Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Author: Alexandre Torgue + */ + +#ifndef __DWMAC4_DESCS_H__ +#define __DWMAC4_DESCS_H__ + +#include + +/* Normal transmit descriptor defines (without split feature) */ + +/* TDES2 (read format) */ +#define TDES2_BUFFER1_SIZE_MASK GENMASK(13, 0) +#define TDES2_VLAN_TAG_MASK GENMASK(15, 14) +#define TDES2_BUFFER2_SIZE_MASK GENMASK(29, 16) +#define TDES2_BUFFER2_SIZE_MASK_SHIFT 16 +#define TDES2_TIMESTAMP_ENABLE BIT(30) +#define TDES2_INTERRUPT_ON_COMPLETION BIT(31) + +/* TDES3 (read format) */ +#define TDES3_PACKET_SIZE_MASK GENMASK(14, 0) +#define TDES3_CHECKSUM_INSERTION_MASK GENMASK(17, 16) +#define TDES3_CHECKSUM_INSERTION_SHIFT 16 +#define TDES3_TCP_PKT_PAYLOAD_MASK GENMASK(17, 0) +#define TDES3_TCP_SEGMENTATION_ENABLE BIT(18) +#define TDES3_HDR_LEN_SHIFT 19 +#define TDES3_SLOT_NUMBER_MASK GENMASK(22, 19) +#define TDES3_SA_INSERT_CTRL_MASK GENMASK(25, 23) +#define TDES3_CRC_PAD_CTRL_MASK GENMASK(27, 26) + +/* TDES3 (write back format) */ +#define TDES3_IP_HDR_ERROR BIT(0) +#define TDES3_DEFERRED BIT(1) +#define TDES3_UNDERFLOW_ERROR BIT(2) +#define TDES3_EXCESSIVE_DEFERRAL BIT(3) +#define TDES3_COLLISION_COUNT_MASK GENMASK(7, 4) +#define TDES3_COLLISION_COUNT_SHIFT 4 +#define TDES3_EXCESSIVE_COLLISION BIT(8) +#define TDES3_LATE_COLLISION BIT(9) +#define TDES3_NO_CARRIER BIT(10) +#define TDES3_LOSS_CARRIER BIT(11) +#define TDES3_PAYLOAD_ERROR BIT(12) +#define TDES3_PACKET_FLUSHED BIT(13) +#define TDES3_JABBER_TIMEOUT BIT(14) +#define TDES3_ERROR_SUMMARY BIT(15) +#define TDES3_TIMESTAMP_STATUS BIT(17) +#define TDES3_TIMESTAMP_STATUS_SHIFT 17 + +/* TDES3 context */ +#define TDES3_CTXT_TCMSSV BIT(26) + +/* TDES3 Common */ +#define TDES3_LAST_DESCRIPTOR BIT(28) +#define TDES3_LAST_DESCRIPTOR_SHIFT 28 +#define TDES3_FIRST_DESCRIPTOR BIT(29) +#define TDES3_CONTEXT_TYPE BIT(30) + +/* TDS3 use for both format (read and write back) */ +#define TDES3_OWN BIT(31) +#define TDES3_OWN_SHIFT 31 + +/* Normal receive descriptor defines (without split feature) */ + +/* RDES0 (write back format) */ +#define RDES0_VLAN_TAG_MASK GENMASK(15, 0) + +/* RDES1 (write back format) */ +#define RDES1_IP_PAYLOAD_TYPE_MASK GENMASK(2, 0) +#define RDES1_IP_HDR_ERROR BIT(3) +#define RDES1_IPV4_HEADER BIT(4) +#define RDES1_IPV6_HEADER BIT(5) +#define RDES1_IP_CSUM_BYPASSED BIT(6) +#define RDES1_IP_CSUM_ERROR BIT(7) +#define RDES1_PTP_MSG_TYPE_MASK GENMASK(11, 8) +#define RDES1_PTP_PACKET_TYPE BIT(12) +#define RDES1_PTP_VER BIT(13) +#define RDES1_TIMESTAMP_AVAILABLE BIT(14) +#define RDES1_TIMESTAMP_AVAILABLE_SHIFT 14 +#define RDES1_TIMESTAMP_DROPPED BIT(15) +#define RDES1_IP_TYPE1_CSUM_MASK GENMASK(31, 16) + +/* RDES2 (write back format) */ +#define RDES2_L3_L4_HEADER_SIZE_MASK GENMASK(9, 0) +#define RDES2_VLAN_FILTER_STATUS BIT(15) +#define RDES2_SA_FILTER_FAIL BIT(16) +#define RDES2_DA_FILTER_FAIL BIT(17) +#define RDES2_HASH_FILTER_STATUS BIT(18) +#define RDES2_MAC_ADDR_MATCH_MASK GENMASK(26, 19) +#define RDES2_HASH_VALUE_MATCH_MASK GENMASK(26, 19) +#define RDES2_L3_FILTER_MATCH BIT(27) +#define RDES2_L4_FILTER_MATCH BIT(28) +#define RDES2_L3_L4_FILT_NB_MATCH_MASK GENMASK(27, 26) +#define RDES2_L3_L4_FILT_NB_MATCH_SHIFT 26 + +/* RDES3 (write back format) */ +#define RDES3_PACKET_SIZE_MASK GENMASK(14, 0) +#define RDES3_ERROR_SUMMARY BIT(15) +#define RDES3_PACKET_LEN_TYPE_MASK GENMASK(18, 16) +#define RDES3_DRIBBLE_ERROR BIT(19) +#define RDES3_RECEIVE_ERROR BIT(20) +#define RDES3_OVERFLOW_ERROR BIT(21) +#define RDES3_RECEIVE_WATCHDOG BIT(22) +#define RDES3_GIANT_PACKET BIT(23) +#define RDES3_CRC_ERROR BIT(24) +#define RDES3_RDES0_VALID BIT(25) +#define RDES3_RDES1_VALID BIT(26) +#define RDES3_RDES2_VALID BIT(27) +#define RDES3_LAST_DESCRIPTOR BIT(28) +#define RDES3_FIRST_DESCRIPTOR BIT(29) +#define RDES3_CONTEXT_DESCRIPTOR BIT(30) + +/* RDES3 (read format) */ +#define RDES3_BUFFER1_VALID_ADDR BIT(24) +#define RDES3_BUFFER2_VALID_ADDR BIT(25) +#define RDES3_INT_ON_COMPLETION_EN BIT(30) + +/* TDS3 use for both format (read and write back) */ +#define RDES3_OWN BIT(31) + +#endif /* __DWMAC4_DESCS_H__ */ -- GitLab From 35f74c0c5dce138bd9000d98abf4959af782a96d Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:29 +0200 Subject: [PATCH 1116/9938] stmmac: add GMAC4 DMA/CORE Header File This is the main header file to define all the macro used for GMAC4 DMA and CORE parts. Signed-off-by: Alexandre TORGUE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 224 +++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac4.h diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h new file mode 100644 index 000000000000..c12f15c9b351 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h @@ -0,0 +1,224 @@ +/* + * DWMAC4 Header file. + * + * Copyright (C) 2015 STMicroelectronics Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Author: Alexandre Torgue + */ + +#ifndef __DWMAC4_H__ +#define __DWMAC4_H__ + +#include "common.h" + +/* MAC registers */ +#define GMAC_CONFIG 0x00000000 +#define GMAC_PACKET_FILTER 0x00000008 +#define GMAC_HASH_TAB_0_31 0x00000010 +#define GMAC_HASH_TAB_32_63 0x00000014 +#define GMAC_RX_FLOW_CTRL 0x00000090 +#define GMAC_QX_TX_FLOW_CTRL(x) (0x70 + x * 4) +#define GMAC_INT_STATUS 0x000000b0 +#define GMAC_INT_EN 0x000000b4 +#define GMAC_AN_CTRL 0x000000e0 +#define GMAC_AN_STATUS 0x000000e4 +#define GMAC_AN_ADV 0x000000e8 +#define GMAC_AN_LPA 0x000000ec +#define GMAC_PMT 0x000000c0 +#define GMAC_VERSION 0x00000110 +#define GMAC_DEBUG 0x00000114 +#define GMAC_HW_FEATURE0 0x0000011c +#define GMAC_HW_FEATURE1 0x00000120 +#define GMAC_HW_FEATURE2 0x00000124 +#define GMAC_MDIO_ADDR 0x00000200 +#define GMAC_MDIO_DATA 0x00000204 +#define GMAC_ADDR_HIGH(reg) (0x300 + reg * 8) +#define GMAC_ADDR_LOW(reg) (0x304 + reg * 8) + +/* MAC Packet Filtering */ +#define GMAC_PACKET_FILTER_PR BIT(0) +#define GMAC_PACKET_FILTER_HMC BIT(2) +#define GMAC_PACKET_FILTER_PM BIT(4) + +#define GMAC_MAX_PERFECT_ADDRESSES 128 + +/* MAC Flow Control RX */ +#define GMAC_RX_FLOW_CTRL_RFE BIT(0) + +/* MAC Flow Control TX */ +#define GMAC_TX_FLOW_CTRL_TFE BIT(1) +#define GMAC_TX_FLOW_CTRL_PT_SHIFT 16 + +/* MAC Interrupt bitmap*/ +#define GMAC_INT_PMT_EN BIT(4) +#define GMAC_INT_LPI_EN BIT(5) + +enum dwmac4_irq_status { + time_stamp_irq = 0x00001000, + mmc_rx_csum_offload_irq = 0x00000800, + mmc_tx_irq = 0x00000400, + mmc_rx_irq = 0x00000200, + mmc_irq = 0x00000100, + pmt_irq = 0x00000010, + pcs_ane_irq = 0x00000004, + pcs_link_irq = 0x00000002, +}; + +/* MAC Auto-Neg bitmap*/ +#define GMAC_AN_CTRL_RAN BIT(9) +#define GMAC_AN_CTRL_ANE BIT(12) +#define GMAC_AN_CTRL_ELE BIT(14) +#define GMAC_AN_FD BIT(5) +#define GMAC_AN_HD BIT(6) +#define GMAC_AN_PSE_MASK GENMASK(8, 7) +#define GMAC_AN_PSE_SHIFT 7 + +/* MAC PMT bitmap */ +enum power_event { + pointer_reset = 0x80000000, + global_unicast = 0x00000200, + wake_up_rx_frame = 0x00000040, + magic_frame = 0x00000020, + wake_up_frame_en = 0x00000004, + magic_pkt_en = 0x00000002, + power_down = 0x00000001, +}; + +/* MAC Debug bitmap */ +#define GMAC_DEBUG_TFCSTS_MASK GENMASK(18, 17) +#define GMAC_DEBUG_TFCSTS_SHIFT 17 +#define GMAC_DEBUG_TFCSTS_IDLE 0 +#define GMAC_DEBUG_TFCSTS_WAIT 1 +#define GMAC_DEBUG_TFCSTS_GEN_PAUSE 2 +#define GMAC_DEBUG_TFCSTS_XFER 3 +#define GMAC_DEBUG_TPESTS BIT(16) +#define GMAC_DEBUG_RFCFCSTS_MASK GENMASK(2, 1) +#define GMAC_DEBUG_RFCFCSTS_SHIFT 1 +#define GMAC_DEBUG_RPESTS BIT(0) + +/* MAC config */ +#define GMAC_CONFIG_IPC BIT(27) +#define GMAC_CONFIG_2K BIT(22) +#define GMAC_CONFIG_ACS BIT(20) +#define GMAC_CONFIG_BE BIT(18) +#define GMAC_CONFIG_JD BIT(17) +#define GMAC_CONFIG_JE BIT(16) +#define GMAC_CONFIG_PS BIT(15) +#define GMAC_CONFIG_FES BIT(14) +#define GMAC_CONFIG_DM BIT(13) +#define GMAC_CONFIG_DCRS BIT(9) +#define GMAC_CONFIG_TE BIT(1) +#define GMAC_CONFIG_RE BIT(0) + +/* MAC HW features0 bitmap */ +#define GMAC_HW_FEAT_ADDMAC BIT(18) +#define GMAC_HW_FEAT_RXCOESEL BIT(16) +#define GMAC_HW_FEAT_TXCOSEL BIT(14) +#define GMAC_HW_FEAT_EEESEL BIT(13) +#define GMAC_HW_FEAT_TSSEL BIT(12) +#define GMAC_HW_FEAT_MMCSEL BIT(8) +#define GMAC_HW_FEAT_MGKSEL BIT(7) +#define GMAC_HW_FEAT_RWKSEL BIT(6) +#define GMAC_HW_FEAT_SMASEL BIT(5) +#define GMAC_HW_FEAT_VLHASH BIT(4) +#define GMAC_HW_FEAT_PCSSEL BIT(3) +#define GMAC_HW_FEAT_HDSEL BIT(2) +#define GMAC_HW_FEAT_GMIISEL BIT(1) +#define GMAC_HW_FEAT_MIISEL BIT(0) + +/* MAC HW features1 bitmap */ +#define GMAC_HW_FEAT_AVSEL BIT(20) +#define GMAC_HW_TSOEN BIT(18) + +/* MAC HW features2 bitmap */ +#define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18) +#define GMAC_HW_FEAT_RXCHCNT GENMASK(15, 12) + +/* MAC HW ADDR regs */ +#define GMAC_HI_DCS GENMASK(18, 16) +#define GMAC_HI_DCS_SHIFT 16 +#define GMAC_HI_REG_AE BIT(31) + +/* MTL registers */ +#define MTL_INT_STATUS 0x00000c20 +#define MTL_INT_Q0 BIT(0) + +#define MTL_CHAN_BASE_ADDR 0x00000d00 +#define MTL_CHAN_BASE_OFFSET 0x40 +#define MTL_CHANX_BASE_ADDR(x) (MTL_CHAN_BASE_ADDR + \ + (x * MTL_CHAN_BASE_OFFSET)) + +#define MTL_CHAN_TX_OP_MODE(x) MTL_CHANX_BASE_ADDR(x) +#define MTL_CHAN_TX_DEBUG(x) (MTL_CHANX_BASE_ADDR(x) + 0x8) +#define MTL_CHAN_INT_CTRL(x) (MTL_CHANX_BASE_ADDR(x) + 0x2c) +#define MTL_CHAN_RX_OP_MODE(x) (MTL_CHANX_BASE_ADDR(x) + 0x30) +#define MTL_CHAN_RX_DEBUG(x) (MTL_CHANX_BASE_ADDR(x) + 0x38) + +#define MTL_OP_MODE_RSF BIT(5) +#define MTL_OP_MODE_TSF BIT(1) + +#define MTL_OP_MODE_TTC_MASK 0x70 +#define MTL_OP_MODE_TTC_SHIFT 4 + +#define MTL_OP_MODE_TTC_32 0 +#define MTL_OP_MODE_TTC_64 (1 << MTL_OP_MODE_TTC_SHIFT) +#define MTL_OP_MODE_TTC_96 (2 << MTL_OP_MODE_TTC_SHIFT) +#define MTL_OP_MODE_TTC_128 (3 << MTL_OP_MODE_TTC_SHIFT) +#define MTL_OP_MODE_TTC_192 (4 << MTL_OP_MODE_TTC_SHIFT) +#define MTL_OP_MODE_TTC_256 (5 << MTL_OP_MODE_TTC_SHIFT) +#define MTL_OP_MODE_TTC_384 (6 << MTL_OP_MODE_TTC_SHIFT) +#define MTL_OP_MODE_TTC_512 (7 << MTL_OP_MODE_TTC_SHIFT) + +#define MTL_OP_MODE_RTC_MASK 0x18 +#define MTL_OP_MODE_RTC_SHIFT 3 + +#define MTL_OP_MODE_RTC_32 (1 << MTL_OP_MODE_RTC_SHIFT) +#define MTL_OP_MODE_RTC_64 0 +#define MTL_OP_MODE_RTC_96 (2 << MTL_OP_MODE_RTC_SHIFT) +#define MTL_OP_MODE_RTC_128 (3 << MTL_OP_MODE_RTC_SHIFT) + +/* MTL debug */ +#define MTL_DEBUG_TXSTSFSTS BIT(5) +#define MTL_DEBUG_TXFSTS BIT(4) +#define MTL_DEBUG_TWCSTS BIT(3) + +/* MTL debug: Tx FIFO Read Controller Status */ +#define MTL_DEBUG_TRCSTS_MASK GENMASK(2, 1) +#define MTL_DEBUG_TRCSTS_SHIFT 1 +#define MTL_DEBUG_TRCSTS_IDLE 0 +#define MTL_DEBUG_TRCSTS_READ 1 +#define MTL_DEBUG_TRCSTS_TXW 2 +#define MTL_DEBUG_TRCSTS_WRITE 3 +#define MTL_DEBUG_TXPAUSED BIT(0) + +/* MAC debug: GMII or MII Transmit Protocol Engine Status */ +#define MTL_DEBUG_RXFSTS_MASK GENMASK(5, 4) +#define MTL_DEBUG_RXFSTS_SHIFT 4 +#define MTL_DEBUG_RXFSTS_EMPTY 0 +#define MTL_DEBUG_RXFSTS_BT 1 +#define MTL_DEBUG_RXFSTS_AT 2 +#define MTL_DEBUG_RXFSTS_FULL 3 +#define MTL_DEBUG_RRCSTS_MASK GENMASK(2, 1) +#define MTL_DEBUG_RRCSTS_SHIFT 1 +#define MTL_DEBUG_RRCSTS_IDLE 0 +#define MTL_DEBUG_RRCSTS_RDATA 1 +#define MTL_DEBUG_RRCSTS_RSTAT 2 +#define MTL_DEBUG_RRCSTS_FLUSH 3 +#define MTL_DEBUG_RWCSTS BIT(0) + +/* MTL interrupt */ +#define MTL_RX_OVERFLOW_INT_EN BIT(24) +#define MTL_RX_OVERFLOW_INT BIT(16) + +/* Default operating mode of the MAC */ +#define GMAC_CORE_INIT (GMAC_CONFIG_JD | GMAC_CONFIG_PS | GMAC_CONFIG_ACS | \ + GMAC_CONFIG_BE | GMAC_CONFIG_DCRS) + +/* To dump the core regs excluding the Address Registers */ +#define GMAC_REG_NUM 132 + +#endif /* __DWMAC4_H__ */ -- GitLab From 48863ce5940fa5420096c8beba44e5e1bc0c8ca1 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:30 +0200 Subject: [PATCH 1117/9938] stmmac: add DMA support for GMAC 4.xx DMA behavior is linked to descriptor management: -descriptor mechanism (Tx for example, but it is exactly the same for RX): -useful registers: -DMA_CH#_TxDesc_Ring_Len: length of transmit descriptor ring -DMA_CH#_TxDesc_List_Address: start address of the ring -DMA_CH#_TxDesc_Tail_Pointer: address of the last descriptor to send + 1. -DMA_CH#_TxDesc_Current_App_TxDesc: address of the current descriptor -The descriptor Tail Pointer register contains the pointer to the descriptor address (N). The base address and the current descriptor decide the address of the current descriptor that the DMA can process. The descriptors up to one location less than the one indicated by the descriptor tail pointer (N-1) are owned by the DMA. The DMA continues to process the descriptors until the following condition occurs: "current descriptor pointer == Descriptor Tail pointer" Then the DMA goes into suspend mode. The application must perform a write to descriptor tail pointer register and update the tail pointer to have the following condition and to start a new transfer: "current descriptor pointer < Descriptor tail pointer" The DMA automatically wraps around the base address when the end of ring is reached. Up to 8 DMA could be use but currently we only use one (channel0) Signed-off-by: Alexandre TORGUE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/common.h | 11 + .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 354 ++++++++++++++++++ .../net/ethernet/stmicro/stmmac/dwmac4_dma.h | 202 ++++++++++ .../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 225 +++++++++++ 5 files changed, 793 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index fa000fd36efc..9398acef0125 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -3,7 +3,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ - $(stmmac-y) + dwmac4_dma.o dwmac4_lib.o $(stmmac-y) # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index ea7eb0d5ce98..2a5126e3d3df 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -41,6 +41,8 @@ /* Synopsys Core versions */ #define DWMAC_CORE_3_40 0x34 #define DWMAC_CORE_3_50 0x35 +#define DWMAC_CORE_4_00 0x40 +#define STMMAC_CHAN0 0 /* Always supported and default for all chips */ #define DMA_TX_SIZE 512 #define DMA_RX_SIZE 512 @@ -270,6 +272,7 @@ enum dma_irq_status { #define CORE_PCS_ANE_COMPLETE (1 << 5) #define CORE_PCS_LINK_STATUS (1 << 6) #define CORE_RGMII_IRQ (1 << 7) +#define CORE_IRQ_MTL_RX_OVERFLOW BIT(8) /* Physical Coding Sublayer */ struct rgmii_adv { @@ -301,8 +304,10 @@ struct dma_features { /* 802.3az - Energy-Efficient Ethernet (EEE) */ unsigned int eee; unsigned int av; + unsigned int tsoen; /* TX and RX csum */ unsigned int tx_coe; + unsigned int rx_coe; unsigned int rx_coe_type1; unsigned int rx_coe_type2; unsigned int rxfifo_over_2048; @@ -425,6 +430,11 @@ struct stmmac_dma_ops { struct dma_features *dma_cap); /* Program the HW RX Watchdog */ void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt); + void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len); + void (*set_rx_ring_len)(void __iomem *ioaddr, u32 len); + void (*set_rx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan); + void (*set_tx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan); + void (*enable_tso)(void __iomem *ioaddr, bool en, u32 chan); }; struct mac_device_info; @@ -473,6 +483,7 @@ struct stmmac_hwtimestamp { }; extern const struct stmmac_hwtimestamp stmmac_ptp; +extern const struct stmmac_mode_ops dwmac4_ring_mode_ops; struct mac_link { int port; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c new file mode 100644 index 000000000000..116151cd6a95 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -0,0 +1,354 @@ +/* + * This is the driver for the GMAC on-chip Ethernet controller for ST SoCs. + * DWC Ether MAC version 4.xx has been used for developing this code. + * + * This contains the functions to handle the dma. + * + * Copyright (C) 2015 STMicroelectronics Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Author: Alexandre Torgue + */ + +#include +#include "dwmac4.h" +#include "dwmac4_dma.h" + +static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) +{ + u32 value = readl(ioaddr + DMA_SYS_BUS_MODE); + int i; + + pr_info("dwmac4: Master AXI performs %s burst length\n", + (value & DMA_SYS_BUS_FB) ? "fixed" : "any"); + + if (axi->axi_lpi_en) + value |= DMA_AXI_EN_LPI; + if (axi->axi_xit_frm) + value |= DMA_AXI_LPI_XIT_FRM; + + value |= (axi->axi_wr_osr_lmt & DMA_AXI_OSR_MAX) << + DMA_AXI_WR_OSR_LMT_SHIFT; + + value |= (axi->axi_rd_osr_lmt & DMA_AXI_OSR_MAX) << + DMA_AXI_RD_OSR_LMT_SHIFT; + + /* Depending on the UNDEF bit the Master AXI will perform any burst + * length according to the BLEN programmed (by default all BLEN are + * set). + */ + for (i = 0; i < AXI_BLEN; i++) { + switch (axi->axi_blen[i]) { + case 256: + value |= DMA_AXI_BLEN256; + break; + case 128: + value |= DMA_AXI_BLEN128; + break; + case 64: + value |= DMA_AXI_BLEN64; + break; + case 32: + value |= DMA_AXI_BLEN32; + break; + case 16: + value |= DMA_AXI_BLEN16; + break; + case 8: + value |= DMA_AXI_BLEN8; + break; + case 4: + value |= DMA_AXI_BLEN4; + break; + } + } + + writel(value, ioaddr + DMA_SYS_BUS_MODE); +} + +static void dwmac4_dma_init_channel(void __iomem *ioaddr, int pbl, + u32 dma_tx_phy, u32 dma_rx_phy, + u32 channel) +{ + u32 value; + + /* set PBL for each channels. Currently we affect same configuration + * on each channel + */ + value = readl(ioaddr + DMA_CHAN_CONTROL(channel)); + value = value | DMA_BUS_MODE_PBL; + writel(value, ioaddr + DMA_CHAN_CONTROL(channel)); + + value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel)); + value = value | (pbl << DMA_BUS_MODE_PBL_SHIFT); + writel(value, ioaddr + DMA_CHAN_TX_CONTROL(channel)); + + value = readl(ioaddr + DMA_CHAN_RX_CONTROL(channel)); + value = value | (pbl << DMA_BUS_MODE_RPBL_SHIFT); + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(channel)); + + /* Mask interrupts by writing to CSR7 */ + writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(channel)); + + writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(channel)); + writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(channel)); +} + +static void dwmac4_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, + int aal, u32 dma_tx, u32 dma_rx, int atds) +{ + u32 value = readl(ioaddr + DMA_SYS_BUS_MODE); + int i; + + /* Set the Fixed burst mode */ + if (fb) + value |= DMA_SYS_BUS_FB; + + /* Mixed Burst has no effect when fb is set */ + if (mb) + value |= DMA_SYS_BUS_MB; + + if (aal) + value |= DMA_SYS_BUS_AAL; + + writel(value, ioaddr + DMA_SYS_BUS_MODE); + + for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) + dwmac4_dma_init_channel(ioaddr, pbl, dma_tx, dma_rx, i); +} + +static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel) +{ + pr_debug(" Channel %d\n", channel); + pr_debug("\tDMA_CHAN_CONTROL, offset: 0x%x, val: 0x%x\n", 0, + readl(ioaddr + DMA_CHAN_CONTROL(channel))); + pr_debug("\tDMA_CHAN_TX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x4, + readl(ioaddr + DMA_CHAN_TX_CONTROL(channel))); + pr_debug("\tDMA_CHAN_RX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x8, + readl(ioaddr + DMA_CHAN_RX_CONTROL(channel))); + pr_debug("\tDMA_CHAN_TX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x14, + readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(channel))); + pr_debug("\tDMA_CHAN_RX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x1c, + readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(channel))); + pr_debug("\tDMA_CHAN_TX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x20, + readl(ioaddr + DMA_CHAN_TX_END_ADDR(channel))); + pr_debug("\tDMA_CHAN_RX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x28, + readl(ioaddr + DMA_CHAN_RX_END_ADDR(channel))); + pr_debug("\tDMA_CHAN_TX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x2c, + readl(ioaddr + DMA_CHAN_TX_RING_LEN(channel))); + pr_debug("\tDMA_CHAN_RX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x30, + readl(ioaddr + DMA_CHAN_RX_RING_LEN(channel))); + pr_debug("\tDMA_CHAN_INTR_ENA, offset: 0x%x, val: 0x%x\n", 0x34, + readl(ioaddr + DMA_CHAN_INTR_ENA(channel))); + pr_debug("\tDMA_CHAN_RX_WATCHDOG, offset: 0x%x, val: 0x%x\n", 0x38, + readl(ioaddr + DMA_CHAN_RX_WATCHDOG(channel))); + pr_debug("\tDMA_CHAN_SLOT_CTRL_STATUS, offset: 0x%x, val: 0x%x\n", 0x3c, + readl(ioaddr + DMA_CHAN_SLOT_CTRL_STATUS(channel))); + pr_debug("\tDMA_CHAN_CUR_TX_DESC, offset: 0x%x, val: 0x%x\n", 0x44, + readl(ioaddr + DMA_CHAN_CUR_TX_DESC(channel))); + pr_debug("\tDMA_CHAN_CUR_RX_DESC, offset: 0x%x, val: 0x%x\n", 0x4c, + readl(ioaddr + DMA_CHAN_CUR_RX_DESC(channel))); + pr_debug("\tDMA_CHAN_CUR_TX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x54, + readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(channel))); + pr_debug("\tDMA_CHAN_CUR_RX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x5c, + readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(channel))); + pr_debug("\tDMA_CHAN_STATUS, offset: 0x%x, val: 0x%x\n", 0x60, + readl(ioaddr + DMA_CHAN_STATUS(channel))); +} + +static void dwmac4_dump_dma_regs(void __iomem *ioaddr) +{ + int i; + + pr_debug(" GMAC4 DMA registers\n"); + + for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) + _dwmac4_dump_dma_regs(ioaddr, i); +} + +static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt) +{ + int i; + + for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) + writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(i)); +} + +static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, + int rxmode, u32 channel) +{ + u32 mtl_tx_op, mtl_rx_op, mtl_rx_int; + + /* Following code only done for channel 0, other channels not yet + * supported. + */ + mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel)); + + if (txmode == SF_DMA_MODE) { + pr_debug("GMAC: enable TX store and forward mode\n"); + /* Transmit COE type 2 cannot be done in cut-through mode. */ + mtl_tx_op |= MTL_OP_MODE_TSF; + } else { + pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode); + mtl_tx_op &= ~MTL_OP_MODE_TSF; + mtl_tx_op &= MTL_OP_MODE_TTC_MASK; + /* Set the transmit threshold */ + if (txmode <= 32) + mtl_tx_op |= MTL_OP_MODE_TTC_32; + else if (txmode <= 64) + mtl_tx_op |= MTL_OP_MODE_TTC_64; + else if (txmode <= 96) + mtl_tx_op |= MTL_OP_MODE_TTC_96; + else if (txmode <= 128) + mtl_tx_op |= MTL_OP_MODE_TTC_128; + else if (txmode <= 192) + mtl_tx_op |= MTL_OP_MODE_TTC_192; + else if (txmode <= 256) + mtl_tx_op |= MTL_OP_MODE_TTC_256; + else if (txmode <= 384) + mtl_tx_op |= MTL_OP_MODE_TTC_384; + else + mtl_tx_op |= MTL_OP_MODE_TTC_512; + } + + writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel)); + + mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel)); + + if (rxmode == SF_DMA_MODE) { + pr_debug("GMAC: enable RX store and forward mode\n"); + mtl_rx_op |= MTL_OP_MODE_RSF; + } else { + pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode); + mtl_rx_op &= ~MTL_OP_MODE_RSF; + mtl_rx_op &= MTL_OP_MODE_RTC_MASK; + if (rxmode <= 32) + mtl_rx_op |= MTL_OP_MODE_RTC_32; + else if (rxmode <= 64) + mtl_rx_op |= MTL_OP_MODE_RTC_64; + else if (rxmode <= 96) + mtl_rx_op |= MTL_OP_MODE_RTC_96; + else + mtl_rx_op |= MTL_OP_MODE_RTC_128; + } + + writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel)); + + /* Enable MTL RX overflow */ + mtl_rx_int = readl(ioaddr + MTL_CHAN_INT_CTRL(channel)); + writel(mtl_rx_int | MTL_RX_OVERFLOW_INT_EN, + ioaddr + MTL_CHAN_INT_CTRL(channel)); +} + +static void dwmac4_dma_operation_mode(void __iomem *ioaddr, int txmode, + int rxmode, int rxfifosz) +{ + /* Only Channel 0 is actually configured and used */ + dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0); +} + +static void dwmac4_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) +{ + u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0); + + /* MAC HW feature0 */ + dma_cap->mbps_10_100 = (hw_cap & GMAC_HW_FEAT_MIISEL); + dma_cap->mbps_1000 = (hw_cap & GMAC_HW_FEAT_GMIISEL) >> 1; + dma_cap->half_duplex = (hw_cap & GMAC_HW_FEAT_HDSEL) >> 2; + dma_cap->hash_filter = (hw_cap & GMAC_HW_FEAT_VLHASH) >> 4; + dma_cap->multi_addr = (hw_cap & GMAC_HW_FEAT_ADDMAC) >> 18; + dma_cap->pcs = (hw_cap & GMAC_HW_FEAT_PCSSEL) >> 3; + dma_cap->sma_mdio = (hw_cap & GMAC_HW_FEAT_SMASEL) >> 5; + dma_cap->pmt_remote_wake_up = (hw_cap & GMAC_HW_FEAT_RWKSEL) >> 6; + dma_cap->pmt_magic_frame = (hw_cap & GMAC_HW_FEAT_MGKSEL) >> 7; + /* MMC */ + dma_cap->rmon = (hw_cap & GMAC_HW_FEAT_MMCSEL) >> 8; + /* IEEE 1588-2008 */ + dma_cap->atime_stamp = (hw_cap & GMAC_HW_FEAT_TSSEL) >> 12; + /* 802.3az - Energy-Efficient Ethernet (EEE) */ + dma_cap->eee = (hw_cap & GMAC_HW_FEAT_EEESEL) >> 13; + /* TX and RX csum */ + dma_cap->tx_coe = (hw_cap & GMAC_HW_FEAT_TXCOSEL) >> 14; + dma_cap->rx_coe = (hw_cap & GMAC_HW_FEAT_RXCOESEL) >> 16; + + /* MAC HW feature1 */ + hw_cap = readl(ioaddr + GMAC_HW_FEATURE1); + dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20; + dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18; + /* MAC HW feature2 */ + hw_cap = readl(ioaddr + GMAC_HW_FEATURE2); + /* TX and RX number of channels */ + dma_cap->number_rx_channel = + ((hw_cap & GMAC_HW_FEAT_RXCHCNT) >> 12) + 1; + dma_cap->number_tx_channel = + ((hw_cap & GMAC_HW_FEAT_TXCHCNT) >> 18) + 1; + + /* IEEE 1588-2002 */ + dma_cap->time_stamp = 0; +} + +/* Enable/disable TSO feature and set MSS */ +static void dwmac4_enable_tso(void __iomem *ioaddr, bool en, u32 chan) +{ + u32 value; + + if (en) { + /* enable TSO */ + value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); + writel(value | DMA_CONTROL_TSE, + ioaddr + DMA_CHAN_TX_CONTROL(chan)); + } else { + /* enable TSO */ + value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); + writel(value & ~DMA_CONTROL_TSE, + ioaddr + DMA_CHAN_TX_CONTROL(chan)); + } +} + +const struct stmmac_dma_ops dwmac4_dma_ops = { + .reset = dwmac4_dma_reset, + .init = dwmac4_dma_init, + .axi = dwmac4_dma_axi, + .dump_regs = dwmac4_dump_dma_regs, + .dma_mode = dwmac4_dma_operation_mode, + .enable_dma_irq = dwmac4_enable_dma_irq, + .disable_dma_irq = dwmac4_disable_dma_irq, + .start_tx = dwmac4_dma_start_tx, + .stop_tx = dwmac4_dma_stop_tx, + .start_rx = dwmac4_dma_start_rx, + .stop_rx = dwmac4_dma_stop_rx, + .dma_interrupt = dwmac4_dma_interrupt, + .get_hw_feature = dwmac4_get_hw_feature, + .rx_watchdog = dwmac4_rx_watchdog, + .set_rx_ring_len = dwmac4_set_rx_ring_len, + .set_tx_ring_len = dwmac4_set_tx_ring_len, + .set_rx_tail_ptr = dwmac4_set_rx_tail_ptr, + .set_tx_tail_ptr = dwmac4_set_tx_tail_ptr, + .enable_tso = dwmac4_enable_tso, +}; + +const struct stmmac_dma_ops dwmac410_dma_ops = { + .reset = dwmac4_dma_reset, + .init = dwmac4_dma_init, + .axi = dwmac4_dma_axi, + .dump_regs = dwmac4_dump_dma_regs, + .dma_mode = dwmac4_dma_operation_mode, + .enable_dma_irq = dwmac410_enable_dma_irq, + .disable_dma_irq = dwmac4_disable_dma_irq, + .start_tx = dwmac4_dma_start_tx, + .stop_tx = dwmac4_dma_stop_tx, + .start_rx = dwmac4_dma_start_rx, + .stop_rx = dwmac4_dma_stop_rx, + .dma_interrupt = dwmac4_dma_interrupt, + .get_hw_feature = dwmac4_get_hw_feature, + .rx_watchdog = dwmac4_rx_watchdog, + .set_rx_ring_len = dwmac4_set_rx_ring_len, + .set_tx_ring_len = dwmac4_set_tx_ring_len, + .set_rx_tail_ptr = dwmac4_set_rx_tail_ptr, + .set_tx_tail_ptr = dwmac4_set_tx_tail_ptr, + .enable_tso = dwmac4_enable_tso, +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h new file mode 100644 index 000000000000..1b06df749e2b --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -0,0 +1,202 @@ +/* + * DWMAC4 DMA Header file. + * + * + * Copyright (C) 2007-2015 STMicroelectronics Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Author: Alexandre Torgue + */ + +#ifndef __DWMAC4_DMA_H__ +#define __DWMAC4_DMA_H__ + +/* Define the max channel number used for tx (also rx). + * dwmac4 accepts up to 8 channels for TX (and also 8 channels for RX + */ +#define DMA_CHANNEL_NB_MAX 1 + +#define DMA_BUS_MODE 0x00001000 +#define DMA_SYS_BUS_MODE 0x00001004 +#define DMA_STATUS 0x00001008 +#define DMA_DEBUG_STATUS_0 0x0000100c +#define DMA_DEBUG_STATUS_1 0x00001010 +#define DMA_DEBUG_STATUS_2 0x00001014 +#define DMA_AXI_BUS_MODE 0x00001028 + +/* DMA Bus Mode bitmap */ +#define DMA_BUS_MODE_SFT_RESET BIT(0) + +/* DMA SYS Bus Mode bitmap */ +#define DMA_BUS_MODE_SPH BIT(24) +#define DMA_BUS_MODE_PBL BIT(16) +#define DMA_BUS_MODE_PBL_SHIFT 16 +#define DMA_BUS_MODE_RPBL_SHIFT 16 +#define DMA_BUS_MODE_MB BIT(14) +#define DMA_BUS_MODE_FB BIT(0) + +/* DMA Interrupt top status */ +#define DMA_STATUS_MAC BIT(17) +#define DMA_STATUS_MTL BIT(16) +#define DMA_STATUS_CHAN7 BIT(7) +#define DMA_STATUS_CHAN6 BIT(6) +#define DMA_STATUS_CHAN5 BIT(5) +#define DMA_STATUS_CHAN4 BIT(4) +#define DMA_STATUS_CHAN3 BIT(3) +#define DMA_STATUS_CHAN2 BIT(2) +#define DMA_STATUS_CHAN1 BIT(1) +#define DMA_STATUS_CHAN0 BIT(0) + +/* DMA debug status bitmap */ +#define DMA_DEBUG_STATUS_TS_MASK 0xf +#define DMA_DEBUG_STATUS_RS_MASK 0xf + +/* DMA AXI bitmap */ +#define DMA_AXI_EN_LPI BIT(31) +#define DMA_AXI_LPI_XIT_FRM BIT(30) +#define DMA_AXI_WR_OSR_LMT GENMASK(27, 24) +#define DMA_AXI_WR_OSR_LMT_SHIFT 24 +#define DMA_AXI_RD_OSR_LMT GENMASK(19, 16) +#define DMA_AXI_RD_OSR_LMT_SHIFT 16 + +#define DMA_AXI_OSR_MAX 0xf +#define DMA_AXI_MAX_OSR_LIMIT ((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \ + (DMA_AXI_OSR_MAX << DMA_AXI_RD_OSR_LMT_SHIFT)) + +#define DMA_SYS_BUS_MB BIT(14) +#define DMA_AXI_1KBBE BIT(13) +#define DMA_SYS_BUS_AAL BIT(12) +#define DMA_AXI_BLEN256 BIT(7) +#define DMA_AXI_BLEN128 BIT(6) +#define DMA_AXI_BLEN64 BIT(5) +#define DMA_AXI_BLEN32 BIT(4) +#define DMA_AXI_BLEN16 BIT(3) +#define DMA_AXI_BLEN8 BIT(2) +#define DMA_AXI_BLEN4 BIT(1) +#define DMA_SYS_BUS_FB BIT(0) + +#define DMA_BURST_LEN_DEFAULT (DMA_AXI_BLEN256 | DMA_AXI_BLEN128 | \ + DMA_AXI_BLEN64 | DMA_AXI_BLEN32 | \ + DMA_AXI_BLEN16 | DMA_AXI_BLEN8 | \ + DMA_AXI_BLEN4) + +#define DMA_AXI_BURST_LEN_MASK 0x000000FE + +/* Following DMA defines are chanels oriented */ +#define DMA_CHAN_BASE_ADDR 0x00001100 +#define DMA_CHAN_BASE_OFFSET 0x80 +#define DMA_CHANX_BASE_ADDR(x) (DMA_CHAN_BASE_ADDR + \ + (x * DMA_CHAN_BASE_OFFSET)) +#define DMA_CHAN_REG_NUMBER 17 + +#define DMA_CHAN_CONTROL(x) DMA_CHANX_BASE_ADDR(x) +#define DMA_CHAN_TX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x4) +#define DMA_CHAN_RX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x8) +#define DMA_CHAN_TX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x14) +#define DMA_CHAN_RX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x1c) +#define DMA_CHAN_TX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x20) +#define DMA_CHAN_RX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x28) +#define DMA_CHAN_TX_RING_LEN(x) (DMA_CHANX_BASE_ADDR(x) + 0x2c) +#define DMA_CHAN_RX_RING_LEN(x) (DMA_CHANX_BASE_ADDR(x) + 0x30) +#define DMA_CHAN_INTR_ENA(x) (DMA_CHANX_BASE_ADDR(x) + 0x34) +#define DMA_CHAN_RX_WATCHDOG(x) (DMA_CHANX_BASE_ADDR(x) + 0x38) +#define DMA_CHAN_SLOT_CTRL_STATUS(x) (DMA_CHANX_BASE_ADDR(x) + 0x3c) +#define DMA_CHAN_CUR_TX_DESC(x) (DMA_CHANX_BASE_ADDR(x) + 0x44) +#define DMA_CHAN_CUR_RX_DESC(x) (DMA_CHANX_BASE_ADDR(x) + 0x4c) +#define DMA_CHAN_CUR_TX_BUF_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x54) +#define DMA_CHAN_CUR_RX_BUF_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x5c) +#define DMA_CHAN_STATUS(x) (DMA_CHANX_BASE_ADDR(x) + 0x60) + +/* DMA Control X */ +#define DMA_CONTROL_MSS_MASK GENMASK(13, 0) + +/* DMA Tx Channel X Control register defines */ +#define DMA_CONTROL_TSE BIT(12) +#define DMA_CONTROL_OSP BIT(4) +#define DMA_CONTROL_ST BIT(0) + +/* DMA Rx Channel X Control register defines */ +#define DMA_CONTROL_SR BIT(0) + +/* Interrupt status per channel */ +#define DMA_CHAN_STATUS_REB GENMASK(21, 19) +#define DMA_CHAN_STATUS_REB_SHIFT 19 +#define DMA_CHAN_STATUS_TEB GENMASK(18, 16) +#define DMA_CHAN_STATUS_TEB_SHIFT 16 +#define DMA_CHAN_STATUS_NIS BIT(15) +#define DMA_CHAN_STATUS_AIS BIT(14) +#define DMA_CHAN_STATUS_CDE BIT(13) +#define DMA_CHAN_STATUS_FBE BIT(12) +#define DMA_CHAN_STATUS_ERI BIT(11) +#define DMA_CHAN_STATUS_ETI BIT(10) +#define DMA_CHAN_STATUS_RWT BIT(9) +#define DMA_CHAN_STATUS_RPS BIT(8) +#define DMA_CHAN_STATUS_RBU BIT(7) +#define DMA_CHAN_STATUS_RI BIT(6) +#define DMA_CHAN_STATUS_TBU BIT(2) +#define DMA_CHAN_STATUS_TPS BIT(1) +#define DMA_CHAN_STATUS_TI BIT(0) + +/* Interrupt enable bits per channel */ +#define DMA_CHAN_INTR_ENA_NIE BIT(16) +#define DMA_CHAN_INTR_ENA_AIE BIT(15) +#define DMA_CHAN_INTR_ENA_NIE_4_10 BIT(15) +#define DMA_CHAN_INTR_ENA_AIE_4_10 BIT(14) +#define DMA_CHAN_INTR_ENA_CDE BIT(13) +#define DMA_CHAN_INTR_ENA_FBE BIT(12) +#define DMA_CHAN_INTR_ENA_ERE BIT(11) +#define DMA_CHAN_INTR_ENA_ETE BIT(10) +#define DMA_CHAN_INTR_ENA_RWE BIT(9) +#define DMA_CHAN_INTR_ENA_RSE BIT(8) +#define DMA_CHAN_INTR_ENA_RBUE BIT(7) +#define DMA_CHAN_INTR_ENA_RIE BIT(6) +#define DMA_CHAN_INTR_ENA_TBUE BIT(2) +#define DMA_CHAN_INTR_ENA_TSE BIT(1) +#define DMA_CHAN_INTR_ENA_TIE BIT(0) + +#define DMA_CHAN_INTR_NORMAL (DMA_CHAN_INTR_ENA_NIE | \ + DMA_CHAN_INTR_ENA_RIE | \ + DMA_CHAN_INTR_ENA_TIE) + +#define DMA_CHAN_INTR_ABNORMAL (DMA_CHAN_INTR_ENA_AIE | \ + DMA_CHAN_INTR_ENA_FBE) +/* DMA default interrupt mask for 4.00 */ +#define DMA_CHAN_INTR_DEFAULT_MASK (DMA_CHAN_INTR_NORMAL | \ + DMA_CHAN_INTR_ABNORMAL) + +#define DMA_CHAN_INTR_NORMAL_4_10 (DMA_CHAN_INTR_ENA_NIE_4_10 | \ + DMA_CHAN_INTR_ENA_RIE | \ + DMA_CHAN_INTR_ENA_TIE) + +#define DMA_CHAN_INTR_ABNORMAL_4_10 (DMA_CHAN_INTR_ENA_AIE_4_10 | \ + DMA_CHAN_INTR_ENA_FBE) +/* DMA default interrupt mask for 4.10a */ +#define DMA_CHAN_INTR_DEFAULT_MASK_4_10 (DMA_CHAN_INTR_NORMAL_4_10 | \ + DMA_CHAN_INTR_ABNORMAL_4_10) + +/* channel 0 specific fields */ +#define DMA_CHAN0_DBG_STAT_TPS GENMASK(15, 12) +#define DMA_CHAN0_DBG_STAT_TPS_SHIFT 12 +#define DMA_CHAN0_DBG_STAT_RPS GENMASK(11, 8) +#define DMA_CHAN0_DBG_STAT_RPS_SHIFT 8 + +int dwmac4_dma_reset(void __iomem *ioaddr); +void dwmac4_enable_dma_transmission(void __iomem *ioaddr, u32 tail_ptr); +void dwmac4_enable_dma_irq(void __iomem *ioaddr); +void dwmac410_enable_dma_irq(void __iomem *ioaddr); +void dwmac4_disable_dma_irq(void __iomem *ioaddr); +void dwmac4_dma_start_tx(void __iomem *ioaddr); +void dwmac4_dma_stop_tx(void __iomem *ioaddr); +void dwmac4_dma_start_rx(void __iomem *ioaddr); +void dwmac4_dma_stop_rx(void __iomem *ioaddr); +int dwmac4_dma_interrupt(void __iomem *ioaddr, + struct stmmac_extra_stats *x); +void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len); +void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len); +void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan); +void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan); + +#endif /* __DWMAC4_DMA_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c new file mode 100644 index 000000000000..c7326d5b2f43 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2007-2015 STMicroelectronics Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Author: Alexandre Torgue + */ + +#include +#include +#include "common.h" +#include "dwmac4_dma.h" +#include "dwmac4.h" + +int dwmac4_dma_reset(void __iomem *ioaddr) +{ + u32 value = readl(ioaddr + DMA_BUS_MODE); + int limit; + + /* DMA SW reset */ + value |= DMA_BUS_MODE_SFT_RESET; + writel(value, ioaddr + DMA_BUS_MODE); + limit = 10; + while (limit--) { + if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)) + break; + mdelay(10); + } + + if (limit < 0) + return -EBUSY; + + return 0; +} + +void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan) +{ + writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(0)); +} + +void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan) +{ + writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(0)); +} + +void dwmac4_dma_start_tx(void __iomem *ioaddr) +{ + u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + + value |= DMA_CONTROL_ST; + writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + + value = readl(ioaddr + GMAC_CONFIG); + value |= GMAC_CONFIG_TE; + writel(value, ioaddr + GMAC_CONFIG); +} + +void dwmac4_dma_stop_tx(void __iomem *ioaddr) +{ + u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + + value &= ~DMA_CONTROL_ST; + writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); + + value = readl(ioaddr + GMAC_CONFIG); + value &= ~GMAC_CONFIG_TE; + writel(value, ioaddr + GMAC_CONFIG); +} + +void dwmac4_dma_start_rx(void __iomem *ioaddr) +{ + u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + + value |= DMA_CONTROL_SR; + + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + + value = readl(ioaddr + GMAC_CONFIG); + value |= GMAC_CONFIG_RE; + writel(value, ioaddr + GMAC_CONFIG); +} + +void dwmac4_dma_stop_rx(void __iomem *ioaddr) +{ + u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + + value &= ~DMA_CONTROL_SR; + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); + + value = readl(ioaddr + GMAC_CONFIG); + value &= ~GMAC_CONFIG_RE; + writel(value, ioaddr + GMAC_CONFIG); +} + +void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len) +{ + writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(STMMAC_CHAN0)); +} + +void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len) +{ + writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(STMMAC_CHAN0)); +} + +void dwmac4_enable_dma_irq(void __iomem *ioaddr) +{ + writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr + + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); +} + +void dwmac410_enable_dma_irq(void __iomem *ioaddr) +{ + writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10, + ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); +} + +void dwmac4_disable_dma_irq(void __iomem *ioaddr) +{ + writel(0, ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); +} + +int dwmac4_dma_interrupt(void __iomem *ioaddr, + struct stmmac_extra_stats *x) +{ + int ret = 0; + + u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(0)); + + /* ABNORMAL interrupts */ + if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) { + if (unlikely(intr_status & DMA_CHAN_STATUS_RBU)) + x->rx_buf_unav_irq++; + if (unlikely(intr_status & DMA_CHAN_STATUS_RPS)) + x->rx_process_stopped_irq++; + if (unlikely(intr_status & DMA_CHAN_STATUS_RWT)) + x->rx_watchdog_irq++; + if (unlikely(intr_status & DMA_CHAN_STATUS_ETI)) + x->tx_early_irq++; + if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) { + x->tx_process_stopped_irq++; + ret = tx_hard_error; + } + if (unlikely(intr_status & DMA_CHAN_STATUS_FBE)) { + x->fatal_bus_error_irq++; + ret = tx_hard_error; + } + } + /* TX/RX NORMAL interrupts */ + if (likely(intr_status & DMA_CHAN_STATUS_NIS)) { + x->normal_irq_n++; + if (likely(intr_status & DMA_CHAN_STATUS_RI)) { + u32 value; + + value = readl(ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); + /* to schedule NAPI on real RIE event. */ + if (likely(value & DMA_CHAN_INTR_ENA_RIE)) { + x->rx_normal_irq_n++; + ret |= handle_rx; + } + } + if (likely(intr_status & DMA_CHAN_STATUS_TI)) { + x->tx_normal_irq_n++; + ret |= handle_tx; + } + if (unlikely(intr_status & DMA_CHAN_STATUS_ERI)) + x->rx_early_irq++; + } + + /* Clear the interrupt by writing a logic 1 to the chanX interrupt + * status [21-0] expect reserved bits [5-3] + */ + writel((intr_status & 0x3fffc7), + ioaddr + DMA_CHAN_STATUS(STMMAC_CHAN0)); + + return ret; +} + +void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, u8 addr[6], + unsigned int high, unsigned int low) +{ + unsigned long data; + + data = (addr[5] << 8) | addr[4]; + /* For MAC Addr registers se have to set the Address Enable (AE) + * bit that has no effect on the High Reg 0 where the bit 31 (MO) + * is RO. + */ + data |= (STMMAC_CHAN0 << GMAC_HI_DCS_SHIFT); + writel(data | GMAC_HI_REG_AE, ioaddr + high); + data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; + writel(data, ioaddr + low); +} + +/* Enable disable MAC RX/TX */ +void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable) +{ + u32 value = readl(ioaddr + GMAC_CONFIG); + + if (enable) + value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE; + else + value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE); + + writel(value, ioaddr + GMAC_CONFIG); +} + +void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, + unsigned int high, unsigned int low) +{ + unsigned int hi_addr, lo_addr; + + /* Read the MAC address from the hardware */ + hi_addr = readl(ioaddr + high); + lo_addr = readl(ioaddr + low); + + /* Extract the MAC address from the high and low words */ + addr[0] = lo_addr & 0xff; + addr[1] = (lo_addr >> 8) & 0xff; + addr[2] = (lo_addr >> 16) & 0xff; + addr[3] = (lo_addr >> 24) & 0xff; + addr[4] = hi_addr & 0xff; + addr[5] = (hi_addr >> 8) & 0xff; +} -- GitLab From 477286b53f5576ddec0a4df0f3d0c4bd7a0ed165 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:31 +0200 Subject: [PATCH 1118/9938] stmmac: add GMAC4 core support This is the initial support for GMAC4 that includes the main callbacks to setup the core module: including Csum, basic filtering, mac address and interrupt (MMC, MTL, PMT) No LPI added. Signed-off-by: Alexandre TORGUE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/common.h | 10 +- drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 31 ++ .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 407 ++++++++++++++++++ 4 files changed, 447 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 9398acef0125..0fb362d5a722 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -3,7 +3,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ - dwmac4_dma.o dwmac4_lib.o $(stmmac-y) + dwmac4_dma.o dwmac4_lib.o dwmac4_core.o $(stmmac-y) # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 2a5126e3d3df..eabe86bd8f56 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -527,15 +527,21 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, int perfect_uc_entries, int *synopsys_id); struct mac_device_info *dwmac100_setup(void __iomem *ioaddr, int *synopsys_id); - +struct mac_device_info *dwmac4_setup(void __iomem *ioaddr, int mcbins, + int perfect_uc_entries, int *synopsys_id); void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], unsigned int high, unsigned int low); void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int high, unsigned int low); - void stmmac_set_mac(void __iomem *ioaddr, bool enable); +void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, u8 addr[6], + unsigned int high, unsigned int low); +void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, + unsigned int high, unsigned int low); +void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable); + void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); extern const struct stmmac_mode_ops ring_mode_ops; extern const struct stmmac_mode_ops chain_mode_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h index c12f15c9b351..bc50952a18e7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h @@ -221,4 +221,35 @@ enum power_event { /* To dump the core regs excluding the Address Registers */ #define GMAC_REG_NUM 132 +/* MTL debug */ +#define MTL_DEBUG_TXSTSFSTS BIT(5) +#define MTL_DEBUG_TXFSTS BIT(4) +#define MTL_DEBUG_TWCSTS BIT(3) + +/* MTL debug: Tx FIFO Read Controller Status */ +#define MTL_DEBUG_TRCSTS_MASK GENMASK(2, 1) +#define MTL_DEBUG_TRCSTS_SHIFT 1 +#define MTL_DEBUG_TRCSTS_IDLE 0 +#define MTL_DEBUG_TRCSTS_READ 1 +#define MTL_DEBUG_TRCSTS_TXW 2 +#define MTL_DEBUG_TRCSTS_WRITE 3 +#define MTL_DEBUG_TXPAUSED BIT(0) + +/* MAC debug: GMII or MII Transmit Protocol Engine Status */ +#define MTL_DEBUG_RXFSTS_MASK GENMASK(5, 4) +#define MTL_DEBUG_RXFSTS_SHIFT 4 +#define MTL_DEBUG_RXFSTS_EMPTY 0 +#define MTL_DEBUG_RXFSTS_BT 1 +#define MTL_DEBUG_RXFSTS_AT 2 +#define MTL_DEBUG_RXFSTS_FULL 3 +#define MTL_DEBUG_RRCSTS_MASK GENMASK(2, 1) +#define MTL_DEBUG_RRCSTS_SHIFT 1 +#define MTL_DEBUG_RRCSTS_IDLE 0 +#define MTL_DEBUG_RRCSTS_RDATA 1 +#define MTL_DEBUG_RRCSTS_RSTAT 2 +#define MTL_DEBUG_RRCSTS_FLUSH 3 +#define MTL_DEBUG_RWCSTS BIT(0) + +extern const struct stmmac_dma_ops dwmac4_dma_ops; +extern const struct stmmac_dma_ops dwmac410_dma_ops; #endif /* __DWMAC4_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c new file mode 100644 index 000000000000..4f7283d05588 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -0,0 +1,407 @@ +/* + * This is the driver for the GMAC on-chip Ethernet controller for ST SoCs. + * DWC Ether MAC version 4.00 has been used for developing this code. + * + * This only implements the mac core functions for this chip. + * + * Copyright (C) 2015 STMicroelectronics Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * Author: Alexandre Torgue + */ + +#include +#include +#include +#include +#include "dwmac4.h" + +static void dwmac4_core_init(struct mac_device_info *hw, int mtu) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value = readl(ioaddr + GMAC_CONFIG); + + value |= GMAC_CORE_INIT; + + if (mtu > 1500) + value |= GMAC_CONFIG_2K; + if (mtu > 2000) + value |= GMAC_CONFIG_JE; + + writel(value, ioaddr + GMAC_CONFIG); + + /* Mask GMAC interrupts */ + writel(GMAC_INT_PMT_EN, ioaddr + GMAC_INT_EN); +} + +static void dwmac4_dump_regs(struct mac_device_info *hw) +{ + void __iomem *ioaddr = hw->pcsr; + int i; + + pr_debug("\tDWMAC4 regs (base addr = 0x%p)\n", ioaddr); + + for (i = 0; i < GMAC_REG_NUM; i++) { + int offset = i * 4; + + pr_debug("\tReg No. %d (offset 0x%x): 0x%08x\n", i, + offset, readl(ioaddr + offset)); + } +} + +static int dwmac4_rx_ipc_enable(struct mac_device_info *hw) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value = readl(ioaddr + GMAC_CONFIG); + + if (hw->rx_csum) + value |= GMAC_CONFIG_IPC; + else + value &= ~GMAC_CONFIG_IPC; + + writel(value, ioaddr + GMAC_CONFIG); + + value = readl(ioaddr + GMAC_CONFIG); + + return !!(value & GMAC_CONFIG_IPC); +} + +static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode) +{ + void __iomem *ioaddr = hw->pcsr; + unsigned int pmt = 0; + + if (mode & WAKE_MAGIC) { + pr_debug("GMAC: WOL Magic frame\n"); + pmt |= power_down | magic_pkt_en; + } + if (mode & WAKE_UCAST) { + pr_debug("GMAC: WOL on global unicast\n"); + pmt |= global_unicast; + } + + writel(pmt, ioaddr + GMAC_PMT); +} + +static void dwmac4_set_umac_addr(struct mac_device_info *hw, + unsigned char *addr, unsigned int reg_n) +{ + void __iomem *ioaddr = hw->pcsr; + + stmmac_dwmac4_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), + GMAC_ADDR_LOW(reg_n)); +} + +static void dwmac4_get_umac_addr(struct mac_device_info *hw, + unsigned char *addr, unsigned int reg_n) +{ + void __iomem *ioaddr = hw->pcsr; + + stmmac_dwmac4_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), + GMAC_ADDR_LOW(reg_n)); +} + +static void dwmac4_set_filter(struct mac_device_info *hw, + struct net_device *dev) +{ + void __iomem *ioaddr = (void __iomem *)dev->base_addr; + unsigned int value = 0; + + if (dev->flags & IFF_PROMISC) { + value = GMAC_PACKET_FILTER_PR; + } else if ((dev->flags & IFF_ALLMULTI) || + (netdev_mc_count(dev) > HASH_TABLE_SIZE)) { + /* Pass all multi */ + value = GMAC_PACKET_FILTER_PM; + /* Set the 64 bits of the HASH tab. To be updated if taller + * hash table is used + */ + writel(0xffffffff, ioaddr + GMAC_HASH_TAB_0_31); + writel(0xffffffff, ioaddr + GMAC_HASH_TAB_32_63); + } else if (!netdev_mc_empty(dev)) { + u32 mc_filter[2]; + struct netdev_hw_addr *ha; + + /* Hash filter for multicast */ + value = GMAC_PACKET_FILTER_HMC; + + memset(mc_filter, 0, sizeof(mc_filter)); + netdev_for_each_mc_addr(ha, dev) { + /* The upper 6 bits of the calculated CRC are used to + * index the content of the Hash Table Reg 0 and 1. + */ + int bit_nr = + (bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26); + /* The most significant bit determines the register + * to use while the other 5 bits determines the bit + * within the selected register + */ + mc_filter[bit_nr >> 5] |= (1 << (bit_nr & 0x1F)); + } + writel(mc_filter[0], ioaddr + GMAC_HASH_TAB_0_31); + writel(mc_filter[1], ioaddr + GMAC_HASH_TAB_32_63); + } + + /* Handle multiple unicast addresses */ + if (netdev_uc_count(dev) > GMAC_MAX_PERFECT_ADDRESSES) { + /* Switch to promiscuous mode if more than 128 addrs + * are required + */ + value |= GMAC_PACKET_FILTER_PR; + } else if (!netdev_uc_empty(dev)) { + int reg = 1; + struct netdev_hw_addr *ha; + + netdev_for_each_uc_addr(ha, dev) { + dwmac4_set_umac_addr(ioaddr, ha->addr, reg); + reg++; + } + } + + writel(value, ioaddr + GMAC_PACKET_FILTER); +} + +static void dwmac4_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, + unsigned int fc, unsigned int pause_time) +{ + void __iomem *ioaddr = hw->pcsr; + u32 channel = STMMAC_CHAN0; /* FIXME */ + unsigned int flow = 0; + + pr_debug("GMAC Flow-Control:\n"); + if (fc & FLOW_RX) { + pr_debug("\tReceive Flow-Control ON\n"); + flow |= GMAC_RX_FLOW_CTRL_RFE; + writel(flow, ioaddr + GMAC_RX_FLOW_CTRL); + } + if (fc & FLOW_TX) { + pr_debug("\tTransmit Flow-Control ON\n"); + flow |= GMAC_TX_FLOW_CTRL_TFE; + writel(flow, ioaddr + GMAC_QX_TX_FLOW_CTRL(channel)); + + if (duplex) { + pr_debug("\tduplex mode: PAUSE %d\n", pause_time); + flow |= (pause_time << GMAC_TX_FLOW_CTRL_PT_SHIFT); + writel(flow, ioaddr + GMAC_QX_TX_FLOW_CTRL(channel)); + } + } +} + +static void dwmac4_ctrl_ane(struct mac_device_info *hw, bool restart) +{ + void __iomem *ioaddr = hw->pcsr; + + /* auto negotiation enable and External Loopback enable */ + u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE; + + if (restart) + value |= GMAC_AN_CTRL_RAN; + + writel(value, ioaddr + GMAC_AN_CTRL); +} + +static void dwmac4_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value = readl(ioaddr + GMAC_AN_ADV); + + if (value & GMAC_AN_FD) + adv->duplex = DUPLEX_FULL; + if (value & GMAC_AN_HD) + adv->duplex |= DUPLEX_HALF; + + adv->pause = (value & GMAC_AN_PSE_MASK) >> GMAC_AN_PSE_SHIFT; + + value = readl(ioaddr + GMAC_AN_LPA); + + if (value & GMAC_AN_FD) + adv->lp_duplex = DUPLEX_FULL; + if (value & GMAC_AN_HD) + adv->lp_duplex = DUPLEX_HALF; + + adv->lp_pause = (value & GMAC_AN_PSE_MASK) >> GMAC_AN_PSE_SHIFT; +} + +static int dwmac4_irq_status(struct mac_device_info *hw, + struct stmmac_extra_stats *x) +{ + void __iomem *ioaddr = hw->pcsr; + u32 mtl_int_qx_status; + u32 intr_status; + int ret = 0; + + intr_status = readl(ioaddr + GMAC_INT_STATUS); + + /* Not used events (e.g. MMC interrupts) are not handled. */ + if ((intr_status & mmc_tx_irq)) + x->mmc_tx_irq_n++; + if (unlikely(intr_status & mmc_rx_irq)) + x->mmc_rx_irq_n++; + if (unlikely(intr_status & mmc_rx_csum_offload_irq)) + x->mmc_rx_csum_offload_irq_n++; + /* Clear the PMT bits 5 and 6 by reading the PMT status reg */ + if (unlikely(intr_status & pmt_irq)) { + readl(ioaddr + GMAC_PMT); + x->irq_receive_pmt_irq_n++; + } + + if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) { + readl(ioaddr + GMAC_AN_STATUS); + x->irq_pcs_ane_n++; + } + + mtl_int_qx_status = readl(ioaddr + MTL_INT_STATUS); + /* Check MTL Interrupt: Currently only one queue is used: Q0. */ + if (mtl_int_qx_status & MTL_INT_Q0) { + /* read Queue 0 Interrupt status */ + u32 status = readl(ioaddr + MTL_CHAN_INT_CTRL(STMMAC_CHAN0)); + + if (status & MTL_RX_OVERFLOW_INT) { + /* clear Interrupt */ + writel(status | MTL_RX_OVERFLOW_INT, + ioaddr + MTL_CHAN_INT_CTRL(STMMAC_CHAN0)); + ret = CORE_IRQ_MTL_RX_OVERFLOW; + } + } + + return ret; +} + +static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x) +{ + u32 value; + + /* Currently only channel 0 is supported */ + value = readl(ioaddr + MTL_CHAN_TX_DEBUG(STMMAC_CHAN0)); + + if (value & MTL_DEBUG_TXSTSFSTS) + x->mtl_tx_status_fifo_full++; + if (value & MTL_DEBUG_TXFSTS) + x->mtl_tx_fifo_not_empty++; + if (value & MTL_DEBUG_TWCSTS) + x->mmtl_fifo_ctrl++; + if (value & MTL_DEBUG_TRCSTS_MASK) { + u32 trcsts = (value & MTL_DEBUG_TRCSTS_MASK) + >> MTL_DEBUG_TRCSTS_SHIFT; + if (trcsts == MTL_DEBUG_TRCSTS_WRITE) + x->mtl_tx_fifo_read_ctrl_write++; + else if (trcsts == MTL_DEBUG_TRCSTS_TXW) + x->mtl_tx_fifo_read_ctrl_wait++; + else if (trcsts == MTL_DEBUG_TRCSTS_READ) + x->mtl_tx_fifo_read_ctrl_read++; + else + x->mtl_tx_fifo_read_ctrl_idle++; + } + if (value & MTL_DEBUG_TXPAUSED) + x->mac_tx_in_pause++; + + value = readl(ioaddr + MTL_CHAN_RX_DEBUG(STMMAC_CHAN0)); + + if (value & MTL_DEBUG_RXFSTS_MASK) { + u32 rxfsts = (value & MTL_DEBUG_RXFSTS_MASK) + >> MTL_DEBUG_RRCSTS_SHIFT; + + if (rxfsts == MTL_DEBUG_RXFSTS_FULL) + x->mtl_rx_fifo_fill_level_full++; + else if (rxfsts == MTL_DEBUG_RXFSTS_AT) + x->mtl_rx_fifo_fill_above_thresh++; + else if (rxfsts == MTL_DEBUG_RXFSTS_BT) + x->mtl_rx_fifo_fill_below_thresh++; + else + x->mtl_rx_fifo_fill_level_empty++; + } + if (value & MTL_DEBUG_RRCSTS_MASK) { + u32 rrcsts = (value & MTL_DEBUG_RRCSTS_MASK) >> + MTL_DEBUG_RRCSTS_SHIFT; + + if (rrcsts == MTL_DEBUG_RRCSTS_FLUSH) + x->mtl_rx_fifo_read_ctrl_flush++; + else if (rrcsts == MTL_DEBUG_RRCSTS_RSTAT) + x->mtl_rx_fifo_read_ctrl_read_data++; + else if (rrcsts == MTL_DEBUG_RRCSTS_RDATA) + x->mtl_rx_fifo_read_ctrl_status++; + else + x->mtl_rx_fifo_read_ctrl_idle++; + } + if (value & MTL_DEBUG_RWCSTS) + x->mtl_rx_fifo_ctrl_active++; + + /* GMAC debug */ + value = readl(ioaddr + GMAC_DEBUG); + + if (value & GMAC_DEBUG_TFCSTS_MASK) { + u32 tfcsts = (value & GMAC_DEBUG_TFCSTS_MASK) + >> GMAC_DEBUG_TFCSTS_SHIFT; + + if (tfcsts == GMAC_DEBUG_TFCSTS_XFER) + x->mac_tx_frame_ctrl_xfer++; + else if (tfcsts == GMAC_DEBUG_TFCSTS_GEN_PAUSE) + x->mac_tx_frame_ctrl_pause++; + else if (tfcsts == GMAC_DEBUG_TFCSTS_WAIT) + x->mac_tx_frame_ctrl_wait++; + else + x->mac_tx_frame_ctrl_idle++; + } + if (value & GMAC_DEBUG_TPESTS) + x->mac_gmii_tx_proto_engine++; + if (value & GMAC_DEBUG_RFCFCSTS_MASK) + x->mac_rx_frame_ctrl_fifo = (value & GMAC_DEBUG_RFCFCSTS_MASK) + >> GMAC_DEBUG_RFCFCSTS_SHIFT; + if (value & GMAC_DEBUG_RPESTS) + x->mac_gmii_rx_proto_engine++; +} + +static const struct stmmac_ops dwmac4_ops = { + .core_init = dwmac4_core_init, + .rx_ipc = dwmac4_rx_ipc_enable, + .dump_regs = dwmac4_dump_regs, + .host_irq_status = dwmac4_irq_status, + .flow_ctrl = dwmac4_flow_ctrl, + .pmt = dwmac4_pmt, + .set_umac_addr = dwmac4_set_umac_addr, + .get_umac_addr = dwmac4_get_umac_addr, + .ctrl_ane = dwmac4_ctrl_ane, + .get_adv = dwmac4_get_adv, + .debug = dwmac4_debug, + .set_filter = dwmac4_set_filter, +}; + +struct mac_device_info *dwmac4_setup(void __iomem *ioaddr, int mcbins, + int perfect_uc_entries, int *synopsys_id) +{ + struct mac_device_info *mac; + u32 hwid = readl(ioaddr + GMAC_VERSION); + + mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); + if (!mac) + return NULL; + + mac->pcsr = ioaddr; + mac->multicast_filter_bins = mcbins; + mac->unicast_filter_entries = perfect_uc_entries; + mac->mcast_bits_log2 = 0; + + if (mac->multicast_filter_bins) + mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + + mac->mac = &dwmac4_ops; + + mac->link.port = GMAC_CONFIG_PS; + mac->link.duplex = GMAC_CONFIG_DM; + mac->link.speed = GMAC_CONFIG_FES; + mac->mii.addr = GMAC_MDIO_ADDR; + mac->mii.data = GMAC_MDIO_DATA; + + /* Get and dump the chip ID */ + *synopsys_id = stmmac_get_synopsys_id(hwid); + + if (*synopsys_id > DWMAC_CORE_4_00) + mac->dma = &dwmac410_dma_ops; + else + mac->dma = &dwmac4_dma_ops; + + return mac; +} -- GitLab From 36ff7c1e94a5d43a0ea2d386b211087f77669017 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:32 +0200 Subject: [PATCH 1119/9938] stmmac: enhance mmc counter management For gmac3, the MMC addr map is: 0x100 - 0x2fc For gmac4, the MMC addr map is: 0x700 - 0x8fc So instead of adding 0x600 to the IO address when setup the mmc, the RMON base address is saved inside the private structure and then used to manage the counters. Signed-off-by: Giuseppe Cavallaro Signed-off-by: Alexandre TORGUE Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/mmc.h | 4 + .../net/ethernet/stmicro/stmmac/mmc_core.c | 349 +++++++++--------- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 8 +- 5 files changed, 188 insertions(+), 176 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h index 192c2491330b..38a1a5603293 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc.h +++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h @@ -35,6 +35,10 @@ * current value.*/ #define MMC_CNTRL_PRESET 0x10 #define MMC_CNTRL_FULL_HALF_PRESET 0x20 + +#define MMC_GMAC4_OFFSET 0x700 +#define MMC_GMAC3_X_OFFSET 0x100 + struct stmmac_counters { unsigned int mmc_tx_octetcount_gb; unsigned int mmc_tx_framecount_gb; diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index 3f20bb1fe570..ce9aa792857b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -28,12 +28,12 @@ /* MAC Management Counters register offset */ -#define MMC_CNTRL 0x00000100 /* MMC Control */ -#define MMC_RX_INTR 0x00000104 /* MMC RX Interrupt */ -#define MMC_TX_INTR 0x00000108 /* MMC TX Interrupt */ -#define MMC_RX_INTR_MASK 0x0000010c /* MMC Interrupt Mask */ -#define MMC_TX_INTR_MASK 0x00000110 /* MMC Interrupt Mask */ -#define MMC_DEFAULT_MASK 0xffffffff +#define MMC_CNTRL 0x00 /* MMC Control */ +#define MMC_RX_INTR 0x04 /* MMC RX Interrupt */ +#define MMC_TX_INTR 0x08 /* MMC TX Interrupt */ +#define MMC_RX_INTR_MASK 0x0c /* MMC Interrupt Mask */ +#define MMC_TX_INTR_MASK 0x10 /* MMC Interrupt Mask */ +#define MMC_DEFAULT_MASK 0xffffffff /* MMC TX counter registers */ @@ -41,115 +41,115 @@ * _GB register stands for good and bad frames * _G is for good only. */ -#define MMC_TX_OCTETCOUNT_GB 0x00000114 -#define MMC_TX_FRAMECOUNT_GB 0x00000118 -#define MMC_TX_BROADCASTFRAME_G 0x0000011c -#define MMC_TX_MULTICASTFRAME_G 0x00000120 -#define MMC_TX_64_OCTETS_GB 0x00000124 -#define MMC_TX_65_TO_127_OCTETS_GB 0x00000128 -#define MMC_TX_128_TO_255_OCTETS_GB 0x0000012c -#define MMC_TX_256_TO_511_OCTETS_GB 0x00000130 -#define MMC_TX_512_TO_1023_OCTETS_GB 0x00000134 -#define MMC_TX_1024_TO_MAX_OCTETS_GB 0x00000138 -#define MMC_TX_UNICAST_GB 0x0000013c -#define MMC_TX_MULTICAST_GB 0x00000140 -#define MMC_TX_BROADCAST_GB 0x00000144 -#define MMC_TX_UNDERFLOW_ERROR 0x00000148 -#define MMC_TX_SINGLECOL_G 0x0000014c -#define MMC_TX_MULTICOL_G 0x00000150 -#define MMC_TX_DEFERRED 0x00000154 -#define MMC_TX_LATECOL 0x00000158 -#define MMC_TX_EXESSCOL 0x0000015c -#define MMC_TX_CARRIER_ERROR 0x00000160 -#define MMC_TX_OCTETCOUNT_G 0x00000164 -#define MMC_TX_FRAMECOUNT_G 0x00000168 -#define MMC_TX_EXCESSDEF 0x0000016c -#define MMC_TX_PAUSE_FRAME 0x00000170 -#define MMC_TX_VLAN_FRAME_G 0x00000174 +#define MMC_TX_OCTETCOUNT_GB 0x14 +#define MMC_TX_FRAMECOUNT_GB 0x18 +#define MMC_TX_BROADCASTFRAME_G 0x1c +#define MMC_TX_MULTICASTFRAME_G 0x20 +#define MMC_TX_64_OCTETS_GB 0x24 +#define MMC_TX_65_TO_127_OCTETS_GB 0x28 +#define MMC_TX_128_TO_255_OCTETS_GB 0x2c +#define MMC_TX_256_TO_511_OCTETS_GB 0x30 +#define MMC_TX_512_TO_1023_OCTETS_GB 0x34 +#define MMC_TX_1024_TO_MAX_OCTETS_GB 0x38 +#define MMC_TX_UNICAST_GB 0x3c +#define MMC_TX_MULTICAST_GB 0x40 +#define MMC_TX_BROADCAST_GB 0x44 +#define MMC_TX_UNDERFLOW_ERROR 0x48 +#define MMC_TX_SINGLECOL_G 0x4c +#define MMC_TX_MULTICOL_G 0x50 +#define MMC_TX_DEFERRED 0x54 +#define MMC_TX_LATECOL 0x58 +#define MMC_TX_EXESSCOL 0x5c +#define MMC_TX_CARRIER_ERROR 0x60 +#define MMC_TX_OCTETCOUNT_G 0x64 +#define MMC_TX_FRAMECOUNT_G 0x68 +#define MMC_TX_EXCESSDEF 0x6c +#define MMC_TX_PAUSE_FRAME 0x70 +#define MMC_TX_VLAN_FRAME_G 0x74 /* MMC RX counter registers */ -#define MMC_RX_FRAMECOUNT_GB 0x00000180 -#define MMC_RX_OCTETCOUNT_GB 0x00000184 -#define MMC_RX_OCTETCOUNT_G 0x00000188 -#define MMC_RX_BROADCASTFRAME_G 0x0000018c -#define MMC_RX_MULTICASTFRAME_G 0x00000190 -#define MMC_RX_CRC_ERROR 0x00000194 -#define MMC_RX_ALIGN_ERROR 0x00000198 -#define MMC_RX_RUN_ERROR 0x0000019C -#define MMC_RX_JABBER_ERROR 0x000001A0 -#define MMC_RX_UNDERSIZE_G 0x000001A4 -#define MMC_RX_OVERSIZE_G 0x000001A8 -#define MMC_RX_64_OCTETS_GB 0x000001AC -#define MMC_RX_65_TO_127_OCTETS_GB 0x000001b0 -#define MMC_RX_128_TO_255_OCTETS_GB 0x000001b4 -#define MMC_RX_256_TO_511_OCTETS_GB 0x000001b8 -#define MMC_RX_512_TO_1023_OCTETS_GB 0x000001bc -#define MMC_RX_1024_TO_MAX_OCTETS_GB 0x000001c0 -#define MMC_RX_UNICAST_G 0x000001c4 -#define MMC_RX_LENGTH_ERROR 0x000001c8 -#define MMC_RX_AUTOFRANGETYPE 0x000001cc -#define MMC_RX_PAUSE_FRAMES 0x000001d0 -#define MMC_RX_FIFO_OVERFLOW 0x000001d4 -#define MMC_RX_VLAN_FRAMES_GB 0x000001d8 -#define MMC_RX_WATCHDOG_ERROR 0x000001dc +#define MMC_RX_FRAMECOUNT_GB 0x80 +#define MMC_RX_OCTETCOUNT_GB 0x84 +#define MMC_RX_OCTETCOUNT_G 0x88 +#define MMC_RX_BROADCASTFRAME_G 0x8c +#define MMC_RX_MULTICASTFRAME_G 0x90 +#define MMC_RX_CRC_ERROR 0x94 +#define MMC_RX_ALIGN_ERROR 0x98 +#define MMC_RX_RUN_ERROR 0x9C +#define MMC_RX_JABBER_ERROR 0xA0 +#define MMC_RX_UNDERSIZE_G 0xA4 +#define MMC_RX_OVERSIZE_G 0xA8 +#define MMC_RX_64_OCTETS_GB 0xAC +#define MMC_RX_65_TO_127_OCTETS_GB 0xb0 +#define MMC_RX_128_TO_255_OCTETS_GB 0xb4 +#define MMC_RX_256_TO_511_OCTETS_GB 0xb8 +#define MMC_RX_512_TO_1023_OCTETS_GB 0xbc +#define MMC_RX_1024_TO_MAX_OCTETS_GB 0xc0 +#define MMC_RX_UNICAST_G 0xc4 +#define MMC_RX_LENGTH_ERROR 0xc8 +#define MMC_RX_AUTOFRANGETYPE 0xcc +#define MMC_RX_PAUSE_FRAMES 0xd0 +#define MMC_RX_FIFO_OVERFLOW 0xd4 +#define MMC_RX_VLAN_FRAMES_GB 0xd8 +#define MMC_RX_WATCHDOG_ERROR 0xdc /* IPC*/ -#define MMC_RX_IPC_INTR_MASK 0x00000200 -#define MMC_RX_IPC_INTR 0x00000208 +#define MMC_RX_IPC_INTR_MASK 0x100 +#define MMC_RX_IPC_INTR 0x108 /* IPv4*/ -#define MMC_RX_IPV4_GD 0x00000210 -#define MMC_RX_IPV4_HDERR 0x00000214 -#define MMC_RX_IPV4_NOPAY 0x00000218 -#define MMC_RX_IPV4_FRAG 0x0000021C -#define MMC_RX_IPV4_UDSBL 0x00000220 +#define MMC_RX_IPV4_GD 0x110 +#define MMC_RX_IPV4_HDERR 0x114 +#define MMC_RX_IPV4_NOPAY 0x118 +#define MMC_RX_IPV4_FRAG 0x11C +#define MMC_RX_IPV4_UDSBL 0x120 -#define MMC_RX_IPV4_GD_OCTETS 0x00000250 -#define MMC_RX_IPV4_HDERR_OCTETS 0x00000254 -#define MMC_RX_IPV4_NOPAY_OCTETS 0x00000258 -#define MMC_RX_IPV4_FRAG_OCTETS 0x0000025c -#define MMC_RX_IPV4_UDSBL_OCTETS 0x00000260 +#define MMC_RX_IPV4_GD_OCTETS 0x150 +#define MMC_RX_IPV4_HDERR_OCTETS 0x154 +#define MMC_RX_IPV4_NOPAY_OCTETS 0x158 +#define MMC_RX_IPV4_FRAG_OCTETS 0x15c +#define MMC_RX_IPV4_UDSBL_OCTETS 0x160 /* IPV6*/ -#define MMC_RX_IPV6_GD_OCTETS 0x00000264 -#define MMC_RX_IPV6_HDERR_OCTETS 0x00000268 -#define MMC_RX_IPV6_NOPAY_OCTETS 0x0000026c +#define MMC_RX_IPV6_GD_OCTETS 0x164 +#define MMC_RX_IPV6_HDERR_OCTETS 0x168 +#define MMC_RX_IPV6_NOPAY_OCTETS 0x16c -#define MMC_RX_IPV6_GD 0x00000224 -#define MMC_RX_IPV6_HDERR 0x00000228 -#define MMC_RX_IPV6_NOPAY 0x0000022c +#define MMC_RX_IPV6_GD 0x124 +#define MMC_RX_IPV6_HDERR 0x128 +#define MMC_RX_IPV6_NOPAY 0x12c /* Protocols*/ -#define MMC_RX_UDP_GD 0x00000230 -#define MMC_RX_UDP_ERR 0x00000234 -#define MMC_RX_TCP_GD 0x00000238 -#define MMC_RX_TCP_ERR 0x0000023c -#define MMC_RX_ICMP_GD 0x00000240 -#define MMC_RX_ICMP_ERR 0x00000244 +#define MMC_RX_UDP_GD 0x130 +#define MMC_RX_UDP_ERR 0x134 +#define MMC_RX_TCP_GD 0x138 +#define MMC_RX_TCP_ERR 0x13c +#define MMC_RX_ICMP_GD 0x140 +#define MMC_RX_ICMP_ERR 0x144 -#define MMC_RX_UDP_GD_OCTETS 0x00000270 -#define MMC_RX_UDP_ERR_OCTETS 0x00000274 -#define MMC_RX_TCP_GD_OCTETS 0x00000278 -#define MMC_RX_TCP_ERR_OCTETS 0x0000027c -#define MMC_RX_ICMP_GD_OCTETS 0x00000280 -#define MMC_RX_ICMP_ERR_OCTETS 0x00000284 +#define MMC_RX_UDP_GD_OCTETS 0x170 +#define MMC_RX_UDP_ERR_OCTETS 0x174 +#define MMC_RX_TCP_GD_OCTETS 0x178 +#define MMC_RX_TCP_ERR_OCTETS 0x17c +#define MMC_RX_ICMP_GD_OCTETS 0x180 +#define MMC_RX_ICMP_ERR_OCTETS 0x184 -void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode) +void dwmac_mmc_ctrl(void __iomem *mmcaddr, unsigned int mode) { - u32 value = readl(ioaddr + MMC_CNTRL); + u32 value = readl(mmcaddr + MMC_CNTRL); value |= (mode & 0x3F); - writel(value, ioaddr + MMC_CNTRL); + writel(value, mmcaddr + MMC_CNTRL); pr_debug("stmmac: MMC ctrl register (offset 0x%x): 0x%08x\n", MMC_CNTRL, value); } /* To mask all all interrupts.*/ -void dwmac_mmc_intr_all_mask(void __iomem *ioaddr) +void dwmac_mmc_intr_all_mask(void __iomem *mmcaddr) { - writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK); - writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK); - writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_IPC_INTR_MASK); + writel(MMC_DEFAULT_MASK, mmcaddr + MMC_RX_INTR_MASK); + writel(MMC_DEFAULT_MASK, mmcaddr + MMC_TX_INTR_MASK); + writel(MMC_DEFAULT_MASK, mmcaddr + MMC_RX_IPC_INTR_MASK); } /* This reads the MAC core counters (if actaully supported). @@ -157,111 +157,116 @@ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr) * counter after a read. So all the field of the mmc struct * have to be incremented. */ -void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc) +void dwmac_mmc_read(void __iomem *mmcaddr, struct stmmac_counters *mmc) { - mmc->mmc_tx_octetcount_gb += readl(ioaddr + MMC_TX_OCTETCOUNT_GB); - mmc->mmc_tx_framecount_gb += readl(ioaddr + MMC_TX_FRAMECOUNT_GB); - mmc->mmc_tx_broadcastframe_g += readl(ioaddr + MMC_TX_BROADCASTFRAME_G); - mmc->mmc_tx_multicastframe_g += readl(ioaddr + MMC_TX_MULTICASTFRAME_G); - mmc->mmc_tx_64_octets_gb += readl(ioaddr + MMC_TX_64_OCTETS_GB); + mmc->mmc_tx_octetcount_gb += readl(mmcaddr + MMC_TX_OCTETCOUNT_GB); + mmc->mmc_tx_framecount_gb += readl(mmcaddr + MMC_TX_FRAMECOUNT_GB); + mmc->mmc_tx_broadcastframe_g += readl(mmcaddr + + MMC_TX_BROADCASTFRAME_G); + mmc->mmc_tx_multicastframe_g += readl(mmcaddr + + MMC_TX_MULTICASTFRAME_G); + mmc->mmc_tx_64_octets_gb += readl(mmcaddr + MMC_TX_64_OCTETS_GB); mmc->mmc_tx_65_to_127_octets_gb += - readl(ioaddr + MMC_TX_65_TO_127_OCTETS_GB); + readl(mmcaddr + MMC_TX_65_TO_127_OCTETS_GB); mmc->mmc_tx_128_to_255_octets_gb += - readl(ioaddr + MMC_TX_128_TO_255_OCTETS_GB); + readl(mmcaddr + MMC_TX_128_TO_255_OCTETS_GB); mmc->mmc_tx_256_to_511_octets_gb += - readl(ioaddr + MMC_TX_256_TO_511_OCTETS_GB); + readl(mmcaddr + MMC_TX_256_TO_511_OCTETS_GB); mmc->mmc_tx_512_to_1023_octets_gb += - readl(ioaddr + MMC_TX_512_TO_1023_OCTETS_GB); + readl(mmcaddr + MMC_TX_512_TO_1023_OCTETS_GB); mmc->mmc_tx_1024_to_max_octets_gb += - readl(ioaddr + MMC_TX_1024_TO_MAX_OCTETS_GB); - mmc->mmc_tx_unicast_gb += readl(ioaddr + MMC_TX_UNICAST_GB); - mmc->mmc_tx_multicast_gb += readl(ioaddr + MMC_TX_MULTICAST_GB); - mmc->mmc_tx_broadcast_gb += readl(ioaddr + MMC_TX_BROADCAST_GB); - mmc->mmc_tx_underflow_error += readl(ioaddr + MMC_TX_UNDERFLOW_ERROR); - mmc->mmc_tx_singlecol_g += readl(ioaddr + MMC_TX_SINGLECOL_G); - mmc->mmc_tx_multicol_g += readl(ioaddr + MMC_TX_MULTICOL_G); - mmc->mmc_tx_deferred += readl(ioaddr + MMC_TX_DEFERRED); - mmc->mmc_tx_latecol += readl(ioaddr + MMC_TX_LATECOL); - mmc->mmc_tx_exesscol += readl(ioaddr + MMC_TX_EXESSCOL); - mmc->mmc_tx_carrier_error += readl(ioaddr + MMC_TX_CARRIER_ERROR); - mmc->mmc_tx_octetcount_g += readl(ioaddr + MMC_TX_OCTETCOUNT_G); - mmc->mmc_tx_framecount_g += readl(ioaddr + MMC_TX_FRAMECOUNT_G); - mmc->mmc_tx_excessdef += readl(ioaddr + MMC_TX_EXCESSDEF); - mmc->mmc_tx_pause_frame += readl(ioaddr + MMC_TX_PAUSE_FRAME); - mmc->mmc_tx_vlan_frame_g += readl(ioaddr + MMC_TX_VLAN_FRAME_G); + readl(mmcaddr + MMC_TX_1024_TO_MAX_OCTETS_GB); + mmc->mmc_tx_unicast_gb += readl(mmcaddr + MMC_TX_UNICAST_GB); + mmc->mmc_tx_multicast_gb += readl(mmcaddr + MMC_TX_MULTICAST_GB); + mmc->mmc_tx_broadcast_gb += readl(mmcaddr + MMC_TX_BROADCAST_GB); + mmc->mmc_tx_underflow_error += readl(mmcaddr + MMC_TX_UNDERFLOW_ERROR); + mmc->mmc_tx_singlecol_g += readl(mmcaddr + MMC_TX_SINGLECOL_G); + mmc->mmc_tx_multicol_g += readl(mmcaddr + MMC_TX_MULTICOL_G); + mmc->mmc_tx_deferred += readl(mmcaddr + MMC_TX_DEFERRED); + mmc->mmc_tx_latecol += readl(mmcaddr + MMC_TX_LATECOL); + mmc->mmc_tx_exesscol += readl(mmcaddr + MMC_TX_EXESSCOL); + mmc->mmc_tx_carrier_error += readl(mmcaddr + MMC_TX_CARRIER_ERROR); + mmc->mmc_tx_octetcount_g += readl(mmcaddr + MMC_TX_OCTETCOUNT_G); + mmc->mmc_tx_framecount_g += readl(mmcaddr + MMC_TX_FRAMECOUNT_G); + mmc->mmc_tx_excessdef += readl(mmcaddr + MMC_TX_EXCESSDEF); + mmc->mmc_tx_pause_frame += readl(mmcaddr + MMC_TX_PAUSE_FRAME); + mmc->mmc_tx_vlan_frame_g += readl(mmcaddr + MMC_TX_VLAN_FRAME_G); /* MMC RX counter registers */ - mmc->mmc_rx_framecount_gb += readl(ioaddr + MMC_RX_FRAMECOUNT_GB); - mmc->mmc_rx_octetcount_gb += readl(ioaddr + MMC_RX_OCTETCOUNT_GB); - mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G); - mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G); - mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G); - mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERROR); - mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR); - mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR); - mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR); - mmc->mmc_rx_undersize_g += readl(ioaddr + MMC_RX_UNDERSIZE_G); - mmc->mmc_rx_oversize_g += readl(ioaddr + MMC_RX_OVERSIZE_G); - mmc->mmc_rx_64_octets_gb += readl(ioaddr + MMC_RX_64_OCTETS_GB); + mmc->mmc_rx_framecount_gb += readl(mmcaddr + MMC_RX_FRAMECOUNT_GB); + mmc->mmc_rx_octetcount_gb += readl(mmcaddr + MMC_RX_OCTETCOUNT_GB); + mmc->mmc_rx_octetcount_g += readl(mmcaddr + MMC_RX_OCTETCOUNT_G); + mmc->mmc_rx_broadcastframe_g += readl(mmcaddr + + MMC_RX_BROADCASTFRAME_G); + mmc->mmc_rx_multicastframe_g += readl(mmcaddr + + MMC_RX_MULTICASTFRAME_G); + mmc->mmc_rx_crc_error += readl(mmcaddr + MMC_RX_CRC_ERROR); + mmc->mmc_rx_align_error += readl(mmcaddr + MMC_RX_ALIGN_ERROR); + mmc->mmc_rx_run_error += readl(mmcaddr + MMC_RX_RUN_ERROR); + mmc->mmc_rx_jabber_error += readl(mmcaddr + MMC_RX_JABBER_ERROR); + mmc->mmc_rx_undersize_g += readl(mmcaddr + MMC_RX_UNDERSIZE_G); + mmc->mmc_rx_oversize_g += readl(mmcaddr + MMC_RX_OVERSIZE_G); + mmc->mmc_rx_64_octets_gb += readl(mmcaddr + MMC_RX_64_OCTETS_GB); mmc->mmc_rx_65_to_127_octets_gb += - readl(ioaddr + MMC_RX_65_TO_127_OCTETS_GB); + readl(mmcaddr + MMC_RX_65_TO_127_OCTETS_GB); mmc->mmc_rx_128_to_255_octets_gb += - readl(ioaddr + MMC_RX_128_TO_255_OCTETS_GB); + readl(mmcaddr + MMC_RX_128_TO_255_OCTETS_GB); mmc->mmc_rx_256_to_511_octets_gb += - readl(ioaddr + MMC_RX_256_TO_511_OCTETS_GB); + readl(mmcaddr + MMC_RX_256_TO_511_OCTETS_GB); mmc->mmc_rx_512_to_1023_octets_gb += - readl(ioaddr + MMC_RX_512_TO_1023_OCTETS_GB); + readl(mmcaddr + MMC_RX_512_TO_1023_OCTETS_GB); mmc->mmc_rx_1024_to_max_octets_gb += - readl(ioaddr + MMC_RX_1024_TO_MAX_OCTETS_GB); - mmc->mmc_rx_unicast_g += readl(ioaddr + MMC_RX_UNICAST_G); - mmc->mmc_rx_length_error += readl(ioaddr + MMC_RX_LENGTH_ERROR); - mmc->mmc_rx_autofrangetype += readl(ioaddr + MMC_RX_AUTOFRANGETYPE); - mmc->mmc_rx_pause_frames += readl(ioaddr + MMC_RX_PAUSE_FRAMES); - mmc->mmc_rx_fifo_overflow += readl(ioaddr + MMC_RX_FIFO_OVERFLOW); - mmc->mmc_rx_vlan_frames_gb += readl(ioaddr + MMC_RX_VLAN_FRAMES_GB); - mmc->mmc_rx_watchdog_error += readl(ioaddr + MMC_RX_WATCHDOG_ERROR); + readl(mmcaddr + MMC_RX_1024_TO_MAX_OCTETS_GB); + mmc->mmc_rx_unicast_g += readl(mmcaddr + MMC_RX_UNICAST_G); + mmc->mmc_rx_length_error += readl(mmcaddr + MMC_RX_LENGTH_ERROR); + mmc->mmc_rx_autofrangetype += readl(mmcaddr + MMC_RX_AUTOFRANGETYPE); + mmc->mmc_rx_pause_frames += readl(mmcaddr + MMC_RX_PAUSE_FRAMES); + mmc->mmc_rx_fifo_overflow += readl(mmcaddr + MMC_RX_FIFO_OVERFLOW); + mmc->mmc_rx_vlan_frames_gb += readl(mmcaddr + MMC_RX_VLAN_FRAMES_GB); + mmc->mmc_rx_watchdog_error += readl(mmcaddr + MMC_RX_WATCHDOG_ERROR); /* IPC */ - mmc->mmc_rx_ipc_intr_mask += readl(ioaddr + MMC_RX_IPC_INTR_MASK); - mmc->mmc_rx_ipc_intr += readl(ioaddr + MMC_RX_IPC_INTR); + mmc->mmc_rx_ipc_intr_mask += readl(mmcaddr + MMC_RX_IPC_INTR_MASK); + mmc->mmc_rx_ipc_intr += readl(mmcaddr + MMC_RX_IPC_INTR); /* IPv4 */ - mmc->mmc_rx_ipv4_gd += readl(ioaddr + MMC_RX_IPV4_GD); - mmc->mmc_rx_ipv4_hderr += readl(ioaddr + MMC_RX_IPV4_HDERR); - mmc->mmc_rx_ipv4_nopay += readl(ioaddr + MMC_RX_IPV4_NOPAY); - mmc->mmc_rx_ipv4_frag += readl(ioaddr + MMC_RX_IPV4_FRAG); - mmc->mmc_rx_ipv4_udsbl += readl(ioaddr + MMC_RX_IPV4_UDSBL); + mmc->mmc_rx_ipv4_gd += readl(mmcaddr + MMC_RX_IPV4_GD); + mmc->mmc_rx_ipv4_hderr += readl(mmcaddr + MMC_RX_IPV4_HDERR); + mmc->mmc_rx_ipv4_nopay += readl(mmcaddr + MMC_RX_IPV4_NOPAY); + mmc->mmc_rx_ipv4_frag += readl(mmcaddr + MMC_RX_IPV4_FRAG); + mmc->mmc_rx_ipv4_udsbl += readl(mmcaddr + MMC_RX_IPV4_UDSBL); - mmc->mmc_rx_ipv4_gd_octets += readl(ioaddr + MMC_RX_IPV4_GD_OCTETS); + mmc->mmc_rx_ipv4_gd_octets += readl(mmcaddr + MMC_RX_IPV4_GD_OCTETS); mmc->mmc_rx_ipv4_hderr_octets += - readl(ioaddr + MMC_RX_IPV4_HDERR_OCTETS); + readl(mmcaddr + MMC_RX_IPV4_HDERR_OCTETS); mmc->mmc_rx_ipv4_nopay_octets += - readl(ioaddr + MMC_RX_IPV4_NOPAY_OCTETS); - mmc->mmc_rx_ipv4_frag_octets += readl(ioaddr + MMC_RX_IPV4_FRAG_OCTETS); + readl(mmcaddr + MMC_RX_IPV4_NOPAY_OCTETS); + mmc->mmc_rx_ipv4_frag_octets += readl(mmcaddr + + MMC_RX_IPV4_FRAG_OCTETS); mmc->mmc_rx_ipv4_udsbl_octets += - readl(ioaddr + MMC_RX_IPV4_UDSBL_OCTETS); + readl(mmcaddr + MMC_RX_IPV4_UDSBL_OCTETS); /* IPV6 */ - mmc->mmc_rx_ipv6_gd_octets += readl(ioaddr + MMC_RX_IPV6_GD_OCTETS); + mmc->mmc_rx_ipv6_gd_octets += readl(mmcaddr + MMC_RX_IPV6_GD_OCTETS); mmc->mmc_rx_ipv6_hderr_octets += - readl(ioaddr + MMC_RX_IPV6_HDERR_OCTETS); + readl(mmcaddr + MMC_RX_IPV6_HDERR_OCTETS); mmc->mmc_rx_ipv6_nopay_octets += - readl(ioaddr + MMC_RX_IPV6_NOPAY_OCTETS); + readl(mmcaddr + MMC_RX_IPV6_NOPAY_OCTETS); - mmc->mmc_rx_ipv6_gd += readl(ioaddr + MMC_RX_IPV6_GD); - mmc->mmc_rx_ipv6_hderr += readl(ioaddr + MMC_RX_IPV6_HDERR); - mmc->mmc_rx_ipv6_nopay += readl(ioaddr + MMC_RX_IPV6_NOPAY); + mmc->mmc_rx_ipv6_gd += readl(mmcaddr + MMC_RX_IPV6_GD); + mmc->mmc_rx_ipv6_hderr += readl(mmcaddr + MMC_RX_IPV6_HDERR); + mmc->mmc_rx_ipv6_nopay += readl(mmcaddr + MMC_RX_IPV6_NOPAY); /* Protocols */ - mmc->mmc_rx_udp_gd += readl(ioaddr + MMC_RX_UDP_GD); - mmc->mmc_rx_udp_err += readl(ioaddr + MMC_RX_UDP_ERR); - mmc->mmc_rx_tcp_gd += readl(ioaddr + MMC_RX_TCP_GD); - mmc->mmc_rx_tcp_err += readl(ioaddr + MMC_RX_TCP_ERR); - mmc->mmc_rx_icmp_gd += readl(ioaddr + MMC_RX_ICMP_GD); - mmc->mmc_rx_icmp_err += readl(ioaddr + MMC_RX_ICMP_ERR); + mmc->mmc_rx_udp_gd += readl(mmcaddr + MMC_RX_UDP_GD); + mmc->mmc_rx_udp_err += readl(mmcaddr + MMC_RX_UDP_ERR); + mmc->mmc_rx_tcp_gd += readl(mmcaddr + MMC_RX_TCP_GD); + mmc->mmc_rx_tcp_err += readl(mmcaddr + MMC_RX_TCP_ERR); + mmc->mmc_rx_icmp_gd += readl(mmcaddr + MMC_RX_ICMP_GD); + mmc->mmc_rx_icmp_err += readl(mmcaddr + MMC_RX_ICMP_ERR); - mmc->mmc_rx_udp_gd_octets += readl(ioaddr + MMC_RX_UDP_GD_OCTETS); - mmc->mmc_rx_udp_err_octets += readl(ioaddr + MMC_RX_UDP_ERR_OCTETS); - mmc->mmc_rx_tcp_gd_octets += readl(ioaddr + MMC_RX_TCP_GD_OCTETS); - mmc->mmc_rx_tcp_err_octets += readl(ioaddr + MMC_RX_TCP_ERR_OCTETS); - mmc->mmc_rx_icmp_gd_octets += readl(ioaddr + MMC_RX_ICMP_GD_OCTETS); - mmc->mmc_rx_icmp_err_octets += readl(ioaddr + MMC_RX_ICMP_ERR_OCTETS); + mmc->mmc_rx_udp_gd_octets += readl(mmcaddr + MMC_RX_UDP_GD_OCTETS); + mmc->mmc_rx_udp_err_octets += readl(mmcaddr + MMC_RX_UDP_ERR_OCTETS); + mmc->mmc_rx_tcp_gd_octets += readl(mmcaddr + MMC_RX_TCP_GD_OCTETS); + mmc->mmc_rx_tcp_err_octets += readl(mmcaddr + MMC_RX_TCP_ERR_OCTETS); + mmc->mmc_rx_icmp_gd_octets += readl(mmcaddr + MMC_RX_ICMP_GD_OCTETS); + mmc->mmc_rx_icmp_err_octets += readl(mmcaddr + MMC_RX_ICMP_ERR_OCTETS); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 8bbab97895fe..26fb85531a61 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -128,6 +128,7 @@ struct stmmac_priv { int use_riwt; int irq_wake; spinlock_t ptp_lock; + void __iomem *mmcaddr; #ifdef CONFIG_DEBUG_FS struct dentry *dbgfs_dir; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 3c7928edfebb..fb2e7fc85ca7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -506,7 +506,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, else { /* If supported, for new GMAC chips expose the MMC counters */ if (priv->dma_cap.rmon) { - dwmac_mmc_read(priv->ioaddr, &priv->mmc); + dwmac_mmc_read(priv->mmcaddr, &priv->mmc); for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) { char *p; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 1186ac902bec..00e508498a81 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1450,12 +1450,14 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) static void stmmac_mmc_setup(struct stmmac_priv *priv) { unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | - MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; + MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; - dwmac_mmc_intr_all_mask(priv->ioaddr); + priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET; + + dwmac_mmc_intr_all_mask(priv->mmcaddr); if (priv->dma_cap.rmon) { - dwmac_mmc_ctrl(priv->ioaddr, mode); + dwmac_mmc_ctrl(priv->mmcaddr, mode); memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); } else pr_info(" No MAC Management Counters available\n"); -- GitLab From ee2ae1ed46251dcbdcc2c59b5e30f664ddfbacb1 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:33 +0200 Subject: [PATCH 1120/9938] stmmac: add new DT platform entries for GMAC4 This is to support the snps,dwmac-4.00 and snps,dwmac-4.10a and related features on the platform driver. See binding doc for further details. Signed-off-by: Giuseppe Cavallaro Signed-off-by: Alexandre TORGUE Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/stmmac.txt | 2 ++ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 7 +++++++ include/linux/stmmac.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt index 6605d19601c2..4d302db657c0 100644 --- a/Documentation/devicetree/bindings/net/stmmac.txt +++ b/Documentation/devicetree/bindings/net/stmmac.txt @@ -59,6 +59,8 @@ Optional properties: - snps,fb: fixed-burst - snps,mb: mixed-burst - snps,rb: rebuild INCRx Burst + - snps,tso: this enables the TSO feature otherwise it will be managed by + MAC HW capability register. - mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus. Examples: diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index cf37ea558ecc..effaa4ff5ab7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -284,6 +284,13 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) plat->pmt = 1; } + if (of_device_is_compatible(np, "snps,dwmac-4.00") || + of_device_is_compatible(np, "snps,dwmac-4.10a")) { + plat->has_gmac4 = 1; + plat->pmt = 1; + plat->tso_en = of_property_read_bool(np, "snps,tso"); + } + if (of_device_is_compatible(np, "snps,dwmac-3.610") || of_device_is_compatible(np, "snps,dwmac-3.710")) { plat->enh_desc = 1; diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index e6bc30a42a74..ffdaca9c01af 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -137,5 +137,7 @@ struct plat_stmmacenet_data { void (*exit)(struct platform_device *pdev, void *priv); void *bsp_priv; struct stmmac_axi *axi; + int has_gmac4; + bool tso_en; }; #endif -- GitLab From f748be531d7012c456b97f66091d86b3675c5fef Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:34 +0200 Subject: [PATCH 1121/9938] stmmac: support new GMAC4 This patch adds the whole GMAC4 support inside the stmmac d.d. now able to use the new HW and some new features i.e.: TSO. It is missing the multi-queue and split Header support at this stage. This patch also updates the driver version and the stmmac.txt. Signed-off-by: Alexandre TORGUE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 4 + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 6 +- .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 5 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 483 ++++++++++++++++-- 4 files changed, 444 insertions(+), 54 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index eabe86bd8f56..fc60368df2e7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -169,6 +169,9 @@ struct stmmac_extra_stats { unsigned long mtl_rx_fifo_ctrl_active; unsigned long mac_rx_frame_ctrl_fifo; unsigned long mac_gmii_rx_proto_engine; + /* TSO */ + unsigned long tx_tso_frames; + unsigned long tx_tso_nfrags; }; /* CSR Frequency Access Defines*/ @@ -545,6 +548,7 @@ void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable); void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); extern const struct stmmac_mode_ops ring_mode_ops; extern const struct stmmac_mode_ops chain_mode_ops; +extern const struct stmmac_desc_ops dwmac4_desc_ops; /** * stmmac_get_synopsys_id - return the SYINID. diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 26fb85531a61..317ce3580e13 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -24,7 +24,7 @@ #define __STMMAC_H__ #define STMMAC_RESOURCE_NAME "stmmaceth" -#define DRV_MODULE_VERSION "Oct_2015" +#define DRV_MODULE_VERSION "Dec_2015" #include #include @@ -67,6 +67,7 @@ struct stmmac_priv { spinlock_t tx_lock; bool tx_path_in_lpi_mode; struct timer_list txtimer; + bool tso; struct dma_desc *dma_rx ____cacheline_aligned_in_smp; struct dma_extended_desc *dma_erx; @@ -129,6 +130,9 @@ struct stmmac_priv { int irq_wake; spinlock_t ptp_lock; void __iomem *mmcaddr; + u32 rx_tail_addr; + u32 tx_tail_addr; + u32 mss; #ifdef CONFIG_DEBUG_FS struct dentry *dbgfs_dir; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index fb2e7fc85ca7..e2b98b01647e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -161,6 +161,9 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { STMMAC_STAT(mtl_rx_fifo_ctrl_active), STMMAC_STAT(mac_rx_frame_ctrl_fifo), STMMAC_STAT(mac_gmii_rx_proto_engine), + /* TSO */ + STMMAC_STAT(tx_tso_frames), + STMMAC_STAT(tx_tso_nfrags), }; #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats) @@ -499,7 +502,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, int i, j = 0; /* Update the DMA HW counters for dwmac10/100 */ - if (!priv->plat->has_gmac) + if (priv->hw->dma->dma_diagnostic_fr) priv->hw->dma->dma_diagnostic_fr(&dev->stats, (void *) &priv->xstats, priv->ioaddr); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 00e508498a81..3a13ddd3aac1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -56,6 +56,7 @@ #include "dwmac1000.h" #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) +#define TSO_MAX_BUFF_SIZE (SZ_16K - 1) /* Module parameters */ #define TX_TIMEO 5000 @@ -725,13 +726,15 @@ static void stmmac_adjust_link(struct net_device *dev) new_state = 1; switch (phydev->speed) { case 1000: - if (likely(priv->plat->has_gmac)) + if (likely((priv->plat->has_gmac) || + (priv->plat->has_gmac4))) ctrl &= ~priv->hw->link.port; stmmac_hw_fix_mac_speed(priv); break; case 100: case 10: - if (priv->plat->has_gmac) { + if (likely((priv->plat->has_gmac) || + (priv->plat->has_gmac4))) { ctrl |= priv->hw->link.port; if (phydev->speed == SPEED_100) { ctrl |= priv->hw->link.speed; @@ -971,7 +974,10 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, return -EINVAL; } - p->des2 = priv->rx_skbuff_dma[i]; + if (priv->synopsys_id >= DWMAC_CORE_4_00) + p->des0 = priv->rx_skbuff_dma[i]; + else + p->des2 = priv->rx_skbuff_dma[i]; if ((priv->hw->mode->init_desc3) && (priv->dma_buf_sz == BUF_SIZE_16KiB)) @@ -1062,7 +1068,16 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) p = &((priv->dma_etx + i)->basic); else p = priv->dma_tx + i; - p->des2 = 0; + + if (priv->synopsys_id >= DWMAC_CORE_4_00) { + p->des0 = 0; + p->des1 = 0; + p->des2 = 0; + p->des3 = 0; + } else { + p->des2 = 0; + } + priv->tx_skbuff_dma[i].buf = 0; priv->tx_skbuff_dma[i].map_as_page = false; priv->tx_skbuff_dma[i].len = 0; @@ -1325,9 +1340,13 @@ static void stmmac_tx_clean(struct stmmac_priv *priv) priv->tx_skbuff_dma[entry].len, DMA_TO_DEVICE); priv->tx_skbuff_dma[entry].buf = 0; + priv->tx_skbuff_dma[entry].len = 0; priv->tx_skbuff_dma[entry].map_as_page = false; } - priv->hw->mode->clean_desc3(priv, p); + + if (priv->hw->mode->clean_desc3) + priv->hw->mode->clean_desc3(priv, p); + priv->tx_skbuff_dma[entry].last_segment = false; priv->tx_skbuff_dma[entry].is_jumbo = false; @@ -1452,7 +1471,10 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv) unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; - priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET; + if (priv->synopsys_id >= DWMAC_CORE_4_00) + priv->mmcaddr = priv->ioaddr + MMC_GMAC4_OFFSET; + else + priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET; dwmac_mmc_intr_all_mask(priv->mmcaddr); @@ -1564,8 +1586,19 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst, aal, priv->dma_tx_phy, priv->dma_rx_phy, atds); - if ((priv->synopsys_id >= DWMAC_CORE_3_50) && - (priv->plat->axi && priv->hw->dma->axi)) + if (priv->synopsys_id >= DWMAC_CORE_4_00) { + priv->rx_tail_addr = priv->dma_rx_phy + + (DMA_RX_SIZE * sizeof(struct dma_desc)); + priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, priv->rx_tail_addr, + STMMAC_CHAN0); + + priv->tx_tail_addr = priv->dma_tx_phy + + (DMA_TX_SIZE * sizeof(struct dma_desc)); + priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, + STMMAC_CHAN0); + } + + if (priv->plat->axi && priv->hw->dma->axi) priv->hw->dma->axi(priv->ioaddr, priv->plat->axi); return ret; @@ -1645,7 +1678,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) } /* Enable the MAC Rx/Tx */ - stmmac_set_mac(priv->ioaddr, true); + if (priv->synopsys_id >= DWMAC_CORE_4_00) + stmmac_dwmac4_set_mac(priv->ioaddr, true); + else + stmmac_set_mac(priv->ioaddr, true); /* Set the HW DMA mode and the COE */ stmmac_dma_operation_mode(priv); @@ -1683,6 +1719,18 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) if (priv->pcs && priv->hw->mac->ctrl_ane) priv->hw->mac->ctrl_ane(priv->hw, 0); + /* set TX ring length */ + if (priv->hw->dma->set_tx_ring_len) + priv->hw->dma->set_tx_ring_len(priv->ioaddr, + (DMA_TX_SIZE - 1)); + /* set RX ring length */ + if (priv->hw->dma->set_rx_ring_len) + priv->hw->dma->set_rx_ring_len(priv->ioaddr, + (DMA_RX_SIZE - 1)); + /* Enable TSO */ + if (priv->tso) + priv->hw->dma->enable_tso(priv->ioaddr, 1, STMMAC_CHAN0); + return 0; } @@ -1847,6 +1895,239 @@ static int stmmac_release(struct net_device *dev) return 0; } +/** + * stmmac_tso_allocator - close entry point of the driver + * @priv: driver private structure + * @des: buffer start address + * @total_len: total length to fill in descriptors + * @last_segmant: condition for the last descriptor + * Description: + * This function fills descriptor and request new descriptors according to + * buffer length to fill + */ +static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des, + int total_len, bool last_segment) +{ + struct dma_desc *desc; + int tmp_len; + u32 buff_size; + + tmp_len = total_len; + + while (tmp_len > 0) { + priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); + desc = priv->dma_tx + priv->cur_tx; + + desc->des0 = des + (total_len - tmp_len); + buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ? + TSO_MAX_BUFF_SIZE : tmp_len; + + priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size, + 0, 1, + (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE), + 0, 0); + + tmp_len -= TSO_MAX_BUFF_SIZE; + } +} + +/** + * stmmac_tso_xmit - Tx entry point of the driver for oversized frames (TSO) + * @skb : the socket buffer + * @dev : device pointer + * Description: this is the transmit function that is called on TSO frames + * (support available on GMAC4 and newer chips). + * Diagram below show the ring programming in case of TSO frames: + * + * First Descriptor + * -------- + * | DES0 |---> buffer1 = L2/L3/L4 header + * | DES1 |---> TCP Payload (can continue on next descr...) + * | DES2 |---> buffer 1 and 2 len + * | DES3 |---> must set TSE, TCP hdr len-> [22:19]. TCP payload len [17:0] + * -------- + * | + * ... + * | + * -------- + * | DES0 | --| Split TCP Payload on Buffers 1 and 2 + * | DES1 | --| + * | DES2 | --> buffer 1 and 2 len + * | DES3 | + * -------- + * + * mss is fixed when enable tso, so w/o programming the TDES3 ctx field. + */ +static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) +{ + u32 pay_len, mss; + int tmp_pay_len = 0; + struct stmmac_priv *priv = netdev_priv(dev); + int nfrags = skb_shinfo(skb)->nr_frags; + unsigned int first_entry, des; + struct dma_desc *desc, *first, *mss_desc = NULL; + u8 proto_hdr_len; + int i; + + spin_lock(&priv->tx_lock); + + /* Compute header lengths */ + proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + + /* Desc availability based on threshold should be enough safe */ + if (unlikely(stmmac_tx_avail(priv) < + (((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) { + if (!netif_queue_stopped(dev)) { + netif_stop_queue(dev); + /* This is a hard error, log it. */ + pr_err("%s: Tx Ring full when queue awake\n", __func__); + } + spin_unlock(&priv->tx_lock); + return NETDEV_TX_BUSY; + } + + pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */ + + mss = skb_shinfo(skb)->gso_size; + + /* set new MSS value if needed */ + if (mss != priv->mss) { + mss_desc = priv->dma_tx + priv->cur_tx; + priv->hw->desc->set_mss(mss_desc, mss); + priv->mss = mss; + priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); + } + + if (netif_msg_tx_queued(priv)) { + pr_info("%s: tcphdrlen %d, hdr_len %d, pay_len %d, mss %d\n", + __func__, tcp_hdrlen(skb), proto_hdr_len, pay_len, mss); + pr_info("\tskb->len %d, skb->data_len %d\n", skb->len, + skb->data_len); + } + + first_entry = priv->cur_tx; + + desc = priv->dma_tx + first_entry; + first = desc; + + /* first descriptor: fill Headers on Buf1 */ + des = dma_map_single(priv->device, skb->data, skb_headlen(skb), + DMA_TO_DEVICE); + if (dma_mapping_error(priv->device, des)) + goto dma_map_err; + + priv->tx_skbuff_dma[first_entry].buf = des; + priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb); + priv->tx_skbuff[first_entry] = skb; + + first->des0 = des; + + /* Fill start of payload in buff2 of first descriptor */ + if (pay_len) + first->des1 = des + proto_hdr_len; + + /* If needed take extra descriptors to fill the remaining payload */ + tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; + + stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0)); + + /* Prepare fragments */ + for (i = 0; i < nfrags; i++) { + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + des = skb_frag_dma_map(priv->device, frag, 0, + skb_frag_size(frag), + DMA_TO_DEVICE); + + stmmac_tso_allocator(priv, des, skb_frag_size(frag), + (i == nfrags - 1)); + + priv->tx_skbuff_dma[priv->cur_tx].buf = des; + priv->tx_skbuff_dma[priv->cur_tx].len = skb_frag_size(frag); + priv->tx_skbuff[priv->cur_tx] = NULL; + priv->tx_skbuff_dma[priv->cur_tx].map_as_page = true; + } + + priv->tx_skbuff_dma[priv->cur_tx].last_segment = true; + + priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); + + if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { + if (netif_msg_hw(priv)) + pr_debug("%s: stop transmitted packets\n", __func__); + netif_stop_queue(dev); + } + + dev->stats.tx_bytes += skb->len; + priv->xstats.tx_tso_frames++; + priv->xstats.tx_tso_nfrags += nfrags; + + /* Manage tx mitigation */ + priv->tx_count_frames += nfrags + 1; + if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { + mod_timer(&priv->txtimer, + STMMAC_COAL_TIMER(priv->tx_coal_timer)); + } else { + priv->tx_count_frames = 0; + priv->hw->desc->set_tx_ic(desc); + priv->xstats.tx_set_ic_bit++; + } + + if (!priv->hwts_tx_en) + skb_tx_timestamp(skb); + + if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && + priv->hwts_tx_en)) { + /* declare that device is doing timestamping */ + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + priv->hw->desc->enable_tx_timestamp(first); + } + + /* Complete the first descriptor before granting the DMA */ + priv->hw->desc->prepare_tso_tx_desc(first, 1, + proto_hdr_len, + pay_len, + 1, priv->tx_skbuff_dma[first_entry].last_segment, + tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len)); + + /* If context desc is used to change MSS */ + if (mss_desc) + priv->hw->desc->set_tx_owner(mss_desc); + + /* The own bit must be the latest setting done when prepare the + * descriptor and then barrier is needed to make sure that + * all is coherent before granting the DMA engine. + */ + smp_wmb(); + + if (netif_msg_pktdata(priv)) { + pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n", + __func__, priv->cur_tx, priv->dirty_tx, first_entry, + priv->cur_tx, first, nfrags); + + priv->hw->desc->display_ring((void *)priv->dma_tx, DMA_TX_SIZE, + 0); + + pr_info(">>> frame to be transmitted: "); + print_pkt(skb->data, skb_headlen(skb)); + } + + netdev_sent_queue(dev, skb->len); + + priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, + STMMAC_CHAN0); + + spin_unlock(&priv->tx_lock); + return NETDEV_TX_OK; + +dma_map_err: + spin_unlock(&priv->tx_lock); + dev_err(priv->device, "Tx dma map failed\n"); + dev_kfree_skb(skb); + priv->dev->stats.tx_dropped++; + return NETDEV_TX_OK; +} + /** * stmmac_xmit - Tx entry point of the driver * @skb : the socket buffer @@ -1864,6 +2145,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int entry, first_entry; struct dma_desc *desc, *first; unsigned int enh_desc; + unsigned int des; + + /* Manage oversized TCP frames for GMAC4 device */ + if (skb_is_gso(skb) && priv->tso) { + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + return stmmac_tso_xmit(skb, dev); + } spin_lock(&priv->tx_lock); @@ -1899,7 +2187,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) if (enh_desc) is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc); - if (unlikely(is_jumbo)) { + if (unlikely(is_jumbo) && likely(priv->synopsys_id < + DWMAC_CORE_4_00)) { entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion); if (unlikely(entry < 0)) goto dma_map_err; @@ -1917,13 +2206,21 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) else desc = priv->dma_tx + entry; - desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len, - DMA_TO_DEVICE); - if (dma_mapping_error(priv->device, desc->des2)) + des = skb_frag_dma_map(priv->device, frag, 0, len, + DMA_TO_DEVICE); + if (dma_mapping_error(priv->device, des)) goto dma_map_err; /* should reuse desc w/o issues */ priv->tx_skbuff[entry] = NULL; - priv->tx_skbuff_dma[entry].buf = desc->des2; + + if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { + desc->des0 = des; + priv->tx_skbuff_dma[entry].buf = desc->des0; + } else { + desc->des2 = des; + priv->tx_skbuff_dma[entry].buf = desc->des2; + } + priv->tx_skbuff_dma[entry].map_as_page = true; priv->tx_skbuff_dma[entry].len = len; priv->tx_skbuff_dma[entry].last_segment = last_segment; @@ -1988,12 +2285,19 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) if (likely(!is_jumbo)) { bool last_segment = (nfrags == 0); - first->des2 = dma_map_single(priv->device, skb->data, - nopaged_len, DMA_TO_DEVICE); - if (dma_mapping_error(priv->device, first->des2)) + des = dma_map_single(priv->device, skb->data, + nopaged_len, DMA_TO_DEVICE); + if (dma_mapping_error(priv->device, des)) goto dma_map_err; - priv->tx_skbuff_dma[first_entry].buf = first->des2; + if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { + first->des0 = des; + priv->tx_skbuff_dma[first_entry].buf = first->des0; + } else { + first->des2 = des; + priv->tx_skbuff_dma[first_entry].buf = first->des2; + } + priv->tx_skbuff_dma[first_entry].len = nopaged_len; priv->tx_skbuff_dma[first_entry].last_segment = last_segment; @@ -2017,7 +2321,12 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) } netdev_sent_queue(dev, skb->len); - priv->hw->dma->enable_dma_transmission(priv->ioaddr); + + if (priv->synopsys_id < DWMAC_CORE_4_00) + priv->hw->dma->enable_dma_transmission(priv->ioaddr); + else + priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, + STMMAC_CHAN0); spin_unlock(&priv->tx_lock); return NETDEV_TX_OK; @@ -2099,9 +2408,15 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) dev_kfree_skb(skb); break; } - p->des2 = priv->rx_skbuff_dma[entry]; - priv->hw->mode->refill_desc3(priv, p); + if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { + p->des0 = priv->rx_skbuff_dma[entry]; + p->des1 = 0; + } else { + p->des2 = priv->rx_skbuff_dma[entry]; + } + if (priv->hw->mode->refill_desc3) + priv->hw->mode->refill_desc3(priv, p); if (priv->rx_zeroc_thresh > 0) priv->rx_zeroc_thresh--; @@ -2109,9 +2424,13 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) if (netif_msg_rx_status(priv)) pr_debug("\trefill entry #%d\n", entry); } - wmb(); - priv->hw->desc->set_rx_owner(p); + + if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) + priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0); + else + priv->hw->desc->set_rx_owner(p); + wmb(); entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); @@ -2192,11 +2511,23 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) } else { struct sk_buff *skb; int frame_len; + unsigned int des; + + if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) + des = p->des0; + else + des = p->des2; frame_len = priv->hw->desc->get_rx_frame_len(p, coe); - /* check if frame_len fits the preallocated memory */ + /* If frame length is greather than skb buffer size + * (preallocated during init) then the packet is + * ignored + */ if (frame_len > priv->dma_buf_sz) { + pr_err("%s: len %d larger than size (%d)\n", + priv->dev->name, frame_len, + priv->dma_buf_sz); priv->dev->stats.rx_length_errors++; break; } @@ -2209,14 +2540,19 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) if (netif_msg_rx_status(priv)) { pr_debug("\tdesc: %p [entry %d] buff=0x%x\n", - p, entry, p->des2); + p, entry, des); if (frame_len > ETH_FRAME_LEN) pr_debug("\tframe size %d, COE: %d\n", frame_len, status); } - if (unlikely((frame_len < priv->rx_copybreak) || - stmmac_rx_threshold_count(priv))) { + /* The zero-copy is always used for all the sizes + * in case of GMAC4 because it needs + * to refill the used descriptors, always. + */ + if (unlikely(!priv->plat->has_gmac4 && + ((frame_len < priv->rx_copybreak) || + stmmac_rx_threshold_count(priv)))) { skb = netdev_alloc_skb_ip_align(priv->dev, frame_len); if (unlikely(!skb)) { @@ -2368,7 +2704,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) return -EBUSY; } - if (priv->plat->enh_desc) + if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00)) max_mtu = JUMBO_LEN; else max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); @@ -2382,6 +2718,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) } dev->mtu = new_mtu; + netdev_update_features(dev); return 0; @@ -2406,6 +2743,14 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev, if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) features &= ~NETIF_F_CSUM_MASK; + /* Disable tso if asked by ethtool */ + if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { + if (features & NETIF_F_TSO) + priv->tso = true; + else + priv->tso = false; + } + return features; } @@ -2452,7 +2797,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) } /* To handle GMAC own interrupts */ - if (priv->plat->has_gmac) { + if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) { int status = priv->hw->mac->host_irq_status(priv->hw, &priv->xstats); if (unlikely(status)) { @@ -2461,6 +2806,10 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) priv->tx_path_in_lpi_mode = true; if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) priv->tx_path_in_lpi_mode = false; + if (status & CORE_IRQ_MTL_RX_OVERFLOW) + priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, + priv->rx_tail_addr, + STMMAC_CHAN0); } } @@ -2533,15 +2882,14 @@ static void sysfs_display_ring(void *head, int size, int extend_desc, x = *(u64 *) ep; seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", i, (unsigned int)virt_to_phys(ep), - (unsigned int)x, (unsigned int)(x >> 32), + ep->basic.des0, ep->basic.des1, ep->basic.des2, ep->basic.des3); ep++; } else { x = *(u64 *) p; seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", i, (unsigned int)virt_to_phys(ep), - (unsigned int)x, (unsigned int)(x >> 32), - p->des2, p->des3); + p->des0, p->des1, p->des2, p->des3); p++; } seq_printf(seq, "\n"); @@ -2624,10 +2972,15 @@ static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); seq_printf(seq, "\tChecksum Offload in TX: %s\n", (priv->dma_cap.tx_coe) ? "Y" : "N"); - seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", - (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); - seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", - (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); + if (priv->synopsys_id >= DWMAC_CORE_4_00) { + seq_printf(seq, "\tIP Checksum Offload in RX: %s\n", + (priv->dma_cap.rx_coe) ? "Y" : "N"); + } else { + seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", + (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); + seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", + (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); + } seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); seq_printf(seq, "\tNumber of Additional RX channel: %d\n", @@ -2738,6 +3091,12 @@ static int stmmac_hw_init(struct stmmac_priv *priv) priv->plat->multicast_filter_bins, priv->plat->unicast_filter_entries, &priv->synopsys_id); + } else if (priv->plat->has_gmac4) { + priv->dev->priv_flags |= IFF_UNICAST_FLT; + mac = dwmac4_setup(priv->ioaddr, + priv->plat->multicast_filter_bins, + priv->plat->unicast_filter_entries, + &priv->synopsys_id); } else { mac = dwmac100_setup(priv->ioaddr, &priv->synopsys_id); } @@ -2747,14 +3106,18 @@ static int stmmac_hw_init(struct stmmac_priv *priv) priv->hw = mac; /* To use the chained or ring mode */ - if (chain_mode) { - priv->hw->mode = &chain_mode_ops; - pr_info(" Chain mode enabled\n"); - priv->mode = STMMAC_CHAIN_MODE; + if (priv->synopsys_id >= DWMAC_CORE_4_00) { + priv->hw->mode = &dwmac4_ring_mode_ops; } else { - priv->hw->mode = &ring_mode_ops; - pr_info(" Ring mode enabled\n"); - priv->mode = STMMAC_RING_MODE; + if (chain_mode) { + priv->hw->mode = &chain_mode_ops; + pr_info(" Chain mode enabled\n"); + priv->mode = STMMAC_CHAIN_MODE; + } else { + priv->hw->mode = &ring_mode_ops; + pr_info(" Ring mode enabled\n"); + priv->mode = STMMAC_RING_MODE; + } } /* Get the HW capability (new GMAC newer than 3.50a) */ @@ -2770,11 +3133,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv) priv->plat->enh_desc = priv->dma_cap.enh_desc; priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; - /* TXCOE doesn't work in thresh DMA mode */ - if (priv->plat->force_thresh_dma_mode) - priv->plat->tx_coe = 0; - else - priv->plat->tx_coe = priv->dma_cap.tx_coe; + priv->plat->tx_coe = priv->dma_cap.tx_coe; + /* In case of GMAC4 rx_coe is from HW cap register. */ + priv->plat->rx_coe = priv->dma_cap.rx_coe; if (priv->dma_cap.rx_coe_type2) priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; @@ -2784,13 +3145,17 @@ static int stmmac_hw_init(struct stmmac_priv *priv) } else pr_info(" No HW DMA feature register supported"); - /* To use alternate (extended) or normal descriptor structures */ - stmmac_selec_desc_mode(priv); + /* To use alternate (extended), normal or GMAC4 descriptor structures */ + if (priv->synopsys_id >= DWMAC_CORE_4_00) + priv->hw->desc = &dwmac4_desc_ops; + else + stmmac_selec_desc_mode(priv); if (priv->plat->rx_coe) { priv->hw->rx_csum = priv->plat->rx_coe; - pr_info(" RX Checksum Offload Engine supported (type %d)\n", - priv->plat->rx_coe); + pr_info(" RX Checksum Offload Engine supported\n"); + if (priv->synopsys_id < DWMAC_CORE_4_00) + pr_info("\tCOE Type %d\n", priv->hw->rx_csum); } if (priv->plat->tx_coe) pr_info(" TX Checksum insertion supported\n"); @@ -2800,6 +3165,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv) device_set_wakeup_capable(priv->device, 1); } + if (priv->dma_cap.tsoen) + pr_info(" TSO supported\n"); + return 0; } @@ -2903,6 +3271,12 @@ int stmmac_dvr_probe(struct device *device, ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; + + if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { + ndev->hw_features |= NETIF_F_TSO; + priv->tso = true; + pr_info(" TSO feature enabled\n"); + } ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; ndev->watchdog_timeo = msecs_to_jiffies(watchdog); #ifdef STMMAC_VLAN_TAG_USED @@ -3097,6 +3471,11 @@ int stmmac_resume(struct net_device *ndev) priv->dirty_rx = 0; priv->dirty_tx = 0; priv->cur_tx = 0; + /* reset private mss value to force mss context settings at + * next tso xmit (only used for gmac4). + */ + priv->mss = 0; + stmmac_clear_descriptors(priv); stmmac_hw_setup(ndev, false); -- GitLab From 0b7a43d37633614113ac54af73c193862dff4e50 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:35 +0200 Subject: [PATCH 1122/9938] Documentation: networking: update stmmac Update stmmac driver documentation according to new GMAC 4.x family. Signed-off-by: Alexandre TORGUE Signed-off-by: David S. Miller --- Documentation/networking/stmmac.txt | 44 +++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt index d64a14714236..671fe3dd56d3 100644 --- a/Documentation/networking/stmmac.txt +++ b/Documentation/networking/stmmac.txt @@ -1,6 +1,6 @@ STMicroelectronics 10/100/1000 Synopsys Ethernet driver -Copyright (C) 2007-2014 STMicroelectronics Ltd +Copyright (C) 2007-2015 STMicroelectronics Ltd Author: Giuseppe Cavallaro This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers @@ -138,6 +138,8 @@ struct plat_stmmacenet_data { int (*init)(struct platform_device *pdev, void *priv); void (*exit)(struct platform_device *pdev, void *priv); void *bsp_priv; + int has_gmac4; + bool tso_en; }; Where: @@ -181,6 +183,8 @@ Where: registers. init/exit callbacks should not use or modify platform data. o bsp_priv: another private pointer. + o has_gmac4: uses GMAC4 core. + o tso_en: Enables TSO (TCP Segmentation Offload) feature. For MDIO bus The we have: @@ -278,6 +282,13 @@ Please see the following document: o stmmac_ethtool.c: to implement the ethtool support; o stmmac.h: private driver structure; o common.h: common definitions and VFTs; + o mmc_core.c/mmc.h: Management MAC Counters; + o stmmac_hwtstamp.c: HW timestamp support for PTP; + o stmmac_ptp.c: PTP 1588 clock; + o dwmac-.c: these are for the platform glue-logic file; e.g. dwmac-sti.c + for STMicroelectronics SoCs. + +- GMAC 3.x o descs.h: descriptor structure definitions; o dwmac1000_core.c: dwmac GiGa core functions; o dwmac1000_dma.c: dma functions for the GMAC chip; @@ -289,11 +300,32 @@ Please see the following document: o enh_desc.c: functions for handling enhanced descriptors; o norm_desc.c: functions for handling normal descriptors; o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes; - o mmc_core.c/mmc.h: Management MAC Counters; - o stmmac_hwtstamp.c: HW timestamp support for PTP; - o stmmac_ptp.c: PTP 1588 clock; - o dwmac-.c: these are for the platform glue-logic file; e.g. dwmac-sti.c - for STMicroelectronics SoCs. + +- GMAC4.x generation + o dwmac4_core.c: dwmac GMAC4.x core functions; + o dwmac4_desc.c: functions for handling GMAC4.x descriptors; + o dwmac4_descs.h: descriptor definitions; + o dwmac4_dma.c: dma functions for the GMAC4.x chip; + o dwmac4_dma.h: dma definitions for the GMAC4.x chip; + o dwmac4.h: core definitions for the GMAC4.x chip; + o dwmac4_lib.c: generic GMAC4.x functions; + +4.12) TSO support (GMAC4.x) + +TSO (Tcp Segmentation Offload) feature is supported by GMAC 4.x chip family. +When a packet is sent through TCP protocol, the TCP stack ensures that +the SKB provided to the low level driver (stmmac in our case) matches with +the maximum frame len (IP header + TCP header + payload <= 1500 bytes (for +MTU set to 1500)). It means that if an application using TCP want to send a +packet which will have a length (after adding headers) > 1514 the packet +will be split in several TCP packets: The data payload is split and headers +(TCP/IP ..) are added. It is done by software. + +When TSO is enabled, the TCP stack doesn't care about the maximum frame +length and provide SKB packet to stmmac as it is. The GMAC IP will have to +perform the segmentation by it self to match with maximum frame length. + +This feature can be enabled in device tree through "snps,tso" entry. 5) Debug Information -- GitLab From 06bce7dd1507c9b943fb20c845e02c6f4c172a55 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:36 +0200 Subject: [PATCH 1123/9938] stmmac: update version to Jan_2016 This patch just updates the driver to the version fully tested on STi platforms. This version is Jan_2016. Signed-off-by: Alexandre TORGUE Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 317ce3580e13..ff6750621ff7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -24,7 +24,7 @@ #define __STMMAC_H__ #define STMMAC_RESOURCE_NAME "stmmaceth" -#define DRV_MODULE_VERSION "Dec_2015" +#define DRV_MODULE_VERSION "Jan_2016" #include #include -- GitLab From 91979b9db86340d7cd49392a498663fb1ac74639 Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 1 Apr 2016 11:37:37 +0200 Subject: [PATCH 1124/9938] stmmac: update MAINTAINERS Signed-off-by: Alexandre TORGUE Signed-off-by: David S. Miller --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7ba7bc485d74..67d99dd0e2e5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3348,6 +3348,7 @@ F: Documentation/powerpc/cxlflash.txt STMMAC ETHERNET DRIVER M: Giuseppe Cavallaro +M: Alexandre Torgue L: netdev@vger.kernel.org W: http://www.stlinux.com S: Supported -- GitLab From 91307cbeca7fd372342aaea7e814a19156ee8e64 Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 24 Mar 2016 17:06:01 +0100 Subject: [PATCH 1125/9938] iio: potentiometer: mcp4531: use pointer to access model parameters Use const pointer to element from model configuration array rather then array index, as it will not change anyway. Signed-off-by: Slawomir Stepien Signed-off-by: Peter Rosin Signed-off-by: Jonathan Cameron --- drivers/iio/potentiometer/mcp4531.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c index 0db67fe14766..3b72e1a595db 100644 --- a/drivers/iio/potentiometer/mcp4531.c +++ b/drivers/iio/potentiometer/mcp4531.c @@ -79,7 +79,7 @@ static const struct mcp4531_cfg mcp4531_cfg[] = { struct mcp4531_data { struct i2c_client *client; - unsigned long devid; + const struct mcp4531_cfg *cfg; }; #define MCP4531_CHANNEL(ch) { \ @@ -113,8 +113,8 @@ static int mcp4531_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 1000 * mcp4531_cfg[data->devid].kohms; - *val2 = mcp4531_cfg[data->devid].max_pos; + *val = 1000 * data->cfg->kohms; + *val2 = data->cfg->max_pos; return IIO_VAL_FRACTIONAL; } @@ -130,7 +130,7 @@ static int mcp4531_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (val > mcp4531_cfg[data->devid].max_pos || val < 0) + if (val > data->cfg->max_pos || val < 0) return -EINVAL; break; default: @@ -152,7 +152,6 @@ static int mcp4531_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; - unsigned long devid = id->driver_data; struct mcp4531_data *data; struct iio_dev *indio_dev; @@ -168,12 +167,12 @@ static int mcp4531_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - data->devid = devid; + data->cfg = &mcp4531_cfg[id->driver_data]; indio_dev->dev.parent = dev; indio_dev->info = &mcp4531_info; indio_dev->channels = mcp4531_channels; - indio_dev->num_channels = mcp4531_cfg[devid].wipers; + indio_dev->num_channels = data->cfg->wipers; indio_dev->name = client->name; return devm_iio_device_register(dev, indio_dev); -- GitLab From 23e758b36898d5ff6cc0cd2e54c498b24a15b0dd Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 24 Mar 2016 11:29:26 +0200 Subject: [PATCH 1126/9938] iio: accel: bmc150: use available_scan_masks Use available_scan_masks to allow the iio core to select the data to send to userspace depending on which axes are enabled, instead of doing this in the driver's interrupt handler. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index c73331f7782b..cc52366ad4ad 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -138,6 +138,7 @@ enum bmc150_accel_axis { AXIS_X, AXIS_Y, AXIS_Z, + AXIS_MAX, }; enum bmc150_power_modes { @@ -1104,6 +1105,10 @@ static const struct iio_info bmc150_accel_info_fifo = { .driver_module = THIS_MODULE, }; +static const unsigned long bmc150_accel_scan_masks[] = { + BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), + 0}; + static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -1113,8 +1118,7 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p) unsigned int raw_val; mutex_lock(&data->mutex); - for_each_set_bit(bit, indio_dev->active_scan_mask, - indio_dev->masklength) { + for (bit = 0; bit < AXIS_MAX; bit++) { ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val, 2); @@ -1574,6 +1578,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->num_channels; indio_dev->name = name ? name : data->chip_info->name; + indio_dev->available_scan_masks = bmc150_accel_scan_masks; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &bmc150_accel_info; -- GitLab From 1715e0ccd3b8cd4c1ee76076e1e7452b113be193 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 24 Mar 2016 11:29:27 +0200 Subject: [PATCH 1127/9938] iio: accel: bmc150: optimize transfers in trigger handler Some i2c busses (e.g.: Synopsys DesignWare I2C adapter) need to enable/disable the bus at each i2c transfer and must wait for the enable/disable to happen before sending the data. When reading data in the trigger handler, the bmc150 accel driver does one bus transfer for each axis. This has an impact on the frequency of the accelerometer at high sample rates due to additional delays introduced by the bus at each transfer. Reading all axis values in one bus transfer reduces the delays introduced by the bus. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-core.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index cc52366ad4ad..58df97df562b 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -989,6 +989,7 @@ static const struct iio_event_spec bmc150_accel_event = { .realbits = (bits), \ .storagebits = 16, \ .shift = 16 - (bits), \ + .endianness = IIO_LE, \ }, \ .event_spec = &bmc150_accel_event, \ .num_event_specs = 1 \ @@ -1114,21 +1115,14 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmc150_accel_data *data = iio_priv(indio_dev); - int bit, ret, i = 0; - unsigned int raw_val; + int ret; mutex_lock(&data->mutex); - for (bit = 0; bit < AXIS_MAX; bit++) { - ret = regmap_bulk_read(data->regmap, - BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val, - 2); - if (ret < 0) { - mutex_unlock(&data->mutex); - goto err_read; - } - data->buffer[i++] = raw_val; - } + ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_REG_XOUT_L, + data->buffer, AXIS_MAX * 2); mutex_unlock(&data->mutex); + if (ret < 0) + goto err_read; iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, pf->timestamp); -- GitLab From ee8c5419e06e3a002995f5d1f57c9b5aead331e6 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 24 Mar 2016 11:29:28 +0200 Subject: [PATCH 1128/9938] iio: gyro: bmg160: use available_scan_masks Use available_scan_masks to allow the iio core to select the data to send to userspace depending on which axes are enabled, instead of doing this in the driver's interrupt handler. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/bmg160_core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index bbce3b09ac45..8d6e5b132016 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -116,6 +116,7 @@ enum bmg160_axis { AXIS_X, AXIS_Y, AXIS_Z, + AXIS_MAX, }; static const struct { @@ -763,6 +764,10 @@ static const struct iio_info bmg160_info = { .driver_module = THIS_MODULE, }; +static const unsigned long bmg160_accel_scan_masks[] = { + BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), + 0}; + static irqreturn_t bmg160_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -772,8 +777,7 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p) unsigned int val; mutex_lock(&data->mutex); - for_each_set_bit(bit, indio_dev->active_scan_mask, - indio_dev->masklength) { + for (bit = 0; bit < AXIS_MAX; bit++) { ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(bit), &val, 2); if (ret < 0) { @@ -1019,6 +1023,7 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, indio_dev->channels = bmg160_channels; indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); indio_dev->name = name; + indio_dev->available_scan_masks = bmg160_accel_scan_masks; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &bmg160_info; -- GitLab From 7e3d1eb123d804d2b1088782f458aed5eb36c684 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 24 Mar 2016 11:29:29 +0200 Subject: [PATCH 1129/9938] iio: accel: bmg160: optimize transfers in trigger handler Some i2c busses (e.g.: Synopsys DesignWare I2C adapter) need to enable/disable the bus at each i2c transfer and must wait for the enable/disable to happen before sending the data. When reading data in the trigger handler, the bmg160 gyro driver does one bus transfer for each axis. This has an impact on the frequency of the accelerometer at high sample rates due to additional delays introduced by the bus at each transfer. Reading all axis values in one bus transfer reduces the delays introduced by the bus. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/bmg160_core.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index 8d6e5b132016..43570b8f686d 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -734,6 +734,7 @@ static const struct iio_event_spec bmg160_event = { .sign = 's', \ .realbits = 16, \ .storagebits = 16, \ + .endianness = IIO_LE, \ }, \ .event_spec = &bmg160_event, \ .num_event_specs = 1 \ @@ -773,20 +774,14 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmg160_data *data = iio_priv(indio_dev); - int bit, ret, i = 0; - unsigned int val; + int ret; mutex_lock(&data->mutex); - for (bit = 0; bit < AXIS_MAX; bit++) { - ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(bit), - &val, 2); - if (ret < 0) { - mutex_unlock(&data->mutex); - goto err; - } - data->buffer[i++] = ret; - } + ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L, + data->buffer, AXIS_MAX * 2); mutex_unlock(&data->mutex); + if (ret < 0) + goto err; iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, pf->timestamp); -- GitLab From 09cf1b321ad353eeaeddcfd33771b34ce2a61640 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Thu, 24 Mar 2016 11:29:30 +0200 Subject: [PATCH 1130/9938] iio: accel: kxcjk-1013: use available_scan_masks Use available_scan_masks to allow the iio core to select the data to send to userspace depending on which axes are enabled, instead of doing this in the driver's interrupt handler. Signed-off-by: Adriana Reus Signed-off-by: Irina Tirdea Acked-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index edec1d099e91..3861fe99e8ea 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -115,6 +115,7 @@ enum kxcjk1013_axis { AXIS_X, AXIS_Y, AXIS_Z, + AXIS_MAX, }; enum kxcjk1013_mode { @@ -953,6 +954,8 @@ static const struct iio_info kxcjk1013_info = { .driver_module = THIS_MODULE, }; +static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0}; + static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -962,8 +965,7 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) mutex_lock(&data->mutex); - for_each_set_bit(bit, indio_dev->active_scan_mask, - indio_dev->masklength) { + for (bit = 0; bit < AXIS_MAX; bit++) { ret = kxcjk1013_get_acc_reg(data, bit); if (ret < 0) { mutex_unlock(&data->mutex); @@ -1204,6 +1206,7 @@ static int kxcjk1013_probe(struct i2c_client *client, indio_dev->dev.parent = &client->dev; indio_dev->channels = kxcjk1013_channels; indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels); + indio_dev->available_scan_masks = kxcjk1013_scan_masks; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &kxcjk1013_info; -- GitLab From 65ae47b0ec535a008e53578abc11082f3b742f75 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Thu, 24 Mar 2016 11:29:31 +0200 Subject: [PATCH 1131/9938] iio: accel: kxcjk-1013: optimize i2c transfers in trigger handler Some i2c busses (e.g.: Synopsys DesignWare I2C adapter) need to enable/disable the bus at each i2c transfer and must wait for the enable/disable to happen before sending the data. When reading data in the trigger handler, the kxcjk-1013 accel driver does one i2c transfer for each axis. This has an impact on the frequency of the accelerometer at high sample rates due to additional delays introduced by the i2c bus at each transfer. Reading all axis values in one i2c transfer reduces the delays introduced by the i2c bus. Uses i2c_smbus_read_i2c_block_data_or_emulated that will fallback to reading each axis as a separate word in case i2c block read is not supported. Signed-off-by: Adriana Reus Signed-off-by: Irina Tirdea Acked-by: Jonathan Cameron Acked-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 3861fe99e8ea..488185684c40 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -923,7 +923,7 @@ static const struct iio_event_spec kxcjk1013_event = { .realbits = 12, \ .storagebits = 16, \ .shift = 4, \ - .endianness = IIO_CPU, \ + .endianness = IIO_LE, \ }, \ .event_spec = &kxcjk1013_event, \ .num_event_specs = 1 \ @@ -961,19 +961,16 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct kxcjk1013_data *data = iio_priv(indio_dev); - int bit, ret, i = 0; + int ret; mutex_lock(&data->mutex); - - for (bit = 0; bit < AXIS_MAX; bit++) { - ret = kxcjk1013_get_acc_reg(data, bit); - if (ret < 0) { - mutex_unlock(&data->mutex); - goto err; - } - data->buffer[i++] = ret; - } + ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client, + KXCJK1013_REG_XOUT_L, + AXIS_MAX * 2, + (u8 *)data->buffer); mutex_unlock(&data->mutex); + if (ret < 0) + goto err; iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, data->timestamp); -- GitLab From b1532909decca12e0527473870cec1d57677f916 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 24 Mar 2016 11:08:38 +0200 Subject: [PATCH 1132/9938] iio: remove unused gpio consumer.h include GPIO handling code has been removed from the drivers (since this is now handled by the ACPI core) in commit 0f0796509c07 ("iio: remove gpio interrupt probing from drivers that use a single interrupt"). Remove the include for linux/gpio/consumer.h since it is no longer used. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-core.c | 1 - drivers/iio/accel/kxcjk-1013.c | 1 - drivers/iio/accel/mma9553.c | 1 - drivers/iio/accel/stk8312.c | 1 - drivers/iio/accel/stk8ba50.c | 1 - drivers/iio/imu/kmx61.c | 1 - drivers/iio/light/stk3310.c | 1 - drivers/iio/magnetometer/bmc150_magn.c | 1 - 8 files changed, 8 deletions(-) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 58df97df562b..f3d096f3c539 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 488185684c40..bfe219a8bea2 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index fa7d36217c4b..bb05f3efddca 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index 85fe7f7247c1..e31023dc5f1b 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index 5709d9eb8f34..300d955bad00 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index e5306b4e020e..2e7dd5754a56 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index 42d334ba612e..9e847f8f4f0c 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index ffcb75ea64fb..0e9da189dc4c 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include -- GitLab From fb12b6c725a3936bedaa7fac87432f0ad0d01599 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 24 Mar 2016 11:05:09 +0200 Subject: [PATCH 1133/9938] iio: remove gpio interrupt probing from drivers that use a single interrupt Commit 845c877009cf014b ("i2c / ACPI: Assign IRQ for devices that have GpioInt automatically") automatically assigns the first ACPI GPIO interrupt in client->irq, so we can remove the probing code from drivers that use only one interrupt. Commit 0f0796509c07c1c7 ("iio: remove gpio interrupt probing from drivers that use a single interrupt") removes gpio interrupt probing from most drivers. This patch cleans the remaining ones. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mxc4005.c | 29 ----------------------------- drivers/iio/gyro/bmg160_core.c | 28 ---------------------------- 2 files changed, 57 deletions(-) diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index e72e218c2696..c23f47af7256 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -380,31 +379,6 @@ static const struct iio_trigger_ops mxc4005_trigger_ops = { .owner = THIS_MODULE, }; -static int mxc4005_gpio_probe(struct i2c_client *client, - struct mxc4005_data *data) -{ - struct device *dev; - struct gpio_desc *gpio; - int ret; - - if (!client) - return -EINVAL; - - dev = &client->dev; - - gpio = devm_gpiod_get_index(dev, "mxc4005_int", 0, GPIOD_IN); - if (IS_ERR(gpio)) { - dev_err(dev, "failed to get acpi gpio index\n"); - return PTR_ERR(gpio); - } - - ret = gpiod_to_irq(gpio); - - dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); - - return ret; -} - static int mxc4005_chip_init(struct mxc4005_data *data) { int ret; @@ -470,9 +444,6 @@ static int mxc4005_probe(struct i2c_client *client, return ret; } - if (client->irq < 0) - client->irq = mxc4005_gpio_probe(client, data); - if (client->irq > 0) { data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index 43570b8f686d..2493bb17a03d 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,6 @@ #include "bmg160.h" #define BMG160_IRQ_NAME "bmg160_event" -#define BMG160_GPIO_NAME "gpio_int" #define BMG160_REG_CHIP_ID 0x00 #define BMG160_CHIP_ID_VAL 0x0F @@ -954,29 +952,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = { .postdisable = bmg160_buffer_postdisable, }; -static int bmg160_gpio_probe(struct bmg160_data *data) - -{ - struct device *dev; - struct gpio_desc *gpio; - - dev = data->dev; - - /* data ready gpio interrupt pin */ - gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN); - if (IS_ERR(gpio)) { - dev_err(dev, "acpi gpio get index failed\n"); - return PTR_ERR(gpio); - } - - data->irq = gpiod_to_irq(gpio); - - dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), - data->irq); - - return 0; -} - static const char *bmg160_match_acpi_device(struct device *dev) { const struct acpi_device_id *id; @@ -1022,9 +997,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &bmg160_info; - if (data->irq <= 0) - bmg160_gpio_probe(data); - if (data->irq > 0) { ret = devm_request_threaded_irq(dev, data->irq, -- GitLab From 793d6b5ea80c9bba8de40b720991b436fa5e174d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Mar 2016 09:39:14 +0100 Subject: [PATCH 1134/9938] iio: tools: make generic_buffer look for "-trigger" All the ST Sensors use the old "-trigger" rather than the standard "-devN" new standard suffix for triggers. Now much to do about it since it is ABI, but make the testing tools recognize it too. Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- tools/iio/generic_buffer.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c index 01c4f67801e0..c42b7f836b48 100644 --- a/tools/iio/generic_buffer.c +++ b/tools/iio/generic_buffer.c @@ -304,7 +304,19 @@ int main(int argc, char **argv) } } - /* Verify the trigger exists */ + /* Look for this "-devN" trigger */ + trig_num = find_type_by_name(trigger_name, "trigger"); + if (trig_num < 0) { + /* OK try the simpler "-trigger" suffix instead */ + free(trigger_name); + ret = asprintf(&trigger_name, + "%s-trigger", device_name); + if (ret < 0) { + ret = -ENOMEM; + goto error_free_dev_dir_name; + } + } + trig_num = find_type_by_name(trigger_name, "trigger"); if (trig_num < 0) { fprintf(stderr, "Failed to find the trigger %s\n", -- GitLab From 8cb359e3a1f6318f971bec281623613f48b711be Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 23 Mar 2016 12:34:41 +0000 Subject: [PATCH 1135/9938] iio: buffer: add missing descriptions in iio_buffer_access_funcs The members buffer_group and attrs of iio_buffer_access_funcs have no descriptions for the documentation. Adding them. Fixes: 08e7e0adaa17 ("iio: buffer: Allocate standard attributes in the core") Signed-off-by: Luis de Bethencourt Signed-off-by: Jonathan Cameron --- include/linux/iio/buffer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 2ec3ad58e8a0..70a5164f4728 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -83,10 +83,12 @@ struct iio_buffer_access_funcs { * @access: [DRIVER] buffer access functions associated with the * implementation. * @scan_el_dev_attr_list:[INTERN] list of scan element related attributes. + * @buffer_group: [INTERN] attributes of the buffer group * @scan_el_group: [DRIVER] attribute group for those attributes not * created from the iio_chan_info array. * @pollq: [INTERN] wait queue to allow for polling on the buffer. * @stufftoread: [INTERN] flag to indicate new data. + * @attrs: [INTERN] standard attributes of the buffer * @demux_list: [INTERN] list of operations required to demux the scan. * @demux_bounce: [INTERN] buffer for doing gather from incoming scan. * @buffer_list: [INTERN] entry in the devices list of current buffers. -- GitLab From 6154a108faafe5f7fe08cee933b899b013b457d9 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Wed, 23 Mar 2016 12:06:34 +0100 Subject: [PATCH 1136/9938] Staging: iio: ad7606: Fix sparse endian warning Fix following sparse warning: warning: cast to restricted __be16 Signed-off-by: Ksenija Stanojevic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_spi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index d873a5164595..825da0769936 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -21,7 +21,8 @@ static int ad7606_spi_read_block(struct device *dev, { struct spi_device *spi = to_spi_device(dev); int i, ret; - unsigned short *data = buf; + unsigned short *data; + __be16 *bdata = buf; ret = spi_read(spi, buf, count * 2); if (ret < 0) { @@ -30,7 +31,7 @@ static int ad7606_spi_read_block(struct device *dev, } for (i = 0; i < count; i++) - data[i] = be16_to_cpu(data[i]); + data[i] = be16_to_cpu(bdata[i]); return 0; } -- GitLab From 22d199a53910e2b1666bf873f10779a66844c126 Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Wed, 23 Mar 2016 09:57:20 +0100 Subject: [PATCH 1137/9938] iio: potentiometer: add driver for Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X The following functionalities are supported: - write, read from volatile memory Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf Signed-off-by: Slawomir Stepien Reviewed-by: Joachim Eastwood Signed-off-by: Jonathan Cameron --- .../bindings/iio/potentiometer/mcp4131.txt | 84 +++ drivers/iio/potentiometer/Kconfig | 18 + drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/mcp4131.c | 494 ++++++++++++++++++ 4 files changed, 597 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt create mode 100644 drivers/iio/potentiometer/mcp4131.c diff --git a/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt b/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt new file mode 100644 index 000000000000..3ccba16f7035 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt @@ -0,0 +1,84 @@ +* Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer + driver + +The node for this driver must be a child node of a SPI controller, hence +all mandatory properties described in + + Documentation/devicetree/bindings/spi/spi-bus.txt + +must be specified. + +Required properties: + - compatible: Must be one of the following, depending on the + model: + "microchip,mcp4131-502" + "microchip,mcp4131-103" + "microchip,mcp4131-503" + "microchip,mcp4131-104" + "microchip,mcp4132-502" + "microchip,mcp4132-103" + "microchip,mcp4132-503" + "microchip,mcp4132-104" + "microchip,mcp4141-502" + "microchip,mcp4141-103" + "microchip,mcp4141-503" + "microchip,mcp4141-104" + "microchip,mcp4142-502" + "microchip,mcp4142-103" + "microchip,mcp4142-503" + "microchip,mcp4142-104" + "microchip,mcp4151-502" + "microchip,mcp4151-103" + "microchip,mcp4151-503" + "microchip,mcp4151-104" + "microchip,mcp4152-502" + "microchip,mcp4152-103" + "microchip,mcp4152-503" + "microchip,mcp4152-104" + "microchip,mcp4161-502" + "microchip,mcp4161-103" + "microchip,mcp4161-503" + "microchip,mcp4161-104" + "microchip,mcp4162-502" + "microchip,mcp4162-103" + "microchip,mcp4162-503" + "microchip,mcp4162-104" + "microchip,mcp4231-502" + "microchip,mcp4231-103" + "microchip,mcp4231-503" + "microchip,mcp4231-104" + "microchip,mcp4232-502" + "microchip,mcp4232-103" + "microchip,mcp4232-503" + "microchip,mcp4232-104" + "microchip,mcp4241-502" + "microchip,mcp4241-103" + "microchip,mcp4241-503" + "microchip,mcp4241-104" + "microchip,mcp4242-502" + "microchip,mcp4242-103" + "microchip,mcp4242-503" + "microchip,mcp4242-104" + "microchip,mcp4251-502" + "microchip,mcp4251-103" + "microchip,mcp4251-503" + "microchip,mcp4251-104" + "microchip,mcp4252-502" + "microchip,mcp4252-103" + "microchip,mcp4252-503" + "microchip,mcp4252-104" + "microchip,mcp4261-502" + "microchip,mcp4261-103" + "microchip,mcp4261-503" + "microchip,mcp4261-104" + "microchip,mcp4262-502" + "microchip,mcp4262-103" + "microchip,mcp4262-503" + "microchip,mcp4262-104" + +Example: +mcp4131: mcp4131@0 { + compatible = "mcp4131-502"; + reg = <0>; + spi-max-frequency = <500000>; +}; diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig index ffc735c168fb..7ea069bbca2d 100644 --- a/drivers/iio/potentiometer/Kconfig +++ b/drivers/iio/potentiometer/Kconfig @@ -5,6 +5,24 @@ menu "Digital potentiometers" +config MCP4131 + tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver" + depends on SPI + help + Say yes here to build support for the Microchip + MCP4131, MCP4132, + MCP4141, MCP4142, + MCP4151, MCP4152, + MCP4161, MCP4162, + MCP4231, MCP4232, + MCP4241, MCP4242, + MCP4251, MCP4252, + MCP4261, MCP4262, + digital potentiomenter chips. + + To compile this driver as a module, choose M here: the + module will be called mcp4131. + config MCP4531 tristate "Microchip MCP45xx/MCP46xx Digital Potentiometer driver" depends on I2C diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile index b563b492b486..91a80f8db24d 100644 --- a/drivers/iio/potentiometer/Makefile +++ b/drivers/iio/potentiometer/Makefile @@ -3,5 +3,6 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_MCP4131) += mcp4131.o obj-$(CONFIG_MCP4531) += mcp4531.o obj-$(CONFIG_TPL0102) += tpl0102.o diff --git a/drivers/iio/potentiometer/mcp4131.c b/drivers/iio/potentiometer/mcp4131.c new file mode 100644 index 000000000000..4e7e2c6c522c --- /dev/null +++ b/drivers/iio/potentiometer/mcp4131.c @@ -0,0 +1,494 @@ +/* + * Industrial I/O driver for Microchip digital potentiometers + * + * Copyright (c) 2016 Slawomir Stepien + * Based on: Peter Rosin's code from mcp4531.c + * + * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf + * + * DEVID #Wipers #Positions Resistor Opts (kOhm) + * mcp4131 1 129 5, 10, 50, 100 + * mcp4132 1 129 5, 10, 50, 100 + * mcp4141 1 129 5, 10, 50, 100 + * mcp4142 1 129 5, 10, 50, 100 + * mcp4151 1 257 5, 10, 50, 100 + * mcp4152 1 257 5, 10, 50, 100 + * mcp4161 1 257 5, 10, 50, 100 + * mcp4162 1 257 5, 10, 50, 100 + * mcp4231 2 129 5, 10, 50, 100 + * mcp4232 2 129 5, 10, 50, 100 + * mcp4241 2 129 5, 10, 50, 100 + * mcp4242 2 129 5, 10, 50, 100 + * mcp4251 2 257 5, 10, 50, 100 + * mcp4252 2 257 5, 10, 50, 100 + * mcp4261 2 257 5, 10, 50, 100 + * mcp4262 2 257 5, 10, 50, 100 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/* + * TODO: + * 1. Write wiper setting to EEPROM for EEPROM capable models. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCP4131_WRITE (0x00 << 2) +#define MCP4131_READ (0x03 << 2) + +#define MCP4131_WIPER_SHIFT 4 +#define MCP4131_CMDERR(r) ((r[0]) & 0x02) +#define MCP4131_RAW(r) ((r[0]) == 0xff ? 0x100 : (r[1])) + +struct mcp4131_cfg { + int wipers; + int max_pos; + int kohms; +}; + +enum mcp4131_type { + MCP413x_502 = 0, + MCP413x_103, + MCP413x_503, + MCP413x_104, + MCP414x_502, + MCP414x_103, + MCP414x_503, + MCP414x_104, + MCP415x_502, + MCP415x_103, + MCP415x_503, + MCP415x_104, + MCP416x_502, + MCP416x_103, + MCP416x_503, + MCP416x_104, + MCP423x_502, + MCP423x_103, + MCP423x_503, + MCP423x_104, + MCP424x_502, + MCP424x_103, + MCP424x_503, + MCP424x_104, + MCP425x_502, + MCP425x_103, + MCP425x_503, + MCP425x_104, + MCP426x_502, + MCP426x_103, + MCP426x_503, + MCP426x_104, +}; + +static const struct mcp4131_cfg mcp4131_cfg[] = { + [MCP413x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, + [MCP413x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, + [MCP413x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, + [MCP413x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, + [MCP414x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, + [MCP414x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, + [MCP414x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, + [MCP414x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, + [MCP415x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, + [MCP415x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, + [MCP415x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, + [MCP415x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, + [MCP416x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, + [MCP416x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, + [MCP416x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, + [MCP416x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, + [MCP423x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, + [MCP423x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, + [MCP423x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, + [MCP423x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, + [MCP424x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, + [MCP424x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, + [MCP424x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, + [MCP424x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, + [MCP425x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, + [MCP425x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, + [MCP425x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, + [MCP425x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, + [MCP426x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, + [MCP426x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, + [MCP426x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, + [MCP426x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, +}; + +struct mcp4131_data { + struct spi_device *spi; + const struct mcp4131_cfg *cfg; + struct mutex lock; + u8 buf[2] ____cacheline_aligned; +}; + +#define MCP4131_CHANNEL(ch) { \ + .type = IIO_RESISTANCE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (ch), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec mcp4131_channels[] = { + MCP4131_CHANNEL(0), + MCP4131_CHANNEL(1), +}; + +static int mcp4131_read(struct spi_device *spi, void *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = buf, /* We need to send addr, cmd and 12 bits */ + .rx_buf = buf, + .len = len, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + return spi_sync(spi, &m); +} + +static int mcp4131_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int err; + struct mcp4131_data *data = iio_priv(indio_dev); + int address = chan->channel; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->lock); + + data->buf[0] = (address << MCP4131_WIPER_SHIFT) | MCP4131_READ; + data->buf[1] = 0; + + err = mcp4131_read(data->spi, data->buf, 2); + if (err) { + mutex_unlock(&data->lock); + return err; + } + + /* Error, bad address/command combination */ + if (!MCP4131_CMDERR(data->buf)) { + mutex_unlock(&data->lock); + return -EIO; + } + + *val = MCP4131_RAW(data->buf); + mutex_unlock(&data->lock); + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = 1000 * data->cfg->kohms; + *val2 = data->cfg->max_pos; + return IIO_VAL_FRACTIONAL; + } + + return -EINVAL; +} + +static int mcp4131_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int err; + struct mcp4131_data *data = iio_priv(indio_dev); + int address = chan->channel << MCP4131_WIPER_SHIFT; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val > data->cfg->max_pos || val < 0) + return -EINVAL; + break; + + default: + return -EINVAL; + } + + mutex_lock(&data->lock); + + data->buf[0] = address << MCP4131_WIPER_SHIFT; + data->buf[0] |= MCP4131_WRITE | (val >> 8); + data->buf[1] = val & 0xFF; /* 8 bits here */ + + err = spi_write(data->spi, data->buf, 2); + mutex_unlock(&data->lock); + + return err; +} + +static const struct iio_info mcp4131_info = { + .read_raw = mcp4131_read_raw, + .write_raw = mcp4131_write_raw, + .driver_module = THIS_MODULE, +}; + +static int mcp4131_probe(struct spi_device *spi) +{ + int err; + struct device *dev = &spi->dev; + unsigned long devid = spi_get_device_id(spi)->driver_data; + struct mcp4131_data *data; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + data->spi = spi; + data->cfg = &mcp4131_cfg[devid]; + + mutex_init(&data->lock); + + indio_dev->dev.parent = dev; + indio_dev->info = &mcp4131_info; + indio_dev->channels = mcp4131_channels; + indio_dev->num_channels = data->cfg->wipers; + indio_dev->name = spi_get_device_id(spi)->name; + + err = devm_iio_device_register(dev, indio_dev); + if (err) { + dev_info(&spi->dev, "Unable to register %s\n", indio_dev->name); + return err; + } + + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id mcp4131_dt_ids[] = { + { .compatible = "microchip,mcp4131-502", + .data = &mcp4131_cfg[MCP413x_502] }, + { .compatible = "microchip,mcp4131-103", + .data = &mcp4131_cfg[MCP413x_103] }, + { .compatible = "microchip,mcp4131-503", + .data = &mcp4131_cfg[MCP413x_503] }, + { .compatible = "microchip,mcp4131-104", + .data = &mcp4131_cfg[MCP413x_104] }, + { .compatible = "microchip,mcp4132-502", + .data = &mcp4131_cfg[MCP413x_502] }, + { .compatible = "microchip,mcp4132-103", + .data = &mcp4131_cfg[MCP413x_103] }, + { .compatible = "microchip,mcp4132-503", + .data = &mcp4131_cfg[MCP413x_503] }, + { .compatible = "microchip,mcp4132-104", + .data = &mcp4131_cfg[MCP413x_104] }, + { .compatible = "microchip,mcp4141-502", + .data = &mcp4131_cfg[MCP414x_502] }, + { .compatible = "microchip,mcp4141-103", + .data = &mcp4131_cfg[MCP414x_103] }, + { .compatible = "microchip,mcp4141-503", + .data = &mcp4131_cfg[MCP414x_503] }, + { .compatible = "microchip,mcp4141-104", + .data = &mcp4131_cfg[MCP414x_104] }, + { .compatible = "microchip,mcp4142-502", + .data = &mcp4131_cfg[MCP414x_502] }, + { .compatible = "microchip,mcp4142-103", + .data = &mcp4131_cfg[MCP414x_103] }, + { .compatible = "microchip,mcp4142-503", + .data = &mcp4131_cfg[MCP414x_503] }, + { .compatible = "microchip,mcp4142-104", + .data = &mcp4131_cfg[MCP414x_104] }, + { .compatible = "microchip,mcp4151-502", + .data = &mcp4131_cfg[MCP415x_502] }, + { .compatible = "microchip,mcp4151-103", + .data = &mcp4131_cfg[MCP415x_103] }, + { .compatible = "microchip,mcp4151-503", + .data = &mcp4131_cfg[MCP415x_503] }, + { .compatible = "microchip,mcp4151-104", + .data = &mcp4131_cfg[MCP415x_104] }, + { .compatible = "microchip,mcp4152-502", + .data = &mcp4131_cfg[MCP415x_502] }, + { .compatible = "microchip,mcp4152-103", + .data = &mcp4131_cfg[MCP415x_103] }, + { .compatible = "microchip,mcp4152-503", + .data = &mcp4131_cfg[MCP415x_503] }, + { .compatible = "microchip,mcp4152-104", + .data = &mcp4131_cfg[MCP415x_104] }, + { .compatible = "microchip,mcp4161-502", + .data = &mcp4131_cfg[MCP416x_502] }, + { .compatible = "microchip,mcp4161-103", + .data = &mcp4131_cfg[MCP416x_103] }, + { .compatible = "microchip,mcp4161-503", + .data = &mcp4131_cfg[MCP416x_503] }, + { .compatible = "microchip,mcp4161-104", + .data = &mcp4131_cfg[MCP416x_104] }, + { .compatible = "microchip,mcp4162-502", + .data = &mcp4131_cfg[MCP416x_502] }, + { .compatible = "microchip,mcp4162-103", + .data = &mcp4131_cfg[MCP416x_103] }, + { .compatible = "microchip,mcp4162-503", + .data = &mcp4131_cfg[MCP416x_503] }, + { .compatible = "microchip,mcp4162-104", + .data = &mcp4131_cfg[MCP416x_104] }, + { .compatible = "microchip,mcp4231-502", + .data = &mcp4131_cfg[MCP423x_502] }, + { .compatible = "microchip,mcp4231-103", + .data = &mcp4131_cfg[MCP423x_103] }, + { .compatible = "microchip,mcp4231-503", + .data = &mcp4131_cfg[MCP423x_503] }, + { .compatible = "microchip,mcp4231-104", + .data = &mcp4131_cfg[MCP423x_104] }, + { .compatible = "microchip,mcp4232-502", + .data = &mcp4131_cfg[MCP423x_502] }, + { .compatible = "microchip,mcp4232-103", + .data = &mcp4131_cfg[MCP423x_103] }, + { .compatible = "microchip,mcp4232-503", + .data = &mcp4131_cfg[MCP423x_503] }, + { .compatible = "microchip,mcp4232-104", + .data = &mcp4131_cfg[MCP423x_104] }, + { .compatible = "microchip,mcp4241-502", + .data = &mcp4131_cfg[MCP424x_502] }, + { .compatible = "microchip,mcp4241-103", + .data = &mcp4131_cfg[MCP424x_103] }, + { .compatible = "microchip,mcp4241-503", + .data = &mcp4131_cfg[MCP424x_503] }, + { .compatible = "microchip,mcp4241-104", + .data = &mcp4131_cfg[MCP424x_104] }, + { .compatible = "microchip,mcp4242-502", + .data = &mcp4131_cfg[MCP424x_502] }, + { .compatible = "microchip,mcp4242-103", + .data = &mcp4131_cfg[MCP424x_103] }, + { .compatible = "microchip,mcp4242-503", + .data = &mcp4131_cfg[MCP424x_503] }, + { .compatible = "microchip,mcp4242-104", + .data = &mcp4131_cfg[MCP424x_104] }, + { .compatible = "microchip,mcp4251-502", + .data = &mcp4131_cfg[MCP425x_502] }, + { .compatible = "microchip,mcp4251-103", + .data = &mcp4131_cfg[MCP425x_103] }, + { .compatible = "microchip,mcp4251-503", + .data = &mcp4131_cfg[MCP425x_503] }, + { .compatible = "microchip,mcp4251-104", + .data = &mcp4131_cfg[MCP425x_104] }, + { .compatible = "microchip,mcp4252-502", + .data = &mcp4131_cfg[MCP425x_502] }, + { .compatible = "microchip,mcp4252-103", + .data = &mcp4131_cfg[MCP425x_103] }, + { .compatible = "microchip,mcp4252-503", + .data = &mcp4131_cfg[MCP425x_503] }, + { .compatible = "microchip,mcp4252-104", + .data = &mcp4131_cfg[MCP425x_104] }, + { .compatible = "microchip,mcp4261-502", + .data = &mcp4131_cfg[MCP426x_502] }, + { .compatible = "microchip,mcp4261-103", + .data = &mcp4131_cfg[MCP426x_103] }, + { .compatible = "microchip,mcp4261-503", + .data = &mcp4131_cfg[MCP426x_503] }, + { .compatible = "microchip,mcp4261-104", + .data = &mcp4131_cfg[MCP426x_104] }, + { .compatible = "microchip,mcp4262-502", + .data = &mcp4131_cfg[MCP426x_502] }, + { .compatible = "microchip,mcp4262-103", + .data = &mcp4131_cfg[MCP426x_103] }, + { .compatible = "microchip,mcp4262-503", + .data = &mcp4131_cfg[MCP426x_503] }, + { .compatible = "microchip,mcp4262-104", + .data = &mcp4131_cfg[MCP426x_104] }, + {} +}; +MODULE_DEVICE_TABLE(of, mcp4131_dt_ids); +#endif /* CONFIG_OF */ + +static const struct spi_device_id mcp4131_id[] = { + { "mcp4131-502", MCP413x_502 }, + { "mcp4131-103", MCP413x_103 }, + { "mcp4131-503", MCP413x_503 }, + { "mcp4131-104", MCP413x_104 }, + { "mcp4132-502", MCP413x_502 }, + { "mcp4132-103", MCP413x_103 }, + { "mcp4132-503", MCP413x_503 }, + { "mcp4132-104", MCP413x_104 }, + { "mcp4141-502", MCP414x_502 }, + { "mcp4141-103", MCP414x_103 }, + { "mcp4141-503", MCP414x_503 }, + { "mcp4141-104", MCP414x_104 }, + { "mcp4142-502", MCP414x_502 }, + { "mcp4142-103", MCP414x_103 }, + { "mcp4142-503", MCP414x_503 }, + { "mcp4142-104", MCP414x_104 }, + { "mcp4151-502", MCP415x_502 }, + { "mcp4151-103", MCP415x_103 }, + { "mcp4151-503", MCP415x_503 }, + { "mcp4151-104", MCP415x_104 }, + { "mcp4152-502", MCP415x_502 }, + { "mcp4152-103", MCP415x_103 }, + { "mcp4152-503", MCP415x_503 }, + { "mcp4152-104", MCP415x_104 }, + { "mcp4161-502", MCP416x_502 }, + { "mcp4161-103", MCP416x_103 }, + { "mcp4161-503", MCP416x_503 }, + { "mcp4161-104", MCP416x_104 }, + { "mcp4162-502", MCP416x_502 }, + { "mcp4162-103", MCP416x_103 }, + { "mcp4162-503", MCP416x_503 }, + { "mcp4162-104", MCP416x_104 }, + { "mcp4231-502", MCP423x_502 }, + { "mcp4231-103", MCP423x_103 }, + { "mcp4231-503", MCP423x_503 }, + { "mcp4231-104", MCP423x_104 }, + { "mcp4232-502", MCP423x_502 }, + { "mcp4232-103", MCP423x_103 }, + { "mcp4232-503", MCP423x_503 }, + { "mcp4232-104", MCP423x_104 }, + { "mcp4241-502", MCP424x_502 }, + { "mcp4241-103", MCP424x_103 }, + { "mcp4241-503", MCP424x_503 }, + { "mcp4241-104", MCP424x_104 }, + { "mcp4242-502", MCP424x_502 }, + { "mcp4242-103", MCP424x_103 }, + { "mcp4242-503", MCP424x_503 }, + { "mcp4242-104", MCP424x_104 }, + { "mcp4251-502", MCP425x_502 }, + { "mcp4251-103", MCP425x_103 }, + { "mcp4251-503", MCP425x_503 }, + { "mcp4251-104", MCP425x_104 }, + { "mcp4252-502", MCP425x_502 }, + { "mcp4252-103", MCP425x_103 }, + { "mcp4252-503", MCP425x_503 }, + { "mcp4252-104", MCP425x_104 }, + { "mcp4261-502", MCP426x_502 }, + { "mcp4261-103", MCP426x_103 }, + { "mcp4261-503", MCP426x_503 }, + { "mcp4261-104", MCP426x_104 }, + { "mcp4262-502", MCP426x_502 }, + { "mcp4262-103", MCP426x_103 }, + { "mcp4262-503", MCP426x_503 }, + { "mcp4262-104", MCP426x_104 }, + {} +}; +MODULE_DEVICE_TABLE(spi, mcp4131_id); + +static struct spi_driver mcp4131_driver = { + .driver = { + .name = "mcp4131", + .of_match_table = of_match_ptr(mcp4131_dt_ids), + }, + .probe = mcp4131_probe, + .id_table = mcp4131_id, +}; + +module_spi_driver(mcp4131_driver); + +MODULE_AUTHOR("Slawomir Stepien "); +MODULE_DESCRIPTION("MCP4131 digital potentiometer"); +MODULE_LICENSE("GPL v2"); -- GitLab From 94b24230196da3cd6bd58235137f9a7438983c73 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 22 Mar 2016 17:08:45 +0100 Subject: [PATCH 1138/9938] iio:adc:at91-sama5d2: cleanup mode register use Do not erase previous configuration of the mode register when setting the sampling frequency. Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 5bc038f23609..01ba1068613e 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -66,8 +66,10 @@ #define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET) #define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8 #define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff +#define AT91_SAMA5D2_MR_PRESCAL_MASK GENMASK(15, 8) /* Startup Time */ #define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16) +#define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16) /* Analog Change */ #define AT91_SAMA5D2_MR_ANACH BIT(23) /* Tracking Time */ @@ -226,7 +228,7 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min, static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) { struct iio_dev *indio_dev = iio_priv_to_dev(st); - unsigned f_per, prescal, startup; + unsigned f_per, prescal, startup, mr; f_per = clk_get_rate(st->per_clk); prescal = (f_per / (2 * freq)) - 1; @@ -234,10 +236,11 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) startup = at91_adc_startup_time(st->soc_info.startup_time, freq / 1000); - at91_adc_writel(st, AT91_SAMA5D2_MR, - AT91_SAMA5D2_MR_TRANSFER(2) - | AT91_SAMA5D2_MR_STARTUP(startup) - | AT91_SAMA5D2_MR_PRESCAL(prescal)); + mr = at91_adc_readl(st, AT91_SAMA5D2_MR); + mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK); + mr |= AT91_SAMA5D2_MR_STARTUP(startup); + mr |= AT91_SAMA5D2_MR_PRESCAL(prescal); + at91_adc_writel(st, AT91_SAMA5D2_MR, mr); dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n", freq, startup, prescal); @@ -444,6 +447,8 @@ static int at91_adc_probe(struct platform_device *pdev) at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); + /* Transfer field must be set to 2 according to the datasheet. */ + at91_adc_writel(st, AT91_SAMA5D2_MR, AT91_SAMA5D2_MR_TRANSFER(2)); at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); -- GitLab From d65113222c27e2ca0b292a5163ea294428d481b2 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 22 Mar 2016 17:08:46 +0100 Subject: [PATCH 1139/9938] iio:adc:at91-sama5d2: add support for differential conversions Add signed differential channels and update the voltage scale for differential conversions. Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 71 +++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 01ba1068613e..07adb1070fc2 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -113,8 +113,11 @@ #define AT91_SAMA5D2_CWR 0x44 /* Channel Gain Register */ #define AT91_SAMA5D2_CGR 0x48 + /* Channel Offset Register */ #define AT91_SAMA5D2_COR 0x4c +#define AT91_SAMA5D2_COR_DIFF_OFFSET 16 + /* Channel Data Register 0 */ #define AT91_SAMA5D2_CDR0 0x50 /* Analog Control Register */ @@ -142,7 +145,7 @@ /* Version Register */ #define AT91_SAMA5D2_VERSION 0xfc -#define AT91_SAMA5D2_CHAN(num, addr) \ +#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \ { \ .type = IIO_VOLTAGE, \ .channel = num, \ @@ -158,6 +161,24 @@ .indexed = 1, \ } +#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr) \ + { \ + .type = IIO_VOLTAGE, \ + .differential = 1, \ + .channel = num, \ + .channel2 = num2, \ + .address = addr, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + }, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .datasheet_name = "CH"#num"-CH"#num2, \ + .indexed = 1, \ + } + #define at91_adc_readl(st, reg) readl_relaxed(st->base + reg) #define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg) @@ -187,18 +208,24 @@ struct at91_adc_state { }; static const struct iio_chan_spec at91_adc_channels[] = { - AT91_SAMA5D2_CHAN(0, 0x50), - AT91_SAMA5D2_CHAN(1, 0x54), - AT91_SAMA5D2_CHAN(2, 0x58), - AT91_SAMA5D2_CHAN(3, 0x5c), - AT91_SAMA5D2_CHAN(4, 0x60), - AT91_SAMA5D2_CHAN(5, 0x64), - AT91_SAMA5D2_CHAN(6, 0x68), - AT91_SAMA5D2_CHAN(7, 0x6c), - AT91_SAMA5D2_CHAN(8, 0x70), - AT91_SAMA5D2_CHAN(9, 0x74), - AT91_SAMA5D2_CHAN(10, 0x78), - AT91_SAMA5D2_CHAN(11, 0x7c), + AT91_SAMA5D2_CHAN_SINGLE(0, 0x50), + AT91_SAMA5D2_CHAN_SINGLE(1, 0x54), + AT91_SAMA5D2_CHAN_SINGLE(2, 0x58), + AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c), + AT91_SAMA5D2_CHAN_SINGLE(4, 0x60), + AT91_SAMA5D2_CHAN_SINGLE(5, 0x64), + AT91_SAMA5D2_CHAN_SINGLE(6, 0x68), + AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c), + AT91_SAMA5D2_CHAN_SINGLE(8, 0x70), + AT91_SAMA5D2_CHAN_SINGLE(9, 0x74), + AT91_SAMA5D2_CHAN_SINGLE(10, 0x78), + AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c), + AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50), + AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58), + AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60), + AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68), + AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70), + AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78), }; static unsigned at91_adc_startup_time(unsigned startup_time_min, @@ -281,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct at91_adc_state *st = iio_priv(indio_dev); + u32 cor = 0; int ret; switch (mask) { @@ -289,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, st->chan = chan; + if (chan->differential) + cor = (BIT(chan->channel) | BIT(chan->channel2)) << + AT91_SAMA5D2_COR_DIFF_OFFSET; + + at91_adc_writel(st, AT91_SAMA5D2_COR, cor); at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START); @@ -301,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, if (ret > 0) { *val = st->conversion_value; + if (chan->scan_type.sign == 's') + *val = sign_extend32(*val, 11); ret = IIO_VAL_INT; st->conversion_done = false; } @@ -313,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: *val = st->vref_uv / 1000; + if (chan->differential) + *val *= 2; *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; @@ -447,8 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev) at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); - /* Transfer field must be set to 2 according to the datasheet. */ - at91_adc_writel(st, AT91_SAMA5D2_MR, AT91_SAMA5D2_MR_TRANSFER(2)); + /* + * Transfer field must be set to 2 according to the datasheet and + * allows different analog settings for each channel. + */ + at91_adc_writel(st, AT91_SAMA5D2_MR, + AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH); at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); -- GitLab From eaa3476a7ee27c9927531781c8b25365d77e3030 Mon Sep 17 00:00:00 2001 From: Marc Titinger Date: Fri, 11 Mar 2016 15:52:30 +0100 Subject: [PATCH 1140/9938] iio: ina2xx-adc: fix scale for VShunt The scale would result in uV instead of expected mV. Mostly cosmetic, since the value of 'Power' was computed OK. Signed-off-by: Marc Titinger Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ina2xx-adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 4e56fe3580bf..502f2fbe8aef 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->address) { case INA2XX_SHUNT_VOLTAGE: - /* processed (mV) = raw*1000/shunt_div */ + /* processed (mV) = raw/shunt_div */ *val2 = chip->config->shunt_div; - *val = 1000; + *val = 1; return IIO_VAL_FRACTIONAL; case INA2XX_BUS_VOLTAGE: -- GitLab From 2c5ff1f9a6240d7d2d0928021cb76e421d6aacaf Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler Date: Sun, 20 Mar 2016 16:20:22 +0100 Subject: [PATCH 1141/9938] iio: Add modifier for UV light Signed-off-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 4 +++- drivers/iio/industrialio-core.c | 1 + include/uapi/linux/iio/types.h | 1 + tools/iio/iio_event_monitor.c | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 17a9210fa6b5..6fb9180e7661 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1255,12 +1255,14 @@ Description: What: /sys/.../iio:deviceX/in_intensityY_raw What: /sys/.../iio:deviceX/in_intensityY_ir_raw What: /sys/.../iio:deviceX/in_intensityY_both_raw +What: /sys/.../iio:deviceX/in_intensityY_uv_raw KernelVersion: 3.4 Contact: linux-iio@vger.kernel.org Description: Unit-less light intensity. Modifiers both and ir indicate that measurements contains visible and infrared light - components or just infrared light, respectively. + components or just infrared light, respectively. Modifier uv indicates + that measurements contain ultraviolet light components. What: /sys/.../iio:deviceX/in_intensity_red_integration_time What: /sys/.../iio:deviceX/in_intensity_green_integration_time diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2e768bc99f05..88353ae0ec07 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -101,6 +101,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_LIGHT_RED] = "red", [IIO_MOD_LIGHT_GREEN] = "green", [IIO_MOD_LIGHT_BLUE] = "blue", + [IIO_MOD_LIGHT_UV] = "uv", [IIO_MOD_QUATERNION] = "quaternion", [IIO_MOD_TEMP_AMBIENT] = "ambient", [IIO_MOD_TEMP_OBJECT] = "object", diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index c077617f3304..9337eceb9f9d 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -77,6 +77,7 @@ enum iio_modifier { IIO_MOD_Q, IIO_MOD_CO2, IIO_MOD_VOC, + IIO_MOD_LIGHT_UV, }; enum iio_event_type { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index 90980f586f7a..8d7d9797480b 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -93,6 +93,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_LIGHT_RED] = "red", [IIO_MOD_LIGHT_GREEN] = "green", [IIO_MOD_LIGHT_BLUE] = "blue", + [IIO_MOD_LIGHT_UV] = "uv", [IIO_MOD_QUATERNION] = "quaternion", [IIO_MOD_TEMP_AMBIENT] = "ambient", [IIO_MOD_TEMP_OBJECT] = "object", @@ -172,6 +173,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_LIGHT_RED: case IIO_MOD_LIGHT_GREEN: case IIO_MOD_LIGHT_BLUE: + case IIO_MOD_LIGHT_UV: case IIO_MOD_QUATERNION: case IIO_MOD_TEMP_AMBIENT: case IIO_MOD_TEMP_OBJECT: -- GitLab From d409404cf6e201c2980c7148484c350f33a7912e Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler Date: Sun, 20 Mar 2016 16:20:23 +0100 Subject: [PATCH 1142/9938] iio: Add channel for UV index UV index indicating strength of sunburn-producing ultraviolet (UV) radiation Signed-off-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 9 +++++++++ drivers/iio/industrialio-core.c | 1 + include/uapi/linux/iio/types.h | 1 + tools/iio/iio_event_monitor.c | 2 ++ 4 files changed, 13 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 6fb9180e7661..f155eff910f9 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1264,6 +1264,15 @@ Description: components or just infrared light, respectively. Modifier uv indicates that measurements contain ultraviolet light components. +What: /sys/.../iio:deviceX/in_uvindex_input +KernelVersion: 4.6 +Contact: linux-iio@vger.kernel.org +Description: + UV light intensity index measuring the human skin's response to + different wavelength of sunlight weighted according to the + standardised CIE Erythemal Action Spectrum. UV index values range + from 0 (low) to >=11 (extreme). + What: /sys/.../iio:deviceX/in_intensity_red_integration_time What: /sys/.../iio:deviceX/in_intensity_green_integration_time What: /sys/.../iio:deviceX/in_intensity_blue_integration_time diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 88353ae0ec07..190a5939fd8c 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -79,6 +79,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CONCENTRATION] = "concentration", [IIO_RESISTANCE] = "resistance", [IIO_PH] = "ph", + [IIO_UVINDEX] = "uvindex", }; static const char * const iio_modifier_names[] = { diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 9337eceb9f9d..b0916fc72cce 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -38,6 +38,7 @@ enum iio_chan_type { IIO_CONCENTRATION, IIO_RESISTANCE, IIO_PH, + IIO_UVINDEX, }; enum iio_modifier { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index 8d7d9797480b..d9b7e0f306c6 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -56,6 +56,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CONCENTRATION] = "concentration", [IIO_RESISTANCE] = "resistance", [IIO_PH] = "ph", + [IIO_UVINDEX] = "uvindex", }; static const char * const iio_ev_type_text[] = { @@ -147,6 +148,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_CONCENTRATION: case IIO_RESISTANCE: case IIO_PH: + case IIO_UVINDEX: break; default: return false; -- GitLab From fa4c9c93e93f429bb8a8b01c53d54d6bd53a3028 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Tue, 29 Mar 2016 19:14:27 +0300 Subject: [PATCH 1143/9938] hp206c: Initial support for reading sensor values Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 10 + drivers/iio/pressure/Makefile | 1 + drivers/iio/pressure/hp206c.c | 426 ++++++++++++++++++++++++++++++++++ 3 files changed, 437 insertions(+) create mode 100644 drivers/iio/pressure/hp206c.c diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 31c0e1fd2202..8de0192adea6 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -148,4 +148,14 @@ config T5403 To compile this driver as a module, choose M here: the module will be called t5403. +config HP206C + tristate "HOPERF HP206C precision barometer and altimeter sensor" + depends on I2C + help + Say yes here to build support for the HOPREF HP206C precision + barometer and altimeter sensor. + + This driver can also be built as a module. If so, the module will + be called hp206c. + endmenu diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index d336af14f3fe..6e60863c1086 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o st_pressure-y := st_pressure_core.o st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o obj-$(CONFIG_T5403) += t5403.o +obj-$(CONFIG_HP206C) += hp206c.o obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c new file mode 100644 index 000000000000..90f2b6e4a920 --- /dev/null +++ b/drivers/iio/pressure/hp206c.c @@ -0,0 +1,426 @@ +/* + * hp206c.c - HOPERF HP206C precision barometer and altimeter sensor + * + * Copyright (c) 2016, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * (7-bit I2C slave address 0x76) + * + * Datasheet: + * http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf + */ + +#include +#include +#include +#include +#include +#include +#include + +/* I2C commands: */ +#define HP206C_CMD_SOFT_RST 0x06 + +#define HP206C_CMD_ADC_CVT 0x40 + +#define HP206C_CMD_ADC_CVT_OSR_4096 0x00 +#define HP206C_CMD_ADC_CVT_OSR_2048 0x04 +#define HP206C_CMD_ADC_CVT_OSR_1024 0x08 +#define HP206C_CMD_ADC_CVT_OSR_512 0x0c +#define HP206C_CMD_ADC_CVT_OSR_256 0x10 +#define HP206C_CMD_ADC_CVT_OSR_128 0x14 + +#define HP206C_CMD_ADC_CVT_CHNL_PT 0x00 +#define HP206C_CMD_ADC_CVT_CHNL_T 0x02 + +#define HP206C_CMD_READ_P 0x30 +#define HP206C_CMD_READ_T 0x32 + +#define HP206C_CMD_READ_REG 0x80 +#define HP206C_CMD_WRITE_REG 0xc0 + +#define HP206C_REG_INT_EN 0x0b +#define HP206C_REG_INT_CFG 0x0c + +#define HP206C_REG_INT_SRC 0x0d +#define HP206C_FLAG_DEV_RDY 0x40 + +#define HP206C_REG_PARA 0x0f +#define HP206C_FLAG_CMPS_EN 0x80 + +/* Maximum spin for DEV_RDY */ +#define HP206C_MAX_DEV_RDY_WAIT_COUNT 20 +#define HP206C_DEV_RDY_WAIT_US 20000 + +struct hp206c_data { + struct mutex mutex; + struct i2c_client *client; + int temp_osr_index; + int pres_osr_index; +}; + +struct hp206c_osr_setting { + u8 osr_mask; + unsigned int temp_conv_time_us; + unsigned int pres_conv_time_us; +}; + +/* Data from Table 5 in datasheet. */ +static const struct hp206c_osr_setting hp206c_osr_settings[] = { + { HP206C_CMD_ADC_CVT_OSR_4096, 65600, 131100 }, + { HP206C_CMD_ADC_CVT_OSR_2048, 32800, 65600 }, + { HP206C_CMD_ADC_CVT_OSR_1024, 16400, 32800 }, + { HP206C_CMD_ADC_CVT_OSR_512, 8200, 16400 }, + { HP206C_CMD_ADC_CVT_OSR_256, 4100, 8200 }, + { HP206C_CMD_ADC_CVT_OSR_128, 2100, 4100 }, +}; +static const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 }; +static const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128"; + +static inline int hp206c_read_reg(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg); +} + +static inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val) +{ + return i2c_smbus_write_byte_data(client, + HP206C_CMD_WRITE_REG | reg, val); +} + +static int hp206c_read_20bit(struct i2c_client *client, u8 cmd) +{ + int ret; + u8 values[3]; + + ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values); + if (ret < 0) + return ret; + if (ret != 3) + return -EIO; + return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]); +} + +/* Spin for max 160ms until DEV_RDY is 1, or return error. */ +static int hp206c_wait_dev_rdy(struct iio_dev *indio_dev) +{ + int ret; + int count = 0; + struct hp206c_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + + while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) { + ret = hp206c_read_reg(client, HP206C_REG_INT_SRC); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret); + return ret; + } + if (ret & HP206C_FLAG_DEV_RDY) + return 0; + usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2); + } + return -ETIMEDOUT; +} + +static int hp206c_set_compensation(struct i2c_client *client, bool enabled) +{ + int val; + + val = hp206c_read_reg(client, HP206C_REG_PARA); + if (val < 0) + return val; + if (enabled) + val |= HP206C_FLAG_CMPS_EN; + else + val &= ~HP206C_FLAG_CMPS_EN; + + return hp206c_write_reg(client, HP206C_REG_PARA, val); +} + +/* Do a soft reset */ +static int hp206c_soft_reset(struct iio_dev *indio_dev) +{ + int ret; + struct hp206c_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + + ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST); + if (ret) { + dev_err(&client->dev, "Failed to reset device: %d\n", ret); + return ret; + } + + usleep_range(400, 600); + + ret = hp206c_wait_dev_rdy(indio_dev); + if (ret) { + dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret); + return ret; + } + + ret = hp206c_set_compensation(client, true); + if (ret) + dev_err(&client->dev, "Failed to enable compensation: %d\n", ret); + return ret; +} + +static int hp206c_conv_and_read(struct iio_dev *indio_dev, + u8 conv_cmd, u8 read_cmd, + unsigned int sleep_us) +{ + int ret; + struct hp206c_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + + ret = hp206c_wait_dev_rdy(indio_dev); + if (ret < 0) { + dev_err(&indio_dev->dev, "Device not ready: %d\n", ret); + return ret; + } + + ret = i2c_smbus_write_byte(client, conv_cmd); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed convert: %d\n", ret); + return ret; + } + + usleep_range(sleep_us, sleep_us * 3 / 2); + + ret = hp206c_wait_dev_rdy(indio_dev); + if (ret < 0) { + dev_err(&indio_dev->dev, "Device not ready: %d\n", ret); + return ret; + } + + ret = hp206c_read_20bit(client, read_cmd); + if (ret < 0) + dev_err(&indio_dev->dev, "Failed read: %d\n", ret); + + return ret; +} + +static int hp206c_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + int ret; + struct hp206c_data *data = iio_priv(indio_dev); + const struct hp206c_osr_setting *osr_setting; + u8 conv_cmd; + + mutex_lock(&data->mutex); + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + switch (chan->type) { + case IIO_TEMP: + *val = hp206c_osr_rates[data->temp_osr_index]; + ret = IIO_VAL_INT; + break; + + case IIO_PRESSURE: + *val = hp206c_osr_rates[data->pres_osr_index]; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + } + break; + + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_TEMP: + osr_setting = &hp206c_osr_settings[data->temp_osr_index]; + conv_cmd = HP206C_CMD_ADC_CVT | + osr_setting->osr_mask | + HP206C_CMD_ADC_CVT_CHNL_T; + ret = hp206c_conv_and_read(indio_dev, + conv_cmd, + HP206C_CMD_READ_T, + osr_setting->temp_conv_time_us); + if (ret >= 0) { + /* 20 significant bits are provided. + * Extend sign over the rest. + */ + *val = sign_extend32(ret, 19); + ret = IIO_VAL_INT; + } + break; + + case IIO_PRESSURE: + osr_setting = &hp206c_osr_settings[data->pres_osr_index]; + conv_cmd = HP206C_CMD_ADC_CVT | + osr_setting->osr_mask | + HP206C_CMD_ADC_CVT_CHNL_PT; + ret = hp206c_conv_and_read(indio_dev, + conv_cmd, + HP206C_CMD_READ_P, + osr_setting->pres_conv_time_us); + if (ret >= 0) { + *val = ret; + ret = IIO_VAL_INT; + } + break; + default: + ret = -EINVAL; + } + break; + + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + *val = 0; + *val2 = 10000; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + + case IIO_PRESSURE: + *val = 0; + *val2 = 1000; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + ret = -EINVAL; + } + break; + + default: + ret = -EINVAL; + } + + mutex_unlock(&data->mutex); + return ret; +} + +static int hp206c_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret = 0; + struct hp206c_data *data = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO) + return -EINVAL; + mutex_lock(&data->mutex); + switch (chan->type) { + case IIO_TEMP: + data->temp_osr_index = find_closest_descending(val, + hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates)); + break; + case IIO_PRESSURE: + data->pres_osr_index = find_closest_descending(val, + hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates)); + break; + default: + ret = -EINVAL; + } + mutex_unlock(&data->mutex); + return ret; +} + +static const struct iio_chan_spec hp206c_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + }, + { + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + } +}; + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str); + +static struct attribute *hp206c_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group hp206c_attribute_group = { + .attrs = hp206c_attributes, +}; + +static const struct iio_info hp206c_info = { + .attrs = &hp206c_attribute_group, + .read_raw = hp206c_read_raw, + .write_raw = hp206c_write_raw, + .driver_module = THIS_MODULE, +}; + +static int hp206c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct hp206c_data *data; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + dev_err(&client->dev, "Adapter does not support " + "all required i2c functionality\n"); + return -ENODEV; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + mutex_init(&data->mutex); + + indio_dev->info = &hp206c_info; + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = hp206c_channels; + indio_dev->num_channels = ARRAY_SIZE(hp206c_channels); + + i2c_set_clientdata(client, indio_dev); + + /* Do a soft reset on probe */ + ret = hp206c_soft_reset(indio_dev); + if (ret) { + dev_err(&client->dev, "Failed to reset on startup: %d\n", ret); + return -ENODEV; + } + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id hp206c_id[] = { + {"hp206c"}, + {} +}; + +#ifdef CONFIG_ACPI +static const struct acpi_device_id hp206c_acpi_match[] = { + {"HOP206C", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match); +#endif + +static struct i2c_driver hp206c_driver = { + .probe = hp206c_probe, + .id_table = hp206c_id, + .driver = { + .name = "hp206c", + .acpi_match_table = ACPI_PTR(hp206c_acpi_match), + }, +}; + +module_i2c_driver(hp206c_driver); + +MODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor"); +MODULE_AUTHOR("Leonard Crestez "); +MODULE_LICENSE("GPL v2"); -- GitLab From 486294f184c05cff116160bb731cbb679f047621 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Tue, 29 Mar 2016 15:21:21 +0300 Subject: [PATCH 1144/9938] iio: accel: bmc150: use common definition for regmap conf bmc150_i2c_regmap_conf is defined three times (in bmc150-accel-core.c, bmc150-accel-i2c.c and and bmc150-accel-spi.c), although the definition is the same. Use one common definition for bmc150_i2c_regmap_conf in all included files. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-core.c | 3 ++- drivers/iio/accel/bmc150-accel-i2c.c | 7 +------ drivers/iio/accel/bmc150-accel-spi.c | 8 +------- drivers/iio/accel/bmc150-accel.h | 1 + 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index f3d096f3c539..e631ee9a6a77 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -246,11 +246,12 @@ static const struct { {500000, BMC150_ACCEL_SLEEP_500_MS}, {1000000, BMC150_ACCEL_SLEEP_1_SEC} }; -static const struct regmap_config bmc150_i2c_regmap_conf = { +const struct regmap_config bmc150_regmap_conf = { .reg_bits = 8, .val_bits = 8, .max_register = 0x3f, }; +EXPORT_SYMBOL_GPL(bmc150_regmap_conf); static int bmc150_accel_set_mode(struct bmc150_accel_data *data, enum bmc150_power_modes mode, diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index b41404ba32fc..8ca8041267ef 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -28,11 +28,6 @@ #include "bmc150-accel.h" -static const struct regmap_config bmc150_i2c_regmap_conf = { - .reg_bits = 8, - .val_bits = 8, -}; - static int bmc150_accel_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -43,7 +38,7 @@ static int bmc150_accel_probe(struct i2c_client *client, i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK); - regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf); + regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf); if (IS_ERR(regmap)) { dev_err(&client->dev, "Failed to initialize i2c regmap\n"); return PTR_ERR(regmap); diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c index 16b66f2a7204..006794a70a1f 100644 --- a/drivers/iio/accel/bmc150-accel-spi.c +++ b/drivers/iio/accel/bmc150-accel-spi.c @@ -25,18 +25,12 @@ #include "bmc150-accel.h" -static const struct regmap_config bmc150_spi_regmap_conf = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 0x3f, -}; - static int bmc150_accel_probe(struct spi_device *spi) { struct regmap *regmap; const struct spi_device_id *id = spi_get_device_id(spi); - regmap = devm_regmap_init_spi(spi, &bmc150_spi_regmap_conf); + regmap = devm_regmap_init_spi(spi, &bmc150_regmap_conf); if (IS_ERR(regmap)) { dev_err(&spi->dev, "Failed to initialize spi regmap\n"); return PTR_ERR(regmap); diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h index ba0335987f94..38a8b11f8c19 100644 --- a/drivers/iio/accel/bmc150-accel.h +++ b/drivers/iio/accel/bmc150-accel.h @@ -16,5 +16,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, const char *name, bool block_supported); int bmc150_accel_core_remove(struct device *dev); extern const struct dev_pm_ops bmc150_accel_pm_ops; +extern const struct regmap_config bmc150_regmap_conf; #endif /* _BMC150_ACCEL_H_ */ -- GitLab From fddcca5107051adf9e4481d2a79ae0616577fd2c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 29 Feb 2016 13:20:28 +0100 Subject: [PATCH 1145/9938] mtd: avoid stack overflow in MTD CFI code When map_word gets too large, we use a lot of kernel stack, and for MTD_MAP_BANK_WIDTH_32, this means we use more than the recommended 1024 bytes in a number of functions: drivers/mtd/chips/cfi_cmdset_0020.c: In function 'cfi_staa_write_buffers': drivers/mtd/chips/cfi_cmdset_0020.c:651:1: warning: the frame size of 1336 bytes is larger than 1024 bytes [-Wframe-larger-than=] drivers/mtd/chips/cfi_cmdset_0020.c: In function 'cfi_staa_erase_varsize': drivers/mtd/chips/cfi_cmdset_0020.c:972:1: warning: the frame size of 1208 bytes is larger than 1024 bytes [-Wframe-larger-than=] drivers/mtd/chips/cfi_cmdset_0001.c: In function 'do_write_buffer': drivers/mtd/chips/cfi_cmdset_0001.c:1835:1: warning: the frame size of 1240 bytes is larger than 1024 bytes [-Wframe-larger-than=] This can be avoided if all operations on the map word are done indirectly and the stack gets reused between the calls. We can mostly achieve this by selecting MTD_COMPLEX_MAPPINGS whenever MTD_MAP_BANK_WIDTH_32 is set, but for the case that no other bank width is enabled, we also need to use a non-constant map_bankwidth() to convince the compiler to use less stack. Signed-off-by: Arnd Bergmann [Brian: this patch mostly achieves its goal by forcing MTD_COMPLEX_MAPPINGS (and the accompanying indirection) for 256-bit mappings; the rest of the change is mostly a wash, though it helps reduce stack size slightly. If we really care about supporting 256-bit mappings though, we should consider rewriting some of this code to avoid keeping and assigning so many 256-bit objects on the stack.] Signed-off-by: Brian Norris --- drivers/mtd/chips/Kconfig | 1 + include/linux/mtd/map.h | 19 +++++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 3b3dabce58de..bbfa1f129266 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -115,6 +115,7 @@ config MTD_MAP_BANK_WIDTH_16 config MTD_MAP_BANK_WIDTH_32 bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY + select MTD_COMPLEX_MAPPINGS if HAS_IOMEM default n help If you wish to support CFI devices on a physical bus which is diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 5e0eb7ccabd4..3aa56e3104bb 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -122,18 +122,13 @@ #endif #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 -# ifdef map_bankwidth -# undef map_bankwidth -# define map_bankwidth(map) ((map)->bankwidth) -# undef map_bankwidth_is_large -# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) -# undef map_words -# define map_words(map) map_calc_words(map) -# else -# define map_bankwidth(map) 32 -# define map_bankwidth_is_large(map) (1) -# define map_words(map) map_calc_words(map) -# endif +/* always use indirect access for 256-bit to preserve kernel stack */ +# undef map_bankwidth +# define map_bankwidth(map) ((map)->bankwidth) +# undef map_bankwidth_is_large +# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) +# undef map_words +# define map_words(map) map_calc_words(map) #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32) #undef MAX_MAP_BANKWIDTH #define MAX_MAP_BANKWIDTH 32 -- GitLab From 2958ec177e400be1e26fc37e1759f84fa2c1761c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Mar 2016 21:34:25 -0400 Subject: [PATCH 1146/9938] aio: remove a pointless assignment the value is never used after that point Signed-off-by: Al Viro --- fs/aio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 155f84253f33..a6deaa78326d 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1447,8 +1447,6 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, return ret; } - len = ret; - if (rw == WRITE) file_start_write(file); -- GitLab From bc61384dcdd82a6faabafecdcd80040625db5e40 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Mar 2016 21:48:20 -0400 Subject: [PATCH 1147/9938] rw_verify_area(): saner calling conventions Lift length capping into the few callers that care about it. Most of them treat all non-negatives as "success" and ignore the capped value, and with good reasons. Make rw_verify_area() return 0 on success. Signed-off-by: Al Viro --- fs/read_write.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index cf377cf9dfe3..b1a0e6ca218f 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -410,11 +410,6 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos) } EXPORT_SYMBOL(vfs_iter_write); -/* - * rw_verify_area doesn't like huge counts. We limit - * them to something that fits in "int" so that others - * won't have to do range checks all the time. - */ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) { struct inode *inode; @@ -441,11 +436,8 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t if (retval < 0) return retval; } - retval = security_file_permission(file, + return security_file_permission(file, read_write == READ ? MAY_READ : MAY_WRITE); - if (retval) - return retval; - return count > MAX_RW_COUNT ? MAX_RW_COUNT : count; } static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) @@ -489,8 +481,9 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) return -EFAULT; ret = rw_verify_area(READ, file, pos, count); - if (ret >= 0) { - count = ret; + if (!ret) { + if (count > MAX_RW_COUNT) + count = MAX_RW_COUNT; ret = __vfs_read(file, buf, count, pos); if (ret > 0) { fsnotify_access(file); @@ -572,8 +565,9 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ return -EFAULT; ret = rw_verify_area(WRITE, file, pos, count); - if (ret >= 0) { - count = ret; + if (!ret) { + if (count > MAX_RW_COUNT) + count = MAX_RW_COUNT; file_start_write(file); ret = __vfs_write(file, buf, count, pos); if (ret > 0) { @@ -1323,7 +1317,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, retval = rw_verify_area(READ, in.file, &pos, count); if (retval < 0) goto fput_in; - count = retval; + if (count > MAX_RW_COUNT) + count = MAX_RW_COUNT; /* * Get output file, and verify that it is ok.. @@ -1341,7 +1336,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, retval = rw_verify_area(WRITE, out.file, &out_pos, count); if (retval < 0) goto fput_out; - count = retval; if (!max) max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); @@ -1485,11 +1479,12 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, if (flags != 0) return -EINVAL; - /* copy_file_range allows full ssize_t len, ignoring MAX_RW_COUNT */ ret = rw_verify_area(READ, file_in, &pos_in, len); - if (ret >= 0) - ret = rw_verify_area(WRITE, file_out, &pos_out, len); - if (ret < 0) + if (unlikely(ret)) + return ret; + + ret = rw_verify_area(WRITE, file_out, &pos_out, len); + if (unlikely(ret)) return ret; if (!(file_in->f_mode & FMODE_READ) || -- GitLab From 03cc0789a690eb9ab07070376252961caeae7441 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 2 Apr 2016 14:56:58 -0400 Subject: [PATCH 1148/9938] do_splice_to(): cap the size before passing to ->splice_read() pipe capacity won't exceed 2G anyway. Signed-off-by: Al Viro --- fs/splice.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/splice.c b/fs/splice.c index 9947b5c69664..a6b87b7e0745 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1143,6 +1143,9 @@ static long do_splice_to(struct file *in, loff_t *ppos, if (unlikely(ret < 0)) return ret; + if (unlikely(len > MAX_RW_COUNT)) + len = MAX_RW_COUNT; + if (in->f_op->splice_read) splice_read = in->f_op->splice_read; else -- GitLab From 5651d6aaf489d1db48c253cf884b40214e91c2c5 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 26 Feb 2016 11:50:28 +0100 Subject: [PATCH 1149/9938] mtd: bcm47xxsflash: use ioremap_cache() instead of KSEG0ADDR() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using KSEG0ADDR makes code highly MIPS dependent and not portable. Thanks to the fix a68f376 ("MIPS: io.h: Define `ioremap_cache'") we can use ioremap_cache which is generic and supported on MIPS as well now. KSEG0ADDR was translating 0x1c000000 into 0x9c000000. With ioremap_cache we use MIPS's __ioremap (and then remap_area_pages). This results in different address (e.g. 0xc0080000) but it still should be cached as expected and it was successfully tested with BCM47186B0. Other than that drivers/bcma/driver_chipcommon_sflash.c nicely setups a struct resource for access window, but we wren't using it. Use it now and drop duplicated info. Signed-off-by: Brian Norris Signed-off-by: Rafał Miłecki --- drivers/bcma/driver_chipcommon_sflash.c | 1 - drivers/mtd/devices/bcm47xxsflash.c | 29 +++++++++++++++++---- drivers/mtd/devices/bcm47xxsflash.h | 3 ++- include/linux/bcma/bcma_driver_chipcommon.h | 1 - 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index 04d706ca5f43..35b13a08ca3e 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c @@ -146,7 +146,6 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) return -ENOTSUPP; } - sflash->window = BCMA_SOC_FLASH2; sflash->blocksize = e->blocksize; sflash->numblocks = e->numblocks; sflash->size = sflash->blocksize * sflash->numblocks; diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 347bb83db864..1c65c15b31a1 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -109,8 +110,7 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, if ((from + len) > mtd->size) return -EINVAL; - memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from), - len); + memcpy_fromio(buf, b47s->window + from, len); *retlen = len; return len; @@ -275,15 +275,33 @@ static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset, static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) { - struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); + struct device *dev = &pdev->dev; + struct bcma_sflash *sflash = dev_get_platdata(dev); struct bcm47xxsflash *b47s; + struct resource *res; int err; - b47s = devm_kzalloc(&pdev->dev, sizeof(*b47s), GFP_KERNEL); + b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL); if (!b47s) return -ENOMEM; sflash->priv = b47s; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "invalid resource\n"); + return -EINVAL; + } + if (!devm_request_mem_region(dev, res->start, resource_size(res), + res->name)) { + dev_err(dev, "can't request region for resource %pR\n", res); + return -EBUSY; + } + b47s->window = ioremap_cache(res->start, resource_size(res)); + if (!b47s->window) { + dev_err(dev, "ioremap failed for resource %pR\n", res); + return -ENOMEM; + } + b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash); b47s->cc_read = bcm47xxsflash_bcma_cc_read; b47s->cc_write = bcm47xxsflash_bcma_cc_write; @@ -297,7 +315,6 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) break; } - b47s->window = sflash->window; b47s->blocksize = sflash->blocksize; b47s->numblocks = sflash->numblocks; b47s->size = sflash->size; @@ -306,6 +323,7 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); if (err) { pr_err("Failed to register MTD device: %d\n", err); + iounmap(b47s->window); return err; } @@ -321,6 +339,7 @@ static int bcm47xxsflash_bcma_remove(struct platform_device *pdev) struct bcm47xxsflash *b47s = sflash->priv; mtd_device_unregister(&b47s->mtd); + iounmap(b47s->window); return 0; } diff --git a/drivers/mtd/devices/bcm47xxsflash.h b/drivers/mtd/devices/bcm47xxsflash.h index fe93daf4f489..1564b62b412e 100644 --- a/drivers/mtd/devices/bcm47xxsflash.h +++ b/drivers/mtd/devices/bcm47xxsflash.h @@ -65,7 +65,8 @@ struct bcm47xxsflash { enum bcm47xxsflash_type type; - u32 window; + void __iomem *window; + u32 blocksize; u16 numblocks; u32 size; diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 846513c73606..a5ac2cad5cb7 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -587,7 +587,6 @@ struct mtd_info; struct bcma_sflash { bool present; - u32 window; u32 blocksize; u16 numblocks; u32 size; -- GitLab From 85d08340c3de1126467db4e69140fe483d91c114 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 2 Apr 2016 07:44:32 +0300 Subject: [PATCH 1150/9938] HID: roccat: silence an uninitialized variable warning My static checker complains because we use "dev_id" before we check for errors so it could be uninitialized. Fix this by moving the error handling forward a couple lines. Signed-off-by: Dan Carpenter Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index 65c4ccfcbd29..76d06cf87b2a 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -421,14 +421,13 @@ static int __init roccat_init(void) retval = alloc_chrdev_region(&dev_id, ROCCAT_FIRST_MINOR, ROCCAT_MAX_DEVICES, "roccat"); - - roccat_major = MAJOR(dev_id); - if (retval < 0) { pr_warn("can't get major number\n"); goto error; } + roccat_major = MAJOR(dev_id); + cdev_init(&roccat_cdev, &roccat_ops); retval = cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES); -- GitLab From 6edac6fde59e231bd297ebcbc3d1bd395006cd1d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 2 Apr 2016 07:45:01 +0300 Subject: [PATCH 1151/9938] HID: hidraw: silence an uninitialized variable warning My static checker complains that "devid" can be uninitialized if alloc_chrdev_region() fails. Fix this by moving the error hanling forward a couple lines. Signed-off-by: Dan Carpenter Signed-off-by: Jiri Kosina --- drivers/hid/hidraw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 9c2d7c23f296..4b981fd324e8 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -587,14 +587,13 @@ int __init hidraw_init(void) result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR, HIDRAW_MAX_DEVICES, "hidraw"); - - hidraw_major = MAJOR(dev_id); - if (result < 0) { pr_warn("can't get major number\n"); goto out; } + hidraw_major = MAJOR(dev_id); + hidraw_class = class_create(THIS_MODULE, "hidraw"); if (IS_ERR(hidraw_class)) { result = PTR_ERR(hidraw_class); -- GitLab From b94f7d5ddf1b114e66d9bcc07d0ead080470383b Mon Sep 17 00:00:00 2001 From: Yusuke Fujimaki Date: Sun, 3 Apr 2016 23:15:16 +0900 Subject: [PATCH 1152/9938] HID: asus: add support for VivoBook E200HA Asus X205TA and E200HA built-in keyboard contain wrong logical maximum value in report descriptor. This patch correct wrong logical maximum in report descriptor. Signed-off-by: Yusuke Fujimaki Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 +++++- drivers/hid/hid-asus.c | 12 ++++++++---- drivers/hid/hid-core.c | 2 +- drivers/hid/hid-ids.h | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 513c93e2c650..5646ca4b95de 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -138,7 +138,11 @@ config HID_ASUS tristate "Asus" depends on I2C_HID ---help--- - Support for Asus X205TA built-in keyboard via i2c. + Support for Asus notebook built-in keyboard via i2c. + + Supported devices: + - EeeBook X205TA + - VivoBook E200HA config HID_AUREAL tristate "Aureal" diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 1734e11298ed..7a811ec4f2e1 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -1,7 +1,11 @@ /* - * HID driver for Asus X205TA built-in keyboard. + * HID driver for Asus notebook built-in keyboard. * Fixes small logical maximum to match usage maximum. * + * Currently supported devices are: + * EeeBook X205TA + * VivoBook E200HA + * * Copyright (c) 2016 Yusuke Fujimaki * * This module based on hid-ortek by @@ -25,15 +29,15 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { - if (*rsize >= 180 && rdesc[54] == 0x25 && rdesc[55] == 0x65) { - hid_info(hdev, "Fixing up Asus X205TA report descriptor\n"); + if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) { + hid_info(hdev, "Fixing up Asus notebook report descriptor\n"); rdesc[55] = 0xdd; } return rdesc; } static const struct hid_device_id asus_devices[] = { - { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_X205TA_KEYBOARD) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) }, { } }; MODULE_DEVICE_TABLE(hid, asus_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7426b5aabf27..7f8105b5255a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1856,7 +1856,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_X205TA_KEYBOARD) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f83e7fd0626b..1219e59626ce 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -163,7 +163,7 @@ #define USB_VENDOR_ID_ASUSTEK 0x0b05 #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b -#define USB_DEVICE_ID_ASUSTEK_X205TA_KEYBOARD 0x8585 +#define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD 0x8585 #define USB_VENDOR_ID_ATEN 0x0557 #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 -- GitLab From 20c5ea4fc131dc45c2639653b5b7aeeb2d4d0d1e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 4 Mar 2016 10:05:39 +0100 Subject: [PATCH 1153/9938] ARM: reintroduce ioremap_cached() for creating cached I/O mappings The original ARM-only ioremap flavor 'ioremap_cached' has been renamed to 'ioremap_cache' to align with other architectures, and subsequently abused in generic code to map things like firmware tables in memory. For that reason, there is currently an effort underway to deprecate ioremap_cache, whose semantics are poorly defined, and which is typed with an __iomem annotation that is inappropriate for mappings of ordinary memory. However, original users of ioremap_cached() used it in a context where the I/O connotation is appropriate, and replacing those instances with memremap() does not make sense. So let's revive ioremap_cached(), so that we can change back those original users before we drop ioremap_cache entirely in favor of memremap. Cc: Russell King Acked-by: Dan Williams Signed-off-by: Ard Biesheuvel --- arch/arm/include/asm/io.h | 6 ++++++ arch/arm/mm/ioremap.c | 4 ++++ arch/arm/mm/nommu.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 485982084fe9..fb94de290edd 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -395,6 +395,12 @@ void __iomem *ioremap(resource_size_t res_cookie, size_t size); void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size); #define ioremap_cache ioremap_cache +/* + * Do not use ioremap_cached in new code. Provided for the benefit of + * the pxa2xx-flash MTD driver only. + */ +void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size); + void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size); #define ioremap_wc ioremap_wc #define ioremap_wt ioremap_wc diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 66a978d05958..d5350f6af089 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -380,11 +380,15 @@ void __iomem *ioremap(resource_size_t res_cookie, size_t size) EXPORT_SYMBOL(ioremap); void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) + __alias(ioremap_cached); + +void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size) { return arch_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, __builtin_return_address(0)); } EXPORT_SYMBOL(ioremap_cache); +EXPORT_SYMBOL(ioremap_cached); void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) { diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 1dd10936d68d..f24967e8ff7f 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -367,11 +367,15 @@ void __iomem *ioremap(resource_size_t res_cookie, size_t size) EXPORT_SYMBOL(ioremap); void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) + __alias(ioremap_cached); + +void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size) { return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, __builtin_return_address(0)); } EXPORT_SYMBOL(ioremap_cache); +EXPORT_SYMBOL(ioremap_cached); void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) { -- GitLab From 7769aea2a27db8f12859dcecce37a3da44ab588b Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 25 Feb 2016 08:57:52 +0100 Subject: [PATCH 1154/9938] mtd: pxa2xx-flash: switch back from memremap to ioremap_cached This reverts commit 06968a54790d ("mtd: pxa2xx-flash: switch from ioremap_cache to memremap"), since NOR with memory semantics in array mode and RAM are not necessarily the same thing, and architectures may implement ioremap_cached() and memremap() with different memory attributes. For this reason, ioremap_cached() has been brought back from the dead on the ARM side, so switch this driver back to using it instead of memremap(). Cc: David Woodhouse Acked-by: Brian Norris Acked-by: Dan Williams Signed-off-by: Ard Biesheuvel --- drivers/mtd/maps/pxa2xx-flash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 7497090e9900..2cde28ed95c9 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -71,8 +71,8 @@ static int pxa2xx_flash_probe(struct platform_device *pdev) info->map.name); return -ENOMEM; } - info->map.cached = memremap(info->map.phys, info->map.size, - MEMREMAP_WB); + info->map.cached = + ioremap_cached(info->map.phys, info->map.size); if (!info->map.cached) printk(KERN_WARNING "Failed to ioremap cached %s\n", info->map.name); @@ -111,7 +111,7 @@ static int pxa2xx_flash_remove(struct platform_device *dev) map_destroy(info->mtd); iounmap(info->map.virt); if (info->map.cached) - memunmap(info->map.cached); + iounmap(info->map.cached); kfree(info); return 0; } -- GitLab From c269cba35b061181bc23c470809c00e8f71e535a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 22 Feb 2016 15:02:07 +0100 Subject: [PATCH 1155/9938] memremap: add arch specific hook for MEMREMAP_WB mappings Currently, the memremap code serves MEMREMAP_WB mappings directly from the kernel direct mapping, unless the region is in high memory, in which case it falls back to using ioremap_cache(). However, the semantics of ioremap_cache() are not unambiguously defined, and on ARM, it will actually result in a mapping type that differs from the attributes used for the linear mapping, and for this reason, the ioremap_cache() call fails if the region is part of the memory managed by the kernel. So instead, implement an optional hook 'arch_memremap_wb' whose default implementation calls ioremap_cache() as before, but which can be overridden by the architecture to do what is appropriate for it. Acked-by: Dan Williams Signed-off-by: Ard Biesheuvel --- kernel/memremap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/memremap.c b/kernel/memremap.c index a6d382312e6f..017532193fb1 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c @@ -27,6 +27,13 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size) } #endif +#ifndef arch_memremap_wb +static void *arch_memremap_wb(resource_size_t offset, unsigned long size) +{ + return (__force void *)ioremap_cache(offset, size); +} +#endif + static void *try_ram_remap(resource_size_t offset, size_t size) { unsigned long pfn = PHYS_PFN(offset); @@ -34,7 +41,7 @@ static void *try_ram_remap(resource_size_t offset, size_t size) /* In the simple case just return the existing linear address */ if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn))) return __va(offset); - return NULL; /* fallback to ioremap_cache */ + return NULL; /* fallback to arch_memremap_wb */ } /** @@ -90,7 +97,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags) if (is_ram == REGION_INTERSECTS) addr = try_ram_remap(offset, size); if (!addr) - addr = ioremap_cache(offset, size); + addr = arch_memremap_wb(offset, size); } /* -- GitLab From 9ab9e4fce45379cb6a7dbf87cf8f8e6ba01853c2 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 22 Feb 2016 15:02:08 +0100 Subject: [PATCH 1156/9938] ARM: memremap: implement arch_memremap_wb() The generic memremap() falls back to using ioremap_cache() to create MEMREMAP_WB mappings if the requested region is not already covered by the linear mapping, unless the architecture provides an implementation of arch_memremap_wb(). Since ioremap_cache() is not appropriate on ARM to map memory with the same attributes used for the linear mapping, implement arch_memremap_wb() which does exactly that. Also, relax the WARN() check to allow MT_MEMORY_RW mappings of pfn_valid() pages. Cc: Russell King Acked-by: Dan Williams Signed-off-by: Ard Biesheuvel --- arch/arm/include/asm/io.h | 6 ++++++ arch/arm/mm/ioremap.c | 12 ++++++++++-- arch/arm/mm/nommu.c | 5 +++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index fb94de290edd..781ef5fe235d 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -392,6 +392,9 @@ void __iomem *ioremap(resource_size_t res_cookie, size_t size); #define ioremap ioremap #define ioremap_nocache ioremap +/* + * Do not use ioremap_cache for mapping memory. Use memremap instead. + */ void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size); #define ioremap_cache ioremap_cache @@ -408,6 +411,9 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size); void iounmap(volatile void __iomem *iomem_cookie); #define iounmap iounmap +void *arch_memremap_wb(phys_addr_t phys_addr, size_t size); +#define arch_memremap_wb arch_memremap_wb + /* * io{read,write}{16,32}be() macros */ diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index d5350f6af089..ff0eed23ddf1 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -297,9 +297,10 @@ static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, } /* - * Don't allow RAM to be mapped - this causes problems with ARMv6+ + * Don't allow RAM to be mapped with mismatched attributes - this + * causes problems with ARMv6+ */ - if (WARN_ON(pfn_valid(pfn))) + if (WARN_ON(pfn_valid(pfn) && mtype != MT_MEMORY_RW)) return NULL; area = get_vm_area_caller(size, VM_IOREMAP, caller); @@ -418,6 +419,13 @@ __arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached) __builtin_return_address(0)); } +void *arch_memremap_wb(phys_addr_t phys_addr, size_t size) +{ + return (__force void *)arch_ioremap_caller(phys_addr, size, + MT_MEMORY_RW, + __builtin_return_address(0)); +} + void __iounmap(volatile void __iomem *io_addr) { void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index f24967e8ff7f..ca6d8e8ca1f8 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -384,6 +384,11 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) } EXPORT_SYMBOL(ioremap_wc); +void *arch_memremap_wb(phys_addr_t phys_addr, size_t size) +{ + return (void *)phys_addr; +} + void __iounmap(volatile void __iomem *addr) { } -- GitLab From b0afd44bc192ff4c0e90a5fc1724350bcfc32b33 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 26 Jan 2016 11:58:07 +0100 Subject: [PATCH 1157/9938] mtd: physmap_of: add a hook for Versatile write protection In order to support device tree probing of Versatile NOR flash chips, there must be a way to add the VPP (write protection) enable/disable callback. The register in question is in the system controllers of these machines. Apart from this quirk, the ARM flash chips are standard CFI flash chips from various vendors. Additionally, the Integrator/AP require you to set up the external bus interface (EBI) to allow writes to the chip select where the flash memory is connected. Solve this by looking for the arm,versatile-flash compatible string in the flash device tree node. In the driver, add a special hook to check for the various Versatile syscons and register a callback for .set_vpp() if this compatible is present. Provide a special Kconfig entry for the addon hook so it will not be compiled in if the Versatile boards are not supported. Stubs in the header file make sure the impact will be zero on other platforms. (Compilers optimze this out.) With this patch, a large slew of ARM board file code can be removed. Cc: Grant Likely Cc: Rob Herring Cc: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/mtd/maps/Kconfig | 10 + drivers/mtd/maps/Makefile | 1 + drivers/mtd/maps/physmap_of.c | 6 + drivers/mtd/maps/physmap_of_versatile.c | 253 ++++++++++++++++++++++++ drivers/mtd/maps/physmap_of_versatile.h | 16 ++ 5 files changed, 286 insertions(+) create mode 100644 drivers/mtd/maps/physmap_of_versatile.c create mode 100644 drivers/mtd/maps/physmap_of_versatile.h diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 7c95a656f9e4..392f9eff5fb7 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -74,6 +74,16 @@ config MTD_PHYSMAP_OF physically into the CPU's memory. The mapping description here is taken from OF device tree. +config MTD_PHYSMAP_OF_VERSATILE + bool "Support ARM Versatile physmap OF" + depends on MTD_PHYSMAP_OF + depends on MFD_SYSCON + default y if (ARCH_INTEGRATOR || ARCH_VERSATILE || REALVIEW_DT) + help + This provides some extra DT physmap parsing for the ARM Versatile + platforms, basically to add a VPP (write protection) callback so + the flash can be taken out of write protection. + config MTD_PMC_MSP_EVM tristate "CFI Flash device mapped on PMC-Sierra MSP" depends on PMC_MSP && MTD_CFI diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 141c91a5b24c..188873a72f1d 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o obj-$(CONFIG_MTD_PHYSMAP) += physmap.o obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o +obj-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o obj-$(CONFIG_MTD_PISMO) += pismo.o obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 70c453144f00..22f3858c0364 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -24,6 +24,7 @@ #include #include #include +#include "physmap_of_versatile.h" struct of_flash_list { struct mtd_info *mtd; @@ -240,6 +241,11 @@ static int of_flash_probe(struct platform_device *dev) info->list[i].map.size = res_size; info->list[i].map.bankwidth = be32_to_cpup(width); info->list[i].map.device_node = dp; + err = of_flash_probe_versatile(dev, dp, &info->list[i].map); + if (err) { + dev_err(&dev->dev, "Can't probe Versatile VPP\n"); + return err; + } err = -ENOMEM; info->list[i].map.virt = ioremap(info->list[i].map.phys, diff --git a/drivers/mtd/maps/physmap_of_versatile.c b/drivers/mtd/maps/physmap_of_versatile.c new file mode 100644 index 000000000000..fa40539e0d7f --- /dev/null +++ b/drivers/mtd/maps/physmap_of_versatile.c @@ -0,0 +1,253 @@ +/* + * Versatile OF physmap driver add-on + * + * Copyright (c) 2016, Linaro Limited + * Author: Linus Walleij + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "physmap_of_versatile.h" + +static struct regmap *syscon_regmap; + +enum versatile_flashprot { + INTEGRATOR_AP_FLASHPROT, + INTEGRATOR_CP_FLASHPROT, + VERSATILE_FLASHPROT, + REALVIEW_FLASHPROT, +}; + +static const struct of_device_id syscon_match[] = { + { + .compatible = "arm,integrator-ap-syscon", + .data = (void *)INTEGRATOR_AP_FLASHPROT, + }, + { + .compatible = "arm,integrator-cp-syscon", + .data = (void *)INTEGRATOR_CP_FLASHPROT, + }, + { + .compatible = "arm,core-module-versatile", + .data = (void *)VERSATILE_FLASHPROT, + }, + { + .compatible = "arm,realview-eb-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pb1176-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pb11mp-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pba8-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pbx-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + {}, +}; + +/* + * Flash protection handling for the Integrator/AP + */ +#define INTEGRATOR_SC_CTRLS_OFFSET 0x08 +#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C +#define INTEGRATOR_SC_CTRL_FLVPPEN BIT(1) +#define INTEGRATOR_SC_CTRL_FLWP BIT(2) + +#define INTEGRATOR_EBI_CSR1_OFFSET 0x04 +/* The manual says bit 2, the code says bit 3, trust the code */ +#define INTEGRATOR_EBI_WRITE_ENABLE BIT(3) +#define INTEGRATOR_EBI_LOCK_OFFSET 0x20 +#define INTEGRATOR_EBI_LOCK_VAL 0xA05F + +static const struct of_device_id ebi_match[] = { + { .compatible = "arm,external-bus-interface"}, + { }, +}; + +static int ap_flash_init(struct platform_device *pdev) +{ + struct device_node *ebi; + static void __iomem *ebi_base; + u32 val; + int ret; + + /* Look up the EBI */ + ebi = of_find_matching_node(NULL, ebi_match); + if (!ebi) { + return -ENODEV; + } + ebi_base = of_iomap(ebi, 0); + if (!ebi_base) + return -ENODEV; + + /* Clear VPP and write protection bits */ + ret = regmap_write(syscon_regmap, + INTEGRATOR_SC_CTRLC_OFFSET, + INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); + if (ret) + dev_err(&pdev->dev, "error clearing Integrator VPP/WP\n"); + + /* Unlock the EBI */ + writel(INTEGRATOR_EBI_LOCK_VAL, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); + + /* Enable write cycles on the EBI, CSR1 (flash) */ + val = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); + val |= INTEGRATOR_EBI_WRITE_ENABLE; + writel(val, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); + + /* Lock the EBI again */ + writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); + iounmap(ebi_base); + + return 0; +} + +static void ap_flash_set_vpp(struct map_info *map, int on) +{ + int ret; + + if (on) { + ret = regmap_write(syscon_regmap, + INTEGRATOR_SC_CTRLS_OFFSET, + INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); + if (ret) + pr_err("error enabling AP VPP\n"); + } else { + ret = regmap_write(syscon_regmap, + INTEGRATOR_SC_CTRLC_OFFSET, + INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); + if (ret) + pr_err("error disabling AP VPP\n"); + } +} + +/* + * Flash protection handling for the Integrator/CP + */ + +#define INTCP_FLASHPROG_OFFSET 0x04 +#define CINTEGRATOR_FLVPPEN BIT(0) +#define CINTEGRATOR_FLWREN BIT(1) +#define CINTEGRATOR_FLMASK BIT(0)|BIT(1) + +static void cp_flash_set_vpp(struct map_info *map, int on) +{ + int ret; + + if (on) { + ret = regmap_update_bits(syscon_regmap, + INTCP_FLASHPROG_OFFSET, + CINTEGRATOR_FLMASK, + CINTEGRATOR_FLVPPEN | CINTEGRATOR_FLWREN); + if (ret) + pr_err("error setting CP VPP\n"); + } else { + ret = regmap_update_bits(syscon_regmap, + INTCP_FLASHPROG_OFFSET, + CINTEGRATOR_FLMASK, + 0); + if (ret) + pr_err("error setting CP VPP\n"); + } +} + +/* + * Flash protection handling for the Versatiles and RealViews + */ + +#define VERSATILE_SYS_FLASH_OFFSET 0x4C + +static void versatile_flash_set_vpp(struct map_info *map, int on) +{ + int ret; + + ret = regmap_update_bits(syscon_regmap, VERSATILE_SYS_FLASH_OFFSET, + 0x01, !!on); + if (ret) + pr_err("error setting Versatile VPP\n"); +} + +int of_flash_probe_versatile(struct platform_device *pdev, + struct device_node *np, + struct map_info *map) +{ + struct device_node *sysnp; + const struct of_device_id *devid; + struct regmap *rmap; + static enum versatile_flashprot versatile_flashprot; + int ret; + + /* Not all flash chips use this protection line */ + if (!of_device_is_compatible(np, "arm,versatile-flash")) + return 0; + + /* For first chip probed, look up the syscon regmap */ + if (!syscon_regmap) { + sysnp = of_find_matching_node_and_match(NULL, + syscon_match, + &devid); + if (!sysnp) + return -ENODEV; + + versatile_flashprot = (enum versatile_flashprot)devid->data; + rmap = syscon_node_to_regmap(sysnp); + if (IS_ERR(rmap)) + return PTR_ERR(rmap); + + syscon_regmap = rmap; + } + + switch (versatile_flashprot) { + case INTEGRATOR_AP_FLASHPROT: + ret = ap_flash_init(pdev); + if (ret) + return ret; + map->set_vpp = ap_flash_set_vpp; + dev_info(&pdev->dev, "Integrator/AP flash protection\n"); + break; + case INTEGRATOR_CP_FLASHPROT: + map->set_vpp = cp_flash_set_vpp; + dev_info(&pdev->dev, "Integrator/CP flash protection\n"); + break; + case VERSATILE_FLASHPROT: + case REALVIEW_FLASHPROT: + map->set_vpp = versatile_flash_set_vpp; + dev_info(&pdev->dev, "versatile/realview flash protection\n"); + break; + default: + dev_info(&pdev->dev, "device marked as Versatile flash " + "but no system controller was found\n"); + break; + } + + return 0; +} diff --git a/drivers/mtd/maps/physmap_of_versatile.h b/drivers/mtd/maps/physmap_of_versatile.h new file mode 100644 index 000000000000..5b86f6dc6b3d --- /dev/null +++ b/drivers/mtd/maps/physmap_of_versatile.h @@ -0,0 +1,16 @@ +#include +#include + +#ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE +int of_flash_probe_versatile(struct platform_device *pdev, + struct device_node *np, + struct map_info *map); +#else +static inline +int of_flash_probe_versatile(struct platform_device *pdev, + struct device_node *np, + struct map_info *map) +{ + return 0; +} +#endif -- GitLab From 81fc3eb2b3c253b9aa5f55b6af5246a6c431dbf4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 26 Jan 2016 12:00:13 +0100 Subject: [PATCH 1158/9938] mtd: augment the "arm,versatile-flash" bindings The bindings for the "arm,versatile-flash" device was merged in commit 3ba7222ac992d24d09ccd0b55940b54849eef752 "arm/versatile: Add device tree support" but was never used for anything. Versatile flash chips are actually just standard CFI chips, but they have one or two bits in a system controller to control VPP and write protection. Let's use this compatible string in conjunction with "cfi-flash" to indicate that we have a normal CFI flash with some extra Versatile-specific protection. Cc: devicetree@vger.kernel.org Cc: Grant Likely Cc: Arnd Bergmann Cc: Mark Rutland Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../devicetree/bindings/mtd/arm-versatile.txt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/arm-versatile.txt b/Documentation/devicetree/bindings/mtd/arm-versatile.txt index beace4b89daa..4ec28796a3c0 100644 --- a/Documentation/devicetree/bindings/mtd/arm-versatile.txt +++ b/Documentation/devicetree/bindings/mtd/arm-versatile.txt @@ -1,8 +1,26 @@ Flash device on ARM Versatile board +These flash chips are found in the ARM reference designs like Integrator, +Versatile, RealView, Versatile Express etc. + +They are regular CFI compatible (Intel or AMD extended) flash chips with +some special write protect/VPP bits that can be controlled by the machine's +system controller. + Required properties: -- compatible : must be "arm,versatile-flash"; +- compatible : must be "arm,versatile-flash", "cfi-flash"; +- reg : memory address for the flash chip - bank-width : width in bytes of flash interface. +For the rest of the properties, see mtd-physmap.txt. + The device tree may optionally contain sub-nodes describing partitions of the address space. See partition.txt for more detail. + +Example: + +flash@34000000 { + compatible = "arm,versatile-flash", "cfi-flash"; + reg = <0x34000000 0x4000000>; + bank-width = <4>; +}; -- GitLab From 7bb73fd719805dc40616d0c0dcd1d2d1e17b9b23 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 26 Jan 2016 10:55:32 +0100 Subject: [PATCH 1159/9938] ARM: versatile: move flash registration to the device tree This moves the boardfile definition of the flash memory in the Versatile board into the device tree. The flash was already defined with the property "arm,versatile-flash" which was not handled by the kernel: instead define it as compatible also with "cfi-flash" so it detects properly, and delete the corresponding boardfile code so we get a smooth transition. The old compatible string "arm,versatile-flash" is reused to indicate to the MTD physmap subsystem that this flash requires special VPP handling. (See separate patch.) Cc: Grant Likely Cc: Rob Herring Cc: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/boot/dts/versatile-ab.dts | 5 +-- arch/arm/mach-versatile/versatile_dt.c | 47 -------------------------- 2 files changed, 3 insertions(+), 49 deletions(-) diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts index d23320af5ea7..409e069b3a84 100644 --- a/arch/arm/boot/dts/versatile-ab.dts +++ b/arch/arm/boot/dts/versatile-ab.dts @@ -119,8 +119,9 @@ }; flash@34000000 { - compatible = "arm,versatile-flash"; - reg = <0x34000000 0x4000000>; + /* 64 MiB NOR flash in non-interleaved chips */ + compatible = "arm,versatile-flash", "cfi-flash"; + reg = <0x34000000 0x04000000>; bank-width = <4>; }; diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c index dff1c0595b67..d643b9210dbd 100644 --- a/arch/arm/mach-versatile/versatile_dt.c +++ b/arch/arm/mach-versatile/versatile_dt.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -41,12 +40,6 @@ #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) #define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n)) -/* - * Memory definitions - */ -#define VERSATILE_FLASH_BASE 0x34000000 -#define VERSATILE_FLASH_SIZE SZ_64M - /* * ------------------------------------------------------------------------ * Versatile Registers @@ -54,14 +47,8 @@ */ #define VERSATILE_SYS_PCICTL_OFFSET 0x44 #define VERSATILE_SYS_MCI_OFFSET 0x48 -#define VERSATILE_SYS_FLASH_OFFSET 0x4C #define VERSATILE_SYS_CLCD_OFFSET 0x50 -/* - * VERSATILE_SYS_FLASH - */ -#define VERSATILE_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */ - /* * VERSATILE peripheral addresses */ @@ -86,39 +73,6 @@ static void __iomem *versatile_sys_base; static void __iomem *versatile_ib2_ctrl; -static void versatile_flash_set_vpp(struct platform_device *pdev, int on) -{ - u32 val; - - val = readl(versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET); - if (on) - val |= VERSATILE_FLASHPROG_FLVPPEN; - else - val &= ~VERSATILE_FLASHPROG_FLVPPEN; - writel(val, versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET); -} - -static struct physmap_flash_data versatile_flash_data = { - .width = 4, - .set_vpp = versatile_flash_set_vpp, -}; - -static struct resource versatile_flash_resource = { - .start = VERSATILE_FLASH_BASE, - .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -struct platform_device versatile_flash_device = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &versatile_flash_data, - }, - .num_resources = 1, - .resource = &versatile_flash_resource, -}; - unsigned int mmc_status(struct device *dev) { struct amba_device *adev = container_of(dev, struct amba_device, dev); @@ -390,7 +344,6 @@ static void __init versatile_dt_init(void) versatile_dt_pci_init(); - platform_device_register(&versatile_flash_device); of_platform_populate(NULL, of_default_bus_match_table, versatile_auxdata_lookup, NULL); } -- GitLab From 91011a7605822cd9c16eabcd1cc11ae31d604bfd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 26 Jan 2016 11:09:22 +0100 Subject: [PATCH 1160/9938] ARM: integrator: move flash registration to device tree The flash on the Integrator was already defined by the device tree, but VPP control and flash protection was in the boardfiles. Simply add the compatible string "arm,versatile-flash" and the special add-on code for flash programming voltage and protection kicks in in the MTD layer. Remove the board file code and augment the device tree in one go for seamless transition. Cc: Grant Likely Cc: Rob Herring Cc: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/boot/dts/integrator.dtsi | 3 +- arch/arm/mach-integrator/integrator_ap.c | 62 ------------------------ arch/arm/mach-integrator/integrator_cp.c | 51 ------------------- 3 files changed, 2 insertions(+), 114 deletions(-) diff --git a/arch/arm/boot/dts/integrator.dtsi b/arch/arm/boot/dts/integrator.dtsi index b82f0e6d9a63..6fe0dd1d3541 100644 --- a/arch/arm/boot/dts/integrator.dtsi +++ b/arch/arm/boot/dts/integrator.dtsi @@ -52,8 +52,9 @@ }; flash@24000000 { - compatible = "cfi-flash"; + compatible = "arm,versatile-flash", "cfi-flash"; reg = <0x24000000 0x02000000>; + bank-width = <4>; }; fpga { diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 5b0e363fe5ba..2b118f20c62c 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -146,65 +145,6 @@ static int __init irq_syscore_init(void) device_initcall(irq_syscore_init); -/* - * Flash handling. - */ -static int ap_flash_init(struct platform_device *dev) -{ - u32 tmp; - - writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, - ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); - - tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) | - INTEGRATOR_EBI_WRITE_ENABLE; - writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - - if (!(readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) - & INTEGRATOR_EBI_WRITE_ENABLE)) { - writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); - writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); - } - return 0; -} - -static void ap_flash_exit(struct platform_device *dev) -{ - u32 tmp; - - writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, - ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); - - tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) & - ~INTEGRATOR_EBI_WRITE_ENABLE; - writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - - if (readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) & - INTEGRATOR_EBI_WRITE_ENABLE) { - writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); - writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); - } -} - -static void ap_flash_set_vpp(struct platform_device *pdev, int on) -{ - if (on) - writel(INTEGRATOR_SC_CTRL_nFLVPPEN, - ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET); - else - writel(INTEGRATOR_SC_CTRL_nFLVPPEN, - ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); -} - -static struct physmap_flash_data ap_flash_data = { - .width = 4, - .init = ap_flash_init, - .exit = ap_flash_exit, - .set_vpp = ap_flash_set_vpp, -}; - /* * For the PL010 found in the Integrator/AP some of the UART control is * implemented in the system controller and accessed using a callback @@ -266,8 +206,6 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = { "kmi0", NULL), OF_DEV_AUXDATA("arm,primecell", KMI1_BASE, "kmi1", NULL), - OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE, - "physmap-flash", &ap_flash_data), { /* sentinel */ }, }; diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index b5fb71a36ee6..6f6b051e81e0 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -43,14 +42,8 @@ /* Base address to the CP controller */ static void __iomem *intcp_con_base; -#define INTCP_PA_FLASH_BASE 0x24000000 - #define INTCP_PA_CLCD_BASE 0xc0000000 -#define INTCP_FLASHPROG 0x04 -#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0) -#define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1) - /* * Logical Physical * f1000000 10000000 Core module registers @@ -107,48 +100,6 @@ static void __init intcp_map_io(void) iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc)); } -/* - * Flash handling. - */ -static int intcp_flash_init(struct platform_device *dev) -{ - u32 val; - - val = readl(intcp_con_base + INTCP_FLASHPROG); - val |= CINTEGRATOR_FLASHPROG_FLWREN; - writel(val, intcp_con_base + INTCP_FLASHPROG); - - return 0; -} - -static void intcp_flash_exit(struct platform_device *dev) -{ - u32 val; - - val = readl(intcp_con_base + INTCP_FLASHPROG); - val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN); - writel(val, intcp_con_base + INTCP_FLASHPROG); -} - -static void intcp_flash_set_vpp(struct platform_device *pdev, int on) -{ - u32 val; - - val = readl(intcp_con_base + INTCP_FLASHPROG); - if (on) - val |= CINTEGRATOR_FLASHPROG_FLVPPEN; - else - val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN; - writel(val, intcp_con_base + INTCP_FLASHPROG); -} - -static struct physmap_flash_data intcp_flash_data = { - .width = 4, - .init = intcp_flash_init, - .exit = intcp_flash_exit, - .set_vpp = intcp_flash_set_vpp, -}; - /* * It seems that the card insertion interrupt remains active after * we've acknowledged it. We therefore ignore the interrupt, and @@ -260,8 +211,6 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = { "aaci", &mmc_data), OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE, "clcd", &clcd_data), - OF_DEV_AUXDATA("cfi-flash", INTCP_PA_FLASH_BASE, - "physmap-flash", &intcp_flash_data), { /* sentinel */ }, }; -- GitLab From 1a66ab2ddc4756ee2887301a55d502139fe37e73 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 4 Feb 2016 14:53:12 +0100 Subject: [PATCH 1161/9938] Documentation/DT: add blurb for IB2 syscon to Versatile The ARM Versatile has an optional daughterboard, if this is mounted, we need to be able to access its system controller. Put in a documentation blurb for this. Cc: Pawel Moll Cc: Rob Herring Cc: Russell King Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/arm/arm-boards | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards index 0226bc2cc1f6..ab318a56fca2 100644 --- a/Documentation/devicetree/bindings/arm/arm-boards +++ b/Documentation/devicetree/bindings/arm/arm-boards @@ -93,6 +93,14 @@ Required nodes: a core-module with regs and the compatible strings "arm,core-module-versatile", "syscon" +Optional nodes: + +- arm,versatile-ib2-syscon : if the Versatile has an IB2 interface + board mounted, this has a separate system controller that is + defined in this node. + Required properties: + compatible = "arm,versatile-ib2-syscon", "syscon" + ARM RealView Boards ------------------- The RealView boards cover tailored evaluation boards that are used to explore -- GitLab From 6096188af679b00aa4f55c641945628d3bd1c1bd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 1 Feb 2016 11:05:26 +0100 Subject: [PATCH 1162/9938] ARM: dts: realview: PB11MPCore: define a standard VGA panel Let's supply a standard VGA panel by default on the PB11MPCore, this will work with most monitors. If more screen real estate is desired, users can update the DPI definition. Cc: Pawel Moll Cc: Rob Herring Cc: Russell King Signed-off-by: Linus Walleij --- arch/arm/boot/dts/arm-realview-pb11mp.dts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/arm-realview-pb11mp.dts b/arch/arm/boot/dts/arm-realview-pb11mp.dts index 63d6a051839f..3944765ac4b0 100644 --- a/arch/arm/boot/dts/arm-realview-pb11mp.dts +++ b/arch/arm/boot/dts/arm-realview-pb11mp.dts @@ -627,16 +627,17 @@ }; }; + /* Standard 640x480 VGA timings */ panel-timing { - clock-frequency = <63500127>; - hactive = <1024>; - hback-porch = <152>; - hfront-porch = <48>; - hsync-len = <104>; - vactive = <768>; - vback-porch = <23>; - vfront-porch = <3>; - vsync-len = <4>; + clock-frequency = <25175000>; + hactive = <640>; + hback-porch = <48>; + hfront-porch = <16>; + hsync-len = <96>; + vactive = <480>; + vback-porch = <33>; + vfront-porch = <10>; + vsync-len = <2>; }; }; }; -- GitLab From 95109b8b4d425d48c802acfc5c6e38f55c6e7fb5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 1 Feb 2016 11:07:20 +0100 Subject: [PATCH 1163/9938] ARM: dts: realview: PB1176: define a standard VGA panel This defines the CLCD block in the PB1176 and adds a standard 640x480 VGA panel to the device tree. Cc: Pawel Moll Cc: Rob Herring Cc: Russell King Signed-off-by: Linus Walleij --- arch/arm/boot/dts/arm-realview-pb1176.dts | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm/boot/dts/arm-realview-pb1176.dts b/arch/arm/boot/dts/arm-realview-pb1176.dts index 652d85b28aaa..c789564f2803 100644 --- a/arch/arm/boot/dts/arm-realview-pb1176.dts +++ b/arch/arm/boot/dts/arm-realview-pb1176.dts @@ -394,6 +394,46 @@ reg = <0x10200000 0x4000>; bank-width = <1>; }; + + clcd@10112000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x10112000 0x1000>; + interrupt-parent = <&intc_dc1176>; + interrupt-names = "combined"; + interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&oscclk0>, <&pclk>; + clock-names = "clcdclk", "apb_pclk"; + + port { + clcd_pads: endpoint { + remote-endpoint = <&clcd_panel>; + arm,pl11x,tft-r0g0b0-pads = <0 8 16>; + }; + }; + + panel { + compatible = "panel-dpi"; + + port { + clcd_panel: endpoint { + remote-endpoint = <&clcd_pads>; + }; + }; + + /* Standard 640x480 VGA timings */ + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + hback-porch = <48>; + hfront-porch = <16>; + hsync-len = <96>; + vactive = <480>; + vback-porch = <33>; + vfront-porch = <10>; + vsync-len = <2>; + }; + }; + }; }; /* These peripherals are inside the FPGA rather than the DevChip */ -- GitLab From 2440d29d2ae2b4f3b1d1ae87c8130351793d6df6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 18 Feb 2016 14:23:31 +0100 Subject: [PATCH 1164/9938] ARM: dts: realview: support all the RealView EB board variants The ARM RealView Evaluation Baseboards are basically these: - The original ARMv5 EB board with an ARM926EJ-S, ARM1136 or ARM1176 core tile here described in arm-realview-eb.dts no matter which of these core tiles is being used. This can be emulated by QEMU "realview-eb" machine, which by default will have the ARM926EJ-S core tile. - The same board with one of three MPCore Core tiles: ARM11MPCore, not to be confused with the similar ARM PB11MPCore ARM11MPCore test system. This exist in two revisions: - Revision A modeled in arm-realview-eb-11mp.dts - Revision B modeled arm-realview-eb-11mp-revb.dts Revision B can be emulated by the QEMU "realview-eb-mpcore" machine, but to match the hardware also the argument -smp cpus=4 must be passed so that it has four CPU cores, like the hardware. There is also evidently from the code in the kernel a Cortex-A9 core tile for the EB, and this is modeled in arm-realview-eb-a9mp.dts based on the kernel boardfile. I have not found a user guide for this EB core tile on the ARM website and it seems uncommon. It is however included for completeness. Cc: Pawel Moll Cc: Peter Maydell Cc: Marc Zyngier Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/boot/dts/Makefile | 6 +- .../boot/dts/arm-realview-eb-11mp-revb.dts | 93 ++++ arch/arm/boot/dts/arm-realview-eb-11mp.dts | 74 +++ arch/arm/boot/dts/arm-realview-eb-a9mp.dts | 70 +++ arch/arm/boot/dts/arm-realview-eb-mp.dtsi | 225 +++++++++ arch/arm/boot/dts/arm-realview-eb.dts | 166 +++++++ arch/arm/boot/dts/arm-realview-eb.dtsi | 453 ++++++++++++++++++ 7 files changed, 1086 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts create mode 100644 arch/arm/boot/dts/arm-realview-eb-11mp.dts create mode 100644 arch/arm/boot/dts/arm-realview-eb-a9mp.dts create mode 100644 arch/arm/boot/dts/arm-realview-eb-mp.dtsi create mode 100644 arch/arm/boot/dts/arm-realview-eb.dts create mode 100644 arch/arm/boot/dts/arm-realview-eb.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..ea508fdc1fcc 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -552,7 +552,11 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-msm8974-sony-xperia-honami.dtb dtb-$(CONFIG_ARCH_REALVIEW) += \ arm-realview-pb1176.dtb \ - arm-realview-pb11mp.dtb + arm-realview-pb11mp.dtb \ + arm-realview-eb.dtb \ + arm-realview-eb-11mp.dtb \ + arm-realview-eb-11mp-revb.dtb \ + arm-realview-eb-a9mp.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3036-evb.dtb \ rk3036-kylin.dtb \ diff --git a/arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts b/arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts new file mode 100644 index 000000000000..e68527b0d552 --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts @@ -0,0 +1,93 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "arm-realview-eb-11mp.dts" + +/ { + model = "ARM RealView Emulation Baseboard with ARM11MPCore Rev B"; +}; + +/* + * The revision B has a distinctly different layout of the syscon, so + * append a specific compatible-string. + */ +&syscon { + compatible = "arm,realview-eb11mp-revb-syscon", "arm,realview-eb-syscon", "syscon", "simple-mfd"; +}; + +&intc { + reg = <0x10101000 0x1000>, + <0x10100100 0x100>; +}; + +&L2 { + reg = <0x10102000 0x1000>; +}; + +&scu { + reg = <0x10100000 0x100>; +}; + +&twd_timer { + reg = <0x10100600 0x20>; +}; + +&twd_wdog { + reg = <0x10100620 0x20>; +}; + +/* + * On revision B, we cannot reach the secondary interrupt + * controller, as a result, some peripherals that are dependent + * on their IRQ cannot be reached, so disable them. + */ +&intc_second { + status = "disabled"; +}; + +&gpio0 { + status = "disabled"; +}; + +&gpio1 { + status = "disabled"; +}; + +&gpio2 { + status = "disabled"; +}; + +&serial2 { + status = "disabled"; +}; + +&serial3 { + status = "disabled"; +}; + +&ssp { + status = "disabled"; +}; + +&wdog { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/arm-realview-eb-11mp.dts b/arch/arm/boot/dts/arm-realview-eb-11mp.dts new file mode 100644 index 000000000000..87ff602a2a2d --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-eb-11mp.dts @@ -0,0 +1,74 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/dts-v1/; +#include "arm-realview-eb-mp.dtsi" + +/ { + model = "ARM RealView Emulation Baseboard with ARM11MPCore Rev C"; + arm,hbi = <0x146>; + + /* + * This is the ARM11 MPCore tile (HBI-0146) used with the RealView EB. + * Reference: ARM DUI 0318F + * + * To run this machine with QEMU, specify the following: + * qemu-system-arm -M realview-eb-mpcore -smp cpus=4 + */ + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "arm,realview-smp"; + + MP11_0: cpu@0 { + device_type = "cpu"; + compatible = "arm,arm11mpcore"; + reg = <0>; + next-level-cache = <&L2>; + }; + + MP11_1: cpu@1 { + device_type = "cpu"; + compatible = "arm,arm11mpcore"; + reg = <1>; + next-level-cache = <&L2>; + }; + + MP11_2: cpu@2 { + device_type = "cpu"; + compatible = "arm,arm11mpcore"; + reg = <2>; + next-level-cache = <&L2>; + }; + + MP11_3: cpu@3 { + device_type = "cpu"; + compatible = "arm,arm11mpcore"; + reg = <3>; + next-level-cache = <&L2>; + }; + }; +}; + +&pmu { + interrupt-affinity = <&MP11_0>, <&MP11_1>, <&MP11_2>, <&MP11_3>; +}; diff --git a/arch/arm/boot/dts/arm-realview-eb-a9mp.dts b/arch/arm/boot/dts/arm-realview-eb-a9mp.dts new file mode 100644 index 000000000000..967684b3636c --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-eb-a9mp.dts @@ -0,0 +1,70 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/dts-v1/; +#include "arm-realview-eb-mp.dtsi" + +/ { + model = "ARM RealView EB Cortex A9 MPCore"; + + /* + * This is the Cortex A9 MPCore tile used with the + * RealView EB. + */ + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "arm,realview-smp"; + + A9_0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + next-level-cache = <&L2>; + }; + + A9_1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + next-level-cache = <&L2>; + }; + + A9_2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <2>; + next-level-cache = <&L2>; + }; + + A9_3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <3>; + next-level-cache = <&L2>; + }; + }; +}; + +&pmu { + interrupt-affinity = <&A9_0>, <&A9_1>, <&A9_2>, <&A9_3>; +}; diff --git a/arch/arm/boot/dts/arm-realview-eb-mp.dtsi b/arch/arm/boot/dts/arm-realview-eb-mp.dtsi new file mode 100644 index 000000000000..7b8d90b7aeea --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-eb-mp.dtsi @@ -0,0 +1,225 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include "arm-realview-eb.dtsi" + +/* + * This is the common include file for all MPCore variants of the + * Evaluation Baseboard, i.e. ARM11MPCore, ARM11MPCore Revision B + * and Cortex-A9 MPCore. + */ +/ { + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "arm,realview-eb-soc", "simple-bus"; + regmap = <&syscon>; + ranges; + + /* Primary interrupt controller in the test chip */ + intc: interrupt-controller@1f000100 { + compatible = "arm,eb11mp-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0x1f001000 0x1000>, + <0x1f000100 0x100>; + }; + + /* Secondary interrupt controller on the FPGA */ + intc_second: interrupt-controller@10040000 { + compatible = "arm,pl390"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0x10041000 0x1000>, + <0x10040000 0x100>; + interrupt-parent = <&intc>; + interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>; + }; + + L2: l2-cache { + compatible = "arm,l220-cache"; + reg = <0x1f002000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>, + <0 30 IRQ_TYPE_LEVEL_HIGH>, + <0 31 IRQ_TYPE_LEVEL_HIGH>; + cache-unified; + cache-level = <2>; + /* + * Override default cache size, sets and + * associativity as these may be erroneously set + * up by boot loader(s), probably for safety + * since th outer sync operation can cause the + * cache to hang unless disabled. + */ + cache-size = <1048576>; // 1MB + cache-sets = <4096>; + cache-line-size = <32>; + arm,shared-override; + arm,parity-enable; + arm,outer-sync-disable; + }; + + scu: scu@1f000000 { + compatible = "arm,arm11mp-scu"; + reg = <0x1f000000 0x100>; + }; + + twd_timer: timer@1f000600 { + compatible = "arm,arm11mp-twd-timer"; + reg = <0x1f000600 0x20>; + interrupt-parent = <&intc>; + interrupts = <1 13 0xf04>; + }; + + twd_wdog: watchdog@1f000620 { + compatible = "arm,arm11mp-twd-wdt"; + reg = <0x1f000620 0x20>; + interrupt-parent = <&intc>; + interrupts = <1 14 0xf04>; + }; + + /* PMU with one IRQ line per core */ + pmu: pmu@0 { + compatible = "arm,arm11mpcore-pmu"; + interrupt-parent = <&intc>; + interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>, + <0 18 IRQ_TYPE_LEVEL_HIGH>, + <0 19 IRQ_TYPE_LEVEL_HIGH>, + <0 20 IRQ_TYPE_LEVEL_HIGH>; + }; + }; +}; + +/* + * This adapts all the peripherals to the interrupt routing + * to the GIC on the core tile. + */ + +ðernet { + interrupt-parent = <&intc>; + interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>; +}; + +&usb { + interrupt-parent = <&intc>; + interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>; +}; + +&aaci { + interrupt-parent = <&intc>; + interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>; +}; + +&mmc { + interrupt-parent = <&intc>; + interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>, + <0 15 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi0 { + interrupt-parent = <&intc>; + interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi1 { + interrupt-parent = <&intc>; + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>; +}; + +&charlcd { + interrupt-parent = <&intc>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial0 { + interrupt-parent = <&intc>; + interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial1 { + interrupt-parent = <&intc>; + interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer01 { + interrupt-parent = <&intc>; + interrupts = <0 1 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer23 { + interrupt-parent = <&intc>; + interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>; +}; + +&rtc { + interrupt-parent = <&intc>; + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; +}; + +/* + * On revision A, these peripherals does not have their IRQ lines + * routed to the core tile, but they can be reached on the secondary + * GIC. + */ +&gpio0 { + interrupt-parent = <&intc_second>; + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio1 { + interrupt-parent = <&intc_second>; + interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio2 { + interrupt-parent = <&intc_second>; + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial2 { + interrupt-parent = <&intc_second>; + interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; +}; + +&serial3 { + interrupt-parent = <&intc_second>; + interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; +}; + +&ssp { + interrupt-parent = <&intc_second>; + interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; +}; + +&wdog { + interrupt-parent = <&intc_second>; + interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/arm-realview-eb.dts b/arch/arm/boot/dts/arm-realview-eb.dts new file mode 100644 index 000000000000..15431077f00c --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-eb.dts @@ -0,0 +1,166 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/dts-v1/; +#include +#include +#include "arm-realview-eb.dtsi" + +/ { + model = "ARM RealView Emulation Baseboard"; + compatible = "arm,realview-eb"; + arm,hbi = <0x140>; + + /* + * This is the core tile with the CPU and GIC etc for the + * ARM926EJ-S, ARM1136, ARM1176 that does not have L2 cache + * or PMU. + * + * To run this machine with QEMU, specify the following: + * qemu-system-arm -M realview-eb + * Unless specified, QEMU will emulate an ARM926EJ-S core tile. + * Switches -cpu arm1136 or -cpu arm1176 emulates the other + * core tiles. + */ + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "arm,realview-eb-soc", "simple-bus"; + regmap = <&syscon>; + ranges; + + intc: interrupt-controller@10040000 { + compatible = "arm,pl390"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0x10041000 0x1000>, + <0x10040000 0x100>; + }; + }; +}; + +/* + * This adapts all the peripherals to the interrupt routing + * to the GIC on the core tile. + */ + +ðernet { + interrupt-parent = <&intc>; + interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>; +}; + +&usb { + interrupt-parent = <&intc>; + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>; +}; + +&aaci { + interrupt-parent = <&intc>; + interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>; +}; + +&mmc { + interrupt-parent = <&intc>; + interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>, + <0 18 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi0 { + interrupt-parent = <&intc>; + interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi1 { + interrupt-parent = <&intc>; + interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>; +}; + +&charlcd { + interrupt-parent = <&intc>; + interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial0 { + interrupt-parent = <&intc>; + interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial1 { + interrupt-parent = <&intc>; + interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial2 { + interrupt-parent = <&intc>; + interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial3 { + interrupt-parent = <&intc>; + interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>; +}; + +&ssp { + interrupt-parent = <&intc>; + interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>; +}; + +&wdog { + interrupt-parent = <&intc>; + interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer01 { + interrupt-parent = <&intc>; + interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer23 { + interrupt-parent = <&intc>; + interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio0 { + interrupt-parent = <&intc>; + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio1 { + interrupt-parent = <&intc>; + interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio2 { + interrupt-parent = <&intc>; + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>; +}; + +&rtc { + interrupt-parent = <&intc>; + interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>; +}; + +&clcd { + interrupt-parent = <&intc>; + interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>; +}; diff --git a/arch/arm/boot/dts/arm-realview-eb.dtsi b/arch/arm/boot/dts/arm-realview-eb.dtsi new file mode 100644 index 000000000000..1c6a040218e3 --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-eb.dtsi @@ -0,0 +1,453 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include "skeleton.dtsi" + +/ { + compatible = "arm,realview-eb"; + + chosen { }; + + aliases { + serial0 = &serial0; + serial1 = &serial1; + serial2 = &serial2; + serial3 = &serial3; + i2c0 = &i2c; + }; + + memory { + /* 128 MiB memory @ 0x0 */ + reg = <0x00000000 0x08000000>; + }; + + /* The voltage to the MMC card is hardwired at 3.3V */ + vmmc: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + veth: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "veth"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + xtal24mhz: xtal24mhz@24M { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + timclk: timclk@1M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <24>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + mclk: mclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + kmiclk: kmiclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + sspclk: sspclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + uartclk: uartclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + wdogclk: wdogclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + /* FIXME: this actually hangs off the PLL clocks */ + pclk: pclk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; + + flash0@40000000 { + /* 2 * 32MiB NOR Flash memory */ + compatible = "arm,versatile-flash", "cfi-flash"; + reg = <0x40000000 0x04000000>; + bank-width = <4>; + }; + + flash1@44000000 { + /* 2 * 32MiB NOR Flash memory */ + compatible = "arm,versatile-flash", "cfi-flash"; + reg = <0x44000000 0x04000000>; + bank-width = <4>; + }; + + /* SMSC 9118 ethernet with PHY and EEPROM */ + ethernet: ethernet@4e000000 { + compatible = "smsc,lan9118", "smsc,lan9115"; + reg = <0x4e000000 0x10000>; + phy-mode = "mii"; + reg-io-width = <4>; + smsc,irq-active-high; + smsc,irq-push-pull; + vdd33a-supply = <&veth>; + vddvario-supply = <&veth>; + }; + + usb: usb@4f000000 { + compatible = "nxp,usb-isp1761"; + reg = <0x4f000000 0x20000>; + port1-otg; + }; + + /* These peripherals are inside the FPGA */ + fpga { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + syscon: syscon@10000000 { + compatible = "arm,realview-eb-syscon", "syscon", "simple-mfd"; + reg = <0x10000000 0x1000>; + + led@08.0 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x01>; + label = "versatile:0"; + linux,default-trigger = "heartbeat"; + default-state = "on"; + }; + led@08.1 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x02>; + label = "versatile:1"; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + led@08.2 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x04>; + label = "versatile:2"; + linux,default-trigger = "cpu0"; + default-state = "off"; + }; + led@08.3 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x08>; + label = "versatile:3"; + default-state = "off"; + }; + led@08.4 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x10>; + label = "versatile:4"; + default-state = "off"; + }; + led@08.5 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x20>; + label = "versatile:5"; + default-state = "off"; + }; + led@08.6 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x40>; + label = "versatile:6"; + default-state = "off"; + }; + led@08.7 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x80>; + label = "versatile:7"; + default-state = "off"; + }; + oscclk0: osc0@0c { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x0C>; + clocks = <&xtal24mhz>; + }; + oscclk1: osc1@10 { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x10>; + clocks = <&xtal24mhz>; + }; + oscclk2: osc2@14 { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x14>; + clocks = <&xtal24mhz>; + }; + oscclk3: osc3@18 { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x18>; + clocks = <&xtal24mhz>; + }; + oscclk4: osc4@1c { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x1c>; + clocks = <&xtal24mhz>; + }; + }; + + i2c: i2c@10002000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "arm,versatile-i2c"; + reg = <0x10002000 0x1000>; + + rtc@68 { + compatible = "dallas,ds1338"; + reg = <0x68>; + }; + }; + + aaci: aaci@10004000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x10004000 0x1000>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + mmc: mmcsd@10005000 { + compatible = "arm,pl18x", "arm,primecell"; + reg = <0x10005000 0x1000>; + + /* Due to frequent FIFO overruns, use just 500 kHz */ + max-frequency = <500000>; + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + clocks = <&mclk>, <&pclk>; + clock-names = "mclk", "apb_pclk"; + vmmc-supply = <&vmmc>; + cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + + kmi0: kmi@10006000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x10006000 0x1000>; + clocks = <&kmiclk>, <&pclk>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi1: kmi@10007000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x10007000 0x1000>; + clocks = <&kmiclk>, <&pclk>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + charlcd: fpga_charlcd: charlcd@10008000 { + compatible = "arm,versatile-lcd"; + reg = <0x10008000 0x1000>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + serial0: serial@10009000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x10009000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + serial1: serial@1000a000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1000a000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + serial2: serial@1000b000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1000b000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + serial3: serial@1000c000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1000c000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + ssp: ssp@1000d000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x1000d000 0x1000>; + clocks = <&sspclk>, <&pclk>; + clock-names = "SSPCLK", "apb_pclk"; + }; + + wdog: watchdog@10010000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x10010000 0x1000>; + clocks = <&wdogclk>, <&pclk>; + clock-names = "wdogclk", "apb_pclk"; + status = "disabled"; + }; + + timer01: timer@10011000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x10011000 0x1000>; + clocks = <&timclk>, <&timclk>, <&pclk>; + clock-names = "timer1", "timer2", "apb_pclk"; + }; + + timer23: timer@10012000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x10012000 0x1000>; + clocks = <&timclk>, <&timclk>, <&pclk>; + clock-names = "timer1", "timer2", "apb_pclk"; + }; + + gpio0: gpio@10013000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x10013000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + gpio1: gpio@10014000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x10014000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + gpio2: gpio@10015000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x10015000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + rtc: rtc@10017000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x10017000 0x1000>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + clcd: clcd@10020000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x10020000 0x1000>; + interrupt-names = "combined"; + clocks = <&oscclk0>, <&pclk>; + clock-names = "clcdclk", "apb_pclk"; + + port { + clcd_pads: endpoint { + remote-endpoint = <&clcd_panel>; + arm,pl11x,tft-r0g0b0-pads = <0 8 16>; + }; + }; + + panel { + compatible = "panel-dpi"; + + port { + clcd_panel: endpoint { + remote-endpoint = <&clcd_pads>; + }; + }; + + /* Standard 640x480 VGA timings */ + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + hback-porch = <48>; + hfront-porch = <16>; + hsync-len = <96>; + vactive = <480>; + vback-porch = <33>; + vfront-porch = <10>; + vsync-len = <2>; + }; + }; + }; + }; +}; -- GitLab From dfc8a117388786ab3cfdf0880a09abd05c4e0a4d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 23 Feb 2016 16:51:35 +0100 Subject: [PATCH 1165/9938] ARM: dts: realview: DT support for the PBA8 and PBX-A9 This adds a devicetree for the ARM RealView PBA8 platform, also known as HBI-0178, "RealView Platform Baseboard for Cortex-A8" and PBX-A9 "RealView Platform Baseboard Explore for Cortex-A9" Tested in QEMU with -M realview-pb-a8, as well as with -M realview-pbx-a9 -smp cpus=2 Cc: Arnd Bergmann Cc: Pawel Moll Cc: Peter Maydell Cc: Marc Zyngier Tested-by: Robin Murphy Signed-off-by: Linus Walleij --- arch/arm/boot/dts/Makefile | 4 +- arch/arm/boot/dts/arm-realview-pba8.dts | 178 +++++++ arch/arm/boot/dts/arm-realview-pbx-a9.dts | 229 +++++++++ arch/arm/boot/dts/arm-realview-pbx.dtsi | 542 ++++++++++++++++++++++ 4 files changed, 952 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/arm-realview-pba8.dts create mode 100644 arch/arm/boot/dts/arm-realview-pbx-a9.dts create mode 100644 arch/arm/boot/dts/arm-realview-pbx.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index ea508fdc1fcc..e18858d30d4a 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -556,7 +556,9 @@ dtb-$(CONFIG_ARCH_REALVIEW) += \ arm-realview-eb.dtb \ arm-realview-eb-11mp.dtb \ arm-realview-eb-11mp-revb.dtb \ - arm-realview-eb-a9mp.dtb + arm-realview-eb-a9mp.dtb \ + arm-realview-pba8.dtb \ + arm-realview-pbx-a9.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3036-evb.dtb \ rk3036-kylin.dtb \ diff --git a/arch/arm/boot/dts/arm-realview-pba8.dts b/arch/arm/boot/dts/arm-realview-pba8.dts new file mode 100644 index 000000000000..d3238c252b59 --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-pba8.dts @@ -0,0 +1,178 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/dts-v1/; +#include "arm-realview-pbx.dtsi" + +/ { + model = "ARM RealView Platform Baseboard for Cortex-A8"; + compatible = "arm,realview-pba8"; + arm,hbi = <0x178>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "arm,realview-smp"; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a8"; + reg = <0>; + }; + }; + + pmu: pmu@0 { + compatible = "arm,cortex-a8-pmu"; + interrupt-parent = <&intc>; + interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&cpu0>; + }; + + /* Primary GIC PL390 interrupt controller in the test chip */ + intc: interrupt-controller@1e000000 { + compatible = "arm,pl390"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0x1e001000 0x1000>, + <0x1e000000 0x100>; + }; +}; + +ðernet { + interrupt-parent = <&intc>; + interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>; +}; + +&usb { + interrupt-parent = <&intc>; + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>; +}; + +&soc { + compatible = "arm,realview-pba8-soc", "simple-bus"; +}; + +&syscon { + compatible = "arm,realview-pba8-syscon", "syscon", "simple-mfd"; +}; + +&serial0 { + interrupt-parent = <&intc>; + interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial1 { + interrupt-parent = <&intc>; + interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial2 { + interrupt-parent = <&intc>; + interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial3 { + interrupt-parent = <&intc>; + interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>; +}; + +&ssp { + interrupt-parent = <&intc>; + interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>; +}; + +&wdog0 { + interrupt-parent = <&intc>; + interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>; +}; + +&wdog1 { + interrupt-parent = <&intc>; + interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer01 { + interrupt-parent = <&intc>; + interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer23 { + interrupt-parent = <&intc>; + interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio0 { + interrupt-parent = <&intc>; + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio1 { + interrupt-parent = <&intc>; + interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio2 { + interrupt-parent = <&intc>; + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>; +}; + +&rtc { + interrupt-parent = <&intc>; + interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer45 { + interrupt-parent = <&intc>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer67 { + interrupt-parent = <&intc>; + interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>; +}; + +&aaci { + interrupt-parent = <&intc>; + interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>; +}; + +&mmc { + interrupt-parent = <&intc>; + interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>, + <0 18 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi0 { + interrupt-parent = <&intc>; + interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi1 { + interrupt-parent = <&intc>; + interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>; +}; + +&clcd { + interrupt-parent = <&intc>; + interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>; +}; diff --git a/arch/arm/boot/dts/arm-realview-pbx-a9.dts b/arch/arm/boot/dts/arm-realview-pbx-a9.dts new file mode 100644 index 000000000000..db808f92dd79 --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-pbx-a9.dts @@ -0,0 +1,229 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/dts-v1/; +#include "arm-realview-pbx.dtsi" + +/ { + /* + * This is the RealView Platform Baseboard Explore for Cortex-A9 + * (HBI0182 + HBI0183) as described in ARM DUI 0440B + */ + model = "ARM RealView Platform Baseboard Explore for Cortex-A9"; + arm,hbi = <0x182>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "arm,realview-smp"; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + }; + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x0>; + next-level-cache = <&L2>; + }; + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x1>; + next-level-cache = <&L2>; + }; + }; + + L2: l2-cache { + compatible = "arm,pl310-cache"; + reg = <0x1f002000 0x1000>; + cache-unified; + cache-level = <2>; + /* + * Override default cache size, sets and + * associativity as these may be erroneously set + * up by boot loader(s). + */ + cache-size = <1048576>; // 1MB + cache-sets = <4096>; + cache-line-size = <32>; + arm,parity-disable; + arm,tag-latency = <1>; + arm,data-latency = <1 1>; + arm,dirty-latency = <1>; + }; + + scu: scu@1f000000 { + compatible = "arm,cortex-a9-scu"; + reg = <0x1f000000 0x100>; + }; + + twd_timer: timer@1f000600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x1f000600 0x20>; + interrupt-parent = <&intc>; + interrupts = <1 13 0xf04>; + }; + + twd_wdog: watchdog@1f000620 { + compatible = "arm,cortex-a9-twd-wdt"; + reg = <0x1f000620 0x20>; + interrupt-parent = <&intc>; + interrupts = <1 14 0xf04>; + }; + + pmu: pmu@0 { + compatible = "arm,cortex-a9-pmu"; + interrupt-parent = <&intc>; + interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>, + <0 45 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&CPU0>, <&CPU1>; + }; + + /* Primary GIC PL390 interrupt controller in the test chip */ + intc: interrupt-controller@1f000000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0x1f001000 0x1000>, + <0x1f000100 0x100>; + }; +}; + +ðernet { + interrupt-parent = <&intc>; + interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>; +}; + +&usb { + interrupt-parent = <&intc>; + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial0 { + interrupt-parent = <&intc>; + interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial1 { + interrupt-parent = <&intc>; + interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial2 { + interrupt-parent = <&intc>; + interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>; +}; + +&serial3 { + interrupt-parent = <&intc>; + interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>; +}; + +&ssp { + interrupt-parent = <&intc>; + interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>; +}; + +&wdog0 { + interrupt-parent = <&intc>; + interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>; +}; + +&wdog1 { + interrupt-parent = <&intc>; + interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer01 { + interrupt-parent = <&intc>; + interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer23 { + interrupt-parent = <&intc>; + interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio0 { + interrupt-parent = <&intc>; + interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio1 { + interrupt-parent = <&intc>; + interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; +}; + +&gpio2 { + interrupt-parent = <&intc>; + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>; +}; + +&rtc { + interrupt-parent = <&intc>; + interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer45 { + interrupt-parent = <&intc>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; +}; + +&timer67 { + interrupt-parent = <&intc>; + interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>; +}; + +&aaci { + interrupt-parent = <&intc>; + interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>; +}; + +&mmc { + interrupt-parent = <&intc>; + interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>, + <0 18 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi0 { + interrupt-parent = <&intc>; + interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>; +}; + +&kmi1 { + interrupt-parent = <&intc>; + interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>; +}; + +&clcd { + interrupt-parent = <&intc>; + interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>; +}; diff --git a/arch/arm/boot/dts/arm-realview-pbx.dtsi b/arch/arm/boot/dts/arm-realview-pbx.dtsi new file mode 100644 index 000000000000..aeb49c4bd773 --- /dev/null +++ b/arch/arm/boot/dts/arm-realview-pbx.dtsi @@ -0,0 +1,542 @@ +/* + * Copyright 2016 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include "skeleton.dtsi" + +/ { + compatible = "arm,realview-pbx"; + + chosen { }; + + aliases { + serial0 = &serial0; + serial1 = &serial1; + serial2 = &serial2; + serial3 = &serial3; + i2c0 = &i2c; + }; + + memory { + /* 128 MiB memory @ 0x0 */ + reg = <0x00000000 0x08000000>; + }; + + /* The voltage to the MMC card is hardwired at 3.3V */ + vmmc: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + veth: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "veth"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + xtal24mhz: xtal24mhz@24M { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + refclk32khz: refclk32khz { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + timclk: timclk@1M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <24>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + mclk: mclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + kmiclk: kmiclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + sspclk: sspclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + uartclk: uartclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + wdogclk: wdogclk@24M { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clock-mult = <1>; + clocks = <&xtal24mhz>; + }; + + /* FIXME: this actually hangs off the PLL clocks */ + pclk: pclk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; + + flash0@40000000 { + /* 2 * 32MiB NOR Flash memory */ + compatible = "arm,versatile-flash", "cfi-flash"; + reg = <0x40000000 0x04000000>; + bank-width = <4>; + }; + + flash1@44000000 { + /* 2 * 32MiB NOR Flash memory */ + compatible = "arm,versatile-flash", "cfi-flash"; + reg = <0x44000000 0x04000000>; + bank-width = <4>; + }; + + /* SMSC 9118 ethernet with PHY and EEPROM */ + ethernet: ethernet@4e000000 { + compatible = "smsc,lan9118", "smsc,lan9115"; + reg = <0x4e000000 0x10000>; + phy-mode = "mii"; + reg-io-width = <4>; + smsc,irq-active-high; + smsc,irq-push-pull; + vdd33a-supply = <&veth>; + vddvario-supply = <&veth>; + }; + + usb: usb@4f000000 { + compatible = "nxp,usb-isp1761"; + reg = <0x4f000000 0x20000>; + port1-otg; + }; + + soc: soc@0 { + compatible = "arm,realview-pbx-soc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + regmap = <&syscon>; + ranges; + + syscon: syscon@10000000 { + compatible = "arm,realview-pbx-syscon", "syscon", "simple-mfd"; + reg = <0x10000000 0x1000>; + + led@08.0 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x01>; + label = "versatile:0"; + linux,default-trigger = "heartbeat"; + default-state = "on"; + }; + led@08.1 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x02>; + label = "versatile:1"; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + led@08.2 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x04>; + label = "versatile:2"; + linux,default-trigger = "cpu0"; + default-state = "off"; + }; + led@08.3 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x08>; + label = "versatile:3"; + default-state = "off"; + }; + led@08.4 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x10>; + label = "versatile:4"; + default-state = "off"; + }; + led@08.5 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x20>; + label = "versatile:5"; + default-state = "off"; + }; + led@08.6 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x40>; + label = "versatile:6"; + default-state = "off"; + }; + led@08.7 { + compatible = "register-bit-led"; + offset = <0x08>; + mask = <0x80>; + label = "versatile:7"; + default-state = "off"; + }; + oscclk0: osc0@0c { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x0C>; + clocks = <&xtal24mhz>; + }; + oscclk1: osc1@10 { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x10>; + clocks = <&xtal24mhz>; + }; + oscclk2: osc2@14 { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x14>; + clocks = <&xtal24mhz>; + }; + oscclk3: osc3@18 { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x18>; + clocks = <&xtal24mhz>; + }; + oscclk4: osc4@1c { + compatible = "arm,syscon-icst307"; + #clock-cells = <0>; + lock-offset = <0x20>; + vco-offset = <0x1c>; + clocks = <&xtal24mhz>; + }; + }; + + sp810_syscon0: sysctl@10001000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x10001000 0x1000>; + clocks = <&refclk32khz>, <&timclk>, <&xtal24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclk0", + "timerclk1", + "timerclk2", + "timerclk3"; + assigned-clocks = <&sp810_syscon0 0>, + <&sp810_syscon0 1>, + <&sp810_syscon0 2>, + <&sp810_syscon0 3>; + assigned-clock-parents = <&timclk>, + <&timclk>, + <&timclk>, + <&timclk>; + }; + + i2c: i2c@10002000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "arm,versatile-i2c"; + reg = <0x10002000 0x1000>; + + rtc@68 { + compatible = "dallas,ds1338"; + reg = <0x68>; + }; + }; + + serial0: serial@10009000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x10009000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + serial1: serial@1000a000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1000a000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + serial2: serial@1000b000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1000b000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + ssp: ssp@1000d000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x1000d000 0x1000>; + clocks = <&sspclk>, <&pclk>; + clock-names = "SSPCLK", "apb_pclk"; + }; + + wdog0: watchdog@1000f000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x1000f000 0x1000>; + clocks = <&wdogclk>, <&pclk>; + clock-names = "wdogclk", "apb_pclk"; + status = "disabled"; + }; + + wdog1: watchdog@10010000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x10010000 0x1000>; + clocks = <&wdogclk>, <&pclk>; + clock-names = "wdogclk", "apb_pclk"; + status = "disabled"; + }; + + timer01: timer@10011000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x10011000 0x1000>; + clocks = <&sp810_syscon0 0>, + <&sp810_syscon0 1>, + <&pclk>; + clock-names = "timerclk0", + "timerclk1", + "apb_pclk"; + }; + + timer23: timer@10012000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x10012000 0x1000>; + clocks = <&sp810_syscon0 2>, + <&sp810_syscon0 3>, + <&pclk>; + clock-names = "timerclk2", + "timerclk3", + "apb_pclk"; + }; + + gpio0: gpio@10013000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x10013000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + gpio1: gpio@10014000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x10014000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + gpio2: gpio@10015000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x10015000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + /* DVI serial bus control is at 10016000 */ + + rtc: rtc@10017000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x10017000 0x1000>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + timer45: timer@10018000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x10018000 0x1000>; + clocks = <&timclk>, <&timclk>, <&pclk>; + clock-names = "timerclk4", "timerclk5", "apb_pclk"; + }; + + timer67: timer@10019000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x10019000 0x1000>; + clocks = <&timclk>, <&timclk>, <&pclk>; + clock-names = "timerclk6", "timerclk7", "apb_pclk"; + }; + + sp810_syscon1: sysctl@1001a000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x1001a000 0x1000>; + clocks = <&refclk32khz>, <&timclk>, <&xtal24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclk4", + "timerclk5", + "timerclk6", + "timerclk7"; + assigned-clocks = <&sp810_syscon1 0>, + <&sp810_syscon1 1>, + <&sp810_syscon1 2>, + <&sp810_syscon1 3>; + assigned-clock-parents = <&timclk>, + <&timclk>, + <&timclk>, + <&timclk>; + }; + }; + + + /* These peripherals are inside the FPGA */ + fpga { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + aaci: aaci@10004000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x10004000 0x1000>; + clocks = <&pclk>; + clock-names = "apb_pclk"; + }; + + mmc: mmcsd@10005000 { + compatible = "arm,pl18x", "arm,primecell"; + reg = <0x10005000 0x1000>; + + /* Due to frequent FIFO overruns, use just 500 kHz */ + max-frequency = <500000>; + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + clocks = <&mclk>, <&pclk>; + clock-names = "mclk", "apb_pclk"; + vmmc-supply = <&vmmc>; + cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; + }; + + kmi0: kmi@10006000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x10006000 0x1000>; + clocks = <&kmiclk>, <&pclk>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi1: kmi@10007000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x10007000 0x1000>; + clocks = <&kmiclk>, <&pclk>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + serial3: serial@1000c000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1000c000 0x1000>; + clocks = <&uartclk>, <&pclk>; + clock-names = "uartclk", "apb_pclk"; + }; + }; + + /* These peripherals are inside the NEC ISSP */ + issp { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + clcd: clcd@10020000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x10020000 0x1000>; + interrupt-names = "combined"; + clocks = <&oscclk4>, <&pclk>; + clock-names = "clcdclk", "apb_pclk"; + + port { + clcd_pads: endpoint { + remote-endpoint = <&clcd_panel>; + arm,pl11x,tft-r0g0b0-pads = <0 8 16>; + }; + }; + + panel { + compatible = "panel-dpi"; + + port { + clcd_panel: endpoint { + remote-endpoint = <&clcd_pads>; + }; + }; + + /* Standard 640x480 VGA timings */ + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + hback-porch = <48>; + hfront-porch = <16>; + hsync-len = <96>; + vactive = <480>; + vback-porch = <33>; + vfront-porch = <10>; + vsync-len = <2>; + }; + }; + }; + }; +}; + -- GitLab From fccc2b3675371e4077d7aa7f23d116e97dcdcd07 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 18 Feb 2016 14:21:54 +0100 Subject: [PATCH 1166/9938] soc: versatile: dynamically detect RealView HBI numbers We cannot pile all numbers on this list, just print the three hex digits representing the board ID so we can handle all the new RealView boards. Cc: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/soc/versatile/soc-realview.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c index c337764de867..282e371378ce 100644 --- a/drivers/soc/versatile/soc-realview.c +++ b/drivers/soc/versatile/soc-realview.c @@ -31,18 +31,6 @@ static const struct of_device_id realview_soc_of_match[] = { static u32 realview_coreid; -static const char *realview_board_str(u32 id) -{ - switch ((id >> 16) & 0xfff) { - case 0x0147: - return "HBI-0147"; - case 0x0159: - return "HBI-0159"; - default: - return "Unknown"; - } -} - static const char *realview_arch_str(u32 id) { switch ((id >> 8) & 0xf) { @@ -69,7 +57,7 @@ static ssize_t realview_get_board(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", realview_board_str(realview_coreid)); + return sprintf(buf, "HBI-%03x\n", ((realview_coreid >> 16) & 0xfff)); } static struct device_attribute realview_board_attr = @@ -133,8 +121,9 @@ static int realview_soc_probe(struct platform_device *pdev) device_create_file(soc_device_to_device(soc_dev), &realview_arch_attr); device_create_file(soc_device_to_device(soc_dev), &realview_build_attr); - dev_info(&pdev->dev, "RealView Syscon Core ID: 0x%08x\n", - realview_coreid); + dev_info(&pdev->dev, "RealView Syscon Core ID: 0x%08x, HBI-%03x\n", + realview_coreid, + ((realview_coreid >> 16) & 0xfff)); /* FIXME: add attributes for SoC to sysfs */ return 0; } -- GitLab From 7fbbe38aa11816ef15844238e8eb3164b887d265 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Feb 2016 14:35:58 +0100 Subject: [PATCH 1167/9938] ARM: realview: hide unused 'pmu_device' object The pmu_device is only accessed when CACHE_L2X0 is enabled, and we get a warning otherwise: mach-realview/realview_pbx.c:274:31: error: 'pmu_device' defined but not used [-Werror=unused-variable] This adds another #ifdef for it. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-realview/realview_pbx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index b9f0757787ac..be1cec5fe3ad 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -248,6 +248,7 @@ static struct resource realview_pbx_isp1761_resources[] = { }, }; +#ifdef CONFIG_CACHE_L2X0 static struct resource pmu_resources[] = { [0] = { .start = IRQ_PBX_PMU_CPU0, @@ -277,6 +278,7 @@ static struct platform_device pmu_device = { .num_resources = ARRAY_SIZE(pmu_resources), .resource = pmu_resources, }; +#endif static void __init gic_init_irq(void) { -- GitLab From ef859312c3a16b42f398e6dbb14de23bffd5dd41 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 14 Mar 2016 16:51:09 +0200 Subject: [PATCH 1168/9938] dmaengine: core: Use dev_ functions for debug and error prints According to dmaengine kerneldoc the struct dma_chan has always a non-NULL pointer to DMA device and a test in dma_async_device_register() validates that DMA device must also point to struct device. All pr_ prints except one in dma_channel_table_init() have valid DMA channel or DMA device pointer available which allow convert them to use dev_ functions and thus able to show the associated DMA device. Signed-off-by: Jarkko Nikula Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 0cb259c59916..a7131d4141d8 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -289,7 +289,7 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) do { status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); if (time_after_eq(jiffies, dma_sync_wait_timeout)) { - pr_err("%s: timeout!\n", __func__); + dev_err(chan->device->dev, "%s: timeout!\n", __func__); return DMA_ERROR; } if (status != DMA_IN_PROGRESS) @@ -518,7 +518,7 @@ static struct dma_chan *private_candidate(const dma_cap_mask_t *mask, struct dma_chan *chan; if (mask && !__dma_device_satisfies_mask(dev, mask)) { - pr_debug("%s: wrong capabilities\n", __func__); + dev_dbg(dev->dev, "%s: wrong capabilities\n", __func__); return NULL; } /* devices with multiple channels need special handling as we need to @@ -533,12 +533,12 @@ static struct dma_chan *private_candidate(const dma_cap_mask_t *mask, list_for_each_entry(chan, &dev->channels, device_node) { if (chan->client_count) { - pr_debug("%s: %s busy\n", + dev_dbg(dev->dev, "%s: %s busy\n", __func__, dma_chan_name(chan)); continue; } if (fn && !fn(chan, fn_param)) { - pr_debug("%s: %s filter said false\n", + dev_dbg(dev->dev, "%s: %s filter said false\n", __func__, dma_chan_name(chan)); continue; } @@ -567,11 +567,12 @@ static struct dma_chan *find_candidate(struct dma_device *device, if (err) { if (err == -ENODEV) { - pr_debug("%s: %s module removed\n", __func__, - dma_chan_name(chan)); + dev_dbg(device->dev, "%s: %s module removed\n", + __func__, dma_chan_name(chan)); list_del_rcu(&device->global_node); } else - pr_debug("%s: failed to get %s: (%d)\n", + dev_dbg(device->dev, + "%s: failed to get %s: (%d)\n", __func__, dma_chan_name(chan), err); if (--device->privatecnt == 0) @@ -602,7 +603,8 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan) device->privatecnt++; err = dma_chan_get(chan); if (err) { - pr_debug("%s: failed to get %s: (%d)\n", + dev_dbg(chan->device->dev, + "%s: failed to get %s: (%d)\n", __func__, dma_chan_name(chan), err); chan = NULL; if (--device->privatecnt == 0) @@ -662,7 +664,7 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, } mutex_unlock(&dma_list_mutex); - pr_debug("%s: %s (%s)\n", + dev_dbg(chan->device->dev, "%s: %s (%s)\n", __func__, chan ? "success" : "fail", chan ? dma_chan_name(chan) : NULL); @@ -814,8 +816,9 @@ void dmaengine_get(void) list_del_rcu(&device->global_node); break; } else if (err) - pr_debug("%s: failed to get %s: (%d)\n", - __func__, dma_chan_name(chan), err); + dev_dbg(chan->device->dev, + "%s: failed to get %s: (%d)\n", + __func__, dma_chan_name(chan), err); } } @@ -1222,8 +1225,9 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) while (tx->cookie == -EBUSY) { if (time_after_eq(jiffies, dma_sync_wait_timeout)) { - pr_err("%s timeout waiting for descriptor submission\n", - __func__); + dev_err(tx->chan->device->dev, + "%s timeout waiting for descriptor submission\n", + __func__); return DMA_ERROR; } cpu_relax(); -- GitLab From 903589ca7165c41d149d902a06006b0f2b975231 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 1 Apr 2016 10:47:22 +0100 Subject: [PATCH 1169/9938] ARM: 8554/1: kernel: pci: remove pci=firmware command line parameter handling According to kernel documentation, the pci=firmware command line parameter is only meant to be used on IXP2000 ARM platforms to prevent the kernel from assigning PCI resources configured by the bootloader. Since the IXP2000 ARM platforms support has been removed from the kernel in commit: commit c65f2abf54a6 ("ARM: remove ixp23xx and ixp2000 platforms") its platforms specific kernel parameters should be removed too from the kernel documentation along with the kernel code currently handling them in that they have just become obsolete. This patch removes the pci=firmware command line parameter handling from ARM code and the related kernel parameters documentation section. Signed-off-by: Lorenzo Pieralisi Acked-by: Bjorn Helgaas Acked-by: Lennert Buytenhek Cc: Arnd Bergmann Cc: Lennert Buytenhek Cc: Jonathan Corbet Cc: Bjorn Helgaas Cc: Rob Herring Signed-off-by: Russell King --- Documentation/kernel-parameters.txt | 5 ----- arch/arm/kernel/bios32.c | 3 --- 2 files changed, 8 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ecc74fa4bfde..a036762157f0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2921,11 +2921,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. for broken drivers that don't call it. skip_isa_align [X86] do not align io start addr, so can handle more pci cards - firmware [ARM] Do not re-enumerate the bus but instead - just use the configuration from the - bootloader. This is currently used on - IXP2000 systems where the bus has to be - configured a certain way for adjunct CPUs. noearly [X86] Don't do any early type 1 scanning. This might help on some broken boards which machine check when some devices' config space diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 066f7f9ba411..05e61a2eeabe 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -550,9 +550,6 @@ char * __init pcibios_setup(char *str) if (!strcmp(str, "debug")) { debug_pci = 1; return NULL; - } else if (!strcmp(str, "firmware")) { - pci_add_flags(PCI_PROBE_ONLY); - return NULL; } return str; } -- GitLab From 47771902a9beb23859805721f1d98d03dee5da7c Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 16 Mar 2016 18:13:33 +0530 Subject: [PATCH 1170/9938] ath10k: introduce Extended Resource Config support for 10.4 Add API support for Extended Resource Configuration for 10.4. This is useful to enable new features like Peer Stats, LTEU etc if the firmware advertises support for the service. This is also done to provide backward compatibility with older firmware. Also for clarity send default host platform type as 'WMI_HOST_PLATFORM_HIGH_PERF', though this should not make any difference in functionality Signed-off-by: Raja Mani Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi-ops.h | 23 +++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 24 ++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 31 +++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 32ab34edceb5..7fb00dcc03b8 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -186,6 +186,9 @@ struct wmi_ops { u8 enable, u32 detect_level, u32 detect_margin); + struct sk_buff *(*ext_resource_config)(struct ath10k *ar, + enum wmi_host_platform_type type, + u32 fw_feature_bitmap); int (*get_vdev_subtype)(struct ath10k *ar, enum wmi_vdev_subtype subtype); }; @@ -1329,6 +1332,26 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); } +static inline int +ath10k_wmi_ext_resource_config(struct ath10k *ar, + enum wmi_host_platform_type type, + u32 fw_feature_bitmap) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->ext_resource_config) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->ext_resource_config(ar, type, + fw_feature_bitmap); + + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->ext_resource_cfg_cmdid); +} + static inline int ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index afed9dab74f4..3af1af74e84d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -705,6 +705,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = { .set_cca_params_cmdid = WMI_10_4_SET_CCA_PARAMS_CMDID, .pdev_bss_chan_info_request_cmdid = WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, + .ext_resource_cfg_cmdid = WMI_10_4_EXT_RESOURCE_CFG_CMDID, }; /* MAIN WMI VDEV param map */ @@ -7479,6 +7480,28 @@ static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar, return -ENOTSUPP; } +static struct sk_buff * +ath10k_wmi_10_4_ext_resource_config(struct ath10k *ar, + enum wmi_host_platform_type type, + u32 fw_feature_bitmap) +{ + struct wmi_ext_resource_config_10_4_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_ext_resource_config_10_4_cmd *)skb->data; + cmd->host_platform_config = __cpu_to_le32(type); + cmd->fw_feature_bitmap = __cpu_to_le32(fw_feature_bitmap); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi ext resource config host type %d firmware feature bitmap %08x\n", + type, fw_feature_bitmap); + return skb; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -7805,6 +7828,7 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, + .ext_resource_config = ath10k_wmi_10_4_ext_resource_config, /* shared with 10.2 */ .gen_request_stats = ath10k_wmi_op_gen_request_stats, diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index bb42f7a6ba23..bd29f271524d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -816,6 +816,7 @@ struct wmi_cmd_map { u32 set_cca_params_cmdid; u32 pdev_bss_chan_info_request_cmdid; u32 pdev_enable_adaptive_cca_cmdid; + u32 ext_resource_cfg_cmdid; }; /* @@ -2667,6 +2668,31 @@ struct wmi_resource_config_10_4 { __le32 qwrap_config; } __packed; +/** + * enum wmi_10_4_feature_mask - WMI 10.4 feature enable/disable flags + * @WMI_10_4_LTEU_SUPPORT: LTEU config + * @WMI_10_4_COEX_GPIO_SUPPORT: COEX GPIO config + * @WMI_10_4_AUX_RADIO_SPECTRAL_INTF: AUX Radio Enhancement for spectral scan + * @WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF: AUX Radio Enhancement for chan load scan + * @WMI_10_4_BSS_CHANNEL_INFO_64: BSS channel info stats + * @WMI_10_4_PEER_STATS: Per station stats + */ +enum wmi_10_4_feature_mask { + WMI_10_4_LTEU_SUPPORT = BIT(0), + WMI_10_4_COEX_GPIO_SUPPORT = BIT(1), + WMI_10_4_AUX_RADIO_SPECTRAL_INTF = BIT(2), + WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF = BIT(3), + WMI_10_4_BSS_CHANNEL_INFO_64 = BIT(4), + WMI_10_4_PEER_STATS = BIT(5), +}; + +struct wmi_ext_resource_config_10_4_cmd { + /* contains enum wmi_host_platform_type */ + __le32 host_platform_config; + /* see enum wmi_10_4_feature_mask */ + __le32 fw_feature_bitmap; +}; + /* strucutre describing host memory chunk. */ struct host_memory_chunk { /* id of the request that is passed up in service ready */ @@ -6408,6 +6434,11 @@ struct wmi_pdev_set_adaptive_cca_params { __le32 cca_detect_margin; } __packed; +enum wmi_host_platform_type { + WMI_HOST_PLATFORM_HIGH_PERF, + WMI_HOST_PLATFORM_LOW_PERF, +}; + struct ath10k; struct ath10k_vif; struct ath10k_fw_stats_pdev; -- GitLab From 0bf676d1fd5144e66ac06939fa3c7c12086c3b18 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 31 Mar 2016 10:49:28 +0200 Subject: [PATCH 1171/9938] audit: cleanup prune_tree_thread We can use kthread_run instead of kthread_create+wake_up_process for creating the thread. We do not need to set the task state to TASK_RUNNING after schedule(), the process is in that state already. And we do not need to set the state to TASK_INTERRUPTIBLE when not doing schedule() as we set the state to TASK_RUNNING immediately afterwards. Signed-off-by: Jiri Slaby Cc: Paul Moore Cc: Eric Paris Cc: Signed-off-by: Paul Moore --- kernel/audit_tree.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 5efe9b299a12..25772476fa4a 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -661,10 +661,10 @@ static int tag_mount(struct vfsmount *mnt, void *arg) static int prune_tree_thread(void *unused) { for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (list_empty(&prune_list)) + if (list_empty(&prune_list)) { + set_current_state(TASK_INTERRUPTIBLE); schedule(); - __set_current_state(TASK_RUNNING); + } mutex_lock(&audit_cmd_mutex); mutex_lock(&audit_filter_mutex); @@ -693,16 +693,14 @@ static int audit_launch_prune(void) { if (prune_thread) return 0; - prune_thread = kthread_create(prune_tree_thread, NULL, + prune_thread = kthread_run(prune_tree_thread, NULL, "audit_prune_tree"); if (IS_ERR(prune_thread)) { pr_err("cannot start thread audit_prune_tree"); prune_thread = NULL; return -ENOMEM; - } else { - wake_up_process(prune_thread); - return 0; } + return 0; } /* called with audit_filter_mutex */ -- GitLab From c8f5c4c7c82c916faf4699927801c8038d1fac51 Mon Sep 17 00:00:00 2001 From: Cristina Ciocan Date: Fri, 1 Apr 2016 14:00:02 +0300 Subject: [PATCH 1172/9938] pinctrl: baytrail: Add pin control data structures In order to implement pin control for Baytrail, we need data structures in which to store and pass along pin, group, function, community and SOC data information. Baytrail has 3 GPIO controllers. Add SCORE, NCORE and SUS controller data: - pins (for all controllers), - pad map for pins (for all controllers; we need this since pads are not ordered), - groups (for SCORE and SUS controllers), - functions (for SCORE and SUS controllers), - communities (for all controllers), - soc specific data gathering all of the above and the ACPI UID (for all controllers) This information is useful for pin control functionality. NCORE data is lighter than the other two controllers' due to lack of pin documentation in the public datasheet. Datasheet: http://www.intel.com/content/www/us/en/embedded/products/bay-trail/atom-e3800-family-datasheet.html Signed-off-by: Cristina Ciocan Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-baytrail.c | 628 ++++++++++++++++++++++- 1 file changed, 606 insertions(+), 22 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 21b79a446d5a..364f56c3991d 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -73,17 +73,207 @@ #define BYT_NCORE_ACPI_UID "2" #define BYT_SUS_ACPI_UID "3" -/* - * Baytrail gpio controller consist of three separate sub-controllers called - * SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID. - * - * GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does - * _not_ correspond to the first gpio register at controller's gpio base. - * There is no logic or pattern in mapping gpio numbers to registers (pads) so - * each sub-controller needs to have its own mapping table - */ +struct byt_gpio_pin_context { + u32 conf0; + u32 val; +}; + +struct byt_simple_func_mux { + const char *name; + unsigned short func; +}; + +struct byt_mixed_func_mux { + const char *name; + const unsigned short *func_values; +}; + +struct byt_pingroup { + const char *name; + const unsigned int *pins; + size_t npins; + unsigned short has_simple_funcs; + union { + const struct byt_simple_func_mux *simple_funcs; + const struct byt_mixed_func_mux *mixed_funcs; + }; + size_t nfuncs; +}; + +struct byt_function { + const char *name; + const char * const *groups; + size_t ngroups; +}; + +struct byt_community { + unsigned int pin_base; + size_t npins; + const unsigned int *pad_map; + void __iomem *reg_base; +}; + +#define SIMPLE_FUNC(n, f) \ + { \ + .name = (n), \ + .func = (f), \ + } +#define MIXED_FUNC(n, f) \ + { \ + .name = (n), \ + .func_values = (f), \ + } + +#define PIN_GROUP_SIMPLE(n, p, f) \ + { \ + .name = (n), \ + .pins = (p), \ + .npins = ARRAY_SIZE((p)), \ + .has_simple_funcs = 1, \ + .simple_funcs = (f), \ + .nfuncs = ARRAY_SIZE((f)), \ + } +#define PIN_GROUP_MIXED(n, p, f) \ + { \ + .name = (n), \ + .pins = (p), \ + .npins = ARRAY_SIZE((p)), \ + .has_simple_funcs = 0, \ + .mixed_funcs = (f), \ + .nfuncs = ARRAY_SIZE((f)), \ + } + +#define FUNCTION(n, g) \ + { \ + .name = (n), \ + .groups = (g), \ + .ngroups = ARRAY_SIZE((g)), \ + } + +#define COMMUNITY(p, n, map) \ + { \ + .pin_base = (p), \ + .npins = (n), \ + .pad_map = (map),\ + } -/* score_pins[gpio_nr] = pad_nr */ +struct byt_pinctrl_soc_data { + const char *uid; + const struct pinctrl_pin_desc *pins; + size_t npins; + const struct byt_pingroup *groups; + size_t ngroups; + const struct byt_function *functions; + size_t nfunctions; + const struct byt_community *communities; + size_t ncommunities; +}; + +/* SCORE pins, aka GPIOC_ or GPIO_S0_SC[] */ +static const struct pinctrl_pin_desc byt_score_pins[] = { + PINCTRL_PIN(0, "SATA_GP0"), + PINCTRL_PIN(1, "SATA_GP1"), + PINCTRL_PIN(2, "SATA_LED#"), + PINCTRL_PIN(3, "PCIE_CLKREQ0"), + PINCTRL_PIN(4, "PCIE_CLKREQ1"), + PINCTRL_PIN(5, "PCIE_CLKREQ2"), + PINCTRL_PIN(6, "PCIE_CLKREQ3"), + PINCTRL_PIN(7, "SD3_WP"), + PINCTRL_PIN(8, "HDA_RST"), + PINCTRL_PIN(9, "HDA_SYNC"), + PINCTRL_PIN(10, "HDA_CLK"), + PINCTRL_PIN(11, "HDA_SDO"), + PINCTRL_PIN(12, "HDA_SDI0"), + PINCTRL_PIN(13, "HDA_SDI1"), + PINCTRL_PIN(14, "GPIO_S0_SC14"), + PINCTRL_PIN(15, "GPIO_S0_SC15"), + PINCTRL_PIN(16, "MMC1_CLK"), + PINCTRL_PIN(17, "MMC1_D0"), + PINCTRL_PIN(18, "MMC1_D1"), + PINCTRL_PIN(19, "MMC1_D2"), + PINCTRL_PIN(20, "MMC1_D3"), + PINCTRL_PIN(21, "MMC1_D4"), + PINCTRL_PIN(22, "MMC1_D5"), + PINCTRL_PIN(23, "MMC1_D6"), + PINCTRL_PIN(24, "MMC1_D7"), + PINCTRL_PIN(25, "MMC1_CMD"), + PINCTRL_PIN(26, "MMC1_RST"), + PINCTRL_PIN(27, "SD2_CLK"), + PINCTRL_PIN(28, "SD2_D0"), + PINCTRL_PIN(29, "SD2_D1"), + PINCTRL_PIN(30, "SD2_D2"), + PINCTRL_PIN(31, "SD2_D3_CD"), + PINCTRL_PIN(32, "SD2_CMD"), + PINCTRL_PIN(33, "SD3_CLK"), + PINCTRL_PIN(34, "SD3_D0"), + PINCTRL_PIN(35, "SD3_D1"), + PINCTRL_PIN(36, "SD3_D2"), + PINCTRL_PIN(37, "SD3_D3"), + PINCTRL_PIN(38, "SD3_CD"), + PINCTRL_PIN(39, "SD3_CMD"), + PINCTRL_PIN(40, "SD3_1P8EN"), + PINCTRL_PIN(41, "SD3_PWREN#"), + PINCTRL_PIN(42, "ILB_LPC_AD0"), + PINCTRL_PIN(43, "ILB_LPC_AD1"), + PINCTRL_PIN(44, "ILB_LPC_AD2"), + PINCTRL_PIN(45, "ILB_LPC_AD3"), + PINCTRL_PIN(46, "ILB_LPC_FRAME"), + PINCTRL_PIN(47, "ILB_LPC_CLK0"), + PINCTRL_PIN(48, "ILB_LPC_CLK1"), + PINCTRL_PIN(49, "ILB_LPC_CLKRUN"), + PINCTRL_PIN(50, "ILB_LPC_SERIRQ"), + PINCTRL_PIN(51, "PCU_SMB_DATA"), + PINCTRL_PIN(52, "PCU_SMB_CLK"), + PINCTRL_PIN(53, "PCU_SMB_ALERT"), + PINCTRL_PIN(54, "ILB_8254_SPKR"), + PINCTRL_PIN(55, "GPIO_S0_SC55"), + PINCTRL_PIN(56, "GPIO_S0_SC56"), + PINCTRL_PIN(57, "GPIO_S0_SC57"), + PINCTRL_PIN(58, "GPIO_S0_SC58"), + PINCTRL_PIN(59, "GPIO_S0_SC59"), + PINCTRL_PIN(60, "GPIO_S0_SC60"), + PINCTRL_PIN(61, "GPIO_S0_SC61"), + PINCTRL_PIN(62, "LPE_I2S2_CLK"), + PINCTRL_PIN(63, "LPE_I2S2_FRM"), + PINCTRL_PIN(64, "LPE_I2S2_DATAIN"), + PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"), + PINCTRL_PIN(66, "SIO_SPI_CS"), + PINCTRL_PIN(67, "SIO_SPI_MISO"), + PINCTRL_PIN(68, "SIO_SPI_MOSI"), + PINCTRL_PIN(69, "SIO_SPI_CLK"), + PINCTRL_PIN(70, "SIO_UART1_RXD"), + PINCTRL_PIN(71, "SIO_UART1_TXD"), + PINCTRL_PIN(72, "SIO_UART1_RTS"), + PINCTRL_PIN(73, "SIO_UART1_CTS"), + PINCTRL_PIN(74, "SIO_UART2_RXD"), + PINCTRL_PIN(75, "SIO_UART2_TXD"), + PINCTRL_PIN(76, "SIO_UART2_RTS"), + PINCTRL_PIN(77, "SIO_UART2_CTS"), + PINCTRL_PIN(78, "SIO_I2C0_DATA"), + PINCTRL_PIN(79, "SIO_I2C0_CLK"), + PINCTRL_PIN(80, "SIO_I2C1_DATA"), + PINCTRL_PIN(81, "SIO_I2C1_CLK"), + PINCTRL_PIN(82, "SIO_I2C2_DATA"), + PINCTRL_PIN(83, "SIO_I2C2_CLK"), + PINCTRL_PIN(84, "SIO_I2C3_DATA"), + PINCTRL_PIN(85, "SIO_I2C3_CLK"), + PINCTRL_PIN(86, "SIO_I2C4_DATA"), + PINCTRL_PIN(87, "SIO_I2C4_CLK"), + PINCTRL_PIN(88, "SIO_I2C5_DATA"), + PINCTRL_PIN(89, "SIO_I2C5_CLK"), + PINCTRL_PIN(90, "SIO_I2C6_DATA"), + PINCTRL_PIN(91, "SIO_I2C6_CLK"), + PINCTRL_PIN(92, "GPIO_S0_SC92"), + PINCTRL_PIN(93, "GPIO_S0_SC93"), + PINCTRL_PIN(94, "SIO_PWM0"), + PINCTRL_PIN(95, "SIO_PWM1"), + PINCTRL_PIN(96, "PMC_PLT_CLK0"), + PINCTRL_PIN(97, "PMC_PLT_CLK1"), + PINCTRL_PIN(98, "PMC_PLT_CLK2"), + PINCTRL_PIN(99, "PMC_PLT_CLK3"), + PINCTRL_PIN(100, "PMC_PLT_CLK4"), + PINCTRL_PIN(101, "PMC_PLT_CLK5"), +}; static unsigned const score_pins[BYT_NGPIO_SCORE] = { 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, @@ -99,13 +289,285 @@ static unsigned const score_pins[BYT_NGPIO_SCORE] = { 97, 100, }; -static unsigned const ncore_pins[BYT_NGPIO_NCORE] = { - 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, - 14, 15, 12, 26, 27, 1, 4, 8, 11, 0, - 3, 6, 10, 13, 2, 5, 9, 7, +static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = { + 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, + 36, 38, 39, 35, 40, 84, 62, 61, 64, 59, + 54, 56, 60, 55, 63, 57, 51, 50, 53, 47, + 52, 49, 48, 43, 46, 41, 45, 42, 58, 44, + 95, 105, 70, 68, 67, 66, 69, 71, 65, 72, + 86, 90, 88, 92, 103, 77, 79, 83, 78, 81, + 80, 82, 13, 12, 15, 14, 17, 18, 19, 16, + 2, 1, 0, 4, 6, 7, 9, 8, 33, 32, + 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, + 24, 22, 5, 3, 10, 11, 106, 87, 91, 104, + 97, 100, +}; + +/* SCORE groups */ +static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 }; +static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 }; +static const struct byt_simple_func_mux byt_score_uart_mux[] = { + SIMPLE_FUNC("uart", 1), +}; + +static const unsigned int byt_score_pwm0_pins[] = { 94 }; +static const unsigned int byt_score_pwm1_pins[] = { 95 }; +static const struct byt_simple_func_mux byt_score_pwm_mux[] = { + SIMPLE_FUNC("pwm", 1), +}; + +static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 }; +static const struct byt_simple_func_mux byt_score_spi_mux[] = { + SIMPLE_FUNC("spi", 1), +}; + +static const unsigned int byt_score_i2c5_pins[] = { 88, 89 }; +static const unsigned int byt_score_i2c6_pins[] = { 90, 91 }; +static const unsigned int byt_score_i2c4_pins[] = { 86, 87 }; +static const unsigned int byt_score_i2c3_pins[] = { 84, 85 }; +static const unsigned int byt_score_i2c2_pins[] = { 82, 83 }; +static const unsigned int byt_score_i2c1_pins[] = { 80, 81 }; +static const unsigned int byt_score_i2c0_pins[] = { 78, 79 }; +static const struct byt_simple_func_mux byt_score_i2c_mux[] = { + SIMPLE_FUNC("i2c", 1), +}; + +static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 }; +static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 }; +static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 }; +static const struct byt_simple_func_mux byt_score_ssp_mux[] = { + SIMPLE_FUNC("ssp", 1), +}; + +static const unsigned int byt_score_sdcard_pins[] = { + 7, 33, 34, 35, 36, 37, 38, 39, 40, 41, +}; +static const unsigned short byt_score_sdcard_mux_values[] = { + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; +static const struct byt_mixed_func_mux byt_score_sdcard_mux[] = { + MIXED_FUNC("sdcard", byt_score_sdcard_mux_values), +}; + +static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 }; +static const struct byt_simple_func_mux byt_score_sdio_mux[] = { + SIMPLE_FUNC("sdio", 1), +}; + +static const unsigned int byt_score_emmc_pins[] = { + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, +}; +static const struct byt_simple_func_mux byt_score_emmc_mux[] = { + SIMPLE_FUNC("emmc", 1), +}; + +static const unsigned int byt_score_ilb_lpc_pins[] = { + 42, 43, 44, 45, 46, 47, 48, 49, 50, +}; +static const struct byt_simple_func_mux byt_score_lpc_mux[] = { + SIMPLE_FUNC("lpc", 1), +}; + +static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 }; +static const struct byt_simple_func_mux byt_score_sata_mux[] = { + SIMPLE_FUNC("sata", 1), +}; + +static const unsigned int byt_score_plt_clk0_pins[] = { 96 }; +static const unsigned int byt_score_plt_clk1_pins[] = { 97 }; +static const unsigned int byt_score_plt_clk2_pins[] = { 98 }; +static const unsigned int byt_score_plt_clk4_pins[] = { 99 }; +static const unsigned int byt_score_plt_clk5_pins[] = { 100 }; +static const unsigned int byt_score_plt_clk3_pins[] = { 101 }; +static const struct byt_simple_func_mux byt_score_plt_clk_mux[] = { + SIMPLE_FUNC("plt_clk", 1), }; -static unsigned const sus_pins[BYT_NGPIO_SUS] = { +static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 }; +static const struct byt_simple_func_mux byt_score_smbus_mux[] = { + SIMPLE_FUNC("smbus", 1), +}; + +static const struct byt_pingroup byt_score_groups[] = { + PIN_GROUP_SIMPLE("uart1_grp", + byt_score_uart1_pins, byt_score_uart_mux), + PIN_GROUP_SIMPLE("uart2_grp", + byt_score_uart2_pins, byt_score_uart_mux), + PIN_GROUP_SIMPLE("pwm0_grp", + byt_score_pwm0_pins, byt_score_pwm_mux), + PIN_GROUP_SIMPLE("pwm1_grp", + byt_score_pwm1_pins, byt_score_pwm_mux), + PIN_GROUP_SIMPLE("ssp2_grp", + byt_score_ssp2_pins, byt_score_pwm_mux), + PIN_GROUP_SIMPLE("sio_spi_grp", + byt_score_sio_spi_pins, byt_score_spi_mux), + PIN_GROUP_SIMPLE("i2c5_grp", + byt_score_i2c5_pins, byt_score_i2c_mux), + PIN_GROUP_SIMPLE("i2c6_grp", + byt_score_i2c6_pins, byt_score_i2c_mux), + PIN_GROUP_SIMPLE("i2c4_grp", + byt_score_i2c4_pins, byt_score_i2c_mux), + PIN_GROUP_SIMPLE("i2c3_grp", + byt_score_i2c3_pins, byt_score_i2c_mux), + PIN_GROUP_SIMPLE("i2c2_grp", + byt_score_i2c2_pins, byt_score_i2c_mux), + PIN_GROUP_SIMPLE("i2c1_grp", + byt_score_i2c1_pins, byt_score_i2c_mux), + PIN_GROUP_SIMPLE("i2c0_grp", + byt_score_i2c0_pins, byt_score_i2c_mux), + PIN_GROUP_SIMPLE("ssp0_grp", + byt_score_ssp0_pins, byt_score_ssp_mux), + PIN_GROUP_SIMPLE("ssp1_grp", + byt_score_ssp1_pins, byt_score_ssp_mux), + PIN_GROUP_MIXED("sdcard_grp", + byt_score_sdcard_pins, byt_score_sdcard_mux), + PIN_GROUP_SIMPLE("sdio_grp", + byt_score_sdio_pins, byt_score_sdio_mux), + PIN_GROUP_SIMPLE("emmc_grp", + byt_score_emmc_pins, byt_score_emmc_mux), + PIN_GROUP_SIMPLE("lpc_grp", + byt_score_ilb_lpc_pins, byt_score_lpc_mux), + PIN_GROUP_SIMPLE("sata_grp", + byt_score_sata_pins, byt_score_sata_mux), + PIN_GROUP_SIMPLE("plt_clk0_grp", + byt_score_plt_clk0_pins, byt_score_plt_clk_mux), + PIN_GROUP_SIMPLE("plt_clk1_grp", + byt_score_plt_clk1_pins, byt_score_plt_clk_mux), + PIN_GROUP_SIMPLE("plt_clk2_grp", + byt_score_plt_clk2_pins, byt_score_plt_clk_mux), + PIN_GROUP_SIMPLE("plt_clk3_grp", + byt_score_plt_clk3_pins, byt_score_plt_clk_mux), + PIN_GROUP_SIMPLE("plt_clk4_grp", + byt_score_plt_clk4_pins, byt_score_plt_clk_mux), + PIN_GROUP_SIMPLE("plt_clk5_grp", + byt_score_plt_clk5_pins, byt_score_plt_clk_mux), + PIN_GROUP_SIMPLE("smbus_grp", + byt_score_smbus_pins, byt_score_smbus_mux), +}; + +static const char * const byt_score_uart_groups[] = { + "uart1_grp", "uart2_grp", +}; +static const char * const byt_score_pwm_groups[] = { + "pwm0_grp", "pwm1_grp", +}; +static const char * const byt_score_ssp_groups[] = { + "ssp0_grp", "ssp1_grp", "ssp2_grp", +}; +static const char * const byt_score_spi_groups[] = { "sio_spi_grp" }; +static const char * const byt_score_i2c_groups[] = { + "i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", + "i2c6_grp", +}; +static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" }; +static const char * const byt_score_sdio_groups[] = { "sdio_grp" }; +static const char * const byt_score_emmc_groups[] = { "emmc_grp" }; +static const char * const byt_score_lpc_groups[] = { "lpc_grp" }; +static const char * const byt_score_sata_groups[] = { "sata_grp" }; +static const char * const byt_score_plt_clk_groups[] = { + "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp", + "plt_clk4_grp", "plt_clk5_grp", +}; +static const char * const byt_score_smbus_groups[] = { "smbus_grp" }; +static const char * const byt_score_gpio_groups[] = { + "uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp", + "ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp", + "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp", + "sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp", + "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp", + "plt_clk4_grp", "plt_clk5_grp", "smbus_grp", + +}; + +static const struct byt_function byt_score_functions[] = { + FUNCTION("uart", byt_score_uart_groups), + FUNCTION("pwm", byt_score_pwm_groups), + FUNCTION("ssp", byt_score_ssp_groups), + FUNCTION("spi", byt_score_spi_groups), + FUNCTION("i2c", byt_score_i2c_groups), + FUNCTION("sdcard", byt_score_sdcard_groups), + FUNCTION("sdio", byt_score_sdio_groups), + FUNCTION("emmc", byt_score_emmc_groups), + FUNCTION("lpc", byt_score_lpc_groups), + FUNCTION("sata", byt_score_sata_groups), + FUNCTION("plt_clk", byt_score_plt_clk_groups), + FUNCTION("smbus", byt_score_smbus_groups), + FUNCTION("gpio", byt_score_gpio_groups), +}; + +static const struct byt_community byt_score_communities[] = { + COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map), +}; + +static const struct byt_pinctrl_soc_data byt_score_soc_data = { + .uid = BYT_SCORE_ACPI_UID, + .pins = byt_score_pins, + .npins = ARRAY_SIZE(byt_score_pins), + .groups = byt_score_groups, + .ngroups = ARRAY_SIZE(byt_score_groups), + .functions = byt_score_functions, + .nfunctions = ARRAY_SIZE(byt_score_functions), + .communities = byt_score_communities, + .ncommunities = ARRAY_SIZE(byt_score_communities), +}; + +/* SUS pins, aka GPIOS_ or GPIO_S5[] */ +static const struct pinctrl_pin_desc byt_sus_pins[] = { + PINCTRL_PIN(0, "GPIO_S50"), + PINCTRL_PIN(1, "GPIO_S51"), + PINCTRL_PIN(2, "GPIO_S52"), + PINCTRL_PIN(3, "GPIO_S53"), + PINCTRL_PIN(4, "GPIO_S54"), + PINCTRL_PIN(5, "GPIO_S55"), + PINCTRL_PIN(6, "GPIO_S56"), + PINCTRL_PIN(7, "GPIO_S57"), + PINCTRL_PIN(8, "GPIO_S58"), + PINCTRL_PIN(9, "GPIO_S59"), + PINCTRL_PIN(10, "GPIO_S510"), + PINCTRL_PIN(11, "PMC_SUSPWRDNACK"), + PINCTRL_PIN(12, "PMC_SUSCLK0"), + PINCTRL_PIN(13, "GPIO_S513"), + PINCTRL_PIN(14, "USB_ULPI_RST"), + PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"), + PINCTRL_PIN(16, "PMC_PWRBTN"), + PINCTRL_PIN(17, "GPIO_S517"), + PINCTRL_PIN(18, "PMC_SUS_STAT"), + PINCTRL_PIN(19, "USB_OC0"), + PINCTRL_PIN(20, "USB_OC1"), + PINCTRL_PIN(21, "PCU_SPI_CS1"), + PINCTRL_PIN(22, "GPIO_S522"), + PINCTRL_PIN(23, "GPIO_S523"), + PINCTRL_PIN(24, "GPIO_S524"), + PINCTRL_PIN(25, "GPIO_S525"), + PINCTRL_PIN(26, "GPIO_S526"), + PINCTRL_PIN(27, "GPIO_S527"), + PINCTRL_PIN(28, "GPIO_S528"), + PINCTRL_PIN(29, "GPIO_S529"), + PINCTRL_PIN(30, "GPIO_S530"), + PINCTRL_PIN(31, "USB_ULPI_CLK"), + PINCTRL_PIN(32, "USB_ULPI_DATA0"), + PINCTRL_PIN(33, "USB_ULPI_DATA1"), + PINCTRL_PIN(34, "USB_ULPI_DATA2"), + PINCTRL_PIN(35, "USB_ULPI_DATA3"), + PINCTRL_PIN(36, "USB_ULPI_DATA4"), + PINCTRL_PIN(37, "USB_ULPI_DATA5"), + PINCTRL_PIN(38, "USB_ULPI_DATA6"), + PINCTRL_PIN(39, "USB_ULPI_DATA7"), + PINCTRL_PIN(40, "USB_ULPI_DIR"), + PINCTRL_PIN(41, "USB_ULPI_NXT"), + PINCTRL_PIN(42, "USB_ULPI_STP"), + PINCTRL_PIN(43, "USB_ULPI_REFCLK"), +}; + +static const unsigned int sus_pins[BYT_NGPIO_SUS] = { + 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, + 18, 7, 11, 20, 17, 1, 8, 10, 19, 12, + 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, + 26, 51, 56, 54, 49, 55, 48, 57, 50, 58, + 52, 53, 59, 40, +}; + +static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = { 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 18, 7, 11, 20, 17, 1, 8, 10, 19, 12, 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, @@ -113,6 +575,126 @@ static unsigned const sus_pins[BYT_NGPIO_SUS] = { 52, 53, 59, 40, }; +static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 }; +static const struct byt_simple_func_mux byt_sus_usb_oc_mux[] = { + SIMPLE_FUNC("usb", 0), + SIMPLE_FUNC("gpio", 1), +}; + +static const unsigned int byt_sus_usb_ulpi_pins[] = { + 14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, +}; +static const unsigned short byt_sus_usb_ulpi_mode_values[] = { + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; +static const unsigned short byt_sus_usb_ulpi_gpio_mode_values[] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static const struct byt_mixed_func_mux byt_sus_usb_ulpi_mux[] = { + MIXED_FUNC("usb", byt_sus_usb_ulpi_mode_values), + MIXED_FUNC("gpio", byt_sus_usb_ulpi_gpio_mode_values), +}; + +static const unsigned int byt_sus_pcu_spi_pins[] = { 21 }; +static const struct byt_simple_func_mux byt_sus_pcu_spi_mux[] = { + SIMPLE_FUNC("spi", 0), + SIMPLE_FUNC("gpio", 1), +}; + +static const struct byt_pingroup byt_sus_groups[] = { + PIN_GROUP_SIMPLE("usb_oc_grp", + byt_sus_usb_over_current_pins, byt_sus_usb_oc_mux), + PIN_GROUP_MIXED("usb_ulpi_grp", + byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mux), + PIN_GROUP_SIMPLE("pcu_spi_grp", + byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mux), +}; + +static const char * const byt_sus_usb_groups[] = { + "usb_oc_grp", "usb_ulpi_grp", +}; +static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" }; +static const char * const byt_sus_gpio_groups[] = { + "usb_oc_grp", "usb_ulpi_grp", "pcu_spi_grp", +}; + +static const struct byt_function byt_sus_functions[] = { + FUNCTION("usb", byt_sus_usb_groups), + FUNCTION("spi", byt_sus_spi_groups), + FUNCTION("gpio", byt_sus_gpio_groups), +}; + +static const struct byt_community byt_sus_communities[] = { + COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map), +}; + +static const struct byt_pinctrl_soc_data byt_sus_soc_data = { + .uid = BYT_SUS_ACPI_UID, + .pins = byt_sus_pins, + .npins = ARRAY_SIZE(byt_sus_pins), + .groups = byt_sus_groups, + .ngroups = ARRAY_SIZE(byt_sus_groups), + .functions = byt_sus_functions, + .nfunctions = ARRAY_SIZE(byt_sus_functions), + .communities = byt_sus_communities, + .ncommunities = ARRAY_SIZE(byt_sus_communities), +}; + +static const struct pinctrl_pin_desc byt_ncore_pins[] = { + PINCTRL_PIN(0, "GPIO_NCORE0"), + PINCTRL_PIN(1, "GPIO_NCORE1"), + PINCTRL_PIN(2, "GPIO_NCORE2"), + PINCTRL_PIN(3, "GPIO_NCORE3"), + PINCTRL_PIN(4, "GPIO_NCORE4"), + PINCTRL_PIN(5, "GPIO_NCORE5"), + PINCTRL_PIN(6, "GPIO_NCORE6"), + PINCTRL_PIN(7, "GPIO_NCORE7"), + PINCTRL_PIN(8, "GPIO_NCORE8"), + PINCTRL_PIN(9, "GPIO_NCORE9"), + PINCTRL_PIN(10, "GPIO_NCORE10"), + PINCTRL_PIN(11, "GPIO_NCORE11"), + PINCTRL_PIN(12, "GPIO_NCORE12"), + PINCTRL_PIN(13, "GPIO_NCORE13"), + PINCTRL_PIN(14, "GPIO_NCORE14"), + PINCTRL_PIN(15, "GPIO_NCORE15"), + PINCTRL_PIN(16, "GPIO_NCORE16"), + PINCTRL_PIN(17, "GPIO_NCORE17"), + PINCTRL_PIN(18, "GPIO_NCORE18"), + PINCTRL_PIN(19, "GPIO_NCORE19"), + PINCTRL_PIN(20, "GPIO_NCORE20"), + PINCTRL_PIN(21, "GPIO_NCORE21"), + PINCTRL_PIN(22, "GPIO_NCORE22"), + PINCTRL_PIN(23, "GPIO_NCORE23"), + PINCTRL_PIN(24, "GPIO_NCORE24"), + PINCTRL_PIN(25, "GPIO_NCORE25"), + PINCTRL_PIN(26, "GPIO_NCORE26"), + PINCTRL_PIN(27, "GPIO_NCORE27"), +}; + +static unsigned const byt_ncore_pins_map[BYT_NGPIO_NCORE] = { + 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, + 14, 15, 12, 26, 27, 1, 4, 8, 11, 0, + 3, 6, 10, 13, 2, 5, 9, 7, +}; + +static const struct byt_community byt_ncore_communities[] = { + COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map), +}; + +static const struct byt_pinctrl_soc_data byt_ncore_soc_data = { + .uid = BYT_NCORE_ACPI_UID, + .pins = byt_ncore_pins, + .npins = ARRAY_SIZE(byt_ncore_pins), + .communities = byt_ncore_communities, + .ncommunities = ARRAY_SIZE(byt_ncore_communities), +}; + +static unsigned const ncore_pins[BYT_NGPIO_NCORE] = { + 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, + 14, 15, 12, 26, 27, 1, 4, 8, 11, 0, + 3, 6, 10, 13, 2, 5, 9, 7, +}; + static struct pinctrl_gpio_range byt_ranges[] = { { .name = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */ @@ -133,11 +715,6 @@ static struct pinctrl_gpio_range byt_ranges[] = { }, }; -struct byt_gpio_pin_context { - u32 conf0; - u32 val; -}; - struct byt_gpio { struct gpio_chip chip; struct platform_device *pdev; @@ -147,6 +724,13 @@ struct byt_gpio { struct byt_gpio_pin_context *saved_context; }; +static const struct byt_pinctrl_soc_data *byt_soc_data[] = { + &byt_score_soc_data, + &byt_sus_soc_data, + &byt_ncore_soc_data, + NULL, +}; + static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset, int reg) { @@ -713,8 +1297,8 @@ static const struct dev_pm_ops byt_gpio_pm_ops = { }; static const struct acpi_device_id byt_gpio_acpi_match[] = { - { "INT33B2", 0 }, - { "INT33FC", 0 }, + { "INT33B2", (kernel_ulong_t)byt_soc_data }, + { "INT33FC", (kernel_ulong_t)byt_soc_data }, { } }; MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); -- GitLab From c501d0b149de1248fa9c29c906bf70f3b87b8bd8 Mon Sep 17 00:00:00 2001 From: Cristina Ciocan Date: Fri, 1 Apr 2016 14:00:03 +0300 Subject: [PATCH 1173/9938] pinctrl: baytrail: Add pin control operations Add implementation for: - pin control, group information retrieval: count, name and pins - pin muxing: - function information (count, name and groups) - mux setting - gpio control (enable, disable, set direction) - pin configuration: - pull disable - pull up/down and pull strength - debounce - any other option is treated as not supported. Signed-off-by: Cristina Ciocan Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/Kconfig | 3 + drivers/pinctrl/intel/pinctrl-baytrail.c | 560 +++++++++++++++++++++-- 2 files changed, 528 insertions(+), 35 deletions(-) diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig index 4d2efad6553c..1c74e038b7b0 100644 --- a/drivers/pinctrl/intel/Kconfig +++ b/drivers/pinctrl/intel/Kconfig @@ -6,6 +6,9 @@ config PINCTRL_BAYTRAIL bool "Intel Baytrail GPIO pin control" depends on GPIOLIB && ACPI select GPIOLIB_IRQCHIP + select PINMUX + select PINCONF + select GENERIC_PINCONF help driver for memory mapped GPIO functionality on Intel Baytrail platforms. Supports 3 banks with 102, 28 and 44 gpios. diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 364f56c3991d..415d2d5554b5 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include /* memory mapped register offsets */ #define BYT_CONF0_REG 0x000 @@ -73,6 +76,14 @@ #define BYT_NCORE_ACPI_UID "2" #define BYT_SUS_ACPI_UID "3" +/* + * This is the function value most pins have for GPIO muxing. If the value + * differs from the default one, it must be explicitly mentioned. Otherwise, the + * pin control implementation will set the muxing value to default GPIO if it + * does not find a match for the requested function. + */ +#define BYT_DEFAULT_GPIO_MUX 0 + struct byt_gpio_pin_context { u32 conf0; u32 val; @@ -722,6 +733,8 @@ struct byt_gpio { void __iomem *reg_base; struct pinctrl_gpio_range *range; struct byt_gpio_pin_context *saved_context; + const struct byt_pinctrl_soc_data *soc_data; + struct byt_community *communities_copy; }; static const struct byt_pinctrl_soc_data *byt_soc_data[] = { @@ -731,52 +744,252 @@ static const struct byt_pinctrl_soc_data *byt_soc_data[] = { NULL, }; -static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset, - int reg) +static struct byt_community *byt_get_community(struct byt_gpio *vg, + unsigned int pin) { - struct byt_gpio *vg = gpiochip_get_data(chip); - u32 reg_offset; + struct byt_community *comm; + int i; + + for (i = 0; i < vg->soc_data->ncommunities; i++) { + comm = vg->communities_copy + i; + if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base) + return comm; + } + return NULL; +} + +static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset, + int reg) +{ + struct byt_community *comm = byt_get_community(vg, offset); + u32 reg_offset = 0; + + if (!comm) + return NULL; + + offset -= comm->pin_base; if (reg == BYT_INT_STAT_REG) reg_offset = (offset / 32) * 4; else - reg_offset = vg->range->pins[offset] * 16; + reg_offset = comm->pad_map[offset] * 16; + + return comm->reg_base + reg_offset + reg; +} + +static int byt_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev); + + return vg->soc_data->ngroups; +} + +static const char *byt_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev); + + return vg->soc_data->groups[selector].name; +} + +static int byt_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev); + + *pins = vg->soc_data->groups[selector].pins; + *num_pins = vg->soc_data->groups[selector].npins; + + return 0; +} + +static const struct pinctrl_ops byt_pinctrl_ops = { + .get_groups_count = byt_get_groups_count, + .get_group_name = byt_get_group_name, + .get_group_pins = byt_get_group_pins, +}; + +static int byt_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev); + + return vg->soc_data->nfunctions; +} + +static const char *byt_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev); + + return vg->soc_data->functions[selector].name; +} + +static int byt_get_function_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned int *num_groups) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev); + + *groups = vg->soc_data->functions[selector].groups; + *num_groups = vg->soc_data->functions[selector].ngroups; + + return 0; +} + +static int byt_get_group_simple_mux(const struct byt_pingroup group, + const char *func_name, + unsigned short *func) +{ + int i; + + for (i = 0; i < group.nfuncs; i++) { + if (!strcmp(group.simple_funcs[i].name, func_name)) { + *func = group.simple_funcs[i].func; + return 0; + } + } + + return 1; +} + +static int byt_get_group_mixed_mux(const struct byt_pingroup group, + const char *func_name, + const unsigned short **func) +{ + int i; + + for (i = 0; i < group.nfuncs; i++) { + if (!strcmp(group.mixed_funcs[i].name, func_name)) { + *func = group.mixed_funcs[i].func_values; + return 0; + } + } - return vg->reg_base + reg_offset + reg; + return 1; } -static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned offset) +static void byt_set_group_simple_mux(struct byt_gpio *vg, + const struct byt_pingroup group, + unsigned short func) { - void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); unsigned long flags; - u32 value; + int i; raw_spin_lock_irqsave(&vg->lock, flags); - value = readl(reg); - value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); - writel(value, reg); + + for (i = 0; i < group.npins; i++) { + void __iomem *padcfg0; + u32 value; + + padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG); + if (!padcfg0) { + dev_warn(&vg->pdev->dev, + "Group %s, pin %i not muxed (no padcfg0)\n", + group.name, i); + continue; + } + + value = readl(padcfg0); + value &= ~BYT_PIN_MUX; + value |= func; + writel(value, padcfg0); + } + raw_spin_unlock_irqrestore(&vg->lock, flags); } +static void byt_set_group_mixed_mux(struct byt_gpio *vg, + const struct byt_pingroup group, + const unsigned short *func) +{ + unsigned long flags; + int i; + + raw_spin_lock_irqsave(&vg->lock, flags); + + for (i = 0; i < group.npins; i++) { + void __iomem *padcfg0; + u32 value; + + padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG); + if (!padcfg0) { + dev_warn(&vg->pdev->dev, + "Group %s, pin %i not muxed (no padcfg0)\n", + group.name, i); + continue; + } + + value = readl(padcfg0); + value &= ~BYT_PIN_MUX; + value |= func[i]; + writel(value, padcfg0); + } + + raw_spin_unlock_irqrestore(&vg->lock, flags); +} + +static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, + unsigned int group_selector) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev); + const struct byt_function func = vg->soc_data->functions[func_selector]; + const struct byt_pingroup group = vg->soc_data->groups[group_selector]; + const unsigned short *mixed_func; + unsigned short simple_func; + int ret = 1; + + if (group.has_simple_funcs) + ret = byt_get_group_simple_mux(group, func.name, &simple_func); + else + ret = byt_get_group_mixed_mux(group, func.name, &mixed_func); + + if (ret) + byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX); + else if (group.has_simple_funcs) + byt_set_group_simple_mux(vg, group, simple_func); + else + byt_set_group_mixed_mux(vg, group, mixed_func); + + return 0; +} + static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset) { /* SCORE pin 92-93 */ - if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) && - offset >= 92 && offset <= 93) + if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) && + offset >= 92 && offset <= 93) return 1; /* SUS pin 11-21 */ - if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) && - offset >= 11 && offset <= 21) + if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) && + offset >= 11 && offset <= 21) return 1; return 0; } -static int byt_gpio_request(struct gpio_chip *chip, unsigned offset) +static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset) { - struct byt_gpio *vg = gpiochip_get_data(chip); - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG); + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&vg->lock, flags); + value = readl(reg); + value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); + writel(value, reg); + raw_spin_unlock_irqrestore(&vg->lock, flags); +} + +static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev); + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); u32 value, gpio_mux; unsigned long flags; @@ -817,13 +1030,102 @@ static void byt_gpio_free(struct gpio_chip *chip, unsigned offset) pm_runtime_put(&vg->pdev->dev); } +static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev); + + byt_gpio_clear_triggering(vg, offset); + pm_runtime_put(&vg->pdev->dev); +} + +static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, + struct pinctrl_gpio_range *range, + unsigned int offset, + bool input) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev); + void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&vg->lock, flags); + + value = readl(val_reg); + value &= ~BYT_DIR_MASK; + if (input) + value |= BYT_OUTPUT_EN; + else + /* + * Before making any direction modifications, do a check if gpio + * is set for direct IRQ. On baytrail, setting GPIO to output + * does not make sense, so let's at least warn the caller before + * they shoot themselves in the foot. + */ + WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, + "Potential Error: Setting GPIO with direct_irq_en to output"); + writel(value, val_reg); + + raw_spin_unlock_irqrestore(&vg->lock, flags); + + return 0; +} + +static const struct pinmux_ops byt_pinmux_ops = { + .get_functions_count = byt_get_functions_count, + .get_function_name = byt_get_function_name, + .get_function_groups = byt_get_function_groups, + .set_mux = byt_set_mux, + .gpio_request_enable = byt_gpio_request_enable, + .gpio_disable_free = byt_gpio_disable_free, + .gpio_set_direction = byt_gpio_set_direction, +}; + +static int byt_gpio_request(struct gpio_chip *chip, unsigned int offset) +{ + struct byt_gpio *vg = gpiochip_get_data(chip); + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + u32 value, gpio_mux; + unsigned long flags; + + raw_spin_lock_irqsave(&vg->lock, flags); + + /* + * In most cases, func pin mux 000 means GPIO function. + * But, some pins may have func pin mux 001 represents + * GPIO function. + * + * Because there are devices out there where some pins were not + * configured correctly we allow changing the mux value from + * request (but print out warning about that). + */ + value = readl(reg) & BYT_PIN_MUX; + gpio_mux = byt_get_gpio_mux(vg, offset); + if (WARN_ON(gpio_mux != value)) { + value = readl(reg) & ~BYT_PIN_MUX; + value |= gpio_mux; + writel(value, reg); + + dev_warn(&vg->pdev->dev, + "pin %u forcibly re-configured as GPIO\n", offset); + } + + raw_spin_unlock_irqrestore(&vg->lock, flags); + + pm_runtime_get(&vg->pdev->dev); + + return 0; +} + static int byt_irq_type(struct irq_data *d, unsigned type) { struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d)); u32 offset = irqd_to_hwirq(d); u32 value; unsigned long flags; - void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); if (offset >= vg->chip.ngpio) return -EINVAL; @@ -832,7 +1134,7 @@ static int byt_irq_type(struct irq_data *d, unsigned type) value = readl(reg); WARN(value & BYT_DIRECT_IRQ_EN, - "Bad pad config for io mode, force direct_irq_en bit clearing"); + "Bad pad config for io mode, force direct_irq_en bit clearing"); /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits * are used to indicate high and low level triggering @@ -852,10 +1154,198 @@ static int byt_irq_type(struct irq_data *d, unsigned type) return 0; } +static void byt_get_pull_strength(u32 reg, u16 *strength) +{ + switch (reg & BYT_PULL_STR_MASK) { + case BYT_PULL_STR_2K: + *strength = 2000; + break; + case BYT_PULL_STR_10K: + *strength = 10000; + break; + case BYT_PULL_STR_20K: + *strength = 20000; + break; + case BYT_PULL_STR_40K: + *strength = 40000; + break; + } +} + +static int byt_set_pull_strength(u32 *reg, u16 strength) +{ + *reg &= ~BYT_PULL_STR_MASK; + + switch (strength) { + case 2000: + *reg |= BYT_PULL_STR_2K; + break; + case 10000: + *reg |= BYT_PULL_STR_10K; + break; + case 20000: + *reg |= BYT_PULL_STR_20K; + break; + case 40000: + *reg |= BYT_PULL_STR_40K; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, + unsigned long *config) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev); + enum pin_config_param param = pinconf_to_config_param(*config); + void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + unsigned long flags; + u32 conf, pull, val; + u16 arg = 0; + + raw_spin_lock_irqsave(&vg->lock, flags); + conf = readl(conf_reg); + pull = conf & BYT_PULL_ASSIGN_MASK; + val = readl(val_reg); + raw_spin_unlock_irqrestore(&vg->lock, flags); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + if (pull) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + /* Pull assignment is only applicable in input mode */ + if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN) + return -EINVAL; + + byt_get_pull_strength(conf, &arg); + + break; + case PIN_CONFIG_BIAS_PULL_UP: + /* Pull assignment is only applicable in input mode */ + if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP) + return -EINVAL; + + byt_get_pull_strength(conf, &arg); + + break; + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, + unsigned int offset, + unsigned long *configs, + unsigned int num_configs) +{ + struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev); + unsigned int param, arg; + void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + unsigned long flags; + u32 conf, val; + int i, ret = 0; + + raw_spin_lock_irqsave(&vg->lock, flags); + + conf = readl(conf_reg); + val = readl(val_reg); + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + conf &= ~BYT_PULL_ASSIGN_MASK; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + /* Set default strength value in case none is given */ + if (arg == 1) + arg = 2000; + + /* + * Pull assignment is only applicable in input mode. If + * chip is not in input mode, set it and warn about it. + */ + if (val & BYT_INPUT_EN) { + val &= ~BYT_INPUT_EN; + writel(val, val_reg); + dev_warn(&vg->pdev->dev, + "pin %u forcibly set to input mode\n", + offset); + } + + conf &= ~BYT_PULL_ASSIGN_MASK; + conf |= BYT_PULL_ASSIGN_DOWN; + ret = byt_set_pull_strength(&conf, arg); + + break; + case PIN_CONFIG_BIAS_PULL_UP: + /* Set default strength value in case none is given */ + if (arg == 1) + arg = 2000; + + /* + * Pull assignment is only applicable in input mode. If + * chip is not in input mode, set it and warn about it. + */ + if (val & BYT_INPUT_EN) { + val &= ~BYT_INPUT_EN; + writel(val, val_reg); + dev_warn(&vg->pdev->dev, + "pin %u forcibly set to input mode\n", + offset); + } + + conf &= ~BYT_PULL_ASSIGN_MASK; + conf |= BYT_PULL_ASSIGN_UP; + ret = byt_set_pull_strength(&conf, arg); + + break; + default: + ret = -ENOTSUPP; + } + + if (ret) + break; + } + + if (!ret) + writel(conf, conf_reg); + + raw_spin_unlock_irqrestore(&vg->lock, flags); + + return ret; +} + +static const struct pinconf_ops byt_pinconf_ops = { + .is_generic = true, + .pin_config_get = byt_pin_config_get, + .pin_config_set = byt_pin_config_set, +}; + +static const struct pinctrl_desc byt_pinctrl_desc = { + .pctlops = &byt_pinctrl_ops, + .pmxops = &byt_pinmux_ops, + .confops = &byt_pinconf_ops, + .owner = THIS_MODULE, +}; + static int byt_gpio_get(struct gpio_chip *chip, unsigned offset) { - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); struct byt_gpio *vg = gpiochip_get_data(chip); + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); unsigned long flags; u32 val; @@ -869,7 +1359,7 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset) static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct byt_gpio *vg = gpiochip_get_data(chip); - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); unsigned long flags; u32 old_val; @@ -888,7 +1378,7 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct byt_gpio *vg = gpiochip_get_data(chip); - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); unsigned long flags; u32 value; @@ -907,8 +1397,8 @@ static int byt_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { struct byt_gpio *vg = gpiochip_get_data(chip); - void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG); - void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG); + void __iomem *conf_reg = byt_gpio_reg(vg, gpio, BYT_CONF0_REG); + void __iomem *reg = byt_gpio_reg(vg, gpio, BYT_VAL_REG); unsigned long flags; u32 reg_val; @@ -1019,7 +1509,7 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) /* check from GPIO controller which pin triggered the interrupt */ for (base = 0; base < vg->chip.ngpio; base += 32) { - reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); + reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); pending = readl(reg); for_each_set_bit(pin, &pending, 32) { virq = irq_find_mapping(vg->chip.irqdomain, base + pin); @@ -1037,7 +1527,7 @@ static void byt_irq_ack(struct irq_data *d) void __iomem *reg; raw_spin_lock(&vg->lock); - reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG); + reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG); writel(BIT(offset % 32), reg); raw_spin_unlock(&vg->lock); } @@ -1051,7 +1541,7 @@ static void byt_irq_unmask(struct irq_data *d) void __iomem *reg; u32 value; - reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); + reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); raw_spin_lock_irqsave(&vg->lock, flags); value = readl(reg); @@ -1106,7 +1596,7 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg) * interrupts from misconfigured pins. */ for (i = 0; i < vg->chip.ngpio; i++) { - value = readl(byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG)); + value = readl(byt_gpio_reg(vg, i, BYT_CONF0_REG)); if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) && !(value & BYT_DIRECT_IRQ_EN)) { byt_gpio_clear_triggering(vg, i); @@ -1116,7 +1606,7 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg) /* clear interrupt status trigger registers */ for (base = 0; base < vg->chip.ngpio; base += 32) { - reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); + reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); writel(0xffffffff, reg); /* make sure trigger bits are cleared, if not then a pin might be misconfigured in bios */ @@ -1226,11 +1716,11 @@ static int byt_gpio_suspend(struct device *dev) void __iomem *reg; u32 value; - reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG); + reg = byt_gpio_reg(vg, i, BYT_CONF0_REG); value = readl(reg) & BYT_CONF0_RESTORE_MASK; vg->saved_context[i].conf0 = value; - reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG); + reg = byt_gpio_reg(vg, i, BYT_VAL_REG); value = readl(reg) & BYT_VAL_RESTORE_MASK; vg->saved_context[i].val = value; } @@ -1248,7 +1738,7 @@ static int byt_gpio_resume(struct device *dev) void __iomem *reg; u32 value; - reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG); + reg = byt_gpio_reg(vg, i, BYT_CONF0_REG); value = readl(reg); if ((value & BYT_CONF0_RESTORE_MASK) != vg->saved_context[i].conf0) { @@ -1258,7 +1748,7 @@ static int byt_gpio_resume(struct device *dev) dev_info(dev, "restored pin %d conf0 %#08x", i, value); } - reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG); + reg = byt_gpio_reg(vg, i, BYT_VAL_REG); value = readl(reg); if ((value & BYT_VAL_RESTORE_MASK) != vg->saved_context[i].val) { -- GitLab From 86e3ef812fe3df8298c0bee81b0c786006a9c85c Mon Sep 17 00:00:00 2001 From: Cristina Ciocan Date: Fri, 1 Apr 2016 14:00:04 +0300 Subject: [PATCH 1174/9938] pinctrl: baytrail: Update gpio chip operations This patch updates the gpio chip implementation in order to interact with the pin control model: the chip contains reference to SOC data and pin/group/community information is retrieved through the SOC reference. Signed-off-by: Cristina Ciocan Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-baytrail.c | 97 +++++++++++++++++------- 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 415d2d5554b5..a24b51e47f00 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1363,44 +1364,45 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) unsigned long flags; u32 old_val; - raw_spin_lock_irqsave(&vg->lock, flags); + if (!reg) + return; + raw_spin_lock_irqsave(&vg->lock, flags); old_val = readl(reg); - if (value) writel(old_val | BYT_LEVEL, reg); else writel(old_val & ~BYT_LEVEL, reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); } -static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { struct byt_gpio *vg = gpiochip_get_data(chip); void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); unsigned long flags; u32 value; - raw_spin_lock_irqsave(&vg->lock, flags); - - value = readl(reg) | BYT_DIR_MASK; - value &= ~BYT_INPUT_EN; /* active low */ - writel(value, reg); + if (!reg) + return -EINVAL; + raw_spin_lock_irqsave(&vg->lock, flags); + value = readl(reg); raw_spin_unlock_irqrestore(&vg->lock, flags); - return 0; + if (!(value & BYT_OUTPUT_EN)) + return GPIOF_DIR_OUT; + if (!(value & BYT_INPUT_EN)) + return GPIOF_DIR_IN; + + return -EINVAL; } -static int byt_gpio_direction_output(struct gpio_chip *chip, - unsigned gpio, int value) +static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { struct byt_gpio *vg = gpiochip_get_data(chip); - void __iomem *conf_reg = byt_gpio_reg(vg, gpio, BYT_CONF0_REG); - void __iomem *reg = byt_gpio_reg(vg, gpio, BYT_VAL_REG); + void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); unsigned long flags; - u32 reg_val; raw_spin_lock_irqsave(&vg->lock, flags); @@ -1413,15 +1415,18 @@ static int byt_gpio_direction_output(struct gpio_chip *chip, WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, "Potential Error: Setting GPIO with direct_irq_en to output"); - reg_val = readl(reg) | BYT_DIR_MASK; - reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN); + return pinctrl_gpio_direction_input(chip->base + offset); +} - if (value) - writel(reg_val | BYT_LEVEL, reg); - else - writel(reg_val & ~BYT_LEVEL, reg); +static int byt_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + int ret = pinctrl_gpio_direction_output(chip->base + offset); - raw_spin_unlock_irqrestore(&vg->lock, flags); + if (ret) + return ret; + + byt_gpio_set(chip, offset, value); return 0; } @@ -1430,20 +1435,42 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { struct byt_gpio *vg = gpiochip_get_data(chip); int i; - u32 conf0, val, offs; + u32 conf0, val; - for (i = 0; i < vg->chip.ngpio; i++) { + for (i = 0; i < vg->soc_data->npins; i++) { + const struct byt_community *comm; const char *pull_str = NULL; const char *pull = NULL; + void __iomem *reg; unsigned long flags; const char *label; - offs = vg->range->pins[i] * 16; + unsigned int pin; raw_spin_lock_irqsave(&vg->lock, flags); - conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); - val = readl(vg->reg_base + offs + BYT_VAL_REG); + pin = vg->soc_data->pins[i].number; + reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); + if (!reg) { + seq_printf(s, + "Could not retrieve pin %i conf0 reg\n", + pin); + continue; + } + conf0 = readl(reg); + + reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); + if (!reg) { + seq_printf(s, + "Could not retrieve pin %i val reg\n", pin); + } + val = readl(reg); raw_spin_unlock_irqrestore(&vg->lock, flags); + comm = byt_get_community(vg, pin); + if (!comm) { + seq_printf(s, + "Could not get community for pin %i\n", pin); + continue; + } label = gpiochip_is_requested(chip, i); if (!label) label = "Unrequested"; @@ -1474,12 +1501,12 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s", - i, + pin, label, val & BYT_INPUT_EN ? " " : "in", val & BYT_OUTPUT_EN ? " " : "out", val & BYT_LEVEL ? "hi" : "lo", - vg->range->pins[i], offs, + comm->pad_map[i], comm->pad_map[i] * 32, conf0 & 0x7, conf0 & BYT_TRIG_NEG ? " fall" : " ", conf0 & BYT_TRIG_POS ? " rise" : " ", @@ -1519,6 +1546,18 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) chip->irq_eoi(data); } +static const struct gpio_chip byt_gpio_chip = { + .owner = THIS_MODULE, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .get_direction = byt_gpio_get_direction, + .direction_input = byt_gpio_direction_input, + .direction_output = byt_gpio_direction_output, + .get = byt_gpio_get, + .set = byt_gpio_set, + .dbg_show = byt_gpio_dbg_show, +}; + static void byt_irq_ack(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); -- GitLab From f9575793d44ce68b574d9d8ffb9813eb05c3fd2b Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 16 Mar 2016 18:13:34 +0530 Subject: [PATCH 1175/9938] ath10k: enable parsing per station rx duration for 10.4 Rx duration support for per station is part of extended peer stats, enable provision to parse the same and provide backward compatibility based on the 'stats_id' event Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 19 +++++++++++++++- drivers/net/wireless/ath/ath10k/wmi.c | 30 ++++++++++++++++++++------ drivers/net/wireless/ath/ath10k/wmi.h | 16 ++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 7a714d971615..b2c7fe3d30a4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1615,7 +1615,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS; ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; ar->num_tids = TARGET_10_4_TGT_NUM_TIDS; - ar->fw_stats_req_mask = WMI_STAT_PEER; + ar->fw_stats_req_mask = WMI_10_4_STAT_PEER | + WMI_10_4_STAT_PEER_EXTD; ar->max_spatial_stream = ar->hw_params.max_spatial_stream; if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, @@ -1660,6 +1661,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) { int status; + u32 val; lockdep_assert_held(&ar->conf_mutex); @@ -1780,6 +1782,21 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n", ar->hw->wiphy->fw_version); + if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) { + val = 0; + if (ath10k_peer_stats_enabled(ar)) + val = WMI_10_4_PEER_STATS; + + status = ath10k_wmi_ext_resource_config(ar, + WMI_HOST_PLATFORM_HIGH_PERF, val); + if (status) { + ath10k_err(ar, + "failed to send ext resource cfg command : %d\n", + status); + goto err_hif_stop; + } + } + status = ath10k_wmi_cmd_init(ar); if (status) { ath10k_err(ar, "could not send WMI init command (%d)\n", diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 3af1af74e84d..ac8622718f58 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2604,6 +2604,16 @@ void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); } +static void +ath10k_wmi_10_4_pull_peer_stats(const struct wmi_10_4_peer_stats *src, + struct ath10k_fw_stats_peer *dst) +{ + ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); + dst->peer_rssi = __le32_to_cpu(src->peer_rssi); + dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); + dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); +} + static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb, struct ath10k_fw_stats *stats) @@ -2894,6 +2904,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, u32 num_pdev_ext_stats; u32 num_vdev_stats; u32 num_peer_stats; + u32 stats_id; int i; if (!skb_pull(skb, sizeof(*ev))) @@ -2903,6 +2914,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); num_peer_stats = __le32_to_cpu(ev->num_peer_stats); + stats_id = __le32_to_cpu(ev->stats_id); for (i = 0; i < num_pdev_stats; i++) { const struct wmi_10_4_pdev_stats *src; @@ -2942,22 +2954,28 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, /* fw doesn't implement vdev stats */ for (i = 0; i < num_peer_stats; i++) { - const struct wmi_10_4_peer_stats *src; + const struct wmi_10_4_peer_extd_stats *src; struct ath10k_fw_stats_peer *dst; + int stats_len; + bool extd_peer_stats = !!(stats_id & WMI_10_4_STAT_PEER_EXTD); + + if (extd_peer_stats) + stats_len = sizeof(struct wmi_10_4_peer_extd_stats); + else + stats_len = sizeof(struct wmi_10_4_peer_stats); src = (void *)skb->data; - if (!skb_pull(skb, sizeof(*src))) + if (!skb_pull(skb, stats_len)) return -EPROTO; dst = kzalloc(sizeof(*dst), GFP_ATOMIC); if (!dst) continue; - ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); - dst->peer_rssi = __le32_to_cpu(src->peer_rssi); - dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); - dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); + ath10k_wmi_10_4_pull_peer_stats(&src->common, dst); /* FIXME: expose 10.4 specific values */ + if (extd_peer_stats) + dst->rx_duration = __le32_to_cpu(src->rx_duration); list_add_tail(&dst->list, &stats->peers); } diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index bd29f271524d..feebd19ff08c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4104,6 +4104,13 @@ enum wmi_stats_id { WMI_STAT_VDEV_RATE = BIT(5), }; +enum wmi_10_4_stats_id { + WMI_10_4_STAT_PEER = BIT(0), + WMI_10_4_STAT_AP = BIT(1), + WMI_10_4_STAT_INST = BIT(2), + WMI_10_4_STAT_PEER_EXTD = BIT(3), +}; + struct wlan_inst_rssi_args { __le16 cfg_retry_count; __le16 retry_count; @@ -4303,6 +4310,15 @@ struct wmi_10_4_peer_stats { __le32 peer_rssi_changed; } __packed; +struct wmi_10_4_peer_extd_stats { + struct wmi_10_4_peer_stats common; + struct wmi_mac_addr peer_macaddr; + __le32 inactive_time; + __le32 peer_chain_rssi; + __le32 rx_duration; + __le32 reserved[10]; +} __packed; + struct wmi_10_2_pdev_ext_stats { __le32 rx_rssi_comb; __le32 rx_rssi[4]; -- GitLab From 59465fe46ef1c2caf2c1beca828c4f29d28b98ca Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:11 +0530 Subject: [PATCH 1176/9938] ath10k: speedup htt rx descriptor processing for tx completion To optimize CPU usage htt rx descriptors will be reused instead of refilling it for htt rx copy engine (CE5). To support that all htt rx indications should be processed at same context. FIFO queue is used to maintain tx completion status for each msdu. This helps to retain the order of tx completion. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 18 ++++++-- drivers/net/wireless/ath/ath10k/htt_rx.c | 58 ++++++++++++++---------- drivers/net/wireless/ath/ath10k/htt_tx.c | 14 +++++- drivers/net/wireless/ath/ath10k/txrx.c | 12 ++--- 4 files changed, 65 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index d196bcc50e50..76c4bae0b434 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "htc.h" @@ -1526,10 +1527,15 @@ struct htt_resp { /*** host side structures follow ***/ struct htt_tx_done { - u32 msdu_id; - bool discard; - bool no_ack; - bool success; + u16 msdu_id; + u16 status; +}; + +enum htt_tx_compl_state { + HTT_TX_COMPL_STATE_NONE, + HTT_TX_COMPL_STATE_ACK, + HTT_TX_COMPL_STATE_NOACK, + HTT_TX_COMPL_STATE_DISCARD, }; struct htt_peer_map_event { @@ -1650,6 +1656,9 @@ struct ath10k_htt { struct idr pending_tx; wait_queue_head_t empty_tx_wq; + /* FIFO for storing tx done status {ack, no-ack, discard} and msdu id */ + DECLARE_KFIFO_PTR(txdone_fifo, struct htt_tx_done); + /* set if host-fw communication goes haywire * used to avoid further failures */ bool rx_confused; @@ -1658,7 +1667,6 @@ struct ath10k_htt { /* This is used to group tx/rx completions separately and process them * in batches to reduce cache stalls */ struct tasklet_struct txrx_compl_task; - struct sk_buff_head tx_compl_q; struct sk_buff_head rx_compl_q; struct sk_buff_head rx_in_ord_compl_q; struct sk_buff_head tx_fetch_ind_q; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 06975bf49351..ea73a233ecd7 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -226,7 +226,6 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) tasklet_kill(&htt->rx_replenish_task); tasklet_kill(&htt->txrx_compl_task); - skb_queue_purge(&htt->tx_compl_q); skb_queue_purge(&htt->rx_compl_q); skb_queue_purge(&htt->rx_in_ord_compl_q); skb_queue_purge(&htt->tx_fetch_ind_q); @@ -567,7 +566,6 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task, (unsigned long)htt); - skb_queue_head_init(&htt->tx_compl_q); skb_queue_head_init(&htt->rx_compl_q); skb_queue_head_init(&htt->rx_in_ord_compl_q); skb_queue_head_init(&htt->tx_fetch_ind_q); @@ -1678,7 +1676,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, } } -static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, +static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; @@ -1690,19 +1688,19 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, switch (status) { case HTT_DATA_TX_STATUS_NO_ACK: - tx_done.no_ack = true; + tx_done.status = HTT_TX_COMPL_STATE_NOACK; break; case HTT_DATA_TX_STATUS_OK: - tx_done.success = true; + tx_done.status = HTT_TX_COMPL_STATE_ACK; break; case HTT_DATA_TX_STATUS_DISCARD: case HTT_DATA_TX_STATUS_POSTPONE: case HTT_DATA_TX_STATUS_DOWNLOAD_FAIL: - tx_done.discard = true; + tx_done.status = HTT_TX_COMPL_STATE_DISCARD; break; default: ath10k_warn(ar, "unhandled tx completion status %d\n", status); - tx_done.discard = true; + tx_done.status = HTT_TX_COMPL_STATE_DISCARD; break; } @@ -1712,7 +1710,20 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { msdu_id = resp->data_tx_completion.msdus[i]; tx_done.msdu_id = __le16_to_cpu(msdu_id); - ath10k_txrx_tx_unref(htt, &tx_done); + + /* kfifo_put: In practice firmware shouldn't fire off per-CE + * interrupt and main interrupt (MSI/-X range case) for the same + * HTC service so it should be safe to use kfifo_put w/o lock. + * + * From kfifo_put() documentation: + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these macro. + */ + if (!kfifo_put(&htt->txdone_fifo, tx_done)) { + ath10k_warn(ar, "txdone fifo overrun, msdu_id %d status %d\n", + tx_done.msdu_id, tx_done.status); + ath10k_txrx_tx_unref(htt, &tx_done); + } } } @@ -2339,18 +2350,17 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) struct htt_tx_done tx_done = {}; int status = __le32_to_cpu(resp->mgmt_tx_completion.status); - tx_done.msdu_id = - __le32_to_cpu(resp->mgmt_tx_completion.desc_id); + tx_done.msdu_id = __le32_to_cpu(resp->mgmt_tx_completion.desc_id); switch (status) { case HTT_MGMT_TX_STATUS_OK: - tx_done.success = true; + tx_done.status = HTT_TX_COMPL_STATE_ACK; break; case HTT_MGMT_TX_STATUS_RETRY: - tx_done.no_ack = true; + tx_done.status = HTT_TX_COMPL_STATE_NOACK; break; case HTT_MGMT_TX_STATUS_DROP: - tx_done.discard = true; + tx_done.status = HTT_TX_COMPL_STATE_DISCARD; break; } @@ -2364,9 +2374,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; } case HTT_T2H_MSG_TYPE_TX_COMPL_IND: - skb_queue_tail(&htt->tx_compl_q, skb); + ath10k_htt_rx_tx_compl_ind(htt->ar, skb); tasklet_schedule(&htt->txrx_compl_task); - return; + break; case HTT_T2H_MSG_TYPE_SEC_IND: { struct ath10k *ar = htt->ar; struct htt_security_indication *ev = &resp->security_indication; @@ -2475,7 +2485,7 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) { struct ath10k_htt *htt = (struct ath10k_htt *)ptr; struct ath10k *ar = htt->ar; - struct sk_buff_head tx_q; + struct htt_tx_done tx_done = {}; struct sk_buff_head rx_q; struct sk_buff_head rx_ind_q; struct sk_buff_head tx_ind_q; @@ -2483,15 +2493,10 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) struct sk_buff *skb; unsigned long flags; - __skb_queue_head_init(&tx_q); __skb_queue_head_init(&rx_q); __skb_queue_head_init(&rx_ind_q); __skb_queue_head_init(&tx_ind_q); - spin_lock_irqsave(&htt->tx_compl_q.lock, flags); - skb_queue_splice_init(&htt->tx_compl_q, &tx_q); - spin_unlock_irqrestore(&htt->tx_compl_q.lock, flags); - spin_lock_irqsave(&htt->rx_compl_q.lock, flags); skb_queue_splice_init(&htt->rx_compl_q, &rx_q); spin_unlock_irqrestore(&htt->rx_compl_q.lock, flags); @@ -2504,10 +2509,13 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q); spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags); - while ((skb = __skb_dequeue(&tx_q))) { - ath10k_htt_rx_frm_tx_compl(htt->ar, skb); - dev_kfree_skb_any(skb); - } + /* kfifo_get: called only within txrx_tasklet so it's neatly serialized. + * From kfifo_get() documentation: + * Note that with only one concurrent reader and one concurrent writer, + * you don't need extra locking to use these macro. + */ + while (kfifo_get(&htt->txdone_fifo, &tx_done)) + ath10k_txrx_tx_unref(htt, &tx_done); while ((skb = __skb_dequeue(&tx_ind_q))) { ath10k_htt_rx_tx_fetch_ind(ar, skb); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index b2ae122381ca..9baa2e677f8a 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -339,8 +339,18 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) goto free_frag_desc; } + size = roundup_pow_of_two(htt->max_num_pending_tx); + ret = kfifo_alloc(&htt->txdone_fifo, size, GFP_KERNEL); + if (ret) { + ath10k_err(ar, "failed to alloc txdone fifo: %d\n", ret); + goto free_txq; + } + return 0; +free_txq: + ath10k_htt_tx_free_txq(htt); + free_frag_desc: ath10k_htt_tx_free_cont_frag_desc(htt); @@ -364,8 +374,8 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx) ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", msdu_id); - tx_done.discard = 1; tx_done.msdu_id = msdu_id; + tx_done.status = HTT_TX_COMPL_STATE_DISCARD; ath10k_txrx_tx_unref(htt, &tx_done); @@ -388,6 +398,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) ath10k_htt_tx_free_txq(htt); ath10k_htt_tx_free_cont_frag_desc(htt); + WARN_ON(!kfifo_is_empty(&htt->txdone_fifo)); + kfifo_free(&htt->txdone_fifo); } void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 48e26cdfe9a5..9369411a9ac0 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -61,9 +61,8 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *msdu; ath10k_dbg(ar, ATH10K_DBG_HTT, - "htt tx completion msdu_id %u discard %d no_ack %d success %d\n", - tx_done->msdu_id, !!tx_done->discard, - !!tx_done->no_ack, !!tx_done->success); + "htt tx completion msdu_id %u status %d\n", + tx_done->msdu_id, tx_done->status); if (tx_done->msdu_id >= htt->max_num_pending_tx) { ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n", @@ -101,7 +100,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, memset(&info->status, 0, sizeof(info->status)); trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); - if (tx_done->discard) { + if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) { ieee80211_free_txskb(htt->ar->hw, msdu); return 0; } @@ -109,10 +108,11 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; - if (tx_done->no_ack) + if (tx_done->status == HTT_TX_COMPL_STATE_NOACK) info->flags &= ~IEEE80211_TX_STAT_ACK; - if (tx_done->success && (info->flags & IEEE80211_TX_CTL_NO_ACK)) + if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) && + (info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; ieee80211_tx_status(htt->ar->hw, msdu); -- GitLab From b2fdbccd15a27d1115a780dcbdcc874e0c9f4abe Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:12 +0530 Subject: [PATCH 1177/9938] ath10k: copy tx fetch indication message To optmize CPU usage htt rx descriptors will be reused instead of refilling it for htt rx copy engine (CE5). To support that all htt rx indications should be proecssed at same context. Instead of queueing actual indication message, queue copied message for txrx processing. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index ea73a233ecd7..552e8d1a3371 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2449,10 +2449,17 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) } case HTT_T2H_MSG_TYPE_AGGR_CONF: break; - case HTT_T2H_MSG_TYPE_TX_FETCH_IND: - skb_queue_tail(&htt->tx_fetch_ind_q, skb); + case HTT_T2H_MSG_TYPE_TX_FETCH_IND: { + struct sk_buff *tx_fetch_ind = skb_copy(skb, GFP_ATOMIC); + + if (!tx_fetch_ind) { + ath10k_warn(ar, "failed to copy htt tx fetch ind\n"); + break; + } + skb_queue_tail(&htt->tx_fetch_ind_q, tx_fetch_ind); tasklet_schedule(&htt->txrx_compl_task); - return; + break; + } case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: ath10k_htt_rx_tx_fetch_confirm(ar, skb); break; -- GitLab From 6b61d6632a358bc72e14de03ba491907d871c94e Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:13 +0530 Subject: [PATCH 1178/9938] ath10k: remove unused fw_desc processing The fw descriptor was never used and probably never will be. It makes little sense to maintain support for it. Remove it and simplify rx processing. This will make it easier to optimize rx processing later as well. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 65 +----------------------- 1 file changed, 2 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 552e8d1a3371..6a2cbd1a34d3 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -281,7 +281,6 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) /* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, - u8 **fw_desc, int *fw_desc_len, struct sk_buff_head *amsdu) { struct ath10k *ar = htt->ar; @@ -323,48 +322,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, return -EIO; } - /* - * Copy the FW rx descriptor for this MSDU from the rx - * indication message into the MSDU's netbuf. HL uses the - * same rx indication message definition as LL, and simply - * appends new info (fields from the HW rx desc, and the - * MSDU payload itself). So, the offset into the rx - * indication message only has to account for the standard - * offset of the per-MSDU FW rx desc info within the - * message, and how many bytes of the per-MSDU FW rx desc - * info have already been consumed. (And the endianness of - * the host, since for a big-endian host, the rx ind - * message contents, including the per-MSDU rx desc bytes, - * were byteswapped during upload.) - */ - if (*fw_desc_len > 0) { - rx_desc->fw_desc.info0 = **fw_desc; - /* - * The target is expected to only provide the basic - * per-MSDU rx descriptors. Just to be sure, verify - * that the target has not attached extension data - * (e.g. LRO flow ID). - */ - - /* or more, if there's extension data */ - (*fw_desc)++; - (*fw_desc_len)--; - } else { - /* - * When an oversized AMSDU happened, FW will lost - * some of MSDU status - in this case, the FW - * descriptors provided will be less than the - * actual MSDUs inside this MPDU. Mark the FW - * descriptors so that it will still deliver to - * upper stack, if no CRC error for this MPDU. - * - * FIX THIS - the FW descriptors are actually for - * MSDUs in the end of this A-MSDU instead of the - * beginning. - */ - rx_desc->fw_desc.info0 = 0; - } - msdu_len_invalid = !!(__le32_to_cpu(rx_desc->attention.flags) & (RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR | RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR)); @@ -1579,8 +1536,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, struct htt_rx_indication_mpdu_range *mpdu_ranges; struct sk_buff_head amsdu; int num_mpdu_ranges; - int fw_desc_len; - u8 *fw_desc; int i, ret, mpdu_count = 0; lockdep_assert_held(&htt->rx_ring.lock); @@ -1588,9 +1543,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, if (htt->rx_confused) return; - fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes); - fw_desc = (u8 *)&rx->fw_desc; - num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1), HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES); mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx); @@ -1605,8 +1557,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, while (mpdu_count--) { __skb_queue_head_init(&amsdu); - ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, - &fw_desc_len, &amsdu); + ret = ath10k_htt_rx_amsdu_pop(htt, &amsdu); if (ret < 0) { ath10k_warn(ar, "rx ring became corrupted: %d\n", ret); __skb_queue_purge(&amsdu); @@ -1634,17 +1585,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, struct ieee80211_rx_status *rx_status = &htt->rx_status; struct sk_buff_head amsdu; int ret; - u8 *fw_desc; - int fw_desc_len; - - fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes); - fw_desc = (u8 *)frag->fw_msdu_rx_desc; __skb_queue_head_init(&amsdu); spin_lock_bh(&htt->rx_ring.lock); - ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len, - &amsdu); + ret = ath10k_htt_rx_amsdu_pop(htt, &amsdu); spin_unlock_bh(&htt->rx_ring.lock); tasklet_schedule(&htt->rx_replenish_task); @@ -1668,12 +1613,6 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); - - if (fw_desc_len > 0) { - ath10k_dbg(ar, ATH10K_DBG_HTT, - "expecting more fragmented rx in one indication %d\n", - fw_desc_len); - } } static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, -- GitLab From 18235664e7f9a5664cbef25d23b222ff2faf55bc Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:14 +0530 Subject: [PATCH 1179/9938] ath10k: cleanup amsdu processing for rx indication Make amsdu handlers (i.e amsdu_pop and rx_h_handler) common to both rx_ind and frag_ind htt events. It is sufficient to hold rx_ring lock for amsdu_pop alone and no need to hold it until the packets are delivered to mac80211. This helps to reduce rx_lock contention as well. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 100 ++++++++++------------- 1 file changed, 41 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 6a2cbd1a34d3..cf44e18313f6 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1528,20 +1528,49 @@ static void ath10k_htt_rx_h_filter(struct ath10k *ar, __skb_queue_purge(amsdu); } +static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) +{ + struct ath10k *ar = htt->ar; + static struct ieee80211_rx_status rx_status; + struct sk_buff_head amsdu; + int ret; + + __skb_queue_head_init(&amsdu); + + spin_lock_bh(&htt->rx_ring.lock); + if (htt->rx_confused) { + spin_unlock_bh(&htt->rx_ring.lock); + return -EIO; + } + ret = ath10k_htt_rx_amsdu_pop(htt, &amsdu); + spin_unlock_bh(&htt->rx_ring.lock); + + if (ret < 0) { + ath10k_warn(ar, "rx ring became corrupted: %d\n", ret); + __skb_queue_purge(&amsdu); + /* FIXME: It's probably a good idea to reboot the + * device instead of leaving it inoperable. + */ + htt->rx_confused = true; + return ret; + } + + ath10k_htt_rx_h_ppdu(ar, &amsdu, &rx_status, 0xffff); + ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0); + ath10k_htt_rx_h_filter(ar, &amsdu, &rx_status); + ath10k_htt_rx_h_mpdu(ar, &amsdu, &rx_status); + ath10k_htt_rx_h_deliver(ar, &amsdu, &rx_status); + + return 0; +} + static void ath10k_htt_rx_handler(struct ath10k_htt *htt, struct htt_rx_indication *rx) { struct ath10k *ar = htt->ar; - struct ieee80211_rx_status *rx_status = &htt->rx_status; struct htt_rx_indication_mpdu_range *mpdu_ranges; - struct sk_buff_head amsdu; int num_mpdu_ranges; - int i, ret, mpdu_count = 0; - - lockdep_assert_held(&htt->rx_ring.lock); - - if (htt->rx_confused) - return; + int i, mpdu_count = 0; num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1), HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES); @@ -1556,63 +1585,18 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, mpdu_count += mpdu_ranges[i].mpdu_count; while (mpdu_count--) { - __skb_queue_head_init(&amsdu); - ret = ath10k_htt_rx_amsdu_pop(htt, &amsdu); - if (ret < 0) { - ath10k_warn(ar, "rx ring became corrupted: %d\n", ret); - __skb_queue_purge(&amsdu); - /* FIXME: It's probably a good idea to reboot the - * device instead of leaving it inoperable. - */ - htt->rx_confused = true; + if (ath10k_htt_rx_handle_amsdu(htt) < 0) break; - } - - ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); - ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0); - ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); - ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); } tasklet_schedule(&htt->rx_replenish_task); } -static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, - struct htt_rx_fragment_indication *frag) +static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt) { - struct ath10k *ar = htt->ar; - struct ieee80211_rx_status *rx_status = &htt->rx_status; - struct sk_buff_head amsdu; - int ret; - - __skb_queue_head_init(&amsdu); - - spin_lock_bh(&htt->rx_ring.lock); - ret = ath10k_htt_rx_amsdu_pop(htt, &amsdu); - spin_unlock_bh(&htt->rx_ring.lock); + ath10k_htt_rx_handle_amsdu(htt); tasklet_schedule(&htt->rx_replenish_task); - - ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); - - if (ret) { - ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n", - ret); - __skb_queue_purge(&amsdu); - return; - } - - if (skb_queue_len(&amsdu) != 1) { - ath10k_warn(ar, "failed to pop frag amsdu: too many msdus\n"); - __skb_queue_purge(&amsdu); - return; - } - - ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); - ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); - ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); } static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, @@ -2331,7 +2315,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) case HTT_T2H_MSG_TYPE_RX_FRAG_IND: { ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", skb->data, skb->len); - ath10k_htt_rx_frag_handler(htt, &resp->rx_frag_ind); + ath10k_htt_rx_frag_handler(htt); break; } case HTT_T2H_MSG_TYPE_TEST: @@ -2472,9 +2456,7 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) while ((skb = __skb_dequeue(&rx_q))) { resp = (struct htt_resp *)skb->data; - spin_lock_bh(&htt->rx_ring.lock); ath10k_htt_rx_handler(htt, &resp->rx_ind); - spin_unlock_bh(&htt->rx_ring.lock); dev_kfree_skb_any(skb); } -- GitLab From 3128b3d8a2b97ba8fe38b21c3ed70c2c66cc7a9e Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:15 +0530 Subject: [PATCH 1180/9938] ath10k: speedup htt rx descriptor processing for rx_ind In follow up patch, htt rx descriptors will be reused instead of dealloc and refill. To achieve that htt rx indication messages should not be deferred and should be processed in pci tasklet itself. Also from rx indication message, mpdu_count alone is used. So it is maintained as atomic variable and all rx amsdu handlers are done processed from txrx tasklet. This change get rid of rx_compl_q usage. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 1 + drivers/net/wireless/ath/ath10k/htt_rx.c | 39 +++++++++++------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 76c4bae0b434..27a65ecba7b0 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1663,6 +1663,7 @@ struct ath10k_htt { * used to avoid further failures */ bool rx_confused; struct tasklet_struct rx_replenish_task; + atomic_t num_mpdus_ready; /* This is used to group tx/rx completions separately and process them * in batches to reduce cache stalls */ diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index cf44e18313f6..6c616a36c4c4 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -526,6 +526,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) skb_queue_head_init(&htt->rx_compl_q); skb_queue_head_init(&htt->rx_in_ord_compl_q); skb_queue_head_init(&htt->tx_fetch_ind_q); + atomic_set(&htt->num_mpdus_ready, 0); tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task, (unsigned long)htt); @@ -1564,8 +1565,8 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) return 0; } -static void ath10k_htt_rx_handler(struct ath10k_htt *htt, - struct htt_rx_indication *rx) +static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt, + struct htt_rx_indication *rx) { struct ath10k *ar = htt->ar; struct htt_rx_indication_mpdu_range *mpdu_ranges; @@ -1584,19 +1585,16 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, for (i = 0; i < num_mpdu_ranges; i++) mpdu_count += mpdu_ranges[i].mpdu_count; - while (mpdu_count--) { - if (ath10k_htt_rx_handle_amsdu(htt) < 0) - break; - } + atomic_add(mpdu_count, &htt->num_mpdus_ready); - tasklet_schedule(&htt->rx_replenish_task); + tasklet_schedule(&htt->txrx_compl_task); } static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt) { - ath10k_htt_rx_handle_amsdu(htt); + atomic_inc(&htt->num_mpdus_ready); - tasklet_schedule(&htt->rx_replenish_task); + tasklet_schedule(&htt->txrx_compl_task); } static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, @@ -2250,9 +2248,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; } case HTT_T2H_MSG_TYPE_RX_IND: - skb_queue_tail(&htt->rx_compl_q, skb); - tasklet_schedule(&htt->txrx_compl_task); - return; + ath10k_htt_rx_proc_rx_ind(htt, &resp->rx_ind); + break; case HTT_T2H_MSG_TYPE_PEER_MAP: { struct htt_peer_map_event ev = { .vdev_id = resp->peer_map.vdev_id, @@ -2419,18 +2416,14 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) struct sk_buff_head rx_q; struct sk_buff_head rx_ind_q; struct sk_buff_head tx_ind_q; - struct htt_resp *resp; struct sk_buff *skb; unsigned long flags; + int num_mpdus; __skb_queue_head_init(&rx_q); __skb_queue_head_init(&rx_ind_q); __skb_queue_head_init(&tx_ind_q); - spin_lock_irqsave(&htt->rx_compl_q.lock, flags); - skb_queue_splice_init(&htt->rx_compl_q, &rx_q); - spin_unlock_irqrestore(&htt->rx_compl_q.lock, flags); - spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags); skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q); spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags); @@ -2454,10 +2447,12 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) ath10k_mac_tx_push_pending(ar); - while ((skb = __skb_dequeue(&rx_q))) { - resp = (struct htt_resp *)skb->data; - ath10k_htt_rx_handler(htt, &resp->rx_ind); - dev_kfree_skb_any(skb); + num_mpdus = atomic_read(&htt->num_mpdus_ready); + atomic_sub(num_mpdus, &htt->num_mpdus_ready); + + while (num_mpdus--) { + if (ath10k_htt_rx_handle_amsdu(htt)) + break; } while ((skb = __skb_dequeue(&rx_ind_q))) { @@ -2466,4 +2461,6 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) spin_unlock_bh(&htt->rx_ring.lock); dev_kfree_skb_any(skb); } + + tasklet_schedule(&htt->rx_replenish_task); } -- GitLab From e3a91f877c60ce8b29d8cd180c23f3de33a7d7e1 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:16 +0530 Subject: [PATCH 1181/9938] ath10k: register ath10k_htt_htc_t2h_msg_handler Except qca61x4 family chips (qca6164, qca6174), copy engine 5 is used for receiving target to host htt messages. In follow up patch, CE5 descriptors will be reused. In such case, same API can not be used as htc layer callback where the response messages will be freed at the end. Hence register new API for HTC layer that free up received message and keep the message handler common for both HTC and HIF layers. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.c | 2 +- drivers/net/wireless/ath/ath10k/htt.h | 3 ++- drivers/net/wireless/ath/ath10k/htt_rx.c | 22 +++++++++++++++------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 7561f22f10f9..17a3008d9ab1 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -149,7 +149,7 @@ int ath10k_htt_connect(struct ath10k_htt *htt) memset(&conn_resp, 0, sizeof(conn_resp)); conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete; - conn_req.ep_ops.ep_rx_complete = ath10k_htt_t2h_msg_handler; + conn_req.ep_ops.ep_rx_complete = ath10k_htt_htc_t2h_msg_handler; /* connect to control service */ conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG; diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 27a65ecba7b0..1adcae4faccf 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1765,7 +1765,8 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar); void ath10k_htt_rx_free(struct ath10k_htt *htt); void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); -void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); +void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); +bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie); int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt); diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 6c616a36c4c4..ac16ce746afb 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2219,7 +2219,18 @@ static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) return band; } -void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) +void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) +{ + bool release; + + release = ath10k_htt_t2h_msg_handler(ar, skb); + + /* Free the indication buffer */ + if (release) + dev_kfree_skb_any(skb); +} + +bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; struct htt_resp *resp = (struct htt_resp *)skb->data; @@ -2235,8 +2246,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) if (resp->hdr.msg_type >= ar->htt.t2h_msg_types_max) { ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx, unsupported msg_type: 0x%0X\n max: 0x%0X", resp->hdr.msg_type, ar->htt.t2h_msg_types_max); - dev_kfree_skb_any(skb); - return; + return true; } type = ar->htt.t2h_msg_types[resp->hdr.msg_type]; @@ -2352,7 +2362,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: { skb_queue_tail(&htt->rx_in_ord_compl_q, skb); tasklet_schedule(&htt->txrx_compl_task); - return; + return false; } case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: break; @@ -2394,9 +2404,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) skb->data, skb->len); break; }; - - /* Free the indication buffer */ - dev_kfree_skb_any(skb); + return true; } EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler); -- GitLab From 24d9ef5eff5057bb6339ed1cf852a2b2a7be324d Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:17 +0530 Subject: [PATCH 1182/9938] ath10k: cleanup copy engine receive next completion The physical address necessary to unmap DMA ('bufferp') is stored in ath10k_skb_cb as 'paddr'. For diag register read and write operations, 'paddr' is stored in transfer context. ath10k doesn't rely on the meta/transfer_id. So the unused output arguments {bufferp, nbytesp and transfer_idp} are removed from CE recv_next completion. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 21 ++----------- drivers/net/wireless/ath/ath10k/ce.h | 10 ++----- drivers/net/wireless/ath/ath10k/pci.c | 43 +++++++++++---------------- 3 files changed, 22 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index edf3629288bc..d6da404c9fa7 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -444,14 +444,10 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) */ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp, - unsigned int *flagsp) + unsigned int *nbytesp) { struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; - struct ath10k *ar = ce_state->ar; unsigned int sw_index = dest_ring->sw_index; struct ce_desc *base = dest_ring->base_addr_owner_space; @@ -476,14 +472,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, desc->nbytes = 0; /* Return data from completed destination descriptor */ - *bufferp = __le32_to_cpu(sdesc.addr); *nbytesp = nbytes; - *transfer_idp = MS(__le16_to_cpu(sdesc.flags), CE_DESC_FLAGS_META_DATA); - - if (__le16_to_cpu(sdesc.flags) & CE_DESC_FLAGS_BYTE_SWAP) - *flagsp = CE_RECV_FLAG_SWAPPED; - else - *flagsp = 0; if (per_transfer_contextp) *per_transfer_contextp = @@ -501,10 +490,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp, - unsigned int *flagsp) + unsigned int *nbytesp) { struct ath10k *ar = ce_state->ar; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -513,8 +499,7 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, spin_lock_bh(&ar_pci->ce_lock); ret = ath10k_ce_completed_recv_next_nolock(ce_state, per_transfer_contextp, - bufferp, nbytesp, - transfer_idp, flagsp); + nbytesp); spin_unlock_bh(&ar_pci->ce_lock); return ret; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index dac676817532..68717e5b9d89 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -177,10 +177,7 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr); */ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp, - unsigned int *flagsp); + unsigned int *nbytesp); /* * Supply data for the next completed unprocessed send descriptor. * Pops 1 completed send buffer from Source ring. @@ -212,10 +209,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp, - unsigned int *flagsp); + unsigned int *nbytesp); /* * Support clean shutdown by allowing the caller to cancel diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index b3cff1d3364a..290a61afde1a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -870,10 +870,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret = 0; - u32 buf; + u32 *buf; unsigned int completed_nbytes, orig_nbytes, remaining_bytes; - unsigned int id; - unsigned int flags; struct ath10k_ce_pipe *ce_diag; /* Host buffer address in CE space */ u32 ce_data; @@ -909,7 +907,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, nbytes = min_t(unsigned int, remaining_bytes, DIAG_TRANSFER_LIMIT); - ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); + ret = __ath10k_ce_rx_post_buf(ce_diag, &ce_data, ce_data); if (ret != 0) goto done; @@ -940,9 +938,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, } i = 0; - while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, - &completed_nbytes, - &id, &flags) != 0) { + while (ath10k_ce_completed_recv_next_nolock(ce_diag, + (void **)&buf, + &completed_nbytes) + != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -956,7 +955,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, goto done; } - if (buf != ce_data) { + if (*buf != ce_data) { ret = -EIO; goto done; } @@ -1026,10 +1025,8 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret = 0; - u32 buf; + u32 *buf; unsigned int completed_nbytes, orig_nbytes, remaining_bytes; - unsigned int id; - unsigned int flags; struct ath10k_ce_pipe *ce_diag; void *data_buf = NULL; u32 ce_data; /* Host buffer address in CE space */ @@ -1078,7 +1075,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); /* Set up to receive directly into Target(!) address */ - ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address); + ret = __ath10k_ce_rx_post_buf(ce_diag, &address, address); if (ret != 0) goto done; @@ -1103,9 +1100,10 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, } i = 0; - while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, - &completed_nbytes, - &id, &flags) != 0) { + while (ath10k_ce_completed_recv_next_nolock(ce_diag, + (void **)&buf, + &completed_nbytes) + != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -1119,7 +1117,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, goto done; } - if (buf != address) { + if (*buf != address) { ret = -EIO; goto done; } @@ -1181,15 +1179,11 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state, struct sk_buff *skb; struct sk_buff_head list; void *transfer_context; - u32 ce_data; unsigned int nbytes, max_nbytes; - unsigned int transfer_id; - unsigned int flags; __skb_queue_head_init(&list); while (ath10k_ce_completed_recv_next(ce_state, &transfer_context, - &ce_data, &nbytes, &transfer_id, - &flags) == 0) { + &nbytes) == 0) { skb = transfer_context; max_nbytes = skb->len + skb_tailroom(skb); dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr, @@ -1835,13 +1829,10 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) { struct ath10k *ar = ce_state->ar; struct bmi_xfer *xfer; - u32 ce_data; unsigned int nbytes; - unsigned int transfer_id; - unsigned int flags; - if (ath10k_ce_completed_recv_next(ce_state, (void **)&xfer, &ce_data, - &nbytes, &transfer_id, &flags)) + if (ath10k_ce_completed_recv_next(ce_state, (void **)&xfer, + &nbytes)) return; if (WARN_ON_ONCE(!xfer)) -- GitLab From 128abd09134a5b415fef4373841ea6d3fb7b680f Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:18 +0530 Subject: [PATCH 1183/9938] ath10k: reuse copy engine 5 (htt rx) descriptors Whenever htt rx indication i.e target to host messages are received on rx copy engine (CE5), the message will be freed after processing the response. Then CE 5 will be refilled with new descriptors at post rx processing. This memory alloc and free operations can be avoided by reusing the same descriptors. During CE pipe allocation, full ring is not initialized i.e n-1 entries are filled up. So for CE 5 full ring should be filled up to reuse descriptors. Moreover CE 5 write index will be updated in single shot instead of incremental access. This could avoid multiple pci_write and ce_ring access. From experiments, It improves CPU usage by ~3% in IPQ4019 platform. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 23 ++++++++-- drivers/net/wireless/ath/ath10k/ce.h | 3 ++ drivers/net/wireless/ath/ath10k/pci.c | 63 ++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index d6da404c9fa7..7212802eb327 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -411,7 +411,8 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) lockdep_assert_held(&ar_pci->ce_lock); - if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) + if ((pipe->id != 5) && + CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) return -ENOSPC; desc->addr = __cpu_to_le32(paddr); @@ -425,6 +426,19 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) return 0; } +void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries) +{ + struct ath10k *ar = pipe->ar; + struct ath10k_ce_ring *dest_ring = pipe->dest_ring; + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int write_index = dest_ring->write_index; + u32 ctrl_addr = pipe->ctrl_addr; + + write_index = CE_RING_IDX_ADD(nentries_mask, write_index, nentries); + ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index); + dest_ring->write_index = write_index; +} + int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) { struct ath10k *ar = pipe->ar; @@ -478,8 +492,11 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, *per_transfer_contextp = dest_ring->per_transfer_context[sw_index]; - /* sanity */ - dest_ring->per_transfer_context[sw_index] = NULL; + /* Copy engine 5 (HTT Rx) will reuse the same transfer context. + * So update transfer context all CEs except CE5. + */ + if (ce_state->id != 5) + dest_ring->per_transfer_context[sw_index] = NULL; /* Update sw_index */ sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 68717e5b9d89..25cafcfd6b12 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -166,6 +166,7 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe); int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe); int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr); int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr); +void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries); /* recv flags */ /* Data is byte-swapped */ @@ -410,6 +411,8 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) (((int)(toidx)-(int)(fromidx)) & (nentries_mask)) #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) +#define CE_RING_IDX_ADD(nentries_mask, idx, num) \ + (((idx) + (num)) & (nentries_mask)) #define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \ ar->regs->ce_wrap_intr_sum_host_msi_lsb diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 290a61afde1a..0b305efe6c94 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -809,7 +809,8 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) spin_lock_bh(&ar_pci->ce_lock); num = __ath10k_ce_rx_num_free_bufs(ce_pipe); spin_unlock_bh(&ar_pci->ce_lock); - while (num--) { + + while (num >= 0) { ret = __ath10k_pci_rx_post_buf(pipe); if (ret) { if (ret == -ENOSPC) @@ -819,6 +820,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) ATH10K_PCI_RX_POST_RETRY_MS); break; } + num--; } } @@ -1212,6 +1214,63 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state, ath10k_pci_rx_post_pipe(pipe_info); } +static void ath10k_pci_process_htt_rx_cb(struct ath10k_ce_pipe *ce_state, + void (*callback)(struct ath10k *ar, + struct sk_buff *skb)) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; + struct ath10k_ce_pipe *ce_pipe = pipe_info->ce_hdl; + struct sk_buff *skb; + struct sk_buff_head list; + void *transfer_context; + unsigned int nbytes, max_nbytes, nentries; + int orig_len; + + /* No need to aquire ce_lock for CE5, since this is the only place CE5 + * is processed other than init and deinit. Before releasing CE5 + * buffers, interrupts are disabled. Thus CE5 access is serialized. + */ + __skb_queue_head_init(&list); + while (ath10k_ce_completed_recv_next_nolock(ce_state, &transfer_context, + &nbytes) == 0) { + skb = transfer_context; + max_nbytes = skb->len + skb_tailroom(skb); + + if (unlikely(max_nbytes < nbytes)) { + ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)", + nbytes, max_nbytes); + continue; + } + + dma_sync_single_for_cpu(ar->dev, ATH10K_SKB_RXCB(skb)->paddr, + max_nbytes, DMA_FROM_DEVICE); + skb_put(skb, nbytes); + __skb_queue_tail(&list, skb); + } + + nentries = skb_queue_len(&list); + while ((skb = __skb_dequeue(&list))) { + ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n", + ce_state->id, skb->len); + ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", + skb->data, skb->len); + + orig_len = skb->len; + callback(ar, skb); + skb_push(skb, orig_len - skb->len); + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + /*let device gain the buffer again*/ + dma_sync_single_for_device(ar->dev, ATH10K_SKB_RXCB(skb)->paddr, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); + } + ath10k_ce_rx_update_write_idx(ce_pipe, nentries); +} + /* Called by lower (CE) layer when data is received from the Target. */ static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state) { @@ -1268,7 +1327,7 @@ static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state) */ ath10k_ce_per_engine_service(ce_state->ar, 4); - ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); + ath10k_pci_process_htt_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); } int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, -- GitLab From 5c86d97bcc1d42ce7f75685a61be4dad34ee8183 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 22 Mar 2016 17:22:19 +0530 Subject: [PATCH 1184/9938] ath10k: combine txrx and replenish task Since tx completion and rx indication processing are moved out of txrx tasklet and rx ring lock contention also removed from txrx for rx_ind messages, it would be efficient to combine both replenish and txrx tasks. Refill threshold is adjusted for both AP135 and AP148 (low and high end systems). With this adjustment in AP135, TCP DL is improved from 603 Mbps to 620 Mbps and UDP DL is improved from 758 Mbps to 803 Mbps. Also no watchdog are observed on UDP BiDi. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 3 +-- drivers/net/wireless/ath/ath10k/htt_rx.c | 21 ++++++--------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 1adcae4faccf..60bd9fe4b2d9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1662,7 +1662,6 @@ struct ath10k_htt { /* set if host-fw communication goes haywire * used to avoid further failures */ bool rx_confused; - struct tasklet_struct rx_replenish_task; atomic_t num_mpdus_ready; /* This is used to group tx/rx completions separately and process them @@ -1737,7 +1736,7 @@ struct htt_rx_desc { /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle * aggregated traffic more nicely. */ -#define ATH10K_HTT_MAX_NUM_REFILL 16 +#define ATH10K_HTT_MAX_NUM_REFILL 100 /* * DMA_MAP expects the buffer to be an integral number of cache lines. diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index ac16ce746afb..592421ec5635 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -31,6 +31,8 @@ /* when under memory pressure rx ring refill may fail and needs a retry */ #define HTT_RX_RING_REFILL_RETRY_MS 50 +#define HTT_RX_RING_REFILL_RESCHED_MS 5 + static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); static void ath10k_htt_txrx_compl_task(unsigned long ptr); @@ -192,7 +194,8 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt) mod_timer(&htt->rx_ring.refill_retry_timer, jiffies + msecs_to_jiffies(HTT_RX_RING_REFILL_RETRY_MS)); } else if (num_deficit > 0) { - tasklet_schedule(&htt->rx_replenish_task); + mod_timer(&htt->rx_ring.refill_retry_timer, jiffies + + msecs_to_jiffies(HTT_RX_RING_REFILL_RESCHED_MS)); } spin_unlock_bh(&htt->rx_ring.lock); } @@ -223,7 +226,6 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar) void ath10k_htt_rx_free(struct ath10k_htt *htt) { del_timer_sync(&htt->rx_ring.refill_retry_timer); - tasklet_kill(&htt->rx_replenish_task); tasklet_kill(&htt->txrx_compl_task); skb_queue_purge(&htt->rx_compl_q); @@ -380,13 +382,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, return msdu_chaining; } -static void ath10k_htt_rx_replenish_task(unsigned long ptr) -{ - struct ath10k_htt *htt = (struct ath10k_htt *)ptr; - - ath10k_htt_rx_msdu_buff_replenish(htt); -} - static struct sk_buff *ath10k_htt_rx_pop_paddr(struct ath10k_htt *htt, u32 paddr) { @@ -520,9 +515,6 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) htt->rx_ring.sw_rd_idx.msdu_payld = 0; hash_init(htt->rx_ring.skb_table); - tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task, - (unsigned long)htt); - skb_queue_head_init(&htt->rx_compl_q); skb_queue_head_init(&htt->rx_in_ord_compl_q); skb_queue_head_init(&htt->tx_fetch_ind_q); @@ -1912,8 +1904,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) return; } } - - tasklet_schedule(&htt->rx_replenish_task); + ath10k_htt_rx_msdu_buff_replenish(htt); } static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, @@ -2470,5 +2461,5 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) dev_kfree_skb_any(skb); } - tasklet_schedule(&htt->rx_replenish_task); + ath10k_htt_rx_msdu_buff_replenish(htt); } -- GitLab From 7d5efd0888331a0f7ed2e1d5a6977a32b7e9bfb7 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Tue, 22 Mar 2016 15:44:53 -0700 Subject: [PATCH 1185/9938] ath10k: parse Rx MAC timestamp in mgmt frame for FW 10.4 Check and parse Rx MAC timestamp when firmware sets its flag to status variable. 10.4 firmware adds it in Rx beacon frame only at this moment. Drivers and mac80211 may utilize it to detect such clockdrift or beacon collision and use the result for beacon collision avoidance. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ac8622718f58..f7ec65f263a0 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2192,6 +2192,8 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar, struct wmi_10_4_mgmt_rx_hdr *ev_hdr; size_t pull_len; u32 msdu_len; + struct wmi_mgmt_rx_ext_info *ext_info; + u32 len; ev = (struct wmi_10_4_mgmt_rx_event *)skb->data; ev_hdr = &ev->hdr; @@ -2212,6 +2214,13 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar, if (skb->len < msdu_len) return -EPROTO; + if (le32_to_cpu(arg->status) & WMI_RX_STATUS_EXT_INFO) { + len = ALIGN(le32_to_cpu(arg->buf_len), 4); + ext_info = (struct wmi_mgmt_rx_ext_info *)(skb->data + len); + memcpy(&arg->ext_info, ext_info, + sizeof(struct wmi_mgmt_rx_ext_info)); + } + /* Make sure bytes added for padding are removed. */ skb_trim(skb, msdu_len); -- GitLab From 7b9bc799a445aea95f64f15e0083cb19b5789abe Mon Sep 17 00:00:00 2001 From: Joseph Salisbury Date: Mon, 14 Mar 2016 14:51:48 -0400 Subject: [PATCH 1186/9938] ath5k: Change led pin configuration for compaq c700 laptop BugLink: http://bugs.launchpad.net/bugs/972604 Commit 09c9bae26b0d3c9472cb6ae45010460a2cee8b8d ("ath5k: add led pin configuration for compaq c700 laptop") added a pin configuration for the Compaq c700 laptop. However, the polarity of the led pin is reversed. It should be red for wifi off and blue for wifi on, but it is the opposite. This bug was reported in the following bug report: http://pad.lv/972604 Fixes: 09c9bae26b0d3c9472cb6ae45010460a2cee8b8d ("ath5k: add led pin configuration for compaq c700 laptop") Signed-off-by: Joseph Salisbury Cc: stable@vger.kernel.org Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath5k/led.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 803030fd17d3..6a2a16856763 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -77,7 +77,7 @@ static const struct pci_device_id ath5k_led_devices[] = { /* HP Compaq CQ60-206US (ddreggors@jumptv.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, /* HP Compaq C700 (nitrousnrg@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, + { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 0) }, /* LiteOn AR5BXB63 (magooz@salug.it) */ { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) }, /* IBM-specific AR5212 (all others) */ -- GitLab From 44fde3b89ba1e154b3cec7d711703fff53852983 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Mon, 4 Apr 2016 19:23:54 +0530 Subject: [PATCH 1187/9938] ALSA: hda - Update chmap tlv to report sink's capability The existing TLV callback implementation copies all of the cea_channel_speaker_allocation map table to the TLV container irrespective of what is reported by sink. This is of little use to the userspace application. With this patch, it parses the spk_alloc block as queried from the ELD, and copies only the corresponding mapping channel allocation entries from the cea channel speaker allocation table. Thus the user can parse the TLV container to identify sink's capability and set the channel map accordingly. It shouldn't impact the behavior in AMD chipset, as this makes use of already parsed spk alloc block to calculate the channel map. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai --- include/sound/hda_chmap.h | 2 ++ sound/hda/hdmi_chmap.c | 44 ++++++++++++++++++++++++++++++++++---- sound/pci/hda/patch_hdmi.c | 13 +++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/include/sound/hda_chmap.h b/include/sound/hda_chmap.h index e20d219a0304..babd445c7505 100644 --- a/include/sound/hda_chmap.h +++ b/include/sound/hda_chmap.h @@ -36,6 +36,8 @@ struct hdac_chmap_ops { int (*chmap_validate)(struct hdac_chmap *hchmap, int ca, int channels, unsigned char *chmap); + int (*get_spk_alloc)(struct hdac_device *hdac, int pcm_idx); + void (*get_chmap)(struct hdac_device *hdac, int pcm_idx, unsigned char *chmap); void (*set_chmap)(struct hdac_device *hdac, int pcm_idx, diff --git a/sound/hda/hdmi_chmap.c b/sound/hda/hdmi_chmap.c index d7ec86263828..c6c75e7e0981 100644 --- a/sound/hda/hdmi_chmap.c +++ b/sound/hda/hdmi_chmap.c @@ -625,13 +625,30 @@ static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap, WARN_ON(count != channels); } +static int spk_mask_from_spk_alloc(int spk_alloc) +{ + int i; + int spk_mask = eld_speaker_allocation_bits[0]; + + for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { + if (spk_alloc & (1 << i)) + spk_mask |= eld_speaker_allocation_bits[i]; + } + + return spk_mask; +} + static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv) { struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); struct hdac_chmap *chmap = info->private_data; + int pcm_idx = kcontrol->private_value; unsigned int __user *dst; int chs, count = 0; + unsigned long max_chs; + int type; + int spk_alloc, spk_mask; if (size < 8) return -ENOMEM; @@ -639,40 +656,59 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, return -EFAULT; size -= 8; dst = tlv + 2; - for (chs = 2; chs <= chmap->channels_max; chs++) { + + spk_alloc = chmap->ops.get_spk_alloc(chmap->hdac, pcm_idx); + spk_mask = spk_mask_from_spk_alloc(spk_alloc); + + max_chs = hweight_long(spk_mask); + + for (chs = 2; chs <= max_chs; chs++) { int i; struct hdac_cea_channel_speaker_allocation *cap; cap = channel_allocations; for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { int chs_bytes = chs * 4; - int type = chmap->ops.chmap_cea_alloc_validate_get_type( - chmap, cap, chs); unsigned int tlv_chmap[8]; - if (type < 0) + if (cap->channels != chs) + continue; + + if (!(cap->spk_mask == (spk_mask & cap->spk_mask))) continue; + + type = chmap->ops.chmap_cea_alloc_validate_get_type( + chmap, cap, chs); + if (type < 0) + return -ENODEV; if (size < 8) return -ENOMEM; + if (put_user(type, dst) || put_user(chs_bytes, dst + 1)) return -EFAULT; + dst += 2; size -= 8; count += 8; + if (size < chs_bytes) return -ENOMEM; + size -= chs_bytes; count += chs_bytes; chmap->ops.cea_alloc_to_tlv_chmap(chmap, cap, tlv_chmap, chs); + if (copy_to_user(dst, tlv_chmap, chs_bytes)) return -EFAULT; dst += chs; } } + if (put_user(count, tlv + 1)) return -EFAULT; + return 0; } diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 4833c7bdd1e8..9452384d2000 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1837,6 +1837,18 @@ static const struct hda_pcm_ops generic_ops = { .cleanup = generic_hdmi_playback_pcm_cleanup, }; +static int hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) +{ + struct hda_codec *codec = container_of(hdac, struct hda_codec, core); + struct hdmi_spec *spec = codec->spec; + struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); + + if (!per_pin) + return 0; + + return per_pin->sink_eld.info.spk_alloc; +} + static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx, unsigned char *chmap) { @@ -2165,6 +2177,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec) spec->chmap.ops.get_chmap = hdmi_get_chmap; spec->chmap.ops.set_chmap = hdmi_set_chmap; spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached; + spec->chmap.ops.get_spk_alloc = hdmi_get_spk_alloc, codec->spec = spec; hdmi_array_init(spec, 4); -- GitLab From 69218a48005d0c93b8e9ec483f42ead481a43034 Mon Sep 17 00:00:00 2001 From: Lior David Date: Mon, 21 Mar 2016 22:01:11 +0200 Subject: [PATCH 1188/9938] wil6210: allow empty WMI commands in debugfs wmi_send There are many valid WMI commands with only header without any additional payload. Such WMI commands could not be sent using the debugfs wmi_send facility. Fix the code to allow sending of such commands. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index a4d3f70c3d29..b338a09175ad 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -832,7 +832,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, u16 cmdid; int rc, rc1; - if (cmdlen <= 0) + if (cmdlen < 0) return -EINVAL; wmi = kmalloc(len, GFP_KERNEL); @@ -845,7 +845,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, return rc; } - cmd = &wmi[1]; + cmd = (cmdlen > 0) ? &wmi[1] : NULL; cmdid = le16_to_cpu(wmi->command_id); rc1 = wmi_send(wil, cmdid, cmd, cmdlen); -- GitLab From a2cb3d5f043e4cc646c396a3e188a171b38c15a0 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Fri, 18 Mar 2016 17:54:56 +0800 Subject: [PATCH 1189/9938] ath9k: fix rng high cpu load If no valid ADC randomness output, ath9k rng will continuously reading ADC, which will cause high CPU load. So increase the delay to wait for ADC ready. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=114261 Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/rng.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c index c9cb2aad7b6f..d38e50f96db7 100644 --- a/drivers/net/wireless/ath/ath9k/rng.c +++ b/drivers/net/wireless/ath/ath9k/rng.c @@ -55,11 +55,26 @@ static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size) return j << 2; } +static u32 ath9k_rng_delay_get(u32 fail_stats) +{ + u32 delay; + + if (fail_stats < 100) + delay = 10; + else if (fail_stats < 105) + delay = 1000; + else + delay = 10000; + + return delay; +} + static int ath9k_rng_kthread(void *data) { int bytes_read; struct ath_softc *sc = data; u32 *rng_buf; + u32 delay, fail_stats = 0; rng_buf = kmalloc_array(ATH9K_RNG_BUF_SIZE, sizeof(u32), GFP_KERNEL); if (!rng_buf) @@ -69,10 +84,13 @@ static int ath9k_rng_kthread(void *data) bytes_read = ath9k_rng_data_read(sc, rng_buf, ATH9K_RNG_BUF_SIZE); if (unlikely(!bytes_read)) { - msleep_interruptible(10); + delay = ath9k_rng_delay_get(++fail_stats); + msleep_interruptible(delay); continue; } + fail_stats = 0; + /* sleep until entropy bits under write_wakeup_threshold */ add_hwgenerator_randomness((void *)rng_buf, bytes_read, ATH9K_RNG_ENTROPY(bytes_read)); -- GitLab From 9f573b98ca502ad495641ce42fcc18ccb32f5827 Mon Sep 17 00:00:00 2001 From: Cristina Ciocan Date: Fri, 1 Apr 2016 14:00:05 +0300 Subject: [PATCH 1190/9938] pinctrl: baytrail: Update irq chip operations This patch updates the irq chip implementation in order to interact with the pin control chip model: the chip contains reference to SOC data and pin/group/community information is retrieved through the SOC reference. Signed-off-by: Cristina Ciocan Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-baytrail.c | 97 +++++++++++++----------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index a24b51e47f00..f7c752b4bb6d 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1120,41 +1120,6 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned int offset) return 0; } -static int byt_irq_type(struct irq_data *d, unsigned type) -{ - struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - u32 offset = irqd_to_hwirq(d); - u32 value; - unsigned long flags; - void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); - - if (offset >= vg->chip.ngpio) - return -EINVAL; - - raw_spin_lock_irqsave(&vg->lock, flags); - value = readl(reg); - - WARN(value & BYT_DIRECT_IRQ_EN, - "Bad pad config for io mode, force direct_irq_en bit clearing"); - - /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits - * are used to indicate high and low level triggering - */ - value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | - BYT_TRIG_LVL); - - writel(value, reg); - - if (type & IRQ_TYPE_EDGE_BOTH) - irq_set_handler_locked(d, handle_edge_irq); - else if (type & IRQ_TYPE_LEVEL_MASK) - irq_set_handler_locked(d, handle_level_irq); - - raw_spin_unlock_irqrestore(&vg->lock, flags); - - return 0; -} - static void byt_get_pull_strength(u32 reg, u16 *strength) { switch (reg & BYT_PULL_STR_MASK) { @@ -1565,12 +1530,23 @@ static void byt_irq_ack(struct irq_data *d) unsigned offset = irqd_to_hwirq(d); void __iomem *reg; - raw_spin_lock(&vg->lock); reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG); + if (!reg) + return; + + raw_spin_lock(&vg->lock); writel(BIT(offset % 32), reg); raw_spin_unlock(&vg->lock); } +static void byt_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct byt_gpio *vg = gpiochip_get_data(gc); + + byt_gpio_clear_triggering(vg, irqd_to_hwirq(d)); +} + static void byt_irq_unmask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); @@ -1581,6 +1557,8 @@ static void byt_irq_unmask(struct irq_data *d) u32 value; reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + if (!reg) + return; raw_spin_lock_irqsave(&vg->lock, flags); value = readl(reg); @@ -1606,21 +1584,48 @@ static void byt_irq_unmask(struct irq_data *d) raw_spin_unlock_irqrestore(&vg->lock, flags); } -static void byt_irq_mask(struct irq_data *d) +static int byt_irq_type(struct irq_data *d, unsigned int type) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct byt_gpio *vg = gpiochip_get_data(gc); + struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + u32 offset = irqd_to_hwirq(d); + u32 value; + unsigned long flags; + void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); - byt_gpio_clear_triggering(vg, irqd_to_hwirq(d)); + if (!reg || offset >= vg->chip.ngpio) + return -EINVAL; + + raw_spin_lock_irqsave(&vg->lock, flags); + value = readl(reg); + + WARN(value & BYT_DIRECT_IRQ_EN, + "Bad pad config for io mode, force direct_irq_en bit clearing"); + + /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits + * are used to indicate high and low level triggering + */ + value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | + BYT_TRIG_LVL); + + writel(value, reg); + + if (type & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(d, handle_edge_irq); + else if (type & IRQ_TYPE_LEVEL_MASK) + irq_set_handler_locked(d, handle_level_irq); + + raw_spin_unlock_irqrestore(&vg->lock, flags); + + return 0; } static struct irq_chip byt_irqchip = { - .name = "BYT-GPIO", - .irq_ack = byt_irq_ack, - .irq_mask = byt_irq_mask, - .irq_unmask = byt_irq_unmask, - .irq_set_type = byt_irq_type, - .flags = IRQCHIP_SKIP_SET_WAKE, + .name = "BYT-GPIO", + .irq_ack = byt_irq_ack, + .irq_mask = byt_irq_mask, + .irq_unmask = byt_irq_unmask, + .irq_set_type = byt_irq_type, + .flags = IRQCHIP_SKIP_SET_WAKE, }; static void byt_gpio_irq_init_hw(struct byt_gpio *vg) -- GitLab From 71e6ca61e82667c5c0de4aa779a4438d6568262f Mon Sep 17 00:00:00 2001 From: Cristina Ciocan Date: Fri, 1 Apr 2016 14:00:06 +0300 Subject: [PATCH 1191/9938] pinctrl: baytrail: Register pin control handling This patch updates device's probing, removal and irq handling in order to register it as pinctrl device. Pin control data is matched by ACPI UID, since it is passed along as driver data in acpi_device_id structure. Signed-off-by: Cristina Ciocan Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-baytrail.c | 447 +++++++++++------------ 1 file changed, 221 insertions(+), 226 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index f7c752b4bb6d..b087b0030617 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -181,6 +181,17 @@ struct byt_pinctrl_soc_data { size_t ncommunities; }; +struct byt_gpio { + struct gpio_chip chip; + struct platform_device *pdev; + struct pinctrl_dev *pctl_dev; + struct pinctrl_desc pctl_desc; + raw_spinlock_t lock; + const struct byt_pinctrl_soc_data *soc_data; + struct byt_community *communities_copy; + struct byt_gpio_pin_context *saved_context; +}; + /* SCORE pins, aka GPIOC_ or GPIO_S0_SC[] */ static const struct pinctrl_pin_desc byt_score_pins[] = { PINCTRL_PIN(0, "SATA_GP0"), @@ -287,20 +298,6 @@ static const struct pinctrl_pin_desc byt_score_pins[] = { PINCTRL_PIN(101, "PMC_PLT_CLK5"), }; -static unsigned const score_pins[BYT_NGPIO_SCORE] = { - 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, - 36, 38, 39, 35, 40, 84, 62, 61, 64, 59, - 54, 56, 60, 55, 63, 57, 51, 50, 53, 47, - 52, 49, 48, 43, 46, 41, 45, 42, 58, 44, - 95, 105, 70, 68, 67, 66, 69, 71, 65, 72, - 86, 90, 88, 92, 103, 77, 79, 83, 78, 81, - 80, 82, 13, 12, 15, 14, 17, 18, 19, 16, - 2, 1, 0, 4, 6, 7, 9, 8, 33, 32, - 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, - 24, 22, 5, 3, 10, 11, 106, 87, 91, 104, - 97, 100, -}; - static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = { 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 36, 38, 39, 35, 40, 84, 62, 61, 64, 59, @@ -571,14 +568,6 @@ static const struct pinctrl_pin_desc byt_sus_pins[] = { PINCTRL_PIN(43, "USB_ULPI_REFCLK"), }; -static const unsigned int sus_pins[BYT_NGPIO_SUS] = { - 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, - 18, 7, 11, 20, 17, 1, 8, 10, 19, 12, - 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, - 26, 51, 56, 54, 49, 55, 48, 57, 50, 58, - 52, 53, 59, 40, -}; - static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = { 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 18, 7, 11, 20, 17, 1, 8, 10, 19, 12, @@ -701,43 +690,6 @@ static const struct byt_pinctrl_soc_data byt_ncore_soc_data = { .ncommunities = ARRAY_SIZE(byt_ncore_communities), }; -static unsigned const ncore_pins[BYT_NGPIO_NCORE] = { - 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, - 14, 15, 12, 26, 27, 1, 4, 8, 11, 0, - 3, 6, 10, 13, 2, 5, 9, 7, -}; - -static struct pinctrl_gpio_range byt_ranges[] = { - { - .name = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */ - .npins = BYT_NGPIO_SCORE, - .pins = score_pins, - }, - { - .name = BYT_NCORE_ACPI_UID, - .npins = BYT_NGPIO_NCORE, - .pins = ncore_pins, - }, - { - .name = BYT_SUS_ACPI_UID, - .npins = BYT_NGPIO_SUS, - .pins = sus_pins, - }, - { - }, -}; - -struct byt_gpio { - struct gpio_chip chip; - struct platform_device *pdev; - raw_spinlock_t lock; - void __iomem *reg_base; - struct pinctrl_gpio_range *range; - struct byt_gpio_pin_context *saved_context; - const struct byt_pinctrl_soc_data *soc_data; - struct byt_community *communities_copy; -}; - static const struct byt_pinctrl_soc_data *byt_soc_data[] = { &byt_score_soc_data, &byt_sus_soc_data, @@ -1023,14 +975,6 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, return 0; } -static void byt_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct byt_gpio *vg = gpiochip_get_data(chip); - - byt_gpio_clear_triggering(vg, offset); - pm_runtime_put(&vg->pdev->dev); -} - static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev, struct pinctrl_gpio_range *range, unsigned int offset) @@ -1084,42 +1028,6 @@ static const struct pinmux_ops byt_pinmux_ops = { .gpio_set_direction = byt_gpio_set_direction, }; -static int byt_gpio_request(struct gpio_chip *chip, unsigned int offset) -{ - struct byt_gpio *vg = gpiochip_get_data(chip); - void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); - u32 value, gpio_mux; - unsigned long flags; - - raw_spin_lock_irqsave(&vg->lock, flags); - - /* - * In most cases, func pin mux 000 means GPIO function. - * But, some pins may have func pin mux 001 represents - * GPIO function. - * - * Because there are devices out there where some pins were not - * configured correctly we allow changing the mux value from - * request (but print out warning about that). - */ - value = readl(reg) & BYT_PIN_MUX; - gpio_mux = byt_get_gpio_mux(vg, offset); - if (WARN_ON(gpio_mux != value)) { - value = readl(reg) & ~BYT_PIN_MUX; - value |= gpio_mux; - writel(value, reg); - - dev_warn(&vg->pdev->dev, - "pin %u forcibly re-configured as GPIO\n", offset); - } - - raw_spin_unlock_irqrestore(&vg->lock, flags); - - pm_runtime_get(&vg->pdev->dev); - - return 0; -} - static void byt_get_pull_strength(u32 reg, u16 *strength) { switch (reg & BYT_PULL_STR_MASK) { @@ -1365,21 +1273,6 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { - struct byt_gpio *vg = gpiochip_get_data(chip); - void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); - unsigned long flags; - - raw_spin_lock_irqsave(&vg->lock, flags); - - /* - * Before making any direction modifications, do a check if gpio - * is set for direct IRQ. On baytrail, setting GPIO to output does - * not make sense, so let's at least warn the caller before they shoot - * themselves in the foot. - */ - WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, - "Potential Error: Setting GPIO with direct_irq_en to output"); - return pinctrl_gpio_direction_input(chip->base + offset); } @@ -1489,28 +1382,6 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) } } -static void byt_gpio_irq_handler(struct irq_desc *desc) -{ - struct irq_data *data = irq_desc_get_irq_data(desc); - struct byt_gpio *vg = gpiochip_get_data(irq_desc_get_handler_data(desc)); - struct irq_chip *chip = irq_data_get_irq_chip(data); - u32 base, pin; - void __iomem *reg; - unsigned long pending; - unsigned virq; - - /* check from GPIO controller which pin triggered the interrupt */ - for (base = 0; base < vg->chip.ngpio; base += 32) { - reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); - pending = readl(reg); - for_each_set_bit(pin, &pending, 32) { - virq = irq_find_mapping(vg->chip.irqdomain, base + pin); - generic_handle_irq(virq); - } - } - chip->irq_eoi(data); -} - static const struct gpio_chip byt_gpio_chip = { .owner = THIS_MODULE, .request = gpiochip_generic_request, @@ -1628,6 +1499,37 @@ static struct irq_chip byt_irqchip = { .flags = IRQCHIP_SKIP_SET_WAKE, }; +static void byt_gpio_irq_handler(struct irq_desc *desc) +{ + struct irq_data *data = irq_desc_get_irq_data(desc); + struct byt_gpio *vg = gpiochip_get_data( + irq_desc_get_handler_data(desc)); + struct irq_chip *chip = irq_data_get_irq_chip(data); + u32 base, pin; + void __iomem *reg; + unsigned long pending; + unsigned int virq; + + /* check from GPIO controller which pin triggered the interrupt */ + for (base = 0; base < vg->chip.ngpio; base += 32) { + reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); + + if (!reg) { + dev_warn(&vg->pdev->dev, + "Pin %i: could not retrieve interrupt status register\n", + base); + continue; + } + + pending = readl(reg); + for_each_set_bit(pin, &pending, 32) { + virq = irq_find_mapping(vg->chip.irqdomain, base + pin); + generic_handle_irq(virq); + } + } + chip->irq_eoi(data); +} + static void byt_gpio_irq_init_hw(struct byt_gpio *vg) { void __iomem *reg; @@ -1639,8 +1541,18 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg) * do not use direct IRQ mode. This will prevent spurious * interrupts from misconfigured pins. */ - for (i = 0; i < vg->chip.ngpio; i++) { - value = readl(byt_gpio_reg(vg, i, BYT_CONF0_REG)); + for (i = 0; i < vg->soc_data->npins; i++) { + unsigned int pin = vg->soc_data->pins[i].number; + + reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); + if (!reg) { + dev_warn(&vg->pdev->dev, + "Pin %i: could not retrieve conf0 register\n", + i); + continue; + } + + value = readl(reg); if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) && !(value & BYT_DIRECT_IRQ_EN)) { byt_gpio_clear_triggering(vg, i); @@ -1649,8 +1561,16 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg) } /* clear interrupt status trigger registers */ - for (base = 0; base < vg->chip.ngpio; base += 32) { + for (base = 0; base < vg->soc_data->npins; base += 32) { reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); + + if (!reg) { + dev_warn(&vg->pdev->dev, + "Pin %i: could not retrieve irq status reg\n", + base); + continue; + } + writel(0xffffffff, reg); /* make sure trigger bits are cleared, if not then a pin might be misconfigured in bios */ @@ -1661,82 +1581,47 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg) } } -static int byt_gpio_probe(struct platform_device *pdev) +static int byt_gpio_probe(struct byt_gpio *vg) { - struct byt_gpio *vg; struct gpio_chip *gc; - struct resource *mem_rc, *irq_rc; - struct device *dev = &pdev->dev; - struct acpi_device *acpi_dev; - struct pinctrl_gpio_range *range; - acpi_handle handle = ACPI_HANDLE(dev); + struct resource *irq_rc; int ret; - if (acpi_bus_get_device(handle, &acpi_dev)) - return -ENODEV; - - vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL); - if (!vg) { - dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n"); - return -ENOMEM; - } - - for (range = byt_ranges; range->name; range++) { - if (!strcmp(acpi_dev->pnp.unique_id, range->name)) { - vg->chip.ngpio = range->npins; - vg->range = range; - break; - } - } - - if (!vg->chip.ngpio || !vg->range) - return -ENODEV; - - vg->pdev = pdev; - platform_set_drvdata(pdev, vg); - - mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); - vg->reg_base = devm_ioremap_resource(dev, mem_rc); - if (IS_ERR(vg->reg_base)) - return PTR_ERR(vg->reg_base); - - raw_spin_lock_init(&vg->lock); - - gc = &vg->chip; - gc->label = dev_name(&pdev->dev); - gc->owner = THIS_MODULE; - gc->request = byt_gpio_request; - gc->free = byt_gpio_free; - gc->direction_input = byt_gpio_direction_input; - gc->direction_output = byt_gpio_direction_output; - gc->get = byt_gpio_get; - gc->set = byt_gpio_set; - gc->dbg_show = byt_gpio_dbg_show; - gc->base = -1; - gc->can_sleep = false; - gc->parent = dev; + /* Set up gpio chip */ + vg->chip = byt_gpio_chip; + gc = &vg->chip; + gc->label = dev_name(&vg->pdev->dev); + gc->base = -1; + gc->can_sleep = false; + gc->parent = &vg->pdev->dev; + gc->ngpio = vg->soc_data->npins; #ifdef CONFIG_PM_SLEEP - vg->saved_context = devm_kcalloc(&pdev->dev, gc->ngpio, + vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio, sizeof(*vg->saved_context), GFP_KERNEL); #endif - ret = gpiochip_add_data(gc, vg); if (ret) { - dev_err(&pdev->dev, "failed adding byt-gpio chip\n"); + dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n"); return ret; } + ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev), + 0, 0, vg->soc_data->npins); + if (ret) { + dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n"); + goto fail; + } + /* set up interrupts */ - irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0); if (irq_rc && irq_rc->start) { byt_gpio_irq_init_hw(vg); ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0, handle_simple_irq, IRQ_TYPE_NONE); if (ret) { - dev_err(dev, "failed to add irqchip\n"); - gpiochip_remove(gc); - return ret; + dev_err(&vg->pdev->dev, "failed to add irqchip\n"); + goto fail; } gpiochip_set_chained_irqchip(gc, &byt_irqchip, @@ -1744,7 +1629,120 @@ static int byt_gpio_probe(struct platform_device *pdev) byt_gpio_irq_handler); } - pm_runtime_enable(dev); + return ret; + +fail: + gpiochip_remove(&vg->chip); + + return ret; +} + +static int byt_set_soc_data(struct byt_gpio *vg, + const struct byt_pinctrl_soc_data *soc_data) +{ + int i; + + vg->soc_data = soc_data; + vg->communities_copy = devm_kcalloc(&vg->pdev->dev, + soc_data->ncommunities, + sizeof(*vg->communities_copy), + GFP_KERNEL); + if (!vg->communities_copy) + return -ENOMEM; + + for (i = 0; i < soc_data->ncommunities; i++) { + struct byt_community *comm = vg->communities_copy + i; + struct resource *mem_rc; + + *comm = vg->soc_data->communities[i]; + + mem_rc = platform_get_resource(vg->pdev, IORESOURCE_MEM, 0); + comm->reg_base = devm_ioremap_resource(&vg->pdev->dev, mem_rc); + if (IS_ERR(comm->reg_base)) + return PTR_ERR(comm->reg_base); + } + + return 0; +} + +static const struct acpi_device_id byt_gpio_acpi_match[] = { + { "INT33B2", (kernel_ulong_t)byt_soc_data }, + { "INT33FC", (kernel_ulong_t)byt_soc_data }, + { } +}; +MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); + +static int byt_pinctrl_probe(struct platform_device *pdev) +{ + const struct byt_pinctrl_soc_data *soc_data = NULL; + const struct byt_pinctrl_soc_data **soc_table; + const struct acpi_device_id *acpi_id; + struct acpi_device *acpi_dev; + struct byt_gpio *vg; + int i, ret; + + acpi_dev = ACPI_COMPANION(&pdev->dev); + if (!acpi_dev) + return -ENODEV; + + acpi_id = acpi_match_device(byt_gpio_acpi_match, &pdev->dev); + if (!acpi_id) + return -ENODEV; + + soc_table = (const struct byt_pinctrl_soc_data **)acpi_id->driver_data; + + for (i = 0; soc_table[i]; i++) { + if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) { + soc_data = soc_table[i]; + break; + } + } + + if (!soc_data) + return -ENODEV; + + vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL); + if (!vg) + return -ENOMEM; + + vg->pdev = pdev; + ret = byt_set_soc_data(vg, soc_data); + if (ret) { + dev_err(&pdev->dev, "failed to set soc data\n"); + return ret; + } + + vg->pctl_desc = byt_pinctrl_desc; + vg->pctl_desc.name = dev_name(&pdev->dev); + vg->pctl_desc.pins = vg->soc_data->pins; + vg->pctl_desc.npins = vg->soc_data->npins; + + vg->pctl_dev = pinctrl_register(&vg->pctl_desc, &pdev->dev, vg); + if (IS_ERR(vg->pctl_dev)) { + dev_err(&pdev->dev, "failed to register pinctrl driver\n"); + return PTR_ERR(vg->pctl_dev); + } + + ret = byt_gpio_probe(vg); + if (ret) { + pinctrl_unregister(vg->pctl_dev); + return ret; + } + + platform_set_drvdata(pdev, vg); + raw_spin_lock_init(&vg->lock); + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int byt_pinctrl_remove(struct platform_device *pdev) +{ + struct byt_gpio *vg = platform_get_drvdata(pdev); + + pm_runtime_disable(&pdev->dev); + gpiochip_remove(&vg->chip); + pinctrl_unregister(vg->pctl_dev); return 0; } @@ -1756,15 +1754,22 @@ static int byt_gpio_suspend(struct device *dev) struct byt_gpio *vg = platform_get_drvdata(pdev); int i; - for (i = 0; i < vg->chip.ngpio; i++) { + for (i = 0; i < vg->soc_data->npins; i++) { void __iomem *reg; u32 value; + unsigned int pin = vg->soc_data->pins[i].number; - reg = byt_gpio_reg(vg, i, BYT_CONF0_REG); + reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); + if (!reg) { + dev_warn(&vg->pdev->dev, + "Pin %i: could not retrieve conf0 register\n", + i); + continue; + } value = readl(reg) & BYT_CONF0_RESTORE_MASK; vg->saved_context[i].conf0 = value; - reg = byt_gpio_reg(vg, i, BYT_VAL_REG); + reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); value = readl(reg) & BYT_VAL_RESTORE_MASK; vg->saved_context[i].val = value; } @@ -1778,11 +1783,18 @@ static int byt_gpio_resume(struct device *dev) struct byt_gpio *vg = platform_get_drvdata(pdev); int i; - for (i = 0; i < vg->chip.ngpio; i++) { + for (i = 0; i < vg->soc_data->npins; i++) { void __iomem *reg; u32 value; + unsigned int pin = vg->soc_data->pins[i].number; - reg = byt_gpio_reg(vg, i, BYT_CONF0_REG); + reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); + if (!reg) { + dev_warn(&vg->pdev->dev, + "Pin %i: could not retrieve conf0 register\n", + i); + continue; + } value = readl(reg); if ((value & BYT_CONF0_RESTORE_MASK) != vg->saved_context[i].conf0) { @@ -1792,7 +1804,7 @@ static int byt_gpio_resume(struct device *dev) dev_info(dev, "restored pin %d conf0 %#08x", i, value); } - reg = byt_gpio_reg(vg, i, BYT_VAL_REG); + reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); value = readl(reg); if ((value & BYT_VAL_RESTORE_MASK) != vg->saved_context[i].val) { @@ -1830,26 +1842,9 @@ static const struct dev_pm_ops byt_gpio_pm_ops = { NULL) }; -static const struct acpi_device_id byt_gpio_acpi_match[] = { - { "INT33B2", (kernel_ulong_t)byt_soc_data }, - { "INT33FC", (kernel_ulong_t)byt_soc_data }, - { } -}; -MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); - -static int byt_gpio_remove(struct platform_device *pdev) -{ - struct byt_gpio *vg = platform_get_drvdata(pdev); - - pm_runtime_disable(&pdev->dev); - gpiochip_remove(&vg->chip); - - return 0; -} - static struct platform_driver byt_gpio_driver = { - .probe = byt_gpio_probe, - .remove = byt_gpio_remove, + .probe = byt_pinctrl_probe, + .remove = byt_pinctrl_remove, .driver = { .name = "byt_gpio", .pm = &byt_gpio_pm_ops, -- GitLab From fae6bd7090283dccc1487b997e6dea4529cbf839 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 11 Mar 2016 18:46:33 +0100 Subject: [PATCH 1192/9938] ARM: dts: armv7-m: add unit name to interrupt-controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add unit name to nvic to remove the following warning: Warning (unit_address_vs_reg): Node /nv-interrupt-controller has a reg or ranges property, but no unit name Also correct the node name to 'interrupt-controller' while changing the line. Signed-off-by: Joachim Eastwood Acked-by: Uwe Kleine-König Acked-by: Stefan Agner --- arch/arm/boot/dts/armv7-m.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/armv7-m.dtsi b/arch/arm/boot/dts/armv7-m.dtsi index b1ad7cf6ac02..16331aa79775 100644 --- a/arch/arm/boot/dts/armv7-m.dtsi +++ b/arch/arm/boot/dts/armv7-m.dtsi @@ -1,7 +1,7 @@ #include "skeleton.dtsi" / { - nvic: nv-interrupt-controller { + nvic: interrupt-controller@e000e100 { compatible = "arm,armv7m-nvic"; interrupt-controller; #interrupt-cells = <1>; -- GitLab From 472a5a3ddf86725f87432d70462e3ce6dc3996b6 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sat, 27 Feb 2016 19:39:03 +0100 Subject: [PATCH 1193/9938] ARM: dts: lpc18xx: remove unit addresses from creg childs DT nodes without reg properties should not have a unit address. This fixes the following warnings from dtc. Warning (unit_address_vs_reg): Node /soc/syscon@40043000/phy@004 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /soc/syscon@40043000/dma-mux@11c has a unit name, but no reg property Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc18xx.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/lpc18xx.dtsi index fdc991bedd37..fdb736c82045 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/lpc18xx.dtsi @@ -201,13 +201,13 @@ #clock-cells = <1>; }; - usb0_otg_phy: phy@004 { + usb0_otg_phy: phy { compatible = "nxp,lpc1850-usb-otg-phy"; clocks = <&ccu1 CLK_USB0>; #phy-cells = <0>; }; - dmamux: dma-mux@11c { + dmamux: dma-mux { compatible = "nxp,lpc1850-dmamux"; #dma-cells = <3>; dma-requests = <64>; -- GitLab From eeadc20c6a4e700c80d26e10e9e2c49fd551b2d4 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 11 Mar 2016 19:05:03 +0100 Subject: [PATCH 1194/9938] ARM: dts: lpc4357-ea4357: fix unit name warnings from dtc Fix the following warnings from dtc by either adding or removing the unit name from the node. Warning (unit_address_vs_reg): Node /soc/flash-controller@40003000/flash@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /gpio_joystick/button@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /gpio_joystick/button@1 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /gpio_joystick/button@2 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /gpio_joystick/button@3 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /gpio_joystick/button@4 has a unit name, but no reg property Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc4357-ea4357-devkit.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts b/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts index a211b6ef538d..1919be4dab2b 100644 --- a/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts +++ b/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts @@ -62,31 +62,31 @@ poll-interval = <100>; autorepeat; - button@0 { + button0 { label = "joy_enter"; linux,code = ; gpios = <&gpio LPC_GPIO(4,8) GPIO_ACTIVE_LOW>; }; - button@1 { + button1 { label = "joy_left"; linux,code = ; gpios = <&gpio LPC_GPIO(4,9) GPIO_ACTIVE_LOW>; }; - button@2 { + button2 { label = "joy_up"; linux,code = ; gpios = <&gpio LPC_GPIO(4,10) GPIO_ACTIVE_LOW>; }; - button@3 { + button3 { label = "joy_right"; linux,code = ; gpios = <&gpio LPC_GPIO(4,12) GPIO_ACTIVE_LOW>; }; - button@4 { + button4 { label = "joy_down"; linux,code = ; gpios = <&gpio LPC_GPIO(4,13) GPIO_ACTIVE_LOW>; @@ -584,7 +584,7 @@ pinctrl-names = "default"; pinctrl-0 = <&spifi_pins>; - flash@0 { + flash { compatible = "jedec,spi-nor"; spi-cpol; spi-cpha; -- GitLab From 3a572c4aa96d6c7831fa1798152241ce24d720c2 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 11 Mar 2016 19:05:47 +0100 Subject: [PATCH 1195/9938] ARM: dts: lpc4350-hitex-eval: fix unit name warnings from dtc Fix the following warnings from dtc by either adding or removing the unit name from the node. Warning (unit_address_vs_reg): Node /soc/flash-controller@40003000/flash@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@1 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@2 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@3 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@4 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@5 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@6 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /pca_buttons/button@7 has a unit name, but no reg property Signed-off-by: Joachim Eastwood --- arch/arm/boot/dts/lpc4350-hitex-eval.dts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/lpc4350-hitex-eval.dts b/arch/arm/boot/dts/lpc4350-hitex-eval.dts index 6d0c698a6d94..6c9048d4d03c 100644 --- a/arch/arm/boot/dts/lpc4350-hitex-eval.dts +++ b/arch/arm/boot/dts/lpc4350-hitex-eval.dts @@ -45,50 +45,50 @@ poll-interval = <100>; autorepeat; - button@0 { + button0 { label = "joy:right"; linux,code = ; gpios = <&pca_gpio 8 GPIO_ACTIVE_LOW>; }; - button@1 { + button1 { label = "joy:up"; linux,code = ; gpios = <&pca_gpio 9 GPIO_ACTIVE_LOW>; }; - button@2 { + button2 { label = "joy:enter"; linux,code = ; gpios = <&pca_gpio 10 GPIO_ACTIVE_LOW>; }; - button@3 { + button3 { label = "joy:left"; linux,code = ; gpios = <&pca_gpio 11 GPIO_ACTIVE_LOW>; }; - button@4 { + button4 { label = "joy:down"; linux,code = ; gpios = <&pca_gpio 12 GPIO_ACTIVE_LOW>; }; - button@5 { + button5 { label = "user:sw3"; linux,code = ; gpios = <&pca_gpio 13 GPIO_ACTIVE_LOW>; }; - button@6 { + button6 { label = "user:sw4"; linux,code = ; gpios = <&pca_gpio 14 GPIO_ACTIVE_LOW>; }; - button@7 { + button7 { label = "user:sw5"; linux,code = ; gpios = <&pca_gpio 15 GPIO_ACTIVE_LOW>; @@ -453,7 +453,7 @@ pinctrl-names = "default"; pinctrl-0 = <&spifi_pins>; - flash@0 { + flash { compatible = "jedec,spi-nor"; spi-rx-bus-width = <4>; #address-cells = <1>; -- GitLab From 1db7f6201dfce1740e41f87c81389cc2e9c73e99 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Wed, 24 Feb 2016 23:10:42 +0100 Subject: [PATCH 1196/9938] dt-bindings: phy-lpc18xx-usb-otg: remove unit address from binding DT bindings should either use a unit address and a reg property or none of them. Since either of them aren't really useful for such a simple device like this one remove the unit address. Signed-off-by: Joachim Eastwood Acked-by: Rob Herring --- Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt b/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt index bd61b467e30a..3bb821cd6a7f 100644 --- a/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt +++ b/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt @@ -18,7 +18,7 @@ creg: syscon@40043000 { compatible = "nxp,lpc1850-creg", "syscon", "simple-mfd"; reg = <0x40043000 0x1000>; - usb0_otg_phy: phy@004 { + usb0_otg_phy: phy { compatible = "nxp,lpc1850-usb-otg-phy"; clocks = <&ccu1 CLK_USB0>; #phy-cells = <0>; -- GitLab From 658b476c742fe379e7020309fd590a27b457a4c1 Mon Sep 17 00:00:00 2001 From: Cristina Ciocan Date: Fri, 1 Apr 2016 14:00:07 +0300 Subject: [PATCH 1197/9938] pinctrl: baytrail: Add debounce configuration Make debounce setting and getting functionality available when configurating a certain pin. Signed-off-by: Cristina Ciocan Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-baytrail.c | 83 +++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index b087b0030617..6dcf43ab9efe 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -38,6 +38,7 @@ #define BYT_VAL_REG 0x008 #define BYT_DFT_REG 0x00c #define BYT_INT_STAT_REG 0x800 +#define BYT_DEBOUNCE_REG 0x9d0 /* BYT_CONF0_REG register bits */ #define BYT_IODEN BIT(31) @@ -45,6 +46,7 @@ #define BYT_TRIG_NEG BIT(26) #define BYT_TRIG_POS BIT(25) #define BYT_TRIG_LVL BIT(24) +#define BYT_DEBOUNCE_EN BIT(20) #define BYT_PULL_STR_SHIFT 9 #define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT) #define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT) @@ -69,6 +71,16 @@ BYT_PIN_MUX) #define BYT_VAL_RESTORE_MASK (BYT_DIR_MASK | BYT_LEVEL) +/* BYT_DEBOUNCE_REG bits */ +#define BYT_DEBOUNCE_PULSE_MASK 0x7 +#define BYT_DEBOUNCE_PULSE_375US 1 +#define BYT_DEBOUNCE_PULSE_750US 2 +#define BYT_DEBOUNCE_PULSE_1500US 3 +#define BYT_DEBOUNCE_PULSE_3MS 4 +#define BYT_DEBOUNCE_PULSE_6MS 5 +#define BYT_DEBOUNCE_PULSE_12MS 6 +#define BYT_DEBOUNCE_PULSE_24MS 7 + #define BYT_NGPIO_SCORE 102 #define BYT_NGPIO_NCORE 28 #define BYT_NGPIO_SUS 44 @@ -1078,7 +1090,7 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); unsigned long flags; - u32 conf, pull, val; + u32 conf, pull, val, debounce; u16 arg = 0; raw_spin_lock_irqsave(&vg->lock, flags); @@ -1107,6 +1119,41 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, byt_get_pull_strength(conf, &arg); + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + if (!(conf & BYT_DEBOUNCE_EN)) + return -EINVAL; + + raw_spin_lock_irqsave(&vg->lock, flags); + debounce = readl(byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG)); + raw_spin_unlock_irqrestore(&vg->lock, flags); + + switch (debounce & BYT_DEBOUNCE_PULSE_MASK) { + case BYT_DEBOUNCE_PULSE_375US: + arg = 375; + break; + case BYT_DEBOUNCE_PULSE_750US: + arg = 750; + break; + case BYT_DEBOUNCE_PULSE_1500US: + arg = 1500; + break; + case BYT_DEBOUNCE_PULSE_3MS: + arg = 3000; + break; + case BYT_DEBOUNCE_PULSE_6MS: + arg = 6000; + break; + case BYT_DEBOUNCE_PULSE_12MS: + arg = 12000; + break; + case BYT_DEBOUNCE_PULSE_24MS: + arg = 24000; + break; + default: + return -EINVAL; + } + break; default: return -ENOTSUPP; @@ -1127,7 +1174,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); unsigned long flags; - u32 conf, val; + u32 conf, val, debounce; int i, ret = 0; raw_spin_lock_irqsave(&vg->lock, flags); @@ -1186,6 +1233,38 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, conf |= BYT_PULL_ASSIGN_UP; ret = byt_set_pull_strength(&conf, arg); + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + debounce = readl(byt_gpio_reg(vg, offset, + BYT_DEBOUNCE_REG)); + conf &= ~BYT_DEBOUNCE_PULSE_MASK; + + switch (arg) { + case 375: + conf |= BYT_DEBOUNCE_PULSE_375US; + break; + case 750: + conf |= BYT_DEBOUNCE_PULSE_750US; + break; + case 1500: + conf |= BYT_DEBOUNCE_PULSE_1500US; + break; + case 3000: + conf |= BYT_DEBOUNCE_PULSE_3MS; + break; + case 6000: + conf |= BYT_DEBOUNCE_PULSE_6MS; + break; + case 12000: + conf |= BYT_DEBOUNCE_PULSE_12MS; + break; + case 24000: + conf |= BYT_DEBOUNCE_PULSE_24MS; + break; + default: + ret = -EINVAL; + } + break; default: ret = -ENOTSUPP; -- GitLab From 80b28810cc98aadc80e7ce8cc155a774a7ada8ca Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:38:28 +0800 Subject: [PATCH 1198/9938] ACPICA: Linuxize: reduce divergences for 20160212 release The patch reduces source code differences between the Linux kernel and the ACPICA upstream so that the linuxized ACPICA 20160212 release can be applied with reduced human intervention. Signed-off-by: Lv Zheng [ rjw: White space damage fixes ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsinit.c | 1 - drivers/acpi/acpica/nsload.c | 2 +- drivers/acpi/osl.c | 2 +- include/acpi/acpiosxf.h | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index d4aa8b696ee9..2de8adb41d64 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -602,7 +602,6 @@ acpi_ns_init_one_device(acpi_handle obj_handle, info->flags = ACPI_IGNORE_RETURN_VALUE; status = acpi_ns_evaluate(info); - if (ACPI_SUCCESS(status)) { walk_info->num_INI++; } diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 75cdb8790d49..b5e2b0ada0ab 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -123,8 +123,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list. tables[table_index].owner_id); - acpi_tb_release_owner_id(table_index); + acpi_tb_release_owner_id(table_index); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 814d5f83b75e..bef06c9503cd 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -582,7 +582,7 @@ static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN]; acpi_status acpi_os_predefined_override(const struct acpi_predefined_names *init_val, - char **new_val) + acpi_string *new_val) { if (!init_val || !new_val) return AE_BAD_PARAMETER; diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index d1e34d1eeea6..6026308f5b26 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -96,7 +96,7 @@ acpi_physical_address acpi_os_get_root_pointer(void); #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_predefined_override acpi_status acpi_os_predefined_override(const struct acpi_predefined_names *init_val, - char **new_val); + acpi_string *new_val); #endif #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_table_override -- GitLab From 5b01e4b9efa0b78672cbbea830c9fbcc7f239e29 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:43:54 +0200 Subject: [PATCH 1199/9938] libata: Implement NCQ autosense Some newer devices support NCQ autosense (cf ACS-4), so we should be using it to retrieve the sense code and speed up recovery. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-eh.c | 12 ++++++++++++ drivers/ata/libata-scsi.c | 7 ++++++- drivers/ata/libata.h | 1 + include/linux/ata.h | 2 ++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 961acc788f44..8c8355f0792e 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1600,6 +1600,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev, tf->hob_lbah = buf[10]; tf->nsect = buf[12]; tf->hob_nsect = buf[13]; + if (ata_id_has_ncq_autosense(dev->id)) + tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; return 0; } @@ -1797,6 +1799,16 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) memcpy(&qc->result_tf, &tf, sizeof(tf)); qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; + if (qc->result_tf.auxiliary) { + char sense_key, asc, ascq; + + sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; + asc = (qc->result_tf.auxiliary >> 8) & 0xff; + ascq = qc->result_tf.auxiliary & 0xff; + ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } + ehc->i.err_mask &= ~AC_ERR_DEV; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 567859ce0512..6dc2fadfd7c5 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -270,8 +270,11 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, ata_scsi_park_show, ata_scsi_park_store); EXPORT_SYMBOL_GPL(dev_attr_unload_heads); -static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) +void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) { + if (!cmd) + return; + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); @@ -1784,6 +1787,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && ((cdb[2] & 0x20) || need_sense)) ata_gen_passthru_sense(qc); + else if (qc->flags & ATA_QCFLAG_SENSE_VALID) + cmd->result = SAM_STAT_CHECK_CONDITION; else if (need_sense) ata_gen_ata_sense(qc); else diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index f840ca18a7c0..8cfdd9616d16 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -137,6 +137,7 @@ extern int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht); extern void ata_scsi_scan_host(struct ata_port *ap, int sync); extern int ata_scsi_offline_dev(struct ata_device *dev); +extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq); extern void ata_scsi_media_change_notify(struct ata_device *dev); extern void ata_scsi_hotplug(struct work_struct *work); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); diff --git a/include/linux/ata.h b/include/linux/ata.h index c1a2f345cbe6..e797e1b53006 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -528,6 +528,8 @@ struct ata_bmdma_prd { #define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20) #define ata_id_has_da(id) ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4)) #define ata_id_has_devslp(id) ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8)) +#define ata_id_has_ncq_autosense(id) \ + ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7)) static inline bool ata_id_has_hipm(const u16 *id) { -- GitLab From e87fd28cf9a2d9018ac4b6dd92f0b417714bc18d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:43:55 +0200 Subject: [PATCH 1200/9938] libata: Implement support for sense data reporting ACS-4 defines a sense data reporting feature set. This patch implements support for it. tj: Cosmetic formatting updates. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 20 +++++++++++- drivers/ata/libata-eh.c | 68 ++++++++++++++++++++++++++++++++++++--- include/linux/ata.h | 16 +++++++++ 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 55e257c268dd..f991f786227e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2148,6 +2148,24 @@ static int ata_dev_config_ncq(struct ata_device *dev, return 0; } +static void ata_dev_config_sense_reporting(struct ata_device *dev) +{ + unsigned int err_mask; + + if (!ata_id_has_sense_reporting(dev->id)) + return; + + if (ata_id_sense_reporting_enabled(dev->id)) + return; + + err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1); + if (err_mask) { + ata_dev_dbg(dev, + "failed to enable Sense Data Reporting, Emask 0x%x\n", + err_mask); + } +} + /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure @@ -2370,7 +2388,7 @@ int ata_dev_configure(struct ata_device *dev) dev->devslp_timing[i] = sata_setting[j]; } } - + ata_dev_config_sense_reporting(dev); dev->cdb_len = 16; } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8c8355f0792e..170e891e79af 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1637,6 +1637,56 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) return err_mask; } +/** + * ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT + * @dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to + * @cmd: scsi command for which the sense code should be set + * + * Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK + * SENSE. This function is an EH helper. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_request_sense(struct ata_queued_cmd *qc, + struct scsi_cmnd *cmd) +{ + struct ata_device *dev = qc->dev; + struct ata_taskfile tf; + unsigned int err_mask; + + if (qc->ap->pflags & ATA_PFLAG_FROZEN) { + ata_dev_warn(dev, "sense data available but port frozen\n"); + return; + } + + if (!cmd) + return; + + if (!ata_id_sense_reporting_enabled(dev->id)) { + ata_dev_warn(qc->dev, "sense data reporting disabled\n"); + return; + } + + DPRINTK("ATA request sense\n"); + + ata_tf_init(dev, &tf); + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + tf.command = ATA_CMD_REQ_SENSE_DATA; + tf.protocol = ATA_PROT_NODATA; + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + /* Ignore err_mask; ATA_ERR might be set */ + if (tf.command & ATA_SENSE) { + ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } else { + ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", + tf.command, err_mask); + } +} + /** * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE * @dev: device to perform REQUEST_SENSE to @@ -1838,14 +1888,23 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, return ATA_EH_RESET; } - if (stat & (ATA_ERR | ATA_DF)) + if (stat & (ATA_ERR | ATA_DF)) { qc->err_mask |= AC_ERR_DEV; - else + /* + * Sense data reporting does not work if the + * device fault bit is set. + */ + if (stat & ATA_DF) + stat &= ~ATA_SENSE; + } else { return 0; + } switch (qc->dev->class) { case ATA_DEV_ATA: case ATA_DEV_ZAC: + if (stat & ATA_SENSE) + ata_eh_request_sense(qc, qc->scsicmd); if (err & ATA_ICRC) qc->err_mask |= AC_ERR_ATA_BUS; if (err & (ATA_UNC | ATA_AMNF)) @@ -2581,14 +2640,15 @@ static void ata_eh_link_report(struct ata_link *link) #ifdef CONFIG_ATA_VERBOSE_ERROR if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | - ATA_ERR)) { + ATA_SENSE | ATA_ERR)) { if (res->command & ATA_BUSY) ata_dev_err(qc->dev, "status: { Busy }\n"); else - ata_dev_err(qc->dev, "status: { %s%s%s%s}\n", + ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n", res->command & ATA_DRDY ? "DRDY " : "", res->command & ATA_DF ? "DF " : "", res->command & ATA_DRQ ? "DRQ " : "", + res->command & ATA_SENSE ? "SENSE " : "", res->command & ATA_ERR ? "ERR " : ""); } diff --git a/include/linux/ata.h b/include/linux/ata.h index e797e1b53006..00aebc4c83ad 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -385,6 +385,8 @@ enum { SATA_SSP = 0x06, /* Software Settings Preservation */ SATA_DEVSLP = 0x09, /* Device Sleep */ + SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */ + /* feature values for SET_MAX */ ATA_SET_MAX_ADDR = 0x00, ATA_SET_MAX_PASSWD = 0x01, @@ -718,6 +720,20 @@ static inline bool ata_id_has_read_log_dma_ext(const u16 *id) return false; } +static inline bool ata_id_has_sense_reporting(const u16 *id) +{ + if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) + return false; + return id[ATA_ID_COMMAND_SET_3] & (1 << 6); +} + +static inline bool ata_id_sense_reporting_enabled(const u16 *id) +{ + if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) + return false; + return id[ATA_ID_COMMAND_SET_4] & (1 << 6); +} + /** * ata_id_major_version - get ATA level of drive * @id: Identify data -- GitLab From 5e6acd1c8c4dc9a7c16208aeac3de09151ee6233 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:43:56 +0200 Subject: [PATCH 1201/9938] libata-scsi: sanitize ata_gen_ata_sense() ata_to_sense_error() is called conditionally, so we should be generating a default sense if the condition is not met. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6dc2fadfd7c5..e331077ee446 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1074,6 +1074,12 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, &sb[1], &sb[2], &sb[3], verbose); sb[1] &= 0x0f; + } else { + /* Could not decode error */ + ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", + tf->command, qc->err_mask); + ata_scsi_set_sense(cmd, ABORTED_COMMAND, 0, 0); + return; } block = ata_tf_read_block(&qc->result_tf, dev); -- GitLab From cffd1ee991c566bca937392cfacdafbe3b7b58c6 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:43:57 +0200 Subject: [PATCH 1202/9938] libata: sanitize ata_tf_read_block() Return U64_MAX if ata_tf_read_block() could not decode the LBA address, and do not set the information sense descriptor in ata_gen_ata_sense() in these cases. tj: s/(u64)-1/U64_MAX/ Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 4 ++-- drivers/ata/libata-scsi.c | 2 ++ drivers/ata/libata.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f991f786227e..7bdb2c4e357f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -695,7 +695,7 @@ static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev) * RETURNS: * Block address read from @tf. */ -u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) +u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) { u64 block = 0; @@ -720,7 +720,7 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) if (!sect) { ata_dev_warn(dev, "device reported invalid CHS sector 0\n"); - sect = 1; /* oh well */ + return U64_MAX; } block = (cyl * dev->heads + head) * dev->sectors + sect - 1; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index e331077ee446..fc23d3f4282d 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1083,6 +1083,8 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) } block = ata_tf_read_block(&qc->result_tf, dev); + if (block == U64_MAX) + return; /* information sense data descriptor */ sb[7] = 12; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 8cfdd9616d16..507c22f7a63b 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -67,7 +67,8 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); -extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); +extern u64 ata_tf_read_block(const struct ata_taskfile *tf, + struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen, -- GitLab From cf8b49b0af39b8e8fa358623acda57f01251b6d4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:43:58 +0200 Subject: [PATCH 1203/9938] libata-scsi: use scsi_set_sense_information() Use scsi_set_sense_information() instead of hand-crafted function. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index fc23d3f4282d..47b103d9baac 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1055,7 +1055,6 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) struct scsi_cmnd *cmd = qc->scsicmd; struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; - unsigned char *desc = sb + 8; int verbose = qc->ap->ops->error_handler == NULL; u64 block; @@ -1086,18 +1085,7 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) if (block == U64_MAX) return; - /* information sense data descriptor */ - sb[7] = 12; - desc[0] = 0x00; - desc[1] = 10; - - desc[2] |= 0x80; /* valid */ - desc[6] = block >> 40; - desc[7] = block >> 32; - desc[8] = block >> 24; - desc[9] = block >> 16; - desc[10] = block >> 8; - desc[11] = block; + scsi_set_sense_information(sb, SCSI_SENSE_BUFFERSIZE, block); } static void ata_scsi_sdev_config(struct scsi_device *sdev) -- GitLab From 492bf62107347aca764070dbc9d412da6bda73d1 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:43:59 +0200 Subject: [PATCH 1204/9938] libata-eh: Set 'information' field for autosense If NCQ autosense or the sense data reporting feature is enabled the LBA of the offending command should be stored in the sense data 'information' field. tj: s/(u64)-1/U64_MAX/ Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-eh.c | 2 ++ drivers/ata/libata-scsi.c | 17 +++++++++++++++++ drivers/ata/libata.h | 3 +++ 3 files changed, 22 insertions(+) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 170e891e79af..e4e0e2e80c20 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1856,6 +1856,8 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) asc = (qc->result_tf.auxiliary >> 8) & 0xff; ascq = qc->result_tf.auxiliary & 0xff; ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq); + ata_scsi_set_sense_information(dev, qc->scsicmd, + &qc->result_tf); qc->flags |= ATA_QCFLAG_SENSE_VALID; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 47b103d9baac..97e8f6b0494c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -280,6 +280,23 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); } +void ata_scsi_set_sense_information(struct ata_device *dev, + struct scsi_cmnd *cmd, + const struct ata_taskfile *tf) +{ + u64 information; + + if (!cmd) + return; + + information = ata_tf_read_block(tf, dev); + if (information == U64_MAX) + return; + + scsi_set_sense_information(cmd->sense_buffer, + SCSI_SENSE_BUFFERSIZE, information); +} + static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 507c22f7a63b..dbc67604b3c5 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -139,6 +139,9 @@ extern int ata_scsi_add_hosts(struct ata_host *host, extern void ata_scsi_scan_host(struct ata_port *ap, int sync); extern int ata_scsi_offline_dev(struct ata_device *dev); extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq); +extern void ata_scsi_set_sense_information(struct ata_device *dev, + struct scsi_cmnd *cmd, + const struct ata_taskfile *tf); extern void ata_scsi_media_change_notify(struct ata_device *dev); extern void ata_scsi_hotplug(struct work_struct *work); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); -- GitLab From b525e7731b90ebc7a70a095fc5d5363408b94274 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:00 +0200 Subject: [PATCH 1205/9938] libata-scsi: use ata_scsi_set_sense() Use ata_scsi_set_sense() throughout to ensure the sense code format is consistent. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 97e8f6b0494c..3c33f32c04c4 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1000,6 +1000,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) unsigned char *sb = cmd->sense_buffer; unsigned char *desc = sb + 8; int verbose = qc->ap->ops->error_handler == NULL; + u8 sense_key, asc, ascq; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); @@ -1012,12 +1013,11 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) if (qc->err_mask || tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, - &sb[1], &sb[2], &sb[3], verbose); - sb[1] &= 0x0f; + &sense_key, &asc, &ascq, verbose); + ata_scsi_set_sense(cmd, sense_key, asc, ascq); } else { - sb[1] = RECOVERED_ERROR; - sb[2] = 0; - sb[3] = 0x1D; + /* ATA PASS-THROUGH INFORMATION AVAILABLE */ + ata_scsi_set_sense(cmd, RECOVERED_ERROR, 0, 0x1D); } /* @@ -1074,22 +1074,20 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) unsigned char *sb = cmd->sense_buffer; int verbose = qc->ap->ops->error_handler == NULL; u64 block; + u8 sense_key, asc, ascq; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* sense data is current and format is descriptor */ - sb[0] = 0x72; - /* Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ if (qc->err_mask || tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, - &sb[1], &sb[2], &sb[3], verbose); - sb[1] &= 0x0f; + &sense_key, &asc, &ascq, verbose); + ata_scsi_set_sense(cmd, sense_key, asc, ascq); } else { /* Could not decode error */ ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", -- GitLab From 3852e37382664a06cd006bb389a8223e32cedf45 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:01 +0200 Subject: [PATCH 1206/9938] libata: evaluate SCSI sense code Whenever a sense code is set it would need to be evaluated to update the error mask. tj: Cosmetic formatting updates. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-eh.c | 29 ++++++++++++++++++++--------- drivers/scsi/scsi_error.c | 3 ++- include/scsi/scsi_eh.h | 1 + 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index e4e0e2e80c20..e37258b78e01 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1920,20 +1920,31 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, tmp = atapi_eh_request_sense(qc->dev, qc->scsicmd->sense_buffer, qc->result_tf.feature >> 4); - if (!tmp) { - /* ATA_QCFLAG_SENSE_VALID is used to - * tell atapi_qc_complete() that sense - * data is already valid. - * - * TODO: interpret sense data and set - * appropriate err_mask. - */ + if (!tmp) qc->flags |= ATA_QCFLAG_SENSE_VALID; - } else + else qc->err_mask |= tmp; } } + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + int ret = scsi_check_sense(qc->scsicmd); + /* + * SUCCESS here means that the sense code could + * evaluated and should be passed to the upper layers + * for correct evaluation. + * FAILED means the sense code could not interpreted + * and the device would need to be reset. + * NEEDS_RETRY and ADD_TO_MLQUEUE means that the + * command would need to be retried. + */ + if (ret == NEEDS_RETRY || ret == ADD_TO_MLQUEUE) { + qc->flags |= ATA_QCFLAG_RETRY; + qc->err_mask |= AC_ERR_OTHER; + } else if (ret != SUCCESS) { + qc->err_mask |= AC_ERR_HSM; + } + } if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS)) action |= ATA_EH_RESET; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 984ddcb4786d..a8b610eaa0ca 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -452,7 +452,7 @@ static void scsi_report_sense(struct scsi_device *sdev, * When a deferred error is detected the current command has * not been executed and needs retrying. */ -static int scsi_check_sense(struct scsi_cmnd *scmd) +int scsi_check_sense(struct scsi_cmnd *scmd) { struct scsi_device *sdev = scmd->device; struct scsi_sense_hdr sshdr; @@ -602,6 +602,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) return SUCCESS; } } +EXPORT_SYMBOL_GPL(scsi_check_sense); static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) { diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index dbb8c640e26f..98d366b55770 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -16,6 +16,7 @@ extern void scsi_report_device_reset(struct Scsi_Host *, int, int); extern int scsi_block_when_processing_errors(struct scsi_device *); extern bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd, struct scsi_sense_hdr *sshdr); +extern int scsi_check_sense(struct scsi_cmnd *); static inline bool scsi_sense_is_deferred(const struct scsi_sense_hdr *sshdr) { -- GitLab From 11093cb1ef56147fe33f5750b1eab347bdef30db Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:02 +0200 Subject: [PATCH 1207/9938] libata-scsi: generate correct ATA pass-through sense Generate ATA pass-through sense for both fixed and descriptor format sense. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 93 +++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3c33f32c04c4..0da03c019f27 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1016,43 +1016,68 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) &sense_key, &asc, &ascq, verbose); ata_scsi_set_sense(cmd, sense_key, asc, ascq); } else { - /* ATA PASS-THROUGH INFORMATION AVAILABLE */ - ata_scsi_set_sense(cmd, RECOVERED_ERROR, 0, 0x1D); + /* + * ATA PASS-THROUGH INFORMATION AVAILABLE + * Always in descriptor format sense. + */ + scsi_build_sense_buffer(1, cmd->sense_buffer, + RECOVERED_ERROR, 0, 0x1D); } - /* - * Sense data is current and format is descriptor. - */ - sb[0] = 0x72; - - desc[0] = 0x09; - - /* set length of additional sense data */ - sb[7] = 14; - desc[1] = 12; - - /* - * Copy registers into sense buffer. - */ - desc[2] = 0x00; - desc[3] = tf->feature; /* == error reg */ - desc[5] = tf->nsect; - desc[7] = tf->lbal; - desc[9] = tf->lbam; - desc[11] = tf->lbah; - desc[12] = tf->device; - desc[13] = tf->command; /* == status reg */ + if ((cmd->sense_buffer[0] & 0x7f) >= 0x72) { + u8 len; + + /* descriptor format */ + len = sb[7]; + desc = (char *)scsi_sense_desc_find(sb, len + 8, 9); + if (!desc) { + if (SCSI_SENSE_BUFFERSIZE < len + 14) + return; + sb[7] = len + 14; + desc = sb + 8 + len; + } + desc[0] = 9; + desc[1] = 12; + /* + * Copy registers into sense buffer. + */ + desc[2] = 0x00; + desc[3] = tf->feature; /* == error reg */ + desc[5] = tf->nsect; + desc[7] = tf->lbal; + desc[9] = tf->lbam; + desc[11] = tf->lbah; + desc[12] = tf->device; + desc[13] = tf->command; /* == status reg */ - /* - * Fill in Extend bit, and the high order bytes - * if applicable. - */ - if (tf->flags & ATA_TFLAG_LBA48) { - desc[2] |= 0x01; - desc[4] = tf->hob_nsect; - desc[6] = tf->hob_lbal; - desc[8] = tf->hob_lbam; - desc[10] = tf->hob_lbah; + /* + * Fill in Extend bit, and the high order bytes + * if applicable. + */ + if (tf->flags & ATA_TFLAG_LBA48) { + desc[2] |= 0x01; + desc[4] = tf->hob_nsect; + desc[6] = tf->hob_lbal; + desc[8] = tf->hob_lbam; + desc[10] = tf->hob_lbah; + } + } else { + /* Fixed sense format */ + desc[0] = tf->feature; + desc[1] = tf->command; /* status */ + desc[2] = tf->device; + desc[3] = tf->nsect; + desc[0] = 0; + if (tf->flags & ATA_TFLAG_LBA48) { + desc[8] |= 0x80; + if (tf->hob_nsect) + desc[8] |= 0x40; + if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah) + desc[8] |= 0x20; + } + desc[9] = tf->lbal; + desc[10] = tf->lbam; + desc[11] = tf->lbah; } } -- GitLab From 06dbde5f3a44248fc02e24d662ac4849202abb48 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:03 +0200 Subject: [PATCH 1208/9938] libata: Implement control mode page to select sense format Implement MODE SELECT for the control mode page to allow the OS to switch to descriptor sense. tj: Dropped s/sb/cmd->sense_buffer/ in ata_gen_ata_sense(). Added @dev description to ata_msense_ctl_mode(). Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-eh.c | 4 +- drivers/ata/libata-scsi.c | 116 ++++++++++++++++++++++++++++---------- drivers/ata/libata.h | 3 +- include/linux/libata.h | 1 + 4 files changed, 91 insertions(+), 33 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index e37258b78e01..5b340ce4eeac 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1679,7 +1679,7 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc, err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); /* Ignore err_mask; ATA_ERR might be set */ if (tf.command & ATA_SENSE) { - ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal); + ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal); qc->flags |= ATA_QCFLAG_SENSE_VALID; } else { ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", @@ -1855,7 +1855,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; asc = (qc->result_tf.auxiliary >> 8) & 0xff; ascq = qc->result_tf.auxiliary & 0xff; - ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq); + ata_scsi_set_sense(dev, qc->scsicmd, sense_key, asc, ascq); ata_scsi_set_sense_information(dev, qc->scsicmd, &qc->result_tf); qc->flags |= ATA_QCFLAG_SENSE_VALID; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0da03c019f27..2389247bdf6f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -270,14 +270,17 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, ata_scsi_park_show, ata_scsi_park_store); EXPORT_SYMBOL_GPL(dev_attr_unload_heads); -void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) +void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, + u8 sk, u8 asc, u8 ascq) { + bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); + if (!cmd) return; cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); + scsi_build_sense_buffer(d_sense, cmd->sense_buffer, sk, asc, ascq); } void ata_scsi_set_sense_information(struct ata_device *dev, @@ -384,9 +387,10 @@ struct device_attribute *ata_common_sdev_attrs[] = { }; EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); -static void ata_scsi_invalid_field(struct scsi_cmnd *cmd) +static void ata_scsi_invalid_field(struct ata_device *dev, + struct scsi_cmnd *cmd) { - ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0); + ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ cmd->scsi_done(cmd); } @@ -1014,7 +1018,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, &sense_key, &asc, &ascq, verbose); - ata_scsi_set_sense(cmd, sense_key, asc, ascq); + ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq); } else { /* * ATA PASS-THROUGH INFORMATION AVAILABLE @@ -1112,12 +1116,12 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, &sense_key, &asc, &ascq, verbose); - ata_scsi_set_sense(cmd, sense_key, asc, ascq); + ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq); } else { /* Could not decode error */ ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", tf->command, qc->err_mask); - ata_scsi_set_sense(cmd, ABORTED_COMMAND, 0, 0); + ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); return; } @@ -1440,7 +1444,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ return 1; skip: @@ -1679,12 +1683,12 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ return 1; out_of_range: - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x0); /* "Logical Block Address out of range" */ return 1; @@ -1781,12 +1785,12 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto out_of_range; /* treat all other errors as -EINVAL, fall through */ invalid_fld: - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ return 1; out_of_range: - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x0); /* "Logical Block Address out of range" */ return 1; @@ -2358,6 +2362,7 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) /** * ata_msense_ctl_mode - Simulate MODE SENSE control mode page + * @dev: ATA device of interest * @buf: output buffer * @changeable: whether changeable parameters are requested * @@ -2366,9 +2371,12 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) * LOCKING: * None. */ -static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable) +static unsigned int ata_msense_ctl_mode(struct ata_device *dev, u8 *buf, + bool changeable) { modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); + if (changeable && (dev->flags & ATA_DFLAG_D_SENSE)) + buf[2] |= (1 << 2); /* Descriptor sense requested */ return sizeof(def_control_mpage); } @@ -2482,13 +2490,13 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) break; case CONTROL_MPAGE: - p += ata_msense_ctl_mode(p, page_control == 1); + p += ata_msense_ctl_mode(args->dev, p, page_control == 1); break; case ALL_MPAGES: p += ata_msense_rw_recovery(p, page_control == 1); p += ata_msense_caching(args->id, p, page_control == 1); - p += ata_msense_ctl_mode(p, page_control == 1); + p += ata_msense_ctl_mode(args->dev, p, page_control == 1); break; default: /* invalid page code */ @@ -2521,12 +2529,12 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) return 0; invalid_fld: - ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0); + ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ return 1; saving_not_supp: - ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0); + ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x39, 0x0); /* "Saving parameters not supported" */ return 1; } @@ -3163,7 +3171,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x00); + ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); /* "Invalid field in cdb" */ return 1; } @@ -3228,7 +3236,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x00); + ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); /* "Invalid field in cdb" */ return 1; } @@ -3279,6 +3287,51 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc, return 0; } +/** + * ata_mselect_control - Simulate MODE SELECT for control page + * @qc: Storage for translated ATA taskfile + * @buf: input buffer + * @len: number of valid bytes in the input buffer + * + * Prepare a taskfile to modify caching information for the device. + * + * LOCKING: + * None. + */ +static int ata_mselect_control(struct ata_queued_cmd *qc, + const u8 *buf, int len) +{ + struct ata_device *dev = qc->dev; + char mpage[CONTROL_MPAGE_LEN]; + u8 d_sense; + + /* + * The first two bytes of def_control_mpage are a header, so offsets + * in mpage are off by 2 compared to buf. Same for len. + */ + + if (len != CONTROL_MPAGE_LEN - 2) + return -EINVAL; + + d_sense = buf[0] & (1 << 2); + + /* + * Check that read-only bits are not modified. + */ + ata_msense_ctl_mode(dev, mpage, false); + mpage[2] &= ~(1 << 2); + mpage[2] |= d_sense; + if (memcmp(mpage + 2, buf, CONTROL_MPAGE_LEN - 2) != 0) + return -EINVAL; + if (d_sense & (1 << 2)) + dev->flags |= ATA_DFLAG_D_SENSE; + else + dev->flags &= ~ATA_DFLAG_D_SENSE; + qc->scsicmd->result = SAM_STAT_GOOD; + qc->scsicmd->scsi_done(qc->scsicmd); + return 0; +} + /** * ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands * @qc: Storage for translated ATA taskfile @@ -3381,7 +3434,10 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) if (ata_mselect_caching(qc, p, pg_len) < 0) goto invalid_param; break; - + case CONTROL_MPAGE: + if (ata_mselect_control(qc, p, pg_len) < 0) + goto invalid_param; + break; default: /* invalid page code */ goto invalid_param; } @@ -3397,17 +3453,17 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) invalid_fld: /* "Invalid field in CDB" */ - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); return 1; invalid_param: /* "Invalid field in parameter list" */ - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x26, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x26, 0x0); return 1; invalid_param_len: /* "Parameter list length error" */ - ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x1a, 0x0); + ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); return 1; skip: @@ -3611,12 +3667,12 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) switch(scsicmd[0]) { /* TODO: worth improving? */ case FORMAT_UNIT: - ata_scsi_invalid_field(cmd); + ata_scsi_invalid_field(dev, cmd); break; case INQUIRY: if (scsicmd[1] & 2) /* is CmdDt set? */ - ata_scsi_invalid_field(cmd); + ata_scsi_invalid_field(dev, cmd); else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); else switch (scsicmd[2]) { @@ -3642,7 +3698,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); break; default: - ata_scsi_invalid_field(cmd); + ata_scsi_invalid_field(dev, cmd); break; } break; @@ -3660,7 +3716,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); else - ata_scsi_invalid_field(cmd); + ata_scsi_invalid_field(dev, cmd); break; case REPORT_LUNS: @@ -3668,7 +3724,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) break; case REQUEST_SENSE: - ata_scsi_set_sense(cmd, 0, 0, 0); + ata_scsi_set_sense(dev, cmd, 0, 0, 0); cmd->result = (DRIVER_SENSE << 24); cmd->scsi_done(cmd); break; @@ -3692,12 +3748,12 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4])) ata_scsi_rbuf_fill(&args, ata_scsiop_noop); else - ata_scsi_invalid_field(cmd); + ata_scsi_invalid_field(dev, cmd); break; /* all other commands */ default: - ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0); + ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x20, 0x0); /* "Invalid command operation code" */ cmd->scsi_done(cmd); break; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index dbc67604b3c5..3b301a48007c 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -138,7 +138,8 @@ extern int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht); extern void ata_scsi_scan_host(struct ata_port *ap, int sync); extern int ata_scsi_offline_dev(struct ata_device *dev); -extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq); +extern void ata_scsi_set_sense(struct ata_device *dev, + struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq); extern void ata_scsi_set_sense_information(struct ata_device *dev, struct scsi_cmnd *cmd, const struct ata_taskfile *tf); diff --git a/include/linux/libata.h b/include/linux/libata.h index 2c4ebef79d0c..a418bca0df0d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -180,6 +180,7 @@ enum { ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */ ATA_DFLAG_DEVSLP = (1 << 27), /* device supports Device Sleep */ ATA_DFLAG_ACPI_DISABLED = (1 << 28), /* ACPI for the device is disabled */ + ATA_DFLAG_D_SENSE = (1 << 29), /* Descriptor sense requested */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ -- GitLab From 78db6e30281aa056a6773cb4def00afc158c097f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:04 +0200 Subject: [PATCH 1209/9938] scsi: add scsi_set_sense_field_pointer() Add a function to set the field pointer for SCSI sense codes. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/scsi/scsi_common.c | 53 ++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_common.h | 1 + 2 files changed, 54 insertions(+) diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index ce79de822e46..b1383a71400e 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -293,3 +293,56 @@ int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) return 0; } EXPORT_SYMBOL(scsi_set_sense_information); + +/** + * scsi_set_sense_field_pointer - set the field pointer sense key + * specific information in a formatted sense data buffer + * @buf: Where to build sense data + * @buf_len: buffer length + * @fp: field pointer to be set + * @bp: bit pointer to be set + * @cd: command/data bit + * + * Return value: + * 0 on success or EINVAL for invalid sense buffer length + */ +int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd) +{ + u8 *ucp, len; + + if ((buf[0] & 0x7f) == 0x72) { + len = buf[7]; + ucp = (char *)scsi_sense_desc_find(buf, len + 8, 2); + if (!ucp) { + buf[7] = len + 8; + ucp = buf + 8 + len; + } + + if (buf_len < len + 8) + /* Not enough room for info */ + return -EINVAL; + + ucp[0] = 2; + ucp[1] = 6; + ucp[4] = 0x80; /* Valid bit */ + if (cd) + ucp[4] |= 0x40; + if (bp < 0x8) + ucp[4] |= 0x8 | bp; + put_unaligned_be16(fp, &ucp[5]); + } else if ((buf[0] & 0x7f) == 0x70) { + len = buf[7]; + if (len < 18) + buf[7] = 18; + + buf[15] = 0x80; + if (cd) + buf[15] |= 0x40; + if (bp < 0x8) + buf[15] |= 0x8 | bp; + put_unaligned_be16(fp, &buf[16]); + } + + return 0; +} +EXPORT_SYMBOL(scsi_set_sense_field_pointer); diff --git a/include/scsi/scsi_common.h b/include/scsi/scsi_common.h index 11571b2a831e..20bf7eaef05a 100644 --- a/include/scsi/scsi_common.h +++ b/include/scsi/scsi_common.h @@ -63,6 +63,7 @@ extern bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); int scsi_set_sense_information(u8 *buf, int buf_len, u64 info); +int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd); extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, int desc_type); -- GitLab From bcfc867d467c98aba23ce0331455282936c04b73 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:05 +0200 Subject: [PATCH 1210/9938] libata-scsi: Set field pointer in sense code If the sense code is 'Invalid field in CDB' we should be setting the field pointer to the offending byte. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 155 ++++++++++++++++++++++++++------------ 1 file changed, 108 insertions(+), 47 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2389247bdf6f..062cb2eee8de 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -300,6 +300,15 @@ void ata_scsi_set_sense_information(struct ata_device *dev, SCSI_SENSE_BUFFERSIZE, information); } +static void ata_scsi_set_invalid_field(struct ata_device *dev, + struct scsi_cmnd *cmd, u16 field) +{ + ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); + /* "Invalid field in cbd" */ + scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, + field, 0xff, 1); +} + static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -388,10 +397,9 @@ struct device_attribute *ata_common_sdev_attrs[] = { EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); static void ata_scsi_invalid_field(struct ata_device *dev, - struct scsi_cmnd *cmd) + struct scsi_cmnd *cmd, u16 field) { - ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); - /* "Invalid field in cbd" */ + ata_scsi_set_invalid_field(dev, cmd, field); cmd->scsi_done(cmd); } @@ -1386,19 +1394,26 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; struct ata_taskfile *tf = &qc->tf; const u8 *cdb = scmd->cmnd; + u16 fp; - if (scmd->cmd_len < 5) + if (scmd->cmd_len < 5) { + fp = 4; goto invalid_fld; + } tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; tf->protocol = ATA_PROT_NODATA; if (cdb[1] & 0x1) { ; /* ignore IMMED bit, violates sat-r05 */ } - if (cdb[4] & 0x2) + if (cdb[4] & 0x2) { + fp = 4; goto invalid_fld; /* LOEJ bit set not supported */ - if (((cdb[4] >> 4) & 0xf) != 0) + } + if (((cdb[4] >> 4) & 0xf) != 0) { + fp = 4; goto invalid_fld; /* power conditions not supported */ + } if (cdb[4] & 0x1) { tf->nsect = 1; /* 1 sector, lba=0 */ @@ -1444,8 +1459,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); - /* "Invalid field in cbd" */ + ata_scsi_set_invalid_field(qc->dev, scmd, fp); return 1; skip: scmd->result = SAM_STAT_GOOD; @@ -1596,20 +1610,27 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) const u8 *cdb = scmd->cmnd; u64 block; u32 n_block; + u16 fp; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; if (cdb[0] == VERIFY) { - if (scmd->cmd_len < 10) + if (scmd->cmd_len < 10) { + fp = 9; goto invalid_fld; + } scsi_10_lba_len(cdb, &block, &n_block); } else if (cdb[0] == VERIFY_16) { - if (scmd->cmd_len < 16) + if (scmd->cmd_len < 16) { + fp = 15; goto invalid_fld; + } scsi_16_lba_len(cdb, &block, &n_block); - } else + } else { + fp = 0; goto invalid_fld; + } if (!n_block) goto nothing_to_do; @@ -1683,8 +1704,7 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); - /* "Invalid field in cbd" */ + ata_scsi_set_invalid_field(qc->dev, scmd, fp); return 1; out_of_range: @@ -1723,6 +1743,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) u64 block; u32 n_block; int rc; + u16 fp = 0; if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16) tf_flags |= ATA_TFLAG_WRITE; @@ -1731,16 +1752,20 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) switch (cdb[0]) { case READ_10: case WRITE_10: - if (unlikely(scmd->cmd_len < 10)) + if (unlikely(scmd->cmd_len < 10)) { + fp = 9; goto invalid_fld; + } scsi_10_lba_len(cdb, &block, &n_block); if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; break; case READ_6: case WRITE_6: - if (unlikely(scmd->cmd_len < 6)) + if (unlikely(scmd->cmd_len < 6)) { + fp = 5; goto invalid_fld; + } scsi_6_lba_len(cdb, &block, &n_block); /* for 6-byte r/w commands, transfer length 0 @@ -1751,14 +1776,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) break; case READ_16: case WRITE_16: - if (unlikely(scmd->cmd_len < 16)) + if (unlikely(scmd->cmd_len < 16)) { + fp = 15; goto invalid_fld; + } scsi_16_lba_len(cdb, &block, &n_block); if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; break; default: DPRINTK("no-byte command\n"); + fp = 0; goto invalid_fld; } @@ -1785,8 +1813,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto out_of_range; /* treat all other errors as -EINVAL, fall through */ invalid_fld: - ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); - /* "Invalid field in cbd" */ + ata_scsi_set_invalid_field(qc->dev, scmd, fp); return 1; out_of_range: @@ -2445,6 +2472,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) u8 pg, spg; unsigned int ebd, page_control, six_byte; u8 dpofua; + u16 fp; VPRINTK("ENTER\n"); @@ -2463,6 +2491,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) case 3: /* saved */ goto saving_not_supp; default: + fp = 2; goto invalid_fld; } @@ -2477,8 +2506,10 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) * No mode subpages supported (yet) but asking for _all_ * subpages may be valid */ - if (spg && (spg != ALL_SUB_MPAGES)) + if (spg && (spg != ALL_SUB_MPAGES)) { + fp = 3; goto invalid_fld; + } switch(pg) { case RW_RECOVERY_MPAGE: @@ -2500,6 +2531,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) break; default: /* invalid page code */ + fp = 2; goto invalid_fld; } @@ -2529,8 +2561,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) return 0; invalid_fld: - ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x24, 0x0); - /* "Invalid field in cbd" */ + ata_scsi_set_invalid_field(dev, args->cmd, fp); return 1; saving_not_supp: @@ -2991,9 +3022,12 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; struct ata_device *dev = qc->dev; const u8 *cdb = scmd->cmnd; + u16 fp; - if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) + if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) { + fp = 1; goto invalid_fld; + } /* enable LBA */ tf->flags |= ATA_TFLAG_LBA; @@ -3057,8 +3091,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) case ATA_CMD_READ_LONG_ONCE: case ATA_CMD_WRITE_LONG: case ATA_CMD_WRITE_LONG_ONCE: - if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) + if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) { + fp = 1; goto invalid_fld; + } qc->sect_size = scsi_bufflen(scmd); break; @@ -3121,12 +3157,16 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) ata_qc_set_pc_nbytes(qc); /* We may not issue DMA commands if no DMA mode is set */ - if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) + if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) { + fp = 1; goto invalid_fld; + } /* sanity check for pio multi commands */ - if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) + if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) { + fp = 1; goto invalid_fld; + } if (is_multi_taskfile(tf)) { unsigned int multi_count = 1 << (cdb[1] >> 5); @@ -3147,8 +3187,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * ->set_dmamode(), and ->post_set_mode() hooks). */ if (tf->command == ATA_CMD_SET_FEATURES && - tf->feature == SETFEATURES_XFER) + tf->feature == SETFEATURES_XFER) { + fp = (cdb[0] == ATA_16) ? 4 : 3; goto invalid_fld; + } /* * Filter TPM commands by default. These provide an @@ -3165,14 +3207,15 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * so that we comply with the TC consortium stated goal that the user * can turn off TC features of their system. */ - if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) + if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) { + fp = (cdb[0] == ATA_16) ? 14 : 9; goto invalid_fld; + } return 0; invalid_fld: - ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); - /* "Invalid field in cdb" */ + ata_scsi_set_invalid_field(dev, scmd, fp); return 1; } @@ -3186,25 +3229,30 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) u32 n_block; u32 size; void *buf; + u16 fp; /* we may not issue DMA commands if no DMA mode is set */ if (unlikely(!dev->dma_mode)) - goto invalid_fld; + goto invalid_opcode; - if (unlikely(scmd->cmd_len < 16)) + if (unlikely(scmd->cmd_len < 16)) { + fp = 15; goto invalid_fld; + } scsi_16_lba_len(cdb, &block, &n_block); /* for now we only support WRITE SAME with the unmap bit set */ - if (unlikely(!(cdb[1] & 0x8))) + if (unlikely(!(cdb[1] & 0x8))) { + fp = 1; goto invalid_fld; + } /* * WRITE SAME always has a sector sized buffer as payload, this * should never be a multiple entry S/G list. */ if (!scsi_sg_count(scmd)) - goto invalid_fld; + goto invalid_param_len; buf = page_address(sg_page(scsi_sglist(scmd))); size = ata_set_lba_range_entries(buf, 512, block, n_block); @@ -3235,9 +3283,16 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) return 0; - invalid_fld: - ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); - /* "Invalid field in cdb" */ +invalid_fld: + ata_scsi_set_invalid_field(dev, scmd, fp); + return 1; +invalid_param_len: + /* "Parameter list length error" */ + ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); + return 1; +invalid_opcode: + /* "Invalid command operation code" */ + ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0); return 1; } @@ -3351,27 +3406,34 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; int len; + u16 fp; VPRINTK("ENTER\n"); six_byte = (cdb[0] == MODE_SELECT); if (six_byte) { - if (scmd->cmd_len < 5) + if (scmd->cmd_len < 5) { + fp = 4; goto invalid_fld; + } len = cdb[4]; hdr_len = 4; } else { - if (scmd->cmd_len < 9) + if (scmd->cmd_len < 9) { + fp = 8; goto invalid_fld; + } len = (cdb[7] << 8) + cdb[8]; hdr_len = 8; } /* We only support PF=1, SP=0. */ - if ((cdb[1] & 0x11) != 0x10) + if ((cdb[1] & 0x11) != 0x10) { + fp = 1; goto invalid_fld; + } /* Test early for possible overrun. */ if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) @@ -3452,8 +3514,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - /* "Invalid field in CDB" */ - ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); + ata_scsi_set_invalid_field(qc->dev, scmd, fp); return 1; invalid_param: @@ -3667,12 +3728,12 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) switch(scsicmd[0]) { /* TODO: worth improving? */ case FORMAT_UNIT: - ata_scsi_invalid_field(dev, cmd); + ata_scsi_invalid_field(dev, cmd, 0); break; case INQUIRY: - if (scsicmd[1] & 2) /* is CmdDt set? */ - ata_scsi_invalid_field(dev, cmd); + if (scsicmd[1] & 2) /* is CmdDt set? */ + ata_scsi_invalid_field(dev, cmd, 1); else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); else switch (scsicmd[2]) { @@ -3698,7 +3759,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); break; default: - ata_scsi_invalid_field(dev, cmd); + ata_scsi_invalid_field(dev, cmd, 2); break; } break; @@ -3716,7 +3777,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); else - ata_scsi_invalid_field(dev, cmd); + ata_scsi_invalid_field(dev, cmd, 1); break; case REPORT_LUNS: @@ -3748,7 +3809,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4])) ata_scsi_rbuf_fill(&args, ata_scsiop_noop); else - ata_scsi_invalid_field(dev, cmd); + ata_scsi_invalid_field(dev, cmd, 1); break; /* all other commands */ -- GitLab From 0df10b84af88a482beea982f5f27a2e42157f600 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:06 +0200 Subject: [PATCH 1211/9938] libata-scsi: set bit pointer for sense code information When generating a sense code of 'Invalid field in CDB' we should be setting the bit pointer where appropriate. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 062cb2eee8de..339a373250f3 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -301,12 +301,12 @@ void ata_scsi_set_sense_information(struct ata_device *dev, } static void ata_scsi_set_invalid_field(struct ata_device *dev, - struct scsi_cmnd *cmd, u16 field) + struct scsi_cmnd *cmd, u16 field, u8 bit) { ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, - field, 0xff, 1); + field, bit, 1); } static ssize_t @@ -399,7 +399,7 @@ EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); static void ata_scsi_invalid_field(struct ata_device *dev, struct scsi_cmnd *cmd, u16 field) { - ata_scsi_set_invalid_field(dev, cmd, field); + ata_scsi_set_invalid_field(dev, cmd, field, 0xff); cmd->scsi_done(cmd); } @@ -1395,6 +1395,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) struct ata_taskfile *tf = &qc->tf; const u8 *cdb = scmd->cmnd; u16 fp; + u8 bp = 0xff; if (scmd->cmd_len < 5) { fp = 4; @@ -1408,10 +1409,12 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) } if (cdb[4] & 0x2) { fp = 4; + bp = 1; goto invalid_fld; /* LOEJ bit set not supported */ } if (((cdb[4] >> 4) & 0xf) != 0) { fp = 4; + bp = 3; goto invalid_fld; /* power conditions not supported */ } @@ -1459,7 +1462,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_invalid_field(qc->dev, scmd, fp); + ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp); return 1; skip: scmd->result = SAM_STAT_GOOD; @@ -1704,7 +1707,7 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_invalid_field(qc->dev, scmd, fp); + ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff); return 1; out_of_range: @@ -1813,7 +1816,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto out_of_range; /* treat all other errors as -EINVAL, fall through */ invalid_fld: - ata_scsi_set_invalid_field(qc->dev, scmd, fp); + ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff); return 1; out_of_range: @@ -2471,7 +2474,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) }; u8 pg, spg; unsigned int ebd, page_control, six_byte; - u8 dpofua; + u8 dpofua, bp = 0xff; u16 fp; VPRINTK("ENTER\n"); @@ -2492,6 +2495,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) goto saving_not_supp; default: fp = 2; + bp = 6; goto invalid_fld; } @@ -2561,7 +2565,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) return 0; invalid_fld: - ata_scsi_set_invalid_field(dev, args->cmd, fp); + ata_scsi_set_invalid_field(dev, args->cmd, fp, bp); return 1; saving_not_supp: @@ -3215,7 +3219,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_invalid_field(dev, scmd, fp); + ata_scsi_set_invalid_field(dev, scmd, fp, 0xff); return 1; } @@ -3230,6 +3234,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) u32 size; void *buf; u16 fp; + u8 bp = 0xff; /* we may not issue DMA commands if no DMA mode is set */ if (unlikely(!dev->dma_mode)) @@ -3244,6 +3249,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) /* for now we only support WRITE SAME with the unmap bit set */ if (unlikely(!(cdb[1] & 0x8))) { fp = 1; + bp = 3; goto invalid_fld; } @@ -3284,7 +3290,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_invalid_field(dev, scmd, fp); + ata_scsi_set_invalid_field(dev, scmd, fp, bp); return 1; invalid_param_len: /* "Parameter list length error" */ @@ -3407,6 +3413,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) unsigned six_byte, pg_len, hdr_len, bd_len; int len; u16 fp; + u8 bp; VPRINTK("ENTER\n"); @@ -3432,6 +3439,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) /* We only support PF=1, SP=0. */ if ((cdb[1] & 0x11) != 0x10) { fp = 1; + bp = (cdb[1] & 0x01) ? 1 : 5; goto invalid_fld; } @@ -3514,7 +3522,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) return 0; invalid_fld: - ata_scsi_set_invalid_field(qc->dev, scmd, fp); + ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp); return 1; invalid_param: -- GitLab From 7780081c1f04a4ea31331b5579ca010cc1f26c74 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 4 Apr 2016 11:44:07 +0200 Subject: [PATCH 1212/9938] libata-scsi: Set information sense field for invalid parameter Whenever the sense key is set to 'invalid parameter' we should be filling out the sense-key specific information field in the sense buffer. tj: Added description of @fp for ata_mselect_*(). Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 81 +++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 339a373250f3..8b61d63ab0be 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -309,6 +309,15 @@ static void ata_scsi_set_invalid_field(struct ata_device *dev, field, bit, 1); } +static void ata_scsi_set_invalid_parameter(struct ata_device *dev, + struct scsi_cmnd *cmd, u16 field) +{ + /* "Invalid field in parameter list" */ + ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x26, 0x0); + scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, + field, 0xff, 0); +} + static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -3307,6 +3316,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) * @qc: Storage for translated ATA taskfile * @buf: input buffer * @len: number of valid bytes in the input buffer + * @fp: out parameter for the failed field on error * * Prepare a taskfile to modify caching information for the device. * @@ -3314,20 +3324,26 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) * None. */ static int ata_mselect_caching(struct ata_queued_cmd *qc, - const u8 *buf, int len) + const u8 *buf, int len, u16 *fp) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; char mpage[CACHE_MPAGE_LEN]; u8 wce; + int i; /* * The first two bytes of def_cache_mpage are a header, so offsets * in mpage are off by 2 compared to buf. Same for len. */ - if (len != CACHE_MPAGE_LEN - 2) + if (len != CACHE_MPAGE_LEN - 2) { + if (len < CACHE_MPAGE_LEN - 2) + *fp = len; + else + *fp = CACHE_MPAGE_LEN - 2; return -EINVAL; + } wce = buf[0] & (1 << 2); @@ -3335,10 +3351,14 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc, * Check that read-only bits are not modified. */ ata_msense_caching(dev->id, mpage, false); - mpage[2] &= ~(1 << 2); - mpage[2] |= wce; - if (memcmp(mpage + 2, buf, CACHE_MPAGE_LEN - 2) != 0) - return -EINVAL; + for (i = 0; i < CACHE_MPAGE_LEN - 2; i++) { + if (i == 0) + continue; + if (mpage[i + 2] != buf[i]) { + *fp = i; + return -EINVAL; + } + } tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; tf->protocol = ATA_PROT_NODATA; @@ -3353,6 +3373,7 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc, * @qc: Storage for translated ATA taskfile * @buf: input buffer * @len: number of valid bytes in the input buffer + * @fp: out parameter for the failed field on error * * Prepare a taskfile to modify caching information for the device. * @@ -3360,19 +3381,25 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc, * None. */ static int ata_mselect_control(struct ata_queued_cmd *qc, - const u8 *buf, int len) + const u8 *buf, int len, u16 *fp) { struct ata_device *dev = qc->dev; char mpage[CONTROL_MPAGE_LEN]; u8 d_sense; + int i; /* * The first two bytes of def_control_mpage are a header, so offsets * in mpage are off by 2 compared to buf. Same for len. */ - if (len != CONTROL_MPAGE_LEN - 2) + if (len != CONTROL_MPAGE_LEN - 2) { + if (len < CONTROL_MPAGE_LEN - 2) + *fp = len; + else + *fp = CONTROL_MPAGE_LEN - 2; return -EINVAL; + } d_sense = buf[0] & (1 << 2); @@ -3380,10 +3407,14 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, * Check that read-only bits are not modified. */ ata_msense_ctl_mode(dev, mpage, false); - mpage[2] &= ~(1 << 2); - mpage[2] |= d_sense; - if (memcmp(mpage + 2, buf, CONTROL_MPAGE_LEN - 2) != 0) - return -EINVAL; + for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) { + if (i == 0) + continue; + if (mpage[2 + i] != buf[i]) { + *fp = i; + return -EINVAL; + } + } if (d_sense & (1 << 2)) dev->flags |= ATA_DFLAG_D_SENSE; else @@ -3412,8 +3443,8 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; int len; - u16 fp; - u8 bp; + u16 fp = (u16)-1; + u8 bp = 0xff; VPRINTK("ENTER\n"); @@ -3462,8 +3493,11 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) p += hdr_len; if (len < bd_len) goto invalid_param_len; - if (bd_len != 0 && bd_len != 8) + if (bd_len != 0 && bd_len != 8) { + fp = (six_byte) ? 3 : 6; + fp += bd_len + hdr_len; goto invalid_param; + } len -= bd_len; p += bd_len; @@ -3494,21 +3528,29 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) * No mode subpages supported (yet) but asking for _all_ * subpages may be valid */ - if (spg && (spg != ALL_SUB_MPAGES)) + if (spg && (spg != ALL_SUB_MPAGES)) { + fp = (p[0] & 0x40) ? 1 : 0; + fp += hdr_len + bd_len; goto invalid_param; + } if (pg_len > len) goto invalid_param_len; switch (pg) { case CACHE_MPAGE: - if (ata_mselect_caching(qc, p, pg_len) < 0) + if (ata_mselect_caching(qc, p, pg_len, &fp) < 0) { + fp += hdr_len + bd_len; goto invalid_param; + } break; case CONTROL_MPAGE: - if (ata_mselect_control(qc, p, pg_len) < 0) + if (ata_mselect_control(qc, p, pg_len, &fp) < 0) { + fp += hdr_len + bd_len; goto invalid_param; + } break; default: /* invalid page code */ + fp = bd_len + hdr_len; goto invalid_param; } @@ -3526,8 +3568,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) return 1; invalid_param: - /* "Invalid field in parameter list" */ - ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x26, 0x0); + ata_scsi_set_invalid_parameter(qc->dev, scmd, fp); return 1; invalid_param_len: -- GitLab From 4113652252fad972e0c191b1e536dc74a6faebdc Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 1 Apr 2016 21:38:16 +0200 Subject: [PATCH 1213/9938] reset: Add missing function stub for device_reset The Mediatek's thermal driver fails to compile when the RESET_CONTROLLER option is not set. Logically, as the driver depends on this option to compile, the Kconfig should select it but actually that is not correct because the Kconfig provides also the COMPILE_TEST to increase the compile test coverage. By providing the missing 'device_reset' stub for the driver in reset.h, that let the kernel to compile on different platforms with the Mediatek thermal driver enabled with the COMPILE_TEST option. Signed-off-by: Daniel Lezcano Signed-off-by: Philipp Zabel --- include/linux/reset.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/reset.h b/include/linux/reset.h index a552134a209e..ec0306ce7b92 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -56,6 +56,12 @@ static inline void reset_control_put(struct reset_control *rstc) WARN_ON(1); } +static inline int __must_check device_reset(struct device *dev) +{ + WARN_ON(1); + return -ENOTSUPP; +} + static inline int device_reset_optional(struct device *dev) { return -ENOTSUPP; -- GitLab From 974e0a4537f556867483f493c7f67ccdcb7fc504 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 4 Apr 2016 12:17:09 -0400 Subject: [PATCH 1214/9938] libata-core: Allow longer timeout for drive spinup from PUIS When spinning up a drive from powered on standby mode (PUIS), SETFEATURES_SPINUP is executed with the default timeout used for any SETFEATURES subcommand, that is 5+10 seconds. The total 15s is too short for some drives to complete spinup (e.g. drives with a large indirection table stored on media), resulting in ata_dev_read_id to fail twice on the execution of SETFEATURES_SPINUP. For this feature, allow a larger default timeout of 30 seconds. However, in the same spirit as with the timeout of other feature subcommands, do not ignore ata_probe_timeout if it is set). Signed-off-by: Damien Le Moal Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 6 +++++- include/linux/ata.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 55e257c268dd..7b21021dbf7d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4528,6 +4528,7 @@ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature) { struct ata_taskfile tf; unsigned int err_mask; + unsigned long timeout = 0; /* set up set-features taskfile */ DPRINTK("set features - SATA features\n"); @@ -4539,7 +4540,10 @@ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature) tf.protocol = ATA_PROT_NODATA; tf.nsect = feature; - err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + if (enable == SETFEATURES_SPINUP) + timeout = ata_probe_timeout ? + ata_probe_timeout * 1000 : SETFEATURES_SPINUP_TIMEOUT; + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, timeout); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; diff --git a/include/linux/ata.h b/include/linux/ata.h index c1a2f345cbe6..f310ec0f072e 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -371,7 +371,8 @@ enum { SETFEATURES_AAM_ON = 0x42, SETFEATURES_AAM_OFF = 0xC2, - SETFEATURES_SPINUP = 0x07, /* Spin-up drive */ + SETFEATURES_SPINUP = 0x07, /* Spin-up drive */ + SETFEATURES_SPINUP_TIMEOUT = 30000, /* 30s timeout for drive spin-up from PUIS */ SETFEATURES_SATA_ENABLE = 0x10, /* Enable use of SATA feature */ SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */ -- GitLab From 2d4d689f3ec56ad1eca6c899f418aeb6c0cf43ca Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 14:26:34 +0200 Subject: [PATCH 1215/9938] dmaengine: hsu: allow more than 3 descriptors Current code allows only up to 3 descriptors to be programmed to the hardware since it is used wrong calculations. Change % to min_t() to allow as many descriptors as user supplied. At once it could be programmed up to 4 descriptors due to hardware limitations. The issue was found under stress test, so it might not bother ordinary users. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/hsu/hsu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index eef145edb936..6fce5ed2fc40 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -77,8 +77,8 @@ static void hsu_dma_chan_start(struct hsu_dma_chan *hsuc) hsu_chan_writel(hsuc, HSU_CH_MTSR, mtsr); /* Set descriptors */ - count = (desc->nents - desc->active) % HSU_DMA_CHAN_NR_DESC; - for (i = 0; i < count; i++) { + count = desc->nents - desc->active; + for (i = 0; i < count && i < HSU_DMA_CHAN_NR_DESC; i++) { hsu_chan_writel(hsuc, HSU_CH_DxSAR(i), desc->sg[i].addr); hsu_chan_writel(hsuc, HSU_CH_DxTSR(i), desc->sg[i].len); -- GitLab From c36a0176ba678fd1a4bf985fd62f43dd4f4d4a03 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 14:26:35 +0200 Subject: [PATCH 1216/9938] dmaengine: hsu: don't check direction of timeouted channel The timeout capability is only available on the so called DMA write channels, i.e. associated with UART Rx FIFO. It means we don't need to check the direction of the channel to handle timeouts. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/hsu/hsu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index 6fce5ed2fc40..1817b7bc9576 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -160,7 +160,7 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr) return IRQ_NONE; /* Timeout IRQ, need wait some time, see Errata 2 */ - if (hsuc->direction == DMA_DEV_TO_MEM && (sr & HSU_CH_SR_DESCTO_ANY)) + if (sr & HSU_CH_SR_DESCTO_ANY) udelay(2); sr &= ~HSU_CH_SR_DESCTO_ANY; -- GitLab From 17b3cf4233d77698df0e5ff39303c145ac355d6a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 14:26:36 +0200 Subject: [PATCH 1217/9938] dmaengine: hsu: set maximum allowed segment size for DMA This tells, for example, IOMMU what the maximum size of a segment the DMA controller can send. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/hsu/hsu.c | 2 ++ drivers/dma/hsu/hsu.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index 1817b7bc9576..59d1e7c6fd0f 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -417,6 +417,8 @@ int hsu_dma_probe(struct hsu_dma_chip *chip) hsu->dma.dev = chip->dev; + dma_set_max_seg_size(hsu->dma.dev, HSU_CH_DxTSR_MASK); + ret = dma_async_device_register(&hsu->dma); if (ret) return ret; diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h index 578a8ee8cd05..50a9d1bda253 100644 --- a/drivers/dma/hsu/hsu.h +++ b/drivers/dma/hsu/hsu.h @@ -55,6 +55,10 @@ #define HSU_CH_DCR_CHEI BIT(23) #define HSU_CH_DCR_CHTOI(x) BIT(24 + (x)) +/* Bits in HSU_CH_DxTSR */ +#define HSU_CH_DxTSR_MASK GENMASK(15, 0) +#define HSU_CH_DxTSR_TSR(x) ((x) & HSU_CH_DxTSR_MASK) + struct hsu_dma_sg { dma_addr_t addr; unsigned int len; -- GitLab From 237ec70903bcf50768138b6c663c67ef1f946cc8 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Fri, 18 Mar 2016 14:57:19 +0100 Subject: [PATCH 1218/9938] dmaengine: mpc512x: Fix hanging DMA device transfer for MPC8308 Since the MPC8308 has no external request lines to initiate DMA transfers, all transfers must be triggered by software. Because of this, the current implementation of DMA transfers from and to devices on MPC8308 SoCs using major and minor loops is faulty: After the completion of the first major loop, the DMA engine resets the start flag in the channel's TCD, thus halting the transfer. The driver would have to set the start bit again to trigger the next iteration of the major loop; on MPC512x SoCs, this is done via the external request lines, so in this case, the driver doesn't have to interfer in any way. This has the effect that on MPC8308s, every DMA transfer to or from a device hangs after executing the first major loop. The patch fixes this behavior by using just one major loop for the whole DMA transfer on MPC8308s. Signed-off-by: Mario Six Signed-off-by: Vinod Koul --- drivers/dma/mpc512x_dma.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index aae76fb39adc..3a9104a1041c 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -760,21 +760,31 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, tcd->ssize = MPC_DMA_TSIZE_4; tcd->dsize = MPC_DMA_TSIZE_4; - len = sg_dma_len(sg); - tcd->nbytes = tcd_nunits * 4; - if (!IS_ALIGNED(len, tcd->nbytes)) - goto err_prep; - - iter = len / tcd->nbytes; - if (iter >= 1 << 15) { - /* len is too big */ - goto err_prep; + if (mdma->is_mpc8308) { + tcd->nbytes = sg_dma_len(sg); + if (!IS_ALIGNED(tcd->nbytes, 4)) + goto err_prep; + + /* No major loops for MPC8303 */ + tcd->biter = 1; + tcd->citer = 1; + } else { + len = sg_dma_len(sg); + tcd->nbytes = tcd_nunits * 4; + if (!IS_ALIGNED(len, tcd->nbytes)) + goto err_prep; + + iter = len / tcd->nbytes; + if (iter >= 1 << 15) { + /* len is too big */ + goto err_prep; + } + /* citer_linkch contains the high bits of iter */ + tcd->biter = iter & 0x1ff; + tcd->biter_linkch = iter >> 9; + tcd->citer = tcd->biter; + tcd->citer_linkch = tcd->biter_linkch; } - /* citer_linkch contains the high bits of iter */ - tcd->biter = iter & 0x1ff; - tcd->biter_linkch = iter >> 9; - tcd->citer = tcd->biter; - tcd->citer_linkch = tcd->biter_linkch; tcd->e_sg = 0; tcd->d_req = 1; -- GitLab From 899ed9dd4f2d007dfad66cd074b8ff26a0894ae8 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Fri, 18 Mar 2016 14:57:20 +0100 Subject: [PATCH 1219/9938] dmaengine: mpc512x: Implement additional chunk sizes for DMA transfers This patch extends the capabilities of the driver to handle DMA transfers to and from devices of 1, 2, 4, 16 (for MPC512x), and 32 byte widths. Signed-off-by: Mario Six Signed-off-by: Vinod Koul --- drivers/dma/mpc512x_dma.c | 112 ++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 36 deletions(-) diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 3a9104a1041c..1a161a8d68f3 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -3,6 +3,7 @@ * Copyright (C) Semihalf 2009 * Copyright (C) Ilya Yanok, Emcraft Systems 2010 * Copyright (C) Alexander Popov, Promcontroller 2014 + * Copyright (C) Mario Six, Guntermann & Drunck GmbH, 2016 * * Written by Piotr Ziecik . Hardware description * (defines, structures and comments) was taken from MPC5121 DMA driver @@ -26,18 +27,19 @@ */ /* - * MPC512x and MPC8308 DMA driver. It supports - * memory to memory data transfers (tested using dmatest module) and - * data transfers between memory and peripheral I/O memory - * by means of slave scatter/gather with these limitations: - * - chunked transfers (described by s/g lists with more than one item) - * are refused as long as proper support for scatter/gather is missing; - * - transfers on MPC8308 always start from software as this SoC appears - * not to have external request lines for peripheral flow control; - * - only peripheral devices with 4-byte FIFO access register are supported; - * - minimal memory <-> I/O memory transfer chunk is 4 bytes and consequently - * source and destination addresses must be 4-byte aligned - * and transfer size must be aligned on (4 * maxburst) boundary; + * MPC512x and MPC8308 DMA driver. It supports memory to memory data transfers + * (tested using dmatest module) and data transfers between memory and + * peripheral I/O memory by means of slave scatter/gather with these + * limitations: + * - chunked transfers (described by s/g lists with more than one item) are + * refused as long as proper support for scatter/gather is missing + * - transfers on MPC8308 always start from software as this SoC does not have + * external request lines for peripheral flow control + * - memory <-> I/O memory transfer chunks of sizes of 1, 2, 4, 16 (for + * MPC512x), and 32 bytes are supported, and, consequently, source + * addresses and destination addresses must be aligned accordingly; + * furthermore, for MPC512x SoCs, the transfer size must be aligned on + * (chunk size * maxburst) */ #include @@ -213,8 +215,10 @@ struct mpc_dma_chan { /* Settings for access to peripheral FIFO */ dma_addr_t src_per_paddr; u32 src_tcd_nunits; + u8 swidth; dma_addr_t dst_per_paddr; u32 dst_tcd_nunits; + u8 dwidth; /* Lock for this structure */ spinlock_t lock; @@ -684,6 +688,15 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, return &mdesc->desc; } +inline u8 buswidth_to_dmatsize(u8 buswidth) +{ + u8 res; + + for (res = 0; buswidth > 1; buswidth /= 2) + res++; + return res; +} + static struct dma_async_tx_descriptor * mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, @@ -742,27 +755,32 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, memset(tcd, 0, sizeof(struct mpc_dma_tcd)); - if (!IS_ALIGNED(sg_dma_address(sg), 4)) - goto err_prep; - if (direction == DMA_DEV_TO_MEM) { tcd->saddr = per_paddr; tcd->daddr = sg_dma_address(sg); + + if (!IS_ALIGNED(sg_dma_address(sg), mchan->dwidth)) + goto err_prep; + tcd->soff = 0; - tcd->doff = 4; + tcd->doff = mchan->dwidth; } else { tcd->saddr = sg_dma_address(sg); tcd->daddr = per_paddr; - tcd->soff = 4; + + if (!IS_ALIGNED(sg_dma_address(sg), mchan->swidth)) + goto err_prep; + + tcd->soff = mchan->swidth; tcd->doff = 0; } - tcd->ssize = MPC_DMA_TSIZE_4; - tcd->dsize = MPC_DMA_TSIZE_4; + tcd->ssize = buswidth_to_dmatsize(mchan->swidth); + tcd->dsize = buswidth_to_dmatsize(mchan->dwidth); if (mdma->is_mpc8308) { tcd->nbytes = sg_dma_len(sg); - if (!IS_ALIGNED(tcd->nbytes, 4)) + if (!IS_ALIGNED(tcd->nbytes, mchan->swidth)) goto err_prep; /* No major loops for MPC8303 */ @@ -770,7 +788,7 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, tcd->citer = 1; } else { len = sg_dma_len(sg); - tcd->nbytes = tcd_nunits * 4; + tcd->nbytes = tcd_nunits * tcd->ssize; if (!IS_ALIGNED(len, tcd->nbytes)) goto err_prep; @@ -806,40 +824,62 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return NULL; } +inline bool is_buswidth_valid(u8 buswidth, bool is_mpc8308) +{ + switch (buswidth) { + case 16: + if (is_mpc8308) + return false; + case 1: + case 2: + case 4: + case 32: + break; + default: + return false; + } + + return true; +} + static int mpc_dma_device_config(struct dma_chan *chan, struct dma_slave_config *cfg) { struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan); + struct mpc_dma *mdma = dma_chan_to_mpc_dma(&mchan->chan); unsigned long flags; /* * Software constraints: - * - only transfers between a peripheral device and - * memory are supported; - * - only peripheral devices with 4-byte FIFO access register - * are supported; - * - minimal transfer chunk is 4 bytes and consequently - * source and destination addresses must be 4-byte aligned - * and transfer size must be aligned on (4 * maxburst) - * boundary; - * - during the transfer RAM address is being incremented by - * the size of minimal transfer chunk; - * - peripheral port's address is constant during the transfer. + * - only transfers between a peripheral device and memory are + * supported + * - transfer chunk sizes of 1, 2, 4, 16 (for MPC512x), and 32 bytes + * are supported, and, consequently, source addresses and + * destination addresses; must be aligned accordingly; furthermore, + * for MPC512x SoCs, the transfer size must be aligned on (chunk + * size * maxburst) + * - during the transfer, the RAM address is incremented by the size + * of transfer chunk + * - the peripheral port's address is constant during the transfer. */ - if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES || - cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES || - !IS_ALIGNED(cfg->src_addr, 4) || - !IS_ALIGNED(cfg->dst_addr, 4)) { + if (!IS_ALIGNED(cfg->src_addr, cfg->src_addr_width) || + !IS_ALIGNED(cfg->dst_addr, cfg->dst_addr_width)) { return -EINVAL; } + if (!is_buswidth_valid(cfg->src_addr_width, mdma->is_mpc8308) || + !is_buswidth_valid(cfg->dst_addr_width, mdma->is_mpc8308)) + return -EINVAL; + spin_lock_irqsave(&mchan->lock, flags); mchan->src_per_paddr = cfg->src_addr; mchan->src_tcd_nunits = cfg->src_maxburst; + mchan->swidth = cfg->src_addr_width; mchan->dst_per_paddr = cfg->dst_addr; mchan->dst_tcd_nunits = cfg->dst_maxburst; + mchan->dwidth = cfg->dst_addr_width; /* Apply defaults */ if (mchan->src_tcd_nunits == 0) -- GitLab From 77fc397661e714c2bc4f96ae38f6776c15cc85ab Mon Sep 17 00:00:00 2001 From: Mario Six Date: Fri, 18 Mar 2016 14:57:21 +0100 Subject: [PATCH 1220/9938] dmaengine: mpc512x: Fix code style Signed-off-by: Mario Six Signed-off-by: Vinod Koul --- drivers/dma/mpc512x_dma.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 1a161a8d68f3..ccadafa51d5e 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -251,6 +251,7 @@ static inline struct mpc_dma_chan *dma_chan_to_mpc_dma_chan(struct dma_chan *c) static inline struct mpc_dma *dma_chan_to_mpc_dma(struct dma_chan *c) { struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(c); + return container_of(mchan, struct mpc_dma, channels[c->chan_id]); } @@ -258,9 +259,9 @@ static inline struct mpc_dma *dma_chan_to_mpc_dma(struct dma_chan *c) * Execute all queued DMA descriptors. * * Following requirements must be met while calling mpc_dma_execute(): - * a) mchan->lock is acquired, - * b) mchan->active list is empty, - * c) mchan->queued list contains at least one entry. + * a) mchan->lock is acquired, + * b) mchan->active list is empty, + * c) mchan->queued list contains at least one entry. */ static void mpc_dma_execute(struct mpc_dma_chan *mchan) { @@ -450,20 +451,15 @@ static void mpc_dma_tasklet(unsigned long data) if (es & MPC_DMA_DMAES_SAE) dev_err(mdma->dma.dev, "- Source Address Error\n"); if (es & MPC_DMA_DMAES_SOE) - dev_err(mdma->dma.dev, "- Source Offset" - " Configuration Error\n"); + dev_err(mdma->dma.dev, "- Source Offset Configuration Error\n"); if (es & MPC_DMA_DMAES_DAE) - dev_err(mdma->dma.dev, "- Destination Address" - " Error\n"); + dev_err(mdma->dma.dev, "- Destination Address Error\n"); if (es & MPC_DMA_DMAES_DOE) - dev_err(mdma->dma.dev, "- Destination Offset" - " Configuration Error\n"); + dev_err(mdma->dma.dev, "- Destination Offset Configuration Error\n"); if (es & MPC_DMA_DMAES_NCE) - dev_err(mdma->dma.dev, "- NBytes/Citter" - " Configuration Error\n"); + dev_err(mdma->dma.dev, "- NBytes/Citter Configuration Error\n"); if (es & MPC_DMA_DMAES_SGE) - dev_err(mdma->dma.dev, "- Scatter/Gather" - " Configuration Error\n"); + dev_err(mdma->dma.dev, "- Scatter/Gather Configuration Error\n"); if (es & MPC_DMA_DMAES_SBE) dev_err(mdma->dma.dev, "- Source Bus Error\n"); if (es & MPC_DMA_DMAES_DBE) @@ -522,8 +518,8 @@ static int mpc_dma_alloc_chan_resources(struct dma_chan *chan) for (i = 0; i < MPC_DMA_DESCRIPTORS; i++) { mdesc = kzalloc(sizeof(struct mpc_dma_desc), GFP_KERNEL); if (!mdesc) { - dev_notice(mdma->dma.dev, "Memory allocation error. " - "Allocated only %u descriptors\n", i); + dev_notice(mdma->dma.dev, + "Memory allocation error. Allocated only %u descriptors\n", i); break; } @@ -925,7 +921,6 @@ static int mpc_dma_probe(struct platform_device *op) mdma = devm_kzalloc(dev, sizeof(struct mpc_dma), GFP_KERNEL); if (!mdma) { - dev_err(dev, "Memory exhausted!\n"); retval = -ENOMEM; goto err; } @@ -1049,7 +1044,8 @@ static int mpc_dma_probe(struct platform_device *op) out_be32(&mdma->regs->dmaerrl, 0xFFFF); } else { out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG | - MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA); + MPC_DMA_DMACR_ERGA | + MPC_DMA_DMACR_ERCA); /* Disable hardware DMA requests */ out_be32(&mdma->regs->dmaerqh, 0); -- GitLab From 120e8989ebac7c7c702e351046c20e9918912aca Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 1 Apr 2016 16:48:49 +0530 Subject: [PATCH 1221/9938] spi: pic32: Add bindings for PIC32 SPI peripheral Document the devicetree bindings for the SPI peripheral found on Microchip PIC32 class devices. Signed-off-by: Purna Chandra Mandal Acked-by: Rob Herring Signed-off-by: Mark Brown --- .../bindings/spi/microchip,spi-pic32.txt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt diff --git a/Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt b/Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt new file mode 100644 index 000000000000..79de379f4dc0 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt @@ -0,0 +1,34 @@ +Microchip PIC32 SPI Master controller + +Required properties: +- compatible: Should be "microchip,pic32mzda-spi". +- reg: Address and length of register space for the device. +- interrupts: Should contain all three spi interrupts in sequence + of , , . +- interrupt-names: Should be "fault", "rx", "tx" in order. +- clocks: Phandle of the clock generating SPI clock on the bus. +- clock-names: Should be "mck0". +- cs-gpios: Specifies the gpio pins to be used for chipselects. + See: Documentation/devicetree/bindings/spi/spi-bus.txt + +Optional properties: +- dmas: Two or more DMA channel specifiers following the convention outlined + in Documentation/devicetree/bindings/dma/dma.txt +- dma-names: Names for the dma channels. There must be at least one channel + named "spi-tx" for transmit and named "spi-rx" for receive. + +Example: + +spi1: spi@1f821000 { + compatible = "microchip,pic32mzda-spi"; + reg = <0x1f821000 0x200>; + interrupts = <109 IRQ_TYPE_LEVEL_HIGH>, + <110 IRQ_TYPE_LEVEL_HIGH>, + <111 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "fault", "rx", "tx"; + clocks = <&PBCLK2>; + clock-names = "mck0"; + cs-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; + dmas = <&dma 134>, <&dma 135>; + dma-names = "spi-rx", "spi-tx"; +}; -- GitLab From 1bcb9f8ceb67803960871ecf4ed2d365a2a919c8 Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 1 Apr 2016 16:48:50 +0530 Subject: [PATCH 1222/9938] spi: spi-pic32: Add PIC32 SPI master driver The PIC32 SPI driver is capable of performing SPI transfers using PIO or external DMA engine. GPIO controlled /CS support is made default in the driver for correct operation of the controller. This can be enabled by adding "cs-gpios" property of the SPI node in board dts file. Signed-off-by: Purna Chandra Mandal Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/spi-pic32.c | 888 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 895 insertions(+) create mode 100644 drivers/spi/spi-pic32.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9d8c84bb1544..8a8ff5051c64 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -436,6 +436,12 @@ config SPI_ORION help This enables using the SPI master controller on the Orion chips. +config SPI_PIC32 + tristate "Microchip PIC32 series SPI" + depends on MACH_PIC32 || COMPILE_TEST + help + SPI driver for Microchip PIC32 SPI master controller. + config SPI_PL022 tristate "ARM AMBA PL022 SSP controller" depends on ARM_AMBA diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index fbb255c5a608..06019ed11fac 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_SPI_OMAP_100K) += spi-omap-100k.o obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o obj-$(CONFIG_SPI_ORION) += spi-orion.o +obj-$(CONFIG_SPI_PIC32) += spi-pic32.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-dma.o diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c new file mode 100644 index 000000000000..f8313ea11a34 --- /dev/null +++ b/drivers/spi/spi-pic32.c @@ -0,0 +1,888 @@ +/* + * Microchip PIC32 SPI controller driver. + * + * Purna Chandra Mandal + * Copyright (c) 2016, Microchip Technology Inc. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPI controller registers */ +struct pic32_spi_regs { + u32 ctrl; + u32 ctrl_clr; + u32 ctrl_set; + u32 ctrl_inv; + u32 status; + u32 status_clr; + u32 status_set; + u32 status_inv; + u32 buf; + u32 dontuse[3]; + u32 baud; + u32 dontuse2[3]; + u32 ctrl2; + u32 ctrl2_clr; + u32 ctrl2_set; + u32 ctrl2_inv; +}; + +/* Bit fields of SPI Control Register */ +#define CTRL_RX_INT_SHIFT 0 /* Rx interrupt generation */ +#define RX_FIFO_EMTPY 0 +#define RX_FIFO_NOT_EMPTY 1 /* not empty */ +#define RX_FIFO_HALF_FULL 2 /* full by half or more */ +#define RX_FIFO_FULL 3 /* completely full */ + +#define CTRL_TX_INT_SHIFT 2 /* TX interrupt generation */ +#define TX_FIFO_ALL_EMPTY 0 /* completely empty */ +#define TX_FIFO_EMTPY 1 /* empty */ +#define TX_FIFO_HALF_EMPTY 2 /* empty by half or more */ +#define TX_FIFO_NOT_FULL 3 /* atleast one empty */ + +#define CTRL_MSTEN BIT(5) /* enable master mode */ +#define CTRL_CKP BIT(6) /* active low */ +#define CTRL_CKE BIT(8) /* Tx on falling edge */ +#define CTRL_SMP BIT(9) /* Rx at middle or end of tx */ +#define CTRL_BPW_MASK 0x03 /* bits per word/sample */ +#define CTRL_BPW_SHIFT 10 +#define PIC32_BPW_8 0 +#define PIC32_BPW_16 1 +#define PIC32_BPW_32 2 +#define CTRL_SIDL BIT(13) /* sleep when idle */ +#define CTRL_ON BIT(15) /* enable macro */ +#define CTRL_ENHBUF BIT(16) /* enable enhanced buffering */ +#define CTRL_MCLKSEL BIT(23) /* select clock source */ +#define CTRL_MSSEN BIT(28) /* macro driven /SS */ +#define CTRL_FRMEN BIT(31) /* enable framing mode */ + +/* Bit fields of SPI Status Register */ +#define STAT_RF_EMPTY BIT(5) /* RX Fifo empty */ +#define STAT_RX_OV BIT(6) /* err, s/w needs to clear */ +#define STAT_TX_UR BIT(8) /* UR in Framed SPI modes */ +#define STAT_FRM_ERR BIT(12) /* Multiple Frame Sync pulse */ +#define STAT_TF_LVL_MASK 0x1F +#define STAT_TF_LVL_SHIFT 16 +#define STAT_RF_LVL_MASK 0x1F +#define STAT_RF_LVL_SHIFT 24 + +/* Bit fields of SPI Baud Register */ +#define BAUD_MASK 0x1ff + +/* Bit fields of SPI Control2 Register */ +#define CTRL2_TX_UR_EN BIT(10) /* Enable int on Tx under-run */ +#define CTRL2_RX_OV_EN BIT(11) /* Enable int on Rx over-run */ +#define CTRL2_FRM_ERR_EN BIT(12) /* Enable frame err int */ + +/* Minimum DMA transfer size */ +#define PIC32_DMA_LEN_MIN 64 + +struct pic32_spi { + dma_addr_t dma_base; + struct pic32_spi_regs __iomem *regs; + int fault_irq; + int rx_irq; + int tx_irq; + u32 fifo_n_byte; /* FIFO depth in bytes */ + struct clk *clk; + struct spi_master *master; + /* Current controller setting */ + u32 speed_hz; /* spi-clk rate */ + u32 mode; + u32 bits_per_word; + u32 fifo_n_elm; /* FIFO depth in words */ +#define PIC32F_DMA_PREP 0 /* DMA chnls configured */ + unsigned long flags; + /* Current transfer state */ + struct completion xfer_done; + /* PIO transfer specific */ + const void *tx; + const void *tx_end; + const void *rx; + const void *rx_end; + int len; + void (*rx_fifo)(struct pic32_spi *); + void (*tx_fifo)(struct pic32_spi *); +}; + +static inline void pic32_spi_enable(struct pic32_spi *pic32s) +{ + writel(CTRL_ON | CTRL_SIDL, &pic32s->regs->ctrl_set); +} + +static inline void pic32_spi_disable(struct pic32_spi *pic32s) +{ + writel(CTRL_ON | CTRL_SIDL, &pic32s->regs->ctrl_clr); + + /* avoid SPI registers read/write at immediate next CPU clock */ + ndelay(20); +} + +static void pic32_spi_set_clk_rate(struct pic32_spi *pic32s, u32 spi_ck) +{ + u32 div; + + /* div = (clk_in / 2 * spi_ck) - 1 */ + div = DIV_ROUND_CLOSEST(clk_get_rate(pic32s->clk), 2 * spi_ck) - 1; + + writel(div & BAUD_MASK, &pic32s->regs->baud); +} + +static inline u32 pic32_rx_fifo_level(struct pic32_spi *pic32s) +{ + u32 sr = readl(&pic32s->regs->status); + + return (sr >> STAT_RF_LVL_SHIFT) & STAT_RF_LVL_MASK; +} + +static inline u32 pic32_tx_fifo_level(struct pic32_spi *pic32s) +{ + u32 sr = readl(&pic32s->regs->status); + + return (sr >> STAT_TF_LVL_SHIFT) & STAT_TF_LVL_MASK; +} + +/* Return the max entries we can fill into tx fifo */ +static u32 pic32_tx_max(struct pic32_spi *pic32s, int n_bytes) +{ + u32 tx_left, tx_room, rxtx_gap; + + tx_left = (pic32s->tx_end - pic32s->tx) / n_bytes; + tx_room = pic32s->fifo_n_elm - pic32_tx_fifo_level(pic32s); + + /* + * Another concern is about the tx/rx mismatch, we + * though to use (pic32s->fifo_n_byte - rxfl - txfl) as + * one maximum value for tx, but it doesn't cover the + * data which is out of tx/rx fifo and inside the + * shift registers. So a ctrl from sw point of + * view is taken. + */ + rxtx_gap = ((pic32s->rx_end - pic32s->rx) - + (pic32s->tx_end - pic32s->tx)) / n_bytes; + return min3(tx_left, tx_room, (u32)(pic32s->fifo_n_elm - rxtx_gap)); +} + +/* Return the max entries we should read out of rx fifo */ +static u32 pic32_rx_max(struct pic32_spi *pic32s, int n_bytes) +{ + u32 rx_left = (pic32s->rx_end - pic32s->rx) / n_bytes; + + return min_t(u32, rx_left, pic32_rx_fifo_level(pic32s)); +} + +#define BUILD_SPI_FIFO_RW(__name, __type, __bwl) \ +static void pic32_spi_rx_##__name(struct pic32_spi *pic32s) \ +{ \ + __type v; \ + u32 mx = pic32_rx_max(pic32s, sizeof(__type)); \ + for (; mx; mx--) { \ + v = read##__bwl(&pic32s->regs->buf); \ + if (pic32s->rx_end - pic32s->len) \ + *(__type *)(pic32s->rx) = v; \ + pic32s->rx += sizeof(__type); \ + } \ +} \ + \ +static void pic32_spi_tx_##__name(struct pic32_spi *pic32s) \ +{ \ + __type v; \ + u32 mx = pic32_tx_max(pic32s, sizeof(__type)); \ + for (; mx ; mx--) { \ + v = (__type)~0U; \ + if (pic32s->tx_end - pic32s->len) \ + v = *(__type *)(pic32s->tx); \ + write##__bwl(v, &pic32s->regs->buf); \ + pic32s->tx += sizeof(__type); \ + } \ +} + +BUILD_SPI_FIFO_RW(byte, u8, b); +BUILD_SPI_FIFO_RW(word, u16, w); +BUILD_SPI_FIFO_RW(dword, u32, l); + +static void pic32_err_stop(struct pic32_spi *pic32s, const char *msg) +{ + /* disable all interrupts */ + disable_irq_nosync(pic32s->fault_irq); + disable_irq_nosync(pic32s->rx_irq); + disable_irq_nosync(pic32s->tx_irq); + + /* Show err message and abort xfer with err */ + dev_err(&pic32s->master->dev, "%s\n", msg); + if (pic32s->master->cur_msg) + pic32s->master->cur_msg->status = -EIO; + complete(&pic32s->xfer_done); +} + +static irqreturn_t pic32_spi_fault_irq(int irq, void *dev_id) +{ + struct pic32_spi *pic32s = dev_id; + u32 status; + + status = readl(&pic32s->regs->status); + + /* Error handling */ + if (status & (STAT_RX_OV | STAT_TX_UR)) { + writel(STAT_RX_OV, &pic32s->regs->status_clr); + writel(STAT_TX_UR, &pic32s->regs->status_clr); + pic32_err_stop(pic32s, "err_irq: fifo ov/ur-run\n"); + return IRQ_HANDLED; + } + + if (status & STAT_FRM_ERR) { + pic32_err_stop(pic32s, "err_irq: frame error"); + return IRQ_HANDLED; + } + + if (!pic32s->master->cur_msg) { + pic32_err_stop(pic32s, "err_irq: no mesg"); + return IRQ_NONE; + } + + return IRQ_NONE; +} + +static irqreturn_t pic32_spi_rx_irq(int irq, void *dev_id) +{ + struct pic32_spi *pic32s = dev_id; + + pic32s->rx_fifo(pic32s); + + /* rx complete ? */ + if (pic32s->rx_end == pic32s->rx) { + /* disable all interrupts */ + disable_irq_nosync(pic32s->fault_irq); + disable_irq_nosync(pic32s->rx_irq); + + /* complete current xfer */ + complete(&pic32s->xfer_done); + } + + return IRQ_HANDLED; +} + +static irqreturn_t pic32_spi_tx_irq(int irq, void *dev_id) +{ + struct pic32_spi *pic32s = dev_id; + + pic32s->tx_fifo(pic32s); + + /* tx complete? disable tx interrupt */ + if (pic32s->tx_end == pic32s->tx) + disable_irq_nosync(pic32s->tx_irq); + + return IRQ_HANDLED; +} + +static void pic32_spi_dma_rx_notify(void *data) +{ + struct pic32_spi *pic32s = data; + + complete(&pic32s->xfer_done); +} + +static int pic32_spi_dma_transfer(struct pic32_spi *pic32s, + struct spi_transfer *xfer) +{ + struct spi_master *master = pic32s->master; + struct dma_async_tx_descriptor *desc_rx; + struct dma_async_tx_descriptor *desc_tx; + dma_cookie_t cookie; + int ret; + + if (!master->dma_rx || !master->dma_tx) + return -ENODEV; + + desc_rx = dmaengine_prep_slave_sg(master->dma_rx, + xfer->rx_sg.sgl, + xfer->rx_sg.nents, + DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc_rx) { + ret = -EINVAL; + goto err_dma; + } + + desc_tx = dmaengine_prep_slave_sg(master->dma_tx, + xfer->tx_sg.sgl, + xfer->tx_sg.nents, + DMA_TO_DEVICE, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc_tx) { + ret = -EINVAL; + goto err_dma; + } + + /* Put callback on the RX transfer, that should finish last */ + desc_rx->callback = pic32_spi_dma_rx_notify; + desc_rx->callback_param = pic32s; + + cookie = dmaengine_submit(desc_rx); + ret = dma_submit_error(cookie); + if (ret) + goto err_dma; + + cookie = dmaengine_submit(desc_tx); + ret = dma_submit_error(cookie); + if (ret) + goto err_dma_tx; + + dma_async_issue_pending(master->dma_rx); + dma_async_issue_pending(master->dma_tx); + + return 0; + +err_dma_tx: + dmaengine_terminate_all(master->dma_rx); +err_dma: + return ret; +} + +static int pic32_spi_dma_config(struct pic32_spi *pic32s, u32 dma_width) +{ + int buf_offset = offsetof(struct pic32_spi_regs, buf); + struct spi_master *master = pic32s->master; + struct dma_slave_config cfg; + int ret; + + cfg.device_fc = true; + cfg.src_addr = pic32s->dma_base + buf_offset; + cfg.dst_addr = pic32s->dma_base + buf_offset; + cfg.src_maxburst = pic32s->fifo_n_elm / 2; /* fill one-half */ + cfg.dst_maxburst = pic32s->fifo_n_elm / 2; /* drain one-half */ + cfg.src_addr_width = dma_width; + cfg.dst_addr_width = dma_width; + /* tx channel */ + cfg.slave_id = pic32s->tx_irq; + cfg.direction = DMA_MEM_TO_DEV; + ret = dmaengine_slave_config(master->dma_tx, &cfg); + if (ret) { + dev_err(&master->dev, "tx channel setup failed\n"); + return ret; + } + /* rx channel */ + cfg.slave_id = pic32s->rx_irq; + cfg.direction = DMA_DEV_TO_MEM; + ret = dmaengine_slave_config(master->dma_rx, &cfg); + if (ret) + dev_err(&master->dev, "rx channel setup failed\n"); + + return ret; +} + +static int pic32_spi_set_word_size(struct pic32_spi *pic32s, u8 bits_per_word) +{ + enum dma_slave_buswidth dmawidth; + u32 buswidth, v; + + switch (bits_per_word) { + case 8: + pic32s->rx_fifo = pic32_spi_rx_byte; + pic32s->tx_fifo = pic32_spi_tx_byte; + buswidth = PIC32_BPW_8; + dmawidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + break; + case 16: + pic32s->rx_fifo = pic32_spi_rx_word; + pic32s->tx_fifo = pic32_spi_tx_word; + buswidth = PIC32_BPW_16; + dmawidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + break; + case 32: + pic32s->rx_fifo = pic32_spi_rx_dword; + pic32s->tx_fifo = pic32_spi_tx_dword; + buswidth = PIC32_BPW_32; + dmawidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + break; + default: + /* not supported */ + return -EINVAL; + } + + /* calculate maximum number of words fifos can hold */ + pic32s->fifo_n_elm = DIV_ROUND_UP(pic32s->fifo_n_byte, + bits_per_word / 8); + /* set word size */ + v = readl(&pic32s->regs->ctrl); + v &= ~(CTRL_BPW_MASK << CTRL_BPW_SHIFT); + v |= buswidth << CTRL_BPW_SHIFT; + writel(v, &pic32s->regs->ctrl); + + /* re-configure dma width, if required */ + if (test_bit(PIC32F_DMA_PREP, &pic32s->flags)) + pic32_spi_dma_config(pic32s, dmawidth); + + return 0; +} + +static int pic32_spi_prepare_hardware(struct spi_master *master) +{ + struct pic32_spi *pic32s = spi_master_get_devdata(master); + + pic32_spi_enable(pic32s); + + return 0; +} + +static int pic32_spi_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + struct pic32_spi *pic32s = spi_master_get_devdata(master); + struct spi_device *spi = msg->spi; + u32 val; + + /* set device specific bits_per_word */ + if (pic32s->bits_per_word != spi->bits_per_word) { + pic32_spi_set_word_size(pic32s, spi->bits_per_word); + pic32s->bits_per_word = spi->bits_per_word; + } + + /* device specific speed change */ + if (pic32s->speed_hz != spi->max_speed_hz) { + pic32_spi_set_clk_rate(pic32s, spi->max_speed_hz); + pic32s->speed_hz = spi->max_speed_hz; + } + + /* device specific mode change */ + if (pic32s->mode != spi->mode) { + val = readl(&pic32s->regs->ctrl); + /* active low */ + if (spi->mode & SPI_CPOL) + val |= CTRL_CKP; + else + val &= ~CTRL_CKP; + /* tx on rising edge */ + if (spi->mode & SPI_CPHA) + val &= ~CTRL_CKE; + else + val |= CTRL_CKE; + + /* rx at end of tx */ + val |= CTRL_SMP; + writel(val, &pic32s->regs->ctrl); + pic32s->mode = spi->mode; + } + + return 0; +} + +static bool pic32_spi_can_dma(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct pic32_spi *pic32s = spi_master_get_devdata(master); + + /* skip using DMA on small size transfer to avoid overhead.*/ + return (xfer->len >= PIC32_DMA_LEN_MIN) && + test_bit(PIC32F_DMA_PREP, &pic32s->flags); +} + +static int pic32_spi_one_transfer(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *transfer) +{ + struct pic32_spi *pic32s; + bool dma_issued = false; + int ret; + + pic32s = spi_master_get_devdata(master); + + /* handle transfer specific word size change */ + if (transfer->bits_per_word && + (transfer->bits_per_word != pic32s->bits_per_word)) { + ret = pic32_spi_set_word_size(pic32s, transfer->bits_per_word); + if (ret) + return ret; + pic32s->bits_per_word = transfer->bits_per_word; + } + + /* handle transfer specific speed change */ + if (transfer->speed_hz && (transfer->speed_hz != pic32s->speed_hz)) { + pic32_spi_set_clk_rate(pic32s, transfer->speed_hz); + pic32s->speed_hz = transfer->speed_hz; + } + + reinit_completion(&pic32s->xfer_done); + + /* transact by DMA mode */ + if (transfer->rx_sg.nents && transfer->tx_sg.nents) { + ret = pic32_spi_dma_transfer(pic32s, transfer); + if (ret) { + dev_err(&spi->dev, "dma submit error\n"); + return ret; + } + + /* DMA issued */ + dma_issued = true; + } else { + /* set current transfer information */ + pic32s->tx = (const void *)transfer->tx_buf; + pic32s->rx = (const void *)transfer->rx_buf; + pic32s->tx_end = pic32s->tx + transfer->len; + pic32s->rx_end = pic32s->rx + transfer->len; + pic32s->len = transfer->len; + + /* transact by interrupt driven PIO */ + enable_irq(pic32s->fault_irq); + enable_irq(pic32s->rx_irq); + enable_irq(pic32s->tx_irq); + } + + /* wait for completion */ + ret = wait_for_completion_timeout(&pic32s->xfer_done, 2 * HZ); + if (ret <= 0) { + dev_err(&spi->dev, "wait error/timedout\n"); + if (dma_issued) { + dmaengine_terminate_all(master->dma_rx); + dmaengine_terminate_all(master->dma_rx); + } + ret = -ETIMEDOUT; + } else { + ret = 0; + } + + return ret; +} + +static int pic32_spi_unprepare_message(struct spi_master *master, + struct spi_message *msg) +{ + /* nothing to do */ + return 0; +} + +static int pic32_spi_unprepare_hardware(struct spi_master *master) +{ + struct pic32_spi *pic32s = spi_master_get_devdata(master); + + pic32_spi_disable(pic32s); + + return 0; +} + +/* This may be called multiple times by same spi dev */ +static int pic32_spi_setup(struct spi_device *spi) +{ + if (!spi->max_speed_hz) { + dev_err(&spi->dev, "No max speed HZ parameter\n"); + return -EINVAL; + } + + switch (spi->bits_per_word) { + case 8: + case 16: + case 32: + break; + default: + dev_err(&spi->dev, "Invalid bits_per_word defined\n"); + return -EINVAL; + } + + /* PIC32 spi controller can drive /CS during transfer depending + * on tx fifo fill-level. /CS will stay asserted as long as TX + * fifo is non-empty, else will be deasserted indicating + * completion of the ongoing transfer. This might result into + * unreliable/erroneous SPI transactions. + * To avoid that we will always handle /CS by toggling GPIO. + */ + if (!gpio_is_valid(spi->cs_gpio)) + return -EINVAL; + + gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + + return 0; +} + +static void pic32_spi_cleanup(struct spi_device *spi) +{ + /* de-activate cs-gpio */ + gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); +} + +static void pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) +{ + struct spi_master *master = pic32s->master; + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + master->dma_rx = dma_request_slave_channel_compat(mask, NULL, NULL, + dev, "spi-rx"); + if (!master->dma_rx) { + dev_warn(dev, "RX channel not found.\n"); + goto out_err; + } + + master->dma_tx = dma_request_slave_channel_compat(mask, NULL, NULL, + dev, "spi-tx"); + if (!master->dma_tx) { + dev_warn(dev, "TX channel not found.\n"); + goto out_err; + } + + if (pic32_spi_dma_config(pic32s, DMA_SLAVE_BUSWIDTH_1_BYTE)) + goto out_err; + + /* DMA chnls allocated and prepared */ + set_bit(PIC32F_DMA_PREP, &pic32s->flags); + + return; + +out_err: + if (master->dma_rx) + dma_release_channel(master->dma_rx); + + if (master->dma_tx) + dma_release_channel(master->dma_tx); +} + +static void pic32_spi_dma_unprep(struct pic32_spi *pic32s) +{ + if (!test_bit(PIC32F_DMA_PREP, &pic32s->flags)) + return; + + clear_bit(PIC32F_DMA_PREP, &pic32s->flags); + if (pic32s->master->dma_rx) + dma_release_channel(pic32s->master->dma_rx); + + if (pic32s->master->dma_tx) + dma_release_channel(pic32s->master->dma_tx); +} + +static void pic32_spi_hw_init(struct pic32_spi *pic32s) +{ + u32 ctrl; + + /* disable hardware */ + pic32_spi_disable(pic32s); + + ctrl = readl(&pic32s->regs->ctrl); + /* enable enhanced fifo of 128bit deep */ + ctrl |= CTRL_ENHBUF; + pic32s->fifo_n_byte = 16; + + /* disable framing mode */ + ctrl &= ~CTRL_FRMEN; + + /* enable master mode while disabled */ + ctrl |= CTRL_MSTEN; + + /* set tx fifo threshold interrupt */ + ctrl &= ~(0x3 << CTRL_TX_INT_SHIFT); + ctrl |= (TX_FIFO_HALF_EMPTY << CTRL_TX_INT_SHIFT); + + /* set rx fifo threshold interrupt */ + ctrl &= ~(0x3 << CTRL_RX_INT_SHIFT); + ctrl |= (RX_FIFO_NOT_EMPTY << CTRL_RX_INT_SHIFT); + + /* select clk source */ + ctrl &= ~CTRL_MCLKSEL; + + /* set manual /CS mode */ + ctrl &= ~CTRL_MSSEN; + + writel(ctrl, &pic32s->regs->ctrl); + + /* enable error reporting */ + ctrl = CTRL2_TX_UR_EN | CTRL2_RX_OV_EN | CTRL2_FRM_ERR_EN; + writel(ctrl, &pic32s->regs->ctrl2_set); +} + +static int pic32_spi_hw_probe(struct platform_device *pdev, + struct pic32_spi *pic32s) +{ + struct resource *mem; + int ret; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pic32s->regs = devm_ioremap_resource(&pdev->dev, mem); + if (!pic32s->regs) { + dev_err(&pdev->dev, "ioremap() failed\n"); + return -ENOMEM; + } + pic32s->dma_base = mem->start; + + /* get irq resources: err-irq, rx-irq, tx-irq */ + pic32s->fault_irq = platform_get_irq_byname(pdev, "fault"); + if (pic32s->fault_irq < 0) { + dev_err(&pdev->dev, "fault-irq not found\n"); + return pic32s->fault_irq; + } + + pic32s->rx_irq = platform_get_irq_byname(pdev, "rx"); + if (pic32s->rx_irq < 0) { + dev_err(&pdev->dev, "rx-irq not found\n"); + return pic32s->rx_irq; + } + + pic32s->tx_irq = platform_get_irq_byname(pdev, "tx"); + if (pic32s->tx_irq < 0) { + dev_err(&pdev->dev, "tx-irq not found\n"); + return pic32s->tx_irq; + } + + /* get clock */ + pic32s->clk = devm_clk_get(&pdev->dev, "mck0"); + if (IS_ERR(pic32s->clk)) { + dev_err(&pdev->dev, "clk not found\n"); + ret = PTR_ERR(pic32s->clk); + goto err_unmap_mem; + } + + ret = clk_prepare_enable(pic32s->clk); + if (ret) + goto err_unmap_mem; + + pic32_spi_hw_init(pic32s); + + return 0; + +err_unmap_mem: + dev_err(&pdev->dev, "%s failed, err %d\n", __func__, ret); + return ret; +} + +static int pic32_spi_probe(struct platform_device *pdev) +{ + struct spi_master *master; + struct pic32_spi *pic32s; + int ret; + + master = spi_alloc_master(&pdev->dev, sizeof(*pic32s)); + if (!master) + return -ENOMEM; + + pic32s = spi_master_get_devdata(master); + pic32s->master = master; + + ret = pic32_spi_hw_probe(pdev, pic32s); + if (ret) + goto err_master; + + master->dev.of_node = of_node_get(pdev->dev.of_node); + master->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_CS_HIGH; + master->num_chipselect = 1; /* single chip-select */ + master->max_speed_hz = clk_get_rate(pic32s->clk); + master->setup = pic32_spi_setup; + master->cleanup = pic32_spi_cleanup; + master->flags = SPI_MASTER_MUST_TX | SPI_MASTER_MUST_RX; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); + master->transfer_one = pic32_spi_one_transfer; + master->prepare_message = pic32_spi_prepare_message; + master->unprepare_message = pic32_spi_unprepare_message; + master->prepare_transfer_hardware = pic32_spi_prepare_hardware; + master->unprepare_transfer_hardware = pic32_spi_unprepare_hardware; + + /* optional DMA support */ + pic32_spi_dma_prep(pic32s, &pdev->dev); + if (test_bit(PIC32F_DMA_PREP, &pic32s->flags)) + master->can_dma = pic32_spi_can_dma; + + init_completion(&pic32s->xfer_done); + pic32s->mode = -1; + + /* install irq handlers (with irq-disabled) */ + irq_set_status_flags(pic32s->fault_irq, IRQ_NOAUTOEN); + ret = devm_request_irq(&pdev->dev, pic32s->fault_irq, + pic32_spi_fault_irq, IRQF_NO_THREAD, + dev_name(&pdev->dev), pic32s); + if (ret < 0) { + dev_err(&pdev->dev, "request fault-irq %d\n", pic32s->rx_irq); + goto err_bailout; + } + + /* receive interrupt handler */ + irq_set_status_flags(pic32s->rx_irq, IRQ_NOAUTOEN); + ret = devm_request_irq(&pdev->dev, pic32s->rx_irq, + pic32_spi_rx_irq, IRQF_NO_THREAD, + dev_name(&pdev->dev), pic32s); + if (ret < 0) { + dev_err(&pdev->dev, "request rx-irq %d\n", pic32s->rx_irq); + goto err_bailout; + } + + /* transmit interrupt handler */ + irq_set_status_flags(pic32s->tx_irq, IRQ_NOAUTOEN); + ret = devm_request_irq(&pdev->dev, pic32s->tx_irq, + pic32_spi_tx_irq, IRQF_NO_THREAD, + dev_name(&pdev->dev), pic32s); + if (ret < 0) { + dev_err(&pdev->dev, "request tx-irq %d\n", pic32s->tx_irq); + goto err_bailout; + } + + /* register master */ + ret = devm_spi_register_master(&pdev->dev, master); + if (ret) { + dev_err(&master->dev, "failed registering spi master\n"); + goto err_bailout; + } + + platform_set_drvdata(pdev, pic32s); + + return 0; + +err_bailout: + clk_disable_unprepare(pic32s->clk); +err_master: + spi_master_put(master); + return ret; +} + +static int pic32_spi_remove(struct platform_device *pdev) +{ + struct pic32_spi *pic32s; + + pic32s = platform_get_drvdata(pdev); + pic32_spi_disable(pic32s); + clk_disable_unprepare(pic32s->clk); + pic32_spi_dma_unprep(pic32s); + + return 0; +} + +static const struct of_device_id pic32_spi_of_match[] = { + {.compatible = "microchip,pic32mzda-spi",}, + {}, +}; +MODULE_DEVICE_TABLE(of, pic32_spi_of_match); + +static struct platform_driver pic32_spi_driver = { + .driver = { + .name = "spi-pic32", + .of_match_table = of_match_ptr(pic32_spi_of_match), + }, + .probe = pic32_spi_probe, + .remove = pic32_spi_remove, +}; + +module_platform_driver(pic32_spi_driver); + +MODULE_AUTHOR("Purna Chandra Mandal "); +MODULE_DESCRIPTION("Microchip SPI driver for PIC32 SPI controller."); +MODULE_LICENSE("GPL v2"); -- GitLab From 8f03488b7478f82897ad909f743db0cd6e3947ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 28 Mar 2016 18:52:27 -0700 Subject: [PATCH 1223/9938] ARM: multi_v7_defconfig: Add more BCM2835 support The WDT is required for reboot and I2S is used for audio devices on the P5 header (or BT audio on the Pi3). Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/configs/multi_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 28234906a064..43a8ce0a3019 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -438,6 +438,7 @@ CONFIG_TEGRA_WATCHDOG=m CONFIG_MESON_WATCHDOG=y CONFIG_DW_WATCHDOG=y CONFIG_DIGICOLOR_WATCHDOG=y +CONFIG_BCM2835_WDT=y CONFIG_MFD_AS3711=y CONFIG_MFD_AS3722=y CONFIG_MFD_ATMEL_FLEXCOM=y @@ -564,6 +565,7 @@ CONFIG_SND_USB_AUDIO=m CONFIG_SND_SOC=m CONFIG_SND_ATMEL_SOC=m CONFIG_SND_ATMEL_SOC_WM8904=m +CONFIG_SND_BCM2835_SOC_I2S=m CONFIG_SND_SOC_FSL_SAI=m CONFIG_SND_SOC_ROCKCHIP=m CONFIG_SND_SOC_ROCKCHIP_SPDIF=m -- GitLab From abcfccdfa14c2e74ede1ee7c876a907274f6bfb5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 28 Mar 2016 19:01:27 -0700 Subject: [PATCH 1224/9938] ARM: multi_v7_defconfig: Switch BCM2835 to sdhci-iproc.c for MMC This approximately triples write performance for the SD card. My card is too full of important data to collect very reliable numbers, but I see 271.361% +/- 166.742% improvement (n=3 before, 6 after), for 'dd if=/dev/zero of=/boot/asdf bs=1M count=3 oflag=dsync,direct'. Read performance appears to be unaffected. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/configs/multi_v7_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 43a8ce0a3019..a913520b1d44 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -642,7 +642,6 @@ CONFIG_MMC_SDHCI_SPEAR=y CONFIG_MMC_SDHCI_S3C=y CONFIG_MMC_SDHCI_S3C_DMA=y CONFIG_MMC_SDHCI_BCM_KONA=y -CONFIG_MMC_SDHCI_BCM2835=y CONFIG_MMC_SDHCI_ST=y CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y -- GitLab From 54fff103fd9b8312e8cb958dda3a0dc9d0793086 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 31 Mar 2016 13:38:57 -0700 Subject: [PATCH 1225/9938] ARM: multi_v7_defconfig: Build in DWC2 USB support This allows the Raspberry Pi 2 to be network booted from the defconfig. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/configs/multi_v7_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index a913520b1d44..8079f7d0575b 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -611,7 +611,7 @@ CONFIG_USB_STORAGE=y CONFIG_USB_MUSB_HDRC=m CONFIG_USB_MUSB_SUNXI=m CONFIG_USB_DWC3=y -CONFIG_USB_DWC2=m +CONFIG_USB_DWC2=y CONFIG_USB_CHIPIDEA=y CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_HOST=y -- GitLab From bf9dbf50b1a3a8af3c72dc722bfb0137dda873f7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 31 Mar 2016 14:19:56 -0700 Subject: [PATCH 1226/9938] ARM: bcm2835: Switch BCM2835 to sdhci-iproc.c for MMC This approximately triples write performance for the SD card. My card is too full of important data to collect very reliable numbers, but I see 271.361% +/- 166.742% improvement (n=3 before, 6 after), for 'dd if=/dev/zero of=/boot/asdf bs=1M count=3 oflag=dsync,direct'. Read performance appears to be unaffected. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/configs/bcm2835_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index 1ef69fcbdf2e..1617fd27bab9 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -87,7 +87,7 @@ CONFIG_USB_DWC2=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_MMC_SDHCI_IPROC=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_GPIO=y -- GitLab From 8d1a8c92a8c04f344a57c271b5c0792bc552ae3e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 31 Mar 2016 14:29:03 -0700 Subject: [PATCH 1227/9938] ARM: bcm2835: Enable CONFIG_PM. The power domain driver we've enabled doesn't actually do anything without it, and we need it to do its job for VC4 to initialize successfully. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/configs/bcm2835_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index 1617fd27bab9..1192a6fa5934 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -38,6 +38,7 @@ CONFIG_CRASH_DUMP=y CONFIG_VFP=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_SUSPEND is not set +CONFIG_PM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y -- GitLab From 4400d9ac05ee5100ecff2ad0ed1f0dea390bc349 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 31 Mar 2016 14:17:45 -0700 Subject: [PATCH 1228/9938] ARM: bcm2835: Enable the VC4 graphics driver in the defconfig Combined with the queued DT changes, we now get HDMI and 3D support. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/configs/bcm2835_defconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index 1192a6fa5934..896500fde884 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -64,7 +64,6 @@ CONFIG_INPUT_EVDEV=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_TTY_PRINTK=y -CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_BCM2835=y CONFIG_SPI=y @@ -74,10 +73,10 @@ CONFIG_GPIO_SYSFS=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_BCM2835_WDT=y -CONFIG_FB=y +CONFIG_DRM=y +CONFIG_DRM_VC4=y CONFIG_FB_SIMPLE=y CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y -- GitLab From 3652bb35abf6ee11333cbec1d2855c1c0f9f6b27 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 31 Mar 2016 14:55:34 -0700 Subject: [PATCH 1229/9938] ARM: bcm2835: Enable NFS root support. This is also present in multi_v7_defconfig, and means that I can test the pi1 with the 2835 defconfig in my normal environment. Signed-off-by: Eric Anholt --- arch/arm/configs/bcm2835_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index 896500fde884..79de828e49ad 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -43,6 +43,8 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y CONFIG_NETWORK_SECMARK=y CONFIG_NETFILTER=y CONFIG_CFG80211=y @@ -122,6 +124,7 @@ CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y -- GitLab From 77ed2c5745d93416992857d124f35834b62b3e70 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 8 Mar 2016 20:01:32 +0900 Subject: [PATCH 1230/9938] android,lowmemorykiller: Don't abuse TIF_MEMDIE. Currently, lowmemorykiller (LMK) is using TIF_MEMDIE for two purposes. One is to remember processes killed by LMK, and the other is to accelerate termination of processes killed by LMK. But since LMK is invoked as a memory shrinker function, there still should be some memory available. It is very likely that memory allocations by processes killed by LMK will succeed without using ALLOC_NO_WATERMARKS via TIF_MEMDIE. Even if their allocations cannot escape from memory allocation loop unless they use ALLOC_NO_WATERMARKS, lowmem_deathpending_timeout can guarantee forward progress by choosing next victim process. On the other hand, mark_oom_victim() assumes that it must be called with oom_lock held and it must not be called after oom_killer_disable() was called. But LMK is calling it without holding oom_lock and checking oom_killer_disabled. It is possible that LMK calls mark_oom_victim() due to allocation requests by kernel threads after current thread returned from oom_killer_disabled(). This will break synchronization for PM/suspend. This patch introduces per a task_struct flag for remembering processes killed by LMK, and replaces TIF_MEMDIE with that flag. By applying this patch, assumption by mark_oom_victim() becomes true. Signed-off-by: Tetsuo Handa Acked-by: Michal Hocko Cc: Arve Hjonnevag Cc: Riley Andrews Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/lowmemorykiller.c | 9 ++------- include/linux/sched.h | 4 ++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 2509e5df7244..c79f22425fa8 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -131,7 +131,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (!p) continue; - if (test_tsk_thread_flag(p, TIF_MEMDIE) && + if (task_lmk_waiting(p) && p->mm && time_before_eq(jiffies, lowmem_deathpending_timeout)) { task_unlock(p); rcu_read_unlock(); @@ -162,13 +162,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (selected) { task_lock(selected); send_sig(SIGKILL, selected, 0); - /* - * FIXME: lowmemorykiller shouldn't abuse global OOM killer - * infrastructure. There is no real reason why the selected - * task should have access to the memory reserves. - */ if (selected->mm) - mark_oom_victim(selected); + task_set_lmk_waiting(selected); task_unlock(selected); lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" " to free %ldkB on behalf of '%s' (%d) because\n" diff --git a/include/linux/sched.h b/include/linux/sched.h index 60bba7e032dc..9dff190e6a0a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2184,6 +2184,7 @@ static inline void memalloc_noio_restore(unsigned int flags) #define PFA_NO_NEW_PRIVS 0 /* May not gain new privileges. */ #define PFA_SPREAD_PAGE 1 /* Spread page cache over cpuset */ #define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */ +#define PFA_LMK_WAITING 3 /* Lowmemorykiller is waiting */ #define TASK_PFA_TEST(name, func) \ @@ -2207,6 +2208,9 @@ TASK_PFA_TEST(SPREAD_SLAB, spread_slab) TASK_PFA_SET(SPREAD_SLAB, spread_slab) TASK_PFA_CLEAR(SPREAD_SLAB, spread_slab) +TASK_PFA_TEST(LMK_WAITING, lmk_waiting) +TASK_PFA_SET(LMK_WAITING, lmk_waiting) + /* * task->jobctl flags */ -- GitLab From 8670a56ff70ec1fcbb95bd05a478c5a8361fee53 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Fri, 1 Apr 2016 17:28:22 +0900 Subject: [PATCH 1231/9938] staging: dgnc: remove too many traverse pointer The "ch->ch_bd" is already assined to "bd" but this is only for checking null or MAGIC number. in the dgnc_tty_ioctl function, bd can be used for referencing to board_ops structure. Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_tty.c | 37 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index d617fca682dc..5d8da411edc6 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -2518,6 +2518,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct dgnc_board *bd; + struct board_ops *ch_bd_ops; struct channel_t *ch; struct un_t *un; int rc; @@ -2539,6 +2540,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if (!bd || bd->magic != DGNC_BOARD_MAGIC) return -ENODEV; + ch_bd_ops = bd->bd_ops; + spin_lock_irqsave(&ch->ch_lock, flags); if (un->un_open_count <= 0) { @@ -2563,7 +2566,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if (rc) return rc; - rc = ch->ch_bd->bd_ops->drain(tty, 0); + rc = ch_bd_ops->drain(tty, 0); if (rc) return -EINTR; @@ -2571,7 +2574,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_lock_irqsave(&ch->ch_lock, flags); if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) - ch->ch_bd->bd_ops->send_break(ch, 250); + ch_bd_ops->send_break(ch, 250); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -2588,13 +2591,13 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if (rc) return rc; - rc = ch->ch_bd->bd_ops->drain(tty, 0); + rc = ch_bd_ops->drain(tty, 0); if (rc) return -EINTR; spin_lock_irqsave(&ch->ch_lock, flags); - ch->ch_bd->bd_ops->send_break(ch, 250); + ch_bd_ops->send_break(ch, 250); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -2606,13 +2609,13 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if (rc) return rc; - rc = ch->ch_bd->bd_ops->drain(tty, 0); + rc = ch_bd_ops->drain(tty, 0); if (rc) return -EINTR; spin_lock_irqsave(&ch->ch_lock, flags); - ch->ch_bd->bd_ops->send_break(ch, 250); + ch_bd_ops->send_break(ch, 250); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -2641,7 +2644,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_lock_irqsave(&ch->ch_lock, flags); tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); - ch->ch_bd->bd_ops->param(tty); + ch_bd_ops->param(tty); spin_unlock_irqrestore(&ch->ch_lock, flags); return 0; @@ -2678,7 +2681,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) { ch->ch_r_head = ch->ch_r_tail; - ch->ch_bd->bd_ops->flush_uart_read(ch); + ch_bd_ops->flush_uart_read(ch); /* Force queue flow control to be released, if needed */ dgnc_check_queue_flow_control(ch); } @@ -2686,7 +2689,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) { if (!(un->un_type == DGNC_PRINT)) { ch->ch_w_head = ch->ch_w_tail; - ch->ch_bd->bd_ops->flush_uart_write(ch); + ch_bd_ops->flush_uart_write(ch); if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) { ch->ch_tun.un_flags &= @@ -2720,14 +2723,14 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, /* flush rx */ ch->ch_flags &= ~CH_STOP; ch->ch_r_head = ch->ch_r_tail; - ch->ch_bd->bd_ops->flush_uart_read(ch); + ch_bd_ops->flush_uart_read(ch); /* Force queue flow control to be released, if needed */ dgnc_check_queue_flow_control(ch); } /* now wait for all the output to drain */ spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = ch->ch_bd->bd_ops->drain(tty, 0); + rc = ch_bd_ops->drain(tty, 0); if (rc) return -EINTR; @@ -2737,7 +2740,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case TCSETAW: spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = ch->ch_bd->bd_ops->drain(tty, 0); + rc = ch_bd_ops->drain(tty, 0); if (rc) return -EINTR; @@ -2760,7 +2763,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, /* set information for ditty */ if (cmd == (DIGI_SETAW)) { spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = ch->ch_bd->bd_ops->drain(tty, 0); + rc = ch_bd_ops->drain(tty, 0); if (rc) return -EINTR; @@ -2793,7 +2796,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, else ch->ch_flags &= ~(CH_LOOPBACK); - ch->ch_bd->bd_ops->param(tty); + ch_bd_ops->param(tty); spin_unlock_irqrestore(&ch->ch_lock, flags); return 0; } @@ -2813,7 +2816,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, return rc; spin_lock_irqsave(&ch->ch_lock, flags); dgnc_set_custom_speed(ch, new_rate); - ch->ch_bd->bd_ops->param(tty); + ch_bd_ops->param(tty); spin_unlock_irqrestore(&ch->ch_lock, flags); return 0; } @@ -2834,7 +2837,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if (rc) return rc; spin_lock_irqsave(&ch->ch_lock, flags); - ch->ch_bd->bd_ops->send_immediate_char(ch, c); + ch_bd_ops->send_immediate_char(ch, c); spin_unlock_irqrestore(&ch->ch_lock, flags); return 0; } @@ -2922,7 +2925,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, /* * Is the UART empty? Add that value to whats in our TX queue. */ - count = buf.txbuf + ch->ch_bd->bd_ops->get_uart_bytes_left(ch); + count = buf.txbuf + ch_bd_ops->get_uart_bytes_left(ch); /* * Figure out how much data the RealPort Server believes should -- GitLab From b9f8463728eb0dd46b9f2b34ee59b12e358b4ce7 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Fri, 1 Apr 2016 17:28:44 +0900 Subject: [PATCH 1232/9938] staging: dgnc: fix CamelCase in dgnc_tty.c fix checkpatch.pl warning about 'Avoid CamelCase' Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_tty.c | 2 +- drivers/staging/dgnc/digi.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 5d8da411edc6..074988d99639 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -2931,7 +2931,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, * Figure out how much data the RealPort Server believes should * be in our TX queue. */ - tdist = (buf.tIn - buf.tOut) & 0xffff; + tdist = (buf.tx_in - buf.tx_out) & 0xffff; /* * If we have more data than the RealPort Server believes we diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h index 523a2d34f747..5b983e6f5ee2 100644 --- a/drivers/staging/dgnc/digi.h +++ b/drivers/staging/dgnc/digi.h @@ -109,8 +109,8 @@ struct digi_info { struct digi_getbuffer /* Struct for holding buffer use counts */ { - unsigned long tIn; - unsigned long tOut; + unsigned long tx_in; + unsigned long tx_out; unsigned long rxbuf; unsigned long txbuf; unsigned long txdone; -- GitLab From 148e45dc87cb76ba89e80da264bc692cc91a5149 Mon Sep 17 00:00:00 2001 From: Clifton Barnes Date: Thu, 31 Mar 2016 18:53:14 -0400 Subject: [PATCH 1233/9938] staging: vme: fix bare use of 'unsigned' fix checkpatch.pl warning about 'Prefer 'unsigned int' to bare use of 'unsigned'' Signed-off-by: Clifton Barnes Acked-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/devices/vme_pio2_gpio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c index df992c3cb5ce..f52a9ed75871 100644 --- a/drivers/staging/vme/devices/vme_pio2_gpio.c +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -97,7 +97,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, } /* Directionality configured at board build - send appropriate response */ -static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) +static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned int offset) { int data; struct pio2_card *card = gpio_to_pio2_card(chip); @@ -116,7 +116,8 @@ static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) } /* Directionality configured at board build - send appropriate response */ -static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) +static int pio2_gpio_dir_out(struct gpio_chip *chip, + unsigned int offset, int value) { int data; struct pio2_card *card = gpio_to_pio2_card(chip); -- GitLab From 75b6462e965dc76d16254b5fcb3f41ca97f6fef0 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Fri, 11 Dec 2015 17:05:14 +0300 Subject: [PATCH 1234/9938] ixgbe: on recv increment rx.ring->stats.yields It seem to be non intentionally changed to Tx in commit adc810900a70 ("ixgbe: Refactor busy poll socket code to address multiple issues") Lock is taken from ixgbe_low_latency_recv, and there under this lock we use ixgbe_clean_rx_irq so it looks wrong for me to increment Tx counter. Yield stats can be shown through ethtool: ethtool -S enp129s0 | grep yield Signed-off-by: Pavel Tikhomirov Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index e4949af7dd6b..9f64354c9c9e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -456,7 +456,7 @@ static inline bool ixgbe_qv_lock_poll(struct ixgbe_q_vector *q_vector) IXGBE_QV_STATE_POLL); #ifdef BP_EXTENDED_STATS if (rc != IXGBE_QV_STATE_IDLE) - q_vector->tx.ring->stats.yields++; + q_vector->rx.ring->stats.yields++; #endif return rc == IXGBE_QV_STATE_IDLE; } -- GitLab From 39771b127b412377d6354893c7d43ee8f2edecfd Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Sat, 2 Apr 2016 23:08:06 -0400 Subject: [PATCH 1235/9938] sock: break up sock_cmsg_snd into __sock_cmsg_snd and loop To process cmsg's of the SOL_SOCKET level in addition to cmsgs of another level, protocols can call sock_cmsg_send(). This causes a double walk on the cmsghdr list, one for SOL_SOCKET and one for the other level. Extract the inner demultiplex logic from the loop that walks the list, to allow having this called directly from a walker in the protocol specific code. Signed-off-by: Willem de Bruijn Signed-off-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- include/net/sock.h | 2 ++ net/core/sock.c | 33 ++++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 255d3e03727b..03772d4b06e6 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1420,6 +1420,8 @@ struct sockcm_cookie { u32 mark; }; +int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, + struct sockcm_cookie *sockc); int sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct sockcm_cookie *sockc); diff --git a/net/core/sock.c b/net/core/sock.c index b67b9aedb230..66976f88566b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1866,27 +1866,38 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, } EXPORT_SYMBOL(sock_alloc_send_skb); +int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, + struct sockcm_cookie *sockc) +{ + switch (cmsg->cmsg_type) { + case SO_MARK: + if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) + return -EPERM; + if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32))) + return -EINVAL; + sockc->mark = *(u32 *)CMSG_DATA(cmsg); + break; + default: + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL(__sock_cmsg_send); + int sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct sockcm_cookie *sockc) { struct cmsghdr *cmsg; + int ret; for_each_cmsghdr(cmsg, msg) { if (!CMSG_OK(msg, cmsg)) return -EINVAL; if (cmsg->cmsg_level != SOL_SOCKET) continue; - switch (cmsg->cmsg_type) { - case SO_MARK: - if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) - return -EPERM; - if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32))) - return -EINVAL; - sockc->mark = *(u32 *)CMSG_DATA(cmsg); - break; - default: - return -EINVAL; - } + ret = __sock_cmsg_send(sk, msg, cmsg, sockc); + if (ret) + return ret; } return 0; } -- GitLab From 6db8b963a7a31047573f229492ff6fc0f51cc377 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 2 Apr 2016 23:08:07 -0400 Subject: [PATCH 1236/9938] tcp: accept SOF_TIMESTAMPING_OPT_ID for passive TFO SOF_TIMESTAMPING_OPT_ID is set to get data-independent IDs to associate timestamps with send calls. For TCP connections, tp->snd_una is used as the starting point to calculate relative IDs. This socket option will fail if set before the handshake on a passive TCP fast open connection with data in SYN or SYN/ACK, since setsockopt requires the connection to be in the ESTABLISHED state. To address these, instead of limiting the option to the ESTABLISHED state, accept the SOF_TIMESTAMPING_OPT_ID option as long as the connection is not in LISTEN or CLOSE states. Signed-off-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Acked-by: Yuchung Cheng Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/sock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 66976f88566b..0a64fe20ce5a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -832,7 +832,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname, !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { if (sk->sk_protocol == IPPROTO_TCP && sk->sk_type == SOCK_STREAM) { - if (sk->sk_state != TCP_ESTABLISHED) { + if ((1 << sk->sk_state) & + (TCPF_CLOSE | TCPF_LISTEN)) { ret = -EINVAL; break; } -- GitLab From 6b084928baac562ed61866f540a96120e9c9ddb7 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 2 Apr 2016 23:08:08 -0400 Subject: [PATCH 1237/9938] tcp: use one bit in TCP_SKB_CB to mark ACK timestamps Currently, to avoid a cache line miss for accessing skb_shinfo, tcp_ack_tstamp skips socket that do not have SOF_TIMESTAMPING_TX_ACK bit set in sk_tsflags. This is implemented based on an implicit assumption that the SOF_TIMESTAMPING_TX_ACK is set via socket options for the duration that ACK timestamps are needed. To implement per-write timestamps, this check should be removed and replaced with a per-packet alternative that quickly skips packets missing ACK timestamps marks without a cache-line miss. To enable per-packet marking without a cache line miss, use one bit in TCP_SKB_CB to mark a whether a SKB might need a ack tx timestamp or not. Further checks in tcp_ack_tstamp are not modified and work as before. Signed-off-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 3 ++- net/ipv4/tcp.c | 2 ++ net/ipv4/tcp_input.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index f8bb4a4ed3d1..a23282996ca9 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -754,7 +754,8 @@ struct tcp_skb_cb { TCPCB_REPAIRED) __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */ - /* 1 byte hole */ + __u8 txstamp_ack:1, /* Record TX timestamp for ack? */ + unused:7; __u32 ack_seq; /* Sequence number ACK'd */ union { struct inet_skb_parm h4; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 08b8b960a8ed..ce3c9eb901a0 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -432,10 +432,12 @@ static void tcp_tx_timestamp(struct sock *sk, struct sk_buff *skb) { if (sk->sk_tsflags) { struct skb_shared_info *shinfo = skb_shinfo(skb); + struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); sock_tx_timestamp(sk, &shinfo->tx_flags); if (shinfo->tx_flags & SKBTX_ANY_TSTAMP) shinfo->tskey = TCP_SKB_CB(skb)->seq + skb->len - 1; + tcb->txstamp_ack = !!(shinfo->tx_flags & SKBTX_ACK_TSTAMP); } } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index f87b84a75691..a26e2d262358 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3082,7 +3082,7 @@ static void tcp_ack_tstamp(struct sock *sk, struct sk_buff *skb, const struct skb_shared_info *shinfo; /* Avoid cache line misses to get skb_shinfo() and shinfo->tx_flags */ - if (likely(!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK))) + if (likely(!TCP_SKB_CB(skb)->txstamp_ack)) return; shinfo = skb_shinfo(skb); -- GitLab From 3dd17e63f5131bf2528f34aa5e3e57758175af92 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 2 Apr 2016 23:08:09 -0400 Subject: [PATCH 1238/9938] sock: accept SO_TIMESTAMPING flags in socket cmsg Accept SO_TIMESTAMPING in control messages of the SOL_SOCKET level as a basis to accept timestamping requests per write. This implementation only accepts TX recording flags (i.e., SOF_TIMESTAMPING_TX_HARDWARE, SOF_TIMESTAMPING_TX_SOFTWARE, SOF_TIMESTAMPING_TX_SCHED, and SOF_TIMESTAMPING_TX_ACK) in control messages. Users need to set reporting flags (e.g., SOF_TIMESTAMPING_OPT_ID) per socket via socket options. This commit adds a tsflags field in sockcm_cookie which is set in __sock_cmsg_send. It only override the SOF_TIMESTAMPING_TX_* bits in sockcm_cookie.tsflags allowing the control message to override the recording behavior per write, yet maintaining the value of other flags. This patch implements validating the control message and setting tsflags in struct sockcm_cookie. Next commits in this series will actually implement timestamping per write for different protocols. Signed-off-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/net/sock.h | 1 + include/uapi/linux/net_tstamp.h | 10 ++++++++++ net/core/sock.c | 13 +++++++++++++ 3 files changed, 24 insertions(+) diff --git a/include/net/sock.h b/include/net/sock.h index 03772d4b06e6..af012da5e608 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1418,6 +1418,7 @@ void sk_send_sigurg(struct sock *sk); struct sockcm_cookie { u32 mark; + u16 tsflags; }; int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h index 6d1abea9746e..264e515de16f 100644 --- a/include/uapi/linux/net_tstamp.h +++ b/include/uapi/linux/net_tstamp.h @@ -31,6 +31,16 @@ enum { SOF_TIMESTAMPING_LAST }; +/* + * SO_TIMESTAMPING flags are either for recording a packet timestamp or for + * reporting the timestamp to user space. + * Recording flags can be set both via socket options and control messages. + */ +#define SOF_TIMESTAMPING_TX_RECORD_MASK (SOF_TIMESTAMPING_TX_HARDWARE | \ + SOF_TIMESTAMPING_TX_SOFTWARE | \ + SOF_TIMESTAMPING_TX_SCHED | \ + SOF_TIMESTAMPING_TX_ACK) + /** * struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter * diff --git a/net/core/sock.c b/net/core/sock.c index 0a64fe20ce5a..315f5e57fffe 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1870,6 +1870,8 @@ EXPORT_SYMBOL(sock_alloc_send_skb); int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, struct sockcm_cookie *sockc) { + u32 tsflags; + switch (cmsg->cmsg_type) { case SO_MARK: if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) @@ -1878,6 +1880,17 @@ int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, return -EINVAL; sockc->mark = *(u32 *)CMSG_DATA(cmsg); break; + case SO_TIMESTAMPING: + if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32))) + return -EINVAL; + + tsflags = *(u32 *)CMSG_DATA(cmsg); + if (tsflags & ~SOF_TIMESTAMPING_TX_RECORD_MASK) + return -EINVAL; + + sockc->tsflags &= ~SOF_TIMESTAMPING_TX_RECORD_MASK; + sockc->tsflags |= tsflags; + break; default: return -EINVAL; } -- GitLab From 24025c465f77c3585f73450bab19501b2edd6fba Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 2 Apr 2016 23:08:10 -0400 Subject: [PATCH 1239/9938] ipv4: process socket-level control messages in IPv4 Process socket-level control messages by invoking __sock_cmsg_send in ip_cmsg_send for control messages on the SOL_SOCKET layer. This makes sure whenever ip_cmsg_send is called in udp, icmp, and raw, we also process socket-level control messages. Note that this commit interprets new control messages that were ignored before. As such, this commit does not change the behavior of IPv4 control messages. Signed-off-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/net/ip.h | 3 ++- net/ipv4/ip_sockglue.c | 9 ++++++++- net/ipv4/ping.c | 2 +- net/ipv4/raw.c | 2 +- net/ipv4/udp.c | 3 +-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index fad74d323bd6..93725e546758 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -56,6 +56,7 @@ static inline unsigned int ip_hdrlen(const struct sk_buff *skb) } struct ipcm_cookie { + struct sockcm_cookie sockc; __be32 addr; int oif; struct ip_options_rcu *opt; @@ -550,7 +551,7 @@ int ip_options_rcv_srr(struct sk_buff *skb); void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb); void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int offset); -int ip_cmsg_send(struct net *net, struct msghdr *msg, +int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc, bool allow_ipv6); int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 035ad645a8d9..1b7c0776c805 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -219,11 +219,12 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, } EXPORT_SYMBOL(ip_cmsg_recv_offset); -int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, +int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc, bool allow_ipv6) { int err, val; struct cmsghdr *cmsg; + struct net *net = sock_net(sk); for_each_cmsghdr(cmsg, msg) { if (!CMSG_OK(msg, cmsg)) @@ -244,6 +245,12 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, continue; } #endif + if (cmsg->cmsg_level == SOL_SOCKET) { + if (__sock_cmsg_send(sk, msg, cmsg, &ipc->sockc)) + return -EINVAL; + continue; + } + if (cmsg->cmsg_level != SOL_IP) continue; switch (cmsg->cmsg_type) { diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index cf9700b1a106..670639bf9f7e 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -747,7 +747,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) sock_tx_timestamp(sk, &ipc.tx_flags); if (msg->msg_controllen) { - err = ip_cmsg_send(sock_net(sk), msg, &ipc, false); + err = ip_cmsg_send(sk, msg, &ipc, false); if (unlikely(err)) { kfree(ipc.opt); return err; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 8d22de74080c..088ce665fc7b 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -548,7 +548,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ipc.oif = sk->sk_bound_dev_if; if (msg->msg_controllen) { - err = ip_cmsg_send(net, msg, &ipc, false); + err = ip_cmsg_send(sk, msg, &ipc, false); if (unlikely(err)) { kfree(ipc.opt); goto out; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 08eed5e16df0..bccb4e11047a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1034,8 +1034,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) sock_tx_timestamp(sk, &ipc.tx_flags); if (msg->msg_controllen) { - err = ip_cmsg_send(sock_net(sk), msg, &ipc, - sk->sk_family == AF_INET6); + err = ip_cmsg_send(sk, msg, &ipc, sk->sk_family == AF_INET6); if (unlikely(err)) { kfree(ipc.opt); return err; -- GitLab From ad1e46a837163a3e7160a1250825bcfafd2e714b Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 2 Apr 2016 23:08:11 -0400 Subject: [PATCH 1240/9938] ipv6: process socket-level control messages in IPv6 Process socket-level control messages by invoking __sock_cmsg_send in ip6_datagram_send_ctl for control messages on the SOL_SOCKET layer. This makes sure whenever ip6_datagram_send_ctl is called for udp and raw, we also process socket-level control messages. This is a bit uglier than IPv4, since IPv6 does not have something like ipcm_cookie. Perhaps we can later create a control message cookie for IPv6? Note that this commit interprets new control messages that were ignored before. As such, this commit does not change the behavior of IPv6 control messages. Signed-off-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/net/transp_v6.h | 3 ++- net/ipv6/datagram.c | 9 ++++++++- net/ipv6/ip6_flowlabel.c | 3 ++- net/ipv6/ipv6_sockglue.c | 3 ++- net/ipv6/raw.c | 6 +++++- net/ipv6/udp.c | 5 ++++- net/l2tp/l2tp_ip6.c | 8 +++++--- 7 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index b927413dde86..2b1c3450ab20 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -42,7 +42,8 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg, int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, struct flowi6 *fl6, struct ipv6_txoptions *opt, - int *hlimit, int *tclass, int *dontfrag); + int *hlimit, int *tclass, int *dontfrag, + struct sockcm_cookie *sockc); void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, __u16 srcp, __u16 destp, int bucket); diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 428162155280..a73d70119fcd 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -685,7 +685,8 @@ EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl); int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, struct flowi6 *fl6, struct ipv6_txoptions *opt, - int *hlimit, int *tclass, int *dontfrag) + int *hlimit, int *tclass, int *dontfrag, + struct sockcm_cookie *sockc) { struct in6_pktinfo *src_info; struct cmsghdr *cmsg; @@ -702,6 +703,12 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, goto exit_f; } + if (cmsg->cmsg_level == SOL_SOCKET) { + if (__sock_cmsg_send(sk, msg, cmsg, sockc)) + return -EINVAL; + continue; + } + if (cmsg->cmsg_level != SOL_IPV6) continue; diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index dc2db4f7b182..35d3ddc328f8 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -372,6 +372,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, if (olen > 0) { struct msghdr msg; struct flowi6 flowi6; + struct sockcm_cookie sockc_junk; int junk; err = -ENOMEM; @@ -390,7 +391,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, memset(&flowi6, 0, sizeof(flowi6)); err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, - &junk, &junk, &junk); + &junk, &junk, &junk, &sockc_junk); if (err) goto done; err = -EINVAL; diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 4449ad1f8114..a5557d22f89e 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -471,6 +471,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, struct ipv6_txoptions *opt = NULL; struct msghdr msg; struct flowi6 fl6; + struct sockcm_cookie sockc_junk; int junk; memset(&fl6, 0, sizeof(fl6)); @@ -503,7 +504,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, msg.msg_control = (void *)(opt+1); retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, - &junk, &junk); + &junk, &junk, &sockc_junk); if (retv) goto done; update: diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index fa59dd7a427e..f175ec0a97ce 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -745,6 +745,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) struct dst_entry *dst = NULL; struct raw6_frag_vec rfv; struct flowi6 fl6; + struct sockcm_cookie sockc; int addr_len = msg->msg_namelen; int hlimit = -1; int tclass = -1; @@ -821,13 +822,16 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (fl6.flowi6_oif == 0) fl6.flowi6_oif = sk->sk_bound_dev_if; + sockc.tsflags = 0; + if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_txoptions)); opt->tot_len = sizeof(struct ipv6_txoptions); err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, - &hlimit, &tclass, &dontfrag); + &hlimit, &tclass, &dontfrag, + &sockc); if (err < 0) { fl6_sock_release(flowlabel); return err; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8125931106be..2a787af42163 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1128,6 +1128,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) int connected = 0; int is_udplite = IS_UDPLITE(sk); int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); + struct sockcm_cookie sockc; /* destination address check */ if (sin6) { @@ -1247,6 +1248,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; fl6.flowi6_mark = sk->sk_mark; + sockc.tsflags = 0; if (msg->msg_controllen) { opt = &opt_space; @@ -1254,7 +1256,8 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) opt->tot_len = sizeof(*opt); err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, - &hlimit, &tclass, &dontfrag); + &hlimit, &tclass, &dontfrag, + &sockc); if (err < 0) { fl6_sock_release(flowlabel); return err; diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 6b54ff3ff4cb..4f29a4a0f360 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -492,6 +492,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) struct ip6_flowlabel *flowlabel = NULL; struct dst_entry *dst = NULL; struct flowi6 fl6; + struct sockcm_cookie sockc_unused = {0}; int addr_len = msg->msg_namelen; int hlimit = -1; int tclass = -1; @@ -562,9 +563,10 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) memset(opt, 0, sizeof(struct ipv6_txoptions)); opt->tot_len = sizeof(struct ipv6_txoptions); - err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, - &hlimit, &tclass, &dontfrag); - if (err < 0) { + err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, + &hlimit, &tclass, &dontfrag, + &sockc_unused); + if (err < 0) { fl6_sock_release(flowlabel); return err; } -- GitLab From c14ac9451c34832554db33386a4393be8bba3a7b Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 2 Apr 2016 23:08:12 -0400 Subject: [PATCH 1241/9938] sock: enable timestamping using control messages Currently, SOL_TIMESTAMPING can only be enabled using setsockopt. This is very costly when users want to sample writes to gather tx timestamps. Add support for enabling SO_TIMESTAMPING via control messages by using tsflags added in `struct sockcm_cookie` (added in the previous patches in this series) to set the tx_flags of the last skb created in a sendmsg. With this patch, the timestamp recording bits in tx_flags of the skbuff is overridden if SO_TIMESTAMPING is passed in a cmsg. Please note that this is only effective for overriding the recording timestamps flags. Users should enable timestamp reporting (e.g., SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID) using socket options and then should ask for SOF_TIMESTAMPING_TX_* using control messages per sendmsg to sample timestamps for each write. Signed-off-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Signed-off-by: David S. Miller --- drivers/net/tun.c | 3 ++- include/net/ipv6.h | 6 ++++-- include/net/sock.h | 10 ++++++---- net/can/raw.c | 2 +- net/ipv4/ping.c | 5 +++-- net/ipv4/raw.c | 11 ++++++----- net/ipv4/tcp.c | 20 +++++++++++++++----- net/ipv4/udp.c | 7 ++++--- net/ipv6/icmp.c | 6 ++++-- net/ipv6/ip6_output.c | 15 +++++++++------ net/ipv6/ping.c | 3 ++- net/ipv6/raw.c | 5 ++--- net/ipv6/udp.c | 7 ++++--- net/l2tp/l2tp_ip6.c | 2 +- net/packet/af_packet.c | 30 +++++++++++++++++++++++++----- net/socket.c | 10 +++++----- 16 files changed, 93 insertions(+), 49 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 510e90a6bb26..9abc36bf77ea 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -861,7 +861,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) goto drop; if (skb->sk && sk_fullsock(skb->sk)) { - sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags); + sock_tx_timestamp(skb->sk, skb->sk->sk_tsflags, + &skb_shinfo(skb)->tx_flags); sw_tx_timestamp(skb); } diff --git a/include/net/ipv6.h b/include/net/ipv6.h index d0aeb97aec5d..55ee1eb7d026 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -867,7 +867,8 @@ int ip6_append_data(struct sock *sk, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, - struct rt6_info *rt, unsigned int flags, int dontfrag); + struct rt6_info *rt, unsigned int flags, int dontfrag, + const struct sockcm_cookie *sockc); int ip6_push_pending_frames(struct sock *sk); @@ -884,7 +885,8 @@ struct sk_buff *ip6_make_skb(struct sock *sk, void *from, int length, int transhdrlen, int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, struct rt6_info *rt, - unsigned int flags, int dontfrag); + unsigned int flags, int dontfrag, + const struct sockcm_cookie *sockc); static inline struct sk_buff *ip6_finish_skb(struct sock *sk) { diff --git a/include/net/sock.h b/include/net/sock.h index af012da5e608..e91b87f54f99 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2057,19 +2057,21 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, sk->sk_stamp = skb->tstamp; } -void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags); +void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags); /** * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped * @sk: socket sending this packet + * @tsflags: timestamping flags to use * @tx_flags: completed with instructions for time stamping * * Note : callers should take care of initial *tx_flags value (usually 0) */ -static inline void sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags) +static inline void sock_tx_timestamp(const struct sock *sk, __u16 tsflags, + __u8 *tx_flags) { - if (unlikely(sk->sk_tsflags)) - __sock_tx_timestamp(sk, tx_flags); + if (unlikely(tsflags)) + __sock_tx_timestamp(tsflags, tx_flags); if (unlikely(sock_flag(sk, SOCK_WIFI_STATUS))) *tx_flags |= SKBTX_WIFI_STATUS; } diff --git a/net/can/raw.c b/net/can/raw.c index 2e67b1423cd3..972c187d40ab 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -755,7 +755,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) if (err < 0) goto free_skb; - sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); + sock_tx_timestamp(sk, sk->sk_tsflags, &skb_shinfo(skb)->tx_flags); skb->dev = dev; skb->sk = sk; diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 670639bf9f7e..66ddcb60519a 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -737,6 +737,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) /* no remote port */ } + ipc.sockc.tsflags = sk->sk_tsflags; ipc.addr = inet->inet_saddr; ipc.opt = NULL; ipc.oif = sk->sk_bound_dev_if; @@ -744,8 +745,6 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ipc.ttl = 0; ipc.tos = -1; - sock_tx_timestamp(sk, &ipc.tx_flags); - if (msg->msg_controllen) { err = ip_cmsg_send(sk, msg, &ipc, false); if (unlikely(err)) { @@ -768,6 +767,8 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) rcu_read_unlock(); } + sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags); + saddr = ipc.addr; ipc.addr = faddr = daddr; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 088ce665fc7b..438f50c1a676 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -339,8 +339,8 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb) static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, struct msghdr *msg, size_t length, - struct rtable **rtp, - unsigned int flags) + struct rtable **rtp, unsigned int flags, + const struct sockcm_cookie *sockc) { struct inet_sock *inet = inet_sk(sk); struct net *net = sock_net(sk); @@ -379,7 +379,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, skb->ip_summed = CHECKSUM_NONE; - sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); + sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags); skb->transport_header = skb->network_header; err = -EFAULT; @@ -540,6 +540,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) daddr = inet->inet_daddr; } + ipc.sockc.tsflags = sk->sk_tsflags; ipc.addr = inet->inet_saddr; ipc.opt = NULL; ipc.tx_flags = 0; @@ -638,10 +639,10 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (inet->hdrincl) err = raw_send_hdrinc(sk, &fl4, msg, len, - &rt, msg->msg_flags); + &rt, msg->msg_flags, &ipc.sockc); else { - sock_tx_timestamp(sk, &ipc.tx_flags); + sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags); if (!ipc.addr) ipc.addr = fl4.daddr; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ce3c9eb901a0..4d73858991af 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -428,13 +428,13 @@ void tcp_init_sock(struct sock *sk) } EXPORT_SYMBOL(tcp_init_sock); -static void tcp_tx_timestamp(struct sock *sk, struct sk_buff *skb) +static void tcp_tx_timestamp(struct sock *sk, u16 tsflags, struct sk_buff *skb) { - if (sk->sk_tsflags) { + if (sk->sk_tsflags || tsflags) { struct skb_shared_info *shinfo = skb_shinfo(skb); struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); - sock_tx_timestamp(sk, &shinfo->tx_flags); + sock_tx_timestamp(sk, tsflags, &shinfo->tx_flags); if (shinfo->tx_flags & SKBTX_ANY_TSTAMP) shinfo->tskey = TCP_SKB_CB(skb)->seq + skb->len - 1; tcb->txstamp_ack = !!(shinfo->tx_flags & SKBTX_ACK_TSTAMP); @@ -959,7 +959,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, offset += copy; size -= copy; if (!size) { - tcp_tx_timestamp(sk, skb); + tcp_tx_timestamp(sk, sk->sk_tsflags, skb); goto out; } @@ -1079,6 +1079,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; + struct sockcm_cookie sockc; int flags, err, copied = 0; int mss_now = 0, size_goal, copied_syn = 0; bool sg; @@ -1121,6 +1122,15 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) /* 'common' sending to sendq */ } + sockc.tsflags = sk->sk_tsflags; + if (msg->msg_controllen) { + err = sock_cmsg_send(sk, msg, &sockc); + if (unlikely(err)) { + err = -EINVAL; + goto out_err; + } + } + /* This should be in poll */ sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); @@ -1239,7 +1249,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) copied += copy; if (!msg_data_left(msg)) { - tcp_tx_timestamp(sk, skb); + tcp_tx_timestamp(sk, sockc.tsflags, skb); goto out; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index bccb4e11047a..45ff590661f4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1027,12 +1027,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) */ connected = 1; } - ipc.addr = inet->inet_saddr; + ipc.sockc.tsflags = sk->sk_tsflags; + ipc.addr = inet->inet_saddr; ipc.oif = sk->sk_bound_dev_if; - sock_tx_timestamp(sk, &ipc.tx_flags); - if (msg->msg_controllen) { err = ip_cmsg_send(sk, msg, &ipc, sk->sk_family == AF_INET6); if (unlikely(err)) { @@ -1059,6 +1058,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) saddr = ipc.addr; ipc.addr = faddr = daddr; + sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags); + if (ipc.opt && ipc.opt->opt.srr) { if (!daddr) return -EINVAL; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 0a37ddc7af51..6b573ebe49de 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -400,6 +400,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) struct icmp6hdr tmp_hdr; struct flowi6 fl6; struct icmpv6_msg msg; + struct sockcm_cookie sockc_unused = {0}; int iif = 0; int addr_type = 0; int len; @@ -527,7 +528,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) len + sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl6, (struct rt6_info *)dst, - MSG_DONTWAIT, np->dontfrag); + MSG_DONTWAIT, np->dontfrag, &sockc_unused); if (err) { ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); ip6_flush_pending_frames(sk); @@ -566,6 +567,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) int hlimit; u8 tclass; u32 mark = IP6_REPLY_MARK(net, skb->mark); + struct sockcm_cookie sockc_unused = {0}; saddr = &ipv6_hdr(skb)->daddr; @@ -617,7 +619,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl6, (struct rt6_info *)dst, MSG_DONTWAIT, - np->dontfrag); + np->dontfrag, &sockc_unused); if (err) { ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9428345d3a07..612f3d138bf0 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1258,7 +1258,8 @@ static int __ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, - unsigned int flags, int dontfrag) + unsigned int flags, int dontfrag, + const struct sockcm_cookie *sockc) { struct sk_buff *skb, *skb_prev = NULL; unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu; @@ -1329,7 +1330,7 @@ static int __ip6_append_data(struct sock *sk, csummode = CHECKSUM_PARTIAL; if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { - sock_tx_timestamp(sk, &tx_flags); + sock_tx_timestamp(sk, sockc->tsflags, &tx_flags); if (tx_flags & SKBTX_ANY_SW_TSTAMP && sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) tskey = sk->sk_tskey++; @@ -1565,7 +1566,8 @@ int ip6_append_data(struct sock *sk, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, - struct rt6_info *rt, unsigned int flags, int dontfrag) + struct rt6_info *rt, unsigned int flags, int dontfrag, + const struct sockcm_cookie *sockc) { struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); @@ -1593,7 +1595,8 @@ int ip6_append_data(struct sock *sk, return __ip6_append_data(sk, fl6, &sk->sk_write_queue, &inet->cork.base, &np->cork, sk_page_frag(sk), getfrag, - from, length, transhdrlen, flags, dontfrag); + from, length, transhdrlen, flags, dontfrag, + sockc); } EXPORT_SYMBOL_GPL(ip6_append_data); @@ -1752,7 +1755,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk, int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, struct rt6_info *rt, unsigned int flags, - int dontfrag) + int dontfrag, const struct sockcm_cookie *sockc) { struct inet_cork_full cork; struct inet6_cork v6_cork; @@ -1779,7 +1782,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk, err = __ip6_append_data(sk, fl6, &queue, &cork.base, &v6_cork, ¤t->task_frag, getfrag, from, length + exthdrlen, transhdrlen + exthdrlen, - flags, dontfrag); + flags, dontfrag, sockc); if (err) { __ip6_flush_pending_frames(sk, &queue, &cork, &v6_cork); return ERR_PTR(err); diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index c382db7a2e73..da1cff79e447 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -62,6 +62,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) struct dst_entry *dst; struct rt6_info *rt; struct pingfakehdr pfh; + struct sockcm_cookie junk = {0}; pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); @@ -144,7 +145,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) err = ip6_append_data(sk, ping_getfrag, &pfh, len, 0, hlimit, np->tclass, NULL, &fl6, rt, - MSG_DONTWAIT, np->dontfrag); + MSG_DONTWAIT, np->dontfrag, &junk); if (err) { ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev, diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index f175ec0a97ce..b07ce21983aa 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -822,8 +822,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (fl6.flowi6_oif == 0) fl6.flowi6_oif = sk->sk_bound_dev_if; - sockc.tsflags = 0; - + sockc.tsflags = sk->sk_tsflags; if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_txoptions)); @@ -901,7 +900,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) lock_sock(sk); err = ip6_append_data(sk, raw6_getfrag, &rfv, len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, - msg->msg_flags, dontfrag); + msg->msg_flags, dontfrag, &sockc); if (err) ip6_flush_pending_frames(sk); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 2a787af42163..b772a7641fbd 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1248,7 +1248,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; fl6.flowi6_mark = sk->sk_mark; - sockc.tsflags = 0; + sockc.tsflags = sk->sk_tsflags; if (msg->msg_controllen) { opt = &opt_space; @@ -1324,7 +1324,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) skb = ip6_make_skb(sk, getfrag, msg, ulen, sizeof(struct udphdr), hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, - msg->msg_flags, dontfrag); + msg->msg_flags, dontfrag, &sockc); err = PTR_ERR(skb); if (!IS_ERR_OR_NULL(skb)) err = udp_v6_send_skb(skb, &fl6); @@ -1351,7 +1351,8 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr), hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, - corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); + corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag, + &sockc); if (err) udp_v6_flush_pending_frames(sk); else if (!corkreq) diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 4f29a4a0f360..1a38f20b1ca6 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -627,7 +627,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) err = ip6_append_data(sk, ip_generic_getfrag, msg, ulen, transhdrlen, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, - msg->msg_flags, dontfrag); + msg->msg_flags, dontfrag, &sockc_unused); if (err) ip6_flush_pending_frames(sk); else if (!(msg->msg_flags & MSG_MORE)) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1ecfa710ca98..0007e23202e4 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1837,6 +1837,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, DECLARE_SOCKADDR(struct sockaddr_pkt *, saddr, msg->msg_name); struct sk_buff *skb = NULL; struct net_device *dev; + struct sockcm_cookie sockc; __be16 proto = 0; int err; int extra_len = 0; @@ -1925,12 +1926,21 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, goto out_unlock; } + sockc.tsflags = 0; + if (msg->msg_controllen) { + err = sock_cmsg_send(sk, msg, &sockc); + if (unlikely(err)) { + err = -EINVAL; + goto out_unlock; + } + } + skb->protocol = proto; skb->dev = dev; skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); + sock_tx_timestamp(sk, sockc.tsflags, &skb_shinfo(skb)->tx_flags); if (unlikely(extra_len == 4)) skb->no_fcs = 1; @@ -2486,7 +2496,8 @@ static int packet_snd_vnet_gso(struct sk_buff *skb, static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, void *frame, struct net_device *dev, void *data, int tp_len, - __be16 proto, unsigned char *addr, int hlen, int copylen) + __be16 proto, unsigned char *addr, int hlen, int copylen, + const struct sockcm_cookie *sockc) { union tpacket_uhdr ph; int to_write, offset, len, nr_frags, len_max; @@ -2500,7 +2511,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, skb->dev = dev; skb->priority = po->sk.sk_priority; skb->mark = po->sk.sk_mark; - sock_tx_timestamp(&po->sk, &skb_shinfo(skb)->tx_flags); + sock_tx_timestamp(&po->sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags); skb_shinfo(skb)->destructor_arg = ph.raw; skb_reserve(skb, hlen); @@ -2624,6 +2635,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) struct sk_buff *skb; struct net_device *dev; struct virtio_net_hdr *vnet_hdr = NULL; + struct sockcm_cookie sockc; __be16 proto; int err, reserve = 0; void *ph; @@ -2655,6 +2667,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); } + sockc.tsflags = 0; + if (msg->msg_controllen) { + err = sock_cmsg_send(&po->sk, msg, &sockc); + if (unlikely(err)) + goto out; + } + err = -ENXIO; if (unlikely(dev == NULL)) goto out; @@ -2712,7 +2731,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) goto out_status; } tp_len = tpacket_fill_skb(po, skb, ph, dev, data, tp_len, proto, - addr, hlen, copylen); + addr, hlen, copylen, &sockc); if (likely(tp_len >= 0) && tp_len > dev->mtu + reserve && !po->has_vnet_hdr && @@ -2851,6 +2870,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) if (unlikely(!(dev->flags & IFF_UP))) goto out_unlock; + sockc.tsflags = 0; sockc.mark = sk->sk_mark; if (msg->msg_controllen) { err = sock_cmsg_send(sk, msg, &sockc); @@ -2908,7 +2928,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) goto out_free; } - sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); + sock_tx_timestamp(sk, sockc.tsflags, &skb_shinfo(skb)->tx_flags); if (!vnet_hdr.gso_type && (len > dev->mtu + reserve + extra_len) && !packet_extra_vlan_len_allowed(dev, skb)) { diff --git a/net/socket.c b/net/socket.c index 5f77a8e93830..979d3146b081 100644 --- a/net/socket.c +++ b/net/socket.c @@ -587,20 +587,20 @@ void sock_release(struct socket *sock) } EXPORT_SYMBOL(sock_release); -void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags) +void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) { u8 flags = *tx_flags; - if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE) + if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) flags |= SKBTX_HW_TSTAMP; - if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) + if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) flags |= SKBTX_SW_TSTAMP; - if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED) + if (tsflags & SOF_TIMESTAMPING_TX_SCHED) flags |= SKBTX_SCHED_TSTAMP; - if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK) + if (tsflags & SOF_TIMESTAMPING_TX_ACK) flags |= SKBTX_ACK_TSTAMP; *tx_flags = flags; -- GitLab From fd91e12f594b40fdb2dad530e8b895cc5c07db21 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 2 Apr 2016 23:08:13 -0400 Subject: [PATCH 1242/9938] sock: document timestamping via cmsg in Documentation Update docs and add code snippet for using cmsg for timestamping. Signed-off-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Signed-off-by: David S. Miller --- Documentation/networking/timestamping.txt | 48 +++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt index a977339fbe0a..671cccf0dcd2 100644 --- a/Documentation/networking/timestamping.txt +++ b/Documentation/networking/timestamping.txt @@ -44,11 +44,17 @@ timeval of SO_TIMESTAMP (ms). Supports multiple types of timestamp requests. As a result, this socket option takes a bitmap of flags, not a boolean. In - err = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, (void *) val, &val); + err = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, (void *) val, + sizeof(val)); val is an integer with any of the following bits set. Setting other bit returns EINVAL and does not change the current state. +The socket option configures timestamp generation for individual +sk_buffs (1.3.1), timestamp reporting to the socket's error +queue (1.3.2) and options (1.3.3). Timestamp generation can also +be enabled for individual sendmsg calls using cmsg (1.3.4). + 1.3.1 Timestamp Generation @@ -71,13 +77,16 @@ SOF_TIMESTAMPING_RX_SOFTWARE: kernel receive stack. SOF_TIMESTAMPING_TX_HARDWARE: - Request tx timestamps generated by the network adapter. + Request tx timestamps generated by the network adapter. This flag + can be enabled via both socket options and control messages. SOF_TIMESTAMPING_TX_SOFTWARE: Request tx timestamps when data leaves the kernel. These timestamps are generated in the device driver as close as possible, but always prior to, passing the packet to the network interface. Hence, they require driver support and may not be available for all devices. + This flag can be enabled via both socket options and control messages. + SOF_TIMESTAMPING_TX_SCHED: Request tx timestamps prior to entering the packet scheduler. Kernel @@ -90,7 +99,8 @@ SOF_TIMESTAMPING_TX_SCHED: machines with virtual devices where a transmitted packet travels through multiple devices and, hence, multiple packet schedulers, a timestamp is generated at each layer. This allows for fine - grained measurement of queuing delay. + grained measurement of queuing delay. This flag can be enabled + via both socket options and control messages. SOF_TIMESTAMPING_TX_ACK: Request tx timestamps when all data in the send buffer has been @@ -99,6 +109,7 @@ SOF_TIMESTAMPING_TX_ACK: over-report measurement, because the timestamp is generated when all data up to and including the buffer at send() was acknowledged: the cumulative acknowledgment. The mechanism ignores SACK and FACK. + This flag can be enabled via both socket options and control messages. 1.3.2 Timestamp Reporting @@ -183,6 +194,37 @@ having access to the contents of the original packet, so cannot be combined with SOF_TIMESTAMPING_OPT_TSONLY. +1.3.4. Enabling timestamps via control messages + +In addition to socket options, timestamp generation can be requested +per write via cmsg, only for SOF_TIMESTAMPING_TX_* (see Section 1.3.1). +Using this feature, applications can sample timestamps per sendmsg() +without paying the overhead of enabling and disabling timestamps via +setsockopt: + + struct msghdr *msg; + ... + cmsg = CMSG_FIRSTHDR(msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPING; + cmsg->cmsg_len = CMSG_LEN(sizeof(__u32)); + *((__u32 *) CMSG_DATA(cmsg)) = SOF_TIMESTAMPING_TX_SCHED | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_TX_ACK; + err = sendmsg(fd, msg, 0); + +The SOF_TIMESTAMPING_TX_* flags set via cmsg will override +the SOF_TIMESTAMPING_TX_* flags set via setsockopt. + +Moreover, applications must still enable timestamp reporting via +setsockopt to receive timestamps: + + __u32 val = SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_OPT_ID /* or any other flag */; + err = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, (void *) val, + sizeof(val)); + + 1.4 Bytestream Timestamps The SO_TIMESTAMPING interface supports timestamping of bytes in a -- GitLab From d5dd7c3fa4dbff70fc25acf54acb63cf971fd6e9 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 17 Dec 2015 17:32:55 -0800 Subject: [PATCH 1243/9938] ixgbevf: use bit operations for setting and checking resets Move the reset flags to adapter->state in order to make use of bit operations. This is an alternative patch to the one previously submitted by John Greene. Suggested-by: Alexander Duyck Reported-by: Scott Otto Reported-by: John Greene Signed-off-by: Emil Tantilov Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 9 ++------- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 15 ++++++--------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 991eeae81473..5ac60eefb0cd 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -403,13 +403,6 @@ struct ixgbevf_adapter { u32 alloc_rx_page_failed; u32 alloc_rx_buff_failed; - /* Some features need tri-state capability, - * thus the additional *_CAPABLE flags. - */ - u32 flags; -#define IXGBEVF_FLAG_RESET_REQUESTED (u32)(1) -#define IXGBEVF_FLAG_QUEUE_RESET_REQUESTED (u32)(1 << 2) - struct msix_entry *msix_entries; /* OS defined structs */ @@ -461,6 +454,8 @@ enum ixbgevf_state_t { __IXGBEVF_REMOVING, __IXGBEVF_SERVICE_SCHED, __IXGBEVF_SERVICE_INITED, + __IXGBEVF_RESET_REQUESTED, + __IXGBEVF_QUEUE_RESET_REQUESTED, }; enum ixgbevf_boards { diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index b0edae94d73d..9a2eed0f5245 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -268,7 +268,7 @@ static void ixgbevf_tx_timeout_reset(struct ixgbevf_adapter *adapter) { /* Do the reset outside of interrupt context */ if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) { - adapter->flags |= IXGBEVF_FLAG_RESET_REQUESTED; + set_bit(__IXGBEVF_RESET_REQUESTED, &adapter->state); ixgbevf_service_event_schedule(adapter); } } @@ -1984,7 +1984,7 @@ static int ixgbevf_configure_dcb(struct ixgbevf_adapter *adapter) hw->mbx.timeout = 0; /* wait for watchdog to come around and bail us out */ - adapter->flags |= IXGBEVF_FLAG_QUEUE_RESET_REQUESTED; + set_bit(__IXGBEVF_QUEUE_RESET_REQUESTED, &adapter->state); } return 0; @@ -2749,11 +2749,9 @@ static void ixgbevf_service_timer(unsigned long data) static void ixgbevf_reset_subtask(struct ixgbevf_adapter *adapter) { - if (!(adapter->flags & IXGBEVF_FLAG_RESET_REQUESTED)) + if (!test_and_clear_bit(__IXGBEVF_RESET_REQUESTED, &adapter->state)) return; - adapter->flags &= ~IXGBEVF_FLAG_RESET_REQUESTED; - /* If we're already down or resetting, just bail */ if (test_bit(__IXGBEVF_DOWN, &adapter->state) || test_bit(__IXGBEVF_RESETTING, &adapter->state)) @@ -2821,7 +2819,7 @@ static void ixgbevf_watchdog_update_link(struct ixgbevf_adapter *adapter) /* if check for link returns error we will need to reset */ if (err && time_after(jiffies, adapter->last_reset + (10 * HZ))) { - adapter->flags |= IXGBEVF_FLAG_RESET_REQUESTED; + set_bit(__IXGBEVF_RESET_REQUESTED, &adapter->state); link_up = false; } @@ -3222,11 +3220,10 @@ static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter) { struct net_device *dev = adapter->netdev; - if (!(adapter->flags & IXGBEVF_FLAG_QUEUE_RESET_REQUESTED)) + if (!test_and_clear_bit(__IXGBEVF_QUEUE_RESET_REQUESTED, + &adapter->state)) return; - adapter->flags &= ~IXGBEVF_FLAG_QUEUE_RESET_REQUESTED; - /* if interface is down do nothing */ if (test_bit(__IXGBEVF_DOWN, &adapter->state) || test_bit(__IXGBEVF_RESETTING, &adapter->state)) -- GitLab From 1d96cf9822bf801b1a93a0817e45dd02af5ac0e6 Mon Sep 17 00:00:00 2001 From: chas williams <3chas3@gmail.com> Date: Tue, 5 Jan 2016 17:30:39 -0500 Subject: [PATCH 1244/9938] ixgbe: Extend trust to allow guest to set unicast address When running certain routing protocols like VRRP, VF guests need the ability to set the unicast address of the interface. Extend the new ndo trust feature to let the hypervisor trust a guest to set/update its own unicast address. Signed-off-by: Chas Williams <3chas3@gmail.com> Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 8025a3f93598..80e47dbc530b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -887,7 +887,7 @@ static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter, return -1; } - if (adapter->vfinfo[vf].pf_set_mac && + if (adapter->vfinfo[vf].pf_set_mac && !adapter->vfinfo[vf].trusted && !ether_addr_equal(adapter->vfinfo[vf].vf_mac_addresses, new_mac)) { e_warn(drv, "VF %d attempted to override administratively set MAC address\n" -- GitLab From 18be4fce00fef206dc6f104a6a258b193e9871cf Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 Jan 2016 22:48:44 -0800 Subject: [PATCH 1245/9938] ixgbe: Do not allow PF to add VLVF entry unless it actually needs it While doing the work on igb I realized there were a few cases where we were still adding VLANs to the VLVF entries for the PF when they were not needed. This patch cleans that up so that the only time we add a PF entry to the VLVF is either for VLAN 0 or if the PF has requested a VLAN that a VF is already using. Signed-off-by: Alexander Duyck Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 8 ++--- .../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 31 ++++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 7df3fe29b210..a01a7f251e03 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3908,7 +3908,9 @@ static int ixgbe_vlan_rx_add_vid(struct net_device *netdev, struct ixgbe_hw *hw = &adapter->hw; /* add VID to filter table */ - hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), true, true); + if (!vid || !(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC)) + hw->mac.ops.set_vfta(&adapter->hw, vid, VMDQ_P(0), true, !!vid); + set_bit(vid, adapter->active_vlans); return 0; @@ -3965,9 +3967,7 @@ static int ixgbe_vlan_rx_kill_vid(struct net_device *netdev, struct ixgbe_hw *hw = &adapter->hw; /* remove VID from filter table */ - if (adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC) - ixgbe_update_pf_promisc_vlvf(adapter, vid); - else + if (vid && !(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC)) hw->mac.ops.set_vfta(hw, vid, VMDQ_P(0), false, true); clear_bit(vid, adapter->active_vlans); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 80e47dbc530b..4bc249632ec2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -589,40 +589,40 @@ static void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf) static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; - u32 i; + u32 vlvfb_mask, pool_mask, i; + + /* create mask for VF and other pools */ + pool_mask = ~(1 << (VMDQ_P(0) % 32)); + vlvfb_mask = 1 << (vf % 32); /* post increment loop, covers VLVF_ENTRIES - 1 to 0 */ for (i = IXGBE_VLVF_ENTRIES; i--;) { u32 bits[2], vlvfb, vid, vfta, vlvf; u32 word = i * 2 + vf / 32; - u32 mask = 1 << (vf % 32); + u32 mask; vlvfb = IXGBE_READ_REG(hw, IXGBE_VLVFB(word)); /* if our bit isn't set we can skip it */ - if (!(vlvfb & mask)) + if (!(vlvfb & vlvfb_mask)) continue; /* clear our bit from vlvfb */ - vlvfb ^= mask; + vlvfb ^= vlvfb_mask; /* create 64b mask to chedk to see if we should clear VLVF */ bits[word % 2] = vlvfb; bits[~word % 2] = IXGBE_READ_REG(hw, IXGBE_VLVFB(word ^ 1)); - /* if promisc is enabled, PF will be present, leave VFTA */ - if (adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC) { - bits[VMDQ_P(0) / 32] &= ~(1 << (VMDQ_P(0) % 32)); - - if (bits[0] || bits[1]) - goto update_vlvfb; - goto update_vlvf; - } - /* if other pools are present, just remove ourselves */ - if (bits[0] || bits[1]) + if (bits[(VMDQ_P(0) / 32) ^ 1] || + (bits[VMDQ_P(0) / 32] & pool_mask)) goto update_vlvfb; + /* if PF is present, leave VFTA */ + if (bits[0] || bits[1]) + goto update_vlvf; + /* if we cannot determine VLAN just remove ourselves */ vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(i)); if (!vlvf) @@ -638,6 +638,9 @@ static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf) update_vlvf: /* clear POOL selection enable */ IXGBE_WRITE_REG(hw, IXGBE_VLVF(i), 0); + + if (!(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC)) + vlvfb = 0; update_vlvfb: /* clear pool bits */ IXGBE_WRITE_REG(hw, IXGBE_VLVFB(word), vlvfb); -- GitLab From f51bdc236b6c5835fa5e0df772acc234288b8af2 Mon Sep 17 00:00:00 2001 From: Kazuya Mizuguchi Date: Sun, 3 Apr 2016 23:54:38 +0900 Subject: [PATCH 1246/9938] ravb: Add dma queue interrupt support This patch supports the following interrupts. - One interrupt for multiple (timestamp, error, gPTP) - One interrupt for emac - Four interrupts for dma queue (best effort rx/tx, network control rx/tx) This patch improve efficiency of the interrupt handler by adding the interrupt handler corresponding to each interrupt source described above. Additionally, it reduces the number of times of the access to EthernetAVB IF. Also this patch prevent this driver depends on the whim of a boot loader. [ykaneko0929@gmail.com: define bit names of registers] [ykaneko0929@gmail.com: add comment for gen3 only registers] [ykaneko0929@gmail.com: fix coding style] [ykaneko0929@gmail.com: update changelog] [ykaneko0929@gmail.com: gen3: fix initialization of interrupts] [ykaneko0929@gmail.com: gen3: fix clearing interrupts] [ykaneko0929@gmail.com: gen3: add helper function for request_irq()] [ykaneko0929@gmail.com: gen3: remove IRQF_SHARED flag for request_irq()] [ykaneko0929@gmail.com: revert ravb_close() and ravb_ptp_stop()] [ykaneko0929@gmail.com: avoid calling free_irq() to non-hooked interrupts] [ykaneko0929@gmail.com: make NC/BE interrupt handler a function] [ykaneko0929@gmail.com: make timestamp interrupt handler a function] [ykaneko0929@gmail.com: timestamp interrupt is handled in multiple interrupt handler instead of dma queue interrupt handler] Signed-off-by: Kazuya Mizuguchi Signed-off-by: Yoshihiro Kaneko Acked-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb.h | 204 +++++++++++++++++ drivers/net/ethernet/renesas/ravb_main.c | 266 +++++++++++++++++++---- drivers/net/ethernet/renesas/ravb_ptp.c | 17 +- 3 files changed, 439 insertions(+), 48 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h index b2160d1b9c71..5c1624147778 100644 --- a/drivers/net/ethernet/renesas/ravb.h +++ b/drivers/net/ethernet/renesas/ravb.h @@ -157,6 +157,7 @@ enum ravb_reg { TIC = 0x0378, TIS = 0x037C, ISS = 0x0380, + CIE = 0x0384, /* R-Car Gen3 only */ GCCR = 0x0390, GMTT = 0x0394, GPTC = 0x0398, @@ -170,6 +171,15 @@ enum ravb_reg { GCT0 = 0x03B8, GCT1 = 0x03BC, GCT2 = 0x03C0, + GIE = 0x03CC, /* R-Car Gen3 only */ + GID = 0x03D0, /* R-Car Gen3 only */ + DIL = 0x0440, /* R-Car Gen3 only */ + RIE0 = 0x0460, /* R-Car Gen3 only */ + RID0 = 0x0464, /* R-Car Gen3 only */ + RIE2 = 0x0470, /* R-Car Gen3 only */ + RID2 = 0x0474, /* R-Car Gen3 only */ + TIE = 0x0478, /* R-Car Gen3 only */ + TID = 0x047c, /* R-Car Gen3 only */ /* E-MAC registers */ ECMR = 0x0500, @@ -556,6 +566,16 @@ enum ISS_BIT { ISS_DPS15 = 0x80000000, }; +/* CIE (R-Car Gen3 only) */ +enum CIE_BIT { + CIE_CRIE = 0x00000001, + CIE_CTIE = 0x00000100, + CIE_RQFM = 0x00010000, + CIE_CL0M = 0x00020000, + CIE_RFWL = 0x00040000, + CIE_RFFL = 0x00080000, +}; + /* GCCR */ enum GCCR_BIT { GCCR_TCR = 0x00000003, @@ -592,6 +612,188 @@ enum GIS_BIT { GIS_PTMF = 0x00000004, }; +/* GIE (R-Car Gen3 only) */ +enum GIE_BIT { + GIE_PTCS = 0x00000001, + GIE_PTOS = 0x00000002, + GIE_PTMS0 = 0x00000004, + GIE_PTMS1 = 0x00000008, + GIE_PTMS2 = 0x00000010, + GIE_PTMS3 = 0x00000020, + GIE_PTMS4 = 0x00000040, + GIE_PTMS5 = 0x00000080, + GIE_PTMS6 = 0x00000100, + GIE_PTMS7 = 0x00000200, + GIE_ATCS0 = 0x00010000, + GIE_ATCS1 = 0x00020000, + GIE_ATCS2 = 0x00040000, + GIE_ATCS3 = 0x00080000, + GIE_ATCS4 = 0x00100000, + GIE_ATCS5 = 0x00200000, + GIE_ATCS6 = 0x00400000, + GIE_ATCS7 = 0x00800000, + GIE_ATCS8 = 0x01000000, + GIE_ATCS9 = 0x02000000, + GIE_ATCS10 = 0x04000000, + GIE_ATCS11 = 0x08000000, + GIE_ATCS12 = 0x10000000, + GIE_ATCS13 = 0x20000000, + GIE_ATCS14 = 0x40000000, + GIE_ATCS15 = 0x80000000, +}; + +/* GID (R-Car Gen3 only) */ +enum GID_BIT { + GID_PTCD = 0x00000001, + GID_PTOD = 0x00000002, + GID_PTMD0 = 0x00000004, + GID_PTMD1 = 0x00000008, + GID_PTMD2 = 0x00000010, + GID_PTMD3 = 0x00000020, + GID_PTMD4 = 0x00000040, + GID_PTMD5 = 0x00000080, + GID_PTMD6 = 0x00000100, + GID_PTMD7 = 0x00000200, + GID_ATCD0 = 0x00010000, + GID_ATCD1 = 0x00020000, + GID_ATCD2 = 0x00040000, + GID_ATCD3 = 0x00080000, + GID_ATCD4 = 0x00100000, + GID_ATCD5 = 0x00200000, + GID_ATCD6 = 0x00400000, + GID_ATCD7 = 0x00800000, + GID_ATCD8 = 0x01000000, + GID_ATCD9 = 0x02000000, + GID_ATCD10 = 0x04000000, + GID_ATCD11 = 0x08000000, + GID_ATCD12 = 0x10000000, + GID_ATCD13 = 0x20000000, + GID_ATCD14 = 0x40000000, + GID_ATCD15 = 0x80000000, +}; + +/* RIE0 (R-Car Gen3 only) */ +enum RIE0_BIT { + RIE0_FRS0 = 0x00000001, + RIE0_FRS1 = 0x00000002, + RIE0_FRS2 = 0x00000004, + RIE0_FRS3 = 0x00000008, + RIE0_FRS4 = 0x00000010, + RIE0_FRS5 = 0x00000020, + RIE0_FRS6 = 0x00000040, + RIE0_FRS7 = 0x00000080, + RIE0_FRS8 = 0x00000100, + RIE0_FRS9 = 0x00000200, + RIE0_FRS10 = 0x00000400, + RIE0_FRS11 = 0x00000800, + RIE0_FRS12 = 0x00001000, + RIE0_FRS13 = 0x00002000, + RIE0_FRS14 = 0x00004000, + RIE0_FRS15 = 0x00008000, + RIE0_FRS16 = 0x00010000, + RIE0_FRS17 = 0x00020000, +}; + +/* RID0 (R-Car Gen3 only) */ +enum RID0_BIT { + RID0_FRD0 = 0x00000001, + RID0_FRD1 = 0x00000002, + RID0_FRD2 = 0x00000004, + RID0_FRD3 = 0x00000008, + RID0_FRD4 = 0x00000010, + RID0_FRD5 = 0x00000020, + RID0_FRD6 = 0x00000040, + RID0_FRD7 = 0x00000080, + RID0_FRD8 = 0x00000100, + RID0_FRD9 = 0x00000200, + RID0_FRD10 = 0x00000400, + RID0_FRD11 = 0x00000800, + RID0_FRD12 = 0x00001000, + RID0_FRD13 = 0x00002000, + RID0_FRD14 = 0x00004000, + RID0_FRD15 = 0x00008000, + RID0_FRD16 = 0x00010000, + RID0_FRD17 = 0x00020000, +}; + +/* RIE2 (R-Car Gen3 only) */ +enum RIE2_BIT { + RIE2_QFS0 = 0x00000001, + RIE2_QFS1 = 0x00000002, + RIE2_QFS2 = 0x00000004, + RIE2_QFS3 = 0x00000008, + RIE2_QFS4 = 0x00000010, + RIE2_QFS5 = 0x00000020, + RIE2_QFS6 = 0x00000040, + RIE2_QFS7 = 0x00000080, + RIE2_QFS8 = 0x00000100, + RIE2_QFS9 = 0x00000200, + RIE2_QFS10 = 0x00000400, + RIE2_QFS11 = 0x00000800, + RIE2_QFS12 = 0x00001000, + RIE2_QFS13 = 0x00002000, + RIE2_QFS14 = 0x00004000, + RIE2_QFS15 = 0x00008000, + RIE2_QFS16 = 0x00010000, + RIE2_QFS17 = 0x00020000, + RIE2_RFFS = 0x80000000, +}; + +/* RID2 (R-Car Gen3 only) */ +enum RID2_BIT { + RID2_QFD0 = 0x00000001, + RID2_QFD1 = 0x00000002, + RID2_QFD2 = 0x00000004, + RID2_QFD3 = 0x00000008, + RID2_QFD4 = 0x00000010, + RID2_QFD5 = 0x00000020, + RID2_QFD6 = 0x00000040, + RID2_QFD7 = 0x00000080, + RID2_QFD8 = 0x00000100, + RID2_QFD9 = 0x00000200, + RID2_QFD10 = 0x00000400, + RID2_QFD11 = 0x00000800, + RID2_QFD12 = 0x00001000, + RID2_QFD13 = 0x00002000, + RID2_QFD14 = 0x00004000, + RID2_QFD15 = 0x00008000, + RID2_QFD16 = 0x00010000, + RID2_QFD17 = 0x00020000, + RID2_RFFD = 0x80000000, +}; + +/* TIE (R-Car Gen3 only) */ +enum TIE_BIT { + TIE_FTS0 = 0x00000001, + TIE_FTS1 = 0x00000002, + TIE_FTS2 = 0x00000004, + TIE_FTS3 = 0x00000008, + TIE_TFUS = 0x00000100, + TIE_TFWS = 0x00000200, + TIE_MFUS = 0x00000400, + TIE_MFWS = 0x00000800, + TIE_TDPS0 = 0x00010000, + TIE_TDPS1 = 0x00020000, + TIE_TDPS2 = 0x00040000, + TIE_TDPS3 = 0x00080000, +}; + +/* TID (R-Car Gen3 only) */ +enum TID_BIT { + TID_FTD0 = 0x00000001, + TID_FTD1 = 0x00000002, + TID_FTD2 = 0x00000004, + TID_FTD3 = 0x00000008, + TID_TFUD = 0x00000100, + TID_TFWD = 0x00000200, + TID_MFUD = 0x00000400, + TID_MFWD = 0x00000800, + TID_TDPD0 = 0x00010000, + TID_TDPD1 = 0x00020000, + TID_TDPD2 = 0x00040000, + TID_TDPD3 = 0x00080000, +}; + /* ECMR */ enum ECMR_BIT { ECMR_PRM = 0x00000001, @@ -817,6 +1019,8 @@ struct ravb_private { int duplex; int emac_irq; enum ravb_chip_id chip_id; + int rx_irqs[NUM_RX_QUEUE]; + int tx_irqs[NUM_TX_QUEUE]; unsigned no_avb_link:1; unsigned avb_link_active_low:1; diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 087e14a3fba7..4b71951e185d 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -42,6 +42,16 @@ NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) +static const char *ravb_rx_irqs[NUM_RX_QUEUE] = { + "ch0", /* RAVB_BE */ + "ch1", /* RAVB_NC */ +}; + +static const char *ravb_tx_irqs[NUM_TX_QUEUE] = { + "ch18", /* RAVB_BE */ + "ch19", /* RAVB_NC */ +}; + void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear, u32 set) { @@ -365,6 +375,7 @@ static void ravb_emac_init(struct net_device *ndev) /* Device init function for Ethernet AVB */ static int ravb_dmac_init(struct net_device *ndev) { + struct ravb_private *priv = netdev_priv(ndev); int error; /* Set CONFIG mode */ @@ -401,6 +412,12 @@ static int ravb_dmac_init(struct net_device *ndev) ravb_write(ndev, TCCR_TFEN, TCCR); /* Interrupt init: */ + if (priv->chip_id == RCAR_GEN3) { + /* Clear DIL.DPLx */ + ravb_write(ndev, 0, DIL); + /* Set queue specific interrupt */ + ravb_write(ndev, CIE_CRIE | CIE_CTIE | CIE_CL0M, CIE); + } /* Frame receive */ ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0); /* Disable FIFO full warning */ @@ -643,7 +660,7 @@ static int ravb_stop_dma(struct net_device *ndev) } /* E-MAC interrupt handler */ -static void ravb_emac_interrupt(struct net_device *ndev) +static void ravb_emac_interrupt_unlocked(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); u32 ecsr, psr; @@ -669,6 +686,18 @@ static void ravb_emac_interrupt(struct net_device *ndev) } } +static irqreturn_t ravb_emac_interrupt(int irq, void *dev_id) +{ + struct net_device *ndev = dev_id; + struct ravb_private *priv = netdev_priv(ndev); + + spin_lock(&priv->lock); + ravb_emac_interrupt_unlocked(ndev); + mmiowb(); + spin_unlock(&priv->lock); + return IRQ_HANDLED; +} + /* Error interrupt handler */ static void ravb_error_interrupt(struct net_device *ndev) { @@ -695,6 +724,50 @@ static void ravb_error_interrupt(struct net_device *ndev) } } +static bool ravb_queue_interrupt(struct net_device *ndev, int q) +{ + struct ravb_private *priv = netdev_priv(ndev); + u32 ris0 = ravb_read(ndev, RIS0); + u32 ric0 = ravb_read(ndev, RIC0); + u32 tis = ravb_read(ndev, TIS); + u32 tic = ravb_read(ndev, TIC); + + if (((ris0 & ric0) & BIT(q)) || ((tis & tic) & BIT(q))) { + if (napi_schedule_prep(&priv->napi[q])) { + /* Mask RX and TX interrupts */ + if (priv->chip_id == RCAR_GEN2) { + ravb_write(ndev, ric0 & ~BIT(q), RIC0); + ravb_write(ndev, tic & ~BIT(q), TIC); + } else { + ravb_write(ndev, BIT(q), RID0); + ravb_write(ndev, BIT(q), TID); + } + __napi_schedule(&priv->napi[q]); + } else { + netdev_warn(ndev, + "ignoring interrupt, rx status 0x%08x, rx mask 0x%08x,\n", + ris0, ric0); + netdev_warn(ndev, + " tx status 0x%08x, tx mask 0x%08x.\n", + tis, tic); + } + return true; + } + return false; +} + +static bool ravb_timestamp_interrupt(struct net_device *ndev) +{ + u32 tis = ravb_read(ndev, TIS); + + if (tis & TIS_TFUF) { + ravb_write(ndev, ~TIS_TFUF, TIS); + ravb_get_tx_tstamp(ndev); + return true; + } + return false; +} + static irqreturn_t ravb_interrupt(int irq, void *dev_id) { struct net_device *ndev = dev_id; @@ -708,46 +781,22 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id) /* Received and transmitted interrupts */ if (iss & (ISS_FRS | ISS_FTS | ISS_TFUS)) { - u32 ris0 = ravb_read(ndev, RIS0); - u32 ric0 = ravb_read(ndev, RIC0); - u32 tis = ravb_read(ndev, TIS); - u32 tic = ravb_read(ndev, TIC); int q; /* Timestamp updated */ - if (tis & TIS_TFUF) { - ravb_write(ndev, ~TIS_TFUF, TIS); - ravb_get_tx_tstamp(ndev); + if (ravb_timestamp_interrupt(ndev)) result = IRQ_HANDLED; - } /* Network control and best effort queue RX/TX */ for (q = RAVB_NC; q >= RAVB_BE; q--) { - if (((ris0 & ric0) & BIT(q)) || - ((tis & tic) & BIT(q))) { - if (napi_schedule_prep(&priv->napi[q])) { - /* Mask RX and TX interrupts */ - ric0 &= ~BIT(q); - tic &= ~BIT(q); - ravb_write(ndev, ric0, RIC0); - ravb_write(ndev, tic, TIC); - __napi_schedule(&priv->napi[q]); - } else { - netdev_warn(ndev, - "ignoring interrupt, rx status 0x%08x, rx mask 0x%08x,\n", - ris0, ric0); - netdev_warn(ndev, - " tx status 0x%08x, tx mask 0x%08x.\n", - tis, tic); - } + if (ravb_queue_interrupt(ndev, q)) result = IRQ_HANDLED; - } } } /* E-MAC status summary */ if (iss & ISS_MS) { - ravb_emac_interrupt(ndev); + ravb_emac_interrupt_unlocked(ndev); result = IRQ_HANDLED; } @@ -757,6 +806,7 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id) result = IRQ_HANDLED; } + /* gPTP interrupt status summary */ if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED) result = IRQ_HANDLED; @@ -765,6 +815,64 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id) return result; } +/* Timestamp/Error/gPTP interrupt handler */ +static irqreturn_t ravb_multi_interrupt(int irq, void *dev_id) +{ + struct net_device *ndev = dev_id; + struct ravb_private *priv = netdev_priv(ndev); + irqreturn_t result = IRQ_NONE; + u32 iss; + + spin_lock(&priv->lock); + /* Get interrupt status */ + iss = ravb_read(ndev, ISS); + + /* Timestamp updated */ + if ((iss & ISS_TFUS) && ravb_timestamp_interrupt(ndev)) + result = IRQ_HANDLED; + + /* Error status summary */ + if (iss & ISS_ES) { + ravb_error_interrupt(ndev); + result = IRQ_HANDLED; + } + + /* gPTP interrupt status summary */ + if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED) + result = IRQ_HANDLED; + + mmiowb(); + spin_unlock(&priv->lock); + return result; +} + +static irqreturn_t ravb_dma_interrupt(int irq, void *dev_id, int q) +{ + struct net_device *ndev = dev_id; + struct ravb_private *priv = netdev_priv(ndev); + irqreturn_t result = IRQ_NONE; + + spin_lock(&priv->lock); + + /* Network control/Best effort queue RX/TX */ + if (ravb_queue_interrupt(ndev, q)) + result = IRQ_HANDLED; + + mmiowb(); + spin_unlock(&priv->lock); + return result; +} + +static irqreturn_t ravb_be_interrupt(int irq, void *dev_id) +{ + return ravb_dma_interrupt(irq, dev_id, RAVB_BE); +} + +static irqreturn_t ravb_nc_interrupt(int irq, void *dev_id) +{ + return ravb_dma_interrupt(irq, dev_id, RAVB_NC); +} + static int ravb_poll(struct napi_struct *napi, int budget) { struct net_device *ndev = napi->dev; @@ -804,8 +912,13 @@ static int ravb_poll(struct napi_struct *napi, int budget) /* Re-enable RX/TX interrupts */ spin_lock_irqsave(&priv->lock, flags); - ravb_modify(ndev, RIC0, mask, mask); - ravb_modify(ndev, TIC, mask, mask); + if (priv->chip_id == RCAR_GEN2) { + ravb_modify(ndev, RIC0, mask, mask); + ravb_modify(ndev, TIC, mask, mask); + } else { + ravb_write(ndev, mask, RIE0); + ravb_write(ndev, mask, TIE); + } mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); @@ -1208,35 +1321,72 @@ static const struct ethtool_ops ravb_ethtool_ops = { .get_ts_info = ravb_get_ts_info, }; +static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler, + struct net_device *ndev, struct device *dev, + const char *ch) +{ + char *name; + int error; + + name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch); + if (!name) + return -ENOMEM; + error = request_irq(irq, handler, 0, name, ndev); + if (error) + netdev_err(ndev, "cannot request IRQ %s\n", name); + + return error; +} + /* Network device open function for Ethernet AVB */ static int ravb_open(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); + struct platform_device *pdev = priv->pdev; + struct device *dev = &pdev->dev; int error; napi_enable(&priv->napi[RAVB_BE]); napi_enable(&priv->napi[RAVB_NC]); - error = request_irq(ndev->irq, ravb_interrupt, IRQF_SHARED, ndev->name, - ndev); - if (error) { - netdev_err(ndev, "cannot request IRQ\n"); - goto out_napi_off; - } - - if (priv->chip_id == RCAR_GEN3) { - error = request_irq(priv->emac_irq, ravb_interrupt, - IRQF_SHARED, ndev->name, ndev); + if (priv->chip_id == RCAR_GEN2) { + error = request_irq(ndev->irq, ravb_interrupt, IRQF_SHARED, + ndev->name, ndev); if (error) { netdev_err(ndev, "cannot request IRQ\n"); - goto out_free_irq; + goto out_napi_off; } + } else { + error = ravb_hook_irq(ndev->irq, ravb_multi_interrupt, ndev, + dev, "ch22:multi"); + if (error) + goto out_napi_off; + error = ravb_hook_irq(priv->emac_irq, ravb_emac_interrupt, ndev, + dev, "ch24:emac"); + if (error) + goto out_free_irq; + error = ravb_hook_irq(priv->rx_irqs[RAVB_BE], ravb_be_interrupt, + ndev, dev, "ch0:rx_be"); + if (error) + goto out_free_irq_emac; + error = ravb_hook_irq(priv->tx_irqs[RAVB_BE], ravb_be_interrupt, + ndev, dev, "ch18:tx_be"); + if (error) + goto out_free_irq_be_rx; + error = ravb_hook_irq(priv->rx_irqs[RAVB_NC], ravb_nc_interrupt, + ndev, dev, "ch1:rx_nc"); + if (error) + goto out_free_irq_be_tx; + error = ravb_hook_irq(priv->tx_irqs[RAVB_NC], ravb_nc_interrupt, + ndev, dev, "ch19:tx_nc"); + if (error) + goto out_free_irq_nc_rx; } /* Device init */ error = ravb_dmac_init(ndev); if (error) - goto out_free_irq2; + goto out_free_irq_nc_tx; ravb_emac_init(ndev); /* Initialise PTP Clock driver */ @@ -1256,9 +1406,18 @@ static int ravb_open(struct net_device *ndev) /* Stop PTP Clock driver */ if (priv->chip_id == RCAR_GEN2) ravb_ptp_stop(ndev); -out_free_irq2: - if (priv->chip_id == RCAR_GEN3) - free_irq(priv->emac_irq, ndev); +out_free_irq_nc_tx: + if (priv->chip_id == RCAR_GEN2) + goto out_free_irq; + free_irq(priv->tx_irqs[RAVB_NC], ndev); +out_free_irq_nc_rx: + free_irq(priv->rx_irqs[RAVB_NC], ndev); +out_free_irq_be_tx: + free_irq(priv->tx_irqs[RAVB_BE], ndev); +out_free_irq_be_rx: + free_irq(priv->rx_irqs[RAVB_BE], ndev); +out_free_irq_emac: + free_irq(priv->emac_irq, ndev); out_free_irq: free_irq(ndev->irq, ndev); out_napi_off: @@ -1713,6 +1872,7 @@ static int ravb_probe(struct platform_device *pdev) struct net_device *ndev; int error, irq, q; struct resource *res; + int i; if (!np) { dev_err(&pdev->dev, @@ -1782,6 +1942,22 @@ static int ravb_probe(struct platform_device *pdev) goto out_release; } priv->emac_irq = irq; + for (i = 0; i < NUM_RX_QUEUE; i++) { + irq = platform_get_irq_byname(pdev, ravb_rx_irqs[i]); + if (irq < 0) { + error = irq; + goto out_release; + } + priv->rx_irqs[i] = irq; + } + for (i = 0; i < NUM_TX_QUEUE; i++) { + irq = platform_get_irq_byname(pdev, ravb_tx_irqs[i]); + if (irq < 0) { + error = irq; + goto out_release; + } + priv->tx_irqs[i] = irq; + } } priv->chip_id = chip_id; diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c index 57992ccc4657..f1b2cbb336e8 100644 --- a/drivers/net/ethernet/renesas/ravb_ptp.c +++ b/drivers/net/ethernet/renesas/ravb_ptp.c @@ -194,7 +194,12 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp, priv->ptp.extts[req->index] = on; spin_lock_irqsave(&priv->lock, flags); - ravb_modify(ndev, GIC, GIC_PTCE, on ? GIC_PTCE : 0); + if (priv->chip_id == RCAR_GEN2) + ravb_modify(ndev, GIC, GIC_PTCE, on ? GIC_PTCE : 0); + else if (on) + ravb_write(ndev, GIE_PTCS, GIE); + else + ravb_write(ndev, GID_PTCD, GID); mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); @@ -241,7 +246,10 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp, error = ravb_ptp_update_compare(priv, (u32)start_ns); if (!error) { /* Unmask interrupt */ - ravb_modify(ndev, GIC, GIC_PTME, GIC_PTME); + if (priv->chip_id == RCAR_GEN2) + ravb_modify(ndev, GIC, GIC_PTME, GIC_PTME); + else + ravb_write(ndev, GIE_PTMS0, GIE); } } else { spin_lock_irqsave(&priv->lock, flags); @@ -250,7 +258,10 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp, perout->period = 0; /* Mask interrupt */ - ravb_modify(ndev, GIC, GIC_PTME, 0); + if (priv->chip_id == RCAR_GEN2) + ravb_modify(ndev, GIC, GIC_PTME, 0); + else + ravb_write(ndev, GID_PTMD0, GID); } mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); -- GitLab From 96ec6310908a5f02450b18206d85e531f08cfa97 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 29 Mar 2016 19:11:11 -0700 Subject: [PATCH 1247/9938] net: macb: Fix coding style error message checkpatch.pl gave the following error: ERROR: space required before the open parenthesis '(' + for(; p < end; p++, offset += 4) Acked-by: Nicolas Ferre Acked-by: Michal Simek Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 48a7d7dee846..b5aa96e8f1b5 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -499,7 +499,7 @@ static void macb_update_stats(struct macb *bp) WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); - for(; p < end; p++, offset += 4) + for (; p < end; p++, offset += 4) *p += bp->macb_reg_readl(bp, offset); } -- GitLab From 64ec42fe272322c73ee159c68f7fb31896f65d1a Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 29 Mar 2016 19:11:12 -0700 Subject: [PATCH 1248/9938] net: macb: Fix coding style warnings This commit takes care of the coding style warnings that are mostly due to a different comment style and lines over 80 chars, as well as a dangling else. Acked-by: Nicolas Ferre Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 100 ++++++++++++---------------- 1 file changed, 42 insertions(+), 58 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index b5aa96e8f1b5..f25681ba6418 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -61,8 +61,7 @@ #define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) #define MACB_WOL_ENABLED (0x1 << 1) -/* - * Graceful stop timeouts in us. We should allow up to +/* Graceful stop timeouts in us. We should allow up to * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions) */ #define MACB_HALT_TIMEOUT 1230 @@ -130,8 +129,7 @@ static void hw_writel(struct macb *bp, int offset, u32 value) writel_relaxed(value, bp->regs + offset); } -/* - * Find the CPU endianness by using the loopback bit of NCR register. When the +/* Find the CPU endianness by using the loopback bit of NCR register. When the * CPU is in big endian we need to program swaped mode for management * descriptor access. */ @@ -386,7 +384,8 @@ static int macb_mii_probe(struct net_device *dev) pdata = dev_get_platdata(&bp->pdev->dev); if (pdata && gpio_is_valid(pdata->phy_irq_pin)) { - ret = devm_gpio_request(&bp->pdev->dev, pdata->phy_irq_pin, "phy int"); + ret = devm_gpio_request(&bp->pdev->dev, pdata->phy_irq_pin, + "phy int"); if (!ret) { phy_irq = gpio_to_irq(pdata->phy_irq_pin); phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq; @@ -452,7 +451,8 @@ static int macb_mii_init(struct macb *bp) err = of_mdiobus_register(bp->mii_bus, np); /* fallback to standard phy registration if no phy were - found during dt phy registration */ + * found during dt phy registration + */ if (!err && !phy_find_first(bp->mii_bus)) { for (i = 0; i < PHY_MAX_ADDR; i++) { struct phy_device *phydev; @@ -567,8 +567,7 @@ static void macb_tx_error_task(struct work_struct *work) /* Make sure nobody is trying to queue up new packets */ netif_tx_stop_all_queues(bp->dev); - /* - * Stop transmission now + /* Stop transmission now * (in case we have just queued new packets) * macb/gem must be halted to write TBQP register */ @@ -576,8 +575,7 @@ static void macb_tx_error_task(struct work_struct *work) /* Just complain for now, reinitializing TX path can be good */ netdev_err(bp->dev, "BUG: halt tx timed out\n"); - /* - * Treat frames in TX queue including the ones that caused the error. + /* Treat frames in TX queue including the ones that caused the error. * Free transmit buffers in upper layer. */ for (tail = queue->tx_tail; tail != queue->tx_head; tail++) { @@ -607,10 +605,9 @@ static void macb_tx_error_task(struct work_struct *work) bp->stats.tx_bytes += skb->len; } } else { - /* - * "Buffers exhausted mid-frame" errors may only happen - * if the driver is buggy, so complain loudly about those. - * Statistics are updated by hardware. + /* "Buffers exhausted mid-frame" errors may only happen + * if the driver is buggy, so complain loudly about + * those. Statistics are updated by hardware. */ if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED)) netdev_err(bp->dev, @@ -722,7 +719,8 @@ static void gem_rx_refill(struct macb *bp) struct sk_buff *skb; dma_addr_t paddr; - while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, RX_RING_SIZE) > 0) { + while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, + RX_RING_SIZE) > 0) { entry = macb_rx_ring_wrap(bp->rx_prepared_head); /* Make hw descriptor updates visible to CPU */ @@ -741,7 +739,8 @@ static void gem_rx_refill(struct macb *bp) /* now fill corresponding descriptor entry */ paddr = dma_map_single(&bp->pdev->dev, skb->data, - bp->rx_buffer_size, DMA_FROM_DEVICE); + bp->rx_buffer_size, + DMA_FROM_DEVICE); if (dma_mapping_error(&bp->pdev->dev, paddr)) { dev_kfree_skb(skb); break; @@ -777,14 +776,14 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin, for (frag = begin; frag != end; frag++) { struct macb_dma_desc *desc = macb_rx_desc(bp, frag); + desc->addr &= ~MACB_BIT(RX_USED); } /* Make descriptor updates visible to hardware */ wmb(); - /* - * When this happens, the hardware stats registers for + /* When this happens, the hardware stats registers for * whatever caused this is updated, so we don't have to record * anything. */ @@ -883,8 +882,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, macb_rx_ring_wrap(first_frag), macb_rx_ring_wrap(last_frag), len); - /* - * The ethernet header starts NET_IP_ALIGN bytes into the + /* The ethernet header starts NET_IP_ALIGN bytes into the * first buffer. Since the header is 14 bytes, this makes the * payload word-aligned. * @@ -1099,8 +1097,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) (unsigned long)status); if (status & MACB_RX_INT_FLAGS) { - /* - * There's no point taking any more interrupts + /* There's no point taking any more interrupts * until we have processed the buffers. The * scheduling call may fail if the poll routine * is already scheduled, so disable interrupts @@ -1129,8 +1126,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) if (status & MACB_BIT(TCOMP)) macb_tx_interrupt(queue); - /* - * Link change detection isn't possible with RMII, so we'll + /* Link change detection isn't possible with RMII, so we'll * add that if/when we get our hands on a full-blown MII PHY. */ @@ -1161,8 +1157,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) } if (status & MACB_BIT(HRESP)) { - /* - * TODO: Reset the hardware, and maybe move the + /* TODO: Reset the hardware, and maybe move the * netdev_err to a lower-priority context as well * (work queue?) */ @@ -1181,8 +1176,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) } #ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling receive - used by netconsole and other diagnostic tools +/* Polling receive - used by netconsole and other diagnostic tools * to allow network i/o with interrupts disabled. */ static void macb_poll_controller(struct net_device *dev) @@ -1478,10 +1472,10 @@ static int gem_alloc_rx_buffers(struct macb *bp) bp->rx_skbuff = kzalloc(size, GFP_KERNEL); if (!bp->rx_skbuff) return -ENOMEM; - else - netdev_dbg(bp->dev, - "Allocated %d RX struct sk_buff entries at %p\n", - RX_RING_SIZE, bp->rx_skbuff); + + netdev_dbg(bp->dev, + "Allocated %d RX struct sk_buff entries at %p\n", + RX_RING_SIZE, bp->rx_skbuff); return 0; } @@ -1494,10 +1488,10 @@ static int macb_alloc_rx_buffers(struct macb *bp) &bp->rx_buffers_dma, GFP_KERNEL); if (!bp->rx_buffers) return -ENOMEM; - else - netdev_dbg(bp->dev, - "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n", - size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers); + + netdev_dbg(bp->dev, + "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers); return 0; } @@ -1588,8 +1582,7 @@ static void macb_reset_hw(struct macb *bp) struct macb_queue *queue; unsigned int q; - /* - * Disable RX and TX (XXX: Should we halt the transmission + /* Disable RX and TX (XXX: Should we halt the transmission * more gracefully?) */ macb_writel(bp, NCR, 0); @@ -1652,8 +1645,7 @@ static u32 macb_mdc_clk_div(struct macb *bp) return config; } -/* - * Get the DMA bus width field of the network configuration register that we +/* Get the DMA bus width field of the network configuration register that we * should program. We find the width from decoding the design configuration * register to find the maximum supported data bus width. */ @@ -1673,8 +1665,7 @@ static u32 macb_dbw(struct macb *bp) } } -/* - * Configure the receive DMA engine +/* Configure the receive DMA engine * - use the correct receive buffer size * - set best burst length for DMA operations * (if not supported by FIFO, it will fallback to default) @@ -1762,8 +1753,7 @@ static void macb_init_hw(struct macb *bp) macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE)); } -/* - * The hash address register is 64 bits long and takes up two +/* The hash address register is 64 bits long and takes up two * locations in the memory map. The least significant bits are stored * in EMAC_HSL and the most significant bits in EMAC_HSH. * @@ -1803,9 +1793,7 @@ static inline int hash_bit_value(int bitnr, __u8 *addr) return 0; } -/* - * Return the hash index value for the specified address. - */ +/* Return the hash index value for the specified address. */ static int hash_get_index(__u8 *addr) { int i, j, bitval; @@ -1821,9 +1809,7 @@ static int hash_get_index(__u8 *addr) return hash_index; } -/* - * Add multicast addresses to the internal multicast-hash table. - */ +/* Add multicast addresses to the internal multicast-hash table. */ static void macb_sethashtable(struct net_device *dev) { struct netdev_hw_addr *ha; @@ -1842,9 +1828,7 @@ static void macb_sethashtable(struct net_device *dev) macb_or_gem_writel(bp, HRT, mc_filter[1]); } -/* - * Enable/Disable promiscuous and multicast modes. - */ +/* Enable/Disable promiscuous and multicast modes. */ static void macb_set_rx_mode(struct net_device *dev) { unsigned long cfg; @@ -2161,9 +2145,8 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs, if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) regs_buff[12] = macb_or_gem_readl(bp, USRIO); - if (macb_is_gem(bp)) { + if (macb_is_gem(bp)) regs_buff[13] = gem_readl(bp, DMACFG); - } } static void macb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) @@ -2286,11 +2269,11 @@ static const struct net_device_ops macb_netdev_ops = { .ndo_set_features = macb_set_features, }; -/* - * Configure peripheral capabilities according to device tree +/* Configure peripheral capabilities according to device tree * and integration options used */ -static void macb_configure_caps(struct macb *bp, const struct macb_config *dt_conf) +static void macb_configure_caps(struct macb *bp, + const struct macb_config *dt_conf) { u32 dcfg; @@ -2996,6 +2979,7 @@ static int macb_probe(struct platform_device *pdev) phy_node = of_get_next_available_child(np, NULL); if (phy_node) { int gpio = of_get_named_gpio(phy_node, "reset-gpios", 0); + if (gpio_is_valid(gpio)) { bp->reset_gpio = gpio_to_desc(gpio); gpiod_direction_output(bp->reset_gpio, 1); -- GitLab From aa50b55262d459f69c7b32eb7ce38cde84cc089b Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 29 Mar 2016 19:11:13 -0700 Subject: [PATCH 1249/9938] net: macb: Fix coding style suggestions This commit deals with a bunch of checkpatch suggestions that without changing behavior make checkpatch happier. Acked-by: Michal Simek Acked-by: Nicolas Ferre Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 46 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index f25681ba6418..2ba0934e52dc 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -187,7 +187,7 @@ static void macb_get_hwaddr(struct macb *bp) pdata = dev_get_platdata(&bp->pdev->dev); - /* Check all 4 address register for vaild address */ + /* Check all 4 address register for valid address */ for (i = 0; i < 4; i++) { bottom = macb_or_gem_readl(bp, SA1B + i * 8); top = macb_or_gem_readl(bp, SA1T + i * 8); @@ -295,7 +295,7 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev) ferr = DIV_ROUND_UP(ferr, rate / 100000); if (ferr > 5) netdev_warn(dev, "unable to generate target frequency: %ld Hz\n", - rate); + rate); if (clk_set_rate(clk, rate_rounded)) netdev_err(dev, "adjusting tx_clk failed.\n"); @@ -429,7 +429,7 @@ static int macb_mii_init(struct macb *bp) macb_writel(bp, NCR, MACB_BIT(MPE)); bp->mii_bus = mdiobus_alloc(); - if (bp->mii_bus == NULL) { + if (!bp->mii_bus) { err = -ENOMEM; goto err_out; } @@ -438,7 +438,7 @@ static int macb_mii_init(struct macb *bp) bp->mii_bus->read = &macb_mdio_read; bp->mii_bus->write = &macb_mdio_write; snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", - bp->pdev->name, bp->pdev->id); + bp->pdev->name, bp->pdev->id); bp->mii_bus->priv = bp; bp->mii_bus->parent = &bp->dev->dev; pdata = dev_get_platdata(&bp->pdev->dev); @@ -659,7 +659,7 @@ static void macb_tx_interrupt(struct macb_queue *queue) queue_writel(queue, ISR, MACB_BIT(TCOMP)); netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n", - (unsigned long)status); + (unsigned long)status); head = queue->tx_head; for (tail = queue->tx_tail; tail != head; tail++) { @@ -728,10 +728,10 @@ static void gem_rx_refill(struct macb *bp) bp->rx_prepared_head++; - if (bp->rx_skbuff[entry] == NULL) { + if (!bp->rx_skbuff[entry]) { /* allocate sk_buff for this free entry in ring */ skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size); - if (unlikely(skb == NULL)) { + if (unlikely(!skb)) { netdev_err(bp->dev, "Unable to allocate sk_buff\n"); break; @@ -765,7 +765,7 @@ static void gem_rx_refill(struct macb *bp) wmb(); netdev_vdbg(bp->dev, "rx ring: prepared head %d, tail %d\n", - bp->rx_prepared_head, bp->rx_tail); + bp->rx_prepared_head, bp->rx_tail); } /* Mark DMA descriptors from begin up to and not including end as unused */ @@ -879,8 +879,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, len = desc->ctrl & bp->rx_frm_len_mask; netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n", - macb_rx_ring_wrap(first_frag), - macb_rx_ring_wrap(last_frag), len); + macb_rx_ring_wrap(first_frag), + macb_rx_ring_wrap(last_frag), len); /* The ethernet header starts NET_IP_ALIGN bytes into the * first buffer. Since the header is 14 bytes, this makes the @@ -922,7 +922,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, frag_len = len - offset; } skb_copy_to_linear_data_offset(skb, offset, - macb_rx_buffer(bp, frag), frag_len); + macb_rx_buffer(bp, frag), + frag_len); offset += bp->rx_buffer_size; desc = macb_rx_desc(bp, frag); desc->addr &= ~MACB_BIT(RX_USED); @@ -940,7 +941,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, bp->stats.rx_packets++; bp->stats.rx_bytes += skb->len; netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n", - skb->len, skb->csum); + skb->len, skb->csum); netif_receive_skb(skb); return 0; @@ -1047,7 +1048,7 @@ static int macb_poll(struct napi_struct *napi, int budget) work_done = 0; netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n", - (unsigned long)status, budget); + (unsigned long)status, budget); work_done = bp->macbgem_ops.mog_rx(bp, budget); if (work_done < budget) { @@ -1262,7 +1263,7 @@ static unsigned int macb_tx_map(struct macb *bp, } /* Should never happen */ - if (unlikely(tx_skb == NULL)) { + if (unlikely(!tx_skb)) { netdev_err(bp->dev, "BUG! empty skb!\n"); return 0; } @@ -1332,16 +1333,16 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) #if defined(DEBUG) && defined(VERBOSE_DEBUG) netdev_vdbg(bp->dev, - "start_xmit: queue %hu len %u head %p data %p tail %p end %p\n", - queue_index, skb->len, skb->head, skb->data, - skb_tail_pointer(skb), skb_end_pointer(skb)); + "start_xmit: queue %hu len %u head %p data %p tail %p end %p\n", + queue_index, skb->len, skb->head, skb->data, + skb_tail_pointer(skb), skb_end_pointer(skb)); print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, 16, true); #endif /* Count how many TX buffer descriptors are needed to send this * socket buffer: skb fragments of jumbo frames may need to be - * splitted into many buffer descriptors. + * split into many buffer descriptors. */ count = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length); nr_frags = skb_shinfo(skb)->nr_frags; @@ -1392,8 +1393,8 @@ static void macb_init_rx_buffer_size(struct macb *bp, size_t size) if (bp->rx_buffer_size % RX_BUFFER_MULTIPLE) { netdev_dbg(bp->dev, - "RX buffer must be multiple of %d bytes, expanding\n", - RX_BUFFER_MULTIPLE); + "RX buffer must be multiple of %d bytes, expanding\n", + RX_BUFFER_MULTIPLE); bp->rx_buffer_size = roundup(bp->rx_buffer_size, RX_BUFFER_MULTIPLE); } @@ -1416,7 +1417,7 @@ static void gem_free_rx_buffers(struct macb *bp) for (i = 0; i < RX_RING_SIZE; i++) { skb = bp->rx_skbuff[i]; - if (skb == NULL) + if (!skb) continue; desc = &bp->rx_ring[i]; @@ -1817,7 +1818,8 @@ static void macb_sethashtable(struct net_device *dev) unsigned int bitnr; struct macb *bp = netdev_priv(dev); - mc_filter[0] = mc_filter[1] = 0; + mc_filter[0] = 0; + mc_filter[1] = 0; netdev_for_each_mc_addr(ha, dev) { bitnr = hash_get_index(ha->addr); -- GitLab From eefb52d1ec8eb1354ff1bf55811a0da74bffccb8 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 29 Mar 2016 19:11:14 -0700 Subject: [PATCH 1250/9938] net: macb: Use ether_addr_copy over memcpy Checkpatch suggests using ether_addr_copy over memcpy to copy the mac address. Acked-by: Michal Simek Acked-by: Nicolas Ferre Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 2ba0934e52dc..01a8ffbfc464 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -2973,7 +2973,7 @@ static int macb_probe(struct platform_device *pdev) mac = of_get_mac_address(np); if (mac) - memcpy(bp->dev->dev_addr, mac, ETH_ALEN); + ether_addr_copy(bp->dev->dev_addr, mac); else macb_get_hwaddr(bp); -- GitLab From 88023beb2a467dcfd9aa958138f0f3b5e1c432e0 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 29 Mar 2016 19:11:15 -0700 Subject: [PATCH 1251/9938] net: macb: Fix simple typo Acked-by: Michal Simek Acked-by: Nicolas Ferre Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 01a8ffbfc464..eec3200ade4a 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -130,7 +130,7 @@ static void hw_writel(struct macb *bp, int offset, u32 value) } /* Find the CPU endianness by using the loopback bit of NCR register. When the - * CPU is in big endian we need to program swaped mode for management + * CPU is in big endian we need to program swapped mode for management * descriptor access. */ static bool hw_is_native_io(void __iomem *addr) -- GitLab From 9ef280c6c28f0c01aa9d909263ad47c796713a8e Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 4 Apr 2016 10:44:39 +0900 Subject: [PATCH 1252/9938] irda: sh_irda: remove driver Remove the sh-irda driver as it appears to be unused since c0bb9b302769 ("ARCH: ARM: shmobile: Remove ag5evm board support"). Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/irda/Kconfig | 7 - drivers/net/irda/Makefile | 1 - drivers/net/irda/sh_irda.c | 875 ------------------------------------- 3 files changed, 883 deletions(-) delete mode 100644 drivers/net/irda/sh_irda.c diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index a2c227bfb687..e070e1222733 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -394,12 +394,5 @@ config MCS_FIR To compile it as a module, choose M here: the module will be called mcs7780. -config SH_IRDA - tristate "SuperH IrDA driver" - depends on IRDA - depends on (ARCH_SHMOBILE || COMPILE_TEST) && HAS_IOMEM - help - Say Y here if your want to enable SuperH IrDA devices. - endmenu diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index be8ab5b9a4a2..4c344433dae5 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_VIA_FIR) += via-ircc.o obj-$(CONFIG_PXA_FICP) += pxaficp_ir.o obj-$(CONFIG_MCS_FIR) += mcs7780.o obj-$(CONFIG_AU1000_FIR) += au1k_ir.o -obj-$(CONFIG_SH_IRDA) += sh_irda.o # SIR drivers obj-$(CONFIG_IRTTY_SIR) += irtty-sir.o sir-dev.o obj-$(CONFIG_BFIN_SIR) += bfin_sir.o diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c deleted file mode 100644 index c96b46b2c3a8..000000000000 --- a/drivers/net/irda/sh_irda.c +++ /dev/null @@ -1,875 +0,0 @@ -/* - * SuperH IrDA Driver - * - * Copyright (C) 2010 Renesas Solutions Corp. - * Kuninori Morimoto - * - * Based on sh_sir.c - * Copyright (C) 2009 Renesas Solutions Corp. - * Copyright 2006-2009 Analog Devices Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * CAUTION - * - * This driver is very simple. - * So, it doesn't have below support now - * - MIR/FIR support - * - DMA transfer support - * - FIFO mode support - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "sh_irda" - -#define __IRDARAM_LEN 0x1039 - -#define IRTMR 0x1F00 /* Transfer mode */ -#define IRCFR 0x1F02 /* Configuration */ -#define IRCTR 0x1F04 /* IR control */ -#define IRTFLR 0x1F20 /* Transmit frame length */ -#define IRTCTR 0x1F22 /* Transmit control */ -#define IRRFLR 0x1F40 /* Receive frame length */ -#define IRRCTR 0x1F42 /* Receive control */ -#define SIRISR 0x1F60 /* SIR-UART mode interrupt source */ -#define SIRIMR 0x1F62 /* SIR-UART mode interrupt mask */ -#define SIRICR 0x1F64 /* SIR-UART mode interrupt clear */ -#define SIRBCR 0x1F68 /* SIR-UART mode baud rate count */ -#define MFIRISR 0x1F70 /* MIR/FIR mode interrupt source */ -#define MFIRIMR 0x1F72 /* MIR/FIR mode interrupt mask */ -#define MFIRICR 0x1F74 /* MIR/FIR mode interrupt clear */ -#define CRCCTR 0x1F80 /* CRC engine control */ -#define CRCIR 0x1F86 /* CRC engine input data */ -#define CRCCR 0x1F8A /* CRC engine calculation */ -#define CRCOR 0x1F8E /* CRC engine output data */ -#define FIFOCP 0x1FC0 /* FIFO current pointer */ -#define FIFOFP 0x1FC2 /* FIFO follow pointer */ -#define FIFORSMSK 0x1FC4 /* FIFO receive status mask */ -#define FIFORSOR 0x1FC6 /* FIFO receive status OR */ -#define FIFOSEL 0x1FC8 /* FIFO select */ -#define FIFORS 0x1FCA /* FIFO receive status */ -#define FIFORFL 0x1FCC /* FIFO receive frame length */ -#define FIFORAMCP 0x1FCE /* FIFO RAM current pointer */ -#define FIFORAMFP 0x1FD0 /* FIFO RAM follow pointer */ -#define BIFCTL 0x1FD2 /* BUS interface control */ -#define IRDARAM 0x0000 /* IrDA buffer RAM */ -#define IRDARAM_LEN __IRDARAM_LEN /* - 8/16/32 (read-only for 32) */ - -/* IRTMR */ -#define TMD_MASK (0x3 << 14) /* Transfer Mode */ -#define TMD_SIR (0x0 << 14) -#define TMD_MIR (0x3 << 14) -#define TMD_FIR (0x2 << 14) - -#define FIFORIM (1 << 8) /* FIFO receive interrupt mask */ -#define MIM (1 << 4) /* MIR/FIR Interrupt Mask */ -#define SIM (1 << 0) /* SIR Interrupt Mask */ -#define xIM_MASK (FIFORIM | MIM | SIM) - -/* IRCFR */ -#define RTO_SHIFT 8 /* shift for Receive Timeout */ -#define RTO (0x3 << RTO_SHIFT) - -/* IRTCTR */ -#define ARMOD (1 << 15) /* Auto-Receive Mode */ -#define TE (1 << 0) /* Transmit Enable */ - -/* IRRFLR */ -#define RFL_MASK (0x1FFF) /* mask for Receive Frame Length */ - -/* IRRCTR */ -#define RE (1 << 0) /* Receive Enable */ - -/* - * SIRISR, SIRIMR, SIRICR, - * MFIRISR, MFIRIMR, MFIRICR - */ -#define FRE (1 << 15) /* Frame Receive End */ -#define TROV (1 << 11) /* Transfer Area Overflow */ -#define xIR_9 (1 << 9) -#define TOT xIR_9 /* for SIR Timeout */ -#define ABTD xIR_9 /* for MIR/FIR Abort Detection */ -#define xIR_8 (1 << 8) -#define FER xIR_8 /* for SIR Framing Error */ -#define CRCER xIR_8 /* for MIR/FIR CRC error */ -#define FTE (1 << 7) /* Frame Transmit End */ -#define xIR_MASK (FRE | TROV | xIR_9 | xIR_8 | FTE) - -/* SIRBCR */ -#define BRC_MASK (0x3F) /* mask for Baud Rate Count */ - -/* CRCCTR */ -#define CRC_RST (1 << 15) /* CRC Engine Reset */ -#define CRC_CT_MASK 0x0FFF /* mask for CRC Engine Input Data Count */ - -/* CRCIR */ -#define CRC_IN_MASK 0x0FFF /* mask for CRC Engine Input Data */ - -/************************************************************************ - - - enum / structure - - -************************************************************************/ -enum sh_irda_mode { - SH_IRDA_NONE = 0, - SH_IRDA_SIR, - SH_IRDA_MIR, - SH_IRDA_FIR, -}; - -struct sh_irda_self; -struct sh_irda_xir_func { - int (*xir_fre) (struct sh_irda_self *self); - int (*xir_trov) (struct sh_irda_self *self); - int (*xir_9) (struct sh_irda_self *self); - int (*xir_8) (struct sh_irda_self *self); - int (*xir_fte) (struct sh_irda_self *self); -}; - -struct sh_irda_self { - void __iomem *membase; - unsigned int irq; - struct platform_device *pdev; - - struct net_device *ndev; - - struct irlap_cb *irlap; - struct qos_info qos; - - iobuff_t tx_buff; - iobuff_t rx_buff; - - enum sh_irda_mode mode; - spinlock_t lock; - - struct sh_irda_xir_func *xir_func; -}; - -/************************************************************************ - - - common function - - -************************************************************************/ -static void sh_irda_write(struct sh_irda_self *self, u32 offset, u16 data) -{ - unsigned long flags; - - spin_lock_irqsave(&self->lock, flags); - iowrite16(data, self->membase + offset); - spin_unlock_irqrestore(&self->lock, flags); -} - -static u16 sh_irda_read(struct sh_irda_self *self, u32 offset) -{ - unsigned long flags; - u16 ret; - - spin_lock_irqsave(&self->lock, flags); - ret = ioread16(self->membase + offset); - spin_unlock_irqrestore(&self->lock, flags); - - return ret; -} - -static void sh_irda_update_bits(struct sh_irda_self *self, u32 offset, - u16 mask, u16 data) -{ - unsigned long flags; - u16 old, new; - - spin_lock_irqsave(&self->lock, flags); - old = ioread16(self->membase + offset); - new = (old & ~mask) | data; - if (old != new) - iowrite16(data, self->membase + offset); - spin_unlock_irqrestore(&self->lock, flags); -} - -/************************************************************************ - - - mode function - - -************************************************************************/ -/*===================================== - * - * common - * - *=====================================*/ -static void sh_irda_rcv_ctrl(struct sh_irda_self *self, int enable) -{ - struct device *dev = &self->ndev->dev; - - sh_irda_update_bits(self, IRRCTR, RE, enable ? RE : 0); - dev_dbg(dev, "recv %s\n", enable ? "enable" : "disable"); -} - -static int sh_irda_set_timeout(struct sh_irda_self *self, int interval) -{ - struct device *dev = &self->ndev->dev; - - if (SH_IRDA_SIR != self->mode) - interval = 0; - - if (interval < 0 || interval > 2) { - dev_err(dev, "unsupported timeout interval\n"); - return -EINVAL; - } - - sh_irda_update_bits(self, IRCFR, RTO, interval << RTO_SHIFT); - return 0; -} - -static int sh_irda_set_baudrate(struct sh_irda_self *self, int baudrate) -{ - struct device *dev = &self->ndev->dev; - u16 val; - - if (baudrate < 0) - return 0; - - if (SH_IRDA_SIR != self->mode) { - dev_err(dev, "it is not SIR mode\n"); - return -EINVAL; - } - - /* - * Baud rate (bits/s) = - * (48 MHz / 26) / (baud rate counter value + 1) x 16 - */ - val = (48000000 / 26 / 16 / baudrate) - 1; - dev_dbg(dev, "baudrate = %d, val = 0x%02x\n", baudrate, val); - - sh_irda_update_bits(self, SIRBCR, BRC_MASK, val); - - return 0; -} - -static int sh_irda_get_rcv_length(struct sh_irda_self *self) -{ - return RFL_MASK & sh_irda_read(self, IRRFLR); -} - -/*===================================== - * - * NONE MODE - * - *=====================================*/ -static int sh_irda_xir_fre(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - dev_err(dev, "none mode: frame recv\n"); - return 0; -} - -static int sh_irda_xir_trov(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - dev_err(dev, "none mode: buffer ram over\n"); - return 0; -} - -static int sh_irda_xir_9(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - dev_err(dev, "none mode: time over\n"); - return 0; -} - -static int sh_irda_xir_8(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - dev_err(dev, "none mode: framing error\n"); - return 0; -} - -static int sh_irda_xir_fte(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - dev_err(dev, "none mode: frame transmit end\n"); - return 0; -} - -static struct sh_irda_xir_func sh_irda_xir_func = { - .xir_fre = sh_irda_xir_fre, - .xir_trov = sh_irda_xir_trov, - .xir_9 = sh_irda_xir_9, - .xir_8 = sh_irda_xir_8, - .xir_fte = sh_irda_xir_fte, -}; - -/*===================================== - * - * MIR/FIR MODE - * - * MIR/FIR are not supported now - *=====================================*/ -static struct sh_irda_xir_func sh_irda_mfir_func = { - .xir_fre = sh_irda_xir_fre, - .xir_trov = sh_irda_xir_trov, - .xir_9 = sh_irda_xir_9, - .xir_8 = sh_irda_xir_8, - .xir_fte = sh_irda_xir_fte, -}; - -/*===================================== - * - * SIR MODE - * - *=====================================*/ -static int sh_irda_sir_fre(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - u16 data16; - u8 *data = (u8 *)&data16; - int len = sh_irda_get_rcv_length(self); - int i, j; - - if (len > IRDARAM_LEN) - len = IRDARAM_LEN; - - dev_dbg(dev, "frame recv length = %d\n", len); - - for (i = 0; i < len; i++) { - j = i % 2; - if (!j) - data16 = sh_irda_read(self, IRDARAM + i); - - async_unwrap_char(self->ndev, &self->ndev->stats, - &self->rx_buff, data[j]); - } - self->ndev->last_rx = jiffies; - - sh_irda_rcv_ctrl(self, 1); - - return 0; -} - -static int sh_irda_sir_trov(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - - dev_err(dev, "buffer ram over\n"); - sh_irda_rcv_ctrl(self, 1); - return 0; -} - -static int sh_irda_sir_tot(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - - dev_err(dev, "time over\n"); - sh_irda_set_baudrate(self, 9600); - sh_irda_rcv_ctrl(self, 1); - return 0; -} - -static int sh_irda_sir_fer(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - - dev_err(dev, "framing error\n"); - sh_irda_rcv_ctrl(self, 1); - return 0; -} - -static int sh_irda_sir_fte(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - - dev_dbg(dev, "frame transmit end\n"); - netif_wake_queue(self->ndev); - - return 0; -} - -static struct sh_irda_xir_func sh_irda_sir_func = { - .xir_fre = sh_irda_sir_fre, - .xir_trov = sh_irda_sir_trov, - .xir_9 = sh_irda_sir_tot, - .xir_8 = sh_irda_sir_fer, - .xir_fte = sh_irda_sir_fte, -}; - -static void sh_irda_set_mode(struct sh_irda_self *self, enum sh_irda_mode mode) -{ - struct device *dev = &self->ndev->dev; - struct sh_irda_xir_func *func; - const char *name; - u16 data; - - switch (mode) { - case SH_IRDA_SIR: - name = "SIR"; - data = TMD_SIR; - func = &sh_irda_sir_func; - break; - case SH_IRDA_MIR: - name = "MIR"; - data = TMD_MIR; - func = &sh_irda_mfir_func; - break; - case SH_IRDA_FIR: - name = "FIR"; - data = TMD_FIR; - func = &sh_irda_mfir_func; - break; - default: - name = "NONE"; - data = 0; - func = &sh_irda_xir_func; - break; - } - - self->mode = mode; - self->xir_func = func; - sh_irda_update_bits(self, IRTMR, TMD_MASK, data); - - dev_dbg(dev, "switch to %s mode", name); -} - -/************************************************************************ - - - irq function - - -************************************************************************/ -static void sh_irda_set_irq_mask(struct sh_irda_self *self) -{ - u16 tmr_hole; - u16 xir_reg; - - /* set all mask */ - sh_irda_update_bits(self, IRTMR, xIM_MASK, xIM_MASK); - sh_irda_update_bits(self, SIRIMR, xIR_MASK, xIR_MASK); - sh_irda_update_bits(self, MFIRIMR, xIR_MASK, xIR_MASK); - - /* clear irq */ - sh_irda_update_bits(self, SIRICR, xIR_MASK, xIR_MASK); - sh_irda_update_bits(self, MFIRICR, xIR_MASK, xIR_MASK); - - switch (self->mode) { - case SH_IRDA_SIR: - tmr_hole = SIM; - xir_reg = SIRIMR; - break; - case SH_IRDA_MIR: - case SH_IRDA_FIR: - tmr_hole = MIM; - xir_reg = MFIRIMR; - break; - default: - tmr_hole = 0; - xir_reg = 0; - break; - } - - /* open mask */ - if (xir_reg) { - sh_irda_update_bits(self, IRTMR, tmr_hole, 0); - sh_irda_update_bits(self, xir_reg, xIR_MASK, 0); - } -} - -static irqreturn_t sh_irda_irq(int irq, void *dev_id) -{ - struct sh_irda_self *self = dev_id; - struct sh_irda_xir_func *func = self->xir_func; - u16 isr = sh_irda_read(self, SIRISR); - - /* clear irq */ - sh_irda_write(self, SIRICR, isr); - - if (isr & FRE) - func->xir_fre(self); - if (isr & TROV) - func->xir_trov(self); - if (isr & xIR_9) - func->xir_9(self); - if (isr & xIR_8) - func->xir_8(self); - if (isr & FTE) - func->xir_fte(self); - - return IRQ_HANDLED; -} - -/************************************************************************ - - - CRC function - - -************************************************************************/ -static void sh_irda_crc_reset(struct sh_irda_self *self) -{ - sh_irda_write(self, CRCCTR, CRC_RST); -} - -static void sh_irda_crc_add(struct sh_irda_self *self, u16 data) -{ - sh_irda_write(self, CRCIR, data & CRC_IN_MASK); -} - -static u16 sh_irda_crc_cnt(struct sh_irda_self *self) -{ - return CRC_CT_MASK & sh_irda_read(self, CRCCTR); -} - -static u16 sh_irda_crc_out(struct sh_irda_self *self) -{ - return sh_irda_read(self, CRCOR); -} - -static int sh_irda_crc_init(struct sh_irda_self *self) -{ - struct device *dev = &self->ndev->dev; - int ret = -EIO; - u16 val; - - sh_irda_crc_reset(self); - - sh_irda_crc_add(self, 0xCC); - sh_irda_crc_add(self, 0xF5); - sh_irda_crc_add(self, 0xF1); - sh_irda_crc_add(self, 0xA7); - - val = sh_irda_crc_cnt(self); - if (4 != val) { - dev_err(dev, "CRC count error %x\n", val); - goto crc_init_out; - } - - val = sh_irda_crc_out(self); - if (0x51DF != val) { - dev_err(dev, "CRC result error%x\n", val); - goto crc_init_out; - } - - ret = 0; - -crc_init_out: - - sh_irda_crc_reset(self); - return ret; -} - -/************************************************************************ - - - iobuf function - - -************************************************************************/ -static void sh_irda_remove_iobuf(struct sh_irda_self *self) -{ - kfree(self->rx_buff.head); - - self->tx_buff.head = NULL; - self->tx_buff.data = NULL; - self->rx_buff.head = NULL; - self->rx_buff.data = NULL; -} - -static int sh_irda_init_iobuf(struct sh_irda_self *self, int rxsize, int txsize) -{ - if (self->rx_buff.head || - self->tx_buff.head) { - dev_err(&self->ndev->dev, "iobuff has already existed."); - return -EINVAL; - } - - /* rx_buff */ - self->rx_buff.head = kmalloc(rxsize, GFP_KERNEL); - if (!self->rx_buff.head) - return -ENOMEM; - - self->rx_buff.truesize = rxsize; - self->rx_buff.in_frame = FALSE; - self->rx_buff.state = OUTSIDE_FRAME; - self->rx_buff.data = self->rx_buff.head; - - /* tx_buff */ - self->tx_buff.head = self->membase + IRDARAM; - self->tx_buff.truesize = IRDARAM_LEN; - - return 0; -} - -/************************************************************************ - - - net_device_ops function - - -************************************************************************/ -static int sh_irda_hard_xmit(struct sk_buff *skb, struct net_device *ndev) -{ - struct sh_irda_self *self = netdev_priv(ndev); - struct device *dev = &self->ndev->dev; - int speed = irda_get_next_speed(skb); - int ret; - - dev_dbg(dev, "hard xmit\n"); - - netif_stop_queue(ndev); - sh_irda_rcv_ctrl(self, 0); - - ret = sh_irda_set_baudrate(self, speed); - if (ret < 0) - goto sh_irda_hard_xmit_end; - - self->tx_buff.len = 0; - if (skb->len) { - unsigned long flags; - - spin_lock_irqsave(&self->lock, flags); - self->tx_buff.len = async_wrap_skb(skb, - self->tx_buff.head, - self->tx_buff.truesize); - spin_unlock_irqrestore(&self->lock, flags); - - if (self->tx_buff.len > self->tx_buff.truesize) - self->tx_buff.len = self->tx_buff.truesize; - - sh_irda_write(self, IRTFLR, self->tx_buff.len); - sh_irda_write(self, IRTCTR, ARMOD | TE); - } else - goto sh_irda_hard_xmit_end; - - dev_kfree_skb(skb); - - return 0; - -sh_irda_hard_xmit_end: - sh_irda_set_baudrate(self, 9600); - netif_wake_queue(self->ndev); - sh_irda_rcv_ctrl(self, 1); - dev_kfree_skb(skb); - - return ret; - -} - -static int sh_irda_ioctl(struct net_device *ndev, struct ifreq *ifreq, int cmd) -{ - /* - * FIXME - * - * This function is needed for irda framework. - * But nothing to do now - */ - return 0; -} - -static struct net_device_stats *sh_irda_stats(struct net_device *ndev) -{ - struct sh_irda_self *self = netdev_priv(ndev); - - return &self->ndev->stats; -} - -static int sh_irda_open(struct net_device *ndev) -{ - struct sh_irda_self *self = netdev_priv(ndev); - int err; - - pm_runtime_get_sync(&self->pdev->dev); - err = sh_irda_crc_init(self); - if (err) - goto open_err; - - sh_irda_set_mode(self, SH_IRDA_SIR); - sh_irda_set_timeout(self, 2); - sh_irda_set_baudrate(self, 9600); - - self->irlap = irlap_open(ndev, &self->qos, DRIVER_NAME); - if (!self->irlap) { - err = -ENODEV; - goto open_err; - } - - netif_start_queue(ndev); - sh_irda_rcv_ctrl(self, 1); - sh_irda_set_irq_mask(self); - - dev_info(&ndev->dev, "opened\n"); - - return 0; - -open_err: - pm_runtime_put_sync(&self->pdev->dev); - - return err; -} - -static int sh_irda_stop(struct net_device *ndev) -{ - struct sh_irda_self *self = netdev_priv(ndev); - - /* Stop IrLAP */ - if (self->irlap) { - irlap_close(self->irlap); - self->irlap = NULL; - } - - netif_stop_queue(ndev); - pm_runtime_put_sync(&self->pdev->dev); - - dev_info(&ndev->dev, "stopped\n"); - - return 0; -} - -static const struct net_device_ops sh_irda_ndo = { - .ndo_open = sh_irda_open, - .ndo_stop = sh_irda_stop, - .ndo_start_xmit = sh_irda_hard_xmit, - .ndo_do_ioctl = sh_irda_ioctl, - .ndo_get_stats = sh_irda_stats, -}; - -/************************************************************************ - - - platform_driver function - - -************************************************************************/ -static int sh_irda_probe(struct platform_device *pdev) -{ - struct net_device *ndev; - struct sh_irda_self *self; - struct resource *res; - int irq; - int err = -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - if (!res || irq < 0) { - dev_err(&pdev->dev, "Not enough platform resources.\n"); - goto exit; - } - - ndev = alloc_irdadev(sizeof(*self)); - if (!ndev) - goto exit; - - self = netdev_priv(ndev); - self->membase = ioremap_nocache(res->start, resource_size(res)); - if (!self->membase) { - err = -ENXIO; - dev_err(&pdev->dev, "Unable to ioremap.\n"); - goto err_mem_1; - } - - err = sh_irda_init_iobuf(self, IRDA_SKB_MAX_MTU, IRDA_SIR_MAX_FRAME); - if (err) - goto err_mem_2; - - self->pdev = pdev; - pm_runtime_enable(&pdev->dev); - - irda_init_max_qos_capabilies(&self->qos); - - ndev->netdev_ops = &sh_irda_ndo; - ndev->irq = irq; - - self->ndev = ndev; - self->qos.baud_rate.bits &= IR_9600; /* FIXME */ - self->qos.min_turn_time.bits = 1; /* 10 ms or more */ - spin_lock_init(&self->lock); - - irda_qos_bits_to_value(&self->qos); - - err = register_netdev(ndev); - if (err) - goto err_mem_4; - - platform_set_drvdata(pdev, ndev); - err = devm_request_irq(&pdev->dev, irq, sh_irda_irq, 0, "sh_irda", self); - if (err) { - dev_warn(&pdev->dev, "Unable to attach sh_irda interrupt\n"); - goto err_mem_4; - } - - dev_info(&pdev->dev, "SuperH IrDA probed\n"); - - goto exit; - -err_mem_4: - pm_runtime_disable(&pdev->dev); - sh_irda_remove_iobuf(self); -err_mem_2: - iounmap(self->membase); -err_mem_1: - free_netdev(ndev); -exit: - return err; -} - -static int sh_irda_remove(struct platform_device *pdev) -{ - struct net_device *ndev = platform_get_drvdata(pdev); - struct sh_irda_self *self = netdev_priv(ndev); - - if (!self) - return 0; - - unregister_netdev(ndev); - pm_runtime_disable(&pdev->dev); - sh_irda_remove_iobuf(self); - iounmap(self->membase); - free_netdev(ndev); - - return 0; -} - -static int sh_irda_runtime_nop(struct device *dev) -{ - /* Runtime PM callback shared between ->runtime_suspend() - * and ->runtime_resume(). Simply returns success. - * - * This driver re-initializes all registers after - * pm_runtime_get_sync() anyway so there is no need - * to save and restore registers here. - */ - return 0; -} - -static const struct dev_pm_ops sh_irda_pm_ops = { - .runtime_suspend = sh_irda_runtime_nop, - .runtime_resume = sh_irda_runtime_nop, -}; - -static struct platform_driver sh_irda_driver = { - .probe = sh_irda_probe, - .remove = sh_irda_remove, - .driver = { - .name = DRIVER_NAME, - .pm = &sh_irda_pm_ops, - }, -}; - -module_platform_driver(sh_irda_driver); - -MODULE_AUTHOR("Kuninori Morimoto "); -MODULE_DESCRIPTION("SuperH IrDA driver"); -MODULE_LICENSE("GPL"); -- GitLab From 06bb1c39d8be0b2ee60b5bc9384fdac6e19bc270 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 Jan 2016 22:48:50 -0800 Subject: [PATCH 1253/9938] ixgbe: Avoid adding VLAN 0 twice to VLVF and VFTA We were adding VLAN 0 twice each time we restored the VLAN configuration. Instead of doing it twice we can just start working through the active VLANs from ID 1 on and skip the double write. Signed-off-by: Alexander Duyck Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a01a7f251e03..297e7d32adfd 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4172,11 +4172,11 @@ static void ixgbe_vlan_promisc_disable(struct ixgbe_adapter *adapter) static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter) { - u16 vid; + u16 vid = 1; ixgbe_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), 0); - for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) + for_each_set_bit_from(vid, adapter->active_vlans, VLAN_N_VID) ixgbe_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); } -- GitLab From 37689010da28c6dfd9f59e60d7f42c47b775171c Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Thu, 7 Jan 2016 10:13:03 -0800 Subject: [PATCH 1254/9938] ixgbe: Make all unchanging ops structures const The source for the ops structure contents are const, so make them so. Copy them in place with structure assignments instead of memcpys. Make the mbx_ops accessed by reference instead of making a copy of the source structure. Update copyright date on the touched files. Reported-by: Julia Lawall Signed-off-by: Mark Rustad Acked-by: Julia Lawall Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 12 +++--- .../net/ethernet/intel/ixgbe/ixgbe_82598.c | 10 ++--- .../net/ethernet/intel/ixgbe/ixgbe_82599.c | 10 ++--- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 10 ++--- drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c | 40 +++++++++---------- drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h | 4 +- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 12 +++--- drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 10 ++--- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 18 ++++----- 9 files changed, 63 insertions(+), 63 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 9f64354c9c9e..4590fabdedf0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -862,11 +862,11 @@ enum ixgbe_boards { board_X550EM_x, }; -extern struct ixgbe_info ixgbe_82598_info; -extern struct ixgbe_info ixgbe_82599_info; -extern struct ixgbe_info ixgbe_X540_info; -extern struct ixgbe_info ixgbe_X550_info; -extern struct ixgbe_info ixgbe_X550EM_x_info; +extern const struct ixgbe_info ixgbe_82598_info; +extern const struct ixgbe_info ixgbe_82599_info; +extern const struct ixgbe_info ixgbe_X540_info; +extern const struct ixgbe_info ixgbe_X550_info; +extern const struct ixgbe_info ixgbe_X550EM_x_info; #ifdef CONFIG_IXGBE_DCB extern const struct dcbnl_rtnl_ops dcbnl_ops; #endif diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index d8a9fb8a59e2..9790d0274f7f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2015 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -1160,7 +1160,7 @@ static void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB); } -static struct ixgbe_mac_operations mac_ops_82598 = { +static const struct ixgbe_mac_operations mac_ops_82598 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82598, .start_hw = &ixgbe_start_hw_82598, @@ -1203,7 +1203,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = { .disable_rx = &ixgbe_disable_rx_generic, }; -static struct ixgbe_eeprom_operations eeprom_ops_82598 = { +static const struct ixgbe_eeprom_operations eeprom_ops_82598 = { .init_params = &ixgbe_init_eeprom_params_generic, .read = &ixgbe_read_eerd_generic, .write = &ixgbe_write_eeprom_generic, @@ -1214,7 +1214,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82598 = { .update_checksum = &ixgbe_update_eeprom_checksum_generic, }; -static struct ixgbe_phy_operations phy_ops_82598 = { +static const struct ixgbe_phy_operations phy_ops_82598 = { .identify = &ixgbe_identify_phy_generic, .identify_sfp = &ixgbe_identify_module_generic, .init = &ixgbe_init_phy_ops_82598, @@ -1230,7 +1230,7 @@ static struct ixgbe_phy_operations phy_ops_82598 = { .check_overtemp = &ixgbe_tn_check_overtemp, }; -struct ixgbe_info ixgbe_82598_info = { +const struct ixgbe_info ixgbe_82598_info = { .mac = ixgbe_mac_82598EB, .get_invariants = &ixgbe_get_invariants_82598, .mac_ops = &mac_ops_82598, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index fa8d4f40ac2a..b276fe0bc665 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2015 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -2181,7 +2181,7 @@ static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, return status; } -static struct ixgbe_mac_operations mac_ops_82599 = { +static const struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, .start_hw = &ixgbe_start_hw_82599, @@ -2235,7 +2235,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = { .disable_rx = &ixgbe_disable_rx_generic, }; -static struct ixgbe_eeprom_operations eeprom_ops_82599 = { +static const struct ixgbe_eeprom_operations eeprom_ops_82599 = { .init_params = &ixgbe_init_eeprom_params_generic, .read = &ixgbe_read_eeprom_82599, .read_buffer = &ixgbe_read_eeprom_buffer_82599, @@ -2246,7 +2246,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82599 = { .update_checksum = &ixgbe_update_eeprom_checksum_generic, }; -static struct ixgbe_phy_operations phy_ops_82599 = { +static const struct ixgbe_phy_operations phy_ops_82599 = { .identify = &ixgbe_identify_phy_82599, .identify_sfp = &ixgbe_identify_module_generic, .init = &ixgbe_init_phy_ops_82599, @@ -2263,7 +2263,7 @@ static struct ixgbe_phy_operations phy_ops_82599 = { .check_overtemp = &ixgbe_tn_check_overtemp, }; -struct ixgbe_info ixgbe_82599_info = { +const struct ixgbe_info ixgbe_82599_info = { .mac = ixgbe_mac_82599EB, .get_invariants = &ixgbe_get_invariants_82599, .mac_ops = &mac_ops_82599, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 297e7d32adfd..5f4ecf50eedd 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2015 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -9136,12 +9136,12 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); /* Setup hw api */ - memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops)); + hw->mac.ops = *ii->mac_ops; hw->mac.type = ii->mac; hw->mvals = ii->mvals; /* EEPROM */ - memcpy(&hw->eeprom.ops, ii->eeprom_ops, sizeof(hw->eeprom.ops)); + hw->eeprom.ops = *ii->eeprom_ops; eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); if (ixgbe_removed(hw->hw_addr)) { err = -EIO; @@ -9152,7 +9152,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->eeprom.ops.read = &ixgbe_read_eeprom_bit_bang_generic; /* PHY */ - memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops)); + hw->phy.ops = *ii->phy_ops; hw->phy.sfp_type = ixgbe_sfp_type_unknown; /* ixgbe_identify_phy_generic will set prtad and mmds properly */ hw->phy.mdio.prtad = MDIO_PRTAD_NONE; @@ -9215,7 +9215,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto skip_sriov; /* Mailbox */ ixgbe_init_mbx_params_pf(hw); - memcpy(&hw->mbx.ops, ii->mbx_ops, sizeof(hw->mbx.ops)); + hw->mbx.ops = ii->mbx_ops; pci_sriov_set_totalvfs(pdev, IXGBE_MAX_VFS_DRV_LIMIT); ixgbe_enable_sriov(adapter); skip_sriov: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c index 9993a471d668..2837c94d6e35 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2014 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -48,10 +48,10 @@ s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) if (size > mbx->size) size = mbx->size; - if (!mbx->ops.read) + if (!mbx->ops) return IXGBE_ERR_MBX; - return mbx->ops.read(hw, msg, size, mbx_id); + return mbx->ops->read(hw, msg, size, mbx_id); } /** @@ -70,10 +70,10 @@ s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) if (size > mbx->size) return IXGBE_ERR_MBX; - if (!mbx->ops.write) + if (!mbx->ops) return IXGBE_ERR_MBX; - return mbx->ops.write(hw, msg, size, mbx_id); + return mbx->ops->write(hw, msg, size, mbx_id); } /** @@ -87,10 +87,10 @@ s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - if (!mbx->ops.check_for_msg) + if (!mbx->ops) return IXGBE_ERR_MBX; - return mbx->ops.check_for_msg(hw, mbx_id); + return mbx->ops->check_for_msg(hw, mbx_id); } /** @@ -104,10 +104,10 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - if (!mbx->ops.check_for_ack) + if (!mbx->ops) return IXGBE_ERR_MBX; - return mbx->ops.check_for_ack(hw, mbx_id); + return mbx->ops->check_for_ack(hw, mbx_id); } /** @@ -121,10 +121,10 @@ s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - if (!mbx->ops.check_for_rst) + if (!mbx->ops) return IXGBE_ERR_MBX; - return mbx->ops.check_for_rst(hw, mbx_id); + return mbx->ops->check_for_rst(hw, mbx_id); } /** @@ -139,10 +139,10 @@ static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id) struct ixgbe_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; - if (!countdown || !mbx->ops.check_for_msg) + if (!countdown || !mbx->ops) return IXGBE_ERR_MBX; - while (mbx->ops.check_for_msg(hw, mbx_id)) { + while (mbx->ops->check_for_msg(hw, mbx_id)) { countdown--; if (!countdown) return IXGBE_ERR_MBX; @@ -164,10 +164,10 @@ static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) struct ixgbe_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; - if (!countdown || !mbx->ops.check_for_ack) + if (!countdown || !mbx->ops) return IXGBE_ERR_MBX; - while (mbx->ops.check_for_ack(hw, mbx_id)) { + while (mbx->ops->check_for_ack(hw, mbx_id)) { countdown--; if (!countdown) return IXGBE_ERR_MBX; @@ -193,7 +193,7 @@ static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val; - if (!mbx->ops.read) + if (!mbx->ops) return IXGBE_ERR_MBX; ret_val = ixgbe_poll_for_msg(hw, mbx_id); @@ -201,7 +201,7 @@ static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, return ret_val; /* if ack received read message */ - return mbx->ops.read(hw, msg, size, mbx_id); + return mbx->ops->read(hw, msg, size, mbx_id); } /** @@ -221,11 +221,11 @@ static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, s32 ret_val; /* exit if either we can't write or there isn't a defined timeout */ - if (!mbx->ops.write || !mbx->timeout) + if (!mbx->ops || !mbx->timeout) return IXGBE_ERR_MBX; /* send msg */ - ret_val = mbx->ops.write(hw, msg, size, mbx_id); + ret_val = mbx->ops->write(hw, msg, size, mbx_id); if (ret_val) return ret_val; @@ -446,7 +446,7 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) } #endif /* CONFIG_PCI_IOV */ -struct ixgbe_mbx_operations mbx_ops_generic = { +const struct ixgbe_mbx_operations mbx_ops_generic = { .read = ixgbe_read_mbx_pf, .write = ixgbe_write_mbx_pf, .read_posted = ixgbe_read_posted_mbx, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h index 8daa95f74548..01c2667c0f92 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -123,6 +123,6 @@ s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16); void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); #endif /* CONFIG_PCI_IOV */ -extern struct ixgbe_mbx_operations mbx_ops_generic; +extern const struct ixgbe_mbx_operations mbx_ops_generic; #endif /* _IXGBE_MBX_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index bf7367a08716..29e0b0e1cb67 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2015 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -3442,7 +3442,7 @@ struct ixgbe_mbx_stats { }; struct ixgbe_mbx_info { - struct ixgbe_mbx_operations ops; + const struct ixgbe_mbx_operations *ops; struct ixgbe_mbx_stats stats; u32 timeout; u32 usec_delay; @@ -3475,10 +3475,10 @@ struct ixgbe_hw { struct ixgbe_info { enum ixgbe_mac_type mac; s32 (*get_invariants)(struct ixgbe_hw *); - struct ixgbe_mac_operations *mac_ops; - struct ixgbe_eeprom_operations *eeprom_ops; - struct ixgbe_phy_operations *phy_ops; - struct ixgbe_mbx_operations *mbx_ops; + const struct ixgbe_mac_operations *mac_ops; + const struct ixgbe_eeprom_operations *eeprom_ops; + const struct ixgbe_phy_operations *phy_ops; + const struct ixgbe_mbx_operations *mbx_ops; const u32 *mvals; }; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index 2358c1b7d586..0d69564f3a1b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2014 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -810,7 +810,7 @@ s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index) return 0; } -static struct ixgbe_mac_operations mac_ops_X540 = { +static const struct ixgbe_mac_operations mac_ops_X540 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_X540, .start_hw = &ixgbe_start_hw_X540, @@ -863,7 +863,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = { .disable_rx = &ixgbe_disable_rx_generic, }; -static struct ixgbe_eeprom_operations eeprom_ops_X540 = { +static const struct ixgbe_eeprom_operations eeprom_ops_X540 = { .init_params = &ixgbe_init_eeprom_params_X540, .read = &ixgbe_read_eerd_X540, .read_buffer = &ixgbe_read_eerd_buffer_X540, @@ -874,7 +874,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_X540 = { .update_checksum = &ixgbe_update_eeprom_checksum_X540, }; -static struct ixgbe_phy_operations phy_ops_X540 = { +static const struct ixgbe_phy_operations phy_ops_X540 = { .identify = &ixgbe_identify_phy_generic, .identify_sfp = &ixgbe_identify_sfp_module_generic, .init = NULL, @@ -897,7 +897,7 @@ static const u32 ixgbe_mvals_X540[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(X540) }; -struct ixgbe_info ixgbe_X540_info = { +const struct ixgbe_info ixgbe_X540_info = { .mac = ixgbe_mac_X540, .get_invariants = &ixgbe_get_invariants_X540, .mac_ops = &mac_ops_X540, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 68a9c646498e..26e0b8df2afe 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Intel 10 Gigabit PCI Express Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. + * Copyright(c) 1999 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -2342,7 +2342,7 @@ static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) .enable_rx = &ixgbe_enable_rx_generic, \ .disable_rx = &ixgbe_disable_rx_x550, \ -static struct ixgbe_mac_operations mac_ops_X550 = { +static const struct ixgbe_mac_operations mac_ops_X550 = { X550_COMMON_MAC .reset_hw = &ixgbe_reset_hw_X540, .get_media_type = &ixgbe_get_media_type_X540, @@ -2356,7 +2356,7 @@ static struct ixgbe_mac_operations mac_ops_X550 = { .release_swfw_sync = &ixgbe_release_swfw_sync_X540, }; -static struct ixgbe_mac_operations mac_ops_X550EM_x = { +static const struct ixgbe_mac_operations mac_ops_X550EM_x = { X550_COMMON_MAC .reset_hw = &ixgbe_reset_hw_X550em, .get_media_type = &ixgbe_get_media_type_X550em, @@ -2379,12 +2379,12 @@ static struct ixgbe_mac_operations mac_ops_X550EM_x = { .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ -static struct ixgbe_eeprom_operations eeprom_ops_X550 = { +static const struct ixgbe_eeprom_operations eeprom_ops_X550 = { X550_COMMON_EEP .init_params = &ixgbe_init_eeprom_params_X550, }; -static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { +static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { X550_COMMON_EEP .init_params = &ixgbe_init_eeprom_params_X540, }; @@ -2405,13 +2405,13 @@ static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { .check_overtemp = &ixgbe_tn_check_overtemp, \ .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, -static struct ixgbe_phy_operations phy_ops_X550 = { +static const struct ixgbe_phy_operations phy_ops_X550 = { X550_COMMON_PHY .init = NULL, .identify = &ixgbe_identify_phy_generic, }; -static struct ixgbe_phy_operations phy_ops_X550EM_x = { +static const struct ixgbe_phy_operations phy_ops_X550EM_x = { X550_COMMON_PHY .init = &ixgbe_init_phy_ops_X550em, .identify = &ixgbe_identify_phy_x550em, @@ -2430,7 +2430,7 @@ static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(X550EM_x) }; -struct ixgbe_info ixgbe_X550_info = { +const struct ixgbe_info ixgbe_X550_info = { .mac = ixgbe_mac_X550, .get_invariants = &ixgbe_get_invariants_X540, .mac_ops = &mac_ops_X550, @@ -2440,7 +2440,7 @@ struct ixgbe_info ixgbe_X550_info = { .mvals = ixgbe_mvals_X550, }; -struct ixgbe_info ixgbe_X550EM_x_info = { +const struct ixgbe_info ixgbe_X550EM_x_info = { .mac = ixgbe_mac_X550EM_x, .get_invariants = &ixgbe_get_invariants_X550_x, .mac_ops = &mac_ops_X550EM_x, -- GitLab From 7ffb8e317bae03b8ee5bdcec93dc3723be945e9b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 4 Apr 2016 16:44:02 -0400 Subject: [PATCH 1255/9938] audit: we don't need to __set_current_state(TASK_RUNNING) Remove the calls to __set_current_state() to mark the task as running and do some related cleanup in wait_for_auditd() to limit the amount of work we do when we aren't going to reschedule the current task. Signed-off-by: Paul Moore --- kernel/audit.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 3a3e5deeda8d..f52fbefede09 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -430,7 +430,6 @@ static void kauditd_send_skb(struct sk_buff *skb) attempts, audit_pid); set_current_state(TASK_INTERRUPTIBLE); schedule(); - __set_current_state(TASK_RUNNING); goto restart; } } @@ -1324,15 +1323,14 @@ static inline void audit_get_stamp(struct audit_context *ctx, static long wait_for_auditd(long sleep_time) { DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue_exclusive(&audit_backlog_wait, &wait); if (audit_backlog_limit && - skb_queue_len(&audit_skb_queue) > audit_backlog_limit) + skb_queue_len(&audit_skb_queue) > audit_backlog_limit) { + add_wait_queue_exclusive(&audit_backlog_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); sleep_time = schedule_timeout(sleep_time); - - __set_current_state(TASK_RUNNING); - remove_wait_queue(&audit_backlog_wait, &wait); + remove_wait_queue(&audit_backlog_wait, &wait); + } return sleep_time; } -- GitLab From c7374b5a767cb6c7d9acbfc82656dc89afeae257 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Tue, 12 Jan 2016 19:32:30 -0800 Subject: [PATCH 1256/9938] ixgbe: use eth_platform_get_mac_address() This commit converts commit c762dff24c06 ("ixgbe: Look up MAC address in Open Firmware or IDPROM") to use eth_platform_get_mac_address() added by commit c7f5d105495a ("net: Add eth_platform_get_mac_address() helper.") Signed-off-by: Sowmini Varadhan Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 35 ++----------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5f4ecf50eedd..bce5737b1a96 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -54,15 +54,6 @@ #include #include -#ifdef CONFIG_OF -#include -#endif - -#ifdef CONFIG_SPARC -#include -#include -#endif - #include "ixgbe.h" #include "ixgbe_common.h" #include "ixgbe_dcb_82599.h" @@ -9010,29 +9001,6 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id, return is_wol_supported; } -/** - * ixgbe_get_platform_mac_addr - Look up MAC address in Open Firmware / IDPROM - * @adapter: Pointer to adapter struct - */ -static void ixgbe_get_platform_mac_addr(struct ixgbe_adapter *adapter) -{ -#ifdef CONFIG_OF - struct device_node *dp = pci_device_to_OF_node(adapter->pdev); - struct ixgbe_hw *hw = &adapter->hw; - const unsigned char *addr; - - addr = of_get_mac_address(dp); - if (addr) { - ether_addr_copy(hw->mac.perm_addr, addr); - return; - } -#endif /* CONFIG_OF */ - -#ifdef CONFIG_SPARC - ether_addr_copy(hw->mac.perm_addr, idprom->id_ethaddr); -#endif /* CONFIG_SPARC */ -} - /** * ixgbe_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -9304,7 +9272,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_sw_init; } - ixgbe_get_platform_mac_addr(adapter); + eth_platform_get_mac_address(&adapter->pdev->dev, + adapter->hw.mac.perm_addr); memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len); -- GitLab From 49763de0425560eed50a186428010189eae69372 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 13 Jan 2016 07:31:11 -0800 Subject: [PATCH 1257/9938] ixgbe: Add support for generic Tx checksums This patch adds support for generic Tx checksums to the ixgbe driver. It turns out this is actually pretty easy after going over the datasheet as we were doing a number of steps we didn't need to. In order to perform a Tx checksum for an L4 header we need to fill in the following fields in the Tx descriptor: MACLEN (maximum of 127), retrieved from: skb_network_offset() IPLEN (maximum of 511), retrieved from: skb_checksum_start_offset() - skb_network_offset() TUCMD.L4T indicates offset and if checksum or crc32c, based on: skb->csum_offset The added advantage to doing this is that we can support inner checksum offloads for tunnels and MPLS while still being able to transparently insert VLAN tags. I also took the opportunity to clean-up many of the feature flag configuration bits to make them a bit more consistent between drivers. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 162 +++++++----------- 1 file changed, 58 insertions(+), 104 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index bce5737b1a96..0f007d9a2a13 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7202,103 +7202,61 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring, return 1; } +static inline bool ixgbe_ipv6_csum_is_sctp(struct sk_buff *skb) +{ + unsigned int offset = 0; + + ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL); + + return offset == skb_checksum_start_offset(skb); +} + static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring, struct ixgbe_tx_buffer *first) { struct sk_buff *skb = first->skb; u32 vlan_macip_lens = 0; - u32 mss_l4len_idx = 0; u32 type_tucmd = 0; if (skb->ip_summed != CHECKSUM_PARTIAL) { - if (!(first->tx_flags & IXGBE_TX_FLAGS_HW_VLAN) && - !(first->tx_flags & IXGBE_TX_FLAGS_CC)) +csum_failed: + if (!(first->tx_flags & (IXGBE_TX_FLAGS_HW_VLAN | + IXGBE_TX_FLAGS_CC))) return; - vlan_macip_lens = skb_network_offset(skb) << - IXGBE_ADVTXD_MACLEN_SHIFT; - } else { - u8 l4_hdr = 0; - union { - struct iphdr *ipv4; - struct ipv6hdr *ipv6; - u8 *raw; - } network_hdr; - union { - struct tcphdr *tcphdr; - u8 *raw; - } transport_hdr; - __be16 frag_off; - - if (skb->encapsulation) { - network_hdr.raw = skb_inner_network_header(skb); - transport_hdr.raw = skb_inner_transport_header(skb); - vlan_macip_lens = skb_inner_network_offset(skb) << - IXGBE_ADVTXD_MACLEN_SHIFT; - } else { - network_hdr.raw = skb_network_header(skb); - transport_hdr.raw = skb_transport_header(skb); - vlan_macip_lens = skb_network_offset(skb) << - IXGBE_ADVTXD_MACLEN_SHIFT; - } + goto no_csum; + } - /* use first 4 bits to determine IP version */ - switch (network_hdr.ipv4->version) { - case IPVERSION: - vlan_macip_lens |= transport_hdr.raw - network_hdr.raw; - type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; - l4_hdr = network_hdr.ipv4->protocol; - break; - case 6: - vlan_macip_lens |= transport_hdr.raw - network_hdr.raw; - l4_hdr = network_hdr.ipv6->nexthdr; - if (likely((transport_hdr.raw - network_hdr.raw) == - sizeof(struct ipv6hdr))) - break; - ipv6_skip_exthdr(skb, network_hdr.raw - skb->data + - sizeof(struct ipv6hdr), - &l4_hdr, &frag_off); - if (unlikely(frag_off)) - l4_hdr = NEXTHDR_FRAGMENT; - break; - default: + switch (skb->csum_offset) { + case offsetof(struct tcphdr, check): + type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP; + /* fall through */ + case offsetof(struct udphdr, check): + break; + case offsetof(struct sctphdr, checksum): + /* validate that this is actually an SCTP request */ + if (((first->protocol == htons(ETH_P_IP)) && + (ip_hdr(skb)->protocol == IPPROTO_SCTP)) || + ((first->protocol == htons(ETH_P_IPV6)) && + ixgbe_ipv6_csum_is_sctp(skb))) { + type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_SCTP; break; } - - switch (l4_hdr) { - case IPPROTO_TCP: - type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP; - mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) << - IXGBE_ADVTXD_L4LEN_SHIFT; - break; - case IPPROTO_SCTP: - type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP; - mss_l4len_idx = sizeof(struct sctphdr) << - IXGBE_ADVTXD_L4LEN_SHIFT; - break; - case IPPROTO_UDP: - mss_l4len_idx = sizeof(struct udphdr) << - IXGBE_ADVTXD_L4LEN_SHIFT; - break; - default: - if (unlikely(net_ratelimit())) { - dev_warn(tx_ring->dev, - "partial checksum, version=%d, l4 proto=%x\n", - network_hdr.ipv4->version, l4_hdr); - } - skb_checksum_help(skb); - goto no_csum; - } - - /* update TX checksum flag */ - first->tx_flags |= IXGBE_TX_FLAGS_CSUM; + /* fall through */ + default: + skb_checksum_help(skb); + goto csum_failed; } + /* update TX checksum flag */ + first->tx_flags |= IXGBE_TX_FLAGS_CSUM; + vlan_macip_lens = skb_checksum_start_offset(skb) - + skb_network_offset(skb); no_csum: /* vlan_macip_lens: MACLEN, VLAN tag */ + vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; - ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, - type_tucmd, mss_l4len_idx); + ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd, 0); } #define IXGBE_SET_FLAG(_input, _flag, _result) \ @@ -9190,41 +9148,37 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #endif netdev->features = NETIF_F_SG | - NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXHASH | - NETIF_F_RXCSUM; - - netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD; + NETIF_F_RXCSUM | + NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; - switch (adapter->hw.mac.type) { - case ixgbe_mac_82599EB: - case ixgbe_mac_X540: - case ixgbe_mac_X550: - case ixgbe_mac_X550EM_x: + if (hw->mac.type >= ixgbe_mac_82599EB) netdev->features |= NETIF_F_SCTP_CRC; - netdev->hw_features |= NETIF_F_SCTP_CRC | - NETIF_F_NTUPLE | + + /* copy netdev features into list of user selectable features */ + netdev->hw_features |= netdev->features; + netdev->hw_features |= NETIF_F_RXALL | + NETIF_F_HW_L2FW_DOFFLOAD; + + if (hw->mac.type >= ixgbe_mac_82599EB) + netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; - break; - default: - break; - } - netdev->hw_features |= NETIF_F_RXALL; + /* set this bit last since it cannot be part of hw_features */ netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - netdev->vlan_features |= NETIF_F_TSO; - netdev->vlan_features |= NETIF_F_TSO6; - netdev->vlan_features |= NETIF_F_IP_CSUM; - netdev->vlan_features |= NETIF_F_IPV6_CSUM; - netdev->vlan_features |= NETIF_F_SG; + netdev->vlan_features |= NETIF_F_SG | + NETIF_F_TSO | + NETIF_F_TSO6 | + NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC; - netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + netdev->mpls_features |= NETIF_F_HW_CSUM; + netdev->hw_enc_features |= NETIF_F_HW_CSUM; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; -- GitLab From cb2b3edbece804d9836647c1ca51282ad384d425 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 13 Jan 2016 07:31:17 -0800 Subject: [PATCH 1258/9938] ixgbevf: Add support for generic Tx checksums This patch adds support for generic Tx checksums to the ixgbevf driver. It turns out this is actually pretty easy after going over the datasheet as we were doing a number of steps we didn't need to. In order to perform a Tx checksum for an L4 header we need to fill in the following fields in the Tx descriptor: MACLEN (maximum of 127), retrieved from: skb_network_offset() IPLEN (maximum of 511), retrieved from: skb_checksum_start_offset() - skb_network_offset() TUCMD.L4T indicates offset and if checksum or crc32c, based on: skb->csum_offset The added advantage to doing this is that we can support inner checksum offloads for tunnels and MPLS while still being able to transparently insert VLAN tags. I also took the opportunity to clean-up many of the feature flag configuration bits to make them a bit more consistent between drivers. In the case of the VF drivers this meant adding support for SCTP CRCs, and inner checksum offloads for MPLS and various tunnel types. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 104 ++++++++---------- 1 file changed, 43 insertions(+), 61 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 9a2eed0f5245..50b6bfffaf32 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3334,76 +3334,55 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring, return 1; } +static inline bool ixgbevf_ipv6_csum_is_sctp(struct sk_buff *skb) +{ + unsigned int offset = 0; + + ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL); + + return offset == skb_checksum_start_offset(skb); +} + static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring, struct ixgbevf_tx_buffer *first) { struct sk_buff *skb = first->skb; u32 vlan_macip_lens = 0; - u32 mss_l4len_idx = 0; u32 type_tucmd = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 l4_hdr = 0; - __be16 frag_off; - - switch (first->protocol) { - case htons(ETH_P_IP): - vlan_macip_lens |= skb_network_header_len(skb); - type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; - l4_hdr = ip_hdr(skb)->protocol; - break; - case htons(ETH_P_IPV6): - vlan_macip_lens |= skb_network_header_len(skb); - l4_hdr = ipv6_hdr(skb)->nexthdr; - if (likely(skb_network_header_len(skb) == - sizeof(struct ipv6hdr))) - break; - ipv6_skip_exthdr(skb, skb_network_offset(skb) + - sizeof(struct ipv6hdr), - &l4_hdr, &frag_off); - if (unlikely(frag_off)) - l4_hdr = NEXTHDR_FRAGMENT; - break; - default: - break; - } + if (skb->ip_summed != CHECKSUM_PARTIAL) + goto no_csum; - switch (l4_hdr) { - case IPPROTO_TCP: - type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP; - mss_l4len_idx = tcp_hdrlen(skb) << - IXGBE_ADVTXD_L4LEN_SHIFT; - break; - case IPPROTO_SCTP: - type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP; - mss_l4len_idx = sizeof(struct sctphdr) << - IXGBE_ADVTXD_L4LEN_SHIFT; - break; - case IPPROTO_UDP: - mss_l4len_idx = sizeof(struct udphdr) << - IXGBE_ADVTXD_L4LEN_SHIFT; + switch (skb->csum_offset) { + case offsetof(struct tcphdr, check): + type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP; + /* fall through */ + case offsetof(struct udphdr, check): + break; + case offsetof(struct sctphdr, checksum): + /* validate that this is actually an SCTP request */ + if (((first->protocol == htons(ETH_P_IP)) && + (ip_hdr(skb)->protocol == IPPROTO_SCTP)) || + ((first->protocol == htons(ETH_P_IPV6)) && + ixgbevf_ipv6_csum_is_sctp(skb))) { + type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_SCTP; break; - default: - if (unlikely(net_ratelimit())) { - dev_warn(tx_ring->dev, - "partial checksum, l3 proto=%x, l4 proto=%x\n", - first->protocol, l4_hdr); - } - skb_checksum_help(skb); - goto no_csum; } - - /* update TX checksum flag */ - first->tx_flags |= IXGBE_TX_FLAGS_CSUM; + /* fall through */ + default: + skb_checksum_help(skb); + goto no_csum; } - + /* update TX checksum flag */ + first->tx_flags |= IXGBE_TX_FLAGS_CSUM; + vlan_macip_lens = skb_checksum_start_offset(skb) - + skb_network_offset(skb); no_csum: /* vlan_macip_lens: MACLEN, VLAN tag */ vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; - ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, - type_tucmd, mss_l4len_idx); + ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, 0); } static __le32 ixgbevf_tx_cmd_type(u32 tx_flags) @@ -4010,22 +3989,25 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } netdev->hw_features = NETIF_F_SG | - NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_RXCSUM; + NETIF_F_RXCSUM | + NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC; netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; - netdev->vlan_features |= NETIF_F_TSO | + netdev->vlan_features |= NETIF_F_SG | + NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | - NETIF_F_SG; + NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC; + + netdev->mpls_features |= NETIF_F_HW_CSUM; + netdev->hw_enc_features |= NETIF_F_HW_CSUM; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; -- GitLab From afdc71e4d6dc46d0f5bea7461ce356e6056f5ba8 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 25 Jan 2016 16:32:10 -0800 Subject: [PATCH 1259/9938] ixgbe: Fix flow control for Xeon D KR backplane Xeon D KR backplane is different from other backplanes, in that we can't use auto-negotiation to determine the mode. Instead, use whatever the user configured. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ixgbe/ixgbe_82598.c | 1 + .../net/ethernet/intel/ixgbe/ixgbe_82599.c | 1 + .../net/ethernet/intel/ixgbe/ixgbe_common.c | 8 +- .../net/ethernet/intel/ixgbe/ixgbe_common.h | 3 +- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 5 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 86 ++++++++++++++++++- 7 files changed, 98 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index 9790d0274f7f..f47eb12a9c50 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -1192,6 +1192,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = { .clear_vfta = &ixgbe_clear_vfta_82598, .set_vfta = &ixgbe_set_vfta_82598, .fc_enable = &ixgbe_fc_enable_82598, + .setup_fc = ixgbe_setup_fc_generic, .set_fw_drv_ver = NULL, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync, .release_swfw_sync = &ixgbe_release_swfw_sync, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index b276fe0bc665..c3ae5a701d43 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -2220,6 +2220,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = { .clear_vfta = &ixgbe_clear_vfta_generic, .set_vfta = &ixgbe_set_vfta_generic, .fc_enable = &ixgbe_fc_enable_generic, + .setup_fc = ixgbe_setup_fc_generic, .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, .init_uta_tables = &ixgbe_init_uta_tables_generic, .setup_sfp = &ixgbe_setup_sfp_modules_82599, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 64045053e874..8c7e78b21c4e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2015 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -111,12 +111,12 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) } /** - * ixgbe_setup_fc - Set up flow control + * ixgbe_setup_fc_generic - Set up flow control * @hw: pointer to hardware structure * * Called at init time to set up flow control. **/ -static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) +s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) { s32 ret_val = 0; u32 reg = 0, reg_bp = 0; @@ -296,7 +296,7 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) IXGBE_WRITE_FLUSH(hw); /* Setup flow control */ - ret_val = ixgbe_setup_fc(hw); + ret_val = hw->mac.ops.setup_fc(hw); if (ret_val) return ret_val; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 2b9563137fd8..2e290150ab54 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2014 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -81,6 +81,7 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw); +s32 ixgbe_setup_fc_generic(struct ixgbe_hw *); bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw); void ixgbe_fc_autoneg(struct ixgbe_hw *hw); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 29e0b0e1cb67..787d2b21465e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3308,6 +3308,7 @@ struct ixgbe_mac_operations { /* Flow Control */ s32 (*fc_enable)(struct ixgbe_hw *); + s32 (*setup_fc)(struct ixgbe_hw *); /* Manageability interface */ s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8); @@ -3525,6 +3526,7 @@ struct ixgbe_info { #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010) #define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) +#define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C) #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00) @@ -3547,6 +3549,9 @@ struct ixgbe_info { #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE (1 << 29) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART (1 << 31) +#define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE (1 << 28) +#define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE (1 << 29) + #define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN (1 << 6) #define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN (1 << 15) #define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN (1 << 16) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index 0d69564f3a1b..c00b67b4c1dc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -846,6 +846,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = { .clear_vfta = &ixgbe_clear_vfta_generic, .set_vfta = &ixgbe_set_vfta_generic, .fc_enable = &ixgbe_fc_enable_generic, + .setup_fc = ixgbe_setup_fc_generic, .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, .init_uta_tables = &ixgbe_init_uta_tables_generic, .setup_sfp = NULL, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 26e0b8df2afe..972c9aa17503 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -27,6 +27,7 @@ #include "ixgbe_phy.h" static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); +static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) { @@ -1342,15 +1343,18 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; + mac->ops.setup_fc = ixgbe_setup_fc_x550em; mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em; mac->ops.set_rate_select_speed = ixgbe_set_soft_rate_select_speed; break; case ixgbe_media_type_copper: mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; + mac->ops.setup_fc = ixgbe_setup_fc_generic; mac->ops.check_link = ixgbe_check_link_t_X550em; break; default: + mac->ops.setup_fc = ixgbe_setup_fc_x550em; break; } } @@ -1842,6 +1846,82 @@ static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, return status; } +/** + * ixgbe_setup_fc_x550em - Set up flow control + * @hw: pointer to hardware structure + */ +static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) +{ + bool pause, asm_dir; + u32 reg_val; + s32 rc; + + /* Validate the requested mode */ + if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { + hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); + return IXGBE_ERR_INVALID_LINK_SETTINGS; + } + + /* 10gig parts do not have a word in the EEPROM to determine the + * default flow control setting, so we explicitly set it to full. + */ + if (hw->fc.requested_mode == ixgbe_fc_default) + hw->fc.requested_mode = ixgbe_fc_full; + + /* Determine PAUSE and ASM_DIR bits. */ + switch (hw->fc.requested_mode) { + case ixgbe_fc_none: + pause = false; + asm_dir = false; + break; + case ixgbe_fc_tx_pause: + pause = false; + asm_dir = true; + break; + case ixgbe_fc_rx_pause: + /* Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE, as such we fall + * through to the fc_full statement. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + /* Fallthrough */ + case ixgbe_fc_full: + pause = true; + asm_dir = true; + break; + default: + hw_err(hw, "Flow control param set incorrectly\n"); + return IXGBE_ERR_CONFIG; + } + + if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR) + return 0; + + rc = ixgbe_read_iosf_sb_reg_x550(hw, + IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (rc) + return rc; + + reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | + IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); + if (pause) + reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; + if (asm_dir) + reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; + rc = ixgbe_write_iosf_sb_reg_x550(hw, + IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + + /* This device does not fully support AN. */ + hw->fc.disable_fc_autoneg = true; + + return rc; +} + /** ixgbe_enter_lplu_x550em - Transition to low power states * @hw: pointer to hardware structure * @@ -2337,8 +2417,6 @@ static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ .get_thermal_sensor_data = NULL, \ .init_thermal_sensor_thresh = NULL, \ - .prot_autoc_read = &prot_autoc_read_generic, \ - .prot_autoc_write = &prot_autoc_write_generic, \ .enable_rx = &ixgbe_enable_rx_generic, \ .disable_rx = &ixgbe_disable_rx_x550, \ @@ -2354,6 +2432,9 @@ static const struct ixgbe_mac_operations mac_ops_X550 = { .setup_sfp = NULL, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, .release_swfw_sync = &ixgbe_release_swfw_sync_X540, + .prot_autoc_read = prot_autoc_read_generic, + .prot_autoc_write = prot_autoc_write_generic, + .setup_fc = ixgbe_setup_fc_generic, }; static const struct ixgbe_mac_operations mac_ops_X550EM_x = { @@ -2368,6 +2449,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = { .setup_sfp = ixgbe_setup_sfp_modules_X550em, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, + .setup_fc = NULL, /* defined later */ }; #define X550_COMMON_EEP \ -- GitLab From c04f90e592431489df114971ff025265d429e48f Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Wed, 27 Jan 2016 18:33:30 +0000 Subject: [PATCH 1260/9938] ixgbe: add a callback to set the maximum transmit bitrate This commit adds a callback which allows to adjust the maximum transmit bitrate the card can output. This makes it possible to get a smooth traffic instead of the default burst-y behaviour when trying to output e.g. a video stream. Much of the logic needed to get a correct bcnrc_val was taken from the ixgbe_set_vf_rate_limit() function. Signed-off-by: Rostislav Pehlivanov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 31 +++++++++++++++++++ .../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 2 +- .../net/ethernet/intel/ixgbe/ixgbe_sriov.h | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 0f007d9a2a13..115656c690bf 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1077,6 +1077,36 @@ static void ixgbe_tx_timeout_reset(struct ixgbe_adapter *adapter) } } +/** + * ixgbe_tx_maxrate - callback to set the maximum per-queue bitrate + **/ +static int ixgbe_tx_maxrate(struct net_device *netdev, + int queue_index, u32 maxrate) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u32 bcnrc_val = ixgbe_link_mbps(adapter); + + if (!maxrate) + return 0; + + /* Calculate the rate factor values to set */ + bcnrc_val <<= IXGBE_RTTBCNRC_RF_INT_SHIFT; + bcnrc_val /= maxrate; + + /* clear everything but the rate factor */ + bcnrc_val &= IXGBE_RTTBCNRC_RF_INT_MASK | + IXGBE_RTTBCNRC_RF_DEC_MASK; + + /* enable the rate scheduler */ + bcnrc_val |= IXGBE_RTTBCNRC_RS_ENA; + + IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, queue_index); + IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val); + + return 0; +} + /** * ixgbe_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: structure containing interrupt and ring information @@ -8807,6 +8837,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_set_mac_address = ixgbe_set_mac, .ndo_change_mtu = ixgbe_change_mtu, .ndo_tx_timeout = ixgbe_tx_timeout, + .ndo_set_tx_maxrate = ixgbe_tx_maxrate, .ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid, .ndo_do_ioctl = ixgbe_ioctl, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 4bc249632ec2..adcf00002483 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -1398,7 +1398,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) return err; } -static int ixgbe_link_mbps(struct ixgbe_adapter *adapter) +int ixgbe_link_mbps(struct ixgbe_adapter *adapter) { switch (adapter->link_speed) { case IXGBE_LINK_SPEED_100_FULL: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h index dad925706f4c..47e65e2f886a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h @@ -44,6 +44,7 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter); int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int queue, u8 *mac); int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan, u8 qos); +int ixgbe_link_mbps(struct ixgbe_adapter *adapter); int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int max_tx_rate); int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); -- GitLab From dbd15b8f9cc3f0f8d665d048a31c0f4b5c9150a5 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 9 Mar 2016 16:45:00 -0500 Subject: [PATCH 1261/9938] ixgbe: Place SWFW semaphore in known valid state at probe It is possible on some HW that a system reset could occur when we are holding the SWFW semaphore lock. So next time the driver was loaded we would see it incorrectly as locked. This patch will recover from that state by: Attempting to acquire the semaphore and then regardless of whether or not it was acquire we immediately release it. This will force us into a known good state. Signed-off-by: Don Skidmore Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ixgbe/ixgbe_82598.c | 1 + .../net/ethernet/intel/ixgbe/ixgbe_82599.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 20 +++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 2 ++ 7 files changed, 30 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index f47eb12a9c50..6ecd598c6ef5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -1196,6 +1196,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = { .set_fw_drv_ver = NULL, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync, .release_swfw_sync = &ixgbe_release_swfw_sync, + .init_swfw_sync = NULL, .get_thermal_sensor_data = NULL, .init_thermal_sensor_thresh = NULL, .prot_autoc_read = &prot_autoc_read_generic, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index c3ae5a701d43..4bb6b685263b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -2228,6 +2228,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = { .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync, .release_swfw_sync = &ixgbe_release_swfw_sync, + .init_swfw_sync = NULL, .get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic, .init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic, .prot_autoc_read = &prot_autoc_read_82599, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 115656c690bf..77c1c85a957c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9126,6 +9126,10 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_sw_init; + /* Make sure the SWFW semaphore is in a valid state */ + if (hw->mac.ops.init_swfw_sync) + hw->mac.ops.init_swfw_sync(hw); + /* Make it possible the adapter to be woken up via WOL */ switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 787d2b21465e..bc012ab48475 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3266,6 +3266,7 @@ struct ixgbe_mac_operations { s32 (*enable_rx_dma)(struct ixgbe_hw *, u32); s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u32); void (*release_swfw_sync)(struct ixgbe_hw *, u32); + void (*init_swfw_sync)(struct ixgbe_hw *); s32 (*prot_autoc_read)(struct ixgbe_hw *, bool *, u32 *); s32 (*prot_autoc_write)(struct ixgbe_hw *, u32, bool); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index c00b67b4c1dc..40824d85d807 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -746,6 +746,25 @@ static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw) IXGBE_WRITE_FLUSH(hw); } +/** + * ixgbe_init_swfw_sync_X540 - Release hardware semaphore + * @hw: pointer to hardware structure + * + * This function reset hardware semaphore bits for a semaphore that may + * have be left locked due to a catastrophic failure. + **/ +void ixgbe_init_swfw_sync_X540(struct ixgbe_hw *hw) +{ + /* First try to grab the semaphore but we don't need to bother + * looking to see whether we got the lock or not since we do + * the same thing regardless of whether we got the lock or not. + * We got the lock - we release it. + * We timeout trying to get the lock - we force its release. + */ + ixgbe_get_swfw_sync_semaphore(hw); + ixgbe_release_swfw_sync_semaphore(hw); +} + /** * ixgbe_blink_led_start_X540 - Blink LED based on index. * @hw: pointer to hardware structure @@ -854,6 +873,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = { .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, .release_swfw_sync = &ixgbe_release_swfw_sync_X540, + .init_swfw_sync = &ixgbe_init_swfw_sync_X540, .disable_rx_buff = &ixgbe_disable_rx_buff_generic, .enable_rx_buff = &ixgbe_enable_rx_buff_generic, .get_thermal_sensor_data = NULL, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h index a1468b1f4d8a..e21cd48491d3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h @@ -36,4 +36,5 @@ s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index); s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask); void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask); +void ixgbe_init_swfw_sync_X540(struct ixgbe_hw *hw); s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 972c9aa17503..9d3f765638cc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2432,6 +2432,7 @@ static const struct ixgbe_mac_operations mac_ops_X550 = { .setup_sfp = NULL, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, .release_swfw_sync = &ixgbe_release_swfw_sync_X540, + .init_swfw_sync = &ixgbe_init_swfw_sync_X540, .prot_autoc_read = prot_autoc_read_generic, .prot_autoc_write = prot_autoc_write_generic, .setup_fc = ixgbe_setup_fc_generic, @@ -2449,6 +2450,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = { .setup_sfp = ixgbe_setup_sfp_modules_X550em, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, + .init_swfw_sync = &ixgbe_init_swfw_sync_X540, .setup_fc = NULL, /* defined later */ }; -- GitLab From 4ae7834221679bff2d7f75ba80a20673cecb38ad Mon Sep 17 00:00:00 2001 From: Amritha Nambiar Date: Wed, 9 Mar 2016 18:32:16 -0500 Subject: [PATCH 1262/9938] ixgbe: Extend cls_u32 offload to support UDP headers Added support to match on UDP fields in the transport layer. Extended core logic to support multiple headers. Verified with the following filters : handle 1: u32 divisor 1 u32 ht 800: order 1 link 1: \ offset at 0 mask 0f00 shift 6 plus 0 eat match ip protocol 6 ff u32 ht 1: order 2 \ match tcp src 1024 ffff match tcp dst 23 ffff action drop handle 2: u32 divisor 1 u32 ht 800: order 3 link 2: \ offset at 0 mask 0f00 shift 6 plus 0 eat match ip protocol 17 ff u32 ht 2: order 4 \ match udp src 1025 ffff match udp dst 24 ffff action drop Signed-off-by: Amritha Nambiar Acked-by: John Fastabend Acked-by: Sridhar Samudrala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 19 ++++++++++--------- .../net/ethernet/intel/ixgbe/ixgbe_model.h | 8 ++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 77c1c85a957c..359869cf5b09 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8257,19 +8257,20 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, return -EINVAL; for (i = 0; nexthdr[i].jump; i++) { - if (nexthdr->o != cls->knode.sel->offoff || - nexthdr->s != cls->knode.sel->offshift || - nexthdr->m != cls->knode.sel->offmask || + if (nexthdr[i].o != cls->knode.sel->offoff || + nexthdr[i].s != cls->knode.sel->offshift || + nexthdr[i].m != cls->knode.sel->offmask || /* do not support multiple key jumps its just mad */ cls->knode.sel->nkeys > 1) return -EINVAL; - if (nexthdr->off != cls->knode.sel->keys[0].off || - nexthdr->val != cls->knode.sel->keys[0].val || - nexthdr->mask != cls->knode.sel->keys[0].mask) - return -EINVAL; - - adapter->jump_tables[link_uhtid] = nexthdr->jump; + if (nexthdr[i].off == cls->knode.sel->keys[0].off && + nexthdr[i].val == cls->knode.sel->keys[0].val && + nexthdr[i].mask == cls->knode.sel->keys[0].mask) { + adapter->jump_tables[link_uhtid] = + nexthdr[i].jump; + break; + } } return 0; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h index 74c53ad9d268..60adde55a8c3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h @@ -82,6 +82,12 @@ static struct ixgbe_mat_field ixgbe_tcp_fields[] = { { .val = NULL } /* terminal node */ }; +static struct ixgbe_mat_field ixgbe_udp_fields[] = { + {.off = 0, .val = ixgbe_mat_prgm_ports, + .type = IXGBE_ATR_FLOW_TYPE_UDPV4}, + { .val = NULL } /* terminal node */ +}; + struct ixgbe_nexthdr { /* offset, shift, and mask of position to next header */ unsigned int o; @@ -98,6 +104,8 @@ struct ixgbe_nexthdr { static struct ixgbe_nexthdr ixgbe_ipv4_jumps[] = { { .o = 0, .s = 6, .m = 0xf, .off = 8, .val = 0x600, .mask = 0xff00, .jump = ixgbe_tcp_fields}, + { .o = 0, .s = 6, .m = 0xf, + .off = 8, .val = 0x1100, .mask = 0xff00, .jump = ixgbe_udp_fields}, { .jump = NULL } /* terminal node */ }; #endif /* _IXGBE_MODEL_H_ */ -- GitLab From 0c5a616650a08b766e529511348274c1914ef4bf Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 10 Mar 2016 10:01:10 -0800 Subject: [PATCH 1263/9938] ixgbe: Add support for toggling VLAN filtering flag via ethtool This change makes it so that we can use the ethtool rx-vlan-filter flag to toggle Rx VLAN filtering on and off. This is basically just an extension of the existing VLAN promisc work in that it just adds support for the additional ethtool flag. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 359869cf5b09..19bf3860d3d8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4447,6 +4447,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev) struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 fctrl, vmolr = IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE; + netdev_features_t features = netdev->features; int count; /* Check for Promiscuous and All Multicast modes */ @@ -4464,14 +4465,13 @@ void ixgbe_set_rx_mode(struct net_device *netdev) hw->addr_ctrl.user_set_promisc = true; fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); vmolr |= IXGBE_VMOLR_MPE; - ixgbe_vlan_promisc_enable(adapter); + features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; } else { if (netdev->flags & IFF_ALLMULTI) { fctrl |= IXGBE_FCTRL_MPE; vmolr |= IXGBE_VMOLR_MPE; } hw->addr_ctrl.user_set_promisc = false; - ixgbe_vlan_promisc_disable(adapter); } /* @@ -4504,7 +4504,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev) } /* This is useful for sniffing bad packets. */ - if (adapter->netdev->features & NETIF_F_RXALL) { + if (features & NETIF_F_RXALL) { /* UPE and MPE will be handled by normal PROMISC logic * in e1000e_set_rx_mode */ fctrl |= (IXGBE_FCTRL_SBP | /* Receive bad packets */ @@ -4517,10 +4517,15 @@ void ixgbe_set_rx_mode(struct net_device *netdev) IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) + if (features & NETIF_F_HW_VLAN_CTAG_RX) ixgbe_vlan_strip_enable(adapter); else ixgbe_vlan_strip_disable(adapter); + + if (features & NETIF_F_HW_VLAN_CTAG_FILTER) + ixgbe_vlan_promisc_disable(adapter); + else + ixgbe_vlan_promisc_enable(adapter); } static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) @@ -8495,11 +8500,6 @@ static int ixgbe_set_features(struct net_device *netdev, adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; } - if (features & NETIF_F_HW_VLAN_CTAG_RX) - ixgbe_vlan_strip_enable(adapter); - else - ixgbe_vlan_strip_disable(adapter); - if (changed & NETIF_F_RXALL) need_reset = true; @@ -8516,6 +8516,9 @@ static int ixgbe_set_features(struct net_device *netdev, if (need_reset) ixgbe_do_reset(netdev); + else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_FILTER)) + ixgbe_set_rx_mode(netdev); return 0; } @@ -9190,7 +9193,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_RXCSUM | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX; + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_FILTER; if (hw->mac.type >= ixgbe_mac_82599EB) netdev->features |= NETIF_F_SCTP_CRC; @@ -9204,9 +9208,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; - /* set this bit last since it cannot be part of hw_features */ - netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | -- GitLab From 2e7bd5ef98030999eaf4bf101707e595432fc8c2 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 31 Mar 2016 16:53:41 -0400 Subject: [PATCH 1264/9938] net: dsa: mv88e6xxx: protect SID register access Introduce a mv88e6xxx_has_stu() helper to protect the access to the GLOBAL_VTU_SID register, instead of checking switch families. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 50454be86570..29b24446bd2b 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -482,6 +482,16 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds) return false; } +static bool mv88e6xxx_has_stu(struct dsa_switch *ds) +{ + /* Does the device have STU and dedicated SID registers for VTU ops? */ + if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || + mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) + return true; + + return false; +} + /* We expect the switch to perform auto negotiation if there is a real * phy. However, in the case of a fixed link phy, we force the port * settings from the fixed link settings. @@ -1329,7 +1339,9 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, return ret; next.fid = ret & GLOBAL_VTU_FID_MASK; + } + if (mv88e6xxx_has_stu(ds)) { ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_SID); if (ret < 0) @@ -1412,8 +1424,7 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, if (ret < 0) return ret; - if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) { + if (mv88e6xxx_has_stu(ds)) { reg = entry->sid & GLOBAL_VTU_SID_MASK; ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, reg); if (ret < 0) -- GitLab From b426e5f7fe4cd7041b3d8bed58f1e60bba1d11bf Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 31 Mar 2016 16:53:42 -0400 Subject: [PATCH 1265/9938] net: dsa: mv88e6xxx: protect FID registers access Only switch families with 4096 address databases have dedicated FID registers for ATU and VTU operations. Factorize the access to the GLOBAL_ATU_FID register and introduce a mv88e6xxx_has_fid_reg() helper function to protect the access to GLOBAL_ATU_FID and GLOBAL_VTU_FID. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 42 ++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 29b24446bd2b..ebb9ae927426 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -482,6 +482,16 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds) return false; } +static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds) +{ + /* Does the device have dedicated FID registers for ATU and VTU ops? */ + if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || + mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) + return true; + + return false; +} + static bool mv88e6xxx_has_stu(struct dsa_switch *ds) { /* Does the device have STU and dedicated SID registers for VTU ops? */ @@ -961,10 +971,16 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, return ret; } -static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 cmd) +static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd) { int ret; + if (mv88e6xxx_has_fid_reg(ds)) { + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); + if (ret < 0) + return ret; + } + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd); if (ret < 0) return ret; @@ -1011,11 +1027,6 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds, return err; if (entry->fid) { - err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, - entry->fid); - if (err) - return err; - op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB : GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB; } else { @@ -1023,7 +1034,7 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds, GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC; } - return _mv88e6xxx_atu_cmd(ds, op); + return _mv88e6xxx_atu_cmd(ds, entry->fid, op); } static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too) @@ -1331,8 +1342,7 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, if (ret < 0) return ret; - if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) { + if (mv88e6xxx_has_fid_reg(ds)) { ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_FID); if (ret < 0) @@ -1429,7 +1439,9 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, reg); if (ret < 0) return ret; + } + if (mv88e6xxx_has_fid_reg(ds)) { reg = entry->fid & GLOBAL_VTU_FID_MASK; ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_FID, reg); if (ret < 0) @@ -1976,11 +1988,7 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds, if (ret < 0) return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, entry->fid); - if (ret < 0) - return ret; - - return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_LOAD_DB); + return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB); } static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, @@ -2063,11 +2071,7 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, if (ret < 0) return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); - if (ret < 0) - return ret; - - ret = _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_GET_NEXT_DB); + ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); if (ret < 0) return ret; -- GitLab From f74df0be82d7d29747bfd68d955f4f573f9e5691 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 31 Mar 2016 16:53:43 -0400 Subject: [PATCH 1266/9938] net: dsa: mv88e6xxx: variable number of databases Marvell switch chips have different number of address databases. The code currently only supports models with 4096 databases. Such switch has dedicated FID registers for ATU and VTU operations. Models with fewer databases have their FID split in several registers. List them all but only support models with 4096 databases at the moment. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 38 +++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index ebb9ae927426..f103319dbe14 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -482,6 +482,30 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds) return false; } +static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + + /* The following devices have 4-bit identifiers for 16 databases */ + if (ps->id == PORT_SWITCH_ID_6061) + return 16; + + /* The following devices have 6-bit identifiers for 64 databases */ + if (ps->id == PORT_SWITCH_ID_6065) + return 64; + + /* The following devices have 8-bit identifiers for 256 databases */ + if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) + return 256; + + /* The following devices have 12-bit identifiers for 4096 databases */ + if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || + mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) + return 4096; + + return 0; +} + static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds) { /* Does the device have dedicated FID registers for ATU and VTU ops? */ @@ -1534,9 +1558,15 @@ static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds, static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, u16 *old) { + u16 upper_mask; u16 fid; int ret; + if (mv88e6xxx_num_databases(ds) == 4096) + upper_mask = 0xff; + else + return -EOPNOTSUPP; + /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */ ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN); if (ret < 0) @@ -1559,11 +1589,11 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, if (ret < 0) return ret; - fid |= (ret & PORT_CONTROL_1_FID_11_4_MASK) << 4; + fid |= (ret & upper_mask) << 4; if (new) { - ret &= ~PORT_CONTROL_1_FID_11_4_MASK; - ret |= (*new >> 4) & PORT_CONTROL_1_FID_11_4_MASK; + ret &= ~upper_mask; + ret |= (*new >> 4) & upper_mask; ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1, ret); @@ -1627,7 +1657,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid) * databases are not needed. Return the next positive available. */ *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1); - if (unlikely(*fid == MV88E6XXX_N_FID)) + if (unlikely(*fid >= mv88e6xxx_num_databases(ds))) return -ENOSPC; /* Clear the database */ -- GitLab From 11ea809f1a74b006f08e7dad0b257e06c817f313 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 31 Mar 2016 16:53:44 -0400 Subject: [PATCH 1267/9938] net: dsa: mv88e6xxx: support 256 databases The 6185 family of devices has only 256 address databases. Their 8-bit FID for ATU and VTU operations are split into ATU Control and ATU/VTU Operation registers. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index f103319dbe14..75a4abc595b1 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1003,6 +1003,20 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd) ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); if (ret < 0) return ret; + } else if (mv88e6xxx_num_databases(ds) == 256) { + /* ATU DBNum[7:4] are located in ATU Control 15:12 */ + ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL); + if (ret < 0) + return ret; + + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL, + (ret & 0xfff) | + ((fid << 8) & 0xf000)); + if (ret < 0) + return ret; + + /* ATU DBNum[3:0] are located in ATU Operation 3:0 */ + cmd |= fid & 0xf; } ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd); @@ -1373,6 +1387,17 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, return ret; next.fid = ret & GLOBAL_VTU_FID_MASK; + } else if (mv88e6xxx_num_databases(ds) == 256) { + /* VTU DBNum[7:4] are located in VTU Operation 11:8, and + * VTU DBNum[3:0] are located in VTU Operation 3:0 + */ + ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, + GLOBAL_VTU_OP); + if (ret < 0) + return ret; + + next.fid = (ret & 0xf00) >> 4; + next.fid |= ret & 0xf; } if (mv88e6xxx_has_stu(ds)) { @@ -1443,6 +1468,7 @@ int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, struct mv88e6xxx_vtu_stu_entry *entry) { + u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE; u16 reg = 0; int ret; @@ -1470,6 +1496,12 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_FID, reg); if (ret < 0) return ret; + } else if (mv88e6xxx_num_databases(ds) == 256) { + /* VTU DBNum[7:4] are located in VTU Operation 11:8, and + * VTU DBNum[3:0] are located in VTU Operation 3:0 + */ + op |= (entry->fid & 0xf0) << 8; + op |= entry->fid & 0xf; } reg = GLOBAL_VTU_VID_VALID; @@ -1479,7 +1511,7 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, if (ret < 0) return ret; - return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_VTU_LOAD_PURGE); + return _mv88e6xxx_vtu_cmd(ds, op); } static int _mv88e6xxx_stu_getnext(struct dsa_switch *ds, u8 sid, @@ -1564,6 +1596,8 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, if (mv88e6xxx_num_databases(ds) == 4096) upper_mask = 0xff; + else if (mv88e6xxx_num_databases(ds) == 256) + upper_mask = 0xf; else return -EOPNOTSUPP; -- GitLab From f93dd042de08633ff481d092245f2d9b4a3cdb6a Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 31 Mar 2016 16:53:45 -0400 Subject: [PATCH 1268/9938] net: dsa: mv88e6xxx: map destination addresses for 6185 The 88E6185 switch also has a MapDA bit in its Port Control 2 register. When this bit is cleared, all frames are sent out to the CPU port. Set this bit to rely on address databases (ATU) hits and direct frames out of the correct ports, and thus allow hardware bridging. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 75a4abc595b1..0dda2817d0ec 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2523,7 +2523,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) reg = 0; if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || - mv88e6xxx_6095_family(ds) || mv88e6xxx_6320_family(ds)) + mv88e6xxx_6095_family(ds) || mv88e6xxx_6320_family(ds) || + mv88e6xxx_6185_family(ds)) reg = PORT_CONTROL_2_MAP_DA; if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || -- GitLab From 26892ffc80b4276f6f0d61232a769100023b38ab Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 31 Mar 2016 16:53:46 -0400 Subject: [PATCH 1269/9938] net: dsa: mv88e6131: enable hardware bridging By adding support for bridge operations, FDB operations, and optionally VLAN operations (for 802.1Q and VLAN filtering aware systems), the switch bridges ports correctly, the CPU is able to populate the hardware address databases, and thus hardware bridging becomes functional within the 88E6185 family of switches. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6131.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index a92ca651c399..24070287c2bc 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -169,6 +169,17 @@ struct dsa_switch_driver mv88e6131_switch_driver = { .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, .adjust_link = mv88e6xxx_adjust_link, + .port_bridge_join = mv88e6xxx_port_bridge_join, + .port_bridge_leave = mv88e6xxx_port_bridge_leave, + .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, + .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, + .port_vlan_add = mv88e6xxx_port_vlan_add, + .port_vlan_del = mv88e6xxx_port_vlan_del, + .port_vlan_dump = mv88e6xxx_port_vlan_dump, + .port_fdb_prepare = mv88e6xxx_port_fdb_prepare, + .port_fdb_add = mv88e6xxx_port_fdb_add, + .port_fdb_del = mv88e6xxx_port_fdb_del, + .port_fdb_dump = mv88e6xxx_port_fdb_dump, }; MODULE_ALIAS("platform:mv88e6085"); -- GitLab From f1974b484f9d070623215b4f461f3420b4fbbd07 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:38:35 +0800 Subject: [PATCH 1270/9938] ACPICA: Linuxize: Remove useless platform headers Some platform headers were added to Linux during previous release cycles, but they are not useful in Linux, so drop them. Signed-off-by: Lv Zheng [ rjw: Changelog ] Signed-off-by: Rafael J. Wysocki --- include/acpi/platform/acmsvcex.h | 54 -------------------------------- include/acpi/platform/acwinex.h | 49 ----------------------------- 2 files changed, 103 deletions(-) delete mode 100644 include/acpi/platform/acmsvcex.h delete mode 100644 include/acpi/platform/acwinex.h diff --git a/include/acpi/platform/acmsvcex.h b/include/acpi/platform/acmsvcex.h deleted file mode 100644 index 28084a1034fe..000000000000 --- a/include/acpi/platform/acmsvcex.h +++ /dev/null @@ -1,54 +0,0 @@ -/****************************************************************************** - * - * Name: acmsvcex.h - Extra VC specific defines, etc. - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2016, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#ifndef __ACMSVCEX_H__ -#define __ACMSVCEX_H__ - -/* Debug support. */ - -#ifdef _DEBUG -#define _CRTDBG_MAP_ALLOC /* Enables specific file/lineno for leaks */ -#include -#endif - -#endif /* __ACMSVCEX_H__ */ diff --git a/include/acpi/platform/acwinex.h b/include/acpi/platform/acwinex.h deleted file mode 100644 index a00b3e4b80b0..000000000000 --- a/include/acpi/platform/acwinex.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Name: acwinex.h - Extra OS specific defines, etc. - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2016, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#ifndef __ACWINEX_H__ -#define __ACWINEX_H__ - -/* Windows uses VC */ - -#endif /* __ACWINEX_H__ */ -- GitLab From c7200ffe432c6544b373f08fab33dc8e9b92516c Mon Sep 17 00:00:00 2001 From: Aleksey Makarov Date: Thu, 24 Mar 2016 09:38:42 +0800 Subject: [PATCH 1271/9938] ACPICA: Headers: Add new constants for the DBG2 ACPI table ACPICA commit 1607b69238df9c1b2940262a17aa94ec49033278 Link: https://github.com/acpica/acpica/commit/1607b692 Signed-off-by: Aleksey Makarov . Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index a4ef62537cac..7702b27a18ed 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -321,7 +321,7 @@ struct acpi_csrt_descriptor { * DBG2 - Debug Port Table 2 * Version 0 (Both main table and subtables) * - * Conforms to "Microsoft Debug Port Table 2 (DBG2)", May 22 2012. + * Conforms to "Microsoft Debug Port Table 2 (DBG2)", December 10, 2015 * ******************************************************************************/ @@ -371,6 +371,11 @@ struct acpi_dbg2_device { #define ACPI_DBG2_16550_COMPATIBLE 0x0000 #define ACPI_DBG2_16550_SUBSET 0x0001 +#define ACPI_DBG2_ARM_PL011 0x0003 +#define ACPI_DBG2_ARM_SBSA_32BIT 0x000D +#define ACPI_DBG2_ARM_SBSA_GENERIC 0x000E +#define ACPI_DBG2_ARM_DCC 0x000F +#define ACPI_DBG2_BCM2835 0x0010 #define ACPI_DBG2_1394_STANDARD 0x0000 -- GitLab From 29a3f38e4452b2ec9686927bd290a1048ab6ab07 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:38:49 +0800 Subject: [PATCH 1272/9938] ACPICA: Headers: Minor update for SPCR ACPI table ACPICA commit f3caa7f2e63be31f7fb8dbccabffbb70c29c3021 Update version number and date of specification document. Point to DBG2 table for some constants. Link: https://github.com/acpica/acpica/commit/f3caa7f2 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 7702b27a18ed..e9d3cc159181 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1107,10 +1107,10 @@ struct acpi_table_slic { /******************************************************************************* * * SPCR - Serial Port Console Redirection table - * Version 1 + * Version 2 * * Conforms to "Serial Port Console Redirection Table", - * Version 1.00, January 11, 2002 + * Version 1.03, August 10, 2015 * ******************************************************************************/ @@ -1142,6 +1142,8 @@ struct acpi_table_spcr { #define ACPI_SPCR_DO_NOT_DISABLE (1) +/* Values for Interface Type: See the definition of the DBG2 table */ + /******************************************************************************* * * SPMI - Server Platform Management Interface table -- GitLab From 7cd55c76f35ffb9aa0a3062be0e3b2f66babfcd0 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:38:57 +0800 Subject: [PATCH 1273/9938] ACPICA: ACPI 6.1: Updates for the HEST ACPI table ACPICA commit 7e81afb625f5184000713de2b1f280e73251bc03 Additional structure for the generic error entry. Some additional constants/flags. With assistance from Abdulhamid, Harb Link: https://github.com/acpica/acpica/commit/7e81afb6 Reviewed-by: Harb Abdulhamid Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl1.h | 54 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 16e013600c19..b7c96b7832ef 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -427,7 +427,8 @@ enum acpi_hest_types { ACPI_HEST_TYPE_AER_ENDPOINT = 7, ACPI_HEST_TYPE_AER_BRIDGE = 8, ACPI_HEST_TYPE_GENERIC_ERROR = 9, - ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */ + ACPI_HEST_TYPE_GENERIC_ERROR_V2 = 10, + ACPI_HEST_TYPE_RESERVED = 11 /* 11 and greater are reserved */ }; /* @@ -506,7 +507,11 @@ enum acpi_hest_notify_types { ACPI_HEST_NOTIFY_NMI = 4, ACPI_HEST_NOTIFY_CMCI = 5, /* ACPI 5.0 */ ACPI_HEST_NOTIFY_MCE = 6, /* ACPI 5.0 */ - ACPI_HEST_NOTIFY_RESERVED = 7 /* 7 and greater are reserved */ + ACPI_HEST_NOTIFY_GPIO = 7, /* ACPI 6.0 */ + ACPI_HEST_NOTIFY_SEA = 8, /* ACPI 6.1 */ + ACPI_HEST_NOTIFY_SEI = 9, /* ACPI 6.1 */ + ACPI_HEST_NOTIFY_GSIV = 10, /* ACPI 6.1 */ + ACPI_HEST_NOTIFY_RESERVED = 11 /* 11 and greater are reserved */ }; /* Values for config_write_enable bitfield above */ @@ -603,6 +608,24 @@ struct acpi_hest_generic { u32 error_block_length; }; +/* 10: Generic Hardware Error Source, version 2 */ + +struct acpi_hest_generic_v2 { + struct acpi_hest_header header; + u16 related_source_id; + u8 reserved; + u8 enabled; + u32 records_to_preallocate; + u32 max_sections_per_record; + u32 max_raw_data_length; + struct acpi_generic_address error_status_address; + struct acpi_hest_notify notify; + u32 error_block_length; + struct acpi_generic_address read_ack_register; + u64 read_ack_preserve; + u64 read_ack_write; +}; + /* Generic Error Status block */ struct acpi_hest_generic_status { @@ -634,6 +657,33 @@ struct acpi_hest_generic_data { u8 fru_text[20]; }; +/* Extension for revision 0x0300 */ + +struct acpi_hest_generic_data_v300 { + u8 section_type[16]; + u32 error_severity; + u16 revision; + u8 validation_bits; + u8 flags; + u32 error_data_length; + u8 fru_id[16]; + u8 fru_text[20]; + u64 time_stamp; +}; + +/* Values for error_severity above */ + +#define ACPI_HEST_GEN_ERROR_RECOVERABLE 0 +#define ACPI_HEST_GEN_ERROR_FATAL 1 +#define ACPI_HEST_GEN_ERROR_CORRECTED 2 +#define ACPI_HEST_GEN_ERROR_NONE 3 + +/* Flags for validation_bits above */ + +#define ACPI_HEST_GEN_VALID_FRU_ID (1) +#define ACPI_HEST_GEN_VALID_FRU_STRING (1<<1) +#define ACPI_HEST_GEN_VALID_TIMESTAMP (1<<2) + /******************************************************************************* * * MADT - Multiple APIC Description Table -- GitLab From 4ac78baf88d85c49883fcc87d31198ebe408e54d Mon Sep 17 00:00:00 2001 From: Al Stone Date: Thu, 24 Mar 2016 09:39:07 +0800 Subject: [PATCH 1274/9938] ACPICA: IORT: Add in support for the SMMUv3 subtable ACPICA commit 9f7c3e148f440049615e2791d73b292f65692d7e The most recent version of the IORT specification adds in a definition for a subtable to describe SMMUv3 devices; there is already a subtable for SMMUv1/v2 devices. Add in the definition of the subtable, add in the code to compile it, and add in a template for it. Link: https://github.com/acpica/acpica/commit/9f7c3e14 Signed-off-by: Al Stone Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index e9d3cc159181..d6bd37758e33 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -660,7 +660,7 @@ struct acpi_ibft_target { * IORT - IO Remapping Table * * Conforms to "IO Remapping Table System Software on ARM Platforms", - * Document number: ARM DEN 0049A, 2015 + * Document number: ARM DEN 0049B, October 2015 * ******************************************************************************/ @@ -690,7 +690,8 @@ enum acpi_iort_node_type { ACPI_IORT_NODE_ITS_GROUP = 0x00, ACPI_IORT_NODE_NAMED_COMPONENT = 0x01, ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02, - ACPI_IORT_NODE_SMMU = 0x03 + ACPI_IORT_NODE_SMMU = 0x03, + ACPI_IORT_NODE_SMMU_V3 = 0x04 }; struct acpi_iort_id_mapping { @@ -780,6 +781,23 @@ struct acpi_iort_smmu { #define ACPI_IORT_SMMU_DVM_SUPPORTED (1) #define ACPI_IORT_SMMU_COHERENT_WALK (1<<1) +struct acpi_iort_smmu_v3 { + u64 base_address; /* SMMUv3 base address */ + u32 flags; + u32 reserved; + u64 vatos_address; + u32 model; /* O: generic SMMUv3 */ + u32 event_gsiv; + u32 pri_gsiv; + u32 gerr_gsiv; + u32 sync_gsiv; +}; + +/* Masks for Flags field above */ + +#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1) +#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (1<<1) + /******************************************************************************* * * IVRS - I/O Virtualization Reporting Structure -- GitLab From 138a95547ab04f5f9d49bfb12bd764f7a7edbcf4 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:39:14 +0800 Subject: [PATCH 1275/9938] ACPICA: ACPI 6.1: Update NFIT table for additional new fields ACPICA commit bc81a4494d7648a496e0a82f0d27562103ee1ec1 Changes the NFIT Control Region. Link: https://github.com/acpica/acpica/commit/bc81a449 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl1.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index b7c96b7832ef..912dff90c4c2 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -984,7 +984,7 @@ struct acpi_msct_proximity { /******************************************************************************* * - * NFIT - NVDIMM Interface Table (ACPI 6.0) + * NFIT - NVDIMM Interface Table (ACPI 6.0+) * Version 1 * ******************************************************************************/ @@ -1065,6 +1065,7 @@ struct acpi_nfit_memory_map { #define ACPI_NFIT_MEM_NOT_ARMED (1<<3) /* 03: Memory Device is not armed */ #define ACPI_NFIT_MEM_HEALTH_OBSERVED (1<<4) /* 04: Memory Device observed SMART/health events */ #define ACPI_NFIT_MEM_HEALTH_ENABLED (1<<5) /* 05: SMART/health events enabled */ +#define ACPI_NFIT_MEM_MAP_FAILED (1<<6) /* 06: Mapping to SPA failed */ /* 2: Interleave Structure */ @@ -1096,7 +1097,10 @@ struct acpi_nfit_control_region { u16 subsystem_vendor_id; u16 subsystem_device_id; u16 subsystem_revision_id; - u8 reserved[6]; /* Reserved, must be zero */ + u8 valid_fields; + u8 manufacturing_location; + u16 manufacturing_date; + u8 reserved[2]; /* Reserved, must be zero */ u32 serial_number; u16 code; u16 windows; @@ -1111,7 +1115,11 @@ struct acpi_nfit_control_region { /* Flags */ -#define ACPI_NFIT_CONTROL_BUFFERED (1) /* Block Data Windows implementation is buffered */ +#define ACPI_NFIT_CONTROL_BUFFERED (1) /* Block Data Windows implementation is buffered */ + +/* valid_fields bits */ + +#define ACPI_NFIT_CONTROL_MFG_INFO_VALID (1) /* Manufacturing fields are valid */ /* 5: NVDIMM Block Data Window Region Structure */ -- GitLab From 3a9ca4d5f179b19919679171240e9ba3ea0c5df9 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:39:21 +0800 Subject: [PATCH 1276/9938] ACPICA: Headers: Update DMAR table for October 2014 I/O spec ACPICA commit 454b2ea5f0c254e97612e15994f7d4734a7931ea Adds two flags to the DMAR table. Link: https://github.com/acpica/acpica/commit/454b2ea5 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl2.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index d6bd37758e33..c93dbadfc71d 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -404,7 +404,7 @@ struct acpi_table_dbgp { * Version 1 * * Conforms to "Intel Virtualization Technology for Directed I/O", - * Version 2.2, Sept. 2013 + * Version 2.3, October 2014 * ******************************************************************************/ @@ -418,6 +418,8 @@ struct acpi_table_dmar { /* Masks for Flags field above */ #define ACPI_DMAR_INTR_REMAP (1) +#define ACPI_DMAR_X2APIC_OPT_OUT (1<<1) +#define ACPI_DMAR_X2APIC_MODE (1<<2) /* DMAR subtable header */ -- GitLab From b94cd8118c057933127f28e9a3bc79cc92de9714 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:39:28 +0800 Subject: [PATCH 1277/9938] ACPICA: Tables: Update FADT handling ACPICA commit bca0c4cb063ee488c543e6f160fe89679a2338d6 Update a warning message simplify versioning for "table too big" case. Link: https://github.com/acpica/acpica/commit/bca0c4cb Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbfadt.c | 18 +++++++++++------- include/acpi/actbl.h | 4 +++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index a79e4f30b530..f63f3fd0d932 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -385,14 +385,15 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) { /* * Check if the FADT is larger than the largest table that we expect - * (the ACPI 5.0 version). If so, truncate the table, and issue - * a warning. + * (typically the current ACPI specification version). If so, truncate + * the table, and issue a warning. */ if (length > sizeof(struct acpi_table_fadt)) { ACPI_BIOS_WARNING((AE_INFO, - "FADT (revision %u) is longer than ACPI 5.0 version, " + "FADT (revision %u) is longer than %s length, " "truncating length %u to %u", - table->revision, length, + table->revision, ACPI_FADT_CONFORMANCE, + length, (u32)sizeof(struct acpi_table_fadt))); } @@ -646,9 +647,12 @@ static void acpi_tb_convert_fadt(void) if ((address64->address && !length) || (!address64->address && length)) { ACPI_BIOS_WARNING((AE_INFO, - "Optional FADT field %s has zero address or length: " - "0x%8.8X%8.8X/0x%X", - name, + "Optional FADT field %s has valid %s but zero %s: " + "0x%8.8X%8.8X/0x%X", name, + (length ? "Length" : + "Address"), + (length ? "Address" : + "Length"), ACPI_FORMAT_UINT64 (address64->address), length)); diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 0cb1a0036986..c19700e2a2fe 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -223,7 +223,7 @@ struct acpi_table_facs { /******************************************************************************* * * FADT - Fixed ACPI Description Table (Signature "FACP") - * Version 4 + * Version 6 * ******************************************************************************/ @@ -413,4 +413,6 @@ struct acpi_table_desc { #define ACPI_FADT_V5_SIZE (u32) (ACPI_FADT_OFFSET (hypervisor_id)) #define ACPI_FADT_V6_SIZE (u32) (sizeof (struct acpi_table_fadt)) +#define ACPI_FADT_CONFORMANCE "ACPI 6.1 (FADT version 6)" + #endif /* __ACTBL_H__ */ -- GitLab From a88e0ce6beffb5ba1df8930f2f0112024f2a215e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:39:36 +0800 Subject: [PATCH 1278/9938] ACPICA: ACPI 6.1: Add full support for this version of ACPI spec ACPICA commit 5f21bddaa2cec035ca80608803ce2f0858d4f387 Small changes: 1) A couple new predefined names 2) New _HID values 3) New subtable for HEST Link: https://github.com/acpica/acpica/commit/5f21bdda Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acpredef.h | 9 +++++++++ drivers/acpi/acpica/utdecode.c | 30 +++++++++++++++++------------- include/acpi/actbl1.h | 6 ++++-- include/acpi/actypes.h | 3 ++- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 5faeab41e302..4ca426b55509 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -523,6 +523,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0), + {{"_FIT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, /* ACPI 6.0 */ + {{"_FIX", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */ PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0), @@ -1053,6 +1056,12 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER)}}, + {{"_WPC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* ACPI 6.1 */ + + {{"_WPP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* ACPI 6.1 */ + PACKAGE_INFO(0, 0, 0, 0, 0, 0) /* Table terminator */ }; #else diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 6ba65b02550c..efd7988e34cb 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -446,7 +446,7 @@ const char *acpi_ut_get_mutex_name(u32 mutex_id) /* Names for Notify() values, used for debug output */ -static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = { +static const char *acpi_gbl_generic_notify[ACPI_GENERIC_NOTIFY_MAX + 1] = { /* 00 */ "Bus Check", /* 01 */ "Device Check", /* 02 */ "Device Wake", @@ -459,49 +459,53 @@ static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = { /* 09 */ "Device PLD Check", /* 0A */ "Reserved", /* 0B */ "System Locality Update", - /* 0C */ "Shutdown Request", + /* 0C */ "Shutdown Request", + /* Reserved in ACPI 6.0 */ /* 0D */ "System Resource Affinity Update" }; -static const char *acpi_gbl_device_notify[4] = { +static const char *acpi_gbl_device_notify[5] = { /* 80 */ "Status Change", /* 81 */ "Information Change", /* 82 */ "Device-Specific Change", - /* 83 */ "Device-Specific Change" + /* 83 */ "Device-Specific Change", + /* 84 */ "Reserved" }; -static const char *acpi_gbl_processor_notify[4] = { +static const char *acpi_gbl_processor_notify[5] = { /* 80 */ "Performance Capability Change", /* 81 */ "C-State Change", /* 82 */ "Throttling Capability Change", - /* 83 */ "Device-Specific Change" + /* 83 */ "Guaranteed Change", + /* 84 */ "Minimum Excursion" }; -static const char *acpi_gbl_thermal_notify[4] = { +static const char *acpi_gbl_thermal_notify[5] = { /* 80 */ "Thermal Status Change", /* 81 */ "Thermal Trip Point Change", /* 82 */ "Thermal Device List Change", - /* 83 */ "Thermal Relationship Change" + /* 83 */ "Thermal Relationship Change", + /* 84 */ "Reserved" }; const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type) { - /* 00 - 0D are common to all object types */ + /* 00 - 0D are "common to all object types" (from ACPI Spec) */ - if (notify_value <= ACPI_NOTIFY_MAX) { + if (notify_value <= ACPI_GENERIC_NOTIFY_MAX) { return (acpi_gbl_generic_notify[notify_value]); } - /* 0D - 7F are reserved */ + /* 0E - 7F are reserved */ if (notify_value <= ACPI_MAX_SYS_NOTIFY) { return ("Reserved"); } - /* 80 - 83 are per-object-type */ + /* 80 - 84 are per-object-type */ - if (notify_value <= 0x83) { + if (notify_value <= ACPI_SPECIFIC_NOTIFY_MAX) { switch (type) { case ACPI_TYPE_ANY: case ACPI_TYPE_DEVICE: diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 912dff90c4c2..796d6baae3a3 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -236,7 +236,8 @@ enum acpi_einj_actions { ACPI_EINJ_CHECK_BUSY_STATUS = 6, ACPI_EINJ_GET_COMMAND_STATUS = 7, ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS = 8, - ACPI_EINJ_ACTION_RESERVED = 9, /* 9 and greater are reserved */ + ACPI_EINJ_GET_EXECUTE_TIMINGS = 9, + ACPI_EINJ_ACTION_RESERVED = 10, /* 10 and greater are reserved */ ACPI_EINJ_TRIGGER_ERROR = 0xFF /* Except for this value */ }; @@ -348,7 +349,8 @@ enum acpi_erst_actions { ACPI_ERST_GET_ERROR_RANGE = 13, ACPI_ERST_GET_ERROR_LENGTH = 14, ACPI_ERST_GET_ERROR_ATTRIBUTES = 15, - ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */ + ACPI_ERST_EXECUTE_TIMINGS = 16, + ACPI_ERST_ACTION_RESERVED = 17 /* 17 and greater are reserved */ }; /* Values for Instruction field above */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index db46546d3b9d..140886e4973f 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -630,7 +630,8 @@ typedef u64 acpi_integer; #define ACPI_NOTIFY_SHUTDOWN_REQUEST (u8) 0x0C #define ACPI_NOTIFY_AFFINITY_UPDATE (u8) 0x0D -#define ACPI_NOTIFY_MAX 0x0D +#define ACPI_GENERIC_NOTIFY_MAX 0x0D +#define ACPI_SPECIFIC_NOTIFY_MAX 0x84 /* * Types associated with ACPI names and objects. The first group of -- GitLab From 28a9a69bdf36f639df9820592eb2ce2e99002338 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:39:44 +0800 Subject: [PATCH 1279/9938] ACPICA: iASL/Headers: Fix incorrect definition of FPDT table ACPICA commit f30ba83711bcb860f9b17dd36d0bcc5242a4ef91 ACPICA BZ 1249. Link: https://github.com/acpica/acpica/commit/f30ba837 Link: https://bugs.acpica.org/show_bug.cgi?id=1249 Reported-by: Greg Elkin Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl3.h | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index ddf5e66c3b15..f12f4bb1907b 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h @@ -184,7 +184,7 @@ struct acpi_table_fpdt { struct acpi_table_header header; /* Common ACPI table header */ }; -/* FPDT subtable header */ +/* FPDT subtable header (Performance Record Structure) */ struct acpi_fpdt_header { u16 type; @@ -205,19 +205,15 @@ enum acpi_fpdt_type { /* 0: Firmware Basic Boot Performance Record */ -struct acpi_fpdt_boot { +struct acpi_fpdt_boot_pointer { struct acpi_fpdt_header header; u8 reserved[4]; - u64 reset_end; - u64 load_start; - u64 startup_start; - u64 exit_services_entry; - u64 exit_services_exit; + u64 address; }; /* 1: S3 Performance Table Pointer Record */ -struct acpi_fpdt_s3pt_ptr { +struct acpi_fpdt_s3pt_pointer { struct acpi_fpdt_header header; u8 reserved[4]; u64 address; @@ -225,7 +221,7 @@ struct acpi_fpdt_s3pt_ptr { /* * S3PT - S3 Performance Table. This table is pointed to by the - * FPDT S3 Pointer Record above. + * S3 Pointer Record above. */ struct acpi_table_s3pt { u8 signature[4]; /* "S3PT" */ @@ -233,34 +229,43 @@ struct acpi_table_s3pt { }; /* - * S3PT Subtables + * S3PT Subtables (Not part of the actual FPDT) */ -struct acpi_s3pt_header { - u16 type; - u8 length; - u8 revision; -}; -/* Values for Type field above */ +/* Values for Type field in S3PT header */ enum acpi_s3pt_type { ACPI_S3PT_TYPE_RESUME = 0, - ACPI_S3PT_TYPE_SUSPEND = 1 + ACPI_S3PT_TYPE_SUSPEND = 1, + ACPI_FPDT_BOOT_PERFORMANCE = 2 }; struct acpi_s3pt_resume { - struct acpi_s3pt_header header; + struct acpi_fpdt_header header; u32 resume_count; u64 full_resume; u64 average_resume; }; struct acpi_s3pt_suspend { - struct acpi_s3pt_header header; + struct acpi_fpdt_header header; u64 suspend_start; u64 suspend_end; }; +/* + * FPDT Boot Performance Record (Not part of the actual FPDT) + */ +struct acpi_fpdt_boot { + struct acpi_fpdt_header header; + u8 reserved[4]; + u64 reset_end; + u64 load_start; + u64 startup_start; + u64 exit_services_entry; + u64 exit_services_exit; +}; + /******************************************************************************* * * GTDT - Generic Timer Description Table (ACPI 5.1) -- GitLab From 890b090ef5ab6f0a125b8668c49d734442333d3c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:39:51 +0800 Subject: [PATCH 1280/9938] ACPICA: Intepreter: Add object extensions to Concatenate operand ACPICA commit 60d9cfd403a9824199b971597c930f6f563e5c71 Allows all object types to be used with Concatenate. Objects other than Int/Str/Buf are convert to a string that contains the type of the object. Improves the utility of the Printf and Fprintf macros. Adds a new file, exconcat.c Link: https://github.com/acpica/acpica/commit/60d9cfd4 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/Makefile | 1 + drivers/acpi/acpica/exconcat.c | 439 +++++++++++++++++++++++++++++++++ drivers/acpi/acpica/exmisc.c | 290 ---------------------- 3 files changed, 440 insertions(+), 290 deletions(-) create mode 100644 drivers/acpi/acpica/exconcat.c diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index f682374c19f4..188597fface7 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -43,6 +43,7 @@ acpi-y += \ evxfregn.o acpi-y += \ + exconcat.o \ exconfig.o \ exconvrt.o \ excreate.o \ diff --git a/drivers/acpi/acpica/exconcat.c b/drivers/acpi/acpica/exconcat.c new file mode 100644 index 000000000000..553e0146338e --- /dev/null +++ b/drivers/acpi/acpica/exconcat.c @@ -0,0 +1,439 @@ +/****************************************************************************** + * + * Module Name: exconcat - Concatenate-type AML operators + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2016, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acinterp.h" +#include "amlresrc.h" + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exconcat") + +/* Local Prototypes */ +static acpi_status +acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc, + union acpi_operand_object **result_desc); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_concatenate + * + * PARAMETERS: operand0 - First source object + * operand1 - Second source object + * actual_return_desc - Where to place the return object + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion + * rules as necessary. + * NOTE: + * Per the ACPI spec (up to 6.1), Concatenate only supports Integer, + * String, and Buffer objects. However, we support all objects here + * as an extension. This improves the usefulness of both Concatenate + * and the Printf/Fprintf macros. The extension returns a string + * describing the object type for the other objects. + * 02/2016. + * + ******************************************************************************/ + +acpi_status +acpi_ex_do_concatenate(union acpi_operand_object *operand0, + union acpi_operand_object *operand1, + union acpi_operand_object **actual_return_desc, + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *local_operand0 = operand0; + union acpi_operand_object *local_operand1 = operand1; + union acpi_operand_object *temp_operand1 = NULL; + union acpi_operand_object *return_desc; + char *buffer; + acpi_object_type operand0_type; + acpi_object_type operand1_type; + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_do_concatenate); + + /* Operand 0 preprocessing */ + + switch (operand0->common.type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + operand0_type = operand0->common.type; + break; + + default: + + /* For all other types, get the "object type" string */ + + status = + acpi_ex_convert_to_object_type_string(operand0, + &local_operand0); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + operand0_type = ACPI_TYPE_STRING; + break; + } + + /* Operand 1 preprocessing */ + + switch (operand1->common.type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + operand1_type = operand1->common.type; + break; + + default: + + /* For all other types, get the "object type" string */ + + status = + acpi_ex_convert_to_object_type_string(operand1, + &local_operand1); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + operand1_type = ACPI_TYPE_STRING; + break; + } + + /* + * Convert the second operand if necessary. The first operand (0) + * determines the type of the second operand (1) (See the Data Types + * section of the ACPI specification). Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (operand0_type) { + case ACPI_TYPE_INTEGER: + + status = + acpi_ex_convert_to_integer(local_operand1, &temp_operand1, + 16); + break; + + case ACPI_TYPE_BUFFER: + + status = + acpi_ex_convert_to_buffer(local_operand1, &temp_operand1); + break; + + case ACPI_TYPE_STRING: + + switch (operand1_type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Other types have already been converted to string */ + + status = + acpi_ex_convert_to_string(local_operand1, + &temp_operand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + default: + + status = AE_OK; + break; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", + operand0->common.type)); + status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Take care with any newly created operand objects */ + + if ((local_operand1 != operand1) && (local_operand1 != temp_operand1)) { + acpi_ut_remove_reference(local_operand1); + } + + local_operand1 = temp_operand1; + + /* + * Both operands are now known to be the same object type + * (Both are Integer, String, or Buffer), and we can now perform + * the concatenation. + * + * There are three cases to handle, as per the ACPI spec: + * + * 1) Two Integers concatenated to produce a new Buffer + * 2) Two Strings concatenated to produce a new String + * 3) Two Buffers concatenated to produce a new Buffer + */ + switch (operand0_type) { + case ACPI_TYPE_INTEGER: + + /* Result of two Integers is a Buffer */ + /* Need enough buffer space for two integers */ + + return_desc = acpi_ut_create_buffer_object((acpi_size) + ACPI_MUL_2 + (acpi_gbl_integer_byte_width)); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + buffer = (char *)return_desc->buffer.pointer; + + /* Copy the first integer, LSB first */ + + memcpy(buffer, &operand0->integer.value, + acpi_gbl_integer_byte_width); + + /* Copy the second integer (LSB first) after the first */ + + memcpy(buffer + acpi_gbl_integer_byte_width, + &local_operand1->integer.value, + acpi_gbl_integer_byte_width); + break; + + case ACPI_TYPE_STRING: + + /* Result of two Strings is a String */ + + return_desc = acpi_ut_create_string_object(((acpi_size) + local_operand0-> + string.length + + local_operand1-> + string.length)); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + buffer = return_desc->string.pointer; + + /* Concatenate the strings */ + + strcpy(buffer, local_operand0->string.pointer); + strcat(buffer, local_operand1->string.pointer); + break; + + case ACPI_TYPE_BUFFER: + + /* Result of two Buffers is a Buffer */ + + return_desc = acpi_ut_create_buffer_object(((acpi_size) + operand0->buffer. + length + + local_operand1-> + buffer.length)); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + buffer = (char *)return_desc->buffer.pointer; + + /* Concatenate the buffers */ + + memcpy(buffer, operand0->buffer.pointer, + operand0->buffer.length); + memcpy(buffer + operand0->buffer.length, + local_operand1->buffer.pointer, + local_operand1->buffer.length); + break; + + default: + + /* Invalid object type, should not happen here */ + + ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", + operand0->common.type)); + status = AE_AML_INTERNAL; + goto cleanup; + } + + *actual_return_desc = return_desc; + +cleanup: + if (local_operand0 != operand0) { + acpi_ut_remove_reference(local_operand0); + } + + if (local_operand1 != operand1) { + acpi_ut_remove_reference(local_operand1); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_convert_to_object_type_string + * + * PARAMETERS: obj_desc - Object to be converted + * return_desc - Where to place the return object + * + * RETURN: Status + * + * DESCRIPTION: Convert an object of arbitrary type to a string object that + * contains the namestring for the object. Used for the + * concatenate operator. + * + ******************************************************************************/ + +static acpi_status +acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc, + union acpi_operand_object **result_desc) +{ + union acpi_operand_object *return_desc; + const char *type_string; + + type_string = acpi_ut_get_type_name(obj_desc->common.type); + + return_desc = acpi_ut_create_string_object(((acpi_size) strlen(type_string) + 9)); /* 9 For "[ Object]" */ + if (!return_desc) { + return (AE_NO_MEMORY); + } + + strcpy(return_desc->string.pointer, "["); + strcat(return_desc->string.pointer, type_string); + strcat(return_desc->string.pointer, " Object]"); + + *result_desc = return_desc; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_concat_template + * + * PARAMETERS: operand0 - First source object + * operand1 - Second source object + * actual_return_desc - Where to place the return object + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two resource templates + * + ******************************************************************************/ + +acpi_status +acpi_ex_concat_template(union acpi_operand_object *operand0, + union acpi_operand_object *operand1, + union acpi_operand_object **actual_return_desc, + struct acpi_walk_state * walk_state) +{ + acpi_status status; + union acpi_operand_object *return_desc; + u8 *new_buf; + u8 *end_tag; + acpi_size length0; + acpi_size length1; + acpi_size new_length; + + ACPI_FUNCTION_TRACE(ex_concat_template); + + /* + * Find the end_tag descriptor in each resource template. + * Note1: returned pointers point TO the end_tag, not past it. + * Note2: zero-length buffers are allowed; treated like one end_tag + */ + + /* Get the length of the first resource template */ + + status = acpi_ut_get_resource_end_tag(operand0, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer); + + /* Get the length of the second resource template */ + + status = acpi_ut_get_resource_end_tag(operand1, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer); + + /* Combine both lengths, minimum size will be 2 for end_tag */ + + new_length = length0 + length1 + sizeof(struct aml_resource_end_tag); + + /* Create a new buffer object for the result (with one end_tag) */ + + return_desc = acpi_ut_create_buffer_object(new_length); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the templates to the new buffer, 0 first, then 1 follows. One + * end_tag descriptor is copied from Operand1. + */ + new_buf = return_desc->buffer.pointer; + memcpy(new_buf, operand0->buffer.pointer, length0); + memcpy(new_buf + length0, operand1->buffer.pointer, length1); + + /* Insert end_tag and set the checksum to zero, means "ignore checksum" */ + + new_buf[new_length - 1] = 0; + new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; + + /* Return the completed resource template */ + + *actual_return_desc = return_desc; + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index db30ae43ddd8..4f7e667624b3 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -45,7 +45,6 @@ #include "accommon.h" #include "acinterp.h" #include "amlcode.h" -#include "amlresrc.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exmisc") @@ -138,295 +137,6 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_OK); } -/******************************************************************************* - * - * FUNCTION: acpi_ex_concat_template - * - * PARAMETERS: operand0 - First source object - * operand1 - Second source object - * actual_return_desc - Where to place the return object - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Concatenate two resource templates - * - ******************************************************************************/ - -acpi_status -acpi_ex_concat_template(union acpi_operand_object *operand0, - union acpi_operand_object *operand1, - union acpi_operand_object **actual_return_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object *return_desc; - u8 *new_buf; - u8 *end_tag; - acpi_size length0; - acpi_size length1; - acpi_size new_length; - - ACPI_FUNCTION_TRACE(ex_concat_template); - - /* - * Find the end_tag descriptor in each resource template. - * Note1: returned pointers point TO the end_tag, not past it. - * Note2: zero-length buffers are allowed; treated like one end_tag - */ - - /* Get the length of the first resource template */ - - status = acpi_ut_get_resource_end_tag(operand0, &end_tag); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer); - - /* Get the length of the second resource template */ - - status = acpi_ut_get_resource_end_tag(operand1, &end_tag); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer); - - /* Combine both lengths, minimum size will be 2 for end_tag */ - - new_length = length0 + length1 + sizeof(struct aml_resource_end_tag); - - /* Create a new buffer object for the result (with one end_tag) */ - - return_desc = acpi_ut_create_buffer_object(new_length); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Copy the templates to the new buffer, 0 first, then 1 follows. One - * end_tag descriptor is copied from Operand1. - */ - new_buf = return_desc->buffer.pointer; - memcpy(new_buf, operand0->buffer.pointer, length0); - memcpy(new_buf + length0, operand1->buffer.pointer, length1); - - /* Insert end_tag and set the checksum to zero, means "ignore checksum" */ - - new_buf[new_length - 1] = 0; - new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; - - /* Return the completed resource template */ - - *actual_return_desc = return_desc; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_do_concatenate - * - * PARAMETERS: operand0 - First source object - * operand1 - Second source object - * actual_return_desc - Where to place the return object - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. - * - ******************************************************************************/ - -acpi_status -acpi_ex_do_concatenate(union acpi_operand_object *operand0, - union acpi_operand_object *operand1, - union acpi_operand_object **actual_return_desc, - struct acpi_walk_state *walk_state) -{ - union acpi_operand_object *local_operand1 = operand1; - union acpi_operand_object *return_desc; - char *new_buf; - const char *type_string; - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_do_concatenate); - - /* - * Convert the second operand if necessary. The first operand - * determines the type of the second operand, (See the Data Types - * section of the ACPI specification.) Both object types are - * guaranteed to be either Integer/String/Buffer by the operand - * resolution mechanism. - */ - switch (operand0->common.type) { - case ACPI_TYPE_INTEGER: - - status = - acpi_ex_convert_to_integer(operand1, &local_operand1, 16); - break; - - case ACPI_TYPE_STRING: - /* - * Per the ACPI spec, Concatenate only supports int/str/buf. - * However, we support all objects here as an extension. - * This improves the usefulness of the Printf() macro. - * 12/2015. - */ - switch (operand1->common.type) { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - status = - acpi_ex_convert_to_string(operand1, &local_operand1, - ACPI_IMPLICIT_CONVERT_HEX); - break; - - default: - /* - * Just emit a string containing the object type. - */ - type_string = - acpi_ut_get_type_name(operand1->common.type); - - local_operand1 = acpi_ut_create_string_object(((acpi_size) strlen(type_string) + 9)); /* 9 For "[Object]" */ - if (!local_operand1) { - status = AE_NO_MEMORY; - goto cleanup; - } - - strcpy(local_operand1->string.pointer, "["); - strcat(local_operand1->string.pointer, type_string); - strcat(local_operand1->string.pointer, " Object]"); - status = AE_OK; - break; - } - break; - - case ACPI_TYPE_BUFFER: - - status = acpi_ex_convert_to_buffer(operand1, &local_operand1); - break; - - default: - - ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", - operand0->common.type)); - status = AE_AML_INTERNAL; - } - - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * Both operands are now known to be the same object type - * (Both are Integer, String, or Buffer), and we can now perform the - * concatenation. - */ - - /* - * There are three cases to handle: - * - * 1) Two Integers concatenated to produce a new Buffer - * 2) Two Strings concatenated to produce a new String - * 3) Two Buffers concatenated to produce a new Buffer - */ - switch (operand0->common.type) { - case ACPI_TYPE_INTEGER: - - /* Result of two Integers is a Buffer */ - /* Need enough buffer space for two integers */ - - return_desc = acpi_ut_create_buffer_object((acpi_size) - ACPI_MUL_2 - (acpi_gbl_integer_byte_width)); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - new_buf = (char *)return_desc->buffer.pointer; - - /* Copy the first integer, LSB first */ - - memcpy(new_buf, &operand0->integer.value, - acpi_gbl_integer_byte_width); - - /* Copy the second integer (LSB first) after the first */ - - memcpy(new_buf + acpi_gbl_integer_byte_width, - &local_operand1->integer.value, - acpi_gbl_integer_byte_width); - break; - - case ACPI_TYPE_STRING: - - /* Result of two Strings is a String */ - - return_desc = acpi_ut_create_string_object(((acpi_size) - operand0->string. - length + - local_operand1-> - string.length)); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - new_buf = return_desc->string.pointer; - - /* Concatenate the strings */ - - strcpy(new_buf, operand0->string.pointer); - strcat(new_buf, local_operand1->string.pointer); - break; - - case ACPI_TYPE_BUFFER: - - /* Result of two Buffers is a Buffer */ - - return_desc = acpi_ut_create_buffer_object(((acpi_size) - operand0->buffer. - length + - local_operand1-> - buffer.length)); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - new_buf = (char *)return_desc->buffer.pointer; - - /* Concatenate the buffers */ - - memcpy(new_buf, operand0->buffer.pointer, - operand0->buffer.length); - memcpy(new_buf + operand0->buffer.length, - local_operand1->buffer.pointer, - local_operand1->buffer.length); - break; - - default: - - /* Invalid object type, should not happen here */ - - ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", - operand0->common.type)); - status = AE_AML_INTERNAL; - goto cleanup; - } - - *actual_return_desc = return_desc; - -cleanup: - if (local_operand1 != operand1) { - acpi_ut_remove_reference(local_operand1); - } - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_ex_do_math_op -- GitLab From d8aa069a35b40150abb00658be91dcb284648a04 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:39:58 +0800 Subject: [PATCH 1281/9938] ACPICA: Interpreter: Update some function headers, no functional change ACPICA commit e068948f49eb61a78c211028976a174604c5644a Fix some issues in the exutils.c file. Link: https://github.com/acpica/acpica/commit/e068948f Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/exutils.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 4d44bc1cb2ca..425f13372e68 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -301,8 +301,8 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base) * * FUNCTION: acpi_ex_eisa_id_to_string * - * PARAMETERS: compressed_id - EISAID to be converted - * out_string - Where to put the converted string (8 bytes) + * PARAMETERS: out_string - Where to put the converted string (8 bytes) + * compressed_id - EISAID to be converted * * RETURN: None * @@ -354,7 +354,7 @@ void acpi_ex_eisa_id_to_string(char *out_string, u64 compressed_id) * possible 64-bit integer. * value - Value to be converted * - * RETURN: None, string + * RETURN: Converted string in out_string * * DESCRIPTION: Convert a 64-bit integer to decimal string representation. * Assumes string buffer is large enough to hold the string. The @@ -384,9 +384,9 @@ void acpi_ex_integer_to_string(char *out_string, u64 value) * FUNCTION: acpi_ex_pci_cls_to_string * * PARAMETERS: out_string - Where to put the converted string (7 bytes) - * PARAMETERS: class_code - PCI class code to be converted (3 bytes) + * class_code - PCI class code to be converted (3 bytes) * - * RETURN: None + * RETURN: Converted string in out_string * * DESCRIPTION: Convert 3-bytes PCI class code to string representation. * Return buffer must be large enough to hold the string. The @@ -417,7 +417,7 @@ void acpi_ex_pci_cls_to_string(char *out_string, u8 class_code[3]) * * PARAMETERS: space_id - ID to be validated * - * RETURN: TRUE if valid/supported ID. + * RETURN: TRUE if space_id is a valid/supported ID. * * DESCRIPTION: Validate an operation region space_ID. * -- GitLab From fe0f8765dfd224775db1df9b878bfeb6121cbe6c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:40:05 +0800 Subject: [PATCH 1282/9938] ACPICA: iASL: Cleanup/optimization for ToPLD macro support ACPICA commit 0e6125401cf38427d5376f4bafbfb3d5a40f8467 Use local variables for access to string/value Op fields. Move duplicate PLD string tables to a single common table. Link: https://github.com/acpica/acpica/commit/0e612540 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 9 +++++++ drivers/acpi/acpica/utglobal.c | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 51b073b68f16..54b42a57118e 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -361,6 +361,15 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects); #endif /* ACPI_DEBUGGER */ +#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER) + +ACPI_GLOBAL(const char, *acpi_gbl_pld_panel_list[]); +ACPI_GLOBAL(const char, *acpi_gbl_pld_vertical_position_list[]); +ACPI_GLOBAL(const char, *acpi_gbl_pld_horizontal_position_list[]); +ACPI_GLOBAL(const char, *acpi_gbl_pld_shape_list[]); + +#endif + /***************************************************************************** * * Application globals diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 48fffcfe9911..d45899c17d4e 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -221,6 +221,49 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = }; #endif /* !ACPI_REDUCED_HARDWARE */ +#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER) + +/* to_pld macro: compile/disassemble strings */ + +const char *acpi_gbl_pld_panel_list[] = { + "TOP", + "BOTTOM", + "LEFT", + "RIGHT", + "FRONT", + "BACK", + "UNKNOWN", + NULL +}; + +const char *acpi_gbl_pld_vertical_position_list[] = { + "UPPER", + "CENTER", + "LOWER", + NULL +}; + +const char *acpi_gbl_pld_horizontal_position_list[] = { + "LEFT", + "CENTER", + "RIGHT", + NULL +}; + +const char *acpi_gbl_pld_shape_list[] = { + "ROUND", + "OVAL", + "SQUARE", + "VERTICALRECTANGLE", + "HORIZONTALRECTANGLE", + "VERTICALTRAPEZOID", + "HORIZONTALTRAPEZOID", + "UNKNOWN", + "CHAMFERED", + NULL +}; +#endif + /* Public globals */ ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) -- GitLab From 2156510f300f9ac70a024994acb5235ebd4ee087 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:40:12 +0800 Subject: [PATCH 1283/9938] ACPICA: Cleanup some invocation indentations, no functional change ACPICA commit 9ed98dc36645aaeba11967722951156650d94f47 For consistency, cleanup function invocations. Link: https://github.com/acpica/acpica/commit/9ed98dc3 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsprepkg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index 9047f2808d5b..fde5a09819e0 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -179,6 +179,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, if (ACPI_FAILURE(status)) { return (status); } + elements++; } break; @@ -225,6 +226,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, return (status); } } + elements++; } break; @@ -569,11 +571,13 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, if (sub_package->package.count < expected_count) { goto package_too_small; } + if (sub_package->package.count < package->ret_info.count1) { expected_count = package->ret_info.count1; goto package_too_small; } + if (expected_count == 0) { /* * Either the num_entries element was originally zero or it was @@ -661,6 +665,7 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info, if (ACPI_FAILURE(status)) { return (status); } + this_element++; } @@ -671,6 +676,7 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info, if (ACPI_FAILURE(status)) { return (status); } + this_element++; } -- GitLab From 95df7b5e4c9c7a6b1e75d7bbc16ac19ee2784379 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:40:19 +0800 Subject: [PATCH 1284/9938] ACPICA: Headers: Update generation of the ACPICA library ACPICA commit 0af0f9092dcc3db6c05875eae68965fda333ad7f For windows only, ensure that debug output is disabled for the "release" (non-debug) case. Link: https://github.com/acpica/acpica/commit/0af0f909 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/platform/acenv.h | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 7c0595bde132..72f85b4bdc44 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -66,17 +66,28 @@ * *****************************************************************************/ +/* Common application configuration. All single threaded except for acpi_exec. */ + +#if (defined ACPI_ASL_COMPILER) || \ + (defined ACPI_BIN_APP) || \ + (defined ACPI_DUMP_APP) || \ + (defined ACPI_HELP_APP) || \ + (defined ACPI_NAMES_APP) || \ + (defined ACPI_SRC_APP) || \ + (defined ACPI_XTRACT_APP) || \ + (defined ACPI_EXAMPLE_APP) +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#endif + /* iASL configuration */ #ifdef ACPI_ASL_COMPILER -#define ACPI_APPLICATION #define ACPI_DEBUG_OUTPUT #define ACPI_CONSTANT_EVAL_ONLY #define ACPI_LARGE_NAMESPACE_NODE #define ACPI_DATA_TABLE_DISASSEMBLY -#define ACPI_SINGLE_THREADED #define ACPI_32BIT_PHYSICAL_ADDRESS - #define ACPI_DISASSEMBLER 1 #endif @@ -89,21 +100,6 @@ #define ACPI_DBG_TRACK_ALLOCATIONS #endif -/* - * acpi_bin/acpi_dump/acpi_help/acpi_names/acpi_src/acpi_xtract/Example - * configuration. All single threaded. - */ -#if (defined ACPI_BIN_APP) || \ - (defined ACPI_DUMP_APP) || \ - (defined ACPI_HELP_APP) || \ - (defined ACPI_NAMES_APP) || \ - (defined ACPI_SRC_APP) || \ - (defined ACPI_XTRACT_APP) || \ - (defined ACPI_EXAMPLE_APP) -#define ACPI_APPLICATION -#define ACPI_SINGLE_THREADED -#endif - /* acpi_help configuration. Error messages disabled. */ #ifdef ACPI_HELP_APP @@ -138,11 +134,16 @@ #define ACPI_REDUCED_HARDWARE 1 #endif -/* Linkable ACPICA library */ +/* Linkable ACPICA library. Two versions, one with full debug. */ #ifdef ACPI_LIBRARY #define ACPI_USE_LOCAL_CACHE -#define ACPI_FULL_DEBUG +#define ACPI_DEBUGGER 1 +#define ACPI_DISASSEMBLER 1 + +#ifdef _DEBUG +#define ACPI_DEBUG_OUTPUT +#endif #endif /* Common for all ACPICA applications */ -- GitLab From 53c78d75d8a4615e5c2f1d9fe94f25e049f0e61b Mon Sep 17 00:00:00 2001 From: Will Miles Date: Thu, 24 Mar 2016 09:40:26 +0800 Subject: [PATCH 1285/9938] ACPICA: Add support for QNX 6.6 platform ACPICA commit 37a1dec2391272251e59948c16c60713183ae78f Link: https://github.com/acpica/acpica/commit/37a1dec2 Signed-off-by: Will Miles Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/platform/acenv.h | 3 +++ tools/power/acpi/os_specific/service_layers/osunixmap.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 72f85b4bdc44..86b5a8447606 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -219,6 +219,9 @@ #elif defined(__HAIKU__) #include "achaiku.h" +#elif defined(__QNX__) +#include "acqnx.h" + #else /* Unknown environment */ diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c index 3818fd07e50f..cbfbce18783d 100644 --- a/tools/power/acpi/os_specific/service_layers/osunixmap.c +++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c @@ -54,7 +54,7 @@ ACPI_MODULE_NAME("osunixmap") #ifndef O_BINARY #define O_BINARY 0 #endif -#if defined(_dragon_fly) || defined(_free_BSD) +#if defined(_dragon_fly) || defined(_free_BSD) || defined(_QNX) #define MMAP_FLAGS MAP_SHARED #else #define MMAP_FLAGS MAP_PRIVATE -- GitLab From 3a05be7575a46cf3b16abb77e1072afa13307a1b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:40:33 +0800 Subject: [PATCH 1286/9938] ACPICA: Utilities: Update for strtoul64 merger ACPICA commit 795e136d2ac77c1c8b091fba019b5fe36a44a323 Fixes a problem with the merger of the two internal versions of this function. Make the maximum integer width (32-bit or 64-bit) a parameter to the function so that it no longer exclusively uses the integer width specified in the DSDT/SSDT. ACPICA BZ 1260 Link: https://github.com/acpica/acpica/commit/795e136d Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acutils.h | 9 +++- drivers/acpi/acpica/dbconvert.c | 4 +- drivers/acpi/acpica/exconvrt.c | 4 +- drivers/acpi/acpica/nsconvert.c | 3 +- drivers/acpi/acpica/utnonansi.c | 67 +++++++++++++----------- tools/power/acpi/tools/acpidump/apdump.c | 3 +- tools/power/acpi/tools/acpidump/apmain.c | 3 +- 7 files changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index e43ab6f2ad7e..7422ff7bfb6d 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -175,7 +175,14 @@ void acpi_ut_strlwr(char *src_string); int acpi_ut_stricmp(char *string1, char *string2); -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); +acpi_status +acpi_ut_strtoul64(char *string, + u32 base, u32 max_integer_byte_width, u64 *ret_integer); + +/* Values for max_integer_byte_width above */ + +#define ACPI_MAX32_BYTE_WIDTH 4 +#define ACPI_MAX64_BYTE_WIDTH 8 /* * utglobal - Global data structures and procedures diff --git a/drivers/acpi/acpica/dbconvert.c b/drivers/acpi/acpica/dbconvert.c index 68f4e0f4b095..c79c5fb23fb6 100644 --- a/drivers/acpi/acpica/dbconvert.c +++ b/drivers/acpi/acpica/dbconvert.c @@ -277,7 +277,9 @@ acpi_db_convert_to_object(acpi_object_type type, default: object->type = ACPI_TYPE_INTEGER; - status = acpi_ut_strtoul64(string, 16, &object->integer.value); + status = + acpi_ut_strtoul64(string, 16, acpi_gbl_integer_byte_width, + &object->integer.value); break; } diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index 0b9f2c13b98a..d0d16daa7ed5 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -124,7 +124,9 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, * of ACPI 3.0) is that the to_integer() operator allows both decimal * and hexadecimal strings (hex prefixed with "0x"). */ - status = acpi_ut_strtoul64((char *)pointer, flags, &result); + status = acpi_ut_strtoul64((char *)pointer, flags, + acpi_gbl_integer_byte_width, + &result); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c index 878e8fb6a64c..256f56c583d6 100644 --- a/drivers/acpi/acpica/nsconvert.c +++ b/drivers/acpi/acpica/nsconvert.c @@ -79,7 +79,8 @@ acpi_ns_convert_to_integer(union acpi_operand_object *original_object, /* String-to-Integer conversion */ status = acpi_ut_strtoul64(original_object->string.pointer, - ACPI_ANY_BASE, &value); + ACPI_ANY_BASE, + acpi_gbl_integer_byte_width, &value); if (ACPI_FAILURE(status)) { return (status); } diff --git a/drivers/acpi/acpica/utnonansi.c b/drivers/acpi/acpica/utnonansi.c index d5c3adf19bd0..3465fe2c5a5c 100644 --- a/drivers/acpi/acpica/utnonansi.c +++ b/drivers/acpi/acpica/utnonansi.c @@ -205,37 +205,41 @@ acpi_ut_safe_strncat(char *dest, * * FUNCTION: acpi_ut_strtoul64 * - * PARAMETERS: string - Null terminated string - * base - Radix of the string: 16 or ACPI_ANY_BASE; - * ACPI_ANY_BASE means 'in behalf of to_integer' - * ret_integer - Where the converted integer is returned + * PARAMETERS: string - Null terminated string + * base - Radix of the string: 16 or 10 or + * ACPI_ANY_BASE + * max_integer_byte_width - Maximum allowable integer,in bytes: + * 4 or 8 (32 or 64 bits) + * ret_integer - Where the converted integer is + * returned * * RETURN: Status and Converted value * * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the current mode - * of the interpreter. + * 32-bit or 64-bit conversion, depending on the input integer + * size (often the current mode of the interpreter). * - * NOTES: acpi_gbl_integer_byte_width should be set to the proper width. + * NOTES: Negative numbers are not supported, as they are not supported + * by ACPI. + * + * acpi_gbl_integer_byte_width should be set to the proper width. * For the core ACPICA code, this width depends on the DSDT - * version. For iASL, the default byte width is always 8. + * version. For iASL, the default byte width is always 8 for the + * parser, but error checking is performed later to flag cases + * where a 64-bit constant is defined in a 32-bit DSDT/SSDT. * * Does not support Octal strings, not needed at this time. * - * There is an earlier version of the function after this one, - * below. It is slightly different than this one, and the two - * may eventually may need to be merged. (01/2016). - * ******************************************************************************/ -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) +acpi_status +acpi_ut_strtoul64(char *string, + u32 base, u32 max_integer_byte_width, u64 *ret_integer) { u32 this_digit = 0; u64 return_value = 0; u64 quotient; u64 dividend; - u32 to_integer_op = (base == ACPI_ANY_BASE); - u32 mode32 = (acpi_gbl_integer_byte_width == 4); u8 valid_digits = 0; u8 sign_of0x = 0; u8 term = 0; @@ -244,6 +248,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) switch (base) { case ACPI_ANY_BASE: + case 10: case 16: break; @@ -265,9 +270,9 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) string++; } - if (to_integer_op) { + if (base == ACPI_ANY_BASE) { /* - * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * Base equal to ACPI_ANY_BASE means 'Either decimal or hex'. * We need to determine if it is decimal or hexadecimal. */ if ((*string == '0') && (tolower((int)*(string + 1)) == 'x')) { @@ -284,7 +289,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) /* Any string left? Check that '0x' is not followed by white space. */ if (!(*string) || isspace((int)*string) || *string == '\t') { - if (to_integer_op) { + if (base == ACPI_ANY_BASE) { goto error_exit; } else { goto all_done; @@ -292,10 +297,11 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) } /* - * Perform a 32-bit or 64-bit conversion, depending upon the current - * execution mode of the interpreter + * Perform a 32-bit or 64-bit conversion, depending upon the input + * byte width */ - dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + dividend = (max_integer_byte_width <= ACPI_MAX32_BYTE_WIDTH) ? + ACPI_UINT32_MAX : ACPI_UINT64_MAX; /* Main loop: convert the string to a 32- or 64-bit integer */ @@ -323,7 +329,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) } if (term) { - if (to_integer_op) { + if (base == ACPI_ANY_BASE) { goto error_exit; } else { break; @@ -338,12 +344,13 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) valid_digits++; - if (sign_of0x - && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { + if (sign_of0x && ((valid_digits > 16) || + ((valid_digits > 8) + && (max_integer_byte_width <= + ACPI_MAX32_BYTE_WIDTH)))) { /* * This is to_integer operation case. - * No any restrictions for string-to-integer conversion, + * No restrictions for string-to-integer conversion, * see ACPI spec. */ goto error_exit; @@ -355,7 +362,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) "ient, NULL); if (return_value > quotient) { - if (to_integer_op) { + if (base == ACPI_ANY_BASE) { goto error_exit; } else { break; @@ -378,7 +385,8 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) return_ACPI_STATUS(AE_OK); error_exit: - /* Base was set/validated above */ + + /* Base was set/validated above (10 or 16) */ if (base == 10) { return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); @@ -388,8 +396,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) } #ifdef _OBSOLETE_FUNCTIONS -/* TBD: use version in ACPICA main code base? */ -/* DONE: 01/2016 */ +/* Removed: 01/2016 */ /******************************************************************************* * diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c index da44458d3b6c..9c2db0eb467f 100644 --- a/tools/power/acpi/tools/acpidump/apdump.c +++ b/tools/power/acpi/tools/acpidump/apdump.c @@ -286,7 +286,8 @@ int ap_dump_table_by_address(char *ascii_address) /* Convert argument to an integer physical address */ - status = acpi_ut_strtoul64(ascii_address, 0, &long_address); + status = acpi_ut_strtoul64(ascii_address, ACPI_ANY_BASE, + ACPI_MAX64_BYTE_WIDTH, &long_address); if (ACPI_FAILURE(status)) { acpi_log_error("%s: Could not convert to a physical address\n", ascii_address); diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c index c3c09152fac6..7692e6b887e1 100644 --- a/tools/power/acpi/tools/acpidump/apmain.c +++ b/tools/power/acpi/tools/acpidump/apmain.c @@ -209,7 +209,8 @@ static int ap_do_options(int argc, char **argv) case 'r': /* Dump tables from specified RSDP */ status = - acpi_ut_strtoul64(acpi_gbl_optarg, 0, + acpi_ut_strtoul64(acpi_gbl_optarg, ACPI_ANY_BASE, + ACPI_MAX64_BYTE_WIDTH, &gbl_rsdp_base); if (ACPI_FAILURE(status)) { acpi_log_error -- GitLab From 0dfaaa3d51df011c16279bb010bff90f45b6d62c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:40:40 +0800 Subject: [PATCH 1287/9938] ACPICA: All: const keyword changes across the ACPICA source ACPICA commit a240cbb93647bddf525b3daf6e9d31b8b9bca34e Integrated most changes proposed by net_BSD. >From joerg@net_BSD.org (Joerg Sonnenberger) ACPICA BZ 732. Link: https://github.com/acpica/acpica/commit/a240cbb9 Link: https://bugs.acpica.org/show_bug.cgi?id=732 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 4 +-- drivers/acpi/acpica/acglobal.h | 2 ++ drivers/acpi/acpica/acinterp.h | 2 +- drivers/acpi/acpica/acnamesp.h | 5 ++-- drivers/acpi/acpica/acparser.h | 2 +- drivers/acpi/acpica/acresrc.h | 4 +-- drivers/acpi/acpica/acstruct.h | 2 +- drivers/acpi/acpica/acutils.h | 14 ++++++---- drivers/acpi/acpica/dbinput.c | 13 +++++---- drivers/acpi/acpica/dbutils.c | 9 +++--- drivers/acpi/acpica/evregion.c | 3 +- drivers/acpi/acpica/exdump.c | 15 +++++----- drivers/acpi/acpica/hwxface.c | 4 +-- drivers/acpi/acpica/nsaccess.c | 7 +++-- drivers/acpi/acpica/nsdump.c | 9 ++++-- drivers/acpi/acpica/psopinfo.c | 2 +- drivers/acpi/acpica/rsdump.c | 50 ++++++++++++++-------------------- drivers/acpi/acpica/rsutils.c | 2 +- drivers/acpi/acpica/tbfadt.c | 8 +++--- drivers/acpi/acpica/utdebug.c | 47 ++++++++++++++++---------------- drivers/acpi/acpica/uteval.c | 4 +-- drivers/acpi/acpica/utglobal.c | 5 ++++ drivers/acpi/acpica/utmisc.c | 2 +- drivers/acpi/acpica/utprint.c | 5 ---- drivers/acpi/acpica/uttrack.c | 2 +- include/acpi/actypes.h | 4 +-- 26 files changed, 113 insertions(+), 113 deletions(-) diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 993af9eb007a..9e2e080ac9af 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -53,7 +53,7 @@ #define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */ struct acpi_db_command_info { - char *name; /* Command Name */ + const char *name; /* Command Name */ u8 min_args; /* Minimum arguments required */ }; @@ -64,7 +64,7 @@ struct acpi_db_command_help { }; struct acpi_db_argument_info { - char *name; /* Argument Name */ + const char *name; /* Argument Name */ }; struct acpi_db_execute_walk { diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 54b42a57118e..fded776236e2 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -187,6 +187,8 @@ extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS]; extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; +extern const char acpi_gbl_lower_hex_digits[]; +extern const char acpi_gbl_upper_hex_digits[]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; #ifdef ACPI_DBG_TRACK_ALLOCATIONS diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index bae1a35c345f..8b09d28fe5a8 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -67,7 +67,7 @@ typedef const struct acpi_exdump_info { u8 opcode; u8 offset; - char *name; + const char *name; } acpi_exdump_info; diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 022d69cb345a..f33a4ba8e0cb 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -206,9 +206,10 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth); void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level); void -acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component); +acpi_ns_dump_pathname(acpi_handle handle, + const char *msg, u32 level, u32 component); -void acpi_ns_print_pathname(u32 num_segments, char *pathname); +void acpi_ns_print_pathname(u32 num_segments, const char *pathname); acpi_status acpi_ns_dump_one_object(acpi_handle obj_handle, diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index 7da639d62416..fc305775c3d7 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -139,7 +139,7 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, */ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode); -char *acpi_ps_get_opcode_name(u16 opcode); +const char *acpi_ps_get_opcode_name(u16 opcode); u8 acpi_ps_get_argument_count(u32 op_type); diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index 5dd58beafa5c..83e9a296c6ee 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -124,7 +124,7 @@ typedef enum { typedef const struct acpi_rsdump_info { u8 opcode; u8 offset; - char *name; + const char *name; const char **pointer; } acpi_rsdump_info; @@ -209,7 +209,7 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, acpi_status acpi_rs_get_method_data(acpi_handle handle, - char *path, struct acpi_buffer *ret_buffer); + const char *path, struct acpi_buffer *ret_buffer); acpi_status acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index b3b386e0b119..6235642e31d3 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -184,7 +184,7 @@ struct acpi_evaluate_info { /* The first 3 elements are passed by the caller to acpi_ns_evaluate */ struct acpi_namespace_node *prefix_node; /* Input: starting node */ - char *relative_pathname; /* Input: path relative to prefix_node */ + const char *relative_pathname; /* Input: path relative to prefix_node */ union acpi_operand_object **parameters; /* Input: argument list */ struct acpi_namespace_node *node; /* Resolved node (prefix_node:relative_pathname) */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 7422ff7bfb6d..4ff971c4c979 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -273,7 +273,8 @@ acpi_ut_trace(u32 line_number, void acpi_ut_trace_ptr(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, void *pointer); + const char *module_name, + u32 component_id, const void *pointer); void acpi_ut_trace_u32(u32 line_number, @@ -283,7 +284,8 @@ acpi_ut_trace_u32(u32 line_number, void acpi_ut_trace_str(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, char *string); + const char *module_name, + u32 component_id, const char *string); void acpi_ut_exit(u32 line_number, @@ -342,12 +344,12 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list); */ acpi_status acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, - char *path, + const char *path, u32 expected_return_btypes, union acpi_operand_object **return_desc); acpi_status -acpi_ut_evaluate_numeric_object(char *object_name, +acpi_ut_evaluate_numeric_object(const char *object_name, struct acpi_namespace_node *device_node, u64 *value); @@ -533,7 +535,7 @@ void acpi_ut_set_integer_width(u8 revision); void acpi_ut_display_init_pathname(u8 type, struct acpi_namespace_node *obj_handle, - char *path); + const char *path); #endif /* @@ -635,7 +637,7 @@ void acpi_ut_dump_allocation_info(void); void acpi_ut_dump_allocations(u32 component, const char *module); acpi_status -acpi_ut_create_list(char *list_name, +acpi_ut_create_list(const char *list_name, u16 object_size, struct acpi_memory_list **return_cache); #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c index 417c02a89915..f53cb30e0a09 100644 --- a/drivers/acpi/acpica/dbinput.c +++ b/drivers/acpi/acpica/dbinput.c @@ -57,12 +57,12 @@ static u32 acpi_db_get_line(char *input_buffer); static u32 acpi_db_match_command(char *user_command); -static void acpi_db_display_command_info(char *command, u8 display_all); +static void acpi_db_display_command_info(const char *command, u8 display_all); static void acpi_db_display_help(char *command); static u8 -acpi_db_match_command_help(char *command, +acpi_db_match_command_help(const char *command, const struct acpi_db_command_help *help); /* @@ -348,7 +348,7 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { ******************************************************************************/ static u8 -acpi_db_match_command_help(char *command, +acpi_db_match_command_help(const char *command, const struct acpi_db_command_help *help) { char *invocation = help->invocation; @@ -402,7 +402,7 @@ acpi_db_match_command_help(char *command, * ******************************************************************************/ -static void acpi_db_display_command_info(char *command, u8 display_all) +static void acpi_db_display_command_info(const char *command, u8 display_all) { const struct acpi_db_command_help *next; u8 matched; @@ -656,8 +656,9 @@ static u32 acpi_db_match_command(char *user_command) } for (i = CMD_FIRST_VALID; acpi_gbl_db_commands[i].name; i++) { - if (strstr(acpi_gbl_db_commands[i].name, user_command) == - acpi_gbl_db_commands[i].name) { + if (strstr + (ACPI_CAST_PTR(char, acpi_gbl_db_commands[i].name), + user_command) == acpi_gbl_db_commands[i].name) { return (i); } } diff --git a/drivers/acpi/acpica/dbutils.c b/drivers/acpi/acpica/dbutils.c index b37a2c77b86b..ae80106d1000 100644 --- a/drivers/acpi/acpica/dbutils.c +++ b/drivers/acpi/acpica/dbutils.c @@ -56,8 +56,6 @@ acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root); void acpi_db_dump_buffer(u32 address); #endif -static char *gbl_hex_to_ascii = "0123456789ABCDEF"; - /******************************************************************************* * * FUNCTION: acpi_db_match_argument @@ -82,8 +80,9 @@ acpi_db_match_argument(char *user_argument, } for (i = 0; arguments[i].name; i++) { - if (strstr(arguments[i].name, user_argument) == - arguments[i].name) { + if (strstr(ACPI_CAST_PTR(char, arguments[i].name), + ACPI_CAST_PTR(char, + user_argument)) == arguments[i].name) { return (i); } } @@ -339,7 +338,7 @@ void acpi_db_uint32_to_hex_string(u32 value, char *buffer) buffer[8] = '\0'; for (i = 7; i >= 0; i--) { - buffer[i] = gbl_hex_to_ascii[value & 0x0F]; + buffer[i] = acpi_gbl_upper_hex_digits[value & 0x0F]; value = value >> 4; } } diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 63924d1c737a..17d61c6a5b85 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -538,7 +538,8 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj) { - acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; + const acpi_name *reg_name_ptr = + ACPI_CAST_PTR(acpi_name, METHOD_NAME__REG); struct acpi_namespace_node *method_node; struct acpi_namespace_node *node; union acpi_operand_object *region_obj2; diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index ee30974b245a..fce6b2e10209 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -55,9 +55,9 @@ ACPI_MODULE_NAME("exdump") */ #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* Local prototypes */ -static void acpi_ex_out_string(char *title, char *value); +static void acpi_ex_out_string(const char *title, const char *value); -static void acpi_ex_out_pointer(char *title, void *value); +static void acpi_ex_out_pointer(const char *title, const void *value); static void acpi_ex_dump_object(union acpi_operand_object *obj_desc, @@ -365,8 +365,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, struct acpi_exdump_info *info) { u8 *target; - char *name; - const char *reference_name; + const char *name; u8 count; union acpi_operand_object *start; union acpi_operand_object *data = NULL; @@ -459,9 +458,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, case ACPI_EXD_REFERENCE: - reference_name = acpi_ut_get_reference_name(obj_desc); acpi_ex_out_string("Class Name", - ACPI_CAST_PTR(char, reference_name)); + acpi_ut_get_reference_name + (obj_desc)); acpi_ex_dump_reference_obj(obj_desc); break; @@ -934,12 +933,12 @@ acpi_ex_dump_operands(union acpi_operand_object **operands, * ******************************************************************************/ -static void acpi_ex_out_string(char *title, char *value) +static void acpi_ex_out_string(const char *title, const char *value) { acpi_os_printf("%20s : %s\n", title, value); } -static void acpi_ex_out_pointer(char *title, void *value) +static void acpi_ex_out_pointer(const char *title, const void *value) { acpi_os_printf("%20s : %p\n", title, value); } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index a01ddb393a55..7caaaf3b8787 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -504,9 +504,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) * Evaluate the \_Sx namespace object containing the register values * for this state */ - info->relative_pathname = ACPI_CAST_PTR(char, - acpi_gbl_sleep_state_names - [sleep_state]); + info->relative_pathname = acpi_gbl_sleep_state_names[sleep_state]; status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 697af810e5ad..426a6307eafa 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -107,9 +107,10 @@ acpi_status acpi_ns_root_initialize(void) continue; } - status = acpi_ns_lookup(NULL, init_val->name, init_val->type, - ACPI_IMODE_LOAD_PASS2, - ACPI_NS_NO_UPSEARCH, NULL, &new_node); + status = + acpi_ns_lookup(NULL, (char *)init_val->name, init_val->type, + ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, + NULL, &new_node); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create predefined name %s", diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index af236e348294..ce1f8605d996 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -81,7 +81,7 @@ acpi_ns_get_max_depth(acpi_handle obj_handle, * ******************************************************************************/ -void acpi_ns_print_pathname(u32 num_segments, char *pathname) +void acpi_ns_print_pathname(u32 num_segments, const char *pathname) { u32 i; @@ -114,6 +114,9 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) acpi_os_printf("]\n"); } +#ifdef ACPI_OBSOLETE_FUNCTIONS +/* Not used at this time, perhaps later */ + /******************************************************************************* * * FUNCTION: acpi_ns_dump_pathname @@ -131,7 +134,8 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) ******************************************************************************/ void -acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) +acpi_ns_dump_pathname(acpi_handle handle, + const char *msg, u32 level, u32 component) { ACPI_FUNCTION_TRACE(ns_dump_pathname); @@ -148,6 +152,7 @@ acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) acpi_os_printf("\n"); return_VOID; } +#endif /******************************************************************************* * diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c index cfd17a4f2e91..177b05b239b7 100644 --- a/drivers/acpi/acpica/psopinfo.c +++ b/drivers/acpi/acpica/psopinfo.c @@ -158,7 +158,7 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) * ******************************************************************************/ -char *acpi_ps_get_opcode_name(u16 opcode) +const char *acpi_ps_get_opcode_name(u16 opcode) { #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index 23a17c86d5a9..5ffdb5602d8d 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -52,17 +52,17 @@ ACPI_MODULE_NAME("rsdump") * All functions in this module are used by the AML Debugger only */ /* Local prototypes */ -static void acpi_rs_out_string(char *title, char *value); +static void acpi_rs_out_string(const char *title, const char *value); -static void acpi_rs_out_integer8(char *title, u8 value); +static void acpi_rs_out_integer8(const char *title, u8 value); -static void acpi_rs_out_integer16(char *title, u16 value); +static void acpi_rs_out_integer16(const char *title, u16 value); -static void acpi_rs_out_integer32(char *title, u32 value); +static void acpi_rs_out_integer32(const char *title, u32 value); -static void acpi_rs_out_integer64(char *title, u64 value); +static void acpi_rs_out_integer64(const char *title, u64 value); -static void acpi_rs_out_title(char *title); +static void acpi_rs_out_title(const char *title); static void acpi_rs_dump_byte_list(u16 length, u8 *data); @@ -208,7 +208,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) { u8 *target = NULL; u8 *previous_target; - char *name; + const char *name; u8 count; /* First table entry must contain the table length (# of table entries) */ @@ -248,10 +248,8 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) case ACPI_RSD_UINT8: if (table->pointer) { - acpi_rs_out_string(name, ACPI_CAST_PTR(char, - table-> - pointer - [*target])); + acpi_rs_out_string(name, + table->pointer[*target]); } else { acpi_rs_out_integer8(name, ACPI_GET8(target)); } @@ -276,26 +274,20 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) case ACPI_RSD_1BITFLAG: - acpi_rs_out_string(name, ACPI_CAST_PTR(char, - table-> - pointer[*target & - 0x01])); + acpi_rs_out_string(name, + table->pointer[*target & 0x01]); break; case ACPI_RSD_2BITFLAG: - acpi_rs_out_string(name, ACPI_CAST_PTR(char, - table-> - pointer[*target & - 0x03])); + acpi_rs_out_string(name, + table->pointer[*target & 0x03]); break; case ACPI_RSD_3BITFLAG: - acpi_rs_out_string(name, ACPI_CAST_PTR(char, - table-> - pointer[*target & - 0x07])); + acpi_rs_out_string(name, + table->pointer[*target & 0x07]); break; case ACPI_RSD_SHORTLIST: @@ -481,7 +473,7 @@ static void acpi_rs_dump_address_common(union acpi_resource_data *resource) * ******************************************************************************/ -static void acpi_rs_out_string(char *title, char *value) +static void acpi_rs_out_string(const char *title, const char *value) { acpi_os_printf("%27s : %s", title, value); @@ -491,30 +483,30 @@ static void acpi_rs_out_string(char *title, char *value) acpi_os_printf("\n"); } -static void acpi_rs_out_integer8(char *title, u8 value) +static void acpi_rs_out_integer8(const char *title, u8 value) { acpi_os_printf("%27s : %2.2X\n", title, value); } -static void acpi_rs_out_integer16(char *title, u16 value) +static void acpi_rs_out_integer16(const char *title, u16 value) { acpi_os_printf("%27s : %4.4X\n", title, value); } -static void acpi_rs_out_integer32(char *title, u32 value) +static void acpi_rs_out_integer32(const char *title, u32 value) { acpi_os_printf("%27s : %8.8X\n", title, value); } -static void acpi_rs_out_integer64(char *title, u64 value) +static void acpi_rs_out_integer64(const char *title, u64 value) { acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value)); } -static void acpi_rs_out_title(char *title) +static void acpi_rs_out_title(const char *title) { acpi_os_printf("%27s : ", title); diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index cf06e49cd91c..e0d60239d6ff 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -671,7 +671,7 @@ acpi_rs_get_aei_method_data(struct acpi_namespace_node *node, acpi_status acpi_rs_get_method_data(acpi_handle handle, - char *path, struct acpi_buffer *ret_buffer) + const char *path, struct acpi_buffer *ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index f63f3fd0d932..635d9513994d 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -53,7 +53,7 @@ static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, u8 space_id, u8 byte_width, - u64 address, char *register_name, u8 flags); + u64 address, const char *register_name, u8 flags); static void acpi_tb_convert_fadt(void); @@ -65,7 +65,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64); /* Table for conversion of FADT to common internal format and FADT validation */ typedef struct acpi_fadt_info { - char *name; + const char *name; u16 address64; u16 address32; u16 length; @@ -192,7 +192,7 @@ static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, u8 space_id, u8 byte_width, - u64 address, char *register_name, u8 flags) + u64 address, const char *register_name, u8 flags) { u8 bit_width; @@ -468,7 +468,7 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) static void acpi_tb_convert_fadt(void) { - char *name; + const char *name; struct acpi_generic_address *address64; u32 address32; u8 length; diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 1cfc5f69b033..574422205005 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -51,13 +51,9 @@ ACPI_MODULE_NAME("utdebug") #ifdef ACPI_DEBUG_OUTPUT -static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF; -static char *acpi_gbl_fn_entry_str = "----Entry"; -static char *acpi_gbl_fn_exit_str = "----Exit-"; - -/* Local prototypes */ - -static const char *acpi_ut_trim_function_name(const char *function_name); +static acpi_thread_id acpi_gbl_previous_thread_id = (acpi_thread_id) 0xFFFFFFFF; +static const char *acpi_gbl_function_entry_prefix = "----Entry"; +static const char *acpi_gbl_function_exit_prefix = "----Exit-"; /******************************************************************************* * @@ -178,14 +174,14 @@ acpi_debug_print(u32 requested_debug_level, * Thread tracking and context switch notification */ thread_id = acpi_os_get_thread_id(); - if (thread_id != acpi_gbl_prev_thread_id) { + if (thread_id != acpi_gbl_previous_thread_id) { if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf ("\n**** Context Switch from TID %u to TID %u ****\n\n", - (u32)acpi_gbl_prev_thread_id, (u32)thread_id); + (u32)acpi_gbl_previous_thread_id, (u32)thread_id); } - acpi_gbl_prev_thread_id = thread_id; + acpi_gbl_previous_thread_id = thread_id; acpi_gbl_nesting_level = 0; } @@ -287,7 +283,8 @@ acpi_ut_trace(u32 line_number, if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, - component_id, "%s\n", acpi_gbl_fn_entry_str); + component_id, "%s\n", + acpi_gbl_function_entry_prefix); } } @@ -312,7 +309,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace) void acpi_ut_trace_ptr(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, void *pointer) + const char *module_name, + u32 component_id, const void *pointer) { acpi_gbl_nesting_level++; @@ -323,8 +321,8 @@ acpi_ut_trace_ptr(u32 line_number, if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, - component_id, "%s %p\n", acpi_gbl_fn_entry_str, - pointer); + component_id, "%s %p\n", + acpi_gbl_function_entry_prefix, pointer); } } @@ -348,7 +346,7 @@ acpi_ut_trace_ptr(u32 line_number, void acpi_ut_trace_str(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, char *string) + const char *module_name, u32 component_id, const char *string) { acpi_gbl_nesting_level++; @@ -359,8 +357,8 @@ acpi_ut_trace_str(u32 line_number, if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, - component_id, "%s %s\n", acpi_gbl_fn_entry_str, - string); + component_id, "%s %s\n", + acpi_gbl_function_entry_prefix, string); } } @@ -396,7 +394,7 @@ acpi_ut_trace_u32(u32 line_number, acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, component_id, "%s %08X\n", - acpi_gbl_fn_entry_str, integer); + acpi_gbl_function_entry_prefix, integer); } } @@ -427,7 +425,8 @@ acpi_ut_exit(u32 line_number, if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, - component_id, "%s\n", acpi_gbl_fn_exit_str); + component_id, "%s\n", + acpi_gbl_function_exit_prefix); } if (acpi_gbl_nesting_level) { @@ -467,14 +466,14 @@ acpi_ut_status_exit(u32 line_number, acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, component_id, "%s %s\n", - acpi_gbl_fn_exit_str, + acpi_gbl_function_exit_prefix, acpi_format_exception(status)); } else { acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, component_id, "%s ****Exception****: %s\n", - acpi_gbl_fn_exit_str, + acpi_gbl_function_exit_prefix, acpi_format_exception(status)); } } @@ -514,7 +513,7 @@ acpi_ut_value_exit(u32 line_number, acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, component_id, "%s %8.8X%8.8X\n", - acpi_gbl_fn_exit_str, + acpi_gbl_function_exit_prefix, ACPI_FORMAT_UINT64(value)); } @@ -552,8 +551,8 @@ acpi_ut_ptr_exit(u32 line_number, if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { acpi_debug_print(ACPI_LV_FUNCTIONS, line_number, function_name, module_name, - component_id, "%s %p\n", acpi_gbl_fn_exit_str, - ptr); + component_id, "%s %p\n", + acpi_gbl_function_exit_prefix, ptr); } if (acpi_gbl_nesting_level) { diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 17b9f3e6e1e1..7bad13f2e518 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -69,7 +69,7 @@ ACPI_MODULE_NAME("uteval") acpi_status acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, - char *path, + const char *path, u32 expected_return_btypes, union acpi_operand_object **return_desc) { @@ -204,7 +204,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, ******************************************************************************/ acpi_status -acpi_ut_evaluate_numeric_object(char *object_name, +acpi_ut_evaluate_numeric_object(const char *object_name, struct acpi_namespace_node *device_node, u64 *value) { diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index d45899c17d4e..dd3fd7f97f8e 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -80,6 +80,11 @@ const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = { "_S4D" }; +/* Hex-to-ascii */ + +const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef"; +const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF"; + /******************************************************************************* * * Namespace globals diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index d938c27cc6cf..389de3bd1ff1 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -361,7 +361,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object, void acpi_ut_display_init_pathname(u8 type, struct acpi_namespace_node *obj_handle, - char *path) + const char *path) { acpi_status status; struct acpi_buffer buffer; diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c index 8c218ad787cd..208d71aa9f50 100644 --- a/drivers/acpi/acpica/utprint.c +++ b/drivers/acpi/acpica/utprint.c @@ -67,11 +67,6 @@ static char *acpi_ut_format_number(char *string, static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper); -/* Module globals */ - -static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef"; -static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF"; - /******************************************************************************* * * FUNCTION: acpi_ut_bound_string_length diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 60c406a8efcb..0df07dfa53b6 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -90,7 +90,7 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *address, ******************************************************************************/ acpi_status -acpi_ut_create_list(char *list_name, +acpi_ut_create_list(const char *list_name, u16 object_size, struct acpi_memory_list **return_cache) { struct acpi_memory_list *cache; diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 140886e4973f..b9a8b72e297c 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -995,7 +995,7 @@ struct acpi_buffer { * Predefined Namespace items */ struct acpi_predefined_names { - char *name; + const char *name; u8 type; char *val; }; @@ -1228,7 +1228,7 @@ struct acpi_mem_space_context { * struct acpi_memory_list is used only if the ACPICA local cache is enabled */ struct acpi_memory_list { - char *list_name; + const char *list_name; void *list_head; u16 object_size; u16 max_depth; -- GitLab From 7447bc1e69bafab72ef69a7f054bb1e5f9ff908d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:40:48 +0800 Subject: [PATCH 1288/9938] ACPICA: iASL/Disassembler: Improve handling of unresolved methods ACPICA commit 16cd0872a070c8d3b16b8b13c1fc90a443a6b6fe If the definition of a control method cannot be found (probably it is in another module/SSDT), the disassembler must try to guess at the number of arguments to that method. This change improves the guessing heuristic. Link: https://github.com/acpica/acpica/commit/16cd0872 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 9562a10a1a18..083b16ada31e 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -1096,6 +1096,7 @@ struct acpi_external_list { #define ACPI_EXT_ORIGIN_FROM_FILE 0x02 /* External came from a file */ #define ACPI_EXT_INTERNAL_PATH_ALLOCATED 0x04 /* Deallocate internal path on completion */ #define ACPI_EXT_EXTERNAL_EMITTED 0x08 /* External() statement has been emitted */ +#define ACPI_EXT_ORIGIN_FROM_OPCODE 0x10 /* External came from a External() opcode */ struct acpi_external_file { char *path; -- GitLab From a8d1e1c063b0b1c91a9415f5cb09e37a75bce809 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:40:56 +0800 Subject: [PATCH 1289/9938] ACPICA: Utilities: Add ACPI_IS_POWER_OF_TWO() ACPICA commit cbcb77565c5032dd48e19b3a8a8b8704c5f29faf This patch adds a macro ACPI_IS_POWER_OF_TWO, which can be used to detect if a number is a power of two. Lv Zheng. Link: https://github.com/acpica/acpica/commit/cbcb7756 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acmacros.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 411c18b7d541..b461f5568e8c 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -260,6 +260,10 @@ #define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1)) +/* Generic (power-of-two) rounding */ + +#define ACPI_IS_POWER_OF_TWO(a) (((a) & ((a) - 1)) == 0) + /* * Bitmask creation * Bit positions start at zero. -- GitLab From 0461f34e16b39b083f289d27d2355df9d5ba1420 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:41:02 +0800 Subject: [PATCH 1290/9938] Utilities: Fix missing parentheses in ACPI_GET_BITS()/ACPI_SET_BITS() Some compilers require parentheses to be enforced in the macro definition, so that the macro caller side can be simpler. This patch fixes this kind of macro issue in ACPI_SET_BITS()/ACPI_GET_BITS(). Lv Zheng. Link: https://bugs.acpica.org/show_bug.cgi?id=1268 Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acmacros.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index b461f5568e8c..73f6653c848d 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -287,10 +287,10 @@ /* Generic bitfield macros and masks */ #define ACPI_GET_BITS(source_ptr, position, mask) \ - ((*source_ptr >> position) & mask) + ((*(source_ptr) >> (position)) & (mask)) #define ACPI_SET_BITS(target_ptr, position, mask, value) \ - (*target_ptr |= ((value & mask) << position)) + (*(target_ptr) |= (((value) & (mask)) << (position))) #define ACPI_1BIT_MASK 0x00000001 #define ACPI_2BIT_MASK 0x00000003 -- GitLab From 920de6ebfab865a5bb2bcc60f6998aa270300b95 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:41:09 +0800 Subject: [PATCH 1291/9938] ACPICA: Hardware: Enhance acpi_hw_validate_register() with access_width/bit_offset awareness ACPICA commit 997a90f810a4cb78604ef2e187611a181b498286 This patch enhances acpi_hw_validate_register() to sanitize register accesses with awareness of access_width and bit_offset. Lv Zheng. Link: https://github.com/acpica/acpica/commit/997a90f8 Link: https://bugs.acpica.org/show_bug.cgi?id=1240 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwregs.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 5ba0498412fd..035fb52c3bcd 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -83,6 +83,8 @@ acpi_status acpi_hw_validate_register(struct acpi_generic_address *reg, u8 max_bit_width, u64 *address) { + u8 bit_width; + u8 access_width; /* Must have a valid pointer to a GAS structure */ @@ -109,23 +111,26 @@ acpi_hw_validate_register(struct acpi_generic_address *reg, return (AE_SUPPORT); } - /* Validate the bit_width */ + /* Validate the access_width */ - if ((reg->bit_width != 8) && - (reg->bit_width != 16) && - (reg->bit_width != 32) && (reg->bit_width != max_bit_width)) { + if (reg->access_width > 4) { ACPI_ERROR((AE_INFO, - "Unsupported register bit width: 0x%X", - reg->bit_width)); + "Unsupported register access width: 0x%X", + reg->access_width)); return (AE_SUPPORT); } - /* Validate the bit_offset. Just a warning for now. */ + /* Validate the bit_width, convert access_width into number of bits */ - if (reg->bit_offset != 0) { + access_width = reg->access_width ? reg->access_width : 1; + access_width = 1 << (access_width + 2); + bit_width = + ACPI_ROUND_UP(reg->bit_offset + reg->bit_width, access_width); + if (max_bit_width < bit_width) { ACPI_WARNING((AE_INFO, - "Unsupported register bit offset: 0x%X", - reg->bit_offset)); + "Requested bit width 0x%X is smaller than register bit width 0x%X", + max_bit_width, bit_width)); + return (AE_SUPPORT); } return (AE_OK); -- GitLab From 78542058f522076c888822735d8fc9bd93cfd586 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:41:32 +0800 Subject: [PATCH 1292/9938] ACPICA: Interpreter: Fix wrong conditions for acpi_ev_install_region_handlers() invocation ACPICA commit 9a6ecc9ec9ee067cad51eec539230bf494421d76 Since AE_ALREADY_EXISTS has already been converted to AE_OK in acpi_ev_install_region_handlers(), this patch simplies a return value check. Lv Zheng. Link: https://github.com/acpica/acpica/commit/9a6ecc9e Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbxfload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 3151968c10d1..ac71abcd32bb 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -82,7 +82,7 @@ acpi_status __init acpi_load_tables(void) * their customized default region handlers. */ status = acpi_ev_install_region_handlers(); - if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) { + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During Region initialization")); return_ACPI_STATUS(status); -- GitLab From ca4fc02714f046cbdc8c0ee4af6733b6231e57dc Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:41:39 +0800 Subject: [PATCH 1293/9938] ACPICA: Tables: Fix wrong MLC condition for dynamic table loading ACPICA commit 5798cd6171ea38bcf4594d0ccc78870784776ba5 The patch corrects wrong condition before group MLC is disabled. Link: https://github.com/acpica/acpica/commit/5798cd61 Link: https://bugs.acpica.org/show_bug.cgi?id=1262 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/exconfig.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index f74161301037..a1d177d58254 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -118,7 +118,9 @@ acpi_ex_add_table(u32 table_index, /* Execute any module-level code that was found in the table */ acpi_ex_exit_interpreter(); - acpi_ns_exec_module_code_list(); + if (acpi_gbl_group_module_level_code) { + acpi_ns_exec_module_code_list(); + } acpi_ex_enter_interpreter(); /* -- GitLab From d1461a1b506e4a2df9f703c5f39f765b65c9672e Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:41:47 +0800 Subject: [PATCH 1294/9938] ACPICA: Events: Fix an issue that _REG association can happen before namespace is initialized ACPICA commit c508f8592efaa0d8197f26d7fee6382c5ac8e383 Current code flow cannot ensure _REG association can happen after the namespace is initialized, so we move _REG association to where _REG was about to run to fix this issue. This issue is detected when acpi_ev_initialize_region() is invoked during the table loading. And this is one of the most important the root cause why ACPICA table loading is split into 2 load passes. Lv Zheng. Link: https://github.com/acpica/acpica/commit/c508f859 Link: https://bugs.acpica.org/show_bug.cgi?id=1252 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acevents.h | 2 - drivers/acpi/acpica/evregion.c | 71 ++++++++++++---------------------- drivers/acpi/acpica/evrgnini.c | 1 - 3 files changed, 24 insertions(+), 50 deletions(-) diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 010cf81bada9..17f221782d2f 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -198,8 +198,6 @@ void acpi_ev_detach_region(union acpi_operand_object *region_obj, u8 acpi_ns_is_locked); -void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj); - void acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, acpi_adr_space_type space_id, u32 function); diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 17d61c6a5b85..4c6f79514040 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -526,82 +526,59 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, /******************************************************************************* * - * FUNCTION: acpi_ev_associate_reg_method + * FUNCTION: acpi_ev_execute_reg_method * * PARAMETERS: region_obj - Region object + * function - Passed to _REG: On (1) or Off (0) * * RETURN: Status * - * DESCRIPTION: Find and associate _REG method to a region + * DESCRIPTION: Execute _REG method for a region * ******************************************************************************/ -void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj) +acpi_status +acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) { + struct acpi_evaluate_info *info; + union acpi_operand_object *args[3]; + union acpi_operand_object *region_obj2; const acpi_name *reg_name_ptr = ACPI_CAST_PTR(acpi_name, METHOD_NAME__REG); struct acpi_namespace_node *method_node; struct acpi_namespace_node *node; - union acpi_operand_object *region_obj2; acpi_status status; - ACPI_FUNCTION_TRACE(ev_associate_reg_method); + ACPI_FUNCTION_TRACE(ev_execute_reg_method); + + if (!acpi_gbl_namespace_initialized || + region_obj->region.handler == NULL) { + return_ACPI_STATUS(AE_OK); + } region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { - return_VOID; + return_ACPI_STATUS(AE_NOT_EXIST); } + /* + * Find any "_REG" method associated with this region definition. + * The method should always be updated as this function may be + * invoked after a namespace change. + */ node = region_obj->region.node->parent; - - /* Find any "_REG" method associated with this region definition */ - status = acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD, &method_node); if (ACPI_SUCCESS(status)) { /* - * The _REG method is optional and there can be only one per region - * definition. This will be executed when the handler is attached - * or removed + * The _REG method is optional and there can be only one per + * region definition. This will be executed when the handler is + * attached or removed. */ region_obj2->extra.method_REG = method_node; } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_execute_reg_method - * - * PARAMETERS: region_obj - Region object - * function - Passed to _REG: On (1) or Off (0) - * - * RETURN: Status - * - * DESCRIPTION: Execute _REG method for a region - * - ******************************************************************************/ - -acpi_status -acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) -{ - struct acpi_evaluate_info *info; - union acpi_operand_object *args[3]; - union acpi_operand_object *region_obj2; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_execute_reg_method); - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - if (region_obj2->extra.method_REG == NULL || - region_obj->region.handler == NULL || - !acpi_gbl_namespace_initialized) { + if (region_obj2->extra.method_REG == NULL) { return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index fda869c9ad0b..6972ab4ddb66 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -518,7 +518,6 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, return_ACPI_STATUS(AE_OK); } - acpi_ev_associate_reg_method(region_obj); region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; node = region_obj->region.node->parent; -- GitLab From 2d3349de8072baf2c2dd096664fa818d5339bb5a Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 09:41:54 +0800 Subject: [PATCH 1295/9938] ACPICA: Namespace: Reorder \_SB._INI to make sure it is evaluated before _REG evaluations ACPICA commit f005ee6b90d152c1f499efcca6b771a93903cb55 This patch splits \_SB._INI evaluation from device initialization code, so that it can be performed before PCI_Config _REG evaluations. This is required for the device enumeration process. Some named objects are initialized in \_SB._INI and PCI_Config _REG evaluations may use uninitialized named objects because of the order issue. This must be fixed before fixing ECDT order issue. There are existing tables allowing ECDT EC to be used for the entire device enumeration process, but the enabling of ECDT EC is done in \_SB._INI. Thus \_SB._INI must be the first control method evaluated in the device enumeration process. Normally, the order should be automatically ensured by the device enumeration process itself (for example, PCI_Config _REGs are evaluated by the PCI bus driver when the driver is probed by the enumeration process), but since the process is split on Linux (partially done in Linux, partially done in ACPICA), we need to ensure this with special logics in order to be regression safe. Lv Zheng. Link: https://github.com/acpica/acpica/commit/f005ee6b Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsinit.c | 75 ++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 2de8adb41d64..36643a8cf65a 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -140,6 +140,7 @@ acpi_status acpi_ns_initialize_devices(u32 flags) { acpi_status status = AE_OK; struct acpi_device_walk_info info; + acpi_handle handle; ACPI_FUNCTION_TRACE(ns_initialize_devices); @@ -190,6 +191,27 @@ acpi_status acpi_ns_initialize_devices(u32 flags) if (ACPI_SUCCESS(status)) { info.num_INI++; } + + /* + * Execute \_SB._INI. + * There appears to be a strict order requirement for \_SB._INI, + * which should be evaluated before any _REG evaluations. + */ + status = acpi_get_handle(NULL, "\\_SB", &handle); + if (ACPI_SUCCESS(status)) { + memset(info.evaluate_info, 0, + sizeof(struct acpi_evaluate_info)); + info.evaluate_info->prefix_node = handle; + info.evaluate_info->relative_pathname = + METHOD_NAME__INI; + info.evaluate_info->parameters = NULL; + info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE; + + status = acpi_ns_evaluate(info.evaluate_info); + if (ACPI_SUCCESS(status)) { + info.num_INI++; + } + } } /* @@ -198,6 +220,12 @@ acpi_status acpi_ns_initialize_devices(u32 flags) * Note: Any objects accessed by the _REG methods will be automatically * initialized, even if they contain executable AML (see the call to * acpi_ns_initialize_objects below). + * + * Note: According to the ACPI specification, we actually needn't execute + * _REG for system_memory/system_io operation regions, but for PCI_Config + * operation regions, it is required to evaluate _REG for those on a PCI + * root bus that doesn't contain _BBN object. So this code is kept here + * in order not to break things. */ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -592,32 +620,37 @@ acpi_ns_init_one_device(acpi_handle obj_handle, * Note: We know there is an _INI within this subtree, but it may not be * under this particular device, it may be lower in the branch. */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); - - memset(info, 0, sizeof(struct acpi_evaluate_info)); - info->prefix_node = device_node; - info->relative_pathname = METHOD_NAME__INI; - info->parameters = NULL; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - status = acpi_ns_evaluate(info); - if (ACPI_SUCCESS(status)) { - walk_info->num_INI++; - } + if (!ACPI_COMPARE_NAME(device_node->name.ascii, "_SB_") || + device_node->parent != acpi_gbl_root_node) { + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, device_node, + METHOD_NAME__INI)); + + memset(info, 0, sizeof(struct acpi_evaluate_info)); + info->prefix_node = device_node; + info->relative_pathname = METHOD_NAME__INI; + info->parameters = NULL; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + status = acpi_ns_evaluate(info); + if (ACPI_SUCCESS(status)) { + walk_info->num_INI++; + } #ifdef ACPI_DEBUG_OUTPUT - else if (status != AE_NOT_FOUND) { + else if (status != AE_NOT_FOUND) { - /* Ignore error and move on to next device */ + /* Ignore error and move on to next device */ - char *scope_name = - acpi_ns_get_normalized_pathname(device_node, TRUE); + char *scope_name = + acpi_ns_get_normalized_pathname(device_node, TRUE); - ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", - scope_name)); - ACPI_FREE(scope_name); - } + ACPI_EXCEPTION((AE_INFO, status, + "during %s._INI execution", + scope_name)); + ACPI_FREE(scope_name); + } #endif + } /* Ignore errors from above */ -- GitLab From 8804f2525a56261b93576a1900185ac2691d138a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 24 Mar 2016 09:42:01 +0800 Subject: [PATCH 1296/9938] ACPICA: Update version to 20160318 ACPICA commit e714615fda31cce3df9cfd95ee03c1f2c74b2b5e Version 20160318. Link: https://github.com/acpica/acpica/commit/e714615f Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 17556979dc79..83583a251e72 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20160108 +#define ACPI_CA_VERSION 0x20160318 #include #include -- GitLab From a4298e4522d687a79af8f8fbb7eca68399ab2d81 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:12 -0700 Subject: [PATCH 1297/9938] net: add SOCK_RCU_FREE socket flag We want a generic way to insert an RCU grace period before socket freeing for cases where RCU_SLAB_DESTROY_BY_RCU is adding too much overhead. SLAB_DESTROY_BY_RCU strict rules force us to take a reference on the socket sk_refcnt, and it is a performance problem for UDP encapsulation, or TCP synflood behavior, as many CPUs might attempt the atomic operations on a shared sk_refcnt UDP sockets and TCP listeners can set SOCK_RCU_FREE so that their lookup can use traditional RCU rules, without refcount changes. They can set the flag only once hashed and visible by other cpus. Signed-off-by: Eric Dumazet Cc: Tom Herbert Tested-by: Tom Herbert Signed-off-by: David S. Miller --- include/net/sock.h | 2 ++ net/core/sock.c | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index e91b87f54f99..9e77353a92ae 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -438,6 +438,7 @@ struct sock { struct sk_buff *skb); void (*sk_destruct)(struct sock *sk); struct sock_reuseport __rcu *sk_reuseport_cb; + struct rcu_head sk_rcu; }; #define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data))) @@ -720,6 +721,7 @@ enum sock_flags { */ SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */ SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */ + SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */ }; #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) diff --git a/net/core/sock.c b/net/core/sock.c index 315f5e57fffe..7a6a063b28b3 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1419,8 +1419,12 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, } EXPORT_SYMBOL(sk_alloc); -void sk_destruct(struct sock *sk) +/* Sockets having SOCK_RCU_FREE will call this function after one RCU + * grace period. This is the case for UDP sockets and TCP listeners. + */ +static void __sk_destruct(struct rcu_head *head) { + struct sock *sk = container_of(head, struct sock, sk_rcu); struct sk_filter *filter; if (sk->sk_destruct) @@ -1449,6 +1453,14 @@ void sk_destruct(struct sock *sk) sk_prot_free(sk->sk_prot_creator, sk); } +void sk_destruct(struct sock *sk) +{ + if (sock_flag(sk, SOCK_RCU_FREE)) + call_rcu(&sk->sk_rcu, __sk_destruct); + else + __sk_destruct(&sk->sk_rcu); +} + static void __sk_free(struct sock *sk) { if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt)) -- GitLab From ca065d0cf80fa547724440a8bf37f1e674d917c0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:13 -0700 Subject: [PATCH 1298/9938] udp: no longer use SLAB_DESTROY_BY_RCU Tom Herbert would like not touching UDP socket refcnt for encapsulated traffic. For this to happen, we need to use normal RCU rules, with a grace period before freeing a socket. UDP sockets are not short lived in the high usage case, so the added cost of call_rcu() should not be a concern. This actually removes a lot of complexity in UDP stack. Multicast receives no longer need to hold a bucket spinlock. Note that ip early demux still needs to take a reference on the socket. Same remark for functions used by xt_socket and xt_PROXY netfilter modules, but this might be changed later. Performance for a single UDP socket receiving flood traffic from many RX queues/cpus. Simple udp_rx using simple recvfrom() loop : 438 kpps instead of 374 kpps : 17 % increase of the peak rate. v2: Addressed Willem de Bruijn feedback in multicast handling - keep early demux break in __udp4_lib_demux_lookup() Signed-off-by: Eric Dumazet Cc: Tom Herbert Cc: Willem de Bruijn Tested-by: Tom Herbert Signed-off-by: David S. Miller --- include/linux/udp.h | 8 +- include/net/sock.h | 12 +- include/net/udp.h | 2 +- net/ipv4/udp.c | 293 +++++++++++++------------------------------- net/ipv4/udp_diag.c | 18 +-- net/ipv6/udp.c | 196 ++++++++++------------------- 6 files changed, 171 insertions(+), 358 deletions(-) diff --git a/include/linux/udp.h b/include/linux/udp.h index 87c094961bd5..32342754643a 100644 --- a/include/linux/udp.h +++ b/include/linux/udp.h @@ -98,11 +98,11 @@ static inline bool udp_get_no_check6_rx(struct sock *sk) return udp_sk(sk)->no_check6_rx; } -#define udp_portaddr_for_each_entry(__sk, node, list) \ - hlist_nulls_for_each_entry(__sk, node, list, __sk_common.skc_portaddr_node) +#define udp_portaddr_for_each_entry(__sk, list) \ + hlist_for_each_entry(__sk, list, __sk_common.skc_portaddr_node) -#define udp_portaddr_for_each_entry_rcu(__sk, node, list) \ - hlist_nulls_for_each_entry_rcu(__sk, node, list, __sk_common.skc_portaddr_node) +#define udp_portaddr_for_each_entry_rcu(__sk, list) \ + hlist_for_each_entry_rcu(__sk, list, __sk_common.skc_portaddr_node) #define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag) diff --git a/include/net/sock.h b/include/net/sock.h index 9e77353a92ae..7ad73db9dde2 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -178,7 +178,7 @@ struct sock_common { int skc_bound_dev_if; union { struct hlist_node skc_bind_node; - struct hlist_nulls_node skc_portaddr_node; + struct hlist_node skc_portaddr_node; }; struct proto *skc_prot; possible_net_t skc_net; @@ -670,18 +670,18 @@ static inline void sk_add_bind_node(struct sock *sk, hlist_for_each_entry(__sk, list, sk_bind_node) /** - * sk_nulls_for_each_entry_offset - iterate over a list at a given struct offset + * sk_for_each_entry_offset_rcu - iterate over a list at a given struct offset * @tpos: the type * to use as a loop cursor. * @pos: the &struct hlist_node to use as a loop cursor. * @head: the head for your list. * @offset: offset of hlist_node within the struct. * */ -#define sk_nulls_for_each_entry_offset(tpos, pos, head, offset) \ - for (pos = (head)->first; \ - (!is_a_nulls(pos)) && \ +#define sk_for_each_entry_offset_rcu(tpos, pos, head, offset) \ + for (pos = rcu_dereference((head)->first); \ + pos != NULL && \ ({ tpos = (typeof(*tpos) *)((void *)pos - offset); 1;}); \ - pos = pos->next) + pos = rcu_dereference(pos->next)) static inline struct user_namespace *sk_user_ns(struct sock *sk) { diff --git a/include/net/udp.h b/include/net/udp.h index 92927f729ac8..d870ec1611c4 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -59,7 +59,7 @@ struct udp_skb_cb { * @lock: spinlock protecting changes to head/count */ struct udp_hslot { - struct hlist_nulls_head head; + struct hlist_head head; int count; spinlock_t lock; } __attribute__((aligned(2 * sizeof(long)))); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 45ff590661f4..355bdb221057 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -143,10 +143,9 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num, unsigned int log) { struct sock *sk2; - struct hlist_nulls_node *node; kuid_t uid = sock_i_uid(sk); - sk_nulls_for_each(sk2, node, &hslot->head) { + sk_for_each(sk2, &hslot->head) { if (net_eq(sock_net(sk2), net) && sk2 != sk && (bitmap || udp_sk(sk2)->udp_port_hash == num) && @@ -177,12 +176,11 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, bool match_wildcard)) { struct sock *sk2; - struct hlist_nulls_node *node; kuid_t uid = sock_i_uid(sk); int res = 0; spin_lock(&hslot2->lock); - udp_portaddr_for_each_entry(sk2, node, &hslot2->head) { + udp_portaddr_for_each_entry(sk2, &hslot2->head) { if (net_eq(sock_net(sk2), net) && sk2 != sk && (udp_sk(sk2)->udp_port_hash == num) && @@ -207,11 +205,10 @@ static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot, bool match_wildcard)) { struct net *net = sock_net(sk); - struct hlist_nulls_node *node; kuid_t uid = sock_i_uid(sk); struct sock *sk2; - sk_nulls_for_each(sk2, node, &hslot->head) { + sk_for_each(sk2, &hslot->head) { if (net_eq(sock_net(sk2), net) && sk2 != sk && sk2->sk_family == sk->sk_family && @@ -333,17 +330,18 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, goto fail_unlock; } - sk_nulls_add_node_rcu(sk, &hslot->head); + sk_add_node_rcu(sk, &hslot->head); hslot->count++; sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); spin_lock(&hslot2->lock); - hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, + hlist_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, &hslot2->head); hslot2->count++; spin_unlock(&hslot2->lock); } + sock_set_flag(sk, SOCK_RCU_FREE); error = 0; fail_unlock: spin_unlock_bh(&hslot->lock); @@ -497,37 +495,27 @@ static struct sock *udp4_lib_lookup2(struct net *net, struct sk_buff *skb) { struct sock *sk, *result; - struct hlist_nulls_node *node; int score, badness, matches = 0, reuseport = 0; - bool select_ok = true; u32 hash = 0; -begin: result = NULL; badness = 0; - udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) { + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { score = compute_score2(sk, net, saddr, sport, daddr, hnum, dif); if (score > badness) { - result = sk; - badness = score; reuseport = sk->sk_reuseport; if (reuseport) { hash = udp_ehashfn(net, daddr, hnum, saddr, sport); - if (select_ok) { - struct sock *sk2; - - sk2 = reuseport_select_sock(sk, hash, skb, + result = reuseport_select_sock(sk, hash, skb, sizeof(struct udphdr)); - if (sk2) { - result = sk2; - select_ok = false; - goto found; - } - } + if (result) + return result; matches = 1; } + badness = score; + result = sk; } else if (score == badness && reuseport) { matches++; if (reciprocal_scale(hash, matches) == 0) @@ -535,23 +523,6 @@ static struct sock *udp4_lib_lookup2(struct net *net, hash = next_pseudo_random32(hash); } } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != slot2) - goto begin; - if (result) { -found: - if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) - result = NULL; - else if (unlikely(compute_score2(result, net, saddr, sport, - daddr, hnum, dif) < badness)) { - sock_put(result); - goto begin; - } - } return result; } @@ -563,15 +534,12 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, int dif, struct udp_table *udptable, struct sk_buff *skb) { struct sock *sk, *result; - struct hlist_nulls_node *node; unsigned short hnum = ntohs(dport); unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; int score, badness, matches = 0, reuseport = 0; - bool select_ok = true; u32 hash = 0; - rcu_read_lock(); if (hslot->count > 10) { hash2 = udp4_portaddr_hash(net, daddr, hnum); slot2 = hash2 & udptable->mask; @@ -593,35 +561,27 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, htonl(INADDR_ANY), hnum, dif, hslot2, slot2, skb); } - rcu_read_unlock(); return result; } begin: result = NULL; badness = 0; - sk_nulls_for_each_rcu(sk, node, &hslot->head) { + sk_for_each_rcu(sk, &hslot->head) { score = compute_score(sk, net, saddr, hnum, sport, daddr, dport, dif); if (score > badness) { - result = sk; - badness = score; reuseport = sk->sk_reuseport; if (reuseport) { hash = udp_ehashfn(net, daddr, hnum, saddr, sport); - if (select_ok) { - struct sock *sk2; - - sk2 = reuseport_select_sock(sk, hash, skb, + result = reuseport_select_sock(sk, hash, skb, sizeof(struct udphdr)); - if (sk2) { - result = sk2; - select_ok = false; - goto found; - } - } + if (result) + return result; matches = 1; } + result = sk; + badness = score; } else if (score == badness && reuseport) { matches++; if (reciprocal_scale(hash, matches) == 0) @@ -629,25 +589,6 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, hash = next_pseudo_random32(hash); } } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != slot) - goto begin; - - if (result) { -found: - if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) - result = NULL; - else if (unlikely(compute_score(result, net, saddr, hnum, sport, - daddr, dport, dif) < badness)) { - sock_put(result); - goto begin; - } - } - rcu_read_unlock(); return result; } EXPORT_SYMBOL_GPL(__udp4_lib_lookup); @@ -663,13 +604,24 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, udptable, skb); } +/* Must be called under rcu_read_lock(). + * Does increment socket refcount. + */ +#if IS_ENABLED(CONFIG_NETFILTER_XT_MATCH_SOCKET) || \ + IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY) struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, __be32 daddr, __be16 dport, int dif) { - return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, - &udp_table, NULL); + struct sock *sk; + + sk = __udp4_lib_lookup(net, saddr, sport, daddr, dport, + dif, &udp_table, NULL); + if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) + sk = NULL; + return sk; } EXPORT_SYMBOL_GPL(udp4_lib_lookup); +#endif static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk, __be16 loc_port, __be32 loc_addr, @@ -771,7 +723,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) sk->sk_err = err; sk->sk_error_report(sk); out: - sock_put(sk); + return; } void udp_err(struct sk_buff *skb, u32 info) @@ -1474,13 +1426,13 @@ void udp_lib_unhash(struct sock *sk) spin_lock_bh(&hslot->lock); if (rcu_access_pointer(sk->sk_reuseport_cb)) reuseport_detach_sock(sk); - if (sk_nulls_del_node_init_rcu(sk)) { + if (sk_del_node_init_rcu(sk)) { hslot->count--; inet_sk(sk)->inet_num = 0; sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); spin_lock(&hslot2->lock); - hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); + hlist_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); hslot2->count--; spin_unlock(&hslot2->lock); } @@ -1513,12 +1465,12 @@ void udp_lib_rehash(struct sock *sk, u16 newhash) if (hslot2 != nhslot2) { spin_lock(&hslot2->lock); - hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); + hlist_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); hslot2->count--; spin_unlock(&hslot2->lock); spin_lock(&nhslot2->lock); - hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, + hlist_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, &nhslot2->head); nhslot2->count++; spin_unlock(&nhslot2->lock); @@ -1697,35 +1649,6 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) return -1; } -static void flush_stack(struct sock **stack, unsigned int count, - struct sk_buff *skb, unsigned int final) -{ - unsigned int i; - struct sk_buff *skb1 = NULL; - struct sock *sk; - - for (i = 0; i < count; i++) { - sk = stack[i]; - if (likely(!skb1)) - skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); - - if (!skb1) { - atomic_inc(&sk->sk_drops); - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, - IS_UDPLITE(sk)); - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, - IS_UDPLITE(sk)); - } - - if (skb1 && udp_queue_rcv_skb(sk, skb1) <= 0) - skb1 = NULL; - - sock_put(sk); - } - if (unlikely(skb1)) - kfree_skb(skb1); -} - /* For TCP sockets, sk_rx_dst is protected by socket lock * For UDP, we use xchg() to guard against concurrent changes. */ @@ -1749,14 +1672,14 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, struct udp_table *udptable, int proto) { - struct sock *sk, *stack[256 / sizeof(struct sock *)]; - struct hlist_nulls_node *node; + struct sock *sk, *first = NULL; unsigned short hnum = ntohs(uh->dest); struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum); - int dif = skb->dev->ifindex; - unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); - bool inner_flushed = false; + unsigned int offset = offsetof(typeof(*sk), sk_node); + int dif = skb->dev->ifindex; + struct hlist_node *node; + struct sk_buff *nskb; if (use_hash2) { hash2_any = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum) & @@ -1767,23 +1690,28 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); } - spin_lock(&hslot->lock); - sk_nulls_for_each_entry_offset(sk, node, &hslot->head, offset) { - if (__udp_is_mcast_sock(net, sk, - uh->dest, daddr, - uh->source, saddr, - dif, hnum)) { - if (unlikely(count == ARRAY_SIZE(stack))) { - flush_stack(stack, count, skb, ~0); - inner_flushed = true; - count = 0; - } - stack[count++] = sk; - sock_hold(sk); + sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) { + if (!__udp_is_mcast_sock(net, sk, uh->dest, daddr, + uh->source, saddr, dif, hnum)) + continue; + + if (!first) { + first = sk; + continue; } - } + nskb = skb_clone(skb, GFP_ATOMIC); - spin_unlock(&hslot->lock); + if (unlikely(!nskb)) { + atomic_inc(&sk->sk_drops); + UDP_INC_STATS_BH(net, UDP_MIB_RCVBUFERRORS, + IS_UDPLITE(sk)); + UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, + IS_UDPLITE(sk)); + continue; + } + if (udp_queue_rcv_skb(sk, nskb) > 0) + consume_skb(nskb); + } /* Also lookup *:port if we are using hash2 and haven't done so yet. */ if (use_hash2 && hash2 != hash2_any) { @@ -1791,16 +1719,13 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, goto start_lookup; } - /* - * do the slow work with no lock held - */ - if (count) { - flush_stack(stack, count, skb, count - 1); + if (first) { + if (udp_queue_rcv_skb(first, skb) > 0) + consume_skb(skb); } else { - if (!inner_flushed) - UDP_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, - proto == IPPROTO_UDPLITE); - consume_skb(skb); + kfree_skb(skb); + UDP_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, + proto == IPPROTO_UDPLITE); } return 0; } @@ -1897,7 +1822,6 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, inet_compute_pseudo); ret = udp_queue_rcv_skb(sk, skb); - sock_put(sk); /* a return value > 0 means to resubmit the input, but * it wants the return to be -protocol, or 0 @@ -1958,49 +1882,24 @@ static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net, int dif) { struct sock *sk, *result; - struct hlist_nulls_node *node; unsigned short hnum = ntohs(loc_port); - unsigned int count, slot = udp_hashfn(net, hnum, udp_table.mask); + unsigned int slot = udp_hashfn(net, hnum, udp_table.mask); struct udp_hslot *hslot = &udp_table.hash[slot]; /* Do not bother scanning a too big list */ if (hslot->count > 10) return NULL; - rcu_read_lock(); -begin: - count = 0; result = NULL; - sk_nulls_for_each_rcu(sk, node, &hslot->head) { - if (__udp_is_mcast_sock(net, sk, - loc_port, loc_addr, - rmt_port, rmt_addr, - dif, hnum)) { + sk_for_each_rcu(sk, &hslot->head) { + if (__udp_is_mcast_sock(net, sk, loc_port, loc_addr, + rmt_port, rmt_addr, dif, hnum)) { + if (result) + return NULL; result = sk; - ++count; - } - } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != slot) - goto begin; - - if (result) { - if (count != 1 || - unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) - result = NULL; - else if (unlikely(!__udp_is_mcast_sock(net, result, - loc_port, loc_addr, - rmt_port, rmt_addr, - dif, hnum))) { - sock_put(result); - result = NULL; } } - rcu_read_unlock(); + return result; } @@ -2013,37 +1912,22 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net, __be16 rmt_port, __be32 rmt_addr, int dif) { - struct sock *sk, *result; - struct hlist_nulls_node *node; unsigned short hnum = ntohs(loc_port); unsigned int hash2 = udp4_portaddr_hash(net, loc_addr, hnum); unsigned int slot2 = hash2 & udp_table.mask; struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; INET_ADDR_COOKIE(acookie, rmt_addr, loc_addr); const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); + struct sock *sk; - rcu_read_lock(); - result = NULL; - udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) { - if (INET_MATCH(sk, net, acookie, - rmt_addr, loc_addr, ports, dif)) - result = sk; + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { + if (INET_MATCH(sk, net, acookie, rmt_addr, + loc_addr, ports, dif)) + return sk; /* Only check first socket in chain */ break; } - - if (result) { - if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) - result = NULL; - else if (unlikely(!INET_MATCH(sk, net, acookie, - rmt_addr, loc_addr, - ports, dif))) { - sock_put(result); - result = NULL; - } - } - rcu_read_unlock(); - return result; + return NULL; } void udp_v4_early_demux(struct sk_buff *skb) @@ -2051,7 +1935,7 @@ void udp_v4_early_demux(struct sk_buff *skb) struct net *net = dev_net(skb->dev); const struct iphdr *iph; const struct udphdr *uh; - struct sock *sk; + struct sock *sk = NULL; struct dst_entry *dst; int dif = skb->dev->ifindex; int ours; @@ -2083,11 +1967,9 @@ void udp_v4_early_demux(struct sk_buff *skb) } else if (skb->pkt_type == PACKET_HOST) { sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, uh->source, iph->saddr, dif); - } else { - return; } - if (!sk) + if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2)) return; skb->sk = sk; @@ -2387,14 +2269,13 @@ static struct sock *udp_get_first(struct seq_file *seq, int start) for (state->bucket = start; state->bucket <= state->udp_table->mask; ++state->bucket) { - struct hlist_nulls_node *node; struct udp_hslot *hslot = &state->udp_table->hash[state->bucket]; - if (hlist_nulls_empty(&hslot->head)) + if (hlist_empty(&hslot->head)) continue; spin_lock_bh(&hslot->lock); - sk_nulls_for_each(sk, node, &hslot->head) { + sk_for_each(sk, &hslot->head) { if (!net_eq(sock_net(sk), net)) continue; if (sk->sk_family == state->family) @@ -2413,7 +2294,7 @@ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) struct net *net = seq_file_net(seq); do { - sk = sk_nulls_next(sk); + sk = sk_next(sk); } while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family)); if (!sk) { @@ -2622,12 +2503,12 @@ void __init udp_table_init(struct udp_table *table, const char *name) table->hash2 = table->hash + (table->mask + 1); for (i = 0; i <= table->mask; i++) { - INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i); + INIT_HLIST_HEAD(&table->hash[i].head); table->hash[i].count = 0; spin_lock_init(&table->hash[i].lock); } for (i = 0; i <= table->mask; i++) { - INIT_HLIST_NULLS_HEAD(&table->hash2[i].head, i); + INIT_HLIST_HEAD(&table->hash2[i].head); table->hash2[i].count = 0; spin_lock_init(&table->hash2[i].lock); } diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index df1966f3b6ec..3d5ccf4b1412 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c @@ -36,10 +36,11 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, const struct inet_diag_req_v2 *req) { int err = -EINVAL; - struct sock *sk; + struct sock *sk = NULL; struct sk_buff *rep; struct net *net = sock_net(in_skb->sk); + rcu_read_lock(); if (req->sdiag_family == AF_INET) sk = __udp4_lib_lookup(net, req->id.idiag_src[0], req->id.idiag_sport, @@ -54,9 +55,9 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, req->id.idiag_dport, req->id.idiag_if, tbl, NULL); #endif - else - goto out_nosk; - + if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) + sk = NULL; + rcu_read_unlock(); err = -ENOENT; if (!sk) goto out_nosk; @@ -96,24 +97,23 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb, const struct inet_diag_req_v2 *r, struct nlattr *bc) { - int num, s_num, slot, s_slot; struct net *net = sock_net(skb->sk); + int num, s_num, slot, s_slot; s_slot = cb->args[0]; num = s_num = cb->args[1]; for (slot = s_slot; slot <= table->mask; s_num = 0, slot++) { - struct sock *sk; - struct hlist_nulls_node *node; struct udp_hslot *hslot = &table->hash[slot]; + struct sock *sk; num = 0; - if (hlist_nulls_empty(&hslot->head)) + if (hlist_empty(&hslot->head)) continue; spin_lock_bh(&hslot->lock); - sk_nulls_for_each(sk, node, &hslot->head) { + sk_for_each(sk, &hslot->head) { struct inet_sock *inet = inet_sk(sk); if (!net_eq(sock_net(sk), net)) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b772a7641fbd..78a7dfd12707 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -213,37 +213,28 @@ static struct sock *udp6_lib_lookup2(struct net *net, struct sk_buff *skb) { struct sock *sk, *result; - struct hlist_nulls_node *node; int score, badness, matches = 0, reuseport = 0; - bool select_ok = true; u32 hash = 0; -begin: result = NULL; badness = -1; - udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) { + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { score = compute_score2(sk, net, saddr, sport, daddr, hnum, dif); if (score > badness) { - result = sk; - badness = score; reuseport = sk->sk_reuseport; if (reuseport) { hash = udp6_ehashfn(net, daddr, hnum, saddr, sport); - if (select_ok) { - struct sock *sk2; - sk2 = reuseport_select_sock(sk, hash, skb, + result = reuseport_select_sock(sk, hash, skb, sizeof(struct udphdr)); - if (sk2) { - result = sk2; - select_ok = false; - goto found; - } - } + if (result) + return result; matches = 1; } + result = sk; + badness = score; } else if (score == badness && reuseport) { matches++; if (reciprocal_scale(hash, matches) == 0) @@ -251,27 +242,10 @@ static struct sock *udp6_lib_lookup2(struct net *net, hash = next_pseudo_random32(hash); } } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != slot2) - goto begin; - - if (result) { -found: - if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) - result = NULL; - else if (unlikely(compute_score2(result, net, saddr, sport, - daddr, hnum, dif) < badness)) { - sock_put(result); - goto begin; - } - } return result; } +/* rcu_read_lock() must be held */ struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, @@ -279,15 +253,12 @@ struct sock *__udp6_lib_lookup(struct net *net, struct sk_buff *skb) { struct sock *sk, *result; - struct hlist_nulls_node *node; unsigned short hnum = ntohs(dport); unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; int score, badness, matches = 0, reuseport = 0; - bool select_ok = true; u32 hash = 0; - rcu_read_lock(); if (hslot->count > 10) { hash2 = udp6_portaddr_hash(net, daddr, hnum); slot2 = hash2 & udptable->mask; @@ -309,34 +280,26 @@ struct sock *__udp6_lib_lookup(struct net *net, &in6addr_any, hnum, dif, hslot2, slot2, skb); } - rcu_read_unlock(); return result; } begin: result = NULL; badness = -1; - sk_nulls_for_each_rcu(sk, node, &hslot->head) { + sk_for_each_rcu(sk, &hslot->head) { score = compute_score(sk, net, hnum, saddr, sport, daddr, dport, dif); if (score > badness) { - result = sk; - badness = score; reuseport = sk->sk_reuseport; if (reuseport) { hash = udp6_ehashfn(net, daddr, hnum, saddr, sport); - if (select_ok) { - struct sock *sk2; - - sk2 = reuseport_select_sock(sk, hash, skb, + result = reuseport_select_sock(sk, hash, skb, sizeof(struct udphdr)); - if (sk2) { - result = sk2; - select_ok = false; - goto found; - } - } + if (result) + return result; matches = 1; } + result = sk; + badness = score; } else if (score == badness && reuseport) { matches++; if (reciprocal_scale(hash, matches) == 0) @@ -344,25 +307,6 @@ struct sock *__udp6_lib_lookup(struct net *net, hash = next_pseudo_random32(hash); } } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != slot) - goto begin; - - if (result) { -found: - if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) - result = NULL; - else if (unlikely(compute_score(result, net, hnum, saddr, sport, - daddr, dport, dif) < badness)) { - sock_put(result); - goto begin; - } - } - rcu_read_unlock(); return result; } EXPORT_SYMBOL_GPL(__udp6_lib_lookup); @@ -382,12 +326,24 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, udptable, skb); } +/* Must be called under rcu_read_lock(). + * Does increment socket refcount. + */ +#if IS_ENABLED(CONFIG_NETFILTER_XT_MATCH_SOCKET) || \ + IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY) struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, int dif) { - return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table, NULL); + struct sock *sk; + + sk = __udp6_lib_lookup(net, saddr, sport, daddr, dport, + dif, &udp_table, NULL); + if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) + sk = NULL; + return sk; } EXPORT_SYMBOL_GPL(udp6_lib_lookup); +#endif /* * This should be easy, if there is something there we @@ -585,7 +541,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, sk->sk_err = err; sk->sk_error_report(sk); out: - sock_put(sk); + return; } static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) @@ -747,33 +703,6 @@ static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk, return true; } -static void flush_stack(struct sock **stack, unsigned int count, - struct sk_buff *skb, unsigned int final) -{ - struct sk_buff *skb1 = NULL; - struct sock *sk; - unsigned int i; - - for (i = 0; i < count; i++) { - sk = stack[i]; - if (likely(!skb1)) - skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); - if (!skb1) { - atomic_inc(&sk->sk_drops); - UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, - IS_UDPLITE(sk)); - UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, - IS_UDPLITE(sk)); - } - - if (skb1 && udpv6_queue_rcv_skb(sk, skb1) <= 0) - skb1 = NULL; - sock_put(sk); - } - if (unlikely(skb1)) - kfree_skb(skb1); -} - static void udp6_csum_zero_error(struct sk_buff *skb) { /* RFC 2460 section 8.1 says that we SHOULD log @@ -792,15 +721,15 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, const struct in6_addr *saddr, const struct in6_addr *daddr, struct udp_table *udptable, int proto) { - struct sock *sk, *stack[256 / sizeof(struct sock *)]; + struct sock *sk, *first = NULL; const struct udphdr *uh = udp_hdr(skb); - struct hlist_nulls_node *node; unsigned short hnum = ntohs(uh->dest); struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum); - int dif = inet6_iif(skb); - unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); + unsigned int offset = offsetof(typeof(*sk), sk_node); unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); - bool inner_flushed = false; + int dif = inet6_iif(skb); + struct hlist_node *node; + struct sk_buff *nskb; if (use_hash2) { hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) & @@ -811,27 +740,32 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); } - spin_lock(&hslot->lock); - sk_nulls_for_each_entry_offset(sk, node, &hslot->head, offset) { - if (__udp_v6_is_mcast_sock(net, sk, - uh->dest, daddr, - uh->source, saddr, - dif, hnum) && - /* If zero checksum and no_check is not on for - * the socket then skip it. - */ - (uh->check || udp_sk(sk)->no_check6_rx)) { - if (unlikely(count == ARRAY_SIZE(stack))) { - flush_stack(stack, count, skb, ~0); - inner_flushed = true; - count = 0; - } - stack[count++] = sk; - sock_hold(sk); + sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) { + if (!__udp_v6_is_mcast_sock(net, sk, uh->dest, daddr, + uh->source, saddr, dif, hnum)) + continue; + /* If zero checksum and no_check is not on for + * the socket then skip it. + */ + if (!uh->check && !udp_sk(sk)->no_check6_rx) + continue; + if (!first) { + first = sk; + continue; + } + nskb = skb_clone(skb, GFP_ATOMIC); + if (unlikely(!nskb)) { + atomic_inc(&sk->sk_drops); + UDP6_INC_STATS_BH(net, UDP_MIB_RCVBUFERRORS, + IS_UDPLITE(sk)); + UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, + IS_UDPLITE(sk)); + continue; } - } - spin_unlock(&hslot->lock); + if (udpv6_queue_rcv_skb(sk, nskb) > 0) + consume_skb(nskb); + } /* Also lookup *:port if we are using hash2 and haven't done so yet. */ if (use_hash2 && hash2 != hash2_any) { @@ -839,13 +773,13 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, goto start_lookup; } - if (count) { - flush_stack(stack, count, skb, count - 1); + if (first) { + if (udpv6_queue_rcv_skb(first, skb) > 0) + consume_skb(skb); } else { - if (!inner_flushed) - UDP6_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, - proto == IPPROTO_UDPLITE); - consume_skb(skb); + kfree_skb(skb); + UDP6_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, + proto == IPPROTO_UDPLITE); } return 0; } @@ -853,10 +787,10 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, int proto) { + const struct in6_addr *saddr, *daddr; struct net *net = dev_net(skb->dev); - struct sock *sk; struct udphdr *uh; - const struct in6_addr *saddr, *daddr; + struct sock *sk; u32 ulen = 0; if (!pskb_may_pull(skb, sizeof(struct udphdr))) @@ -910,7 +844,6 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, int ret; if (!uh->check && !udp_sk(sk)->no_check6_rx) { - sock_put(sk); udp6_csum_zero_error(skb); goto csum_error; } @@ -920,7 +853,6 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, ip6_compute_pseudo); ret = udpv6_queue_rcv_skb(sk, skb); - sock_put(sk); /* a return value > 0 means to resubmit the input */ if (ret > 0) -- GitLab From ee3cf32a4a5e6cf5ccc0f0de9865fda3ebc46436 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:14 -0700 Subject: [PATCH 1299/9938] tcp/dccp: remove BH disable/enable in lookup Since linux 2.6.29, lookups only use rcu locking. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/inet_hashtables.h | 7 +------ net/ipv6/inet6_hashtables.c | 2 -- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 50f635c2c536..a77acee93aaf 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -280,11 +280,8 @@ static inline struct sock *inet_lookup_listener(struct net *net, net_eq(sock_net(__sk), (__net))) #endif /* 64-bit arch */ -/* - * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need +/* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need * not check it for lookups anymore, thanks Alexey. -DaveM - * - * Local BH must be disabled here. */ struct sock *__inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, @@ -326,10 +323,8 @@ static inline struct sock *inet_lookup(struct net *net, { struct sock *sk; - local_bh_disable(); sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, dport, dif); - local_bh_enable(); return sk; } diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 70f2628be6fa..d253f32874c9 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -200,10 +200,8 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, { struct sock *sk; - local_bh_disable(); sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, ntohs(dport), dif); - local_bh_enable(); return sk; } -- GitLab From 2d331915a04144dad738e725769d8fac06ef6155 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:15 -0700 Subject: [PATCH 1300/9938] tcp/dccp: use rcu locking in inet_diag_find_one_icsk() RX packet processing holds rcu_read_lock(), so we can remove pairs of rcu_read_lock()/rcu_read_unlock() in lookup functions if inet_diag also holds rcu before calling them. This is needed anyway as __inet_lookup_listener() and inet6_lookup_listener() will soon no longer increment refcount on the found listener. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 7 +++++-- net/ipv4/inet_hashtables.c | 4 ---- net/ipv6/inet6_hashtables.c | 4 ---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 5fdb02f5598e..ea8df527b279 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -356,6 +356,7 @@ struct sock *inet_diag_find_one_icsk(struct net *net, { struct sock *sk; + rcu_read_lock(); if (req->sdiag_family == AF_INET) sk = inet_lookup(net, hashinfo, NULL, 0, req->id.idiag_dst[0], req->id.idiag_dport, req->id.idiag_src[0], @@ -376,9 +377,11 @@ struct sock *inet_diag_find_one_icsk(struct net *net, req->id.idiag_if); } #endif - else + else { + rcu_read_unlock(); return ERR_PTR(-EINVAL); - + } + rcu_read_unlock(); if (!sk) return ERR_PTR(-ENOENT); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index bc68eced0105..387338d71dcd 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -220,7 +220,6 @@ struct sock *__inet_lookup_listener(struct net *net, bool select_ok = true; u32 phash = 0; - rcu_read_lock(); begin: result = NULL; hiscore = 0; @@ -269,7 +268,6 @@ struct sock *__inet_lookup_listener(struct net *net, goto begin; } } - rcu_read_unlock(); return result; } EXPORT_SYMBOL_GPL(__inet_lookup_listener); @@ -312,7 +310,6 @@ struct sock *__inet_lookup_established(struct net *net, unsigned int slot = hash & hashinfo->ehash_mask; struct inet_ehash_bucket *head = &hashinfo->ehash[slot]; - rcu_read_lock(); begin: sk_nulls_for_each_rcu(sk, node, &head->chain) { if (sk->sk_hash != hash) @@ -339,7 +336,6 @@ struct sock *__inet_lookup_established(struct net *net, out: sk = NULL; found: - rcu_read_unlock(); return sk; } EXPORT_SYMBOL_GPL(__inet_lookup_established); diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index d253f32874c9..e6ef6ce1ed74 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -69,7 +69,6 @@ struct sock *__inet6_lookup_established(struct net *net, struct inet_ehash_bucket *head = &hashinfo->ehash[slot]; - rcu_read_lock(); begin: sk_nulls_for_each_rcu(sk, node, &head->chain) { if (sk->sk_hash != hash) @@ -90,7 +89,6 @@ struct sock *__inet6_lookup_established(struct net *net, out: sk = NULL; found: - rcu_read_unlock(); return sk; } EXPORT_SYMBOL(__inet6_lookup_established); @@ -138,7 +136,6 @@ struct sock *inet6_lookup_listener(struct net *net, unsigned int hash = inet_lhashfn(net, hnum); struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash]; - rcu_read_lock(); begin: result = NULL; hiscore = 0; @@ -187,7 +184,6 @@ struct sock *inet6_lookup_listener(struct net *net, goto begin; } } - rcu_read_unlock(); return result; } EXPORT_SYMBOL_GPL(inet6_lookup_listener); -- GitLab From 3a5d1c0e7cb5ba91aabbd7e28626e3cc925f8093 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:16 -0700 Subject: [PATCH 1301/9938] inet: reqsk_alloc() needs to take care of dead listeners We'll soon no longer take a refcount on listeners, so reqsk_alloc() can not assume a listener refcount is not zero. We need to use atomic_inc_not_zero() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/request_sock.h | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/include/net/request_sock.h b/include/net/request_sock.h index f49759decb28..6ebe13eb1c4c 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -85,24 +85,23 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener, struct request_sock *req; req = kmem_cache_alloc(ops->slab, GFP_ATOMIC | __GFP_NOWARN); - - if (req) { - req->rsk_ops = ops; - if (attach_listener) { - sock_hold(sk_listener); - req->rsk_listener = sk_listener; - } else { - req->rsk_listener = NULL; + if (!req) + return NULL; + req->rsk_listener = NULL; + if (attach_listener) { + if (unlikely(!atomic_inc_not_zero(&sk_listener->sk_refcnt))) { + kmem_cache_free(ops->slab, req); + return NULL; } - req_to_sk(req)->sk_prot = sk_listener->sk_prot; - sk_node_init(&req_to_sk(req)->sk_node); - sk_tx_queue_clear(req_to_sk(req)); - req->saved_syn = NULL; - /* Following is temporary. It is coupled with debugging - * helpers in reqsk_put() & reqsk_free() - */ - atomic_set(&req->rsk_refcnt, 0); + req->rsk_listener = sk_listener; } + req->rsk_ops = ops; + req_to_sk(req)->sk_prot = sk_listener->sk_prot; + sk_node_init(&req_to_sk(req)->sk_node); + sk_tx_queue_clear(req_to_sk(req)); + req->saved_syn = NULL; + atomic_set(&req->rsk_refcnt, 0); + return req; } -- GitLab From 3b24d854cb35383c30642116e5992fd619bdc9bc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:17 -0700 Subject: [PATCH 1302/9938] tcp/dccp: do not touch listener sk_refcnt under synflood When a SYNFLOOD targets a non SO_REUSEPORT listener, multiple cpus contend on sk->sk_refcnt and sk->sk_wmem_alloc changes. By letting listeners use SOCK_RCU_FREE infrastructure, we can relax TCP_LISTEN lookup rules and avoid touching sk_refcnt Note that we still use SLAB_DESTROY_BY_RCU rules for other sockets, only listeners are impacted by this change. Peak performance under SYNFLOOD is increased by ~33% : On my test machine, I could process 3.2 Mpps instead of 2.4 Mpps Most consuming functions are now skb_set_owner_w() and sock_wfree() contending on sk->sk_wmem_alloc when cooking SYNACK and freeing them. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/inet6_hashtables.h | 12 ++++-- include/net/inet_hashtables.h | 40 +++++++++++-------- net/dccp/ipv4.c | 7 +++- net/dccp/ipv6.c | 7 +++- net/ipv4/inet_diag.c | 3 +- net/ipv4/inet_hashtables.c | 73 ++++++++++++---------------------- net/ipv4/tcp_ipv4.c | 66 +++++++++++++++--------------- net/ipv6/inet6_hashtables.c | 56 +++++++------------------- net/ipv6/tcp_ipv6.c | 27 +++++++------ net/netfilter/xt_socket.c | 6 +-- 10 files changed, 134 insertions(+), 163 deletions(-) diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 28332bdac333..b87becacd9d3 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -66,13 +66,15 @@ static inline struct sock *__inet6_lookup(struct net *net, const __be16 sport, const struct in6_addr *daddr, const u16 hnum, - const int dif) + const int dif, + bool *refcounted) { struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr, sport, daddr, hnum, dif); + *refcounted = true; if (sk) return sk; - + *refcounted = false; return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport, daddr, hnum, dif); } @@ -81,17 +83,19 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, const __be16 sport, const __be16 dport, - int iif) + int iif, + bool *refcounted) { struct sock *sk = skb_steal_sock(skb); + *refcounted = true; if (sk) return sk; return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, doff, &ipv6_hdr(skb)->saddr, sport, &ipv6_hdr(skb)->daddr, ntohs(dport), - iif); + iif, refcounted); } struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index a77acee93aaf..0574493e3899 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -100,14 +100,10 @@ struct inet_bind_hashbucket { /* * Sockets can be hashed in established or listening table - * We must use different 'nulls' end-of-chain value for listening - * hash table, or we might find a socket that was closed and - * reallocated/inserted into established hash table */ -#define LISTENING_NULLS_BASE (1U << 29) struct inet_listen_hashbucket { spinlock_t lock; - struct hlist_nulls_head head; + struct hlist_head head; }; /* This is for listening sockets, thus all sockets which possess wildcards. */ @@ -304,14 +300,20 @@ static inline struct sock *__inet_lookup(struct net *net, struct sk_buff *skb, int doff, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, - const int dif) + const int dif, + bool *refcounted) { u16 hnum = ntohs(dport); - struct sock *sk = __inet_lookup_established(net, hashinfo, - saddr, sport, daddr, hnum, dif); + struct sock *sk; - return sk ? : __inet_lookup_listener(net, hashinfo, skb, doff, saddr, - sport, daddr, hnum, dif); + sk = __inet_lookup_established(net, hashinfo, saddr, sport, + daddr, hnum, dif); + *refcounted = true; + if (sk) + return sk; + *refcounted = false; + return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, + sport, daddr, hnum, dif); } static inline struct sock *inet_lookup(struct net *net, @@ -322,10 +324,13 @@ static inline struct sock *inet_lookup(struct net *net, const int dif) { struct sock *sk; + bool refcounted; sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, - dport, dif); + dport, dif, &refcounted); + if (sk && !refcounted && !atomic_inc_not_zero(&sk->sk_refcnt)) + sk = NULL; return sk; } @@ -333,17 +338,20 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, const __be16 sport, - const __be16 dport) + const __be16 dport, + bool *refcounted) { struct sock *sk = skb_steal_sock(skb); const struct iphdr *iph = ip_hdr(skb); + *refcounted = true; if (sk) return sk; - else - return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, - doff, iph->saddr, sport, - iph->daddr, dport, inet_iif(skb)); + + return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, + doff, iph->saddr, sport, + iph->daddr, dport, inet_iif(skb), + refcounted); } u32 sk_ehashfn(const struct sock *sk); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 9c67a961ba53..6438c5a7efc4 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -764,6 +764,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) { const struct dccp_hdr *dh; const struct iphdr *iph; + bool refcounted; struct sock *sk; int min_cov; @@ -801,7 +802,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) lookup: sk = __inet_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh), - dh->dccph_sport, dh->dccph_dport); + dh->dccph_sport, dh->dccph_dport, &refcounted); if (!sk) { dccp_pr_debug("failed to look up flow ID in table and " "get corresponding socket\n"); @@ -830,6 +831,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) goto lookup; } sock_hold(sk); + refcounted = true; nsk = dccp_check_req(sk, skb, req); if (!nsk) { reqsk_put(req); @@ -886,7 +888,8 @@ static int dccp_v4_rcv(struct sk_buff *skb) return 0; discard_and_relse: - sock_put(sk); + if (refcounted) + sock_put(sk); goto discard_it; } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 4663a01d5039..71bf1deba4c5 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -642,6 +642,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) static int dccp_v6_rcv(struct sk_buff *skb) { const struct dccp_hdr *dh; + bool refcounted; struct sock *sk; int min_cov; @@ -670,7 +671,7 @@ static int dccp_v6_rcv(struct sk_buff *skb) lookup: sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh), dh->dccph_sport, dh->dccph_dport, - inet6_iif(skb)); + inet6_iif(skb), &refcounted); if (!sk) { dccp_pr_debug("failed to look up flow ID in table and " "get corresponding socket\n"); @@ -699,6 +700,7 @@ static int dccp_v6_rcv(struct sk_buff *skb) goto lookup; } sock_hold(sk); + refcounted = true; nsk = dccp_check_req(sk, skb, req); if (!nsk) { reqsk_put(req); @@ -752,7 +754,8 @@ static int dccp_v6_rcv(struct sk_buff *skb) return 0; discard_and_relse: - sock_put(sk); + if (refcounted) + sock_put(sk); goto discard_it; } diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index ea8df527b279..bd591eb81ec9 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -775,13 +775,12 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, for (i = s_i; i < INET_LHTABLE_SIZE; i++) { struct inet_listen_hashbucket *ilb; - struct hlist_nulls_node *node; struct sock *sk; num = 0; ilb = &hashinfo->listening_hash[i]; spin_lock_bh(&ilb->lock); - sk_nulls_for_each(sk, node, &ilb->head) { + sk_for_each(sk, &ilb->head) { struct inet_sock *inet = inet_sk(sk); if (!net_eq(sock_net(sk), net)) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 387338d71dcd..98ba03b6f87d 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -198,13 +198,13 @@ static inline int compute_score(struct sock *sk, struct net *net, } /* - * Don't inline this cruft. Here are some nice properties to exploit here. The - * BSD API does not allow a listening sock to specify the remote port nor the + * Here are some nice properties to exploit here. The BSD API + * does not allow a listening sock to specify the remote port nor the * remote address for the connection. So always assume those are both * wildcarded during the search since they can never be otherwise. */ - +/* called with rcu_read_lock() : No refcount taken on the socket */ struct sock *__inet_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, @@ -212,37 +212,27 @@ struct sock *__inet_lookup_listener(struct net *net, const __be32 daddr, const unsigned short hnum, const int dif) { - struct sock *sk, *result; - struct hlist_nulls_node *node; unsigned int hash = inet_lhashfn(net, hnum); struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash]; - int score, hiscore, matches = 0, reuseport = 0; - bool select_ok = true; + int score, hiscore = 0, matches = 0, reuseport = 0; + struct sock *sk, *result = NULL; u32 phash = 0; -begin: - result = NULL; - hiscore = 0; - sk_nulls_for_each_rcu(sk, node, &ilb->head) { + sk_for_each_rcu(sk, &ilb->head) { score = compute_score(sk, net, hnum, daddr, dif); if (score > hiscore) { - result = sk; - hiscore = score; reuseport = sk->sk_reuseport; if (reuseport) { phash = inet_ehashfn(net, daddr, hnum, saddr, sport); - if (select_ok) { - struct sock *sk2; - sk2 = reuseport_select_sock(sk, phash, - skb, doff); - if (sk2) { - result = sk2; - goto found; - } - } + result = reuseport_select_sock(sk, phash, + skb, doff); + if (result) + return result; matches = 1; } + result = sk; + hiscore = score; } else if (score == hiscore && reuseport) { matches++; if (reciprocal_scale(phash, matches) == 0) @@ -250,24 +240,6 @@ struct sock *__inet_lookup_listener(struct net *net, phash = next_pseudo_random32(phash); } } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != hash + LISTENING_NULLS_BASE) - goto begin; - if (result) { -found: - if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) - result = NULL; - else if (unlikely(compute_score(result, net, hnum, daddr, - dif) < hiscore)) { - sock_put(result); - select_ok = false; - goto begin; - } - } return result; } EXPORT_SYMBOL_GPL(__inet_lookup_listener); @@ -508,7 +480,8 @@ int __inet_hash(struct sock *sk, struct sock *osk, if (err) goto unlock; } - __sk_nulls_add_node_rcu(sk, &ilb->head); + hlist_add_head_rcu(&sk->sk_node, &ilb->head); + sock_set_flag(sk, SOCK_RCU_FREE); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); unlock: spin_unlock(&ilb->lock); @@ -535,20 +508,25 @@ void inet_unhash(struct sock *sk) { struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; spinlock_t *lock; + bool listener = false; int done; if (sk_unhashed(sk)) return; - if (sk->sk_state == TCP_LISTEN) + if (sk->sk_state == TCP_LISTEN) { lock = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)].lock; - else + listener = true; + } else { lock = inet_ehash_lockp(hashinfo, sk->sk_hash); - + } spin_lock_bh(lock); if (rcu_access_pointer(sk->sk_reuseport_cb)) reuseport_detach_sock(sk); - done = __sk_nulls_del_node_init_rcu(sk); + if (listener) + done = __sk_del_node_init(sk); + else + done = __sk_nulls_del_node_init_rcu(sk); if (done) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); spin_unlock_bh(lock); @@ -684,9 +662,8 @@ void inet_hashinfo_init(struct inet_hashinfo *h) for (i = 0; i < INET_LHTABLE_SIZE; i++) { spin_lock_init(&h->listening_hash[i].lock); - INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].head, - i + LISTENING_NULLS_BASE); - } + INIT_HLIST_HEAD(&h->listening_hash[i].head); + } } EXPORT_SYMBOL_GPL(inet_hashinfo_init); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ad450509029b..e5f924b29946 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -628,6 +628,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev); #ifdef CONFIG_TCP_MD5SIG + rcu_read_lock(); hash_location = tcp_parse_md5sig_option(th); if (sk && sk_fullsock(sk)) { key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *) @@ -646,16 +647,18 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) ntohs(th->source), inet_iif(skb)); /* don't send rst if it can't find key */ if (!sk1) - return; - rcu_read_lock(); + goto out; + key = tcp_md5_do_lookup(sk1, (union tcp_md5_addr *) &ip_hdr(skb)->saddr, AF_INET); if (!key) - goto release_sk1; + goto out; + genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, skb); if (genhash || memcmp(hash_location, newhash, 16) != 0) - goto release_sk1; + goto out; + } if (key) { @@ -698,11 +701,8 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); #ifdef CONFIG_TCP_MD5SIG -release_sk1: - if (sk1) { - rcu_read_unlock(); - sock_put(sk1); - } +out: + rcu_read_unlock(); #endif } @@ -1538,11 +1538,12 @@ EXPORT_SYMBOL(tcp_prequeue); int tcp_v4_rcv(struct sk_buff *skb) { + struct net *net = dev_net(skb->dev); const struct iphdr *iph; const struct tcphdr *th; + bool refcounted; struct sock *sk; int ret; - struct net *net = dev_net(skb->dev); if (skb->pkt_type != PACKET_HOST) goto discard_it; @@ -1588,7 +1589,7 @@ int tcp_v4_rcv(struct sk_buff *skb) lookup: sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source, - th->dest); + th->dest, &refcounted); if (!sk) goto no_tcp_socket; @@ -1609,7 +1610,11 @@ int tcp_v4_rcv(struct sk_buff *skb) inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; } + /* We own a reference on the listener, increase it again + * as we might lose it too soon. + */ sock_hold(sk); + refcounted = true; nsk = tcp_check_req(sk, skb, req, false); if (!nsk) { reqsk_put(req); @@ -1665,7 +1670,8 @@ int tcp_v4_rcv(struct sk_buff *skb) bh_unlock_sock(sk); put_and_return: - sock_put(sk); + if (refcounted) + sock_put(sk); return ret; @@ -1688,7 +1694,8 @@ int tcp_v4_rcv(struct sk_buff *skb) return 0; discard_and_relse: - sock_put(sk); + if (refcounted) + sock_put(sk); goto discard_it; do_time_wait: @@ -1712,6 +1719,7 @@ int tcp_v4_rcv(struct sk_buff *skb) if (sk2) { inet_twsk_deschedule_put(inet_twsk(sk)); sk = sk2; + refcounted = false; goto process; } /* Fall through to ACK */ @@ -1845,17 +1853,17 @@ EXPORT_SYMBOL(tcp_v4_destroy_sock); */ static void *listening_get_next(struct seq_file *seq, void *cur) { - struct inet_connection_sock *icsk; - struct hlist_nulls_node *node; - struct sock *sk = cur; - struct inet_listen_hashbucket *ilb; struct tcp_iter_state *st = seq->private; struct net *net = seq_file_net(seq); + struct inet_listen_hashbucket *ilb; + struct inet_connection_sock *icsk; + struct sock *sk = cur; if (!sk) { +get_head: ilb = &tcp_hashinfo.listening_hash[st->bucket]; spin_lock_bh(&ilb->lock); - sk = sk_nulls_head(&ilb->head); + sk = sk_head(&ilb->head); st->offset = 0; goto get_sk; } @@ -1863,28 +1871,20 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ++st->num; ++st->offset; - sk = sk_nulls_next(sk); + sk = sk_next(sk); get_sk: - sk_nulls_for_each_from(sk, node) { + sk_for_each_from(sk) { if (!net_eq(sock_net(sk), net)) continue; - if (sk->sk_family == st->family) { - cur = sk; - goto out; - } + if (sk->sk_family == st->family) + return sk; icsk = inet_csk(sk); } spin_unlock_bh(&ilb->lock); st->offset = 0; - if (++st->bucket < INET_LHTABLE_SIZE) { - ilb = &tcp_hashinfo.listening_hash[st->bucket]; - spin_lock_bh(&ilb->lock); - sk = sk_nulls_head(&ilb->head); - goto get_sk; - } - cur = NULL; -out: - return cur; + if (++st->bucket < INET_LHTABLE_SIZE) + goto get_head; + return NULL; } static void *listening_get_idx(struct seq_file *seq, loff_t *pos) diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index e6ef6ce1ed74..607da088344d 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -120,6 +120,7 @@ static inline int compute_score(struct sock *sk, struct net *net, return score; } +/* called with rcu_read_lock() */ struct sock *inet6_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, struct sk_buff *skb, int doff, @@ -127,38 +128,27 @@ struct sock *inet6_lookup_listener(struct net *net, const __be16 sport, const struct in6_addr *daddr, const unsigned short hnum, const int dif) { - struct sock *sk; - const struct hlist_nulls_node *node; - struct sock *result; - int score, hiscore, matches = 0, reuseport = 0; - bool select_ok = true; - u32 phash = 0; unsigned int hash = inet_lhashfn(net, hnum); struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash]; + int score, hiscore = 0, matches = 0, reuseport = 0; + struct sock *sk, *result = NULL; + u32 phash = 0; -begin: - result = NULL; - hiscore = 0; - sk_nulls_for_each(sk, node, &ilb->head) { + sk_for_each(sk, &ilb->head) { score = compute_score(sk, net, hnum, daddr, dif); if (score > hiscore) { hiscore = score; - result = sk; - reuseport = sk->sk_reuseport; if (reuseport) { phash = inet6_ehashfn(net, daddr, hnum, saddr, sport); - if (select_ok) { - struct sock *sk2; - sk2 = reuseport_select_sock(sk, phash, - skb, doff); - if (sk2) { - result = sk2; - goto found; - } - } + result = reuseport_select_sock(sk, phash, + skb, doff); + if (result) + return result; matches = 1; } + result = sk; + reuseport = sk->sk_reuseport; } else if (score == hiscore && reuseport) { matches++; if (reciprocal_scale(phash, matches) == 0) @@ -166,24 +156,6 @@ struct sock *inet6_lookup_listener(struct net *net, phash = next_pseudo_random32(phash); } } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != hash + LISTENING_NULLS_BASE) - goto begin; - if (result) { -found: - if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) - result = NULL; - else if (unlikely(compute_score(result, net, hnum, daddr, - dif) < hiscore)) { - sock_put(result); - select_ok = false; - goto begin; - } - } return result; } EXPORT_SYMBOL_GPL(inet6_lookup_listener); @@ -195,10 +167,12 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, const int dif) { struct sock *sk; + bool refcounted; sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, - ntohs(dport), dif); - + ntohs(dport), dif, &refcounted); + if (sk && !refcounted && !atomic_inc_not_zero(&sk->sk_refcnt)) + sk = NULL; return sk; } EXPORT_SYMBOL_GPL(inet6_lookup); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 711d209f9124..f0422e782731 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -858,6 +858,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) return; #ifdef CONFIG_TCP_MD5SIG + rcu_read_lock(); hash_location = tcp_parse_md5sig_option(th); if (sk && sk_fullsock(sk)) { key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr); @@ -875,16 +876,15 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) th->source, &ipv6h->daddr, ntohs(th->source), tcp_v6_iif(skb)); if (!sk1) - return; + goto out; - rcu_read_lock(); key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr); if (!key) - goto release_sk1; + goto out; genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb); if (genhash || memcmp(hash_location, newhash, 16) != 0) - goto release_sk1; + goto out; } #endif @@ -898,11 +898,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0); #ifdef CONFIG_TCP_MD5SIG -release_sk1: - if (sk1) { - rcu_read_unlock(); - sock_put(sk1); - } +out: + rcu_read_unlock(); #endif } @@ -1351,6 +1348,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) { const struct tcphdr *th; const struct ipv6hdr *hdr; + bool refcounted; struct sock *sk; int ret; struct net *net = dev_net(skb->dev); @@ -1381,7 +1379,8 @@ static int tcp_v6_rcv(struct sk_buff *skb) lookup: sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), - th->source, th->dest, inet6_iif(skb)); + th->source, th->dest, inet6_iif(skb), + &refcounted); if (!sk) goto no_tcp_socket; @@ -1404,6 +1403,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) goto lookup; } sock_hold(sk); + refcounted = true; nsk = tcp_check_req(sk, skb, req, false); if (!nsk) { reqsk_put(req); @@ -1460,7 +1460,8 @@ static int tcp_v6_rcv(struct sk_buff *skb) bh_unlock_sock(sk); put_and_return: - sock_put(sk); + if (refcounted) + sock_put(sk); return ret ? -1 : 0; no_tcp_socket: @@ -1483,7 +1484,8 @@ static int tcp_v6_rcv(struct sk_buff *skb) return 0; discard_and_relse: - sock_put(sk); + if (refcounted) + sock_put(sk); goto discard_it; do_time_wait: @@ -1514,6 +1516,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) inet_twsk_deschedule_put(tw); sk = sk2; tcp_v6_restore_cb(skb); + refcounted = false; goto process; } /* Fall through to ACK */ diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 49d14ecad444..b10ade272b50 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -120,9 +120,9 @@ xt_socket_get_sock_v4(struct net *net, struct sk_buff *skb, const int doff, { switch (protocol) { case IPPROTO_TCP: - return __inet_lookup(net, &tcp_hashinfo, skb, doff, - saddr, sport, daddr, dport, - in->ifindex); + return inet_lookup(net, &tcp_hashinfo, skb, doff, + saddr, sport, daddr, dport, + in->ifindex); case IPPROTO_UDP: return udp4_lib_lookup(net, saddr, sport, daddr, dport, in->ifindex); -- GitLab From 15239302edd46b184e758048253541fb211e315e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:18 -0700 Subject: [PATCH 1303/9938] sock_diag: add SK_MEMINFO_DROPS Reporting sk_drops to user space was available for UDP sockets using /proc interface. Add this to sock_diag, so that we can have the same information available to ss users, and we'll be able to add sk_drops indications for TCP sockets as well. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/uapi/linux/sock_diag.h | 1 + net/core/sock_diag.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/uapi/linux/sock_diag.h b/include/uapi/linux/sock_diag.h index bae2d80034d4..7ff505d8a47b 100644 --- a/include/uapi/linux/sock_diag.h +++ b/include/uapi/linux/sock_diag.h @@ -20,6 +20,7 @@ enum { SK_MEMINFO_WMEM_QUEUED, SK_MEMINFO_OPTMEM, SK_MEMINFO_BACKLOG, + SK_MEMINFO_DROPS, SK_MEMINFO_VARS, }; diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index a996ce8c8fb2..ca9e35bbe13c 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -67,6 +67,7 @@ int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attrtype) mem[SK_MEMINFO_WMEM_QUEUED] = sk->sk_wmem_queued; mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc); mem[SK_MEMINFO_BACKLOG] = sk->sk_backlog.len; + mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops); return nla_put(skb, attrtype, sizeof(mem), &mem); } -- GitLab From 532182cd610782db8c18230c2747626562032205 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:19 -0700 Subject: [PATCH 1304/9938] tcp: increment sk_drops for dropped rx packets Now ss can report sk_drops, we can instruct TCP to increment this per socket counter when it drops an incoming frame, to refine monitoring and debugging. Following patch takes care of listeners drops. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sock.h | 7 +++++++ net/ipv4/tcp_input.c | 33 ++++++++++++++++++++------------- net/ipv4/tcp_ipv4.c | 1 + net/ipv6/tcp_ipv6.c | 1 + 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 7ad73db9dde2..310c4367ea83 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2012,6 +2012,13 @@ sock_skb_set_dropcount(const struct sock *sk, struct sk_buff *skb) SOCK_SKB_CB(skb)->dropcount = atomic_read(&sk->sk_drops); } +static inline void sk_drops_add(struct sock *sk, const struct sk_buff *skb) +{ + int segs = max_t(u16, 1, skb_shinfo(skb)->gso_segs); + + atomic_add(segs, &sk->sk_drops); +} + void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb); void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a26e2d262358..0ffcd07e3409 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4307,6 +4307,12 @@ static bool tcp_try_coalesce(struct sock *sk, return true; } +static void tcp_drop(struct sock *sk, struct sk_buff *skb) +{ + sk_drops_add(sk, skb); + __kfree_skb(skb); +} + /* This one checks to see if we can put data from the * out_of_order queue into the receive_queue. */ @@ -4331,7 +4337,7 @@ static void tcp_ofo_queue(struct sock *sk) __skb_unlink(skb, &tp->out_of_order_queue); if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) { SOCK_DEBUG(sk, "ofo packet was already received\n"); - __kfree_skb(skb); + tcp_drop(sk, skb); continue; } SOCK_DEBUG(sk, "ofo requeuing : rcv_next %X seq %X - %X\n", @@ -4383,7 +4389,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP); - __kfree_skb(skb); + tcp_drop(sk, skb); return; } @@ -4447,7 +4453,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) if (!after(end_seq, TCP_SKB_CB(skb1)->end_seq)) { /* All the bits are present. Drop. */ NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE); - __kfree_skb(skb); + tcp_drop(sk, skb); skb = NULL; tcp_dsack_set(sk, seq, end_seq); goto add_sack; @@ -4486,7 +4492,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq, TCP_SKB_CB(skb1)->end_seq); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE); - __kfree_skb(skb1); + tcp_drop(sk, skb1); } add_sack: @@ -4569,12 +4575,13 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); - int eaten = -1; bool fragstolen = false; + int eaten = -1; - if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) - goto drop; - + if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) { + __kfree_skb(skb); + return; + } skb_dst_drop(skb); __skb_pull(skb, tcp_hdr(skb)->doff * 4); @@ -4656,7 +4663,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) tcp_enter_quickack_mode(sk); inet_csk_schedule_ack(sk); drop: - __kfree_skb(skb); + tcp_drop(sk, skb); return; } @@ -5233,7 +5240,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, return true; discard: - __kfree_skb(skb); + tcp_drop(sk, skb); return false; } @@ -5451,7 +5458,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); discard: - __kfree_skb(skb); + tcp_drop(sk, skb); } EXPORT_SYMBOL(tcp_rcv_established); @@ -5682,7 +5689,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, TCP_DELACK_MAX, TCP_RTO_MAX); discard: - __kfree_skb(skb); + tcp_drop(sk, skb); return 0; } else { tcp_send_ack(sk); @@ -6043,7 +6050,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) if (!queued) { discard: - __kfree_skb(skb); + tcp_drop(sk, skb); } return 0; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e5f924b29946..059a98f5e7e1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1694,6 +1694,7 @@ int tcp_v4_rcv(struct sk_buff *skb) return 0; discard_and_relse: + sk_drops_add(sk, skb); if (refcounted) sock_put(sk); goto discard_it; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f0422e782731..5fa8fea394c9 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1484,6 +1484,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) return 0; discard_and_relse: + sk_drops_add(sk, skb); if (refcounted) sock_put(sk); goto discard_it; -- GitLab From 9caad864151e525929d323de96cad382da49c3b2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:20 -0700 Subject: [PATCH 1305/9938] tcp: increment sk_drops for listeners Goal: packets dropped by a listener are accounted for. This adds tcp_listendrop() helper, and clears sk_drops in sk_clone_lock() so that children do not inherit their parent drop count. Note that we no longer increment LINUX_MIB_LISTENDROPS counter when sending a SYNCOOKIE, since the SYN packet generated a SYNACK. We already have a separate LINUX_MIB_SYNCOOKIESSENT Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 13 +++++++++++++ net/core/sock.c | 1 + net/ipv4/tcp_input.c | 8 +++++--- net/ipv4/tcp_ipv4.c | 6 +++--- net/ipv6/tcp_ipv6.c | 4 ++-- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index a23282996ca9..74d3ed5eb219 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1836,4 +1836,17 @@ static inline void tcp_segs_in(struct tcp_sock *tp, const struct sk_buff *skb) tp->data_segs_in += segs_in; } +/* + * TCP listen path runs lockless. + * We forced "struct sock" to be const qualified to make sure + * we don't modify one of its field by mistake. + * Here, we increment sk_drops which is an atomic_t, so we can safely + * make sock writable again. + */ +static inline void tcp_listendrop(const struct sock *sk) +{ + atomic_inc(&((struct sock *)sk)->sk_drops); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); +} + #endif /* _TCP_H */ diff --git a/net/core/sock.c b/net/core/sock.c index 7a6a063b28b3..2f517ea56786 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1525,6 +1525,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) newsk->sk_dst_cache = NULL; newsk->sk_wmem_queued = 0; newsk->sk_forward_alloc = 0; + atomic_set(&newsk->sk_drops, 0); newsk->sk_send_head = NULL; newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0ffcd07e3409..983f04c11177 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6339,8 +6339,10 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); af_ops->send_synack(sk, dst, &fl, req, &foc, !want_cookie); - if (want_cookie) - goto drop_and_free; + if (want_cookie) { + reqsk_free(req); + return 0; + } } reqsk_put(req); return 0; @@ -6350,7 +6352,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, drop_and_free: reqsk_free(req); drop: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + tcp_listendrop(sk); return 0; } EXPORT_SYMBOL(tcp_conn_request); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 059a98f5e7e1..f3ce0afe70aa 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -329,7 +329,7 @@ void tcp_req_err(struct sock *sk, u32 seq, bool abort) * errors returned from accept(). */ inet_csk_reqsk_queue_drop(req->rsk_listener, req); - NET_INC_STATS_BH(net, LINUX_MIB_LISTENDROPS); + tcp_listendrop(req->rsk_listener); } reqsk_put(req); } @@ -1246,7 +1246,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) &tcp_request_sock_ipv4_ops, sk, skb); drop: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + tcp_listendrop(sk); return 0; } EXPORT_SYMBOL(tcp_v4_conn_request); @@ -1348,7 +1348,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, exit_nonewsk: dst_release(dst); exit: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + tcp_listendrop(sk); return NULL; put_and_exit: inet_csk_prepare_forced_close(newsk); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5fa8fea394c9..7cde1b6fdda3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -964,7 +964,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) &tcp_request_sock_ipv6_ops, sk, skb); drop: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + tcp_listendrop(sk); return 0; /* don't send reset */ } @@ -1169,7 +1169,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * out_nonewsk: dst_release(dst); out: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + tcp_listendrop(sk); return NULL; } -- GitLab From a9d6532b567489196dac4ce60c62343e43228759 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:21 -0700 Subject: [PATCH 1306/9938] ipv4: tcp: set SOCK_USE_WRITE_QUEUE for ip_send_unicast_reply() TCP uses per cpu 'sockets' to send some packets : - RST packets ( tcp_v4_send_reset()) ) - ACK packets for SYN_RECV and TIMEWAIT sockets By setting SOCK_USE_WRITE_QUEUE flag, we tell sock_wfree() to not call sk_write_space() since these internal sockets do not care. This gives a small performance improvement, merely by allowing cpu to properly predict the sock_wfree() conditional branch, and avoiding one atomic operation. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f3ce0afe70aa..456ff3d6a132 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2384,6 +2384,7 @@ static int __net_init tcp_sk_init(struct net *net) IPPROTO_TCP, net); if (res) goto fail; + sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; } -- GitLab From 4ce7e93cb3fe87db5b700050172dc41def9834b3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Apr 2016 08:52:22 -0700 Subject: [PATCH 1307/9938] tcp: rate limit ACK sent by SYN_RECV request sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attackers like to use SYNFLOOD targeting one 5-tuple, as they hit a single RX queue (and cpu) on the victim. If they use random sequence numbers in their SYN, we detect they do not match the expected window and send back an ACK. This patch adds a rate limitation, so that the effect of such attacks is limited to ingress only. We roughly double our ability to absorb such attacks. Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Cc: Neal Cardwell Cc: Maciej Żenczykowski Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_minisocks.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index acb366dd61e6..4c53e7c86586 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -704,7 +704,10 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, tcp_rsk(req)->rcv_nxt, tcp_rsk(req)->rcv_nxt + req->rsk_rcv_wnd)) { /* Out of window: send ACK and drop. */ - if (!(flg & TCP_FLAG_RST)) + if (!(flg & TCP_FLAG_RST) && + !tcp_oow_rate_limited(sock_net(sk), skb, + LINUX_MIB_TCPACKSKIPPEDSYNRECV, + &tcp_rsk(req)->last_oow_ack_time)) req->rsk_ops->send_ack(sk, skb, req); if (paws_reject) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); -- GitLab From 08ca38742b63ae3825096e943de371a3b372c4a0 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 3 Feb 2016 09:20:47 +0100 Subject: [PATCH 1308/9938] i40e: call ndo_stop() instead of dev_close() when running offline selftest Calling dev_close() causes IFF_UP to be cleared which will remove the interfaces routes and some addresses. That's probably not what the user intended when running the offline selftest. Besides this does not happen if the interface is brought down before the test, so the current behaviour is inconsistent. Instead call the net_device_ops ndo_stop function directly and avoid touching IFF_UP at all. Signed-off-by: Stefan Assmann Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 +- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 1ce6e9c0427d..f208570cfdbf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -811,6 +811,7 @@ int i40e_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid); #endif int i40e_open(struct net_device *netdev); +int i40e_close(struct net_device *netdev); int i40e_vsi_open(struct i40e_vsi *vsi); void i40e_vlan_stripping_disable(struct i40e_vsi *vsi); int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); @@ -823,7 +824,6 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, bool is_vf, bool is_netdev); #ifdef I40E_FCOE -int i40e_close(struct net_device *netdev); int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, struct tc_to_netdev *tc); void i40e_netpoll(struct net_device *netdev); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 784b1659457a..410d237f9137 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1714,7 +1714,7 @@ static void i40e_diag_test(struct net_device *netdev, /* If the device is online then take it offline */ if (if_running) /* indicate we're in test mode */ - dev_close(netdev); + i40e_close(netdev); else /* This reset does not affect link - if it is * changed to a type of reset that does affect @@ -1743,7 +1743,7 @@ static void i40e_diag_test(struct net_device *netdev, i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED)); if (if_running) - dev_open(netdev); + i40e_open(netdev); } else { /* Online tests */ netif_info(pf, drv, netdev, "online testing starting\n"); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 67006431726a..650336e50255 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5509,11 +5509,7 @@ static void i40e_fdir_filter_exit(struct i40e_pf *pf) * * Returns 0, this is not allowed to fail **/ -#ifdef I40E_FCOE int i40e_close(struct net_device *netdev) -#else -static int i40e_close(struct net_device *netdev) -#endif { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; -- GitLab From 5c4654daf2e2f25dfbd7fa572c59937ea6d4198b Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 19 Feb 2016 12:17:08 -0800 Subject: [PATCH 1309/9938] i40e/i40evf: Allow up to 12K bytes of data per Tx descriptor instead of 8K From what I can tell the practical limitation on the size of the Tx data buffer is the fact that the Tx descriptor is limited to 14 bits. As such we cannot use 16K as is typically used on the other Intel drivers. However artificially limiting ourselves to 8K can be expensive as this means that we will consume up to 10 descriptors (1 context, 1 for header, and 9 for payload, non-8K aligned) in a single send. I propose that we can reduce this by increasing the maximum data for a 4K aligned block to 12K. We can reduce the descriptors used for a 32K aligned block by 1 by increasing the size like this. In addition we still have the 4K - 1 of space that is still unused. We can use this as a bit of extra padding when dealing with data that is not aligned to 4K. By aligning the descriptors after the first to 4K we can improve the efficiency of PCIe accesses as we can avoid using byte enables and can fetch full TLP transactions after the first fetch of the buffer. This helps to improve PCIe efficiency. Below is the results of testing before and after with this patch: Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % U us/KB us/KB Before: 87380 16384 16384 10.00 33682.24 20.27 -1.00 0.592 -1.00 After: 87380 16384 16384 10.00 34204.08 20.54 -1.00 0.590 -1.00 So the net result of this patch is that we have a small gain in throughput due to a reduction in overhead for putting together the frame. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 ++++--- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 35 +++++++++++++++++-- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 13 ++++--- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 35 +++++++++++++++++-- 5 files changed, 83 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 8ad162c16f61..92d2208d13c7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1371,7 +1371,7 @@ static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb, if (i40e_chk_linearize(skb, count)) { if (__skb_linearize(skb)) goto out_drop; - count = TXD_USE_COUNT(skb->len); + count = i40e_txd_use_count(skb->len); tx_ring->tx_stats.tx_linearize++; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 084d0ab316b7..9af1411bd423 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2717,6 +2717,8 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_bi = first; for (frag = &skb_shinfo(skb)->frags[0];; frag++) { + unsigned int max_data = I40E_MAX_DATA_PER_TXD_ALIGNED; + if (dma_mapping_error(tx_ring->dev, dma)) goto dma_error; @@ -2724,12 +2726,14 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, dma_unmap_len_set(tx_bi, len, size); dma_unmap_addr_set(tx_bi, dma, dma); + /* align size to end of page */ + max_data += -dma & (I40E_MAX_READ_REQ_SIZE - 1); tx_desc->buffer_addr = cpu_to_le64(dma); while (unlikely(size > I40E_MAX_DATA_PER_TXD)) { tx_desc->cmd_type_offset_bsz = build_ctob(td_cmd, td_offset, - I40E_MAX_DATA_PER_TXD, td_tag); + max_data, td_tag); tx_desc++; i++; @@ -2740,9 +2744,10 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, i = 0; } - dma += I40E_MAX_DATA_PER_TXD; - size -= I40E_MAX_DATA_PER_TXD; + dma += max_data; + size -= max_data; + max_data = I40E_MAX_DATA_PER_TXD_ALIGNED; tx_desc->buffer_addr = cpu_to_le64(dma); } @@ -2892,7 +2897,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, if (i40e_chk_linearize(skb, count)) { if (__skb_linearize(skb)) goto out_drop; - count = TXD_USE_COUNT(skb->len); + count = i40e_txd_use_count(skb->len); tx_ring->tx_stats.tx_linearize++; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index cdd5dc00aec5..9e654e611642 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -146,10 +146,39 @@ enum i40e_dyn_idx_t { #define I40E_MAX_BUFFER_TXD 8 #define I40E_MIN_TX_LEN 17 -#define I40E_MAX_DATA_PER_TXD 8192 + +/* The size limit for a transmit buffer in a descriptor is (16K - 1). + * In order to align with the read requests we will align the value to + * the nearest 4K which represents our maximum read request size. + */ +#define I40E_MAX_READ_REQ_SIZE 4096 +#define I40E_MAX_DATA_PER_TXD (16 * 1024 - 1) +#define I40E_MAX_DATA_PER_TXD_ALIGNED \ + (I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1)) + +/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is + * the value I40E_MAX_DATA_PER_TXD_ALIGNED. It is needed due to the fact + * that 12K is not a power of 2 and division is expensive. It is used to + * approximate the number of descriptors used per linear buffer. Note + * that this will overestimate in some cases as it doesn't account for the + * fact that we will add up to 4K - 1 in aligning the 12K buffer, however + * the error should not impact things much as large buffers usually mean + * we will use fewer descriptors then there are frags in an skb. + */ +static inline unsigned int i40e_txd_use_count(unsigned int size) +{ + const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED; + const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max; + unsigned int adjust = ~(u32)0; + + /* if we rounded up on the reciprocal pull down the adjustment */ + if ((max * reciprocal) > adjust) + adjust = ~(u32)(reciprocal - 1); + + return (u32)((((u64)size * reciprocal) + adjust) >> 32); +} /* Tx Descriptors needed, worst case */ -#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), I40E_MAX_DATA_PER_TXD) #define DESC_NEEDED (MAX_SKB_FRAGS + 4) #define I40E_MIN_DESC_PENDING 4 @@ -377,7 +406,7 @@ static inline int i40e_xmit_descriptor_count(struct sk_buff *skb) int count = 0, size = skb_headlen(skb); for (;;) { - count += TXD_USE_COUNT(size); + count += i40e_txd_use_count(size); if (!nr_frags--) break; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index ebcc25c05796..5f9c1bbab1fa 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1936,6 +1936,8 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_bi = first; for (frag = &skb_shinfo(skb)->frags[0];; frag++) { + unsigned int max_data = I40E_MAX_DATA_PER_TXD_ALIGNED; + if (dma_mapping_error(tx_ring->dev, dma)) goto dma_error; @@ -1943,12 +1945,14 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, dma_unmap_len_set(tx_bi, len, size); dma_unmap_addr_set(tx_bi, dma, dma); + /* align size to end of page */ + max_data += -dma & (I40E_MAX_READ_REQ_SIZE - 1); tx_desc->buffer_addr = cpu_to_le64(dma); while (unlikely(size > I40E_MAX_DATA_PER_TXD)) { tx_desc->cmd_type_offset_bsz = build_ctob(td_cmd, td_offset, - I40E_MAX_DATA_PER_TXD, td_tag); + max_data, td_tag); tx_desc++; i++; @@ -1959,9 +1963,10 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, i = 0; } - dma += I40E_MAX_DATA_PER_TXD; - size -= I40E_MAX_DATA_PER_TXD; + dma += max_data; + size -= max_data; + max_data = I40E_MAX_DATA_PER_TXD_ALIGNED; tx_desc->buffer_addr = cpu_to_le64(dma); } @@ -2110,7 +2115,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, if (i40e_chk_linearize(skb, count)) { if (__skb_linearize(skb)) goto out_drop; - count = TXD_USE_COUNT(skb->len); + count = i40e_txd_use_count(skb->len); tx_ring->tx_stats.tx_linearize++; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index c1dd8c5c9666..3ec0ea5ea3db 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -146,10 +146,39 @@ enum i40e_dyn_idx_t { #define I40E_MAX_BUFFER_TXD 8 #define I40E_MIN_TX_LEN 17 -#define I40E_MAX_DATA_PER_TXD 8192 + +/* The size limit for a transmit buffer in a descriptor is (16K - 1). + * In order to align with the read requests we will align the value to + * the nearest 4K which represents our maximum read request size. + */ +#define I40E_MAX_READ_REQ_SIZE 4096 +#define I40E_MAX_DATA_PER_TXD (16 * 1024 - 1) +#define I40E_MAX_DATA_PER_TXD_ALIGNED \ + (I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1)) + +/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is + * the value I40E_MAX_DATA_PER_TXD_ALIGNED. It is needed due to the fact + * that 12K is not a power of 2 and division is expensive. It is used to + * approximate the number of descriptors used per linear buffer. Note + * that this will overestimate in some cases as it doesn't account for the + * fact that we will add up to 4K - 1 in aligning the 12K buffer, however + * the error should not impact things much as large buffers usually mean + * we will use fewer descriptors then there are frags in an skb. + */ +static inline unsigned int i40e_txd_use_count(unsigned int size) +{ + const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED; + const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max; + unsigned int adjust = ~(u32)0; + + /* if we rounded up on the reciprocal pull down the adjustment */ + if ((max * reciprocal) > adjust) + adjust = ~(u32)(reciprocal - 1); + + return (u32)((((u64)size * reciprocal) + adjust) >> 32); +} /* Tx Descriptors needed, worst case */ -#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), I40E_MAX_DATA_PER_TXD) #define DESC_NEEDED (MAX_SKB_FRAGS + 4) #define I40E_MIN_DESC_PENDING 4 @@ -359,7 +388,7 @@ static inline int i40e_xmit_descriptor_count(struct sk_buff *skb) int count = 0, size = skb_headlen(skb); for (;;) { - count += TXD_USE_COUNT(size); + count += i40e_txd_use_count(size); if (!nr_frags--) break; -- GitLab From 311f23e9a4314f62fed6c13e112c998b07e37e63 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Mar 2016 16:02:15 -0800 Subject: [PATCH 1310/9938] i40evf: remove dead code The only error case is when the malloc fails, in which case the clean up loop does nothing at all, so remove it Signed-off-by: Alan Cox Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 4b70aae2fa84..820ad94c932b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1507,7 +1507,7 @@ static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter) adapter->q_vectors = kcalloc(num_q_vectors, sizeof(*q_vector), GFP_KERNEL); if (!adapter->q_vectors) - goto err_out; + return -ENOMEM; for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { q_vector = &adapter->q_vectors[q_idx]; @@ -1519,15 +1519,6 @@ static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter) } return 0; - -err_out: - while (q_idx) { - q_idx--; - q_vector = &adapter->q_vectors[q_idx]; - netif_napi_del(&q_vector->napi); - } - kfree(adapter->q_vectors); - return -ENOMEM; } /** -- GitLab From 98bd147d7903580ca5d5dfa0bc39c2d16714d84e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Mar 2016 14:29:08 +0100 Subject: [PATCH 1311/9938] wext: unregister_pernet_subsys() on notifier registration failure If register_netdevice_notifier() fails (which in practice it can't right now), we should call unregister_pernet_subsys(). Do that. Reported-by: Ben Hutchings Signed-off-by: Johannes Berg --- net/wireless/wext-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index b50ee5d622e1..6250b1cfcde5 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -399,7 +399,10 @@ static int __init wireless_nlevent_init(void) if (err) return err; - return register_netdevice_notifier(&wext_netdev_notifier); + err = register_netdevice_notifier(&wext_netdev_notifier); + if (err) + unregister_pernet_subsys(&wext_pernet_ops); + return err; } subsys_initcall(wireless_nlevent_init); -- GitLab From 1948b2a2ec132115b422ae1feba1a3f5598f4acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Rechi=20Vita?= Date: Mon, 22 Feb 2016 11:36:39 -0500 Subject: [PATCH 1312/9938] rfkill: Use switch to demux userspace operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a switch to handle different ev.op values in rfkill_fop_write() makes the code easier to extend, as out-of-range values can always be handled by the default case. Signed-off-by: João Paulo Rechi Vita [roll in fix for RFKILL_OP_CHANGE from Jouni] Signed-off-by: Johannes Berg --- net/rfkill/core.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 03f26e3a6f48..884027f62783 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -1141,6 +1141,7 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf, { struct rfkill *rfkill; struct rfkill_event ev; + int ret; /* we don't need the 'hard' variable but accept it */ if (count < RFKILL_EVENT_SIZE_V1 - 1) @@ -1155,29 +1156,36 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf, if (copy_from_user(&ev, buf, count)) return -EFAULT; - if (ev.op != RFKILL_OP_CHANGE && ev.op != RFKILL_OP_CHANGE_ALL) - return -EINVAL; - if (ev.type >= NUM_RFKILL_TYPES) return -EINVAL; mutex_lock(&rfkill_global_mutex); - if (ev.op == RFKILL_OP_CHANGE_ALL) + switch (ev.op) { + case RFKILL_OP_CHANGE_ALL: rfkill_update_global_state(ev.type, ev.soft); - - list_for_each_entry(rfkill, &rfkill_list, node) { - if (rfkill->idx != ev.idx && ev.op != RFKILL_OP_CHANGE_ALL) - continue; - - if (rfkill->type != ev.type && ev.type != RFKILL_TYPE_ALL) - continue; - - rfkill_set_block(rfkill, ev.soft); + list_for_each_entry(rfkill, &rfkill_list, node) + if (rfkill->type == ev.type || + ev.type == RFKILL_TYPE_ALL) + rfkill_set_block(rfkill, ev.soft); + ret = 0; + break; + case RFKILL_OP_CHANGE: + list_for_each_entry(rfkill, &rfkill_list, node) + if (rfkill->idx == ev.idx && + (rfkill->type == ev.type || + ev.type == RFKILL_TYPE_ALL)) + rfkill_set_block(rfkill, ev.soft); + ret = 0; + break; + default: + ret = -EINVAL; + break; } + mutex_unlock(&rfkill_global_mutex); - return count; + return ret ?: count; } static int rfkill_fop_release(struct inode *inode, struct file *file) -- GitLab From 646e76bb5daf4ca38438c69ffb72cccb605f3466 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 23 Feb 2016 15:43:35 +0100 Subject: [PATCH 1313/9938] mac80211: parse VHT info in injected frames Add VHT radiotap parsing support to ieee80211_parse_tx_radiotap(). That capability has been tested using a d-link dir-860l rev b1 running OpenWrt trunk and mt76 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Johannes Berg --- .../networking/mac80211-injection.txt | 13 ++++++++ net/mac80211/tx.c | 31 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt index ec8f934c2eb2..e0efcaf5b0ee 100644 --- a/Documentation/networking/mac80211-injection.txt +++ b/Documentation/networking/mac80211-injection.txt @@ -45,6 +45,19 @@ radiotap headers and used to control injection: number of retries when either IEEE80211_RADIOTAP_RATE or IEEE80211_RADIOTAP_MCS was used + * IEEE80211_RADIOTAP_VHT + + VHT mcs and number of streams used in the transmission (only for devices + without own rate control). Also other fields are parsed + + flags field + IEEE80211_RADIOTAP_VHT_FLAG_SGI: use short guard interval + + bandwidth field + 1: send using 40MHz channel width + 4: send using 80MHz channel width + 11: send using 160MHz channel width + The injection code can also skip all other currently defined radiotap fields facilitating replay of captured radiotap headers directly. diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 62ad5321257d..c485fc26fa0c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1692,6 +1692,8 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, u8 rate_retries = 0; u16 rate_flags = 0; u8 mcs_known, mcs_flags; + u16 vht_known; + u8 vht_mcs = 0, vht_nss = 0; int i; info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | @@ -1772,6 +1774,32 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; break; + case IEEE80211_RADIOTAP_VHT: + vht_known = get_unaligned_le16(iterator.this_arg); + rate_found = true; + + rate_flags = IEEE80211_TX_RC_VHT_MCS; + if ((vht_known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) && + (iterator.this_arg[2] & + IEEE80211_RADIOTAP_VHT_FLAG_SGI)) + rate_flags |= IEEE80211_TX_RC_SHORT_GI; + if (vht_known & + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) { + if (iterator.this_arg[3] == 1) + rate_flags |= + IEEE80211_TX_RC_40_MHZ_WIDTH; + else if (iterator.this_arg[3] == 4) + rate_flags |= + IEEE80211_TX_RC_80_MHZ_WIDTH; + else if (iterator.this_arg[3] == 11) + rate_flags |= + IEEE80211_TX_RC_160_MHZ_WIDTH; + } + + vht_mcs = iterator.this_arg[4] >> 4; + vht_nss = iterator.this_arg[4] & 0xF; + break; + /* * Please update the file * Documentation/networking/mac80211-injection.txt @@ -1797,6 +1825,9 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, if (rate_flags & IEEE80211_TX_RC_MCS) { info->control.rates[0].idx = rate; + } else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) { + ieee80211_rate_set_vht(info->control.rates, vht_mcs, + vht_nss); } else { for (i = 0; i < sband->n_bitrates; i++) { if (rate * 5 != sband->bitrates[i].bitrate) -- GitLab From 162dd6a7253ab009c6335c21ce6b80cf227ddda4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 23 Feb 2016 23:05:06 +0200 Subject: [PATCH 1314/9938] mac80211: allow drivers to report CLOCK_BOOTTIME for scan results This was requested by Android, and the appropriate cfg80211 API had been added by Dmitry. Support it in mac80211, allowing drivers to provide the timestamp. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 3 +++ net/mac80211/scan.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 0c09da34b67a..1b9f729bb074 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1120,6 +1120,8 @@ enum mac80211_rx_vht_flags { * * @mactime: value in microseconds of the 64-bit Time Synchronization Function * (TSF) timer when the first data symbol (MPDU) arrived at the hardware. + * @boottime_ns: CLOCK_BOOTTIME timestamp the frame was received at, this is + * needed only for beacons and probe responses that update the scan cache. * @device_timestamp: arbitrary timestamp for the device, mac80211 doesn't use * it but can store it and pass it back to the driver for synchronisation * @band: the active band when this frame was received @@ -1146,6 +1148,7 @@ enum mac80211_rx_vht_flags { */ struct ieee80211_rx_status { u64 mactime; + u64 boottime_ns; u32 device_timestamp; u32 ampdu_reference; u32 flag; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ae980ce8daff..a3fea1f35ef9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -66,7 +66,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local, struct cfg80211_bss *cbss; struct ieee80211_bss *bss; int clen, srlen; - struct cfg80211_inform_bss bss_meta = {}; + struct cfg80211_inform_bss bss_meta = { + .boottime_ns = rx_status->boottime_ns, + }; bool signal_valid; if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) -- GitLab From f980ebc058c2fa2a552e495db1de0b330082ab70 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 24 Feb 2016 11:49:45 +0200 Subject: [PATCH 1315/9938] mac80211: allow not sending MIC up from driver for HW crypto When HW crypto is used, there's no need for the CCMP/GCMP MIC to be available to mac80211, and the hardware might have removed it already after checking. The MIC is also useless to have when the frame is already decrypted, so allow indicating that it's not present. Since we are running out of bits in mac80211_rx_flags, make the flags field a u64. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath10k/htt_rx.c | 2 +- drivers/net/wireless/ath/wcn36xx/txrx.c | 2 +- include/net/mac80211.h | 5 ++++- net/mac80211/util.c | 5 +++-- net/mac80211/wpa.c | 26 +++++++++++++----------- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index ae9b686a4e91..feab80a5b6eb 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -979,7 +979,7 @@ static void ath10k_process_rx(struct ath10k *ar, *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, - "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", + "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n", skb, skb->len, ieee80211_get_SA(hdr), diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 9bec8237231d..99c21aac68bd 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -57,7 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) RX_FLAG_MMIC_STRIPPED | RX_FLAG_DECRYPTED; - wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag); + wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%llx\n", status.flag); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1b9f729bb074..7cb791f21722 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1034,6 +1034,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * on this subframe * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC * is stored in the @ampdu_delimiter_crc field) + * @RX_FLAG_MIC_STRIPPED: The mic was stripped of this packet. Decryption was + * done by the hardware * @RX_FLAG_LDPC: LDPC was used * @RX_FLAG_ONLY_MONITOR: Report frame only to monitor interfaces without * processing it in any regular way. @@ -1091,6 +1093,7 @@ enum mac80211_rx_flags { RX_FLAG_5MHZ = BIT(29), RX_FLAG_AMSDU_MORE = BIT(30), RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31), + RX_FLAG_MIC_STRIPPED = BIT_ULL(32), }; #define RX_FLAG_STBC_SHIFT 26 @@ -1151,7 +1154,7 @@ struct ieee80211_rx_status { u64 boottime_ns; u32 device_timestamp; u32 ampdu_reference; - u32 flag; + u64 flag; u16 freq; u8 vht_flag; u8 rate_idx; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 7390de4946a9..0319d6d4f863 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2724,8 +2724,9 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, rate = cfg80211_calculate_bitrate(&ri); if (WARN_ONCE(!rate, - "Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n", - status->flag, status->rate_idx, status->vht_nss)) + "Invalid bitrate: flags=0x%llx, idx=%d, vht_nss=%d\n", + (unsigned long long)status->flag, status->rate_idx, + status->vht_nss)) return 0; /* rewind from end of MPDU */ diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 18848258adde..7e4f2652bca7 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -504,18 +504,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, !ieee80211_is_robust_mgmt_frame(skb)) return RX_CONTINUE; - data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; - if (!rx->sta || data_len < 0) - return RX_DROP_UNUSABLE; - if (status->flag & RX_FLAG_DECRYPTED) { if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN)) return RX_DROP_UNUSABLE; + if (status->flag & RX_FLAG_MIC_STRIPPED) + mic_len = 0; } else { if (skb_linearize(rx->skb)) return RX_DROP_UNUSABLE; } + data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; + if (!rx->sta || data_len < 0) + return RX_DROP_UNUSABLE; + if (!(status->flag & RX_FLAG_PN_VALIDATED)) { ccmp_hdr2pn(pn, skb->data + hdrlen); @@ -720,8 +722,7 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) struct sk_buff *skb = rx->skb; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); u8 pn[IEEE80211_GCMP_PN_LEN]; - int data_len; - int queue; + int data_len, queue, mic_len = IEEE80211_GCMP_MIC_LEN; hdrlen = ieee80211_hdrlen(hdr->frame_control); @@ -729,19 +730,20 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) !ieee80211_is_robust_mgmt_frame(skb)) return RX_CONTINUE; - data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - - IEEE80211_GCMP_MIC_LEN; - if (!rx->sta || data_len < 0) - return RX_DROP_UNUSABLE; - if (status->flag & RX_FLAG_DECRYPTED) { if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN)) return RX_DROP_UNUSABLE; + if (status->flag & RX_FLAG_MIC_STRIPPED) + mic_len = 0; } else { if (skb_linearize(rx->skb)) return RX_DROP_UNUSABLE; } + data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len; + if (!rx->sta || data_len < 0) + return RX_DROP_UNUSABLE; + if (!(status->flag & RX_FLAG_PN_VALIDATED)) { gcmp_hdr2pn(pn, skb->data + hdrlen); @@ -772,7 +774,7 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) } /* Remove GCMP header and MIC */ - if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN)) + if (pskb_trim(skb, skb->len - mic_len)) return RX_DROP_UNUSABLE; memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen); skb_pull(skb, IEEE80211_GCMP_HDR_LEN); -- GitLab From 5c05803a3e2054257d7e8e737a6efaf2c7f6b725 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 24 Feb 2016 16:25:48 +0100 Subject: [PATCH 1316/9938] mac80211: document only injected *_RADIOTAP_* flags Not the internal flags but the radiotap flags are parsed when the monitor injected frames are prepared for transmission. Thus the documentation should only document these. Reported-by: Lorenzo Bianconi Reported-by: Johannes Berg Fixes: dfdfc2beb0dd ("mac80211: Parse legacy and HT rate in injected frames") Signed-off-by: Sven Eckelmann Signed-off-by: Johannes Berg --- Documentation/networking/mac80211-injection.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt index e0efcaf5b0ee..d58d78df9ca2 100644 --- a/Documentation/networking/mac80211-injection.txt +++ b/Documentation/networking/mac80211-injection.txt @@ -37,8 +37,8 @@ radiotap headers and used to control injection: HT rate for the transmission (only for devices without own rate control). Also some flags are parsed - IEEE80211_TX_RC_SHORT_GI: use short guard interval - IEEE80211_TX_RC_40_MHZ_WIDTH: send in HT40 mode + IEEE80211_RADIOTAP_MCS_SGI: use short guard interval + IEEE80211_RADIOTAP_MCS_BW_40: send in HT40 mode * IEEE80211_RADIOTAP_DATA_RETRIES -- GitLab From f2edaaaa392bc21c24f532ea9bcc952a54a22367 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 7 Mar 2016 09:29:57 -0800 Subject: [PATCH 1317/9938] i40e/i40evf: Fix handling of boolean logic in polling routines In the polling routines for i40e and i40evf we were using bitwise operators to avoid the side effects of the logical operators, specifically the fact that if the first case is true with "||" we skip the second case, or if it is false with "&&" we skip the second case. This fixes an earlier patch that converted the bitwise operators over to the logical operators and instead replaces the entire thing with just an if statement since it should be more readable what we are trying to do this way. Fixes: 1a36d7fadd14 ("i40e/i40evf: use logical operators, not bitwise") Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 ++++++++----- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 9af1411bd423..8fb2a966d70e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1975,9 +1975,11 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) * budget and be more aggressive about cleaning up the Tx descriptors. */ i40e_for_each_ring(ring, q_vector->tx) { - clean_complete = clean_complete && - i40e_clean_tx_irq(ring, vsi->work_limit); - arm_wb = arm_wb || ring->arm_wb; + if (!i40e_clean_tx_irq(ring, vsi->work_limit)) { + clean_complete = false; + continue; + } + arm_wb |= ring->arm_wb; ring->arm_wb = false; } @@ -1999,8 +2001,9 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring); work_done += cleaned; - /* if we didn't clean as many as budgeted, we must be done */ - clean_complete = clean_complete && (budget_per_ring > cleaned); + /* if we clean as many as budgeted, we must not be done */ + if (cleaned >= budget_per_ring) + clean_complete = false; } /* If work not completed, return budget and polling will return */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 5f9c1bbab1fa..839a6df62f72 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1411,9 +1411,11 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) * budget and be more aggressive about cleaning up the Tx descriptors. */ i40e_for_each_ring(ring, q_vector->tx) { - clean_complete = clean_complete && - i40e_clean_tx_irq(ring, vsi->work_limit); - arm_wb = arm_wb || ring->arm_wb; + if (!i40e_clean_tx_irq(ring, vsi->work_limit)) { + clean_complete = false; + continue; + } + arm_wb |= ring->arm_wb; ring->arm_wb = false; } @@ -1435,8 +1437,9 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring); work_done += cleaned; - /* if we didn't clean as many as budgeted, we must be done */ - clean_complete = clean_complete && (budget_per_ring > cleaned); + /* if we clean as many as budgeted, we must not be done */ + if (cleaned >= budget_per_ring) + clean_complete = false; } /* If work not completed, return budget and polling will return */ -- GitLab From 818965d3917774955fad52f87b59d690d8be9e8b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Feb 2016 22:12:47 +0200 Subject: [PATCH 1318/9938] cfg80211: Allow a scan request for a specific BSSID This allows scans for a specific BSSID to be optimized by the user space application by requesting the driver to set the Probe Request frame BSSID field (Address 3) to the specified BSSID instead of the wildcard BSSID. This prevents other APs from replying which reduces airtime need and latency in getting the response from the target AP through. This is an optimization and as such, it is acceptable for some of the drivers not to support the mechanism. If not supported, the wildcard BSSID will be used and more responses may be received. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ include/uapi/linux/nl80211.h | 4 +++- net/wireless/nl80211.c | 6 ++++++ net/wireless/scan.c | 2 ++ net/wireless/sme.c | 2 ++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9e1b24c29f0c..14c0c437d973 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1455,6 +1455,7 @@ struct cfg80211_ssid { * @mac_addr_mask: MAC address mask used with randomisation, bits that * are 0 in the mask should be randomised, bits that are 1 should * be taken from the @mac_addr + * @bssid: BSSID to scan for (most commonly, the wildcard BSSID) */ struct cfg80211_scan_request { struct cfg80211_ssid *ssids; @@ -1471,6 +1472,7 @@ struct cfg80211_scan_request { u8 mac_addr[ETH_ALEN] __aligned(2); u8 mac_addr_mask[ETH_ALEN] __aligned(2); + u8 bssid[ETH_ALEN] __aligned(2); /* internal */ struct wiphy *wiphy; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 5a30a7563633..23bf0667540c 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -322,7 +322,9 @@ * @NL80211_CMD_GET_SCAN: get scan results * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the - * probe requests at CCK rate or not. + * probe requests at CCK rate or not. %NL80211_ATTR_MAC can be used to + * specify a BSSID to scan for; if not included, the wildcard BSSID will + * be used. * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to * NL80211_CMD_GET_SCAN and on the "scan" multicast group) * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 98c924260b3d..1b43f7839eeb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5996,6 +5996,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); + if (info->attrs[NL80211_ATTR_MAC]) + memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]), + ETH_ALEN); + else + eth_broadcast_addr(request->bssid); + request->wdev = wdev; request->wiphy = &rdev->wiphy; request->scan_start = jiffies; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 14d5369eb778..50ea8e3fcbeb 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1293,6 +1293,8 @@ int cfg80211_wext_siwscan(struct net_device *dev, if (wiphy->bands[i]) creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; + eth_broadcast_addr(creq->bssid); + rdev->scan_req = creq; err = rdev_scan(rdev, creq); if (err) { diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 544558171787..65882d2777c0 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -119,6 +119,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) wdev->conn->params.ssid_len); request->ssids[0].ssid_len = wdev->conn->params.ssid_len; + eth_broadcast_addr(request->bssid); + request->wdev = wdev; request->wiphy = &rdev->wiphy; request->scan_start = jiffies; -- GitLab From e345f44f2b7c6a77c1c0677b7c8606a0bb1c5c5c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Feb 2016 22:12:48 +0200 Subject: [PATCH 1319/9938] mac80211: Support a scan request for a specific BSSID If the cfg80211 scan trigger operation specifies a single BSSID, use that value instead of the wildcard BSSID in the Probe Request frames. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- net/mac80211/scan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a3fea1f35ef9..41aa728e5468 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -305,6 +305,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr); ether_addr_copy(local->hw_scan_req->req.mac_addr_mask, req->mac_addr_mask); + ether_addr_copy(local->hw_scan_req->req.bssid, req->bssid); return true; } @@ -499,7 +500,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, for (i = 0; i < scan_req->n_ssids; i++) ieee80211_send_probe_req( - sdata, local->scan_addr, NULL, + sdata, local->scan_addr, scan_req->bssid, scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, scan_req->ie, scan_req->ie_len, scan_req->rates[band], false, @@ -564,6 +565,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, req->n_channels * sizeof(req->channels[0]); local->hw_scan_req->req.ie = ies; local->hw_scan_req->req.flags = req->flags; + eth_broadcast_addr(local->hw_scan_req->req.bssid); local->hw_scan_band = 0; -- GitLab From 12880d169471fb14c46d6f323f31127702a6d5e6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Feb 2016 22:12:49 +0200 Subject: [PATCH 1320/9938] mac80211_hwsim: Support a hw scan request for a specific BSSID If the hw scan request specifies a single BSSID, use that value instead of the wildcard BSSID in the Probe Request frames. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e85e0737771c..2b185feb1aa0 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1909,6 +1909,7 @@ static void hw_scan_work(struct work_struct *work) /* send probes */ for (i = 0; i < req->n_ssids; i++) { struct sk_buff *probe; + struct ieee80211_mgmt *mgmt; probe = ieee80211_probereq_get(hwsim->hw, hwsim->scan_addr, @@ -1918,6 +1919,10 @@ static void hw_scan_work(struct work_struct *work) if (!probe) continue; + mgmt = (struct ieee80211_mgmt *) probe->data; + memcpy(mgmt->da, req->bssid, ETH_ALEN); + memcpy(mgmt->bssid, req->bssid, ETH_ALEN); + if (req->ie_len) memcpy(skb_put(probe, req->ie_len), req->ie, req->ie_len); -- GitLab From 2bdaf386f99c4a82788812e583ff59c6714ae4d6 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Feb 2016 20:03:56 -0500 Subject: [PATCH 1321/9938] mac80211: mesh: move path tables into if_mesh The mesh path and mesh gate hashtables are global, containing all of the mpaths for every mesh interface, but the paths are all tied logically to a single interface. The common case is just a single mesh interface, so optimize for that by moving the global hashtable into the per-interface struct. Doing so allows us to drop sdata pointer comparisons inside the lookups and also saves a few bytes of BSS and data. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 4 +- net/mac80211/ieee80211_i.h | 12 +++ net/mac80211/mesh.c | 10 +- net/mac80211/mesh.h | 10 +- net/mac80211/mesh_pathtbl.c | 181 ++++++++++++++++-------------------- net/mac80211/tx.c | 2 +- 6 files changed, 104 insertions(+), 115 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index fe1704c4e8fb..b37adb60c9cb 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1499,7 +1499,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, memset(pinfo, 0, sizeof(*pinfo)); - pinfo->generation = mesh_paths_generation; + pinfo->generation = mpath->sdata->u.mesh.mesh_paths_generation; pinfo->filled = MPATH_INFO_FRAME_QLEN | MPATH_INFO_SN | @@ -1577,7 +1577,7 @@ static void mpp_set_pinfo(struct mesh_path *mpath, u8 *mpp, memset(pinfo, 0, sizeof(*pinfo)); memcpy(mpp, mpath->mpp, ETH_ALEN); - pinfo->generation = mpp_paths_generation; + pinfo->generation = mpath->sdata->u.mesh.mpp_paths_generation; } static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 804575ff7af5..db7f0dbebc4b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -696,6 +696,18 @@ struct ieee80211_if_mesh { /* offset from skb->data while building IE */ int meshconf_offset; + + struct mesh_table __rcu *mesh_paths; + struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */ + int mesh_paths_generation; + int mpp_paths_generation; + + /* Protects assignment of the mesh_paths/mpp_paths table + * pointer for resize against reading it for add/delete + * of individual paths. Pure readers (lookups) just use + * RCU. + */ + rwlock_t pathtbl_resize_lock; }; #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index d32cefcb63b0..c92af2a7714d 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -25,7 +25,6 @@ bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) void ieee80211s_init(void) { - mesh_pathtbl_init(); mesh_allocated = 1; rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry), 0, 0, NULL); @@ -35,7 +34,6 @@ void ieee80211s_stop(void) { if (!mesh_allocated) return; - mesh_pathtbl_unregister(); kmem_cache_destroy(rm_cache); } @@ -902,6 +900,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) /* flush STAs and mpaths on this iface */ sta_info_flush(sdata); mesh_path_flush_by_iface(sdata); + mesh_pathtbl_unregister(sdata); /* free all potentially still buffered group-addressed frames */ local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf); @@ -1349,10 +1348,10 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) mesh_path_start_discovery(sdata); if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) - mesh_mpath_table_grow(); + mesh_mpath_table_grow(sdata); if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags)) - mesh_mpp_table_grow(); + mesh_mpp_table_grow(sdata); if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) ieee80211_mesh_housekeeping(sdata); @@ -1388,6 +1387,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) /* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) ieee80211s_init(); + + mesh_pathtbl_init(sdata); + setup_timer(&ifmsh->mesh_path_timer, ieee80211_mesh_path_timer, (unsigned long) sdata); diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 87c017a3b1ce..601992b6cd8a 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -300,8 +300,8 @@ void mesh_sta_cleanup(struct sta_info *sta); /* Private interfaces */ /* Mesh tables */ -void mesh_mpath_table_grow(void); -void mesh_mpp_table_grow(void); +void mesh_mpath_table_grow(struct ieee80211_sub_if_data *sdata); +void mesh_mpp_table_grow(struct ieee80211_sub_if_data *sdata); /* Mesh paths */ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, u8 ttl, const u8 *target, u32 target_sn, @@ -309,8 +309,8 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); void mesh_path_flush_pending(struct mesh_path *mpath); void mesh_path_tx_pending(struct mesh_path *mpath); -int mesh_pathtbl_init(void); -void mesh_pathtbl_unregister(void); +int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata); +void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata); int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr); void mesh_path_timer(unsigned long data); void mesh_path_flush_by_nexthop(struct sta_info *sta); @@ -319,8 +319,6 @@ void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); -extern int mesh_paths_generation; -extern int mpp_paths_generation; #ifdef CONFIG_MAC80211_MESH static inline diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 2ba7aa56b11c..0508b37b0471 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -40,36 +40,24 @@ struct mpath_node { struct mesh_path *mpath; }; -static struct mesh_table __rcu *mesh_paths; -static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */ - -int mesh_paths_generation; -int mpp_paths_generation; - -/* This lock will have the grow table function as writer and add / delete nodes - * as readers. RCU provides sufficient protection only when reading the table - * (i.e. doing lookups). Adding or adding or removing nodes requires we take - * the read lock or we risk operating on an old table. The write lock is only - * needed when modifying the number of buckets a table. - */ -static DEFINE_RWLOCK(pathtbl_resize_lock); - - static inline struct mesh_table *resize_dereference_paths( + struct ieee80211_sub_if_data *sdata, struct mesh_table __rcu *table) { return rcu_dereference_protected(table, - lockdep_is_held(&pathtbl_resize_lock)); + lockdep_is_held(&sdata->u.mesh.pathtbl_resize_lock)); } -static inline struct mesh_table *resize_dereference_mesh_paths(void) +static inline struct mesh_table *resize_dereference_mesh_paths( + struct ieee80211_sub_if_data *sdata) { - return resize_dereference_paths(mesh_paths); + return resize_dereference_paths(sdata, sdata->u.mesh.mesh_paths); } -static inline struct mesh_table *resize_dereference_mpp_paths(void) +static inline struct mesh_table *resize_dereference_mpp_paths( + struct ieee80211_sub_if_data *sdata) { - return resize_dereference_paths(mpp_paths); + return resize_dereference_paths(sdata, sdata->u.mesh.mpp_paths); } /* @@ -346,8 +334,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; hlist_for_each_entry_rcu(node, bucket, list) { mpath = node->mpath; - if (mpath->sdata == sdata && - ether_addr_equal(dst, mpath->dst)) { + if (ether_addr_equal(dst, mpath->dst)) { if (mpath_expired(mpath)) { spin_lock_bh(&mpath->state_lock); mpath->flags &= ~MESH_PATH_ACTIVE; @@ -371,13 +358,15 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, struct mesh_path * mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) { - return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); + return mpath_lookup(rcu_dereference(sdata->u.mesh.mesh_paths), dst, + sdata); } struct mesh_path * mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) { - return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); + return mpath_lookup(rcu_dereference(sdata->u.mesh.mpp_paths), dst, + sdata); } @@ -393,14 +382,12 @@ mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) struct mesh_path * mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) { - struct mesh_table *tbl = rcu_dereference(mesh_paths); + struct mesh_table *tbl = rcu_dereference(sdata->u.mesh.mesh_paths); struct mpath_node *node; int i; int j = 0; for_each_mesh_entry(tbl, node, i) { - if (sdata && node->mpath->sdata != sdata) - continue; if (j++ == idx) { if (mpath_expired(node->mpath)) { spin_lock_bh(&node->mpath->state_lock); @@ -426,14 +413,12 @@ mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) struct mesh_path * mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) { - struct mesh_table *tbl = rcu_dereference(mpp_paths); + struct mesh_table *tbl = rcu_dereference(sdata->u.mesh.mpp_paths); struct mpath_node *node; int i; int j = 0; for_each_mesh_entry(tbl, node, i) { - if (sdata && node->mpath->sdata != sdata) - continue; if (j++ == idx) return node->mpath; } @@ -452,7 +437,7 @@ int mesh_path_add_gate(struct mesh_path *mpath) int err; rcu_read_lock(); - tbl = rcu_dereference(mesh_paths); + tbl = rcu_dereference(mpath->sdata->u.mesh.mesh_paths); hlist_for_each_entry_rcu(gate, tbl->known_gates, list) if (gate->mpath == mpath) { @@ -550,8 +535,8 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) return ERR_PTR(-ENOSPC); - read_lock_bh(&pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(); + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + tbl = resize_dereference_mesh_paths(sdata); hash_idx = mesh_table_hash(dst, sdata, tbl); bucket = &tbl->hash_buckets[hash_idx]; @@ -560,8 +545,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, hlist_for_each_entry(node, bucket, list) { mpath = node->mpath; - if (mpath->sdata == sdata && - ether_addr_equal(dst, mpath->dst)) + if (ether_addr_equal(dst, mpath->dst)) goto found; } @@ -592,7 +576,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, MEAN_CHAIN_LEN * (tbl->hash_mask + 1)) grow = 1; - mesh_paths_generation++; + sdata->u.mesh.mesh_paths_generation++; if (grow) { set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); @@ -601,7 +585,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, mpath = new_mpath; found: spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&pathtbl_resize_lock); + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); return mpath; err_node_alloc: @@ -609,7 +593,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, err_path_alloc: atomic_dec(&sdata->u.mesh.mpaths); spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&pathtbl_resize_lock); + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); return ERR_PTR(err); } @@ -620,12 +604,12 @@ static void mesh_table_free_rcu(struct rcu_head *rcu) mesh_table_free(tbl, false); } -void mesh_mpath_table_grow(void) +void mesh_mpath_table_grow(struct ieee80211_sub_if_data *sdata) { struct mesh_table *oldtbl, *newtbl; - write_lock_bh(&pathtbl_resize_lock); - oldtbl = resize_dereference_mesh_paths(); + write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + oldtbl = resize_dereference_mesh_paths(sdata); newtbl = mesh_table_alloc(oldtbl->size_order + 1); if (!newtbl) goto out; @@ -633,20 +617,20 @@ void mesh_mpath_table_grow(void) __mesh_table_free(newtbl); goto out; } - rcu_assign_pointer(mesh_paths, newtbl); + rcu_assign_pointer(sdata->u.mesh.mesh_paths, newtbl); call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu); out: - write_unlock_bh(&pathtbl_resize_lock); + write_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); } -void mesh_mpp_table_grow(void) +void mesh_mpp_table_grow(struct ieee80211_sub_if_data *sdata) { struct mesh_table *oldtbl, *newtbl; - write_lock_bh(&pathtbl_resize_lock); - oldtbl = resize_dereference_mpp_paths(); + write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + oldtbl = resize_dereference_mpp_paths(sdata); newtbl = mesh_table_alloc(oldtbl->size_order + 1); if (!newtbl) goto out; @@ -654,11 +638,11 @@ void mesh_mpp_table_grow(void) __mesh_table_free(newtbl); goto out; } - rcu_assign_pointer(mpp_paths, newtbl); + rcu_assign_pointer(sdata->u.mesh.mpp_paths, newtbl); call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu); out: - write_unlock_bh(&pathtbl_resize_lock); + write_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); } int mpp_path_add(struct ieee80211_sub_if_data *sdata, @@ -690,7 +674,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, if (!new_node) goto err_node_alloc; - read_lock_bh(&pathtbl_resize_lock); + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); memcpy(new_mpath->mpp, mpp, ETH_ALEN); new_mpath->sdata = sdata; @@ -701,7 +685,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, new_mpath->exp_time = jiffies; spin_lock_init(&new_mpath->state_lock); - tbl = resize_dereference_mpp_paths(); + tbl = resize_dereference_mpp_paths(sdata); hash_idx = mesh_table_hash(dst, sdata, tbl); bucket = &tbl->hash_buckets[hash_idx]; @@ -711,8 +695,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, err = -EEXIST; hlist_for_each_entry(node, bucket, list) { mpath = node->mpath; - if (mpath->sdata == sdata && - ether_addr_equal(dst, mpath->dst)) + if (ether_addr_equal(dst, mpath->dst)) goto err_exists; } @@ -722,9 +705,9 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, grow = 1; spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&pathtbl_resize_lock); + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - mpp_paths_generation++; + sdata->u.mesh.mpp_paths_generation++; if (grow) { set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); @@ -734,7 +717,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, err_exists: spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&pathtbl_resize_lock); + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); kfree(new_node); err_node_alloc: kfree(new_mpath); @@ -761,7 +744,7 @@ void mesh_plink_broken(struct sta_info *sta) int i; rcu_read_lock(); - tbl = rcu_dereference(mesh_paths); + tbl = rcu_dereference(sdata->u.mesh.mesh_paths); for_each_mesh_entry(tbl, node, i) { mpath = node->mpath; if (rcu_access_pointer(mpath->next_hop) == sta && @@ -819,14 +802,15 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) */ void mesh_path_flush_by_nexthop(struct sta_info *sta) { + struct ieee80211_sub_if_data *sdata = sta->sdata; struct mesh_table *tbl; struct mesh_path *mpath; struct mpath_node *node; int i; rcu_read_lock(); - read_lock_bh(&pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(); + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + tbl = resize_dereference_mesh_paths(sdata); for_each_mesh_entry(tbl, node, i) { mpath = node->mpath; if (rcu_access_pointer(mpath->next_hop) == sta) { @@ -835,7 +819,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) spin_unlock(&tbl->hashwlock[i]); } } - read_unlock_bh(&pathtbl_resize_lock); + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); rcu_read_unlock(); } @@ -848,8 +832,8 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, int i; rcu_read_lock(); - read_lock_bh(&pathtbl_resize_lock); - tbl = resize_dereference_mpp_paths(); + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + tbl = resize_dereference_mpp_paths(sdata); for_each_mesh_entry(tbl, node, i) { mpp = node->mpath; if (ether_addr_equal(mpp->mpp, proxy)) { @@ -858,7 +842,7 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, spin_unlock(&tbl->hashwlock[i]); } } - read_unlock_bh(&pathtbl_resize_lock); + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); rcu_read_unlock(); } @@ -872,8 +856,6 @@ static void table_flush_by_iface(struct mesh_table *tbl, WARN_ON(!rcu_read_lock_held()); for_each_mesh_entry(tbl, node, i) { mpath = node->mpath; - if (mpath->sdata != sdata) - continue; spin_lock_bh(&tbl->hashwlock[i]); __mesh_path_del(tbl, node); spin_unlock_bh(&tbl->hashwlock[i]); @@ -893,12 +875,12 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) struct mesh_table *tbl; rcu_read_lock(); - read_lock_bh(&pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(); + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + tbl = resize_dereference_mesh_paths(sdata); table_flush_by_iface(tbl, sdata); - tbl = resize_dereference_mpp_paths(); + tbl = resize_dereference_mpp_paths(sdata); table_flush_by_iface(tbl, sdata); - read_unlock_bh(&pathtbl_resize_lock); + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); rcu_read_unlock(); } @@ -922,15 +904,14 @@ static int table_path_del(struct mesh_table __rcu *rcu_tbl, int hash_idx; int err = 0; - tbl = resize_dereference_paths(rcu_tbl); + tbl = resize_dereference_paths(sdata, rcu_tbl); hash_idx = mesh_table_hash(addr, sdata, tbl); bucket = &tbl->hash_buckets[hash_idx]; spin_lock(&tbl->hashwlock[hash_idx]); hlist_for_each_entry(node, bucket, list) { mpath = node->mpath; - if (mpath->sdata == sdata && - ether_addr_equal(addr, mpath->dst)) { + if (ether_addr_equal(addr, mpath->dst)) { __mesh_path_del(tbl, node); goto enddel; } @@ -957,10 +938,10 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) /* flush relevant mpp entries first */ mpp_flush_by_proxy(sdata, addr); - read_lock_bh(&pathtbl_resize_lock); - err = table_path_del(mesh_paths, sdata, addr); - mesh_paths_generation++; - read_unlock_bh(&pathtbl_resize_lock); + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + err = table_path_del(sdata->u.mesh.mesh_paths, sdata, addr); + sdata->u.mesh.mesh_paths_generation++; + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); return err; } @@ -977,10 +958,10 @@ static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) { int err = 0; - read_lock_bh(&pathtbl_resize_lock); - err = table_path_del(mpp_paths, sdata, addr); - mpp_paths_generation++; - read_unlock_bh(&pathtbl_resize_lock); + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); + err = table_path_del(sdata->u.mesh.mpp_paths, sdata, addr); + sdata->u.mesh.mpp_paths_generation++; + read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); return err; } @@ -1020,7 +1001,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) struct hlist_head *known_gates; rcu_read_lock(); - tbl = rcu_dereference(mesh_paths); + tbl = rcu_dereference(sdata->u.mesh.mesh_paths); known_gates = tbl->known_gates; rcu_read_unlock(); @@ -1028,9 +1009,6 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) return -EHOSTUNREACH; hlist_for_each_entry_rcu(gate, known_gates, list) { - if (gate->mpath->sdata != sdata) - continue; - if (gate->mpath->flags & MESH_PATH_ACTIVE) { mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst); mesh_path_move_to_queue(gate->mpath, from_mpath, copy); @@ -1043,11 +1021,10 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) } } - hlist_for_each_entry_rcu(gate, known_gates, list) - if (gate->mpath->sdata == sdata) { - mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst); - mesh_path_tx_pending(gate->mpath); - } + hlist_for_each_entry_rcu(gate, known_gates, list) { + mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst); + mesh_path_tx_pending(gate->mpath); + } return (from_mpath == mpath) ? -EHOSTUNREACH : 0; } @@ -1136,7 +1113,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) return 0; } -int mesh_pathtbl_init(void) +int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) { struct mesh_table *tbl_path, *tbl_mpp; int ret; @@ -1168,9 +1145,11 @@ int mesh_pathtbl_init(void) } INIT_HLIST_HEAD(tbl_mpp->known_gates); + rwlock_init(&sdata->u.mesh.pathtbl_resize_lock); + /* Need no locking since this is during init */ - RCU_INIT_POINTER(mesh_paths, tbl_path); - RCU_INIT_POINTER(mpp_paths, tbl_mpp); + RCU_INIT_POINTER(sdata->u.mesh.mesh_paths, tbl_path); + RCU_INIT_POINTER(sdata->u.mesh.mpp_paths, tbl_mpp); return 0; @@ -1189,33 +1168,31 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) int i; rcu_read_lock(); - tbl = rcu_dereference(mesh_paths); + tbl = rcu_dereference(sdata->u.mesh.mesh_paths); for_each_mesh_entry(tbl, node, i) { - if (node->mpath->sdata != sdata) - continue; mpath = node->mpath; if ((!(mpath->flags & MESH_PATH_RESOLVING)) && (!(mpath->flags & MESH_PATH_FIXED)) && time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) - mesh_path_del(mpath->sdata, mpath->dst); + mesh_path_del(sdata, mpath->dst); } - tbl = rcu_dereference(mpp_paths); + tbl = rcu_dereference(sdata->u.mesh.mpp_paths); for_each_mesh_entry(tbl, node, i) { - if (node->mpath->sdata != sdata) - continue; mpath = node->mpath; if ((!(mpath->flags & MESH_PATH_FIXED)) && time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) - mpp_path_del(mpath->sdata, mpath->dst); + mpp_path_del(sdata, mpath->dst); } rcu_read_unlock(); } -void mesh_pathtbl_unregister(void) +void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata) { /* no need for locking during exit path */ - mesh_table_free(rcu_dereference_protected(mesh_paths, 1), true); - mesh_table_free(rcu_dereference_protected(mpp_paths, 1), true); + mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mesh_paths, 1), + true); + mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mpp_paths, 1), + true); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c485fc26fa0c..b3196b1e15c2 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2212,7 +2212,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, } if (mppath && mpath) - mesh_path_del(mpath->sdata, mpath->dst); + mesh_path_del(sdata, mpath->dst); } /* -- GitLab From 443954815b63b36f09623d74170520e6554f5fac Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Feb 2016 20:03:57 -0500 Subject: [PATCH 1322/9938] mac80211: mesh: don't hash sdata in mpath tables Now that the sdata pointer is the same for all entries of a path table, hashing it is pointless, so hash only the address. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh_pathtbl.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0508b37b0471..fc3cc350df8c 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -177,12 +177,10 @@ static int mesh_table_grow(struct mesh_table *oldtbl, return -ENOMEM; } -static u32 mesh_table_hash(const u8 *addr, struct ieee80211_sub_if_data *sdata, - struct mesh_table *tbl) +static u32 mesh_table_hash(const u8 *addr, struct mesh_table *tbl) { - /* Use last four bytes of hw addr and interface index as hash index */ - return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, - tbl->hash_rnd) & tbl->hash_mask; + /* Use last four bytes of hw addr as hash index */ + return jhash_1word(*(u32 *)(addr+2), tbl->hash_rnd) & tbl->hash_mask; } @@ -331,7 +329,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, struct hlist_head *bucket; struct mpath_node *node; - bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; + bucket = &tbl->hash_buckets[mesh_table_hash(dst, tbl)]; hlist_for_each_entry_rcu(node, bucket, list) { mpath = node->mpath; if (ether_addr_equal(dst, mpath->dst)) { @@ -538,7 +536,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); tbl = resize_dereference_mesh_paths(sdata); - hash_idx = mesh_table_hash(dst, sdata, tbl); + hash_idx = mesh_table_hash(dst, tbl); bucket = &tbl->hash_buckets[hash_idx]; spin_lock(&tbl->hashwlock[hash_idx]); @@ -687,7 +685,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, tbl = resize_dereference_mpp_paths(sdata); - hash_idx = mesh_table_hash(dst, sdata, tbl); + hash_idx = mesh_table_hash(dst, tbl); bucket = &tbl->hash_buckets[hash_idx]; spin_lock(&tbl->hashwlock[hash_idx]); @@ -905,7 +903,7 @@ static int table_path_del(struct mesh_table __rcu *rcu_tbl, int err = 0; tbl = resize_dereference_paths(sdata, rcu_tbl); - hash_idx = mesh_table_hash(addr, sdata, tbl); + hash_idx = mesh_table_hash(addr, tbl); bucket = &tbl->hash_buckets[hash_idx]; spin_lock(&tbl->hashwlock[hash_idx]); @@ -1107,7 +1105,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) node = hlist_entry(p, struct mpath_node, list); mpath = node->mpath; new_node->mpath = mpath; - hash_idx = mesh_table_hash(mpath->dst, mpath->sdata, newtbl); + hash_idx = mesh_table_hash(mpath->dst, newtbl); hlist_add_head(&new_node->list, &newtbl->hash_buckets[hash_idx]); return 0; -- GitLab From b15dc38b9817729d3d4962f8c84bbda0eccb3532 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Feb 2016 20:03:58 -0500 Subject: [PATCH 1323/9938] mac80211: mesh: factor out common mesh path allocation code Remove duplicate code to allocate and initialize a mesh path or mesh proxy path. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh_pathtbl.c | 51 ++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index fc3cc350df8c..4794240e8f94 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -501,6 +501,31 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata) return sdata->u.mesh.num_gates; } +static +struct mesh_path *mesh_path_new(struct ieee80211_sub_if_data *sdata, + const u8 *dst, gfp_t gfp_flags) +{ + struct mesh_path *new_mpath; + + new_mpath = kzalloc(sizeof(struct mesh_path), gfp_flags); + if (!new_mpath) + return NULL; + + memcpy(new_mpath->dst, dst, ETH_ALEN); + eth_broadcast_addr(new_mpath->rann_snd_addr); + new_mpath->is_root = false; + new_mpath->sdata = sdata; + new_mpath->flags = 0; + skb_queue_head_init(&new_mpath->frame_queue); + new_mpath->timer.data = (unsigned long) new_mpath; + new_mpath->timer.function = mesh_path_timer; + new_mpath->exp_time = jiffies; + spin_lock_init(&new_mpath->state_lock); + init_timer(&new_mpath->timer); + + return new_mpath; +} + /** * mesh_path_add - allocate and add a new path to the mesh path table * @dst: destination address of the path (ETH_ALEN length) @@ -548,7 +573,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, } err = -ENOMEM; - new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC); + new_mpath = mesh_path_new(sdata, dst, GFP_ATOMIC); if (!new_mpath) goto err_path_alloc; @@ -556,19 +581,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, if (!new_node) goto err_node_alloc; - memcpy(new_mpath->dst, dst, ETH_ALEN); - eth_broadcast_addr(new_mpath->rann_snd_addr); - new_mpath->is_root = false; - new_mpath->sdata = sdata; - new_mpath->flags = 0; - skb_queue_head_init(&new_mpath->frame_queue); new_node->mpath = new_mpath; - new_mpath->timer.data = (unsigned long) new_mpath; - new_mpath->timer.function = mesh_path_timer; - new_mpath->exp_time = jiffies; - spin_lock_init(&new_mpath->state_lock); - init_timer(&new_mpath->timer); - hlist_add_head_rcu(&new_node->list, bucket); if (atomic_inc_return(&tbl->entries) >= MEAN_CHAIN_LEN * (tbl->hash_mask + 1)) @@ -664,7 +677,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, return -ENOTSUPP; err = -ENOMEM; - new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC); + new_mpath = mesh_path_new(sdata, dst, GFP_ATOMIC); if (!new_mpath) goto err_path_alloc; @@ -672,17 +685,9 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, if (!new_node) goto err_node_alloc; - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - memcpy(new_mpath->dst, dst, ETH_ALEN); memcpy(new_mpath->mpp, mpp, ETH_ALEN); - new_mpath->sdata = sdata; - new_mpath->flags = 0; - skb_queue_head_init(&new_mpath->frame_queue); new_node->mpath = new_mpath; - init_timer(&new_mpath->timer); - new_mpath->exp_time = jiffies; - spin_lock_init(&new_mpath->state_lock); - + read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); tbl = resize_dereference_mpp_paths(sdata); hash_idx = mesh_table_hash(dst, tbl); -- GitLab From 947c2a0eccec29fcd30e717787e65792b1e607ed Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Feb 2016 20:03:59 -0500 Subject: [PATCH 1324/9938] mac80211: mesh: embed known gates list in struct mesh_path The mesh path table uses a struct mesh_node in its hlists in order to support a resizable hash table: the mesh_node provides an indirection to the actual mesh path so that two different bucket lists can point to the same path entry. However, for the known gates list, we don't need this indirection because there is ever only one list. So we can just embed the hlist_node in the mesh path itself, which simplifies things a bit and saves a linear search whenever we need to find an item in the list. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh.h | 1 + net/mac80211/mesh_pathtbl.c | 100 ++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 56 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 601992b6cd8a..f3cc3917e048 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -105,6 +105,7 @@ enum mesh_deferred_task_flags { struct mesh_path { u8 dst[ETH_ALEN]; u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ + struct hlist_node gate_list; struct ieee80211_sub_if_data *sdata; struct sta_info __rcu *next_hop; struct timer_list timer; diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 4794240e8f94..e4daf4b94eaf 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -119,10 +119,18 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) { struct hlist_head *mesh_hash; struct hlist_node *p, *q; - struct mpath_node *gate; + struct mesh_path *gate; int i; mesh_hash = tbl->hash_buckets; + if (free_leafs) { + spin_lock_bh(&tbl->gates_lock); + hlist_for_each_entry_safe(gate, q, + tbl->known_gates, gate_list) + hlist_del(&gate->gate_list); + kfree(tbl->known_gates); + spin_unlock_bh(&tbl->gates_lock); + } for (i = 0; i <= tbl->hash_mask; i++) { spin_lock_bh(&tbl->hashwlock[i]); hlist_for_each_safe(p, q, &mesh_hash[i]) { @@ -131,16 +139,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) } spin_unlock_bh(&tbl->hashwlock[i]); } - if (free_leafs) { - spin_lock_bh(&tbl->gates_lock); - hlist_for_each_entry_safe(gate, q, - tbl->known_gates, list) { - hlist_del(&gate->list); - kfree(gate); - } - kfree(tbl->known_gates); - spin_unlock_bh(&tbl->gates_lock); - } __mesh_table_free(tbl); } @@ -431,30 +429,26 @@ mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) int mesh_path_add_gate(struct mesh_path *mpath) { struct mesh_table *tbl; - struct mpath_node *gate, *new_gate; int err; rcu_read_lock(); tbl = rcu_dereference(mpath->sdata->u.mesh.mesh_paths); - hlist_for_each_entry_rcu(gate, tbl->known_gates, list) - if (gate->mpath == mpath) { - err = -EEXIST; - goto err_rcu; - } - - new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC); - if (!new_gate) { - err = -ENOMEM; + spin_lock_bh(&mpath->state_lock); + if (mpath->is_gate) { + err = -EEXIST; + spin_unlock_bh(&mpath->state_lock); goto err_rcu; } - mpath->is_gate = true; mpath->sdata->u.mesh.num_gates++; - new_gate->mpath = mpath; - spin_lock_bh(&tbl->gates_lock); - hlist_add_head_rcu(&new_gate->list, tbl->known_gates); - spin_unlock_bh(&tbl->gates_lock); + + spin_lock(&tbl->gates_lock); + hlist_add_head_rcu(&mpath->gate_list, tbl->known_gates); + spin_unlock(&tbl->gates_lock); + + spin_unlock_bh(&mpath->state_lock); + mpath_dbg(mpath->sdata, "Mesh path: Recorded new gate: %pM. %d known gates\n", mpath->dst, mpath->sdata->u.mesh.num_gates); @@ -468,28 +462,22 @@ int mesh_path_add_gate(struct mesh_path *mpath) * mesh_gate_del - remove a mesh gate from the list of known gates * @tbl: table which holds our list of known gates * @mpath: gate mpath - * - * Locking: must be called inside rcu_read_lock() section */ static void mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) { - struct mpath_node *gate; - struct hlist_node *q; + lockdep_assert_held(&mpath->state_lock); + if (!mpath->is_gate) + return; - hlist_for_each_entry_safe(gate, q, tbl->known_gates, list) { - if (gate->mpath != mpath) - continue; - spin_lock_bh(&tbl->gates_lock); - hlist_del_rcu(&gate->list); - kfree_rcu(gate, rcu); - spin_unlock_bh(&tbl->gates_lock); - mpath->sdata->u.mesh.num_gates--; - mpath->is_gate = false; - mpath_dbg(mpath->sdata, - "Mesh path: Deleted gate: %pM. %d known gates\n", - mpath->dst, mpath->sdata->u.mesh.num_gates); - break; - } + mpath->is_gate = false; + spin_lock_bh(&tbl->gates_lock); + hlist_del_rcu(&mpath->gate_list); + mpath->sdata->u.mesh.num_gates--; + spin_unlock_bh(&tbl->gates_lock); + + mpath_dbg(mpath->sdata, + "Mesh path: Deleted gate: %pM. %d known gates\n", + mpath->dst, mpath->sdata->u.mesh.num_gates); } /** @@ -781,13 +769,13 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) struct mesh_path *mpath = node->mpath; struct ieee80211_sub_if_data *sdata = node->mpath->sdata; - spin_lock(&mpath->state_lock); + spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING; if (mpath->is_gate) mesh_gate_del(tbl, mpath); hlist_del_rcu(&node->list); call_rcu(&node->rcu, mesh_path_node_reclaim); - spin_unlock(&mpath->state_lock); + spin_unlock_bh(&mpath->state_lock); atomic_dec(&sdata->u.mesh.mpaths); atomic_dec(&tbl->entries); } @@ -999,7 +987,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) struct ieee80211_sub_if_data *sdata = mpath->sdata; struct mesh_table *tbl; struct mesh_path *from_mpath = mpath; - struct mpath_node *gate = NULL; + struct mesh_path *gate = NULL; bool copy = false; struct hlist_head *known_gates; @@ -1011,22 +999,22 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) if (!known_gates) return -EHOSTUNREACH; - hlist_for_each_entry_rcu(gate, known_gates, list) { - if (gate->mpath->flags & MESH_PATH_ACTIVE) { - mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst); - mesh_path_move_to_queue(gate->mpath, from_mpath, copy); - from_mpath = gate->mpath; + hlist_for_each_entry_rcu(gate, known_gates, gate_list) { + if (gate->flags & MESH_PATH_ACTIVE) { + mpath_dbg(sdata, "Forwarding to %pM\n", gate->dst); + mesh_path_move_to_queue(gate, from_mpath, copy); + from_mpath = gate; copy = true; } else { mpath_dbg(sdata, "Not forwarding to %pM (flags %#x)\n", - gate->mpath->dst, gate->mpath->flags); + gate->dst, gate->flags); } } - hlist_for_each_entry_rcu(gate, known_gates, list) { - mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst); - mesh_path_tx_pending(gate->mpath); + hlist_for_each_entry_rcu(gate, known_gates, gate_list) { + mpath_dbg(sdata, "Sending to %pM\n", gate->dst); + mesh_path_tx_pending(gate); } return (from_mpath == mpath) ? -EHOSTUNREACH : 0; -- GitLab From 8f6fd83c6c5ec66a4a70c728535ddcdfef4f3697 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 2 Mar 2016 10:09:19 -0500 Subject: [PATCH 1325/9938] rhashtable: accept GFP flags in rhashtable_walk_init In certain cases, the 802.11 mesh pathtable code wants to iterate over all of the entries in the forwarding table from the receive path, which is inside an RCU read-side critical section. Enable walks inside atomic sections by allowing GFP_ATOMIC allocations for the walker state. Change all existing callsites to pass in GFP_KERNEL. Acked-by: Thomas Graf Signed-off-by: Bob Copeland [also adjust gfs2/glock.c and rhashtable tests] Signed-off-by: Johannes Berg --- fs/gfs2/glock.c | 4 ++-- include/linux/rhashtable.h | 3 ++- lib/rhashtable.c | 6 ++++-- lib/test_rhashtable.c | 2 +- net/ipv6/ila/ila_xlat.c | 3 ++- net/netfilter/nft_hash.c | 4 ++-- net/netlink/af_netlink.c | 3 ++- net/sctp/proc.c | 3 ++- 8 files changed, 17 insertions(+), 11 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 6539131c52a2..4b73bd101bdc 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1913,7 +1913,7 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file) if (seq->buf) seq->size = GFS2_SEQ_GOODSIZE; gi->gl = NULL; - ret = rhashtable_walk_init(&gl_hash_table, &gi->hti); + ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL); } return ret; } @@ -1941,7 +1941,7 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file) if (seq->buf) seq->size = GFS2_SEQ_GOODSIZE; gi->gl = NULL; - ret = rhashtable_walk_init(&gl_hash_table, &gi->hti); + ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL); } return ret; } diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 63bd7601b6de..3eef0802a0cd 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -346,7 +346,8 @@ struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, struct bucket_table *old_tbl); int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *tbl); -int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter); +int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter, + gfp_t gfp); void rhashtable_walk_exit(struct rhashtable_iter *iter); int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU); void *rhashtable_walk_next(struct rhashtable_iter *iter); diff --git a/lib/rhashtable.c b/lib/rhashtable.c index cc808707d1cf..5d845ffd7982 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -487,6 +487,7 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow); * rhashtable_walk_init - Initialise an iterator * @ht: Table to walk over * @iter: Hash table Iterator + * @gfp: GFP flags for allocations * * This function prepares a hash table walk. * @@ -504,14 +505,15 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow); * You must call rhashtable_walk_exit if this function returns * successfully. */ -int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter) +int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter, + gfp_t gfp) { iter->ht = ht; iter->p = NULL; iter->slot = 0; iter->skip = 0; - iter->walker = kmalloc(sizeof(*iter->walker), GFP_KERNEL); + iter->walker = kmalloc(sizeof(*iter->walker), gfp); if (!iter->walker) return -ENOMEM; diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index 270bf7289b1e..297fdb5e74bd 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c @@ -143,7 +143,7 @@ static void test_bucket_stats(struct rhashtable *ht) struct rhashtable_iter hti; struct rhash_head *pos; - err = rhashtable_walk_init(ht, &hti); + err = rhashtable_walk_init(ht, &hti, GFP_KERNEL); if (err) { pr_warn("Test failed: allocation error"); return; diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 295ca29a23c3..0b03533453e4 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -501,7 +501,8 @@ static int ila_nl_dump_start(struct netlink_callback *cb) struct ila_net *ilan = net_generic(net, ila_net_id); struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; - return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter); + return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter, + GFP_KERNEL); } static int ila_nl_dump_done(struct netlink_callback *cb) diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index 3f9d45d3d9b7..6fa016564f90 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c @@ -192,7 +192,7 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); int err; - err = rhashtable_walk_init(&priv->ht, &hti); + err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL); iter->err = err; if (err) return; @@ -248,7 +248,7 @@ static void nft_hash_gc(struct work_struct *work) priv = container_of(work, struct nft_hash, gc_work.work); set = nft_set_container_of(priv); - err = rhashtable_walk_init(&priv->ht, &hti); + err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL); if (err) goto schedule; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 215fc08c02ab..0f16bf635480 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2343,7 +2343,8 @@ static int netlink_walk_start(struct nl_seq_iter *iter) { int err; - err = rhashtable_walk_init(&nl_table[iter->link].hash, &iter->hti); + err = rhashtable_walk_init(&nl_table[iter->link].hash, &iter->hti, + GFP_KERNEL); if (err) { iter->link = MAX_LINKS; return err; diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 5cfac8d5d3b3..6d45d53321e6 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -319,7 +319,8 @@ static int sctp_transport_walk_start(struct seq_file *seq) struct sctp_ht_iter *iter = seq->private; int err; - err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti); + err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti, + GFP_KERNEL); if (err) return err; -- GitLab From 60854fd94573f0d3b80b55b40cf0140a0430f3ab Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 2 Mar 2016 10:09:20 -0500 Subject: [PATCH 1326/9938] mac80211: mesh: convert path table to rhashtable In the time since the mesh path table was implemented as an RCU-traversable, dynamically growing hash table, a generic RCU hashtable implementation was added to the kernel. Switch the mesh path table over to rhashtable to remove some code and also gain some features like automatic shrinking. Cc: Thomas Graf Cc: netdev@vger.kernel.org Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 11 +- net/mac80211/mesh.c | 6 - net/mac80211/mesh.h | 31 +- net/mac80211/mesh_pathtbl.c | 786 ++++++++++++------------------------ 4 files changed, 259 insertions(+), 575 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index db7f0dbebc4b..c8945e2d8a86 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -697,17 +697,10 @@ struct ieee80211_if_mesh { /* offset from skb->data while building IE */ int meshconf_offset; - struct mesh_table __rcu *mesh_paths; - struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */ + struct mesh_table *mesh_paths; + struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ int mesh_paths_generation; int mpp_paths_generation; - - /* Protects assignment of the mesh_paths/mpp_paths table - * pointer for resize against reading it for add/delete - * of individual paths. Pure readers (lookups) just use - * RCU. - */ - rwlock_t pathtbl_resize_lock; }; #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c92af2a7714d..a216c439b6f2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -1347,12 +1347,6 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) mesh_path_start_discovery(sdata); - if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) - mesh_mpath_table_grow(sdata); - - if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags)) - mesh_mpp_table_grow(sdata); - if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) ieee80211_mesh_housekeeping(sdata); diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index f3cc3917e048..cc6854db156e 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -51,10 +51,6 @@ enum mesh_path_flags { * * * @MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks - * @MESH_WORK_GROW_MPATH_TABLE: the mesh path table is full and needs - * to grow. - * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to - * grow * @MESH_WORK_ROOT: the mesh root station needs to send a frame * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other * mesh nodes @@ -62,8 +58,6 @@ enum mesh_path_flags { */ enum mesh_deferred_task_flags { MESH_WORK_HOUSEKEEPING, - MESH_WORK_GROW_MPATH_TABLE, - MESH_WORK_GROW_MPP_TABLE, MESH_WORK_ROOT, MESH_WORK_DRIFT_ADJUST, MESH_WORK_MBSS_CHANGED, @@ -105,6 +99,7 @@ enum mesh_deferred_task_flags { struct mesh_path { u8 dst[ETH_ALEN]; u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ + struct rhash_head rhash; struct hlist_node gate_list; struct ieee80211_sub_if_data *sdata; struct sta_info __rcu *next_hop; @@ -129,34 +124,17 @@ struct mesh_path { /** * struct mesh_table * - * @hash_buckets: array of hash buckets of the table - * @hashwlock: array of locks to protect write operations, one per bucket - * @hash_mask: 2^size_order - 1, used to compute hash idx - * @hash_rnd: random value used for hash computations * @entries: number of entries in the table - * @free_node: function to free nodes of the table - * @copy_node: function to copy nodes of the table - * @size_order: determines size of the table, there will be 2^size_order hash - * buckets * @known_gates: list of known mesh gates and their mpaths by the station. The * gate's mpath may or may not be resolved and active. - * - * rcu_head: RCU head to free the table + * @rhash: the rhashtable containing struct mesh_paths, keyed by dest addr */ struct mesh_table { - /* Number of buckets will be 2^N */ - struct hlist_head *hash_buckets; - spinlock_t *hashwlock; /* One per bucket, for add/del */ - unsigned int hash_mask; /* (2^size_order) - 1 */ - __u32 hash_rnd; /* Used for hash generation */ atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ - void (*free_node) (struct hlist_node *p, bool free_leafs); - int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); - int size_order; struct hlist_head *known_gates; spinlock_t gates_lock; - struct rcu_head rcu_head; + struct rhashtable rhead; }; /* Recent multicast cache */ @@ -300,9 +278,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, void mesh_sta_cleanup(struct sta_info *sta); /* Private interfaces */ -/* Mesh tables */ -void mesh_mpath_table_grow(struct ieee80211_sub_if_data *sdata); -void mesh_mpp_table_grow(struct ieee80211_sub_if_data *sdata); /* Mesh paths */ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, u8 ttl, const u8 *target, u32 target_sn, diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index e4daf4b94eaf..7455397f8c3b 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -18,11 +18,20 @@ #include "ieee80211_i.h" #include "mesh.h" -/* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */ -#define INIT_PATHS_SIZE_ORDER 2 +static u32 mesh_table_hash(const void *addr, u32 len, u32 seed) +{ + /* Use last four bytes of hw addr as hash index */ + return jhash_1word(*(u32 *)(addr+2), seed); +} -/* Keep the mean chain length below this constant */ -#define MEAN_CHAIN_LEN 2 +static const struct rhashtable_params mesh_rht_params = { + .nelem_hint = 2, + .automatic_shrinking = true, + .key_len = ETH_ALEN, + .key_offset = offsetof(struct mesh_path, dst), + .head_offset = offsetof(struct mesh_path, rhash), + .hashfn = mesh_table_hash, +}; static inline bool mpath_expired(struct mesh_path *mpath) { @@ -31,157 +40,47 @@ static inline bool mpath_expired(struct mesh_path *mpath) !(mpath->flags & MESH_PATH_FIXED); } -struct mpath_node { - struct hlist_node list; - struct rcu_head rcu; - /* This indirection allows two different tables to point to the same - * mesh_path structure, useful when resizing - */ - struct mesh_path *mpath; -}; - -static inline struct mesh_table *resize_dereference_paths( - struct ieee80211_sub_if_data *sdata, - struct mesh_table __rcu *table) +static void mesh_path_reclaim(struct rcu_head *rp) { - return rcu_dereference_protected(table, - lockdep_is_held(&sdata->u.mesh.pathtbl_resize_lock)); -} + struct mesh_path *mpath = container_of(rp, struct mesh_path, rcu); -static inline struct mesh_table *resize_dereference_mesh_paths( - struct ieee80211_sub_if_data *sdata) -{ - return resize_dereference_paths(sdata, sdata->u.mesh.mesh_paths); + del_timer_sync(&mpath->timer); + kfree(mpath); } -static inline struct mesh_table *resize_dereference_mpp_paths( - struct ieee80211_sub_if_data *sdata) +static void mesh_path_rht_free(void *ptr, void *unused_arg) { - return resize_dereference_paths(sdata, sdata->u.mesh.mpp_paths); + struct mesh_path *mpath = ptr; + call_rcu(&mpath->rcu, mesh_path_reclaim); } -/* - * CAREFUL -- "tbl" must not be an expression, - * in particular not an rcu_dereference(), since - * it's used twice. So it is illegal to do - * for_each_mesh_entry(rcu_dereference(...), ...) - */ -#define for_each_mesh_entry(tbl, node, i) \ - for (i = 0; i <= tbl->hash_mask; i++) \ - hlist_for_each_entry_rcu(node, &tbl->hash_buckets[i], list) - - -static struct mesh_table *mesh_table_alloc(int size_order) +static struct mesh_table *mesh_table_alloc(void) { - int i; struct mesh_table *newtbl; newtbl = kmalloc(sizeof(struct mesh_table), GFP_ATOMIC); if (!newtbl) return NULL; - newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * - (1 << size_order), GFP_ATOMIC); - - if (!newtbl->hash_buckets) { + newtbl->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); + if (!newtbl->known_gates) { kfree(newtbl); return NULL; } - - newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * - (1 << size_order), GFP_ATOMIC); - if (!newtbl->hashwlock) { - kfree(newtbl->hash_buckets); - kfree(newtbl); - return NULL; - } - - newtbl->size_order = size_order; - newtbl->hash_mask = (1 << size_order) - 1; + INIT_HLIST_HEAD(newtbl->known_gates); atomic_set(&newtbl->entries, 0); - get_random_bytes(&newtbl->hash_rnd, - sizeof(newtbl->hash_rnd)); - for (i = 0; i <= newtbl->hash_mask; i++) - spin_lock_init(&newtbl->hashwlock[i]); spin_lock_init(&newtbl->gates_lock); return newtbl; } -static void __mesh_table_free(struct mesh_table *tbl) +static void mesh_table_free(struct mesh_table *tbl) { - kfree(tbl->hash_buckets); - kfree(tbl->hashwlock); + rhashtable_free_and_destroy(&tbl->rhead, + mesh_path_rht_free, NULL); kfree(tbl); } -static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) -{ - struct hlist_head *mesh_hash; - struct hlist_node *p, *q; - struct mesh_path *gate; - int i; - - mesh_hash = tbl->hash_buckets; - if (free_leafs) { - spin_lock_bh(&tbl->gates_lock); - hlist_for_each_entry_safe(gate, q, - tbl->known_gates, gate_list) - hlist_del(&gate->gate_list); - kfree(tbl->known_gates); - spin_unlock_bh(&tbl->gates_lock); - } - for (i = 0; i <= tbl->hash_mask; i++) { - spin_lock_bh(&tbl->hashwlock[i]); - hlist_for_each_safe(p, q, &mesh_hash[i]) { - tbl->free_node(p, free_leafs); - atomic_dec(&tbl->entries); - } - spin_unlock_bh(&tbl->hashwlock[i]); - } - - __mesh_table_free(tbl); -} - -static int mesh_table_grow(struct mesh_table *oldtbl, - struct mesh_table *newtbl) -{ - struct hlist_head *oldhash; - struct hlist_node *p, *q; - int i; - - if (atomic_read(&oldtbl->entries) - < MEAN_CHAIN_LEN * (oldtbl->hash_mask + 1)) - return -EAGAIN; - - newtbl->free_node = oldtbl->free_node; - newtbl->copy_node = oldtbl->copy_node; - newtbl->known_gates = oldtbl->known_gates; - atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); - - oldhash = oldtbl->hash_buckets; - for (i = 0; i <= oldtbl->hash_mask; i++) - hlist_for_each(p, &oldhash[i]) - if (oldtbl->copy_node(p, newtbl) < 0) - goto errcopy; - - return 0; - -errcopy: - for (i = 0; i <= newtbl->hash_mask; i++) { - hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) - oldtbl->free_node(p, 0); - } - return -ENOMEM; -} - -static u32 mesh_table_hash(const u8 *addr, struct mesh_table *tbl) -{ - /* Use last four bytes of hw addr as hash index */ - return jhash_1word(*(u32 *)(addr+2), tbl->hash_rnd) & tbl->hash_mask; -} - - /** * * mesh_path_assign_nexthop - update mesh path next hop @@ -324,22 +223,15 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; - struct hlist_head *bucket; - struct mpath_node *node; - - bucket = &tbl->hash_buckets[mesh_table_hash(dst, tbl)]; - hlist_for_each_entry_rcu(node, bucket, list) { - mpath = node->mpath; - if (ether_addr_equal(dst, mpath->dst)) { - if (mpath_expired(mpath)) { - spin_lock_bh(&mpath->state_lock); - mpath->flags &= ~MESH_PATH_ACTIVE; - spin_unlock_bh(&mpath->state_lock); - } - return mpath; - } + + mpath = rhashtable_lookup_fast(&tbl->rhead, dst, mesh_rht_params); + + if (mpath && mpath_expired(mpath)) { + spin_lock_bh(&mpath->state_lock); + mpath->flags &= ~MESH_PATH_ACTIVE; + spin_unlock_bh(&mpath->state_lock); } - return NULL; + return mpath; } /** @@ -354,17 +246,52 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, struct mesh_path * mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) { - return mpath_lookup(rcu_dereference(sdata->u.mesh.mesh_paths), dst, - sdata); + return mpath_lookup(sdata->u.mesh.mesh_paths, dst, sdata); } struct mesh_path * mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) { - return mpath_lookup(rcu_dereference(sdata->u.mesh.mpp_paths), dst, - sdata); + return mpath_lookup(sdata->u.mesh.mpp_paths, dst, sdata); } +static struct mesh_path * +__mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx) +{ + int i = 0, ret; + struct mesh_path *mpath = NULL; + struct rhashtable_iter iter; + + ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); + if (ret) + return NULL; + + ret = rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto err; + + while ((mpath = rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + if (i++ == idx) + break; + } +err: + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); + + if (IS_ERR(mpath) || !mpath) + return NULL; + + if (mpath_expired(mpath)) { + spin_lock_bh(&mpath->state_lock); + mpath->flags &= ~MESH_PATH_ACTIVE; + spin_unlock_bh(&mpath->state_lock); + } + return mpath; +} /** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index @@ -378,23 +305,7 @@ mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) struct mesh_path * mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) { - struct mesh_table *tbl = rcu_dereference(sdata->u.mesh.mesh_paths); - struct mpath_node *node; - int i; - int j = 0; - - for_each_mesh_entry(tbl, node, i) { - if (j++ == idx) { - if (mpath_expired(node->mpath)) { - spin_lock_bh(&node->mpath->state_lock); - node->mpath->flags &= ~MESH_PATH_ACTIVE; - spin_unlock_bh(&node->mpath->state_lock); - } - return node->mpath; - } - } - - return NULL; + return __mesh_path_lookup_by_idx(sdata->u.mesh.mesh_paths, idx); } /** @@ -409,17 +320,7 @@ mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) struct mesh_path * mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) { - struct mesh_table *tbl = rcu_dereference(sdata->u.mesh.mpp_paths); - struct mpath_node *node; - int i; - int j = 0; - - for_each_mesh_entry(tbl, node, i) { - if (j++ == idx) - return node->mpath; - } - - return NULL; + return __mesh_path_lookup_by_idx(sdata->u.mesh.mpp_paths, idx); } /** @@ -432,7 +333,7 @@ int mesh_path_add_gate(struct mesh_path *mpath) int err; rcu_read_lock(); - tbl = rcu_dereference(mpath->sdata->u.mesh.mesh_paths); + tbl = mpath->sdata->u.mesh.mesh_paths; spin_lock_bh(&mpath->state_lock); if (mpath->is_gate) { @@ -526,15 +427,9 @@ struct mesh_path *mesh_path_new(struct ieee80211_sub_if_data *sdata, struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) { - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct ieee80211_local *local = sdata->local; struct mesh_table *tbl; struct mesh_path *mpath, *new_mpath; - struct mpath_node *node, *new_node; - struct hlist_head *bucket; - int grow = 0; - int err; - u32 hash_idx; + int ret; if (ether_addr_equal(dst, sdata->vif.addr)) /* never add ourselves as neighbours */ @@ -546,116 +441,44 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) return ERR_PTR(-ENOSPC); - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(sdata); - - hash_idx = mesh_table_hash(dst, tbl); - bucket = &tbl->hash_buckets[hash_idx]; - - spin_lock(&tbl->hashwlock[hash_idx]); - - hlist_for_each_entry(node, bucket, list) { - mpath = node->mpath; - if (ether_addr_equal(dst, mpath->dst)) - goto found; - } - - err = -ENOMEM; new_mpath = mesh_path_new(sdata, dst, GFP_ATOMIC); if (!new_mpath) - goto err_path_alloc; - - new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC); - if (!new_node) - goto err_node_alloc; - - new_node->mpath = new_mpath; - hlist_add_head_rcu(&new_node->list, bucket); - if (atomic_inc_return(&tbl->entries) >= - MEAN_CHAIN_LEN * (tbl->hash_mask + 1)) - grow = 1; - - sdata->u.mesh.mesh_paths_generation++; - - if (grow) { - set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); - ieee80211_queue_work(&local->hw, &sdata->work); - } - mpath = new_mpath; -found: - spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - return mpath; - -err_node_alloc: - kfree(new_mpath); -err_path_alloc: - atomic_dec(&sdata->u.mesh.mpaths); - spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - return ERR_PTR(err); -} - -static void mesh_table_free_rcu(struct rcu_head *rcu) -{ - struct mesh_table *tbl = container_of(rcu, struct mesh_table, rcu_head); - - mesh_table_free(tbl, false); -} - -void mesh_mpath_table_grow(struct ieee80211_sub_if_data *sdata) -{ - struct mesh_table *oldtbl, *newtbl; + return ERR_PTR(-ENOMEM); - write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - oldtbl = resize_dereference_mesh_paths(sdata); - newtbl = mesh_table_alloc(oldtbl->size_order + 1); - if (!newtbl) - goto out; - if (mesh_table_grow(oldtbl, newtbl) < 0) { - __mesh_table_free(newtbl); - goto out; - } - rcu_assign_pointer(sdata->u.mesh.mesh_paths, newtbl); + tbl = sdata->u.mesh.mesh_paths; + do { + ret = rhashtable_lookup_insert_fast(&tbl->rhead, + &new_mpath->rhash, + mesh_rht_params); - call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu); + if (ret == -EEXIST) + mpath = rhashtable_lookup_fast(&tbl->rhead, + dst, + mesh_rht_params); - out: - write_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); -} + } while (unlikely(ret == -EEXIST && !mpath)); -void mesh_mpp_table_grow(struct ieee80211_sub_if_data *sdata) -{ - struct mesh_table *oldtbl, *newtbl; + if (ret && ret != -EEXIST) + return ERR_PTR(ret); - write_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - oldtbl = resize_dereference_mpp_paths(sdata); - newtbl = mesh_table_alloc(oldtbl->size_order + 1); - if (!newtbl) - goto out; - if (mesh_table_grow(oldtbl, newtbl) < 0) { - __mesh_table_free(newtbl); - goto out; + /* At this point either new_mpath was added, or we found a + * matching entry already in the table; in the latter case + * free the unnecessary new entry. + */ + if (ret == -EEXIST) { + kfree(new_mpath); + new_mpath = mpath; } - rcu_assign_pointer(sdata->u.mesh.mpp_paths, newtbl); - call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu); - - out: - write_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); + sdata->u.mesh.mesh_paths_generation++; + return new_mpath; } int mpp_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst, const u8 *mpp) { - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct ieee80211_local *local = sdata->local; struct mesh_table *tbl; - struct mesh_path *mpath, *new_mpath; - struct mpath_node *node, *new_node; - struct hlist_head *bucket; - int grow = 0; - int err = 0; - u32 hash_idx; + struct mesh_path *new_mpath; + int ret; if (ether_addr_equal(dst, sdata->vif.addr)) /* never add ourselves as neighbours */ @@ -664,56 +487,19 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, if (is_multicast_ether_addr(dst)) return -ENOTSUPP; - err = -ENOMEM; new_mpath = mesh_path_new(sdata, dst, GFP_ATOMIC); - if (!new_mpath) - goto err_path_alloc; - new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC); - if (!new_node) - goto err_node_alloc; + if (!new_mpath) + return -ENOMEM; memcpy(new_mpath->mpp, mpp, ETH_ALEN); - new_node->mpath = new_mpath; - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - tbl = resize_dereference_mpp_paths(sdata); - - hash_idx = mesh_table_hash(dst, tbl); - bucket = &tbl->hash_buckets[hash_idx]; - - spin_lock(&tbl->hashwlock[hash_idx]); - - err = -EEXIST; - hlist_for_each_entry(node, bucket, list) { - mpath = node->mpath; - if (ether_addr_equal(dst, mpath->dst)) - goto err_exists; - } - - hlist_add_head_rcu(&new_node->list, bucket); - if (atomic_inc_return(&tbl->entries) >= - MEAN_CHAIN_LEN * (tbl->hash_mask + 1)) - grow = 1; - - spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); + tbl = sdata->u.mesh.mpp_paths; + ret = rhashtable_lookup_insert_fast(&tbl->rhead, + &new_mpath->rhash, + mesh_rht_params); sdata->u.mesh.mpp_paths_generation++; - - if (grow) { - set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); - ieee80211_queue_work(&local->hw, &sdata->work); - } - return 0; - -err_exists: - spin_unlock(&tbl->hashwlock[hash_idx]); - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - kfree(new_node); -err_node_alloc: - kfree(new_mpath); -err_path_alloc: - return err; + return ret; } @@ -727,17 +513,26 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, */ void mesh_plink_broken(struct sta_info *sta) { - struct mesh_table *tbl; + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct mesh_table *tbl = sdata->u.mesh.mesh_paths; static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct mesh_path *mpath; - struct mpath_node *node; - struct ieee80211_sub_if_data *sdata = sta->sdata; - int i; + struct rhashtable_iter iter; + int ret; - rcu_read_lock(); - tbl = rcu_dereference(sdata->u.mesh.mesh_paths); - for_each_mesh_entry(tbl, node, i) { - mpath = node->mpath; + ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); + if (ret) + return; + + ret = rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; if (rcu_access_pointer(mpath->next_hop) == sta && mpath->flags & MESH_PATH_ACTIVE && !(mpath->flags & MESH_PATH_FIXED)) { @@ -751,30 +546,20 @@ void mesh_plink_broken(struct sta_info *sta) WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast); } } - rcu_read_unlock(); -} - -static void mesh_path_node_reclaim(struct rcu_head *rp) -{ - struct mpath_node *node = container_of(rp, struct mpath_node, rcu); - - del_timer_sync(&node->mpath->timer); - kfree(node->mpath); - kfree(node); +out: + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); } -/* needs to be called with the corresponding hashwlock taken */ -static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) +static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath) { - struct mesh_path *mpath = node->mpath; - struct ieee80211_sub_if_data *sdata = node->mpath->sdata; + struct ieee80211_sub_if_data *sdata = mpath->sdata; + rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params); spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING; - if (mpath->is_gate) - mesh_gate_del(tbl, mpath); - hlist_del_rcu(&node->list); - call_rcu(&node->rcu, mesh_path_node_reclaim); + mesh_gate_del(tbl, mpath); + call_rcu(&mpath->rcu, mesh_path_reclaim); spin_unlock_bh(&mpath->state_lock); atomic_dec(&sdata->u.mesh.mpaths); atomic_dec(&tbl->entries); @@ -794,63 +579,87 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) void mesh_path_flush_by_nexthop(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; - struct mesh_table *tbl; + struct mesh_table *tbl = sdata->u.mesh.mesh_paths; struct mesh_path *mpath; - struct mpath_node *node; - int i; + struct rhashtable_iter iter; + int ret; - rcu_read_lock(); - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(sdata); - for_each_mesh_entry(tbl, node, i) { - mpath = node->mpath; - if (rcu_access_pointer(mpath->next_hop) == sta) { - spin_lock(&tbl->hashwlock[i]); - __mesh_path_del(tbl, node); - spin_unlock(&tbl->hashwlock[i]); - } + ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); + if (ret) + return; + + ret = rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + + if (rcu_access_pointer(mpath->next_hop) == sta) + __mesh_path_del(tbl, mpath); } - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - rcu_read_unlock(); +out: + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); } static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, const u8 *proxy) { - struct mesh_table *tbl; - struct mesh_path *mpp; - struct mpath_node *node; - int i; + struct mesh_table *tbl = sdata->u.mesh.mpp_paths; + struct mesh_path *mpath; + struct rhashtable_iter iter; + int ret; - rcu_read_lock(); - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - tbl = resize_dereference_mpp_paths(sdata); - for_each_mesh_entry(tbl, node, i) { - mpp = node->mpath; - if (ether_addr_equal(mpp->mpp, proxy)) { - spin_lock(&tbl->hashwlock[i]); - __mesh_path_del(tbl, node); - spin_unlock(&tbl->hashwlock[i]); - } + ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); + if (ret) + return; + + ret = rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + + if (ether_addr_equal(mpath->mpp, proxy)) + __mesh_path_del(tbl, mpath); } - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - rcu_read_unlock(); +out: + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); } -static void table_flush_by_iface(struct mesh_table *tbl, - struct ieee80211_sub_if_data *sdata) +static void table_flush_by_iface(struct mesh_table *tbl) { struct mesh_path *mpath; - struct mpath_node *node; - int i; - - WARN_ON(!rcu_read_lock_held()); - for_each_mesh_entry(tbl, node, i) { - mpath = node->mpath; - spin_lock_bh(&tbl->hashwlock[i]); - __mesh_path_del(tbl, node); - spin_unlock_bh(&tbl->hashwlock[i]); + struct rhashtable_iter iter; + int ret; + + ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); + if (ret) + return; + + ret = rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + __mesh_path_del(tbl, mpath); } +out: + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); } /** @@ -863,16 +672,8 @@ static void table_flush_by_iface(struct mesh_table *tbl, */ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) { - struct mesh_table *tbl; - - rcu_read_lock(); - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(sdata); - table_flush_by_iface(tbl, sdata); - tbl = resize_dereference_mpp_paths(sdata); - table_flush_by_iface(tbl, sdata); - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - rcu_read_unlock(); + table_flush_by_iface(sdata->u.mesh.mesh_paths); + table_flush_by_iface(sdata->u.mesh.mpp_paths); } /** @@ -884,36 +685,25 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) * * Returns: 0 if successful */ -static int table_path_del(struct mesh_table __rcu *rcu_tbl, +static int table_path_del(struct mesh_table *tbl, struct ieee80211_sub_if_data *sdata, const u8 *addr) { - struct mesh_table *tbl; struct mesh_path *mpath; - struct mpath_node *node; - struct hlist_head *bucket; - int hash_idx; - int err = 0; - - tbl = resize_dereference_paths(sdata, rcu_tbl); - hash_idx = mesh_table_hash(addr, tbl); - bucket = &tbl->hash_buckets[hash_idx]; - - spin_lock(&tbl->hashwlock[hash_idx]); - hlist_for_each_entry(node, bucket, list) { - mpath = node->mpath; - if (ether_addr_equal(addr, mpath->dst)) { - __mesh_path_del(tbl, node); - goto enddel; - } + + rcu_read_lock(); + mpath = rhashtable_lookup_fast(&tbl->rhead, addr, mesh_rht_params); + if (!mpath) { + rcu_read_unlock(); + return -ENXIO; } - err = -ENXIO; -enddel: - spin_unlock(&tbl->hashwlock[hash_idx]); - return err; + __mesh_path_del(tbl, mpath); + rcu_read_unlock(); + return 0; } + /** * mesh_path_del - delete a mesh path from the table * @@ -924,36 +714,13 @@ static int table_path_del(struct mesh_table __rcu *rcu_tbl, */ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) { - int err = 0; + int err; /* flush relevant mpp entries first */ mpp_flush_by_proxy(sdata, addr); - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); err = table_path_del(sdata->u.mesh.mesh_paths, sdata, addr); sdata->u.mesh.mesh_paths_generation++; - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - - return err; -} - -/** - * mpp_path_del - delete a mesh proxy path from the table - * - * @addr: addr address (ETH_ALEN length) - * @sdata: local subif - * - * Returns: 0 if successful - */ -static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) -{ - int err = 0; - - read_lock_bh(&sdata->u.mesh.pathtbl_resize_lock); - err = table_path_del(sdata->u.mesh.mpp_paths, sdata, addr); - sdata->u.mesh.mpp_paths_generation++; - read_unlock_bh(&sdata->u.mesh.pathtbl_resize_lock); - return err; } @@ -987,18 +754,17 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) struct ieee80211_sub_if_data *sdata = mpath->sdata; struct mesh_table *tbl; struct mesh_path *from_mpath = mpath; - struct mesh_path *gate = NULL; + struct mesh_path *gate; bool copy = false; struct hlist_head *known_gates; - rcu_read_lock(); - tbl = rcu_dereference(sdata->u.mesh.mesh_paths); + tbl = sdata->u.mesh.mesh_paths; known_gates = tbl->known_gates; - rcu_read_unlock(); if (!known_gates) return -EHOSTUNREACH; + rcu_read_lock(); hlist_for_each_entry_rcu(gate, known_gates, gate_list) { if (gate->flags & MESH_PATH_ACTIVE) { mpath_dbg(sdata, "Forwarding to %pM\n", gate->dst); @@ -1016,6 +782,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) mpath_dbg(sdata, "Sending to %pM\n", gate->dst); mesh_path_tx_pending(gate); } + rcu_read_unlock(); return (from_mpath == mpath) ? -EHOSTUNREACH : 0; } @@ -1072,118 +839,73 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop) mesh_path_tx_pending(mpath); } -static void mesh_path_node_free(struct hlist_node *p, bool free_leafs) -{ - struct mesh_path *mpath; - struct mpath_node *node = hlist_entry(p, struct mpath_node, list); - mpath = node->mpath; - hlist_del_rcu(p); - if (free_leafs) { - del_timer_sync(&mpath->timer); - kfree(mpath); - } - kfree(node); -} - -static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) -{ - struct mesh_path *mpath; - struct mpath_node *node, *new_node; - u32 hash_idx; - - new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC); - if (new_node == NULL) - return -ENOMEM; - - node = hlist_entry(p, struct mpath_node, list); - mpath = node->mpath; - new_node->mpath = mpath; - hash_idx = mesh_table_hash(mpath->dst, newtbl); - hlist_add_head(&new_node->list, - &newtbl->hash_buckets[hash_idx]); - return 0; -} - int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) { struct mesh_table *tbl_path, *tbl_mpp; int ret; - tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + tbl_path = mesh_table_alloc(); if (!tbl_path) return -ENOMEM; - tbl_path->free_node = &mesh_path_node_free; - tbl_path->copy_node = &mesh_path_node_copy; - tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); - if (!tbl_path->known_gates) { - ret = -ENOMEM; - goto free_path; - } - INIT_HLIST_HEAD(tbl_path->known_gates); - - tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + tbl_mpp = mesh_table_alloc(); if (!tbl_mpp) { ret = -ENOMEM; goto free_path; } - tbl_mpp->free_node = &mesh_path_node_free; - tbl_mpp->copy_node = &mesh_path_node_copy; - tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); - if (!tbl_mpp->known_gates) { - ret = -ENOMEM; - goto free_mpp; - } - INIT_HLIST_HEAD(tbl_mpp->known_gates); - rwlock_init(&sdata->u.mesh.pathtbl_resize_lock); + rhashtable_init(&tbl_path->rhead, &mesh_rht_params); + rhashtable_init(&tbl_mpp->rhead, &mesh_rht_params); - /* Need no locking since this is during init */ - RCU_INIT_POINTER(sdata->u.mesh.mesh_paths, tbl_path); - RCU_INIT_POINTER(sdata->u.mesh.mpp_paths, tbl_mpp); + sdata->u.mesh.mesh_paths = tbl_path; + sdata->u.mesh.mpp_paths = tbl_mpp; return 0; -free_mpp: - mesh_table_free(tbl_mpp, true); free_path: - mesh_table_free(tbl_path, true); + mesh_table_free(tbl_path); return ret; } -void mesh_path_expire(struct ieee80211_sub_if_data *sdata) +static +void mesh_path_tbl_expire(struct ieee80211_sub_if_data *sdata, + struct mesh_table *tbl) { - struct mesh_table *tbl; struct mesh_path *mpath; - struct mpath_node *node; - int i; + struct rhashtable_iter iter; + int ret; - rcu_read_lock(); - tbl = rcu_dereference(sdata->u.mesh.mesh_paths); - for_each_mesh_entry(tbl, node, i) { - mpath = node->mpath; + ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_KERNEL); + if (ret) + return; + + ret = rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; if ((!(mpath->flags & MESH_PATH_RESOLVING)) && (!(mpath->flags & MESH_PATH_FIXED)) && time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) - mesh_path_del(sdata, mpath->dst); - } - - tbl = rcu_dereference(sdata->u.mesh.mpp_paths); - for_each_mesh_entry(tbl, node, i) { - mpath = node->mpath; - if ((!(mpath->flags & MESH_PATH_FIXED)) && - time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) - mpp_path_del(sdata, mpath->dst); + __mesh_path_del(tbl, mpath); } +out: + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); +} - rcu_read_unlock(); +void mesh_path_expire(struct ieee80211_sub_if_data *sdata) +{ + mesh_path_tbl_expire(sdata, sdata->u.mesh.mesh_paths); + mesh_path_tbl_expire(sdata, sdata->u.mesh.mpp_paths); } void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata) { - /* no need for locking during exit path */ - mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mesh_paths, 1), - true); - mesh_table_free(rcu_dereference_protected(sdata->u.mesh.mpp_paths, 1), - true); + mesh_table_free(sdata->u.mesh.mesh_paths); + mesh_table_free(sdata->u.mesh.mpp_paths); } -- GitLab From f59374eb427fb1377fdb7b8b3691c48e0c77a3c4 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 2 Mar 2016 23:46:14 +0200 Subject: [PATCH 1327/9938] mac80211: synchronize driver rx queues before removing a station Some devices, like iwlwifi, have RSS queues. This may cause a situation where a disassociation is handled in control path and results in station removal while there are prior RX frames that were still not processed in other queues. When they will be processed the station will be gone, and the frames will be dropped. Add a synchronization interface to avoid that. When driver returns from the synchronization mac80211 may remove the station. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/mac80211.h | 5 +++++ net/mac80211/driver-ops.h | 15 +++++++++++++++ net/mac80211/sta_info.c | 9 ++++++++- net/mac80211/trace.h | 12 ++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7cb791f21722..a53333cb1528 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3354,6 +3354,10 @@ enum ieee80211_reconfig_type { * the function call. * * @wake_tx_queue: Called when new packets have been added to the queue. + * @sync_rx_queues: Process all pending frames in RSS queues. This is a + * synchronization which is needed in case driver has in its RSS queues + * pending frames that were received prior to the control path action + * currently taken (e.g. disassociation) but are not processed yet. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, @@ -3591,6 +3595,7 @@ struct ieee80211_ops { void (*wake_tx_queue)(struct ieee80211_hw *hw, struct ieee80211_txq *txq); + void (*sync_rx_queues)(struct ieee80211_hw *hw); }; /** diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 18b0d65baff0..184473c257eb 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -1,3 +1,8 @@ +/* +* Portions of this file +* Copyright(c) 2016 Intel Deutschland GmbH +*/ + #ifndef __MAC80211_DRIVER_OPS #define __MAC80211_DRIVER_OPS @@ -29,6 +34,16 @@ static inline void drv_tx(struct ieee80211_local *local, local->ops->tx(&local->hw, control, skb); } +static inline void drv_sync_rx_queues(struct ieee80211_local *local, + struct sta_info *sta) +{ + if (local->ops->sync_rx_queues) { + trace_drv_sync_rx_queues(local, sta->sdata, &sta->sta); + local->ops->sync_rx_queues(&local->hw); + trace_drv_return_void(local); + } +} + static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, u32 sset, u8 *data) { diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d20bab5c146c..00c82fb152c0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2,7 +2,7 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2006-2007 Jiri Benc * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright (C) 2015 Intel Deutschland GmbH + * Copyright (C) 2015 - 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -875,6 +875,13 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta) set_sta_flag(sta, WLAN_STA_BLOCK_BA); ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA); + /* + * Before removing the station from the driver there might be pending + * rx frames on RSS queues sent prior to the disassociation - wait for + * all such frames to be processed. + */ + drv_sync_rx_queues(local, sta); + ret = sta_info_hash_del(local, sta); if (WARN_ON(ret)) return ret; diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 2b0a17ee907a..8c3b7ae103bc 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -1,3 +1,8 @@ +/* +* Portions of this file +* Copyright(c) 2016 Intel Deutschland GmbH +*/ + #if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ) #define __MAC80211_DRIVER_TRACE @@ -899,6 +904,13 @@ DEFINE_EVENT(sta_event, drv_sta_pre_rcu_remove, TP_ARGS(local, sdata, sta) ); +DEFINE_EVENT(sta_event, drv_sync_rx_queues, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta), + TP_ARGS(local, sdata, sta) +); + DEFINE_EVENT(sta_event, drv_sta_rate_tbl_update, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, -- GitLab From 38de03d2a28925b489c11546804e2f5418cc17a4 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 2 Mar 2016 20:37:18 +0100 Subject: [PATCH 1328/9938] nl80211: add feature for BSS selection support Introducing a new feature that the driver can use to indicate the driver/firmware supports configuration of BSS selection criteria upon CONNECT command. This can be useful when multiple BSS-es are found belonging to the same ESS, ie. Infra-BSS with same SSID. The criteria can then be used to offload selection of a preferred BSS. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Lei Zhang Signed-off-by: Arend van Spriel [move wiphy support check into parse_bss_select()] Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 34 +++++++++++ include/uapi/linux/nl80211.h | 52 ++++++++++++++++ net/wireless/core.c | 7 +++ net/wireless/nl80211.c | 111 +++++++++++++++++++++++++++++++++++ 4 files changed, 204 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 14c0c437d973..0bbfbf3cbca8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1858,6 +1858,33 @@ struct cfg80211_ibss_params { struct ieee80211_ht_cap ht_capa_mask; }; +/** + * struct cfg80211_bss_select_adjust - BSS selection with RSSI adjustment. + * + * @band: band of BSS which should match for RSSI level adjustment. + * @delta: value of RSSI level adjustment. + */ +struct cfg80211_bss_select_adjust { + enum ieee80211_band band; + s8 delta; +}; + +/** + * struct cfg80211_bss_selection - connection parameters for BSS selection. + * + * @behaviour: requested BSS selection behaviour. + * @param: parameters for requestion behaviour. + * @band_pref: preferred band for %NL80211_BSS_SELECT_ATTR_BAND_PREF. + * @adjust: parameters for %NL80211_BSS_SELECT_ATTR_RSSI_ADJUST. + */ +struct cfg80211_bss_selection { + enum nl80211_bss_select_attr behaviour; + union { + enum ieee80211_band band_pref; + struct cfg80211_bss_select_adjust adjust; + } param; +}; + /** * struct cfg80211_connect_params - Connection parameters * @@ -1895,6 +1922,7 @@ struct cfg80211_ibss_params { * @vht_capa_mask: The bits of vht_capa which are to be used. * @pbss: if set, connect to a PCP instead of AP. Valid for DMG * networks. + * @bss_select: criteria to be used for BSS selection. */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -1918,6 +1946,7 @@ struct cfg80211_connect_params { struct ieee80211_vht_cap vht_capa; struct ieee80211_vht_cap vht_capa_mask; bool pbss; + struct cfg80211_bss_selection bss_select; }; /** @@ -3186,6 +3215,9 @@ struct wiphy_vendor_command { * low rssi when a frame is heard on different channel, then it should set * this variable to the maximal offset for which it can compensate. * This value should be set in MHz. + * @bss_select_support: bitmask indicating the BSS selection criteria supported + * by the driver in the .connect() callback. The bit position maps to the + * attribute indices defined in &enum nl80211_bss_select_attr. */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -3308,6 +3340,8 @@ struct wiphy { u8 max_num_csa_counters; u8 max_adj_channel_rssi_comp; + u32 bss_select_support; + char priv[0] __aligned(NETDEV_ALIGN); }; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 23bf0667540c..b2a8d8c84a57 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1797,6 +1797,12 @@ enum nl80211_commands { * in a PBSS. Specified in %NL80211_CMD_CONNECT to request * connecting to a PCP, and in %NL80211_CMD_START_AP to start * a PCP instead of AP. Relevant for DMG networks only. + * @NL80211_ATTR_BSS_SELECT: nested attribute for driver supporting the + * BSS selection feature. When used with %NL80211_CMD_GET_WIPHY it contains + * attributes according &enum nl80211_bss_select_attr to indicate what + * BSS selection behaviours are supported. When used with %NL80211_CMD_CONNECT + * it contains the behaviour-specific attribute containing the parameters for + * BSS selection to be done by driver and/or firmware. * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined @@ -2174,6 +2180,8 @@ enum nl80211_attrs { NL80211_ATTR_PBSS, + NL80211_ATTR_BSS_SELECT, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -4667,4 +4675,48 @@ enum nl80211_sched_scan_plan { __NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1 }; +/** + * struct nl80211_bss_select_rssi_adjust - RSSI adjustment parameters. + * + * @band: band of BSS that must match for RSSI value adjustment. + * @delta: value used to adjust the RSSI value of matching BSS. + */ +struct nl80211_bss_select_rssi_adjust { + __u8 band; + __s8 delta; +} __attribute__((packed)); + +/** + * enum nl80211_bss_select_attr - attributes for bss selection. + * + * @__NL80211_BSS_SELECT_ATTR_INVALID: reserved. + * @NL80211_BSS_SELECT_ATTR_RSSI: Flag indicating only RSSI-based BSS selection + * is requested. + * @NL80211_BSS_SELECT_ATTR_BAND_PREF: attribute indicating BSS + * selection should be done such that the specified band is preferred. + * When there are multiple BSS-es in the preferred band, the driver + * shall use RSSI-based BSS selection as a second step. The value of + * this attribute is according to &enum nl80211_band (u32). + * @NL80211_BSS_SELECT_ATTR_RSSI_ADJUST: When present the RSSI level for + * BSS-es in the specified band is to be adjusted before doing + * RSSI-based BSS selection. The attribute value is a packed structure + * value as specified by &struct nl80211_bss_select_rssi_adjust. + * @NL80211_BSS_SELECT_ATTR_MAX: highest bss select attribute number. + * @__NL80211_BSS_SELECT_ATTR_AFTER_LAST: internal use. + * + * One and only one of these attributes are found within %NL80211_ATTR_BSS_SELECT + * for %NL80211_CMD_CONNECT. It specifies the required BSS selection behaviour + * which the driver shall use. + */ +enum nl80211_bss_select_attr { + __NL80211_BSS_SELECT_ATTR_INVALID, + NL80211_BSS_SELECT_ATTR_RSSI, + NL80211_BSS_SELECT_ATTR_BAND_PREF, + NL80211_BSS_SELECT_ATTR_RSSI_ADJUST, + + /* keep last */ + __NL80211_BSS_SELECT_ATTR_AFTER_LAST, + NL80211_BSS_SELECT_ATTR_MAX = __NL80211_BSS_SELECT_ATTR_AFTER_LAST - 1 +}; + #endif /* __LINUX_NL80211_H */ diff --git a/net/wireless/core.c b/net/wireless/core.c index 9f1c4aa851ef..5327e4b974fa 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -626,6 +626,13 @@ int wiphy_register(struct wiphy *wiphy) !rdev->ops->set_mac_acl))) return -EINVAL; + /* assure only valid behaviours are flagged by driver + * hence subtract 2 as bit 0 is invalid. + */ + if (WARN_ON(wiphy->bss_select_support && + (wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2)))) + return -EINVAL; + if (wiphy->addresses) memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1b43f7839eeb..d6c6449c0389 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -402,6 +402,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 }, [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, [NL80211_ATTR_PBSS] = { .type = NLA_FLAG }, + [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED }, }; /* policy for the key attributes */ @@ -486,6 +487,15 @@ nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = { [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 }, }; +static const struct nla_policy +nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = { + [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG }, + [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 }, + [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = { + .len = sizeof(struct nl80211_bss_select_rssi_adjust) + }, +}; + static int nl80211_prepare_wdev_dump(struct sk_buff *skb, struct netlink_callback *cb, struct cfg80211_registered_device **rdev, @@ -1731,6 +1741,25 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, rdev->wiphy.ext_features)) goto nla_put_failure; + if (rdev->wiphy.bss_select_support) { + struct nlattr *nested; + u32 bss_select_support = rdev->wiphy.bss_select_support; + + nested = nla_nest_start(msg, NL80211_ATTR_BSS_SELECT); + if (!nested) + goto nla_put_failure; + + i = 0; + while (bss_select_support) { + if ((bss_select_support & 1) && + nla_put_flag(msg, i)) + goto nla_put_failure; + i++; + bss_select_support >>= 1; + } + nla_nest_end(msg, nested); + } + /* done */ state->split_start = 0; break; @@ -5758,6 +5787,73 @@ static int validate_scan_freqs(struct nlattr *freqs) return n_channels; } +static bool is_band_valid(struct wiphy *wiphy, enum ieee80211_band b) +{ + return b < IEEE80211_NUM_BANDS && wiphy->bands[b]; +} + +static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy, + struct cfg80211_bss_selection *bss_select) +{ + struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1]; + struct nlattr *nest; + int err; + bool found = false; + int i; + + /* only process one nested attribute */ + nest = nla_data(nla); + if (!nla_ok(nest, nla_len(nest))) + return -EINVAL; + + err = nla_parse(attr, NL80211_BSS_SELECT_ATTR_MAX, nla_data(nest), + nla_len(nest), nl80211_bss_select_policy); + if (err) + return err; + + /* only one attribute may be given */ + for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) { + if (attr[i]) { + if (found) + return -EINVAL; + found = true; + } + } + + bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID; + + if (attr[NL80211_BSS_SELECT_ATTR_RSSI]) + bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI; + + if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) { + bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF; + bss_select->param.band_pref = + nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]); + if (!is_band_valid(wiphy, bss_select->param.band_pref)) + return -EINVAL; + } + + if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) { + struct nl80211_bss_select_rssi_adjust *adj_param; + + adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]); + bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST; + bss_select->param.adjust.band = adj_param->band; + bss_select->param.adjust.delta = adj_param->delta; + if (!is_band_valid(wiphy, bss_select->param.adjust.band)) + return -EINVAL; + } + + /* user-space did not provide behaviour attribute */ + if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID) + return -EINVAL; + + if (!(wiphy->bss_select_support & BIT(bss_select->behaviour))) + return -EINVAL; + + return 0; +} + static int nl80211_parse_random_mac(struct nlattr **attrs, u8 *mac_addr, u8 *mac_addr_mask) { @@ -8001,6 +8097,21 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) return -EOPNOTSUPP; } + if (info->attrs[NL80211_ATTR_BSS_SELECT]) { + /* bss selection makes no sense if bssid is set */ + if (connect.bssid) { + kzfree(connkeys); + return -EINVAL; + } + + err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT], + wiphy, &connect.bss_select); + if (err) { + kzfree(connkeys); + return err; + } + } + wdev_lock(dev->ieee80211_ptr); err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL); wdev_unlock(dev->ieee80211_ptr); -- GitLab From f66b60f6524c970d43af7a68dd50dcce289887e7 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 24 Feb 2016 16:25:49 +0100 Subject: [PATCH 1329/9938] mac80211: fix parsing of 40Mhz in injected radiotap header The MCS bandwidth part of the radiotap header is 2 bits wide. The full 2 bit have to compared against IEEE80211_RADIOTAP_MCS_BW_40 and not only if the first bit is set. Otherwise IEEE80211_RADIOTAP_MCS_BW_40 can be confused with IEEE80211_RADIOTAP_MCS_BW_20U. Fixes: dfdfc2beb0dd ("mac80211: Parse legacy and HT rate in injected frames") Signed-off-by: Sven Eckelmann Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b3196b1e15c2..51e225e4b450 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1691,7 +1691,7 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, bool rate_found = false; u8 rate_retries = 0; u16 rate_flags = 0; - u8 mcs_known, mcs_flags; + u8 mcs_known, mcs_flags, mcs_bw; u16 vht_known; u8 vht_mcs = 0, vht_nss = 0; int i; @@ -1769,8 +1769,9 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, mcs_flags & IEEE80211_RADIOTAP_MCS_SGI) rate_flags |= IEEE80211_TX_RC_SHORT_GI; + mcs_bw = mcs_flags & IEEE80211_RADIOTAP_MCS_BW_MASK; if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW && - mcs_flags & IEEE80211_RADIOTAP_MCS_BW_40) + mcs_bw == IEEE80211_RADIOTAP_MCS_BW_40) rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; break; -- GitLab From 07310a63147164eaf44a68932fbe9dbbde0fa82b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 2 Mar 2016 15:54:51 +0100 Subject: [PATCH 1330/9938] mac80211: do not pass injected frames without a valid rate to the driver Fall back to rate control if the requested bitrate was not found. Fixes: dfdfc2beb0dd ("mac80211: Parse legacy and HT rate in injected frames") Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 51e225e4b450..597c8fe672a3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1839,6 +1839,9 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, } } + if (info->control.rates[0].idx < 0) + info->control.flags &= ~IEEE80211_TX_CTRL_RATE_INJECT; + info->control.rates[0].flags = rate_flags; info->control.rates[0].count = min_t(u8, rate_retries + 1, local->hw.max_rate_tries); -- GitLab From a619afe814453300684f1d5a6478d67f791bc723 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 7 Mar 2016 09:30:03 -0800 Subject: [PATCH 1331/9938] i40e/i40evf: Add support for bulk free in Tx cleanup This patch enables bulk Tx clean for skbs. In order to enable it we need to pass the napi_budget value as that is used to determine if we are truly running in NAPI mode or if we are simply calling the routine from netpoll with a budget of 0. In order to avoid adding too many more variables I thought it best to pass the VSI directly in a fashion similar to what we do on igb and ixgbe with the q_vector. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 20 ++++++++++--------- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 20 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 8fb2a966d70e..01cff073f8db 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -636,19 +636,21 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw) /** * i40e_clean_tx_irq - Reclaim resources after transmit completes - * @tx_ring: tx ring to clean - * @budget: how many cleans we're allowed + * @vsi: the VSI we care about + * @tx_ring: Tx ring to clean + * @napi_budget: Used to determine if we are in netpoll * * Returns true if there's any budget left (e.g. the clean is finished) **/ -static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) +static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, + struct i40e_ring *tx_ring, int napi_budget) { u16 i = tx_ring->next_to_clean; struct i40e_tx_buffer *tx_buf; struct i40e_tx_desc *tx_head; struct i40e_tx_desc *tx_desc; - unsigned int total_packets = 0; - unsigned int total_bytes = 0; + unsigned int total_bytes = 0, total_packets = 0; + unsigned int budget = vsi->work_limit; tx_buf = &tx_ring->tx_bi[i]; tx_desc = I40E_TX_DESC(tx_ring, i); @@ -678,7 +680,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) total_packets += tx_buf->gso_segs; /* free the skb */ - dev_consume_skb_any(tx_buf->skb); + napi_consume_skb(tx_buf->skb, napi_budget); /* unmap skb header data */ dma_unmap_single(tx_ring->dev, @@ -749,7 +751,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) if (budget && ((j / (WB_STRIDE + 1)) == 0) && (j != 0) && - !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && + !test_bit(__I40E_DOWN, &vsi->state) && (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) tx_ring->arm_wb = true; } @@ -767,7 +769,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) smp_mb(); if (__netif_subqueue_stopped(tx_ring->netdev, tx_ring->queue_index) && - !test_bit(__I40E_DOWN, &tx_ring->vsi->state)) { + !test_bit(__I40E_DOWN, &vsi->state)) { netif_wake_subqueue(tx_ring->netdev, tx_ring->queue_index); ++tx_ring->tx_stats.restart_queue; @@ -1975,7 +1977,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) * budget and be more aggressive about cleaning up the Tx descriptors. */ i40e_for_each_ring(ring, q_vector->tx) { - if (!i40e_clean_tx_irq(ring, vsi->work_limit)) { + if (!i40e_clean_tx_irq(vsi, ring, budget)) { clean_complete = false; continue; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 839a6df62f72..9e911363c11b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -155,19 +155,21 @@ u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw) /** * i40e_clean_tx_irq - Reclaim resources after transmit completes - * @tx_ring: tx ring to clean - * @budget: how many cleans we're allowed + * @vsi: the VSI we care about + * @tx_ring: Tx ring to clean + * @napi_budget: Used to determine if we are in netpoll * * Returns true if there's any budget left (e.g. the clean is finished) **/ -static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) +static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, + struct i40e_ring *tx_ring, int napi_budget) { u16 i = tx_ring->next_to_clean; struct i40e_tx_buffer *tx_buf; struct i40e_tx_desc *tx_head; struct i40e_tx_desc *tx_desc; - unsigned int total_packets = 0; - unsigned int total_bytes = 0; + unsigned int total_bytes = 0, total_packets = 0; + unsigned int budget = vsi->work_limit; tx_buf = &tx_ring->tx_bi[i]; tx_desc = I40E_TX_DESC(tx_ring, i); @@ -197,7 +199,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) total_packets += tx_buf->gso_segs; /* free the skb */ - dev_kfree_skb_any(tx_buf->skb); + napi_consume_skb(tx_buf->skb, napi_budget); /* unmap skb header data */ dma_unmap_single(tx_ring->dev, @@ -267,7 +269,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) if (budget && ((j / (WB_STRIDE + 1)) == 0) && (j > 0) && - !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && + !test_bit(__I40E_DOWN, &vsi->state) && (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) tx_ring->arm_wb = true; } @@ -285,7 +287,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) smp_mb(); if (__netif_subqueue_stopped(tx_ring->netdev, tx_ring->queue_index) && - !test_bit(__I40E_DOWN, &tx_ring->vsi->state)) { + !test_bit(__I40E_DOWN, &vsi->state)) { netif_wake_subqueue(tx_ring->netdev, tx_ring->queue_index); ++tx_ring->tx_stats.restart_queue; @@ -1411,7 +1413,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) * budget and be more aggressive about cleaning up the Tx descriptors. */ i40e_for_each_ring(ring, q_vector->tx) { - if (!i40e_clean_tx_irq(ring, vsi->work_limit)) { + if (!i40e_clean_tx_irq(vsi, ring, budget)) { clean_complete = false; continue; } -- GitLab From 4ea623922d1d73c162da53e02cce1d0d3fd55893 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 10 Mar 2016 14:59:39 -0800 Subject: [PATCH 1332/9938] i40e/i40evf: Fix casting in transmit code Simple cast to fix a sparse warning. Fixes: commit 5453205cd097 ("i40e/i40evf: Enable support for SKB_GSO_UDP_TUNNEL_CSUM") Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 5 +++-- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 01cff073f8db..5bef5b0f00d9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2305,7 +2305,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, /* remove payload length from outer checksum */ paylen = (__force u16)l4.udp->check; - paylen += ntohs(1) * (u16)~(skb->len - l4_offset); + paylen += ntohs((__force __be16)1) * + (u16)~(skb->len - l4_offset); l4.udp->check = ~csum_fold((__force __wsum)paylen); } @@ -2327,7 +2328,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, /* remove payload length from inner checksum */ paylen = (__force u16)l4.tcp->check; - paylen += ntohs(1) * (u16)~(skb->len - l4_offset); + paylen += ntohs((__force __be16)1) * (u16)~(skb->len - l4_offset); l4.tcp->check = ~csum_fold((__force __wsum)paylen); /* compute length of segmentation header */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 9e911363c11b..570348d93e5d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1572,7 +1572,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, /* remove payload length from outer checksum */ paylen = (__force u16)l4.udp->check; - paylen += ntohs(1) * (u16)~(skb->len - l4_offset); + paylen += ntohs((__force __be16)1) * + (u16)~(skb->len - l4_offset); l4.udp->check = ~csum_fold((__force __wsum)paylen); } @@ -1594,7 +1595,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, /* remove payload length from inner checksum */ paylen = (__force u16)l4.tcp->check; - paylen += ntohs(1) * (u16)~(skb->len - l4_offset); + paylen += ntohs((__force __be16)1) * (u16)~(skb->len - l4_offset); l4.tcp->check = ~csum_fold((__force __wsum)paylen); /* compute length of segmentation header */ -- GitLab From b7c359376429953dc1672224dbc9845eadf2a29c Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 10 Mar 2016 14:59:40 -0800 Subject: [PATCH 1333/9938] i40e/i40evf: Remove I40E_MAX_USER_PRIORITY define This patch removes the duplicate definition of I40E_MAX_USER_PRIORITY in i40e.h that is not needed. Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index f208570cfdbf..d25b3be5ba89 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -244,7 +244,6 @@ struct i40e_fdir_filter { #define I40E_DCB_PRIO_TYPE_STRICT 0 #define I40E_DCB_PRIO_TYPE_ETS 1 #define I40E_DCB_STRICT_PRIO_CREDITS 127 -#define I40E_MAX_USER_PRIORITY 8 /* DCB per TC information data structure */ struct i40e_tc_info { u16 qoffset; /* Queue offset from base queue */ -- GitLab From 06171e9c0bd54bd7dde67dfb2fa4cced23cff880 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 3 Mar 2016 23:25:42 +0100 Subject: [PATCH 1334/9938] mac80211: minstrel_ht: improve sample rate skip logic There were a few issues that were slowing down the process of finding the optimal rate, especially on devices with multi-rate retry limitations: When max_tp_rate[0] was slower than max_tp_rate[1], the code did not sample max_tp_rate[1], which would often allow it to switch places with max_tp_rate[0] (e.g. if only the first sampling attempts were bad, but the rate is otherwise good). Also, sample attempts of rates between max_tp_rate[0] and [1] were being ignored in this case, because the code only checked if the rate was slower than [1]. Fix this by checking against the fastest / second fastest max_tp_rate instead of assuming a specific order between the two. In my tests this patch significantly reduces the time until minstrel_ht finds the optimal rate right after assoc Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 370d677b547b..46ce08ed70b5 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -924,6 +924,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) struct minstrel_rate_stats *mrs; struct minstrel_mcs_group_data *mg; unsigned int sample_dur, sample_group, cur_max_tp_streams; + int tp_rate1, tp_rate2; int sample_idx = 0; if (mi->sample_wait > 0) { @@ -945,14 +946,22 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) mrs = &mg->rates[sample_idx]; sample_idx += sample_group * MCS_GROUP_RATES; + /* Set tp_rate1, tp_rate2 to the highest / second highest max_tp_rate */ + if (minstrel_get_duration(mi->max_tp_rate[0]) > + minstrel_get_duration(mi->max_tp_rate[1])) { + tp_rate1 = mi->max_tp_rate[1]; + tp_rate2 = mi->max_tp_rate[0]; + } else { + tp_rate1 = mi->max_tp_rate[0]; + tp_rate2 = mi->max_tp_rate[1]; + } + /* * Sampling might add some overhead (RTS, no aggregation) - * to the frame. Hence, don't use sampling for the currently - * used rates. + * to the frame. Hence, don't use sampling for the highest currently + * used highest throughput or probability rate. */ - if (sample_idx == mi->max_tp_rate[0] || - sample_idx == mi->max_tp_rate[1] || - sample_idx == mi->max_prob_rate) + if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate) return -1; /* @@ -967,10 +976,10 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) * if the link is working perfectly. */ - cur_max_tp_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / + cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 / MCS_GROUP_RATES].streams; sample_dur = minstrel_get_duration(sample_idx); - if (sample_dur >= minstrel_get_duration(mi->max_tp_rate[1]) && + if (sample_dur >= minstrel_get_duration(tp_rate2) && (cur_max_tp_streams - 1 < minstrel_mcs_groups[sample_group].streams || sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { -- GitLab From 2aa4d45635ad09fbd7ff6b6155d2d50b2b31cf90 Mon Sep 17 00:00:00 2001 From: Akira Moroo Date: Tue, 8 Mar 2016 23:17:42 +0900 Subject: [PATCH 1335/9938] cfg80211: fix kernel-doc struct name This patch fix a structure name mismatch in cfg80211.h. Signed-off-by: Moroo Akira Reviewed-by: Julian Calaby Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0bbfbf3cbca8..4ece4f961f40 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1619,7 +1619,7 @@ struct cfg80211_inform_bss { }; /** - * struct cfg80211_bss_ie_data - BSS entry IE data + * struct cfg80211_bss_ies - BSS entry IE data * @tsf: TSF contained in the frame that carried these IEs * @rcu_head: internal use, for freeing * @len: length of the IEs -- GitLab From f278ce4ffaaa2ee3adb957add3df7b41e6ecc1b3 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 9 Mar 2016 10:08:27 +0200 Subject: [PATCH 1336/9938] mac80211: Set global RRM capability Allow publishing RRM capabilities for features that are not HW dependent. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/mac80211/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8190bf27ebff..815596140057 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -558,6 +558,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, if (!ops->set_key) wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM); + wiphy->bss_priv_size = sizeof(struct ieee80211_bss); local = wiphy_priv(wiphy); -- GitLab From e03521232d2f808b1b593f44565665efb7b242b1 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 9 Mar 2016 13:27:08 +0200 Subject: [PATCH 1337/9938] mac80211: add NETIF_F_RXCSUM to features white list NETIF_F_RXCSUM is not in the white list, though some drivers may want to set it in order to enable seeing the actual RX checksum status in ethtool. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/mac80211/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 815596140057..33c80de61eca 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -856,7 +856,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) /* Only HW csum features are currently compatible with mac80211 */ feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | - NETIF_F_GSO_SOFTWARE; + NETIF_F_GSO_SOFTWARE | NETIF_F_RXCSUM; if (WARN_ON(hw->netdev_features & ~feature_whitelist)) return -EINVAL; -- GitLab From 1e0bbebaae660f27c24cbd9c3e693420234115ff Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 9 Mar 2016 13:27:09 +0200 Subject: [PATCH 1338/9938] mac80211: enable starting BA session with custom timeout Currently the debugfs entry for starting aggregation session starts it with timeout of 5 seconds. Allow opening a session with a custom timeout (according to spec 0 is no timeout). while at it, refactor the function and remove the magic numbers. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/mac80211/debugfs_sta.c | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index a39512f09f9e..fbbd66c9ca51 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -3,6 +3,7 @@ * Copyright (c) 2006 Jiri Benc * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -151,11 +152,12 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char _buf[12] = {}, *buf = _buf; + char _buf[25] = {}, *buf = _buf; struct sta_info *sta = file->private_data; bool start, tx; unsigned long tid; - int ret; + char *pos; + int ret, timeout = 5000; if (count > sizeof(_buf)) return -EINVAL; @@ -164,37 +166,48 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu return -EFAULT; buf[sizeof(_buf) - 1] = '\0'; + pos = buf; + buf = strsep(&pos, " "); + if (!buf) + return -EINVAL; - if (strncmp(buf, "tx ", 3) == 0) { - buf += 3; + if (!strcmp(buf, "tx")) tx = true; - } else if (strncmp(buf, "rx ", 3) == 0) { - buf += 3; + else if (!strcmp(buf, "rx")) tx = false; - } else + else return -EINVAL; - if (strncmp(buf, "start ", 6) == 0) { - buf += 6; + buf = strsep(&pos, " "); + if (!buf) + return -EINVAL; + if (!strcmp(buf, "start")) { start = true; if (!tx) return -EINVAL; - } else if (strncmp(buf, "stop ", 5) == 0) { - buf += 5; + } else if (!strcmp(buf, "stop")) { start = false; - } else + } else { + return -EINVAL; + } + + buf = strsep(&pos, " "); + if (!buf) return -EINVAL; + if (sscanf(buf, "timeout=%d", &timeout) == 1) { + buf = strsep(&pos, " "); + if (!buf || !tx || !start) + return -EINVAL; + } ret = kstrtoul(buf, 0, &tid); - if (ret) - return ret; - - if (tid >= IEEE80211_NUM_TIDS) + if (ret || tid >= IEEE80211_NUM_TIDS) return -EINVAL; if (tx) { if (start) - ret = ieee80211_start_tx_ba_session(&sta->sta, tid, 5000); + ret = ieee80211_start_tx_ba_session(&sta->sta, tid, + timeout); else ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); } else { -- GitLab From b6caccaccf749dddd296f3056111d6c4b94500c1 Mon Sep 17 00:00:00 2001 From: Kevin Scott Date: Thu, 10 Mar 2016 14:59:41 -0800 Subject: [PATCH 1339/9938] i40e: Save off VSI resource count when updating VSI When updating a VSI, save off the number of allocated and unallocated VSIs as we do when adding a VSI. Signed-off-by: Kevin Scott Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 4596294c2ab1..b0fd6844bcd7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2157,6 +2157,9 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw, struct i40e_aq_desc desc; struct i40e_aqc_add_get_update_vsi *cmd = (struct i40e_aqc_add_get_update_vsi *)&desc.params.raw; + struct i40e_aqc_add_get_update_vsi_completion *resp = + (struct i40e_aqc_add_get_update_vsi_completion *) + &desc.params.raw; i40e_status status; i40e_fill_default_direct_cmd_desc(&desc, @@ -2168,6 +2171,9 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw, status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info, sizeof(vsi_ctx->info), cmd_details); + vsi_ctx->vsis_allocated = le16_to_cpu(resp->vsi_used); + vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free); + return status; } -- GitLab From 618290262e960469758d4ab67457fcb2ea356d51 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 10 Mar 2016 14:59:42 -0800 Subject: [PATCH 1340/9938] i40e: Fix up return code The i40e_common.c typically uses i40e_status as a return code, but got missed this one case. Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index b0fd6844bcd7..8276a1393e6d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1901,13 +1901,13 @@ i40e_status i40e_aq_set_phy_int_mask(struct i40e_hw *hw, * * Reset the external PHY. **/ -enum i40e_status_code i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags, - struct i40e_asq_cmd_details *cmd_details) +i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags, + struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_phy_debug *cmd = (struct i40e_aqc_set_phy_debug *)&desc.params.raw; - enum i40e_status_code status; + i40e_status status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_phy_debug); -- GitLab From 692783980ad6163e8586baa36c066cd0d22fc7ce Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 10 Mar 2016 14:59:43 -0800 Subject: [PATCH 1341/9938] i40e: Remove MSIx only if created When cleaning up the interrupt handling, clean up the IRQs only if we actually got them set up. There are a couple of error recovery paths that were violating this and causing the kernel a bit of indigestion. Signed-off-by: Shannon Nelson Reviewed-by: Williams, Mitch A Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 650336e50255..2464dca88f79 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4164,7 +4164,7 @@ static void i40e_clear_interrupt_scheme(struct i40e_pf *pf) int i; i40e_stop_misc_vector(pf); - if (pf->flags & I40E_FLAG_MSIX_ENABLED) { + if (pf->flags & I40E_FLAG_MSIX_ENABLED && pf->msix_entries) { synchronize_irq(pf->msix_entries[0].vector); free_irq(pf->msix_entries[0].vector, pf); } -- GitLab From 96f321c9d42a61aa1e2760a47a574f286b028be2 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Sat, 19 Mar 2016 19:59:43 +0530 Subject: [PATCH 1342/9938] mac80211: Remove unused variable in per STA debugfs struct Remove unused variable in per STA debugfs structure, 'commit 34e895075e21 ("mac80211: allow station add/remove to sleep")' removed the only user of 'add_has_run'. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Johannes Berg --- net/mac80211/debugfs_sta.c | 2 -- net/mac80211/sta_info.h | 1 - 2 files changed, 3 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index fbbd66c9ca51..051b22505720 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -352,8 +352,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations; u8 mac[3*ETH_ALEN]; - sta->debugfs.add_has_run = true; - if (!stations_dir) return; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 053f5c4fa495..276056e99862 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -488,7 +488,6 @@ struct sta_info { #ifdef CONFIG_MAC80211_DEBUGFS struct sta_info_debugfsdentries { struct dentry *dir; - bool add_has_run; } debugfs; #endif -- GitLab From fc4a25c5b741ecb4ef4d0f1802775e8a88d7e0a7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Apr 2016 11:59:05 +0200 Subject: [PATCH 1343/9938] mac80211: remove sta_info debugfs sub-struct Since the previous patch, the struct only has a single member, so remove the struct and leave just the single member. Signed-off-by: Johannes Berg --- net/mac80211/debugfs_sta.c | 22 +++++++++++----------- net/mac80211/rate.h | 4 ++-- net/mac80211/sta_info.h | 6 ++---- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 051b22505720..af034912abbe 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -335,14 +335,14 @@ STA_OPS(vht_capa); #define DEBUGFS_ADD(name) \ debugfs_create_file(#name, 0400, \ - sta->debugfs.dir, sta, &sta_ ##name## _ops); + sta->debugfs_dir, sta, &sta_ ##name## _ops); #define DEBUGFS_ADD_COUNTER(name, field) \ if (sizeof(sta->field) == sizeof(u32)) \ - debugfs_create_u32(#name, 0400, sta->debugfs.dir, \ + debugfs_create_u32(#name, 0400, sta->debugfs_dir, \ (u32 *) &sta->field); \ else \ - debugfs_create_u64(#name, 0400, sta->debugfs.dir, \ + debugfs_create_u64(#name, 0400, sta->debugfs_dir, \ (u64 *) &sta->field); void ieee80211_sta_debugfs_add(struct sta_info *sta) @@ -366,8 +366,8 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) * destroyed quickly enough the old station's debugfs * dir might still be around. */ - sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); - if (!sta->debugfs.dir) + sta->debugfs_dir = debugfs_create_dir(mac, stations_dir); + if (!sta->debugfs_dir) return; DEBUGFS_ADD(flags); @@ -383,14 +383,14 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) debugfs_create_x32("driver_buffered_tids", 0400, - sta->debugfs.dir, + sta->debugfs_dir, (u32 *)&sta->driver_buffered_tids); else debugfs_create_x64("driver_buffered_tids", 0400, - sta->debugfs.dir, + sta->debugfs_dir, (u64 *)&sta->driver_buffered_tids); - drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs.dir); + drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs_dir); } void ieee80211_sta_debugfs_remove(struct sta_info *sta) @@ -398,7 +398,7 @@ void ieee80211_sta_debugfs_remove(struct sta_info *sta) struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - drv_sta_remove_debugfs(local, sdata, &sta->sta, sta->debugfs.dir); - debugfs_remove_recursive(sta->debugfs.dir); - sta->debugfs.dir = NULL; + drv_sta_remove_debugfs(local, sdata, &sta->sta, sta->debugfs_dir); + debugfs_remove_recursive(sta->debugfs_dir); + sta->debugfs_dir = NULL; } diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 624fe5b81615..8d3260785b94 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -96,9 +96,9 @@ static inline void rate_control_add_sta_debugfs(struct sta_info *sta) { #ifdef CONFIG_MAC80211_DEBUGFS struct rate_control_ref *ref = sta->rate_ctrl; - if (ref && sta->debugfs.dir && ref->ops->add_sta_debugfs) + if (ref && sta->debugfs_dir && ref->ops->add_sta_debugfs) ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv, - sta->debugfs.dir); + sta->debugfs_dir); #endif } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 276056e99862..3b2105562d8b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -371,7 +371,7 @@ DECLARE_EWMA(signal, 1024, 8) * @ampdu_mlme: A-MPDU state machine state * @timer_to_tid: identity mapping to ID timers * @mesh: mesh STA information - * @debugfs: debug filesystem info + * @debugfs_dir: debug filesystem directory dentry * @dead: set to true when sta is unlinked * @removed: set to true when sta is being removed from sta_list * @uploaded: set to true when sta is uploaded to the driver @@ -486,9 +486,7 @@ struct sta_info { u8 timer_to_tid[IEEE80211_NUM_TIDS]; #ifdef CONFIG_MAC80211_DEBUGFS - struct sta_info_debugfsdentries { - struct dentry *dir; - } debugfs; + struct dentry *debugfs_dir; #endif enum ieee80211_sta_rx_bandwidth cur_max_bandwidth; -- GitLab From de03d2b0ef6520cf9da2e429cd7afb534782b737 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 10 Mar 2016 14:59:44 -0800 Subject: [PATCH 1344/9938] i40e: Assure that adminq is alive in debug mode When dropping into debug mode in a failed probe, make sure that the AdminQ is left alive for possible hand debug of driver and firmware states. Move the mutex_init calls earlier in probe so that if init fails, the admin queue interface is still available for debugging purposes. Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2464dca88f79..56d4416c9a11 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10822,6 +10822,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->bus.func = PCI_FUNC(pdev->devfn); pf->instance = pfs_found; + /* set up the locks for the AQ, do this only once in probe + * and destroy them only once in remove + */ + mutex_init(&hw->aq.asq_mutex); + mutex_init(&hw->aq.arq_mutex); + if (debug != -1) { pf->msg_enable = pf->hw.debug_mask; pf->msg_enable = debug; @@ -10867,12 +10873,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* set up a default setting for link flow control */ pf->hw.fc.requested_mode = I40E_FC_NONE; - /* set up the locks for the AQ, do this only once in probe - * and destroy them only once in remove - */ - mutex_init(&hw->aq.asq_mutex); - mutex_init(&hw->aq.arq_mutex); - err = i40e_init_adminq(hw); if (err) { if (err == I40E_ERR_FIRMWARE_API_VERSION) @@ -11265,7 +11265,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) kfree(pf->qp_pile); err_sw_init: err_adminq_setup: - (void)i40e_shutdown_adminq(hw); err_pf_reset: iounmap(hw->hw_addr); err_ioremap: -- GitLab From 602fae425cf3ade41a4787f8ddf850af418faa3b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 17 Mar 2016 15:02:52 +0200 Subject: [PATCH 1345/9938] mac80211: don't start dynamic PS timer if not needed If the device implements dynamic PS itself, there's no need to ever start the dynamic powersave timer on RX. While at it, fix up some indentation in this code. Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index dc27becb9b71..36214e332225 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2474,14 +2474,14 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) rx->skb->dev = dev; - if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && + if (!ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS) && + local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && !is_multicast_ether_addr( ((struct ethhdr *)rx->skb->data)->h_dest) && (!local->scanning && - !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) { - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); - } + !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); ieee80211_deliver_skb(rx); -- GitLab From 3c5bcb2e1930bdbccd14a49660895f014349b51d Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Thu, 17 Mar 2016 15:02:53 +0200 Subject: [PATCH 1346/9938] ieee80211: support parsing Fine Timing Measurement action frame Add definition for Fine Timing Measurement (FTM) frame format as defined in IEEE802.11-REVmcD5.0 section 9.6.8.33 Signed-off-by: Avraham Stern Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 3b1f6cef9513..bf9706c5b0bd 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -7,6 +7,7 @@ * Copyright (c) 2005, Devicescape Software, Inc. * Copyright (c) 2006, Michael Wu * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright (c) 2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1011,6 +1012,16 @@ struct ieee80211_mgmt { u8 tpc_elem_length; struct ieee80211_tpc_report_ie tpc; } __packed tpc_report; + struct { + u8 action_code; + u8 dialog_token; + u8 follow_up; + u8 tod[6]; + u8 toa[6]; + __le16 tod_error; + __le16 toa_error; + u8 variable[0]; + } __packed ftm; } u; } __packed action; } u; -- GitLab From c84387d2f2c83d1d49a8dfefed13a8b39f017230 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 17 Mar 2016 15:02:54 +0200 Subject: [PATCH 1347/9938] mac80211: clean up station flags debugfs Avoid the really strange %s%s%s expression, use an array of flag names and check that all flags are present. Signed-off-by: Johannes Berg --- net/mac80211/debugfs_sta.c | 63 ++++++++++++++++++++++++++------------ net/mac80211/sta_info.h | 4 +++ 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index af034912abbe..33dfcbc2bf9c 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -52,31 +52,54 @@ static const struct file_operations sta_ ##name## _ops = { \ STA_FILE(aid, sta.aid, D); +static const char * const sta_flag_names[] = { +#define FLAG(F) [WLAN_STA_##F] = #F + FLAG(AUTH), + FLAG(ASSOC), + FLAG(PS_STA), + FLAG(AUTHORIZED), + FLAG(SHORT_PREAMBLE), + FLAG(WDS), + FLAG(CLEAR_PS_FILT), + FLAG(MFP), + FLAG(BLOCK_BA), + FLAG(PS_DRIVER), + FLAG(PSPOLL), + FLAG(TDLS_PEER), + FLAG(TDLS_PEER_AUTH), + FLAG(TDLS_INITIATOR), + FLAG(TDLS_CHAN_SWITCH), + FLAG(TDLS_OFF_CHANNEL), + FLAG(TDLS_WIDER_BW), + FLAG(UAPSD), + FLAG(SP), + FLAG(4ADDR_EVENT), + FLAG(INSERTED), + FLAG(RATE_CONTROL), + FLAG(TOFFSET_KNOWN), + FLAG(MPSP_OWNER), + FLAG(MPSP_RECIPIENT), + FLAG(PS_DELIVER), +#undef FLAG +}; + static ssize_t sta_flags_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - char buf[121]; + char buf[16 * NUM_WLAN_STA_FLAGS], *pos = buf; + char *end = buf + sizeof(buf) - 1; struct sta_info *sta = file->private_data; + unsigned int flg; + + BUILD_BUG_ON(ARRAY_SIZE(sta_flag_names) != NUM_WLAN_STA_FLAGS); + + for (flg = 0; flg < NUM_WLAN_STA_FLAGS; flg++) { + if (test_sta_flag(sta, flg)) + pos += scnprintf(pos, end - pos, "%s\n", + sta_flag_names[flg]); + } -#define TEST(flg) \ - test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" - - int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - TEST(AUTH), TEST(ASSOC), TEST(PS_STA), - TEST(PS_DRIVER), TEST(AUTHORIZED), - TEST(SHORT_PREAMBLE), - sta->sta.wme ? "WME\n" : "", - TEST(WDS), TEST(CLEAR_PS_FILT), - TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), - TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), - TEST(TDLS_PEER_AUTH), TEST(TDLS_INITIATOR), - TEST(TDLS_CHAN_SWITCH), TEST(TDLS_OFF_CHANNEL), - TEST(4ADDR_EVENT), TEST(INSERTED), - TEST(RATE_CONTROL), TEST(TOFFSET_KNOWN), - TEST(MPSP_OWNER), TEST(MPSP_RECIPIENT)); -#undef TEST - return simple_read_from_buffer(userbuf, count, ppos, buf, res); + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); } STA_OPS(flags); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 3b2105562d8b..4e1ed6f26484 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -69,6 +69,8 @@ * @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP. * @WLAN_STA_PS_DELIVER: station woke up, but we're still blocking TX * until pending frames are delivered + * + * @NUM_WLAN_STA_FLAGS: number of defined flags */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH, @@ -97,6 +99,8 @@ enum ieee80211_sta_info_flags { WLAN_STA_MPSP_OWNER, WLAN_STA_MPSP_RECIPIENT, WLAN_STA_PS_DELIVER, + + NUM_WLAN_STA_FLAGS, }; #define ADDBA_RESP_INTERVAL HZ -- GitLab From 2c61cf9c56cbc4e0a4475232659ac30bb4c28674 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 17 Mar 2016 15:02:55 +0200 Subject: [PATCH 1348/9938] mac80211: fix cipher scheme function name The code is only used with iwlwifi, but still should have proper mac80211 naming scheme; fix that. Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 36214e332225..009bb90d7f5a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -722,8 +722,8 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) return -1; } -static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, - struct sk_buff *skb) +static int ieee80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, + struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc; @@ -1586,7 +1586,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) { cs = rx->sta->cipher_scheme; - keyid = iwl80211_get_cs_keyid(cs, rx->skb); + keyid = ieee80211_get_cs_keyid(cs, rx->skb); if (unlikely(keyid < 0)) return RX_DROP_UNUSABLE; } @@ -1670,7 +1670,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) hdrlen = ieee80211_hdrlen(fc); if (cs) { - keyidx = iwl80211_get_cs_keyid(cs, rx->skb); + keyidx = ieee80211_get_cs_keyid(cs, rx->skb); if (unlikely(keyidx < 0)) return RX_DROP_UNUSABLE; -- GitLab From 83094e5e9e49f893403d6fad20c9c06c980c2d1b Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Fri, 11 Mar 2016 11:50:33 -0800 Subject: [PATCH 1349/9938] crypto: af_alg - add async support to algif_aead Following the async change for algif_skcipher this patch adds similar async read to algif_aead. changes in v3: - add call to aead_reset_ctx directly from aead_put_sgl instead of calling them separatelly one after the other - remove wait from aead_sock_destruct function as it is not needed when sock_hold is used changes in v2: - change internal data structures from fixed size arrays, limited to RSGL_MAX_ENTRIES, to linked list model with no artificial limitation. - use sock_kmalloc instead of kmalloc for memory allocation - use sock_hold instead of separate atomic ctr to wait for outstanding request Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- crypto/algif_aead.c | 268 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 237 insertions(+), 31 deletions(-) diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 147069c9afd0..80a0f1a78551 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -13,7 +13,7 @@ * any later version. */ -#include +#include #include #include #include @@ -29,15 +29,24 @@ struct aead_sg_list { struct scatterlist sg[ALG_MAX_PAGES]; }; +struct aead_async_rsgl { + struct af_alg_sgl sgl; + struct list_head list; +}; + +struct aead_async_req { + struct scatterlist *tsgl; + struct aead_async_rsgl first_rsgl; + struct list_head list; + struct kiocb *iocb; + unsigned int tsgls; + char iv[]; +}; + struct aead_ctx { struct aead_sg_list tsgl; - /* - * RSGL_MAX_ENTRIES is an artificial limit where user space at maximum - * can cause the kernel to allocate RSGL_MAX_ENTRIES * ALG_MAX_PAGES - * pages - */ -#define RSGL_MAX_ENTRIES ALG_MAX_PAGES - struct af_alg_sgl rsgl[RSGL_MAX_ENTRIES]; + struct aead_async_rsgl first_rsgl; + struct list_head list; void *iv; @@ -75,6 +84,17 @@ static inline bool aead_sufficient_data(struct aead_ctx *ctx) return ctx->used >= ctx->aead_assoclen + as; } +static void aead_reset_ctx(struct aead_ctx *ctx) +{ + struct aead_sg_list *sgl = &ctx->tsgl; + + sg_init_table(sgl->sg, ALG_MAX_PAGES); + sgl->cur = 0; + ctx->used = 0; + ctx->more = 0; + ctx->merge = 0; +} + static void aead_put_sgl(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); @@ -90,11 +110,7 @@ static void aead_put_sgl(struct sock *sk) put_page(sg_page(sg + i)); sg_assign_page(sg + i, NULL); } - sg_init_table(sg, ALG_MAX_PAGES); - sgl->cur = 0; - ctx->used = 0; - ctx->more = 0; - ctx->merge = 0; + aead_reset_ctx(ctx); } static void aead_wmem_wakeup(struct sock *sk) @@ -349,23 +365,188 @@ static ssize_t aead_sendpage(struct socket *sock, struct page *page, return err ?: size; } -static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) +#define GET_ASYM_REQ(req, tfm) (struct aead_async_req *) \ + ((char *)req + sizeof(struct aead_request) + \ + crypto_aead_reqsize(tfm)) + + #define GET_REQ_SIZE(tfm) sizeof(struct aead_async_req) + \ + crypto_aead_reqsize(tfm) + crypto_aead_ivsize(tfm) + \ + sizeof(struct aead_request) + +static void aead_async_cb(struct crypto_async_request *_req, int err) +{ + struct sock *sk = _req->data; + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req); + struct aead_request *req = aead_request_cast(_req); + struct aead_async_req *areq = GET_ASYM_REQ(req, tfm); + struct scatterlist *sg = areq->tsgl; + struct aead_async_rsgl *rsgl; + struct kiocb *iocb = areq->iocb; + unsigned int i, reqlen = GET_REQ_SIZE(tfm); + + list_for_each_entry(rsgl, &areq->list, list) { + af_alg_free_sg(&rsgl->sgl); + if (rsgl != &areq->first_rsgl) + sock_kfree_s(sk, rsgl, sizeof(*rsgl)); + } + + for (i = 0; i < areq->tsgls; i++) + put_page(sg_page(sg + i)); + + sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls); + sock_kfree_s(sk, req, reqlen); + __sock_put(sk); + iocb->ki_complete(iocb, err, err); +} + +static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg, + int flags) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req); + struct aead_async_req *areq; + struct aead_request *req = NULL; + struct aead_sg_list *sgl = &ctx->tsgl; + struct aead_async_rsgl *last_rsgl = NULL, *rsgl; + unsigned int as = crypto_aead_authsize(tfm); + unsigned int i, reqlen = GET_REQ_SIZE(tfm); + int err = -ENOMEM; + unsigned long used; + size_t outlen; + size_t usedpages = 0; + + lock_sock(sk); + if (ctx->more) { + err = aead_wait_for_data(sk, flags); + if (err) + goto unlock; + } + + used = ctx->used; + outlen = used; + + if (!aead_sufficient_data(ctx)) + goto unlock; + + req = sock_kmalloc(sk, reqlen, GFP_KERNEL); + if (unlikely(!req)) + goto unlock; + + areq = GET_ASYM_REQ(req, tfm); + memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl)); + INIT_LIST_HEAD(&areq->list); + areq->iocb = msg->msg_iocb; + memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm)); + aead_request_set_tfm(req, tfm); + aead_request_set_ad(req, ctx->aead_assoclen); + aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + aead_async_cb, sk); + used -= ctx->aead_assoclen + (ctx->enc ? as : 0); + + /* take over all tx sgls from ctx */ + areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur, + GFP_KERNEL); + if (unlikely(!areq->tsgl)) + goto free; + + sg_init_table(areq->tsgl, sgl->cur); + for (i = 0; i < sgl->cur; i++) + sg_set_page(&areq->tsgl[i], sg_page(&sgl->sg[i]), + sgl->sg[i].length, sgl->sg[i].offset); + + areq->tsgls = sgl->cur; + + /* create rx sgls */ + while (iov_iter_count(&msg->msg_iter)) { + size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), + (outlen - usedpages)); + + if (list_empty(&areq->list)) { + rsgl = &areq->first_rsgl; + + } else { + rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL); + if (unlikely(!rsgl)) { + err = -ENOMEM; + goto free; + } + } + rsgl->sgl.npages = 0; + list_add_tail(&rsgl->list, &areq->list); + + /* make one iovec available as scatterlist */ + err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); + if (err < 0) + goto free; + + usedpages += err; + + /* chain the new scatterlist with previous one */ + if (last_rsgl) + af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl); + + last_rsgl = rsgl; + + /* we do not need more iovecs as we have sufficient memory */ + if (outlen <= usedpages) + break; + + iov_iter_advance(&msg->msg_iter, err); + } + err = -EINVAL; + /* ensure output buffer is sufficiently large */ + if (usedpages < outlen) + goto free; + + aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used, + areq->iv); + err = ctx->enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); + if (err) { + if (err == -EINPROGRESS) { + sock_hold(sk); + err = -EIOCBQUEUED; + aead_reset_ctx(ctx); + goto unlock; + } else if (err == -EBADMSG) { + aead_put_sgl(sk); + } + goto free; + } + aead_put_sgl(sk); + +free: + list_for_each_entry(rsgl, &areq->list, list) { + af_alg_free_sg(&rsgl->sgl); + if (rsgl != &areq->first_rsgl) + sock_kfree_s(sk, rsgl, sizeof(*rsgl)); + } + if (areq->tsgl) + sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls); + if (req) + sock_kfree_s(sk, req, reqlen); +unlock: + aead_wmem_wakeup(sk); + release_sock(sk); + return err ? err : outlen; +} + +static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags) { struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); struct aead_ctx *ctx = ask->private; unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); struct aead_sg_list *sgl = &ctx->tsgl; - unsigned int i = 0; + struct aead_async_rsgl *last_rsgl = NULL; + struct aead_async_rsgl *rsgl, *tmp; int err = -EINVAL; unsigned long used = 0; size_t outlen = 0; size_t usedpages = 0; - unsigned int cnt = 0; - - /* Limit number of IOV blocks to be accessed below */ - if (msg->msg_iter.nr_segs > RSGL_MAX_ENTRIES) - return -ENOMSG; lock_sock(sk); @@ -417,21 +598,33 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), (outlen - usedpages)); + if (list_empty(&ctx->list)) { + rsgl = &ctx->first_rsgl; + } else { + rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL); + if (unlikely(!rsgl)) { + err = -ENOMEM; + goto unlock; + } + } + rsgl->sgl.npages = 0; + list_add_tail(&rsgl->list, &ctx->list); + /* make one iovec available as scatterlist */ - err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter, - seglen); + err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); if (err < 0) goto unlock; usedpages += err; /* chain the new scatterlist with previous one */ - if (cnt) - af_alg_link_sg(&ctx->rsgl[cnt-1], &ctx->rsgl[cnt]); + if (last_rsgl) + af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl); + + last_rsgl = rsgl; /* we do not need more iovecs as we have sufficient memory */ if (outlen <= usedpages) break; iov_iter_advance(&msg->msg_iter, err); - cnt++; } err = -EINVAL; @@ -440,8 +633,7 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, goto unlock; sg_mark_end(sgl->sg + sgl->cur - 1); - - aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg, + aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg, used, ctx->iv); aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen); @@ -454,23 +646,35 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, /* EBADMSG implies a valid cipher operation took place */ if (err == -EBADMSG) aead_put_sgl(sk); + goto unlock; } aead_put_sgl(sk); - err = 0; unlock: - for (i = 0; i < cnt; i++) - af_alg_free_sg(&ctx->rsgl[i]); - + list_for_each_entry_safe(rsgl, tmp, &ctx->list, list) { + af_alg_free_sg(&rsgl->sgl); + if (rsgl != &ctx->first_rsgl) + sock_kfree_s(sk, rsgl, sizeof(*rsgl)); + list_del(&rsgl->list); + } + INIT_LIST_HEAD(&ctx->list); aead_wmem_wakeup(sk); release_sock(sk); return err ? err : outlen; } +static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, + int flags) +{ + return (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) ? + aead_recvmsg_async(sock, msg, flags) : + aead_recvmsg_sync(sock, msg, flags); +} + static unsigned int aead_poll(struct file *file, struct socket *sock, poll_table *wait) { @@ -540,6 +744,7 @@ static void aead_sock_destruct(struct sock *sk) unsigned int ivlen = crypto_aead_ivsize( crypto_aead_reqtfm(&ctx->aead_req)); + WARN_ON(atomic_read(&sk->sk_refcnt) != 0); aead_put_sgl(sk); sock_kzfree_s(sk, ctx->iv, ivlen); sock_kfree_s(sk, ctx, ctx->len); @@ -574,6 +779,7 @@ static int aead_accept_parent(void *private, struct sock *sk) ctx->aead_assoclen = 0; af_alg_init_completion(&ctx->completion); sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES); + INIT_LIST_HEAD(&ctx->list); ask->private = ctx; -- GitLab From 97ee7ed394f9f277f492026b9a0708cd92e6ef7d Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 13 Mar 2016 16:15:37 +0100 Subject: [PATCH 1350/9938] crypto: omap-des - Improve wording for CRYPTO_DEV_OMAP_DES in Kconfig Signed-off-by: Peter Meerwald Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 477fffdb4f49..41f194b92d34 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -302,15 +302,15 @@ config CRYPTO_DEV_OMAP_AES want to use the OMAP module for AES algorithms. config CRYPTO_DEV_OMAP_DES - tristate "Support for OMAP DES3DES hw engine" + tristate "Support for OMAP DES/3DES hw engine" depends on ARCH_OMAP2PLUS select CRYPTO_DES select CRYPTO_BLKCIPHER help OMAP processors have DES/3DES module accelerator. Select this if you want to use the OMAP module for DES and 3DES algorithms. Currently - the ECB and CBC modes of operation supported by the driver. Also - accesses made on unaligned boundaries are also supported. + the ECB and CBC modes of operation are supported by the driver. Also + accesses made on unaligned boundaries are supported. config CRYPTO_DEV_PICOXCELL tristate "Support for picoXcell IPSEC and Layer2 crypto engines" -- GitLab From f0d947ac01632fa6c75cb07262922a93736385c1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Mar 2016 09:07:12 +0900 Subject: [PATCH 1351/9938] hwrng: exynos - Runtime suspend device after init The driver uses pm_runtime_put_noidle() after initialization so the device might remain in active state if the core does not read from it (the read callback contains regular runtime put). The put_noidle() was chosen probably to avoid unneeded suspend and resume cycle after the initialization. However for this purpose autosuspend is enabled so it is safe to runtime put just after the initialization. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/char/hw_random/exynos-rng.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c index ada081232528..d1fd21e99368 100644 --- a/drivers/char/hw_random/exynos-rng.c +++ b/drivers/char/hw_random/exynos-rng.c @@ -77,7 +77,8 @@ static int exynos_init(struct hwrng *rng) pm_runtime_get_sync(exynos_rng->dev); ret = exynos_rng_configure(exynos_rng); - pm_runtime_put_noidle(exynos_rng->dev); + pm_runtime_mark_last_busy(exynos_rng->dev); + pm_runtime_put_autosuspend(exynos_rng->dev); return ret; } -- GitLab From f1925d78d7b710a1179828d53e918295f5f5d222 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Mar 2016 09:07:13 +0900 Subject: [PATCH 1352/9938] hwrng: exynos - Fix unbalanced PM runtime put on timeout error path In case of timeout during read operation, the exit path lacked PM runtime put. This could lead to unbalanced runtime PM usage counter thus leaving the device in an active state. Fixes: d7fd6075a205 ("hwrng: exynos - Add timeout for waiting on init done") Cc: # v4.4+ Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/char/hw_random/exynos-rng.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c index d1fd21e99368..38b80f82ddd2 100644 --- a/drivers/char/hw_random/exynos-rng.c +++ b/drivers/char/hw_random/exynos-rng.c @@ -90,6 +90,7 @@ static int exynos_read(struct hwrng *rng, void *buf, struct exynos_rng, rng); u32 *data = buf; int retry = 100; + int ret = 4; pm_runtime_get_sync(exynos_rng->dev); @@ -98,17 +99,20 @@ static int exynos_read(struct hwrng *rng, void *buf, while (!(exynos_rng_readl(exynos_rng, EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry) cpu_relax(); - if (!retry) - return -ETIMEDOUT; + if (!retry) { + ret = -ETIMEDOUT; + goto out; + } exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET); *data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET); +out: pm_runtime_mark_last_busy(exynos_rng->dev); pm_runtime_put_sync_autosuspend(exynos_rng->dev); - return 4; + return ret; } static int exynos_rng_probe(struct platform_device *pdev) -- GitLab From 48a61e1e2af8020f11a2b8f8dc878144477623c6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Mar 2016 09:07:14 +0900 Subject: [PATCH 1353/9938] hwrng: exynos - Disable runtime PM on probe failure Add proper error path (for disabling runtime PM) when registering of hwrng fails. Fixes: b329669ea0b5 ("hwrng: exynos - Add support for Exynos random number generator") Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/char/hw_random/exynos-rng.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c index 38b80f82ddd2..71b45b153cf2 100644 --- a/drivers/char/hw_random/exynos-rng.c +++ b/drivers/char/hw_random/exynos-rng.c @@ -119,6 +119,7 @@ static int exynos_rng_probe(struct platform_device *pdev) { struct exynos_rng *exynos_rng; struct resource *res; + int ret; exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng), GFP_KERNEL); @@ -146,7 +147,13 @@ static int exynos_rng_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); - return devm_hwrng_register(&pdev->dev, &exynos_rng->rng); + ret = devm_hwrng_register(&pdev->dev, &exynos_rng->rng); + if (ret) { + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_disable(&pdev->dev); + } + + return ret; } static int __maybe_unused exynos_rng_runtime_suspend(struct device *dev) -- GitLab From 27d80fa8bccf8d28bef4f89709638efc624fef9a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Mar 2016 09:07:15 +0900 Subject: [PATCH 1354/9938] hwrng: exynos - Disable runtime PM on driver unbind Driver enabled runtime PM but did not revert this on removal. Re-binding of a device triggered warning: exynos-rng 10830400.rng: Unbalanced pm_runtime_enable! Fixes: b329669ea0b5 ("hwrng: exynos - Add support for Exynos random number generator") Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/char/hw_random/exynos-rng.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c index 71b45b153cf2..ed78f25e4ec6 100644 --- a/drivers/char/hw_random/exynos-rng.c +++ b/drivers/char/hw_random/exynos-rng.c @@ -156,6 +156,14 @@ static int exynos_rng_probe(struct platform_device *pdev) return ret; } +static int exynos_rng_remove(struct platform_device *pdev) +{ + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + static int __maybe_unused exynos_rng_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -213,6 +221,7 @@ static struct platform_driver exynos_rng_driver = { .of_match_table = exynos_rng_dt_match, }, .probe = exynos_rng_probe, + .remove = exynos_rng_remove, }; module_platform_driver(exynos_rng_driver); -- GitLab From 4dd6e9ea7ae824ebfd054b92e4f97ad75454b4c2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Mar 2016 13:19:55 +0900 Subject: [PATCH 1355/9938] hwrng: exynos - Enable COMPILE_TEST Get some build coverage of Exynos H/W random number generator driver. Driver uses devm_ioremap_resource() so add IOMEM dependency for the compile testing. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 67ee8b08ab53..3c5be60befce 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -309,7 +309,8 @@ config HW_RANDOM_POWERNV config HW_RANDOM_EXYNOS tristate "EXYNOS HW random number generator support" - depends on ARCH_EXYNOS + depends on ARCH_EXYNOS || COMPILE_TEST + depends on HAS_IOMEM default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number -- GitLab From dc1d9dee3042d4c507bd7eb557a06918a1f09ae0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Mar 2016 13:20:18 +0900 Subject: [PATCH 1356/9938] crypto: s5p-sss - Enable COMPILE_TEST Get some build coverage of S5P/Exynos AES H/W acceleration driver. Driver uses DMA and devm_ioremap_resource() so add DMA and IOMEM dependencies for the compile testing. Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 41f194b92d34..8c141f01f29c 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -342,7 +342,8 @@ config CRYPTO_DEV_SAHARA config CRYPTO_DEV_S5P tristate "Support for Samsung S5PV210/Exynos crypto accelerator" - depends on ARCH_S5PV210 || ARCH_EXYNOS + depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST + depends on HAS_IOMEM && HAS_DMA select CRYPTO_AES select CRYPTO_BLKCIPHER help -- GitLab From 150f6d457cfcb37646b026251d8a584978618726 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Fri, 18 Mar 2016 19:08:48 +0530 Subject: [PATCH 1357/9938] crypto: n2 - Remove return statement from void function Return statement at the end of a void function is useless. The Coccinelle semantic patch used to make this change is as follows: // @@ identifier f; expression e; @@ void f(...) { <... - return e; ...> } // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Herbert Xu --- drivers/crypto/n2_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index b85a7a7dbf63..c5aac25a5738 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -1598,7 +1598,7 @@ static void *new_queue(unsigned long q_type) static void free_queue(void *p, unsigned long q_type) { - return kmem_cache_free(queue_cache[q_type - 1], p); + kmem_cache_free(queue_cache[q_type - 1], p); } static int queue_cache_init(void) -- GitLab From 06af9b0f4949b85b20107e6d75f5eba15111d220 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 18 Mar 2016 15:51:31 +0000 Subject: [PATCH 1358/9938] PKCS#7: fix missing break on OID_sha224 case The OID_sha224 case is missing a break and it falls through to the -ENOPKG error default. Since HASH_ALGO_SHA224 seems to be supported, this looks like an unintentional missing break. Fixes: 07f081fb5057 ("PKCS#7: Add OIDs for sha224, sha284 and sha512 hash algos and use them") Cc: # 4.2+ Signed-off-by: Colin Ian King Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/pkcs7_parser.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 40de03f49ff8..bdd0d753ce5d 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -237,6 +237,7 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, break; case OID_sha224: ctx->sinfo->sig.hash_algo = "sha224"; + break; default: printk("Unsupported digest algo: %u\n", ctx->last_oid); return -ENOPKG; -- GitLab From 063327f54e864874de3f4d6715ff284e8d135e12 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 21 Mar 2016 12:03:43 +0300 Subject: [PATCH 1359/9938] crypto: marvell/cesa - remove unneeded condition creq->cache[] is an array inside the struct, it's not a pointer and it can't be NULL. Signed-off-by: Dan Carpenter Acked-by: Boris Brezillon Signed-off-by: Herbert Xu --- drivers/crypto/marvell/hash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c index 7ca2e0f9dc2e..7a5058da9151 100644 --- a/drivers/crypto/marvell/hash.c +++ b/drivers/crypto/marvell/hash.c @@ -768,8 +768,7 @@ static int mv_cesa_ahash_export(struct ahash_request *req, void *hash, *len = creq->len; memcpy(hash, creq->state, digsize); memset(cache, 0, blocksize); - if (creq->cache) - memcpy(cache, creq->cache, creq->cache_ptr); + memcpy(cache, creq->cache, creq->cache_ptr); return 0; } -- GitLab From 29e9330f2ba8cbca7c9dd8a03db1e6e453aea2f2 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Mon, 21 Mar 2016 11:43:22 -0500 Subject: [PATCH 1360/9938] MAINTAINERS: Add a new maintainer for the CCP driver Gary will be taking over future development of the CCP driver, so add him as a co-maintainer of the driver. Signed-off-by: Tom Lendacky Acked-by: Gary Hook Signed-off-by: Herbert Xu --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1c32f8a3d6c4..c5048fa1316d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -627,6 +627,7 @@ F: include/linux/altera_jtaguart.h AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER M: Tom Lendacky +M: Gary Hook L: linux-crypto@vger.kernel.org S: Supported F: drivers/crypto/ccp/ -- GitLab From 119c3ab4ed33c04782f02040a4bc686216788c53 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 22 Mar 2016 10:58:23 +0900 Subject: [PATCH 1361/9938] crypto: s5p-sss - Minor coding cleanups Remove unneeded inclusion of delay.h and get rid of indentation from labels. Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 5f161a9777e3..60f835455a41 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -11,7 +11,6 @@ * */ -#include #include #include #include @@ -284,7 +283,7 @@ static int s5p_set_outdata(struct s5p_aes_dev *dev, struct scatterlist *sg) dev->sg_dst = sg; err = 0; - exit: +exit: return err; } @@ -310,7 +309,7 @@ static int s5p_set_indata(struct s5p_aes_dev *dev, struct scatterlist *sg) dev->sg_src = sg; err = 0; - exit: +exit: return err; } @@ -452,10 +451,10 @@ static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) return; - outdata_error: +outdata_error: s5p_unset_indata(dev); - indata_error: +indata_error: s5p_aes_complete(dev, err); spin_unlock_irqrestore(&dev->lock, flags); } @@ -506,7 +505,7 @@ static int s5p_aes_handle_req(struct s5p_aes_dev *dev, tasklet_schedule(&dev->tasklet); - exit: +exit: return err; } @@ -705,7 +704,7 @@ static int s5p_aes_probe(struct platform_device *pdev) return 0; - err_algs: +err_algs: dev_err(dev, "can't register '%s': %d\n", algs[i].cra_name, err); for (j = 0; j < i; j++) @@ -713,7 +712,7 @@ static int s5p_aes_probe(struct platform_device *pdev) tasklet_kill(&pdata->tasklet); - err_irq: +err_irq: clk_disable_unprepare(pdata->clk); s5p_dev = NULL; -- GitLab From 9e4a1100a445671dd55ff74dce859221cc1464fa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 22 Mar 2016 10:58:24 +0900 Subject: [PATCH 1362/9938] crypto: s5p-sss - Handle unaligned buffers During crypto selftests on Odroid XU3 (Exynos5422) some of the algorithms failed because of passing AES-block unaligned source and destination buffers: alg: skcipher: encryption failed on chunk test 1 for ecb-aes-s5p: ret=22 Handle such case by copying the buffers to a new aligned and contiguous space. Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 150 +++++++++++++++++++++++++++++++++++---- 1 file changed, 138 insertions(+), 12 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 60f835455a41..3730fb0af4d8 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -28,6 +28,7 @@ #include #include #include +#include #define _SBF(s, v) ((v) << (s)) #define _BIT(b) _SBF(b, 1) @@ -185,6 +186,10 @@ struct s5p_aes_dev { struct scatterlist *sg_src; struct scatterlist *sg_dst; + /* In case of unaligned access: */ + struct scatterlist *sg_src_cpy; + struct scatterlist *sg_dst_cpy; + struct tasklet_struct tasklet; struct crypto_queue queue; bool busy; @@ -244,8 +249,45 @@ static void s5p_set_dma_outdata(struct s5p_aes_dev *dev, struct scatterlist *sg) SSS_WRITE(dev, FCBTDMAL, sg_dma_len(sg)); } +static void s5p_free_sg_cpy(struct s5p_aes_dev *dev, struct scatterlist **sg) +{ + int len; + + if (!*sg) + return; + + len = ALIGN(dev->req->nbytes, AES_BLOCK_SIZE); + free_pages((unsigned long)sg_virt(*sg), get_order(len)); + + kfree(*sg); + *sg = NULL; +} + +static void s5p_sg_copy_buf(void *buf, struct scatterlist *sg, + unsigned int nbytes, int out) +{ + struct scatter_walk walk; + + if (!nbytes) + return; + + scatterwalk_start(&walk, sg); + scatterwalk_copychunks(buf, &walk, nbytes, out); + scatterwalk_done(&walk, out, 0); +} + static void s5p_aes_complete(struct s5p_aes_dev *dev, int err) { + if (dev->sg_dst_cpy) { + dev_dbg(dev->dev, + "Copying %d bytes of output data back to original place\n", + dev->req->nbytes); + s5p_sg_copy_buf(sg_virt(dev->sg_dst_cpy), dev->req->dst, + dev->req->nbytes, 1); + } + s5p_free_sg_cpy(dev, &dev->sg_src_cpy); + s5p_free_sg_cpy(dev, &dev->sg_dst_cpy); + /* holding a lock outside */ dev->req->base.complete(&dev->req->base, err); dev->busy = false; @@ -261,14 +303,36 @@ static void s5p_unset_indata(struct s5p_aes_dev *dev) dma_unmap_sg(dev->dev, dev->sg_src, 1, DMA_TO_DEVICE); } +static int s5p_make_sg_cpy(struct s5p_aes_dev *dev, struct scatterlist *src, + struct scatterlist **dst) +{ + void *pages; + int len; + + *dst = kmalloc(sizeof(**dst), GFP_ATOMIC); + if (!*dst) + return -ENOMEM; + + len = ALIGN(dev->req->nbytes, AES_BLOCK_SIZE); + pages = (void *)__get_free_pages(GFP_ATOMIC, get_order(len)); + if (!pages) { + kfree(*dst); + *dst = NULL; + return -ENOMEM; + } + + s5p_sg_copy_buf(pages, src, dev->req->nbytes, 0); + + sg_init_table(*dst, 1); + sg_set_buf(*dst, pages, len); + + return 0; +} + static int s5p_set_outdata(struct s5p_aes_dev *dev, struct scatterlist *sg) { int err; - if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) { - err = -EINVAL; - goto exit; - } if (!sg_dma_len(sg)) { err = -EINVAL; goto exit; @@ -291,10 +355,6 @@ static int s5p_set_indata(struct s5p_aes_dev *dev, struct scatterlist *sg) { int err; - if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) { - err = -EINVAL; - goto exit; - } if (!sg_dma_len(sg)) { err = -EINVAL; goto exit; @@ -394,6 +454,71 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, memcpy_toio(keystart, key, keylen); } +static bool s5p_is_sg_aligned(struct scatterlist *sg) +{ + while (sg) { + if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) + return false; + sg = sg_next(sg); + } + + return true; +} + +static int s5p_set_indata_start(struct s5p_aes_dev *dev, + struct ablkcipher_request *req) +{ + struct scatterlist *sg; + int err; + + dev->sg_src_cpy = NULL; + sg = req->src; + if (!s5p_is_sg_aligned(sg)) { + dev_dbg(dev->dev, + "At least one unaligned source scatter list, making a copy\n"); + err = s5p_make_sg_cpy(dev, sg, &dev->sg_src_cpy); + if (err) + return err; + + sg = dev->sg_src_cpy; + } + + err = s5p_set_indata(dev, sg); + if (err) { + s5p_free_sg_cpy(dev, &dev->sg_src_cpy); + return err; + } + + return 0; +} + +static int s5p_set_outdata_start(struct s5p_aes_dev *dev, + struct ablkcipher_request *req) +{ + struct scatterlist *sg; + int err; + + dev->sg_dst_cpy = NULL; + sg = req->dst; + if (!s5p_is_sg_aligned(sg)) { + dev_dbg(dev->dev, + "At least one unaligned dest scatter list, making a copy\n"); + err = s5p_make_sg_cpy(dev, sg, &dev->sg_dst_cpy); + if (err) + return err; + + sg = dev->sg_dst_cpy; + } + + err = s5p_set_outdata(dev, sg); + if (err) { + s5p_free_sg_cpy(dev, &dev->sg_dst_cpy); + return err; + } + + return 0; +} + static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) { struct ablkcipher_request *req = dev->req; @@ -430,19 +555,19 @@ static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) SSS_FCINTENCLR_BTDMAINTENCLR | SSS_FCINTENCLR_BRDMAINTENCLR); SSS_WRITE(dev, FCFIFOCTRL, 0x00); - err = s5p_set_indata(dev, req->src); + err = s5p_set_indata_start(dev, req); if (err) goto indata_error; - err = s5p_set_outdata(dev, req->dst); + err = s5p_set_outdata_start(dev, req); if (err) goto outdata_error; SSS_AES_WRITE(dev, AES_CONTROL, aes_control); s5p_set_aes(dev, dev->ctx->aes_key, req->info, dev->ctx->keylen); - s5p_set_dma_indata(dev, req->src); - s5p_set_dma_outdata(dev, req->dst); + s5p_set_dma_indata(dev, dev->sg_src); + s5p_set_dma_outdata(dev, dev->sg_dst); SSS_WRITE(dev, FCINTENSET, SSS_FCINTENSET_BTDMAINTENSET | SSS_FCINTENSET_BRDMAINTENSET); @@ -452,6 +577,7 @@ static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) return; outdata_error: + s5p_free_sg_cpy(dev, &dev->sg_src_cpy); s5p_unset_indata(dev); indata_error: -- GitLab From 3cf9d84eb84abb4c186cd793d8720437a2ee2b1a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 22 Mar 2016 10:58:25 +0900 Subject: [PATCH 1363/9938] crypto: s5p-sss - Sort the headers to improve readability Sort the headers alphabetically to improve readability and to spot duplications easier. Suggested-by: Vladimir Zapolskiy Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 3730fb0af4d8..4f6d5b3ec418 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -11,23 +11,23 @@ * */ +#include +#include +#include #include -#include -#include #include +#include +#include +#include #include -#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include #define _SBF(s, v) ((v) << (s)) -- GitLab From f2d1362ff7d266b3d2b1c764d6c2ef4a3b457f23 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:35 +0100 Subject: [PATCH 1364/9938] lib/mpi: mpi_write_sgl(): fix skipping of leading zero limbs Currently, if the number of leading zeros is greater than fits into a complete limb, mpi_write_sgl() skips them by iterating over them limb-wise. However, it fails to adjust its internal leading zeros tracking variable, lzeros, accordingly: it does a p -= sizeof(alimb); continue; which should really have been a lzeros -= sizeof(alimb); continue; Since lzeros never decreases if its initial value >= sizeof(alimb), nothing gets copied by mpi_write_sgl() in that case. Instead of skipping the high order zero limbs within the loop as shown above, fix the issue by adjusting the copying loop's bounds. Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers") Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index eb15e7dc7b65..6bb52beb06b0 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -380,7 +380,9 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, buf_len = sgl->length; p2 = sg_virt(sgl); - for (i = a->nlimbs - 1; i >= 0; i--) { + for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB, + lzeros %= BYTES_PER_MPI_LIMB; + i >= 0; i--) { alimb = a->d[i]; p = (u8 *)&alimb2; #if BYTES_PER_MPI_LIMB == 4 @@ -401,17 +403,12 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, #error please implement for this limb size. #endif if (lzeros > 0) { - if (lzeros >= sizeof(alimb)) { - p -= sizeof(alimb); - continue; - } else { - mpi_limb_t *limb1 = (void *)p - sizeof(alimb); - mpi_limb_t *limb2 = (void *)p - sizeof(alimb) - + lzeros; - *limb1 = *limb2; - p -= lzeros; - y = lzeros; - } + mpi_limb_t *limb1 = (void *)p - sizeof(alimb); + mpi_limb_t *limb2 = (void *)p - sizeof(alimb) + + lzeros; + *limb1 = *limb2; + p -= lzeros; + y = lzeros; lzeros -= sizeof(alimb); } -- GitLab From 654842ef53d7820129a751f5cc620e5a69c694a9 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:36 +0100 Subject: [PATCH 1365/9938] lib/mpi: mpi_write_sgl(): fix style issue with lzero decrement Within the copying loop in mpi_write_sgl(), we have if (lzeros > 0) { ... lzeros -= sizeof(alimb); } However, at this point, lzeros < sizeof(alimb) holds. Make this fact explicit by rewriting the above to if (lzeros) { ... lzeros = 0; } Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 6bb52beb06b0..d8b372b9cc11 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -402,14 +402,14 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, #else #error please implement for this limb size. #endif - if (lzeros > 0) { + if (lzeros) { mpi_limb_t *limb1 = (void *)p - sizeof(alimb); mpi_limb_t *limb2 = (void *)p - sizeof(alimb) + lzeros; *limb1 = *limb2; p -= lzeros; y = lzeros; - lzeros -= sizeof(alimb); + lzeros = 0; } p = p - (sizeof(alimb) - y); -- GitLab From ea122be0b8f788b30e71ed5536fddc05f5ddff86 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:37 +0100 Subject: [PATCH 1366/9938] lib/mpi: mpi_write_sgl(): purge redundant pointer arithmetic Within the copying loop in mpi_write_sgl(), we have if (lzeros) { ... p -= lzeros; y = lzeros; } p = p - (sizeof(alimb) - y); If lzeros == 0, then y == 0, too. Thus, lzeros gets subtracted and added back again to p. Purge this redundancy. Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index d8b372b9cc11..78ec4e1131b9 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -407,12 +407,11 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, mpi_limb_t *limb2 = (void *)p - sizeof(alimb) + lzeros; *limb1 = *limb2; - p -= lzeros; y = lzeros; lzeros = 0; } - p = p - (sizeof(alimb) - y); + p = p - sizeof(alimb); for (x = 0; x < sizeof(alimb) - y; x++) { if (!buf_len) { -- GitLab From cece762f6f3cb1c1687f467e98faef21b0096600 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:38 +0100 Subject: [PATCH 1367/9938] lib/mpi: mpi_write_sgl(): fix out-of-bounds stack access Within the copying loop in mpi_write_sgl(), we have if (lzeros) { mpi_limb_t *limb1 = (void *)p - sizeof(alimb); mpi_limb_t *limb2 = (void *)p - sizeof(alimb) + lzeros; *limb1 = *limb2; ... } where p points past the end of alimb2 which lives on the stack and contains the current limb in BE order. The purpose of the above is to shift the non-zero bytes of alimb2 to its beginning in memory, i.e. to skip its leading zero bytes. However, limb2 points somewhere into the middle of alimb2 and thus, reading *limb2 pulls in lzero bytes from somewhere. Indeed, KASAN splats: BUG: KASAN: stack-out-of-bounds in mpi_write_to_sgl+0x4e3/0x6f0 at addr ffff8800cb04f601 Read of size 8 by task systemd-udevd/391 page:ffffea00032c13c0 count:0 mapcount:0 mapping: (null) index:0x0 flags: 0x3fff8000000000() page dumped because: kasan: bad access detected CPU: 3 PID: 391 Comm: systemd-udevd Tainted: G B L 4.5.0-next-20160316+ #12 [...] Call Trace: [] dump_stack+0xdc/0x15e [] ? _atomic_dec_and_lock+0xa2/0xa2 [] ? __dump_page+0x185/0x330 [] kasan_report_error+0x5e6/0x8b0 [] ? kzfree+0x2d/0x40 [] ? mpi_free_limb_space+0xe/0x20 [] ? mpi_powm+0x37e/0x16f0 [] kasan_report+0x71/0xa0 [] ? mpi_write_to_sgl+0x4e3/0x6f0 [] __asan_load8+0x64/0x70 [] mpi_write_to_sgl+0x4e3/0x6f0 [] ? mpi_set_buffer+0x620/0x620 [] ? mpi_cmp+0xbf/0x180 [] rsa_verify+0x202/0x260 What's more, since lzeros can be anything from 1 to sizeof(mpi_limb_t)-1, the above will cause unaligned accesses which is bad on non-x86 archs. Fix the issue, by preparing the starting point p for the upcoming copy operation instead of shifting the source memory, i.e. alimb2. Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers") Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 78ec4e1131b9..b05d3902d363 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -403,15 +403,11 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, #error please implement for this limb size. #endif if (lzeros) { - mpi_limb_t *limb1 = (void *)p - sizeof(alimb); - mpi_limb_t *limb2 = (void *)p - sizeof(alimb) - + lzeros; - *limb1 = *limb2; y = lzeros; lzeros = 0; } - p = p - sizeof(alimb); + p = p - sizeof(alimb) + y; for (x = 0; x < sizeof(alimb) - y; x++) { if (!buf_len) { -- GitLab From d755290689646fa66cc4830ca55569f2c9863666 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:39 +0100 Subject: [PATCH 1368/9938] lib/mpi: mpi_write_sgl(): replace open coded endian conversion Currently, the endian conversion from CPU order to BE is open coded in mpi_write_sgl(). Replace this by the centrally provided cpu_to_be*() macros. Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index b05d3902d363..623439e4bad5 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -20,6 +20,7 @@ #include #include +#include #include "mpi-internal.h" #define MAX_EXTERN_MPI_BITS 16384 @@ -359,7 +360,13 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, int *sign) { u8 *p, *p2; - mpi_limb_t alimb, alimb2; +#if BYTES_PER_MPI_LIMB == 4 + __be32 alimb; +#elif BYTES_PER_MPI_LIMB == 8 + __be64 alimb; +#else +#error please implement for this limb size. +#endif unsigned int n = mpi_get_size(a); int i, x, y = 0, lzeros, buf_len; @@ -383,22 +390,10 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB, lzeros %= BYTES_PER_MPI_LIMB; i >= 0; i--) { - alimb = a->d[i]; - p = (u8 *)&alimb2; #if BYTES_PER_MPI_LIMB == 4 - *p++ = alimb >> 24; - *p++ = alimb >> 16; - *p++ = alimb >> 8; - *p++ = alimb; + alimb = cpu_to_be32(a->d[i]); #elif BYTES_PER_MPI_LIMB == 8 - *p++ = alimb >> 56; - *p++ = alimb >> 48; - *p++ = alimb >> 40; - *p++ = alimb >> 32; - *p++ = alimb >> 24; - *p++ = alimb >> 16; - *p++ = alimb >> 8; - *p++ = alimb; + alimb = cpu_to_be64(a->d[i]); #else #error please implement for this limb size. #endif @@ -407,7 +402,7 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, lzeros = 0; } - p = p - sizeof(alimb) + y; + p = (u8 *)&alimb + y; for (x = 0; x < sizeof(alimb) - y; x++) { if (!buf_len) { -- GitLab From f00fa2417b3e1252b1a761f88731af03afff4407 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:40 +0100 Subject: [PATCH 1369/9938] lib/mpi: mpi_read_buffer(): optimize skipping of leading zero limbs Currently, if the number of leading zeros is greater than fits into a complete limb, mpi_read_buffer() skips them by iterating over them limb-wise. Instead of skipping the high order zero limbs within the loop as shown above, adjust the copying loop's bounds. Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 623439e4bad5..2fd8d418526c 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -184,7 +184,9 @@ int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, p = buf; *nbytes = n - lzeros; - for (i = a->nlimbs - 1; i >= 0; i--) { + for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB, + lzeros %= BYTES_PER_MPI_LIMB; + i >= 0; i--) { alimb = a->d[i]; #if BYTES_PER_MPI_LIMB == 4 *p++ = alimb >> 24; @@ -205,15 +207,11 @@ int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, #endif if (lzeros > 0) { - if (lzeros >= sizeof(alimb)) { - p -= sizeof(alimb); - } else { - mpi_limb_t *limb1 = (void *)p - sizeof(alimb); - mpi_limb_t *limb2 = (void *)p - sizeof(alimb) - + lzeros; - *limb1 = *limb2; - p -= lzeros; - } + mpi_limb_t *limb1 = (void *)p - sizeof(alimb); + mpi_limb_t *limb2 = (void *)p - sizeof(alimb) + + lzeros; + *limb1 = *limb2; + p -= lzeros; lzeros -= sizeof(alimb); } } -- GitLab From 90f864e20029600a8dc33e27b1192af4636100d4 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:41 +0100 Subject: [PATCH 1370/9938] lib/mpi: mpi_read_buffer(): replace open coded endian conversion Currently, the endian conversion from CPU order to BE is open coded in mpi_read_buffer(). Replace this by the centrally provided cpu_to_be*() macros. Copy from the temporary storage on stack to the destination buffer by means of memcpy(). Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 2fd8d418526c..a999ee1cddc5 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "mpi-internal.h" #define MAX_EXTERN_MPI_BITS 16384 @@ -164,7 +165,13 @@ int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, int *sign) { uint8_t *p; - mpi_limb_t alimb; +#if BYTES_PER_MPI_LIMB == 4 + __be32 alimb; +#elif BYTES_PER_MPI_LIMB == 8 + __be64 alimb; +#else +#error please implement for this limb size. +#endif unsigned int n = mpi_get_size(a); int i, lzeros; @@ -187,25 +194,15 @@ int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB, lzeros %= BYTES_PER_MPI_LIMB; i >= 0; i--) { - alimb = a->d[i]; #if BYTES_PER_MPI_LIMB == 4 - *p++ = alimb >> 24; - *p++ = alimb >> 16; - *p++ = alimb >> 8; - *p++ = alimb; + alimb = cpu_to_be32(a->d[i]); #elif BYTES_PER_MPI_LIMB == 8 - *p++ = alimb >> 56; - *p++ = alimb >> 48; - *p++ = alimb >> 40; - *p++ = alimb >> 32; - *p++ = alimb >> 24; - *p++ = alimb >> 16; - *p++ = alimb >> 8; - *p++ = alimb; + alimb = cpu_to_be64(a->d[i]); #else #error please implement for this limb size. #endif - + memcpy(p, &alimb, BYTES_PER_MPI_LIMB); + p += BYTES_PER_MPI_LIMB; if (lzeros > 0) { mpi_limb_t *limb1 = (void *)p - sizeof(alimb); mpi_limb_t *limb2 = (void *)p - sizeof(alimb) -- GitLab From 462696fd0fd2aae2fd38d22d19b2d08a55606014 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:42 +0100 Subject: [PATCH 1371/9938] lib/mpi: mpi_read_buffer(): fix buffer overflow Currently, mpi_read_buffer() writes full limbs to the output buffer and moves memory around to purge leading zero limbs afterwards. However, with commit 9cbe21d8f89d ("lib/mpi: only require buffers as big as needed for the integer") the caller is only required to provide a buffer large enough to hold the result without the leading zeros. This might result in a buffer overflow for small MP numbers with leading zeros. Fix this by coping the result to its final destination within the output buffer and not copying the leading zeros at all. Fixes: 9cbe21d8f89d ("lib/mpi: only require buffers as big as needed for the integer") Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index a999ee1cddc5..d995a4c0f1b6 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -201,16 +201,9 @@ int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, #else #error please implement for this limb size. #endif - memcpy(p, &alimb, BYTES_PER_MPI_LIMB); - p += BYTES_PER_MPI_LIMB; - if (lzeros > 0) { - mpi_limb_t *limb1 = (void *)p - sizeof(alimb); - mpi_limb_t *limb2 = (void *)p - sizeof(alimb) - + lzeros; - *limb1 = *limb2; - p -= lzeros; - lzeros -= sizeof(alimb); - } + memcpy(p, (u8 *)&alimb + lzeros, BYTES_PER_MPI_LIMB - lzeros); + p += BYTES_PER_MPI_LIMB - lzeros; + lzeros = 0; } return 0; } -- GitLab From b698538951a45dd853d9e40f51e143fdd46a60c6 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:43 +0100 Subject: [PATCH 1372/9938] lib/mpi: mpi_read_raw_from_sgl(): replace len argument by nbytes Currently, the nbytes local variable is calculated from the len argument as follows: ... mpi_read_raw_from_sgl(..., unsigned int len) { unsigned nbytes; ... if (!ents) nbytes = 0; else nbytes = len - lzeros; ... } Given that nbytes is derived from len in a trivial way and that the len argument is shadowed by a local len variable in several loops, this is just confusing. Rename the len argument to nbytes and get rid of the nbytes local variable. Do the nbytes calculation in place. Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index d995a4c0f1b6..048f0aa505ce 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -418,15 +418,15 @@ EXPORT_SYMBOL_GPL(mpi_write_to_sgl); * a new MPI and reads the content of the sgl to the MPI. * * @sgl: scatterlist to read from - * @len: number of bytes to read + * @nbytes: number of bytes to read * * Return: Pointer to a new MPI or NULL on error */ -MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int len) +MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) { struct scatterlist *sg; int x, i, j, z, lzeros, ents; - unsigned int nbits, nlimbs, nbytes; + unsigned int nbits, nlimbs; mpi_limb_t a; MPI val = NULL; @@ -455,7 +455,7 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int len) if (!ents) nbytes = 0; else - nbytes = len - lzeros; + nbytes -= lzeros; nbits = nbytes * 8; if (nbits > MAX_EXTERN_MPI_BITS) { -- GitLab From ab1e912ec1021e7532148398a01eb1283437fe62 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:44 +0100 Subject: [PATCH 1373/9938] lib/mpi: mpi_read_raw_from_sgl(): don't include leading zero SGEs in nbytes At the very beginning of mpi_read_raw_from_sgl(), the leading zeros of the input scatterlist are counted: lzeros = 0; for_each_sg(sgl, sg, ents, i) { ... if (/* sg contains nonzero bytes */) break; /* sg contains nothing but zeros here */ ents--; lzeros = 0; } Later on, the total number of trailing nonzero bytes is calculated by subtracting the number of leading zero bytes from the total number of input bytes: nbytes -= lzeros; However, since lzeros gets reset to zero for each completely zero leading sg in the loop above, it doesn't include those. Besides wasting resources by allocating a too large output buffer, this mistake propagates into the calculation of x, the number of leading zeros within the most significant output limb: x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; What's more, the low order bytes of the output, equal in number to the extra bytes in nbytes, are left uninitialized. Fix this by adjusting nbytes for each completely zero leading scatterlist entry. Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers") Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 048f0aa505ce..4ba0f2361d3c 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -447,16 +447,12 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) break; ents--; + nbytes -= lzeros; lzeros = 0; } sgl = sg; - - if (!ents) - nbytes = 0; - else - nbytes -= lzeros; - + nbytes -= lzeros; nbits = nbytes * 8; if (nbits > MAX_EXTERN_MPI_BITS) { pr_info("MPI: mpi too large (%u bits)\n", nbits); -- GitLab From 60e1b74c224e9eda14e5b479413c5d990373c2cb Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:12:45 +0100 Subject: [PATCH 1374/9938] lib/mpi: mpi_read_raw_from_sgl(): purge redundant clearing of nbits In mpi_read_raw_from_sgl(), unsigned nbits is calculated as follows: nbits = nbytes * 8; and redundantly cleared later on if nbytes == 0: if (nbytes > 0) ... else nbits = 0; Purge this redundant clearing for the sake of clarity. Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 4ba0f2361d3c..27703aad287a 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -461,8 +461,6 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) if (nbytes > 0) nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); - else - nbits = 0; nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); val = mpi_alloc(nlimbs); -- GitLab From 64c09b0b59b92ad231dd526f57f24139b728044b Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:17:27 +0100 Subject: [PATCH 1375/9938] lib/mpi: mpi_read_raw_from_sgl(): fix nbits calculation The number of bits, nbits, is calculated in mpi_read_raw_from_sgl() as follows: nbits = nbytes * 8; Afterwards, the number of leading zero bits of the first byte get subtracted: nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); However, count_leading_zeros() takes an unsigned long and thus, the u8 gets promoted to an unsigned long. Thus, the above doesn't subtract the number of leading zeros in the most significant nonzero input byte from nbits, but the number of leading zeros of the most significant nonzero input byte promoted to unsigned long, i.e. BITS_PER_LONG - 8 too many. Fix this by subtracting count_leading_zeros(...) - (BITS_PER_LONG - 8) from nbits only. Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers") Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 27703aad287a..24a015513b40 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -460,7 +460,8 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) } if (nbytes > 0) - nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); + nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)) - + (BITS_PER_LONG - 8); nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); val = mpi_alloc(nlimbs); -- GitLab From 85d541a3d14ab7a4e08c280740d9a7e097b04835 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:18:07 +0100 Subject: [PATCH 1376/9938] lib/mpi: mpi_read_raw_from_sgl(): sanitize meaning of indices Within the byte reading loop in mpi_read_raw_sgl(), there are two housekeeping indices used, z and x. At all times, the index z represents the number of output bytes covered by the input SGEs for which processing has completed so far. This includes any leading zero bytes within the most significant limb. The index x changes its meaning after the first outer loop's iteration though: while processing the first input SGE, it represents "number of leading zero bytes in most significant output limb" + "current position within current SGE" For the remaining SGEs OTOH, x corresponds just to "current position within current SGE" After all, it is only the sum of z and x that has any meaning for the output buffer and thus, the "number of leading zero bytes in most significant output limb" part can be moved away from x into z from the beginning, opening up the opportunity for cleaner code. Before the outer loop iterating over the SGEs, don't initialize z with zero, but with the number of leading zero bytes in the most significant output limb. For the inner loop iterating over a single SGE's bytes, get rid of the buf_shift offset to x' bounds and let x run from zero to sg->length - 1. Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 24a015513b40..a9f1097c18cb 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -477,19 +477,17 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) j = nlimbs - 1; a = 0; - z = 0; - x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; - x %= BYTES_PER_MPI_LIMB; + z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + z %= BYTES_PER_MPI_LIMB; for_each_sg(sgl, sg, ents, i) { const u8 *buffer = sg_virt(sg) + lzeros; int len = sg->length - lzeros; - int buf_shift = x; if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); - for (; x < len + buf_shift; x++) { + for (x = 0; x < len; x++) { a <<= 8; a |= *buffer++; if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { @@ -498,7 +496,6 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) } } z += x; - x = 0; lzeros = 0; } return val; -- GitLab From 0bb5c9ead62f4e1eaf226744076e0b4e8348f68f Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 13:18:16 +0100 Subject: [PATCH 1377/9938] lib/mpi: mpi_read_raw_from_sgl(): fix out-of-bounds buffer access Within the copying loop in mpi_read_raw_from_sgl(), the last input SGE's byte count gets artificially extended as follows: if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); Within the following byte copying loop, this causes reads beyond that SGE's allocated buffer: BUG: KASAN: slab-out-of-bounds in mpi_read_raw_from_sgl+0x331/0x650 at addr ffff8801e168d4d8 Read of size 1 by task systemd-udevd/721 [...] Call Trace: [] dump_stack+0xbc/0x117 [] ? _atomic_dec_and_lock+0x169/0x169 [] ? print_section+0x61/0xb0 [] print_trailer+0x179/0x2c0 [] object_err+0x34/0x40 [] kasan_report_error+0x307/0x8c0 [] ? kasan_unpoison_shadow+0x35/0x50 [] ? kasan_kmalloc+0x5e/0x70 [] kasan_report+0x71/0xa0 [] ? mpi_read_raw_from_sgl+0x331/0x650 [] __asan_load1+0x46/0x50 [] mpi_read_raw_from_sgl+0x331/0x650 [] rsa_verify+0x106/0x260 [] ? rsa_set_pub_key+0xf0/0xf0 [] ? sg_init_table+0x29/0x50 [] ? pkcs1pad_sg_set_buf+0xb2/0x2e0 [] pkcs1pad_verify+0x1f4/0x2b0 [] public_key_verify_signature+0x3a7/0x5e0 [] ? public_key_describe+0x80/0x80 [] ? keyring_search_aux+0x150/0x150 [] ? x509_request_asymmetric_key+0x114/0x370 [] ? kfree+0x220/0x370 [] public_key_verify_signature_2+0x32/0x50 [] verify_signature+0x7c/0xb0 [] pkcs7_validate_trust+0x42c/0x5f0 [] system_verify_data+0xca/0x170 [] ? top_trace_array+0x9b/0x9b [] ? __vfs_read+0x279/0x3d0 [] mod_verify_sig+0x1ff/0x290 [...] The exact purpose of the len extension isn't clear to me, but due to its form, I suspect that it's a leftover somehow accounting for leading zero bytes within the most significant output limb. Note however that without that len adjustement, the total number of bytes ever processed by the inner loop equals nbytes and thus, the last output limb gets written at this point. Thus the net effect of the len adjustement cited above is just to keep the inner loop running for some more iterations, namely < BYTES_PER_MPI_LIMB ones, reading some extra bytes from beyond the last SGE's buffer and discarding them afterwards. Fix this issue by purging the extension of len beyond the last input SGE's buffer length. Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers") Signed-off-by: Nicolai Stange Signed-off-by: Herbert Xu --- lib/mpi/mpicoder.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index a9f1097c18cb..747606f9e4a3 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -484,9 +484,6 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) const u8 *buffer = sg_virt(sg) + lzeros; int len = sg->length - lzeros; - if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) - len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); - for (x = 0; x < len; x++) { a <<= 8; a |= *buffer++; -- GitLab From 082ebe92ca7f09845f0550e85837a878d6cedb34 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 22 Mar 2016 10:45:25 -0700 Subject: [PATCH 1378/9938] crypto: qat - make sure const_tab is 1024 bytes aligned FW requires the const_tab to be 1024 bytes aligned. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_admin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/adf_admin.c b/drivers/crypto/qat/qat_common/adf_admin.c index eb557f69e367..ce7c4626c983 100644 --- a/drivers/crypto/qat/qat_common/adf_admin.c +++ b/drivers/crypto/qat/qat_common/adf_admin.c @@ -61,7 +61,7 @@ #define ADF_DH895XCC_MAILBOX_STRIDE 0x1000 #define ADF_ADMINMSG_LEN 32 -static const u8 const_tab[1024] = { +static const u8 const_tab[1024] __aligned(1024) = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -- GitLab From 0c4935b31df0e5ffa6da0f8a2fdfc690d1118ba7 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Tue, 22 Mar 2016 11:25:21 -0700 Subject: [PATCH 1379/9938] crypto: qat - Remove redundant nrbg rings Remove redundant nrbg rings. Signed-off-by: Ahsan Atta Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_cfg_strings.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/crypto/qat/qat_common/adf_cfg_strings.h b/drivers/crypto/qat/qat_common/adf_cfg_strings.h index 13575111382c..7632ed0f25c5 100644 --- a/drivers/crypto/qat/qat_common/adf_cfg_strings.h +++ b/drivers/crypto/qat/qat_common/adf_cfg_strings.h @@ -57,10 +57,8 @@ #define ADF_RING_DC_SIZE "NumConcurrentRequests" #define ADF_RING_ASYM_TX "RingAsymTx" #define ADF_RING_SYM_TX "RingSymTx" -#define ADF_RING_RND_TX "RingNrbgTx" #define ADF_RING_ASYM_RX "RingAsymRx" #define ADF_RING_SYM_RX "RingSymRx" -#define ADF_RING_RND_RX "RingNrbgRx" #define ADF_RING_DC_TX "RingTx" #define ADF_RING_DC_RX "RingRx" #define ADF_ETRMGR_BANK "Bank" -- GitLab From aa8b6dd4b06bab62ec7f8972f9e66782dbc23d60 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 23 Mar 2016 17:06:39 +0200 Subject: [PATCH 1380/9938] crypto: qat - avoid memory corruption or undefined behaviour memcopying to a (null pointer + offset) will result in memory corruption or undefined behaviour. Signed-off-by: Tudor Ambarus Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/qat_asym_algs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index e5c0727d4876..8dbbf0849436 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -593,7 +593,7 @@ int qat_rsa_get_d(void *context, size_t hdrlen, unsigned char tag, ret = -ENOMEM; ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL); - if (!ctx->n) + if (!ctx->d) goto err; memcpy(ctx->d + (ctx->key_sz - vlen), ptr, vlen); -- GitLab From 738f98233b94db55607f97a76f9699efc4217276 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 23 Mar 2016 17:06:40 +0200 Subject: [PATCH 1381/9938] crypto: qat - fix address leaking of RSA public exponent Signed-off-by: Tudor Ambarus Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/qat_asym_algs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index 8dbbf0849436..05f49d4f94b2 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -711,7 +711,7 @@ static void qat_rsa_exit_tfm(struct crypto_akcipher *tfm) } qat_crypto_put_instance(ctx->inst); ctx->n = NULL; - ctx->d = NULL; + ctx->e = NULL; ctx->d = NULL; } -- GitLab From bdb6cf9f6fe6d9af905ea34b7c4bb78ea601329e Mon Sep 17 00:00:00 2001 From: Corentin LABBE Date: Wed, 23 Mar 2016 16:11:24 +0100 Subject: [PATCH 1382/9938] crypto: sun4i-ss - Replace spinlock_bh by spin_lock_irq{save|restore} The current sun4i-ss driver could generate data corruption when ciphering/deciphering. It occurs randomly on end of handled data. No root cause have been found and the only way to remove it is to replace all spin_lock_bh by their irq counterparts. Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator") Signed-off-by: LABBE Corentin Cc: stable Signed-off-by: Herbert Xu --- drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index 7be3fbcd8d78..3830d7c4e138 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -35,6 +35,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq) unsigned int todo; struct sg_mapping_iter mi, mo; unsigned int oi, oo; /* offset for in and out */ + unsigned long flags; if (areq->nbytes == 0) return 0; @@ -49,7 +50,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq) return -EINVAL; } - spin_lock_bh(&ss->slock); + spin_lock_irqsave(&ss->slock, flags); for (i = 0; i < op->keylen; i += 4) writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); @@ -117,7 +118,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq) sg_miter_stop(&mi); sg_miter_stop(&mo); writel(0, ss->base + SS_CTL); - spin_unlock_bh(&ss->slock); + spin_unlock_irqrestore(&ss->slock, flags); return err; } @@ -149,6 +150,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) unsigned int ob = 0; /* offset in buf */ unsigned int obo = 0; /* offset in bufo*/ unsigned int obl = 0; /* length of data in bufo */ + unsigned long flags; if (areq->nbytes == 0) return 0; @@ -181,7 +183,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) if (no_chunk == 1) return sun4i_ss_opti_poll(areq); - spin_lock_bh(&ss->slock); + spin_lock_irqsave(&ss->slock, flags); for (i = 0; i < op->keylen; i += 4) writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); @@ -307,7 +309,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) sg_miter_stop(&mi); sg_miter_stop(&mo); writel(0, ss->base + SS_CTL); - spin_unlock_bh(&ss->slock); + spin_unlock_irqrestore(&ss->slock, flags); return err; } -- GitLab From 4218ebe8cab421c72f134cca1374e0985303f34a Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Mon, 28 Mar 2016 16:47:55 +0200 Subject: [PATCH 1383/9938] crypto: drbg - set HMAC key only when altered The HMAC implementation allows setting the HMAC key independently from the hashing operation. Therefore, the key only needs to be set when a new key is generated. This patch increases the speed of the HMAC DRBG by at least 35% depending on the use case. The patch is fully CAVS tested. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/drbg.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 1b86310db7b1..0a3538f6cf22 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -592,8 +592,10 @@ static const struct drbg_state_ops drbg_ctr_ops = { ******************************************************************/ #if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC) -static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, - unsigned char *outval, const struct list_head *in); +static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, + const struct list_head *in); +static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, + const unsigned char *key); static int drbg_init_hash_kernel(struct drbg_state *drbg); static int drbg_fini_hash_kernel(struct drbg_state *drbg); #endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ @@ -619,9 +621,11 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, LIST_HEAD(seedlist); LIST_HEAD(vdatalist); - if (!reseed) + if (!reseed) { /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */ memset(drbg->V, 1, drbg_statelen(drbg)); + drbg_kcapi_hmacsetkey(drbg, drbg->C); + } drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg)); list_add_tail(&seed1.list, &seedlist); @@ -641,12 +645,13 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, prefix = DRBG_PREFIX1; /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ seed2.buf = &prefix; - ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist); + ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist); if (ret) return ret; + drbg_kcapi_hmacsetkey(drbg, drbg->C); /* 10.1.2.2 step 2 and 5 -- HMAC for V */ - ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist); + ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist); if (ret) return ret; @@ -681,7 +686,7 @@ static int drbg_hmac_generate(struct drbg_state *drbg, while (len < buflen) { unsigned int outlen = 0; /* 10.1.2.5 step 4.1 */ - ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist); + ret = drbg_kcapi_hash(drbg, drbg->V, &datalist); if (ret) return ret; outlen = (drbg_blocklen(drbg) < (buflen - len)) ? @@ -796,7 +801,7 @@ static int drbg_hash_df(struct drbg_state *drbg, while (len < outlen) { short blocklen = 0; /* 10.4.1 step 4.1 */ - ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist); + ret = drbg_kcapi_hash(drbg, tmp, entropylist); if (ret) goto out; /* 10.4.1 step 4.2 */ @@ -874,7 +879,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg, list_add_tail(&data1.list, &datalist); list_add_tail(&data2.list, &datalist); list_splice_tail(addtl, &datalist); - ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist); + ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist); if (ret) goto out; @@ -907,7 +912,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg, while (len < buflen) { unsigned int outlen = 0; /* 10.1.1.4 step hashgen 4.1 */ - ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist); + ret = drbg_kcapi_hash(drbg, dst, &datalist); if (ret) { len = ret; goto out; @@ -956,7 +961,7 @@ static int drbg_hash_generate(struct drbg_state *drbg, list_add_tail(&data1.list, &datalist); drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); list_add_tail(&data2.list, &datalist); - ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist); + ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist); if (ret) { len = ret; goto out; @@ -1600,14 +1605,20 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg) return 0; } -static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, - unsigned char *outval, const struct list_head *in) +static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, + const unsigned char *key) +{ + struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; + + crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg)); +} + +static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, + const struct list_head *in) { struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; struct drbg_string *input = NULL; - if (key) - crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg)); crypto_shash_init(&sdesc->shash); list_for_each_entry(input, in, list) crypto_shash_update(&sdesc->shash, input->buf, input->len); -- GitLab From cb00bca42f8b819498b2647f24b6148d65ec9aa4 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 29 Mar 2016 10:20:52 -0700 Subject: [PATCH 1384/9938] crypto: qat - explicitly stop all VFs first When stopping devices it is not enought to loop backwards. We need to explicitly stop all VFs first. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_ctl_drv.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c index 5c897e6e7994..740335630c57 100644 --- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c @@ -275,7 +275,26 @@ static int adf_ctl_stop_devices(uint32_t id) struct adf_accel_dev *accel_dev; int ret = 0; - list_for_each_entry_reverse(accel_dev, adf_devmgr_get_head(), list) { + list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) { + if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) { + if (!adf_dev_started(accel_dev)) + continue; + + /* First stop all VFs */ + if (!accel_dev->is_vf) + continue; + + if (adf_dev_stop(accel_dev)) { + dev_err(&GET_DEV(accel_dev), + "Failed to stop qat_dev%d\n", id); + ret = -EFAULT; + } else { + adf_dev_shutdown(accel_dev); + } + } + } + + list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) { if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) { if (!adf_dev_started(accel_dev)) continue; -- GitLab From f1420ceef3011547323733e3bb4fcb4aca3fe840 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 29 Mar 2016 10:21:07 -0700 Subject: [PATCH 1385/9938] crypto: qat - changed adf_dev_stop to void It returns always zero anyway. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_c3xxx/adf_drv.c | 4 +--- drivers/crypto/qat/qat_c3xxxvf/adf_drv.c | 4 +--- drivers/crypto/qat/qat_c62x/adf_drv.c | 4 +--- drivers/crypto/qat/qat_c62xvf/adf_drv.c | 4 +--- drivers/crypto/qat/qat_common/adf_common_drv.h | 2 +- drivers/crypto/qat/qat_common/adf_ctl_drv.c | 18 ++++-------------- drivers/crypto/qat/qat_common/adf_init.c | 12 +++++------- drivers/crypto/qat/qat_common/adf_sriov.c | 8 +------- drivers/crypto/qat/qat_dh895xcc/adf_drv.c | 4 +--- drivers/crypto/qat/qat_dh895xccvf/adf_drv.c | 4 +--- 10 files changed, 17 insertions(+), 47 deletions(-) diff --git a/drivers/crypto/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/qat/qat_c3xxx/adf_drv.c index e13bd08ddd1e..640c3fc870fd 100644 --- a/drivers/crypto/qat/qat_c3xxx/adf_drv.c +++ b/drivers/crypto/qat/qat_c3xxx/adf_drv.c @@ -300,9 +300,7 @@ static void adf_remove(struct pci_dev *pdev) pr_err("QAT: Driver removal failed\n"); return; } - if (adf_dev_stop(accel_dev)) - dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n"); - + adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); adf_disable_aer(accel_dev); adf_cleanup_accel(accel_dev); diff --git a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c index 1ac4ae90e072..a998981e9610 100644 --- a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c +++ b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c @@ -270,9 +270,7 @@ static void adf_remove(struct pci_dev *pdev) pr_err("QAT: Driver removal failed\n"); return; } - if (adf_dev_stop(accel_dev)) - dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n"); - + adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); adf_cleanup_accel(accel_dev); adf_cleanup_pci_dev(accel_dev); diff --git a/drivers/crypto/qat/qat_c62x/adf_drv.c b/drivers/crypto/qat/qat_c62x/adf_drv.c index 512c56509718..bc5cbc193aae 100644 --- a/drivers/crypto/qat/qat_c62x/adf_drv.c +++ b/drivers/crypto/qat/qat_c62x/adf_drv.c @@ -300,9 +300,7 @@ static void adf_remove(struct pci_dev *pdev) pr_err("QAT: Driver removal failed\n"); return; } - if (adf_dev_stop(accel_dev)) - dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n"); - + adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); adf_disable_aer(accel_dev); adf_cleanup_accel(accel_dev); diff --git a/drivers/crypto/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/qat/qat_c62xvf/adf_drv.c index d2e4b928f3be..ccfb25e8a4a1 100644 --- a/drivers/crypto/qat/qat_c62xvf/adf_drv.c +++ b/drivers/crypto/qat/qat_c62xvf/adf_drv.c @@ -270,9 +270,7 @@ static void adf_remove(struct pci_dev *pdev) pr_err("QAT: Driver removal failed\n"); return; } - if (adf_dev_stop(accel_dev)) - dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n"); - + adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); adf_cleanup_accel(accel_dev); adf_cleanup_pci_dev(accel_dev); diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index 0e82ce3c383e..c9e4d469e930 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -103,7 +103,7 @@ int adf_service_unregister(struct service_hndl *service); int adf_dev_init(struct adf_accel_dev *accel_dev); int adf_dev_start(struct adf_accel_dev *accel_dev); -int adf_dev_stop(struct adf_accel_dev *accel_dev); +void adf_dev_stop(struct adf_accel_dev *accel_dev); void adf_dev_shutdown(struct adf_accel_dev *accel_dev); int adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr); diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c index 740335630c57..48a1248381b3 100644 --- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c @@ -284,13 +284,8 @@ static int adf_ctl_stop_devices(uint32_t id) if (!accel_dev->is_vf) continue; - if (adf_dev_stop(accel_dev)) { - dev_err(&GET_DEV(accel_dev), - "Failed to stop qat_dev%d\n", id); - ret = -EFAULT; - } else { - adf_dev_shutdown(accel_dev); - } + adf_dev_stop(accel_dev); + adf_dev_shutdown(accel_dev); } } @@ -299,13 +294,8 @@ static int adf_ctl_stop_devices(uint32_t id) if (!adf_dev_started(accel_dev)) continue; - if (adf_dev_stop(accel_dev)) { - dev_err(&GET_DEV(accel_dev), - "Failed to stop qat_dev%d\n", id); - ret = -EFAULT; - } else { - adf_dev_shutdown(accel_dev); - } + adf_dev_stop(accel_dev); + adf_dev_shutdown(accel_dev); } } return ret; diff --git a/drivers/crypto/qat/qat_common/adf_init.c b/drivers/crypto/qat/qat_common/adf_init.c index ef5575e4a215..a29470bc8539 100644 --- a/drivers/crypto/qat/qat_common/adf_init.c +++ b/drivers/crypto/qat/qat_common/adf_init.c @@ -236,9 +236,9 @@ EXPORT_SYMBOL_GPL(adf_dev_start); * is shuting down. * To be used by QAT device specific drivers. * - * Return: 0 on success, error code otherwise. + * Return: void */ -int adf_dev_stop(struct adf_accel_dev *accel_dev) +void adf_dev_stop(struct adf_accel_dev *accel_dev) { struct service_hndl *service; struct list_head *list_itr; @@ -246,9 +246,9 @@ int adf_dev_stop(struct adf_accel_dev *accel_dev) int ret; if (!adf_dev_started(accel_dev) && - !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) { - return 0; - } + !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) + return; + clear_bit(ADF_STATUS_STARTING, &accel_dev->status); clear_bit(ADF_STATUS_STARTED, &accel_dev->status); @@ -279,8 +279,6 @@ int adf_dev_stop(struct adf_accel_dev *accel_dev) else clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status); } - - return 0; } EXPORT_SYMBOL_GPL(adf_dev_stop); diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c index 1117a8b58280..4479b0b63296 100644 --- a/drivers/crypto/qat/qat_common/adf_sriov.c +++ b/drivers/crypto/qat/qat_common/adf_sriov.c @@ -259,13 +259,7 @@ int adf_sriov_configure(struct pci_dev *pdev, int numvfs) return -EBUSY; } - if (adf_dev_stop(accel_dev)) { - dev_err(&GET_DEV(accel_dev), - "Failed to stop qat_dev%d\n", - accel_dev->accel_id); - return -EFAULT; - } - + adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); } diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/qat/qat_dh895xcc/adf_drv.c index a8c4b92a7cbd..4d2de2838451 100644 --- a/drivers/crypto/qat/qat_dh895xcc/adf_drv.c +++ b/drivers/crypto/qat/qat_dh895xcc/adf_drv.c @@ -302,9 +302,7 @@ static void adf_remove(struct pci_dev *pdev) pr_err("QAT: Driver removal failed\n"); return; } - if (adf_dev_stop(accel_dev)) - dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n"); - + adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); adf_disable_aer(accel_dev); adf_cleanup_accel(accel_dev); diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c index f8cc4bf0a50c..1bf753244230 100644 --- a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c +++ b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c @@ -270,9 +270,7 @@ static void adf_remove(struct pci_dev *pdev) pr_err("QAT: Driver removal failed\n"); return; } - if (adf_dev_stop(accel_dev)) - dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n"); - + adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); adf_cleanup_accel(accel_dev); adf_cleanup_pci_dev(accel_dev); -- GitLab From 043809d8d25eac8307c8c7b74bca7266070cb007 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 Apr 2016 11:04:28 +0900 Subject: [PATCH 1386/9938] hwrng: exynos - Fix misspelled Samsung address Correct smasung.com into samsung.com. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/char/hw_random/exynos-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c index ed78f25e4ec6..ed44561ea647 100644 --- a/drivers/char/hw_random/exynos-rng.c +++ b/drivers/char/hw_random/exynos-rng.c @@ -2,7 +2,7 @@ * exynos-rng.c - Random Number Generator driver for the exynos * * Copyright (C) 2012 Samsung Electronics - * Jonghwa Lee + * Jonghwa Lee * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- GitLab From 35b67291b4a85d37ec31f9d9ea3c5d3258ee0da6 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 4 Dec 2015 14:57:03 +0000 Subject: [PATCH 1387/9938] soc/tegra: pmc: Add missing structure members to kernel-doc Some members of the tegra_pmc structure are missing from the kernel-doc comment for this structure. Add the missing members. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index bc34cf7482fb..99ca91f09929 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -113,8 +113,10 @@ struct tegra_pmc_soc { /** * struct tegra_pmc - NVIDIA Tegra PMC + * @dev: pointer to PMC device structure * @base: pointer to I/O remapped register region * @clk: pointer to pclk clock + * @soc: pointer to SoC data structure * @rate: currently configured rate of pclk * @suspend_mode: lowest suspend mode available * @cpu_good_time: CPU power good time (in microseconds) -- GitLab From 1e52efdfc6a29f9bad767b92b89ae6ae772063cc Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 4 Dec 2015 14:57:04 +0000 Subject: [PATCH 1388/9938] soc/tegra: pmc: Fix sparse warning for tegra_pmc_init_tsense_reset() Sparse reports the following warning for tegra_pmc_init_tsense_reset(): drivers/soc/tegra/pmc.c:741:6: warning: symbol 'tegra_pmc_init_tsense_reset' was not declared. Should it be static? This function is only used internally by the PMC driver and so fix this by making it static. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 99ca91f09929..5b6125ecd69a 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -729,7 +729,7 @@ static void tegra_pmc_init(struct tegra_pmc *pmc) tegra_pmc_writel(value, PMC_CNTRL); } -void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) +static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) { static const char disabled[] = "emergency thermal reset disabled"; u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux; -- GitLab From 3195ac6d9cbeef23631913d67f8c1e76b891da4d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 4 Dec 2015 14:57:05 +0000 Subject: [PATCH 1389/9938] soc/tegra: pmc: Remove debugfs entry on probe failure The debugfs entry for the PMC device will not be removed if the probe of the device fails to register the restart handler. This leaves behind the dangling debugfs entry with no driver backing it. Remove the entry to avoid this. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 5b6125ecd69a..e60fc2d33c94 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -117,6 +117,7 @@ struct tegra_pmc_soc { * @base: pointer to I/O remapped register region * @clk: pointer to pclk clock * @soc: pointer to SoC data structure + * @debugfs: pointer to debugfs entry * @rate: currently configured rate of pclk * @suspend_mode: lowest suspend mode available * @cpu_good_time: CPU power good time (in microseconds) @@ -136,6 +137,7 @@ struct tegra_pmc { struct device *dev; void __iomem *base; struct clk *clk; + struct dentry *debugfs; const struct tegra_pmc_soc *soc; @@ -447,11 +449,9 @@ static const struct file_operations powergate_fops = { static int tegra_powergate_debugfs_init(void) { - struct dentry *d; - - d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL, - &powergate_fops); - if (!d) + pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL, + &powergate_fops); + if (!pmc->debugfs) return -ENOMEM; return 0; @@ -844,6 +844,7 @@ static int tegra_pmc_probe(struct platform_device *pdev) err = register_restart_handler(&tegra_pmc_restart_handler); if (err) { + debugfs_remove(pmc->debugfs); dev_err(&pdev->dev, "unable to register restart handler, %d\n", err); return err; -- GitLab From e8de5b81ff930a95f1a45e6feb3df278ee9850ae Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 4 Dec 2015 14:57:08 +0000 Subject: [PATCH 1390/9938] soc/tegra: pmc: Remove non-existing power partitions for Tegra210 The power partitions L2, HEG, CELP and C1NC do not exist on Tegra210 but were incorrectly documented in the TRM. These will be removed from the TRM and so also remove their definitions. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index e60fc2d33c94..88c7e506177e 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -1009,17 +1009,13 @@ static const char * const tegra210_powergates[] = { [TEGRA_POWERGATE_3D] = "3d", [TEGRA_POWERGATE_VENC] = "venc", [TEGRA_POWERGATE_PCIE] = "pcie", - [TEGRA_POWERGATE_L2] = "l2", [TEGRA_POWERGATE_MPE] = "mpe", - [TEGRA_POWERGATE_HEG] = "heg", [TEGRA_POWERGATE_SATA] = "sata", [TEGRA_POWERGATE_CPU1] = "cpu1", [TEGRA_POWERGATE_CPU2] = "cpu2", [TEGRA_POWERGATE_CPU3] = "cpu3", - [TEGRA_POWERGATE_CELP] = "celp", [TEGRA_POWERGATE_CPU0] = "cpu0", [TEGRA_POWERGATE_C0NC] = "c0nc", - [TEGRA_POWERGATE_C1NC] = "c1nc", [TEGRA_POWERGATE_SOR] = "sor", [TEGRA_POWERGATE_DIS] = "dis", [TEGRA_POWERGATE_DISB] = "disb", -- GitLab From 668419afe65c146e115897e8fef6ca23c48bf121 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 18:03:19 +0000 Subject: [PATCH 1391/9938] soc/tegra: pmc: Remove non-existing L2 partition for Tegra124 Tegra124 does not have an L2 power partition and the L2 cache is part of the cluster 0 non-CPU (CONC) partition. Remove the L2 as a valid partition for Tegra124. The TRM also shows that there is no L2 partition for Tegra124. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 88c7e506177e..922430322877 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -967,7 +967,6 @@ static const char * const tegra124_powergates[] = { [TEGRA_POWERGATE_VENC] = "venc", [TEGRA_POWERGATE_PCIE] = "pcie", [TEGRA_POWERGATE_VDEC] = "vdec", - [TEGRA_POWERGATE_L2] = "l2", [TEGRA_POWERGATE_MPE] = "mpe", [TEGRA_POWERGATE_HEG] = "heg", [TEGRA_POWERGATE_SATA] = "sata", -- GitLab From 0259f522e04f19b433a4dc7586d80da106afbbcc Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 18:03:20 +0000 Subject: [PATCH 1392/9938] soc/tegra: pmc: Restore base address on probe failure During early initialisation, the PMC registers are mapped and the PMC SoC data is populated in the PMC data structure. This allows other drivers access the PMC register space, via the public Tegra PMC APIs, prior to probing the PMC device. When the PMC device is probed, the PMC registers are mapped again and if successful the initial mapping is freed. If the probing of the PMC device fails after the registers are remapped, then the registers will be unmapped and hence the pointer to the PMC registers will be invalid. This could lead to a potential crash, because once the PMC SoC data pointer is populated, the driver assumes that the PMC register mapping is also valid and a user calling any of the public Tegra PMC APIs could trigger an exception because these APIs don't check that the mapping is still valid. Fix this by updating the mapping and freeing the original mapping only if probing the PMC device is successful. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 922430322877..900f72f0d757 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -807,7 +807,7 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) static int tegra_pmc_probe(struct platform_device *pdev) { - void __iomem *base = pmc->base; + void __iomem *base, *tmp; struct resource *res; int err; @@ -817,11 +817,9 @@ static int tegra_pmc_probe(struct platform_device *pdev) /* take over the memory region from the early initialization */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pmc->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pmc->base)) - return PTR_ERR(pmc->base); - - iounmap(base); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); pmc->clk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(pmc->clk)) { @@ -850,6 +848,10 @@ static int tegra_pmc_probe(struct platform_device *pdev) return err; } + tmp = pmc->base; + pmc->base = base; + iounmap(tmp); + return 0; } -- GitLab From e8cf6616a346029fe3e3931dd34fc589fade4b6e Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 18:03:21 +0000 Subject: [PATCH 1393/9938] soc/tegra: pmc: Protect public functions from potential race conditions The PMC base address pointer is initialised during early boot so that early platform code may used the PMC public functions. During the probe of the PMC driver the base address pointer is mapped again and the initial mapping is freed. This exposes a window where a device accessing the PMC registers via one of the public functions, could race with the updating of the pointer and lead to a invalid access. Furthermore, the only protection between multiple devices attempting to access the PMC registers is when setting the powergate state to on or off. None of the other public functions that access the PMC registers are protected. Use the existing mutex to protect paths that may race with regard to accessing the PMC registers. Note that functions tegra_io_rail_prepare()/poll() either return a negative value on failure or zero on success. Therefore, it is not necessary to check if the return value is less than zero and so only test that the return value is not zero to test for failure. This simplifies the error handling with the mutex locking in place. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 47 +++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 900f72f0d757..5449d1aa14e8 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -235,7 +235,10 @@ int tegra_powergate_is_powered(int id) if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates) return -EINVAL; + mutex_lock(&pmc->powergates_lock); status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id); + mutex_unlock(&pmc->powergates_lock); + return !!status; } @@ -250,6 +253,8 @@ int tegra_powergate_remove_clamping(int id) if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates) return -EINVAL; + mutex_lock(&pmc->powergates_lock); + /* * On Tegra124 and later, the clamps for the GPU are controlled by a * separate register (with different semantics). @@ -257,7 +262,7 @@ int tegra_powergate_remove_clamping(int id) if (id == TEGRA_POWERGATE_3D) { if (pmc->soc->has_gpu_clamps) { tegra_pmc_writel(0, GPU_RG_CNTRL); - return 0; + goto out; } } @@ -274,6 +279,9 @@ int tegra_powergate_remove_clamping(int id) tegra_pmc_writel(mask, REMOVE_CLAMPING); +out: + mutex_unlock(&pmc->powergates_lock); + return 0; } EXPORT_SYMBOL(tegra_powergate_remove_clamping); @@ -520,9 +528,11 @@ int tegra_io_rail_power_on(int id) unsigned int bit, mask; int err; + mutex_lock(&pmc->powergates_lock); + err = tegra_io_rail_prepare(id, &request, &status, &bit); - if (err < 0) - return err; + if (err) + goto error; mask = 1 << bit; @@ -533,14 +543,17 @@ int tegra_io_rail_power_on(int id) tegra_pmc_writel(value, request); err = tegra_io_rail_poll(status, mask, 0, 250); - if (err < 0) { + if (err) { pr_info("tegra_io_rail_poll() failed: %d\n", err); - return err; + goto error; } tegra_io_rail_unprepare(); - return 0; +error: + mutex_unlock(&pmc->powergates_lock); + + return err; } EXPORT_SYMBOL(tegra_io_rail_power_on); @@ -550,10 +563,12 @@ int tegra_io_rail_power_off(int id) unsigned int bit, mask; int err; + mutex_lock(&pmc->powergates_lock); + err = tegra_io_rail_prepare(id, &request, &status, &bit); - if (err < 0) { + if (err) { pr_info("tegra_io_rail_prepare() failed: %d\n", err); - return err; + goto error; } mask = 1 << bit; @@ -565,12 +580,15 @@ int tegra_io_rail_power_off(int id) tegra_pmc_writel(value, request); err = tegra_io_rail_poll(status, mask, mask, 250); - if (err < 0) - return err; + if (err) + goto error; tegra_io_rail_unprepare(); - return 0; +error: + mutex_unlock(&pmc->powergates_lock); + + return err; } EXPORT_SYMBOL(tegra_io_rail_power_off); @@ -807,7 +825,7 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) static int tegra_pmc_probe(struct platform_device *pdev) { - void __iomem *base, *tmp; + void __iomem *base; struct resource *res; int err; @@ -848,9 +866,10 @@ static int tegra_pmc_probe(struct platform_device *pdev) return err; } - tmp = pmc->base; + mutex_lock(&pmc->powergates_lock); + iounmap(pmc->base); pmc->base = base; - iounmap(tmp); + mutex_unlock(&pmc->powergates_lock); return 0; } -- GitLab From 70293ed09decd1ec4ae5632af27cab73c16a50ba Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 18:03:22 +0000 Subject: [PATCH 1394/9938] soc/tegra: pmc: Change powergate and rail IDs to be an unsigned type The Tegra powergate and rail IDs are always positive values and so change the type to be unsigned and remove the tests to see if the ID is less than zero. Update the Tegra DC powergate type to be an unsigned as well. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/drm.h | 2 +- drivers/soc/tegra/pmc.c | 36 ++++++++++++++++++------------------ include/soc/tegra/pmc.h | 35 ++++++++++++++++++----------------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 8a10f5b7d9dc..f52d6cb24ff5 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -121,7 +121,7 @@ struct tegra_dc { spinlock_t lock; struct drm_crtc base; - int powergate; + unsigned int powergate; int pipe; struct clk *clk; diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 5449d1aa14e8..5f32a3e34476 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -179,7 +179,7 @@ static void tegra_pmc_writel(u32 value, unsigned long offset) * @id: partition ID * @new_state: new state of the partition */ -static int tegra_powergate_set(int id, bool new_state) +static int tegra_powergate_set(unsigned int id, bool new_state) { bool status; @@ -203,9 +203,9 @@ static int tegra_powergate_set(int id, bool new_state) * tegra_powergate_power_on() - power on partition * @id: partition ID */ -int tegra_powergate_power_on(int id) +int tegra_powergate_power_on(unsigned int id) { - if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates) + if (!pmc->soc || id >= pmc->soc->num_powergates) return -EINVAL; return tegra_powergate_set(id, true); @@ -215,9 +215,9 @@ int tegra_powergate_power_on(int id) * tegra_powergate_power_off() - power off partition * @id: partition ID */ -int tegra_powergate_power_off(int id) +int tegra_powergate_power_off(unsigned int id) { - if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates) + if (!pmc->soc || id >= pmc->soc->num_powergates) return -EINVAL; return tegra_powergate_set(id, false); @@ -228,11 +228,11 @@ EXPORT_SYMBOL(tegra_powergate_power_off); * tegra_powergate_is_powered() - check if partition is powered * @id: partition ID */ -int tegra_powergate_is_powered(int id) +int tegra_powergate_is_powered(unsigned int id) { u32 status; - if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates) + if (!pmc->soc || id >= pmc->soc->num_powergates) return -EINVAL; mutex_lock(&pmc->powergates_lock); @@ -246,11 +246,11 @@ int tegra_powergate_is_powered(int id) * tegra_powergate_remove_clamping() - remove power clamps for partition * @id: partition ID */ -int tegra_powergate_remove_clamping(int id) +int tegra_powergate_remove_clamping(unsigned int id) { u32 mask; - if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates) + if (!pmc->soc || id >= pmc->soc->num_powergates) return -EINVAL; mutex_lock(&pmc->powergates_lock); @@ -294,7 +294,7 @@ EXPORT_SYMBOL(tegra_powergate_remove_clamping); * * Must be called with clk disabled, and returns with clk enabled. */ -int tegra_powergate_sequence_power_up(int id, struct clk *clk, +int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, struct reset_control *rst) { int ret; @@ -337,9 +337,9 @@ EXPORT_SYMBOL(tegra_powergate_sequence_power_up); * Returns the partition ID corresponding to the CPU partition ID or a * negative error code on failure. */ -static int tegra_get_cpu_powergate_id(int cpuid) +static int tegra_get_cpu_powergate_id(unsigned int cpuid) { - if (pmc->soc && cpuid > 0 && cpuid < pmc->soc->num_cpu_powergates) + if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates) return pmc->soc->cpu_powergates[cpuid]; return -EINVAL; @@ -349,7 +349,7 @@ static int tegra_get_cpu_powergate_id(int cpuid) * tegra_pmc_cpu_is_powered() - check if CPU partition is powered * @cpuid: CPU partition ID */ -bool tegra_pmc_cpu_is_powered(int cpuid) +bool tegra_pmc_cpu_is_powered(unsigned int cpuid) { int id; @@ -364,7 +364,7 @@ bool tegra_pmc_cpu_is_powered(int cpuid) * tegra_pmc_cpu_power_on() - power on CPU partition * @cpuid: CPU partition ID */ -int tegra_pmc_cpu_power_on(int cpuid) +int tegra_pmc_cpu_power_on(unsigned int cpuid) { int id; @@ -379,7 +379,7 @@ int tegra_pmc_cpu_power_on(int cpuid) * tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition * @cpuid: CPU partition ID */ -int tegra_pmc_cpu_remove_clamping(int cpuid) +int tegra_pmc_cpu_remove_clamping(unsigned int cpuid) { int id; @@ -465,7 +465,7 @@ static int tegra_powergate_debugfs_init(void) return 0; } -static int tegra_io_rail_prepare(int id, unsigned long *request, +static int tegra_io_rail_prepare(unsigned int id, unsigned long *request, unsigned long *status, unsigned int *bit) { unsigned long rate, value; @@ -522,7 +522,7 @@ static void tegra_io_rail_unprepare(void) tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE); } -int tegra_io_rail_power_on(int id) +int tegra_io_rail_power_on(unsigned int id) { unsigned long request, status, value; unsigned int bit, mask; @@ -557,7 +557,7 @@ int tegra_io_rail_power_on(int id) } EXPORT_SYMBOL(tegra_io_rail_power_on); -int tegra_io_rail_power_off(int id) +int tegra_io_rail_power_off(unsigned int id) { unsigned long request, status, value; unsigned int bit, mask; diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h index d18efe402ff1..07e332dd44fb 100644 --- a/include/soc/tegra/pmc.h +++ b/include/soc/tegra/pmc.h @@ -33,9 +33,9 @@ void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode); #endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_SMP -bool tegra_pmc_cpu_is_powered(int cpuid); -int tegra_pmc_cpu_power_on(int cpuid); -int tegra_pmc_cpu_remove_clamping(int cpuid); +bool tegra_pmc_cpu_is_powered(unsigned int cpuid); +int tegra_pmc_cpu_power_on(unsigned int cpuid); +int tegra_pmc_cpu_remove_clamping(unsigned int cpuid); #endif /* CONFIG_SMP */ /* @@ -108,50 +108,51 @@ int tegra_pmc_cpu_remove_clamping(int cpuid); #define TEGRA_IO_RAIL_SYS_DDC 58 #ifdef CONFIG_ARCH_TEGRA -int tegra_powergate_is_powered(int id); -int tegra_powergate_power_on(int id); -int tegra_powergate_power_off(int id); -int tegra_powergate_remove_clamping(int id); +int tegra_powergate_is_powered(unsigned int id); +int tegra_powergate_power_on(unsigned int id); +int tegra_powergate_power_off(unsigned int id); +int tegra_powergate_remove_clamping(unsigned int id); /* Must be called with clk disabled, and returns with clk enabled */ -int tegra_powergate_sequence_power_up(int id, struct clk *clk, +int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, struct reset_control *rst); -int tegra_io_rail_power_on(int id); -int tegra_io_rail_power_off(int id); +int tegra_io_rail_power_on(unsigned int id); +int tegra_io_rail_power_off(unsigned int id); #else -static inline int tegra_powergate_is_powered(int id) +static inline int tegra_powergate_is_powered(unsigned int id) { return -ENOSYS; } -static inline int tegra_powergate_power_on(int id) +static inline int tegra_powergate_power_on(unsigned int id) { return -ENOSYS; } -static inline int tegra_powergate_power_off(int id) +static inline int tegra_powergate_power_off(unsigned int id) { return -ENOSYS; } -static inline int tegra_powergate_remove_clamping(int id) +static inline int tegra_powergate_remove_clamping(unsigned int id) { return -ENOSYS; } -static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk, +static inline int tegra_powergate_sequence_power_up(unsigned int id, + struct clk *clk, struct reset_control *rst) { return -ENOSYS; } -static inline int tegra_io_rail_power_on(int id) +static inline int tegra_io_rail_power_on(unsigned int id) { return -ENOSYS; } -static inline int tegra_io_rail_power_off(int id) +static inline int tegra_io_rail_power_off(unsigned int id) { return -ENOSYS; } -- GitLab From 0ecf2d33bb4686b5d8f06b3b18877de0d88d3af4 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 18:03:23 +0000 Subject: [PATCH 1395/9938] soc/tegra: pmc: Fix testing of powergate state In tegra_powergate_set() the state of the powergates is read and OR'ed with the bit for the powergate of interest. This unsigned 32-bit value is then compared with a boolean value to test if the powergate is already in the desired state. When turning on a powergate, apart from the powergate that is represented by bit 0, this test will always return false and so we may attempt to turn on the powergate when it is already on. After OR'ing the bit for the powergate, check if the result is not equal to zero before comparing with the boolean value. Add a helper function to return the current state of a powergate and use this in both tegra_powergate_set() and tegra_powergate_is_powered() where we check the powergate status. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 5f32a3e34476..9e8d359baf0e 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -174,6 +174,11 @@ static void tegra_pmc_writel(u32 value, unsigned long offset) writel(value, pmc->base + offset); } +static inline bool tegra_powergate_state(int id) +{ + return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0; +} + /** * tegra_powergate_set() - set the state of a partition * @id: partition ID @@ -181,13 +186,9 @@ static void tegra_pmc_writel(u32 value, unsigned long offset) */ static int tegra_powergate_set(unsigned int id, bool new_state) { - bool status; - mutex_lock(&pmc->powergates_lock); - status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id); - - if (status == new_state) { + if (tegra_powergate_state(id) == new_state) { mutex_unlock(&pmc->powergates_lock); return 0; } @@ -230,16 +231,16 @@ EXPORT_SYMBOL(tegra_powergate_power_off); */ int tegra_powergate_is_powered(unsigned int id) { - u32 status; + int status; if (!pmc->soc || id >= pmc->soc->num_powergates) return -EINVAL; mutex_lock(&pmc->powergates_lock); - status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id); + status = tegra_powergate_state(id); mutex_unlock(&pmc->powergates_lock); - return !!status; + return status; } /** -- GitLab From 0a243bd438ce3d44e03140adf58df4df11dce978 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 18:03:24 +0000 Subject: [PATCH 1396/9938] soc/tegra: pmc: Fix verification of valid partitions The Tegra power partitions are referenced by numerical IDs which are the same values programmed into the PMC registers for controlling the partition. For a given device, the valid partition IDs may not be contiguous and so simply checking that an ID is not greater than the maximum ID supported may not mean it is valid. Fix this by checking if the powergate is defined in the list of powergates for the Tegra SoC. Add a helper function for checking valid powergates and use where we need to verify if the powergate ID is valid or not. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 9e8d359baf0e..e75782b47267 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -179,6 +179,11 @@ static inline bool tegra_powergate_state(int id) return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0; } +static inline bool tegra_powergate_is_valid(int id) +{ + return (pmc->soc && pmc->soc->powergates[id]); +} + /** * tegra_powergate_set() - set the state of a partition * @id: partition ID @@ -206,7 +211,7 @@ static int tegra_powergate_set(unsigned int id, bool new_state) */ int tegra_powergate_power_on(unsigned int id) { - if (!pmc->soc || id >= pmc->soc->num_powergates) + if (!tegra_powergate_is_valid(id)) return -EINVAL; return tegra_powergate_set(id, true); @@ -218,7 +223,7 @@ int tegra_powergate_power_on(unsigned int id) */ int tegra_powergate_power_off(unsigned int id) { - if (!pmc->soc || id >= pmc->soc->num_powergates) + if (!tegra_powergate_is_valid(id)) return -EINVAL; return tegra_powergate_set(id, false); @@ -233,7 +238,7 @@ int tegra_powergate_is_powered(unsigned int id) { int status; - if (!pmc->soc || id >= pmc->soc->num_powergates) + if (!tegra_powergate_is_valid(id)) return -EINVAL; mutex_lock(&pmc->powergates_lock); @@ -251,7 +256,7 @@ int tegra_powergate_remove_clamping(unsigned int id) { u32 mask; - if (!pmc->soc || id >= pmc->soc->num_powergates) + if (!tegra_powergate_is_valid(id)) return -EINVAL; mutex_lock(&pmc->powergates_lock); -- GitLab From c3ea297260b77a99a2383c1029a381d125f788fe Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 18:03:25 +0000 Subject: [PATCH 1397/9938] soc/tegra: pmc: Remove additional check for a valid partition The function tegra_powergate_is_powered() verifies that the partition being queried is valid and so there is no need to check this before calling tegra_powergate_is_powered() in powergate_show(). So remove this extra check. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index e75782b47267..8e358dbffaed 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -434,16 +434,18 @@ static struct notifier_block tegra_pmc_restart_handler = { static int powergate_show(struct seq_file *s, void *data) { unsigned int i; + int status; seq_printf(s, " powergate powered\n"); seq_printf(s, "------------------\n"); for (i = 0; i < pmc->soc->num_powergates; i++) { - if (!pmc->soc->powergates[i]) + status = tegra_powergate_is_powered(i); + if (status < 0) continue; seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i], - tegra_powergate_is_powered(i) ? "yes" : "no"); + status ? "yes" : "no"); } return 0; -- GitLab From bc9af23d314f5c846e66e9425b31df2815ef1763 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 15 Feb 2016 12:38:11 +0000 Subject: [PATCH 1398/9938] soc/tegra: pmc: Ensure GPU partition can be toggled on/off by PMC For Tegra124 and Tegra210, the GPU partition cannot be toggled on and off via the APBDEV_PMC_PWRGATE_TOGGLE_0 register. For these devices, the partition is simply powered up and down via an external regulator. For these devices, there is a separate register for controlling the signal clamping of the partition and this is described in the PMC SoC data by the "has_gpu_clamp" variable. Use this variable to determine if the GPU partition can be controlled via the APBDEV_PMC_PWRGATE_TOGGLE_0 register and ensure that no one can incorrectly try to toggle the GPU partition via the APBDEV_PMC_PWRGATE_TOGGLE_0 register. Furthermore, we cannot use the APBDEV_PMC_PWRGATE_STATUS_0 register to determine if the GPU partition is powered for Tegra124 and Tegra210. However, if the GPU partition is powered, then the signal clamp for the GPU partition should be removed and so use bit 0 of the APBDEV_PMC_GPU_RG_CNTRL_0 register to determine if the clamp has been removed (bit[0] = 0) and the GPU partition is powered. Signed-off-by: Jon Hunter Reviewed-by: Mathieu Poirier Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 8e358dbffaed..e4fd40fa27e8 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -176,7 +176,10 @@ static void tegra_pmc_writel(u32 value, unsigned long offset) static inline bool tegra_powergate_state(int id) { - return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0; + if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps) + return (tegra_pmc_readl(GPU_RG_CNTRL) & 0x1) == 0; + else + return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0; } static inline bool tegra_powergate_is_valid(int id) @@ -191,6 +194,9 @@ static inline bool tegra_powergate_is_valid(int id) */ static int tegra_powergate_set(unsigned int id, bool new_state) { + if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps) + return -EINVAL; + mutex_lock(&pmc->powergates_lock); if (tegra_powergate_state(id) == new_state) { -- GitLab From 0a2d87e0473fc5eea3f8168f5a24a35e4cf3f29c Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Feb 2016 15:48:40 +0000 Subject: [PATCH 1399/9938] soc/tegra: pmc: Wait for powergate state to change Currently, the function tegra_powergate_set() simply sets the desired powergate state but does not wait for the state to change. In most cases we should wait for the state to change before proceeding. Currently, there is a case for Tegra114 and Tegra124 devices where we do not wait when starting the secondary CPU as this is not necessary. However, this is only done at boot time and so waiting here will only have a small impact on boot time. Therefore, update tegra_powergate_set() to wait when setting the powergate. By adding this feature, we can also eliminate the polling loop from tegra30_boot_secondary(). A function has been added for checking the status of the powergate and so update the tegra_powergate_is_powered() to use this macro as well. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- arch/arm/mach-tegra/platsmp.c | 16 +++------------- drivers/soc/tegra/pmc.c | 9 ++++++++- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index f3f61dbbda97..75620ae73913 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -108,19 +108,9 @@ static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle) * be un-gated by un-toggling the power gate register * manually. */ - if (!tegra_pmc_cpu_is_powered(cpu)) { - ret = tegra_pmc_cpu_power_on(cpu); - if (ret) - return ret; - - /* Wait for the power to come up. */ - timeout = jiffies + msecs_to_jiffies(100); - while (!tegra_pmc_cpu_is_powered(cpu)) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - udelay(10); - } - } + ret = tegra_pmc_cpu_power_on(cpu); + if (ret) + return ret; remove_clamps: /* CPU partition is powered. Enable the CPU clock. */ diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index e4fd40fa27e8..08966c26d65c 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -194,6 +195,9 @@ static inline bool tegra_powergate_is_valid(int id) */ static int tegra_powergate_set(unsigned int id, bool new_state) { + bool status; + int err; + if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps) return -EINVAL; @@ -206,9 +210,12 @@ static int tegra_powergate_set(unsigned int id, bool new_state) tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); + err = readx_poll_timeout(tegra_powergate_state, id, status, + status == new_state, 10, 100000); + mutex_unlock(&pmc->powergates_lock); - return 0; + return err; } /** -- GitLab From 605aa5e48bfc3dbf0272bc4aac8674e06c19c1b3 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 26 Feb 2016 15:48:38 +0000 Subject: [PATCH 1400/9938] dt-bindings: Update NVIDIA PMC for Tegra Add the PMC driver compatible strings for Tegra132 and Tegra210. Signed-off-by: Jon Hunter Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt index 02c27004d4a8..53aa5496c5cf 100644 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt @@ -6,11 +6,13 @@ modes. It provides power-gating controllers for SoC and CPU power-islands. Required properties: - name : Should be pmc -- compatible : For Tegra20, must contain "nvidia,tegra20-pmc". For Tegra30, - must contain "nvidia,tegra30-pmc". For Tegra114, must contain - "nvidia,tegra114-pmc". For Tegra124, must contain "nvidia,tegra124-pmc". - Otherwise, must contain "nvidia,-pmc", plus at least one of the - above, where is tegra132. +- compatible : Should contain one of the following: + For Tegra20 must contain "nvidia,tegra20-pmc". + For Tegra30 must contain "nvidia,tegra30-pmc". + For Tegra114 must contain "nvidia,tegra114-pmc" + For Tegra124 must contain "nvidia,tegra124-pmc" + For Tegra132 must contain "nvidia,tegra124-pmc" + For Tegra210 must contain "nvidia,tegra210-pmc" - reg : Offset and length of the register set for the device - clocks : Must contain an entry for each entry in clock-names. See ../clocks/clock-bindings.txt for details. -- GitLab From 54c6d242fa32cba8313936e3a35f27dc2c7c3e04 Mon Sep 17 00:00:00 2001 From: Cosmin-Gabriel Samoila Date: Sun, 13 Mar 2016 02:17:27 +0200 Subject: [PATCH 1401/9938] iommu/io-pgtable: Fix a brace coding style issue. Fixed a coding style issue. Signed-off-by: Cosmin-Gabriel Samoila Signed-off-by: Joerg Roedel --- drivers/iommu/io-pgtable.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c index 876f6a76d288..127558d83667 100644 --- a/drivers/iommu/io-pgtable.c +++ b/drivers/iommu/io-pgtable.c @@ -25,8 +25,7 @@ #include "io-pgtable.h" static const struct io_pgtable_init_fns * -io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = -{ +io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = { #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE [ARM_32_LPAE_S1] = &io_pgtable_arm_32_lpae_s1_init_fns, [ARM_32_LPAE_S2] = &io_pgtable_arm_32_lpae_s2_init_fns, -- GitLab From 1afe23194d0580bc332fe27c4e8717f6562348c5 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Mon, 14 Mar 2016 06:01:10 +0800 Subject: [PATCH 1402/9938] iommu/io-pgtable: Add MTK 4GB mode in Short-descriptor In MT8173, Normally the first 1GB PA is for the HW SRAM and Regs, so the PA will be 33bits if the dram size is 4GB. We have a "DRAM 4GB mode" toggle bit for this. If it's enabled, from CPU's point of view, the dram PA will be from 0x1_00000000~0x1_ffffffff. In short descriptor, the pagetable descriptor is always 32bit. Mediatek extend bit9 in the lvl1 and lvl2 pgtable descriptor as the 4GB mode. In the 4GB mode, the bit9 must be set, then M4U help add 0x1_00000000 based on the PA in pagetable. Thus the M4U output address to EMI is always 33bits(the input address is still 32bits). We add a special quirk for this MTK-4GB mode. And in the standard spec, Bit9 in the lvl1 is "IMPLEMENTATION DEFINED", while it's AP[2] in the lvl2, therefore if this quirk is enabled, NO_PERMS is also expected. Signed-off-by: Yong Wu Reviewed-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/io-pgtable-arm-v7s.c | 13 ++++++++++++- drivers/iommu/io-pgtable.h | 6 ++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 9488e3c97bcb..0f93dc2f98a3 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -121,6 +121,8 @@ #define ARM_V7S_TEX_MASK 0x7 #define ARM_V7S_ATTR_TEX(val) (((val) & ARM_V7S_TEX_MASK) << ARM_V7S_TEX_SHIFT) +#define ARM_V7S_ATTR_MTK_4GB BIT(9) /* MTK extend it for 4GB mode */ + /* *well, except for TEX on level 2 large pages, of course :( */ #define ARM_V7S_CONT_PAGE_TEX_SHIFT 6 #define ARM_V7S_CONT_PAGE_TEX_MASK (ARM_V7S_TEX_MASK << ARM_V7S_CONT_PAGE_TEX_SHIFT) @@ -364,6 +366,9 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data, if (lvl == 1 && (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS)) pte |= ARM_V7S_ATTR_NS_SECTION; + if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) + pte |= ARM_V7S_ATTR_MTK_4GB; + if (num_entries > 1) pte = arm_v7s_pte_to_cont(pte, lvl); @@ -625,9 +630,15 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg, if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS | IO_PGTABLE_QUIRK_NO_PERMS | - IO_PGTABLE_QUIRK_TLBI_ON_MAP)) + IO_PGTABLE_QUIRK_TLBI_ON_MAP | + IO_PGTABLE_QUIRK_ARM_MTK_4GB)) return NULL; + /* If ARM_MTK_4GB is enabled, the NO_PERMS is also expected. */ + if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB && + !(cfg->quirks & IO_PGTABLE_QUIRK_NO_PERMS)) + return NULL; + data = kmalloc(sizeof(*data), GFP_KERNEL); if (!data) return NULL; diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h index d4f502742e3b..969d82cc92ca 100644 --- a/drivers/iommu/io-pgtable.h +++ b/drivers/iommu/io-pgtable.h @@ -60,10 +60,16 @@ struct io_pgtable_cfg { * IO_PGTABLE_QUIRK_TLBI_ON_MAP: If the format forbids caching invalid * (unmapped) entries but the hardware might do so anyway, perform * TLB maintenance when mapping as well as when unmapping. + * + * IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all + * PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit + * when the SoC is in "4GB mode" and they can only access the high + * remap of DRAM (0x1_00000000 to 0x1_ffffffff). */ #define IO_PGTABLE_QUIRK_ARM_NS BIT(0) #define IO_PGTABLE_QUIRK_NO_PERMS BIT(1) #define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2) + #define IO_PGTABLE_QUIRK_ARM_MTK_4GB BIT(3) unsigned long quirks; unsigned long pgsize_bitmap; unsigned int ias; -- GitLab From 01e23c93868884327828a01e864135f05e515ae5 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Mon, 14 Mar 2016 06:01:11 +0800 Subject: [PATCH 1403/9938] iommu/mediatek: Add 4GB mode support This patch add 4GB mode support for m4u. Signed-off-by: Yong Wu Signed-off-by: Joerg Roedel --- drivers/iommu/mtk_iommu.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 929a66a81b2b..db745533ea92 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -11,6 +11,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#include #include #include #include @@ -56,7 +57,7 @@ #define F_MMU_TF_PROTECT_SEL(prot) (((prot) & 0x3) << 5) #define REG_MMU_IVRP_PADDR 0x114 -#define F_MMU_IVRP_PA_SET(pa) ((pa) >> 1) +#define F_MMU_IVRP_PA_SET(pa, ext) (((pa) >> 1) | ((!!(ext)) << 31)) #define REG_MMU_INT_CONTROL0 0x120 #define F_L2_MULIT_HIT_EN BIT(0) @@ -125,6 +126,7 @@ struct mtk_iommu_data { struct mtk_iommu_domain *m4u_dom; struct iommu_group *m4u_group; struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */ + bool enable_4GB; }; static struct iommu_ops mtk_iommu_ops; @@ -257,6 +259,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) .iommu_dev = data->dev, }; + if (data->enable_4GB) + dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_4GB; + dom->iop = alloc_io_pgtable_ops(ARM_V7S, &dom->cfg, data); if (!dom->iop) { dev_err(data->dev, "Failed to alloc io pgtable\n"); @@ -530,7 +535,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) F_INT_PRETETCH_TRANSATION_FIFO_FAULT; writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL); - writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base), + writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB), data->base + REG_MMU_IVRP_PADDR); writel_relaxed(0, data->base + REG_MMU_DCM_DIS); @@ -591,6 +596,9 @@ static int mtk_iommu_probe(struct platform_device *pdev) return -ENOMEM; data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN); + /* Whether the current dram is over 4GB */ + data->enable_4GB = !!(max_pfn > (0xffffffffUL >> PAGE_SHIFT)); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); data->base = devm_ioremap_resource(dev, res); if (IS_ERR(data->base)) @@ -690,7 +698,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev) writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG); writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0); writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL); - writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base), + writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB), base + REG_MMU_IVRP_PADDR); return 0; } -- GitLab From c43fce4eebae257ca413733690e2076757282093 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 17 Mar 2016 14:12:25 -0600 Subject: [PATCH 1404/9938] iommu/vt-d: Ratelimit fault handler Fault rates can easily overwhelm the console and make the system unresponsive. Ratelimit to allow an opportunity for maintenance. Signed-off-by: Alex Williamson Fixes: 0ac2491f57af ('x86, dmar: move page fault handling code to dmar.c') Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 8ffd7568fc91..8f8bfffbf1e6 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1602,10 +1602,17 @@ irqreturn_t dmar_fault(int irq, void *dev_id) int reg, fault_index; u32 fault_status; unsigned long flag; + bool ratelimited; + static DEFINE_RATELIMIT_STATE(rs, + DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + + /* Disable printing, simply clear the fault when ratelimited */ + ratelimited = !__ratelimit(&rs); raw_spin_lock_irqsave(&iommu->register_lock, flag); fault_status = readl(iommu->reg + DMAR_FSTS_REG); - if (fault_status) + if (fault_status && !ratelimited) pr_err("DRHD: handling fault status reg %x\n", fault_status); /* TBD: ignore advanced fault log currently */ @@ -1627,24 +1634,28 @@ irqreturn_t dmar_fault(int irq, void *dev_id) if (!(data & DMA_FRCD_F)) break; - fault_reason = dma_frcd_fault_reason(data); - type = dma_frcd_type(data); + if (!ratelimited) { + fault_reason = dma_frcd_fault_reason(data); + type = dma_frcd_type(data); - data = readl(iommu->reg + reg + - fault_index * PRIMARY_FAULT_REG_LEN + 8); - source_id = dma_frcd_source_id(data); + data = readl(iommu->reg + reg + + fault_index * PRIMARY_FAULT_REG_LEN + 8); + source_id = dma_frcd_source_id(data); + + guest_addr = dmar_readq(iommu->reg + reg + + fault_index * PRIMARY_FAULT_REG_LEN); + guest_addr = dma_frcd_page_addr(guest_addr); + } - guest_addr = dmar_readq(iommu->reg + reg + - fault_index * PRIMARY_FAULT_REG_LEN); - guest_addr = dma_frcd_page_addr(guest_addr); /* clear the fault */ writel(DMA_FRCD_F, iommu->reg + reg + fault_index * PRIMARY_FAULT_REG_LEN + 12); raw_spin_unlock_irqrestore(&iommu->register_lock, flag); - dmar_fault_do_one(iommu, type, fault_reason, - source_id, guest_addr); + if (!ratelimited) + dmar_fault_do_one(iommu, type, fault_reason, + source_id, guest_addr); fault_index++; if (fault_index >= cap_num_fault_regs(iommu->cap)) -- GitLab From a0fe14d7dcf5db2f101b4fe8689ecabb255ab7d3 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 17 Mar 2016 14:12:31 -0600 Subject: [PATCH 1405/9938] iommu/vt-d: Improve fault handler error messages Remove new line in error logs, avoid duplicate and explicit pr_fmt. Suggested-by: Joe Perches Signed-off-by: Alex Williamson Fixes: 0ac2491f57af ('x86, dmar: move page fault handling code to dmar.c') Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 8f8bfffbf1e6..6a86b5d1defa 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1579,18 +1579,14 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type, reason = dmar_get_fault_reason(fault_reason, &fault_type); if (fault_type == INTR_REMAP) - pr_err("INTR-REMAP: Request device [[%02x:%02x.%d] " - "fault index %llx\n" - "INTR-REMAP:[fault reason %02d] %s\n", - (source_id >> 8), PCI_SLOT(source_id & 0xFF), + pr_err("[INTR-REMAP] Request device [%02x:%02x.%d] fault index %llx [fault reason %02d] %s\n", + source_id >> 8, PCI_SLOT(source_id & 0xFF), PCI_FUNC(source_id & 0xFF), addr >> 48, fault_reason, reason); else - pr_err("DMAR:[%s] Request device [%02x:%02x.%d] " - "fault addr %llx \n" - "DMAR:[fault reason %02d] %s\n", - (type ? "DMA Read" : "DMA Write"), - (source_id >> 8), PCI_SLOT(source_id & 0xFF), + pr_err("[%s] Request device [%02x:%02x.%d] fault addr %llx [fault reason %02d] %s\n", + type ? "DMA Read" : "DMA Write", + source_id >> 8, PCI_SLOT(source_id & 0xFF), PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason); return 0; } -- GitLab From 8d7f2d84ed2d44b05e1ce88fa4b74886af46a139 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Mon, 21 Mar 2016 12:00:23 +0100 Subject: [PATCH 1406/9938] iommu/rockchip: Don't feed NULL res pointers to devres If we do, devres prints a "invalid resource" string in the error loglevel. Signed-off-by: Tomeu Vizoso Reviewed-by: Javier Martinez Canillas Signed-off-by: Joerg Roedel --- drivers/iommu/rockchip-iommu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index a6f593a0a29e..0253ab35c33b 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1049,6 +1049,8 @@ static int rk_iommu_probe(struct platform_device *pdev) for (i = 0; i < pdev->num_resources; i++) { res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + continue; iommu->bases[i] = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(iommu->bases[i])) continue; -- GitLab From c663e5f56737757db4d0b317c510ab505f93cecb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 22 Mar 2016 10:51:16 +0100 Subject: [PATCH 1407/9938] gpio: support native single-ended hardware drivers Some GPIO controllers has a special hardware bit we can flip to support open drain / source. This means that on these hardwares we do not need to emulate OD/OS by setting the line to input instead of actively driving it high/low. Add an optional vtable callback to the driver set_single_ended() so that driver can implement this in hardware if they have it. We may need a pinctrl_gpio_set_config() call at some point to propagate this down to a backing pin control device on systems with split GPIO/pin control. Reported-by: Michael Hennerich Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 52 ++++++++++++++++++++++++++----------- include/linux/gpio/driver.h | 25 +++++++++++++++++- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 72065532c1c7..1edc830a1b51 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1509,8 +1509,8 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input); static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) { - struct gpio_chip *chip; - int status = -EINVAL; + struct gpio_chip *gc = desc->gdev->chip; + int ret; /* GPIOs used for IRQs shall not be set as output */ if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { @@ -1520,28 +1520,50 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) return -EIO; } - /* Open drain pin should not be driven to 1 */ - if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) - return gpiod_direction_input(desc); - - /* Open source pin should not be driven to 0 */ - if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) - return gpiod_direction_input(desc); + if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { + /* First see if we can enable open drain in hardware */ + if (gc->set_single_ended) { + ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), + LINE_MODE_OPEN_DRAIN); + if (!ret) + goto set_output_value; + } + /* Emulate open drain by not actively driving the line high */ + if (value) + return gpiod_direction_input(desc); + } + else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { + if (gc->set_single_ended) { + ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), + LINE_MODE_OPEN_SOURCE); + if (!ret) + goto set_output_value; + } + /* Emulate open source by not actively driving the line low */ + if (!value) + return gpiod_direction_input(desc); + } else { + /* Make sure to disable open drain/source hardware, if any */ + if (gc->set_single_ended) + gc->set_single_ended(gc, + gpio_chip_hwgpio(desc), + LINE_MODE_PUSH_PULL); + } - chip = desc->gdev->chip; - if (!chip->set || !chip->direction_output) { +set_output_value: + if (!gc->set || !gc->direction_output) { gpiod_warn(desc, "%s: missing set() or direction_output() operations\n", __func__); return -EIO; } - status = chip->direction_output(chip, gpio_chip_hwgpio(desc), value); - if (status == 0) + ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), value); + if (!ret) set_bit(FLAG_IS_OUT, &desc->flags); trace_gpio_value(desc_to_gpio(desc), 0, value); - trace_gpio_direction(desc_to_gpio(desc), 0, status); - return status; + trace_gpio_direction(desc_to_gpio(desc), 0, ret); + return ret; } /** diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index bee976f82788..50882e09289b 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -19,6 +19,18 @@ struct gpio_device; #ifdef CONFIG_GPIOLIB +/** + * enum single_ended_mode - mode for single ended operation + * @LINE_MODE_PUSH_PULL: normal mode for a GPIO line, drive actively high/low + * @LINE_MODE_OPEN_DRAIN: set line to be open drain + * @LINE_MODE_OPEN_SOURCE: set line to be open source + */ +enum single_ended_mode { + LINE_MODE_PUSH_PULL, + LINE_MODE_OPEN_DRAIN, + LINE_MODE_OPEN_SOURCE, +}; + /** * struct gpio_chip - abstract a GPIO controller * @label: a functional name for the GPIO device, such as a part @@ -38,7 +50,15 @@ struct gpio_device; * @set: assigns output value for signal "offset" * @set_multiple: assigns output values for multiple signals defined by "mask" * @set_debounce: optional hook for setting debounce time for specified gpio in - * interrupt triggered gpio chips + * interrupt triggered gpio chips + * @set_single_ended: optional hook for setting a line as open drain, open + * source, or non-single ended (restore from open drain/source to normal + * push-pull mode) this should be implemented if the hardware supports + * open drain or open source settings. The GPIOlib will otherwise try + * to emulate open drain/source by not actively driving lines high/low + * if a consumer request this. The driver may return -ENOTSUPP if e.g. + * it supports just open drain but not open source and is called + * with LINE_MODE_OPEN_SOURCE as mode argument. * @to_irq: optional hook supporting non-static gpio_to_irq() mappings; * implementation may not sleep * @dbg_show: optional routine to show contents in debugfs; default code @@ -130,6 +150,9 @@ struct gpio_chip { int (*set_debounce)(struct gpio_chip *chip, unsigned offset, unsigned debounce); + int (*set_single_ended)(struct gpio_chip *chip, + unsigned offset, + enum single_ended_mode mode); int (*to_irq)(struct gpio_chip *chip, unsigned offset); -- GitLab From cee1b40d96f1b49e9a1b38e2d57d37a2c20ced31 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 5 Apr 2016 15:09:09 +0200 Subject: [PATCH 1408/9938] gpio: tc3589x: use BIT() macro This switch to use BIT(n) instead of (1 << n) which is less to the point. Most GPIO drivers do this to avoid mistakes. Also switch from using to the apropriate include. Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tc3589x.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 4f566e6b81f1..2845653f394a 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -10,10 +10,11 @@ #include #include #include -#include +#include #include #include #include +#include /* * These registers are modified under the irq bus lock and cached to avoid @@ -39,7 +40,7 @@ static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; - u8 mask = 1 << (offset % 8); + u8 mask = BIT(offset % 8); int ret; ret = tc3589x_reg_read(tc3589x, reg); @@ -55,7 +56,7 @@ static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val) struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; unsigned pos = offset % 8; - u8 data[] = {!!val << pos, 1 << pos}; + u8 data[] = {val ? BIT(pos) : 0, BIT(pos)}; tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); } @@ -70,7 +71,7 @@ static int tc3589x_gpio_direction_output(struct gpio_chip *chip, tc3589x_gpio_set(chip, offset, val); - return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos); + return tc3589x_set_bits(tc3589x, reg, BIT(pos), BIT(pos)); } static int tc3589x_gpio_direction_input(struct gpio_chip *chip, @@ -81,7 +82,7 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip, u8 reg = TC3589x_GPIODIR0 + offset / 8; unsigned pos = offset % 8; - return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); + return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0); } static struct gpio_chip template_chip = { @@ -100,7 +101,7 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc); int offset = d->hwirq; int regoffset = offset / 8; - int mask = 1 << (offset % 8); + int mask = BIT(offset % 8); if (type == IRQ_TYPE_EDGE_BOTH) { tc3589x_gpio->regs[REG_IBE][regoffset] |= mask; @@ -165,7 +166,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc); int offset = d->hwirq; int regoffset = offset / 8; - int mask = 1 << (offset % 8); + int mask = BIT(offset % 8); tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; } @@ -176,7 +177,7 @@ static void tc3589x_gpio_irq_unmask(struct irq_data *d) struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc); int offset = d->hwirq; int regoffset = offset / 8; - int mask = 1 << (offset % 8); + int mask = BIT(offset % 8); tc3589x_gpio->regs[REG_IE][regoffset] |= mask; } -- GitLab From 3d1a2442d2c08c872150db7a554647c06f6e864f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 23 Mar 2016 20:34:19 +0200 Subject: [PATCH 1409/9938] x86/vt-d: Fix comment for dma_pte_free_pagetable() dma_pte_free_pagetable no longer depends on last level ptes being clear, it clears them itself. Fix up the comment to match. Cc: Jiang Liu Suggested-by: Alex Williamson Signed-off-by: Michael S. Tsirkin Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a2e1b7f14df2..01005531891b 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1143,7 +1143,7 @@ static void dma_pte_free_level(struct dmar_domain *domain, int level, } while (!first_pte_in_page(++pte) && pfn <= last_pfn); } -/* free page table pages. last level pte should already be cleared */ +/* clear last level (leaf) ptes and free page table pages. */ static void dma_pte_free_pagetable(struct dmar_domain *domain, unsigned long start_pfn, unsigned long last_pfn) -- GitLab From 8b866b0682c5de249afed3f7cb23c8421bc735b0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 5 Apr 2016 15:11:11 +0200 Subject: [PATCH 1410/9938] gpio: tc3589x: implement open drain/source callback This makes use of the new .set_single_ended() callback to set the GPIO line as open drain/open source using hardware. The TC3589x can do this by either disabling the N-MOS transistor (open drain) or the P-MOS transistor (open source) of the output driver stage, in the first case making the signal drive actively low and high impedance as "high" and in the second case actively high and high impedance, which is as close to native open drain support as we come. Cc: Michael Hennerich Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tc3589x.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 2845653f394a..15552fdadcba 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -85,6 +85,46 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip, return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0); } +static int tc3589x_gpio_single_ended(struct gpio_chip *chip, + unsigned offset, + enum single_ended_mode mode) +{ + struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + /* + * These registers are alterated at each second address + * ODM bit 0 = drive to GND or Hi-Z (open drain) + * ODM bit 1 = drive to VDD or Hi-Z (open source) + */ + u8 odmreg = TC3589x_GPIOODM0 + (offset / 8) * 2; + u8 odereg = TC3589x_GPIOODE0 + (offset / 8) * 2; + unsigned pos = offset % 8; + int ret; + + switch(mode) { + case LINE_MODE_OPEN_DRAIN: + /* Set open drain mode */ + ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0); + if (ret) + return ret; + /* Enable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); + case LINE_MODE_OPEN_SOURCE: + /* Set open source mode */ + ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos)); + if (ret) + return ret; + /* Enable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); + case LINE_MODE_PUSH_PULL: + /* Disable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0); + default: + break; + } + return -ENOTSUPP; +} + static struct gpio_chip template_chip = { .label = "tc3589x", .owner = THIS_MODULE, @@ -92,6 +132,7 @@ static struct gpio_chip template_chip = { .get = tc3589x_gpio_get, .direction_output = tc3589x_gpio_direction_output, .set = tc3589x_gpio_set, + .set_single_ended = tc3589x_gpio_single_ended, .can_sleep = true, }; -- GitLab From fe7b778802593ccb1cae859553be912a2a1ef412 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:33 -0400 Subject: [PATCH 1411/9938] gpio: rc5t583: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_RC5T583 drivers/gpio/Kconfig: bool "RICOH RC5T583 GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Laxman Dewangan Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rc5t583.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index 1d6100fa312a..3b4dc1a9a68d 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -152,14 +151,3 @@ static int __init rc5t583_gpio_init(void) return platform_driver_register(&rc5t583_gpio_driver); } subsys_initcall(rc5t583_gpio_init); - -static void __exit rc5t583_gpio_exit(void) -{ - platform_driver_unregister(&rc5t583_gpio_driver); -} -module_exit(rc5t583_gpio_exit); - -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_DESCRIPTION("GPIO interface for RC5T583"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:rc5t583-gpio"); -- GitLab From 8513334115c818ef2bddbca5d2e6dd52c994ce19 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:34 -0400 Subject: [PATCH 1412/9938] gpio: tc3589x: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_TC3589X drivers/gpio/Kconfig: bool "TC3589X GPIOs" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Rabin Vincent Cc: Hanumath Prasad Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tc3589x.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 15552fdadcba..2e35ed3abbcf 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -6,7 +6,6 @@ * Author: Rabin Vincent for ST-Ericsson */ -#include #include #include #include @@ -353,13 +352,3 @@ static int __init tc3589x_gpio_init(void) return platform_driver_register(&tc3589x_gpio_driver); } subsys_initcall(tc3589x_gpio_init); - -static void __exit tc3589x_gpio_exit(void) -{ - platform_driver_unregister(&tc3589x_gpio_driver); -} -module_exit(tc3589x_gpio_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("TC3589x GPIO driver"); -MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); -- GitLab From 24a876cef408eae8bad4f7d74f38dc1a2d919bcc Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:35 -0400 Subject: [PATCH 1413/9938] gpio: sx150x: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_SX150X drivers/gpio/Kconfig: bool "Semtech SX150x I2C GPIO expander" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Gregory Bean Cc: Linus Walleij Cc: Alexandre Courbot Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sx150x.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d387eb524bf3..d57e8ad0bfd2 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -1,4 +1,8 @@ /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * Driver for Semtech SX150X I2C GPIO Expanders + * + * Author: Gregory Bean * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -718,13 +721,3 @@ static int __init sx150x_init(void) return i2c_add_driver(&sx150x_driver); } subsys_initcall(sx150x_init); - -static void __exit sx150x_exit(void) -{ - return i2c_del_driver(&sx150x_driver); -} -module_exit(sx150x_exit); - -MODULE_AUTHOR("Gregory Bean "); -MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders"); -MODULE_LICENSE("GPL v2"); -- GitLab From f9f2b5cba71e51998e60b7cebba0413e5bf4d1f0 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:36 -0400 Subject: [PATCH 1414/9938] gpio: palmas: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_PALMAS drivers/gpio/Kconfig: bool "TI PALMAS series PMICs GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Laxman Dewangan Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-palmas.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 6f27b3d94d53..e248707ca39e 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include #include @@ -218,14 +218,3 @@ static int __init palmas_gpio_init(void) return platform_driver_register(&palmas_gpio_driver); } subsys_initcall(palmas_gpio_init); - -static void __exit palmas_gpio_exit(void) -{ - platform_driver_unregister(&palmas_gpio_driver); -} -module_exit(palmas_gpio_exit); - -MODULE_ALIAS("platform:palmas-gpio"); -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_DESCRIPTION("GPIO driver for TI Palmas series PMICs"); -MODULE_LICENSE("GPL v2"); -- GitLab From 02c7a13eabd85103167a822d470743b640120e7d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:37 -0400 Subject: [PATCH 1415/9938] gpio: tps65910: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_TPS65910 drivers/gpio/Kconfig: bool "TPS65910 GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Linus Walleij Cc: Alexandre Courbot Cc: Graeme Gregory Cc: Jorge Eduardo Candelaria Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tps65910.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index cdbd7c740043..0ae6a5a54ea8 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -4,7 +4,7 @@ * Copyright 2010 Texas Instruments Inc. * * Author: Graeme Gregory - * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk> + * Author: Jorge Eduardo Candelaria * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -193,15 +193,3 @@ static int __init tps65910_gpio_init(void) return platform_driver_register(&tps65910_gpio_driver); } subsys_initcall(tps65910_gpio_init); - -static void __exit tps65910_gpio_exit(void) -{ - platform_driver_unregister(&tps65910_gpio_driver); -} -module_exit(tps65910_gpio_exit); - -MODULE_AUTHOR("Graeme Gregory "); -MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>"); -MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps65910-gpio"); -- GitLab From a0e637387a9858f9c2e8228bc15e299387dadcd1 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 Apr 2016 14:49:38 -0400 Subject: [PATCH 1416/9938] gpio: tps6586x: make explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/gpio/Kconfig:config GPIO_TPS6586X drivers/gpio/Kconfig: bool "TPS6586X GPIO" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Alexandre Courbot Cc: Laxman Dewangan Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tps6586x.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index c88bdc8ee2c9..6b15e68a314f 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -140,14 +140,3 @@ static int __init tps6586x_gpio_init(void) return platform_driver_register(&tps6586x_gpio_driver); } subsys_initcall(tps6586x_gpio_init); - -static void __exit tps6586x_gpio_exit(void) -{ - platform_driver_unregister(&tps6586x_gpio_driver); -} -module_exit(tps6586x_gpio_exit); - -MODULE_ALIAS("platform:tps6586x-gpio"); -MODULE_DESCRIPTION("GPIO interface for TPS6586X PMIC"); -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_LICENSE("GPL"); -- GitLab From 521f40823ebf2818045546d45aa378eba1c41717 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 4 Apr 2016 17:46:18 -0500 Subject: [PATCH 1417/9938] iommu/omap: Remove iopgtable_clear_entry_all() from driver remove The function iopgtable_clear_entry_all() is used for clearing all the page table entries. These entries are neither created nor initialized during the OMAP IOMMU driver probe, and are managed only when a client device attaches to the IOMMU. So, there is no need to invoke this function on a driver remove. Removing this fixes a NULL pointer dereference crash if the IOMMU device is unbound from the driver with no client device attached to the IOMMU device. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 3dc5b65f3990..c05d48f88596 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -987,7 +987,6 @@ static int omap_iommu_remove(struct platform_device *pdev) { struct omap_iommu *obj = platform_get_drvdata(pdev); - iopgtable_clear_entry_all(obj); omap_iommu_debugfs_remove(obj); pm_runtime_disable(obj->dev); -- GitLab From 7c1ab60008755fc229b623a875f1e42de31cdb64 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 4 Apr 2016 17:46:19 -0500 Subject: [PATCH 1418/9938] iommu/omap: Replace BUG() in iopgtable_store_entry_core() The iopgtable_store_entry_core() function uses a BUG() statement for an unsupported page size entry programming. Replace this with a less severe WARN_ON() and perform a graceful bailout on error. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index c05d48f88596..f6cf728ee32a 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -628,10 +628,12 @@ iopgtable_store_entry_core(struct omap_iommu *obj, struct iotlb_entry *e) break; default: fn = NULL; - BUG(); break; } + if (WARN_ON(!fn)) + return -EINVAL; + prot = get_iopte_attr(e); spin_lock(&obj->page_table_lock); -- GitLab From 433c434a269e6a39753f0a97b4be903f96d030a9 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 4 Apr 2016 17:46:20 -0500 Subject: [PATCH 1419/9938] iommu/omap: Use WARN_ON for page table alignment check The OMAP IOMMU page table needs to be aligned on a 16K boundary, and the current code uses a BUG_ON on the alignment sanity check in the .domain_alloc() ops implementation. Replace this with a less severe WARN_ON and bail out gracefully. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index f6cf728ee32a..e2583cce2cc1 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1162,7 +1162,8 @@ static struct iommu_domain *omap_iommu_domain_alloc(unsigned type) * should never fail, but please keep this around to ensure * we keep the hardware happy */ - BUG_ON(!IS_ALIGNED((long)omap_domain->pgtable, IOPGD_TABLE_SIZE)); + if (WARN_ON(!IS_ALIGNED((long)omap_domain->pgtable, IOPGD_TABLE_SIZE))) + goto fail_align; clean_dcache_area(omap_domain->pgtable, IOPGD_TABLE_SIZE); spin_lock_init(&omap_domain->lock); @@ -1173,6 +1174,8 @@ static struct iommu_domain *omap_iommu_domain_alloc(unsigned type) return &omap_domain->domain; +fail_align: + kfree(omap_domain->pgtable); fail_nomem: kfree(omap_domain); out: -- GitLab From a5c0e0b4ac07434056c5c4ecafeb9a5cff3d1a9d Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 4 Apr 2016 17:46:21 -0500 Subject: [PATCH 1420/9938] iommu/omap: Align code with open parenthesis This patch fixes one existing alignment checkpatch check warning of the type "Alignment should match open parenthesis" in the OMAP IOMMU debug source file. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 9bc20e2119a3..505548aafeff 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -136,7 +136,7 @@ static ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, struct seq_file *s) { seq_printf(s, "%08x %08x %01x\n", cr->cam, cr->ram, - (cr->cam & MMU_CAM_P) ? 1 : 0); + (cr->cam & MMU_CAM_P) ? 1 : 0); return 0; } -- GitLab From 73cc86252bd8a547349d2856497eceaf4f2d1766 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Fri, 1 Apr 2016 13:18:38 -0400 Subject: [PATCH 1421/9938] GFS2: Get rid of dead code in inode_go_demote_ok Function inode_go_demote_ok had some code that was only executed if gl_holders was not empty. However, if gl_holders was not empty, the only caller, demote_ok(), returns before inode_go_demote_ok would ever be called. Therefore, it's dead code, so I removed it. Signed-off-by: Bob Peterson Acked-by: Steven Whitehouse --- fs/gfs2/glops.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 437fd73e381e..5db59d444838 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -286,17 +286,10 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) static int inode_go_demote_ok(const struct gfs2_glock *gl) { struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; - struct gfs2_holder *gh; if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) return 0; - if (!list_empty(&gl->gl_holders)) { - gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); - if (gh->gh_list.next != &gl->gl_holders) - return 0; - } - return 1; } -- GitLab From 611526756a3d0fa7f4d1c519397ba8898f40443f Mon Sep 17 00:00:00 2001 From: Abhi Das Date: Tue, 5 Apr 2016 12:06:15 -0400 Subject: [PATCH 1422/9938] gfs2: Use gfs2 wrapper to sync inode before calling generic_file_splice_read() gfs2_file_splice_read() f_op grabs and releases the cluster-wide inode glock to sync the inode size to the latest. Without this, generic_file_splice_read() uses an older i_size value and can return EOF for valid offsets in the inode. Signed-off-by: Abhi Das Signed-off-by: Bob Peterson --- fs/gfs2/file.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index c9384f932975..fd9a10e4518d 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -950,6 +950,30 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t le return ret; } +static ssize_t gfs2_file_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + struct inode *inode = in->f_mapping->host; + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_holder gh; + int ret; + + mutex_lock(&inode->i_mutex); + + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + if (ret) { + mutex_unlock(&inode->i_mutex); + return ret; + } + + gfs2_glock_dq_uninit(&gh); + mutex_unlock(&inode->i_mutex); + + return generic_file_splice_read(in, ppos, pipe, len, flags); +} + + static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) @@ -1112,7 +1136,7 @@ const struct file_operations gfs2_file_fops = { .fsync = gfs2_fsync, .lock = gfs2_lock, .flock = gfs2_flock, - .splice_read = generic_file_splice_read, + .splice_read = gfs2_file_splice_read, .splice_write = gfs2_file_splice_write, .setlease = simple_nosetlease, .fallocate = gfs2_fallocate, @@ -1140,7 +1164,7 @@ const struct file_operations gfs2_file_fops_nolock = { .open = gfs2_open, .release = gfs2_release, .fsync = gfs2_fsync, - .splice_read = generic_file_splice_read, + .splice_read = gfs2_file_splice_read, .splice_write = gfs2_file_splice_write, .setlease = generic_setlease, .fallocate = gfs2_fallocate, -- GitLab From dcbb408ac5a2803ba44ca2fae8bf53eb5d4082f3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 5 Apr 2016 12:12:45 -0500 Subject: [PATCH 1423/9938] PCI: Fix spelling errors Fix spelling of "initalization". [bhelgaas: also fix pci/pci.c] Signed-off-by: Colin Ian King Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-xilinx-nwl.c | 2 +- drivers/pci/pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index 5139e6443bbd..3479d30e2be8 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c @@ -819,7 +819,7 @@ static int nwl_pcie_probe(struct platform_device *pdev) err = nwl_pcie_bridge_init(pcie); if (err) { - dev_err(pcie->dev, "HW Initalization failed\n"); + dev_err(pcie->dev, "HW Initialization failed\n"); return err; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 25e0327d4429..e3d6b33fd596 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2389,7 +2389,7 @@ static int pci_ea_read(struct pci_dev *dev, int offset) return offset + ent_size; } -/* Enhanced Allocation Initalization */ +/* Enhanced Allocation Initialization */ void pci_ea_init(struct pci_dev *dev) { int ea; -- GitLab From 94016680737fd5f9dcfac3fe65b2e61d38fcfba6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 7 Jan 2016 22:25:39 -0800 Subject: [PATCH 1424/9938] Input: omap-keypad - remove adjusting of scan delay As of 35f8679f577ae5673a778598bcbe7b45cbec8923 ("Input: omap-keypad - remove dead check") we no longer declare keypresses as spurious, therefore we can use constant delay between scans. Suggested-by: Janusz Krzysztofik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/omap-keypad.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index e0d72c8c01e4..d115acf0a805 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -133,7 +133,6 @@ static void omap_kp_tasklet(unsigned long data) unsigned int row_shift = get_count_order(omap_kp_data->cols); unsigned char new_state[8], changed, key_down = 0; int col, row; - int spurious = 0; /* check for any changes */ omap_kp_scan_keypad(omap_kp_data, new_state); @@ -170,12 +169,9 @@ static void omap_kp_tasklet(unsigned long data) memcpy(keypad_state, new_state, sizeof(keypad_state)); if (key_down) { - int delay = HZ / 20; /* some key is pressed - keep irq disabled and use timer * to poll the keypad */ - if (spurious) - delay = 2 * HZ; - mod_timer(&omap_kp_data->timer, jiffies + delay); + mod_timer(&omap_kp_data->timer, jiffies + HZ / 20); } else { /* enable interrupts */ omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); -- GitLab From a56f9235c9702544319f8ea0ce0c3aefed23d153 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 7 Jan 2016 22:16:35 -0800 Subject: [PATCH 1425/9938] Input: omap-keypad - drop empty PM stubs There is no reason to have empty suspend and resume stubs. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/omap-keypad.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index d115acf0a805..8dc34ee772ae 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -212,25 +212,6 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, omap_kp_enable_show, omap_kp_enable_store); -#ifdef CONFIG_PM -static int omap_kp_suspend(struct platform_device *dev, pm_message_t state) -{ - /* Nothing yet */ - - return 0; -} - -static int omap_kp_resume(struct platform_device *dev) -{ - /* Nothing yet */ - - return 0; -} -#else -#define omap_kp_suspend NULL -#define omap_kp_resume NULL -#endif - static int omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; @@ -367,8 +348,6 @@ static int omap_kp_remove(struct platform_device *pdev) static struct platform_driver omap_kp_driver = { .probe = omap_kp_probe, .remove = omap_kp_remove, - .suspend = omap_kp_suspend, - .resume = omap_kp_resume, .driver = { .name = "omap-keypad", }, -- GitLab From b5ca3ea327a6467591751e4c98207281fe884da3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 7 Jan 2016 22:33:49 -0800 Subject: [PATCH 1426/9938] Input: omap-keypad - remove set_col_gpio_val() and get_row_gpio_val() Commit f799a3d8fe170159257b75c1baf48a7c1f625d1d ("Input: omap-keypad: Remove dependencies to mach includes") removed users of the above functions, but left them in the code. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/omap-keypad.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 8dc34ee772ae..146b26f665f6 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -64,31 +64,6 @@ static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); static unsigned int *row_gpios; static unsigned int *col_gpios; -#ifdef CONFIG_ARCH_OMAP2 -static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value) -{ - int col; - - for (col = 0; col < omap_kp->cols; col++) - gpio_set_value(col_gpios[col], value & (1 << col)); -} - -static u8 get_row_gpio_val(struct omap_kp *omap_kp) -{ - int row; - u8 value = 0; - - for (row = 0; row < omap_kp->rows; row++) { - if (gpio_get_value(row_gpios[row])) - value |= (1 << row); - } - return value; -} -#else -#define set_col_gpio_val(x, y) do {} while (0) -#define get_row_gpio_val(x) 0 -#endif - static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) { /* disable keyboard interrupt and schedule for handling */ -- GitLab From 20aa787e453faec948ad75ebaa1535dbd5adb271 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 7 Jan 2016 17:28:06 -0800 Subject: [PATCH 1427/9938] Input: ti_am335x_tsc - use SIMPLE_DEV_PM_OPS Instead of doing the dance with macro that either resolves to a pointer or NULL, let's switch to using SIMPLE_DEV_PM_OPS(). Also let's mark suspend and resume methods as __maybe_unused instead of guarding them with an #ifdef and rely on linker to drop unused code. Doing so should allow better compile coverage. Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ti_am335x_tsc.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index a21a07c3ab6d..8b3f15ca7725 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -487,8 +487,7 @@ static int titsc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int titsc_suspend(struct device *dev) +static int __maybe_unused titsc_suspend(struct device *dev) { struct titsc *ts_dev = dev_get_drvdata(dev); struct ti_tscadc_dev *tscadc_dev; @@ -504,7 +503,7 @@ static int titsc_suspend(struct device *dev) return 0; } -static int titsc_resume(struct device *dev) +static int __maybe_unused titsc_resume(struct device *dev) { struct titsc *ts_dev = dev_get_drvdata(dev); struct ti_tscadc_dev *tscadc_dev; @@ -521,14 +520,7 @@ static int titsc_resume(struct device *dev) return 0; } -static const struct dev_pm_ops titsc_pm_ops = { - .suspend = titsc_suspend, - .resume = titsc_resume, -}; -#define TITSC_PM_OPS (&titsc_pm_ops) -#else -#define TITSC_PM_OPS NULL -#endif +static SIMPLE_DEV_PM_OPS(titsc_pm_ops, titsc_suspend, titsc_resume); static const struct of_device_id ti_tsc_dt_ids[] = { { .compatible = "ti,am3359-tsc", }, @@ -541,7 +533,7 @@ static struct platform_driver ti_tsc_driver = { .remove = titsc_remove, .driver = { .name = "TI-am335x-tsc", - .pm = TITSC_PM_OPS, + .pm = &titsc_pm_ops, .of_match_table = ti_tsc_dt_ids, }, }; -- GitLab From 08922f644878c9163ada8df3ef9def89be1d5e90 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 29 Mar 2016 11:16:17 +0530 Subject: [PATCH 1428/9938] mtd: devices: m25p80: add support for mmap read request Certain SPI controllers may provide accelerated hardware interface to read from m25p80 type flash devices in order to provide better read performance. SPI core supports such devices with spi_flash_read() API. Call spi_flash_read(), if supported, to make use of such interface. Signed-off-by: Vignesh R [Brian: add memset()] Signed-off-by: Brian Norris --- drivers/mtd/devices/m25p80.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index c9c3b7fa3051..9d6854467651 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -131,6 +131,28 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, /* convert the dummy cycles to the number of bytes */ dummy /= 8; + if (spi_flash_read_supported(spi)) { + struct spi_flash_read_message msg; + int ret; + + memset(&msg, 0, sizeof(msg)); + + msg.buf = buf; + msg.from = from; + msg.len = len; + msg.read_opcode = nor->read_opcode; + msg.addr_width = nor->addr_width; + msg.dummy_bytes = dummy; + /* TODO: Support other combinations */ + msg.opcode_nbits = SPI_NBITS_SINGLE; + msg.addr_nbits = SPI_NBITS_SINGLE; + msg.data_nbits = m25p80_rx_nbits(nor); + + ret = spi_flash_read(spi, &msg); + *retlen = msg.retlen; + return ret; + } + spi_message_init(&m); memset(t, 0, (sizeof t)); -- GitLab From a221f95ef4257a48c4f8cba8e804431ab66a359d Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Tue, 5 Apr 2016 08:59:34 +0300 Subject: [PATCH 1429/9938] regulator: twl: Provide of_map_mode for twl4030 of_map_mode is needed so to be possible to set initial regulators mode from the board DTS. Otherwise, for DT boot, regulators are left in their default state after reset/reboot. Document device specific modes as well. Signed-off-by: Ivaylo Dimitrov Signed-off-by: Mark Brown --- .../bindings/regulator/twl-regulator.txt | 6 +++++ drivers/regulator/twl-regulator.c | 22 ++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index 75b0c1669504..74a91c4f8530 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -57,6 +57,12 @@ For twl4030 regulators/LDOs Optional properties: - Any optional property defined in bindings/regulator/regulator.txt +For twl4030 regulators/LDOs: + - regulator-initial-mode: + - 0x08 - Sleep mode, the nominal output voltage is maintained with low power + consumption with low load current capability. + - 0x0e - Active mode, the regulator can deliver its nominal output voltage + with full-load current capability. Example: diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 7355616194ab..11c6a5c98c46 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -387,6 +387,18 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) return twl4030_send_pb_msg(message); } +static inline unsigned int twl4030reg_map_mode(unsigned int mode) +{ + switch (mode) { + case RES_STATE_ACTIVE: + return REGULATOR_MODE_NORMAL; + case RES_STATE_SLEEP: + return REGULATOR_MODE_STANDBY; + default: + return -EINVAL; + } +} + static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) { struct twlreg_info *info = rdev_get_drvdata(rdev); @@ -889,10 +901,11 @@ static struct regulator_ops twlsmps_ops = { #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ - remap_conf, TWL4030, twl4030fixed_ops) + remap_conf, TWL4030, twl4030fixed_ops, \ + twl4030reg_map_mode) #define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \ TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \ - 0x0, TWL6030, twl6030fixed_ops) + 0x0, TWL6030, twl6030fixed_ops, 0x0) #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \ static const struct twlreg_info TWL4030_INFO_##label = { \ @@ -909,6 +922,7 @@ static const struct twlreg_info TWL4030_INFO_##label = { \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ .enable_time = turnon_delay, \ + .of_map_mode = twl4030reg_map_mode, \ }, \ } @@ -924,6 +938,7 @@ static const struct twlreg_info TWL4030_INFO_##label = { \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ .enable_time = turnon_delay, \ + .of_map_mode = twl4030reg_map_mode, \ }, \ } @@ -969,7 +984,7 @@ static const struct twlreg_info TWL6032_INFO_##label = { \ } #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ - family, operations) \ + family, operations, map_mode) \ static const struct twlreg_info TWLFIXED_INFO_##label = { \ .base = offset, \ .id = num, \ @@ -984,6 +999,7 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \ .owner = THIS_MODULE, \ .min_uV = mVolts * 1000, \ .enable_time = turnon_delay, \ + .of_map_mode = map_mode, \ }, \ } -- GitLab From 724fef53449d22ed41c99164aff7d7c3654603e2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 Apr 2016 11:05:15 +0900 Subject: [PATCH 1430/9938] regulator: max8997/max77802: Fix misspelled Samsung address Correct smasung.com into samsung.com. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/max77802-regulator.c | 2 +- drivers/regulator/max8997-regulator.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c index c07ee13bd470..1d3539324d9a 100644 --- a/drivers/regulator/max77802-regulator.c +++ b/drivers/regulator/max77802-regulator.c @@ -5,7 +5,7 @@ * Simon Glass * * Copyright (C) 2012 Samsung Electronics - * Chiwoong Byun + * Chiwoong Byun * Jonghwa Lee * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/regulator/max8997-regulator.c b/drivers/regulator/max8997-regulator.c index ea0196d4496b..efabc0ea0e96 100644 --- a/drivers/regulator/max8997-regulator.c +++ b/drivers/regulator/max8997-regulator.c @@ -2,7 +2,7 @@ * max8997.c - Regulator driver for the Maxim 8997/8966 * * Copyright (C) 2011 Samsung Electronics - * MyungJoo Ham + * MyungJoo Ham * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- GitLab From fd786fb0276a22155058018f76eb4c665d37f170 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 5 Apr 2016 15:09:48 +0530 Subject: [PATCH 1431/9938] regulator: pwm: Try to avoid voltage error in duty cycle calculation In continuous mode of the PWM regulators, the requested voltage PWM duty cycle is calculated in terms of 100% scale where entire range denotes 100%. The calculation for PWM pulse ON time(duty_pulse) is done as: duty_cycle = ((requested - minimum) * 100) / voltage_range. then duty pulse is calculated as duty_pulse = (pwm_period/100) * duty_cycle This leads to the calculation error if we have the requested voltage where accurate pulse time is possible. For example: Consider following case voltage range is 800000uV to 1350000uV. pwm-period = 1550ns (1ns time is 1mV). Requested 900000uV. duty_cycle = ((900000uV - 800000uV) * 100)/ 1550000 = 6.45 but we will get 6. duty_pulse = (1550/100) * 6 = 90 pulse time. 90 pulse time is equivalent to 90mV and this gives us pulse time equivalent to 890000uV instead of 900000uV. Proposing the solution in which if requested voltage makes the accurate duty pulse then there will not be any error. On this case, if (req_uV - min_uV) * pwm_period is perfect dividable by voltage_range then get the duty pulse time directly. duty_pulse = ((900000uV - 800000uV) * 1550)/1550000) = 100 and this is equivalent to 100mV and so final voltage is (800000 + 100000) = 900000uV which is same as requested, Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/pwm-regulator.c | 38 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index f99a6970be29..8e928f23279b 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -113,18 +113,6 @@ static int pwm_regulator_is_enabled(struct regulator_dev *dev) return pwm_is_enabled(drvdata->pwm); } -/** - * Continuous voltage call-backs - */ -static int pwm_voltage_to_duty_cycle_percentage(struct regulator_dev *rdev, int req_uV) -{ - int min_uV = rdev->constraints->min_uV; - int max_uV = rdev->constraints->max_uV; - int diff = max_uV - min_uV; - - return ((req_uV * 100) - (min_uV * 100)) / diff; -} - static int pwm_regulator_get_voltage(struct regulator_dev *rdev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); @@ -139,12 +127,32 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev, struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); unsigned int ramp_delay = rdev->constraints->ramp_delay; unsigned int period = pwm_get_period(drvdata->pwm); - int duty_cycle; + unsigned int req_diff = min_uV - rdev->constraints->min_uV; + unsigned int diff; + unsigned int duty_pulse; + u64 req_period; + u32 rem; int ret; - duty_cycle = pwm_voltage_to_duty_cycle_percentage(rdev, min_uV); + diff = rdev->constraints->max_uV - rdev->constraints->min_uV; + + /* First try to find out if we get the iduty cycle time which is + * factor of PWM period time. If (request_diff_to_min * pwm_period) + * is perfect divided by voltage_range_diff then it is possible to + * get duty cycle time which is factor of PWM period. This will help + * to get output voltage nearer to requested value as there is no + * calculation loss. + */ + req_period = req_diff * period; + div_u64_rem(req_period, diff, &rem); + if (!rem) { + do_div(req_period, diff); + duty_pulse = (unsigned int)req_period; + } else { + duty_pulse = (period / 100) * ((req_diff * 100) / diff); + } - ret = pwm_config(drvdata->pwm, (period / 100) * duty_cycle, period); + ret = pwm_config(drvdata->pwm, duty_pulse, period); if (ret) { dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); return ret; -- GitLab From 15a1c5030a1e0445af2e4eaa1535cccc8519d99c Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 5 Apr 2016 23:37:48 +0530 Subject: [PATCH 1432/9938] spi: cadence: Fix a check patch warning CHECK: Comparison to NULL could be written "!master" + if (master == NULL) Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 121a4135b540..3acaac33218a 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -481,7 +481,7 @@ static int cdns_spi_probe(struct platform_device *pdev) u32 num_cs; master = spi_alloc_master(&pdev->dev, sizeof(*xspi)); - if (master == NULL) + if (!master) return -ENOMEM; xspi = spi_master_get_devdata(master); -- GitLab From 24746675fbc8dcc09e10283ca0b3f038e58182e9 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 5 Apr 2016 23:37:49 +0530 Subject: [PATCH 1433/9938] spi: cadence: Remove _MASK and _OFFSET suffix Remove the _MASK and _OFFSET from the macros. It improves readability, removes some checkpatch error for exceeding 80 chars and also prevents some linebreaks. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 161 ++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 87 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 3acaac33218a..97a3bf680ccb 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -25,17 +25,17 @@ #define CDNS_SPI_NAME "cdns-spi" /* Register offset definitions */ -#define CDNS_SPI_CR_OFFSET 0x00 /* Configuration Register, RW */ -#define CDNS_SPI_ISR_OFFSET 0x04 /* Interrupt Status Register, RO */ -#define CDNS_SPI_IER_OFFSET 0x08 /* Interrupt Enable Register, WO */ -#define CDNS_SPI_IDR_OFFSET 0x0c /* Interrupt Disable Register, WO */ -#define CDNS_SPI_IMR_OFFSET 0x10 /* Interrupt Enabled Mask Register, RO */ -#define CDNS_SPI_ER_OFFSET 0x14 /* Enable/Disable Register, RW */ -#define CDNS_SPI_DR_OFFSET 0x18 /* Delay Register, RW */ -#define CDNS_SPI_TXD_OFFSET 0x1C /* Data Transmit Register, WO */ -#define CDNS_SPI_RXD_OFFSET 0x20 /* Data Receive Register, RO */ -#define CDNS_SPI_SICR_OFFSET 0x24 /* Slave Idle Count Register, RW */ -#define CDNS_SPI_THLD_OFFSET 0x28 /* Transmit FIFO Watermark Register,RW */ +#define CDNS_SPI_CR 0x00 /* Configuration Register, RW */ +#define CDNS_SPI_ISR 0x04 /* Interrupt Status Register, RO */ +#define CDNS_SPI_IER 0x08 /* Interrupt Enable Register, WO */ +#define CDNS_SPI_IDR 0x0c /* Interrupt Disable Register, WO */ +#define CDNS_SPI_IMR 0x10 /* Interrupt Enabled Mask Register, RO */ +#define CDNS_SPI_ER 0x14 /* Enable/Disable Register, RW */ +#define CDNS_SPI_DR 0x18 /* Delay Register, RW */ +#define CDNS_SPI_TXD 0x1C /* Data Transmit Register, WO */ +#define CDNS_SPI_RXD 0x20 /* Data Receive Register, RO */ +#define CDNS_SPI_SICR 0x24 /* Slave Idle Count Register, RW */ +#define CDNS_SPI_THLD 0x28 /* Transmit FIFO Watermark Register,RW */ /* * SPI Configuration Register bit Masks @@ -43,20 +43,20 @@ * This register contains various control bits that affect the operation * of the SPI controller */ -#define CDNS_SPI_CR_MANSTRT_MASK 0x00010000 /* Manual TX Start */ -#define CDNS_SPI_CR_CPHA_MASK 0x00000004 /* Clock Phase Control */ -#define CDNS_SPI_CR_CPOL_MASK 0x00000002 /* Clock Polarity Control */ -#define CDNS_SPI_CR_SSCTRL_MASK 0x00003C00 /* Slave Select Mask */ -#define CDNS_SPI_CR_PERI_SEL_MASK 0x00000200 /* Peripheral Select Decode */ -#define CDNS_SPI_CR_BAUD_DIV_MASK 0x00000038 /* Baud Rate Divisor Mask */ -#define CDNS_SPI_CR_MSTREN_MASK 0x00000001 /* Master Enable Mask */ -#define CDNS_SPI_CR_MANSTRTEN_MASK 0x00008000 /* Manual TX Enable Mask */ -#define CDNS_SPI_CR_SSFORCE_MASK 0x00004000 /* Manual SS Enable Mask */ -#define CDNS_SPI_CR_BAUD_DIV_4_MASK 0x00000008 /* Default Baud Div Mask */ -#define CDNS_SPI_CR_DEFAULT_MASK (CDNS_SPI_CR_MSTREN_MASK | \ - CDNS_SPI_CR_SSCTRL_MASK | \ - CDNS_SPI_CR_SSFORCE_MASK | \ - CDNS_SPI_CR_BAUD_DIV_4_MASK) +#define CDNS_SPI_CR_MANSTRT 0x00010000 /* Manual TX Start */ +#define CDNS_SPI_CR_CPHA 0x00000004 /* Clock Phase Control */ +#define CDNS_SPI_CR_CPOL 0x00000002 /* Clock Polarity Control */ +#define CDNS_SPI_CR_SSCTRL 0x00003C00 /* Slave Select Mask */ +#define CDNS_SPI_CR_PERI_SEL 0x00000200 /* Peripheral Select Decode */ +#define CDNS_SPI_CR_BAUD_DIV 0x00000038 /* Baud Rate Divisor Mask */ +#define CDNS_SPI_CR_MSTREN 0x00000001 /* Master Enable Mask */ +#define CDNS_SPI_CR_MANSTRTEN 0x00008000 /* Manual TX Enable Mask */ +#define CDNS_SPI_CR_SSFORCE 0x00004000 /* Manual SS Enable Mask */ +#define CDNS_SPI_CR_BAUD_DIV_4 0x00000008 /* Default Baud Div Mask */ +#define CDNS_SPI_CR_DEFAULT (CDNS_SPI_CR_MSTREN | \ + CDNS_SPI_CR_SSCTRL | \ + CDNS_SPI_CR_SSFORCE | \ + CDNS_SPI_CR_BAUD_DIV_4) /* * SPI Configuration Register - Baud rate and slave select @@ -77,21 +77,21 @@ * All the four interrupt registers (Status/Mask/Enable/Disable) have the same * bit definitions. */ -#define CDNS_SPI_IXR_TXOW_MASK 0x00000004 /* SPI TX FIFO Overwater */ -#define CDNS_SPI_IXR_MODF_MASK 0x00000002 /* SPI Mode Fault */ -#define CDNS_SPI_IXR_RXNEMTY_MASK 0x00000010 /* SPI RX FIFO Not Empty */ -#define CDNS_SPI_IXR_DEFAULT_MASK (CDNS_SPI_IXR_TXOW_MASK | \ - CDNS_SPI_IXR_MODF_MASK) -#define CDNS_SPI_IXR_TXFULL_MASK 0x00000008 /* SPI TX Full */ -#define CDNS_SPI_IXR_ALL_MASK 0x0000007F /* SPI all interrupts */ +#define CDNS_SPI_IXR_TXOW 0x00000004 /* SPI TX FIFO Overwater */ +#define CDNS_SPI_IXR_MODF 0x00000002 /* SPI Mode Fault */ +#define CDNS_SPI_IXR_RXNEMTY 0x00000010 /* SPI RX FIFO Not Empty */ +#define CDNS_SPI_IXR_DEFAULT (CDNS_SPI_IXR_TXOW | \ + CDNS_SPI_IXR_MODF) +#define CDNS_SPI_IXR_TXFULL 0x00000008 /* SPI TX Full */ +#define CDNS_SPI_IXR_ALL 0x0000007F /* SPI all interrupts */ /* * SPI Enable Register bit Masks * * This register is used to enable or disable the SPI controller */ -#define CDNS_SPI_ER_ENABLE_MASK 0x00000001 /* SPI Enable Bit Mask */ -#define CDNS_SPI_ER_DISABLE_MASK 0x0 /* SPI Disable Bit Mask */ +#define CDNS_SPI_ER_ENABLE 0x00000001 /* SPI Enable Bit Mask */ +#define CDNS_SPI_ER_DISABLE 0x0 /* SPI Disable Bit Mask */ /* SPI FIFO depth in bytes */ #define CDNS_SPI_FIFO_DEPTH 128 @@ -149,26 +149,21 @@ static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val) */ static void cdns_spi_init_hw(struct cdns_spi *xspi) { - u32 ctrl_reg = CDNS_SPI_CR_DEFAULT_MASK; + u32 ctrl_reg = CDNS_SPI_CR_DEFAULT; if (xspi->is_decoded_cs) - ctrl_reg |= CDNS_SPI_CR_PERI_SEL_MASK; + ctrl_reg |= CDNS_SPI_CR_PERI_SEL; - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, - CDNS_SPI_ER_DISABLE_MASK); - cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, - CDNS_SPI_IXR_ALL_MASK); + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); + cdns_spi_write(xspi, CDNS_SPI_IDR, CDNS_SPI_IXR_ALL); /* Clear the RX FIFO */ - while (cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET) & - CDNS_SPI_IXR_RXNEMTY_MASK) - cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET); - - cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, - CDNS_SPI_IXR_ALL_MASK); - cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, - CDNS_SPI_ER_ENABLE_MASK); + while (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_RXNEMTY) + cdns_spi_read(xspi, CDNS_SPI_RXD); + + cdns_spi_write(xspi, CDNS_SPI_ISR, CDNS_SPI_IXR_ALL); + cdns_spi_write(xspi, CDNS_SPI_CR, ctrl_reg); + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_ENABLE); } /** @@ -181,24 +176,24 @@ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg; - ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); + ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); if (is_high) { /* Deselect the slave */ - ctrl_reg |= CDNS_SPI_CR_SSCTRL_MASK; + ctrl_reg |= CDNS_SPI_CR_SSCTRL; } else { /* Select the slave */ - ctrl_reg &= ~CDNS_SPI_CR_SSCTRL_MASK; + ctrl_reg &= ~CDNS_SPI_CR_SSCTRL; if (!(xspi->is_decoded_cs)) ctrl_reg |= ((~(CDNS_SPI_SS0 << spi->chip_select)) << CDNS_SPI_SS_SHIFT) & - CDNS_SPI_CR_SSCTRL_MASK; + CDNS_SPI_CR_SSCTRL; else ctrl_reg |= (spi->chip_select << CDNS_SPI_SS_SHIFT) & - CDNS_SPI_CR_SSCTRL_MASK; + CDNS_SPI_CR_SSCTRL; } - cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); + cdns_spi_write(xspi, CDNS_SPI_CR, ctrl_reg); } /** @@ -212,14 +207,14 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi) struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg, new_ctrl_reg; - new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); + new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); /* Set the SPI clock phase and clock polarity */ - new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); + new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA | CDNS_SPI_CR_CPOL); if (spi->mode & SPI_CPHA) - new_ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; + new_ctrl_reg |= CDNS_SPI_CR_CPHA; if (spi->mode & SPI_CPOL) - new_ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; + new_ctrl_reg |= CDNS_SPI_CR_CPOL; if (new_ctrl_reg != ctrl_reg) { /* @@ -228,11 +223,9 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi) * polarity as it will cause the SPI slave to see spurious clock * transitions. To workaround the issue toggle the ER register. */ - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, - CDNS_SPI_ER_DISABLE_MASK); - cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, new_ctrl_reg); - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, - CDNS_SPI_ER_ENABLE_MASK); + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); + cdns_spi_write(xspi, CDNS_SPI_CR, new_ctrl_reg); + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_ENABLE); } } @@ -259,7 +252,7 @@ static void cdns_spi_config_clock_freq(struct spi_device *spi, frequency = clk_get_rate(xspi->ref_clk); - ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); + ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); /* Set the clock frequency */ if (xspi->speed_hz != transfer->speed_hz) { @@ -269,12 +262,12 @@ static void cdns_spi_config_clock_freq(struct spi_device *spi, (frequency / (2 << baud_rate_val)) > transfer->speed_hz) baud_rate_val++; - ctrl_reg &= ~CDNS_SPI_CR_BAUD_DIV_MASK; + ctrl_reg &= ~CDNS_SPI_CR_BAUD_DIV; ctrl_reg |= baud_rate_val << CDNS_SPI_BAUD_DIV_SHIFT; xspi->speed_hz = frequency / (2 << baud_rate_val); } - cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); + cdns_spi_write(xspi, CDNS_SPI_CR, ctrl_reg); } /** @@ -313,10 +306,9 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) && (xspi->tx_bytes > 0)) { if (xspi->txbuf) - cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, - *xspi->txbuf++); + cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); else - cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, 0); + cdns_spi_write(xspi, CDNS_SPI_TXD, 0); xspi->tx_bytes--; trans_cnt++; @@ -344,19 +336,18 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) u32 intr_status, status; status = IRQ_NONE; - intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET); - cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, intr_status); + intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR); + cdns_spi_write(xspi, CDNS_SPI_ISR, intr_status); - if (intr_status & CDNS_SPI_IXR_MODF_MASK) { + if (intr_status & CDNS_SPI_IXR_MODF) { /* Indicate that transfer is completed, the SPI subsystem will * identify the error as the remaining bytes to be * transferred is non-zero */ - cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, - CDNS_SPI_IXR_DEFAULT_MASK); + cdns_spi_write(xspi, CDNS_SPI_IDR, CDNS_SPI_IXR_DEFAULT); spi_finalize_current_transfer(master); status = IRQ_HANDLED; - } else if (intr_status & CDNS_SPI_IXR_TXOW_MASK) { + } else if (intr_status & CDNS_SPI_IXR_TXOW) { unsigned long trans_cnt; trans_cnt = xspi->rx_bytes - xspi->tx_bytes; @@ -365,7 +356,7 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) while (trans_cnt) { u8 data; - data = cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET); + data = cdns_spi_read(xspi, CDNS_SPI_RXD); if (xspi->rxbuf) *xspi->rxbuf++ = data; @@ -378,8 +369,8 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) cdns_spi_fill_tx_fifo(xspi); } else { /* Transfer is completed */ - cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, - CDNS_SPI_IXR_DEFAULT_MASK); + cdns_spi_write(xspi, CDNS_SPI_IDR, + CDNS_SPI_IXR_DEFAULT); spi_finalize_current_transfer(master); } status = IRQ_HANDLED; @@ -421,8 +412,7 @@ static int cdns_transfer_one(struct spi_master *master, cdns_spi_fill_tx_fifo(xspi); - cdns_spi_write(xspi, CDNS_SPI_IER_OFFSET, - CDNS_SPI_IXR_DEFAULT_MASK); + cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT); return transfer->len; } @@ -439,8 +429,7 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master) { struct cdns_spi *xspi = spi_master_get_devdata(master); - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, - CDNS_SPI_ER_ENABLE_MASK); + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_ENABLE); return 0; } @@ -458,8 +447,7 @@ static int cdns_unprepare_transfer_hardware(struct spi_master *master) { struct cdns_spi *xspi = spi_master_get_devdata(master); - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, - CDNS_SPI_ER_DISABLE_MASK); + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); return 0; } @@ -595,8 +583,7 @@ static int cdns_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct cdns_spi *xspi = spi_master_get_devdata(master); - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, - CDNS_SPI_ER_DISABLE_MASK); + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); clk_disable_unprepare(xspi->ref_clk); clk_disable_unprepare(xspi->pclk); -- GitLab From 50ac697baf0c83d5dd34d90acfcd8b83648c2d56 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 5 Apr 2016 23:37:50 +0530 Subject: [PATCH 1434/9938] spi: cadence: Fix probe error handling The clock disabling is missed out in some error cases at probe. Fix the same. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 97a3bf680ccb..2915b257921d 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -527,7 +527,7 @@ static int cdns_spi_probe(struct platform_device *pdev) if (irq <= 0) { ret = -ENXIO; dev_err(&pdev->dev, "irq number is invalid\n"); - goto remove_master; + goto clk_dis_all; } ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq, @@ -535,7 +535,7 @@ static int cdns_spi_probe(struct platform_device *pdev) if (ret != 0) { ret = -ENXIO; dev_err(&pdev->dev, "request_irq failed\n"); - goto remove_master; + goto clk_dis_all; } master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; -- GitLab From b4037360e66b90755ed73022976f10108bc82045 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 5 Apr 2016 23:37:51 +0530 Subject: [PATCH 1435/9938] spi: cadance: Fix the Documentation cdns_spi_chipselect has parameter is_high however the comment describes it as is_on. Also fixes the below warning. drivers/spi/spi-cadence.c:182: warning: No description found for parameter 'is_high' drivers/spi/spi-cadence.c:182: warning: Excess function parameter 'is_on' description in 'cdns_spi_chipselect' Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 2915b257921d..8a6fee934364 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -169,7 +169,7 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi) /** * cdns_spi_chipselect - Select or deselect the chip select line * @spi: Pointer to the spi_device structure - * @is_on: Select(0) or deselect (1) the chip select line + * @is_high: Select(0) or deselect (1) the chip select line */ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) { -- GitLab From d36ccd9f7ea41f343391a15677b8a858376e1107 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 5 Apr 2016 23:37:52 +0530 Subject: [PATCH 1436/9938] spi: cadence: Runtime pm adaptation Currently the clocks are enabled at probe and disabled at remove. This patch moves the clock enable to the start of transaction and disables at the end. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 70 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 8a6fee934364..3b94063b2823 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -19,6 +19,7 @@ #include #include #include +#include #include /* Name of this driver */ @@ -37,6 +38,7 @@ #define CDNS_SPI_SICR 0x24 /* Slave Idle Count Register, RW */ #define CDNS_SPI_THLD 0x28 /* Transmit FIFO Watermark Register,RW */ +#define SPI_AUTOSUSPEND_TIMEOUT 3000 /* * SPI Configuration Register bit Masks * @@ -509,6 +511,11 @@ static int cdns_spi_probe(struct platform_device *pdev) goto clk_dis_apb; } + pm_runtime_enable(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); + pm_runtime_set_active(&pdev->dev); + ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); if (ret < 0) master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS; @@ -523,6 +530,9 @@ static int cdns_spi_probe(struct platform_device *pdev) /* SPI controller initializations */ cdns_spi_init_hw(xspi); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + irq = platform_get_irq(pdev, 0); if (irq <= 0) { ret = -ENXIO; @@ -543,6 +553,7 @@ static int cdns_spi_probe(struct platform_device *pdev) master->transfer_one = cdns_transfer_one; master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; master->set_cs = cdns_spi_chipselect; + master->auto_runtime_pm = true; master->mode_bits = SPI_CPOL | SPI_CPHA; /* Set to default valid value */ @@ -560,6 +571,8 @@ static int cdns_spi_probe(struct platform_device *pdev) return ret; clk_dis_all: + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(xspi->ref_clk); clk_dis_apb: clk_disable_unprepare(xspi->pclk); @@ -587,6 +600,8 @@ static int cdns_spi_remove(struct platform_device *pdev) clk_disable_unprepare(xspi->ref_clk); clk_disable_unprepare(xspi->pclk); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_disable(&pdev->dev); spi_unregister_master(master); @@ -649,8 +664,59 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, - cdns_spi_resume); +/** + * cdns_spi_runtime_resume - Runtime resume method for the SPI driver + * @dev: Address of the platform_device structure + * + * This function enables the clocks + * + * Return: 0 on success and error value on error + */ +static int cnds_runtime_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct cdns_spi *xspi = spi_master_get_devdata(master); + int ret; + + ret = clk_prepare_enable(xspi->pclk); + if (ret) { + dev_err(dev, "Cannot enable APB clock.\n"); + return ret; + } + + ret = clk_prepare_enable(xspi->ref_clk); + if (ret) { + dev_err(dev, "Cannot enable device clock.\n"); + clk_disable(xspi->pclk); + return ret; + } + return 0; +} + +/** + * cdns_spi_runtime_suspend - Runtime suspend method for the SPI driver + * @dev: Address of the platform_device structure + * + * This function disables the clocks + * + * Return: Always 0 + */ +static int cnds_runtime_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct cdns_spi *xspi = spi_master_get_devdata(master); + + clk_disable_unprepare(xspi->ref_clk); + clk_disable_unprepare(xspi->pclk); + + return 0; +} + +static const struct dev_pm_ops cdns_spi_dev_pm_ops = { + SET_RUNTIME_PM_OPS(cnds_runtime_suspend, + cnds_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(cdns_spi_suspend, cdns_spi_resume) +}; static const struct of_device_id cdns_spi_of_match[] = { { .compatible = "xlnx,zynq-spi-r1p6" }, -- GitLab From 2198b7483d4a89cf2cc710045c76a76dba573ea5 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 5 Apr 2016 23:37:53 +0530 Subject: [PATCH 1437/9938] spi: cadence: Remove the clock enable and disable from suspend and resume Now that the clocks are enabled and disabled per transaction , remove the clock enable and disable from resume and suspend hooks. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 3b94063b2823..d0cdd1801e9e 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -621,14 +621,9 @@ static int __maybe_unused cdns_spi_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - struct cdns_spi *xspi = spi_master_get_devdata(master); spi_master_suspend(master); - clk_disable_unprepare(xspi->ref_clk); - - clk_disable_unprepare(xspi->pclk); - return 0; } @@ -644,21 +639,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - struct cdns_spi *xspi = spi_master_get_devdata(master); - int ret = 0; - - ret = clk_prepare_enable(xspi->pclk); - if (ret) { - dev_err(dev, "Cannot enable APB clock.\n"); - return ret; - } - ret = clk_prepare_enable(xspi->ref_clk); - if (ret) { - dev_err(dev, "Cannot enable device clock.\n"); - clk_disable(xspi->pclk); - return ret; - } spi_master_resume(master); return 0; -- GitLab From 6fe9b67dbe5e0a0abeeabd428cb596b913995b36 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 5 Apr 2016 23:37:54 +0530 Subject: [PATCH 1438/9938] spi: cadence: Return the error code for cdns_spi_suspend and cdns_spi_resume Return the error code for cdns_spi_suspend and cdns_spi_resume. Also fixes a comment where which claims that the error code is returned. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index d0cdd1801e9e..07481e12d8a3 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -615,16 +615,14 @@ static int cdns_spi_remove(struct platform_device *pdev) * This function disables the SPI controller and * changes the driver state to "suspend" * - * Return: Always 0 + * Return: 0 on success and error value on error */ static int __maybe_unused cdns_spi_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - spi_master_suspend(master); - - return 0; + return spi_master_suspend(master); } /** @@ -640,9 +638,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = platform_get_drvdata(pdev); - spi_master_resume(master); - - return 0; + return spi_master_resume(master); } /** -- GitLab From 613c7c4003c8338a9a638485d95de2775948295b Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Tue, 5 Apr 2016 18:08:02 +0100 Subject: [PATCH 1439/9938] ASoC: dwc: Unmask I2S interrupts only for enabled channels There is no need to unmask all interrupts at I2S start. This can cause performance issues in slower platforms. Unmask only the interrupts for the used channels. Signed-off-by: Jose Abreu Signed-off-by: Mark Brown --- sound/soc/dwc/designware_i2s.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index bff258d7bcea..3effcd1a7df8 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c @@ -147,17 +147,18 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream) static void i2s_start(struct dw_i2s_dev *dev, struct snd_pcm_substream *substream) { + struct i2s_clk_config_data *config = &dev->config; u32 i, irq; i2s_write_reg(dev->i2s_base, IER, 1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - for (i = 0; i < 4; i++) { + for (i = 0; i < (config->chan_nr / 2); i++) { irq = i2s_read_reg(dev->i2s_base, IMR(i)); i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x30); } i2s_write_reg(dev->i2s_base, ITER, 1); } else { - for (i = 0; i < 4; i++) { + for (i = 0; i < (config->chan_nr / 2); i++) { irq = i2s_read_reg(dev->i2s_base, IMR(i)); i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x03); } -- GitLab From b555cf4a50c17a9714715a2d7c8574dca1a7b356 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 5 Apr 2016 10:20:02 +0200 Subject: [PATCH 1440/9938] mlxsw: spectrum: Reduce number of supported 802.1D bridges Resources allocated for these bridges at init time cannot be later used for other purposes. While current number is supported by the device, it's mostly theoretical with regards to any real use case, which leads to poor utilization of device's resources. Solve that by reducing the number. The long term plan is to make this value (along with others) user configurable via devlink and write it to NVRAM, so that it can be used during the next init. Until then we must hardcode such values. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 4b8abaf06321..d58ab0cd9507 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -50,7 +50,7 @@ #define MLXSW_SP_VFID_BASE VLAN_N_VID #define MLXSW_SP_VFID_PORT_MAX 512 /* Non-bridged VLAN interfaces */ -#define MLXSW_SP_VFID_BR_MAX 8192 /* Bridged VLAN interfaces */ +#define MLXSW_SP_VFID_BR_MAX 6144 /* Bridged VLAN interfaces */ #define MLXSW_SP_VFID_MAX (MLXSW_SP_VFID_PORT_MAX + MLXSW_SP_VFID_BR_MAX) #define MLXSW_SP_LAG_MAX 64 -- GitLab From 75f3a1018f0103025558caa60e24132a4cc9ce8f Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 5 Apr 2016 10:20:03 +0200 Subject: [PATCH 1441/9938] switchdev: Use switch ID in suggested udev rule Since there can be multiple switch ASICs on the same system we should use the switch ID in order to differentiate between them and set the switch name (e.g. swX) accordingly. Also, replace the order of the "Switch ID" and "Port Netdev Naming" sections following the above change. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index 2f659129694b..31c39115834d 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -89,6 +89,18 @@ Typically, the management port is not participating in offloaded data plane and is loaded with a different driver, such as a NIC driver, on the management port device. +Switch ID +^^^^^^^^^ + +The switchdev driver must implement the switchdev op switchdev_port_attr_get +for SWITCHDEV_ATTR_ID_PORT_PARENT_ID for each port netdev, returning the same +physical ID for each port of a switch. The ID must be unique between switches +on the same system. The ID does not need to be unique between switches on +different systems. + +The switch ID is used to locate ports on a switch and to know if aggregated +ports belong to the same switch. + Port Netdev Naming ^^^^^^^^^^^^^^^^^^ @@ -104,25 +116,13 @@ external configuration. For example, if a physical 40G port is split logically into 4 10G ports, resulting in 4 port netdevs, the device can give a unique name for each port using port PHYS name. The udev rule would be: -SUBSYSTEM=="net", ACTION=="add", DRIVER="", ATTR{phys_port_name}!="", \ - NAME="$attr{phys_port_name}" +SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}=="", \ + ATTR{phys_port_name}!="", NAME="swX$attr{phys_port_name}" Suggested naming convention is "swXpYsZ", where X is the switch name or ID, Y is the port name or ID, and Z is the sub-port name or ID. For example, sw1p1s0 would be sub-port 0 on port 1 on switch 1. -Switch ID -^^^^^^^^^ - -The switchdev driver must implement the switchdev op switchdev_port_attr_get -for SWITCHDEV_ATTR_ID_PORT_PARENT_ID for each port netdev, returning the same -physical ID for each port of a switch. The ID must be unique between switches -on the same system. The ID does not need to be unique between switches on -different systems. - -The switch ID is used to locate ports on a switch and to know if aggregated -ports belong to the same switch. - Port Features ^^^^^^^^^^^^^ -- GitLab From 2bf9a58675c5d6d37cdcb4301e6320009d299080 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 5 Apr 2016 10:20:04 +0200 Subject: [PATCH 1442/9938] mlxsw: spectrum: Add support for physical port names Export to userspace the front panel name of the port, so that udev can rename the ports accordingly. The convention suggested by switchdev documentation is used: 1) Non-split: pX 2) Split: pXsY Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 4afbc3e9e381..cb5f36e497e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -305,9 +305,9 @@ mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sspr), sspr_pl); } -static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, - u8 local_port, u8 *p_module, - u8 *p_width) +static int __mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, + u8 local_port, u8 *p_module, + u8 *p_width, u8 *p_lane) { char pmlp_pl[MLXSW_REG_PMLP_LEN]; int err; @@ -318,9 +318,20 @@ static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, return err; *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); + *p_lane = mlxsw_reg_pmlp_tx_lane_get(pmlp_pl, 0); return 0; } +static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, + u8 local_port, u8 *p_module, + u8 *p_width) +{ + u8 lane; + + return __mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, p_module, + p_width, &lane); +} + static int mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port, u8 module, u8 width, u8 lane) { @@ -861,6 +872,33 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev, return 0; } +static int mlxsw_sp_port_get_phys_port_name(struct net_device *dev, char *name, + size_t len) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + u8 module, width, lane; + int err; + + err = __mlxsw_sp_port_module_info_get(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_port->local_port, + &module, &width, &lane); + if (err) { + netdev_err(dev, "Failed to retrieve module information\n"); + return err; + } + + if (!mlxsw_sp_port->split) + err = snprintf(name, len, "p%d", module + 1); + else + err = snprintf(name, len, "p%ds%d", module + 1, + lane / width); + + if (err >= len) + return -EINVAL; + + return 0; +} + static const struct net_device_ops mlxsw_sp_port_netdev_ops = { .ndo_open = mlxsw_sp_port_open, .ndo_stop = mlxsw_sp_port_stop, @@ -877,6 +915,7 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = { .ndo_bridge_setlink = switchdev_port_bridge_setlink, .ndo_bridge_getlink = switchdev_port_bridge_getlink, .ndo_bridge_dellink = switchdev_port_bridge_dellink, + .ndo_get_phys_port_name = mlxsw_sp_port_get_phys_port_name, }; static void mlxsw_sp_port_get_drvinfo(struct net_device *dev, -- GitLab From 92dc20d83adec565378254c0630e839ff5674e14 Mon Sep 17 00:00:00 2001 From: Andrey Vostrikov Date: Tue, 5 Apr 2016 15:33:14 +0300 Subject: [PATCH 1443/9938] spi: spi-fsl-dspi: Fix cs_change handling in message transfer There are use cases when chip select should be triggered between transfers in single SPI message. Current implementation does this only on last transfer in message ignoring cs_change value provided in current transfer. Signed-off-by: Andrey Vostrikov Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 39412c9097c6..c1a2d747b246 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -385,8 +385,8 @@ static int dspi_transfer_one_message(struct spi_master *master, dspi->cur_chip = spi_get_ctldata(spi); dspi->cs = spi->chip_select; dspi->cs_change = 0; - if (dspi->cur_transfer->transfer_list.next - == &dspi->cur_msg->transfers) + if (list_is_last(&dspi->cur_transfer->transfer_list, + &dspi->cur_msg->transfers) || transfer->cs_change) dspi->cs_change = 1; dspi->void_write_data = dspi->cur_chip->void_write_data; -- GitLab From c99abb4cb8227bf8172c085213c91bf155c6618a Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 10 Mar 2016 14:59:45 -0800 Subject: [PATCH 1444/9938] i40e: Remove timer and task only if created In some error scenarios, we may find ourselves trying to remove a non-existent timer or worktask. This causes the kernel some bit of consternation, so don't do it. Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 56d4416c9a11..e615f66f576f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -11306,8 +11306,10 @@ static void i40e_remove(struct pci_dev *pdev) /* no more scheduling of any task */ set_bit(__I40E_SUSPENDED, &pf->state); set_bit(__I40E_DOWN, &pf->state); - del_timer_sync(&pf->service_timer); - cancel_work_sync(&pf->service_task); + if (pf->service_timer.data) + del_timer_sync(&pf->service_timer); + if (pf->service_task.func) + cancel_work_sync(&pf->service_task); if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { i40e_free_vfs(pf); -- GitLab From d3ce57344100023faa8f514eb66dfb110b53629c Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 10 Mar 2016 14:59:46 -0800 Subject: [PATCH 1445/9938] i40e: Notify VFs of all resets Notify VFs in the reset interrupt handler, instead of the actual reset initiation code. This allows the VFs to get properly notified for all resets, including resets initiated by different PFs on the same physical device. Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e615f66f576f..98bc749ce9f0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5534,8 +5534,6 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) WARN_ON(in_interrupt()); - if (i40e_check_asq_alive(&pf->hw)) - i40e_vc_notify_reset(pf); /* do the biggest reset indicated */ if (reset_flags & BIT_ULL(__I40E_GLOBAL_RESET_REQUESTED)) { @@ -6738,6 +6736,8 @@ static void i40e_prep_for_reset(struct i40e_pf *pf) clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state); if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) return; + if (i40e_check_asq_alive(&pf->hw)) + i40e_vc_notify_reset(pf); dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n"); -- GitLab From 7e5a313ed9b18ba9f35df2523eb9e386a195a2c4 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 10 Mar 2016 14:59:47 -0800 Subject: [PATCH 1446/9938] i40e: Added code to prevent double resets Clear the VFLR bit after reset processing, instead of before. This prevents double resets on VF init. Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 816c6bbf7093..291d6282f95b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -917,9 +917,9 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) { struct i40e_pf *pf = vf->pf; struct i40e_hw *hw = &pf->hw; + u32 reg, reg_idx, bit_idx; bool rsd = false; int i; - u32 reg; if (test_and_set_bit(__I40E_VF_DISABLE, &pf->state)) return; @@ -988,6 +988,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) } /* tell the VF the reset is done */ wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE); + + /* clear the VFLR bit in GLGEN_VFLRSTAT */ + reg_idx = (hw->func_caps.vf_base_id + vf->vf_id) / 32; + bit_idx = (hw->func_caps.vf_base_id + vf->vf_id) % 32; + wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx)); i40e_flush(hw); clear_bit(__I40E_VF_DISABLE, &pf->state); } @@ -2293,9 +2298,7 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) vf = &pf->vf[vf_id]; reg = rd32(hw, I40E_GLGEN_VFLRSTAT(reg_idx)); if (reg & BIT(bit_idx)) { - /* clear the bit in GLGEN_VFLRSTAT */ - wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx)); - + /* i40e_reset_vf will clear the bit in GLGEN_VFLRSTAT */ if (!test_bit(__I40E_DOWN, &pf->state)) i40e_reset_vf(vf, true); } -- GitLab From 56e5ca688f3d334ddc2acab27cb7efa83b238557 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 10 Mar 2016 14:59:48 -0800 Subject: [PATCH 1447/9938] i40e: Change unknown event error msg to ignore message There's no real error in an unknown event from the Firmware, we're just posting a useful FYI notice, so this patch simply removes the "Error" word. Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 98bc749ce9f0..38410050401c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6371,7 +6371,7 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) break; default: dev_info(&pf->pdev->dev, - "ARQ Error: Unknown event 0x%04x received\n", + "ARQ: Unknown event 0x%04x ignored\n", opcode); break; } -- GitLab From 19b73d8efaa459a66665b5e0a3e7acedd05f4901 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 10 Mar 2016 14:59:49 -0800 Subject: [PATCH 1448/9938] i40evf: Add additional check for reset If the driver happens to read a register during the time in which the device is undergoing reset, it will receive a value of 0xdeadbeef instead of a valid value. Unfortunately, the driver may misinterpret this as a valid value, especially if it's just looking for individual bits. Add an explicit check for this value when we are looking for admin queue errors, and trigger reset recovery if we find it. Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 820ad94c932b..d783c1b19a16 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1994,6 +1994,8 @@ static void i40evf_adminq_task(struct work_struct *work) /* check for error indications */ val = rd32(hw, hw->aq.arq.len); + if (val == 0xdeadbeef) /* indicates device in reset */ + goto freedom; oldval = val; if (val & I40E_VF_ARQLEN1_ARQVFE_MASK) { dev_info(&adapter->pdev->dev, "ARQ VF Error detected\n"); -- GitLab From 55f7d7233bd15c8a3fcf7051c681b05de5980a18 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 10 Mar 2016 14:59:50 -0800 Subject: [PATCH 1449/9938] i40e: Change comment to reflect correct function name Minor correction in the comment to reflect the correct function name Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 291d6282f95b..47b9e62473c4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -63,7 +63,7 @@ static void i40e_vc_vf_broadcast(struct i40e_pf *pf, } /** - * i40e_vc_notify_link_state + * i40e_vc_notify_vf_link_state * @vf: pointer to the VF structure * * send a link status message to a single VF -- GitLab From 50f26a507664499ccef017607a29cc1456695343 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 10 Mar 2016 14:59:51 -0800 Subject: [PATCH 1450/9938] i40e/i40evf: Bump patch from 1.4.25 to 1.5.1 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 38410050401c..297fd39ba255 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -45,8 +45,8 @@ static const char i40e_driver_string[] = #define DRV_KERN "-k" #define DRV_VERSION_MAJOR 1 -#define DRV_VERSION_MINOR 4 -#define DRV_VERSION_BUILD 25 +#define DRV_VERSION_MINOR 5 +#define DRV_VERSION_BUILD 1 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index d783c1b19a16..e3973684746b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -37,8 +37,8 @@ static const char i40evf_driver_string[] = #define DRV_KERN "-k" #define DRV_VERSION_MAJOR 1 -#define DRV_VERSION_MINOR 4 -#define DRV_VERSION_BUILD 15 +#define DRV_VERSION_MINOR 5 +#define DRV_VERSION_BUILD 1 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) \ -- GitLab From b100e5d622aa8719cc2e776c397817afe24b1f3b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 17 Mar 2016 15:41:37 +0200 Subject: [PATCH 1451/9938] mac80211: avoid useless memory write on each frame RX In the likely case that probe_count is 0, don't write to the memory there. Also use ifmgd consistently in the function, instead of using sdata->u.mgd as well. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 281b8d6e5109..2112df4ffb7b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -122,15 +122,16 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - if (unlikely(!sdata->u.mgd.associated)) + if (unlikely(!ifmgd->associated)) return; - ifmgd->probe_send_count = 0; + if (ifmgd->probe_send_count) + ifmgd->probe_send_count = 0; if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR)) return; - mod_timer(&sdata->u.mgd.conn_mon_timer, + mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); } -- GitLab From 17b942478643c5a90c06d978479bd326040bfa19 Mon Sep 17 00:00:00 2001 From: Ayala Beker Date: Thu, 17 Mar 2016 15:41:38 +0200 Subject: [PATCH 1452/9938] cfg80211: allow userspace to specify client P2P PS support Legacy clients don't support P2P power save mechanisms, and thus if a P2P GO has a legacy client connected to it, it has to make some changes in the PS behavior. To handle this, add an attribute to specify whether a station supports P2P PS or not. If the attribute was not specified cfg80211 will assume that station supports it for P2P GO interface, and does NOT support it for AP interface, matching the current assumptions in the code. Signed-off-by: Ayala Beker Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ include/uapi/linux/nl80211.h | 19 +++++++++++++++++++ net/wireless/nl80211.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4ece4f961f40..568c10f6d564 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -816,6 +816,7 @@ enum station_parameters_apply_mask { * @supported_oper_classes_len: number of supported operating classes * @opmode_notif: operating mode field from Operating Mode Notification * @opmode_notif_used: information if operating mode field is used + * @support_p2p_ps: information if station supports P2P PS mechanism */ struct station_parameters { const u8 *supported_rates; @@ -841,6 +842,7 @@ struct station_parameters { u8 supported_oper_classes_len; u8 opmode_notif; bool opmode_notif_used; + int support_p2p_ps; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b2a8d8c84a57..6da52d7b48c4 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1804,6 +1804,9 @@ enum nl80211_commands { * it contains the behaviour-specific attribute containing the parameters for * BSS selection to be done by driver and/or firmware. * + * @NL80211_ATTR_STA_SUPPORT_P2P_PS: whether P2P PS mechanism supported + * or not. u8, one of the values of &enum nl80211_sta_p2p_ps_status + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2182,6 +2185,8 @@ enum nl80211_attrs { NL80211_ATTR_BSS_SELECT, + NL80211_ATTR_STA_SUPPORT_P2P_PS, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2325,6 +2330,20 @@ enum nl80211_sta_flags { NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 }; +/** + * enum nl80211_sta_p2p_ps_status - station support of P2P PS + * + * @NL80211_P2P_PS_UNSUPPORTED: station doesn't support P2P PS mechanism + * @@NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism + * @NUM_NL80211_P2P_PS_STATUS: number of values + */ +enum nl80211_sta_p2p_ps_status { + NL80211_P2P_PS_UNSUPPORTED = 0, + NL80211_P2P_PS_SUPPORTED, + + NUM_NL80211_P2P_PS_STATUS, +}; + #define NL80211_STA_FLAG_MAX_OLD_API NL80211_STA_FLAG_TDLS_PEER /** diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d6c6449c0389..824569b1c5a1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -403,6 +403,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, [NL80211_ATTR_PBSS] = { .type = NLA_FLAG }, [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED }, + [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 }, }; /* policy for the key attributes */ @@ -4006,6 +4007,10 @@ int cfg80211_check_station_change(struct wiphy *wiphy, statype != CFG80211_STA_AP_CLIENT_UNASSOC) return -EINVAL; + if (params->support_p2p_ps != -1 && + statype != CFG80211_STA_AP_CLIENT_UNASSOC) + return -EINVAL; + if (params->aid && !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && statype != CFG80211_STA_AP_CLIENT_UNASSOC) @@ -4299,6 +4304,18 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) else params.listen_interval = -1; + if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) { + u8 tmp; + + tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]); + if (tmp >= NUM_NL80211_P2P_PS_STATUS) + return -EINVAL; + + params.support_p2p_ps = tmp; + } else { + params.support_p2p_ps = -1; + } + if (!info->attrs[NL80211_ATTR_MAC]) return -EINVAL; @@ -4422,6 +4439,23 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); + if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) { + u8 tmp; + + tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]); + if (tmp >= NUM_NL80211_P2P_PS_STATUS) + return -EINVAL; + + params.support_p2p_ps = tmp; + } else { + /* + * if not specified, assume it's supported for P2P GO interface, + * and is NOT supported for AP interface + */ + params.support_p2p_ps = + dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO; + } + if (info->attrs[NL80211_ATTR_PEER_AID]) params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); else -- GitLab From 52cfa1d6146c5aa48360b02533fc7e039a66086e Mon Sep 17 00:00:00 2001 From: Ayala Beker Date: Thu, 17 Mar 2016 15:41:39 +0200 Subject: [PATCH 1453/9938] mac80211: track and tell driver about GO client P2P PS abilities Legacy clients don't support P2P power save mechanism, and thus if a P2P GO has a legacy client connected to it, it should disable P2P PS mechanisms. Let the driver know about this with a new bss_conf parameter. Signed-off-by: Ayala Beker Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/mac80211.h | 8 +++++++- net/mac80211/cfg.c | 4 ++++ net/mac80211/sta_info.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a53333cb1528..6e346750cb29 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -291,7 +291,7 @@ struct ieee80211_vif_chanctx_switch { * @BSS_CHANGED_PS: PS changed for this BSS (STA mode) * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS) - * changed (currently only in P2P client mode, GO mode will be later) + * changed * @BSS_CHANGED_BEACON_INFO: Data from the AP's beacon became available: * currently dtim_period only is under consideration. * @BSS_CHANGED_BANDWIDTH: The bandwidth used by this interface changed, @@ -526,6 +526,9 @@ struct ieee80211_mu_group_data { * userspace), whereas TPC is disabled if %txpower_type is set to * NL80211_TX_POWER_FIXED (use value configured from userspace) * @p2p_noa_attr: P2P NoA attribute for P2P powersave + * @allow_p2p_go_ps: indication for AP or P2P GO interface, whether it's allowed + * to use P2P PS mechanism or not. AP/P2P GO is not allowed to use P2P PS + * if it has associated clients without P2P PS support. */ struct ieee80211_bss_conf { const u8 *bssid; @@ -563,6 +566,7 @@ struct ieee80211_bss_conf { int txpower; enum nl80211_tx_power_setting txpower_type; struct ieee80211_p2p_noa_attr p2p_noa_attr; + bool allow_p2p_go_ps; }; /** @@ -1741,6 +1745,7 @@ struct ieee80211_sta_rates { * size is min(max_amsdu_len, 7935) bytes. * Both additional HT limits must be enforced by the low level driver. * This is defined by the spec (IEEE 802.11-2012 section 8.3.2.2 NOTE 2). + * @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not. * @txq: per-TID data TX queues (if driver uses the TXQ abstraction) */ struct ieee80211_sta { @@ -1761,6 +1766,7 @@ struct ieee80211_sta { bool mfp; u8 max_amsdu_subframes; u16 max_amsdu_len; + bool support_p2p_ps; struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b37adb60c9cb..62a90f270f03 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -732,6 +732,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, sdata->vif.bss_conf.beacon_int = params->beacon_interval; sdata->vif.bss_conf.dtim_period = params->dtim_period; sdata->vif.bss_conf.enable_beacon = true; + sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p; sdata->vif.bss_conf.ssid_len = params->ssid_len; if (params->ssid_len) @@ -1202,6 +1203,9 @@ static int sta_apply_parameters(struct ieee80211_local *local, params->opmode_notif, band); } + if (params->support_p2p_ps >= 0) + sta->sta.support_p2p_ps = params->support_p2p_ps; + if (ieee80211_vif_is_mesh(&sdata->vif)) sta_apply_mesh_params(local, sta, params); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 00c82fb152c0..01e070c6e713 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1767,6 +1767,31 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, } EXPORT_SYMBOL(ieee80211_sta_set_buffered); +static void +ieee80211_recalc_p2p_go_ps_allowed(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + bool allow_p2p_go_ps = sdata->vif.p2p; + struct sta_info *sta; + + rcu_read_lock(); + list_for_each_entry_rcu(sta, &local->sta_list, list) { + if (sdata != sta->sdata || + !test_sta_flag(sta, WLAN_STA_ASSOC)) + continue; + if (!sta->sta.support_p2p_ps) { + allow_p2p_go_ps = false; + break; + } + } + rcu_read_unlock(); + + if (allow_p2p_go_ps != sdata->vif.bss_conf.allow_p2p_go_ps) { + sdata->vif.bss_conf.allow_p2p_go_ps = allow_p2p_go_ps; + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_P2P_PS); + } +} + int sta_info_move_state(struct sta_info *sta, enum ieee80211_sta_state new_state) { @@ -1828,12 +1853,16 @@ int sta_info_move_state(struct sta_info *sta, } else if (sta->sta_state == IEEE80211_STA_ASSOC) { clear_bit(WLAN_STA_ASSOC, &sta->_flags); ieee80211_recalc_min_chandef(sta->sdata); + if (!sta->sta.support_p2p_ps) + ieee80211_recalc_p2p_go_ps_allowed(sta->sdata); } break; case IEEE80211_STA_ASSOC: if (sta->sta_state == IEEE80211_STA_AUTH) { set_bit(WLAN_STA_ASSOC, &sta->_flags); ieee80211_recalc_min_chandef(sta->sdata); + if (!sta->sta.support_p2p_ps) + ieee80211_recalc_p2p_go_ps_allowed(sta->sdata); } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { if (sta->sdata->vif.type == NL80211_IFTYPE_AP || (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && -- GitLab From 749329594b5e0fb612b2de642a692323ddf661dd Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 18 Mar 2016 22:03:24 -0400 Subject: [PATCH 1454/9938] mac80211: mesh: fix crash in mesh_path_timer The mesh_path_reclaim() function, called from an rcu callback, cancels the mesh_path_timer associated with a mesh path. Unfortunately, this call can happen much later, perhaps after the hash table itself is destroyed. Such a situation led to the following crash in mesh_path_send_to_gates() when dereferencing the tbl pointer: [ 23.901661] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 [ 23.905516] IP: [] mesh_path_send_to_gates+0x2b/0x740 [ 23.908757] PGD 99ca067 PUD 99c4067 PMD 0 [ 23.910789] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 23.913485] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.5.0-rc6-wt+ #43 [ 23.916675] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014 [ 23.920471] task: ffffffff81685500 ti: ffffffff81678000 task.ti: ffffffff81678000 [ 23.922619] RIP: 0010:[] [] mesh_path_send_to_gates+0x2b/0x740 [ 23.925237] RSP: 0018:ffff88000b403d30 EFLAGS: 00010286 [ 23.926739] RAX: 0000000000000000 RBX: ffff880009bc0d20 RCX: 0000000000000102 [ 23.928796] RDX: 000000000000002e RSI: 0000000000000001 RDI: ffff880009bc0d20 [ 23.930895] RBP: ffff88000b403e18 R08: 0000000000000001 R09: 0000000000000001 [ 23.932917] R10: 0000000000000000 R11: 0000000000000001 R12: ffff880009c20940 [ 23.936370] R13: ffff880009bc0e70 R14: ffff880009c21c40 R15: ffff880009bc0d20 [ 23.939823] FS: 0000000000000000(0000) GS:ffff88000b400000(0000) knlGS:0000000000000000 [ 23.943688] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 23.946429] CR2: 0000000000000008 CR3: 00000000099c5000 CR4: 00000000000006b0 [ 23.949861] Stack: [ 23.950840] 000000000000002e ffff880009c20940 ffff88000b403da8 ffffffff8109e551 [ 23.954467] ffffffff82711be2 000000000000002e 0000000000000000 ffffffff8166a5f5 [ 23.958141] 0000000000685ce8 0000000000000246 ffff880009bc0d20 ffff880009c20940 [ 23.961801] Call Trace: [ 23.962987] [ 23.963963] [] ? vprintk_emit+0x351/0x5e0 [ 23.966782] [] ? vprintk_default+0x1f/0x30 [ 23.969529] [] ? printk+0x48/0x50 [ 23.971956] [] mesh_path_timer+0x133/0x160 [ 23.974707] [] ? mesh_nexthop_resolve+0x230/0x230 [ 23.977775] [] call_timer_fn+0xce/0x330 [ 23.980448] [] ? call_timer_fn+0x5/0x330 [ 23.983126] [] ? mesh_nexthop_resolve+0x230/0x230 [ 23.986091] [] run_timer_softirq+0x22c/0x390 Instead of cancelling in the RCU callback, set a new flag to prevent the timer from being rearmed, and then cancel the timer synchronously when freeing the mesh path. This leaves mesh_path_reclaim() doing nothing but kfree, so switch to kfree_rcu(). Fixes: 3b302ada7f0a ("mac80211: mesh: move path tables into if_mesh") Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh.h | 3 +++ net/mac80211/mesh_hwmp.c | 4 ++++ net/mac80211/mesh_pathtbl.c | 33 ++++++++++++++++++--------------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index cc6854db156e..e1415c952e9c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -32,6 +32,8 @@ * @MESH_PATH_RESOLVED: the mesh path can has been resolved * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination * already queued up, waiting for the discovery process to start. + * @MESH_PATH_DELETED: the mesh path has been deleted and should no longer + * be used * * MESH_PATH_RESOLVED is used by the mesh path timer to * decide when to stop or cancel the mesh path discovery. @@ -43,6 +45,7 @@ enum mesh_path_flags { MESH_PATH_FIXED = BIT(3), MESH_PATH_RESOLVED = BIT(4), MESH_PATH_REQ_QUEUED = BIT(5), + MESH_PATH_DELETED = BIT(6), }; /** diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 5b6aec1a0630..2748cf627ee3 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -1012,6 +1012,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) goto enddiscovery; spin_lock_bh(&mpath->state_lock); + if (mpath->flags & MESH_PATH_DELETED) { + spin_unlock_bh(&mpath->state_lock); + goto enddiscovery; + } mpath->flags &= ~MESH_PATH_REQ_QUEUED; if (preq_node->flags & PREQ_Q_F_START) { if (mpath->flags & MESH_PATH_RESOLVING) { diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 7455397f8c3b..1c9412a29ca3 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -18,6 +18,8 @@ #include "ieee80211_i.h" #include "mesh.h" +static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath); + static u32 mesh_table_hash(const void *addr, u32 len, u32 seed) { /* Use last four bytes of hw addr as hash index */ @@ -40,18 +42,12 @@ static inline bool mpath_expired(struct mesh_path *mpath) !(mpath->flags & MESH_PATH_FIXED); } -static void mesh_path_reclaim(struct rcu_head *rp) -{ - struct mesh_path *mpath = container_of(rp, struct mesh_path, rcu); - - del_timer_sync(&mpath->timer); - kfree(mpath); -} - -static void mesh_path_rht_free(void *ptr, void *unused_arg) +static void mesh_path_rht_free(void *ptr, void *tblptr) { struct mesh_path *mpath = ptr; - call_rcu(&mpath->rcu, mesh_path_reclaim); + struct mesh_table *tbl = tblptr; + + mesh_path_free_rcu(tbl, mpath); } static struct mesh_table *mesh_table_alloc(void) @@ -77,7 +73,7 @@ static struct mesh_table *mesh_table_alloc(void) static void mesh_table_free(struct mesh_table *tbl) { rhashtable_free_and_destroy(&tbl->rhead, - mesh_path_rht_free, NULL); + mesh_path_rht_free, tbl); kfree(tbl); } @@ -551,18 +547,25 @@ void mesh_plink_broken(struct sta_info *sta) rhashtable_walk_exit(&iter); } -static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath) +static void mesh_path_free_rcu(struct mesh_table *tbl, + struct mesh_path *mpath) { struct ieee80211_sub_if_data *sdata = mpath->sdata; - rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params); spin_lock_bh(&mpath->state_lock); - mpath->flags |= MESH_PATH_RESOLVING; + mpath->flags |= MESH_PATH_RESOLVING | MESH_PATH_DELETED; mesh_gate_del(tbl, mpath); - call_rcu(&mpath->rcu, mesh_path_reclaim); spin_unlock_bh(&mpath->state_lock); + del_timer_sync(&mpath->timer); atomic_dec(&sdata->u.mesh.mpaths); atomic_dec(&tbl->entries); + kfree_rcu(mpath, rcu); +} + +static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath) +{ + rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params); + mesh_path_free_rcu(tbl, mpath); } /** -- GitLab From 0aa7fabbd5d9da1f8a8fdc3e2837c532bcfa5664 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 18 Mar 2016 22:11:28 -0400 Subject: [PATCH 1455/9938] mac80211: mesh: handle failed alloc for rmc cache In the unlikely case that mesh_rmc_init() fails with -ENOMEM, the rmc pointer will be left as NULL but the interface is still operational because ieee80211_mesh_init_sdata() is not allowed to fail. If this happens, we would blindly dereference rmc when checking whether a multicast frame is in the cache. Instead just drop the frames in the forwarding path. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a216c439b6f2..d0d8eeaa8129 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -220,6 +220,9 @@ int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, u8 idx; struct rmc_entry *p, *n; + if (!rmc) + return -1; + /* Don't care about endianness since only match matters */ memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; -- GitLab From 47a0489ce1e518f4936c7fedb93b3d2abd7ccd2e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 18 Mar 2016 22:11:29 -0400 Subject: [PATCH 1456/9938] mac80211: mesh: use hlist for rmc cache The RMC cache has 256 list heads plus a u32, which puts it at the unfortunate size of 4104 bytes with padding. kmalloc() will then round this up to the next power-of-two, so we wind up actually using two pages here where most of the second is wasted. Switch to hlist heads here to reduce the structure size down to fit within a page. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 18 ++++++++++-------- net/mac80211/mesh.h | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index d0d8eeaa8129..1a2aaf461e98 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -174,22 +174,23 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) return -ENOMEM; sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; for (i = 0; i < RMC_BUCKETS; i++) - INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]); + INIT_HLIST_HEAD(&sdata->u.mesh.rmc->bucket[i]); return 0; } void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) { struct mesh_rmc *rmc = sdata->u.mesh.rmc; - struct rmc_entry *p, *n; + struct rmc_entry *p; + struct hlist_node *n; int i; if (!sdata->u.mesh.rmc) return; for (i = 0; i < RMC_BUCKETS; i++) { - list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { - list_del(&p->list); + hlist_for_each_entry_safe(p, n, &rmc->bucket[i], list) { + hlist_del(&p->list); kmem_cache_free(rm_cache, p); } } @@ -218,7 +219,8 @@ int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, u32 seqnum = 0; int entries = 0; u8 idx; - struct rmc_entry *p, *n; + struct rmc_entry *p; + struct hlist_node *n; if (!rmc) return -1; @@ -226,11 +228,11 @@ int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, /* Don't care about endianness since only match matters */ memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; - list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { + hlist_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { ++entries; if (time_after(jiffies, p->exp_time) || entries == RMC_QUEUE_MAX_LEN) { - list_del(&p->list); + hlist_del(&p->list); kmem_cache_free(rm_cache, p); --entries; } else if ((seqnum == p->seqnum) && ether_addr_equal(sa, p->sa)) @@ -244,7 +246,7 @@ int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, p->seqnum = seqnum; p->exp_time = jiffies + RMC_TIMEOUT; memcpy(p->sa, sa, ETH_ALEN); - list_add(&p->list, &rmc->bucket[idx]); + hlist_add_head(&p->list, &rmc->bucket[idx]); return 0; } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index e1415c952e9c..bc3f9a32b5a4 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -158,14 +158,14 @@ struct mesh_table { * that are found in the cache. */ struct rmc_entry { - struct list_head list; + struct hlist_node list; u32 seqnum; unsigned long exp_time; u8 sa[ETH_ALEN]; }; struct mesh_rmc { - struct list_head bucket[RMC_BUCKETS]; + struct hlist_head bucket[RMC_BUCKETS]; u32 idx_mask; }; -- GitLab From 18b27ff7d2e232b0f07f2f51aa8052ff2a617908 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 18 Mar 2016 22:11:30 -0400 Subject: [PATCH 1457/9938] mac80211: mesh: embed gates hlist head directly Since we have converted the mesh path tables to rhashtable, we are no longer swapping out the entire mesh_pathtbl pointer with RCU. As a result, we no longer need indirection to the hlist head for the gates list and can simply embed it, saving a pair of pointer-sized allocations. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh.h | 2 +- net/mac80211/mesh_pathtbl.c | 18 ++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index bc3f9a32b5a4..46b540a25d9d 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -134,7 +134,7 @@ struct mesh_path { */ struct mesh_table { atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ - struct hlist_head *known_gates; + struct hlist_head known_gates; spinlock_t gates_lock; struct rhashtable rhead; diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 1c9412a29ca3..6db2ddfa0695 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -58,12 +58,7 @@ static struct mesh_table *mesh_table_alloc(void) if (!newtbl) return NULL; - newtbl->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); - if (!newtbl->known_gates) { - kfree(newtbl); - return NULL; - } - INIT_HLIST_HEAD(newtbl->known_gates); + INIT_HLIST_HEAD(&newtbl->known_gates); atomic_set(&newtbl->entries, 0); spin_lock_init(&newtbl->gates_lock); @@ -341,7 +336,7 @@ int mesh_path_add_gate(struct mesh_path *mpath) mpath->sdata->u.mesh.num_gates++; spin_lock(&tbl->gates_lock); - hlist_add_head_rcu(&mpath->gate_list, tbl->known_gates); + hlist_add_head_rcu(&mpath->gate_list, &tbl->known_gates); spin_unlock(&tbl->gates_lock); spin_unlock_bh(&mpath->state_lock); @@ -759,16 +754,11 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) struct mesh_path *from_mpath = mpath; struct mesh_path *gate; bool copy = false; - struct hlist_head *known_gates; tbl = sdata->u.mesh.mesh_paths; - known_gates = tbl->known_gates; - - if (!known_gates) - return -EHOSTUNREACH; rcu_read_lock(); - hlist_for_each_entry_rcu(gate, known_gates, gate_list) { + hlist_for_each_entry_rcu(gate, &tbl->known_gates, gate_list) { if (gate->flags & MESH_PATH_ACTIVE) { mpath_dbg(sdata, "Forwarding to %pM\n", gate->dst); mesh_path_move_to_queue(gate, from_mpath, copy); @@ -781,7 +771,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) } } - hlist_for_each_entry_rcu(gate, known_gates, gate_list) { + hlist_for_each_entry_rcu(gate, &tbl->known_gates, gate_list) { mpath_dbg(sdata, "Sending to %pM\n", gate->dst); mesh_path_tx_pending(gate); } -- GitLab From 3257523bed496316dad95d5a341bfd49ac16624b Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 18 Mar 2016 22:11:31 -0400 Subject: [PATCH 1458/9938] mac80211: mesh: reorder structure members Reduce padding waste in struct mesh_table and struct rmc_entry by moving the smaller fields to the end. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 46b540a25d9d..4a59c034cc6d 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -133,11 +133,10 @@ struct mesh_path { * @rhash: the rhashtable containing struct mesh_paths, keyed by dest addr */ struct mesh_table { - atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ struct hlist_head known_gates; spinlock_t gates_lock; - struct rhashtable rhead; + atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ }; /* Recent multicast cache */ @@ -159,8 +158,8 @@ struct mesh_table { */ struct rmc_entry { struct hlist_node list; - u32 seqnum; unsigned long exp_time; + u32 seqnum; u8 sa[ETH_ALEN]; }; -- GitLab From 68bb54b47ea1130e57049d86d172d0e098edb3f4 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 18 Mar 2016 22:11:32 -0400 Subject: [PATCH 1459/9938] mac80211: mesh: fix mesh path kerneldoc Several of the mesh path fields are undocumented and some of the documentation is no longer correct or relevant after the switch to rhashtable. Clean up the kernel doc accordingly and reorder some fields to match the structure layout. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 4a59c034cc6d..f298987228c9 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -21,8 +21,6 @@ /** * enum mesh_path_flags - mac80211 mesh path flags * - * - * * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path * @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence @@ -70,12 +68,16 @@ enum mesh_deferred_task_flags { * struct mesh_path - mac80211 mesh path structure * * @dst: mesh path destination mac address + * @mpp: mesh proxy mac address + * @rhash: rhashtable list pointer + * @gate_list: list pointer for known gates list * @sdata: mesh subif * @next_hop: mesh neighbor to which frames for this destination will be * forwarded * @timer: mesh path discovery timer * @frame_queue: pending queue for frames sent to this destination while the * path is unresolved + * @rcu: rcu head for freeing mesh path * @sn: target sequence number * @metric: current metric to this destination * @hop_count: hops to destination @@ -94,10 +96,10 @@ enum mesh_deferred_task_flags { * @is_gate: the destination station of this path is a mesh gate * * - * The combination of dst and sdata is unique in the mesh path table. Since the - * next_hop STA is only protected by RCU as well, deleting the STA must also - * remove/substitute the mesh_path structure and wait until that is no longer - * reachable before destroying the STA completely. + * The dst address is unique in the mesh path table. Since the mesh_path is + * protected by RCU, deleting the next_hop STA must remove / substitute the + * mesh_path structure and wait until that is no longer reachable before + * destroying the STA completely. */ struct mesh_path { u8 dst[ETH_ALEN]; @@ -127,10 +129,11 @@ struct mesh_path { /** * struct mesh_table * - * @entries: number of entries in the table * @known_gates: list of known mesh gates and their mpaths by the station. The * gate's mpath may or may not be resolved and active. - * @rhash: the rhashtable containing struct mesh_paths, keyed by dest addr + * @gates_lock: protects updates to known_gates + * @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr + * @entries: number of entries in the table */ struct mesh_table { struct hlist_head known_gates; @@ -151,6 +154,7 @@ struct mesh_table { * @seqnum: mesh sequence number of the frame * @exp_time: expiration time of the entry, in jiffies * @sa: source address of the frame + * @list: hashtable list pointer * * The Recent Multicast Cache keeps track of the latest multicast frames that * have been received by a mesh interface and discards received multicast frames -- GitLab From 0371a08fbb3e557f19db41e47a199ad8300c9c97 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 26 Mar 2016 11:27:18 -0400 Subject: [PATCH 1460/9938] mac80211: mesh: fix cleanup for mesh pathtable The mesh path table needs to be around for the entire time the interface is in mesh mode, as users can perform an mpath dump at any time. The existing path table lifetime is instead tied to the mesh BSS which can cause crashes when different MBSSes are joined in the context of a single interface, or when the path table is dumped when no MBSS is joined. Introduce a new function to perform the final teardown of the interface and perform path table cleanup there. We already free the individual path elements when the leaving the mesh so no additional cleanup is needed there. This fixes the following crash: [ 47.753026] BUG: unable to handle kernel paging request at fffffff0 [ 47.753026] IP: [] kthread_data+0xa/0xe [ 47.753026] *pde = 00741067 *pte = 00000000 [ 47.753026] Oops: 0000 [#4] PREEMPT [ 47.753026] Modules linked in: ppp_generic slhc 8021q garp mrp sch_fq_codel iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat ip_tables ath9k_htc ath5k 8139too ath10k_pci ath10k_core arc4 ath9k ath9k_common ath9k_hw mac80211 ath cfg80211 cpufreq_powersave br_netfilter bridge stp llc ipw usb_wwan sierra_net usbnet af_alg natsemi via_rhine mii iTCO_wdt iTCO_vendor_support gpio_ich sierra coretemp pcspkr i2c_i801 lpc_ich ata_generic ata_piix libata ide_pci_generic piix e1000e igb i2c_algo_bit ptp pps_core [last unloaded: 8139too] [ 47.753026] CPU: 0 PID: 12 Comm: kworker/u2:1 Tainted: G D W 4.5.0-wt-V3 #6 [ 47.753026] Hardware name: To Be Filled By O.E.M./To be filled by O.E.M., BIOS 080016 11/07/2014 [ 47.753026] task: f645a0c0 ti: f6462000 task.ti: f6462000 [ 47.753026] EIP: 0060:[] EFLAGS: 00010002 CPU: 0 [ 47.753026] EIP is at kthread_data+0xa/0xe [ 47.753026] EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000000 [ 47.753026] ESI: f645a0c0 EDI: f645a2fc EBP: f6463a80 ESP: f6463a78 [ 47.753026] DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 [ 47.753026] CR0: 8005003b CR2: 00000014 CR3: 353e5000 CR4: 00000690 [ 47.753026] Stack: [ 47.753026] c0236866 00000000 f6463aac c05768b4 00000009 f6463ba8 f6463ab0 c0247010 [ 47.753026] 00000000 f645a0c0 f6464000 00000009 f6463ba8 f6463ab8 c0576eb2 f645a0c0 [ 47.753026] f6463aec c0228be4 c06335a4 f6463adc f6463ad0 c06c06d4 f6463ae4 c02471b0 [ 47.753026] Call Trace: [ 47.753026] [] ? wq_worker_sleeping+0xb/0x78 [ 47.753026] [] __schedule+0xda/0x587 [ 47.753026] [] ? vprintk_default+0x12/0x14 [ 47.753026] [] schedule+0x72/0x89 [ 47.753026] [] do_exit+0xb8/0x71d [ 47.753026] [] ? kmsg_dump+0xa9/0xae [ 47.753026] [] oops_end+0x69/0x70 [ 47.753026] [] no_context+0x1bb/0x1c5 [ 47.753026] [] __bad_area_nosemaphore+0x136/0x140 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] bad_area_nosemaphore+0xd/0x10 [ 47.753026] [] __do_page_fault+0x26c/0x320 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] do_page_fault+0xb/0xd [ 47.753026] [] error_code+0x58/0x60 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] ? kthread_data+0xa/0xe [ 47.753026] [] ? wq_worker_sleeping+0xb/0x78 [ 47.753026] [] __schedule+0xda/0x587 [ 47.753026] [] ? vprintk_default+0x12/0x14 [ 47.753026] [] schedule+0x72/0x89 [ 47.753026] [] do_exit+0xb8/0x71d [ 47.753026] [] ? kmsg_dump+0xa9/0xae [ 47.753026] [] oops_end+0x69/0x70 [ 47.753026] [] no_context+0x1bb/0x1c5 [ 47.753026] [] __bad_area_nosemaphore+0x136/0x140 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] bad_area_nosemaphore+0xd/0x10 [ 47.753026] [] __do_page_fault+0x26c/0x320 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] do_page_fault+0xb/0xd [ 47.753026] [] error_code+0x58/0x60 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] ? kthread_data+0xa/0xe [ 47.753026] [] ? wq_worker_sleeping+0xb/0x78 [ 47.753026] [] __schedule+0xda/0x587 [ 47.753026] [] ? put_io_context_active+0x6d/0x95 [ 47.753026] [] schedule+0x72/0x89 [ 47.753026] [] do_exit+0x6cc/0x71d [ 47.753026] [] oops_end+0x69/0x70 [ 47.753026] [] no_context+0x1bb/0x1c5 [ 47.753026] [] __bad_area_nosemaphore+0x136/0x140 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] bad_area_nosemaphore+0xd/0x10 [ 47.753026] [] __do_page_fault+0x26c/0x320 [ 47.753026] [] ? debug_smp_processor_id+0x12/0x16 [ 47.753026] [] ? __switch_to+0x24/0x40e [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] do_page_fault+0xb/0xd [ 47.753026] [] error_code+0x58/0x60 [ 47.753026] [] ? vmalloc_sync_all+0x19a/0x19a [ 47.753026] [] ? rhashtable_walk_init+0x5c/0x93 [ 47.753026] [] mesh_path_tbl_expire.isra.24+0x19/0x82 [mac80211] [ 47.753026] [] mesh_path_expire+0x11/0x1f [mac80211] [ 47.753026] [] ieee80211_mesh_work+0x73/0x1a9 [mac80211] [ 47.753026] [] ieee80211_iface_work+0x2ff/0x311 [mac80211] [ 47.753026] [] process_one_work+0x14b/0x24e [ 47.753026] [] worker_thread+0x249/0x343 [ 47.753026] [] ? process_scheduled_works+0x24/0x24 [ 47.753026] [] kthread+0x9e/0xa3 [ 47.753026] [] ret_from_kernel_thread+0x20/0x40 [ 47.753026] [] ? kthread_parkme+0x18/0x18 [ 47.753026] Code: 6b c0 85 c0 75 05 e8 fb 74 fc ff 89 f8 84 c0 75 08 8d 45 e8 e8 34 dd 33 00 83 c4 28 5b 5e 5f 5d c3 55 8b 80 10 02 00 00 89 e5 5d <8b> 40 f0 c3 55 b9 04 00 00 00 89 e5 52 8b 90 10 02 00 00 8d 45 [ 47.753026] EIP: [] kthread_data+0xa/0xe SS:ESP 0068:f6463a78 [ 47.753026] CR2: 00000000fffffff0 [ 47.753026] ---[ end trace 867ca0bdd0767790 ]--- Fixes: 3b302ada7f0a ("mac80211: mesh: move path tables into if_mesh") Reported-by: Fred Veldini Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 2 +- net/mac80211/mesh.c | 7 ++++++- net/mac80211/mesh.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 453b4e741780..097ece8b5c02 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1093,7 +1093,7 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) sdata->fragment_next = 0; if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rmc_free(sdata); + ieee80211_mesh_teardown_sdata(sdata); } static void ieee80211_uninit(struct net_device *dev) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 1a2aaf461e98..dcc1facc807c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -905,7 +905,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) /* flush STAs and mpaths on this iface */ sta_info_flush(sdata); mesh_path_flush_by_iface(sdata); - mesh_pathtbl_unregister(sdata); /* free all potentially still buffered group-addressed frames */ local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf); @@ -1403,3 +1402,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.bssid = zero_addr; } + +void ieee80211_mesh_teardown_sdata(struct ieee80211_sub_if_data *sdata) +{ + mesh_rmc_free(sdata); + mesh_pathtbl_unregister(sdata); +} diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index f298987228c9..26b9ccbe1fce 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -219,6 +219,7 @@ void ieee80211s_init(void); void ieee80211s_update_metric(struct ieee80211_local *local, struct sta_info *sta, struct sk_buff *skb); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); +void ieee80211_mesh_teardown_sdata(struct ieee80211_sub_if_data *sdata); int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); -- GitLab From e596af827960c41a6051d4e719bafcfb7da11b64 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 26 Mar 2016 11:27:19 -0400 Subject: [PATCH 1461/9938] mac80211: mesh: flush paths outside of plink lock Lockdep warned of a lock dependency between the mesh_plink lock and the internal lock for the rhashtable. The problem is that the rhashtable code uses a spin lock with softirqs enabled, while mesh_plink_timer executes a walk (to flush paths on a state change) inside a softirq with the plink lock held. This leads to the following deadlock if the timer fires while rht lock is held on this CPU, and plink lock is held on another CPU: CPU0 CPU1 ---- ---- lock(&(&ht->lock)->rlock); local_irq_disable(); lock(&(&sta->mesh->plink_lock)->rlock); lock(&(&ht->lock)->rlock); lock(&(&sta->mesh->plink_lock)->rlock); *** DEADLOCK *** Fix by waiting until we drop the plink lock to flush paths. Fixes: d48a1b7cd439 ("mac80211: mesh: convert path table to rhashtable") Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh_plink.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index a07e93c21c9e..ecfba8ad29e4 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -331,7 +331,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, * * @sta: mesh peer link to deactivate * - * All mesh paths with this peer as next hop will be flushed + * Mesh paths with this peer as next hop should be flushed + * by the caller outside of plink_lock. + * * Returns beacon changed flag if the beacon content changed. * * Locking: the caller must hold sta->mesh->plink_lock @@ -346,7 +348,6 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) if (sta->mesh->plink_state == NL80211_PLINK_ESTAB) changed = mesh_plink_dec_estab_count(sdata); sta->mesh->plink_state = NL80211_PLINK_BLOCKED; - mesh_path_flush_by_nexthop(sta); ieee80211_mps_sta_status_update(sta); changed |= ieee80211_mps_set_sta_local_pm(sta, @@ -374,6 +375,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta) sta->sta.addr, sta->mesh->llid, sta->mesh->plid, sta->mesh->reason); spin_unlock_bh(&sta->mesh->plink_lock); + mesh_path_flush_by_nexthop(sta); return changed; } @@ -748,6 +750,7 @@ u32 mesh_plink_block(struct sta_info *sta) changed = __mesh_plink_deactivate(sta); sta->mesh->plink_state = NL80211_PLINK_BLOCKED; spin_unlock_bh(&sta->mesh->plink_lock); + mesh_path_flush_by_nexthop(sta); return changed; } @@ -797,6 +800,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; enum ieee80211_self_protected_actioncode action = 0; u32 changed = 0; + bool flush = false; mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr, mplstates[sta->mesh->plink_state], mplevents[event]); @@ -885,6 +889,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, changed |= mesh_set_short_slot_time(sdata); mesh_plink_close(sdata, sta, event); action = WLAN_SP_MESH_PEERING_CLOSE; + flush = true; break; case OPN_ACPT: action = WLAN_SP_MESH_PEERING_CONFIRM; @@ -916,6 +921,8 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, break; } spin_unlock_bh(&sta->mesh->plink_lock); + if (flush) + mesh_path_flush_by_nexthop(sta); if (action) { mesh_plink_frame_tx(sdata, sta, action, sta->sta.addr, sta->mesh->llid, sta->mesh->plid, -- GitLab From 1aab144c507a9849d5b4557d6d78db185ceaef37 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 22 Dec 2015 13:43:44 -0800 Subject: [PATCH 1462/9938] fm10k: Move constants to the right of binary operators The semantic patch that makes this change is available in scripts/coccinelle/misc/compare_const_fl.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 16 ++++++++-------- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 4de17db3808c..d411aa506661 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -420,7 +420,7 @@ static inline void fm10k_rx_hash(struct fm10k_ring *ring, return; skb_set_hash(skb, le32_to_cpu(rx_desc->d.rss), - (FM10K_RSS_L4_TYPES_MASK & (1ul << rss_type)) ? + ((1ul << rss_type) & FM10K_RSS_L4_TYPES_MASK) ? PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 4eb7a6fa6b0d..86700a45fe13 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -579,7 +579,7 @@ static void fm10k_configure_tx_ring(struct fm10k_intfc *interface, u64 tdba = ring->dma; u32 size = ring->count * sizeof(struct fm10k_tx_desc); u32 txint = FM10K_INT_MAP_DISABLE; - u32 txdctl = FM10K_TXDCTL_ENABLE | (1 << FM10K_TXDCTL_MAX_TIME_SHIFT); + u32 txdctl = (1 << FM10K_TXDCTL_MAX_TIME_SHIFT) | FM10K_TXDCTL_ENABLE; u8 reg_idx = ring->reg_idx; /* disable queue to avoid issues while updating state */ @@ -903,8 +903,8 @@ static irqreturn_t fm10k_msix_mbx_vf(int __always_unused irq, void *data) /* re-enable mailbox interrupt and indicate 20us delay */ fm10k_write_reg(hw, FM10K_VFITR(FM10K_MBX_VECTOR), - FM10K_ITR_ENABLE | (FM10K_MBX_INT_DELAY >> - hw->mac.itr_scale)); + (FM10K_MBX_INT_DELAY >> hw->mac.itr_scale) | + FM10K_ITR_ENABLE); /* service upstream mailbox */ if (fm10k_mbx_trylock(interface)) { @@ -1135,8 +1135,8 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) /* re-enable mailbox interrupt and indicate 20us delay */ fm10k_write_reg(hw, FM10K_ITR(FM10K_MBX_VECTOR), - FM10K_ITR_ENABLE | (FM10K_MBX_INT_DELAY >> - hw->mac.itr_scale)); + (FM10K_MBX_INT_DELAY >> hw->mac.itr_scale) | + FM10K_ITR_ENABLE); return IRQ_HANDLED; } @@ -1253,7 +1253,7 @@ static int fm10k_mbx_request_irq_vf(struct fm10k_intfc *interface) int err; /* Use timer0 for interrupt moderation on the mailbox */ - u32 itr = FM10K_INT_MAP_TIMER0 | entry->entry; + u32 itr = entry->entry | FM10K_INT_MAP_TIMER0; /* register mailbox handlers */ err = hw->mbx.ops.register_handlers(&hw->mbx, vf_mbx_data); @@ -1420,8 +1420,8 @@ static int fm10k_mbx_request_irq_pf(struct fm10k_intfc *interface) int err; /* Use timer0 for interrupt moderation on the mailbox */ - u32 mbx_itr = FM10K_INT_MAP_TIMER0 | entry->entry; - u32 other_itr = FM10K_INT_MAP_IMMEDIATE | entry->entry; + u32 mbx_itr = entry->entry | FM10K_INT_MAP_TIMER0; + u32 other_itr = entry->entry | FM10K_INT_MAP_IMMEDIATE; /* register mailbox handlers */ err = hw->mbx.ops.register_handlers(&hw->mbx, pf_mbx_data); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 62ccebc5f728..34a0b035887d 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -711,8 +711,8 @@ static s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs, FM10K_RXDCTL_WRITE_BACK_MIN_DELAY | FM10K_RXDCTL_DROP_ON_EMPTY); fm10k_write_reg(hw, FM10K_RXQCTL(vf_q_idx), - FM10K_RXQCTL_VF | - (i << FM10K_RXQCTL_VF_SHIFT)); + (i << FM10K_RXQCTL_VF_SHIFT) | + FM10K_RXQCTL_VF); /* map queue pair to VF */ fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), vf_q_idx); @@ -987,7 +987,7 @@ static s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) | (vf_idx << FM10K_TXQCTL_TC_SHIFT) | FM10K_TXQCTL_VF | vf_idx; - rxqctl = FM10K_RXQCTL_VF | (vf_idx << FM10K_RXQCTL_VF_SHIFT); + rxqctl = (vf_idx << FM10K_RXQCTL_VF_SHIFT) | FM10K_RXQCTL_VF; /* stop further DMA and reset queue ownership back to VF */ for (i = vf_q_idx; i < (queues_per_pool + vf_q_idx); i++) { -- GitLab From fcdb0a9951d8a5edfc47e89a7fe62457c25e18c4 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 22 Dec 2015 13:43:49 -0800 Subject: [PATCH 1463/9938] fm10k: cleanup remaining right-bit-shifted 1 Use BIT() macro instead. Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k.h | 12 +++++----- .../net/ethernet/intel/fm10k/fm10k_ethtool.c | 20 +++++++--------- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 20 ++++++++-------- .../net/ethernet/intel/fm10k/fm10k_netdev.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 8 +++---- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 12 +++++----- drivers/net/ethernet/intel/fm10k/fm10k_tlv.c | 24 +++++++++---------- drivers/net/ethernet/intel/fm10k/fm10k_type.h | 8 +++---- 8 files changed, 52 insertions(+), 54 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index b34bb008b104..83f386714e87 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -262,12 +262,12 @@ struct fm10k_intfc { unsigned long state; u32 flags; -#define FM10K_FLAG_RESET_REQUESTED (u32)(1 << 0) -#define FM10K_FLAG_RSS_FIELD_IPV4_UDP (u32)(1 << 1) -#define FM10K_FLAG_RSS_FIELD_IPV6_UDP (u32)(1 << 2) -#define FM10K_FLAG_RX_TS_ENABLED (u32)(1 << 3) -#define FM10K_FLAG_SWPRI_CONFIG (u32)(1 << 4) -#define FM10K_FLAG_DEBUG_STATS (u32)(1 << 5) +#define FM10K_FLAG_RESET_REQUESTED (u32)(BIT(0)) +#define FM10K_FLAG_RSS_FIELD_IPV4_UDP (u32)(BIT(1)) +#define FM10K_FLAG_RSS_FIELD_IPV6_UDP (u32)(BIT(2)) +#define FM10K_FLAG_RX_TS_ENABLED (u32)(BIT(3)) +#define FM10K_FLAG_SWPRI_CONFIG (u32)(BIT(4)) +#define FM10K_FLAG_DEBUG_STATS (u32)(BIT(5)) int xcast_mode; /* Tx fast path data */ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 2f6a05b57228..28837ae099df 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -425,7 +425,7 @@ static void fm10k_get_regs(struct net_device *netdev, u32 *buff = p; u16 i; - regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; + regs->version = BIT(24) | (hw->revision_id << 16) | hw->device_id; switch (hw->mac.type) { case fm10k_mac_pf: @@ -942,8 +942,8 @@ static int fm10k_mbx_test(struct fm10k_intfc *interface, u64 *data) return 0; /* loop through both nested and unnested attribute types */ - for (attr_flag = (1 << FM10K_TEST_MSG_UNSET); - attr_flag < (1 << (2 * FM10K_TEST_MSG_NESTED)); + for (attr_flag = BIT(FM10K_TEST_MSG_UNSET); + attr_flag < BIT(2 * FM10K_TEST_MSG_NESTED); attr_flag += attr_flag) { /* generate message to be tested */ fm10k_tlv_msg_test_create(test_msg, attr_flag); @@ -1005,7 +1005,7 @@ static u32 fm10k_get_priv_flags(struct net_device *netdev) u32 priv_flags = 0; if (interface->flags & FM10K_FLAG_DEBUG_STATS) - priv_flags |= 1 << FM10K_PRV_FLAG_DEBUG_STATS; + priv_flags |= BIT(FM10K_PRV_FLAG_DEBUG_STATS); return priv_flags; } @@ -1014,10 +1014,10 @@ static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags) { struct fm10k_intfc *interface = netdev_priv(netdev); - if (priv_flags >= (1 << FM10K_PRV_FLAG_LEN)) + if (priv_flags >= BIT(FM10K_PRV_FLAG_LEN)) return -EINVAL; - if (priv_flags & (1 << FM10K_PRV_FLAG_DEBUG_STATS)) + if (priv_flags & BIT(FM10K_PRV_FLAG_DEBUG_STATS)) interface->flags |= FM10K_FLAG_DEBUG_STATS; else interface->flags &= ~FM10K_FLAG_DEBUG_STATS; @@ -1145,7 +1145,7 @@ static unsigned int fm10k_max_channels(struct net_device *dev) /* For QoS report channels per traffic class */ if (tcs > 1) - max_combined = 1 << (fls(max_combined / tcs) - 1); + max_combined = BIT((fls(max_combined / tcs) - 1)); return max_combined; } @@ -1210,11 +1210,9 @@ static int fm10k_get_ts_info(struct net_device *dev, else info->phc_index = -1; - info->tx_types = (1 << HWTSTAMP_TX_OFF) | - (1 << HWTSTAMP_TX_ON); + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); - info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | - (1 << HWTSTAMP_FILTER_ALL); + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); return 0; } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index d411aa506661..db4353ba0932 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -401,10 +401,10 @@ static inline void fm10k_rx_checksum(struct fm10k_ring *ring, } #define FM10K_RSS_L4_TYPES_MASK \ - ((1ul << FM10K_RSSTYPE_IPV4_TCP) | \ - (1ul << FM10K_RSSTYPE_IPV4_UDP) | \ - (1ul << FM10K_RSSTYPE_IPV6_TCP) | \ - (1ul << FM10K_RSSTYPE_IPV6_UDP)) + (BIT(FM10K_RSSTYPE_IPV4_TCP) | \ + BIT(FM10K_RSSTYPE_IPV4_UDP) | \ + BIT(FM10K_RSSTYPE_IPV6_TCP) | \ + BIT(FM10K_RSSTYPE_IPV6_UDP)) static inline void fm10k_rx_hash(struct fm10k_ring *ring, union fm10k_rx_desc *rx_desc, @@ -420,7 +420,7 @@ static inline void fm10k_rx_hash(struct fm10k_ring *ring, return; skb_set_hash(skb, le32_to_cpu(rx_desc->d.rss), - ((1ul << rss_type) & FM10K_RSS_L4_TYPES_MASK) ? + (BIT(rss_type) & FM10K_RSS_L4_TYPES_MASK) ? PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); } @@ -1409,7 +1409,7 @@ static void fm10k_update_itr(struct fm10k_ring_container *ring_container) * accounts for changes in the ITR due to PCIe link speed. */ itr_round = ACCESS_ONCE(ring_container->itr_scale) + 8; - avg_wire_size += (1 << itr_round) - 1; + avg_wire_size += BIT(itr_round) - 1; avg_wire_size >>= itr_round; /* write back value and retain adaptive flag */ @@ -1511,17 +1511,17 @@ static bool fm10k_set_qos_queues(struct fm10k_intfc *interface) /* set QoS mask and indices */ f = &interface->ring_feature[RING_F_QOS]; f->indices = pcs; - f->mask = (1 << fls(pcs - 1)) - 1; + f->mask = BIT(fls(pcs - 1)) - 1; /* determine the upper limit for our current DCB mode */ rss_i = interface->hw.mac.max_queues / pcs; - rss_i = 1 << (fls(rss_i) - 1); + rss_i = BIT(fls(rss_i) - 1); /* set RSS mask and indices */ f = &interface->ring_feature[RING_F_RSS]; rss_i = min_t(u16, rss_i, f->limit); f->indices = rss_i; - f->mask = (1 << fls(rss_i - 1)) - 1; + f->mask = BIT(fls(rss_i - 1)) - 1; /* configure pause class to queue mapping */ for (i = 0; i < pcs; i++) @@ -1551,7 +1551,7 @@ static bool fm10k_set_rss_queues(struct fm10k_intfc *interface) /* record indices and power of 2 mask for RSS */ f->indices = rss_i; - f->mask = (1 << fls(rss_i - 1)) - 1; + f->mask = BIT(fls(rss_i - 1)) - 1; interface->num_rx_queues = rss_i; interface->num_tx_queues = rss_i; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index d09a8dd71fc2..0ff68747c6c4 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1429,7 +1429,7 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info) /* configure default debug level */ interface = netdev_priv(dev); - interface->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1; + interface->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1; /* configure default features */ dev->features |= NETIF_F_IP_CSUM | diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 86700a45fe13..c9324c79c879 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -579,7 +579,7 @@ static void fm10k_configure_tx_ring(struct fm10k_intfc *interface, u64 tdba = ring->dma; u32 size = ring->count * sizeof(struct fm10k_tx_desc); u32 txint = FM10K_INT_MAP_DISABLE; - u32 txdctl = (1 << FM10K_TXDCTL_MAX_TIME_SHIFT) | FM10K_TXDCTL_ENABLE; + u32 txdctl = BIT(FM10K_TXDCTL_MAX_TIME_SHIFT) | FM10K_TXDCTL_ENABLE; u8 reg_idx = ring->reg_idx; /* disable queue to avoid issues while updating state */ @@ -730,7 +730,7 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface, if (interface->pfc_en) rx_pause = interface->pfc_en; #endif - if (!(rx_pause & (1 << ring->qos_pc))) + if (!(rx_pause & BIT(ring->qos_pc))) rxdctl |= FM10K_RXDCTL_DROP_ON_EMPTY; fm10k_write_reg(hw, FM10K_RXDCTL(reg_idx), rxdctl); @@ -779,7 +779,7 @@ void fm10k_update_rx_drop_en(struct fm10k_intfc *interface) u32 rxdctl = FM10K_RXDCTL_WRITE_BACK_MIN_DELAY; u8 reg_idx = ring->reg_idx; - if (!(rx_pause & (1 << ring->qos_pc))) + if (!(rx_pause & BIT(ring->qos_pc))) rxdctl |= FM10K_RXDCTL_DROP_ON_EMPTY; fm10k_write_reg(hw, FM10K_RXDCTL(reg_idx), rxdctl); @@ -1065,7 +1065,7 @@ static void fm10k_reset_drop_on_empty(struct fm10k_intfc *interface, u32 eicr) if (maxholdq) fm10k_write_reg(hw, FM10K_MAXHOLDQ(7), maxholdq); for (q = 255;;) { - if (maxholdq & (1 << 31)) { + if (maxholdq & BIT(31)) { if (q < FM10K_MAX_QUEUES_PF) { interface->rx_overrun_pf++; fm10k_write_reg(hw, FM10K_RXDCTL(q), rxdctl); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 34a0b035887d..23de956d1acc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -527,8 +527,8 @@ static s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw, return FM10K_ERR_PARAM; /* determine count of VSIs and queues */ - queue_count = 1 << (dglort->rss_l + dglort->pc_l); - vsi_count = 1 << (dglort->vsi_l + dglort->queue_l); + queue_count = BIT(dglort->rss_l + dglort->pc_l); + vsi_count = BIT(dglort->vsi_l + dglort->queue_l); glort = dglort->glort; q_idx = dglort->queue_b; @@ -544,8 +544,8 @@ static s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw, } /* determine count of PCs and queues */ - queue_count = 1 << (dglort->queue_l + dglort->rss_l + dglort->vsi_l); - pc_count = 1 << dglort->pc_l; + queue_count = BIT(dglort->queue_l + dglort->rss_l + dglort->vsi_l); + pc_count = BIT(dglort->pc_l); /* configure PC for Tx queues */ for (pc = 0; pc < pc_count; pc++) { @@ -952,7 +952,7 @@ static s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, return FM10K_ERR_PARAM; /* clear event notification of VF FLR */ - fm10k_write_reg(hw, FM10K_PFVFLREC(vf_idx / 32), 1 << (vf_idx % 32)); + fm10k_write_reg(hw, FM10K_PFVFLREC(vf_idx / 32), BIT(vf_idx % 32)); /* force timeout and then disconnect the mailbox */ vf_info->mbx.timeout = 0; @@ -1370,7 +1370,7 @@ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, mode = fm10k_iov_supported_xcast_mode_pf(vf_info, mode); /* if mode is not currently enabled, enable it */ - if (!(FM10K_VF_FLAG_ENABLED(vf_info) & (1 << mode))) + if (!(FM10K_VF_FLAG_ENABLED(vf_info) & BIT(mode))) fm10k_update_xcast_mode_pf(hw, vf_info->glort, mode); /* swap mode back to a bit flag */ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c index ab01bb30752f..b999897e50d8 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c @@ -222,7 +222,7 @@ s32 fm10k_tlv_attr_put_value(u32 *msg, u16 attr_id, s64 value, u32 len) attr = &msg[FM10K_TLV_DWORD_LEN(*msg)]; if (len < 4) { - attr[1] = (u32)value & ((0x1ul << (8 * len)) - 1); + attr[1] = (u32)value & (BIT(8 * len) - 1); } else { attr[1] = (u32)value; if (len > 4) @@ -652,29 +652,29 @@ const struct fm10k_tlv_attr fm10k_tlv_msg_test_attr[] = { **/ static void fm10k_tlv_msg_test_generate_data(u32 *msg, u32 attr_flags) { - if (attr_flags & (1 << FM10K_TEST_MSG_STRING)) + if (attr_flags & BIT(FM10K_TEST_MSG_STRING)) fm10k_tlv_attr_put_null_string(msg, FM10K_TEST_MSG_STRING, test_str); - if (attr_flags & (1 << FM10K_TEST_MSG_MAC_ADDR)) + if (attr_flags & BIT(FM10K_TEST_MSG_MAC_ADDR)) fm10k_tlv_attr_put_mac_vlan(msg, FM10K_TEST_MSG_MAC_ADDR, test_mac, test_vlan); - if (attr_flags & (1 << FM10K_TEST_MSG_U8)) + if (attr_flags & BIT(FM10K_TEST_MSG_U8)) fm10k_tlv_attr_put_u8(msg, FM10K_TEST_MSG_U8, test_u8); - if (attr_flags & (1 << FM10K_TEST_MSG_U16)) + if (attr_flags & BIT(FM10K_TEST_MSG_U16)) fm10k_tlv_attr_put_u16(msg, FM10K_TEST_MSG_U16, test_u16); - if (attr_flags & (1 << FM10K_TEST_MSG_U32)) + if (attr_flags & BIT(FM10K_TEST_MSG_U32)) fm10k_tlv_attr_put_u32(msg, FM10K_TEST_MSG_U32, test_u32); - if (attr_flags & (1 << FM10K_TEST_MSG_U64)) + if (attr_flags & BIT(FM10K_TEST_MSG_U64)) fm10k_tlv_attr_put_u64(msg, FM10K_TEST_MSG_U64, test_u64); - if (attr_flags & (1 << FM10K_TEST_MSG_S8)) + if (attr_flags & BIT(FM10K_TEST_MSG_S8)) fm10k_tlv_attr_put_s8(msg, FM10K_TEST_MSG_S8, test_s8); - if (attr_flags & (1 << FM10K_TEST_MSG_S16)) + if (attr_flags & BIT(FM10K_TEST_MSG_S16)) fm10k_tlv_attr_put_s16(msg, FM10K_TEST_MSG_S16, test_s16); - if (attr_flags & (1 << FM10K_TEST_MSG_S32)) + if (attr_flags & BIT(FM10K_TEST_MSG_S32)) fm10k_tlv_attr_put_s32(msg, FM10K_TEST_MSG_S32, test_s32); - if (attr_flags & (1 << FM10K_TEST_MSG_S64)) + if (attr_flags & BIT(FM10K_TEST_MSG_S64)) fm10k_tlv_attr_put_s64(msg, FM10K_TEST_MSG_S64, test_s64); - if (attr_flags & (1 << FM10K_TEST_MSG_LE_STRUCT)) + if (attr_flags & BIT(FM10K_TEST_MSG_LE_STRUCT)) fm10k_tlv_attr_put_le_struct(msg, FM10K_TEST_MSG_LE_STRUCT, test_le, 8); } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index 854ebb1906bf..5c0533054c5f 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -617,10 +617,10 @@ struct fm10k_vf_info { */ }; -#define FM10K_VF_FLAG_ALLMULTI_CAPABLE ((u8)1 << FM10K_XCAST_MODE_ALLMULTI) -#define FM10K_VF_FLAG_MULTI_CAPABLE ((u8)1 << FM10K_XCAST_MODE_MULTI) -#define FM10K_VF_FLAG_PROMISC_CAPABLE ((u8)1 << FM10K_XCAST_MODE_PROMISC) -#define FM10K_VF_FLAG_NONE_CAPABLE ((u8)1 << FM10K_XCAST_MODE_NONE) +#define FM10K_VF_FLAG_ALLMULTI_CAPABLE (u8)(BIT(FM10K_XCAST_MODE_ALLMULTI)) +#define FM10K_VF_FLAG_MULTI_CAPABLE (u8)(BIT(FM10K_XCAST_MODE_MULTI)) +#define FM10K_VF_FLAG_PROMISC_CAPABLE (u8)(BIT(FM10K_XCAST_MODE_PROMISC)) +#define FM10K_VF_FLAG_NONE_CAPABLE (u8)(BIT(FM10K_XCAST_MODE_NONE)) #define FM10K_VF_FLAG_CAPABLE(vf_info) ((vf_info)->vf_flags & (u8)0xF) #define FM10K_VF_FLAG_ENABLED(vf_info) ((vf_info)->vf_flags >> 4) #define FM10K_VF_FLAG_SET_MODE(mode) ((u8)0x10 << (mode)) -- GitLab From 838e6102920a288a88f5bba10784ab10b2f2eb3e Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 22 Dec 2015 14:55:20 -0800 Subject: [PATCH 1464/9938] fm10k: demote BUG_ON() to WARN_ON() where appropriate We don't need to crash the kernel in this instance so just warn about the condition and play on. Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index c9324c79c879..60a70e9730a0 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -99,7 +99,7 @@ void fm10k_service_event_schedule(struct fm10k_intfc *interface) static void fm10k_service_event_complete(struct fm10k_intfc *interface) { - BUG_ON(!test_bit(__FM10K_SERVICE_SCHED, &interface->state)); + WARN_ON(!test_bit(__FM10K_SERVICE_SCHED, &interface->state)); /* flush memory to make sure state is correct before next watchog */ smp_mb__before_atomic(); -- GitLab From 1905add427cdee1b52380241574ab1339b1df413 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 22 Dec 2015 14:55:26 -0800 Subject: [PATCH 1465/9938] fm10k: cleanup SPACE_BEFORE_TAB checkpatch warning Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c b/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c index b4945e8abe03..1c1ccade6538 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c @@ -416,7 +416,7 @@ void fm10k_ptp_register(struct fm10k_intfc *interface) /* This math is simply the inverse of the math in * fm10k_adjust_systime_pf applied to an adjustment value * of 2^30 - 1 which is the maximum value of the register: - * max_ppb == ((2^30 - 1) * 5^9) / 2^31 + * max_ppb == ((2^30 - 1) * 5^9) / 2^31 */ ptp_caps->max_adj = 976562; ptp_caps->adjfreq = fm10k_ptp_adjfreq; -- GitLab From 11c49f79b294081010f7e13a95c6b40c4d36b1de Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Mon, 28 Dec 2015 18:00:30 -0800 Subject: [PATCH 1466/9938] fm10k: use ether_addr_copy to copy MAC address Cleanup the remaining instances of using memcpy() instead of the preferred ether_addr_copy(). Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 60a70e9730a0..6190a81b7c32 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1776,8 +1776,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, netdev->addr_assign_type |= NET_ADDR_RANDOM; } - memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); - memcpy(netdev->perm_addr, hw->mac.addr, netdev->addr_len); + ether_addr_copy(netdev->dev_addr, hw->mac.addr); + ether_addr_copy(netdev->perm_addr, hw->mac.addr); if (!is_valid_ether_addr(netdev->perm_addr)) { dev_err(&pdev->dev, "Invalid MAC Address\n"); -- GitLab From de66c610a6adade32bf955f67b4f4f4aaeeeff85 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 4 Feb 2016 10:47:54 -0800 Subject: [PATCH 1467/9938] fm10k: prevent null pointer dereference of msix_entries table According to the C standard dereferencing a variable before it is checked invokes undefined behavior, and thus compilers are free to assume the check for NULL isn't necessary. Prevent this by re-ordering the NULL check of msix_entries in fm10k_free_mbx_irq. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 6190a81b7c32..8c23fb3df572 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1143,14 +1143,16 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) void fm10k_mbx_free_irq(struct fm10k_intfc *interface) { - struct msix_entry *entry = &interface->msix_entries[FM10K_MBX_VECTOR]; struct fm10k_hw *hw = &interface->hw; + struct msix_entry *entry; int itr_reg; /* no mailbox IRQ to free if MSI-X is not enabled */ if (!interface->msix_entries) return; + entry = &interface->msix_entries[FM10K_MBX_VECTOR]; + /* disconnect the mailbox */ hw->mbx.ops.disconnect(hw, &hw->mbx); -- GitLab From e72319bba814b115c47785b3b88f7263d0b8a1b8 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 4 Feb 2016 10:47:55 -0800 Subject: [PATCH 1468/9938] fm10k: don't initialize service task until later in probe Delay initialization of the service timer and service task until late probe. If we don't wait, failures in probe do not properly cleanup the service timer or service task items, which results in the kernel panic below, potentially freezing the whole system. In addition, ensure that the SERVICE_DISABLE bit is set before we request the MBX IRQ since the MBX interrupt attempts to schedule the service task otherwise. This prevents a similar trace from occurring after this change. We didn't notice this issue before because probe almost always completes successfully. I discovered it due to a mis-ordered mailbox handler array, which resulted in the following failure when requesting mailbox interrupt. [ 555.325619] ------------[ cut here ]------------ [ 555.325628] WARNING: CPU: 0 PID: 4941 at lib/list_debug.c:33 __list_add+0xa0/0xd0() [ 555.325631] list_add corruption. prev->next should be next (ffffffff81f46648), but was (null). (prev=ffff8807fad5d0e8). [ 555.325722] CPU: 0 PID: 4941 Comm: insmod Tainted: G OE 4.0.4-303.fc22.x86_64 #1 [ 555.325725] Hardware name: Intel Corporation S2600CO/S2600CO, BIOS SE5C600.86B.02.03.8x23.060520140825 06/05/2014 [ 555.325727] 0000000000000000 00000000b4f161b3 ffff88081a21f8e8 ffffffff81783124 [ 555.325734] 0000000000000000 ffff88081a21f940 ffff88081a21f928 ffffffff8109c66a [ 555.325740] 0000000064000000 ffff8807fad5d0e8 ffff8807fad5d0e8 ffffffff81f46648 [ 555.325746] Call Trace: [ 555.325752] [] dump_stack+0x45/0x57 [ 555.325757] [] warn_slowpath_common+0x8a/0xc0 [ 555.325759] [] warn_slowpath_fmt+0x55/0x70 [ 555.325763] [] __list_add+0xa0/0xd0 [ 555.325768] [] __internal_add_timer+0x9d/0x110 [ 555.325771] [] internal_add_timer+0x2f/0xc0 [ 555.325774] [] mod_timer+0x12a/0x230 [ 555.325782] [] fm10k_probe+0x69a/0xc80 [fm10k] [ 555.325787] [] local_pci_probe+0x45/0xa0 [ 555.325791] [] ? sysfs_do_create_link_sd.isra.2+0x72/0xc0 [ 555.325794] [] pci_device_probe+0xf9/0x150 [ 555.325799] [] driver_probe_device+0xa3/0x400 [ 555.325802] [] __driver_attach+0x9b/0xa0 [ 555.325805] [] ? __device_attach+0x40/0x40 [ 555.325808] [] bus_for_each_dev+0x73/0xc0 [ 555.325811] [] driver_attach+0x1e/0x20 [ 555.325815] [] bus_add_driver+0x180/0x250 [ 555.325819] [] ? 0xffffffffa03b2000 [ 555.325823] [] driver_register+0x64/0xf0 [ 555.325826] [] __pci_register_driver+0x4c/0x50 [ 555.325832] [] fm10k_register_pci_driver+0x23/0x30 [fm10k] [ 555.325838] [] fm10k_init_module+0x80/0x1000 [fm10k] [ 555.325843] [] do_one_initcall+0xb8/0x200 [ 555.325848] [] ? __vunmap+0xa2/0x100 [ 555.325852] [] ? kmem_cache_alloc_trace+0x1b9/0x240 [ 555.325855] [] ? do_init_module+0x28/0x1cb [ 555.325858] [] do_init_module+0x60/0x1cb [ 555.325862] [] load_module+0x205e/0x26b0 [ 555.325866] [] ? store_uevent+0x70/0x70 [ 555.325870] [] ? kernel_read+0x50/0x80 [ 555.325873] [] SyS_finit_module+0xbe/0xf0 [ 555.325878] [] system_call_fastpath+0x12/0x17 [ 555.325880] ---[ end trace 9e0f58d071eafd2a ]--- Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 25 +++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 8c23fb3df572..ed1f8cf39508 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1795,15 +1795,6 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, /* initialize DCBNL interface */ fm10k_dcbnl_set_ops(netdev); - /* Initialize service timer and service task */ - set_bit(__FM10K_SERVICE_DISABLE, &interface->state); - setup_timer(&interface->service_timer, &fm10k_service_timer, - (unsigned long)interface); - INIT_WORK(&interface->service_task, fm10k_service_task); - - /* kick off service timer now, even when interface is down */ - mod_timer(&interface->service_timer, (HZ * 2) + jiffies); - /* Intitialize timestamp data */ fm10k_ts_init(interface); @@ -1989,6 +1980,12 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_sw_init; + /* the mbx interrupt might attempt to schedule the service task, so we + * must ensure it is disabled since we haven't yet requested the timer + * or work item. + */ + set_bit(__FM10K_SERVICE_DISABLE, &interface->state); + err = fm10k_mbx_request_irq(interface); if (err) goto err_mbx_interrupt; @@ -2008,6 +2005,16 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* stop all the transmit queues from transmitting until link is up */ netif_tx_stop_all_queues(netdev); + /* Initialize service timer and service task late in order to avoid + * cleanup issues. + */ + setup_timer(&interface->service_timer, &fm10k_service_timer, + (unsigned long)interface); + INIT_WORK(&interface->service_task, fm10k_service_task); + + /* kick off service timer now, even when interface is down */ + mod_timer(&interface->service_timer, (HZ * 2) + jiffies); + /* Register PTP interface */ fm10k_ptp_register(interface); -- GitLab From b3525696adba1ecddff3d667680461cc533e63a4 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 4 Feb 2016 10:47:56 -0800 Subject: [PATCH 1469/9938] fm10k: base queue scheme covered by RSS In fm10k_set_num_queues, we previously assigned the base template. This would always be overwritten by either fm10k_set_qos_queues or fm10k_set_rss_queues. In either case, we don't need the base values, so we can just remove them. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index db4353ba0932..b87401c38571 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1572,13 +1572,11 @@ static bool fm10k_set_rss_queues(struct fm10k_intfc *interface) **/ static void fm10k_set_num_queues(struct fm10k_intfc *interface) { - /* Start with base case */ - interface->num_rx_queues = 1; - interface->num_tx_queues = 1; - + /* Attempt to setup QoS and RSS first */ if (fm10k_set_qos_queues(interface)) return; + /* If we don't have QoS, just fallback to only RSS. */ fm10k_set_rss_queues(interface); } -- GitLab From 61e0217e83353cf895f8b2d0a187804171d119ca Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 4 Feb 2016 10:47:57 -0800 Subject: [PATCH 1470/9938] fm10k: print error message when stop_hw fails fm10k_stop_hw_generic calls fm10k_disable_queues_generic, which may return an error code indicating that the queues were not stopped within the time limit. Notify the user by displaying a message in the kernel message ring, in a similar way to how we notify the user when reset_hw fails. There isn't much we can do to recover from this error, so currently nothing else is done. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index ed1f8cf39508..3c7c819ac8d9 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1656,6 +1656,7 @@ void fm10k_down(struct fm10k_intfc *interface) { struct net_device *netdev = interface->netdev; struct fm10k_hw *hw = &interface->hw; + int err; /* signal that we are down to the interrupt handler and service task */ set_bit(__FM10K_DOWN, &interface->state); @@ -1680,7 +1681,9 @@ void fm10k_down(struct fm10k_intfc *interface) fm10k_update_stats(interface); /* Disable DMA engine for Tx/Rx */ - hw->mac.ops.stop_hw(hw); + err = hw->mac.ops.stop_hw(hw); + if (err) + dev_err(&interface->pdev->dev, "stop_hw failed: %d\n", err); /* free any buffers still on the rings */ fm10k_clean_all_tx_rings(interface); -- GitLab From c8ed563bebeabbf0b1085b52916dd2fb6e219276 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 4 Feb 2016 10:47:58 -0800 Subject: [PATCH 1471/9938] fm10k: free MBX IRQ before clearing interrupt scheme During fm10k_io_error_detected we were clearing the interrupt scheme before we freed the MBX IRQ. This causes a kernel panic because the MBX IRQ are assigned after MSI-X initialization. Clearing the interrupt scheme results in removing the MSI-X entry table. Fix this by freeing the MBX IRQ before we clear the interrupt scheme, as we do elsewhere in the driver. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 3c7c819ac8d9..da38af052519 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -2274,11 +2274,11 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, if (netif_running(netdev)) fm10k_close(netdev); + fm10k_mbx_free_irq(interface); + /* free interrupts */ fm10k_clear_queueing_scheme(interface); - fm10k_mbx_free_irq(interface); - pci_disable_device(pdev); /* Request a slot reset. */ -- GitLab From d2e0721b18f320232dc36a0e4cc7beb620e8c9bd Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 5 Feb 2016 10:43:08 -0800 Subject: [PATCH 1472/9938] fm10k: add helper functions to set strings and data for ethtool stats Reduce duplicate code and the amount of indentation by adding fm10k_add_stat_strings and fm10k_add_ethtool_stats functions which help add fm10k_stat structures to the ethtool stats callbacks. This helps increase ease of use for future stat additions, and increases code readability. Skip handling of the per-queue stats as these will be reworked in a following patch. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/fm10k/fm10k_ethtool.c | 164 +++++++++--------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 28837ae099df..c67121cc7b23 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -153,57 +153,51 @@ static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = { "debug-statistics", }; +static void fm10k_add_stat_strings(char **p, const char *prefix, + const struct fm10k_stats stats[], + const unsigned int size) +{ + unsigned int i; + + for (i = 0; i < size; i++) { + snprintf(*p, ETH_GSTRING_LEN, "%s%s", + prefix, stats[i].stat_string); + *p += ETH_GSTRING_LEN; + } +} + static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) { struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_iov_data *iov_data = interface->iov_data; char *p = (char *)data; unsigned int i; - unsigned int j; - for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_net_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } + fm10k_add_stat_strings(&p, "", fm10k_gstrings_net_stats, + FM10K_NETDEV_STATS_LEN); - for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_global_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } + fm10k_add_stat_strings(&p, "", fm10k_gstrings_global_stats, + FM10K_GLOBAL_STATS_LEN); - if (interface->flags & FM10K_FLAG_DEBUG_STATS) { - for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_debug_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } - } + if (interface->flags & FM10K_FLAG_DEBUG_STATS) + fm10k_add_stat_strings(&p, "", fm10k_gstrings_debug_stats, + FM10K_DEBUG_STATS_LEN); - for (i = 0; i < FM10K_MBX_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_mbx_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } + fm10k_add_stat_strings(&p, "", fm10k_gstrings_mbx_stats, + FM10K_MBX_STATS_LEN); - if (interface->hw.mac.type != fm10k_mac_vf) { - for (i = 0; i < FM10K_PF_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_pf_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } - } + if (interface->hw.mac.type != fm10k_mac_vf) + fm10k_add_stat_strings(&p, "", fm10k_gstrings_pf_stats, + FM10K_PF_STATS_LEN); if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { for (i = 0; i < iov_data->num_vfs; i++) { - for (j = 0; j < FM10K_MBX_STATS_LEN; j++) { - snprintf(p, - ETH_GSTRING_LEN, - "vf_%u_%s", i, - fm10k_gstrings_mbx_stats[j].stat_string); - p += ETH_GSTRING_LEN; - } + char prefix[ETH_GSTRING_LEN]; + + snprintf(prefix, ETH_GSTRING_LEN, "vf_%u_", i); + fm10k_add_stat_strings(&p, prefix, + fm10k_gstrings_mbx_stats, + FM10K_MBX_STATS_LEN); } } @@ -271,6 +265,41 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset) } } +static void fm10k_add_ethtool_stats(u64 **data, void *pointer, + const struct fm10k_stats stats[], + const unsigned int size) +{ + unsigned int i; + char *p; + + /* simply skip forward if we were not given a valid pointer */ + if (!pointer) { + *data += size; + return; + } + + for (i = 0; i < size; i++) { + p = (char *)pointer + stats[i].stat_offset; + + switch (stats[i].sizeof_stat) { + case sizeof(u64): + *((*data)++) = *(u64 *)p; + break; + case sizeof(u32): + *((*data)++) = *(u32 *)p; + break; + case sizeof(u16): + *((*data)++) = *(u16 *)p; + break; + case sizeof(u8): + *((*data)++) = *(u8 *)p; + break; + default: + *((*data)++) = 0; + } + } +} + static void fm10k_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats __always_unused *stats, u64 *data) @@ -279,47 +308,29 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_iov_data *iov_data = interface->iov_data; struct net_device_stats *net_stats = &netdev->stats; - char *p; int i, j; fm10k_update_stats(interface); - for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) { - p = (char *)net_stats + fm10k_gstrings_net_stats[i].stat_offset; - *(data++) = (fm10k_gstrings_net_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } + fm10k_add_ethtool_stats(&data, net_stats, fm10k_gstrings_net_stats, + FM10K_NETDEV_STATS_LEN); - for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { - p = (char *)interface + - fm10k_gstrings_global_stats[i].stat_offset; - *(data++) = (fm10k_gstrings_global_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } + fm10k_add_ethtool_stats(&data, interface, fm10k_gstrings_global_stats, + FM10K_GLOBAL_STATS_LEN); - if (interface->flags & FM10K_FLAG_DEBUG_STATS) { - for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) { - p = (char *)interface + - fm10k_gstrings_debug_stats[i].stat_offset; - *(data++) = (fm10k_gstrings_debug_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } - } + if (interface->flags & FM10K_FLAG_DEBUG_STATS) + fm10k_add_ethtool_stats(&data, interface, + fm10k_gstrings_debug_stats, + FM10K_DEBUG_STATS_LEN); - for (i = 0; i < FM10K_MBX_STATS_LEN; i++) { - p = (char *)&interface->hw.mbx + - fm10k_gstrings_mbx_stats[i].stat_offset; - *(data++) = (fm10k_gstrings_mbx_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } + fm10k_add_ethtool_stats(&data, &interface->hw.mbx, + fm10k_gstrings_mbx_stats, + FM10K_MBX_STATS_LEN); if (interface->hw.mac.type != fm10k_mac_vf) { - for (i = 0; i < FM10K_PF_STATS_LEN; i++) { - p = (char *)interface + - fm10k_gstrings_pf_stats[i].stat_offset; - *(data++) = (fm10k_gstrings_pf_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } + fm10k_add_ethtool_stats(&data, interface, + fm10k_gstrings_pf_stats, + FM10K_PF_STATS_LEN); } if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { @@ -328,18 +339,9 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, vf_info = &iov_data->vf_info[i]; - /* skip stats if we don't have a vf info */ - if (!vf_info) { - data += FM10K_MBX_STATS_LEN; - continue; - } - - for (j = 0; j < FM10K_MBX_STATS_LEN; j++) { - p = (char *)&vf_info->mbx + - fm10k_gstrings_mbx_stats[j].stat_offset; - *(data++) = (fm10k_gstrings_mbx_stats[j].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } + fm10k_add_ethtool_stats(&data, &vf_info->mbx, + fm10k_gstrings_mbx_stats, + FM10K_MBX_STATS_LEN); } } -- GitLab From c4114e3db6429c665adc3db871685c474a467efe Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 10 Feb 2016 14:45:47 -0800 Subject: [PATCH 1473/9938] fm10k: prevent possibly uninitialized variable If 'attr_flag < (1 << (2 * FM10K_TEST_MSG_NESTED))' is ever false, err will be used uninitialized. Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index c67121cc7b23..2e4ea8861852 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -937,7 +937,7 @@ static int fm10k_mbx_test(struct fm10k_intfc *interface, u64 *data) struct fm10k_mbx_info *mbx = &hw->mbx; u32 attr_flag, test_msg[6]; unsigned long timeout; - int err; + int err = -EINVAL; /* For now this is a VF only feature */ if (hw->mac.type != fm10k_mac_vf) -- GitLab From 4be37c42a40cec94b0381b42e5796d3316f96c32 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 10 Feb 2016 14:45:50 -0800 Subject: [PATCH 1474/9938] fm10k: correctly clean up when init_queueing_scheme fails Fix a kernel panic that occurs during surprise removal. Clear the interface queue counts upon fm10k_init_msix_capability failure. This prevents further code (fm10k_update_stats etc.) from attempting to access unallocated queue vector or ring memory. [ 628.692648] BUG: unable to handle kernel NULL pointer dereference at 0000000000000068 [ 628.692805] IP: [] fm10k_update_stats+0x7f/0x2c0 [fm10k] [ 628.693173] PGD 0 [ 628.693759] Oops: 0000 [#1] SMP [ 628.699321] CPU: 10 PID: 8164 Comm: kworker/10:0 Tainted: G OE ------------ 3.10.0-327.el7.x86_64 #1 [ 628.700096] Hardware name: Supermicro X9DAi/X9DAi, BIOS 3.2 05/09/2015 [ 628.700894] Workqueue: pciehp-1 pciehp_power_thread [ 628.701686] task: ffff88086559c500 ti: ffff8808593c0000 task.ti: ffff8808593c0000 [ 628.702493] RIP: 0010:[] [] fm10k_update_stats+0x7f/0x2c0 [fm10k] [ 628.703310] RSP: 0018:ffff8808593c3b00 EFLAGS: 00010282 [ 628.704132] RAX: 0000000000000000 RBX: ffff880860760000 RCX: 0000000000000000 [ 628.704963] RDX: ffff880860760b08 RSI: 0000000000000000 RDI: 0000000000000000 [ 628.705794] RBP: ffff8808593c3b40 R08: 0000000000000000 R09: 0000000000000000 [ 628.706604] R10: 0000000000000000 R11: ffff880860760c40 R12: 0000000000000080 [ 628.707420] R13: ffff8808607608c0 R14: ffff880860779ec0 R15: ffff880860779f40 [ 628.708238] FS: 0000000000000000(0000) GS:ffff88086f000000(0000) knlGS:0000000000000000 [ 628.709071] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 628.709923] CR2: 0000000000000068 CR3: 000000000194a000 CR4: 00000000001407e0 [ 628.710752] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 628.711596] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 628.712438] Stack: [ 628.713255] ffff880860764458 ffff8808607608c0 ffff880860760000 ffff880860760000 [ 628.714088] 0000000000000080 ffff8808607608c0 ffff880860779ec0 ffff880860779f40 [ 628.714925] ffff8808593c3b88 ffffffffa04780c5 ffff880860764458 0000000a8163cb5b [ 628.715752] Call Trace: [ 628.716560] [] fm10k_down+0x155/0x1f0 [fm10k] [ 628.717367] [] fm10k_close+0x28/0xd0 [fm10k] [ 628.718184] [] __dev_close_many+0x85/0xd0 [ 628.718986] [] dev_close_many+0x98/0x120 [ 628.719764] [] rollback_registered_many+0xa8/0x230 [ 628.720527] [] rollback_registered+0x40/0x70 [ 628.721294] [] unregister_netdevice_queue+0x48/0x80 [ 628.722052] [] unregister_netdev+0x1c/0x30 [ 628.722816] [] fm10k_remove+0xd8/0xe0 [fm10k] [ 628.723581] [] pci_device_remove+0x3b/0xb0 [ 628.724340] [] __device_release_driver+0x7f/0xf0 [ 628.725088] [] device_release_driver+0x23/0x30 [ 628.725814] [] pci_stop_bus_device+0x94/0xa0 [ 628.726535] [] pci_stop_and_remove_bus_device+0x12/0x20 [ 628.727249] [] pciehp_unconfigure_device+0xb0/0x1b0 [ 628.727964] [] pciehp_disable_slot+0x52/0xd0 [ 628.728664] [] pciehp_power_thread+0xea/0x150 [ 628.729358] [] process_one_work+0x17b/0x470 [ 628.730036] [] worker_thread+0x11b/0x400 [ 628.730730] [] ? rescuer_thread+0x400/0x400 [ 628.731385] [] kthread+0xcf/0xe0 [ 628.732036] [] ? kthread_create_on_node+0x140/0x140 [ 628.732674] [] ret_from_fork+0x58/0x90 [ 628.733289] [] ? kthread_create_on_node+0x140/0x140 [ 628.733883] Code: 83 e8 01 48 8d 97 40 02 00 00 45 31 c0 4c 8d 9c c7 48 02 0 [ 628.735202] RIP [] fm10k_update_stats+0x7f/0x2c0 [fm10k] [ 628.735732] RSP [ 628.736285] CR2: 0000000000000068 [ 628.736846] ---[ end trace 9156088b311aff42 ]--- Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index b87401c38571..31179afb8468 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1580,6 +1580,20 @@ static void fm10k_set_num_queues(struct fm10k_intfc *interface) fm10k_set_rss_queues(interface); } +/** + * fm10k_reset_num_queues - Reset the number of queues to zero + * @interface: board private structure + * + * This function should be called whenever we need to reset the number of + * queues after an error condition. + */ +static void fm10k_reset_num_queues(struct fm10k_intfc *interface) +{ + interface->num_tx_queues = 0; + interface->num_rx_queues = 0; + interface->num_q_vectors = 0; +} + /** * fm10k_alloc_q_vector - Allocate memory for a single interrupt vector * @interface: board private structure to initialize @@ -1763,9 +1777,7 @@ static int fm10k_alloc_q_vectors(struct fm10k_intfc *interface) return 0; err_out: - interface->num_tx_queues = 0; - interface->num_rx_queues = 0; - interface->num_q_vectors = 0; + fm10k_reset_num_queues(interface); while (v_idx--) fm10k_free_q_vector(interface, v_idx); @@ -1785,9 +1797,7 @@ static void fm10k_free_q_vectors(struct fm10k_intfc *interface) { int v_idx = interface->num_q_vectors; - interface->num_tx_queues = 0; - interface->num_rx_queues = 0; - interface->num_q_vectors = 0; + fm10k_reset_num_queues(interface); while (v_idx--) fm10k_free_q_vector(interface, v_idx); @@ -1995,14 +2005,15 @@ int fm10k_init_queueing_scheme(struct fm10k_intfc *interface) if (err) { dev_err(&interface->pdev->dev, "Unable to initialize MSI-X capability\n"); - return err; + goto err_init_msix; } /* Allocate memory for queues */ err = fm10k_alloc_q_vectors(interface); if (err) { - fm10k_reset_msix_capability(interface); - return err; + dev_err(&interface->pdev->dev, + "Unable to allocate queue vectors\n"); + goto err_alloc_q_vectors; } /* Map rings to devices, and map devices to physical queues */ @@ -2012,6 +2023,12 @@ int fm10k_init_queueing_scheme(struct fm10k_intfc *interface) fm10k_init_reta(interface); return 0; + +err_alloc_q_vectors: + fm10k_reset_msix_capability(interface); +err_init_msix: + fm10k_reset_num_queues(interface); + return err; } /** -- GitLab From d8ec92f2cdcc7f2d06dd0a40b600b6da7d9d1070 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 10 Feb 2016 14:45:51 -0800 Subject: [PATCH 1475/9938] fm10k: fix a minor typo in some comments s/funciton/function to resolve a typo, and cleanup grammar on a few comments regarding processing the VF mailboxes. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 6 +++--- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index acfb8b1f88a7..bbf7c4bac303 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c @@ -50,7 +50,7 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface) s64 vflre; int i; - /* if there is no iov_data then there is no mailboxes to process */ + /* if there is no iov_data then there is no mailbox to process */ if (!ACCESS_ONCE(interface->iov_data)) return 0; @@ -98,7 +98,7 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface) struct fm10k_iov_data *iov_data; int i; - /* if there is no iov_data then there is no mailboxes to process */ + /* if there is no iov_data then there is no mailbox to process */ if (!ACCESS_ONCE(interface->iov_data)) return 0; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 0ff68747c6c4..1d0f0583222c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -440,7 +440,7 @@ static void fm10k_restore_vxlan_port(struct fm10k_intfc *interface) * @sa_family: Address family of new port * @port: port number used for VXLAN * - * This funciton is called when a new VXLAN interface has added a new port + * This function is called when a new VXLAN interface has added a new port * number to the range that is currently in use for VXLAN. The new port * number is always added to the tail so that the port number list should * match the order in which the ports were allocated. The head of the list @@ -484,7 +484,7 @@ static void fm10k_add_vxlan_port(struct net_device *dev, * @sa_family: Address family of freed port * @port: port number used for VXLAN * - * This funciton is called when a new VXLAN interface has freed a port + * This function is called when a new VXLAN interface has freed a port * number from the range that is currently in use for VXLAN. The freed * port is removed from the list and the new head is used to determine * the port number for offloads. diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index da38af052519..f0992950e228 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1379,7 +1379,7 @@ static s32 fm10k_1588_msg_pf(struct fm10k_hw *hw, u32 **results, return 0; } - /* if there is no iov_data then there is no mailboxes to process */ + /* if there is no iov_data then there is no mailbox to process */ if (!ACCESS_ONCE(interface->iov_data)) return FM10K_ERR_PARAM; @@ -2394,7 +2394,7 @@ static struct pci_driver fm10k_driver = { /** * fm10k_register_pci_driver - register driver interface * - * This funciton is called on module load in order to register the driver. + * This function is called on module load in order to register the driver. **/ int fm10k_register_pci_driver(void) { @@ -2404,7 +2404,7 @@ int fm10k_register_pci_driver(void) /** * fm10k_unregister_pci_driver - unregister driver interface * - * This funciton is called on module unload in order to remove the driver. + * This function is called on module unload in order to remove the driver. **/ void fm10k_unregister_pci_driver(void) { diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 23de956d1acc..ecc99f9d2cce 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1604,7 +1604,7 @@ static s32 fm10k_request_lport_map_pf(struct fm10k_hw *hw) * @hw: pointer to hardware structure * @switch_ready: pointer to boolean value that will record switch state * - * This funciton will check the DMA_CTRL2 register and mailbox in order + * This function will check the DMA_CTRL2 register and mailbox in order * to determine if the switch is ready for the PF to begin requesting * addresses and mapping traffic to the local interface. **/ -- GitLab From 0ea7fae44094b4ca06ea68105457a7dc64041bd3 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Tue, 16 Feb 2016 16:19:24 -0800 Subject: [PATCH 1476/9938] fm10k: use ethtool_rxfh_indir_default for default redirection table The fm10k driver used its own code for generating a default indirection table on device load, which was not the same as the default generated by ethtool when indir_size of 0 is passed to SRXFH. Take advantage of ethtool_rxfh_indir_default() and simplify code to write the redirection table to reduce some code duplication. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k.h | 2 + .../net/ethernet/intel/fm10k/fm10k_ethtool.c | 37 +++++++++++-------- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 24 +++++------- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index 83f386714e87..9c7fafef7cf6 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -510,6 +510,8 @@ int fm10k_close(struct net_device *netdev); /* Ethtool */ void fm10k_set_ethtool_ops(struct net_device *dev); +u32 fm10k_get_reta_size(struct net_device *netdev); +void fm10k_write_reta(struct fm10k_intfc *interface, const u32 *indir); /* IOV */ s32 fm10k_iov_event(struct fm10k_intfc *interface); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 2e4ea8861852..a23748777b1b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -1027,11 +1027,31 @@ static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags) return 0; } -static u32 fm10k_get_reta_size(struct net_device __always_unused *netdev) +u32 fm10k_get_reta_size(struct net_device __always_unused *netdev) { return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG; } +void fm10k_write_reta(struct fm10k_intfc *interface, const u32 *indir) +{ + struct fm10k_hw *hw = &interface->hw; + int i; + + /* record entries to reta table */ + for (i = 0; i < FM10K_RETA_SIZE; i++, indir += 4) { + u32 reta = indir[0] | + (indir[1] << 8) | + (indir[2] << 16) | + (indir[3] << 24); + + if (interface->reta[i] == reta) + continue; + + interface->reta[i] = reta; + fm10k_write_reg(hw, FM10K_RETA(0, i), reta); + } +} + static int fm10k_get_reta(struct net_device *netdev, u32 *indir) { struct fm10k_intfc *interface = netdev_priv(netdev); @@ -1055,7 +1075,6 @@ static int fm10k_get_reta(struct net_device *netdev, u32 *indir) static int fm10k_set_reta(struct net_device *netdev, const u32 *indir) { struct fm10k_intfc *interface = netdev_priv(netdev); - struct fm10k_hw *hw = &interface->hw; int i; u16 rss_i; @@ -1070,19 +1089,7 @@ static int fm10k_set_reta(struct net_device *netdev, const u32 *indir) return -EINVAL; } - /* record entries to reta table */ - for (i = 0; i < FM10K_RETA_SIZE; i++, indir += 4) { - u32 reta = indir[0] | - (indir[1] << 8) | - (indir[2] << 16) | - (indir[3] << 24); - - if (interface->reta[i] == reta) - continue; - - interface->reta[i] = reta; - fm10k_write_reg(hw, FM10K_RETA(0, i), reta); - } + fm10k_write_reta(interface, indir); return 0; } diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 31179afb8468..0b465394f88a 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1943,7 +1943,8 @@ static void fm10k_assign_rings(struct fm10k_intfc *interface) static void fm10k_init_reta(struct fm10k_intfc *interface) { u16 i, rss_i = interface->ring_feature[RING_F_RSS].indices; - u32 reta, base; + struct net_device *netdev = interface->netdev; + u32 reta, *indir; /* If the Rx flow indirection table has been configured manually, we * need to maintain it when possible. @@ -1968,21 +1969,16 @@ static void fm10k_init_reta(struct fm10k_intfc *interface) } repopulate_reta: - /* Populate the redirection table 4 entries at a time. To do this - * we are generating the results for n and n+2 and then interleaving - * those with the results with n+1 and n+3. - */ - for (i = FM10K_RETA_SIZE; i--;) { - /* first pass generates n and n+2 */ - base = ((i * 0x00040004) + 0x00020000) * rss_i; - reta = (base & 0x3F803F80) >> 7; + indir = kcalloc(fm10k_get_reta_size(netdev), + sizeof(indir[0]), GFP_KERNEL); - /* second pass generates n+1 and n+3 */ - base += 0x00010001 * rss_i; - reta |= (base & 0x3F803F80) << 1; + /* generate redirection table using the default kernel policy */ + for (i = 0; i < fm10k_get_reta_size(netdev); i++) + indir[i] = ethtool_rxfh_indir_default(i, rss_i); - interface->reta[i] = reta; - } + fm10k_write_reta(interface, indir); + + kfree(indir); } /** -- GitLab From 341e0cb593a2b7ec86dd6ca96c68eadc3f6fe1e6 Mon Sep 17 00:00:00 2001 From: Janak Desai Date: Mon, 28 Mar 2016 11:09:46 -0400 Subject: [PATCH 1477/9938] netlabel: fix a problem with netlbl_secattr_catmap_setrng() We try to be clever and set large chunks of the bitmap at once, when possible; unfortunately we weren't very clever when we wrote the code and messed up the if-conditional. Fix this bug and restore proper operation. Signed-off-by: Janak Desai Signed-off-by: Paul Moore --- net/netlabel/netlabel_kapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 28cddc85b700..1325776daa27 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -677,7 +677,7 @@ int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap, u32 spot = start; while (rc == 0 && spot <= end) { - if (((spot & (BITS_PER_LONG - 1)) != 0) && + if (((spot & (BITS_PER_LONG - 1)) == 0) && ((end - spot) > BITS_PER_LONG)) { rc = netlbl_catmap_setlong(catmap, spot, -- GitLab From 899134f2f6e27dcae1fee12593c492577cc80987 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 28 Mar 2016 15:19:10 -0400 Subject: [PATCH 1478/9938] selinux: don't revalidate inodes in selinux_socket_getpeersec_dgram() We don't have to worry about socket inodes being invalidated so use inode_security_novalidate() to fetch the inode's security blob. Signed-off-by: Paul Moore --- security/selinux/hooks.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 912deee3f01e..65642be91644 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4598,6 +4598,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * { u32 peer_secid = SECSID_NULL; u16 family; + struct inode_security_struct *isec; if (skb && skb->protocol == htons(ETH_P_IP)) family = PF_INET; @@ -4608,9 +4609,10 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * else goto out; - if (sock && family == PF_UNIX) - selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid); - else if (skb) + if (sock && family == PF_UNIX) { + isec = inode_security_novalidate(SOCK_INODE(sock)); + peer_secid = isec->sid; + } else if (skb) selinux_skb_peerlbl_sid(skb, family, &peer_secid); out: -- GitLab From 4b57d6bcd94034e2eb168bdec2474e3b2b848e44 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 28 Mar 2016 15:16:53 -0400 Subject: [PATCH 1479/9938] selinux: simply inode label states to INVALID and INITIALIZED There really is no need for LABEL_MISSING as we really only care if the inode's label is INVALID or INITIALIZED. Also adjust the revalidate code to reload the label whenever the label is not INITIALIZED so we are less sensitive to label state in the future. Signed-off-by: Paul Moore --- security/selinux/hooks.c | 2 +- security/selinux/include/objsec.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 65642be91644..dd1fbea37b78 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -259,7 +259,7 @@ static int __inode_security_revalidate(struct inode *inode, might_sleep_if(may_sleep); - if (isec->initialized == LABEL_INVALID) { + if (isec->initialized != LABEL_INITIALIZED) { if (!may_sleep) return -ECHILD; diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index a2ae05414ba1..c21e135460a5 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -38,9 +38,8 @@ struct task_security_struct { }; enum label_initialized { - LABEL_MISSING, /* not initialized */ - LABEL_INITIALIZED, /* inizialized */ - LABEL_INVALID /* invalid */ + LABEL_INVALID, /* invalid or not initialized */ + LABEL_INITIALIZED /* initialized */ }; struct inode_security_struct { -- GitLab From 0c6181cb301fd04a5800920ba423be753b0a4a01 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 30 Mar 2016 21:41:21 -0400 Subject: [PATCH 1480/9938] selinux: consolidate the ptrace parent lookup code We lookup the tracing parent in two places, using effectively the same code, let's consolidate it. Signed-off-by: Paul Moore --- security/selinux/hooks.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index dd1fbea37b78..5003b5aa3b43 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2229,6 +2229,20 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) /* binprm security operations */ +static u32 ptrace_parent_sid(struct task_struct *task) +{ + u32 sid = 0; + struct task_struct *tracer; + + rcu_read_lock(); + tracer = ptrace_parent(task); + if (tracer) + sid = task_sid(tracer); + rcu_read_unlock(); + + return sid; +} + static int check_nnp_nosuid(const struct linux_binprm *bprm, const struct task_security_struct *old_tsec, const struct task_security_struct *new_tsec) @@ -2350,18 +2364,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) * changes its SID has the appropriate permit */ if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { - struct task_struct *tracer; - struct task_security_struct *sec; - u32 ptsid = 0; - - rcu_read_lock(); - tracer = ptrace_parent(current); - if (likely(tracer != NULL)) { - sec = __task_cred(tracer)->security; - ptsid = sec->sid; - } - rcu_read_unlock(); - + u32 ptsid = ptrace_parent_sid(current); if (ptsid != 0) { rc = avc_has_perm(ptsid, new_tsec->sid, SECCLASS_PROCESS, @@ -5677,7 +5680,6 @@ static int selinux_setprocattr(struct task_struct *p, char *name, void *value, size_t size) { struct task_security_struct *tsec; - struct task_struct *tracer; struct cred *new; u32 sid = 0, ptsid; int error; @@ -5784,14 +5786,8 @@ static int selinux_setprocattr(struct task_struct *p, /* Check for ptracing, and update the task SID if ok. Otherwise, leave SID unchanged and fail. */ - ptsid = 0; - rcu_read_lock(); - tracer = ptrace_parent(p); - if (tracer) - ptsid = task_sid(tracer); - rcu_read_unlock(); - - if (tracer) { + ptsid = ptrace_parent_sid(p); + if (ptsid != 0) { error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); if (error) -- GitLab From 61d612ea731e57dc510472fb746b55cdc017f371 Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Tue, 5 Apr 2016 13:06:27 -0700 Subject: [PATCH 1481/9938] selinux: restrict kernel module loading Utilize existing kernel_read_file hook on kernel module load. Add module_load permission to the system class. Enforces restrictions on kernel module origin when calling the finit_module syscall. The hook checks that source type has permission module_load for the target type. Example for finit_module: allow foo bar_file:system module_load; Similarly restrictions are enforced on kernel module loading when calling the init_module syscall. The hook checks that source type has permission module_load with itself as the target object because the kernel module is sourced from the calling process. Example for init_module: allow foo foo:system module_load; Signed-off-by: Jeff Vander Stoep [PM: fixed return value of selinux_kernel_read_file()] Signed-off-by: Paul Moore --- security/selinux/hooks.c | 47 +++++++++++++++++++++++++++++ security/selinux/include/classmap.h | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5003b5aa3b43..fce7dc81f2d9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3722,6 +3722,52 @@ static int selinux_kernel_module_request(char *kmod_name) SYSTEM__MODULE_REQUEST, &ad); } +static int selinux_kernel_module_from_file(struct file *file) +{ + struct common_audit_data ad; + struct inode_security_struct *isec; + struct file_security_struct *fsec; + u32 sid = current_sid(); + int rc; + + /* init_module */ + if (file == NULL) + return avc_has_perm(sid, sid, SECCLASS_SYSTEM, + SYSTEM__MODULE_LOAD, NULL); + + /* finit_module */ + ad.type = LSM_AUDIT_DATA_PATH; + ad.u.path = file->f_path; + + isec = inode_security(file_inode(file)); + fsec = file->f_security; + + if (sid != fsec->sid) { + rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); + if (rc) + return rc; + } + + return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, + SYSTEM__MODULE_LOAD, &ad); +} + +static int selinux_kernel_read_file(struct file *file, + enum kernel_read_file_id id) +{ + int rc = 0; + + switch (id) { + case READING_MODULE: + rc = selinux_kernel_module_from_file(file); + break; + default: + break; + } + + return rc; +} + static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { return current_has_perm(p, PROCESS__SETPGID); @@ -6018,6 +6064,7 @@ static struct security_hook_list selinux_hooks[] = { LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), + LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file), LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), LSM_HOOK_INIT(task_getsid, selinux_task_getsid), diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index ef83c4b85a33..8fbd1383d75e 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -32,7 +32,7 @@ struct security_class_mapping secclass_map[] = { "setsockcreate", NULL } }, { "system", { "ipc_info", "syslog_read", "syslog_mod", - "syslog_console", "module_request", NULL } }, + "syslog_console", "module_request", "module_load", NULL } }, { "capability", { "chown", "dac_override", "dac_read_search", "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", -- GitLab From 11f15ed394782dd018d60a0bb550616a8571b43c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:08:55 -0400 Subject: [PATCH 1482/9938] bnxt_en: Update to Firmware 1.2.2 spec. Use new field names in API structs and stop using deprecated fields auto_link_speed and auto_duplex in phy_cfg/phy_qcfg structs. Update copyright year to 2016. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 20 +- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 8 +- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 4 +- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.h | 2 +- .../net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 433 ++++++++++++++++-- .../ethernet/broadcom/bnxt/bnxt_nvm_defs.h | 2 +- .../net/ethernet/broadcom/bnxt/bnxt_sriov.c | 14 +- .../net/ethernet/broadcom/bnxt/bnxt_sriov.h | 2 +- 9 files changed, 431 insertions(+), 56 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 12a009d720cd..bfe98cbcefca 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -2763,7 +2763,7 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp) * only checks if it is non-zero to enable async event forwarding */ req.async_event_fwd[0] |= cpu_to_le32(1); - req.os_type = cpu_to_le16(1); + req.os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX); req.ver_maj = DRV_VER_MAJ; req.ver_min = DRV_VER_MIN; req.ver_upd = DRV_VER_UPD; @@ -3726,7 +3726,7 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp) pf->fw_fid = le16_to_cpu(resp->fid); pf->port_id = le16_to_cpu(resp->port_id); - memcpy(pf->mac_addr, resp->perm_mac_address, ETH_ALEN); + memcpy(pf->mac_addr, resp->mac_address, ETH_ALEN); memcpy(bp->dev->dev_addr, pf->mac_addr, ETH_ALEN); pf->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx); pf->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings); @@ -3751,7 +3751,7 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp) struct bnxt_vf_info *vf = &bp->vf; vf->fw_fid = le16_to_cpu(resp->fid); - memcpy(vf->mac_addr, resp->perm_mac_address, ETH_ALEN); + memcpy(vf->mac_addr, resp->mac_address, ETH_ALEN); if (is_valid_ether_addr(vf->mac_addr)) /* overwrite netdev dev_adr with admin VF MAC */ memcpy(bp->dev->dev_addr, vf->mac_addr, ETH_ALEN); @@ -3842,6 +3842,8 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) memcpy(&bp->ver_resp, resp, sizeof(struct hwrm_ver_get_output)); + bp->hwrm_spec_code = resp->hwrm_intf_maj << 16 | + resp->hwrm_intf_min << 8 | resp->hwrm_intf_upd; if (resp->hwrm_intf_maj < 1) { netdev_warn(bp->dev, "HWRM interface %d.%d.%d is older than 1.0.0.\n", resp->hwrm_intf_maj, resp->hwrm_intf_min, @@ -4523,7 +4525,6 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) else link_info->link_speed = 0; link_info->force_link_speed = le16_to_cpu(resp->force_link_speed); - link_info->auto_link_speed = le16_to_cpu(resp->auto_link_speed); link_info->support_speeds = le16_to_cpu(resp->support_speeds); link_info->auto_link_speeds = le16_to_cpu(resp->auto_link_speed_mask); link_info->lp_auto_link_speeds = @@ -4533,8 +4534,8 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) link_info->phy_ver[1] = resp->phy_min; link_info->phy_ver[2] = resp->phy_bld; link_info->media_type = resp->media_type; - link_info->transceiver = resp->transceiver_type; - link_info->phy_addr = resp->phy_addr; + link_info->transceiver = resp->xcvr_pkg_type; + link_info->phy_addr = resp->eee_config_phy_addr; /* TODO: need to add more logic to report VF link */ if (chng_link_state) { @@ -4581,7 +4582,7 @@ static void bnxt_hwrm_set_link_common(struct bnxt *bp, if (autoneg & BNXT_AUTONEG_SPEED) { req->auto_mode |= - PORT_PHY_CFG_REQ_AUTO_MODE_MASK; + PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK; req->enables |= cpu_to_le32( PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK); @@ -4595,9 +4596,6 @@ static void bnxt_hwrm_set_link_common(struct bnxt *bp, req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE); } - /* currently don't support half duplex */ - req->auto_duplex = PORT_PHY_CFG_REQ_AUTO_DUPLEX_FULL; - req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX); /* tell chimp that the setting takes effect immediately */ req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESET_PHY); } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 709b95b8fcba..e98c37ae81f2 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -11,7 +11,7 @@ #define BNXT_H #define DRV_MODULE_NAME "bnxt_en" -#define DRV_MODULE_VERSION "1.0.0" +#define DRV_MODULE_VERSION "1.2.0" #define DRV_VER_MAJ 1 #define DRV_VER_MIN 0 @@ -788,7 +788,7 @@ struct bnxt_link_info { #define BNXT_LINK_AUTO_ALLSPDS PORT_PHY_QCFG_RESP_AUTO_MODE_ALL_SPEEDS #define BNXT_LINK_AUTO_ONESPD PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_SPEED #define BNXT_LINK_AUTO_ONEORBELOW PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_OR_BELOW -#define BNXT_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_MASK +#define BNXT_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_SPEED_MASK #define PHY_VER_LEN 3 u8 phy_ver[PHY_VER_LEN]; u16 link_speed; @@ -813,7 +813,6 @@ struct bnxt_link_info { #define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB #define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB u16 lp_auto_link_speeds; - u16 auto_link_speed; u16 force_link_speed; u32 preemphasis; @@ -940,6 +939,7 @@ struct bnxt { u32 msg_enable; + u32 hwrm_spec_code; u16 hwrm_cmd_seq; u32 hwrm_intr_seq_id; void *hwrm_cmd_resp_addr; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 2e472f6dbf2d..f103f9b06e6d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -728,7 +728,7 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed); ethtool_cmd_speed_set(cmd, ethtool_speed); if (link_info->transceiver == - PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL) + PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL) cmd->transceiver = XCVR_INTERNAL; else cmd->transceiver = XCVR_EXTERNAL; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h index 98fa81e08b58..b2d8bd3a37fb 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h index e0aac65c6d82..461675caaacd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index 4badbedcb421..80f95560086d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -104,6 +104,7 @@ struct hwrm_async_event_cmpl { #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE (0x3UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED (0x4UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED (0x5UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE (0x6UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD (0x10UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD (0x11UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD (0x20UL << 0) @@ -111,6 +112,7 @@ struct hwrm_async_event_cmpl { #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR (0x30UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE (0x31UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE (0x32UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE (0x33UL << 0) #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR (0xffUL << 0) __le32 event_data2; u8 opaque_v; @@ -141,6 +143,7 @@ struct hwrm_async_event_cmpl_link_status_change { #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE 0x1UL #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_DOWN (0x0UL << 0) #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP (0x1UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_LAST HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_MASK 0xeUL #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_SFT 1 #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0UL @@ -195,6 +198,9 @@ struct hwrm_async_event_cmpl_link_speed_change { #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (0xfaUL << 1) #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (0x190UL << 1) #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (0x1f4UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB (0x3e8UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10MB (0xffffUL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_LAST HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10MB #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0000UL #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_SFT 16 }; @@ -237,6 +243,55 @@ struct hwrm_async_event_cmpl_port_conn_not_allowed { __le32 event_data1; #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK 0xff0000UL + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT 16 + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_NONE (0x0UL << 16) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_DISABLETX (0x1UL << 16) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_WARNINGMSG (0x2UL << 16) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN (0x3UL << 16) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_LAST HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN +}; + +/* HWRM Asynchronous Event Completion Record for link speed config not allowed (16 bytes) */ +struct hwrm_async_event_cmpl_link_speed_cfg_not_allowed { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED (0x5UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_SFT 1 + u8 timestamp_lo; + __le16 timestamp_hi; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for link speed configuration change (16 bytes) */ +struct hwrm_async_event_cmpl_link_speed_cfg_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_ID_LINK_SPEED_CFG_CHANGE (0x6UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_SFT 1 + u8 timestamp_lo; + __le16 timestamp_hi; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_SUPPORTED_LINK_SPEEDS_CHANGE 0x10000UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_ILLEGAL_LINK_SPEED_CFG 0x20000UL }; /* HWRM Asynchronous Event Completion Record for Function Driver Unload (16 bytes) */ @@ -363,6 +418,47 @@ struct hwrm_async_event_cmpl_vf_mac_addr_change { #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0 }; +/* HWRM Asynchronous Event Completion Record for PF-VF communication status change (16 bytes) */ +struct hwrm_async_event_cmpl_pf_vf_comm_status_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_ID_PF_VF_COMM_STATUS_CHANGE (0x32UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_SFT 1 + u8 timestamp_lo; + __le16 timestamp_hi; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_DATA1_COMM_ESTABLISHED 0x1UL +}; + +/* HWRM Asynchronous Event Completion Record for VF configuration change (16 bytes) */ +struct hwrm_async_event_cmpl_vf_cfg_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_ID_VF_CFG_CHANGE (0x33UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_SFT 1 + u8 timestamp_lo; + __le16 timestamp_hi; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MTU_CHANGE 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MRU_CHANGE 0x2UL + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_MAC_ADDR_CHANGE 0x4UL + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_VLAN_CHANGE 0x8UL +}; + /* HWRM Asynchronous Event Completion Record for HWRM Error (16 bytes) */ struct hwrm_async_event_cmpl_hwrm_error { __le16 type; @@ -377,6 +473,7 @@ struct hwrm_async_event_cmpl_hwrm_error { #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING (0x0UL << 0) #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL (0x1UL << 0) #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL (0x2UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_LAST HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL u8 opaque_v; #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_V 0x1UL #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK 0xfeUL @@ -387,12 +484,12 @@ struct hwrm_async_event_cmpl_hwrm_error { #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP 0x1UL }; -/* HW Resource Manager Specification 1.0.0 */ +/* HW Resource Manager Specification 1.2.2 */ #define HWRM_VERSION_MAJOR 1 -#define HWRM_VERSION_MINOR 0 -#define HWRM_VERSION_UPDATE 0 +#define HWRM_VERSION_MINOR 2 +#define HWRM_VERSION_UPDATE 2 -#define HWRM_VERSION_STR "1.0.0" +#define HWRM_VERSION_STR "1.2.2" /* * Following is the signature for HWRM message field that indicates not * applicable (All F's). Need to cast it the size of the field if needed. @@ -444,7 +541,7 @@ struct cmd_nums { #define HWRM_FUNC_BUF_RGTR (0x1fUL) #define HWRM_PORT_PHY_CFG (0x20UL) #define HWRM_PORT_MAC_CFG (0x21UL) - #define RESERVED2 (0x22UL) + #define HWRM_PORT_TS_QUERY (0x22UL) #define HWRM_PORT_QSTATS (0x23UL) #define HWRM_PORT_LPBK_QSTATS (0x24UL) #define HWRM_PORT_CLR_STATS (0x25UL) @@ -452,6 +549,9 @@ struct cmd_nums { #define HWRM_PORT_PHY_QCFG (0x27UL) #define HWRM_PORT_MAC_QCFG (0x28UL) #define HWRM_PORT_BLINK_LED (0x29UL) + #define HWRM_PORT_PHY_QCAPS (0x2aUL) + #define HWRM_PORT_PHY_I2C_WRITE (0x2bUL) + #define HWRM_PORT_PHY_I2C_READ (0x2cUL) #define HWRM_QUEUE_QPORTCFG (0x30UL) #define HWRM_QUEUE_QCFG (0x31UL) #define HWRM_QUEUE_CFG (0x32UL) @@ -531,6 +631,7 @@ struct cmd_nums { __le16 unused_0[3]; }; +/* Return Codes (8 bytes) */ struct ret_codes { __le16 error_code; #define HWRM_ERR_CODE_SUCCESS (0x0UL) @@ -875,10 +976,11 @@ struct hwrm_func_vf_cfg_input { #define FUNC_VF_CFG_REQ_ENABLES_MTU 0x1UL #define FUNC_VF_CFG_REQ_ENABLES_GUEST_VLAN 0x2UL #define FUNC_VF_CFG_REQ_ENABLES_ASYNC_EVENT_CR 0x4UL + #define FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR 0x8UL __le16 mtu; __le16 guest_vlan; __le16 async_event_cr; - __le16 unused_0[3]; + u8 dflt_mac_addr[6]; }; /* Output (16 bytes) */ @@ -917,7 +1019,8 @@ struct hwrm_func_qcaps_output { __le32 flags; #define FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED 0x1UL #define FUNC_QCAPS_RESP_FLAGS_GLOBAL_MSIX_AUTOMASKING 0x2UL - u8 perm_mac_address[6]; + #define FUNC_QCAPS_RESP_FLAGS_PTP_SUPPORTED 0x4UL + u8 mac_address[6]; __le16 max_rsscos_ctx; __le16 max_cmpl_rings; __le16 max_tx_rings; @@ -942,6 +1045,67 @@ struct hwrm_func_qcaps_output { u8 valid; }; +/* hwrm_func_qcfg */ +/* Input (24 bytes) */ +struct hwrm_func_qcfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 fid; + __le16 unused_0[3]; +}; + +/* Output (72 bytes) */ +struct hwrm_func_qcfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 fid; + __le16 port_id; + __le16 vlan; + u8 unused_0; + u8 unused_1; + u8 mac_address[6]; + __le16 pci_id; + __le16 alloc_rsscos_ctx; + __le16 alloc_cmpl_rings; + __le16 alloc_tx_rings; + __le16 alloc_rx_rings; + __le16 alloc_l2_ctx; + __le16 alloc_vnics; + __le16 mtu; + __le16 mru; + __le16 stat_ctx_id; + u8 port_partition_type; + #define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_SPF (0x0UL << 0) + #define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_MPFS (0x1UL << 0) + #define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_0 (0x2UL << 0) + #define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_5 (0x3UL << 0) + #define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR2_0 (0x4UL << 0) + #define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_UNKNOWN (0xffUL << 0) + u8 unused_2; + __le16 dflt_vnic_id; + u8 unused_3; + u8 unused_4; + __le32 min_bw; + __le32 max_bw; + u8 evb_mode; + #define FUNC_QCFG_RESP_EVB_MODE_NO_EVB (0x0UL << 0) + #define FUNC_QCFG_RESP_EVB_MODE_VEB (0x1UL << 0) + #define FUNC_QCFG_RESP_EVB_MODE_VEPA (0x2UL << 0) + u8 unused_5; + __le16 unused_6; + __le32 alloc_mcast_filters; + __le32 alloc_hw_ring_grps; + u8 unused_7; + u8 unused_8; + u8 unused_9; + u8 valid; +}; + /* hwrm_func_cfg */ /* Input (88 bytes) */ struct hwrm_func_cfg_input { @@ -1171,6 +1335,7 @@ struct hwrm_func_drv_rgtr_input { #define FUNC_DRV_RGTR_REQ_OS_TYPE_UNKNOWN (0x0UL << 0) #define FUNC_DRV_RGTR_REQ_OS_TYPE_OTHER (0x1UL << 0) #define FUNC_DRV_RGTR_REQ_OS_TYPE_MSDOS (0xeUL << 0) + #define FUNC_DRV_RGTR_REQ_OS_TYPE_WINDOWS (0x12UL << 0) #define FUNC_DRV_RGTR_REQ_OS_TYPE_SOLARIS (0x1dUL << 0) #define FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX (0x24UL << 0) #define FUNC_DRV_RGTR_REQ_OS_TYPE_FREEBSD (0x2aUL << 0) @@ -1302,6 +1467,7 @@ struct hwrm_func_drv_qver_output { #define FUNC_DRV_QVER_RESP_OS_TYPE_UNKNOWN (0x0UL << 0) #define FUNC_DRV_QVER_RESP_OS_TYPE_OTHER (0x1UL << 0) #define FUNC_DRV_QVER_RESP_OS_TYPE_MSDOS (0xeUL << 0) + #define FUNC_DRV_QVER_RESP_OS_TYPE_WINDOWS (0x12UL << 0) #define FUNC_DRV_QVER_RESP_OS_TYPE_SOLARIS (0x1dUL << 0) #define FUNC_DRV_QVER_RESP_OS_TYPE_LINUX (0x24UL << 0) #define FUNC_DRV_QVER_RESP_OS_TYPE_FREEBSD (0x2aUL << 0) @@ -1317,7 +1483,7 @@ struct hwrm_func_drv_qver_output { }; /* hwrm_port_phy_cfg */ -/* Input (48 bytes) */ +/* Input (56 bytes) */ struct hwrm_port_phy_cfg_input { __le16 req_type; __le16 cmpl_ring; @@ -1329,6 +1495,10 @@ struct hwrm_port_phy_cfg_input { #define PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN 0x2UL #define PORT_PHY_CFG_REQ_FLAGS_FORCE 0x4UL #define PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG 0x8UL + #define PORT_PHY_CFG_REQ_FLAGS_EEE_ENABLE 0x10UL + #define PORT_PHY_CFG_REQ_FLAGS_EEE_DISABLE 0x20UL + #define PORT_PHY_CFG_REQ_FLAGS_EEE_TX_LPI_ENABLE 0x40UL + #define PORT_PHY_CFG_REQ_FLAGS_EEE_TX_LPI_DISABLE 0x80UL __le32 enables; #define PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE 0x1UL #define PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX 0x2UL @@ -1339,6 +1509,8 @@ struct hwrm_port_phy_cfg_input { #define PORT_PHY_CFG_REQ_ENABLES_LPBK 0x40UL #define PORT_PHY_CFG_REQ_ENABLES_PREEMPHASIS 0x80UL #define PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE 0x100UL + #define PORT_PHY_CFG_REQ_ENABLES_EEE_LINK_SPEED_MASK 0x200UL + #define PORT_PHY_CFG_REQ_ENABLES_TX_LPI_TIMER 0x400UL __le16 port_id; __le16 force_link_speed; #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_100MB (0x1UL << 0) @@ -1350,12 +1522,14 @@ struct hwrm_port_phy_cfg_input { #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_25GB (0xfaUL << 0) #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_40GB (0x190UL << 0) #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_50GB (0x1f4UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_100GB (0x3e8UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_10MB (0xffffUL << 0) u8 auto_mode; #define PORT_PHY_CFG_REQ_AUTO_MODE_NONE (0x0UL << 0) #define PORT_PHY_CFG_REQ_AUTO_MODE_ALL_SPEEDS (0x1UL << 0) #define PORT_PHY_CFG_REQ_AUTO_MODE_ONE_SPEED (0x2UL << 0) #define PORT_PHY_CFG_REQ_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0) - #define PORT_PHY_CFG_REQ_AUTO_MODE_MASK (0x4UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK (0x4UL << 0) u8 auto_duplex; #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_HALF (0x0UL << 0) #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_FULL (0x1UL << 0) @@ -1363,6 +1537,7 @@ struct hwrm_port_phy_cfg_input { u8 auto_pause; #define PORT_PHY_CFG_REQ_AUTO_PAUSE_TX 0x1UL #define PORT_PHY_CFG_REQ_AUTO_PAUSE_RX 0x2UL + #define PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE 0x4UL u8 unused_0; __le16 auto_link_speed; #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB (0x1UL << 0) @@ -1374,6 +1549,8 @@ struct hwrm_port_phy_cfg_input { #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB (0xfaUL << 0) #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB (0x190UL << 0) #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB (0x1f4UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100GB (0x3e8UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10MB (0xffffUL << 0) __le16 auto_link_speed_mask; #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_100MBHD 0x1UL #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_100MB 0x2UL @@ -1386,6 +1563,9 @@ struct hwrm_port_phy_cfg_input { #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_25GB 0x100UL #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_40GB 0x200UL #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_50GB 0x400UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_100GB 0x800UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_10MBHD 0x1000UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_10MB 0x2000UL u8 wirespeed; #define PORT_PHY_CFG_REQ_WIRESPEED_OFF (0x0UL << 0) #define PORT_PHY_CFG_REQ_WIRESPEED_ON (0x1UL << 0) @@ -1398,7 +1578,20 @@ struct hwrm_port_phy_cfg_input { #define PORT_PHY_CFG_REQ_FORCE_PAUSE_RX 0x2UL u8 unused_1; __le32 preemphasis; - __le32 unused_2; + __le16 eee_link_speed_mask; + #define PORT_PHY_CFG_REQ_EEE_LINK_SPEED_MASK_RSVD1 0x1UL + #define PORT_PHY_CFG_REQ_EEE_LINK_SPEED_MASK_100MB 0x2UL + #define PORT_PHY_CFG_REQ_EEE_LINK_SPEED_MASK_RSVD2 0x4UL + #define PORT_PHY_CFG_REQ_EEE_LINK_SPEED_MASK_1GB 0x8UL + #define PORT_PHY_CFG_REQ_EEE_LINK_SPEED_MASK_RSVD3 0x10UL + #define PORT_PHY_CFG_REQ_EEE_LINK_SPEED_MASK_RSVD4 0x20UL + #define PORT_PHY_CFG_REQ_EEE_LINK_SPEED_MASK_10GB 0x40UL + u8 unused_2; + u8 unused_3; + __le32 tx_lpi_timer; + __le32 unused_4; + #define PORT_PHY_CFG_REQ_TX_LPI_TIMER_MASK 0xffffffUL + #define PORT_PHY_CFG_REQ_TX_LPI_TIMER_SFT 0 }; /* Output (16 bytes) */ @@ -1426,7 +1619,7 @@ struct hwrm_port_phy_qcfg_input { __le16 unused_0[3]; }; -/* Output (48 bytes) */ +/* Output (96 bytes) */ struct hwrm_port_phy_qcfg_output { __le16 error_code; __le16 req_type; @@ -1447,6 +1640,8 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_LINK_SPEED_25GB (0xfaUL << 0) #define PORT_PHY_QCFG_RESP_LINK_SPEED_40GB (0x190UL << 0) #define PORT_PHY_QCFG_RESP_LINK_SPEED_50GB (0x1f4UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_100GB (0x3e8UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_10MB (0xffffUL << 0) u8 duplex; #define PORT_PHY_QCFG_RESP_DUPLEX_HALF (0x0UL << 0) #define PORT_PHY_QCFG_RESP_DUPLEX_FULL (0x1UL << 0) @@ -1465,6 +1660,9 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_25GB 0x100UL #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB 0x200UL #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB 0x400UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100GB 0x800UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_10MBHD 0x1000UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_10MB 0x2000UL __le16 force_link_speed; #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_100MB (0x1UL << 0) #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_1GB (0xaUL << 0) @@ -1475,15 +1673,18 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_25GB (0xfaUL << 0) #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_40GB (0x190UL << 0) #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_50GB (0x1f4UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_100GB (0x3e8UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_10MB (0xffffUL << 0) u8 auto_mode; #define PORT_PHY_QCFG_RESP_AUTO_MODE_NONE (0x0UL << 0) #define PORT_PHY_QCFG_RESP_AUTO_MODE_ALL_SPEEDS (0x1UL << 0) #define PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_SPEED (0x2UL << 0) #define PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0) - #define PORT_PHY_QCFG_RESP_AUTO_MODE_MASK (0x4UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_MODE_SPEED_MASK (0x4UL << 0) u8 auto_pause; #define PORT_PHY_QCFG_RESP_AUTO_PAUSE_TX 0x1UL #define PORT_PHY_QCFG_RESP_AUTO_PAUSE_RX 0x2UL + #define PORT_PHY_QCFG_RESP_AUTO_PAUSE_AUTONEG_PAUSE 0x4UL __le16 auto_link_speed; #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_100MB (0x1UL << 0) #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_1GB (0xaUL << 0) @@ -1494,6 +1695,8 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_25GB (0xfaUL << 0) #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_40GB (0x190UL << 0) #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_50GB (0x1f4UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_100GB (0x3e8UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_10MB (0xffffUL << 0) __le16 auto_link_speed_mask; #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_100MBHD 0x1UL #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_100MB 0x2UL @@ -1506,6 +1709,9 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_25GB 0x100UL #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_40GB 0x200UL #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_50GB 0x400UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_100GB 0x800UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_10MBHD 0x1000UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_10MB 0x2000UL u8 wirespeed; #define PORT_PHY_QCFG_RESP_WIRESPEED_OFF (0x0UL << 0) #define PORT_PHY_QCFG_RESP_WIRESPEED_ON (0x1UL << 0) @@ -1516,31 +1722,49 @@ struct hwrm_port_phy_qcfg_output { u8 force_pause; #define PORT_PHY_QCFG_RESP_FORCE_PAUSE_TX 0x1UL #define PORT_PHY_QCFG_RESP_FORCE_PAUSE_RX 0x2UL - u8 reserved1; + u8 module_status; + #define PORT_PHY_QCFG_RESP_MODULE_STATUS_NONE (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_MODULE_STATUS_WARNINGMSG (0x2UL << 0) + #define PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN (0x3UL << 0) + #define PORT_PHY_QCFG_RESP_MODULE_STATUS_NOTINSERTED (0x4UL << 0) + #define PORT_PHY_QCFG_RESP_MODULE_STATUS_NOTAPPLICABLE (0xffUL << 0) __le32 preemphasis; u8 phy_maj; u8 phy_min; u8 phy_bld; u8 phy_type; - #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASECR4 (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_UNKNOWN (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASECR (0x1UL << 0) #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR4 (0x2UL << 0) - #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASELR4 (0x3UL << 0) - #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASESR4 (0x4UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASELR (0x3UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASESR (0x4UL << 0) #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR2 (0x5UL << 0) - #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKX4 (0x6UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKX (0x6UL << 0) #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR (0x7UL << 0) #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASET (0x8UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASETE (0x9UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_SGMIIEXTPHY (0xaUL << 0) u8 media_type; + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_UNKNOWN (0x0UL << 0) #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP (0x1UL << 0) #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC (0x2UL << 0) #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE (0x3UL << 0) - u8 transceiver_type; - #define PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL (0x1UL << 0) - #define PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_EXTERNAL (0x2UL << 0) - u8 phy_addr; + u8 xcvr_pkg_type; + #define PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_EXTERNAL (0x2UL << 0) + u8 eee_config_phy_addr; #define PORT_PHY_QCFG_RESP_PHY_ADDR_MASK 0x1fUL #define PORT_PHY_QCFG_RESP_PHY_ADDR_SFT 0 - u8 unused_2; + #define PORT_PHY_QCFG_RESP_EEE_CONFIG_EEE_ENABLED 0x20UL + #define PORT_PHY_QCFG_RESP_EEE_CONFIG_EEE_ACTIVE 0x40UL + #define PORT_PHY_QCFG_RESP_EEE_CONFIG_EEE_TX_LPI 0x80UL + #define PORT_PHY_QCFG_RESP_EEE_CONFIG_MASK 0xe0UL + #define PORT_PHY_QCFG_RESP_EEE_CONFIG_SFT 5 + u8 parallel_detect; + #define PORT_PHY_QCFG_RESP_PARALLEL_DETECT 0x1UL + #define PORT_PHY_QCFG_RESP_RESERVED_MASK 0xfeUL + #define PORT_PHY_QCFG_RESP_RESERVED_SFT 1 __le16 link_partner_adv_speeds; #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_100MBHD 0x1UL #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_100MB 0x2UL @@ -1553,15 +1777,48 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_25GB 0x100UL #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_40GB 0x200UL #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_50GB 0x400UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_100GB 0x800UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_10MBHD 0x1000UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_10MB 0x2000UL u8 link_partner_adv_auto_mode; #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_NONE (0x0UL << 0) #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ALL_SPEEDS (0x1UL << 0) #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ONE_SPEED (0x2UL << 0) #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0) - #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_MASK (0x4UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_SPEED_MASK (0x4UL << 0) u8 link_partner_adv_pause; #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_PAUSE_TX 0x1UL #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_PAUSE_RX 0x2UL + __le16 adv_eee_link_speed_mask; + #define PORT_PHY_QCFG_RESP_ADV_EEE_LINK_SPEED_MASK_RSVD1 0x1UL + #define PORT_PHY_QCFG_RESP_ADV_EEE_LINK_SPEED_MASK_100MB 0x2UL + #define PORT_PHY_QCFG_RESP_ADV_EEE_LINK_SPEED_MASK_RSVD2 0x4UL + #define PORT_PHY_QCFG_RESP_ADV_EEE_LINK_SPEED_MASK_1GB 0x8UL + #define PORT_PHY_QCFG_RESP_ADV_EEE_LINK_SPEED_MASK_RSVD3 0x10UL + #define PORT_PHY_QCFG_RESP_ADV_EEE_LINK_SPEED_MASK_RSVD4 0x20UL + #define PORT_PHY_QCFG_RESP_ADV_EEE_LINK_SPEED_MASK_10GB 0x40UL + __le16 link_partner_adv_eee_link_speed_mask; + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD1 0x1UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_100MB 0x2UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD2 0x4UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_1GB 0x8UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD3 0x10UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD4 0x20UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_10GB 0x40UL + __le32 xcvr_identifier_type_tx_lpi_timer; + #define PORT_PHY_QCFG_RESP_TX_LPI_TIMER_MASK 0xffffffUL + #define PORT_PHY_QCFG_RESP_TX_LPI_TIMER_SFT 0 + #define PORT_PHY_QCFG_RESP_XCVR_IDENTIFIER_TYPE_MASK 0xff000000UL + #define PORT_PHY_QCFG_RESP_XCVR_IDENTIFIER_TYPE_SFT 24 + #define PORT_PHY_QCFG_RESP_XCVR_IDENTIFIER_TYPE_UNKNOWN (0x0UL << 24) + #define PORT_PHY_QCFG_RESP_XCVR_IDENTIFIER_TYPE_SFP (0x3UL << 24) + #define PORT_PHY_QCFG_RESP_XCVR_IDENTIFIER_TYPE_QSFP (0xcUL << 24) + #define PORT_PHY_QCFG_RESP_XCVR_IDENTIFIER_TYPE_QSFPPLUS (0xdUL << 24) + #define PORT_PHY_QCFG_RESP_XCVR_IDENTIFIER_TYPE_QSFP28 (0x11UL << 24) + __le32 unused_1; + char phy_vendor_name[16]; + char phy_vendor_partnumber[16]; + __le32 unused_2; u8 unused_3; u8 unused_4; u8 unused_5; @@ -1569,7 +1826,7 @@ struct hwrm_port_phy_qcfg_output { }; /* hwrm_port_mac_cfg */ -/* Input (32 bytes) */ +/* Input (40 bytes) */ struct hwrm_port_mac_cfg_input { __le16 req_type; __le16 cmpl_ring; @@ -1581,6 +1838,10 @@ struct hwrm_port_mac_cfg_input { #define PORT_MAC_CFG_REQ_FLAGS_COS_ASSIGNMENT_ENABLE 0x2UL #define PORT_MAC_CFG_REQ_FLAGS_TUNNEL_PRI2COS_ENABLE 0x4UL #define PORT_MAC_CFG_REQ_FLAGS_IP_DSCP2COS_ENABLE 0x8UL + #define PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_ENABLE 0x10UL + #define PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE 0x20UL + #define PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_ENABLE 0x40UL + #define PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_DISABLE 0x80UL __le32 enables; #define PORT_MAC_CFG_REQ_ENABLES_IPG 0x1UL #define PORT_MAC_CFG_REQ_ENABLES_LPBK 0x2UL @@ -1588,6 +1849,8 @@ struct hwrm_port_mac_cfg_input { #define PORT_MAC_CFG_REQ_ENABLES_LCOS_MAP_PRI 0x8UL #define PORT_MAC_CFG_REQ_ENABLES_TUNNEL_PRI2COS_MAP_PRI 0x10UL #define PORT_MAC_CFG_REQ_ENABLES_DSCP2COS_MAP_PRI 0x20UL + #define PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE 0x40UL + #define PORT_MAC_CFG_REQ_ENABLES_TX_TS_CAPTURE_PTP_MSG_TYPE 0x80UL __le16 port_id; u8 ipg; u8 lpbk; @@ -1598,6 +1861,9 @@ struct hwrm_port_mac_cfg_input { u8 lcos_map_pri; u8 tunnel_pri2cos_map_pri; u8 dscp2pri_map_pri; + __le16 rx_ts_capture_ptp_msg_type; + __le16 tx_ts_capture_ptp_msg_type; + __le32 unused_0; }; /* Output (16 bytes) */ @@ -1754,7 +2020,79 @@ struct hwrm_port_blink_led_output { u8 valid; }; -/* hwrm_queue_qportcfg */ +/* hwrm_port_phy_qcaps */ +/* Input (24 bytes) */ +struct hwrm_port_phy_qcaps_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 port_id; + __le16 unused_0[3]; +}; + +/* Output (24 bytes) */ +struct hwrm_port_phy_qcaps_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 eee_supported; + #define PORT_PHY_QCAPS_RESP_EEE_SUPPORTED 0x1UL + #define PORT_PHY_QCAPS_RESP_RSVD1_MASK 0xfeUL + #define PORT_PHY_QCAPS_RESP_RSVD1_SFT 1 + u8 unused_0; + __le16 supported_speeds_force_mode; + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_100MBHD 0x1UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_100MB 0x2UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_1GBHD 0x4UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_1GB 0x8UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_2GB 0x10UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_2_5GB 0x20UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_10GB 0x40UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_20GB 0x80UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_25GB 0x100UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_40GB 0x200UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_50GB 0x400UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_100GB 0x800UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_10MBHD 0x1000UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_10MB 0x2000UL + __le16 supported_speeds_auto_mode; + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100MBHD 0x1UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100MB 0x2UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_1GBHD 0x4UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_1GB 0x8UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_2GB 0x10UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_2_5GB 0x20UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_10GB 0x40UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_20GB 0x80UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_25GB 0x100UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_40GB 0x200UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_50GB 0x400UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100GB 0x800UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_10MBHD 0x1000UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_10MB 0x2000UL + __le16 supported_speeds_eee_mode; + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_RSVD1 0x1UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_100MB 0x2UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_RSVD2 0x4UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_1GB 0x8UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_RSVD3 0x10UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_RSVD4 0x20UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_10GB 0x40UL + __le32 tx_lpi_timer_low; + #define PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_LOW_MASK 0xffffffUL + #define PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_LOW_SFT 0 + #define PORT_PHY_QCAPS_RESP_RSVD2_MASK 0xff000000UL + #define PORT_PHY_QCAPS_RESP_RSVD2_SFT 24 + __le32 valid_tx_lpi_timer_high; + #define PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_HIGH_MASK 0xffffffUL + #define PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_HIGH_SFT 0 + #define PORT_PHY_QCAPS_RESP_VALID_MASK 0xff000000UL + #define PORT_PHY_QCAPS_RESP_VALID_SFT 24 +}; + /* Input (24 bytes) */ struct hwrm_queue_qportcfg_input { __le16 req_type; @@ -1766,6 +2104,7 @@ struct hwrm_queue_qportcfg_input { #define QUEUE_QPORTCFG_REQ_FLAGS_PATH 0x1UL #define QUEUE_QPORTCFG_REQ_FLAGS_PATH_TX (0x0UL << 0) #define QUEUE_QPORTCFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define QUEUE_QPORTCFG_REQ_FLAGS_PATH_LAST QUEUE_QPORTCFG_REQ_FLAGS_PATH_RX __le16 port_id; __le16 unused_0; }; @@ -1838,6 +2177,7 @@ struct hwrm_queue_cfg_input { #define QUEUE_CFG_REQ_FLAGS_PATH 0x1UL #define QUEUE_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) #define QUEUE_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define QUEUE_CFG_REQ_FLAGS_PATH_LAST QUEUE_CFG_REQ_FLAGS_PATH_RX __le32 enables; #define QUEUE_CFG_REQ_ENABLES_DFLT_LEN 0x1UL #define QUEUE_CFG_REQ_ENABLES_SERVICE_PROFILE 0x2UL @@ -1875,6 +2215,7 @@ struct hwrm_queue_buffers_cfg_input { #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH 0x1UL #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_LAST QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_RX __le32 enables; #define QUEUE_BUFFERS_CFG_REQ_ENABLES_RESERVED 0x1UL #define QUEUE_BUFFERS_CFG_REQ_ENABLES_SHARED 0x2UL @@ -1952,6 +2293,7 @@ struct hwrm_queue_pri2cos_cfg_input { #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH 0x1UL #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_LAST QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_RX #define QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN 0x2UL __le32 enables; u8 port_id; @@ -2158,6 +2500,8 @@ struct hwrm_vnic_cfg_input { #define VNIC_CFG_REQ_FLAGS_DEFAULT 0x1UL #define VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE 0x2UL #define VNIC_CFG_REQ_FLAGS_BD_STALL_MODE 0x4UL + #define VNIC_CFG_REQ_FLAGS_ROCE_DUAL_VNIC_MODE 0x8UL + #define VNIC_CFG_REQ_FLAGS_ROCE_ONLY_VNIC_MODE 0x10UL __le32 enables; #define VNIC_CFG_REQ_ENABLES_DFLT_RING_GRP 0x1UL #define VNIC_CFG_REQ_ENABLES_RSS_RULE 0x2UL @@ -2622,6 +2966,7 @@ struct hwrm_cfa_l2_filter_alloc_input { #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH 0x1UL #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_TX (0x0UL << 0) #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_LAST CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x2UL #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_DROP 0x4UL #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_OUTERMOST 0x8UL @@ -2747,6 +3092,7 @@ struct hwrm_cfa_l2_filter_cfg_input { #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH 0x1UL #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_LAST CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_RX #define CFA_L2_FILTER_CFG_REQ_FLAGS_DROP 0x2UL __le32 enables; #define CFA_L2_FILTER_CFG_REQ_ENABLES_DST_ID 0x1UL @@ -3337,6 +3683,41 @@ struct hwrm_fw_reset_output { u8 valid; }; +/* hwrm_fw_qstatus */ +/* Input (24 bytes) */ +struct hwrm_fw_qstatus_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 embedded_proc_type; + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_BOOT (0x0UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_MGMT (0x1UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_NETCTRL (0x2UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_ROCE (0x3UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_RSVD (0x4UL << 0) + u8 unused_0[7]; +}; + +/* Output (16 bytes) */ +struct hwrm_fw_qstatus_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 selfrst_status; + #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTNONE (0x0UL << 0) + #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTASAP (0x1UL << 0) + #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTPCIERST (0x2UL << 0) + u8 unused_0; + __le16 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + /* hwrm_exec_fwd_resp */ /* Input (128 bytes) */ struct hwrm_exec_fwd_resp_input { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h index 43ef392c8588..40a7b0e09612 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index 0c5f510492f1..8457850b0bdd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -771,12 +771,8 @@ static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf) PORT_PHY_QCFG_RESP_LINK_NO_LINK) { phy_qcfg_resp.link = PORT_PHY_QCFG_RESP_LINK_LINK; - if (phy_qcfg_resp.auto_link_speed) - phy_qcfg_resp.link_speed = - phy_qcfg_resp.auto_link_speed; - else - phy_qcfg_resp.link_speed = - phy_qcfg_resp.force_link_speed; + phy_qcfg_resp.link_speed = cpu_to_le16( + PORT_PHY_QCFG_RESP_LINK_SPEED_10GB); phy_qcfg_resp.duplex = PORT_PHY_QCFG_RESP_DUPLEX_FULL; phy_qcfg_resp.pause = @@ -859,8 +855,8 @@ void bnxt_update_vf_mac(struct bnxt *bp) * default but the stored zero MAC will allow the VF user to change * the random MAC address using ndo_set_mac_address() if he wants. */ - if (!ether_addr_equal(resp->perm_mac_address, bp->vf.mac_addr)) - memcpy(bp->vf.mac_addr, resp->perm_mac_address, ETH_ALEN); + if (!ether_addr_equal(resp->mac_address, bp->vf.mac_addr)) + memcpy(bp->vf.mac_addr, resp->mac_address, ETH_ALEN); /* overwrite netdev dev_addr with admin VF MAC */ if (is_valid_ether_addr(bp->vf.mac_addr)) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h index c151280e3980..3f08354a247e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h @@ -1,6 +1,6 @@ /* Broadcom NetXtreme-C/E network driver. * - * Copyright (c) 2014-2015 Broadcom Corporation + * Copyright (c) 2014-2016 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- GitLab From c9ee9516c161da2d072e035907aa35a35dfa68a8 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:08:56 -0400 Subject: [PATCH 1483/9938] bnxt_en: Improve flow control autoneg with Firmware 1.2.1 interface. Make use of the new AUTONEG_PAUSE bit in the new interface to better control autoneg flow control settings, independent of RX and TX advertisement settings. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 28 +++++++++++++++---- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 10 +++---- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index bfe98cbcefca..2b5a54162f80 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4557,6 +4557,9 @@ static void bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req) { if (bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) { + if (bp->hwrm_spec_code >= 0x10201) + req->auto_pause = + PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE; if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX) req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX) @@ -4570,6 +4573,11 @@ bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req) req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_TX; req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE); + if (bp->hwrm_spec_code >= 0x10201) { + req->auto_pause = req->force_pause; + req->enables |= cpu_to_le32( + PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); + } } } @@ -4656,7 +4664,8 @@ static int bnxt_update_phy_setting(struct bnxt *bp) return rc; } if ((link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) && - link_info->auto_pause_setting != link_info->req_flow_ctrl) + (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) != + link_info->req_flow_ctrl) update_pause = true; if (!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) && link_info->force_pause_setting != link_info->req_flow_ctrl) @@ -5825,15 +5834,24 @@ static int bnxt_probe_phy(struct bnxt *bp) /*initialize the ethool setting copy with NVM settings */ if (BNXT_AUTO_MODE(link_info->auto_mode)) { - link_info->autoneg = BNXT_AUTONEG_SPEED | - BNXT_AUTONEG_FLOW_CTRL; + link_info->autoneg = BNXT_AUTONEG_SPEED; + if (bp->hwrm_spec_code >= 0x10201) { + if (link_info->auto_pause_setting & + PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE) + link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; + } else { + link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; + } link_info->advertising = link_info->auto_link_speeds; - link_info->req_flow_ctrl = link_info->auto_pause_setting; } else { link_info->req_link_speed = link_info->force_link_speed; link_info->req_duplex = link_info->duplex_setting; - link_info->req_flow_ctrl = link_info->force_pause_setting; } + if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) + link_info->req_flow_ctrl = + link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH; + else + link_info->req_flow_ctrl = link_info->force_pause_setting; return rc; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index f103f9b06e6d..99b1740781d5 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -874,7 +874,9 @@ static int bnxt_set_pauseparam(struct net_device *dev, return -EINVAL; link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; - link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH; + if (bp->hwrm_spec_code >= 0x10201) + link_info->req_flow_ctrl = + PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE; } else { /* when transition from auto pause to force pause, * force a link change @@ -882,17 +884,13 @@ static int bnxt_set_pauseparam(struct net_device *dev, if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) link_info->force_link_chng = true; link_info->autoneg &= ~BNXT_AUTONEG_FLOW_CTRL; - link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_BOTH; + link_info->req_flow_ctrl = 0; } if (epause->rx_pause) link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_RX; - else - link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_RX; if (epause->tx_pause) link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX; - else - link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_TX; if (netif_running(dev)) rc = bnxt_hwrm_set_pause(bp); -- GitLab From 170ce01301a2a1a87808765531d938fa0b023641 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:08:57 -0400 Subject: [PATCH 1484/9938] bnxt_en: Add basic EEE support. Get EEE capability and the initial EEE settings from firmware. Add "EEE is active | not active" to link up dmesg. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 82 ++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 + .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.h | 1 + 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 2b5a54162f80..7442e206760f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4488,12 +4488,49 @@ static void bnxt_report_link(struct bnxt *bp) speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed); netdev_info(bp->dev, "NIC Link is Up, %d Mbps %s duplex, Flow control: %s\n", speed, duplex, flow_ctrl); + if (bp->flags & BNXT_FLAG_EEE_CAP) + netdev_info(bp->dev, "EEE is %s\n", + bp->eee.eee_active ? "active" : + "not active"); } else { netif_carrier_off(bp->dev); netdev_err(bp->dev, "NIC Link is Down\n"); } } +static int bnxt_hwrm_phy_qcaps(struct bnxt *bp) +{ + int rc = 0; + struct hwrm_port_phy_qcaps_input req = {0}; + struct hwrm_port_phy_qcaps_output *resp = bp->hwrm_cmd_resp_addr; + + if (bp->hwrm_spec_code < 0x10201) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCAPS, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) + goto hwrm_phy_qcaps_exit; + + if (resp->eee_supported & PORT_PHY_QCAPS_RESP_EEE_SUPPORTED) { + struct ethtool_eee *eee = &bp->eee; + u16 fw_speeds = le16_to_cpu(resp->supported_speeds_eee_mode); + + bp->flags |= BNXT_FLAG_EEE_CAP; + eee->supported = _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0); + bp->lpi_tmr_lo = le32_to_cpu(resp->tx_lpi_timer_low) & + PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_LOW_MASK; + bp->lpi_tmr_hi = le32_to_cpu(resp->valid_tx_lpi_timer_high) & + PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_HIGH_MASK; + } + +hwrm_phy_qcaps_exit: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) { int rc = 0; @@ -4535,8 +4572,44 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) link_info->phy_ver[2] = resp->phy_bld; link_info->media_type = resp->media_type; link_info->transceiver = resp->xcvr_pkg_type; - link_info->phy_addr = resp->eee_config_phy_addr; + link_info->phy_addr = resp->eee_config_phy_addr & + PORT_PHY_QCFG_RESP_PHY_ADDR_MASK; + + if (bp->flags & BNXT_FLAG_EEE_CAP) { + struct ethtool_eee *eee = &bp->eee; + u16 fw_speeds; + + eee->eee_active = 0; + if (resp->eee_config_phy_addr & + PORT_PHY_QCFG_RESP_EEE_CONFIG_EEE_ACTIVE) { + eee->eee_active = 1; + fw_speeds = le16_to_cpu( + resp->link_partner_adv_eee_link_speed_mask); + eee->lp_advertised = + _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0); + } + + /* Pull initial EEE config */ + if (!chng_link_state) { + if (resp->eee_config_phy_addr & + PORT_PHY_QCFG_RESP_EEE_CONFIG_EEE_ENABLED) + eee->eee_enabled = 1; + fw_speeds = le16_to_cpu(resp->adv_eee_link_speed_mask); + eee->advertised = + _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0); + + if (resp->eee_config_phy_addr & + PORT_PHY_QCFG_RESP_EEE_CONFIG_EEE_TX_LPI) { + __le32 tmr; + + eee->tx_lpi_enabled = 1; + tmr = resp->xcvr_identifier_type_tx_lpi_timer; + eee->tx_lpi_timer = le32_to_cpu(tmr) & + PORT_PHY_QCFG_RESP_TX_LPI_TIMER_MASK; + } + } + } /* TODO: need to add more logic to report VF link */ if (chng_link_state) { if (link_info->phy_link_status == BNXT_LINK_LINK) @@ -5825,6 +5898,13 @@ static int bnxt_probe_phy(struct bnxt *bp) int rc = 0; struct bnxt_link_info *link_info = &bp->link_info; + rc = bnxt_hwrm_phy_qcaps(bp); + if (rc) { + netdev_err(bp->dev, "Probe phy can't get phy capabilities (rc: %x)\n", + rc); + return rc; + } + rc = bnxt_update_link(bp, false); if (rc) { netdev_err(bp->dev, "Probe phy can't update link (rc: %x)\n", diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index e98c37ae81f2..5e8340523cf6 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -874,6 +874,7 @@ struct bnxt { #define BNXT_FLAG_RFS 0x100 #define BNXT_FLAG_SHARED_RINGS 0x200 #define BNXT_FLAG_PORT_STATS 0x400 + #define BNXT_FLAG_EEE_CAP 0x1000 #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \ BNXT_FLAG_RFS | \ @@ -1011,6 +1012,9 @@ struct bnxt { int ntp_fltr_count; struct bnxt_link_info link_info; + struct ethtool_eee eee; + u32 lpi_tmr_lo; + u32 lpi_tmr_hi; }; #ifdef CONFIG_NET_RX_BUSY_POLL diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 99b1740781d5..bdc62209a9c1 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -597,7 +597,7 @@ static void bnxt_get_drvinfo(struct net_device *dev, kfree(pkglog); } -static u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause) +u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause) { u32 speed_mask = 0; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h index b2d8bd3a37fb..e061f8f7a3ae 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h @@ -12,6 +12,7 @@ extern const struct ethtool_ops bnxt_ethtool_ops; +u32 _bnxt_fw_to_ethtool_adv_spds(u16, u8); u32 bnxt_fw_to_ethtool_speed(u16); #endif -- GitLab From 939f7f0ca442187db2a4ec7a40979c711b0c939e Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:08:58 -0400 Subject: [PATCH 1485/9938] bnxt_en: Add EEE setup code. 1. Add bnxt_hwrm_set_eee() function to setup EEE firmware parameters based on the bp->eee settings. 2. The new function bnxt_eee_config_ok() will check if EEE parameters need to be modified due to autoneg changes. 3. bnxt_hwrm_set_link() has added a new parameter to update EEE. If the parameter is set, it will call bnxt_hwrm_set_eee(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 58 ++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 +- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 4 +- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.h | 1 + 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 7442e206760f..2c3c7950bfea 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4711,7 +4711,30 @@ int bnxt_hwrm_set_pause(struct bnxt *bp) return rc; } -int bnxt_hwrm_set_link_setting(struct bnxt *bp, bool set_pause) +static void bnxt_hwrm_set_eee(struct bnxt *bp, + struct hwrm_port_phy_cfg_input *req) +{ + struct ethtool_eee *eee = &bp->eee; + + if (eee->eee_enabled) { + u16 eee_speeds; + u32 flags = PORT_PHY_CFG_REQ_FLAGS_EEE_ENABLE; + + if (eee->tx_lpi_enabled) + flags |= PORT_PHY_CFG_REQ_FLAGS_EEE_TX_LPI_ENABLE; + else + flags |= PORT_PHY_CFG_REQ_FLAGS_EEE_TX_LPI_DISABLE; + + req->flags |= cpu_to_le32(flags); + eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised); + req->eee_link_speed_mask = cpu_to_le16(eee_speeds); + req->tx_lpi_timer = cpu_to_le32(eee->tx_lpi_timer); + } else { + req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_EEE_DISABLE); + } +} + +int bnxt_hwrm_set_link_setting(struct bnxt *bp, bool set_pause, bool set_eee) { struct hwrm_port_phy_cfg_input req = {0}; @@ -4720,14 +4743,42 @@ int bnxt_hwrm_set_link_setting(struct bnxt *bp, bool set_pause) bnxt_hwrm_set_pause_common(bp, &req); bnxt_hwrm_set_link_common(bp, &req); + + if (set_eee) + bnxt_hwrm_set_eee(bp, &req); return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); } +static bool bnxt_eee_config_ok(struct bnxt *bp) +{ + struct ethtool_eee *eee = &bp->eee; + struct bnxt_link_info *link_info = &bp->link_info; + + if (!(bp->flags & BNXT_FLAG_EEE_CAP)) + return true; + + if (eee->eee_enabled) { + u32 advertising = + _bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0); + + if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) { + eee->eee_enabled = 0; + return false; + } + if (eee->advertised & ~advertising) { + eee->advertised = advertising & eee->supported; + return false; + } + } + return true; +} + static int bnxt_update_phy_setting(struct bnxt *bp) { int rc; bool update_link = false; bool update_pause = false; + bool update_eee = false; struct bnxt_link_info *link_info = &bp->link_info; rc = bnxt_update_link(bp, true); @@ -4757,8 +4808,11 @@ static int bnxt_update_phy_setting(struct bnxt *bp) update_link = true; } + if (!bnxt_eee_config_ok(bp)) + update_eee = true; + if (update_link) - rc = bnxt_hwrm_set_link_setting(bp, update_pause); + rc = bnxt_hwrm_set_link_setting(bp, update_pause, update_eee); else if (update_pause) rc = bnxt_hwrm_set_pause(bp); if (rc) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 5e8340523cf6..a981e2c17107 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1112,7 +1112,7 @@ int hwrm_send_message_silent(struct bnxt *, void *, u32, int); int bnxt_hwrm_set_coal(struct bnxt *); int bnxt_hwrm_func_qcaps(struct bnxt *); int bnxt_hwrm_set_pause(struct bnxt *); -int bnxt_hwrm_set_link_setting(struct bnxt *, bool); +int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool); int bnxt_open_nic(struct bnxt *, bool, bool); int bnxt_close_nic(struct bnxt *, bool, bool); int bnxt_get_max_rings(struct bnxt *, int *, int *, bool); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index bdc62209a9c1..14f0520c5668 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -763,7 +763,7 @@ static u32 bnxt_get_fw_speed(struct net_device *dev, u16 ethtool_speed) return 0; } -static u16 bnxt_get_fw_auto_link_speeds(u32 advertising) +u16 bnxt_get_fw_auto_link_speeds(u32 advertising) { u16 fw_speed_mask = 0; @@ -840,7 +840,7 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } if (netif_running(dev)) - rc = bnxt_hwrm_set_link_setting(bp, set_pause); + rc = bnxt_hwrm_set_link_setting(bp, set_pause, false); set_setting_exit: return rc; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h index e061f8f7a3ae..3abc03b60dbc 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h @@ -14,5 +14,6 @@ extern const struct ethtool_ops bnxt_ethtool_ops; u32 _bnxt_fw_to_ethtool_adv_spds(u16, u8); u32 bnxt_fw_to_ethtool_speed(u16); +u16 bnxt_get_fw_auto_link_speeds(u32); #endif -- GitLab From 72b34f04e0b00956dd679ae18bf2163669df8b56 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:08:59 -0400 Subject: [PATCH 1486/9938] bnxt_en: Add get_eee() and set_eee() ethtool support. Allow users to get|set EEE parameters. v2: Added comment for preserving the tx_lpi_timer value in get_eee. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 14f0520c5668..47e08a8b1563 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -1379,6 +1379,80 @@ static int bnxt_set_eeprom(struct net_device *dev, eeprom->len); } +static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata) +{ + struct bnxt *bp = netdev_priv(dev); + struct ethtool_eee *eee = &bp->eee; + struct bnxt_link_info *link_info = &bp->link_info; + u32 advertising = + _bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0); + int rc = 0; + + if (BNXT_VF(bp)) + return 0; + + if (!(bp->flags & BNXT_FLAG_EEE_CAP)) + return -EOPNOTSUPP; + + if (!edata->eee_enabled) + goto eee_ok; + + if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) { + netdev_warn(dev, "EEE requires autoneg\n"); + return -EINVAL; + } + if (edata->tx_lpi_enabled) { + if (bp->lpi_tmr_hi && (edata->tx_lpi_timer > bp->lpi_tmr_hi || + edata->tx_lpi_timer < bp->lpi_tmr_lo)) { + netdev_warn(dev, "Valid LPI timer range is %d and %d microsecs\n", + bp->lpi_tmr_lo, bp->lpi_tmr_hi); + return -EINVAL; + } else if (!bp->lpi_tmr_hi) { + edata->tx_lpi_timer = eee->tx_lpi_timer; + } + } + if (!edata->advertised) { + edata->advertised = advertising & eee->supported; + } else if (edata->advertised & ~advertising) { + netdev_warn(dev, "EEE advertised %x must be a subset of autoneg advertised speeds %x\n", + edata->advertised, advertising); + return -EINVAL; + } + + eee->advertised = edata->advertised; + eee->tx_lpi_enabled = edata->tx_lpi_enabled; + eee->tx_lpi_timer = edata->tx_lpi_timer; +eee_ok: + eee->eee_enabled = edata->eee_enabled; + + if (netif_running(dev)) + rc = bnxt_hwrm_set_link_setting(bp, false, true); + + return rc; +} + +static int bnxt_get_eee(struct net_device *dev, struct ethtool_eee *edata) +{ + struct bnxt *bp = netdev_priv(dev); + + if (!(bp->flags & BNXT_FLAG_EEE_CAP)) + return -EOPNOTSUPP; + + *edata = bp->eee; + if (!bp->eee.eee_enabled) { + /* Preserve tx_lpi_timer so that the last value will be used + * by default when it is re-enabled. + */ + edata->advertised = 0; + edata->tx_lpi_enabled = 0; + } + + if (!bp->eee.eee_active) + edata->lp_advertised = 0; + + return 0; +} + const struct ethtool_ops bnxt_ethtool_ops = { .get_settings = bnxt_get_settings, .set_settings = bnxt_set_settings, @@ -1407,4 +1481,6 @@ const struct ethtool_ops bnxt_ethtool_ops = { .get_eeprom = bnxt_get_eeprom, .set_eeprom = bnxt_set_eeprom, .get_link = bnxt_get_link, + .get_eee = bnxt_get_eee, + .set_eee = bnxt_set_eee, }; -- GitLab From 25be862370031056989ee76e3c48c3ac8ff67fd4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:09:00 -0400 Subject: [PATCH 1487/9938] bnxt_en: Set async event bits when registering with the firmware. Currently, the driver only sets bit 0 of the async_event_fwd fields. To be compatible with the latest spec, we need to set the appropriate event bits handled by the driver. We should be handling link change and PF driver unload events, so these 2 bits should be set. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 2c3c7950bfea..dd0b32c58a24 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -118,6 +118,11 @@ static const u16 bnxt_vf_req_snif[] = { HWRM_CFA_L2_FILTER_ALLOC, }; +static const u16 bnxt_async_events_arr[] = { + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD, +}; + static bool bnxt_vf_pciid(enum board_idx idx) { return (idx == BCM57304_VF || idx == BCM57404_VF); @@ -2751,6 +2756,8 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp) { struct hwrm_func_drv_rgtr_input req = {0}; int i; + DECLARE_BITMAP(async_events_bmap, 256); + u32 *events = (u32 *)async_events_bmap; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR, -1, -1); @@ -2759,10 +2766,13 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp) FUNC_DRV_RGTR_REQ_ENABLES_VER | FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD); - /* TODO: current async event fwd bits are not defined and the firmware - * only checks if it is non-zero to enable async event forwarding - */ - req.async_event_fwd[0] |= cpu_to_le32(1); + memset(async_events_bmap, 0, sizeof(async_events_bmap)); + for (i = 0; i < ARRAY_SIZE(bnxt_async_events_arr); i++) + __set_bit(bnxt_async_events_arr[i], async_events_bmap); + + for (i = 0; i < 8; i++) + req.async_event_fwd[i] |= cpu_to_le32(events[i]); + req.os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX); req.ver_maj = DRV_VER_MAJ; req.ver_min = DRV_VER_MIN; -- GitLab From 4bb13abf208cb484a9b9d1af9233b0ef850c2fe7 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:09:01 -0400 Subject: [PATCH 1488/9938] bnxt_en: Add unsupported SFP+ module warnings. Add the PORT_CONN_NOT_ALLOWED async event handling logic. The driver will print an appropriate warning to reflect the SFP+ module enforcement policy done in the firmware. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 55 +++++++++++++++++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 3 ++ 2 files changed, 58 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index dd0b32c58a24..597e4724a474 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -121,6 +121,7 @@ static const u16 bnxt_vf_req_snif[] = { static const u16 bnxt_async_events_arr[] = { HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED, }; static bool bnxt_vf_pciid(enum board_idx idx) @@ -1236,6 +1237,19 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons, return rc; } +#define BNXT_GET_EVENT_PORT(data) \ + ((data) & \ + HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK) + +#define BNXT_EVENT_POLICY_MASK \ + HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK + +#define BNXT_EVENT_POLICY_SFT \ + HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT + +#define BNXT_GET_EVENT_POLICY(data) \ + (((data) & BNXT_EVENT_POLICY_MASK) >> BNXT_EVENT_POLICY_SFT) + static int bnxt_async_event_process(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl) { @@ -1249,6 +1263,22 @@ static int bnxt_async_event_process(struct bnxt *bp, case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD: set_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event); break; + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: { + u32 data1 = le32_to_cpu(cmpl->event_data1); + u16 port_id = BNXT_GET_EVENT_PORT(data1); + + if (BNXT_VF(bp)) + break; + + if (bp->pf.port_id != port_id) + break; + + bp->link_info.last_port_module_event = + BNXT_GET_EVENT_POLICY(data1); + + set_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event); + break; + } default: netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n", event_id); @@ -5447,6 +5477,28 @@ static void bnxt_timer(unsigned long data) mod_timer(&bp->timer, jiffies + bp->current_interval); } +static void bnxt_port_module_event(struct bnxt *bp) +{ + struct bnxt_link_info *link_info = &bp->link_info; + struct hwrm_port_phy_qcfg_output *resp = &link_info->phy_qcfg_resp; + + if (bnxt_update_link(bp, true)) + return; + + if (link_info->last_port_module_event != 0) { + netdev_warn(bp->dev, "Unqualified SFP+ module detected on port %d\n", + bp->pf.port_id); + if (bp->hwrm_spec_code >= 0x10201) { + netdev_warn(bp->dev, "Module part number %s\n", + resp->phy_vendor_partnumber); + } + } + if (link_info->last_port_module_event == 1) + netdev_warn(bp->dev, "TX is disabled\n"); + if (link_info->last_port_module_event == 3) + netdev_warn(bp->dev, "Shutdown SFP+ module\n"); +} + static void bnxt_cfg_ntp_filters(struct bnxt *); static void bnxt_sp_task(struct work_struct *work) @@ -5494,6 +5546,9 @@ static void bnxt_sp_task(struct work_struct *work) rtnl_unlock(); } + if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) + bnxt_port_module_event(bp); + if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event)) bnxt_hwrm_port_qstats(bp); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index a981e2c17107..cc8e38a9f684 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -825,6 +825,8 @@ struct bnxt_link_info { u16 req_link_speed; u32 advertising; bool force_link_chng; + + u8 last_port_module_event; /* a copy of phy_qcfg output used to report link * info to VF */ @@ -992,6 +994,7 @@ struct bnxt { #define BNXT_RST_RING_SP_EVENT 7 #define BNXT_HWRM_PF_UNLOAD_SP_EVENT 8 #define BNXT_PERIODIC_STATS_SP_EVENT 9 +#define BNXT_HWRM_PORT_MODULE_SP_EVENT 10 struct bnxt_pf_info pf; #ifdef CONFIG_BNXT_SRIOV -- GitLab From 9d9cee08fc9f5c4df84ef314158fd19c013bcec6 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:09:02 -0400 Subject: [PATCH 1489/9938] bnxt_en: Check for valid forced speed during ethtool -s. Check that the forced speed is a valid speed supported by firmware. If not supported, return -EINVAL. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 47e08a8b1563..952b5ba1c4da 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -739,28 +739,49 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static u32 bnxt_get_fw_speed(struct net_device *dev, u16 ethtool_speed) { + struct bnxt *bp = netdev_priv(dev); + struct bnxt_link_info *link_info = &bp->link_info; + u16 support_spds = link_info->support_speeds; + u32 fw_speed = 0; + switch (ethtool_speed) { case SPEED_100: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB; + if (support_spds & BNXT_LINK_SPEED_MSK_100MB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB; + break; case SPEED_1000: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB; + if (support_spds & BNXT_LINK_SPEED_MSK_1GB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB; + break; case SPEED_2500: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB; + if (support_spds & BNXT_LINK_SPEED_MSK_2_5GB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB; + break; case SPEED_10000: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB; + if (support_spds & BNXT_LINK_SPEED_MSK_10GB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB; + break; case SPEED_20000: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB; + if (support_spds & BNXT_LINK_SPEED_MSK_20GB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB; + break; case SPEED_25000: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB; + if (support_spds & BNXT_LINK_SPEED_MSK_25GB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB; + break; case SPEED_40000: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB; + if (support_spds & BNXT_LINK_SPEED_MSK_40GB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB; + break; case SPEED_50000: - return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB; + if (support_spds & BNXT_LINK_SPEED_MSK_50GB) + fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB; + break; default: netdev_err(dev, "unsupported speed!\n"); break; } - return 0; + return fw_speed; } u16 bnxt_get_fw_auto_link_speeds(u32 advertising) @@ -823,6 +844,8 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) */ set_pause = true; } else { + u16 fw_speed; + /* TODO: currently don't support half duplex */ if (cmd->duplex == DUPLEX_HALF) { netdev_err(dev, "HALF DUPLEX is not supported!\n"); @@ -833,7 +856,12 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->duplex == DUPLEX_UNKNOWN) cmd->duplex = DUPLEX_FULL; speed = ethtool_cmd_speed(cmd); - link_info->req_link_speed = bnxt_get_fw_speed(dev, speed); + fw_speed = bnxt_get_fw_speed(dev, speed); + if (!fw_speed) { + rc = -EINVAL; + goto set_setting_exit; + } + link_info->req_link_speed = fw_speed; link_info->req_duplex = BNXT_LINK_DUPLEX_FULL; link_info->autoneg = 0; link_info->advertising = 0; -- GitLab From 29c262fed4067c52977ba279cf71520f9991a050 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 5 Apr 2016 14:09:03 -0400 Subject: [PATCH 1490/9938] bnxt_en: Improve ethtool .get_settings(). If autoneg is off, we should always report the speed and duplex settings even if it is link down so the user knows the current settings. The unknown speed and duplex should only be used for autoneg when link is down. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 952b5ba1c4da..a2e93241b06b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -698,10 +698,23 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (link_info->phy_link_status == BNXT_LINK_LINK) cmd->lp_advertising = bnxt_fw_to_ethtool_lp_adv(link_info); + ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed); + if (!netif_carrier_ok(dev)) + cmd->duplex = DUPLEX_UNKNOWN; + else if (link_info->duplex & BNXT_LINK_DUPLEX_FULL) + cmd->duplex = DUPLEX_FULL; + else + cmd->duplex = DUPLEX_HALF; } else { cmd->autoneg = AUTONEG_DISABLE; cmd->advertising = 0; + ethtool_speed = + bnxt_fw_to_ethtool_speed(link_info->req_link_speed); + cmd->duplex = DUPLEX_HALF; + if (link_info->req_duplex == BNXT_LINK_DUPLEX_FULL) + cmd->duplex = DUPLEX_FULL; } + ethtool_cmd_speed_set(cmd, ethtool_speed); cmd->port = PORT_NONE; if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { @@ -719,14 +732,6 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->port = PORT_FIBRE; } - if (link_info->phy_link_status == BNXT_LINK_LINK) { - if (link_info->duplex & BNXT_LINK_DUPLEX_FULL) - cmd->duplex = DUPLEX_FULL; - } else { - cmd->duplex = DUPLEX_UNKNOWN; - } - ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed); - ethtool_cmd_speed_set(cmd, ethtool_speed); if (link_info->transceiver == PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL) cmd->transceiver = XCVR_INTERNAL; -- GitLab From b9bb53f3836f4eb2bdeb3447be11042bd29c2408 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Tue, 5 Apr 2016 12:41:14 -0400 Subject: [PATCH 1491/9938] sock: convert sk_peek_offset functions to WRITE_ONCE Make the peek offset interface safe to use in lockless environments. Use READ_ONCE and WRITE_ONCE to avoid race conditions between testing and updating the peek offset. Suggested-by: Eric Dumazet Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/net/sock.h | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 310c4367ea83..09aec75eb184 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -459,26 +459,28 @@ struct sock { static inline int sk_peek_offset(struct sock *sk, int flags) { - if ((flags & MSG_PEEK) && (sk->sk_peek_off >= 0)) - return sk->sk_peek_off; - else - return 0; + if (unlikely(flags & MSG_PEEK)) { + s32 off = READ_ONCE(sk->sk_peek_off); + if (off >= 0) + return off; + } + + return 0; } static inline void sk_peek_offset_bwd(struct sock *sk, int val) { - if (sk->sk_peek_off >= 0) { - if (sk->sk_peek_off >= val) - sk->sk_peek_off -= val; - else - sk->sk_peek_off = 0; + s32 off = READ_ONCE(sk->sk_peek_off); + + if (unlikely(off >= 0)) { + off = max_t(s32, off - val, 0); + WRITE_ONCE(sk->sk_peek_off, off); } } static inline void sk_peek_offset_fwd(struct sock *sk, int val) { - if (sk->sk_peek_off >= 0) - sk->sk_peek_off += val; + sk_peek_offset_bwd(sk, -val); } /* -- GitLab From e6afc8ace6dd5cef5e812f26c72579da8806f5ac Mon Sep 17 00:00:00 2001 From: samanthakumar Date: Tue, 5 Apr 2016 12:41:15 -0400 Subject: [PATCH 1492/9938] udp: remove headers from UDP packets before queueing Remove UDP transport headers before queueing packets for reception. This change simplifies a follow-up patch to add MSG_PEEK support. Signed-off-by: Sam Kumar Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/net/sock.h | 1 + include/net/udp.h | 9 +++++++++ net/core/sock.c | 19 +++++++++++++------ net/ipv4/udp.c | 20 +++++++++++--------- net/ipv6/udp.c | 12 +++++++----- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 09aec75eb184..b75998952482 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1864,6 +1864,7 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer, void sk_stop_timer(struct sock *sk, struct timer_list *timer); +int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb); diff --git a/include/net/udp.h b/include/net/udp.h index d870ec1611c4..a0b0da97164c 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -158,6 +158,15 @@ static inline __sum16 udp_v4_check(int len, __be32 saddr, void udp_set_csum(bool nocheck, struct sk_buff *skb, __be32 saddr, __be32 daddr, int len); +static inline void udp_csum_pull_header(struct sk_buff *skb) +{ + if (skb->ip_summed == CHECKSUM_NONE) + skb->csum = csum_partial(udp_hdr(skb), sizeof(struct udphdr), + skb->csum); + skb_pull_rcsum(skb, sizeof(struct udphdr)); + UDP_SKB_CB(skb)->cscov -= sizeof(struct udphdr); +} + struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, struct udphdr *uh); int udp_gro_complete(struct sk_buff *skb, int nhoff); diff --git a/net/core/sock.c b/net/core/sock.c index 2f517ea56786..e12197b359fd 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -402,9 +402,8 @@ static void sock_disable_timestamp(struct sock *sk, unsigned long flags) } -int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { - int err; unsigned long flags; struct sk_buff_head *list = &sk->sk_receive_queue; @@ -414,10 +413,6 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) return -ENOMEM; } - err = sk_filter(sk, skb); - if (err) - return err; - if (!sk_rmem_schedule(sk, skb, skb->truesize)) { atomic_inc(&sk->sk_drops); return -ENOBUFS; @@ -440,6 +435,18 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) sk->sk_data_ready(sk); return 0; } +EXPORT_SYMBOL(__sock_queue_rcv_skb); + +int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +{ + int err; + + err = sk_filter(sk, skb); + if (err) + return err; + + return __sock_queue_rcv_skb(sk, skb); +} EXPORT_SYMBOL(sock_queue_rcv_skb); int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 355bdb221057..cf747e86ce52 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1309,7 +1309,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, if (!skb) goto out; - ulen = skb->len - sizeof(struct udphdr); + ulen = skb->len; copied = len; if (copied > ulen) copied = ulen; @@ -1329,11 +1329,9 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, } if (checksum_valid || skb_csum_unnecessary(skb)) - err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), - msg, copied); + err = skb_copy_datagram_msg(skb, 0, msg, copied); else { - err = skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), - msg); + err = skb_copy_and_csum_datagram_msg(skb, 0, msg); if (err == -EINVAL) goto csum_copy_err; @@ -1500,7 +1498,7 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) sk_incoming_cpu_update(sk); } - rc = sock_queue_rcv_skb(sk, skb); + rc = __sock_queue_rcv_skb(sk, skb); if (rc < 0) { int is_udplite = IS_UDPLITE(sk); @@ -1616,10 +1614,14 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) } } - if (rcu_access_pointer(sk->sk_filter) && - udp_lib_checksum_complete(skb)) - goto csum_error; + if (rcu_access_pointer(sk->sk_filter)) { + if (udp_lib_checksum_complete(skb)) + goto csum_error; + if (sk_filter(sk, skb)) + goto drop; + } + udp_csum_pull_header(skb); if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, is_udplite); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 78a7dfd12707..84c8d7b66820 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -376,7 +376,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (!skb) goto out; - ulen = skb->len - sizeof(struct udphdr); + ulen = skb->len; copied = len; if (copied > ulen) copied = ulen; @@ -398,10 +398,9 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, } if (checksum_valid || skb_csum_unnecessary(skb)) - err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), - msg, copied); + err = skb_copy_datagram_msg(skb, 0, msg, copied); else { - err = skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); + err = skb_copy_and_csum_datagram_msg(skb, 0, msg); if (err == -EINVAL) goto csum_copy_err; } @@ -554,7 +553,7 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) sk_incoming_cpu_update(sk); } - rc = sock_queue_rcv_skb(sk, skb); + rc = __sock_queue_rcv_skb(sk, skb); if (rc < 0) { int is_udplite = IS_UDPLITE(sk); @@ -648,8 +647,11 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) if (rcu_access_pointer(sk->sk_filter)) { if (udp_lib_checksum_complete(skb)) goto csum_error; + if (sk_filter(sk, skb)) + goto drop; } + udp_csum_pull_header(skb); if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, is_udplite); -- GitLab From 627d2d6b550094d88f9e518e15967e7bf906ebbf Mon Sep 17 00:00:00 2001 From: samanthakumar Date: Tue, 5 Apr 2016 12:41:16 -0400 Subject: [PATCH 1493/9938] udp: enable MSG_PEEK at non-zero offset Enable peeking at UDP datagrams at the offset specified with socket option SOL_SOCKET/SO_PEEK_OFF. Peek at any datagram in the queue, up to the end of the given datagram. Implement the SO_PEEK_OFF semantics introduced in commit ef64a54f6e55 ("sock: Introduce the SO_PEEK_OFF sock option"). Increase the offset on peek, decrease it on regular reads. When peeking, always checksum the packet immediately, to avoid recomputation on subsequent peeks and final read. The socket lock is not held for the duration of udp_recvmsg, so peek and read operations can run concurrently. Only the last store to sk_peek_off is preserved. Signed-off-by: Sam Kumar Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/linux/skbuff.h | 7 ++++++- include/net/sock.h | 2 ++ net/core/datagram.c | 9 ++++++--- net/core/sock.c | 9 +++++++++ net/ipv4/af_inet.c | 1 + net/ipv4/udp.c | 22 +++++++++++----------- net/ipv6/af_inet6.c | 1 + net/ipv6/udp.c | 22 +++++++++++----------- 8 files changed, 47 insertions(+), 26 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 15d0df943466..007381270ff8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2949,7 +2949,12 @@ int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, struct iov_iter *from, int len); int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm); void skb_free_datagram(struct sock *sk, struct sk_buff *skb); -void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb); +void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len); +static inline void skb_free_datagram_locked(struct sock *sk, + struct sk_buff *skb) +{ + __skb_free_datagram_locked(sk, skb, 0); +} int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len); int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len); diff --git a/include/net/sock.h b/include/net/sock.h index b75998952482..1decb7a22261 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -457,6 +457,8 @@ struct sock { #define SK_CAN_REUSE 1 #define SK_FORCE_REUSE 2 +int sk_set_peek_off(struct sock *sk, int val); + static inline int sk_peek_offset(struct sock *sk, int flags) { if (unlikely(flags & MSG_PEEK)) { diff --git a/net/core/datagram.c b/net/core/datagram.c index fa9dc6450b08..b7de71f8d5d3 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -301,16 +301,19 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) } EXPORT_SYMBOL(skb_free_datagram); -void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) +void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len) { bool slow; if (likely(atomic_read(&skb->users) == 1)) smp_rmb(); - else if (likely(!atomic_dec_and_test(&skb->users))) + else if (likely(!atomic_dec_and_test(&skb->users))) { + sk_peek_offset_bwd(sk, len); return; + } slow = lock_sock_fast(sk); + sk_peek_offset_bwd(sk, len); skb_orphan(skb); sk_mem_reclaim_partial(sk); unlock_sock_fast(sk, slow); @@ -318,7 +321,7 @@ void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) /* skb is now orphaned, can be freed outside of locked section */ __kfree_skb(skb); } -EXPORT_SYMBOL(skb_free_datagram_locked); +EXPORT_SYMBOL(__skb_free_datagram_locked); /** * skb_kill_datagram - Free a datagram skbuff forcibly diff --git a/net/core/sock.c b/net/core/sock.c index e12197b359fd..2ce76e82857f 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2187,6 +2187,15 @@ void __sk_mem_reclaim(struct sock *sk, int amount) } EXPORT_SYMBOL(__sk_mem_reclaim); +int sk_set_peek_off(struct sock *sk, int val) +{ + if (val < 0) + return -EINVAL; + + sk->sk_peek_off = val; + return 0; +} +EXPORT_SYMBOL_GPL(sk_set_peek_off); /* * Set of default routines for initialising struct proto_ops when diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9e481992dbae..a38b9910af60 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -948,6 +948,7 @@ const struct proto_ops inet_dgram_ops = { .recvmsg = inet_recvmsg, .mmap = sock_no_mmap, .sendpage = inet_sendpage, + .set_peek_off = sk_set_peek_off, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index cf747e86ce52..d80312ddbb8a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1294,7 +1294,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); struct sk_buff *skb; unsigned int ulen, copied; - int peeked, off = 0; + int peeked, peeking, off; int err; int is_udplite = IS_UDPLITE(sk); bool checksum_valid = false; @@ -1304,15 +1304,16 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, return ip_recv_error(sk, msg, len, addr_len); try_again: + peeking = off = sk_peek_offset(sk, flags); skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), &peeked, &off, &err); if (!skb) - goto out; + return err; ulen = skb->len; copied = len; - if (copied > ulen) - copied = ulen; + if (copied > ulen - off) + copied = ulen - off; else if (copied < ulen) msg->msg_flags |= MSG_TRUNC; @@ -1322,16 +1323,16 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, * coverage checksum (UDP-Lite), do it before the copy. */ - if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov || peeking) { checksum_valid = !udp_lib_checksum_complete(skb); if (!checksum_valid) goto csum_copy_err; } if (checksum_valid || skb_csum_unnecessary(skb)) - err = skb_copy_datagram_msg(skb, 0, msg, copied); + err = skb_copy_datagram_msg(skb, off, msg, copied); else { - err = skb_copy_and_csum_datagram_msg(skb, 0, msg); + err = skb_copy_and_csum_datagram_msg(skb, off, msg); if (err == -EINVAL) goto csum_copy_err; @@ -1344,7 +1345,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); } - goto out_free; + skb_free_datagram_locked(sk, skb); + return err; } if (!peeked) @@ -1368,9 +1370,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, if (flags & MSG_TRUNC) err = ulen; -out_free: - skb_free_datagram_locked(sk, skb); -out: + __skb_free_datagram_locked(sk, skb, peeking ? -err : err); return err; csum_copy_err: diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index b11c37cfd67c..2b78aad0d52f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -561,6 +561,7 @@ const struct proto_ops inet6_dgram_ops = { .recvmsg = inet_recvmsg, /* ok */ .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, + .set_peek_off = sk_set_peek_off, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 84c8d7b66820..87bd7aff88b4 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -357,7 +357,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, struct inet_sock *inet = inet_sk(sk); struct sk_buff *skb; unsigned int ulen, copied; - int peeked, off = 0; + int peeked, peeking, off; int err; int is_udplite = IS_UDPLITE(sk); bool checksum_valid = false; @@ -371,15 +371,16 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, return ipv6_recv_rxpmtu(sk, msg, len, addr_len); try_again: + peeking = off = sk_peek_offset(sk, flags); skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), &peeked, &off, &err); if (!skb) - goto out; + return err; ulen = skb->len; copied = len; - if (copied > ulen) - copied = ulen; + if (copied > ulen - off) + copied = ulen - off; else if (copied < ulen) msg->msg_flags |= MSG_TRUNC; @@ -391,16 +392,16 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, * coverage checksum (UDP-Lite), do it before the copy. */ - if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov || peeking) { checksum_valid = !udp_lib_checksum_complete(skb); if (!checksum_valid) goto csum_copy_err; } if (checksum_valid || skb_csum_unnecessary(skb)) - err = skb_copy_datagram_msg(skb, 0, msg, copied); + err = skb_copy_datagram_msg(skb, off, msg, copied); else { - err = skb_copy_and_csum_datagram_msg(skb, 0, msg); + err = skb_copy_and_csum_datagram_msg(skb, off, msg); if (err == -EINVAL) goto csum_copy_err; } @@ -417,7 +418,8 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, UDP_MIB_INERRORS, is_udplite); } - goto out_free; + skb_free_datagram_locked(sk, skb); + return err; } if (!peeked) { if (is_udp4) @@ -465,9 +467,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (flags & MSG_TRUNC) err = ulen; -out_free: - skb_free_datagram_locked(sk, skb); -out: + __skb_free_datagram_locked(sk, skb, peeking ? -err : err); return err; csum_copy_err: -- GitLab From d0a58e833931234c44e515b5b8bede32bd4e6eed Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 6 Apr 2016 07:05:41 +1000 Subject: [PATCH 1494/9938] xfs: disallow rw remount on fs with unknown ro-compat features Today, a kernel which refuses to mount a filesystem read-write due to unknown ro-compat features can still transition to read-write via the remount path. The old kernel is most likely none the wiser, because it's unaware of the new feature, and isn't using it. However, writing to the filesystem may well corrupt metadata related to that new feature, and moving to a newer kernel which understand the feature will have problems. Right now the only ro-compat feature we have is the free inode btree, which showed up in v3.16. It would be good to push this back to all the active stable kernels, I think, so that if anyone is using newer mkfs (which enables the finobt feature) with older kernel releases, they'll be protected. Cc: # 3.10.x- Signed-off-by: Eric Sandeen Reviewed-by: Bill O'Donnell Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_super.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index d760934109b5..ca058a153c15 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1276,6 +1276,16 @@ xfs_fs_remount( return -EINVAL; } + if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && + xfs_sb_has_ro_compat_feature(sbp, + XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) { + xfs_warn(mp, +"ro->rw transition prohibited on unknown (0x%x) ro-compat filesystem", + (sbp->sb_features_ro_compat & + XFS_SB_FEAT_RO_COMPAT_UNKNOWN)); + return -EINVAL; + } + mp->m_flags &= ~XFS_MOUNT_RDONLY; /* -- GitLab From ad747e3b299671e1a53db74963cc6c5f6cdb9f6d Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 6 Apr 2016 07:06:20 +1000 Subject: [PATCH 1495/9938] xfs: Don't wrap growfs AGFL indexes Commit 96f859d ("libxfs: pack the agfl header structure so XFS_AGFL_SIZE is correct") allowed the freelist to use the empty slot at the end of the freelist on 64 bit systems that was not being used due to sizeof() rounding up the structure size. This has caused versions of xfs_repair prior to 4.5.0 (which also has the fix) to report this as a corruption once the filesystem has been grown. Older kernels can also have problems (seen from a whacky container/vm management environment) mounting filesystems grown on a system with a newer kernel than the vm/container it is deployed on. To avoid this problem, change the initial free list indexes not to wrap across the end of the AGFL, hence avoiding the initialisation of agf_fllast to the last index in the AGFL. cc: # 4.4-4.5 Signed-off-by: Dave Chinner Reviewed-by: Carlos Maiolino Signed-off-by: Dave Chinner --- fs/xfs/xfs_fsops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index ee3aaa0a5317..ca0d3eb44925 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -243,8 +243,8 @@ xfs_growfs_data_private( agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp)); agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1); agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1); - agf->agf_flfirst = 0; - agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); + agf->agf_flfirst = cpu_to_be32(1); + agf->agf_fllast = 0; agf->agf_flcount = 0; tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp); agf->agf_freeblks = cpu_to_be32(tmpsize); -- GitLab From ce5c767db079649db88a9f189798839f9c544981 Mon Sep 17 00:00:00 2001 From: Eryu Guan Date: Wed, 6 Apr 2016 07:19:40 +1000 Subject: [PATCH 1496/9938] xfs: add missing break in xfs_parseargs() Commit 2e74af0e1189 ("xfs: convert mount option parsing to tokens") missed a 'break;' in xfs_parseargs() which causes mount to fail with "-o pqnoenforce" option when mounting a v4 filesystem. xfs/050 catches this failure: XFS (vda6): Super block does not support project and group quota together Fixes: 2e74af0e1189 ("xfs: convert mount option parsing to tokens") Signed-off-by: Eryu Guan Reviewed-by: Brian Foster Reviewed-by: Eric Sandeen Signed-off-by: Dave Chinner --- fs/xfs/xfs_super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index ca058a153c15..a9ea12d46b74 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -350,6 +350,7 @@ xfs_parseargs( case Opt_pqnoenforce: mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE); mp->m_qflags &= ~XFS_PQUOTA_ENFD; + break; case Opt_gquota: case Opt_grpquota: mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE | -- GitLab From 143f4aede7fb25b9198b15660d6f9830936394a8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 07:41:43 +1000 Subject: [PATCH 1497/9938] xfs: factor out a helper to initialize a local format inode fork Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_dir2_sf.c | 9 +++---- fs/xfs/libxfs/xfs_inode_fork.c | 48 +++++++++++++++++++++------------- fs/xfs/libxfs/xfs_inode_fork.h | 1 + fs/xfs/xfs_symlink.c | 12 ++------- 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c index 974d62e677f4..e5bb9cc3b243 100644 --- a/fs/xfs/libxfs/xfs_dir2_sf.c +++ b/fs/xfs/libxfs/xfs_dir2_sf.c @@ -257,15 +257,12 @@ xfs_dir2_block_to_sf( * * Convert the inode to local format and copy the data in. */ - dp->i_df.if_flags &= ~XFS_IFEXTENTS; - dp->i_df.if_flags |= XFS_IFINLINE; - dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; ASSERT(dp->i_df.if_bytes == 0); - xfs_idata_realloc(dp, size, XFS_DATA_FORK); + xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size); + dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; + dp->i_d.di_size = size; logflags |= XFS_ILOG_DDATA; - memcpy(dp->i_df.if_u1.if_data, dst, size); - dp->i_d.di_size = size; xfs_dir2_sf_check(args); out: xfs_trans_log_inode(args->trans, dp, logflags); diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 11faf7df14c8..86a97f8a9de3 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -231,6 +231,34 @@ xfs_iformat_fork( return error; } +void +xfs_init_local_fork( + struct xfs_inode *ip, + int whichfork, + const void *data, + int size) +{ + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + int real_size = 0; + + if (size == 0) + ifp->if_u1.if_data = NULL; + else if (size <= sizeof(ifp->if_u2.if_inline_data)) + ifp->if_u1.if_data = ifp->if_u2.if_inline_data; + else { + real_size = roundup(size, 4); + ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); + } + + if (size) + memcpy(ifp->if_u1.if_data, data, size); + + ifp->if_bytes = size; + ifp->if_real_bytes = real_size; + ifp->if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT); + ifp->if_flags |= XFS_IFINLINE; +} + /* * The file is in-lined in the on-disk inode. * If it fits into if_inline_data, then copy @@ -248,8 +276,6 @@ xfs_iformat_local( int whichfork, int size) { - xfs_ifork_t *ifp; - int real_size; /* * If the size is unreasonable, then something @@ -265,22 +291,8 @@ xfs_iformat_local( ip->i_mount, dip); return -EFSCORRUPTED; } - ifp = XFS_IFORK_PTR(ip, whichfork); - real_size = 0; - if (size == 0) - ifp->if_u1.if_data = NULL; - else if (size <= sizeof(ifp->if_u2.if_inline_data)) - ifp->if_u1.if_data = ifp->if_u2.if_inline_data; - else { - real_size = roundup(size, 4); - ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); - } - ifp->if_bytes = size; - ifp->if_real_bytes = real_size; - if (size) - memcpy(ifp->if_u1.if_data, XFS_DFORK_PTR(dip, whichfork), size); - ifp->if_flags &= ~XFS_IFEXTENTS; - ifp->if_flags |= XFS_IFINLINE; + + xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size); return 0; } diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index 7d3b1ed6dcbe..f95e072ae646 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h @@ -134,6 +134,7 @@ void xfs_iroot_realloc(struct xfs_inode *, int, int); int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, int); +void xfs_init_local_fork(struct xfs_inode *, int, const void *, int); struct xfs_bmbt_rec_host * xfs_iext_get_ext(struct xfs_ifork *, xfs_extnum_t); diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index b44284c1adda..b69f4a770fc9 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -302,19 +302,11 @@ xfs_symlink( * If the symlink will fit into the inode, write it inline. */ if (pathlen <= XFS_IFORK_DSIZE(ip)) { - xfs_idata_realloc(ip, pathlen, XFS_DATA_FORK); - memcpy(ip->i_df.if_u1.if_data, target_path, pathlen); - ip->i_d.di_size = pathlen; - - /* - * The inode was initially created in extent format. - */ - ip->i_df.if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT); - ip->i_df.if_flags |= XFS_IFINLINE; + xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen); + ip->i_d.di_size = pathlen; ip->i_d.di_format = XFS_DINODE_FMT_LOCAL; xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE); - } else { int offset; -- GitLab From 2b3d1d41b4d96c3b074096ae57b27cd191969643 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 07:48:27 +1000 Subject: [PATCH 1498/9938] xfs: set up inode operation vectors later In the next patch we'll set up different inode operations for inline vs out of line symlinks, for that we need to make sure the flags are already set up properly. [dchinner: added xfs_setup_iops() call to xfs_rename_alloc_whiteout()] Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode.c | 1 + fs/xfs/xfs_inode.h | 5 +++- fs/xfs/xfs_iops.c | 59 +++++++++++++++++++++++++++++----------------- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 96f606deee31..4fcd6a722213 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2855,6 +2855,7 @@ xfs_rename_alloc_whiteout( * and flag it as linkable. */ drop_nlink(VFS_I(tmpfile)); + xfs_setup_iops(tmpfile); xfs_finish_inode_setup(tmpfile); VFS_I(tmpfile)->i_state |= I_LINKABLE; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 43e1d51b15eb..e52d7c7aeb5b 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -440,6 +440,9 @@ loff_t __xfs_seek_hole_data(struct inode *inode, loff_t start, /* from xfs_iops.c */ +extern void xfs_setup_inode(struct xfs_inode *ip); +extern void xfs_setup_iops(struct xfs_inode *ip); + /* * When setting up a newly allocated inode, we need to call * xfs_finish_inode_setup() once the inode is fully instantiated at @@ -447,7 +450,6 @@ loff_t __xfs_seek_hole_data(struct inode *inode, loff_t start, * before we've completed instantiation. Otherwise we can do it * the moment the inode lookup is complete. */ -extern void xfs_setup_inode(struct xfs_inode *ip); static inline void xfs_finish_inode_setup(struct xfs_inode *ip) { xfs_iflags_clear(ip, XFS_INEW); @@ -458,6 +460,7 @@ static inline void xfs_finish_inode_setup(struct xfs_inode *ip) static inline void xfs_setup_existing_inode(struct xfs_inode *ip) { xfs_setup_inode(ip); + xfs_setup_iops(ip); xfs_finish_inode_setup(ip); } diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index fb7dc61f4a29..f08d91c51b7f 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -181,6 +181,8 @@ xfs_generic_create( } #endif + xfs_setup_iops(ip); + if (tmpfile) d_tmpfile(dentry, inode); else @@ -368,6 +370,8 @@ xfs_vn_symlink( if (unlikely(error)) goto out_cleanup_inode; + xfs_setup_iops(cip); + d_instantiate(dentry, inode); xfs_finish_inode_setup(cip); return 0; @@ -1193,7 +1197,7 @@ xfs_diflags_to_iflags( } /* - * Initialize the Linux inode and set up the operation vectors. + * Initialize the Linux inode. * * When reading existing inodes from disk this is called directly from xfs_iget, * when creating a new inode it is called from xfs_ialloc after setting up the @@ -1232,8 +1236,38 @@ xfs_setup_inode( i_size_write(inode, ip->i_d.di_size); xfs_diflags_to_iflags(inode, ip); - ip->d_ops = ip->i_mount->m_nondir_inode_ops; - lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class); + if (S_ISDIR(inode->i_mode)) { + lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class); + ip->d_ops = ip->i_mount->m_dir_inode_ops; + } else { + ip->d_ops = ip->i_mount->m_nondir_inode_ops; + lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class); + } + + /* + * Ensure all page cache allocations are done from GFP_NOFS context to + * prevent direct reclaim recursion back into the filesystem and blowing + * stacks or deadlocking. + */ + gfp_mask = mapping_gfp_mask(inode->i_mapping); + mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS))); + + /* + * If there is no attribute fork no ACL can exist on this inode, + * and it can't have any file capabilities attached to it either. + */ + if (!XFS_IFORK_Q(ip)) { + inode_has_no_xattr(inode); + cache_no_acl(inode); + } +} + +void +xfs_setup_iops( + struct xfs_inode *ip) +{ + struct inode *inode = &ip->i_vnode; + switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_op = &xfs_inode_operations; @@ -1241,13 +1275,11 @@ xfs_setup_inode( inode->i_mapping->a_ops = &xfs_address_space_operations; break; case S_IFDIR: - lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class); if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) inode->i_op = &xfs_dir_ci_inode_operations; else inode->i_op = &xfs_dir_inode_operations; inode->i_fop = &xfs_dir_file_operations; - ip->d_ops = ip->i_mount->m_dir_inode_ops; break; case S_IFLNK: inode->i_op = &xfs_symlink_inode_operations; @@ -1259,21 +1291,4 @@ xfs_setup_inode( init_special_inode(inode, inode->i_mode, inode->i_rdev); break; } - - /* - * Ensure all page cache allocations are done from GFP_NOFS context to - * prevent direct reclaim recursion back into the filesystem and blowing - * stacks or deadlocking. - */ - gfp_mask = mapping_gfp_mask(inode->i_mapping); - mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS))); - - /* - * If there is no attribute fork no ACL can exist on this inode, - * and it can't have any file capabilities attached to it either. - */ - if (!XFS_IFORK_Q(ip)) { - inode_has_no_xattr(inode); - cache_no_acl(inode); - } } -- GitLab From bfe8804d908a791b16e3686c101f0d7eca9fb5b9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 07:50:54 +1000 Subject: [PATCH 1499/9938] xfs: use ->readlink to implement the readlink_by_handle ioctl Also drop the now unused readlink_copy export. [dchinner: use d_inode(dentry) rather than dentry->d_inode] Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/namei.c | 1 - fs/xfs/xfs_ioctl.c | 18 ++---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 794f81dce766..cdd041985929 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4515,7 +4515,6 @@ int readlink_copy(char __user *buffer, int buflen, const char *link) out: return len; } -EXPORT_SYMBOL(readlink_copy); /* * A helper for ->readlink(). This should be used *ONLY* for symlinks that diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index bcb6c19ce3ea..5414bcaf2e73 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -277,7 +277,6 @@ xfs_readlink_by_handle( { struct dentry *dentry; __u32 olen; - void *link; int error; if (!capable(CAP_SYS_ADMIN)) @@ -288,7 +287,7 @@ xfs_readlink_by_handle( return PTR_ERR(dentry); /* Restrict this handle operation to symlinks only. */ - if (!d_is_symlink(dentry)) { + if (!d_inode(dentry)->i_op->readlink) { error = -EINVAL; goto out_dput; } @@ -298,21 +297,8 @@ xfs_readlink_by_handle( goto out_dput; } - link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); - if (!link) { - error = -ENOMEM; - goto out_dput; - } - - error = xfs_readlink(XFS_I(d_inode(dentry)), link); - if (error) - goto out_kfree; - error = readlink_copy(hreq->ohandle, olen, link); - if (error) - goto out_kfree; + error = d_inode(dentry)->i_op->readlink(dentry, hreq->ohandle, olen); - out_kfree: - kfree(link); out_dput: dput(dentry); return error; -- GitLab From 30ee052e12b97c190b27fe6f20e3ac3047df7b5c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 07:53:29 +1000 Subject: [PATCH 1500/9938] xfs: optimize inline symlinks By overallocating the in-core inode fork data buffer and zero terminating the link target in xfs_init_local_fork we can avoid the memory allocation in ->follow_link. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_inode_fork.c | 22 ++++++++++++++++++---- fs/xfs/xfs_inode_item.c | 4 ++-- fs/xfs/xfs_iops.c | 29 ++++++++++++++++++++++++++--- fs/xfs/xfs_symlink.c | 9 +++------ 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 86a97f8a9de3..4fbe2263c1fc 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -239,19 +239,33 @@ xfs_init_local_fork( int size) { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); - int real_size = 0; + int mem_size = size, real_size = 0; + bool zero_terminate; + + /* + * If we are using the local fork to store a symlink body we need to + * zero-terminate it so that we can pass it back to the VFS directly. + * Overallocate the in-memory fork by one for that and add a zero + * to terminate it below. + */ + zero_terminate = S_ISLNK(VFS_I(ip)->i_mode); + if (zero_terminate) + mem_size++; if (size == 0) ifp->if_u1.if_data = NULL; - else if (size <= sizeof(ifp->if_u2.if_inline_data)) + else if (mem_size <= sizeof(ifp->if_u2.if_inline_data)) ifp->if_u1.if_data = ifp->if_u2.if_inline_data; else { - real_size = roundup(size, 4); + real_size = roundup(mem_size, 4); ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); } - if (size) + if (size) { memcpy(ifp->if_u1.if_data, data, size); + if (zero_terminate) + ifp->if_u1.if_data[size] = '\0'; + } ifp->if_bytes = size; ifp->if_real_bytes = real_size; diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index c48b5b18d771..37e23c7a5684 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -210,7 +210,7 @@ xfs_inode_item_format_data_fork( */ data_bytes = roundup(ip->i_df.if_bytes, 4); ASSERT(ip->i_df.if_real_bytes == 0 || - ip->i_df.if_real_bytes == data_bytes); + ip->i_df.if_real_bytes >= data_bytes); ASSERT(ip->i_df.if_u1.if_data != NULL); ASSERT(ip->i_d.di_size > 0); xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_ILOCAL, @@ -305,7 +305,7 @@ xfs_inode_item_format_attr_fork( */ data_bytes = roundup(ip->i_afp->if_bytes, 4); ASSERT(ip->i_afp->if_real_bytes == 0 || - ip->i_afp->if_real_bytes == data_bytes); + ip->i_afp->if_real_bytes >= data_bytes); ASSERT(ip->i_afp->if_u1.if_data != NULL); xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_LOCAL, ip->i_afp->if_u1.if_data, diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f08d91c51b7f..aee06d9a7b6c 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -446,6 +446,16 @@ xfs_vn_get_link( return ERR_PTR(error); } +STATIC const char * +xfs_vn_get_link_inline( + struct dentry *dentry, + struct inode *inode, + struct delayed_call *done) +{ + ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE); + return XFS_I(inode)->i_df.if_u1.if_data; +} + STATIC int xfs_vn_getattr( struct vfsmount *mnt, @@ -1171,6 +1181,18 @@ static const struct inode_operations xfs_symlink_inode_operations = { .update_time = xfs_vn_update_time, }; +static const struct inode_operations xfs_inline_symlink_inode_operations = { + .readlink = generic_readlink, + .get_link = xfs_vn_get_link_inline, + .getattr = xfs_vn_getattr, + .setattr = xfs_vn_setattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .removexattr = generic_removexattr, + .listxattr = xfs_vn_listxattr, + .update_time = xfs_vn_update_time, +}; + STATIC void xfs_diflags_to_iflags( struct inode *inode, @@ -1282,9 +1304,10 @@ xfs_setup_iops( inode->i_fop = &xfs_dir_file_operations; break; case S_IFLNK: - inode->i_op = &xfs_symlink_inode_operations; - if (!(ip->i_df.if_flags & XFS_IFINLINE)) - inode->i_mapping->a_ops = &xfs_address_space_operations; + if (ip->i_df.if_flags & XFS_IFINLINE) + inode->i_op = &xfs_inline_symlink_inode_operations; + else + inode->i_op = &xfs_symlink_inode_operations; break; default: inode->i_op = &xfs_inode_operations; diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index b69f4a770fc9..5961c1e880c2 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -131,6 +131,8 @@ xfs_readlink( trace_xfs_readlink(ip); + ASSERT(!(ip->i_df.if_flags & XFS_IFINLINE)); + if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; @@ -150,12 +152,7 @@ xfs_readlink( } - if (ip->i_df.if_flags & XFS_IFINLINE) { - memcpy(link, ip->i_df.if_u1.if_data, pathlen); - link[pathlen] = '\0'; - } else { - error = xfs_readlink_bmap(ip, link); - } + error = xfs_readlink_bmap(ip, link); out: xfs_iunlock(ip, XFS_ILOCK_SHARED); -- GitLab From 2a6fba6d2311151598abaa1e7c9abd5f8d024a43 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 6 Apr 2016 07:57:18 +1000 Subject: [PATCH 1501/9938] xfs: only return -errno or success from attr ->put_listent Today, the put_listent formatters return either 1 or 0; if they return 1, some callers treat this as an error and return it up the stack, despite "1" not being a valid (negative) error code. The intent seems to be that if the input buffer is full, we set seen_enough or set count = -1, and return 1; but some callers check the return before checking the seen_enough or count fields of the context. Fix this by only returning non-zero for actual errors encountered, and rely on the caller to first check the return value, then check the values in the context to decide what to do. Signed-off-by: Eric Sandeen Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_attr.h | 1 + fs/xfs/xfs_attr_list.c | 8 +++----- fs/xfs/xfs_xattr.c | 14 ++++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index dd4824589470..234331227c0c 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -112,6 +112,7 @@ typedef struct attrlist_cursor_kern { *========================================================================*/ +/* Return 0 on success, or -errno; other state communicated via *context */ typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, int, unsigned char *, int, int, unsigned char *); diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 4fa14820e2e2..c8be331a3196 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -108,16 +108,14 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) (int)sfe->namelen, (int)sfe->valuelen, &sfe->nameval[sfe->namelen]); - + if (error) + return error; /* * Either search callback finished early or * didn't fit it all in the buffer after all. */ if (context->seen_enough) break; - - if (error) - return error; sfe = XFS_ATTR_SF_NEXTENTRY(sfe); } trace_xfs_attr_list_sf_all(context); @@ -581,7 +579,7 @@ xfs_attr_put_listent( trace_xfs_attr_list_full(context); alist->al_more = 1; context->seen_enough = 1; - return 1; + return 0; } aep = (attrlist_ent_t *)&context->alist[context->firstu]; diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 110f1d7d86b0..f2201299311f 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -146,7 +146,7 @@ __xfs_xattr_put_listent( arraytop = context->count + prefix_len + namelen + 1; if (arraytop > context->firstu) { context->count = -1; /* insufficient space */ - return 1; + return 0; } offset = (char *)context->alist + context->count; strncpy(offset, prefix, prefix_len); @@ -221,11 +221,15 @@ xfs_xattr_put_listent( } ssize_t -xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) +xfs_vn_listxattr( + struct dentry *dentry, + char *data, + size_t size) { struct xfs_attr_list_context context; struct attrlist_cursor_kern cursor = { 0 }; - struct inode *inode = d_inode(dentry); + struct inode *inode = d_inode(dentry); + int error; /* * First read the regular on-disk attributes. @@ -239,7 +243,9 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) context.firstu = context.bufsize; context.put_listent = xfs_xattr_put_listent; - xfs_attr_list_int(&context); + error = xfs_attr_list_int(&context); + if (error) + return error; if (context.count < 0) return -ERANGE; -- GitLab From e5bd12bfea60af455f4cbad494e4ac1082e3abd6 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 6 Apr 2016 07:57:32 +1000 Subject: [PATCH 1502/9938] xfs: don't pass value into attr ->put_listent The value is not used; only names and value lengths are returned. Remove the argument. Signed-off-by: Eric Sandeen Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_attr.h | 2 +- fs/xfs/xfs_attr_list.c | 18 ++++++------------ fs/xfs/xfs_xattr.c | 3 +-- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index 234331227c0c..dab4f41de278 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -114,7 +114,7 @@ typedef struct attrlist_cursor_kern { /* Return 0 on success, or -errno; other state communicated via *context */ typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, int, - unsigned char *, int, int, unsigned char *); + unsigned char *, int, int); typedef struct xfs_attr_list_context { struct xfs_inode *dp; /* inode */ diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index c8be331a3196..d30dbfae05fe 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -106,8 +106,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) sfe->flags, sfe->nameval, (int)sfe->namelen, - (int)sfe->valuelen, - &sfe->nameval[sfe->namelen]); + (int)sfe->valuelen); if (error) return error; /* @@ -198,8 +197,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) sbp->flags, sbp->name, sbp->namelen, - sbp->valuelen, - &sbp->name[sbp->namelen]); + sbp->valuelen); if (error) { kmem_free(sbuf); return error; @@ -430,8 +428,7 @@ xfs_attr3_leaf_list_int( entry->flags, name_loc->nameval, (int)name_loc->namelen, - be16_to_cpu(name_loc->valuelen), - &name_loc->nameval[name_loc->namelen]); + be16_to_cpu(name_loc->valuelen)); if (retval) return retval; } else { @@ -459,16 +456,14 @@ xfs_attr3_leaf_list_int( entry->flags, name_rmt->name, (int)name_rmt->namelen, - valuelen, - args.value); + valuelen); kmem_free(args.value); } else { retval = context->put_listent(context, entry->flags, name_rmt->name, (int)name_rmt->namelen, - valuelen, - NULL); + valuelen); } if (retval) return retval; @@ -549,8 +544,7 @@ xfs_attr_put_listent( int flags, unsigned char *name, int namelen, - int valuelen, - unsigned char *value) + int valuelen) { struct attrlist *alist = (struct attrlist *)context->alist; attrlist_ent_t *aep; diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index f2201299311f..7fdcf3327652 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -166,8 +166,7 @@ xfs_xattr_put_listent( int flags, unsigned char *name, int namelen, - int valuelen, - unsigned char *value) + int valuelen) { char *prefix; int prefix_len; -- GitLab From 7af5ad28a603f2d1ef4c579b8ab0a9d4767a348e Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 6 Apr 2016 07:57:45 +1000 Subject: [PATCH 1503/9938] xfs: remove put_value from attr ->put_listent context The put_value context member is never set; remove it and the conditional test in xfs_attr3_leaf_list_int(). Signed-off-by: Eric Sandeen Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_attr.h | 1 - fs/xfs/xfs_attr_list.c | 31 +++---------------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index dab4f41de278..e3da5d448bcf 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -127,7 +127,6 @@ typedef struct xfs_attr_list_context { int firstu; /* first used byte in buffer */ int flags; /* from VOP call */ int resynch; /* T/F: resynch with cursor */ - int put_value; /* T/F: need value for listent */ put_listent_func_t put_listent; /* list output fmt function */ int index; /* index into output buffer */ } xfs_attr_list_context_t; diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index d30dbfae05fe..cbf4f5d072f6 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -429,45 +429,20 @@ xfs_attr3_leaf_list_int( name_loc->nameval, (int)name_loc->namelen, be16_to_cpu(name_loc->valuelen)); - if (retval) - return retval; } else { xfs_attr_leaf_name_remote_t *name_rmt = xfs_attr3_leaf_name_remote(leaf, i); int valuelen = be32_to_cpu(name_rmt->valuelen); - if (context->put_value) { - xfs_da_args_t args; - - memset((char *)&args, 0, sizeof(args)); - args.geo = context->dp->i_mount->m_attr_geo; - args.dp = context->dp; - args.whichfork = XFS_ATTR_FORK; - args.valuelen = valuelen; - args.rmtvaluelen = valuelen; - args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS); - args.rmtblkno = be32_to_cpu(name_rmt->valueblk); - args.rmtblkcnt = xfs_attr3_rmt_blocks( - args.dp->i_mount, valuelen); - retval = xfs_attr_rmtval_get(&args); - if (!retval) - retval = context->put_listent(context, - entry->flags, - name_rmt->name, - (int)name_rmt->namelen, - valuelen); - kmem_free(args.value); - } else { - retval = context->put_listent(context, + retval = context->put_listent(context, entry->flags, name_rmt->name, (int)name_rmt->namelen, valuelen); - } - if (retval) - return retval; } + if (retval) + break; if (context->seen_enough) break; cursor->offset++; -- GitLab From 3ab3ffcaca99e0b77480d77bd393fc227b09069f Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 6 Apr 2016 07:57:47 +1000 Subject: [PATCH 1504/9938] xfs: collapse cases in xfs_attr3_leaf_list_int Consolidate the 2 calls to ->put_listent in xfs_attr3_leaf_list_int(), by setting up name, namelen, and valuelen for the local vs remote cases, then call ->put_listent and do the error handling all in one spot. Signed-off-by: Eric Sandeen --- fs/xfs/xfs_attr_list.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index cbf4f5d072f6..d25f26b22ac9 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -412,6 +412,9 @@ xfs_attr3_leaf_list_int( */ retval = 0; for (; i < ichdr.count; entry++, i++) { + char *name; + int namelen, valuelen; + if (be32_to_cpu(entry->hashval) != cursor->hashval) { cursor->hashval = be32_to_cpu(entry->hashval); cursor->offset = 0; @@ -421,26 +424,23 @@ xfs_attr3_leaf_list_int( continue; /* skip incomplete entries */ if (entry->flags & XFS_ATTR_LOCAL) { - xfs_attr_leaf_name_local_t *name_loc = - xfs_attr3_leaf_name_local(leaf, i); - - retval = context->put_listent(context, - entry->flags, - name_loc->nameval, - (int)name_loc->namelen, - be16_to_cpu(name_loc->valuelen)); - } else { - xfs_attr_leaf_name_remote_t *name_rmt = - xfs_attr3_leaf_name_remote(leaf, i); + xfs_attr_leaf_name_local_t *name_loc; - int valuelen = be32_to_cpu(name_rmt->valuelen); + name_loc = xfs_attr3_leaf_name_local(leaf, i); + name = name_loc->nameval; + namelen = name_loc->namelen; + valuelen = be16_to_cpu(name_loc->valuelen); + } else { + xfs_attr_leaf_name_remote_t *name_rmt; - retval = context->put_listent(context, - entry->flags, - name_rmt->name, - (int)name_rmt->namelen, - valuelen); + name_rmt = xfs_attr3_leaf_name_remote(leaf, i); + name = name_rmt->name; + namelen = name_rmt->namelen; + valuelen = be32_to_cpu(name_rmt->valuelen); } + + retval = context->put_listent(context, entry->flags, + name, namelen, valuelen); if (retval) break; if (context->seen_enough) -- GitLab From 7e57fd1444bf8f4ba9179f826ed6817c56b801d4 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 16 Mar 2016 19:40:33 +0800 Subject: [PATCH 1505/9938] PCI: designware: Move Root Complex setup code to dw_pcie_setup_rc() dw_pcie_host_init() looks up host bridge resources, ioremaps them, creates IRQ domains, and enumerates devices below the bridge. dw_pcie_setup_rc() programs the Root Complex registers. The Root Complex may lose power during suspend-to-RAM, and when we resume, we want to redo the latter but not the former. Move some Root Complex programming from dw_pcie_host_init() to dw_pcie_setup_rc() where it belongs. DesignWare-based drivers can call dw_pcie_setup_rc() in their resume paths. [Niklas Cassel : This change moves outbound ATU programming, which uses pp->mem_base, to dw_pcie_setup_rc(). Apply the dra7xx pp->mem_base update before calling dw_pcie_setup_rc().] [bhelgaas: changelog, fold in dra7xx fix from Niklas] Signed-off-by: Jisheng Zhang Signed-off-by: Bjorn Helgaas Acked-by: Pratyush Anand --- drivers/pci/host/pci-dra7xx.c | 4 +-- drivers/pci/host/pcie-designware.c | 39 +++++++++++++++--------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 2ca3a1f30ebf..f441130407e7 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c @@ -142,13 +142,13 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp) static void dra7xx_pcie_host_init(struct pcie_port *pp) { - dw_pcie_setup_rc(pp); - pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR; pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR; pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR; pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR; + dw_pcie_setup_rc(pp); + dra7xx_pcie_establish_link(pp); if (IS_ENABLED(CONFIG_PCI_MSI)) dw_pcie_msi_init(pp); diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index a4cccd356304..261e4a1106df 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -434,7 +434,6 @@ int dw_pcie_host_init(struct pcie_port *pp) struct platform_device *pdev = to_platform_device(pp->dev); struct pci_bus *bus, *child; struct resource *cfg_res; - u32 val; int i, ret; LIST_HEAD(res); struct resource_entry *win; @@ -544,25 +543,6 @@ int dw_pcie_host_init(struct pcie_port *pp) if (pp->ops->host_init) pp->ops->host_init(pp); - /* - * If the platform provides ->rd_other_conf, it means the platform - * uses its own address translation component rather than ATU, so - * we should not program the ATU here. - */ - if (!pp->ops->rd_other_conf) - dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, - PCIE_ATU_TYPE_MEM, pp->mem_base, - pp->mem_bus_addr, pp->mem_size); - - dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); - - /* program correct class for RC */ - dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); - - dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val); - val |= PORT_LOGIC_SPEED_CHANGE; - dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); - pp->root_bus_nr = pp->busn->start; if (IS_ENABLED(CONFIG_PCI_MSI)) { bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr, @@ -800,6 +780,25 @@ void dw_pcie_setup_rc(struct pcie_port *pp) val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; dw_pcie_writel_rc(pp, val, PCI_COMMAND); + + /* + * If the platform provides ->rd_other_conf, it means the platform + * uses its own address translation component rather than ATU, so + * we should not program the ATU here. + */ + if (!pp->ops->rd_other_conf) + dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, + PCIE_ATU_TYPE_MEM, pp->mem_base, + pp->mem_bus_addr, pp->mem_size); + + dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); + + /* program correct class for RC */ + dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); + + dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val); + val |= PORT_LOGIC_SPEED_CHANGE; + dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); } MODULE_AUTHOR("Jingoo Han "); -- GitLab From bb18782aa47d8cde90fed5cb0af312642e98a4fa Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 6 Apr 2016 08:11:25 +1000 Subject: [PATCH 1506/9938] xfs: build bios directly in xfs_add_to_ioend Currently adding a buffer to the ioend and then building a bio from the buffer list are two separate operations. We don't build the bios and submit them until the ioend is submitted, and this places a fixed dependency on bufferhead chaining in the ioend. The first step to removing the bufferhead chaining in the ioend is on the IO submission side. We can build the bio directly as we add the buffers to the ioend chain, thereby removing the need for a latter "buffer-to-bio" submission loop. This allows us to submit bios on large ioends as soon as we cannot add more data to the bio. These bios then get captured by the active plug, and hence will be dispatched as soon as either the plug overflows or we schedule away from the writeback context. This will reduce submission latency for large IOs, but will also allow more timely request queue based writeback blocking when the device becomes congested. Signed-off-by: Dave Chinner [hch: various small updates] Signed-off-by: Christoph Hellwig Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_aops.c | 69 +++++++++++++++++++++-------------------------- fs/xfs/xfs_aops.h | 1 + 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index d445a64b979e..d03946719992 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -274,6 +274,7 @@ xfs_alloc_ioend( xfs_ioend_t *ioend; ioend = mempool_alloc(xfs_ioend_pool, GFP_NOFS); + memset(ioend, 0, sizeof(*ioend)); /* * Set the count to 1 initially, which will prevent an I/O @@ -281,16 +282,9 @@ xfs_alloc_ioend( * all the I/O from calling the completion routine too early. */ atomic_set(&ioend->io_remaining, 1); - ioend->io_error = 0; INIT_LIST_HEAD(&ioend->io_list); ioend->io_type = type; ioend->io_inode = inode; - ioend->io_buffer_head = NULL; - ioend->io_buffer_tail = NULL; - ioend->io_offset = 0; - ioend->io_size = 0; - ioend->io_append_trans = NULL; - INIT_WORK(&ioend->io_work, xfs_end_io); return ioend; } @@ -452,13 +446,18 @@ static inline int xfs_bio_add_buffer(struct bio *bio, struct buffer_head *bh) } /* - * Submit all of the bios for an ioend. We are only passed a single ioend at a - * time; the caller is responsible for chaining prior to submission. + * Submit the bio for an ioend. We are passed an ioend with a bio attached to + * it, and we submit that bio. The ioend may be used for multiple bio + * submissions, so we only want to allocate an append transaction for the ioend + * once. In the case of multiple bio submission, each bio will take an IO + * reference to the ioend to ensure that the ioend completion is only done once + * all bios have been submitted and the ioend is really done. * * If @fail is non-zero, it means that we have a situation where some part of * the submission process has failed after we have marked paged for writeback - * and unlocked them. In this situation, we need to fail the ioend chain rather - * than submit it to IO. This typically only happens on a filesystem shutdown. + * and unlocked them. In this situation, we need to fail the bio and ioend + * rather than submit it to IO. This typically only happens on a filesystem + * shutdown. */ STATIC int xfs_submit_ioend( @@ -466,14 +465,13 @@ xfs_submit_ioend( xfs_ioend_t *ioend, int status) { - struct buffer_head *bh; - struct bio *bio; - sector_t lastblock = 0; - /* Reserve log space if we might write beyond the on-disk inode size. */ if (!status && - ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend)) + ioend->io_bio && ioend->io_type != XFS_IO_UNWRITTEN && + xfs_ioend_is_append(ioend) && + !ioend->io_append_trans) status = xfs_setfilesize_trans_alloc(ioend); + /* * If we are failing the IO now, just mark the ioend with an * error and finish it. This will run IO completion immediately @@ -481,31 +479,15 @@ xfs_submit_ioend( * time. */ if (status) { + if (ioend->io_bio) + bio_put(ioend->io_bio); ioend->io_error = status; xfs_finish_ioend(ioend); return status; } - bio = NULL; - for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { - - if (!bio) { -retry: - bio = xfs_alloc_ioend_bio(bh); - } else if (bh->b_blocknr != lastblock + 1) { - xfs_submit_ioend_bio(wbc, ioend, bio); - goto retry; - } - - if (xfs_bio_add_buffer(bio, bh) != bh->b_size) { - xfs_submit_ioend_bio(wbc, ioend, bio); - goto retry; - } - - lastblock = bh->b_blocknr; - } - if (bio) - xfs_submit_ioend_bio(wbc, ioend, bio); + xfs_submit_ioend_bio(wbc, ioend, ioend->io_bio); + ioend->io_bio = NULL; xfs_finish_ioend(ioend); return 0; } @@ -523,6 +505,7 @@ xfs_add_to_ioend( struct buffer_head *bh, xfs_off_t offset, struct xfs_writepage_ctx *wpc, + struct writeback_control *wbc, struct list_head *iolist) { if (!wpc->ioend || wpc->io_type != wpc->ioend->io_type || @@ -542,8 +525,18 @@ xfs_add_to_ioend( wpc->ioend->io_buffer_tail->b_private = bh; wpc->ioend->io_buffer_tail = bh; } - bh->b_private = NULL; + +retry: + if (!wpc->ioend->io_bio) + wpc->ioend->io_bio = xfs_alloc_ioend_bio(bh); + + if (xfs_bio_add_buffer(wpc->ioend->io_bio, bh) != bh->b_size) { + xfs_submit_ioend_bio(wbc, wpc->ioend, wpc->ioend->io_bio); + wpc->ioend->io_bio = NULL; + goto retry; + } + wpc->ioend->io_size += bh->b_size; wpc->last_block = bh->b_blocknr; xfs_start_buffer_writeback(bh); @@ -803,7 +796,7 @@ xfs_writepage_map( lock_buffer(bh); if (wpc->io_type != XFS_IO_OVERWRITE) xfs_map_at_offset(inode, bh, &wpc->imap, offset); - xfs_add_to_ioend(inode, bh, offset, wpc, &submit_list); + xfs_add_to_ioend(inode, bh, offset, wpc, wbc, &submit_list); count++; } diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index b4421177b68d..8947991e0990 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -52,6 +52,7 @@ typedef struct xfs_ioend { xfs_off_t io_offset; /* offset in the file */ struct work_struct io_work; /* xfsdatad work queue */ struct xfs_trans *io_append_trans;/* xact. for size update */ + struct bio *io_bio; /* bio being built */ } xfs_ioend_t; extern const struct address_space_operations xfs_address_space_operations; -- GitLab From 37992c18bba3f578860c6448b7bae18a14e535d3 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 6 Apr 2016 08:12:28 +1000 Subject: [PATCH 1507/9938] xfs: don't release bios on completion immediately Completion of an ioend requires us to walk the bufferhead list to end writback on all the bufferheads. This, in turn, is needed so that we can end writeback on all the pages we just did IO on. To remove our dependency on bufferheads in writeback, we need to turn this around the other way - we need to walk the pages we've just completed IO on, and then walk the buffers attached to the pages and complete their IO. In doing this, we remove the requirement for the ioend to track bufferheads directly. To enable IO completion to walk all the pages we've submitted IO on, we need to keep the bios that we used for IO around until the ioend has been completed. We can do this simply by chaining the bios to the ioend at completion time, and then walking their pages directly just before destroying the ioend. Signed-off-by: Dave Chinner [hch: changed the xfs_finish_page_writeback calling convention] Signed-off-by: Christoph Hellwig Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_aops.c | 95 +++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_aops.h | 5 ++- 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index d03946719992..9d9a01b50078 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -84,20 +84,64 @@ xfs_find_bdev_for_inode( } /* - * We're now finished for good with this ioend structure. - * Update the page state via the associated buffer_heads, - * release holds on the inode and bio, and finally free - * up memory. Do not use the ioend after this. + * We're now finished for good with this page. Update the page state via the + * associated buffer_heads, paying attention to the start and end offsets that + * we need to process on the page. + */ +static void +xfs_finish_page_writeback( + struct inode *inode, + struct bio_vec *bvec, + int error) +{ + unsigned int blockmask = (1 << inode->i_blkbits) - 1; + unsigned int end = bvec->bv_offset + bvec->bv_len - 1; + struct buffer_head *head, *bh; + unsigned int off = 0; + + ASSERT(bvec->bv_offset < PAGE_SIZE); + ASSERT((bvec->bv_offset & blockmask) == 0); + ASSERT(end < PAGE_SIZE); + ASSERT((bvec->bv_len & blockmask) == 0); + + bh = head = page_buffers(bvec->bv_page); + + do { + if (off < bvec->bv_offset) + goto next_bh; + if (off > end) + break; + bh->b_end_io(bh, !error); +next_bh: + off += bh->b_size; + } while ((bh = bh->b_this_page) != head); +} + +/* + * We're now finished for good with this ioend structure. Update the page + * state, release holds on bios, and finally free up memory. Do not use the + * ioend after this. */ STATIC void xfs_destroy_ioend( - xfs_ioend_t *ioend) + struct xfs_ioend *ioend) { - struct buffer_head *bh, *next; + struct inode *inode = ioend->io_inode; + int error = ioend->io_error; + struct bio *bio, *next; + + for (bio = ioend->io_bio_done; bio; bio = next) { + struct bio_vec *bvec; + int i; + + next = bio->bi_private; + bio->bi_private = NULL; - for (bh = ioend->io_buffer_head; bh; bh = next) { - next = bh->b_private; - bh->b_end_io(bh, !ioend->io_error); + /* walk each page on bio, ending page IO on them */ + bio_for_each_segment_all(bvec, bio, i) + xfs_finish_page_writeback(inode, bvec, error); + + bio_put(bio); } mempool_free(ioend, xfs_ioend_pool); @@ -286,6 +330,7 @@ xfs_alloc_ioend( ioend->io_type = type; ioend->io_inode = inode; INIT_WORK(&ioend->io_work, xfs_end_io); + spin_lock_init(&ioend->io_lock); return ioend; } @@ -365,15 +410,21 @@ STATIC void xfs_end_bio( struct bio *bio) { - xfs_ioend_t *ioend = bio->bi_private; - - if (!ioend->io_error) - ioend->io_error = bio->bi_error; + struct xfs_ioend *ioend = bio->bi_private; + unsigned long flags; - /* Toss bio and pass work off to an xfsdatad thread */ bio->bi_private = NULL; bio->bi_end_io = NULL; - bio_put(bio); + + spin_lock_irqsave(&ioend->io_lock, flags); + if (!ioend->io_error) + ioend->io_error = bio->bi_error; + if (!ioend->io_bio_done) + ioend->io_bio_done = bio; + else + ioend->io_bio_done_tail->bi_private = bio; + ioend->io_bio_done_tail = bio; + spin_unlock_irqrestore(&ioend->io_lock, flags); xfs_finish_ioend(ioend); } @@ -511,21 +562,11 @@ xfs_add_to_ioend( if (!wpc->ioend || wpc->io_type != wpc->ioend->io_type || bh->b_blocknr != wpc->last_block + 1 || offset != wpc->ioend->io_offset + wpc->ioend->io_size) { - struct xfs_ioend *new; - if (wpc->ioend) list_add(&wpc->ioend->io_list, iolist); - - new = xfs_alloc_ioend(inode, wpc->io_type); - new->io_offset = offset; - new->io_buffer_head = bh; - new->io_buffer_tail = bh; - wpc->ioend = new; - } else { - wpc->ioend->io_buffer_tail->b_private = bh; - wpc->ioend->io_buffer_tail = bh; + wpc->ioend = xfs_alloc_ioend(inode, wpc->io_type); + wpc->ioend->io_offset = offset; } - bh->b_private = NULL; retry: if (!wpc->ioend->io_bio) diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 8947991e0990..61a3dc3dbdf8 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -46,13 +46,14 @@ typedef struct xfs_ioend { int io_error; /* I/O error code */ atomic_t io_remaining; /* hold count */ struct inode *io_inode; /* file being written to */ - struct buffer_head *io_buffer_head;/* buffer linked list head */ - struct buffer_head *io_buffer_tail;/* buffer linked list tail */ size_t io_size; /* size of the extent */ xfs_off_t io_offset; /* offset in the file */ struct work_struct io_work; /* xfsdatad work queue */ struct xfs_trans *io_append_trans;/* xact. for size update */ struct bio *io_bio; /* bio being built */ + struct bio *io_bio_done; /* bios completed */ + struct bio *io_bio_done_tail; /* bios completed */ + spinlock_t io_lock; /* for bio completion list */ } xfs_ioend_t; extern const struct address_space_operations xfs_address_space_operations; -- GitLab From b2d8984f3e7c84303e4d1cbd40d9e8cefd3c9737 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 5 Apr 2016 15:31:33 -0700 Subject: [PATCH 1508/9938] dmaengine: add DMA_CYCLIC to dma_get_slave_caps dma_get_slave_caps() API only checked for slave capability where we use slave capabilities for cyclic dma operations as well, so we should add the cyclic case here too. Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 0cb259c59916..3e55755e0ff1 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -482,7 +482,8 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps) device = chan->device; /* check if the channel supports slave transactions */ - if (!test_bit(DMA_SLAVE, device->cap_mask.bits)) + if ((!test_bit(DMA_SLAVE, device->cap_mask.bits)) || + (!test_bit(DMA_CYCLIC, device->cap_mask.bits))) return -ENXIO; /* -- GitLab From 0e51a8e191dbd9b9c7b7bb0a1c28d57cd2be8e6a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 08:34:30 +1000 Subject: [PATCH 1509/9938] xfs: optimize bio handling in the buffer writeback path This patch implements two closely related changes: First it embeds a bio the ioend structure so that we don't have to allocate one separately. Second it uses the block layer bio chaining mechanism to chain additional bios off this first one if needed instead of manually accounting for multiple bio completions in the ioend structure. Together this removes a memory allocation per ioend and greatly simplifies the ioend setup and I/O completion path. Signed-off-by: Christoph Hellwig Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_aops.c | 247 ++++++++++++++++++++------------------------- fs/xfs/xfs_aops.h | 15 +-- fs/xfs/xfs_super.c | 26 ++--- 3 files changed, 123 insertions(+), 165 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 9d9a01b50078..b5f1c66bbb58 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -124,18 +124,25 @@ xfs_finish_page_writeback( */ STATIC void xfs_destroy_ioend( - struct xfs_ioend *ioend) + struct xfs_ioend *ioend, + int error) { struct inode *inode = ioend->io_inode; - int error = ioend->io_error; + struct bio *last = ioend->io_bio; struct bio *bio, *next; - for (bio = ioend->io_bio_done; bio; bio = next) { + for (bio = &ioend->io_inline_bio; bio; bio = next) { struct bio_vec *bvec; int i; - next = bio->bi_private; - bio->bi_private = NULL; + /* + * For the last bio, bi_private points to the ioend, so we + * need to explicitly end the iteration here. + */ + if (bio == last) + next = NULL; + else + next = bio->bi_private; /* walk each page on bio, ending page IO on them */ bio_for_each_segment_all(bvec, bio, i) @@ -143,8 +150,6 @@ xfs_destroy_ioend( bio_put(bio); } - - mempool_free(ioend, xfs_ioend_pool); } /* @@ -218,7 +223,8 @@ xfs_setfilesize( STATIC int xfs_setfilesize_ioend( - struct xfs_ioend *ioend) + struct xfs_ioend *ioend, + int error) { struct xfs_inode *ip = XFS_I(ioend->io_inode); struct xfs_trans *tp = ioend->io_append_trans; @@ -232,36 +238,14 @@ xfs_setfilesize_ioend( __sb_writers_acquired(VFS_I(ip)->i_sb, SB_FREEZE_FS); /* we abort the update if there was an IO error */ - if (ioend->io_error) { + if (error) { xfs_trans_cancel(tp); - return ioend->io_error; + return error; } return xfs_setfilesize(ip, tp, ioend->io_offset, ioend->io_size); } -/* - * Schedule IO completion handling on the final put of an ioend. - * - * If there is no work to do we might as well call it a day and free the - * ioend right now. - */ -STATIC void -xfs_finish_ioend( - struct xfs_ioend *ioend) -{ - if (atomic_dec_and_test(&ioend->io_remaining)) { - struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount; - - if (ioend->io_type == XFS_IO_UNWRITTEN) - queue_work(mp->m_unwritten_workqueue, &ioend->io_work); - else if (ioend->io_append_trans) - queue_work(mp->m_data_workqueue, &ioend->io_work); - else - xfs_destroy_ioend(ioend); - } -} - /* * IO write completion. */ @@ -269,16 +253,17 @@ STATIC void xfs_end_io( struct work_struct *work) { - xfs_ioend_t *ioend = container_of(work, xfs_ioend_t, io_work); - struct xfs_inode *ip = XFS_I(ioend->io_inode); - int error = 0; + struct xfs_ioend *ioend = + container_of(work, struct xfs_ioend, io_work); + struct xfs_inode *ip = XFS_I(ioend->io_inode); + int error = ioend->io_bio->bi_error; /* * Set an error if the mount has shut down and proceed with end I/O * processing so it can perform whatever cleanups are necessary. */ if (XFS_FORCED_SHUTDOWN(ip->i_mount)) - ioend->io_error = -EIO; + error = -EIO; /* * For unwritten extents we need to issue transactions to convert a @@ -288,50 +273,33 @@ xfs_end_io( * on error. */ if (ioend->io_type == XFS_IO_UNWRITTEN) { - if (ioend->io_error) + if (error) goto done; error = xfs_iomap_write_unwritten(ip, ioend->io_offset, ioend->io_size); } else if (ioend->io_append_trans) { - error = xfs_setfilesize_ioend(ioend); + error = xfs_setfilesize_ioend(ioend, error); } else { ASSERT(!xfs_ioend_is_append(ioend)); } done: - if (error) - ioend->io_error = error; - xfs_destroy_ioend(ioend); + xfs_destroy_ioend(ioend, error); } -/* - * Allocate and initialise an IO completion structure. - * We need to track unwritten extent write completion here initially. - * We'll need to extend this for updating the ondisk inode size later - * (vs. incore size). - */ -STATIC xfs_ioend_t * -xfs_alloc_ioend( - struct inode *inode, - unsigned int type) +STATIC void +xfs_end_bio( + struct bio *bio) { - xfs_ioend_t *ioend; - - ioend = mempool_alloc(xfs_ioend_pool, GFP_NOFS); - memset(ioend, 0, sizeof(*ioend)); + struct xfs_ioend *ioend = bio->bi_private; + struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount; - /* - * Set the count to 1 initially, which will prevent an I/O - * completion callback from happening before we have started - * all the I/O from calling the completion routine too early. - */ - atomic_set(&ioend->io_remaining, 1); - INIT_LIST_HEAD(&ioend->io_list); - ioend->io_type = type; - ioend->io_inode = inode; - INIT_WORK(&ioend->io_work, xfs_end_io); - spin_lock_init(&ioend->io_lock); - return ioend; + if (ioend->io_type == XFS_IO_UNWRITTEN) + queue_work(mp->m_unwritten_workqueue, &ioend->io_work); + else if (ioend->io_append_trans) + queue_work(mp->m_data_workqueue, &ioend->io_work); + else + xfs_destroy_ioend(ioend, bio->bi_error); } STATIC int @@ -403,56 +371,6 @@ xfs_imap_valid( offset < imap->br_startoff + imap->br_blockcount; } -/* - * BIO completion handler for buffered IO. - */ -STATIC void -xfs_end_bio( - struct bio *bio) -{ - struct xfs_ioend *ioend = bio->bi_private; - unsigned long flags; - - bio->bi_private = NULL; - bio->bi_end_io = NULL; - - spin_lock_irqsave(&ioend->io_lock, flags); - if (!ioend->io_error) - ioend->io_error = bio->bi_error; - if (!ioend->io_bio_done) - ioend->io_bio_done = bio; - else - ioend->io_bio_done_tail->bi_private = bio; - ioend->io_bio_done_tail = bio; - spin_unlock_irqrestore(&ioend->io_lock, flags); - - xfs_finish_ioend(ioend); -} - -STATIC void -xfs_submit_ioend_bio( - struct writeback_control *wbc, - xfs_ioend_t *ioend, - struct bio *bio) -{ - atomic_inc(&ioend->io_remaining); - bio->bi_private = ioend; - bio->bi_end_io = xfs_end_bio; - submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio); -} - -STATIC struct bio * -xfs_alloc_ioend_bio( - struct buffer_head *bh) -{ - struct bio *bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); - - ASSERT(bio->bi_private == NULL); - bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); - bio->bi_bdev = bh->b_bdev; - return bio; -} - STATIC void xfs_start_buffer_writeback( struct buffer_head *bh) @@ -513,16 +431,19 @@ static inline int xfs_bio_add_buffer(struct bio *bio, struct buffer_head *bh) STATIC int xfs_submit_ioend( struct writeback_control *wbc, - xfs_ioend_t *ioend, + struct xfs_ioend *ioend, int status) { /* Reserve log space if we might write beyond the on-disk inode size. */ if (!status && - ioend->io_bio && ioend->io_type != XFS_IO_UNWRITTEN && + ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend) && !ioend->io_append_trans) status = xfs_setfilesize_trans_alloc(ioend); + ioend->io_bio->bi_private = ioend; + ioend->io_bio->bi_end_io = xfs_end_bio; + /* * If we are failing the IO now, just mark the ioend with an * error and finish it. This will run IO completion immediately @@ -530,19 +451,75 @@ xfs_submit_ioend( * time. */ if (status) { - if (ioend->io_bio) - bio_put(ioend->io_bio); - ioend->io_error = status; - xfs_finish_ioend(ioend); + ioend->io_bio->bi_error = status; + bio_endio(ioend->io_bio); return status; } - xfs_submit_ioend_bio(wbc, ioend, ioend->io_bio); - ioend->io_bio = NULL; - xfs_finish_ioend(ioend); + submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, + ioend->io_bio); return 0; } +static void +xfs_init_bio_from_bh( + struct bio *bio, + struct buffer_head *bh) +{ + bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); + bio->bi_bdev = bh->b_bdev; +} + +static struct xfs_ioend * +xfs_alloc_ioend( + struct inode *inode, + unsigned int type, + xfs_off_t offset, + struct buffer_head *bh) +{ + struct xfs_ioend *ioend; + struct bio *bio; + + bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES, xfs_ioend_bioset); + xfs_init_bio_from_bh(bio, bh); + + ioend = container_of(bio, struct xfs_ioend, io_inline_bio); + INIT_LIST_HEAD(&ioend->io_list); + ioend->io_type = type; + ioend->io_inode = inode; + ioend->io_size = 0; + ioend->io_offset = offset; + INIT_WORK(&ioend->io_work, xfs_end_io); + ioend->io_append_trans = NULL; + ioend->io_bio = bio; + return ioend; +} + +/* + * Allocate a new bio, and chain the old bio to the new one. + * + * Note that we have to do perform the chaining in this unintuitive order + * so that the bi_private linkage is set up in the right direction for the + * traversal in xfs_destroy_ioend(). + */ +static void +xfs_chain_bio( + struct xfs_ioend *ioend, + struct writeback_control *wbc, + struct buffer_head *bh) +{ + struct bio *new; + + new = bio_alloc(GFP_NOFS, BIO_MAX_PAGES); + xfs_init_bio_from_bh(new, bh); + + bio_chain(ioend->io_bio, new); + bio_get(ioend->io_bio); /* for xfs_destroy_ioend */ + submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, + ioend->io_bio); + ioend->io_bio = new; +} + /* * Test to see if we've been building up a completion structure for * earlier buffers -- if so, we try to append to this ioend if we @@ -564,19 +541,15 @@ xfs_add_to_ioend( offset != wpc->ioend->io_offset + wpc->ioend->io_size) { if (wpc->ioend) list_add(&wpc->ioend->io_list, iolist); - wpc->ioend = xfs_alloc_ioend(inode, wpc->io_type); - wpc->ioend->io_offset = offset; + wpc->ioend = xfs_alloc_ioend(inode, wpc->io_type, offset, bh); } -retry: - if (!wpc->ioend->io_bio) - wpc->ioend->io_bio = xfs_alloc_ioend_bio(bh); - - if (xfs_bio_add_buffer(wpc->ioend->io_bio, bh) != bh->b_size) { - xfs_submit_ioend_bio(wbc, wpc->ioend, wpc->ioend->io_bio); - wpc->ioend->io_bio = NULL; - goto retry; - } + /* + * If the buffer doesn't fit into the bio we need to allocate a new + * one. This shouldn't happen more than once for a given buffer. + */ + while (xfs_bio_add_buffer(wpc->ioend->io_bio, bh) != bh->b_size) + xfs_chain_bio(wpc->ioend, wbc, bh); wpc->ioend->io_size += bh->b_size; wpc->last_block = bh->b_blocknr; diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 61a3dc3dbdf8..814aab790713 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -18,7 +18,7 @@ #ifndef __XFS_AOPS_H__ #define __XFS_AOPS_H__ -extern mempool_t *xfs_ioend_pool; +extern struct bio_set *xfs_ioend_bioset; /* * Types of I/O for bmap clustering and I/O completion tracking. @@ -37,24 +37,19 @@ enum { { XFS_IO_OVERWRITE, "overwrite" } /* - * xfs_ioend struct manages large extent writes for XFS. - * It can manage several multi-page bio's at once. + * Structure for buffered I/O completions. */ -typedef struct xfs_ioend { +struct xfs_ioend { struct list_head io_list; /* next ioend in chain */ unsigned int io_type; /* delalloc / unwritten */ - int io_error; /* I/O error code */ - atomic_t io_remaining; /* hold count */ struct inode *io_inode; /* file being written to */ size_t io_size; /* size of the extent */ xfs_off_t io_offset; /* offset in the file */ struct work_struct io_work; /* xfsdatad work queue */ struct xfs_trans *io_append_trans;/* xact. for size update */ struct bio *io_bio; /* bio being built */ - struct bio *io_bio_done; /* bios completed */ - struct bio *io_bio_done_tail; /* bios completed */ - spinlock_t io_lock; /* for bio completion list */ -} xfs_ioend_t; + struct bio io_inline_bio; /* MUST BE LAST! */ +}; extern const struct address_space_operations xfs_address_space_operations; diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index d760934109b5..e52e9c1fd933 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -58,8 +58,7 @@ #include static const struct super_operations xfs_super_operations; -static kmem_zone_t *xfs_ioend_zone; -mempool_t *xfs_ioend_pool; +struct bio_set *xfs_ioend_bioset; static struct kset *xfs_kset; /* top-level xfs sysfs dir */ #ifdef DEBUG @@ -1688,20 +1687,15 @@ MODULE_ALIAS_FS("xfs"); STATIC int __init xfs_init_zones(void) { - - xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend"); - if (!xfs_ioend_zone) + xfs_ioend_bioset = bioset_create(4 * MAX_BUF_PER_PAGE, + offsetof(struct xfs_ioend, io_inline_bio)); + if (!xfs_ioend_bioset) goto out; - xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE, - xfs_ioend_zone); - if (!xfs_ioend_pool) - goto out_destroy_ioend_zone; - xfs_log_ticket_zone = kmem_zone_init(sizeof(xlog_ticket_t), "xfs_log_ticket"); if (!xfs_log_ticket_zone) - goto out_destroy_ioend_pool; + goto out_free_ioend_bioset; xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t), "xfs_bmap_free_item"); @@ -1797,10 +1791,8 @@ xfs_init_zones(void) kmem_zone_destroy(xfs_bmap_free_item_zone); out_destroy_log_ticket_zone: kmem_zone_destroy(xfs_log_ticket_zone); - out_destroy_ioend_pool: - mempool_destroy(xfs_ioend_pool); - out_destroy_ioend_zone: - kmem_zone_destroy(xfs_ioend_zone); + out_free_ioend_bioset: + bioset_free(xfs_ioend_bioset); out: return -ENOMEM; } @@ -1826,9 +1818,7 @@ xfs_destroy_zones(void) kmem_zone_destroy(xfs_btree_cur_zone); kmem_zone_destroy(xfs_bmap_free_item_zone); kmem_zone_destroy(xfs_log_ticket_zone); - mempool_destroy(xfs_ioend_pool); - kmem_zone_destroy(xfs_ioend_zone); - + bioset_free(xfs_ioend_bioset); } STATIC int __init -- GitLab From 253f4911f297b83745938b7f2c5649b94730b002 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 09:19:55 +1000 Subject: [PATCH 1510/9938] xfs: better xfs_trans_alloc interface Merge xfs_trans_reserve and xfs_trans_alloc into a single function call that returns a transaction with all the required log and block reservations, and which allows passing transaction flags directly to avoid the cumbersome _xfs_trans_alloc interface. While we're at it we also get rid of the transaction type argument that has been superflous since we stopped supporting the non-CIL logging mode. The guts of it will be removed in another patch. [dchinner: fixed transaction leak in error path in xfs_setattr_nonsize] Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_attr.c | 58 ++++++------------------- fs/xfs/libxfs/xfs_bmap.c | 22 ++++------ fs/xfs/libxfs/xfs_sb.c | 8 ++-- fs/xfs/libxfs/xfs_shared.h | 5 ++- fs/xfs/xfs_aops.c | 19 +++----- fs/xfs/xfs_attr_inactive.c | 16 ++----- fs/xfs/xfs_bmap_util.c | 45 ++++++------------- fs/xfs/xfs_dquot.c | 7 ++- fs/xfs/xfs_file.c | 8 ++-- fs/xfs/xfs_fsops.c | 10 ++--- fs/xfs/xfs_inode.c | 60 ++++++++++---------------- fs/xfs/xfs_ioctl.c | 13 +++--- fs/xfs/xfs_iomap.c | 53 ++++++++--------------- fs/xfs/xfs_iops.c | 29 +++++-------- fs/xfs/xfs_log_recover.c | 10 ++--- fs/xfs/xfs_pnfs.c | 7 +-- fs/xfs/xfs_qm.c | 9 ++-- fs/xfs/xfs_qm_syscalls.c | 26 +++-------- fs/xfs/xfs_rtalloc.c | 21 ++++----- fs/xfs/xfs_symlink.c | 16 +++---- fs/xfs/xfs_trans.c | 88 ++++++++++++++++++-------------------- fs/xfs/xfs_trans.h | 8 ++-- 22 files changed, 191 insertions(+), 347 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index fa3b948ef9c2..4e126f41a0aa 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -242,37 +242,21 @@ xfs_attr_set( return error; } - /* - * Start our first transaction of the day. - * - * All future transactions during this code must be "chained" off - * this one via the trans_dup() call. All transactions will contain - * the inode, and the inode will always be marked with trans_ihold(). - * Since the inode will be locked in all transactions, we must log - * the inode in every transaction to let it float upward through - * the log. - */ - args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET); + tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres + + M_RES(mp)->tr_attrsetrt.tr_logres * args.total; + tres.tr_logcount = XFS_ATTRSET_LOG_COUNT; + tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; /* * Root fork attributes can use reserved data blocks for this * operation if necessary */ - - if (rsvd) - args.trans->t_flags |= XFS_TRANS_RESERVE; - - tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres + - M_RES(mp)->tr_attrsetrt.tr_logres * args.total; - tres.tr_logcount = XFS_ATTRSET_LOG_COUNT; - tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; - error = xfs_trans_reserve(args.trans, &tres, args.total, 0); - if (error) { - xfs_trans_cancel(args.trans); + error = xfs_trans_alloc(mp, &tres, args.total, 0, + rsvd ? XFS_TRANS_RESERVE : 0, &args.trans); + if (error) return error; - } - xfs_ilock(dp, XFS_ILOCK_EXCL); + xfs_ilock(dp, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0, rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : XFS_QMOPT_RES_REGBLKS); @@ -428,32 +412,16 @@ xfs_attr_remove( if (error) return error; - /* - * Start our first transaction of the day. - * - * All future transactions during this code must be "chained" off - * this one via the trans_dup() call. All transactions will contain - * the inode, and the inode will always be marked with trans_ihold(). - * Since the inode will be locked in all transactions, we must log - * the inode in every transaction to let it float upward through - * the log. - */ - args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM); - /* * Root fork attributes can use reserved data blocks for this * operation if necessary */ - - if (flags & ATTR_ROOT) - args.trans->t_flags |= XFS_TRANS_RESERVE; - - error = xfs_trans_reserve(args.trans, &M_RES(mp)->tr_attrrm, - XFS_ATTRRM_SPACE_RES(mp), 0); - if (error) { - xfs_trans_cancel(args.trans); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_attrrm, + XFS_ATTRRM_SPACE_RES(mp), 0, + (flags & ATTR_ROOT) ? XFS_TRANS_RESERVE : 0, + &args.trans); + if (error) return error; - } xfs_ilock(dp, XFS_ILOCK_EXCL); /* diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 041b6948aecc..e7ec8ccd3d64 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -1121,15 +1121,14 @@ xfs_bmap_add_attrfork( mp = ip->i_mount; ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); - tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK); + blks = XFS_ADDAFORK_SPACE_RES(mp); - if (rsvd) - tp->t_flags |= XFS_TRANS_RESERVE; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_addafork, blks, 0); - if (error) { - xfs_trans_cancel(tp); + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0, + rsvd ? XFS_TRANS_RESERVE : 0, &tp); + if (error) return error; - } + xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : @@ -6026,13 +6025,10 @@ xfs_bmap_split_extent( xfs_fsblock_t firstfsb; int error; - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, + XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp); + if (error) return error; - } xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 8a53eaa349f4..12ca86778e02 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -838,12 +838,10 @@ xfs_sync_sb( struct xfs_trans *tp; int error; - tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_CHANGE, KM_SLEEP); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, + XFS_TRANS_NO_WRITECOUNT, &tp); + if (error) return error; - } xfs_log_sb(tp); if (wait) diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 81ac870834da..7d4ab6439081 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -181,8 +181,9 @@ int xfs_log_calc_minimum_size(struct xfs_mount *); #define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ -#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer - count in superblock */ +#define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ +#define XFS_TRANS_NOFS 0x80 /* pass KM_NOFS to kmem_alloc */ + /* * Field values for xfs_trans_mod_sb. */ diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index d445a64b979e..3311db6ecbbd 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -120,13 +120,9 @@ xfs_setfilesize_trans_alloc( struct xfs_trans *tp; int error; - tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); - - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp); + if (error) return error; - } ioend->io_append_trans = tp; @@ -1391,13 +1387,10 @@ xfs_end_io_direct_write( trace_xfs_end_io_direct_write_append(ip, offset, size); - tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); - if (error) { - xfs_trans_cancel(tp); - return error; - } - error = xfs_setfilesize(ip, tp, offset, size); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, + &tp); + if (!error) + error = xfs_setfilesize(ip, tp, offset, size); } return error; diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index 2bb959ada45b..55d214981ed2 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -405,21 +405,11 @@ xfs_attr_inactive( goto out_destroy_fork; xfs_iunlock(dp, lock_mode); - /* - * Start our first transaction of the day. - * - * All future transactions during this code must be "chained" off - * this one via the trans_dup() call. All transactions will contain - * the inode, and the inode will always be marked with trans_ihold(). - * Since the inode will be locked in all transactions, we must log - * the inode in every transaction to let it float upward through - * the log. - */ lock_mode = 0; - trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL); - error = xfs_trans_reserve(trans, &M_RES(mp)->tr_attrinval, 0, 0); + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_attrinval, 0, 0, 0, &trans); if (error) - goto out_cancel; + goto out_destroy_fork; lock_mode = XFS_ILOCK_EXCL; xfs_ilock(dp, lock_mode); diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index a32c1dcae2ff..3246ebc7cbd0 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -900,19 +900,15 @@ xfs_free_eofblocks( * Free them up now by truncating the file to * its current size. */ - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - if (need_iolock) { - if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) { - xfs_trans_cancel(tp); + if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) return -EAGAIN; - } } - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, + &tp); if (error) { ASSERT(XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp); if (need_iolock) xfs_iunlock(ip, XFS_IOLOCK_EXCL); return error; @@ -1037,9 +1033,9 @@ xfs_alloc_file_space( /* * Allocate and setup the transaction. */ - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - resblks, resrtextents); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, + resrtextents, 0, &tp); + /* * Check for running out of space */ @@ -1048,7 +1044,6 @@ xfs_alloc_file_space( * Free the transaction structure. */ ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp); break; } xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -1311,18 +1306,10 @@ xfs_free_file_space( * transaction to dip into the reserve blocks to ensure * the freeing of the space succeeds at ENOSPC. */ - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, resblks, 0); - - /* - * check for running out of space - */ + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, + &tp); if (error) { - /* - * Free the transaction structure. - */ ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp); break; } xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -1482,19 +1469,16 @@ xfs_shift_file_space( } while (!error && !done) { - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); /* * We would need to reserve permanent block for transaction. * This will come into picture when after shifting extent into * hole we found that adjacent extents can be merged which * may lead to freeing of a block during record update. */ - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, + XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp); + if (error) break; - } xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota(tp, mp, ip->i_udquot, @@ -1747,12 +1731,9 @@ xfs_swap_extents( if (error) goto out_unlock; - tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); + if (error) goto out_unlock; - } /* * Lock and join the inodes to the tansaction so that transaction commit diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 316b2a1bdba5..23e24329b132 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -614,11 +614,10 @@ xfs_qm_dqread( trace_xfs_dqread(dqp); if (flags & XFS_QMOPT_DQALLOC) { - tp = xfs_trans_alloc(mp, XFS_TRANS_QM_DQALLOC); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_dqalloc, - XFS_QM_DQALLOC_SPACE_RES(mp), 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_dqalloc, + XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp); if (error) - goto error1; + goto error0; } /* diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ac0fd32de31e..98bbd8f84c76 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -145,12 +145,10 @@ xfs_update_prealloc_flags( struct xfs_trans *tp; int error; - tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID); - error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_writeid, + 0, 0, 0, &tp); + if (error) return error; - } xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index ee3aaa0a5317..9c563d480b3c 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -198,14 +198,10 @@ xfs_growfs_data_private( return error; } - tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); - tp->t_flags |= XFS_TRANS_RESERVE; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata, - XFS_GROWFS_SPACE_RES(mp), 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata, + XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp); + if (error) return error; - } /* * Write new AG headers to disk. Non-transactional, but written diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 96f606deee31..b82c729634f6 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1161,11 +1161,9 @@ xfs_create( rdev = 0; resblks = XFS_MKDIR_SPACE_RES(mp, name->len); tres = &M_RES(mp)->tr_mkdir; - tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR); } else { resblks = XFS_CREATE_SPACE_RES(mp, name->len); tres = &M_RES(mp)->tr_create; - tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE); } /* @@ -1174,20 +1172,19 @@ xfs_create( * the case we'll drop the one we have and get a more * appropriate transaction later. */ - error = xfs_trans_reserve(tp, tres, resblks, 0); + error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp); if (error == -ENOSPC) { /* flush outstanding delalloc blocks and retry */ xfs_flush_inodes(mp); - error = xfs_trans_reserve(tp, tres, resblks, 0); + error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp); } if (error == -ENOSPC) { /* No space at all so try a "no-allocation" reservation */ resblks = 0; - error = xfs_trans_reserve(tp, tres, 0, 0); + error = xfs_trans_alloc(mp, tres, 0, 0, 0, &tp); } if (error) - goto out_trans_cancel; - + goto out_release_inode; xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL | XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT); @@ -1337,17 +1334,16 @@ xfs_create_tmpfile( return error; resblks = XFS_IALLOC_SPACE_RES(mp); - tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE_TMPFILE); - tres = &M_RES(mp)->tr_create_tmpfile; - error = xfs_trans_reserve(tp, tres, resblks, 0); + + error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp); if (error == -ENOSPC) { /* No space at all so try a "no-allocation" reservation */ resblks = 0; - error = xfs_trans_reserve(tp, tres, 0, 0); + error = xfs_trans_alloc(mp, tres, 0, 0, 0, &tp); } if (error) - goto out_trans_cancel; + goto out_release_inode; error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, pdqp, resblks, 1, 0); @@ -1432,15 +1428,14 @@ xfs_link( if (error) goto std_return; - tp = xfs_trans_alloc(mp, XFS_TRANS_LINK); resblks = XFS_LINK_SPACE_RES(mp, target_name->len); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_link, resblks, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_link, resblks, 0, 0, &tp); if (error == -ENOSPC) { resblks = 0; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_link, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_link, 0, 0, 0, &tp); } if (error) - goto error_return; + goto std_return; xfs_ilock(tdp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); @@ -1710,11 +1705,9 @@ xfs_inactive_truncate( struct xfs_trans *tp; int error; - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); if (error) { ASSERT(XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp); return error; } @@ -1764,8 +1757,6 @@ xfs_inactive_ifree( struct xfs_trans *tp; int error; - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - /* * The ifree transaction might need to allocate blocks for record * insertion to the finobt. We don't want to fail here at ENOSPC, so @@ -1781,9 +1772,8 @@ xfs_inactive_ifree( * now remains allocated and sits on the unlinked list until the fs is * repaired. */ - tp->t_flags |= XFS_TRANS_RESERVE; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, - XFS_IFREE_SPACE_RES(mp), 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ifree, + XFS_IFREE_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp); if (error) { if (error == -ENOSPC) { xfs_warn_ratelimited(mp, @@ -1792,7 +1782,6 @@ xfs_inactive_ifree( } else { ASSERT(XFS_FORCED_SHUTDOWN(mp)); } - xfs_trans_cancel(tp); return error; } @@ -2525,11 +2514,6 @@ xfs_remove( if (error) goto std_return; - if (is_dir) - tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR); - else - tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE); - /* * We try to get the real space reservation first, * allowing for directory btree deletion(s) implying @@ -2540,14 +2524,15 @@ xfs_remove( * block from the directory. */ resblks = XFS_REMOVE_SPACE_RES(mp); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_remove, resblks, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_remove, resblks, 0, 0, &tp); if (error == -ENOSPC) { resblks = 0; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_remove, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_remove, 0, 0, 0, + &tp); } if (error) { ASSERT(error != -ENOSPC); - goto out_trans_cancel; + goto std_return; } xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); @@ -2910,15 +2895,15 @@ xfs_rename( xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip, wip, inodes, &num_inodes); - tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME); spaceres = XFS_RENAME_SPACE_RES(mp, target_name->len); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_rename, spaceres, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_rename, spaceres, 0, 0, &tp); if (error == -ENOSPC) { spaceres = 0; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_rename, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_rename, 0, 0, 0, + &tp); } if (error) - goto out_trans_cancel; + goto out_release_wip; /* * Attach the dquots to the inodes @@ -3155,6 +3140,7 @@ xfs_rename( xfs_bmap_cancel(&free_list); out_trans_cancel: xfs_trans_cancel(tp); +out_release_wip: if (wip) IRELE(wip); return error; diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index bcb6c19ce3ea..6f82187ee297 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -334,12 +334,10 @@ xfs_set_dmattrs( if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; - tp = xfs_trans_alloc(mp, XFS_TRANS_SET_DMATTRS); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); + if (error) return error; - } + xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); @@ -1141,10 +1139,9 @@ xfs_ioctl_setattr_get_trans( if (XFS_FORCED_SHUTDOWN(mp)) goto out_unlock; - tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); if (error) - goto out_cancel; + return ERR_PTR(error); xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | join_flags); diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index d81bdc080370..58391355a44d 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -132,6 +132,7 @@ xfs_iomap_write_direct( int error; int lockmode; int bmapi_flags = XFS_BMAPI_PREALLOC; + uint tflags = 0; rt = XFS_IS_REALTIME_INODE(ip); extsz = xfs_get_extsz_hint(ip); @@ -191,11 +192,6 @@ xfs_iomap_write_direct( if (error) return error; - /* - * Allocate and setup the transaction - */ - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - /* * For DAX, we do not allocate unwritten extents, but instead we zero * the block before we commit the transaction. Ideally we'd like to do @@ -209,23 +205,17 @@ xfs_iomap_write_direct( * the reserve block pool for bmbt block allocation if there is no space * left but we need to do unwritten extent conversion. */ - if (IS_DAX(VFS_I(ip))) { bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO; if (ISUNWRITTEN(imap)) { - tp->t_flags |= XFS_TRANS_RESERVE; + tflags |= XFS_TRANS_RESERVE; resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1; } } - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - resblks, resrtextents); - /* - * Check for running out of space, note: need lock to return - */ - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents, + tflags, &tp); + if (error) return error; - } lockmode = XFS_ILOCK_EXCL; xfs_ilock(ip, lockmode); @@ -726,15 +716,13 @@ xfs_iomap_write_allocate( nimaps = 0; while (nimaps == 0) { - tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); - tp->t_flags |= XFS_TRANS_RESERVE; nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - nres, 0); - if (error) { - xfs_trans_cancel(tp); + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, nres, + 0, XFS_TRANS_RESERVE, &tp); + if (error) return error; - } + xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); @@ -878,25 +866,18 @@ xfs_iomap_write_unwritten( do { /* - * set up a transaction to convert the range of extents + * Set up a transaction to convert the range of extents * from unwritten to real. Do allocations in a loop until * we have covered the range passed in. * - * Note that we open code the transaction allocation here - * to pass KM_NOFS--we can't risk to recursing back into - * the filesystem here as we might be asked to write out - * the same inode that we complete here and might deadlock - * on the iolock. + * Note that we can't risk to recursing back into the filesystem + * here as we might be asked to write out the same inode that we + * complete here and might deadlock on the iolock. */ - sb_start_intwrite(mp->m_super); - tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS); - tp->t_flags |= XFS_TRANS_RESERVE | XFS_TRANS_FREEZE_PROT; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - resblks, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, + XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp); + if (error) return error; - } xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index fb7dc61f4a29..fc7766164dc9 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -599,12 +599,12 @@ xfs_setattr_nonsize( return error; } - tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); if (error) - goto out_trans_cancel; + goto out_dqrele; xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); /* * Change file ownership. Must be the owner or privileged. @@ -633,12 +633,10 @@ xfs_setattr_nonsize( NULL, capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0); if (error) /* out of quota */ - goto out_unlock; + goto out_cancel; } } - xfs_trans_ijoin(tp, ip, 0); - /* * Change file ownership. Must be the owner or privileged. */ @@ -722,10 +720,9 @@ xfs_setattr_nonsize( return 0; -out_unlock: - xfs_iunlock(ip, XFS_ILOCK_EXCL); -out_trans_cancel: +out_cancel: xfs_trans_cancel(tp); +out_dqrele: xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); return error; @@ -834,7 +831,7 @@ xfs_setattr_size( * We have to do all the page cache truncate work outside the * transaction context as the "lock" order is page lock->log space * reservation as defined by extent allocation in the writeback path. - * Hence a truncate can fail with ENOMEM from xfs_trans_reserve(), but + * Hence a truncate can fail with ENOMEM from xfs_trans_alloc(), but * having already truncated the in-memory version of the file (i.e. made * user visible changes). There's not much we can do about this, except * to hope that the caller sees ENOMEM and retries the truncate @@ -849,10 +846,9 @@ xfs_setattr_size( return error; truncate_setsize(inode, newsize); - tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); if (error) - goto out_trans_cancel; + return error; lock_flags |= XFS_ILOCK_EXCL; xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -971,12 +967,9 @@ xfs_vn_update_time( trace_xfs_update_time(ip); - tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp); + if (error) return error; - } xfs_ilock(ip, XFS_ILOCK_EXCL); if (flags & S_CTIME) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 396565f43247..558f3d1d91ad 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4205,10 +4205,9 @@ xlog_recover_process_efi( } } - tp = xfs_trans_alloc(mp, 0); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); if (error) - goto abort_error; + return error; efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); for (i = 0; i < efip->efi_format.efi_nextents; i++) { @@ -4355,10 +4354,9 @@ xlog_recover_clear_agi_bucket( int offset; int error; - tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_clearagi, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_clearagi, 0, 0, 0, &tp); if (error) - goto out_abort; + goto out_error; error = xfs_read_agi(mp, tp, agno, &agibp); if (error) diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index ade236e90bb3..3332baeac582 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c @@ -308,12 +308,9 @@ xfs_fs_commit_blocks( goto out_drop_iolock; } - tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); + if (error) goto out_drop_iolock; - } xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index be125e1758c1..a60d9e2739d1 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -783,13 +783,10 @@ xfs_qm_qino_alloc( } } - tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_create, - XFS_QM_QINOCREATE_SPACE_RES(mp), 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_create, + XFS_QM_QINOCREATE_SPACE_RES(mp), 0, 0, &tp); + if (error) return error; - } if (need_alloc) { error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index f4d0e0a8f517..475a3882a81f 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -236,10 +236,8 @@ xfs_qm_scall_trunc_qfile( xfs_ilock(ip, XFS_IOLOCK_EXCL); - tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); if (error) { - xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_IOLOCK_EXCL); goto out_put; } @@ -436,12 +434,9 @@ xfs_qm_scall_setqlim( defq = xfs_get_defquota(dqp, q); xfs_dqunlock(dqp); - tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_setqlim, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp); + if (error) goto out_rele; - } xfs_dqlock(dqp); xfs_trans_dqjoin(tp, dqp); @@ -569,13 +564,9 @@ xfs_qm_log_quotaoff_end( int error; xfs_qoff_logitem_t *qoffi; - tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END); - - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_equotaoff, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_equotaoff, 0, 0, 0, &tp); + if (error) return error; - } qoffi = xfs_trans_get_qoff_item(tp, startqoff, flags & XFS_ALL_QUOTA_ACCT); @@ -603,12 +594,9 @@ xfs_qm_log_quotaoff( *qoffstartp = NULL; - tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_quotaoff, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_quotaoff, 0, 0, 0, &tp); + if (error) goto out; - } qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT); xfs_trans_log_quotaoff_item(tp, qoffi); diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index abf44435d04a..3938b37d1043 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -780,15 +780,14 @@ xfs_growfs_rt_alloc( * Allocate space to the file, as necessary. */ while (oblocks < nblocks) { - tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC); resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks); /* * Reserve space & log for one extent added to the file. */ - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtalloc, - resblks, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtalloc, resblks, + 0, 0, &tp); if (error) - goto out_trans_cancel; + return error; /* * Lock the inode. */ @@ -823,14 +822,13 @@ xfs_growfs_rt_alloc( for (bno = map.br_startoff, fsbno = map.br_startblock; bno < map.br_startoff + map.br_blockcount; bno++, fsbno++) { - tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO); /* * Reserve log for one block zeroing. */ - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero, - 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtzero, + 0, 0, 0, &tp); if (error) - goto out_trans_cancel; + return error; /* * Lock the bitmap inode. */ @@ -994,11 +992,10 @@ xfs_growfs_rt( /* * Start a transaction, get the log reservation. */ - tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_FREE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtfree, - 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtfree, 0, 0, 0, + &tp); if (error) - goto error_cancel; + break; /* * Lock out other callers by grabbing the bitmap inode lock. */ diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index b44284c1adda..c3aeaa884478 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -221,7 +221,6 @@ xfs_symlink( if (error) return error; - tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK); /* * The symlink will fit into the inode data fork? * There can't be any attributes so we get the whole variable part. @@ -231,13 +230,15 @@ xfs_symlink( else fs_blocks = xfs_symlink_blocks(mp, pathlen); resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, resblks, 0); + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_symlink, resblks, 0, 0, &tp); if (error == -ENOSPC && fs_blocks == 0) { resblks = 0; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, 0, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_symlink, 0, 0, 0, + &tp); } if (error) - goto out_trans_cancel; + goto out_release_inode; xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL | XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT); @@ -455,12 +456,9 @@ xfs_inactive_symlink_rmt( */ ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); + if (error) return error; - } xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 20c53666cb4b..b3669efb2a0a 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -46,47 +46,6 @@ xfs_trans_init( xfs_trans_resv_calc(mp, M_RES(mp)); } -/* - * This routine is called to allocate a transaction structure. - * The type parameter indicates the type of the transaction. These - * are enumerated in xfs_trans.h. - * - * Dynamically allocate the transaction structure from the transaction - * zone, initialize it, and return it to the caller. - */ -xfs_trans_t * -xfs_trans_alloc( - xfs_mount_t *mp, - uint type) -{ - xfs_trans_t *tp; - - sb_start_intwrite(mp->m_super); - tp = _xfs_trans_alloc(mp, type, KM_SLEEP); - tp->t_flags |= XFS_TRANS_FREEZE_PROT; - return tp; -} - -xfs_trans_t * -_xfs_trans_alloc( - xfs_mount_t *mp, - uint type, - xfs_km_flags_t memflags) -{ - xfs_trans_t *tp; - - WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); - atomic_inc(&mp->m_active_trans); - - tp = kmem_zone_zalloc(xfs_trans_zone, memflags); - tp->t_magic = XFS_TRANS_HEADER_MAGIC; - tp->t_type = type; - tp->t_mountp = mp; - INIT_LIST_HEAD(&tp->t_items); - INIT_LIST_HEAD(&tp->t_busy); - return tp; -} - /* * Free the transaction structure. If there is more clean up * to do when the structure is freed, add it here. @@ -99,7 +58,7 @@ xfs_trans_free( xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false); atomic_dec(&tp->t_mountp->m_active_trans); - if (tp->t_flags & XFS_TRANS_FREEZE_PROT) + if (!(tp->t_flags & XFS_TRANS_NO_WRITECOUNT)) sb_end_intwrite(tp->t_mountp->m_super); xfs_trans_free_dqinfo(tp); kmem_zone_free(xfs_trans_zone, tp); @@ -125,7 +84,6 @@ xfs_trans_dup( * Initialize the new transaction structure. */ ntp->t_magic = XFS_TRANS_HEADER_MAGIC; - ntp->t_type = tp->t_type; ntp->t_mountp = tp->t_mountp; INIT_LIST_HEAD(&ntp->t_items); INIT_LIST_HEAD(&ntp->t_busy); @@ -135,9 +93,9 @@ xfs_trans_dup( ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE) | - (tp->t_flags & XFS_TRANS_FREEZE_PROT); + (tp->t_flags & XFS_TRANS_NO_WRITECOUNT); /* We gave our writer reference to the new transaction */ - tp->t_flags &= ~XFS_TRANS_FREEZE_PROT; + tp->t_flags |= XFS_TRANS_NO_WRITECOUNT; ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket); ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; tp->t_blk_res = tp->t_blk_res_used; @@ -165,7 +123,7 @@ xfs_trans_dup( * This does not do quota reservations. That typically is done by the * caller afterwards. */ -int +static int xfs_trans_reserve( struct xfs_trans *tp, struct xfs_trans_res *resp, @@ -219,7 +177,7 @@ xfs_trans_reserve( resp->tr_logres, resp->tr_logcount, &tp->t_ticket, XFS_TRANSACTION, - permanent, tp->t_type); + permanent, 0); } if (error) @@ -268,6 +226,42 @@ xfs_trans_reserve( return error; } +int +xfs_trans_alloc( + struct xfs_mount *mp, + struct xfs_trans_res *resp, + uint blocks, + uint rtextents, + uint flags, + struct xfs_trans **tpp) +{ + struct xfs_trans *tp; + int error; + + if (!(flags & XFS_TRANS_NO_WRITECOUNT)) + sb_start_intwrite(mp->m_super); + + WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); + atomic_inc(&mp->m_active_trans); + + tp = kmem_zone_zalloc(xfs_trans_zone, + (flags & XFS_TRANS_NOFS) ? KM_NOFS : KM_SLEEP); + tp->t_magic = XFS_TRANS_HEADER_MAGIC; + tp->t_flags = flags; + tp->t_mountp = mp; + INIT_LIST_HEAD(&tp->t_items); + INIT_LIST_HEAD(&tp->t_busy); + + error = xfs_trans_reserve(tp, resp, blocks, rtextents); + if (error) { + xfs_trans_cancel(tp); + return error; + } + + *tpp = tp; + return 0; +} + /* * Record the indicated change to the given field for application * to the file system's superblock when the transaction commits. diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index e7c49cf43fbc..9a462e892e4f 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -90,7 +90,6 @@ void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item, */ typedef struct xfs_trans { unsigned int t_magic; /* magic number */ - unsigned int t_type; /* transaction type */ unsigned int t_log_res; /* amt of log space resvd */ unsigned int t_log_count; /* count for perm log res */ unsigned int t_blk_res; /* # of blocks resvd */ @@ -148,10 +147,9 @@ typedef struct xfs_trans { /* * XFS transaction mechanism exported interfaces. */ -xfs_trans_t *xfs_trans_alloc(struct xfs_mount *, uint); -xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint, xfs_km_flags_t); -int xfs_trans_reserve(struct xfs_trans *, struct xfs_trans_res *, - uint, uint); +int xfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp, + uint blocks, uint rtextents, uint flags, + struct xfs_trans **tpp); void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t); struct xfs_buf *xfs_trans_get_buf_map(struct xfs_trans *tp, -- GitLab From 710b1e2c2948c1e5d0499def5273ecbc6472342d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 09:20:36 +1000 Subject: [PATCH 1511/9938] xfs: remove transaction types These aren't used for CIL-style logging and can be dropped. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_log_format.h | 5 ++ fs/xfs/libxfs/xfs_shared.h | 97 ---------------------------------- fs/xfs/xfs_log.c | 58 +------------------- fs/xfs/xfs_log.h | 3 +- fs/xfs/xfs_log_cil.c | 1 - fs/xfs/xfs_log_priv.h | 1 - fs/xfs/xfs_trace.h | 5 +- fs/xfs/xfs_trans.c | 2 +- 8 files changed, 10 insertions(+), 162 deletions(-) diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index d54a8018b079..e8f49c029ff0 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -211,6 +211,11 @@ typedef struct xfs_trans_header { #define XFS_TRANS_HEADER_MAGIC 0x5452414e /* TRAN */ +/* + * The only type valid for th_type in CIL-enabled file system logs: + */ +#define XFS_TRANS_CHECKPOINT 40 + /* * Log item types. */ diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 7d4ab6439081..16002b5ec4eb 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -55,103 +55,6 @@ extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops; extern const struct xfs_buf_ops xfs_symlink_buf_ops; extern const struct xfs_buf_ops xfs_rtbuf_ops; -/* - * Transaction types. Used to distinguish types of buffers. These never reach - * the log. - */ -#define XFS_TRANS_SETATTR_NOT_SIZE 1 -#define XFS_TRANS_SETATTR_SIZE 2 -#define XFS_TRANS_INACTIVE 3 -#define XFS_TRANS_CREATE 4 -#define XFS_TRANS_CREATE_TRUNC 5 -#define XFS_TRANS_TRUNCATE_FILE 6 -#define XFS_TRANS_REMOVE 7 -#define XFS_TRANS_LINK 8 -#define XFS_TRANS_RENAME 9 -#define XFS_TRANS_MKDIR 10 -#define XFS_TRANS_RMDIR 11 -#define XFS_TRANS_SYMLINK 12 -#define XFS_TRANS_SET_DMATTRS 13 -#define XFS_TRANS_GROWFS 14 -#define XFS_TRANS_STRAT_WRITE 15 -#define XFS_TRANS_DIOSTRAT 16 -/* 17 was XFS_TRANS_WRITE_SYNC */ -#define XFS_TRANS_WRITEID 18 -#define XFS_TRANS_ADDAFORK 19 -#define XFS_TRANS_ATTRINVAL 20 -#define XFS_TRANS_ATRUNCATE 21 -#define XFS_TRANS_ATTR_SET 22 -#define XFS_TRANS_ATTR_RM 23 -#define XFS_TRANS_ATTR_FLAG 24 -#define XFS_TRANS_CLEAR_AGI_BUCKET 25 -#define XFS_TRANS_SB_CHANGE 26 -/* - * Dummy entries since we use the transaction type to index into the - * trans_type[] in xlog_recover_print_trans_head() - */ -#define XFS_TRANS_DUMMY1 27 -#define XFS_TRANS_DUMMY2 28 -#define XFS_TRANS_QM_QUOTAOFF 29 -#define XFS_TRANS_QM_DQALLOC 30 -#define XFS_TRANS_QM_SETQLIM 31 -#define XFS_TRANS_QM_DQCLUSTER 32 -#define XFS_TRANS_QM_QINOCREATE 33 -#define XFS_TRANS_QM_QUOTAOFF_END 34 -#define XFS_TRANS_FSYNC_TS 35 -#define XFS_TRANS_GROWFSRT_ALLOC 36 -#define XFS_TRANS_GROWFSRT_ZERO 37 -#define XFS_TRANS_GROWFSRT_FREE 38 -#define XFS_TRANS_SWAPEXT 39 -#define XFS_TRANS_CHECKPOINT 40 -#define XFS_TRANS_ICREATE 41 -#define XFS_TRANS_CREATE_TMPFILE 42 -#define XFS_TRANS_TYPE_MAX 43 -/* new transaction types need to be reflected in xfs_logprint(8) */ - -#define XFS_TRANS_TYPES \ - { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \ - { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ - { XFS_TRANS_INACTIVE, "INACTIVE" }, \ - { XFS_TRANS_CREATE, "CREATE" }, \ - { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ - { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ - { XFS_TRANS_REMOVE, "REMOVE" }, \ - { XFS_TRANS_LINK, "LINK" }, \ - { XFS_TRANS_RENAME, "RENAME" }, \ - { XFS_TRANS_MKDIR, "MKDIR" }, \ - { XFS_TRANS_RMDIR, "RMDIR" }, \ - { XFS_TRANS_SYMLINK, "SYMLINK" }, \ - { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \ - { XFS_TRANS_GROWFS, "GROWFS" }, \ - { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \ - { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \ - { XFS_TRANS_WRITEID, "WRITEID" }, \ - { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \ - { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \ - { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \ - { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \ - { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \ - { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \ - { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \ - { XFS_TRANS_SB_CHANGE, "SBCHANGE" }, \ - { XFS_TRANS_DUMMY1, "DUMMY1" }, \ - { XFS_TRANS_DUMMY2, "DUMMY2" }, \ - { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \ - { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \ - { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \ - { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \ - { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \ - { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \ - { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \ - { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \ - { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \ - { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \ - { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \ - { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \ - { XFS_TRANS_ICREATE, "ICREATE" }, \ - { XFS_TRANS_CREATE_TMPFILE, "CREATE_TMPFILE" }, \ - { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" } - /* * This structure is used to track log items associated with * a transaction. It points to the log item and keeps some diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index b49ccf5c1d75..268f7d65cfd4 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -435,8 +435,7 @@ xfs_log_reserve( int cnt, struct xlog_ticket **ticp, __uint8_t client, - bool permanent, - uint t_type) + bool permanent) { struct xlog *log = mp->m_log; struct xlog_ticket *tic; @@ -456,7 +455,6 @@ xfs_log_reserve( if (!tic) return -ENOMEM; - tic->t_trans_type = t_type; *ticp = tic; xlog_grant_push_ail(log, tic->t_cnt ? tic->t_unit_res * tic->t_cnt @@ -823,8 +821,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) } while (iclog != first_iclog); #endif if (! (XLOG_FORCED_SHUTDOWN(log))) { - error = xfs_log_reserve(mp, 600, 1, &tic, - XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE); + error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0); if (!error) { /* the data section must be 32 bit size aligned */ struct { @@ -2032,58 +2029,8 @@ xlog_print_tic_res( REG_TYPE_STR(ICREATE, "inode create") }; #undef REG_TYPE_STR -#define TRANS_TYPE_STR(type) [XFS_TRANS_##type] = #type - static char *trans_type_str[XFS_TRANS_TYPE_MAX] = { - TRANS_TYPE_STR(SETATTR_NOT_SIZE), - TRANS_TYPE_STR(SETATTR_SIZE), - TRANS_TYPE_STR(INACTIVE), - TRANS_TYPE_STR(CREATE), - TRANS_TYPE_STR(CREATE_TRUNC), - TRANS_TYPE_STR(TRUNCATE_FILE), - TRANS_TYPE_STR(REMOVE), - TRANS_TYPE_STR(LINK), - TRANS_TYPE_STR(RENAME), - TRANS_TYPE_STR(MKDIR), - TRANS_TYPE_STR(RMDIR), - TRANS_TYPE_STR(SYMLINK), - TRANS_TYPE_STR(SET_DMATTRS), - TRANS_TYPE_STR(GROWFS), - TRANS_TYPE_STR(STRAT_WRITE), - TRANS_TYPE_STR(DIOSTRAT), - TRANS_TYPE_STR(WRITEID), - TRANS_TYPE_STR(ADDAFORK), - TRANS_TYPE_STR(ATTRINVAL), - TRANS_TYPE_STR(ATRUNCATE), - TRANS_TYPE_STR(ATTR_SET), - TRANS_TYPE_STR(ATTR_RM), - TRANS_TYPE_STR(ATTR_FLAG), - TRANS_TYPE_STR(CLEAR_AGI_BUCKET), - TRANS_TYPE_STR(SB_CHANGE), - TRANS_TYPE_STR(DUMMY1), - TRANS_TYPE_STR(DUMMY2), - TRANS_TYPE_STR(QM_QUOTAOFF), - TRANS_TYPE_STR(QM_DQALLOC), - TRANS_TYPE_STR(QM_SETQLIM), - TRANS_TYPE_STR(QM_DQCLUSTER), - TRANS_TYPE_STR(QM_QINOCREATE), - TRANS_TYPE_STR(QM_QUOTAOFF_END), - TRANS_TYPE_STR(FSYNC_TS), - TRANS_TYPE_STR(GROWFSRT_ALLOC), - TRANS_TYPE_STR(GROWFSRT_ZERO), - TRANS_TYPE_STR(GROWFSRT_FREE), - TRANS_TYPE_STR(SWAPEXT), - TRANS_TYPE_STR(CHECKPOINT), - TRANS_TYPE_STR(ICREATE), - TRANS_TYPE_STR(CREATE_TMPFILE) - }; -#undef TRANS_TYPE_STR xfs_warn(mp, "xlog_write: reservation summary:"); - xfs_warn(mp, " trans type = %s (%u)", - ((ticket->t_trans_type <= 0 || - ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? - "bad-trans-type" : trans_type_str[ticket->t_trans_type]), - ticket->t_trans_type); xfs_warn(mp, " unit res = %d bytes", ticket->t_unit_res); xfs_warn(mp, " current res = %d bytes", @@ -3709,7 +3656,6 @@ xlog_ticket_alloc( tic->t_tid = prandom_u32(); tic->t_clientid = client; tic->t_flags = XLOG_TIC_INITED; - tic->t_trans_type = 0; if (permanent) tic->t_flags |= XLOG_TIC_PERM_RESERV; diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index aa533a7d50f2..80ba0c047090 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h @@ -161,8 +161,7 @@ int xfs_log_reserve(struct xfs_mount *mp, int count, struct xlog_ticket **ticket, __uint8_t clientid, - bool permanent, - uint t_type); + bool permanent); int xfs_log_regrant(struct xfs_mount *mp, struct xlog_ticket *tic); int xfs_log_unmount_write(struct xfs_mount *mp); void xfs_log_unmount(struct xfs_mount *mp); diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 4e7649351f5a..5e54e7955ea6 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -51,7 +51,6 @@ xlog_cil_ticket_alloc( tic = xlog_ticket_alloc(log, 0, 1, XFS_TRANSACTION, 0, KM_SLEEP|KM_NOFS); - tic->t_trans_type = XFS_TRANS_CHECKPOINT; /* * set the current reservation to zero so we know to steal the basic diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index ed8896310c00..765f084759b5 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -175,7 +175,6 @@ typedef struct xlog_ticket { char t_cnt; /* current count : 1 */ char t_clientid; /* who does this belong to; : 1 */ char t_flags; /* properties of reservation : 1 */ - uint t_trans_type; /* transaction type : 4 */ /* reservation array fields */ uint t_res_num; /* num in array : 4 */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index c8d58426008e..f08129444280 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -944,7 +944,6 @@ DECLARE_EVENT_CLASS(xfs_loggrant_class, TP_ARGS(log, tic), TP_STRUCT__entry( __field(dev_t, dev) - __field(unsigned, trans_type) __field(char, ocnt) __field(char, cnt) __field(int, curr_res) @@ -962,7 +961,6 @@ DECLARE_EVENT_CLASS(xfs_loggrant_class, ), TP_fast_assign( __entry->dev = log->l_mp->m_super->s_dev; - __entry->trans_type = tic->t_trans_type; __entry->ocnt = tic->t_ocnt; __entry->cnt = tic->t_cnt; __entry->curr_res = tic->t_curr_res; @@ -980,14 +978,13 @@ DECLARE_EVENT_CLASS(xfs_loggrant_class, __entry->curr_block = log->l_curr_block; __entry->tail_lsn = atomic64_read(&log->l_tail_lsn); ), - TP_printk("dev %d:%d type %s t_ocnt %u t_cnt %u t_curr_res %u " + TP_printk("dev %d:%d t_ocnt %u t_cnt %u t_curr_res %u " "t_unit_res %u t_flags %s reserveq %s " "writeq %s grant_reserve_cycle %d " "grant_reserve_bytes %d grant_write_cycle %d " "grant_write_bytes %d curr_cycle %d curr_block %d " "tail_cycle %d tail_block %d", MAJOR(__entry->dev), MINOR(__entry->dev), - __print_symbolic(__entry->trans_type, XFS_TRANS_TYPES), __entry->ocnt, __entry->cnt, __entry->curr_res, diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index b3669efb2a0a..5f3d33d16e67 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -177,7 +177,7 @@ xfs_trans_reserve( resp->tr_logres, resp->tr_logcount, &tp->t_ticket, XFS_TRANSACTION, - permanent, 0); + permanent); } if (error) -- GitLab From f5a9ec20b3b2adf03a0b01902cda913b05abd382 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Tue, 5 Apr 2016 13:59:59 -0700 Subject: [PATCH 1512/9938] net: bcmgenet: cleanup for bcmgenet_xmit() 1. Readability: Move nr_frags assignment a few lines down in order to bundle index -> ring -> txq calculations together. 2. Readability: Add parentheses around nr_frags + 1. 3. Minor fix: Stop the Tx queue and throw the error message only if the Tx queue hasn't already been stopped. Signed-off-by: Petri Gynther Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index cf6445d148ca..7f85a8494eee 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1447,15 +1447,19 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) else index -= 1; - nr_frags = skb_shinfo(skb)->nr_frags; ring = &priv->tx_rings[index]; txq = netdev_get_tx_queue(dev, ring->queue); + nr_frags = skb_shinfo(skb)->nr_frags; + spin_lock_irqsave(&ring->lock, flags); - if (ring->free_bds <= nr_frags + 1) { - netif_tx_stop_queue(txq); - netdev_err(dev, "%s: tx ring %d full when queue %d awake\n", - __func__, index, ring->queue); + if (ring->free_bds <= (nr_frags + 1)) { + if (!netif_tx_queue_stopped(txq)) { + netif_tx_stop_queue(txq); + netdev_err(dev, + "%s: tx ring %d full when queue %d awake\n", + __func__, index, ring->queue); + } ret = NETDEV_TX_BUSY; goto out; } -- GitLab From 824ba603573d910e32df75fe6a5e7d7ec2a0a6a7 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Tue, 5 Apr 2016 14:00:00 -0700 Subject: [PATCH 1513/9938] net: bcmgenet: cleanup for bcmgenet_xmit_frag() Add frag_size = skb_frag_size(frag) and use it when needed. Signed-off-by: Petri Gynther Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 7f85a8494eee..d77cd6dee092 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1331,6 +1331,7 @@ static int bcmgenet_xmit_frag(struct net_device *dev, struct bcmgenet_priv *priv = netdev_priv(dev); struct device *kdev = &priv->pdev->dev; struct enet_cb *tx_cb_ptr; + unsigned int frag_size; dma_addr_t mapping; int ret; @@ -1338,10 +1339,12 @@ static int bcmgenet_xmit_frag(struct net_device *dev, if (unlikely(!tx_cb_ptr)) BUG(); + tx_cb_ptr->skb = NULL; - mapping = skb_frag_dma_map(kdev, frag, 0, - skb_frag_size(frag), DMA_TO_DEVICE); + frag_size = skb_frag_size(frag); + + mapping = skb_frag_dma_map(kdev, frag, 0, frag_size, DMA_TO_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { priv->mib.tx_dma_failed++; @@ -1351,10 +1354,10 @@ static int bcmgenet_xmit_frag(struct net_device *dev, } dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping); - dma_unmap_len_set(tx_cb_ptr, dma_len, frag->size); + dma_unmap_len_set(tx_cb_ptr, dma_len, frag_size); dmadesc_set(priv, tx_cb_ptr->bd_addr, mapping, - (frag->size << DMA_BUFLENGTH_SHIFT) | dma_desc_flags | + (frag_size << DMA_BUFLENGTH_SHIFT) | dma_desc_flags | (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT)); return 0; -- GitLab From 7ee4062562bae8f248f0aa72dfb3023ddea65942 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Tue, 5 Apr 2016 14:00:01 -0700 Subject: [PATCH 1514/9938] net: bcmgenet: cleanup for dmadesc_set() dmadesc_set() is used for setting the Tx buffer DMA address, length, and status bits on a Tx ring descriptor when a frame is being Tx'ed. Always set the Tx buffer DMA address first, before updating the length and status bits, i.e. giving the Tx descriptor to the hardware. The reason this is a cleanup rather than a fix is that the hardware won't transmit anything from a Tx ring until the TDMA producer index has been incremented. As long as the dmadesc_set() writes complete before the TDMA producer index write, life is good. Signed-off-by: Petri Gynther Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index d77cd6dee092..f7b42b9fc979 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -104,8 +104,8 @@ static inline void dmadesc_set_addr(struct bcmgenet_priv *priv, static inline void dmadesc_set(struct bcmgenet_priv *priv, void __iomem *d, dma_addr_t addr, u32 val) { - dmadesc_set_length_status(priv, d, val); dmadesc_set_addr(priv, d, addr); + dmadesc_set_length_status(priv, d, val); } static inline dma_addr_t dmadesc_get_addr(struct bcmgenet_priv *priv, -- GitLab From 9f27889f3a96ff356ac92688cc0c4be3935ae3af Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Wed, 6 Apr 2016 09:46:30 +1000 Subject: [PATCH 1515/9938] xfs: Add caller function output to xfs_log_force tracepoint I had sent this patch yesterday, but for some reason it didn't reach xfs list, sending again. Output the caller of xfs_log_force might be useful when tracing log checkpoint problems without the need to build kernel with DEBUG. Signed-off-by: Carlos Maiolino Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_log.c | 4 ++-- fs/xfs/xfs_trace.h | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index b49ccf5c1d75..8c08015bc094 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -3378,7 +3378,7 @@ xfs_log_force( { int error; - trace_xfs_log_force(mp, 0); + trace_xfs_log_force(mp, 0, _RET_IP_); error = _xfs_log_force(mp, flags, NULL); if (error) xfs_warn(mp, "%s: error %d returned.", __func__, error); @@ -3527,7 +3527,7 @@ xfs_log_force_lsn( { int error; - trace_xfs_log_force(mp, lsn); + trace_xfs_log_force(mp, lsn, _RET_IP_); error = _xfs_log_force_lsn(mp, lsn, flags, NULL); if (error) xfs_warn(mp, "%s: error %d returned.", __func__, error); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index c8d58426008e..384bb1791481 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1053,19 +1053,21 @@ DECLARE_EVENT_CLASS(xfs_log_item_class, ) TRACE_EVENT(xfs_log_force, - TP_PROTO(struct xfs_mount *mp, xfs_lsn_t lsn), - TP_ARGS(mp, lsn), + TP_PROTO(struct xfs_mount *mp, xfs_lsn_t lsn, unsigned long caller_ip), + TP_ARGS(mp, lsn, caller_ip), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_lsn_t, lsn) + __field(unsigned long, caller_ip) ), TP_fast_assign( __entry->dev = mp->m_super->s_dev; __entry->lsn = lsn; + __entry->caller_ip = caller_ip; ), - TP_printk("dev %d:%d lsn 0x%llx", + TP_printk("dev %d:%d lsn 0x%llx caller %ps", MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->lsn) + __entry->lsn, (void *)__entry->caller_ip) ) #define DEFINE_LOG_ITEM_EVENT(name) \ -- GitLab From 664b60f6babc98ee03c2ff15b9482cc8c5e15a83 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 6 Apr 2016 09:47:01 +1000 Subject: [PATCH 1516/9938] xfs: improve kmem_realloc Use krealloc to implement our realloc function. This helps to avoid new allocations if we are still in the slab bucket. At least for the bmap btree root that's actually the common case. This also allows removing the now unused oldsize argument. Signed-off-by: Christoph Hellwig Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/kmem.c | 26 +++++++++++++++----------- fs/xfs/kmem.h | 2 +- fs/xfs/libxfs/xfs_inode_fork.c | 10 +++------- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_mount.c | 1 - 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c index 686ba6fb20dd..339c696bbc01 100644 --- a/fs/xfs/kmem.c +++ b/fs/xfs/kmem.c @@ -93,19 +93,23 @@ kmem_zalloc_large(size_t size, xfs_km_flags_t flags) } void * -kmem_realloc(const void *ptr, size_t newsize, size_t oldsize, - xfs_km_flags_t flags) +kmem_realloc(const void *old, size_t newsize, xfs_km_flags_t flags) { - void *new; + int retries = 0; + gfp_t lflags = kmem_flags_convert(flags); + void *ptr; - new = kmem_alloc(newsize, flags); - if (ptr) { - if (new) - memcpy(new, ptr, - ((oldsize < newsize) ? oldsize : newsize)); - kmem_free(ptr); - } - return new; + do { + ptr = krealloc(old, newsize, lflags); + if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP))) + return ptr; + if (!(++retries % 100)) + xfs_err(NULL, + "%s(%u) possible memory allocation deadlock size %zu in %s (mode:0x%x)", + current->comm, current->pid, + newsize, __func__, lflags); + congestion_wait(BLK_RW_ASYNC, HZ/50); + } while (1); } void * diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index d1c66e465ca5..689f746224e7 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h @@ -62,7 +62,7 @@ kmem_flags_convert(xfs_km_flags_t flags) extern void *kmem_alloc(size_t, xfs_km_flags_t); extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t); -extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); +extern void *kmem_realloc(const void *, size_t, xfs_km_flags_t); static inline void kmem_free(const void *ptr) { kvfree(ptr); diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 11faf7df14c8..1c842dce44b6 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -516,7 +516,6 @@ xfs_iroot_realloc( new_max = cur_max + rec_diff; new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max); ifp->if_broot = kmem_realloc(ifp->if_broot, new_size, - XFS_BMAP_BROOT_SPACE_CALC(mp, cur_max), KM_SLEEP | KM_NOFS); op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, ifp->if_broot_bytes); @@ -660,7 +659,6 @@ xfs_idata_realloc( ifp->if_u1.if_data = kmem_realloc(ifp->if_u1.if_data, real_size, - ifp->if_real_bytes, KM_SLEEP | KM_NOFS); } } else { @@ -1376,8 +1374,7 @@ xfs_iext_realloc_direct( if (rnew_size != ifp->if_real_bytes) { ifp->if_u1.if_extents = kmem_realloc(ifp->if_u1.if_extents, - rnew_size, - ifp->if_real_bytes, KM_NOFS); + rnew_size, KM_NOFS); } if (rnew_size > ifp->if_real_bytes) { memset(&ifp->if_u1.if_extents[ifp->if_bytes / @@ -1461,9 +1458,8 @@ xfs_iext_realloc_indirect( if (new_size == 0) { xfs_iext_destroy(ifp); } else { - ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *) - kmem_realloc(ifp->if_u1.if_ext_irec, - new_size, size, KM_NOFS); + ifp->if_u1.if_ext_irec = + kmem_realloc(ifp->if_u1.if_ext_irec, new_size, KM_NOFS); } } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 396565f43247..bf6e80703613 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3843,7 +3843,7 @@ xlog_recover_add_to_cont_trans( old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; old_len = item->ri_buf[item->ri_cnt-1].i_len; - ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP); + ptr = kmem_realloc(old_ptr, len + old_len, KM_SLEEP); memcpy(&ptr[old_len], dp, len); item->ri_buf[item->ri_cnt-1].i_len += len; item->ri_buf[item->ri_cnt-1].i_addr = ptr; diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 536a0ee9cd5a..654799f716fc 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -89,7 +89,6 @@ xfs_uuid_mount( if (hole < 0) { xfs_uuid_table = kmem_realloc(xfs_uuid_table, (xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table), - xfs_uuid_table_size * sizeof(*xfs_uuid_table), KM_SLEEP); hole = xfs_uuid_table_size++; } -- GitLab From 6e3e6d55e51774ec7cfc24975749bbddb28a9051 Mon Sep 17 00:00:00 2001 From: Eryu Guan Date: Wed, 6 Apr 2016 09:47:21 +1000 Subject: [PATCH 1517/9938] xfs: mute some sparse warnings These three warnings are fixed: fs/xfs/xfs_inode.c:1033:44: warning: Using plain integer as NULL pointer fs/xfs/xfs_inode_item.c:525:20: warning: context imbalance in 'xfs_inode_item_push' - unexpected unlock fs/xfs/xfs_dquot.c:696:1: warning: symbol 'xfs_dq_get_next_id' was not declared. Should it be static? Signed-off-by: Eryu Guan Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_dquot.c | 2 +- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode_item.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 316b2a1bdba5..8f51370c95c4 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -692,7 +692,7 @@ xfs_qm_dqread( * end of the chunk, skip ahead to first id in next allocated chunk * using the SEEK_DATA interface. */ -int +static int xfs_dq_get_next_id( xfs_mount_t *mp, uint type, diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 96f606deee31..1445a99a6868 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1030,7 +1030,7 @@ xfs_dir_ialloc( tp->t_flags &= ~(XFS_TRANS_DQ_DIRTY); } - code = xfs_trans_roll(&tp, 0); + code = xfs_trans_roll(&tp, NULL); if (committed != NULL) *committed = 1; diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index c48b5b18d771..d02cbab18f45 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -479,6 +479,8 @@ STATIC uint xfs_inode_item_push( struct xfs_log_item *lip, struct list_head *buffer_list) + __releases(&lip->li_ailp->xa_lock) + __acquires(&lip->li_ailp->xa_lock) { struct xfs_inode_log_item *iip = INODE_ITEM(lip); struct xfs_inode *ip = iip->ili_inode; -- GitLab From ad7775dc7b8b0b5585ff114b04d5ad50737c423e Mon Sep 17 00:00:00 2001 From: Thomas Falcon Date: Fri, 1 Apr 2016 17:20:34 -0500 Subject: [PATCH 1518/9938] ibmvnic: map L2/L3/L4 header descriptors to firmware Allow the VNIC driver to provide descriptors containing L2/L3/L4 headers to firmware. This feature is needed for greater hardware compatibility and enablement of checksum and TCP offloading features. A new function is included for the hypervisor call, H_SEND_SUBCRQ_INDIRECT, allowing a DMA-mapped array of SCRQ descriptor elements to be sent to the VNIC server. These additions will help fully enable checksum offloading as well as other features as they are included later. Signed-off-by: Thomas Falcon Cc: John Allen Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 195 ++++++++++++++++++++++++++++- drivers/net/ethernet/ibm/ibmvnic.h | 3 + 2 files changed, 194 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 6e9e16eee5d0..4e97e762e297 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,7 @@ static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *); static int ibmvnic_send_crq(struct ibmvnic_adapter *, union ibmvnic_crq *); static int send_subcrq(struct ibmvnic_adapter *adapter, u64 remote_handle, union sub_crq *sub_crq); +static int send_subcrq_indirect(struct ibmvnic_adapter *, u64, u64, u64); static irqreturn_t ibmvnic_interrupt_rx(int irq, void *instance); static int enable_scrq_irq(struct ibmvnic_adapter *, struct ibmvnic_sub_crq_queue *); @@ -561,10 +563,141 @@ static int ibmvnic_close(struct net_device *netdev) return 0; } +/** + * build_hdr_data - creates L2/L3/L4 header data buffer + * @hdr_field - bitfield determining needed headers + * @skb - socket buffer + * @hdr_len - array of header lengths + * @tot_len - total length of data + * + * Reads hdr_field to determine which headers are needed by firmware. + * Builds a buffer containing these headers. Saves individual header + * lengths and total buffer length to be used to build descriptors. + */ +static int build_hdr_data(u8 hdr_field, struct sk_buff *skb, + int *hdr_len, u8 *hdr_data) +{ + int len = 0; + u8 *hdr; + + hdr_len[0] = sizeof(struct ethhdr); + + if (skb->protocol == htons(ETH_P_IP)) { + hdr_len[1] = ip_hdr(skb)->ihl * 4; + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + hdr_len[2] = tcp_hdrlen(skb); + else if (ip_hdr(skb)->protocol == IPPROTO_UDP) + hdr_len[2] = sizeof(struct udphdr); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + hdr_len[1] = sizeof(struct ipv6hdr); + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + hdr_len[2] = tcp_hdrlen(skb); + else if (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP) + hdr_len[2] = sizeof(struct udphdr); + } + + memset(hdr_data, 0, 120); + if ((hdr_field >> 6) & 1) { + hdr = skb_mac_header(skb); + memcpy(hdr_data, hdr, hdr_len[0]); + len += hdr_len[0]; + } + + if ((hdr_field >> 5) & 1) { + hdr = skb_network_header(skb); + memcpy(hdr_data + len, hdr, hdr_len[1]); + len += hdr_len[1]; + } + + if ((hdr_field >> 4) & 1) { + hdr = skb_transport_header(skb); + memcpy(hdr_data + len, hdr, hdr_len[2]); + len += hdr_len[2]; + } + return len; +} + +/** + * create_hdr_descs - create header and header extension descriptors + * @hdr_field - bitfield determining needed headers + * @data - buffer containing header data + * @len - length of data buffer + * @hdr_len - array of individual header lengths + * @scrq_arr - descriptor array + * + * Creates header and, if needed, header extension descriptors and + * places them in a descriptor array, scrq_arr + */ + +static void create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len, + union sub_crq *scrq_arr) +{ + union sub_crq hdr_desc; + int tmp_len = len; + u8 *data, *cur; + int tmp; + + while (tmp_len > 0) { + cur = hdr_data + len - tmp_len; + + memset(&hdr_desc, 0, sizeof(hdr_desc)); + if (cur != hdr_data) { + data = hdr_desc.hdr_ext.data; + tmp = tmp_len > 29 ? 29 : tmp_len; + hdr_desc.hdr_ext.first = IBMVNIC_CRQ_CMD; + hdr_desc.hdr_ext.type = IBMVNIC_HDR_EXT_DESC; + hdr_desc.hdr_ext.len = tmp; + } else { + data = hdr_desc.hdr.data; + tmp = tmp_len > 24 ? 24 : tmp_len; + hdr_desc.hdr.first = IBMVNIC_CRQ_CMD; + hdr_desc.hdr.type = IBMVNIC_HDR_DESC; + hdr_desc.hdr.len = tmp; + hdr_desc.hdr.l2_len = (u8)hdr_len[0]; + hdr_desc.hdr.l3_len = cpu_to_be16((u16)hdr_len[1]); + hdr_desc.hdr.l4_len = (u8)hdr_len[2]; + hdr_desc.hdr.flag = hdr_field << 1; + } + memcpy(data, cur, tmp); + tmp_len -= tmp; + *scrq_arr = hdr_desc; + scrq_arr++; + } +} + +/** + * build_hdr_descs_arr - build a header descriptor array + * @skb - socket buffer + * @num_entries - number of descriptors to be sent + * @subcrq - first TX descriptor + * @hdr_field - bit field determining which headers will be sent + * + * This function will build a TX descriptor array with applicable + * L2/L3/L4 packet header descriptors to be sent by send_subcrq_indirect. + */ + +static void build_hdr_descs_arr(struct ibmvnic_tx_buff *txbuff, + int *num_entries, u8 hdr_field) +{ + int hdr_len[3] = {0, 0, 0}; + int tot_len, len; + u8 *hdr_data = txbuff->hdr_data; + + tot_len = build_hdr_data(hdr_field, txbuff->skb, hdr_len, + txbuff->hdr_data); + len = tot_len; + len -= 24; + if (len > 0) + num_entries += len % 29 ? len / 29 + 1 : len / 29; + create_hdr_descs(hdr_field, hdr_data, tot_len, hdr_len, + txbuff->indir_arr + 1); +} + static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); int queue_num = skb_get_queue_mapping(skb); + u8 *hdrs = (u8 *)&adapter->tx_rx_desc_req; struct device *dev = &adapter->vdev->dev; struct ibmvnic_tx_buff *tx_buff = NULL; struct ibmvnic_tx_pool *tx_pool; @@ -579,6 +712,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) unsigned long lpar_rc; union sub_crq tx_crq; unsigned int offset; + int num_entries = 1; unsigned char *dst; u64 *handle_array; int index = 0; @@ -644,11 +778,34 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) tx_crq.v1.flags1 |= IBMVNIC_TX_PROT_UDP; } - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_PARTIAL) { tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD; - - lpar_rc = send_subcrq(adapter, handle_array[0], &tx_crq); - + hdrs += 2; + } + /* determine if l2/3/4 headers are sent to firmware */ + if ((*hdrs >> 7) & 1 && + (skb->protocol == htons(ETH_P_IP) || + skb->protocol == htons(ETH_P_IPV6))) { + build_hdr_descs_arr(tx_buff, &num_entries, *hdrs); + tx_crq.v1.n_crq_elem = num_entries; + tx_buff->indir_arr[0] = tx_crq; + tx_buff->indir_dma = dma_map_single(dev, tx_buff->indir_arr, + sizeof(tx_buff->indir_arr), + DMA_TO_DEVICE); + if (dma_mapping_error(dev, tx_buff->indir_dma)) { + if (!firmware_has_feature(FW_FEATURE_CMO)) + dev_err(dev, "tx: unable to map descriptor array\n"); + tx_map_failed++; + tx_dropped++; + ret = NETDEV_TX_BUSY; + goto out; + } + lpar_rc = send_subcrq_indirect(adapter, handle_array[0], + (u64)tx_buff->indir_dma, + (u64)num_entries); + } else { + lpar_rc = send_subcrq(adapter, handle_array[0], &tx_crq); + } if (lpar_rc != H_SUCCESS) { dev_err(dev, "tx failed with code %ld\n", lpar_rc); @@ -1159,6 +1316,7 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter, union sub_crq *next; int index; int i, j; + u8 first; restart_loop: while (pending_scrq(adapter, scrq)) { @@ -1181,6 +1339,13 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter, txbuff->data_dma[j] = 0; txbuff->used_bounce = false; } + /* if sub_crq was sent indirectly */ + first = txbuff->indir_arr[0].generic.first; + if (first == IBMVNIC_CRQ_CMD) { + dma_unmap_single(dev, txbuff->indir_dma, + sizeof(txbuff->indir_arr), + DMA_TO_DEVICE); + } if (txbuff->last_frag) dev_kfree_skb_any(txbuff->skb); @@ -1494,6 +1659,28 @@ static int send_subcrq(struct ibmvnic_adapter *adapter, u64 remote_handle, return rc; } +static int send_subcrq_indirect(struct ibmvnic_adapter *adapter, + u64 remote_handle, u64 ioba, u64 num_entries) +{ + unsigned int ua = adapter->vdev->unit_address; + struct device *dev = &adapter->vdev->dev; + int rc; + + /* Make sure the hypervisor sees the complete request */ + mb(); + rc = plpar_hcall_norets(H_SEND_SUB_CRQ_INDIRECT, ua, + cpu_to_be64(remote_handle), + ioba, num_entries); + + if (rc) { + if (rc == H_CLOSED) + dev_warn(dev, "CRQ Queue closed\n"); + dev_err(dev, "Send (indirect) error (rc=%d)\n", rc); + } + + return rc; +} + static int ibmvnic_send_crq(struct ibmvnic_adapter *adapter, union ibmvnic_crq *crq) { diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 1a9993cc79b5..5af8a796e523 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -879,6 +879,9 @@ struct ibmvnic_tx_buff { int pool_index; bool last_frag; bool used_bounce; + union sub_crq indir_arr[6]; + u8 hdr_data[140]; + dma_addr_t indir_dma; }; struct ibmvnic_tx_pool { -- GitLab From 9be02cdfa601776f9e65013d9f1b949d5024f457 Mon Sep 17 00:00:00 2001 From: Thomas Falcon Date: Fri, 1 Apr 2016 17:20:35 -0500 Subject: [PATCH 1519/9938] ibmvnic: enable RX checksum offload Enable RX Checksum offload feature in the ibmvnic driver. Signed-off-by: Thomas Falcon Cc: John Allen Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 4e97e762e297..21bccf6eb919 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2105,6 +2105,10 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter) if (buf->tcp_ipv6_chksum || buf->udp_ipv6_chksum) adapter->netdev->features |= NETIF_F_IPV6_CSUM; + if ((adapter->netdev->features & + (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))) + adapter->netdev->features |= NETIF_F_RXCSUM; + memset(&crq, 0, sizeof(crq)); crq.control_ip_offload.first = IBMVNIC_CRQ_CMD; crq.control_ip_offload.cmd = CONTROL_IP_OFFLOAD; -- GitLab From f9cd476123ced488e628339becedb2cf3243a58a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 4 Apr 2016 22:44:59 +0200 Subject: [PATCH 1520/9938] dmaengine: pl08x: allocate OF slave channel data at probe time The current OF translation of channels can never work with any DMA client using the DMA channels directly: the only way to get the channels initialized properly is in the dma_async_device_register() call, where chan->dev etc is allocated and initialized. Allocate and initialize all possible DMA channels and only augment a target channel with the periph_buses at of_xlate(). Remove some const settings to make things work. Cc: Maxime Ripard Tested-by: Joachim Eastwood Tested-by: Johannes Stezenbach Signed-off-by: Linus Walleij Signed-off-by: Vinod Koul --- drivers/dma/amba-pl08x.c | 86 +++++++++++++++++++++++++------------- include/linux/amba/pl08x.h | 2 +- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 9b42c0588550..81db1c4811ce 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -107,16 +107,20 @@ struct pl08x_driver_data; /** * struct vendor_data - vendor-specific config parameters for PL08x derivatives * @channels: the number of channels available in this variant + * @signals: the number of request signals available from the hardware * @dualmaster: whether this version supports dual AHB masters or not. * @nomadik: whether the channels have Nomadik security extension bits * that need to be checked for permission before use and some registers are * missing * @pl080s: whether this version is a PL080S, which has separate register and * LLI word for transfer size. + * @max_transfer_size: the maximum single element transfer size for this + * PL08x variant. */ struct vendor_data { u8 config_offset; u8 channels; + u8 signals; bool dualmaster; bool nomadik; bool pl080s; @@ -235,7 +239,7 @@ struct pl08x_dma_chan { struct virt_dma_chan vc; struct pl08x_phy_chan *phychan; const char *name; - const struct pl08x_channel_data *cd; + struct pl08x_channel_data *cd; struct dma_slave_config cfg; struct pl08x_txd *at; struct pl08x_driver_data *host; @@ -1909,6 +1913,12 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x, if (slave) { chan->cd = &pl08x->pd->slave_channels[i]; + /* + * Some implementations have muxed signals, whereas some + * use a mux in front of the signals and need dynamic + * assignment of signals. + */ + chan->signal = i; pl08x_dma_slave_init(chan); } else { chan->cd = &pl08x->pd->memcpy_channel; @@ -2050,40 +2060,33 @@ static struct dma_chan *pl08x_of_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { struct pl08x_driver_data *pl08x = ofdma->of_dma_data; - struct pl08x_channel_data *data; - struct pl08x_dma_chan *chan; struct dma_chan *dma_chan; + struct pl08x_dma_chan *plchan; if (!pl08x) return NULL; - if (dma_spec->args_count != 2) + if (dma_spec->args_count != 2) { + dev_err(&pl08x->adev->dev, + "DMA channel translation requires two cells\n"); return NULL; + } dma_chan = pl08x_find_chan_id(pl08x, dma_spec->args[0]); - if (dma_chan) - return dma_get_slave_channel(dma_chan); - - chan = devm_kzalloc(pl08x->slave.dev, sizeof(*chan) + sizeof(*data), - GFP_KERNEL); - if (!chan) + if (!dma_chan) { + dev_err(&pl08x->adev->dev, + "DMA slave channel not found\n"); return NULL; + } - data = (void *)&chan[1]; - data->bus_id = "(none)"; - data->periph_buses = dma_spec->args[1]; - - chan->cd = data; - chan->host = pl08x; - chan->slave = true; - chan->name = data->bus_id; - chan->state = PL08X_CHAN_IDLE; - chan->signal = dma_spec->args[0]; - chan->vc.desc_free = pl08x_desc_free; - - vchan_init(&chan->vc, &pl08x->slave); + plchan = to_pl08x_chan(dma_chan); + dev_dbg(&pl08x->adev->dev, + "translated channel for signal %d\n", + dma_spec->args[0]); - return dma_get_slave_channel(&chan->vc.chan); + /* Augment channel data for applicable AHB buses */ + plchan->cd->periph_buses = dma_spec->args[1]; + return dma_get_slave_channel(dma_chan); } static int pl08x_of_probe(struct amba_device *adev, @@ -2091,9 +2094,11 @@ static int pl08x_of_probe(struct amba_device *adev, struct device_node *np) { struct pl08x_platform_data *pd; + struct pl08x_channel_data *chanp = NULL; u32 cctl_memcpy = 0; u32 val; int ret; + int i; pd = devm_kzalloc(&adev->dev, sizeof(*pd), GFP_KERNEL); if (!pd) @@ -2195,6 +2200,27 @@ static int pl08x_of_probe(struct amba_device *adev, /* Use the buses that can access memory, obviously */ pd->memcpy_channel.periph_buses = pd->mem_buses; + /* + * Allocate channel data for all possible slave channels (one + * for each possible signal), channels will then be allocated + * for a device and have it's AHB interfaces set up at + * translation time. + */ + chanp = devm_kcalloc(&adev->dev, + pl08x->vd->signals, + sizeof(struct pl08x_channel_data), + GFP_KERNEL); + if (!chanp) + return -ENOMEM; + + pd->slave_channels = chanp; + for (i = 0; i < pl08x->vd->signals; i++) { + /* chanp->periph_buses will be assigned at translation */ + chanp->bus_id = kasprintf(GFP_KERNEL, "slave%d", i); + chanp++; + } + pd->num_slave_channels = pl08x->vd->signals; + pl08x->pd = pd; return of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate, @@ -2234,6 +2260,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) goto out_no_pl08x; } + /* Assign useful pointers to the driver state */ + pl08x->adev = adev; + pl08x->vd = vd; + /* Initialize memcpy engine */ dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask); pl08x->memcpy.dev = &adev->dev; @@ -2284,10 +2314,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) } } - /* Assign useful pointers to the driver state */ - pl08x->adev = adev; - pl08x->vd = vd; - /* By default, AHB1 only. If dualmaster, from platform */ pl08x->lli_buses = PL08X_AHB1; pl08x->mem_buses = PL08X_AHB1; @@ -2438,6 +2464,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) static struct vendor_data vendor_pl080 = { .config_offset = PL080_CH_CONFIG, .channels = 8, + .signals = 16, .dualmaster = true, .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK, }; @@ -2445,6 +2472,7 @@ static struct vendor_data vendor_pl080 = { static struct vendor_data vendor_nomadik = { .config_offset = PL080_CH_CONFIG, .channels = 8, + .signals = 32, .dualmaster = true, .nomadik = true, .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK, @@ -2453,6 +2481,7 @@ static struct vendor_data vendor_nomadik = { static struct vendor_data vendor_pl080s = { .config_offset = PL080S_CH_CONFIG, .channels = 8, + .signals = 32, .pl080s = true, .max_transfer_size = PL080S_CONTROL_TRANSFER_SIZE_MASK, }; @@ -2460,6 +2489,7 @@ static struct vendor_data vendor_pl080s = { static struct vendor_data vendor_pl081 = { .config_offset = PL080_CH_CONFIG, .channels = 2, + .signals = 16, .dualmaster = false, .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK, }; diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h index 10fe2a211c2e..27e9ec8778eb 100644 --- a/include/linux/amba/pl08x.h +++ b/include/linux/amba/pl08x.h @@ -86,7 +86,7 @@ struct pl08x_channel_data { * @mem_buses: buses which memory can be accessed from: PL08X_AHB1 | PL08X_AHB2 */ struct pl08x_platform_data { - const struct pl08x_channel_data *slave_channels; + struct pl08x_channel_data *slave_channels; unsigned int num_slave_channels; struct pl08x_channel_data memcpy_channel; int (*get_xfer_signal)(const struct pl08x_channel_data *); -- GitLab From 4da46cebbd3b4dc445195a9672c99c1353af5695 Mon Sep 17 00:00:00 2001 From: Aaron Conole Date: Sat, 2 Apr 2016 15:26:43 -0400 Subject: [PATCH 1521/9938] net/core/dev: Warn on a too-short GRO frame When signaling that a GRO frame is ready to be processed, the network stack correctly checks length and aborts processing when a frame is less than 14 bytes. However, such a condition is really indicative of a broken driver, and should be loudly signaled, rather than silently dropped as the case is today. Convert the condition to use net_warn_ratelimited() to ensure the stack loudly complains about such broken drivers. Signed-off-by: Aaron Conole Signed-off-by: David S. Miller --- net/core/dev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index b9bcbe77d913..273f10d1e306 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4663,6 +4663,8 @@ static struct sk_buff *napi_frags_skb(struct napi_struct *napi) if (unlikely(skb_gro_header_hard(skb, hlen))) { eth = skb_gro_header_slow(skb, hlen, 0); if (unlikely(!eth)) { + net_warn_ratelimited("%s: dropping impossible skb from %s\n", + __func__, napi->dev->name); napi_reuse_skb(napi, skb); return NULL; } -- GitLab From afb8ece4326f2151771f4c40b8d9f799cee5ae6e Mon Sep 17 00:00:00 2001 From: Colin King Date: Sat, 13 Feb 2016 23:57:16 +0000 Subject: [PATCH 1522/9938] i40e: remove redundant check on vsi->active_vlans active_vlans is an unsigned long array, hence a null check on this array is superfluous and can be removed. Detected with static analysis by smatch: drivers/net/ethernet/intel/i40e/i40e_debugfs.c:386 i40e_dbg_dump_vsi_seid() warn: this array is probably non-NULL. 'vsi->active_vlans' Signed-off-by: Colin Ian King Acked-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 0c97733d253c..83dccf1792e7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -147,9 +147,8 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) dev_info(&pf->pdev->dev, " vlan_features = 0x%08lx\n", (unsigned long int)nd->vlan_features); } - if (vsi->active_vlans) - dev_info(&pf->pdev->dev, - " vlgrp: & = %p\n", vsi->active_vlans); + dev_info(&pf->pdev->dev, + " vlgrp: & = %p\n", vsi->active_vlans); dev_info(&pf->pdev->dev, " state = %li flags = 0x%08lx, netdev_registered = %i, current_netdev_flags = 0x%04x\n", vsi->state, vsi->flags, -- GitLab From 3845ccea34df30680b5be7ec119f5c74ab57fdc0 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Fri, 18 Mar 2016 12:18:05 -0700 Subject: [PATCH 1523/9938] i40e: Enable Geneve offload for FW API ver > 1.4 for XL710/X710 devices This patch enables the Capability for XL710/X710 devices with FW API version higher than 1.4 to do geneve Rx offload. Change-ID: I9a8f87772c48d7d67dc85e3701d2e0b845034c0b Signed-off-by: Anjali Singhai Jain Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 297fd39ba255..fdcb50ac5028 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9158,6 +9158,12 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) I40E_VLAN_ANY, false, true); spin_unlock_bh(&vsi->mac_filter_list_lock); } + } else if ((pf->hw.aq.api_maj_ver > 1) || + ((pf->hw.aq.api_maj_ver == 1) && + (pf->hw.aq.api_min_ver > 4))) { + /* Supported in FW API version higher than 1.4 */ + pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE; + pf->auto_disable_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE; } else { /* relate the VSI_VMDQ name to the VSI_MAIN name */ snprintf(netdev->name, IFNAMSIZ, "%sv%%d", -- GitLab From 442b25e455f5e693c23f9d3a32b208ca9ab25cf0 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 18 Mar 2016 12:18:06 -0700 Subject: [PATCH 1524/9938] i40e: Remove unused variable This variable is vestigial, a remnant of the primordial code from which this driver spawned. We can safely remove it. Change-ID: I24e0fe338e7c7c50d27dc5515564f33caefbb93a Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 47b9e62473c4..150002ed3ad6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1311,8 +1311,8 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) struct i40e_pf *pf = vf->pf; i40e_status aq_ret = 0; struct i40e_vsi *vsi; - int i = 0, len = 0; int num_vsis = 1; + int len = 0; int ret; if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states)) { @@ -1374,15 +1374,14 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) vfres->num_queue_pairs = vf->num_queue_pairs; vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf; if (vf->lan_vsi_idx) { - vfres->vsi_res[i].vsi_id = vf->lan_vsi_id; - vfres->vsi_res[i].vsi_type = I40E_VSI_SRIOV; - vfres->vsi_res[i].num_queue_pairs = vsi->alloc_queue_pairs; + vfres->vsi_res[0].vsi_id = vf->lan_vsi_id; + vfres->vsi_res[0].vsi_type = I40E_VSI_SRIOV; + vfres->vsi_res[0].num_queue_pairs = vsi->alloc_queue_pairs; /* VFs only use TC 0 */ - vfres->vsi_res[i].qset_handle + vfres->vsi_res[0].qset_handle = le16_to_cpu(vsi->info.qs_handle[0]); - ether_addr_copy(vfres->vsi_res[i].default_mac_addr, + ether_addr_copy(vfres->vsi_res[0].default_mac_addr, vf->default_lan_addr.addr); - i++; } set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states); -- GitLab From c4445aedfe092907c2e792ff76ed4338d9a1cd52 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 18 Mar 2016 12:18:07 -0700 Subject: [PATCH 1525/9938] i40evf: Fix VLAN features Users of ethtool were being given the mistaken impression that this driver was able to change its VLAN tagging features, and were disappointed that this was not actually the case. Implement ndo_fix_features method so that we can adjust these flags as needed to avoid false impressions. Change-ID: I08584f103a4fa73d6a4128d472e4ef44dcfda57f Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/i40evf/i40evf_main.c | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index e3973684746b..2d018b4d1afc 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2252,6 +2252,28 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu) return 0; } +#define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\ + NETIF_F_HW_VLAN_CTAG_RX |\ + NETIF_F_HW_VLAN_CTAG_FILTER) + +/** + * i40evf_fix_features - fix up the netdev feature bits + * @netdev: our net device + * @features: desired feature bits + * + * Returns fixed-up features bits + **/ +static netdev_features_t i40evf_fix_features(struct net_device *netdev, + netdev_features_t features) +{ + struct i40evf_adapter *adapter = netdev_priv(netdev); + + features &= ~I40EVF_VLAN_FEATURES; + if (adapter->vf_res->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_VLAN) + features |= I40EVF_VLAN_FEATURES; + return features; +} + static const struct net_device_ops i40evf_netdev_ops = { .ndo_open = i40evf_open, .ndo_stop = i40evf_close, @@ -2264,6 +2286,7 @@ static const struct net_device_ops i40evf_netdev_ops = { .ndo_tx_timeout = i40evf_tx_timeout, .ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid, + .ndo_fix_features = i40evf_fix_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = i40evf_netpoll, #endif -- GitLab From d6bf58c2e88f9e0cfc029c158e1182eb1f07d7eb Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Fri, 18 Mar 2016 12:18:08 -0700 Subject: [PATCH 1526/9938] i40e: Add new device ID for X722 The new device ID is 0x37D3 and it should follow the same flows and branding string as for 0x37D0. Change-ID: Ia5ad4a1910268c4666a3fd46a7afffbec55b4fc2 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 1 + drivers/net/ethernet/intel/i40e/i40e_devids.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + drivers/net/ethernet/intel/i40evf/i40e_common.c | 1 + drivers/net/ethernet/intel/i40evf/i40e_devids.h | 1 + 5 files changed, 5 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 8276a1393e6d..ebcc0d3ecbfb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -60,6 +60,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_SFP_X722: case I40E_DEV_ID_1G_BASE_T_X722: case I40E_DEV_ID_10G_BASE_T_X722: + case I40E_DEV_ID_SFP_I_X722: hw->mac.type = I40E_MAC_X722; break; default: diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h index 99257fcd1ef4..dd4457d29e98 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h @@ -44,6 +44,7 @@ #define I40E_DEV_ID_SFP_X722 0x37D0 #define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 #define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 +#define I40E_DEV_ID_SFP_I_X722 0x37D3 #define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \ (d) == I40E_DEV_ID_QSFP_B || \ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index fdcb50ac5028..73d4bea4c574 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -90,6 +90,7 @@ static const struct pci_device_id i40e_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_1G_BASE_T_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_X722), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_I_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0}, /* required last entry */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index 771ac6ad8cda..4db0c0326185 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -58,6 +58,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_SFP_X722: case I40E_DEV_ID_1G_BASE_T_X722: case I40E_DEV_ID_10G_BASE_T_X722: + case I40E_DEV_ID_SFP_I_X722: hw->mac.type = I40E_MAC_X722; break; case I40E_DEV_ID_X722_VF: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h index ca8b58c3d1f5..70235706915e 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_devids.h @@ -44,6 +44,7 @@ #define I40E_DEV_ID_SFP_X722 0x37D0 #define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 #define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 +#define I40E_DEV_ID_SFP_I_X722 0x37D3 #define I40E_DEV_ID_X722_VF 0x37CD #define I40E_DEV_ID_X722_VF_HV 0x37D9 -- GitLab From 7369ca8745499d001663e1dccf15064a3eb34b4d Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 18 Mar 2016 12:18:09 -0700 Subject: [PATCH 1527/9938] i40e: Make VF resets more reliable Clear the VFLR bit immediately after triggering a reset instead of waiting until after cleanup is complete. Make sure to trigger a reset every time, not just if the PF is up. These changes fix a problem where VF resets would get lost by the PF, preventing the VF driver from initializing. Change-ID: I5945cf2884095b7b0554867c64df8617e71d9d29 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 150002ed3ad6..169c256fd6ba 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -937,6 +937,10 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg); i40e_flush(hw); } + /* clear the VFLR bit in GLGEN_VFLRSTAT */ + reg_idx = (hw->func_caps.vf_base_id + vf->vf_id) / 32; + bit_idx = (hw->func_caps.vf_base_id + vf->vf_id) % 32; + wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx)); if (i40e_quiesce_vf_pci(vf)) dev_err(&pf->pdev->dev, "VF %d PCI transactions stuck\n", @@ -989,10 +993,6 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) /* tell the VF the reset is done */ wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE); - /* clear the VFLR bit in GLGEN_VFLRSTAT */ - reg_idx = (hw->func_caps.vf_base_id + vf->vf_id) / 32; - bit_idx = (hw->func_caps.vf_base_id + vf->vf_id) % 32; - wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx)); i40e_flush(hw); clear_bit(__I40E_VF_DISABLE, &pf->state); } @@ -2296,11 +2296,9 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) /* read GLGEN_VFLRSTAT register to find out the flr VFs */ vf = &pf->vf[vf_id]; reg = rd32(hw, I40E_GLGEN_VFLRSTAT(reg_idx)); - if (reg & BIT(bit_idx)) { + if (reg & BIT(bit_idx)) /* i40e_reset_vf will clear the bit in GLGEN_VFLRSTAT */ - if (!test_bit(__I40E_DOWN, &pf->state)) - i40e_reset_vf(vf, true); - } + i40e_reset_vf(vf, true); } return 0; -- GitLab From 22ead37f8af83b4fa32c15cc21d3541e74661339 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 18 Mar 2016 12:18:10 -0700 Subject: [PATCH 1528/9938] i40evf: Add longer wait after remove module Upon module remove, wait a little longer after requesting a reset before checking to see if the firmware responded. This change prevents double resets when the firmware is busy. Change-ID: Ieedc988ee82fac1f32a074bf4d9e4dba426bfa58 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 2d018b4d1afc..6561a33d84aa 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2854,11 +2854,11 @@ static void i40evf_remove(struct pci_dev *pdev) adapter->state = __I40EVF_REMOVE; adapter->aq_required = 0; i40evf_request_reset(adapter); - msleep(20); + msleep(50); /* If the FW isn't responding, kick it once, but only once. */ if (!i40evf_asq_done(hw)) { i40evf_request_reset(adapter); - msleep(20); + msleep(50); } if (adapter->msix_entries) { -- GitLab From 8c806b676d21a49628250731f4e30a8a071d080c Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 18 Mar 2016 12:18:11 -0700 Subject: [PATCH 1529/9938] i40e: Disable link polling Periodic link polling was added when the link events were found not to be trustworthy. This was the case early on, but was likely because the link event mask was being used incorrectly. As this has been fixed in recent code, we can disable the link polling to lessen the AQ traffic. Change-ID: Id890b5ee3c2d04381fc76ffa434777644f5d8eb0 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 73d4bea4c574..184f3f965a01 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8448,7 +8448,6 @@ static int i40e_sw_init(struct i40e_pf *pf) /* Set default capability flags */ pf->flags = I40E_FLAG_RX_CSUM_ENABLED | I40E_FLAG_MSI_ENABLED | - I40E_FLAG_LINK_POLLING_ENABLED | I40E_FLAG_MSIX_ENABLED; if (iommu_present(&pci_bus_type)) -- GitLab From 539a379c50220d6ac19c7300671fe25819bd3f1b Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Fri, 18 Mar 2016 12:18:12 -0700 Subject: [PATCH 1530/9938] i40evf: Fix get_rss_aq We were passing in the seed where we should just be passing false because we want the VSI table not the pf table. Change-ID: I9b633ab06eb59468087f0c0af8539857e99f9495 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 6561a33d84aa..2d1fe560cf7d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1341,7 +1341,7 @@ static int i40evf_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed, } if (lut) { - ret = i40evf_aq_get_rss_lut(hw, vsi->id, seed, lut, lut_size); + ret = i40evf_aq_get_rss_lut(hw, vsi->id, false, lut, lut_size); if (ret) { dev_err(&adapter->pdev->dev, "Cannot get RSS lut, err %s aq_err %s\n", -- GitLab From 16badc34695ff489a39e450b4e4e5a241ac85a31 Mon Sep 17 00:00:00 2001 From: Avinash Dayanand Date: Fri, 18 Mar 2016 12:18:13 -0700 Subject: [PATCH 1531/9938] i40e: Fix for supported link modes in 10GBaseT PHY's 100baseT/Full is now listed and supported link mode for 10GBaseT PHY. This is a fix to list all the supported link modes of 10GBaseT PHY. Change-ID: If2be3212ef0fef85fd5d6e4550c7783de2f915e9 Signed-off-by: Avinash Dayanand Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 410d237f9137..8a83d4514812 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -313,6 +313,13 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, ecmd->advertising |= ADVERTISED_10000baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) ecmd->advertising |= ADVERTISED_1000baseT_Full; + /* adding 100baseT support for 10GBASET_PHY */ + if (pf->flags & I40E_FLAG_HAVE_10GBASET_PHY) { + ecmd->supported |= SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_10000baseT_Full; + } break; case I40E_PHY_TYPE_1000BASE_T_OPTICAL: ecmd->supported = SUPPORTED_Autoneg | @@ -325,6 +332,15 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, SUPPORTED_100baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) ecmd->advertising |= ADVERTISED_100baseT_Full; + /* firmware detects 10G phy as 100M phy at 100M speed */ + if (pf->flags & I40E_FLAG_HAVE_10GBASET_PHY) { + ecmd->supported |= SUPPORTED_10000baseT_Full | + SUPPORTED_1000baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_10000baseT_Full; + } break; case I40E_PHY_TYPE_10GBASE_CR1_CU: case I40E_PHY_TYPE_10GBASE_CR1: -- GitLab From 18b7af57d9c1165c2b8f13ec4668d6d7f51708cf Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 18 Mar 2016 12:18:14 -0700 Subject: [PATCH 1532/9938] i40e: Lower some message levels These conditions can happen any time VFs are enabled or disabled and are not really indicative of fatal problems unless they happen continuously. Lower the log level so that people don't get scared. Change-ID: I1ceb4adbd10d03cbeed54d1f5b7f20d60328351d Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 169c256fd6ba..9924503c88f5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1232,8 +1232,8 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, /* single place to detect unsuccessful return values */ if (v_retval) { vf->num_invalid_msgs++; - dev_err(&pf->pdev->dev, "VF %d failed opcode %d, error: %d\n", - vf->vf_id, v_opcode, v_retval); + dev_info(&pf->pdev->dev, "VF %d failed opcode %d, retval: %d\n", + vf->vf_id, v_opcode, v_retval); if (vf->num_invalid_msgs > I40E_DEFAULT_NUM_INVALID_MSGS_ALLOWED) { dev_err(&pf->pdev->dev, @@ -1251,9 +1251,9 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, aq_ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval, msg, msglen, NULL); if (aq_ret) { - dev_err(&pf->pdev->dev, - "Unable to send the message to VF %d aq_err %d\n", - vf->vf_id, pf->hw.aq.asq_last_status); + dev_info(&pf->pdev->dev, + "Unable to send the message to VF %d aq_err %d\n", + vf->vf_id, pf->hw.aq.asq_last_status); return -EIO; } -- GitLab From 867a79e37ed9a3a5a2051cc11df21a57a8a00bfe Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 18 Mar 2016 12:18:15 -0700 Subject: [PATCH 1533/9938] i40e: Request PHY media event at reset time Add the Media Not Available flag to the link event mask. It seems that event comes first if you have a DA cable pulled out, but there's no follow-up event for Link Down; if you're not looking for MEDIA_NA you will get no event, even though there's now no Link. Change-ID: cb3340a2849805bb881f64f6f2ae810eef46eba7 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 184f3f965a01..d2c0106fe71e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6859,6 +6859,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) */ ret = i40e_aq_set_phy_int_mask(&pf->hw, ~(I40E_AQ_EVENT_LINK_UPDOWN | + I40E_AQ_EVENT_MEDIA_NA | I40E_AQ_EVENT_MODULE_QUAL_FAIL), NULL); if (ret) dev_info(&pf->pdev->dev, "set phy mask fail, err %s aq_err %s\n", @@ -11070,6 +11071,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ err = i40e_aq_set_phy_int_mask(&pf->hw, ~(I40E_AQ_EVENT_LINK_UPDOWN | + I40E_AQ_EVENT_MEDIA_NA | I40E_AQ_EVENT_MODULE_QUAL_FAIL), NULL); if (err) dev_info(&pf->pdev->dev, "set phy mask fail, err %s aq_err %s\n", -- GitLab From 066439ce791b5d8533556a89836c0849589c2b41 Mon Sep 17 00:00:00 2001 From: Avinash Dayanand Date: Fri, 18 Mar 2016 12:18:16 -0700 Subject: [PATCH 1534/9938] i40e/i40evf: Bump patch from 1.5.1 to 1.5.2 Signed-off-by: Avinash Dayanand Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d2c0106fe71e..d6147f899062 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -46,7 +46,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 5 -#define DRV_VERSION_BUILD 1 +#define DRV_VERSION_BUILD 2 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 2d1fe560cf7d..f4dada02bbcf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -38,7 +38,7 @@ static const char i40evf_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 5 -#define DRV_VERSION_BUILD 1 +#define DRV_VERSION_BUILD 2 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) \ -- GitLab From 24d41e5e2c9afe99b0584832206ba8779dfb783e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 18 Mar 2016 16:06:47 -0700 Subject: [PATCH 1535/9938] i40e/i40evf: Fix TSO checksum pseudo-header adjustment With IPv4 and IPv6 now using the same format for checksums based on the length of the frame we need to update the i40e and i40evf drivers so that they correctly account for lengths greater than or equal to 64K. With this patch the driver should now correctly update checksums for frames up to 16776960 in length which should be more than large enough for all possible TSO frames in the near future. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 11 ++++------- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 5bef5b0f00d9..5d5fa5359a1d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2304,10 +2304,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, l4_offset = l4.hdr - skb->data; /* remove payload length from outer checksum */ - paylen = (__force u16)l4.udp->check; - paylen += ntohs((__force __be16)1) * - (u16)~(skb->len - l4_offset); - l4.udp->check = ~csum_fold((__force __wsum)paylen); + paylen = skb->len - l4_offset; + csum_replace_by_diff(&l4.udp->check, htonl(paylen)); } /* reset pointers to inner headers */ @@ -2327,9 +2325,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, l4_offset = l4.hdr - skb->data; /* remove payload length from inner checksum */ - paylen = (__force u16)l4.tcp->check; - paylen += ntohs((__force __be16)1) * (u16)~(skb->len - l4_offset); - l4.tcp->check = ~csum_fold((__force __wsum)paylen); + paylen = skb->len - l4_offset; + csum_replace_by_diff(&l4.tcp->check, htonl(paylen)); /* compute length of segmentation header */ *hdr_len = (l4.tcp->doff * 4) + l4_offset; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 570348d93e5d..04aabc52ba0d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1571,10 +1571,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, l4_offset = l4.hdr - skb->data; /* remove payload length from outer checksum */ - paylen = (__force u16)l4.udp->check; - paylen += ntohs((__force __be16)1) * - (u16)~(skb->len - l4_offset); - l4.udp->check = ~csum_fold((__force __wsum)paylen); + paylen = skb->len - l4_offset; + csum_replace_by_diff(&l4.udp->check, htonl(paylen)); } /* reset pointers to inner headers */ @@ -1594,9 +1592,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, l4_offset = l4.hdr - skb->data; /* remove payload length from inner checksum */ - paylen = (__force u16)l4.tcp->check; - paylen += ntohs((__force __be16)1) * (u16)~(skb->len - l4_offset); - l4.tcp->check = ~csum_fold((__force __wsum)paylen); + paylen = skb->len - l4_offset; + csum_replace_by_diff(&l4.tcp->check, htonl(paylen)); /* compute length of segmentation header */ *hdr_len = (l4.tcp->doff * 4) + l4_offset; -- GitLab From 4926c8046549cc3c9689e8050e303c016a0b0cba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 4 Apr 2016 11:33:54 +0200 Subject: [PATCH 1536/9938] ALSA: intel8x0: Drop superfluous VM checks intel8x0 driver has the inside_vm check for skipping a buggy hardware workaround in the PCM pointer callback in the commit [228cf79376f1: ALSA: intel8x0: Improve performance in virtual environment]. This was originally applied to all devices on known VMs, but the code was switched to use the PCI ID matching for applying to only known devices (KVM and Parallels), in order to avoid applying wrongly to VT-d and other such cases, in the commit [7fb4f392bd27: ALSA: intel8x0: improve virtual environment detection]. Meanwhile, the original VM check was kept even after switching to the PCI ID matching. It was partly because we weren't 100% sure whether we had covered all well, and partly because this would help identifying the issue once when a user of another VM hit the same problem or a regression. Currently the VM check is used only for showing the kernel message that the VM-optimization isn't applied, and the VM check itself doesn't change the actual driver behavior at all. Despite the relatively safe driver behavior, the code caught attention of developers badly and brought many confusion / misunderstanding. Since we've got neither regression nor enhancement report for other VMs for five years long, it's likely safe to drop this superfluous VM check now. The module option is still kept, so if a user still needs to adjust, it can be applied as was. Acked-by: Konstantin Ozerkov Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 8151318a69a2..9720a30dbfff 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -42,12 +42,6 @@ #include #include -#ifdef CONFIG_KVM_GUEST -#include -#else -#define kvm_para_available() (0) -#endif - MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); MODULE_LICENSE("GPL"); @@ -2972,25 +2966,17 @@ static int snd_intel8x0_inside_vm(struct pci_dev *pci) goto fini; } - /* detect KVM and Parallels virtual environments */ - result = kvm_para_available(); -#ifdef X86_FEATURE_HYPERVISOR - result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR); -#endif - if (!result) - goto fini; - /* check for known (emulated) devices */ + result = 0; if (pci->subsystem_vendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && pci->subsystem_device == PCI_SUBDEVICE_ID_QEMU) { /* KVM emulated sound, PCI SSID: 1af4:1100 */ msg = "enable KVM"; + result = 1; } else if (pci->subsystem_vendor == 0x1ab8) { /* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */ msg = "enable Parallels VM"; - } else { - msg = "disable (unknown or VT-d) VM"; - result = 0; + result = 1; } fini: -- GitLab From 5d3927f655e58e644557a3dc8ee7af8884f59931 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 30 Mar 2016 16:58:18 +0200 Subject: [PATCH 1537/9938] clk: renesas: cpg-mssr: add generic support for read-only DIV6 clocks Gen3 has two clocks (OSC and R) which look like a DIV6 clock but their divider value is read-only and depends on MD pins at bootup. Add support for such clocks by reading the value and adding a fixed clock. Signed-off-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 18 ++++++++++++------ drivers/clk/renesas/renesas-cpg-mssr.h | 3 +++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 58e24b326a48..3e4d2609cc02 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -253,7 +253,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, { struct clk *clk = NULL, *parent; struct device *dev = priv->dev; - unsigned int id = core->id; + unsigned int id = core->id, div = core->div; const char *parent_name; WARN_DEBUG(id >= priv->num_core_clks); @@ -266,6 +266,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, case CLK_TYPE_FF: case CLK_TYPE_DIV6P1: + case CLK_TYPE_DIV6_RO: WARN_DEBUG(core->parent >= priv->num_core_clks); parent = priv->clks[core->parent]; if (IS_ERR(parent)) { @@ -274,13 +275,18 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, } parent_name = __clk_get_name(parent); - if (core->type == CLK_TYPE_FF) { - clk = clk_register_fixed_factor(NULL, core->name, - parent_name, 0, - core->mult, core->div); - } else { + + if (core->type == CLK_TYPE_DIV6_RO) + /* Multiply with the DIV6 register value */ + div *= (readl(priv->base + core->offset) & 0x3f) + 1; + + if (core->type == CLK_TYPE_DIV6P1) { clk = cpg_div6_register(core->name, 1, &parent_name, priv->base + core->offset); + } else { + clk = clk_register_fixed_factor(NULL, core->name, + parent_name, 0, + core->mult, div); } break; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index cad3c7d1b0c6..0d1e3e811e79 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -37,6 +37,7 @@ enum clk_types { CLK_TYPE_IN, /* External Clock Input */ CLK_TYPE_FF, /* Fixed Factor Clock */ CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */ + CLK_TYPE_DIV6_RO, /* DIV6 Clock read only with extra divisor */ /* Custom definitions start here */ CLK_TYPE_CUSTOM, @@ -53,6 +54,8 @@ enum clk_types { DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) #define DEF_DIV6P1(_name, _id, _parent, _offset) \ DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset) +#define DEF_DIV6_RO(_name, _id, _parent, _offset, _div) \ + DEF_BASE(_name, _id, CLK_TYPE_DIV6_RO, _parent, .offset = _offset, .div = _div, .mult = 1) /* * Definitions of Module Clocks -- GitLab From 5524a67f3a4ad8625cab6a9b99419f747cea4c71 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 30 Mar 2016 16:58:19 +0200 Subject: [PATCH 1538/9938] clk: renesas: r8a7795: add OSC and RINT clocks Signed-off-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 9dc2b735ead8..08715ca2ebb4 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -26,6 +26,7 @@ #include "renesas-cpg-mssr.h" +#define CPG_RCKCR 0x240 enum clk_ids { /* Core Clock Outputs exported to DT */ @@ -50,6 +51,7 @@ enum clk_ids { CLK_S3, CLK_SDSRC, CLK_SSPSRC, + CLK_RINT, /* Module Clocks */ MOD_CLK_BASE @@ -116,6 +118,9 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244), + + DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), + DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), }; static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { -- GitLab From 1e6237e32ef4bf4104a8ef14cece60541e11e14d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 30 Mar 2016 16:58:20 +0200 Subject: [PATCH 1539/9938] clk: renesas: r8a7795: add R clk R can select between two parents. We deal with it like this: During initialization, check if EXTALR is populated. If so, use it for R. If not, use R_Internal. clk_mux doesn't help here because we don't want to switch parents depending on the clock rate. The clock rate (and source) should stay constant for the watchdog, so I think a setup like this during initialization makes sense. Signed-off-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 08715ca2ebb4..19b026457718 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -65,6 +66,7 @@ enum r8a7795_clk_types { CLK_TYPE_GEN3_PLL3, CLK_TYPE_GEN3_PLL4, CLK_TYPE_GEN3_SD, + CLK_TYPE_GEN3_R, }; #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ @@ -121,6 +123,8 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), + + DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), }; static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { @@ -587,6 +591,18 @@ struct clk * __init r8a7795_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_SD: return cpg_sd_clk_register(core, base, __clk_get_name(parent)); + case CLK_TYPE_GEN3_R: + /* RINT is default. Only if EXTALR is populated, we switch to it */ + value = readl(base + CPG_RCKCR) & 0x3f; + + if (clk_get_rate(clks[CLK_EXTALR])) { + parent = clks[CLK_EXTALR]; + value |= BIT(15); + } + + writel(value, base + CPG_RCKCR); + break; + default: return ERR_PTR(-EINVAL); } -- GitLab From 6248620b30403bcbe3ef308499026226e999597c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 30 Mar 2016 16:58:21 +0200 Subject: [PATCH 1540/9938] clk: renesas: r8a7795: add RWDT clock Signed-off-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 19b026457718..6af7f5b6e824 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -151,6 +151,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1), DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1), DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1), + DEF_MOD("rwdt0", 402, R8A7795_CLK_R), DEF_MOD("intc-ex", 407, R8A7795_CLK_CP), DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), -- GitLab From 4aba2755b8e8abbe29a12d18523d97c27bf53183 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Sat, 2 Apr 2016 18:25:45 +0200 Subject: [PATCH 1541/9938] clk: imx: add ckil clock for i.MX7 Add the necessary clock to use the ckil on i.MX7. Inspired from the following patch: https://github.com/boundarydevices/linux-imx6/commit/b80e8271 Signed-off-by: Troy Kisky Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx7d.c | 3 ++- include/dt-bindings/clock/imx7d-clock.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index fbb6a8c8653d..7912be83c4af 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -342,7 +342,7 @@ static const char *clko1_sel[] = { "osc", "pll_sys_main_clk", static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk", - "pll_audio_main_clk", "pll_video_main_clk", "osc_32k_clk", }; + "pll_audio_main_clk", "pll_video_main_clk", "ckil", }; static const char *lvds1_sel[] = { "pll_arm_main_clk", "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk", @@ -382,6 +382,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0); clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc"); + clks[IMX7D_CKIL] = of_clk_get_by_name(ccm_node, "ckil"); np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop"); base = of_iomap(np, 0); diff --git a/include/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h index edca8985c50e..1183347c383f 100644 --- a/include/dt-bindings/clock/imx7d-clock.h +++ b/include/dt-bindings/clock/imx7d-clock.h @@ -448,5 +448,6 @@ #define IMX7D_PLL_DRAM_TEST_DIV 435 #define IMX7D_ADC_ROOT_CLK 436 #define IMX7D_CLK_ARM 437 -#define IMX7D_CLK_END 438 +#define IMX7D_CKIL 438 +#define IMX7D_CLK_END 439 #endif /* __DT_BINDINGS_CLOCK_IMX7D_H */ -- GitLab From 2b2fe36def086f0b721be2f34223cf662dd87902 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Mon, 28 Mar 2016 14:53:16 +0800 Subject: [PATCH 1542/9938] usb: chipidea: imx: delete the redundant setting default DMA mask code For each platform devices which is created by device tree, the default DMA mask is set by of_dma_configure when the device are created. So delete the redundant code at driver. Signed-off-by: Peter Chen --- drivers/usb/chipidea/ci_hdrc_imx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 9ce8c9f91674..dedc33e589f4 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -292,10 +292,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM) data->supports_runtime_pm = true; - ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (ret) - goto err_clk; - ret = imx_usbmisc_init(data->usbmisc_data); if (ret) { dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret); -- GitLab From fa59507f720077a856c9952a31cfd45cd97ef6f9 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 30 Mar 2016 12:56:28 +0300 Subject: [PATCH 1543/9938] usb: otg-fsm: Add documentation for struct otg_fsm struct otg_fsm is the interface to the OTG state machine. Document the input, output and internal state variables. Definations are taken from Table 7-2 and Table 7-4 of the USB OTG & EH Specification Rev.2.0 Re-arrange some of the members as per use case for more clarity. Signed-off-by: Roger Quadros Acked-by: Peter Chen Signed-off-by: Peter Chen --- include/linux/usb/otg-fsm.h | 90 ++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h index 24198e16f849..8eec0c261be5 100644 --- a/include/linux/usb/otg-fsm.h +++ b/include/linux/usb/otg-fsm.h @@ -72,37 +72,113 @@ enum otg_fsm_timer { NUM_OTG_FSM_TIMERS, }; -/* OTG state machine according to the OTG spec */ +/** + * struct otg_fsm - OTG state machine according to the OTG spec + * + * OTG hardware Inputs + * + * Common inputs for A and B device + * @id: TRUE for B-device, FALSE for A-device. + * @adp_change: TRUE when current ADP measurement (n) value, compared to the + * ADP measurement taken at n-2, differs by more than CADP_THR + * @power_up: TRUE when the OTG device first powers up its USB system and + * ADP measurement taken if ADP capable + * + * A-Device state inputs + * @a_srp_det: TRUE if the A-device detects SRP + * @a_vbus_vld: TRUE when VBUS voltage is in regulation + * @b_conn: TRUE if the A-device detects connection from the B-device + * @a_bus_resume: TRUE when the B-device detects that the A-device is signaling + * a resume (K state) + * B-Device state inputs + * @a_bus_suspend: TRUE when the B-device detects that the A-device has put the + * bus into suspend + * @a_conn: TRUE if the B-device detects a connection from the A-device + * @b_se0_srp: TRUE when the line has been at SE0 for more than the minimum + * time before generating SRP + * @b_ssend_srp: TRUE when the VBUS has been below VOTG_SESS_VLD for more than + * the minimum time before generating SRP + * @b_sess_vld: TRUE when the B-device detects that the voltage on VBUS is + * above VOTG_SESS_VLD + * @test_device: TRUE when the B-device switches to B-Host and detects an OTG + * test device. This must be set by host/hub driver + * + * Application inputs (A-Device) + * @a_bus_drop: TRUE when A-device application needs to power down the bus + * @a_bus_req: TRUE when A-device application wants to use the bus. + * FALSE to suspend the bus + * + * Application inputs (B-Device) + * @b_bus_req: TRUE during the time that the Application running on the + * B-device wants to use the bus + * + * Auxilary inputs (OTG v1.3 only. Obsolete now.) + * @a_sess_vld: TRUE if the A-device detects that VBUS is above VA_SESS_VLD + * @b_bus_suspend: TRUE when the A-device detects that the B-device has put + * the bus into suspend + * @b_bus_resume: TRUE when the A-device detects that the B-device is signaling + * resume on the bus + * + * OTG Output status. Read only for users. Updated by OTG FSM helpers defined + * in this file + * + * Outputs for Both A and B device + * @drv_vbus: TRUE when A-device is driving VBUS + * @loc_conn: TRUE when the local device has signaled that it is connected + * to the bus + * @loc_sof: TRUE when the local device is generating activity on the bus + * @adp_prb: TRUE when the local device is in the process of doing + * ADP probing + * + * Outputs for B-device state + * @adp_sns: TRUE when the B-device is in the process of carrying out + * ADP sensing + * @data_pulse: TRUE when the B-device is performing data line pulsing + * + * Internal Variables + * + * a_set_b_hnp_en: TRUE when the A-device has successfully set the + * b_hnp_enable bit in the B-device. + * Unused as OTG fsm uses otg->host->b_hnp_enable instead + * b_srp_done: TRUE when the B-device has completed initiating SRP + * b_hnp_enable: TRUE when the B-device has accepted the + * SetFeature(b_hnp_enable) B-device. + * Unused as OTG fsm uses otg->gadget->b_hnp_enable instead + * a_clr_err: Asserted (by application ?) to clear a_vbus_err due to an + * overcurrent condition and causes the A-device to transition + * to a_wait_vfall + */ struct otg_fsm { /* Input */ int id; int adp_change; int power_up; - int test_device; - int a_bus_drop; - int a_bus_req; int a_srp_det; int a_vbus_vld; int b_conn; int a_bus_resume; int a_bus_suspend; int a_conn; - int b_bus_req; int b_se0_srp; int b_ssend_srp; int b_sess_vld; + int test_device; + int a_bus_drop; + int a_bus_req; + int b_bus_req; + /* Auxilary inputs */ int a_sess_vld; int b_bus_resume; int b_bus_suspend; /* Output */ - int data_pulse; int drv_vbus; int loc_conn; int loc_sof; int adp_prb; int adp_sns; + int data_pulse; /* Internal variables */ int a_set_b_hnp_en; @@ -110,7 +186,7 @@ struct otg_fsm { int b_hnp_enable; int a_clr_err; - /* Informative variables */ + /* Informative variables. All unused as of now */ int a_bus_drop_inf; int a_bus_req_inf; int a_clr_err_inf; -- GitLab From 4e332df63487418ec512c3c376c07df9ab3ae035 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 30 Mar 2016 12:56:29 +0300 Subject: [PATCH 1544/9938] usb: otg-fsm: support multiple instances Move the state_changed variable into struct otg_fsm so that we can support multiple instances. Signed-off-by: Roger Quadros Acked-by: Peter Chen Signed-off-by: Peter Chen --- drivers/usb/common/usb-otg-fsm.c | 10 ++++------ include/linux/usb/otg-fsm.h | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c index 504708f59b93..9059b7dc185e 100644 --- a/drivers/usb/common/usb-otg-fsm.c +++ b/drivers/usb/common/usb-otg-fsm.c @@ -61,8 +61,6 @@ static int otg_set_protocol(struct otg_fsm *fsm, int protocol) return 0; } -static int state_changed; - /* Called when leaving a state. Do state clean up jobs here */ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state) { @@ -208,7 +206,6 @@ static void otg_start_hnp_polling(struct otg_fsm *fsm) /* Called when entering a state */ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) { - state_changed = 1; if (fsm->otg->state == new_state) return 0; VDBG("Set state: %s\n", usb_otg_state_string(new_state)); @@ -324,6 +321,7 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) } fsm->otg->state = new_state; + fsm->state_changed = 1; return 0; } @@ -335,7 +333,7 @@ int otg_statemachine(struct otg_fsm *fsm) mutex_lock(&fsm->lock); state = fsm->otg->state; - state_changed = 0; + fsm->state_changed = 0; /* State machine state change judgement */ switch (state) { @@ -448,7 +446,7 @@ int otg_statemachine(struct otg_fsm *fsm) } mutex_unlock(&fsm->lock); - VDBG("quit statemachine, changed = %d\n", state_changed); - return state_changed; + VDBG("quit statemachine, changed = %d\n", fsm->state_changed); + return fsm->state_changed; } EXPORT_SYMBOL_GPL(otg_statemachine); diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h index 8eec0c261be5..7a0350535cb1 100644 --- a/include/linux/usb/otg-fsm.h +++ b/include/linux/usb/otg-fsm.h @@ -210,6 +210,7 @@ struct otg_fsm { struct mutex lock; u8 *host_req_flag; struct delayed_work hnp_polling_work; + bool state_changed; }; struct otg_fsm_ops { -- GitLab From d63b548fffdbd239a5e65bb89424be19229048ba Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:02 +0300 Subject: [PATCH 1545/9938] mac80211: allow passing transmitter station on RX Sometimes drivers already looked up, or know out-of-band from their device, which station transmitted a given RX frame. Allow them to pass the station pointer to mac80211 to save the extra lookup. Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 +- include/net/mac80211.h | 7 ++++--- net/mac80211/rx.c | 18 +++++++++++++----- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 52ab1e012e8f..27ea61e3a390 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -686,7 +686,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); - ieee80211_rx_napi(priv->hw, skb, priv->napi); + ieee80211_rx_napi(priv->hw, NULL, skb, priv->napi); } static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index e885db3464b0..fba1cd2ce1ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1499,5 +1499,5 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); /* pass it as regular rx to mac80211 */ - ieee80211_rx_napi(mvm->hw, skb, NULL); + ieee80211_rx_napi(mvm->hw, NULL, skb, NULL); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 485cfc1a4daa..d8cadf2fe098 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -131,7 +131,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, fraglen, rxb->truesize); } - ieee80211_rx_napi(mvm->hw, skb, napi); + ieee80211_rx_napi(mvm->hw, NULL, skb, napi); } /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 9a54f2d2a66b..38e7fa9bd675 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -210,7 +210,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, if (iwl_mvm_check_pn(mvm, skb, queue, sta)) kfree_skb(skb); else - ieee80211_rx_napi(mvm->hw, skb, napi); + ieee80211_rx_napi(mvm->hw, NULL, skb, napi); } static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 6e346750cb29..fd5ec446a7a9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3855,11 +3855,12 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw); * This function must be called with BHs disabled. * * @hw: the hardware this frame came in on + * @sta: the station the frame was received from, or %NULL * @skb: the buffer to receive, owned by mac80211 after this call * @napi: the NAPI context */ -void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb, - struct napi_struct *napi); +void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + struct sk_buff *skb, struct napi_struct *napi); /** * ieee80211_rx - receive frame @@ -3883,7 +3884,7 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb, */ static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) { - ieee80211_rx_napi(hw, skb, NULL); + ieee80211_rx_napi(hw, NULL, skb, NULL); } /** diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 009bb90d7f5a..212b9993c8dc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3552,6 +3552,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, * be called with rcu_read_lock protection. */ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + struct ieee80211_sta *pubsta, struct sk_buff *skb, struct napi_struct *napi) { @@ -3561,7 +3562,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, __le16 fc; struct ieee80211_rx_data rx; struct ieee80211_sub_if_data *prev; - struct sta_info *sta, *prev_sta; struct rhash_head *tmp; int err = 0; @@ -3597,7 +3597,14 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, ieee80211_is_beacon(hdr->frame_control))) ieee80211_scan_rx(local, skb); - if (ieee80211_is_data(fc)) { + if (pubsta) { + rx.sta = container_of(pubsta, struct sta_info, sta); + rx.sdata = rx.sta->sdata; + if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) + return; + goto out; + } else if (ieee80211_is_data(fc)) { + struct sta_info *sta, *prev_sta; const struct bucket_table *tbl; prev_sta = NULL; @@ -3671,8 +3678,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, * This is the receive path handler. It is called by a low level driver when an * 802.11 MPDU is received from the hardware. */ -void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb, - struct napi_struct *napi) +void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + struct sk_buff *skb, struct napi_struct *napi) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate = NULL; @@ -3771,7 +3778,8 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb, ieee80211_tpt_led_trig_rx(local, ((struct ieee80211_hdr *)skb->data)->frame_control, skb->len); - __ieee80211_rx_handle_packet(hw, skb, napi); + + __ieee80211_rx_handle_packet(hw, pubsta, skb, napi); rcu_read_unlock(); -- GitLab From de8f18d3a80bee94ee8a2d3c511707390dad88d6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:03 +0300 Subject: [PATCH 1546/9938] mac80211: count MSDUs in A-MSDU properly For the RX MSDU statistics, we need to count the number of MSDUs created and accepted from an A-MSDU. Right now, all frames in any A-MSDUs were completely ignored. Fix this by moving the RX MSDU statistics accounting into the deliver function. Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 212b9993c8dc..a94d314d0055 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2129,6 +2129,15 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) ieee80211_rx_stats(dev, skb->len); + if (rx->sta) { + /* The seqno index has the same property as needed + * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS + * for non-QoS-data frames. Here we know it's a data + * frame, so count MSDUs. + */ + rx->sta->rx_stats.msdu[rx->seqno_idx]++; + } + if ((sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && @@ -2415,15 +2424,6 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) return RX_DROP_MONITOR; - if (rx->sta) { - /* The seqno index has the same property as needed - * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS - * for non-QoS-data frames. Here we know it's a data - * frame, so count MSDUs. - */ - rx->sta->rx_stats.msdu[rx->seqno_idx]++; - } - /* * Send unexpected-4addr-frame event to hostapd. For older versions, * also drop the frame to cooked monitor interfaces. -- GitLab From 8ebaa5b0a791631dddbb3a215b342fabb2a5307b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:04 +0300 Subject: [PATCH 1547/9938] mac80211: move semicolon out of CALL_RXH macro Move the semicolon, people typically assume that and once line already put a semicolon behind the "call". Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a94d314d0055..570ae3d03ae1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3201,7 +3201,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, res = rxh(rx); \ if (res != RX_CONTINUE) \ goto rxh_next; \ - } while (0); + } while (0) /* Lock here to avoid hitting all of the data used in the RX * path (e.g. key data, station data, ...) concurrently when @@ -3219,30 +3219,30 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, */ rx->skb = skb; - CALL_RXH(ieee80211_rx_h_check_more_data) - CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll) - CALL_RXH(ieee80211_rx_h_sta_process) - CALL_RXH(ieee80211_rx_h_decrypt) - CALL_RXH(ieee80211_rx_h_defragment) - CALL_RXH(ieee80211_rx_h_michael_mic_verify) + CALL_RXH(ieee80211_rx_h_check_more_data); + CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll); + CALL_RXH(ieee80211_rx_h_sta_process); + CALL_RXH(ieee80211_rx_h_decrypt); + CALL_RXH(ieee80211_rx_h_defragment); + CALL_RXH(ieee80211_rx_h_michael_mic_verify); /* must be after MMIC verify so header is counted in MPDU mic */ #ifdef CONFIG_MAC80211_MESH if (ieee80211_vif_is_mesh(&rx->sdata->vif)) CALL_RXH(ieee80211_rx_h_mesh_fwding); #endif - CALL_RXH(ieee80211_rx_h_amsdu) - CALL_RXH(ieee80211_rx_h_data) + CALL_RXH(ieee80211_rx_h_amsdu); + CALL_RXH(ieee80211_rx_h_data); /* special treatment -- needs the queue */ res = ieee80211_rx_h_ctrl(rx, frames); if (res != RX_CONTINUE) goto rxh_next; - CALL_RXH(ieee80211_rx_h_mgmt_check) - CALL_RXH(ieee80211_rx_h_action) - CALL_RXH(ieee80211_rx_h_userspace_mgmt) - CALL_RXH(ieee80211_rx_h_action_return) - CALL_RXH(ieee80211_rx_h_mgmt) + CALL_RXH(ieee80211_rx_h_mgmt_check); + CALL_RXH(ieee80211_rx_h_action); + CALL_RXH(ieee80211_rx_h_userspace_mgmt); + CALL_RXH(ieee80211_rx_h_action_return); + CALL_RXH(ieee80211_rx_h_mgmt); rxh_next: ieee80211_rx_handlers_result(rx, res); @@ -3265,10 +3265,10 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) res = rxh(rx); \ if (res != RX_CONTINUE) \ goto rxh_next; \ - } while (0); + } while (0) - CALL_RXH(ieee80211_rx_h_check_dup) - CALL_RXH(ieee80211_rx_h_check) + CALL_RXH(ieee80211_rx_h_check_dup); + CALL_RXH(ieee80211_rx_h_check); ieee80211_rx_reorder_ampdu(rx, &reorder_release); -- GitLab From 0be6ed133835b1a5e492f86099ce372b5a2e2296 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:05 +0300 Subject: [PATCH 1548/9938] mac80211: move averaged values out of rx_stats Move the averaged values out of rx_stats and into rx_stats_avg, to cleanly split them out. The averaged ones cannot be supported for parallel RX in a per-CPU fashion, while the other values can be collected per CPU and then combined/selected when needed. Signed-off-by: Johannes Berg --- net/mac80211/mesh_plink.c | 2 +- net/mac80211/rx.c | 4 ++-- net/mac80211/sta_info.c | 10 +++++----- net/mac80211/sta_info.h | 6 ++++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index ecfba8ad29e4..563bea050383 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -61,7 +61,7 @@ static bool rssi_threshold_check(struct ieee80211_sub_if_data *sdata, s32 rssi_threshold = sdata->u.mesh.mshcfg.rssi_threshold; return rssi_threshold == 0 || (sta && - (s8)-ewma_signal_read(&sta->rx_stats.avg_signal) > + (s8)-ewma_signal_read(&sta->rx_stats_avg.signal) > rssi_threshold); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 570ae3d03ae1..d14c66df9e86 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1455,7 +1455,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) sta->rx_stats.bytes += rx->skb->len; if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { sta->rx_stats.last_signal = status->signal; - ewma_signal_add(&sta->rx_stats.avg_signal, -status->signal); + ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal); } if (status->chains) { @@ -1467,7 +1467,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) continue; sta->rx_stats.chain_signal_last[i] = signal; - ewma_signal_add(&sta->rx_stats.chain_signal_avg[i], + ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], -signal); } } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 01e070c6e713..4f19505f3757 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -341,9 +341,9 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->reserved_tid = IEEE80211_TID_UNRESERVED; sta->last_connected = ktime_get_seconds(); - ewma_signal_init(&sta->rx_stats.avg_signal); - for (i = 0; i < ARRAY_SIZE(sta->rx_stats.chain_signal_avg); i++) - ewma_signal_init(&sta->rx_stats.chain_signal_avg[i]); + ewma_signal_init(&sta->rx_stats_avg.signal); + for (i = 0; i < ARRAY_SIZE(sta->rx_stats_avg.chain_signal); i++) + ewma_signal_init(&sta->rx_stats_avg.chain_signal[i]); if (local->ops->wake_tx_queue) { void *txq_data; @@ -2056,7 +2056,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { sinfo->signal_avg = - -ewma_signal_read(&sta->rx_stats.avg_signal); + -ewma_signal_read(&sta->rx_stats_avg.signal); sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); } } @@ -2072,7 +2072,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->chain_signal[i] = sta->rx_stats.chain_signal_last[i]; sinfo->chain_signal_avg[i] = - -ewma_signal_read(&sta->rx_stats.chain_signal_avg[i]); + -ewma_signal_read(&sta->rx_stats_avg.chain_signal[i]); } } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4e1ed6f26484..93dc567e6100 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -450,16 +450,18 @@ struct sta_info { unsigned long fragments; unsigned long dropped; int last_signal; - struct ewma_signal avg_signal; u8 chains; s8 chain_signal_last[IEEE80211_MAX_CHAINS]; - struct ewma_signal chain_signal_avg[IEEE80211_MAX_CHAINS]; int last_rate_idx; u32 last_rate_flag; u32 last_rate_vht_flag; u8 last_rate_vht_nss; u64 msdu[IEEE80211_NUM_TIDS + 1]; } rx_stats; + struct { + struct ewma_signal signal; + struct ewma_signal chain_signal[IEEE80211_MAX_CHAINS]; + } rx_stats_avg; /* Plus 1 for non-QoS frames */ __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; -- GitLab From 2df8bfd7240117b91241a01e3f50f2e83827ccab Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:06 +0300 Subject: [PATCH 1549/9938] mac80211: remove rx_stats.last_rx update after sta alloc There's no need to update rx_stats.last_rx after allocating a station since it's already updated during allocation. Signed-off-by: Johannes Berg --- net/mac80211/ibss.c | 4 ---- net/mac80211/ocb.c | 2 -- 2 files changed, 6 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index fc3238376b39..b3407dbe4b7d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -649,8 +649,6 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, return NULL; } - sta->rx_stats.last_rx = jiffies; - /* make sure mandatory rates are always added */ sband = local->hw.wiphy->bands[band]; sta->sta.supp_rates[band] = supp_rates | @@ -1236,8 +1234,6 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, if (!sta) return; - sta->rx_stats.last_rx = jiffies; - /* make sure mandatory rates are always added */ sband = local->hw.wiphy->bands[band]; sta->sta.supp_rates[band] = supp_rates | diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c index 0be0aadfc559..88e6ebbbe24f 100644 --- a/net/mac80211/ocb.c +++ b/net/mac80211/ocb.c @@ -75,8 +75,6 @@ void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata, if (!sta) return; - sta->rx_stats.last_rx = jiffies; - /* Add only mandatory rates for now */ sband = local->hw.wiphy->bands[band]; sta->sta.supp_rates[band] = -- GitLab From b8da6b6a99b4b0d8d464b621ba7dcbcb08172b7d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:07 +0300 Subject: [PATCH 1550/9938] mac80211: add separate last_ack variable Instead of touching the rx_stats.last_rx from the status path, introduce and use a status_stats.last_ack variable. This will make rx_stats.last_rx indicate when the last frame was received, making it available for real "last_rx" and statistics gathering; statistics, when done per-CPU, will need to figure out which place was updated last for those items where the "last" value is exposed. Signed-off-by: Johannes Berg --- net/mac80211/ibss.c | 13 ++++++++----- net/mac80211/sta_info.c | 13 +++++++++++-- net/mac80211/sta_info.h | 3 +++ net/mac80211/status.c | 4 ++-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b3407dbe4b7d..c6d4b75eb60b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -668,10 +668,11 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) rcu_read_lock(); list_for_each_entry_rcu(sta, &local->sta_list, list) { + unsigned long last_active = ieee80211_sta_last_active(sta); + if (sta->sdata == sdata && - time_after(sta->rx_stats.last_rx + - IEEE80211_IBSS_MERGE_INTERVAL, - jiffies)) { + time_is_after_jiffies(last_active + + IEEE80211_IBSS_MERGE_INTERVAL)) { active++; break; } @@ -1255,11 +1256,13 @@ static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) mutex_lock(&local->sta_mtx); list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { + unsigned long last_active = ieee80211_sta_last_active(sta); + if (sdata != sta->sdata) continue; - if (time_after(jiffies, sta->rx_stats.last_rx + exp_time) || - (time_after(jiffies, sta->rx_stats.last_rx + exp_rsn) && + if (time_is_before_jiffies(last_active + exp_time) || + (time_is_before_jiffies(last_active + exp_rsn) && sta->sta_state != IEEE80211_STA_AUTHORIZED)) { sta_dbg(sta->sdata, "expiring inactive %sSTA %pM\n", sta->sta_state != IEEE80211_STA_AUTHORIZED ? diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4f19505f3757..ac73b9c7e8d8 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1094,10 +1094,12 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->sta_mtx); list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { + unsigned long last_active = ieee80211_sta_last_active(sta); + if (sdata != sta->sdata) continue; - if (time_after(jiffies, sta->rx_stats.last_rx + exp_time)) { + if (time_is_before_jiffies(last_active + exp_time)) { sta_dbg(sta->sdata, "expiring inactive STA %pM\n", sta->sta.addr); @@ -2000,7 +2002,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->connected_time = ktime_get_seconds() - sta->last_connected; sinfo->inactive_time = - jiffies_to_msecs(jiffies - sta->rx_stats.last_rx); + jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta)); if (!(sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES64) | BIT(NL80211_STA_INFO_TX_BYTES)))) { @@ -2186,3 +2188,10 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->expected_throughput = thr; } } + +unsigned long ieee80211_sta_last_active(struct sta_info *sta) +{ + if (time_after(sta->rx_stats.last_rx, sta->status_stats.last_ack)) + return sta->rx_stats.last_rx; + return sta->status_stats.last_ack; +} diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 93dc567e6100..8a8e84bfe3d2 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -474,6 +474,7 @@ struct sta_info { unsigned long last_tdls_pkt_time; u64 msdu_retries[IEEE80211_NUM_TIDS + 1]; u64 msdu_failed[IEEE80211_NUM_TIDS + 1]; + unsigned long last_ack; } status_stats; /* Updated from TX path only, no locking requirements */ @@ -680,4 +681,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); +unsigned long ieee80211_sta_last_active(struct sta_info *sta); + #endif /* STA_INFO_H */ diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 8b1b2ea03eb5..c6d5c724e032 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -188,7 +188,7 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) struct ieee80211_sub_if_data *sdata = sta->sdata; if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) - sta->rx_stats.last_rx = jiffies; + sta->status_stats.last_ack = jiffies; if (ieee80211_is_data_qos(mgmt->frame_control)) { struct ieee80211_hdr *hdr = (void *) skb->data; @@ -647,7 +647,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, sta->status_stats.retry_count += retry_count; if (acked) { - sta->rx_stats.last_rx = jiffies; + sta->status_stats.last_ack = jiffies; if (sta->status_stats.lost_packets) sta->status_stats.lost_packets = 0; -- GitLab From 4f6b1b3daaf167bf927174224e07efd17ed95984 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:08 +0300 Subject: [PATCH 1551/9938] mac80211: fix last RX rate data consistency When storing the last_rate_* values in the RX code, there's nothing to guarantee consistency, so a concurrent reader could see, e.g. last_rate_idx on the new value, but last_rate_flag still on the old, getting completely bogus values in the end. To fix this, I lifted the sta_stats_encode_rate() function from my old rate statistics code, which encodes the entire rate data into a single 16-bit value, avoiding the consistency issue. Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 21 ++++----------- net/mac80211/sta_info.c | 60 ++++++++++++++++++++++------------------- net/mac80211/sta_info.h | 45 +++++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 49 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d14c66df9e86..5a6c36c3aed6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1421,16 +1421,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { sta->rx_stats.last_rx = jiffies; if (ieee80211_is_data(hdr->frame_control) && - !is_multicast_ether_addr(hdr->addr1)) { - sta->rx_stats.last_rate_idx = - status->rate_idx; - sta->rx_stats.last_rate_flag = - status->flag; - sta->rx_stats.last_rate_vht_flag = - status->vht_flag; - sta->rx_stats.last_rate_vht_nss = - status->vht_nss; - } + !is_multicast_ether_addr(hdr->addr1)) + sta->rx_stats.last_rate = + sta_stats_encode_rate(status); } } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) { sta->rx_stats.last_rx = jiffies; @@ -1440,12 +1433,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) * match the current local configuration when processed. */ sta->rx_stats.last_rx = jiffies; - if (ieee80211_is_data(hdr->frame_control)) { - sta->rx_stats.last_rate_idx = status->rate_idx; - sta->rx_stats.last_rate_flag = status->flag; - sta->rx_stats.last_rate_vht_flag = status->vht_flag; - sta->rx_stats.last_rate_vht_nss = status->vht_nss; - } + if (ieee80211_is_data(hdr->frame_control)) + sta->rx_stats.last_rate = sta_stats_encode_rate(status); } if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ac73b9c7e8d8..0b50ae3f0b05 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1928,43 +1928,47 @@ u8 sta_info_tx_streams(struct sta_info *sta) >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; } -static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) +static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, + struct rate_info *rinfo) { - rinfo->flags = 0; - - if (sta->rx_stats.last_rate_flag & RX_FLAG_HT) { - rinfo->flags |= RATE_INFO_FLAGS_MCS; - rinfo->mcs = sta->rx_stats.last_rate_idx; - } else if (sta->rx_stats.last_rate_flag & RX_FLAG_VHT) { - rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; - rinfo->nss = sta->rx_stats.last_rate_vht_nss; - rinfo->mcs = sta->rx_stats.last_rate_idx; - } else { + rinfo->bw = (rate & STA_STATS_RATE_BW_MASK) >> + STA_STATS_RATE_BW_SHIFT; + + if (rate & STA_STATS_RATE_VHT) { + rinfo->flags = RATE_INFO_FLAGS_VHT_MCS; + rinfo->mcs = rate & 0xf; + rinfo->nss = (rate & 0xf0) >> 4; + } else if (rate & STA_STATS_RATE_HT) { + rinfo->flags = RATE_INFO_FLAGS_MCS; + rinfo->mcs = rate & 0xff; + } else if (rate & STA_STATS_RATE_LEGACY) { struct ieee80211_supported_band *sband; - int shift = ieee80211_vif_get_shift(&sta->sdata->vif); u16 brate; - - sband = sta->local->hw.wiphy->bands[ - ieee80211_get_sdata_band(sta->sdata)]; - brate = sband->bitrates[sta->rx_stats.last_rate_idx].bitrate; + unsigned int shift; + + sband = local->hw.wiphy->bands[(rate >> 4) & 0xf]; + brate = sband->bitrates[rate & 0xf].bitrate; + if (rinfo->bw == RATE_INFO_BW_5) + shift = 2; + else if (rinfo->bw == RATE_INFO_BW_10) + shift = 1; + else + shift = 0; rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); } - if (sta->rx_stats.last_rate_flag & RX_FLAG_SHORT_GI) + if (rate & STA_STATS_RATE_SGI) rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; +} + +static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) +{ + u16 rate = ACCESS_ONCE(sta->rx_stats.last_rate); - if (sta->rx_stats.last_rate_flag & RX_FLAG_5MHZ) - rinfo->bw = RATE_INFO_BW_5; - else if (sta->rx_stats.last_rate_flag & RX_FLAG_10MHZ) - rinfo->bw = RATE_INFO_BW_10; - else if (sta->rx_stats.last_rate_flag & RX_FLAG_40MHZ) - rinfo->bw = RATE_INFO_BW_40; - else if (sta->rx_stats.last_rate_vht_flag & RX_VHT_FLAG_80MHZ) - rinfo->bw = RATE_INFO_BW_80; - else if (sta->rx_stats.last_rate_vht_flag & RX_VHT_FLAG_160MHZ) - rinfo->bw = RATE_INFO_BW_160; + if (rate == STA_STATS_RATE_INVALID) + rinfo->flags = 0; else - rinfo->bw = RATE_INFO_BW_20; + sta_stats_decode_rate(sta->local, rate, rinfo); } void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 8a8e84bfe3d2..5549ceb9cbb3 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -1,7 +1,7 @@ /* * Copyright 2002-2005, Devicescape Software, Inc. * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015-2016 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -452,10 +452,7 @@ struct sta_info { int last_signal; u8 chains; s8 chain_signal_last[IEEE80211_MAX_CHAINS]; - int last_rate_idx; - u32 last_rate_flag; - u32 last_rate_vht_flag; - u8 last_rate_vht_nss; + u16 last_rate; u64 msdu[IEEE80211_NUM_TIDS + 1]; } rx_stats; struct { @@ -683,4 +680,42 @@ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); unsigned long ieee80211_sta_last_active(struct sta_info *sta); +#define STA_STATS_RATE_INVALID 0 +#define STA_STATS_RATE_VHT 0x8000 +#define STA_STATS_RATE_HT 0x4000 +#define STA_STATS_RATE_LEGACY 0x2000 +#define STA_STATS_RATE_SGI 0x1000 +#define STA_STATS_RATE_BW_SHIFT 9 +#define STA_STATS_RATE_BW_MASK (0x7 << STA_STATS_RATE_BW_SHIFT) + +static inline u16 sta_stats_encode_rate(struct ieee80211_rx_status *s) +{ + u16 r = s->rate_idx; + + if (s->vht_flag & RX_VHT_FLAG_80MHZ) + r |= RATE_INFO_BW_80 << STA_STATS_RATE_BW_SHIFT; + else if (s->vht_flag & RX_VHT_FLAG_160MHZ) + r |= RATE_INFO_BW_160 << STA_STATS_RATE_BW_SHIFT; + else if (s->flag & RX_FLAG_40MHZ) + r |= RATE_INFO_BW_40 << STA_STATS_RATE_BW_SHIFT; + else if (s->flag & RX_FLAG_10MHZ) + r |= RATE_INFO_BW_10 << STA_STATS_RATE_BW_SHIFT; + else if (s->flag & RX_FLAG_5MHZ) + r |= RATE_INFO_BW_5 << STA_STATS_RATE_BW_SHIFT; + else + r |= RATE_INFO_BW_20 << STA_STATS_RATE_BW_SHIFT; + + if (s->flag & RX_FLAG_SHORT_GI) + r |= STA_STATS_RATE_SGI; + + if (s->flag & RX_FLAG_VHT) + r |= STA_STATS_RATE_VHT | (s->vht_nss << 4); + else if (s->flag & RX_FLAG_HT) + r |= STA_STATS_RATE_HT; + else + r |= STA_STATS_RATE_LEGACY | (s->band << 4); + + return r; +} + #endif /* STA_INFO_H */ -- GitLab From 0f9c5a61d4b2330b12c59126aa5a9108dbfce555 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:09 +0300 Subject: [PATCH 1552/9938] mac80211: fix RX u64 stats consistency on 32-bit platforms On 32-bit platforms, the 64-bit counters we keep need to be protected to be consistently read. Use the u64_stats_sync mechanism to do that. In order to not end up with overly long lines, refactor the tidstats assignments a bit. Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 6 ++++ net/mac80211/sta_info.c | 72 +++++++++++++++++++++++++---------------- net/mac80211/sta_info.h | 5 ++- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5a6c36c3aed6..2863832b0db4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1441,7 +1441,11 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ieee80211_sta_rx_notify(rx->sdata, hdr); sta->rx_stats.fragments++; + + u64_stats_update_begin(&rx->sta->rx_stats.syncp); sta->rx_stats.bytes += rx->skb->len; + u64_stats_update_end(&rx->sta->rx_stats.syncp); + if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { sta->rx_stats.last_signal = status->signal; ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal); @@ -2124,7 +2128,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) * for non-QoS-data frames. Here we know it's a data * frame, so count MSDUs. */ + u64_stats_update_begin(&rx->sta->rx_stats.syncp); rx->sta->rx_stats.msdu[rx->seqno_idx]++; + u64_stats_update_end(&rx->sta->rx_stats.syncp); } if ((sdata->vif.type == NL80211_IFTYPE_AP || diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 0b50ae3f0b05..bdd303e8b577 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -335,6 +335,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->sdata = sdata; sta->rx_stats.last_rx = jiffies; + u64_stats_init(&sta->rx_stats.syncp); + sta->sta_state = IEEE80211_STA_NONE; /* Mark TID as unreserved */ @@ -1971,6 +1973,41 @@ static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) sta_stats_decode_rate(sta->local, rate, rinfo); } +static void sta_set_tidstats(struct sta_info *sta, + struct cfg80211_tid_stats *tidstats, + int tid) +{ + struct ieee80211_local *local = sta->local; + + if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { + unsigned int start; + + do { + start = u64_stats_fetch_begin(&sta->rx_stats.syncp); + tidstats->rx_msdu = sta->rx_stats.msdu[tid]; + } while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start)); + + tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU); + } + + if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) { + tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU); + tidstats->tx_msdu = sta->tx_stats.msdu[tid]; + } + + if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) && + ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { + tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_RETRIES); + tidstats->tx_msdu_retries = sta->status_stats.msdu_retries[tid]; + } + + if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) && + ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { + tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED); + tidstats->tx_msdu_failed = sta->status_stats.msdu_failed[tid]; + } +} + void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) { struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -2025,7 +2062,12 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | BIT(NL80211_STA_INFO_RX_BYTES)))) { - sinfo->rx_bytes = sta->rx_stats.bytes; + unsigned int start; + + do { + start = u64_stats_fetch_begin(&sta->rx_stats.syncp); + sinfo->rx_bytes = sta->rx_stats.bytes; + } while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start)); sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); } @@ -2097,33 +2139,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i]; - if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { - tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU); - tidstats->rx_msdu = sta->rx_stats.msdu[i]; - } - - if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) { - tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU); - tidstats->tx_msdu = sta->tx_stats.msdu[i]; - } - - if (!(tidstats->filled & - BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) && - ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { - tidstats->filled |= - BIT(NL80211_TID_STATS_TX_MSDU_RETRIES); - tidstats->tx_msdu_retries = - sta->status_stats.msdu_retries[i]; - } - - if (!(tidstats->filled & - BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) && - ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { - tidstats->filled |= - BIT(NL80211_TID_STATS_TX_MSDU_FAILED); - tidstats->tx_msdu_failed = - sta->status_stats.msdu_failed[i]; - } + sta_set_tidstats(sta, tidstats, i); } if (ieee80211_vif_is_mesh(&sdata->vif)) { diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5549ceb9cbb3..7c23b575672e 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "key.h" /** @@ -444,7 +445,6 @@ struct sta_info { /* Updated from RX path only, no locking requirements */ struct { unsigned long packets; - u64 bytes; unsigned long last_rx; unsigned long num_duplicates; unsigned long fragments; @@ -453,6 +453,9 @@ struct sta_info { u8 chains; s8 chain_signal_last[IEEE80211_MAX_CHAINS]; u16 last_rate; + + struct u64_stats_sync syncp; + u64 bytes; u64 msdu[IEEE80211_NUM_TIDS + 1]; } rx_stats; struct { -- GitLab From 49ddf8e6e2347cffdcf83d1ca2d04ff929820178 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:10 +0300 Subject: [PATCH 1553/9938] mac80211: add fast-rx path The regular RX path has a lot of code, but with a few assumptions on the hardware it's possible to reduce the amount of code significantly. Currently the assumptions on the driver are the following: * hardware/driver reordering buffer (if supporting aggregation) * hardware/driver decryption & PN checking (if using encryption) * hardware/driver did de-duplication * hardware/driver did A-MSDU deaggregation * AP_LINK_PS is used (in AP mode) * no client powersave handling in mac80211 (in client mode) of which some are actually checked per packet: * de-duplication * PN checking * decryption and additionally packets must * not be A-MSDU (have been deaggregated by driver/device) * be data packets * not be fragmented * be unicast * have RFC 1042 header Additionally dynamically we assume: * no encryption or CCMP/GCMP, TKIP/WEP/other not allowed * station must be authorized * 4-addr format not enabled Some data needed for the RX path is cached in a new per-station "fast_rx" structure, so that we only need to look at this and the packet, no other memory when processing packets on the fast RX path. After doing the above per-packet checks, the data path collapses down to a pretty simple conversion function taking advantage of the data cached in the small fast_rx struct. This should speed up the RX processing, and will make it easier to reason about parallelizing RX (for which statistics will need to be per-CPU still.) Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 10 ++ net/mac80211/cfg.c | 10 +- net/mac80211/ieee80211_i.h | 5 + net/mac80211/key.c | 1 + net/mac80211/mlme.c | 9 + net/mac80211/rx.c | 351 +++++++++++++++++++++++++++++++++++++ net/mac80211/sta_info.c | 2 + net/mac80211/sta_info.h | 34 ++++ 8 files changed, 419 insertions(+), 3 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index bf9706c5b0bd..113bfc468a4d 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -638,6 +638,16 @@ static inline bool ieee80211_is_first_frag(__le16 seq_ctrl) return (seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0; } +/** + * ieee80211_is_frag - check if a frame is a fragment + * @hdr: 802.11 header of the frame + */ +static inline bool ieee80211_is_frag(struct ieee80211_hdr *hdr) +{ + return ieee80211_has_morefrags(hdr->frame_control) || + hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG); +} + struct ieee80211s_hdr { u8 flags; u8 ttl; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 62a90f270f03..fc4730b938d0 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -65,11 +65,13 @@ static int ieee80211_change_iface(struct wiphy *wiphy, return ret; if (type == NL80211_IFTYPE_AP_VLAN && - params && params->use_4addr == 0) + params && params->use_4addr == 0) { RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); - else if (type == NL80211_IFTYPE_STATION && - params && params->use_4addr >= 0) + ieee80211_check_fast_rx_iface(sdata); + } else if (type == NL80211_IFTYPE_STATION && + params && params->use_4addr >= 0) { sdata->u.mgd.use_4addr = params->use_4addr; + } if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) { struct ieee80211_local *local = sdata->local; @@ -1367,6 +1369,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, rcu_assign_pointer(vlansdata->u.vlan.sta, sta); new_4addr = true; + __ieee80211_check_fast_rx_iface(vlansdata); } if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && @@ -1889,6 +1892,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; else sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; + ieee80211_check_fast_rx_iface(sdata); } if (params->ht_opmode >= 0) { diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c8945e2d8a86..6243109979ed 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1494,6 +1494,11 @@ u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local); int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb, u64 *cookie, gfp_t gfp); +void ieee80211_check_fast_rx(struct sta_info *sta); +void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata); +void ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata); +void ieee80211_clear_fast_rx(struct sta_info *sta); + /* STA code */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 3df7b0392d30..edd6f2945f69 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -338,6 +338,7 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, } else { rcu_assign_pointer(sta->gtk[idx], new); } + ieee80211_check_fast_rx(sta); } else { defunikey = old && old == key_mtx_dereference(sdata->local, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2112df4ffb7b..d3c75ac8a029 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2217,6 +2217,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) const u8 *ssid; u8 *dst = ifmgd->associated->bssid; u8 unicast_limit = max(1, max_probe_tries - 3); + struct sta_info *sta; /* * Try sending broadcast probe requests for the last three @@ -2235,6 +2236,14 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) */ ifmgd->probe_send_count++; + if (dst) { + mutex_lock(&sdata->local->sta_mtx); + sta = sta_info_get(sdata, dst); + if (!WARN_ON(!sta)) + ieee80211_check_fast_rx(sta); + mutex_unlock(&sdata->local->sta_mtx); + } + if (ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) { ifmgd->nullfunc_failed = false; ieee80211_send_nullfunc(sdata->local, sdata, false); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2863832b0db4..96f8bbf21649 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3508,6 +3508,342 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) return false; } +void ieee80211_check_fast_rx(struct sta_info *sta) +{ + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; + struct ieee80211_key *key; + struct ieee80211_fast_rx fastrx = { + .dev = sdata->dev, + .vif_type = sdata->vif.type, + .control_port_protocol = sdata->control_port_protocol, + }, *old, *new = NULL; + bool assign = false; + + /* use sparse to check that we don't return without updating */ + __acquire(check_fast_rx); + + BUILD_BUG_ON(sizeof(fastrx.rfc1042_hdr) != sizeof(rfc1042_header)); + BUILD_BUG_ON(sizeof(fastrx.rfc1042_hdr) != ETH_ALEN); + ether_addr_copy(fastrx.rfc1042_hdr, rfc1042_header); + ether_addr_copy(fastrx.vif_addr, sdata->vif.addr); + + /* fast-rx doesn't do reordering */ + if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) && + !ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) + goto clear; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + /* 4-addr is harder to deal with, later maybe */ + if (sdata->u.mgd.use_4addr) + goto clear; + /* software powersave is a huge mess, avoid all of it */ + if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) + goto clear; + if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) && + !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) + goto clear; + if (sta->sta.tdls) { + fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1); + fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2); + fastrx.expected_ds_bits = 0; + } else { + fastrx.sta_notify = sdata->u.mgd.probe_send_count > 0; + fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1); + fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr3); + fastrx.expected_ds_bits = + cpu_to_le16(IEEE80211_FCTL_FROMDS); + } + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_AP: + /* parallel-rx requires this, at least with calls to + * ieee80211_sta_ps_transition() + */ + if (!ieee80211_hw_check(&local->hw, AP_LINK_PS)) + goto clear; + fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3); + fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2); + fastrx.expected_ds_bits = cpu_to_le16(IEEE80211_FCTL_TODS); + + fastrx.internal_forward = + !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && + (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || + !sdata->u.vlan.sta); + break; + default: + goto clear; + } + + if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) + goto clear; + + rcu_read_lock(); + key = rcu_dereference(sta->ptk[sta->ptk_idx]); + if (key) { + switch (key->conf.cipher) { + case WLAN_CIPHER_SUITE_TKIP: + /* we don't want to deal with MMIC in fast-rx */ + goto clear_rcu; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: + break; + default: + /* we also don't want to deal with WEP or cipher scheme + * since those require looking up the key idx in the + * frame, rather than assuming the PTK is used + * (we need to revisit this once we implement the real + * PTK index, which is now valid in the spec, but we + * haven't implemented that part yet) + */ + goto clear_rcu; + } + + fastrx.key = true; + fastrx.icv_len = key->conf.icv_len; + } + + assign = true; + clear_rcu: + rcu_read_unlock(); + clear: + __release(check_fast_rx); + + if (assign) + new = kmemdup(&fastrx, sizeof(fastrx), GFP_KERNEL); + + spin_lock_bh(&sta->lock); + old = rcu_dereference_protected(sta->fast_rx, true); + rcu_assign_pointer(sta->fast_rx, new); + spin_unlock_bh(&sta->lock); + + if (old) + kfree_rcu(old, rcu_head); +} + +void ieee80211_clear_fast_rx(struct sta_info *sta) +{ + struct ieee80211_fast_rx *old; + + spin_lock_bh(&sta->lock); + old = rcu_dereference_protected(sta->fast_rx, true); + RCU_INIT_POINTER(sta->fast_rx, NULL); + spin_unlock_bh(&sta->lock); + + if (old) + kfree_rcu(old, rcu_head); +} + +void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + + lockdep_assert_held(&local->sta_mtx); + + list_for_each_entry_rcu(sta, &local->sta_list, list) { + if (sdata != sta->sdata && + (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) + continue; + ieee80211_check_fast_rx(sta); + } +} + +void ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + + mutex_lock(&local->sta_mtx); + __ieee80211_check_fast_rx_iface(sdata); + mutex_unlock(&local->sta_mtx); +} + +static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, + struct ieee80211_fast_rx *fast_rx) +{ + struct sk_buff *skb = rx->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct sta_info *sta = rx->sta; + int orig_len = skb->len; + int snap_offs = ieee80211_hdrlen(hdr->frame_control); + struct { + u8 snap[sizeof(rfc1042_header)]; + __be16 proto; + } *payload __aligned(2); + struct { + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + } addrs __aligned(2); + + /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write + * to a common data structure; drivers can implement that per queue + * but we don't have that information in mac80211 + */ + if (!(status->flag & RX_FLAG_DUP_VALIDATED)) + return false; + +#define FAST_RX_CRYPT_FLAGS (RX_FLAG_PN_VALIDATED | RX_FLAG_DECRYPTED) + + /* If using encryption, we also need to have: + * - PN_VALIDATED: similar, but the implementation is tricky + * - DECRYPTED: necessary for PN_VALIDATED + */ + if (fast_rx->key && + (status->flag & FAST_RX_CRYPT_FLAGS) != FAST_RX_CRYPT_FLAGS) + return false; + + /* we don't deal with A-MSDU deaggregation here */ + if (status->rx_flags & IEEE80211_RX_AMSDU) + return false; + + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) + return false; + + if (unlikely(ieee80211_is_frag(hdr))) + return false; + + /* Since our interface address cannot be multicast, this + * implicitly also rejects multicast frames without the + * explicit check. + * + * We shouldn't get any *data* frames not addressed to us + * (AP mode will accept multicast *management* frames), but + * punting here will make it go through the full checks in + * ieee80211_accept_frame(). + */ + if (!ether_addr_equal(fast_rx->vif_addr, hdr->addr1)) + return false; + + if ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FROMDS | + IEEE80211_FCTL_TODS)) != + fast_rx->expected_ds_bits) + goto drop; + + /* assign the key to drop unencrypted frames (later) + * and strip the IV/MIC if necessary + */ + if (fast_rx->key && !(status->flag & RX_FLAG_IV_STRIPPED)) { + /* GCMP header length is the same */ + snap_offs += IEEE80211_CCMP_HDR_LEN; + } + + if (!pskb_may_pull(skb, snap_offs + sizeof(*payload))) + goto drop; + payload = (void *)(skb->data + snap_offs); + + if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr)) + return false; + + /* Don't handle these here since they require special code. + * Accept AARP and IPX even though they should come with a + * bridge-tunnel header - but if we get them this way then + * there's little point in discarding them. + */ + if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) || + payload->proto == fast_rx->control_port_protocol)) + return false; + + /* after this point, don't punt to the slowpath! */ + + if (rx->key && !(status->flag & RX_FLAG_MIC_STRIPPED) && + pskb_trim(skb, skb->len - fast_rx->icv_len)) + goto drop; + + if (unlikely(fast_rx->sta_notify)) { + ieee80211_sta_rx_notify(rx->sdata, hdr); + fast_rx->sta_notify = false; + } + + /* statistics part of ieee80211_rx_h_sta_process() */ + sta->rx_stats.last_rx = jiffies; + sta->rx_stats.last_rate = sta_stats_encode_rate(status); + + sta->rx_stats.fragments++; + + if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { + sta->rx_stats.last_signal = status->signal; + ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal); + } + + if (status->chains) { + int i; + + sta->rx_stats.chains = status->chains; + for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { + int signal = status->chain_signal[i]; + + if (!(status->chains & BIT(i))) + continue; + + sta->rx_stats.chain_signal_last[i] = signal; + ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], + -signal); + } + } + /* end of statistics */ + + if (rx->key && !ieee80211_has_protected(hdr->frame_control)) + goto drop; + + /* do the header conversion - first grab the addresses */ + ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs); + ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs); + /* remove the SNAP but leave the ethertype */ + skb_pull(skb, snap_offs + sizeof(rfc1042_header)); + /* push the addresses in front */ + memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs)); + + skb->dev = fast_rx->dev; + + ieee80211_rx_stats(fast_rx->dev, skb->len); + + /* The seqno index has the same property as needed + * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS + * for non-QoS-data frames. Here we know it's a data + * frame, so count MSDUs. + */ + u64_stats_update_begin(&sta->rx_stats.syncp); + sta->rx_stats.msdu[rx->seqno_idx]++; + sta->rx_stats.bytes += orig_len; + u64_stats_update_end(&sta->rx_stats.syncp); + + if (fast_rx->internal_forward) { + struct sta_info *dsta = sta_info_get(rx->sdata, skb->data); + + if (dsta) { + /* + * Send to wireless media and increase priority by 256 + * to keep the received priority instead of + * reclassifying the frame (see cfg80211_classify8021d). + */ + skb->priority += 256; + skb->protocol = htons(ETH_P_802_3); + skb_reset_network_header(skb); + skb_reset_mac_header(skb); + dev_queue_xmit(skb); + return true; + } + } + + /* deliver to local stack */ + skb->protocol = eth_type_trans(skb, fast_rx->dev); + memset(skb->cb, 0, sizeof(skb->cb)); + if (rx->napi) + napi_gro_receive(rx->napi, skb); + else + netif_receive_skb(skb); + + return true; + drop: + dev_kfree_skb(skb); + sta->rx_stats.dropped++; + return true; +} + /* * This function returns whether or not the SKB * was destined for RX processing or not, which, @@ -3522,6 +3858,21 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, rx->skb = skb; + /* See if we can do fast-rx; if we have to copy we already lost, + * so punt in that case. We should never have to deliver a data + * frame to multiple interfaces anyway. + * + * We skip the ieee80211_accept_frame() call and do the necessary + * checking inside ieee80211_invoke_fast_rx(). + */ + if (consume && rx->sta) { + struct ieee80211_fast_rx *fast_rx; + + fast_rx = rcu_dereference(rx->sta->fast_rx); + if (fast_rx && ieee80211_invoke_fast_rx(rx, fast_rx)) + return true; + } + if (!ieee80211_accept_frame(rx)) return false; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index bdd303e8b577..a0ce7e40f420 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1874,6 +1874,7 @@ int sta_info_move_state(struct sta_info *sta, atomic_dec(&sta->sdata->bss->num_mcast_sta); clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); ieee80211_clear_fast_xmit(sta); + ieee80211_clear_fast_rx(sta); } break; case IEEE80211_STA_AUTHORIZED: @@ -1884,6 +1885,7 @@ int sta_info_move_state(struct sta_info *sta, atomic_inc(&sta->sdata->bss->num_mcast_sta); set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); ieee80211_check_fast_xmit(sta); + ieee80211_check_fast_rx(sta); } break; default: diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 7c23b575672e..a0a06609338d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -285,6 +285,38 @@ struct ieee80211_fast_tx { struct rcu_head rcu_head; }; +/** + * struct ieee80211_fast_rx - RX fastpath information + * @dev: netdevice for reporting the SKB + * @vif_type: (P2P-less) interface type of the original sdata (sdata->vif.type) + * @vif_addr: interface address + * @rfc1042_hdr: copy of the RFC 1042 SNAP header (to have in cache) + * @control_port_protocol: control port protocol copied from sdata + * @expected_ds_bits: from/to DS bits expected + * @icv_len: length of the MIC if present + * @key: bool indicating encryption is expected (key is set) + * @sta_notify: notify the MLME code (once) + * @internal_forward: forward froms internally on AP/VLAN type interfaces + * @da_offs: offset of the DA in the header (for header conversion) + * @sa_offs: offset of the SA in the header (for header conversion) + * @rcu_head: RCU head for freeing this structure + */ +struct ieee80211_fast_rx { + struct net_device *dev; + enum nl80211_iftype vif_type; + u8 vif_addr[ETH_ALEN] __aligned(2); + u8 rfc1042_hdr[6] __aligned(2); + __be16 control_port_protocol; + __le16 expected_ds_bits; + u8 icv_len; + u8 key:1, + sta_notify:1, + internal_forward:1; + u8 da_offs, sa_offs; + + struct rcu_head rcu_head; +}; + /** * struct mesh_sta - mesh STA information * @plink_lock: serialize access to plink fields @@ -391,6 +423,7 @@ DECLARE_EWMA(signal, 1024, 8) * @cipher_scheme: optional cipher scheme for this station * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) * @fast_tx: TX fastpath information + * @fast_rx: RX fastpath information * @tdls_chandef: a TDLS peer can have a wider chandef that is compatible to * the BSS one. * @tx_stats: TX statistics @@ -414,6 +447,7 @@ struct sta_info { spinlock_t lock; struct ieee80211_fast_tx __rcu *fast_tx; + struct ieee80211_fast_rx __rcu *fast_rx; #ifdef CONFIG_MAC80211_MESH struct mesh_sta *mesh; -- GitLab From c9c5962b56c10c34d8fedc20cd6d6ebdaa2383c6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Mar 2016 20:02:11 +0300 Subject: [PATCH 1554/9938] mac80211: enable collecting station statistics per-CPU If the driver advertises the new HW flag USE_RSS, make the station statistics on the fast-rx path per-CPU. This will enable calling the RX in parallel, only hitting locking or shared cachelines when the fast-RX path isn't available. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 4 ++ net/mac80211/debugfs.c | 1 + net/mac80211/rx.c | 37 ++++++++------ net/mac80211/sta_info.c | 108 ++++++++++++++++++++++++++++++++++------ net/mac80211/sta_info.h | 38 ++++++++------ 5 files changed, 142 insertions(+), 46 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index fd5ec446a7a9..5f4b4c773a92 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1980,6 +1980,9 @@ struct ieee80211_txq { * order and does not need to manage its own reorder buffer or BA session * timeout. * + * @IEEE80211_HW_USES_RSS: The device uses RSS and thus requires parallel RX, + * which implies using per-CPU station statistics. + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2017,6 +2020,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_BEACON_TX_STATUS, IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR, IEEE80211_HW_SUPPORTS_REORDERING_BUFFER, + IEEE80211_HW_USES_RSS, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 4ab5c522ceee..52ed2afc408d 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -127,6 +127,7 @@ static const char *hw_flag_names[] = { FLAG(BEACON_TX_STATUS), FLAG(NEEDS_UNIQUE_STA_ADDR), FLAG(SUPPORTS_REORDERING_BUFFER), + FLAG(USES_RSS), #undef FLAG }; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 96f8bbf21649..c2b659e9a9f9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3528,6 +3528,8 @@ void ieee80211_check_fast_rx(struct sta_info *sta) ether_addr_copy(fastrx.rfc1042_hdr, rfc1042_header); ether_addr_copy(fastrx.vif_addr, sdata->vif.addr); + fastrx.uses_rss = ieee80211_hw_check(&local->hw, USES_RSS); + /* fast-rx doesn't do reordering */ if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) && !ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) @@ -3678,6 +3680,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; } addrs __aligned(2); + struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; + + if (fast_rx->uses_rss) + stats = this_cpu_ptr(sta->pcpu_rx_stats); /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write * to a common data structure; drivers can implement that per queue @@ -3759,29 +3765,32 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, } /* statistics part of ieee80211_rx_h_sta_process() */ - sta->rx_stats.last_rx = jiffies; - sta->rx_stats.last_rate = sta_stats_encode_rate(status); + stats->last_rx = jiffies; + stats->last_rate = sta_stats_encode_rate(status); - sta->rx_stats.fragments++; + stats->fragments++; if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { - sta->rx_stats.last_signal = status->signal; - ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal); + stats->last_signal = status->signal; + if (!fast_rx->uses_rss) + ewma_signal_add(&sta->rx_stats_avg.signal, + -status->signal); } if (status->chains) { int i; - sta->rx_stats.chains = status->chains; + stats->chains = status->chains; for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { int signal = status->chain_signal[i]; if (!(status->chains & BIT(i))) continue; - sta->rx_stats.chain_signal_last[i] = signal; - ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], - -signal); + stats->chain_signal_last[i] = signal; + if (!fast_rx->uses_rss) + ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], + -signal); } } /* end of statistics */ @@ -3806,10 +3815,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, * for non-QoS-data frames. Here we know it's a data * frame, so count MSDUs. */ - u64_stats_update_begin(&sta->rx_stats.syncp); - sta->rx_stats.msdu[rx->seqno_idx]++; - sta->rx_stats.bytes += orig_len; - u64_stats_update_end(&sta->rx_stats.syncp); + u64_stats_update_begin(&stats->syncp); + stats->msdu[rx->seqno_idx]++; + stats->bytes += orig_len; + u64_stats_update_end(&stats->syncp); if (fast_rx->internal_forward) { struct sta_info *dsta = sta_info_get(rx->sdata, skb->data); @@ -3840,7 +3849,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, return true; drop: dev_kfree_skb(skb); - sta->rx_stats.dropped++; + stats->dropped++; return true; } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a0ce7e40f420..cf2aca0cc200 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -254,6 +254,7 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) #ifdef CONFIG_MAC80211_MESH kfree(sta->mesh); #endif + free_percpu(sta->pcpu_rx_stats); kfree(sta); } @@ -311,6 +312,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, if (!sta) return NULL; + if (ieee80211_hw_check(hw, USES_RSS)) { + sta->pcpu_rx_stats = + alloc_percpu(struct ieee80211_sta_rx_stats); + if (!sta->pcpu_rx_stats) + goto free; + } + spin_lock_init(&sta->lock); spin_lock_init(&sta->ps_lock); INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); @@ -1932,6 +1940,28 @@ u8 sta_info_tx_streams(struct sta_info *sta) >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; } +static struct ieee80211_sta_rx_stats * +sta_get_last_rx_stats(struct sta_info *sta) +{ + struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; + struct ieee80211_local *local = sta->local; + int cpu; + + if (!ieee80211_hw_check(&local->hw, USES_RSS)) + return stats; + + for_each_possible_cpu(cpu) { + struct ieee80211_sta_rx_stats *cpustats; + + cpustats = per_cpu_ptr(sta->pcpu_rx_stats, cpu); + + if (time_after(cpustats->last_rx, stats->last_rx)) + stats = cpustats; + } + + return stats; +} + static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, struct rate_info *rinfo) { @@ -1967,7 +1997,7 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) { - u16 rate = ACCESS_ONCE(sta->rx_stats.last_rate); + u16 rate = ACCESS_ONCE(sta_get_last_rx_stats(sta)->last_rate); if (rate == STA_STATS_RATE_INVALID) rinfo->flags = 0; @@ -2010,13 +2040,29 @@ static void sta_set_tidstats(struct sta_info *sta, } } +static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats) +{ + unsigned int start; + u64 value; + + do { + start = u64_stats_fetch_begin(&rxstats->syncp); + value = rxstats->bytes; + } while (u64_stats_fetch_retry(&rxstats->syncp, start)); + + return value; +} + void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; struct rate_control_ref *ref = NULL; u32 thr = 0; - int i, ac; + int i, ac, cpu; + struct ieee80211_sta_rx_stats *last_rxstats; + + last_rxstats = sta_get_last_rx_stats(sta); if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) ref = local->rate_ctrl; @@ -2064,17 +2110,30 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | BIT(NL80211_STA_INFO_RX_BYTES)))) { - unsigned int start; + sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats); + + if (sta->pcpu_rx_stats) { + for_each_possible_cpu(cpu) { + struct ieee80211_sta_rx_stats *cpurxs; + + cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu); + sinfo->rx_bytes += sta_get_stats_bytes(cpurxs); + } + } - do { - start = u64_stats_fetch_begin(&sta->rx_stats.syncp); - sinfo->rx_bytes = sta->rx_stats.bytes; - } while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start)); sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); } if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) { sinfo->rx_packets = sta->rx_stats.packets; + if (sta->pcpu_rx_stats) { + for_each_possible_cpu(cpu) { + struct ieee80211_sta_rx_stats *cpurxs; + + cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu); + sinfo->rx_packets += cpurxs->packets; + } + } sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); } @@ -2089,6 +2148,14 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) } sinfo->rx_dropped_misc = sta->rx_stats.dropped; + if (sta->pcpu_rx_stats) { + for_each_possible_cpu(cpu) { + struct ieee80211_sta_rx_stats *cpurxs; + + cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu); + sinfo->rx_packets += cpurxs->dropped; + } + } if (sdata->vif.type == NL80211_IFTYPE_STATION && !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) { @@ -2100,27 +2167,34 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) || ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) { if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) { - sinfo->signal = (s8)sta->rx_stats.last_signal; + sinfo->signal = (s8)last_rxstats->last_signal; sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); } - if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { + if (!sta->pcpu_rx_stats && + !(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { sinfo->signal_avg = -ewma_signal_read(&sta->rx_stats_avg.signal); sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); } } - if (sta->rx_stats.chains && + /* for the average - if pcpu_rx_stats isn't set - rxstats must point to + * the sta->rx_stats struct, so the check here is fine with and without + * pcpu statistics + */ + if (last_rxstats->chains && !(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) { - sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | - BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); + sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL); + if (!sta->pcpu_rx_stats) + sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); + + sinfo->chains = last_rxstats->chains; - sinfo->chains = sta->rx_stats.chains; for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { sinfo->chain_signal[i] = - sta->rx_stats.chain_signal_last[i]; + last_rxstats->chain_signal_last[i]; sinfo->chain_signal_avg[i] = -ewma_signal_read(&sta->rx_stats_avg.chain_signal[i]); } @@ -2213,7 +2287,9 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) unsigned long ieee80211_sta_last_active(struct sta_info *sta) { - if (time_after(sta->rx_stats.last_rx, sta->status_stats.last_ack)) - return sta->rx_stats.last_rx; + struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta); + + if (time_after(stats->last_rx, sta->status_stats.last_ack)) + return stats->last_rx; return sta->status_stats.last_ack; } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index a0a06609338d..dd6c6d400208 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -297,6 +297,7 @@ struct ieee80211_fast_tx { * @key: bool indicating encryption is expected (key is set) * @sta_notify: notify the MLME code (once) * @internal_forward: forward froms internally on AP/VLAN type interfaces + * @uses_rss: copy of USES_RSS hw flag * @da_offs: offset of the DA in the header (for header conversion) * @sa_offs: offset of the SA in the header (for header conversion) * @rcu_head: RCU head for freeing this structure @@ -311,7 +312,8 @@ struct ieee80211_fast_rx { u8 icv_len; u8 key:1, sta_notify:1, - internal_forward:1; + internal_forward:1, + uses_rss:1; u8 da_offs, sa_offs; struct rcu_head rcu_head; @@ -367,6 +369,21 @@ struct mesh_sta { DECLARE_EWMA(signal, 1024, 8) +struct ieee80211_sta_rx_stats { + unsigned long packets; + unsigned long last_rx; + unsigned long num_duplicates; + unsigned long fragments; + unsigned long dropped; + int last_signal; + u8 chains; + s8 chain_signal_last[IEEE80211_MAX_CHAINS]; + u16 last_rate; + struct u64_stats_sync syncp; + u64 bytes; + u64 msdu[IEEE80211_NUM_TIDS + 1]; +}; + /** * struct sta_info - STA information * @@ -428,6 +445,8 @@ DECLARE_EWMA(signal, 1024, 8) * the BSS one. * @tx_stats: TX statistics * @rx_stats: RX statistics + * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs + * this (by advertising the USES_RSS hw flag) * @status_stats: TX status statistics */ struct sta_info { @@ -448,6 +467,7 @@ struct sta_info { struct ieee80211_fast_tx __rcu *fast_tx; struct ieee80211_fast_rx __rcu *fast_rx; + struct ieee80211_sta_rx_stats __percpu *pcpu_rx_stats; #ifdef CONFIG_MAC80211_MESH struct mesh_sta *mesh; @@ -477,21 +497,7 @@ struct sta_info { long last_connected; /* Updated from RX path only, no locking requirements */ - struct { - unsigned long packets; - unsigned long last_rx; - unsigned long num_duplicates; - unsigned long fragments; - unsigned long dropped; - int last_signal; - u8 chains; - s8 chain_signal_last[IEEE80211_MAX_CHAINS]; - u16 last_rate; - - struct u64_stats_sync syncp; - u64 bytes; - u64 msdu[IEEE80211_NUM_TIDS + 1]; - } rx_stats; + struct ieee80211_sta_rx_stats rx_stats; struct { struct ewma_signal signal; struct ewma_signal chain_signal[IEEE80211_MAX_CHAINS]; -- GitLab From 6e0456b5454561c4e9fa9e8a4acea405e6d56c80 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 3 Mar 2016 22:59:00 +0100 Subject: [PATCH 1555/9938] mac80211: add A-MSDU tx support Requires software tx queueing and fast-xmit support. For good performance, drivers need frag_list support as well. This avoids the need for copying data of aggregated frames. Running without it is only supported for debugging purposes. To avoid performance and packet size issues, the rate control module or driver needs to limit the maximum A-MSDU size by setting max_rc_amsdu_len in struct ieee80211_sta. Signed-off-by: Felix Fietkau [fix locking issue] Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 3 + include/net/mac80211.h | 19 +++++ net/mac80211/agg-tx.c | 5 ++ net/mac80211/debugfs.c | 2 + net/mac80211/ieee80211_i.h | 1 + net/mac80211/sta_info.c | 2 + net/mac80211/tx.c | 156 +++++++++++++++++++++++++++++++++++++ 7 files changed, 188 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 113bfc468a4d..b118744d3382 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -164,6 +164,9 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2) /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ #define IEEE80211_MAX_FRAME_LEN 2352 +/* Maximal size of an A-MSDU that can be transported in a HT BA session */ +#define IEEE80211_MAX_MPDU_LEN_HT_BA 4095 + /* Maximal size of an A-MSDU */ #define IEEE80211_MAX_MPDU_LEN_HT_3839 3839 #define IEEE80211_MAX_MPDU_LEN_HT_7935 7935 diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5f4b4c773a92..a3ee76559791 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -713,6 +713,7 @@ enum mac80211_tx_info_flags { * @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll * frame (PS-Poll or uAPSD). * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information + * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame * * These flags are used in tx_info->control.flags. */ @@ -720,6 +721,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0), IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1), IEEE80211_TX_CTRL_RATE_INJECT = BIT(2), + IEEE80211_TX_CTRL_AMSDU = BIT(3), }; /* @@ -1746,6 +1748,7 @@ struct ieee80211_sta_rates { * Both additional HT limits must be enforced by the low level driver. * This is defined by the spec (IEEE 802.11-2012 section 8.3.2.2 NOTE 2). * @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not. + * @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control. * @txq: per-TID data TX queues (if driver uses the TXQ abstraction) */ struct ieee80211_sta { @@ -1767,6 +1770,7 @@ struct ieee80211_sta { u8 max_amsdu_subframes; u16 max_amsdu_len; bool support_p2p_ps; + u16 max_rc_amsdu_len; struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; @@ -1983,6 +1987,15 @@ struct ieee80211_txq { * @IEEE80211_HW_USES_RSS: The device uses RSS and thus requires parallel RX, * which implies using per-CPU station statistics. * + * @IEEE80211_HW_TX_AMSDU: Hardware (or driver) supports software aggregated + * A-MSDU frames. Requires software tx queueing and fast-xmit support. + * When not using minstrel/minstrel_ht rate control, the driver must + * limit the maximum A-MSDU size based on the current tx rate by setting + * max_rc_amsdu_len in struct ieee80211_sta. + * + * @IEEE80211_HW_TX_FRAG_LIST: Hardware (or driver) supports sending frag_list + * skbs, needed for zero-copy software A-MSDU. + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2021,6 +2034,8 @@ enum ieee80211_hw_flags { IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR, IEEE80211_HW_SUPPORTS_REORDERING_BUFFER, IEEE80211_HW_USES_RSS, + IEEE80211_HW_TX_AMSDU, + IEEE80211_HW_TX_FRAG_LIST, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS @@ -2093,6 +2108,9 @@ enum ieee80211_hw_flags { * size is smaller (an example is LinkSys WRT120N with FW v1.0.07 * build 002 Jun 18 2012). * + * @max_tx_fragments: maximum number of tx buffers per (A)-MSDU, sum + * of 1 + skb_shinfo(skb)->nr_frags for each skb in the frag_list. + * * @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX * (if %IEEE80211_HW_QUEUE_CONTROL is set) * @@ -2147,6 +2165,7 @@ struct ieee80211_hw { u8 max_rate_tries; u8 max_rx_aggregation_subframes; u8 max_tx_aggregation_subframes; + u8 max_tx_fragments; u8 offchannel_tx_hw_queue; u8 radiotap_mcs_details; u16 radiotap_vht_details; diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 4932e9f243a2..42fa81031dfa 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -935,6 +935,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, size_t len) { struct tid_ampdu_tx *tid_tx; + struct ieee80211_txq *txq; u16 capab, tid; u8 buf_size; bool amsdu; @@ -945,6 +946,10 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes); + txq = sta->sta.txq[tid]; + if (!amsdu && txq) + set_bit(IEEE80211_TXQ_NO_AMSDU, &to_txq_info(txq)->flags); + mutex_lock(&sta->ampdu_mlme.mtx); tid_tx = rcu_dereference_protected_tid_tx(sta, tid); diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 52ed2afc408d..b251b2f7f8dd 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -128,6 +128,8 @@ static const char *hw_flag_names[] = { FLAG(NEEDS_UNIQUE_STA_ADDR), FLAG(SUPPORTS_REORDERING_BUFFER), FLAG(USES_RSS), + FLAG(TX_AMSDU), + FLAG(TX_FRAG_LIST), #undef FLAG }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6243109979ed..40c1d343992c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -802,6 +802,7 @@ struct mac80211_qos_map { enum txq_info_flags { IEEE80211_TXQ_STOP, IEEE80211_TXQ_AMPDU, + IEEE80211_TXQ_NO_AMSDU, }; struct txq_info { diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index cf2aca0cc200..960e13d8ed30 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -416,6 +416,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, } } + sta->sta.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA; + sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); return sta; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 597c8fe672a3..4fa2842ddb25 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1324,6 +1324,10 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, out: spin_unlock_bh(&txqi->queue.lock); + if (skb && skb_has_frag_list(skb) && + !ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) + skb_linearize(skb); + return skb; } EXPORT_SYMBOL(ieee80211_tx_dequeue); @@ -2802,6 +2806,154 @@ void ieee80211_clear_fast_xmit(struct sta_info *sta) kfree_rcu(fast_tx, rcu_head); } +static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local, + struct sk_buff *skb, int headroom, + int *subframe_len) +{ + int amsdu_len = *subframe_len + sizeof(struct ethhdr); + int padding = (4 - amsdu_len) & 3; + + if (skb_headroom(skb) < headroom || skb_tailroom(skb) < padding) { + I802_DEBUG_INC(local->tx_expand_skb_head); + + if (pskb_expand_head(skb, headroom, padding, GFP_ATOMIC)) { + wiphy_debug(local->hw.wiphy, + "failed to reallocate TX buffer\n"); + return false; + } + } + + if (padding) { + *subframe_len += padding; + memset(skb_put(skb, padding), 0, padding); + } + + return true; +} + +static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata, + struct ieee80211_fast_tx *fast_tx, + struct sk_buff *skb) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr; + struct ethhdr amsdu_hdr; + int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header); + int subframe_len = skb->len - hdr_len; + void *data; + u8 *qc; + + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) + return false; + + if (info->control.flags & IEEE80211_TX_CTRL_AMSDU) + return true; + + if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(amsdu_hdr), + &subframe_len)) + return false; + + amsdu_hdr.h_proto = cpu_to_be16(subframe_len); + memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN); + memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN); + + data = skb_push(skb, sizeof(amsdu_hdr)); + memmove(data, data + sizeof(amsdu_hdr), hdr_len); + memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr)); + + hdr = data; + qc = ieee80211_get_qos_ctl(hdr); + *qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT; + + info->control.flags |= IEEE80211_TX_CTRL_AMSDU; + + return true; +} + +static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + struct ieee80211_fast_tx *fast_tx, + struct sk_buff *skb) +{ + struct ieee80211_local *local = sdata->local; + u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; + struct ieee80211_txq *txq = sta->sta.txq[tid]; + struct txq_info *txqi; + struct sk_buff **frag_tail, *head; + int subframe_len = skb->len - ETH_ALEN; + u8 max_subframes = sta->sta.max_amsdu_subframes; + int max_frags = local->hw.max_tx_fragments; + int max_amsdu_len = sta->sta.max_amsdu_len; + __be16 len; + void *data; + bool ret = false; + int n = 1, nfrags; + + if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) + return false; + + if (!txq) + return false; + + txqi = to_txq_info(txq); + if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags)) + return false; + + if (sta->sta.max_rc_amsdu_len) + max_amsdu_len = min_t(int, max_amsdu_len, + sta->sta.max_rc_amsdu_len); + + spin_lock_bh(&txqi->queue.lock); + + head = skb_peek_tail(&txqi->queue); + if (!head) + goto out; + + if (skb->len + head->len > max_amsdu_len) + goto out; + + if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) + goto out; + + nfrags = 1 + skb_shinfo(skb)->nr_frags; + nfrags += 1 + skb_shinfo(head)->nr_frags; + frag_tail = &skb_shinfo(head)->frag_list; + while (*frag_tail) { + nfrags += 1 + skb_shinfo(*frag_tail)->nr_frags; + frag_tail = &(*frag_tail)->next; + n++; + } + + if (max_subframes && n > max_subframes) + goto out; + + if (max_frags && nfrags > max_frags) + goto out; + + if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + 2, + &subframe_len)) + goto out; + + ret = true; + data = skb_push(skb, ETH_ALEN + 2); + memmove(data, data + ETH_ALEN + 2, 2 * ETH_ALEN); + + data += 2 * ETH_ALEN; + len = cpu_to_be16(subframe_len); + memcpy(data, &len, 2); + memcpy(data + 2, rfc1042_header, sizeof(rfc1042_header)); + + head->len += skb->len; + head->data_len += skb->len; + *frag_tail = skb; + +out: + spin_unlock_bh(&txqi->queue.lock); + + return ret; +} + static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, struct net_device *dev, struct sta_info *sta, struct ieee80211_fast_tx *fast_tx, @@ -2856,6 +3008,10 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, ieee80211_tx_stats(dev, skb->len + extra_head); + if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) && + ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb)) + return true; + /* will not be crypto-handled beyond what we do here, so use false * as the may-encrypt argument for the resize to not account for * more room than we already have in 'extra_head' -- GitLab From 918fe04b288b3784f4ca90d3dff12fc23dc2751f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 3 Mar 2016 22:59:01 +0100 Subject: [PATCH 1556/9938] mac80211: minstrel_ht: set A-MSDU tx limits based on selected max_prob_rate Prevents excessive A-MSDU aggregation at low data rates or bad conditions. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 46ce08ed70b5..d77a9a842338 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -883,6 +883,59 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, ratetbl->rate[offset].flags = flags; } +static inline int +minstrel_ht_get_prob_ewma(struct minstrel_ht_sta *mi, int rate) +{ + int group = rate / MCS_GROUP_RATES; + rate %= MCS_GROUP_RATES; + return mi->groups[group].rates[rate].prob_ewma; +} + +static int +minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) +{ + int group = mi->max_prob_rate / MCS_GROUP_RATES; + const struct mcs_group *g = &minstrel_mcs_groups[group]; + int rate = mi->max_prob_rate % MCS_GROUP_RATES; + + /* Disable A-MSDU if max_prob_rate is bad */ + if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100)) + return 1; + + /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */ + if (g->duration[rate] > MCS_DURATION(1, 0, 52)) + return 500; + + /* + * If the rate is slower than single-stream MCS4, limit A-MSDU to usual + * data packet size + */ + if (g->duration[rate] > MCS_DURATION(1, 0, 104)) + return 1600; + + /* + * If the rate is slower than single-stream MCS7, or if the max throughput + * rate success probability is less than 75%, limit A-MSDU to twice the usual + * data packet size + */ + if (g->duration[rate] > MCS_DURATION(1, 0, 260) || + (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) < + MINSTREL_FRAC(75, 100))) + return 3200; + + /* + * HT A-MPDU limits maximum MPDU size under BA agreement to 4095 bytes. + * Since aggregation sessions are started/stopped without txq flush, use + * the limit here to avoid the complexity of having to de-aggregate + * packets in the queue. + */ + if (!mi->sta->vht_cap.vht_supported) + return IEEE80211_MAX_MPDU_LEN_HT_BA; + + /* unlimited */ + return 0; +} + static void minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) { @@ -907,6 +960,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate); } + mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi); rates->rate[i].idx = -1; rate_control_set_rates(mp->hw, mi->sta, rates); } -- GitLab From ba6fbacf9c073effaedf0c52fe7e52e2baf67725 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 29 Mar 2016 13:53:27 +0300 Subject: [PATCH 1557/9938] cfg80211: Add option to specify previous BSSID for Connect command This extends NL80211_CMD_CONNECT to allow the NL80211_ATTR_PREV_BSSID attribute to be used similarly to way this was already allowed with NL80211_CMD_ASSOCIATE. This allows user space to request reassociation (instead of association) when already connected to an AP. This provides an option to reassociate within an ESS without having to disconnect and associate with the AP. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ net/wireless/nl80211.c | 4 ++++ net/wireless/trace.h | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 568c10f6d564..b39277eb251f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1925,6 +1925,7 @@ struct cfg80211_bss_selection { * @pbss: if set, connect to a PCP instead of AP. Valid for DMG * networks. * @bss_select: criteria to be used for BSS selection. + * @prev_bssid: previous BSSID, if not %NULL use reassociate frame */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -1949,6 +1950,7 @@ struct cfg80211_connect_params { struct ieee80211_vht_cap vht_capa_mask; bool pbss; struct cfg80211_bss_selection bss_select; + const u8 *prev_bssid; }; /** diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 824569b1c5a1..4f89e2dbb70e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -8058,6 +8058,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) connect.mfp = NL80211_MFP_NO; } + if (info->attrs[NL80211_ATTR_PREV_BSSID]) + connect.prev_bssid = + nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { connect.channel = nl80211_get_valid_chan( wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]); diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 09b242b09bed..8da1fae23cfb 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1259,6 +1259,7 @@ TRACE_EVENT(rdev_connect, __field(bool, privacy) __field(u32, wpa_versions) __field(u32, flags) + MAC_ENTRY(prev_bssid) ), TP_fast_assign( WIPHY_ASSIGN; @@ -1270,13 +1271,14 @@ TRACE_EVENT(rdev_connect, __entry->privacy = sme->privacy; __entry->wpa_versions = sme->crypto.wpa_versions; __entry->flags = sme->flags; + MAC_ASSIGN(prev_bssid, sme->prev_bssid); ), TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, " - "flags: %u", + "flags: %u, previous bssid: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid, __entry->auth_type, BOOL_TO_STR(__entry->privacy), - __entry->wpa_versions, __entry->flags) + __entry->wpa_versions, __entry->flags, MAC_PR_ARG(prev_bssid)) ); TRACE_EVENT(rdev_set_cqm_rssi_config, -- GitLab From daf7bb1dde0131f2a61cda51a117da63bf718ea4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 18 Jun 2014 14:32:04 +0100 Subject: [PATCH 1558/9938] ARM: multi_v7_defconfig: Enable ST's PWM driver Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/configs/multi_v7_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 28234906a064..7cc9beeaa998 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -784,7 +784,7 @@ CONFIG_PWM_SUN4I=y CONFIG_PWM_TEGRA=y CONFIG_PWM_VT8500=y CONFIG_PHY_HIX5HD2_SATA=y -CONFIG_PWM_STI=m +CONFIG_PWM_STI=y CONFIG_PWM_BCM2835=y CONFIG_OMAP_USB2=y CONFIG_TI_PIPE3=y -- GitLab From 39b86a3e8bc4fc072da5d4df09a8b6d5834a213b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 22 Jul 2014 14:20:25 +0100 Subject: [PATCH 1559/9938] ARM: multi_v7_defconfig: Enable ST's Power Reset driver Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 7cc9beeaa998..79ac536bae4c 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -410,6 +410,7 @@ CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_KEYSTONE=y CONFIG_POWER_RESET_RMOBILE=y +CONFIG_POWER_RESET_ST=y CONFIG_POWER_AVS=y CONFIG_ROCKCHIP_IODOMAIN=y CONFIG_SENSORS_IIO_HWMON=y -- GitLab From 95e2106f46702f720b80a22b3c79be25362e02be Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 11 Jun 2015 09:39:21 +0100 Subject: [PATCH 1560/9938] ARM: multi_v7_defconfig: Enable support for PWM Regulators Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/configs/multi_v7_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 79ac536bae4c..cc13a3735071 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -489,7 +489,7 @@ CONFIG_REGULATOR_MAX77693=m CONFIG_REGULATOR_MAX77802=m CONFIG_REGULATOR_PALMAS=y CONFIG_REGULATOR_PBIAS=y -CONFIG_REGULATOR_PWM=m +CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_QCOM_RPM=y CONFIG_REGULATOR_QCOM_SMD_RPM=y CONFIG_REGULATOR_S2MPS11=y -- GitLab From 3047f3f98eabd655ca2db4e42219a2990052f73a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 16 Mar 2016 05:04:03 -0700 Subject: [PATCH 1561/9938] [media] media-device: Fix a comment The comment is for the wrong function. Fix it. Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- include/media/media-device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/media/media-device.h b/include/media/media-device.h index df74cfa7da4a..6d2860657021 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -494,7 +494,7 @@ int __must_check __media_device_register(struct media_device *mdev, #define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE) /** - * __media_device_unregister() - Unegisters a media device element + * media_device_unregister() - Unregisters a media device element * * @mdev: pointer to struct &media_device * -- GitLab From 952f8eef901b170dbe6b48e80f098be5d835a82c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 16 Mar 2016 05:34:39 -0700 Subject: [PATCH 1562/9938] [media] media-device: make topology_version u64 The uAPI defines it with 64 bits. Let's change the Kernel implementation too. Signed-off-by: Mauro Carvalho Chehab --- include/media/media-device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/media/media-device.h b/include/media/media-device.h index 6d2860657021..07809f698464 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -357,7 +357,7 @@ struct media_device { u32 hw_revision; u32 driver_version; - u32 topology_version; + u64 topology_version; u32 id; struct ida entity_internal_idx; -- GitLab From 88336e174645948da269e1812f138f727cd2896b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 21 Mar 2016 04:33:12 -0700 Subject: [PATCH 1563/9938] [media] media-devnode: add missing mutex lock in error handler We should protect the device unregister patch too, at the error condition. Signed-off-by: Max Kellermann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-devnode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index 29409f440f1c..64a4b1ef3dcd 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -267,8 +267,11 @@ int __must_check media_devnode_register(struct media_devnode *mdev, return 0; error: + mutex_lock(&media_devnode_lock); cdev_del(&mdev->cdev); clear_bit(mdev->minor, media_devnode_nums); + mutex_unlock(&media_devnode_lock); + return ret; } -- GitLab From bc5ccdbc990debbcae4602214dddc8d5fd38b01d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 16 Mar 2016 05:04:04 -0700 Subject: [PATCH 1564/9938] [media] au0828: Unregister notifiers If au0828 gets removed, we need to remove the notifiers. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-core.c | 38 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index cc22b32776ad..321ea5cf1329 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -131,22 +131,36 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, return status; } +#ifdef CONFIG_MEDIA_CONTROLLER +static void au0828_media_graph_notify(struct media_entity *new, + void *notify_data); +#endif + static void au0828_unregister_media_device(struct au0828_dev *dev) { - #ifdef CONFIG_MEDIA_CONTROLLER - if (dev->media_dev && - media_devnode_is_registered(&dev->media_dev->devnode)) { - /* clear enable_source, disable_source */ - dev->media_dev->source_priv = NULL; - dev->media_dev->enable_source = NULL; - dev->media_dev->disable_source = NULL; - - media_device_unregister(dev->media_dev); - media_device_cleanup(dev->media_dev); - kfree(dev->media_dev); - dev->media_dev = NULL; + struct media_device *mdev = dev->media_dev; + struct media_entity_notify *notify, *nextp; + + if (!mdev || !media_devnode_is_registered(&mdev->devnode)) + return; + + /* Remove au0828 entity_notify callbacks */ + list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list) { + if (notify->notify != au0828_media_graph_notify) + continue; + media_device_unregister_entity_notify(mdev, notify); } + + /* clear enable_source, disable_source */ + dev->media_dev->source_priv = NULL; + dev->media_dev->enable_source = NULL; + dev->media_dev->disable_source = NULL; + + media_device_unregister(dev->media_dev); + media_device_cleanup(dev->media_dev); + kfree(dev->media_dev); + dev->media_dev = NULL; #endif } -- GitLab From 4ce2bd9c4c1dfb416206ff1ad5283f6d24af4031 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 29 Mar 2016 13:53:28 +0300 Subject: [PATCH 1565/9938] cfg80211: Allow reassociation to be requested with internal SME If the user space issues a NL80211_CMD_CONNECT with NL80211_ATTR_PREV_BSSID when there is already a connection, allow this to proceed as a reassociation instead of rejecting the new connect command with EALREADY. Signed-off-by: Jouni Malinen [validate prev_bssid] Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 3 ++- net/wireless/sme.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4f89e2dbb70e..4f45a2913104 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -8151,7 +8151,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) } wdev_lock(dev->ieee80211_ptr); - err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL); + err = cfg80211_connect(rdev, dev, &connect, connkeys, + connect.prev_bssid); wdev_unlock(dev->ieee80211_ptr); if (err) kzfree(connkeys); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 65882d2777c0..1fba41676428 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -492,8 +492,18 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, if (!rdev->ops->auth || !rdev->ops->assoc) return -EOPNOTSUPP; - if (wdev->current_bss) - return -EALREADY; + if (wdev->current_bss) { + if (!prev_bssid) + return -EALREADY; + if (prev_bssid && + !ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid)) + return -ENOTCONN; + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + wdev->current_bss = NULL; + + cfg80211_sme_free(wdev); + } if (WARN_ON(wdev->conn)) return -EINPROGRESS; -- GitLab From d8e28654f28de74951ab1b7e59d2bebb442972aa Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Mon, 4 Apr 2016 22:07:39 +0000 Subject: [PATCH 1566/9938] perf config: Fix build with older toolchain. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix build error on Ubuntu 12.04.5 with GCC 4.6.3. CC util/config.o util/config.c: In function ‘perf_buildid_config’: util/config.c:384:15: error: declaration of ‘dirname’ shadows a global declaration [-Werror=shadow] Signed-off-by: Vinson Lee Cc: Alexander Shishkin Cc: Alexei Starovoitov Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Peter Zijlstra Cc: Taeung Song Cc: Wang Nan Fixes: 9cb5987c8227 ("perf config: Rework buildid_dir_command_config to perf_buildid_config") Link: http://lkml.kernel.org/r/1459807659-9020-1-git-send-email-vlee@freedesktop.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 5c20d783423b..664490b8b327 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -381,11 +381,11 @@ static int perf_buildid_config(const char *var, const char *value) { /* same dir for all commands */ if (!strcmp(var, "buildid.dir")) { - const char *dirname = perf_config_dirname(var, value); + const char *dir = perf_config_dirname(var, value); - if (!dirname) + if (!dir) return -1; - strncpy(buildid_dir, dirname, MAXPATHLEN-1); + strncpy(buildid_dir, dir, MAXPATHLEN-1); buildid_dir[MAXPATHLEN-1] = '\0'; } -- GitLab From bd0419e2a5a9fd9396cb7dc69044f961f52e19f0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 5 Apr 2016 11:33:41 -0300 Subject: [PATCH 1567/9938] perf probe: Check if dwarf_getlocations() is available If not, tell the user that: config/Makefile:273: Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157 And return -ENOTSUPP in die_get_var_range(), failing features that need it, like the one pointed out above. This fixes the build on older systems, such as Ubuntu 12.04.5. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Vinson Lee Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-9l7luqkq4gfnx7vrklkq4obs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.feature | 2 ++ tools/build/feature/Makefile | 4 ++++ tools/build/feature/test-all.c | 5 +++++ tools/build/feature/test-dwarf_getlocations.c | 12 ++++++++++++ tools/perf/config/Makefile | 6 ++++++ tools/perf/util/dwarf-aux.c | 9 +++++++++ 6 files changed, 38 insertions(+) create mode 100644 tools/build/feature/test-dwarf_getlocations.c diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 6b7707270aa3..9f878619077a 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -30,6 +30,7 @@ endef FEATURE_TESTS_BASIC := \ backtrace \ dwarf \ + dwarf_getlocations \ fortify-source \ sync-compare-and-swap \ glibc \ @@ -78,6 +79,7 @@ endif FEATURE_DISPLAY ?= \ dwarf \ + dwarf_getlocations \ glibc \ gtk2 \ libaudit \ diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index c5f4c417428d..4ae94dbfdab9 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -3,6 +3,7 @@ FILES= \ test-backtrace.bin \ test-bionic.bin \ test-dwarf.bin \ + test-dwarf_getlocations.bin \ test-fortify-source.bin \ test-sync-compare-and-swap.bin \ test-glibc.bin \ @@ -82,6 +83,9 @@ endif $(OUTPUT)test-dwarf.bin: $(BUILD) $(DWARFLIBS) +$(OUTPUT)test-dwarf_getlocations.bin: + $(BUILD) $(DWARFLIBS) + $(OUTPUT)test-libelf-mmap.bin: $(BUILD) -lelf diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c index e499a36c1e4a..a282e8cb84f3 100644 --- a/tools/build/feature/test-all.c +++ b/tools/build/feature/test-all.c @@ -41,6 +41,10 @@ # include "test-dwarf.c" #undef main +#define main main_test_dwarf_getlocations +# include "test-dwarf_getlocations.c" +#undef main + #define main main_test_libelf_getphdrnum # include "test-libelf-getphdrnum.c" #undef main @@ -143,6 +147,7 @@ int main(int argc, char *argv[]) main_test_libelf_mmap(); main_test_glibc(); main_test_dwarf(); + main_test_dwarf_getlocations(); main_test_libelf_getphdrnum(); main_test_libunwind(); main_test_libaudit(); diff --git a/tools/build/feature/test-dwarf_getlocations.c b/tools/build/feature/test-dwarf_getlocations.c new file mode 100644 index 000000000000..70162699dd43 --- /dev/null +++ b/tools/build/feature/test-dwarf_getlocations.c @@ -0,0 +1,12 @@ +#include +#include + +int main(void) +{ + Dwarf_Addr base, start, end; + Dwarf_Attribute attr; + Dwarf_Op *op; + size_t nops; + ptrdiff_t offset = 0; + return (int)dwarf_getlocations(&attr, offset, &base, &start, &end, &op, &nops); +} diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index f7d7f5a1cad5..6f8f6430f2bf 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -268,6 +268,12 @@ else ifneq ($(feature-dwarf), 1) msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); NO_DWARF := 1 + else + ifneq ($(feature-dwarf_getlocations), 1) + msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); + else + CFLAGS += -DHAVE_DWARF_GETLOCATIONS + endif # dwarf_getlocations endif # Dwarf support endif # libelf support endif # NO_LIBELF diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 577e600c8eb1..aea189b41cc8 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -959,6 +959,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) return 0; } +#ifdef HAVE_DWARF_GETLOCATIONS /** * die_get_var_innermost_scope - Get innermost scope range of given variable DIE * @sp_die: a subprogram DIE @@ -1080,3 +1081,11 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) return ret; } +#else +int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, + Dwarf_Die *vr_die __maybe_unused, + struct strbuf *buf __maybe_unused) +{ + return -ENOTSUP; +} +#endif -- GitLab From 76e20522b709f3772e415d70b108028454a86ad5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 5 Apr 2016 12:21:44 -0300 Subject: [PATCH 1568/9938] perf script perl: Do error checking on new backtrace routine This ended up triggering these warnings when building on Ubuntu 12.04.5: util/scripting-engines/trace-event-perl.c: In function 'perl_process_callchain': util/scripting-engines/trace-event-perl.c:293:4: error: value computed is not used [-Werror=unused-value] util/scripting-engines/trace-event-perl.c:294:4: error: value computed is not used [-Werror=unused-value] util/scripting-engines/trace-event-perl.c:295:4: error: value computed is not used [-Werror=unused-value] util/scripting-engines/trace-event-perl.c:297:4: error: value computed is not used [-Werror=unused-value] util/scripting-engines/trace-event-perl.c:309:4: error: value computed is not used [-Werror=unused-value] cc1: all warnings being treated as errors mv: cannot stat `/tmp/build/perf/util/scripting-engines/.trace-event-perl.o.tmp': No such file or directory make[4]: *** [/tmp/build/perf/util/scripting-engines/trace-event-perl.o] Error 1 Fix it by doing error checking when building the perl data structures related to callchains. Cc: Adrian Hunter Cc: David Ahern Cc: Dima Kogan Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Fixes: f7380c12ec6c ("perf script perl: Perl scripts now get a backtrace, like the python ones") Signed-off-by: Arnaldo Carvalho de Melo --- .../util/scripting-engines/trace-event-perl.c | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 1d160855cda9..35ed00a600fb 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -283,18 +283,27 @@ static SV *perl_process_callchain(struct perf_sample *sample, if (!elem) goto exit; - hv_stores(elem, "ip", newSVuv(node->ip)); + if (!hv_stores(elem, "ip", newSVuv(node->ip))) { + hv_undef(elem); + goto exit; + } if (node->sym) { HV *sym = newHV(); - if (!sym) + if (!sym) { + hv_undef(elem); + goto exit; + } + if (!hv_stores(sym, "start", newSVuv(node->sym->start)) || + !hv_stores(sym, "end", newSVuv(node->sym->end)) || + !hv_stores(sym, "binding", newSVuv(node->sym->binding)) || + !hv_stores(sym, "name", newSVpvn(node->sym->name, + node->sym->namelen)) || + !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) { + hv_undef(sym); + hv_undef(elem); goto exit; - hv_stores(sym, "start", newSVuv(node->sym->start)); - hv_stores(sym, "end", newSVuv(node->sym->end)); - hv_stores(sym, "binding", newSVuv(node->sym->binding)); - hv_stores(sym, "name", newSVpvn(node->sym->name, - node->sym->namelen)); - hv_stores(elem, "sym", newRV_noinc((SV*)sym)); + } } if (node->map) { @@ -306,7 +315,10 @@ static SV *perl_process_callchain(struct perf_sample *sample, else if (map->dso->name) dsoname = map->dso->name; } - hv_stores(elem, "dso", newSVpv(dsoname,0)); + if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) { + hv_undef(elem); + goto exit; + } } callchain_cursor_advance(&callchain_cursor); -- GitLab From 860b69f1d533de39fa70784768008d0eaf242e5c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 5 Apr 2016 17:01:52 +0200 Subject: [PATCH 1569/9938] perf tools: Remove superfluous ARCH Makefile includes Link: http://lkml.kernel.org/n/tip-yk6brsq3opuotr9by18xlkr8@git.kernel.org Signed-off-by: Jiri Olsa --- tools/perf/Makefile.perf | 2 -- tools/perf/config/Makefile | 3 --- 2 files changed, 5 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 000ea210389d..58aed81a21ea 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -297,8 +297,6 @@ endif # because maintaining the nesting to match is a pain. If # we had "elif" things would have been much nicer... --include arch/$(ARCH)/Makefile - ifneq ($(OUTPUT),) CFLAGS += -I$(OUTPUT) endif diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 6f8f6430f2bf..d1e2b856ef0f 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -295,9 +295,6 @@ ifndef NO_LIBELF CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT endif - # include ARCH specific config - -include $(src-perf)/arch/$(ARCH)/Makefile - ifndef NO_DWARF ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); -- GitLab From 85f8f966a152f5110a12b76511743fbfb62130ba Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 4 Apr 2016 15:58:06 -0700 Subject: [PATCH 1570/9938] perf list: Document event specifications better Document some features for specifying events in the perf list manpage: - Event groups - Leader sampling - How to specify raw PMU events in the new syntax - Global versus per process PMUs. - Access restrictions - Fix Intel SDM URL v2: Lots of new content. address review feedback. Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Link: http://lkml.kernel.org/r/1459810686-15913-1-git-send-email-andi@firstfloor.org [ Add quotes to some keywords, such as "any" ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-list.txt | 107 ++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index ec723d0a5bb3..a126e97a8114 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -93,6 +93,67 @@ raw encoding of 0x1A8 can be used: You should refer to the processor specific documentation for getting these details. Some of them are referenced in the SEE ALSO section below. +ARBITRARY PMUS +-------------- + +perf also supports an extended syntax for specifying raw parameters +to PMUs. Using this typically requires looking up the specific event +in the CPU vendor specific documentation. + +The available PMUs and their raw parameters can be listed with + + ls /sys/devices/*/format + +For example the raw event "LSD.UOPS" core pmu event above could +be specified as + + perf stat -e cpu/event=0xa8,umask=0x1,name=LSD.UOPS_CYCLES,cmask=1/ ... + +PER SOCKET PMUS +--------------- + +Some PMUs are not associated with a core, but with a whole CPU socket. +Events on these PMUs generally cannot be sampled, but only counted globally +with perf stat -a. They can be bound to one logical CPU, but will measure +all the CPUs in the same socket. + +This example measures memory bandwidth every second +on the first memory controller on socket 0 of a Intel Xeon system + + perf stat -C 0 -a uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ -I 1000 ... + +Each memory controller has its own PMU. Measuring the complete system +bandwidth would require specifying all imc PMUs (see perf list output), +and adding the values together. + +This example measures the combined core power every second + + perf stat -I 1000 -e power/energy-cores/ -a + +ACCESS RESTRICTIONS +------------------- + +For non root users generally only context switched PMU events are available. +This is normally only the events in the cpu PMU, the predefined events +like cycles and instructions and some software events. + +Other PMUs and global measurements are normally root only. +Some event qualifiers, such as "any", are also root only. + +This can be overriden by setting the kernel.perf_event_paranoid +sysctl to -1, which allows non root to use these events. + +For accessing trace point events perf needs to have read access to +/sys/kernel/debug/tracing, even when perf_event_paranoid is in a relaxed +setting. + +TRACING +------- + +Some PMUs control advanced hardware tracing capabilities, such as Intel PT, +that allows low overhead execution tracing. These are described in a separate +intel-pt.txt document. + PARAMETERIZED EVENTS -------------------- @@ -106,6 +167,50 @@ also be supplied. For example: perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... +EVENT GROUPS +------------ + +Perf supports time based multiplexing of events, when the number of events +active exceeds the number of hardware performance counters. Multiplexing +can cause measurement errors when the workload changes its execution +profile. + +When metrics are computed using formulas from event counts, it is useful to +ensure some events are always measured together as a group to minimize multiplexing +errors. Event groups can be specified using { }. + + perf stat -e '{instructions,cycles}' ... + +The number of available performance counters depend on the CPU. A group +cannot contain more events than available counters. +For example Intel Core CPUs typically have four generic performance counters +for the core, plus three fixed counters for instructions, cycles and +ref-cycles. Some special events have restrictions on which counter they +can schedule, and may not support multiple instances in a single group. +When too many events are specified in the group none of them will not +be measured. + +Globally pinned events can limit the number of counters available for +other groups. On x86 systems, the NMI watchdog pins a counter by default. +The nmi watchdog can be disabled as root with + + echo 0 > /proc/sys/kernel/nmi_watchdog + +Events from multiple different PMUs cannot be mixed in a group, with +some exceptions for software events. + +LEADER SAMPLING +--------------- + +perf also supports group leader sampling using the :S specifier. + + perf record -e '{cycles,instructions}:S' ... + perf report --group + +Normally all events in a event group sample, but with :S only +the first event (the leader) samples, and it only reads the values of the +other events in the group. + OPTIONS ------- @@ -143,5 +248,5 @@ SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-top[1], linkperf:perf-record[1], -http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide], +http://www.intel.com/sdm/[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide], http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming] -- GitLab From 6fbe99046de430bf68232e464c1aad3b3546dc1a Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Sat, 2 Apr 2016 18:25:49 +0200 Subject: [PATCH 1571/9938] ARM: imx_v6_v7_defconfig: add FT5x06 and TSC2004 touch support Those two touch controllers are used by Boundary Devices platforms. Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 978c5deeb47c..49dd8165431a 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -162,7 +162,9 @@ CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_EGALAX=y CONFIG_TOUCHSCREEN_IMX6UL_TSC=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y CONFIG_TOUCHSCREEN_MC13783=y +CONFIG_TOUCHSCREEN_TSC2004=y CONFIG_TOUCHSCREEN_TSC2007=y CONFIG_TOUCHSCREEN_STMPE=y CONFIG_TOUCHSCREEN_SX8654=y -- GitLab From e70e18d6e017755c4b635107e088f4e658db9493 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Sat, 2 Apr 2016 18:25:50 +0200 Subject: [PATCH 1572/9938] ARM: imx_v6_v7_defconfig: add CONFIG_I2C_MUX_GPIO I2C muxing is used on Nitrogen6_MAX board from Boundary Devices. Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 49dd8165431a..1faafe36e7e5 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -180,6 +180,7 @@ CONFIG_SERIAL_FSL_LPUART=y CONFIG_SERIAL_FSL_LPUART_CONSOLE=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX_GPIO=y # CONFIG_I2C_HELPER_AUTO is not set CONFIG_I2C_ALGOPCF=m CONFIG_I2C_ALGOPCA=m -- GitLab From fd84aa108a1daf2611374f31ddc3691d0ee24396 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Sat, 2 Apr 2016 18:25:51 +0200 Subject: [PATCH 1573/9938] ARM: imx_v6_v7_defconfig: add CONFIG_RTC_DRV_M41T80 The rv4168 RTC is used by the following platforms: - Nitrogen6_MAX (both Quad and Quad Plus versions) - Nitrogen7 Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 1faafe36e7e5..af22ea4170c5 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -316,6 +316,7 @@ CONFIG_RTC_DRV_DS1307=y CONFIG_RTC_DRV_ISL1208=y CONFIG_RTC_DRV_PCF8523=y CONFIG_RTC_DRV_PCF8563=y +CONFIG_RTC_DRV_M41T80=y CONFIG_RTC_DRV_MC13XXX=y CONFIG_RTC_DRV_MXC=y CONFIG_RTC_DRV_SNVS=y -- GitLab From d7e7479b215e6ba581bc5e21f43a578e07017b5a Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Sat, 26 Mar 2016 12:28:25 +0100 Subject: [PATCH 1574/9938] ARM: multi_v5_defconfig: Enable support for MX21/MX27 Although the SoC support was already enabled, the drivers and machines were missing. Signed-off-by: Jan Luebbe Acked-by: Sascha Hauer Signed-off-by: Shawn Guo --- arch/arm/configs/multi_v5_defconfig | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig index e11d99d529ee..bb8d60998b70 100644 --- a/arch/arm/configs/multi_v5_defconfig +++ b/arch/arm/configs/multi_v5_defconfig @@ -13,6 +13,11 @@ CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_MVEBU=y CONFIG_MACH_KIRKWOOD=y CONFIG_ARCH_MXC=y +CONFIG_MACH_MX21ADS=y +CONFIG_MACH_MX27ADS=y +CONFIG_MACH_MX27_3DS=y +CONFIG_MACH_IMX27_VISSTRIM_M10=y +CONFIG_MACH_PCA100=y CONFIG_MACH_IMX27_DT=y CONFIG_SOC_IMX25=y CONFIG_ARCH_ORION5X=y @@ -67,6 +72,7 @@ CONFIG_NET_PKTGEN=m CONFIG_CFG80211=y CONFIG_MAC80211=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_IMX_WEIM=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=y @@ -110,13 +116,17 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_RUNTIME_UARTS=2 CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y +CONFIG_I2C_IMX=y CONFIG_I2C_MV64XXX=y CONFIG_I2C_NOMADIK=y CONFIG_SPI=y +CONFIG_SPI_IMX=y CONFIG_SPI_ORION=y CONFIG_GPIO_SYSFS=y CONFIG_POWER_RESET=y @@ -131,10 +141,12 @@ CONFIG_THERMAL=y CONFIG_KIRKWOOD_THERMAL=y CONFIG_WATCHDOG=y CONFIG_ORION_WATCHDOG=y +CONFIG_IMX2_WDT=y # CONFIG_ABX500_CORE is not set CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_FB=y +CONFIG_FB_IMX=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y @@ -158,7 +170,6 @@ CONFIG_HID_ZEROPLUS=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_PRINTER=m CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_DATAFAB=y @@ -166,6 +177,8 @@ CONFIG_USB_STORAGE_FREECOM=y CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_HOST=y CONFIG_MMC=y CONFIG_SDIO_UART=y CONFIG_MMC_MVSDIO=y -- GitLab From 864e7a816a0646a6d9aecbd59a8e366c39b8ad2d Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:13:33 +0100 Subject: [PATCH 1575/9938] X.509: Whitespace cleanup Clean up some whitespace. Signed-off-by: David Howells --- crypto/asymmetric_keys/x509_public_key.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 733c046aacc6..2fcf707fb208 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -88,7 +88,7 @@ struct key *x509_request_asymmetric_key(struct key *keyring, lookup = skid->data; len = skid->len; } - + /* Construct an identifier "id:". */ p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); if (!req) @@ -137,7 +137,7 @@ struct key *x509_request_asymmetric_key(struct key *keyring, goto reject; } } - + pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); return key; -- GitLab From 3b764563177c1e435ef3e2608271c07955f73ea6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:13:33 +0100 Subject: [PATCH 1576/9938] KEYS: Allow authentication data to be stored in an asymmetric key Allow authentication data to be stored in an asymmetric key in the 4th element of the key payload and provide a way for it to be destroyed. For the public key subtype, this will be a public_key_signature struct. Signed-off-by: David Howells --- crypto/asymmetric_keys/asymmetric_type.c | 7 +++++-- crypto/asymmetric_keys/public_key.c | 20 ++++++++++++++------ crypto/asymmetric_keys/signature.c | 14 ++++++++++++++ crypto/asymmetric_keys/x509_cert_parser.c | 2 +- include/crypto/public_key.h | 5 ++++- include/keys/asymmetric-subtype.h | 2 +- include/keys/asymmetric-type.h | 7 ++++--- 7 files changed, 43 insertions(+), 14 deletions(-) diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 9f2165b27d52..a79d30128821 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -331,7 +331,8 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) pr_devel("==>%s()\n", __func__); if (subtype) { - subtype->destroy(prep->payload.data[asym_crypto]); + subtype->destroy(prep->payload.data[asym_crypto], + prep->payload.data[asym_auth]); module_put(subtype->owner); } asymmetric_key_free_kids(kids); @@ -346,13 +347,15 @@ static void asymmetric_key_destroy(struct key *key) struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids]; void *data = key->payload.data[asym_crypto]; + void *auth = key->payload.data[asym_auth]; key->payload.data[asym_crypto] = NULL; key->payload.data[asym_subtype] = NULL; key->payload.data[asym_key_ids] = NULL; + key->payload.data[asym_auth] = NULL; if (subtype) { - subtype->destroy(data); + subtype->destroy(data, auth); module_put(subtype->owner); } diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 0f8b264b3961..fd76b5fc3b3a 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -39,15 +39,23 @@ static void public_key_describe(const struct key *asymmetric_key, /* * Destroy a public key algorithm key. */ -void public_key_destroy(void *payload) +void public_key_free(struct public_key *key) { - struct public_key *key = payload; - - if (key) + if (key) { kfree(key->key); - kfree(key); + kfree(key); + } +} +EXPORT_SYMBOL_GPL(public_key_free); + +/* + * Destroy a public key algorithm key. + */ +static void public_key_destroy(void *payload0, void *payload3) +{ + public_key_free(payload0); + public_key_signature_free(payload3); } -EXPORT_SYMBOL_GPL(public_key_destroy); struct public_key_completion { struct completion completion; diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c index 004d5fc8e56b..3beee3976ed5 100644 --- a/crypto/asymmetric_keys/signature.c +++ b/crypto/asymmetric_keys/signature.c @@ -15,9 +15,23 @@ #include #include #include +#include #include #include "asymmetric_keys.h" +/* + * Destroy a public key signature. + */ +void public_key_signature_free(struct public_key_signature *sig) +{ + if (sig) { + kfree(sig->s); + kfree(sig->digest); + kfree(sig); + } +} +EXPORT_SYMBOL_GPL(public_key_signature_free); + /** * verify_signature - Initiate the use of an asymmetric key to verify a signature * @key: The asymmetric key to verify against diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 4a29bac70060..05251c7f9a03 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -47,7 +47,7 @@ struct x509_parse_context { void x509_free_certificate(struct x509_certificate *cert) { if (cert) { - public_key_destroy(cert->pub); + public_key_free(cert->pub); kfree(cert->issuer); kfree(cert->subject); kfree(cert->id); diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index aa730ea7faf8..19f557ca50ba 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -41,7 +41,7 @@ struct public_key { const char *pkey_algo; }; -extern void public_key_destroy(void *payload); +extern void public_key_free(struct public_key *key); /* * Public key cryptography signature data @@ -55,7 +55,10 @@ struct public_key_signature { const char *hash_algo; }; +extern void public_key_signature_free(struct public_key_signature *sig); + extern struct asymmetric_key_subtype public_key_subtype; + struct key; extern int verify_signature(const struct key *key, const struct public_key_signature *sig); diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h index 4915d40d3c3c..2480469ce8fb 100644 --- a/include/keys/asymmetric-subtype.h +++ b/include/keys/asymmetric-subtype.h @@ -32,7 +32,7 @@ struct asymmetric_key_subtype { void (*describe)(const struct key *key, struct seq_file *m); /* Destroy a key of this subtype */ - void (*destroy)(void *payload); + void (*destroy)(void *payload_crypto, void *payload_auth); /* Verify the signature on a key of this subtype (optional) */ int (*verify_signature)(const struct key *key, diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h index 59c1df9cf922..70a8775bb444 100644 --- a/include/keys/asymmetric-type.h +++ b/include/keys/asymmetric-type.h @@ -23,9 +23,10 @@ extern struct key_type key_type_asymmetric; * follows: */ enum asymmetric_payload_bits { - asym_crypto, - asym_subtype, - asym_key_ids, + asym_crypto, /* The data representing the key */ + asym_subtype, /* Pointer to an asymmetric_key_subtype struct */ + asym_key_ids, /* Pointer to an asymmetric_key_ids struct */ + asym_auth /* The key's authorisation (signature, parent key ID) */ }; /* -- GitLab From a022ec02691cf68e1fe237d5f79d54aa95446cc6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:13:33 +0100 Subject: [PATCH 1577/9938] KEYS: Add identifier pointers to public_key_signature struct Add key identifier pointers to public_key_signature struct so that they can be used to retain the identifier of the key to be used to verify the signature in both PKCS#7 and X.509. Signed-off-by: David Howells --- crypto/asymmetric_keys/signature.c | 4 ++++ include/crypto/public_key.h | 1 + 2 files changed, 5 insertions(+) diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c index 3beee3976ed5..11b7ba170904 100644 --- a/crypto/asymmetric_keys/signature.c +++ b/crypto/asymmetric_keys/signature.c @@ -24,7 +24,11 @@ */ void public_key_signature_free(struct public_key_signature *sig) { + int i; + if (sig) { + for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++) + kfree(sig->auth_ids[i]); kfree(sig->s); kfree(sig->digest); kfree(sig); diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 19f557ca50ba..2f5de5c1a3a0 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -47,6 +47,7 @@ extern void public_key_free(struct public_key *key); * Public key cryptography signature data */ struct public_key_signature { + struct asymmetric_key_id *auth_ids[2]; u8 *s; /* Signature */ u32 s_size; /* Number of bytes in signature */ u8 *digest; -- GitLab From 77d0910d153a7946df17cc15d3f423e534345f65 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:13:33 +0100 Subject: [PATCH 1578/9938] X.509: Retain the key verification data Retain the key verification data (ie. the struct public_key_signature) including the digest and the key identifiers. Note that this means that we need to take a separate copy of the digest in x509_get_sig_params() rather than lumping it in with the crypto layer data. Signed-off-by: David Howells --- crypto/asymmetric_keys/pkcs7_trust.c | 8 +-- crypto/asymmetric_keys/pkcs7_verify.c | 20 ++++---- crypto/asymmetric_keys/x509_cert_parser.c | 40 +++++++-------- crypto/asymmetric_keys/x509_parser.h | 4 +- crypto/asymmetric_keys/x509_public_key.c | 61 ++++++++++++----------- 5 files changed, 67 insertions(+), 66 deletions(-) diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 7d7a39b47c62..ed8128230dce 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -80,16 +80,16 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, might_sleep(); last = x509; - sig = &last->sig; + sig = last->sig; } /* No match - see if the root certificate has a signer amongst the * trusted keys. */ - if (last && (last->akid_id || last->akid_skid)) { + if (last && (last->sig->auth_ids[0] || last->sig->auth_ids[1])) { key = x509_request_asymmetric_key(trust_keyring, - last->akid_id, - last->akid_skid, + last->sig->auth_ids[0], + last->sig->auth_ids[1], false); if (!IS_ERR(key)) { x509 = last; diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 50be2a15e531..d8d8d234874e 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -174,6 +174,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo) { + struct public_key_signature *sig; struct x509_certificate *x509 = sinfo->signer, *p; struct asymmetric_key_id *auth; int ret; @@ -193,14 +194,15 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, goto maybe_missing_crypto_in_x509; pr_debug("- issuer %s\n", x509->issuer); - if (x509->akid_id) + sig = x509->sig; + if (sig->auth_ids[0]) pr_debug("- authkeyid.id %*phN\n", - x509->akid_id->len, x509->akid_id->data); - if (x509->akid_skid) + sig->auth_ids[0]->len, sig->auth_ids[0]->data); + if (sig->auth_ids[1]) pr_debug("- authkeyid.skid %*phN\n", - x509->akid_skid->len, x509->akid_skid->data); + sig->auth_ids[1]->len, sig->auth_ids[1]->data); - if ((!x509->akid_id && !x509->akid_skid) || + if ((!x509->sig->auth_ids[0] && !x509->sig->auth_ids[1]) || strcmp(x509->subject, x509->issuer) == 0) { /* If there's no authority certificate specified, then * the certificate must be self-signed and is the root @@ -224,7 +226,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, /* Look through the X.509 certificates in the PKCS#7 message's * list to see if the next one is there. */ - auth = x509->akid_id; + auth = sig->auth_ids[0]; if (auth) { pr_debug("- want %*phN\n", auth->len, auth->data); for (p = pkcs7->certs; p; p = p->next) { @@ -234,7 +236,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, goto found_issuer_check_skid; } } else { - auth = x509->akid_skid; + auth = sig->auth_ids[1]; pr_debug("- want %*phN\n", auth->len, auth->data); for (p = pkcs7->certs; p; p = p->next) { if (!p->skid) @@ -254,8 +256,8 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, /* We matched issuer + serialNumber, but if there's an * authKeyId.keyId, that must match the CA subjKeyId also. */ - if (x509->akid_skid && - !asymmetric_key_id_same(p->skid, x509->akid_skid)) { + if (sig->auth_ids[1] && + !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) { pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n", sinfo->index, x509->index, p->index); return -EKEYREJECTED; diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 05251c7f9a03..a2fefa713614 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -48,14 +48,11 @@ void x509_free_certificate(struct x509_certificate *cert) { if (cert) { public_key_free(cert->pub); + public_key_signature_free(cert->sig); kfree(cert->issuer); kfree(cert->subject); kfree(cert->id); kfree(cert->skid); - kfree(cert->akid_id); - kfree(cert->akid_skid); - kfree(cert->sig.digest); - kfree(cert->sig.s); kfree(cert); } } @@ -78,6 +75,9 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); if (!cert->pub) goto error_no_ctx; + cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL); + if (!cert->sig) + goto error_no_ctx; ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); if (!ctx) goto error_no_ctx; @@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, return -ENOPKG; /* Unsupported combination */ case OID_md4WithRSAEncryption: - ctx->cert->sig.hash_algo = "md4"; - ctx->cert->sig.pkey_algo = "rsa"; + ctx->cert->sig->hash_algo = "md4"; + ctx->cert->sig->pkey_algo = "rsa"; break; case OID_sha1WithRSAEncryption: - ctx->cert->sig.hash_algo = "sha1"; - ctx->cert->sig.pkey_algo = "rsa"; + ctx->cert->sig->hash_algo = "sha1"; + ctx->cert->sig->pkey_algo = "rsa"; break; case OID_sha256WithRSAEncryption: - ctx->cert->sig.hash_algo = "sha256"; - ctx->cert->sig.pkey_algo = "rsa"; + ctx->cert->sig->hash_algo = "sha256"; + ctx->cert->sig->pkey_algo = "rsa"; break; case OID_sha384WithRSAEncryption: - ctx->cert->sig.hash_algo = "sha384"; - ctx->cert->sig.pkey_algo = "rsa"; + ctx->cert->sig->hash_algo = "sha384"; + ctx->cert->sig->pkey_algo = "rsa"; break; case OID_sha512WithRSAEncryption: - ctx->cert->sig.hash_algo = "sha512"; - ctx->cert->sig.pkey_algo = "rsa"; + ctx->cert->sig->hash_algo = "sha512"; + ctx->cert->sig->pkey_algo = "rsa"; break; case OID_sha224WithRSAEncryption: - ctx->cert->sig.hash_algo = "sha224"; - ctx->cert->sig.pkey_algo = "rsa"; + ctx->cert->sig->hash_algo = "sha224"; + ctx->cert->sig->pkey_algo = "rsa"; break; } @@ -572,14 +572,14 @@ int x509_akid_note_kid(void *context, size_t hdrlen, pr_debug("AKID: keyid: %*phN\n", (int)vlen, value); - if (ctx->cert->akid_skid) + if (ctx->cert->sig->auth_ids[1]) return 0; kid = asymmetric_key_generate_id(value, vlen, "", 0); if (IS_ERR(kid)) return PTR_ERR(kid); pr_debug("authkeyid %*phN\n", kid->len, kid->data); - ctx->cert->akid_skid = kid; + ctx->cert->sig->auth_ids[1] = kid; return 0; } @@ -611,7 +611,7 @@ int x509_akid_note_serial(void *context, size_t hdrlen, pr_debug("AKID: serial: %*phN\n", (int)vlen, value); - if (!ctx->akid_raw_issuer || ctx->cert->akid_id) + if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0]) return 0; kid = asymmetric_key_generate_id(value, @@ -622,6 +622,6 @@ int x509_akid_note_serial(void *context, size_t hdrlen, return PTR_ERR(kid); pr_debug("authkeyid %*phN\n", kid->len, kid->data); - ctx->cert->akid_id = kid; + ctx->cert->sig->auth_ids[0] = kid; return 0; } diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index dbeed6018e63..26a4d83e4e6d 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -17,13 +17,11 @@ struct x509_certificate { struct x509_certificate *next; struct x509_certificate *signer; /* Certificate that signed this one */ struct public_key *pub; /* Public key details */ - struct public_key_signature sig; /* Signature parameters */ + struct public_key_signature *sig; /* Signature parameters */ char *issuer; /* Name of certificate issuer */ char *subject; /* Name of certificate subject */ struct asymmetric_key_id *id; /* Issuer + Serial number */ struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ - struct asymmetric_key_id *akid_id; /* CA AuthKeyId matching ->id (optional) */ - struct asymmetric_key_id *akid_skid; /* CA AuthKeyId matching ->skid (optional) */ time64_t valid_from; time64_t valid_to; const void *tbs; /* Signed data */ diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 2fcf707fb208..4cd102de174c 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -153,30 +153,29 @@ EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); */ int x509_get_sig_params(struct x509_certificate *cert) { + struct public_key_signature *sig = cert->sig; struct crypto_shash *tfm; struct shash_desc *desc; - size_t digest_size, desc_size; - void *digest; + size_t desc_size; int ret; pr_devel("==>%s()\n", __func__); if (cert->unsupported_crypto) return -ENOPKG; - if (cert->sig.s) + if (sig->s) return 0; - cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size, - GFP_KERNEL); - if (!cert->sig.s) + sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); + if (!sig->s) return -ENOMEM; - cert->sig.s_size = cert->raw_sig_size; + sig->s_size = cert->raw_sig_size; /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0); + tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); if (IS_ERR(tfm)) { if (PTR_ERR(tfm) == -ENOENT) { cert->unsupported_crypto = true; @@ -186,29 +185,28 @@ int x509_get_sig_params(struct x509_certificate *cert) } desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); - digest_size = crypto_shash_digestsize(tfm); + sig->digest_size = crypto_shash_digestsize(tfm); - /* We allocate the hash operational data storage on the end of the - * digest storage space. - */ ret = -ENOMEM; - digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size, - GFP_KERNEL); - if (!digest) + sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); + if (!sig->digest) goto error; - cert->sig.digest = digest; - cert->sig.digest_size = digest_size; + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) + goto error; - desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc)); desc->tfm = tfm; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ret = crypto_shash_init(desc); if (ret < 0) - goto error; + goto error_2; might_sleep(); - ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); + ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); + +error_2: + kfree(desc); error: crypto_free_shash(tfm); pr_devel("<==%s() = %d\n", __func__, ret); @@ -230,7 +228,7 @@ int x509_check_signature(const struct public_key *pub, if (ret < 0) return ret; - ret = public_key_verify_signature(pub, &cert->sig); + ret = public_key_verify_signature(pub, cert->sig); if (ret == -ENOPKG) cert->unsupported_crypto = true; pr_debug("Cert Verification: %d\n", ret); @@ -250,17 +248,18 @@ EXPORT_SYMBOL_GPL(x509_check_signature); static int x509_validate_trust(struct x509_certificate *cert, struct key *trust_keyring) { + struct public_key_signature *sig = cert->sig; struct key *key; int ret = 1; if (!trust_keyring) return -EOPNOTSUPP; - if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) + if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) return -EPERM; key = x509_request_asymmetric_key(trust_keyring, - cert->akid_id, cert->akid_skid, + sig->auth_ids[0], sig->auth_ids[1], false); if (!IS_ERR(key)) { if (!use_builtin_keys @@ -292,8 +291,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Subject: %s\n", cert->subject); if (!cert->pub->pkey_algo || - !cert->sig.pkey_algo || - !cert->sig.hash_algo) { + !cert->sig->pkey_algo || + !cert->sig->hash_algo) { ret = -ENOPKG; goto error_free_cert; } @@ -301,15 +300,15 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); pr_devel("Cert Signature: %s + %s\n", - cert->sig.pkey_algo, - cert->sig.hash_algo); + cert->sig->pkey_algo, + cert->sig->hash_algo); cert->pub->id_type = "X509"; /* Check the signature on the key if it appears to be self-signed */ - if ((!cert->akid_skid && !cert->akid_id) || - asymmetric_key_id_same(cert->skid, cert->akid_skid) || - asymmetric_key_id_same(cert->id, cert->akid_id)) { + if ((!cert->sig->auth_ids[0] && !cert->sig->auth_ids[1]) || + asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]) || + asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0])) { ret = x509_check_signature(cert->pub, cert); /* self-signed */ if (ret < 0) goto error_free_cert; @@ -353,6 +352,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) prep->payload.data[asym_subtype] = &public_key_subtype; prep->payload.data[asym_key_ids] = kids; prep->payload.data[asym_crypto] = cert->pub; + prep->payload.data[asym_auth] = cert->sig; prep->description = desc; prep->quotalen = 100; @@ -360,6 +360,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) cert->pub = NULL; cert->id = NULL; cert->skid = NULL; + cert->sig = NULL; desc = NULL; ret = 0; -- GitLab From 566a117a8b24e1ae2dfa817cf0c9eec092c783b5 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:13:33 +0100 Subject: [PATCH 1579/9938] PKCS#7: Make the signature a pointer rather than embedding it Point to the public_key_signature struct from the pkcs7_signed_info struct rather than embedding it. This makes the code consistent with the X.509 signature handling and makes it possible to have a common cleanup function. We also save a copy of the digest in the signature without sharing the memory with the crypto layer metadata. Signed-off-by: David Howells --- crypto/asymmetric_keys/pkcs7_parser.c | 38 ++++++++++++-------- crypto/asymmetric_keys/pkcs7_parser.h | 10 +++--- crypto/asymmetric_keys/pkcs7_trust.c | 4 +-- crypto/asymmetric_keys/pkcs7_verify.c | 51 ++++++++++++++------------- 4 files changed, 55 insertions(+), 48 deletions(-) diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 40de03f49ff8..835701613125 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -44,9 +44,7 @@ struct pkcs7_parse_context { static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) { if (sinfo) { - kfree(sinfo->sig.s); - kfree(sinfo->sig.digest); - kfree(sinfo->signing_cert_id); + public_key_signature_free(sinfo->sig); kfree(sinfo); } } @@ -125,6 +123,10 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); if (!ctx->sinfo) goto out_no_sinfo; + ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature), + GFP_KERNEL); + if (!ctx->sinfo->sig) + goto out_no_sig; ctx->data = (unsigned long)data; ctx->ppcerts = &ctx->certs; @@ -150,6 +152,7 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) ctx->certs = cert->next; x509_free_certificate(cert); } +out_no_sig: pkcs7_free_signed_info(ctx->sinfo); out_no_sinfo: pkcs7_free_message(ctx->msg); @@ -218,25 +221,26 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, switch (ctx->last_oid) { case OID_md4: - ctx->sinfo->sig.hash_algo = "md4"; + ctx->sinfo->sig->hash_algo = "md4"; break; case OID_md5: - ctx->sinfo->sig.hash_algo = "md5"; + ctx->sinfo->sig->hash_algo = "md5"; break; case OID_sha1: - ctx->sinfo->sig.hash_algo = "sha1"; + ctx->sinfo->sig->hash_algo = "sha1"; break; case OID_sha256: - ctx->sinfo->sig.hash_algo = "sha256"; + ctx->sinfo->sig->hash_algo = "sha256"; break; case OID_sha384: - ctx->sinfo->sig.hash_algo = "sha384"; + ctx->sinfo->sig->hash_algo = "sha384"; break; case OID_sha512: - ctx->sinfo->sig.hash_algo = "sha512"; + ctx->sinfo->sig->hash_algo = "sha512"; break; case OID_sha224: - ctx->sinfo->sig.hash_algo = "sha224"; + ctx->sinfo->sig->hash_algo = "sha224"; + break; default: printk("Unsupported digest algo: %u\n", ctx->last_oid); return -ENOPKG; @@ -255,7 +259,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, switch (ctx->last_oid) { case OID_rsaEncryption: - ctx->sinfo->sig.pkey_algo = "rsa"; + ctx->sinfo->sig->pkey_algo = "rsa"; break; default: printk("Unsupported pkey algo: %u\n", ctx->last_oid); @@ -615,11 +619,11 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen, { struct pkcs7_parse_context *ctx = context; - ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL); - if (!ctx->sinfo->sig.s) + ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL); + if (!ctx->sinfo->sig->s) return -ENOMEM; - ctx->sinfo->sig.s_size = vlen; + ctx->sinfo->sig->s_size = vlen; return 0; } @@ -655,12 +659,16 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen, pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data); - sinfo->signing_cert_id = kid; + sinfo->sig->auth_ids[0] = kid; sinfo->index = ++ctx->sinfo_index; *ctx->ppsinfo = sinfo; ctx->ppsinfo = &sinfo->next; ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); if (!ctx->sinfo) return -ENOMEM; + ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature), + GFP_KERNEL); + if (!ctx->sinfo->sig) + return -ENOMEM; return 0; } diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h index a66b19ebcf47..d5eec31e95b6 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h @@ -41,19 +41,17 @@ struct pkcs7_signed_info { #define sinfo_has_ms_statement_type 5 time64_t signing_time; - /* Issuing cert serial number and issuer's name [PKCS#7 or CMS ver 1] - * or issuing cert's SKID [CMS ver 3]. - */ - struct asymmetric_key_id *signing_cert_id; - /* Message signature. * * This contains the generated digest of _either_ the Content Data or * the Authenticated Attributes [RFC2315 9.3]. If the latter, one of * the attributes contains the digest of the the Content Data within * it. + * + * THis also contains the issuing cert serial number and issuer's name + * [PKCS#7 or CMS ver 1] or issuing cert's SKID [CMS ver 3]. */ - struct public_key_signature sig; + struct public_key_signature *sig; }; struct pkcs7_message { diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index ed8128230dce..b9a5487cd82d 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -27,7 +27,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo, struct key *trust_keyring) { - struct public_key_signature *sig = &sinfo->sig; + struct public_key_signature *sig = sinfo->sig; struct x509_certificate *x509, *last = NULL, *p; struct key *key; bool trusted; @@ -105,7 +105,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, * the signed info directly. */ key = x509_request_asymmetric_key(trust_keyring, - sinfo->signing_cert_id, + sinfo->sig->auth_ids[0], NULL, false); if (!IS_ERR(key)) { diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index d8d8d234874e..1426f03e630b 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -25,34 +25,36 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo) { + struct public_key_signature *sig = sinfo->sig; struct crypto_shash *tfm; struct shash_desc *desc; - size_t digest_size, desc_size; - void *digest; + size_t desc_size; int ret; - kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo); + kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); - if (!sinfo->sig.hash_algo) + if (!sinfo->sig->hash_algo) return -ENOPKG; /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0); + tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); - sinfo->sig.digest_size = digest_size = crypto_shash_digestsize(tfm); + sig->digest_size = crypto_shash_digestsize(tfm); ret = -ENOMEM; - digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size, - GFP_KERNEL); - if (!digest) + sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); + if (!sig->digest) + goto error_no_desc; + + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) goto error_no_desc; - desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc)); desc->tfm = tfm; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; @@ -60,10 +62,11 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, ret = crypto_shash_init(desc); if (ret < 0) goto error; - ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, digest); + ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, + sig->digest); if (ret < 0) goto error; - pr_devel("MsgDigest = [%*ph]\n", 8, digest); + pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest); /* However, if there are authenticated attributes, there must be a * message digest attribute amongst them which corresponds to the @@ -78,14 +81,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, goto error; } - if (sinfo->msgdigest_len != sinfo->sig.digest_size) { + if (sinfo->msgdigest_len != sig->digest_size) { pr_debug("Sig %u: Invalid digest size (%u)\n", sinfo->index, sinfo->msgdigest_len); ret = -EBADMSG; goto error; } - if (memcmp(digest, sinfo->msgdigest, sinfo->msgdigest_len) != 0) { + if (memcmp(sig->digest, sinfo->msgdigest, + sinfo->msgdigest_len) != 0) { pr_debug("Sig %u: Message digest doesn't match\n", sinfo->index); ret = -EKEYREJECTED; @@ -97,7 +101,7 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, * convert the attributes from a CONT.0 into a SET before we * hash it. */ - memset(digest, 0, sinfo->sig.digest_size); + memset(sig->digest, 0, sig->digest_size); ret = crypto_shash_init(desc); if (ret < 0) @@ -107,17 +111,14 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, if (ret < 0) goto error; ret = crypto_shash_finup(desc, sinfo->authattrs, - sinfo->authattrs_len, digest); + sinfo->authattrs_len, sig->digest); if (ret < 0) goto error; - pr_devel("AADigest = [%*ph]\n", 8, digest); + pr_devel("AADigest = [%*ph]\n", 8, sig->digest); } - sinfo->sig.digest = digest; - digest = NULL; - error: - kfree(digest); + kfree(desc); error_no_desc: crypto_free_shash(tfm); kleave(" = %d", ret); @@ -144,12 +145,12 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, * PKCS#7 message - but I can't be 100% sure of that. It's * possible this will need element-by-element comparison. */ - if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id)) + if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0])) continue; pr_devel("Sig %u: Found cert serial match X.509[%u]\n", sinfo->index, certix); - if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) { + if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) { pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", sinfo->index); continue; @@ -164,7 +165,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, */ pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", sinfo->index, - sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); + sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data); return 0; } @@ -334,7 +335,7 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, } /* Verify the PKCS#7 binary against the key */ - ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig); + ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig); if (ret < 0) return ret; -- GitLab From 6c2dc5ae4ab719a61d19e8cef082226410b04ff8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:13:34 +0100 Subject: [PATCH 1580/9938] X.509: Extract signature digest and make self-signed cert checks earlier Extract the signature digest for an X.509 certificate earlier, at the end of x509_cert_parse() rather than leaving it to the callers thereof since it has to be called anyway. Further, immediately after that, check the signature on self-signed certificates, also rather in the callers of x509_cert_parse(). We note in the x509_certificate struct the following bits of information: (1) Whether the signature is self-signed (even if we can't check the signature due to missing crypto). (2) Whether the key held in the certificate needs unsupported crypto to be used. We may get a PKCS#7 message with X.509 certs that we can't make use of - we just ignore them and give ENOPKG at the end it we couldn't verify anything if at least one of these unusable certs are in the chain of trust. (3) Whether the signature held in the certificate needs unsupported crypto to be checked. We can still use the key held in this certificate, even if we can't check the signature on it - if it is held in the system trusted keyring, for instance. We just can't add it to a ring of trusted keys or follow it further up the chain of trust. Making these checks earlier allows x509_check_signature() to be removed and replaced with direct calls to public_key_verify_signature(). Signed-off-by: David Howells --- crypto/asymmetric_keys/pkcs7_verify.c | 38 ++----- crypto/asymmetric_keys/x509_cert_parser.c | 10 ++ crypto/asymmetric_keys/x509_parser.h | 7 +- crypto/asymmetric_keys/x509_public_key.c | 126 +++++++++++++++------- 4 files changed, 110 insertions(+), 71 deletions(-) diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 1426f03e630b..44b746e9df1b 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -190,9 +190,8 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, x509->subject, x509->raw_serial_size, x509->raw_serial); x509->seen = true; - ret = x509_get_sig_params(x509); - if (ret < 0) - goto maybe_missing_crypto_in_x509; + if (x509->unsupported_key) + goto unsupported_crypto_in_x509; pr_debug("- issuer %s\n", x509->issuer); sig = x509->sig; @@ -203,22 +202,14 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, pr_debug("- authkeyid.skid %*phN\n", sig->auth_ids[1]->len, sig->auth_ids[1]->data); - if ((!x509->sig->auth_ids[0] && !x509->sig->auth_ids[1]) || - strcmp(x509->subject, x509->issuer) == 0) { + if (x509->self_signed) { /* If there's no authority certificate specified, then * the certificate must be self-signed and is the root * of the chain. Likewise if the cert is its own * authority. */ - pr_debug("- no auth?\n"); - if (x509->raw_subject_size != x509->raw_issuer_size || - memcmp(x509->raw_subject, x509->raw_issuer, - x509->raw_issuer_size) != 0) - return 0; - - ret = x509_check_signature(x509->pub, x509); - if (ret < 0) - goto maybe_missing_crypto_in_x509; + if (x509->unsupported_sig) + goto unsupported_crypto_in_x509; x509->signer = x509; pr_debug("- self-signed\n"); return 0; @@ -270,7 +261,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, sinfo->index); return 0; } - ret = x509_check_signature(p->pub, x509); + ret = public_key_verify_signature(p->pub, p->sig); if (ret < 0) return ret; x509->signer = p; @@ -282,16 +273,14 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, might_sleep(); } -maybe_missing_crypto_in_x509: +unsupported_crypto_in_x509: /* Just prune the certificate chain at this point if we lack some * crypto module to go further. Note, however, we don't want to set - * sinfo->missing_crypto as the signed info block may still be + * sinfo->unsupported_crypto as the signed info block may still be * validatable against an X.509 cert lower in the chain that we have a * trusted copy of. */ - if (ret == -ENOPKG) - return 0; - return ret; + return 0; } /* @@ -378,9 +367,8 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, enum key_being_used_for usage) { struct pkcs7_signed_info *sinfo; - struct x509_certificate *x509; int enopkg = -ENOPKG; - int ret, n; + int ret; kenter(""); @@ -422,12 +410,6 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, return -EINVAL; } - for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) { - ret = x509_get_sig_params(x509); - if (ret < 0) - return ret; - } - for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { ret = pkcs7_verify_one(pkcs7, sinfo); if (ret < 0) { diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index a2fefa713614..865f46ea724f 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -108,6 +108,11 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) cert->pub->keylen = ctx->key_size; + /* Grab the signature bits */ + ret = x509_get_sig_params(cert); + if (ret < 0) + goto error_decode; + /* Generate cert issuer + serial number key ID */ kid = asymmetric_key_generate_id(cert->raw_serial, cert->raw_serial_size, @@ -119,6 +124,11 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) } cert->id = kid; + /* Detect self-signed certificates */ + ret = x509_check_for_self_signed(cert); + if (ret < 0) + goto error_decode; + kfree(ctx); return cert; diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 26a4d83e4e6d..f24f4d808e7f 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -40,7 +40,9 @@ struct x509_certificate { bool seen; /* Infinite recursion prevention */ bool verified; bool trusted; - bool unsupported_crypto; /* T if can't be verified due to missing crypto */ + bool self_signed; /* T if self-signed (check unsupported_sig too) */ + bool unsupported_key; /* T if key uses unsupported crypto */ + bool unsupported_sig; /* T if signature uses unsupported crypto */ }; /* @@ -56,5 +58,4 @@ extern int x509_decode_time(time64_t *_t, size_t hdrlen, * x509_public_key.c */ extern int x509_get_sig_params(struct x509_certificate *cert); -extern int x509_check_signature(const struct public_key *pub, - struct x509_certificate *cert); +extern int x509_check_for_self_signed(struct x509_certificate *cert); diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 4cd102de174c..752d8d5b48fa 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -161,10 +161,17 @@ int x509_get_sig_params(struct x509_certificate *cert) pr_devel("==>%s()\n", __func__); - if (cert->unsupported_crypto) - return -ENOPKG; - if (sig->s) + if (!cert->pub->pkey_algo) + cert->unsupported_key = true; + + if (!sig->pkey_algo) + cert->unsupported_sig = true; + + /* We check the hash if we can - even if we can't then verify it */ + if (!sig->hash_algo) { + cert->unsupported_sig = true; return 0; + } sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); if (!sig->s) @@ -178,8 +185,8 @@ int x509_get_sig_params(struct x509_certificate *cert) tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); if (IS_ERR(tfm)) { if (PTR_ERR(tfm) == -ENOENT) { - cert->unsupported_crypto = true; - return -ENOPKG; + cert->unsupported_sig = true; + return 0; } return PTR_ERR(tfm); } @@ -212,29 +219,53 @@ int x509_get_sig_params(struct x509_certificate *cert) pr_devel("<==%s() = %d\n", __func__, ret); return ret; } -EXPORT_SYMBOL_GPL(x509_get_sig_params); /* - * Check the signature on a certificate using the provided public key + * Check for self-signedness in an X.509 cert and if found, check the signature + * immediately if we can. */ -int x509_check_signature(const struct public_key *pub, - struct x509_certificate *cert) +int x509_check_for_self_signed(struct x509_certificate *cert) { - int ret; + int ret = 0; pr_devel("==>%s()\n", __func__); - ret = x509_get_sig_params(cert); - if (ret < 0) - return ret; + if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) { + /* If the AKID is present it may have one or two parts. If + * both are supplied, both must match. + */ + bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]); + bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]); + + if (!a && !b) + goto not_self_signed; + + ret = -EKEYREJECTED; + if (((a && !b) || (b && !a)) && + cert->sig->auth_ids[0] && cert->sig->auth_ids[1]) + goto out; + } + + ret = public_key_verify_signature(cert->pub, cert->sig); + if (ret < 0) { + if (ret == -ENOPKG) { + cert->unsupported_sig = true; + ret = 0; + } + goto out; + } + + pr_devel("Cert Self-signature verified"); + cert->self_signed = true; - ret = public_key_verify_signature(pub, cert->sig); - if (ret == -ENOPKG) - cert->unsupported_crypto = true; - pr_debug("Cert Verification: %d\n", ret); +out: + pr_devel("<==%s() = %d\n", __func__, ret); return ret; + +not_self_signed: + pr_devel("<==%s() = 0 [not]\n", __func__); + return 0; } -EXPORT_SYMBOL_GPL(x509_check_signature); /* * Check the new certificate against the ones in the trust keyring. If one of @@ -252,22 +283,30 @@ static int x509_validate_trust(struct x509_certificate *cert, struct key *key; int ret = 1; + if (!sig->auth_ids[0] && !sig->auth_ids[1]) + return 1; + if (!trust_keyring) return -EOPNOTSUPP; - if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) return -EPERM; + if (cert->unsupported_sig) + return -ENOPKG; key = x509_request_asymmetric_key(trust_keyring, sig->auth_ids[0], sig->auth_ids[1], false); - if (!IS_ERR(key)) { - if (!use_builtin_keys - || test_bit(KEY_FLAG_BUILTIN, &key->flags)) - ret = x509_check_signature(key->payload.data[asym_crypto], - cert); - key_put(key); + if (IS_ERR(key)) + return PTR_ERR(key); + + if (!use_builtin_keys || + test_bit(KEY_FLAG_BUILTIN, &key->flags)) { + ret = public_key_verify_signature( + key->payload.data[asym_crypto], cert->sig); + if (ret == -ENOPKG) + cert->unsupported_sig = true; } + key_put(key); return ret; } @@ -290,34 +329,41 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Issuer: %s\n", cert->issuer); pr_devel("Cert Subject: %s\n", cert->subject); - if (!cert->pub->pkey_algo || - !cert->sig->pkey_algo || - !cert->sig->hash_algo) { + if (cert->unsupported_key) { ret = -ENOPKG; goto error_free_cert; } pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); - pr_devel("Cert Signature: %s + %s\n", - cert->sig->pkey_algo, - cert->sig->hash_algo); cert->pub->id_type = "X509"; - /* Check the signature on the key if it appears to be self-signed */ - if ((!cert->sig->auth_ids[0] && !cert->sig->auth_ids[1]) || - asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]) || - asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0])) { - ret = x509_check_signature(cert->pub, cert); /* self-signed */ - if (ret < 0) - goto error_free_cert; - } else if (!prep->trusted) { + /* See if we can derive the trustability of this certificate. + * + * When it comes to self-signed certificates, we cannot evaluate + * trustedness except by the fact that we obtained it from a trusted + * location. So we just rely on x509_validate_trust() failing in this + * case. + * + * Note that there's a possibility of a self-signed cert matching a + * cert that we have (most likely a duplicate that we already trust) - + * in which case it will be marked trusted. + */ + if (cert->unsupported_sig || cert->self_signed) { + public_key_signature_free(cert->sig); + cert->sig = NULL; + } else { + pr_devel("Cert Signature: %s + %s\n", + cert->sig->pkey_algo, cert->sig->hash_algo); + ret = x509_validate_trust(cert, get_system_trusted_keyring()); if (ret) ret = x509_validate_trust(cert, get_ima_mok_keyring()); + if (ret == -EKEYREJECTED) + goto error_free_cert; if (!ret) - prep->trusted = 1; + prep->trusted = true; } /* Propose a description */ -- GitLab From ad3043fda39db0361d9601685356db4512e914be Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:13:34 +0100 Subject: [PATCH 1581/9938] X.509: Fix self-signed determination There's a bug in the code determining whether a certificate is self-signed or not: if they have neither AKID nor SKID then we just assume that the cert is self-signed, which may not be true. Fix this by checking that the raw subject name matches the raw issuer name and that the public key algorithm for the key and signature are both the same in addition to requiring that the AKID bits match. Signed-off-by: David Howells --- crypto/asymmetric_keys/x509_public_key.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 752d8d5b48fa..fc77a2bd70ba 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -230,6 +230,11 @@ int x509_check_for_self_signed(struct x509_certificate *cert) pr_devel("==>%s()\n", __func__); + if (cert->raw_subject_size != cert->raw_issuer_size || + memcmp(cert->raw_subject, cert->raw_issuer, + cert->raw_issuer_size) != 0) + goto not_self_signed; + if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) { /* If the AKID is present it may have one or two parts. If * both are supplied, both must match. @@ -246,6 +251,10 @@ int x509_check_for_self_signed(struct x509_certificate *cert) goto out; } + ret = -EKEYREJECTED; + if (cert->pub->pkey_algo != cert->sig->pkey_algo) + goto out; + ret = public_key_verify_signature(cert->pub, cert->sig); if (ret < 0) { if (ret == -ENOPKG) { -- GitLab From e68503bd6836ba765dc8e0ee77ea675fedc07e41 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:24 +0100 Subject: [PATCH 1582/9938] KEYS: Generalise system_verify_data() to provide access to internal content Generalise system_verify_data() to provide access to internal content through a callback. This allows all the PKCS#7 stuff to be hidden inside this function and removed from the PE file parser and the PKCS#7 test key. If external content is not required, NULL should be passed as data to the function. If the callback is not required, that can be set to NULL. The function is now called verify_pkcs7_signature() to contrast with verify_pefile_signature() and the definitions of both have been moved into linux/verification.h along with the key_being_used_for enum. Signed-off-by: David Howells --- arch/x86/kernel/kexec-bzimage64.c | 18 ++----- certs/system_keyring.c | 45 ++++++++++++---- crypto/asymmetric_keys/Kconfig | 4 +- crypto/asymmetric_keys/mscode_parser.c | 21 +++----- crypto/asymmetric_keys/pkcs7_key_type.c | 72 ++++++++++--------------- crypto/asymmetric_keys/pkcs7_parser.c | 21 ++++---- crypto/asymmetric_keys/verify_pefile.c | 40 ++++---------- crypto/asymmetric_keys/verify_pefile.h | 5 +- include/crypto/pkcs7.h | 3 +- include/crypto/public_key.h | 14 ----- include/keys/asymmetric-type.h | 1 + include/keys/system_keyring.h | 7 +-- include/linux/verification.h | 50 +++++++++++++++++ include/linux/verify_pefile.h | 22 -------- kernel/module_signing.c | 5 +- 15 files changed, 155 insertions(+), 173 deletions(-) create mode 100644 include/linux/verification.h delete mode 100644 include/linux/verify_pefile.h diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index 2af478e3fd4e..f2356bda2b05 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -19,8 +19,7 @@ #include #include #include -#include -#include +#include #include #include @@ -529,18 +528,9 @@ static int bzImage64_cleanup(void *loader_data) #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len) { - bool trusted; - int ret; - - ret = verify_pefile_signature(kernel, kernel_len, - system_trusted_keyring, - VERIFYING_KEXEC_PE_SIGNATURE, - &trusted); - if (ret < 0) - return ret; - if (!trusted) - return -EKEYREJECTED; - return 0; + return verify_pefile_signature(kernel, kernel_len, + NULL, + VERIFYING_KEXEC_PE_SIGNATURE); } #endif diff --git a/certs/system_keyring.c b/certs/system_keyring.c index f4180326c2e1..a83bffedc0aa 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -108,16 +108,25 @@ late_initcall(load_system_certificate_list); #ifdef CONFIG_SYSTEM_DATA_VERIFICATION /** - * Verify a PKCS#7-based signature on system data. - * @data: The data to be verified. + * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data. + * @data: The data to be verified (NULL if expecting internal data). * @len: Size of @data. * @raw_pkcs7: The PKCS#7 message that is the signature. * @pkcs7_len: The size of @raw_pkcs7. + * @trusted_keys: Trusted keys to use (NULL for system_trusted_keyring). * @usage: The use to which the key is being put. + * @view_content: Callback to gain access to content. + * @ctx: Context for callback. */ -int system_verify_data(const void *data, unsigned long len, - const void *raw_pkcs7, size_t pkcs7_len, - enum key_being_used_for usage) +int verify_pkcs7_signature(const void *data, size_t len, + const void *raw_pkcs7, size_t pkcs7_len, + struct key *trusted_keys, + int untrusted_error, + enum key_being_used_for usage, + int (*view_content)(void *ctx, + const void *data, size_t len, + size_t asn1hdrlen), + void *ctx) { struct pkcs7_message *pkcs7; bool trusted; @@ -128,7 +137,7 @@ int system_verify_data(const void *data, unsigned long len, return PTR_ERR(pkcs7); /* The data should be detached - so we need to supply it. */ - if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) { + if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) { pr_err("PKCS#7 signature with non-detached data\n"); ret = -EBADMSG; goto error; @@ -138,13 +147,29 @@ int system_verify_data(const void *data, unsigned long len, if (ret < 0) goto error; - ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); + if (!trusted_keys) + trusted_keys = system_trusted_keyring; + ret = pkcs7_validate_trust(pkcs7, trusted_keys, &trusted); if (ret < 0) goto error; - if (!trusted) { + if (!trusted && untrusted_error) { pr_err("PKCS#7 signature not signed with a trusted key\n"); - ret = -ENOKEY; + ret = untrusted_error; + goto error; + } + + if (view_content) { + size_t asn1hdrlen; + + ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen); + if (ret < 0) { + if (ret == -ENODATA) + pr_devel("PKCS#7 message does not contain data\n"); + goto error; + } + + ret = view_content(ctx, data, len, asn1hdrlen); } error: @@ -152,6 +177,6 @@ int system_verify_data(const void *data, unsigned long len, pr_devel("<==%s() = %d\n", __func__, ret); return ret; } -EXPORT_SYMBOL_GPL(system_verify_data); +EXPORT_SYMBOL_GPL(verify_pkcs7_signature); #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 91a7e047a765..f7d2ef9789d8 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -40,8 +40,7 @@ config PKCS7_MESSAGE_PARSER config PKCS7_TEST_KEY tristate "PKCS#7 testing key type" - depends on PKCS7_MESSAGE_PARSER - select SYSTEM_TRUSTED_KEYRING + depends on SYSTEM_DATA_VERIFICATION help This option provides a type of key that can be loaded up from a PKCS#7 message - provided the message is signed by a trusted key. If @@ -54,6 +53,7 @@ config PKCS7_TEST_KEY config SIGNED_PE_FILE_VERIFICATION bool "Support for PE file signature verification" depends on PKCS7_MESSAGE_PARSER=y + depends on SYSTEM_DATA_VERIFICATION select ASN1 select OID_REGISTRY help diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c index 3242cbfaeaa2..6a76d5c70ef6 100644 --- a/crypto/asymmetric_keys/mscode_parser.c +++ b/crypto/asymmetric_keys/mscode_parser.c @@ -21,19 +21,13 @@ /* * Parse a Microsoft Individual Code Signing blob */ -int mscode_parse(struct pefile_context *ctx) +int mscode_parse(void *_ctx, const void *content_data, size_t data_len, + size_t asn1hdrlen) { - const void *content_data; - size_t data_len; - int ret; - - ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1); - - if (ret) { - pr_debug("PKCS#7 message does not contain data\n"); - return ret; - } + struct pefile_context *ctx = _ctx; + content_data -= asn1hdrlen; + data_len += asn1hdrlen; pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len), content_data); @@ -129,7 +123,6 @@ int mscode_note_digest(void *context, size_t hdrlen, { struct pefile_context *ctx = context; - ctx->digest = value; - ctx->digest_len = vlen; - return 0; + ctx->digest = kmemdup(value, vlen, GFP_KERNEL); + return ctx->digest ? 0 : -ENOMEM; } diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c index e2d0edbbc71a..ab9bf5363ecd 100644 --- a/crypto/asymmetric_keys/pkcs7_key_type.c +++ b/crypto/asymmetric_keys/pkcs7_key_type.c @@ -13,12 +13,9 @@ #include #include #include +#include #include -#include -#include #include -#include -#include "pkcs7_parser.h" MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("PKCS#7 testing key type"); @@ -29,59 +26,46 @@ MODULE_PARM_DESC(pkcs7_usage, "Usage to specify when verifying the PKCS#7 message"); /* - * Preparse a PKCS#7 wrapped and validated data blob. + * Retrieve the PKCS#7 message content. */ -static int pkcs7_preparse(struct key_preparsed_payload *prep) +static int pkcs7_view_content(void *ctx, const void *data, size_t len, + size_t asn1hdrlen) { - enum key_being_used_for usage = pkcs7_usage; - struct pkcs7_message *pkcs7; - const void *data, *saved_prep_data; - size_t datalen, saved_prep_datalen; - bool trusted; + struct key_preparsed_payload *prep = ctx; + const void *saved_prep_data; + size_t saved_prep_datalen; int ret; - kenter(""); - - if (usage >= NR__KEY_BEING_USED_FOR) { - pr_err("Invalid usage type %d\n", usage); - return -EINVAL; - } - saved_prep_data = prep->data; saved_prep_datalen = prep->datalen; - pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen); - if (IS_ERR(pkcs7)) { - ret = PTR_ERR(pkcs7); - goto error; - } - - ret = pkcs7_verify(pkcs7, usage); - if (ret < 0) - goto error_free; - - ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); - if (ret < 0) - goto error_free; - if (!trusted) - pr_warn("PKCS#7 message doesn't chain back to a trusted key\n"); - - ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false); - if (ret < 0) - goto error_free; - prep->data = data; - prep->datalen = datalen; + prep->datalen = len; + ret = user_preparse(prep); + prep->data = saved_prep_data; prep->datalen = saved_prep_datalen; - -error_free: - pkcs7_free_message(pkcs7); -error: - kleave(" = %d", ret); return ret; } +/* + * Preparse a PKCS#7 wrapped and validated data blob. + */ +static int pkcs7_preparse(struct key_preparsed_payload *prep) +{ + enum key_being_used_for usage = pkcs7_usage; + + if (usage >= NR__KEY_BEING_USED_FOR) { + pr_err("Invalid usage type %d\n", usage); + return -EINVAL; + } + + return verify_pkcs7_signature(NULL, 0, + prep->data, prep->datalen, + NULL, -ENOKEY, usage, + pkcs7_view_content, prep); +} + /* * user defined keys take an arbitrary string as the description and an * arbitrary blob of data as the payload diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 835701613125..af4cd8649117 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -168,24 +168,25 @@ EXPORT_SYMBOL_GPL(pkcs7_parse_message); * @pkcs7: The preparsed PKCS#7 message to access * @_data: Place to return a pointer to the data * @_data_len: Place to return the data length - * @want_wrapper: True if the ASN.1 object header should be included in the data + * @_headerlen: Size of ASN.1 header not included in _data * - * Get access to the data content of the PKCS#7 message, including, optionally, - * the header of the ASN.1 object that contains it. Returns -ENODATA if the - * data object was missing from the message. + * Get access to the data content of the PKCS#7 message. The size of the + * header of the ASN.1 object that contains it is also provided and can be used + * to adjust *_data and *_data_len to get the entire object. + * + * Returns -ENODATA if the data object was missing from the message. */ int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, const void **_data, size_t *_data_len, - bool want_wrapper) + size_t *_headerlen) { - size_t wrapper; - if (!pkcs7->data) return -ENODATA; - wrapper = want_wrapper ? pkcs7->data_hdrlen : 0; - *_data = pkcs7->data - wrapper; - *_data_len = pkcs7->data_len + wrapper; + *_data = pkcs7->data; + *_data_len = pkcs7->data_len; + if (_headerlen) + *_headerlen = pkcs7->data_hdrlen; return 0; } EXPORT_SYMBOL_GPL(pkcs7_get_content_data); diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 7e8c2338ae25..265351075b0e 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include "verify_pefile.h" @@ -392,9 +392,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, * verify_pefile_signature - Verify the signature on a PE binary image * @pebuf: Buffer containing the PE binary image * @pelen: Length of the binary image - * @trust_keyring: Signing certificates to use as starting points + * @trust_keys: Signing certificate(s) to use as starting points * @usage: The use to which the key is being put. - * @_trusted: Set to true if trustworth, false otherwise * * Validate that the certificate chain inside the PKCS#7 message inside the PE * binary image intersects keys we already know and trust. @@ -418,14 +417,10 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, * May also return -ENOMEM. */ int verify_pefile_signature(const void *pebuf, unsigned pelen, - struct key *trusted_keyring, - enum key_being_used_for usage, - bool *_trusted) + struct key *trusted_keys, + enum key_being_used_for usage) { - struct pkcs7_message *pkcs7; struct pefile_context ctx; - const void *data; - size_t datalen; int ret; kenter(""); @@ -439,19 +434,10 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, if (ret < 0) return ret; - pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len); - if (IS_ERR(pkcs7)) - return PTR_ERR(pkcs7); - ctx.pkcs7 = pkcs7; - - ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false); - if (ret < 0 || datalen == 0) { - pr_devel("PKCS#7 message does not contain data\n"); - ret = -EBADMSG; - goto error; - } - - ret = mscode_parse(&ctx); + ret = verify_pkcs7_signature(NULL, 0, + pebuf + ctx.sig_offset, ctx.sig_len, + trusted_keys, -EKEYREJECTED, usage, + mscode_parse, &ctx); if (ret < 0) goto error; @@ -462,16 +448,8 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, * contents. */ ret = pefile_digest_pe(pebuf, pelen, &ctx); - if (ret < 0) - goto error; - - ret = pkcs7_verify(pkcs7, usage); - if (ret < 0) - goto error; - - ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted); error: - pkcs7_free_message(ctx.pkcs7); + kfree(ctx.digest); return ret; } diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h index a133eb81a492..cd4d20930728 100644 --- a/crypto/asymmetric_keys/verify_pefile.h +++ b/crypto/asymmetric_keys/verify_pefile.h @@ -9,7 +9,6 @@ * 2 of the Licence, or (at your option) any later version. */ -#include #include #include @@ -23,7 +22,6 @@ struct pefile_context { unsigned sig_offset; unsigned sig_len; const struct section_header *secs; - struct pkcs7_message *pkcs7; /* PKCS#7 MS Individual Code Signing content */ const void *digest; /* Digest */ @@ -39,4 +37,5 @@ struct pefile_context { /* * mscode_parser.c */ -extern int mscode_parse(struct pefile_context *ctx); +extern int mscode_parse(void *_ctx, const void *content_data, size_t data_len, + size_t asn1hdrlen); diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h index 441aff9b5aa7..8323e3e57131 100644 --- a/include/crypto/pkcs7.h +++ b/include/crypto/pkcs7.h @@ -12,6 +12,7 @@ #ifndef _CRYPTO_PKCS7_H #define _CRYPTO_PKCS7_H +#include #include struct key; @@ -26,7 +27,7 @@ extern void pkcs7_free_message(struct pkcs7_message *pkcs7); extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, const void **_data, size_t *_datalen, - bool want_wrapper); + size_t *_headerlen); /* * pkcs7_trust.c diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 2f5de5c1a3a0..b3928e801b8c 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -14,20 +14,6 @@ #ifndef _LINUX_PUBLIC_KEY_H #define _LINUX_PUBLIC_KEY_H -/* - * The use to which an asymmetric key is being put. - */ -enum key_being_used_for { - VERIFYING_MODULE_SIGNATURE, - VERIFYING_FIRMWARE_SIGNATURE, - VERIFYING_KEXEC_PE_SIGNATURE, - VERIFYING_KEY_SIGNATURE, - VERIFYING_KEY_SELF_SIGNATURE, - VERIFYING_UNSPECIFIED_SIGNATURE, - NR__KEY_BEING_USED_FOR -}; -extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR]; - /* * Cryptographic data for the public-key subtype of the asymmetric key type. * diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h index 70a8775bb444..d1e23dda4363 100644 --- a/include/keys/asymmetric-type.h +++ b/include/keys/asymmetric-type.h @@ -15,6 +15,7 @@ #define _KEYS_ASYMMETRIC_TYPE_H #include +#include extern struct key_type key_type_asymmetric; diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index 39fd38cfa8c9..b2d645ac35a0 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -15,6 +15,7 @@ #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING #include +#include #include extern struct key *system_trusted_keyring; @@ -29,12 +30,6 @@ static inline struct key *get_system_trusted_keyring(void) } #endif -#ifdef CONFIG_SYSTEM_DATA_VERIFICATION -extern int system_verify_data(const void *data, unsigned long len, - const void *raw_pkcs7, size_t pkcs7_len, - enum key_being_used_for usage); -#endif - #ifdef CONFIG_IMA_MOK_KEYRING extern struct key *ima_mok_keyring; extern struct key *ima_blacklist_keyring; diff --git a/include/linux/verification.h b/include/linux/verification.h new file mode 100644 index 000000000000..bb0fcf941cb7 --- /dev/null +++ b/include/linux/verification.h @@ -0,0 +1,50 @@ +/* Signature verification + * + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _LINUX_VERIFICATION_H +#define _LINUX_VERIFICATION_H + +/* + * The use to which an asymmetric key is being put. + */ +enum key_being_used_for { + VERIFYING_MODULE_SIGNATURE, + VERIFYING_FIRMWARE_SIGNATURE, + VERIFYING_KEXEC_PE_SIGNATURE, + VERIFYING_KEY_SIGNATURE, + VERIFYING_KEY_SELF_SIGNATURE, + VERIFYING_UNSPECIFIED_SIGNATURE, + NR__KEY_BEING_USED_FOR +}; +extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR]; + +#ifdef CONFIG_SYSTEM_DATA_VERIFICATION + +struct key; + +extern int verify_pkcs7_signature(const void *data, size_t len, + const void *raw_pkcs7, size_t pkcs7_len, + struct key *trusted_keys, + int untrusted_error, + enum key_being_used_for usage, + int (*view_content)(void *ctx, + const void *data, size_t len, + size_t asn1hdrlen), + void *ctx); + +#ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION +extern int verify_pefile_signature(const void *pebuf, unsigned pelen, + struct key *trusted_keys, + enum key_being_used_for usage); +#endif + +#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ +#endif /* _LINUX_VERIFY_PEFILE_H */ diff --git a/include/linux/verify_pefile.h b/include/linux/verify_pefile.h deleted file mode 100644 index da2049b5161c..000000000000 --- a/include/linux/verify_pefile.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Signed PE file verification - * - * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -#ifndef _LINUX_VERIFY_PEFILE_H -#define _LINUX_VERIFY_PEFILE_H - -#include - -extern int verify_pefile_signature(const void *pebuf, unsigned pelen, - struct key *trusted_keyring, - enum key_being_used_for usage, - bool *_trusted); - -#endif /* _LINUX_VERIFY_PEFILE_H */ diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 64b9dead4a07..593aace88a02 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -80,6 +80,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen) return -EBADMSG; } - return system_verify_data(mod, modlen, mod + modlen, sig_len, - VERIFYING_MODULE_SIGNATURE); + return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, + NULL, -ENOKEY, VERIFYING_MODULE_SIGNATURE, + NULL, NULL); } -- GitLab From bda850cd214e90b1be0cc25bc48c4f6ac53eb543 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:24 +0100 Subject: [PATCH 1583/9938] PKCS#7: Make trust determination dependent on contents of trust keyring Make the determination of the trustworthiness of a key dependent on whether a key that can verify it is present in the supplied ring of trusted keys rather than whether or not the verifying key has KEY_FLAG_TRUSTED set. verify_pkcs7_signature() will return -ENOKEY if the PKCS#7 message trust chain cannot be verified. Signed-off-by: David Howells --- certs/system_keyring.c | 13 ++++--------- crypto/asymmetric_keys/pkcs7_key_type.c | 2 +- crypto/asymmetric_keys/pkcs7_parser.h | 1 - crypto/asymmetric_keys/pkcs7_trust.c | 18 +++--------------- crypto/asymmetric_keys/verify_pefile.c | 2 +- crypto/asymmetric_keys/x509_parser.h | 1 - include/crypto/pkcs7.h | 3 +-- include/linux/verification.h | 1 - kernel/module_signing.c | 2 +- 9 files changed, 11 insertions(+), 32 deletions(-) diff --git a/certs/system_keyring.c b/certs/system_keyring.c index a83bffedc0aa..dc18869ff680 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -121,7 +121,6 @@ late_initcall(load_system_certificate_list); int verify_pkcs7_signature(const void *data, size_t len, const void *raw_pkcs7, size_t pkcs7_len, struct key *trusted_keys, - int untrusted_error, enum key_being_used_for usage, int (*view_content)(void *ctx, const void *data, size_t len, @@ -129,7 +128,6 @@ int verify_pkcs7_signature(const void *data, size_t len, void *ctx) { struct pkcs7_message *pkcs7; - bool trusted; int ret; pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len); @@ -149,13 +147,10 @@ int verify_pkcs7_signature(const void *data, size_t len, if (!trusted_keys) trusted_keys = system_trusted_keyring; - ret = pkcs7_validate_trust(pkcs7, trusted_keys, &trusted); - if (ret < 0) - goto error; - - if (!trusted && untrusted_error) { - pr_err("PKCS#7 signature not signed with a trusted key\n"); - ret = untrusted_error; + ret = pkcs7_validate_trust(pkcs7, trusted_keys); + if (ret < 0) { + if (ret == -ENOKEY) + pr_err("PKCS#7 signature not signed with a trusted key\n"); goto error; } diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c index ab9bf5363ecd..3b92523882e5 100644 --- a/crypto/asymmetric_keys/pkcs7_key_type.c +++ b/crypto/asymmetric_keys/pkcs7_key_type.c @@ -62,7 +62,7 @@ static int pkcs7_preparse(struct key_preparsed_payload *prep) return verify_pkcs7_signature(NULL, 0, prep->data, prep->datalen, - NULL, -ENOKEY, usage, + NULL, usage, pkcs7_view_content, prep); } diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h index d5eec31e95b6..f4e81074f5e0 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h @@ -22,7 +22,6 @@ struct pkcs7_signed_info { struct pkcs7_signed_info *next; struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ unsigned index; - bool trusted; bool unsupported_crypto; /* T if not usable due to missing crypto */ /* Message digest - the digest of the Content Data (or NULL) */ diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index b9a5487cd82d..36e77cb07bd0 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -30,7 +30,6 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, struct public_key_signature *sig = sinfo->sig; struct x509_certificate *x509, *last = NULL, *p; struct key *key; - bool trusted; int ret; kenter(",%u,", sinfo->index); @@ -42,10 +41,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, for (x509 = sinfo->signer; x509; x509 = x509->signer) { if (x509->seen) { - if (x509->verified) { - trusted = x509->trusted; + if (x509->verified) goto verified; - } kleave(" = -ENOKEY [cached]"); return -ENOKEY; } @@ -122,7 +119,6 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, matched: ret = verify_signature(key, sig); - trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags); key_put(key); if (ret < 0) { if (ret == -ENOMEM) @@ -134,12 +130,9 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, verified: if (x509) { x509->verified = true; - for (p = sinfo->signer; p != x509; p = p->signer) { + for (p = sinfo->signer; p != x509; p = p->signer) p->verified = true; - p->trusted = trusted; - } } - sinfo->trusted = trusted; kleave(" = 0"); return 0; } @@ -148,7 +141,6 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, * pkcs7_validate_trust - Validate PKCS#7 trust chain * @pkcs7: The PKCS#7 certificate to validate * @trust_keyring: Signing certificates to use as starting points - * @_trusted: Set to true if trustworth, false otherwise * * Validate that the certificate chain inside the PKCS#7 message intersects * keys we already know and trust. @@ -170,16 +162,13 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, * May also return -ENOMEM. */ int pkcs7_validate_trust(struct pkcs7_message *pkcs7, - struct key *trust_keyring, - bool *_trusted) + struct key *trust_keyring) { struct pkcs7_signed_info *sinfo; struct x509_certificate *p; int cached_ret = -ENOKEY; int ret; - *_trusted = false; - for (p = pkcs7->certs; p; p = p->next) p->seen = false; @@ -193,7 +182,6 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7, cached_ret = -ENOPKG; continue; case 0: - *_trusted |= sinfo->trusted; cached_ret = 0; continue; default: diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 265351075b0e..672a94c2c3ff 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -436,7 +436,7 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, ret = verify_pkcs7_signature(NULL, 0, pebuf + ctx.sig_offset, ctx.sig_len, - trusted_keys, -EKEYREJECTED, usage, + trusted_keys, usage, mscode_parse, &ctx); if (ret < 0) goto error; diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index f24f4d808e7f..05eef1c68881 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -39,7 +39,6 @@ struct x509_certificate { unsigned index; bool seen; /* Infinite recursion prevention */ bool verified; - bool trusted; bool self_signed; /* T if self-signed (check unsupported_sig too) */ bool unsupported_key; /* T if key uses unsupported crypto */ bool unsupported_sig; /* T if signature uses unsupported crypto */ diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h index 8323e3e57131..583f199400a3 100644 --- a/include/crypto/pkcs7.h +++ b/include/crypto/pkcs7.h @@ -33,8 +33,7 @@ extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, * pkcs7_trust.c */ extern int pkcs7_validate_trust(struct pkcs7_message *pkcs7, - struct key *trust_keyring, - bool *_trusted); + struct key *trust_keyring); /* * pkcs7_verify.c diff --git a/include/linux/verification.h b/include/linux/verification.h index bb0fcf941cb7..a10549a6c7cd 100644 --- a/include/linux/verification.h +++ b/include/linux/verification.h @@ -33,7 +33,6 @@ struct key; extern int verify_pkcs7_signature(const void *data, size_t len, const void *raw_pkcs7, size_t pkcs7_len, struct key *trusted_keys, - int untrusted_error, enum key_being_used_for usage, int (*view_content)(void *ctx, const void *data, size_t len, diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 593aace88a02..6a64e03b9f44 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -81,6 +81,6 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen) } return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, - NULL, -ENOKEY, VERIFYING_MODULE_SIGNATURE, + NULL, VERIFYING_MODULE_SIGNATURE, NULL, NULL); } -- GitLab From b72db4005fe4bf4af16d1436abd3c9d3aac991d1 Mon Sep 17 00:00:00 2001 From: Kedareswara rao Appana Date: Wed, 6 Apr 2016 10:38:08 +0530 Subject: [PATCH 1584/9938] dmaengine: vdma: Add 64 bit addressing support to the driver This VDMA is a soft ip, which can be programmed to support 32 bit addressing or greater than 32 bit addressing. When the VDMA ip is configured for 32 bit address space the buffer address is specified by a single register (0x5C for MM2S and 0xAC for S2MM channel). When the VDMA core is configured for an address space greater than 32 then each buffer address is specified by a combination of two registers. The first register specifies the LSB 32 bits of address, while the next register specifies the MSB 32 bits of address. For example, 5Ch will specify the LSB 32 bits while 60h will specify the MSB 32 bits of the first start address. So we need to program two registers at a time. This patch adds the 64 bit addressing support to the vdma driver. Signed-off-by: Anurag Kumar Vulisha Signed-off-by: Kedareswara rao Appana Signed-off-by: Vinod Koul --- .../bindings/dma/xilinx/xilinx_vdma.txt | 4 + drivers/dma/Kconfig | 2 +- drivers/dma/xilinx/xilinx_vdma.c | 73 +++++++++++++++++-- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt index e4c4d47f8137..a86737c99f53 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt @@ -8,6 +8,8 @@ Required properties: - #dma-cells: Should be <1>, see "dmas" property below - reg: Should contain VDMA registers location and length. - xlnx,num-fstores: Should be the number of framebuffers as configured in h/w. +- xlnx,addrwidth: Should be the vdma addressing size in bits(ex: 32 bits). +- dma-ranges: Should be as the following . - dma-channel child node: Should have at least one channel and can have up to two channels per device. This node specifies the properties of each DMA channel (see child node properties below). @@ -41,8 +43,10 @@ axi_vdma_0: axivdma@40030000 { compatible = "xlnx,axi-vdma-1.00.a"; #dma_cells = <1>; reg = < 0x40030000 0x10000 >; + dma-ranges = <0x00000000 0x00000000 0x40000000>; xlnx,num-fstores = <0x8>; xlnx,flush-fsync = <0x1>; + xlnx,addrwidth = <0x20>; dma-channel@40030000 { compatible = "xlnx,axi-vdma-mm2s-channel"; interrupts = < 0 54 4 >; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index d96d87c56f2e..2846753ddf6c 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -507,7 +507,7 @@ config XGENE_DMA config XILINX_VDMA tristate "Xilinx AXI VDMA Engine" - depends on (ARCH_ZYNQ || MICROBLAZE) + depends on (ARCH_ZYNQ || MICROBLAZE || ARM64) select DMA_ENGINE help Enable support for Xilinx AXI VDMA Soft IP. diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c index 0ee0321868d3..abe915c73266 100644 --- a/drivers/dma/xilinx/xilinx_vdma.c +++ b/drivers/dma/xilinx/xilinx_vdma.c @@ -100,6 +100,7 @@ #define XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT 0 #define XILINX_VDMA_REG_START_ADDRESS(n) (0x000c + 4 * (n)) +#define XILINX_VDMA_REG_START_ADDRESS_64(n) (0x000c + 8 * (n)) /* HW specific definitions */ #define XILINX_VDMA_MAX_CHANS_PER_DEVICE 0x2 @@ -144,7 +145,7 @@ * @next_desc: Next Descriptor Pointer @0x00 * @pad1: Reserved @0x04 * @buf_addr: Buffer address @0x08 - * @pad2: Reserved @0x0C + * @buf_addr_msb: MSB of Buffer address @0x0C * @vsize: Vertical Size @0x10 * @hsize: Horizontal Size @0x14 * @stride: Number of bytes between the first @@ -154,7 +155,7 @@ struct xilinx_vdma_desc_hw { u32 next_desc; u32 pad1; u32 buf_addr; - u32 pad2; + u32 buf_addr_msb; u32 vsize; u32 hsize; u32 stride; @@ -207,6 +208,7 @@ struct xilinx_vdma_tx_descriptor { * @config: Device configuration info * @flush_on_fsync: Flush on Frame sync * @desc_pendingcount: Descriptor pending count + * @ext_addr: Indicates 64 bit addressing is supported by dma channel */ struct xilinx_vdma_chan { struct xilinx_vdma_device *xdev; @@ -230,6 +232,7 @@ struct xilinx_vdma_chan { struct xilinx_vdma_config config; bool flush_on_fsync; u32 desc_pendingcount; + bool ext_addr; }; /** @@ -240,6 +243,7 @@ struct xilinx_vdma_chan { * @chan: Driver specific VDMA channel * @has_sg: Specifies whether Scatter-Gather is present or not * @flush_on_fsync: Flush on frame sync + * @ext_addr: Indicates 64 bit addressing is supported by dma device */ struct xilinx_vdma_device { void __iomem *regs; @@ -248,6 +252,7 @@ struct xilinx_vdma_device { struct xilinx_vdma_chan *chan[XILINX_VDMA_MAX_CHANS_PER_DEVICE]; bool has_sg; u32 flush_on_fsync; + bool ext_addr; }; /* Macros */ @@ -299,6 +304,27 @@ static inline void vdma_ctrl_set(struct xilinx_vdma_chan *chan, u32 reg, vdma_ctrl_write(chan, reg, vdma_ctrl_read(chan, reg) | set); } +/** + * vdma_desc_write_64 - 64-bit descriptor write + * @chan: Driver specific VDMA channel + * @reg: Register to write + * @value_lsb: lower address of the descriptor. + * @value_msb: upper address of the descriptor. + * + * Since vdma driver is trying to write to a register offset which is not a + * multiple of 64 bits(ex : 0x5c), we are writing as two separate 32 bits + * instead of a single 64 bit register write. + */ +static inline void vdma_desc_write_64(struct xilinx_vdma_chan *chan, u32 reg, + u32 value_lsb, u32 value_msb) +{ + /* Write the lsb 32 bits*/ + writel(value_lsb, chan->xdev->regs + chan->desc_offset + reg); + + /* Write the msb 32 bits */ + writel(value_msb, chan->xdev->regs + chan->desc_offset + reg + 4); +} + /* ----------------------------------------------------------------------------- * Descriptors and segments alloc and free */ @@ -693,9 +719,16 @@ static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) list_for_each_entry(desc, &chan->pending_list, node) { segment = list_first_entry(&desc->segments, struct xilinx_vdma_tx_segment, node); - vdma_desc_write(chan, + if (chan->ext_addr) + vdma_desc_write_64(chan, + XILINX_VDMA_REG_START_ADDRESS_64(i++), + segment->hw.buf_addr, + segment->hw.buf_addr_msb); + else + vdma_desc_write(chan, XILINX_VDMA_REG_START_ADDRESS(i++), segment->hw.buf_addr); + last = segment; } @@ -987,10 +1020,21 @@ xilinx_vdma_dma_prep_interleaved(struct dma_chan *dchan, hw->stride |= chan->config.frm_dly << XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT; - if (xt->dir != DMA_MEM_TO_DEV) - hw->buf_addr = xt->dst_start; - else - hw->buf_addr = xt->src_start; + if (xt->dir != DMA_MEM_TO_DEV) { + if (chan->ext_addr) { + hw->buf_addr = lower_32_bits(xt->dst_start); + hw->buf_addr_msb = upper_32_bits(xt->dst_start); + } else { + hw->buf_addr = xt->dst_start; + } + } else { + if (chan->ext_addr) { + hw->buf_addr = lower_32_bits(xt->src_start); + hw->buf_addr_msb = upper_32_bits(xt->src_start); + } else { + hw->buf_addr = xt->src_start; + } + } /* Insert the segment into the descriptor segments list. */ list_add_tail(&segment->node, &desc->segments); @@ -1140,6 +1184,7 @@ static int xilinx_vdma_chan_probe(struct xilinx_vdma_device *xdev, chan->xdev = xdev; chan->has_sg = xdev->has_sg; chan->desc_pendingcount = 0x0; + chan->ext_addr = xdev->ext_addr; spin_lock_init(&chan->lock); INIT_LIST_HEAD(&chan->pending_list); @@ -1254,7 +1299,7 @@ static int xilinx_vdma_probe(struct platform_device *pdev) struct xilinx_vdma_device *xdev; struct device_node *child; struct resource *io; - u32 num_frames; + u32 num_frames, addr_width; int i, err; /* Allocate and initialize the DMA engine structure */ @@ -1284,6 +1329,18 @@ static int xilinx_vdma_probe(struct platform_device *pdev) if (err < 0) dev_warn(xdev->dev, "missing xlnx,flush-fsync property\n"); + err = of_property_read_u32(node, "xlnx,addrwidth", &addr_width); + if (err < 0) + dev_warn(xdev->dev, "missing xlnx,addrwidth property\n"); + + if (addr_width > 32) + xdev->ext_addr = true; + else + xdev->ext_addr = false; + + /* Set the dma mask bits */ + dma_set_mask(xdev->dev, DMA_BIT_MASK(addr_width)); + /* Initialize the DMA engine */ xdev->common.dev = &pdev->dev; -- GitLab From a65cf5125b49f3d4703c02692609501166e23735 Mon Sep 17 00:00:00 2001 From: Kedareswara rao Appana Date: Wed, 6 Apr 2016 10:38:09 +0530 Subject: [PATCH 1585/9938] dmaengine: vdma: Fix race condition in Non-SG mode When VDMA is configured in Non-sg mode Users can queue descriptors greater than h/w configured frames. Current driver allows the user to queue descriptors upto h/w configured. Which is wrong for non-sg mode configuration. This patch fixes this issue. Signed-off-by: Kedareswara rao Appana Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_vdma.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c index abe915c73266..b873d98d756b 100644 --- a/drivers/dma/xilinx/xilinx_vdma.c +++ b/drivers/dma/xilinx/xilinx_vdma.c @@ -209,6 +209,7 @@ struct xilinx_vdma_tx_descriptor { * @flush_on_fsync: Flush on Frame sync * @desc_pendingcount: Descriptor pending count * @ext_addr: Indicates 64 bit addressing is supported by dma channel + * @desc_submitcount: Descriptor h/w submitted count */ struct xilinx_vdma_chan { struct xilinx_vdma_device *xdev; @@ -233,6 +234,7 @@ struct xilinx_vdma_chan { bool flush_on_fsync; u32 desc_pendingcount; bool ext_addr; + u32 desc_submitcount; }; /** @@ -716,9 +718,10 @@ static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) struct xilinx_vdma_tx_segment *segment, *last = NULL; int i = 0; - list_for_each_entry(desc, &chan->pending_list, node) { - segment = list_first_entry(&desc->segments, - struct xilinx_vdma_tx_segment, node); + if (chan->desc_submitcount < chan->num_frms) + i = chan->desc_submitcount; + + list_for_each_entry(segment, &desc->segments, node) { if (chan->ext_addr) vdma_desc_write_64(chan, XILINX_VDMA_REG_START_ADDRESS_64(i++), @@ -742,8 +745,17 @@ static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) vdma_desc_write(chan, XILINX_VDMA_REG_VSIZE, last->hw.vsize); } - list_splice_tail_init(&chan->pending_list, &chan->active_list); - chan->desc_pendingcount = 0; + if (!chan->has_sg) { + list_del(&desc->node); + list_add_tail(&desc->node, &chan->active_list); + chan->desc_submitcount++; + chan->desc_pendingcount--; + if (chan->desc_submitcount == chan->num_frms) + chan->desc_submitcount = 0; + } else { + list_splice_tail_init(&chan->pending_list, &chan->active_list); + chan->desc_pendingcount = 0; + } } /** @@ -927,7 +939,8 @@ static void append_desc_queue(struct xilinx_vdma_chan *chan, list_add_tail(&desc->node, &chan->pending_list); chan->desc_pendingcount++; - if (unlikely(chan->desc_pendingcount > chan->num_frms)) { + if (chan->has_sg && + unlikely(chan->desc_pendingcount > chan->num_frms)) { dev_dbg(chan->dev, "desc pendingcount is too high\n"); chan->desc_pendingcount = chan->num_frms; } -- GitLab From 48a59edc63ed83283bf2d2523137ab0578feac1a Mon Sep 17 00:00:00 2001 From: Kedareswara rao Appana Date: Wed, 6 Apr 2016 10:44:55 +0530 Subject: [PATCH 1586/9938] dmaengine: vdma: Fix checkpatch.pl warnings This patch fixes the below checkpatch.pl warnings. WARNING: void function return statements are not generally useful + return; +} WARNING: void function return statements are not generally useful + return; +} WARNING: Missing a blank line after declarations + u32 errors = status & XILINX_VDMA_DMASR_ALL_ERR_MASK; + vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR, Acked-by: Laurent Pinchart Acked-by: Moritz Fischer Signed-off-by: Kedareswara rao Appana Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_vdma.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c index b873d98d756b..3c5ce373b99d 100644 --- a/drivers/dma/xilinx/xilinx_vdma.c +++ b/drivers/dma/xilinx/xilinx_vdma.c @@ -597,8 +597,6 @@ static void xilinx_vdma_halt(struct xilinx_vdma_chan *chan) chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR)); chan->err = true; } - - return; } /** @@ -623,8 +621,6 @@ static void xilinx_vdma_start(struct xilinx_vdma_chan *chan) chan->err = true; } - - return; } /** @@ -874,6 +870,7 @@ static irqreturn_t xilinx_vdma_irq_handler(int irq, void *data) * make sure not to write to other error bits to 1. */ u32 errors = status & XILINX_VDMA_DMASR_ALL_ERR_MASK; + vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR, errors & XILINX_VDMA_DMASR_ERR_RECOVER_MASK); -- GitLab From 74d8b45fa344129b3dfd37019877ba68b1287e18 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Wed, 6 Apr 2016 09:06:03 +0300 Subject: [PATCH 1587/9938] regulator: twl: Fix a typo in twl4030_send_pb_msg Commit <2330b05c095bdeaaf1261c54cd2d4b9127496996> ("regulator: twl: Make sure we have access to powerbus before trying to write to it") has implemented the needed logic to correctly access powerbus through i2c, however it brought a typo when powerbus configuration is restored, which results in writing to a wrong register. Fix that by providing the correct register value. Signed-off-by: Ivaylo Dimitrov Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 11c6a5c98c46..faeb5ee92c9e 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -253,7 +253,7 @@ static int twl4030_send_pb_msg(unsigned msg) /* Restore powerbus configuration */ return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val, - TWL_MODULE_PM_MASTER); + TWL4030_PM_MASTER_PB_CFG); } static int twl4030reg_enable(struct regulator_dev *rdev) -- GitLab From 5ab3c4949580a18e86b0bedd7b7b21c708192b91 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 6 Apr 2016 09:49:46 -0400 Subject: [PATCH 1588/9938] regulator: s2mps11: Use module_platform_driver() instead subsys initcall The driver's init and exit function don't do anything besides registering and unregistering the platform driver, so the module_platform_driver() macro could just be used instead of having separate functions. Currently the macro is not being used because the driver is initialized at subsys init call level but this isn't necessary since consumer devices are defined in the DT as dependencies so there's no need for init calls order. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index d24e2c783dc5..46e5a2922c4d 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -1221,17 +1221,7 @@ static struct platform_driver s2mps11_pmic_driver = { .id_table = s2mps11_pmic_id, }; -static int __init s2mps11_pmic_init(void) -{ - return platform_driver_register(&s2mps11_pmic_driver); -} -subsys_initcall(s2mps11_pmic_init); - -static void __exit s2mps11_pmic_exit(void) -{ - platform_driver_unregister(&s2mps11_pmic_driver); -} -module_exit(s2mps11_pmic_exit); +module_platform_driver(s2mps11_pmic_driver); /* Module information */ MODULE_AUTHOR("Sangbeom Kim "); -- GitLab From 314a8203b6de2df164399996ece1412ae8f6270d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 6 Apr 2016 09:49:47 -0400 Subject: [PATCH 1589/9938] regulator: max77686: Use module_platform_driver() instead subsys initcall The driver's init and exit function don't do anything besides registering and unregistering the platform driver, so the module_platform_driver() macro could just be used instead of having separate functions. Currently the macro is not being used because the driver is initialized at subsys init call level but this isn't necessary since consumer devices are defined in the DT as dependencies so there's no need for init calls order. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/max77686-regulator.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c index 17ccf365a9c0..d1ab6a4da88f 100644 --- a/drivers/regulator/max77686-regulator.c +++ b/drivers/regulator/max77686-regulator.c @@ -553,17 +553,7 @@ static struct platform_driver max77686_pmic_driver = { .id_table = max77686_pmic_id, }; -static int __init max77686_pmic_init(void) -{ - return platform_driver_register(&max77686_pmic_driver); -} -subsys_initcall(max77686_pmic_init); - -static void __exit max77686_pmic_cleanup(void) -{ - platform_driver_unregister(&max77686_pmic_driver); -} -module_exit(max77686_pmic_cleanup); +module_platform_driver(max77686_pmic_driver); MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver"); MODULE_AUTHOR("Chiwoong Byun "); -- GitLab From a3bca91f2fe54af502deaf277dd5ac0e18bffde4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 6 Apr 2016 12:51:33 -0300 Subject: [PATCH 1590/9938] perf trace: Beautify sched_setscheduler 'policy' argument $ trace -e sched_setscheduler chrt -f 1 usleep 1 chrt: failed to set pid 0's policy: Operation not permitted 0.005 ( 0.005 ms): chrt/19189 sched_setscheduler(policy: FIFO, param: 0x7ffec5273d70) = -1 EPERM Operation not permitted $ Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-i5vlo5n5jv0amt8bkyicmdxh@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 +++ tools/perf/trace/beauty/sched_policy.c | 44 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tools/perf/trace/beauty/sched_policy.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d309f4535a45..c283153d8c7f 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1073,6 +1073,8 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ .arg_parm = { [arg] = &strarray__##array, } +#include "trace/beauty/sched_policy.c" + static struct syscall_fmt { const char *name; const char *alias; @@ -1304,6 +1306,8 @@ static struct syscall_fmt { .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, { .name = "rt_tgsigqueueinfo", .errmsg = true, .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, + { .name = "sched_setscheduler", .errmsg = true, + .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, }, { .name = "seccomp", .errmsg = true, .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */ [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c new file mode 100644 index 000000000000..c205bc608b3c --- /dev/null +++ b/tools/perf/trace/beauty/sched_policy.c @@ -0,0 +1,44 @@ +#include + +/* + * Not defined anywhere else, probably, just to make sure we + * catch future flags + */ +#define SCHED_POLICY_MASK 0xff + +#ifndef SCHED_DEADLINE +#define SCHED_DEADLINE 6 +#endif + +static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, + struct syscall_arg *arg) +{ + const char *policies[] = { + "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "DEADLINE", + }; + size_t printed; + int policy = arg->val, + flags = policy & ~SCHED_POLICY_MASK; + + policy &= SCHED_POLICY_MASK; + if (policy <= SCHED_DEADLINE) + printed = scnprintf(bf, size, "%s", policies[policy]); + else + printed = scnprintf(bf, size, "%#x", policy); + +#define P_POLICY_FLAG(n) \ + if (flags & SCHED_##n) { \ + printed += scnprintf(bf + printed, size - printed, "|%s", #n); \ + flags &= ~SCHED_##n; \ + } + + P_POLICY_FLAG(RESET_ON_FORK); +#undef P_POLICY_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "|%#x", flags); + + return printed; +} + +#define SCA_SCHED_POLICY syscall_arg__scnprintf_sched_policy -- GitLab From 7206b900e6e4b7f4c2e766eab64ea1ca5303e421 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 6 Apr 2016 14:11:36 -0300 Subject: [PATCH 1591/9938] perf trace: Beautify wait4/waitid 'options' argument # trace -e waitid,wait4 0.557 ( 0.557 ms): bash/27335 wait4(upid: -1, stat_addr: 0x7ffd02f449f0) = 27336 1.250 ( 0.685 ms): bash/27335 wait4(upid: -1, stat_addr: 0x7ffd02f449f0) = 27337 1.312 ( 0.002 ms): bash/27335 wait4(upid: -1, stat_addr: 0x7ffd02f44690, options: NOHANG) = -1 ECHILD No child processes 1.550 ( 0.015 ms): bash/3856 wait4(upid: -1, stat_addr: 0x7ffd02f44990, options: NOHANG|UNTRACED|CONTINUED) = 27335 1.552 ( 0.001 ms): bash/3856 wait4(upid: -1, stat_addr: 0x7ffd02f44990, options: NOHANG|UNTRACED|CONTINUED) = 0 # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-i5vlo5n5jv0amt8bkyicmdxh@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 5 +++++ tools/perf/trace/beauty/waitid_options.c | 26 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tools/perf/trace/beauty/waitid_options.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c283153d8c7f..9a6c7b1fd5a1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1074,6 +1074,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, .arg_parm = { [arg] = &strarray__##array, } #include "trace/beauty/sched_policy.c" +#include "trace/beauty/waitid_options.c" static struct syscall_fmt { const char *name; @@ -1364,6 +1365,10 @@ static struct syscall_fmt { .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, { .name = "vmsplice", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "wait4", .errmsg = true, + .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, + { .name = "waitid", .errmsg = true, + .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, { .name = "write", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "writev", .errmsg = true, diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c new file mode 100644 index 000000000000..7942724adec8 --- /dev/null +++ b/tools/perf/trace/beauty/waitid_options.c @@ -0,0 +1,26 @@ +#include +#include + +static size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size, + struct syscall_arg *arg) +{ + int printed = 0, options = arg->val; + +#define P_OPTION(n) \ + if (options & W##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + options &= ~W##n; \ + } + + P_OPTION(NOHANG); + P_OPTION(UNTRACED); + P_OPTION(CONTINUED); +#undef P_OPTION + + if (options) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", options); + + return printed; +} + +#define SCA_WAITID_OPTIONS syscall_arg__scnprintf_waitid_options -- GitLab From 9771b18a0b374b6e6ecfa84c8b59d5ef79e969b1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 6 Apr 2016 11:21:53 +0100 Subject: [PATCH 1592/9938] ASoC: wm_adsp: Factor out fetching of stream errors from the DSP Factor out the reading of the DSP error flag into its own function to support further improvements to the code. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 953c4278b75e..f70c60914042 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2816,6 +2816,23 @@ static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) return 0; } +static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf) +{ + int ret; + + ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error); + if (ret < 0) { + adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret); + return ret; + } + if (buf->error != 0) { + adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error); + return -EIO; + } + + return 0; +} + int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) { struct wm_adsp_compr_buf *buf; @@ -2834,16 +2851,9 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) adsp_dbg(dsp, "Handling buffer IRQ\n"); - ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error); - if (ret < 0) { - adsp_err(dsp, "Failed to check buffer error: %d\n", ret); - goto out; - } - if (buf->error != 0) { - adsp_err(dsp, "Buffer error occurred: %d\n", buf->error); - ret = -EIO; + ret = wm_adsp_buffer_get_error(buf); + if (ret < 0) goto out; - } ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count), &buf->irq_count); -- GitLab From 5847609edb3c80be07e897e449a9bb579a0fe9d8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 6 Apr 2016 11:21:54 +0100 Subject: [PATCH 1593/9938] ASoC: wm_adsp: Improve DSP error handling If we encounter an error on the DSP side whilst user-space is waiting on the poll we should call snd_compr_fragment_elapsed, although data is not actually available we want to wake user-space such that the error can be propagated out quickly. Additionally some versions of the DSP firmware are not super consistent about actually generating an IRQ if they encounter an error, as such we will check the DSP error status every time we run out of available data as well, to ensure we catch it. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f70c60914042..3ac2e1f06ad3 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2853,7 +2853,7 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) ret = wm_adsp_buffer_get_error(buf); if (ret < 0) - goto out; + goto out_notify; /* Wake poll to report error */ ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count), &buf->irq_count); @@ -2868,6 +2868,7 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) goto out; } +out_notify: if (compr && compr->stream) snd_compr_fragment_elapsed(compr->stream); @@ -2928,6 +2929,10 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream, * DSP to inform us once a whole fragment is available. */ if (buf->avail < wm_adsp_compr_frag_words(compr)) { + ret = wm_adsp_buffer_get_error(buf); + if (ret < 0) + goto out; + ret = wm_adsp_buffer_reenable_irq(buf); if (ret < 0) { adsp_err(dsp, -- GitLab From 57bb1369de36a72e2e13fde9c88663342f729ace Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Wed, 6 Apr 2016 14:55:35 +0530 Subject: [PATCH 1594/9938] spi: cadence: Fix some checkpatch warnings No functional change. Fixing some style related issues CHECK: multiple assignments should be avoided + new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); CHECK: Alignment should match open parenthesis +static void cdns_spi_config_clock_freq(struct spi_device *spi, + struct spi_transfer *transfer) CHECK: Please use a blank line after function/struct/union/enum declarations +} +static int cdns_prepare_message(struct spi_master *master, Signed-off-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 07481e12d8a3..8a0bd62a5088 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -209,7 +209,8 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi) struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg, new_ctrl_reg; - new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); + new_ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); + ctrl_reg = new_ctrl_reg; /* Set the SPI clock phase and clock polarity */ new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA | CDNS_SPI_CR_CPOL); @@ -246,7 +247,7 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi) * controller. */ static void cdns_spi_config_clock_freq(struct spi_device *spi, - struct spi_transfer *transfer) + struct spi_transfer *transfer) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg, baud_rate_val; @@ -380,6 +381,7 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) return status; } + static int cdns_prepare_message(struct spi_master *master, struct spi_message *msg) { -- GitLab From 11c8e39f5133aed9e0f8ffc624c7d5f64c97bc79 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 6 Apr 2016 14:33:07 -0300 Subject: [PATCH 1595/9938] perf trace: Infrastructure to show COMM strings for syscalls returning PIDs Starting with clone, waitid and wait4: # trace -e waitid,wait4 1.385 ( 1.385 ms): bash/12122 wait4(upid: -1, stat_addr: 0x7ffe0cee1720, options: UNTRACED|CONTINUED) = 1210 (ls) 1.426 ( 0.002 ms): bash/12122 wait4(upid: -1, stat_addr: 0x7ffe0cee1150, options: NOHANG|UNTRACED|CONTINUED) = 0 3.293 ( 0.604 ms): bash/1211 wait4(upid: -1, stat_addr: 0x7ffe0cee0560 ) = 1214 (sed) 3.342 ( 0.002 ms): bash/1211 wait4(upid: -1, stat_addr: 0x7ffe0cee01d0, options: NOHANG ) = -1 ECHILD No child processes 3.576 ( 0.016 ms): bash/12122 wait4(upid: -1, stat_addr: 0x7ffe0cee0550, options: NOHANG|UNTRACED|CONTINUED) = 1211 (bash) ^C# trace -e clone 0.027 ( 0.000 ms): systemd/1 ... [continued]: clone()) = 1227 (systemd) 0.050 ( 0.000 ms): systemd/1227 ... [continued]: clone()) = 0 ^C[root@jouet ~]# Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-lyf5d3y5j15wikjb6pe6ukoi@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 9a6c7b1fd5a1..22a4901d057b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1082,6 +1082,7 @@ static struct syscall_fmt { size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg); void *arg_parm[6]; bool errmsg; + bool errpid; bool timeout; bool hexret; } syscall_fmts[] = { @@ -1099,6 +1100,7 @@ static struct syscall_fmt { { .name = "chroot", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, + { .name = "clone", .errpid = true, }, { .name = "close", .errmsg = true, .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, { .name = "connect", .errmsg = true, }, @@ -1365,9 +1367,9 @@ static struct syscall_fmt { .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, { .name = "vmsplice", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "wait4", .errmsg = true, + { .name = "wait4", .errpid = true, .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, - { .name = "waitid", .errmsg = true, + { .name = "waitid", .errpid = true, .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, { .name = "write", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, @@ -2156,7 +2158,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, if (sc->fmt == NULL) { signed_print: fprintf(trace->output, ") = %ld", ret); - } else if (ret < 0 && sc->fmt->errmsg) { + } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) { char bf[STRERR_BUFSIZE]; const char *emsg = strerror_r(-ret, bf, sizeof(bf)), *e = audit_errno_to_name(-ret); @@ -2166,7 +2168,16 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, fprintf(trace->output, ") = 0 Timeout"); else if (sc->fmt->hexret) fprintf(trace->output, ") = %#lx", ret); - else + else if (sc->fmt->errpid) { + struct thread *child = machine__find_thread(trace->host, ret, ret); + + if (child != NULL) { + fprintf(trace->output, ") = %ld", ret); + if (child->comm_set) + fprintf(trace->output, " (%s)", thread__comm_str(child)); + thread__put(child); + } + } else goto signed_print; fputc('\n', trace->output); -- GitLab From c65f10701ac68259043ccbfac1979778a1fd7846 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 6 Apr 2016 14:55:18 -0300 Subject: [PATCH 1596/9938] perf trace: Beautify set_tid_address, getpid, getppid return values Showing the COMM for that return, if available. # trace -e getpid,getppid,set_tid_address 490.007 ( 0.005 ms): sh/8250 getpid(...) = 8250 (sh) 490.014 ( 0.001 ms): sh/8250 getppid(...) = 7886 (make) 491.156 ( 0.004 ms): install/8251 set_tid_address(tidptr: 0x7f204a9d4ad0) = 8251 (install) ^C Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-psbpplqupatom9x4uohbxid5@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 22a4901d057b..191f4d61eb16 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1166,6 +1166,8 @@ static struct syscall_fmt { { .name = "getdents64", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, + { .name = "getpid", .errpid = true, }, + { .name = "getppid", .errpid = true, }, { .name = "getrandom", .errmsg = true, .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, @@ -1324,6 +1326,7 @@ static struct syscall_fmt { { .name = "sendto", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ [3] = SCA_MSG_FLAGS, /* flags */ }, }, + { .name = "set_tid_address", .errpid = true, }, { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, { .name = "setxattr", .errmsg = true, -- GitLab From f8df33da2c9bbea3a72dff5326bb5de2ef8392d6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:31:10 +0100 Subject: [PATCH 1597/9938] mwifiex: Spelling s/minmum/minimum/, s/bandwidth/bandwith/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/tdls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 150649602e98..df9704de0715 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -285,7 +285,7 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, else usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; - /* find the minmum bandwith between AP/TDLS peers */ + /* find the minimum bandwidth between AP/TDLS peers */ vht_cap = &sta_ptr->tdls_cap.vhtcap; supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info); peer_supp_chwd_set = -- GitLab From 977bc523000d51693c4b083463dc93bbb692a662 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 15 Mar 2016 10:06:10 +0300 Subject: [PATCH 1598/9938] brcmfmac: uninitialized "ret" variable There is an error path where "ret" isn't initialized. Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index da0cdd313880..2fc0597f2cd0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -250,7 +250,7 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, u32 addr, u8 regsz, void *data, bool write) { struct sdio_func *func; - int ret; + int ret = -EINVAL; brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", write, fn, addr, regsz); -- GitLab From 0026b32d723e958bac8f335ba3f47825b11b7287 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 16 Mar 2016 07:46:16 -0700 Subject: [PATCH 1599/9938] mwifiex: fix Tx timeout issue during suspend test Call netif_carrier_off/on while stoping/starting netdev queues. This fixes netdev watchdog warning and ->ndo_tx_timeout() invocation during suspend resume stress test. Signed-off-by: Amitkumar Karwar Fixes: 54f008497b9f09f ('mwifiex: Empty Tx queue during suspend') Tested-by: Wei-Ning Huang Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index bb7235e1b9d1..b0663bdea5b5 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3272,8 +3272,11 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; - if (priv && priv->netdev) + if (priv && priv->netdev) { mwifiex_stop_net_dev_queue(priv->netdev, adapter); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + } } for (i = 0; i < retry_num; i++) { @@ -3344,8 +3347,11 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; - if (priv && priv->netdev) + if (priv && priv->netdev) { + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); + } } priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); -- GitLab From c18d8f5095715c56bb3cd9cba64242542632054b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 16 Mar 2016 13:33:34 -0500 Subject: [PATCH 1600/9938] rtlwifi: rtl8723be: Add antenna select module parameter A number of new laptops have been delivered with only a single antenna. In principle, this is OK; however, a problem arises when the on-board EEPROM is programmed to use the other antenna connection. The option of opening the computer and moving the connector is not always possible as it will void the warranty in some cases. In addition, this solution breaks the Windows driver when the box dual boots Linux and Windows. A fix involving a new module parameter has been developed. This commit adds the new parameter and implements the changes needed for the driver. Signed-off-by: Larry Finger Cc: Stable [V4.0+] Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 5 +++++ drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 3 +++ drivers/net/wireless/realtek/rtlwifi/wifi.h | 3 +++ 3 files changed, 11 insertions(+) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index c983d2fe147f..5a3df9198ddf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -2684,6 +2684,7 @@ void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, bool auto_load_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params; u8 value; u32 tmpu_32; @@ -2702,6 +2703,10 @@ void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; } + /* override ant_num / ant_path */ + if (mod_params->ant_sel) + rtlpriv->btcoexist.btc_info.ant_num = + (mod_params->ant_sel == 1 ? ANT_X2 : ANT_X1); } void rtl8723be_bt_reg_init(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index a78eaeda0008..2101793438ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -273,6 +273,7 @@ static struct rtl_mod_params rtl8723be_mod_params = { .msi_support = false, .disable_watchdog = false, .debug = DBG_EMERG, + .ant_sel = 0, }; static struct rtl_hal_cfg rtl8723be_hal_cfg = { @@ -394,6 +395,7 @@ module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444); module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444); module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog, bool, 0444); +module_param_named(ant_sel, rtl8723be_mod_params.ant_sel, int, 0444); MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); @@ -402,6 +404,7 @@ MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n"); MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n"); +MODULE_PARM_DESC(ant_sel, "Set to 1 or 2 to force antenna number (default 0)\n"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 554d81420f19..93bd7fcd2b61 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2246,6 +2246,9 @@ struct rtl_mod_params { /* default 0: 1 means do not disable interrupts */ bool int_clear; + + /* select antenna */ + int ant_sel; }; struct rtl_hal_usbint_cfg { -- GitLab From baa1702290953295e421f0f433e2b1ff4815827c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 16 Mar 2016 13:33:35 -0500 Subject: [PATCH 1601/9938] rtlwifi: btcoexist: Implement antenna selection The previous patch added an option to rtl8723be to manually select the antenna for those cases when only a single antenna is present, and the on-board EEPROM is incorrectly programmed. This patch implements the necessary changes in the Bluetooth coexistence driver. Signed-off-by: Larry Finger Cc: Stable [V4.0+] Signed-off-by: Kalle Valo --- .../rtlwifi/btcoexist/halbtc8723b2ant.c | 9 +++++-- .../realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 27 ++++++++++++++++++- .../realtek/rtlwifi/btcoexist/halbtcoutsrc.h | 2 +- .../realtek/rtlwifi/btcoexist/rtl_btc.c | 5 +++- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c index c43ab59a690a..77cbd10e807d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c @@ -1203,7 +1203,6 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist, /* Force GNT_BT to low */ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0); - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) { /* tell firmware "no antenna inverse" */ @@ -1211,19 +1210,25 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist, h2c_parameter[1] = 1; /* ext switch type */ btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, h2c_parameter); + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); } else { /* tell firmware "antenna inverse" */ h2c_parameter[0] = 1; h2c_parameter[1] = 1; /* ext switch type */ btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, h2c_parameter); + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280); } } /* ext switch setting */ if (use_ext_switch) { /* fixed internal switch S1->WiFi, S0->BT */ - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); + else + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280); + switch (antpos_type) { case BTC_ANT_WIFI_AT_MAIN: /* ext switch main at wifi */ diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index b2791c893417..babd1490f20c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -965,13 +965,38 @@ void exhalbtc_set_chip_type(u8 chip_type) } } -void exhalbtc_set_ant_num(u8 type, u8 ant_num) +void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num) { if (BT_COEX_ANT_TYPE_PG == type) { gl_bt_coexist.board_info.pg_ant_num = ant_num; gl_bt_coexist.board_info.btdm_ant_num = ant_num; + /* The antenna position: + * Main (default) or Aux for pgAntNum=2 && btdmAntNum =1. + * The antenna position should be determined by + * auto-detect mechanism. + * The following is assumed to main, + * and those must be modified + * if y auto-detect mechanism is ready + */ + if ((gl_bt_coexist.board_info.pg_ant_num == 2) && + (gl_bt_coexist.board_info.btdm_ant_num == 1)) + gl_bt_coexist.board_info.btdm_ant_pos = + BTC_ANTENNA_AT_MAIN_PORT; + else + gl_bt_coexist.board_info.btdm_ant_pos = + BTC_ANTENNA_AT_MAIN_PORT; } else if (BT_COEX_ANT_TYPE_ANTDIV == type) { gl_bt_coexist.board_info.btdm_ant_num = ant_num; + gl_bt_coexist.board_info.btdm_ant_pos = + BTC_ANTENNA_AT_MAIN_PORT; + } else if (type == BT_COEX_ANT_TYPE_DETECTED) { + gl_bt_coexist.board_info.btdm_ant_num = ant_num; + if (rtlpriv->cfg->mod_params->ant_sel == 1) + gl_bt_coexist.board_info.btdm_ant_pos = + BTC_ANTENNA_AT_AUX_PORT; + else + gl_bt_coexist.board_info.btdm_ant_pos = + BTC_ANTENNA_AT_MAIN_PORT; } } diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h index 0a903ea179ef..f41ca57dd8a7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h @@ -535,7 +535,7 @@ void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version); void exhalbtc_update_min_bt_rssi(char bt_rssi); void exhalbtc_set_bt_exist(bool bt_exist); void exhalbtc_set_chip_type(u8 chip_type); -void exhalbtc_set_ant_num(u8 type, u8 ant_num); +void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num); void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist); void exhalbtc_signal_compensation(struct btc_coexist *btcoexist, u8 *rssi_wifi, u8 *rssi_bt); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c index b9b0cb7af8ea..d3fd9211b3a4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c @@ -72,7 +72,10 @@ void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv) __func__, bt_type); exhalbtc_set_chip_type(bt_type); - exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_PG, ant_num); + if (rtlpriv->cfg->mod_params->ant_sel == 1) + exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_DETECTED, 1); + else + exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num); } void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv) -- GitLab From 37c52934c66810205707ddeb42eb08b06a5af4c4 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:40:56 -0500 Subject: [PATCH 1602/9938] rtlwifi: Fix Smatch warnings Smatch reports the following: CHECK drivers/net/wireless/realtek/rtlwifi/pci.c drivers/net/wireless/realtek/rtlwifi/pci.c:366 rtl_pci_check_buddy_priv() error: we previously assumed 'tpriv' could be null (see line 368) drivers/net/wireless/realtek/rtlwifi/pci.c:1216 _rtl_pci_init_struct() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/pci.c | 39 +++++++++++----------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 283d608b9973..1ac41b8bd19a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -359,30 +359,28 @@ static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); bool find_buddy_priv = false; - struct rtl_priv *tpriv = NULL; + struct rtl_priv *tpriv; struct rtl_pci_priv *tpcipriv = NULL; if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) { list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list, list) { - if (tpriv) { - tpcipriv = (struct rtl_pci_priv *)tpriv->priv; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "pcipriv->ndis_adapter.funcnumber %x\n", - pcipriv->ndis_adapter.funcnumber); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "tpcipriv->ndis_adapter.funcnumber %x\n", - tpcipriv->ndis_adapter.funcnumber); - - if ((pcipriv->ndis_adapter.busnumber == - tpcipriv->ndis_adapter.busnumber) && - (pcipriv->ndis_adapter.devnumber == - tpcipriv->ndis_adapter.devnumber) && - (pcipriv->ndis_adapter.funcnumber != - tpcipriv->ndis_adapter.funcnumber)) { - find_buddy_priv = true; - break; - } + tpcipriv = (struct rtl_pci_priv *)tpriv->priv; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "pcipriv->ndis_adapter.funcnumber %x\n", + pcipriv->ndis_adapter.funcnumber); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "tpcipriv->ndis_adapter.funcnumber %x\n", + tpcipriv->ndis_adapter.funcnumber); + + if ((pcipriv->ndis_adapter.busnumber == + tpcipriv->ndis_adapter.busnumber) && + (pcipriv->ndis_adapter.devnumber == + tpcipriv->ndis_adapter.devnumber) && + (pcipriv->ndis_adapter.funcnumber != + tpcipriv->ndis_adapter.funcnumber)) { + find_buddy_priv = true; + break; } } } @@ -1213,7 +1211,8 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, /*Tx/Rx related var */ _rtl_pci_init_trx_var(hw); - /*IBSS*/ mac->beacon_interval = 100; + /*IBSS*/ + mac->beacon_interval = 100; /*AMPDU*/ mac->min_space_cfg = 0; -- GitLab From 2e074fab347e1231bc1da156a12b37b6f746712c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:40:57 -0500 Subject: [PATCH 1603/9938] rtlwifi: btcoexist: Fix Smatch warning Smatch reports the following: CHECK drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c:3078 btc8723b2ant_run_coexist_mechanism() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c index 77cbd10e807d..205f78b3ab23 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c @@ -3075,7 +3075,7 @@ static void btc8723b2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) "[BTCoex], Action 2-Ant, " "algorithm = HS mode.\n"); btc8723b2ant_action_pan_hs(btcoexist); - break; + break; case BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP: BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, "[BTCoex], Action 2-Ant, " -- GitLab From 844026f609fc35918228cbb9ff2fd48e373504f7 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:40:58 -0500 Subject: [PATCH 1604/9938] rtlwifi: rtl8188ee: Fix Smatch warnings Smatch reports the following: CHECK drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c:1140 rtl88e_dm_check_txpower_tracking() warn: inconsistent indenting CHECK drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c:1906 _rtl88e_phy_lc_calibrate() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c | 2 +- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c index ce4da9d79fbd..db9a7829d568 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c @@ -1137,7 +1137,7 @@ void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw) } else { RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "Schedule TxPowerTracking !!\n"); - dm_txpower_track_cb_therm(hw); + dm_txpower_track_cb_therm(hw); rtlpriv->dm.tm_trigger = 0; } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c index a2bb02c7b837..416a9ba6382e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c @@ -1903,8 +1903,7 @@ static void _rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } else { rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); } -RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); } static void _rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, -- GitLab From de8a9a6eeb572f7f0e8a87df9f29264c04503af4 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:40:59 -0500 Subject: [PATCH 1605/9938] rtlwifi: rtl8192c-common: Fix Smatch warning Smatch lists the following: CHECK drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c:243 rtl92c_dm_false_alarm_counter_statistics() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c index 03cbe4cf110b..316be5ff69ca 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c @@ -240,7 +240,7 @@ static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); - ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); + ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); -- GitLab From 05d9e1bba43b3b9e722ca06fc45b79d93374be18 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:41:00 -0500 Subject: [PATCH 1606/9938] rtlwifi: rtl8192ee: Fix Smatch warning Smatch lists the following: CHECK drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c:371 rtl92ee_rx_query_desc() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index 24eff8ea4c2e..35e6bf7e233d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c @@ -368,7 +368,7 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, status->decrypted = !GET_RX_DESC_SWDEC(pdesc); status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); - status->timestamp_low = GET_RX_DESC_TSFL(pdesc); + status->timestamp_low = GET_RX_DESC_TSFL(pdesc); status->is_cck = RTL92EE_RX_HAL_IS_CCK_RATE(status->rate); status->macid = GET_RX_DESC_MACID(pdesc); -- GitLab From c42ceccec17056940d0c97da79ff14d71062cc28 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:41:01 -0500 Subject: [PATCH 1607/9938] rtlwifi: rtl8192se: Fix Smatch warning Smatch lists the following: CHECK drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c:648 rtl92s_phy_set_rf_power_state() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c index 4b4612fe2fdb..881821f4e243 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c @@ -645,7 +645,7 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, rtlpriv->psc.state_inap); ppsc->last_sleep_jiffies = jiffies; _rtl92se_phy_set_rf_sleep(hw); - break; + break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "switch case not processed\n"); -- GitLab From 154fb486df3d8e2fb346dfb9777abe20b23e1d6f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:41:02 -0500 Subject: [PATCH 1608/9938] rtlwifi: rtl8723ae: Fix Smatch warning Smatch reports the following: CHECK drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c:137 rtl8723e_dm_bt_need_to_dec_bt_pwr() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c index 00a0531cc5f4..44de695dc999 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c @@ -134,9 +134,9 @@ static bool rtl8723e_dm_bt_need_to_dec_bt_pwr(struct ieee80211_hw *hw) if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) { RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "Need to decrease bt power\n"); - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_DEC_BT_POWER; - return true; + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_DEC_BT_POWER; + return true; } rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_DEC_BT_POWER; -- GitLab From b3c4201bce5e32a353e68e1daf2aed213b8495e7 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:41:03 -0500 Subject: [PATCH 1609/9938] rtlwifi: rtl8723be: Fix Smatch warnings Smatch reports the following: CHECK drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c:1726 _rtl8723be_phy_path_a_rx_iqk() warn: inconsistent indenting drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c:2304 _rtl8723be_phy_lc_calibrate() warn: inconsistent indenting drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c:2609 _rtl8723be_phy_set_rf_power_state() warn: inconsistent indenting CHECK drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c:306 _rtl8723be_get_txpower_writeval_by_regulatory() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c | 10 ++++------ drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c index b7b73cbe346d..445f681d08c0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c @@ -1723,8 +1723,8 @@ static u8 _rtl8723be_phy_path_a_rx_iqk(struct ieee80211_hw *hw) /* Allen 20131125 */ tmp = (reg_eac & 0x03FF0000) >> 16; - if ((tmp & 0x200) > 0) - tmp = 0x400 - tmp; + if ((tmp & 0x200) > 0) + tmp = 0x400 - tmp; /* if Tx is OK, check whether Rx is OK */ if (!(reg_eac & BIT(27)) && (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && @@ -2301,8 +2301,7 @@ static void _rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } else { rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); } -RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); } static void _rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, @@ -2606,8 +2605,7 @@ static bool _rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, "IPS Set eRf nic enable\n"); rtstatus = rtl_ps_enable_nic(hw); } while (!rtstatus && (initializecount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); } else { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "Set ERFON sleeped:%d ms\n", diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c index 5ed4492d3c80..97f5a0377e7a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c @@ -303,8 +303,8 @@ static void _rtl8723be_get_txpower_writeval_by_regulatory( [chnlgroup][index + (rf ? 8 : 0)] & (0x7f << (i * 8))) >> (i * 8)); - if (pwr_diff_limit[i] > pwr_diff) - pwr_diff_limit[i] = pwr_diff; + if (pwr_diff_limit[i] > pwr_diff) + pwr_diff_limit[i] = pwr_diff; } customer_limit = (pwr_diff_limit[3] << 24) | -- GitLab From 1e812458206e3b787951868d6f8acaae5e3f4aca Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 17 Mar 2016 13:41:04 -0500 Subject: [PATCH 1610/9938] rtlwifi: rtl8821ae: Fix Smatch warnings Smatch reports the following: CHECK drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c:1960 rtl8812ae_dm_txpower_tracking_callback_thermalmeter() warn: inconsistent indenting CHECK drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c:455 phy_get_tx_swing_8812A() warn: inconsistent indenting drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c:517 phy_get_tx_swing_8812A() warn: inconsistent indenting Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c | 6 +++--- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index 95dcbff4673b..e346cb86cb08 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -1957,9 +1957,9 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p]; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n", - rtldm->thermalvalue, thermal_value); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n", + rtldm->thermalvalue, thermal_value); /*Record last Power Tracking Thermal Value*/ rtldm->thermalvalue = thermal_value; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 74165b3eb362..ddf74d527017 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -418,9 +418,9 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, out = 0x16A; /* -3 dB */ } } else { - u32 swing = 0, swing_a = 0, swing_b = 0; + u32 swing = 0, swing_a = 0, swing_b = 0; - if (band == BAND_ON_2_4G) { + if (band == BAND_ON_2_4G) { if (reg_swing_2g == auto_temp) { efuse_shadow_read(hw, 1, 0xC6, (u32 *)&swing); swing = (swing == 0xFF) ? 0x00 : swing; @@ -514,7 +514,7 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "<=== PHY_GetTxBBSwing_8812A, out = 0x%X\n", out); - return out; + return out; } void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) -- GitLab From 466414a084a90a15b81601bdde0c5803dc061ecd Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 17 Mar 2016 17:00:21 -0700 Subject: [PATCH 1611/9938] rtlwifi: btcoexist: Convert BTC_PRINTK to btc__dbg Use a more common logging style. Miscellanea: o Add specific logging macros for ALGORITHM and INTERFACE types o Output the messages at KERN_DEBUG o Coalesce formats o Align arguments o Whitespace style adjustments for only these changes Signed-off-by: Joe Perches Signed-off-by: Kalle Valo --- .../rtlwifi/btcoexist/halbtc8192e2ant.c | 847 +++++++++-------- .../rtlwifi/btcoexist/halbtc8723b1ant.c | 611 ++++++------- .../rtlwifi/btcoexist/halbtc8723b2ant.c | 854 ++++++++---------- .../rtlwifi/btcoexist/halbtc8821a1ant.c | 652 +++++++------ .../rtlwifi/btcoexist/halbtc8821a2ant.c | 851 +++++++++-------- .../realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 4 +- .../realtek/rtlwifi/btcoexist/halbtcoutsrc.h | 17 +- 7 files changed, 1851 insertions(+), 1985 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c index 451456835f87..a30af6cc21f3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c @@ -70,83 +70,83 @@ static u8 halbtc8192e2ant_btrssi_state(u8 level_num, u8 rssi_thresh, if (level_num == 2) { if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = LOW\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi pre state = LOW\n"); if (btrssi >= (rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { btrssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state switch to High\n"); } else { btrssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state stay at Low\n"); } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = HIGH\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi pre state = HIGH\n"); if (btrssi < rssi_thresh) { btrssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Low\n"); } else { btrssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi thresh error!!\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi thresh error!!\n"); return coex_sta->pre_bt_rssi_state; } if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = LOW\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi pre state = LOW\n"); if (btrssi >= (rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { btrssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Medium\n"); } else { btrssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state stay at Low\n"); } } else if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_MEDIUM) || (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi pre state = MEDIUM\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi pre state = MEDIUM\n"); if (btrssi >= (rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { btrssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state switch to High\n"); } else if (btrssi < rssi_thresh) { btrssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Low\n"); } else { btrssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state stay at Medium\n"); } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = HIGH\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi pre state = HIGH\n"); if (btrssi < rssi_thresh1) { btrssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Medium\n"); } else { btrssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "BT Rssi state stay at High\n"); } } } @@ -173,32 +173,28 @@ static u8 halbtc8192e2ant_wifirssi_state(struct btc_coexist *btcoexist, if (wifirssi >= (rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { wifirssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to High\n"); } else { wifirssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at Low\n"); } } else { if (wifirssi < rssi_thresh) { wifirssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Low\n"); } else { wifirssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "wifi RSSI thresh error!!\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI thresh error!!\n"); return coex_sta->pre_wifi_rssi_state[index]; } @@ -209,14 +205,12 @@ static u8 halbtc8192e2ant_wifirssi_state(struct btc_coexist *btcoexist, if (wifirssi >= (rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { wifirssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Medium\n"); } else { wifirssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at Low\n"); } } else if ((coex_sta->pre_wifi_rssi_state[index] == BTC_RSSI_STATE_MEDIUM) || @@ -225,31 +219,26 @@ static u8 halbtc8192e2ant_wifirssi_state(struct btc_coexist *btcoexist, if (wifirssi >= (rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { wifirssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to High\n"); } else if (wifirssi < rssi_thresh) { wifirssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Low\n"); } else { wifirssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at Medium\n"); } } else { if (wifirssi < rssi_thresh1) { wifirssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Medium\n"); } else { wifirssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at High\n"); } } } @@ -284,26 +273,26 @@ static void btc8192e2ant_monitor_bt_enable_dis(struct btc_coexist *btcoexist) bt_disabled = false; btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is enabled !!\n"); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is enabled !!\n"); } else { bt_disable_cnt++; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], bt all counters = 0, %d times!!\n", - bt_disable_cnt); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], bt all counters = 0, %d times!!\n", + bt_disable_cnt); if (bt_disable_cnt >= 2) { bt_disabled = true; btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is disabled !!\n"); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is disabled !!\n"); } } if (pre_bt_disabled != bt_disabled) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is from %s to %s!!\n", - (pre_bt_disabled ? "disabled" : "enabled"), - (bt_disabled ? "disabled" : "enabled")); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is from %s to %s!!\n", + (pre_bt_disabled ? "disabled" : "enabled"), + (bt_disabled ? "disabled" : "enabled")); pre_bt_disabled = bt_disabled; } } @@ -499,12 +488,12 @@ static void halbtc8192e2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) coex_sta->low_priority_tx = reg_lp_tx; coex_sta->low_priority_rx = reg_lp_rx; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex] High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex] Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex] High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex] Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); /* reset counter */ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); @@ -518,9 +507,9 @@ static void halbtc8192e2ant_querybt_info(struct btc_coexist *btcoexist) h2c_parameter[0] |= BIT0; /* trigger */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); } @@ -592,8 +581,8 @@ static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "No BT link exists!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "No BT link exists!!!\n"); return algorithm; } @@ -608,27 +597,27 @@ static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) if (numdiffprofile == 1) { if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO only\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO only\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; } else { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID only\n"); + btc_alg_dbg(ALGO_TRACE, + "HID only\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_HID; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "A2DP only\n"); + btc_alg_dbg(ALGO_TRACE, + "A2DP only\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_A2DP; } else if (bt_link_info->pan_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "PAN(HS) only\n"); + btc_alg_dbg(ALGO_TRACE, + "PAN(HS) only\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "PAN(EDR) only\n"); + btc_alg_dbg(ALGO_TRACE, + "PAN(EDR) only\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR; } @@ -637,21 +626,21 @@ static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) } else if (numdiffprofile == 2) { if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + HID\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + A2DP ==> SCO\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + A2DP ==> SCO\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; } else if (bt_link_info->pan_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + PAN(HS)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + PAN(EDR)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_SCO_PAN; } @@ -660,38 +649,38 @@ static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { if (stack_info->num_of_hid >= 2) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID*2 + A2DP\n"); + btc_alg_dbg(ALGO_TRACE, + "HID*2 + A2DP\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + A2DP\n"); + btc_alg_dbg(ALGO_TRACE, + "HID + A2DP\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_HID_A2DP; } } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "HID + PAN(HS)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "HID + PAN(EDR)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "A2DP + PAN(HS)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "A2DP + PAN(EDR)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP; } @@ -701,30 +690,30 @@ static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID + A2DP ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + HID + A2DP ==> HID\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + HID + PAN(HS)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + HID + PAN(EDR)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_SCO_PAN; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + A2DP + PAN(HS)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO + A2DP + PAN(EDR)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; } @@ -734,13 +723,13 @@ static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "HID + A2DP + PAN(HS)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "HID + A2DP + PAN(EDR)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR; } @@ -752,12 +741,12 @@ static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "ErrorSCO+HID+A2DP+PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "ErrorSCO+HID+A2DP+PAN(HS)\n"); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO+HID+A2DP+PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "SCO+HID+A2DP+PAN(EDR)\n"); algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; } @@ -778,10 +767,10 @@ static void halbtc8192e2ant_setfw_dac_swinglevel(struct btc_coexist *btcoexist, */ h2c_parameter[0] = dac_swinglvl; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swinglvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swinglvl); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); } @@ -793,9 +782,9 @@ static void halbtc8192e2ant_set_fwdec_btpwr(struct btc_coexist *btcoexist, h2c_parameter[0] = dec_btpwr_lvl; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex] decrease Bt Power level = %d, FW write 0x62 = 0x%x\n", - dec_btpwr_lvl, h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex] decrease Bt Power level = %d, FW write 0x62 = 0x%x\n", + dec_btpwr_lvl, h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); } @@ -803,15 +792,15 @@ static void halbtc8192e2ant_set_fwdec_btpwr(struct btc_coexist *btcoexist, static void halbtc8192e2ant_dec_btpwr(struct btc_coexist *btcoexist, bool force_exec, u8 dec_btpwr_lvl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s Dec BT power level = %d\n", - (force_exec ? "force to" : ""), dec_btpwr_lvl); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s Dec BT power level = %d\n", + (force_exec ? "force to" : ""), dec_btpwr_lvl); coex_dm->cur_dec_bt_pwr = dec_btpwr_lvl; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], preBtDecPwrLvl=%d, curBtDecPwrLvl=%d\n", - coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], preBtDecPwrLvl=%d, curBtDecPwrLvl=%d\n", + coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); } halbtc8192e2ant_set_fwdec_btpwr(btcoexist, coex_dm->cur_dec_bt_pwr); @@ -828,10 +817,10 @@ static void halbtc8192e2ant_set_bt_autoreport(struct btc_coexist *btcoexist, if (enable_autoreport) h2c_parameter[0] |= BIT0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", - (enable_autoreport ? "Enabled!!" : "Disabled!!"), - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", + (enable_autoreport ? "Enabled!!" : "Disabled!!"), + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); } @@ -840,17 +829,17 @@ static void halbtc8192e2ant_bt_autoreport(struct btc_coexist *btcoexist, bool force_exec, bool enable_autoreport) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT Auto report = %s\n", - (force_exec ? "force to" : ""), - ((enable_autoreport) ? "Enabled" : "Disabled")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s BT Auto report = %s\n", + (force_exec ? "force to" : ""), + ((enable_autoreport) ? "Enabled" : "Disabled")); coex_dm->cur_bt_auto_report = enable_autoreport; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex] bPreBtAutoReport=%d, bCurBtAutoReport=%d\n", - coex_dm->pre_bt_auto_report, - coex_dm->cur_bt_auto_report); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex] bPreBtAutoReport=%d, bCurBtAutoReport=%d\n", + coex_dm->pre_bt_auto_report, + coex_dm->cur_bt_auto_report); if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) return; @@ -864,16 +853,16 @@ static void halbtc8192e2ant_bt_autoreport(struct btc_coexist *btcoexist, static void halbtc8192e2ant_fw_dac_swinglvl(struct btc_coexist *btcoexist, bool force_exec, u8 fw_dac_swinglvl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set FW Dac Swing level = %d\n", - (force_exec ? "force to" : ""), fw_dac_swinglvl); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s set FW Dac Swing level = %d\n", + (force_exec ? "force to" : ""), fw_dac_swinglvl); coex_dm->cur_fw_dac_swing_lvl = fw_dac_swinglvl; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex] preFwDacSwingLvl=%d, curFwDacSwingLvl=%d\n", - coex_dm->pre_fw_dac_swing_lvl, - coex_dm->cur_fw_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex] preFwDacSwingLvl=%d, curFwDacSwingLvl=%d\n", + coex_dm->pre_fw_dac_swing_lvl, + coex_dm->cur_fw_dac_swing_lvl); if (coex_dm->pre_fw_dac_swing_lvl == coex_dm->cur_fw_dac_swing_lvl) @@ -891,8 +880,8 @@ static void btc8192e2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, { if (rx_rf_shrink_on) { /* Shrink RF Rx LPF corner */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Shrink RF Rx LPF corner!!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Shrink RF Rx LPF corner!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff, 0xffffc); } else { @@ -900,8 +889,8 @@ static void btc8192e2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, * After initialized, we can use coex_dm->btRf0x1eBackup */ if (btcoexist->initilized) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Resume RF Rx LPF corner!!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Resume RF Rx LPF corner!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff, coex_dm->bt_rf0x1e_backup); @@ -912,17 +901,17 @@ static void btc8192e2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, static void halbtc8192e2ant_rf_shrink(struct btc_coexist *btcoexist, bool force_exec, bool rx_rf_shrink_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn Rx RF Shrink = %s\n", - (force_exec ? "force to" : ""), - ((rx_rf_shrink_on) ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn Rx RF Shrink = %s\n", + (force_exec ? "force to" : ""), + ((rx_rf_shrink_on) ? "ON" : "OFF")); coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex]bPreRfRxLpfShrink=%d,bCurRfRxLpfShrink=%d\n", - coex_dm->pre_rf_rx_lpf_shrink, - coex_dm->cur_rf_rx_lpf_shrink); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex]bPreRfRxLpfShrink=%d,bCurRfRxLpfShrink=%d\n", + coex_dm->pre_rf_rx_lpf_shrink, + coex_dm->cur_rf_rx_lpf_shrink); if (coex_dm->pre_rf_rx_lpf_shrink == coex_dm->cur_rf_rx_lpf_shrink) @@ -939,8 +928,8 @@ static void halbtc8192e2ant_set_dac_swingreg(struct btc_coexist *btcoexist, { u8 val = (u8)level; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Write SwDacSwing = 0x%x\n", level); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Write SwDacSwing = 0x%x\n", level); btcoexist->btc_write_1byte_bitmask(btcoexist, 0x883, 0x3e, val); } @@ -958,22 +947,22 @@ static void halbtc8192e2ant_DacSwing(struct btc_coexist *btcoexist, bool force_exec, bool dac_swingon, u32 dac_swinglvl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn DacSwing=%s, dac_swinglvl = 0x%x\n", - (force_exec ? "force to" : ""), - ((dac_swingon) ? "ON" : "OFF"), dac_swinglvl); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn DacSwing=%s, dac_swinglvl = 0x%x\n", + (force_exec ? "force to" : ""), + ((dac_swingon) ? "ON" : "OFF"), dac_swinglvl); coex_dm->cur_dac_swing_on = dac_swingon; coex_dm->cur_dac_swing_lvl = dac_swinglvl; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl = 0x%x, ", - coex_dm->pre_dac_swing_on, - coex_dm->pre_dac_swing_lvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "bCurDacSwingOn=%d, curDacSwingLvl = 0x%x\n", - coex_dm->cur_dac_swing_on, - coex_dm->cur_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl = 0x%x, ", + coex_dm->pre_dac_swing_on, + coex_dm->pre_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "bCurDacSwingOn=%d, curDacSwingLvl = 0x%x\n", + coex_dm->cur_dac_swing_on, + coex_dm->cur_dac_swing_lvl); if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && (coex_dm->pre_dac_swing_lvl == coex_dm->cur_dac_swing_lvl)) @@ -991,8 +980,8 @@ static void halbtc8192e2ant_set_agc_table(struct btc_coexist *btcoexist, { /* BB AGC Gain Table */ if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table On!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table On!\n"); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x0a1A0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x091B0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x081C0001); @@ -1000,8 +989,8 @@ static void halbtc8192e2ant_set_agc_table(struct btc_coexist *btcoexist, btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x061E0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x051F0001); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table Off!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table Off!\n"); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xaa1A0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa91B0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa81C0001); @@ -1014,16 +1003,17 @@ static void halbtc8192e2ant_set_agc_table(struct btc_coexist *btcoexist, static void halbtc8192e2ant_AgcTable(struct btc_coexist *btcoexist, bool force_exec, bool agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s %s Agc Table\n", - (force_exec ? "force to" : ""), - ((agc_table_en) ? "Enable" : "Disable")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s %s Agc Table\n", + (force_exec ? "force to" : ""), + ((agc_table_en) ? "Enable" : "Disable")); coex_dm->cur_agc_table_en = agc_table_en; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", - coex_dm->pre_agc_table_en, coex_dm->cur_agc_table_en); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", + coex_dm->pre_agc_table_en, + coex_dm->cur_agc_table_en); if (coex_dm->pre_agc_table_en == coex_dm->cur_agc_table_en) return; @@ -1037,20 +1027,20 @@ static void halbtc8192e2ant_set_coex_table(struct btc_coexist *btcoexist, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); } @@ -1059,30 +1049,30 @@ static void halbtc8192e2ant_coex_table(struct btc_coexist *btcoexist, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, ", - (force_exec ? "force to" : ""), val0x6c0); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - val0x6c4, val0x6c8, val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, ", + (force_exec ? "force to" : ""), val0x6c0); + btc_alg_dbg(ALGO_TRACE_SW, + "0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", + val0x6c4, val0x6c8, val0x6cc); coex_dm->cur_val0x6c0 = val0x6c0; coex_dm->cur_val0x6c4 = val0x6c4; coex_dm->cur_val0x6c8 = val0x6c8; coex_dm->cur_val0x6cc = val0x6cc; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c4 = 0x%x, ", - coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", - coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c4 = 0x%x,\n", - coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", - coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c4 = 0x%x, ", + coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", + coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c4 = 0x%x\n", + coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", + coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && @@ -1136,9 +1126,9 @@ static void halbtc8192e2ant_set_fw_ignore_wlanact(struct btc_coexist *btcoexist, if (enable) h2c_parameter[0] |= BIT0; /* function enable */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex]set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex]set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); } @@ -1146,18 +1136,18 @@ static void halbtc8192e2ant_set_fw_ignore_wlanact(struct btc_coexist *btcoexist, static void halbtc8192e2ant_IgnoreWlanAct(struct btc_coexist *btcoexist, bool force_exec, bool enable) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); coex_dm->cur_ignore_wlan_act = enable; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreIgnoreWlanAct = %d ", - coex_dm->pre_ignore_wlan_act); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "bCurIgnoreWlanAct = %d!!\n", - coex_dm->cur_ignore_wlan_act); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreIgnoreWlanAct = %d ", + coex_dm->pre_ignore_wlan_act); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "bCurIgnoreWlanAct = %d!!\n", + coex_dm->cur_ignore_wlan_act); if (coex_dm->pre_ignore_wlan_act == coex_dm->cur_ignore_wlan_act) @@ -1185,11 +1175,11 @@ static void halbtc8192e2ant_SetFwPstdma(struct btc_coexist *btcoexist, u8 byte1, coex_dm->ps_tdma_para[3] = byte4; coex_dm->ps_tdma_para[4] = byte5; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | - h2c_parameter[3] << 8 | h2c_parameter[4]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | h2c_parameter[4]); btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); } @@ -1213,20 +1203,20 @@ static void btc8192e2ant_sw_mec2(struct btc_coexist *btcoexist, static void halbtc8192e2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec, bool turn_on, u8 type) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn %s PS TDMA, type=%d\n", - (force_exec ? "force to" : ""), - (turn_on ? "ON" : "OFF"), type); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn %s PS TDMA, type=%d\n", + (force_exec ? "force to" : ""), + (turn_on ? "ON" : "OFF"), type); coex_dm->cur_ps_tdma_on = turn_on; coex_dm->cur_ps_tdma = type; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", - coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", - coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", + coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", + coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) @@ -1353,8 +1343,8 @@ static void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist, u8 mimops = BTC_MIMO_PS_DYNAMIC; u32 disra_mask = 0x0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], REAL set SS Type = %d\n", sstype); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], REAL set SS Type = %d\n", sstype); disra_mask = halbtc8192e2ant_decidera_mask(btcoexist, sstype, coex_dm->curra_masktype); @@ -1386,9 +1376,9 @@ static void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist, static void halbtc8192e2ant_switch_sstype(struct btc_coexist *btcoexist, bool force_exec, u8 new_sstype) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], %s Switch SS Type = %d\n", - (force_exec ? "force to" : ""), new_sstype); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], %s Switch SS Type = %d\n", + (force_exec ? "force to" : ""), new_sstype); coex_dm->cur_sstype = new_sstype; if (!force_exec) { @@ -1469,8 +1459,8 @@ static bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non-connected idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non-connected idle!!\n"); if ((BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE == coex_dm->bt_status) || @@ -1506,8 +1496,8 @@ static bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi connected + BT non connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "Wifi connected + BT non connected-idle!!\n"); halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 2); @@ -1534,8 +1524,8 @@ static bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) if (bt_hson) return false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi connected + BT connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "Wifi connected + BT connected-idle!!\n"); halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 2); @@ -1560,12 +1550,12 @@ static bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) &low_pwr_disable); if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi Connected-Busy + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "Wifi Connected-Busy + BT Busy!!\n"); common = false; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi Connected-Idle + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "Wifi Connected-Idle + BT Busy!!\n"); halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); @@ -1592,9 +1582,8 @@ static void btc8192e_int1(struct btc_coexist *btcoexist, bool tx_pause, int result) { if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 71) { halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, @@ -1689,9 +1678,8 @@ static void btc8192e_int1(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 71); @@ -1795,9 +1783,8 @@ static void btc8192e_int2(struct btc_coexist *btcoexist, bool tx_pause, int result) { if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 1) { halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); @@ -1886,9 +1873,8 @@ static void btc8192e_int2(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); @@ -1983,9 +1969,8 @@ static void btc8192e_int3(struct btc_coexist *btcoexist, bool tx_pause, int result) { if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 1) { halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); @@ -2074,9 +2059,8 @@ static void btc8192e_int3(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); @@ -2178,13 +2162,13 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, int result; u8 retry_cnt = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjust()\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjust()\n"); if (!coex_dm->auto_tdma_adjust) { coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); if (sco_hid) { if (tx_pause) { if (max_interval == 1) { @@ -2288,11 +2272,11 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, } else { /* accquire the BT TRx retry count from BT_Info byte2 */ retry_cnt = coex_sta->bt_retry_cnt; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], retry_cnt = %d\n", retry_cnt); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_cnt=%d\n", - up, dn, m, n, wait_cnt); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], retry_cnt = %d\n", retry_cnt); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_cnt=%d\n", + up, dn, m, n, wait_cnt); result = 0; wait_cnt++; /* no retry in the last 2-second duration */ @@ -2309,9 +2293,8 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, up = 0; dn = 0; result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex]Increase wifi duration!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex]Increase wifi duration!!\n"); } } else if (retry_cnt <= 3) { up--; @@ -2334,9 +2317,8 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, dn = 0; wait_cnt = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "Reduce wifi duration for retry<3\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "Reduce wifi duration for retry<3\n"); } } else { if (wait_cnt == 1) @@ -2352,12 +2334,12 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, dn = 0; wait_cnt = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "Decrease wifi duration for retryCounter>3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "Decrease wifi duration for retryCounter>3!!\n"); } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], max Interval = %d\n", max_interval); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], max Interval = %d\n", max_interval); if (max_interval == 1) btc8192e_int1(btcoexist, tx_pause, result); else if (max_interval == 2) @@ -2373,11 +2355,11 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { bool scan = false, link = false, roam = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], PsTdma type dismatch!!!, "); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "curPsTdma=%d, recordPsTdma=%d\n", - coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], PsTdma type dismatch!!!, "); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "curPsTdma=%d, recordPsTdma=%d\n", + coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); @@ -2388,9 +2370,8 @@ static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, true, coex_dm->tdma_adj_type); else - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); } } @@ -2594,8 +2575,8 @@ static void halbtc8192e2ant_action_a2dp(struct btc_coexist *btcoexist) btrssi_state == BTC_RSSI_STATE_STAY_LOW) && (wifirssi_state == BTC_RSSI_STATE_LOW || wifirssi_state == BTC_RSSI_STATE_STAY_LOW)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2dp, wifi/bt rssi both LOW!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], A2dp, wifi/bt rssi both LOW!!\n"); long_dist = true; } if (long_dist) { @@ -3100,105 +3081,105 @@ static void halbtc8192e2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) { u8 algorithm = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], return for Manual CTRL <===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], return for Manual CTRL <===\n"); return; } if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); return; } algorithm = halbtc8192e2ant_action_algorithm(btcoexist); if (coex_sta->c2h_bt_inquiry_page && (BT_8192E_2ANT_COEX_ALGO_PANHS != algorithm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT is under inquiry/page scan !!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT is under inquiry/page scan !!\n"); halbtc8192e2ant_action_bt_inquiry(btcoexist); return; } coex_dm->cur_algorithm = algorithm; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); if (halbtc8192e2ant_is_common_action(btcoexist)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant common.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant common\n"); coex_dm->auto_tdma_adjust = false; } else { if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex] preAlgorithm=%d, curAlgorithm=%d\n", - coex_dm->pre_algorithm, - coex_dm->cur_algorithm); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex] preAlgorithm=%d, curAlgorithm=%d\n", + coex_dm->pre_algorithm, + coex_dm->cur_algorithm); coex_dm->auto_tdma_adjust = false; } switch (coex_dm->cur_algorithm) { case BT_8192E_2ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = SCO.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = SCO\n"); halbtc8192e2ant_action_sco(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_SCO_PAN: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = SCO+PAN(EDR).\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = SCO+PAN(EDR)\n"); halbtc8192e2ant_action_sco_pan(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = HID\n"); halbtc8192e2ant_action_hid(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = A2DP\n"); halbtc8192e2ant_action_a2dp(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = A2DP+PAN(HS).\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = A2DP+PAN(HS)\n"); halbtc8192e2ant_action_a2dp_pan_hs(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = PAN(EDR).\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = PAN(EDR)\n"); halbtc8192e2ant_action_pan_edr(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HS mode.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = HS mode\n"); halbtc8192e2ant_action_pan_hs(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = PAN+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = PAN+A2DP\n"); halbtc8192e2ant_action_pan_edr_a2dp(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = PAN(EDR)+HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = PAN(EDR)+HID\n"); halbtc8192e2ant_action_pan_edr_hid(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HID+A2DP+PAN.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = HID+A2DP+PAN\n"); btc8192e2ant_action_hid_a2dp_pan_edr(btcoexist); break; case BT_8192E_2ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HID+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = HID+A2DP\n"); halbtc8192e2ant_action_hid_a2dp(btcoexist); break; default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = unknown!!\n"); + btc_alg_dbg(ALGO_TRACE, + "Action 2-Ant, algorithm = unknown!!\n"); /* halbtc8192e2ant_coex_alloff(btcoexist); */ break; } @@ -3212,8 +3193,8 @@ static void halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist, u16 u16tmp = 0; u8 u8tmp = 0; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 2Ant Init HW Config!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], 2Ant Init HW Config!!\n"); if (backup) { /* backup rf 0x1e value */ @@ -3296,8 +3277,8 @@ void ex_halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist) void ex_halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); halbtc8192e2ant_init_coex_dm(btcoexist); } @@ -3525,13 +3506,13 @@ void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist) void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); coex_sta->under_ips = true; halbtc8192e2ant_coex_alloff(btcoexist); } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); coex_sta->under_ips = false; } } @@ -3539,12 +3520,12 @@ void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); coex_sta->under_lps = true; } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); coex_sta->under_lps = false; } } @@ -3552,21 +3533,21 @@ void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) void ex_halbtc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_SCAN_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); else if (BTC_SCAN_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); } void ex_halbtc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_ASSOCIATE_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); else if (BTC_ASSOCIATE_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); } void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist, @@ -3582,11 +3563,11 @@ void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist, return; if (BTC_MEDIA_CONNECT == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); /* only 2.4G we need to inform bt the chnl mask */ btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, @@ -3606,10 +3587,10 @@ void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist, coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | - h2c_parameter[2]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | + h2c_parameter[2]); btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); } @@ -3618,8 +3599,8 @@ void ex_halbtc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist, u8 type) { if (type == BTC_PACKET_DHCP) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], DHCP Packet notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], DHCP Packet notify\n"); } void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, @@ -3637,19 +3618,19 @@ void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, rsp_source = BT_INFO_SRC_8192E_2ANT_WIFI_FW; coex_sta->bt_info_c2h_cnt[rsp_source]++; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length=%d, hex data = [", - rsp_source, length); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Bt info[%d], length=%d, hex data = [", + rsp_source, length); for (i = 0; i < length; i++) { coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; if (i == 1) bt_info = tmp_buf[i]; if (i == length-1) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); } if (BT_INFO_SRC_8192E_2ANT_WIFI_FW != rsp_source) { @@ -3666,8 +3647,8 @@ void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, * because bt is reset and loss of the info. */ if ((coex_sta->bt_info_ext & BIT1)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "bit1, send wifi BW&Chnl to BT!!\n"); + btc_alg_dbg(ALGO_TRACE, + "bit1, send wifi BW&Chnl to BT!!\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); if (wifi_connected) @@ -3683,8 +3664,8 @@ void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, if ((coex_sta->bt_info_ext & BIT3)) { if (!btcoexist->manual_control && !btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "bit3, BT NOT ignore Wlan active!\n"); + btc_alg_dbg(ALGO_TRACE, + "bit3, BT NOT ignore Wlan active!\n"); halbtc8192e2ant_IgnoreWlanAct(btcoexist, FORCE_EXEC, false); @@ -3742,25 +3723,25 @@ void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, if (!(bt_info&BT_INFO_8192E_2ANT_B_CONNECTION)) { coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Non-Connected idle!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Non-Connected idle!!!\n"); } else if (bt_info == BT_INFO_8192E_2ANT_B_CONNECTION) { coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], bt_infoNotify(), BT Connected-idle!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], bt_infoNotify(), BT Connected-idle!!!\n"); } else if ((bt_info&BT_INFO_8192E_2ANT_B_SCO_ESCO) || (bt_info&BT_INFO_8192E_2ANT_B_SCO_BUSY)) { coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], bt_infoNotify(), BT SCO busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], bt_infoNotify(), BT SCO busy!!!\n"); } else if (bt_info&BT_INFO_8192E_2ANT_B_ACL_BUSY) { coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], bt_infoNotify(), BT ACL busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], bt_infoNotify(), BT ACL busy!!!\n"); } else { coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex]bt_infoNotify(), BT Non-Defined state!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex]bt_infoNotify(), BT Non-Defined state!!!\n"); } if ((BT_8192E_2ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || @@ -3788,7 +3769,7 @@ void ex_halbtc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist, void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); + btc_iface_dbg(INTF_NOTIFY, "[BTCoex], Halt notify\n"); halbtc8192e2ant_IgnoreWlanAct(btcoexist, FORCE_EXEC, true); ex_halbtc8192e2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); @@ -3801,29 +3782,29 @@ void ex_halbtc8192e2ant_periodical(struct btc_coexist *btcoexist) struct btc_board_info *board_info = &btcoexist->board_info; struct btc_stack_info *stack_info = &btcoexist->stack_info; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "=======================Periodical=======================\n"); + btc_alg_dbg(ALGO_TRACE, + "=======================Periodical=======================\n"); if (dis_ver_info_cnt <= 5) { dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); + btc_iface_dbg(INTF_INIT, + "************************************************\n"); + btc_iface_dbg(INTF_INIT, + "Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, board_info->btdm_ant_num, + board_info->btdm_ant_pos); + btc_iface_dbg(INTF_INIT, + "BT stack/ hci ext ver = %s / %d\n", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8192e_2ant, glcoex_ver_8192e_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "************************************************\n"); + btc_iface_dbg(INTF_INIT, + "CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8192e_2ant, glcoex_ver_8192e_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + btc_iface_dbg(INTF_INIT, + "************************************************\n"); } #if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c index 7e239d3cea26..16add42a62af 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c @@ -74,28 +74,28 @@ static u8 halbtc8723b1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else { if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); return coex_sta->pre_bt_rssi_state; } @@ -104,12 +104,12 @@ static u8 halbtc8723b1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_MEDIUM) || @@ -118,26 +118,26 @@ static u8 halbtc8723b1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Medium\n"); } } else { if (bt_rssi < rssi_thresh1) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } @@ -165,32 +165,28 @@ static u8 halbtc8723b1ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else { if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); return coex_sta->pre_wifi_rssi_state[index]; } @@ -201,14 +197,12 @@ static u8 halbtc8723b1ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else if ((coex_sta->pre_wifi_rssi_state[index] == BTC_RSSI_STATE_MEDIUM) || @@ -217,31 +211,26 @@ static u8 halbtc8723b1ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Medium\n"); } } else { if (wifi_rssi < rssi_thresh1) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } @@ -435,9 +424,9 @@ static void halbtc8723b1ant_query_bt_info(struct btc_coexist *btcoexist) h2c_parameter[0] |= BIT0; /* trigger*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); } @@ -532,8 +521,8 @@ static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No BT link exists!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], No BT link exists!!!\n"); return algorithm; } @@ -548,27 +537,27 @@ static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) if (numdiffprofile == 1) { if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO only\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; } else { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID only\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = A2DP only\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP; } else if (bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(HS) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = PAN(HS) only\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(EDR) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = PAN(EDR) only\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR; } @@ -577,21 +566,21 @@ static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) } else if (numdiffprofile == 2) { if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; } else if (bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(HS)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; } @@ -599,32 +588,32 @@ static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) } else { if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(HS)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(EDR)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP; } @@ -634,31 +623,31 @@ static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID; } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; } @@ -668,13 +657,13 @@ static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR; } @@ -686,11 +675,11 @@ static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; } @@ -717,9 +706,9 @@ static void btc8723b1ant_set_sw_pen_tx_rate_adapt(struct btc_coexist *btcoexist, h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36 */ } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); } @@ -743,20 +732,20 @@ static void halbtc8723b1ant_set_coex_table(struct btc_coexist *btcoexist, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); } @@ -765,10 +754,10 @@ static void halbtc8723b1ant_coex_table(struct btc_coexist *btcoexist, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6cc = 0x%x\n", - (force_exec ? "force to" : ""), - val0x6c0, val0x6c4, val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6cc = 0x%x\n", + (force_exec ? "force to" : ""), + val0x6c0, val0x6c4, val0x6cc); coex_dm->cur_val0x6c0 = val0x6c0; coex_dm->cur_val0x6c4 = val0x6c4; coex_dm->cur_val0x6c8 = val0x6c8; @@ -839,9 +828,9 @@ static void halbtc8723b1ant_SetFwIgnoreWlanAct(struct btc_coexist *btcoexist, if (enable) h2c_parameter[0] |= BIT0; /* function enable */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); } @@ -849,16 +838,16 @@ static void halbtc8723b1ant_SetFwIgnoreWlanAct(struct btc_coexist *btcoexist, static void halbtc8723b1ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); coex_dm->cur_ignore_wlan_act = enable; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); if (coex_dm->pre_ignore_wlan_act == coex_dm->cur_ignore_wlan_act) @@ -882,8 +871,8 @@ static void halbtc8723b1ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, if (ap_enable) { if ((byte1 & BIT4) && !(byte1 & BIT5)) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], FW for 1Ant AP mode\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], FW for 1Ant AP mode\n"); real_byte1 &= ~BIT4; real_byte1 |= BIT5; @@ -904,13 +893,13 @@ static void halbtc8723b1ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, coex_dm->ps_tdma_para[3] = byte4; coex_dm->ps_tdma_para[4] = real_byte5; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1] << 24 | - h2c_parameter[2] << 16 | - h2c_parameter[3] << 8 | - h2c_parameter[4]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | + h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | + h2c_parameter[4]); btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); } @@ -929,22 +918,22 @@ static void halbtc8723b1ant_LpsRpwm(struct btc_coexist *btcoexist, bool force_exec, u8 lps_val, u8 rpwm_val) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", - (force_exec ? "force to" : ""), lps_val, rpwm_val); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", + (force_exec ? "force to" : ""), lps_val, rpwm_val); coex_dm->cur_lps = lps_val; coex_dm->cur_rpwm = rpwm_val; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RxBeaconMode = 0x%x , LPS-RPWM = 0x%x!!\n", - coex_dm->cur_lps, coex_dm->cur_rpwm); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RxBeaconMode = 0x%x , LPS-RPWM = 0x%x!!\n", + coex_dm->cur_lps, coex_dm->cur_rpwm); if ((coex_dm->pre_lps == coex_dm->cur_lps) && (coex_dm->pre_rpwm == coex_dm->cur_rpwm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RPWM_Last = 0x%x , LPS-RPWM_Now = 0x%x!!\n", - coex_dm->pre_rpwm, coex_dm->cur_rpwm); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RPWM_Last = 0x%x , LPS-RPWM_Now = 0x%x!!\n", + coex_dm->pre_rpwm, coex_dm->cur_rpwm); return; } @@ -958,8 +947,8 @@ static void halbtc8723b1ant_LpsRpwm(struct btc_coexist *btcoexist, static void halbtc8723b1ant_sw_mechanism(struct btc_coexist *btcoexist, bool low_penalty_ra) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); halbtc8723b1ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); } @@ -1174,13 +1163,13 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist, if (!force_exec) { if (coex_dm->cur_ps_tdma_on) - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ******** TDMA(on, %d) *********\n", - coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], ******** TDMA(on, %d) *********\n", + coex_dm->cur_ps_tdma); else - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ******** TDMA(off, %d) ********\n", - coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], ******** TDMA(off, %d) ********\n", + coex_dm->cur_ps_tdma); if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) @@ -1394,45 +1383,45 @@ static bool halbtc8723b1ant_is_common_action(struct btc_coexist *btcoexist) if (!wifi_connected && BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == coex_dm->bt_status) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); halbtc8723b1ant_sw_mechanism(btcoexist, false); commom = true; } else if (wifi_connected && (BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT non connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi connected + BT non connected-idle!!\n"); halbtc8723b1ant_sw_mechanism(btcoexist, false); commom = true; } else if (!wifi_connected && (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); halbtc8723b1ant_sw_mechanism(btcoexist, false); commom = true; } else if (wifi_connected && (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi connected + BT connected-idle!!\n"); halbtc8723b1ant_sw_mechanism(btcoexist, false); commom = true; } else if (!wifi_connected && (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE != coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - ("[BTCoex], Wifi non connected-idle + BT Busy!!\n")); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT Busy!!\n"); halbtc8723b1ant_sw_mechanism(btcoexist, false); commom = true; } else { if (wifi_busy) - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); else - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); commom = false; } @@ -1451,8 +1440,8 @@ static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, u8 retry_count = 0, bt_info_ext; bool wifi_busy = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjustForAcl()\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjustForAcl()\n"); if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY == wifi_status) wifi_busy = true; @@ -1481,8 +1470,8 @@ static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, if (!coex_dm->auto_tdma_adjust) { coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); coex_dm->tdma_adj_type = 2; @@ -1513,9 +1502,8 @@ static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, up = 0; dn = 0; result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi duration!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi duration!!\n"); } } else if (retry_count <= 3) { up--; @@ -1538,9 +1526,8 @@ static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); } } else { if (wait_count == 1) @@ -1556,8 +1543,8 @@ static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); } if (result == -1) { @@ -1602,9 +1589,9 @@ static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, } } else { /*no change */ /*if busy / idle change */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex],********* TDMA(on, %d) ********\n", - coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex],********* TDMA(on, %d) ********\n", + coex_dm->cur_ps_tdma); } if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 && @@ -2010,15 +1997,15 @@ static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist) bool scan = false, link = false, roam = false; bool under_4way = false, ap_enable = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect()===>\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], CoexForWifiConnect()===>\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &under_4way); if (under_4way) { halbtc8723b1ant_action_wifi_connected_special_packet(btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); return; } @@ -2032,8 +2019,8 @@ static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist) else halbtc8723b1ant_action_wifi_connected_special_packet( btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); return; } @@ -2102,58 +2089,58 @@ static void btc8723b1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) if (!halbtc8723b1ant_is_common_action(btcoexist)) { switch (coex_dm->cur_algorithm) { case BT_8723B_1ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = SCO.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = SCO\n"); halbtc8723b1ant_action_sco(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HID\n"); halbtc8723b1ant_action_hid(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP\n"); halbtc8723b1ant_action_a2dp(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP+PAN(HS).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP+PAN(HS)\n"); halbtc8723b1ant_action_a2dp_pan_hs(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR)\n"); halbtc8723b1ant_action_pan_edr(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HS mode.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HS mode\n"); halbtc8723b1ant_action_pan_hs(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = PAN+A2DP\n"); halbtc8723b1ant_action_pan_edr_a2dp(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR)+HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR)+HID\n"); halbtc8723b1ant_action_pan_edr_hid(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP+PAN.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP+PAN\n"); btc8723b1ant_action_hid_a2dp_pan_edr(btcoexist); break; case BT_8723B_1ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP\n"); halbtc8723b1ant_action_hid_a2dp(btcoexist); break; default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = coexist All Off!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = coexist All Off!!\n"); break; } coex_dm->pre_algorithm = coex_dm->cur_algorithm; @@ -2171,24 +2158,24 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) u32 wifi_link_status = 0; u32 num_of_wifi_link = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); return; } if (btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); return; } if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); return; } @@ -2267,8 +2254,8 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) if (!wifi_connected) { bool scan = false, link = false, roam = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is non connected-idle !!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], wifi is non connected-idle !!!\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); @@ -2305,8 +2292,8 @@ static void halbtc8723b1ant_init_hw_config(struct btc_coexist *btcoexist, u8 u8tmp = 0; u32 cnt_bt_cal_chk = 0; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 1Ant Init HW Config!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], 1Ant Init HW Config!!\n"); if (backup) {/* backup rf 0x1e value */ coex_dm->backup_arfr_cnt1 = @@ -2333,14 +2320,14 @@ static void halbtc8723b1ant_init_hw_config(struct btc_coexist *btcoexist, u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x49d); cnt_bt_cal_chk++; if (u32tmp & BIT0) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ########### BT calibration(cnt=%d) ###########\n", - cnt_bt_cal_chk); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ########### BT calibration(cnt=%d) ###########\n", + cnt_bt_cal_chk); mdelay(50); } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ********** BT NOT calibration (cnt=%d)**********\n", - cnt_bt_cal_chk); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ********** BT NOT calibration (cnt=%d)**********\n", + cnt_bt_cal_chk); break; } } @@ -2383,8 +2370,8 @@ void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist) void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); btcoexist->stop_coex_dm = false; @@ -2677,8 +2664,8 @@ void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) return; if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); coex_sta->under_ips = true; halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, @@ -2689,8 +2676,8 @@ void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) NORMAL_EXEC, 0); halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); coex_sta->under_ips = false; halbtc8723b1ant_init_hw_config(btcoexist, false); @@ -2705,12 +2692,12 @@ void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type) return; if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); coex_sta->under_lps = true; } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); coex_sta->under_lps = false; } } @@ -2753,15 +2740,15 @@ void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type) } if (BTC_SCAN_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); if (!wifi_connected) /* non-connected scan */ btc8723b1ant_action_wifi_not_conn_scan(btcoexist); else /* wifi is connected */ btc8723b1ant_action_wifi_conn_scan(btcoexist); } else if (BTC_SCAN_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); if (!wifi_connected) /* non-connected scan */ btc8723b1ant_action_wifi_not_conn(btcoexist); else @@ -2802,12 +2789,12 @@ void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type) } if (BTC_ASSOCIATE_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); btc8723b1ant_act_wifi_not_conn_asso_auth(btcoexist); } else if (BTC_ASSOCIATE_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); @@ -2830,11 +2817,11 @@ void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist, return; if (BTC_MEDIA_CONNECT == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); /* only 2.4G we need to inform bt the chnl mask */ btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, @@ -2855,10 +2842,10 @@ void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist, coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | - h2c_parameter[2]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | + h2c_parameter[2]); btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); } @@ -2900,8 +2887,8 @@ void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist, if (BTC_PACKET_DHCP == type || BTC_PACKET_EAPOL == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], special Packet(%d) notify\n", type); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], special Packet(%d) notify\n", type); halbtc8723b1ant_action_wifi_connected_special_packet(btcoexist); } } @@ -2921,19 +2908,19 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, rsp_source = BT_INFO_SRC_8723B_1ANT_WIFI_FW; coex_sta->bt_info_c2h_cnt[rsp_source]++; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length=%d, hex data = [", - rsp_source, length); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Bt info[%d], length=%d, hex data = [", + rsp_source, length); for (i = 0; i < length; i++) { coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; if (i == 1) bt_info = tmp_buf[i]; if (i == length - 1) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); } if (BT_INFO_SRC_8723B_1ANT_WIFI_FW != rsp_source) { @@ -2950,8 +2937,8 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, * because bt is reset and loss of the info. */ if (coex_sta->bt_info_ext & BIT1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); if (wifi_connected) @@ -2965,8 +2952,8 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, if (coex_sta->bt_info_ext & BIT3) { if (!btcoexist->manual_control && !btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit3 check, set BT NOT ignore Wlan active!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT ext info bit3 check, set BT NOT ignore Wlan active!!\n"); halbtc8723b1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, false); @@ -3021,30 +3008,30 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, if (!(bt_info&BT_INFO_8723B_1ANT_B_CONNECTION)) { coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Connected idle!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Connected idle!\n"); /* connection exists but no busy */ } else if (bt_info == BT_INFO_8723B_1ANT_B_CONNECTION) { coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); } else if ((bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) || (bt_info & BT_INFO_8723B_1ANT_B_SCO_BUSY)) { coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); } else if (bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY) { if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status) coex_dm->auto_tdma_adjust = false; coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); } else { coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Defined state!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Defined state!!\n"); } if ((BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || @@ -3060,7 +3047,7 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); + btc_iface_dbg(INTF_NOTIFY, "[BTCoex], Halt notify\n"); btcoexist->stop_coex_dm = true; @@ -3078,11 +3065,11 @@ void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist) void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Pnp notify\n"); + btc_iface_dbg(INTF_NOTIFY, "[BTCoex], Pnp notify\n"); if (BTC_WIFI_PNP_SLEEP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to SLEEP\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Pnp notify to SLEEP\n"); btcoexist->stop_coex_dm = true; halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, false, true); @@ -3092,8 +3079,8 @@ void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); } else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to WAKE UP\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Pnp notify to WAKE UP\n"); btcoexist->stop_coex_dm = false; halbtc8723b1ant_init_hw_config(btcoexist, false); halbtc8723b1ant_init_coex_dm(btcoexist); @@ -3103,8 +3090,8 @@ void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], *****************Coex DM Reset****************\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], *****************Coex DM Reset****************\n"); halbtc8723b1ant_init_hw_config(btcoexist, false); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); @@ -3119,31 +3106,31 @@ void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist) static u8 dis_ver_info_cnt; u32 fw_ver = 0, bt_patch_ver = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================Periodical===========================\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], ==========================Periodical===========================\n"); if (dis_ver_info_cnt <= 5) { dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, board_info->btdm_ant_num, + board_info->btdm_ant_pos); + btc_iface_dbg(INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + stack_info->profile_notified ? "Yes" : "No", + stack_info->hci_version); btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8723b_1ant, - glcoex_ver_8723b_1ant, fw_ver, - bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8723b_1ant, + glcoex_ver_8723b_1ant, fw_ver, + bt_patch_ver, bt_patch_ver); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); } #if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c index 205f78b3ab23..5f488ecaef70 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c @@ -72,32 +72,28 @@ static u8 btc8723b2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else { if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); return coex_sta->pre_bt_rssi_state; } @@ -106,14 +102,12 @@ static u8 btc8723b2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_MEDIUM) || @@ -122,31 +116,26 @@ static u8 btc8723b2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Medium\n"); } } else { if (bt_rssi < rssi_thresh1) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } @@ -173,36 +162,28 @@ static u8 btc8723b2ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else { if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); return coex_sta->pre_wifi_rssi_state[index]; } @@ -213,16 +194,12 @@ static u8 btc8723b2ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else if ((coex_sta->pre_wifi_rssi_state[index] == BTC_RSSI_STATE_MEDIUM) || @@ -231,36 +208,26 @@ static u8 btc8723b2ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Medium\n"); } } else { if (wifi_rssi < rssi_thresh1) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } @@ -292,12 +259,12 @@ static void btc8723b2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) coex_sta->low_priority_tx = reg_lp_tx; coex_sta->low_priority_rx = reg_lp_rx; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], High Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", - reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], Low Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", - reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], High Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", + reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], Low Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", + reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); /* reset counter */ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); @@ -311,9 +278,9 @@ static void btc8723b2ant_query_bt_info(struct btc_coexist *btcoexist) h2c_parameter[0] |= BIT0; /* trigger */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); } @@ -427,8 +394,8 @@ static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No BT link exists!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], No BT link exists!!!\n"); return algorithm; } @@ -443,27 +410,27 @@ static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) if (num_of_diff_profile == 1) { if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO only\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; } else { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID only\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_HID; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], A2DP only\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP; } else if (bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(HS) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], PAN(HS) only\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(EDR) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], PAN(EDR) only\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR; } @@ -472,21 +439,21 @@ static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) } else if (num_of_diff_profile == 2) { if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP ==> SCO\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + A2DP ==> SCO\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else if (bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + PAN(HS)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + PAN(EDR)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } @@ -494,31 +461,31 @@ static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) } else { if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + A2DP\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP; } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + PAN(HS)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + PAN(EDR)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], A2DP + PAN(HS)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex],A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex],A2DP + PAN(EDR)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP; } @@ -528,37 +495,32 @@ static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP" - " ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP ==> HID\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + " - "PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + PAN(HS)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + " - "PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + PAN(EDR)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + " - "PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + A2DP + PAN(HS)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + " - "PAN(EDR) ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + A2DP + PAN(EDR) ==> HID\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } @@ -568,15 +530,13 @@ static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + " - "PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + A2DP + PAN(HS)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + " - "PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + A2DP + PAN(EDR)\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR; } @@ -588,13 +548,11 @@ static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! SCO + HID" - " + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP +" - " PAN(EDR)==>PAN(EDR)+HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } @@ -624,17 +582,15 @@ static bool btc8723b_need_dec_pwr(struct btc_coexist *btcoexist) if (wifi_connected) { if (bt_hs_on) { if (bt_hs_rssi > 37) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt " - "power for HS mode!!\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt power for HS mode!!\n"); ret = true; } } else { if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt " - "power for Wifi is connected!!\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt power for Wifi is connected!!\n"); ret = true; } } @@ -653,10 +609,10 @@ static void btc8723b2ant_set_fw_dac_swing_level(struct btc_coexist *btcoexist, */ h2c_parameter[0] = dac_swing_lvl; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Set Dac Swing Level=0x%x\n", dac_swing_lvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x64=0x%x\n", h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Set Dac Swing Level=0x%x\n", dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x64=0x%x\n", h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); } @@ -671,9 +627,9 @@ static void btc8723b2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, if (dec_bt_pwr) h2c_parameter[0] |= BIT1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], decrease Bt Power : %s, FW write 0x62=0x%x\n", - (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], decrease Bt Power : %s, FW write 0x62=0x%x\n", + (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); } @@ -681,15 +637,15 @@ static void btc8723b2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, static void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist, bool force_exec, bool dec_bt_pwr) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s Dec BT power = %s\n", - (force_exec ? "force to" : ""), (dec_bt_pwr ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s Dec BT power = %s\n", + force_exec ? "force to" : "", dec_bt_pwr ? "ON" : "OFF"); coex_dm->cur_dec_bt_pwr = dec_bt_pwr; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreDecBtPwr=%d, bCurDecBtPwr=%d\n", - coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreDecBtPwr=%d, bCurDecBtPwr=%d\n", + coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); if (coex_dm->pre_dec_bt_pwr == coex_dm->cur_dec_bt_pwr) return; @@ -702,17 +658,16 @@ static void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist, static void btc8723b2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist, bool force_exec, u8 fw_dac_swing_lvl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set FW Dac Swing level = %d\n", - (force_exec ? "force to" : ""), fw_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s set FW Dac Swing level = %d\n", + (force_exec ? "force to" : ""), fw_dac_swing_lvl); coex_dm->cur_fw_dac_swing_lvl = fw_dac_swing_lvl; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], preFwDacSwingLvl=%d, " - "curFwDacSwingLvl=%d\n", - coex_dm->pre_fw_dac_swing_lvl, - coex_dm->cur_fw_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], preFwDacSwingLvl=%d, curFwDacSwingLvl=%d\n", + coex_dm->pre_fw_dac_swing_lvl, + coex_dm->cur_fw_dac_swing_lvl); if (coex_dm->pre_fw_dac_swing_lvl == coex_dm->cur_fw_dac_swing_lvl) @@ -729,16 +684,16 @@ static void btc8723b2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, { if (rx_rf_shrink_on) { /* Shrink RF Rx LPF corner */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Shrink RF Rx LPF corner!!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Shrink RF Rx LPF corner!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff, 0xffffc); } else { /* Resume RF Rx LPF corner */ /* After initialized, we can use coex_dm->btRf0x1eBackup */ if (btcoexist->initilized) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Resume RF Rx LPF corner!!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Resume RF Rx LPF corner!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff, coex_dm->bt_rf0x1e_backup); @@ -749,18 +704,17 @@ static void btc8723b2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, static void btc8723b2ant_rf_shrink(struct btc_coexist *btcoexist, bool force_exec, bool rx_rf_shrink_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn Rx RF Shrink = %s\n", - (force_exec ? "force to" : ""), (rx_rf_shrink_on ? - "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn Rx RF Shrink = %s\n", + (force_exec ? "force to" : ""), (rx_rf_shrink_on ? + "ON" : "OFF")); coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreRfRxLpfShrink=%d, " - "bCurRfRxLpfShrink=%d\n", - coex_dm->pre_rf_rx_lpf_shrink, - coex_dm->cur_rf_rx_lpf_shrink); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreRfRxLpfShrink=%d, bCurRfRxLpfShrink=%d\n", + coex_dm->pre_rf_rx_lpf_shrink, + coex_dm->cur_rf_rx_lpf_shrink); if (coex_dm->pre_rf_rx_lpf_shrink == coex_dm->cur_rf_rx_lpf_shrink) @@ -788,9 +742,9 @@ static void btc8723b_set_penalty_txrate(struct btc_coexist *btcoexist, h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36*/ } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); } @@ -799,18 +753,17 @@ static void btc8723b2ant_low_penalty_ra(struct btc_coexist *btcoexist, bool force_exec, bool low_penalty_ra) { /*return; */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn LowPenaltyRA = %s\n", - (force_exec ? "force to" : ""), (low_penalty_ra ? - "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn LowPenaltyRA = %s\n", + (force_exec ? "force to" : ""), (low_penalty_ra ? + "ON" : "OFF")); coex_dm->cur_low_penalty_ra = low_penalty_ra; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreLowPenaltyRa=%d, " - "bCurLowPenaltyRa=%d\n", - coex_dm->pre_low_penalty_ra, - coex_dm->cur_low_penalty_ra); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreLowPenaltyRa=%d, bCurLowPenaltyRa=%d\n", + coex_dm->pre_low_penalty_ra, + coex_dm->cur_low_penalty_ra); if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) return; @@ -824,8 +777,8 @@ static void btc8723b2ant_set_dac_swing_reg(struct btc_coexist *btcoexist, u32 level) { u8 val = (u8) level; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Write SwDacSwing = 0x%x\n", level); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Write SwDacSwing = 0x%x\n", level); btcoexist->btc_write_1byte_bitmask(btcoexist, 0x883, 0x3e, val); } @@ -843,20 +796,20 @@ static void btc8723b2ant_dac_swing(struct btc_coexist *btcoexist, bool force_exec, bool dac_swing_on, u32 dac_swing_lvl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn DacSwing=%s, dac_swing_lvl=0x%x\n", - (force_exec ? "force to" : ""), - (dac_swing_on ? "ON" : "OFF"), dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn DacSwing=%s, dac_swing_lvl=0x%x\n", + (force_exec ? "force to" : ""), + (dac_swing_on ? "ON" : "OFF"), dac_swing_lvl); coex_dm->cur_dac_swing_on = dac_swing_on; coex_dm->cur_dac_swing_lvl = dac_swing_lvl; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl=0x%x," - " bCurDacSwingOn=%d, curDacSwingLvl=0x%x\n", - coex_dm->pre_dac_swing_on, coex_dm->pre_dac_swing_lvl, - coex_dm->cur_dac_swing_on, - coex_dm->cur_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl=0x%x, bCurDacSwingOn=%d, curDacSwingLvl=0x%x\n", + coex_dm->pre_dac_swing_on, + coex_dm->pre_dac_swing_lvl, + coex_dm->cur_dac_swing_on, + coex_dm->cur_dac_swing_lvl); if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && (coex_dm->pre_dac_swing_lvl == coex_dm->cur_dac_swing_lvl)) @@ -877,8 +830,8 @@ static void btc8723b2ant_set_agc_table(struct btc_coexist *btcoexist, /* BB AGC Gain Table */ if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table On!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table On!\n"); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6e1A0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6d1B0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6c1C0001); @@ -887,8 +840,8 @@ static void btc8723b2ant_set_agc_table(struct btc_coexist *btcoexist, btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x691F0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x68200001); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table Off!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table Off!\n"); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xaa1A0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa91B0001); btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa81C0001); @@ -901,15 +854,15 @@ static void btc8723b2ant_set_agc_table(struct btc_coexist *btcoexist, /* RF Gain */ btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xef, 0xfffff, 0x02000); if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table On!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table On!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38fff); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38ffe); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table Off!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table Off!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, 0xfffff, 0x380c3); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, @@ -920,15 +873,15 @@ static void btc8723b2ant_set_agc_table(struct btc_coexist *btcoexist, btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xed, 0xfffff, 0x1); if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table On!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table On!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, 0xfffff, 0x38fff); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, 0xfffff, 0x38ffe); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table Off!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table Off!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, 0xfffff, 0x380c3); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, @@ -946,16 +899,17 @@ static void btc8723b2ant_set_agc_table(struct btc_coexist *btcoexist, static void btc8723b2ant_agc_table(struct btc_coexist *btcoexist, bool force_exec, bool agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s %s Agc Table\n", - (force_exec ? "force to" : ""), - (agc_table_en ? "Enable" : "Disable")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s %s Agc Table\n", + (force_exec ? "force to" : ""), + (agc_table_en ? "Enable" : "Disable")); coex_dm->cur_agc_table_en = agc_table_en; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", - coex_dm->pre_agc_table_en, coex_dm->cur_agc_table_en); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", + coex_dm->pre_agc_table_en, + coex_dm->cur_agc_table_en); if (coex_dm->pre_agc_table_en == coex_dm->cur_agc_table_en) return; @@ -969,20 +923,20 @@ static void btc8723b2ant_set_coex_table(struct btc_coexist *btcoexist, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0=0x%x\n", val0x6c0); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0=0x%x\n", val0x6c0); btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4=0x%x\n", val0x6c4); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4=0x%x\n", val0x6c4); btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8=0x%x\n", val0x6c8); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8=0x%x\n", val0x6c8); btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc=0x%x\n", val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc=0x%x\n", val0x6cc); btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); } @@ -991,29 +945,24 @@ static void btc8723b2ant_coex_table(struct btc_coexist *btcoexist, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0=0x%x," - " 0x6c4=0x%x, 0x6c8=0x%x, 0x6cc=0x%x\n", - (force_exec ? "force to" : ""), val0x6c0, - val0x6c4, val0x6c8, val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0=0x%x, 0x6c4=0x%x, 0x6c8=0x%x, 0x6cc=0x%x\n", + force_exec ? "force to" : "", + val0x6c0, val0x6c4, val0x6c8, val0x6cc); coex_dm->cur_val0x6c0 = val0x6c0; coex_dm->cur_val0x6c4 = val0x6c4; coex_dm->cur_val0x6c8 = val0x6c8; coex_dm->cur_val0x6cc = val0x6cc; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], preVal0x6c0=0x%x, " - "preVal0x6c4=0x%x, preVal0x6c8=0x%x, " - "preVal0x6cc=0x%x !!\n", - coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4, - coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], curVal0x6c0=0x%x, " - "curVal0x6c4=0x%x, curVal0x6c8=0x%x, " - "curVal0x6cc=0x%x !!\n", - coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4, - coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], preVal0x6c0=0x%x, preVal0x6c4=0x%x, preVal0x6c8=0x%x, preVal0x6cc=0x%x !!\n", + coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4, + coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], curVal0x6c0=0x%x, curVal0x6c4=0x%x, curVal0x6c8=0x%x, curVal0x6cc=0x%x !!\n", + coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4, + coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && @@ -1099,9 +1048,9 @@ static void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, if (enable) h2c_parameter[0] |= BIT0;/* function enable*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, " - "FW write 0x63=0x%x\n", h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63=0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); } @@ -1109,17 +1058,16 @@ static void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, static void btc8723b2ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); coex_dm->cur_ignore_wlan_act = enable; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreIgnoreWlanAct = %d, " - "bCurIgnoreWlanAct = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); if (coex_dm->pre_ignore_wlan_act == coex_dm->cur_ignore_wlan_act) @@ -1147,11 +1095,11 @@ static void btc8723b2ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, u8 byte1, coex_dm->ps_tdma_para[3] = byte4; coex_dm->ps_tdma_para[4] = byte5; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x60(5bytes)=0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | - h2c_parameter[3] << 8 | h2c_parameter[4]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x60(5bytes)=0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | h2c_parameter[4]); btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); } @@ -1260,20 +1208,20 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist, static void btc8723b2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec, bool turn_on, u8 type) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn %s PS TDMA, type=%d\n", - (force_exec ? "force to" : ""), - (turn_on ? "ON" : "OFF"), type); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn %s PS TDMA, type=%d\n", + (force_exec ? "force to" : ""), + (turn_on ? "ON" : "OFF"), type); coex_dm->cur_ps_tdma_on = turn_on; coex_dm->cur_ps_tdma = type; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", - coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", - coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", + coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", + coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) @@ -1471,8 +1419,8 @@ static bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non-connected idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non-connected idle!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); @@ -1495,9 +1443,8 @@ static bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + " - "BT non connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi connected + BT non connected-idle!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); @@ -1523,9 +1470,8 @@ static bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) if (bt_hs_on) return false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + " - "BT connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi connected + BT connected-idle!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); @@ -1549,17 +1495,15 @@ static bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) &low_pwr_disable); if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Busy + " - "BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); common = false; } else { if (bt_hs_on) return false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Idle + " - "BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); @@ -1597,9 +1541,8 @@ static void set_tdma_int1(struct btc_coexist *btcoexist, bool tx_pause, { /* Set PS TDMA for max interval == 1 */ if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 71) { btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, @@ -1695,9 +1638,8 @@ static void set_tdma_int1(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 71); coex_dm->tdma_adj_type = 71; @@ -1795,9 +1737,8 @@ static void set_tdma_int2(struct btc_coexist *btcoexist, bool tx_pause, { /* Set PS TDMA for max interval == 2 */ if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 1) { btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); coex_dm->tdma_adj_type = 6; @@ -1878,9 +1819,8 @@ static void set_tdma_int2(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); coex_dm->tdma_adj_type = 2; @@ -1968,9 +1908,8 @@ static void set_tdma_int3(struct btc_coexist *btcoexist, bool tx_pause, { /* Set PS TDMA for max interval == 3 */ if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 1) { btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); coex_dm->tdma_adj_type = 7; @@ -2051,9 +1990,8 @@ static void set_tdma_int3(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); coex_dm->tdma_adj_type = 3; @@ -2145,13 +2083,13 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, s32 result; u8 retry_count = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjust()\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjust()\n"); if (!coex_dm->auto_tdma_adjust) { coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); if (sco_hid) { if (tx_pause) { if (max_interval == 1) { @@ -2255,11 +2193,11 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, } else { /*accquire the BT TRx retry count from BT_Info byte2*/ retry_count = coex_sta->bt_retry_cnt; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], retry_count = %d\n", retry_count); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_count=%d\n", - up, dn, m, n, wait_count); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], retry_count = %d\n", retry_count); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_count=%d\n", + up, dn, m, n, wait_count); result = 0; wait_count++; /* no retry in the last 2-second duration*/ @@ -2276,10 +2214,8 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, up = 0; dn = 0; result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi " - "duration!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi duration!!\n"); } /* <=3 retry in the last 2-second duration*/ } else if (retry_count <= 3) { up--; @@ -2302,10 +2238,8 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration " - "for retry_counter<3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retry_counter<3!!\n"); } } else { if (wait_count == 1) @@ -2321,13 +2255,12 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration " - "for retry_counter>3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retry_counter>3!!\n"); } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], max Interval = %d\n", max_interval); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], max Interval = %d\n", max_interval); if (max_interval == 1) set_tdma_int1(btcoexist, tx_pause, result); else if (max_interval == 2) @@ -2341,10 +2274,9 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, */ if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { bool scan = false, link = false, roam = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], PsTdma type dismatch!!!, " - "curPsTdma=%d, recordPsTdma=%d\n", - coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], PsTdma type dismatch!!!, curPsTdma=%d, recordPsTdma=%d\n", + coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); @@ -2354,9 +2286,8 @@ static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, coex_dm->tdma_adj_type); else - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], roaming/link/scan is under" - " progress, will adjust next time!!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); } } @@ -2994,27 +2925,26 @@ static void btc8723b2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) { u8 algorithm = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), " - "return for Manual CTRL <===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); return; } if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); return; } algorithm = btc8723b2ant_action_algorithm(btcoexist); if (coex_sta->c2h_bt_inquiry_page && (BT_8723B_2ANT_COEX_ALGO_PANHS != algorithm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT is under inquiry/page scan !!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT is under inquiry/page scan !!\n"); btc8723b2ant_action_bt_inquiry(btcoexist); return; } else { @@ -3026,84 +2956,75 @@ static void btc8723b2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) } coex_dm->cur_algorithm = algorithm; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, "[BTCoex], Algorithm = %d\n", - coex_dm->cur_algorithm); + btc_alg_dbg(ALGO_TRACE, "[BTCoex], Algorithm = %d\n", + coex_dm->cur_algorithm); if (btc8723b2ant_is_common_action(btcoexist)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant common.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant common\n"); coex_dm->auto_tdma_adjust = false; } else { if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], preAlgorithm=%d, " - "curAlgorithm=%d\n", coex_dm->pre_algorithm, - coex_dm->cur_algorithm); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], preAlgorithm=%d, curAlgorithm=%d\n", + coex_dm->pre_algorithm, + coex_dm->cur_algorithm); coex_dm->auto_tdma_adjust = false; } switch (coex_dm->cur_algorithm) { case BT_8723B_2ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = SCO.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = SCO\n"); btc8723b2ant_action_sco(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID\n"); btc8723b2ant_action_hid(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = A2DP\n"); btc8723b2ant_action_a2dp(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = A2DP+PAN(HS).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS)\n"); btc8723b2ant_action_a2dp_pan_hs(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = PAN(EDR).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)\n"); btc8723b2ant_action_pan_edr(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = HS mode.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HS mode\n"); btc8723b2ant_action_pan_hs(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = PAN+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN+A2DP\n"); btc8723b2ant_action_pan_edr_a2dp(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = PAN(EDR)+HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID\n"); btc8723b2ant_action_pan_edr_hid(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = HID+A2DP+PAN.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN\n"); btc8723b2ant_action_hid_a2dp_pan_edr(btcoexist); break; case BT_8723B_2ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = HID+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID+A2DP\n"); btc8723b2ant_action_hid_a2dp(btcoexist); break; default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = coexist All Off!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n"); btc8723b2ant_coex_alloff(btcoexist); break; } @@ -3131,8 +3052,8 @@ void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist) { u8 u8tmp = 0; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 2Ant Init HW Config!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], 2Ant Init HW Config!!\n"); coex_dm->bt_rf0x1e_backup = btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff); @@ -3157,8 +3078,8 @@ void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist) void ex_btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); btc8723b2ant_init_coex_dm(btcoexist); } @@ -3393,15 +3314,15 @@ void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist) void ex_btc8723b2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); coex_sta->under_ips = true; btc8723b2ant_wifioff_hwcfg(btcoexist); btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); btc8723b2ant_coex_alloff(btcoexist); } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); coex_sta->under_ips = false; ex_btc8723b2ant_init_hwconfig(btcoexist); btc8723b2ant_init_coex_dm(btcoexist); @@ -3412,12 +3333,12 @@ void ex_btc8723b2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) void ex_btc8723b2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); coex_sta->under_lps = true; } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); coex_sta->under_lps = false; } } @@ -3425,21 +3346,21 @@ void ex_btc8723b2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) void ex_btc8723b2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_SCAN_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); else if (BTC_SCAN_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); } void ex_btc8723b2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_ASSOCIATE_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); else if (BTC_ASSOCIATE_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); } void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist, @@ -3450,11 +3371,11 @@ void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist, u8 wifi_central_chnl; if (BTC_MEDIA_CONNECT == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); /* only 2.4G we need to inform bt the chnl mask */ btcoexist->btc_get(btcoexist, @@ -3475,10 +3396,10 @@ void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist, coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66=0x%x\n", - h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | - h2c_parameter[2]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66=0x%x\n", + h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | + h2c_parameter[2]); btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); } @@ -3487,8 +3408,8 @@ void ex_btc8723b2ant_special_packet_notify(struct btc_coexist *btcoexist, u8 type) { if (type == BTC_PACKET_DHCP) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], DHCP Packet notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], DHCP Packet notify\n"); } void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, @@ -3506,25 +3427,24 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, rsp_source = BT_INFO_SRC_8723B_2ANT_WIFI_FW; coex_sta->bt_info_c2h_cnt[rsp_source]++; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length=%d, hex data=[", - rsp_source, length); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Bt info[%d], length=%d, hex data=[", + rsp_source, length); for (i = 0; i < length; i++) { coex_sta->bt_info_c2h[rsp_source][i] = tmpbuf[i]; if (i == 1) bt_info = tmpbuf[i]; if (i == length-1) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmpbuf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x]\n", tmpbuf[i]); else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmpbuf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x, ", tmpbuf[i]); } if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), " - "return for Manual CTRL<===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), return for Manual CTRL<===\n"); return; } @@ -3542,9 +3462,8 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, because bt is reset and loss of the info. */ if ((coex_sta->bt_info_ext & BIT1)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit1 check," - " send wifi BW&Chnl to BT!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); if (wifi_connected) @@ -3558,9 +3477,8 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, } if ((coex_sta->bt_info_ext & BIT3)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit3 check, " - "set BT NOT to ignore Wlan active!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"); btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, false); } else { @@ -3613,28 +3531,26 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, if (!(bt_info & BT_INFO_8723B_2ANT_B_CONNECTION)) { coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), " - "BT Non-Connected idle!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n"); /* connection exists but no busy */ } else if (bt_info == BT_INFO_8723B_2ANT_B_CONNECTION) { coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); } else if ((bt_info & BT_INFO_8723B_2ANT_B_SCO_ESCO) || (bt_info & BT_INFO_8723B_2ANT_B_SCO_BUSY)) { coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); } else if (bt_info&BT_INFO_8723B_2ANT_B_ACL_BUSY) { coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); } else { coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), " - "BT Non-Defined state!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n"); } if ((BT_8723B_2ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || @@ -3657,7 +3573,7 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); + btc_iface_dbg(INTF_NOTIFY, "[BTCoex], Halt notify\n"); btc8723b2ant_wifioff_hwcfg(btcoexist); btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); @@ -3671,33 +3587,31 @@ void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist) static u8 dis_ver_info_cnt; u32 fw_ver = 0, bt_patch_ver = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================" - "Periodical===========================\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], ==========================Periodical===========================\n"); if (dis_ver_info_cnt <= 5) { dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************" - "************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ " - "Ant Pos = %d/ %d/ %d\n", board_info->pg_ant_num, - board_info->btdm_ant_num, board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, + board_info->btdm_ant_num, + board_info->btdm_ant_pos); + btc_iface_dbg(INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + stack_info->profile_notified ? "Yes" : "No", + stack_info->hci_version); btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ fw_ver/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8723b_2ant, glcoex_ver_8723b_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], *****************************" - "***********************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], CoexVer/ fw_ver/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8723b_2ant, glcoex_ver_8723b_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); } #if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c index 9cecf174a37d..3ce47c70bfa4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c @@ -76,28 +76,28 @@ static u8 halbtc8821a1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= (rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else { if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); return coex_sta->pre_bt_rssi_state; } @@ -106,12 +106,12 @@ static u8 halbtc8821a1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= (rssi_thresh + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_MEDIUM) || @@ -120,26 +120,26 @@ static u8 halbtc8821a1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= (rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Medium\n"); } } else { if (bt_rssi < rssi_thresh1) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } @@ -165,32 +165,28 @@ static u8 halbtc8821a1ant_WifiRssiState(struct btc_coexist *btcoexist, if (wifi_rssi >= (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else { if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); return coex_sta->pre_wifi_rssi_state[index]; } @@ -201,14 +197,12 @@ static u8 halbtc8821a1ant_WifiRssiState(struct btc_coexist *btcoexist, if (wifi_rssi >= (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else if ((coex_sta->pre_wifi_rssi_state[index] == BTC_RSSI_STATE_MEDIUM) || @@ -218,31 +212,26 @@ static u8 halbtc8821a1ant_WifiRssiState(struct btc_coexist *btcoexist, (rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Medium\n"); } } else { if (wifi_rssi < rssi_thresh1) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } @@ -431,9 +420,9 @@ static void halbtc8821a1ant_query_bt_info(struct btc_coexist *btcoexist) h2c_parameter[0] |= BIT0; /* trigger*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); } @@ -504,8 +493,8 @@ static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No BT link exists!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], No BT link exists!!!\n"); return algorithm; } @@ -520,26 +509,26 @@ static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) if (num_of_diff_profile == 1) { if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO only\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; } else { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID only\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = A2DP only\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_A2DP; } else if (bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(HS) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = PAN(HS) only\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(EDR) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = PAN(EDR) only\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR; } } @@ -547,50 +536,50 @@ static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) } else if (num_of_diff_profile == 2) { if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID; } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; } else if (bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(HS)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; } } } else { if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(HS)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(EDR)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP; } } @@ -599,29 +588,29 @@ static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) if (bt_link_info->sco_exist) { if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID; } else if (bt_link_info->hid_exist && bt_link_info->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; } } else if (bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; } } @@ -630,12 +619,12 @@ static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR; } } @@ -646,12 +635,12 @@ static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) bt_link_info->pan_exist && bt_link_info->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; } } @@ -670,10 +659,10 @@ static void halbtc8821a1ant_set_bt_auto_report(struct btc_coexist *btcoexist, if (enable_auto_report) h2c_parameter[0] |= BIT0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", - (enable_auto_report ? "Enabled!!" : "Disabled!!"), - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", + (enable_auto_report ? "Enabled!!" : "Disabled!!"), + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); } @@ -682,17 +671,16 @@ static void halbtc8821a1ant_bt_auto_report(struct btc_coexist *btcoexist, bool force_exec, bool enable_auto_report) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, "[BTCoex], %s BT Auto report = %s\n", - (force_exec ? "force to" : ""), ((enable_auto_report) ? - "Enabled" : "Disabled")); + btc_alg_dbg(ALGO_TRACE_FW, "[BTCoex], %s BT Auto report = %s\n", + (force_exec ? "force to" : ""), ((enable_auto_report) ? + "Enabled" : "Disabled")); coex_dm->cur_bt_auto_report = enable_auto_report; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", - coex_dm->pre_bt_auto_report, - coex_dm->cur_bt_auto_report); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", + coex_dm->pre_bt_auto_report, + coex_dm->cur_bt_auto_report); if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) return; @@ -718,9 +706,9 @@ static void btc8821a1ant_set_sw_pen_tx_rate(struct btc_coexist *btcoexist, h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36*/ } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); } @@ -743,20 +731,20 @@ static void halbtc8821a1ant_set_coex_table(struct btc_coexist *btcoexist, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); } @@ -764,10 +752,10 @@ static void halbtc8821a1ant_coex_table(struct btc_coexist *btcoexist, bool force_exec, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - (force_exec ? "force to" : ""), val0x6c0, val0x6c4, - val0x6c8, val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", + (force_exec ? "force to" : ""), val0x6c0, val0x6c4, + val0x6c8, val0x6cc); coex_dm->cur_val_0x6c0 = val0x6c0; coex_dm->cur_val_0x6c4 = val0x6c4; coex_dm->cur_val_0x6c8 = val0x6c8; @@ -839,9 +827,9 @@ static void btc8821a1ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, if (enable) h2c_parameter[0] |= BIT0; /* function enable*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); } @@ -849,16 +837,16 @@ static void btc8821a1ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, static void halbtc8821a1ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); coex_dm->cur_ignore_wlan_act = enable; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); if (coex_dm->pre_ignore_wlan_act == coex_dm->cur_ignore_wlan_act) @@ -887,13 +875,13 @@ static void halbtc8821a1ant_set_fw_pstdma(struct btc_coexist *btcoexist, coex_dm->ps_tdma_para[3] = byte4; coex_dm->ps_tdma_para[4] = byte5; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1]<<24 | - h2c_parameter[2]<<16 | - h2c_parameter[3]<<8 | - h2c_parameter[4]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | + h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | + h2c_parameter[4]); btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); } @@ -910,22 +898,22 @@ static void halbtc8821a1ant_set_lps_rpwm(struct btc_coexist *btcoexist, static void halbtc8821a1ant_lps_rpwm(struct btc_coexist *btcoexist, bool force_exec, u8 lps_val, u8 rpwm_val) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", - (force_exec ? "force to" : ""), lps_val, rpwm_val); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", + (force_exec ? "force to" : ""), lps_val, rpwm_val); coex_dm->cur_lps = lps_val; coex_dm->cur_rpwm = rpwm_val; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RxBeaconMode = 0x%x, LPS-RPWM = 0x%x!!\n", - coex_dm->cur_lps, coex_dm->cur_rpwm); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RxBeaconMode = 0x%x, LPS-RPWM = 0x%x!!\n", + coex_dm->cur_lps, coex_dm->cur_rpwm); if ((coex_dm->pre_lps == coex_dm->cur_lps) && (coex_dm->pre_rpwm == coex_dm->cur_rpwm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RPWM_Last = 0x%x, LPS-RPWM_Now = 0x%x!!\n", - coex_dm->pre_rpwm, coex_dm->cur_rpwm); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RPWM_Last = 0x%x, LPS-RPWM_Now = 0x%x!!\n", + coex_dm->pre_rpwm, coex_dm->cur_rpwm); return; } @@ -939,8 +927,8 @@ static void halbtc8821a1ant_lps_rpwm(struct btc_coexist *btcoexist, static void halbtc8821a1ant_sw_mechanism(struct btc_coexist *btcoexist, bool low_penalty_ra) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); halbtc8821a1ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); } @@ -1036,13 +1024,13 @@ static void halbtc8821a1ant_ps_tdma(struct btc_coexist *btcoexist, if (!force_exec) { if (coex_dm->cur_ps_tdma_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ********** TDMA(on, %d) **********\n", - coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], ********** TDMA(on, %d) **********\n", + coex_dm->cur_ps_tdma); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ********** TDMA(off, %d) **********\n", - coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], ********** TDMA(off, %d) **********\n", + coex_dm->cur_ps_tdma); } if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) @@ -1253,50 +1241,50 @@ static bool halbtc8821a1ant_is_common_action(struct btc_coexist *btcoexist) if (!wifi_connected && BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == coex_dm->bt_status) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); halbtc8821a1ant_sw_mechanism(btcoexist, false); common = true; } else if (wifi_connected && (BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT non connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi connected + BT non connected-idle!!\n"); halbtc8821a1ant_sw_mechanism(btcoexist, false); common = true; } else if (!wifi_connected && (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); halbtc8821a1ant_sw_mechanism(btcoexist, false); common = true; } else if (wifi_connected && (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT connected-idle!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi connected + BT connected-idle!!\n"); halbtc8821a1ant_sw_mechanism(btcoexist, false); common = true; } else if (!wifi_connected && (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE != coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT Busy!!\n"); halbtc8821a1ant_sw_mechanism(btcoexist, false); common = true; } else { if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); } common = false; @@ -1313,8 +1301,8 @@ static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, long result; u8 retry_count = 0, bt_info_ext; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjustForAcl()\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjustForAcl()\n"); if ((BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == wifi_status) || @@ -1342,8 +1330,8 @@ static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, if (!coex_dm->auto_tdma_adjust) { coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); coex_dm->tdma_adj_type = 2; @@ -1378,9 +1366,8 @@ static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, up = 0; dn = 0; result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi duration!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi duration!!\n"); } } else if (retry_count <= 3) { /* <=3 retry in the last 2-second duration*/ @@ -1410,9 +1397,8 @@ static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); } } else { /* retry count > 3, if retry count > 3 happens once, @@ -1433,8 +1419,8 @@ static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); } if (result == -1) { @@ -1479,9 +1465,9 @@ static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, } } else { /*no change*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ********** TDMA(on, %d) **********\n", - coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], ********** TDMA(on, %d) **********\n", + coex_dm->cur_ps_tdma); } if (coex_dm->cur_ps_tdma != 1 && @@ -1603,27 +1589,27 @@ static void btc8821a1ant_mon_bt_en_dis(struct btc_coexist *btcoexist) bt_disabled = false; btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is enabled !!\n"); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is enabled !!\n"); } else { bt_disable_cnt++; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], bt all counters = 0, %d times!!\n", - bt_disable_cnt); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], bt all counters = 0, %d times!!\n", + bt_disable_cnt); if (bt_disable_cnt >= 2) { bt_disabled = true; btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is disabled !!\n"); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is disabled !!\n"); halbtc8821a1ant_action_wifi_only(btcoexist); } } if (pre_bt_disabled != bt_disabled) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is from %s to %s!!\n", - (pre_bt_disabled ? "disabled" : "enabled"), - (bt_disabled ? "disabled" : "enabled")); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is from %s to %s!!\n", + (pre_bt_disabled ? "disabled" : "enabled"), + (bt_disabled ? "disabled" : "enabled")); pre_bt_disabled = bt_disabled; if (bt_disabled) { btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, @@ -1897,15 +1883,15 @@ static void halbtc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist) bool scan = false, link = false, roam = false; bool under_4way = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect()===>\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], CoexForWifiConnect()===>\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &under_4way); if (under_4way) { btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); return; } @@ -1914,8 +1900,8 @@ static void halbtc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist) btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); if (scan || link || roam) { halbtc8821a1ant_action_wifi_connected_scan(btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); return; } @@ -1976,58 +1962,58 @@ static void btc8821a1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) if (!halbtc8821a1ant_is_common_action(btcoexist)) { switch (coex_dm->cur_algorithm) { case BT_8821A_1ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = SCO.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = SCO\n"); halbtc8821a1ant_action_sco(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HID\n"); halbtc8821a1ant_action_hid(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP\n"); halbtc8821a1ant_action_a2dp(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP+PAN(HS).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP+PAN(HS)\n"); halbtc8821a1ant_action_a2dp_pan_hs(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR)\n"); halbtc8821a1ant_action_pan_edr(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HS mode.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HS mode\n"); halbtc8821a1ant_action_pan_hs(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = PAN+A2DP\n"); halbtc8821a1ant_action_pan_edr_a2dp(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR)+HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR)+HID\n"); halbtc8821a1ant_action_pan_edr_hid(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP+PAN.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP+PAN\n"); btc8821a1ant_action_hid_a2dp_pan_edr(btcoexist); break; case BT_8821A_1ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP\n"); halbtc8821a1ant_action_hid_a2dp(btcoexist); break; default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = coexist All Off!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action algorithm = coexist All Off!!\n"); /*halbtc8821a1ant_coex_all_off(btcoexist);*/ break; } @@ -2045,31 +2031,31 @@ static void halbtc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH; bool wifi_under_5g = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); return; } if (btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); return; } if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); return; } btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); if (wifi_under_5g) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for 5G <===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for 5G <===\n"); halbtc8821a1ant_coex_under_5g(btcoexist); return; } @@ -2135,8 +2121,8 @@ static void halbtc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) if (!wifi_connected) { bool scan = false, link = false, roam = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is non connected-idle !!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], wifi is non connected-idle !!!\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); @@ -2168,8 +2154,8 @@ static void halbtc8821a1ant_init_hw_config(struct btc_coexist *btcoexist, u8 u1_tmp = 0; bool wifi_under_5g = false; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 1Ant Init HW Config!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], 1Ant Init HW Config!!\n"); if (back_up) { coex_dm->backup_arfr_cnt1 = btcoexist->btc_read_4byte(btcoexist, @@ -2220,8 +2206,8 @@ void ex_halbtc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist) void ex_halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); btcoexist->stop_coex_dm = false; @@ -2515,8 +2501,8 @@ void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) return; if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); coex_sta->under_ips = true; halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, false, true); @@ -2525,8 +2511,8 @@ void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); coex_sta->under_ips = false; halbtc8821a1ant_run_coexist_mechanism(btcoexist); @@ -2539,12 +2525,12 @@ void ex_halbtc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type) return; if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); coex_sta->under_Lps = true; } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); coex_sta->under_Lps = false; } } @@ -2574,8 +2560,8 @@ void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type) } if (BTC_SCAN_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); if (!wifi_connected) { /* non-connected scan*/ btc8821a1ant_act_wifi_not_conn_scan(btcoexist); @@ -2584,8 +2570,8 @@ void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type) halbtc8821a1ant_action_wifi_connected_scan(btcoexist); } } else if (BTC_SCAN_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); if (!wifi_connected) { /* non-connected scan*/ halbtc8821a1ant_action_wifi_not_connected(btcoexist); @@ -2614,12 +2600,12 @@ void ex_halbtc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type) } if (BTC_ASSOCIATE_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); btc8821a1ant_act_wifi_not_conn_scan(btcoexist); } else if (BTC_ASSOCIATE_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); @@ -2645,11 +2631,11 @@ void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist, return; if (BTC_MEDIA_CONNECT == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); } /* only 2.4G we need to inform bt the chnl mask*/ @@ -2672,9 +2658,11 @@ void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist, coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0] << 16 | + h2c_parameter[1] << 8 | + h2c_parameter[2]); btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); } @@ -2702,8 +2690,8 @@ void ex_halbtc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist, if (BTC_PACKET_DHCP == type || BTC_PACKET_EAPOL == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], special Packet(%d) notify\n", type); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], special Packet(%d) notify\n", type); btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist); } } @@ -2727,19 +2715,19 @@ void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, rsp_source = BT_INFO_SRC_8821A_1ANT_WIFI_FW; coex_sta->bt_info_c2h_cnt[rsp_source]++; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length = %d, hex data = [", - rsp_source, length); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Bt info[%d], length = %d, hex data = [", + rsp_source, length); for (i = 0; i < length; i++) { coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; if (i == 1) bt_info = tmp_buf[i]; if (i == length-1) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); } } @@ -2756,8 +2744,8 @@ void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, /* Here we need to resend some wifi info to BT*/ /* because bt is reset and loss of the info.*/ if (coex_sta->bt_info_ext & BIT1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); @@ -2773,8 +2761,8 @@ void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, if ((coex_sta->bt_info_ext & BIT3) && !wifi_under_5g) { if (!btcoexist->manual_control && !btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"); halbtc8821a1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, false); @@ -2782,8 +2770,8 @@ void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, } #if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0) if (!(coex_sta->bt_info_ext & BIT4)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit4 check, set BT to enable Auto Report!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT ext info bit4 check, set BT to enable Auto Report!!\n"); halbtc8821a1ant_bt_auto_report(btcoexist, FORCE_EXEC, true); } @@ -2828,28 +2816,28 @@ void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, if (!(bt_info&BT_INFO_8821A_1ANT_B_CONNECTION)) { coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n"); } else if (bt_info == BT_INFO_8821A_1ANT_B_CONNECTION) { /* connection exists but no busy*/ coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); } else if ((bt_info&BT_INFO_8821A_1ANT_B_SCO_ESCO) || (bt_info&BT_INFO_8821A_1ANT_B_SCO_BUSY)) { coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); } else if (bt_info&BT_INFO_8821A_1ANT_B_ACL_BUSY) { if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status) coex_dm->auto_tdma_adjust = false; coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); } else { coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n"); } if ((BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || @@ -2866,8 +2854,8 @@ void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Halt notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Halt notify\n"); btcoexist->stop_coex_dm = true; @@ -2885,20 +2873,20 @@ void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist) void ex_halbtc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Pnp notify\n"); if (BTC_WIFI_PNP_SLEEP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to SLEEP\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Pnp notify to SLEEP\n"); btcoexist->stop_coex_dm = true; halbtc8821a1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0); halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9); } else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to WAKE UP\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Pnp notify to WAKE UP\n"); btcoexist->stop_coex_dm = false; halbtc8821a1ant_init_hw_config(btcoexist, false); halbtc8821a1ant_init_coex_dm(btcoexist); @@ -2914,33 +2902,33 @@ ex_halbtc8821a1ant_periodical( struct btc_board_info *board_info = &btcoexist->board_info; struct btc_stack_info *stack_info = &btcoexist->stack_info; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================Periodical===========================\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], ==========================Periodical===========================\n"); if (dis_ver_info_cnt <= 5) { dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, - board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, + board_info->btdm_ant_num, + board_info->btdm_ant_pos); + btc_iface_dbg(INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + stack_info->profile_notified ? "Yes" : "No", + stack_info->hci_version); btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8821a_1ant, - glcoex_ver_8821a_1ant, - fw_ver, bt_patch_ver, - bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8821a_1ant, + glcoex_ver_8821a_1ant, + fw_ver, bt_patch_ver, + bt_patch_ver); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); } #if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c index 044d914291c0..81f843bba771 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c @@ -80,28 +80,28 @@ static u8 halbtc8821a2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT; if (bt_rssi >= tmp) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else { if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); return coex_sta->pre_bt_rssi_state; } @@ -110,12 +110,12 @@ static u8 halbtc8821a2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, if (bt_rssi >= (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); } } else if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_MEDIUM) || @@ -125,26 +125,26 @@ static u8 halbtc8821a2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, (rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); } else if (bt_rssi < rssi_thresh) { bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Medium\n"); } } else { if (bt_rssi < rssi_thresh1) { bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); } else { bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); + btc_alg_dbg(ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); } } } @@ -171,32 +171,28 @@ static u8 halbtc8821a2ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else { if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } else if (level_num == 3) { if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); return coex_sta->pre_wifi_rssi_state[index]; } @@ -207,14 +203,12 @@ static u8 halbtc8821a2ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); } } else if ((coex_sta->pre_wifi_rssi_state[index] == BTC_RSSI_STATE_MEDIUM) || @@ -223,31 +217,26 @@ static u8 halbtc8821a2ant_wifi_rssi_state(struct btc_coexist *btcoexist, if (wifi_rssi >= (rssi_thresh1 + BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); } else if (wifi_rssi < rssi_thresh) { wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Medium\n"); } } else { if (wifi_rssi < rssi_thresh1) { wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); } else { wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); + btc_alg_dbg(ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); } } } @@ -279,26 +268,26 @@ static void btc8821a2ant_mon_bt_en_dis(struct btc_coexist *btcoexist) bt_disabled = false; btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is enabled !!\n"); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is enabled !!\n"); } else { bt_disable_cnt++; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], bt all counters = 0, %d times!!\n", - bt_disable_cnt); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], bt all counters = 0, %d times!!\n", + bt_disable_cnt); if (bt_disable_cnt >= 2) { bt_disabled = true; btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is disabled !!\n"); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is disabled !!\n"); } } if (pre_bt_disabled != bt_disabled) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is from %s to %s!!\n", - (pre_bt_disabled ? "disabled" : "enabled"), - (bt_disabled ? "disabled" : "enabled")); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], BT is from %s to %s!!\n", + (pre_bt_disabled ? "disabled" : "enabled"), + (bt_disabled ? "disabled" : "enabled")); pre_bt_disabled = bt_disabled; } } @@ -324,12 +313,12 @@ static void halbtc8821a2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) coex_sta->low_priority_tx = reg_lp_tx; coex_sta->low_priority_rx = reg_lp_rx; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); + btc_alg_dbg(ALGO_BT_MONITOR, + "[BTCoex], Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); /* reset counter */ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); @@ -343,9 +332,9 @@ static void halbtc8821a2ant_query_bt_info(struct btc_coexist *btcoexist) h2c_parameter[0] |= BIT0; /* trigger */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); } @@ -368,8 +357,8 @@ static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) stack_info->bt_link_exist = coex_sta->bt_link_exist; if (!coex_sta->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No profile exists!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], No profile exists!!!\n"); return algorithm; } @@ -384,26 +373,26 @@ static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) if (num_of_diff_profile == 1) { if (coex_sta->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO only\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_SCO; } else { if (coex_sta->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID only\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_HID; } else if (coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], A2DP only\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_A2DP; } else if (coex_sta->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(HS) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], PAN(HS) only\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(EDR) only\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], PAN(EDR) only\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR; } } @@ -411,50 +400,50 @@ static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) } else if (num_of_diff_profile == 2) { if (coex_sta->sco_exist) { if (coex_sta->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } else if (coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP ==> SCO\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + A2DP ==> SCO\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } else if (coex_sta->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + PAN(HS)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + PAN(EDR)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } } } else { if (coex_sta->hid_exist && coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + A2DP\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP; } else if (coex_sta->hid_exist && coex_sta->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + PAN(HS)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + PAN(EDR)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } } else if (coex_sta->pan_exist && coex_sta->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], A2DP + PAN(HS)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], A2DP + PAN(EDR)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP; } } @@ -463,29 +452,29 @@ static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) if (coex_sta->sco_exist) { if (coex_sta->hid_exist && coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP ==> HID\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } else if (coex_sta->hid_exist && coex_sta->pan_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + PAN(HS)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + PAN(EDR)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } } else if (coex_sta->pan_exist && coex_sta->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + A2DP + PAN(HS)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + PAN(EDR) ==> HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + A2DP + PAN(EDR) ==> HID\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } } @@ -494,12 +483,12 @@ static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) coex_sta->pan_exist && coex_sta->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + A2DP + PAN(HS)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + PAN(EDR)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], HID + A2DP + PAN(EDR)\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR; } } @@ -510,12 +499,12 @@ static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) coex_sta->pan_exist && coex_sta->a2dp_exist) { if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; } } @@ -544,15 +533,15 @@ static bool halbtc8821a2ant_need_to_dec_bt_pwr(struct btc_coexist *btcoexist) if (wifi_connected) { if (bt_hs_on) { if (bt_hs_rssi > 37) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt power for HS mode!!\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt power for HS mode!!\n"); ret = true; } } else { if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt power for Wifi is connected!!\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt power for Wifi is connected!!\n"); ret = true; } } @@ -570,10 +559,10 @@ static void btc8821a2ant_set_fw_dac_swing_lev(struct btc_coexist *btcoexist, */ h2c_parameter[0] = dac_swing_lvl; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swing_lvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); } @@ -588,9 +577,9 @@ static void halbtc8821a2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, if (dec_bt_pwr) h2c_parameter[0] |= BIT1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], decrease Bt Power : %s, FW write 0x62 = 0x%x\n", - (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], decrease Bt Power : %s, FW write 0x62 = 0x%x\n", + (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); } @@ -598,16 +587,16 @@ static void halbtc8821a2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, static void halbtc8821a2ant_dec_bt_pwr(struct btc_coexist *btcoexist, bool force_exec, bool dec_bt_pwr) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s Dec BT power = %s\n", - (force_exec ? "force to" : ""), - ((dec_bt_pwr) ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s Dec BT power = %s\n", + (force_exec ? "force to" : ""), + ((dec_bt_pwr) ? "ON" : "OFF")); coex_dm->cur_dec_bt_pwr = dec_bt_pwr; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_dec_bt_pwr = %d, cur_dec_bt_pwr = %d\n", - coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_dec_bt_pwr = %d, cur_dec_bt_pwr = %d\n", + coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); if (coex_dm->pre_dec_bt_pwr == coex_dm->cur_dec_bt_pwr) return; @@ -627,10 +616,10 @@ static void btc8821a2ant_set_fw_bt_lna_constr(struct btc_coexist *btcoexist, if (bt_lna_cons_on) h2c_parameter[1] |= BIT0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set BT LNA Constrain: %s, FW write 0x69 = 0x%x\n", - (bt_lna_cons_on ? "ON!!" : "OFF!!"), - h2c_parameter[0]<<8|h2c_parameter[1]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set BT LNA Constrain: %s, FW write 0x69 = 0x%x\n", + bt_lna_cons_on ? "ON!!" : "OFF!!", + h2c_parameter[0] << 8 | h2c_parameter[1]); btcoexist->btc_fill_h2c(btcoexist, 0x69, 2, h2c_parameter); } @@ -638,17 +627,17 @@ static void btc8821a2ant_set_fw_bt_lna_constr(struct btc_coexist *btcoexist, static void btc8821a2_set_bt_lna_const(struct btc_coexist *btcoexist, bool force_exec, bool bt_lna_cons_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT Constrain = %s\n", - (force_exec ? "force" : ""), - ((bt_lna_cons_on) ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s BT Constrain = %s\n", + (force_exec ? "force" : ""), + ((bt_lna_cons_on) ? "ON" : "OFF")); coex_dm->cur_bt_lna_constrain = bt_lna_cons_on; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_lna_constrain = %d,cur_bt_lna_constrain = %d\n", - coex_dm->pre_bt_lna_constrain, - coex_dm->cur_bt_lna_constrain); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_lna_constrain = %d,cur_bt_lna_constrain = %d\n", + coex_dm->pre_bt_lna_constrain, + coex_dm->cur_bt_lna_constrain); if (coex_dm->pre_bt_lna_constrain == coex_dm->cur_bt_lna_constrain) @@ -669,10 +658,10 @@ static void halbtc8821a2ant_set_fw_bt_psd_mode(struct btc_coexist *btcoexist, h2c_parameter[1] = bt_psd_mode; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set BT PSD mode = 0x%x, FW write 0x69 = 0x%x\n", - h2c_parameter[1], - h2c_parameter[0]<<8|h2c_parameter[1]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set BT PSD mode = 0x%x, FW write 0x69 = 0x%x\n", + h2c_parameter[1], + h2c_parameter[0] << 8 | h2c_parameter[1]); btcoexist->btc_fill_h2c(btcoexist, 0x69, 2, h2c_parameter); } @@ -680,15 +669,15 @@ static void halbtc8821a2ant_set_fw_bt_psd_mode(struct btc_coexist *btcoexist, static void halbtc8821a2ant_set_bt_psd_mode(struct btc_coexist *btcoexist, bool force_exec, u8 bt_psd_mode) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT PSD mode = 0x%x\n", - (force_exec ? "force" : ""), bt_psd_mode); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s BT PSD mode = 0x%x\n", + (force_exec ? "force" : ""), bt_psd_mode); coex_dm->cur_bt_psd_mode = bt_psd_mode; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_psd_mode = 0x%x, cur_bt_psd_mode = 0x%x\n", - coex_dm->pre_bt_psd_mode, coex_dm->cur_bt_psd_mode); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_psd_mode = 0x%x, cur_bt_psd_mode = 0x%x\n", + coex_dm->pre_bt_psd_mode, coex_dm->cur_bt_psd_mode); if (coex_dm->pre_bt_psd_mode == coex_dm->cur_bt_psd_mode) return; @@ -709,10 +698,10 @@ static void halbtc8821a2ant_set_bt_auto_report(struct btc_coexist *btcoexist, if (enable_auto_report) h2c_parameter[0] |= BIT0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", - (enable_auto_report ? "Enabled!!" : "Disabled!!"), - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", + (enable_auto_report ? "Enabled!!" : "Disabled!!"), + h2c_parameter[0]); btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); } @@ -721,17 +710,17 @@ static void halbtc8821a2ant_bt_auto_report(struct btc_coexist *btcoexist, bool force_exec, bool enable_auto_report) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT Auto report = %s\n", - (force_exec ? "force to" : ""), - ((enable_auto_report) ? "Enabled" : "Disabled")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s BT Auto report = %s\n", + (force_exec ? "force to" : ""), + ((enable_auto_report) ? "Enabled" : "Disabled")); coex_dm->cur_bt_auto_report = enable_auto_report; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", - coex_dm->pre_bt_auto_report, - coex_dm->cur_bt_auto_report); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", + coex_dm->pre_bt_auto_report, + coex_dm->cur_bt_auto_report); if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) return; @@ -746,16 +735,16 @@ static void halbtc8821a2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist, bool force_exec, u8 fw_dac_swing_lvl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set FW Dac Swing level = %d\n", - (force_exec ? "force to" : ""), fw_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s set FW Dac Swing level = %d\n", + (force_exec ? "force to" : ""), fw_dac_swing_lvl); coex_dm->cur_fw_dac_swing_lvl = fw_dac_swing_lvl; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_fw_dac_swing_lvl = %d, cur_fw_dac_swing_lvl = %d\n", - coex_dm->pre_fw_dac_swing_lvl, - coex_dm->cur_fw_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_fw_dac_swing_lvl = %d, cur_fw_dac_swing_lvl = %d\n", + coex_dm->pre_fw_dac_swing_lvl, + coex_dm->cur_fw_dac_swing_lvl); if (coex_dm->pre_fw_dac_swing_lvl == coex_dm->cur_fw_dac_swing_lvl) @@ -773,8 +762,8 @@ static void btc8821a2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, { if (rx_rf_shrink_on) { /* Shrink RF Rx LPF corner */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Shrink RF Rx LPF corner!!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Shrink RF Rx LPF corner!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff, 0xffffc); } else { @@ -782,8 +771,8 @@ static void btc8821a2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, * After initialized, we can use coex_dm->bt_rf0x1e_backup */ if (btcoexist->initilized) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Resume RF Rx LPF corner!!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Resume RF Rx LPF corner!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff, coex_dm->bt_rf0x1e_backup); @@ -794,17 +783,17 @@ static void btc8821a2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, static void halbtc8821a2ant_RfShrink(struct btc_coexist *btcoexist, bool force_exec, bool rx_rf_shrink_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn Rx RF Shrink = %s\n", - (force_exec ? "force to" : ""), - ((rx_rf_shrink_on) ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn Rx RF Shrink = %s\n", + (force_exec ? "force to" : ""), + ((rx_rf_shrink_on) ? "ON" : "OFF")); coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_rf_rx_lpf_shrink = %d, cur_rf_rx_lpf_shrink = %d\n", - coex_dm->pre_rf_rx_lpf_shrink, - coex_dm->cur_rf_rx_lpf_shrink); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_rf_rx_lpf_shrink = %d, cur_rf_rx_lpf_shrink = %d\n", + coex_dm->pre_rf_rx_lpf_shrink, + coex_dm->cur_rf_rx_lpf_shrink); if (coex_dm->pre_rf_rx_lpf_shrink == coex_dm->cur_rf_rx_lpf_shrink) @@ -835,9 +824,9 @@ static void btc8821a2ant_SetSwPenTxRateAdapt(struct btc_coexist *btcoexist, h2c_parameter[5] = 0xf9; } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); } @@ -846,17 +835,17 @@ static void halbtc8821a2ant_low_penalty_ra(struct btc_coexist *btcoexist, bool force_exec, bool low_penalty_ra) { /*return;*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn LowPenaltyRA = %s\n", - (force_exec ? "force to" : ""), - ((low_penalty_ra) ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn LowPenaltyRA = %s\n", + (force_exec ? "force to" : ""), + ((low_penalty_ra) ? "ON" : "OFF")); coex_dm->cur_low_penalty_ra = low_penalty_ra; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_low_penalty_ra = %d, cur_low_penalty_ra = %d\n", - coex_dm->pre_low_penalty_ra, - coex_dm->cur_low_penalty_ra); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_low_penalty_ra = %d, cur_low_penalty_ra = %d\n", + coex_dm->pre_low_penalty_ra, + coex_dm->cur_low_penalty_ra); if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) return; @@ -872,8 +861,8 @@ static void halbtc8821a2ant_set_dac_swing_reg(struct btc_coexist *btcoexist, { u8 val = (u8)level; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Write SwDacSwing = 0x%x\n", level); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], Write SwDacSwing = 0x%x\n", level); btcoexist->btc_write_1byte_bitmask(btcoexist, 0xc5b, 0x3e, val); } @@ -891,21 +880,21 @@ static void halbtc8821a2ant_dac_swing(struct btc_coexist *btcoexist, bool force_exec, bool dac_swing_on, u32 dac_swing_lvl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn DacSwing = %s, dac_swing_lvl = 0x%x\n", - (force_exec ? "force to" : ""), - ((dac_swing_on) ? "ON" : "OFF"), - dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn DacSwing = %s, dac_swing_lvl = 0x%x\n", + (force_exec ? "force to" : ""), + ((dac_swing_on) ? "ON" : "OFF"), + dac_swing_lvl); coex_dm->cur_dac_swing_on = dac_swing_on; coex_dm->cur_dac_swing_lvl = dac_swing_lvl; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_dac_swing_on = %d, pre_dac_swing_lvl = 0x%x, cur_dac_swing_on = %d, cur_dac_swing_lvl = 0x%x\n", - coex_dm->pre_dac_swing_on, - coex_dm->pre_dac_swing_lvl, - coex_dm->cur_dac_swing_on, - coex_dm->cur_dac_swing_lvl); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_dac_swing_on = %d, pre_dac_swing_lvl = 0x%x, cur_dac_swing_on = %d, cur_dac_swing_lvl = 0x%x\n", + coex_dm->pre_dac_swing_on, + coex_dm->pre_dac_swing_lvl, + coex_dm->cur_dac_swing_on, + coex_dm->cur_dac_swing_lvl); if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && (coex_dm->pre_dac_swing_lvl == @@ -924,12 +913,12 @@ static void halbtc8821a2ant_set_adc_back_off(struct btc_coexist *btcoexist, bool adc_back_off) { if (adc_back_off) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB BackOff Level On!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], BB BackOff Level On!\n"); btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x3); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB BackOff Level Off!\n"); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], BB BackOff Level Off!\n"); btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x1); } } @@ -937,16 +926,17 @@ static void halbtc8821a2ant_set_adc_back_off(struct btc_coexist *btcoexist, static void halbtc8821a2ant_adc_back_off(struct btc_coexist *btcoexist, bool force_exec, bool adc_back_off) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn AdcBackOff = %s\n", - (force_exec ? "force to" : ""), - ((adc_back_off) ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s turn AdcBackOff = %s\n", + (force_exec ? "force to" : ""), + ((adc_back_off) ? "ON" : "OFF")); coex_dm->cur_adc_back_off = adc_back_off; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_adc_back_off = %d, cur_adc_back_off = %d\n", - coex_dm->pre_adc_back_off, coex_dm->cur_adc_back_off); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_adc_back_off = %d, cur_adc_back_off = %d\n", + coex_dm->pre_adc_back_off, + coex_dm->cur_adc_back_off); if (coex_dm->pre_adc_back_off == coex_dm->cur_adc_back_off) return; @@ -960,20 +950,20 @@ static void halbtc8821a2ant_set_coex_table(struct btc_coexist *btcoexist, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); } @@ -981,28 +971,28 @@ static void halbtc8821a2ant_coex_table(struct btc_coexist *btcoexist, bool force_exec, u32 val0x6c0, u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - (force_exec ? "force to" : ""), - val0x6c0, val0x6c4, val0x6c8, val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", + (force_exec ? "force to" : ""), + val0x6c0, val0x6c4, val0x6c8, val0x6cc); coex_dm->cur_val0x6c0 = val0x6c0; coex_dm->cur_val0x6c4 = val0x6c4; coex_dm->cur_val0x6c8 = val0x6c8; coex_dm->cur_val0x6cc = val0x6cc; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_val0x6c0 = 0x%x, pre_val0x6c4 = 0x%x, pre_val0x6c8 = 0x%x, pre_val0x6cc = 0x%x !!\n", - coex_dm->pre_val0x6c0, - coex_dm->pre_val0x6c4, - coex_dm->pre_val0x6c8, - coex_dm->pre_val0x6cc); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], cur_val0x6c0 = 0x%x, cur_val0x6c4 = 0x%x, cur_val0x6c8 = 0x%x, cur_val0x6cc = 0x%x !!\n", - coex_dm->cur_val0x6c0, - coex_dm->cur_val0x6c4, - coex_dm->cur_val0x6c8, - coex_dm->cur_val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_val0x6c0 = 0x%x, pre_val0x6c4 = 0x%x, pre_val0x6c8 = 0x%x, pre_val0x6cc = 0x%x !!\n", + coex_dm->pre_val0x6c0, + coex_dm->pre_val0x6c4, + coex_dm->pre_val0x6c8, + coex_dm->pre_val0x6cc); + btc_alg_dbg(ALGO_TRACE_SW_DETAIL, + "[BTCoex], cur_val0x6c0 = 0x%x, cur_val0x6c4 = 0x%x, cur_val0x6c8 = 0x%x, cur_val0x6cc = 0x%x !!\n", + coex_dm->cur_val0x6c0, + coex_dm->cur_val0x6c4, + coex_dm->cur_val0x6c8, + coex_dm->cur_val0x6cc); if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && @@ -1027,9 +1017,9 @@ static void halbtc8821a2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoex, if (enable) h2c_parameter[0] |= BIT0;/* function enable */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); btcoex->btc_fill_h2c(btcoex, 0x63, 1, h2c_parameter); } @@ -1037,16 +1027,16 @@ static void halbtc8821a2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoex, static void halbtc8821a2ant_ignore_wlan_act(struct btc_coexist *btcoexist, bool force_exec, bool enable) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); coex_dm->cur_ignore_wlan_act = enable; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); if (coex_dm->pre_ignore_wlan_act == coex_dm->cur_ignore_wlan_act) @@ -1075,13 +1065,13 @@ static void halbtc8821a2ant_set_fw_pstdma(struct btc_coexist *btcoexist, coex_dm->ps_tdma_para[3] = byte4; coex_dm->ps_tdma_para[4] = byte5; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1]<<24| - h2c_parameter[2]<<16| - h2c_parameter[3]<<8| - h2c_parameter[4]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | + h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | + h2c_parameter[4]); btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); } @@ -1175,20 +1165,20 @@ static void halbtc8821a2ant_set_ant_path(struct btc_coexist *btcoexist, static void halbtc8821a2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec, bool turn_on, u8 type) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn %s PS TDMA, type = %d\n", - (force_exec ? "force to" : ""), (turn_on ? "ON" : "OFF"), - type); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], %s turn %s PS TDMA, type = %d\n", + (force_exec ? "force to" : ""), (turn_on ? "ON" : "OFF"), + type); coex_dm->cur_ps_tdma_on = turn_on; coex_dm->cur_ps_tdma = type; if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ps_tdma_on = %d, cur_ps_tdma_on = %d!!\n", - coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ps_tdma = %d, cur_ps_tdma = %d!!\n", - coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ps_tdma_on = %d, cur_ps_tdma_on = %d!!\n", + coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ps_tdma = %d, cur_ps_tdma = %d!!\n", + coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) @@ -1374,8 +1364,8 @@ static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi IPS + BT IPS!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi IPS + BT IPS!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); @@ -1392,13 +1382,13 @@ static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) &low_pwr_disable); if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Busy + BT IPS!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Busy + BT IPS!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi LPS + BT IPS!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi LPS + BT IPS!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); } @@ -1416,8 +1406,8 @@ static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi IPS + BT LPS!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi IPS + BT LPS!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); @@ -1433,13 +1423,13 @@ static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Busy + BT LPS!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Busy + BT LPS!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi LPS + BT LPS!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi LPS + BT LPS!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); } @@ -1458,8 +1448,8 @@ static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi IPS + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi IPS + BT Busy!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); @@ -1478,12 +1468,12 @@ static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) &low_pwr_disable); if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Busy + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi Busy + BT Busy!!\n"); common = false; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi LPS + BT Busy!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Wifi LPS + BT Busy!!\n"); halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 21); @@ -1505,8 +1495,8 @@ static void btc8821a2_int1(struct btc_coexist *btcoexist, bool tx_pause, int result) { if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 71) { halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, @@ -1601,8 +1591,8 @@ static void btc8821a2_int1(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 71); @@ -1706,8 +1696,8 @@ static void btc8821a2_int2(struct btc_coexist *btcoexist, bool tx_pause, int result) { if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 1) { halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); @@ -1796,8 +1786,8 @@ static void btc8821a2_int2(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); @@ -1892,8 +1882,8 @@ static void btc8821a2_int3(struct btc_coexist *btcoexist, bool tx_pause, int result) { if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); if (coex_dm->cur_ps_tdma == 1) { halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); @@ -1982,8 +1972,8 @@ static void btc8821a2_int3(struct btc_coexist *btcoexist, bool tx_pause, } } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); if (coex_dm->cur_ps_tdma == 5) { halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); @@ -2085,13 +2075,13 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, int result; u8 retry_count = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjust()\n"); + btc_alg_dbg(ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjust()\n"); if (coex_dm->reset_tdma_adjust) { coex_dm->reset_tdma_adjust = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); if (sco_hid) { if (tx_pause) { if (max_interval == 1) { @@ -2195,11 +2185,11 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, } else { /* accquire the BT TRx retry count from BT_Info byte2 */ retry_count = coex_sta->bt_retry_cnt; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], retry_count = %d\n", retry_count); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], up = %d, dn = %d, m = %d, n = %d, wait_count = %d\n", - (int)up, (int)dn, (int)m, (int)n, (int)wait_count); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], retry_count = %d\n", retry_count); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], up = %d, dn = %d, m = %d, n = %d, wait_count = %d\n", + (int)up, (int)dn, (int)m, (int)n, (int)wait_count); result = 0; wait_count++; @@ -2220,9 +2210,8 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, up = 0; dn = 0; result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi duration!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi duration!!\n"); } } else if (retry_count <= 3) { /* <=3 retry in the last 2-second duration */ @@ -2251,9 +2240,8 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); } } else { /* retry count > 3, if retry count > 3 happens once, @@ -2274,12 +2262,12 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, dn = 0; wait_count = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], max Interval = %d\n", max_interval); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], max Interval = %d\n", max_interval); if (max_interval == 1) btc8821a2_int1(btcoexist, tx_pause, result); else if (max_interval == 2) @@ -2295,9 +2283,9 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { bool scan = false, link = false, roam = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], PsTdma type dismatch!!!, cur_ps_tdma = %d, recordPsTdma = %d\n", - coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], PsTdma type dismatch!!!, cur_ps_tdma = %d, recordPsTdma = %d\n", + coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); @@ -2307,8 +2295,8 @@ static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, coex_dm->tdma_adj_type); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); + btc_alg_dbg(ALGO_TRACE_FW_DETAIL, + "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); } } @@ -3183,8 +3171,8 @@ static void halbtc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) u8 algorithm = 0; if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Manual control!!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Manual control!!!\n"); return; } @@ -3192,8 +3180,8 @@ static void halbtc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); if (wifi_under_5g) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), run 5G coex setting!!<===\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), run 5G coex setting!!<===\n"); halbtc8821a2ant_coex_under_5g(btcoexist); return; } @@ -3201,81 +3189,82 @@ static void halbtc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) algorithm = halbtc8821a2ant_action_algorithm(btcoexist); if (coex_sta->c2h_bt_inquiry_page && (BT_8821A_2ANT_COEX_ALGO_PANHS != algorithm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT is under inquiry/page scan !!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], BT is under inquiry/page scan !!\n"); halbtc8821a2ant_bt_inquiry_page(btcoexist); return; } coex_dm->cur_algorithm = algorithm; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); if (halbtc8821a2ant_is_common_action(btcoexist)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant common.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant common\n"); coex_dm->reset_tdma_adjust = true; } else { if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], pre_algorithm = %d, cur_algorithm = %d\n", - coex_dm->pre_algorithm, coex_dm->cur_algorithm); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], pre_algorithm = %d, cur_algorithm = %d\n", + coex_dm->pre_algorithm, + coex_dm->cur_algorithm); coex_dm->reset_tdma_adjust = true; } switch (coex_dm->cur_algorithm) { case BT_8821A_2ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = SCO.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = SCO\n"); halbtc8821a2ant_action_sco(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID\n"); halbtc8821a2ant_action_hid(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = A2DP\n"); halbtc8821a2ant_action_a2dp(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS)\n"); halbtc8821a2ant_action_a2dp_pan_hs(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = PAN(EDR).\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)\n"); halbtc8821a2ant_action_pan_edr(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HS mode.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HS mode\n"); halbtc8821a2ant_action_pan_hs(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = PAN+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN+A2DP\n"); halbtc8821a2ant_action_pan_edr_a2dp(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID\n"); halbtc8821a2ant_action_pan_edr_hid(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN\n"); btc8821a2ant_act_hid_a2dp_pan_edr(btcoexist); break; case BT_8821A_2ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID+A2DP.\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID+A2DP\n"); halbtc8821a2ant_action_hid_a2dp(btcoexist); break; default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n"); halbtc8821a2ant_coex_all_off(btcoexist); break; } @@ -3294,8 +3283,8 @@ void ex_halbtc8821a2ant_init_hwconfig(struct btc_coexist *btcoexist) { u8 u1tmp = 0; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 2Ant Init HW Config!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], 2Ant Init HW Config!!\n"); /* backup rf 0x1e value */ coex_dm->bt_rf0x1e_backup = @@ -3328,8 +3317,8 @@ ex_halbtc8821a2ant_init_coex_dm( struct btc_coexist *btcoexist ) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); halbtc8821a2ant_init_coex_dm(btcoexist); } @@ -3574,13 +3563,13 @@ ex_halbtc8821a2ant_display_coex_info( void ex_halbtc8821a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); coex_sta->under_ips = true; halbtc8821a2ant_coex_all_off(btcoexist); } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); coex_sta->under_ips = false; /*halbtc8821a2ant_init_coex_dm(btcoexist);*/ } @@ -3589,12 +3578,12 @@ void ex_halbtc8821a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) void ex_halbtc8821a2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); coex_sta->under_lps = true; } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); coex_sta->under_lps = false; } } @@ -3602,22 +3591,22 @@ void ex_halbtc8821a2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) void ex_halbtc8821a2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_SCAN_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); } else if (BTC_SCAN_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); } } void ex_halbtc8821a2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) { if (BTC_ASSOCIATE_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); } else if (BTC_ASSOCIATE_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); } } @@ -3629,11 +3618,11 @@ void ex_halbtc8821a2ant_media_status_notify(struct btc_coexist *btcoexist, u8 wifi_central_chnl; if (BTC_MEDIA_CONNECT == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); } /* only 2.4G we need to inform bt the chnl mask*/ @@ -3654,9 +3643,11 @@ void ex_halbtc8821a2ant_media_status_notify(struct btc_coexist *btcoexist, coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); + btc_alg_dbg(ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0] << 16 | + h2c_parameter[1] << 8 | + h2c_parameter[2]); btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); } @@ -3664,8 +3655,8 @@ void ex_halbtc8821a2ant_media_status_notify(struct btc_coexist *btcoexist, void ex_halbtc8821a2ant_special_packet_notify(struct btc_coexist *btcoexist, u8 type) { if (type == BTC_PACKET_DHCP) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], DHCP Packet notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], DHCP Packet notify\n"); } } @@ -3685,19 +3676,19 @@ void ex_halbtc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist, rsp_source = BT_INFO_SRC_8821A_2ANT_WIFI_FW; coex_sta->bt_info_c2h_cnt[rsp_source]++; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length = %d, hex data = [", - rsp_source, length); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Bt info[%d], length = %d, hex data = [", + rsp_source, length); for (i = 0; i < length; i++) { coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; if (i == 1) bt_info = tmp_buf[i]; if (i == length-1) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); + btc_iface_dbg(INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); } } @@ -3823,8 +3814,8 @@ void ex_halbtc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist, void ex_halbtc8821a2ant_halt_notify(struct btc_coexist *btcoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Halt notify\n"); + btc_iface_dbg(INTF_NOTIFY, + "[BTCoex], Halt notify\n"); halbtc8821a2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); ex_halbtc8821a2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); @@ -3837,31 +3828,31 @@ void ex_halbtc8821a2ant_periodical(struct btc_coexist *btcoexist) struct btc_board_info *board_info = &btcoexist->board_info; struct btc_stack_info *stack_info = &btcoexist->stack_info; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================Periodical===========================\n"); + btc_alg_dbg(ALGO_TRACE, + "[BTCoex], ==========================Periodical===========================\n"); if (dis_ver_info_cnt <= 5) { dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, - board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, + board_info->btdm_ant_num, + board_info->btdm_ant_pos); + btc_iface_dbg(INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + stack_info->profile_notified ? "Yes" : "No", + stack_info->hci_version); btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); + btc_iface_dbg(INTF_INIT, + "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + btc_iface_dbg(INTF_INIT, + "[BTCoex], ****************************************************************\n"); } halbtc8821a2ant_query_bt_info(btcoexist); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index babd1490f20c..b660c214dc71 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -141,8 +141,8 @@ static u8 halbtc_get_wifi_central_chnl(struct btc_coexist *btcoexist) if (rtlphy->current_channel != 0) chnl = rtlphy->current_channel; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "static halbtc_get_wifi_central_chnl:%d\n", chnl); + btc_alg_dbg(ALGO_TRACE, + "static halbtc_get_wifi_central_chnl:%d\n", chnl); return chnl; } diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h index f41ca57dd8a7..3cbe34c535ec 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h @@ -116,12 +116,17 @@ extern u32 btc_dbg_type[]; #define WIFI_P2P_GO_CONNECTED BIT3 #define WIFI_P2P_GC_CONNECTED BIT4 -#define BTC_PRINT(dbgtype, dbgflag, printstr, ...) \ - do { \ - if (unlikely(btc_dbg_type[dbgtype] & dbgflag)) {\ - printk(printstr, ##__VA_ARGS__); \ - } \ - } while (0) +#define btc_alg_dbg(dbgflag, fmt, ...) \ +do { \ + if (unlikely(btc_dbg_type[BTC_MSG_ALGORITHM] & dbgflag)) \ + printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ +} while (0) +#define btc_iface_dbg(dbgflag, fmt, ...) \ +do { \ + if (unlikely(btc_dbg_type[BTC_MSG_INTERFACE] & dbgflag)) \ + printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ +} while (0) + #define BTC_RSSI_HIGH(_rssi_) \ ((_rssi_ == BTC_RSSI_STATE_HIGH || \ -- GitLab From e32993eb3aed598790ba0c581796c357898bd8f0 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 18 Mar 2016 16:20:48 +0000 Subject: [PATCH 1612/9938] wl12xx: remove redundant null check on wl->scan.ssid ssid is an array of u8, so it can never be null, so the null check on wl->scan.ssid is redundant and can be removed. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wl12xx/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c index ebed13af9852..a0dfc59e9644 100644 --- a/drivers/net/wireless/ti/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wl12xx/scan.c @@ -149,7 +149,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif, else cmd->params.band = WL1271_SCAN_BAND_5_GHZ; - if (wl->scan.ssid_len && wl->scan.ssid) { + if (wl->scan.ssid_len) { cmd->params.ssid_len = wl->scan.ssid_len; memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); } -- GitLab From 8b4c0009313f3d42e2540e3e1f776097dd0db73d Mon Sep 17 00:00:00 2001 From: Vishal Thanki Date: Sat, 19 Mar 2016 11:41:01 +0100 Subject: [PATCH 1613/9938] rt2x00usb: Use usb anchor to manage URB With current driver, it is observed that a URB is not completed while the USB disconnect is initiated. Due to that, the URB completion handler is trying to access the resource which was freed as a part of USB disconnect. Managing the URBs with anchor will make sure that all the URBs are handled gracefully before device gets disconnected. Signed-off-by: Vishal Thanki Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 3 +++ .../net/wireless/ralink/rt2x00/rt2x00dev.c | 3 +++ .../net/wireless/ralink/rt2x00/rt2x00usb.c | 21 +++++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 6418620f95ff..3dacede7da5e 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -1002,6 +1003,8 @@ struct rt2x00_dev { /* Extra TX headroom required for alignment purposes. */ unsigned int extra_tx_headroom; + + struct usb_anchor *anchor; }; struct rt2x00_bar_list_entry { diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c index 5639ed816813..b2f7c586045d 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c @@ -1422,11 +1422,14 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) cancel_work_sync(&rt2x00dev->intf_work); cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); cancel_work_sync(&rt2x00dev->sleep_work); +#ifdef CONFIG_RT2X00_LIB_USB if (rt2x00_is_usb(rt2x00dev)) { + usb_kill_anchored_urbs(rt2x00dev->anchor); hrtimer_cancel(&rt2x00dev->txstatus_timer); cancel_work_sync(&rt2x00dev->rxdone_work); cancel_work_sync(&rt2x00dev->txdone_work); } +#endif if (rt2x00dev->workqueue) destroy_workqueue(rt2x00dev->workqueue); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c index 7627af6098eb..7cf26c6124d1 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c @@ -171,8 +171,11 @@ static void rt2x00usb_register_read_async_cb(struct urb *urb) { struct rt2x00_async_read_data *rd = urb->context; if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) { - if (usb_submit_urb(urb, GFP_ATOMIC) < 0) + usb_anchor_urb(urb, rd->rt2x00dev->anchor); + if (usb_submit_urb(urb, GFP_ATOMIC) < 0) { + usb_unanchor_urb(urb); kfree(rd); + } } else kfree(rd); } @@ -206,8 +209,11 @@ void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0), (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg), rt2x00usb_register_read_async_cb, rd); - if (usb_submit_urb(urb, GFP_ATOMIC) < 0) + usb_anchor_urb(urb, rt2x00dev->anchor); + if (usb_submit_urb(urb, GFP_ATOMIC) < 0) { + usb_unanchor_urb(urb); kfree(rd); + } usb_free_urb(urb); } EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async); @@ -313,8 +319,10 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data) entry->skb->data, length, rt2x00usb_interrupt_txdone, entry); + usb_anchor_urb(entry_priv->urb, rt2x00dev->anchor); status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); if (status) { + usb_unanchor_urb(entry_priv->urb); if (status == -ENODEV) clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); @@ -402,8 +410,10 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data) entry->skb->data, entry->skb->len, rt2x00usb_interrupt_rxdone, entry); + usb_anchor_urb(entry_priv->urb, rt2x00dev->anchor); status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); if (status) { + usb_unanchor_urb(entry_priv->urb); if (status == -ENODEV) clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); @@ -818,6 +828,13 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, if (retval) goto exit_free_reg; + rt2x00dev->anchor = devm_kmalloc(&usb_dev->dev, + sizeof(struct usb_anchor), + GFP_KERNEL); + if (!rt2x00dev->anchor) + goto exit_free_reg; + + init_usb_anchor(rt2x00dev->anchor); return 0; exit_free_reg: -- GitLab From 3d43e031840057f9609da3c546787f05cd6c5518 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 20 Mar 2016 17:34:52 +0000 Subject: [PATCH 1614/9938] brcmfmac: sdio: remove unused variable retry_limit retry_limit has never been used during the life of this driver, so we may as well remove it as it is redundant. Signed-off-by: Colin Ian King Reviewed-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 43fd3f402eba..cd92ba77ecfd 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -535,9 +535,6 @@ static int qcount[NUMPRIO]; #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) -/* Retry count for register access failures */ -static const uint retry_limit = 2; - /* Limit on rounding up frames */ static const uint max_roundup = 512; -- GitLab From d9f5725fb00b87f99d6fc876d27f7d54ab351669 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 22 Mar 2016 12:09:56 +0800 Subject: [PATCH 1615/9938] mwifiex: advertise low priority scan feature Low priority scan handling code which delays or aborts scan operation based on Tx traffic is removed recently. The reason is firmware already takes care of it in our new feature scan channel gap. Hence we should advertise low priority scan support to cfg80211. This patch fixes a problem in which OBSS scan request from wpa_supplicant was being rejected by cfg80211. Signed-off-by: Amitkumar Karwar Signed-off-by: Wei-Ning Huang Tested-by: Wei-Ning Huang Acked-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index b0663bdea5b5..108e64137826 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4092,6 +4092,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->features |= NL80211_FEATURE_HT_IBSS | NL80211_FEATURE_INACTIVITY_TIMER | + NL80211_FEATURE_LOW_PRIORITY_SCAN | NL80211_FEATURE_NEED_OBSS_SCAN; if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) -- GitLab From 4a4436573a6669516f73bac25016683d396ed4c4 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 31 Mar 2016 16:35:58 +0300 Subject: [PATCH 1616/9938] ALSA: pcm: add IEC958 channel status helper for hw_params Add IEC958 channel status helper that gets the audio properties from snd_pcm_hw_params instead of snd_pcm_runtime. This is needed to produce the channel status bits already in audio stream configuration phase. Signed-off-by: Jyri Sarha Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- include/sound/pcm_iec958.h | 2 ++ sound/core/pcm_iec958.c | 64 ++++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h index 0eed397aca8e..36f023acb201 100644 --- a/include/sound/pcm_iec958.h +++ b/include/sound/pcm_iec958.h @@ -6,4 +6,6 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, size_t len); +int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, + u8 *cs, size_t len); #endif diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c index 36b2d7aca1bd..e016871a978f 100644 --- a/sound/core/pcm_iec958.c +++ b/sound/core/pcm_iec958.c @@ -9,30 +9,18 @@ #include #include #include +#include #include -/** - * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status - * @runtime: pcm runtime structure with ->rate filled in - * @cs: channel status buffer, at least four bytes - * @len: length of channel status buffer - * - * Create the consumer format channel status data in @cs of maximum size - * @len corresponding to the parameters of the PCM runtime @runtime. - * - * Drivers may wish to tweak the contents of the buffer after creation. - * - * Returns: length of buffer, or negative error code if something failed. - */ -int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, - size_t len) +static int create_iec958_consumer(uint rate, uint sample_width, + u8 *cs, size_t len) { unsigned int fs, ws; if (len < 4) return -EINVAL; - switch (runtime->rate) { + switch (rate) { case 32000: fs = IEC958_AES3_CON_FS_32000; break; @@ -59,7 +47,7 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, } if (len > 4) { - switch (snd_pcm_format_width(runtime->format)) { + switch (sample_width) { case 16: ws = IEC958_AES4_CON_WORDLEN_20_16; break; @@ -92,4 +80,46 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, return len; } + +/** + * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status + * @runtime: pcm runtime structure with ->rate filled in + * @cs: channel status buffer, at least four bytes + * @len: length of channel status buffer + * + * Create the consumer format channel status data in @cs of maximum size + * @len corresponding to the parameters of the PCM runtime @runtime. + * + * Drivers may wish to tweak the contents of the buffer after creation. + * + * Returns: length of buffer, or negative error code if something failed. + */ +int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, + size_t len) +{ + return create_iec958_consumer(runtime->rate, + snd_pcm_format_width(runtime->format), + cs, len); +} EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); + +/** + * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status + * @hw_params: the hw_params instance for extracting rate and sample format + * @cs: channel status buffer, at least four bytes + * @len: length of channel status buffer + * + * Create the consumer format channel status data in @cs of maximum size + * @len corresponding to the parameters of the PCM runtime @runtime. + * + * Drivers may wish to tweak the contents of the buffer after creation. + * + * Returns: length of buffer, or negative error code if something failed. + */ +int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, + u8 *cs, size_t len) +{ + return create_iec958_consumer(params_rate(params), params_width(params), + cs, len); +} +EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params); -- GitLab From 415cd2a645b2573f173cc52419049f9caacf9a47 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 18 Mar 2016 16:06:53 -0700 Subject: [PATCH 1617/9938] igb: Fix sparse warning about passing __beXX into leXX_to_cpup We were casting the addr as __beXX and then passing it into le32_to_cpu because the device expects the MAC address to be in network order even though the register set is little endian. Instead of casting it as __beXX we can just cast it as __leXX in order to maintain consistency since the region of memory is already in little endian order as far as we are concerned. Signed-off-by: Alexander Duyck Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 55a1405cb2a1..36814a2e326d 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -7845,11 +7845,13 @@ static void igb_rar_set_qsel(struct igb_adapter *adapter, u8 *addr, u32 index, struct e1000_hw *hw = &adapter->hw; u32 rar_low, rar_high; - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to CPU endian + /* HW expects these to be in network order when they are plugged + * into the registers which are little endian. In order to guarantee + * that ordering we need to do an leXX_to_cpup here in order to be + * ready for the byteswap that occurs with writel */ - rar_low = le32_to_cpup((__be32 *)(addr)); - rar_high = le16_to_cpup((__be16 *)(addr + 4)); + rar_low = le32_to_cpup((__le32 *)(addr)); + rar_high = le16_to_cpup((__le16 *)(addr + 4)); /* Indicate to hardware the Address is Valid. */ rar_high |= E1000_RAH_AV; -- GitLab From 7f0ba845607364c76009e396a31651fa3a24bd1c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 7 Mar 2016 09:30:21 -0800 Subject: [PATCH 1618/9938] igb: Add support for bulk Tx cleanup & cleanup boolean logic This patch enables bulk free in Tx cleanup for igb and cleans up the boolean logic in the polling routines for igb in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf. Signed-off-by: Alexander Duyck Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 36814a2e326d..e40983ca35b4 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -150,7 +150,7 @@ static void igb_update_dca(struct igb_q_vector *); static void igb_setup_dca(struct igb_adapter *); #endif /* CONFIG_IGB_DCA */ static int igb_poll(struct napi_struct *, int); -static bool igb_clean_tx_irq(struct igb_q_vector *); +static bool igb_clean_tx_irq(struct igb_q_vector *, int); static int igb_clean_rx_irq(struct igb_q_vector *, int); static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); static void igb_tx_timeout(struct net_device *); @@ -6522,13 +6522,14 @@ static int igb_poll(struct napi_struct *napi, int budget) igb_update_dca(q_vector); #endif if (q_vector->tx.ring) - clean_complete = igb_clean_tx_irq(q_vector); + clean_complete = igb_clean_tx_irq(q_vector, budget); if (q_vector->rx.ring) { int cleaned = igb_clean_rx_irq(q_vector, budget); work_done += cleaned; - clean_complete &= (cleaned < budget); + if (cleaned >= budget) + clean_complete = false; } /* If all work not completed, return budget and keep polling */ @@ -6545,10 +6546,11 @@ static int igb_poll(struct napi_struct *napi, int budget) /** * igb_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: pointer to q_vector containing needed info + * @napi_budget: Used to determine if we are in netpoll * * returns true if ring is completely cleaned **/ -static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) +static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) { struct igb_adapter *adapter = q_vector->adapter; struct igb_ring *tx_ring = q_vector->tx.ring; @@ -6587,7 +6589,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) total_packets += tx_buffer->gso_segs; /* free the skb */ - dev_consume_skb_any(tx_buffer->skb); + napi_consume_skb(tx_buffer->skb, napi_budget); /* unmap skb header data */ dma_unmap_single(tx_ring->dev, -- GitLab From 806ffb1d504927d1449397377eac63bb63489266 Mon Sep 17 00:00:00 2001 From: John Holland Date: Thu, 18 Feb 2016 12:10:52 +0100 Subject: [PATCH 1619/9938] igb: allow setting MAC address on i211 using a device tree blob The Intel i211 LOM PCIe Ethernet controllers' iNVM operates as an OTP and has no external EEPROM interface [1]. The following allows the driver to pickup the MAC address from a device tree blob when CONFIG_OF has been enabled. [1] http://www.intel.com/content/www/us/en/embedded/products/networking/i211-ethernet-controller-datasheet.html Signed-off-by: John Holland Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index e40983ca35b4..ff0476c89438 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -50,6 +50,7 @@ #include #include #include +#include #ifdef CONFIG_IGB_DCA #include #endif @@ -2442,9 +2443,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } - /* copy the MAC address out of the NVM */ - if (hw->mac.ops.read_mac_addr(hw)) - dev_err(&pdev->dev, "NVM Read Error\n"); + if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) { + /* copy the MAC address out of the NVM */ + if (hw->mac.ops.read_mac_addr(hw)) + dev_err(&pdev->dev, "NVM Read Error\n"); + } memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); -- GitLab From 8a21ec4e0abb99884ef2da3e4f950025f3bf7fd3 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 5 Apr 2016 09:52:21 +0530 Subject: [PATCH 1620/9938] cxgb4/cxgb4vf: Deprecate module parameter dflt_msg_enable Message level can be set through ethtool, so deprecate module parameter which is used to set the same. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 ++- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index d1e3f0997d6b..a1e329ec24cd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -168,7 +168,8 @@ MODULE_PARM_DESC(force_init, "Forcibly become Master PF and initialize adapter," static int dflt_msg_enable = DFLT_MSG_ENABLE; module_param(dflt_msg_enable, int, 0644); -MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T4 default message enable bitmap"); +MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T4 default message enable bitmap, " + "deprecated parameter"); /* * The driver uses the best interrupt scheme available on a platform in the diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 1cc8a7a69457..730fec73d5a6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -74,7 +74,8 @@ static int dflt_msg_enable = DFLT_MSG_ENABLE; module_param(dflt_msg_enable, int, 0644); MODULE_PARM_DESC(dflt_msg_enable, - "default adapter ethtool message level bitmap"); + "default adapter ethtool message level bitmap, " + "deprecated parameter"); /* * The driver uses the best interrupt scheme available on a platform in the -- GitLab From efea95d45e6ab4a30df9801f8e9bf68007ee9b43 Mon Sep 17 00:00:00 2001 From: Doron Shikmoni Date: Wed, 17 Feb 2016 09:34:25 +0200 Subject: [PATCH 1621/9938] igb: Garbled output for "ethtool -m" Garbled output for "ethtool -m ethX", in igb-driven NICs with module / plugin EEPROM (i.e. SFP information). Each output data byte appears duplicated. In igb_ethtool.c, igb_get_module_eeprom() is reading the EEPROM via i2c; the eeprom offset for each word that's read via igb_read_phy_reg_i2c() was passed in #words, whereas it needs to be a byte offset. This patches fixes the bug. Signed-off-by: Doron Shikmoni Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 7982243d1f9b..bb4d6cdcd0b8 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -2831,7 +2831,8 @@ static int igb_get_module_eeprom(struct net_device *netdev, /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */ for (i = 0; i < last_word - first_word + 1; i++) { - status = igb_read_phy_reg_i2c(hw, first_word + i, &dataword[i]); + status = igb_read_phy_reg_i2c(hw, (first_word + i) * 2, + &dataword[i]); if (status) { /* Error occurred while reading module */ kfree(dataword); -- GitLab From 0c867c9bf84ce2a998f83725bd363f66ce84d548 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 5 Apr 2016 14:47:10 +0200 Subject: [PATCH 1622/9938] vxlan: move Ethernet initialization to a separate function This will allow to initialize vxlan in ARPHRD_NONE mode based on the passed rtnl attributes. v2: renamed "l2mode" to "ether". Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 1c0fa364323e..6bd5b874ead7 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2404,7 +2404,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) return 0; } -static const struct net_device_ops vxlan_netdev_ops = { +static const struct net_device_ops vxlan_netdev_ether_ops = { .ndo_init = vxlan_init, .ndo_uninit = vxlan_uninit, .ndo_open = vxlan_open, @@ -2458,10 +2458,6 @@ static void vxlan_setup(struct net_device *dev) struct vxlan_dev *vxlan = netdev_priv(dev); unsigned int h; - eth_hw_addr_random(dev); - ether_setup(dev); - - dev->netdev_ops = &vxlan_netdev_ops; dev->destructor = free_netdev; SET_NETDEV_DEVTYPE(dev, &vxlan_type); @@ -2476,8 +2472,7 @@ static void vxlan_setup(struct net_device *dev) dev->hw_features |= NETIF_F_GSO_SOFTWARE; dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; netif_keep_dst(dev); - dev->priv_flags &= ~IFF_TX_SKB_SHARING; - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; + dev->priv_flags |= IFF_NO_QUEUE; INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); @@ -2496,6 +2491,15 @@ static void vxlan_setup(struct net_device *dev) INIT_HLIST_HEAD(&vxlan->fdb_head[h]); } +static void vxlan_ether_setup(struct net_device *dev) +{ + eth_hw_addr_random(dev); + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + dev->netdev_ops = &vxlan_netdev_ether_ops; +} + static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_ID] = { .type = NLA_U32 }, [IFLA_VXLAN_GROUP] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, @@ -2722,6 +2726,8 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, __be16 default_port = vxlan->cfg.dst_port; struct net_device *lowerdev = NULL; + vxlan_ether_setup(dev); + vxlan->net = src_net; dst->remote_vni = conf->vni; -- GitLab From 47e5d1b06305e73afc917f47b65490adb06c7194 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 5 Apr 2016 14:47:11 +0200 Subject: [PATCH 1623/9938] vxlan: move fdb code to common location in vxlan_xmit Handle VXLAN_F_COLLECT_METADATA before VXLAN_F_PROXY. The latter does not make sense with the former, as it needs populated fdb which does not happen in metadata mode. After this cleanup, the fdb code in vxlan_xmit is moved to a common location and can be later skipped for VXLAN-GPE which does not necessarily carry inner Ethernet header. v2: changed commit description to not reference L3 mode Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 6bd5b874ead7..d62eebaa9720 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2106,9 +2106,17 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) info = skb_tunnel_info(skb); skb_reset_mac_header(skb); - eth = eth_hdr(skb); - if ((vxlan->flags & VXLAN_F_PROXY)) { + if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { + if (info && info->mode & IP_TUNNEL_INFO_TX) + vxlan_xmit_one(skb, dev, NULL, false); + else + kfree_skb(skb); + return NETDEV_TX_OK; + } + + if (vxlan->flags & VXLAN_F_PROXY) { + eth = eth_hdr(skb); if (ntohs(eth->h_proto) == ETH_P_ARP) return arp_reduce(dev, skb); #if IS_ENABLED(CONFIG_IPV6) @@ -2123,18 +2131,10 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) return neigh_reduce(dev, skb); } - eth = eth_hdr(skb); #endif } - if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { - if (info && info->mode & IP_TUNNEL_INFO_TX) - vxlan_xmit_one(skb, dev, NULL, false); - else - kfree_skb(skb); - return NETDEV_TX_OK; - } - + eth = eth_hdr(skb); f = vxlan_find_mac(vxlan, eth->h_dest); did_rsc = false; -- GitLab From a6d5bbf34efa8330af7b0b1dba0f38148516ed97 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 5 Apr 2016 14:47:12 +0200 Subject: [PATCH 1624/9938] ip_tunnel: implement __iptunnel_pull_header Allow calling of iptunnel_pull_header without special casing ETH_P_TEB inner protocol. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- include/net/ip_tunnels.h | 11 +++++++++-- net/ipv4/ip_tunnel_core.c | 8 ++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 56050f913339..16435d8b1f93 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -295,8 +295,15 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, return INET_ECN_encapsulate(tos, inner); } -int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto, - bool xnet); +int __iptunnel_pull_header(struct sk_buff *skb, int hdr_len, + __be16 inner_proto, bool raw_proto, bool xnet); + +static inline int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, + __be16 inner_proto, bool xnet) +{ + return __iptunnel_pull_header(skb, hdr_len, inner_proto, false, xnet); +} + void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, u8 proto, u8 tos, u8 ttl, __be16 df, bool xnet); diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index b3ab1205dfdf..43445df61efd 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -86,15 +86,15 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, } EXPORT_SYMBOL_GPL(iptunnel_xmit); -int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto, - bool xnet) +int __iptunnel_pull_header(struct sk_buff *skb, int hdr_len, + __be16 inner_proto, bool raw_proto, bool xnet) { if (unlikely(!pskb_may_pull(skb, hdr_len))) return -ENOMEM; skb_pull_rcsum(skb, hdr_len); - if (inner_proto == htons(ETH_P_TEB)) { + if (!raw_proto && inner_proto == htons(ETH_P_TEB)) { struct ethhdr *eh; if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) @@ -117,7 +117,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto, return iptunnel_pull_offloads(skb); } -EXPORT_SYMBOL_GPL(iptunnel_pull_header); +EXPORT_SYMBOL_GPL(__iptunnel_pull_header); struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md, gfp_t flags) -- GitLab From e1e5314de08ba6003b358125eafc9ad9e75a950c Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 5 Apr 2016 14:47:13 +0200 Subject: [PATCH 1625/9938] vxlan: implement GPE Implement VXLAN-GPE. Only COLLECT_METADATA is supported for now (it is possible to support static configuration, too, if there is demand for it). The GPE header parsing has to be moved before iptunnel_pull_header, as we need to know the protocol. v2: Removed what was called "L2 mode" in v1 of the patchset. Only "L3 mode" (now called "raw mode") is added by this patch. This mode does not allow Ethernet header to be encapsulated in VXLAN-GPE when using ip route to specify the encapsulation, IP header is encapsulated instead. The patch does support Ethernet to be encapsulated, though, using ETH_P_TEB in skb->protocol. This will be utilized by other COLLECT_METADATA users (openvswitch in particular). If there is ever demand for Ethernet encapsulation with VXLAN-GPE using ip route, it's easy to add a new flag switching the interface to "Ethernet mode" (called "L2 mode" in v1 of this patchset). For now, leave this out, it seems we don't need it. Disallowed more flag combinations, especially RCO with GPE. Added comment explaining that GBP and GPE cannot be set together. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 170 +++++++++++++++++++++++++++++++---- include/net/vxlan.h | 68 ++++++++++++++ include/uapi/linux/if_link.h | 1 + 3 files changed, 222 insertions(+), 17 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d62eebaa9720..51cccddfe403 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1192,6 +1192,45 @@ static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed, unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS; } +static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed, + __be32 *protocol, + struct sk_buff *skb, u32 vxflags) +{ + struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed; + + /* Need to have Next Protocol set for interfaces in GPE mode. */ + if (!gpe->np_applied) + return false; + /* "The initial version is 0. If a receiver does not support the + * version indicated it MUST drop the packet. + */ + if (gpe->version != 0) + return false; + /* "When the O bit is set to 1, the packet is an OAM packet and OAM + * processing MUST occur." However, we don't implement OAM + * processing, thus drop the packet. + */ + if (gpe->oam_flag) + return false; + + switch (gpe->next_protocol) { + case VXLAN_GPE_NP_IPV4: + *protocol = htons(ETH_P_IP); + break; + case VXLAN_GPE_NP_IPV6: + *protocol = htons(ETH_P_IPV6); + break; + case VXLAN_GPE_NP_ETHERNET: + *protocol = htons(ETH_P_TEB); + break; + default: + return false; + } + + unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS; + return true; +} + static bool vxlan_set_mac(struct vxlan_dev *vxlan, struct vxlan_sock *vs, struct sk_buff *skb) @@ -1257,9 +1296,11 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) struct vxlanhdr unparsed; struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; + __be32 protocol = htons(ETH_P_TEB); + bool raw_proto = false; void *oiph; - /* Need Vxlan and inner Ethernet header to be present */ + /* Need UDP and VXLAN header to be present */ if (!pskb_may_pull(skb, VXLAN_HLEN)) return 1; @@ -1283,9 +1324,18 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) if (!vxlan) goto drop; - if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB), - !net_eq(vxlan->net, dev_net(vxlan->dev)))) - goto drop; + /* For backwards compatibility, only allow reserved fields to be + * used by VXLAN extensions if explicitly requested. + */ + if (vs->flags & VXLAN_F_GPE) { + if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags)) + goto drop; + raw_proto = true; + } + + if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto, + !net_eq(vxlan->net, dev_net(vxlan->dev)))) + goto drop; if (vxlan_collect_metadata(vs)) { __be32 vni = vxlan_vni(vxlan_hdr(skb)->vx_vni); @@ -1304,14 +1354,14 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) memset(md, 0, sizeof(*md)); } - /* For backwards compatibility, only allow reserved fields to be - * used by VXLAN extensions if explicitly requested. - */ if (vs->flags & VXLAN_F_REMCSUM_RX) if (!vxlan_remcsum(&unparsed, skb, vs->flags)) goto drop; if (vs->flags & VXLAN_F_GBP) vxlan_parse_gbp_hdr(&unparsed, skb, vs->flags, md); + /* Note that GBP and GPE can never be active together. This is + * ensured in vxlan_dev_configure. + */ if (unparsed.vx_flags || unparsed.vx_vni) { /* If there are any unprocessed flags remaining treat @@ -1325,8 +1375,13 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) goto drop; } - if (!vxlan_set_mac(vxlan, vs, skb)) - goto drop; + if (!raw_proto) { + if (!vxlan_set_mac(vxlan, vs, skb)) + goto drop; + } else { + skb->dev = vxlan->dev; + skb->pkt_type = PACKET_HOST; + } oiph = skb_network_header(skb); skb_reset_network_header(skb); @@ -1685,6 +1740,27 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags, gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK); } +static int vxlan_build_gpe_hdr(struct vxlanhdr *vxh, u32 vxflags, + __be16 protocol) +{ + struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vxh; + + gpe->np_applied = 1; + + switch (protocol) { + case htons(ETH_P_IP): + gpe->next_protocol = VXLAN_GPE_NP_IPV4; + return 0; + case htons(ETH_P_IPV6): + gpe->next_protocol = VXLAN_GPE_NP_IPV6; + return 0; + case htons(ETH_P_TEB): + gpe->next_protocol = VXLAN_GPE_NP_ETHERNET; + return 0; + } + return -EPFNOSUPPORT; +} + static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, int iphdr_len, __be32 vni, struct vxlan_metadata *md, u32 vxflags, @@ -1694,6 +1770,7 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, int min_headroom; int err; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; + __be16 inner_protocol = htons(ETH_P_TEB); if ((vxflags & VXLAN_F_REMCSUM_TX) && skb->ip_summed == CHECKSUM_PARTIAL) { @@ -1712,10 +1789,8 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, /* Need space for new headers (invalidates iph ptr) */ err = skb_cow_head(skb, min_headroom); - if (unlikely(err)) { - kfree_skb(skb); - return err; - } + if (unlikely(err)) + goto out_free; skb = vlan_hwaccel_push_inside(skb); if (WARN_ON(!skb)) @@ -1744,9 +1819,19 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, if (vxflags & VXLAN_F_GBP) vxlan_build_gbp_hdr(vxh, vxflags, md); + if (vxflags & VXLAN_F_GPE) { + err = vxlan_build_gpe_hdr(vxh, vxflags, skb->protocol); + if (err < 0) + goto out_free; + inner_protocol = skb->protocol; + } - skb_set_inner_protocol(skb, htons(ETH_P_TEB)); + skb_set_inner_protocol(skb, inner_protocol); return 0; + +out_free: + kfree_skb(skb); + return err; } static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, @@ -2421,6 +2506,17 @@ static const struct net_device_ops vxlan_netdev_ether_ops = { .ndo_fill_metadata_dst = vxlan_fill_metadata_dst, }; +static const struct net_device_ops vxlan_netdev_raw_ops = { + .ndo_init = vxlan_init, + .ndo_uninit = vxlan_uninit, + .ndo_open = vxlan_open, + .ndo_stop = vxlan_stop, + .ndo_start_xmit = vxlan_xmit, + .ndo_get_stats64 = ip_tunnel_get_stats64, + .ndo_change_mtu = vxlan_change_mtu, + .ndo_fill_metadata_dst = vxlan_fill_metadata_dst, +}; + /* Info for udev, that this is a virtual tunnel endpoint */ static struct device_type vxlan_type = { .name = "vxlan", @@ -2500,6 +2596,17 @@ static void vxlan_ether_setup(struct net_device *dev) dev->netdev_ops = &vxlan_netdev_ether_ops; } +static void vxlan_raw_setup(struct net_device *dev) +{ + dev->type = ARPHRD_NONE; + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = ETH_DATA_LEN; + dev->tx_queue_len = 1000; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->netdev_ops = &vxlan_netdev_raw_ops; +} + static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_ID] = { .type = NLA_U32 }, [IFLA_VXLAN_GROUP] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, @@ -2526,6 +2633,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 }, [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 }, [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, }, + [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, }, [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, }; @@ -2726,7 +2834,20 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, __be16 default_port = vxlan->cfg.dst_port; struct net_device *lowerdev = NULL; - vxlan_ether_setup(dev); + if (conf->flags & VXLAN_F_GPE) { + if (conf->flags & ~VXLAN_F_ALLOWED_GPE) + return -EINVAL; + /* For now, allow GPE only together with COLLECT_METADATA. + * This can be relaxed later; in such case, the other side + * of the PtP link will have to be provided. + */ + if (!(conf->flags & VXLAN_F_COLLECT_METADATA)) + return -EINVAL; + + vxlan_raw_setup(dev); + } else { + vxlan_ether_setup(dev); + } vxlan->net = src_net; @@ -2789,8 +2910,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, dev->needed_headroom = needed_headroom; memcpy(&vxlan->cfg, conf, sizeof(*conf)); - if (!vxlan->cfg.dst_port) - vxlan->cfg.dst_port = default_port; + if (!vxlan->cfg.dst_port) { + if (conf->flags & VXLAN_F_GPE) + vxlan->cfg.dst_port = 4790; /* IANA assigned VXLAN-GPE port */ + else + vxlan->cfg.dst_port = default_port; + } vxlan->flags |= conf->flags; if (!vxlan->cfg.age_interval) @@ -2961,6 +3086,9 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, if (data[IFLA_VXLAN_GBP]) conf.flags |= VXLAN_F_GBP; + if (data[IFLA_VXLAN_GPE]) + conf.flags |= VXLAN_F_GPE; + if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL; @@ -2977,6 +3105,10 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, case -EEXIST: pr_info("duplicate VNI %u\n", be32_to_cpu(conf.vni)); break; + + case -EINVAL: + pr_info("unsupported combination of extensions\n"); + break; } return err; @@ -3104,6 +3236,10 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) nla_put_flag(skb, IFLA_VXLAN_GBP)) goto nla_put_failure; + if (vxlan->flags & VXLAN_F_GPE && + nla_put_flag(skb, IFLA_VXLAN_GPE)) + goto nla_put_failure; + if (vxlan->flags & VXLAN_F_REMCSUM_NOPARTIAL && nla_put_flag(skb, IFLA_VXLAN_REMCSUM_NOPARTIAL)) goto nla_put_failure; diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 73ed2e951c02..dcc6f4057115 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -119,6 +119,64 @@ struct vxlanhdr_gbp { #define VXLAN_GBP_POLICY_APPLIED (BIT(3) << 16) #define VXLAN_GBP_ID_MASK (0xFFFF) +/* + * VXLAN Generic Protocol Extension (VXLAN_F_GPE): + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |R|R|Ver|I|P|R|O| Reserved |Next Protocol | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | VXLAN Network Identifier (VNI) | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Ver = Version. Indicates VXLAN GPE protocol version. + * + * P = Next Protocol Bit. The P bit is set to indicate that the + * Next Protocol field is present. + * + * O = OAM Flag Bit. The O bit is set to indicate that the packet + * is an OAM packet. + * + * Next Protocol = This 8 bit field indicates the protocol header + * immediately following the VXLAN GPE header. + * + * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 + */ + +struct vxlanhdr_gpe { +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 oam_flag:1, + reserved_flags1:1, + np_applied:1, + instance_applied:1, + version:2, +reserved_flags2:2; +#elif defined(__BIG_ENDIAN_BITFIELD) + u8 reserved_flags2:2, + version:2, + instance_applied:1, + np_applied:1, + reserved_flags1:1, + oam_flag:1; +#endif + u8 reserved_flags3; + u8 reserved_flags4; + u8 next_protocol; + __be32 vx_vni; +}; + +/* VXLAN-GPE header flags. */ +#define VXLAN_HF_VER cpu_to_be32(BIT(29) | BIT(28)) +#define VXLAN_HF_NP cpu_to_be32(BIT(26)) +#define VXLAN_HF_OAM cpu_to_be32(BIT(24)) + +#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \ + cpu_to_be32(0xff)) + +/* VXLAN-GPE header Next Protocol. */ +#define VXLAN_GPE_NP_IPV4 0x01 +#define VXLAN_GPE_NP_IPV6 0x02 +#define VXLAN_GPE_NP_ETHERNET 0x03 +#define VXLAN_GPE_NP_NSH 0x04 + struct vxlan_metadata { u32 gbp; }; @@ -206,16 +264,26 @@ struct vxlan_dev { #define VXLAN_F_GBP 0x800 #define VXLAN_F_REMCSUM_NOPARTIAL 0x1000 #define VXLAN_F_COLLECT_METADATA 0x2000 +#define VXLAN_F_GPE 0x4000 /* Flags that are used in the receive path. These flags must match in * order for a socket to be shareable */ #define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \ + VXLAN_F_GPE | \ VXLAN_F_UDP_ZERO_CSUM6_RX | \ VXLAN_F_REMCSUM_RX | \ VXLAN_F_REMCSUM_NOPARTIAL | \ VXLAN_F_COLLECT_METADATA) +/* Flags that can be set together with VXLAN_F_GPE. */ +#define VXLAN_F_ALLOWED_GPE (VXLAN_F_GPE | \ + VXLAN_F_IPV6 | \ + VXLAN_F_UDP_ZERO_CSUM_TX | \ + VXLAN_F_UDP_ZERO_CSUM6_TX | \ + VXLAN_F_UDP_ZERO_CSUM6_RX | \ + VXLAN_F_COLLECT_METADATA) + struct net_device *vxlan_dev_create(struct net *net, const char *name, u8 name_assign_type, struct vxlan_config *conf); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index c488066fb53a..9427f17d06d6 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -488,6 +488,7 @@ enum { IFLA_VXLAN_REMCSUM_NOPARTIAL, IFLA_VXLAN_COLLECT_METADATA, IFLA_VXLAN_LABEL, + IFLA_VXLAN_GPE, __IFLA_VXLAN_MAX }; #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) -- GitLab From d5ea45da1f04a3443710306e16db3b3aeae92918 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 3 Feb 2016 09:20:52 +0100 Subject: [PATCH 1626/9938] e1000e: call ndo_stop() instead of dev_close() when running offline selftest Calling dev_close() causes IFF_UP to be cleared which will remove the interfaces routes and some addresses. That's probably not what the user intended when running the offline selftest. Besides this does not happen if the interface is brought down before the test, so the current behaviour is inconsistent. Instead call the net_device_ops ndo_stop function directly and avoid touching IFF_UP at all. Signed-off-by: Stefan Assmann Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/e1000.h | 2 ++ drivers/net/ethernet/intel/e1000e/ethtool.c | 4 ++-- drivers/net/ethernet/intel/e1000e/netdev.c | 12 ++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index 1dc293bad87b..52eb641fc9dc 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -480,6 +480,8 @@ extern const char e1000e_driver_version[]; void e1000e_check_options(struct e1000_adapter *adapter); void e1000e_set_ethtool_ops(struct net_device *netdev); +int e1000e_open(struct net_device *netdev); +int e1000e_close(struct net_device *netdev); void e1000e_up(struct e1000_adapter *adapter); void e1000e_down(struct e1000_adapter *adapter, bool reset); void e1000e_reinit_locked(struct e1000_adapter *adapter); diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 6cab1f30d41e..1e3973aa707c 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -1816,7 +1816,7 @@ static void e1000_diag_test(struct net_device *netdev, if (if_running) /* indicate we're in test mode */ - dev_close(netdev); + e1000e_close(netdev); if (e1000_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1849,7 +1849,7 @@ static void e1000_diag_test(struct net_device *netdev, clear_bit(__E1000_TESTING, &adapter->state); if (if_running) - dev_open(netdev); + e1000e_open(netdev); } else { /* Online tests */ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 9b4ec13d9161..a7f16c35ebcd 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4495,7 +4495,7 @@ static int e1000_test_msi(struct e1000_adapter *adapter) } /** - * e1000_open - Called when a network interface is made active + * e1000e_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure @@ -4506,7 +4506,7 @@ static int e1000_test_msi(struct e1000_adapter *adapter) * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/ -static int e1000_open(struct net_device *netdev) +int e1000e_open(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -4604,7 +4604,7 @@ static int e1000_open(struct net_device *netdev) } /** - * e1000_close - Disables a network interface + * e1000e_close - Disables a network interface * @netdev: network interface device structure * * Returns 0, this is not allowed to fail @@ -4614,7 +4614,7 @@ static int e1000_open(struct net_device *netdev) * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ -static int e1000_close(struct net_device *netdev) +int e1000e_close(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct pci_dev *pdev = adapter->pdev; @@ -6920,8 +6920,8 @@ static int e1000_set_features(struct net_device *netdev, } static const struct net_device_ops e1000e_netdev_ops = { - .ndo_open = e1000_open, - .ndo_stop = e1000_close, + .ndo_open = e1000e_open, + .ndo_stop = e1000e_close, .ndo_start_xmit = e1000_xmit_frame, .ndo_get_stats64 = e1000e_get_stats64, .ndo_set_rx_mode = e1000e_set_rx_mode, -- GitLab From b98ff151b659b08f71cc2e21ce7044da6662b314 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:00 +0200 Subject: [PATCH 1627/9938] mlxsw: reg: Add Port Prio To Buffer register When packets ingress the switch they are assigned a switch priority number that dictates the packet's priority group (PG) buffer in the port's headroom buffer. Add the Port Prio To Buffer (PPTB) register, which configures the switch priority to PG mapping. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index ffe4c0305733..0995beee6c91 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2340,6 +2340,87 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port) mlxsw_reg_ppcnt_prio_tc_set(payload, 0); } +/* PPTB - Port Prio To Buffer Register + * ----------------------------------- + * Configures the switch priority to buffer table. + */ +#define MLXSW_REG_PPTB_ID 0x500B +#define MLXSW_REG_PPTB_LEN 0x0C + +static const struct mlxsw_reg_info mlxsw_reg_pptb = { + .id = MLXSW_REG_PPTB_ID, + .len = MLXSW_REG_PPTB_LEN, +}; + +enum { + MLXSW_REG_PPTB_MM_UM, + MLXSW_REG_PPTB_MM_UNICAST, + MLXSW_REG_PPTB_MM_MULTICAST, +}; + +/* reg_pptb_mm + * Mapping mode. + * 0 - Map both unicast and multicast packets to the same buffer. + * 1 - Map only unicast packets. + * 2 - Map only multicast packets. + * Access: Index + * + * Note: SwitchX-2 only supports the first option. + */ +MLXSW_ITEM32(reg, pptb, mm, 0x00, 28, 2); + +/* reg_pptb_local_port + * Local port number. + * Access: Index + */ +MLXSW_ITEM32(reg, pptb, local_port, 0x00, 16, 8); + +/* reg_pptb_um + * Enables the update of the untagged_buf field. + * Access: RW + */ +MLXSW_ITEM32(reg, pptb, um, 0x00, 8, 1); + +/* reg_pptb_pm + * Enables the update of the prio_to_buff field. + * Bit is a flag for updating the mapping for switch priority . + * Access: RW + */ +MLXSW_ITEM32(reg, pptb, pm, 0x00, 0, 8); + +/* reg_pptb_prio_to_buff + * Mapping of switch priority to one of the allocated receive port + * buffers. + * Access: RW + */ +MLXSW_ITEM_BIT_ARRAY(reg, pptb, prio_to_buff, 0x04, 0x04, 4); + +/* reg_pptb_pm_msb + * Enables the update of the prio_to_buff field. + * Bit is a flag for updating the mapping for switch priority . + * Access: RW + */ +MLXSW_ITEM32(reg, pptb, pm_msb, 0x08, 24, 8); + +/* reg_pptb_untagged_buff + * Mapping of untagged frames to one of the allocated receive port buffers. + * Access: RW + * + * Note: In SwitchX-2 this field must be mapped to buffer 8. Reserved for + * Spectrum, as it maps untagged packets based on the default switch priority. + */ +MLXSW_ITEM32(reg, pptb, untagged_buff, 0x08, 0, 4); + +#define MLXSW_REG_PPTB_ALL_PRIO 0xFF + +static inline void mlxsw_reg_pptb_pack(char *payload, u8 local_port) +{ + MLXSW_REG_ZERO(pptb, payload); + mlxsw_reg_pptb_mm_set(payload, MLXSW_REG_PPTB_MM_UM); + mlxsw_reg_pptb_local_port_set(payload, local_port); + mlxsw_reg_pptb_pm_set(payload, MLXSW_REG_PPTB_ALL_PRIO); +} + /* PBMC - Port Buffer Management Control Register * ---------------------------------------------- * The PBMC register configures and retrieves the port packet buffer @@ -3295,6 +3376,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "PAOS"; case MLXSW_REG_PPCNT_ID: return "PPCNT"; + case MLXSW_REG_PPTB_ID: + return "PPTB"; case MLXSW_REG_PBMC_ID: return "PBMC"; case MLXSW_REG_PSPA_ID: -- GitLab From dd6cb0f9fdb31c4bf89e482031cd098bf5f706d4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:01 +0200 Subject: [PATCH 1628/9938] mlxsw: spectrum: Map all switch priorities to priority group 0 During transmission, the skb's priority is used to map the skb to a traffic class, where the idea is to group priorities with similar characteristics (e.g. lossy, lossless) to the same traffic class. By default, all priorities are mapped to traffic class 0. In the device, we model the skb's priority as the switch priority, which is assigned to a packet according to its PCP value and ingress port (untagged packets are assigned the port's default switch priority - 0). At ingress, the packet is directed to a priority group (PG) buffer in the port's headroom buffer according to the packet's switch priority and switch priority to buffer mapping. While it's possible to configure the egress mapping between skb's priority (switch priority) and traffic class, there is no mechanism to configure the ingress mapping to a PG. In order to keep things simple and since grouping certain priorities into a traffic class at egress also implies they should be grouped the same at ingress, treat a PG as the ingress counterpart of an egress traffic class. Having established the above, during initialization map all the switch priorities to PG0 in accordance with the Linux defaults for traffic class mapping. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../mellanox/mlxsw/spectrum_buffers.c | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index d59195e3f7fb..c3a275bb46cf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -34,6 +34,7 @@ #include #include +#include #include "spectrum.h" #include "core.h" @@ -82,6 +83,28 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) MLXSW_REG(pbmc), pbmc_pl); } +static int mlxsw_sp_port_pb_prio_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + char pptb_pl[MLXSW_REG_PPTB_LEN]; + int i; + + mlxsw_reg_pptb_pack(pptb_pl, mlxsw_sp_port->local_port); + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) + mlxsw_reg_pptb_prio_to_buff_set(pptb_pl, i, 0); + return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pptb), + pptb_pl); +} + +static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + int err; + + err = mlxsw_sp_port_pb_init(mlxsw_sp_port); + if (err) + return err; + return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port); +} + #define MLXSW_SP_SB_BYTES_PER_CELL 96 struct mlxsw_sp_sb_pool { @@ -410,7 +433,7 @@ int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port) { int err; - err = mlxsw_sp_port_pb_init(mlxsw_sp_port); + err = mlxsw_sp_port_headroom_init(mlxsw_sp_port); if (err) return err; err = mlxsw_sp_port_sb_cms_init(mlxsw_sp_port); -- GitLab From 1a1984490f5c123ee62394bc435a2c09db15cc18 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:02 +0200 Subject: [PATCH 1629/9938] mlxsw: spectrum: Add bytes to cells helper Buffers in the switch store packets in units called buffer cells. Add a helper to convert from bytes to cells, so that the actual number of cells required (result is round up) is returned. Also, drop the SB (shared buffer) acronym from the BYTES_PER_CELL macro, as this unit is also used in the ports' buffers and not only the switch's shared buffer. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.h | 4 ++ .../mellanox/mlxsw/spectrum_buffers.c | 64 +++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index d58ab0cd9507..84dddd47f1b0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -62,6 +62,10 @@ #define MLXSW_SP_PORT_BASE_SPEED 25000 /* Mb/s */ +#define MLXSW_SP_BYTES_PER_CELL 96 + +#define MLXSW_SP_BYTES_TO_CELLS(b) DIV_ROUND_UP(b, MLXSW_SP_BYTES_PER_CELL) + struct mlxsw_sp_port; struct mlxsw_sp_upper { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index c3a275bb46cf..dadb6e1ccf82 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -105,8 +105,6 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port); } -#define MLXSW_SP_SB_BYTES_PER_CELL 96 - struct mlxsw_sp_sb_pool { u8 pool; enum mlxsw_reg_sbpr_dir dir; @@ -115,11 +113,9 @@ struct mlxsw_sp_sb_pool { }; #define MLXSW_SP_SB_POOL_INGRESS_SIZE \ - ((15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) / \ - MLXSW_SP_SB_BYTES_PER_CELL) + (15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) #define MLXSW_SP_SB_POOL_EGRESS_SIZE \ - ((14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) / \ - MLXSW_SP_SB_BYTES_PER_CELL) + (14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) #define MLXSW_SP_SB_POOL(_pool, _dir, _mode, _size) \ { \ @@ -138,14 +134,14 @@ struct mlxsw_sp_sb_pool { MLXSW_REG_SBPR_MODE_DYNAMIC, _size) static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = { - MLXSW_SP_SB_POOL_INGRESS(0, MLXSW_SP_SB_POOL_INGRESS_SIZE), + MLXSW_SP_SB_POOL_INGRESS(0, MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_INGRESS_SIZE)), MLXSW_SP_SB_POOL_INGRESS(1, 0), MLXSW_SP_SB_POOL_INGRESS(2, 0), MLXSW_SP_SB_POOL_INGRESS(3, 0), - MLXSW_SP_SB_POOL_EGRESS(0, MLXSW_SP_SB_POOL_EGRESS_SIZE), + MLXSW_SP_SB_POOL_EGRESS(0, MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), MLXSW_SP_SB_POOL_EGRESS(1, 0), MLXSW_SP_SB_POOL_EGRESS(2, 0), - MLXSW_SP_SB_POOL_EGRESS(2, MLXSW_SP_SB_POOL_EGRESS_SIZE), + MLXSW_SP_SB_POOL_EGRESS(2, MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), }; #define MLXSW_SP_SB_POOLS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools) @@ -201,7 +197,7 @@ struct mlxsw_sp_sb_cm { MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, 104, 2, 3) static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = { - MLXSW_SP_SB_CM_INGRESS(0, 10000 / MLXSW_SP_SB_BYTES_PER_CELL, 8), + MLXSW_SP_SB_CM_INGRESS(0, MLXSW_SP_BYTES_TO_CELLS(10000), 8), MLXSW_SP_SB_CM_INGRESS(1, 0, 0), MLXSW_SP_SB_CM_INGRESS(2, 0, 0), MLXSW_SP_SB_CM_INGRESS(3, 0, 0), @@ -209,15 +205,15 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = { MLXSW_SP_SB_CM_INGRESS(5, 0, 0), MLXSW_SP_SB_CM_INGRESS(6, 0, 0), MLXSW_SP_SB_CM_INGRESS(7, 0, 0), - MLXSW_SP_SB_CM_INGRESS(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff), - MLXSW_SP_SB_CM_EGRESS(0, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), - MLXSW_SP_SB_CM_EGRESS(1, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), - MLXSW_SP_SB_CM_EGRESS(2, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), - MLXSW_SP_SB_CM_EGRESS(3, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), - MLXSW_SP_SB_CM_EGRESS(4, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), - MLXSW_SP_SB_CM_EGRESS(5, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), - MLXSW_SP_SB_CM_EGRESS(6, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), - MLXSW_SP_SB_CM_EGRESS(7, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_INGRESS(9, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff), + MLXSW_SP_SB_CM_EGRESS(0, MLXSW_SP_BYTES_TO_CELLS(1500), 9), + MLXSW_SP_SB_CM_EGRESS(1, MLXSW_SP_BYTES_TO_CELLS(1500), 9), + MLXSW_SP_SB_CM_EGRESS(2, MLXSW_SP_BYTES_TO_CELLS(1500), 9), + MLXSW_SP_SB_CM_EGRESS(3, MLXSW_SP_BYTES_TO_CELLS(1500), 9), + MLXSW_SP_SB_CM_EGRESS(4, MLXSW_SP_BYTES_TO_CELLS(1500), 9), + MLXSW_SP_SB_CM_EGRESS(5, MLXSW_SP_BYTES_TO_CELLS(1500), 9), + MLXSW_SP_SB_CM_EGRESS(6, MLXSW_SP_BYTES_TO_CELLS(1500), 9), + MLXSW_SP_SB_CM_EGRESS(7, MLXSW_SP_BYTES_TO_CELLS(1500), 9), MLXSW_SP_SB_CM_EGRESS(8, 0, 0), MLXSW_SP_SB_CM_EGRESS(9, 0, 0), MLXSW_SP_SB_CM_EGRESS(10, 0, 0), @@ -376,21 +372,21 @@ struct mlxsw_sp_sb_mm { } static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = { - MLXSW_SP_SB_MM(0, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(1, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(2, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(3, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(4, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(5, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(6, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(7, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(8, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(10, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(11, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(12, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(13, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), - MLXSW_SP_SB_MM(14, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(0, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(1, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(2, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(3, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(4, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(5, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(6, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(7, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(8, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(9, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(10, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(11, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(12, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(13, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(14, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), }; #define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms) -- GitLab From ff6551ec0c2748a31087878f00bcaf6db2f82116 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:03 +0200 Subject: [PATCH 1630/9938] mlxsw: spectrum: Correctly configure headroom size When packets ingress the switch they are assigned a switch priority and directed to the corresponding priority group (PG) buffer in the port's headroom buffer. Since we now map all switch priorities to priority group 0 (PG0) by default, there is no need to allocate the other priority groups during initialization. The only exception is PG9, which is used for control traffic. At minimum, the PG should be able to store the currently classified packet (pipeline latency isn't 0) and also the packets arriving during the classification time. However, an incoming packet will not be buffered if there is no available MTU-sized buffer space for storing it. The buffer needed to accommodate for pipeline latency is variable and needs to take into account both the current link speed and current latency of the pipeline, which is time-dependent. Testing showed that setting the PG's size to twice the current MTU is optimal. Since PG9 is used strictly for control packets and not subject to flow control, we are not going to resize it according to user configuration, so we simply set it according to worst case scenario, which is twice the maximum MTU. In any case, later patches in the series will allow a user to direct lossless flows to other PGs than PG0 and set their size to accommodate for round-trip propagation delay. The above change also requires us to resize the PG buffer whenever the port's MTU is changed. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 25 ++++++++++++++++++- .../mellanox/mlxsw/spectrum_buffers.c | 19 +++++++------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index cb5f36e497e9..4576d59a98a2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -449,16 +449,39 @@ static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p) return 0; } +static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, + int mtu) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u16 pg_size = 2 * MLXSW_SP_BYTES_TO_CELLS(mtu); + char pbmc_pl[MLXSW_REG_PBMC_LEN]; + int err; + + mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0, 0); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); + if (err) + return err; + mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, 0, pg_size); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); +} + static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); int err; - err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu); + err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu); if (err) return err; + err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu); + if (err) + goto err_port_mtu_set; dev->mtu = mtu; return 0; + +err_port_mtu_set: + mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu); + return err; } static struct rtnl_link_stats64 * diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index dadb6e1ccf82..e7a5b73188f1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "spectrum.h" #include "core.h" @@ -53,15 +54,15 @@ struct mlxsw_sp_pb { } static const struct mlxsw_sp_pb mlxsw_sp_pbs[] = { - MLXSW_SP_PB(0, 208), - MLXSW_SP_PB(1, 208), - MLXSW_SP_PB(2, 208), - MLXSW_SP_PB(3, 208), - MLXSW_SP_PB(4, 208), - MLXSW_SP_PB(5, 208), - MLXSW_SP_PB(6, 208), - MLXSW_SP_PB(7, 208), - MLXSW_SP_PB(9, 208), + MLXSW_SP_PB(0, 2 * MLXSW_SP_BYTES_TO_CELLS(ETH_FRAME_LEN)), + MLXSW_SP_PB(1, 0), + MLXSW_SP_PB(2, 0), + MLXSW_SP_PB(3, 0), + MLXSW_SP_PB(4, 0), + MLXSW_SP_PB(5, 0), + MLXSW_SP_PB(6, 0), + MLXSW_SP_PB(7, 0), + MLXSW_SP_PB(9, 2 * MLXSW_SP_BYTES_TO_CELLS(MLXSW_PORT_MAX_MTU)), }; #define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs) -- GitLab From 7ad7cd6113bacace67c55cadef6459eb0e74403d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:04 +0200 Subject: [PATCH 1631/9938] mlxsw: reg: Use correct PBMC register length The last field of the PBMC register is at offset 0x64 and its size is 0x8, so the correct register's length is 0x6C bytes. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 0995beee6c91..f08a17fdd4c3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2427,7 +2427,7 @@ static inline void mlxsw_reg_pptb_pack(char *payload, u8 local_port) * allocation for different Prios, and the Pause threshold management. */ #define MLXSW_REG_PBMC_ID 0x500C -#define MLXSW_REG_PBMC_LEN 0x68 +#define MLXSW_REG_PBMC_LEN 0x6C static const struct mlxsw_reg_info mlxsw_reg_pbmc = { .id = MLXSW_REG_PBMC_ID, -- GitLab From d6b7c13b018f1785743150f079638bb3ed69fff1 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:05 +0200 Subject: [PATCH 1632/9938] mlxsw: spectrum: Set port's shared buffer size to 0 In addition to the priority group (PG) buffers in the headroom, the device enables the allocation of headroom shared buffer, which can be shared between different PGs. However, we are not going to use the headroom shared buffer and instead allow the user to use its size for PGs or the switch's shared buffer. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index f08a17fdd4c3..370914e607e0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2455,6 +2455,8 @@ MLXSW_ITEM32(reg, pbmc, xoff_timer_value, 0x04, 16, 16); */ MLXSW_ITEM32(reg, pbmc, xoff_refresh, 0x04, 0, 16); +#define MLXSW_REG_PBMC_PORT_SHARED_BUF_IDX 11 + /* reg_pbmc_buf_lossy * The field indicates if the buffer is lossy. * 0 - Lossless diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index e7a5b73188f1..97c8d537be5b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -80,6 +80,8 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) pb = &mlxsw_sp_pbs[i]; mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pb->index, pb->size); } + mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, + MLXSW_REG_PBMC_PORT_SHARED_BUF_IDX, 0); return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); } -- GitLab From b9b7cee405797cc395f699d8dee4747b96b1e0a8 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:06 +0200 Subject: [PATCH 1633/9938] mlxsw: reg: Add QoS ETS Element Configuration register We are going to introduce support for DCB, so we need to be able to configure the traffic selection algorithm (TSA) used by each traffic class (TC), as well as the bandwidth percentage allocated to each TC in case of ETS. Add the QoS ETS Element Configuration register, which controls the above parameters. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 127 ++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 370914e607e0..bc08f8bdca7a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1805,6 +1805,131 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port, } } +/* QEEC - QoS ETS Element Configuration Register + * --------------------------------------------- + * Configures the ETS elements. + */ +#define MLXSW_REG_QEEC_ID 0x400D +#define MLXSW_REG_QEEC_LEN 0x1C + +static const struct mlxsw_reg_info mlxsw_reg_qeec = { + .id = MLXSW_REG_QEEC_ID, + .len = MLXSW_REG_QEEC_LEN, +}; + +/* reg_qeec_local_port + * Local port number. + * Access: Index + * + * Note: CPU port is supported. + */ +MLXSW_ITEM32(reg, qeec, local_port, 0x00, 16, 8); + +enum mlxsw_reg_qeec_hr { + MLXSW_REG_QEEC_HIERARCY_PORT, + MLXSW_REG_QEEC_HIERARCY_GROUP, + MLXSW_REG_QEEC_HIERARCY_SUBGROUP, + MLXSW_REG_QEEC_HIERARCY_TC, +}; + +/* reg_qeec_element_hierarchy + * 0 - Port + * 1 - Group + * 2 - Subgroup + * 3 - Traffic Class + * Access: Index + */ +MLXSW_ITEM32(reg, qeec, element_hierarchy, 0x04, 16, 4); + +/* reg_qeec_element_index + * The index of the element in the hierarchy. + * Access: Index + */ +MLXSW_ITEM32(reg, qeec, element_index, 0x04, 0, 8); + +/* reg_qeec_next_element_index + * The index of the next (lower) element in the hierarchy. + * Access: RW + * + * Note: Reserved for element_hierarchy 0. + */ +MLXSW_ITEM32(reg, qeec, next_element_index, 0x08, 0, 8); + +enum { + MLXSW_REG_QEEC_BYTES_MODE, + MLXSW_REG_QEEC_PACKETS_MODE, +}; + +/* reg_qeec_pb + * Packets or bytes mode. + * 0 - Bytes mode + * 1 - Packets mode + * Access: RW + * + * Note: Used for max shaper configuration. For Spectrum, packets mode + * is supported only for traffic classes of CPU port. + */ +MLXSW_ITEM32(reg, qeec, pb, 0x0C, 28, 1); + +/* reg_qeec_mase + * Max shaper configuration enable. Enables configuration of the max + * shaper on this ETS element. + * 0 - Disable + * 1 - Enable + * Access: RW + */ +MLXSW_ITEM32(reg, qeec, mase, 0x10, 31, 1); + +/* A large max rate will disable the max shaper. */ +#define MLXSW_REG_QEEC_MAS_DIS 200000000 /* Kbps */ + +/* reg_qeec_max_shaper_rate + * Max shaper information rate. + * For CPU port, can only be configured for port hierarchy. + * When in bytes mode, value is specified in units of 1000bps. + * Access: RW + */ +MLXSW_ITEM32(reg, qeec, max_shaper_rate, 0x10, 0, 28); + +/* reg_qeec_de + * DWRR configuration enable. Enables configuration of the dwrr and + * dwrr_weight. + * 0 - Disable + * 1 - Enable + * Access: RW + */ +MLXSW_ITEM32(reg, qeec, de, 0x18, 31, 1); + +/* reg_qeec_dwrr + * Transmission selection algorithm to use on the link going down from + * the ETS element. + * 0 - Strict priority + * 1 - DWRR + * Access: RW + */ +MLXSW_ITEM32(reg, qeec, dwrr, 0x18, 15, 1); + +/* reg_qeec_dwrr_weight + * DWRR weight on the link going down from the ETS element. The + * percentage of bandwidth guaranteed to an ETS element within + * its hierarchy. The sum of all weights across all ETS elements + * within one hierarchy should be equal to 100. Reserved when + * transmission selection algorithm is strict priority. + * Access: RW + */ +MLXSW_ITEM32(reg, qeec, dwrr_weight, 0x18, 0, 8); + +static inline void mlxsw_reg_qeec_pack(char *payload, u8 local_port, + enum mlxsw_reg_qeec_hr hr, u8 index, + u8 next_index) +{ + MLXSW_REG_ZERO(qeec, payload); + mlxsw_reg_qeec_local_port_set(payload, local_port); + mlxsw_reg_qeec_element_hierarchy_set(payload, hr); + mlxsw_reg_qeec_element_index_set(payload, index); + mlxsw_reg_qeec_next_element_index_set(payload, next_index); +} + /* PMLP - Ports Module to Local Port Register * ------------------------------------------ * Configures the assignment of modules to local ports. @@ -3366,6 +3491,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SFMR"; case MLXSW_REG_SPVMLR_ID: return "SPVMLR"; + case MLXSW_REG_QEEC_ID: + return "QEEC"; case MLXSW_REG_PMLP_ID: return "PMLP"; case MLXSW_REG_PMTU_ID: -- GitLab From 2c63a555e8495f3d6db443ca73094a6a3508df4a Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:07 +0200 Subject: [PATCH 1634/9938] mlxsw: reg: Add QoS Switch Traffic Class Table register As part of DCB ops we'll have to configure the priority to traffic class mapping of a port. Add the QoS Switch Traffic Class Table (QTCT) register, which configures the mapping between the packet switch priority and traffic class on the transmit port. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 55 +++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index bc08f8bdca7a..2e58c41e90d4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1805,6 +1805,59 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port, } } +/* QTCT - QoS Switch Traffic Class Table + * ------------------------------------- + * Configures the mapping between the packet switch priority and the + * traffic class on the transmit port. + */ +#define MLXSW_REG_QTCT_ID 0x400A +#define MLXSW_REG_QTCT_LEN 0x08 + +static const struct mlxsw_reg_info mlxsw_reg_qtct = { + .id = MLXSW_REG_QTCT_ID, + .len = MLXSW_REG_QTCT_LEN, +}; + +/* reg_qtct_local_port + * Local port number. + * Access: Index + * + * Note: CPU port is not supported. + */ +MLXSW_ITEM32(reg, qtct, local_port, 0x00, 16, 8); + +/* reg_qtct_sub_port + * Virtual port within the physical port. + * Should be set to 0 when virtual ports are not enabled on the port. + * Access: Index + */ +MLXSW_ITEM32(reg, qtct, sub_port, 0x00, 8, 8); + +/* reg_qtct_switch_prio + * Switch priority. + * Access: Index + */ +MLXSW_ITEM32(reg, qtct, switch_prio, 0x00, 0, 4); + +/* reg_qtct_tclass + * Traffic class. + * Default values: + * switch_prio 0 : tclass 1 + * switch_prio 1 : tclass 0 + * switch_prio i : tclass i, for i > 1 + * Access: RW + */ +MLXSW_ITEM32(reg, qtct, tclass, 0x04, 0, 4); + +static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port, + u8 switch_prio, u8 tclass) +{ + MLXSW_REG_ZERO(qtct, payload); + mlxsw_reg_qtct_local_port_set(payload, local_port); + mlxsw_reg_qtct_switch_prio_set(payload, switch_prio); + mlxsw_reg_qtct_tclass_set(payload, tclass); +} + /* QEEC - QoS ETS Element Configuration Register * --------------------------------------------- * Configures the ETS elements. @@ -3491,6 +3544,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SFMR"; case MLXSW_REG_SPVMLR_ID: return "SPVMLR"; + case MLXSW_REG_QTCT_ID: + return "QTCT"; case MLXSW_REG_QEEC_ID: return "QEEC"; case MLXSW_REG_PMLP_ID: -- GitLab From 90183b980d0af77df2369dee924fff13c792dcc5 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:08 +0200 Subject: [PATCH 1635/9938] mlxsw: spectrum: Initialize egress scheduling Before introducing support for DCB ops we should first make sure we initialize the relevant parts in the device correctly. Specifically, the egress scheduling. The device supports a superset of the 802.1Qaz standard with 4 hierarchy levels that can be linked to each other in multiple ways and with different transmission selection algorithms (TSA) employed between them. However, since we only intend to support the 802.1Qaz standard we flatten the hierarchies and let the user configure via DCB ops the TSA and max rate shaper at the subgroup hierarchy (see figure below) and the mapping between switch priority to traffic class. By default, all switch priorities are mapped to traffic class 0, strict priority is employed and max shaper is disabled. Default configuration: switch priority 0 ... switch priority 7 + + | | +----------------------------------+ | +--v--+ +-----+ Traffic Class | | | | Hierarchy | TC0 | ... | TC7 | | | | | +--+--+ +--+--+ | | +--v--+ +--v--+ Subgroup | SG0 | | SG7 | Hierarchy | | | | +-----+ +-----+ | TSA | | TSA | +-----+ ... +-----+ | MAX | | MAX | +--+--+ +--+--+ | | +---------------+----------------+ | +--v--+ Group | | Hierarchy | GR0 | | | +--+--+ | +--v--+ Port | | Hierarchy | PR0 | | | +-----+ Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 4576d59a98a2..1243c7404356 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1464,6 +1465,108 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); } +static int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_qeec_hr hr, u8 index, + u8 next_index, bool dwrr, u8 dwrr_weight) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char qeec_pl[MLXSW_REG_QEEC_LEN]; + + mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index, + next_index); + mlxsw_reg_qeec_de_set(qeec_pl, true); + mlxsw_reg_qeec_dwrr_set(qeec_pl, dwrr); + mlxsw_reg_qeec_dwrr_weight_set(qeec_pl, dwrr_weight); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl); +} + +static int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_qeec_hr hr, u8 index, + u8 next_index, u32 maxrate) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char qeec_pl[MLXSW_REG_QEEC_LEN]; + + mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index, + next_index); + mlxsw_reg_qeec_mase_set(qeec_pl, true); + mlxsw_reg_qeec_max_shaper_rate_set(qeec_pl, maxrate); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl); +} + +static int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, + u8 switch_prio, u8 tclass) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char qtct_pl[MLXSW_REG_QTCT_LEN]; + + mlxsw_reg_qtct_pack(qtct_pl, mlxsw_sp_port->local_port, switch_prio, + tclass); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qtct), qtct_pl); +} + +static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + int err, i; + + /* Setup the elements hierarcy, so that each TC is linked to + * one subgroup, which are all member in the same group. + */ + err = mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_GROUP, 0, 0, false, + 0); + if (err) + return err; + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_SUBGROUP, i, + 0, false, 0); + if (err) + return err; + } + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_TC, i, i, + false, 0); + if (err) + return err; + } + + /* Make sure the max shaper is disabled in all hierarcies that + * support it. + */ + err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_PORT, 0, 0, + MLXSW_REG_QEEC_MAS_DIS); + if (err) + return err; + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_SUBGROUP, + i, 0, + MLXSW_REG_QEEC_MAS_DIS); + if (err) + return err; + } + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_TC, + i, i, + MLXSW_REG_QEEC_MAS_DIS); + if (err) + return err; + } + + /* Map all priorities to traffic class 0. */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, 0); + if (err) + return err; + } + + return 0; +} + static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, bool split, u8 module, u8 width) { @@ -1571,6 +1674,13 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_port_buffers_init; } + err = mlxsw_sp_port_ets_init(mlxsw_sp_port); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize ETS\n", + mlxsw_sp_port->local_port); + goto err_port_ets_init; + } + mlxsw_sp_port_switchdev_init(mlxsw_sp_port); err = register_netdev(dev); if (err) { @@ -1591,6 +1701,7 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err_port_vlan_init: unregister_netdev(dev); err_register_netdev: +err_port_ets_init: err_port_buffers_init: err_port_admin_status_set: err_port_mtu_set: -- GitLab From f00817df2b428ec13711bd27729f992b8c3af054 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:09 +0200 Subject: [PATCH 1636/9938] mlxsw: spectrum: Introduce support for Data Center Bridging (DCB) Introduce basic infrastructure for DCB and add the missing ops in following patches. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Kconfig | 8 +++ drivers/net/ethernet/mellanox/mlxsw/Makefile | 1 + .../net/ethernet/mellanox/mlxsw/spectrum.c | 10 +++ .../net/ethernet/mellanox/mlxsw/spectrum.h | 17 +++++ .../ethernet/mellanox/mlxsw/spectrum_dcb.c | 65 +++++++++++++++++++ 5 files changed, 101 insertions(+) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index 2ad7f67854d5..5989f7cb5462 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -50,3 +50,11 @@ config MLXSW_SPECTRUM To compile this driver as a module, choose M here: the module will be called mlxsw_spectrum. + +config MLXSW_SPECTRUM_DCB + bool "Data Center Bridging (DCB) support" + depends on MLXSW_SPECTRUM && DCB + default y + ---help--- + Say Y here if you want to use Data Center Bridging (DCB) in the + driver. diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index 584cac444852..9b5ebf84c051 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -8,3 +8,4 @@ mlxsw_switchx2-objs := switchx2.o obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ spectrum_switchdev.o +mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 1243c7404356..baaa9ea52035 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1681,6 +1681,14 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_port_ets_init; } + /* ETS and buffers must be initialized before DCB. */ + err = mlxsw_sp_port_dcb_init(mlxsw_sp_port); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize DCB\n", + mlxsw_sp_port->local_port); + goto err_port_dcb_init; + } + mlxsw_sp_port_switchdev_init(mlxsw_sp_port); err = register_netdev(dev); if (err) { @@ -1701,6 +1709,7 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err_port_vlan_init: unregister_netdev(dev); err_register_netdev: +err_port_dcb_init: err_port_ets_init: err_port_buffers_init: err_port_admin_status_set: @@ -1771,6 +1780,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) devlink_port = &mlxsw_sp_port->devlink_port; devlink_port_type_clear(devlink_port); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ + mlxsw_sp_port_dcb_fini(mlxsw_sp_port); devlink_port_unregister(devlink_port); mlxsw_sp_port_vports_fini(mlxsw_sp_port); mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 84dddd47f1b0..1f50af8e25c2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -270,4 +270,21 @@ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid, void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port); int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid); +#ifdef CONFIG_MLXSW_SPECTRUM_DCB + +int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port); +void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port); + +#else + +static inline int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + return 0; +} + +static inline void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port) +{} + +#endif + #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c new file mode 100644 index 000000000000..631e9803978d --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c @@ -0,0 +1,65 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Ido Schimmel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "spectrum.h" + +static u8 mlxsw_sp_dcbnl_getdcbx(struct net_device __always_unused *dev) +{ + return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE; +} + +static u8 mlxsw_sp_dcbnl_setdcbx(struct net_device __always_unused *dev, + u8 mode) +{ + return (mode != (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE)) ? 1 : 0; +} + +static const struct dcbnl_rtnl_ops mlxsw_sp_dcbnl_ops = { + .getdcbx = mlxsw_sp_dcbnl_getdcbx, + .setdcbx = mlxsw_sp_dcbnl_setdcbx, +}; + +int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + mlxsw_sp_port->dev->dcbnl_ops = &mlxsw_sp_dcbnl_ops; + + return 0; +} + +void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port) +{ +} -- GitLab From 8e8dfe9fdf063cd61f35ed82f5be463791a613a5 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:10 +0200 Subject: [PATCH 1637/9938] mlxsw: spectrum: Add IEEE 802.1Qaz ETS support Implement the appropriate DCB ops and allow a user to configure: * Priority to traffic class (TC) mapping with a total of 8 supported TCs * Transmission selection algorithm (TSA) for each TC and the corresponding weights in case of weighted round robin (WRR) As previously explained, we treat the priority group (PG) buffer in the port's headroom as the ingress counterpart of the egress TC. Therefore, when a certain priority to TC mapping is configured, we also configure the port's headroom buffer. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 53 +++- .../net/ethernet/mellanox/mlxsw/spectrum.h | 11 + .../ethernet/mellanox/mlxsw/spectrum_dcb.c | 229 ++++++++++++++++++ 3 files changed, 283 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index baaa9ea52035..1498e6a25035 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -450,22 +450,55 @@ static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p) return 0; } -static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, - int mtu) +static void mlxsw_sp_pg_buf_pack(char *pbmc_pl, int pg_index, int mtu) { - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; u16 pg_size = 2 * MLXSW_SP_BYTES_TO_CELLS(mtu); + + mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pg_index, pg_size); +} + +int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, + u8 *prio_tc) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char pbmc_pl[MLXSW_REG_PBMC_LEN]; - int err; + int i, j, err; mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0, 0); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); if (err) return err; - mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, 0, pg_size); + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + bool configure = false; + + for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) { + if (prio_tc[j] == i) { + configure = true; + break; + } + } + + if (!configure) + continue; + mlxsw_sp_pg_buf_pack(pbmc_pl, i, mtu); + } + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); } +static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, + int mtu) +{ + u8 def_prio_tc[IEEE_8021QAZ_MAX_TCS] = {0}; + bool dcb_en = !!mlxsw_sp_port->dcb.ets; + u8 *prio_tc; + + prio_tc = dcb_en ? mlxsw_sp_port->dcb.ets->prio_tc : def_prio_tc; + + return __mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, prio_tc); +} + static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); @@ -1465,9 +1498,9 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); } -static int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, - enum mlxsw_reg_qeec_hr hr, u8 index, - u8 next_index, bool dwrr, u8 dwrr_weight) +int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index, + bool dwrr, u8 dwrr_weight) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char qeec_pl[MLXSW_REG_QEEC_LEN]; @@ -1494,8 +1527,8 @@ static int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl); } -static int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, - u8 switch_prio, u8 tclass) +int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, + u8 switch_prio, u8 tclass) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char qtct_pl[MLXSW_REG_QTCT_LEN]; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 1f50af8e25c2..ef02081c4fbf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -170,6 +171,9 @@ struct mlxsw_sp_port { struct mlxsw_sp_vfid *vfid; u16 vid; } vport; + struct { + struct ieee_ets *ets; + } dcb; /* 802.1Q bridge VLANs */ unsigned long *active_vlans; unsigned long *untagged_vlans; @@ -269,6 +273,13 @@ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid, bool set, bool only_uc); void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port); int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid); +int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index, + bool dwrr, u8 dwrr_weight); +int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, + u8 switch_prio, u8 tclass); +int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, + u8 *prio_tc); #ifdef CONFIG_MLXSW_SPECTRUM_DCB diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c index 631e9803978d..aa5b73a20685 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c @@ -33,9 +33,11 @@ */ #include +#include #include #include "spectrum.h" +#include "reg.h" static u8 mlxsw_sp_dcbnl_getdcbx(struct net_device __always_unused *dev) { @@ -48,13 +50,239 @@ static u8 mlxsw_sp_dcbnl_setdcbx(struct net_device __always_unused *dev, return (mode != (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE)) ? 1 : 0; } +static int mlxsw_sp_dcbnl_ieee_getets(struct net_device *dev, + struct ieee_ets *ets) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + + memcpy(ets, mlxsw_sp_port->dcb.ets, sizeof(*ets)); + + return 0; +} + +static int mlxsw_sp_port_ets_validate(struct mlxsw_sp_port *mlxsw_sp_port, + struct ieee_ets *ets) +{ + struct net_device *dev = mlxsw_sp_port->dev; + bool has_ets_tc = false; + int i, tx_bw_sum = 0; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + switch (ets->tc_tsa[i]) { + case IEEE_8021QAZ_TSA_STRICT: + break; + case IEEE_8021QAZ_TSA_ETS: + has_ets_tc = true; + tx_bw_sum += ets->tc_tx_bw[i]; + break; + default: + netdev_err(dev, "Only strict priority and ETS are supported\n"); + return -EINVAL; + } + + if (ets->prio_tc[i] >= IEEE_8021QAZ_MAX_TCS) { + netdev_err(dev, "Invalid TC\n"); + return -EINVAL; + } + } + + if (has_ets_tc && tx_bw_sum != 100) { + netdev_err(dev, "Total ETS bandwidth should equal 100\n"); + return -EINVAL; + } + + return 0; +} + +static int mlxsw_sp_port_pg_prio_map(struct mlxsw_sp_port *mlxsw_sp_port, + u8 *prio_tc) +{ + char pptb_pl[MLXSW_REG_PPTB_LEN]; + int i; + + mlxsw_reg_pptb_pack(pptb_pl, mlxsw_sp_port->local_port); + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) + mlxsw_reg_pptb_prio_to_buff_set(pptb_pl, i, prio_tc[i]); + return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pptb), + pptb_pl); +} + +static bool mlxsw_sp_ets_has_pg(u8 *prio_tc, u8 pg) +{ + int i; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) + if (prio_tc[i] == pg) + return true; + return false; +} + +static int mlxsw_sp_port_pg_destroy(struct mlxsw_sp_port *mlxsw_sp_port, + u8 *old_prio_tc, u8 *new_prio_tc) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char pbmc_pl[MLXSW_REG_PBMC_LEN]; + int err, i; + + mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0, 0); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); + if (err) + return err; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + u8 pg = old_prio_tc[i]; + + if (!mlxsw_sp_ets_has_pg(new_prio_tc, pg)) + mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pg, 0); + } + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); +} + +static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, + struct ieee_ets *ets) +{ + struct ieee_ets *my_ets = mlxsw_sp_port->dcb.ets; + struct net_device *dev = mlxsw_sp_port->dev; + int err; + + /* Create the required PGs, but don't destroy existing ones, as + * traffic is still directed to them. + */ + err = __mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, + ets->prio_tc); + if (err) { + netdev_err(dev, "Failed to configure port's headroom\n"); + return err; + } + + err = mlxsw_sp_port_pg_prio_map(mlxsw_sp_port, ets->prio_tc); + if (err) { + netdev_err(dev, "Failed to set PG-priority mapping\n"); + goto err_port_prio_pg_map; + } + + err = mlxsw_sp_port_pg_destroy(mlxsw_sp_port, my_ets->prio_tc, + ets->prio_tc); + if (err) + netdev_warn(dev, "Failed to remove ununsed PGs\n"); + + return 0; + +err_port_prio_pg_map: + mlxsw_sp_port_pg_destroy(mlxsw_sp_port, ets->prio_tc, my_ets->prio_tc); + return err; +} + +static int __mlxsw_sp_dcbnl_ieee_setets(struct mlxsw_sp_port *mlxsw_sp_port, + struct ieee_ets *ets) +{ + struct ieee_ets *my_ets = mlxsw_sp_port->dcb.ets; + struct net_device *dev = mlxsw_sp_port->dev; + int i, err; + + /* Egress configuration. */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + bool dwrr = ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS; + u8 weight = ets->tc_tx_bw[i]; + + err = mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_SUBGROUP, i, + 0, dwrr, weight); + if (err) { + netdev_err(dev, "Failed to link subgroup ETS element %d to group\n", + i); + goto err_port_ets_set; + } + } + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, + ets->prio_tc[i]); + if (err) { + netdev_err(dev, "Failed to map prio %d to TC %d\n", i, + ets->prio_tc[i]); + goto err_port_prio_tc_set; + } + } + + /* Ingress configuration. */ + err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, ets); + if (err) + goto err_port_headroom_set; + + return 0; + +err_port_headroom_set: + i = IEEE_8021QAZ_MAX_TCS; +err_port_prio_tc_set: + for (i--; i >= 0; i--) + mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, my_ets->prio_tc[i]); + i = IEEE_8021QAZ_MAX_TCS; +err_port_ets_set: + for (i--; i >= 0; i--) { + bool dwrr = my_ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS; + u8 weight = my_ets->tc_tx_bw[i]; + + err = mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_SUBGROUP, i, + 0, dwrr, weight); + } + return err; +} + +static int mlxsw_sp_dcbnl_ieee_setets(struct net_device *dev, + struct ieee_ets *ets) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err; + + err = mlxsw_sp_port_ets_validate(mlxsw_sp_port, ets); + if (err) + return err; + + err = __mlxsw_sp_dcbnl_ieee_setets(mlxsw_sp_port, ets); + if (err) + return err; + + memcpy(mlxsw_sp_port->dcb.ets, ets, sizeof(*ets)); + + return 0; +} + static const struct dcbnl_rtnl_ops mlxsw_sp_dcbnl_ops = { + .ieee_getets = mlxsw_sp_dcbnl_ieee_getets, + .ieee_setets = mlxsw_sp_dcbnl_ieee_setets, + .getdcbx = mlxsw_sp_dcbnl_getdcbx, .setdcbx = mlxsw_sp_dcbnl_setdcbx, }; +static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + mlxsw_sp_port->dcb.ets = kzalloc(sizeof(*mlxsw_sp_port->dcb.ets), + GFP_KERNEL); + if (!mlxsw_sp_port->dcb.ets) + return -ENOMEM; + + mlxsw_sp_port->dcb.ets->ets_cap = IEEE_8021QAZ_MAX_TCS; + + return 0; +} + +static void mlxsw_sp_port_ets_fini(struct mlxsw_sp_port *mlxsw_sp_port) +{ + kfree(mlxsw_sp_port->dcb.ets); +} + int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) { + int err; + + err = mlxsw_sp_port_ets_init(mlxsw_sp_port); + if (err) + return err; + mlxsw_sp_port->dev->dcbnl_ops = &mlxsw_sp_dcbnl_ops; return 0; @@ -62,4 +290,5 @@ int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port) { + mlxsw_sp_port_ets_fini(mlxsw_sp_port); } -- GitLab From cc7cf5175807daa9cb51f6e0eb034f60ced6b251 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:11 +0200 Subject: [PATCH 1638/9938] mlxsw: spectrum: Allow setting maximum rate for a TC Allow a user to set maximum rate for a particular TC using DCB ops. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 6 +- .../net/ethernet/mellanox/mlxsw/spectrum.h | 4 ++ .../ethernet/mellanox/mlxsw/spectrum_dcb.c | 70 +++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 1498e6a25035..5f4d44e14bf4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1513,9 +1513,9 @@ int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl); } -static int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, - enum mlxsw_reg_qeec_hr hr, u8 index, - u8 next_index, u32 maxrate) +int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_qeec_hr hr, u8 index, + u8 next_index, u32 maxrate) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char qeec_pl[MLXSW_REG_QEEC_LEN]; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index ef02081c4fbf..9e1e4fe32d35 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -173,6 +173,7 @@ struct mlxsw_sp_port { } vport; struct { struct ieee_ets *ets; + struct ieee_maxrate *maxrate; } dcb; /* 802.1Q bridge VLANs */ unsigned long *active_vlans; @@ -280,6 +281,9 @@ int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 switch_prio, u8 tclass); int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, u8 *prio_tc); +int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_qeec_hr hr, u8 index, + u8 next_index, u32 maxrate); #ifdef CONFIG_MLXSW_SPECTRUM_DCB diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c index aa5b73a20685..257e2d427cab 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c @@ -250,9 +250,51 @@ static int mlxsw_sp_dcbnl_ieee_setets(struct net_device *dev, return 0; } +static int mlxsw_sp_dcbnl_ieee_getmaxrate(struct net_device *dev, + struct ieee_maxrate *maxrate) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + + memcpy(maxrate, mlxsw_sp_port->dcb.maxrate, sizeof(*maxrate)); + + return 0; +} + +static int mlxsw_sp_dcbnl_ieee_setmaxrate(struct net_device *dev, + struct ieee_maxrate *maxrate) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct ieee_maxrate *my_maxrate = mlxsw_sp_port->dcb.maxrate; + int err, i; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_SUBGROUP, + i, 0, + maxrate->tc_maxrate[i]); + if (err) { + netdev_err(dev, "Failed to set maxrate for TC %d\n", i); + goto err_port_ets_maxrate_set; + } + } + + memcpy(mlxsw_sp_port->dcb.maxrate, maxrate, sizeof(*maxrate)); + + return 0; + +err_port_ets_maxrate_set: + for (i--; i >= 0; i--) + mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_SUBGROUP, + i, 0, my_maxrate->tc_maxrate[i]); + return err; +} + static const struct dcbnl_rtnl_ops mlxsw_sp_dcbnl_ops = { .ieee_getets = mlxsw_sp_dcbnl_ieee_getets, .ieee_setets = mlxsw_sp_dcbnl_ieee_setets, + .ieee_getmaxrate = mlxsw_sp_dcbnl_ieee_getmaxrate, + .ieee_setmaxrate = mlxsw_sp_dcbnl_ieee_setmaxrate, .getdcbx = mlxsw_sp_dcbnl_getdcbx, .setdcbx = mlxsw_sp_dcbnl_setdcbx, @@ -275,6 +317,26 @@ static void mlxsw_sp_port_ets_fini(struct mlxsw_sp_port *mlxsw_sp_port) kfree(mlxsw_sp_port->dcb.ets); } +static int mlxsw_sp_port_maxrate_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + int i; + + mlxsw_sp_port->dcb.maxrate = kmalloc(sizeof(*mlxsw_sp_port->dcb.maxrate), + GFP_KERNEL); + if (!mlxsw_sp_port->dcb.maxrate) + return -ENOMEM; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) + mlxsw_sp_port->dcb.maxrate->tc_maxrate[i] = MLXSW_REG_QEEC_MAS_DIS; + + return 0; +} + +static void mlxsw_sp_port_maxrate_fini(struct mlxsw_sp_port *mlxsw_sp_port) +{ + kfree(mlxsw_sp_port->dcb.maxrate); +} + int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) { int err; @@ -282,13 +344,21 @@ int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) err = mlxsw_sp_port_ets_init(mlxsw_sp_port); if (err) return err; + err = mlxsw_sp_port_maxrate_init(mlxsw_sp_port); + if (err) + goto err_port_maxrate_init; mlxsw_sp_port->dev->dcbnl_ops = &mlxsw_sp_dcbnl_ops; return 0; + +err_port_maxrate_init: + mlxsw_sp_port_ets_fini(mlxsw_sp_port); + return err; } void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port) { + mlxsw_sp_port_maxrate_fini(mlxsw_sp_port); mlxsw_sp_port_ets_fini(mlxsw_sp_port); } -- GitLab From 6f253d8381e9e7b8a254e7384b7d32ea5784e6e8 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:12 +0200 Subject: [PATCH 1639/9938] mlxsw: reg: Add Port Flow Control Configuration register Add the Port Flow Control Configuration (PFCC) register, which configures both flow control and Priority-based Flow Control (PFC). Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 131 ++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 2e58c41e90d4..b83514aeeb0f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2319,6 +2319,135 @@ static inline void mlxsw_reg_paos_pack(char *payload, u8 local_port, mlxsw_reg_paos_e_set(payload, 1); } +/* PFCC - Ports Flow Control Configuration Register + * ------------------------------------------------ + * Configures and retrieves the per port flow control configuration. + */ +#define MLXSW_REG_PFCC_ID 0x5007 +#define MLXSW_REG_PFCC_LEN 0x20 + +static const struct mlxsw_reg_info mlxsw_reg_pfcc = { + .id = MLXSW_REG_PFCC_ID, + .len = MLXSW_REG_PFCC_LEN, +}; + +/* reg_pfcc_local_port + * Local port number. + * Access: Index + */ +MLXSW_ITEM32(reg, pfcc, local_port, 0x00, 16, 8); + +/* reg_pfcc_pnat + * Port number access type. Determines the way local_port is interpreted: + * 0 - Local port number. + * 1 - IB / label port number. + * Access: Index + */ +MLXSW_ITEM32(reg, pfcc, pnat, 0x00, 14, 2); + +/* reg_pfcc_shl_cap + * Send to higher layers capabilities: + * 0 - No capability of sending Pause and PFC frames to higher layers. + * 1 - Device has capability of sending Pause and PFC frames to higher + * layers. + * Access: RO + */ +MLXSW_ITEM32(reg, pfcc, shl_cap, 0x00, 1, 1); + +/* reg_pfcc_shl_opr + * Send to higher layers operation: + * 0 - Pause and PFC frames are handled by the port (default). + * 1 - Pause and PFC frames are handled by the port and also sent to + * higher layers. Only valid if shl_cap = 1. + * Access: RW + */ +MLXSW_ITEM32(reg, pfcc, shl_opr, 0x00, 0, 1); + +/* reg_pfcc_ppan + * Pause policy auto negotiation. + * 0 - Disabled. Generate / ignore Pause frames based on pptx / pprtx. + * 1 - Enabled. When auto-negotiation is performed, set the Pause policy + * based on the auto-negotiation resolution. + * Access: RW + * + * Note: The auto-negotiation advertisement is set according to pptx and + * pprtx. When PFC is set on Tx / Rx, ppan must be set to 0. + */ +MLXSW_ITEM32(reg, pfcc, ppan, 0x04, 28, 4); + +/* reg_pfcc_prio_mask_tx + * Bit per priority indicating if Tx flow control policy should be + * updated based on bit pfctx. + * Access: WO + */ +MLXSW_ITEM32(reg, pfcc, prio_mask_tx, 0x04, 16, 8); + +/* reg_pfcc_prio_mask_rx + * Bit per priority indicating if Rx flow control policy should be + * updated based on bit pfcrx. + * Access: WO + */ +MLXSW_ITEM32(reg, pfcc, prio_mask_rx, 0x04, 0, 8); + +/* reg_pfcc_pptx + * Admin Pause policy on Tx. + * 0 - Never generate Pause frames (default). + * 1 - Generate Pause frames according to Rx buffer threshold. + * Access: RW + */ +MLXSW_ITEM32(reg, pfcc, pptx, 0x08, 31, 1); + +/* reg_pfcc_aptx + * Active (operational) Pause policy on Tx. + * 0 - Never generate Pause frames. + * 1 - Generate Pause frames according to Rx buffer threshold. + * Access: RO + */ +MLXSW_ITEM32(reg, pfcc, aptx, 0x08, 30, 1); + +/* reg_pfcc_pfctx + * Priority based flow control policy on Tx[7:0]. Per-priority bit mask: + * 0 - Never generate priority Pause frames on the specified priority + * (default). + * 1 - Generate priority Pause frames according to Rx buffer threshold on + * the specified priority. + * Access: RW + * + * Note: pfctx and pptx must be mutually exclusive. + */ +MLXSW_ITEM32(reg, pfcc, pfctx, 0x08, 16, 8); + +/* reg_pfcc_pprx + * Admin Pause policy on Rx. + * 0 - Ignore received Pause frames (default). + * 1 - Respect received Pause frames. + * Access: RW + */ +MLXSW_ITEM32(reg, pfcc, pprx, 0x0C, 31, 1); + +/* reg_pfcc_aprx + * Active (operational) Pause policy on Rx. + * 0 - Ignore received Pause frames. + * 1 - Respect received Pause frames. + * Access: RO + */ +MLXSW_ITEM32(reg, pfcc, aprx, 0x0C, 30, 1); + +/* reg_pfcc_pfcrx + * Priority based flow control policy on Rx[7:0]. Per-priority bit mask: + * 0 - Ignore incoming priority Pause frames on the specified priority + * (default). + * 1 - Respect incoming priority Pause frames on the specified priority. + * Access: RW + */ +MLXSW_ITEM32(reg, pfcc, pfcrx, 0x0C, 16, 8); + +static inline void mlxsw_reg_pfcc_pack(char *payload, u8 local_port) +{ + MLXSW_REG_ZERO(pfcc, payload); + mlxsw_reg_pfcc_local_port_set(payload, local_port); +} + /* PPCNT - Ports Performance Counters Register * ------------------------------------------- * The PPCNT register retrieves per port performance counters. @@ -3558,6 +3687,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "PPAD"; case MLXSW_REG_PAOS_ID: return "PAOS"; + case MLXSW_REG_PFCC_ID: + return "PFCC"; case MLXSW_REG_PPCNT_ID: return "PPCNT"; case MLXSW_REG_PPTB_ID: -- GitLab From 155f9de2e09547ed510b86a4b463c2980e7df46a Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:13 +0200 Subject: [PATCH 1640/9938] mlxsw: reg: Add lossless settings for PBMC register When configuring PAUSE frames and PFC we'll need to configure the Xon/Xoff threshold for the priority group (PG) buffers. Add the Xon/Xoff threshold fields to the PBMC register so that we can configure these when needed. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index b83514aeeb0f..bcd38ffd0d41 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2788,6 +2788,30 @@ MLXSW_ITEM32_INDEXED(reg, pbmc, buf_epsb, 0x0C, 24, 1, 0x08, 0x00, false); */ MLXSW_ITEM32_INDEXED(reg, pbmc, buf_size, 0x0C, 0, 16, 0x08, 0x00, false); +/* reg_pbmc_buf_xoff_threshold + * Once the amount of data in the buffer goes above this value, device + * starts sending PFC frames for all priorities associated with the + * buffer. Units are represented in cells. Reserved in case of lossy + * buffer. + * Access: RW + * + * Note: In Spectrum, reserved for buffer[9]. + */ +MLXSW_ITEM32_INDEXED(reg, pbmc, buf_xoff_threshold, 0x0C, 16, 16, + 0x08, 0x04, false); + +/* reg_pbmc_buf_xon_threshold + * When the amount of data in the buffer goes below this value, device + * stops sending PFC frames for the priorities associated with the + * buffer. Units are represented in cells. Reserved in case of lossy + * buffer. + * Access: RW + * + * Note: In Spectrum, reserved for buffer[9]. + */ +MLXSW_ITEM32_INDEXED(reg, pbmc, buf_xon_threshold, 0x0C, 0, 16, + 0x08, 0x04, false); + static inline void mlxsw_reg_pbmc_pack(char *payload, u8 local_port, u16 xoff_timer_value, u16 xoff_refresh) { @@ -2806,6 +2830,17 @@ static inline void mlxsw_reg_pbmc_lossy_buffer_pack(char *payload, mlxsw_reg_pbmc_buf_size_set(payload, buf_index, size); } +static inline void mlxsw_reg_pbmc_lossless_buffer_pack(char *payload, + int buf_index, u16 size, + u16 threshold) +{ + mlxsw_reg_pbmc_buf_lossy_set(payload, buf_index, 0); + mlxsw_reg_pbmc_buf_epsb_set(payload, buf_index, 0); + mlxsw_reg_pbmc_buf_size_set(payload, buf_index, size); + mlxsw_reg_pbmc_buf_xoff_threshold_set(payload, buf_index, threshold); + mlxsw_reg_pbmc_buf_xon_threshold_set(payload, buf_index, threshold); +} + /* PSPA - Port Switch Partition Allocation * --------------------------------------- * Controls the association of a port with a switch partition and enables -- GitLab From 9f7ec052b75e1fd8a4cc876349a665f5b76669d5 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:14 +0200 Subject: [PATCH 1641/9938] mlxsw: spectrum: Add support for PAUSE frames When a packet ingress the switch it's placed in its assigned priority group (PG) buffer in the port's headroom buffer while it goes through the switch's pipeline. After going through the pipeline - which determines its egress port(s) and traffic class - it's moved to the switch's shared buffer awaiting transmission. However, some packets are not eligible to enter the shared buffer due to exceeded quotas or insufficient space. Marking their associated PGs as lossless will cause the packets to accumulate in the PG buffer. Another reason for packets accumulation are complicated pipelines (e.g. involving a lot of ACLs). To prevent packets from being dropped a user can enable PAUSE frames on the port. This will mark all the active PGs as lossless and set their size according to the maximum delay, as it's not configured by user. +----------------+ + | | | | | | | | | | | | | | | | | | Delay | | | | | | | | | | | | | | | Xon/Xoff threshold +----------------+ + | | | | | | 2 * MTU | | | +----------------+ + The delay (612 [Cells]) was calculated according to worst-case scenario involving maximum MTU and 100m cables. After marking the PGs as lossless the device is configured to respect incoming PAUSE frames (Rx PAUSE) and generate PAUSE frames (Tx PAUSE) according to user's settings. Whenever the port's headroom configuration changes we take into account the PAUSE configuration, so that we correctly set the PG's type (lossy / lossless), size and threshold. This can happen when: a) The port's MTU changes, as it directly affects the PG's size. b) A PG is created following user configuration, by binding a priority to it. Note that the relevant SUPPORTED flags were already mistakenly set by the driver before this commit. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 85 +++++++++++++++++-- .../net/ethernet/mellanox/mlxsw/spectrum.h | 17 +++- .../ethernet/mellanox/mlxsw/spectrum_dcb.c | 3 +- 3 files changed, 95 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 5f4d44e14bf4..086682e51c24 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -450,15 +450,23 @@ static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p) return 0; } -static void mlxsw_sp_pg_buf_pack(char *pbmc_pl, int pg_index, int mtu) +static void mlxsw_sp_pg_buf_pack(char *pbmc_pl, int pg_index, int mtu, + bool pause_en) { u16 pg_size = 2 * MLXSW_SP_BYTES_TO_CELLS(mtu); - mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pg_index, pg_size); + if (pause_en) { + u16 pg_pause_size = pg_size + MLXSW_SP_PAUSE_DELAY; + + mlxsw_reg_pbmc_lossless_buffer_pack(pbmc_pl, pg_index, + pg_pause_size, pg_size); + } else { + mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pg_index, pg_size); + } } int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, - u8 *prio_tc) + u8 *prio_tc, bool pause_en) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char pbmc_pl[MLXSW_REG_PBMC_LEN]; @@ -481,14 +489,14 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, if (!configure) continue; - mlxsw_sp_pg_buf_pack(pbmc_pl, i, mtu); + mlxsw_sp_pg_buf_pack(pbmc_pl, i, mtu, pause_en); } return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); } static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, - int mtu) + int mtu, bool pause_en) { u8 def_prio_tc[IEEE_8021QAZ_MAX_TCS] = {0}; bool dcb_en = !!mlxsw_sp_port->dcb.ets; @@ -496,15 +504,17 @@ static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, prio_tc = dcb_en ? mlxsw_sp_port->dcb.ets->prio_tc : def_prio_tc; - return __mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, prio_tc); + return __mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, prio_tc, + pause_en); } static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + bool pause_en = mlxsw_sp_port_is_pause_en(mlxsw_sp_port); int err; - err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu); + err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, pause_en); if (err) return err; err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu); @@ -514,7 +524,7 @@ static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) return 0; err_port_mtu_set: - mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu); + mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en); return err; } @@ -993,6 +1003,63 @@ static void mlxsw_sp_port_get_drvinfo(struct net_device *dev, sizeof(drvinfo->bus_info)); } +static void mlxsw_sp_port_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + + pause->rx_pause = mlxsw_sp_port->link.rx_pause; + pause->tx_pause = mlxsw_sp_port->link.tx_pause; +} + +static int mlxsw_sp_port_pause_set(struct mlxsw_sp_port *mlxsw_sp_port, + struct ethtool_pauseparam *pause) +{ + char pfcc_pl[MLXSW_REG_PFCC_LEN]; + + mlxsw_reg_pfcc_pack(pfcc_pl, mlxsw_sp_port->local_port); + mlxsw_reg_pfcc_pprx_set(pfcc_pl, pause->rx_pause); + mlxsw_reg_pfcc_pptx_set(pfcc_pl, pause->tx_pause); + + return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pfcc), + pfcc_pl); +} + +static int mlxsw_sp_port_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + bool pause_en = pause->tx_pause || pause->rx_pause; + int err; + + if (pause->autoneg) { + netdev_err(dev, "PAUSE frames autonegotiation isn't supported\n"); + return -EINVAL; + } + + err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en); + if (err) { + netdev_err(dev, "Failed to configure port's headroom\n"); + return err; + } + + err = mlxsw_sp_port_pause_set(mlxsw_sp_port, pause); + if (err) { + netdev_err(dev, "Failed to set PAUSE parameters\n"); + goto err_port_pause_configure; + } + + mlxsw_sp_port->link.rx_pause = pause->rx_pause; + mlxsw_sp_port->link.tx_pause = pause->tx_pause; + + return 0; + +err_port_pause_configure: + pause_en = mlxsw_sp_port_is_pause_en(mlxsw_sp_port); + mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en); + return err; +} + struct mlxsw_sp_port_hw_stats { char str[ETH_GSTRING_LEN]; u64 (*getter)(char *payload); @@ -1476,6 +1543,8 @@ static int mlxsw_sp_port_set_settings(struct net_device *dev, static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { .get_drvinfo = mlxsw_sp_port_get_drvinfo, .get_link = ethtool_op_get_link, + .get_pauseparam = mlxsw_sp_port_get_pauseparam, + .set_pauseparam = mlxsw_sp_port_set_pauseparam, .get_strings = mlxsw_sp_port_get_strings, .set_phys_id = mlxsw_sp_port_set_phys_id, .get_ethtool_stats = mlxsw_sp_port_get_stats, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 9e1e4fe32d35..f4b53dd34f22 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -67,6 +67,11 @@ #define MLXSW_SP_BYTES_TO_CELLS(b) DIV_ROUND_UP(b, MLXSW_SP_BYTES_PER_CELL) +/* Maximum delay buffer needed in case of PAUSE frames, in cells. + * Assumes 100m cable and maximum MTU. + */ +#define MLXSW_SP_PAUSE_DELAY 612 + struct mlxsw_sp_port; struct mlxsw_sp_upper { @@ -171,6 +176,10 @@ struct mlxsw_sp_port { struct mlxsw_sp_vfid *vfid; u16 vid; } vport; + struct { + u8 tx_pause:1, + rx_pause:1; + } link; struct { struct ieee_ets *ets; struct ieee_maxrate *maxrate; @@ -183,6 +192,12 @@ struct mlxsw_sp_port { struct devlink_port devlink_port; }; +static inline bool +mlxsw_sp_port_is_pause_en(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + return mlxsw_sp_port->link.tx_pause || mlxsw_sp_port->link.rx_pause; +} + static inline struct mlxsw_sp_port * mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id, u8 port_index) { @@ -280,7 +295,7 @@ int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 switch_prio, u8 tclass); int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, - u8 *prio_tc); + u8 *prio_tc, bool pause_en); int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index, u32 maxrate); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c index 257e2d427cab..8786424f6191 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c @@ -142,6 +142,7 @@ static int mlxsw_sp_port_pg_destroy(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, struct ieee_ets *ets) { + bool pause_en = mlxsw_sp_port_is_pause_en(mlxsw_sp_port); struct ieee_ets *my_ets = mlxsw_sp_port->dcb.ets; struct net_device *dev = mlxsw_sp_port->dev; int err; @@ -150,7 +151,7 @@ static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, * traffic is still directed to them. */ err = __mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, - ets->prio_tc); + ets->prio_tc, pause_en); if (err) { netdev_err(dev, "Failed to configure port's headroom\n"); return err; -- GitLab From 34dba0a59d072201171be1aeb9e52d1148d7c365 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:15 +0200 Subject: [PATCH 1642/9938] mlxsw: reg: Introduce per priority counters We are going to add support for PFC as part of DCB ops, which requires us to report the number of PFC frames sent and received per priority. Add per priority counters in order to report number of PFC frames sent and received per priority. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 62 ++++++++++++++++++- .../net/ethernet/mellanox/mlxsw/spectrum.c | 3 +- .../net/ethernet/mellanox/mlxsw/switchx2.c | 3 +- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index bcd38ffd0d41..84aacb36c12a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2487,6 +2487,11 @@ MLXSW_ITEM32(reg, ppcnt, local_port, 0x00, 16, 8); */ MLXSW_ITEM32(reg, ppcnt, pnat, 0x00, 14, 2); +enum mlxsw_reg_ppcnt_grp { + MLXSW_REG_PPCNT_IEEE_8023_CNT = 0x0, + MLXSW_REG_PPCNT_PRIO_CNT = 0x10, +}; + /* reg_ppcnt_grp * Performance counter group. * Group 63 indicates all groups. Only valid on Set() operation with @@ -2522,6 +2527,8 @@ MLXSW_ITEM32(reg, ppcnt, clr, 0x04, 31, 1); */ MLXSW_ITEM32(reg, ppcnt, prio_tc, 0x04, 0, 5); +/* Ethernet IEEE 802.3 Counter Group */ + /* reg_ppcnt_a_frames_transmitted_ok * Access: RO */ @@ -2636,15 +2643,64 @@ MLXSW_ITEM64(reg, ppcnt, a_pause_mac_ctrl_frames_received, MLXSW_ITEM64(reg, ppcnt, a_pause_mac_ctrl_frames_transmitted, 0x08 + 0x90, 0, 64); -static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port) +/* Ethernet Per Priority Group Counters */ + +/* reg_ppcnt_rx_octets + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, rx_octets, 0x08 + 0x00, 0, 64); + +/* reg_ppcnt_rx_frames + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, rx_frames, 0x08 + 0x20, 0, 64); + +/* reg_ppcnt_tx_octets + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, tx_octets, 0x08 + 0x28, 0, 64); + +/* reg_ppcnt_tx_frames + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, tx_frames, 0x08 + 0x48, 0, 64); + +/* reg_ppcnt_rx_pause + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, rx_pause, 0x08 + 0x50, 0, 64); + +/* reg_ppcnt_rx_pause_duration + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, rx_pause_duration, 0x08 + 0x58, 0, 64); + +/* reg_ppcnt_tx_pause + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, tx_pause, 0x08 + 0x60, 0, 64); + +/* reg_ppcnt_tx_pause_duration + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, tx_pause_duration, 0x08 + 0x68, 0, 64); + +/* reg_ppcnt_rx_pause_transition + * Access: RO + */ +MLXSW_ITEM64(reg, ppcnt, tx_pause_transition, 0x08 + 0x70, 0, 64); + +static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port, + enum mlxsw_reg_ppcnt_grp grp, + u8 prio_tc) { MLXSW_REG_ZERO(ppcnt, payload); mlxsw_reg_ppcnt_swid_set(payload, 0); mlxsw_reg_ppcnt_local_port_set(payload, local_port); mlxsw_reg_ppcnt_pnat_set(payload, 0); - mlxsw_reg_ppcnt_grp_set(payload, 0); + mlxsw_reg_ppcnt_grp_set(payload, grp); mlxsw_reg_ppcnt_clr_set(payload, 0); - mlxsw_reg_ppcnt_prio_tc_set(payload, 0); + mlxsw_reg_ppcnt_prio_tc_set(payload, prio_tc); } /* PPTB - Port Prio To Buffer Register diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 086682e51c24..36a94a94a420 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1195,7 +1195,8 @@ static void mlxsw_sp_port_get_stats(struct net_device *dev, int i; int err; - mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port); + mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port, + MLXSW_REG_PPCNT_IEEE_8023_CNT, 0); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ppcnt), ppcnt_pl); for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) data[i] = !err ? mlxsw_sp_port_hw_stats[i].getter(ppcnt_pl) : 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 7a60a26759b6..c49447f31acc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -518,7 +518,8 @@ static void mlxsw_sx_port_get_stats(struct net_device *dev, int i; int err; - mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sx_port->local_port); + mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sx_port->local_port, + MLXSW_REG_PPCNT_IEEE_8023_CNT, 0); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ppcnt), ppcnt_pl); for (i = 0; i < MLXSW_SX_PORT_HW_STATS_LEN; i++) data[i] = !err ? mlxsw_sx_port_hw_stats[i].getter(ppcnt_pl) : 0; -- GitLab From d81a6bdb87ce75337b453169ee39cdccb3286ddf Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Apr 2016 17:10:16 +0200 Subject: [PATCH 1643/9938] mlxsw: spectrum: Add IEEE 802.1Qbb PFC support Implement the appropriate DCB ops and allow a user to configure certain traffic classes as lossless. The operation configures PFC for both the egress (respecting PFC frames) and ingress (sending PFC frames) parts of the port. At egress, when a PFC frame is received for a PFC enabled priority, then all the priorities mapped to the same TC are stopped. At ingress, the priority group (PG) buffers to which the enabled PFC priorities are mapped are configured to be lossless. PFC frames will be transmitted when the Xoff threshold is crossed. The user-supplied delay parameter is used to determine the PG's size according to the following formula: PG_SIZE = PG_SIZE_LOSSY + delay * CELL_FACTOR + MTU In the worst case scenario the delay will be made up of packets that are all of size CELL_SIZE + 1, which means each packet will require almost twice its true size when buffered in the switch. We therefore multiply this value by the "cell factor", which is close to 2. Another MTU is added in case the transmitting host already started transmitting a maximum length frame when the PFC packet was received. As with PAUSE enabled ports, when the port's MTU is changed both the PGs' size and threshold are adjusted accordingly. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 10 ++ .../net/ethernet/mellanox/mlxsw/spectrum.c | 30 +++-- .../net/ethernet/mellanox/mlxsw/spectrum.h | 12 +- .../ethernet/mellanox/mlxsw/spectrum_dcb.c | 117 +++++++++++++++++- 4 files changed, 158 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 84aacb36c12a..28f5b99e585a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2442,6 +2442,16 @@ MLXSW_ITEM32(reg, pfcc, aprx, 0x0C, 30, 1); */ MLXSW_ITEM32(reg, pfcc, pfcrx, 0x0C, 16, 8); +#define MLXSW_REG_PFCC_ALL_PRIO 0xFF + +static inline void mlxsw_reg_pfcc_prio_pack(char *payload, u8 pfc_en) +{ + mlxsw_reg_pfcc_prio_mask_tx_set(payload, MLXSW_REG_PFCC_ALL_PRIO); + mlxsw_reg_pfcc_prio_mask_rx_set(payload, MLXSW_REG_PFCC_ALL_PRIO); + mlxsw_reg_pfcc_pfctx_set(payload, pfc_en); + mlxsw_reg_pfcc_pfcrx_set(payload, pfc_en); +} + static inline void mlxsw_reg_pfcc_pack(char *payload, u8 local_port) { MLXSW_REG_ZERO(pfcc, payload); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 36a94a94a420..507263a2d226 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -451,24 +451,27 @@ static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p) } static void mlxsw_sp_pg_buf_pack(char *pbmc_pl, int pg_index, int mtu, - bool pause_en) + bool pause_en, bool pfc_en, u16 delay) { u16 pg_size = 2 * MLXSW_SP_BYTES_TO_CELLS(mtu); - if (pause_en) { - u16 pg_pause_size = pg_size + MLXSW_SP_PAUSE_DELAY; + delay = pfc_en ? mlxsw_sp_pfc_delay_get(mtu, delay) : + MLXSW_SP_PAUSE_DELAY; + if (pause_en || pfc_en) mlxsw_reg_pbmc_lossless_buffer_pack(pbmc_pl, pg_index, - pg_pause_size, pg_size); - } else { + pg_size + delay, pg_size); + else mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pg_index, pg_size); - } } int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, - u8 *prio_tc, bool pause_en) + u8 *prio_tc, bool pause_en, + struct ieee_pfc *my_pfc) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 pfc_en = !!my_pfc ? my_pfc->pfc_en : 0; + u16 delay = !!my_pfc ? my_pfc->delay : 0; char pbmc_pl[MLXSW_REG_PBMC_LEN]; int i, j, err; @@ -479,9 +482,11 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { bool configure = false; + bool pfc = false; for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) { if (prio_tc[j] == i) { + pfc = pfc_en & BIT(j); configure = true; break; } @@ -489,7 +494,7 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, if (!configure) continue; - mlxsw_sp_pg_buf_pack(pbmc_pl, i, mtu, pause_en); + mlxsw_sp_pg_buf_pack(pbmc_pl, i, mtu, pause_en, pfc, delay); } return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); @@ -500,12 +505,14 @@ static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, { u8 def_prio_tc[IEEE_8021QAZ_MAX_TCS] = {0}; bool dcb_en = !!mlxsw_sp_port->dcb.ets; + struct ieee_pfc *my_pfc; u8 *prio_tc; prio_tc = dcb_en ? mlxsw_sp_port->dcb.ets->prio_tc : def_prio_tc; + my_pfc = dcb_en ? mlxsw_sp_port->dcb.pfc : NULL; return __mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, prio_tc, - pause_en); + pause_en, my_pfc); } static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) @@ -1032,6 +1039,11 @@ static int mlxsw_sp_port_set_pauseparam(struct net_device *dev, bool pause_en = pause->tx_pause || pause->rx_pause; int err; + if (mlxsw_sp_port->dcb.pfc && mlxsw_sp_port->dcb.pfc->pfc_en) { + netdev_err(dev, "PFC already enabled on port\n"); + return -EINVAL; + } + if (pause->autoneg) { netdev_err(dev, "PAUSE frames autonegotiation isn't supported\n"); return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index f4b53dd34f22..47610a5ccd78 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -72,6 +72,14 @@ */ #define MLXSW_SP_PAUSE_DELAY 612 +#define MLXSW_SP_CELL_FACTOR 2 /* 2 * cell_size / (IPG + cell_size + 1) */ + +static inline u16 mlxsw_sp_pfc_delay_get(int mtu, u16 delay) +{ + delay = MLXSW_SP_BYTES_TO_CELLS(DIV_ROUND_UP(delay, BITS_PER_BYTE)); + return MLXSW_SP_CELL_FACTOR * delay + MLXSW_SP_BYTES_TO_CELLS(mtu); +} + struct mlxsw_sp_port; struct mlxsw_sp_upper { @@ -183,6 +191,7 @@ struct mlxsw_sp_port { struct { struct ieee_ets *ets; struct ieee_maxrate *maxrate; + struct ieee_pfc *pfc; } dcb; /* 802.1Q bridge VLANs */ unsigned long *active_vlans; @@ -295,7 +304,8 @@ int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port, int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 switch_prio, u8 tclass); int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, - u8 *prio_tc, bool pause_en); + u8 *prio_tc, bool pause_en, + struct ieee_pfc *my_pfc); int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index, u32 maxrate); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c index 8786424f6191..0b323661c0b6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c @@ -34,6 +34,7 @@ #include #include +#include #include #include "spectrum.h" @@ -151,7 +152,8 @@ static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, * traffic is still directed to them. */ err = __mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, - ets->prio_tc, pause_en); + ets->prio_tc, pause_en, + mlxsw_sp_port->dcb.pfc); if (err) { netdev_err(dev, "Failed to configure port's headroom\n"); return err; @@ -291,11 +293,101 @@ static int mlxsw_sp_dcbnl_ieee_setmaxrate(struct net_device *dev, return err; } +static int mlxsw_sp_port_pfc_cnt_get(struct mlxsw_sp_port *mlxsw_sp_port, + u8 prio) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct ieee_pfc *my_pfc = mlxsw_sp_port->dcb.pfc; + char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; + int err; + + mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port, + MLXSW_REG_PPCNT_PRIO_CNT, prio); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ppcnt), ppcnt_pl); + if (err) + return err; + + my_pfc->requests[prio] = mlxsw_reg_ppcnt_tx_pause_get(ppcnt_pl); + my_pfc->indications[prio] = mlxsw_reg_ppcnt_rx_pause_get(ppcnt_pl); + + return 0; +} + +static int mlxsw_sp_dcbnl_ieee_getpfc(struct net_device *dev, + struct ieee_pfc *pfc) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err, i; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = mlxsw_sp_port_pfc_cnt_get(mlxsw_sp_port, i); + if (err) { + netdev_err(dev, "Failed to get PFC count for priority %d\n", + i); + return err; + } + } + + memcpy(pfc, mlxsw_sp_port->dcb.pfc, sizeof(*pfc)); + + return 0; +} + +static int mlxsw_sp_port_pfc_set(struct mlxsw_sp_port *mlxsw_sp_port, + struct ieee_pfc *pfc) +{ + char pfcc_pl[MLXSW_REG_PFCC_LEN]; + + mlxsw_reg_pfcc_pack(pfcc_pl, mlxsw_sp_port->local_port); + mlxsw_reg_pfcc_prio_pack(pfcc_pl, pfc->pfc_en); + + return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pfcc), + pfcc_pl); +} + +static int mlxsw_sp_dcbnl_ieee_setpfc(struct net_device *dev, + struct ieee_pfc *pfc) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err; + + if (mlxsw_sp_port->link.tx_pause || mlxsw_sp_port->link.rx_pause) { + netdev_err(dev, "PAUSE frames already enabled on port\n"); + return -EINVAL; + } + + err = __mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, + mlxsw_sp_port->dcb.ets->prio_tc, + false, pfc); + if (err) { + netdev_err(dev, "Failed to configure port's headroom for PFC\n"); + return err; + } + + err = mlxsw_sp_port_pfc_set(mlxsw_sp_port, pfc); + if (err) { + netdev_err(dev, "Failed to configure PFC\n"); + goto err_port_pfc_set; + } + + memcpy(mlxsw_sp_port->dcb.pfc, pfc, sizeof(*pfc)); + + return 0; + +err_port_pfc_set: + __mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, + mlxsw_sp_port->dcb.ets->prio_tc, false, + mlxsw_sp_port->dcb.pfc); + return err; +} + static const struct dcbnl_rtnl_ops mlxsw_sp_dcbnl_ops = { .ieee_getets = mlxsw_sp_dcbnl_ieee_getets, .ieee_setets = mlxsw_sp_dcbnl_ieee_setets, .ieee_getmaxrate = mlxsw_sp_dcbnl_ieee_getmaxrate, .ieee_setmaxrate = mlxsw_sp_dcbnl_ieee_setmaxrate, + .ieee_getpfc = mlxsw_sp_dcbnl_ieee_getpfc, + .ieee_setpfc = mlxsw_sp_dcbnl_ieee_setpfc, .getdcbx = mlxsw_sp_dcbnl_getdcbx, .setdcbx = mlxsw_sp_dcbnl_setdcbx, @@ -338,6 +430,23 @@ static void mlxsw_sp_port_maxrate_fini(struct mlxsw_sp_port *mlxsw_sp_port) kfree(mlxsw_sp_port->dcb.maxrate); } +static int mlxsw_sp_port_pfc_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + mlxsw_sp_port->dcb.pfc = kzalloc(sizeof(*mlxsw_sp_port->dcb.pfc), + GFP_KERNEL); + if (!mlxsw_sp_port->dcb.pfc) + return -ENOMEM; + + mlxsw_sp_port->dcb.pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS; + + return 0; +} + +static void mlxsw_sp_port_pfc_fini(struct mlxsw_sp_port *mlxsw_sp_port) +{ + kfree(mlxsw_sp_port->dcb.pfc); +} + int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) { int err; @@ -348,11 +457,16 @@ int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) err = mlxsw_sp_port_maxrate_init(mlxsw_sp_port); if (err) goto err_port_maxrate_init; + err = mlxsw_sp_port_pfc_init(mlxsw_sp_port); + if (err) + goto err_port_pfc_init; mlxsw_sp_port->dev->dcbnl_ops = &mlxsw_sp_dcbnl_ops; return 0; +err_port_pfc_init: + mlxsw_sp_port_maxrate_fini(mlxsw_sp_port); err_port_maxrate_init: mlxsw_sp_port_ets_fini(mlxsw_sp_port); return err; @@ -360,6 +474,7 @@ int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port) void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port) { + mlxsw_sp_port_pfc_fini(mlxsw_sp_port); mlxsw_sp_port_maxrate_fini(mlxsw_sp_port); mlxsw_sp_port_ets_fini(mlxsw_sp_port); } -- GitLab From 4a462ce084d5beb92cfc68f53f88c035c82e6b59 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 31 Mar 2016 16:35:59 +0300 Subject: [PATCH 1644/9938] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper Treat 32 bit sample width as if it was 24 bits when generating IEC958 channel status bits. On some platforms 24 sample width is problematic and to get full 24 bit precision a 32 bit format, using only the 24 most significant bits, may have to be used. Signed-off-by: Jyri Sarha Reviewed-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/core/pcm_iec958.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c index e016871a978f..5e6aed64f451 100644 --- a/sound/core/pcm_iec958.c +++ b/sound/core/pcm_iec958.c @@ -59,6 +59,7 @@ static int create_iec958_consumer(uint rate, uint sample_width, IEC958_AES4_CON_MAX_WORDLEN_24; break; case 24: + case 32: /* Assume 24-bit width for 32-bit samples. */ ws = IEC958_AES4_CON_WORDLEN_24_20 | IEC958_AES4_CON_MAX_WORDLEN_24; break; -- GitLab From 1f2f83f838489d386ecad9d0c77c3d6ec983102c Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 3 Feb 2016 09:20:51 +0100 Subject: [PATCH 1645/9938] e1000: call ndo_stop() instead of dev_close() when running offline selftest Calling dev_close() causes IFF_UP to be cleared which will remove the interfaces routes and some addresses. That's probably not what the user intended when running the offline selftest. Besides this does not happen if the interface is brought down before the test, so the current behaviour is inconsistent. Instead call the net_device_ops ndo_stop function directly and avoid touching IFF_UP at all. Signed-off-by: Stefan Assmann Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000/e1000.h | 2 ++ drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 4 ++-- drivers/net/ethernet/intel/e1000/e1000_main.c | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index 98fe5a2cd6e3..d7bdea79e9fa 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h @@ -358,6 +358,8 @@ struct net_device *e1000_get_hw_dev(struct e1000_hw *hw); extern char e1000_driver_name[]; extern const char e1000_driver_version[]; +int e1000_open(struct net_device *netdev); +int e1000_close(struct net_device *netdev); int e1000_up(struct e1000_adapter *adapter); void e1000_down(struct e1000_adapter *adapter); void e1000_reinit_locked(struct e1000_adapter *adapter); diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index 83e557c7f279..975eeb885ca2 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -1553,7 +1553,7 @@ static void e1000_diag_test(struct net_device *netdev, if (if_running) /* indicate we're in test mode */ - dev_close(netdev); + e1000_close(netdev); else e1000_reset(adapter); @@ -1582,7 +1582,7 @@ static void e1000_diag_test(struct net_device *netdev, e1000_reset(adapter); clear_bit(__E1000_TESTING, &adapter->flags); if (if_running) - dev_open(netdev); + e1000_open(netdev); } else { e_info(hw, "online testing starting\n"); /* Online tests */ diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 3fc7bde699ba..6de0c7df56fa 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -114,8 +114,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void e1000_remove(struct pci_dev *pdev); static int e1000_alloc_queues(struct e1000_adapter *adapter); static int e1000_sw_init(struct e1000_adapter *adapter); -static int e1000_open(struct net_device *netdev); -static int e1000_close(struct net_device *netdev); +int e1000_open(struct net_device *netdev); +int e1000_close(struct net_device *netdev); static void e1000_configure_tx(struct e1000_adapter *adapter); static void e1000_configure_rx(struct e1000_adapter *adapter); static void e1000_setup_rctl(struct e1000_adapter *adapter); @@ -1360,7 +1360,7 @@ static int e1000_alloc_queues(struct e1000_adapter *adapter) * handler is registered with the OS, the watchdog task is started, * and the stack is notified that the interface is ready. **/ -static int e1000_open(struct net_device *netdev) +int e1000_open(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -1437,7 +1437,7 @@ static int e1000_open(struct net_device *netdev) * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ -static int e1000_close(struct net_device *netdev) +int e1000_close(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; -- GitLab From d1d438a3b1eb64eb99fc918d13a52ded3e941d67 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 6 Apr 2016 18:02:41 -0300 Subject: [PATCH 1646/9938] perf trace: Beautify pid_t arguments When reading the syscall tracepoint /format file, look for arguments of type "pid_t" and attach the PID beautifier, that will do a lookup on the threads it knows, i.e. the ones that came from PERF_RECORD_COMM events and add the COMM after the pid in such args: Excerpt of a system wide trace for syscalls with pid_t args: 55602.977 ( 0.006 ms): bash/12122 setpgid(pid: 24347 (bash), pgid: 24347 (bash)) = 0 55603.024 ( 0.004 ms): bash/24347 setpgid(pid: 24347 (bash), pgid: 24347 (bash)) = 0 55691.527 (88.397 ms): bash/12122 wait4(upid: -1, stat_addr: 0x7ffe0cee1720, options: UNTRACED|CONTINUED) ... 55692.479 ( 0.952 ms): git/24347 wait4(upid: 24368, stat_addr: 0x7ffe030d5724) ... 55694.549 ( 2.070 ms): pre-commit/24368 wait4(upid: -1, stat_addr: 0x7ffc94f4fc10) = 24369 (pre-commit) 55694.575 ( 0.002 ms): pre-commit/24368 wait4(upid: -1, stat_addr: 0x7ffc94f4f650, options: NOHANG) = -1 ECHILD No child processes 55695.934 ( 0.010 ms): pre-commit/24368 wait4(upid: -1, stat_addr: 0x7ffc94f4f2d0, options: NOHANG) = 24370 (git) 55695.937 ( 0.001 ms): pre-commit/24368 wait4(upid: -1, stat_addr: 0x7ffc94f4f2d0, options: NOHANG) = -1 ECHILD No child processes 55717.963 ( 0.000 ms): pre-commit/24371 ... [continued]: wait4()) = 24372 55717.978 (21.468 ms): :24371/24371 wait4(upid: -1, stat_addr: 0x7ffc94f4f230) ... 55718.087 ( 0.109 ms): pre-commit/24371 wait4(upid: -1, stat_addr: 0x7ffc94f4f230) = 24373 (tr) 55718.187 ( 0.096 ms): pre-commit/24371 wait4(upid: -1, stat_addr: 0x7ffc94f4f230) = 24374 (wc) 55718.218 ( 0.002 ms): pre-commit/24371 wait4(upid: -1, stat_addr: 0x7ffc94f4eed0, options: NOHANG) = -1 ECHILD No child processes 55718.367 ( 0.005 ms): pre-commit/24368 wait4(upid: -1, stat_addr: 0x7ffc94f4f1d0, options: NOHANG) = 24371 (pre-commit) 55718.369 ( 0.001 ms): pre-commit/24368 wait4(upid: -1, stat_addr: 0x7ffc94f4f1d0, options: NOHANG) = -1 ECHILD No child processes 55741.021 (49.494 ms): git/24347 ... [continued]: wait4()) = 24368 (pre-commit) 74146.427 (18319.601 ms): git/24347 wait4(upid: 24375 (git), stat_addr: 0x7ffe030d6824) ... 74149.036 ( 0.891 ms): bash/24391 wait4(upid: -1, stat_addr: 0x7ffe0cee0560) = 24393 (sed) Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-75yl9hzjhb020iadc81gdj8t@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 110 ++++++++++++++++++---------------- tools/perf/trace/beauty/pid.c | 18 ++++++ 2 files changed, 75 insertions(+), 53 deletions(-) create mode 100644 tools/perf/trace/beauty/pid.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 191f4d61eb16..57d4bb473add 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -112,6 +112,58 @@ # define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */ #endif +struct trace { + struct perf_tool tool; + struct { + int machine; + int open_id; + } audit; + struct { + int max; + struct syscall *table; + struct { + struct perf_evsel *sys_enter, + *sys_exit; + } events; + } syscalls; + struct record_opts opts; + struct perf_evlist *evlist; + struct machine *host; + struct thread *current; + u64 base_time; + FILE *output; + unsigned long nr_events; + struct strlist *ev_qualifier; + struct { + size_t nr; + int *entries; + } ev_qualifier_ids; + struct intlist *tid_list; + struct intlist *pid_list; + struct { + size_t nr; + pid_t *entries; + } filter_pids; + double duration_filter; + double runtime_ms; + struct { + u64 vfs_getname, + proc_getname; + } stats; + bool not_ev_qualifier; + bool live; + bool full_time; + bool sched; + bool multiple_threads; + bool summary; + bool summary_only; + bool show_comm; + bool show_tool_stats; + bool trace_syscalls; + bool force; + bool vfs_getname; + int trace_pgfaults; +}; struct tp_field { int offset; @@ -1073,6 +1125,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ .arg_parm = { [arg] = &strarray__##array, } +#include "trace/beauty/pid.c" #include "trace/beauty/sched_policy.c" #include "trace/beauty/waitid_options.c" @@ -1167,6 +1220,7 @@ static struct syscall_fmt { .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, { .name = "getpid", .errpid = true, }, + { .name = "getpgid", .errpid = true, }, { .name = "getppid", .errpid = true, }, { .name = "getrandom", .errmsg = true, .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, @@ -1328,6 +1382,7 @@ static struct syscall_fmt { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "set_tid_address", .errpid = true, }, { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, + { .name = "setpgid", .errmsg = true, }, { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, { .name = "setxattr", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, @@ -1485,59 +1540,6 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp) static const size_t trace__entry_str_size = 2048; -struct trace { - struct perf_tool tool; - struct { - int machine; - int open_id; - } audit; - struct { - int max; - struct syscall *table; - struct { - struct perf_evsel *sys_enter, - *sys_exit; - } events; - } syscalls; - struct record_opts opts; - struct perf_evlist *evlist; - struct machine *host; - struct thread *current; - u64 base_time; - FILE *output; - unsigned long nr_events; - struct strlist *ev_qualifier; - struct { - size_t nr; - int *entries; - } ev_qualifier_ids; - struct intlist *tid_list; - struct intlist *pid_list; - struct { - size_t nr; - pid_t *entries; - } filter_pids; - double duration_filter; - double runtime_ms; - struct { - u64 vfs_getname, - proc_getname; - } stats; - bool not_ev_qualifier; - bool live; - bool full_time; - bool sched; - bool multiple_threads; - bool summary; - bool summary_only; - bool show_comm; - bool show_tool_stats; - bool trace_syscalls; - bool force; - bool vfs_getname; - int trace_pgfaults; -}; - static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) { struct thread_trace *ttrace = thread__priv(thread); @@ -1763,6 +1765,8 @@ static int syscall__set_arg_fmts(struct syscall *sc) sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; else if (field->flags & FIELD_IS_POINTER) sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; + else if (strcmp(field->type, "pid_t") == 0) + sc->arg_scnprintf[idx] = SCA_PID; ++idx; } diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c new file mode 100644 index 000000000000..111ae08d38f1 --- /dev/null +++ b/tools/perf/trace/beauty/pid.c @@ -0,0 +1,18 @@ +static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg) +{ + int pid = arg->val; + struct trace *trace = arg->trace; + size_t printed = scnprintf(bf, size, "%d", pid); + struct thread *thread = machine__find_thread(trace->host, pid, pid); + + if (thread != NULL) { + if (thread->comm_set) + printed += scnprintf(bf + printed, size - printed, + " (%s)", thread__comm_str(thread)); + thread__put(thread); + } + + return printed; +} + +#define SCA_PID syscall_arg__scnprintf_pid -- GitLab From 74813cebd678dd471b4fcd7d3019aecab9dbcedd Mon Sep 17 00:00:00 2001 From: Raveendra Padasalagi Date: Wed, 6 Apr 2016 10:26:27 -0700 Subject: [PATCH 1647/9938] Input: bcm_iproc_tsc - use syscon to access shared registers In Cygnus SOC touch screen controller registers are shared with ADC and flex timer. Using readl/writel could lead to race condition. So touch screen driver is enhanced to support register access using syscon framework API's to take care of mutually exclusive access. Signed-off-by: Raveendra Padasalagi Reviewed-by: Ray Jui Reviewed-by: Scott Branden Acked-by: Rob Herring Acked-by: Florian Fainelli Signed-off-by: Dmitry Torokhov --- .../touchscreen/brcm,iproc-touchscreen.txt | 21 +++-- arch/arm/boot/dts/bcm-cygnus.dtsi | 11 ++- drivers/input/touchscreen/bcm_iproc_tsc.c | 77 +++++++++++-------- 3 files changed, 68 insertions(+), 41 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt b/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt index 34e3382a0659..25541f30e387 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt @@ -2,11 +2,17 @@ Required properties: - compatible: must be "brcm,iproc-touchscreen" -- reg: physical base address of the controller and length of memory mapped - region. +- ts_syscon: handler of syscon node defining physical base + address of the controller and length of memory mapped region. + If this property is selected please make sure MFD_SYSCON config + is enabled in the defconfig file. - clocks: The clock provided by the SOC to driver the tsc - clock-name: name for the clock - interrupts: The touchscreen controller's interrupt +- address-cells: Specify the number of u32 entries needed in child nodes. + Should set to 1. +- size-cells: Specify number of u32 entries needed to specify child nodes size + in reg property. Should set to 1. Optional properties: - scanning_period: Time between scans. Each step is 1024 us. Valid 1-256. @@ -53,13 +59,18 @@ Optional properties: - touchscreen-inverted-x: X axis is inverted (boolean) - touchscreen-inverted-y: Y axis is inverted (boolean) -Example: +Example: An example of touchscreen node - touchscreen: tsc@0x180A6000 { + ts_adc_syscon: ts_adc_syscon@180a6000 { + compatible = "brcm,iproc-ts-adc-syscon","syscon"; + reg = <0x180a6000 0xc30>; + }; + + touchscreen: touchscreen@180A6000 { compatible = "brcm,iproc-touchscreen"; #address-cells = <1>; #size-cells = <1>; - reg = <0x180A6000 0x40>; + ts_syscon = <&ts_adc_syscon>; clocks = <&adc_clk>; clock-names = "tsc_clk"; interrupts = ; diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 3878793364f0..b42fe5596b94 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -351,9 +351,16 @@ <&pinctrl 142 10 1>; }; - touchscreen: tsc@180a6000 { + ts_adc_syscon: ts_adc_syscon@180a6000 { + compatible = "brcm,iproc-ts-adc-syscon", "syscon"; + reg = <0x180a6000 0xc30>; + }; + + touchscreen: touchscreen@180a6000 { compatible = "brcm,iproc-touchscreen"; - reg = <0x180a6000 0x40>; + #address-cells = <1>; + #size-cells = <1>; + ts_syscon = <&ts_adc_syscon>; clocks = <&asiu_clks BCM_CYGNUS_ASIU_ADC_CLK>; clock-names = "tsc_clk"; interrupts = ; diff --git a/drivers/input/touchscreen/bcm_iproc_tsc.c b/drivers/input/touchscreen/bcm_iproc_tsc.c index ae460a5c93d5..4d11b27c7c43 100644 --- a/drivers/input/touchscreen/bcm_iproc_tsc.c +++ b/drivers/input/touchscreen/bcm_iproc_tsc.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #define IPROC_TS_NAME "iproc-ts" @@ -88,7 +90,11 @@ #define TS_WIRE_MODE_BIT BIT(1) #define dbg_reg(dev, priv, reg) \ - dev_dbg(dev, "%20s= 0x%08x\n", #reg, readl((priv)->regs + reg)) +do { \ + u32 val; \ + regmap_read(priv->regmap, reg, &val); \ + dev_dbg(dev, "%20s= 0x%08x\n", #reg, val); \ +} while (0) struct tsc_param { /* Each step is 1024 us. Valid 1-256 */ @@ -141,7 +147,7 @@ struct iproc_ts_priv { struct platform_device *pdev; struct input_dev *idev; - void __iomem *regs; + struct regmap *regmap; struct clk *tsc_clk; int pen_status; @@ -196,22 +202,22 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) int i; bool needs_sync = false; - intr_status = readl(priv->regs + INTERRUPT_STATUS); + regmap_read(priv->regmap, INTERRUPT_STATUS, &intr_status); intr_status &= TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; if (intr_status == 0) return IRQ_NONE; /* Clear all interrupt status bits, write-1-clear */ - writel(intr_status, priv->regs + INTERRUPT_STATUS); - + regmap_write(priv->regmap, INTERRUPT_STATUS, intr_status); /* Pen up/down */ if (intr_status & TS_PEN_INTR_MASK) { - if (readl(priv->regs + CONTROLLER_STATUS) & TS_PEN_DOWN) + regmap_read(priv->regmap, CONTROLLER_STATUS, &priv->pen_status); + if (priv->pen_status & TS_PEN_DOWN) priv->pen_status = PEN_DOWN_STATUS; else priv->pen_status = PEN_UP_STATUS; - input_report_key(priv->idev, BTN_TOUCH, priv->pen_status); + input_report_key(priv->idev, BTN_TOUCH, priv->pen_status); needs_sync = true; dev_dbg(&priv->pdev->dev, @@ -221,7 +227,7 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) /* coordinates in FIFO exceed the theshold */ if (intr_status & TS_FIFO_INTR_MASK) { for (i = 0; i < priv->cfg_params.fifo_threshold; i++) { - raw_coordinate = readl(priv->regs + FIFO_DATA); + regmap_read(priv->regmap, FIFO_DATA, &raw_coordinate); if (raw_coordinate == INVALID_COORD) continue; @@ -239,7 +245,7 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) x = (x >> 4) & 0x0FFF; y = (y >> 4) & 0x0FFF; - /* adjust x y according to lcd tsc mount angle */ + /* Adjust x y according to LCD tsc mount angle. */ if (priv->cfg_params.invert_x) x = priv->cfg_params.max_x - x; @@ -262,9 +268,10 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) static int iproc_ts_start(struct input_dev *idev) { - struct iproc_ts_priv *priv = input_get_drvdata(idev); u32 val; + u32 mask; int error; + struct iproc_ts_priv *priv = input_get_drvdata(idev); /* Enable clock */ error = clk_prepare_enable(priv->tsc_clk); @@ -279,9 +286,10 @@ static int iproc_ts_start(struct input_dev *idev) * FIFO reaches the int_th value, and pen event(up/down) */ val = TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; - writel(val, priv->regs + INTERRUPT_MASK); + regmap_update_bits(priv->regmap, INTERRUPT_MASK, val, val); - writel(priv->cfg_params.fifo_threshold, priv->regs + INTERRUPT_THRES); + val = priv->cfg_params.fifo_threshold; + regmap_write(priv->regmap, INTERRUPT_THRES, val); /* Initialize control reg1 */ val = 0; @@ -289,26 +297,23 @@ static int iproc_ts_start(struct input_dev *idev) val |= priv->cfg_params.debounce_timeout << DEBOUNCE_TIMEOUT_SHIFT; val |= priv->cfg_params.settling_timeout << SETTLING_TIMEOUT_SHIFT; val |= priv->cfg_params.touch_timeout << TOUCH_TIMEOUT_SHIFT; - writel(val, priv->regs + REGCTL1); + regmap_write(priv->regmap, REGCTL1, val); /* Try to clear all interrupt status */ - val = readl(priv->regs + INTERRUPT_STATUS); - val |= TS_FIFO_INTR_MASK | TS_PEN_INTR_MASK; - writel(val, priv->regs + INTERRUPT_STATUS); + val = TS_FIFO_INTR_MASK | TS_PEN_INTR_MASK; + regmap_update_bits(priv->regmap, INTERRUPT_STATUS, val, val); /* Initialize control reg2 */ - val = readl(priv->regs + REGCTL2); - val |= TS_CONTROLLER_EN_BIT | TS_WIRE_MODE_BIT; - - val &= ~TS_CONTROLLER_AVGDATA_MASK; + val = TS_CONTROLLER_EN_BIT | TS_WIRE_MODE_BIT; val |= priv->cfg_params.average_data << TS_CONTROLLER_AVGDATA_SHIFT; - val &= ~(TS_CONTROLLER_PWR_LDO | /* PWR up LDO */ + mask = (TS_CONTROLLER_AVGDATA_MASK); + mask |= (TS_CONTROLLER_PWR_LDO | /* PWR up LDO */ TS_CONTROLLER_PWR_ADC | /* PWR up ADC */ TS_CONTROLLER_PWR_BGP | /* PWR up BGP */ TS_CONTROLLER_PWR_TS); /* PWR up TS */ - - writel(val, priv->regs + REGCTL2); + mask |= val; + regmap_update_bits(priv->regmap, REGCTL2, mask, val); ts_reg_dump(priv); @@ -320,12 +325,17 @@ static void iproc_ts_stop(struct input_dev *dev) u32 val; struct iproc_ts_priv *priv = input_get_drvdata(dev); - writel(0, priv->regs + INTERRUPT_MASK); /* Disable all interrupts */ + /* + * Disable FIFO int_th and pen event(up/down)Interrupts only + * as the interrupt mask register is shared between ADC, TS and + * flextimer. + */ + val = TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; + regmap_update_bits(priv->regmap, INTERRUPT_MASK, val, 0); /* Only power down touch screen controller */ - val = readl(priv->regs + REGCTL2); - val |= TS_CONTROLLER_PWR_TS; - writel(val, priv->regs + REGCTL2); + val = TS_CONTROLLER_PWR_TS; + regmap_update_bits(priv->regmap, REGCTL2, val, val); clk_disable(priv->tsc_clk); } @@ -414,7 +424,6 @@ static int iproc_ts_probe(struct platform_device *pdev) { struct iproc_ts_priv *priv; struct input_dev *idev; - struct resource *res; int irq; int error; @@ -422,12 +431,12 @@ static int iproc_ts_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - /* touchscreen controller memory mapped regs */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->regs)) { - error = PTR_ERR(priv->regs); - dev_err(&pdev->dev, "unable to map I/O memory: %d\n", error); + /* touchscreen controller memory mapped regs via syscon*/ + priv->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "ts_syscon"); + if (IS_ERR(priv->regmap)) { + error = PTR_ERR(priv->regmap); + dev_err(&pdev->dev, "unable to map I/O memory:%d\n", error); return error; } -- GitLab From 95cface95b6a6a8de6e95de2c8a25a64fd0f3558 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 31 Mar 2016 19:28:26 +0200 Subject: [PATCH 1648/9938] ARM: dts: rockchip: fix rk3288 power-domain unit names The power-domain sub-nodes do have reg properties, but so far are missing the expected unit names. So add the missing ones. Signed-off-by: Heiko Stuebner Acked-by: Rob Herring --- arch/arm/boot/dts/rk3288.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 74eae995c330..f445d190ed1a 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -659,7 +659,7 @@ * *_HDMI HDMI * *_MIPI_* MIPI */ - pd_vio { + pd_vio@RK3288_PD_VIO { reg = ; clocks = <&cru ACLK_IEP>, <&cru ACLK_ISP>, @@ -692,7 +692,7 @@ * Note: The following 3 are HEVC(H.265) clocks, * and on the ACLK_HEVC_NIU (NOC). */ - pd_hevc { + pd_hevc@RK3288_PD_HEVC { reg = ; clocks = <&cru ACLK_HEVC>, <&cru SCLK_HEVC_CABAC>, @@ -704,7 +704,7 @@ * (video endecoder & decoder) clocks that on the * ACLK_VCODEC_NIU and HCLK_VCODEC_NIU (NOC). */ - pd_video { + pd_video@RK3288_PD_VIDEO { reg = ; clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; @@ -714,7 +714,7 @@ * Note: ACLK_GPU is the GPU clock, * and on the ACLK_GPU_NIU (NOC). */ - pd_gpu { + pd_gpu@RK3288_PD_GPU { reg = ; clocks = <&cru ACLK_GPU>; }; -- GitLab From a8f0fa2764626d2dd808cfbe1a160f2939a36c88 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 31 Mar 2016 20:12:14 +0200 Subject: [PATCH 1649/9938] ARM: dts: rockchip: fix missing usbphy unit-names The usbphy subnodes do have a reg property but no unitname, add them. Signed-off-by: Heiko Stuebner Acked-by: Rob Herring --- arch/arm/boot/dts/rk3066a.dtsi | 4 ++-- arch/arm/boot/dts/rk3188.dtsi | 4 ++-- arch/arm/boot/dts/rk3288.dtsi | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi index cb0a552e0b18..c84a306fd73f 100644 --- a/arch/arm/boot/dts/rk3066a.dtsi +++ b/arch/arm/boot/dts/rk3066a.dtsi @@ -207,7 +207,7 @@ #size-cells = <0>; status = "disabled"; - usbphy0: usb-phy0 { + usbphy0: usb-phy@17c { #phy-cells = <0>; reg = <0x17c>; clocks = <&cru SCLK_OTGPHY0>; @@ -215,7 +215,7 @@ #clock-cells = <0>; }; - usbphy1: usb-phy1 { + usbphy1: usb-phy@188 { #phy-cells = <0>; reg = <0x188>; clocks = <&cru SCLK_OTGPHY1>; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 9271833958f9..c44c31874bbd 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -166,7 +166,7 @@ #size-cells = <0>; status = "disabled"; - usbphy0: usb-phy0 { + usbphy0: usb-phy@10c { #phy-cells = <0>; reg = <0x10c>; clocks = <&cru SCLK_OTGPHY0>; @@ -174,7 +174,7 @@ #clock-cells = <0>; }; - usbphy1: usb-phy1 { + usbphy1: usb-phy@11c { #phy-cells = <0>; reg = <0x11c>; clocks = <&cru SCLK_OTGPHY1>; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index f445d190ed1a..ee4085dd7007 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -967,7 +967,7 @@ #size-cells = <0>; status = "disabled"; - usbphy0: usb-phy0 { + usbphy0: usb-phy@320 { #phy-cells = <0>; reg = <0x320>; clocks = <&cru SCLK_OTGPHY0>; @@ -975,7 +975,7 @@ #clock-cells = <0>; }; - usbphy1: usb-phy1 { + usbphy1: usb-phy@334 { #phy-cells = <0>; reg = <0x334>; clocks = <&cru SCLK_OTGPHY1>; @@ -983,7 +983,7 @@ #clock-cells = <0>; }; - usbphy2: usb-phy2 { + usbphy2: usb-phy@348 { #phy-cells = <0>; reg = <0x348>; clocks = <&cru SCLK_OTGPHY2>; -- GitLab From 8b30c899c7dd9eb92b957a3c112d3226a9ac1c3c Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 31 Mar 2016 20:24:29 +0200 Subject: [PATCH 1650/9938] ARM: dts: rockchip: clean up gpio-keys nodes Drop superfluous #address-cells and #size-cells, rename key-nodes to individual names and also use the key constants intead of numbers. Reported-by: Julien Chauveau Signed-off-by: Heiko Stuebner Acked-by: Rob Herring --- arch/arm/boot/dts/rk3066a-bqcurie2.dts | 11 +++++------ arch/arm/boot/dts/rk3066a-rayeager.dts | 7 +++---- arch/arm/boot/dts/rk3188-radxarock.dts | 7 +++---- arch/arm/boot/dts/rk3288-evb.dtsi | 7 +++---- arch/arm/boot/dts/rk3288-firefly.dtsi | 7 +++---- arch/arm/boot/dts/rk3288-popmetal.dts | 8 +++----- arch/arm/boot/dts/rk3288-r89.dts | 7 +++---- 7 files changed, 23 insertions(+), 31 deletions(-) diff --git a/arch/arm/boot/dts/rk3066a-bqcurie2.dts b/arch/arm/boot/dts/rk3066a-bqcurie2.dts index 6d2a5b3a84a8..bc674ee206ec 100644 --- a/arch/arm/boot/dts/rk3066a-bqcurie2.dts +++ b/arch/arm/boot/dts/rk3066a-bqcurie2.dts @@ -42,6 +42,7 @@ */ /dts-v1/; +#include #include "rk3066a.dtsi" / { @@ -77,21 +78,19 @@ gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; autorepeat; - button@0 { + power { gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* GPIO6_A2 */ - linux,code = <116>; + linux,code = ; label = "GPIO Key Power"; linux,input-type = <1>; wakeup-source; debounce-interval = <100>; }; - button@1 { + volume-down { gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; /* GPIO4_C5 */ - linux,code = <104>; + linux,code = ; label = "GPIO Key Vol-"; linux,input-type = <1>; debounce-interval = <100>; diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts b/arch/arm/boot/dts/rk3066a-rayeager.dts index 3a5989b1724a..6e7f2187a0e3 100644 --- a/arch/arm/boot/dts/rk3066a-rayeager.dts +++ b/arch/arm/boot/dts/rk3066a-rayeager.dts @@ -41,6 +41,7 @@ */ /dts-v1/; +#include #include "rk3066a.dtsi" / { @@ -61,14 +62,12 @@ keys: gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - button@0 { + power { wakeup-source; gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; label = "GPIO Power"; - linux,code = <116>; + linux,code = ; pinctrl-names = "default"; pinctrl-0 = <&pwr_key>; }; diff --git a/arch/arm/boot/dts/rk3188-radxarock.dts b/arch/arm/boot/dts/rk3188-radxarock.dts index 0b6924c97b6b..1da46d138029 100644 --- a/arch/arm/boot/dts/rk3188-radxarock.dts +++ b/arch/arm/boot/dts/rk3188-radxarock.dts @@ -41,6 +41,7 @@ */ /dts-v1/; +#include #include "rk3188.dtsi" / { @@ -54,13 +55,11 @@ gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; autorepeat; - button@0 { + power { gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; - linux,code = <116>; + linux,code = ; label = "GPIO Key Power"; linux,input-type = <1>; wakeup-source; diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 3ccd8f35a841..963365d12208 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -38,6 +38,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include "rk3288.dtsi" @@ -98,16 +99,14 @@ gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; autorepeat; pinctrl-names = "default"; pinctrl-0 = <&pwrbtn>; - button@0 { + power { gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; - linux,code = <116>; + linux,code = ; label = "GPIO Key Power"; linux,input-type = <1>; wakeup-source; diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi index 5f06d8c1b9f6..d6cf9ada13c9 100644 --- a/arch/arm/boot/dts/rk3288-firefly.dtsi +++ b/arch/arm/boot/dts/rk3288-firefly.dtsi @@ -40,6 +40,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include "rk3288.dtsi" / { @@ -87,14 +88,12 @@ keys: gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - button@0 { + power { wakeup-source; gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; label = "GPIO Power"; - linux,code = <116>; + linux,code = ; pinctrl-names = "default"; pinctrl-0 = <&pwr_key>; }; diff --git a/arch/arm/boot/dts/rk3288-popmetal.dts b/arch/arm/boot/dts/rk3288-popmetal.dts index eb77276e1cc2..720717bb3614 100644 --- a/arch/arm/boot/dts/rk3288-popmetal.dts +++ b/arch/arm/boot/dts/rk3288-popmetal.dts @@ -41,7 +41,7 @@ */ /dts-v1/; - +#include #include "rk3288.dtsi" / { @@ -62,16 +62,14 @@ gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; autorepeat; pinctrl-names = "default"; pinctrl-0 = <&pwrbtn>; - button@0 { + power { gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; - linux,code = <116>; + linux,code = ; label = "GPIO Key Power"; linux,input-type = <1>; wakeup-source; diff --git a/arch/arm/boot/dts/rk3288-r89.dts b/arch/arm/boot/dts/rk3288-r89.dts index 510a1d0d7abb..4b8a8adb243c 100644 --- a/arch/arm/boot/dts/rk3288-r89.dts +++ b/arch/arm/boot/dts/rk3288-r89.dts @@ -41,6 +41,7 @@ */ /dts-v1/; +#include #include #include "rk3288.dtsi" @@ -61,16 +62,14 @@ gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; autorepeat; pinctrl-names = "default"; pinctrl-0 = <&pwrbtn>; - button@0 { + power { gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; - linux,code = <116>; + linux,code = ; label = "GPIO Key Power"; linux,input-type = <1>; wakeup-source; -- GitLab From 6b241fcccb42ab96b3cdca7066cebd0f5cdd44e0 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 31 Mar 2016 20:37:40 +0200 Subject: [PATCH 1651/9938] ARM: dts: rockchip: drop unneeded properties from mipi node The mipi controller node does contain an unused reg property as well as unnecessary #address-cells and #size-cells properties for subnodes not using addresses, so remove those to also make dtc happy. Signed-off-by: Heiko Stuebner Acked-by: Rob Herring --- arch/arm/boot/dts/rk3288.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index ee4085dd7007..9114c7b8dff4 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -888,10 +888,6 @@ status = "disabled"; ports { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - mipi_in: port { #address-cells = <1>; #size-cells = <0>; -- GitLab From 6691409224de8f7badc3f5d072c2bf72b223395d Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 31 Mar 2016 22:15:43 +0200 Subject: [PATCH 1652/9938] ARM: dts: rockchip: add missing unitname to cpu_leakage efuse The cpu_leakage efuse on rk3288 did get it right including the unitname but on both rk3066a and rk3188 it was missing, fix that. Signed-off-by: Heiko Stuebner Acked-by: Rob Herring --- arch/arm/boot/dts/rk3066a.dtsi | 2 +- arch/arm/boot/dts/rk3188.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi index c84a306fd73f..c0ba86c3a2ab 100644 --- a/arch/arm/boot/dts/rk3066a.dtsi +++ b/arch/arm/boot/dts/rk3066a.dtsi @@ -169,7 +169,7 @@ clocks = <&cru PCLK_EFUSE>; clock-names = "pclk_efuse"; - cpu_leakage: cpu_leakage { + cpu_leakage: cpu_leakage@17 { reg = <0x17 0x1>; }; }; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index c44c31874bbd..31f81b265cef 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -154,7 +154,7 @@ clocks = <&cru PCLK_EFUSE>; clock-names = "pclk_efuse"; - cpu_leakage: cpu_leakage { + cpu_leakage: cpu_leakage@17 { reg = <0x17 0x1>; }; }; -- GitLab From f5663969d8125a5c5b7835812e1e636ecedf030b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 28 Oct 2015 10:54:22 +0100 Subject: [PATCH 1653/9938] ARM: dts: rockchip: add rk3288 edp-phy node Add the core device node of the edp-phy on rk3288 socs. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 9114c7b8dff4..437dd263a753 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -201,6 +201,15 @@ #clock-cells = <0>; }; + edp_phy: edp-phy { + compatible = "rockchip,rk3288-dp-phy"; + clocks = <&cru SCLK_EDP_24M>; + clock-names = "24m"; + rockchip,grf = <&grf>; + #phy-cells = <0>; + status = "disabled"; + }; + timer { compatible = "arm,armv7-timer"; arm,cpu-registers-not-fw-configured; -- GitLab From 6df7ec6186644a4ffb4f0c859327ef41a1145a5f Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 28 Oct 2015 10:55:19 +0100 Subject: [PATCH 1654/9938] ARM: dts: rockchip: add rk3288 displayport controller node Add the rk3288 edp node and its hooks into the display-subsystem. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288.dtsi | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 437dd263a753..688cb37b156e 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -830,6 +830,12 @@ reg = <0>; remote-endpoint = <&hdmi_in_vopb>; }; + + vopb_out_edp: endpoint@1 { + reg = <1>; + remote-endpoint = <&edp_in_vopb>; + }; + vopb_out_mipi: endpoint@2 { reg = <2>; remote-endpoint = <&mipi_in_vopb>; @@ -867,6 +873,12 @@ reg = <0>; remote-endpoint = <&hdmi_in_vopl>; }; + + vopl_out_edp: endpoint@1 { + reg = <1>; + remote-endpoint = <&edp_in_vopl>; + }; + vopl_out_mipi: endpoint@2 { reg = <2>; remote-endpoint = <&mipi_in_vopl>; @@ -912,6 +924,38 @@ }; }; + edp: dp@ff970000 { + compatible = "rockchip,rk3288-dp"; + reg = <0xff970000 0x4000>; + interrupts = ; + clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>; + clock-names = "dp", "pclk"; + phys = <&edp_phy>; + phy-names = "dp"; + resets = <&cru SRST_EDP>; + reset-names = "dp"; + rockchip,grf = <&grf>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + edp_in: port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + edp_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_edp>; + }; + edp_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_edp>; + }; + }; + }; + }; + hdmi: hdmi@ff980000 { compatible = "rockchip,rk3288-dw-hdmi"; reg = <0xff980000 0x20000>; -- GitLab From a4e00345b29dbc93fe7e6f4070458f325261b0ac Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 28 Oct 2015 00:19:37 +0100 Subject: [PATCH 1655/9938] ARM: dts: rockchip: move edp-hpd pin definition into common location The edp hotplug pin is fixed on the soc side, anybody wanting to use it will need the same definition anyway, so move it to a common location. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288-veyron-jaq.dts | 6 ------ arch/arm/boot/dts/rk3288.dtsi | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts index c2f52cfb4d06..5c97e3153526 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts @@ -142,12 +142,6 @@ }; }; - edp { - edp_hpd: edp_hpd { - rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_down>; - }; - }; - hdmi { vcc50_hdmi_en: vcc50-hdmi-en { rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 688cb37b156e..3071e94e86ed 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1208,6 +1208,12 @@ }; }; + edp { + edp_hpd: edp-hpd { + rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_down>; + }; + }; + i2c0 { i2c0_xfer: i2c0-xfer { rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>, -- GitLab From 1f45e8c6d0161f044d679f242fe7514e2625af4a Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 29 Nov 2015 19:46:09 +0100 Subject: [PATCH 1656/9938] ARM: dts: rockchip: add startup delay to rk3288-veyron panel-regulators The panels need a bit of time to actually turn on. If this isn't observed, this results in problems when trying talk to the panels and thus produces detection errors. 100ms seem to be a safe value for the time being. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288-veyron-jaq.dts | 1 + arch/arm/boot/dts/rk3288-veyron-jerry.dts | 1 + arch/arm/boot/dts/rk3288-veyron-minnie.dts | 1 + arch/arm/boot/dts/rk3288-veyron-speedy.dts | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts index 5c97e3153526..2123ac21491e 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts @@ -61,6 +61,7 @@ pinctrl-names = "default"; pinctrl-0 = <&lcd_enable_h>; regulator-name = "panel_regulator"; + startup-delay-us = <100000>; vin-supply = <&vcc33_sys>; }; diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rk3288-veyron-jerry.dts index 60bd6e91e308..1a9bef1303d3 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jerry.dts @@ -60,6 +60,7 @@ pinctrl-names = "default"; pinctrl-0 = <&lcd_enable_h>; regulator-name = "panel_regulator"; + startup-delay-us = <100000>; vin-supply = <&vcc33_sys>; }; diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts index 699beb0a9481..8b16f378a847 100644 --- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts +++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts @@ -70,6 +70,7 @@ pinctrl-names = "default"; pinctrl-0 = <&lcd_enable_h>; regulator-name = "panel_regulator"; + startup-delay-us = <100000>; vin-supply = <&vcc33_sys>; }; diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts index b34a7b5b3f62..e62cdee78302 100644 --- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts +++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts @@ -61,6 +61,7 @@ pinctrl-names = "default"; pinctrl-0 = <&lcd_enable_h>; regulator-name = "panel_regulator"; + startup-delay-us = <100000>; vin-supply = <&vcc33_sys>; }; -- GitLab From dfb2146efc6b07f1a6cc04938248c2ce948c9c98 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 14 Dec 2015 11:32:28 +0100 Subject: [PATCH 1657/9938] ARM: dts: rockchip: add core rk3288-veyron backlight and panel nodes Many Veyron chromebooks share the same panel type, so define the core settings for all of them and allow the few runaways to override it later. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- .../boot/dts/rk3288-veyron-chromebook.dtsi | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi index 610769d99522..7563d3d156d7 100644 --- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi @@ -54,6 +54,50 @@ i2c20 = &i2c_tunnel; }; + backlight: backlight { + compatible = "pwm-backlight"; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <128>; + enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>; + backlight-boot-off; + pinctrl-names = "default"; + pinctrl-0 = <&bl_en>; + pwms = <&pwm0 0 1000000 0>; + pwm-delay-us = <10000>; + }; + gpio-charger { compatible = "gpio-charger"; charger-type = "mains"; @@ -62,6 +106,13 @@ pinctrl-0 = <&ac_present_ap>; }; + panel: panel { + compatible ="innolux,n116bge", "simple-panel"; + status = "okay"; + power-supply = <&vcc33_lcd>; + backlight = <&backlight>; + }; + /* A non-regulated voltage from power supply or battery */ vccsys: vccsys { compatible = "regulator-fixed"; @@ -184,6 +235,12 @@ &suspend_l_sleep >; + backlight { + bl_en: bl-en { + rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + buttons { ap_lid_int_l: ap-lid-int-l { rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_up>; -- GitLab From d8444fed59261f0342095e5a259386baf929f92e Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Mon, 7 Dec 2015 21:11:08 +0800 Subject: [PATCH 1658/9938] ARM: dts: rockchip: add rk3288-veyron-jaq backlight and panel overrides The panel which jaq uses requires the pwm duty cycle larger than 3%, when the backlight status from power off to power on, otherwise the backlight will flush, so we modify the second brightness-level to 8, and when the backlight from power off to power on the pwm duty cycle will larger than 3%. Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288-veyron-jaq.dts | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rk3288-veyron-jaq.dts index 2123ac21491e..3748abf562b1 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jaq.dts @@ -89,6 +89,48 @@ }; }; +&backlight { + /* Jaq panel PWM must be >= 3%, so start non-zero brightness at 8 */ + brightness-levels = < + 0 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + power-supply = <&backlight_regulator>; +}; + +&panel { + power-supply = <&panel_regulator>; +}; + &rk808 { pinctrl-names = "default"; pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>; -- GitLab From 712e6051c440a41f5e797412afa7b246d27adc69 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 14 Dec 2015 11:39:58 +0100 Subject: [PATCH 1659/9938] ARM: dts: rockchip: add rk3288-veyron-minnie backlight and panel settings The pwm for Minnie's backlight needs to be above 1%, so adapt the start of non-zero brightness accordingly. Minnie is also using a different panel, so re-set the compatible property. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288-veyron-minnie.dts | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts index 8b16f378a847..f72d616d1bf8 100644 --- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts +++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts @@ -87,6 +87,44 @@ }; }; +&backlight { + /* Minnie panel PWM must be >= 1%, so start non-zero brightness at 3 */ + brightness-levels = < + 0 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + power-supply = <&backlight_regulator>; +}; + &emmc { /delete-property/mmc-hs200-1_8v; }; @@ -136,6 +174,11 @@ }; }; +&panel { + compatible = "auo,b101ean01", "simple-panel"; + power-supply= <&panel_regulator>; +}; + &rk808 { pinctrl-names = "default"; pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>; -- GitLab From 2f171d4043cf574cc003b3cbe0325b2fd02c2a43 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 14 Dec 2015 17:12:47 +0100 Subject: [PATCH 1660/9938] ARM: dts: rockchip: override edp hpd handling on veyron-pinky and speedy Pinky boards don't have the hotplug pin connected. So remove the hotplug pinctrl setting and enable the force-hpd option, to allow them to find the display too. While on speedy boards, the hotplug pin is connected, judging by comments in a chromeos change it seems the "panels HPD voltage is too low to be detected", so it also needs the forced hotplug, as we of course also know that a display is connected. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288-veyron-pinky.dts | 7 +++++++ arch/arm/boot/dts/rk3288-veyron-speedy.dts | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-pinky.dts b/arch/arm/boot/dts/rk3288-veyron-pinky.dts index 94b56e33d947..d44351ec2333 100644 --- a/arch/arm/boot/dts/rk3288-veyron-pinky.dts +++ b/arch/arm/boot/dts/rk3288-veyron-pinky.dts @@ -65,6 +65,13 @@ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8 &emmc_reset>; }; +&edp { + /delete-property/pinctrl-names; + /delete-property/pinctrl-0; + + force-hpd; +}; + &gpio_keys { pinctrl-0 = <&pwr_key_h &ap_lid_int_l>; diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts index e62cdee78302..90aa145404b5 100644 --- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts +++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts @@ -97,6 +97,13 @@ temperature = <70000>; }; +&edp { + /delete-property/pinctrl-names; + /delete-property/pinctrl-0; + + force-hpd; +}; + &rk808 { pinctrl-names = "default"; pinctrl-0 = <&pmic_int_l>; -- GitLab From 03deaf4a814425ceb67c73c1b1b9ada1ee929ca5 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 14 Dec 2015 17:15:25 +0100 Subject: [PATCH 1661/9938] ARM: dts: rockchip: simple panel and backlight supplies on veyron boards Jerry and Speedy don't need any special handling wrt the backlight or panel, so only need their backlight and panel-regulators hooked up. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- arch/arm/boot/dts/rk3288-veyron-jerry.dts | 8 ++++++++ arch/arm/boot/dts/rk3288-veyron-speedy.dts | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rk3288-veyron-jerry.dts index 1a9bef1303d3..f6b2eaaebb9a 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts +++ b/arch/arm/boot/dts/rk3288-veyron-jerry.dts @@ -88,6 +88,14 @@ }; }; +&backlight { + power-supply = <&backlight_regulator>; +}; + +&panel { + power-supply= <&panel_regulator>; +}; + &rk808 { pinctrl-names = "default"; pinctrl-0 = <&pmic_int_l>; diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rk3288-veyron-speedy.dts index 90aa145404b5..a0d033f6fe52 100644 --- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts +++ b/arch/arm/boot/dts/rk3288-veyron-speedy.dts @@ -89,6 +89,10 @@ }; }; +&backlight { + power-supply = <&backlight_regulator>; +}; + &cpu_alert0 { temperature = <65000>; }; @@ -104,6 +108,10 @@ force-hpd; }; +&panel { + power-supply= <&panel_regulator>; +}; + &rk808 { pinctrl-names = "default"; pinctrl-0 = <&pmic_int_l>; -- GitLab From 37aedb29b9f053215a5a0dfb15ecc49af67c1fbc Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 14 Dec 2015 17:18:42 +0100 Subject: [PATCH 1662/9938] ARM: dts: rockchip: enable the eDP on rk3288 veyron devices After hooking up panel and backlight informations, enable the edp on veyron chromebooks now. Signed-off-by: Heiko Stuebner Tested-by: Douglas Anderson --- .../boot/dts/rk3288-veyron-chromebook.dtsi | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi index 7563d3d156d7..2958c36d12a0 100644 --- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi @@ -111,6 +111,14 @@ status = "okay"; power-supply = <&vcc33_lcd>; backlight = <&backlight>; + + ports { + panel_in: port { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; }; /* A non-regulated voltage from power supply or battery */ @@ -154,6 +162,29 @@ }; }; +&edp { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&edp_hpd>; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + edp_out_panel: endpoint { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + +&edp_phy { + status = "okay"; +}; + &gpio_keys { pinctrl-0 = <&pwr_key_l &ap_lid_int_l>; lid { @@ -166,6 +197,10 @@ }; }; +&pwm0 { + status = "okay"; +}; + &rk808 { vcc11-supply = <&vcc_5v>; @@ -219,6 +254,14 @@ }; }; +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + &pinctrl { pinctrl-0 = < /* Common for sleep and wake, but no owners */ -- GitLab From fbf15046f12d6c8d5821c0dc5bf3ffc55a132243 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 30 Mar 2016 17:33:24 +0200 Subject: [PATCH 1663/9938] ARM: dts: rockchip: move rk3036 memory definition to board files The amount of available memory is clearly a board-specific value, so the core per-soc dtsi should not define a default of any sort. Therefore move the memory-nodes to the two board files. Also fix the amount of memory on Kylin (512MB instead of 1GB). While in most cases the bootloader will override this with the actual amount of memory, there is no need to keep known wrong values in the board-dts. Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036-evb.dts | 5 +++++ arch/arm/boot/dts/rk3036-kylin.dts | 5 +++++ arch/arm/boot/dts/rk3036.dtsi | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/rk3036-evb.dts b/arch/arm/boot/dts/rk3036-evb.dts index b3d6ec87f615..8db9e9b197a2 100644 --- a/arch/arm/boot/dts/rk3036-evb.dts +++ b/arch/arm/boot/dts/rk3036-evb.dts @@ -45,6 +45,11 @@ / { model = "Rockchip RK3036 Evaluation board"; compatible = "rockchip,rk3036-evb", "rockchip,rk3036"; + + memory { + device_type = "memory"; + reg = <0x60000000 0x40000000>; + }; }; &emac { diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rk3036-kylin.dts index 951f15d675c7..1df1557a46c3 100644 --- a/arch/arm/boot/dts/rk3036-kylin.dts +++ b/arch/arm/boot/dts/rk3036-kylin.dts @@ -46,6 +46,11 @@ model = "Rockchip RK3036 KylinBoard"; compatible = "rockchip,rk3036-kylin", "rockchip,rk3036"; + memory { + device_type = "memory"; + reg = <0x60000000 0x20000000>; + }; + leds: gpio-leds { compatible = "gpio-leds"; diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index fa6b5cf31aa7..843d2be2e4e9 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -63,11 +63,6 @@ spi = &spi; }; - memory { - device_type = "memory"; - reg = <0x60000000 0x40000000>; - }; - cpus { #address-cells = <1>; #size-cells = <0>; -- GitLab From 453e16e8e8b96821111e8d90252f4df8ec418eea Mon Sep 17 00:00:00 2001 From: Deepthi Kavalur Date: Fri, 1 Apr 2016 03:56:01 -0700 Subject: [PATCH 1664/9938] i40e: Inserting a HW capability display info Display MSIx vector count for HW capabilities. Change-ID: I4b41e9b50360cf660e7fbcb85b9390fedcf313b1 Signed-off-by: Deepthi Kavalur Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index ebcc0d3ecbfb..f3c1d8890cbb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -3080,6 +3080,9 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, break; case I40E_AQ_CAP_ID_MSIX: p->num_msix_vectors = number; + i40e_debug(hw, I40E_DEBUG_INIT, + "HW Capability: MSIX vector count = %d\n", + p->num_msix_vectors); break; case I40E_AQ_CAP_ID_VF_MSIX: p->num_msix_vectors_vf = number; -- GitLab From 89dd05512b79ee9ba0950f1ba1fb8077ec898ea2 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 1 Apr 2016 03:56:02 -0700 Subject: [PATCH 1665/9938] i40e: Leave debug_mask cleared at init Don't set our internal debug_mask at startup unless we get specific signal to from the debug module parameter. This should take care of the issue with all the device capabilities getting printed even when we hadn't asked for the debug info. Change-ID: I7fbc6bd8b11ed9b0631ec018ff36015a04100b6c Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d6147f899062..86abd086ccbd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8438,7 +8438,6 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE, (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)); - pf->hw.debug_mask = pf->msg_enable | I40E_DEBUG_DIAG; if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) { if (I40E_DEBUG_USER & debug) pf->hw.debug_mask = debug; -- GitLab From 30728c5bdf2ac6618eebf6949a2e59b3c4cf640f Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Fri, 1 Apr 2016 03:56:03 -0700 Subject: [PATCH 1666/9938] i40e: Move HW flush This patch moves the HW flush routine to the end of the reset flow, after the completion of writing to the device VFLR registers- the benefit is to avoid problems in the passthrough routines. Change-ID: Ieb56866f21895e6c1fc514b7328c3df79807a57c Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 9924503c88f5..f2a9c14829ca 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -941,6 +941,7 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) reg_idx = (hw->func_caps.vf_base_id + vf->vf_id) / 32; bit_idx = (hw->func_caps.vf_base_id + vf->vf_id) % 32; wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx)); + i40e_flush(hw); if (i40e_quiesce_vf_pci(vf)) dev_err(&pf->pdev->dev, "VF %d PCI transactions stuck\n", -- GitLab From d1bd743b5b4d675e739b574284d1412ba996fe07 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 1 Apr 2016 03:56:04 -0700 Subject: [PATCH 1667/9938] i40e/i40evf: Move stack var deeper A local variable could move down inside the context where it is used. Change-ID: I9caba9e1eacf921037077f2665cbce83fd8e95d6 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 ++- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 5d5fa5359a1d..76a48e9c859b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2408,7 +2408,7 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, unsigned char *hdr; } l4; unsigned char *exthdr; - u32 offset, cmd = 0, tunnel = 0; + u32 offset, cmd = 0; __be16 frag_off; u8 l4_proto = 0; @@ -2422,6 +2422,7 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, offset = ((ip.hdr - skb->data) / 2) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; if (skb->encapsulation) { + u32 tunnel = 0; /* define outer network header type */ if (*tx_flags & I40E_TX_FLAGS_IPV4) { tunnel |= (*tx_flags & I40E_TX_FLAGS_TSO) ? diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 04aabc52ba0d..d633dcf4a882 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1633,7 +1633,7 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, unsigned char *hdr; } l4; unsigned char *exthdr; - u32 offset, cmd = 0, tunnel = 0; + u32 offset, cmd = 0; __be16 frag_off; u8 l4_proto = 0; @@ -1647,6 +1647,7 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, offset = ((ip.hdr - skb->data) / 2) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; if (skb->encapsulation) { + u32 tunnel = 0; /* define outer network header type */ if (*tx_flags & I40E_TX_FLAGS_IPV4) { tunnel |= (*tx_flags & I40E_TX_FLAGS_TSO) ? -- GitLab From 84b079928a10559ebc6679e1e973a3ee5b20ba83 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 1 Apr 2016 03:56:05 -0700 Subject: [PATCH 1668/9938] i40e/i40evf: Drop unused tx_ring argument Some of the tx_ring arguments can be deleted since they are not used. Change-ID: I99275b0f191d7f63ec2f05061919904940c36f31 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 6 ++---- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 76a48e9c859b..f4e4d3d098dc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2252,15 +2252,13 @@ static inline int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, /** * i40e_tso - set up the tso context descriptor - * @tx_ring: ptr to the ring to send * @skb: ptr to the skb we're sending * @hdr_len: ptr to the size of the packet header * @cd_type_cmd_tso_mss: Quad Word 1 * * Returns 0 if no TSO can happen, 1 if tso is going, or error **/ -static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, - u8 *hdr_len, u64 *cd_type_cmd_tso_mss) +static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss) { u64 cd_cmd, cd_tso_len, cd_mss; union { @@ -2932,7 +2930,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, else if (protocol == htons(ETH_P_IPV6)) tx_flags |= I40E_TX_FLAGS_IPV6; - tso = i40e_tso(tx_ring, skb, &hdr_len, &cd_type_cmd_tso_mss); + tso = i40e_tso(skb, &hdr_len, &cd_type_cmd_tso_mss); if (tso < 0) goto out_drop; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index d633dcf4a882..ec1f4479d72e 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1519,15 +1519,13 @@ static inline int i40evf_tx_prepare_vlan_flags(struct sk_buff *skb, /** * i40e_tso - set up the tso context descriptor - * @tx_ring: ptr to the ring to send * @skb: ptr to the skb we're sending * @hdr_len: ptr to the size of the packet header * @cd_type_cmd_tso_mss: Quad Word 1 * * Returns 0 if no TSO can happen, 1 if tso is going, or error **/ -static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, - u8 *hdr_len, u64 *cd_type_cmd_tso_mss) +static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss) { u64 cd_cmd, cd_tso_len, cd_mss; union { @@ -2150,7 +2148,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, else if (protocol == htons(ETH_P_IPV6)) tx_flags |= I40E_TX_FLAGS_IPV6; - tso = i40e_tso(tx_ring, skb, &hdr_len, &cd_type_cmd_tso_mss); + tso = i40e_tso(skb, &hdr_len, &cd_type_cmd_tso_mss); if (tso < 0) goto out_drop; -- GitLab From 1f15d66712bb64e39fe2c23b1b32f68f9e1d4ee7 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 1 Apr 2016 03:56:06 -0700 Subject: [PATCH 1669/9938] i40e/i40evf: Faster RX via avoiding FCoE As it turns out, calling into other files from hot path hurts performance a lot. In this case the majority of the time we call "check FCoE" and the packet is *not* FCoE, but this call was taking 5% of our total cycles spent on receive. Change-ID: I080552c26e7060bc7b78504dc2763f6f0b3d8c76 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 12 +----------- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 ++++++-- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 10 ++++++++++ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 4 +++- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 10 ++++++++++ 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 92d2208d13c7..58e6c1570335 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Intel Ethernet Controller XL710 Family Linux Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -37,16 +37,6 @@ #include "i40e.h" #include "i40e_fcoe.h" -/** - * i40e_rx_is_fcoe - returns true if the rx packet type is FCoE - * @ptype: the packet type field from rx descriptor write-back - **/ -static inline bool i40e_rx_is_fcoe(u16 ptype) -{ - return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) && - (ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER); -} - /** * i40e_fcoe_sof_is_class2 - returns true if this is a FC Class 2 SOF * @sof: the FCoE start of frame delimiter diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index f4e4d3d098dc..29ffed27e5a9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1703,7 +1703,9 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, const int budget) ? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0; #ifdef I40E_FCOE - if (!i40e_fcoe_handle_offload(rx_ring, rx_desc, skb)) { + if (unlikely( + i40e_rx_is_fcoe(rx_ptype) && + !i40e_fcoe_handle_offload(rx_ring, rx_desc, skb))) { dev_kfree_skb_any(skb); continue; } @@ -1834,7 +1836,9 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget) ? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0; #ifdef I40E_FCOE - if (!i40e_fcoe_handle_offload(rx_ring, rx_desc, skb)) { + if (unlikely( + i40e_rx_is_fcoe(rx_ptype) && + !i40e_fcoe_handle_offload(rx_ring, rx_desc, skb))) { dev_kfree_skb_any(skb); continue; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 9e654e611642..77ccdde56c0c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -448,4 +448,14 @@ static inline bool i40e_chk_linearize(struct sk_buff *skb, int count) return __i40e_chk_linearize(skb); } + +/** + * i40e_rx_is_fcoe - returns true if the Rx packet type is FCoE + * @ptype: the packet type field from Rx descriptor write-back + **/ +static inline bool i40e_rx_is_fcoe(u16 ptype) +{ + return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) && + (ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER); +} #endif /* _I40E_TXRX_H_ */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index ec1f4479d72e..0c912a4999db 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1160,7 +1160,9 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, const int budget) ? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0; #ifdef I40E_FCOE - if (!i40e_fcoe_handle_offload(rx_ring, rx_desc, skb)) { + if (unlikely( + i40e_rx_is_fcoe(rx_ptype) && + !i40e_fcoe_handle_offload(rx_ring, rx_desc, skb))) { dev_kfree_skb_any(skb); continue; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index 3ec0ea5ea3db..84c28aa64fdf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -430,4 +430,14 @@ static inline bool i40e_chk_linearize(struct sk_buff *skb, int count) return __i40evf_chk_linearize(skb); } + +/** + * i40e_rx_is_fcoe - returns true if the Rx packet type is FCoE + * @ptype: the packet type field from Rx descriptor write-back + **/ +static inline bool i40e_rx_is_fcoe(u16 ptype) +{ + return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) && + (ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER); +} #endif /* _I40E_TXRX_H_ */ -- GitLab From c3bbbd2002b9565475721bb17b17f48ef5927498 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Fri, 1 Apr 2016 03:56:07 -0700 Subject: [PATCH 1670/9938] i40e: Patch to support trusted VF This patch adds hook to support changing a VF from not-trusted to trusted and vice-versa. Fixed the wrappers and function prototype. Changed the dmesg to reflex the current state better. This patch also disables turning on/off trusted VF in MFP mode. Change-ID: Ibcd910935c01f0be1f3fdd6d427230291ee92ebe Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 42 +++++++++++++++++++ .../ethernet/intel/i40e/i40e_virtchnl_pf.h | 2 + 3 files changed, 45 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 86abd086ccbd..627acf0c5fea 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9069,6 +9069,7 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_get_vf_config = i40e_ndo_get_vf_config, .ndo_set_vf_link_state = i40e_ndo_set_vf_link_state, .ndo_set_vf_spoofchk = i40e_ndo_set_vf_spoofchk, + .ndo_set_vf_trust = i40e_ndo_set_vf_trust, #if IS_ENABLED(CONFIG_VXLAN) .ndo_add_vxlan_port = i40e_add_vxlan_port, .ndo_del_vxlan_port = i40e_del_vxlan_port, diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index f2a9c14829ca..b3539660f4f1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2763,3 +2763,45 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable) out: return ret; } + +/** + * i40e_ndo_set_vf_trust + * @netdev: network interface device structure of the pf + * @vf_id: VF identifier + * @setting: trust setting + * + * Enable or disable VF trust setting + **/ +int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; + struct i40e_vf *vf; + int ret = 0; + + /* validate the request */ + if (vf_id >= pf->num_alloc_vfs) { + dev_err(&pf->pdev->dev, "Invalid VF Identifier %d\n", vf_id); + return -EINVAL; + } + + if (pf->flags & I40E_FLAG_MFP_ENABLED) { + dev_err(&pf->pdev->dev, "Trusted VF not supported in MFP mode.\n"); + return -EINVAL; + } + + vf = &pf->vf[vf_id]; + + if (!vf) + return -EINVAL; + if (setting == vf->trusted) + goto out; + + vf->trusted = setting; + i40e_vc_notify_vf_reset(vf); + i40e_reset_vf(vf, false); + dev_info(&pf->pdev->dev, "VF %u is now %strusted\n", + vf_id, setting ? "" : "un"); +out: + return ret; +} diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index e7b2fba0309e..838cbd2299a4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -88,6 +88,7 @@ struct i40e_vf { struct i40e_virtchnl_ether_addr default_fcoe_addr; u16 port_vlan_id; bool pf_set_mac; /* The VMM admin set the VF MAC address */ + bool trusted; /* VSI indices - actual VSI pointers are maintained in the PF structure * When assigned, these will be non-zero, because VSI 0 is always @@ -127,6 +128,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos); int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, int max_tx_rate); +int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting); int i40e_ndo_get_vf_config(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi); int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link); -- GitLab From 14c5f5d264c3ee28e8ec9fd4dffb29f5d1ea1d02 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 1 Apr 2016 03:56:08 -0700 Subject: [PATCH 1671/9938] i40e: Restrict VF poll mode to only single function mode devices The VFs can request their queues to be set up into polling mode, rather than interrupt mode, which works well for supporting things like DPDK, but this should not be available when working in an multi-function support device. Change-ID: Id36792e4e7422db8f2033336507211f68f14ff6f Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index b3539660f4f1..30f8cbe6b54b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1362,8 +1362,16 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2; } - if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) { + if (pf->flags & I40E_FLAG_MFP_ENABLED) { + dev_err(&pf->pdev->dev, + "VF %d requested polling mode: this feature is supported only when the device is running in single function per port (SFP) mode\n", + vf->vf_id); + ret = I40E_ERR_PARAM; + goto err; + } vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING; + } if (pf->flags & I40E_FLAG_WB_ON_ITR_CAPABLE) { if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) -- GitLab From 437f82a2290ed94f0d6a86b749101f1ad5ed6231 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 1 Apr 2016 03:56:09 -0700 Subject: [PATCH 1672/9938] i40e: Move NVM variable out of AQ struct The NVM update status info should stay collected together, not spread across different structs. Change-ID: Ic16f9e9fd79945d865bb7226184c889884585025 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 6 +++--- drivers/net/ethernet/intel/i40e/i40e_adminq.h | 1 - drivers/net/ethernet/intel/i40e/i40e_nvm.c | 12 ++++++------ drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_adminq.h | 1 - drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index df8e2fd6a649..e8278e1d6130 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -624,7 +624,7 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) /* pre-emptive resource lock release */ i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); - hw->aq.nvm_release_on_done = false; + hw->nvm_release_on_done = false; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; ret_code = i40e_aq_set_hmc_resource_profile(hw, @@ -1024,9 +1024,9 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, hw->aq.arq.next_to_use = ntu; if (i40e_is_nvm_update_op(&e->desc)) { - if (hw->aq.nvm_release_on_done) { + if (hw->nvm_release_on_done) { i40e_release_nvm(hw); - hw->aq.nvm_release_on_done = false; + hw->nvm_release_on_done = false; } switch (hw->nvmupd_state) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index 12fbbddea299..d92aad38afdc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -97,7 +97,6 @@ struct i40e_adminq_info { u32 fw_build; /* firmware build number */ u16 api_maj_ver; /* api major version */ u16 api_min_ver; /* api minor version */ - bool nvm_release_on_done; struct mutex asq_mutex; /* Send queue lock */ struct mutex arq_mutex; /* Receive queue lock */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 5730f8091e1b..1ae29ac8c310 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -696,7 +696,7 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n", i40e_nvm_update_state_str[upd_cmd], hw->nvmupd_state, - hw->aq.nvm_release_on_done, + hw->nvm_release_on_done, cmd->command, cmd->config, cmd->offset, cmd->data_size); if (upd_cmd == I40E_NVMUPD_INVALID) { @@ -799,7 +799,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, if (status) { i40e_release_nvm(hw); } else { - hw->aq.nvm_release_on_done = true; + hw->nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } } @@ -815,7 +815,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, if (status) { i40e_release_nvm(hw); } else { - hw->aq.nvm_release_on_done = true; + hw->nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } } @@ -849,7 +849,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, -EIO; i40e_release_nvm(hw); } else { - hw->aq.nvm_release_on_done = true; + hw->nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } } @@ -953,7 +953,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, -EIO; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; } else { - hw->aq.nvm_release_on_done = true; + hw->nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } break; @@ -980,7 +980,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, -EIO; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; } else { - hw->aq.nvm_release_on_done = true; + hw->nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } break; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 3335f9d13374..bf693580f9c4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -549,6 +549,7 @@ struct i40e_hw { enum i40e_nvmupd_state nvmupd_state; struct i40e_aq_desc nvm_wb_desc; struct i40e_virt_mem nvm_buff; + bool nvm_release_on_done; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h index a3eae5d9a2bd..1f9b3b5d946d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h @@ -97,7 +97,6 @@ struct i40e_adminq_info { u32 fw_build; /* firmware build number */ u16 api_maj_ver; /* api major version */ u16 api_min_ver; /* api minor version */ - bool nvm_release_on_done; struct mutex asq_mutex; /* Send queue lock */ struct mutex arq_mutex; /* Receive queue lock */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 301fe2b6dd03..d68e017079e3 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -522,6 +522,7 @@ struct i40e_hw { enum i40e_nvmupd_state nvmupd_state; struct i40e_aq_desc nvm_wb_desc; struct i40e_virt_mem nvm_buff; + bool nvm_release_on_done; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ -- GitLab From 585954f8b808def857771037392c1621f167fa92 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 1 Apr 2016 03:56:10 -0700 Subject: [PATCH 1673/9938] i40e: Add RSS configuration to virtual channel Add opcodes and structures to support RSS configuration by PF driver on behalf of the VF drivers. This reduces complexity in the VF driver and allows us to support future hardware designs without modifying the VF driver. Change-ID: I8c75765c630eacb71f95967f1109a198542593ac Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/i40e/i40e_virtchnl.h | 45 +++++++++++++++++-- .../net/ethernet/intel/i40evf/i40e_virtchnl.h | 45 +++++++++++++++++-- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h index ab866cf3dc18..c92a3bdee229 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h @@ -80,10 +80,15 @@ enum i40e_virtchnl_ops { I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14, I40E_VIRTCHNL_OP_GET_STATS = 15, I40E_VIRTCHNL_OP_FCOE = 16, - I40E_VIRTCHNL_OP_EVENT = 17, + I40E_VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */ I40E_VIRTCHNL_OP_IWARP = 20, I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21, I40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22, + I40E_VIRTCHNL_OP_CONFIG_RSS_KEY = 23, + I40E_VIRTCHNL_OP_CONFIG_RSS_LUT = 24, + I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25, + I40E_VIRTCHNL_OP_SET_RSS_HENA = 26, + }; /* Virtual channel message descriptor. This overlays the admin queue @@ -157,6 +162,7 @@ struct i40e_virtchnl_vsi_resource { #define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000 #define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 0x00040000 +#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000 struct i40e_virtchnl_vf_resource { u16 num_vsis; @@ -165,8 +171,8 @@ struct i40e_virtchnl_vf_resource { u16 max_mtu; u32 vf_offload_flags; - u32 max_fcoe_contexts; - u32 max_fcoe_filters; + u32 rss_key_size; + u32 rss_lut_size; struct i40e_virtchnl_vsi_resource vsi_res[1]; }; @@ -325,6 +331,39 @@ struct i40e_virtchnl_promisc_info { * PF replies with struct i40e_eth_stats in an external buffer. */ +/* I40E_VIRTCHNL_OP_CONFIG_RSS_KEY + * I40E_VIRTCHNL_OP_CONFIG_RSS_LUT + * VF sends these messages to configure RSS. Only supported if both PF + * and VF drivers set the I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF bit during + * configuration negotiation. If this is the case, then the RSS fields in + * the VF resource struct are valid. + * Both the key and LUT are initialized to 0 by the PF, meaning that + * RSS is effectively disabled until set up by the VF. + */ +struct i40e_virtchnl_rss_key { + u16 vsi_id; + u16 key_len; + u8 key[1]; /* RSS hash key, packed bytes */ +}; + +struct i40e_virtchnl_rss_lut { + u16 vsi_id; + u16 lut_entries; + u8 lut[1]; /* RSS lookup table*/ +}; + +/* I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS + * I40E_VIRTCHNL_OP_SET_RSS_HENA + * VF sends these messages to get and set the hash filter enable bits for RSS. + * By default, the PF sets these to all possible traffic types that the + * hardware supports. The VF can query this value if it wants to change the + * traffic types that are hashed by the hardware. + * Traffic types are defined in the i40e_filter_pctype enum in i40e_type.h + */ +struct i40e_virtchnl_rss_hena { + u64 hena; +}; + /* I40E_VIRTCHNL_OP_EVENT * PF sends this message to inform the VF driver of events that may affect it. * No direct response is expected from the VF, though it may generate other diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h index 3b9d2037456c..f04ce6cb70dc 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h @@ -80,7 +80,12 @@ enum i40e_virtchnl_ops { I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14, I40E_VIRTCHNL_OP_GET_STATS = 15, I40E_VIRTCHNL_OP_FCOE = 16, - I40E_VIRTCHNL_OP_EVENT = 17, + I40E_VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */ + I40E_VIRTCHNL_OP_CONFIG_RSS_KEY = 23, + I40E_VIRTCHNL_OP_CONFIG_RSS_LUT = 24, + I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25, + I40E_VIRTCHNL_OP_SET_RSS_HENA = 26, + }; /* Virtual channel message descriptor. This overlays the admin queue @@ -154,6 +159,7 @@ struct i40e_virtchnl_vsi_resource { #define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000 #define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 0x00040000 +#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000 struct i40e_virtchnl_vf_resource { u16 num_vsis; @@ -162,8 +168,8 @@ struct i40e_virtchnl_vf_resource { u16 max_mtu; u32 vf_offload_flags; - u32 max_fcoe_contexts; - u32 max_fcoe_filters; + u32 rss_key_size; + u32 rss_lut_size; struct i40e_virtchnl_vsi_resource vsi_res[1]; }; @@ -322,6 +328,39 @@ struct i40e_virtchnl_promisc_info { * PF replies with struct i40e_eth_stats in an external buffer. */ +/* I40E_VIRTCHNL_OP_CONFIG_RSS_KEY + * I40E_VIRTCHNL_OP_CONFIG_RSS_LUT + * VF sends these messages to configure RSS. Only supported if both PF + * and VF drivers set the I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF bit during + * configuration negotiation. If this is the case, then the RSS fields in + * the VF resource struct are valid. + * Both the key and LUT are initialized to 0 by the PF, meaning that + * RSS is effectively disabled until set up by the VF. + */ +struct i40e_virtchnl_rss_key { + u16 vsi_id; + u16 key_len; + u8 key[1]; /* RSS hash key, packed bytes */ +}; + +struct i40e_virtchnl_rss_lut { + u16 vsi_id; + u16 lut_entries; + u8 lut[1]; /* RSS lookup table*/ +}; + +/* I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS + * I40E_VIRTCHNL_OP_SET_RSS_HENA + * VF sends these messages to get and set the hash filter enable bits for RSS. + * By default, the PF sets these to all possible traffic types that the + * hardware supports. The VF can query this value if it wants to change the + * traffic types that are hashed by the hardware. + * Traffic types are defined in the i40e_filter_pctype enum in i40e_type.h + */ +struct i40e_virtchnl_rss_hena { + u64 hena; +}; + /* I40E_VIRTCHNL_OP_EVENT * PF sends this message to inform the VF driver of events that may affect it. * No direct response is expected from the VF, though it may generate other -- GitLab From bab2fb60dcdd0f9d8715749d056ddd6c465b1875 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 1 Apr 2016 03:56:11 -0700 Subject: [PATCH 1674/9938] i40e: Move NVM event wait check to NVM code The logic that checks AQ events for NVM done events is better kept in nvm.c with the rest of the nvmupdate handling code. Change-ID: I2ea58980df8ecaa3726b28a37bff3dfcb8df03dc Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 31 +------------------ drivers/net/ethernet/intel/i40e/i40e_nvm.c | 31 +++++++++++++++++++ .../net/ethernet/intel/i40e/i40e_prototype.h | 1 + 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index e8278e1d6130..43bb4139d896 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -32,16 +32,6 @@ static void i40e_resume_aq(struct i40e_hw *hw); -/** - * i40e_is_nvm_update_op - return true if this is an NVM update operation - * @desc: API request descriptor - **/ -static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc) -{ - return (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_erase)) || - (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_update)); -} - /** * i40e_adminq_init_regs - Initialize AdminQ registers * @hw: pointer to the hardware structure @@ -1023,26 +1013,7 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, hw->aq.arq.next_to_clean = ntc; hw->aq.arq.next_to_use = ntu; - if (i40e_is_nvm_update_op(&e->desc)) { - if (hw->nvm_release_on_done) { - i40e_release_nvm(hw); - hw->nvm_release_on_done = false; - } - - switch (hw->nvmupd_state) { - case I40E_NVMUPD_STATE_INIT_WAIT: - hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; - break; - - case I40E_NVMUPD_STATE_WRITE_WAIT: - hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; - break; - - default: - break; - } - } - + i40e_nvmupd_check_wait_event(hw, le16_to_cpu(e->desc.opcode)); clean_arq_element_out: /* Set pending if needed, unlock and return */ if (pending) diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 1ae29ac8c310..f2cea3d25de3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -1029,6 +1029,37 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, return status; } +/** + * i40e_nvmupd_check_wait_event - handle NVM update operation events + * @hw: pointer to the hardware structure + * @opcode: the event that just happened + **/ +void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode) +{ + if (opcode == i40e_aqc_opc_nvm_erase || + opcode == i40e_aqc_opc_nvm_update) { + i40e_debug(hw, I40E_DEBUG_NVM, + "NVMUPD: clearing wait on opcode 0x%04x\n", opcode); + if (hw->nvm_release_on_done) { + i40e_release_nvm(hw); + hw->nvm_release_on_done = false; + } + + switch (hw->nvmupd_state) { + case I40E_NVMUPD_STATE_INIT_WAIT: + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + break; + + case I40E_NVMUPD_STATE_WRITE_WAIT: + hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; + break; + + default: + break; + } + } +} + /** * i40e_nvmupd_validate_command - Validate given command * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index d51eee5bf79a..134035f53f2c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -308,6 +308,7 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw, i40e_status i40e_nvmupd_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *); +void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode); void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status); extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[]; -- GitLab From 17a035be959ef0316ec86adb0c82ed3f057a853b Mon Sep 17 00:00:00 2001 From: Kiran Patil Date: Mon, 4 Apr 2016 07:01:10 -0700 Subject: [PATCH 1675/9938] i40e: Input set mask constants for RSS, flow director, and flex bytes Add defines for input set mask (RSS, flow director, flexible payload), including defines specific to IPv6. Change-ID: Ie95ef7d0916a4d6ca011c194283f959774c8dce9 Signed-off-by: Kiran Patil Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_type.h | 33 +++++++++++++++ drivers/net/ethernet/intel/i40evf/i40e_type.h | 42 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index bf693580f9c4..793036b259e5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1534,4 +1534,37 @@ struct i40e_lldp_variables { /* RSS Hash Table Size */ #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000 + +/* INPUT SET MASK for RSS, flow director, and flexible payload */ +#define I40E_L3_SRC_SHIFT 47 +#define I40E_L3_SRC_MASK (0x3ULL << I40E_L3_SRC_SHIFT) +#define I40E_L3_V6_SRC_SHIFT 43 +#define I40E_L3_V6_SRC_MASK (0xFFULL << I40E_L3_V6_SRC_SHIFT) +#define I40E_L3_DST_SHIFT 35 +#define I40E_L3_DST_MASK (0x3ULL << I40E_L3_DST_SHIFT) +#define I40E_L3_V6_DST_SHIFT 35 +#define I40E_L3_V6_DST_MASK (0xFFULL << I40E_L3_V6_DST_SHIFT) +#define I40E_L4_SRC_SHIFT 34 +#define I40E_L4_SRC_MASK (0x1ULL << I40E_L4_SRC_SHIFT) +#define I40E_L4_DST_SHIFT 33 +#define I40E_L4_DST_MASK (0x1ULL << I40E_L4_DST_SHIFT) +#define I40E_VERIFY_TAG_SHIFT 31 +#define I40E_VERIFY_TAG_MASK (0x3ULL << I40E_VERIFY_TAG_SHIFT) + +#define I40E_FLEX_50_SHIFT 13 +#define I40E_FLEX_50_MASK (0x1ULL << I40E_FLEX_50_SHIFT) +#define I40E_FLEX_51_SHIFT 12 +#define I40E_FLEX_51_MASK (0x1ULL << I40E_FLEX_51_SHIFT) +#define I40E_FLEX_52_SHIFT 11 +#define I40E_FLEX_52_MASK (0x1ULL << I40E_FLEX_52_SHIFT) +#define I40E_FLEX_53_SHIFT 10 +#define I40E_FLEX_53_MASK (0x1ULL << I40E_FLEX_53_SHIFT) +#define I40E_FLEX_54_SHIFT 9 +#define I40E_FLEX_54_MASK (0x1ULL << I40E_FLEX_54_SHIFT) +#define I40E_FLEX_55_SHIFT 8 +#define I40E_FLEX_55_MASK (0x1ULL << I40E_FLEX_55_SHIFT) +#define I40E_FLEX_56_SHIFT 7 +#define I40E_FLEX_56_MASK (0x1ULL << I40E_FLEX_56_SHIFT) +#define I40E_FLEX_57_SHIFT 6 +#define I40E_FLEX_57_MASK (0x1ULL << I40E_FLEX_57_SHIFT) #endif /* _I40E_TYPE_H_ */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index d68e017079e3..4a78c18e0b7b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -1330,4 +1330,46 @@ enum i40e_reset_type { /* RSS Hash Table Size */ #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000 + +/* INPUT SET MASK for RSS, flow director and flexible payload */ +#define I40E_FD_INSET_L3_SRC_SHIFT 47 +#define I40E_FD_INSET_L3_SRC_WORD_MASK (0x3ULL << \ + I40E_FD_INSET_L3_SRC_SHIFT) +#define I40E_FD_INSET_L3_DST_SHIFT 35 +#define I40E_FD_INSET_L3_DST_WORD_MASK (0x3ULL << \ + I40E_FD_INSET_L3_DST_SHIFT) +#define I40E_FD_INSET_L4_SRC_SHIFT 34 +#define I40E_FD_INSET_L4_SRC_WORD_MASK (0x1ULL << \ + I40E_FD_INSET_L4_SRC_SHIFT) +#define I40E_FD_INSET_L4_DST_SHIFT 33 +#define I40E_FD_INSET_L4_DST_WORD_MASK (0x1ULL << \ + I40E_FD_INSET_L4_DST_SHIFT) +#define I40E_FD_INSET_VERIFY_TAG_SHIFT 31 +#define I40E_FD_INSET_VERIFY_TAG_WORD_MASK (0x3ULL << \ + I40E_FD_INSET_VERIFY_TAG_SHIFT) + +#define I40E_FD_INSET_FLEX_WORD50_SHIFT 17 +#define I40E_FD_INSET_FLEX_WORD50_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD50_SHIFT) +#define I40E_FD_INSET_FLEX_WORD51_SHIFT 16 +#define I40E_FD_INSET_FLEX_WORD51_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD51_SHIFT) +#define I40E_FD_INSET_FLEX_WORD52_SHIFT 15 +#define I40E_FD_INSET_FLEX_WORD52_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD52_SHIFT) +#define I40E_FD_INSET_FLEX_WORD53_SHIFT 14 +#define I40E_FD_INSET_FLEX_WORD53_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD53_SHIFT) +#define I40E_FD_INSET_FLEX_WORD54_SHIFT 13 +#define I40E_FD_INSET_FLEX_WORD54_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD54_SHIFT) +#define I40E_FD_INSET_FLEX_WORD55_SHIFT 12 +#define I40E_FD_INSET_FLEX_WORD55_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD55_SHIFT) +#define I40E_FD_INSET_FLEX_WORD56_SHIFT 11 +#define I40E_FD_INSET_FLEX_WORD56_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD56_SHIFT) +#define I40E_FD_INSET_FLEX_WORD57_SHIFT 10 +#define I40E_FD_INSET_FLEX_WORD57_MASK (0x1ULL << \ + I40E_FD_INSET_FLEX_WORD57_SHIFT) #endif /* _I40E_TYPE_H_ */ -- GitLab From 47c46778e1905721433a413b2522a8e2b3d6c354 Mon Sep 17 00:00:00 2001 From: Harshitha Ramamurthy Date: Fri, 1 Apr 2016 03:56:13 -0700 Subject: [PATCH 1676/9938] i40e/i40evf: Bump patch from 1.5.2 to 1.5.5 Signed-off-by: Harshitha Ramamurthy Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 627acf0c5fea..dc3b3939dd0a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -46,7 +46,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 5 -#define DRV_VERSION_BUILD 2 +#define DRV_VERSION_BUILD 5 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index f4dada02bbcf..4659ac2cf035 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -38,7 +38,7 @@ static const char i40evf_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 5 -#define DRV_VERSION_BUILD 2 +#define DRV_VERSION_BUILD 5 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) \ -- GitLab From ba6cc7f6f194e3645368f87d951bedd7e3b75f39 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 1 Apr 2016 13:34:31 -0700 Subject: [PATCH 1677/9938] i40evf: properly handle VLAN features Correctly set the VLAN feature flags after setting the rest of the netdev flags. And don't set them in hw_features, because these can't be controlled by the VF driver. Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/i40evf/i40evf_main.c | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 4659ac2cf035..9110319a8f00 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2323,29 +2323,20 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw) **/ int i40evf_process_config(struct i40evf_adapter *adapter) { + struct i40e_virtchnl_vf_resource *vfres = adapter->vf_res; struct net_device *netdev = adapter->netdev; int i; /* got VF config message back from PF, now we can parse it */ - for (i = 0; i < adapter->vf_res->num_vsis; i++) { - if (adapter->vf_res->vsi_res[i].vsi_type == I40E_VSI_SRIOV) - adapter->vsi_res = &adapter->vf_res->vsi_res[i]; + for (i = 0; i < vfres->num_vsis; i++) { + if (vfres->vsi_res[i].vsi_type == I40E_VSI_SRIOV) + adapter->vsi_res = &vfres->vsi_res[i]; } if (!adapter->vsi_res) { dev_err(&adapter->pdev->dev, "No LAN VSI found\n"); return -ENODEV; } - if (adapter->vf_res->vf_offload_flags - & I40E_VIRTCHNL_VF_OFFLOAD_VLAN) { - netdev->vlan_features = netdev->features & - ~(NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER); - netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER; - } netdev->features |= NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_IP_CSUM | @@ -2354,7 +2345,7 @@ int i40evf_process_config(struct i40evf_adapter *adapter) NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | - NETIF_F_GSO_GRE | + NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM | NETIF_F_GRO; @@ -2371,9 +2362,15 @@ int i40evf_process_config(struct i40evf_adapter *adapter) if (adapter->flags & I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE) netdev->features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; + /* always clear VLAN features because they can change at every reset */ + netdev->features &= ~(I40EVF_VLAN_FEATURES); /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features; - netdev->hw_features &= ~NETIF_F_RXCSUM; + + if (vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_VLAN) { + netdev->vlan_features = netdev->features; + netdev->features |= I40EVF_VLAN_FEATURES; + } adapter->vsi.id = adapter->vsi_res->vsi_id; -- GitLab From 5bd0c0202aca1003a244b13792c09b40f73eadc0 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 5 Apr 2016 16:25:07 +0200 Subject: [PATCH 1678/9938] net: intel: remove dead links The Kconfig for Intel NICs references two different URLs for the "Adapter & Driver ID Guide". Neither of those two links works. The current URL seems to be http://www.intel.com/content/www/us/en/support/network-and-i-o/ethernet-products/000005584.html but given it's apparently constantly changing, there's no point in having it in the help text. Just keep a generic pointer to http://support.intel.com. Hopefully, this one will have a longer live. It still works, at least. Furthermore, remove a link to "the latest Intel PRO/100 network driver for Linux", this has no place in the mainline kernel and the latest Linux driver it offers is from 2006, anyway. Signed-off-by: Jiri Benc Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/Kconfig | 80 ++++++------------------------ 1 file changed, 14 insertions(+), 66 deletions(-) diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 3772f3ac956e..714bd1014ddb 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -25,16 +25,13 @@ config E100 on the adapter. Look for a label that has a barcode and a number in the format 123456-001 (six digits hyphen three digits). - Use the above information and the Adapter & Driver ID Guide at: + Use the above information and the Adapter & Driver ID Guide that + can be located at: - + to identify the adapter. - For the latest Intel PRO/100 network driver for Linux, see: - - - More specific information on configuring the driver is in . @@ -47,12 +44,7 @@ config E1000 ---help--- This driver supports Intel(R) PRO/1000 gigabit ethernet family of adapters. For more information on how to identify your adapter, go - to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + to the Adapter & Driver ID Guide that can be located at: @@ -71,12 +63,8 @@ config E1000E This driver supports the PCI-Express Intel(R) PRO/1000 gigabit ethernet family of adapters. For PCI or PCI-X e1000 adapters, use the regular e1000 driver For more information on how to - identify your adapter, go to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + identify your adapter, go to the Adapter & Driver ID Guide that + can be located at: @@ -101,12 +89,7 @@ config IGB ---help--- This driver supports Intel(R) 82575/82576 gigabit ethernet family of adapters. For more information on how to identify your adapter, go - to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + to the Adapter & Driver ID Guide that can be located at: @@ -142,12 +125,7 @@ config IGBVF ---help--- This driver supports Intel(R) 82576 virtual functions. For more information on how to identify your adapter, go to the Adapter & - Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + Driver ID Guide that can be located at: @@ -164,12 +142,7 @@ config IXGB This driver supports Intel(R) PRO/10GbE family of adapters for PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver instead. For more information on how to identify your adapter, go - to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + to the Adapter & Driver ID Guide that can be located at: @@ -187,12 +160,7 @@ config IXGBE ---help--- This driver supports Intel(R) 10GbE PCI Express family of adapters. For more information on how to identify your adapter, go - to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + to the Adapter & Driver ID Guide that can be located at: @@ -243,12 +211,7 @@ config IXGBEVF ---help--- This driver supports Intel(R) PCI Express virtual functions for the Intel(R) ixgbe driver. For more information on how to identify your - adapter, go to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + adapter, go to the Adapter & Driver ID Guide that can be located at: @@ -266,12 +229,7 @@ config I40E ---help--- This driver supports Intel(R) Ethernet Controller XL710 Family of devices. For more information on how to identify your adapter, go - to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + to the Adapter & Driver ID Guide that can be located at: @@ -326,12 +284,7 @@ config I40EVF ---help--- This driver supports Intel(R) XL710 and X710 virtual functions. For more information on how to identify your adapter, go to the - Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + Adapter & Driver ID Guide that can be located at: @@ -347,12 +300,7 @@ config FM10K ---help--- This driver supports Intel(R) FM10000 Ethernet Switch Host Interface. For more information on how to identify your adapter, - go to the Adapter & Driver ID Guide at: - - - - For general information and support, go to the Intel support - website at: + go to the Adapter & Driver ID Guide that can be located at: -- GitLab From d99e366fc90c9b6e6197584ecd3a185441452b0c Mon Sep 17 00:00:00 2001 From: Arika Chen Date: Wed, 6 Apr 2016 21:02:11 -0700 Subject: [PATCH 1679/9938] Revert "igb: Fix a deadlock in igb_sriov_reinit" This reverts commit 3eb14ea8d958 ("igb: Fix a deadlock in igb_sriov_reinit") It is the same as commit f468adc944ef ("igb: missing rtnl_unlock in igb_sriov_reinit()") There is no rtnl_lock() in igb_resume before, rtnl_unlock will cause a deadlock. Signed-off-by: Arika Chen Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index ff0476c89438..8e96c35307fb 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -7579,7 +7579,6 @@ static int igb_resume(struct device *dev) if (igb_init_interrupt_scheme(adapter, true)) { dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); - rtnl_unlock(); return -ENOMEM; } -- GitLab From 6d54fb8a08a7b9ac06bbf4d7c41e6818d22e392f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 11 Sep 2015 09:48:03 +0100 Subject: [PATCH 1680/9938] ARM: multi_v7_defconfig: Enable ST's HW Random Number Generator Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/configs/multi_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index cc13a3735071..c25893ca784a 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -830,6 +830,8 @@ CONFIG_LOCKUP_DETECTOR=y CONFIG_CRYPTO_DEV_TEGRA_AES=y CONFIG_CPUFREQ_DT=y CONFIG_KEYSTONE_IRQ=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_ST=y CONFIG_CRYPTO_DEV_SUN4I_SS=m CONFIG_CRYPTO_DEV_ROCKCHIP=m CONFIG_ARM_CRYPTO=y -- GitLab From c7b4be8db8bc33ec60d21940b3d78b203cdffaac Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 6 Apr 2016 20:22:54 -0500 Subject: [PATCH 1681/9938] EDAC, altera: Add Arria10 OCRAM ECC support Add Arria10 On-Chip RAM ECC handling. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1459992174-8015-1-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 78 ++++++++++++++++++++++++++++++++++++++ drivers/edac/altera_edac.h | 35 +++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index f7ffc77998a4..11775dc0b139 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -550,6 +550,7 @@ module_platform_driver(altr_edac_driver); const struct edac_device_prv_data ocramecc_data; const struct edac_device_prv_data l2ecc_data; +const struct edac_device_prv_data a10_ocramecc_data; const struct edac_device_prv_data a10_l2ecc_data; static irqreturn_t altr_edac_device_handler(int irq, void *dev_id) @@ -674,6 +675,16 @@ static const struct file_operations altr_edac_device_inject_fops = { .llseek = generic_file_llseek, }; +static ssize_t altr_edac_a10_device_trig(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos); + +static const struct file_operations altr_edac_a10_device_inject_fops = { + .open = simple_open, + .write = altr_edac_a10_device_trig, + .llseek = generic_file_llseek, +}; + static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci, const struct edac_device_prv_data *priv) { @@ -701,6 +712,8 @@ static const struct of_device_id altr_edac_device_of_match[] = { #ifdef CONFIG_EDAC_ALTERA_OCRAM { .compatible = "altr,socfpga-ocram-ecc", .data = (void *)&ocramecc_data }, + { .compatible = "altr,socfpga-a10-ocram-ecc", + .data = (void *)&a10_ocramecc_data }, #endif {}, }; @@ -889,6 +902,24 @@ const struct edac_device_prv_data ocramecc_data = { .inject_fops = &altr_edac_device_inject_fops, }; +static irqreturn_t altr_edac_a10_ecc_irq(struct altr_edac_device_dev *dci, + bool sberr); + +const struct edac_device_prv_data a10_ocramecc_data = { + .setup = altr_check_ecc_deps, + .ce_clear_mask = ALTR_A10_ECC_SERRPENA, + .ue_clear_mask = ALTR_A10_ECC_DERRPENA, + .irq_status_mask = A10_SYSMGR_ECC_INTSTAT_OCRAM, + .dbgfs_name = "altr_ocram_trigger", + .ecc_enable_mask = ALTR_A10_OCRAM_ECC_EN_CTL, + .ecc_en_ofst = ALTR_A10_ECC_CTRL_OFST, + .ce_set_mask = ALTR_A10_ECC_TSERRA, + .ue_set_mask = ALTR_A10_ECC_TDERRA, + .set_err_ofst = ALTR_A10_ECC_INTTEST_OFST, + .ecc_irq_handler = altr_edac_a10_ecc_irq, + .inject_fops = &altr_edac_a10_device_inject_fops, +}; + #endif /* CONFIG_EDAC_ALTERA_OCRAM */ /********************* L2 Cache EDAC Device Functions ********************/ @@ -1007,6 +1038,50 @@ const struct edac_device_prv_data a10_l2ecc_data = { * Based on xgene_edac.c peripheral code. */ +static ssize_t altr_edac_a10_device_trig(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct edac_device_ctl_info *edac_dci = file->private_data; + struct altr_edac_device_dev *drvdata = edac_dci->pvt_info; + const struct edac_device_prv_data *priv = drvdata->data; + void __iomem *set_addr = (drvdata->base + priv->set_err_ofst); + unsigned long flags; + u8 trig_type; + + if (!user_buf || get_user(trig_type, user_buf)) + return -EFAULT; + + local_irq_save(flags); + if (trig_type == ALTR_UE_TRIGGER_CHAR) + writel(priv->ue_set_mask, set_addr); + else + writel(priv->ce_set_mask, set_addr); + /* Ensure the interrupt test bits are set */ + wmb(); + local_irq_restore(flags); + + return count; +} + +static irqreturn_t altr_edac_a10_ecc_irq(struct altr_edac_device_dev *dci, + bool sberr) +{ + void __iomem *base = dci->base; + + if (sberr) { + writel(ALTR_A10_ECC_SERRPENA, + base + ALTR_A10_ECC_INTSTAT_OFST); + edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name); + } else { + writel(ALTR_A10_ECC_DERRPENA, + base + ALTR_A10_ECC_INTSTAT_OFST); + edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name); + panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n"); + } + return IRQ_HANDLED; +} + static irqreturn_t altr_edac_a10_irq_handler(int irq, void *dev_id) { irqreturn_t rc = IRQ_NONE; @@ -1171,6 +1246,9 @@ static int altr_edac_a10_probe(struct platform_device *pdev) continue; if (of_device_is_compatible(child, "altr,socfpga-a10-l2-ecc")) altr_edac_a10_device_add(edac, child); + else if (of_device_is_compatible(child, + "altr,socfpga-a10-ocram-ecc")) + altr_edac_a10_device_add(edac, child); } return 0; diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index cb6b2b9079e8..42090f36ba6e 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h @@ -220,9 +220,41 @@ struct altr_sdram_mc_data { #define ALTR_L2_ECC_INJD BIT(2) /* Arria10 General ECC Block Module Defines */ +#define ALTR_A10_ECC_CTRL_OFST 0x08 +#define ALTR_A10_ECC_EN BIT(0) +#define ALTR_A10_ECC_INITA BIT(16) +#define ALTR_A10_ECC_INITB BIT(24) + +#define ALTR_A10_ECC_INITSTAT_OFST 0x0C +#define ALTR_A10_ECC_INITCOMPLETEA BIT(0) +#define ALTR_A10_ECC_INITCOMPLETEB BIT(8) + +#define ALTR_A10_ECC_ERRINTEN_OFST 0x10 +#define ALTR_A10_ECC_SERRINTEN BIT(0) + +#define ALTR_A10_ECC_INTSTAT_OFST 0x20 +#define ALTR_A10_ECC_SERRPENA BIT(0) +#define ALTR_A10_ECC_DERRPENA BIT(8) +#define ALTR_A10_ECC_ERRPENA_MASK (ALTR_A10_ECC_SERRPENA | \ + ALTR_A10_ECC_DERRPENA) +#define ALTR_A10_ECC_SERRPENB BIT(16) +#define ALTR_A10_ECC_DERRPENB BIT(24) +#define ALTR_A10_ECC_ERRPENB_MASK (ALTR_A10_ECC_SERRPENB | \ + ALTR_A10_ECC_DERRPENB) + +#define ALTR_A10_ECC_INTTEST_OFST 0x24 +#define ALTR_A10_ECC_TSERRA BIT(0) +#define ALTR_A10_ECC_TDERRA BIT(8) + +/* ECC Manager Defines */ +#define A10_SYSMGR_ECC_INTMASK_SET_OFST 0x94 +#define A10_SYSMGR_ECC_INTMASK_CLR_OFST 0x98 +#define A10_SYSMGR_ECC_INTMASK_OCRAM BIT(1) + #define A10_SYSMGR_ECC_INTSTAT_SERR_OFST 0x9C #define A10_SYSMGR_ECC_INTSTAT_DERR_OFST 0xA0 #define A10_SYSMGR_ECC_INTSTAT_L2 BIT(0) +#define A10_SYSMGR_ECC_INTSTAT_OCRAM BIT(1) #define A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST 0xA8 #define A10_SYSGMR_MPU_CLEAR_L2_ECC_SB BIT(15) @@ -245,6 +277,9 @@ struct altr_sdram_mc_data { #define ALTR_A10_L2_ECC_CE_INJ_MASK 0x00000101 #define ALTR_A10_L2_ECC_UE_INJ_MASK 0x00010101 +/* Arria 10 OCRAM ECC Management Group Defines */ +#define ALTR_A10_OCRAM_ECC_EN_CTL (BIT(1) | BIT(0)) + struct altr_edac_device_dev; struct edac_device_prv_data { -- GitLab From 2364d423a7b34bd972761eeed1f764c962980c23 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 6 Apr 2016 20:09:42 -0500 Subject: [PATCH 1682/9938] ARM: socfpga: Enable Arria10 OCRAM ECC on startup Enable ECC for Arria10 On-Chip RAM on machine startup. The ECC has to be enabled and memory initialized before data is stored in memory otherwise the ECC will fail on reads. Signed-off-by: Thor Thayer Acked-by: Dinh Nguyen Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-edac Link: http://lkml.kernel.org/r/1459991382-7859-1-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- arch/arm/mach-socfpga/ocram.c | 133 ++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/arch/arm/mach-socfpga/ocram.c b/arch/arm/mach-socfpga/ocram.c index 60ec643ac2be..10d673252395 100644 --- a/arch/arm/mach-socfpga/ocram.c +++ b/arch/arm/mach-socfpga/ocram.c @@ -13,12 +13,15 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ +#include #include #include #include #include #include +#include "core.h" + #define ALTR_OCRAM_CLEAR_ECC 0x00000018 #define ALTR_OCRAM_ECC_EN 0x00000019 @@ -47,3 +50,133 @@ void socfpga_init_ocram_ecc(void) iounmap(mapped_ocr_edac_addr); } + +/* Arria10 OCRAM Section */ +#define ALTR_A10_ECC_CTRL_OFST 0x08 +#define ALTR_A10_OCRAM_ECC_EN_CTL (BIT(1) | BIT(0)) +#define ALTR_A10_ECC_INITA BIT(16) + +#define ALTR_A10_ECC_INITSTAT_OFST 0x0C +#define ALTR_A10_ECC_INITCOMPLETEA BIT(0) +#define ALTR_A10_ECC_INITCOMPLETEB BIT(8) + +#define ALTR_A10_ECC_ERRINTEN_OFST 0x10 +#define ALTR_A10_ECC_SERRINTEN BIT(0) + +#define ALTR_A10_ECC_INTSTAT_OFST 0x20 +#define ALTR_A10_ECC_SERRPENA BIT(0) +#define ALTR_A10_ECC_DERRPENA BIT(8) +#define ALTR_A10_ECC_ERRPENA_MASK (ALTR_A10_ECC_SERRPENA | \ + ALTR_A10_ECC_DERRPENA) +/* ECC Manager Defines */ +#define A10_SYSMGR_ECC_INTMASK_SET_OFST 0x94 +#define A10_SYSMGR_ECC_INTMASK_CLR_OFST 0x98 +#define A10_SYSMGR_ECC_INTMASK_OCRAM BIT(1) + +#define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000 + +static inline void ecc_set_bits(u32 bit_mask, void __iomem *ioaddr) +{ + u32 value = readl(ioaddr); + + value |= bit_mask; + writel(value, ioaddr); +} + +static inline void ecc_clear_bits(u32 bit_mask, void __iomem *ioaddr) +{ + u32 value = readl(ioaddr); + + value &= ~bit_mask; + writel(value, ioaddr); +} + +static inline int ecc_test_bits(u32 bit_mask, void __iomem *ioaddr) +{ + u32 value = readl(ioaddr); + + return (value & bit_mask) ? 1 : 0; +} + +/* + * This function uses the memory initialization block in the Arria10 ECC + * controller to initialize/clear the entire memory data and ECC data. + */ +static int altr_init_memory_port(void __iomem *ioaddr) +{ + int limit = ALTR_A10_ECC_INIT_WATCHDOG_10US; + + ecc_set_bits(ALTR_A10_ECC_INITA, (ioaddr + ALTR_A10_ECC_CTRL_OFST)); + while (limit--) { + if (ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA, + (ioaddr + ALTR_A10_ECC_INITSTAT_OFST))) + break; + udelay(1); + } + if (limit < 0) + return -EBUSY; + + /* Clear any pending ECC interrupts */ + writel(ALTR_A10_ECC_ERRPENA_MASK, + (ioaddr + ALTR_A10_ECC_INTSTAT_OFST)); + + return 0; +} + +void socfpga_init_arria10_ocram_ecc(void) +{ + struct device_node *np; + int ret = 0; + void __iomem *ecc_block_base; + + if (!sys_manager_base_addr) { + pr_err("SOCFPGA: sys-mgr is not initialized\n"); + return; + } + + /* Find the OCRAM EDAC device tree node */ + np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-ocram-ecc"); + if (!np) { + pr_err("Unable to find socfpga-a10-ocram-ecc\n"); + return; + } + + /* Map the ECC Block */ + ecc_block_base = of_iomap(np, 0); + of_node_put(np); + if (!ecc_block_base) { + pr_err("Unable to map OCRAM ECC block\n"); + return; + } + + /* Disable ECC */ + writel(ALTR_A10_OCRAM_ECC_EN_CTL, + sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_SET_OFST); + ecc_clear_bits(ALTR_A10_ECC_SERRINTEN, + (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST)); + ecc_clear_bits(ALTR_A10_OCRAM_ECC_EN_CTL, + (ecc_block_base + ALTR_A10_ECC_CTRL_OFST)); + + /* Ensure all writes complete */ + wmb(); + + /* Use HW initialization block to initialize memory for ECC */ + ret = altr_init_memory_port(ecc_block_base); + if (ret) { + pr_err("ECC: cannot init OCRAM PORTA memory\n"); + goto exit; + } + + /* Enable ECC */ + ecc_set_bits(ALTR_A10_OCRAM_ECC_EN_CTL, + (ecc_block_base + ALTR_A10_ECC_CTRL_OFST)); + ecc_set_bits(ALTR_A10_ECC_SERRINTEN, + (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST)); + writel(ALTR_A10_OCRAM_ECC_EN_CTL, + sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_CLR_OFST); + + /* Ensure all writes complete */ + wmb(); +exit: + iounmap(ecc_block_base); +} -- GitLab From 7d7d38afb3e8fdfebfd867cc0ff4b5c45c14053c Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 1 Apr 2016 09:05:57 -0400 Subject: [PATCH 1683/9938] iommu/amd: Adding Extended Feature Register check for PC support The IVHD header type 11h and 40h introduce the PCSup bit in the EFR Register Image bit fileds. This should be used to determine the IOMMU performance support instead of relying on the PNCounters and PNBanks. Note also that the PNCouters and PNBanks bits in the IOMMU attributes field of IVHD headers type 11h are incorrectly programmed on some systems. So, we should not rely on it to determine the performance counter/banks size. Instead, these values should be read from the MMIO Offset 0030h IOMMU Extended Feature Register. Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index bf4959f4225b..dff1e01174d1 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -99,7 +99,11 @@ struct ivhd_header { u64 mmio_phys; u16 pci_seg; u16 info; - u32 efr; + u32 efr_attr; + + /* Following only valid on IVHD type 11h and 40h */ + u64 efr_reg; /* Exact copy of MMIO_EXT_FEATURES */ + u64 res; } __attribute__((packed)); /* @@ -1078,13 +1082,25 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; - /* Check if IVHD EFR contains proper max banks/counters */ - if ((h->efr != 0) && - ((h->efr & (0xF << 13)) != 0) && - ((h->efr & (0x3F << 17)) != 0)) { - iommu->mmio_phys_end = MMIO_REG_END_OFFSET; - } else { - iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; + switch (h->type) { + case 0x10: + /* Check if IVHD EFR contains proper max banks/counters */ + if ((h->efr_attr != 0) && + ((h->efr_attr & (0xF << 13)) != 0) && + ((h->efr_attr & (0x3F << 17)) != 0)) + iommu->mmio_phys_end = MMIO_REG_END_OFFSET; + else + iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; + break; + case 0x11: + case 0x40: + if (h->efr_reg & (1 << 9)) + iommu->mmio_phys_end = MMIO_REG_END_OFFSET; + else + iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; + break; + default: + return -EINVAL; } iommu->mmio_base = iommu_map_mmio_space(iommu->mmio_phys, -- GitLab From ac7ccf6765af5a255cec82fa95ec11f6c769022c Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 1 Apr 2016 09:05:58 -0400 Subject: [PATCH 1684/9938] iommu/amd: Modify ivhd_header structure to support type 11h and 40h This patch modifies the existing struct ivhd_header, which currently only support IVHD type 0x10, to add new fields from IVHD type 11h and 40h. It also modifies the pointer calculation to allow support for IVHD type 11h and 40h Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 35 ++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index dff1e01174d1..22e078bfe35b 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -398,6 +398,22 @@ static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu) release_mem_region(iommu->mmio_phys, iommu->mmio_phys_end); } +static inline u32 get_ivhd_header_size(struct ivhd_header *h) +{ + u32 size = 0; + + switch (h->type) { + case 0x10: + size = 24; + break; + case 0x11: + case 0x40: + size = 40; + break; + } + return size; +} + /**************************************************************************** * * The functions below belong to the first pass of AMD IOMMU ACPI table @@ -424,7 +440,14 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h) u8 *p = (void *)h, *end = (void *)h; struct ivhd_entry *dev; - p += sizeof(*h); + u32 ivhd_size = get_ivhd_header_size(h); + + if (!ivhd_size) { + pr_err("AMD-Vi: Unsupported IVHD type %#x\n", h->type); + return -EINVAL; + } + + p += ivhd_size; end += h->length; while (p < end) { @@ -789,6 +812,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, u32 dev_i, ext_flags = 0; bool alias = false; struct ivhd_entry *e; + u32 ivhd_size; int ret; @@ -804,7 +828,14 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, /* * Done. Now parse the device entries */ - p += sizeof(struct ivhd_header); + ivhd_size = get_ivhd_header_size(h); + if (!ivhd_size) { + pr_err("AMD-Vi: Unsupported IVHD type %#x\n", h->type); + return -EINVAL; + } + + p += ivhd_size; + end += h->length; -- GitLab From 8c7142f56fedfc6824b5bca56fee1f443e01746b Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 1 Apr 2016 09:05:59 -0400 Subject: [PATCH 1685/9938] iommu/amd: Use the most comprehensive IVHD type that the driver can support The IVRS in more recent AMD system usually contains multiple IVHD block types (e.g. 0x10, 0x11, and 0x40) for each IOMMU. The newer IVHD types provide more information (e.g. new features specified in the IOMMU spec), while maintain compatibility with the older IVHD type. Having multiple IVHD type allows older IOMMU drivers to still function (e.g. using the older IVHD type 0x10) while the newer IOMMU driver can use the newer IVHD types (e.g. 0x11 and 0x40). Therefore, the IOMMU driver should only make use of the newest IVHD type that it can support. This patch adds new logic to determine the highest level of IVHD type it can support, and use it throughout the to initialize the driver. This requires adding another pass to the IVRS parsing to determine appropriate IVHD type (see function get_highest_supported_ivhd_type()) before parsing the contents. [Vincent: fix the build error of IVHD_DEV_ACPI_HID flag not found] Signed-off-by: Wan Zongshun Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 107 ++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 29 deletions(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 22e078bfe35b..8f4961225724 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -44,7 +44,7 @@ */ #define IVRS_HEADER_LENGTH 48 -#define ACPI_IVHD_TYPE 0x10 +#define ACPI_IVHD_TYPE_MAX_SUPPORTED 0x40 #define ACPI_IVMD_TYPE_ALL 0x20 #define ACPI_IVMD_TYPE 0x21 #define ACPI_IVMD_TYPE_RANGE 0x22 @@ -58,6 +58,7 @@ #define IVHD_DEV_EXT_SELECT 0x46 #define IVHD_DEV_EXT_SELECT_RANGE 0x47 #define IVHD_DEV_SPECIAL 0x48 +#define IVHD_DEV_ACPI_HID 0xf0 #define IVHD_SPECIAL_IOAPIC 1 #define IVHD_SPECIAL_HPET 2 @@ -137,6 +138,7 @@ bool amd_iommu_irq_remap __read_mostly; static bool amd_iommu_detected; static bool __initdata amd_iommu_disabled; +static int amd_iommu_target_ivhd_type; u16 amd_iommu_last_bdf; /* largest PCI device id we have to handle */ @@ -428,7 +430,15 @@ static inline u32 get_ivhd_header_size(struct ivhd_header *h) */ static inline int ivhd_entry_length(u8 *ivhd) { - return 0x04 << (*ivhd >> 6); + u32 type = ((struct ivhd_entry *)ivhd)->type; + + if (type < 0x80) { + return 0x04 << (*ivhd >> 6); + } else if (type == IVHD_DEV_ACPI_HID) { + /* For ACPI_HID, offset 21 is uid len */ + return *((u8 *)ivhd + 21) + 22; + } + return 0; } /* @@ -475,6 +485,22 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h) return 0; } +static int __init check_ivrs_checksum(struct acpi_table_header *table) +{ + int i; + u8 checksum = 0, *p = (u8 *)table; + + for (i = 0; i < table->length; ++i) + checksum += p[i]; + if (checksum != 0) { + /* ACPI table corrupt */ + pr_err(FW_BUG "AMD-Vi: IVRS invalid checksum\n"); + return -ENODEV; + } + + return 0; +} + /* * Iterate over all IVHD entries in the ACPI table and find the highest device * id which we need to handle. This is the first of three functions which parse @@ -482,31 +508,19 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h) */ static int __init find_last_devid_acpi(struct acpi_table_header *table) { - int i; - u8 checksum = 0, *p = (u8 *)table, *end = (u8 *)table; + u8 *p = (u8 *)table, *end = (u8 *)table; struct ivhd_header *h; - /* - * Validate checksum here so we don't need to do it when - * we actually parse the table - */ - for (i = 0; i < table->length; ++i) - checksum += p[i]; - if (checksum != 0) - /* ACPI table corrupt */ - return -ENODEV; - p += IVRS_HEADER_LENGTH; end += table->length; while (p < end) { h = (struct ivhd_header *)p; - switch (h->type) { - case ACPI_IVHD_TYPE: - find_last_devid_from_ivhd(h); - break; - default: - break; + if (h->type == amd_iommu_target_ivhd_type) { + int ret = find_last_devid_from_ivhd(h); + + if (ret) + return ret; } p += h->length; } @@ -1164,6 +1178,32 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) return 0; } +/** + * get_highest_supported_ivhd_type - Look up the appropriate IVHD type + * @ivrs Pointer to the IVRS header + * + * This function search through all IVDB of the maximum supported IVHD + */ +static u8 get_highest_supported_ivhd_type(struct acpi_table_header *ivrs) +{ + u8 *base = (u8 *)ivrs; + struct ivhd_header *ivhd = (struct ivhd_header *) + (base + IVRS_HEADER_LENGTH); + u8 last_type = ivhd->type; + u16 devid = ivhd->devid; + + while (((u8 *)ivhd - base < ivrs->length) && + (ivhd->type <= ACPI_IVHD_TYPE_MAX_SUPPORTED)) { + u8 *p = (u8 *) ivhd; + + if (ivhd->devid == devid) + last_type = ivhd->type; + ivhd = (struct ivhd_header *)(p + ivhd->length); + } + + return last_type; +} + /* * Iterates over all IOMMU entries in the ACPI table, allocates the * IOMMU structure and initializes it with init_iommu_one() @@ -1180,8 +1220,7 @@ static int __init init_iommu_all(struct acpi_table_header *table) while (p < end) { h = (struct ivhd_header *)p; - switch (*p) { - case ACPI_IVHD_TYPE: + if (*p == amd_iommu_target_ivhd_type) { DUMP_printk("device: %02x:%02x.%01x cap: %04x " "seg: %d flags: %01x info %04x\n", @@ -1198,9 +1237,6 @@ static int __init init_iommu_all(struct acpi_table_header *table) ret = init_iommu_one(iommu, h); if (ret) return ret; - break; - default: - break; } p += h->length; @@ -1865,18 +1901,20 @@ static void __init free_dma_resources(void) * remapping setup code. * * This function basically parses the ACPI table for AMD IOMMU (IVRS) - * three times: + * four times: * - * 1 pass) Find the highest PCI device id the driver has to handle. + * 1 pass) Discover the most comprehensive IVHD type to use. + * + * 2 pass) Find the highest PCI device id the driver has to handle. * Upon this information the size of the data structures is * determined that needs to be allocated. * - * 2 pass) Initialize the data structures just allocated with the + * 3 pass) Initialize the data structures just allocated with the * information in the ACPI table about available AMD IOMMUs * in the system. It also maps the PCI devices in the * system to specific IOMMUs * - * 3 pass) After the basic data structures are allocated and + * 4 pass) After the basic data structures are allocated and * initialized we update them with information about memory * remapping requirements parsed out of the ACPI table in * this last pass. @@ -1903,6 +1941,17 @@ static int __init early_amd_iommu_init(void) return -EINVAL; } + /* + * Validate checksum here so we don't need to do it when + * we actually parse the table + */ + ret = check_ivrs_checksum(ivrs_base); + if (ret) + return ret; + + amd_iommu_target_ivhd_type = get_highest_supported_ivhd_type(ivrs_base); + DUMP_printk("Using IVHD type %#x\n", amd_iommu_target_ivhd_type); + /* * First parse ACPI tables to find the largest Bus/Dev/Func * we need to handle. Upon this information the shared data -- GitLab From 2a0cb4e2d423c8aeafa79945279246f6b35ea8cf Mon Sep 17 00:00:00 2001 From: Wan Zongshun Date: Fri, 1 Apr 2016 09:06:00 -0400 Subject: [PATCH 1686/9938] iommu/amd: Add new map for storing IVHD dev entry type HID This patch introduces acpihid_map, which is used to store the new IVHD device entry extracted from BIOS IVRS table. It also provides a utility function add_acpi_hid_device(), to add this types of devices to the map. Signed-off-by: Wan Zongshun Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 1 + drivers/iommu/amd_iommu_init.c | 122 ++++++++++++++++++++++++++++++++ drivers/iommu/amd_iommu_types.h | 14 ++++ 3 files changed, 137 insertions(+) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 374c129219ef..d8e59a84f7c0 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -72,6 +72,7 @@ static DEFINE_SPINLOCK(dev_data_list_lock); LIST_HEAD(ioapic_map); LIST_HEAD(hpet_map); +LIST_HEAD(acpihid_map); /* * Domain for untranslated devices - only allocated diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 8f4961225724..e7ebfa2a6c2c 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -60,6 +60,10 @@ #define IVHD_DEV_SPECIAL 0x48 #define IVHD_DEV_ACPI_HID 0xf0 +#define UID_NOT_PRESENT 0 +#define UID_IS_INTEGER 1 +#define UID_IS_CHARACTER 2 + #define IVHD_SPECIAL_IOAPIC 1 #define IVHD_SPECIAL_HPET 2 @@ -116,6 +120,11 @@ struct ivhd_entry { u16 devid; u8 flags; u32 ext; + u32 hidh; + u64 cid; + u8 uidf; + u8 uidl; + u8 uid; } __attribute__((packed)); /* @@ -224,8 +233,12 @@ enum iommu_init_state { #define EARLY_MAP_SIZE 4 static struct devid_map __initdata early_ioapic_map[EARLY_MAP_SIZE]; static struct devid_map __initdata early_hpet_map[EARLY_MAP_SIZE]; +static struct acpihid_map_entry __initdata early_acpihid_map[EARLY_MAP_SIZE]; + static int __initdata early_ioapic_map_size; static int __initdata early_hpet_map_size; +static int __initdata early_acpihid_map_size; + static bool __initdata cmdline_maps; static enum iommu_init_state init_state = IOMMU_START_STATE; @@ -765,6 +778,42 @@ static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line) return 0; } +static int __init add_acpi_hid_device(u8 *hid, u8 *uid, u16 *devid, + bool cmd_line) +{ + struct acpihid_map_entry *entry; + struct list_head *list = &acpihid_map; + + list_for_each_entry(entry, list, list) { + if (strcmp(entry->hid, hid) || + (*uid && *entry->uid && strcmp(entry->uid, uid)) || + !entry->cmd_line) + continue; + + pr_info("AMD-Vi: Command-line override for hid:%s uid:%s\n", + hid, uid); + *devid = entry->devid; + return 0; + } + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + memcpy(entry->uid, uid, strlen(uid)); + memcpy(entry->hid, hid, strlen(hid)); + entry->devid = *devid; + entry->cmd_line = cmd_line; + entry->root_devid = (entry->devid & (~0x7)); + + pr_info("AMD-Vi:%s, add hid:%s, uid:%s, rdevid:%d\n", + entry->cmd_line ? "cmd" : "ivrs", + entry->hid, entry->uid, entry->root_devid); + + list_add_tail(&entry->list, list); + return 0; +} + static int __init add_early_maps(void) { int i, ret; @@ -787,6 +836,15 @@ static int __init add_early_maps(void) return ret; } + for (i = 0; i < early_acpihid_map_size; ++i) { + ret = add_acpi_hid_device(early_acpihid_map[i].hid, + early_acpihid_map[i].uid, + &early_acpihid_map[i].devid, + early_acpihid_map[i].cmd_line); + if (ret) + return ret; + } + return 0; } @@ -1007,6 +1065,70 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, break; } + case IVHD_DEV_ACPI_HID: { + u16 devid; + u8 hid[ACPIHID_HID_LEN] = {0}; + u8 uid[ACPIHID_UID_LEN] = {0}; + int ret; + + if (h->type != 0x40) { + pr_err(FW_BUG "Invalid IVHD device type %#x\n", + e->type); + break; + } + + memcpy(hid, (u8 *)(&e->ext), ACPIHID_HID_LEN - 1); + hid[ACPIHID_HID_LEN - 1] = '\0'; + + if (!(*hid)) { + pr_err(FW_BUG "Invalid HID.\n"); + break; + } + + switch (e->uidf) { + case UID_NOT_PRESENT: + + if (e->uidl != 0) + pr_warn(FW_BUG "Invalid UID length.\n"); + + break; + case UID_IS_INTEGER: + + sprintf(uid, "%d", e->uid); + + break; + case UID_IS_CHARACTER: + + memcpy(uid, (u8 *)(&e->uid), ACPIHID_UID_LEN - 1); + uid[ACPIHID_UID_LEN - 1] = '\0'; + + break; + default: + break; + } + + DUMP_printk(" DEV_ACPI_HID(%s[%s])\t\tdevid: %02x:%02x.%x\n", + hid, uid, + PCI_BUS_NUM(devid), + PCI_SLOT(devid), + PCI_FUNC(devid)); + + devid = e->devid; + flags = e->flags; + + ret = add_acpi_hid_device(hid, uid, &devid, false); + if (ret) + return ret; + + /* + * add_special_device might update the devid in case a + * command-line override is present. So call + * set_dev_entry_from_acpi after add_special_device. + */ + set_dev_entry_from_acpi(iommu, devid, e->flags, 0); + + break; + } default: break; } diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 9d32b20a5e9a..b6b14d288b0b 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -527,6 +527,19 @@ struct amd_iommu { #endif }; +#define ACPIHID_UID_LEN 256 +#define ACPIHID_HID_LEN 9 + +struct acpihid_map_entry { + struct list_head list; + u8 uid[ACPIHID_UID_LEN]; + u8 hid[ACPIHID_HID_LEN]; + u16 devid; + u16 root_devid; + bool cmd_line; + struct iommu_group *group; +}; + struct devid_map { struct list_head list; u8 id; @@ -537,6 +550,7 @@ struct devid_map { /* Map HPET and IOAPIC ids to the devid used by the IOMMU */ extern struct list_head ioapic_map; extern struct list_head hpet_map; +extern struct list_head acpihid_map; /* * List with all IOMMUs in the system. This list is not locked because it is -- GitLab From ca3bf5d47cec8b7614bcb2e9132c40081d6d81db Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Fri, 1 Apr 2016 09:06:01 -0400 Subject: [PATCH 1687/9938] iommu/amd: Introduces ivrs_acpihid kernel parameter This patch introduces a new kernel parameter, ivrs_acpihid. This is used to override existing ACPI-HID IVHD device entry, or add an entry in case it is missing in the IVHD. Signed-off-by: Wan Zongshun Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- Documentation/kernel-parameters.txt | 7 ++++++ drivers/iommu/amd_iommu_init.c | 33 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ecc74fa4bfde..8c881a5f7af0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1767,6 +1767,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. PCI device 00:14.0 write the parameter as: ivrs_hpet[0]=00:14.0 + ivrs_acpihid [HW,X86_64] + Provide an override to the ACPI-HID:UID<->DEVICE-ID + mapping provided in the IVRS ACPI table. For + example, to map UART-HID:UID AMD0020:0 to + PCI device 00:14.5 write the parameter as: + ivrs_acpihid[00:14.5]=AMD0020:0 + js= [HW,JOY] Analog joystick See Documentation/input/joystick.txt. diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index e7ebfa2a6c2c..9e0034196e10 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2477,10 +2477,43 @@ static int __init parse_ivrs_hpet(char *str) return 1; } +static int __init parse_ivrs_acpihid(char *str) +{ + u32 bus, dev, fn; + char *hid, *uid, *p; + char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0}; + int ret, i; + + ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid); + if (ret != 4) { + pr_err("AMD-Vi: Invalid command line: ivrs_acpihid(%s)\n", str); + return 1; + } + + p = acpiid; + hid = strsep(&p, ":"); + uid = p; + + if (!hid || !(*hid) || !uid) { + pr_err("AMD-Vi: Invalid command line: hid or uid\n"); + return 1; + } + + i = early_acpihid_map_size++; + memcpy(early_acpihid_map[i].hid, hid, strlen(hid)); + memcpy(early_acpihid_map[i].uid, uid, strlen(uid)); + early_acpihid_map[i].devid = + ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7); + early_acpihid_map[i].cmd_line = true; + + return 1; +} + __setup("amd_iommu_dump", parse_amd_iommu_dump); __setup("amd_iommu=", parse_amd_iommu_options); __setup("ivrs_ioapic", parse_ivrs_ioapic); __setup("ivrs_hpet", parse_ivrs_hpet); +__setup("ivrs_acpihid", parse_ivrs_acpihid); IOMMU_INIT_FINISH(amd_iommu_detect, gart_iommu_hole_init, -- GitLab From 7aba6cb9ee9db7849d0bf57891d9c7feb4e89457 Mon Sep 17 00:00:00 2001 From: Wan Zongshun Date: Fri, 1 Apr 2016 09:06:02 -0400 Subject: [PATCH 1688/9938] iommu/amd: Make call-sites of get_device_id aware of its return value This patch is to make the call-sites of get_device_id aware of its return value. Signed-off-by: Wan Zongshun Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 51 +++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index d8e59a84f7c0..400867f01d35 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -279,9 +279,11 @@ static void init_unity_mappings_for_device(struct device *dev, struct dma_ops_domain *dma_dom) { struct unity_map_entry *e; - u16 devid; + int devid; devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return; list_for_each_entry(e, &amd_iommu_unity_map, list) { if (!(devid >= e->devid_start && devid <= e->devid_end)) @@ -296,7 +298,7 @@ static void init_unity_mappings_for_device(struct device *dev, */ static bool check_device(struct device *dev) { - u16 devid; + int devid; if (!dev || !dev->dma_mask) return false; @@ -306,6 +308,8 @@ static bool check_device(struct device *dev) return false; devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return false; /* Out of our scope? */ if (devid > amd_iommu_last_bdf) @@ -342,11 +346,16 @@ static int iommu_init_device(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct iommu_dev_data *dev_data; + int devid; if (dev->archdata.iommu) return 0; - dev_data = find_dev_data(get_device_id(dev)); + devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return devid; + + dev_data = find_dev_data(devid); if (!dev_data) return -ENOMEM; @@ -367,9 +376,13 @@ static int iommu_init_device(struct device *dev) static void iommu_ignore_device(struct device *dev) { - u16 devid, alias; + u16 alias; + int devid; devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return; + alias = amd_iommu_alias_table[devid]; memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry)); @@ -381,8 +394,14 @@ static void iommu_ignore_device(struct device *dev) static void iommu_uninit_device(struct device *dev) { - struct iommu_dev_data *dev_data = search_dev_data(get_device_id(dev)); + int devid; + struct iommu_dev_data *dev_data; + + devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return; + dev_data = search_dev_data(devid); if (!dev_data) return; @@ -2314,13 +2333,15 @@ static int amd_iommu_add_device(struct device *dev) struct iommu_dev_data *dev_data; struct iommu_domain *domain; struct amd_iommu *iommu; - u16 devid; - int ret; + int ret, devid; if (!check_device(dev) || get_dev_data(dev)) return 0; devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return devid; + iommu = amd_iommu_rlookup_table[devid]; ret = iommu_init_device(dev); @@ -2358,12 +2379,15 @@ static int amd_iommu_add_device(struct device *dev) static void amd_iommu_remove_device(struct device *dev) { struct amd_iommu *iommu; - u16 devid; + int devid; if (!check_device(dev)) return; devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return; + iommu = amd_iommu_rlookup_table[devid]; iommu_uninit_device(dev); @@ -3035,12 +3059,14 @@ static void amd_iommu_detach_device(struct iommu_domain *dom, { struct iommu_dev_data *dev_data = dev->archdata.iommu; struct amd_iommu *iommu; - u16 devid; + int devid; if (!check_device(dev)) return; devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return; if (dev_data->domain != NULL) detach_device(dev); @@ -3158,9 +3184,11 @@ static void amd_iommu_get_dm_regions(struct device *dev, struct list_head *head) { struct unity_map_entry *entry; - u16 devid; + int devid; devid = get_device_id(dev); + if (IS_ERR_VALUE(devid)) + return; list_for_each_entry(entry, &amd_iommu_unity_map, list) { struct iommu_dm_region *region; @@ -3862,6 +3890,9 @@ static struct irq_domain *get_irq_domain(struct irq_alloc_info *info) case X86_IRQ_ALLOC_TYPE_MSI: case X86_IRQ_ALLOC_TYPE_MSIX: devid = get_device_id(&info->msi_dev->dev); + if (IS_ERR_VALUE(devid)) + return NULL; + iommu = amd_iommu_rlookup_table[devid]; if (iommu) return iommu->msi_domain; -- GitLab From 2bf9a0a12749b2c45964020795859d4a1f228a1d Mon Sep 17 00:00:00 2001 From: Wan Zongshun Date: Fri, 1 Apr 2016 09:06:03 -0400 Subject: [PATCH 1689/9938] iommu/amd: Add iommu support for ACPI HID devices Current IOMMU driver make assumption that the downstream devices are PCI. With the newly added ACPI-HID IVHD device entry support, this is no longer true. This patch is to add dev type check and to distinguish the pci and acpihid device code path. Signed-off-by: Wan Zongshun Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 69 ++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 400867f01d35..0df651a379df 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -216,13 +217,60 @@ static struct iommu_dev_data *find_dev_data(u16 devid) return dev_data; } -static inline u16 get_device_id(struct device *dev) +static inline int match_hid_uid(struct device *dev, + struct acpihid_map_entry *entry) +{ + const char *hid, *uid; + + hid = acpi_device_hid(ACPI_COMPANION(dev)); + uid = acpi_device_uid(ACPI_COMPANION(dev)); + + if (!hid || !(*hid)) + return -ENODEV; + + if (!uid || !(*uid)) + return strcmp(hid, entry->hid); + + if (!(*entry->uid)) + return strcmp(hid, entry->hid); + + return (strcmp(hid, entry->hid) || strcmp(uid, entry->uid)); +} + +static inline u16 get_pci_device_id(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); return PCI_DEVID(pdev->bus->number, pdev->devfn); } +static inline int get_acpihid_device_id(struct device *dev, + struct acpihid_map_entry **entry) +{ + struct acpihid_map_entry *p; + + list_for_each_entry(p, &acpihid_map, list) { + if (!match_hid_uid(dev, p)) { + if (entry) + *entry = p; + return p->devid; + } + } + return -EINVAL; +} + +static inline int get_device_id(struct device *dev) +{ + int devid; + + if (dev_is_pci(dev)) + devid = get_pci_device_id(dev); + else + devid = get_acpihid_device_id(dev, NULL); + + return devid; +} + static struct iommu_dev_data *get_dev_data(struct device *dev) { return dev->archdata.iommu; @@ -303,10 +351,6 @@ static bool check_device(struct device *dev) if (!dev || !dev->dma_mask) return false; - /* No PCI device */ - if (!dev_is_pci(dev)) - return false; - devid = get_device_id(dev); if (IS_ERR_VALUE(devid)) return false; @@ -344,7 +388,6 @@ static void init_iommu_group(struct device *dev) static int iommu_init_device(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); struct iommu_dev_data *dev_data; int devid; @@ -359,10 +402,10 @@ static int iommu_init_device(struct device *dev) if (!dev_data) return -ENOMEM; - if (pci_iommuv2_capable(pdev)) { + if (dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) { struct amd_iommu *iommu; - iommu = amd_iommu_rlookup_table[dev_data->devid]; + iommu = amd_iommu_rlookup_table[dev_data->devid]; dev_data->iommu_v2 = iommu->is_iommu_v2; } @@ -2239,13 +2282,17 @@ static bool pci_pri_tlp_required(struct pci_dev *pdev) static int attach_device(struct device *dev, struct protection_domain *domain) { - struct pci_dev *pdev = to_pci_dev(dev); + struct pci_dev *pdev; struct iommu_dev_data *dev_data; unsigned long flags; int ret; dev_data = get_dev_data(dev); + if (!dev_is_pci(dev)) + goto skip_ats_check; + + pdev = to_pci_dev(dev); if (domain->flags & PD_IOMMUV2_MASK) { if (!dev_data->passthrough) return -EINVAL; @@ -2264,6 +2311,7 @@ static int attach_device(struct device *dev, dev_data->ats.qdep = pci_ats_queue_depth(pdev); } +skip_ats_check: write_lock_irqsave(&amd_iommu_devtable_lock, flags); ret = __attach_device(dev_data, domain); write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); @@ -2320,6 +2368,9 @@ static void detach_device(struct device *dev) __detach_device(dev_data); write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); + if (!dev_is_pci(dev)) + return; + if (domain->flags & PD_IOMMUV2_MASK && dev_data->iommu_v2) pdev_iommuv2_disable(to_pci_dev(dev)); else if (dev_data->ats.enabled) -- GitLab From b097d11a0fa3f97be88774d09ee9ed1d8532a7b0 Mon Sep 17 00:00:00 2001 From: Wan Zongshun Date: Fri, 1 Apr 2016 09:06:04 -0400 Subject: [PATCH 1690/9938] iommu/amd: Manage iommu_group for ACPI HID devices This patch creates a new function for finding or creating an IOMMU group for acpihid(ACPI Hardware ID) device. The acpihid devices with the same devid will be put into same group and there will have the same domain id and share the same page table. Signed-off-by: Wan Zongshun Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 0df651a379df..713e7ea06210 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -276,6 +276,29 @@ static struct iommu_dev_data *get_dev_data(struct device *dev) return dev->archdata.iommu; } +/* +* Find or create an IOMMU group for a acpihid device. +*/ +static struct iommu_group *acpihid_device_group(struct device *dev) +{ + struct acpihid_map_entry *p, *entry = NULL; + u16 devid; + + devid = get_acpihid_device_id(dev, &entry); + if (devid < 0) + return ERR_PTR(devid); + + list_for_each_entry(p, &acpihid_map, list) { + if ((devid == p->devid) && p->group) + entry->group = p->group; + } + + if (!entry->group) + entry->group = generic_device_group(dev); + + return entry->group; +} + static bool pci_iommuv2_capable(struct pci_dev *pdev) { static const int caps[] = { @@ -2445,6 +2468,14 @@ static void amd_iommu_remove_device(struct device *dev) iommu_completion_wait(iommu); } +static struct iommu_group *amd_iommu_device_group(struct device *dev) +{ + if (dev_is_pci(dev)) + return pci_device_group(dev); + + return acpihid_device_group(dev); +} + /***************************************************************************** * * The next functions belong to the dma_ops mapping/unmapping code. @@ -3286,7 +3317,7 @@ static const struct iommu_ops amd_iommu_ops = { .iova_to_phys = amd_iommu_iova_to_phys, .add_device = amd_iommu_add_device, .remove_device = amd_iommu_remove_device, - .device_group = pci_device_group, + .device_group = amd_iommu_device_group, .get_dm_regions = amd_iommu_get_dm_regions, .put_dm_regions = amd_iommu_put_dm_regions, .pgsize_bitmap = AMD_IOMMU_PGSIZES, -- GitLab From 9a4d3bf56c87be9ad8916e2013af04787d6bac9b Mon Sep 17 00:00:00 2001 From: Wan Zongshun Date: Fri, 1 Apr 2016 09:06:05 -0400 Subject: [PATCH 1691/9938] iommu/amd: Set AMD iommu callbacks for amba bus AMD Uart DMA belongs to ACPI HID type device, and its driver is basing on AMBA Bus, need also IOMMU support. This patch is just to set the AMD iommu callbacks for amba bus. Signed-off-by: Wan Zongshun Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 713e7ea06210..c430c10fb645 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -2969,7 +2970,17 @@ static struct dma_map_ops amd_iommu_dma_ops = { int __init amd_iommu_init_api(void) { - return bus_set_iommu(&pci_bus_type, &amd_iommu_ops); + int err = 0; + + err = bus_set_iommu(&pci_bus_type, &amd_iommu_ops); + if (err) + return err; +#ifdef CONFIG_ARM_AMBA + err = bus_set_iommu(&amba_bustype, &amd_iommu_ops); + if (err) + return err; +#endif + return 0; } int __init amd_iommu_init_dma_ops(void) -- GitLab From a0d284d2b1d9f7453ff1c5cc7854219daf4f7590 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 16 Mar 2016 23:15:44 -0500 Subject: [PATCH 1692/9938] powerpc: Fix incorrect PPC32 PAMU dependency The Freescale PAMU can be enabled on both 32 and 64-bit Power chips. Commit 477ab7a19ce restricted PAMU to PPC32. PPC covers both. Signed-off-by: Andy Fleming Signed-off-by: Joerg Roedel --- drivers/iommu/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd1dc39f84ff..e0dfb8676d61 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -76,8 +76,7 @@ config IOMMU_DMA config FSL_PAMU bool "Freescale IOMMU support" - depends on PPC32 - depends on PPC_E500MC || COMPILE_TEST + depends on PPC_E500MC || (COMPILE_TEST && PPC) select IOMMU_API select GENERIC_ALLOCATOR help -- GitLab From 31e6850e0fdb3a586363cc4d2f9801cdf9374310 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 5 Apr 2016 12:39:30 +0100 Subject: [PATCH 1693/9938] iommu: Add MMIO mapping type On some platforms, MMIO regions might need slightly different treatment compared to mapping regular memory; add the notion of MMIO mappings to the IOMMU API's memory type flags, so that callers can let the IOMMU drivers know to do the right thing. Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a5c539fa5d2b..34b643227df1 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -30,6 +30,7 @@ #define IOMMU_WRITE (1 << 1) #define IOMMU_CACHE (1 << 2) /* DMA cache coherency */ #define IOMMU_NOEXEC (1 << 3) +#define IOMMU_MMIO (1 << 4) /* e.g. things like MSI doorbells */ struct iommu_ops; struct iommu_group; -- GitLab From fb948251e4be1f4aedbe17ec96890ceee147c6d6 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 5 Apr 2016 12:39:31 +0100 Subject: [PATCH 1694/9938] iommu/io-pgtable-arm: Support IOMMU_MMIO flag Teach the LPAE format to create Device mappings when asked. Signed-off-by: Robin Murphy Tested-by: Eric Auger Signed-off-by: Joerg Roedel --- drivers/iommu/io-pgtable-arm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index f433b516098a..a1ed1b73fed4 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -355,7 +355,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data, if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ)) pte |= ARM_LPAE_PTE_AP_RDONLY; - if (prot & IOMMU_CACHE) + if (prot & IOMMU_MMIO) + pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV + << ARM_LPAE_PTE_ATTRINDX_SHIFT); + else if (prot & IOMMU_CACHE) pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE << ARM_LPAE_PTE_ATTRINDX_SHIFT); } else { @@ -364,7 +367,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data, pte |= ARM_LPAE_PTE_HAP_READ; if (prot & IOMMU_WRITE) pte |= ARM_LPAE_PTE_HAP_WRITE; - if (prot & IOMMU_CACHE) + if (prot & IOMMU_MMIO) + pte |= ARM_LPAE_PTE_MEMATTR_DEV; + else if (prot & IOMMU_CACHE) pte |= ARM_LPAE_PTE_MEMATTR_OIWB; else pte |= ARM_LPAE_PTE_MEMATTR_NC; -- GitLab From e88ccab12a9e85c536544f1464bd75610b1c46d6 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 5 Apr 2016 12:39:32 +0100 Subject: [PATCH 1695/9938] iommu/io-pgtable-arm-v7s: Support IOMMU_MMIO flag Teach the short-descriptor format to create Device mappings when asked. Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/io-pgtable-arm-v7s.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 0f93dc2f98a3..8c6139986d7d 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -260,9 +260,10 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl, struct io_pgtable_cfg *cfg) { bool ap = !(cfg->quirks & IO_PGTABLE_QUIRK_NO_PERMS); - arm_v7s_iopte pte = ARM_V7S_ATTR_NG | ARM_V7S_ATTR_S | - ARM_V7S_ATTR_TEX(1); + arm_v7s_iopte pte = ARM_V7S_ATTR_NG | ARM_V7S_ATTR_S; + if (!(prot & IOMMU_MMIO)) + pte |= ARM_V7S_ATTR_TEX(1); if (ap) { pte |= ARM_V7S_PTE_AF | ARM_V7S_PTE_AP_UNPRIV; if (!(prot & IOMMU_WRITE)) @@ -272,7 +273,9 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl, if ((prot & IOMMU_NOEXEC) && ap) pte |= ARM_V7S_ATTR_XN(lvl); - if (prot & IOMMU_CACHE) + if (prot & IOMMU_MMIO) + pte |= ARM_V7S_ATTR_B; + else if (prot & IOMMU_CACHE) pte |= ARM_V7S_ATTR_B | ARM_V7S_ATTR_C; return pte; @@ -281,10 +284,13 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl, static int arm_v7s_pte_to_prot(arm_v7s_iopte pte, int lvl) { int prot = IOMMU_READ; + arm_v7s_iopte attr = pte >> ARM_V7S_ATTR_SHIFT(lvl); - if (pte & (ARM_V7S_PTE_AP_RDONLY << ARM_V7S_ATTR_SHIFT(lvl))) + if (attr & ARM_V7S_PTE_AP_RDONLY) prot |= IOMMU_WRITE; - if (pte & ARM_V7S_ATTR_C) + if ((attr & (ARM_V7S_TEX_MASK << ARM_V7S_TEX_SHIFT)) == 0) + prot |= IOMMU_MMIO; + else if (pte & ARM_V7S_ATTR_C) prot |= IOMMU_CACHE; return prot; -- GitLab From 7d6a7e782558323364bc0ae59f3523175c10b258 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 7 Apr 2016 09:11:11 +0200 Subject: [PATCH 1696/9938] perf tools: Introduce trim function To be used in cases for both sides trim. Signed-off-by: Jiri Olsa Cc: Andreas Hollmann Cc: David Ahern Cc: Milian Wolff Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460013073-18444-1-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 3 +-- tools/perf/ui/stdio/hist.c | 3 +-- tools/perf/util/util.h | 5 +++++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 2a83414159a6..e70df2e54d66 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1607,9 +1607,8 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); dummy_hpp.buf[ret] = '\0'; - rtrim(dummy_hpp.buf); - start = ltrim(dummy_hpp.buf); + start = trim(dummy_hpp.buf); ret = strlen(start); if (start != dummy_hpp.buf) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 7aff5acf3265..560eb47d56f9 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -569,9 +569,8 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, first_col = false; fmt->header(fmt, hpp, hists_to_evsel(hists)); - rtrim(hpp->buf); - header_width += fprintf(fp, "%s", ltrim(hpp->buf)); + header_width += fprintf(fp, "%s", trim(hpp->buf)); } } diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 8298d607c738..3bf3de86d429 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -254,6 +254,11 @@ int hex2u64(const char *ptr, u64 *val); char *ltrim(char *s); char *rtrim(char *s); +static inline char *trim(char *s) +{ + return ltrim(rtrim(s)); +} + void dump_stack(void); void sighandler_dump_stack(int sig); -- GitLab From 95d1c8951e5bd50bb89654a99a7012b1e75646bd Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Apr 2016 10:19:58 -0700 Subject: [PATCH 1697/9938] HID: simplify implement() a bit The 'size' variable is not really needed, and we can also shift constant in the loop body when masking off existing bits. Also we do not have to use 64 bit calculations if we take an extra branch. [jkosina@suse.cz: fix a small error in changelog] Suggested-by: Doug Anderson Signed-off-by: Dmitry Torokhov Reviewed-by: Douglas Anderson Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bdb8cc89cacc..9985c0ab7c7f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1129,49 +1129,46 @@ EXPORT_SYMBOL_GPL(hid_field_extract); static void __implement(u8 *report, unsigned offset, int n, u32 value) { unsigned int idx = offset / 8; - unsigned int size = offset + n; unsigned int bit_shift = offset % 8; int bits_to_set = 8 - bit_shift; - u8 bit_mask = 0xff << bit_shift; while (n - bits_to_set >= 0) { - report[idx] &= ~bit_mask; + report[idx] &= ~(0xff << bit_shift); report[idx] |= value << bit_shift; value >>= bits_to_set; n -= bits_to_set; bits_to_set = 8; - bit_mask = 0xff; bit_shift = 0; idx++; } /* last nibble */ if (n) { - if (size % 8) - bit_mask &= (1U << (size % 8)) - 1; - report[idx] &= ~bit_mask; - report[idx] |= (value << bit_shift) & bit_mask; + u8 bit_mask = ((1U << n) - 1); + report[idx] &= ~(bit_mask << bit_shift); + report[idx] |= value << bit_shift; } } static void implement(const struct hid_device *hid, u8 *report, unsigned offset, unsigned n, u32 value) { - u64 m; - - if (n > 32) { + if (unlikely(n > 32)) { hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", __func__, n, current->comm); n = 32; + } else if (n < 32) { + u32 m = (1U << n) - 1; + + if (unlikely(value > m)) { + hid_warn(hid, + "%s() called with too large value %d (n: %d)! (%s)\n", + __func__, value, n, current->comm); + WARN_ON(1); + value &= m; + } } - m = (1ULL << n) - 1; - if (value > m) - hid_warn(hid, "%s() called with too large value %d! (%s)\n", - __func__, value, current->comm); - WARN_ON(value > m); - value &= m; - __implement(report, offset, n, value); } -- GitLab From 1d4b42bcccb9ea851ec0b4127e8cb103e8a7183f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 2 Dec 2015 16:18:50 +0000 Subject: [PATCH 1698/9938] MAINTAINERS: Add ST's CPUFreq driver to the STI file list Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..174e85486a52 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1638,6 +1638,7 @@ F: arch/arm/boot/dts/sti* F: drivers/char/hw_random/st-rng.c F: drivers/clocksource/arm_global_timer.c F: drivers/clocksource/clksrc_st_lpc.c +F: drivers/cpufreq/sti-cpufreq.c F: drivers/i2c/busses/i2c-st.c F: drivers/media/rc/st_rc.c F: drivers/media/platform/sti/c8sectpfe/ -- GitLab From aac2252443a568ebf8b9e1b5682650645c6b57c9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 2 Sep 2015 13:31:31 +0100 Subject: [PATCH 1699/9938] MAINTAINERS: Add ST's Remote Processor Driver to ARM/STI ARCHITECTURE Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 174e85486a52..a47be8b24b24 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1648,6 +1648,7 @@ F: drivers/phy/phy-miphy365x.c F: drivers/phy/phy-stih407-usb.c F: drivers/phy/phy-stih41x-usb.c F: drivers/pinctrl/pinctrl-st.c +F: drivers/remoteproc/st_remoteproc.c F: drivers/reset/sti/ F: drivers/rtc/rtc-st-lpc.c F: drivers/tty/serial/st-asc.c -- GitLab From 33406c805730377ff48741f9ad99e7aada91595b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 5 May 2015 13:13:57 +0100 Subject: [PATCH 1700/9938] ARM: STi: Update platform level menuconfig 'help' Encompass newer STiH4{07,10} and STiH418 SoC based platforms. Acked-by: Peter Griffin Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/mach-sti/Kconfig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig index a196d14f65f5..6f1af29f935d 100644 --- a/arch/arm/mach-sti/Kconfig +++ b/arch/arm/mach-sti/Kconfig @@ -18,11 +18,10 @@ menuconfig ARCH_STI select PL310_ERRATA_769419 if CACHE_L2X0 select RESET_CONTROLLER help - Include support for STiH41x SOCs like STiH415/416 using the device tree - for discovery - More information at Documentation/arm/STiH41x and - at Documentation/devicetree - + Include support for STMicroelectronics' STiH415/416, STiH407/10 and + STiH418 family SoCs using the Device Tree for discovery. More + information can be found in Documentation/arm/sti/ and + Documentation/devicetree. if ARCH_STI -- GitLab From 848fc67da5fb43ef7d92d20891eef79f5de45816 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 4 Mar 2016 15:32:40 +0100 Subject: [PATCH 1701/9938] clk: renesas: mstp: Drop check for CONFIG_PM_GENERIC_DOMAINS_OF As of commit 71d076ceb245f0d9 ("ARM: shmobile: Enable PM and PM_GENERIC_DOMAINS for SoCs with PM Domains"), CONFIG_PM_GENERIC_DOMAINS_OF is always enabled for SoCs with MSTP clocks. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart --- drivers/clk/renesas/clk-mstp.c | 3 --- include/linux/clk/renesas.h | 4 ---- 2 files changed, 7 deletions(-) diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 3d44e183aedd..5e3b3d856eef 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c @@ -243,8 +243,6 @@ static void __init cpg_mstp_clocks_init(struct device_node *np) } CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init); - -#ifdef CONFIG_PM_GENERIC_DOMAINS_OF int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev) { struct device_node *np = dev->of_node; @@ -326,4 +324,3 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np) of_genpd_add_provider_simple(np, pd); } -#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */ diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 7adfd80fbf55..2a3379cf1330 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -24,12 +24,8 @@ void r8a7778_clocks_init(u32 mode); void r8a7779_clocks_init(u32 mode); void rcar_gen2_clocks_init(u32 mode); -#ifdef CONFIG_PM_GENERIC_DOMAINS_OF void cpg_mstp_add_clk_domain(struct device_node *np); int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev); void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev); -#else -static inline void cpg_mstp_add_clk_domain(struct device_node *np) {} -#endif #endif -- GitLab From da437d2d09de0af1ffd7ae3d88317ef1bf7f9456 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 4 Mar 2016 15:36:33 +0100 Subject: [PATCH 1702/9938] clk: renesas: cpg-mssr: Drop check for CONFIG_PM_GENERIC_DOMAINS_OF As of commit 71d076ceb245f0d9 ("ARM: shmobile: Enable PM and PM_GENERIC_DOMAINS for SoCs with PM Domains"), CONFIG_PM_GENERIC_DOMAINS_OF is always enabled for SoCs with a CPG/MSSR block. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart --- drivers/clk/renesas/renesas-cpg-mssr.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 3e4d2609cc02..703bdb157528 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -381,8 +381,6 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, kfree(clock); } - -#ifdef CONFIG_PM_GENERIC_DOMAINS_OF struct cpg_mssr_clk_domain { struct generic_pm_domain genpd; struct device_node *np; @@ -497,15 +495,6 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, of_genpd_add_provider_simple(np, genpd); return 0; } -#else -static inline int cpg_mssr_add_clk_domain(struct device *dev, - const unsigned int *core_pm_clks, - unsigned int num_core_pm_clks) -{ - return 0; -} -#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */ - static const struct of_device_id cpg_mssr_match[] = { #ifdef CONFIG_ARCH_R8A7795 -- GitLab From 12a56817b329d8a73ab53bad09aa976aeea46db9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 4 Mar 2016 16:59:26 +0100 Subject: [PATCH 1703/9938] clk: renesas: mstp: Clarify cpg_mstp_{at,de}tach_dev() domain parameter Make it clear that the "domain" parameter of the cpg_mstp_attach_dev() and cpg_mstp_detach_dev() functions is not used. The cpg_mstp_attach_dev() and cpg_mstp_detach_dev() callbacks are not only used by the CPG/MSTP Clock Domain driver, but also by the R-Mobile SYSC PM Domain driver. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/clk-mstp.c | 4 ++-- include/linux/clk/renesas.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 5e3b3d856eef..8b597b9a3804 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c @@ -243,7 +243,7 @@ static void __init cpg_mstp_clocks_init(struct device_node *np) } CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init); -int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev) +int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev) { struct device_node *np = dev->of_node; struct of_phandle_args clkspec; @@ -295,7 +295,7 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev) return error; } -void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev) +void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev) { if (!list_empty(&dev->power.subsys_data->clock_list)) pm_clk_destroy(dev); diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 2a3379cf1330..095b1681daf4 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -25,7 +25,7 @@ void r8a7779_clocks_init(u32 mode); void rcar_gen2_clocks_init(u32 mode); void cpg_mstp_add_clk_domain(struct device_node *np); -int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev); -void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev); +int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev); +void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev); #endif -- GitLab From b131129d96575479e2447d134cb1797cf430b3a4 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Apr 2016 12:07:29 +0530 Subject: [PATCH 1704/9938] ath10k: fix calibration init sequence of qca99x0 pre-calibration is meant for qca4019 which contains only caldata whereas calibration file is used by ar9888 and qca99x0 that contains both board data and caldata. So by definition both pre-cal-file and cal-file can not coexist. Keeping them in shared memory (union), is breaking boot sequence of qca99x0. Fix it by storing both binaries in separate memories. This issue is reported in ipq8064 platform which includes caldata in flash memory. Fixes: 3d9195ea19e4 ("ath10k: incorporate qca4019 cal data download sequence") Reported-by: Sebastian Gottschall Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index c23c37312ef7..d85b99164212 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -728,10 +728,8 @@ struct ath10k { const void *firmware_data; size_t firmware_len; - union { - const struct firmware *pre_cal_file; - const struct firmware *cal_file; - }; + const struct firmware *pre_cal_file; + const struct firmware *cal_file; struct { const void *firmware_codeswap_data; -- GitLab From dd7c280f9bf5ee6c7c46f03b2064f9f8fb617183 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Apr 2016 12:07:30 +0530 Subject: [PATCH 1705/9938] ath10k: remove unnecessary warning for probe response drops qca99x0 and qca4019 solutions limit probe responses transmissions. Logging warning message for each probe response drop is flooding kernel log unnecessary with " failed to increase tx mgmt pending count: -16, dropping". Hence reducing log level to debug. Reported-by: Sebastian Gottschall Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 20d72e29dfa1..b0e613bc10a5 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3994,8 +3994,8 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp); if (ret) { - ath10k_warn(ar, "failed to increase tx mgmt pending count: %d, dropping\n", - ret); + ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n", + ret); ath10k_htt_tx_dec_pending(htt); spin_unlock_bh(&ar->htt.tx_lock); ieee80211_free_txskb(ar->hw, skb); -- GitLab From 689de38e37179c6f524dd003e1dae92042f8f5cd Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Apr 2016 12:07:31 +0530 Subject: [PATCH 1706/9938] ath10k: fix unconditional num_mpdus_ready subtraction Decrement num_mpdus_ready only when rx amsdu is processed successfully. Not doing so, will result in leak and impact stabilty under low memory cases. Also commit 3128b3d8a2b9 ("ath10k: speedup htt rx descriptor processing for rx_ind") missed to removed unused skb list rx_q. Fixes: 3128b3d8a2b9 ("ath10k: speedup htt rx descriptor processing for rx_ind") Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 592421ec5635..6a2d2643de42 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2412,14 +2412,12 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) struct ath10k_htt *htt = (struct ath10k_htt *)ptr; struct ath10k *ar = htt->ar; struct htt_tx_done tx_done = {}; - struct sk_buff_head rx_q; struct sk_buff_head rx_ind_q; struct sk_buff_head tx_ind_q; struct sk_buff *skb; unsigned long flags; int num_mpdus; - __skb_queue_head_init(&rx_q); __skb_queue_head_init(&rx_ind_q); __skb_queue_head_init(&tx_ind_q); @@ -2447,11 +2445,13 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) ath10k_mac_tx_push_pending(ar); num_mpdus = atomic_read(&htt->num_mpdus_ready); - atomic_sub(num_mpdus, &htt->num_mpdus_ready); - while (num_mpdus--) { + while (num_mpdus) { if (ath10k_htt_rx_handle_amsdu(htt)) break; + + num_mpdus--; + atomic_dec(&htt->num_mpdus_ready); } while ((skb = __skb_dequeue(&rx_ind_q))) { -- GitLab From 8501786929de4616b10b8059ad97abd304a7dddf Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 6 Apr 2016 22:07:34 -0700 Subject: [PATCH 1707/9938] tcp/dccp: fix inet_reuseport_add_sock() David Ahern reported panics in __inet_hash() caused by my recent commit. The reason is inet_reuseport_add_sock() was still using sk_nulls_for_each_rcu() instead of sk_for_each_rcu(). SO_REUSEPORT enabled listeners were causing an instant crash. While chasing this bug, I found that I forgot to clear SOCK_RCU_FREE flag, as it is inherited from the parent at clone time. Fixes: 3b24d854cb35 ("tcp/dccp: do not touch listener sk_refcnt under synflood") Signed-off-by: Eric Dumazet Reported-by: David Ahern Tested-by: David Ahern Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 3 +++ net/ipv4/inet_hashtables.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index bc5196ea1bdf..ab69da2d2a77 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -661,6 +661,9 @@ struct sock *inet_csk_clone_lock(const struct sock *sk, inet_sk(newsk)->inet_sport = htons(inet_rsk(req)->ir_num); newsk->sk_write_space = sk_stream_write_space; + /* listeners have SOCK_RCU_FREE, not the children */ + sock_reset_flag(newsk, SOCK_RCU_FREE); + newsk->sk_mark = inet_rsk(req)->ir_mark; atomic64_set(&newsk->sk_cookie, atomic64_read(&inet_rsk(req)->ir_cookie)); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 98ba03b6f87d..fcadb670f50b 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -439,10 +439,9 @@ static int inet_reuseport_add_sock(struct sock *sk, bool match_wildcard)) { struct sock *sk2; - struct hlist_nulls_node *node; kuid_t uid = sock_i_uid(sk); - sk_nulls_for_each_rcu(sk2, node, &ilb->head) { + sk_for_each_rcu(sk2, &ilb->head) { if (sk2 != sk && sk2->sk_family == sk->sk_family && ipv6_only_sock(sk2) == ipv6_only_sock(sk) && -- GitLab From 0fef3c768037169f656fc4ae89cf88ff7175e586 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Fri, 18 Mar 2016 13:16:26 +1100 Subject: [PATCH 1708/9938] ath9k: Remove unnecessary ?: operator "(thermometer < 0) ? 0 : (thermometer == X)" is equivalent to "thermometer == X" for X >= 0. Signed-off-by: Ivan Safonov [Updated commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 54ed2f72d35e..a049f8d34f99 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4097,16 +4097,16 @@ static void ar9003_hw_thermometer_apply(struct ath_hw *ah) REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); - therm_on = (thermometer < 0) ? 0 : (thermometer == 0); + therm_on = thermometer == 0; REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); if (pCap->chip_chainmask & BIT(1)) { - therm_on = (thermometer < 0) ? 0 : (thermometer == 1); + therm_on = thermometer == 1; REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); } if (pCap->chip_chainmask & BIT(2)) { - therm_on = (thermometer < 0) ? 0 : (thermometer == 2); + therm_on = thermometer == 2; REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); } -- GitLab From ea544aab42dbf35c7b8e80f931db400f4b5add60 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 18 Mar 2016 13:20:59 +1100 Subject: [PATCH 1709/9938] ipw2x00: use to_pci_dev() Use to_pci_dev() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Julian Calaby Acked-by: Stanislav Yakovlev Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/ipw2x00/ipw2100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index f93a7f71c047..717320b17622 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -3521,7 +3521,7 @@ static void ipw2100_msg_free(struct ipw2100_priv *priv) static ssize_t show_pci(struct device *d, struct device_attribute *attr, char *buf) { - struct pci_dev *pci_dev = container_of(d, struct pci_dev, dev); + struct pci_dev *pci_dev = to_pci_dev(d); char *out = buf; int i, j; u32 val; -- GitLab From 61383412f00d5917a28f388c59ebd78cf7c9d909 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 18 Mar 2016 13:21:28 +1100 Subject: [PATCH 1710/9938] wlcore: use to_delayed_work() Use to_delayed_work() instead of open-coding it. Signed-off-by: Geliang Tang [Update commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/main.c | 10 +++++----- drivers/net/wireless/ti/wlcore/ps.c | 2 +- drivers/net/wireless/ti/wlcore/scan.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index dde36203ca42..a872a07a484c 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -243,7 +243,7 @@ static void wl12xx_tx_watchdog_work(struct work_struct *work) struct delayed_work *dwork; struct wl1271 *wl; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wl = container_of(dwork, struct wl1271, tx_watchdog_work); mutex_lock(&wl->mutex); @@ -2011,7 +2011,7 @@ static void wlcore_channel_switch_work(struct work_struct *work) struct wl12xx_vif *wlvif; int ret; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wlvif = container_of(dwork, struct wl12xx_vif, channel_switch_work); wl = wlvif->wl; @@ -2047,7 +2047,7 @@ static void wlcore_connection_loss_work(struct work_struct *work) struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wlvif = container_of(dwork, struct wl12xx_vif, connection_loss_work); wl = wlvif->wl; @@ -2076,7 +2076,7 @@ static void wlcore_pending_auth_complete_work(struct work_struct *work) unsigned long time_spare; int ret; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wlvif = container_of(dwork, struct wl12xx_vif, pending_auth_complete_work); wl = wlvif->wl; @@ -5588,7 +5588,7 @@ static void wlcore_roc_complete_work(struct work_struct *work) struct wl1271 *wl; int ret; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wl = container_of(dwork, struct wl1271, roc_complete_work); ret = wlcore_roc_completed(wl); diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 4cd316e61466..d4420da637d8 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c @@ -38,7 +38,7 @@ void wl1271_elp_work(struct work_struct *work) struct wl12xx_vif *wlvif; int ret; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wl = container_of(dwork, struct wl1271, elp_work); wl1271_debug(DEBUG_PSM, "elp work"); diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index 1e3d51cd673a..a384f3f83099 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -38,7 +38,7 @@ void wl1271_scan_complete_work(struct work_struct *work) struct wl12xx_vif *wlvif; int ret; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wl = container_of(dwork, struct wl1271, scan_complete_work); wl1271_debug(DEBUG_SCAN, "Scanning complete"); -- GitLab From d1162f0283f0b4421d1098dd048a5e3cf8b2abb6 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 18 Mar 2016 13:22:03 +1100 Subject: [PATCH 1711/9938] wl1251: use to_delayed_work() Use to_delayed_work() instead of open-coding it. Signed-off-by: Geliang Tang [Update commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wl1251/ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wl1251/ps.c b/drivers/net/wireless/ti/wl1251/ps.c index b9e27b98bbc9..fa01b0a0f312 100644 --- a/drivers/net/wireless/ti/wl1251/ps.c +++ b/drivers/net/wireless/ti/wl1251/ps.c @@ -32,7 +32,7 @@ void wl1251_elp_work(struct work_struct *work) struct delayed_work *dwork; struct wl1251 *wl; - dwork = container_of(work, struct delayed_work, work); + dwork = to_delayed_work(work); wl = container_of(dwork, struct wl1251, elp_work); wl1251_debug(DEBUG_PSM, "elp work"); -- GitLab From 4679f41322012cf69b1035cde3de81151d2aefec Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 18 Mar 2016 13:22:24 +1100 Subject: [PATCH 1712/9938] rtlwifi: use to_delayed_work() Use to_delayed_work() instead of open-coding it. Signed-off-by: Geliang Tang [Update commit message] Signed-off-by: Julian Calaby Acked-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/wifi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 93bd7fcd2b61..389dc47776c0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2870,7 +2870,7 @@ value to host byte ordering.*/ (ppsc->cur_ps_level |= _ps_flg) #define container_of_dwork_rtl(x, y, z) \ - container_of(container_of(x, struct delayed_work, work), y, z) + container_of(to_delayed_work(x), y, z) #define FILL_OCTET_STRING(_os, _octet, _len) \ (_os).octet = (u8 *)(_octet); \ -- GitLab From cfbfbd13695c8f9a93b1ad3edeeedacbb86dbe5c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 18 Mar 2016 13:22:52 +1100 Subject: [PATCH 1713/9938] ath9k_htc: Delete unnecessary variable initialisation In ath9k_hif_usb_rx_stream(), i is initialised in the for loop it's used in. Signed-off-by: Markus Elfring Reviewed-by: Oleksij Rempel [Rewrote commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 8cbf4904db7b..e1c338cb9cb5 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -527,7 +527,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, struct sk_buff *skb) { struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; - int index = 0, i = 0, len = skb->len; + int index = 0, i, len = skb->len; int rx_remain_len, rx_pkt_len; u16 pool_index = 0; u8 *ptr; -- GitLab From 9e12904a953c46abc87b0ea157be8de90205b70d Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 18 Mar 2016 13:23:24 +1100 Subject: [PATCH 1714/9938] brcmfmac: Delete unnecessary variable initialisation In brcmf_sdio_download_firmware(), bcmerror is set by the call to brcmf_sdio_download_code_file(), before it's checked in the following line. Signed-off-by: Markus Elfring Acked-by: Arend van Spriel [Rewrote commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index cd92ba77ecfd..48d7467d270e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3258,7 +3258,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, const struct firmware *fw, void *nvram, u32 nvlen) { - int bcmerror = -EFAULT; + int bcmerror; u32 rstvec; sdio_claim_host(bus->sdiodev->func[1]); -- GitLab From fb9693f04544068e6176051ce5b96e4574730107 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 18 Mar 2016 13:23:46 +1100 Subject: [PATCH 1715/9938] iwlegacy: Return directly if allocation fails in il_eeprom_init() Also remove an unused label. Signed-off-by: Markus Elfring Acked-by: Stanislaw Gruszka [Rewrote commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlegacy/common.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index eb5cb603bc52..c3afaf71066e 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -723,10 +723,9 @@ il_eeprom_init(struct il_priv *il) sz = il->cfg->eeprom_size; D_EEPROM("NVM size = %d\n", sz); il->eeprom = kzalloc(sz, GFP_KERNEL); - if (!il->eeprom) { - ret = -ENOMEM; - goto alloc_err; - } + if (!il->eeprom) + return -ENOMEM; + e = (__le16 *) il->eeprom; il->ops->apm_init(il); @@ -778,7 +777,6 @@ il_eeprom_init(struct il_priv *il) il_eeprom_free(il); /* Reset chip to save power until we load uCode during "up". */ il_apm_stop(il); -alloc_err: return ret; } EXPORT_SYMBOL(il_eeprom_init); -- GitLab From fe9b47944edff9b6244c4f5e81bd7b50574dc22b Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 18 Mar 2016 13:24:06 +1100 Subject: [PATCH 1716/9938] iwl4965: Fix a null pointer dereference in il_tx_queue_free and il_cmd_queue_free If "txq->cmd = kzalloc(...)" in il_tx_queue_init fails, "kfree(txq->cmd[i])" in il_tx_queue_free and il_cmd_queue_free in iwl4965_hw_txq_ctx_free will causes a null pointer dereference, because txq->cmd is NULL at that time. This patch fixes this problem by adding a if-check before kfree. To avoid double free in il_tx_queue_free and il_cmd_queue_free caused by the fixing, txq->meta and txq->cmd in error handling code of il_tx_queue_init are assigned null values. Otherwise, a double free will occur. This patch has been tested in real device, and it actually fixes the bug. Thanks Stanislaw for his suggestion. Signed-off-by: Jia-Ju Bai Acked-by: Stanislaw Gruszka Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlegacy/common.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index c3afaf71066e..2cc3d42bbab7 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -2792,8 +2792,10 @@ il_tx_queue_free(struct il_priv *il, int txq_id) il_tx_queue_unmap(il, txq_id); /* De-alloc array of command/tx buffers */ - for (i = 0; i < TFD_TX_CMD_SLOTS; i++) - kfree(txq->cmd[i]); + if (txq->cmd) { + for (i = 0; i < TFD_TX_CMD_SLOTS; i++) + kfree(txq->cmd[i]); + } /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) @@ -2871,8 +2873,10 @@ il_cmd_queue_free(struct il_priv *il) il_cmd_queue_unmap(il); /* De-alloc array of command/tx buffers */ - for (i = 0; i <= TFD_CMD_SLOTS; i++) - kfree(txq->cmd[i]); + if (txq->cmd) { + for (i = 0; i <= TFD_CMD_SLOTS; i++) + kfree(txq->cmd[i]); + } /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) @@ -3078,7 +3082,9 @@ il_tx_queue_init(struct il_priv *il, u32 txq_id) kfree(txq->cmd[i]); out_free_arrays: kfree(txq->meta); + txq->meta = NULL; kfree(txq->cmd); + txq->cmd = NULL; return -ENOMEM; } -- GitLab From 96838d61102a0fca20a7bda7289e0492aaf11896 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 18 Mar 2016 13:24:28 +1100 Subject: [PATCH 1717/9938] b43: Fix memory leaks in b43_bus_dev_ssb_init and b43_bus_dev_bcma_init The memory allocated by kzalloc in b43_bus_dev_ssb_init and b43_bus_dev_bcma_init is not freed. This patch fixes the bug by adding kfree in b43_ssb_remove, b43_bcma_remove and error handling code of b43_bcma_probe. Thanks Michael for his suggestion. Signed-off-by: Jia-Ju Bai Tested-by: Sudip Mukherjee Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/b43/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index 72380af9dc52..b0603e796ad8 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -5680,11 +5680,12 @@ static int b43_bcma_probe(struct bcma_device *core) INIT_WORK(&wl->firmware_load, b43_request_firmware); schedule_work(&wl->firmware_load); -bcma_out: return err; bcma_err_wireless_exit: ieee80211_free_hw(wl->hw); +bcma_out: + kfree(dev); return err; } @@ -5712,8 +5713,8 @@ static void b43_bcma_remove(struct bcma_device *core) b43_rng_exit(wl); b43_leds_unregister(wl); - ieee80211_free_hw(wl->hw); + kfree(wldev->dev); } static struct bcma_driver b43_bcma_driver = { @@ -5796,6 +5797,7 @@ static void b43_ssb_remove(struct ssb_device *sdev) b43_leds_unregister(wl); b43_wireless_exit(dev, wl); + kfree(dev); } static struct ssb_driver b43_ssb_driver = { -- GitLab From 1c76b4902c26c73283bb3578829dd0cfe53ce10a Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 18 Mar 2016 13:24:51 +1100 Subject: [PATCH 1718/9938] rtl818x_pci: Disable pci device in error handling code When pci_request_regions in rtl8180_probe fails, pci_disable_device is not called to disable the device which is enabled by pci_enbale_device. This patch fixes the problem by adding a new lable in error handling code. Signed-off-by: Jia-Ju Bai Acked-by: Andrea Merello Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index a43a16fde59d..c76af5d8b8e0 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -1736,7 +1736,7 @@ static int rtl8180_probe(struct pci_dev *pdev, if (err) { printk(KERN_ERR "%s (rtl8180): Cannot obtain PCI resources\n", pci_name(pdev)); - return err; + goto err_disable_dev; } io_addr = pci_resource_start(pdev, 0); @@ -1938,6 +1938,8 @@ static int rtl8180_probe(struct pci_dev *pdev, err_free_reg: pci_release_regions(pdev); + + err_disable_dev: pci_disable_device(pdev); return err; } -- GitLab From 8b28310efe241339248e875400c6da16f5d91c1f Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 18 Mar 2016 13:25:13 +1100 Subject: [PATCH 1719/9938] rsi: Delete unnecessary variable initialisation In rsi_send_mgmt_pkt(), the following variables are assigned to before they're used: * wh - Assigned on line 161, first used on line 180 * bss - Assigned on line 160, first used on line 196 * msg - Assigned on line 168, first used on line 175 * extnd_size - Assigned on line 139, first used on line 142 Signed-off-by: Markus Elfring [Rewrote commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_pkt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c index 702593f19997..571eaba368dc 100644 --- a/drivers/net/wireless/rsi/rsi_91x_pkt.c +++ b/drivers/net/wireless/rsi/rsi_91x_pkt.c @@ -123,15 +123,15 @@ int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb) { struct rsi_hw *adapter = common->priv; - struct ieee80211_hdr *wh = NULL; + struct ieee80211_hdr *wh; struct ieee80211_tx_info *info; - struct ieee80211_bss_conf *bss = NULL; + struct ieee80211_bss_conf *bss; struct ieee80211_hw *hw = adapter->hw; struct ieee80211_conf *conf = &hw->conf; struct skb_info *tx_params; int status = -E2BIG; - __le16 *msg = NULL; - u8 extnd_size = 0; + __le16 *msg; + u8 extnd_size; u8 vap_id = 0; info = IEEE80211_SKB_CB(skb); -- GitLab From ab2ef1d68f62d9e2ec6e494668f288fc000fe886 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 18 Mar 2016 13:25:33 +1100 Subject: [PATCH 1720/9938] rsi: Delete unnecessary variable initialisation In rsi_send_data_pkt(), the following variables are assigned to before they're used: * tmp_hdr - Assigned on line 47, first used on line 48 * bss - Assigned on line 41, first used on line 44 * extnd_size - Assigned on line 50, first used on line 52 * seq_num - Assigned on line 48, first used on line 96 Signed-off-by: Markus Elfring [Rewrote commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_pkt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c index 571eaba368dc..4322df1fefdc 100644 --- a/drivers/net/wireless/rsi/rsi_91x_pkt.c +++ b/drivers/net/wireless/rsi/rsi_91x_pkt.c @@ -27,15 +27,15 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb) { struct rsi_hw *adapter = common->priv; - struct ieee80211_hdr *tmp_hdr = NULL; + struct ieee80211_hdr *tmp_hdr; struct ieee80211_tx_info *info; struct skb_info *tx_params; - struct ieee80211_bss_conf *bss = NULL; + struct ieee80211_bss_conf *bss; int status = -EINVAL; u8 ieee80211_size = MIN_802_11_HDR_LEN; - u8 extnd_size = 0; + u8 extnd_size; __le16 *frame_desc; - u16 seq_num = 0; + u16 seq_num; info = IEEE80211_SKB_CB(skb); bss = &info->control.vif->bss_conf; -- GitLab From 37190b2694911552c09119e2b23e65049bf47a1e Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 18 Mar 2016 13:27:31 +1100 Subject: [PATCH 1721/9938] rsi: Move variable initialisation into error code In rsi_send_data_pkt(), it's a little more logical to assign 'status' in the actual error handling code as opposed to at the top of the functon. Signed-off-by: Markus Elfring [Deleted controversial bits, rewrote commit message] Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_pkt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c index 4322df1fefdc..a0b31c0cf25b 100644 --- a/drivers/net/wireless/rsi/rsi_91x_pkt.c +++ b/drivers/net/wireless/rsi/rsi_91x_pkt.c @@ -31,7 +31,7 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb) struct ieee80211_tx_info *info; struct skb_info *tx_params; struct ieee80211_bss_conf *bss; - int status = -EINVAL; + int status; u8 ieee80211_size = MIN_802_11_HDR_LEN; u8 extnd_size; __le16 *frame_desc; @@ -41,8 +41,10 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb) bss = &info->control.vif->bss_conf; tx_params = (struct skb_info *)info->driver_data; - if (!bss->assoc) + if (!bss->assoc) { + status = -EINVAL; goto err; + } tmp_hdr = (struct ieee80211_hdr *)&skb->data[0]; seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4); -- GitLab From c2fd34469d1623111e3c3db65cde533f3bddc26e Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 18 Mar 2016 13:28:33 +1100 Subject: [PATCH 1722/9938] iwl4965: Fix a memory leak in error handling code of __il4965_up When il4965_hw_nic_init in __il4965_up fails, the memory allocated by iwl4965_sta_alloc_lq in iwl4965_alloc_bcast_station is not freed. This patches adds il_dealloc_bcast_stations in the error handling code of __il4965_up to fix this problem. This patch has been tested in real device, and it actually fixes the bug. Signed-off-by: Jia-Ju Bai Acked-by: Stanislaw Gruszka Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlegacy/4965-mac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index b75f4ef3cdc7..30d9dd3dda53 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -5577,6 +5577,7 @@ __il4965_up(struct il_priv *il) ret = il4965_hw_nic_init(il); if (ret) { IL_ERR("Unable to init nic\n"); + il_dealloc_bcast_stations(il); return ret; } -- GitLab From 84d17a2a5a0f9e19e25d0472f0528996d945826e Mon Sep 17 00:00:00 2001 From: Julian Calaby Date: Fri, 18 Mar 2016 13:29:11 +1100 Subject: [PATCH 1723/9938] iwl4965: Fix more memory leaks in __il4965_up() In some of the non-success return paths, the memory allocated by iwl4965_sta_alloc_lq() in iwl4965_alloc_bcast_station() is not freed. In particular: - if the card isn't ready after il4965_prepare_card_hw() - if the card is hardware-rfkilled In the hardware rfkilled path, the driver enables the rfkill interrupt. When the card is unrfkilled and this interrupt is raised we end up calling il4965_bg_restart() which calls __il4965_up() which calls iwl4965_alloc_bcast_station() again. Suggested-by: Jia-Ju Bai Signed-off-by: Julian Calaby Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlegacy/4965-mac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index 30d9dd3dda53..f9ed48070e17 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -5553,6 +5553,7 @@ __il4965_up(struct il_priv *il) il4965_prepare_card_hw(il); if (!il->hw_ready) { + il_dealloc_bcast_stations(il); IL_ERR("HW not ready\n"); return -EIO; } @@ -5564,6 +5565,7 @@ __il4965_up(struct il_priv *il) set_bit(S_RFKILL, &il->status); wiphy_rfkill_set_hw_state(il->hw->wiphy, true); + il_dealloc_bcast_stations(il); il_enable_rfkill_int(il); IL_WARN("Radio disabled by HW RF Kill switch\n"); return 0; -- GitLab From 001351881da1822b06e5d92e1fa2bf4920318e8c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 28 Mar 2016 16:53:33 +0100 Subject: [PATCH 1724/9938] mwifiex: ie_list is an array, so no need to check if NULL ap_ie->ie_list is an array of struct mwifiex_ie and can never be null, so the null check on this array is redundant and can be removed. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/uap_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c index 16d95b22fe5c..92ce32f5bb13 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c @@ -694,7 +694,7 @@ static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size) struct mwifiex_ie_list *ap_ie = cmd_buf; struct mwifiex_ie_types_header *tlv_ie = (void *)tlv; - if (!ap_ie || !ap_ie->len || !ap_ie->ie_list) + if (!ap_ie || !ap_ie->len) return -1; *ie_size += le16_to_cpu(ap_ie->len) + -- GitLab From a5c92f0b6a88a8abe3840869425f1372591a762c Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Wed, 30 Mar 2016 18:14:55 +0800 Subject: [PATCH 1725/9938] mwifiex: fix NULL pointer dereference error In mwifiex_enable_hs, we need to check if priv->wdev.wiphy->wowlan_config is NULL before accessing its member. This sometimes cause kernel panic when suspend/resume. Signed-off-by: Wei-Ning Huang Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index d5c56eb9e985..d8de432d46a2 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -509,7 +509,8 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) if (priv && priv->sched_scanning) { #ifdef CONFIG_PM - if (!priv->wdev.wiphy->wowlan_config->nd_config) { + if (priv->wdev.wiphy->wowlan_config && + !priv->wdev.wiphy->wowlan_config->nd_config) { #endif mwifiex_dbg(adapter, CMD, "aborting bgscan!\n"); mwifiex_stop_bg_scan(priv); -- GitLab From dbb2896b485e79be55bacd891db60c85f010045f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:33 -0400 Subject: [PATCH 1726/9938] rtl8xxxu: Change name of struct tx_desc to be more decriptive There are two major types of TX descriptor formats for the RTL parts, the old 32 byte descriptor, and the newer 40 byte descriptor used by the 8723bu, 8192eu, and 88xx series. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 20 +++++++++---------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index abdff458b80f..13feb18ffa8e 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7014,7 +7014,7 @@ static u32 rtl8xxxu_queue_select(struct ieee80211_hw *hw, struct sk_buff *skb) * format. The descriptor checksum is still only calculated over the * initial 32 bytes of the descriptor! */ -static void rtl8xxxu_calc_tx_desc_csum(struct rtl8723au_tx_desc *tx_desc) +static void rtl8xxxu_calc_tx_desc_csum(struct rtl8xxxu_txdesc32 *tx_desc) { __le16 *ptr = (__le16 *)tx_desc; u16 csum = 0; @@ -7026,7 +7026,7 @@ static void rtl8xxxu_calc_tx_desc_csum(struct rtl8723au_tx_desc *tx_desc) */ tx_desc->csum = cpu_to_le16(0); - for (i = 0; i < (sizeof(struct rtl8723au_tx_desc) / sizeof(u16)); i++) + for (i = 0; i < (sizeof(struct rtl8xxxu_txdesc32) / sizeof(u16)); i++) csum = csum ^ le16_to_cpu(ptr[i]); tx_desc->csum |= cpu_to_le16(csum); @@ -7164,8 +7164,8 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); struct rtl8xxxu_priv *priv = hw->priv; - struct rtl8723au_tx_desc *tx_desc; - struct rtl8723bu_tx_desc *tx_desc40; + struct rtl8xxxu_txdesc32 *tx_desc; + struct rtl8xxxu_txdesc40 *tx_desc40; struct rtl8xxxu_tx_urb *tx_urb; struct ieee80211_sta *sta = NULL; struct ieee80211_vif *vif = tx_info->control.vif; @@ -7210,7 +7210,7 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, if (control && control->sta) sta = control->sta; - tx_desc = (struct rtl8723au_tx_desc *)skb_push(skb, tx_desc_size); + tx_desc = (struct rtl8xxxu_txdesc32 *)skb_push(skb, tx_desc_size); memset(tx_desc, 0, tx_desc_size); tx_desc->pkt_size = cpu_to_le16(pktlen); @@ -7314,7 +7314,7 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, cpu_to_le32(TXDESC_HW_RTS_ENABLE_8723A); } } else { - tx_desc40 = (struct rtl8723bu_tx_desc *)tx_desc; + tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc; tx_desc40->txdw4 = cpu_to_le32(rate); if (ieee80211_is_data(hdr->frame_control)) { @@ -8454,7 +8454,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, - .tx_desc_size = sizeof(struct rtl8723au_tx_desc), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), .adda_1t_init = 0x0b1b25a0, .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, @@ -8482,7 +8482,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, - .tx_desc_size = sizeof(struct rtl8723bu_tx_desc), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), .has_s0s1 = 1, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, @@ -8510,7 +8510,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, - .tx_desc_size = sizeof(struct rtl8723au_tx_desc), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), .adda_1t_init = 0x0b1b25a0, .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, @@ -8537,7 +8537,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, - .tx_desc_size = sizeof(struct rtl8723au_tx_desc), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), .has_s0s1 = 1, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 7b73654e1368..05579a038a8f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -332,7 +332,7 @@ struct rtl8723bu_rx_desc { __le32 tsfl; }; -struct rtl8723au_tx_desc { +struct rtl8xxxu_txdesc32 { __le16 pkt_size; u8 pkt_offset; u8 txdw0; @@ -346,7 +346,7 @@ struct rtl8723au_tx_desc { __le16 txdw7; }; -struct rtl8723bu_tx_desc { +struct rtl8xxxu_txdesc40 { __le16 pkt_size; u8 pkt_offset; u8 txdw0; -- GitLab From 33f3724948422bc594ffd976ec4272b653562414 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:34 -0400 Subject: [PATCH 1727/9938] rtl8xxxu: Rename TX descriptor bits to map them to 32/40 byte descriptors With the size based naming of TX descriptors. Change the bit definition namings to indicate which descriptor format they match, rather than having a device name in the bit name. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 51 +++++----- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 98 +++++++++---------- 2 files changed, 71 insertions(+), 78 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 13feb18ffa8e..d7363165547a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7267,31 +7267,29 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, tx_desc->txdw5 |= cpu_to_le32(0x0001ff00); tx_desc->txdw3 = - cpu_to_le32((u32)seq_number << TXDESC_SEQ_SHIFT_8723A); + cpu_to_le32((u32)seq_number << TXDESC32_SEQ_SHIFT); if (ampdu_enable) - tx_desc->txdw1 |= cpu_to_le32(TXDESC_AGG_ENABLE_8723A); + tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_ENABLE); else - tx_desc->txdw1 |= cpu_to_le32(TXDESC_AGG_BREAK_8723A); + tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_BREAK); if (ieee80211_is_mgmt(hdr->frame_control)) { tx_desc->txdw5 = cpu_to_le32(tx_rate->hw_value); tx_desc->txdw4 |= - cpu_to_le32(TXDESC_USE_DRIVER_RATE_8723A); + cpu_to_le32(TXDESC32_USE_DRIVER_RATE); tx_desc->txdw5 |= - cpu_to_le32(6 << - TXDESC_RETRY_LIMIT_SHIFT_8723A); + cpu_to_le32(6 << TXDESC32_RETRY_LIMIT_SHIFT); tx_desc->txdw5 |= - cpu_to_le32(TXDESC_RETRY_LIMIT_ENABLE_8723A); + cpu_to_le32(TXDESC32_RETRY_LIMIT_ENABLE); } if (ieee80211_is_data_qos(hdr->frame_control)) - tx_desc->txdw4 |= cpu_to_le32(TXDESC_QOS_8723A); + tx_desc->txdw4 |= cpu_to_le32(TXDESC32_QOS); if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE || (sta && vif && vif->bss_conf.use_short_preamble)) - tx_desc->txdw4 |= - cpu_to_le32(TXDESC_SHORT_PREAMBLE_8723A); + tx_desc->txdw4 |= cpu_to_le32(TXDESC32_SHORT_PREAMBLE); if (rate_flag & IEEE80211_TX_RC_SHORT_GI || (ieee80211_is_data_qos(hdr->frame_control) && @@ -7307,11 +7305,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, */ tx_desc->txdw4 |= cpu_to_le32(DESC_RATE_24M << - TXDESC_RTS_RATE_SHIFT_8723A); - tx_desc->txdw4 |= - cpu_to_le32(TXDESC_RTS_CTS_ENABLE_8723A); + TXDESC32_RTS_RATE_SHIFT); tx_desc->txdw4 |= - cpu_to_le32(TXDESC_HW_RTS_ENABLE_8723A); + cpu_to_le32(TXDESC32_RTS_CTS_ENABLE); + tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); } } else { tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc; @@ -7320,33 +7317,31 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, if (ieee80211_is_data(hdr->frame_control)) { tx_desc->txdw4 |= cpu_to_le32(0x1f << - TXDESC_DATA_RATE_FB_SHIFT_8723B); + TXDESC40_DATA_RATE_FB_SHIFT); } tx_desc40->txdw9 = - cpu_to_le32((u32)seq_number << TXDESC_SEQ_SHIFT_8723B); + cpu_to_le32((u32)seq_number << TXDESC40_SEQ_SHIFT); if (ampdu_enable) - tx_desc40->txdw2 |= - cpu_to_le32(TXDESC_AGG_ENABLE_8723B); + tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_ENABLE); else - tx_desc40->txdw2 |= cpu_to_le32(TXDESC_AGG_BREAK_8723B); + tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_BREAK); if (ieee80211_is_mgmt(hdr->frame_control)) { tx_desc40->txdw4 = cpu_to_le32(tx_rate->hw_value); tx_desc40->txdw3 |= - cpu_to_le32(TXDESC_USE_DRIVER_RATE_8723B); + cpu_to_le32(TXDESC40_USE_DRIVER_RATE); tx_desc40->txdw4 |= - cpu_to_le32(6 << - TXDESC_RETRY_LIMIT_SHIFT_8723B); + cpu_to_le32(6 << TXDESC40_RETRY_LIMIT_SHIFT); tx_desc40->txdw4 |= - cpu_to_le32(TXDESC_RETRY_LIMIT_ENABLE_8723B); + cpu_to_le32(TXDESC40_RETRY_LIMIT_ENABLE); } if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE || (sta && vif && vif->bss_conf.use_short_preamble)) tx_desc40->txdw5 |= - cpu_to_le32(TXDESC_SHORT_PREAMBLE_8723B); + cpu_to_le32(TXDESC40_SHORT_PREAMBLE); if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { /* @@ -7355,11 +7350,9 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, */ tx_desc->txdw4 |= cpu_to_le32(DESC_RATE_24M << - TXDESC_RTS_RATE_SHIFT_8723B); - tx_desc->txdw3 |= - cpu_to_le32(TXDESC_RTS_CTS_ENABLE_8723B); - tx_desc->txdw3 |= - cpu_to_le32(TXDESC_HW_RTS_ENABLE_8723B); + TXDESC40_RTS_RATE_SHIFT); + tx_desc->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE); + tx_desc->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE); } } diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 05579a038a8f..38d4f5686f67 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -422,10 +422,10 @@ struct rtl8xxxu_txdesc40 { * aggregation enable and break respectively. For 8723bu, bits 0-7 are macid. */ #define TXDESC_PKT_OFFSET_SZ 0 -#define TXDESC_AGG_ENABLE_8723A BIT(5) -#define TXDESC_AGG_BREAK_8723A BIT(6) -#define TXDESC_MACID_SHIFT_8723B 0 -#define TXDESC_MACID_MASK_8723B 0x00f0 +#define TXDESC32_AGG_ENABLE BIT(5) +#define TXDESC32_AGG_BREAK BIT(6) +#define TXDESC40_MACID_SHIFT 0 +#define TXDESC40_MACID_MASK 0x00f0 #define TXDESC_QUEUE_SHIFT 8 #define TXDESC_QUEUE_MASK 0x1f00 #define TXDESC_QUEUE_BK 0x2 @@ -437,9 +437,9 @@ struct rtl8xxxu_txdesc40 { #define TXDESC_QUEUE_MGNT 0x12 #define TXDESC_QUEUE_CMD 0x13 #define TXDESC_QUEUE_MAX (TXDESC_QUEUE_CMD + 1) -#define TXDESC_RDG_NAV_EXT_8723B BIT(13) -#define TXDESC_LSIG_TXOP_ENABLE_8723B BIT(14) -#define TXDESC_PIFS_8723B BIT(15) +#define TXDESC40_RDG_NAV_EXT BIT(13) +#define TXDESC40_LSIG_TXOP_ENABLE BIT(14) +#define TXDESC40_PIFS BIT(15) #define DESC_RATE_ID_SHIFT 16 #define DESC_RATE_ID_MASK 0xf @@ -451,71 +451,71 @@ struct rtl8xxxu_txdesc40 { #define TXDESC_HWPC BIT(31) /* Word 2 */ -#define TXDESC_PAID_SHIFT_8723B 0 -#define TXDESC_PAID_MASK_8723B 0x1ff -#define TXDESC_CCA_RTS_SHIFT_8723B 10 -#define TXDESC_CCA_RTS_MASK_8723B 0xc00 -#define TXDESC_AGG_ENABLE_8723B BIT(12) -#define TXDESC_RDG_ENABLE_8723B BIT(13) -#define TXDESC_AGG_BREAK_8723B BIT(16) -#define TXDESC_MORE_FRAG_8723B BIT(17) -#define TXDESC_RAW_8723B BIT(18) -#define TXDESC_ACK_REPORT_8723A BIT(19) -#define TXDESC_SPE_RPT_8723B BIT(19) +#define TXDESC40_PAID_SHIFT 0 +#define TXDESC40_PAID_MASK 0x1ff +#define TXDESC40_CCA_RTS_SHIFT 10 +#define TXDESC40_CCA_RTS_MASK 0xc00 +#define TXDESC40_AGG_ENABLE BIT(12) +#define TXDESC40_RDG_ENABLE BIT(13) +#define TXDESC40_AGG_BREAK BIT(16) +#define TXDESC40_MORE_FRAG BIT(17) +#define TXDESC40_RAW BIT(18) +#define TXDESC32_ACK_REPORT BIT(19) +#define TXDESC40_SPE_RPT BIT(19) #define TXDESC_AMPDU_DENSITY_SHIFT 20 -#define TXDESC_BT_INT_8723B BIT(23) -#define TXDESC_GID_8723B BIT(24) +#define TXDESC40_BT_INT BIT(23) +#define TXDESC40_GID BIT(24) /* Word 3 */ -#define TXDESC_USE_DRIVER_RATE_8723B BIT(8) -#define TXDESC_CTS_SELF_ENABLE_8723B BIT(11) -#define TXDESC_RTS_CTS_ENABLE_8723B BIT(12) -#define TXDESC_HW_RTS_ENABLE_8723B BIT(13) -#define TXDESC_SEQ_SHIFT_8723A 16 -#define TXDESC_SEQ_MASK_8723A 0x0fff0000 +#define TXDESC40_USE_DRIVER_RATE BIT(8) +#define TXDESC40_CTS_SELF_ENABLE BIT(11) +#define TXDESC40_RTS_CTS_ENABLE BIT(12) +#define TXDESC40_HW_RTS_ENABLE BIT(13) +#define TXDESC32_SEQ_SHIFT 16 +#define TXDESC32_SEQ_MASK 0x0fff0000 /* Word 4 */ -#define TXDESC_RTS_RATE_SHIFT_8723A 0 -#define TXDESC_RTS_RATE_MASK_8723A 0x3f -#define TXDESC_QOS_8723A BIT(6) -#define TXDESC_HW_SEQ_ENABLE_8723A BIT(7) -#define TXDESC_USE_DRIVER_RATE_8723A BIT(8) +#define TXDESC32_RTS_RATE_SHIFT 0 +#define TXDESC32_RTS_RATE_MASK 0x3f +#define TXDESC32_QOS BIT(6) +#define TXDESC32_HW_SEQ_ENABLE BIT(7) +#define TXDESC32_USE_DRIVER_RATE BIT(8) #define TXDESC_DISABLE_DATA_FB BIT(10) -#define TXDESC_CTS_SELF_ENABLE_8723A BIT(11) -#define TXDESC_RTS_CTS_ENABLE_8723A BIT(12) -#define TXDESC_HW_RTS_ENABLE_8723A BIT(13) +#define TXDESC32_CTS_SELF_ENABLE BIT(11) +#define TXDESC32_RTS_CTS_ENABLE BIT(12) +#define TXDESC32_HW_RTS_ENABLE BIT(13) #define TXDESC_PRIME_CH_OFF_LOWER BIT(20) #define TXDESC_PRIME_CH_OFF_UPPER BIT(21) -#define TXDESC_SHORT_PREAMBLE_8723A BIT(24) +#define TXDESC32_SHORT_PREAMBLE BIT(24) #define TXDESC_DATA_BW BIT(25) #define TXDESC_RTS_DATA_BW BIT(27) #define TXDESC_RTS_PRIME_CH_OFF_LOWER BIT(28) #define TXDESC_RTS_PRIME_CH_OFF_UPPER BIT(29) -#define TXDESC_DATA_RATE_FB_SHIFT_8723B 8 -#define TXDESC_DATA_RATE_FB_MASK_8723B 0x00001f00 -#define TXDESC_RETRY_LIMIT_ENABLE_8723B BIT(17) -#define TXDESC_RETRY_LIMIT_SHIFT_8723B 18 -#define TXDESC_RETRY_LIMIT_MASK_8723B 0x00fc0000 -#define TXDESC_RTS_RATE_SHIFT_8723B 24 -#define TXDESC_RTS_RATE_MASK_8723B 0x3f000000 +#define TXDESC40_DATA_RATE_FB_SHIFT 8 +#define TXDESC40_DATA_RATE_FB_MASK 0x00001f00 +#define TXDESC40_RETRY_LIMIT_ENABLE BIT(17) +#define TXDESC40_RETRY_LIMIT_SHIFT 18 +#define TXDESC40_RETRY_LIMIT_MASK 0x00fc0000 +#define TXDESC40_RTS_RATE_SHIFT 24 +#define TXDESC40_RTS_RATE_MASK 0x3f000000 /* Word 5 */ -#define TXDESC_SHORT_PREAMBLE_8723B BIT(4) +#define TXDESC40_SHORT_PREAMBLE BIT(4) #define TXDESC_SHORT_GI BIT(6) #define TXDESC_CCX_TAG BIT(7) -#define TXDESC_RETRY_LIMIT_ENABLE_8723A BIT(17) -#define TXDESC_RETRY_LIMIT_SHIFT_8723A 18 -#define TXDESC_RETRY_LIMIT_MASK_8723A 0x00fc0000 +#define TXDESC32_RETRY_LIMIT_ENABLE BIT(17) +#define TXDESC32_RETRY_LIMIT_SHIFT 18 +#define TXDESC32_RETRY_LIMIT_MASK 0x00fc0000 /* Word 6 */ #define TXDESC_MAX_AGG_SHIFT 11 /* Word 8 */ -#define TXDESC_HW_SEQ_ENABLE_8723B BIT(15) +#define TXDESC40_HW_SEQ_ENABLE BIT(15) /* Word 9 */ -#define TXDESC_SEQ_SHIFT_8723B 12 -#define TXDESC_SEQ_MASK_8723B 0x00fff000 +#define TXDESC40_SEQ_SHIFT 12 +#define TXDESC40_SEQ_MASK 0x00fff000 struct phy_rx_agc_info { #ifdef __LITTLE_ENDIAN -- GitLab From 169bc5cb0b8162d271c8fd38ff3d90b098241e16 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:35 -0400 Subject: [PATCH 1728/9938] rtl8xxxu: Correct txdesc40 gid definition txdesc40 dword2 gid is a 6 bit field, not a single bit Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 38d4f5686f67..af1d50482e12 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -464,7 +464,7 @@ struct rtl8xxxu_txdesc40 { #define TXDESC40_SPE_RPT BIT(19) #define TXDESC_AMPDU_DENSITY_SHIFT 20 #define TXDESC40_BT_INT BIT(23) -#define TXDESC40_GID BIT(24) +#define TXDESC40_GID_SHIFT 24 /* Word 3 */ #define TXDESC40_USE_DRIVER_RATE BIT(8) -- GitLab From 1df1de348572dff0fa7fb9c447d991c8dc1348f8 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:36 -0400 Subject: [PATCH 1729/9938] rtl8xxxu: TXDESC_SHORT_GI is txdesc32 only This is no short GI bit in the txdesc40 format. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index d7363165547a..484d08fe80cd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7295,7 +7295,7 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, (ieee80211_is_data_qos(hdr->frame_control) && sta && sta->ht_cap.cap & (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))) { - tx_desc->txdw5 |= cpu_to_le32(TXDESC_SHORT_GI); + tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI); } if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index af1d50482e12..f211c5db753f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -501,7 +501,7 @@ struct rtl8xxxu_txdesc40 { /* Word 5 */ #define TXDESC40_SHORT_PREAMBLE BIT(4) -#define TXDESC_SHORT_GI BIT(6) +#define TXDESC32_SHORT_GI BIT(6) #define TXDESC_CCX_TAG BIT(7) #define TXDESC32_RETRY_LIMIT_ENABLE BIT(17) #define TXDESC32_RETRY_LIMIT_SHIFT 18 -- GitLab From f3fc251162f9390baabcbf812766b074e404d29a Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:37 -0400 Subject: [PATCH 1730/9938] rtl8xxxu: 8192eu uses txdesc40 8192eu uses the new TX descriptor format Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 484d08fe80cd..ad280cfae694 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8530,7 +8530,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, - .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), .has_s0s1 = 1, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, -- GitLab From 931d9278259a91a601c93fe62979c7db53678abb Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:38 -0400 Subject: [PATCH 1731/9938] rtl8xxxu: Update some register definitions Improve descriptive names of some registers and add some additional registers only found on nextgen chips. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index e545e849f5a3..ade42fe7e742 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -417,13 +417,20 @@ /* spec version 11 */ /* 0x0400 ~ 0x047F Protocol Configuration */ -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040c -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 +/* 8192c, 8192d */ +#define REG_VOQ_INFO 0x0400 +#define REG_VIQ_INFO 0x0404 +#define REG_BEQ_INFO 0x0408 +#define REG_BKQ_INFO 0x040c +/* 8188e, 8723a, 8812a, 8821a, 8192e, 8723b */ +#define REG_Q0_INFO 0x400 +#define REG_Q1_INFO 0x404 +#define REG_Q2_INFO 0x408 +#define REG_Q3_INFO 0x40c + +#define REG_MGQ_INFO 0x0410 +#define REG_HGQ_INFO 0x0414 +#define REG_BCNQ_INFO 0x0418 #define REG_CPU_MGQ_INFORMATION 0x041c #define REG_FWHW_TXQ_CTRL 0x0420 @@ -494,6 +501,9 @@ #define REG_DATA_SUBCHANNEL 0x0483 /* 8723au */ #define REG_INIDATA_RATE_SEL 0x0484 +/* MACID_SLEEP_1/3 for 8723b, 8192e, 8812a, 8821a */ +#define REG_MACID_SLEEP_3_8732B 0x0484 +#define REG_MACID_SLEEP_1_8732B 0x0488 #define REG_POWER_STATUS 0x04a4 #define REG_POWER_STAGE1 0x04b4 @@ -508,6 +518,13 @@ #define REG_RTS_MAX_AGGR_NUM 0x04cb #define REG_BAR_MODE_CTRL 0x04cc #define REG_RA_TRY_RATE_AGG_LMT 0x04cf +/* MACID_DROP for 8723a */ +#define REG_MACID_DROP_8732A 0x04d0 +/* EARLY_MODE_CONTROL 8188e */ +#define REG_EARLY_MODE_CONTROL_8188E 0x04d0 +/* MACID_SLEEP_2 for 8723b, 8192e, 8812a, 8821a */ +#define REG_MACID_SLEEP_2_8732B 0x04d0 +#define REG_MACID_SLEEP 0x04d4 #define REG_NQOS_SEQ 0x04dc #define REG_QOS_SEQ 0x04de #define REG_NEED_CPU_HANDLE 0x04e0 -- GitLab From ba17d824783805235f317f79f2871b17bd679956 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:39 -0400 Subject: [PATCH 1732/9938] rtl8xxxu: Use enums for chip version numbers With support for more chips being added, use an enum to specify the chip version. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 84 +++++++++---------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 26 +++++- 2 files changed, 67 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ad280cfae694..38576692f9b8 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1574,7 +1574,7 @@ static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv) val32 &= ~OFDM_RF_PATH_TX_MASK; if (priv->tx_paths == 2) val32 |= OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B; - else if (priv->rtlchip == 0x8192c || priv->rtlchip == 0x8191c) + else if (priv->rtl_chip == RTL8192C || priv->rtl_chip == RTL8191C) val32 |= OFDM_RF_PATH_TX_B; else val32 |= OFDM_RF_PATH_TX_A; @@ -2199,11 +2199,11 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) if (val32 & SYS_CFG_BT_FUNC) { if (priv->chip_cut >= 3) { sprintf(priv->chip_name, "8723BU"); - priv->rtlchip = 0x8723b; + priv->rtl_chip = RTL8723B; } else { sprintf(priv->chip_name, "8723AU"); priv->usb_interrupts = 1; - priv->rtlchip = 0x8723a; + priv->rtl_chip = RTL8723A; } priv->rf_paths = 1; @@ -2227,13 +2227,13 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) priv->rf_paths = 2; priv->rx_paths = 2; priv->tx_paths = 1; - priv->rtlchip = 0x8191e; + priv->rtl_chip = RTL8191E; } else { sprintf(priv->chip_name, "8192EU"); priv->rf_paths = 2; priv->rx_paths = 2; priv->tx_paths = 2; - priv->rtlchip = 0x8192e; + priv->rtl_chip = RTL8192E; } } else if (bonding == HPON_FSM_BONDING_1T2R) { sprintf(priv->chip_name, "8191CU"); @@ -2241,14 +2241,14 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) priv->rx_paths = 2; priv->tx_paths = 1; priv->usb_interrupts = 1; - priv->rtlchip = 0x8191c; + priv->rtl_chip = RTL8191C; } else { sprintf(priv->chip_name, "8192CU"); priv->rf_paths = 2; priv->rx_paths = 2; priv->tx_paths = 2; priv->usb_interrupts = 1; - priv->rtlchip = 0x8192c; + priv->rtl_chip = RTL8192C; } priv->has_wifi = 1; } else { @@ -2256,15 +2256,15 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) priv->rf_paths = 1; priv->rx_paths = 1; priv->tx_paths = 1; - priv->rtlchip = 0x8188c; + priv->rtl_chip = RTL8188C; priv->usb_interrupts = 1; priv->has_wifi = 1; } - switch (priv->rtlchip) { - case 0x8188e: - case 0x8192e: - case 0x8723b: + switch (priv->rtl_chip) { + case RTL8188E: + case RTL8192E: + case RTL8723B: switch (val32 & SYS_CFG_VENDOR_EXT_MASK) { case SYS_CFG_VENDOR_ID_TSMC: sprintf(priv->chip_vendor, "TSMC"); @@ -2814,7 +2814,7 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) /* * Init H2C command */ - if (priv->rtlchip == 0x8723b) + if (priv->rtl_chip == RTL8723B) rtl8xxxu_write8(priv, REG_HMTFR, 0x0f); exit: return ret; @@ -2997,7 +2997,7 @@ static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv) if (!priv->vendor_umc) fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; - else if (priv->chip_cut || priv->rtlchip == 0x8192c) + else if (priv->chip_cut || priv->rtl_chip == RTL8192C) fw_name = "rtlwifi/rtl8192cufw_B.bin"; else fw_name = "rtlwifi/rtl8192cufw_A.bin"; @@ -3108,7 +3108,7 @@ rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array) } } - if (priv->rtlchip != 0x8723b) + if (priv->rtl_chip != RTL8723B) rtl8xxxu_write8(priv, REG_MAX_AGGR_NUM, 0x0a); return 0; @@ -3154,7 +3154,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) * addresses, which is initialized here. Do we need this? */ - if (priv->rtlchip == 0x8723b) { + if (priv->rtl_chip == RTL8723B) { val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF; @@ -3176,7 +3176,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); } - if (priv->rtlchip != 0x8723b) { + if (priv->rtl_chip != RTL8723B) { /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */ val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); val32 &= ~AFE_XTAL_RF_GATE; @@ -3193,7 +3193,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); else if (priv->tx_paths == 2) rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); - else if (priv->rtlchip == 0x8723b) { + else if (priv->rtl_chip == RTL8723B) { /* * Why? */ @@ -3204,7 +3204,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); - if (priv->rtlchip == 0x8188c && priv->hi_pa && + if (priv->rtl_chip == RTL8188C && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); @@ -3266,7 +3266,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_TX_TO_TX, val32); } - if (priv->rtlchip == 0x8723b) + if (priv->rtl_chip == RTL8723B) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); else if (priv->hi_pa) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); @@ -3283,7 +3283,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); } - if (priv->rtlchip != 0x8723bu) { + if (priv->rtl_chip != RTL8723B) { ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); ldohci12 = 0x57; @@ -5955,7 +5955,7 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) /* * Workaround for 8188RU LNA power leakage problem. */ - if (priv->rtlchip == 0x8188c && priv->hi_pa) { + if (priv->rtl_chip == RTL8188C && priv->hi_pa) { val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); val32 &= ~BIT(1); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); @@ -6020,7 +6020,7 @@ static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) /* * Workaround for 8188RU LNA power leakage problem. */ - if (priv->rtlchip == 0x8188c && priv->hi_pa) { + if (priv->rtl_chip == RTL8188C && priv->hi_pa) { val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); val32 |= BIT(1); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); @@ -6313,7 +6313,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) * Presumably this is for 8188EU as well * Enable TX report and TX report timer */ - if (priv->rtlchip == 0x8723bu) { + if (priv->rtl_chip == RTL8723B) { val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL); val8 |= TX_REPORT_CTRL_TIMER_ENABLE; rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); @@ -6340,9 +6340,9 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* Solve too many protocol error on USB bus */ /* Can't do this for 8188/8192 UMC A cut parts */ - if (priv->rtlchip == 0x8723a || - ((priv->rtlchip == 0x8192c || priv->rtlchip == 0x8191c || - priv->rtlchip == 0x8188c) && + if (priv->rtl_chip == RTL8723A || + ((priv->rtl_chip == RTL8192C || priv->rtl_chip == RTL8191C || + priv->rtl_chip == RTL8188C) && (priv->chip_cut || !priv->vendor_umc))) { rtl8xxxu_write8(priv, 0xfe40, 0xe6); rtl8xxxu_write8(priv, 0xfe41, 0x94); @@ -6361,7 +6361,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, 0xfe42, 0x80); } - if (priv->rtlchip == 0x8192e) { + if (priv->rtl_chip == RTL8192E) { rtl8xxxu_write32(priv, REG_HIMR0, 0x00); rtl8xxxu_write32(priv, REG_HIMR1, 0x00); } @@ -6369,7 +6369,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->fops->phy_init_antenna_selection) priv->fops->phy_init_antenna_selection(priv); - if (priv->rtlchip == 0x8723b) + if (priv->rtl_chip == RTL8723B) ret = rtl8xxxu_init_mac(priv, rtl8723b_mac_init_table); else ret = rtl8xxxu_init_mac(priv, rtl8723a_mac_init_table); @@ -6383,12 +6383,12 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; - switch(priv->rtlchip) { - case 0x8723a: + switch(priv->rtl_chip) { + case RTL8723A: rftable = rtl8723au_radioa_1t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); break; - case 0x8723b: + case RTL8723B: rftable = rtl8723bu_radioa_1t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); /* @@ -6399,18 +6399,18 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) msleep(200); rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdffe0); break; - case 0x8188c: + case RTL8188C: if (priv->hi_pa) rftable = rtl8188ru_radioa_1t_highpa_table; else rftable = rtl8192cu_radioa_1t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); break; - case 0x8191c: + case RTL8191C: rftable = rtl8192cu_radioa_1t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); break; - case 0x8192c: + case RTL8192C: rftable = rtl8192cu_radioa_2t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); if (ret) @@ -6428,7 +6428,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Chip specific quirks */ - if (priv->rtlchip == 0x8723a) { + if (priv->rtl_chip == RTL8723A) { /* Fix USB interface interference issue */ rtl8xxxu_write8(priv, 0xfe40, 0xe0); rtl8xxxu_write8(priv, 0xfe41, 0x8d); @@ -6468,7 +6468,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) */ val8 = TX_TOTAL_PAGE_NUM + 1; - if (priv->rtlchip == 0x8723b) + if (priv->rtl_chip == RTL8723B) val8 -= 1; rtl8xxxu_write8(priv, REG_TXPKTBUF_BCNQ_BDNY, val8); @@ -6484,7 +6484,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) goto exit; /* RFSW Control - clear bit 14 ?? */ - if (priv->rtlchip != 0x8723b) + if (priv->rtl_chip != RTL8723B) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); /* 0x07000760 */ val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | @@ -6501,14 +6501,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Set RX page boundary */ - if (priv->rtlchip == 0x8723b) + if (priv->rtl_chip == RTL8723B) rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); else rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); /* * Transfer page size is always 128 */ - if (priv->rtlchip == 0x8723b) + if (priv->rtl_chip == RTL8723B) val8 = (PBP_PAGE_SIZE_256 << PBP_PAGE_SIZE_RX_SHIFT) | (PBP_PAGE_SIZE_256 << PBP_PAGE_SIZE_TX_SHIFT); else @@ -6600,7 +6600,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Initialize burst parameters */ - if (priv->rtlchip == 0x8723b) { + if (priv->rtl_chip == RTL8723B) { /* * For USB high speed set 512B packets */ @@ -6682,7 +6682,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) val8 = ((30000 + NAV_UPPER_UNIT - 1) / NAV_UPPER_UNIT); rtl8xxxu_write8(priv, REG_NAV_UPPER, val8); - if (priv->rtlchip == 0x8723a) { + if (priv->rtl_chip == RTL8723A) { /* * 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, * but we need to find root cause. diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index f211c5db753f..455e1122dbb5 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -65,6 +65,30 @@ #define EFUSE_BT_MAP_LEN_8723A 1024 #define EFUSE_MAX_WORD_UNIT 4 +enum rtl8xxxu_rtl_chip { + RTL8192S = 0x81920, + RTL8191S = 0x81910, + RTL8192C = 0x8192c, + RTL8191C = 0x8191c, + RTL8188C = 0x8188c, + RTL8188R = 0x81889, + RTL8192D = 0x8192d, + RTL8723A = 0x8723a, + RTL8188E = 0x8188e, + RTL8812 = 0x88120, + RTL8821 = 0x88210, + RTL8192E = 0x8192e, + RTL8191E = 0x8191e, + RTL8723B = 0x8723b, + RTL8814A = 0x8814a, + RTL8881A = 0x8881a, + RTL8821B = 0x8821b, + RTL8822B = 0x8822b, + RTL8703B = 0x8703b, + RTL8195A = 0x8195a, + RTL8188F = 0x8188f +}; + enum rtl8xxxu_rx_type { RX_TYPE_DATA_PKT = 0, RX_TYPE_C2H = 1, @@ -1236,7 +1260,7 @@ struct rtl8xxxu_priv { u32 mac_backup[RTL8XXXU_MAC_REGS]; u32 bb_backup[RTL8XXXU_BB_REGS]; u32 bb_recovery_backup[RTL8XXXU_BB_REGS]; - u32 rtlchip; + enum rtl8xxxu_rtl_chip rtl_chip; u8 pi_enabled:1; u8 int_buf[USB_INTR_CONTENT_LENGTH]; }; -- GitLab From af13faff851b49fb99c9b930c823a5362aeb80a1 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:40 -0400 Subject: [PATCH 1733/9938] rtl8xxxu: Identify 8192eu rev A/B parts correctly 8192eu A/B cut parts were incorrectly identified as 8192cu devices. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 38576692f9b8..201f6cfaccc2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2221,7 +2221,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) } else if (val32 & SYS_CFG_TYPE_ID) { bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); bonding &= HPON_FSM_BONDING_MASK; - if (priv->chip_cut >= 3) { + if (priv->fops->has_s0s1) { if (bonding == HPON_FSM_BONDING_1T2R) { sprintf(priv->chip_name, "8191EU"); priv->rf_paths = 2; -- GitLab From 91cbe4e73197859498fba9920890979296b842e6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:41 -0400 Subject: [PATCH 1734/9938] rtl8xxxu: Use correct H2C calls for 8192eu The 8192eu uses the same H2C API as the 8723bu. Call the correct functions for update_rate_mask() and report_connect(). Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 201f6cfaccc2..f2e32a78e43c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8525,8 +8525,8 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, .set_tx_power = rtl8723b_set_tx_power, - .update_rate_mask = rtl8723au_update_rate_mask, - .report_connect = rtl8723au_report_connect, + .update_rate_mask = rtl8723bu_update_rate_mask, + .report_connect = rtl8723bu_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, -- GitLab From a069caa3c30fc9744a82a6b83503ed93e00e723c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 31 Mar 2016 17:08:42 -0400 Subject: [PATCH 1735/9938] rtl8xxxu: Do not set LDOA15 / LDOV12 on 8192eu Per the vendor driver, it looks like the 8192eu doesn't have LDOA15 / LDOV12 registers. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index f2e32a78e43c..333addd3d46a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3283,7 +3283,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); } - if (priv->rtl_chip != RTL8723B) { + if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) { ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); ldohci12 = 0x57; -- GitLab From f6b1cbe029f6828bbdac8b54bdcbdc35420e842e Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Tue, 5 Apr 2016 01:04:34 -0700 Subject: [PATCH 1736/9938] mwifiex: add support for GTK rekey offload Added driver functionality to offload GTK rekey to firmware. When AP sends new GTK, firmware will update it. Signed-off-by: Ganapathi Bhat Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- .../net/wireless/marvell/mwifiex/cfg80211.c | 13 ++++++++- drivers/net/wireless/marvell/mwifiex/fw.h | 10 +++++++ .../net/wireless/marvell/mwifiex/sta_cmd.c | 28 +++++++++++++++++++ .../wireless/marvell/mwifiex/sta_cmdresp.c | 2 ++ .../net/wireless/marvell/mwifiex/sta_event.c | 3 ++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 108e64137826..ca8cdd2ec409 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3416,6 +3416,16 @@ static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, device_set_wakeup_enable(adapter->dev, enabled); } + +static int mwifiex_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + return mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG, + HostCmd_ACT_GEN_SET, 0, data, true); +} + #endif static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq) @@ -3938,6 +3948,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .suspend = mwifiex_cfg80211_suspend, .resume = mwifiex_cfg80211_resume, .set_wakeup = mwifiex_cfg80211_set_wakeup, + .set_rekey_data = mwifiex_set_rekey_data, #endif .set_coalesce = mwifiex_cfg80211_set_coalesce, .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt, @@ -3954,7 +3965,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { #ifdef CONFIG_PM static const struct wiphy_wowlan_support mwifiex_wowlan_support = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_NET_DETECT, + WIPHY_WOWLAN_NET_DETECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY, .n_patterns = MWIFIEX_MEF_MAX_FILTERS, .pattern_min_len = 1, .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index c134cf865291..8703d24eaa9e 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -372,6 +372,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_COALESCE_CFG 0x010a #define HostCmd_CMD_MGMT_FRAME_REG 0x010c #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d +#define HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG 0x010f #define HostCmd_CMD_11AC_CFG 0x0112 #define HostCmd_CMD_HS_WAKEUP_REASON 0x0116 #define HostCmd_CMD_TDLS_CONFIG 0x0100 @@ -2183,6 +2184,14 @@ struct host_cmd_ds_wakeup_reason { u16 wakeup_reason; } __packed; +struct host_cmd_ds_gtk_rekey_params { + __le16 action; + u8 kck[NL80211_KCK_LEN]; + u8 kek[NL80211_KEK_LEN]; + __le32 replay_ctr_low; + __le32 replay_ctr_high; +} __packed; + struct host_cmd_ds_command { __le16 command; __le16 size; @@ -2256,6 +2265,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_multi_chan_policy mc_policy; struct host_cmd_ds_robust_coex coex; struct host_cmd_ds_wakeup_reason hs_wakeup_reason; + struct host_cmd_ds_gtk_rekey_params rekey; } params; } __packed; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 30f152601c57..8cb895b7f2ee 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -1558,6 +1558,30 @@ static int mwifiex_cmd_robust_coex(struct mwifiex_private *priv, return 0; } +static int mwifiex_cmd_gtk_rekey_offload(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, + struct cfg80211_gtk_rekey_data *data) +{ + struct host_cmd_ds_gtk_rekey_params *rekey = &cmd->params.rekey; + u64 rekey_ctr; + + cmd->command = cpu_to_le16(HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG); + cmd->size = cpu_to_le16(sizeof(*rekey) + S_DS_GEN); + + rekey->action = cpu_to_le16(cmd_action); + if (cmd_action == HostCmd_ACT_GEN_SET) { + memcpy(rekey->kek, data->kek, NL80211_KEK_LEN); + memcpy(rekey->kck, data->kck, NL80211_KCK_LEN); + rekey_ctr = be64_to_cpup((__be64 *)data->replay_ctr); + rekey->replay_ctr_low = cpu_to_le32((u32)rekey_ctr); + rekey->replay_ctr_high = + cpu_to_le32((u32)((u64)rekey_ctr >> 32)); + } + + return 0; +} + static int mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, @@ -2094,6 +2118,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action, data_buf); break; + case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG: + ret = mwifiex_cmd_gtk_rekey_offload(priv, cmd_ptr, cmd_action, + data_buf); + break; default: mwifiex_dbg(priv->adapter, ERROR, "PREP_CMD: unknown cmd- %#x\n", cmd_no); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index d96523e10eb4..434b9776db45 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1244,6 +1244,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_ROBUST_COEX: ret = mwifiex_ret_robust_coex(priv, resp, data_buf); break; + case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG: + break; default: mwifiex_dbg(adapter, ERROR, "CMD_RESP: unknown cmd response %#x\n", diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 070bce401151..0104108b4ea2 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -147,6 +147,9 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); + + mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG, + HostCmd_ACT_GEN_REMOVE, 0, NULL, false); } static int mwifiex_parse_tdls_event(struct mwifiex_private *priv, -- GitLab From 8fa0a0dc634ba1bcf7678db296902d9c4e5025e0 Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Tue, 5 Apr 2016 01:04:35 -0700 Subject: [PATCH 1737/9938] mwifiex: add support for wakeup on GTK rekey failure User can configure wakeup on GTK rekey fail with wowlan. Added corresponding wakeup reason. Signed-off-by: Ganapathi Bhat Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 7 ++++++- drivers/net/wireless/marvell/mwifiex/fw.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index ca8cdd2ec409..49661e087811 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3390,6 +3390,10 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) break; case MANAGEMENT_FRAME_MATCHED: break; + case GTK_REKEY_FAILURE: + if (wiphy->wowlan_config->gtk_rekey_failure) + wakeup_report.gtk_rekey_failure = true; + break; default: break; } @@ -3965,7 +3969,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { #ifdef CONFIG_PM static const struct wiphy_wowlan_support mwifiex_wowlan_support = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_NET_DETECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY, + WIPHY_WOWLAN_NET_DETECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE, .n_patterns = MWIFIEX_MEF_MAX_FILTERS, .pattern_min_len = 1, .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 8703d24eaa9e..8e4145abdbfa 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -620,6 +620,7 @@ enum HS_WAKEUP_REASON { MAGIC_PATTERN_MATCHED, CONTROL_FRAME_MATCHED, MANAGEMENT_FRAME_MATCHED, + GTK_REKEY_FAILURE, RESERVED }; -- GitLab From a362e16b83e1823746874485710c7515eb5ee369 Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Tue, 5 Apr 2016 01:04:36 -0700 Subject: [PATCH 1738/9938] mwifiex: check revision id while choosing PCIe firmware Some of the chipsets have two revisions. This patch selects appropriate firmware by checking revision id. Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 56 +++++++++++++++++++-- drivers/net/wireless/marvell/mwifiex/pcie.h | 16 +++--- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index de364381fe7b..6a06ca5c3eb1 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -190,7 +190,6 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, if (ent->driver_data) { struct mwifiex_pcie_device *data = (void *)ent->driver_data; - card->pcie.firmware = data->firmware; card->pcie.reg = data->reg; card->pcie.blksz_fw_dl = data->blksz_fw_dl; card->pcie.tx_buf_size = data->tx_buf_size; @@ -269,6 +268,11 @@ static const struct pci_device_id mwifiex_ids[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, .driver_data = (unsigned long)&mwifiex_pcie8997, }, + { + PCIE_VENDOR_ID_V2_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + .driver_data = (unsigned long)&mwifiex_pcie8997, + }, {}, }; @@ -2758,6 +2762,51 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) return 0; } +/* + * This function get firmare name for downloading by revision id + * + * Read revision id register to get revision id + */ +static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) +{ + int revision_id = 0; + struct pcie_service_card *card = adapter->card; + + switch (card->dev->device) { + case PCIE_DEVICE_ID_MARVELL_88W8766P: + strcpy(adapter->fw_name, PCIE8766_DEFAULT_FW_NAME); + break; + case PCIE_DEVICE_ID_MARVELL_88W8897: + mwifiex_write_reg(adapter, 0x0c58, 0x80c00000); + mwifiex_read_reg(adapter, 0x0c58, &revision_id); + revision_id &= 0xff00; + switch (revision_id) { + case PCIE8897_A0: + strcpy(adapter->fw_name, PCIE8897_A0_FW_NAME); + break; + case PCIE8897_B0: + strcpy(adapter->fw_name, PCIE8897_B0_FW_NAME); + break; + default: + break; + } + case PCIE_DEVICE_ID_MARVELL_88W8997: + mwifiex_read_reg(adapter, 0x0c48, &revision_id); + switch (revision_id) { + case PCIE8997_V2: + strcpy(adapter->fw_name, PCIE8997_FW_NAME_V2); + break; + case PCIE8997_Z: + strcpy(adapter->fw_name, PCIE8997_FW_NAME_Z); + break; + default: + break; + } + default: + break; + } +} + /* * This function registers the PCIE device. * @@ -2778,8 +2827,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) adapter->tx_buf_size = card->pcie.tx_buf_size; adapter->mem_type_mapping_tbl = card->pcie.mem_type_mapping_tbl; adapter->num_mem_types = card->pcie.num_mem_types; - strcpy(adapter->fw_name, card->pcie.firmware); adapter->ext_scan = card->pcie.can_ext_scan; + mwifiex_pcie_get_fw_name(adapter); return 0; } @@ -2907,6 +2956,3 @@ MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION); MODULE_VERSION(PCIE_VERSION); MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME); -MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME); -MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 29e58ce877e3..4455d1905d94 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -30,14 +30,22 @@ #include "main.h" #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" -#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin" -#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcie8997_uapsta.bin" +#define PCIE8897_A0_FW_NAME "mrvl/pcie8897_uapsta_a0.bin" +#define PCIE8897_B0_FW_NAME "mrvl/pcie8897_uapsta.bin" +#define PCIE8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin" +#define PCIE8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin" #define PCIE_VENDOR_ID_MARVELL (0x11ab) +#define PCIE_VENDOR_ID_V2_MARVELL (0x1b4b) #define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30) #define PCIE_DEVICE_ID_MARVELL_88W8897 (0x2b38) #define PCIE_DEVICE_ID_MARVELL_88W8997 (0x2b42) +#define PCIE8897_A0 0x1100 +#define PCIE8897_B0 0x1200 +#define PCIE8997_Z 0x0 +#define PCIE8997_V2 0x471 + /* Constants for Buffer Descriptor (BD) rings */ #define MWIFIEX_MAX_TXRX_BD 0x20 #define MWIFIEX_TXBD_MASK 0x3F @@ -263,7 +271,6 @@ static struct memory_type_mapping mem_type_mapping_tbl_w8997[] = { }; struct mwifiex_pcie_device { - const char *firmware; const struct mwifiex_pcie_card_reg *reg; u16 blksz_fw_dl; u16 tx_buf_size; @@ -274,7 +281,6 @@ struct mwifiex_pcie_device { }; static const struct mwifiex_pcie_device mwifiex_pcie8766 = { - .firmware = PCIE8766_DEFAULT_FW_NAME, .reg = &mwifiex_reg_8766, .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, @@ -283,7 +289,6 @@ static const struct mwifiex_pcie_device mwifiex_pcie8766 = { }; static const struct mwifiex_pcie_device mwifiex_pcie8897 = { - .firmware = PCIE8897_DEFAULT_FW_NAME, .reg = &mwifiex_reg_8897, .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, @@ -294,7 +299,6 @@ static const struct mwifiex_pcie_device mwifiex_pcie8897 = { }; static const struct mwifiex_pcie_device mwifiex_pcie8997 = { - .firmware = PCIE8997_DEFAULT_FW_NAME, .reg = &mwifiex_reg_8997, .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, -- GitLab From 00c5478049683b15599339e36cae7fffc1e62844 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 5 Apr 2016 01:04:37 -0700 Subject: [PATCH 1739/9938] mwifiex: remove redundant GFP_DMA flag skb forwarded to TCP/IP stack doesn't need to allocate in DMA ZONE. This patch removes GFP_DMA flag in this case to save precious DMA memory. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sdio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index b2c839ae2c3c..a0aec3e00457 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1123,8 +1123,8 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter, __func__, pkt_len, blk_size); break; } - skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len, - GFP_KERNEL | GFP_DMA); + + skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len, GFP_KERNEL); if (!skb_deaggr) break; skb_put(skb_deaggr, pkt_len); @@ -1373,8 +1373,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, /* copy pkt to deaggr buf */ skb_deaggr = mwifiex_alloc_dma_align_buf(len_arr[pind], - GFP_KERNEL | - GFP_DMA); + GFP_KERNEL); if (!skb_deaggr) { mwifiex_dbg(adapter, ERROR, "skb allocation failure\t" "drop pkt len=%d type=%d\n", -- GitLab From ad5ca845e3d194703be82ad4a2f3042f2e198e2b Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 5 Apr 2016 01:04:38 -0700 Subject: [PATCH 1740/9938] mwifiex: schedule main workqueue for transmitting bridge packets Bridge packets are enqueued to wmm tx queue, but will not be sent until main workqeue is scheduled for new interrupt or other reason. This adds unnecessary delay during traffic. We will schedule main workqueue when bridge packet is queued. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index 52f7981a8afc..ee7fe58dd266 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -212,6 +212,8 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, atomic_inc(&adapter->tx_pending); atomic_inc(&adapter->pending_bridged_pkts); + mwifiex_queue_main_work(priv->adapter); + return; } -- GitLab From bf00dc22bc7a72d58fd1945814321b30948dc83b Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 5 Apr 2016 01:04:39 -0700 Subject: [PATCH 1741/9938] mwifiex: AMSDU Rx frame handling in AP mode This patch processes sub AMSDU frame received in AP mode. If a packet is multicast/broadcast, it is sent to kernel/upper layer as well as queued back to AP TX queue so that it can be sent to other associated stations. If a packet is unicast and RA is present in associated station list, it is again requeued into AP TX queue. If a packet is unicast and RA is not in associated station list, packet is forwarded to kernel to handle routing logic. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- .../wireless/marvell/mwifiex/11n_rxreorder.c | 5 +- drivers/net/wireless/marvell/mwifiex/main.h | 2 + .../net/wireless/marvell/mwifiex/uap_txrx.c | 90 +++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 09578c6cde59..a74cc43b1953 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -59,7 +59,10 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, skb->len); } - ret = mwifiex_recv_packet(priv, rx_skb); + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + ret = mwifiex_uap_recv_packet(priv, rx_skb); + else + ret = mwifiex_recv_packet(priv, rx_skb); if (ret == -1) mwifiex_dbg(priv->adapter, ERROR, "Rx of A-MSDU failed"); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index aafc4ab4e5ae..a159fbef20cd 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1019,6 +1019,8 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb); +int mwifiex_uap_recv_packet(struct mwifiex_private *priv, + struct sk_buff *skb); int mwifiex_process_mgmt_packet(struct mwifiex_private *priv, struct sk_buff *skb); diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index ee7fe58dd266..c95b61dc87c2 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -265,6 +265,96 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, return mwifiex_process_rx_packet(priv, skb); } +int mwifiex_uap_recv_packet(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + struct mwifiex_adapter *adapter = adapter; + struct mwifiex_sta_node *src_node; + struct ethhdr *p_ethhdr; + struct sk_buff *skb_uap; + struct mwifiex_txinfo *tx_info; + + if (!skb) + return -1; + + p_ethhdr = (void *)skb->data; + src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source); + if (src_node) { + src_node->stats.last_rx = jiffies; + src_node->stats.rx_bytes += skb->len; + src_node->stats.rx_packets++; + } + + skb->dev = priv->netdev; + skb->protocol = eth_type_trans(skb, priv->netdev); + skb->ip_summed = CHECKSUM_NONE; + + /* This is required only in case of 11n and USB/PCIE as we alloc + * a buffer of 4K only if its 11N (to be able to receive 4K + * AMSDU packets). In case of SD we allocate buffers based + * on the size of packet and hence this is not needed. + * + * Modifying the truesize here as our allocation for each + * skb is 4K but we only receive 2K packets and this cause + * the kernel to start dropping packets in case where + * application has allocated buffer based on 2K size i.e. + * if there a 64K packet received (in IP fragments and + * application allocates 64K to receive this packet but + * this packet would almost double up because we allocate + * each 1.5K fragment in 4K and pass it up. As soon as the + * 64K limit hits kernel will start to drop rest of the + * fragments. Currently we fail the Filesndl-ht.scr script + * for UDP, hence this fix + */ + if ((adapter->iface_type == MWIFIEX_USB || + adapter->iface_type == MWIFIEX_PCIE) && + (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) + skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); + + if (is_multicast_ether_addr(p_ethhdr->h_dest) || + mwifiex_get_sta_entry(priv, p_ethhdr->h_dest)) { + if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) + skb_uap = + skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); + else + skb_uap = skb_copy(skb, GFP_ATOMIC); + + if (likely(skb_uap)) { + tx_info = MWIFIEX_SKB_TXCB(skb_uap); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->bss_num = priv->bss_num; + tx_info->bss_type = priv->bss_type; + tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT; + __net_timestamp(skb_uap); + mwifiex_wmm_add_buf_txqueue(priv, skb_uap); + atomic_inc(&adapter->tx_pending); + atomic_inc(&adapter->pending_bridged_pkts); + if ((atomic_read(&adapter->pending_bridged_pkts) >= + MWIFIEX_BRIDGED_PKTS_THR_HIGH)) { + mwifiex_dbg(adapter, ERROR, + "Tx: Bridge packet limit reached. Drop packet!\n"); + mwifiex_uap_cleanup_tx_queues(priv); + } + + } else { + mwifiex_dbg(adapter, ERROR, "failed to allocate skb_uap"); + } + + mwifiex_queue_main_work(adapter); + /* Don't forward Intra-BSS unicast packet to upper layer*/ + if (mwifiex_get_sta_entry(priv, p_ethhdr->h_dest)) + return 0; + } + + /* Forward multicast/broadcast packet to upper layer*/ + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + + return 0; +} + /* * This function processes the packet received on AP interface. * -- GitLab From 4646968b94bdf88ae3c507c347d03acd5798939d Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 5 Apr 2016 01:04:40 -0700 Subject: [PATCH 1742/9938] mwifiex: dump pcie scratch registers This patch prints pcie scratch registers during firmware dump. They will be useful for analysing firmware status. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.c | 8 ++-- drivers/net/wireless/marvell/mwifiex/pcie.c | 42 +++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/pcie.h | 2 + 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 3cfa94677a8e..04b975cbb330 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1074,12 +1074,14 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) priv->netdev->name, priv->num_tx_timeout); } - if (adapter->iface_type == MWIFIEX_SDIO) { - p += sprintf(p, "\n=== SDIO register dump===\n"); + if (adapter->iface_type == MWIFIEX_SDIO || + adapter->iface_type == MWIFIEX_PCIE) { + p += sprintf(p, "\n=== %s register dump===\n", + adapter->iface_type == MWIFIEX_SDIO ? + "SDIO" : "PCIE"); if (adapter->if_ops.reg_dump) p += adapter->if_ops.reg_dump(adapter, p); } - p += sprintf(p, "\n=== more debug information\n"); debug_info = kzalloc(sizeof(*debug_info), GFP_KERNEL); if (debug_info) { diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 6a06ca5c3eb1..edf8b070f665 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2355,6 +2355,47 @@ static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type, return 0; } +/* Function to dump PCIE scratch registers in case of FW crash + */ +static int +mwifiex_pcie_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf) +{ + char *p = drv_buf; + char buf[256], *ptr; + int i; + u32 value; + struct pcie_service_card *card = adapter->card; + const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + int pcie_scratch_reg[] = {PCIE_SCRATCH_12_REG, + PCIE_SCRATCH_13_REG, + PCIE_SCRATCH_14_REG}; + + if (!p) + return 0; + + mwifiex_dbg(adapter, MSG, "PCIE register dump start\n"); + + if (mwifiex_read_reg(adapter, reg->fw_status, &value)) { + mwifiex_dbg(adapter, ERROR, "failed to read firmware status"); + return 0; + } + + ptr = buf; + mwifiex_dbg(adapter, MSG, "pcie scratch register:"); + for (i = 0; i < ARRAY_SIZE(pcie_scratch_reg); i++) { + mwifiex_read_reg(adapter, pcie_scratch_reg[i], &value); + ptr += sprintf(ptr, "reg:0x%x, value=0x%x\n", + pcie_scratch_reg[i], value); + } + + mwifiex_dbg(adapter, MSG, "%s\n", buf); + p += sprintf(p, "%s\n", buf); + + mwifiex_dbg(adapter, MSG, "PCIE register dump end\n"); + + return p - drv_buf; +} + /* This function read/write firmware */ static enum rdwr_status mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) @@ -2899,6 +2940,7 @@ static struct mwifiex_if_ops pcie_ops = { .cleanup_mpa_buf = NULL, .init_fw_port = mwifiex_pcie_init_fw_port, .clean_pcie_ring = mwifiex_clean_pcie_ring_buf, + .reg_dump = mwifiex_pcie_reg_dump, .device_dump = mwifiex_pcie_device_dump, }; diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 4455d1905d94..cc7a5df903be 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -73,6 +73,8 @@ #define PCIE_SCRATCH_10_REG 0xCE8 #define PCIE_SCRATCH_11_REG 0xCEC #define PCIE_SCRATCH_12_REG 0xCF0 +#define PCIE_SCRATCH_13_REG 0xCF8 +#define PCIE_SCRATCH_14_REG 0xCFC #define PCIE_RD_DATA_PTR_Q0_Q1 0xC08C #define PCIE_WR_DATA_PTR_Q0_Q1 0xC05C -- GitLab From 6e9a426d7964703098bde5752ae5d062a596ca99 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 16 Mar 2016 17:59:40 +0800 Subject: [PATCH 1743/9938] PCI: mvebu: Constify mvebu_pcie_pm_ops structure The mvebu_pcie_pm_ops structure is never modified, so declare it as const. Signed-off-by: Jisheng Zhang Signed-off-by: Bjorn Helgaas Reviewed-by: Thomas Petazzoni --- drivers/pci/host/pci-mvebu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 53b79c5f0559..6c43cb88da12 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -1298,7 +1298,7 @@ static const struct of_device_id mvebu_pcie_of_match_table[] = { }; MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table); -static struct dev_pm_ops mvebu_pcie_pm_ops = { +static const struct dev_pm_ops mvebu_pcie_pm_ops = { .suspend_noirq = mvebu_pcie_suspend, .resume_noirq = mvebu_pcie_resume, }; -- GitLab From dfc6535a8401b8fd15b18e2a5b8256600dd7e6b6 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 16 Mar 2016 17:59:41 +0800 Subject: [PATCH 1744/9938] PCI: mvebu: Use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS for mvebu_pcie_pm_ops Use the SET_NOIRQ_SYSTEM_SLEEP_PM_OPS helper macro for mvebu_pcie_pm_ops. The macro also sets up freeze_noirq, thaw_noirq and poweroff_noirq, restore_noirq accordingly. Signed-off-by: Jisheng Zhang Signed-off-by: Bjorn Helgaas Reviewed-by: Thomas Petazzoni --- drivers/pci/host/pci-mvebu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 6c43cb88da12..6b451df6502c 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -1003,6 +1003,7 @@ static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie) pcie->msi->dev = &pcie->pdev->dev; } +#ifdef CONFIG_PM_SLEEP static int mvebu_pcie_suspend(struct device *dev) { struct mvebu_pcie *pcie; @@ -1031,6 +1032,7 @@ static int mvebu_pcie_resume(struct device *dev) return 0; } +#endif static void mvebu_pcie_port_clk_put(void *data) { @@ -1299,8 +1301,7 @@ static const struct of_device_id mvebu_pcie_of_match_table[] = { MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table); static const struct dev_pm_ops mvebu_pcie_pm_ops = { - .suspend_noirq = mvebu_pcie_suspend, - .resume_noirq = mvebu_pcie_resume, + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mvebu_pcie_suspend, mvebu_pcie_resume) }; static struct platform_driver mvebu_pcie_driver = { -- GitLab From 85f1e7c29a46360b1b5f9cf87af6b27066c345fd Mon Sep 17 00:00:00 2001 From: Haishuang Yan Date: Sun, 3 Apr 2016 22:03:33 +0800 Subject: [PATCH 1745/9938] netfilter: ipv6: unnecessary to check whether ip6_route_output() returns NULL ip6_route_output() never returns NULL, so it is not appropriate to check if the return value is NULL. Signed-off-by: Haishuang Yan Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/nf_reject_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index 4709f657b7b6..a5400223fd74 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c @@ -158,7 +158,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) fl6.fl6_dport = otcph->source; security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); dst = ip6_route_output(net, NULL, &fl6); - if (dst == NULL || dst->error) { + if (dst->error) { dst_release(dst); return; } -- GitLab From 3fafd14d9422c46f5c2a142298384dc15dbf88b2 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Thu, 7 Apr 2016 17:53:57 +0100 Subject: [PATCH 1746/9938] ASoC: dwc: Use fifo depth to program FCR This patch makes Designware I2S driver use the fifo depth value to program the fifo configuration register instead of using hardcoded values. Signed-off-by: Jose Abreu Signed-off-by: Mark Brown --- sound/soc/dwc/designware_i2s.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index 3effcd1a7df8..0db69b7e9617 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c @@ -100,6 +100,7 @@ struct dw_i2s_dev { struct device *dev; u32 ccr; u32 xfer_resolution; + u32 fifo_th; /* data related to DMA transfers b/w i2s and DMAC */ union dw_i2s_snd_dma_data play_dma_data; @@ -232,14 +233,16 @@ static void dw_i2s_config(struct dw_i2s_dev *dev, int stream) if (stream == SNDRV_PCM_STREAM_PLAYBACK) { i2s_write_reg(dev->i2s_base, TCR(ch_reg), dev->xfer_resolution); - i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); + i2s_write_reg(dev->i2s_base, TFCR(ch_reg), + dev->fifo_th - 1); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); } else { i2s_write_reg(dev->i2s_base, RCR(ch_reg), dev->xfer_resolution); - i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); + i2s_write_reg(dev->i2s_base, RFCR(ch_reg), + dev->fifo_th - 1); irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); @@ -499,6 +502,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, */ u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1); u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2); + u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1)); u32 idx; if (dev->capability & DWC_I2S_RECORD && @@ -537,6 +541,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, dev->capability |= DW_I2S_SLAVE; } + dev->fifo_th = fifo_depth / 2; return 0; } -- GitLab From 61bf12d3304d78ff499245ea995858c3bedb162e Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 7 Apr 2016 18:06:25 +0200 Subject: [PATCH 1747/9938] livepatch: robustify klp_register_patch() API error checking Commit 425595a7fc20 ("livepatch: reuse module loader code to write relocations") adds a possibility of dereferncing pointers supplied by the consumer of the livepatch API before sanity (NULL) checking them (patch and patch->mod). Spotted by smatch tool. Reported-by: Dan Carpenter Acked-by: Josh Poimboeuf Acked-by: Jessica Yu Signed-off-by: Jiri Kosina --- kernel/livepatch/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index eb5db6e837aa..28c37fa3d3f9 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -876,6 +876,9 @@ int klp_register_patch(struct klp_patch *patch) { int ret; + if (!patch || !patch->mod) + return -EINVAL; + if (!is_livepatch_module(patch->mod)) { pr_err("module %s is not marked as a livepatch module", patch->mod->name); @@ -885,9 +888,6 @@ int klp_register_patch(struct klp_patch *patch) if (!klp_initialized()) return -ENODEV; - if (!patch || !patch->mod) - return -EINVAL; - /* * A reference is taken on the patch module to prevent it from being * unloaded. Right now, we don't allow patch modules to unload since -- GitLab From 61881cfb5ad80c1d0a46ca6d08b7e271892b2ff6 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 5 Apr 2016 17:10:14 +0200 Subject: [PATCH 1748/9938] sock: fix lockdep annotation in release_sock During release_sock we use callbacks to finish the processing of outstanding skbs on the socket. We actually are still locked, sk_locked.owned == 1, but we already told lockdep that the mutex is released. This could lead to false positives in lockdep for lockdep_sock_is_held (we don't hold the slock spinlock during processing the outstanding skbs). I took over this patch from Eric Dumazet and tested it. Signed-off-by: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/net/sock.h | 7 ++++++- net/core/sock.c | 5 ----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 1decb7a22261..91cee51086dc 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1333,7 +1333,12 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) static inline void sock_release_ownership(struct sock *sk) { - sk->sk_lock.owned = 0; + if (sk->sk_lock.owned) { + sk->sk_lock.owned = 0; + + /* The sk_lock has mutex_unlock() semantics: */ + mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); + } } /* diff --git a/net/core/sock.c b/net/core/sock.c index 2ce76e82857f..152274d188ef 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2483,11 +2483,6 @@ EXPORT_SYMBOL(lock_sock_nested); void release_sock(struct sock *sk) { - /* - * The sk_lock has mutex_unlock() semantics: - */ - mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); - spin_lock_bh(&sk->sk_lock.slock); if (sk->sk_backlog.tail) __release_sock(sk); -- GitLab From 1e1d04e678cf72442f57ce82803c7a407769135f Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 5 Apr 2016 17:10:15 +0200 Subject: [PATCH 1749/9938] net: introduce lockdep_is_held and update various places to use it The socket is either locked if we hold the slock spin_lock for lock_sock_fast and unlock_sock_fast or we own the lock (sk_lock.owned != 0). Check for this and at the same time improve that the current thread/cpu is really holding the lock. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/net/sock.h | 12 ++++++++++-- net/dccp/ipv4.c | 2 +- net/dccp/ipv6.c | 2 +- net/ipv4/af_inet.c | 2 +- net/ipv4/cipso_ipv4.c | 3 ++- net/ipv4/ip_sockglue.c | 4 ++-- net/ipv4/tcp_ipv4.c | 8 +++----- net/ipv6/ipv6_sockglue.c | 6 ++++-- net/ipv6/tcp_ipv6.c | 2 +- net/socket.c | 2 +- 10 files changed, 26 insertions(+), 17 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 91cee51086dc..eb2d7c3e120b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1360,6 +1360,14 @@ do { \ lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \ } while (0) +static bool lockdep_sock_is_held(const struct sock *csk) +{ + struct sock *sk = (struct sock *)csk; + + return lockdep_is_held(&sk->sk_lock) || + lockdep_is_held(&sk->sk_lock.slock); +} + void lock_sock_nested(struct sock *sk, int subclass); static inline void lock_sock(struct sock *sk) @@ -1598,8 +1606,8 @@ static inline void sk_rethink_txhash(struct sock *sk) static inline struct dst_entry * __sk_dst_get(struct sock *sk) { - return rcu_dereference_check(sk->sk_dst_cache, sock_owned_by_user(sk) || - lockdep_is_held(&sk->sk_lock.slock)); + return rcu_dereference_check(sk->sk_dst_cache, + lockdep_sock_is_held(sk)); } static inline struct dst_entry * diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 6438c5a7efc4..f6d183f8f332 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -62,7 +62,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) nexthop = daddr = usin->sin_addr.s_addr; inet_opt = rcu_dereference_protected(inet->inet_opt, - sock_owned_by_user(sk)); + lockdep_sock_is_held(sk)); if (inet_opt != NULL && inet_opt->opt.srr) { if (daddr == 0) return -EINVAL; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 71bf1deba4c5..8ceb3cebcad4 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -868,7 +868,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl6.fl6_sport = inet->inet_sport; security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); - opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); + opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk)); final_p = fl6_update_dst(&fl6, opt, &final); dst = ip6_dst_lookup_flow(sk, &fl6, final_p); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index a38b9910af60..8217cd22f921 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1107,7 +1107,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) struct ip_options_rcu *inet_opt; inet_opt = rcu_dereference_protected(inet->inet_opt, - sock_owned_by_user(sk)); + lockdep_sock_is_held(sk)); if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index bdb2a07ec363..40d6b87713a1 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1933,7 +1933,8 @@ int cipso_v4_sock_setattr(struct sock *sk, sk_inet = inet_sk(sk); - old = rcu_dereference_protected(sk_inet->inet_opt, sock_owned_by_user(sk)); + old = rcu_dereference_protected(sk_inet->inet_opt, + lockdep_sock_is_held(sk)); if (sk_inet->is_icsk) { sk_conn = inet_csk(sk); if (old) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 1b7c0776c805..89b5f3bd6694 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -642,7 +642,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, if (err) break; old = rcu_dereference_protected(inet->inet_opt, - sock_owned_by_user(sk)); + lockdep_sock_is_held(sk)); if (inet->is_icsk) { struct inet_connection_sock *icsk = inet_csk(sk); #if IS_ENABLED(CONFIG_IPV6) @@ -1302,7 +1302,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, struct ip_options_rcu *inet_opt; inet_opt = rcu_dereference_protected(inet->inet_opt, - sock_owned_by_user(sk)); + lockdep_sock_is_held(sk)); opt->optlen = 0; if (inet_opt) memcpy(optbuf, &inet_opt->opt, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 456ff3d6a132..f4f2a0a3849d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -157,7 +157,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) nexthop = daddr = usin->sin_addr.s_addr; inet_opt = rcu_dereference_protected(inet->inet_opt, - sock_owned_by_user(sk)); + lockdep_sock_is_held(sk)); if (inet_opt && inet_opt->opt.srr) { if (!daddr) return -EINVAL; @@ -882,8 +882,7 @@ struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk, /* caller either holds rcu_read_lock() or socket lock */ md5sig = rcu_dereference_check(tp->md5sig_info, - sock_owned_by_user(sk) || - lockdep_is_held((spinlock_t *)&sk->sk_lock.slock)); + lockdep_sock_is_held(sk)); if (!md5sig) return NULL; #if IS_ENABLED(CONFIG_IPV6) @@ -928,8 +927,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, } md5sig = rcu_dereference_protected(tp->md5sig_info, - sock_owned_by_user(sk) || - lockdep_is_held(&sk->sk_lock.slock)); + lockdep_sock_is_held(sk)); if (!md5sig) { md5sig = kmalloc(sizeof(*md5sig), gfp); if (!md5sig) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index a5557d22f89e..4ff4b29894eb 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -407,7 +407,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW)) break; - opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); + opt = rcu_dereference_protected(np->opt, + lockdep_sock_is_held(sk)); opt = ipv6_renew_options(sk, opt, optname, (struct ipv6_opt_hdr __user *)optval, optlen); @@ -1124,7 +1125,8 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, struct ipv6_txoptions *opt; lock_sock(sk); - opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); + opt = rcu_dereference_protected(np->opt, + lockdep_sock_is_held(sk)); len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len); release_sock(sk); /* check if ipv6_getsockopt_sticky() returns err code */ diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7cde1b6fdda3..0e621bc1ae11 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -234,7 +234,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl6.fl6_dport = usin->sin6_port; fl6.fl6_sport = inet->inet_sport; - opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); + opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk)); final_p = fl6_update_dst(&fl6, opt, &final); security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); diff --git a/net/socket.c b/net/socket.c index 979d3146b081..afa3c3470717 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1046,7 +1046,7 @@ static int sock_fasync(int fd, struct file *filp, int on) return -EINVAL; lock_sock(sk); - wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk)); + wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk)); fasync_helper(fd, filp, on, &wq->fasync_list); if (!wq->fasync_list) -- GitLab From 8ced425ee630c03beea06c1dfa35190bf8395d07 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 5 Apr 2016 17:10:16 +0200 Subject: [PATCH 1750/9938] tun: use socket locks for sk_{attach,detatch}_filter This reverts commit 5a5abb1fa3b05dd ("tun, bpf: fix suspicious RCU usage in tun_{attach, detach}_filter") and replaces it to use lock_sock around sk_{attach,detach}_filter. The checks inside filter.c are updated with lockdep_sock_is_held to check for proper socket locks. It keeps the code cleaner by ensuring that only one lock governs the socket filter instead of two independent locks. Cc: Daniel Borkmann Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/tun.c | 14 +++++++++----- include/linux/filter.h | 4 ---- net/core/filter.c | 35 +++++++++++++---------------------- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9abc36bf77ea..64bc143eddd9 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -622,8 +622,9 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte /* Re-attach the filter to persist device */ if (!skip_filter && (tun->filter_attached == true)) { - err = __sk_attach_filter(&tun->fprog, tfile->socket.sk, - lockdep_rtnl_is_held()); + lock_sock(tfile->socket.sk); + err = sk_attach_filter(&tun->fprog, tfile->socket.sk); + release_sock(tfile->socket.sk); if (!err) goto out; } @@ -1824,7 +1825,9 @@ static void tun_detach_filter(struct tun_struct *tun, int n) for (i = 0; i < n; i++) { tfile = rtnl_dereference(tun->tfiles[i]); - __sk_detach_filter(tfile->socket.sk, lockdep_rtnl_is_held()); + lock_sock(tfile->socket.sk); + sk_detach_filter(tfile->socket.sk); + release_sock(tfile->socket.sk); } tun->filter_attached = false; @@ -1837,8 +1840,9 @@ static int tun_attach_filter(struct tun_struct *tun) for (i = 0; i < tun->numqueues; i++) { tfile = rtnl_dereference(tun->tfiles[i]); - ret = __sk_attach_filter(&tun->fprog, tfile->socket.sk, - lockdep_rtnl_is_held()); + lock_sock(tfile->socket.sk); + ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); + release_sock(tfile->socket.sk); if (ret) { tun_detach_filter(tun, i); return ret; diff --git a/include/linux/filter.h b/include/linux/filter.h index a51a5361695f..43aa1f8855c7 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -465,14 +465,10 @@ int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog, void bpf_prog_destroy(struct bpf_prog *fp); int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); -int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk, - bool locked); int sk_attach_bpf(u32 ufd, struct sock *sk); int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk); int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk); int sk_detach_filter(struct sock *sk); -int __sk_detach_filter(struct sock *sk, bool locked); - int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned int len); diff --git a/net/core/filter.c b/net/core/filter.c index ca7f832b2980..e8486ba601ea 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1149,8 +1149,7 @@ void bpf_prog_destroy(struct bpf_prog *fp) } EXPORT_SYMBOL_GPL(bpf_prog_destroy); -static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk, - bool locked) +static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk) { struct sk_filter *fp, *old_fp; @@ -1166,8 +1165,10 @@ static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk, return -ENOMEM; } - old_fp = rcu_dereference_protected(sk->sk_filter, locked); + old_fp = rcu_dereference_protected(sk->sk_filter, + lockdep_sock_is_held(sk)); rcu_assign_pointer(sk->sk_filter, fp); + if (old_fp) sk_filter_uncharge(sk, old_fp); @@ -1246,8 +1247,7 @@ struct bpf_prog *__get_filter(struct sock_fprog *fprog, struct sock *sk) * occurs or there is insufficient memory for the filter a negative * errno code is returned. On success the return is zero. */ -int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk, - bool locked) +int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) { struct bpf_prog *prog = __get_filter(fprog, sk); int err; @@ -1255,7 +1255,7 @@ int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk, if (IS_ERR(prog)) return PTR_ERR(prog); - err = __sk_attach_prog(prog, sk, locked); + err = __sk_attach_prog(prog, sk); if (err < 0) { __bpf_prog_release(prog); return err; @@ -1263,12 +1263,7 @@ int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk, return 0; } -EXPORT_SYMBOL_GPL(__sk_attach_filter); - -int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) -{ - return __sk_attach_filter(fprog, sk, sock_owned_by_user(sk)); -} +EXPORT_SYMBOL_GPL(sk_attach_filter); int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk) { @@ -1314,7 +1309,7 @@ int sk_attach_bpf(u32 ufd, struct sock *sk) if (IS_ERR(prog)) return PTR_ERR(prog); - err = __sk_attach_prog(prog, sk, sock_owned_by_user(sk)); + err = __sk_attach_prog(prog, sk); if (err < 0) { bpf_prog_put(prog); return err; @@ -2255,7 +2250,7 @@ static int __init register_sk_filter_ops(void) } late_initcall(register_sk_filter_ops); -int __sk_detach_filter(struct sock *sk, bool locked) +int sk_detach_filter(struct sock *sk) { int ret = -ENOENT; struct sk_filter *filter; @@ -2263,7 +2258,8 @@ int __sk_detach_filter(struct sock *sk, bool locked) if (sock_flag(sk, SOCK_FILTER_LOCKED)) return -EPERM; - filter = rcu_dereference_protected(sk->sk_filter, locked); + filter = rcu_dereference_protected(sk->sk_filter, + lockdep_sock_is_held(sk)); if (filter) { RCU_INIT_POINTER(sk->sk_filter, NULL); sk_filter_uncharge(sk, filter); @@ -2272,12 +2268,7 @@ int __sk_detach_filter(struct sock *sk, bool locked) return ret; } -EXPORT_SYMBOL_GPL(__sk_detach_filter); - -int sk_detach_filter(struct sock *sk) -{ - return __sk_detach_filter(sk, sock_owned_by_user(sk)); -} +EXPORT_SYMBOL_GPL(sk_detach_filter); int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len) @@ -2288,7 +2279,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, lock_sock(sk); filter = rcu_dereference_protected(sk->sk_filter, - sock_owned_by_user(sk)); + lockdep_sock_is_held(sk)); if (!filter) goto out; -- GitLab From 0340d0b9e0e2dc340acb664f19d6550940b22cde Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:49 -0700 Subject: [PATCH 1751/9938] net: Checks skb_dst to be NULL in inet_iif In inet_iif check if skb_rtable is NULL for the skb and return skb->skb_iif if it is. This change allows inet_iif to be called before the dst information has been set in the skb (e.g. when doing socket based UDP GRO). Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- include/net/route.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index 9b0a523bb428..f4b11eee1754 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -322,10 +322,11 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable static inline int inet_iif(const struct sk_buff *skb) { - int iif = skb_rtable(skb)->rt_iif; + struct rtable *rt = skb_rtable(skb); + + if (rt && rt->rt_iif) + return rt->rt_iif; - if (iif) - return iif; return skb->skb_iif; } -- GitLab From 63058308cd55182bbfd7a87970bd57883fcfbd2e Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:50 -0700 Subject: [PATCH 1752/9938] udp: Add udp6_lib_lookup_skb and udp4_lib_lookup_skb Add externally visible functions to lookup a UDP socket by skb. This will be used for GRO in UDP sockets. These functions also check if skb->dst is set, and if it is not skb->dev is used to get dev_net. This allows calling lookup functions before dst has been set on the skbuff. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- include/net/udp.h | 4 ++++ net/ipv4/udp.c | 13 +++++++++++++ net/ipv6/udp.c | 13 +++++++++++++ 3 files changed, 30 insertions(+) diff --git a/include/net/udp.h b/include/net/udp.h index a0b0da97164c..3aa0b3ec1fb0 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -269,6 +269,8 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, __be32 daddr, __be16 dport, int dif, struct udp_table *tbl, struct sk_buff *skb); +struct sock *udp4_lib_lookup_skb(struct sk_buff *skb, + __be16 sport, __be16 dport); struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, @@ -278,6 +280,8 @@ struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *daddr, __be16 dport, int dif, struct udp_table *tbl, struct sk_buff *skb); +struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, + __be16 sport, __be16 dport); /* * SNMP statistics for UDP and UDP-Lite diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d80312ddbb8a..3563788d064f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -604,6 +604,19 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, udptable, skb); } +struct sock *udp4_lib_lookup_skb(struct sk_buff *skb, + __be16 sport, __be16 dport) +{ + const struct iphdr *iph = ip_hdr(skb); + const struct net_device *dev = + skb_dst(skb) ? skb_dst(skb)->dev : skb->dev; + + return __udp4_lib_lookup(dev_net(dev), iph->saddr, sport, + iph->daddr, dport, inet_iif(skb), + &udp_table, skb); +} +EXPORT_SYMBOL_GPL(udp4_lib_lookup_skb); + /* Must be called under rcu_read_lock(). * Does increment socket refcount. */ diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 87bd7aff88b4..a050b70b9101 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -326,6 +326,19 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, udptable, skb); } +struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, + __be16 sport, __be16 dport) +{ + const struct ipv6hdr *iph = ipv6_hdr(skb); + const struct net_device *dev = + skb_dst(skb) ? skb_dst(skb)->dev : skb->dev; + + return __udp6_lib_lookup(dev_net(dev), &iph->saddr, sport, + &iph->daddr, dport, inet6_iif(skb), + &udp_table, skb); +} +EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb); + /* Must be called under rcu_read_lock(). * Does increment socket refcount. */ -- GitLab From a6024562ffd7e0f31bc6671817840ad1e91de7b4 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:51 -0700 Subject: [PATCH 1753/9938] udp: Add GRO functions to UDP socket This patch adds GRO functions (gro_receive and gro_complete) to UDP sockets. udp_gro_receive is changed to perform socket lookup on a packet. If a socket is found the related GRO functions are called. This features obsoletes using UDP offload infrastructure for GRO (udp_offload). This has the advantage of not being limited to provide offload on a per port basis, GRO is now applied to whatever individual UDP sockets are bound to. This also allows the possbility of "application defined GRO"-- that is we can attach something like a BPF program to a UDP socket to perfrom GRO on an application layer protocol. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- include/linux/udp.h | 8 +++++++ include/net/udp.h | 7 ++++-- net/ipv4/udp_offload.c | 52 ++++++++++++++++-------------------------- net/ipv6/Makefile | 5 ++-- net/ipv6/af_inet6.c | 8 +++++++ net/ipv6/ip6_offload.c | 2 -- net/ipv6/ip6_offload.h | 3 ++- net/ipv6/udp_offload.c | 11 ++++++--- 8 files changed, 54 insertions(+), 42 deletions(-) diff --git a/include/linux/udp.h b/include/linux/udp.h index 32342754643a..d1fd8cd39478 100644 --- a/include/linux/udp.h +++ b/include/linux/udp.h @@ -71,6 +71,14 @@ struct udp_sock { */ int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); void (*encap_destroy)(struct sock *sk); + + /* GRO functions for UDP socket */ + struct sk_buff ** (*gro_receive)(struct sock *sk, + struct sk_buff **head, + struct sk_buff *skb); + int (*gro_complete)(struct sock *sk, + struct sk_buff *skb, + int nhoff); }; static inline struct udp_sock *udp_sk(const struct sock *sk) diff --git a/include/net/udp.h b/include/net/udp.h index 3aa0b3ec1fb0..3c5a65e0946d 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -167,9 +167,12 @@ static inline void udp_csum_pull_header(struct sk_buff *skb) UDP_SKB_CB(skb)->cscov -= sizeof(struct udphdr); } +typedef struct sock *(*udp_lookup_t)(struct sk_buff *skb, __be16 sport, + __be16 dport); + struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, - struct udphdr *uh); -int udp_gro_complete(struct sk_buff *skb, int nhoff); + struct udphdr *uh, udp_lookup_t lookup); +int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup); static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb) { diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 0ed2dafb7cc4..65c3fd34b363 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -179,6 +179,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, return segs; } +EXPORT_SYMBOL(skb_udp_tunnel_segment); static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, netdev_features_t features) @@ -304,13 +305,13 @@ void udp_del_offload(struct udp_offload *uo) EXPORT_SYMBOL(udp_del_offload); struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, - struct udphdr *uh) + struct udphdr *uh, udp_lookup_t lookup) { - struct udp_offload_priv *uo_priv; struct sk_buff *p, **pp = NULL; struct udphdr *uh2; unsigned int off = skb_gro_offset(skb); int flush = 1; + struct sock *sk; if (NAPI_GRO_CB(skb)->encap_mark || (skb->ip_summed != CHECKSUM_PARTIAL && @@ -322,13 +323,11 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, NAPI_GRO_CB(skb)->encap_mark = 1; rcu_read_lock(); - uo_priv = rcu_dereference(udp_offload_base); - for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) { - if (net_eq(read_pnet(&uo_priv->net), dev_net(skb->dev)) && - uo_priv->offload->port == uh->dest && - uo_priv->offload->callbacks.gro_receive) - goto unflush; - } + sk = (*lookup)(skb, uh->source, uh->dest); + + if (sk && udp_sk(sk)->gro_receive) + goto unflush; + goto out_unlock; unflush: @@ -352,9 +351,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */ skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr)); - NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto; - pp = uo_priv->offload->callbacks.gro_receive(head, skb, - uo_priv->offload); + pp = udp_sk(sk)->gro_receive(sk, head, skb); out_unlock: rcu_read_unlock(); @@ -362,6 +359,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, NAPI_GRO_CB(skb)->flush |= flush; return pp; } +EXPORT_SYMBOL(udp_gro_receive); static struct sk_buff **udp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) @@ -383,39 +381,28 @@ static struct sk_buff **udp4_gro_receive(struct sk_buff **head, inet_gro_compute_pseudo); skip: NAPI_GRO_CB(skb)->is_ipv6 = 0; - return udp_gro_receive(head, skb, uh); + return udp_gro_receive(head, skb, uh, udp4_lib_lookup_skb); flush: NAPI_GRO_CB(skb)->flush = 1; return NULL; } -int udp_gro_complete(struct sk_buff *skb, int nhoff) +int udp_gro_complete(struct sk_buff *skb, int nhoff, + udp_lookup_t lookup) { - struct udp_offload_priv *uo_priv; __be16 newlen = htons(skb->len - nhoff); struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); int err = -ENOSYS; + struct sock *sk; uh->len = newlen; rcu_read_lock(); - - uo_priv = rcu_dereference(udp_offload_base); - for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) { - if (net_eq(read_pnet(&uo_priv->net), dev_net(skb->dev)) && - uo_priv->offload->port == uh->dest && - uo_priv->offload->callbacks.gro_complete) - break; - } - - if (uo_priv) { - NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto; - err = uo_priv->offload->callbacks.gro_complete(skb, - nhoff + sizeof(struct udphdr), - uo_priv->offload); - } - + sk = (*lookup)(skb, uh->source, uh->dest); + if (sk && udp_sk(sk)->gro_complete) + err = udp_sk(sk)->gro_complete(sk, skb, + nhoff + sizeof(struct udphdr)); rcu_read_unlock(); if (skb->remcsum_offload) @@ -426,6 +413,7 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff) return err; } +EXPORT_SYMBOL(udp_gro_complete); static int udp4_gro_complete(struct sk_buff *skb, int nhoff) { @@ -440,7 +428,7 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff) skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; } - return udp_gro_complete(skb, nhoff); + return udp_gro_complete(skb, nhoff, udp4_lib_lookup_skb); } static const struct net_offload udpv4_offload = { diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 2fbd90bf8d33..5e9d6bf4aaca 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -8,9 +8,10 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ addrlabel.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \ - exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o + exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o \ + udp_offload.o -ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o +ipv6-offload := ip6_offload.o tcpv6_offload.o exthdrs_offload.o ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 2b78aad0d52f..bfa86f040c16 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -64,6 +64,8 @@ #include #include +#include "ip6_offload.h" + MODULE_AUTHOR("Cast of dozens"); MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); MODULE_LICENSE("GPL"); @@ -959,6 +961,10 @@ static int __init inet6_init(void) if (err) goto udplitev6_fail; + err = udpv6_offload_init(); + if (err) + goto udpv6_offload_fail; + err = tcpv6_init(); if (err) goto tcpv6_fail; @@ -988,6 +994,8 @@ static int __init inet6_init(void) ipv6_packet_fail: tcpv6_exit(); tcpv6_fail: + udpv6_offload_exit(); +udpv6_offload_fail: udplitev6_exit(); udplitev6_fail: udpv6_exit(); diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 82e9f3076028..204af2219471 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -325,8 +325,6 @@ static int __init ipv6_offload_init(void) if (tcpv6_offload_init() < 0) pr_crit("%s: Cannot add TCP protocol offload\n", __func__); - if (udp_offload_init() < 0) - pr_crit("%s: Cannot add UDP protocol offload\n", __func__); if (ipv6_exthdrs_offload_init() < 0) pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__); diff --git a/net/ipv6/ip6_offload.h b/net/ipv6/ip6_offload.h index 2e155c651b35..96b40e41ac53 100644 --- a/net/ipv6/ip6_offload.h +++ b/net/ipv6/ip6_offload.h @@ -12,7 +12,8 @@ #define __ip6_offload_h int ipv6_exthdrs_offload_init(void); -int udp_offload_init(void); +int udpv6_offload_init(void); +int udpv6_offload_exit(void); int tcpv6_offload_init(void); #endif diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 2b0fbe6929e8..5429f6bcf047 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -153,7 +153,7 @@ static struct sk_buff **udp6_gro_receive(struct sk_buff **head, skip: NAPI_GRO_CB(skb)->is_ipv6 = 1; - return udp_gro_receive(head, skb, uh); + return udp_gro_receive(head, skb, uh, udp6_lib_lookup_skb); flush: NAPI_GRO_CB(skb)->flush = 1; @@ -173,7 +173,7 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff) skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; } - return udp_gro_complete(skb, nhoff); + return udp_gro_complete(skb, nhoff, udp6_lib_lookup_skb); } static const struct net_offload udpv6_offload = { @@ -184,7 +184,12 @@ static const struct net_offload udpv6_offload = { }, }; -int __init udp_offload_init(void) +int udpv6_offload_init(void) { return inet6_add_offload(&udpv6_offload, IPPROTO_UDP); } + +int udpv6_offload_exit(void) +{ + return inet6_del_offload(&udpv6_offload, IPPROTO_UDP); +} -- GitLab From 38fd2af24fcfda93f9fea3e53f26e48775ae9e09 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:52 -0700 Subject: [PATCH 1754/9938] udp: Add socket based GRO and config Add gro_receive and gro_complete to struct udp_tunnel_sock_cfg. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- include/net/udp_tunnel.h | 7 +++++++ net/ipv4/udp_tunnel.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index b83114077cee..2dcf1de948ac 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -64,6 +64,11 @@ static inline int udp_sock_create(struct net *net, typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb); typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk); +typedef struct sk_buff **(*udp_tunnel_gro_receive_t)(struct sock *sk, + struct sk_buff **head, + struct sk_buff *skb); +typedef int (*udp_tunnel_gro_complete_t)(struct sock *sk, struct sk_buff *skb, + int nhoff); struct udp_tunnel_sock_cfg { void *sk_user_data; /* user data used by encap_rcv call back */ @@ -71,6 +76,8 @@ struct udp_tunnel_sock_cfg { __u8 encap_type; udp_tunnel_encap_rcv_t encap_rcv; udp_tunnel_encap_destroy_t encap_destroy; + udp_tunnel_gro_receive_t gro_receive; + udp_tunnel_gro_complete_t gro_complete; }; /* Setup the given (UDP) sock to receive UDP encapsulated packets */ diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c index 96599d1a1318..47f12c73d959 100644 --- a/net/ipv4/udp_tunnel.c +++ b/net/ipv4/udp_tunnel.c @@ -69,6 +69,8 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, udp_sk(sk)->encap_type = cfg->encap_type; udp_sk(sk)->encap_rcv = cfg->encap_rcv; udp_sk(sk)->encap_destroy = cfg->encap_destroy; + udp_sk(sk)->gro_receive = cfg->gro_receive; + udp_sk(sk)->gro_complete = cfg->gro_complete; udp_tunnel_encap_enable(sock); } -- GitLab From 5602c48cf87562c2f95b831d690631935e834295 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:53 -0700 Subject: [PATCH 1755/9938] vxlan: change vxlan to use UDP socket GRO Adapt vxlan_gro_receive, vxlan_gro_complete to take a socket argument. Set these functions in tunnel_config. Don't set udp_offloads any more. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 30 ++++++++---------------------- include/net/vxlan.h | 1 - 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 51cccddfe403..9f3634064c92 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -551,16 +551,15 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, return vh; } -static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, - struct sk_buff *skb, - struct udp_offload *uoff) +static struct sk_buff **vxlan_gro_receive(struct sock *sk, + struct sk_buff **head, + struct sk_buff *skb) { struct sk_buff *p, **pp = NULL; struct vxlanhdr *vh, *vh2; unsigned int hlen, off_vx; int flush = 1; - struct vxlan_sock *vs = container_of(uoff, struct vxlan_sock, - udp_offloads); + struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk); __be32 flags; struct gro_remcsum grc; @@ -613,8 +612,7 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, return pp; } -static int vxlan_gro_complete(struct sk_buff *skb, int nhoff, - struct udp_offload *uoff) +static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) { udp_tunnel_gro_complete(skb, nhoff); @@ -629,13 +627,6 @@ static void vxlan_notify_add_rx_port(struct vxlan_sock *vs) struct net *net = sock_net(sk); sa_family_t sa_family = vxlan_get_sk_family(vs); __be16 port = inet_sk(sk)->inet_sport; - int err; - - if (sa_family == AF_INET) { - err = udp_add_offload(net, &vs->udp_offloads); - if (err) - pr_warn("vxlan: udp_add_offload failed with status %d\n", err); - } rcu_read_lock(); for_each_netdev_rcu(net, dev) { @@ -662,9 +653,6 @@ static void vxlan_notify_del_rx_port(struct vxlan_sock *vs) port); } rcu_read_unlock(); - - if (sa_family == AF_INET) - udp_del_offload(&vs->udp_offloads); } /* Add new entry to forwarding table -- assumes lock held */ @@ -2752,21 +2740,19 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6, atomic_set(&vs->refcnt, 1); vs->flags = (flags & VXLAN_F_RCV_FLAGS); - /* Initialize the vxlan udp offloads structure */ - vs->udp_offloads.port = port; - vs->udp_offloads.callbacks.gro_receive = vxlan_gro_receive; - vs->udp_offloads.callbacks.gro_complete = vxlan_gro_complete; - spin_lock(&vn->sock_lock); hlist_add_head_rcu(&vs->hlist, vs_head(net, port)); vxlan_notify_add_rx_port(vs); spin_unlock(&vn->sock_lock); /* Mark socket as an encapsulation socket. */ + memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); tunnel_cfg.sk_user_data = vs; tunnel_cfg.encap_type = 1; tunnel_cfg.encap_rcv = vxlan_rcv; tunnel_cfg.encap_destroy = NULL; + tunnel_cfg.gro_receive = vxlan_gro_receive; + tunnel_cfg.gro_complete = vxlan_gro_complete; setup_udp_tunnel_sock(net, sock, &tunnel_cfg); diff --git a/include/net/vxlan.h b/include/net/vxlan.h index dcc6f4057115..2f168f0ea32c 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -189,7 +189,6 @@ struct vxlan_sock { struct rcu_head rcu; struct hlist_head vni_list[VNI_HASH_SIZE]; atomic_t refcnt; - struct udp_offload udp_offloads; u32 flags; }; -- GitLab From d92283e338f6d6503b7417536bf3478f466cbc01 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:54 -0700 Subject: [PATCH 1756/9938] fou: change to use UDP socket GRO Adapt gue_gro_receive, gue_gro_complete to take a socket argument. Don't set udp_offloads any more. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- net/ipv4/fou.c | 48 +++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 5a94aea280d3..5738b9771067 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -22,7 +22,6 @@ struct fou { u8 flags; __be16 port; u16 type; - struct udp_offload udp_offloads; struct list_head list; struct rcu_head rcu; }; @@ -186,13 +185,13 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb) return 0; } -static struct sk_buff **fou_gro_receive(struct sk_buff **head, - struct sk_buff *skb, - struct udp_offload *uoff) +static struct sk_buff **fou_gro_receive(struct sock *sk, + struct sk_buff **head, + struct sk_buff *skb) { const struct net_offload *ops; struct sk_buff **pp = NULL; - u8 proto = NAPI_GRO_CB(skb)->proto; + u8 proto = fou_from_sock(sk)->protocol; const struct net_offload **offloads; /* We can clear the encap_mark for FOU as we are essentially doing @@ -217,11 +216,11 @@ static struct sk_buff **fou_gro_receive(struct sk_buff **head, return pp; } -static int fou_gro_complete(struct sk_buff *skb, int nhoff, - struct udp_offload *uoff) +static int fou_gro_complete(struct sock *sk, struct sk_buff *skb, + int nhoff) { const struct net_offload *ops; - u8 proto = NAPI_GRO_CB(skb)->proto; + u8 proto = fou_from_sock(sk)->protocol; int err = -ENOSYS; const struct net_offload **offloads; @@ -264,9 +263,9 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, return guehdr; } -static struct sk_buff **gue_gro_receive(struct sk_buff **head, - struct sk_buff *skb, - struct udp_offload *uoff) +static struct sk_buff **gue_gro_receive(struct sock *sk, + struct sk_buff **head, + struct sk_buff *skb) { const struct net_offload **offloads; const struct net_offload *ops; @@ -277,7 +276,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, void *data; u16 doffset = 0; int flush = 1; - struct fou *fou = container_of(uoff, struct fou, udp_offloads); + struct fou *fou = fou_from_sock(sk); struct gro_remcsum grc; skb_gro_remcsum_init(&grc); @@ -386,8 +385,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, return pp; } -static int gue_gro_complete(struct sk_buff *skb, int nhoff, - struct udp_offload *uoff) +static int gue_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) { const struct net_offload **offloads; struct guehdr *guehdr = (struct guehdr *)(skb->data + nhoff); @@ -435,10 +433,7 @@ static int fou_add_to_port_list(struct net *net, struct fou *fou) static void fou_release(struct fou *fou) { struct socket *sock = fou->sock; - struct sock *sk = sock->sk; - if (sk->sk_family == AF_INET) - udp_del_offload(&fou->udp_offloads); list_del(&fou->list); udp_tunnel_sock_release(sock); @@ -448,11 +443,9 @@ static void fou_release(struct fou *fou) static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg) { udp_sk(sk)->encap_rcv = fou_udp_recv; - fou->protocol = cfg->protocol; - fou->udp_offloads.callbacks.gro_receive = fou_gro_receive; - fou->udp_offloads.callbacks.gro_complete = fou_gro_complete; - fou->udp_offloads.port = cfg->udp_config.local_udp_port; - fou->udp_offloads.ipproto = cfg->protocol; + udp_sk(sk)->gro_receive = fou_gro_receive; + udp_sk(sk)->gro_complete = fou_gro_complete; + fou_from_sock(sk)->protocol = cfg->protocol; return 0; } @@ -460,9 +453,8 @@ static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg) static int gue_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg) { udp_sk(sk)->encap_rcv = gue_udp_recv; - fou->udp_offloads.callbacks.gro_receive = gue_gro_receive; - fou->udp_offloads.callbacks.gro_complete = gue_gro_complete; - fou->udp_offloads.port = cfg->udp_config.local_udp_port; + udp_sk(sk)->gro_receive = gue_gro_receive; + udp_sk(sk)->gro_complete = gue_gro_complete; return 0; } @@ -521,12 +513,6 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, sk->sk_allocation = GFP_ATOMIC; - if (cfg->udp_config.family == AF_INET) { - err = udp_add_offload(net, &fou->udp_offloads); - if (err) - goto error; - } - err = fou_add_to_port_list(net, fou); if (err) goto error; -- GitLab From 4a0090a98e5f6e7813d807c883abf362df4b0507 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:55 -0700 Subject: [PATCH 1757/9938] geneve: change to use UDP socket GRO Adapt geneve_gro_receive, geneve_gro_complete to take a socket argument. Set these functions in tunnel_config. Don't set udp_offloads any more. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- drivers/net/geneve.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index bc168894bda3..a9fbf17eb256 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -87,7 +87,6 @@ struct geneve_sock { struct socket *sock; struct rcu_head rcu; int refcnt; - struct udp_offload udp_offloads; struct hlist_head vni_list[VNI_HASH_SIZE]; u32 flags; }; @@ -409,14 +408,6 @@ static void geneve_notify_add_rx_port(struct geneve_sock *gs) struct net *net = sock_net(sk); sa_family_t sa_family = geneve_get_sk_family(gs); __be16 port = inet_sk(sk)->inet_sport; - int err; - - if (sa_family == AF_INET) { - err = udp_add_offload(sock_net(sk), &gs->udp_offloads); - if (err) - pr_warn("geneve: udp_add_offload failed with status %d\n", - err); - } rcu_read_lock(); for_each_netdev_rcu(net, dev) { @@ -432,9 +423,9 @@ static int geneve_hlen(struct genevehdr *gh) return sizeof(*gh) + gh->opt_len * 4; } -static struct sk_buff **geneve_gro_receive(struct sk_buff **head, - struct sk_buff *skb, - struct udp_offload *uoff) +static struct sk_buff **geneve_gro_receive(struct sock *sk, + struct sk_buff **head, + struct sk_buff *skb) { struct sk_buff *p, **pp = NULL; struct genevehdr *gh, *gh2; @@ -495,8 +486,8 @@ static struct sk_buff **geneve_gro_receive(struct sk_buff **head, return pp; } -static int geneve_gro_complete(struct sk_buff *skb, int nhoff, - struct udp_offload *uoff) +static int geneve_gro_complete(struct sock *sk, struct sk_buff *skb, + int nhoff) { struct genevehdr *gh; struct packet_offload *ptype; @@ -545,14 +536,14 @@ static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port, INIT_HLIST_HEAD(&gs->vni_list[h]); /* Initialize the geneve udp offloads structure */ - gs->udp_offloads.port = port; - gs->udp_offloads.callbacks.gro_receive = geneve_gro_receive; - gs->udp_offloads.callbacks.gro_complete = geneve_gro_complete; geneve_notify_add_rx_port(gs); /* Mark socket as an encapsulation socket */ + memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); tunnel_cfg.sk_user_data = gs; tunnel_cfg.encap_type = 1; + tunnel_cfg.gro_receive = geneve_gro_receive; + tunnel_cfg.gro_complete = geneve_gro_complete; tunnel_cfg.encap_rcv = geneve_udp_encap_recv; tunnel_cfg.encap_destroy = NULL; setup_udp_tunnel_sock(net, sock, &tunnel_cfg); @@ -576,9 +567,6 @@ static void geneve_notify_del_rx_port(struct geneve_sock *gs) } rcu_read_unlock(); - - if (sa_family == AF_INET) - udp_del_offload(&gs->udp_offloads); } static void __geneve_sock_release(struct geneve_sock *gs) -- GitLab From 46aa2f30aa7fe03a4dcd732b009284c02ff4f093 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Tue, 5 Apr 2016 08:22:56 -0700 Subject: [PATCH 1758/9938] udp: Remove udp_offloads Now that the UDP encapsulation GRO functions have been moved to the UDP socket we not longer need the udp_offload insfrastructure so removing it. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- include/linux/netdevice.h | 17 ----------- include/net/protocol.h | 3 -- net/ipv4/udp_offload.c | 63 --------------------------------------- 3 files changed, 83 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cb0d5d09c2e4..cb4e508b3f38 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2159,23 +2159,6 @@ struct packet_offload { struct list_head list; }; -struct udp_offload; - -struct udp_offload_callbacks { - struct sk_buff **(*gro_receive)(struct sk_buff **head, - struct sk_buff *skb, - struct udp_offload *uoff); - int (*gro_complete)(struct sk_buff *skb, - int nhoff, - struct udp_offload *uoff); -}; - -struct udp_offload { - __be16 port; - u8 ipproto; - struct udp_offload_callbacks callbacks; -}; - /* often modified stats are per-CPU, other are shared (netdev->stats) */ struct pcpu_sw_netstats { u64 rx_packets; diff --git a/include/net/protocol.h b/include/net/protocol.h index da689f5432de..bf36ca34af7a 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -107,9 +107,6 @@ int inet_del_offload(const struct net_offload *prot, unsigned char num); void inet_register_protosw(struct inet_protosw *p); void inet_unregister_protosw(struct inet_protosw *p); -int udp_add_offload(struct net *net, struct udp_offload *prot); -void udp_del_offload(struct udp_offload *prot); - #if IS_ENABLED(CONFIG_IPV6) int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num); int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num); diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 65c3fd34b363..6230cf4b0d2d 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -14,18 +14,6 @@ #include #include -static DEFINE_SPINLOCK(udp_offload_lock); -static struct udp_offload_priv __rcu *udp_offload_base __read_mostly; - -#define udp_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&udp_offload_lock)) - -struct udp_offload_priv { - struct udp_offload *offload; - possible_net_t net; - struct rcu_head rcu; - struct udp_offload_priv __rcu *next; -}; - static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, netdev_features_t features, struct sk_buff *(*gso_inner_segment)(struct sk_buff *skb, @@ -254,56 +242,6 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, return segs; } -int udp_add_offload(struct net *net, struct udp_offload *uo) -{ - struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC); - - if (!new_offload) - return -ENOMEM; - - write_pnet(&new_offload->net, net); - new_offload->offload = uo; - - spin_lock(&udp_offload_lock); - new_offload->next = udp_offload_base; - rcu_assign_pointer(udp_offload_base, new_offload); - spin_unlock(&udp_offload_lock); - - return 0; -} -EXPORT_SYMBOL(udp_add_offload); - -static void udp_offload_free_routine(struct rcu_head *head) -{ - struct udp_offload_priv *ou_priv = container_of(head, struct udp_offload_priv, rcu); - kfree(ou_priv); -} - -void udp_del_offload(struct udp_offload *uo) -{ - struct udp_offload_priv __rcu **head = &udp_offload_base; - struct udp_offload_priv *uo_priv; - - spin_lock(&udp_offload_lock); - - uo_priv = udp_deref_protected(*head); - for (; uo_priv != NULL; - uo_priv = udp_deref_protected(*head)) { - if (uo_priv->offload == uo) { - rcu_assign_pointer(*head, - udp_deref_protected(uo_priv->next)); - goto unlock; - } - head = &uo_priv->next; - } - pr_warn("udp_del_offload: didn't find offload for port %d\n", ntohs(uo->port)); -unlock: - spin_unlock(&udp_offload_lock); - if (uo_priv) - call_rcu(&uo_priv->rcu, udp_offload_free_routine); -} -EXPORT_SYMBOL(udp_del_offload); - struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, struct udphdr *uh, udp_lookup_t lookup) { @@ -327,7 +265,6 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, if (sk && udp_sk(sk)->gro_receive) goto unflush; - goto out_unlock; unflush: -- GitLab From b67dd2e9bdc0f79a3389e57c51189ed2c2127c00 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 7 Mar 2016 03:35:56 +0100 Subject: [PATCH 1759/9938] ARM: 8548/1: dma-mapping: remove arm_dma_set_mask() arm_dma_set_mask() implements exactly the same behavior as the fallback that dma_set_mask() takes if the set_dma_mask op is not set. Remove it and use that fallback instead like what is already done for dma_get_mask(). Signed-off-by: Alexandre Courbot Signed-off-by: Russell King --- arch/arm/include/asm/dma-mapping.h | 2 -- arch/arm/mm/dma-mapping.c | 16 ---------------- 2 files changed, 18 deletions(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 6ad1ceda62a5..0f2034d28885 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -162,8 +162,6 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) static inline void dma_mark_clean(void *addr, size_t size) { } -extern int arm_dma_set_mask(struct device *dev, u64 dma_mask); - /** * arm_dma_alloc - allocate consistent memory for DMA * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index deac58d5f1f7..bad0c6a4bb7b 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -190,7 +190,6 @@ struct dma_map_ops arm_dma_ops = { .sync_single_for_device = arm_dma_sync_single_for_device, .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu, .sync_sg_for_device = arm_dma_sync_sg_for_device, - .set_dma_mask = arm_dma_set_mask, }; EXPORT_SYMBOL(arm_dma_ops); @@ -209,7 +208,6 @@ struct dma_map_ops arm_coherent_dma_ops = { .get_sgtable = arm_dma_get_sgtable, .map_page = arm_coherent_dma_map_page, .map_sg = arm_dma_map_sg, - .set_dma_mask = arm_dma_set_mask, }; EXPORT_SYMBOL(arm_coherent_dma_ops); @@ -1142,16 +1140,6 @@ int dma_supported(struct device *dev, u64 mask) } EXPORT_SYMBOL(dma_supported); -int arm_dma_set_mask(struct device *dev, u64 dma_mask) -{ - if (!dev->dma_mask || !dma_supported(dev, dma_mask)) - return -EIO; - - *dev->dma_mask = dma_mask; - - return 0; -} - #define PREALLOC_DMA_DEBUG_ENTRIES 4096 static int __init dma_debug_do_init(void) @@ -2005,8 +1993,6 @@ struct dma_map_ops iommu_ops = { .unmap_sg = arm_iommu_unmap_sg, .sync_sg_for_cpu = arm_iommu_sync_sg_for_cpu, .sync_sg_for_device = arm_iommu_sync_sg_for_device, - - .set_dma_mask = arm_dma_set_mask, }; struct dma_map_ops iommu_coherent_ops = { @@ -2020,8 +2006,6 @@ struct dma_map_ops iommu_coherent_ops = { .map_sg = arm_coherent_iommu_map_sg, .unmap_sg = arm_coherent_iommu_unmap_sg, - - .set_dma_mask = arm_dma_set_mask, }; /** -- GitLab From b9b74be163a247fcbb3ef18086cc27123539131c Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 1 Apr 2016 14:33:48 +0100 Subject: [PATCH 1760/9938] ARM: 8555/1: kallsyms: ignore ARM mode switching veneers On ARM, the linker may emit veneers to deal with relative branch instructions that appear too far away from their targets. Since the second kallsyms pass results in an increase of the kernel size, it may result in additional veneers to be emitted, potentially affecting the output of kallsyms itself if these symbols are visible to it, and for that reason, symbols whose names end in '_veneer' are ignored explicitly. However, when building Thumb2 kernels, such veneers are named differently if they also incur a mode switch, and since they are not filtered by kallsyms, they may cause the build to fail. So filter symbols whose names end in '_from_arm' or '_from_thumb' as well. Tested-by: Arnd Bergmann Signed-off-by: Ard Biesheuvel Signed-off-by: Russell King --- scripts/kallsyms.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 638b143ee60f..e287ce60bb11 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -223,6 +223,8 @@ static int symbol_valid(struct sym_entry *s) static char *special_suffixes[] = { "_veneer", /* arm */ + "_from_arm", /* arm */ + "_from_thumb", /* arm */ NULL }; int i; -- GitLab From d4ffe418195b2d0581dfcda05f366e3b0f23d2a9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 29 Mar 2016 08:51:48 +0100 Subject: [PATCH 1761/9938] ARM: 8552/1: kallsyms: remove special lower address limit for CONFIG_ARM Now that we no longer emit .stubs symbols into a section VMA loaded at absolute address 0x1000, we can drop the ARM-specific override that sets a lower limit based on CONFIG_PAGE_OFFSET, below which symbols are filtered from the kallsyms output. Acked-by: Nicolas Pitre Acked-by: Chris Brandt Signed-off-by: Ard Biesheuvel Signed-off-by: Russell King --- scripts/link-vmlinux.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 49d61ade9425..f0f6d9d75435 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -82,10 +82,6 @@ kallsyms() kallsymopt="${kallsymopt} --all-symbols" fi - if [ -n "${CONFIG_ARM}" ] && [ -z "${CONFIG_XIP_KERNEL}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then - kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET" - fi - if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then kallsymopt="${kallsymopt} --absolute-percpu" fi -- GitLab From 2d9586399932dff4746dc25d6498123959d69762 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 29 Mar 2016 08:54:47 +0100 Subject: [PATCH 1762/9938] ARM: 8553/1: kallsyms: remove --page-offset command line option The --page-offset command line option was only used for ARM, to filter symbol addresses below CONFIG_PAGE_OFFSET. This is no longer needed, so remove the functionality altogether. Acked-by: Nicolas Pitre Acked-by: Chris Brandt Signed-off-by: Ard Biesheuvel Signed-off-by: Russell King --- scripts/kallsyms.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index e287ce60bb11..1f22a186c18c 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -63,7 +63,6 @@ static unsigned int table_size, table_cnt; static int all_symbols = 0; static int absolute_percpu = 0; static char symbol_prefix_char = '\0'; -static unsigned long long kernel_start_addr = 0; static int base_relative = 0; int token_profit[0x10000]; @@ -230,10 +229,6 @@ static int symbol_valid(struct sym_entry *s) int i; char *sym_name = (char *)s->sym + 1; - - if (s->addr < kernel_start_addr) - return 0; - /* skip prefix char */ if (symbol_prefix_char && *sym_name == symbol_prefix_char) sym_name++; @@ -767,9 +762,6 @@ int main(int argc, char **argv) if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\'')) p++; symbol_prefix_char = *p; - } else if (strncmp(argv[i], "--page-offset=", 14) == 0) { - const char *p = &argv[i][14]; - kernel_start_addr = strtoull(p, NULL, 16); } else if (strcmp(argv[i], "--base-relative") == 0) base_relative = 1; else -- GitLab From 4e801fa14f68223d36480bced975ebf0c5f9a284 Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Thu, 7 Apr 2016 10:09:13 -0400 Subject: [PATCH 1763/9938] tipc: eliminate buffer leak in bearer layer When enabling a bearer we create a 'neigbor discoverer' instance by calling the function tipc_disc_create() before the bearer is actually registered in the list of enabled bearers. Because of this, the very first discovery broadcast message, created by the mentioned function, is lost, since it cannot find any valid bearer to use. Furthermore, the used send function, tipc_bearer_xmit_skb() does not free the given buffer when it cannot find a bearer, resulting in the leak of exactly one send buffer each time a bearer is enabled. This commit fixes this problem by introducing two changes: 1) Instead of attemting to send the discovery message directly, we let tipc_disc_create() return the discovery buffer to the calling function, tipc_enable_bearer(), so that the latter can send it when the enabling sequence is finished. 2) In tipc_bearer_xmit_skb(), as well as in the two other transmit functions at the bearer layer, we now free the indicated buffer or buffer chain when a valid bearer cannot be found. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/bearer.c | 51 +++++++++++++++++++++++---------------------- net/tipc/discover.c | 7 ++----- net/tipc/discover.h | 2 +- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 27a5406213c6..20566e9a1369 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -205,6 +205,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, struct tipc_bearer *b; struct tipc_media *m; struct tipc_bearer_names b_names; + struct sk_buff *skb; char addr_string[16]; u32 bearer_id; u32 with_this_prio; @@ -301,7 +302,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, b->net_plane = bearer_id + 'A'; b->priority = priority; - res = tipc_disc_create(net, b, &b->bcast_addr); + res = tipc_disc_create(net, b, &b->bcast_addr, &skb); if (res) { bearer_disable(net, b); pr_warn("Bearer <%s> rejected, discovery object creation failed\n", @@ -310,7 +311,8 @@ static int tipc_enable_bearer(struct net *net, const char *name, } rcu_assign_pointer(tn->bearer_list[bearer_id], b); - + if (skb) + tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr); pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", name, tipc_addr_string_fill(addr_string, disc_domain), priority); @@ -450,6 +452,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (likely(b)) b->media->send_msg(net, skb, b, dest); + else + kfree_skb(skb); rcu_read_unlock(); } @@ -468,11 +472,11 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, rcu_read_lock(); b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); - if (likely(b)) { - skb_queue_walk_safe(xmitq, skb, tmp) { - __skb_dequeue(xmitq); - b->media->send_msg(net, skb, b, dst); - } + if (unlikely(!b)) + __skb_queue_purge(xmitq); + skb_queue_walk_safe(xmitq, skb, tmp) { + __skb_dequeue(xmitq); + b->media->send_msg(net, skb, b, dst); } rcu_read_unlock(); } @@ -490,14 +494,14 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, rcu_read_lock(); b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); - if (likely(b)) { - skb_queue_walk_safe(xmitq, skb, tmp) { - hdr = buf_msg(skb); - msg_set_non_seq(hdr, 1); - msg_set_mc_netid(hdr, net_id); - __skb_dequeue(xmitq); - b->media->send_msg(net, skb, b, &b->bcast_addr); - } + if (unlikely(!b)) + __skb_queue_purge(xmitq); + skb_queue_walk_safe(xmitq, skb, tmp) { + hdr = buf_msg(skb); + msg_set_non_seq(hdr, 1); + msg_set_mc_netid(hdr, net_id); + __skb_dequeue(xmitq); + b->media->send_msg(net, skb, b, &b->bcast_addr); } rcu_read_unlock(); } @@ -513,24 +517,21 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, * ignores packets sent using interface multicast, and traffic sent to other * nodes (which can happen if interface is running in promiscuous mode). */ -static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, +static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { struct tipc_bearer *b; rcu_read_lock(); b = rcu_dereference_rtnl(dev->tipc_ptr); - if (likely(b)) { - if (likely(buf->pkt_type <= PACKET_BROADCAST)) { - buf->next = NULL; - tipc_rcv(dev_net(dev), buf, b); - rcu_read_unlock(); - return NET_RX_SUCCESS; - } + if (likely(b && (skb->pkt_type <= PACKET_BROADCAST))) { + skb->next = NULL; + tipc_rcv(dev_net(dev), skb, b); + rcu_read_unlock(); + return NET_RX_SUCCESS; } rcu_read_unlock(); - - kfree_skb(buf); + kfree_skb(skb); return NET_RX_DROP; } diff --git a/net/tipc/discover.c b/net/tipc/discover.c index f1e738e80535..ad9d477cc242 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -268,10 +268,9 @@ static void disc_timeout(unsigned long data) * Returns 0 if successful, otherwise -errno. */ int tipc_disc_create(struct net *net, struct tipc_bearer *b, - struct tipc_media_addr *dest) + struct tipc_media_addr *dest, struct sk_buff **skb) { struct tipc_link_req *req; - struct sk_buff *skb; req = kmalloc(sizeof(*req), GFP_ATOMIC); if (!req) @@ -293,9 +292,7 @@ int tipc_disc_create(struct net *net, struct tipc_bearer *b, setup_timer(&req->timer, disc_timeout, (unsigned long)req); mod_timer(&req->timer, jiffies + req->timer_intv); b->link_req = req; - skb = skb_clone(req->buf, GFP_ATOMIC); - if (skb) - tipc_bearer_xmit_skb(net, req->bearer_id, skb, &req->dest); + *skb = skb_clone(req->buf, GFP_ATOMIC); return 0; } diff --git a/net/tipc/discover.h b/net/tipc/discover.h index c9b12770c5ed..b80a335389c0 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -40,7 +40,7 @@ struct tipc_link_req; int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr, - struct tipc_media_addr *dest); + struct tipc_media_addr *dest, struct sk_buff **skb); void tipc_disc_delete(struct tipc_link_req *req); void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr); void tipc_disc_add_dest(struct tipc_link_req *req); -- GitLab From 5b7066c3dd24c7d538e5ee402eb24bb182c16dab Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Thu, 7 Apr 2016 10:09:14 -0400 Subject: [PATCH 1764/9938] tipc: stricter filtering of packets in bearer layer Resetting a bearer/interface, with the consequence of resetting all its pertaining links, is not an atomic action. This becomes particularly evident in very large clusters, where a lot of traffic may happen on the remaining links while we are busy shutting them down. In extreme cases, we may even see links being re-created and re-established before we are finished with the job. To solve this, we now introduce a solution where we temporarily detach the bearer from the interface when the bearer is reset. This inhibits all packet reception, while sending still is possible. For the latter, we use the fact that the device's user pointer now is zero to filter out which packets can be sent during this situation; i.e., outgoing RESET messages only. This filtering serves to speed up the neighbors' detection of the loss event, and saves us from unnecessary probing. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/bearer.c | 50 +++++++++++++++++++++++++++++++---------------- net/tipc/msg.h | 5 +++++ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 20566e9a1369..6f11c62bc8f9 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -337,23 +337,16 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b) */ static void bearer_disable(struct net *net, struct tipc_bearer *b) { - struct tipc_net *tn = net_generic(net, tipc_net_id); - u32 i; + struct tipc_net *tn = tipc_net(net); + int bearer_id = b->identity; pr_info("Disabling bearer <%s>\n", b->name); b->media->disable_media(b); - - tipc_node_delete_links(net, b->identity); + tipc_node_delete_links(net, bearer_id); RCU_INIT_POINTER(b->media_ptr, NULL); if (b->link_req) tipc_disc_delete(b->link_req); - - for (i = 0; i < MAX_BEARERS; i++) { - if (b == rtnl_dereference(tn->bearer_list[i])) { - RCU_INIT_POINTER(tn->bearer_list[i], NULL); - break; - } - } + RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL); kfree_rcu(b, rcu); } @@ -396,7 +389,7 @@ void tipc_disable_l2_media(struct tipc_bearer *b) /** * tipc_l2_send_msg - send a TIPC packet out over an L2 interface - * @buf: the packet to be sent + * @skb: the packet to be sent * @b: the bearer through which the packet is to be sent * @dest: peer destination address */ @@ -405,17 +398,21 @@ int tipc_l2_send_msg(struct net *net, struct sk_buff *skb, { struct net_device *dev; int delta; + void *tipc_ptr; dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr); if (!dev) return 0; + /* Send RESET message even if bearer is detached from device */ + tipc_ptr = rtnl_dereference(dev->tipc_ptr); + if (unlikely(!tipc_ptr && !msg_is_reset(buf_msg(skb)))) + goto drop; + delta = dev->hard_header_len - skb_headroom(skb); if ((delta > 0) && - pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { - kfree_skb(skb); - return 0; - } + pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) + goto drop; skb_reset_network_header(skb); skb->dev = dev; @@ -424,6 +421,9 @@ int tipc_l2_send_msg(struct net *net, struct sk_buff *skb, dev->dev_addr, skb->len); dev_queue_xmit(skb); return 0; +drop: + kfree_skb(skb); + return 0; } int tipc_bearer_mtu(struct net *net, u32 bearer_id) @@ -549,9 +549,18 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); + struct tipc_net *tn = tipc_net(net); struct tipc_bearer *b; + int i; b = rtnl_dereference(dev->tipc_ptr); + if (!b) { + for (i = 0; i < MAX_BEARERS; b = NULL, i++) { + b = rtnl_dereference(tn->bearer_list[i]); + if (b && (b->media_ptr == dev)) + break; + } + } if (!b) return NOTIFY_DONE; @@ -561,13 +570,20 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, case NETDEV_CHANGE: if (netif_carrier_ok(dev)) break; + case NETDEV_UP: + rcu_assign_pointer(dev->tipc_ptr, b); + break; case NETDEV_GOING_DOWN: + RCU_INIT_POINTER(dev->tipc_ptr, NULL); + synchronize_net(); + tipc_reset_bearer(net, b); + break; case NETDEV_CHANGEMTU: tipc_reset_bearer(net, b); break; case NETDEV_CHANGEADDR: b->media->raw2addr(b, &b->addr, - (char *)dev->dev_addr); + (char *)dev->dev_addr); tipc_reset_bearer(net, b); break; case NETDEV_UNREGISTER: diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 55778a0aebf3..f34f639df643 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -779,6 +779,11 @@ static inline bool msg_peer_node_is_up(struct tipc_msg *m) return msg_redundant_link(m); } +static inline bool msg_is_reset(struct tipc_msg *hdr) +{ + return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG); +} + struct sk_buff *tipc_buf_acquire(u32 size); bool tipc_msg_validate(struct sk_buff *skb); bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err); -- GitLab From 03be98226c14d787939381b9f42d81764ea8eedc Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 7 Apr 2016 23:53:35 +0200 Subject: [PATCH 1765/9938] sock: make lockdep_sock_is_held static inline I forgot to add inline to lockdep_sock_is_held, so it generated all kinds of build warnings if not build with lockdep support. Reported-by: kbuild test robot Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/net/sock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index eb2d7c3e120b..46b29374df8e 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1360,7 +1360,7 @@ do { \ lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \ } while (0) -static bool lockdep_sock_is_held(const struct sock *csk) +static inline bool lockdep_sock_is_held(const struct sock *csk) { struct sock *sk = (struct sock *)csk; -- GitLab From 832ac592149f542052e387f17dfcfa7ebea50aaf Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 14 Mar 2016 11:05:40 -0700 Subject: [PATCH 1766/9938] ixgbe: Delete some unused register definitions I noticed the SRAMREL registers are not referenced for any device, so delete the definitions. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index bc012ab48475..d02a0a3fa1d8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -143,13 +143,6 @@ #define IXGBE_GRC_X550EM_a 0x15F64 #define IXGBE_GRC(_hw) IXGBE_BY_MAC((_hw), GRC) -#define IXGBE_SRAMREL_8259X 0x10210 -#define IXGBE_SRAMREL_X540 IXGBE_SRAMREL_8259X -#define IXGBE_SRAMREL_X550 IXGBE_SRAMREL_8259X -#define IXGBE_SRAMREL_X550EM_x IXGBE_SRAMREL_8259X -#define IXGBE_SRAMREL_X550EM_a 0x15F6C -#define IXGBE_SRAMREL(_hw) IXGBE_BY_MAC((_hw), SRAMREL) - /* General Receive Control */ #define IXGBE_GRC_MNG 0x00000001 /* Manageability Enable */ #define IXGBE_GRC_APME 0x00000002 /* APM enabled in EEPROM */ @@ -2948,7 +2941,6 @@ union ixgbe_atr_hash_dword { IXGBE_CAT(EEC, m), \ IXGBE_CAT(FLA, m), \ IXGBE_CAT(GRC, m), \ - IXGBE_CAT(SRAMREL, m), \ IXGBE_CAT(FACTPS, m), \ IXGBE_CAT(SWSM, m), \ IXGBE_CAT(SWFW_SYNC, m), \ -- GitLab From 3775b814d5380a25ed89b881d845f79f81bc5547 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 14 Mar 2016 11:05:46 -0700 Subject: [PATCH 1767/9938] ixgbe: Change the lan_id and func fields to a u8 to avoid casts Since the lan_id and func fields only ever hold small values, make them u8 to avoid casts used to silence warnings. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 4 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 8c7e78b21c4e..dfdb1149b6fd 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3600,7 +3600,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; - fw_cmd.port_num = (u8)hw->bus.func; + fw_cmd.port_num = hw->bus.func; fw_cmd.ver_maj = maj; fw_cmd.ver_min = min; fw_cmd.ver_build = build; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index d02a0a3fa1d8..7ae4bbd26ad8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3122,8 +3122,8 @@ struct ixgbe_bus_info { enum ixgbe_bus_width width; enum ixgbe_bus_type type; - u16 func; - u16 lan_id; + u8 func; + u8 lan_id; }; /* Flow control parameters */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 9d3f765638cc..5affac123b75 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -862,7 +862,7 @@ static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; - fw_cmd.port_number = (u8)hw->bus.lan_id; + fw_cmd.port_number = hw->bus.lan_id; status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, sizeof(struct ixgbe_hic_disable_rxen), -- GitLab From 73457165d71d5ce0e41c0adb7bfa484702c36248 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 14 Mar 2016 11:05:51 -0700 Subject: [PATCH 1768/9938] ixgbe: Correct length check for round up The function ixgbe_host_interface_command actually uses a multiple of word sized buffer to do its business, but only checks against the actual length passed in. This means that on read operations it could be possible to modify locations beyond the length passed in. Change the check to round up in the same way, just to avoid any possible hazard. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index dfdb1149b6fd..a2ca9ef0daab 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3557,7 +3557,7 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, if (buf_len == 0) return 0; - if (length < (buf_len + hdr_size)) { + if (length < round_up(buf_len, 4) + hdr_size) { hw_dbg(hw, "Buffer not large enough for reply message.\n"); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } -- GitLab From 5cffde309cb3f6f7aaaa459abd3eba245a863f8a Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 14 Mar 2016 11:05:57 -0700 Subject: [PATCH 1769/9938] ixgbe: Clean up interface for firmware commands Clean up the interface for issuing firmware commands to use a void * instead of a u32 *. This eliminates a number of casts. Also clean up ixgbe_host_interface_command in a few other ways, eliminating comparisons with 0, redundant parens and minor formatting issues. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ixgbe/ixgbe_common.c | 39 ++++++++++--------- .../net/ethernet/intel/ixgbe/ixgbe_common.h | 4 +- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 13 +++---- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index a2ca9ef0daab..b8cdff7fe673 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3483,15 +3483,19 @@ static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) * Communicates with the manageability block. On success return 0 * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. **/ -s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, +s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer, u32 length, u32 timeout, bool return_data) { - u32 hicr, i, bi, fwsts; u32 hdr_size = sizeof(struct ixgbe_hic_hdr); + u32 hicr, i, bi, fwsts; u16 buf_len, dword_len; + union { + struct ixgbe_hic_hdr hdr; + u32 u32arr[1]; + } *bp = buffer; - if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { + if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } @@ -3502,26 +3506,25 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, /* Check that the host interface is enabled. */ hicr = IXGBE_READ_REG(hw, IXGBE_HICR); - if ((hicr & IXGBE_HICR_EN) == 0) { + if (!(hicr & IXGBE_HICR_EN)) { hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n"); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } /* Calculate length in DWORDs. We must be DWORD aligned */ - if ((length % (sizeof(u32))) != 0) { + if (length % sizeof(u32)) { hw_dbg(hw, "Buffer length failure, not aligned to dword"); return IXGBE_ERR_INVALID_ARGUMENT; } dword_len = length >> 2; - /* - * The device driver writes the relevant command block + /* The device driver writes the relevant command block * into the ram area. */ for (i = 0; i < dword_len; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, - i, cpu_to_le32(buffer[i])); + i, cpu_to_le32(bp->u32arr[i])); /* Setting this bit tells the ARC that a new command is pending. */ IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); @@ -3534,8 +3537,8 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, } /* Check command successful completion. */ - if ((timeout != 0 && i == timeout) || - (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) { + if ((timeout && i == timeout) || + !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { hw_dbg(hw, "Command has failed with no status valid.\n"); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } @@ -3548,13 +3551,13 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, /* first pull in the header so we know the buffer length */ for (bi = 0; bi < dword_len; bi++) { - buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); - le32_to_cpus(&buffer[bi]); + bp->u32arr[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); + le32_to_cpus(&bp->u32arr[bi]); } /* If there is any thing in data position pull it in */ - buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; - if (buf_len == 0) + buf_len = bp->hdr.buf_len; + if (!buf_len) return 0; if (length < round_up(buf_len, 4) + hdr_size) { @@ -3565,10 +3568,10 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, /* Calculate length in DWORDs, add 3 for odd lengths */ dword_len = (buf_len + 3) >> 2; - /* Pull in the rest of the buffer (bi is where we left off)*/ + /* Pull in the rest of the buffer (bi is where we left off) */ for (; bi <= dword_len; bi++) { - buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); - le32_to_cpus(&buffer[bi]); + bp->u32arr[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); + le32_to_cpus(&bp->u32arr[bi]); } return 0; @@ -3612,7 +3615,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, fw_cmd.pad2 = 0; for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { - ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, + ret_val = ixgbe_host_interface_command(hw, &fw_cmd, sizeof(fw_cmd), IXGBE_HI_COMMAND_TIMEOUT, true); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 2e290150ab54..6f8e6a56e242 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -111,8 +111,8 @@ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps); s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 ver); -s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, - u32 length, u32 timeout, bool return_data); +s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *, u32 length, + u32 timeout, bool return_data); void ixgbe_clear_tx_pending(struct ixgbe_hw *hw); bool ixgbe_mng_present(struct ixgbe_hw *hw); bool ixgbe_mng_enabled(struct ixgbe_hw *hw); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 5affac123b75..65832fa30426 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -437,8 +437,7 @@ static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, /* one word */ buffer.length = cpu_to_be16(sizeof(u16)); - status = ixgbe_host_interface_command(hw, (u32 *)&buffer, - sizeof(buffer), + status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); if (status) return status; @@ -488,7 +487,7 @@ static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, buffer.address = cpu_to_be32((offset + current_word) * 2); buffer.length = cpu_to_be16(words_to_read * 2); - status = ixgbe_host_interface_command(hw, (u32 *)&buffer, + status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); @@ -771,8 +770,7 @@ static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, buffer.data = data; buffer.address = cpu_to_be32(offset * 2); - status = ixgbe_host_interface_command(hw, (u32 *)&buffer, - sizeof(buffer), + status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); return status; } @@ -814,8 +812,7 @@ static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; buffer.req.checksum = FW_DEFAULT_CHECKSUM; - status = ixgbe_host_interface_command(hw, (u32 *)&buffer, - sizeof(buffer), + status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); return status; } @@ -864,7 +861,7 @@ static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; fw_cmd.port_number = hw->bus.lan_id; - status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, + status = ixgbe_host_interface_command(hw, &fw_cmd, sizeof(struct ixgbe_hic_disable_rxen), IXGBE_HI_COMMAND_TIMEOUT, true); -- GitLab From af7419017626b93ccdf76b12c2b1dc8fe17da4ad Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 14 Mar 2016 11:06:02 -0700 Subject: [PATCH 1770/9938] ixgbe: Take manageability semaphore for firmware commands We need to take the manageability semaphore when issuing firmware commands to avoid problems. With this in place, the semaphore is no longer taken in the ixgbe_set_fw_drv_ver_generic function, since it will now always be taken by the ixgbe_host_interface_command function. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ixgbe/ixgbe_common.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index b8cdff7fe673..ee43a383aa0a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3494,11 +3494,16 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer, struct ixgbe_hic_hdr hdr; u32 u32arr[1]; } *bp = buffer; + s32 status; if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } + /* Take management host interface semaphore */ + status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); + if (status) + return status; /* Set bit 9 of FWSTS clearing FW reset indication */ fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); @@ -3508,13 +3513,15 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer, hicr = IXGBE_READ_REG(hw, IXGBE_HICR); if (!(hicr & IXGBE_HICR_EN)) { hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n"); - return IXGBE_ERR_HOST_INTERFACE_COMMAND; + status = IXGBE_ERR_HOST_INTERFACE_COMMAND; + goto rel_out; } /* Calculate length in DWORDs. We must be DWORD aligned */ if (length % sizeof(u32)) { hw_dbg(hw, "Buffer length failure, not aligned to dword"); - return IXGBE_ERR_INVALID_ARGUMENT; + status = IXGBE_ERR_INVALID_ARGUMENT; + goto rel_out; } dword_len = length >> 2; @@ -3540,11 +3547,12 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer, if ((timeout && i == timeout) || !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { hw_dbg(hw, "Command has failed with no status valid.\n"); - return IXGBE_ERR_HOST_INTERFACE_COMMAND; + status = IXGBE_ERR_HOST_INTERFACE_COMMAND; + goto rel_out; } if (!return_data) - return 0; + goto rel_out; /* Calculate length in DWORDs */ dword_len = hdr_size >> 2; @@ -3558,11 +3566,12 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer, /* If there is any thing in data position pull it in */ buf_len = bp->hdr.buf_len; if (!buf_len) - return 0; + goto rel_out; if (length < round_up(buf_len, 4) + hdr_size) { hw_dbg(hw, "Buffer not large enough for reply message.\n"); - return IXGBE_ERR_HOST_INTERFACE_COMMAND; + status = IXGBE_ERR_HOST_INTERFACE_COMMAND; + goto rel_out; } /* Calculate length in DWORDs, add 3 for odd lengths */ @@ -3574,7 +3583,10 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer, le32_to_cpus(&bp->u32arr[bi]); } - return 0; +rel_out: + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); + + return status; } /** @@ -3597,9 +3609,6 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, int i; s32 ret_val; - if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM)) - return IXGBE_ERR_SWFW_SYNC; - fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; @@ -3631,7 +3640,6 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, break; } - hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); return ret_val; } -- GitLab From 8220bbc12d39175964cb56e100fabcedd59c48da Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 7 Mar 2016 09:30:09 -0800 Subject: [PATCH 1771/9938] ixgbe/ixgbevf: Add support for bulk free in Tx cleanup & cleanup boolean logic This patch enables bulk free in Tx cleanup for ixgbevf and cleans up the boolean logic in the polling routines for ixgbe and ixgbevf in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 10 +++++++--- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 14 +++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 19bf3860d3d8..d5509cc30abd 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1111,6 +1111,7 @@ static int ixgbe_tx_maxrate(struct net_device *netdev, * ixgbe_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: structure containing interrupt and ring information * @tx_ring: tx ring to clean + * @napi_budget: Used to determine if we are in netpoll **/ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *tx_ring, int napi_budget) @@ -2807,8 +2808,10 @@ int ixgbe_poll(struct napi_struct *napi, int budget) ixgbe_update_dca(q_vector); #endif - ixgbe_for_each_ring(ring, q_vector->tx) - clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring, budget); + ixgbe_for_each_ring(ring, q_vector->tx) { + if (!ixgbe_clean_tx_irq(q_vector, ring, budget)) + clean_complete = false; + } /* Exit if we are called by netpoll or busy polling is active */ if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector)) @@ -2826,7 +2829,8 @@ int ixgbe_poll(struct napi_struct *napi, int budget) per_ring_budget); work_done += cleaned; - clean_complete &= (cleaned < per_ring_budget); + if (cleaned >= per_ring_budget) + clean_complete = false; } ixgbe_qv_unlock_napi(q_vector); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 50b6bfffaf32..007cbe094990 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -288,9 +288,10 @@ static void ixgbevf_tx_timeout(struct net_device *netdev) * ixgbevf_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: board private structure * @tx_ring: tx ring to clean + * @napi_budget: Used to determine if we are in netpoll **/ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, - struct ixgbevf_ring *tx_ring) + struct ixgbevf_ring *tx_ring, int napi_budget) { struct ixgbevf_adapter *adapter = q_vector->adapter; struct ixgbevf_tx_buffer *tx_buffer; @@ -328,7 +329,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, total_packets += tx_buffer->gso_segs; /* free the skb */ - dev_kfree_skb_any(tx_buffer->skb); + napi_consume_skb(tx_buffer->skb, napi_budget); /* unmap skb header data */ dma_unmap_single(tx_ring->dev, @@ -1013,8 +1014,10 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) int per_ring_budget, work_done = 0; bool clean_complete = true; - ixgbevf_for_each_ring(ring, q_vector->tx) - clean_complete &= ixgbevf_clean_tx_irq(q_vector, ring); + ixgbevf_for_each_ring(ring, q_vector->tx) { + if (!ixgbevf_clean_tx_irq(q_vector, ring, budget)) + clean_complete = false; + } if (budget <= 0) return budget; @@ -1035,7 +1038,8 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) int cleaned = ixgbevf_clean_rx_irq(q_vector, ring, per_ring_budget); work_done += cleaned; - clean_complete &= (cleaned < per_ring_budget); + if (cleaned >= per_ring_budget) + clean_complete = false; } #ifdef CONFIG_NET_RX_BUSY_POLL -- GitLab From a711ad89a887f7cb2ecbea591a58b6102ad9be7a Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 21 Mar 2016 11:21:31 -0700 Subject: [PATCH 1772/9938] ixgbe: Add support for single-port X550 device Add support for a single-port X550 device. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index ee43a383aa0a..8c560da29d23 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -97,6 +97,7 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) case IXGBE_DEV_ID_X540T: case IXGBE_DEV_ID_X540T1: case IXGBE_DEV_ID_X550T: + case IXGBE_DEV_ID_X550T1: case IXGBE_DEV_ID_X550EM_X_10G_T: supported = true; break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index d5509cc30abd..9594438ffa07 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -125,6 +125,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550T), board_X550}, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550T1), board_X550}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KX4), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x}, @@ -8983,6 +8984,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id, case IXGBE_DEV_ID_X540T: case IXGBE_DEV_ID_X540T1: case IXGBE_DEV_ID_X550T: + case IXGBE_DEV_ID_X550T1: case IXGBE_DEV_ID_X550EM_X_KX4: case IXGBE_DEV_ID_X550EM_X_KR: case IXGBE_DEV_ID_X550EM_X_10G_T: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 7ae4bbd26ad8..bd95be2d7927 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -75,6 +75,7 @@ #define IXGBE_DEV_ID_X540T1 0x1560 #define IXGBE_DEV_ID_X550T 0x1563 +#define IXGBE_DEV_ID_X550T1 0x15D1 #define IXGBE_DEV_ID_X550EM_X_KX4 0x15AA #define IXGBE_DEV_ID_X550EM_X_KR 0x15AB #define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC -- GitLab From 207969b94cf2736f4f2f51aec287a6a0ea7d5dbd Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:17:59 -0700 Subject: [PATCH 1773/9938] ixgbe: Add definitions for x550em_a 10G MAC Add definitions for a x550em_a 10G MAC device with a native SFP interface. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index bd95be2d7927..b505da3e9778 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -81,16 +81,18 @@ #define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC #define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD #define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE +#define IXGBE_DEV_ID_X550EM_A_SFP_N 0x15C4 + +/* VF Device IDs */ #define IXGBE_DEV_ID_X550_VF_HV 0x1564 #define IXGBE_DEV_ID_X550_VF 0x1565 #define IXGBE_DEV_ID_X550EM_X_VF 0x15A8 #define IXGBE_DEV_ID_X550EM_X_VF_HV 0x15A9 - -/* VF Device IDs */ #define IXGBE_DEV_ID_82599_VF 0x10ED #define IXGBE_DEV_ID_X540_VF 0x1515 #define IXGBE_DEV_ID_X550_VF 0x1565 #define IXGBE_DEV_ID_X550EM_X_VF 0x15A8 +#define IXGBE_DEV_ID_X550EM_A_VF 0x15C5 #define IXGBE_CAT(r, m) IXGBE_##r##_##m @@ -129,7 +131,7 @@ #define IXGBE_FLA_X540 IXGBE_FLA_8259X #define IXGBE_FLA_X550 IXGBE_FLA_8259X #define IXGBE_FLA_X550EM_x IXGBE_FLA_8259X -#define IXGBE_FLA_X550EM_a 0x15F6C +#define IXGBE_FLA_X550EM_a 0x15F68 #define IXGBE_FLA(_hw) IXGBE_BY_MAC((_hw), FLA) #define IXGBE_EEMNGCTL 0x10110 #define IXGBE_EEMNGDATA 0x10114 @@ -369,6 +371,8 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_MRCTL(_i) (0x0F600 + ((_i) * 4)) #define IXGBE_VMRVLAN(_i) (0x0F610 + ((_i) * 4)) #define IXGBE_VMRVM(_i) (0x0F630 + ((_i) * 4)) +#define IXGBE_WQBR_RX(_i) (0x2FB0 + ((_i) * 4)) /* 4 total */ +#define IXGBE_WQBR_TX(_i) (0x8130 + ((_i) * 4)) /* 4 total */ #define IXGBE_L34T_IMIR(_i) (0x0E800 + ((_i) * 4)) /*128 of these (0-127)*/ #define IXGBE_RXFECCERR0 0x051B8 #define IXGBE_LLITHRESH 0x0EC90 @@ -440,6 +444,8 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_DMATXCTL_TE 0x1 /* Transmit Enable */ #define IXGBE_DMATXCTL_NS 0x2 /* No Snoop LSO hdr buffer */ #define IXGBE_DMATXCTL_GDV 0x8 /* Global Double VLAN */ +#define IXGBE_DMATXCTL_MDP_EN 0x20 /* Bit 5 */ +#define IXGBE_DMATXCTL_MBINTEN 0x40 /* Bit 6 */ #define IXGBE_DMATXCTL_VT_SHIFT 16 /* VLAN EtherType */ #define IXGBE_PFDTXGSWC_VT_LBEN 0x1 /* Local L2 VT switch enable */ @@ -548,7 +554,6 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_TDPT2TCCR(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TDPT2TCSR(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */ - /* Security Control Registers */ #define IXGBE_SECTXCTRL 0x08800 #define IXGBE_SECTXSTAT 0x08804 @@ -1197,6 +1202,8 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_RDRXCTL_RSCLLIDIS 0x00800000 /* Disable RSC compl on LLI */ #define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC enabled */ #define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC enabled */ +#define IXGBE_RDRXCTL_MBINTEN 0x10000000 +#define IXGBE_RDRXCTL_MDP_EN 0x20000000 /* RQTC Bit Masks and Shifts */ #define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4) @@ -1951,7 +1958,9 @@ enum { #define IXGBE_GSSR_PHY1_SM 0x0004 #define IXGBE_GSSR_MAC_CSR_SM 0x0008 #define IXGBE_GSSR_FLASH_SM 0x0010 +#define IXGBE_GSSR_NVM_UPDATE_SM 0x0200 #define IXGBE_GSSR_SW_MNG_SM 0x0400 +#define IXGBE_GSSR_TOKEN_SM 0x40000000 /* SW bit for shared access */ #define IXGBE_GSSR_SHARED_I2C_SM 0x1806 /* Wait for both phys & I2Cs */ #define IXGBE_GSSR_I2C_MASK 0x1800 #define IXGBE_GSSR_NVM_PHY_MASK 0xF @@ -2524,6 +2533,10 @@ enum ixgbe_fdir_pballoc_type { #define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS 0x00000080 #define IXGBE_FDIRCTRL_DROP_Q_SHIFT 8 #define IXGBE_FDIRCTRL_FLEX_SHIFT 16 +#define IXGBE_FDIRCTRL_DROP_NO_MATCH 0x00008000 +#define IXGBE_FDIRCTRL_FILTERMODE_SHIFT 21 +#define IXGBE_FDIRCTRL_FILTERMODE_MACVLAN 0x0001 /* bit 23:21, 001b */ +#define IXGBE_FDIRCTRL_FILTERMODE_CLOUD 0x0002 /* bit 23:21, 010b */ #define IXGBE_FDIRCTRL_SEARCHLIM 0x00800000 #define IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT 24 #define IXGBE_FDIRCTRL_FULL_THRESH_MASK 0xF0000000 @@ -2982,6 +2995,7 @@ enum ixgbe_mac_type { ixgbe_mac_X540, ixgbe_mac_X550, ixgbe_mac_X550EM_x, + ixgbe_mac_x550em_a, ixgbe_num_macs }; -- GitLab From 9a5c27e6ef9166612f95564bc2fc69506d1be2b3 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:04 -0700 Subject: [PATCH 1774/9938] ixgbe: Use method pointer to access IOSF devices Provide method pointers and use them to access IOSF-attached devices. A new MAC will introduce a new access method. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 32 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index b505da3e9778..fef2264ff5f0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3332,6 +3332,8 @@ struct ixgbe_mac_operations { s32 (*dmac_config)(struct ixgbe_hw *hw); s32 (*dmac_update_tcs)(struct ixgbe_hw *hw); s32 (*dmac_config_tcs)(struct ixgbe_hw *hw); + s32 (*read_iosf_sb_reg)(struct ixgbe_hw *, u32, u32, u32 *); + s32 (*write_iosf_sb_reg)(struct ixgbe_hw *, u32, u32, u32); }; struct ixgbe_phy_operations { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 65832fa30426..878ea1ed87b4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1615,7 +1615,7 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, s32 status; u32 reg_val; - status = ixgbe_read_iosf_sb_reg_x550(hw, + status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status) @@ -1637,7 +1637,7 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, /* Restart auto-negotiation. */ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; - status = ixgbe_write_iosf_sb_reg_x550(hw, + status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); @@ -1654,9 +1654,9 @@ static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) s32 status; u32 reg_val; - status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, - IXGBE_SB_IOSF_TARGET_KX4_PCS0 + - hw->bus.lan_id, ®_val); + status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, + IXGBE_SB_IOSF_TARGET_KX4_PCS0 + + hw->bus.lan_id, ®_val); if (status) return status; @@ -1675,9 +1675,9 @@ static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) /* Restart auto-negotiation. */ reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; - status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, - IXGBE_SB_IOSF_TARGET_KX4_PCS0 + - hw->bus.lan_id, reg_val); + status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, + IXGBE_SB_IOSF_TARGET_KX4_PCS0 + + hw->bus.lan_id, reg_val); return status; } @@ -1897,9 +1897,10 @@ static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR) return 0; - rc = ixgbe_read_iosf_sb_reg_x550(hw, - IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + rc = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, + ®_val); if (rc) return rc; @@ -1909,9 +1910,10 @@ static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; if (asm_dir) reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; - rc = ixgbe_write_iosf_sb_reg_x550(hw, - IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + rc = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, + reg_val); /* This device does not fully support AN. */ hw->fc.disable_fc_autoneg = true; @@ -2449,6 +2451,8 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = { .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, .init_swfw_sync = &ixgbe_init_swfw_sync_X540, .setup_fc = NULL, /* defined later */ + .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, + .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, }; #define X550_COMMON_EEP \ -- GitLab From 49425dfc74512bef9cf15eafb5de0fc98f024e20 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:09 -0700 Subject: [PATCH 1775/9938] ixgbe: Add support for x550em_a 10G MAC type Add support for x550em_a 10G MAC type to the ixgbe driver. The new MAC includes new firmware commands that need to be used to control PHY and IOSF access, so that support is also added. The interface supported is a native SFP+ interface. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 + .../net/ethernet/intel/ixgbe/ixgbe_82599.c | 1 + .../net/ethernet/intel/ixgbe/ixgbe_common.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c | 6 +- .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 9 +- drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 3 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 43 +++- drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 6 +- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 38 ++++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 208 +++++++++++++++++- 11 files changed, 311 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 4590fabdedf0..d10ed62993c1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -817,6 +817,7 @@ static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter) return IXGBE_MAX_RSS_INDICES; case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: return IXGBE_MAX_RSS_INDICES_X550; default: return 0; @@ -860,6 +861,7 @@ enum ixgbe_boards { board_X540, board_X550, board_X550EM_x, + board_x550em_a, }; extern const struct ixgbe_info ixgbe_82598_info; @@ -867,6 +869,7 @@ extern const struct ixgbe_info ixgbe_82599_info; extern const struct ixgbe_info ixgbe_X540_info; extern const struct ixgbe_info ixgbe_X550_info; extern const struct ixgbe_info ixgbe_X550EM_x_info; +extern const struct ixgbe_info ixgbe_x550em_a_info; #ifdef CONFIG_IXGBE_DCB extern const struct dcbnl_rtnl_ops dcbnl_ops; #endif diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 4bb6b685263b..01519787324a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -1633,6 +1633,7 @@ s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, switch (hw->mac.type) { case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm); break; default: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 8c560da29d23..11450bd8ec9c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -2855,6 +2855,7 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c index 02c7333a9c83..f8fb2acc2632 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2014 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -293,6 +293,7 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: return ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max, bwgid, ptype, prio_tc); default: @@ -311,6 +312,7 @@ s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: return ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc); default: break; @@ -368,6 +370,7 @@ s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id, prio_type, prio_tc); ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max, @@ -398,6 +401,7 @@ void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: ixgbe_dcb_read_rtrup2tc_82599(hw, map); break; default: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index b3530e1e3ce1..9f76be1431b1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2014 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -547,6 +547,7 @@ static void ixgbe_get_regs(struct net_device *netdev, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i)); regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i)); break; @@ -660,6 +661,7 @@ static void ixgbe_get_regs(struct net_device *netdev, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_RTTDCS); regs_buff[832] = IXGBE_READ_REG(hw, IXGBE_RTRPCS); for (i = 0; i < 8; i++) @@ -1443,6 +1445,7 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: toggle = 0x7FFFF30F; test = reg_test_82599; break; @@ -1681,6 +1684,7 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); reg_ctl &= ~IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl); @@ -1720,6 +1724,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL); reg_data |= IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data); @@ -1780,6 +1785,7 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: reg_data = IXGBE_READ_REG(hw, IXGBE_MACC); reg_data |= IXGBE_MACC_FLU; IXGBE_WRITE_REG(hw, IXGBE_MACC, reg_data); @@ -2991,6 +2997,7 @@ static int ixgbe_get_ts_info(struct net_device *dev, switch (adapter->hw.mac.type) { case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: case ixgbe_mac_X540: case ixgbe_mac_82599EB: info->so_timestamping = diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index e771e764daa3..bcdc88444ceb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -128,6 +128,7 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: if (num_tcs > 4) { /* * TCs : TC0/1 TC2/3 TC4-7 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9594438ffa07..eb93319337a1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -73,7 +73,7 @@ static char ixgbe_default_device_descr[] = #define DRV_VERSION "4.2.1-k" const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = - "Copyright (c) 1999-2015 Intel Corporation."; + "Copyright (c) 1999-2016 Intel Corporation."; static const char ixgbe_overheat_msg[] = "Network adapter has been stopped because it has over heated. Restart the computer. If the problem persists, power off the system and replace the adapter"; @@ -83,6 +83,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_X540] = &ixgbe_X540_info, [board_X550] = &ixgbe_X550_info, [board_X550EM_x] = &ixgbe_X550EM_x_info, + [board_x550em_a] = &ixgbe_x550em_a_info, }; /* ixgbe_pci_tbl - PCI Device ID Table @@ -130,6 +131,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x}, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP_N), board_x550em_a }, /* required last entry */ {0, } }; @@ -861,6 +863,7 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: if (direction == -1) { /* other causes */ msix_vector |= IXGBE_IVAR_ALLOC_VAL; @@ -899,6 +902,7 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: mask = (qmask & 0xFFFFFFFF); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask); mask = (qmask >> 32); @@ -2245,6 +2249,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: ixgbe_set_ivar(adapter, -1, 1, v_idx); break; default: @@ -2356,6 +2361,7 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: /* * set the WDIS bit to not clear the timer bits and cause an * immediate assertion of the interrupt @@ -2517,6 +2523,7 @@ static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw) return false; case ixgbe_mac_82599EB: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: switch (hw->mac.ops.get_media_type(hw)) { case ixgbe_media_type_fiber: case ixgbe_media_type_fiber_qsfp: @@ -2591,6 +2598,7 @@ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: mask = (qmask & 0xFFFFFFFF); if (mask) IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); @@ -2619,6 +2627,7 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: mask = (qmask & 0xFFFFFFFF); if (mask) IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); @@ -2654,6 +2663,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: mask |= IXGBE_EIMS_TS; break; default: @@ -2669,7 +2679,9 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: - if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_SFP) + case ixgbe_mac_x550em_a: + if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_SFP || + adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) mask |= IXGBE_EIMS_GPI_SDP0(&adapter->hw); if (adapter->hw.phy.type == ixgbe_phy_x550em_ext_t) mask |= IXGBE_EICR_GPI_SDP0_X540; @@ -2727,6 +2739,7 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: if (hw->phy.type == ixgbe_phy_x550em_ext_t && (eicr & IXGBE_EICR_GPI_SDP0_X540)) { adapter->flags2 |= IXGBE_FLAG2_PHY_INTERRUPT; @@ -2963,6 +2976,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: if (eicr & IXGBE_EICR_ECC) { e_info(link, "Received ECC Err, initiating reset\n"); adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED; @@ -3059,6 +3073,7 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); @@ -3858,6 +3873,7 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) break; case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: if (adapter->num_vfs) rdrxctl |= IXGBE_RDRXCTL_PSP; /* fall through for older HW */ @@ -4021,6 +4037,7 @@ static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *ring = adapter->rx_ring[i]; @@ -4057,6 +4074,7 @@ static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *ring = adapter->rx_ring[i]; @@ -4083,6 +4101,7 @@ static void ixgbe_vlan_promisc_enable(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: default: if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) break; @@ -4173,6 +4192,7 @@ static void ixgbe_vlan_promisc_disable(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: default: if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) break; @@ -4561,6 +4581,7 @@ static void ixgbe_clear_vxlan_port(struct ixgbe_adapter *adapter) switch (adapter->hw.mac.type) { case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: IXGBE_WRITE_REG(&adapter->hw, IXGBE_VXLANCTRL, 0); adapter->vxlan_port = 0; break; @@ -4661,6 +4682,7 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: dv_id = IXGBE_DV_X540(link, tc); break; default: @@ -4721,6 +4743,7 @@ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter, int pb) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: dv_id = IXGBE_LOW_DV_X540(tc); break; default: @@ -5137,6 +5160,7 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: default: IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); @@ -5187,6 +5211,7 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) gpie |= IXGBE_SDP1_GPIEN_8259X | IXGBE_SDP2_GPIEN_8259X; break; case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: gpie |= IXGBE_SDP0_GPIEN_X540; break; default: @@ -5498,6 +5523,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) & ~IXGBE_DMATXCTL_TE)); @@ -5616,6 +5642,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; break; case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: case ixgbe_mac_X550: #ifdef CONFIG_IXGBE_DCA adapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE; @@ -5641,6 +5668,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS; adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS; break; @@ -6248,6 +6276,7 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: pci_wake_from_d3(pdev, !!wufc); break; default: @@ -6383,6 +6412,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: hwstats->pxonrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); break; @@ -6398,7 +6428,8 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) if ((hw->mac.type == ixgbe_mac_82599EB) || (hw->mac.type == ixgbe_mac_X540) || (hw->mac.type == ixgbe_mac_X550) || - (hw->mac.type == ixgbe_mac_X550EM_x)) { + (hw->mac.type == ixgbe_mac_X550EM_x) || + (hw->mac.type == ixgbe_mac_x550em_a)) { hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); /* to clear */ hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); @@ -6423,6 +6454,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: /* OS2BMC stats are X540 and later */ hwstats->o2bgptc += IXGBE_READ_REG(hw, IXGBE_O2BGPTC); hwstats->o2bspc += IXGBE_READ_REG(hw, IXGBE_O2BSPC); @@ -6693,6 +6725,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: case ixgbe_mac_82599EB: { u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN); u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG); @@ -9146,6 +9179,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); break; default: @@ -9578,6 +9612,9 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, case ixgbe_mac_X550EM_x: device_id = IXGBE_DEV_ID_X550EM_X_VF; break; + case ixgbe_mac_x550em_a: + device_id = IXGBE_DEV_ID_X550EM_A_VF; + break; default: device_id = 0; break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c index 2837c94d6e35..b2125e358f7b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c @@ -307,6 +307,7 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); break; default: @@ -430,6 +431,7 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) if (hw->mac.type != ixgbe_mac_82599EB && hw->mac.type != ixgbe_mac_X550 && hw->mac.type != ixgbe_mac_X550EM_x && + hw->mac.type != ixgbe_mac_x550em_a && hw->mac.type != ixgbe_mac_X540) return; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index ef1504d41890..bdc8fdcc07a5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2015 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -333,6 +333,7 @@ static void ixgbe_ptp_convert_to_hwtstamp(struct ixgbe_adapter *adapter, */ case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: /* Upper 32 bits represent billions of cycles, lower 32 bits * represent cycles. However, we use timespec64_to_ns for the * correct math even though the units haven't been corrected @@ -921,6 +922,7 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter, switch (hw->mac.type) { case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: /* enable timestamping all packets only if at least some * packets were requested. Otherwise, play nice and disable * timestamping @@ -1083,6 +1085,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) cc.shift = 2; } /* fallthrough */ + case ixgbe_mac_x550em_a: case ixgbe_mac_X550: cc.read = ixgbe_ptp_read_X550; @@ -1223,6 +1226,7 @@ static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) break; case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 30000000; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index fef2264ff5f0..ced38c19436c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -2627,6 +2627,20 @@ enum ixgbe_fdir_pballoc_type { #define FW_MAX_READ_BUFFER_SIZE 1024 #define FW_DISABLE_RXEN_CMD 0xDE #define FW_DISABLE_RXEN_LEN 0x1 +#define FW_PHY_MGMT_REQ_CMD 0x20 +#define FW_PHY_TOKEN_REQ_CMD 0x0A +#define FW_PHY_TOKEN_REQ_LEN 2 +#define FW_PHY_TOKEN_REQ 0 +#define FW_PHY_TOKEN_REL 1 +#define FW_PHY_TOKEN_OK 1 +#define FW_PHY_TOKEN_RETRY 0x80 +#define FW_PHY_TOKEN_DELAY 5 /* milliseconds */ +#define FW_PHY_TOKEN_WAIT 5 /* seconds */ +#define FW_PHY_TOKEN_RETRIES ((FW_PHY_TOKEN_WAIT * 1000) / FW_PHY_TOKEN_DELAY) +#define FW_INT_PHY_REQ_CMD 0xB +#define FW_INT_PHY_REQ_LEN 10 +#define FW_INT_PHY_REQ_READ 0 +#define FW_INT_PHY_REQ_WRITE 1 /* Host Interface Command Structures */ struct ixgbe_hic_hdr { @@ -2695,6 +2709,28 @@ struct ixgbe_hic_disable_rxen { u16 pad3; }; +struct ixgbe_hic_phy_token_req { + struct ixgbe_hic_hdr hdr; + u8 port_number; + u8 command_type; + u16 pad; +}; + +struct ixgbe_hic_internal_phy_req { + struct ixgbe_hic_hdr hdr; + u8 port_number; + u8 command_type; + __be16 address; + u16 rsv1; + __be32 write_data; + u16 pad; +} __packed; + +struct ixgbe_hic_internal_phy_resp { + struct ixgbe_hic_hdr hdr; + __be32 read_data; +}; + /* Transmit Descriptor - Advanced */ union ixgbe_adv_tx_desc { struct { @@ -3528,6 +3564,8 @@ struct ixgbe_info { #define IXGBE_ERR_INVALID_ARGUMENT -32 #define IXGBE_ERR_HOST_INTERFACE_COMMAND -33 #define IXGBE_ERR_FDIR_CMD_INCOMPLETE -38 +#define IXGBE_ERR_FW_RESP_INVALID -39 +#define IXGBE_ERR_TOKEN_RETRY -40 #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF #define IXGBE_FUSES0_GROUP(_i) (0x11158 + ((_i) * 4)) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 878ea1ed87b4..ba161b5077eb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -278,6 +278,8 @@ static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; ixgbe_setup_mux_ctl(hw); ixgbe_check_cs4227(hw); + /* Fallthrough */ + case IXGBE_DEV_ID_X550EM_A_SFP_N: return ixgbe_identify_module_generic(hw); case IXGBE_DEV_ID_X550EM_X_KX4: hw->phy.type = ixgbe_phy_x550em_kx4; @@ -413,6 +415,121 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, return ret; } +/** + * ixgbe_get_phy_token - Get the token for shared PHY access + * @hw: Pointer to hardware structure + */ +static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) +{ + struct ixgbe_hic_phy_token_req token_cmd; + s32 status; + + token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; + token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; + token_cmd.hdr.cmd_or_resp.cmd_resv = 0; + token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; + token_cmd.port_number = hw->bus.lan_id; + token_cmd.command_type = FW_PHY_TOKEN_REQ; + token_cmd.pad = 0; + status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), + IXGBE_HI_COMMAND_TIMEOUT, + true); + if (status) + return status; + if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) + return 0; + if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) + return IXGBE_ERR_FW_RESP_INVALID; + + return IXGBE_ERR_TOKEN_RETRY; +} + +/** + * ixgbe_put_phy_token - Put the token for shared PHY access + * @hw: Pointer to hardware structure + */ +static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) +{ + struct ixgbe_hic_phy_token_req token_cmd; + s32 status; + + token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; + token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; + token_cmd.hdr.cmd_or_resp.cmd_resv = 0; + token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; + token_cmd.port_number = hw->bus.lan_id; + token_cmd.command_type = FW_PHY_TOKEN_REL; + token_cmd.pad = 0; + status = ixgbe_host_interface_command(hw, &token_cmd, sizeof(token_cmd), + IXGBE_HI_COMMAND_TIMEOUT, + true); + if (status) + return status; + if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) + return 0; + return IXGBE_ERR_FW_RESP_INVALID; +} + +/** + * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register + * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 3 bit device type + * @data: Data to write to the register + **/ +static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, + __always_unused u32 device_type, + u32 data) +{ + struct ixgbe_hic_internal_phy_req write_cmd; + + memset(&write_cmd, 0, sizeof(write_cmd)); + write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; + write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; + write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; + write_cmd.port_number = hw->bus.lan_id; + write_cmd.command_type = FW_INT_PHY_REQ_WRITE; + write_cmd.address = cpu_to_be16(reg_addr); + write_cmd.write_data = cpu_to_be32(data); + + return ixgbe_host_interface_command(hw, &write_cmd, sizeof(write_cmd), + IXGBE_HI_COMMAND_TIMEOUT, false); +} + +/** + * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register + * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 3 bit device type + * @data: Pointer to read data from the register + **/ +static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, + __always_unused u32 device_type, + u32 *data) +{ + union { + struct ixgbe_hic_internal_phy_req cmd; + struct ixgbe_hic_internal_phy_resp rsp; + } hic; + s32 status; + + memset(&hic, 0, sizeof(hic)); + hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; + hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; + hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; + hic.cmd.port_number = hw->bus.lan_id; + hic.cmd.command_type = FW_INT_PHY_REQ_READ; + hic.cmd.address = cpu_to_be16(reg_addr); + + status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), + IXGBE_HI_COMMAND_TIMEOUT, true); + + /* Extract the register value from the response. */ + *data = be32_to_cpu(hic.rsp.read_data); + + return status; +} + /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface * command assuming that the semaphore is already obtained. * @hw: pointer to hardware structure @@ -1339,9 +1456,9 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) mac->ops.disable_tx_laser = NULL; mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; + mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em; mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; mac->ops.setup_fc = ixgbe_setup_fc_x550em; - mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em; mac->ops.set_rate_select_speed = ixgbe_set_soft_rate_select_speed; break; @@ -1349,6 +1466,8 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; mac->ops.setup_fc = ixgbe_setup_fc_generic; mac->ops.check_link = ixgbe_check_link_t_X550em; + return; + case ixgbe_media_type_backplane: break; default: mac->ops.setup_fc = ixgbe_setup_fc_x550em; @@ -2107,11 +2226,12 @@ static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_X550EM_X_SFP: + case IXGBE_DEV_ID_X550EM_A_SFP_N: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_X550EM_X_1G_T: case IXGBE_DEV_ID_X550EM_X_10G_T: - media_type = ixgbe_media_type_copper; + media_type = ixgbe_media_type_copper; break; default: media_type = ixgbe_media_type_unknown; @@ -2375,6 +2495,59 @@ static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) ixgbe_release_swfw_sync_X540(hw, mask); } +/** + * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to acquire + * + * Acquires the SWFW semaphore and get the shared PHY token as needed + */ +static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) +{ + u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; + int retries = FW_PHY_TOKEN_RETRIES; + s32 status; + + while (--retries) { + status = 0; + if (hmask) + status = ixgbe_acquire_swfw_sync_X540(hw, hmask); + if (status) + return status; + if (!(mask & IXGBE_GSSR_TOKEN_SM)) + return 0; + + status = ixgbe_get_phy_token(hw); + if (!status) + return 0; + if (hmask) + ixgbe_release_swfw_sync_X540(hw, hmask); + if (status != IXGBE_ERR_TOKEN_RETRY) + return status; + udelay(FW_PHY_TOKEN_DELAY * 1000); + } + + return status; +} + +/** + * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to release + * + * Release the SWFW semaphore and puts the shared PHY token as needed + */ +static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) +{ + u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; + + if (mask & IXGBE_GSSR_TOKEN_SM) + ixgbe_put_phy_token(hw); + + if (hmask) + ixgbe_release_swfw_sync_X540(hw, hmask); +} + #define X550_COMMON_MAC \ .init_hw = &ixgbe_init_hw_generic, \ .start_hw = &ixgbe_start_hw_X540, \ @@ -2455,6 +2628,23 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = { .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, }; +static struct ixgbe_mac_operations mac_ops_x550em_a = { + X550_COMMON_MAC + .reset_hw = ixgbe_reset_hw_X550em, + .get_media_type = ixgbe_get_media_type_X550em, + .get_san_mac_addr = NULL, + .get_wwn_prefix = NULL, + .setup_link = NULL, /* defined later */ + .get_link_capabilities = ixgbe_get_link_capabilities_X550em, + .get_bus_info = ixgbe_get_bus_info_X550em, + .setup_sfp = ixgbe_setup_sfp_modules_X550em, + .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, + .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, + .setup_fc = ixgbe_setup_fc_generic, + .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, + .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, +}; + #define X550_COMMON_EEP \ .read = &ixgbe_read_ee_hostif_X550, \ .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ @@ -2515,6 +2705,10 @@ static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(X550EM_x) }; +static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { + IXGBE_MVALS_INIT(X550EM_a) +}; + const struct ixgbe_info ixgbe_X550_info = { .mac = ixgbe_mac_X550, .get_invariants = &ixgbe_get_invariants_X540, @@ -2534,3 +2728,13 @@ const struct ixgbe_info ixgbe_X550EM_x_info = { .mbx_ops = &mbx_ops_generic, .mvals = ixgbe_mvals_X550EM_x, }; + +const struct ixgbe_info ixgbe_x550em_a_info = { + .mac = ixgbe_mac_x550em_a, + .get_invariants = &ixgbe_get_invariants_X550_x, + .mac_ops = &mac_ops_x550em_a, + .eeprom_ops = &eeprom_ops_X550EM_x, + .phy_ops = &phy_ops_X550EM_x, + .mbx_ops = &mbx_ops_generic, + .mvals = ixgbe_mvals_x550em_a, +}; -- GitLab From d31afc8f5ca11249a3b15dafa5972fc76e4099cf Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:14 -0700 Subject: [PATCH 1776/9938] ixgbe: Use new methods for PHY access Now x550em_a devices will use a new method for PHY access that will get the firmware token for each access. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index ba161b5077eb..ef1dc3b5b4ed 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2548,6 +2548,57 @@ static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) ixgbe_release_swfw_sync_X540(hw, hmask); } +/** + * ixgbe_read_phy_reg_x550a - Reads specified PHY register + * @hw: pointer to hardware structure + * @reg_addr: 32 bit address of PHY register to read + * @phy_data: Pointer to read data from PHY register + * + * Reads a value from a specified PHY register using the SWFW lock and PHY + * Token. The PHY Token is needed since the MDIO is shared between to MAC + * instances. + */ +static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data) +{ + u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; + s32 status; + + if (hw->mac.ops.acquire_swfw_sync(hw, mask)) + return IXGBE_ERR_SWFW_SYNC; + + status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); + + hw->mac.ops.release_swfw_sync(hw, mask); + + return status; +} + +/** + * ixgbe_write_phy_reg_x550a - Writes specified PHY register + * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 5 bit device type + * @phy_data: Data to write to the PHY register + * + * Writes a value to specified PHY register using the SWFW lock and PHY Token. + * The PHY Token is needed since the MDIO is shared between to MAC instances. + */ +static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data) +{ + u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; + s32 status; + + if (hw->mac.ops.acquire_swfw_sync(hw, mask)) + return IXGBE_ERR_SWFW_SYNC; + + status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); + hw->mac.ops.release_swfw_sync(hw, mask); + + return status; +} + #define X550_COMMON_MAC \ .init_hw = &ixgbe_init_hw_generic, \ .start_hw = &ixgbe_start_hw_X540, \ @@ -2673,8 +2724,6 @@ static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ - .read_reg = &ixgbe_read_phy_reg_generic, \ - .write_reg = &ixgbe_write_phy_reg_generic, \ .setup_link = &ixgbe_setup_phy_link_generic, \ .set_phy_power = NULL, \ .check_overtemp = &ixgbe_tn_check_overtemp, \ @@ -2684,12 +2733,16 @@ static const struct ixgbe_phy_operations phy_ops_X550 = { X550_COMMON_PHY .init = NULL, .identify = &ixgbe_identify_phy_generic, + .read_reg = &ixgbe_read_phy_reg_generic, + .write_reg = &ixgbe_write_phy_reg_generic, }; static const struct ixgbe_phy_operations phy_ops_X550EM_x = { X550_COMMON_PHY .init = &ixgbe_init_phy_ops_X550em, .identify = &ixgbe_identify_phy_x550em, + .read_reg = &ixgbe_read_phy_reg_generic, + .write_reg = &ixgbe_write_phy_reg_generic, .read_i2c_combined = &ixgbe_read_i2c_combined_generic, .write_i2c_combined = &ixgbe_write_i2c_combined_generic, .read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, @@ -2697,6 +2750,14 @@ static const struct ixgbe_phy_operations phy_ops_X550EM_x = { &ixgbe_write_i2c_combined_generic_unlocked, }; +static const struct ixgbe_phy_operations phy_ops_x550em_a = { + X550_COMMON_PHY + .init = &ixgbe_init_phy_ops_X550em, + .identify = &ixgbe_identify_phy_x550em, + .read_reg = &ixgbe_read_phy_reg_x550a, + .write_reg = &ixgbe_write_phy_reg_x550a, +}; + static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(X550) }; @@ -2734,7 +2795,7 @@ const struct ixgbe_info ixgbe_x550em_a_info = { .get_invariants = &ixgbe_get_invariants_X550_x, .mac_ops = &mac_ops_x550em_a, .eeprom_ops = &eeprom_ops_X550EM_x, - .phy_ops = &phy_ops_X550EM_x, + .phy_ops = &phy_ops_x550em_a, .mbx_ops = &mbx_ops_generic, .mvals = ixgbe_mvals_x550em_a, }; -- GitLab From c898fe280457dcdf500fc1001ee73cb1adedc4d2 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:20 -0700 Subject: [PATCH 1777/9938] ixgbe: Read and set instance id Read the instance number from EEPROM and save it for later use. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 8 ++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 11450bd8ec9c..737443a015d5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -682,6 +682,7 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) { struct ixgbe_bus_info *bus = &hw->bus; + u16 ee_ctrl_4; u32 reg; reg = IXGBE_READ_REG(hw, IXGBE_STATUS); @@ -692,6 +693,13 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) reg = IXGBE_READ_REG(hw, IXGBE_FACTPS(hw)); if (reg & IXGBE_FACTPS_LFS) bus->func ^= 0x1; + + /* Get MAC instance from EEPROM for configuring CS4227 */ + if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { + hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); + bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> + IXGBE_EE_CTRL_4_INST_ID_SHIFT; + } } /** diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index ced38c19436c..a5c789e30de3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -82,6 +82,7 @@ #define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD #define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE #define IXGBE_DEV_ID_X550EM_A_SFP_N 0x15C4 +#define IXGBE_DEV_ID_X550EM_A_SFP 0x15CE /* VF Device IDs */ #define IXGBE_DEV_ID_X550_VF_HV 0x1564 @@ -2000,6 +2001,9 @@ enum { #define IXGBE_PBANUM_PTR_GUARD 0xFAFA #define IXGBE_EEPROM_CHECKSUM 0x3F #define IXGBE_EEPROM_SUM 0xBABA +#define IXGBE_EEPROM_CTRL_4 0x45 +#define IXGBE_EE_CTRL_4_INST_ID 0x10 +#define IXGBE_EE_CTRL_4_INST_ID_SHIFT 4 #define IXGBE_PCIE_ANALOG_PTR 0x03 #define IXGBE_ATLAS0_CONFIG_PTR 0x04 #define IXGBE_PHY_PTR 0x04 @@ -3175,6 +3179,7 @@ struct ixgbe_bus_info { u8 func; u8 lan_id; + u8 instance_id; }; /* Flow control parameters */ -- GitLab From 537cc5df4fcb82c0ee1f1dc4751357929a135bbc Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:25 -0700 Subject: [PATCH 1778/9938] ixgbe: Read and parse NW_MNG_IF_SEL register Read the IXGBE_NW_MNG_IF_SEL register and use it to set interface attributes. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 5 +++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 37 ++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index a5c789e30de3..6b68e8ba1dce 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3649,5 +3649,10 @@ struct ixgbe_info { #define IXGBE_SB_IOSF_TARGET_KX4_PCS1 3 #define IXGBE_NW_MNG_IF_SEL 0x00011178 +#define IXGBE_NW_MNG_IF_SEL_MDIO_ACT BIT(1) +#define IXGBE_NW_MNG_IF_SEL_ENABLE_10_100M BIT(23) #define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE BIT(24) +#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT 3 +#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD \ + (0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT) #endif /* _IXGBE_TYPE_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index ef1dc3b5b4ed..3563b862d8ea 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2137,6 +2137,36 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) return status; } +/** + * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register + * @hw: pointer to hardware structure + * + * Read NW_MNG_IF_SEL register and save field values. + */ +static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) +{ + /* Save NW management interface connected on board. This is used + * to determine internal PHY mode. + */ + hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); + + /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set + * PHY address. This register field was has only been used for X552. + */ + if (!hw->phy.nw_mng_if_sel) { + if (hw->mac.type == ixgbe_mac_x550em_a) { + struct ixgbe_adapter *adapter = hw->back; + + e_warn(drv, "nw_mng_if_sel not set\n"); + } + return; + } + + hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & + IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> + IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; +} + /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init * @hw: pointer to hardware structure * @@ -2151,14 +2181,11 @@ static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) hw->mac.ops.set_lan_id(hw); + ixgbe_read_mng_if_sel_x550em(hw); + if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; ixgbe_setup_mux_ctl(hw); - - /* Save NW management interface connected on board. This is used - * to determine internal PHY mode. - */ - phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); } /* Identify the PHY or SFP module */ -- GitLab From e84db7272798ed8abb2760a3fcd9c6d89abf99a5 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:30 -0700 Subject: [PATCH 1779/9938] ixgbe: Introduce function to control MDIO speed Move code that controls MDIO speed into a new function because there will be more MACs that need the control. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 3563b862d8ea..0d6cbb0af1a6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2306,6 +2306,26 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) return status; } +/** + * ixgbe_set_mdio_speed - Set MDIO clock speed + * @hw: pointer to hardware structure + */ +static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) +{ + u32 hlreg0; + + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_X_10G_T: + /* Config MDIO clock speed before the first MDIO PHY access */ + hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); + hlreg0 &= ~IXGBE_HLREG0_MDCSPD; + IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); + break; + default: + break; + } +} + /** ixgbe_reset_hw_X550em - Perform hardware reset ** @hw: pointer to hardware structure ** @@ -2319,7 +2339,6 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) s32 status; u32 ctrl = 0; u32 i; - u32 hlreg0; bool link_up = false; /* Call adapter stop to disable Tx/Rx and clear interrupts */ @@ -2405,11 +2424,7 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); - if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { - hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); - hlreg0 &= ~IXGBE_HLREG0_MDCSPD; - IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); - } + ixgbe_set_mdio_speed(hw); if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) ixgbe_setup_mux_ctl(hw); -- GitLab From 2d40cd1720cb6eb4406b80866c08d97b92595dfe Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:35 -0700 Subject: [PATCH 1780/9938] ixgbe: Add support for SFPs with retimer Add support for SFPs with an external retimer. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 6 +- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 5 + drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 133 +++++++++++++++++- 4 files changed, 144 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index eb93319337a1..93db4bf00dfe 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -132,6 +132,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP_N), board_x550em_a }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP), board_x550em_a }, /* required last entry */ {0, } }; @@ -2681,6 +2682,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, case ixgbe_mac_X550EM_x: case ixgbe_mac_x550em_a: if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_SFP || + adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_SFP || adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) mask |= IXGBE_EIMS_GPI_SDP0(&adapter->hw); if (adapter->hw.phy.type == ixgbe_phy_x550em_ext_t) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index 5abd66c84d00..cdf4c3800801 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2014 Intel Corporation. + Copyright(c) 1999 - 2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -81,7 +81,11 @@ #define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2 #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 #define IXGBE_CS4227 0xBE /* CS4227 address */ +#define IXGBE_CS4227_GLOBAL_ID_LSB 0 +#define IXGBE_CS4227_GLOBAL_ID_MSB 1 #define IXGBE_CS4227_SCRATCH 2 +#define IXGBE_CS4223_PHY_ID 0x7003 /* Quad port */ +#define IXGBE_CS4227_PHY_ID 0x3003 /* Dual port */ #define IXGBE_CS4227_RESET_PENDING 0x1357 #define IXGBE_CS4227_RESET_COMPLETE 0x5AA5 #define IXGBE_CS4227_RETRIES 15 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 6b68e8ba1dce..fbbc13224657 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1311,6 +1311,7 @@ struct ixgbe_thermal_sensor_data { /* MDIO definitions */ +#define IXGBE_MDIO_ZERO_DEV_TYPE 0x0 #define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 #define IXGBE_MDIO_PCS_DEV_TYPE 0x3 #define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4 @@ -3580,6 +3581,7 @@ struct ixgbe_info { #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010) #define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) #define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C) +#define IXGBE_KRM_AN_CNTL_8(P) ((P) ? 0x8248 : 0x4248) #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00) @@ -3605,6 +3607,9 @@ struct ixgbe_info { #define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE (1 << 28) #define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE (1 << 29) +#define IXGBE_KRM_AN_CNTL_8_LINEAR BIT(0) +#define IXGBE_KRM_AN_CNTL_8_LIMITING BIT(1) + #define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN (1 << 6) #define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN (1 << 15) #define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN (1 << 16) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 0d6cbb0af1a6..a9d86b37872c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -273,6 +273,12 @@ static void ixgbe_check_cs4227(struct ixgbe_hw *hw) static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) { switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_SFP: + if (hw->bus.lan_id) + hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; + else + hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; + return ixgbe_identify_module_generic(hw); case IXGBE_DEV_ID_X550EM_X_SFP: /* set up for CS4227 usage */ hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; @@ -1362,6 +1368,117 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, return status; } +/** + * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP + * @hw: pointer to hardware structure + * + * Configure the the integrated PHY for native SFP support. + */ +static s32 +ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, + __always_unused bool autoneg_wait_to_complete) +{ + bool setup_linear = false; + u32 reg_phy_int; + s32 rc; + + /* Check if SFP module is supported and linear */ + rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); + + /* If no SFP module present, then return success. Return success since + * SFP not present error is not excepted in the setup MAC link flow. + */ + if (rc == IXGBE_ERR_SFP_NOT_PRESENT) + return 0; + + if (!rc) + return rc; + + /* Configure internal PHY for native SFI */ + rc = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, + ®_phy_int); + if (rc) + return rc; + + if (setup_linear) { + reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; + reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; + } else { + reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; + reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; + } + + rc = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, + reg_phy_int); + if (rc) + return rc; + + /* Setup XFI/SFI internal link */ + return ixgbe_setup_ixfi_x550em(hw, &speed); +} + +/** + * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP + * @hw: pointer to hardware structure + * + * Configure the the integrated PHY for SFP support. + */ +static s32 +ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, + __always_unused bool autoneg_wait_to_complete) +{ + u32 reg_slice, slice_offset; + bool setup_linear = false; + u16 reg_phy_ext; + s32 rc; + + /* Check if SFP module is supported and linear */ + rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); + + /* If no SFP module present, then return success. Return success since + * SFP not present error is not excepted in the setup MAC link flow. + */ + if (rc == IXGBE_ERR_SFP_NOT_PRESENT) + return 0; + + if (!rc) + return rc; + + /* Configure internal PHY for KR/KX. */ + ixgbe_setup_kr_speed_x550em(hw, speed); + + if (!hw->phy.mdio.prtad || hw->phy.mdio.prtad == 0xFFFF) + return IXGBE_ERR_PHY_ADDR_INVALID; + + /* Get external PHY device id */ + rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, + IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); + if (rc) + return rc; + + /* When configuring quad port CS4223, the MAC instance is part + * of the slice offset. + */ + if (reg_phy_ext == IXGBE_CS4223_PHY_ID) + slice_offset = (hw->bus.lan_id + + (hw->bus.instance_id << 1)) << 12; + else + slice_offset = hw->bus.lan_id << 12; + + /* Configure CS4227/CS4223 LINE side to proper mode. */ + reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; + if (setup_linear) + reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; + else + reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; + return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE, + reg_phy_ext); +} + /** * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed * @hw: pointer to hardware structure @@ -1456,9 +1573,21 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) mac->ops.disable_tx_laser = NULL; mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; - mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em; mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; mac->ops.setup_fc = ixgbe_setup_fc_x550em; + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_SFP_N: + mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; + break; + case IXGBE_DEV_ID_X550EM_A_SFP: + mac->ops.setup_mac_link = + ixgbe_setup_mac_link_sfp_x550a; + break; + default: + mac->ops.setup_mac_link = + ixgbe_setup_mac_link_sfp_x550em; + break; + } mac->ops.set_rate_select_speed = ixgbe_set_soft_rate_select_speed; break; @@ -2253,6 +2382,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_X550EM_X_SFP: + case IXGBE_DEV_ID_X550EM_A_SFP: case IXGBE_DEV_ID_X550EM_A_SFP_N: media_type = ixgbe_media_type_fiber; break; @@ -2316,6 +2446,7 @@ static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_X550EM_X_10G_T: + case IXGBE_DEV_ID_X550EM_A_SFP: /* Config MDIO clock speed before the first MDIO PHY access */ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); hlreg0 &= ~IXGBE_HLREG0_MDCSPD; -- GitLab From 200157c2e31a5931d0d825e9fddb44d10888e6b3 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:40 -0700 Subject: [PATCH 1781/9938] ixgbe: Add support for SGMII backplane interface Add support for an SGMII backplane interface. Signed-off-by: Mark Rustad Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 9 +++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 58 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 93db4bf00dfe..c96af3fdd554 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -132,6 +132,8 @@ static const struct pci_device_id ixgbe_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP_N), board_x550em_a }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SGMII), board_x550em_a }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SGMII_L), board_x550em_a }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP), board_x550em_a }, /* required last entry */ {0, } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index fbbc13224657..50e8bc0ef4e7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -82,6 +82,8 @@ #define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD #define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE #define IXGBE_DEV_ID_X550EM_A_SFP_N 0x15C4 +#define IXGBE_DEV_ID_X550EM_A_SGMII 0x15C6 +#define IXGBE_DEV_ID_X550EM_A_SGMII_L 0x15C7 #define IXGBE_DEV_ID_X550EM_A_SFP 0x15CE /* VF Device IDs */ @@ -3065,6 +3067,7 @@ enum ixgbe_phy_type { ixgbe_phy_qsfp_intel, ixgbe_phy_qsfp_unknown, ixgbe_phy_sfp_unsupported, + ixgbe_phy_sgmii, ixgbe_phy_generic }; @@ -3582,6 +3585,7 @@ struct ixgbe_info { #define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) #define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C) #define IXGBE_KRM_AN_CNTL_8(P) ((P) ? 0x8248 : 0x4248) +#define IXGBE_KRM_SGMII_CTRL(P) ((P) ? 0x82A0 : 0x42A0) #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00) @@ -3595,6 +3599,8 @@ struct ixgbe_info { #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK (0x7 << 8) #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G (2 << 8) #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G (4 << 8) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN BIT(12) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN BIT(13) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ (1 << 14) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC (1 << 15) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX (1 << 16) @@ -3610,6 +3616,9 @@ struct ixgbe_info { #define IXGBE_KRM_AN_CNTL_8_LINEAR BIT(0) #define IXGBE_KRM_AN_CNTL_8_LIMITING BIT(1) +#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D BIT(12) +#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D BIT(19) + #define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN (1 << 6) #define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN (1 << 15) #define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN (1 << 16) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index a9d86b37872c..81e5d54476c7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1558,6 +1558,57 @@ static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, return 0; } +/** + * ixgbe_setup_sgmii - Set up link for sgmii + * @hw: pointer to hardware structure + */ +static s32 +ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, + __always_unused bool autoneg_wait_to_complete) +{ + struct ixgbe_mac_info *mac = &hw->mac; + u32 lval, sval; + s32 rc; + + rc = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); + if (rc) + return rc; + + lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; + lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; + lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; + lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; + lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; + rc = mac->ops.write_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, lval); + if (rc) + return rc; + + rc = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); + if (rc) + return rc; + + sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; + sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; + rc = mac->ops.write_iosf_sb_reg(hw, + IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, sval); + if (rc) + return rc; + + lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; + rc = mac->ops.write_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, lval); + + return rc; +} + /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers * @hw: pointer to hardware structure **/ @@ -1597,6 +1648,9 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) mac->ops.check_link = ixgbe_check_link_t_X550em; return; case ixgbe_media_type_backplane: + if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || + hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) + mac->ops.setup_link = ixgbe_setup_sgmii; break; default: mac->ops.setup_fc = ixgbe_setup_fc_x550em; @@ -2377,6 +2431,10 @@ static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) /* Detect if there is a copper PHY attached. */ switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_SGMII: + case IXGBE_DEV_ID_X550EM_A_SGMII_L: + hw->phy.type = ixgbe_phy_sgmii; + /* Fallthrough */ case IXGBE_DEV_ID_X550EM_X_KR: case IXGBE_DEV_ID_X550EM_X_KX4: media_type = ixgbe_media_type_backplane; -- GitLab From f572b2c4c86dcebe6b8684cbab03d9b2ea0d2ad6 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:46 -0700 Subject: [PATCH 1782/9938] ixgbe: Add KR backplane support for x550em_a Add support for x550em_a-based KR backplane devices. Signed-off-by: Mark Rustad Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 18 ++++++++++++++---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c96af3fdd554..1a7bfcfc030e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -131,6 +131,8 @@ static const struct pci_device_id ixgbe_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x}, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR), board_x550em_a }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR_L), board_x550em_a }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP_N), board_x550em_a }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SGMII), board_x550em_a }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SGMII_L), board_x550em_a }, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 50e8bc0ef4e7..ba3b837c7e9d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -81,6 +81,8 @@ #define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC #define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD #define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE +#define IXGBE_DEV_ID_X550EM_A_KR 0x15C2 +#define IXGBE_DEV_ID_X550EM_A_KR_L 0x15C3 #define IXGBE_DEV_ID_X550EM_A_SFP_N 0x15C4 #define IXGBE_DEV_ID_X550EM_A_SGMII 0x15C6 #define IXGBE_DEV_ID_X550EM_A_SGMII_L 0x15C7 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 81e5d54476c7..c71e93ed4451 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -291,6 +291,8 @@ static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) hw->phy.type = ixgbe_phy_x550em_kx4; break; case IXGBE_DEV_ID_X550EM_X_KR: + case IXGBE_DEV_ID_X550EM_A_KR: + case IXGBE_DEV_ID_X550EM_A_KR_L: hw->phy.type = ixgbe_phy_x550em_kr; break; case IXGBE_DEV_ID_X550EM_X_1G_T: @@ -1984,13 +1986,17 @@ static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) return status; } -/** ixgbe_setup_kr_x550em - Configure the KR PHY. - * @hw: pointer to hardware structure +/** + * ixgbe_setup_kr_x550em - Configure the KR PHY + * @hw: pointer to hardware structure * - * Configures the integrated KR PHY. + * Configures the integrated KR PHY for X550EM_x. **/ static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) { + if (hw->mac.type != ixgbe_mac_X550EM_x) + return 0; + return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); } @@ -2196,7 +2202,9 @@ static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) return IXGBE_ERR_CONFIG; } - if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR) + if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR && + hw->device_id != IXGBE_DEV_ID_X550EM_A_KR && + hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L) return 0; rc = hw->mac.ops.read_iosf_sb_reg(hw, @@ -2437,6 +2445,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) /* Fallthrough */ case IXGBE_DEV_ID_X550EM_X_KR: case IXGBE_DEV_ID_X550EM_X_KX4: + case IXGBE_DEV_ID_X550EM_A_KR: + case IXGBE_DEV_ID_X550EM_A_KR_L: media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_X550EM_X_SFP: -- GitLab From 10ef00fe539a387ded9e0d710012500896589dbb Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 1 Apr 2016 12:18:51 -0700 Subject: [PATCH 1783/9938] ixgbe: Bump version number Update ixgbe version number. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 1a7bfcfc030e..2976df77bf14 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -70,7 +70,7 @@ char ixgbe_default_device_descr[] = static char ixgbe_default_device_descr[] = "Intel(R) 10 Gigabit Network Connection"; #endif -#define DRV_VERSION "4.2.1-k" +#define DRV_VERSION "4.4.0-k" const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2016 Intel Corporation."; -- GitLab From b33b0a1bf69faff89693df49519fa7b459f5d807 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 7 Apr 2016 20:40:25 -0400 Subject: [PATCH 1784/9938] net: Fix build failure due to lockdep_sock_is_held(). Needs to be protected with CONFIG_LOCKDEP. Based upon a patch by Hannes Frederic Sowa. Signed-off-by: David S. Miller --- include/net/sock.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/sock.h b/include/net/sock.h index 46b29374df8e..81d6fecec0a2 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1360,6 +1360,7 @@ do { \ lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \ } while (0) +#ifdef CONFIG_LOCKDEP static inline bool lockdep_sock_is_held(const struct sock *csk) { struct sock *sk = (struct sock *)csk; @@ -1367,6 +1368,7 @@ static inline bool lockdep_sock_is_held(const struct sock *csk) return lockdep_is_held(&sk->sk_lock) || lockdep_is_held(&sk->sk_lock.slock); } +#endif void lock_sock_nested(struct sock *sk, int subclass); -- GitLab From ec5e099d6e941668d121ea9ca7057f4fa00830b0 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:22 -0700 Subject: [PATCH 1785/9938] perf: optimize perf_fetch_caller_regs avoid memset in perf_fetch_caller_regs, since it's the critical path of all tracepoints. It's called from perf_sw_event_sched, perf_event_task_sched_in and all of perf_trace_##call with this_cpu_ptr(&__perf_regs[..]) which are zero initialized by perpcu init logic and subsequent call to perf_arch_fetch_caller_regs initializes the same fields on all archs, so we can safely drop memset from all of the above cases and move it into perf_ftrace_function_call that calls it with stack allocated pt_regs. Acked-by: Peter Zijlstra (Intel) Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/perf_event.h | 2 -- kernel/trace/trace_event_perf.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index f291275ffd71..e89f7199c223 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -882,8 +882,6 @@ static inline void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned lo */ static inline void perf_fetch_caller_regs(struct pt_regs *regs) { - memset(regs, 0, sizeof(*regs)); - perf_arch_fetch_caller_regs(regs, CALLER_ADDR0); } diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 00df25fd86ef..7a68afca8249 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -316,6 +316,7 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, BUILD_BUG_ON(ENTRY_SIZE > PERF_MAX_TRACE_SIZE); + memset(®s, 0, sizeof(regs)); perf_fetch_caller_regs(®s); entry = perf_trace_buf_prepare(ENTRY_SIZE, TRACE_FN, NULL, &rctx); -- GitLab From e93735be6a1898dd9f8de8f55254cc76309777ce Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:23 -0700 Subject: [PATCH 1786/9938] perf: remove unused __addr variable now all calls to perf_trace_buf_submit() pass 0 as 4th argument which will be repurposed in the next patch which will change the meaning of 1st arg of perf_tp_event() to event_type Signed-off-by: Alexei Starovoitov Acked-by: Peter Zijlstra (Intel) Signed-off-by: David S. Miller --- include/trace/perf.h | 7 ++----- include/trace/trace_events.h | 3 --- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/include/trace/perf.h b/include/trace/perf.h index 26486fcd74ce..6f7e37869065 100644 --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -20,9 +20,6 @@ #undef __get_bitmask #define __get_bitmask(field) (char *)__get_dynamic_array(field) -#undef __perf_addr -#define __perf_addr(a) (__addr = (a)) - #undef __perf_count #define __perf_count(c) (__count = (c)) @@ -38,7 +35,7 @@ perf_trace_##call(void *__data, proto) \ struct trace_event_data_offsets_##call __maybe_unused __data_offsets;\ struct trace_event_raw_##call *entry; \ struct pt_regs *__regs; \ - u64 __addr = 0, __count = 1; \ + u64 __count = 1; \ struct task_struct *__task = NULL; \ struct hlist_head *head; \ int __entry_size; \ @@ -67,7 +64,7 @@ perf_trace_##call(void *__data, proto) \ \ { assign; } \ \ - perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ + perf_trace_buf_submit(entry, __entry_size, rctx, 0, \ __count, __regs, head, __task); \ } diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h index 170c93bbdbb7..80679a9fae65 100644 --- a/include/trace/trace_events.h +++ b/include/trace/trace_events.h @@ -652,9 +652,6 @@ static inline notrace int trace_event_get_offsets_##call( \ #undef TP_fast_assign #define TP_fast_assign(args...) args -#undef __perf_addr -#define __perf_addr(a) (a) - #undef __perf_count #define __perf_count(c) (c) -- GitLab From 1e1dcd93b468901e114f279c94a0b356adc5e7cd Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:24 -0700 Subject: [PATCH 1787/9938] perf: split perf_trace_buf_prepare into alloc and update parts split allows to move expensive update of 'struct trace_entry' to later phase. Repurpose unused 1st argument of perf_tp_event() to indicate event type. While splitting use temp variable 'rctx' instead of '*rctx' to avoid unnecessary loads done by the compiler due to -fno-strict-aliasing Signed-off-by: Alexei Starovoitov Acked-by: Peter Zijlstra (Intel) Signed-off-by: David S. Miller --- include/linux/perf_event.h | 2 +- include/linux/trace_events.h | 8 +++---- include/trace/perf.h | 8 +++---- kernel/events/core.c | 6 +++-- kernel/trace/trace_event_perf.c | 39 +++++++++++++++++---------------- kernel/trace/trace_kprobe.c | 10 +++++---- kernel/trace/trace_syscalls.c | 13 ++++++----- kernel/trace/trace_uprobe.c | 5 +++-- 8 files changed, 49 insertions(+), 42 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index e89f7199c223..eb41b535ef38 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1016,7 +1016,7 @@ static inline bool perf_paranoid_kernel(void) } extern void perf_event_init(void); -extern void perf_tp_event(u64 addr, u64 count, void *record, +extern void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, struct pt_regs *regs, struct hlist_head *head, int rctx, struct task_struct *task); diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 0810f81b6db2..56f795e6a093 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -605,15 +605,15 @@ extern void perf_trace_del(struct perf_event *event, int flags); extern int ftrace_profile_set_filter(struct perf_event *event, int event_id, char *filter_str); extern void ftrace_profile_free_filter(struct perf_event *event); -extern void *perf_trace_buf_prepare(int size, unsigned short type, - struct pt_regs **regs, int *rctxp); +void perf_trace_buf_update(void *record, u16 type); +void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp); static inline void -perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, +perf_trace_buf_submit(void *raw_data, int size, int rctx, u16 type, u64 count, struct pt_regs *regs, void *head, struct task_struct *task) { - perf_tp_event(addr, count, raw_data, size, regs, head, rctx, task); + perf_tp_event(type, count, raw_data, size, regs, head, rctx, task); } #endif diff --git a/include/trace/perf.h b/include/trace/perf.h index 6f7e37869065..77cd9043b7e4 100644 --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -53,8 +53,7 @@ perf_trace_##call(void *__data, proto) \ sizeof(u64)); \ __entry_size -= sizeof(u32); \ \ - entry = perf_trace_buf_prepare(__entry_size, \ - event_call->event.type, &__regs, &rctx); \ + entry = perf_trace_buf_alloc(__entry_size, &__regs, &rctx); \ if (!entry) \ return; \ \ @@ -64,8 +63,9 @@ perf_trace_##call(void *__data, proto) \ \ { assign; } \ \ - perf_trace_buf_submit(entry, __entry_size, rctx, 0, \ - __count, __regs, head, __task); \ + perf_trace_buf_submit(entry, __entry_size, rctx, \ + event_call->event.type, __count, __regs, \ + head, __task); \ } /* diff --git a/kernel/events/core.c b/kernel/events/core.c index de24fbce5277..d8512883c0a0 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6987,7 +6987,7 @@ static int perf_tp_event_match(struct perf_event *event, return 1; } -void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, +void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, struct pt_regs *regs, struct hlist_head *head, int rctx, struct task_struct *task) { @@ -6999,9 +6999,11 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, .data = record, }; - perf_sample_data_init(&data, addr, 0); + perf_sample_data_init(&data, 0, 0); data.raw = &raw; + perf_trace_buf_update(record, event_type); + hlist_for_each_entry_rcu(event, head, hlist_entry) { if (perf_tp_event_match(event, &data, regs)) perf_swevent_event(event, count, &data, regs); diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 7a68afca8249..5a927075977f 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -260,42 +260,43 @@ void perf_trace_del(struct perf_event *p_event, int flags) tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event); } -void *perf_trace_buf_prepare(int size, unsigned short type, - struct pt_regs **regs, int *rctxp) +void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp) { - struct trace_entry *entry; - unsigned long flags; char *raw_data; - int pc; + int rctx; BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(unsigned long)); if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, - "perf buffer not large enough")) + "perf buffer not large enough")) return NULL; - pc = preempt_count(); - - *rctxp = perf_swevent_get_recursion_context(); - if (*rctxp < 0) + *rctxp = rctx = perf_swevent_get_recursion_context(); + if (rctx < 0) return NULL; if (regs) - *regs = this_cpu_ptr(&__perf_regs[*rctxp]); - raw_data = this_cpu_ptr(perf_trace_buf[*rctxp]); + *regs = this_cpu_ptr(&__perf_regs[rctx]); + raw_data = this_cpu_ptr(perf_trace_buf[rctx]); /* zero the dead bytes from align to not leak stack to user */ memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64)); + return raw_data; +} +EXPORT_SYMBOL_GPL(perf_trace_buf_alloc); +NOKPROBE_SYMBOL(perf_trace_buf_alloc); + +void perf_trace_buf_update(void *record, u16 type) +{ + struct trace_entry *entry = record; + int pc = preempt_count(); + unsigned long flags; - entry = (struct trace_entry *)raw_data; local_save_flags(flags); tracing_generic_entry_update(entry, flags, pc); entry->type = type; - - return raw_data; } -EXPORT_SYMBOL_GPL(perf_trace_buf_prepare); -NOKPROBE_SYMBOL(perf_trace_buf_prepare); +NOKPROBE_SYMBOL(perf_trace_buf_update); #ifdef CONFIG_FUNCTION_TRACER static void @@ -319,13 +320,13 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, memset(®s, 0, sizeof(regs)); perf_fetch_caller_regs(®s); - entry = perf_trace_buf_prepare(ENTRY_SIZE, TRACE_FN, NULL, &rctx); + entry = perf_trace_buf_alloc(ENTRY_SIZE, NULL, &rctx); if (!entry) return; entry->ip = ip; entry->parent_ip = parent_ip; - perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, 0, + perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, TRACE_FN, 1, ®s, head, NULL); #undef ENTRY_SIZE diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 919e0ddd8fcc..5546eec0505f 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1149,14 +1149,15 @@ kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs) size = ALIGN(__size + sizeof(u32), sizeof(u64)); size -= sizeof(u32); - entry = perf_trace_buf_prepare(size, call->event.type, NULL, &rctx); + entry = perf_trace_buf_alloc(size, NULL, &rctx); if (!entry) return; entry->ip = (unsigned long)tk->rp.kp.addr; memset(&entry[1], 0, dsize); store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); - perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, + head, NULL); } NOKPROBE_SYMBOL(kprobe_perf_func); @@ -1184,14 +1185,15 @@ kretprobe_perf_func(struct trace_kprobe *tk, struct kretprobe_instance *ri, size = ALIGN(__size + sizeof(u32), sizeof(u64)); size -= sizeof(u32); - entry = perf_trace_buf_prepare(size, call->event.type, NULL, &rctx); + entry = perf_trace_buf_alloc(size, NULL, &rctx); if (!entry) return; entry->func = (unsigned long)tk->rp.kp.addr; entry->ret_ip = (unsigned long)ri->ret_addr; store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); - perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, + head, NULL); } NOKPROBE_SYMBOL(kretprobe_perf_func); #endif /* CONFIG_PERF_EVENTS */ diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index e78f364cc192..b2b6efc083a4 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -587,15 +587,16 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) size = ALIGN(size + sizeof(u32), sizeof(u64)); size -= sizeof(u32); - rec = (struct syscall_trace_enter *)perf_trace_buf_prepare(size, - sys_data->enter_event->event.type, NULL, &rctx); + rec = perf_trace_buf_alloc(size, NULL, &rctx); if (!rec) return; rec->nr = syscall_nr; syscall_get_arguments(current, regs, 0, sys_data->nb_args, (unsigned long *)&rec->args); - perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); + perf_trace_buf_submit(rec, size, rctx, + sys_data->enter_event->event.type, 1, regs, + head, NULL); } static int perf_sysenter_enable(struct trace_event_call *call) @@ -660,14 +661,14 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) size = ALIGN(sizeof(*rec) + sizeof(u32), sizeof(u64)); size -= sizeof(u32); - rec = (struct syscall_trace_exit *)perf_trace_buf_prepare(size, - sys_data->exit_event->event.type, NULL, &rctx); + rec = perf_trace_buf_alloc(size, NULL, &rctx); if (!rec) return; rec->nr = syscall_nr; rec->ret = syscall_get_return_value(current, regs); - perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); + perf_trace_buf_submit(rec, size, rctx, sys_data->exit_event->event.type, + 1, regs, head, NULL); } static int perf_sysexit_enable(struct trace_event_call *call) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 7915142c89e4..c53485441c88 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -1131,7 +1131,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu, if (hlist_empty(head)) goto out; - entry = perf_trace_buf_prepare(size, call->event.type, NULL, &rctx); + entry = perf_trace_buf_alloc(size, NULL, &rctx); if (!entry) goto out; @@ -1152,7 +1152,8 @@ static void __uprobe_perf_func(struct trace_uprobe *tu, memset(data + len, 0, size - esize - len); } - perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, + head, NULL); out: preempt_enable(); } -- GitLab From 98b5c2c65c2951772a8fc661f50d675e450e8bce Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:25 -0700 Subject: [PATCH 1788/9938] perf, bpf: allow bpf programs attach to tracepoints introduce BPF_PROG_TYPE_TRACEPOINT program type and allow it to be attached to the perf tracepoint handler, which will copy the arguments into the per-cpu buffer and pass it to the bpf program as its first argument. The layout of the fields can be discovered by doing 'cat /sys/kernel/debug/tracing/events/sched/sched_switch/format' prior to the compilation of the program with exception that first 8 bytes are reserved and not accessible to the program. This area is used to store the pointer to 'struct pt_regs' which some of the bpf helpers will use: +---------+ | 8 bytes | hidden 'struct pt_regs *' (inaccessible to bpf program) +---------+ | N bytes | static tracepoint fields defined in tracepoint/format (bpf readonly) +---------+ | dynamic | __dynamic_array bytes of tracepoint (inaccessible to bpf yet) +---------+ Not that all of the fields are already dumped to user space via perf ring buffer and broken application access it directly without consulting tracepoint/format. Same rule applies here: static tracepoint fields should only be accessed in a format defined in tracepoint/format. The order of fields and field sizes are not an ABI. Signed-off-by: Alexei Starovoitov Acked-by: Peter Zijlstra (Intel) Signed-off-by: David S. Miller --- include/trace/perf.h | 10 +++++++++- include/uapi/linux/bpf.h | 1 + kernel/events/core.c | 13 +++++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/trace/perf.h b/include/trace/perf.h index 77cd9043b7e4..a182306eefd7 100644 --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -34,6 +34,7 @@ perf_trace_##call(void *__data, proto) \ struct trace_event_call *event_call = __data; \ struct trace_event_data_offsets_##call __maybe_unused __data_offsets;\ struct trace_event_raw_##call *entry; \ + struct bpf_prog *prog = event_call->prog; \ struct pt_regs *__regs; \ u64 __count = 1; \ struct task_struct *__task = NULL; \ @@ -45,7 +46,7 @@ perf_trace_##call(void *__data, proto) \ __data_size = trace_event_get_offsets_##call(&__data_offsets, args); \ \ head = this_cpu_ptr(event_call->perf_events); \ - if (__builtin_constant_p(!__task) && !__task && \ + if (!prog && __builtin_constant_p(!__task) && !__task && \ hlist_empty(head)) \ return; \ \ @@ -63,6 +64,13 @@ perf_trace_##call(void *__data, proto) \ \ { assign; } \ \ + if (prog) { \ + *(struct pt_regs **)entry = __regs; \ + if (!trace_call_bpf(prog, entry) || hlist_empty(head)) { \ + perf_swevent_put_recursion_context(rctx); \ + return; \ + } \ + } \ perf_trace_buf_submit(entry, __entry_size, rctx, \ event_call->event.type, __count, __regs, \ head, __task); \ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 23917bb47bf3..70eda5aeb304 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -92,6 +92,7 @@ enum bpf_prog_type { BPF_PROG_TYPE_KPROBE, BPF_PROG_TYPE_SCHED_CLS, BPF_PROG_TYPE_SCHED_ACT, + BPF_PROG_TYPE_TRACEPOINT, }; #define BPF_PSEUDO_MAP_FD 1 diff --git a/kernel/events/core.c b/kernel/events/core.c index d8512883c0a0..e5ffe97d6166 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6725,12 +6725,13 @@ int perf_swevent_get_recursion_context(void) } EXPORT_SYMBOL_GPL(perf_swevent_get_recursion_context); -inline void perf_swevent_put_recursion_context(int rctx) +void perf_swevent_put_recursion_context(int rctx) { struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable); put_recursion_context(swhash->recursion, rctx); } +EXPORT_SYMBOL_GPL(perf_swevent_put_recursion_context); void ___perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr) { @@ -7106,6 +7107,7 @@ static void perf_event_free_filter(struct perf_event *event) static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) { + bool is_kprobe, is_tracepoint; struct bpf_prog *prog; if (event->attr.type != PERF_TYPE_TRACEPOINT) @@ -7114,15 +7116,18 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) if (event->tp_event->prog) return -EEXIST; - if (!(event->tp_event->flags & TRACE_EVENT_FL_UKPROBE)) - /* bpf programs can only be attached to u/kprobes */ + is_kprobe = event->tp_event->flags & TRACE_EVENT_FL_UKPROBE; + is_tracepoint = event->tp_event->flags & TRACE_EVENT_FL_TRACEPOINT; + if (!is_kprobe && !is_tracepoint) + /* bpf programs can only be attached to u/kprobe or tracepoint */ return -EINVAL; prog = bpf_prog_get(prog_fd); if (IS_ERR(prog)) return PTR_ERR(prog); - if (prog->type != BPF_PROG_TYPE_KPROBE) { + if ((is_kprobe && prog->type != BPF_PROG_TYPE_KPROBE) || + (is_tracepoint && prog->type != BPF_PROG_TYPE_TRACEPOINT)) { /* valid fd, but invalid bpf program type */ bpf_prog_put(prog); return -EINVAL; -- GitLab From 9fd82b610ba3351f05a59c3e9117cfefe82f7751 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:26 -0700 Subject: [PATCH 1789/9938] bpf: register BPF_PROG_TYPE_TRACEPOINT program type register tracepoint bpf program type and let it call the same set of helper functions as BPF_PROG_TYPE_KPROBE Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/trace/bpf_trace.c | 45 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 3e4ffb3ace5f..3e5ebe3254d2 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -268,7 +268,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = { .arg5_type = ARG_CONST_STACK_SIZE, }; -static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id) +static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id) { switch (func_id) { case BPF_FUNC_map_lookup_elem: @@ -295,12 +295,20 @@ static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func return &bpf_get_smp_processor_id_proto; case BPF_FUNC_perf_event_read: return &bpf_perf_event_read_proto; + default: + return NULL; + } +} + +static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id) +{ + switch (func_id) { case BPF_FUNC_perf_event_output: return &bpf_perf_event_output_proto; case BPF_FUNC_get_stackid: return &bpf_get_stackid_proto; default: - return NULL; + return tracing_func_proto(func_id); } } @@ -332,9 +340,42 @@ static struct bpf_prog_type_list kprobe_tl = { .type = BPF_PROG_TYPE_KPROBE, }; +static const struct bpf_func_proto *tp_prog_func_proto(enum bpf_func_id func_id) +{ + switch (func_id) { + case BPF_FUNC_perf_event_output: + case BPF_FUNC_get_stackid: + return NULL; + default: + return tracing_func_proto(func_id); + } +} + +static bool tp_prog_is_valid_access(int off, int size, enum bpf_access_type type) +{ + if (off < sizeof(void *) || off >= PERF_MAX_TRACE_SIZE) + return false; + if (type != BPF_READ) + return false; + if (off % size != 0) + return false; + return true; +} + +static const struct bpf_verifier_ops tracepoint_prog_ops = { + .get_func_proto = tp_prog_func_proto, + .is_valid_access = tp_prog_is_valid_access, +}; + +static struct bpf_prog_type_list tracepoint_tl = { + .ops = &tracepoint_prog_ops, + .type = BPF_PROG_TYPE_TRACEPOINT, +}; + static int __init register_kprobe_prog_ops(void) { bpf_register_prog_type(&kprobe_tl); + bpf_register_prog_type(&tracepoint_tl); return 0; } late_initcall(register_kprobe_prog_ops); -- GitLab From 9940d67c93b5bb7ddcf862b41b1847cb728186c4 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:27 -0700 Subject: [PATCH 1790/9938] bpf: support bpf_get_stackid() and bpf_perf_event_output() in tracepoint programs needs two wrapper functions to fetch 'struct pt_regs *' to convert tracepoint bpf context into kprobe bpf context to reuse existing helper functions Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/bpf.h | 1 + kernel/bpf/stackmap.c | 2 +- kernel/trace/bpf_trace.c | 42 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 21ee41b92e8a..198f6ace70ec 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -160,6 +160,7 @@ struct bpf_array { #define MAX_TAIL_CALL_CNT 32 u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5); +u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); void bpf_fd_array_map_clear(struct bpf_map *map); bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp); const struct bpf_func_proto *bpf_get_trace_printk_proto(void); diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 499d9e933f8e..35114725cf30 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -116,7 +116,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr) return ERR_PTR(err); } -static u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) +u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) { struct pt_regs *regs = (struct pt_regs *) (long) r1; struct bpf_map *map = (struct bpf_map *) (long) r2; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 3e5ebe3254d2..413ec5614180 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -340,12 +340,52 @@ static struct bpf_prog_type_list kprobe_tl = { .type = BPF_PROG_TYPE_KPROBE, }; +static u64 bpf_perf_event_output_tp(u64 r1, u64 r2, u64 index, u64 r4, u64 size) +{ + /* + * r1 points to perf tracepoint buffer where first 8 bytes are hidden + * from bpf program and contain a pointer to 'struct pt_regs'. Fetch it + * from there and call the same bpf_perf_event_output() helper + */ + u64 ctx = *(long *)r1; + + return bpf_perf_event_output(ctx, r2, index, r4, size); +} + +static const struct bpf_func_proto bpf_perf_event_output_proto_tp = { + .func = bpf_perf_event_output_tp, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_CONST_MAP_PTR, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_PTR_TO_STACK, + .arg5_type = ARG_CONST_STACK_SIZE, +}; + +static u64 bpf_get_stackid_tp(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) +{ + u64 ctx = *(long *)r1; + + return bpf_get_stackid(ctx, r2, r3, r4, r5); +} + +static const struct bpf_func_proto bpf_get_stackid_proto_tp = { + .func = bpf_get_stackid_tp, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_CONST_MAP_PTR, + .arg3_type = ARG_ANYTHING, +}; + static const struct bpf_func_proto *tp_prog_func_proto(enum bpf_func_id func_id) { switch (func_id) { case BPF_FUNC_perf_event_output: + return &bpf_perf_event_output_proto_tp; case BPF_FUNC_get_stackid: - return NULL; + return &bpf_get_stackid_proto_tp; default: return tracing_func_proto(func_id); } -- GitLab From 32bbe0078afe86a8bf4c67c6b3477781b15e94dc Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:28 -0700 Subject: [PATCH 1791/9938] bpf: sanitize bpf tracepoint access during bpf program loading remember the last byte of ctx access and at the time of attaching the program to tracepoint check that the program doesn't access bytes beyond defined in tracepoint fields This also disallows access to __dynamic_array fields, but can be relaxed in the future. Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/bpf.h | 1 + include/linux/trace_events.h | 1 + kernel/bpf/verifier.c | 6 +++++- kernel/events/core.c | 8 ++++++++ kernel/trace/trace_events.c | 18 ++++++++++++++++++ 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 198f6ace70ec..b2365a6eba3d 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -131,6 +131,7 @@ struct bpf_prog_type_list { struct bpf_prog_aux { atomic_t refcnt; u32 used_map_cnt; + u32 max_ctx_offset; const struct bpf_verifier_ops *ops; struct bpf_map **used_maps; struct bpf_prog *prog; diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 56f795e6a093..fe6441203b59 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -569,6 +569,7 @@ extern int trace_define_field(struct trace_event_call *call, const char *type, int is_signed, int filter_type); extern int trace_add_event_call(struct trace_event_call *call); extern int trace_remove_event_call(struct trace_event_call *call); +extern int trace_event_get_offsets(struct trace_event_call *call); #define is_signed_type(type) (((type)(-1)) < (type)1) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2e08f8e9b771..58792fed5678 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -652,8 +652,12 @@ static int check_ctx_access(struct verifier_env *env, int off, int size, enum bpf_access_type t) { if (env->prog->aux->ops->is_valid_access && - env->prog->aux->ops->is_valid_access(off, size, t)) + env->prog->aux->ops->is_valid_access(off, size, t)) { + /* remember the offset of last byte accessed in ctx */ + if (env->prog->aux->max_ctx_offset < off + size) + env->prog->aux->max_ctx_offset = off + size; return 0; + } verbose("invalid bpf_context access off=%d size=%d\n", off, size); return -EACCES; diff --git a/kernel/events/core.c b/kernel/events/core.c index e5ffe97d6166..9a01019ff7c8 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7133,6 +7133,14 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) return -EINVAL; } + if (is_tracepoint) { + int off = trace_event_get_offsets(event->tp_event); + + if (prog->aux->max_ctx_offset > off) { + bpf_prog_put(prog); + return -EACCES; + } + } event->tp_event->prog = prog; return 0; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 05ddc0820771..ced963049e0a 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -204,6 +204,24 @@ static void trace_destroy_fields(struct trace_event_call *call) } } +/* + * run-time version of trace_event_get_offsets_() that returns the last + * accessible offset of trace fields excluding __dynamic_array bytes + */ +int trace_event_get_offsets(struct trace_event_call *call) +{ + struct ftrace_event_field *tail; + struct list_head *head; + + head = trace_get_fields(call); + /* + * head->next points to the last field with the largest offset, + * since it was added last by trace_define_field() + */ + tail = list_first_entry(head, struct ftrace_event_field, link); + return tail->offset + tail->size; +} + int trace_event_raw_init(struct trace_event_call *call) { int id; -- GitLab From c07660409ec954403776200cec1dd04b2db851f8 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:29 -0700 Subject: [PATCH 1792/9938] samples/bpf: add tracepoint support to bpf loader Recognize "tracepoint/" section name prefix and attach the program to that tracepoint. Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/bpf_load.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c index 58f86bd11b3d..022af71c2bb5 100644 --- a/samples/bpf/bpf_load.c +++ b/samples/bpf/bpf_load.c @@ -49,6 +49,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) bool is_socket = strncmp(event, "socket", 6) == 0; bool is_kprobe = strncmp(event, "kprobe/", 7) == 0; bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; + bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0; enum bpf_prog_type prog_type; char buf[256]; int fd, efd, err, id; @@ -63,6 +64,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) prog_type = BPF_PROG_TYPE_SOCKET_FILTER; } else if (is_kprobe || is_kretprobe) { prog_type = BPF_PROG_TYPE_KPROBE; + } else if (is_tracepoint) { + prog_type = BPF_PROG_TYPE_TRACEPOINT; } else { printf("Unknown event '%s'\n", event); return -1; @@ -111,12 +114,23 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) event, strerror(errno)); return -1; } - } - strcpy(buf, DEBUGFS); - strcat(buf, "events/kprobes/"); - strcat(buf, event); - strcat(buf, "/id"); + strcpy(buf, DEBUGFS); + strcat(buf, "events/kprobes/"); + strcat(buf, event); + strcat(buf, "/id"); + } else if (is_tracepoint) { + event += 11; + + if (*event == 0) { + printf("event name cannot be empty\n"); + return -1; + } + strcpy(buf, DEBUGFS); + strcat(buf, "events/"); + strcat(buf, event); + strcat(buf, "/id"); + } efd = open(buf, O_RDONLY, 0); if (efd < 0) { @@ -304,6 +318,7 @@ int load_bpf_file(char *path) if (memcmp(shname_prog, "kprobe/", 7) == 0 || memcmp(shname_prog, "kretprobe/", 10) == 0 || + memcmp(shname_prog, "tracepoint/", 11) == 0 || memcmp(shname_prog, "socket", 6) == 0) load_and_attach(shname_prog, insns, data_prog->d_size); } @@ -320,6 +335,7 @@ int load_bpf_file(char *path) if (memcmp(shname, "kprobe/", 7) == 0 || memcmp(shname, "kretprobe/", 10) == 0 || + memcmp(shname, "tracepoint/", 11) == 0 || memcmp(shname, "socket", 6) == 0) load_and_attach(shname, data->d_buf, data->d_size); } -- GitLab From 3c9b16448cf6924c203e3c01696c87fcbfb71fc6 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:30 -0700 Subject: [PATCH 1793/9938] samples/bpf: tracepoint example modify offwaketime to work with sched/sched_switch tracepoint instead of kprobe into finish_task_switch Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/offwaketime_kern.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/samples/bpf/offwaketime_kern.c b/samples/bpf/offwaketime_kern.c index c0aa5a9b9c48..983629a31c79 100644 --- a/samples/bpf/offwaketime_kern.c +++ b/samples/bpf/offwaketime_kern.c @@ -73,7 +73,7 @@ int waker(struct pt_regs *ctx) return 0; } -static inline int update_counts(struct pt_regs *ctx, u32 pid, u64 delta) +static inline int update_counts(void *ctx, u32 pid, u64 delta) { struct key_t key = {}; struct wokeby_t *woke; @@ -100,15 +100,33 @@ static inline int update_counts(struct pt_regs *ctx, u32 pid, u64 delta) return 0; } +#if 1 +/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */ +struct sched_switch_args { + unsigned long long pad; + char prev_comm[16]; + int prev_pid; + int prev_prio; + long long prev_state; + char next_comm[16]; + int next_pid; + int next_prio; +}; +SEC("tracepoint/sched/sched_switch") +int oncpu(struct sched_switch_args *ctx) +{ + /* record previous thread sleep time */ + u32 pid = ctx->prev_pid; +#else SEC("kprobe/finish_task_switch") int oncpu(struct pt_regs *ctx) { struct task_struct *p = (void *) PT_REGS_PARM1(ctx); + /* record previous thread sleep time */ + u32 pid = _(p->pid); +#endif u64 delta, ts, *tsp; - u32 pid; - /* record previous thread sleep time */ - pid = _(p->pid); ts = bpf_ktime_get_ns(); bpf_map_update_elem(&start, &pid, &ts, BPF_ANY); -- GitLab From e3edfdec04d43aa6276db639d3721e073161d2c2 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 18:43:31 -0700 Subject: [PATCH 1794/9938] samples/bpf: add tracepoint vs kprobe performance tests the first microbenchmark does fd=open("/proc/self/comm"); for() { write(fd, "test"); } and on 4 cpus in parallel: writes per sec base (no tracepoints, no kprobes) 930k with kprobe at __set_task_comm() 420k with tracepoint at task:task_rename 730k For kprobe + full bpf program manully fetches oldcomm, newcomm via bpf_probe_read. For tracepint bpf program does nothing, since arguments are copied by tracepoint. 2nd microbenchmark does: fd=open("/dev/urandom"); for() { read(fd, buf); } and on 4 cpus in parallel: reads per sec base (no tracepoints, no kprobes) 300k with kprobe at urandom_read() 279k with tracepoint at random:urandom_read 290k bpf progs attached to kprobe and tracepoint are noop. Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/Makefile | 5 + samples/bpf/test_overhead_kprobe_kern.c | 41 ++++++ samples/bpf/test_overhead_tp_kern.c | 36 ++++++ samples/bpf/test_overhead_user.c | 162 ++++++++++++++++++++++++ 4 files changed, 244 insertions(+) create mode 100644 samples/bpf/test_overhead_kprobe_kern.c create mode 100644 samples/bpf/test_overhead_tp_kern.c create mode 100644 samples/bpf/test_overhead_user.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 502c9fc8db85..9959771bf808 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -19,6 +19,7 @@ hostprogs-y += lathist hostprogs-y += offwaketime hostprogs-y += spintest hostprogs-y += map_perf_test +hostprogs-y += test_overhead test_verifier-objs := test_verifier.o libbpf.o test_maps-objs := test_maps.o libbpf.o @@ -38,6 +39,7 @@ lathist-objs := bpf_load.o libbpf.o lathist_user.o offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o spintest-objs := bpf_load.o libbpf.o spintest_user.o map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o +test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o # Tell kbuild to always build the programs always := $(hostprogs-y) @@ -56,6 +58,8 @@ always += lathist_kern.o always += offwaketime_kern.o always += spintest_kern.o always += map_perf_test_kern.o +always += test_overhead_tp_kern.o +always += test_overhead_kprobe_kern.o HOSTCFLAGS += -I$(objtree)/usr/include @@ -75,6 +79,7 @@ HOSTLOADLIBES_lathist += -lelf HOSTLOADLIBES_offwaketime += -lelf HOSTLOADLIBES_spintest += -lelf HOSTLOADLIBES_map_perf_test += -lelf -lrt +HOSTLOADLIBES_test_overhead += -lelf -lrt # point this to your LLVM backend with bpf support LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc diff --git a/samples/bpf/test_overhead_kprobe_kern.c b/samples/bpf/test_overhead_kprobe_kern.c new file mode 100644 index 000000000000..468a66a92ef9 --- /dev/null +++ b/samples/bpf/test_overhead_kprobe_kern.c @@ -0,0 +1,41 @@ +/* Copyright (c) 2016 Facebook + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include +#include +#include +#include "bpf_helpers.h" + +#define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;}) + +SEC("kprobe/__set_task_comm") +int prog(struct pt_regs *ctx) +{ + struct signal_struct *signal; + struct task_struct *tsk; + char oldcomm[16] = {}; + char newcomm[16] = {}; + u16 oom_score_adj; + u32 pid; + + tsk = (void *)PT_REGS_PARM1(ctx); + + pid = _(tsk->pid); + bpf_probe_read(oldcomm, sizeof(oldcomm), &tsk->comm); + bpf_probe_read(newcomm, sizeof(newcomm), (void *)PT_REGS_PARM2(ctx)); + signal = _(tsk->signal); + oom_score_adj = _(signal->oom_score_adj); + return 0; +} + +SEC("kprobe/urandom_read") +int prog2(struct pt_regs *ctx) +{ + return 0; +} + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/test_overhead_tp_kern.c b/samples/bpf/test_overhead_tp_kern.c new file mode 100644 index 000000000000..38f5c0b9da9f --- /dev/null +++ b/samples/bpf/test_overhead_tp_kern.c @@ -0,0 +1,36 @@ +/* Copyright (c) 2016 Facebook + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include +#include "bpf_helpers.h" + +/* from /sys/kernel/debug/tracing/events/task/task_rename/format */ +struct task_rename { + __u64 pad; + __u32 pid; + char oldcomm[16]; + char newcomm[16]; + __u16 oom_score_adj; +}; +SEC("tracepoint/task/task_rename") +int prog(struct task_rename *ctx) +{ + return 0; +} + +/* from /sys/kernel/debug/tracing/events/random/urandom_read/format */ +struct urandom_read { + __u64 pad; + int got_bits; + int pool_left; + int input_left; +}; +SEC("tracepoint/random/urandom_read") +int prog2(struct urandom_read *ctx) +{ + return 0; +} +char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/test_overhead_user.c b/samples/bpf/test_overhead_user.c new file mode 100644 index 000000000000..d291167fd3c7 --- /dev/null +++ b/samples/bpf/test_overhead_user.c @@ -0,0 +1,162 @@ +/* Copyright (c) 2016 Facebook + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libbpf.h" +#include "bpf_load.h" + +#define MAX_CNT 1000000 + +static __u64 time_get_ns(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000000000ull + ts.tv_nsec; +} + +static void test_task_rename(int cpu) +{ + __u64 start_time; + char buf[] = "test\n"; + int i, fd; + + fd = open("/proc/self/comm", O_WRONLY|O_TRUNC); + if (fd < 0) { + printf("couldn't open /proc\n"); + exit(1); + } + start_time = time_get_ns(); + for (i = 0; i < MAX_CNT; i++) + write(fd, buf, sizeof(buf)); + printf("task_rename:%d: %lld events per sec\n", + cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); + close(fd); +} + +static void test_urandom_read(int cpu) +{ + __u64 start_time; + char buf[4]; + int i, fd; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) { + printf("couldn't open /dev/urandom\n"); + exit(1); + } + start_time = time_get_ns(); + for (i = 0; i < MAX_CNT; i++) + read(fd, buf, sizeof(buf)); + printf("urandom_read:%d: %lld events per sec\n", + cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); + close(fd); +} + +static void loop(int cpu, int flags) +{ + cpu_set_t cpuset; + + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + sched_setaffinity(0, sizeof(cpuset), &cpuset); + + if (flags & 1) + test_task_rename(cpu); + if (flags & 2) + test_urandom_read(cpu); +} + +static void run_perf_test(int tasks, int flags) +{ + pid_t pid[tasks]; + int i; + + for (i = 0; i < tasks; i++) { + pid[i] = fork(); + if (pid[i] == 0) { + loop(i, flags); + exit(0); + } else if (pid[i] == -1) { + printf("couldn't spawn #%d process\n", i); + exit(1); + } + } + for (i = 0; i < tasks; i++) { + int status; + + assert(waitpid(pid[i], &status, 0) == pid[i]); + assert(status == 0); + } +} + +static void unload_progs(void) +{ + close(prog_fd[0]); + close(prog_fd[1]); + close(event_fd[0]); + close(event_fd[1]); +} + +int main(int argc, char **argv) +{ + struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; + char filename[256]; + int num_cpu = 8; + int test_flags = ~0; + + setrlimit(RLIMIT_MEMLOCK, &r); + + if (argc > 1) + test_flags = atoi(argv[1]) ? : test_flags; + if (argc > 2) + num_cpu = atoi(argv[2]) ? : num_cpu; + + if (test_flags & 0x3) { + printf("BASE\n"); + run_perf_test(num_cpu, test_flags); + } + + if (test_flags & 0xC) { + snprintf(filename, sizeof(filename), + "%s_kprobe_kern.o", argv[0]); + if (load_bpf_file(filename)) { + printf("%s", bpf_log_buf); + return 1; + } + printf("w/KPROBE\n"); + run_perf_test(num_cpu, test_flags >> 2); + unload_progs(); + } + + if (test_flags & 0x30) { + snprintf(filename, sizeof(filename), + "%s_tp_kern.o", argv[0]); + if (load_bpf_file(filename)) { + printf("%s", bpf_log_buf); + return 1; + } + printf("w/TRACEPOINT\n"); + run_perf_test(num_cpu, test_flags >> 4); + unload_progs(); + } + + return 0; +} -- GitLab From e8369d65693bd4e21e043c0e66eff1056ed1e7a3 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 8 Apr 2016 12:45:25 +0900 Subject: [PATCH 1795/9938] ALSA: Fix a typo in timestamping.txt This patch fix a spelling typo found in Documentation/sound/alsa/timestamping.txt Signed-off-by: Masanari Iida Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/timestamping.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/timestamping.txt b/Documentation/sound/alsa/timestamping.txt index 0b191a23f534..1b6473f393a8 100644 --- a/Documentation/sound/alsa/timestamping.txt +++ b/Documentation/sound/alsa/timestamping.txt @@ -129,7 +129,7 @@ will be required to issue multiple queries and perform an interpolation of the results In some hardware-specific configuration, the system timestamp is -latched by a low-level audio subsytem, and the information provided +latched by a low-level audio subsystem, and the information provided back to the driver. Due to potential delays in the communication with the hardware, there is a risk of misalignment with the avail and delay information. To make sure applications are not confused, a -- GitLab From e583d70c54976f81855c7ca763b036bad399f4e0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 7 Apr 2016 09:11:12 +0200 Subject: [PATCH 1796/9938] perf tools: Add dedicated unwind addr_space member into thread struct Milian reported issue with thread::priv, which was double booked by perf trace and DWARF unwind code. So using those together is impossible at the moment. Moving DWARF unwind private data into separate variable so perf trace can keep using thread::priv. Reported-and-Tested-by: Milian Wolff Signed-off-by: Jiri Olsa Cc: Andreas Hollmann Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460013073-18444-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.h | 6 ++++++ tools/perf/util/unwind-libunwind.c | 25 +++++++++---------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index a0ac0317affb..e214207bb13a 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -9,6 +9,9 @@ #include "symbol.h" #include #include +#ifdef HAVE_LIBUNWIND_SUPPORT +#include +#endif struct thread_stack; @@ -32,6 +35,9 @@ struct thread { void *priv; struct thread_stack *ts; +#ifdef HAVE_LIBUNWIND_SUPPORT + unw_addr_space_t addr_space; +#endif }; struct machine; diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index ee7e372297e5..63687d3a344e 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -32,6 +32,7 @@ #include "symbol.h" #include "util.h" #include "debug.h" +#include "asm/bug.h" extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, @@ -580,43 +581,33 @@ static unw_accessors_t accessors = { int unwind__prepare_access(struct thread *thread) { - unw_addr_space_t addr_space; - if (callchain_param.record_mode != CALLCHAIN_DWARF) return 0; - addr_space = unw_create_addr_space(&accessors, 0); - if (!addr_space) { + thread->addr_space = unw_create_addr_space(&accessors, 0); + if (!thread->addr_space) { pr_err("unwind: Can't create unwind address space.\n"); return -ENOMEM; } - unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); - thread__set_priv(thread, addr_space); - + unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL); return 0; } void unwind__flush_access(struct thread *thread) { - unw_addr_space_t addr_space; - if (callchain_param.record_mode != CALLCHAIN_DWARF) return; - addr_space = thread__priv(thread); - unw_flush_cache(addr_space, 0, 0); + unw_flush_cache(thread->addr_space, 0, 0); } void unwind__finish_access(struct thread *thread) { - unw_addr_space_t addr_space; - if (callchain_param.record_mode != CALLCHAIN_DWARF) return; - addr_space = thread__priv(thread); - unw_destroy_addr_space(addr_space); + unw_destroy_addr_space(thread->addr_space); } static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, @@ -639,7 +630,9 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, * unwind itself. */ if (max_stack - 1 > 0) { - addr_space = thread__priv(ui->thread); + WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL"); + addr_space = ui->thread->addr_space; + if (addr_space == NULL) return -1; -- GitLab From 91daee306a51ca7b4d3ca7fdcf7472b0ed2c80c1 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 7 Apr 2016 09:11:13 +0200 Subject: [PATCH 1797/9938] perf script: Process event update events Andreas reported following command produces no output: # cat test.py #!/usr/bin/env python def stat__krava(cpu, thread, time, val, ena, run): print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \ ("krava", cpu, thread, time, val, ena, run) # perf stat -a -I 1000 -e cycles,"cpu/config=0x6530160,name=krava/" record | perf script -s test.py ^C # The reason is that 'perf script' does not process event update events and will never get the event name update thus the python callback is never called. The fix is just to add already existing callback we use in 'perf stat report'. Committer note: After the patch: # perf stat -a -I 1000 -e cycles,"cpu/config=0x6530160,name=krava/" record | perf script -s test.py event krava cpu -1, thread -1, time 1000239179, val 1789051, ena 4000690920, run 4000690920 event krava cpu -1, thread -1, time 2000479061, val 2391338, ena 4000879596, run 4000879596 event krava cpu -1, thread -1, time 3000740802, val 1939121, ena 4000977209, run 4000977209 event krava cpu -1, thread -1, time 4001006730, val 2356115, ena 4001000489, run 4001000489 ^C # Reported-by: Andreas Hollmann Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Milian Wolff Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460013073-18444-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 3770c3dffe5e..59009aa7e2ca 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1961,6 +1961,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) .exit = perf_event__process_exit, .fork = perf_event__process_fork, .attr = process_attr, + .event_update = perf_event__process_event_update, .tracing_data = perf_event__process_tracing_data, .build_id = perf_event__process_build_id, .id_index = perf_event__process_id_index, -- GitLab From ba2f22cf9989561c08225f0e88078d5562832313 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 7 Apr 2016 12:05:51 -0300 Subject: [PATCH 1798/9938] perf trace: Beautify mode_t arguments When reading the syscall tracepoint /format file, look for arguments of type "mode_t" and attach a beautifier: [root@jouet ~]# cat ~/bin/tp_with_fields_of_type #!/bin/bash grep -w $1 /sys/kernel/tracing/events/syscalls/*/format | sed -r 's%.*sys_enter_(.*)/format.*%\1%g' | paste -d, -s # tp_with_fields_of_type umode_t chmod,creat,fchmodat,fchmod,mkdirat,mkdir,mknodat,mknod,mq_open,openat,open # Testing it: #define S_ISUID 0004000 #define S_ISGID 0002000 #define S_ISVTX 0001000 #define S_IRWXU 0000700 #define S_IRUSR 0000400 #define S_IWUSR 0000200 #define S_IXUSR 0000100 #define S_IRWXG 0000070 #define S_IRGRP 0000040 #define S_IWGRP 0000020 #define S_IXGRP 0000010 #define S_IRWXO 0000007 #define S_IROTH 0000004 #define S_IWOTH 0000002 #define S_IXOTH 0000001 # for mode in 4000 2000 1000 700 400 200 100 70 40 20 10 7 4 2 1 ; do \ echo -n $mode '->' ; trace --no-inherit -e chmod,fchmodat,fchmod chmod $mode x; \ done 4000 -> 0.338 ( 0.012 ms): fchmodat(dfd: CWD, filename: x, mode: ISUID) = 0 2000 -> 0.438 ( 0.015 ms): fchmodat(dfd: CWD, filename: x, mode: ISGID) = 0 1000 -> 0.677 ( 0.040 ms): fchmodat(dfd: CWD, filename: x, mode: ISVTX) = 0 700 -> 0.394 ( 0.013 ms): fchmodat(dfd: CWD, filename: x, mode: IRWXU) = 0 400 -> 0.337 ( 0.010 ms): fchmodat(dfd: CWD, filename: x, mode: IRUSR) = 0 200 -> 0.259 ( 0.008 ms): fchmodat(dfd: CWD, filename: x, mode: IWUSR) = 0 100 -> 0.249 ( 0.008 ms): fchmodat(dfd: CWD, filename: x, mode: IXUSR) = 0 70 -> 0.266 ( 0.008 ms): fchmodat(dfd: CWD, filename: x, mode: IRWXG) = 0 40 -> 0.329 ( 0.009 ms): fchmodat(dfd: CWD, filename: x, mode: IRGRP) = 0 20 -> 0.250 ( 0.009 ms): fchmodat(dfd: CWD, filename: x, mode: IWGRP) = 0 10 -> 0.259 ( 0.008 ms): fchmodat(dfd: CWD, filename: x, mode: IXGRP) = 0 7 -> 0.249 ( 0.009 ms): fchmodat(dfd: CWD, filename: x, mode: IRWXO) = 0 4 -> 0.278 ( 0.011 ms): fchmodat(dfd: CWD, filename: x, mode: IROTH) = 0 2 -> 0.276 ( 0.009 ms): fchmodat(dfd: CWD, filename: x, mode: IWOTH) = 0 1 -> 0.250 ( 0.008 ms): fchmodat(dfd: CWD, filename: x, mode: IXOTH) = 0 # # trace --no-inherit -e chmod,fchmodat,fchmod chmod 7777 x 0.258 ( 0.011 ms): fchmodat(dfd: CWD, filename: x, mode: IALLUGO) = 0 # trace --no-inherit -e chmod,fchmodat,fchmod chmod 7770 x 0.258 ( 0.008 ms): fchmodat(dfd: CWD, filename: x, mode: ISUID|ISGID|ISVTX|IRWXU|IRWXG) = 0 # trace --no-inherit -e chmod,fchmodat,fchmod chmod 777 x 0.293 ( 0.012 ms): fchmodat(dfd: CWD, filename: x, mode: IRWXUGO # Now lets see if check by using the tracepoint for that specific syscall, instead of raw_syscalls:sys_enter as 'trace' does for its strace fu: # trace --no-inherit --ev syscalls:sys_enter_fchmodat -e fchmodat chmod 666 x 0.255 ( ): syscalls:sys_enter_fchmodat:dfd: 0xffffffffffffff9c, filename: 0x55db32a3f0f0, mode: 0x000001b6) 0.268 ( 0.012 ms): fchmodat(dfd: CWD, filename: x, mode: IRUGO|IWUGO ) = 0 # Perfect, 0x1bc == 0666. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-18e8zfgbkj83xo87yoom43kd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 ++ tools/perf/trace/beauty/mode_t.c | 68 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 tools/perf/trace/beauty/mode_t.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 57d4bb473add..8440e2b92c6c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1126,6 +1126,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, .arg_parm = { [arg] = &strarray__##array, } #include "trace/beauty/pid.c" +#include "trace/beauty/mode_t.c" #include "trace/beauty/sched_policy.c" #include "trace/beauty/waitid_options.c" @@ -1767,6 +1768,8 @@ static int syscall__set_arg_fmts(struct syscall *sc) sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; else if (strcmp(field->type, "pid_t") == 0) sc->arg_scnprintf[idx] = SCA_PID; + else if (strcmp(field->type, "umode_t") == 0) + sc->arg_scnprintf[idx] = SCA_MODE_T; ++idx; } diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c new file mode 100644 index 000000000000..930d8fef2400 --- /dev/null +++ b/tools/perf/trace/beauty/mode_t.c @@ -0,0 +1,68 @@ +#include +#include +#include + +/* From include/linux/stat.h */ +#ifndef S_IRWXUGO +#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) +#endif +#ifndef S_IALLUGO +#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) +#endif +#ifndef S_IRUGO +#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) +#endif +#ifndef S_IWUGO +#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) +#endif +#ifndef S_IXUGO +#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) +#endif + +static size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg) +{ + int printed = 0, mode = arg->val; + +#define P_MODE(n) \ + if ((mode & S_##n) == S_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + mode &= ~S_##n; \ + } + + P_MODE(IALLUGO); + P_MODE(IRWXUGO); + P_MODE(IRUGO); + P_MODE(IWUGO); + P_MODE(IXUGO); + P_MODE(IFMT); + P_MODE(IFSOCK); + P_MODE(IFLNK); + P_MODE(IFREG); + P_MODE(IFBLK); + P_MODE(IFDIR); + P_MODE(IFCHR); + P_MODE(IFIFO); + P_MODE(ISUID); + P_MODE(ISGID); + P_MODE(ISVTX); + P_MODE(IRWXU); + P_MODE(IRUSR); + P_MODE(IWUSR); + P_MODE(IXUSR); + P_MODE(IRWXG); + P_MODE(IRGRP); + P_MODE(IWGRP); + P_MODE(IXGRP); + P_MODE(IRWXO); + P_MODE(IROTH); + P_MODE(IWOTH); + P_MODE(IXOTH); +#undef P_MODE + + if (mode) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", mode); + + return printed; +} + +#define SCA_MODE_T syscall_arg__scnprintf_mode_t -- GitLab From fd0db10268b3729eb466fd726a39ce7d800bb150 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Apr 2016 13:32:20 -0300 Subject: [PATCH 1799/9938] perf trace: Move syscall table id <-> name routines to separate class We're using libaudit for doing name to id and id to syscall name translations, but that makes 'perf trace' to have to wait for newer libaudit versions supporting recently added syscalls, such as "userfaultfd" at the time of this changeset. We have all the information right there, in the kernel sources, so move this code to a separate place, wrapped behind functions that will progressively use the kernel source files to extract the syscall table for use in 'perf trace'. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-i38opd09ow25mmyrvfwnbvkj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 24 +++++++++----------- tools/perf/util/Build | 1 + tools/perf/util/syscalltbl.c | 43 ++++++++++++++++++++++++++++++++++++ tools/perf/util/syscalltbl.h | 16 ++++++++++++++ 4 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 tools/perf/util/syscalltbl.c create mode 100644 tools/perf/util/syscalltbl.h diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8440e2b92c6c..11290b57ce04 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -34,8 +34,9 @@ #include "trace-event.h" #include "util/parse-events.h" #include "util/bpf-loader.h" +#include "syscalltbl.h" -#include +#include /* FIXME: Still needed for audit_errno_to_name */ #include #include #include @@ -114,10 +115,7 @@ struct trace { struct perf_tool tool; - struct { - int machine; - int open_id; - } audit; + struct syscalltbl *sctbl; struct { int max; struct syscall *table; @@ -163,6 +161,7 @@ struct trace { bool force; bool vfs_getname; int trace_pgfaults; + int open_id; }; struct tp_field { @@ -1780,7 +1779,7 @@ static int trace__read_syscall_info(struct trace *trace, int id) { char tp_name[128]; struct syscall *sc; - const char *name = audit_syscall_to_name(id, trace->audit.machine); + const char *name = syscalltbl__name(trace->sctbl, id); if (name == NULL) return -1; @@ -1855,7 +1854,7 @@ static int trace__validate_ev_qualifier(struct trace *trace) strlist__for_each(pos, trace->ev_qualifier) { const char *sc = pos->s; - int id = audit_name_to_syscall(sc, trace->audit.machine); + int id = syscalltbl__id(trace->sctbl, sc); if (id < 0) { if (err == 0) { @@ -2137,7 +2136,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, ret = perf_evsel__sc_tp_uint(evsel, ret, sample); - if (id == trace->audit.open_id && ret >= 0 && ttrace->filename.pending_open) { + if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) { trace__set_fd_pathname(thread, ret, ttrace->filename.name); ttrace->filename.pending_open = false; ++trace->stats.vfs_getname; @@ -3189,10 +3188,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) NULL }; struct trace trace = { - .audit = { - .machine = audit_detect_machine(), - .open_id = audit_name_to_syscall("open", trace.audit.machine), - }, .syscalls = { . max = -1, }, @@ -3267,8 +3262,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) signal(SIGFPE, sighandler_dump_stack); trace.evlist = perf_evlist__new(); + trace.sctbl = syscalltbl__new(); - if (trace.evlist == NULL) { + if (trace.evlist == NULL || trace.sctbl == NULL) { pr_err("Not enough memory to run!\n"); err = -ENOMEM; goto out; @@ -3306,6 +3302,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) } } + trace.open_id = syscalltbl__id(trace.sctbl, "open"); + if (ev_qualifier_str != NULL) { const char *s = ev_qualifier_str; struct strlist_config slist_config = { diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 85ceff357769..3443646d8da3 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -38,6 +38,7 @@ libperf-y += machine.o libperf-y += map.o libperf-y += pstack.o libperf-y += session.o +libperf-$(CONFIG_AUDIT) += syscalltbl.o libperf-y += ordered-events.o libperf-y += comm.o libperf-y += thread.o diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c new file mode 100644 index 000000000000..1f13e57412eb --- /dev/null +++ b/tools/perf/util/syscalltbl.c @@ -0,0 +1,43 @@ +/* + * System call table mapper + * + * (C) 2016 Arnaldo Carvalho de Melo + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "syscalltbl.h" +#include +#include + + +struct syscalltbl *syscalltbl__new(void) +{ + struct syscalltbl *tbl = malloc(sizeof(*tbl)); + if (tbl) { + tbl->audit_machine = audit_detect_machine(); + } + return tbl; +} + +void syscalltbl__delete(struct syscalltbl *tbl) +{ + free(tbl); +} + +const char *syscalltbl__name(const struct syscalltbl *tbl, int id) +{ + return audit_syscall_to_name(id, tbl->audit_machine); +} + +int syscalltbl__id(struct syscalltbl *tbl, const char *name) +{ + return audit_name_to_syscall(name, tbl->audit_machine); +} diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h new file mode 100644 index 000000000000..9dee73c2e082 --- /dev/null +++ b/tools/perf/util/syscalltbl.h @@ -0,0 +1,16 @@ +#ifndef __PERF_SYSCALLTBL_H +#define __PERF_SYSCALLTBL_H + +struct syscalltbl { + union { + int audit_machine; + }; +}; + +struct syscalltbl *syscalltbl__new(void); +void syscalltbl__delete(struct syscalltbl *tbl); + +const char *syscalltbl__name(const struct syscalltbl *tbl, int id); +int syscalltbl__id(struct syscalltbl *tbl, const char *name); + +#endif /* __PERF_SYSCALLTBL_H */ -- GitLab From 5af56fab2b11769e35ce96613d321bcc0f7b84c1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Apr 2016 17:52:18 -0300 Subject: [PATCH 1800/9938] perf tools: Allow generating per-arch syscall table arrays Tools should use a mechanism similar to arch/x86/entry/syscalls/ to generate a header file with the definitions for two variables: static const char *syscalltbl_x86_64[] = { [0] = "read", [1] = "write", [324] = "membarrier", [325] = "mlock2", [326] = "copy_file_range", }; static const int syscalltbl_x86_64_max_id = 326; In a per arch file that should then be included in tools/perf/util/syscalltbl.c. First one will be for x86_64. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-02uuamkxgccczdth8komspgp@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/syscalltbl.c | 89 +++++++++++++++++++++++++++++++++++- tools/perf/util/syscalltbl.h | 4 ++ 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c index 1f13e57412eb..eb74a97b1f11 100644 --- a/tools/perf/util/syscalltbl.c +++ b/tools/perf/util/syscalltbl.c @@ -14,19 +14,103 @@ */ #include "syscalltbl.h" +#include + +#ifdef HAVE_SYSCALL_TABLE +#include #include -#include +#include "util.h" + +struct syscall { + int id; + const char *name; +}; +static int syscallcmpname(const void *vkey, const void *ventry) +{ + const char *key = vkey; + const struct syscall *entry = ventry; + + return strcmp(key, entry->name); +} + +static int syscallcmp(const void *va, const void *vb) +{ + const struct syscall *a = va, *b = vb; + + return strcmp(a->name, b->name); +} + +static int syscalltbl__init_native(struct syscalltbl *tbl) +{ + int nr_entries = 0, i, j; + struct syscall *entries; + + for (i = 0; i <= syscalltbl_native_max_id; ++i) + if (syscalltbl_native[i]) + ++nr_entries; + + entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries); + if (tbl->syscalls.entries == NULL) + return -1; + + for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) { + if (syscalltbl_native[i]) { + entries[j].name = syscalltbl_native[i]; + entries[j].id = i; + ++j; + } + } + + qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp); + tbl->syscalls.nr_entries = nr_entries; + return 0; +} struct syscalltbl *syscalltbl__new(void) { struct syscalltbl *tbl = malloc(sizeof(*tbl)); if (tbl) { - tbl->audit_machine = audit_detect_machine(); + if (syscalltbl__init_native(tbl)) { + free(tbl); + return NULL; + } } return tbl; } +void syscalltbl__delete(struct syscalltbl *tbl) +{ + zfree(&tbl->syscalls.entries); + free(tbl); +} + +const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id) +{ + return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL; +} + +int syscalltbl__id(struct syscalltbl *tbl, const char *name) +{ + struct syscall *sc = bsearch(name, tbl->syscalls.entries, + tbl->syscalls.nr_entries, sizeof(*sc), + syscallcmpname); + + return sc ? sc->id : -1; +} + +#else /* HAVE_SYSCALL_TABLE */ + +#include + +struct syscalltbl *syscalltbl__new(void) +{ + struct syscalltbl *tbl = malloc(sizeof(*tbl)); + if (tbl) + tbl->audit_machine = audit_detect_machine(); + return tbl; +} + void syscalltbl__delete(struct syscalltbl *tbl) { free(tbl); @@ -41,3 +125,4 @@ int syscalltbl__id(struct syscalltbl *tbl, const char *name) { return audit_name_to_syscall(name, tbl->audit_machine); } +#endif /* HAVE_SYSCALL_TABLE */ diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h index 9dee73c2e082..e2951510484f 100644 --- a/tools/perf/util/syscalltbl.h +++ b/tools/perf/util/syscalltbl.h @@ -4,6 +4,10 @@ struct syscalltbl { union { int audit_machine; + struct { + int nr_entries; + void *entries; + } syscalls; }; }; -- GitLab From 1b700c9975008615ad470cf79acc8455ce60a695 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Apr 2016 19:05:36 -0300 Subject: [PATCH 1801/9938] perf tools: Build syscall table .c header from kernel's syscall_64.tbl We used libaudit to map ids to syscall names and vice-versa, but that imposes a delay in supporting new syscalls, having to wait for libaudit to get those new syscalls on its tables. To remove that delay, for x86_64 initially, grab a copy of arch/x86/entry/syscalls/syscall_64.tbl and use it to generate those tables. Syscalls currently not available in audit-libs: # trace -e copy_file_range,membarrier,mlock2,pread64,pwrite64,timerfd_create,userfaultfd Error: Invalid syscall copy_file_range, membarrier, mlock2, pread64, pwrite64, timerfd_create, userfaultfd Hint: try 'perf list syscalls:sys_enter_*' Hint: and: 'man syscalls' # With this patch: # trace -e copy_file_range,membarrier,mlock2,pread64,pwrite64,timerfd_create,userfaultfd 8505.733 ( 0.010 ms): gnome-shell/2519 timerfd_create(flags: 524288) = 36 8506.688 ( 0.005 ms): gnome-shell/2519 timerfd_create(flags: 524288) = 40 30023.097 ( 0.025 ms): qemu-system-x8/24629 pwrite64(fd: 18, buf: 0x7f63ae382000, count: 4096, pos: 529592320) = 4096 31268.712 ( 0.028 ms): qemu-system-x8/24629 pwrite64(fd: 18, buf: 0x7f63afd8b000, count: 4096, pos: 2314133504) = 4096 31268.854 ( 0.016 ms): qemu-system-x8/24629 pwrite64(fd: 18, buf: 0x7f63afda2000, count: 4096, pos: 2314137600) = 4096 Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-51xfjbxevdsucmnbc4ka5r88@git.kernel.org [ Added make dep for 'prepare' in 'LIBPERF_IN', fix by Wang Nan to fix parallell build ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 13 +- tools/perf/arch/x86/Makefile | 23 ++ .../arch/x86/entry/syscalls/syscall_64.tbl | 374 ++++++++++++++++++ .../arch/x86/entry/syscalls/syscalltbl.sh | 39 ++ tools/perf/config/Makefile | 2 +- tools/perf/util/Build | 4 + tools/perf/util/syscalltbl.c | 6 + 7 files changed, 456 insertions(+), 5 deletions(-) create mode 100644 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl create mode 100755 tools/perf/arch/x86/entry/syscalls/syscalltbl.sh diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 58aed81a21ea..bde8cbae7dd9 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -183,6 +183,11 @@ endif include config/Makefile endif +ifeq ($(config),0) +include $(srctree)/tools/scripts/Makefile.arch +-include arch/$(ARCH)/Makefile +endif + # The FEATURE_DUMP_EXPORT holds location of the actual # FEATURE_DUMP file to be used to bypass feature detection # (for bpf or any other subproject) @@ -388,7 +393,7 @@ endif __build-dir = $(subst $(OUTPUT),,$(dir $@)) build-dir = $(if $(__build-dir),$(__build-dir),.) -prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep +prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep archheaders $(OUTPUT)%.o: %.c prepare FORCE $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ @@ -428,7 +433,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) LIBPERF_IN := $(OUTPUT)libperf-in.o -$(LIBPERF_IN): fixdep FORCE +$(LIBPERF_IN): prepare fixdep FORCE $(Q)$(MAKE) $(build)=libperf $(LIB_FILE): $(LIBPERF_IN) @@ -623,7 +628,7 @@ config-clean: $(call QUIET_CLEAN, config) $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null -clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean +clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete $(Q)$(RM) $(OUTPUT).config-detected @@ -660,5 +665,5 @@ FORCE: .PHONY: all install clean config-clean strip install-gtk .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell .PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare -.PHONY: libtraceevent_plugins +.PHONY: libtraceevent_plugins archheaders diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 269af2143735..a33729173b13 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile @@ -4,3 +4,26 @@ endif HAVE_KVM_STAT_SUPPORT := 1 PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 PERF_HAVE_JITDUMP := 1 + +### +# Syscall table generation +# + +out := $(OUTPUT)arch/x86/include/generated/asm +header := $(out)/syscalls_64.c +sys := $(srctree)/tools/perf/arch/x86/entry/syscalls +systbl := $(sys)/syscalltbl.sh + +# Create output directory if not already present +_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') + +$(header): $(sys)/syscall_64.tbl $(systbl) + @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \ + (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \ + || echo "Warning: x86_64's syscall_64.tbl differs from kernel" >&2 )) || true + $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@ + +clean:: + rm -f $(header) + +archheaders: $(header) diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl new file mode 100644 index 000000000000..2e5b565adacc --- /dev/null +++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl @@ -0,0 +1,374 @@ +# +# 64-bit system call numbers and entry vectors +# +# The format is: +# +# +# The abi is "common", "64" or "x32" for this file. +# +0 common read sys_read +1 common write sys_write +2 common open sys_open +3 common close sys_close +4 common stat sys_newstat +5 common fstat sys_newfstat +6 common lstat sys_newlstat +7 common poll sys_poll +8 common lseek sys_lseek +9 common mmap sys_mmap +10 common mprotect sys_mprotect +11 common munmap sys_munmap +12 common brk sys_brk +13 64 rt_sigaction sys_rt_sigaction +14 common rt_sigprocmask sys_rt_sigprocmask +15 64 rt_sigreturn sys_rt_sigreturn/ptregs +16 64 ioctl sys_ioctl +17 common pread64 sys_pread64 +18 common pwrite64 sys_pwrite64 +19 64 readv sys_readv +20 64 writev sys_writev +21 common access sys_access +22 common pipe sys_pipe +23 common select sys_select +24 common sched_yield sys_sched_yield +25 common mremap sys_mremap +26 common msync sys_msync +27 common mincore sys_mincore +28 common madvise sys_madvise +29 common shmget sys_shmget +30 common shmat sys_shmat +31 common shmctl sys_shmctl +32 common dup sys_dup +33 common dup2 sys_dup2 +34 common pause sys_pause +35 common nanosleep sys_nanosleep +36 common getitimer sys_getitimer +37 common alarm sys_alarm +38 common setitimer sys_setitimer +39 common getpid sys_getpid +40 common sendfile sys_sendfile64 +41 common socket sys_socket +42 common connect sys_connect +43 common accept sys_accept +44 common sendto sys_sendto +45 64 recvfrom sys_recvfrom +46 64 sendmsg sys_sendmsg +47 64 recvmsg sys_recvmsg +48 common shutdown sys_shutdown +49 common bind sys_bind +50 common listen sys_listen +51 common getsockname sys_getsockname +52 common getpeername sys_getpeername +53 common socketpair sys_socketpair +54 64 setsockopt sys_setsockopt +55 64 getsockopt sys_getsockopt +56 common clone sys_clone/ptregs +57 common fork sys_fork/ptregs +58 common vfork sys_vfork/ptregs +59 64 execve sys_execve/ptregs +60 common exit sys_exit +61 common wait4 sys_wait4 +62 common kill sys_kill +63 common uname sys_newuname +64 common semget sys_semget +65 common semop sys_semop +66 common semctl sys_semctl +67 common shmdt sys_shmdt +68 common msgget sys_msgget +69 common msgsnd sys_msgsnd +70 common msgrcv sys_msgrcv +71 common msgctl sys_msgctl +72 common fcntl sys_fcntl +73 common flock sys_flock +74 common fsync sys_fsync +75 common fdatasync sys_fdatasync +76 common truncate sys_truncate +77 common ftruncate sys_ftruncate +78 common getdents sys_getdents +79 common getcwd sys_getcwd +80 common chdir sys_chdir +81 common fchdir sys_fchdir +82 common rename sys_rename +83 common mkdir sys_mkdir +84 common rmdir sys_rmdir +85 common creat sys_creat +86 common link sys_link +87 common unlink sys_unlink +88 common symlink sys_symlink +89 common readlink sys_readlink +90 common chmod sys_chmod +91 common fchmod sys_fchmod +92 common chown sys_chown +93 common fchown sys_fchown +94 common lchown sys_lchown +95 common umask sys_umask +96 common gettimeofday sys_gettimeofday +97 common getrlimit sys_getrlimit +98 common getrusage sys_getrusage +99 common sysinfo sys_sysinfo +100 common times sys_times +101 64 ptrace sys_ptrace +102 common getuid sys_getuid +103 common syslog sys_syslog +104 common getgid sys_getgid +105 common setuid sys_setuid +106 common setgid sys_setgid +107 common geteuid sys_geteuid +108 common getegid sys_getegid +109 common setpgid sys_setpgid +110 common getppid sys_getppid +111 common getpgrp sys_getpgrp +112 common setsid sys_setsid +113 common setreuid sys_setreuid +114 common setregid sys_setregid +115 common getgroups sys_getgroups +116 common setgroups sys_setgroups +117 common setresuid sys_setresuid +118 common getresuid sys_getresuid +119 common setresgid sys_setresgid +120 common getresgid sys_getresgid +121 common getpgid sys_getpgid +122 common setfsuid sys_setfsuid +123 common setfsgid sys_setfsgid +124 common getsid sys_getsid +125 common capget sys_capget +126 common capset sys_capset +127 64 rt_sigpending sys_rt_sigpending +128 64 rt_sigtimedwait sys_rt_sigtimedwait +129 64 rt_sigqueueinfo sys_rt_sigqueueinfo +130 common rt_sigsuspend sys_rt_sigsuspend +131 64 sigaltstack sys_sigaltstack +132 common utime sys_utime +133 common mknod sys_mknod +134 64 uselib +135 common personality sys_personality +136 common ustat sys_ustat +137 common statfs sys_statfs +138 common fstatfs sys_fstatfs +139 common sysfs sys_sysfs +140 common getpriority sys_getpriority +141 common setpriority sys_setpriority +142 common sched_setparam sys_sched_setparam +143 common sched_getparam sys_sched_getparam +144 common sched_setscheduler sys_sched_setscheduler +145 common sched_getscheduler sys_sched_getscheduler +146 common sched_get_priority_max sys_sched_get_priority_max +147 common sched_get_priority_min sys_sched_get_priority_min +148 common sched_rr_get_interval sys_sched_rr_get_interval +149 common mlock sys_mlock +150 common munlock sys_munlock +151 common mlockall sys_mlockall +152 common munlockall sys_munlockall +153 common vhangup sys_vhangup +154 common modify_ldt sys_modify_ldt +155 common pivot_root sys_pivot_root +156 64 _sysctl sys_sysctl +157 common prctl sys_prctl +158 common arch_prctl sys_arch_prctl +159 common adjtimex sys_adjtimex +160 common setrlimit sys_setrlimit +161 common chroot sys_chroot +162 common sync sys_sync +163 common acct sys_acct +164 common settimeofday sys_settimeofday +165 common mount sys_mount +166 common umount2 sys_umount +167 common swapon sys_swapon +168 common swapoff sys_swapoff +169 common reboot sys_reboot +170 common sethostname sys_sethostname +171 common setdomainname sys_setdomainname +172 common iopl sys_iopl/ptregs +173 common ioperm sys_ioperm +174 64 create_module +175 common init_module sys_init_module +176 common delete_module sys_delete_module +177 64 get_kernel_syms +178 64 query_module +179 common quotactl sys_quotactl +180 64 nfsservctl +181 common getpmsg +182 common putpmsg +183 common afs_syscall +184 common tuxcall +185 common security +186 common gettid sys_gettid +187 common readahead sys_readahead +188 common setxattr sys_setxattr +189 common lsetxattr sys_lsetxattr +190 common fsetxattr sys_fsetxattr +191 common getxattr sys_getxattr +192 common lgetxattr sys_lgetxattr +193 common fgetxattr sys_fgetxattr +194 common listxattr sys_listxattr +195 common llistxattr sys_llistxattr +196 common flistxattr sys_flistxattr +197 common removexattr sys_removexattr +198 common lremovexattr sys_lremovexattr +199 common fremovexattr sys_fremovexattr +200 common tkill sys_tkill +201 common time sys_time +202 common futex sys_futex +203 common sched_setaffinity sys_sched_setaffinity +204 common sched_getaffinity sys_sched_getaffinity +205 64 set_thread_area +206 64 io_setup sys_io_setup +207 common io_destroy sys_io_destroy +208 common io_getevents sys_io_getevents +209 64 io_submit sys_io_submit +210 common io_cancel sys_io_cancel +211 64 get_thread_area +212 common lookup_dcookie sys_lookup_dcookie +213 common epoll_create sys_epoll_create +214 64 epoll_ctl_old +215 64 epoll_wait_old +216 common remap_file_pages sys_remap_file_pages +217 common getdents64 sys_getdents64 +218 common set_tid_address sys_set_tid_address +219 common restart_syscall sys_restart_syscall +220 common semtimedop sys_semtimedop +221 common fadvise64 sys_fadvise64 +222 64 timer_create sys_timer_create +223 common timer_settime sys_timer_settime +224 common timer_gettime sys_timer_gettime +225 common timer_getoverrun sys_timer_getoverrun +226 common timer_delete sys_timer_delete +227 common clock_settime sys_clock_settime +228 common clock_gettime sys_clock_gettime +229 common clock_getres sys_clock_getres +230 common clock_nanosleep sys_clock_nanosleep +231 common exit_group sys_exit_group +232 common epoll_wait sys_epoll_wait +233 common epoll_ctl sys_epoll_ctl +234 common tgkill sys_tgkill +235 common utimes sys_utimes +236 64 vserver +237 common mbind sys_mbind +238 common set_mempolicy sys_set_mempolicy +239 common get_mempolicy sys_get_mempolicy +240 common mq_open sys_mq_open +241 common mq_unlink sys_mq_unlink +242 common mq_timedsend sys_mq_timedsend +243 common mq_timedreceive sys_mq_timedreceive +244 64 mq_notify sys_mq_notify +245 common mq_getsetattr sys_mq_getsetattr +246 64 kexec_load sys_kexec_load +247 64 waitid sys_waitid +248 common add_key sys_add_key +249 common request_key sys_request_key +250 common keyctl sys_keyctl +251 common ioprio_set sys_ioprio_set +252 common ioprio_get sys_ioprio_get +253 common inotify_init sys_inotify_init +254 common inotify_add_watch sys_inotify_add_watch +255 common inotify_rm_watch sys_inotify_rm_watch +256 common migrate_pages sys_migrate_pages +257 common openat sys_openat +258 common mkdirat sys_mkdirat +259 common mknodat sys_mknodat +260 common fchownat sys_fchownat +261 common futimesat sys_futimesat +262 common newfstatat sys_newfstatat +263 common unlinkat sys_unlinkat +264 common renameat sys_renameat +265 common linkat sys_linkat +266 common symlinkat sys_symlinkat +267 common readlinkat sys_readlinkat +268 common fchmodat sys_fchmodat +269 common faccessat sys_faccessat +270 common pselect6 sys_pselect6 +271 common ppoll sys_ppoll +272 common unshare sys_unshare +273 64 set_robust_list sys_set_robust_list +274 64 get_robust_list sys_get_robust_list +275 common splice sys_splice +276 common tee sys_tee +277 common sync_file_range sys_sync_file_range +278 64 vmsplice sys_vmsplice +279 64 move_pages sys_move_pages +280 common utimensat sys_utimensat +281 common epoll_pwait sys_epoll_pwait +282 common signalfd sys_signalfd +283 common timerfd_create sys_timerfd_create +284 common eventfd sys_eventfd +285 common fallocate sys_fallocate +286 common timerfd_settime sys_timerfd_settime +287 common timerfd_gettime sys_timerfd_gettime +288 common accept4 sys_accept4 +289 common signalfd4 sys_signalfd4 +290 common eventfd2 sys_eventfd2 +291 common epoll_create1 sys_epoll_create1 +292 common dup3 sys_dup3 +293 common pipe2 sys_pipe2 +294 common inotify_init1 sys_inotify_init1 +295 64 preadv sys_preadv +296 64 pwritev sys_pwritev +297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo +298 common perf_event_open sys_perf_event_open +299 64 recvmmsg sys_recvmmsg +300 common fanotify_init sys_fanotify_init +301 common fanotify_mark sys_fanotify_mark +302 common prlimit64 sys_prlimit64 +303 common name_to_handle_at sys_name_to_handle_at +304 common open_by_handle_at sys_open_by_handle_at +305 common clock_adjtime sys_clock_adjtime +306 common syncfs sys_syncfs +307 64 sendmmsg sys_sendmmsg +308 common setns sys_setns +309 common getcpu sys_getcpu +310 64 process_vm_readv sys_process_vm_readv +311 64 process_vm_writev sys_process_vm_writev +312 common kcmp sys_kcmp +313 common finit_module sys_finit_module +314 common sched_setattr sys_sched_setattr +315 common sched_getattr sys_sched_getattr +316 common renameat2 sys_renameat2 +317 common seccomp sys_seccomp +318 common getrandom sys_getrandom +319 common memfd_create sys_memfd_create +320 common kexec_file_load sys_kexec_file_load +321 common bpf sys_bpf +322 64 execveat sys_execveat/ptregs +323 common userfaultfd sys_userfaultfd +324 common membarrier sys_membarrier +325 common mlock2 sys_mlock2 +326 common copy_file_range sys_copy_file_range + +# +# x32-specific system call numbers start at 512 to avoid cache impact +# for native 64-bit operation. +# +512 x32 rt_sigaction compat_sys_rt_sigaction +513 x32 rt_sigreturn sys32_x32_rt_sigreturn +514 x32 ioctl compat_sys_ioctl +515 x32 readv compat_sys_readv +516 x32 writev compat_sys_writev +517 x32 recvfrom compat_sys_recvfrom +518 x32 sendmsg compat_sys_sendmsg +519 x32 recvmsg compat_sys_recvmsg +520 x32 execve compat_sys_execve/ptregs +521 x32 ptrace compat_sys_ptrace +522 x32 rt_sigpending compat_sys_rt_sigpending +523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait +524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo +525 x32 sigaltstack compat_sys_sigaltstack +526 x32 timer_create compat_sys_timer_create +527 x32 mq_notify compat_sys_mq_notify +528 x32 kexec_load compat_sys_kexec_load +529 x32 waitid compat_sys_waitid +530 x32 set_robust_list compat_sys_set_robust_list +531 x32 get_robust_list compat_sys_get_robust_list +532 x32 vmsplice compat_sys_vmsplice +533 x32 move_pages compat_sys_move_pages +534 x32 preadv compat_sys_preadv64 +535 x32 pwritev compat_sys_pwritev64 +536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo +537 x32 recvmmsg compat_sys_recvmmsg +538 x32 sendmmsg compat_sys_sendmmsg +539 x32 process_vm_readv compat_sys_process_vm_readv +540 x32 process_vm_writev compat_sys_process_vm_writev +541 x32 setsockopt compat_sys_setsockopt +542 x32 getsockopt compat_sys_getsockopt +543 x32 io_setup compat_sys_io_setup +544 x32 io_submit compat_sys_io_submit +545 x32 execveat compat_sys_execveat/ptregs diff --git a/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh new file mode 100755 index 000000000000..49a18b9ad9cf --- /dev/null +++ b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +in="$1" +arch="$2" + +syscall_macro() { + nr="$1" + name="$2" + + echo " [$nr] = \"$name\"," +} + +emit() { + nr="$1" + entry="$2" + + syscall_macro "$nr" "$entry" +} + +echo "static const char *syscalltbl_${arch}[] = {" + +sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX) +grep '^[0-9]' "$in" | sort -n > $sorted_table + +max_nr=0 +while read nr abi name entry compat; do + if [ $nr -ge 512 ] ; then # discard compat sycalls + break + fi + + emit "$nr" "$name" + max_nr=$nr +done < $sorted_table + +rm -f $sorted_table + +echo "};" + +echo "#define SYSCALLTBL_${arch}_MAX_ID ${max_nr}" diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index d1e2b856ef0f..1e46277286c2 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -27,7 +27,7 @@ NO_PERF_REGS := 1 ifeq ($(ARCH),x86) $(call detected,CONFIG_X86) ifeq (${IS_64_BIT}, 1) - CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT + CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 $(call detected,CONFIG_X86_64) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 3443646d8da3..ea4ac03c1ec8 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -148,6 +148,10 @@ CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" CFLAGS_parse-events.o += -Wno-redundant-decls +$(OUTPUT)util/syscalltbl.o: util/syscalltbl.c arch/x86/entry/syscalls/syscall_64.tbl $(OUTPUT)arch/x86/include/generated/asm/syscalls_64.c FORCE + $(call rule_mkdir) + $(call if_changed_dep,cc_o_c) + $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c index eb74a97b1f11..bbb4c1957578 100644 --- a/tools/perf/util/syscalltbl.c +++ b/tools/perf/util/syscalltbl.c @@ -21,6 +21,12 @@ #include #include "util.h" +#if defined(__x86_64__) +#include +const int syscalltbl_native_max_id = SYSCALLTBL_x86_64_MAX_ID; +static const char **syscalltbl_native = syscalltbl_x86_64; +#endif + struct syscall { int id; const char *name; -- GitLab From a58f7033ba892b7d299954b94471450d72623039 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Thu, 7 Apr 2016 10:24:30 +0000 Subject: [PATCH 1802/9938] perf symbols: Record text offset in dso to calculate objdump address In this patch, the offset of '.text' section is stored into dso and used here to re-calculate address to objdump. In most of the cases, executable code is in '.text' section, so the adjustment made to a symbol in dso__load_sym (using sym.st_value -= shdr.sh_addr - shdr.sh_offset) should equal to 'sym.st_value -= dso->text_offset'. Therefore, adding text_offset back get objdump address from symbol address (rip). However, it is not true for kernel and kernel module since there could be multiple executable sections with different offset. Exclude kernel for this reason. After this patch, even dso->adjust_symbols is set to true for shared objects, map__rip_2objdump() and map__objdump_2mem() would return correct result, so perf behavior of annotate won't be changed. Signed-off-by: Wang Nan Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Cody P Schafer Cc: He Kuang Cc: Jiri Olsa Cc: Kirill Smelkov Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460024671-64774-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/map.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 171b6d10a04b..02c31865648b 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -431,6 +431,13 @@ u64 map__rip_2objdump(struct map *map, u64 rip) if (map->dso->rel) return rip - map->pgoff; + /* + * kernel modules also have DSO_TYPE_USER in dso->kernel, + * but all kernel modules are ET_REL, so won't get here. + */ + if (map->dso->kernel == DSO_TYPE_USER) + return rip + map->dso->text_offset; + return map->unmap_ip(map, rip) - map->reloc; } @@ -454,6 +461,13 @@ u64 map__objdump_2mem(struct map *map, u64 ip) if (map->dso->rel) return map->unmap_ip(map, ip + map->pgoff); + /* + * kernel modules also have DSO_TYPE_USER in dso->kernel, + * but all kernel modules are ET_REL, so won't get here. + */ + if (map->dso->kernel == DSO_TYPE_USER) + return map->unmap_ip(map, ip - map->dso->text_offset); + return ip + map->reloc; } -- GitLab From 99e87f7bb7268cf644add87130590966fd5d0d17 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Thu, 7 Apr 2016 10:24:31 +0000 Subject: [PATCH 1803/9938] perf symbols: Adjust symbol for shared objects He Kuang reported a problem that perf fails to get correct symbol on Android platform in [1]. The problem can be reproduced on normal x86_64 platform. I will describe the reproducing steps in detail at the end of commit message. The reason of this problem is the missing of symbol adjustment for normal shared objects. In most of the cases skipping adjustment is okay. However, when '.text' section have different 'address' and 'offset' the result is wrong. I checked all shared objects in my working platform, only wine dll objects and debug objects (in .debug) have this problem. However, it is common on Android. For example: $ readelf -S ./libsurfaceflinger.so | grep \.text [10] .text PROGBITS 0000000000029030 00012030 This patch enables symbol adjustment for dynamic objects so the symbol address got from elfutils would be adjusted correctly. Now nearly all types of ELF files should adjust symbols. Makes ss->adjust_symbols default to true. Steps to reproduce the problem: $ cat ./Makefile PWD := $(shell pwd) LDFLAGS += "-Wl,-rpath=$(PWD)" CFLAGS += -g main: main.c libbuggy.so libbuggy.so: buggy.c gcc -g -shared -fPIC -Wl,-Ttext-segment=0x200000 $< -o $@ clean: rm -rf main libbuggy.so *.o $ cat ./buggy.c int fib(int x) { return (x == 0) ? 1 : (x == 1) ? 1 : fib(x - 1) + fib(x - 2); } $ cat ./main.c #include extern int fib(int x); int main() { int i; for (i = 0; i < 40; i++) printf("%d\n", fib(i)); return 0; } $ make $ perf record ./main ... $ perf report --stdio # Overhead Command Shared Object Symbol # ........ ....... ................. ............................... # 14.97% main libbuggy.so [.] 0x000000000000066c 8.68% main libbuggy.so [.] 0x00000000000006aa 8.52% main libbuggy.so [.] fib@plt 7.95% main libbuggy.so [.] 0x0000000000000664 5.94% main libbuggy.so [.] 0x00000000000006a9 5.35% main libbuggy.so [.] 0x0000000000000678 ... The correct result should be (after this patch): # Overhead Command Shared Object Symbol # ........ ....... ................. ............................... # 91.47% main libbuggy.so [.] fib 8.52% main libbuggy.so [.] fib@plt 0.00% main [kernel.kallsyms] [k] kmem_cache_free [1] http://lkml.kernel.org/g/1452567507-54013-1-git-send-email-hekuang@huawei.com Signed-off-by: Wang Nan Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Cody P Schafer Cc: He Kuang Cc: Jiri Olsa Cc: Kirill Smelkov Cc: Li Zefan Cc: Masami Hiramatsu Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460024671-64774-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index bc229a74c6a9..3f9d6798bd18 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -709,17 +709,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, if (ss->opdshdr.sh_type != SHT_PROGBITS) ss->opdsec = NULL; - if (dso->kernel == DSO_TYPE_USER) { - GElf_Shdr shdr; - ss->adjust_symbols = (ehdr.e_type == ET_EXEC || - ehdr.e_type == ET_REL || - dso__is_vdso(dso) || - elf_section_by_name(elf, &ehdr, &shdr, - ".gnu.prelink_undo", - NULL) != NULL); - } else { + if (dso->kernel == DSO_TYPE_USER) + ss->adjust_symbols = true; + else ss->adjust_symbols = elf__needs_adjust_symbols(ehdr); - } ss->name = strdup(name); if (!ss->name) { -- GitLab From f57af6df6af23c086cfe023896822200eee48dd1 Mon Sep 17 00:00:00 2001 From: Chunyan Zhang Date: Mon, 28 Mar 2016 15:55:42 +0800 Subject: [PATCH 1804/9938] stm class: Fix integer boundary checks for master range Master IDs are of unsigned int type, yet in the configfs policy code we're validating user's input against INT_MAX. This is both pointless and misleading as the real limits are imposed by the stm device's [sw_start..sw_end] (which are also limited by the spec to be no larger than 2^16-1). Clean this up by getting rid of the redundant comparisons. Signed-off-by: Chunyan Zhang Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/stm/policy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/hwtracing/stm/policy.c b/drivers/hwtracing/stm/policy.c index 1db189657b2b..e8b50b1ac619 100644 --- a/drivers/hwtracing/stm/policy.c +++ b/drivers/hwtracing/stm/policy.c @@ -107,8 +107,7 @@ stp_policy_node_masters_store(struct config_item *item, const char *page, goto unlock; /* must be within [sw_start..sw_end], which is an inclusive range */ - if (first > INT_MAX || last > INT_MAX || first > last || - first < stm->data->sw_start || + if (first > last || first < stm->data->sw_start || last > stm->data->sw_end) { ret = -ERANGE; goto unlock; -- GitLab From 118b4515aa6916ee7751f29c8b2a3af95abc9783 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:22:33 +0200 Subject: [PATCH 1805/9938] stm class: dummy_stm: Make nr_dummies parameter read-only Changing nr_dummies after the module has been loaded doesn't actually change anything, so just make it read-only. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/stm/dummy_stm.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/hwtracing/stm/dummy_stm.c b/drivers/hwtracing/stm/dummy_stm.c index 310adf57e7a1..a86612d989f9 100644 --- a/drivers/hwtracing/stm/dummy_stm.c +++ b/drivers/hwtracing/stm/dummy_stm.c @@ -46,9 +46,7 @@ static struct stm_data dummy_stm[DUMMY_STM_MAX]; static int nr_dummies = 4; -module_param(nr_dummies, int, 0600); - -static unsigned int dummy_stm_nr; +module_param(nr_dummies, int, 0400); static unsigned int fail_mode; @@ -65,12 +63,12 @@ static int dummy_stm_link(struct stm_data *data, unsigned int master, static int dummy_stm_init(void) { - int i, ret = -ENOMEM, __nr_dummies = ACCESS_ONCE(nr_dummies); + int i, ret = -ENOMEM; - if (__nr_dummies < 0 || __nr_dummies > DUMMY_STM_MAX) + if (nr_dummies < 0 || nr_dummies > DUMMY_STM_MAX) return -EINVAL; - for (i = 0; i < __nr_dummies; i++) { + for (i = 0; i < nr_dummies; i++) { dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i); if (!dummy_stm[i].name) goto fail_unregister; @@ -86,8 +84,6 @@ static int dummy_stm_init(void) goto fail_free; } - dummy_stm_nr = __nr_dummies; - return 0; fail_unregister: @@ -105,7 +101,7 @@ static void dummy_stm_exit(void) { int i; - for (i = 0; i < dummy_stm_nr; i++) { + for (i = 0; i < nr_dummies; i++) { stm_unregister_device(&dummy_stm[i]); kfree(dummy_stm[i].name); } -- GitLab From c8be4899449c0b27bc5daf71742cd601b2b3b4e3 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:22:33 +0200 Subject: [PATCH 1806/9938] stm class: stm_heartbeat: Make nr_devs parameter read-only Changing nr_devs after the module has been loaded doesn't actually change anything, so just make it read-only. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/stm/heartbeat.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/hwtracing/stm/heartbeat.c b/drivers/hwtracing/stm/heartbeat.c index 0133571b506f..3da7b673aab2 100644 --- a/drivers/hwtracing/stm/heartbeat.c +++ b/drivers/hwtracing/stm/heartbeat.c @@ -26,7 +26,7 @@ static int nr_devs = 4; static int interval_ms = 10; -module_param(nr_devs, int, 0600); +module_param(nr_devs, int, 0400); module_param(interval_ms, int, 0600); static struct stm_heartbeat { @@ -35,8 +35,6 @@ static struct stm_heartbeat { unsigned int active; } stm_heartbeat[STM_HEARTBEAT_MAX]; -static unsigned int nr_instances; - static const char str[] = "heartbeat stm source driver is here to serve you"; static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr) @@ -74,12 +72,12 @@ static void stm_heartbeat_unlink(struct stm_source_data *data) static int stm_heartbeat_init(void) { - int i, ret = -ENOMEM, __nr_instances = ACCESS_ONCE(nr_devs); + int i, ret = -ENOMEM; - if (__nr_instances < 0 || __nr_instances > STM_HEARTBEAT_MAX) + if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX) return -EINVAL; - for (i = 0; i < __nr_instances; i++) { + for (i = 0; i < nr_devs; i++) { stm_heartbeat[i].data.name = kasprintf(GFP_KERNEL, "heartbeat.%d", i); if (!stm_heartbeat[i].data.name) @@ -98,8 +96,6 @@ static int stm_heartbeat_init(void) goto fail_free; } - nr_instances = __nr_instances; - return 0; fail_unregister: @@ -116,7 +112,7 @@ static void stm_heartbeat_exit(void) { int i; - for (i = 0; i < nr_instances; i++) { + for (i = 0; i < nr_devs; i++) { stm_source_unregister_device(&stm_heartbeat[i].data); kfree(stm_heartbeat[i].data.name); } -- GitLab From 8fa11d1c1322f3de40a0e3f3f3e57436a204fcc4 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:30:24 +0200 Subject: [PATCH 1807/9938] stm class: Remove a pointless line No point in explicitly setting something to zero right after we explicitly checked that it is zero. Fix this. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/stm/core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index de80d45d8df9..18f176eac06d 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -546,8 +546,6 @@ static int stm_char_policy_set_ioctl(struct stm_file *stmf, void __user *arg) if (ret) goto err_free; - ret = 0; - if (stm->data->link) ret = stm->data->link(stm->data, stmf->output.master, stmf->output.channel); -- GitLab From cbe4a61d1ddc4790d950ca8c33ef79ee68ef5e2b Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:36:10 +0200 Subject: [PATCH 1808/9938] stm class: Do not leak the chrdev in error path Currently, the error path of stm_register_device() forgets to unregister the chrdev. Fix this. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/stm/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index 18f176eac06d..e55ed6714223 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -688,6 +688,8 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data, return 0; err_device: + unregister_chrdev(stm->major, stm_data->name); + /* matches device_initialize() above */ put_device(&stm->dev); err_free: -- GitLab From 389b6699a2aa0b457aa69986e9ddf39f3b4030fd Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:48:14 +0200 Subject: [PATCH 1809/9938] stm class: Fix stm device initialization order Currently, stm_register_device() makes the device visible and then proceeds to initializing spinlocks and other properties, which leaves a window when the device can already be opened but is not yet fully operational. Fix this by reversing the initialization order. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/stm/core.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index e55ed6714223..2591442e2c5b 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -666,18 +666,11 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data, stm->dev.parent = parent; stm->dev.release = stm_device_release; - err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name); - if (err) - goto err_device; - - err = device_add(&stm->dev); - if (err) - goto err_device; - mutex_init(&stm->link_mutex); spin_lock_init(&stm->link_lock); INIT_LIST_HEAD(&stm->link_list); + /* initialize the object before it is accessible via sysfs */ spin_lock_init(&stm->mc_lock); mutex_init(&stm->policy_mutex); stm->sw_nmasters = nmasters; @@ -685,6 +678,14 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data, stm->data = stm_data; stm_data->stm = stm; + err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name); + if (err) + goto err_device; + + err = device_add(&stm->dev); + if (err) + goto err_device; + return 0; err_device: -- GitLab From fb0801904bbbc7b109d4009520c7fa34bcfb7450 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:55:12 +0200 Subject: [PATCH 1810/9938] stm class: Remove unnecessary pointer increment Readability: a postfix increment is used on a pointer which is not used anywhere afterwards, which may send the reader looking through the function one extra time. Drop the unnecessary increment. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/stm/policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwtracing/stm/policy.c b/drivers/hwtracing/stm/policy.c index e8b50b1ac619..6c0ae2996326 100644 --- a/drivers/hwtracing/stm/policy.c +++ b/drivers/hwtracing/stm/policy.c @@ -341,7 +341,7 @@ stp_policies_make(struct config_group *group, const char *name) return ERR_PTR(-EINVAL); } - *p++ = '\0'; + *p = '\0'; stm = stm_find_device(devname); kfree(devname); -- GitLab From 8f1127ea09a7bfe7e1b5fab5b7f52bd56f2d1bf5 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:10:20 +0200 Subject: [PATCH 1811/9938] intel_th: pti: Do remove sysfs group on device removal Right now, the PTI output driver forgets to clean up its sysfs group when it gets removed. Fix this. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/pti.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwtracing/intel_th/pti.c b/drivers/hwtracing/intel_th/pti.c index 57cbfdcc7ef0..2692cad4c3c5 100644 --- a/drivers/hwtracing/intel_th/pti.c +++ b/drivers/hwtracing/intel_th/pti.c @@ -230,6 +230,7 @@ static int intel_th_pti_probe(struct intel_th_device *thdev) static void intel_th_pti_remove(struct intel_th_device *thdev) { + sysfs_remove_group(&thdev->dev.kobj, &pti_output_group); } static struct intel_th_driver intel_th_pti_driver = { -- GitLab From 6575cbd67172bbcbfbb50ddd854d2b90c9f4e358 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 16:16:31 +0200 Subject: [PATCH 1812/9938] intel_th: msu: Handle kstrndup() failure Currently, the nr_pages attribute store does not check if kstrndup() succeeded. Fix this. Reported-by: Alan Cox Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/msu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index d9d6022c5aca..747ccf84bd93 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -1393,6 +1393,11 @@ nr_pages_store(struct device *dev, struct device_attribute *attr, do { end = memchr(p, ',', len); s = kstrndup(p, end ? end - p : len, GFP_KERNEL); + if (!s) { + ret = -ENOMEM; + goto free_win; + } + ret = kstrtoul(s, 10, &val); kfree(s); -- GitLab From b5edbf1ea3ad044b185be7015cffabba9c442660 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 19:42:48 +0200 Subject: [PATCH 1813/9938] intel_th: Allow subdevice drivers to bring in own attribute groups Some subdevices (MSU, PTI) need to register their own driver-specific attribute groups. Provide a way for those to pass their attribute groups to the core driver in their driver structure so that the core can take care of creating and removing them. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/core.c | 12 ++++++++++++ drivers/hwtracing/intel_th/intel_th.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 4272f2ce5f6e..db0691929a60 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -71,6 +71,15 @@ static int intel_th_probe(struct device *dev) if (ret) return ret; + if (thdrv->attr_group) { + ret = sysfs_create_group(&thdev->dev.kobj, thdrv->attr_group); + if (ret) { + thdrv->remove(thdev); + + return ret; + } + } + if (thdev->type == INTEL_TH_OUTPUT && !intel_th_output_assigned(thdev)) ret = hubdrv->assign(hub, thdev); @@ -91,6 +100,9 @@ static int intel_th_remove(struct device *dev) return err; } + if (thdrv->attr_group) + sysfs_remove_group(&thdev->dev.kobj, thdrv->attr_group); + thdrv->remove(thdev); if (intel_th_output_assigned(thdev)) { diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h index eedd09332db6..15ebd48a29f2 100644 --- a/drivers/hwtracing/intel_th/intel_th.h +++ b/drivers/hwtracing/intel_th/intel_th.h @@ -115,6 +115,7 @@ intel_th_output_assigned(struct intel_th_device *thdev) * @enable: enable tracing for a given output device * @disable: disable tracing for a given output device * @fops: file operations for device nodes + * @attr_group: attributes provided by the driver * * Callbacks @probe and @remove are required for all device types. * Switch device driver needs to fill in @assign, @enable and @disable @@ -139,6 +140,8 @@ struct intel_th_driver { void (*deactivate)(struct intel_th_device *thdev); /* file_operations for those who want a device node */ const struct file_operations *fops; + /* optional attributes */ + struct attribute_group *attr_group; /* source ops */ int (*set_output)(struct intel_th_device *thdev, -- GitLab From 9d482aedd0e2389b483ea8ea727ec201b65e2f27 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 19:55:10 +0200 Subject: [PATCH 1814/9938] intel_th: msu: Create sysfs attributes using core driver's facility The core intel_th driver allows subdevices to bring in their sysfs attributes. Use this instead of taking care of them in probe and remove. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/msu.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 747ccf84bd93..25af2146866c 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -1478,10 +1478,6 @@ static int intel_th_msc_probe(struct intel_th_device *thdev) if (err) return err; - err = sysfs_create_group(&dev->kobj, &msc_output_group); - if (err) - return err; - dev_set_drvdata(dev, msc); return 0; @@ -1489,7 +1485,6 @@ static int intel_th_msc_probe(struct intel_th_device *thdev) static void intel_th_msc_remove(struct intel_th_device *thdev) { - sysfs_remove_group(&thdev->dev.kobj, &msc_output_group); } static struct intel_th_driver intel_th_msc_driver = { @@ -1498,6 +1493,7 @@ static struct intel_th_driver intel_th_msc_driver = { .activate = intel_th_msc_activate, .deactivate = intel_th_msc_deactivate, .fops = &intel_th_msc_fops, + .attr_group = &msc_output_group, .driver = { .name = "msc", .owner = THIS_MODULE, -- GitLab From e8644e4c2aa5c52c357f63af9cc17ef5dce38396 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 4 Mar 2016 19:55:10 +0200 Subject: [PATCH 1815/9938] intel_th: pti: Create sysfs attributes using core driver's facility The core intel_th driver allows subdevices to bring in their sysfs attributes. Use this instead of taking care of them in probe and remove. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/pti.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/hwtracing/intel_th/pti.c b/drivers/hwtracing/intel_th/pti.c index 2692cad4c3c5..35738b5bfccd 100644 --- a/drivers/hwtracing/intel_th/pti.c +++ b/drivers/hwtracing/intel_th/pti.c @@ -200,7 +200,6 @@ static int intel_th_pti_probe(struct intel_th_device *thdev) struct resource *res; struct pti_device *pti; void __iomem *base; - int ret; res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0); if (!res) @@ -219,10 +218,6 @@ static int intel_th_pti_probe(struct intel_th_device *thdev) read_hw_config(pti); - ret = sysfs_create_group(&dev->kobj, &pti_output_group); - if (ret) - return ret; - dev_set_drvdata(dev, pti); return 0; @@ -230,7 +225,6 @@ static int intel_th_pti_probe(struct intel_th_device *thdev) static void intel_th_pti_remove(struct intel_th_device *thdev) { - sysfs_remove_group(&thdev->dev.kobj, &pti_output_group); } static struct intel_th_driver intel_th_pti_driver = { @@ -238,6 +232,7 @@ static struct intel_th_driver intel_th_pti_driver = { .remove = intel_th_pti_remove, .activate = intel_th_pti_activate, .deactivate = intel_th_pti_deactivate, + .attr_group = &pti_output_group, .driver = { .name = "pti", .owner = THIS_MODULE, -- GitLab From f18a9531f6da9aba2920a3a5f166dba5a20592a0 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Mon, 7 Mar 2016 17:04:45 +0200 Subject: [PATCH 1816/9938] intel_th: Fix activating a subdevice without a driver If output subdevice driver is not loaded, activating it will try to call its ->activate method and crash. Fix this by explicitly checking for the driver. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/core.c | 12 ++++++++++-- drivers/hwtracing/intel_th/intel_th.h | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index db0691929a60..20339470c2c6 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -183,7 +183,11 @@ static DEVICE_ATTR_RO(port); static int intel_th_output_activate(struct intel_th_device *thdev) { - struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver); + struct intel_th_driver *thdrv = + to_intel_th_driver_or_null(thdev->dev.driver); + + if (!thdrv) + return -ENODEV; if (thdrv->activate) return thdrv->activate(thdev); @@ -195,7 +199,11 @@ static int intel_th_output_activate(struct intel_th_device *thdev) static void intel_th_output_deactivate(struct intel_th_device *thdev) { - struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver); + struct intel_th_driver *thdrv = + to_intel_th_driver_or_null(thdev->dev.driver); + + if (!thdrv) + return; if (thdrv->deactivate) thdrv->deactivate(thdev); diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h index 15ebd48a29f2..0df22e30673d 100644 --- a/drivers/hwtracing/intel_th/intel_th.h +++ b/drivers/hwtracing/intel_th/intel_th.h @@ -151,6 +151,9 @@ struct intel_th_driver { #define to_intel_th_driver(_d) \ container_of((_d), struct intel_th_driver, driver) +#define to_intel_th_driver_or_null(_d) \ + ((_d) ? to_intel_th_driver(_d) : NULL) + static inline struct intel_th_device * to_intel_th_hub(struct intel_th_device *thdev) { -- GitLab From a45ff6ed742cdfdb3cdebee83d19ab1c00d91fcc Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Thu, 10 Mar 2016 18:21:14 +0200 Subject: [PATCH 1817/9938] intel_th: msu: Serialize enabling/disabling In order to guarantee that readers don't race with trace enabling, both should happen under the same mutex. Having two mutexes seems like an overkill, considering that because of the above, they'll have to be acquired together, around trace enabling and char device opening. This patch makes both buffer accesses and readers serialize on msc::buf_mutex and makes sure that 'enabled' flag accesses are also serialized on it. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/msu.c | 92 +++++++++++++++++--------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 25af2146866c..ee153067e136 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -122,7 +122,6 @@ struct msc { atomic_t mmap_count; struct mutex buf_mutex; - struct mutex iter_mutex; struct list_head iter_list; /* config */ @@ -257,23 +256,37 @@ static struct msc_iter *msc_iter_install(struct msc *msc) iter = kzalloc(sizeof(*iter), GFP_KERNEL); if (!iter) - return NULL; + return ERR_PTR(-ENOMEM); + + mutex_lock(&msc->buf_mutex); + + /* + * Reading and tracing are mutually exclusive; if msc is + * enabled, open() will fail; otherwise existing readers + * will prevent enabling the msc and the rest of fops don't + * need to worry about it. + */ + if (msc->enabled) { + kfree(iter); + iter = ERR_PTR(-EBUSY); + goto unlock; + } msc_iter_init(iter); iter->msc = msc; - mutex_lock(&msc->iter_mutex); list_add_tail(&iter->entry, &msc->iter_list); - mutex_unlock(&msc->iter_mutex); +unlock: + mutex_unlock(&msc->buf_mutex); return iter; } static void msc_iter_remove(struct msc_iter *iter, struct msc *msc) { - mutex_lock(&msc->iter_mutex); + mutex_lock(&msc->buf_mutex); list_del(&iter->entry); - mutex_unlock(&msc->iter_mutex); + mutex_unlock(&msc->buf_mutex); kfree(iter); } @@ -454,7 +467,6 @@ static void msc_buffer_clear_hw_header(struct msc *msc) { struct msc_window *win; - mutex_lock(&msc->buf_mutex); list_for_each_entry(win, &msc->win_list, entry) { unsigned int blk; size_t hw_sz = sizeof(struct msc_block_desc) - @@ -466,7 +478,6 @@ static void msc_buffer_clear_hw_header(struct msc *msc) memset(&bdesc->hw_tag, 0, hw_sz); } } - mutex_unlock(&msc->buf_mutex); } /** @@ -474,12 +485,15 @@ static void msc_buffer_clear_hw_header(struct msc *msc) * @msc: the MSC device to configure * * Program storage mode, wrapping, burst length and trace buffer address - * into a given MSC. If msc::enabled is set, enable the trace, too. + * into a given MSC. Then, enable tracing and set msc::enabled. + * The latter is serialized on msc::buf_mutex, so make sure to hold it. */ static int msc_configure(struct msc *msc) { u32 reg; + lockdep_assert_held(&msc->buf_mutex); + if (msc->mode > MSC_MODE_MULTI) return -ENOTSUPP; @@ -497,21 +511,19 @@ static int msc_configure(struct msc *msc) reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL); reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD); + reg |= MSC_EN; reg |= msc->mode << __ffs(MSC_MODE); reg |= msc->burst_len << __ffs(MSC_LEN); - /*if (msc->mode == MSC_MODE_MULTI) - reg |= MSC_RD_HDR_OVRD; */ + if (msc->wrap) reg |= MSC_WRAPEN; - if (msc->enabled) - reg |= MSC_EN; iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL); - if (msc->enabled) { - msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI; - intel_th_trace_enable(msc->thdev); - } + msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI; + intel_th_trace_enable(msc->thdev); + msc->enabled = 1; + return 0; } @@ -521,15 +533,14 @@ static int msc_configure(struct msc *msc) * @msc: MSC device to disable * * If @msc is enabled, disable tracing on the switch and then disable MSC - * storage. + * storage. Caller must hold msc::buf_mutex. */ static void msc_disable(struct msc *msc) { unsigned long count; u32 reg; - if (!msc->enabled) - return; + lockdep_assert_held(&msc->buf_mutex); intel_th_trace_disable(msc->thdev); @@ -569,33 +580,35 @@ static void msc_disable(struct msc *msc) static int intel_th_msc_activate(struct intel_th_device *thdev) { struct msc *msc = dev_get_drvdata(&thdev->dev); - int ret = 0; + int ret = -EBUSY; if (!atomic_inc_unless_negative(&msc->user_count)) return -ENODEV; - mutex_lock(&msc->iter_mutex); - if (!list_empty(&msc->iter_list)) - ret = -EBUSY; - mutex_unlock(&msc->iter_mutex); + mutex_lock(&msc->buf_mutex); - if (ret) { - atomic_dec(&msc->user_count); - return ret; - } + /* if there are readers, refuse */ + if (list_empty(&msc->iter_list)) + ret = msc_configure(msc); - msc->enabled = 1; + mutex_unlock(&msc->buf_mutex); + + if (ret) + atomic_dec(&msc->user_count); - return msc_configure(msc); + return ret; } static void intel_th_msc_deactivate(struct intel_th_device *thdev) { struct msc *msc = dev_get_drvdata(&thdev->dev); - msc_disable(msc); - - atomic_dec(&msc->user_count); + mutex_lock(&msc->buf_mutex); + if (msc->enabled) { + msc_disable(msc); + atomic_dec(&msc->user_count); + } + mutex_unlock(&msc->buf_mutex); } /** @@ -1035,8 +1048,8 @@ static int intel_th_msc_open(struct inode *inode, struct file *file) return -EPERM; iter = msc_iter_install(msc); - if (!iter) - return -ENOMEM; + if (IS_ERR(iter)) + return PTR_ERR(iter); file->private_data = iter; @@ -1101,11 +1114,6 @@ static ssize_t intel_th_msc_read(struct file *file, char __user *buf, if (!atomic_inc_unless_negative(&msc->user_count)) return 0; - if (msc->enabled) { - ret = -EBUSY; - goto put_count; - } - if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap) size = msc->single_sz; else @@ -1254,8 +1262,6 @@ static int intel_th_msc_init(struct msc *msc) msc->mode = MSC_MODE_MULTI; mutex_init(&msc->buf_mutex); INIT_LIST_HEAD(&msc->win_list); - - mutex_init(&msc->iter_mutex); INIT_LIST_HEAD(&msc->iter_list); msc->burst_len = -- GitLab From a5e8e825bd1704c488bf6a46936aaf3b9f203d6a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 8 Apr 2016 11:25:59 -0300 Subject: [PATCH 1818/9938] perf script: Use readdir() instead of deprecated readdir_r() The readdir() function is thread safe as long as just one thread uses a DIR, which is the case in 'perf script', so, to avoid breaking the build with glibc-2.23.90 (upcoming 2.24), use it instead of readdir_r(). See: http://man7.org/linux/man-pages/man3/readdir.3.html "However, in modern implementations (including the glibc implementation), concurrent calls to readdir() that specify different directory streams are thread-safe. In cases where multiple threads must read from the same directory stream, using readdir() with external synchronization is still preferable to the use of the deprecated readdir_r(3) function." Noticed while building on a Fedora Rawhide docker container. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-mt3xz7n2hl49ni2vx7kuq74g@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 70 ++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 59009aa7e2ca..8f6ab2ac855a 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1415,21 +1415,19 @@ static int is_directory(const char *base_path, const struct dirent *dent) return S_ISDIR(st.st_mode); } -#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\ - while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \ - lang_next) \ - if ((lang_dirent.d_type == DT_DIR || \ - (lang_dirent.d_type == DT_UNKNOWN && \ - is_directory(scripts_path, &lang_dirent))) && \ - (strcmp(lang_dirent.d_name, ".")) && \ - (strcmp(lang_dirent.d_name, ".."))) - -#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\ - while (!readdir_r(lang_dir, &script_dirent, &script_next) && \ - script_next) \ - if (script_dirent.d_type != DT_DIR && \ - (script_dirent.d_type != DT_UNKNOWN || \ - !is_directory(lang_path, &script_dirent))) +#define for_each_lang(scripts_path, scripts_dir, lang_dirent) \ + while ((lang_dirent = readdir(scripts_dir)) != NULL) \ + if ((lang_dirent->d_type == DT_DIR || \ + (lang_dirent->d_type == DT_UNKNOWN && \ + is_directory(scripts_path, lang_dirent))) && \ + (strcmp(lang_dirent->d_name, ".")) && \ + (strcmp(lang_dirent->d_name, ".."))) + +#define for_each_script(lang_path, lang_dir, script_dirent) \ + while ((script_dirent = readdir(lang_dir)) != NULL) \ + if (script_dirent->d_type != DT_DIR && \ + (script_dirent->d_type != DT_UNKNOWN || \ + !is_directory(lang_path, script_dirent))) #define RECORD_SUFFIX "-record" @@ -1575,7 +1573,7 @@ static int list_available_scripts(const struct option *opt __maybe_unused, const char *s __maybe_unused, int unset __maybe_unused) { - struct dirent *script_next, *lang_next, script_dirent, lang_dirent; + struct dirent *script_dirent, *lang_dirent; char scripts_path[MAXPATHLEN]; DIR *scripts_dir, *lang_dir; char script_path[MAXPATHLEN]; @@ -1590,19 +1588,19 @@ static int list_available_scripts(const struct option *opt __maybe_unused, if (!scripts_dir) return -1; - for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { + for_each_lang(scripts_path, scripts_dir, lang_dirent) { snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, - lang_dirent.d_name); + lang_dirent->d_name); lang_dir = opendir(lang_path); if (!lang_dir) continue; - for_each_script(lang_path, lang_dir, script_dirent, script_next) { - script_root = get_script_root(&script_dirent, REPORT_SUFFIX); + for_each_script(lang_path, lang_dir, script_dirent) { + script_root = get_script_root(script_dirent, REPORT_SUFFIX); if (script_root) { desc = script_desc__findnew(script_root); snprintf(script_path, MAXPATHLEN, "%s/%s", - lang_path, script_dirent.d_name); + lang_path, script_dirent->d_name); read_script_info(desc, script_path); free(script_root); } @@ -1690,7 +1688,7 @@ static int check_ev_match(char *dir_name, char *scriptname, */ int find_scripts(char **scripts_array, char **scripts_path_array) { - struct dirent *script_next, *lang_next, script_dirent, lang_dirent; + struct dirent *script_dirent, *lang_dirent; char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; DIR *scripts_dir, *lang_dir; struct perf_session *session; @@ -1713,9 +1711,9 @@ int find_scripts(char **scripts_array, char **scripts_path_array) return -1; } - for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { + for_each_lang(scripts_path, scripts_dir, lang_dirent) { snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, - lang_dirent.d_name); + lang_dirent->d_name); #ifdef NO_LIBPERL if (strstr(lang_path, "perl")) continue; @@ -1729,16 +1727,16 @@ int find_scripts(char **scripts_array, char **scripts_path_array) if (!lang_dir) continue; - for_each_script(lang_path, lang_dir, script_dirent, script_next) { + for_each_script(lang_path, lang_dir, script_dirent) { /* Skip those real time scripts: xxxtop.p[yl] */ - if (strstr(script_dirent.d_name, "top.")) + if (strstr(script_dirent->d_name, "top.")) continue; sprintf(scripts_path_array[i], "%s/%s", lang_path, - script_dirent.d_name); - temp = strchr(script_dirent.d_name, '.'); + script_dirent->d_name); + temp = strchr(script_dirent->d_name, '.'); snprintf(scripts_array[i], - (temp - script_dirent.d_name) + 1, - "%s", script_dirent.d_name); + (temp - script_dirent->d_name) + 1, + "%s", script_dirent->d_name); if (check_ev_match(lang_path, scripts_array[i], session)) @@ -1756,7 +1754,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array) static char *get_script_path(const char *script_root, const char *suffix) { - struct dirent *script_next, *lang_next, script_dirent, lang_dirent; + struct dirent *script_dirent, *lang_dirent; char scripts_path[MAXPATHLEN]; char script_path[MAXPATHLEN]; DIR *scripts_dir, *lang_dir; @@ -1769,21 +1767,21 @@ static char *get_script_path(const char *script_root, const char *suffix) if (!scripts_dir) return NULL; - for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { + for_each_lang(scripts_path, scripts_dir, lang_dirent) { snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, - lang_dirent.d_name); + lang_dirent->d_name); lang_dir = opendir(lang_path); if (!lang_dir) continue; - for_each_script(lang_path, lang_dir, script_dirent, script_next) { - __script_root = get_script_root(&script_dirent, suffix); + for_each_script(lang_path, lang_dir, script_dirent) { + __script_root = get_script_root(script_dirent, suffix); if (__script_root && !strcmp(script_root, __script_root)) { free(__script_root); closedir(lang_dir); closedir(scripts_dir); snprintf(script_path, MAXPATHLEN, "%s/%s", - lang_path, script_dirent.d_name); + lang_path, script_dirent->d_name); return strdup(script_path); } free(__script_root); -- GitLab From 3354cf71104de49326d19d2f9bdb1f66eea52ef4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 8 Apr 2016 11:31:24 -0300 Subject: [PATCH 1819/9938] perf thread_map: Use readdir() instead of deprecated readdir_r() The readdir() function is thread safe as long as just one thread uses a DIR, which is the case in thread_map, so, to avoid breaking the build with glibc-2.23.90 (upcoming 2.24), use it instead of readdir_r(). See: http://man7.org/linux/man-pages/man3/readdir.3.html "However, in modern implementations (including the glibc implementation), concurrent calls to readdir() that specify different directory streams are thread-safe. In cases where multiple threads must read from the same directory stream, using readdir() with external synchronization is still preferable to the use of the deprecated readdir_r(3) function." Noticed while building on a Fedora Rawhide docker container. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-del8h2a0f40z75j4r42l96l0@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 08afc6909953..267112b4e3db 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -94,7 +94,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) DIR *proc; int max_threads = 32, items, i; char path[256]; - struct dirent dirent, *next, **namelist = NULL; + struct dirent *dirent, **namelist = NULL; struct thread_map *threads = thread_map__alloc(max_threads); if (threads == NULL) @@ -107,16 +107,16 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) threads->nr = 0; atomic_set(&threads->refcnt, 1); - while (!readdir_r(proc, &dirent, &next) && next) { + while ((dirent = readdir(proc)) != NULL) { char *end; bool grow = false; struct stat st; - pid_t pid = strtol(dirent.d_name, &end, 10); + pid_t pid = strtol(dirent->d_name, &end, 10); if (*end) /* only interested in proper numerical dirents */ continue; - snprintf(path, sizeof(path), "/proc/%s", dirent.d_name); + snprintf(path, sizeof(path), "/proc/%s", dirent->d_name); if (stat(path, &st) != 0) continue; -- GitLab From 7093b4c963cc4e344e490c774924a180602a7092 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 8 Apr 2016 11:32:15 -0300 Subject: [PATCH 1820/9938] perf tools: Use readdir() instead of deprecated readdir_r() The readdir() function is thread safe as long as just one thread uses a DIR, which is the case when synthesizing events for pre-existing threads by traversing /proc, so, to avoid breaking the build with glibc-2.23.90 (upcoming 2.24), use it instead of readdir_r(). See: http://man7.org/linux/man-pages/man3/readdir.3.html "However, in modern implementations (including the glibc implementation), concurrent calls to readdir() that specify different directory streams are thread-safe. In cases where multiple threads must read from the same directory stream, using readdir() with external synchronization is still preferable to the use of the deprecated readdir_r(3) function." Noticed while building on a Fedora Rawhide docker container. CC /tmp/build/perf/util/event.o util/event.c: In function '__event__synthesize_thread': util/event.c:466:2: error: 'readdir_r' is deprecated [-Werror=deprecated-declarations] while (!readdir_r(tasks, &dirent, &next) && next) { ^~~~~ In file included from /usr/include/features.h:368:0, from /usr/include/stdint.h:25, from /usr/lib/gcc/x86_64-redhat-linux/6.0.0/include/stdint.h:9, from /git/linux/tools/include/linux/types.h:6, from util/event.c:1: /usr/include/dirent.h:189:12: note: declared here Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-i1vj7nyjp2p750rirxgrfd3c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index b68959037688..f6fcc6832949 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -434,7 +434,7 @@ static int __event__synthesize_thread(union perf_event *comm_event, { char filename[PATH_MAX]; DIR *tasks; - struct dirent dirent, *next; + struct dirent *dirent; pid_t tgid, ppid; int rc = 0; @@ -463,11 +463,11 @@ static int __event__synthesize_thread(union perf_event *comm_event, return 0; } - while (!readdir_r(tasks, &dirent, &next) && next) { + while ((dirent = readdir(tasks)) != NULL) { char *end; pid_t _pid; - _pid = strtol(dirent.d_name, &end, 10); + _pid = strtol(dirent->d_name, &end, 10); if (*end) continue; @@ -576,7 +576,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, { DIR *proc; char proc_path[PATH_MAX]; - struct dirent dirent, *next; + struct dirent *dirent; union perf_event *comm_event, *mmap_event, *fork_event; int err = -1; @@ -601,9 +601,9 @@ int perf_event__synthesize_threads(struct perf_tool *tool, if (proc == NULL) goto out_free_fork; - while (!readdir_r(proc, &dirent, &next) && next) { + while ((dirent = readdir(proc)) != NULL) { char *end; - pid_t pid = strtol(dirent.d_name, &end, 10); + pid_t pid = strtol(dirent->d_name, &end, 10); if (*end) /* only interested in proper numerical dirents */ continue; -- GitLab From e2ea295baf87d78f2ed86ce595b30c691b18b210 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 8 Apr 2016 17:35:04 +0300 Subject: [PATCH 1821/9938] intel_th: Hold output driver module reference while capture is active Right now it's possible to unload the output subdevice's driver while the capture to this output is active. Prevent this by holding the output driver's module reference. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 20339470c2c6..1be543e8e42f 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -189,6 +189,9 @@ static int intel_th_output_activate(struct intel_th_device *thdev) if (!thdrv) return -ENODEV; + if (!try_module_get(thdrv->driver.owner)) + return -ENODEV; + if (thdrv->activate) return thdrv->activate(thdev); @@ -209,6 +212,8 @@ static void intel_th_output_deactivate(struct intel_th_device *thdev) thdrv->deactivate(thdev); else intel_th_trace_disable(thdev); + + module_put(thdrv->driver.owner); } static ssize_t active_show(struct device *dev, struct device_attribute *attr, -- GitLab From 8e9a2beb5f991916e530184957c4137fab14604c Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 8 Apr 2016 17:36:04 +0300 Subject: [PATCH 1822/9938] intel_th: msu: Set fops::owner to prevent module from unloading Right now it's possible to unload the msu driver while its character device is open. Prevent it by setting fops::owner, which will result in the module reference being held while the device node is open. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/msu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index ee153067e136..bcc3b4713377 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -1253,6 +1253,7 @@ static const struct file_operations intel_th_msc_fops = { .read = intel_th_msc_read, .mmap = intel_th_msc_mmap, .llseek = no_llseek, + .owner = THIS_MODULE, }; static int intel_th_msc_init(struct msc *msc) -- GitLab From f152dfee19c0cd146b16179a60ffb2cacf995736 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 8 Apr 2016 17:37:40 +0300 Subject: [PATCH 1823/9938] intel_th: msu: Release resources on removal Do release the resources when msu subdevice gets removed: stop the capture if it is active (which is still possible even though the module in pinned) and free the capture buffers. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/msu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index bcc3b4713377..0974090abc7d 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -1492,6 +1492,18 @@ static int intel_th_msc_probe(struct intel_th_device *thdev) static void intel_th_msc_remove(struct intel_th_device *thdev) { + struct msc *msc = dev_get_drvdata(&thdev->dev); + int ret; + + intel_th_msc_deactivate(thdev); + + /* + * Buffers should not be used at this point except if the + * output character device is still open and the parent + * device gets detached from its bus, which is a FIXME. + */ + ret = msc_buffer_free_unless_used(msc); + WARN_ON_ONCE(ret); } static struct intel_th_driver intel_th_msc_driver = { -- GitLab From bfc279f3d233150ff260e9e93012e14f86810648 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 8 Apr 2016 11:53:02 -0300 Subject: [PATCH 1824/9938] perf tools: Use readdir() instead of deprecated readdir_r() The readdir() function is thread safe as long as just one thread uses a DIR, which is the case when parsing tracepoint event definitions, to avoid breaking the build with glibc-2.23.90 (upcoming 2.24), use it instead of readdir_r(). See: http://man7.org/linux/man-pages/man3/readdir.3.html "However, in modern implementations (including the glibc implementation), concurrent calls to readdir() that specify different directory streams are thread-safe. In cases where multiple threads must read from the same directory stream, using readdir() with external synchronization is still preferable to the use of the deprecated readdir_r(3) function." Noticed while building on a Fedora Rawhide docker container. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-wddn49r6bz6wq4ee3dxbl7lo@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 60 +++++++++++++++++----------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4c19d5e79d8c..bcbc983d4b12 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -138,11 +138,11 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) -#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ - while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ - if (sys_dirent.d_type == DT_DIR && \ - (strcmp(sys_dirent.d_name, ".")) && \ - (strcmp(sys_dirent.d_name, ".."))) +#define for_each_subsystem(sys_dir, sys_dirent) \ + while ((sys_dirent = readdir(sys_dir)) != NULL) \ + if (sys_dirent->d_type == DT_DIR && \ + (strcmp(sys_dirent->d_name, ".")) && \ + (strcmp(sys_dirent->d_name, ".."))) static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) { @@ -159,12 +159,12 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) return 0; } -#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ - while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ - if (evt_dirent.d_type == DT_DIR && \ - (strcmp(evt_dirent.d_name, ".")) && \ - (strcmp(evt_dirent.d_name, "..")) && \ - (!tp_event_has_id(&sys_dirent, &evt_dirent))) +#define for_each_event(sys_dirent, evt_dir, evt_dirent) \ + while ((evt_dirent = readdir(evt_dir)) != NULL) \ + if (evt_dirent->d_type == DT_DIR && \ + (strcmp(evt_dirent->d_name, ".")) && \ + (strcmp(evt_dirent->d_name, "..")) && \ + (!tp_event_has_id(sys_dirent, evt_dirent))) #define MAX_EVENT_LENGTH 512 @@ -173,7 +173,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) { struct tracepoint_path *path = NULL; DIR *sys_dir, *evt_dir; - struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; + struct dirent *sys_dirent, *evt_dirent; char id_buf[24]; int fd; u64 id; @@ -184,18 +184,18 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) if (!sys_dir) return NULL; - for_each_subsystem(sys_dir, sys_dirent, sys_next) { + for_each_subsystem(sys_dir, sys_dirent) { snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, - sys_dirent.d_name); + sys_dirent->d_name); evt_dir = opendir(dir_path); if (!evt_dir) continue; - for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { + for_each_event(sys_dirent, evt_dir, evt_dirent) { snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, - evt_dirent.d_name); + evt_dirent->d_name); fd = open(evt_path, O_RDONLY); if (fd < 0) continue; @@ -220,9 +220,9 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) free(path); return NULL; } - strncpy(path->system, sys_dirent.d_name, + strncpy(path->system, sys_dirent->d_name, MAX_EVENT_LENGTH); - strncpy(path->name, evt_dirent.d_name, + strncpy(path->name, evt_dirent->d_name, MAX_EVENT_LENGTH); return path; } @@ -1812,7 +1812,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, bool name_only) { DIR *sys_dir, *evt_dir; - struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; + struct dirent *sys_dirent, *evt_dirent; char evt_path[MAXPATHLEN]; char dir_path[MAXPATHLEN]; char **evt_list = NULL; @@ -1830,20 +1830,20 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, goto out_close_sys_dir; } - for_each_subsystem(sys_dir, sys_dirent, sys_next) { + for_each_subsystem(sys_dir, sys_dirent) { if (subsys_glob != NULL && - !strglobmatch(sys_dirent.d_name, subsys_glob)) + !strglobmatch(sys_dirent->d_name, subsys_glob)) continue; snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, - sys_dirent.d_name); + sys_dirent->d_name); evt_dir = opendir(dir_path); if (!evt_dir) continue; - for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { + for_each_event(sys_dirent, evt_dir, evt_dirent) { if (event_glob != NULL && - !strglobmatch(evt_dirent.d_name, event_glob)) + !strglobmatch(evt_dirent->d_name, event_glob)) continue; if (!evt_num_known) { @@ -1852,7 +1852,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, } snprintf(evt_path, MAXPATHLEN, "%s:%s", - sys_dirent.d_name, evt_dirent.d_name); + sys_dirent->d_name, evt_dirent->d_name); evt_list[evt_i] = strdup(evt_path); if (evt_list[evt_i] == NULL) @@ -1905,7 +1905,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, int is_valid_tracepoint(const char *event_string) { DIR *sys_dir, *evt_dir; - struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; + struct dirent *sys_dirent, *evt_dirent; char evt_path[MAXPATHLEN]; char dir_path[MAXPATHLEN]; @@ -1913,17 +1913,17 @@ int is_valid_tracepoint(const char *event_string) if (!sys_dir) return 0; - for_each_subsystem(sys_dir, sys_dirent, sys_next) { + for_each_subsystem(sys_dir, sys_dirent) { snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, - sys_dirent.d_name); + sys_dirent->d_name); evt_dir = opendir(dir_path); if (!evt_dir) continue; - for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { + for_each_event(sys_dirent, evt_dir, evt_dirent) { snprintf(evt_path, MAXPATHLEN, "%s:%s", - sys_dirent.d_name, evt_dirent.d_name); + sys_dirent->d_name, evt_dirent->d_name); if (!strcmp(evt_path, event_string)) { closedir(evt_dir); closedir(sys_dir); -- GitLab From f9383452a26fc47f62c4ddcfa20ccebb7a09c2d8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 8 Apr 2016 12:04:29 -0300 Subject: [PATCH 1825/9938] perf dwarf: Guard !x86_64 definitions under #ifdef else clause To fix the build on Fedora Rawhide (gcc 6.0.0 20160311 (Red Hat 6.0.0-0.17): CC /tmp/build/perf/arch/x86/util/dwarf-regs.o arch/x86/util/dwarf-regs.c:66:36: error: 'x86_32_regoffset_table' defined but not used [-Werror=unused-const-variable=] static const struct pt_regs_offset x86_32_regoffset_table[] = { ^~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-fghuksc1u8ln82bof4lwcj0o@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/dwarf-regs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c index 9223c164e545..1f86ee8fb831 100644 --- a/tools/perf/arch/x86/util/dwarf-regs.c +++ b/tools/perf/arch/x86/util/dwarf-regs.c @@ -63,6 +63,8 @@ struct pt_regs_offset { # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)} #endif +/* TODO: switching by dwarf address size */ +#ifndef __x86_64__ static const struct pt_regs_offset x86_32_regoffset_table[] = { REG_OFFSET_NAME_32("%ax", eax), REG_OFFSET_NAME_32("%cx", ecx), @@ -75,6 +77,8 @@ static const struct pt_regs_offset x86_32_regoffset_table[] = { REG_OFFSET_END, }; +#define regoffset_table x86_32_regoffset_table +#else static const struct pt_regs_offset x86_64_regoffset_table[] = { REG_OFFSET_NAME_64("%ax", rax), REG_OFFSET_NAME_64("%dx", rdx), @@ -95,11 +99,7 @@ static const struct pt_regs_offset x86_64_regoffset_table[] = { REG_OFFSET_END, }; -/* TODO: switching by dwarf address size */ -#ifdef __x86_64__ #define regoffset_table x86_64_regoffset_table -#else -#define regoffset_table x86_32_regoffset_table #endif /* Minus 1 for the ending REG_OFFSET_END */ -- GitLab From 1d111406c6d91f4d7f6cc69a43e59546e8010aae Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 20 Mar 2016 13:57:20 +0100 Subject: [PATCH 1826/9938] PCI: Add Intel Thunderbolt device IDs Intel Gen 1 and 2 chips use the same ID for NHI, bridges and switch. Gen 3 chips and onward use a distinct ID for the NHI. No functional change intended. Signed-off-by: Lukas Wunner Signed-off-by: Bjorn Helgaas Acked-by: Andreas Noever --- drivers/pci/quirks.c | 16 ++++++++++------ drivers/thunderbolt/nhi.c | 8 +++++--- drivers/thunderbolt/switch.c | 9 +++++---- include/linux/pci_ids.h | 18 ++++++++++++++++++ 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8e678027b900..b584ddf83555 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3232,7 +3232,8 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev) acpi_execute_simple_method(SXIO, NULL, 0); acpi_execute_simple_method(SXLV, NULL, 0); } -DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, 0x1547, +DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, quirk_apple_poweroff_thunderbolt); /* @@ -3266,9 +3267,10 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) if (!nhi) goto out; if (nhi->vendor != PCI_VENDOR_ID_INTEL - || (nhi->device != 0x1547 && nhi->device != 0x156c) - || nhi->subsystem_vendor != 0x2222 - || nhi->subsystem_device != 0x1111) + || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && + nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI) + || nhi->subsystem_vendor != 0x2222 + || nhi->subsystem_device != 0x1111) goto out; dev_info(&dev->dev, "quirk: waiting for thunderbolt to reestablish PCI tunnels...\n"); device_pm_wait_for_dev(&dev->dev, &nhi->dev); @@ -3276,9 +3278,11 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) pci_dev_put(nhi); pci_dev_put(sibling); } -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x1547, +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, quirk_apple_wait_for_thunderbolt); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x156d, +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE, quirk_apple_wait_for_thunderbolt); #endif diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 20a41f7de76f..36be23babb89 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -633,16 +633,18 @@ static const struct dev_pm_ops nhi_pm_ops = { static struct pci_device_id nhi_ids[] = { /* * We have to specify class, the TB bridges use the same device and - * vendor (sub)id. + * vendor (sub)id on gen 1 and gen 2 controllers. */ { .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0, - .vendor = PCI_VENDOR_ID_INTEL, .device = 0x1547, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, .subvendor = 0x2222, .subdevice = 0x1111, }, { .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0, - .vendor = PCI_VENDOR_ID_INTEL, .device = 0x156c, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, { 0,} diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index aeb982969629..db73ffed68a9 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -293,9 +293,9 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active) if (active) { data = data & 0xFFFFFF83; switch (sw->config.device_id) { - case 0x1513: - case 0x151a: - case 0x1549: + case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE: + case PCI_DEVICE_ID_INTEL_EAGLE_RIDGE: + case PCI_DEVICE_ID_INTEL_PORT_RIDGE: break; default: data |= 4; @@ -370,7 +370,8 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route) tb_sw_warn(sw, "unknown switch vendor id %#x\n", sw->config.vendor_id); - if (sw->config.device_id != 0x1547 && sw->config.device_id != 0x1549) + if (sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && + sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE) tb_sw_warn(sw, "unsupported switch device id %#x\n", sw->config.device_id); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 247da8c95860..c58752fe16c4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2604,6 +2604,24 @@ #define PCI_DEVICE_ID_INTEL_82441 0x1237 #define PCI_DEVICE_ID_INTEL_82380FB 0x124b #define PCI_DEVICE_ID_INTEL_82439 0x1250 +#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */ +#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a +#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */ +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548 +#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI 0x1566 /* Tbt 1 Gen 3 */ +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI 0x1568 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569 +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */ +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578 #define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 -- GitLab From aae20bb6b45e0666c63506053c40f71c0c34cba0 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 20 Mar 2016 13:57:20 +0100 Subject: [PATCH 1827/9938] thunderbolt: Fix typos and magic number Fix typo in tb_cfg_print_error() message. Fix bytecount in struct tb_drom_entry_port comment. Replace magic number in tb_switch_alloc(). Rename tb_sw_set_unpplugged() and TB_CAL_IECS to fix typos. [bhelgaas: no functional change intended] Signed-off-by: Lukas Wunner Signed-off-by: Bjorn Helgaas Acked-by: Andreas Noever --- drivers/thunderbolt/ctl.c | 2 +- drivers/thunderbolt/eeprom.c | 2 +- drivers/thunderbolt/switch.c | 10 +++++----- drivers/thunderbolt/tb.c | 2 +- drivers/thunderbolt/tb.h | 2 +- drivers/thunderbolt/tb_regs.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c index 799634b382c6..1146ff4210a9 100644 --- a/drivers/thunderbolt/ctl.c +++ b/drivers/thunderbolt/ctl.c @@ -249,7 +249,7 @@ static void tb_cfg_print_error(struct tb_ctl *ctl, * cfg_read/cfg_write. */ tb_ctl_WARN(ctl, - "CFG_ERROR(%llx:%x): Invalid config space of offset\n", + "CFG_ERROR(%llx:%x): Invalid config space or offset\n", res->response_route, res->response_port); return; case TB_CFG_ERROR_NO_SUCH_PORT: diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 0dde34e3a7c5..47e56e861d61 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -221,7 +221,7 @@ struct tb_drom_entry_port { u8 micro1:4; u8 micro3; - /* BYTES 5-6, TODO: verify (find hardware that has these set) */ + /* BYTES 6-7, TODO: verify (find hardware that has these set) */ u8 peer_port_rid:4; u8 unknown3:3; bool has_peer_port:1; diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index db73ffed68a9..c6270f0bd5c5 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -350,7 +350,7 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route) return NULL; sw->tb = tb; - if (tb_cfg_read(tb->ctl, &sw->config, route, 0, 2, 0, 5)) + if (tb_cfg_read(tb->ctl, &sw->config, route, 0, TB_CFG_SWITCH, 0, 5)) goto err; tb_info(tb, "initializing Switch at %#llx (depth: %d, up port: %d)\n", @@ -426,9 +426,9 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route) } /** - * tb_sw_set_unpplugged() - set is_unplugged on switch and downstream switches + * tb_sw_set_unplugged() - set is_unplugged on switch and downstream switches */ -void tb_sw_set_unpplugged(struct tb_switch *sw) +void tb_sw_set_unplugged(struct tb_switch *sw) { int i; if (sw == sw->tb->root_switch) { @@ -442,7 +442,7 @@ void tb_sw_set_unpplugged(struct tb_switch *sw) sw->is_unplugged = true; for (i = 0; i <= sw->config.max_port_number; i++) { if (!tb_is_upstream_port(&sw->ports[i]) && sw->ports[i].remote) - tb_sw_set_unpplugged(sw->ports[i].remote->sw); + tb_sw_set_unplugged(sw->ports[i].remote->sw); } } @@ -484,7 +484,7 @@ int tb_switch_resume(struct tb_switch *sw) || tb_switch_resume(port->remote->sw)) { tb_port_warn(port, "lost during suspend, disconnecting\n"); - tb_sw_set_unpplugged(port->remote->sw); + tb_sw_set_unplugged(port->remote->sw); } } return 0; diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index d2c3fe346e91..24b6d30c3c86 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -246,7 +246,7 @@ static void tb_handle_hotplug(struct work_struct *work) if (ev->unplug) { if (port->remote) { tb_port_info(port, "unplugged\n"); - tb_sw_set_unpplugged(port->remote->sw); + tb_sw_set_unplugged(port->remote->sw); tb_free_invalid_tunnels(tb); tb_switch_free(port->remote->sw); port->remote = NULL; diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 8b0d7cf2b6d6..61d57ba64035 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -226,7 +226,7 @@ void tb_switch_free(struct tb_switch *sw); void tb_switch_suspend(struct tb_switch *sw); int tb_switch_resume(struct tb_switch *sw); int tb_switch_reset(struct tb *tb, u64 route); -void tb_sw_set_unpplugged(struct tb_switch *sw); +void tb_sw_set_unplugged(struct tb_switch *sw); struct tb_switch *get_switch_at_route(struct tb_switch *sw, u64 route); int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged); diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 6577af75d9dc..1e2a4a8046be 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -30,7 +30,7 @@ enum tb_cap { TB_CAP_I2C = 0x0005, TB_CAP_PLUG_EVENTS = 0x0105, /* also EEPROM */ TB_CAP_TIME2 = 0x0305, - TB_CAL_IECS = 0x0405, + TB_CAP_IECS = 0x0405, TB_CAP_LINK_CONTROLLER = 0x0605, /* also IECS */ }; -- GitLab From 19bf4d4f909d644110cb587545dc385044ac90a4 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 20 Mar 2016 13:57:20 +0100 Subject: [PATCH 1828/9938] thunderbolt: Support 1st gen Light Ridge controller Add support for the 1st gen Light Ridge controller, which is built into these systems: iMac12,1 2011 21.5" iMac12,2 2011 27" Macmini5,1 2011 i5 2.3 GHz Macmini5,2 2011 i5 2.5 GHz Macmini5,3 2011 i7 2.0 GHz MacBookPro8,1 2011 13" MacBookPro8,2 2011 15" MacBookPro8,3 2011 17" MacBookPro9,1 2012 15" MacBookPro9,2 2012 13" Light Ridge (CV82524) was the very first copper Thunderbolt controller, introduced 2010 alongside its fiber-optic cousin Light Peak (CVL2510). Consequently the chip suffers from some teething troubles: - MSI is broken for hotplug signaling on the downstream bridges: The chip just never sends an interrupt. It requests 32 MSIs for each of its six bridges and the pcieport driver only allocates one per bridge. However I've verified that even if 32 MSIs are allocated there's no interrupt on hotplug. The only option is thus to disable MSI, which is also what OS X does. Apparently all Thunderbolt chips up to revision 1 of Cactus Ridge 4C are plagued by this issue so quirk those as well. - The chip supports a maximum hop_count of 32, unlike its successors which support only 12. Fixup ring_interrupt_active() to cope with values >= 32. - Another peculiarity is that the chip supports a maximum of 13 ports whereas its successors support 12. However the additional port (#5) seems to be unusable as reading its TB_CFG_PORT config space results in TB_CFG_ERROR_INVALID_CONFIG_SPACE. Add a quirk to mark the port disabled on the root switch, assuming that's necessary on all Macs using this chip. Tested-by: Lukas Wunner [MacBookPro9,1] Tested-by: William Brown [MacBookPro8,2] Signed-off-by: Lukas Wunner Signed-off-by: Bjorn Helgaas Acked-by: Andreas Noever --- drivers/pci/quirks.c | 29 ++++++++++++++++++++++++++++- drivers/thunderbolt/eeprom.c | 5 +++++ drivers/thunderbolt/nhi.c | 11 +++++++++-- drivers/thunderbolt/switch.c | 3 ++- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b584ddf83555..b1ff270622dd 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3185,6 +3185,29 @@ static void quirk_no_pm_reset(struct pci_dev *dev) DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset); +/* + * Thunderbolt controllers with broken MSI hotplug signaling: + * Entire 1st generation (Light Ridge, Eagle Ridge, Light Peak) and part + * of the 2nd generation (Cactus Ridge 4C up to revision 1, Port Ridge). + */ +static void quirk_thunderbolt_hotplug_msi(struct pci_dev *pdev) +{ + if (pdev->is_hotplug_bridge && + (pdev->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C || + pdev->revision <= 1)) + pdev->no_msi = 1; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, + quirk_thunderbolt_hotplug_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EAGLE_RIDGE, + quirk_thunderbolt_hotplug_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LIGHT_PEAK, + quirk_thunderbolt_hotplug_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, + quirk_thunderbolt_hotplug_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE, + quirk_thunderbolt_hotplug_msi); + #ifdef CONFIG_ACPI /* * Apple: Shutdown Cactus Ridge Thunderbolt controller. @@ -3267,7 +3290,8 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) if (!nhi) goto out; if (nhi->vendor != PCI_VENDOR_ID_INTEL - || (nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && + || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE && + nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI) || nhi->subsystem_vendor != 0x2222 || nhi->subsystem_device != 0x1111) @@ -3278,6 +3302,9 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) pci_dev_put(nhi); pci_dev_put(sibling); } +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, + quirk_apple_wait_for_thunderbolt); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, quirk_apple_wait_for_thunderbolt); diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 47e56e861d61..0c052e25c5bc 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -388,6 +388,11 @@ int tb_drom_read(struct tb_switch *sw) sw->ports[4].link_nr = 1; sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].dual_link_port = &sw->ports[3]; + + /* Port 5 is inaccessible on this gen 1 controller */ + if (sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE) + sw->ports[5].disabled = true; + return 0; } diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 36be23babb89..9c15344b657a 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -37,7 +37,8 @@ static int ring_interrupt_index(struct tb_ring *ring) */ static void ring_interrupt_active(struct tb_ring *ring, bool active) { - int reg = REG_RING_INTERRUPT_BASE + ring_interrupt_index(ring) / 32; + int reg = REG_RING_INTERRUPT_BASE + + ring_interrupt_index(ring) / 32 * 4; int bit = ring_interrupt_index(ring) & 31; int mask = 1 << bit; u32 old, new; @@ -564,7 +565,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* cannot fail - table is allocated bin pcim_iomap_regions */ nhi->iobase = pcim_iomap_table(pdev)[0]; nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff; - if (nhi->hop_count != 12) + if (nhi->hop_count != 12 && nhi->hop_count != 32) dev_warn(&pdev->dev, "unexpected hop count: %d\n", nhi->hop_count); INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work); @@ -635,6 +636,12 @@ static struct pci_device_id nhi_ids[] = { * We have to specify class, the TB bridges use the same device and * vendor (sub)id on gen 1 and gen 2 controllers. */ + { + .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, + .subvendor = 0x2222, .subdevice = 0x1111, + }, { .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0, .vendor = PCI_VENDOR_ID_INTEL, diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index c6270f0bd5c5..1e116f53d6dd 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -370,7 +370,8 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route) tb_sw_warn(sw, "unknown switch vendor id %#x\n", sw->config.vendor_id); - if (sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && + if (sw->config.device_id != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE && + sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE) tb_sw_warn(sw, "unsupported switch device id %#x\n", sw->config.device_id); -- GitLab From f18ba58f538e44a701ad0b86d47bb57b917d7c0a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 6 Apr 2016 13:09:05 +0300 Subject: [PATCH 1829/9938] Bluetooth: Fix setting NO_BREDR advertising flag If we're dealing with a single-mode controller or BR/EDR is disable for a dual-mode one, the NO_BREDR flag needs to be unconditionally present in the advertising data. This patch moves it out from behind an extra condition to be always set in the create_instance_adv_data() function if BR/EDR is disabled. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_request.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 6e125d76df0d..c045b3c54768 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -1065,6 +1065,9 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) flags |= LE_AD_LIMITED; + if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) + flags |= LE_AD_NO_BREDR; + if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { /* If a discovery flag wasn't provided, simply use the global * settings. @@ -1072,9 +1075,6 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) if (!flags) flags |= mgmt_get_adv_discov_flags(hdev); - if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) - flags |= LE_AD_NO_BREDR; - /* If flags would still be empty, then there is no need to * include the "Flags" AD field". */ -- GitLab From 56b40fbf61a247e23b50e426971148b2e50262e0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 7 Apr 2016 21:01:27 +0300 Subject: [PATCH 1830/9938] Bluetooth: Ignore unknown advertising packet types In case of buggy controllers send advertising packet types that we don't know of we should simply ignore them instead of trying to react to them in some (potentially wrong) way. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index c162af5d16bf..d4b3dd5413be 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4727,6 +4727,19 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, u32 flags; u8 *ptr, real_len; + switch (type) { + case LE_ADV_IND: + case LE_ADV_DIRECT_IND: + case LE_ADV_SCAN_IND: + case LE_ADV_NONCONN_IND: + case LE_ADV_SCAN_RSP: + break; + default: + BT_ERR_RATELIMITED("Unknown advetising packet type: 0x%02x", + type); + return; + } + /* Find the end of the data in case the report contains padded zero * bytes at the end causing an invalid length value. * -- GitLab From 1dbfc59a931495b2e7bdc4e85886162a0b03235b Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 4 Apr 2016 11:31:12 +0200 Subject: [PATCH 1831/9938] Bluetooth: hci_bcm: Add BCM2E71 ACPI ID This ID is used at least by Asus T100-CHI. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index d8881dc0600c..1c97eda8bae3 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -825,6 +825,7 @@ static const struct acpi_device_id bcm_acpi_match[] = { { "BCM2E64", 0 }, { "BCM2E65", 0 }, { "BCM2E67", 0 }, + { "BCM2E71", 0 }, { "BCM2E7B", 0 }, { "BCM2E7C", 0 }, { }, -- GitLab From 84cb3df02aea4b00405521e67c4c67c2d525c364 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 4 Apr 2016 10:48:13 +0200 Subject: [PATCH 1832/9938] Bluetooth: hci_ldisc: Fix null pointer derefence in case of early data HCI_UART_PROTO_SET flag is set before hci_uart_set_proto call. If we receive data from tty layer during this procedure, proto pointer may not be assigned yet, leading to null pointer dereference in rx method hci_uart_tty_receive. This patch fixes this issue by introducing HCI_UART_PROTO_READY flag in order to avoid any proto operation before proto opening and assignment. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ldisc.c | 11 +++++++---- drivers/bluetooth/hci_uart.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index c00168a5bb80..49b3e1e2d236 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -227,7 +227,7 @@ static int hci_uart_flush(struct hci_dev *hdev) tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); - if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) hu->proto->flush(hu); return 0; @@ -492,7 +492,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) cancel_work_sync(&hu->write_work); - if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { + if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags)) { if (hdev) { if (test_bit(HCI_UART_REGISTERED, &hu->flags)) hci_unregister_dev(hdev); @@ -500,6 +500,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) } hu->proto->close(hu); } + clear_bit(HCI_UART_PROTO_SET, &hu->flags); kfree(hu); } @@ -526,7 +527,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) if (tty != hu->tty) return; - if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) hci_uart_tx_wakeup(hu); } @@ -550,7 +551,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, if (!hu || tty != hu->tty) return; - if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) return; /* It does not need a lock here as it is already protected by a mutex in @@ -638,9 +639,11 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) return err; hu->proto = p; + set_bit(HCI_UART_PROTO_READY, &hu->flags); err = hci_uart_register_dev(hu); if (err) { + clear_bit(HCI_UART_PROTO_READY, &hu->flags); p->close(hu); return err; } diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 4814ff08f427..839bad1d8152 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -95,6 +95,7 @@ struct hci_uart { /* HCI_UART proto flag bits */ #define HCI_UART_PROTO_SET 0 #define HCI_UART_REGISTERED 1 +#define HCI_UART_PROTO_READY 2 /* TX states */ #define HCI_UART_SENDING 1 -- GitLab From a164cee111085f9ee77f6038f006658249073523 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Thu, 24 Mar 2016 16:04:15 +0200 Subject: [PATCH 1833/9938] Bluetooth: Allow setting BT_SECURITY_FIPS with setsockopt Update the security level check to allow setting BT_SECURITY_FIPS for an L2CAP socket. Signed-off-by: Patrik Flykt Signed-off-by: Marcel Holtmann --- net/bluetooth/l2cap_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index e4cae72895a7..388ee8b59145 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -778,7 +778,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, } if (sec.level < BT_SECURITY_LOW || - sec.level > BT_SECURITY_HIGH) { + sec.level > BT_SECURITY_FIPS) { err = -EINVAL; break; } -- GitLab From 373a32c848ae3a1c03618517cce85f9211a6facf Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 19 Mar 2016 11:05:18 +0100 Subject: [PATCH 1834/9938] Bluetooth: vhci: fix open_timeout vs. hdev race Both vhci_get_user and vhci_release race with open_timeout work. They both contain cancel_delayed_work_sync, but do not test whether the work actually created hdev or not. Since the work can be in progress and _sync will wait for finishing it, we can have data->hdev allocated when cancel_delayed_work_sync returns. But the call sites do 'if (data->hdev)' *before* cancel_delayed_work_sync. As a result: * vhci_get_user allocates a second hdev and puts it into data->hdev. The former is leaked. * vhci_release does not release data->hdev properly as it thinks there is none. Fix both cases by moving the actual test *after* the call to cancel_delayed_work_sync. This can be hit by this program: #include #include #include #include #include #include #include #include int main(int argc, char **argv) { int fd; srand(time(NULL)); while (1) { const int delta = (rand() % 200 - 100) * 100; fd = open("/dev/vhci", O_RDWR); if (fd < 0) err(1, "open"); usleep(1000000 + delta); close(fd); } return 0; } And the result is: BUG: KASAN: use-after-free in skb_queue_tail+0x13e/0x150 at addr ffff88006b0c1228 Read of size 8 by task kworker/u13:1/32068 ============================================================================= BUG kmalloc-192 (Tainted: G E ): kasan: bad access detected ----------------------------------------------------------------------------- Disabling lock debugging due to kernel taint INFO: Allocated in vhci_open+0x50/0x330 [hci_vhci] age=260 cpu=3 pid=32040 ... kmem_cache_alloc_trace+0x150/0x190 vhci_open+0x50/0x330 [hci_vhci] misc_open+0x35b/0x4e0 chrdev_open+0x23b/0x510 ... INFO: Freed in vhci_release+0xa4/0xd0 [hci_vhci] age=9 cpu=2 pid=32040 ... __slab_free+0x204/0x310 vhci_release+0xa4/0xd0 [hci_vhci] ... INFO: Slab 0xffffea0001ac3000 objects=16 used=13 fp=0xffff88006b0c1e00 flags=0x5fffff80004080 INFO: Object 0xffff88006b0c1200 @offset=4608 fp=0xffff88006b0c0600 Bytes b4 ffff88006b0c11f0: 09 df 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffff88006b0c1200: 00 06 0c 6b 00 88 ff ff 00 00 00 00 00 00 00 00 ...k............ Object ffff88006b0c1210: 10 12 0c 6b 00 88 ff ff 10 12 0c 6b 00 88 ff ff ...k.......k.... Object ffff88006b0c1220: c0 46 c2 6b 00 88 ff ff c0 46 c2 6b 00 88 ff ff .F.k.....F.k.... Object ffff88006b0c1230: 01 00 00 00 01 00 00 00 e0 ff ff ff 0f 00 00 00 ................ Object ffff88006b0c1240: 40 12 0c 6b 00 88 ff ff 40 12 0c 6b 00 88 ff ff @..k....@..k.... Object ffff88006b0c1250: 50 0d 6e a0 ff ff ff ff 00 02 00 00 00 00 ad de P.n............. Object ffff88006b0c1260: 00 00 00 00 00 00 00 00 ab 62 02 00 01 00 00 00 .........b...... Object ffff88006b0c1270: 90 b9 19 81 ff ff ff ff 38 12 0c 6b 00 88 ff ff ........8..k.... Object ffff88006b0c1280: 03 00 20 00 ff ff ff ff ff ff ff ff 00 00 00 00 .. ............. Object ffff88006b0c1290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffff88006b0c12a0: 00 00 00 00 00 00 00 00 00 80 cd 3d 00 88 ff ff ...........=.... Object ffff88006b0c12b0: 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . .............. Redzone ffff88006b0c12c0: bb bb bb bb bb bb bb bb ........ Padding ffff88006b0c13f8: 00 00 00 00 00 00 00 00 ........ CPU: 3 PID: 32068 Comm: kworker/u13:1 Tainted: G B E 4.4.6-0-default #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.1-0-g4adadbd-20151112_172657-sheep25 04/01/2014 Workqueue: hci0 hci_cmd_work [bluetooth] 00000000ffffffff ffffffff81926cfa ffff88006be37c68 ffff88006bc27180 ffff88006b0c1200 ffff88006b0c1234 ffffffff81577993 ffffffff82489320 ffff88006bc24240 0000000000000046 ffff88006a100000 000000026e51eb80 Call Trace: ... [] ? skb_queue_tail+0x13e/0x150 [] ? vhci_send_frame+0xac/0x100 [hci_vhci] [] ? hci_send_frame+0x188/0x320 [bluetooth] [] ? hci_cmd_work+0x115/0x310 [bluetooth] [] ? process_one_work+0x815/0x1340 [] ? worker_thread+0xe5/0x11f0 [] ? process_one_work+0x1340/0x1340 [] ? kthread+0x1c8/0x230 ... Memory state around the buggy address: ffff88006b0c1100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff88006b0c1180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc >ffff88006b0c1200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff88006b0c1280: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc ffff88006b0c1300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc Fixes: 23424c0d31 (Bluetooth: Add support creating virtual AMP controllers) Signed-off-by: Jiri Slaby Signed-off-by: Marcel Holtmann Cc: Dmitry Vyukov Cc: stable 3.13+ --- drivers/bluetooth/hci_vhci.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 80783dcb7f57..3ec580e38c17 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -189,13 +189,13 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, break; case HCI_VENDOR_PKT: + cancel_delayed_work_sync(&data->open_timeout); + if (data->hdev) { kfree_skb(skb); return -EBADFD; } - cancel_delayed_work_sync(&data->open_timeout); - opcode = *((__u8 *) skb->data); skb_pull(skb, 1); @@ -333,10 +333,12 @@ static int vhci_open(struct inode *inode, struct file *file) static int vhci_release(struct inode *inode, struct file *file) { struct vhci_data *data = file->private_data; - struct hci_dev *hdev = data->hdev; + struct hci_dev *hdev; cancel_delayed_work_sync(&data->open_timeout); + hdev = data->hdev; + if (hdev) { hci_unregister_dev(hdev); hci_free_dev(hdev); -- GitLab From 13407376b255325fa817798800117a839f3aa055 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 19 Mar 2016 11:49:43 +0100 Subject: [PATCH 1835/9938] Bluetooth: vhci: purge unhandled skbs The write handler allocates skbs and queues them into data->readq. Read side should read them, if there is any. If there is none, skbs should be dropped by hdev->flush. But this happens only if the device is HCI_UP, i.e. hdev->power_on work was triggered already. When it was not, skbs stay allocated in the queue when /dev/vhci is closed. So purge the queue in ->release. Program to reproduce: #include #include #include #include #include #include #include int main() { char buf[] = { 0xff, 0 }; struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf), }; int fd; while (1) { fd = open("/dev/vhci", O_RDWR); if (fd < 0) err(1, "open"); usleep(50); if (writev(fd, &iov, 1) < 0) err(1, "writev"); usleep(50); close(fd); } return 0; } Result: kmemleak: 4609 new suspected memory leaks unreferenced object 0xffff88059f4d5440 (size 232): comm "vhci", pid 1084, jiffies 4294912542 (age 37569.296s) hex dump (first 32 bytes): 20 f0 23 87 05 88 ff ff 20 f0 23 87 05 88 ff ff .#..... .#..... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: ... [] __alloc_skb+0x0/0x5a0 [] vhci_create_device+0x5c/0x580 [hci_vhci] [] vhci_write+0x306/0x4c8 [hci_vhci] Fixes: 23424c0d31 (Bluetooth: Add support creating virtual AMP controllers) Signed-off-by: Jiri Slaby Signed-off-by: Marcel Holtmann Cc: stable 3.13+ --- drivers/bluetooth/hci_vhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 3ec580e38c17..f67ea1c090cb 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -344,6 +344,7 @@ static int vhci_release(struct inode *inode, struct file *file) hci_free_dev(hdev); } + skb_queue_purge(&data->readq); file->private_data = NULL; kfree(data); -- GitLab From feb2add3235ca81dc5cd5d975490c707a24c9889 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 16 Mar 2016 13:52:41 +0100 Subject: [PATCH 1836/9938] 6lowpan: iphc: fix handling of link-local compression This patch fixes handling in case of link-local address compression. A IPv6 link-local address is defined as fe80::/10 prefix which is also what ipv6_addr_type checks for link-local addresses. But IPHC compression for link-local addresses are for fe80::/64 types only. This patch adds additional checks for zero padded bits in case of link-local address compression to match on a fe80::/64 address only. Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Reviewed-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- net/6lowpan/iphc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 99bb22aea346..68c80f3c9add 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -148,6 +148,11 @@ (((a)->s6_addr16[6]) == 0) && \ (((a)->s6_addr[14]) == 0)) +#define lowpan_is_linklocal_zero_padded(a) \ + (!(hdr->saddr.s6_addr[1] & 0x3f) && \ + !hdr->saddr.s6_addr16[1] && \ + !hdr->saddr.s6_addr32[1]) + #define LOWPAN_IPHC_CID_DCI(cid) (cid & 0x0f) #define LOWPAN_IPHC_CID_SCI(cid) ((cid & 0xf0) >> 4) @@ -1101,7 +1106,8 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev, true); iphc1 |= LOWPAN_IPHC_SAC; } else { - if (ipv6_saddr_type & IPV6_ADDR_LINKLOCAL) { + if (ipv6_saddr_type & IPV6_ADDR_LINKLOCAL && + lowpan_is_linklocal_zero_padded(hdr->saddr)) { iphc1 |= lowpan_compress_addr_64(&hc_ptr, &hdr->saddr, saddr, true); @@ -1135,7 +1141,8 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev, false); iphc1 |= LOWPAN_IPHC_DAC; } else { - if (ipv6_daddr_type & IPV6_ADDR_LINKLOCAL) { + if (ipv6_daddr_type & IPV6_ADDR_LINKLOCAL && + lowpan_is_linklocal_zero_padded(hdr->daddr)) { iphc1 |= lowpan_compress_addr_64(&hc_ptr, &hdr->daddr, daddr, false); -- GitLab From cd9d7213d5f546d9c0795fdcffe4ce5bf63445fd Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Thu, 7 Apr 2016 16:46:04 +0530 Subject: [PATCH 1837/9938] ieee802154/adf7242: fix memory leak of firmware If the firmware upload or the firmware verification fails then we printed the error message and exited but we missed releasing the firmware. Signed-off-by: Sudip Mukherjee Acked-by: Michael Hennerich Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/adf7242.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index 89154c079788..b82e39d24394 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c @@ -1030,6 +1030,7 @@ static int adf7242_hw_init(struct adf7242_local *lp) if (ret) { dev_err(&lp->spi->dev, "upload firmware failed with %d\n", ret); + release_firmware(fw); return ret; } @@ -1037,6 +1038,7 @@ static int adf7242_hw_init(struct adf7242_local *lp) if (ret) { dev_err(&lp->spi->dev, "verify firmware failed with %d\n", ret); + release_firmware(fw); return ret; } -- GitLab From ff1b68ab2daf292c0f0897f9c155a6ddc8484693 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:34 +0100 Subject: [PATCH 1838/9938] nfp: correct RX buffer length calculation When calculating the RX buffer length we need to account for up to 2 VLAN tags. Rounding up to 1k is an relic of a distant past and can be removed. While at it also remove trivial print statement. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 43c618bafdb6..0dae81454e77 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1911,9 +1911,6 @@ static void nfp_net_set_rx_mode(struct net_device *netdev) static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) { struct nfp_net *nn = netdev_priv(netdev); - u32 tmp; - - nn_dbg(nn, "New MTU = %d\n", new_mtu); if (new_mtu < 68 || new_mtu > nn->max_mtu) { nn_err(nn, "New MTU (%d) is not valid\n", new_mtu); @@ -1921,10 +1918,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) } netdev->mtu = new_mtu; - - /* Freelist buffer size rounded up to the nearest 1K */ - tmp = new_mtu + ETH_HLEN + VLAN_HLEN + NFP_NET_MAX_PREPEND; - nn->fl_bufsz = roundup(tmp, 1024); + nn->fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu; /* restart if running */ if (netif_running(netdev)) { -- GitLab From 0ba40af963f01b557a4d7a0a6c550a51b0fb8d34 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:35 +0100 Subject: [PATCH 1839/9938] nfp: move link state interrupt request/free calls We need to be able to disable the link state interrupt when the device is brought down. We used to just free the IRQ at the beginning of .ndo_stop(). As we now move towards more ordered .ndo_open()/.ndo_stop() paths LSC allocation should be placed in the "allocate resource" section. Since the IRQ can't be freed early in .ndo_stop(), it is disabled instead. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 0dae81454e77..5da1199e7afb 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1729,10 +1729,16 @@ static int nfp_net_netdev_open(struct net_device *netdev) NFP_NET_IRQ_EXN_IDX, nn->exn_handler); if (err) return err; + err = nfp_net_aux_irq_request(nn, NFP_NET_CFG_LSC, "%s-lsc", + nn->lsc_name, sizeof(nn->lsc_name), + NFP_NET_IRQ_LSC_IDX, nn->lsc_handler); + if (err) + goto err_free_exn; + disable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); err = nfp_net_alloc_rings(nn); if (err) - goto err_free_exn; + goto err_free_lsc; err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); if (err) @@ -1812,19 +1818,11 @@ static int nfp_net_netdev_open(struct net_device *netdev) netif_tx_wake_all_queues(netdev); - err = nfp_net_aux_irq_request(nn, NFP_NET_CFG_LSC, "%s-lsc", - nn->lsc_name, sizeof(nn->lsc_name), - NFP_NET_IRQ_LSC_IDX, nn->lsc_handler); - if (err) - goto err_stop_tx; + enable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); nfp_net_read_link_status(nn); return 0; -err_stop_tx: - netif_tx_disable(netdev); - for (r = 0; r < nn->num_r_vecs; r++) - nfp_net_tx_flush(nn->r_vecs[r].tx_ring); err_disable_napi: while (r--) { napi_disable(&nn->r_vecs[r].napi); @@ -1834,6 +1832,8 @@ static int nfp_net_netdev_open(struct net_device *netdev) nfp_net_clear_config_and_disable(nn); err_free_rings: nfp_net_free_rings(nn); +err_free_lsc: + nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); err_free_exn: nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); return err; @@ -1855,7 +1855,7 @@ static int nfp_net_netdev_close(struct net_device *netdev) /* Step 1: Disable RX and TX rings from the Linux kernel perspective */ - nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); + disable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); netif_carrier_off(netdev); nn->link_up = false; @@ -1876,6 +1876,7 @@ static int nfp_net_netdev_close(struct net_device *netdev) } nfp_net_free_rings(nn); + nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); nn_dbg(nn, "%s down", netdev->name); -- GitLab From 0afbfb183bf5e1029ecc644acbc487d22e095b14 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:36 +0100 Subject: [PATCH 1840/9938] nfp: break up nfp_net_{alloc|free}_rings nfp_net_{alloc|free}_rings contained strange mix of allocations and vector initialization. Remove it, declare vector init as a separate function and handle allocations explicitly. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 126 +++++++----------- 1 file changed, 47 insertions(+), 79 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 5da1199e7afb..8692587904c5 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1488,91 +1488,40 @@ static int nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring) return -ENOMEM; } -static void __nfp_net_free_rings(struct nfp_net *nn, unsigned int n_free) +static int +nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, + int idx) { - struct nfp_net_r_vector *r_vec; - struct msix_entry *entry; + struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx]; + int err; - while (n_free--) { - r_vec = &nn->r_vecs[n_free]; - entry = &nn->irq_entries[r_vec->irq_idx]; + snprintf(r_vec->name, sizeof(r_vec->name), + "%s-rxtx-%d", nn->netdev->name, idx); + err = request_irq(entry->vector, r_vec->handler, 0, r_vec->name, r_vec); + if (err) { + nn_err(nn, "Error requesting IRQ %d\n", entry->vector); + return err; + } - nfp_net_rx_ring_free(r_vec->rx_ring); - nfp_net_tx_ring_free(r_vec->tx_ring); + /* Setup NAPI */ + netif_napi_add(nn->netdev, &r_vec->napi, + nfp_net_poll, NAPI_POLL_WEIGHT); - irq_set_affinity_hint(entry->vector, NULL); - free_irq(entry->vector, r_vec); + irq_set_affinity_hint(entry->vector, &r_vec->affinity_mask); - netif_napi_del(&r_vec->napi); - } -} + nn_dbg(nn, "RV%02d: irq=%03d/%03d\n", idx, entry->vector, entry->entry); -/** - * nfp_net_free_rings() - Free all ring resources - * @nn: NFP Net device to reconfigure - */ -static void nfp_net_free_rings(struct nfp_net *nn) -{ - __nfp_net_free_rings(nn, nn->num_r_vecs); + return 0; } -/** - * nfp_net_alloc_rings() - Allocate resources for RX and TX rings - * @nn: NFP Net device to reconfigure - * - * Return: 0 on success or negative errno on error. - */ -static int nfp_net_alloc_rings(struct nfp_net *nn) +static void +nfp_net_cleanup_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec) { - struct nfp_net_r_vector *r_vec; - struct msix_entry *entry; - int err; - int r; + struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx]; - for (r = 0; r < nn->num_r_vecs; r++) { - r_vec = &nn->r_vecs[r]; - entry = &nn->irq_entries[r_vec->irq_idx]; - - /* Setup NAPI */ - netif_napi_add(nn->netdev, &r_vec->napi, - nfp_net_poll, NAPI_POLL_WEIGHT); - - snprintf(r_vec->name, sizeof(r_vec->name), - "%s-rxtx-%d", nn->netdev->name, r); - err = request_irq(entry->vector, r_vec->handler, 0, - r_vec->name, r_vec); - if (err) { - nn_dbg(nn, "Error requesting IRQ %d\n", entry->vector); - goto err_napi_del; - } - - irq_set_affinity_hint(entry->vector, &r_vec->affinity_mask); - - nn_dbg(nn, "RV%02d: irq=%03d/%03d\n", - r, entry->vector, entry->entry); - - /* Allocate TX ring resources */ - err = nfp_net_tx_ring_alloc(r_vec->tx_ring); - if (err) - goto err_free_irq; - - /* Allocate RX ring resources */ - err = nfp_net_rx_ring_alloc(r_vec->rx_ring); - if (err) - goto err_free_tx; - } - - return 0; - -err_free_tx: - nfp_net_tx_ring_free(r_vec->tx_ring); -err_free_irq: irq_set_affinity_hint(entry->vector, NULL); - free_irq(entry->vector, r_vec); -err_napi_del: netif_napi_del(&r_vec->napi); - __nfp_net_free_rings(nn, r); - return err; + free_irq(entry->vector, r_vec); } /** @@ -1736,9 +1685,19 @@ static int nfp_net_netdev_open(struct net_device *netdev) goto err_free_exn; disable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); - err = nfp_net_alloc_rings(nn); - if (err) - goto err_free_lsc; + for (r = 0; r < nn->num_r_vecs; r++) { + err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r); + if (err) + goto err_free_prev_vecs; + + err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring); + if (err) + goto err_cleanup_vec_p; + + err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring); + if (err) + goto err_free_tx_ring_p; + } err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); if (err) @@ -1831,8 +1790,15 @@ static int nfp_net_netdev_open(struct net_device *netdev) err_clear_config: nfp_net_clear_config_and_disable(nn); err_free_rings: - nfp_net_free_rings(nn); -err_free_lsc: + r = nn->num_r_vecs; +err_free_prev_vecs: + while (r--) { + nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); +err_free_tx_ring_p: + nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); +err_cleanup_vec_p: + nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); + } nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); err_free_exn: nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); @@ -1873,9 +1839,11 @@ static int nfp_net_netdev_close(struct net_device *netdev) for (r = 0; r < nn->num_r_vecs; r++) { nfp_net_rx_flush(nn->r_vecs[r].rx_ring); nfp_net_tx_flush(nn->r_vecs[r].tx_ring); + nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); + nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); + nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); } - nfp_net_free_rings(nn); nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); -- GitLab From d79737c25e4a170e7cd75866e45042de746934d8 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:37 +0100 Subject: [PATCH 1841/9938] nfp: make *x_ring_init do all the init nfp_net_[rt]x_ring_init functions used to be called from probe path only and some of their functionality was spilled to the call site. In order to reuse them for ring reconfiguration we need them to do all the init. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 8692587904c5..7cd20fcd631a 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -347,12 +347,18 @@ static irqreturn_t nfp_net_irq_exn(int irq, void *data) /** * nfp_net_tx_ring_init() - Fill in the boilerplate for a TX ring * @tx_ring: TX ring structure + * @r_vec: IRQ vector servicing this ring + * @idx: Ring index */ -static void nfp_net_tx_ring_init(struct nfp_net_tx_ring *tx_ring) +static void +nfp_net_tx_ring_init(struct nfp_net_tx_ring *tx_ring, + struct nfp_net_r_vector *r_vec, unsigned int idx) { - struct nfp_net_r_vector *r_vec = tx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; + tx_ring->idx = idx; + tx_ring->r_vec = r_vec; + tx_ring->qcidx = tx_ring->idx * nn->stride_tx; tx_ring->qcp_q = nn->tx_bar + NFP_QCP_QUEUE_OFF(tx_ring->qcidx); } @@ -360,12 +366,18 @@ static void nfp_net_tx_ring_init(struct nfp_net_tx_ring *tx_ring) /** * nfp_net_rx_ring_init() - Fill in the boilerplate for a RX ring * @rx_ring: RX ring structure + * @r_vec: IRQ vector servicing this ring + * @idx: Ring index */ -static void nfp_net_rx_ring_init(struct nfp_net_rx_ring *rx_ring) +static void +nfp_net_rx_ring_init(struct nfp_net_rx_ring *rx_ring, + struct nfp_net_r_vector *r_vec, unsigned int idx) { - struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; + rx_ring->idx = idx; + rx_ring->r_vec = r_vec; + rx_ring->fl_qcidx = rx_ring->idx * nn->stride_rx; rx_ring->rx_qcidx = rx_ring->fl_qcidx + (nn->stride_rx - 1); @@ -403,14 +415,10 @@ static void nfp_net_irqs_assign(struct net_device *netdev) cpumask_set_cpu(r, &r_vec->affinity_mask); r_vec->tx_ring = &nn->tx_rings[r]; - nn->tx_rings[r].idx = r; - nn->tx_rings[r].r_vec = r_vec; - nfp_net_tx_ring_init(r_vec->tx_ring); + nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, r); r_vec->rx_ring = &nn->rx_rings[r]; - nn->rx_rings[r].idx = r; - nn->rx_rings[r].r_vec = r_vec; - nfp_net_rx_ring_init(r_vec->rx_ring); + nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, r); } } -- GitLab From 73725d9dfd99c5bb1da4d25bbe980231aa48d251 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:38 +0100 Subject: [PATCH 1842/9938] nfp: allocate ring SW structs dynamically To be able to switch rings more easily on config changes allocate them dynamically, separately from nfp_net structure. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 6 ++-- .../ethernet/netronome/nfp/nfp_net_common.c | 28 +++++++++++++++---- .../ethernet/netronome/nfp/nfp_net_debugfs.c | 20 +++++++------ 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 75683fb26734..fc005c982b7d 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -472,6 +472,9 @@ struct nfp_net { u32 rx_offset; + struct nfp_net_tx_ring *tx_rings; + struct nfp_net_rx_ring *rx_rings; + #ifdef CONFIG_PCI_IOV unsigned int num_vfs; struct vf_data_storage *vfinfo; @@ -504,9 +507,6 @@ struct nfp_net { int txd_cnt; int rxd_cnt; - struct nfp_net_tx_ring tx_rings[NFP_NET_MAX_TX_RINGS]; - struct nfp_net_rx_ring rx_rings[NFP_NET_MAX_RX_RINGS]; - u8 num_irqs; u8 num_r_vecs; struct nfp_net_r_vector r_vecs[NFP_NET_MAX_TX_RINGS]; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 7cd20fcd631a..66fab7162b7c 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -413,12 +413,6 @@ static void nfp_net_irqs_assign(struct net_device *netdev) r_vec->irq_idx = NFP_NET_NON_Q_VECTORS + r; cpumask_set_cpu(r, &r_vec->affinity_mask); - - r_vec->tx_ring = &nn->tx_rings[r]; - nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, r); - - r_vec->rx_ring = &nn->rx_rings[r]; - nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, r); } } @@ -1503,6 +1497,12 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx]; int err; + r_vec->tx_ring = &nn->tx_rings[idx]; + nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx); + + r_vec->rx_ring = &nn->rx_rings[idx]; + nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx); + snprintf(r_vec->name, sizeof(r_vec->name), "%s-rxtx-%d", nn->netdev->name, idx); err = request_irq(entry->vector, r_vec->handler, 0, r_vec->name, r_vec); @@ -1693,6 +1693,15 @@ static int nfp_net_netdev_open(struct net_device *netdev) goto err_free_exn; disable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); + nn->rx_rings = kcalloc(nn->num_rx_rings, sizeof(*nn->rx_rings), + GFP_KERNEL); + if (!nn->rx_rings) + goto err_free_lsc; + nn->tx_rings = kcalloc(nn->num_tx_rings, sizeof(*nn->tx_rings), + GFP_KERNEL); + if (!nn->tx_rings) + goto err_free_rx_rings; + for (r = 0; r < nn->num_r_vecs; r++) { err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r); if (err) @@ -1807,6 +1816,10 @@ static int nfp_net_netdev_open(struct net_device *netdev) err_cleanup_vec_p: nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); } + kfree(nn->tx_rings); +err_free_rx_rings: + kfree(nn->rx_rings); +err_free_lsc: nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); err_free_exn: nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); @@ -1852,6 +1865,9 @@ static int nfp_net_netdev_close(struct net_device *netdev) nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); } + kfree(nn->rx_rings); + kfree(nn->tx_rings); + nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c index 4c97c713121c..f86a1f13d27b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c @@ -40,8 +40,9 @@ static struct dentry *nfp_dir; static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data) { - struct nfp_net_rx_ring *rx_ring = file->private; int fl_rd_p, fl_wr_p, rx_rd_p, rx_wr_p, rxd_cnt; + struct nfp_net_r_vector *r_vec = file->private; + struct nfp_net_rx_ring *rx_ring; struct nfp_net_rx_desc *rxd; struct sk_buff *skb; struct nfp_net *nn; @@ -49,9 +50,10 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data) rtnl_lock(); - if (!rx_ring->r_vec || !rx_ring->r_vec->nfp_net) + if (!r_vec->nfp_net || !r_vec->rx_ring) goto out; - nn = rx_ring->r_vec->nfp_net; + nn = r_vec->nfp_net; + rx_ring = r_vec->rx_ring; if (!netif_running(nn->netdev)) goto out; @@ -115,7 +117,8 @@ static const struct file_operations nfp_rx_q_fops = { static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data) { - struct nfp_net_tx_ring *tx_ring = file->private; + struct nfp_net_r_vector *r_vec = file->private; + struct nfp_net_tx_ring *tx_ring; struct nfp_net_tx_desc *txd; int d_rd_p, d_wr_p, txd_cnt; struct sk_buff *skb; @@ -124,9 +127,10 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data) rtnl_lock(); - if (!tx_ring->r_vec || !tx_ring->r_vec->nfp_net) + if (!r_vec->nfp_net || !r_vec->tx_ring) goto out; - nn = tx_ring->r_vec->nfp_net; + nn = r_vec->nfp_net; + tx_ring = r_vec->tx_ring; if (!netif_running(nn->netdev)) goto out; @@ -207,13 +211,13 @@ void nfp_net_debugfs_adapter_add(struct nfp_net *nn) for (i = 0; i < nn->num_rx_rings; i++) { sprintf(int_name, "%d", i); debugfs_create_file(int_name, S_IRUSR, rx, - &nn->rx_rings[i], &nfp_rx_q_fops); + &nn->r_vecs[i], &nfp_rx_q_fops); } for (i = 0; i < nn->num_tx_rings; i++) { sprintf(int_name, "%d", i); debugfs_create_file(int_name, S_IRUSR, tx, - &nn->tx_rings[i], &nfp_tx_q_fops); + &nn->r_vecs[i], &nfp_tx_q_fops); } } -- GitLab From 827deea9bcd8fec3b6c0acf0178a5c508f3dfbe1 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:39 +0100 Subject: [PATCH 1843/9938] nfp: cleanup tx ring flush and rename to reset Since we never used flush without freeing the ring later the functionality of the two operations is mixed. Rename flush to ring reset and move there all the things which have to be done after FW ring state is cleared. While at it do some clean-ups. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 81 +++++++++---------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 66fab7162b7c..61f243760ee0 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -867,61 +867,59 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring) } /** - * nfp_net_tx_flush() - Free any untransmitted buffers currently on the TX ring - * @tx_ring: TX ring structure + * nfp_net_tx_ring_reset() - Free any untransmitted buffers and reset pointers + * @nn: NFP Net device + * @tx_ring: TX ring structure * * Assumes that the device is stopped */ -static void nfp_net_tx_flush(struct nfp_net_tx_ring *tx_ring) +static void +nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring) { - struct nfp_net_r_vector *r_vec = tx_ring->r_vec; - struct nfp_net *nn = r_vec->nfp_net; - struct pci_dev *pdev = nn->pdev; const struct skb_frag_struct *frag; struct netdev_queue *nd_q; - struct sk_buff *skb; - int nr_frags; - int fidx; - int idx; + struct pci_dev *pdev = nn->pdev; while (tx_ring->rd_p != tx_ring->wr_p) { - idx = tx_ring->rd_p % tx_ring->cnt; + int nr_frags, fidx, idx; + struct sk_buff *skb; + idx = tx_ring->rd_p % tx_ring->cnt; skb = tx_ring->txbufs[idx].skb; - if (skb) { - nr_frags = skb_shinfo(skb)->nr_frags; - fidx = tx_ring->txbufs[idx].fidx; - - if (fidx == -1) { - /* unmap head */ - dma_unmap_single(&pdev->dev, - tx_ring->txbufs[idx].dma_addr, - skb_headlen(skb), - DMA_TO_DEVICE); - } else { - /* unmap fragment */ - frag = &skb_shinfo(skb)->frags[fidx]; - dma_unmap_page(&pdev->dev, - tx_ring->txbufs[idx].dma_addr, - skb_frag_size(frag), - DMA_TO_DEVICE); - } - - /* check for last gather fragment */ - if (fidx == nr_frags - 1) - dev_kfree_skb_any(skb); - - tx_ring->txbufs[idx].dma_addr = 0; - tx_ring->txbufs[idx].skb = NULL; - tx_ring->txbufs[idx].fidx = -2; + nr_frags = skb_shinfo(skb)->nr_frags; + fidx = tx_ring->txbufs[idx].fidx; + + if (fidx == -1) { + /* unmap head */ + dma_unmap_single(&pdev->dev, + tx_ring->txbufs[idx].dma_addr, + skb_headlen(skb), DMA_TO_DEVICE); + } else { + /* unmap fragment */ + frag = &skb_shinfo(skb)->frags[fidx]; + dma_unmap_page(&pdev->dev, + tx_ring->txbufs[idx].dma_addr, + skb_frag_size(frag), DMA_TO_DEVICE); } - memset(&tx_ring->txds[idx], 0, sizeof(tx_ring->txds[idx])); + /* check for last gather fragment */ + if (fidx == nr_frags - 1) + dev_kfree_skb_any(skb); + + tx_ring->txbufs[idx].dma_addr = 0; + tx_ring->txbufs[idx].skb = NULL; + tx_ring->txbufs[idx].fidx = -2; tx_ring->qcp_rd_p++; tx_ring->rd_p++; } + memset(tx_ring->txds, 0, sizeof(*tx_ring->txds) * tx_ring->cnt); + tx_ring->wr_p = 0; + tx_ring->rd_p = 0; + tx_ring->qcp_rd_p = 0; + tx_ring->wr_ptr_add = 0; + nd_q = netdev_get_tx_queue(nn->netdev, tx_ring->idx); netdev_tx_reset_queue(nd_q); } @@ -1362,11 +1360,6 @@ static void nfp_net_tx_ring_free(struct nfp_net_tx_ring *tx_ring) tx_ring->txds, tx_ring->dma); tx_ring->cnt = 0; - tx_ring->wr_p = 0; - tx_ring->rd_p = 0; - tx_ring->qcp_rd_p = 0; - tx_ring->wr_ptr_add = 0; - tx_ring->txbufs = NULL; tx_ring->txds = NULL; tx_ring->dma = 0; @@ -1859,7 +1852,7 @@ static int nfp_net_netdev_close(struct net_device *netdev) */ for (r = 0; r < nn->num_r_vecs; r++) { nfp_net_rx_flush(nn->r_vecs[r].rx_ring); - nfp_net_tx_flush(nn->r_vecs[r].tx_ring); + nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring); nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); -- GitLab From 1934680f5582b69a708181741cd77473a0d530ed Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:40 +0100 Subject: [PATCH 1844/9938] nfp: reorganize initial filling of RX rings Separate allocation of buffers from giving them to FW, thanks to this it will be possible to move allocation earlier on .ndo_open() path and reuse buffers during runtime reconfiguration. Similar to TX side clean up the spill of functionality from flush to freeing the ring. Unlike on TX side, RX ring reset does not free buffers from the ring. Ring reset means only that FW pointers are zeroed and buffers on the ring must be placed in [0, cnt - 1) positions. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 119 ++++++++++++------ 1 file changed, 78 insertions(+), 41 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 61f243760ee0..0c3c37ad28a4 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1020,61 +1020,99 @@ static void nfp_net_rx_give_one(struct nfp_net_rx_ring *rx_ring, } /** - * nfp_net_rx_flush() - Free any buffers currently on the RX ring - * @rx_ring: RX ring to remove buffers from + * nfp_net_rx_ring_reset() - Reflect in SW state of freelist after disable + * @rx_ring: RX ring structure * - * Assumes that the device is stopped + * Warning: Do *not* call if ring buffers were never put on the FW freelist + * (i.e. device was not enabled)! */ -static void nfp_net_rx_flush(struct nfp_net_rx_ring *rx_ring) +static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) { - struct nfp_net *nn = rx_ring->r_vec->nfp_net; - struct pci_dev *pdev = nn->pdev; - int idx; + unsigned int wr_idx, last_idx; - while (rx_ring->rd_p != rx_ring->wr_p) { - idx = rx_ring->rd_p % rx_ring->cnt; + /* Move the empty entry to the end of the list */ + wr_idx = rx_ring->wr_p % rx_ring->cnt; + last_idx = rx_ring->cnt - 1; + rx_ring->rxbufs[wr_idx].dma_addr = rx_ring->rxbufs[last_idx].dma_addr; + rx_ring->rxbufs[wr_idx].skb = rx_ring->rxbufs[last_idx].skb; + rx_ring->rxbufs[last_idx].dma_addr = 0; + rx_ring->rxbufs[last_idx].skb = NULL; - if (rx_ring->rxbufs[idx].skb) { - dma_unmap_single(&pdev->dev, - rx_ring->rxbufs[idx].dma_addr, - nn->fl_bufsz, DMA_FROM_DEVICE); - dev_kfree_skb_any(rx_ring->rxbufs[idx].skb); - rx_ring->rxbufs[idx].dma_addr = 0; - rx_ring->rxbufs[idx].skb = NULL; - } + memset(rx_ring->rxds, 0, sizeof(*rx_ring->rxds) * rx_ring->cnt); + rx_ring->wr_p = 0; + rx_ring->rd_p = 0; + rx_ring->wr_ptr_add = 0; +} - memset(&rx_ring->rxds[idx], 0, sizeof(rx_ring->rxds[idx])); +/** + * nfp_net_rx_ring_bufs_free() - Free any buffers currently on the RX ring + * @nn: NFP Net device + * @rx_ring: RX ring to remove buffers from + * + * Assumes that the device is stopped and buffers are in [0, ring->cnt - 1) + * entries. After device is disabled nfp_net_rx_ring_reset() must be called + * to restore required ring geometry. + */ +static void +nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) +{ + struct pci_dev *pdev = nn->pdev; + unsigned int i; - rx_ring->rd_p++; + for (i = 0; i < rx_ring->cnt - 1; i++) { + /* NULL skb can only happen when initial filling of the ring + * fails to allocate enough buffers and calls here to free + * already allocated ones. + */ + if (!rx_ring->rxbufs[i].skb) + continue; + + dma_unmap_single(&pdev->dev, rx_ring->rxbufs[i].dma_addr, + nn->fl_bufsz, DMA_FROM_DEVICE); + dev_kfree_skb_any(rx_ring->rxbufs[i].skb); + rx_ring->rxbufs[i].dma_addr = 0; + rx_ring->rxbufs[i].skb = NULL; } } /** - * nfp_net_rx_fill_freelist() - Attempt filling freelist with RX buffers - * @rx_ring: RX ring to fill - * - * Try to fill as many buffers as possible into freelist. Return - * number of buffers added. - * - * Return: Number of freelist buffers added. + * nfp_net_rx_ring_bufs_alloc() - Fill RX ring with buffers (don't give to FW) + * @nn: NFP Net device + * @rx_ring: RX ring to remove buffers from */ -static int nfp_net_rx_fill_freelist(struct nfp_net_rx_ring *rx_ring) +static int +nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) { - struct sk_buff *skb; - dma_addr_t dma_addr; + struct nfp_net_rx_buf *rxbufs; + unsigned int i; + + rxbufs = rx_ring->rxbufs; - while (nfp_net_rx_space(rx_ring)) { - skb = nfp_net_rx_alloc_one(rx_ring, &dma_addr); - if (!skb) { - nfp_net_rx_flush(rx_ring); + for (i = 0; i < rx_ring->cnt - 1; i++) { + rxbufs[i].skb = + nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr); + if (!rxbufs[i].skb) { + nfp_net_rx_ring_bufs_free(nn, rx_ring); return -ENOMEM; } - nfp_net_rx_give_one(rx_ring, skb, dma_addr); } return 0; } +/** + * nfp_net_rx_ring_fill_freelist() - Give buffers from the ring to FW + * @rx_ring: RX ring to fill + */ +static void nfp_net_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring) +{ + unsigned int i; + + for (i = 0; i < rx_ring->cnt - 1; i++) + nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[i].skb, + rx_ring->rxbufs[i].dma_addr); +} + /** * nfp_net_rx_csum_has_errors() - group check if rxd has any csum errors * @flags: RX descriptor flags field in CPU byte order @@ -1431,10 +1469,6 @@ static void nfp_net_rx_ring_free(struct nfp_net_rx_ring *rx_ring) rx_ring->rxds, rx_ring->dma); rx_ring->cnt = 0; - rx_ring->wr_p = 0; - rx_ring->rd_p = 0; - rx_ring->wr_ptr_add = 0; - rx_ring->rxbufs = NULL; rx_ring->rxds = NULL; rx_ring->dma = 0; @@ -1641,12 +1675,13 @@ static int nfp_net_start_vec(struct nfp_net *nn, struct nfp_net_r_vector *r_vec) disable_irq(irq_vec); - err = nfp_net_rx_fill_freelist(r_vec->rx_ring); + err = nfp_net_rx_ring_bufs_alloc(r_vec->nfp_net, r_vec->rx_ring); if (err) { nn_err(nn, "RV%02d: couldn't allocate enough buffers\n", r_vec->irq_idx); goto out; } + nfp_net_rx_ring_fill_freelist(r_vec->rx_ring); napi_enable(&r_vec->napi); out: @@ -1795,7 +1830,8 @@ static int nfp_net_netdev_open(struct net_device *netdev) err_disable_napi: while (r--) { napi_disable(&nn->r_vecs[r].napi); - nfp_net_rx_flush(nn->r_vecs[r].rx_ring); + nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); + nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); } err_clear_config: nfp_net_clear_config_and_disable(nn); @@ -1851,7 +1887,8 @@ static int nfp_net_netdev_close(struct net_device *netdev) /* Step 3: Free resources */ for (r = 0; r < nn->num_r_vecs; r++) { - nfp_net_rx_flush(nn->r_vecs[r].rx_ring); + nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); + nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring); nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); -- GitLab From 114bdef0be28aa9aa71e291d133e79edd514f8dc Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:41 +0100 Subject: [PATCH 1845/9938] nfp: preallocate RX buffers early in .ndo_open We want the .ndo_open() to have following structure: - allocate resources; - configure HW/FW; - enable the device from stack perspective. Therefore filling RX rings needs to be moved to the beginning of .ndo_open(). Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 0c3c37ad28a4..a6a917fe8e31 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1666,28 +1666,19 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) * @nn: NFP Net device structure * @r_vec: Ring vector to be started */ -static int nfp_net_start_vec(struct nfp_net *nn, struct nfp_net_r_vector *r_vec) +static void +nfp_net_start_vec(struct nfp_net *nn, struct nfp_net_r_vector *r_vec) { unsigned int irq_vec; - int err = 0; irq_vec = nn->irq_entries[r_vec->irq_idx].vector; disable_irq(irq_vec); - err = nfp_net_rx_ring_bufs_alloc(r_vec->nfp_net, r_vec->rx_ring); - if (err) { - nn_err(nn, "RV%02d: couldn't allocate enough buffers\n", - r_vec->irq_idx); - goto out; - } nfp_net_rx_ring_fill_freelist(r_vec->rx_ring); - napi_enable(&r_vec->napi); -out: - enable_irq(irq_vec); - return err; + enable_irq(irq_vec); } static int nfp_net_netdev_open(struct net_device *netdev) @@ -1742,6 +1733,10 @@ static int nfp_net_netdev_open(struct net_device *netdev) err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring); if (err) goto err_free_tx_ring_p; + + err = nfp_net_rx_ring_bufs_alloc(nn, nn->r_vecs[r].rx_ring); + if (err) + goto err_flush_rx_ring_p; } err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); @@ -1814,11 +1809,8 @@ static int nfp_net_netdev_open(struct net_device *netdev) * - enable all TX queues * - set link state */ - for (r = 0; r < nn->num_r_vecs; r++) { - err = nfp_net_start_vec(nn, &nn->r_vecs[r]); - if (err) - goto err_disable_napi; - } + for (r = 0; r < nn->num_r_vecs; r++) + nfp_net_start_vec(nn, &nn->r_vecs[r]); netif_tx_wake_all_queues(netdev); @@ -1827,18 +1819,14 @@ static int nfp_net_netdev_open(struct net_device *netdev) return 0; -err_disable_napi: - while (r--) { - napi_disable(&nn->r_vecs[r].napi); - nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); - nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); - } err_clear_config: nfp_net_clear_config_and_disable(nn); err_free_rings: r = nn->num_r_vecs; err_free_prev_vecs: while (r--) { + nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); +err_flush_rx_ring_p: nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); err_free_tx_ring_p: nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); -- GitLab From ca40feab8f3d46a69bde7a13d652db2c9246c067 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:42 +0100 Subject: [PATCH 1846/9938] nfp: move filling ring information to FW config nfp_net_[rt]x_ring_{alloc,free} should only allocate or free ring resources without touching the device. Move setting parameters in the BAR to separate functions. This will make it possible to reuse alloc/free functions to allocate new rings while the device is running. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index a6a917fe8e31..342335d09fb2 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1387,10 +1387,6 @@ static void nfp_net_tx_ring_free(struct nfp_net_tx_ring *tx_ring) struct nfp_net *nn = r_vec->nfp_net; struct pci_dev *pdev = nn->pdev; - nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(tx_ring->idx), 0); - nn_writeb(nn, NFP_NET_CFG_TXR_SZ(tx_ring->idx), 0); - nn_writeb(nn, NFP_NET_CFG_TXR_VEC(tx_ring->idx), 0); - kfree(tx_ring->txbufs); if (tx_ring->txds) @@ -1430,11 +1426,6 @@ static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring) if (!tx_ring->txbufs) goto err_alloc; - /* Write the DMA address, size and MSI-X info to the device */ - nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(tx_ring->idx), tx_ring->dma); - nn_writeb(nn, NFP_NET_CFG_TXR_SZ(tx_ring->idx), ilog2(tx_ring->cnt)); - nn_writeb(nn, NFP_NET_CFG_TXR_VEC(tx_ring->idx), r_vec->irq_idx); - netif_set_xps_queue(nn->netdev, &r_vec->affinity_mask, tx_ring->idx); nn_dbg(nn, "TxQ%02d: QCidx=%02d cnt=%d dma=%#llx host=%p\n", @@ -1458,10 +1449,6 @@ static void nfp_net_rx_ring_free(struct nfp_net_rx_ring *rx_ring) struct nfp_net *nn = r_vec->nfp_net; struct pci_dev *pdev = nn->pdev; - nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(rx_ring->idx), 0); - nn_writeb(nn, NFP_NET_CFG_RXR_SZ(rx_ring->idx), 0); - nn_writeb(nn, NFP_NET_CFG_RXR_VEC(rx_ring->idx), 0); - kfree(rx_ring->rxbufs); if (rx_ring->rxds) @@ -1501,11 +1488,6 @@ static int nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring) if (!rx_ring->rxbufs) goto err_alloc; - /* Write the DMA address, size and MSI-X info to the device */ - nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(rx_ring->idx), rx_ring->dma); - nn_writeb(nn, NFP_NET_CFG_RXR_SZ(rx_ring->idx), ilog2(rx_ring->cnt)); - nn_writeb(nn, NFP_NET_CFG_RXR_VEC(rx_ring->idx), r_vec->irq_idx); - nn_dbg(nn, "RxQ%02d: FlQCidx=%02d RxQCidx=%02d cnt=%d dma=%#llx host=%p\n", rx_ring->idx, rx_ring->fl_qcidx, rx_ring->rx_qcidx, rx_ring->cnt, (unsigned long long)rx_ring->dma, rx_ring->rxds); @@ -1630,6 +1612,17 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn, const u8 *mac) get_unaligned_be16(nn->netdev->dev_addr + 4) << 16); } +static void nfp_net_vec_clear_ring_data(struct nfp_net *nn, unsigned int idx) +{ + nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), 0); + nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), 0); + nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), 0); + + nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), 0); + nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), 0); + nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), 0); +} + /** * nfp_net_clear_config_and_disable() - Clear control BAR and disable NFP * @nn: NFP Net device to reconfigure @@ -1637,6 +1630,7 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn, const u8 *mac) static void nfp_net_clear_config_and_disable(struct nfp_net *nn) { u32 new_ctrl, update; + unsigned int r; int err; new_ctrl = nn->ctrl; @@ -1658,9 +1652,26 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) return; } + for (r = 0; r < nn->num_r_vecs; r++) + nfp_net_vec_clear_ring_data(nn, r); + nn->ctrl = new_ctrl; } +static void +nfp_net_vec_write_ring_data(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, + unsigned int idx) +{ + /* Write the DMA address, size and MSI-X info to the device */ + nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), r_vec->rx_ring->dma); + nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(r_vec->rx_ring->cnt)); + nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), r_vec->irq_idx); + + nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), r_vec->tx_ring->dma); + nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(r_vec->tx_ring->cnt)); + nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx); +} + /** * nfp_net_start_vec() - Start ring vector * @nn: NFP Net device structure @@ -1768,6 +1779,9 @@ static int nfp_net_netdev_open(struct net_device *netdev) * - Set the Freelist buffer size * - Enable the FW */ + for (r = 0; r < nn->num_r_vecs; r++) + nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r); + nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ? 0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1); -- GitLab From 1cd0cfc498f7e928c5ff8e9ced537d41fa46df50 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:43 +0100 Subject: [PATCH 1847/9938] nfp: slice .ndo_open() and .ndo_stop() up Divide .ndo_open() and .ndo_stop() into logical, callable chunks. No functional changes. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 218 +++++++++++------- 1 file changed, 136 insertions(+), 82 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 342335d09fb2..6c1ed8914416 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1672,6 +1672,82 @@ nfp_net_vec_write_ring_data(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx); } +static int __nfp_net_set_config_and_enable(struct nfp_net *nn) +{ + u32 new_ctrl, update = 0; + unsigned int r; + int err; + + new_ctrl = nn->ctrl; + + if (nn->cap & NFP_NET_CFG_CTRL_RSS) { + nfp_net_rss_write_key(nn); + nfp_net_rss_write_itbl(nn); + nn_writel(nn, NFP_NET_CFG_RSS_CTRL, nn->rss_cfg); + update |= NFP_NET_CFG_UPDATE_RSS; + } + + if (nn->cap & NFP_NET_CFG_CTRL_IRQMOD) { + nfp_net_coalesce_write_cfg(nn); + + new_ctrl |= NFP_NET_CFG_CTRL_IRQMOD; + update |= NFP_NET_CFG_UPDATE_IRQMOD; + } + + for (r = 0; r < nn->num_r_vecs; r++) + nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r); + + nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ? + 0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1); + + nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, nn->num_rx_rings == 64 ? + 0xffffffffffffffffULL : ((u64)1 << nn->num_rx_rings) - 1); + + nfp_net_write_mac_addr(nn, nn->netdev->dev_addr); + + nn_writel(nn, NFP_NET_CFG_MTU, nn->netdev->mtu); + nn_writel(nn, NFP_NET_CFG_FLBUFSZ, nn->fl_bufsz); + + /* Enable device */ + new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; + update |= NFP_NET_CFG_UPDATE_GEN; + update |= NFP_NET_CFG_UPDATE_MSIX; + update |= NFP_NET_CFG_UPDATE_RING; + if (nn->cap & NFP_NET_CFG_CTRL_RINGCFG) + new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG; + + nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); + err = nfp_net_reconfig(nn, update); + + nn->ctrl = new_ctrl; + + /* Since reconfiguration requests while NFP is down are ignored we + * have to wipe the entire VXLAN configuration and reinitialize it. + */ + if (nn->ctrl & NFP_NET_CFG_CTRL_VXLAN) { + memset(&nn->vxlan_ports, 0, sizeof(nn->vxlan_ports)); + memset(&nn->vxlan_usecnt, 0, sizeof(nn->vxlan_usecnt)); + vxlan_get_rx_port(nn->netdev); + } + + return err; +} + +/** + * nfp_net_set_config_and_enable() - Write control BAR and enable NFP + * @nn: NFP Net device to reconfigure + */ +static int nfp_net_set_config_and_enable(struct nfp_net *nn) +{ + int err; + + err = __nfp_net_set_config_and_enable(nn); + if (err) + nfp_net_clear_config_and_disable(nn); + + return err; +} + /** * nfp_net_start_vec() - Start ring vector * @nn: NFP Net device structure @@ -1692,20 +1768,33 @@ nfp_net_start_vec(struct nfp_net *nn, struct nfp_net_r_vector *r_vec) enable_irq(irq_vec); } +/** + * nfp_net_open_stack() - Start the device from stack's perspective + * @nn: NFP Net device to reconfigure + */ +static void nfp_net_open_stack(struct nfp_net *nn) +{ + unsigned int r; + + for (r = 0; r < nn->num_r_vecs; r++) + nfp_net_start_vec(nn, &nn->r_vecs[r]); + + netif_tx_wake_all_queues(nn->netdev); + + enable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); + nfp_net_read_link_status(nn); +} + static int nfp_net_netdev_open(struct net_device *netdev) { struct nfp_net *nn = netdev_priv(netdev); int err, r; - u32 update = 0; - u32 new_ctrl; if (nn->ctrl & NFP_NET_CFG_CTRL_ENABLE) { nn_err(nn, "Dev is already enabled: 0x%08x\n", nn->ctrl); return -EBUSY; } - new_ctrl = nn->ctrl; - /* Step 1: Allocate resources for rings and the like * - Request interrupts * - Allocate RX and TX ring resources @@ -1758,20 +1847,6 @@ static int nfp_net_netdev_open(struct net_device *netdev) if (err) goto err_free_rings; - if (nn->cap & NFP_NET_CFG_CTRL_RSS) { - nfp_net_rss_write_key(nn); - nfp_net_rss_write_itbl(nn); - nn_writel(nn, NFP_NET_CFG_RSS_CTRL, nn->rss_cfg); - update |= NFP_NET_CFG_UPDATE_RSS; - } - - if (nn->cap & NFP_NET_CFG_CTRL_IRQMOD) { - nfp_net_coalesce_write_cfg(nn); - - new_ctrl |= NFP_NET_CFG_CTRL_IRQMOD; - update |= NFP_NET_CFG_UPDATE_IRQMOD; - } - /* Step 2: Configure the NFP * - Enable rings from 0 to tx_rings/rx_rings - 1. * - Write MAC address (in case it changed) @@ -1779,43 +1854,9 @@ static int nfp_net_netdev_open(struct net_device *netdev) * - Set the Freelist buffer size * - Enable the FW */ - for (r = 0; r < nn->num_r_vecs; r++) - nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r); - - nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ? - 0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1); - - nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, nn->num_rx_rings == 64 ? - 0xffffffffffffffffULL : ((u64)1 << nn->num_rx_rings) - 1); - - nfp_net_write_mac_addr(nn, netdev->dev_addr); - - nn_writel(nn, NFP_NET_CFG_MTU, netdev->mtu); - nn_writel(nn, NFP_NET_CFG_FLBUFSZ, nn->fl_bufsz); - - /* Enable device */ - new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; - update |= NFP_NET_CFG_UPDATE_GEN; - update |= NFP_NET_CFG_UPDATE_MSIX; - update |= NFP_NET_CFG_UPDATE_RING; - if (nn->cap & NFP_NET_CFG_CTRL_RINGCFG) - new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG; - - nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); - err = nfp_net_reconfig(nn, update); + err = nfp_net_set_config_and_enable(nn); if (err) - goto err_clear_config; - - nn->ctrl = new_ctrl; - - /* Since reconfiguration requests while NFP is down are ignored we - * have to wipe the entire VXLAN configuration and reinitialize it. - */ - if (nn->ctrl & NFP_NET_CFG_CTRL_VXLAN) { - memset(&nn->vxlan_ports, 0, sizeof(nn->vxlan_ports)); - memset(&nn->vxlan_usecnt, 0, sizeof(nn->vxlan_usecnt)); - vxlan_get_rx_port(netdev); - } + goto err_free_rings; /* Step 3: Enable for kernel * - put some freelist descriptors on each RX ring @@ -1823,18 +1864,10 @@ static int nfp_net_netdev_open(struct net_device *netdev) * - enable all TX queues * - set link state */ - for (r = 0; r < nn->num_r_vecs; r++) - nfp_net_start_vec(nn, &nn->r_vecs[r]); - - netif_tx_wake_all_queues(netdev); - - enable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); - nfp_net_read_link_status(nn); + nfp_net_open_stack(nn); return 0; -err_clear_config: - nfp_net_clear_config_and_disable(nn); err_free_rings: r = nn->num_r_vecs; err_free_prev_vecs: @@ -1858,36 +1891,31 @@ static int nfp_net_netdev_open(struct net_device *netdev) } /** - * nfp_net_netdev_close() - Called when the device is downed - * @netdev: netdev structure + * nfp_net_close_stack() - Quiescent the stack (part of close) + * @nn: NFP Net device to reconfigure */ -static int nfp_net_netdev_close(struct net_device *netdev) +static void nfp_net_close_stack(struct nfp_net *nn) { - struct nfp_net *nn = netdev_priv(netdev); - int r; - - if (!(nn->ctrl & NFP_NET_CFG_CTRL_ENABLE)) { - nn_err(nn, "Dev is not up: 0x%08x\n", nn->ctrl); - return 0; - } + unsigned int r; - /* Step 1: Disable RX and TX rings from the Linux kernel perspective - */ disable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector); - netif_carrier_off(netdev); + netif_carrier_off(nn->netdev); nn->link_up = false; for (r = 0; r < nn->num_r_vecs; r++) napi_disable(&nn->r_vecs[r].napi); - netif_tx_disable(netdev); + netif_tx_disable(nn->netdev); +} - /* Step 2: Tell NFP - */ - nfp_net_clear_config_and_disable(nn); +/** + * nfp_net_close_free_all() - Free all runtime resources + * @nn: NFP Net device to reconfigure + */ +static void nfp_net_close_free_all(struct nfp_net *nn) +{ + unsigned int r; - /* Step 3: Free resources - */ for (r = 0; r < nn->num_r_vecs; r++) { nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); @@ -1902,6 +1930,32 @@ static int nfp_net_netdev_close(struct net_device *netdev) nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX); nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX); +} + +/** + * nfp_net_netdev_close() - Called when the device is downed + * @netdev: netdev structure + */ +static int nfp_net_netdev_close(struct net_device *netdev) +{ + struct nfp_net *nn = netdev_priv(netdev); + + if (!(nn->ctrl & NFP_NET_CFG_CTRL_ENABLE)) { + nn_err(nn, "Dev is not up: 0x%08x\n", nn->ctrl); + return 0; + } + + /* Step 1: Disable RX and TX rings from the Linux kernel perspective + */ + nfp_net_close_stack(nn); + + /* Step 2: Tell NFP + */ + nfp_net_clear_config_and_disable(nn); + + /* Step 3: Free resources + */ + nfp_net_close_free_all(nn); nn_dbg(nn, "%s down", netdev->name); return 0; -- GitLab From aba52df80b1a2d15fe1745dfe187e9823821f5c0 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:44 +0100 Subject: [PATCH 1848/9938] nfp: sync ring state during FW reconfiguration FW reconfiguration in .ndo_open()/.ndo_stop() should reset/ restore queue state. Since we need IRQs to be disabled when filling rings on RX path we have to move disable_irq() from .ndo_open() all the way up to IRQ allocation. nfp_net_start_vec() becomes trivial now so it's inlined. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 45 +++++++------------ 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 6c1ed8914416..ed23b9d348c3 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1519,6 +1519,7 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, nn_err(nn, "Error requesting IRQ %d\n", entry->vector); return err; } + disable_irq(entry->vector); /* Setup NAPI */ netif_napi_add(nn->netdev, &r_vec->napi, @@ -1647,13 +1648,14 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); err = nfp_net_reconfig(nn, update); - if (err) { + if (err) nn_err(nn, "Could not disable device: %d\n", err); - return; - } - for (r = 0; r < nn->num_r_vecs; r++) + for (r = 0; r < nn->num_r_vecs; r++) { + nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); + nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring); nfp_net_vec_clear_ring_data(nn, r); + } nn->ctrl = new_ctrl; } @@ -1721,6 +1723,9 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn) nn->ctrl = new_ctrl; + for (r = 0; r < nn->num_r_vecs; r++) + nfp_net_rx_ring_fill_freelist(nn->r_vecs[r].rx_ring); + /* Since reconfiguration requests while NFP is down are ignored we * have to wipe the entire VXLAN configuration and reinitialize it. */ @@ -1748,26 +1753,6 @@ static int nfp_net_set_config_and_enable(struct nfp_net *nn) return err; } -/** - * nfp_net_start_vec() - Start ring vector - * @nn: NFP Net device structure - * @r_vec: Ring vector to be started - */ -static void -nfp_net_start_vec(struct nfp_net *nn, struct nfp_net_r_vector *r_vec) -{ - unsigned int irq_vec; - - irq_vec = nn->irq_entries[r_vec->irq_idx].vector; - - disable_irq(irq_vec); - - nfp_net_rx_ring_fill_freelist(r_vec->rx_ring); - napi_enable(&r_vec->napi); - - enable_irq(irq_vec); -} - /** * nfp_net_open_stack() - Start the device from stack's perspective * @nn: NFP Net device to reconfigure @@ -1776,8 +1761,10 @@ static void nfp_net_open_stack(struct nfp_net *nn) { unsigned int r; - for (r = 0; r < nn->num_r_vecs; r++) - nfp_net_start_vec(nn, &nn->r_vecs[r]); + for (r = 0; r < nn->num_r_vecs; r++) { + napi_enable(&nn->r_vecs[r].napi); + enable_irq(nn->irq_entries[nn->r_vecs[r].irq_idx].vector); + } netif_tx_wake_all_queues(nn->netdev); @@ -1902,8 +1889,10 @@ static void nfp_net_close_stack(struct nfp_net *nn) netif_carrier_off(nn->netdev); nn->link_up = false; - for (r = 0; r < nn->num_r_vecs; r++) + for (r = 0; r < nn->num_r_vecs; r++) { + disable_irq(nn->irq_entries[nn->r_vecs[r].irq_idx].vector); napi_disable(&nn->r_vecs[r].napi); + } netif_tx_disable(nn->netdev); } @@ -1917,9 +1906,7 @@ static void nfp_net_close_free_all(struct nfp_net *nn) unsigned int r; for (r = 0; r < nn->num_r_vecs; r++) { - nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); - nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring); nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); -- GitLab From 30d2117191b7437b5b6ce2f09eddf86f203c7a37 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:45 +0100 Subject: [PATCH 1849/9938] nfp: propagate list buffer size in struct rx_ring Free list buffer size needs to be propagated to few functions as a parameter and added to struct nfp_net_rx_ring since soon some of the functions will be reused to manage rings with buffers of size different than nn->fl_bufsz. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 3 +++ .../ethernet/netronome/nfp/nfp_net_common.c | 24 ++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index fc005c982b7d..9ab8e3967dc9 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -298,6 +298,8 @@ struct nfp_net_rx_buf { * @rxds: Virtual address of FL/RX ring in host memory * @dma: DMA address of the FL/RX ring * @size: Size, in bytes, of the FL/RX ring (needed to free) + * @bufsz: Buffer allocation size for convenience of management routines + * (NOTE: this is in second cache line, do not use on fast path!) */ struct nfp_net_rx_ring { struct nfp_net_r_vector *r_vec; @@ -319,6 +321,7 @@ struct nfp_net_rx_ring { dma_addr_t dma; unsigned int size; + unsigned int bufsz; } ____cacheline_aligned; /** diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index ed23b9d348c3..03c60f755de0 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -957,25 +957,27 @@ static inline int nfp_net_rx_space(struct nfp_net_rx_ring *rx_ring) * nfp_net_rx_alloc_one() - Allocate and map skb for RX * @rx_ring: RX ring structure of the skb * @dma_addr: Pointer to storage for DMA address (output param) + * @fl_bufsz: size of freelist buffers * * This function will allcate a new skb, map it for DMA. * * Return: allocated skb or NULL on failure. */ static struct sk_buff * -nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr) +nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr, + unsigned int fl_bufsz) { struct nfp_net *nn = rx_ring->r_vec->nfp_net; struct sk_buff *skb; - skb = netdev_alloc_skb(nn->netdev, nn->fl_bufsz); + skb = netdev_alloc_skb(nn->netdev, fl_bufsz); if (!skb) { nn_warn_ratelimit(nn, "Failed to alloc receive SKB\n"); return NULL; } *dma_addr = dma_map_single(&nn->pdev->dev, skb->data, - nn->fl_bufsz, DMA_FROM_DEVICE); + fl_bufsz, DMA_FROM_DEVICE); if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) { dev_kfree_skb_any(skb); nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n"); @@ -1068,7 +1070,7 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) continue; dma_unmap_single(&pdev->dev, rx_ring->rxbufs[i].dma_addr, - nn->fl_bufsz, DMA_FROM_DEVICE); + rx_ring->bufsz, DMA_FROM_DEVICE); dev_kfree_skb_any(rx_ring->rxbufs[i].skb); rx_ring->rxbufs[i].dma_addr = 0; rx_ring->rxbufs[i].skb = NULL; @@ -1090,7 +1092,8 @@ nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) for (i = 0; i < rx_ring->cnt - 1; i++) { rxbufs[i].skb = - nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr); + nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr, + rx_ring->bufsz); if (!rxbufs[i].skb) { nfp_net_rx_ring_bufs_free(nn, rx_ring); return -ENOMEM; @@ -1278,7 +1281,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) skb = rx_ring->rxbufs[idx].skb; - new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr); + new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr, + nn->fl_bufsz); if (!new_skb) { nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[idx].skb, rx_ring->rxbufs[idx].dma_addr); @@ -1465,10 +1469,12 @@ static void nfp_net_rx_ring_free(struct nfp_net_rx_ring *rx_ring) /** * nfp_net_rx_ring_alloc() - Allocate resource for a RX ring * @rx_ring: RX ring to allocate + * @fl_bufsz: Size of buffers to allocate * * Return: 0 on success, negative errno otherwise. */ -static int nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring) +static int +nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring, unsigned int fl_bufsz) { struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; @@ -1476,6 +1482,7 @@ static int nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring) int sz; rx_ring->cnt = nn->rxd_cnt; + rx_ring->bufsz = fl_bufsz; rx_ring->size = sizeof(*rx_ring->rxds) * rx_ring->cnt; rx_ring->rxds = dma_zalloc_coherent(&pdev->dev, rx_ring->size, @@ -1817,7 +1824,8 @@ static int nfp_net_netdev_open(struct net_device *netdev) if (err) goto err_cleanup_vec_p; - err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring); + err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring, + nn->fl_bufsz); if (err) goto err_free_tx_ring_p; -- GitLab From 36a857e4f2c9783cd573c948df022011cb386aa4 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:46 +0100 Subject: [PATCH 1850/9938] nfp: convert .ndo_change_mtu() to prepare/commit paradigm When changing MTU on running device first allocate new rings and buffers and once it succeeds proceed with changing MTU. Allocation of new rings is not really necessary for this operation - it's done to keep the code simple and because size of the extra ring memory is quite small compared to the size of buffers. Operation can still fail midway through if FW communication times out. In that case we retry with old MTU (rings). Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 108 +++++++++++++++++- 1 file changed, 102 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 03c60f755de0..e7c420fdcb0d 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1506,6 +1506,64 @@ nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring, unsigned int fl_bufsz) return -ENOMEM; } +static struct nfp_net_rx_ring * +nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, unsigned int fl_bufsz) +{ + struct nfp_net_rx_ring *rings; + unsigned int r; + + rings = kcalloc(nn->num_rx_rings, sizeof(*rings), GFP_KERNEL); + if (!rings) + return NULL; + + for (r = 0; r < nn->num_rx_rings; r++) { + nfp_net_rx_ring_init(&rings[r], nn->rx_rings[r].r_vec, r); + + if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz)) + goto err_free_prev; + + if (nfp_net_rx_ring_bufs_alloc(nn, &rings[r])) + goto err_free_ring; + } + + return rings; + +err_free_prev: + while (r--) { + nfp_net_rx_ring_bufs_free(nn, &rings[r]); +err_free_ring: + nfp_net_rx_ring_free(&rings[r]); + } + kfree(rings); + return NULL; +} + +static struct nfp_net_rx_ring * +nfp_net_shadow_rx_rings_swap(struct nfp_net *nn, struct nfp_net_rx_ring *rings) +{ + struct nfp_net_rx_ring *old = nn->rx_rings; + unsigned int r; + + for (r = 0; r < nn->num_rx_rings; r++) + old[r].r_vec->rx_ring = &rings[r]; + + nn->rx_rings = rings; + return old; +} + +static void +nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings) +{ + unsigned int r; + + for (r = 0; r < nn->num_r_vecs; r++) { + nfp_net_rx_ring_bufs_free(nn, &rings[r]); + nfp_net_rx_ring_free(&rings[r]); + } + + kfree(rings); +} + static int nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, int idx) @@ -1984,23 +2042,61 @@ static void nfp_net_set_rx_mode(struct net_device *netdev) static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) { + unsigned int old_mtu, old_fl_bufsz, new_fl_bufsz; struct nfp_net *nn = netdev_priv(netdev); + struct nfp_net_rx_ring *tmp_rings; + int err; if (new_mtu < 68 || new_mtu > nn->max_mtu) { nn_err(nn, "New MTU (%d) is not valid\n", new_mtu); return -EINVAL; } + old_mtu = netdev->mtu; + old_fl_bufsz = nn->fl_bufsz; + new_fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu; + + if (!netif_running(netdev)) { + netdev->mtu = new_mtu; + nn->fl_bufsz = new_fl_bufsz; + return 0; + } + + /* Prepare new rings */ + tmp_rings = nfp_net_shadow_rx_rings_prepare(nn, new_fl_bufsz); + if (!tmp_rings) + return -ENOMEM; + + /* Stop device, swap in new rings, try to start the firmware */ + nfp_net_close_stack(nn); + nfp_net_clear_config_and_disable(nn); + + tmp_rings = nfp_net_shadow_rx_rings_swap(nn, tmp_rings); + netdev->mtu = new_mtu; - nn->fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu; + nn->fl_bufsz = new_fl_bufsz; + + err = nfp_net_set_config_and_enable(nn); + if (err) { + const int err_new = err; + + /* Try with old configuration and old rings */ + tmp_rings = nfp_net_shadow_rx_rings_swap(nn, tmp_rings); + + netdev->mtu = old_mtu; + nn->fl_bufsz = old_fl_bufsz; - /* restart if running */ - if (netif_running(netdev)) { - nfp_net_netdev_close(netdev); - nfp_net_netdev_open(netdev); + err = __nfp_net_set_config_and_enable(nn); + if (err) + nn_err(nn, "Can't restore MTU - FW communication failed (%d,%d)\n", + err_new, err); } - return 0; + nfp_net_shadow_rx_rings_free(nn, tmp_rings); + + nfp_net_open_stack(nn); + + return err; } static struct rtnl_link_stats64 *nfp_net_stat64(struct net_device *netdev, -- GitLab From a98cb2581211023539887a11f8391dd615409ab8 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:47 +0100 Subject: [PATCH 1851/9938] nfp: pass ring count as function parameter Soon ring resize will call this functions with values different than the current configuration we need to explicitly pass the ring count as parameter. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index e7c420fdcb0d..c4f0c70e77ce 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1407,17 +1407,18 @@ static void nfp_net_tx_ring_free(struct nfp_net_tx_ring *tx_ring) /** * nfp_net_tx_ring_alloc() - Allocate resource for a TX ring * @tx_ring: TX Ring structure to allocate + * @cnt: Ring buffer count * * Return: 0 on success, negative errno otherwise. */ -static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring) +static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt) { struct nfp_net_r_vector *r_vec = tx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; struct pci_dev *pdev = nn->pdev; int sz; - tx_ring->cnt = nn->txd_cnt; + tx_ring->cnt = cnt; tx_ring->size = sizeof(*tx_ring->txds) * tx_ring->cnt; tx_ring->txds = dma_zalloc_coherent(&pdev->dev, tx_ring->size, @@ -1470,18 +1471,20 @@ static void nfp_net_rx_ring_free(struct nfp_net_rx_ring *rx_ring) * nfp_net_rx_ring_alloc() - Allocate resource for a RX ring * @rx_ring: RX ring to allocate * @fl_bufsz: Size of buffers to allocate + * @cnt: Ring buffer count * * Return: 0 on success, negative errno otherwise. */ static int -nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring, unsigned int fl_bufsz) +nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring, unsigned int fl_bufsz, + u32 cnt) { struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; struct pci_dev *pdev = nn->pdev; int sz; - rx_ring->cnt = nn->rxd_cnt; + rx_ring->cnt = cnt; rx_ring->bufsz = fl_bufsz; rx_ring->size = sizeof(*rx_ring->rxds) * rx_ring->cnt; @@ -1507,7 +1510,8 @@ nfp_net_rx_ring_alloc(struct nfp_net_rx_ring *rx_ring, unsigned int fl_bufsz) } static struct nfp_net_rx_ring * -nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, unsigned int fl_bufsz) +nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, unsigned int fl_bufsz, + u32 buf_cnt) { struct nfp_net_rx_ring *rings; unsigned int r; @@ -1519,7 +1523,7 @@ nfp_net_shadow_rx_rings_prepare(struct nfp_net *nn, unsigned int fl_bufsz) for (r = 0; r < nn->num_rx_rings; r++) { nfp_net_rx_ring_init(&rings[r], nn->rx_rings[r].r_vec, r); - if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz)) + if (nfp_net_rx_ring_alloc(&rings[r], fl_bufsz, buf_cnt)) goto err_free_prev; if (nfp_net_rx_ring_bufs_alloc(nn, &rings[r])) @@ -1878,12 +1882,12 @@ static int nfp_net_netdev_open(struct net_device *netdev) if (err) goto err_free_prev_vecs; - err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring); + err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring, nn->txd_cnt); if (err) goto err_cleanup_vec_p; err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring, - nn->fl_bufsz); + nn->fl_bufsz, nn->rxd_cnt); if (err) goto err_free_tx_ring_p; @@ -2063,7 +2067,8 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) } /* Prepare new rings */ - tmp_rings = nfp_net_shadow_rx_rings_prepare(nn, new_fl_bufsz); + tmp_rings = nfp_net_shadow_rx_rings_prepare(nn, new_fl_bufsz, + nn->rxd_cnt); if (!tmp_rings) return -ENOMEM; -- GitLab From cc7c033330fd67dd9d66a1ccb8c9d42381107bcd Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 7 Apr 2016 19:39:48 +0100 Subject: [PATCH 1852/9938] nfp: allow ring size reconfiguration at runtime Since much of the required changes have already been made for changing MTU at runtime let's use it for ring size changes as well. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 1 + .../ethernet/netronome/nfp/nfp_net_common.c | 126 ++++++++++++++++++ .../ethernet/netronome/nfp/nfp_net_ethtool.c | 30 ++--- 3 files changed, 136 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 9ab8e3967dc9..3d53fcf323eb 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -724,6 +724,7 @@ void nfp_net_rss_write_key(struct nfp_net *nn); void nfp_net_coalesce_write_cfg(struct nfp_net *nn); int nfp_net_irqs_alloc(struct nfp_net *nn); void nfp_net_irqs_disable(struct nfp_net *nn); +int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt); #ifdef CONFIG_NFP_NET_DEBUG void nfp_net_debugfs_create(void); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index c4f0c70e77ce..0bdff390c958 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1444,6 +1444,59 @@ static int nfp_net_tx_ring_alloc(struct nfp_net_tx_ring *tx_ring, u32 cnt) return -ENOMEM; } +static struct nfp_net_tx_ring * +nfp_net_shadow_tx_rings_prepare(struct nfp_net *nn, u32 buf_cnt) +{ + struct nfp_net_tx_ring *rings; + unsigned int r; + + rings = kcalloc(nn->num_tx_rings, sizeof(*rings), GFP_KERNEL); + if (!rings) + return NULL; + + for (r = 0; r < nn->num_tx_rings; r++) { + nfp_net_tx_ring_init(&rings[r], nn->tx_rings[r].r_vec, r); + + if (nfp_net_tx_ring_alloc(&rings[r], buf_cnt)) + goto err_free_prev; + } + + return rings; + +err_free_prev: + while (r--) + nfp_net_tx_ring_free(&rings[r]); + kfree(rings); + return NULL; +} + +static struct nfp_net_tx_ring * +nfp_net_shadow_tx_rings_swap(struct nfp_net *nn, struct nfp_net_tx_ring *rings) +{ + struct nfp_net_tx_ring *old = nn->tx_rings; + unsigned int r; + + for (r = 0; r < nn->num_tx_rings; r++) + old[r].r_vec->tx_ring = &rings[r]; + + nn->tx_rings = rings; + return old; +} + +static void +nfp_net_shadow_tx_rings_free(struct nfp_net *nn, struct nfp_net_tx_ring *rings) +{ + unsigned int r; + + if (!rings) + return; + + for (r = 0; r < nn->num_tx_rings; r++) + nfp_net_tx_ring_free(&rings[r]); + + kfree(rings); +} + /** * nfp_net_rx_ring_free() - Free resources allocated to a RX ring * @rx_ring: RX ring to free @@ -1560,6 +1613,9 @@ nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings) { unsigned int r; + if (!rings) + return; + for (r = 0; r < nn->num_r_vecs; r++) { nfp_net_rx_ring_bufs_free(nn, &rings[r]); nfp_net_rx_ring_free(&rings[r]); @@ -2104,6 +2160,76 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) return err; } +int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt) +{ + struct nfp_net_tx_ring *tx_rings = NULL; + struct nfp_net_rx_ring *rx_rings = NULL; + u32 old_rxd_cnt, old_txd_cnt; + int err; + + if (!netif_running(nn->netdev)) { + nn->rxd_cnt = rxd_cnt; + nn->txd_cnt = txd_cnt; + return 0; + } + + old_rxd_cnt = nn->rxd_cnt; + old_txd_cnt = nn->txd_cnt; + + /* Prepare new rings */ + if (nn->rxd_cnt != rxd_cnt) { + rx_rings = nfp_net_shadow_rx_rings_prepare(nn, nn->fl_bufsz, + rxd_cnt); + if (!rx_rings) + return -ENOMEM; + } + if (nn->txd_cnt != txd_cnt) { + tx_rings = nfp_net_shadow_tx_rings_prepare(nn, txd_cnt); + if (!tx_rings) { + nfp_net_shadow_rx_rings_free(nn, rx_rings); + return -ENOMEM; + } + } + + /* Stop device, swap in new rings, try to start the firmware */ + nfp_net_close_stack(nn); + nfp_net_clear_config_and_disable(nn); + + if (rx_rings) + rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings); + if (tx_rings) + tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings); + + nn->rxd_cnt = rxd_cnt; + nn->txd_cnt = txd_cnt; + + err = nfp_net_set_config_and_enable(nn); + if (err) { + const int err_new = err; + + /* Try with old configuration and old rings */ + if (rx_rings) + rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings); + if (tx_rings) + tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings); + + nn->rxd_cnt = old_rxd_cnt; + nn->txd_cnt = old_txd_cnt; + + err = __nfp_net_set_config_and_enable(nn); + if (err) + nn_err(nn, "Can't restore ring config - FW communication failed (%d,%d)\n", + err_new, err); + } + + nfp_net_shadow_rx_rings_free(nn, rx_rings); + nfp_net_shadow_tx_rings_free(nn, tx_rings); + + nfp_net_open_stack(nn); + + return err; +} + static struct rtnl_link_stats64 *nfp_net_stat64(struct net_device *netdev, struct rtnl_link_stats64 *stats) { diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 9a4084a68db5..ccfef1f17627 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -153,37 +153,25 @@ static int nfp_net_set_ringparam(struct net_device *netdev, struct nfp_net *nn = netdev_priv(netdev); u32 rxd_cnt, txd_cnt; - if (netif_running(netdev)) { - /* Some NIC drivers allow reconfiguration on the fly, - * some down the interface, change and then up it - * again. For now we don't allow changes when the - * device is up. - */ - nn_warn(nn, "Can't change rings while device is up\n"); - return -EBUSY; - } - /* We don't have separate queues/rings for small/large frames. */ if (ring->rx_mini_pending || ring->rx_jumbo_pending) return -EINVAL; /* Round up to supported values */ rxd_cnt = roundup_pow_of_two(ring->rx_pending); - rxd_cnt = max_t(u32, rxd_cnt, NFP_NET_MIN_RX_DESCS); - rxd_cnt = min_t(u32, rxd_cnt, NFP_NET_MAX_RX_DESCS); - txd_cnt = roundup_pow_of_two(ring->tx_pending); - txd_cnt = max_t(u32, txd_cnt, NFP_NET_MIN_TX_DESCS); - txd_cnt = min_t(u32, txd_cnt, NFP_NET_MAX_TX_DESCS); - if (nn->rxd_cnt != rxd_cnt || nn->txd_cnt != txd_cnt) - nn_dbg(nn, "Change ring size: RxQ %u->%u, TxQ %u->%u\n", - nn->rxd_cnt, rxd_cnt, nn->txd_cnt, txd_cnt); + if (rxd_cnt < NFP_NET_MIN_RX_DESCS || rxd_cnt > NFP_NET_MAX_RX_DESCS || + txd_cnt < NFP_NET_MIN_TX_DESCS || txd_cnt > NFP_NET_MAX_TX_DESCS) + return -EINVAL; - nn->rxd_cnt = rxd_cnt; - nn->txd_cnt = txd_cnt; + if (nn->rxd_cnt == rxd_cnt && nn->txd_cnt == txd_cnt) + return 0; - return 0; + nn_dbg(nn, "Change ring size: RxQ %u->%u, TxQ %u->%u\n", + nn->rxd_cnt, rxd_cnt, nn->txd_cnt, txd_cnt); + + return nfp_net_set_ring_size(nn, rxd_cnt, txd_cnt); } static void nfp_net_get_strings(struct net_device *netdev, -- GitLab From a9844881ba19d15d274bd684d4de0758bbd71c90 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Apr 2016 19:11:20 +0200 Subject: [PATCH 1853/9938] devlink: remove implicit type set in port register As we rely on caller zeroing or correctly set the struct before the call, this implicit type set is either no-op (DEVLINK_PORT_TYPE_NOTSET is 0) or it rewrites wanted value. So remove this. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/devlink.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index 590fa561cb7f..44f880d3b816 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -630,7 +630,6 @@ int devlink_port_register(struct devlink *devlink, } devlink_port->devlink = devlink; devlink_port->index = port_index; - devlink_port->type = DEVLINK_PORT_TYPE_NOTSET; devlink_port->registered = true; list_add_tail(&devlink_port->list, &devlink->port_list); mutex_unlock(&devlink_port_mutex); -- GitLab From 932762b69a282d3fa12febc1a02628f0fb79a1b8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Apr 2016 19:11:21 +0200 Subject: [PATCH 1854/9938] mlxsw: Move devlink port registration into common core code Remove devlink port reg/unreg from spectrum and switchx2 code and rather do the common work in core. That also ensures code separation where devlink is only used in core.c. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 22 +++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 10 ++++++ .../net/ethernet/mellanox/mlxsw/spectrum.c | 31 +++++++------------ .../net/ethernet/mellanox/mlxsw/spectrum.h | 3 +- .../net/ethernet/mellanox/mlxsw/switchx2.c | 30 +++++++----------- 5 files changed, 55 insertions(+), 41 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index f69f6280519f..004fb8b50fab 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1358,6 +1358,28 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear); +int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, + struct mlxsw_core_port *mlxsw_core_port, u8 local_port, + struct net_device *dev, bool split, u32 split_group) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_core); + struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; + + if (split) + devlink_port_split_set(devlink_port, split_group); + devlink_port_type_eth_set(devlink_port, dev); + return devlink_port_register(devlink, devlink_port, local_port); +} +EXPORT_SYMBOL(mlxsw_core_port_init); + +void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port) +{ + struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; + + devlink_port_unregister(devlink_port); +} +EXPORT_SYMBOL(mlxsw_core_port_fini); + int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, u32 in_mod, bool out_mbox_direct, char *in_mbox, size_t in_mbox_size, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index c73d1c0792a6..06631a0136a5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -43,6 +43,7 @@ #include #include #include +#include #include "trap.h" #include "reg.h" @@ -131,6 +132,15 @@ u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core, void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, u16 lag_id, u8 local_port); +struct mlxsw_core_port { + struct devlink_port devlink_port; +}; + +int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, + struct mlxsw_core_port *mlxsw_core_port, u8 local_port, + struct net_device *dev, bool split, u32 split_group); +void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port); + #define MLXSW_CONFIG_PROFILE_SWID_COUNT 8 struct mlxsw_swid_config { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 507263a2d226..3216f2b9844f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include @@ -1685,9 +1684,7 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port) static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, bool split, u8 module, u8 width) { - struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); struct mlxsw_sp_port *mlxsw_sp_port; - struct devlink_port *devlink_port; struct net_device *dev; size_t bytes; int err; @@ -1740,16 +1737,6 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, */ dev->hard_header_len += MLXSW_TXHDR_LEN; - devlink_port = &mlxsw_sp_port->devlink_port; - if (mlxsw_sp_port->split) - devlink_port_split_set(devlink_port, module); - err = devlink_port_register(devlink, devlink_port, local_port); - if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register devlink port\n", - mlxsw_sp_port->local_port); - goto err_devlink_port_register; - } - err = mlxsw_sp_port_system_port_mapping_set(mlxsw_sp_port); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set system port mapping\n", @@ -1812,7 +1799,14 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_register_netdev; } - devlink_port_type_eth_set(devlink_port, dev); + err = mlxsw_core_port_init(mlxsw_sp->core, &mlxsw_sp_port->core_port, + mlxsw_sp_port->local_port, dev, + mlxsw_sp_port->split, module); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n", + mlxsw_sp_port->local_port); + goto err_core_port_init; + } err = mlxsw_sp_port_vlan_init(mlxsw_sp_port); if (err) @@ -1822,6 +1816,8 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, return 0; err_port_vlan_init: + mlxsw_core_port_fini(&mlxsw_sp_port->core_port); +err_core_port_init: unregister_netdev(dev); err_register_netdev: err_port_dcb_init: @@ -1832,8 +1828,6 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err_port_speed_by_width_set: err_port_swid_set: err_port_system_port_mapping_set: - devlink_port_unregister(&mlxsw_sp_port->devlink_port); -err_devlink_port_register: err_dev_addr_init: free_percpu(mlxsw_sp_port->pcpu_stats); err_alloc_stats: @@ -1887,16 +1881,13 @@ static void mlxsw_sp_port_vports_fini(struct mlxsw_sp_port *mlxsw_sp_port) static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) { struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; - struct devlink_port *devlink_port; if (!mlxsw_sp_port) return; mlxsw_sp->ports[local_port] = NULL; - devlink_port = &mlxsw_sp_port->devlink_port; - devlink_port_type_clear(devlink_port); + mlxsw_core_port_fini(&mlxsw_sp_port->core_port); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ mlxsw_sp_port_dcb_fini(mlxsw_sp_port); - devlink_port_unregister(devlink_port); mlxsw_sp_port_vports_fini(mlxsw_sp_port); mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 47610a5ccd78..361b0c270b56 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -44,7 +44,6 @@ #include #include #include -#include #include "port.h" #include "core.h" @@ -166,6 +165,7 @@ struct mlxsw_sp_port_pcpu_stats { }; struct mlxsw_sp_port { + struct mlxsw_core_port core_port; /* must be first */ struct net_device *dev; struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats; struct mlxsw_sp *mlxsw_sp; @@ -198,7 +198,6 @@ struct mlxsw_sp_port { unsigned long *untagged_vlans; /* VLAN interfaces */ struct list_head vports_list; - struct devlink_port devlink_port; }; static inline bool diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index c49447f31acc..2417f099931b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -75,11 +74,11 @@ struct mlxsw_sx_port_pcpu_stats { }; struct mlxsw_sx_port { + struct mlxsw_core_port core_port; /* must be first */ struct net_device *dev; struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats; struct mlxsw_sx *mlxsw_sx; u8 local_port; - struct devlink_port devlink_port; }; /* tx_hdr_version @@ -956,9 +955,7 @@ mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port, static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) { - struct devlink *devlink = priv_to_devlink(mlxsw_sx->core); struct mlxsw_sx_port *mlxsw_sx_port; - struct devlink_port *devlink_port; struct net_device *dev; bool usable; int err; @@ -1012,14 +1009,6 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) goto port_not_usable; } - devlink_port = &mlxsw_sx_port->devlink_port; - err = devlink_port_register(devlink, devlink_port, local_port); - if (err) { - dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to register devlink port\n", - mlxsw_sx_port->local_port); - goto err_devlink_port_register; - } - err = mlxsw_sx_port_system_port_mapping_set(mlxsw_sx_port); if (err) { dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to set system port mapping\n", @@ -1077,11 +1066,19 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) goto err_register_netdev; } - devlink_port_type_eth_set(devlink_port, dev); + err = mlxsw_core_port_init(mlxsw_sx->core, &mlxsw_sx_port->core_port, + mlxsw_sx_port->local_port, dev, false, 0); + if (err) { + dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n", + mlxsw_sx_port->local_port); + goto err_core_port_init; + } mlxsw_sx->ports[local_port] = mlxsw_sx_port; return 0; +err_core_port_init: + unregister_netdev(dev); err_register_netdev: err_port_mac_learning_mode_set: err_port_stp_state_set: @@ -1090,8 +1087,6 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) err_port_speed_set: err_port_swid_set: err_port_system_port_mapping_set: - devlink_port_unregister(&mlxsw_sx_port->devlink_port); -err_devlink_port_register: port_not_usable: err_port_module_check: err_dev_addr_get: @@ -1104,15 +1099,12 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port) { struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port]; - struct devlink_port *devlink_port; if (!mlxsw_sx_port) return; - devlink_port = &mlxsw_sx_port->devlink_port; - devlink_port_type_clear(devlink_port); + mlxsw_core_port_fini(&mlxsw_sx_port->core_port); unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */ mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT); - devlink_port_unregister(devlink_port); free_percpu(mlxsw_sx_port->pcpu_stats); free_netdev(mlxsw_sx_port->dev); } -- GitLab From 307c2431abf0974996356c13b67432f4b35e5f2f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Apr 2016 19:11:22 +0200 Subject: [PATCH 1855/9938] mlxsw: Pass mlxsw_core as a param of mlxsw_core_skb_transmit* Instead of passing around driver priv, pass struct mlxsw_core * directly. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 15 +++------------ drivers/net/ethernet/mellanox/mlxsw/core.h | 5 ++--- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 4 ++-- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 004fb8b50fab..39161fb91ec1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -381,7 +381,7 @@ static int __mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, mlxsw_core->emad.trans_active = true; - err = mlxsw_core_skb_transmit(mlxsw_core->driver_priv, skb, tx_info); + err = mlxsw_core_skb_transmit(mlxsw_core, skb, tx_info); if (err) { dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n", mlxsw_core->emad.tid); @@ -929,26 +929,17 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core) } EXPORT_SYMBOL(mlxsw_core_bus_device_unregister); -static struct mlxsw_core *__mlxsw_core_get(void *driver_priv) -{ - return container_of(driver_priv, struct mlxsw_core, driver_priv); -} - -bool mlxsw_core_skb_transmit_busy(void *driver_priv, +bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core, const struct mlxsw_tx_info *tx_info) { - struct mlxsw_core *mlxsw_core = __mlxsw_core_get(driver_priv); - return mlxsw_core->bus->skb_transmit_busy(mlxsw_core->bus_priv, tx_info); } EXPORT_SYMBOL(mlxsw_core_skb_transmit_busy); -int mlxsw_core_skb_transmit(void *driver_priv, struct sk_buff *skb, +int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, const struct mlxsw_tx_info *tx_info) { - struct mlxsw_core *mlxsw_core = __mlxsw_core_get(driver_priv); - return mlxsw_core->bus->skb_transmit(mlxsw_core->bus_priv, skb, tx_info); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 06631a0136a5..0454212a86d1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -75,10 +75,9 @@ struct mlxsw_tx_info { bool is_emad; }; -bool mlxsw_core_skb_transmit_busy(void *driver_priv, +bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core, const struct mlxsw_tx_info *tx_info); - -int mlxsw_core_skb_transmit(void *driver_priv, struct sk_buff *skb, +int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, const struct mlxsw_tx_info *tx_info); struct mlxsw_rx_listener { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 3216f2b9844f..8abe1a615c94 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -390,7 +390,7 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb, u64 len; int err; - if (mlxsw_core_skb_transmit_busy(mlxsw_sp, &tx_info)) + if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info)) return NETDEV_TX_BUSY; if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) { @@ -414,7 +414,7 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb, /* Due to a race we might fail here because of a full queue. In that * unlikely case we simply drop the packet. */ - err = mlxsw_core_skb_transmit(mlxsw_sp, skb, &tx_info); + err = mlxsw_core_skb_transmit(mlxsw_sp->core, skb, &tx_info); if (!err) { pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 2417f099931b..2518c84960a0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -302,7 +302,7 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb, u64 len; int err; - if (mlxsw_core_skb_transmit_busy(mlxsw_sx, &tx_info)) + if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info)) return NETDEV_TX_BUSY; if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) { @@ -320,7 +320,7 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb, /* Due to a race we might fail here because of a full queue. In that * unlikely case we simply drop the packet. */ - err = mlxsw_core_skb_transmit(mlxsw_sx, skb, &tx_info); + err = mlxsw_core_skb_transmit(mlxsw_sx->core, skb, &tx_info); if (!err) { pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats); -- GitLab From b2f10571b96414986f7293b06847d202f2d1d0ca Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Apr 2016 19:11:23 +0200 Subject: [PATCH 1856/9938] mlxsw: Do not pass around driver_priv directly Instead of that, pass mlxsw_core and use a helper to get driver priv from driver code. Looks much cleaner that way. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 19 +++++++++++-------- drivers/net/ethernet/mellanox/mlxsw/core.h | 11 +++++++---- .../net/ethernet/mellanox/mlxsw/spectrum.c | 17 +++++++++-------- .../net/ethernet/mellanox/mlxsw/switchx2.c | 8 ++++---- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 39161fb91ec1..3958195526d1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -114,6 +114,12 @@ struct mlxsw_core { /* driver_priv has to be always the last item */ }; +void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core) +{ + return mlxsw_core->driver_priv; +} +EXPORT_SYMBOL(mlxsw_core_driver_priv); + struct mlxsw_rx_listener_item { struct list_head list; struct mlxsw_rx_listener rxl; @@ -795,8 +801,7 @@ static int mlxsw_devlink_port_split(struct devlink *devlink, return -EINVAL; if (!mlxsw_core->driver->port_split) return -EOPNOTSUPP; - return mlxsw_core->driver->port_split(mlxsw_core->driver_priv, - port_index, count); + return mlxsw_core->driver->port_split(mlxsw_core, port_index, count); } static int mlxsw_devlink_port_unsplit(struct devlink *devlink, @@ -808,8 +813,7 @@ static int mlxsw_devlink_port_unsplit(struct devlink *devlink, return -EINVAL; if (!mlxsw_core->driver->port_unsplit) return -EOPNOTSUPP; - return mlxsw_core->driver->port_unsplit(mlxsw_core->driver_priv, - port_index); + return mlxsw_core->driver->port_unsplit(mlxsw_core, port_index); } static const struct devlink_ops mlxsw_devlink_ops = { @@ -880,8 +884,7 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, if (err) goto err_devlink_register; - err = mlxsw_driver->init(mlxsw_core->driver_priv, mlxsw_core, - mlxsw_bus_info); + err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info); if (err) goto err_driver_init; @@ -892,7 +895,7 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, return 0; err_debugfs_init: - mlxsw_core->driver->fini(mlxsw_core->driver_priv); + mlxsw_core->driver->fini(mlxsw_core); err_driver_init: devlink_unregister(devlink); err_devlink_register: @@ -918,7 +921,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core) struct devlink *devlink = priv_to_devlink(mlxsw_core); mlxsw_core_debugfs_fini(mlxsw_core); - mlxsw_core->driver->fini(mlxsw_core->driver_priv); + mlxsw_core->driver->fini(mlxsw_core); devlink_unregister(devlink); mlxsw_emad_fini(mlxsw_core); mlxsw_core->bus->fini(mlxsw_core->bus_priv); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 0454212a86d1..f3cebef9c31c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -62,6 +62,8 @@ struct mlxsw_driver; struct mlxsw_bus; struct mlxsw_bus_info; +void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core); + int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver); void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver); @@ -192,11 +194,12 @@ struct mlxsw_driver { const char *kind; struct module *owner; size_t priv_size; - int (*init)(void *driver_priv, struct mlxsw_core *mlxsw_core, + int (*init)(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info); - void (*fini)(void *driver_priv); - int (*port_split)(void *driver_priv, u8 local_port, unsigned int count); - int (*port_unsplit)(void *driver_priv, u8 local_port); + void (*fini)(struct mlxsw_core *mlxsw_core); + int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port, + unsigned int count); + int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port); void (*txhdr_construct)(struct sk_buff *skb, const struct mlxsw_tx_info *tx_info); u8 txhdr_len; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 8abe1a615c94..19b3c144abc6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1948,9 +1948,10 @@ static u8 mlxsw_sp_cluster_base_port_get(u8 local_port) return local_port - offset; } -static int mlxsw_sp_port_split(void *priv, u8 local_port, unsigned int count) +static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, + unsigned int count) { - struct mlxsw_sp *mlxsw_sp = priv; + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp_port *mlxsw_sp_port; u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count; u8 module, cur_width, base_port; @@ -2022,9 +2023,9 @@ static int mlxsw_sp_port_split(void *priv, u8 local_port, unsigned int count) return err; } -static int mlxsw_sp_port_unsplit(void *priv, u8 local_port) +static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port) { - struct mlxsw_sp *mlxsw_sp = priv; + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp_port *mlxsw_sp_port; u8 module, cur_width, base_port; unsigned int count; @@ -2369,10 +2370,10 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcr), slcr_pl); } -static int mlxsw_sp_init(void *priv, struct mlxsw_core *mlxsw_core, +static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info) { - struct mlxsw_sp *mlxsw_sp = priv; + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); int err; mlxsw_sp->core = mlxsw_core; @@ -2443,9 +2444,9 @@ static int mlxsw_sp_init(void *priv, struct mlxsw_core *mlxsw_core, return err; } -static void mlxsw_sp_fini(void *priv) +static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) { - struct mlxsw_sp *mlxsw_sp = priv; + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); mlxsw_sp_switchdev_fini(mlxsw_sp); mlxsw_sp_traps_fini(mlxsw_sp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 2518c84960a0..3842eab9449a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1447,10 +1447,10 @@ static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx) return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sgcr), sgcr_pl); } -static int mlxsw_sx_init(void *priv, struct mlxsw_core *mlxsw_core, +static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info) { - struct mlxsw_sx *mlxsw_sx = priv; + struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); int err; mlxsw_sx->core = mlxsw_core; @@ -1497,9 +1497,9 @@ static int mlxsw_sx_init(void *priv, struct mlxsw_core *mlxsw_core, return err; } -static void mlxsw_sx_fini(void *priv) +static void mlxsw_sx_fini(struct mlxsw_core *mlxsw_core) { - struct mlxsw_sx *mlxsw_sx = priv; + struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); mlxsw_sx_traps_fini(mlxsw_sx); mlxsw_sx_event_unregister(mlxsw_sx, MLXSW_TRAP_ID_PUDE); -- GitLab From 497e8592c6d22772d0ad100c1f08e601dc417ed5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Apr 2016 19:11:24 +0200 Subject: [PATCH 1857/9938] mlxsw: reg: Share direction enum between SBPR, SBCM, SBPM Same field, same values, so share the same enum. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 23 ++++++------------- .../mellanox/mlxsw/spectrum_buffers.c | 20 ++++++++-------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 28f5b99e585a..19bdc826e3cd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3476,9 +3476,10 @@ static const struct mlxsw_reg_info mlxsw_reg_sbpr = { .len = MLXSW_REG_SBPR_LEN, }; -enum mlxsw_reg_sbpr_dir { - MLXSW_REG_SBPR_DIR_INGRESS, - MLXSW_REG_SBPR_DIR_EGRESS, +/* shared direstion enum for SBPR, SBCM, SBPM */ +enum mlxsw_reg_sbxx_dir { + MLXSW_REG_SBXX_DIR_INGRESS, + MLXSW_REG_SBXX_DIR_EGRESS, }; /* reg_sbpr_dir @@ -3511,7 +3512,7 @@ enum mlxsw_reg_sbpr_mode { MLXSW_ITEM32(reg, sbpr, mode, 0x08, 0, 4); static inline void mlxsw_reg_sbpr_pack(char *payload, u8 pool, - enum mlxsw_reg_sbpr_dir dir, + enum mlxsw_reg_sbxx_dir dir, enum mlxsw_reg_sbpr_mode mode, u32 size) { MLXSW_REG_ZERO(sbpr, payload); @@ -3553,11 +3554,6 @@ MLXSW_ITEM32(reg, sbcm, local_port, 0x00, 16, 8); */ MLXSW_ITEM32(reg, sbcm, pg_buff, 0x00, 8, 6); -enum mlxsw_reg_sbcm_dir { - MLXSW_REG_SBCM_DIR_INGRESS, - MLXSW_REG_SBCM_DIR_EGRESS, -}; - /* reg_sbcm_dir * Direction. * Access: Index @@ -3590,7 +3586,7 @@ MLXSW_ITEM32(reg, sbcm, max_buff, 0x1C, 0, 24); MLXSW_ITEM32(reg, sbcm, pool, 0x24, 0, 4); static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff, - enum mlxsw_reg_sbcm_dir dir, + enum mlxsw_reg_sbxx_dir dir, u32 min_buff, u32 max_buff, u8 pool) { MLXSW_REG_ZERO(sbcm, payload); @@ -3630,11 +3626,6 @@ MLXSW_ITEM32(reg, sbpm, local_port, 0x00, 16, 8); */ MLXSW_ITEM32(reg, sbpm, pool, 0x00, 8, 4); -enum mlxsw_reg_sbpm_dir { - MLXSW_REG_SBPM_DIR_INGRESS, - MLXSW_REG_SBPM_DIR_EGRESS, -}; - /* reg_sbpm_dir * Direction. * Access: Index @@ -3661,7 +3652,7 @@ MLXSW_ITEM32(reg, sbpm, min_buff, 0x18, 0, 24); MLXSW_ITEM32(reg, sbpm, max_buff, 0x1C, 0, 24); static inline void mlxsw_reg_sbpm_pack(char *payload, u8 local_port, u8 pool, - enum mlxsw_reg_sbpm_dir dir, + enum mlxsw_reg_sbxx_dir dir, u32 min_buff, u32 max_buff) { MLXSW_REG_ZERO(sbpm, payload); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 97c8d537be5b..f58b1d3a619a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -110,7 +110,7 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) struct mlxsw_sp_sb_pool { u8 pool; - enum mlxsw_reg_sbpr_dir dir; + enum mlxsw_reg_sbxx_dir dir; enum mlxsw_reg_sbpr_mode mode; u32 size; }; @@ -129,11 +129,11 @@ struct mlxsw_sp_sb_pool { } #define MLXSW_SP_SB_POOL_INGRESS(_pool, _size) \ - MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_INGRESS, \ + MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_INGRESS, \ MLXSW_REG_SBPR_MODE_DYNAMIC, _size) #define MLXSW_SP_SB_POOL_EGRESS(_pool, _size) \ - MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_EGRESS, \ + MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_EGRESS, \ MLXSW_REG_SBPR_MODE_DYNAMIC, _size) static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = { @@ -173,7 +173,7 @@ struct mlxsw_sp_sb_cm { u8 pg; u8 tc; } u; - enum mlxsw_reg_sbcm_dir dir; + enum mlxsw_reg_sbxx_dir dir; u32 min_buff; u32 max_buff; u8 pool; @@ -189,15 +189,15 @@ struct mlxsw_sp_sb_cm { } #define MLXSW_SP_SB_CM_INGRESS(_pg, _min_buff, _max_buff) \ - MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBCM_DIR_INGRESS, \ + MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBXX_DIR_INGRESS, \ _min_buff, _max_buff, 0) #define MLXSW_SP_SB_CM_EGRESS(_tc, _min_buff, _max_buff) \ - MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, \ + MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS, \ _min_buff, _max_buff, 0) #define MLXSW_SP_CPU_PORT_SB_CM_EGRESS(_tc) \ - MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, 104, 2, 3) + MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS, 104, 2, 3) static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = { MLXSW_SP_SB_CM_INGRESS(0, MLXSW_SP_BYTES_TO_CELLS(10000), 8), @@ -304,7 +304,7 @@ static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp) struct mlxsw_sp_sb_pm { u8 pool; - enum mlxsw_reg_sbpm_dir dir; + enum mlxsw_reg_sbxx_dir dir; u32 min_buff; u32 max_buff; }; @@ -318,11 +318,11 @@ struct mlxsw_sp_sb_pm { } #define MLXSW_SP_SB_PM_INGRESS(_pool, _min_buff, _max_buff) \ - MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_INGRESS, \ + MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_INGRESS, \ _min_buff, _max_buff) #define MLXSW_SP_SB_PM_EGRESS(_pool, _min_buff, _max_buff) \ - MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_EGRESS, \ + MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_EGRESS, \ _min_buff, _max_buff) static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = { -- GitLab From 9efc8f655c8488c6ee2f7d5034826880bf5b4bba Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Apr 2016 19:11:25 +0200 Subject: [PATCH 1858/9938] mlxsw: reg: Fix SBPM register name Fix copy&paste error and state the name of SBPM register correctly. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 19bdc826e3cd..57e4a6337ae3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3598,8 +3598,8 @@ static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff, mlxsw_reg_sbcm_pool_set(payload, pool); } -/* SBPM - Shared Buffer Class Management Register - * ---------------------------------------------- +/* SBPM - Shared Buffer Port Management Register + * --------------------------------------------- * The SBPM register configures and retrieves the shared buffer allocation * and configuration according to Port-Pool, including the definition * of the associated quota. -- GitLab From 1fc2257e837f86c2688fdcc5c8810b73c133794d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Apr 2016 19:12:48 +0200 Subject: [PATCH 1859/9938] devlink: share user_ptr pointer for both devlink and devlink_port Ptr to devlink structure can be easily obtained from devlink_port->devlink. So share user_ptr[0] pointer for both and leave user_ptr[1] free for other users. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- net/core/devlink.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index 44f880d3b816..b84cf0df4a0e 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -119,7 +119,8 @@ static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, return devlink_port_get_from_attrs(devlink, info->attrs); } -#define DEVLINK_NL_FLAG_NEED_PORT BIT(0) +#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) +#define DEVLINK_NL_FLAG_NEED_PORT BIT(1) static int devlink_nl_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) @@ -132,8 +133,9 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, mutex_unlock(&devlink_mutex); return PTR_ERR(devlink); } - info->user_ptr[0] = devlink; - if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { + if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) { + info->user_ptr[0] = devlink; + } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { struct devlink_port *devlink_port; mutex_lock(&devlink_port_mutex); @@ -143,7 +145,7 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, mutex_unlock(&devlink_mutex); return PTR_ERR(devlink_port); } - info->user_ptr[1] = devlink_port; + info->user_ptr[0] = devlink_port; } return 0; } @@ -356,8 +358,8 @@ static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb, struct genl_info *info) { - struct devlink *devlink = info->user_ptr[0]; - struct devlink_port *devlink_port = info->user_ptr[1]; + struct devlink_port *devlink_port = info->user_ptr[0]; + struct devlink *devlink = devlink_port->devlink; struct sk_buff *msg; int err; @@ -436,8 +438,8 @@ static int devlink_port_type_set(struct devlink *devlink, static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, struct genl_info *info) { - struct devlink *devlink = info->user_ptr[0]; - struct devlink_port *devlink_port = info->user_ptr[1]; + struct devlink_port *devlink_port = info->user_ptr[0]; + struct devlink *devlink = devlink_port->devlink; int err; if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { @@ -511,6 +513,7 @@ static const struct genl_ops devlink_nl_ops[] = { .doit = devlink_nl_cmd_get_doit, .dumpit = devlink_nl_cmd_get_dumpit, .policy = devlink_nl_policy, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, /* can be retrieved by unprivileged users */ }, { @@ -533,12 +536,14 @@ static const struct genl_ops devlink_nl_ops[] = { .doit = devlink_nl_cmd_port_split_doit, .policy = devlink_nl_policy, .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, }, { .cmd = DEVLINK_CMD_PORT_UNSPLIT, .doit = devlink_nl_cmd_port_unsplit_doit, .policy = devlink_nl_policy, .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, }, }; -- GitLab From 52966bd1c2a09fdd3149f00568cc18f45cc09785 Mon Sep 17 00:00:00 2001 From: Jon Derrick Date: Fri, 8 Apr 2016 14:44:24 -0500 Subject: [PATCH 1860/9938] PCI/ACPI: Allow all PCIe services on non-ACPI host bridges Host bridges we discover via ACPI, i.e., PNP0A03 and PNP0A08 devices, may have an _OSC method by which the OS can ask the platform for control of PCIe features like native hotplug, power management events, AER, etc. Previously, if we found a bridge without an ACPI device, we assumed we did not have permission to use any of these PCIe features. That seems unreasonably restrictive. If we find no ACPI device, assume we can take control of all PCIe features. The Intel Volume Management Device (VMD) is one such bridge with no ACPI device. Prior to this change, users had to boot with "pcie_ports=native" to get hotplug and other services to work below the VMD Root Port. [bhelgaas: changelog] Suggested-by: Bjorn Helgaas Signed-off-by: Jon Derrick Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/portdrv_acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c index b4d2894ee3fc..f097a73cb291 100644 --- a/drivers/pci/pcie/portdrv_acpi.c +++ b/drivers/pci/pcie/portdrv_acpi.c @@ -43,11 +43,11 @@ int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) handle = acpi_find_root_bridge_handle(port); if (!handle) - return -EINVAL; + return 0; root = acpi_pci_find_root(handle); if (!root) - return -ENODEV; + return 0; flags = root->osc_control_set; -- GitLab From 07016151a446d25397b24588df4ed5cf777a69bb Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 5 Apr 2016 22:33:17 +0200 Subject: [PATCH 1861/9938] bpf, verifier: further improve search pruning The verifier needs to go through every path of the program in order to check that it terminates safely, which can be quite a lot of instructions that need to be processed f.e. in cases with more branchy programs. With search pruning from f1bca824dabb ("bpf: add search pruning optimization to verifier") the search space can already be reduced significantly when the verifier detects that a previously walked path with same register and stack contents terminated already (see verifier's states_equal()), so the search can skip walking those states. When working with larger programs of > ~2000 (out of max 4096) insns, we found that the current limit of 32k instructions is easily hit. For example, a case we ran into is that the search space cannot be pruned due to branches at the beginning of the program that make use of certain stack space slots (STACK_MISC), which are never used in the remaining program (STACK_INVALID). Therefore, the verifier needs to walk paths for the slots in STACK_INVALID state, but also all remaining paths with a stack structure, where the slots are in STACK_MISC, which can nearly double the search space needed. After various experiments, we find that a limit of 64k processed insns is a more reasonable choice when dealing with larger programs in practice. This still allows to reject extreme crafted cases that can have a much higher complexity (f.e. > ~300k) within the 4096 insns limit due to search pruning not being able to take effect. Furthermore, we found that a lot of states can be pruned after a call instruction, f.e. we were able to reduce the search state by ~35% in some cases with this heuristic, trade-off is to keep a bit more states in env->explored_states. Usually, call instructions have a number of preceding register assignments and/or stack stores, where search pruning has a better chance to suceed in states_equal() test. The current code marks the branch targets with STATE_LIST_MARK in case of conditional jumps, and the next (t + 1) instruction in case of unconditional jump so that f.e. a backjump will walk it. We also did experiments with using t + insns[t].off + 1 as a marker in the unconditionally jump case instead of t + 1 with the rationale that these two branches of execution that converge after the label might have more potential of pruning. We found that it was a bit better, but not necessarily significantly better than the current state, perhaps also due to clang not generating back jumps often. Hence, we left that as is for now. Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/bpf/verifier.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 58792fed5678..8233021538d3 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -202,6 +202,9 @@ struct verifier_env { bool allow_ptr_leaks; }; +#define BPF_COMPLEXITY_LIMIT_INSNS 65536 +#define BPF_COMPLEXITY_LIMIT_STACK 1024 + /* verbose verifier prints what it's seeing * bpf_check() is called under lock, so no race to access these global vars */ @@ -454,7 +457,7 @@ static struct verifier_state *push_stack(struct verifier_env *env, int insn_idx, elem->next = env->head; env->head = elem; env->stack_size++; - if (env->stack_size > 1024) { + if (env->stack_size > BPF_COMPLEXITY_LIMIT_STACK) { verbose("BPF program is too complex\n"); goto err; } @@ -1543,6 +1546,8 @@ static int check_cfg(struct verifier_env *env) goto peek_stack; else if (ret < 0) goto err_free; + if (t + 1 < insn_cnt) + env->explored_states[t + 1] = STATE_LIST_MARK; } else if (opcode == BPF_JA) { if (BPF_SRC(insns[t].code) != BPF_K) { ret = -EINVAL; @@ -1747,7 +1752,7 @@ static int do_check(struct verifier_env *env) insn = &insns[insn_idx]; class = BPF_CLASS(insn->code); - if (++insn_processed > 32768) { + if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) { verbose("BPF program is too large. Proccessed %d insn\n", insn_processed); return -E2BIG; -- GitLab From 88a97da1eab7587036d8bc937d6bc874b8210df1 Mon Sep 17 00:00:00 2001 From: Jon Derrick Date: Fri, 8 Apr 2016 11:35:51 -0600 Subject: [PATCH 1862/9938] PCI: Remove return values from pcie_port_platform_notify() and relatives Now that pcie_port_acpi_setup() always returns 0, make it and its callers void functions and stop checking the return values. [bhelgaas: changelog] Signed-off-by: Jon Derrick Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/portdrv.h | 11 ++++------- drivers/pci/pcie/portdrv_acpi.c | 10 ++++------ drivers/pci/pcie/portdrv_core.c | 8 ++------ 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index d525548404d6..463b60975194 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -67,17 +67,14 @@ static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {} #endif /* !CONFIG_PCIE_PME */ #ifdef CONFIG_ACPI -int pcie_port_acpi_setup(struct pci_dev *port, int *mask); +void pcie_port_acpi_setup(struct pci_dev *port, int *mask); -static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) +static inline void pcie_port_platform_notify(struct pci_dev *port, int *mask) { - return pcie_port_acpi_setup(port, mask); + pcie_port_acpi_setup(port, mask); } #else /* !CONFIG_ACPI */ -static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) -{ - return 0; -} +static inline void pcie_port_platform_notify(struct pci_dev *port, int *mask){} #endif /* !CONFIG_ACPI */ #endif /* _PORTDRV_H_ */ diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c index f097a73cb291..9f4ed7172fda 100644 --- a/drivers/pci/pcie/portdrv_acpi.c +++ b/drivers/pci/pcie/portdrv_acpi.c @@ -32,22 +32,22 @@ * NOTE: It turns out that we cannot do that for individual port services * separately, because that would make some systems work incorrectly. */ -int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) +void pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) { struct acpi_pci_root *root; acpi_handle handle; u32 flags; if (acpi_pci_disabled) - return 0; + return; handle = acpi_find_root_bridge_handle(port); if (!handle) - return 0; + return; root = acpi_pci_find_root(handle); if (!root) - return 0; + return; flags = root->osc_control_set; @@ -58,6 +58,4 @@ int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) *srv_mask |= PCIE_PORT_SERVICE_PME; if (flags & OSC_PCI_EXPRESS_AER_CONTROL) *srv_mask |= PCIE_PORT_SERVICE_AER; - - return 0; } diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 88122dc2e1b1..de7a85bc8016 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -256,7 +256,6 @@ static int get_port_device_capability(struct pci_dev *dev) int services = 0; u32 reg32; int cap_mask = 0; - int err; if (pcie_ports_disabled) return 0; @@ -266,11 +265,8 @@ static int get_port_device_capability(struct pci_dev *dev) if (pci_aer_available()) cap_mask |= PCIE_PORT_SERVICE_AER; - if (pcie_ports_auto) { - err = pcie_port_platform_notify(dev, &cap_mask); - if (err) - return 0; - } + if (pcie_ports_auto) + pcie_port_platform_notify(dev, &cap_mask); /* Hot-Plug Capable */ if ((cap_mask & PCIE_PORT_SERVICE_HP) && -- GitLab From 6c9d9c81924b4b63c7a487e90fddb3b2d0f7d458 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Apr 2016 23:38:46 +0200 Subject: [PATCH 1863/9938] cpufreq: Call cpufreq_disable_fast_switch() in sugov_exit() Due to differences in the cpufreq core's handling of runtime CPU offline and nonboot CPUs disabling during system suspend-to-RAM, fast frequency switching gets disabled after a suspend-to-RAM and resume cycle on all of the nonboot CPUs. To prevent that from happening, move the invocation of cpufreq_disable_fast_switch() from cpufreq_exit_governor() to sugov_exit(), as the schedutil governor is the only user of fast frequency switching today anyway. That simply prevents cpufreq_disable_fast_switch() from being called without invoking the ->governor callback for the CPUFREQ_GOV_POLICY_EXIT event (which happens during system suspend now). Fixes: b7898fda5bc7 (cpufreq: Support for fast frequency switching) Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 19 +++++++++++-------- include/linux/cpufreq.h | 1 + kernel/sched/cpufreq_schedutil.c | 2 ++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a5b7d77d4816..77d77a4e3b74 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -77,7 +77,11 @@ static inline bool has_target(void) static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static unsigned int __cpufreq_get(struct cpufreq_policy *policy); static int cpufreq_start_governor(struct cpufreq_policy *policy); -static int cpufreq_exit_governor(struct cpufreq_policy *policy); + +static inline int cpufreq_exit_governor(struct cpufreq_policy *policy) +{ + return cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); +} /** * Two notifier lists: the "policy" list is involved in the @@ -482,7 +486,11 @@ void cpufreq_enable_fast_switch(struct cpufreq_policy *policy) } EXPORT_SYMBOL_GPL(cpufreq_enable_fast_switch); -static void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) +/** + * cpufreq_disable_fast_switch - Disable fast frequency switching for policy. + * @policy: cpufreq policy to disable fast frequency switching for. + */ +void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) { mutex_lock(&cpufreq_fast_switch_lock); if (policy->fast_switch_enabled) { @@ -492,6 +500,7 @@ static void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) } mutex_unlock(&cpufreq_fast_switch_lock); } +EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch); /********************************************************************* * SYSFS INTERFACE * @@ -2060,12 +2069,6 @@ static int cpufreq_start_governor(struct cpufreq_policy *policy) return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); } -static int cpufreq_exit_governor(struct cpufreq_policy *policy) -{ - cpufreq_disable_fast_switch(policy); - return cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); -} - int cpufreq_register_governor(struct cpufreq_governor *governor) { int err; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 55e69ebb035c..4e81e08db752 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -168,6 +168,7 @@ int cpufreq_update_policy(unsigned int cpu); bool have_governor_per_policy(void); struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); void cpufreq_enable_fast_switch(struct cpufreq_policy *policy); +void cpufreq_disable_fast_switch(struct cpufreq_policy *policy); #else static inline unsigned int cpufreq_get(unsigned int cpu) { diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index d27ae064b476..154ae3a51e86 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -398,6 +398,8 @@ static int sugov_exit(struct cpufreq_policy *policy) struct sugov_tunables *tunables = sg_policy->tunables; unsigned int count; + cpufreq_disable_fast_switch(policy); + mutex_lock(&global_tunables_lock); count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook); -- GitLab From f453939c1a4a758312f799748b344bacd1db701f Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 6 Apr 2016 11:06:20 -0400 Subject: [PATCH 1864/9938] net: dsa: document missing functions Add description for the missing port_vlan_prepare, port_fdb_prepare, port_fdb_dump functions in the DSA documentation. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- Documentation/networking/dsa/dsa.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/networking/dsa/dsa.txt b/Documentation/networking/dsa/dsa.txt index 3b196c304b73..013b67066b82 100644 --- a/Documentation/networking/dsa/dsa.txt +++ b/Documentation/networking/dsa/dsa.txt @@ -542,6 +542,12 @@ Bridge layer Bridge VLAN filtering --------------------- +- port_vlan_prepare: bridge layer function invoked when the bridge prepares the + configuration of a VLAN on the given port. If the operation is not supported + by the hardware, this function should return -EOPNOTSUPP to inform the bridge + code to fallback to a software implementation. No hardware setup must be done + in this function. See port_vlan_add for this and details. + - port_vlan_add: bridge layer function invoked when a VLAN is configured (tagged or untagged) for the given switch port @@ -552,6 +558,12 @@ Bridge VLAN filtering function that the driver has to call for each VLAN the given port is a member of. A switchdev object is used to carry the VID and bridge flags. +- port_fdb_prepare: bridge layer function invoked when the bridge prepares the + installation of a Forwarding Database entry. If the operation is not + supported, this function should return -EOPNOTSUPP to inform the bridge code + to fallback to a software implementation. No hardware setup must be done in + this function. See port_fdb_add for this and details. + - port_fdb_add: bridge layer function invoked when the bridge wants to install a Forwarding Database entry, the switch hardware should be programmed with the specified address in the specified VLAN Id in the forwarding database @@ -565,6 +577,10 @@ of DSA, would be the its port-based VLAN, used by the associated bridge device. the specified MAC address from the specified VLAN ID if it was mapped into this port forwarding database +- port_fdb_dump: bridge layer function invoked with a switchdev callback + function that the driver has to call for each MAC address known to be behind + the given port. A switchdev object is used to carry the VID and FDB info. + TODO ==== -- GitLab From 43c44a9f655170fb92536167b95b1c6ae8b732cb Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 6 Apr 2016 11:55:03 -0400 Subject: [PATCH 1865/9938] net: dsa: make the STP state function return void The DSA layer doesn't care about the return code of the port_stp_update routine, so make it void in the layer and the DSA drivers. Replace the useless dsa_slave_stp_update function with a dsa_slave_stp_state function used to reply to the switchdev SWITCHDEV_ATTR_ID_PORT_STP_STATE attribute. In the meantime, rename port_stp_update to port_stp_state_set to explicit the state change. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- Documentation/networking/dsa/dsa.txt | 2 +- drivers/net/dsa/bcm_sf2.c | 16 ++++++-------- drivers/net/dsa/mv88e6171.c | 2 +- drivers/net/dsa/mv88e6352.c | 2 +- drivers/net/dsa/mv88e6xxx.c | 6 ++---- drivers/net/dsa/mv88e6xxx.h | 2 +- include/net/dsa.h | 4 ++-- net/dsa/slave.c | 32 +++++++++++++--------------- 8 files changed, 29 insertions(+), 37 deletions(-) diff --git a/Documentation/networking/dsa/dsa.txt b/Documentation/networking/dsa/dsa.txt index 013b67066b82..ba698c56919d 100644 --- a/Documentation/networking/dsa/dsa.txt +++ b/Documentation/networking/dsa/dsa.txt @@ -533,7 +533,7 @@ Bridge layer out at the switch hardware for the switch to (re) learn MAC addresses behind this port. -- port_stp_update: bridge layer function invoked when a given switch port STP +- port_stp_state_set: bridge layer function invoked when a given switch port STP state is computed by the bridge layer and should be propagated to switch hardware to forward/block/learn traffic. The switch driver is responsible for computing a STP state change based on current and asked parameters and perform diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 95944d5e3e22..2bba1d938694 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -545,12 +545,11 @@ static void bcm_sf2_sw_br_leave(struct dsa_switch *ds, int port) priv->port_sts[port].bridge_dev = NULL; } -static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, - u8 state) +static void bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, + u8 state) { struct bcm_sf2_priv *priv = ds_to_priv(ds); u8 hw_state, cur_hw_state; - int ret = 0; u32 reg; reg = core_readl(priv, CORE_G_PCTL_PORT(port)); @@ -574,7 +573,7 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, break; default: pr_err("%s: invalid STP state: %d\n", __func__, state); - return -EINVAL; + return; } /* Fast-age ARL entries if we are moving a port from Learning or @@ -584,10 +583,9 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, if (cur_hw_state != hw_state) { if (cur_hw_state >= G_MISTP_LEARN_STATE && hw_state <= G_MISTP_LISTEN_STATE) { - ret = bcm_sf2_sw_fast_age_port(ds, port); - if (ret) { + if (bcm_sf2_sw_fast_age_port(ds, port)) { pr_err("%s: fast-ageing failed\n", __func__); - return ret; + return; } } } @@ -596,8 +594,6 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, reg &= ~(G_MISTP_STATE_MASK << G_MISTP_STATE_SHIFT); reg |= hw_state; core_writel(priv, reg, CORE_G_PCTL_PORT(port)); - - return 0; } /* Address Resolution Logic routines */ @@ -1387,7 +1383,7 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = { .set_eee = bcm_sf2_sw_set_eee, .port_bridge_join = bcm_sf2_sw_br_join, .port_bridge_leave = bcm_sf2_sw_br_leave, - .port_stp_update = bcm_sf2_sw_br_set_stp_state, + .port_stp_state_set = bcm_sf2_sw_br_set_stp_state, .port_fdb_prepare = bcm_sf2_sw_fdb_prepare, .port_fdb_add = bcm_sf2_sw_fdb_add, .port_fdb_del = bcm_sf2_sw_fdb_del, diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index c0164b98fc08..0e62f3b5bc81 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -105,7 +105,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .get_regs = mv88e6xxx_get_regs, .port_bridge_join = mv88e6xxx_port_bridge_join, .port_bridge_leave = mv88e6xxx_port_bridge_leave, - .port_stp_update = mv88e6xxx_port_stp_update, + .port_stp_state_set = mv88e6xxx_port_stp_state_set, .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, .port_vlan_add = mv88e6xxx_port_vlan_add, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 5f528abc8af1..7f452e4a04a5 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -326,7 +326,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .get_regs = mv88e6xxx_get_regs, .port_bridge_join = mv88e6xxx_port_bridge_join, .port_bridge_leave = mv88e6xxx_port_bridge_leave, - .port_stp_update = mv88e6xxx_port_stp_update, + .port_stp_state_set = mv88e6xxx_port_stp_state_set, .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, .port_vlan_add = mv88e6xxx_port_vlan_add, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 0dda2817d0ec..53c545cbb779 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1193,7 +1193,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg); } -int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) +void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int stp_state; @@ -1215,14 +1215,12 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) break; } - /* mv88e6xxx_port_stp_update may be called with softirqs disabled, + /* mv88e6xxx_port_stp_state_set may be called with softirqs disabled, * so we can not update the port state directly but need to schedule it. */ ps->ports[port].state = stp_state; set_bit(port, ps->port_state_update_mask); schedule_work(&ps->bridge_work); - - return 0; } static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new, diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 26a424acd10f..49448553c44b 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -497,7 +497,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *bridge); void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port); -int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); +void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering); int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, diff --git a/include/net/dsa.h b/include/net/dsa.h index 6463bb2863ac..2123981fd94a 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -299,8 +299,8 @@ struct dsa_switch_driver { int (*port_bridge_join)(struct dsa_switch *ds, int port, struct net_device *bridge); void (*port_bridge_leave)(struct dsa_switch *ds, int port); - int (*port_stp_update)(struct dsa_switch *ds, int port, - u8 state); + void (*port_stp_state_set)(struct dsa_switch *ds, int port, + u8 state); /* * VLAN support diff --git a/net/dsa/slave.c b/net/dsa/slave.c index a575f0350d5a..088215c3642f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -104,8 +104,8 @@ static int dsa_slave_open(struct net_device *dev) goto clear_promisc; } - if (ds->drv->port_stp_update) - ds->drv->port_stp_update(ds, p->port, stp_state); + if (ds->drv->port_stp_state_set) + ds->drv->port_stp_state_set(ds, p->port, stp_state); if (p->phy) phy_start(p->phy); @@ -147,8 +147,8 @@ static int dsa_slave_close(struct net_device *dev) if (ds->drv->port_disable) ds->drv->port_disable(ds, p->port, p->phy); - if (ds->drv->port_stp_update) - ds->drv->port_stp_update(ds, p->port, BR_STATE_DISABLED); + if (ds->drv->port_stp_state_set) + ds->drv->port_stp_state_set(ds, p->port, BR_STATE_DISABLED); return 0; } @@ -305,16 +305,19 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EOPNOTSUPP; } -static int dsa_slave_stp_update(struct net_device *dev, u8 state) +static int dsa_slave_stp_state_set(struct net_device *dev, + const struct switchdev_attr *attr, + struct switchdev_trans *trans) { struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; - int ret = -EOPNOTSUPP; - if (ds->drv->port_stp_update) - ret = ds->drv->port_stp_update(ds, p->port, state); + if (switchdev_trans_ph_prepare(trans)) + return ds->drv->port_stp_state_set ? 0 : -EOPNOTSUPP; - return ret; + ds->drv->port_stp_state_set(ds, p->port, attr->u.stp_state); + + return 0; } static int dsa_slave_vlan_filtering(struct net_device *dev, @@ -339,17 +342,11 @@ static int dsa_slave_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans) { - struct dsa_slave_priv *p = netdev_priv(dev); - struct dsa_switch *ds = p->parent; int ret; switch (attr->id) { case SWITCHDEV_ATTR_ID_PORT_STP_STATE: - if (switchdev_trans_ph_prepare(trans)) - ret = ds->drv->port_stp_update ? 0 : -EOPNOTSUPP; - else - ret = ds->drv->port_stp_update(ds, p->port, - attr->u.stp_state); + ret = dsa_slave_stp_state_set(dev, attr, trans); break; case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: ret = dsa_slave_vlan_filtering(dev, attr, trans); @@ -468,7 +465,8 @@ static void dsa_slave_bridge_port_leave(struct net_device *dev) /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer, * so allow it to be in BR_STATE_FORWARDING to be kept functional */ - dsa_slave_stp_update(dev, BR_STATE_FORWARDING); + if (ds->drv->port_stp_state_set) + ds->drv->port_stp_state_set(ds, p->port, BR_STATE_FORWARDING); } static int dsa_slave_port_attr_get(struct net_device *dev, -- GitLab From 8497aa618dd605b084fae86e676ea23ca85558b5 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 6 Apr 2016 11:55:04 -0400 Subject: [PATCH 1866/9938] net: dsa: make the FDB add function return void The switchdev design implies that a software error should not happen in the commit phase since it must have been previously reported in the prepare phase. If an hardware error occurs during the commit phase, there is nothing switchdev can do about it. The DSA layer separates port_fdb_prepare and port_fdb_add for simplicity and convenience. If an hardware error occurs during the commit phase, there is no need to report it outside the DSA driver itself. Make the DSA port_fdb_add routine return void for explicitness. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 9 +++++---- drivers/net/dsa/mv88e6xxx.c | 12 +++++------- drivers/net/dsa/mv88e6xxx.h | 6 +++--- include/net/dsa.h | 2 +- net/dsa/slave.c | 16 ++++++++-------- 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 2bba1d938694..780f22876538 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -724,13 +724,14 @@ static int bcm_sf2_sw_fdb_prepare(struct dsa_switch *ds, int port, return 0; } -static int bcm_sf2_sw_fdb_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_fdb *fdb, - struct switchdev_trans *trans) +static void bcm_sf2_sw_fdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) { struct bcm_sf2_priv *priv = ds_to_priv(ds); - return bcm_sf2_arl_op(priv, 0, port, fdb->addr, fdb->vid, true); + if (bcm_sf2_arl_op(priv, 0, port, fdb->addr, fdb->vid, true)) + pr_err("%s: failed to add MAC address\n", __func__); } static int bcm_sf2_sw_fdb_del(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 53c545cbb779..ef36bf6d6cdd 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2090,21 +2090,19 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, return 0; } -int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_fdb *fdb, - struct switchdev_trans *trans) +void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) { int state = is_multicast_ether_addr(fdb->addr) ? GLOBAL_ATU_DATA_STATE_MC_STATIC : GLOBAL_ATU_DATA_STATE_UC_STATIC; struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, state); + if (_mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, state)) + netdev_err(ds->ports[port], "failed to load MAC address\n"); mutex_unlock(&ps->smi_mutex); - - return ret; } int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 49448553c44b..a7dccbe229f2 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -514,9 +514,9 @@ int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb, struct switchdev_trans *trans); -int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_fdb *fdb, - struct switchdev_trans *trans); +void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb); int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, diff --git a/include/net/dsa.h b/include/net/dsa.h index 2123981fd94a..f1670a4daaeb 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -325,7 +325,7 @@ struct dsa_switch_driver { int (*port_fdb_prepare)(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb, struct switchdev_trans *trans); - int (*port_fdb_add)(struct dsa_switch *ds, int port, + void (*port_fdb_add)(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb, struct switchdev_trans *trans); int (*port_fdb_del)(struct dsa_switch *ds, int port, diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 088215c3642f..90bc7442c44f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -256,17 +256,17 @@ static int dsa_slave_port_fdb_add(struct net_device *dev, { struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; - int ret; - if (!ds->drv->port_fdb_prepare || !ds->drv->port_fdb_add) - return -EOPNOTSUPP; + if (switchdev_trans_ph_prepare(trans)) { + if (!ds->drv->port_fdb_prepare || !ds->drv->port_fdb_add) + return -EOPNOTSUPP; - if (switchdev_trans_ph_prepare(trans)) - ret = ds->drv->port_fdb_prepare(ds, p->port, fdb, trans); - else - ret = ds->drv->port_fdb_add(ds, p->port, fdb, trans); + return ds->drv->port_fdb_prepare(ds, p->port, fdb, trans); + } - return ret; + ds->drv->port_fdb_add(ds, p->port, fdb, trans); + + return 0; } static int dsa_slave_port_fdb_del(struct net_device *dev, -- GitLab From 4d5770b39710180644f655b2c6cb0c880d108c63 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 6 Apr 2016 11:55:05 -0400 Subject: [PATCH 1867/9938] net: dsa: make the VLAN add function return void The switchdev design implies that a software error should not happen in the commit phase since it must have been previously reported in the prepare phase. If an hardware error occurs during the commit phase, there is nothing switchdev can do about it. The DSA layer separates port_vlan_prepare and port_vlan_add for simplicity and convenience. If an hardware error occurs during the commit phase, there is no need to report it outside the driver itself. Make the DSA port_vlan_add routine return void for explicitness. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 26 +++++++++++--------------- drivers/net/dsa/mv88e6xxx.h | 6 +++--- include/net/dsa.h | 2 +- net/dsa/slave.c | 11 +++-------- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index ef36bf6d6cdd..62320fca6712 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1908,31 +1908,27 @@ static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, return _mv88e6xxx_vtu_loadpurge(ds, &vlan); } -int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan, - struct switchdev_trans *trans) +void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; u16 vid; - int err = 0; mutex_lock(&ps->smi_mutex); - for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { - err = _mv88e6xxx_port_vlan_add(ds, port, vid, untagged); - if (err) - goto unlock; - } + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) + if (_mv88e6xxx_port_vlan_add(ds, port, vid, untagged)) + netdev_err(ds->ports[port], "failed to add VLAN %d%c\n", + vid, untagged ? 'u' : 't'); - /* no PVID with ranges, otherwise it's a bug */ - if (pvid) - err = _mv88e6xxx_port_pvid_set(ds, port, vlan->vid_end); -unlock: - mutex_unlock(&ps->smi_mutex); + if (pvid && _mv88e6xxx_port_pvid_set(ds, port, vlan->vid_end)) + netdev_err(ds->ports[port], "failed to set PVID %d\n", + vlan->vid_end); - return err; + mutex_unlock(&ps->smi_mutex); } static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index a7dccbe229f2..236bcaa606e7 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -503,9 +503,9 @@ int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans); -int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan, - struct switchdev_trans *trans); +void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans); int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan); int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, diff --git a/include/net/dsa.h b/include/net/dsa.h index f1670a4daaeb..18d1be3ad62d 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -310,7 +310,7 @@ struct dsa_switch_driver { int (*port_vlan_prepare)(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans); - int (*port_vlan_add)(struct dsa_switch *ds, int port, + void (*port_vlan_add)(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans); int (*port_vlan_del)(struct dsa_switch *ds, int port, diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 90bc7442c44f..2dae0d064359 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -207,21 +207,16 @@ static int dsa_slave_port_vlan_add(struct net_device *dev, { struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; - int err; if (switchdev_trans_ph_prepare(trans)) { if (!ds->drv->port_vlan_prepare || !ds->drv->port_vlan_add) return -EOPNOTSUPP; - err = ds->drv->port_vlan_prepare(ds, p->port, vlan, trans); - if (err) - return err; - } else { - err = ds->drv->port_vlan_add(ds, p->port, vlan, trans); - if (err) - return err; + return ds->drv->port_vlan_prepare(ds, p->port, vlan, trans); } + ds->drv->port_vlan_add(ds, p->port, vlan, trans); + return 0; } -- GitLab From 8805eea2494a2837983bc4aaaf6842c89666ec25 Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Fri, 8 Apr 2016 23:54:51 +0300 Subject: [PATCH 1868/9938] Bluetooth: hci_bcsp: fix code style This commit fixed: trailing "*/" trailing spaces mixed indent space between ~ and ( Signed-off-by: Maxim Zhukov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcsp.c | 57 ++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 064f2fefad62..d7d23ceba4d1 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -102,13 +102,12 @@ static const u16 crc_table[] = { /* Initialise the crc calculator */ #define BCSP_CRC_INIT(x) x = 0xffff -/* - Update crc with next data byte - - Implementation note - The data byte is treated as two nibbles. The crc is generated - in reverse, i.e., bits are fed into the register from the top. -*/ +/* Update crc with next data byte + * + * Implementation note + * The data byte is treated as two nibbles. The crc is generated + * in reverse, i.e., bits are fed into the register from the top. + */ static void bcsp_crc_update(u16 *crc, u8 d) { u16 reg = *crc; @@ -223,9 +222,10 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, } /* Max len of packet: (original len +4(bcsp hdr) +2(crc))*2 - (because bytes 0xc0 and 0xdb are escaped, worst case is - when the packet is all made of 0xc0 and 0xdb :) ) - + 2 (0xc0 delimiters at start and end). */ + * (because bytes 0xc0 and 0xdb are escaped, worst case is + * when the packet is all made of 0xc0 and 0xdb :) ) + * + 2 (0xc0 delimiters at start and end). + */ nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC); if (!nskb) @@ -285,7 +285,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) struct bcsp_struct *bcsp = hu->priv; unsigned long flags; struct sk_buff *skb; - + /* First of all, check for unreliable messages in the queue, since they have priority */ @@ -305,8 +305,9 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) } /* Now, try to send a reliable pkt. We can only send a - reliable packet if the number of packets sent but not yet ack'ed - is < than the winsize */ + * reliable packet if the number of packets sent but not yet ack'ed + * is < than the winsize + */ spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); @@ -332,12 +333,14 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) spin_unlock_irqrestore(&bcsp->unack.lock, flags); /* We could not send a reliable packet, either because there are - none or because there are too many unack'ed pkts. Did we receive - any packets we have not acknowledged yet ? */ + * none or because there are too many unack'ed pkts. Did we receive + * any packets we have not acknowledged yet ? + */ if (bcsp->txack_req) { /* if so, craft an empty ACK pkt and send it on BCSP unreliable - channel 0 */ + * channel 0 + */ struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, NULL, 0, BCSP_ACK_PKT); return nskb; } @@ -399,8 +402,9 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) } /* Handle BCSP link-establishment packets. When we - detect a "sync" packet, symptom that the BT module has reset, - we do nothing :) (yet) */ + * detect a "sync" packet, symptom that the BT module has reset, + * we do nothing :) (yet) + */ static void bcsp_handle_le_pkt(struct hci_uart *hu) { struct bcsp_struct *bcsp = hu->priv; @@ -462,7 +466,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char case 0xdd: memcpy(skb_put(bcsp->rx_skb, 1), &db, 1); if ((bcsp->rx_skb->data[0] & 0x40) != 0 && - bcsp->rx_state != BCSP_W4_CRC) + bcsp->rx_state != BCSP_W4_CRC) bcsp_crc_update(&bcsp->message_crc, 0xdb); bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; bcsp->rx_count--; @@ -534,7 +538,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu) } else { BT_ERR("Packet for unknown channel (%u %s)", bcsp->rx_skb->data[1] & 0x0f, - bcsp->rx_skb->data[0] & 0x80 ? + bcsp->rx_skb->data[0] & 0x80 ? "reliable" : "unreliable"); kfree_skb(bcsp->rx_skb); } @@ -562,7 +566,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) struct bcsp_struct *bcsp = hu->priv; const unsigned char *ptr; - BT_DBG("hu %p count %d rx_state %d rx_count %ld", + BT_DBG("hu %p count %d rx_state %d rx_count %ld", hu, count, bcsp->rx_state, bcsp->rx_count); ptr = data; @@ -591,7 +595,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) continue; } if (bcsp->rx_skb->data[0] & 0x80 /* reliable pkt */ - && (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) { + && (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) { BT_ERR("Out-of-order packet arrived, got %u expected %u", bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack); @@ -601,7 +605,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) continue; } bcsp->rx_state = BCSP_W4_DATA; - bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + + bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + (bcsp->rx_skb->data[2] << 4); /* May be 0 */ continue; @@ -615,7 +619,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) case BCSP_W4_CRC: if (bitrev16(bcsp->message_crc) != bscp_get_crc(bcsp)) { - BT_ERR ("Checksum failed: computed %04x received %04x", + BT_ERR("Checksum failed: computed %04x received %04x", bitrev16(bcsp->message_crc), bscp_get_crc(bcsp)); @@ -653,8 +657,9 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) BCSP_CRC_INIT(bcsp->message_crc); /* Do not increment ptr or decrement count - * Allocate packet. Max len of a BCSP pkt= - * 0xFFF (payload) +4 (header) +2 (crc) */ + * Allocate packet. Max len of a BCSP pkt= + * 0xFFF (payload) +4 (header) +2 (crc) + */ bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC); if (!bcsp->rx_skb) { -- GitLab From dbbe972c112838bede8772c2a427c816e9f22839 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 18:08:17 -0400 Subject: [PATCH 1869/9938] cpufreq: ppc_cbe_cpufreq_pmi: make the driver explicitly non-modular The Kconfig for this driver is currently: config CPU_FREQ_CBE_PMI bool "CBE frequency scaling using PMI interface" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular and unused code here, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Signed-off-by: Paul Gortmaker Acked-by: Viresh Kumar [ rjw: Changelog ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/ppc_cbe_cpufreq_pmi.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c index 7969f7690498..7c4cd5c634f2 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -142,15 +142,4 @@ static int __init cbe_cpufreq_pmi_init(void) return 0; } - -static void __exit cbe_cpufreq_pmi_exit(void) -{ - cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); - pmi_unregister_handler(&cbe_pmi_handler); -} - -module_init(cbe_cpufreq_pmi_init); -module_exit(cbe_cpufreq_pmi_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Krafft "); +device_initcall(cbe_cpufreq_pmi_init); -- GitLab From f3f24dea2c7fd949377dc512fe1bfd0b7419afa3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 29 Mar 2016 19:35:12 +0530 Subject: [PATCH 1870/9938] cpufreq: tegra124: No need of setting platform-data All CPUs on Tegra platform share clock/voltage lines and there is absolutely no need of setting platform data for 'cpufreq-dt' platform device, as that's the default case. Stop setting platform data for cpufreq-dt device. Signed-off-by: Viresh Kumar Tested-by: Thierry Reding Acked-by: Thierry Reding Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/tegra124-cpufreq.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c index 20bcceb58ccc..43530254201a 100644 --- a/drivers/cpufreq/tegra124-cpufreq.c +++ b/drivers/cpufreq/tegra124-cpufreq.c @@ -14,7 +14,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include @@ -69,10 +68,6 @@ static void tegra124_cpu_switch_to_pllx(struct tegra124_cpufreq_priv *priv) clk_set_parent(priv->cpu_clk, priv->pllx_clk); } -static struct cpufreq_dt_platform_data cpufreq_dt_pd = { - .independent_clocks = false, -}; - static int tegra124_cpufreq_probe(struct platform_device *pdev) { struct tegra124_cpufreq_priv *priv; @@ -129,8 +124,6 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev) cpufreq_dt_devinfo.name = "cpufreq-dt"; cpufreq_dt_devinfo.parent = &pdev->dev; - cpufreq_dt_devinfo.data = &cpufreq_dt_pd; - cpufreq_dt_devinfo.size_data = sizeof(cpufreq_dt_pd); priv->cpufreq_dt_pdev = platform_device_register_full(&cpufreq_dt_devinfo); -- GitLab From 7e67e239a4f32fa3e2d51dd9a7930018651635b6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 30 Mar 2016 13:45:25 +0530 Subject: [PATCH 1871/9938] cpufreq: dt: Include types.h from cpufreq-dt.h cpufreq-dt.h uses 'bool' data type but doesn't include types.h. It works fine for now as the files that include cpufreq-dt.h, also include types.h directly or indirectly. But, when a file includes cpufreq-dt.h without including types.h, we get a build error. Avoid such errors by including types.h in cpufreq-dt itself. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq-dt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/cpufreq-dt.h b/include/linux/cpufreq-dt.h index 0414009e2c30..a87335a1660c 100644 --- a/include/linux/cpufreq-dt.h +++ b/include/linux/cpufreq-dt.h @@ -10,6 +10,8 @@ #ifndef __CPUFREQ_DT_H__ #define __CPUFREQ_DT_H__ +#include + struct cpufreq_dt_platform_data { /* * True when each CPU has its own clock to control its -- GitLab From f56aad1d98f1c0c6df513abcd275a4d914adc1ef Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 30 Mar 2016 13:45:26 +0530 Subject: [PATCH 1872/9938] cpufreq: dt: Add generic platform-device creation support Multiple platforms are using the generic cpufreq-dt driver now, and all of them are required to create a platform device with name "cpufreq-dt", in order to get the cpufreq-dt probed. Many of them do it from platform code, others have special drivers just to do that. It would be more sensible to do this at a generic place, where all such platform can mark their entries. This patch adds a separate file to get this device created. Currently the compat list of platforms that we support is empty, and will be filled in as and when we move platforms to use it. It always compiles as part of the kernel and so doesn't need a module-exit operation. Signed-off-by: Viresh Kumar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/Kconfig | 10 +++++++++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 32 ++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 drivers/cpufreq/cpufreq-dt-platdev.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 5d74826d75be..b38d5028a03e 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -225,6 +225,7 @@ config CPUFREQ_DT depends on HAVE_CLK && OF # if CPU_THERMAL is on and THERMAL=m, CPUFREQ_DT cannot be =y: depends on !CPU_THERMAL || THERMAL + select CPUFREQ_DT_PLATDEV select PM_OPP help This adds a generic DT based cpufreq driver for frequency management. @@ -233,6 +234,15 @@ config CPUFREQ_DT If in doubt, say N. +config CPUFREQ_DT_PLATDEV + bool + help + This adds a generic DT based cpufreq platdev driver for frequency + management. This creates a 'cpufreq-dt' platform device, on the + supported platforms. + + If in doubt, say N. + if X86 source "drivers/cpufreq/Kconfig.x86" endif diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 6d1186701a9c..d7b646c0f2e9 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o +obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o ################################################################################## # x86 drivers. diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c new file mode 100644 index 000000000000..2a3532427ecf --- /dev/null +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016 Linaro. + * Viresh Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +static const struct of_device_id machines[] = { +}; + +static int __init cpufreq_dt_platdev_init(void) +{ + struct device_node *np = of_find_node_by_path("/"); + + if (!np) + return -ENODEV; + + if (!of_match_node(machines, np)) + return -ENODEV; + + of_node_put(of_root); + + return PTR_ERR_OR_ZERO(platform_device_register_simple("cpufreq-dt", -1, + NULL, 0)); +} +device_initcall(cpufreq_dt_platdev_init); -- GitLab From ea3b05e62f097a604f4dbe7d3ab785a148b61e93 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 30 Mar 2016 13:45:27 +0530 Subject: [PATCH 1873/9938] ARM: exynos: exynos-cpufreq platform device isn't supported anymore The driver is removed long back and we don't support this device anymore. Stop adding it. Signed-off-by: Viresh Kumar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-exynos/exynos.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index bbf51a46f772..4dfce1069406 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -232,12 +232,8 @@ static void __init exynos_cpufreq_init(void) const struct of_device_id *match; match = of_match_node(exynos_cpufreq_matches, root); - if (!match) { - platform_device_register_simple("exynos-cpufreq", -1, NULL, 0); - return; - } - - platform_device_register_simple(match->data, -1, NULL, 0); + if (match) + platform_device_register_simple(match->data, -1, NULL, 0); } static void __init exynos_dt_machine_init(void) -- GitLab From 2249c00a0bf854adf49e8e3c2973feddfbaae71f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 30 Mar 2016 13:45:28 +0530 Subject: [PATCH 1874/9938] cpufreq: exynos: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Signed-off-by: Viresh Kumar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-exynos/exynos.c | 25 ------------------------- drivers/cpufreq/cpufreq-dt-platdev.c | 9 +++++++++ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 4dfce1069406..4d3b056fd786 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -213,29 +213,6 @@ static void __init exynos_init_irq(void) exynos_map_pmu(); } -static const struct of_device_id exynos_cpufreq_matches[] = { - { .compatible = "samsung,exynos3250", .data = "cpufreq-dt" }, - { .compatible = "samsung,exynos4210", .data = "cpufreq-dt" }, - { .compatible = "samsung,exynos4212", .data = "cpufreq-dt" }, - { .compatible = "samsung,exynos4412", .data = "cpufreq-dt" }, - { .compatible = "samsung,exynos5250", .data = "cpufreq-dt" }, -#ifndef CONFIG_BL_SWITCHER - { .compatible = "samsung,exynos5420", .data = "cpufreq-dt" }, - { .compatible = "samsung,exynos5800", .data = "cpufreq-dt" }, -#endif - { /* sentinel */ } -}; - -static void __init exynos_cpufreq_init(void) -{ - struct device_node *root = of_find_node_by_path("/"); - const struct of_device_id *match; - - match = of_match_node(exynos_cpufreq_matches, root); - if (match) - platform_device_register_simple(match->data, -1, NULL, 0); -} - static void __init exynos_dt_machine_init(void) { /* @@ -258,8 +235,6 @@ static void __init exynos_dt_machine_init(void) of_machine_is_compatible("samsung,exynos5250")) platform_device_register(&exynos_cpuidle); - exynos_cpufreq_init(); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 2a3532427ecf..f2ae7ad99a3c 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -12,6 +12,15 @@ #include static const struct of_device_id machines[] = { + { .compatible = "samsung,exynos3250", }, + { .compatible = "samsung,exynos4210", }, + { .compatible = "samsung,exynos4212", }, + { .compatible = "samsung,exynos4412", }, + { .compatible = "samsung,exynos5250", }, +#ifndef CONFIG_BL_SWITCHER + { .compatible = "samsung,exynos5420", }, + { .compatible = "samsung,exynos5800", }, +#endif }; static int __init cpufreq_dt_platdev_init(void) -- GitLab From 22590efb98ae0c84f798a9938c0b6d97bc89adf5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Apr 2016 01:25:58 +0200 Subject: [PATCH 1875/9938] intel_pstate: Avoid pointless FRAC_BITS shifts under div_fp() There are multiple places in intel_pstate where int_tofp() is applied to both arguments of div_fp(), but this is pointless, because int_tofp() simply shifts its argument to the left by FRAC_BITS which mathematically is equivalent to multuplication by 2^FRAC_BITS, so if this is done to both arguments of a division, the extra factors will cancel each other during that operation anyway. Drop the pointless int_tofp() applied to div_fp() arguments throughout the driver. Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 6c7cff13f0ed..8a368d2ee25c 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -341,17 +341,17 @@ static inline void pid_reset(struct _pid *pid, int setpoint, int busy, static inline void pid_p_gain_set(struct _pid *pid, int percent) { - pid->p_gain = div_fp(int_tofp(percent), int_tofp(100)); + pid->p_gain = div_fp(percent, 100); } static inline void pid_i_gain_set(struct _pid *pid, int percent) { - pid->i_gain = div_fp(int_tofp(percent), int_tofp(100)); + pid->i_gain = div_fp(percent, 100); } static inline void pid_d_gain_set(struct _pid *pid, int percent) { - pid->d_gain = div_fp(int_tofp(percent), int_tofp(100)); + pid->d_gain = div_fp(percent, 100); } static signed int pid_calc(struct _pid *pid, int32_t busy) @@ -529,7 +529,7 @@ static ssize_t show_turbo_pct(struct kobject *kobj, total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1; no_turbo = cpu->pstate.max_pstate - cpu->pstate.min_pstate + 1; - turbo_fp = div_fp(int_tofp(no_turbo), int_tofp(total)); + turbo_fp = div_fp(no_turbo, total); turbo_pct = 100 - fp_toint(mul_fp(turbo_fp, int_tofp(100))); return sprintf(buf, "%u\n", turbo_pct); } @@ -600,8 +600,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, limits->max_perf_pct); limits->max_perf_pct = max(limits->min_perf_pct, limits->max_perf_pct); - limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), - int_tofp(100)); + limits->max_perf = div_fp(limits->max_perf_pct, 100); if (hwp_active) intel_pstate_hwp_set_online_cpus(); @@ -625,8 +624,7 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, limits->min_perf_pct); limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct); - limits->min_perf = div_fp(int_tofp(limits->min_perf_pct), - int_tofp(100)); + limits->min_perf = div_fp(limits->min_perf_pct, 100); if (hwp_active) intel_pstate_hwp_set_online_cpus(); @@ -1011,8 +1009,8 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu) struct sample *sample = &cpu->sample; int64_t core_pct; - core_pct = int_tofp(sample->aperf) * int_tofp(100); - core_pct = div64_u64(core_pct, int_tofp(sample->mperf)); + core_pct = sample->aperf * int_tofp(100); + core_pct = div64_u64(core_pct, sample->mperf); sample->core_pct_busy = (int32_t)core_pct; } @@ -1115,8 +1113,8 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) * specified pstate. */ core_busy = cpu->sample.core_pct_busy; - max_pstate = int_tofp(cpu->pstate.max_pstate_physical); - current_pstate = int_tofp(cpu->pstate.current_pstate); + max_pstate = cpu->pstate.max_pstate_physical; + current_pstate = cpu->pstate.current_pstate; core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); /* @@ -1127,8 +1125,7 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) */ duration_ns = cpu->sample.time - cpu->last_sample_time; if ((s64)duration_ns > pid_params.sample_rate_ns * 3) { - sample_ratio = div_fp(int_tofp(pid_params.sample_rate_ns), - int_tofp(duration_ns)); + sample_ratio = div_fp(pid_params.sample_rate_ns, duration_ns); core_busy = mul_fp(core_busy, sample_ratio); } @@ -1328,10 +1325,8 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) /* Make sure min_perf_pct <= max_perf_pct */ limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct); - limits->min_perf = div_fp(int_tofp(limits->min_perf_pct), - int_tofp(100)); - limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), - int_tofp(100)); + limits->min_perf = div_fp(limits->min_perf_pct, 100); + limits->max_perf = div_fp(limits->max_perf_pct, 100); out: intel_pstate_set_update_util_hook(policy->cpu); -- GitLab From d2499d05f0f286a754c26e2bda62210d6a65a774 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 5 Apr 2016 10:38:06 +0800 Subject: [PATCH 1876/9938] cpufreq: mt8173: use list_for_each_entry*() Use list_for_each_entry*() instead of list_for_each*() to simplify the code. Signed-off-by: Geliang Tang Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/mt8173-cpufreq.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c index 2058e6d292ce..6f602c7a71bd 100644 --- a/drivers/cpufreq/mt8173-cpufreq.c +++ b/drivers/cpufreq/mt8173-cpufreq.c @@ -59,11 +59,8 @@ static LIST_HEAD(dvfs_info_list); static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu) { struct mtk_cpu_dvfs_info *info; - struct list_head *list; - - list_for_each(list, &dvfs_info_list) { - info = list_entry(list, struct mtk_cpu_dvfs_info, list_head); + list_for_each_entry(info, &dvfs_info_list, list_head) { if (cpumask_test_cpu(cpu, &info->cpus)) return info; } @@ -524,8 +521,7 @@ static struct cpufreq_driver mt8173_cpufreq_driver = { static int mt8173_cpufreq_probe(struct platform_device *pdev) { - struct mtk_cpu_dvfs_info *info; - struct list_head *list, *tmp; + struct mtk_cpu_dvfs_info *info, *tmp; int cpu, ret; for_each_possible_cpu(cpu) { @@ -559,11 +555,9 @@ static int mt8173_cpufreq_probe(struct platform_device *pdev) return 0; release_dvfs_info_list: - list_for_each_safe(list, tmp, &dvfs_info_list) { - info = list_entry(list, struct mtk_cpu_dvfs_info, list_head); - + list_for_each_entry_safe(info, tmp, &dvfs_info_list, list_head) { mtk_cpu_dvfs_info_release(info); - list_del(list); + list_del(&info->list_head); } return ret; -- GitLab From 4836df173aaed4b93e4d4b5c51e40f12e53ea26f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 Apr 2016 13:28:23 -0700 Subject: [PATCH 1877/9938] intel_pstate: Use pr_fmt Prefix the output using the more common kernel style. Signed-off-by: Joe Perches Acked-by: Srinivas Pandruvada Acked-by: Viresh Kumar [ rjw: Rebase ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 8a368d2ee25c..1866705ee5da 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -10,6 +10,8 @@ * of the License. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -571,7 +573,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, update_turbo_state(); if (limits->turbo_disabled) { - pr_warn("intel_pstate: Turbo disabled by BIOS or unavailable on processor\n"); + pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); return -EPERM; } @@ -1239,7 +1241,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum) intel_pstate_busy_pid_reset(cpu); - pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); + pr_debug("controlling: cpu %d\n", cpunum); return 0; } @@ -1296,12 +1298,12 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { limits = &performance_limits; if (policy->max >= policy->cpuinfo.max_freq) { - pr_debug("intel_pstate: set performance\n"); + pr_debug("set performance\n"); intel_pstate_set_performance_limits(limits); goto out; } } else { - pr_debug("intel_pstate: set powersave\n"); + pr_debug("set powersave\n"); limits = &powersave_limits; } @@ -1353,7 +1355,7 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) int cpu_num = policy->cpu; struct cpudata *cpu = all_cpu_data[cpu_num]; - pr_debug("intel_pstate: CPU %d exiting\n", cpu_num); + pr_debug("CPU %d exiting\n", cpu_num); intel_pstate_clear_update_util_hook(cpu_num); @@ -1598,7 +1600,7 @@ static int __init intel_pstate_init(void) if (intel_pstate_platform_pwr_mgmt_exists()) return -ENODEV; - pr_info("Intel P-state driver initializing.\n"); + pr_info("Intel P-state driver initializing\n"); all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus()); if (!all_cpu_data) @@ -1615,7 +1617,7 @@ static int __init intel_pstate_init(void) intel_pstate_sysfs_expose_params(); if (hwp_active) - pr_info("intel_pstate: HWP enabled\n"); + pr_info("HWP enabled\n"); return rc; out: @@ -1641,7 +1643,7 @@ static int __init intel_pstate_setup(char *str) if (!strcmp(str, "disable")) no_load = 1; if (!strcmp(str, "no_hwp")) { - pr_info("intel_pstate: HWP disabled\n"); + pr_info("HWP disabled\n"); no_hwp = 1; } if (!strcmp(str, "force")) -- GitLab From b49c22a6ca3656c68506fea57caf3d8f08878570 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 Apr 2016 13:28:24 -0700 Subject: [PATCH 1878/9938] cpufreq: Convert printk(KERN_ to pr_ Use the more common logging style. Miscellanea: o Coalesce formats o Realign arguments o Add a missing space between a coalesced format Signed-off-by: Joe Perches Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/acpi-cpufreq.c | 10 +-- drivers/cpufreq/cpufreq-nforce2.c | 24 +++---- drivers/cpufreq/e_powersaver.c | 60 +++++++---------- drivers/cpufreq/elanfreq.c | 2 +- drivers/cpufreq/ia64-acpi-cpufreq.c | 9 ++- drivers/cpufreq/longhaul.c | 80 ++++++++++------------- drivers/cpufreq/loongson2_cpufreq.c | 2 +- drivers/cpufreq/maple-cpufreq.c | 9 ++- drivers/cpufreq/omap-cpufreq.c | 4 +- drivers/cpufreq/p4-clockmod.c | 15 +---- drivers/cpufreq/pmac32-cpufreq.c | 12 ++-- drivers/cpufreq/pmac64-cpufreq.c | 43 ++++++------ drivers/cpufreq/powernow-k6.c | 13 ++-- drivers/cpufreq/powernow-k7.c | 65 ++++++++---------- drivers/cpufreq/pxa2xx-cpufreq.c | 7 +- drivers/cpufreq/s3c2412-cpufreq.c | 13 ++-- drivers/cpufreq/s3c2440-cpufreq.c | 4 +- drivers/cpufreq/s3c24xx-cpufreq-debugfs.c | 2 +- drivers/cpufreq/s3c24xx-cpufreq.c | 57 ++++++++-------- drivers/cpufreq/s5pv210-cpufreq.c | 4 +- drivers/cpufreq/sc520_freq.c | 6 +- drivers/cpufreq/speedstep-centrino.c | 3 +- drivers/cpufreq/speedstep-ich.c | 6 +- drivers/cpufreq/speedstep-lib.c | 9 +-- drivers/cpufreq/speedstep-smi.c | 5 +- 25 files changed, 199 insertions(+), 265 deletions(-) diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 7f38fb55f223..ed9e93df7ecf 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -648,10 +648,7 @@ static int acpi_cpufreq_blacklist(struct cpuinfo_x86 *c) if ((c->x86 == 15) && (c->x86_model == 6) && (c->x86_mask == 8)) { - printk(KERN_INFO "acpi-cpufreq: Intel(R) " - "Xeon(R) 7100 Errata AL30, processors may " - "lock up on frequency changes: disabling " - "acpi-cpufreq.\n"); + pr_info("acpi-cpufreq: Intel(R) Xeon(R) 7100 Errata AL30, processors may lock up on frequency changes: disabling acpi-cpufreq\n"); return -ENODEV; } } @@ -799,8 +796,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) if (perf->control_register.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE && policy->cpuinfo.transition_latency > 20 * 1000) { policy->cpuinfo.transition_latency = 20 * 1000; - printk_once(KERN_INFO - "P-state transition latency capped at 20 uS\n"); + pr_info_once("P-state transition latency capped at 20 uS\n"); } /* table init */ @@ -822,7 +818,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) goto err_freqfree; if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq) - printk(KERN_WARNING FW_WARN "P-state 0 is not max freq\n"); + pr_warn(FW_WARN "P-state 0 is not max freq\n"); switch (perf->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index db69eeb501a7..7da96d536ac9 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c @@ -174,13 +174,13 @@ static int nforce2_set_fsb(unsigned int fsb) int pll = 0; if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) { - printk(KERN_ERR PFX "FSB %d is out of range!\n", fsb); + pr_err(PFX "FSB %d is out of range!\n", fsb); return -EINVAL; } tfsb = nforce2_fsb_read(0); if (!tfsb) { - printk(KERN_ERR PFX "Error while reading the FSB\n"); + pr_err(PFX "Error while reading the FSB\n"); return -EINVAL; } @@ -276,8 +276,7 @@ static int nforce2_target(struct cpufreq_policy *policy, /* local_irq_save(flags); */ if (nforce2_set_fsb(target_fsb) < 0) - printk(KERN_ERR PFX "Changing FSB to %d failed\n", - target_fsb); + pr_err(PFX "Changing FSB to %d failed\n", target_fsb); else pr_debug("Changed FSB successfully to %d\n", target_fsb); @@ -325,8 +324,7 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) /* FIX: Get FID from CPU */ if (!fid) { if (!cpu_khz) { - printk(KERN_WARNING PFX - "cpu_khz not set, can't calculate multiplier!\n"); + pr_warn(PFX "cpu_khz not set, can't calculate multiplier!\n"); return -ENODEV; } @@ -341,8 +339,8 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) } } - printk(KERN_INFO PFX "FSB currently at %i MHz, FID %d.%d\n", fsb, - fid / 10, fid % 10); + pr_info(PFX "FSB currently at %i MHz, FID %d.%d\n", + fsb, fid / 10, fid % 10); /* Set maximum FSB to FSB at boot time */ max_fsb = nforce2_fsb_read(1); @@ -401,11 +399,9 @@ static int nforce2_detect_chipset(void) if (nforce2_dev == NULL) return -ENODEV; - printk(KERN_INFO PFX "Detected nForce2 chipset revision %X\n", - nforce2_dev->revision); - printk(KERN_INFO PFX - "FSB changing is maybe unstable and can lead to " - "crashes and data loss.\n"); + pr_info(PFX "Detected nForce2 chipset revision %X\n", + nforce2_dev->revision); + pr_info(PFX "FSB changing is maybe unstable and can lead to crashes and data loss\n"); return 0; } @@ -423,7 +419,7 @@ static int __init nforce2_init(void) /* detect chipset */ if (nforce2_detect_chipset()) { - printk(KERN_INFO PFX "No nForce2 chipset.\n"); + pr_info(PFX "No nForce2 chipset\n"); return -ENODEV; } diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 4085244c8a67..c420f0cb46a7 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -141,11 +141,9 @@ static int eps_set_state(struct eps_cpu_data *centaur, /* Print voltage and multiplier */ rdmsr(MSR_IA32_PERF_STATUS, lo, hi); current_voltage = lo & 0xff; - printk(KERN_INFO "eps: Current voltage = %dmV\n", - current_voltage * 16 + 700); + pr_info("eps: Current voltage = %dmV\n", current_voltage * 16 + 700); current_multiplier = (lo >> 8) & 0xff; - printk(KERN_INFO "eps: Current multiplier = %d\n", - current_multiplier); + pr_info("eps: Current multiplier = %d\n", current_multiplier); } #endif return 0; @@ -166,7 +164,7 @@ static int eps_target(struct cpufreq_policy *policy, unsigned int index) dest_state = centaur->freq_table[index].driver_data & 0xffff; ret = eps_set_state(centaur, policy, dest_state); if (ret) - printk(KERN_ERR "eps: Timeout!\n"); + pr_err("eps: Timeout!\n"); return ret; } @@ -194,36 +192,36 @@ static int eps_cpu_init(struct cpufreq_policy *policy) return -ENODEV; /* Check brand */ - printk(KERN_INFO "eps: Detected VIA "); + pr_info("eps: Detected VIA "); switch (c->x86_model) { case 10: rdmsr(0x1153, lo, hi); brand = (((lo >> 2) ^ lo) >> 18) & 3; - printk(KERN_CONT "Model A "); + pr_cont("Model A "); break; case 13: rdmsr(0x1154, lo, hi); brand = (((lo >> 4) ^ (lo >> 2))) & 0x000000ff; - printk(KERN_CONT "Model D "); + pr_cont("Model D "); break; } switch (brand) { case EPS_BRAND_C7M: - printk(KERN_CONT "C7-M\n"); + pr_cont("C7-M\n"); break; case EPS_BRAND_C7: - printk(KERN_CONT "C7\n"); + pr_cont("C7\n"); break; case EPS_BRAND_EDEN: - printk(KERN_CONT "Eden\n"); + pr_cont("Eden\n"); break; case EPS_BRAND_C7D: - printk(KERN_CONT "C7-D\n"); + pr_cont("C7-D\n"); break; case EPS_BRAND_C3: - printk(KERN_CONT "C3\n"); + pr_cont("C3\n"); return -ENODEV; break; } @@ -235,7 +233,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Can be locked at 0 */ rdmsrl(MSR_IA32_MISC_ENABLE, val); if (!(val & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) { - printk(KERN_INFO "eps: Can't enable Enhanced PowerSaver\n"); + pr_info("eps: Can't enable Enhanced PowerSaver\n"); return -ENODEV; } } @@ -243,22 +241,19 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Print voltage and multiplier */ rdmsr(MSR_IA32_PERF_STATUS, lo, hi); current_voltage = lo & 0xff; - printk(KERN_INFO "eps: Current voltage = %dmV\n", - current_voltage * 16 + 700); + pr_info("eps: Current voltage = %dmV\n", current_voltage * 16 + 700); current_multiplier = (lo >> 8) & 0xff; - printk(KERN_INFO "eps: Current multiplier = %d\n", current_multiplier); + pr_info("eps: Current multiplier = %d\n", current_multiplier); /* Print limits */ max_voltage = hi & 0xff; - printk(KERN_INFO "eps: Highest voltage = %dmV\n", - max_voltage * 16 + 700); + pr_info("eps: Highest voltage = %dmV\n", max_voltage * 16 + 700); max_multiplier = (hi >> 8) & 0xff; - printk(KERN_INFO "eps: Highest multiplier = %d\n", max_multiplier); + pr_info("eps: Highest multiplier = %d\n", max_multiplier); min_voltage = (hi >> 16) & 0xff; - printk(KERN_INFO "eps: Lowest voltage = %dmV\n", - min_voltage * 16 + 700); + pr_info("eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700); min_multiplier = (hi >> 24) & 0xff; - printk(KERN_INFO "eps: Lowest multiplier = %d\n", min_multiplier); + pr_info("eps: Lowest multiplier = %d\n", min_multiplier); /* Sanity checks */ if (current_multiplier == 0 || max_multiplier == 0 @@ -276,17 +271,13 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Check for systems using underclocked CPU */ if (!freq_failsafe_off && max_multiplier != current_multiplier) { - printk(KERN_INFO "eps: Your processor is running at different " - "frequency then its maximum. Aborting.\n"); - printk(KERN_INFO "eps: You can use freq_failsafe_off option " - "to disable this check.\n"); + pr_info("eps: Your processor is running at different frequency then its maximum. Aborting.\n"); + pr_info("eps: You can use freq_failsafe_off option to disable this check.\n"); return -EINVAL; } if (!voltage_failsafe_off && max_voltage != current_voltage) { - printk(KERN_INFO "eps: Your processor is running at different " - "voltage then its maximum. Aborting.\n"); - printk(KERN_INFO "eps: You can use voltage_failsafe_off " - "option to disable this check.\n"); + pr_info("eps: Your processor is running at different voltage then its maximum. Aborting.\n"); + pr_info("eps: You can use voltage_failsafe_off option to disable this check.\n"); return -EINVAL; } @@ -297,13 +288,13 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Check for ACPI processor speed limit */ if (!ignore_acpi_limit && !eps_acpi_init()) { if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) { - printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n", + pr_info("eps: ACPI limit %u.%uGHz\n", limit/1000000, (limit%1000000)/10000); eps_acpi_exit(policy); /* Check if max_multiplier is in BIOS limits */ if (limit && max_multiplier * fsb > limit) { - printk(KERN_INFO "eps: Aborting.\n"); + pr_info("eps: Aborting\n"); return -EINVAL; } } @@ -319,8 +310,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) v = (set_max_voltage - 700) / 16; /* Check if voltage is within limits */ if (v >= min_voltage && v <= max_voltage) { - printk(KERN_INFO "eps: Setting %dmV as maximum.\n", - v * 16 + 700); + pr_info("eps: Setting %dmV as maximum\n", v * 16 + 700); max_voltage = v; } } diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index 1c06e786c9ba..8f4dded3016f 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -185,7 +185,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) static int __init elanfreq_setup(char *str) { max_freq = simple_strtoul(str, &str, 0); - printk(KERN_WARNING "You're using the deprecated elanfreq command line option. Use elanfreq.max_freq instead, please!\n"); + pr_warn("You're using the deprecated elanfreq command line option. Use elanfreq.max_freq instead, please!\n"); return 1; } __setup("elanfreq=", elanfreq_setup); diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 0202429f1c5b..fd36d6cd3787 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -118,8 +118,7 @@ processor_get_freq ( if (ret) { set_cpus_allowed_ptr(current, &saved_mask); - printk(KERN_WARNING "get performance failed with error %d\n", - ret); + pr_warn("get performance failed with error %d\n", ret); ret = 0; goto migrate_end; } @@ -177,7 +176,7 @@ processor_set_freq ( ret = processor_set_pstate(value); if (ret) { - printk(KERN_WARNING "Transition failed with error %d\n", ret); + pr_warn("Transition failed with error %d\n", ret); retval = -ENODEV; goto migrate_end; } @@ -291,8 +290,8 @@ acpi_cpufreq_cpu_init ( /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); - printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management " - "activated.\n", cpu); + pr_info("acpi-cpufreq: CPU%u - ACPI performance management activated\n", + cpu); for (i = 0; i < data->acpi_data.state_count; i++) pr_debug(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n", diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 0f6b229afcb9..2baeb8c01474 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -347,14 +347,13 @@ static int longhaul_setstate(struct cpufreq_policy *policy, freqs.new = calc_speed(longhaul_get_cpu_mult()); /* Check if requested frequency is set. */ if (unlikely(freqs.new != speed)) { - printk(KERN_INFO PFX "Failed to set requested frequency!\n"); + pr_info(PFX "Failed to set requested frequency!\n"); /* Revision ID = 1 but processor is expecting revision key * equal to 0. Jumpers at the bottom of processor will change * multiplier and FSB, but will not change bits in Longhaul * MSR nor enable voltage scaling. */ if (!revid_errata) { - printk(KERN_INFO PFX "Enabling \"Ignore Revision ID\" " - "option.\n"); + pr_info(PFX "Enabling \"Ignore Revision ID\" option\n"); revid_errata = 1; msleep(200); goto retry_loop; @@ -364,11 +363,10 @@ static int longhaul_setstate(struct cpufreq_policy *policy, * but it doesn't change frequency. I tried poking various * bits in northbridge registers, but without success. */ if (longhaul_flags & USE_ACPI_C3) { - printk(KERN_INFO PFX "Disabling ACPI C3 support.\n"); + pr_info(PFX "Disabling ACPI C3 support\n"); longhaul_flags &= ~USE_ACPI_C3; if (revid_errata) { - printk(KERN_INFO PFX "Disabling \"Ignore " - "Revision ID\" option.\n"); + pr_info(PFX "Disabling \"Ignore Revision ID\" option\n"); revid_errata = 0; } msleep(200); @@ -379,7 +377,7 @@ static int longhaul_setstate(struct cpufreq_policy *policy, * RevID = 1. RevID errata will make things right. Just * to be 100% sure. */ if (longhaul_version == TYPE_LONGHAUL_V2) { - printk(KERN_INFO PFX "Switching to Longhaul ver. 1\n"); + pr_info(PFX "Switching to Longhaul ver. 1\n"); longhaul_version = TYPE_LONGHAUL_V1; msleep(200); goto retry_loop; @@ -387,8 +385,7 @@ static int longhaul_setstate(struct cpufreq_policy *policy, } if (!bm_timeout) { - printk(KERN_INFO PFX "Warning: Timeout while waiting for " - "idle PCI bus.\n"); + pr_info(PFX "Warning: Timeout while waiting for idle PCI bus\n"); return -EBUSY; } @@ -433,12 +430,12 @@ static int longhaul_get_ranges(void) /* Get current frequency */ mult = longhaul_get_cpu_mult(); if (mult == -1) { - printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n"); + pr_info(PFX "Invalid (reserved) multiplier!\n"); return -EINVAL; } fsb = guess_fsb(mult); if (fsb == 0) { - printk(KERN_INFO PFX "Invalid (reserved) FSB!\n"); + pr_info(PFX "Invalid (reserved) FSB!\n"); return -EINVAL; } /* Get max multiplier - as we always did. @@ -468,11 +465,11 @@ static int longhaul_get_ranges(void) print_speed(highest_speed/1000)); if (lowest_speed == highest_speed) { - printk(KERN_INFO PFX "highestspeed == lowest, aborting.\n"); + pr_info(PFX "highestspeed == lowest, aborting\n"); return -EINVAL; } if (lowest_speed > highest_speed) { - printk(KERN_INFO PFX "nonsense! lowest (%d > %d) !\n", + pr_info(PFX "nonsense! lowest (%d > %d) !\n", lowest_speed, highest_speed); return -EINVAL; } @@ -538,16 +535,16 @@ static void longhaul_setup_voltagescaling(void) rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); if (!(longhaul.bits.RevisionID & 1)) { - printk(KERN_INFO PFX "Voltage scaling not supported by CPU.\n"); + pr_info(PFX "Voltage scaling not supported by CPU\n"); return; } if (!longhaul.bits.VRMRev) { - printk(KERN_INFO PFX "VRM 8.5\n"); + pr_info(PFX "VRM 8.5\n"); vrm_mV_table = &vrm85_mV[0]; mV_vrm_table = &mV_vrm85[0]; } else { - printk(KERN_INFO PFX "Mobile VRM\n"); + pr_info(PFX "Mobile VRM\n"); if (cpu_model < CPU_NEHEMIAH) return; vrm_mV_table = &mobilevrm_mV[0]; @@ -558,27 +555,21 @@ static void longhaul_setup_voltagescaling(void) maxvid = vrm_mV_table[longhaul.bits.MaximumVID]; if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) { - printk(KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. " - "Voltage scaling disabled.\n", - minvid.mV/1000, minvid.mV%1000, - maxvid.mV/1000, maxvid.mV%1000); + pr_info(PFX "Bogus values Min:%d.%03d Max:%d.%03d - Voltage scaling disabled\n", + minvid.mV/1000, minvid.mV%1000, + maxvid.mV/1000, maxvid.mV%1000); return; } if (minvid.mV == maxvid.mV) { - printk(KERN_INFO PFX "Claims to support voltage scaling but " - "min & max are both %d.%03d. " - "Voltage scaling disabled\n", - maxvid.mV/1000, maxvid.mV%1000); + pr_info(PFX "Claims to support voltage scaling but min & max are both %d.%03d - Voltage scaling disabled\n", + maxvid.mV/1000, maxvid.mV%1000); return; } /* How many voltage steps*/ numvscales = maxvid.pos - minvid.pos + 1; - printk(KERN_INFO PFX - "Max VID=%d.%03d " - "Min VID=%d.%03d, " - "%d possible voltage scales\n", + pr_info(PFX "Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n", maxvid.mV/1000, maxvid.mV%1000, minvid.mV/1000, minvid.mV%1000, numvscales); @@ -617,12 +608,12 @@ static void longhaul_setup_voltagescaling(void) pos = minvid.pos; freq_pos->driver_data |= mV_vrm_table[pos] << 8; vid = vrm_mV_table[mV_vrm_table[pos]]; - printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", + pr_info(PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, (int)(freq_pos - longhaul_table), vid.mV); } can_scale_voltage = 1; - printk(KERN_INFO PFX "Voltage scaling enabled.\n"); + pr_info(PFX "Voltage scaling enabled\n"); } @@ -720,8 +711,7 @@ static int enable_arbiter_disable(void) pci_write_config_byte(dev, reg, pci_cmd); pci_read_config_byte(dev, reg, &pci_cmd); if (!(pci_cmd & 1<<7)) { - printk(KERN_ERR PFX - "Can't enable access to port 0x22.\n"); + pr_err(PFX "Can't enable access to port 0x22\n"); status = 0; } } @@ -758,8 +748,7 @@ static int longhaul_setup_southbridge(void) if (pci_cmd & 1 << 7) { pci_read_config_dword(dev, 0x88, &acpi_regs_addr); acpi_regs_addr &= 0xff00; - printk(KERN_INFO PFX "ACPI I/O at 0x%x\n", - acpi_regs_addr); + pr_info(PFX "ACPI I/O at 0x%x\n", acpi_regs_addr); } pci_dev_put(dev); @@ -853,14 +842,14 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) longhaul_version = TYPE_LONGHAUL_V1; } - printk(KERN_INFO PFX "VIA %s CPU detected. ", cpuname); + pr_info(PFX "VIA %s CPU detected. ", cpuname); switch (longhaul_version) { case TYPE_LONGHAUL_V1: case TYPE_LONGHAUL_V2: - printk(KERN_CONT "Longhaul v%d supported.\n", longhaul_version); + pr_cont("Longhaul v%d supported\n", longhaul_version); break; case TYPE_POWERSAVER: - printk(KERN_CONT "Powersaver supported.\n"); + pr_cont("Powersaver supported\n"); break; }; @@ -889,15 +878,14 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) if (!(longhaul_flags & USE_ACPI_C3 || longhaul_flags & USE_NORTHBRIDGE) && ((pr == NULL) || !(pr->flags.bm_control))) { - printk(KERN_ERR PFX - "No ACPI support. Unsupported northbridge.\n"); + pr_err(PFX "No ACPI support: Unsupported northbridge\n"); return -ENODEV; } if (longhaul_flags & USE_NORTHBRIDGE) - printk(KERN_INFO PFX "Using northbridge support.\n"); + pr_info(PFX "Using northbridge support\n"); if (longhaul_flags & USE_ACPI_C3) - printk(KERN_INFO PFX "Using ACPI support.\n"); + pr_info(PFX "Using ACPI support\n"); ret = longhaul_get_ranges(); if (ret != 0) @@ -934,20 +922,18 @@ static int __init longhaul_init(void) return -ENODEV; if (!enable) { - printk(KERN_ERR PFX "Option \"enable\" not set. Aborting.\n"); + pr_err(PFX "Option \"enable\" not set - Aborting\n"); return -ENODEV; } #ifdef CONFIG_SMP if (num_online_cpus() > 1) { - printk(KERN_ERR PFX "More than 1 CPU detected, " - "longhaul disabled.\n"); + pr_err(PFX "More than 1 CPU detected, longhaul disabled\n"); return -ENODEV; } #endif #ifdef CONFIG_X86_IO_APIC if (cpu_has_apic) { - printk(KERN_ERR PFX "APIC detected. Longhaul is currently " - "broken in this configuration.\n"); + pr_err(PFX "APIC detected. Longhaul is currently broken in this configuration.\n"); return -ENODEV; } #endif @@ -955,7 +941,7 @@ static int __init longhaul_init(void) case 6 ... 9: return cpufreq_register_driver(&longhaul_driver); case 10: - printk(KERN_ERR PFX "Use acpi-cpufreq driver for VIA C7\n"); + pr_err(PFX "Use acpi-cpufreq driver for VIA C7\n"); default: ; } diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index cd593c1f66dc..93c7928cf461 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -76,7 +76,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) cpuclk = clk_get(NULL, "cpu_clk"); if (IS_ERR(cpuclk)) { - printk(KERN_ERR "cpufreq: couldn't get CPU clk\n"); + pr_err("cpufreq: couldn't get CPU clk\n"); return PTR_ERR(cpuclk); } diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index cc3408fc073f..7e55632291d7 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -174,7 +174,7 @@ static int __init maple_cpufreq_init(void) /* Get first CPU node */ cpunode = of_cpu_device_node_get(0); if (cpunode == NULL) { - printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n"); + pr_err("cpufreq: Can't find any CPU 0 node\n"); goto bail_noprops; } @@ -182,8 +182,7 @@ static int __init maple_cpufreq_init(void) /* we actually don't care on which CPU to access PVR */ pvr_hi = PVR_VER(mfspr(SPRN_PVR)); if (pvr_hi != 0x3c && pvr_hi != 0x44) { - printk(KERN_ERR "cpufreq: Unsupported CPU version (%x)\n", - pvr_hi); + pr_err("cpufreq: Unsupported CPU version (%x)\n", pvr_hi); goto bail_noprops; } @@ -222,8 +221,8 @@ static int __init maple_cpufreq_init(void) maple_pmode_cur = -1; maple_scom_switch_freq(maple_scom_query_freq()); - printk(KERN_INFO "Registering Maple CPU frequency driver\n"); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + pr_info("Registering Maple CPU frequency driver\n"); + pr_info("Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", maple_cpu_freqs[1].frequency/1000, maple_cpu_freqs[0].frequency/1000, maple_cpu_freqs[maple_pmode_cur].frequency/1000); diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index e3866e0d5bf8..655fc9427626 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -163,13 +163,13 @@ static int omap_cpufreq_probe(struct platform_device *pdev) { mpu_dev = get_cpu_device(0); if (!mpu_dev) { - pr_warning("%s: unable to get the mpu device\n", __func__); + pr_warn("%s: unable to get the mpu device\n", __func__); return -EINVAL; } mpu_reg = regulator_get(mpu_dev, "vcc"); if (IS_ERR(mpu_reg)) { - pr_warning("%s: unable to get MPU regulator\n", __func__); + pr_warn("%s: unable to get MPU regulator\n", __func__); mpu_reg = NULL; } else { /* diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 5dd95dab580d..4d1a44370338 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -124,11 +124,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) { if (c->x86 == 0x06) { if (cpu_has(c, X86_FEATURE_EST)) - printk_once(KERN_WARNING PFX "Warning: EST-capable " - "CPU detected. The acpi-cpufreq module offers " - "voltage scaling in addition to frequency " - "scaling. You should use that instead of " - "p4-clockmod, if possible.\n"); + pr_warn_once(PFX "Warning: EST-capable CPU detected. The acpi-cpufreq module offers voltage scaling in addition to frequency scaling. You should use that instead of p4-clockmod, if possible.\n"); switch (c->x86_model) { case 0x0E: /* Core */ case 0x0F: /* Core Duo */ @@ -152,11 +148,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4M) { - printk(KERN_WARNING PFX "Warning: Pentium 4-M detected. " - "The speedstep-ich or acpi cpufreq modules offer " - "voltage scaling in addition of frequency scaling. " - "You should use either one instead of p4-clockmod, " - "if possible.\n"); + pr_warn(PFX "Warning: Pentium 4-M detected. The speedstep-ich or acpi cpufreq modules offer voltage scaling in addition of frequency scaling. You should use either one instead of p4-clockmod, if possible.\n"); return speedstep_get_frequency(SPEEDSTEP_CPU_P4M); } @@ -265,8 +257,7 @@ static int __init cpufreq_p4_init(void) ret = cpufreq_register_driver(&p4clockmod_driver); if (!ret) - printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock " - "Modulation available\n"); + pr_info(PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); return ret; } diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 1f49d97a70ea..072d7b3841b9 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -481,13 +481,13 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) freqs = of_get_property(cpunode, "bus-frequencies", &lenp); lenp /= sizeof(u32); if (freqs == NULL || lenp != 2) { - printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); + pr_err("cpufreq: bus-frequencies incorrect or missing\n"); return 1; } ratio = of_get_property(cpunode, "processor-to-bus-ratio*2", NULL); if (ratio == NULL) { - printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); + pr_err("cpufreq: processor-to-bus-ratio*2 missing\n"); return 1; } @@ -550,7 +550,7 @@ static int pmac_cpufreq_init_7447A(struct device_node *cpunode) if (volt_gpio_np) voltage_gpio = read_gpio(volt_gpio_np); if (!voltage_gpio){ - printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); + pr_err("cpufreq: missing cpu-vcore-select gpio\n"); return 1; } @@ -675,9 +675,9 @@ static int __init pmac_cpufreq_setup(void) pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; ppc_proc_freq = cur_freq * 1000ul; - printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", - low_freq/1000, hi_freq/1000, cur_freq/1000); + pr_info("Registering PowerMac CPU frequency driver\n"); + pr_info("Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", + low_freq/1000, hi_freq/1000, cur_freq/1000); return cpufreq_register_driver(&pmac_cpufreq_driver); } diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 4ff86878727f..5ffe0855ba8f 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -138,7 +138,7 @@ static void g5_vdnap_switch_volt(int speed_mode) usleep_range(1000, 1000); } if (done == 0) - printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n"); + pr_warn("cpufreq: Timeout in clock slewing !\n"); } @@ -266,7 +266,7 @@ static int g5_pfunc_switch_freq(int speed_mode) rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL); if (rc) - printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc); + pr_warn("cpufreq: pfunc switch error %d\n", rc); /* It's an irq GPIO so we should be able to just block here, * I'll do that later after I've properly tested the IRQ code for @@ -282,7 +282,7 @@ static int g5_pfunc_switch_freq(int speed_mode) usleep_range(500, 500); } if (done == 0) - printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n"); + pr_warn("cpufreq: Timeout in clock slewing !\n"); /* If frequency is going down, last ramp the voltage */ if (speed_mode > g5_pmode_cur) @@ -368,7 +368,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) } pvr_hi = (*valp) >> 16; if (pvr_hi != 0x3c && pvr_hi != 0x44) { - printk(KERN_ERR "cpufreq: Unsupported CPU version\n"); + pr_err("cpufreq: Unsupported CPU version\n"); goto bail_noprops; } @@ -403,8 +403,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) root = of_find_node_by_path("/"); if (root == NULL) { - printk(KERN_ERR "cpufreq: Can't find root of " - "device tree\n"); + pr_err("cpufreq: Can't find root of device tree\n"); goto bail_noprops; } pfunc_set_vdnap0 = pmf_find_function(root, "set-vdnap0"); @@ -412,8 +411,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) pmf_find_function(root, "slewing-done"); if (pfunc_set_vdnap0 == NULL || pfunc_vdnap0_complete == NULL) { - printk(KERN_ERR "cpufreq: Can't find required " - "platform function\n"); + pr_err("cpufreq: Can't find required platform function\n"); goto bail_noprops; } @@ -453,10 +451,10 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) g5_pmode_cur = -1; g5_switch_freq(g5_query_freq()); - printk(KERN_INFO "Registering G5 CPU frequency driver\n"); - printk(KERN_INFO "Frequency method: %s, Voltage method: %s\n", - freq_method, volt_method); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + pr_info("Registering G5 CPU frequency driver\n"); + pr_info("Frequency method: %s, Voltage method: %s\n", + freq_method, volt_method); + pr_info("Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", g5_cpu_freqs[1].frequency/1000, g5_cpu_freqs[0].frequency/1000, g5_cpu_freqs[g5_pmode_cur].frequency/1000); @@ -493,7 +491,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) if (cpuid != NULL) eeprom = of_get_property(cpuid, "cpuid", NULL); if (eeprom == NULL) { - printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n"); + pr_err("cpufreq: Can't find cpuid EEPROM !\n"); rc = -ENODEV; goto bail; } @@ -511,7 +509,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) break; } if (hwclock == NULL) { - printk(KERN_ERR "cpufreq: Can't find i2c clock chip !\n"); + pr_err("cpufreq: Can't find i2c clock chip !\n"); rc = -ENODEV; goto bail; } @@ -539,7 +537,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Check we have minimum requirements */ if (pfunc_cpu_getfreq == NULL || pfunc_cpu_setfreq_high == NULL || pfunc_cpu_setfreq_low == NULL || pfunc_slewing_done == NULL) { - printk(KERN_ERR "cpufreq: Can't find platform functions !\n"); + pr_err("cpufreq: Can't find platform functions !\n"); rc = -ENODEV; goto bail; } @@ -567,7 +565,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Get max frequency from device-tree */ valp = of_get_property(cpunode, "clock-frequency", NULL); if (!valp) { - printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n"); + pr_err("cpufreq: Can't find CPU frequency !\n"); rc = -ENODEV; goto bail; } @@ -583,8 +581,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Check for machines with no useful settings */ if (il == ih) { - printk(KERN_WARNING "cpufreq: No low frequency mode available" - " on this model !\n"); + pr_warn("cpufreq: No low frequency mode available on this model !\n"); rc = -ENODEV; goto bail; } @@ -595,7 +592,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Sanity check */ if (min_freq >= max_freq || min_freq < 1000) { - printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n"); + pr_err("cpufreq: Can't calculate low frequency !\n"); rc = -ENXIO; goto bail; } @@ -619,10 +616,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) g5_pmode_cur = -1; g5_switch_freq(g5_query_freq()); - printk(KERN_INFO "Registering G5 CPU frequency driver\n"); - printk(KERN_INFO "Frequency method: i2c/pfunc, " - "Voltage method: %s\n", has_volt ? "i2c/pfunc" : "none"); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + pr_info("Registering G5 CPU frequency driver\n"); + pr_info("Frequency method: i2c/pfunc, Voltage method: %s\n", + has_volt ? "i2c/pfunc" : "none"); + pr_info("Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", g5_cpu_freqs[1].frequency/1000, g5_cpu_freqs[0].frequency/1000, g5_cpu_freqs[g5_pmode_cur].frequency/1000); diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index e6f24b281e3e..981f40b1caf4 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -141,7 +141,7 @@ static int powernow_k6_target(struct cpufreq_policy *policy, { if (clock_ratio[best_i].driver_data > max_multiplier) { - printk(KERN_ERR PFX "invalid target frequency\n"); + pr_err(PFX "invalid target frequency\n"); return -EINVAL; } @@ -175,13 +175,14 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) max_multiplier = param_max_multiplier; goto have_max_multiplier; } - printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); + pr_err("powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); return -EINVAL; } if (!max_multiplier) { - printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz); - printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n"); + pr_warn("powernow-k6: unknown frequency %u, cannot determine current multiplier\n", + khz); + pr_warn("powernow-k6: use module parameters max_multiplier and bus_frequency\n"); return -EOPNOTSUPP; } @@ -193,7 +194,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) busfreq = param_busfreq / 10; goto have_busfreq; } - printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); + pr_err("powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); return -EINVAL; } @@ -275,7 +276,7 @@ static int __init powernow_k6_init(void) return -ENODEV; if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) { - printk(KERN_INFO PFX "PowerNow IOPORT region already used.\n"); + pr_info(PFX "PowerNow IOPORT region already used\n"); return -EIO; } diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index c1ae1999770a..4a1b420da72e 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -127,14 +127,13 @@ static int check_powernow(void) maxei = cpuid_eax(0x80000000); if (maxei < 0x80000007) { /* Any powernow info ? */ #ifdef MODULE - printk(KERN_INFO PFX "No powernow capabilities detected\n"); + pr_info(PFX "No powernow capabilities detected\n"); #endif return 0; } if ((c->x86_model == 6) && (c->x86_mask == 0)) { - printk(KERN_INFO PFX "K7 660[A0] core detected, " - "enabling errata workarounds\n"); + pr_info(PFX "K7 660[A0] core detected, enabling errata workarounds\n"); have_a0 = 1; } @@ -144,22 +143,22 @@ static int check_powernow(void) if (!(edx & (1 << 1 | 1 << 2))) return 0; - printk(KERN_INFO PFX "PowerNOW! Technology present. Can scale: "); + pr_info(PFX "PowerNOW! Technology present. Can scale: "); if (edx & 1 << 1) { - printk("frequency"); + pr_cont("frequency"); can_scale_bus = 1; } if ((edx & (1 << 1 | 1 << 2)) == 0x6) - printk(" and "); + pr_cont(" and "); if (edx & 1 << 2) { - printk("voltage"); + pr_cont("voltage"); can_scale_vid = 1; } - printk(".\n"); + pr_cont("\n"); return 1; } @@ -427,16 +426,14 @@ static int powernow_acpi_init(void) err05: kfree(acpi_processor_perf); err0: - printk(KERN_WARNING PFX "ACPI perflib can not be used on " - "this platform\n"); + pr_warn(PFX "ACPI perflib can not be used on this platform\n"); acpi_processor_perf = NULL; return retval; } #else static int powernow_acpi_init(void) { - printk(KERN_INFO PFX "no support for ACPI processor found." - " Please recompile your kernel with ACPI processor\n"); + pr_info(PFX "no support for ACPI processor found - please recompile your kernel with ACPI processor\n"); return -EINVAL; } #endif @@ -468,8 +465,7 @@ static int powernow_decode_bios(int maxfid, int startvid) psb = (struct psb_s *) p; pr_debug("Table version: 0x%x\n", psb->tableversion); if (psb->tableversion != 0x12) { - printk(KERN_INFO PFX "Sorry, only v1.2 tables" - " supported right now\n"); + pr_info(PFX "Sorry, only v1.2 tables supported right now\n"); return -ENODEV; } @@ -481,10 +477,8 @@ static int powernow_decode_bios(int maxfid, int startvid) latency = psb->settlingtime; if (latency < 100) { - printk(KERN_INFO PFX "BIOS set settling time " - "to %d microseconds. " - "Should be at least 100. " - "Correcting.\n", latency); + pr_info(PFX "BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n", + latency); latency = 100; } pr_debug("Settling Time: %d microseconds.\n", @@ -516,10 +510,9 @@ static int powernow_decode_bios(int maxfid, int startvid) p += 2; } } - printk(KERN_INFO PFX "No PST tables match this cpuid " - "(0x%x)\n", etuple); - printk(KERN_INFO PFX "This is indicative of a broken " - "BIOS.\n"); + pr_info(PFX "No PST tables match this cpuid (0x%x)\n", + etuple); + pr_info(PFX "This is indicative of a broken BIOS\n"); return -EINVAL; } @@ -552,7 +545,7 @@ static int fixup_sgtc(void) sgtc = 100 * m * latency; sgtc = sgtc / 3; if (sgtc > 0xfffff) { - printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc); + pr_warn(PFX "SGTC too large %d\n", sgtc); sgtc = 0xfffff; } return sgtc; @@ -574,14 +567,10 @@ static unsigned int powernow_get(unsigned int cpu) static int acer_cpufreq_pst(const struct dmi_system_id *d) { - printk(KERN_WARNING PFX - "%s laptop with broken PST tables in BIOS detected.\n", + pr_warn(PFX "%s laptop with broken PST tables in BIOS detected\n", d->ident); - printk(KERN_WARNING PFX - "You need to downgrade to 3A21 (09/09/2002), or try a newer " - "BIOS than 3A71 (01/20/2003)\n"); - printk(KERN_WARNING PFX - "cpufreq scaling has been disabled as a result of this.\n"); + pr_warn(PFX "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n"); + pr_warn(PFX "cpufreq scaling has been disabled as a result of this\n"); return 0; } @@ -616,40 +605,38 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; if (!fsb) { - printk(KERN_WARNING PFX "can not determine bus frequency\n"); + pr_warn(PFX "can not determine bus frequency\n"); return -EINVAL; } pr_debug("FSB: %3dMHz\n", fsb/1000); if (dmi_check_system(powernow_dmi_table) || acpi_force) { - printk(KERN_INFO PFX "PSB/PST known to be broken. " - "Trying ACPI instead\n"); + pr_info(PFX "PSB/PST known to be broken - trying ACPI instead\n"); result = powernow_acpi_init(); } else { result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID); if (result) { - printk(KERN_INFO PFX "Trying ACPI perflib\n"); + pr_info(PFX "Trying ACPI perflib\n"); maximum_speed = 0; minimum_speed = -1; latency = 0; result = powernow_acpi_init(); if (result) { - printk(KERN_INFO PFX - "ACPI and legacy methods failed\n"); + pr_info(PFX "ACPI and legacy methods failed\n"); } } else { /* SGTC use the bus clock as timer */ latency = fixup_sgtc(); - printk(KERN_INFO PFX "SGTC: %d\n", latency); + pr_info(PFX "SGTC: %d\n", latency); } } if (result) return result; - printk(KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", - minimum_speed/1000, maximum_speed/1000); + pr_info(PFX "Minimum speed %d MHz - Maximum speed %d MHz\n", + minimum_speed/1000, maximum_speed/1000); policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency); diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 46fee1539cc8..8a27667c16fa 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -233,9 +233,8 @@ static void pxa27x_guess_max_freq(void) { if (!pxa27x_maxfreq) { pxa27x_maxfreq = 416000; - printk(KERN_INFO "PXA CPU 27x max frequency not defined " - "(pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n", - pxa27x_maxfreq); + pr_info("PXA CPU 27x max frequency not defined (pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n", + pxa27x_maxfreq); } else { pxa27x_maxfreq *= 1000; } @@ -417,7 +416,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) cpufreq_table_validate_and_show(policy, pxa27x_freq_table); } - printk(KERN_INFO "PXA CPU frequency change support initialized\n"); + pr_info("PXA CPU frequency change support initialized\n"); return 0; } diff --git a/drivers/cpufreq/s3c2412-cpufreq.c b/drivers/cpufreq/s3c2412-cpufreq.c index eb262133fef2..f9447bac9e22 100644 --- a/drivers/cpufreq/s3c2412-cpufreq.c +++ b/drivers/cpufreq/s3c2412-cpufreq.c @@ -197,21 +197,20 @@ static int s3c2412_cpufreq_add(struct device *dev, hclk = clk_get(NULL, "hclk"); if (IS_ERR(hclk)) { - printk(KERN_ERR "%s: cannot find hclk clock\n", __func__); + pr_err("%s: cannot find hclk clock\n", __func__); return -ENOENT; } fclk = clk_get(NULL, "fclk"); if (IS_ERR(fclk)) { - printk(KERN_ERR "%s: cannot find fclk clock\n", __func__); + pr_err("%s: cannot find fclk clock\n", __func__); goto err_fclk; } fclk_rate = clk_get_rate(fclk); if (fclk_rate > 200000000) { - printk(KERN_INFO - "%s: fclk %ld MHz, assuming 266MHz capable part\n", - __func__, fclk_rate / 1000000); + pr_info("%s: fclk %ld MHz, assuming 266MHz capable part\n", + __func__, fclk_rate / 1000000); s3c2412_cpufreq_info.max.fclk = 266000000; s3c2412_cpufreq_info.max.hclk = 133000000; s3c2412_cpufreq_info.max.pclk = 66000000; @@ -219,13 +218,13 @@ static int s3c2412_cpufreq_add(struct device *dev, armclk = clk_get(NULL, "armclk"); if (IS_ERR(armclk)) { - printk(KERN_ERR "%s: cannot find arm clock\n", __func__); + pr_err("%s: cannot find arm clock\n", __func__); goto err_armclk; } xtal = clk_get(NULL, "xtal"); if (IS_ERR(xtal)) { - printk(KERN_ERR "%s: cannot find xtal clock\n", __func__); + pr_err("%s: cannot find xtal clock\n", __func__); goto err_xtal; } diff --git a/drivers/cpufreq/s3c2440-cpufreq.c b/drivers/cpufreq/s3c2440-cpufreq.c index 0129f5c70a61..f6cefe34e411 100644 --- a/drivers/cpufreq/s3c2440-cpufreq.c +++ b/drivers/cpufreq/s3c2440-cpufreq.c @@ -66,7 +66,7 @@ static int s3c2440_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) __func__, fclk, armclk, hclk_max); if (armclk > fclk) { - printk(KERN_WARNING "%s: armclk > fclk\n", __func__); + pr_warn("%s: armclk > fclk\n", __func__); armclk = fclk; } @@ -273,7 +273,7 @@ static int s3c2440_cpufreq_add(struct device *dev, armclk = s3c_cpufreq_clk_get(NULL, "armclk"); if (IS_ERR(xtal) || IS_ERR(hclk) || IS_ERR(fclk) || IS_ERR(armclk)) { - printk(KERN_ERR "%s: failed to get clocks\n", __func__); + pr_err("%s: failed to get clocks\n", __func__); return -ENOENT; } diff --git a/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c b/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c index 9b7b4289d66c..8182608aeac1 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c +++ b/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c @@ -178,7 +178,7 @@ static int __init s3c_freq_debugfs_init(void) { dbgfs_root = debugfs_create_dir("s3c-cpufreq", NULL); if (IS_ERR(dbgfs_root)) { - printk(KERN_ERR "%s: error creating debugfs root\n", __func__); + pr_err("%s: error creating debugfs root\n", __func__); return PTR_ERR(dbgfs_root); } diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 68ef8fd9482f..68f883744500 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -175,7 +175,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, cpu_new.freq.fclk = cpu_new.pll.frequency; if (s3c_cpufreq_calcdivs(&cpu_new) < 0) { - printk(KERN_ERR "no divisors for %d\n", target_freq); + pr_err("no divisors for %d\n", target_freq); goto err_notpossible; } @@ -187,7 +187,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, if (cpu_new.freq.hclk != cpu_cur.freq.hclk) { if (s3c_cpufreq_calcio(&cpu_new) < 0) { - printk(KERN_ERR "%s: no IO timings\n", __func__); + pr_err("%s: no IO timings\n", __func__); goto err_notpossible; } } @@ -262,7 +262,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, return 0; err_notpossible: - printk(KERN_ERR "no compatible settings for %d\n", target_freq); + pr_err("no compatible settings for %d\n", target_freq); return -EINVAL; } @@ -331,7 +331,7 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, &index); if (ret < 0) { - printk(KERN_ERR "%s: no PLL available\n", __func__); + pr_err("%s: no PLL available\n", __func__); goto err_notpossible; } @@ -346,7 +346,7 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, return s3c_cpufreq_settarget(policy, target_freq, pll); err_notpossible: - printk(KERN_ERR "no compatible settings for %d\n", target_freq); + pr_err("no compatible settings for %d\n", target_freq); return -EINVAL; } @@ -356,7 +356,7 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) clk = clk_get(dev, name); if (IS_ERR(clk)) - printk(KERN_ERR "cpufreq: failed to get clock '%s'\n", name); + pr_err("cpufreq: failed to get clock '%s'\n", name); return clk; } @@ -378,15 +378,16 @@ static int __init s3c_cpufreq_initclks(void) if (IS_ERR(clk_fclk) || IS_ERR(clk_hclk) || IS_ERR(clk_pclk) || IS_ERR(_clk_mpll) || IS_ERR(clk_arm) || IS_ERR(_clk_xtal)) { - printk(KERN_ERR "%s: could not get clock(s)\n", __func__); + pr_err("%s: could not get clock(s)\n", __func__); return -ENOENT; } - printk(KERN_INFO "%s: clocks f=%lu,h=%lu,p=%lu,a=%lu\n", __func__, - clk_get_rate(clk_fclk) / 1000, - clk_get_rate(clk_hclk) / 1000, - clk_get_rate(clk_pclk) / 1000, - clk_get_rate(clk_arm) / 1000); + pr_info("%s: clocks f=%lu,h=%lu,p=%lu,a=%lu\n", + __func__, + clk_get_rate(clk_fclk) / 1000, + clk_get_rate(clk_hclk) / 1000, + clk_get_rate(clk_pclk) / 1000, + clk_get_rate(clk_arm) / 1000); return 0; } @@ -424,7 +425,7 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy) ret = s3c_cpufreq_settarget(NULL, suspend_freq, &suspend_pll); if (ret) { - printk(KERN_ERR "%s: failed to reset pll/freq\n", __func__); + pr_err("%s: failed to reset pll/freq\n", __func__); return ret; } @@ -449,13 +450,12 @@ static struct cpufreq_driver s3c24xx_driver = { int s3c_cpufreq_register(struct s3c_cpufreq_info *info) { if (!info || !info->name) { - printk(KERN_ERR "%s: failed to pass valid information\n", - __func__); + pr_err("%s: failed to pass valid information\n", __func__); return -EINVAL; } - printk(KERN_INFO "S3C24XX CPU Frequency driver, %s cpu support\n", - info->name); + pr_info("S3C24XX CPU Frequency driver, %s cpu support\n", + info->name); /* check our driver info has valid data */ @@ -478,7 +478,7 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) struct s3c_cpufreq_board *ours; if (!board) { - printk(KERN_INFO "%s: no board data\n", __func__); + pr_info("%s: no board data\n", __func__); return -EINVAL; } @@ -487,7 +487,7 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) ours = kzalloc(sizeof(*ours), GFP_KERNEL); if (ours == NULL) { - printk(KERN_ERR "%s: no memory\n", __func__); + pr_err("%s: no memory\n", __func__); return -ENOMEM; } @@ -502,15 +502,15 @@ static int __init s3c_cpufreq_auto_io(void) int ret; if (!cpu_cur.info->get_iotiming) { - printk(KERN_ERR "%s: get_iotiming undefined\n", __func__); + pr_err("%s: get_iotiming undefined\n", __func__); return -ENOENT; } - printk(KERN_INFO "%s: working out IO settings\n", __func__); + pr_info("%s: working out IO settings\n", __func__); ret = (cpu_cur.info->get_iotiming)(&cpu_cur, &s3c24xx_iotiming); if (ret) - printk(KERN_ERR "%s: failed to get timings\n", __func__); + pr_err("%s: failed to get timings\n", __func__); return ret; } @@ -561,7 +561,7 @@ static void s3c_cpufreq_update_loctkime(void) val = calc_locktime(rate, cpu_cur.info->locktime_u) << bits; val |= calc_locktime(rate, cpu_cur.info->locktime_m); - printk(KERN_INFO "%s: new locktime is 0x%08x\n", __func__, val); + pr_info("%s: new locktime is 0x%08x\n", __func__, val); __raw_writel(val, S3C2410_LOCKTIME); } @@ -580,7 +580,7 @@ static int s3c_cpufreq_build_freq(void) ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL); if (!ftab) { - printk(KERN_ERR "%s: no memory for tables\n", __func__); + pr_err("%s: no memory for tables\n", __func__); return -ENOMEM; } @@ -608,15 +608,14 @@ static int __init s3c_cpufreq_initcall(void) if (cpu_cur.board->auto_io) { ret = s3c_cpufreq_auto_io(); if (ret) { - printk(KERN_ERR "%s: failed to get io timing\n", + pr_err("%s: failed to get io timing\n", __func__); goto out; } } if (cpu_cur.board->need_io && !cpu_cur.info->set_iotiming) { - printk(KERN_ERR "%s: no IO support registered\n", - __func__); + pr_err("%s: no IO support registered\n", __func__); ret = -EINVAL; goto out; } @@ -666,9 +665,9 @@ int s3c_plltab_register(struct cpufreq_frequency_table *plls, vals += plls_no; vals->frequency = CPUFREQ_TABLE_END; - printk(KERN_INFO "cpufreq: %d PLL entries\n", plls_no); + pr_info("cpufreq: %d PLL entries\n", plls_no); } else - printk(KERN_ERR "cpufreq: no memory for PLL tables\n"); + pr_err("cpufreq: no memory for PLL tables\n"); return vals ? 0 : -ENOMEM; } diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index a145b319d171..344e584412ed 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -205,7 +205,7 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) } else if (ch == DMC1) { reg = (dmc_base[1] + 0x30); } else { - printk(KERN_ERR "Cannot find DMC port\n"); + pr_err("Cannot find DMC port\n"); return; } @@ -534,7 +534,7 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy) mem_type = check_mem_type(dmc_base[0]); if ((mem_type != LPDDR) && (mem_type != LPDDR2)) { - printk(KERN_ERR "CPUFreq doesn't support this memory type\n"); + pr_err("CPUFreq doesn't support this memory type\n"); ret = -EINVAL; goto out_dmc1; } diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index ac84e4818014..57bbddf55786 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -44,8 +44,8 @@ static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu) switch (clockspeed_reg & 0x03) { default: - printk(KERN_ERR PFX "error: cpuctl register has unexpected " - "value %02x\n", clockspeed_reg); + pr_err(PFX "error: cpuctl register has unexpected value %02x\n", + clockspeed_reg); case 0x01: return 100000; case 0x02: @@ -112,7 +112,7 @@ static int __init sc520_freq_init(void) cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); if (!cpuctl) { - printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); + pr_err("sc520_freq: error: failed to remap memory\n"); return -ENOMEM; } diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 7d4a31571608..47df2d649b78 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -386,8 +386,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) /* check to see if it stuck */ rdmsr(MSR_IA32_MISC_ENABLE, l, h); if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) { - printk(KERN_INFO PFX - "couldn't enable Enhanced SpeedStep\n"); + pr_info(PFX "couldn't enable Enhanced SpeedStep\n"); return -ENODEV; } } diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 37555c6b86a7..9d00c226a6aa 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -68,13 +68,13 @@ static int speedstep_find_register(void) /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) { - printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); + pr_err("speedstep-ich: could not find speedstep register\n"); return -ENODEV; } pmbase &= 0xFFFFFFFE; if (!pmbase) { - printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); + pr_err("speedstep-ich: could not find speedstep register\n"); return -ENODEV; } @@ -136,7 +136,7 @@ static void speedstep_set_state(unsigned int state) pr_debug("change to %u MHz succeeded\n", speedstep_get_frequency(speedstep_processor) / 1000); else - printk(KERN_ERR "cpufreq: change failed - I/O error\n"); + pr_err("cpufreq: change failed - I/O error\n"); return; } diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c index 15d3214aaa00..32bdf1df9517 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c @@ -153,7 +153,7 @@ static unsigned int pentium_core_get_frequency(void) fsb = 333333; break; default: - printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value"); + pr_err("PCORE - MSR_FSB_FREQ undefined value\n"); } rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); @@ -453,11 +453,8 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor, */ if (*transition_latency > 10000000 || *transition_latency < 50000) { - printk(KERN_WARNING PFX "frequency transition " - "measured seems out of range (%u " - "nSec), falling back to a safe one of" - "%u nSec.\n", - *transition_latency, 500000); + pr_warn(PFX "frequency transition measured seems out of range (%u nSec), falling back to a safe one of %u nSec\n", + *transition_latency, 500000); *transition_latency = 500000; } } diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index 819229e824fb..af32a5f38806 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -204,9 +204,8 @@ static void speedstep_set_state(unsigned int state) (speedstep_freqs[new_state].frequency / 1000), retry, result); else - printk(KERN_ERR "cpufreq: change to state %u " - "failed with new_state %u and result %u\n", - state, new_state, result); + pr_err("cpufreq: change to state %u failed with new_state %u and result %u\n", + state, new_state, result); return; } -- GitLab From 1c5864e26c99cf32b51e878f3daf73a388d7561a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 Apr 2016 13:28:25 -0700 Subject: [PATCH 1879/9938] cpufreq: Use consistent prefixing via pr_fmt Use the more common kernel style adding a define for pr_fmt. Miscellanea: o Remove now unused PFX defines Signed-off-by: Joe Perches Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/acpi-cpufreq.c | 8 +-- drivers/cpufreq/cpufreq-nforce2.c | 20 ++++---- drivers/cpufreq/e_powersaver.c | 38 +++++++------- drivers/cpufreq/elanfreq.c | 2 + drivers/cpufreq/ia64-acpi-cpufreq.c | 5 +- drivers/cpufreq/longhaul.c | 60 +++++++++++------------ drivers/cpufreq/loongson2_cpufreq.c | 7 ++- drivers/cpufreq/maple-cpufreq.c | 6 ++- drivers/cpufreq/omap-cpufreq.c | 5 +- drivers/cpufreq/p4-clockmod.c | 10 ++-- drivers/cpufreq/pmac32-cpufreq.c | 8 +-- drivers/cpufreq/pmac64-cpufreq.c | 28 ++++++----- drivers/cpufreq/powernow-k6.c | 15 +++--- drivers/cpufreq/powernow-k7.c | 43 ++++++++-------- drivers/cpufreq/pxa2xx-cpufreq.c | 13 ++--- drivers/cpufreq/s3c2412-cpufreq.c | 14 +++--- drivers/cpufreq/s3c2440-cpufreq.c | 2 + drivers/cpufreq/s3c24xx-cpufreq-debugfs.c | 2 + drivers/cpufreq/s3c24xx-cpufreq.c | 8 +-- drivers/cpufreq/s5pv210-cpufreq.c | 6 ++- drivers/cpufreq/sc520_freq.c | 6 +-- drivers/cpufreq/speedstep-centrino.c | 5 +- drivers/cpufreq/speedstep-ich.c | 8 +-- drivers/cpufreq/speedstep-lib.c | 4 +- drivers/cpufreq/speedstep-smi.c | 4 +- 25 files changed, 181 insertions(+), 146 deletions(-) diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index ed9e93df7ecf..67a612e22179 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -25,6 +25,8 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -50,8 +52,6 @@ MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski"); MODULE_DESCRIPTION("ACPI Processor P-States Driver"); MODULE_LICENSE("GPL"); -#define PFX "acpi-cpufreq: " - enum { UNDEFINED_CAPABLE = 0, SYSTEM_INTEL_MSR_CAPABLE, @@ -648,7 +648,7 @@ static int acpi_cpufreq_blacklist(struct cpuinfo_x86 *c) if ((c->x86 == 15) && (c->x86_model == 6) && (c->x86_mask == 8)) { - pr_info("acpi-cpufreq: Intel(R) Xeon(R) 7100 Errata AL30, processors may lock up on frequency changes: disabling acpi-cpufreq\n"); + pr_info("Intel(R) Xeon(R) 7100 Errata AL30, processors may lock up on frequency changes: disabling acpi-cpufreq\n"); return -ENODEV; } } @@ -724,7 +724,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) cpumask_copy(data->freqdomain_cpus, topology_sibling_cpumask(cpu)); policy->shared_type = CPUFREQ_SHARED_TYPE_HW; - pr_info_once(PFX "overriding BIOS provided _PSD data\n"); + pr_info_once("overriding BIOS provided _PSD data\n"); } #endif diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index 7da96d536ac9..5503d491b016 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c @@ -7,6 +7,8 @@ * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -56,8 +58,6 @@ MODULE_PARM_DESC(fid, "CPU multiplier to use (11.5 = 115)"); MODULE_PARM_DESC(min_fsb, "Minimum FSB to use, if not defined: current FSB - 50"); -#define PFX "cpufreq-nforce2: " - /** * nforce2_calc_fsb - calculate FSB * @pll: PLL value @@ -174,13 +174,13 @@ static int nforce2_set_fsb(unsigned int fsb) int pll = 0; if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) { - pr_err(PFX "FSB %d is out of range!\n", fsb); + pr_err("FSB %d is out of range!\n", fsb); return -EINVAL; } tfsb = nforce2_fsb_read(0); if (!tfsb) { - pr_err(PFX "Error while reading the FSB\n"); + pr_err("Error while reading the FSB\n"); return -EINVAL; } @@ -276,7 +276,7 @@ static int nforce2_target(struct cpufreq_policy *policy, /* local_irq_save(flags); */ if (nforce2_set_fsb(target_fsb) < 0) - pr_err(PFX "Changing FSB to %d failed\n", target_fsb); + pr_err("Changing FSB to %d failed\n", target_fsb); else pr_debug("Changed FSB successfully to %d\n", target_fsb); @@ -324,7 +324,7 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) /* FIX: Get FID from CPU */ if (!fid) { if (!cpu_khz) { - pr_warn(PFX "cpu_khz not set, can't calculate multiplier!\n"); + pr_warn("cpu_khz not set, can't calculate multiplier!\n"); return -ENODEV; } @@ -339,7 +339,7 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) } } - pr_info(PFX "FSB currently at %i MHz, FID %d.%d\n", + pr_info("FSB currently at %i MHz, FID %d.%d\n", fsb, fid / 10, fid % 10); /* Set maximum FSB to FSB at boot time */ @@ -399,9 +399,9 @@ static int nforce2_detect_chipset(void) if (nforce2_dev == NULL) return -ENODEV; - pr_info(PFX "Detected nForce2 chipset revision %X\n", + pr_info("Detected nForce2 chipset revision %X\n", nforce2_dev->revision); - pr_info(PFX "FSB changing is maybe unstable and can lead to crashes and data loss\n"); + pr_info("FSB changing is maybe unstable and can lead to crashes and data loss\n"); return 0; } @@ -419,7 +419,7 @@ static int __init nforce2_init(void) /* detect chipset */ if (nforce2_detect_chipset()) { - pr_info(PFX "No nForce2 chipset\n"); + pr_info("No nForce2 chipset\n"); return -ENODEV; } diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index c420f0cb46a7..5ec87e3a97bd 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -6,6 +6,8 @@ * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -141,9 +143,9 @@ static int eps_set_state(struct eps_cpu_data *centaur, /* Print voltage and multiplier */ rdmsr(MSR_IA32_PERF_STATUS, lo, hi); current_voltage = lo & 0xff; - pr_info("eps: Current voltage = %dmV\n", current_voltage * 16 + 700); + pr_info("Current voltage = %dmV\n", current_voltage * 16 + 700); current_multiplier = (lo >> 8) & 0xff; - pr_info("eps: Current multiplier = %d\n", current_multiplier); + pr_info("Current multiplier = %d\n", current_multiplier); } #endif return 0; @@ -164,7 +166,7 @@ static int eps_target(struct cpufreq_policy *policy, unsigned int index) dest_state = centaur->freq_table[index].driver_data & 0xffff; ret = eps_set_state(centaur, policy, dest_state); if (ret) - pr_err("eps: Timeout!\n"); + pr_err("Timeout!\n"); return ret; } @@ -192,7 +194,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) return -ENODEV; /* Check brand */ - pr_info("eps: Detected VIA "); + pr_info("Detected VIA "); switch (c->x86_model) { case 10: @@ -233,7 +235,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Can be locked at 0 */ rdmsrl(MSR_IA32_MISC_ENABLE, val); if (!(val & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) { - pr_info("eps: Can't enable Enhanced PowerSaver\n"); + pr_info("Can't enable Enhanced PowerSaver\n"); return -ENODEV; } } @@ -241,19 +243,19 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Print voltage and multiplier */ rdmsr(MSR_IA32_PERF_STATUS, lo, hi); current_voltage = lo & 0xff; - pr_info("eps: Current voltage = %dmV\n", current_voltage * 16 + 700); + pr_info("Current voltage = %dmV\n", current_voltage * 16 + 700); current_multiplier = (lo >> 8) & 0xff; - pr_info("eps: Current multiplier = %d\n", current_multiplier); + pr_info("Current multiplier = %d\n", current_multiplier); /* Print limits */ max_voltage = hi & 0xff; - pr_info("eps: Highest voltage = %dmV\n", max_voltage * 16 + 700); + pr_info("Highest voltage = %dmV\n", max_voltage * 16 + 700); max_multiplier = (hi >> 8) & 0xff; - pr_info("eps: Highest multiplier = %d\n", max_multiplier); + pr_info("Highest multiplier = %d\n", max_multiplier); min_voltage = (hi >> 16) & 0xff; - pr_info("eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700); + pr_info("Lowest voltage = %dmV\n", min_voltage * 16 + 700); min_multiplier = (hi >> 24) & 0xff; - pr_info("eps: Lowest multiplier = %d\n", min_multiplier); + pr_info("Lowest multiplier = %d\n", min_multiplier); /* Sanity checks */ if (current_multiplier == 0 || max_multiplier == 0 @@ -271,13 +273,13 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Check for systems using underclocked CPU */ if (!freq_failsafe_off && max_multiplier != current_multiplier) { - pr_info("eps: Your processor is running at different frequency then its maximum. Aborting.\n"); - pr_info("eps: You can use freq_failsafe_off option to disable this check.\n"); + pr_info("Your processor is running at different frequency then its maximum. Aborting.\n"); + pr_info("You can use freq_failsafe_off option to disable this check.\n"); return -EINVAL; } if (!voltage_failsafe_off && max_voltage != current_voltage) { - pr_info("eps: Your processor is running at different voltage then its maximum. Aborting.\n"); - pr_info("eps: You can use voltage_failsafe_off option to disable this check.\n"); + pr_info("Your processor is running at different voltage then its maximum. Aborting.\n"); + pr_info("You can use voltage_failsafe_off option to disable this check.\n"); return -EINVAL; } @@ -288,13 +290,13 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Check for ACPI processor speed limit */ if (!ignore_acpi_limit && !eps_acpi_init()) { if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) { - pr_info("eps: ACPI limit %u.%uGHz\n", + pr_info("ACPI limit %u.%uGHz\n", limit/1000000, (limit%1000000)/10000); eps_acpi_exit(policy); /* Check if max_multiplier is in BIOS limits */ if (limit && max_multiplier * fsb > limit) { - pr_info("eps: Aborting\n"); + pr_info("Aborting\n"); return -EINVAL; } } @@ -310,7 +312,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) v = (set_max_voltage - 700) / 16; /* Check if voltage is within limits */ if (v >= min_voltage && v <= max_voltage) { - pr_info("eps: Setting %dmV as maximum\n", v * 16 + 700); + pr_info("Setting %dmV as maximum\n", v * 16 + 700); max_voltage = v; } } diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index 8f4dded3016f..bfce11cba1df 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -16,6 +16,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index fd36d6cd3787..759612da4fdc 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -8,6 +8,8 @@ * Venkatesh Pallipadi */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -290,8 +292,7 @@ acpi_cpufreq_cpu_init ( /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); - pr_info("acpi-cpufreq: CPU%u - ACPI performance management activated\n", - cpu); + pr_info("CPU%u - ACPI performance management activated\n", cpu); for (i = 0; i < data->acpi_data.state_count; i++) pr_debug(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n", diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 2baeb8c01474..beae5cf5c62c 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -21,6 +21,8 @@ * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -40,8 +42,6 @@ #include "longhaul.h" -#define PFX "longhaul: " - #define TYPE_LONGHAUL_V1 1 #define TYPE_LONGHAUL_V2 2 #define TYPE_POWERSAVER 3 @@ -347,13 +347,13 @@ static int longhaul_setstate(struct cpufreq_policy *policy, freqs.new = calc_speed(longhaul_get_cpu_mult()); /* Check if requested frequency is set. */ if (unlikely(freqs.new != speed)) { - pr_info(PFX "Failed to set requested frequency!\n"); + pr_info("Failed to set requested frequency!\n"); /* Revision ID = 1 but processor is expecting revision key * equal to 0. Jumpers at the bottom of processor will change * multiplier and FSB, but will not change bits in Longhaul * MSR nor enable voltage scaling. */ if (!revid_errata) { - pr_info(PFX "Enabling \"Ignore Revision ID\" option\n"); + pr_info("Enabling \"Ignore Revision ID\" option\n"); revid_errata = 1; msleep(200); goto retry_loop; @@ -363,10 +363,10 @@ static int longhaul_setstate(struct cpufreq_policy *policy, * but it doesn't change frequency. I tried poking various * bits in northbridge registers, but without success. */ if (longhaul_flags & USE_ACPI_C3) { - pr_info(PFX "Disabling ACPI C3 support\n"); + pr_info("Disabling ACPI C3 support\n"); longhaul_flags &= ~USE_ACPI_C3; if (revid_errata) { - pr_info(PFX "Disabling \"Ignore Revision ID\" option\n"); + pr_info("Disabling \"Ignore Revision ID\" option\n"); revid_errata = 0; } msleep(200); @@ -377,7 +377,7 @@ static int longhaul_setstate(struct cpufreq_policy *policy, * RevID = 1. RevID errata will make things right. Just * to be 100% sure. */ if (longhaul_version == TYPE_LONGHAUL_V2) { - pr_info(PFX "Switching to Longhaul ver. 1\n"); + pr_info("Switching to Longhaul ver. 1\n"); longhaul_version = TYPE_LONGHAUL_V1; msleep(200); goto retry_loop; @@ -385,7 +385,7 @@ static int longhaul_setstate(struct cpufreq_policy *policy, } if (!bm_timeout) { - pr_info(PFX "Warning: Timeout while waiting for idle PCI bus\n"); + pr_info("Warning: Timeout while waiting for idle PCI bus\n"); return -EBUSY; } @@ -430,12 +430,12 @@ static int longhaul_get_ranges(void) /* Get current frequency */ mult = longhaul_get_cpu_mult(); if (mult == -1) { - pr_info(PFX "Invalid (reserved) multiplier!\n"); + pr_info("Invalid (reserved) multiplier!\n"); return -EINVAL; } fsb = guess_fsb(mult); if (fsb == 0) { - pr_info(PFX "Invalid (reserved) FSB!\n"); + pr_info("Invalid (reserved) FSB!\n"); return -EINVAL; } /* Get max multiplier - as we always did. @@ -465,11 +465,11 @@ static int longhaul_get_ranges(void) print_speed(highest_speed/1000)); if (lowest_speed == highest_speed) { - pr_info(PFX "highestspeed == lowest, aborting\n"); + pr_info("highestspeed == lowest, aborting\n"); return -EINVAL; } if (lowest_speed > highest_speed) { - pr_info(PFX "nonsense! lowest (%d > %d) !\n", + pr_info("nonsense! lowest (%d > %d) !\n", lowest_speed, highest_speed); return -EINVAL; } @@ -535,16 +535,16 @@ static void longhaul_setup_voltagescaling(void) rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); if (!(longhaul.bits.RevisionID & 1)) { - pr_info(PFX "Voltage scaling not supported by CPU\n"); + pr_info("Voltage scaling not supported by CPU\n"); return; } if (!longhaul.bits.VRMRev) { - pr_info(PFX "VRM 8.5\n"); + pr_info("VRM 8.5\n"); vrm_mV_table = &vrm85_mV[0]; mV_vrm_table = &mV_vrm85[0]; } else { - pr_info(PFX "Mobile VRM\n"); + pr_info("Mobile VRM\n"); if (cpu_model < CPU_NEHEMIAH) return; vrm_mV_table = &mobilevrm_mV[0]; @@ -555,21 +555,21 @@ static void longhaul_setup_voltagescaling(void) maxvid = vrm_mV_table[longhaul.bits.MaximumVID]; if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) { - pr_info(PFX "Bogus values Min:%d.%03d Max:%d.%03d - Voltage scaling disabled\n", + pr_info("Bogus values Min:%d.%03d Max:%d.%03d - Voltage scaling disabled\n", minvid.mV/1000, minvid.mV%1000, maxvid.mV/1000, maxvid.mV%1000); return; } if (minvid.mV == maxvid.mV) { - pr_info(PFX "Claims to support voltage scaling but min & max are both %d.%03d - Voltage scaling disabled\n", + pr_info("Claims to support voltage scaling but min & max are both %d.%03d - Voltage scaling disabled\n", maxvid.mV/1000, maxvid.mV%1000); return; } /* How many voltage steps*/ numvscales = maxvid.pos - minvid.pos + 1; - pr_info(PFX "Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n", + pr_info("Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n", maxvid.mV/1000, maxvid.mV%1000, minvid.mV/1000, minvid.mV%1000, numvscales); @@ -608,12 +608,12 @@ static void longhaul_setup_voltagescaling(void) pos = minvid.pos; freq_pos->driver_data |= mV_vrm_table[pos] << 8; vid = vrm_mV_table[mV_vrm_table[pos]]; - pr_info(PFX "f: %d kHz, index: %d, vid: %d mV\n", + pr_info("f: %d kHz, index: %d, vid: %d mV\n", speed, (int)(freq_pos - longhaul_table), vid.mV); } can_scale_voltage = 1; - pr_info(PFX "Voltage scaling enabled\n"); + pr_info("Voltage scaling enabled\n"); } @@ -711,7 +711,7 @@ static int enable_arbiter_disable(void) pci_write_config_byte(dev, reg, pci_cmd); pci_read_config_byte(dev, reg, &pci_cmd); if (!(pci_cmd & 1<<7)) { - pr_err(PFX "Can't enable access to port 0x22\n"); + pr_err("Can't enable access to port 0x22\n"); status = 0; } } @@ -748,7 +748,7 @@ static int longhaul_setup_southbridge(void) if (pci_cmd & 1 << 7) { pci_read_config_dword(dev, 0x88, &acpi_regs_addr); acpi_regs_addr &= 0xff00; - pr_info(PFX "ACPI I/O at 0x%x\n", acpi_regs_addr); + pr_info("ACPI I/O at 0x%x\n", acpi_regs_addr); } pci_dev_put(dev); @@ -842,7 +842,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) longhaul_version = TYPE_LONGHAUL_V1; } - pr_info(PFX "VIA %s CPU detected. ", cpuname); + pr_info("VIA %s CPU detected. ", cpuname); switch (longhaul_version) { case TYPE_LONGHAUL_V1: case TYPE_LONGHAUL_V2: @@ -878,14 +878,14 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) if (!(longhaul_flags & USE_ACPI_C3 || longhaul_flags & USE_NORTHBRIDGE) && ((pr == NULL) || !(pr->flags.bm_control))) { - pr_err(PFX "No ACPI support: Unsupported northbridge\n"); + pr_err("No ACPI support: Unsupported northbridge\n"); return -ENODEV; } if (longhaul_flags & USE_NORTHBRIDGE) - pr_info(PFX "Using northbridge support\n"); + pr_info("Using northbridge support\n"); if (longhaul_flags & USE_ACPI_C3) - pr_info(PFX "Using ACPI support\n"); + pr_info("Using ACPI support\n"); ret = longhaul_get_ranges(); if (ret != 0) @@ -922,18 +922,18 @@ static int __init longhaul_init(void) return -ENODEV; if (!enable) { - pr_err(PFX "Option \"enable\" not set - Aborting\n"); + pr_err("Option \"enable\" not set - Aborting\n"); return -ENODEV; } #ifdef CONFIG_SMP if (num_online_cpus() > 1) { - pr_err(PFX "More than 1 CPU detected, longhaul disabled\n"); + pr_err("More than 1 CPU detected, longhaul disabled\n"); return -ENODEV; } #endif #ifdef CONFIG_X86_IO_APIC if (cpu_has_apic) { - pr_err(PFX "APIC detected. Longhaul is currently broken in this configuration.\n"); + pr_err("APIC detected. Longhaul is currently broken in this configuration.\n"); return -ENODEV; } #endif @@ -941,7 +941,7 @@ static int __init longhaul_init(void) case 6 ... 9: return cpufreq_register_driver(&longhaul_driver); case 10: - pr_err(PFX "Use acpi-cpufreq driver for VIA C7\n"); + pr_err("Use acpi-cpufreq driver for VIA C7\n"); default: ; } diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index 93c7928cf461..6bbdac1065ff 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -10,6 +10,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -76,7 +79,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) cpuclk = clk_get(NULL, "cpu_clk"); if (IS_ERR(cpuclk)) { - pr_err("cpufreq: couldn't get CPU clk\n"); + pr_err("couldn't get CPU clk\n"); return PTR_ERR(cpuclk); } @@ -163,7 +166,7 @@ static int __init cpufreq_init(void) if (ret) return ret; - pr_info("cpufreq: Loongson-2F CPU frequency driver.\n"); + pr_info("Loongson-2F CPU frequency driver\n"); cpufreq_register_notifier(&loongson2_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index 7e55632291d7..d9df89392b84 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -13,6 +13,8 @@ #undef DEBUG +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -174,7 +176,7 @@ static int __init maple_cpufreq_init(void) /* Get first CPU node */ cpunode = of_cpu_device_node_get(0); if (cpunode == NULL) { - pr_err("cpufreq: Can't find any CPU 0 node\n"); + pr_err("Can't find any CPU 0 node\n"); goto bail_noprops; } @@ -182,7 +184,7 @@ static int __init maple_cpufreq_init(void) /* we actually don't care on which CPU to access PVR */ pvr_hi = PVR_VER(mfspr(SPRN_PVR)); if (pvr_hi != 0x3c && pvr_hi != 0x44) { - pr_err("cpufreq: Unsupported CPU version (%x)\n", pvr_hi); + pr_err("Unsupported CPU version (%x)\n", pvr_hi); goto bail_noprops; } diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 655fc9427626..cead9bec4843 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -13,6 +13,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -163,7 +166,7 @@ static int omap_cpufreq_probe(struct platform_device *pdev) { mpu_dev = get_cpu_device(0); if (!mpu_dev) { - pr_warn("%s: unable to get the mpu device\n", __func__); + pr_warn("%s: unable to get the MPU device\n", __func__); return -EINVAL; } diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 4d1a44370338..fd77812313f3 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -20,6 +20,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -35,8 +37,6 @@ #include "speedstep-lib.h" -#define PFX "p4-clockmod: " - /* * Duty Cycle (3bits), note DC_DISABLE is not specified in * intel docs i just use it to mean disable @@ -124,7 +124,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) { if (c->x86 == 0x06) { if (cpu_has(c, X86_FEATURE_EST)) - pr_warn_once(PFX "Warning: EST-capable CPU detected. The acpi-cpufreq module offers voltage scaling in addition to frequency scaling. You should use that instead of p4-clockmod, if possible.\n"); + pr_warn_once("Warning: EST-capable CPU detected. The acpi-cpufreq module offers voltage scaling in addition to frequency scaling. You should use that instead of p4-clockmod, if possible.\n"); switch (c->x86_model) { case 0x0E: /* Core */ case 0x0F: /* Core Duo */ @@ -148,7 +148,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4M) { - pr_warn(PFX "Warning: Pentium 4-M detected. The speedstep-ich or acpi cpufreq modules offer voltage scaling in addition of frequency scaling. You should use either one instead of p4-clockmod, if possible.\n"); + pr_warn("Warning: Pentium 4-M detected. The speedstep-ich or acpi cpufreq modules offer voltage scaling in addition of frequency scaling. You should use either one instead of p4-clockmod, if possible.\n"); return speedstep_get_frequency(SPEEDSTEP_CPU_P4M); } @@ -257,7 +257,7 @@ static int __init cpufreq_p4_init(void) ret = cpufreq_register_driver(&p4clockmod_driver); if (!ret) - pr_info(PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); + pr_info("P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); return ret; } diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 072d7b3841b9..b7b576e53e92 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -13,6 +13,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -481,13 +483,13 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) freqs = of_get_property(cpunode, "bus-frequencies", &lenp); lenp /= sizeof(u32); if (freqs == NULL || lenp != 2) { - pr_err("cpufreq: bus-frequencies incorrect or missing\n"); + pr_err("bus-frequencies incorrect or missing\n"); return 1; } ratio = of_get_property(cpunode, "processor-to-bus-ratio*2", NULL); if (ratio == NULL) { - pr_err("cpufreq: processor-to-bus-ratio*2 missing\n"); + pr_err("processor-to-bus-ratio*2 missing\n"); return 1; } @@ -550,7 +552,7 @@ static int pmac_cpufreq_init_7447A(struct device_node *cpunode) if (volt_gpio_np) voltage_gpio = read_gpio(volt_gpio_np); if (!voltage_gpio){ - pr_err("cpufreq: missing cpu-vcore-select gpio\n"); + pr_err("missing cpu-vcore-select gpio\n"); return 1; } diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 5ffe0855ba8f..267e0894c62d 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -12,6 +12,8 @@ #undef DEBUG +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -138,7 +140,7 @@ static void g5_vdnap_switch_volt(int speed_mode) usleep_range(1000, 1000); } if (done == 0) - pr_warn("cpufreq: Timeout in clock slewing !\n"); + pr_warn("Timeout in clock slewing !\n"); } @@ -266,7 +268,7 @@ static int g5_pfunc_switch_freq(int speed_mode) rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL); if (rc) - pr_warn("cpufreq: pfunc switch error %d\n", rc); + pr_warn("pfunc switch error %d\n", rc); /* It's an irq GPIO so we should be able to just block here, * I'll do that later after I've properly tested the IRQ code for @@ -282,7 +284,7 @@ static int g5_pfunc_switch_freq(int speed_mode) usleep_range(500, 500); } if (done == 0) - pr_warn("cpufreq: Timeout in clock slewing !\n"); + pr_warn("Timeout in clock slewing !\n"); /* If frequency is going down, last ramp the voltage */ if (speed_mode > g5_pmode_cur) @@ -368,7 +370,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) } pvr_hi = (*valp) >> 16; if (pvr_hi != 0x3c && pvr_hi != 0x44) { - pr_err("cpufreq: Unsupported CPU version\n"); + pr_err("Unsupported CPU version\n"); goto bail_noprops; } @@ -403,7 +405,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) root = of_find_node_by_path("/"); if (root == NULL) { - pr_err("cpufreq: Can't find root of device tree\n"); + pr_err("Can't find root of device tree\n"); goto bail_noprops; } pfunc_set_vdnap0 = pmf_find_function(root, "set-vdnap0"); @@ -411,7 +413,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode) pmf_find_function(root, "slewing-done"); if (pfunc_set_vdnap0 == NULL || pfunc_vdnap0_complete == NULL) { - pr_err("cpufreq: Can't find required platform function\n"); + pr_err("Can't find required platform function\n"); goto bail_noprops; } @@ -491,7 +493,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) if (cpuid != NULL) eeprom = of_get_property(cpuid, "cpuid", NULL); if (eeprom == NULL) { - pr_err("cpufreq: Can't find cpuid EEPROM !\n"); + pr_err("Can't find cpuid EEPROM !\n"); rc = -ENODEV; goto bail; } @@ -509,7 +511,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) break; } if (hwclock == NULL) { - pr_err("cpufreq: Can't find i2c clock chip !\n"); + pr_err("Can't find i2c clock chip !\n"); rc = -ENODEV; goto bail; } @@ -537,7 +539,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Check we have minimum requirements */ if (pfunc_cpu_getfreq == NULL || pfunc_cpu_setfreq_high == NULL || pfunc_cpu_setfreq_low == NULL || pfunc_slewing_done == NULL) { - pr_err("cpufreq: Can't find platform functions !\n"); + pr_err("Can't find platform functions !\n"); rc = -ENODEV; goto bail; } @@ -565,7 +567,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Get max frequency from device-tree */ valp = of_get_property(cpunode, "clock-frequency", NULL); if (!valp) { - pr_err("cpufreq: Can't find CPU frequency !\n"); + pr_err("Can't find CPU frequency !\n"); rc = -ENODEV; goto bail; } @@ -581,7 +583,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Check for machines with no useful settings */ if (il == ih) { - pr_warn("cpufreq: No low frequency mode available on this model !\n"); + pr_warn("No low frequency mode available on this model !\n"); rc = -ENODEV; goto bail; } @@ -592,7 +594,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) /* Sanity check */ if (min_freq >= max_freq || min_freq < 1000) { - pr_err("cpufreq: Can't calculate low frequency !\n"); + pr_err("Can't calculate low frequency !\n"); rc = -ENXIO; goto bail; } @@ -651,7 +653,7 @@ static int __init g5_cpufreq_init(void) /* Get first CPU node */ cpunode = of_cpu_device_node_get(0); if (cpunode == NULL) { - pr_err("cpufreq: Can't find any CPU node\n"); + pr_err("Can't find any CPU node\n"); return -ENODEV; } diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index 981f40b1caf4..dedd2568e852 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -8,6 +8,8 @@ * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -22,7 +24,6 @@ #define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long as it is unused */ -#define PFX "powernow-k6: " static unsigned int busfreq; /* FSB, in 10 kHz */ static unsigned int max_multiplier; @@ -141,7 +142,7 @@ static int powernow_k6_target(struct cpufreq_policy *policy, { if (clock_ratio[best_i].driver_data > max_multiplier) { - pr_err(PFX "invalid target frequency\n"); + pr_err("invalid target frequency\n"); return -EINVAL; } @@ -175,14 +176,14 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) max_multiplier = param_max_multiplier; goto have_max_multiplier; } - pr_err("powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); + pr_err("invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); return -EINVAL; } if (!max_multiplier) { - pr_warn("powernow-k6: unknown frequency %u, cannot determine current multiplier\n", + pr_warn("unknown frequency %u, cannot determine current multiplier\n", khz); - pr_warn("powernow-k6: use module parameters max_multiplier and bus_frequency\n"); + pr_warn("use module parameters max_multiplier and bus_frequency\n"); return -EOPNOTSUPP; } @@ -194,7 +195,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) busfreq = param_busfreq / 10; goto have_busfreq; } - pr_err("powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); + pr_err("invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); return -EINVAL; } @@ -276,7 +277,7 @@ static int __init powernow_k6_init(void) return -ENODEV; if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) { - pr_info(PFX "PowerNow IOPORT region already used\n"); + pr_info("PowerNow IOPORT region already used\n"); return -EIO; } diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 4a1b420da72e..9f013ed42977 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -13,6 +13,8 @@ * - We disable half multipliers if ACPI is used on A0 stepping CPUs. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -35,9 +37,6 @@ #include "powernow-k7.h" -#define PFX "powernow: " - - struct psb_s { u8 signature[10]; u8 tableversion; @@ -127,13 +126,13 @@ static int check_powernow(void) maxei = cpuid_eax(0x80000000); if (maxei < 0x80000007) { /* Any powernow info ? */ #ifdef MODULE - pr_info(PFX "No powernow capabilities detected\n"); + pr_info("No powernow capabilities detected\n"); #endif return 0; } if ((c->x86_model == 6) && (c->x86_mask == 0)) { - pr_info(PFX "K7 660[A0] core detected, enabling errata workarounds\n"); + pr_info("K7 660[A0] core detected, enabling errata workarounds\n"); have_a0 = 1; } @@ -143,7 +142,7 @@ static int check_powernow(void) if (!(edx & (1 << 1 | 1 << 2))) return 0; - pr_info(PFX "PowerNOW! Technology present. Can scale: "); + pr_info("PowerNOW! Technology present. Can scale: "); if (edx & 1 << 1) { pr_cont("frequency"); @@ -426,14 +425,14 @@ static int powernow_acpi_init(void) err05: kfree(acpi_processor_perf); err0: - pr_warn(PFX "ACPI perflib can not be used on this platform\n"); + pr_warn("ACPI perflib can not be used on this platform\n"); acpi_processor_perf = NULL; return retval; } #else static int powernow_acpi_init(void) { - pr_info(PFX "no support for ACPI processor found - please recompile your kernel with ACPI processor\n"); + pr_info("no support for ACPI processor found - please recompile your kernel with ACPI processor\n"); return -EINVAL; } #endif @@ -465,7 +464,7 @@ static int powernow_decode_bios(int maxfid, int startvid) psb = (struct psb_s *) p; pr_debug("Table version: 0x%x\n", psb->tableversion); if (psb->tableversion != 0x12) { - pr_info(PFX "Sorry, only v1.2 tables supported right now\n"); + pr_info("Sorry, only v1.2 tables supported right now\n"); return -ENODEV; } @@ -477,7 +476,7 @@ static int powernow_decode_bios(int maxfid, int startvid) latency = psb->settlingtime; if (latency < 100) { - pr_info(PFX "BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n", + pr_info("BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n", latency); latency = 100; } @@ -510,9 +509,9 @@ static int powernow_decode_bios(int maxfid, int startvid) p += 2; } } - pr_info(PFX "No PST tables match this cpuid (0x%x)\n", + pr_info("No PST tables match this cpuid (0x%x)\n", etuple); - pr_info(PFX "This is indicative of a broken BIOS\n"); + pr_info("This is indicative of a broken BIOS\n"); return -EINVAL; } @@ -545,7 +544,7 @@ static int fixup_sgtc(void) sgtc = 100 * m * latency; sgtc = sgtc / 3; if (sgtc > 0xfffff) { - pr_warn(PFX "SGTC too large %d\n", sgtc); + pr_warn("SGTC too large %d\n", sgtc); sgtc = 0xfffff; } return sgtc; @@ -567,10 +566,10 @@ static unsigned int powernow_get(unsigned int cpu) static int acer_cpufreq_pst(const struct dmi_system_id *d) { - pr_warn(PFX "%s laptop with broken PST tables in BIOS detected\n", + pr_warn("%s laptop with broken PST tables in BIOS detected\n", d->ident); - pr_warn(PFX "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n"); - pr_warn(PFX "cpufreq scaling has been disabled as a result of this\n"); + pr_warn("You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n"); + pr_warn("cpufreq scaling has been disabled as a result of this\n"); return 0; } @@ -605,37 +604,37 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; if (!fsb) { - pr_warn(PFX "can not determine bus frequency\n"); + pr_warn("can not determine bus frequency\n"); return -EINVAL; } pr_debug("FSB: %3dMHz\n", fsb/1000); if (dmi_check_system(powernow_dmi_table) || acpi_force) { - pr_info(PFX "PSB/PST known to be broken - trying ACPI instead\n"); + pr_info("PSB/PST known to be broken - trying ACPI instead\n"); result = powernow_acpi_init(); } else { result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID); if (result) { - pr_info(PFX "Trying ACPI perflib\n"); + pr_info("Trying ACPI perflib\n"); maximum_speed = 0; minimum_speed = -1; latency = 0; result = powernow_acpi_init(); if (result) { - pr_info(PFX "ACPI and legacy methods failed\n"); + pr_info("ACPI and legacy methods failed\n"); } } else { /* SGTC use the bus clock as timer */ latency = fixup_sgtc(); - pr_info(PFX "SGTC: %d\n", latency); + pr_info("SGTC: %d\n", latency); } } if (result) return result; - pr_info(PFX "Minimum speed %d MHz - Maximum speed %d MHz\n", + pr_info("Minimum speed %d MHz - Maximum speed %d MHz\n", minimum_speed/1000, maximum_speed/1000); policy->cpuinfo.transition_latency = diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 8a27667c16fa..ce345bf34d5d 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -29,6 +29,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -186,8 +188,7 @@ static int pxa_cpufreq_change_voltage(const struct pxa_freqs *pxa_freq) ret = regulator_set_voltage(vcc_core, vmin, vmax); if (ret) - pr_err("cpufreq: Failed to set vcc_core in [%dmV..%dmV]\n", - vmin, vmax); + pr_err("Failed to set vcc_core in [%dmV..%dmV]\n", vmin, vmax); return ret; } @@ -195,10 +196,10 @@ static void __init pxa_cpufreq_init_voltages(void) { vcc_core = regulator_get(NULL, "vcc_core"); if (IS_ERR(vcc_core)) { - pr_info("cpufreq: Didn't find vcc_core regulator\n"); + pr_info("Didn't find vcc_core regulator\n"); vcc_core = NULL; } else { - pr_info("cpufreq: Found vcc_core regulator\n"); + pr_info("Found vcc_core regulator\n"); } } #else @@ -407,7 +408,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) */ if (cpu_is_pxa25x()) { find_freq_tables(&pxa255_freq_table, &pxa255_freqs); - pr_info("PXA255 cpufreq using %s frequency table\n", + pr_info("using %s frequency table\n", pxa255_turbo_table ? "turbo" : "run"); cpufreq_table_validate_and_show(policy, pxa255_freq_table); @@ -416,7 +417,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) cpufreq_table_validate_and_show(policy, pxa27x_freq_table); } - pr_info("PXA CPU frequency change support initialized\n"); + pr_info("frequency change support initialized\n"); return 0; } diff --git a/drivers/cpufreq/s3c2412-cpufreq.c b/drivers/cpufreq/s3c2412-cpufreq.c index f9447bac9e22..b04b6f02bbdc 100644 --- a/drivers/cpufreq/s3c2412-cpufreq.c +++ b/drivers/cpufreq/s3c2412-cpufreq.c @@ -10,6 +10,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -197,20 +199,20 @@ static int s3c2412_cpufreq_add(struct device *dev, hclk = clk_get(NULL, "hclk"); if (IS_ERR(hclk)) { - pr_err("%s: cannot find hclk clock\n", __func__); + pr_err("cannot find hclk clock\n"); return -ENOENT; } fclk = clk_get(NULL, "fclk"); if (IS_ERR(fclk)) { - pr_err("%s: cannot find fclk clock\n", __func__); + pr_err("cannot find fclk clock\n"); goto err_fclk; } fclk_rate = clk_get_rate(fclk); if (fclk_rate > 200000000) { - pr_info("%s: fclk %ld MHz, assuming 266MHz capable part\n", - __func__, fclk_rate / 1000000); + pr_info("fclk %ld MHz, assuming 266MHz capable part\n", + fclk_rate / 1000000); s3c2412_cpufreq_info.max.fclk = 266000000; s3c2412_cpufreq_info.max.hclk = 133000000; s3c2412_cpufreq_info.max.pclk = 66000000; @@ -218,13 +220,13 @@ static int s3c2412_cpufreq_add(struct device *dev, armclk = clk_get(NULL, "armclk"); if (IS_ERR(armclk)) { - pr_err("%s: cannot find arm clock\n", __func__); + pr_err("cannot find arm clock\n"); goto err_armclk; } xtal = clk_get(NULL, "xtal"); if (IS_ERR(xtal)) { - pr_err("%s: cannot find xtal clock\n", __func__); + pr_err("cannot find xtal clock\n"); goto err_xtal; } diff --git a/drivers/cpufreq/s3c2440-cpufreq.c b/drivers/cpufreq/s3c2440-cpufreq.c index f6cefe34e411..d0d75b65ddd6 100644 --- a/drivers/cpufreq/s3c2440-cpufreq.c +++ b/drivers/cpufreq/s3c2440-cpufreq.c @@ -11,6 +11,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c b/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c index 8182608aeac1..4d976e8dbb2f 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c +++ b/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c @@ -10,6 +10,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 68f883744500..ae8eaed77b70 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -10,6 +10,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -356,7 +358,7 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) clk = clk_get(dev, name); if (IS_ERR(clk)) - pr_err("cpufreq: failed to get clock '%s'\n", name); + pr_err("failed to get clock '%s'\n", name); return clk; } @@ -665,9 +667,9 @@ int s3c_plltab_register(struct cpufreq_frequency_table *plls, vals += plls_no; vals->frequency = CPUFREQ_TABLE_END; - pr_info("cpufreq: %d PLL entries\n", plls_no); + pr_info("%d PLL entries\n", plls_no); } else - pr_err("cpufreq: no memory for PLL tables\n"); + pr_err("no memory for PLL tables\n"); return vals ? 0 : -ENOMEM; } diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 344e584412ed..06d85917b6d5 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -9,6 +9,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -635,13 +637,13 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev) arm_regulator = regulator_get(NULL, "vddarm"); if (IS_ERR(arm_regulator)) { - pr_err("failed to get regulator vddarm"); + pr_err("failed to get regulator vddarm\n"); return PTR_ERR(arm_regulator); } int_regulator = regulator_get(NULL, "vddint"); if (IS_ERR(int_regulator)) { - pr_err("failed to get regulator vddint"); + pr_err("failed to get regulator vddint\n"); regulator_put(arm_regulator); return PTR_ERR(int_regulator); } diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 57bbddf55786..4225501a4b78 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -13,6 +13,8 @@ * 2005-03-30: - initial revision */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -30,8 +32,6 @@ static __u8 __iomem *cpuctl; -#define PFX "sc520_freq: " - static struct cpufreq_frequency_table sc520_freq_table[] = { {0, 0x01, 100000}, {0, 0x02, 133000}, @@ -44,7 +44,7 @@ static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu) switch (clockspeed_reg & 0x03) { default: - pr_err(PFX "error: cpuctl register has unexpected value %02x\n", + pr_err("error: cpuctl register has unexpected value %02x\n", clockspeed_reg); case 0x01: return 100000; diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 47df2d649b78..41bc5397f4bb 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -13,6 +13,8 @@ * Copyright (C) 2003 Jeremy Fitzhardinge */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -27,7 +29,6 @@ #include #include -#define PFX "speedstep-centrino: " #define MAINTAINER "linux-pm@vger.kernel.org" #define INTEL_MSR_RANGE (0xffff) @@ -386,7 +387,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) /* check to see if it stuck */ rdmsr(MSR_IA32_MISC_ENABLE, l, h); if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) { - pr_info(PFX "couldn't enable Enhanced SpeedStep\n"); + pr_info("couldn't enable Enhanced SpeedStep\n"); return -ENODEV; } } diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index 9d00c226a6aa..b86953a3ddc4 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -18,6 +18,8 @@ * SPEEDSTEP - DEFINITIONS * *********************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -68,13 +70,13 @@ static int speedstep_find_register(void) /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) { - pr_err("speedstep-ich: could not find speedstep register\n"); + pr_err("could not find speedstep register\n"); return -ENODEV; } pmbase &= 0xFFFFFFFE; if (!pmbase) { - pr_err("speedstep-ich: could not find speedstep register\n"); + pr_err("could not find speedstep register\n"); return -ENODEV; } @@ -136,7 +138,7 @@ static void speedstep_set_state(unsigned int state) pr_debug("change to %u MHz succeeded\n", speedstep_get_frequency(speedstep_processor) / 1000); else - pr_err("cpufreq: change failed - I/O error\n"); + pr_err("change failed - I/O error\n"); return; } diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c index 32bdf1df9517..1b8062182c81 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c @@ -8,6 +8,8 @@ * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -453,7 +455,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor, */ if (*transition_latency > 10000000 || *transition_latency < 50000) { - pr_warn(PFX "frequency transition measured seems out of range (%u nSec), falling back to a safe one of %u nSec\n", + pr_warn("frequency transition measured seems out of range (%u nSec), falling back to a safe one of %u nSec\n", *transition_latency, 500000); *transition_latency = 500000; } diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index af32a5f38806..770a9ae1999a 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -12,6 +12,8 @@ * SPEEDSTEP - DEFINITIONS * *********************************************************************/ +#define pr_fmt(fmt) "cpufreq: " fmt + #include #include #include @@ -204,7 +206,7 @@ static void speedstep_set_state(unsigned int state) (speedstep_freqs[new_state].frequency / 1000), retry, result); else - pr_err("cpufreq: change to state %u failed with new_state %u and result %u\n", + pr_err("change to state %u failed with new_state %u and result %u\n", state, new_state, result); return; -- GitLab From cd73e9b01f635d25dbd17ed090f9351becf00280 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Apr 2016 03:30:40 +0200 Subject: [PATCH 1880/9938] cpufreq: Simplify switch () in cpufreq_cpu_callback() Merge two switch entries that do the same thing in cpufreq_cpu_callback(). No functional changes. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 77d77a4e3b74..859281592680 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2309,16 +2309,13 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: + case CPU_DOWN_FAILED: cpufreq_online(cpu); break; case CPU_DOWN_PREPARE: cpufreq_offline(cpu); break; - - case CPU_DOWN_FAILED: - cpufreq_online(cpu); - break; } return NOTIFY_OK; } -- GitLab From a794d6138cda391b6a9ba28c4cf27651415669c6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Apr 2016 03:31:57 +0200 Subject: [PATCH 1881/9938] cpufreq: Rearrange cpufreq_add_dev() Reorganize the code in cpufreq_add_dev() to avoid using the ret variable and reduce the indentation level in it. No functional changes. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 859281592680..2f1ae568f74b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1320,26 +1320,24 @@ static int cpufreq_online(unsigned int cpu) */ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) { + struct cpufreq_policy *policy; unsigned cpu = dev->id; - int ret; dev_dbg(dev, "%s: adding CPU%u\n", __func__, cpu); - if (cpu_online(cpu)) { - ret = cpufreq_online(cpu); - } else { - /* - * A hotplug notifier will follow and we will handle it as CPU - * online then. For now, just create the sysfs link, unless - * there is no policy or the link is already present. - */ - struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); + if (cpu_online(cpu)) + return cpufreq_online(cpu); - ret = policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus) - ? add_cpu_dev_symlink(policy, cpu) : 0; - } + /* + * A hotplug notifier will follow and we will handle it as CPU online + * then. For now, just create the sysfs link, unless there is no policy + * or the link is already present. + */ + policy = per_cpu(cpufreq_cpu_data, cpu); + if (!policy || cpumask_test_and_set_cpu(cpu, policy->real_cpus)) + return 0; - return ret; + return add_cpu_dev_symlink(policy, cpu); } static void cpufreq_offline(unsigned int cpu) -- GitLab From 9b55f55af8f017fec053c7eb0675241d057936da Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 7 Apr 2016 14:06:58 +0530 Subject: [PATCH 1882/9938] cpufreq: ACPI: policy->driver_data can't be NULL in ->exit() Its always set by ->init() and so it will always be there in ->exit(). There is no need to have a special check for just that. Signed-off-by: Viresh Kumar [ rjw: Rebase ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/acpi-cpufreq.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 67a612e22179..a24a0c05d7f8 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -878,14 +878,12 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) pr_debug("acpi_cpufreq_cpu_exit\n"); - if (data) { - policy->fast_switch_possible = false; - policy->driver_data = NULL; - acpi_processor_unregister_performance(data->acpi_perf_cpu); - free_cpumask_var(data->freqdomain_cpus); - kfree(data->freq_table); - kfree(data); - } + policy->fast_switch_possible = false; + policy->driver_data = NULL; + acpi_processor_unregister_performance(data->acpi_perf_cpu); + free_cpumask_var(data->freqdomain_cpus); + kfree(data->freq_table); + kfree(data); return 0; } -- GitLab From 357f435d8a0d32068c75f3c7176434d992b3adb7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 8 Apr 2016 19:05:19 -0400 Subject: [PATCH 1883/9938] fix the copy vs. map logics in blk_rq_map_user_iov() Signed-off-by: Al Viro --- block/blk-map.c | 47 ++++++++------------------------------------- include/linux/uio.h | 1 + lib/iov_iter.c | 19 ++++++++++++++++++ 3 files changed, 28 insertions(+), 39 deletions(-) diff --git a/block/blk-map.c b/block/blk-map.c index a54f0543b956..b9f88b7751fb 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -9,24 +9,6 @@ #include "blk.h" -static bool iovec_gap_to_prv(struct request_queue *q, - struct iovec *prv, struct iovec *cur) -{ - unsigned long prev_end; - - if (!queue_virt_boundary(q)) - return false; - - if (prv->iov_base == NULL && prv->iov_len == 0) - /* prv is not set - don't check */ - return false; - - prev_end = (unsigned long)(prv->iov_base + prv->iov_len); - - return (((unsigned long)cur->iov_base & queue_virt_boundary(q)) || - prev_end & queue_virt_boundary(q)); -} - int blk_rq_append_bio(struct request_queue *q, struct request *rq, struct bio *bio) { @@ -125,31 +107,18 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, struct rq_map_data *map_data, const struct iov_iter *iter, gfp_t gfp_mask) { - struct iovec iov, prv = {.iov_base = NULL, .iov_len = 0}; - bool copy = (q->dma_pad_mask & iter->count) || map_data; + bool copy = false; + unsigned long align = q->dma_pad_mask | queue_dma_alignment(q); struct bio *bio = NULL; struct iov_iter i; int ret; - if (!iter || !iter->count) - return -EINVAL; - - iov_for_each(iov, i, *iter) { - unsigned long uaddr = (unsigned long) iov.iov_base; - - if (!iov.iov_len) - return -EINVAL; - - /* - * Keep going so we check length of all segments - */ - if ((uaddr & queue_dma_alignment(q)) || - iovec_gap_to_prv(q, &prv, &iov)) - copy = true; - - prv.iov_base = iov.iov_base; - prv.iov_len = iov.iov_len; - } + if (map_data) + copy = true; + else if (iov_iter_alignment(iter) & align) + copy = true; + else if (queue_virt_boundary(q)) + copy = queue_virt_boundary(q) & iov_iter_gap_alignment(iter); i = *iter; do { diff --git a/include/linux/uio.h b/include/linux/uio.h index fd9bcfedad42..1b5d1cd796e2 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -87,6 +87,7 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); size_t iov_iter_zero(size_t bytes, struct iov_iter *); unsigned long iov_iter_alignment(const struct iov_iter *i); +unsigned long iov_iter_gap_alignment(const struct iov_iter *i); void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, unsigned long nr_segs, size_t count); void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *kvec, diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 5fecddc32b1b..ca5316e0087b 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -569,6 +569,25 @@ unsigned long iov_iter_alignment(const struct iov_iter *i) } EXPORT_SYMBOL(iov_iter_alignment); +unsigned long iov_iter_gap_alignment(const struct iov_iter *i) +{ + unsigned long res = 0; + size_t size = i->count; + if (!size) + return 0; + + iterate_all_kinds(i, size, v, + (res |= (!res ? 0 : (unsigned long)v.iov_base) | + (size != v.iov_len ? size : 0), 0), + (res |= (!res ? 0 : (unsigned long)v.bv_offset) | + (size != v.bv_len ? size : 0)), + (res |= (!res ? 0 : (unsigned long)v.iov_base) | + (size != v.iov_len ? size : 0)) + ); + return res; +} +EXPORT_SYMBOL(iov_iter_gap_alignment); + ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, size_t maxsize, unsigned maxpages, size_t *start) -- GitLab From 8cee1eed8e78143aa2ed60308fb88e2d6fa46205 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 7 Apr 2016 14:06:57 +0530 Subject: [PATCH 1884/9938] cpufreq: ACPI: Remove freq_table from acpi_cpufreq_data The freq-table is stored in struct cpufreq_policy also and there is absolutely no need of keeping a copy of its reference in struct acpi_cpufreq_data. Drop it. Also policy->freq_table can't be NULL in the target() callback, remove the useless check as well. Signed-off-by: Viresh Kumar [ rjw: Rebase ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/acpi-cpufreq.c | 63 ++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index a24a0c05d7f8..32a15052f363 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -65,7 +65,6 @@ enum { #define MSR_K7_HWCR_CPB_DIS (1ULL << 25) struct acpi_cpufreq_data { - struct cpufreq_frequency_table *freq_table; unsigned int resume; unsigned int cpu_feature; unsigned int acpi_perf_cpu; @@ -200,8 +199,9 @@ static int check_amd_hwpstate_cpu(unsigned int cpuid) return cpu_has(cpu, X86_FEATURE_HW_PSTATE); } -static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data) +static unsigned extract_io(struct cpufreq_policy *policy, u32 value) { + struct acpi_cpufreq_data *data = policy->driver_data; struct acpi_processor_performance *perf; int i; @@ -209,13 +209,14 @@ static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data) for (i = 0; i < perf->state_count; i++) { if (value == perf->states[i].status) - return data->freq_table[i].frequency; + return policy->freq_table[i].frequency; } return 0; } -static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) +static unsigned extract_msr(struct cpufreq_policy *policy, u32 msr) { + struct acpi_cpufreq_data *data = policy->driver_data; struct cpufreq_frequency_table *pos; struct acpi_processor_performance *perf; @@ -226,20 +227,22 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) perf = to_perf_data(data); - cpufreq_for_each_entry(pos, data->freq_table) + cpufreq_for_each_entry(pos, policy->freq_table) if (msr == perf->states[pos->driver_data].status) return pos->frequency; - return data->freq_table[0].frequency; + return policy->freq_table[0].frequency; } -static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data) +static unsigned extract_freq(struct cpufreq_policy *policy, u32 val) { + struct acpi_cpufreq_data *data = policy->driver_data; + switch (data->cpu_feature) { case SYSTEM_INTEL_MSR_CAPABLE: case SYSTEM_AMD_MSR_CAPABLE: - return extract_msr(val, data); + return extract_msr(policy, val); case SYSTEM_IO_CAPABLE: - return extract_io(val, data); + return extract_io(policy, val); default: return 0; } @@ -374,11 +377,11 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu) return 0; data = policy->driver_data; - if (unlikely(!data || !data->freq_table)) + if (unlikely(!data || !policy->freq_table)) return 0; - cached_freq = data->freq_table[to_perf_data(data)->state].frequency; - freq = extract_freq(get_cur_val(cpumask_of(cpu), data), data); + cached_freq = policy->freq_table[to_perf_data(data)->state].frequency; + freq = extract_freq(policy, get_cur_val(cpumask_of(cpu), data)); if (freq != cached_freq) { /* * The dreaded BIOS frequency change behind our back. @@ -392,14 +395,15 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu) return freq; } -static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq, - struct acpi_cpufreq_data *data) +static unsigned int check_freqs(struct cpufreq_policy *policy, + const struct cpumask *mask, unsigned int freq) { + struct acpi_cpufreq_data *data = policy->driver_data; unsigned int cur_freq; unsigned int i; for (i = 0; i < 100; i++) { - cur_freq = extract_freq(get_cur_val(mask, data), data); + cur_freq = extract_freq(policy, get_cur_val(mask, data)); if (cur_freq == freq) return 1; udelay(10); @@ -416,12 +420,12 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, unsigned int next_perf_state = 0; /* Index into perf table */ int result = 0; - if (unlikely(data == NULL || data->freq_table == NULL)) { + if (unlikely(!data)) { return -ENODEV; } perf = to_perf_data(data); - next_perf_state = data->freq_table[index].driver_data; + next_perf_state = policy->freq_table[index].driver_data; if (perf->state == next_perf_state) { if (unlikely(data->resume)) { pr_debug("Called after resume, resetting to P%d\n", @@ -444,8 +448,8 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, drv_write(data, mask, perf->states[next_perf_state].control); if (acpi_pstate_strict) { - if (!check_freqs(mask, data->freq_table[index].frequency, - data)) { + if (!check_freqs(policy, mask, + policy->freq_table[index].frequency)) { pr_debug("acpi_cpufreq_target failed (%d)\n", policy->cpu); result = -EAGAIN; @@ -472,7 +476,7 @@ unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy, * The table is sorted in the reverse order with respect to the * frequency and all of the entries are valid (see the initialization). */ - entry = data->freq_table; + entry = policy->freq_table; do { entry++; freq = entry->frequency; @@ -665,6 +669,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) unsigned int result = 0; struct cpuinfo_x86 *c = &cpu_data(policy->cpu); struct acpi_processor_performance *perf; + struct cpufreq_frequency_table *freq_table; #ifdef CONFIG_SMP static int blacklisted; #endif @@ -776,9 +781,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) goto err_unreg; } - data->freq_table = kzalloc(sizeof(*data->freq_table) * + freq_table = kzalloc(sizeof(*freq_table) * (perf->state_count+1), GFP_KERNEL); - if (!data->freq_table) { + if (!freq_table) { result = -ENOMEM; goto err_unreg; } @@ -802,18 +807,18 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) /* table init */ for (i = 0; i < perf->state_count; i++) { if (i > 0 && perf->states[i].core_frequency >= - data->freq_table[valid_states-1].frequency / 1000) + freq_table[valid_states-1].frequency / 1000) continue; - data->freq_table[valid_states].driver_data = i; - data->freq_table[valid_states].frequency = + freq_table[valid_states].driver_data = i; + freq_table[valid_states].frequency = perf->states[i].core_frequency * 1000; valid_states++; } - data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END; + freq_table[valid_states].frequency = CPUFREQ_TABLE_END; perf->state = 0; - result = cpufreq_table_validate_and_show(policy, data->freq_table); + result = cpufreq_table_validate_and_show(policy, freq_table); if (result) goto err_freqfree; @@ -860,7 +865,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) return result; err_freqfree: - kfree(data->freq_table); + kfree(freq_table); err_unreg: acpi_processor_unregister_performance(cpu); err_free_mask: @@ -882,7 +887,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) policy->driver_data = NULL; acpi_processor_unregister_performance(data->acpi_perf_cpu); free_cpumask_var(data->freqdomain_cpus); - kfree(data->freq_table); + kfree(policy->freq_table); kfree(data); return 0; -- GitLab From 3db80c230da15ceb1a526438b458058abcd53800 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Sun, 7 Feb 2016 10:00:31 -0500 Subject: [PATCH 1885/9938] ACPI: implement Generic Event Device Generic Event Device described in ACPI 6.1 allows platforms to handle platform interrupts in ACPI ASL statements. It borrows constructs like _EVT from GPIO events. All interrupts are listed in _CRS and the handler is written in _EVT method. Here is an example. Device (GED0) { Name (_HID, "ACPI0013") Name (_UID, 0) Name(_CRS, ResourceTemplate () { Interrupt(ResourceConsumer, Edge, ActiveHigh, Shared, , , ) {123} }) Method (_EVT, 1) { if (Lequal(123, Arg0)) { } } } Wake capability has not been implemented yet. Signed-off-by: Sinan Kaya Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 1 + drivers/acpi/evged.c | 156 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 drivers/acpi/evged.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index edeb2d1d99be..5a65f85cf7a7 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -47,6 +47,7 @@ acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o acpi-y += int340x_thermal.o acpi-y += power.o acpi-y += event.o +acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o acpi-y += sysfs.o acpi-y += property.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c new file mode 100644 index 000000000000..9c0a868d7b57 --- /dev/null +++ b/drivers/acpi/evged.c @@ -0,0 +1,156 @@ +/* + * Generic Event Device for ACPI. + * + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Generic Event Device allows platforms to handle interrupts in ACPI + * ASL statements. It follows very similar to _EVT method approach + * from GPIO events. All interrupts are listed in _CRS and the handler + * is written in _EVT method. Here is an example. + * + * Device (GED0) + * { + * + * Name (_HID, "ACPI0013") + * Name (_UID, 0) + * Method (_CRS, 0x0, Serialized) + * { + * Name (RBUF, ResourceTemplate () + * { + * Interrupt(ResourceConsumer, Edge, ActiveHigh, Shared, , , ) + * {123} + * } + * }) + * + * Method (_EVT, 1) { + * if (Lequal(123, Arg0)) + * { + * } + * } + * } + * + */ + +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "acpi-ged" + +struct acpi_ged_event { + struct list_head node; + struct device *dev; + unsigned int gsi; + unsigned int irq; + acpi_handle handle; +}; + +static irqreturn_t acpi_ged_irq_handler(int irq, void *data) +{ + struct acpi_ged_event *event = data; + acpi_status acpi_ret; + + acpi_ret = acpi_execute_simple_method(event->handle, NULL, event->gsi); + if (ACPI_FAILURE(acpi_ret)) + dev_err_once(event->dev, "IRQ method execution failed\n"); + + return IRQ_HANDLED; +} + +static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares, + void *context) +{ + struct acpi_ged_event *event; + unsigned int irq; + unsigned int gsi; + unsigned int irqflags = IRQF_ONESHOT; + struct device *dev = context; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_handle evt_handle; + struct resource r; + struct acpi_resource_irq *p = &ares->data.irq; + struct acpi_resource_extended_irq *pext = &ares->data.extended_irq; + + if (ares->type == ACPI_RESOURCE_TYPE_END_TAG) + return AE_OK; + + if (!acpi_dev_resource_interrupt(ares, 0, &r)) { + dev_err(dev, "unable to parse IRQ resource\n"); + return AE_ERROR; + } + if (ares->type == ACPI_RESOURCE_TYPE_IRQ) + gsi = p->interrupts[0]; + else + gsi = pext->interrupts[0]; + + irq = r.start; + + if (ACPI_FAILURE(acpi_get_handle(handle, "_EVT", &evt_handle))) { + dev_err(dev, "cannot locate _EVT method\n"); + return AE_ERROR; + } + + dev_info(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq); + + event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL); + if (!event) + return AE_ERROR; + + event->gsi = gsi; + event->dev = dev; + event->irq = irq; + event->handle = evt_handle; + + if (r.flags & IORESOURCE_IRQ_SHAREABLE) + irqflags |= IRQF_SHARED; + + if (devm_request_threaded_irq(dev, irq, NULL, acpi_ged_irq_handler, + irqflags, "ACPI:Ged", event)) { + dev_err(dev, "failed to setup event handler for irq %u\n", irq); + return AE_ERROR; + } + + return AE_OK; +} + +static int ged_probe(struct platform_device *pdev) +{ + acpi_status acpi_ret; + + acpi_ret = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), "_CRS", + acpi_ged_request_interrupt, &pdev->dev); + if (ACPI_FAILURE(acpi_ret)) { + dev_err(&pdev->dev, "unable to parse the _CRS record\n"); + return -EINVAL; + } + + return 0; +} + +static const struct acpi_device_id ged_acpi_ids[] = { + {"ACPI0013"}, + {}, +}; + +static struct platform_driver ged_driver = { + .probe = ged_probe, + .driver = { + .name = MODULE_NAME, + .acpi_match_table = ACPI_PTR(ged_acpi_ids), + }, +}; + +module_platform_driver(ged_driver); +MODULE_LICENSE("GPL v2"); -- GitLab From 1373718194ebebc43c00d8f117e03885749495b0 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Tue, 22 Mar 2016 08:51:10 +0800 Subject: [PATCH 1886/9938] ACPI / PM: Introduce efi poweroff for HW-full platforms without _S5 The problem is Linux registers pm_power_off = efi_power_off only if we are in hardware reduced mode. Actually, what we also want is to do this when ACPI S5 is simply not supported on non-legacy platforms. Since some future Intel platforms are HW-full mode where the DSDT fails to supply an _S5 object(without SLP_TYP), we should let such kind of platform to leverage efi runtime service to poweroff. This patch uses efi power off as first choice when S5 is unavailable, even if there is a customized poweroff(driver provided, eg). Meanwhile, the legacy platforms will not be affected because there is no path for them to overwrite the pm_power_off to efi power off. Suggested-by: Len Brown Reviewed-by: Matt Fleming Signed-off-by: Chen Yu Signed-off-by: Rafael J. Wysocki --- arch/x86/platform/efi/quirks.c | 2 +- drivers/acpi/sleep.c | 7 +++++++ include/linux/acpi.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index ab50ada1d56e..818d12ad7761 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -373,5 +373,5 @@ bool efi_reboot_required(void) bool efi_poweroff_required(void) { - return !!acpi_gbl_reduced_hardware; + return acpi_gbl_reduced_hardware || acpi_no_s5; } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2a8b59644297..7a2e4d45b266 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -26,6 +26,11 @@ #include "internal.h" #include "sleep.h" +/* + * Some HW-full platforms do not have _S5, so they may need + * to leverage efi power off for a shutdown. + */ +bool acpi_no_s5; static u8 sleep_states[ACPI_S_STATE_COUNT]; static void acpi_sleep_tts_switch(u32 acpi_state) @@ -882,6 +887,8 @@ int __init acpi_sleep_init(void) sleep_states[ACPI_STATE_S5] = 1; pm_power_off_prepare = acpi_power_off_prepare; pm_power_off = acpi_power_off; + } else { + acpi_no_s5 = true; } supported[0] = 0; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 06ed7e54033e..4d2e67f633b6 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -278,6 +278,7 @@ void acpi_irq_stats_init(void); extern u32 acpi_irq_handled; extern u32 acpi_irq_not_handled; extern unsigned int acpi_sci_irq; +extern bool acpi_no_s5; #define INVALID_ACPI_IRQ ((unsigned)-1) static inline bool acpi_sci_irq_valid(void) { -- GitLab From c998c07836f985b24361629dc98506ec7893e7a0 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Tue, 5 Apr 2016 14:05:38 -0500 Subject: [PATCH 1887/9938] cpuidle: Indicate when a device has been unregistered Currently the 'registered' member of the cpuidle_device struct is set to 1 during cpuidle_register_device. In this same function there are checks to see if the device is already registered to prevent duplicate calls to register the device, but this value is never set to 0 even on unregister of the device. Because of this, any attempt to call cpuidle_register_device after a call to cpuidle_unregister_device will fail which shouldn't be the case. To prevent this, set registered to 0 when the device is unregistered. Fixes: c878a52d3c7c (cpuidle: Check if device is already registered) Signed-off-by: Dave Gerlach Acked-by: Daniel Lezcano Cc: All applicable Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index f996efc56605..c2dd99ab1648 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -433,6 +433,8 @@ static void __cpuidle_unregister_device(struct cpuidle_device *dev) list_del(&dev->device_list); per_cpu(cpuidle_devices, dev->cpu) = NULL; module_put(drv->owner); + + dev->registered = 0; } static void __cpuidle_device_init(struct cpuidle_device *dev) -- GitLab From 5dcef694860100fd16885f052591b1268b764d21 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 6 Apr 2016 17:00:47 -0400 Subject: [PATCH 1888/9938] intel_idle: add BXT support Broxton has all the HSW C-states, except C3. BXT C-state timing is slightly different. Here we trust the IRTL MSRs as authority on maximum C-state latency, and override the driver's tables with the values found in the associated IRTL MSRs. Further we set the target_residency to 1x maximum latency, trusting the hardware demotion logic. Signed-off-by: Len Brown Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/msr-index.h | 8 ++ drivers/idle/intel_idle.c | 137 +++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index b05402ef3b84..73d66fa48638 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -162,6 +162,14 @@ #define MSR_PKG_C9_RESIDENCY 0x00000631 #define MSR_PKG_C10_RESIDENCY 0x00000632 +/* Interrupt Response Limit */ +#define MSR_PKGC3_IRTL 0x0000060a +#define MSR_PKGC6_IRTL 0x0000060b +#define MSR_PKGC7_IRTL 0x0000060c +#define MSR_PKGC8_IRTL 0x00000633 +#define MSR_PKGC9_IRTL 0x00000634 +#define MSR_PKGC10_IRTL 0x00000635 + /* Run Time Average Power Limiting (RAPL) Interface */ #define MSR_RAPL_POWER_UNIT 0x00000606 diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index c6935de425fa..c96649292b55 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -766,6 +766,67 @@ static struct cpuidle_state knl_cstates[] = { .enter = NULL } }; +static struct cpuidle_state bxt_cstates[] = { + { + .name = "C1-BXT", + .desc = "MWAIT 0x00", + .flags = MWAIT2flg(0x00), + .exit_latency = 2, + .target_residency = 2, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C1E-BXT", + .desc = "MWAIT 0x01", + .flags = MWAIT2flg(0x01), + .exit_latency = 10, + .target_residency = 20, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C6-BXT", + .desc = "MWAIT 0x20", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 133, + .target_residency = 133, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C7s-BXT", + .desc = "MWAIT 0x31", + .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 155, + .target_residency = 155, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C8-BXT", + .desc = "MWAIT 0x40", + .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 1000, + .target_residency = 1000, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C9-BXT", + .desc = "MWAIT 0x50", + .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 2000, + .target_residency = 2000, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C10-BXT", + .desc = "MWAIT 0x60", + .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 10000, + .target_residency = 10000, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .enter = NULL } +}; + /** * intel_idle * @dev: cpuidle_device @@ -950,6 +1011,11 @@ static const struct idle_cpu idle_cpu_knl = { .state_table = knl_cstates, }; +static const struct idle_cpu idle_cpu_bxt = { + .state_table = bxt_cstates, + .disable_promotion_to_c1e = true, +}; + #define ICPU(model, cpu) \ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } @@ -985,6 +1051,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { ICPU(0x9e, idle_cpu_skl), ICPU(0x55, idle_cpu_skx), ICPU(0x57, idle_cpu_knl), + ICPU(0x5c, idle_cpu_bxt), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); @@ -1075,6 +1142,73 @@ static void ivt_idle_state_table_update(void) /* else, 1 and 2 socket systems use default ivt_cstates */ } + +/* + * Translate IRTL (Interrupt Response Time Limit) MSR to usec + */ + +static unsigned int irtl_ns_units[] = { + 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 }; + +static unsigned long long irtl_2_usec(unsigned long long irtl) +{ + unsigned long long ns; + + ns = irtl_ns_units[(irtl >> 10) & 0x3]; + + return div64_u64((irtl & 0x3FF) * ns, 1000); +} +/* + * bxt_idle_state_table_update(void) + * + * On BXT, we trust the IRTL to show the definitive maximum latency + * We use the same value for target_residency. + */ +static void bxt_idle_state_table_update(void) +{ + unsigned long long msr; + + rdmsrl(MSR_PKGC6_IRTL, msr); + if (msr) { + unsigned int usec = irtl_2_usec(msr); + + bxt_cstates[2].exit_latency = usec; + bxt_cstates[2].target_residency = usec; + } + + rdmsrl(MSR_PKGC7_IRTL, msr); + if (msr) { + unsigned int usec = irtl_2_usec(msr); + + bxt_cstates[3].exit_latency = usec; + bxt_cstates[3].target_residency = usec; + } + + rdmsrl(MSR_PKGC8_IRTL, msr); + if (msr) { + unsigned int usec = irtl_2_usec(msr); + + bxt_cstates[4].exit_latency = usec; + bxt_cstates[4].target_residency = usec; + } + + rdmsrl(MSR_PKGC9_IRTL, msr); + if (msr) { + unsigned int usec = irtl_2_usec(msr); + + bxt_cstates[5].exit_latency = usec; + bxt_cstates[5].target_residency = usec; + } + + rdmsrl(MSR_PKGC10_IRTL, msr); + if (msr) { + unsigned int usec = irtl_2_usec(msr); + + bxt_cstates[6].exit_latency = usec; + bxt_cstates[6].target_residency = usec; + } + +} /* * sklh_idle_state_table_update(void) * @@ -1130,6 +1264,9 @@ static void intel_idle_state_table_update(void) case 0x3e: /* IVT */ ivt_idle_state_table_update(); break; + case 0x5c: /* BXT */ + bxt_idle_state_table_update(); + break; case 0x5e: /* SKL-H */ sklh_idle_state_table_update(); break; -- GitLab From 0e1affe41bdd7b1bef64c007d260e142bcaef220 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 10:42:47 +0800 Subject: [PATCH 1889/9938] ACPI 2.0 / ECDT: Split EC_FLAGS_HANDLERS_INSTALLED This patch splits EC_FLAGS_HANDLERS_INSTALLED so that address space handler can be installed when it is not possible to install GPE handler during early stage. This patch also tunes address space handler installation, making it happening earlier than GPE handler installation for the same purpose. Since acpi_ec_start()/acpi_ec_stop() will be entered multiple times after applying this change, it is also required to protect acpi_enable_gpe()/ acpi_disable_gpe() invocations. Link: https://bugzilla.kernel.org/show_bug.cgi?id=112911 Signed-off-by: Lv Zheng Tested-by: Chris Bainbridge Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 96 +++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b420fb46669d..b8f474b78bc7 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -105,8 +105,8 @@ enum ec_command { enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */ - EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and - * OpReg are installed */ + EC_FLAGS_GPE_HANDLER_INSTALLED, /* GPE handler installed */ + EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */ EC_FLAGS_STARTED, /* Driver is started */ EC_FLAGS_STOPPED, /* Driver is stopped */ EC_FLAGS_COMMAND_STORM, /* GPE storms occurred to the @@ -367,7 +367,8 @@ static inline void acpi_ec_clear_gpe(struct acpi_ec *ec) static void acpi_ec_submit_request(struct acpi_ec *ec) { ec->reference_count++; - if (ec->reference_count == 1) + if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) && + ec->reference_count == 1) acpi_ec_enable_gpe(ec, true); } @@ -376,7 +377,8 @@ static void acpi_ec_complete_request(struct acpi_ec *ec) bool flushed = false; ec->reference_count--; - if (ec->reference_count == 0) + if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) && + ec->reference_count == 0) acpi_ec_disable_gpe(ec, true); flushed = acpi_ec_flushed(ec); if (flushed) @@ -1287,52 +1289,64 @@ static int ec_install_handlers(struct acpi_ec *ec) { acpi_status status; - if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) - return 0; - status = acpi_install_gpe_raw_handler(NULL, ec->gpe, - ACPI_GPE_EDGE_TRIGGERED, - &acpi_ec_gpe_handler, ec); - if (ACPI_FAILURE(status)) - return -ENODEV; - acpi_ec_start(ec, false); - status = acpi_install_address_space_handler(ec->handle, - ACPI_ADR_SPACE_EC, - &acpi_ec_space_handler, - NULL, ec); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_FOUND) { - /* - * Maybe OS fails in evaluating the _REG object. - * The AE_NOT_FOUND error will be ignored and OS - * continue to initialize EC. - */ - pr_err("Fail in evaluating the _REG object" - " of EC device. Broken bios is suspected.\n"); - } else { - acpi_ec_stop(ec, false); - acpi_remove_gpe_handler(NULL, ec->gpe, - &acpi_ec_gpe_handler); - return -ENODEV; + + if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { + status = acpi_install_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, + &acpi_ec_space_handler, + NULL, ec); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) { + /* + * Maybe OS fails in evaluating the _REG + * object. The AE_NOT_FOUND error will be + * ignored and OS * continue to initialize + * EC. + */ + pr_err("Fail in evaluating the _REG object" + " of EC device. Broken bios is suspected.\n"); + } else { + acpi_ec_stop(ec, false); + return -ENODEV; + } + } + set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); + } + + if (!test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) { + status = acpi_install_gpe_raw_handler(NULL, ec->gpe, + ACPI_GPE_EDGE_TRIGGERED, + &acpi_ec_gpe_handler, ec); + /* This is not fatal as we can poll EC events */ + if (ACPI_SUCCESS(status)) { + set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags); + if (test_bit(EC_FLAGS_STARTED, &ec->flags) && + ec->reference_count >= 1) + acpi_ec_enable_gpe(ec, true); } } - set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); return 0; } static void ec_remove_handlers(struct acpi_ec *ec) { - if (!test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) - return; acpi_ec_stop(ec, false); - if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, - ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) - pr_err("failed to remove space handler\n"); - if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, - &acpi_ec_gpe_handler))) - pr_err("failed to remove gpe handler\n"); - clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); + + if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { + if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) + pr_err("failed to remove space handler\n"); + clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); + } + + if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) { + if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, + &acpi_ec_gpe_handler))) + pr_err("failed to remove gpe handler\n"); + clear_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags); + } } static int acpi_ec_add(struct acpi_device *device) @@ -1434,7 +1448,7 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context) int __init acpi_boot_ec_enable(void) { - if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) + if (!boot_ec) return 0; if (!ec_install_handlers(boot_ec)) { first_ec = boot_ec; -- GitLab From 59f0aa9480cfef9173a648cec4537addc5f3ad94 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 10:42:53 +0800 Subject: [PATCH 1890/9938] ACPI 2.0 / ECDT: Remove early namespace reference from EC All operation region accesses are allowed by AML interpreter when AML is executed, so actually BIOSen are responsible to avoid the operation region accesses in AML before OSPM has prepared an operation region driver. This is done via _REG control method. So AML code normally sets a global named object REGC to 1 when _REG(3, 1) is evaluated. Then what is ECDT? Quoting from ACPI spec 6.0, 5.2.15 Embedded Controller Boot Resources Table (ECDT): "The presence of this table allows OSPM to provide Embedded Controller operation region space access before the namespace has been evaluated." Spec also suggests a compatible mean to indicate the early EC access availability: Device (EC) { Name (REGC, Ones) Method (_REG, 2) { If (LEqual (Arg0, 3)) { Store (Arg1, REGC) } } Method (ECAV) { If (LEqual (REGC, Ones)) { If (LGreaterEqual (_REV, 2)) { Return (One) } Else { Return (Zero) } } Else { Return (REGC) } } } In this way, it allows EC accesses to happen before EC._REG(3, 1) is invoked. But ECAV is not the only way practical BIOSen using to indicate the early EC access availibility, the known variations include: 1. Setting REGC to One in \_SB._INI when _REV >= 2. Since \_SB._INI is the first control method evaluated by OSPM during the enumeration, this allows EC accesses to happen for the entire enumeration process before the namespace EC is enumerated. 2. Initialize REGC to One by default, this even allows EC accesses to happen during the table loading. Linux is now broken around ECDT support during the long term bug fixing work because it has merged many wrong ECDT bug fixes (see details below). Linux currently uses namespace EC's settings instead of ECDT settings when ECDT is detected. This apparently will result in namespace walk and _CRS/_GPE/_REG evaluations. Such stuffs could only happen after namespace is ready, while ECDT is purposely to be used before namespace is ready. The wrong bug fixing story is: 1. Link 1: At Linux ACPI early stages, "no _Lxx/_Exx/_Qxx evaluation can happen before the namespace is ready" are not ensured by ACPICA core and Linux. This is currently ensured by deferred enabling of GPE and defered registering of EC query methods (acpi_ec_register_query_methods). 2. Link 2: Reporters reported buggy ECDTs, expecting quirks for the platform. Originally, the quirk is simple, only doing things with ECDT. Bug 9399 and 12461 are platforms (Asus L4R, Asus M6R, MSI MS-171F) reported to have wrong ECDT IO port addresses, the port addresses are reversed. Bug 11880 is a platform (Asus X50GL) reported to have 0 valued port addresses, we can see that all EC accesses are protected by ECAV on this platform, so actually no early EC accesses is required by this platform. 3. Link 3: But when the bug fixing developer was requested to provide a handy and non-quirk bug fix, he tried to use correct EC settings from namespace and broke the spec purpose. We can even see that the developer was suffered from many regrssions. One interesting one is 14086, where the actual root cause obviously should be: _REG is evaluated too early. But unfortunately, the bug is fixed in a totally wrong way. So everything goes wrong from these commits: Commit: c6cb0e878446c79f42e7833d7bb69ed6bfbb381f Subject: ACPI: EC: Don't trust ECDT tables from ASUS Commit: a5032bfdd9c80e0231a6324661e123818eb46ecd Subject: ACPI: EC: Always parse EC device This patch reverts Linux behavior to simple ECDT quirk support in order to stop early _CRS/_GPE/_REG evaluations. For Bug 9399, 12461, since it is reported that the platforms require early EC accesses, this patch restores the simple ECDT quirks for them. For Bug 11880, since it is not reported that the platform requires early EC accesses and its ACPI tables contain correct ECAV, we choose an ECDT enumeration failure for this platform. Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=9916 http://bugzilla.kernel.org/show_bug.cgi?id=10100 https://lkml.org/lkml/2008/2/25/282 Link 2: https://bugzilla.kernel.org/show_bug.cgi?id=9399 https://bugzilla.kernel.org/show_bug.cgi?id=12461 https://bugzilla.kernel.org/show_bug.cgi?id=11880 Link 3: https://bugzilla.kernel.org/show_bug.cgi?id=11884 https://bugzilla.kernel.org/show_bug.cgi?id=14081 https://bugzilla.kernel.org/show_bug.cgi?id=14086 https://bugzilla.kernel.org/show_bug.cgi?id=14446 Link 4: https://bugzilla.kernel.org/show_bug.cgi?id=112911 Signed-off-by: Lv Zheng Tested-by: Chris Bainbridge Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 145 +++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 91 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b8f474b78bc7..0e70181f150c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -175,10 +175,9 @@ static void acpi_ec_event_processor(struct work_struct *work); struct acpi_ec *boot_ec, *first_ec; EXPORT_SYMBOL(first_ec); -static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ -static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ +static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */ /* -------------------------------------------------------------------------- * Logging/Debugging @@ -1358,11 +1357,12 @@ static int acpi_ec_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_EC_CLASS); /* Check for boot EC */ - if (boot_ec && - (boot_ec->handle == device->handle || - boot_ec->handle == ACPI_ROOT_OBJECT)) { + if (boot_ec) { ec = boot_ec; boot_ec = NULL; + ec_remove_handlers(ec); + if (first_ec == ec) + first_ec = NULL; } else { ec = make_acpi_ec(); if (!ec) @@ -1462,20 +1462,6 @@ static const struct acpi_device_id ec_device_ids[] = { {"", 0}, }; -/* Some BIOS do not survive early DSDT scan, skip it */ -static int ec_skip_dsdt_scan(const struct dmi_system_id *id) -{ - EC_FLAGS_SKIP_DSDT_SCAN = 1; - return 0; -} - -/* ASUStek often supplies us with broken ECDT, validate it */ -static int ec_validate_ecdt(const struct dmi_system_id *id) -{ - EC_FLAGS_VALIDATE_ECDT = 1; - return 0; -} - #if 0 /* * Some EC firmware variations refuses to respond QR_EC when SCI_EVT is not @@ -1517,30 +1503,29 @@ static int ec_clear_on_resume(const struct dmi_system_id *id) return 0; } +static int ec_correct_ecdt(const struct dmi_system_id *id) +{ + pr_debug("Detected system needing ECDT address correction.\n"); + EC_FLAGS_CORRECT_ECDT = 1; + return 0; +} + static struct dmi_system_id ec_dmi_table[] __initdata = { { - ec_skip_dsdt_scan, "Compal JFL92", { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL}, + ec_correct_ecdt, "Asus L4R", { + DMI_MATCH(DMI_BIOS_VERSION, "1008.006"), + DMI_MATCH(DMI_PRODUCT_NAME, "L4R"), + DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL}, + { + ec_correct_ecdt, "Asus M6R", { + DMI_MATCH(DMI_BIOS_VERSION, "0207"), + DMI_MATCH(DMI_PRODUCT_NAME, "M6R"), + DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL}, { - ec_validate_ecdt, "MSI MS-171F", { + ec_correct_ecdt, "MSI MS-171F", { DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"), DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL}, { - ec_validate_ecdt, "ASUS hardware", { - DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, - { - ec_validate_ecdt, "ASUS hardware", { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL}, - { - ec_skip_dsdt_scan, "HP Folio 13", { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL}, - { - ec_validate_ecdt, "ASUS hardware", { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL}, - { ec_clear_on_resume, "Samsung hardware", { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, {}, @@ -1548,8 +1533,8 @@ static struct dmi_system_id ec_dmi_table[] __initdata = { int __init acpi_ec_ecdt_probe(void) { + int ret = 0; acpi_status status; - struct acpi_ec *saved_ec = NULL; struct acpi_table_ecdt *ecdt_ptr; boot_ec = make_acpi_ec(); @@ -1561,67 +1546,45 @@ int __init acpi_ec_ecdt_probe(void) dmi_check_system(ec_dmi_table); status = acpi_get_table(ACPI_SIG_ECDT, 1, (struct acpi_table_header **)&ecdt_ptr); - if (ACPI_SUCCESS(status)) { - pr_info("EC description table is found, configuring boot EC\n"); - boot_ec->command_addr = ecdt_ptr->control.address; - boot_ec->data_addr = ecdt_ptr->data.address; - boot_ec->gpe = ecdt_ptr->gpe; - boot_ec->handle = ACPI_ROOT_OBJECT; - acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, - &boot_ec->handle); - /* Don't trust ECDT, which comes from ASUSTek */ - if (!EC_FLAGS_VALIDATE_ECDT) - goto install; - saved_ec = kmemdup(boot_ec, sizeof(struct acpi_ec), GFP_KERNEL); - if (!saved_ec) - return -ENOMEM; - /* fall through */ + if (ACPI_FAILURE(status)) { + ret = -ENODEV; + goto error; } - if (EC_FLAGS_SKIP_DSDT_SCAN) { - kfree(saved_ec); - return -ENODEV; + if (!ecdt_ptr->control.address || !ecdt_ptr->data.address) { + /* + * Asus X50GL: + * https://bugzilla.kernel.org/show_bug.cgi?id=11880 + */ + ret = -ENODEV; + goto error; } - /* This workaround is needed only on some broken machines, - * which require early EC, but fail to provide ECDT */ - pr_debug("Look up EC in DSDT\n"); - status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, - boot_ec, NULL); - /* Check that acpi_get_devices actually find something */ - if (ACPI_FAILURE(status) || !boot_ec->handle) - goto error; - if (saved_ec) { - /* try to find good ECDT from ASUSTek */ - if (saved_ec->command_addr != boot_ec->command_addr || - saved_ec->data_addr != boot_ec->data_addr || - saved_ec->gpe != boot_ec->gpe || - saved_ec->handle != boot_ec->handle) - pr_info("ASUSTek keeps feeding us with broken " - "ECDT tables, which are very hard to workaround. " - "Trying to use DSDT EC info instead. Please send " - "output of acpidump to linux-acpi@vger.kernel.org\n"); - kfree(saved_ec); - saved_ec = NULL; + pr_info("EC description table is found, configuring boot EC\n"); + if (EC_FLAGS_CORRECT_ECDT) { + /* + * Asus L4R, Asus M6R + * https://bugzilla.kernel.org/show_bug.cgi?id=9399 + * MSI MS-171F + * https://bugzilla.kernel.org/show_bug.cgi?id=12461 + */ + boot_ec->command_addr = ecdt_ptr->data.address; + boot_ec->data_addr = ecdt_ptr->control.address; } else { - /* We really need to limit this workaround, the only ASUS, - * which needs it, has fake EC._INI method, so use it as flag. - * Keep boot_ec struct as it will be needed soon. - */ - if (!dmi_name_in_vendors("ASUS") || - !acpi_has_method(boot_ec->handle, "_INI")) - return -ENODEV; + boot_ec->command_addr = ecdt_ptr->control.address; + boot_ec->data_addr = ecdt_ptr->data.address; } -install: - if (!ec_install_handlers(boot_ec)) { + boot_ec->gpe = ecdt_ptr->gpe; + boot_ec->handle = ACPI_ROOT_OBJECT; + ret = ec_install_handlers(boot_ec); + if (!ret) first_ec = boot_ec; - return 0; - } error: - kfree(boot_ec); - kfree(saved_ec); - boot_ec = NULL; - return -ENODEV; + if (ret) { + kfree(boot_ec); + boot_ec = NULL; + } + return ret; } static int param_set_event_clearing(const char *val, struct kernel_param *kp) -- GitLab From fe6cbea0f096bfdb7eafdc7b937570cea8fca00e Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 10:43:00 +0800 Subject: [PATCH 1891/9938] ACPI 2.0 / ECDT: Enable correct ECDT initialization order With wrong ECDT fixes reverted, it is possible to put ECDT probing before acpi_enable_subsystem(). But the ultimate purpose of ECDT re-enabling is to put the ECDT probing before the namespace initialization (acpi_load_tables()). This patch achieves this with protections so that we can enable it later when all necessary corrections are upstreamed. Link 4: https://bugzilla.kernel.org/show_bug.cgi?id=112911 Signed-off-by: Lv Zheng Tested-by: Chris Bainbridge Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c068c829b453..31e8da648fff 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -925,11 +925,13 @@ void __init acpi_early_init(void) goto error0; } - status = acpi_load_tables(); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to load the System Description Tables\n"); - goto error0; + if (acpi_gbl_group_module_level_code) { + status = acpi_load_tables(); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX + "Unable to load the System Description Tables\n"); + goto error0; + } } #ifdef CONFIG_X86 @@ -995,17 +997,10 @@ static int __init acpi_bus_init(void) acpi_os_initialize1(); - status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to start the ACPI Interpreter\n"); - goto error1; - } - /* * ACPI 2.0 requires the EC driver to be loaded and work before - * the EC device is found in the namespace (i.e. before acpi_initialize_objects() - * is called). + * the EC device is found in the namespace (i.e. before + * acpi_load_tables() is called). * * This is accomplished by looking for the ECDT table, and getting * the EC parameters out of that. @@ -1013,6 +1008,22 @@ static int __init acpi_bus_init(void) status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ + if (!acpi_gbl_group_module_level_code) { + status = acpi_load_tables(); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX + "Unable to load the System Description Tables\n"); + goto error1; + } + } + + status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX + "Unable to start the ACPI Interpreter\n"); + goto error1; + } + status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); -- GitLab From 3d4b7ae96d81dc8ed4ecd556118b632c2707ff08 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 10:43:08 +0800 Subject: [PATCH 1892/9938] ACPI 2.0 / AML: Improve module level execution by moving the If/Else/While execution to per-table basis This experiment moves module level If/Else/While executions to per-table basis. If regressions are found against the enabling of this experimental improvement, this patch is the only one that should get bisected out. Please report the regressions to the kernel bugzilla for further root causing. Link: https://bugzilla.kernel.org/show_bug.cgi?id=112911 Signed-off-by: Lv Zheng Tested-by: Chris Bainbridge Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 17556979dc79..3d910e5e05f2 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -192,7 +192,7 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE); /* * Optionally support group module level code. */ -ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, TRUE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, FALSE); /* * Optionally use 32-bit FADT addresses if and when there is a conflict -- GitLab From 60438d9a1ef4176d79739efadee122afe92904b8 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Thu, 24 Mar 2016 13:01:28 +0800 Subject: [PATCH 1893/9938] tools/power/acpi: close file only if it is open The logic on the test for a valid fd to close is incorrect. This was just a mistake and was pointed out by Colin Ian King. Link: https://patchwork.kernel.org/patch/8620201/ Original-by: Colin Ian King Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- tools/power/acpi/tools/acpidbg/acpidbg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/power/acpi/tools/acpidbg/acpidbg.c b/tools/power/acpi/tools/acpidbg/acpidbg.c index d070fccdba6d..a88ac45b7756 100644 --- a/tools/power/acpi/tools/acpidbg/acpidbg.c +++ b/tools/power/acpi/tools/acpidbg/acpidbg.c @@ -375,7 +375,7 @@ void usage(FILE *file, char *progname) int main(int argc, char **argv) { - int fd = 0; + int fd = -1; int ch; int len; int ret = EXIT_SUCCESS; @@ -430,7 +430,7 @@ int main(int argc, char **argv) acpi_aml_loop(fd); exit: - if (fd < 0) + if (fd >= 0) close(fd); if (acpi_aml_batch_cmd) free(acpi_aml_batch_cmd); -- GitLab From f4d05266032346531b9f889e26aa31a0cf2a9822 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Tue, 29 Mar 2016 14:52:23 +0300 Subject: [PATCH 1894/9938] device property: don't bother the drivers with struct property_set Since device_add_property_set() now always takes a copy of the property_set, and also since the fwnode type is always hard coded to be FWNODE_PDATA, there is no need for the drivers to deliver the entire struct property_set. The function can just create the instance of it on its own and bind the properties from the drivers to it on the spot. This renames device_add_property_set() to device_add_properties(). The function now takes struct property_entry as its parameter instead of struct property_set. Reviewed-by: Andy Shevchenko Reviewed-by: Mika Westerberg Acked-by: Thierry Reding Acked-by: Lee Jones Signed-off-by: Heikki Krogerus Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-pxa/raumfeld.c | 12 ++++------- arch/arm/mach-tegra/board-paz00.c | 6 +----- drivers/base/platform.c | 19 +++++++++-------- drivers/base/property.c | 34 +++++++++++++++++++------------ drivers/mfd/intel-lpss-acpi.c | 12 ++--------- drivers/mfd/intel-lpss-pci.c | 20 ++++-------------- drivers/mfd/intel-lpss.c | 2 +- drivers/mfd/intel-lpss.h | 4 ++-- drivers/mfd/mfd-core.c | 4 ++-- include/linux/mfd/core.h | 4 ++-- include/linux/platform_device.h | 6 +++--- include/linux/property.h | 15 +++----------- 12 files changed, 55 insertions(+), 83 deletions(-) diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 5a941bd3dbed..e216433b56ed 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -385,10 +385,6 @@ static struct property_entry raumfeld_rotary_properties[] = { { }, }; -static struct property_set raumfeld_rotary_property_set = { - .properties = raumfeld_rotary_properties, -}; - static struct platform_device rotary_encoder_device = { .name = "rotary-encoder", .id = 0, @@ -1063,8 +1059,8 @@ static void __init __maybe_unused raumfeld_controller_init(void) pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_controller_pin_config)); gpiod_add_lookup_table(&raumfeld_rotary_gpios_table); - device_add_property_set(&rotary_encoder_device.dev, - &raumfeld_rotary_property_set); + device_add_properties(&rotary_encoder_device.dev, + raumfeld_rotary_properties); platform_device_register(&rotary_encoder_device); spi_register_board_info(ARRAY_AND_SIZE(controller_spi_devices)); @@ -1103,8 +1099,8 @@ static void __init __maybe_unused raumfeld_speaker_init(void) platform_device_register(&smc91x_device); gpiod_add_lookup_table(&raumfeld_rotary_gpios_table); - device_add_property_set(&rotary_encoder_device.dev, - &raumfeld_rotary_property_set); + device_add_properties(&rotary_encoder_device.dev, + raumfeld_rotary_properties); platform_device_register(&rotary_encoder_device); raumfeld_audio_init(); diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index 52db8bf7e153..7478f6fb3664 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c @@ -29,10 +29,6 @@ static struct property_entry __initdata wifi_rfkill_prop[] = { { }, }; -static struct property_set __initdata wifi_rfkill_pset = { - .properties = wifi_rfkill_prop, -}; - static struct platform_device wifi_rfkill_device = { .name = "rfkill_gpio", .id = -1, @@ -49,7 +45,7 @@ static struct gpiod_lookup_table wifi_gpio_lookup = { void __init tegra_paz00_wifikill_init(void) { - platform_device_add_properties(&wifi_rfkill_device, &wifi_rfkill_pset); + platform_device_add_properties(&wifi_rfkill_device, wifi_rfkill_prop); gpiod_add_lookup_table(&wifi_gpio_lookup); platform_device_register(&wifi_rfkill_device); } diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f437afa17f2b..6482d47deb50 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -322,16 +322,16 @@ EXPORT_SYMBOL_GPL(platform_device_add_data); /** * platform_device_add_properties - add built-in properties to a platform device * @pdev: platform device to add properties to - * @pset: properties to add + * @properties: null terminated array of properties to add * - * The function will take deep copy of the properties in @pset and attach - * the copy to the platform device. The memory associated with properties - * will be freed when the platform device is released. + * The function will take deep copy of @properties and attach the copy to the + * platform device. The memory associated with properties will be freed when the + * platform device is released. */ int platform_device_add_properties(struct platform_device *pdev, - const struct property_set *pset) + struct property_entry *properties) { - return device_add_property_set(&pdev->dev, pset); + return device_add_properties(&pdev->dev, properties); } EXPORT_SYMBOL_GPL(platform_device_add_properties); @@ -447,7 +447,7 @@ void platform_device_del(struct platform_device *pdev) release_resource(r); } - device_remove_property_set(&pdev->dev); + device_remove_properties(&pdev->dev); } } EXPORT_SYMBOL_GPL(platform_device_del); @@ -526,8 +526,9 @@ struct platform_device *platform_device_register_full( if (ret) goto err; - if (pdevinfo->pset) { - ret = platform_device_add_properties(pdev, pdevinfo->pset); + if (pdevinfo->properties) { + ret = platform_device_add_properties(pdev, + pdevinfo->properties); if (ret) goto err; } diff --git a/drivers/base/property.c b/drivers/base/property.c index 9b1a65debd49..210423d00d78 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -19,6 +19,11 @@ #include #include +struct property_set { + struct fwnode_handle fwnode; + struct property_entry *properties; +}; + static inline bool is_pset_node(struct fwnode_handle *fwnode) { return fwnode && fwnode->type == FWNODE_PDATA; @@ -801,14 +806,14 @@ static struct property_set *pset_copy_set(const struct property_set *pset) } /** - * device_remove_property_set - Remove properties from a device object. + * device_remove_properties - Remove properties from a device object. * @dev: Device whose properties to remove. * * The function removes properties previously associated to the device - * secondary firmware node with device_add_property_set(). Memory allocated + * secondary firmware node with device_add_properties(). Memory allocated * to the properties will also be released. */ -void device_remove_property_set(struct device *dev) +void device_remove_properties(struct device *dev) { struct fwnode_handle *fwnode; @@ -831,24 +836,27 @@ void device_remove_property_set(struct device *dev) } } } -EXPORT_SYMBOL_GPL(device_remove_property_set); +EXPORT_SYMBOL_GPL(device_remove_properties); /** - * device_add_property_set - Add a collection of properties to a device object. + * device_add_properties - Add a collection of properties to a device object. * @dev: Device to add properties to. - * @pset: Collection of properties to add. + * @properties: Collection of properties to add. * - * Associate a collection of device properties represented by @pset with @dev - * as its secondary firmware node. The function takes a copy of @pset. + * Associate a collection of device properties represented by @properties with + * @dev as its secondary firmware node. The function takes a copy of + * @properties. */ -int device_add_property_set(struct device *dev, const struct property_set *pset) +int device_add_properties(struct device *dev, struct property_entry *properties) { - struct property_set *p; + struct property_set *p, pset; - if (!pset) + if (!properties) return -EINVAL; - p = pset_copy_set(pset); + pset.properties = properties; + + p = pset_copy_set(&pset); if (IS_ERR(p)) return PTR_ERR(p); @@ -856,7 +864,7 @@ int device_add_property_set(struct device *dev, const struct property_set *pset) set_secondary_fwnode(dev, &p->fwnode); return 0; } -EXPORT_SYMBOL_GPL(device_add_property_set); +EXPORT_SYMBOL_GPL(device_add_properties); /** * device_get_next_child_node - Return the next child node handle for a device diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c index 5a8d9c766633..7ddc4a9563ea 100644 --- a/drivers/mfd/intel-lpss-acpi.c +++ b/drivers/mfd/intel-lpss-acpi.c @@ -31,13 +31,9 @@ static struct property_entry spt_i2c_properties[] = { { }, }; -static struct property_set spt_i2c_pset = { - .properties = spt_i2c_properties, -}; - static const struct intel_lpss_platform_info spt_i2c_info = { .clk_rate = 120000000, - .pset = &spt_i2c_pset, + .properties = spt_i2c_properties, }; static const struct intel_lpss_platform_info bxt_info = { @@ -51,13 +47,9 @@ static struct property_entry bxt_i2c_properties[] = { { }, }; -static struct property_set bxt_i2c_pset = { - .properties = bxt_i2c_properties, -}; - static const struct intel_lpss_platform_info bxt_i2c_info = { .clk_rate = 133000000, - .pset = &bxt_i2c_pset, + .properties = bxt_i2c_properties, }; static const struct acpi_device_id intel_lpss_acpi_ids[] = { diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index a19e57118641..1d79a3c9370f 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -71,13 +71,9 @@ static struct property_entry spt_i2c_properties[] = { { }, }; -static struct property_set spt_i2c_pset = { - .properties = spt_i2c_properties, -}; - static const struct intel_lpss_platform_info spt_i2c_info = { .clk_rate = 120000000, - .pset = &spt_i2c_pset, + .properties = spt_i2c_properties, }; static struct property_entry uart_properties[] = { @@ -87,14 +83,10 @@ static struct property_entry uart_properties[] = { { }, }; -static struct property_set uart_pset = { - .properties = uart_properties, -}; - static const struct intel_lpss_platform_info spt_uart_info = { .clk_rate = 120000000, .clk_con_id = "baudclk", - .pset = &uart_pset, + .properties = uart_properties, }; static const struct intel_lpss_platform_info bxt_info = { @@ -104,7 +96,7 @@ static const struct intel_lpss_platform_info bxt_info = { static const struct intel_lpss_platform_info bxt_uart_info = { .clk_rate = 100000000, .clk_con_id = "baudclk", - .pset = &uart_pset, + .properties = uart_properties, }; static struct property_entry bxt_i2c_properties[] = { @@ -114,13 +106,9 @@ static struct property_entry bxt_i2c_properties[] = { { }, }; -static struct property_set bxt_i2c_pset = { - .properties = bxt_i2c_properties, -}; - static const struct intel_lpss_platform_info bxt_i2c_info = { .clk_rate = 133000000, - .pset = &bxt_i2c_pset, + .properties = bxt_i2c_properties, }; static const struct pci_device_id intel_lpss_pci_ids[] = { diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 1bbbe877ba7e..6352aaba96a4 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -407,7 +407,7 @@ int intel_lpss_probe(struct device *dev, if (ret) return ret; - lpss->cell->pset = info->pset; + lpss->cell->properties = info->properties; intel_lpss_init_dev(lpss); diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h index 0dcea9eb2d03..694116630ffa 100644 --- a/drivers/mfd/intel-lpss.h +++ b/drivers/mfd/intel-lpss.h @@ -16,14 +16,14 @@ struct device; struct resource; -struct property_set; +struct property_entry; struct intel_lpss_platform_info { struct resource *mem; int irq; unsigned long clk_rate; const char *clk_con_id; - struct property_set *pset; + struct property_entry *properties; }; int intel_lpss_probe(struct device *dev, diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 88bd1b1e47be..fc1c1fc13813 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -193,8 +193,8 @@ static int mfd_add_device(struct device *parent, int id, goto fail_alias; } - if (cell->pset) { - ret = platform_device_add_properties(pdev, cell->pset); + if (cell->properties) { + ret = platform_device_add_properties(pdev, cell->properties); if (ret) goto fail_alias; } diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index bc6f7e00fb3d..9837f1e8c94c 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -17,7 +17,7 @@ #include struct irq_domain; -struct property_set; +struct property_entry; /* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */ struct mfd_cell_acpi_match { @@ -47,7 +47,7 @@ struct mfd_cell { size_t pdata_size; /* device properties passed to the sub devices drivers */ - const struct property_set *pset; + struct property_entry *properties; /* * Device Tree compatible string diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 03b755521fd9..98c2a7c7108e 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -18,7 +18,7 @@ #define PLATFORM_DEVID_AUTO (-2) struct mfd_cell; -struct property_set; +struct property_entry; struct platform_device { const char *name; @@ -73,7 +73,7 @@ struct platform_device_info { size_t size_data; u64 dma_mask; - const struct property_set *pset; + struct property_entry *properties; }; extern struct platform_device *platform_device_register_full( const struct platform_device_info *pdevinfo); @@ -172,7 +172,7 @@ extern int platform_device_add_resources(struct platform_device *pdev, extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); extern int platform_device_add_properties(struct platform_device *pdev, - const struct property_set *pset); + struct property_entry *properties); extern int platform_device_add(struct platform_device *pdev); extern void platform_device_del(struct platform_device *pdev); extern void platform_device_put(struct platform_device *pdev); diff --git a/include/linux/property.h b/include/linux/property.h index b51fcd36d892..ecab11e40794 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -238,18 +238,9 @@ struct property_entry { .name = _name_, \ } -/** - * struct property_set - Collection of "built-in" device properties. - * @fwnode: Handle to be pointed to by the fwnode field of struct device. - * @properties: Array of properties terminated with a null entry. - */ -struct property_set { - struct fwnode_handle fwnode; - struct property_entry *properties; -}; - -int device_add_property_set(struct device *dev, const struct property_set *pset); -void device_remove_property_set(struct device *dev); +int device_add_properties(struct device *dev, + struct property_entry *properties); +void device_remove_properties(struct device *dev); bool device_dma_supported(struct device *dev); -- GitLab From c68ae33e7fb4a010f9a48af3e4b87089dca96551 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Thu, 24 Mar 2016 13:15:20 +0100 Subject: [PATCH 1895/9938] ACPI / utils: Rename acpi_dev_present() acpi_dev_present() was originally named after pci_dev_present() to signify the similarity of the two functions. However Rafael J. Wysocki pointed out that the exported function acpi_dev_present() is easily confused with the non-exported acpi_device_is_present(). Additionally in ACPI parlance the term "present" usually refers to the "device is present" bit returned by the _STA control method, yet acpi_dev_present() merely checks presence in the namespace. It does not invoke _STA at all, let alone check the "device is present" bit. As suggested by Rafael, rename the function to acpi_dev_found() and adjust all existing call sites. Signed-off-by: Lukas Wunner Signed-off-by: Rafael J. Wysocki --- drivers/acpi/utils.c | 6 +++--- include/acpi/acpi_bus.h | 2 +- include/linux/apple-gmux.h | 2 +- sound/pci/hda/thinkpad_helper.c | 2 +- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 2 +- sound/soc/intel/boards/cht_bsw_rt5645.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 050673f0c0b3..ac832bf6f8c9 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -707,7 +707,7 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) EXPORT_SYMBOL(acpi_check_dsm); /** - * acpi_dev_present - Detect presence of a given ACPI device in the system. + * acpi_dev_found - Detect presence of a given ACPI device in the namespace. * @hid: Hardware ID of the device. * * Return %true if the device was present at the moment of invocation. @@ -719,7 +719,7 @@ EXPORT_SYMBOL(acpi_check_dsm); * instead). Calling from module_init() is fine (which is synonymous * with device_initcall()). */ -bool acpi_dev_present(const char *hid) +bool acpi_dev_found(const char *hid) { struct acpi_device_bus_id *acpi_device_bus_id; bool found = false; @@ -734,7 +734,7 @@ bool acpi_dev_present(const char *hid) return found; } -EXPORT_SYMBOL(acpi_dev_present); +EXPORT_SYMBOL(acpi_dev_found); /* * acpi_backlight= handling, this is done here rather then in video_detect.c diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 14362a84c78e..a84fd1533e24 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -87,7 +87,7 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, .package.elements = (eles) \ } -bool acpi_dev_present(const char *hid); +bool acpi_dev_found(const char *hid); #ifdef CONFIG_ACPI diff --git a/include/linux/apple-gmux.h b/include/linux/apple-gmux.h index b2d32e01dfe4..714186de8c36 100644 --- a/include/linux/apple-gmux.h +++ b/include/linux/apple-gmux.h @@ -35,7 +35,7 @@ */ static inline bool apple_gmux_present(void) { - return acpi_dev_present(GMUX_ACPI_HID); + return acpi_dev_found(GMUX_ACPI_HID); } #else /* !CONFIG_APPLE_GMUX */ diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c index 59ab6cee1ad8..f0955fd7a2e7 100644 --- a/sound/pci/hda/thinkpad_helper.c +++ b/sound/pci/hda/thinkpad_helper.c @@ -13,7 +13,7 @@ static void (*old_vmaster_hook)(void *, int); static bool is_thinkpad(struct hda_codec *codec) { return (codec->core.subsystem_id >> 16 == 0x17aa) && - (acpi_dev_present("LEN0068") || acpi_dev_present("IBM0068")); + (acpi_dev_found("LEN0068") || acpi_dev_found("IBM0068")); } static void update_tpacpi_mute_led(void *private_data, int enabled) diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index e609f089593a..ac60b04540fd 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -296,7 +296,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) if (!drv) return -ENOMEM; - drv->ts3a227e_present = acpi_dev_present("104C227E"); + drv->ts3a227e_present = acpi_dev_found("104C227E"); if (!drv->ts3a227e_present) { /* no need probe TI jack detection chip */ snd_soc_card_cht.aux_dev = NULL; diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 2a6f80843bc9..3f2c1ea3a83e 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -357,7 +357,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { - if (acpi_dev_present(snd_soc_cards[i].codec_id)) { + if (acpi_dev_found(snd_soc_cards[i].codec_id)) { dev_dbg(&pdev->dev, "found codec %s\n", snd_soc_cards[i].codec_id); card = snd_soc_cards[i].soc_card; -- GitLab From 9f9de69d754cc9f8f2d8c21bb92275d95ddb3c77 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Thu, 24 Mar 2016 13:15:20 +0100 Subject: [PATCH 1896/9938] eeepc-wmi: Use acpi_dev_found() Use shiny new acpi_dev_found() and remove all the boilerplate to search for a particular ACPI device. No functional change. Signed-off-by: Lukas Wunner Acked-by: Darren Hart Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/eeepc-wmi.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 14fd2ecb06a1..17b365f26f9d 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -204,30 +204,10 @@ static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code, } } -static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level, - void *context, void **retval) -{ - pr_warn("Found legacy ATKD device (%s)\n", EEEPC_ACPI_HID); - *(bool *)context = true; - return AE_CTRL_TERMINATE; -} - -static int eeepc_wmi_check_atkd(void) -{ - acpi_status status; - bool found = false; - - status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device, - &found, NULL); - - if (ACPI_FAILURE(status) || !found) - return 0; - return -1; -} - static int eeepc_wmi_probe(struct platform_device *pdev) { - if (eeepc_wmi_check_atkd()) { + if (acpi_dev_found(EEEPC_ACPI_HID)) { + pr_warn("Found legacy ATKD device (%s)\n", EEEPC_ACPI_HID); pr_warn("WMI device present, but legacy ATKD device is also " "present and enabled\n"); pr_warn("You probably booted with acpi_osi=\"Linux\" or " -- GitLab From 8c92a75e5086e85000deeb05f6f852446c8f758a Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Thu, 24 Mar 2016 13:15:20 +0100 Subject: [PATCH 1897/9938] acer-wmi: Use acpi_dev_found() Use shiny new acpi_dev_found() and remove all the boilerplate to search for a particular ACPI device. No functional change. Signed-off-by: Lukas Wunner Reviewed-by: Lee, Chun-Yi Acked-by: Darren Hart Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/acer-wmi.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 1062fa42ff26..79d64ea00bfb 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -793,15 +793,6 @@ static acpi_status __init AMW0_find_mailled(void) return AE_OK; } -static int AMW0_set_cap_acpi_check_device_found __initdata; - -static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, - u32 level, void *context, void **retval) -{ - AMW0_set_cap_acpi_check_device_found = 1; - return AE_OK; -} - static const struct acpi_device_id norfkill_ids[] __initconst = { { "VPC2004", 0}, { "IBM0068", 0}, @@ -816,9 +807,10 @@ static int __init AMW0_set_cap_acpi_check_device(void) const struct acpi_device_id *id; for (id = norfkill_ids; id->id[0]; id++) - acpi_get_devices(id->id, AMW0_set_cap_acpi_check_device_cb, - NULL, NULL); - return AMW0_set_cap_acpi_check_device_found; + if (acpi_dev_found(id->id)) + return true; + + return false; } static acpi_status __init AMW0_set_capabilities(void) -- GitLab From 498cd8e49509c761b39dab26be7f739d95940e16 Mon Sep 17 00:00:00 2001 From: John Allen Date: Wed, 6 Apr 2016 11:49:55 -0500 Subject: [PATCH 1898/9938] ibmvnic: Enable use of multiple tx/rx scrqs Enables the use of multiple transmit and receive scrqs allowing the ibmvnic driver to take advantage of multiqueue functionality. To achieve this, the driver must implement the process of negotiating the maximum number of queues allowed by the server. Initially, the driver will attempt to login with the maximum number of tx and rx queues supported by the server. If the server fails to allocate the requested number of scrqs, it will return partial success in the login response. In this case, we must reinitiate the login process from the request capabilities stage and attempt to login requesting fewer scrqs. Signed-off-by: John Allen Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 56 +++++++++++++++++++----------- drivers/net/ethernet/ibm/ibmvnic.h | 1 + 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 21bccf6eb919..864cb21351a4 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -800,11 +800,12 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) ret = NETDEV_TX_BUSY; goto out; } - lpar_rc = send_subcrq_indirect(adapter, handle_array[0], + lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num], (u64)tx_buff->indir_dma, (u64)num_entries); } else { - lpar_rc = send_subcrq(adapter, handle_array[0], &tx_crq); + lpar_rc = send_subcrq(adapter, handle_array[queue_num], + &tx_crq); } if (lpar_rc != H_SUCCESS) { dev_err(dev, "tx failed with code %ld\n", lpar_rc); @@ -989,7 +990,7 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget) netdev->stats.rx_bytes += length; frames_processed++; } - replenish_pools(adapter); + replenish_rx_pool(adapter, &adapter->rx_pool[scrq_num]); if (frames_processed < budget) { enable_scrq_irq(adapter, adapter->rx_scrq[scrq_num]); @@ -1426,9 +1427,9 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry) entries_page : adapter->max_rx_add_entries_per_subcrq; /* Choosing the maximum number of queues supported by firmware*/ - adapter->req_tx_queues = adapter->min_tx_queues; - adapter->req_rx_queues = adapter->min_rx_queues; - adapter->req_rx_add_queues = adapter->min_rx_add_queues; + adapter->req_tx_queues = adapter->max_tx_queues; + adapter->req_rx_queues = adapter->max_rx_queues; + adapter->req_rx_add_queues = adapter->max_rx_add_queues; adapter->req_mtu = adapter->max_mtu; } @@ -1776,13 +1777,11 @@ static void send_login(struct ibmvnic_adapter *adapter) goto buf_map_failed; } - rsp_buffer_size = - sizeof(struct ibmvnic_login_rsp_buffer) + - sizeof(u64) * (adapter->req_tx_queues + - adapter->req_rx_queues * - adapter->req_rx_add_queues + adapter-> - req_rx_add_queues) + - sizeof(u8) * (IBMVNIC_TX_DESC_VERSIONS); + rsp_buffer_size = sizeof(struct ibmvnic_login_rsp_buffer) + + sizeof(u64) * adapter->req_tx_queues + + sizeof(u64) * adapter->req_rx_queues + + sizeof(u64) * adapter->req_rx_queues + + sizeof(u8) * IBMVNIC_TX_DESC_VERSIONS; login_rsp_buffer = kmalloc(rsp_buffer_size, GFP_ATOMIC); if (!login_rsp_buffer) @@ -2401,6 +2400,16 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, dma_unmap_single(dev, adapter->login_rsp_buf_token, adapter->login_rsp_buf_sz, DMA_BIDIRECTIONAL); + /* If the number of queues requested can't be allocated by the + * server, the login response will return with code 1. We will need + * to resend the login buffer with fewer queues requested. + */ + if (login_rsp_crq->generic.rc.code) { + adapter->renegotiate = true; + complete(&adapter->init_done); + return 0; + } + netdev_dbg(adapter->netdev, "Login Response Buffer:\n"); for (i = 0; i < (adapter->login_rsp_buf_sz - 1) / 8 + 1; i++) { netdev_dbg(adapter->netdev, "%016lx\n", @@ -3628,14 +3637,21 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) init_completion(&adapter->init_done); wait_for_completion(&adapter->init_done); - /* needed to pull init_sub_crqs outside of an interrupt context - * because it creates IRQ mappings for the subCRQ queues, causing - * a kernel warning - */ - init_sub_crqs(adapter, 0); + do { + adapter->renegotiate = false; - reinit_completion(&adapter->init_done); - wait_for_completion(&adapter->init_done); + init_sub_crqs(adapter, 0); + reinit_completion(&adapter->init_done); + wait_for_completion(&adapter->init_done); + + if (adapter->renegotiate) { + release_sub_crqs(adapter); + send_cap_queries(adapter); + + reinit_completion(&adapter->init_done); + wait_for_completion(&adapter->init_done); + } + } while (adapter->renegotiate); /* if init_sub_crqs is partially successful, retry */ while (!adapter->tx_scrq || !adapter->rx_scrq) { diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 5af8a796e523..0b66a506a4e4 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -980,6 +980,7 @@ struct ibmvnic_adapter { struct ibmvnic_sub_crq_queue **tx_scrq; struct ibmvnic_sub_crq_queue **rx_scrq; int requested_caps; + bool renegotiate; /* rx structs */ struct napi_struct *napi; -- GitLab From 5305239312a5fcc50849e157a3178778c6914aa0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 9 Apr 2016 10:36:15 +0200 Subject: [PATCH 1899/9938] ALSA: constify ct_timer_ops structures The ct_timer_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/pci/ctxfi/cttimer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/ctxfi/cttimer.c b/sound/pci/ctxfi/cttimer.c index a5d460453d7b..8f945341720b 100644 --- a/sound/pci/ctxfi/cttimer.c +++ b/sound/pci/ctxfi/cttimer.c @@ -49,7 +49,7 @@ struct ct_timer { spinlock_t lock; /* global timer lock (for xfitimer) */ spinlock_t list_lock; /* lock for instance list */ struct ct_atc *atc; - struct ct_timer_ops *ops; + const struct ct_timer_ops *ops; struct list_head instance_head; struct list_head running_head; unsigned int wc; /* current wallclock */ @@ -128,7 +128,7 @@ static void ct_systimer_prepare(struct ct_timer_instance *ti) #define ct_systimer_free ct_systimer_prepare -static struct ct_timer_ops ct_systimer_ops = { +static const struct ct_timer_ops ct_systimer_ops = { .init = ct_systimer_init, .free_instance = ct_systimer_free, .prepare = ct_systimer_prepare, @@ -322,7 +322,7 @@ static void ct_xfitimer_free_global(struct ct_timer *atimer) ct_xfitimer_irq_stop(atimer); } -static struct ct_timer_ops ct_xfitimer_ops = { +static const struct ct_timer_ops ct_xfitimer_ops = { .prepare = ct_xfitimer_prepare, .start = ct_xfitimer_start, .stop = ct_xfitimer_stop, -- GitLab From cddaafb9a4a7b6d19030d2632107ba2aa068474d Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Sat, 9 Apr 2016 11:21:46 +0200 Subject: [PATCH 1900/9938] ALSA: usb-audio: add UAC2 clock sources as mixer controls UAC2 specifies clock sources that optionally have validity controls. This patch exposes them as mixer controls, so they can be read (and at least in theory even be written) by userspace applications in order to make clock selection policy decisions. This implementation does nothing if the device is not UAC2 compliant, or if the clock source does not define said validity control bits. Tested with a miniDSP USBStreamer (0x2752/0x0016). Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 4f85757009b3..cab6f5227971 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -1378,6 +1379,71 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, snd_usb_mixer_add_control(&cval->head, kctl); } +static int parse_clock_source_unit(struct mixer_build *state, int unitid, + void *_ftr) +{ + struct uac_clock_source_descriptor *hdr = _ftr; + struct usb_mixer_elem_info *cval; + struct snd_kcontrol *kctl; + char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + int ret; + + if (state->mixer->protocol != UAC_VERSION_2) + return -EINVAL; + + if (hdr->bLength != sizeof(*hdr)) { + usb_audio_dbg(state->chip, + "Bogus clock source descriptor length of %d, ignoring.\n", + hdr->bLength); + return 0; + } + + /* + * The only property of this unit we are interested in is the + * clock source validity. If that isn't readable, just bail out. + */ + if (!uac2_control_is_readable(hdr->bmControls, + ilog2(UAC2_CS_CONTROL_CLOCK_VALID))) + return 0; + + cval = kzalloc(sizeof(*cval), GFP_KERNEL); + if (!cval) + return -ENOMEM; + + snd_usb_mixer_elem_init_std(&cval->head, state->mixer, hdr->bClockID); + + cval->min = 0; + cval->max = 1; + cval->channels = 1; + cval->val_type = USB_MIXER_BOOLEAN; + cval->control = UAC2_CS_CONTROL_CLOCK_VALID; + + if (uac2_control_is_writeable(hdr->bmControls, + ilog2(UAC2_CS_CONTROL_CLOCK_VALID))) + kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); + else { + cval->master_readonly = 1; + kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); + } + + if (!kctl) { + kfree(cval); + return -ENOMEM; + } + + kctl->private_free = snd_usb_mixer_elem_free; + ret = snd_usb_copy_string_desc(state, hdr->iClockSource, + name, sizeof(name)); + if (ret > 0) + snprintf(kctl->id.name, sizeof(kctl->id.name), + "%s Validity", name); + else + snprintf(kctl->id.name, sizeof(kctl->id.name), + "Clock Source %d Validity", hdr->bClockID); + + return snd_usb_mixer_add_control(&cval->head, kctl); +} + /* * parse a feature unit * @@ -2126,10 +2192,11 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) switch (p1[2]) { case UAC_INPUT_TERMINAL: - case UAC2_CLOCK_SOURCE: return 0; /* NOP */ case UAC_MIXER_UNIT: return parse_audio_mixer_unit(state, unitid, p1); + case UAC2_CLOCK_SOURCE: + return parse_clock_source_unit(state, unitid, p1); case UAC_SELECTOR_UNIT: case UAC2_CLOCK_SELECTOR: return parse_audio_selector_unit(state, unitid, p1); -- GitLab From 191227d99a281333b50aaf82ab4152fbfa249c19 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 8 Apr 2016 19:52:02 +0200 Subject: [PATCH 1901/9938] ALSA: usb-audio: allow clock source validity interrupts miniDSP USBStreamer UAC2 devices send clock validity changes with the control field set to zero. The current interrupt handler ignores all packets if the control field does not match the mixer element's, but it really should only do that in case that field is needed to distinguish multiple elements with the same ID. This patch implements a logic that lets notifications packets pass if the element ID is unique for a given device. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index cab6f5227971..2f8c388ef84f 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2374,6 +2374,7 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, __u8 unitid = (index >> 8) & 0xff; __u8 control = (value >> 8) & 0xff; __u8 channel = value & 0xff; + unsigned int count = 0; if (channel >= MAX_CHANNELS) { usb_audio_dbg(mixer->chip, @@ -2382,6 +2383,12 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, return; } + for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) + count++; + + if (count == 0) + return; + for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) { struct usb_mixer_elem_info *info; @@ -2389,7 +2396,7 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, continue; info = (struct usb_mixer_elem_info *)list; - if (info->control != control) + if (count > 1 && info->control != control) continue; switch (attribute) { -- GitLab From 6b5029d3ec86ee9558a1ab0b4b41a98e970e2204 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 5 Apr 2016 16:49:57 +0200 Subject: [PATCH 1902/9938] gpio: document open drain/source behaviour This has been a totally undocumented feature for years so add some generic concepts and documentation about open drain/source, include some facts on how we now support for hardware. Cc: Michael Hennerich Cc: Nicolas Saenz Julienne Cc: H. Nikolaus Schaller Signed-off-by: Linus Walleij --- Documentation/gpio/driver.txt | 89 +++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index bbeec415f406..ae6e0299b16c 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -68,6 +68,95 @@ control callbacks) if it is expected to call GPIO APIs from atomic context on -RT (inside hard IRQ handlers and similar contexts). Normally this should not be required. + +GPIOs with open drain/source support +------------------------------------ + +Open drain (CMOS) or open collector (TTL) means the line is not actively driven +high: instead you provide the drain/collector as output, so when the transistor +is not open, it will present a high-impedance (tristate) to the external rail. + + + CMOS CONFIGURATION TTL CONFIGURATION + + ||--- out +--- out + in ----|| |/ + ||--+ in ----| + | |\ + GND GND + +This configuration is normally used as a way to achieve one of two things: + +- Level-shifting: to reach a logical level higher than that of the silicon + where the output resides. + +- inverse wire-OR on an I/O line, for example a GPIO line, making it possible + for any driving stage on the line to drive it low even if any other output + to the same line is simultaneously driving it high. A special case of this + is driving the SCL and SCA lines of an I2C bus, which is by definition a + wire-OR bus. + +Both usecases require that the line be equipped with a pull-up resistor. This +resistor will make the line tend to high level unless one of the transistors on +the rail actively pulls it down. + +Integrated electronics often have an output driver stage in the form of a CMOS +"totem-pole" with one N-MOS and one P-MOS transistor where one of them drives +the line high and one of them drives the line low. This is called a push-pull +output. The "totem-pole" looks like so: + + VDD + | + OD ||--+ + +--/ ---o|| P-MOS-FET + | ||--+ +in --+ +----- out + | ||--+ + +--/ ----|| N-MOS-FET + OS ||--+ + | + GND + +You see the little "switches" named "OD" and "OS" that enable/disable the +P-MOS or N-MOS transistor right after the split of the input. As you can see, +either transistor will go totally numb if this switch is open. The totem-pole +is then halved and give high impedance instead of actively driving the line +high or low respectively. That is usually how software-controlled open +drain/source works. + +Some GPIO hardware come in open drain / open source configuration. Some are +hard-wired lines that will only support open drain or open source no matter +what: there is only one transistor there. Some are software-configurable: +by flipping a bit in a register the output can be configured as open drain +or open source, by flicking open the switches labeled "OD" and "OS" in the +drawing above. + +By disabling the P-MOS transistor, the output can be driven between GND and +high impedance (open drain), and by disabling the N-MOS transistor, the output +can be driven between VDD and high impedance (open source). In the first case, +a pull-up resistor is needed on the outgoing rail to complete the circuit, and +in the second case, a pull-down resistor is needed on the rail. + +Hardware that supports open drain or open source or both, can implement a +special callback in the gpio_chip: .set_single_ended() that takes an enum flag +telling whether to configure the line as open drain, open source or push-pull. +This will happen in response to the GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag +set in the machine file, or coming from other hardware descriptions. + +If this state can not be configured in hardware, i.e. if the GPIO hardware does +not support open drain/open source in hardware, the GPIO library will instead +use a trick: when a line is set as output, if the line is flagged as open +drain, and the output value is negative, it will be driven low as usual. But +if the output value is set to positive, it will instead *NOT* be driven high, +instead it will be switched to input, as input mode is high impedance, thus +achieveing an "open drain emulation" of sorts: electrically the behaviour will +be identical, with the exception of possible hardware glitches when switching +the mode of the line. + +For open source configuration the same principle is used, just that instead +of actively driving the line low, it is set to input. + + GPIO drivers providing IRQs --------------------------- It is custom that GPIO drivers (GPIO chips) are also providing interrupts, -- GitLab From bd37c999c7ca76afd4f28987314e98e022875dbc Mon Sep 17 00:00:00 2001 From: Kelvin Cheung Date: Wed, 6 Apr 2016 20:34:53 +0800 Subject: [PATCH 1903/9938] gpio: Loongson1: add Loongson1 GPIO driver This patch adds GPIO driver for Loongson1B. Signed-off-by: Kelvin Cheung Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-loongson1.c | 102 ++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 drivers/gpio/gpio-loongson1.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 08a93e0b35c5..37f03786b0e6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -511,6 +511,13 @@ config GPIO_ZX help Say yes here to support the GPIO device on ZTE ZX SoCs. +config GPIO_LOONGSON1 + tristate "Loongson1 GPIO support" + depends on MACH_LOONGSON32 + select GPIO_GENERIC + help + Say Y or M here to support GPIO on Loongson1 SoCs. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1e0b74f3b1ed..40ab9134a40c 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -127,3 +127,4 @@ obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o +obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c new file mode 100644 index 000000000000..10c09bdd8514 --- /dev/null +++ b/drivers/gpio/gpio-loongson1.c @@ -0,0 +1,102 @@ +/* + * GPIO Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include + +/* Loongson 1 GPIO Register Definitions */ +#define GPIO_CFG 0x0 +#define GPIO_DIR 0x10 +#define GPIO_DATA 0x20 +#define GPIO_OUTPUT 0x30 + +static void __iomem *gpio_reg_base; + +static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) | pinmask, + gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static void ls1x_gpio_free(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) & ~pinmask, + gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static int ls1x_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct gpio_chip *gc; + struct resource *res; + int ret; + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to get I/O memory\n"); + return -EINVAL; + } + + gpio_reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(gpio_reg_base)) + return PTR_ERR(gpio_reg_base); + + ret = bgpio_init(gc, dev, 4, gpio_reg_base + GPIO_DATA, + gpio_reg_base + GPIO_OUTPUT, NULL, + NULL, gpio_reg_base + GPIO_DIR, 0); + if (ret) + goto err; + + gc->owner = THIS_MODULE; + gc->request = ls1x_gpio_request; + gc->free = ls1x_gpio_free; + gc->base = pdev->id * 32; + + ret = devm_gpiochip_add_data(dev, gc, NULL); + if (ret) + goto err; + + platform_set_drvdata(pdev, gc); + dev_info(dev, "Loongson1 GPIO driver registered\n"); + + return 0; +err: + dev_err(dev, "failed to register GPIO device\n"); + return ret; +} + +static struct platform_driver ls1x_gpio_driver = { + .probe = ls1x_gpio_probe, + .driver = { + .name = "ls1x-gpio", + }, +}; + +module_platform_driver(ls1x_gpio_driver); + +MODULE_AUTHOR("Kelvin Cheung "); +MODULE_DESCRIPTION("Loongson1 GPIO driver"); +MODULE_LICENSE("GPL"); -- GitLab From 615d23f80efc60f8c5146223f305d19207c742e4 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 4 Apr 2016 23:44:06 +0530 Subject: [PATCH 1904/9938] gpio: zynq: Fix the error path pm_runtime_disable is called only in remove it is missed out in the error path. Fix the same. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 66d3d247d76d..75c6355b018d 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -713,7 +713,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) - return ret; + goto err_pm_dis; /* report a bug if gpio chip registration fails */ ret = gpiochip_add_data(chip, gpio); @@ -745,6 +745,8 @@ static int zynq_gpio_probe(struct platform_device *pdev) gpiochip_remove(chip); err_pm_put: pm_runtime_put(&pdev->dev); +err_pm_dis: + pm_runtime_disable(&pdev->dev); return ret; } -- GitLab From 44896beae605b93f2232301befccb7ef42953198 Mon Sep 17 00:00:00 2001 From: Yong Li Date: Thu, 7 Apr 2016 12:56:32 +0800 Subject: [PATCH 1905/9938] gpio: pca953x: add PCAL9535 interrupt support for Galileo Gen2 Galileo Gen2 board uses the PCAL9535 as the GPIO expansion, it is different from PCA9535 and includes interrupt mask/status registers, The current driver does not support the interrupt registers configuration, it causes some gpio pins cannot trigger interrupt events, this patch fix this issue. The original patch was submitted by Josef Ahmad http://git.yoctoproject.org/cgit/cgit.cgi/meta-intel-quark/tree/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch Signed-off-by: Yong Li Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d0d3065a7557..8d8f06dc0686 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -37,8 +37,13 @@ #define PCA957X_MSK 6 #define PCA957X_INTS 7 +#define PCAL953X_IN_LATCH 34 +#define PCAL953X_INT_MASK 37 +#define PCAL953X_INT_STAT 38 + #define PCA_GPIO_MASK 0x00FF #define PCA_INT 0x0100 +#define PCA_PCAL 0x0200 #define PCA953X_TYPE 0x1000 #define PCA957X_TYPE 0x2000 #define PCA_TYPE_MASK 0xF000 @@ -76,7 +81,7 @@ static const struct i2c_device_id pca953x_id[] = { MODULE_DEVICE_TABLE(i2c, pca953x_id); static const struct acpi_device_id pca953x_acpi_ids[] = { - { "INT3491", 16 | PCA953X_TYPE | PCA_INT, }, + { "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, { } }; MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); @@ -436,6 +441,18 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) struct pca953x_chip *chip = gpiochip_get_data(gc); u8 new_irqs; int level, i; + u8 invert_irq_mask[MAX_BANK]; + + if (chip->driver_data & PCA_PCAL) { + /* Enable latch on interrupt-enabled inputs */ + pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask); + + for (i = 0; i < NBANK(chip); i++) + invert_irq_mask[i] = ~chip->irq_mask[i]; + + /* Unmask enabled interrupts */ + pca953x_write_regs(chip, PCAL953X_INT_MASK, invert_irq_mask); + } /* Look for any newly setup interrupt */ for (i = 0; i < NBANK(chip); i++) { @@ -497,6 +514,29 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) u8 trigger[MAX_BANK]; int ret, i, offset = 0; + if (chip->driver_data & PCA_PCAL) { + /* Read the current interrupt status from the device */ + ret = pca953x_read_regs(chip, PCAL953X_INT_STAT, trigger); + if (ret) + return false; + + /* Check latched inputs and clear interrupt status */ + ret = pca953x_read_regs(chip, PCA953X_INPUT, cur_stat); + if (ret) + return false; + + for (i = 0; i < NBANK(chip); i++) { + /* Apply filter for rising/falling edge selection */ + pending[i] = (~cur_stat[i] & chip->irq_trig_fall[i]) | + (cur_stat[i] & chip->irq_trig_raise[i]); + pending[i] &= trigger[i]; + if (pending[i]) + pending_seen = true; + } + + return pending_seen; + } + switch (chip->chip_type) { case PCA953X_TYPE: offset = PCA953X_INPUT; -- GitLab From 32b9b10961860860268961d9aad0c56a73018c37 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 11 Feb 2016 13:19:09 -0800 Subject: [PATCH 1906/9938] clk: Allow clocks to be marked as CRITICAL Critical clocks are those which must not be gated, else undefined or catastrophic failure would occur. Here we have chosen to ensure the prepare/enable counts are correctly incremented, so as not to confuse users with enabled clocks with no visible users. Signed-off-by: Lee Jones Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1455225554-13267-2-git-send-email-mturquette@baylibre.com --- drivers/clk/clk.c | 5 +++++ include/linux/clk-provider.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb74dc1f7520..275201fd7b01 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2397,6 +2397,11 @@ static int __clk_core_init(struct clk_core *core) if (core->ops->init) core->ops->init(core->hw); + if (core->flags & CLK_IS_CRITICAL) { + clk_core_prepare(core); + clk_core_enable(core); + } + kref_init(&core->ref); out: clk_prepare_unlock(); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index da95258127aa..0638b4154502 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -32,6 +32,7 @@ #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ #define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ #define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */ +#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ struct clk; struct clk_hw; -- GitLab From 2e20fbf592621b2c2aeddd82e0fa3dad053cce03 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 11 Feb 2016 13:19:10 -0800 Subject: [PATCH 1907/9938] clk: WARN_ON about to disable a critical clock Signed-off-by: Lee Jones Reviewed-by: Stephen Boyd Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1455225554-13267-3-git-send-email-mturquette@baylibre.com --- drivers/clk/clk.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 275201fd7b01..dede0ce679e4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -574,6 +574,9 @@ static void clk_core_unprepare(struct clk_core *core) if (WARN_ON(core->prepare_count == 0)) return; + if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL)) + return; + if (--core->prepare_count > 0) return; @@ -679,6 +682,9 @@ static void clk_core_disable(struct clk_core *core) if (WARN_ON(core->enable_count == 0)) return; + if (WARN_ON(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL)) + return; + if (--core->enable_count > 0) return; -- GitLab From d56f8994b6fb928f59481fabc25bcd1c2f9bd06d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 11 Feb 2016 13:19:11 -0800 Subject: [PATCH 1908/9938] clk: Provide OF helper to mark clocks as CRITICAL This call matches clocks which have been marked as critical in DT and sets the appropriate flag. These flags can then be used to mark the clock core flags appropriately prior to registration. Legacy bindings requiring this feature must add the clock-critical property to their binding descriptions, as it is not a part of common-clock binding. Cc: devicetree@vger.kernel.org Signed-off-by: Lee Jones Reviewed-by: Stephen Boyd Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1455225554-13267-4-git-send-email-mturquette@baylibre.com --- drivers/clk/clk.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 8 +++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index dede0ce679e4..9f77cc67cdc3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3137,6 +3137,41 @@ static int parent_ready(struct device_node *np) } } +/** + * of_clk_detect_critical() - set CLK_IS_CRITICAL flag from Device Tree + * @np: Device node pointer associated with clock provider + * @index: clock index + * @flags: pointer to clk_core->flags + * + * Detects if the clock-critical property exists and, if so, sets the + * corresponding CLK_IS_CRITICAL flag. + * + * Do not use this function. It exists only for legacy Device Tree + * bindings, such as the one-clock-per-node style that are outdated. + * Those bindings typically put all clock data into .dts and the Linux + * driver has no clock data, thus making it impossible to set this flag + * correctly from the driver. Only those drivers may call + * of_clk_detect_critical from their setup functions. + * + * Return: error code or zero on success + */ +int of_clk_detect_critical(struct device_node *np, + int index, unsigned long *flags) +{ + struct property *prop; + const __be32 *cur; + uint32_t idx; + + if (!np || !flags) + return -EINVAL; + + of_property_for_each_u32(np, "clock-critical", prop, cur, idx) + if (index == idx) + *flags |= CLK_IS_CRITICAL; + + return 0; +} + /** * of_clk_init() - Scan and init clock providers from the DT * @matches: array of compatible values and init functions for providers. diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 0638b4154502..156286445a25 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -721,7 +721,8 @@ unsigned int of_clk_get_parent_count(struct device_node *np); int of_clk_parent_fill(struct device_node *np, const char **parents, unsigned int size); const char *of_clk_get_parent_name(struct device_node *np, int index); - +int of_clk_detect_critical(struct device_node *np, int index, + unsigned long *flags); void of_clk_init(const struct of_device_id *matches); #else /* !CONFIG_OF */ @@ -758,6 +759,11 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, { return NULL; } +static inline int of_clk_detect_critical(struct device_node *np, int index, + unsigned long *flags) +{ + return 0; +} static inline void of_clk_init(const struct of_device_id *matches) {} #endif /* CONFIG_OF */ -- GitLab From 03c5b534185f9844c1b5fcfdbae2adc32821ec42 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 9 Apr 2016 08:01:13 -0700 Subject: [PATCH 1909/9938] ipv6: fix inet6_lookup_listener() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A stupid refactoring bug in inet6_lookup_listener() needs to be fixed in order to get proper SO_REUSEPORT behavior. Fixes: 3b24d854cb35 ("tcp/dccp: do not touch listener sk_refcnt under synflood") Signed-off-by: Eric Dumazet Reported-by: Maciej Żenczykowski Signed-off-by: David S. Miller --- net/ipv6/inet6_hashtables.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 607da088344d..f1678388fb0d 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -137,7 +137,7 @@ struct sock *inet6_lookup_listener(struct net *net, sk_for_each(sk, &ilb->head) { score = compute_score(sk, net, hnum, daddr, dif); if (score > hiscore) { - hiscore = score; + reuseport = sk->sk_reuseport; if (reuseport) { phash = inet6_ehashfn(net, daddr, hnum, saddr, sport); @@ -148,7 +148,7 @@ struct sock *inet6_lookup_listener(struct net *net, matches = 1; } result = sk; - reuseport = sk->sk_reuseport; + hiscore = score; } else if (score == hiscore && reuseport) { matches++; if (reciprocal_scale(phash, matches) == 0) -- GitLab From e997ebbe46fe46bd4e8d476adca1f9b76779f270 Mon Sep 17 00:00:00 2001 From: Michael Thalmeier Date: Fri, 25 Mar 2016 15:46:51 +0100 Subject: [PATCH 1910/9938] NFC: pn533: Send ATR_REQ only if NFC_PROTO_NFC_DEP bit is set Currently it is not possible to only poll for passive targets with the pn533 driver. To change this ATR_REQ is only sent when NFC_PROTO_NFC_DEP is explicitly requested in poll_protocols. As most implementations (e.g. neard) poll for all protocols that are reported to be supported by the adapter, this should not have much of an effect on current implementations. Signed-off-by: Michael Thalmeier Signed-off-by: Samuel Ortiz --- drivers/nfc/pn533.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index bb3d5ea9869c..a85830fcafd0 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1540,7 +1540,8 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) int rc, tgdata_len; /* Toggle the DEP polling */ - dev->poll_dep = 1; + if (dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK) + dev->poll_dep = 1; nbtg = resp->data[0]; tg = resp->data[1]; @@ -2054,7 +2055,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) dev_dbg(&dev->interface->dev, "%s mod len %d\n", __func__, mod->len); - if (dev->poll_dep) { + if ((dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK) && dev->poll_dep) { dev->poll_dep = 0; return pn533_poll_dep(dev->nfc_dev); } -- GitLab From 37f895d7e85e7d7e23e2395e666ea43001862e5f Mon Sep 17 00:00:00 2001 From: Michael Thalmeier Date: Fri, 25 Mar 2016 15:46:52 +0100 Subject: [PATCH 1911/9938] NFC: pn533: Fix socket deadlock A deadlock can occur when the NFC raw socket is closed while the driver is processing a command. Following is the call graph of the affected situation: send data via raw_sock: ------------- rawsock_tx_work sock_hold => socket refcnt++ nfc_data_exchange => cb = rawsock_data_exchange_complete ops->im_transceive = pn533_transceive => arg->cb = db = rawsock_data_exchange_complete pn533_send_data_async => cb = pn533_data_exchange_complete __pn533_send_async => cmd->complete_cb = cb = pn533_data_exchange_complete if_ops->send_frame_async response: -------- pn533_recv_response queue_work(priv->wq, &priv->cmd_complete_work) pn533_wq_cmd_complete pn533_send_async_complete cmd->complete_cb() = pn533_data_exchange_complete() arg->cb() = rawsock_data_exchange_complete() sock_put => socket refcnt-- => If the corresponding socket gets closed in the meantime socket will be destructed sk_free __sk_free sk->sk_destruct = rawsock_destruct nfc_deactivate_target ops->deactivate_target = pn533_deactivate_target pn533_send_cmd_sync pn533_send_cmd_async __pn533_send_async list_add_tail(&cmd->queue,&dev->cmd_queue) => add to command list because a command is currently processed wait_for_completion => the workqueue thread waits here because it is the one processing the commands => deadlock To fix the deadlock pn533_deactivate_target is changed to issue the PN533_CMD_IN_RELEASE command in async mode. This way nothing blocks and the release command is executed after the current command. Signed-off-by: Michael Thalmeier Signed-off-by: Samuel Ortiz --- drivers/nfc/pn533.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index a85830fcafd0..074f1e42e378 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -2263,12 +2263,35 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, return 0; } +static int pn533_deactivate_target_complete(struct pn533 *dev, void *arg, + struct sk_buff *resp) +{ + int rc = 0; + + dev_dbg(&dev->interface->dev, "%s\n", __func__); + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + + nfc_err(&dev->interface->dev, "Target release error %d\n", rc); + + return rc; + } + + rc = resp->data[0] & PN533_CMD_RET_MASK; + if (rc != PN533_CMD_RET_SUCCESS) + nfc_err(&dev->interface->dev, + "Error 0x%x when releasing the target\n", rc); + + dev_kfree_skb(resp); + return rc; +} + static void pn533_deactivate_target(struct nfc_dev *nfc_dev, struct nfc_target *target, u8 mode) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); struct sk_buff *skb; - struct sk_buff *resp; int rc; dev_dbg(&dev->interface->dev, "%s\n", __func__); @@ -2287,16 +2310,13 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, *skb_put(skb, 1) = 1; /* TG*/ - resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_RELEASE, skb); - if (IS_ERR(resp)) - return; - - rc = resp->data[0] & PN533_CMD_RET_MASK; - if (rc != PN533_CMD_RET_SUCCESS) - nfc_err(&dev->interface->dev, - "Error 0x%x when releasing the target\n", rc); + rc = pn533_send_cmd_async(dev, PN533_CMD_IN_RELEASE, skb, + pn533_deactivate_target_complete, NULL); + if (rc < 0) { + dev_kfree_skb(skb); + nfc_err(&dev->interface->dev, "Target release error %d\n", rc); + } - dev_kfree_skb(resp); return; } -- GitLab From 9815c7cf22daceabfb919ddcd6f2c80e049c1fbc Mon Sep 17 00:00:00 2001 From: Michael Thalmeier Date: Fri, 25 Mar 2016 15:46:53 +0100 Subject: [PATCH 1912/9938] NFC: pn533: Separate physical layer from the core implementation The driver now has all core stuff isolated in one file, and all the hardware link specifics in another. Writing a pn533 driver on top of another hardware link is now just a matter of adding a new file for that new hardware specifics. The first user of this separation will be the i2c based pn532 driver that reuses pn533 core implementation on top of an i2c layer. Signed-off-by: Michael Thalmeier Signed-off-by: Samuel Ortiz --- drivers/nfc/Kconfig | 11 +- drivers/nfc/Makefile | 2 +- drivers/nfc/pn533/Kconfig | 16 + drivers/nfc/pn533/Makefile | 7 + drivers/nfc/{ => pn533}/pn533.c | 1136 ++++++------------------------- drivers/nfc/pn533/pn533.h | 235 +++++++ drivers/nfc/pn533/usb.c | 598 ++++++++++++++++ 7 files changed, 1081 insertions(+), 924 deletions(-) create mode 100644 drivers/nfc/pn533/Kconfig create mode 100644 drivers/nfc/pn533/Makefile rename drivers/nfc/{ => pn533}/pn533.c (67%) create mode 100644 drivers/nfc/pn533/pn533.h create mode 100644 drivers/nfc/pn533/usb.c diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 7437c9dfd8fc..ea8321a483f9 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -5,16 +5,6 @@ menu "Near Field Communication (NFC) devices" depends on NFC -config NFC_PN533 - tristate "NXP PN533 USB driver" - depends on USB - help - NXP PN533 USB driver. - This driver provides support for NFC NXP PN533 devices. - - Say Y here to compile support for PN533 devices into the - kernel or say M to compile it as module (pn533). - config NFC_WILINK tristate "Texas Instruments NFC WiLink driver" depends on TI_ST && NFC_NCI @@ -70,6 +60,7 @@ config NFC_PORT100 source "drivers/nfc/fdp/Kconfig" source "drivers/nfc/pn544/Kconfig" +source "drivers/nfc/pn533/Kconfig" source "drivers/nfc/microread/Kconfig" source "drivers/nfc/nfcmrvl/Kconfig" source "drivers/nfc/st21nfca/Kconfig" diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 0a99e67daa10..bab8ef06ae35 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_NFC_FDP) += fdp/ obj-$(CONFIG_NFC_PN544) += pn544/ obj-$(CONFIG_NFC_MICROREAD) += microread/ -obj-$(CONFIG_NFC_PN533) += pn533.o +obj-$(CONFIG_NFC_PN533) += pn533/ obj-$(CONFIG_NFC_WILINK) += nfcwilink.o obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o obj-$(CONFIG_NFC_SIM) += nfcsim.o diff --git a/drivers/nfc/pn533/Kconfig b/drivers/nfc/pn533/Kconfig new file mode 100644 index 000000000000..b5a926e42f7b --- /dev/null +++ b/drivers/nfc/pn533/Kconfig @@ -0,0 +1,16 @@ +config NFC_PN533 + tristate + help + NXP PN533 core driver. + This driver provides core functionality for NXP PN533 NFC devices. + +config NFC_PN533_USB + tristate "NFC PN533 device support (USB)" + depends on USB + select NFC_PN533 + ---help--- + This module adds support for the NXP pn533 USB interface. + Select this if your platform is using the USB bus. + + If you choose to build a module, it'll be called pn533_usb. + Say N if unsure. diff --git a/drivers/nfc/pn533/Makefile b/drivers/nfc/pn533/Makefile new file mode 100644 index 000000000000..12c6be481483 --- /dev/null +++ b/drivers/nfc/pn533/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for PN533 NFC driver +# +pn533_usb-objs = usb.o + +obj-$(CONFIG_NFC_PN533) += pn533.o +obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533/pn533.c similarity index 67% rename from drivers/nfc/pn533.c rename to drivers/nfc/pn533/pn533.c index 074f1e42e378..52d83fec5add 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -1,4 +1,6 @@ /* + * Driver for NXP PN533 NFC Chip - core functions + * * Copyright (C) 2011 Instituto Nokia de Tecnologia * Copyright (C) 2012-2013 Tieto Poland * @@ -20,137 +22,18 @@ #include #include #include -#include #include #include #include +#include "pn533.h" -#define VERSION "0.2" - -#define PN533_VENDOR_ID 0x4CC -#define PN533_PRODUCT_ID 0x2533 - -#define SCM_VENDOR_ID 0x4E6 -#define SCL3711_PRODUCT_ID 0x5591 - -#define SONY_VENDOR_ID 0x054c -#define PASORI_PRODUCT_ID 0x02e1 - -#define ACS_VENDOR_ID 0x072f -#define ACR122U_PRODUCT_ID 0x2200 - -#define PN533_DEVICE_STD 0x1 -#define PN533_DEVICE_PASORI 0x2 -#define PN533_DEVICE_ACR122U 0x3 - -#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\ - NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\ - NFC_PROTO_NFC_DEP_MASK |\ - NFC_PROTO_ISO14443_B_MASK) - -#define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ - NFC_PROTO_MIFARE_MASK | \ - NFC_PROTO_FELICA_MASK | \ - NFC_PROTO_ISO14443_MASK | \ - NFC_PROTO_NFC_DEP_MASK) - -static const struct usb_device_id pn533_table[] = { - { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID), - .driver_info = PN533_DEVICE_STD }, - { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID), - .driver_info = PN533_DEVICE_STD }, - { USB_DEVICE(SONY_VENDOR_ID, PASORI_PRODUCT_ID), - .driver_info = PN533_DEVICE_PASORI }, - { USB_DEVICE(ACS_VENDOR_ID, ACR122U_PRODUCT_ID), - .driver_info = PN533_DEVICE_ACR122U }, - { } -}; -MODULE_DEVICE_TABLE(usb, pn533_table); +#define VERSION "0.3" /* How much time we spend listening for initiators */ #define PN533_LISTEN_TIME 2 /* Delay between each poll frame (ms) */ #define PN533_POLL_INTERVAL 10 -/* Standard pn533 frame definitions (standard and extended)*/ -#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \ - + 2) /* data[0] TFI, data[1] CC */ -#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ - -#define PN533_EXT_FRAME_HEADER_LEN (sizeof(struct pn533_ext_frame) \ - + 2) /* data[0] TFI, data[1] CC */ - -#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 -#define PN533_CMD_DATAFRAME_MAXLEN 240 /* max data length (send) */ - -/* - * Max extended frame payload len, excluding TFI and CC - * which are already in PN533_FRAME_HEADER_LEN. - */ -#define PN533_STD_FRAME_MAX_PAYLOAD_LEN 263 - -#define PN533_STD_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2), - Postamble (1) */ -#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen]) -#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) -/* Half start code (3), LEN (4) should be 0xffff for extended frame */ -#define PN533_STD_IS_EXTENDED(hdr) ((hdr)->datalen == 0xFF \ - && (hdr)->datalen_checksum == 0xFF) -#define PN533_EXT_FRAME_CHECKSUM(f) (f->data[be16_to_cpu(f->datalen)]) - -/* start of frame */ -#define PN533_STD_FRAME_SOF 0x00FF - -/* standard frame identifier: in/out/error */ -#define PN533_STD_FRAME_IDENTIFIER(f) (f->data[0]) /* TFI */ -#define PN533_STD_FRAME_DIR_OUT 0xD4 -#define PN533_STD_FRAME_DIR_IN 0xD5 - -/* ACS ACR122 pn533 frame definitions */ -#define PN533_ACR122_TX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_tx_frame) \ - + 2) -#define PN533_ACR122_TX_FRAME_TAIL_LEN 0 -#define PN533_ACR122_RX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_rx_frame) \ - + 2) -#define PN533_ACR122_RX_FRAME_TAIL_LEN 2 -#define PN533_ACR122_FRAME_MAX_PAYLOAD_LEN PN533_STD_FRAME_MAX_PAYLOAD_LEN - -/* CCID messages types */ -#define PN533_ACR122_PC_TO_RDR_ICCPOWERON 0x62 -#define PN533_ACR122_PC_TO_RDR_ESCAPE 0x6B - -#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83 - -/* PN533 Commands */ -#define PN533_FRAME_CMD(f) (f->data[1]) - -#define PN533_CMD_GET_FIRMWARE_VERSION 0x02 -#define PN533_CMD_RF_CONFIGURATION 0x32 -#define PN533_CMD_IN_DATA_EXCHANGE 0x40 -#define PN533_CMD_IN_COMM_THRU 0x42 -#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A -#define PN533_CMD_IN_ATR 0x50 -#define PN533_CMD_IN_RELEASE 0x52 -#define PN533_CMD_IN_JUMP_FOR_DEP 0x56 - -#define PN533_CMD_TG_INIT_AS_TARGET 0x8c -#define PN533_CMD_TG_GET_DATA 0x86 -#define PN533_CMD_TG_SET_DATA 0x8e -#define PN533_CMD_TG_SET_META_DATA 0x94 -#define PN533_CMD_UNDEF 0xff - -#define PN533_CMD_RESPONSE(cmd) (cmd + 1) - -/* PN533 Return codes */ -#define PN533_CMD_RET_MASK 0x3F -#define PN533_CMD_MI_MASK 0x40 -#define PN533_CMD_RET_SUCCESS 0x00 - -struct pn533; - -typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg, - struct sk_buff *resp); - /* structs for pn533 commands */ /* PN533_CMD_GET_FIRMWARE_VERSION */ @@ -220,19 +103,6 @@ union pn533_cmd_poll_initdata { } __packed felica; }; -/* Poll modulations */ -enum { - PN533_POLL_MOD_106KBPS_A, - PN533_POLL_MOD_212KBPS_FELICA, - PN533_POLL_MOD_424KBPS_FELICA, - PN533_POLL_MOD_106KBPS_JEWEL, - PN533_POLL_MOD_847KBPS_B, - PN533_LISTEN_MOD, - - __PN533_POLL_MOD_AFTER_LAST, -}; -#define PN533_POLL_MOD_MAX (__PN533_POLL_MOD_AFTER_LAST - 1) - struct pn533_poll_modulations { struct { u8 maxtg; @@ -336,219 +206,6 @@ struct pn533_cmd_jump_dep_response { #define PN533_INIT_TARGET_RESP_ACTIVE 0x1 #define PN533_INIT_TARGET_RESP_DEP 0x4 -enum pn533_protocol_type { - PN533_PROTO_REQ_ACK_RESP = 0, - PN533_PROTO_REQ_RESP -}; - -struct pn533 { - struct usb_device *udev; - struct usb_interface *interface; - struct nfc_dev *nfc_dev; - u32 device_type; - enum pn533_protocol_type protocol_type; - - struct urb *out_urb; - struct urb *in_urb; - - struct sk_buff_head resp_q; - struct sk_buff_head fragment_skb; - - struct workqueue_struct *wq; - struct work_struct cmd_work; - struct work_struct cmd_complete_work; - struct delayed_work poll_work; - struct work_struct mi_rx_work; - struct work_struct mi_tx_work; - struct work_struct mi_tm_rx_work; - struct work_struct mi_tm_tx_work; - struct work_struct tg_work; - struct work_struct rf_work; - - struct list_head cmd_queue; - struct pn533_cmd *cmd; - u8 cmd_pending; - struct mutex cmd_lock; /* protects cmd queue */ - - void *cmd_complete_mi_arg; - void *cmd_complete_dep_arg; - - struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; - u8 poll_mod_count; - u8 poll_mod_curr; - u8 poll_dep; - u32 poll_protocols; - u32 listen_protocols; - struct timer_list listen_timer; - int cancel_listen; - - u8 *gb; - size_t gb_len; - - u8 tgt_available_prots; - u8 tgt_active_prot; - u8 tgt_mode; - - struct pn533_frame_ops *ops; -}; - -struct pn533_cmd { - struct list_head queue; - u8 code; - int status; - struct sk_buff *req; - struct sk_buff *resp; - int resp_len; - pn533_send_async_complete_t complete_cb; - void *complete_cb_context; -}; - -struct pn533_std_frame { - u8 preamble; - __be16 start_frame; - u8 datalen; - u8 datalen_checksum; - u8 data[]; -} __packed; - -struct pn533_ext_frame { /* Extended Information frame */ - u8 preamble; - __be16 start_frame; - __be16 eif_flag; /* fixed to 0xFFFF */ - __be16 datalen; - u8 datalen_checksum; - u8 data[]; -} __packed; - -struct pn533_frame_ops { - void (*tx_frame_init)(void *frame, u8 cmd_code); - void (*tx_frame_finish)(void *frame); - void (*tx_update_payload_len)(void *frame, int len); - int tx_header_len; - int tx_tail_len; - - bool (*rx_is_frame_valid)(void *frame, struct pn533 *dev); - int (*rx_frame_size)(void *frame); - int rx_header_len; - int rx_tail_len; - - int max_payload_len; - u8 (*get_cmd_code)(void *frame); -}; - -struct pn533_acr122_ccid_hdr { - u8 type; - u32 datalen; - u8 slot; - u8 seq; - u8 params[3]; /* 3 msg specific bytes or status, error and 1 specific - byte for reposnse msg */ - u8 data[]; /* payload */ -} __packed; - -struct pn533_acr122_apdu_hdr { - u8 class; - u8 ins; - u8 p1; - u8 p2; -} __packed; - -struct pn533_acr122_tx_frame { - struct pn533_acr122_ccid_hdr ccid; - struct pn533_acr122_apdu_hdr apdu; - u8 datalen; - u8 data[]; /* pn533 frame: TFI ... */ -} __packed; - -struct pn533_acr122_rx_frame { - struct pn533_acr122_ccid_hdr ccid; - u8 data[]; /* pn533 frame : TFI ... */ -} __packed; - -static void pn533_acr122_tx_frame_init(void *_frame, u8 cmd_code) -{ - struct pn533_acr122_tx_frame *frame = _frame; - - frame->ccid.type = PN533_ACR122_PC_TO_RDR_ESCAPE; - frame->ccid.datalen = sizeof(frame->apdu) + 1; /* sizeof(apdu_hdr) + - sizeof(datalen) */ - frame->ccid.slot = 0; - frame->ccid.seq = 0; - frame->ccid.params[0] = 0; - frame->ccid.params[1] = 0; - frame->ccid.params[2] = 0; - - frame->data[0] = PN533_STD_FRAME_DIR_OUT; - frame->data[1] = cmd_code; - frame->datalen = 2; /* data[0] + data[1] */ - - frame->apdu.class = 0xFF; - frame->apdu.ins = 0; - frame->apdu.p1 = 0; - frame->apdu.p2 = 0; -} - -static void pn533_acr122_tx_frame_finish(void *_frame) -{ - struct pn533_acr122_tx_frame *frame = _frame; - - frame->ccid.datalen += frame->datalen; -} - -static void pn533_acr122_tx_update_payload_len(void *_frame, int len) -{ - struct pn533_acr122_tx_frame *frame = _frame; - - frame->datalen += len; -} - -static bool pn533_acr122_is_rx_frame_valid(void *_frame, struct pn533 *dev) -{ - struct pn533_acr122_rx_frame *frame = _frame; - - if (frame->ccid.type != 0x83) - return false; - - if (!frame->ccid.datalen) - return false; - - if (frame->data[frame->ccid.datalen - 2] == 0x63) - return false; - - return true; -} - -static int pn533_acr122_rx_frame_size(void *frame) -{ - struct pn533_acr122_rx_frame *f = frame; - - /* f->ccid.datalen already includes tail length */ - return sizeof(struct pn533_acr122_rx_frame) + f->ccid.datalen; -} - -static u8 pn533_acr122_get_cmd_code(void *frame) -{ - struct pn533_acr122_rx_frame *f = frame; - - return PN533_FRAME_CMD(f); -} - -static struct pn533_frame_ops pn533_acr122_frame_ops = { - .tx_frame_init = pn533_acr122_tx_frame_init, - .tx_frame_finish = pn533_acr122_tx_frame_finish, - .tx_update_payload_len = pn533_acr122_tx_update_payload_len, - .tx_header_len = PN533_ACR122_TX_FRAME_HEADER_LEN, - .tx_tail_len = PN533_ACR122_TX_FRAME_TAIL_LEN, - - .rx_is_frame_valid = pn533_acr122_is_rx_frame_valid, - .rx_header_len = PN533_ACR122_RX_FRAME_HEADER_LEN, - .rx_tail_len = PN533_ACR122_RX_FRAME_TAIL_LEN, - .rx_frame_size = pn533_acr122_rx_frame_size, - - .max_payload_len = PN533_ACR122_FRAME_MAX_PAYLOAD_LEN, - .get_cmd_code = pn533_acr122_get_cmd_code, -}; - /* The rule: value(high byte) + value(low byte) + checksum = 0 */ static inline u8 pn533_ext_checksum(u16 value) { @@ -642,8 +299,10 @@ static bool pn533_std_rx_frame_is_valid(void *_frame, struct pn533 *dev) return true; } -static bool pn533_std_rx_frame_is_ack(struct pn533_std_frame *frame) +bool pn533_rx_frame_is_ack(void *_frame) { + struct pn533_std_frame *frame = _frame; + if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF)) return false; @@ -652,6 +311,7 @@ static bool pn533_std_rx_frame_is_ack(struct pn533_std_frame *frame) return true; } +EXPORT_SYMBOL_GPL(pn533_rx_frame_is_ack); static inline int pn533_std_rx_frame_size(void *frame) { @@ -680,6 +340,14 @@ static u8 pn533_std_get_cmd_code(void *frame) return PN533_FRAME_CMD(f); } +bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame) +{ + return (dev->ops->get_cmd_code(frame) == + PN533_CMD_RESPONSE(dev->cmd->code)); +} +EXPORT_SYMBOL_GPL(pn533_rx_frame_is_cmd_response); + + static struct pn533_frame_ops pn533_std_frame_ops = { .tx_frame_init = pn533_std_tx_frame_init, .tx_frame_finish = pn533_std_tx_frame_finish, @@ -696,172 +364,6 @@ static struct pn533_frame_ops pn533_std_frame_ops = { .get_cmd_code = pn533_std_get_cmd_code, }; -static bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame) -{ - return (dev->ops->get_cmd_code(frame) == - PN533_CMD_RESPONSE(dev->cmd->code)); -} - -static void pn533_recv_response(struct urb *urb) -{ - struct pn533 *dev = urb->context; - struct pn533_cmd *cmd = dev->cmd; - u8 *in_frame; - - cmd->status = urb->status; - - switch (urb->status) { - case 0: - break; /* success */ - case -ECONNRESET: - case -ENOENT: - dev_dbg(&dev->interface->dev, - "The urb has been canceled (status %d)\n", - urb->status); - goto sched_wq; - case -ESHUTDOWN: - default: - nfc_err(&dev->interface->dev, - "Urb failure (status %d)\n", urb->status); - goto sched_wq; - } - - in_frame = dev->in_urb->transfer_buffer; - - dev_dbg(&dev->interface->dev, "Received a frame\n"); - print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, - dev->ops->rx_frame_size(in_frame), false); - - if (!dev->ops->rx_is_frame_valid(in_frame, dev)) { - nfc_err(&dev->interface->dev, "Received an invalid frame\n"); - cmd->status = -EIO; - goto sched_wq; - } - - if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { - nfc_err(&dev->interface->dev, - "It it not the response to the last command\n"); - cmd->status = -EIO; - goto sched_wq; - } - -sched_wq: - queue_work(dev->wq, &dev->cmd_complete_work); -} - -static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags) -{ - dev->in_urb->complete = pn533_recv_response; - - return usb_submit_urb(dev->in_urb, flags); -} - -static void pn533_recv_ack(struct urb *urb) -{ - struct pn533 *dev = urb->context; - struct pn533_cmd *cmd = dev->cmd; - struct pn533_std_frame *in_frame; - int rc; - - cmd->status = urb->status; - - switch (urb->status) { - case 0: - break; /* success */ - case -ECONNRESET: - case -ENOENT: - dev_dbg(&dev->interface->dev, - "The urb has been stopped (status %d)\n", - urb->status); - goto sched_wq; - case -ESHUTDOWN: - default: - nfc_err(&dev->interface->dev, - "Urb failure (status %d)\n", urb->status); - goto sched_wq; - } - - in_frame = dev->in_urb->transfer_buffer; - - if (!pn533_std_rx_frame_is_ack(in_frame)) { - nfc_err(&dev->interface->dev, "Received an invalid ack\n"); - cmd->status = -EIO; - goto sched_wq; - } - - rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); - if (rc) { - nfc_err(&dev->interface->dev, - "usb_submit_urb failed with result %d\n", rc); - cmd->status = rc; - goto sched_wq; - } - - return; - -sched_wq: - queue_work(dev->wq, &dev->cmd_complete_work); -} - -static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) -{ - dev->in_urb->complete = pn533_recv_ack; - - return usb_submit_urb(dev->in_urb, flags); -} - -static int pn533_send_ack(struct pn533 *dev, gfp_t flags) -{ - u8 ack[PN533_STD_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; - /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ - int rc; - - dev->out_urb->transfer_buffer = ack; - dev->out_urb->transfer_buffer_length = sizeof(ack); - rc = usb_submit_urb(dev->out_urb, flags); - - return rc; -} - -static int __pn533_send_frame_async(struct pn533 *dev, - struct sk_buff *out, - struct sk_buff *in, - int in_len) -{ - int rc; - - dev->out_urb->transfer_buffer = out->data; - dev->out_urb->transfer_buffer_length = out->len; - - dev->in_urb->transfer_buffer = in->data; - dev->in_urb->transfer_buffer_length = in_len; - - print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, - out->data, out->len, false); - - rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); - if (rc) - return rc; - - if (dev->protocol_type == PN533_PROTO_REQ_RESP) { - /* request for response for sent packet directly */ - rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); - if (rc) - goto error; - } else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) { - /* request for ACK if that's the case */ - rc = pn533_submit_urb_for_ack(dev, GFP_KERNEL); - if (rc) - goto error; - } - - return 0; - -error: - usb_unlink_urb(dev->out_urb); - return rc; -} - static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code, struct sk_buff *skb) { @@ -897,7 +399,6 @@ static int pn533_send_async_complete(struct pn533 *dev) goto done; } - skb_put(resp, dev->ops->rx_frame_size(resp->data)); skb_pull(resp, dev->ops->rx_header_len); skb_trim(resp, resp->len - dev->ops->rx_tail_len); @@ -910,15 +411,14 @@ static int pn533_send_async_complete(struct pn533 *dev) } static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, - struct sk_buff *req, struct sk_buff *resp, - int resp_len, + struct sk_buff *req, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { struct pn533_cmd *cmd; int rc = 0; - dev_dbg(&dev->interface->dev, "Sending command 0x%x\n", cmd_code); + dev_dbg(dev->dev, "Sending command 0x%x\n", cmd_code); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) @@ -926,8 +426,6 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, cmd->code = cmd_code; cmd->req = req; - cmd->resp = resp; - cmd->resp_len = resp_len; cmd->complete_cb = complete_cb; cmd->complete_cb_context = complete_cb_context; @@ -936,7 +434,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, mutex_lock(&dev->cmd_lock); if (!dev->cmd_pending) { - rc = __pn533_send_frame_async(dev, req, resp, resp_len); + rc = dev->phy_ops->send_frame(dev, req); if (rc) goto error; @@ -945,7 +443,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, goto unlock; } - dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x\n", + dev_dbg(dev->dev, "%s Queueing command 0x%x\n", __func__, cmd_code); INIT_LIST_HEAD(&cmd->queue); @@ -965,20 +463,10 @@ static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - struct sk_buff *resp; int rc; - int resp_len = dev->ops->rx_header_len + - dev->ops->max_payload_len + - dev->ops->rx_tail_len; - - resp = nfc_alloc_recv_skb(resp_len, GFP_KERNEL); - if (!resp) - return -ENOMEM; - rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, + rc = __pn533_send_async(dev, cmd_code, req, complete_cb, complete_cb_context); - if (rc) - dev_kfree_skb(resp); return rc; } @@ -988,20 +476,10 @@ static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - struct sk_buff *resp; int rc; - int resp_len = dev->ops->rx_header_len + - dev->ops->max_payload_len + - dev->ops->rx_tail_len; - resp = alloc_skb(resp_len, GFP_KERNEL); - if (!resp) - return -ENOMEM; - - rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, + rc = __pn533_send_async(dev, cmd_code, req, complete_cb, complete_cb_context); - if (rc) - dev_kfree_skb(resp); return rc; } @@ -1019,39 +497,25 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - struct sk_buff *resp; struct pn533_cmd *cmd; int rc; - int resp_len = dev->ops->rx_header_len + - dev->ops->max_payload_len + - dev->ops->rx_tail_len; - - resp = alloc_skb(resp_len, GFP_KERNEL); - if (!resp) - return -ENOMEM; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - dev_kfree_skb(resp); + if (!cmd) return -ENOMEM; - } cmd->code = cmd_code; cmd->req = req; - cmd->resp = resp; - cmd->resp_len = resp_len; cmd->complete_cb = complete_cb; cmd->complete_cb_context = complete_cb_context; pn533_build_cmd_frame(dev, cmd_code, req); - rc = __pn533_send_frame_async(dev, req, resp, resp_len); - if (rc < 0) { - dev_kfree_skb(resp); + rc = dev->phy_ops->send_frame(dev, req); + if (rc < 0) kfree(cmd); - } else { + else dev->cmd = cmd; - } return rc; } @@ -1086,10 +550,9 @@ static void pn533_wq_cmd(struct work_struct *work) mutex_unlock(&dev->cmd_lock); - rc = __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len); + rc = dev->phy_ops->send_frame(dev, cmd->req); if (rc < 0) { dev_kfree_skb(cmd->req); - dev_kfree_skb(cmd->resp); kfree(cmd); return; } @@ -1121,7 +584,7 @@ static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, * 1. negative in case of error during TX path -> req should be freed * * 2. negative in case of error during RX path -> req should not be freed - * as it's been already freed at the begining of RX path by + * as it's been already freed at the beginning of RX path by * async_complete_cb. * * 3. valid pointer in case of succesfult RX path @@ -1129,7 +592,7 @@ static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, * A caller has to check a return value with IS_ERR macro. If the test pass, * the returned pointer is valid. * - * */ + */ static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, struct sk_buff *req) { @@ -1150,43 +613,6 @@ static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, return arg.resp; } -static void pn533_send_complete(struct urb *urb) -{ - struct pn533 *dev = urb->context; - - switch (urb->status) { - case 0: - break; /* success */ - case -ECONNRESET: - case -ENOENT: - dev_dbg(&dev->interface->dev, - "The urb has been stopped (status %d)\n", - urb->status); - break; - case -ESHUTDOWN: - default: - nfc_err(&dev->interface->dev, "Urb failure (status %d)\n", - urb->status); - } -} - -static void pn533_abort_cmd(struct pn533 *dev, gfp_t flags) -{ - /* ACR122U does not support any command which aborts last - * issued command i.e. as ACK for standard PN533. Additionally, - * it behaves stange, sending broken or incorrect responses, - * when we cancel urb before the chip will send response. - */ - if (dev->device_type == PN533_DEVICE_ACR122U) - return; - - /* An ack will cancel the last issued command */ - pn533_send_ack(dev, flags); - - /* cancel the urb request */ - usb_kill_urb(dev->in_urb); -} - static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size) { struct sk_buff *skb; @@ -1233,8 +659,10 @@ static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a, if (target_data_len < sizeof(struct pn533_target_type_a)) return false; - /* The lenght check of nfcid[] and ats[] are not being performed because - the values are not being used */ + /* + * The length check of nfcid[] and ats[] are not being performed because + * the values are not being used + */ /* Requirement 4.6.3.3 from NFC Forum Digital Spec */ ssd = PN533_TYPE_A_SENS_RES_SSD(type_a->sens_res); @@ -1443,7 +871,7 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, struct nfc_target nfc_tgt; int rc; - dev_dbg(&dev->interface->dev, "%s: modulation=%d\n", + dev_dbg(dev->dev, "%s: modulation=%d\n", __func__, dev->poll_mod_curr); if (tg != 1) @@ -1466,7 +894,7 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); break; default: - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Unknown current poll modulation\n"); return -EPROTO; } @@ -1475,12 +903,12 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, return rc; if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "The Tg found doesn't have the desired protocol\n"); return -EAGAIN; } - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "Target found - supported protocols: 0x%x\n", nfc_tgt.supported_protocols); @@ -1578,8 +1006,10 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) 0x0, 0x0, 0x0, 0x40}; /* SEL_RES for DEP */ - unsigned int skb_len = 36 + /* mode (1), mifare (6), - felica (18), nfcid3 (10), gb_len (1) */ + unsigned int skb_len = 36 + /* + * mode (1), mifare (6), + * felica (18), nfcid3 (10), gb_len (1) + */ gbytes_len + 1; /* len Tk*/ @@ -1615,8 +1045,6 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) return skb; } -#define PN533_CMD_DATAEXCH_HEAD_LEN 1 -#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 static void pn533_wq_tm_mi_recv(struct work_struct *work); static struct sk_buff *pn533_build_response(struct pn533 *dev); @@ -1627,7 +1055,7 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, u8 status, ret, mi; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { skb_queue_purge(&dev->resp_q); @@ -1676,7 +1104,7 @@ static void pn533_wq_tm_mi_recv(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 0); if (!skb) @@ -1690,8 +1118,6 @@ static void pn533_wq_tm_mi_recv(struct work_struct *work) if (rc < 0) dev_kfree_skb(skb); - - return; } static int pn533_tm_send_complete(struct pn533 *dev, void *arg, @@ -1702,7 +1128,7 @@ static void pn533_wq_tm_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); @@ -1724,13 +1150,13 @@ static void pn533_wq_tm_mi_send(struct work_struct *work) if (rc == 0) /* success */ return; - dev_err(&dev->interface->dev, + dev_err(dev->dev, "Error %d when trying to perform set meta data_exchange", rc); dev_kfree_skb(skb); error: - pn533_send_ack(dev, GFP_KERNEL); + dev->phy_ops->send_ack(dev, GFP_KERNEL); queue_work(dev->wq, &dev->cmd_work); } @@ -1740,7 +1166,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 0); if (!skb) @@ -1751,8 +1177,6 @@ static void pn533_wq_tg_get_data(struct work_struct *work) if (rc < 0) dev_kfree_skb(skb); - - return; } #define ATR_REQ_GB_OFFSET 17 @@ -1762,7 +1186,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) size_t gb_len; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (resp->len < ATR_REQ_GB_OFFSET + 1) return -EINVAL; @@ -1770,7 +1194,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) mode = resp->data[0]; cmd = &resp->data[1]; - dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", + dev_dbg(dev->dev, "Target mode 0x%x len %d\n", mode, resp->len); if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == @@ -1786,7 +1210,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, comm_mode, gb, gb_len); if (rc < 0) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error when signaling target activation\n"); return rc; } @@ -1801,7 +1225,7 @@ static void pn533_listen_mode_timer(unsigned long data) { struct pn533 *dev = (struct pn533 *)data; - dev_dbg(&dev->interface->dev, "Listen mode timeout\n"); + dev_dbg(dev->dev, "Listen mode timeout\n"); dev->cancel_listen = 1; @@ -1816,12 +1240,12 @@ static int pn533_rf_complete(struct pn533 *dev, void *arg, { int rc = 0; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_err(&dev->interface->dev, "RF setting error %d\n", rc); + nfc_err(dev->dev, "RF setting error %d\n", rc); return rc; } @@ -1839,7 +1263,7 @@ static void pn533_wq_rf(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 2); if (!skb) @@ -1852,10 +1276,8 @@ static void pn533_wq_rf(struct work_struct *work) pn533_rf_complete, NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_err(&dev->interface->dev, "RF setting error %d\n", rc); + nfc_err(dev->dev, "RF setting error %d\n", rc); } - - return; } static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, @@ -1880,7 +1302,7 @@ static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, return 0; } - dev_dbg(&dev->interface->dev, "Creating new target"); + dev_dbg(dev->dev, "Creating new target"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; @@ -1918,7 +1340,7 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev) u8 *next, nfcid3[NFC_NFCID3_MAXSIZE]; u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(dev->dev, "%s", __func__); if (!dev->gb) { dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); @@ -1975,21 +1397,20 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, struct pn533_poll_modulations *cur_mod; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_err(&dev->interface->dev, "%s Poll complete error %d\n", + nfc_err(dev->dev, "%s Poll complete error %d\n", __func__, rc); if (rc == -ENOENT) { if (dev->poll_mod_count != 0) return rc; - else - goto stop_poll; + goto stop_poll; } else if (rc < 0) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error %d when running poll\n", rc); goto stop_poll; } @@ -2009,7 +1430,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, goto done; if (!dev->poll_mod_count) { - dev_dbg(&dev->interface->dev, "Polling has been stopped\n"); + dev_dbg(dev->dev, "Polling has been stopped\n"); goto done; } @@ -2022,7 +1443,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, return rc; stop_poll: - nfc_err(&dev->interface->dev, "Polling operation has been stopped\n"); + nfc_err(dev->dev, "Polling operation has been stopped\n"); pn533_poll_reset_mod_list(dev); dev->poll_protocols = 0; @@ -2052,7 +1473,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) mod = dev->poll_mod_active[dev->poll_mod_curr]; - dev_dbg(&dev->interface->dev, "%s mod len %d\n", + dev_dbg(dev->dev, "%s mod len %d\n", __func__, mod->len); if ((dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK) && dev->poll_dep) { @@ -2069,7 +1490,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) } if (!skb) { - nfc_err(&dev->interface->dev, "Failed to allocate skb\n"); + nfc_err(dev->dev, "Failed to allocate skb\n"); return -ENOMEM; } @@ -2077,7 +1498,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_err(&dev->interface->dev, "Polling loop error %d\n", rc); + nfc_err(dev->dev, "Polling loop error %d\n", rc); } return rc; @@ -2091,13 +1512,13 @@ static void pn533_wq_poll(struct work_struct *work) cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "%s cancel_listen %d modulation len %d\n", __func__, dev->cancel_listen, cur_mod->len); if (dev->cancel_listen == 1) { dev->cancel_listen = 0; - pn533_abort_cmd(dev, GFP_ATOMIC); + dev->phy_ops->abort_cmd(dev, GFP_ATOMIC); } rc = pn533_send_poll_frame(dev); @@ -2106,8 +1527,6 @@ static void pn533_wq_poll(struct work_struct *work) if (cur_mod->len == 0 && dev->poll_mod_count > 1) mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ); - - return; } static int pn533_start_poll(struct nfc_dev *nfc_dev, @@ -2118,18 +1537,18 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, u8 rand_mod; int rc; - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "%s: im protocols 0x%x tm protocols 0x%x\n", __func__, im_protocols, tm_protocols); if (dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot poll with a target already activated\n"); return -EBUSY; } if (dev->tgt_mode) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot poll while already being activated\n"); return -EBUSY; } @@ -2167,12 +1586,12 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) del_timer(&dev->listen_timer); if (!dev->poll_mod_count) { - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "Polling operation was not running\n"); return; } - pn533_abort_cmd(dev, GFP_KERNEL); + dev->phy_ops->abort_cmd(dev, GFP_KERNEL); flush_delayed_work(&dev->poll_work); pn533_poll_reset_mod_list(dev); } @@ -2185,7 +1604,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ if (!skb) @@ -2201,7 +1620,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) rsp = (struct pn533_cmd_activate_response *)resp->data; rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Target activation failed (error 0x%x)\n", rc); dev_kfree_skb(resp); return -EIO; @@ -2221,28 +1640,28 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - dev_dbg(&dev->interface->dev, "%s: protocol=%u\n", __func__, protocol); + dev_dbg(dev->dev, "%s: protocol=%u\n", __func__, protocol); if (dev->poll_mod_count) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot activate while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "There is already an active target\n"); return -EBUSY; } if (!dev->tgt_available_prots) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "There is no available target to activate\n"); return -EINVAL; } if (!(dev->tgt_available_prots & (1 << protocol))) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Target doesn't support requested proto %u\n", protocol); return -EINVAL; @@ -2251,7 +1670,7 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, if (protocol == NFC_PROTO_NFC_DEP) { rc = pn533_activate_target_nfcdep(dev); if (rc) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Activating target with DEP failed %d\n", rc); return rc; } @@ -2268,19 +1687,19 @@ static int pn533_deactivate_target_complete(struct pn533 *dev, void *arg, { int rc = 0; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_err(&dev->interface->dev, "Target release error %d\n", rc); + nfc_err(dev->dev, "Target release error %d\n", rc); return rc; } rc = resp->data[0] & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error 0x%x when releasing the target\n", rc); dev_kfree_skb(resp); @@ -2294,10 +1713,10 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, "There is no active target\n"); + nfc_err(dev->dev, "There is no active target\n"); return; } @@ -2314,10 +1733,8 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, pn533_deactivate_target_complete, NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_err(&dev->interface->dev, "Target release error %d\n", rc); + nfc_err(dev->dev, "Target release error %d\n", rc); } - - return; } @@ -2336,7 +1753,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (dev->tgt_available_prots && !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "The target does not support DEP\n"); rc = -EINVAL; goto error; @@ -2346,7 +1763,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Bringing DEP link up failed (error 0x%x)\n", rc); goto error; } @@ -2354,7 +1771,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (!dev->tgt_available_prots) { struct nfc_target nfc_target; - dev_dbg(&dev->interface->dev, "Creating new target\n"); + dev_dbg(dev->dev, "Creating new target\n"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; @@ -2392,16 +1809,16 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE]; u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (dev->poll_mod_count) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot bring the DEP link up while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "There is already an active target\n"); return -EBUSY; } @@ -2472,12 +1889,12 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); pn533_poll_reset_mod_list(dev); if (dev->tgt_mode || dev->tgt_active_prot) - pn533_abort_cmd(dev, GFP_KERNEL); + dev->phy_ops->abort_cmd(dev, GFP_KERNEL); dev->tgt_active_prot = 0; dev->tgt_mode = 0; @@ -2497,7 +1914,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) struct sk_buff *skb, *tmp, *t; unsigned int skb_len = 0, tmp_len = 0; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (skb_queue_empty(&dev->resp_q)) return NULL; @@ -2510,7 +1927,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) skb_queue_walk_safe(&dev->resp_q, tmp, t) skb_len += tmp->len; - dev_dbg(&dev->interface->dev, "%s total length %d\n", + dev_dbg(dev->dev, "%s total length %d\n", __func__, skb_len); skb = alloc_skb(skb_len, GFP_KERNEL); @@ -2538,7 +1955,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, int rc = 0; u8 status, ret, mi; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -2552,7 +1969,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, skb_pull(resp, sizeof(status)); if (ret != PN533_CMD_RET_SUCCESS) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Exchanging data failed (error 0x%x)\n", ret); rc = -EIO; goto error; @@ -2593,6 +2010,43 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, return rc; } +/* + * Receive an incoming pn533 frame. skb contains only header and payload. + * If skb == NULL, it is a notification that the link below is dead. + */ +void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status) +{ + dev->cmd->status = status; + + if (skb == NULL) { + pr_err("NULL Frame -> link is dead\n"); + goto sched_wq; + } + + if (pn533_rx_frame_is_ack(skb->data)) { + dev_dbg(dev->dev, "%s: Received ACK frame\n", __func__); + dev_kfree_skb(skb); + return; + } + + print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, skb->data, + dev->ops->rx_frame_size(skb->data), false); + + if (!dev->ops->rx_is_frame_valid(skb->data, dev)) { + nfc_err(dev->dev, "Received an invalid frame\n"); + dev->cmd->status = -EIO; + } else if (!pn533_rx_frame_is_cmd_response(dev, skb->data)) { + nfc_err(dev->dev, "It it not the response to the last command\n"); + dev->cmd->status = -EIO; + } + + dev->cmd->resp = skb; + +sched_wq: + queue_work(dev->wq, &dev->cmd_complete_work); +} +EXPORT_SYMBOL(pn533_recv_frame); + /* Split the Tx skb into small chunks */ static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb) { @@ -2648,10 +2102,10 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, struct pn533_data_exchange_arg *arg = NULL; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Can't exchange data if there is no active target\n"); rc = -EINVAL; goto error; @@ -2715,7 +2169,7 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, { u8 status; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) return PTR_ERR(resp); @@ -2747,7 +2201,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); /* let's split in multiple chunks if size's too big */ if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { @@ -2785,7 +2239,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); if (!skb) @@ -2817,14 +2271,14 @@ static void pn533_wq_mi_recv(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_mi_arg); error: - pn533_send_ack(dev, GFP_KERNEL); + dev->phy_ops->send_ack(dev, GFP_KERNEL); queue_work(dev->wq, &dev->cmd_work); } @@ -2834,7 +2288,7 @@ static void pn533_wq_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); @@ -2861,7 +2315,8 @@ static void pn533_wq_mi_send(struct work_struct *work) default: /* Still some fragments? */ - rc = pn533_send_cmd_direct_async(dev,PN533_CMD_IN_DATA_EXCHANGE, + rc = pn533_send_cmd_direct_async(dev, + PN533_CMD_IN_DATA_EXCHANGE, skb, pn533_data_exchange_complete, dev->cmd_complete_dep_arg); @@ -2872,14 +2327,14 @@ static void pn533_wq_mi_send(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_dep_arg); error: - pn533_send_ack(dev, GFP_KERNEL); + dev->phy_ops->send_ack(dev, GFP_KERNEL); queue_work(dev->wq, &dev->cmd_work); } @@ -2890,7 +2345,7 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, struct sk_buff *resp; int skb_len; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ @@ -2937,7 +2392,7 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8)); if (!skb) @@ -2954,71 +2409,6 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) return 0; } -struct pn533_acr122_poweron_rdr_arg { - int rc; - struct completion done; -}; - -static void pn533_acr122_poweron_rdr_resp(struct urb *urb) -{ - struct pn533_acr122_poweron_rdr_arg *arg = urb->context; - - dev_dbg(&urb->dev->dev, "%s\n", __func__); - - print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, - urb->transfer_buffer, urb->transfer_buffer_length, - false); - - arg->rc = urb->status; - complete(&arg->done); -} - -static int pn533_acr122_poweron_rdr(struct pn533 *dev) -{ - /* Power on th reader (CCID cmd) */ - u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON, - 0, 0, 0, 0, 0, 0, 3, 0, 0}; - u8 buf[255]; - int rc; - void *cntx; - struct pn533_acr122_poweron_rdr_arg arg; - - dev_dbg(&dev->interface->dev, "%s\n", __func__); - - init_completion(&arg.done); - cntx = dev->in_urb->context; /* backup context */ - - dev->in_urb->transfer_buffer = buf; - dev->in_urb->transfer_buffer_length = 255; - dev->in_urb->complete = pn533_acr122_poweron_rdr_resp; - dev->in_urb->context = &arg; - - dev->out_urb->transfer_buffer = cmd; - dev->out_urb->transfer_buffer_length = sizeof(cmd); - - print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, - cmd, sizeof(cmd), false); - - rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); - if (rc) { - nfc_err(&dev->interface->dev, - "Reader power on cmd error %d\n", rc); - return rc; - } - - rc = usb_submit_urb(dev->in_urb, GFP_KERNEL); - if (rc) { - nfc_err(&dev->interface->dev, - "Can't submit reader poweron cmd response %d\n", rc); - return rc; - } - - wait_for_completion(&arg.done); - dev->in_urb->context = cntx; /* restore context */ - - return arg.rc; -} - static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); @@ -3030,7 +2420,7 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD, (u8 *)&rf_field, 1); if (rc) { - nfc_err(&dev->interface->dev, "Error on setting RF field\n"); + nfc_err(dev->dev, "Error on setting RF field\n"); return rc; } @@ -3083,7 +2473,7 @@ static int pn533_setup(struct pn533 *dev) break; default: - nfc_err(&dev->interface->dev, "Unknown device type %d\n", + nfc_err(dev->dev, "Unknown device type %d\n", dev->device_type); return -EINVAL; } @@ -3091,7 +2481,7 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, (u8 *)&max_retries, sizeof(max_retries)); if (rc) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error on setting MAX_RETRIES config\n"); return rc; } @@ -3100,7 +2490,7 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, (u8 *)&timing, sizeof(timing)); if (rc) { - nfc_err(&dev->interface->dev, "Error on setting RF timings\n"); + nfc_err(dev->dev, "Error on setting RF timings\n"); return rc; } @@ -3114,7 +2504,7 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, pasori_cfg, 3); if (rc) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error while settings PASORI config\n"); return rc; } @@ -3127,208 +2517,128 @@ static int pn533_setup(struct pn533 *dev) return 0; } -static int pn533_probe(struct usb_interface *interface, - const struct usb_device_id *id) +struct pn533 *pn533_register_device(u32 device_type, + u32 protocols, + enum pn533_protocol_type protocol_type, + void *phy, + struct pn533_phy_ops *phy_ops, + struct pn533_frame_ops *fops, + struct device *dev) { struct pn533_fw_version fw_ver; - struct pn533 *dev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int in_endpoint = 0; - int out_endpoint = 0; + struct pn533 *priv; int rc = -ENOMEM; - int i; - u32 protocols; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - dev->udev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; - mutex_init(&dev->cmd_lock); - - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) - in_endpoint = endpoint->bEndpointAddress; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return ERR_PTR(-ENOMEM); - if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) - out_endpoint = endpoint->bEndpointAddress; - } - - if (!in_endpoint || !out_endpoint) { - nfc_err(&interface->dev, - "Could not find bulk-in or bulk-out endpoint\n"); - rc = -ENODEV; - goto error; - } - - dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); - dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); - - if (!dev->in_urb || !dev->out_urb) - goto error; - - usb_fill_bulk_urb(dev->in_urb, dev->udev, - usb_rcvbulkpipe(dev->udev, in_endpoint), - NULL, 0, NULL, dev); - usb_fill_bulk_urb(dev->out_urb, dev->udev, - usb_sndbulkpipe(dev->udev, out_endpoint), - NULL, 0, pn533_send_complete, dev); - - INIT_WORK(&dev->cmd_work, pn533_wq_cmd); - INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete); - INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv); - INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send); - INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); - INIT_WORK(&dev->mi_tm_rx_work, pn533_wq_tm_mi_recv); - INIT_WORK(&dev->mi_tm_tx_work, pn533_wq_tm_mi_send); - INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll); - INIT_WORK(&dev->rf_work, pn533_wq_rf); - dev->wq = alloc_ordered_workqueue("pn533", 0); - if (dev->wq == NULL) + priv->phy = phy; + priv->phy_ops = phy_ops; + priv->dev = dev; + if (fops != NULL) + priv->ops = fops; + else + priv->ops = &pn533_std_frame_ops; + + priv->protocol_type = protocol_type; + priv->device_type = device_type; + + mutex_init(&priv->cmd_lock); + + INIT_WORK(&priv->cmd_work, pn533_wq_cmd); + INIT_WORK(&priv->cmd_complete_work, pn533_wq_cmd_complete); + INIT_WORK(&priv->mi_rx_work, pn533_wq_mi_recv); + INIT_WORK(&priv->mi_tx_work, pn533_wq_mi_send); + INIT_WORK(&priv->tg_work, pn533_wq_tg_get_data); + INIT_WORK(&priv->mi_tm_rx_work, pn533_wq_tm_mi_recv); + INIT_WORK(&priv->mi_tm_tx_work, pn533_wq_tm_mi_send); + INIT_DELAYED_WORK(&priv->poll_work, pn533_wq_poll); + INIT_WORK(&priv->rf_work, pn533_wq_rf); + priv->wq = alloc_ordered_workqueue("pn533", 0); + if (priv->wq == NULL) goto error; - init_timer(&dev->listen_timer); - dev->listen_timer.data = (unsigned long) dev; - dev->listen_timer.function = pn533_listen_mode_timer; - - skb_queue_head_init(&dev->resp_q); - skb_queue_head_init(&dev->fragment_skb); - - INIT_LIST_HEAD(&dev->cmd_queue); - - usb_set_intfdata(interface, dev); - - dev->ops = &pn533_std_frame_ops; - - dev->protocol_type = PN533_PROTO_REQ_ACK_RESP; - dev->device_type = id->driver_info; - switch (dev->device_type) { - case PN533_DEVICE_STD: - protocols = PN533_ALL_PROTOCOLS; - break; - - case PN533_DEVICE_PASORI: - protocols = PN533_NO_TYPE_B_PROTOCOLS; - break; + init_timer(&priv->listen_timer); + priv->listen_timer.data = (unsigned long) priv; + priv->listen_timer.function = pn533_listen_mode_timer; - case PN533_DEVICE_ACR122U: - protocols = PN533_NO_TYPE_B_PROTOCOLS; - dev->ops = &pn533_acr122_frame_ops; - dev->protocol_type = PN533_PROTO_REQ_RESP, - - rc = pn533_acr122_poweron_rdr(dev); - if (rc < 0) { - nfc_err(&dev->interface->dev, - "Couldn't poweron the reader (error %d)\n", rc); - goto destroy_wq; - } - break; + skb_queue_head_init(&priv->resp_q); + skb_queue_head_init(&priv->fragment_skb); - default: - nfc_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); - rc = -EINVAL; - goto destroy_wq; - } + INIT_LIST_HEAD(&priv->cmd_queue); memset(&fw_ver, 0, sizeof(fw_ver)); - rc = pn533_get_firmware_version(dev, &fw_ver); + rc = pn533_get_firmware_version(priv, &fw_ver); if (rc < 0) goto destroy_wq; - nfc_info(&dev->interface->dev, - "NXP PN5%02X firmware ver %d.%d now attached\n", + nfc_info(dev, "NXP PN5%02X firmware ver %d.%d now attached\n", fw_ver.ic, fw_ver.ver, fw_ver.rev); - dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, - dev->ops->tx_header_len + + priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, + priv->ops->tx_header_len + PN533_CMD_DATAEXCH_HEAD_LEN, - dev->ops->tx_tail_len); - if (!dev->nfc_dev) { + priv->ops->tx_tail_len); + if (!priv->nfc_dev) { rc = -ENOMEM; goto destroy_wq; } - nfc_set_parent_dev(dev->nfc_dev, &interface->dev); - nfc_set_drvdata(dev->nfc_dev, dev); + nfc_set_drvdata(priv->nfc_dev, priv); - rc = nfc_register_device(dev->nfc_dev); + rc = nfc_register_device(priv->nfc_dev); if (rc) goto free_nfc_dev; - rc = pn533_setup(dev); + rc = pn533_setup(priv); if (rc) goto unregister_nfc_dev; - return 0; + return priv; unregister_nfc_dev: - nfc_unregister_device(dev->nfc_dev); + nfc_unregister_device(priv->nfc_dev); free_nfc_dev: - nfc_free_device(dev->nfc_dev); + nfc_free_device(priv->nfc_dev); destroy_wq: - destroy_workqueue(dev->wq); + destroy_workqueue(priv->wq); error: - usb_free_urb(dev->in_urb); - usb_free_urb(dev->out_urb); - usb_put_dev(dev->udev); - kfree(dev); - return rc; + kfree(priv); + return ERR_PTR(rc); } +EXPORT_SYMBOL_GPL(pn533_register_device); -static void pn533_disconnect(struct usb_interface *interface) +void pn533_unregister_device(struct pn533 *priv) { - struct pn533 *dev; struct pn533_cmd *cmd, *n; - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); + nfc_unregister_device(priv->nfc_dev); + nfc_free_device(priv->nfc_dev); - nfc_unregister_device(dev->nfc_dev); - nfc_free_device(dev->nfc_dev); + flush_delayed_work(&priv->poll_work); + destroy_workqueue(priv->wq); - usb_kill_urb(dev->in_urb); - usb_kill_urb(dev->out_urb); + skb_queue_purge(&priv->resp_q); - flush_delayed_work(&dev->poll_work); - destroy_workqueue(dev->wq); + del_timer(&priv->listen_timer); - skb_queue_purge(&dev->resp_q); - - del_timer(&dev->listen_timer); - - list_for_each_entry_safe(cmd, n, &dev->cmd_queue, queue) { + list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) { list_del(&cmd->queue); kfree(cmd); } - usb_free_urb(dev->in_urb); - usb_free_urb(dev->out_urb); - kfree(dev); - - nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); + kfree(priv); } +EXPORT_SYMBOL_GPL(pn533_unregister_device); -static struct usb_driver pn533_driver = { - .name = "pn533", - .probe = pn533_probe, - .disconnect = pn533_disconnect, - .id_table = pn533_table, -}; - -module_usb_driver(pn533_driver); MODULE_AUTHOR("Lauro Ramos Venancio "); MODULE_AUTHOR("Aloisio Almeida Jr "); MODULE_AUTHOR("Waldemar Rymarkiewicz "); -MODULE_DESCRIPTION("PN533 usb driver ver " VERSION); +MODULE_DESCRIPTION("PN533 driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h new file mode 100644 index 000000000000..1d9f19eb2a99 --- /dev/null +++ b/drivers/nfc/pn533/pn533.h @@ -0,0 +1,235 @@ +/* + * Driver for NXP PN533 NFC Chip + * + * Copyright (C) 2011 Instituto Nokia de Tecnologia + * Copyright (C) 2012-2013 Tieto Poland + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#define PN533_DEVICE_STD 0x1 +#define PN533_DEVICE_PASORI 0x2 +#define PN533_DEVICE_ACR122U 0x3 + +#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\ + NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\ + NFC_PROTO_NFC_DEP_MASK |\ + NFC_PROTO_ISO14443_B_MASK) + +#define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ + NFC_PROTO_MIFARE_MASK | \ + NFC_PROTO_FELICA_MASK | \ + NFC_PROTO_ISO14443_MASK | \ + NFC_PROTO_NFC_DEP_MASK) + +/* Standard pn533 frame definitions (standard and extended)*/ +#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \ + + 2) /* data[0] TFI, data[1] CC */ +#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ + +#define PN533_EXT_FRAME_HEADER_LEN (sizeof(struct pn533_ext_frame) \ + + 2) /* data[0] TFI, data[1] CC */ + +#define PN533_CMD_DATAEXCH_HEAD_LEN 1 +#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 +#define PN533_CMD_DATAFRAME_MAXLEN 240 /* max data length (send) */ + +/* + * Max extended frame payload len, excluding TFI and CC + * which are already in PN533_FRAME_HEADER_LEN. + */ +#define PN533_STD_FRAME_MAX_PAYLOAD_LEN 263 + + +/* Preamble (1), SoPC (2), ACK Code (2), Postamble (1) */ +#define PN533_STD_FRAME_ACK_SIZE 6 +#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen]) +#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) +/* Half start code (3), LEN (4) should be 0xffff for extended frame */ +#define PN533_STD_IS_EXTENDED(hdr) ((hdr)->datalen == 0xFF \ + && (hdr)->datalen_checksum == 0xFF) +#define PN533_EXT_FRAME_CHECKSUM(f) (f->data[be16_to_cpu(f->datalen)]) + +/* start of frame */ +#define PN533_STD_FRAME_SOF 0x00FF + +/* standard frame identifier: in/out/error */ +#define PN533_STD_FRAME_IDENTIFIER(f) (f->data[0]) /* TFI */ +#define PN533_STD_FRAME_DIR_OUT 0xD4 +#define PN533_STD_FRAME_DIR_IN 0xD5 + +/* PN533 Commands */ +#define PN533_FRAME_CMD(f) (f->data[1]) + +#define PN533_CMD_GET_FIRMWARE_VERSION 0x02 +#define PN533_CMD_RF_CONFIGURATION 0x32 +#define PN533_CMD_IN_DATA_EXCHANGE 0x40 +#define PN533_CMD_IN_COMM_THRU 0x42 +#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A +#define PN533_CMD_IN_ATR 0x50 +#define PN533_CMD_IN_RELEASE 0x52 +#define PN533_CMD_IN_JUMP_FOR_DEP 0x56 + +#define PN533_CMD_TG_INIT_AS_TARGET 0x8c +#define PN533_CMD_TG_GET_DATA 0x86 +#define PN533_CMD_TG_SET_DATA 0x8e +#define PN533_CMD_TG_SET_META_DATA 0x94 +#define PN533_CMD_UNDEF 0xff + +#define PN533_CMD_RESPONSE(cmd) (cmd + 1) + +/* PN533 Return codes */ +#define PN533_CMD_RET_MASK 0x3F +#define PN533_CMD_MI_MASK 0x40 +#define PN533_CMD_RET_SUCCESS 0x00 + + +enum pn533_protocol_type { + PN533_PROTO_REQ_ACK_RESP = 0, + PN533_PROTO_REQ_RESP +}; + +/* Poll modulations */ +enum { + PN533_POLL_MOD_106KBPS_A, + PN533_POLL_MOD_212KBPS_FELICA, + PN533_POLL_MOD_424KBPS_FELICA, + PN533_POLL_MOD_106KBPS_JEWEL, + PN533_POLL_MOD_847KBPS_B, + PN533_LISTEN_MOD, + + __PN533_POLL_MOD_AFTER_LAST, +}; +#define PN533_POLL_MOD_MAX (__PN533_POLL_MOD_AFTER_LAST - 1) + +struct pn533_std_frame { + u8 preamble; + __be16 start_frame; + u8 datalen; + u8 datalen_checksum; + u8 data[]; +} __packed; + +struct pn533_ext_frame { /* Extended Information frame */ + u8 preamble; + __be16 start_frame; + __be16 eif_flag; /* fixed to 0xFFFF */ + __be16 datalen; + u8 datalen_checksum; + u8 data[]; +} __packed; + +struct pn533 { + struct nfc_dev *nfc_dev; + u32 device_type; + enum pn533_protocol_type protocol_type; + + struct sk_buff_head resp_q; + struct sk_buff_head fragment_skb; + + struct workqueue_struct *wq; + struct work_struct cmd_work; + struct work_struct cmd_complete_work; + struct delayed_work poll_work; + struct work_struct mi_rx_work; + struct work_struct mi_tx_work; + struct work_struct mi_tm_rx_work; + struct work_struct mi_tm_tx_work; + struct work_struct tg_work; + struct work_struct rf_work; + + struct list_head cmd_queue; + struct pn533_cmd *cmd; + u8 cmd_pending; + struct mutex cmd_lock; /* protects cmd queue */ + + void *cmd_complete_mi_arg; + void *cmd_complete_dep_arg; + + struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; + u8 poll_mod_count; + u8 poll_mod_curr; + u8 poll_dep; + u32 poll_protocols; + u32 listen_protocols; + struct timer_list listen_timer; + int cancel_listen; + + u8 *gb; + size_t gb_len; + + u8 tgt_available_prots; + u8 tgt_active_prot; + u8 tgt_mode; + + struct pn533_frame_ops *ops; + + struct device *dev; + void *phy; + struct pn533_phy_ops *phy_ops; +}; + +typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg, + struct sk_buff *resp); + +struct pn533_cmd { + struct list_head queue; + u8 code; + int status; + struct sk_buff *req; + struct sk_buff *resp; + pn533_send_async_complete_t complete_cb; + void *complete_cb_context; +}; + + +struct pn533_frame_ops { + void (*tx_frame_init)(void *frame, u8 cmd_code); + void (*tx_frame_finish)(void *frame); + void (*tx_update_payload_len)(void *frame, int len); + int tx_header_len; + int tx_tail_len; + + bool (*rx_is_frame_valid)(void *frame, struct pn533 *dev); + bool (*rx_frame_is_ack)(void *frame); + int (*rx_frame_size)(void *frame); + int rx_header_len; + int rx_tail_len; + + int max_payload_len; + u8 (*get_cmd_code)(void *frame); +}; + + +struct pn533_phy_ops { + int (*send_frame)(struct pn533 *priv, + struct sk_buff *out); + int (*send_ack)(struct pn533 *dev, gfp_t flags); + void (*abort_cmd)(struct pn533 *priv, gfp_t flags); +}; + + +struct pn533 *pn533_register_device(u32 device_type, + u32 protocols, + enum pn533_protocol_type protocol_type, + void *phy, + struct pn533_phy_ops *phy_ops, + struct pn533_frame_ops *fops, + struct device *dev); + +void pn533_unregister_device(struct pn533 *priv); +void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status); + +bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame); +bool pn533_rx_frame_is_ack(void *_frame); diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c new file mode 100644 index 000000000000..4f73cbf8ccef --- /dev/null +++ b/drivers/nfc/pn533/usb.c @@ -0,0 +1,598 @@ +/* + * Driver for NXP PN533 NFC Chip - USB transport layer + * + * Copyright (C) 2011 Instituto Nokia de Tecnologia + * Copyright (C) 2012-2013 Tieto Poland + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pn533.h" + +#define VERSION "0.1" + +#define PN533_VENDOR_ID 0x4CC +#define PN533_PRODUCT_ID 0x2533 + +#define SCM_VENDOR_ID 0x4E6 +#define SCL3711_PRODUCT_ID 0x5591 + +#define SONY_VENDOR_ID 0x054c +#define PASORI_PRODUCT_ID 0x02e1 + +#define ACS_VENDOR_ID 0x072f +#define ACR122U_PRODUCT_ID 0x2200 + +static const struct usb_device_id pn533_usb_table[] = { + { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID), + .driver_info = PN533_DEVICE_STD }, + { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID), + .driver_info = PN533_DEVICE_STD }, + { USB_DEVICE(SONY_VENDOR_ID, PASORI_PRODUCT_ID), + .driver_info = PN533_DEVICE_PASORI }, + { USB_DEVICE(ACS_VENDOR_ID, ACR122U_PRODUCT_ID), + .driver_info = PN533_DEVICE_ACR122U }, + { } +}; +MODULE_DEVICE_TABLE(usb, pn533_usb_table); + +struct pn533_usb_phy { + struct usb_device *udev; + struct usb_interface *interface; + + struct urb *out_urb; + struct urb *in_urb; + + struct pn533 *priv; +}; + +static void pn533_recv_response(struct urb *urb) +{ + struct pn533_usb_phy *phy = urb->context; + struct sk_buff *skb = NULL; + + if (!urb->status) { + skb = alloc_skb(urb->actual_length, GFP_KERNEL); + if (!skb) { + nfc_err(&phy->udev->dev, "failed to alloc memory\n"); + } else { + memcpy(skb_put(skb, urb->actual_length), + urb->transfer_buffer, urb->actual_length); + } + } + + pn533_recv_frame(phy->priv, skb, urb->status); +} + +static int pn533_submit_urb_for_response(struct pn533_usb_phy *phy, gfp_t flags) +{ + phy->in_urb->complete = pn533_recv_response; + + return usb_submit_urb(phy->in_urb, flags); +} + +static void pn533_recv_ack(struct urb *urb) +{ + struct pn533_usb_phy *phy = urb->context; + struct pn533 *priv = phy->priv; + struct pn533_cmd *cmd = priv->cmd; + struct pn533_std_frame *in_frame; + int rc; + + cmd->status = urb->status; + + switch (urb->status) { + case 0: + break; /* success */ + case -ECONNRESET: + case -ENOENT: + dev_dbg(&phy->udev->dev, + "The urb has been stopped (status %d)\n", + urb->status); + goto sched_wq; + case -ESHUTDOWN: + default: + nfc_err(&phy->udev->dev, + "Urb failure (status %d)\n", urb->status); + goto sched_wq; + } + + in_frame = phy->in_urb->transfer_buffer; + + if (!pn533_rx_frame_is_ack(in_frame)) { + nfc_err(&phy->udev->dev, "Received an invalid ack\n"); + cmd->status = -EIO; + goto sched_wq; + } + + rc = pn533_submit_urb_for_response(phy, GFP_ATOMIC); + if (rc) { + nfc_err(&phy->udev->dev, + "usb_submit_urb failed with result %d\n", rc); + cmd->status = rc; + goto sched_wq; + } + + return; + +sched_wq: + queue_work(priv->wq, &priv->cmd_complete_work); +} + +static int pn533_submit_urb_for_ack(struct pn533_usb_phy *phy, gfp_t flags) +{ + phy->in_urb->complete = pn533_recv_ack; + + return usb_submit_urb(phy->in_urb, flags); +} + +static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags) +{ + struct pn533_usb_phy *phy = dev->phy; + u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; + /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ + int rc; + + phy->out_urb->transfer_buffer = ack; + phy->out_urb->transfer_buffer_length = sizeof(ack); + rc = usb_submit_urb(phy->out_urb, flags); + + return rc; +} + +static int pn533_usb_send_frame(struct pn533 *dev, + struct sk_buff *out) +{ + struct pn533_usb_phy *phy = dev->phy; + int rc; + + if (phy->priv == NULL) + phy->priv = dev; + + phy->out_urb->transfer_buffer = out->data; + phy->out_urb->transfer_buffer_length = out->len; + + print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, + out->data, out->len, false); + + rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); + if (rc) + return rc; + + if (dev->protocol_type == PN533_PROTO_REQ_RESP) { + /* request for response for sent packet directly */ + rc = pn533_submit_urb_for_response(phy, GFP_ATOMIC); + if (rc) + goto error; + } else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) { + /* request for ACK if that's the case */ + rc = pn533_submit_urb_for_ack(phy, GFP_KERNEL); + if (rc) + goto error; + } + + return 0; + +error: + usb_unlink_urb(phy->out_urb); + return rc; +} + +static void pn533_usb_abort_cmd(struct pn533 *dev, gfp_t flags) +{ + struct pn533_usb_phy *phy = dev->phy; + + /* ACR122U does not support any command which aborts last + * issued command i.e. as ACK for standard PN533. Additionally, + * it behaves stange, sending broken or incorrect responses, + * when we cancel urb before the chip will send response. + */ + if (dev->device_type == PN533_DEVICE_ACR122U) + return; + + /* An ack will cancel the last issued command */ + pn533_usb_send_ack(dev, flags); + + /* cancel the urb request */ + usb_kill_urb(phy->in_urb); +} + +/* ACR122 specific structs and fucntions */ + +/* ACS ACR122 pn533 frame definitions */ +#define PN533_ACR122_TX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_tx_frame) \ + + 2) +#define PN533_ACR122_TX_FRAME_TAIL_LEN 0 +#define PN533_ACR122_RX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_rx_frame) \ + + 2) +#define PN533_ACR122_RX_FRAME_TAIL_LEN 2 +#define PN533_ACR122_FRAME_MAX_PAYLOAD_LEN PN533_STD_FRAME_MAX_PAYLOAD_LEN + +/* CCID messages types */ +#define PN533_ACR122_PC_TO_RDR_ICCPOWERON 0x62 +#define PN533_ACR122_PC_TO_RDR_ESCAPE 0x6B + +#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83 + + +struct pn533_acr122_ccid_hdr { + u8 type; + u32 datalen; + u8 slot; + u8 seq; + + /* + * 3 msg specific bytes or status, error and 1 specific + * byte for reposnse msg + */ + u8 params[3]; + u8 data[]; /* payload */ +} __packed; + +struct pn533_acr122_apdu_hdr { + u8 class; + u8 ins; + u8 p1; + u8 p2; +} __packed; + +struct pn533_acr122_tx_frame { + struct pn533_acr122_ccid_hdr ccid; + struct pn533_acr122_apdu_hdr apdu; + u8 datalen; + u8 data[]; /* pn533 frame: TFI ... */ +} __packed; + +struct pn533_acr122_rx_frame { + struct pn533_acr122_ccid_hdr ccid; + u8 data[]; /* pn533 frame : TFI ... */ +} __packed; + +static void pn533_acr122_tx_frame_init(void *_frame, u8 cmd_code) +{ + struct pn533_acr122_tx_frame *frame = _frame; + + frame->ccid.type = PN533_ACR122_PC_TO_RDR_ESCAPE; + /* sizeof(apdu_hdr) + sizeof(datalen) */ + frame->ccid.datalen = sizeof(frame->apdu) + 1; + frame->ccid.slot = 0; + frame->ccid.seq = 0; + frame->ccid.params[0] = 0; + frame->ccid.params[1] = 0; + frame->ccid.params[2] = 0; + + frame->data[0] = PN533_STD_FRAME_DIR_OUT; + frame->data[1] = cmd_code; + frame->datalen = 2; /* data[0] + data[1] */ + + frame->apdu.class = 0xFF; + frame->apdu.ins = 0; + frame->apdu.p1 = 0; + frame->apdu.p2 = 0; +} + +static void pn533_acr122_tx_frame_finish(void *_frame) +{ + struct pn533_acr122_tx_frame *frame = _frame; + + frame->ccid.datalen += frame->datalen; +} + +static void pn533_acr122_tx_update_payload_len(void *_frame, int len) +{ + struct pn533_acr122_tx_frame *frame = _frame; + + frame->datalen += len; +} + +static bool pn533_acr122_is_rx_frame_valid(void *_frame, struct pn533 *dev) +{ + struct pn533_acr122_rx_frame *frame = _frame; + + if (frame->ccid.type != 0x83) + return false; + + if (!frame->ccid.datalen) + return false; + + if (frame->data[frame->ccid.datalen - 2] == 0x63) + return false; + + return true; +} + +static int pn533_acr122_rx_frame_size(void *frame) +{ + struct pn533_acr122_rx_frame *f = frame; + + /* f->ccid.datalen already includes tail length */ + return sizeof(struct pn533_acr122_rx_frame) + f->ccid.datalen; +} + +static u8 pn533_acr122_get_cmd_code(void *frame) +{ + struct pn533_acr122_rx_frame *f = frame; + + return PN533_FRAME_CMD(f); +} + +static struct pn533_frame_ops pn533_acr122_frame_ops = { + .tx_frame_init = pn533_acr122_tx_frame_init, + .tx_frame_finish = pn533_acr122_tx_frame_finish, + .tx_update_payload_len = pn533_acr122_tx_update_payload_len, + .tx_header_len = PN533_ACR122_TX_FRAME_HEADER_LEN, + .tx_tail_len = PN533_ACR122_TX_FRAME_TAIL_LEN, + + .rx_is_frame_valid = pn533_acr122_is_rx_frame_valid, + .rx_header_len = PN533_ACR122_RX_FRAME_HEADER_LEN, + .rx_tail_len = PN533_ACR122_RX_FRAME_TAIL_LEN, + .rx_frame_size = pn533_acr122_rx_frame_size, + + .max_payload_len = PN533_ACR122_FRAME_MAX_PAYLOAD_LEN, + .get_cmd_code = pn533_acr122_get_cmd_code, +}; + +struct pn533_acr122_poweron_rdr_arg { + int rc; + struct completion done; +}; + +static void pn533_acr122_poweron_rdr_resp(struct urb *urb) +{ + struct pn533_acr122_poweron_rdr_arg *arg = urb->context; + + dev_dbg(&urb->dev->dev, "%s\n", __func__); + + print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, + urb->transfer_buffer, urb->transfer_buffer_length, + false); + + arg->rc = urb->status; + complete(&arg->done); +} + +static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) +{ + /* Power on th reader (CCID cmd) */ + u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON, + 0, 0, 0, 0, 0, 0, 3, 0, 0}; + int rc; + void *cntx; + struct pn533_acr122_poweron_rdr_arg arg; + + dev_dbg(&phy->udev->dev, "%s\n", __func__); + + init_completion(&arg.done); + cntx = phy->in_urb->context; /* backup context */ + + phy->in_urb->complete = pn533_acr122_poweron_rdr_resp; + phy->in_urb->context = &arg; + + phy->out_urb->transfer_buffer = cmd; + phy->out_urb->transfer_buffer_length = sizeof(cmd); + + print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, + cmd, sizeof(cmd), false); + + rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); + if (rc) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); + return rc; + } + + rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); + if (rc) { + nfc_err(&phy->udev->dev, + "Can't submit reader poweron cmd response %d\n", rc); + return rc; + } + + wait_for_completion(&arg.done); + phy->in_urb->context = cntx; /* restore context */ + + return arg.rc; +} + +static void pn533_send_complete(struct urb *urb) +{ + struct pn533_usb_phy *phy = urb->context; + + switch (urb->status) { + case 0: + break; /* success */ + case -ECONNRESET: + case -ENOENT: + dev_dbg(&phy->udev->dev, + "The urb has been stopped (status %d)\n", + urb->status); + break; + case -ESHUTDOWN: + default: + nfc_err(&phy->udev->dev, + "Urb failure (status %d)\n", + urb->status); + } +} + +static struct pn533_phy_ops usb_phy_ops = { + .send_frame = pn533_usb_send_frame, + .send_ack = pn533_usb_send_ack, + .abort_cmd = pn533_usb_abort_cmd, +}; + +static int pn533_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct pn533 *priv; + struct pn533_usb_phy *phy; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int in_endpoint = 0; + int out_endpoint = 0; + int rc = -ENOMEM; + int i; + u32 protocols; + enum pn533_protocol_type protocol_type = PN533_PROTO_REQ_ACK_RESP; + struct pn533_frame_ops *fops = NULL; + unsigned char *in_buf; + int in_buf_len = PN533_EXT_FRAME_HEADER_LEN + + PN533_STD_FRAME_MAX_PAYLOAD_LEN + + PN533_STD_FRAME_TAIL_LEN; + + phy = devm_kzalloc(&interface->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + in_buf = kzalloc(in_buf_len, GFP_KERNEL); + if (!in_buf) { + rc = -ENOMEM; + goto out_free_phy; + } + + phy->udev = usb_get_dev(interface_to_usbdev(interface)); + phy->interface = interface; + + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) + in_endpoint = endpoint->bEndpointAddress; + + if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) + out_endpoint = endpoint->bEndpointAddress; + } + + if (!in_endpoint || !out_endpoint) { + nfc_err(&interface->dev, + "Could not find bulk-in or bulk-out endpoint\n"); + rc = -ENODEV; + goto error; + } + + phy->in_urb = usb_alloc_urb(0, GFP_KERNEL); + phy->out_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!phy->in_urb || !phy->out_urb) + goto error; + + usb_fill_bulk_urb(phy->in_urb, phy->udev, + usb_rcvbulkpipe(phy->udev, in_endpoint), + in_buf, in_buf_len, NULL, phy); + + usb_fill_bulk_urb(phy->out_urb, phy->udev, + usb_sndbulkpipe(phy->udev, out_endpoint), + NULL, 0, pn533_send_complete, phy); + + + switch (id->driver_info) { + case PN533_DEVICE_STD: + protocols = PN533_ALL_PROTOCOLS; + break; + + case PN533_DEVICE_PASORI: + protocols = PN533_NO_TYPE_B_PROTOCOLS; + break; + + case PN533_DEVICE_ACR122U: + protocols = PN533_NO_TYPE_B_PROTOCOLS; + fops = &pn533_acr122_frame_ops; + protocol_type = PN533_PROTO_REQ_RESP, + + rc = pn533_acr122_poweron_rdr(phy); + if (rc < 0) { + nfc_err(&interface->dev, + "Couldn't poweron the reader (error %d)\n", rc); + goto error; + } + break; + + default: + nfc_err(&interface->dev, "Unknown device type %lu\n", + id->driver_info); + rc = -EINVAL; + goto error; + } + + priv = pn533_register_device(id->driver_info, protocols, protocol_type, + phy, &usb_phy_ops, fops, + &phy->udev->dev); + + if (IS_ERR(priv)) { + rc = PTR_ERR(priv); + goto error; + } + + phy->priv = priv; + nfc_set_parent_dev(priv->nfc_dev, &interface->dev); + + usb_set_intfdata(interface, phy); + + return 0; + +error: + usb_free_urb(phy->in_urb); + usb_free_urb(phy->out_urb); + usb_put_dev(phy->udev); + kfree(in_buf); +out_free_phy: + kfree(phy); + return rc; +} + +static void pn533_usb_disconnect(struct usb_interface *interface) +{ + struct pn533_usb_phy *phy = usb_get_intfdata(interface); + + if (!phy) + return; + + pn533_unregister_device(phy->priv); + + usb_set_intfdata(interface, NULL); + + usb_kill_urb(phy->in_urb); + usb_kill_urb(phy->out_urb); + + kfree(phy->in_urb->transfer_buffer); + usb_free_urb(phy->in_urb); + usb_free_urb(phy->out_urb); + + nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); +} + +static struct usb_driver pn533_usb_driver = { + .name = "pn533_usb", + .probe = pn533_usb_probe, + .disconnect = pn533_usb_disconnect, + .id_table = pn533_usb_table, +}; + +module_usb_driver(pn533_usb_driver); + +MODULE_AUTHOR("Lauro Ramos Venancio "); +MODULE_AUTHOR("Aloisio Almeida Jr "); +MODULE_AUTHOR("Waldemar Rymarkiewicz "); +MODULE_DESCRIPTION("PN533 USB driver ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); -- GitLab From dd7bedcd2673e4c8957d15d7e6e649fc6fa40206 Mon Sep 17 00:00:00 2001 From: Michael Thalmeier Date: Fri, 25 Mar 2016 15:46:54 +0100 Subject: [PATCH 1913/9938] NFC: pn533: add I2C phy driver This adds the I2C phy interface for the pn533 driver. This way the driver can be used to interact with I2C connected pn532 devices. Signed-off-by: Michael Thalmeier Signed-off-by: Samuel Ortiz --- drivers/nfc/pn533/Kconfig | 11 ++ drivers/nfc/pn533/Makefile | 2 + drivers/nfc/pn533/i2c.c | 271 +++++++++++++++++++++++++++++++++++++ drivers/nfc/pn533/pn533.c | 31 +++++ drivers/nfc/pn533/pn533.h | 2 + 5 files changed, 317 insertions(+) create mode 100644 drivers/nfc/pn533/i2c.c diff --git a/drivers/nfc/pn533/Kconfig b/drivers/nfc/pn533/Kconfig index b5a926e42f7b..d94122dd30e4 100644 --- a/drivers/nfc/pn533/Kconfig +++ b/drivers/nfc/pn533/Kconfig @@ -14,3 +14,14 @@ config NFC_PN533_USB If you choose to build a module, it'll be called pn533_usb. Say N if unsure. + +config NFC_PN533_I2C + tristate "NFC PN533 device support (I2C)" + depends on I2C + select NFC_PN533 + ---help--- + This module adds support for the NXP pn533 I2C interface. + Select this if your platform is using the I2C bus. + + If you choose to build a module, it'll be called pn533_i2c. + Say N if unsure. diff --git a/drivers/nfc/pn533/Makefile b/drivers/nfc/pn533/Makefile index 12c6be481483..51d24c622fcb 100644 --- a/drivers/nfc/pn533/Makefile +++ b/drivers/nfc/pn533/Makefile @@ -2,6 +2,8 @@ # Makefile for PN533 NFC driver # pn533_usb-objs = usb.o +pn533_i2c-objs = i2c.o obj-$(CONFIG_NFC_PN533) += pn533.o obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o +obj-$(CONFIG_NFC_PN533_I2C) += pn533_i2c.o diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c new file mode 100644 index 000000000000..9679aa52c381 --- /dev/null +++ b/drivers/nfc/pn533/i2c.c @@ -0,0 +1,271 @@ +/* + * Driver for NXP PN533 NFC Chip - I2C transport layer + * + * Copyright (C) 2011 Instituto Nokia de Tecnologia + * Copyright (C) 2012-2013 Tieto Poland + * Copyright (C) 2016 HALE electronic + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pn533.h" + +#define VERSION "0.1" + +#define PN533_I2C_DRIVER_NAME "pn533_i2c" + +struct pn533_i2c_phy { + struct i2c_client *i2c_dev; + struct pn533 *priv; + + int hard_fault; /* + * < 0 if hardware error occurred (e.g. i2c err) + * and prevents normal operation. + */ +}; + +static int pn533_i2c_send_ack(struct pn533 *dev, gfp_t flags) +{ + struct pn533_i2c_phy *phy = dev->phy; + struct i2c_client *client = phy->i2c_dev; + u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; + /* spec 6.2.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ + int rc; + + rc = i2c_master_send(client, ack, 6); + + return rc; +} + +static int pn533_i2c_send_frame(struct pn533 *dev, + struct sk_buff *out) +{ + struct pn533_i2c_phy *phy = dev->phy; + struct i2c_client *client = phy->i2c_dev; + int rc; + + if (phy->hard_fault != 0) + return phy->hard_fault; + + if (phy->priv == NULL) + phy->priv = dev; + + print_hex_dump_debug("PN533_i2c TX: ", DUMP_PREFIX_NONE, 16, 1, + out->data, out->len, false); + + rc = i2c_master_send(client, out->data, out->len); + + if (rc == -EREMOTEIO) { /* Retry, chip was in power down */ + usleep_range(6000, 10000); + rc = i2c_master_send(client, out->data, out->len); + } + + if (rc >= 0) { + if (rc != out->len) + rc = -EREMOTEIO; + else + rc = 0; + } + + return rc; +} + +static void pn533_i2c_abort_cmd(struct pn533 *dev, gfp_t flags) +{ + /* An ack will cancel the last issued command */ + pn533_i2c_send_ack(dev, flags); + + /* schedule cmd_complete_work to finish current command execution */ + if (dev->cmd != NULL) + dev->cmd->status = -ENOENT; + queue_work(dev->wq, &dev->cmd_complete_work); +} + +static int pn533_i2c_read(struct pn533_i2c_phy *phy, struct sk_buff **skb) +{ + struct i2c_client *client = phy->i2c_dev; + int len = PN533_EXT_FRAME_HEADER_LEN + + PN533_STD_FRAME_MAX_PAYLOAD_LEN + + PN533_STD_FRAME_TAIL_LEN + 1; + int r; + + *skb = alloc_skb(len, GFP_KERNEL); + if (*skb == NULL) + return -ENOMEM; + + r = i2c_master_recv(client, skb_put(*skb, len), len); + if (r != len) { + nfc_err(&client->dev, "cannot read. r=%d len=%d\n", r, len); + kfree_skb(*skb); + return -EREMOTEIO; + } + + if (!((*skb)->data[0] & 0x01)) { + nfc_err(&client->dev, "READY flag not set"); + kfree_skb(*skb); + return -EBUSY; + } + + /* remove READY byte */ + skb_pull(*skb, 1); + /* trim to frame size */ + skb_trim(*skb, phy->priv->ops->rx_frame_size((*skb)->data)); + + return 0; +} + +static irqreturn_t pn533_i2c_irq_thread_fn(int irq, void *data) +{ + struct pn533_i2c_phy *phy = data; + struct i2c_client *client; + struct sk_buff *skb = NULL; + int r; + + if (!phy || irq != phy->i2c_dev->irq) { + WARN_ON_ONCE(1); + return IRQ_NONE; + } + + client = phy->i2c_dev; + dev_dbg(&client->dev, "IRQ\n"); + + if (phy->hard_fault != 0) + return IRQ_HANDLED; + + r = pn533_i2c_read(phy, &skb); + if (r == -EREMOTEIO) { + phy->hard_fault = r; + + pn533_recv_frame(phy->priv, NULL, -EREMOTEIO); + + return IRQ_HANDLED; + } else if ((r == -ENOMEM) || (r == -EBADMSG) || (r == -EBUSY)) { + return IRQ_HANDLED; + } + + pn533_recv_frame(phy->priv, skb, 0); + + return IRQ_HANDLED; +} + +static struct pn533_phy_ops i2c_phy_ops = { + .send_frame = pn533_i2c_send_frame, + .send_ack = pn533_i2c_send_ack, + .abort_cmd = pn533_i2c_abort_cmd, +}; + + +static int pn533_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pn533_i2c_phy *phy; + struct pn533 *priv; + int r = 0; + + dev_dbg(&client->dev, "%s\n", __func__); + dev_dbg(&client->dev, "IRQ: %d\n", client->irq); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); + return -ENODEV; + } + + phy = devm_kzalloc(&client->dev, sizeof(struct pn533_i2c_phy), + GFP_KERNEL); + if (!phy) + return -ENOMEM; + + phy->i2c_dev = client; + i2c_set_clientdata(client, phy); + + r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn, + IRQF_TRIGGER_FALLING | + IRQF_SHARED | IRQF_ONESHOT, + PN533_I2C_DRIVER_NAME, phy); + + if (r < 0) + nfc_err(&client->dev, "Unable to register IRQ handler\n"); + + priv = pn533_register_device(PN533_DEVICE_PN532, + PN533_NO_TYPE_B_PROTOCOLS, + PN533_PROTO_REQ_ACK_RESP, + phy, &i2c_phy_ops, NULL, + &phy->i2c_dev->dev); + + if (IS_ERR(priv)) { + r = PTR_ERR(priv); + goto err_register; + } + + phy->priv = priv; + + return 0; + +err_register: + free_irq(client->irq, phy); + + return r; +} + +static int pn533_i2c_remove(struct i2c_client *client) +{ + struct pn533_i2c_phy *phy = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "%s\n", __func__); + + pn533_unregister_device(phy->priv); + + return 0; +} + +static const struct of_device_id of_pn533_i2c_match[] = { + { .compatible = "nxp,pn533-i2c", }, + { .compatible = "nxp,pn532-i2c", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_pn533_i2c_match); + +static struct i2c_device_id pn533_i2c_id_table[] = { + { PN533_I2C_DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pn533_i2c_id_table); + +static struct i2c_driver pn533_i2c_driver = { + .driver = { + .name = PN533_I2C_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(of_pn533_i2c_match), + }, + .probe = pn533_i2c_probe, + .id_table = pn533_i2c_id_table, + .remove = pn533_i2c_remove, +}; + +module_i2c_driver(pn533_i2c_driver); + +MODULE_AUTHOR("Michael Thalmeier "); +MODULE_DESCRIPTION("PN533 I2C driver ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index 52d83fec5add..ee9e8f1195fa 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -2427,8 +2427,37 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) return rc; } +static int pn532_sam_configuration(struct nfc_dev *nfc_dev) +{ + struct pn533 *dev = nfc_get_drvdata(nfc_dev); + struct sk_buff *skb; + struct sk_buff *resp; + + skb = pn533_alloc_skb(dev, 1); + if (!skb) + return -ENOMEM; + + *skb_put(skb, 1) = 0x01; + + resp = pn533_send_cmd_sync(dev, PN533_CMD_SAM_CONFIGURATION, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); + + dev_kfree_skb(resp); + return 0; +} + static int pn533_dev_up(struct nfc_dev *nfc_dev) { + struct pn533 *dev = nfc_get_drvdata(nfc_dev); + + if (dev->device_type == PN533_DEVICE_PN532) { + int rc = pn532_sam_configuration(nfc_dev); + + if (rc) + return rc; + } + return pn533_rf_field(nfc_dev, 1); } @@ -2461,6 +2490,7 @@ static int pn533_setup(struct pn533 *dev) case PN533_DEVICE_STD: case PN533_DEVICE_PASORI: case PN533_DEVICE_ACR122U: + case PN533_DEVICE_PN532: max_retries.mx_rty_atr = 0x2; max_retries.mx_rty_psl = 0x1; max_retries.mx_rty_passive_act = @@ -2496,6 +2526,7 @@ static int pn533_setup(struct pn533 *dev) switch (dev->device_type) { case PN533_DEVICE_STD: + case PN533_DEVICE_PN532: break; case PN533_DEVICE_PASORI: diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h index 1d9f19eb2a99..ba604f6d93f9 100644 --- a/drivers/nfc/pn533/pn533.h +++ b/drivers/nfc/pn533/pn533.h @@ -21,6 +21,7 @@ #define PN533_DEVICE_STD 0x1 #define PN533_DEVICE_PASORI 0x2 #define PN533_DEVICE_ACR122U 0x3 +#define PN533_DEVICE_PN532 0x4 #define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\ NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\ @@ -73,6 +74,7 @@ #define PN533_FRAME_CMD(f) (f->data[1]) #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 +#define PN533_CMD_SAM_CONFIGURATION 0x14 #define PN533_CMD_RF_CONFIGURATION 0x32 #define PN533_CMD_IN_DATA_EXCHANGE 0x40 #define PN533_CMD_IN_COMM_THRU 0x42 -- GitLab From fbbc5e7044f761652e1e83037bd90574976337a3 Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Sun, 10 Apr 2016 13:23:09 +0200 Subject: [PATCH 1914/9938] iio: potentiometer: add driver for Maxim Integrated DS1803 The following functions are supported: - write, read potentiometer value - potentiometer scale Datasheet: https://datasheets.maximintegrated.com/en/ds/DS1803.pdf Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- .../bindings/iio/potentiometer/ds1803.txt | 21 +++ drivers/iio/potentiometer/Kconfig | 10 + drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/ds1803.c | 173 ++++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt create mode 100644 drivers/iio/potentiometer/ds1803.c diff --git a/Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt b/Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt new file mode 100644 index 000000000000..df77bf552656 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt @@ -0,0 +1,21 @@ +* Maxim Integrated DS1803 digital potentiometer driver + +The node for this driver must be a child node of a I2C controller, hence +all mandatory properties for your controller must be specified. See directory: + + Documentation/devicetree/bindings/i2c + +for more details. + +Required properties: + - compatible: Must be one of the following, depending on the + model: + "maxim,ds1803-010", + "maxim,ds1803-050", + "maxim,ds1803-100" + +Example: +ds1803: ds1803@1 { + reg = <0x28>; + compatible = "maxim,ds1803-010"; +}; diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig index 7ea069bbca2d..6acb23810bb4 100644 --- a/drivers/iio/potentiometer/Kconfig +++ b/drivers/iio/potentiometer/Kconfig @@ -5,6 +5,16 @@ menu "Digital potentiometers" +config DS1803 + tristate "Maxim Integrated DS1803 Digital Potentiometer driver" + depends on I2C + help + Say yes here to build support for the Maxim Integrated DS1803 + digital potentiomenter chip. + + To compile this driver as a module, choose M here: the + module will be called ds1803. + config MCP4131 tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver" depends on SPI diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile index 91a80f8db24d..6007faa2fb02 100644 --- a/drivers/iio/potentiometer/Makefile +++ b/drivers/iio/potentiometer/Makefile @@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_DS1803) += ds1803.o obj-$(CONFIG_MCP4131) += mcp4131.o obj-$(CONFIG_MCP4531) += mcp4531.o obj-$(CONFIG_TPL0102) += tpl0102.o diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c new file mode 100644 index 000000000000..fb9e2a337dc2 --- /dev/null +++ b/drivers/iio/potentiometer/ds1803.c @@ -0,0 +1,173 @@ +/* + * Maxim Integrated DS1803 digital potentiometer driver + * Copyright (c) 2016 Slawomir Stepien + * + * Datasheet: https://datasheets.maximintegrated.com/en/ds/DS1803.pdf + * + * DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address + * ds1803 2 256 10, 50, 100 0101xxx + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#define DS1803_MAX_POS 255 +#define DS1803_WRITE(chan) (0xa8 | ((chan) + 1)) + +enum ds1803_type { + DS1803_010, + DS1803_050, + DS1803_100, +}; + +struct ds1803_cfg { + int kohms; +}; + +static const struct ds1803_cfg ds1803_cfg[] = { + [DS1803_010] = { .kohms = 10, }, + [DS1803_050] = { .kohms = 50, }, + [DS1803_100] = { .kohms = 100, }, +}; + +struct ds1803_data { + struct i2c_client *client; + const struct ds1803_cfg *cfg; +}; + +#define DS1803_CHANNEL(ch) { \ + .type = IIO_RESISTANCE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (ch), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec ds1803_channels[] = { + DS1803_CHANNEL(0), + DS1803_CHANNEL(1), +}; + +static int ds1803_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ds1803_data *data = iio_priv(indio_dev); + int pot = chan->channel; + int ret; + u8 result[indio_dev->num_channels]; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_master_recv(data->client, result, + indio_dev->num_channels); + if (ret < 0) + return ret; + + *val = result[pot]; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = 1000 * data->cfg->kohms; + *val2 = DS1803_MAX_POS; + return IIO_VAL_FRACTIONAL; + } + + return -EINVAL; +} + +static int ds1803_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct ds1803_data *data = iio_priv(indio_dev); + int pot = chan->channel; + + if (val2 != 0) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val > DS1803_MAX_POS || val < 0) + return -EINVAL; + break; + default: + return -EINVAL; + } + + return i2c_smbus_write_byte_data(data->client, DS1803_WRITE(pot), val); +} + +static const struct iio_info ds1803_info = { + .read_raw = ds1803_read_raw, + .write_raw = ds1803_write_raw, + .driver_module = THIS_MODULE, +}; + +static int ds1803_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct ds1803_data *data; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + i2c_set_clientdata(client, indio_dev); + + data = iio_priv(indio_dev); + data->client = client; + data->cfg = &ds1803_cfg[id->driver_data]; + + indio_dev->dev.parent = dev; + indio_dev->info = &ds1803_info; + indio_dev->channels = ds1803_channels; + indio_dev->num_channels = ARRAY_SIZE(ds1803_channels); + indio_dev->name = client->name; + + return devm_iio_device_register(dev, indio_dev); +} + +#if defined(CONFIG_OF) +static const struct of_device_id ds1803_dt_ids[] = { + { .compatible = "maxim,ds1803-010", .data = &ds1803_cfg[DS1803_010] }, + { .compatible = "maxim,ds1803-050", .data = &ds1803_cfg[DS1803_050] }, + { .compatible = "maxim,ds1803-100", .data = &ds1803_cfg[DS1803_100] }, + {} +}; +MODULE_DEVICE_TABLE(of, ds1803_dt_ids); +#endif /* CONFIG_OF */ + +static const struct i2c_device_id ds1803_id[] = { + { "ds1803-010", DS1803_010 }, + { "ds1803-050", DS1803_050 }, + { "ds1803-100", DS1803_100 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ds1803_id); + +static struct i2c_driver ds1803_driver = { + .driver = { + .name = "ds1803", + .of_match_table = of_match_ptr(ds1803_dt_ids), + }, + .probe = ds1803_probe, + .id_table = ds1803_id, +}; + +module_i2c_driver(ds1803_driver); + +MODULE_AUTHOR("Slawomir Stepien "); +MODULE_DESCRIPTION("DS1803 digital potentiometer"); +MODULE_LICENSE("GPL v2"); -- GitLab From 332868624c2b863e23bb192b0821605f5d0f084c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 9 Apr 2016 15:22:41 +0200 Subject: [PATCH 1915/9938] ARM: dts: sun8i: Add dts file for the Orange Pi One SBC The Orange Pi One SBC, is a stripped down version of the popular Orange Pi PC. The one is a H3 based SBC, with 512M of RAM, micro-sd slot, 1 host usb, 1 otg usb, hdmi and 100Mbit ethernet. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 145 ++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-one.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9208da82459d..e06a5abe86bc 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -720,6 +720,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a83t-allwinner-h8homlet-v2.dtb \ sun8i-a83t-cubietruck-plus.dtb \ sun8i-h3-orangepi-2.dtb \ + sun8i-h3-orangepi-one.dtb \ sun8i-h3-orangepi-pc.dtb \ sun8i-h3-orangepi-plus.dtb dtb-$(CONFIG_MACH_SUN9I) += \ diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts new file mode 100644 index 000000000000..0adf932fd923 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2016 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun8i-h3.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Xunlong Orange Pi One"; + compatible = "xunlong,orangepi-one", "allwinner,sun8i-h3"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_opc>, <&leds_r_opc>; + + pwr_led { + label = "orangepi:green:pwr"; + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + status_led { + label = "orangepi:red:status"; + gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; + }; + }; + + r_gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&sw_r_opc>; + + sw4 { + label = "sw4"; + linux,code = ; + gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&ehci1 { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ + cd-inverted; + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + leds_opc: led_pins@0 { + allwinner,pins = "PA15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&r_pio { + leds_r_opc: led_pins@0 { + allwinner,pins = "PL10"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + sw_r_opc: key_pins@0 { + allwinner,pins = "PL3"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + /* USB VBUS is always on */ + status = "okay"; +}; -- GitLab From bc11ca4a0b84a2f2ebaca2614b92998738d13b1e Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Fri, 8 Apr 2016 17:09:08 +0200 Subject: [PATCH 1916/9938] iio:magnetometer:ak8975: triggered buffer support This will be used together with an external trigger (e.g hrtimer based software trigger). Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/Kconfig | 2 + drivers/iio/magnetometer/ak8975.c | 135 ++++++++++++++++++++++++------ 2 files changed, 112 insertions(+), 25 deletions(-) diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 021dc5361f53..d9834ed023db 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -9,6 +9,8 @@ config AK8975 tristate "Asahi Kasei AK 3-Axis Magnetometer" depends on I2C depends on GPIOLIB || COMPILE_TEST + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Asahi Kasei AK8975, AK8963, AK09911 or AK09912 3-Axis Magnetometer. diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 48d127a45d90..1e6898141f88 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -36,6 +36,12 @@ #include #include +#include +#include +#include +#include +#include + /* * Register definitions, as well as various shifts and masks to get at the * individual fields of the registers. @@ -633,22 +639,15 @@ static int wait_conversion_complete_interrupt(struct ak8975_data *data) return ret > 0 ? 0 : -ETIME; } -/* - * Emits the raw flux value for the x, y, or z axis. - */ -static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) +static int ak8975_start_read_axis(struct ak8975_data *data, + const struct i2c_client *client) { - struct ak8975_data *data = iio_priv(indio_dev); - struct i2c_client *client = data->client; - int ret; - - mutex_lock(&data->lock); - /* Set up the device for taking a sample. */ - ret = ak8975_set_mode(data, MODE_ONCE); + int ret = ak8975_set_mode(data, MODE_ONCE); + if (ret < 0) { dev_err(&client->dev, "Error in setting operating mode\n"); - goto exit; + return ret; } /* Wait for the conversion to complete. */ @@ -659,7 +658,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) else ret = wait_conversion_complete_polled(data); if (ret < 0) - goto exit; + return ret; /* This will be executed only for non-interrupt based waiting case */ if (ret & data->def->ctrl_masks[ST1_DRDY]) { @@ -667,32 +666,45 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) data->def->ctrl_regs[ST2]); if (ret < 0) { dev_err(&client->dev, "Error in reading ST2\n"); - goto exit; + return ret; } if (ret & (data->def->ctrl_masks[ST2_DERR] | data->def->ctrl_masks[ST2_HOFL])) { dev_err(&client->dev, "ST2 status error 0x%x\n", ret); - ret = -EINVAL; - goto exit; + return -EINVAL; } } - /* Read the flux value from the appropriate register - (the register is specified in the iio device attributes). */ - ret = i2c_smbus_read_word_data(client, data->def->data_regs[index]); - if (ret < 0) { - dev_err(&client->dev, "Read axis data fails\n"); + return 0; +} + +/* Retrieve raw flux value for one of the x, y, or z axis. */ +static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) +{ + struct ak8975_data *data = iio_priv(indio_dev); + const struct i2c_client *client = data->client; + const struct ak_def *def = data->def; + int ret; + + mutex_lock(&data->lock); + + ret = ak8975_start_read_axis(data, client); + if (ret) + goto exit; + + ret = i2c_smbus_read_word_data(client, def->data_regs[index]); + if (ret < 0) goto exit; - } mutex_unlock(&data->lock); /* Clamp to valid range. */ - *val = clamp_t(s16, ret, -data->def->range, data->def->range); + *val = clamp_t(s16, ret, -def->range, def->range); return IIO_VAL_INT; exit: mutex_unlock(&data->lock); + dev_err(&client->dev, "Error in reading axis\n"); return ret; } @@ -722,12 +734,22 @@ static int ak8975_read_raw(struct iio_dev *indio_dev, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE), \ .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU \ + } \ } static const struct iio_chan_spec ak8975_channels[] = { AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), }; +static const unsigned long ak8975_scan_masks[] = { 0x7, 0 }; + static const struct iio_info ak8975_info = { .read_raw = &ak8975_read_raw, .driver_module = THIS_MODULE, @@ -756,6 +778,56 @@ static const char *ak8975_match_acpi_device(struct device *dev, return dev_name(dev); } +static void ak8975_fill_buffer(struct iio_dev *indio_dev) +{ + struct ak8975_data *data = iio_priv(indio_dev); + const struct i2c_client *client = data->client; + const struct ak_def *def = data->def; + int ret; + s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */ + + mutex_lock(&data->lock); + + ret = ak8975_start_read_axis(data, client); + if (ret) + goto unlock; + + /* + * For each axis, read the flux value from the appropriate register + * (the register is specified in the iio device attributes). + */ + ret = i2c_smbus_read_i2c_block_data_or_emulated(client, + def->data_regs[0], + 3 * sizeof(buff[0]), + (u8 *)buff); + if (ret < 0) + goto unlock; + + mutex_unlock(&data->lock); + + /* Clamp to valid range. */ + buff[0] = clamp_t(s16, le16_to_cpu(buff[0]), -def->range, def->range); + buff[1] = clamp_t(s16, le16_to_cpu(buff[1]), -def->range, def->range); + buff[2] = clamp_t(s16, le16_to_cpu(buff[2]), -def->range, def->range); + + iio_push_to_buffers_with_timestamp(indio_dev, buff, iio_get_time_ns()); + return; + +unlock: + mutex_unlock(&data->lock); + dev_err(&client->dev, "Error in reading axes block\n"); +} + +static irqreturn_t ak8975_handle_trigger(int irq, void *p) +{ + const struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + + ak8975_fill_buffer(indio_dev); + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + static int ak8975_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -845,15 +917,27 @@ static int ak8975_probe(struct i2c_client *client, indio_dev->channels = ak8975_channels; indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); indio_dev->info = &ak8975_info; + indio_dev->available_scan_masks = ak8975_scan_masks; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = name; - err = iio_device_register(indio_dev); - if (err) + err = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger, + NULL); + if (err) { + dev_err(&client->dev, "triggered buffer setup failed\n"); goto power_off; + } + + err = iio_device_register(indio_dev); + if (err) { + dev_err(&client->dev, "device register failed\n"); + goto cleanup_buffer; + } return 0; +cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); power_off: ak8975_power_off(client); return err; @@ -864,6 +948,7 @@ static int ak8975_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); ak8975_power_off(client); return 0; -- GitLab From 5ea9274b8613f87120bfa6b0c0abc384c26cefb9 Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 10 Apr 2016 13:03:18 +0000 Subject: [PATCH 1917/9938] iio: mxs-lradc: Move binding document out of staging as well commit f836c45922446df872250a12dd08e48978aceb2f moved mxs-lradc driver out of staging. However the binding document was left in the old place. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/{staging => }/iio/adc/mxs-lradc.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/{staging => }/iio/adc/mxs-lradc.txt (100%) diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/iio/adc/mxs-lradc.txt similarity index 100% rename from Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt rename to Documentation/devicetree/bindings/iio/adc/mxs-lradc.txt -- GitLab From 56ca9db862bf3d78e279d424b3434d66617c27ae Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 5 Apr 2016 09:46:19 +0200 Subject: [PATCH 1918/9938] iio: dac: Add support for the AD5592R/AD5593R ADCs/DACs This patch adds support for the AD5592R (spi) and AD5593R (i2c) ADC/DAC/GPIO devices. Signed-off-by: Paul Cercueil Signed-off-by: Michael Hennerich Reviewed-by: Linus Walleij Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/dac/ad5592r.txt | 155 ++++ drivers/iio/dac/Kconfig | 27 + drivers/iio/dac/Makefile | 3 + drivers/iio/dac/ad5592r-base.c | 691 ++++++++++++++++++ drivers/iio/dac/ad5592r-base.h | 76 ++ drivers/iio/dac/ad5592r.c | 164 +++++ drivers/iio/dac/ad5593r.c | 131 ++++ include/dt-bindings/iio/adi,ad5592r.h | 16 + 8 files changed, 1263 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/dac/ad5592r.txt create mode 100644 drivers/iio/dac/ad5592r-base.c create mode 100644 drivers/iio/dac/ad5592r-base.h create mode 100644 drivers/iio/dac/ad5592r.c create mode 100644 drivers/iio/dac/ad5593r.c create mode 100644 include/dt-bindings/iio/adi,ad5592r.h diff --git a/Documentation/devicetree/bindings/iio/dac/ad5592r.txt b/Documentation/devicetree/bindings/iio/dac/ad5592r.txt new file mode 100644 index 000000000000..989f96f31c66 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/dac/ad5592r.txt @@ -0,0 +1,155 @@ +Analog Devices AD5592R/AD5593R DAC/ADC device driver + +Required properties for the AD5592R: + - compatible: Must be "adi,ad5592r" + - reg: SPI chip select number for the device + - spi-max-frequency: Max SPI frequency to use (< 30000000) + - spi-cpol: The AD5592R requires inverse clock polarity (CPOL) mode + +Required properties for the AD5593R: + - compatible: Must be "adi,ad5593r" + - reg: I2C address of the device + +Required properties for all supported chips: + - #address-cells: Should be 1. + - #size-cells: Should be 0. + - channel nodes: + Each child node represents one channel and has the following + Required properties: + * reg: Pin on which this channel is connected to. + * adi,mode: Mode or function of this channel. + Macros specifying the valid values + can be found in . + + The following values are currently supported: + * CH_MODE_UNUSED (the pin is unused) + * CH_MODE_ADC (the pin is ADC input) + * CH_MODE_DAC (the pin is DAC output) + * CH_MODE_DAC_AND_ADC (the pin is DAC output + but can be monitored by an ADC, since + there is no disadvantage this + this should be considered as the + preferred DAC mode) + * CH_MODE_GPIO (the pin is registered + with GPIOLIB) + Optional properties: + * adi,off-state: State of this channel when unused or the + device gets removed. Macros specifying the + valid values can be found in + . + + * CH_OFFSTATE_PULLDOWN (the pin is pulled down) + * CH_OFFSTATE_OUT_LOW (the pin is output low) + * CH_OFFSTATE_OUT_HIGH (the pin is output high) + * CH_OFFSTATE_OUT_TRISTATE (the pin is + tristated output) + + +Optional properties: + - vref-supply: Phandle to the external reference voltage supply. This should + only be set if there is an external reference voltage connected to the VREF + pin. If the property is not set the internal 2.5V reference is used. + - reset-gpios : GPIO spec for the RESET pin. If specified, it will be + asserted during driver probe. + - gpio-controller: Marks the device node as a GPIO controller. + - #gpio-cells: Should be 2. The first cell is the GPIO number and the second + cell specifies GPIO flags, as defined in . + +AD5592R Example: + + #include + + vref: regulator-vref { + compatible = "regulator-fixed"; + regulator-name = "vref-ad559x"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + ad5592r@0 { + #size-cells = <0>; + #address-cells = <1>; + #gpio-cells = <2>; + compatible = "adi,ad5592r"; + reg = <0>; + + spi-max-frequency = <1000000>; + spi-cpol; + + vref-supply = <&vref>; /* optional */ + reset-gpios = <&gpio0 86 0>; /* optional */ + gpio-controller; + + channel@0 { + reg = <0>; + adi,mode = ; + }; + channel@1 { + reg = <1>; + adi,mode = ; + }; + channel@2 { + reg = <2>; + adi,mode = ; + }; + channel@3 { + reg = <3>; + adi,mode = ; + adi,off-state = ; + }; + channel@4 { + reg = <4>; + adi,mode = ; + adi,off-state = ; + }; + channel@5 { + reg = <5>; + adi,mode = ; + adi,off-state = ; + }; + channel@6 { + reg = <6>; + adi,mode = ; + adi,off-state = ; + }; + channel@7 { + reg = <7>; + adi,mode = ; + adi,off-state = ; + }; + }; + +AD5593R Example: + + #include + + ad5593r@10 { + #size-cells = <0>; + #address-cells = <1>; + #gpio-cells = <2>; + compatible = "adi,ad5593r"; + reg = <0x10>; + gpio-controller; + + channel@0 { + reg = <0>; + adi,mode = ; + adi,off-state = ; + }; + channel@1 { + reg = <1>; + adi,mode = ; + adi,off-state = ; + }; + channel@2 { + reg = <2>; + adi,mode = ; + adi,off-state = ; + }; + channel@6 { + reg = <6>; + adi,mode = ; + adi,off-state = ; + }; + }; diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 210db81ca144..61d5008bff5c 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -74,6 +74,33 @@ config AD5449 To compile this driver as a module, choose M here: the module will be called ad5449. +config AD5592R_BASE + tristate + +config AD5592R + tristate "Analog Devices AD5592R ADC/DAC driver" + depends on SPI_MASTER + select GPIOLIB + select AD5592R_BASE + help + Say yes here to build support for Analog Devices AD5592R + Digital to Analog / Analog to Digital Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5592r. + +config AD5593R + tristate "Analog Devices AD5593R ADC/DAC driver" + depends on I2C + select GPIOLIB + select AD5592R_BASE + help + Say yes here to build support for Analog Devices AD5593R + Digital to Analog / Analog to Digital Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5593r. + config AD5504 tristate "Analog Devices AD5504/AD5501 DAC SPI driver" depends on SPI diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 420a15cdaa53..8b78d5ca9b11 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -11,6 +11,9 @@ obj-$(CONFIG_AD5064) += ad5064.o obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o obj-$(CONFIG_AD5449) += ad5449.o +obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o +obj-$(CONFIG_AD5592R) += ad5592r.o +obj-$(CONFIG_AD5593R) += ad5593r.o obj-$(CONFIG_AD5755) += ad5755.o obj-$(CONFIG_AD5761) += ad5761.o obj-$(CONFIG_AD5764) += ad5764.o diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c new file mode 100644 index 000000000000..948f600e7059 --- /dev/null +++ b/drivers/iio/dac/ad5592r-base.c @@ -0,0 +1,691 @@ +/* + * AD5592R Digital <-> Analog converters driver + * + * Copyright 2014-2016 Analog Devices Inc. + * Author: Paul Cercueil + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ad5592r-base.h" + +static int ad5592r_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct ad5592r_state *st = gpiochip_get_data(chip); + int ret = 0; + u8 val; + + mutex_lock(&st->gpio_lock); + + if (st->gpio_out & BIT(offset)) + val = st->gpio_val; + else + ret = st->ops->gpio_read(st, &val); + + mutex_unlock(&st->gpio_lock); + + if (ret < 0) + return ret; + + return !!(val & BIT(offset)); +} + +static void ad5592r_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct ad5592r_state *st = gpiochip_get_data(chip); + + mutex_lock(&st->gpio_lock); + + if (value) + st->gpio_val |= BIT(offset); + else + st->gpio_val &= ~BIT(offset); + + st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); + + mutex_unlock(&st->gpio_lock); +} + +static int ad5592r_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct ad5592r_state *st = gpiochip_get_data(chip); + int ret; + + mutex_lock(&st->gpio_lock); + + st->gpio_out &= ~BIT(offset); + st->gpio_in |= BIT(offset); + + ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); + if (ret < 0) + goto err_unlock; + + ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); + +err_unlock: + mutex_unlock(&st->gpio_lock); + + return ret; +} + +static int ad5592r_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct ad5592r_state *st = gpiochip_get_data(chip); + int ret; + + mutex_lock(&st->gpio_lock); + + if (value) + st->gpio_val |= BIT(offset); + else + st->gpio_val &= ~BIT(offset); + + st->gpio_in &= ~BIT(offset); + st->gpio_out |= BIT(offset); + + ret = st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); + if (ret < 0) + goto err_unlock; + + ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); + if (ret < 0) + goto err_unlock; + + ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); + +err_unlock: + mutex_unlock(&st->gpio_lock); + + return ret; +} + +static int ad5592r_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct ad5592r_state *st = gpiochip_get_data(chip); + + if (!(st->gpio_map & BIT(offset))) { + dev_err(st->dev, "GPIO %d is reserved by alternate function\n", + offset); + return -ENODEV; + } + + return 0; +} + +static int ad5592r_gpio_init(struct ad5592r_state *st) +{ + if (!st->gpio_map) + return 0; + + st->gpiochip.label = dev_name(st->dev); + st->gpiochip.base = -1; + st->gpiochip.ngpio = 8; + st->gpiochip.parent = st->dev; + st->gpiochip.can_sleep = true; + st->gpiochip.direction_input = ad5592r_gpio_direction_input; + st->gpiochip.direction_output = ad5592r_gpio_direction_output; + st->gpiochip.get = ad5592r_gpio_get; + st->gpiochip.set = ad5592r_gpio_set; + st->gpiochip.request = ad5592r_gpio_request; + st->gpiochip.owner = THIS_MODULE; + + mutex_init(&st->gpio_lock); + + return gpiochip_add_data(&st->gpiochip, st); +} + +static void ad5592r_gpio_cleanup(struct ad5592r_state *st) +{ + if (st->gpio_map) + gpiochip_remove(&st->gpiochip); +} + +static int ad5592r_reset(struct ad5592r_state *st) +{ + struct gpio_desc *gpio; + struct iio_dev *iio_dev = iio_priv_to_dev(st); + + gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + + if (gpio) { + udelay(1); + gpiod_set_value(gpio, 1); + } else { + mutex_lock(&iio_dev->mlock); + /* Writing this magic value resets the device */ + st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac); + mutex_unlock(&iio_dev->mlock); + } + + udelay(250); + + return 0; +} + +static int ad5592r_get_vref(struct ad5592r_state *st) +{ + int ret; + + if (st->reg) { + ret = regulator_get_voltage(st->reg); + if (ret < 0) + return ret; + + return ret / 1000; + } else { + return 2500; + } +} + +static int ad5592r_set_channel_modes(struct ad5592r_state *st) +{ + const struct ad5592r_rw_ops *ops = st->ops; + int ret; + unsigned i; + struct iio_dev *iio_dev = iio_priv_to_dev(st); + u8 pulldown = 0, tristate = 0, dac = 0, adc = 0; + u16 read_back; + + for (i = 0; i < st->num_channels; i++) { + switch (st->channel_modes[i]) { + case CH_MODE_DAC: + dac |= BIT(i); + break; + + case CH_MODE_ADC: + adc |= BIT(i); + break; + + case CH_MODE_DAC_AND_ADC: + dac |= BIT(i); + adc |= BIT(i); + break; + + case CH_MODE_GPIO: + st->gpio_map |= BIT(i); + st->gpio_in |= BIT(i); /* Default to input */ + break; + + case CH_MODE_UNUSED: + /* fall-through */ + default: + switch (st->channel_offstate[i]) { + case CH_OFFSTATE_OUT_TRISTATE: + tristate |= BIT(i); + break; + + case CH_OFFSTATE_OUT_LOW: + st->gpio_out |= BIT(i); + break; + + case CH_OFFSTATE_OUT_HIGH: + st->gpio_out |= BIT(i); + st->gpio_val |= BIT(i); + break; + + case CH_OFFSTATE_PULLDOWN: + /* fall-through */ + default: + pulldown |= BIT(i); + break; + } + } + } + + mutex_lock(&iio_dev->mlock); + + /* Pull down unused pins to GND */ + ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown); + if (ret) + goto err_unlock; + + ret = ops->reg_write(st, AD5592R_REG_TRISTATE, tristate); + if (ret) + goto err_unlock; + + /* Configure pins that we use */ + ret = ops->reg_write(st, AD5592R_REG_DAC_EN, dac); + if (ret) + goto err_unlock; + + ret = ops->reg_write(st, AD5592R_REG_ADC_EN, adc); + if (ret) + goto err_unlock; + + ret = ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); + if (ret) + goto err_unlock; + + ret = ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); + if (ret) + goto err_unlock; + + ret = ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); + if (ret) + goto err_unlock; + + /* Verify that we can read back at least one register */ + ret = ops->reg_read(st, AD5592R_REG_ADC_EN, &read_back); + if (!ret && (read_back & 0xff) != adc) + ret = -EIO; + +err_unlock: + mutex_unlock(&iio_dev->mlock); + return ret; +} + +static int ad5592r_reset_channel_modes(struct ad5592r_state *st) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(st->channel_modes); i++) + st->channel_modes[i] = CH_MODE_UNUSED; + + return ad5592r_set_channel_modes(st); +} + +static int ad5592r_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct ad5592r_state *st = iio_priv(iio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + + if (val >= (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + if (!chan->output) + return -EINVAL; + + mutex_lock(&iio_dev->mlock); + ret = st->ops->write_dac(st, chan->channel, val); + if (!ret) + st->cached_dac[chan->channel] = val; + mutex_unlock(&iio_dev->mlock); + return ret; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_VOLTAGE) { + bool gain; + + if (val == st->scale_avail[0][0] && + val2 == st->scale_avail[0][1]) + gain = false; + else if (val == st->scale_avail[1][0] && + val2 == st->scale_avail[1][1]) + gain = true; + else + return -EINVAL; + + mutex_lock(&iio_dev->mlock); + + ret = st->ops->reg_read(st, AD5592R_REG_CTRL, + &st->cached_gp_ctrl); + if (ret < 0) { + mutex_unlock(&iio_dev->mlock); + return ret; + } + + if (chan->output) { + if (gain) + st->cached_gp_ctrl |= + AD5592R_REG_CTRL_DAC_RANGE; + else + st->cached_gp_ctrl &= + ~AD5592R_REG_CTRL_DAC_RANGE; + } else { + if (gain) + st->cached_gp_ctrl |= + AD5592R_REG_CTRL_ADC_RANGE; + else + st->cached_gp_ctrl &= + ~AD5592R_REG_CTRL_ADC_RANGE; + } + + ret = st->ops->reg_write(st, AD5592R_REG_CTRL, + st->cached_gp_ctrl); + mutex_unlock(&iio_dev->mlock); + + return ret; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ad5592r_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct ad5592r_state *st = iio_priv(iio_dev); + u16 read_val; + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&iio_dev->mlock); + + if (!chan->output) { + ret = st->ops->read_adc(st, chan->channel, &read_val); + if (ret) + goto unlock; + + if ((read_val >> 12 & 0x7) != (chan->channel & 0x7)) { + dev_err(st->dev, "Error while reading channel %u\n", + chan->channel); + ret = -EIO; + goto unlock; + } + + read_val &= GENMASK(11, 0); + + } else { + read_val = st->cached_dac[chan->channel]; + } + + dev_dbg(st->dev, "Channel %u read: 0x%04hX\n", + chan->channel, read_val); + + *val = (int) read_val; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + *val = ad5592r_get_vref(st); + + if (chan->type == IIO_TEMP) { + s64 tmp = *val * (3767897513LL / 25LL); + *val = div_s64_rem(tmp, 1000000000LL, val2); + + ret = IIO_VAL_INT_PLUS_MICRO; + } else { + int mult; + + mutex_lock(&iio_dev->mlock); + + if (chan->output) + mult = !!(st->cached_gp_ctrl & + AD5592R_REG_CTRL_DAC_RANGE); + else + mult = !!(st->cached_gp_ctrl & + AD5592R_REG_CTRL_ADC_RANGE); + + *val *= ++mult; + + *val2 = chan->scan_type.realbits; + ret = IIO_VAL_FRACTIONAL_LOG2; + } + break; + case IIO_CHAN_INFO_OFFSET: + ret = ad5592r_get_vref(st); + + mutex_lock(&iio_dev->mlock); + + if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE) + *val = (-34365 * 25) / ret; + else + *val = (-75365 * 25) / ret; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + } + +unlock: + mutex_unlock(&iio_dev->mlock); + return ret; +} + +static int ad5592r_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + + default: + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; +} + +static const struct iio_info ad5592r_info = { + .read_raw = ad5592r_read_raw, + .write_raw = ad5592r_write_raw, + .write_raw_get_fmt = ad5592r_write_raw_get_fmt, + .driver_module = THIS_MODULE, +}; + +static ssize_t ad5592r_show_scale_available(struct iio_dev *iio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct ad5592r_state *st = iio_priv(iio_dev); + + return sprintf(buf, "%d.%09u %d.%09u\n", + st->scale_avail[0][0], st->scale_avail[0][1], + st->scale_avail[1][0], st->scale_avail[1][1]); +} + +static struct iio_chan_spec_ext_info ad5592r_ext_info[] = { + { + .name = "scale_available", + .read = ad5592r_show_scale_available, + .shared = true, + }, + {}, +}; + +static void ad5592r_setup_channel(struct iio_dev *iio_dev, + struct iio_chan_spec *chan, bool output, unsigned id) +{ + chan->type = IIO_VOLTAGE; + chan->indexed = 1; + chan->output = output; + chan->channel = id; + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 12; + chan->scan_type.storagebits = 16; + chan->ext_info = ad5592r_ext_info; +} + +static int ad5592r_alloc_channels(struct ad5592r_state *st) +{ + unsigned i, curr_channel = 0, + num_channels = st->num_channels; + struct iio_dev *iio_dev = iio_priv_to_dev(st); + struct iio_chan_spec *channels; + struct fwnode_handle *child; + u32 reg, tmp; + int ret; + + device_for_each_child_node(st->dev, child) { + ret = fwnode_property_read_u32(child, "reg", ®); + if (ret || reg > ARRAY_SIZE(st->channel_modes)) + continue; + + ret = fwnode_property_read_u32(child, "adi,mode", &tmp); + if (!ret) + st->channel_modes[reg] = tmp; + + fwnode_property_read_u32(child, "adi,off-state", &tmp); + if (!ret) + st->channel_offstate[reg] = tmp; + } + + channels = devm_kzalloc(st->dev, + (1 + 2 * num_channels) * sizeof(*channels), GFP_KERNEL); + if (!channels) + return -ENOMEM; + + for (i = 0; i < num_channels; i++) { + switch (st->channel_modes[i]) { + case CH_MODE_DAC: + ad5592r_setup_channel(iio_dev, &channels[curr_channel], + true, i); + curr_channel++; + break; + + case CH_MODE_ADC: + ad5592r_setup_channel(iio_dev, &channels[curr_channel], + false, i); + curr_channel++; + break; + + case CH_MODE_DAC_AND_ADC: + ad5592r_setup_channel(iio_dev, &channels[curr_channel], + true, i); + curr_channel++; + ad5592r_setup_channel(iio_dev, &channels[curr_channel], + false, i); + curr_channel++; + break; + + default: + continue; + } + } + + channels[curr_channel].type = IIO_TEMP; + channels[curr_channel].channel = 8; + channels[curr_channel].info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET); + curr_channel++; + + iio_dev->num_channels = curr_channel; + iio_dev->channels = channels; + + return 0; +} + +static void ad5592r_init_scales(struct ad5592r_state *st, int vref_mV) +{ + s64 tmp = (s64)vref_mV * 1000000000LL >> 12; + + st->scale_avail[0][0] = + div_s64_rem(tmp, 1000000000LL, &st->scale_avail[0][1]); + st->scale_avail[1][0] = + div_s64_rem(tmp * 2, 1000000000LL, &st->scale_avail[1][1]); +} + +int ad5592r_probe(struct device *dev, const char *name, + const struct ad5592r_rw_ops *ops) +{ + struct iio_dev *iio_dev; + struct ad5592r_state *st; + int ret; + + iio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!iio_dev) + return -ENOMEM; + + st = iio_priv(iio_dev); + st->dev = dev; + st->ops = ops; + st->num_channels = 8; + dev_set_drvdata(dev, iio_dev); + + st->reg = devm_regulator_get_optional(dev, "vref"); + if (IS_ERR(st->reg)) { + if ((PTR_ERR(st->reg) != -ENODEV) && dev->of_node) + return PTR_ERR(st->reg); + + st->reg = NULL; + } else { + ret = regulator_enable(st->reg); + if (ret) + return ret; + } + + iio_dev->dev.parent = dev; + iio_dev->name = name; + iio_dev->info = &ad5592r_info; + iio_dev->modes = INDIO_DIRECT_MODE; + + ad5592r_init_scales(st, ad5592r_get_vref(st)); + + ret = ad5592r_reset(st); + if (ret) + goto error_disable_reg; + + ret = ops->reg_write(st, AD5592R_REG_PD, + (st->reg == NULL) ? AD5592R_REG_PD_EN_REF : 0); + if (ret) + goto error_disable_reg; + + ret = ad5592r_alloc_channels(st); + if (ret) + goto error_disable_reg; + + ret = ad5592r_set_channel_modes(st); + if (ret) + goto error_reset_ch_modes; + + ret = iio_device_register(iio_dev); + if (ret) + goto error_reset_ch_modes; + + ret = ad5592r_gpio_init(st); + if (ret) + goto error_dev_unregister; + + return 0; + +error_dev_unregister: + iio_device_unregister(iio_dev); + +error_reset_ch_modes: + ad5592r_reset_channel_modes(st); + +error_disable_reg: + if (st->reg) + regulator_disable(st->reg); + + return ret; +} +EXPORT_SYMBOL_GPL(ad5592r_probe); + +int ad5592r_remove(struct device *dev) +{ + struct iio_dev *iio_dev = dev_get_drvdata(dev); + struct ad5592r_state *st = iio_priv(iio_dev); + + iio_device_unregister(iio_dev); + ad5592r_reset_channel_modes(st); + ad5592r_gpio_cleanup(st); + + if (st->reg) + regulator_disable(st->reg); + + return 0; +} +EXPORT_SYMBOL_GPL(ad5592r_remove); + +MODULE_AUTHOR("Paul Cercueil "); +MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5592r-base.h b/drivers/iio/dac/ad5592r-base.h new file mode 100644 index 000000000000..841457e93f85 --- /dev/null +++ b/drivers/iio/dac/ad5592r-base.h @@ -0,0 +1,76 @@ +/* + * AD5592R / AD5593R Digital <-> Analog converters driver + * + * Copyright 2015-2016 Analog Devices Inc. + * Author: Paul Cercueil + * + * Licensed under the GPL-2. + */ + +#ifndef __DRIVERS_IIO_DAC_AD5592R_BASE_H__ +#define __DRIVERS_IIO_DAC_AD5592R_BASE_H__ + +#include +#include +#include +#include + +struct device; +struct ad5592r_state; + +enum ad5592r_registers { + AD5592R_REG_NOOP = 0x0, + AD5592R_REG_DAC_READBACK = 0x1, + AD5592R_REG_ADC_SEQ = 0x2, + AD5592R_REG_CTRL = 0x3, + AD5592R_REG_ADC_EN = 0x4, + AD5592R_REG_DAC_EN = 0x5, + AD5592R_REG_PULLDOWN = 0x6, + AD5592R_REG_LDAC = 0x7, + AD5592R_REG_GPIO_OUT_EN = 0x8, + AD5592R_REG_GPIO_SET = 0x9, + AD5592R_REG_GPIO_IN_EN = 0xA, + AD5592R_REG_PD = 0xB, + AD5592R_REG_OPEN_DRAIN = 0xC, + AD5592R_REG_TRISTATE = 0xD, + AD5592R_REG_RESET = 0xF, +}; + +#define AD5592R_REG_PD_EN_REF BIT(9) +#define AD5592R_REG_CTRL_ADC_RANGE BIT(5) +#define AD5592R_REG_CTRL_DAC_RANGE BIT(4) + +struct ad5592r_rw_ops { + int (*write_dac)(struct ad5592r_state *st, unsigned chan, u16 value); + int (*read_adc)(struct ad5592r_state *st, unsigned chan, u16 *value); + int (*reg_write)(struct ad5592r_state *st, u8 reg, u16 value); + int (*reg_read)(struct ad5592r_state *st, u8 reg, u16 *value); + int (*gpio_read)(struct ad5592r_state *st, u8 *value); +}; + +struct ad5592r_state { + struct device *dev; + struct regulator *reg; + struct gpio_chip gpiochip; + struct mutex gpio_lock; /* Protect cached gpio_out, gpio_val, etc. */ + unsigned int num_channels; + const struct ad5592r_rw_ops *ops; + int scale_avail[2][2]; + u16 cached_dac[8]; + u16 cached_gp_ctrl; + u8 channel_modes[8]; + u8 channel_offstate[8]; + u8 gpio_map; + u8 gpio_out; + u8 gpio_in; + u8 gpio_val; + + __be16 spi_msg ____cacheline_aligned; + __be16 spi_msg_nop; +}; + +int ad5592r_probe(struct device *dev, const char *name, + const struct ad5592r_rw_ops *ops); +int ad5592r_remove(struct device *dev); + +#endif /* __DRIVERS_IIO_DAC_AD5592R_BASE_H__ */ diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c new file mode 100644 index 000000000000..0b235a2c7359 --- /dev/null +++ b/drivers/iio/dac/ad5592r.c @@ -0,0 +1,164 @@ +/* + * AD5592R Digital <-> Analog converters driver + * + * Copyright 2015-2016 Analog Devices Inc. + * Author: Paul Cercueil + * + * Licensed under the GPL-2. + */ + +#include "ad5592r-base.h" + +#include +#include +#include +#include + +#define AD5592R_GPIO_READBACK_EN BIT(10) +#define AD5592R_LDAC_READBACK_EN BIT(6) + +static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, u16 *buf) +{ + struct spi_device *spi = container_of(st->dev, struct spi_device, dev); + struct spi_transfer t = { + .tx_buf = &st->spi_msg_nop, + .rx_buf = buf, + .len = 2 + }; + + st->spi_msg_nop = 0; /* NOP */ + + return spi_sync_transfer(spi, &t, 1); +} + +static int ad5592r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value) +{ + struct spi_device *spi = container_of(st->dev, struct spi_device, dev); + + st->spi_msg = cpu_to_be16(BIT(15) | (chan << 12) | value); + + return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); +} + +static int ad5592r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value) +{ + struct spi_device *spi = container_of(st->dev, struct spi_device, dev); + int ret; + + st->spi_msg = cpu_to_be16((AD5592R_REG_ADC_SEQ << 11) | BIT(chan)); + + ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); + if (ret) + return ret; + + /* + * Invalid data: + * See Figure 40. Single-Channel ADC Conversion Sequence + */ + ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); + if (ret) + return ret; + + ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); + if (ret) + return ret; + + *value = be16_to_cpu(st->spi_msg); + + return 0; +} + +static int ad5592r_reg_write(struct ad5592r_state *st, u8 reg, u16 value) +{ + struct spi_device *spi = container_of(st->dev, struct spi_device, dev); + + st->spi_msg = cpu_to_be16((reg << 11) | value); + + return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); +} + +static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value) +{ + struct spi_device *spi = container_of(st->dev, struct spi_device, dev); + int ret; + + st->spi_msg = cpu_to_be16((AD5592R_REG_LDAC << 11) | + AD5592R_LDAC_READBACK_EN | (reg << 2)); + + ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg)); + if (ret) + return ret; + + ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); + if (ret) + return ret; + + *value = be16_to_cpu(st->spi_msg); + + return 0; +} + +static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value) +{ + int ret; + + ret = ad5592r_reg_write(st, AD5592R_REG_GPIO_IN_EN, + AD5592R_GPIO_READBACK_EN | st->gpio_in); + if (ret) + return ret; + + ret = ad5592r_spi_wnop_r16(st, &st->spi_msg); + if (ret) + return ret; + + *value = (u8) be16_to_cpu(st->spi_msg); + + return 0; +} + +static const struct ad5592r_rw_ops ad5592r_rw_ops = { + .write_dac = ad5592r_write_dac, + .read_adc = ad5592r_read_adc, + .reg_write = ad5592r_reg_write, + .reg_read = ad5592r_reg_read, + .gpio_read = ad5593r_gpio_read, +}; + +static int ad5592r_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + + return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops); +} + +static int ad5592r_spi_remove(struct spi_device *spi) +{ + return ad5592r_remove(&spi->dev); +} + +static const struct spi_device_id ad5592r_spi_ids[] = { + { .name = "ad5592r", }, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5592r_spi_ids); + +static const struct of_device_id ad5592r_of_match[] = { + { .compatible = "adi,ad5592r", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ad5592r_of_match); + +static struct spi_driver ad5592r_spi_driver = { + .driver = { + .name = "ad5592r", + .of_match_table = of_match_ptr(ad5592r_of_match), + }, + .probe = ad5592r_spi_probe, + .remove = ad5592r_spi_remove, + .id_table = ad5592r_spi_ids, +}; +module_spi_driver(ad5592r_spi_driver); + +MODULE_AUTHOR("Paul Cercueil "); +MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c new file mode 100644 index 000000000000..dca158a88f47 --- /dev/null +++ b/drivers/iio/dac/ad5593r.c @@ -0,0 +1,131 @@ +/* + * AD5593R Digital <-> Analog converters driver + * + * Copyright 2015-2016 Analog Devices Inc. + * Author: Paul Cercueil + * + * Licensed under the GPL-2. + */ + +#include "ad5592r-base.h" + +#include +#include +#include +#include + +#define AD5593R_MODE_CONF (0 << 4) +#define AD5593R_MODE_DAC_WRITE (1 << 4) +#define AD5593R_MODE_ADC_READBACK (4 << 4) +#define AD5593R_MODE_DAC_READBACK (5 << 4) +#define AD5593R_MODE_GPIO_READBACK (6 << 4) +#define AD5593R_MODE_REG_READBACK (7 << 4) + +static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value) +{ + struct i2c_client *i2c = to_i2c_client(st->dev); + + return i2c_smbus_write_word_swapped(i2c, + AD5593R_MODE_DAC_WRITE | chan, value); +} + +static int ad5593r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value) +{ + struct i2c_client *i2c = to_i2c_client(st->dev); + s32 val; + + val = i2c_smbus_write_word_swapped(i2c, + AD5593R_MODE_CONF | AD5592R_REG_ADC_SEQ, BIT(chan)); + if (val < 0) + return (int) val; + + val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK); + if (val < 0) + return (int) val; + + *value = (u16) val; + + return 0; +} + +static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value) +{ + struct i2c_client *i2c = to_i2c_client(st->dev); + + return i2c_smbus_write_word_swapped(i2c, + AD5593R_MODE_CONF | reg, value); +} + +static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value) +{ + struct i2c_client *i2c = to_i2c_client(st->dev); + s32 val; + + val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg); + if (val < 0) + return (int) val; + + *value = (u16) val; + + return 0; +} + +static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value) +{ + struct i2c_client *i2c = to_i2c_client(st->dev); + s32 val; + + val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_GPIO_READBACK); + if (val < 0) + return (int) val; + + *value = (u8) val; + + return 0; +} + +static const struct ad5592r_rw_ops ad5593r_rw_ops = { + .write_dac = ad5593r_write_dac, + .read_adc = ad5593r_read_adc, + .reg_write = ad5593r_reg_write, + .reg_read = ad5593r_reg_read, + .gpio_read = ad5593r_gpio_read, +}; + +static int ad5593r_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + return ad5592r_probe(&i2c->dev, id->name, &ad5593r_rw_ops); +} + +static int ad5593r_i2c_remove(struct i2c_client *i2c) +{ + return ad5592r_remove(&i2c->dev); +} + +static const struct i2c_device_id ad5593r_i2c_ids[] = { + { .name = "ad5593r", }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, ad5593r_i2c_ids); + +static const struct of_device_id ad5593r_of_match[] = { + { .compatible = "adi,ad5593r", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ad5593r_of_match); + +static struct i2c_driver ad5593r_driver = { + .driver = { + .name = "ad5593r", + .of_match_table = of_match_ptr(ad5593r_of_match), + }, + .probe = ad5593r_i2c_probe, + .remove = ad5593r_i2c_remove, + .id_table = ad5593r_i2c_ids, +}; +module_i2c_driver(ad5593r_driver); + +MODULE_AUTHOR("Paul Cercueil "); +MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); +MODULE_LICENSE("GPL v2"); diff --git a/include/dt-bindings/iio/adi,ad5592r.h b/include/dt-bindings/iio/adi,ad5592r.h new file mode 100644 index 000000000000..c48aca1dcade --- /dev/null +++ b/include/dt-bindings/iio/adi,ad5592r.h @@ -0,0 +1,16 @@ + +#ifndef _DT_BINDINGS_ADI_AD5592R_H +#define _DT_BINDINGS_ADI_AD5592R_H + +#define CH_MODE_UNUSED 0 +#define CH_MODE_ADC 1 +#define CH_MODE_DAC 2 +#define CH_MODE_DAC_AND_ADC 3 +#define CH_MODE_GPIO 8 + +#define CH_OFFSTATE_PULLDOWN 0 +#define CH_OFFSTATE_OUT_LOW 1 +#define CH_OFFSTATE_OUT_HIGH 2 +#define CH_OFFSTATE_OUT_TRISTATE 3 + +#endif /* _DT_BINDINGS_ADI_AD5592R_H */ -- GitLab From c455e58354adcde7ba1ebf3d753eba9a07cd587d Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Tue, 5 Apr 2016 22:18:44 -0700 Subject: [PATCH 1919/9938] iio: accel: mma7455: use regmap to retrieve struct device Driver includes struct regmap and struct device in its global data. Remove the struct device and use regmap API to retrieve device info. Patch created using Coccinelle plus manual edits. Signed-off-by: Alison Schofield Acked-by: Joachim Eastwood Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma7455_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/mma7455_core.c b/drivers/iio/accel/mma7455_core.c index c633cc2c0789..c902f54c23f5 100644 --- a/drivers/iio/accel/mma7455_core.c +++ b/drivers/iio/accel/mma7455_core.c @@ -55,11 +55,11 @@ struct mma7455_data { struct regmap *regmap; - struct device *dev; }; static int mma7455_drdy(struct mma7455_data *mma7455) { + struct device *dev = regmap_get_device(mma7455->regmap); unsigned int reg; int tries = 3; int ret; @@ -75,7 +75,7 @@ static int mma7455_drdy(struct mma7455_data *mma7455) msleep(20); } - dev_warn(mma7455->dev, "data not ready\n"); + dev_warn(dev, "data not ready\n"); return -EIO; } @@ -260,7 +260,6 @@ int mma7455_core_probe(struct device *dev, struct regmap *regmap, dev_set_drvdata(dev, indio_dev); mma7455 = iio_priv(indio_dev); mma7455->regmap = regmap; - mma7455->dev = dev; indio_dev->info = &mma7455_info; indio_dev->name = name; -- GitLab From ff5c37e3eae2cdba4aba13dc8c7e840abb41e4bb Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Tue, 5 Apr 2016 21:11:31 -0700 Subject: [PATCH 1920/9938] staging: iio: ad7606: use iio_device_{claim|release}_direct_mode() Replace the code that guarantees the device stays in direct mode with iio_device_{claim|release}_direct_mode() which does same. Signed-off-by: Alison Schofield Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 6dbc811730ae..f79ee61851f6 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -88,12 +88,12 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7606_scan_direct(indio_dev, chan->address); - mutex_unlock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = ad7606_scan_direct(indio_dev, chan->address); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; -- GitLab From 0e5f7d0b39e1f184dc25e3adb580c79e85332167 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 16 Mar 2016 14:19:49 +0100 Subject: [PATCH 1921/9938] ARM: dts: at91: shdwc binding: add new shutdown controller documentation The new shutdown controller compatible with sama5d2 has a new binding documentation and properties. Signed-off-by: Nicolas Ferre Acked-by: Alexandre Belloni Acked-by: Rob Herring Signed-off-by: Sebastian Reichel --- .../devicetree/bindings/arm/atmel-at91.txt | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 7fd64ec9ee1d..2f5a07b32fb7 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -147,6 +147,65 @@ Example: clocks = <&clk32k>; }; +SHDWC SAMA5D2-Compatible Shutdown Controller + +1) shdwc node + +required properties: +- compatible: should be "atmel,sama5d2-shdwc". +- reg: should contain registers location and length +- clocks: phandle to input clock. +- #address-cells: should be one. The cell is the wake-up input index. +- #size-cells: should be zero. + +optional properties: + +- debounce-delay-us: minimum wake-up inputs debouncer period in + microseconds. It's usually a board-related property. +- atmel,wakeup-rtc-timer: boolean to enable Real-Time Clock wake-up. + +The node contains child nodes for each wake-up input that the platform uses. + +2) input nodes + +Wake-up input nodes are usually described in the "board" part of the Device +Tree. Note also that input 0 is linked to the wake-up pin and is frequently +used. + +Required properties: +- reg: should contain the wake-up input index [0 - 15]. + +Optional properties: +- atmel,wakeup-active-high: boolean, the corresponding wake-up input described + by the child, forces the wake-up of the core power supply on a high level. + The default is to be active low. + +Example: + +On the SoC side: + shdwc@f8048010 { + compatible = "atmel,sama5d2-shdwc"; + reg = <0xf8048010 0x10>; + clocks = <&clk32k>; + #address-cells = <1>; + #size-cells = <0>; + atmel,wakeup-rtc-timer; + }; + +On the board side: + shdwc@f8048010 { + debounce-delay-us = <976>; + + input@0 { + reg = <0>; + }; + + input@1 { + reg = <1>; + atmel,wakeup-active-high; + }; + }; + Special Function Registers (SFR) Special Function Registers (SFR) manage specific aspects of the integrated -- GitLab From f80cb488439879df6ae3ba32a5dc4e0892fcd3ff Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 16 Mar 2016 14:19:50 +0100 Subject: [PATCH 1922/9938] power: reset: at91-shdwc: add new shutdown controller driver Sama5d2 SoC has a completely new shutdown controller with new features and register layout. It thus makes sense to add a new driver for this new peripheral. This driver is Device Tree only and handles events from the wake-up pin and the RTC. As the register layout may change in the future, so some values are encoded in a configuration structure. Signed-off-by: Nicolas Ferre Acked-by: Alexandre Belloni Signed-off-by: Sebastian Reichel --- MAINTAINERS | 5 + drivers/power/reset/Kconfig | 8 + drivers/power/reset/Makefile | 1 + drivers/power/reset/at91-sama5d2_shdwc.c | 282 +++++++++++++++++++++++ 4 files changed, 296 insertions(+) create mode 100644 drivers/power/reset/at91-sama5d2_shdwc.c diff --git a/MAINTAINERS b/MAINTAINERS index 1c32f8a3d6c4..fe6721de11bf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1996,6 +1996,11 @@ M: Nicolas Ferre S: Supported F: drivers/tty/serial/atmel_serial.c +ATMEL AT91 SAMA5D2-Compatible Shutdown Controller +M: Nicolas Ferre +S: Supported +F: drivers/power/reset/at91-sama5d2_shdwc.c + ATMEL SAMA5D2 ADC DRIVER M: Ludovic Desroches L: linux-iio@vger.kernel.org diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 0a6408a39c66..9bb2622c23bf 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -30,6 +30,14 @@ config POWER_RESET_AT91_RESET This driver supports restart for Atmel AT91SAM9 and SAMA5 SoCs +config POWER_RESET_AT91_SAMA5D2_SHDWC + tristate "Atmel AT91 SAMA5D2-Compatible shutdown controller driver" + depends on ARCH_AT91 || COMPILE_TEST + default SOC_SAMA5 + help + This driver supports the alternate shutdown controller for some Atmel + SAMA5 SoCs. It is present for example on SAMA5D2 SoC. + config POWER_RESET_AXXIA bool "LSI Axxia reset driver" depends on ARCH_AXXIA diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 096fa67047f6..ab7aa8614d1f 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o +obj-$(CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC) += at91-sama5d2_shdwc.o obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c new file mode 100644 index 000000000000..8a5ac9706c9c --- /dev/null +++ b/drivers/power/reset/at91-sama5d2_shdwc.c @@ -0,0 +1,282 @@ +/* + * Atmel SAMA5D2-Compatible Shutdown Controller (SHDWC) driver. + * Found on some SoCs as the sama5d2 (obviously). + * + * Copyright (C) 2015 Atmel Corporation, + * Nicolas Ferre + * + * Evolved from driver at91-poweroff.c. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * TODO: + * - addition to status of other wake-up inputs [1 - 15] + * - Analog Comparator wake-up alarm + * - Serial RX wake-up alarm + * - low power debouncer + */ + +#include +#include +#include +#include +#include +#include + +#define SLOW_CLOCK_FREQ 32768 + +#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */ +#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */ +#define AT91_SHDW_KEY (0xa5UL << 24) /* KEY Password */ + +#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */ +#define AT91_SHDW_WKUPDBC_SHIFT 24 +#define AT91_SHDW_WKUPDBC_MASK GENMASK(31, 16) +#define AT91_SHDW_WKUPDBC(x) (((x) << AT91_SHDW_WKUPDBC_SHIFT) \ + & AT91_SHDW_WKUPDBC_MASK) + +#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */ +#define AT91_SHDW_WKUPIS_SHIFT 16 +#define AT91_SHDW_WKUPIS_MASK GENMASK(31, 16) +#define AT91_SHDW_WKUPIS(x) ((1 << (x)) << AT91_SHDW_WKUPIS_SHIFT \ + & AT91_SHDW_WKUPIS_MASK) + +#define AT91_SHDW_WUIR 0x0c /* Shutdown Wake-up Inputs Register */ +#define AT91_SHDW_WKUPEN_MASK GENMASK(15, 0) +#define AT91_SHDW_WKUPEN(x) ((1 << (x)) & AT91_SHDW_WKUPEN_MASK) +#define AT91_SHDW_WKUPT_SHIFT 16 +#define AT91_SHDW_WKUPT_MASK GENMASK(31, 16) +#define AT91_SHDW_WKUPT(x) ((1 << (x)) << AT91_SHDW_WKUPT_SHIFT \ + & AT91_SHDW_WKUPT_MASK) + +#define SHDW_WK_PIN(reg, cfg) ((reg) & AT91_SHDW_WKUPIS((cfg)->wkup_pin_input)) +#define SHDW_RTCWK(reg, cfg) (((reg) >> ((cfg)->sr_rtcwk_shift)) & 0x1) +#define SHDW_RTCWKEN(cfg) (1 << ((cfg)->mr_rtcwk_shift)) + +#define DBC_PERIOD_US(x) DIV_ROUND_UP_ULL((1000000 * (x)), \ + SLOW_CLOCK_FREQ) + +struct shdwc_config { + u8 wkup_pin_input; + u8 mr_rtcwk_shift; + u8 sr_rtcwk_shift; +}; + +struct shdwc { + struct shdwc_config *cfg; + void __iomem *at91_shdwc_base; +}; + +/* + * Hold configuration here, cannot be more than one instance of the driver + * since pm_power_off itself is global. + */ +static struct shdwc *at91_shdwc; +static struct clk *sclk; + +static const unsigned long long sdwc_dbc_period[] = { + 0, 3, 32, 512, 4096, 32768, +}; + +static void __init at91_wakeup_status(struct platform_device *pdev) +{ + struct shdwc *shdw = platform_get_drvdata(pdev); + u32 reg; + char *reason = "unknown"; + + reg = readl(shdw->at91_shdwc_base + AT91_SHDW_SR); + + dev_dbg(&pdev->dev, "%s: status = %#x\n", __func__, reg); + + /* Simple power-on, just bail out */ + if (!reg) + return; + + if (SHDW_WK_PIN(reg, shdw->cfg)) + reason = "WKUP pin"; + else if (SHDW_RTCWK(reg, shdw->cfg)) + reason = "RTC"; + + pr_info("AT91: Wake-Up source: %s\n", reason); +} + +static void at91_poweroff(void) +{ + writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, + at91_shdwc->at91_shdwc_base + AT91_SHDW_CR); +} + +static u32 at91_shdwc_debouncer_value(struct platform_device *pdev, + u32 in_period_us) +{ + int i; + int max_idx = ARRAY_SIZE(sdwc_dbc_period) - 1; + unsigned long long period_us; + unsigned long long max_period_us = DBC_PERIOD_US(sdwc_dbc_period[max_idx]); + + if (in_period_us > max_period_us) { + dev_warn(&pdev->dev, + "debouncer period %u too big, reduced to %llu us\n", + in_period_us, max_period_us); + return max_idx; + } + + for (i = max_idx - 1; i > 0; i--) { + period_us = DBC_PERIOD_US(sdwc_dbc_period[i]); + dev_dbg(&pdev->dev, "%s: ref[%d] = %llu\n", + __func__, i, period_us); + if (in_period_us > period_us) + break; + } + + return i + 1; +} + +static u32 at91_shdwc_get_wakeup_input(struct platform_device *pdev, + struct device_node *np) +{ + struct device_node *cnp; + u32 wk_input_mask; + u32 wuir = 0; + u32 wk_input; + + for_each_child_of_node(np, cnp) { + if (of_property_read_u32(cnp, "reg", &wk_input)) { + dev_warn(&pdev->dev, "reg property is missing for %s\n", + cnp->full_name); + continue; + } + + wk_input_mask = 1 << wk_input; + if (!(wk_input_mask & AT91_SHDW_WKUPEN_MASK)) { + dev_warn(&pdev->dev, + "wake-up input %d out of bounds ignore\n", + wk_input); + continue; + } + wuir |= wk_input_mask; + + if (of_property_read_bool(cnp, "atmel,wakeup-active-high")) + wuir |= AT91_SHDW_WKUPT(wk_input); + + dev_dbg(&pdev->dev, "%s: (child %d) wuir = %#x\n", + __func__, wk_input, wuir); + } + + return wuir; +} + +static void at91_shdwc_dt_configure(struct platform_device *pdev) +{ + struct shdwc *shdw = platform_get_drvdata(pdev); + struct device_node *np = pdev->dev.of_node; + u32 mode = 0, tmp, input; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return; + } + + if (!of_property_read_u32(np, "debounce-delay-us", &tmp)) + mode |= AT91_SHDW_WKUPDBC(at91_shdwc_debouncer_value(pdev, tmp)); + + if (of_property_read_bool(np, "atmel,wakeup-rtc-timer")) + mode |= SHDW_RTCWKEN(shdw->cfg); + + dev_dbg(&pdev->dev, "%s: mode = %#x\n", __func__, mode); + writel(mode, shdw->at91_shdwc_base + AT91_SHDW_MR); + + input = at91_shdwc_get_wakeup_input(pdev, np); + writel(input, shdw->at91_shdwc_base + AT91_SHDW_WUIR); +} + +static const struct shdwc_config sama5d2_shdwc_config = { + .wkup_pin_input = 0, + .mr_rtcwk_shift = 17, + .sr_rtcwk_shift = 5, +}; + +static const struct of_device_id at91_shdwc_of_match[] = { + { + .compatible = "atmel,sama5d2-shdwc", + .data = &sama5d2_shdwc_config, + }, { + /*sentinel*/ + } +}; +MODULE_DEVICE_TABLE(of, at91_shdwc_of_match); + +static int __init at91_shdwc_probe(struct platform_device *pdev) +{ + struct resource *res; + const struct of_device_id *match; + int ret; + + if (!pdev->dev.of_node) + return -ENODEV; + + at91_shdwc = devm_kzalloc(&pdev->dev, sizeof(*at91_shdwc), GFP_KERNEL); + if (!at91_shdwc) + return -ENOMEM; + + platform_set_drvdata(pdev, at91_shdwc); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + at91_shdwc->at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(at91_shdwc->at91_shdwc_base)) { + dev_err(&pdev->dev, "Could not map reset controller address\n"); + return PTR_ERR(at91_shdwc->at91_shdwc_base); + } + + match = of_match_node(at91_shdwc_of_match, pdev->dev.of_node); + at91_shdwc->cfg = (struct shdwc_config *)(match->data); + + sclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sclk)) + return PTR_ERR(sclk); + + ret = clk_prepare_enable(sclk); + if (ret) { + dev_err(&pdev->dev, "Could not enable slow clock\n"); + return ret; + } + + at91_wakeup_status(pdev); + + at91_shdwc_dt_configure(pdev); + + pm_power_off = at91_poweroff; + + return 0; +} + +static int __exit at91_shdwc_remove(struct platform_device *pdev) +{ + struct shdwc *shdw = platform_get_drvdata(pdev); + + if (pm_power_off == at91_poweroff) + pm_power_off = NULL; + + /* Reset values to disable wake-up features */ + writel(0, shdw->at91_shdwc_base + AT91_SHDW_MR); + writel(0, shdw->at91_shdwc_base + AT91_SHDW_WUIR); + + clk_disable_unprepare(sclk); + + return 0; +} + +static struct platform_driver at91_shdwc_driver = { + .remove = __exit_p(at91_shdwc_remove), + .driver = { + .name = "at91-shdwc", + .of_match_table = at91_shdwc_of_match, + }, +}; +module_platform_driver_probe(at91_shdwc_driver, at91_shdwc_probe); + +MODULE_AUTHOR("Nicolas Ferre "); +MODULE_DESCRIPTION("Atmel shutdown controller driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 1285b0a30d530d0807c229c6aad73ed1966d75ad Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Mar 2016 08:40:16 +0300 Subject: [PATCH 1923/9938] power/max8925: freeing wrong variable We were freeing "info->battery" instead of "info->usb", which leads to an OOps and a resource leak. The labels were wonky, "out_battery" did release the battery but out_usb did not release usb. I was introducing a call to free usb so it sort conflicted with existing misleading name. I renamed them. Signed-off-by: Dan Carpenter Signed-off-by: Sebastian Reichel --- drivers/power/max8925_power.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c index 57eb5c2bfc21..3b94620ce5c1 100644 --- a/drivers/power/max8925_power.c +++ b/drivers/power/max8925_power.c @@ -540,14 +540,14 @@ static int max8925_power_probe(struct platform_device *pdev) info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg); if (IS_ERR(info->usb)) { ret = PTR_ERR(info->usb); - goto out_usb; + goto out_unregister_ac; } info->usb->dev.parent = &pdev->dev; info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL); if (IS_ERR(info->battery)) { ret = PTR_ERR(info->battery); - goto out_battery; + goto out_unregister_usb; } info->battery->dev.parent = &pdev->dev; @@ -560,9 +560,9 @@ static int max8925_power_probe(struct platform_device *pdev) max8925_init_charger(chip, info); return 0; -out_battery: - power_supply_unregister(info->battery); -out_usb: +out_unregister_usb: + power_supply_unregister(info->usb); +out_unregister_ac: power_supply_unregister(info->ac); out: return ret; -- GitLab From b9223da41794030a5dfd5106c34ed1b98255e2ae Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Mar 2016 12:00:51 +0300 Subject: [PATCH 1924/9938] power: ipaq-micro-battery: freeing the wrong variable We accidentally free "micro_ac_power" which is an error pointer and it leads to an oops. We intended to free "micro_batt_power". Fixes: a2c1d531854c ('power_supply: ipaq_micro_battery: Check return values in probe') Signed-off-by: Dan Carpenter Signed-off-by: Sebastian Reichel --- drivers/power/ipaq_micro_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/ipaq_micro_battery.c b/drivers/power/ipaq_micro_battery.c index 3f314b1a30d7..35b01c7d775b 100644 --- a/drivers/power/ipaq_micro_battery.c +++ b/drivers/power/ipaq_micro_battery.c @@ -261,7 +261,7 @@ static int micro_batt_probe(struct platform_device *pdev) return 0; ac_err: - power_supply_unregister(micro_ac_power); + power_supply_unregister(micro_batt_power); batt_err: cancel_delayed_work_sync(&mb->update); destroy_workqueue(mb->wq); -- GitLab From 4a99fa06a8ca27a5187636e630568658000af575 Mon Sep 17 00:00:00 2001 From: YH Huang Date: Wed, 6 Apr 2016 10:32:25 +0800 Subject: [PATCH 1925/9938] sbs-battery: fix power status when battery charging near dry POWER_SUPPLY_STATUS_NOT_CHARGING is used for AC connected, but battery not charging (e.g. because battery temperature is out of acceptable range). When battery is charging near dry and BATTERY_FULL_DISCHARGED is set, it is wrong to set as POWER_SUPPLY_STATUS_NOT_CHARGING. Just use BATTERY_DISCHARGING to decide the power supply status is discharging or charging. Signed-off-by: YH Huang Reviewed-by: Daniel Kurtz Signed-off-by: Sebastian Reichel --- drivers/power/sbs-battery.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c index d6226d68b574..768b9fcb58ea 100644 --- a/drivers/power/sbs-battery.c +++ b/drivers/power/sbs-battery.c @@ -382,8 +382,6 @@ static int sbs_get_battery_property(struct i2c_client *client, if (ret & BATTERY_FULL_CHARGED) val->intval = POWER_SUPPLY_STATUS_FULL; - else if (ret & BATTERY_FULL_DISCHARGED) - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; else if (ret & BATTERY_DISCHARGING) val->intval = POWER_SUPPLY_STATUS_DISCHARGING; else @@ -702,8 +700,6 @@ static void sbs_delayed_work(struct work_struct *work) if (ret & BATTERY_FULL_CHARGED) ret = POWER_SUPPLY_STATUS_FULL; - else if (ret & BATTERY_FULL_DISCHARGED) - ret = POWER_SUPPLY_STATUS_NOT_CHARGING; else if (ret & BATTERY_DISCHARGING) ret = POWER_SUPPLY_STATUS_DISCHARGING; else -- GitLab From ab4b6496a26f87ceff95ee6c0449e6ac2de2f2e4 Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 17 Jan 2016 16:13:31 +0000 Subject: [PATCH 1926/9938] iio: dht11: Improve logging * Unify log messages * Add more DEBUG messages Apparently this driver is working unreliably on some platforms that I can't test. Therefore I want an easy way for bug reporters to provide useful information without making the driver too chatty by default. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 40 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index 20b500da94db..9c47bc98f3ac 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -96,6 +96,24 @@ struct dht11 { struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ]; }; +#ifdef CONFIG_DYNAMIC_DEBUG +/* + * dht11_edges_print: show the data as actually received by the + * driver. + */ +static void dht11_edges_print(struct dht11 *dht11) +{ + int i; + + dev_dbg(dht11->dev, "%d edges detected:\n", dht11->num_edges); + for (i = 1; i < dht11->num_edges; ++i) { + dev_dbg(dht11->dev, "%d: %lld ns %s\n", i, + dht11->edges[i].ts - dht11->edges[i - 1].ts, + dht11->edges[i - 1].value ? "high" : "low"); + } +} +#endif /* CONFIG_DYNAMIC_DEBUG */ + static unsigned char dht11_decode_byte(char *bits) { unsigned char ret = 0; @@ -119,8 +137,12 @@ static int dht11_decode(struct dht11 *dht11, int offset) for (i = 0; i < DHT11_BITS_PER_READ; ++i) { t = dht11->edges[offset + 2 * i + 2].ts - dht11->edges[offset + 2 * i + 1].ts; - if (!dht11->edges[offset + 2 * i + 1].value) - return -EIO; /* lost synchronisation */ + if (!dht11->edges[offset + 2 * i + 1].value) { + dev_dbg(dht11->dev, + "lost synchronisation at edge %d\n", + offset + 2 * i + 1); + return -EIO; + } bits[i] = t > DHT11_THRESHOLD; } @@ -130,8 +152,10 @@ static int dht11_decode(struct dht11 *dht11, int offset) temp_dec = dht11_decode_byte(&bits[24]); checksum = dht11_decode_byte(&bits[32]); - if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) + if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) { + dev_dbg(dht11->dev, "invalid checksum\n"); return -EIO; + } dht11->timestamp = ktime_get_boot_ns(); if (hum_int < 20) { /* DHT22 */ @@ -182,6 +206,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, mutex_lock(&dht11->lock); if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_boot_ns()) { timeres = ktime_get_resolution_ns(); + dev_dbg(dht11->dev, "current timeresolution: %dns\n", timeres); if (timeres > DHT11_MIN_TIMERES) { dev_err(dht11->dev, "timeresolution %dns too low\n", timeres); @@ -219,10 +244,13 @@ static int dht11_read_raw(struct iio_dev *iio_dev, free_irq(dht11->irq, iio_dev); +#ifdef CONFIG_DYNAMIC_DEBUG + dht11_edges_print(dht11); +#endif + if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { - dev_err(&iio_dev->dev, - "Only %d signal edges detected\n", - dht11->num_edges); + dev_err(dht11->dev, "Only %d signal edges detected\n", + dht11->num_edges); ret = -ETIMEDOUT; } if (ret < 0) -- GitLab From 9ad4d9a38a7f62a4891124501cdce4e768dbba16 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Sun, 10 Apr 2016 13:20:09 -0600 Subject: [PATCH 1927/9938] ARM: DRA7: hwmod: Add data for McASP1/2/4/5/6/7/8 Add missing data for all McASP ports for the dra7 family Signed-off-by: Peter Ujfalusi Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 237 ++++++++++++++++++++++ 1 file changed, 237 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 9442d89bd229..7610f3ef28b7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -1374,6 +1374,52 @@ static struct omap_hwmod_class dra7xx_mcasp_hwmod_class = { .sysc = &dra7xx_mcasp_sysc, }; +/* mcasp1 */ +static struct omap_hwmod_opt_clk mcasp1_opt_clks[] = { + { .role = "ahclkx", .clk = "mcasp1_ahclkx_mux" }, + { .role = "ahclkr", .clk = "mcasp1_ahclkr_mux" }, +}; + +static struct omap_hwmod dra7xx_mcasp1_hwmod = { + .name = "mcasp1", + .class = &dra7xx_mcasp_hwmod_class, + .clkdm_name = "ipu_clkdm", + .main_clk = "mcasp1_aux_gfclk_mux", + .flags = HWMOD_OPT_CLKS_NEEDED, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_IPU_MCASP1_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_IPU_MCASP1_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = mcasp1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcasp1_opt_clks), +}; + +/* mcasp2 */ +static struct omap_hwmod_opt_clk mcasp2_opt_clks[] = { + { .role = "ahclkx", .clk = "mcasp2_ahclkx_mux" }, + { .role = "ahclkr", .clk = "mcasp2_ahclkr_mux" }, +}; + +static struct omap_hwmod dra7xx_mcasp2_hwmod = { + .name = "mcasp2", + .class = &dra7xx_mcasp_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "mcasp2_aux_gfclk_mux", + .flags = HWMOD_OPT_CLKS_NEEDED, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP2_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_MCASP2_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = mcasp2_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcasp2_opt_clks), +}; + /* mcasp3 */ static struct omap_hwmod_opt_clk mcasp3_opt_clks[] = { { .role = "ahclkx", .clk = "mcasp3_ahclkx_mux" }, @@ -1396,6 +1442,116 @@ static struct omap_hwmod dra7xx_mcasp3_hwmod = { .opt_clks_cnt = ARRAY_SIZE(mcasp3_opt_clks), }; +/* mcasp4 */ +static struct omap_hwmod_opt_clk mcasp4_opt_clks[] = { + { .role = "ahclkx", .clk = "mcasp4_ahclkx_mux" }, +}; + +static struct omap_hwmod dra7xx_mcasp4_hwmod = { + .name = "mcasp4", + .class = &dra7xx_mcasp_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "mcasp4_aux_gfclk_mux", + .flags = HWMOD_OPT_CLKS_NEEDED, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP4_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_MCASP4_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = mcasp4_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcasp4_opt_clks), +}; + +/* mcasp5 */ +static struct omap_hwmod_opt_clk mcasp5_opt_clks[] = { + { .role = "ahclkx", .clk = "mcasp5_ahclkx_mux" }, +}; + +static struct omap_hwmod dra7xx_mcasp5_hwmod = { + .name = "mcasp5", + .class = &dra7xx_mcasp_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "mcasp5_aux_gfclk_mux", + .flags = HWMOD_OPT_CLKS_NEEDED, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP5_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_MCASP5_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = mcasp5_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcasp5_opt_clks), +}; + +/* mcasp6 */ +static struct omap_hwmod_opt_clk mcasp6_opt_clks[] = { + { .role = "ahclkx", .clk = "mcasp6_ahclkx_mux" }, +}; + +static struct omap_hwmod dra7xx_mcasp6_hwmod = { + .name = "mcasp6", + .class = &dra7xx_mcasp_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "mcasp6_aux_gfclk_mux", + .flags = HWMOD_OPT_CLKS_NEEDED, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP6_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_MCASP6_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = mcasp6_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcasp6_opt_clks), +}; + +/* mcasp7 */ +static struct omap_hwmod_opt_clk mcasp7_opt_clks[] = { + { .role = "ahclkx", .clk = "mcasp7_ahclkx_mux" }, +}; + +static struct omap_hwmod dra7xx_mcasp7_hwmod = { + .name = "mcasp7", + .class = &dra7xx_mcasp_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "mcasp7_aux_gfclk_mux", + .flags = HWMOD_OPT_CLKS_NEEDED, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP7_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_MCASP7_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = mcasp7_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcasp7_opt_clks), +}; + +/* mcasp8 */ +static struct omap_hwmod_opt_clk mcasp8_opt_clks[] = { + { .role = "ahclkx", .clk = "mcasp8_ahclkx_mux" }, +}; + +static struct omap_hwmod dra7xx_mcasp8_hwmod = { + .name = "mcasp8", + .class = &dra7xx_mcasp_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "mcasp8_aux_gfclk_mux", + .flags = HWMOD_OPT_CLKS_NEEDED, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP8_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_MCASP8_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = mcasp8_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcasp8_opt_clks), +}; + /* * 'mmc' class * @@ -2726,6 +2882,38 @@ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__hdmi = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* l4_per2 -> mcasp1 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp1 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_mcasp1_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l3_main_1 -> mcasp1 */ +static struct omap_hwmod_ocp_if dra7xx_l3_main_1__mcasp1 = { + .master = &dra7xx_l3_main_1_hwmod, + .slave = &dra7xx_mcasp1_hwmod, + .clk = "l3_iclk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l4_per2 -> mcasp2 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp2 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_mcasp2_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l3_main_1 -> mcasp2 */ +static struct omap_hwmod_ocp_if dra7xx_l3_main_1__mcasp2 = { + .master = &dra7xx_l3_main_1_hwmod, + .slave = &dra7xx_mcasp2_hwmod, + .clk = "l3_iclk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l4_per2 -> mcasp3 */ static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp3 = { .master = &dra7xx_l4_per2_hwmod, @@ -2742,6 +2930,46 @@ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__mcasp3 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* l4_per2 -> mcasp4 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp4 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_mcasp4_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l4_per2 -> mcasp5 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp5 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_mcasp5_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l4_per2 -> mcasp6 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp6 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_mcasp6_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l4_per2 -> mcasp7 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp7 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_mcasp7_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l4_per2 -> mcasp8 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp8 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_mcasp8_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l4_per1 -> elm */ static struct omap_hwmod_ocp_if dra7xx_l4_per1__elm = { .master = &dra7xx_l4_per1_hwmod, @@ -3484,8 +3712,17 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l4_wkup__dcan1, &dra7xx_l4_per2__dcan2, &dra7xx_l4_per2__cpgmac0, + &dra7xx_l4_per2__mcasp1, + &dra7xx_l3_main_1__mcasp1, + &dra7xx_l4_per2__mcasp2, + &dra7xx_l3_main_1__mcasp2, &dra7xx_l4_per2__mcasp3, &dra7xx_l3_main_1__mcasp3, + &dra7xx_l4_per2__mcasp4, + &dra7xx_l4_per2__mcasp5, + &dra7xx_l4_per2__mcasp6, + &dra7xx_l4_per2__mcasp7, + &dra7xx_l4_per2__mcasp8, &dra7xx_gmac__mdio, &dra7xx_l4_cfg__dma_system, &dra7xx_l3_main_1__tpcc, -- GitLab From b05ff3c394bc5dbb1bc88073759f01c0ebdf5de1 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Sun, 10 Apr 2016 13:20:09 -0600 Subject: [PATCH 1928/9938] ARM: OMAP2+: DRA7: Add hwmod entries for PWMSS Add hwmod entries for the PWMSS on DRA7. Set l4_root_clk_div as the main_clk of PWMSS. It is fixed-factored clock equal to L4PER2_L3_GICLK/2(l3_iclk_div/2). Signed-off-by: Vignesh R [fcooper@ti.com: Do not add eQEP, ePWM and eCAP hwmod entries] Signed-off-by: Franklin S Cooper Jr [paul@pwsan.com: fixed sparse warnings; added missing comments] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 89 +++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 7610f3ef28b7..2f15cf13e0d7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -383,6 +383,68 @@ static struct omap_hwmod dra7xx_dcan2_hwmod = { }, }; +/* pwmss */ +static struct omap_hwmod_class_sysconfig dra7xx_epwmss_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x4, + .sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET, + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +/* + * epwmss class + */ +static struct omap_hwmod_class dra7xx_epwmss_hwmod_class = { + .name = "epwmss", + .sysc = &dra7xx_epwmss_sysc, +}; + +/* epwmss0 */ +static struct omap_hwmod dra7xx_epwmss0_hwmod = { + .name = "epwmss0", + .class = &dra7xx_epwmss_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .modulemode = MODULEMODE_SWCTRL, + .clkctrl_offs = DRA7XX_CM_L4PER2_PWMSS1_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_PWMSS1_CONTEXT_OFFSET, + }, + }, +}; + +/* epwmss1 */ +static struct omap_hwmod dra7xx_epwmss1_hwmod = { + .name = "epwmss1", + .class = &dra7xx_epwmss_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .modulemode = MODULEMODE_SWCTRL, + .clkctrl_offs = DRA7XX_CM_L4PER2_PWMSS2_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_PWMSS2_CONTEXT_OFFSET, + }, + }, +}; + +/* epwmss2 */ +static struct omap_hwmod dra7xx_epwmss2_hwmod = { + .name = "epwmss2", + .class = &dra7xx_epwmss_hwmod_class, + .clkdm_name = "l4per2_clkdm", + .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .modulemode = MODULEMODE_SWCTRL, + .clkctrl_offs = DRA7XX_CM_L4PER2_PWMSS3_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4PER2_PWMSS3_CONTEXT_OFFSET, + }, + }, +}; + /* * 'dma' class * @@ -3693,6 +3755,30 @@ static struct omap_hwmod_ocp_if dra7xx_l4_wkup__wd_timer2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* l4_per2 -> epwmss0 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__epwmss0 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_epwmss0_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU, +}; + +/* l4_per2 -> epwmss1 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__epwmss1 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_epwmss1_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU, +}; + +/* l4_per2 -> epwmss2 */ +static struct omap_hwmod_ocp_if dra7xx_l4_per2__epwmss2 = { + .master = &dra7xx_l4_per2_hwmod, + .slave = &dra7xx_epwmss2_hwmod, + .clk = "l4_root_clk_div", + .user = OCP_USER_MPU, +}; + static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l3_main_1__dmm, &dra7xx_l3_main_2__l3_instr, @@ -3814,6 +3900,9 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l3_main_1__vcp2, &dra7xx_l4_per2__vcp2, &dra7xx_l4_wkup__wd_timer2, + &dra7xx_l4_per2__epwmss0, + &dra7xx_l4_per2__epwmss1, + &dra7xx_l4_per2__epwmss2, NULL, }; -- GitLab From 461932dfb54ebaf7da438fd8b769a01ce97a9360 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Sun, 10 Apr 2016 13:20:10 -0600 Subject: [PATCH 1929/9938] ARM: OMAP2+: hwmod: RTC: Add lock and unlock functions RTC IP have kicker feature which prevents spurious writes to its registers. In order to write into any of the RTC registers, KICK values has to be written to KICK registers. Also, RTC busy flag needs to be polled for non-TC registers as well, without which update is not proper and confirmed it by testing on DRA7-evm. Introduce omap_hwmod_rtc_unlock/lock functions, which writes into these KICK registers inorder to lock and unlock RTC registers. Signed-off-by: Lokesh Vutla [paul@pwsan.com: fixed subject line] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.h | 2 + arch/arm/mach-omap2/omap_hwmod_reset.c | 65 ++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index 7c7a31169475..4041bad79a9a 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -754,6 +754,8 @@ const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh); */ extern int omap_hwmod_aess_preprogram(struct omap_hwmod *oh); +void omap_hwmod_rtc_unlock(struct omap_hwmod *oh); +void omap_hwmod_rtc_lock(struct omap_hwmod *oh); /* * Chip variant-specific hwmod init routines - XXX should be converted diff --git a/arch/arm/mach-omap2/omap_hwmod_reset.c b/arch/arm/mach-omap2/omap_hwmod_reset.c index 65e186c9df55..b68f9c0aff0b 100644 --- a/arch/arm/mach-omap2/omap_hwmod_reset.c +++ b/arch/arm/mach-omap2/omap_hwmod_reset.c @@ -29,6 +29,16 @@ #include #include "omap_hwmod.h" +#include "common.h" + +#define OMAP_RTC_STATUS_REG 0x44 +#define OMAP_RTC_KICK0_REG 0x6c +#define OMAP_RTC_KICK1_REG 0x70 + +#define OMAP_RTC_KICK0_VALUE 0x83E70B13 +#define OMAP_RTC_KICK1_VALUE 0x95A4F1E0 +#define OMAP_RTC_STATUS_BUSY BIT(0) +#define OMAP_RTC_MAX_READY_TIME 50 /** * omap_hwmod_aess_preprogram - enable AESS internal autogating @@ -51,3 +61,58 @@ int omap_hwmod_aess_preprogram(struct omap_hwmod *oh) return 0; } + +/** + * omap_rtc_wait_not_busy - Wait for the RTC BUSY flag + * @oh: struct omap_hwmod * + * + * For updating certain RTC registers, the MPU must wait + * for the BUSY status in OMAP_RTC_STATUS_REG to become zero. + * Once the BUSY status is zero, there is a 15 microseconds access + * period in which the MPU can program. + */ +static void omap_rtc_wait_not_busy(struct omap_hwmod *oh) +{ + int i; + + /* BUSY may stay active for 1/32768 second (~30 usec) */ + omap_test_timeout(omap_hwmod_read(oh, OMAP_RTC_STATUS_REG) + & OMAP_RTC_STATUS_BUSY, OMAP_RTC_MAX_READY_TIME, i); + /* now we have ~15 microseconds to read/write various registers */ +} + +/** + * omap_hwmod_rtc_unlock - Unlock the Kicker mechanism. + * @oh: struct omap_hwmod * + * + * RTC IP have kicker feature. This prevents spurious writes to its registers. + * In order to write into any of the RTC registers, KICK values has te be + * written in respective KICK registers. This is needed for hwmod to write into + * sysconfig register. + */ +void omap_hwmod_rtc_unlock(struct omap_hwmod *oh) +{ + local_irq_disable(); + omap_rtc_wait_not_busy(oh); + omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG); + omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG); + local_irq_enable(); +} + +/** + * omap_hwmod_rtc_lock - Lock the Kicker mechanism. + * @oh: struct omap_hwmod * + * + * RTC IP have kicker feature. This prevents spurious writes to its registers. + * Once the RTC registers are written, KICK mechanism needs to be locked, + * in order to prevent any spurious writes. This function locks back the RTC + * registers once hwmod completes its write into sysconfig register. + */ +void omap_hwmod_rtc_lock(struct omap_hwmod *oh) +{ + local_irq_disable(); + omap_rtc_wait_not_busy(oh); + omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG); + omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG); + local_irq_enable(); +} -- GitLab From d7d31b897050ce2c60960ebb6517fc228c52e9bb Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Sun, 10 Apr 2016 13:20:10 -0600 Subject: [PATCH 1930/9938] ARM: DRA7: RTC: Add lock and unlock functions Hook omap_hwmod_rtc_unlock/lock functions into RTC hwmod, so that SYSCONFIG register is updated properly Signed-off-by: Lokesh Vutla Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 2f15cf13e0d7..ace844b84207 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -1925,6 +1925,8 @@ static struct omap_hwmod_class_sysconfig dra7xx_rtcss_sysc = { static struct omap_hwmod_class dra7xx_rtcss_hwmod_class = { .name = "rtcss", .sysc = &dra7xx_rtcss_sysc, + .unlock = &omap_hwmod_rtc_unlock, + .lock = &omap_hwmod_rtc_lock, }; /* rtcss */ -- GitLab From b5a553c08bec14a058501df3fa6eb39f63f00a98 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Sun, 10 Apr 2016 13:20:10 -0600 Subject: [PATCH 1931/9938] ARM: AMx3xx: RTC: Add lock and unlock functions Hook omap_hwmod_rtc_unlock/lock functions into RTC hwmod, so that SYSCONFIG register is updated properly. Signed-off-by: Lokesh Vutla Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index 907a452b78ea..aed33621deeb 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -918,6 +918,8 @@ static struct omap_hwmod_class_sysconfig am33xx_rtc_sysc = { static struct omap_hwmod_class am33xx_rtc_hwmod_class = { .name = "rtc", .sysc = &am33xx_rtc_sysc, + .unlock = &omap_hwmod_rtc_unlock, + .lock = &omap_hwmod_rtc_lock, }; struct omap_hwmod am33xx_rtc_hwmod = { -- GitLab From 22d20cb4876eaee0c64960c69469e3631a61786f Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Sun, 10 Apr 2016 13:20:11 -0600 Subject: [PATCH 1932/9938] ARM: DRA7: hwmod: Add data for GPTimer 12 Add the hwmod data for GPTimer 12. GPTimer 12 is present in WKUPAON power domain and is clocked from a secure 32K clock. GPTimer 12 serves as a secure timer on HS devices, but is available for kernel on regular GP devices. The hwmod link is registered only on GP devices. The hwmod data also reused the existing timer class instead of reintroducing the identical dra7xx_timer_secure_sysc class which was dropped in commit edec17863362 ("ARM: DRA7: hwmod: Fix the hwmod class for GPTimer4"). Cc: Paul Walmsley Signed-off-by: Suman Anna Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 36 +++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index ace844b84207..d0e7e5259ec3 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -2285,6 +2285,20 @@ static struct omap_hwmod dra7xx_timer11_hwmod = { }, }; +/* timer12 */ +static struct omap_hwmod dra7xx_timer12_hwmod = { + .name = "timer12", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "wkupaon_clkdm", + .main_clk = "secure_32k_clk_src_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_WKUPAON_TIMER12_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_WKUPAON_TIMER12_CONTEXT_OFFSET, + }, + }, +}; + /* timer13 */ static struct omap_hwmod dra7xx_timer13_hwmod = { .name = "timer13", @@ -3573,6 +3587,14 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__timer11 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* l4_wkup -> timer12 */ +static struct omap_hwmod_ocp_if dra7xx_l4_wkup__timer12 = { + .master = &dra7xx_l4_wkup_hwmod, + .slave = &dra7xx_timer12_hwmod, + .clk = "wkupaon_iclk_mux", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l4_per3 -> timer13 */ static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer13 = { .master = &dra7xx_l4_per3_hwmod, @@ -3908,6 +3930,13 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { NULL, }; +/* GP-only hwmod links */ +static struct omap_hwmod_ocp_if *dra7xx_gp_hwmod_ocp_ifs[] __initdata = { + &dra7xx_l4_wkup__timer12, + NULL, +}; + +/* SoC variant specific hwmod links */ static struct omap_hwmod_ocp_if *dra74x_hwmod_ocp_ifs[] __initdata = { &dra7xx_l4_per3__usb_otg_ss4, NULL, @@ -3925,9 +3954,12 @@ int __init dra7xx_hwmod_init(void) ret = omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs); if (!ret && soc_is_dra74x()) - return omap_hwmod_register_links(dra74x_hwmod_ocp_ifs); + ret = omap_hwmod_register_links(dra74x_hwmod_ocp_ifs); else if (!ret && soc_is_dra72x()) - return omap_hwmod_register_links(dra72x_hwmod_ocp_ifs); + ret = omap_hwmod_register_links(dra72x_hwmod_ocp_ifs); + + if (!ret && omap_type() == OMAP2_DEVICE_TYPE_GP) + ret = omap_hwmod_register_links(dra7xx_gp_hwmod_ocp_ifs); return ret; } -- GitLab From c20c8f750d9f8f8617f07ee2352d3ff560e66bc2 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Sun, 10 Apr 2016 13:20:11 -0600 Subject: [PATCH 1933/9938] ARM: OMAP2+: hwmod: fix _idle() hwmod state sanity check sequence The omap_hwmod _enable() function can return success without setting the hwmod state to _HWMOD_STATE_ENABLED for IPs with reset lines when all of the reset lines are asserted. The omap_hwmod _idle() function also performs a similar check, but after checking for the hwmod state first. This triggers the WARN when pm_runtime_get and pm_runtime_put are invoked on IPs with all reset lines asserted. Reverse the checks for hwmod state and reset lines status to fix this. Issue found during a unbind operation on a device with reset lines still asserted, example backtrace below ------------[ cut here ]------------ WARNING: CPU: 1 PID: 879 at arch/arm/mach-omap2/omap_hwmod.c:2207 _idle+0x1e4/0x240() omap_hwmod: mmu_dsp: idle state can only be entered from enabled state Modules linked in: CPU: 1 PID: 879 Comm: sh Not tainted 4.4.0-00008-ga989d951331a #3 Hardware name: Generic OMAP5 (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x90/0xc0) [] (dump_stack) from [] (warn_slowpath_common+0x78/0xb4) [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) [] (warn_slowpath_fmt) from [] (_idle+0x1e4/0x240) [] (_idle) from [] (omap_hwmod_idle+0x28/0x48) [] (omap_hwmod_idle) from [] (omap_device_idle+0x3c/0x90) [] (omap_device_idle) from [] (__rpm_callback+0x2c/0x60) [] (__rpm_callback) from [] (rpm_callback+0x20/0x80) [] (rpm_callback) from [] (rpm_suspend+0x138/0x74c) [] (rpm_suspend) from [] (__pm_runtime_idle+0x78/0xa8) [] (__pm_runtime_idle) from [] (__device_release_driver+0x64/0x100) [] (__device_release_driver) from [] (device_release_driver+0x20/0x2c) [] (device_release_driver) from [] (unbind_store+0x78/0xf8) [] (unbind_store) from [] (kernfs_fop_write+0xc0/0x1c4) [] (kernfs_fop_write) from [] (__vfs_write+0x20/0xdc) [] (__vfs_write) from [] (vfs_write+0x90/0x164) [] (vfs_write) from [] (SyS_write+0x44/0x9c) [] (SyS_write) from [] (ret_fast_syscall+0x0/0x1c) ---[ end trace a4182013c75a9f50 ]--- While at this, fix the sequence in _shutdown() as well, though there is no easy reproducible scenario. Fixes: 747834ab8347 ("ARM: OMAP2+: hwmod: revise hardreset behavior") Signed-off-by: Suman Anna Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2af6ff63e3b4..83cb527755a9 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2207,15 +2207,15 @@ static int _idle(struct omap_hwmod *oh) pr_debug("omap_hwmod: %s: idling\n", oh->name); + if (_are_all_hardreset_lines_asserted(oh)) + return 0; + if (oh->_state != _HWMOD_STATE_ENABLED) { WARN(1, "omap_hwmod: %s: idle state can only be entered from enabled state\n", oh->name); return -EINVAL; } - if (_are_all_hardreset_lines_asserted(oh)) - return 0; - if (oh->class->sysc) _idle_sysc(oh); _del_initiator_dep(oh, mpu_oh); @@ -2262,6 +2262,9 @@ static int _shutdown(struct omap_hwmod *oh) int ret, i; u8 prev_state; + if (_are_all_hardreset_lines_asserted(oh)) + return 0; + if (oh->_state != _HWMOD_STATE_IDLE && oh->_state != _HWMOD_STATE_ENABLED) { WARN(1, "omap_hwmod: %s: disabled state can only be entered from idle, or enabled state\n", @@ -2269,9 +2272,6 @@ static int _shutdown(struct omap_hwmod *oh) return -EINVAL; } - if (_are_all_hardreset_lines_asserted(oh)) - return 0; - pr_debug("omap_hwmod: %s: disabling\n", oh->name); if (oh->class->pre_shutdown) { -- GitLab From fc64005c93090c052637f63578d810b037abb1a1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 Apr 2016 01:33:30 -0400 Subject: [PATCH 1934/9938] don't bother with ->d_inode->i_sb - it's always equal to ->d_sb ... and neither can ever be NULL Signed-off-by: Al Viro --- fs/9p/vfs_inode.c | 2 +- fs/btrfs/tree-log.c | 6 +++--- fs/cifs/cifs_dfs_ref.c | 2 +- fs/cifs/inode.c | 3 +-- fs/cifs/readdir.c | 2 +- fs/cifs/xattr.c | 16 ++++------------ fs/efs/namei.c | 2 +- fs/exofs/super.c | 2 +- fs/ext2/namei.c | 2 +- fs/ext4/namei.c | 4 ++-- fs/f2fs/namei.c | 2 +- fs/gfs2/ops_fstype.c | 2 +- fs/gfs2/super.c | 2 +- fs/jffs2/dir.c | 2 +- fs/jffs2/super.c | 2 +- fs/jfs/namei.c | 2 +- fs/namei.c | 4 ++-- fs/nfs/direct.c | 2 +- fs/nfsd/nfs3proc.c | 4 ++-- fs/nfsd/nfs3xdr.c | 2 +- fs/nfsd/nfsfh.c | 2 +- fs/nilfs2/namei.c | 2 +- fs/ocfs2/file.c | 2 +- fs/udf/namei.c | 2 +- fs/ufs/super.c | 2 +- include/trace/events/ext4.h | 6 +++--- kernel/audit_watch.c | 2 +- security/integrity/evm/evm_main.c | 4 ++-- security/selinux/hooks.c | 2 +- security/smack/smack_lsm.c | 2 +- 30 files changed, 41 insertions(+), 50 deletions(-) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 3a08b3e6ff1d..f4645c515262 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1071,7 +1071,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, if (IS_ERR(st)) return PTR_ERR(st); - v9fs_stat2inode(st, d_inode(dentry), d_inode(dentry)->i_sb); + v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb); generic_fillattr(d_inode(dentry), stat); p9stat_free(st); diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 24d03c751149..a82e20ecbee1 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4851,7 +4851,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, goto out; if (!S_ISDIR(inode->i_mode)) { - if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb) + if (!parent || d_really_is_negative(parent) || sb != parent->d_sb) goto out; inode = d_inode(parent); } @@ -4872,7 +4872,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, break; } - if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb) + if (!parent || d_really_is_negative(parent) || sb != parent->d_sb) break; if (IS_ROOT(parent)) @@ -5285,7 +5285,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, } while (1) { - if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb) + if (!parent || d_really_is_negative(parent) || sb != parent->d_sb) break; inode = d_inode(parent); diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index e956cba94338..94f2c8a9ae6d 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -302,7 +302,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) if (full_path == NULL) goto cdda_exit; - cifs_sb = CIFS_SB(d_inode(mntpt)->i_sb); + cifs_sb = CIFS_SB(mntpt->d_sb); tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) { mnt = ERR_CAST(tlink); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index aeb26dbfa1bf..4cd4705ebfad 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -2418,8 +2418,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) int cifs_setattr(struct dentry *direntry, struct iattr *attrs) { - struct inode *inode = d_inode(direntry); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb); if (pTcon->unix_ext) diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b30a4a6d98a0..4cfb4d9f88e2 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -78,7 +78,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, { struct dentry *dentry, *alias; struct inode *inode; - struct super_block *sb = d_inode(parent)->i_sb; + struct super_block *sb = parent->d_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); cifs_dbg(FYI, "%s: for %s\n", __func__, name->name); diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index f5dc2f0df4ad..612de933431f 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -52,9 +52,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) return -EIO; if (d_really_is_negative(direntry)) return -EIO; - sb = d_inode(direntry)->i_sb; - if (sb == NULL) - return -EIO; + sb = direntry->d_sb; cifs_sb = CIFS_SB(sb); tlink = cifs_sb_tlink(cifs_sb); @@ -113,9 +111,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, return -EIO; if (d_really_is_negative(direntry)) return -EIO; - sb = d_inode(direntry)->i_sb; - if (sb == NULL) - return -EIO; + sb = direntry->d_sb; cifs_sb = CIFS_SB(sb); tlink = cifs_sb_tlink(cifs_sb); @@ -248,9 +244,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, return -EIO; if (d_really_is_negative(direntry)) return -EIO; - sb = d_inode(direntry)->i_sb; - if (sb == NULL) - return -EIO; + sb = direntry->d_sb; cifs_sb = CIFS_SB(sb); tlink = cifs_sb_tlink(cifs_sb); @@ -384,9 +378,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) return -EIO; if (d_really_is_negative(direntry)) return -EIO; - sb = d_inode(direntry)->i_sb; - if (sb == NULL) - return -EIO; + sb = direntry->d_sb; cifs_sb = CIFS_SB(sb); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 40ba9cc41bf7..d34a40edcdb2 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c @@ -113,7 +113,7 @@ struct dentry *efs_get_parent(struct dentry *child) ino = efs_find_entry(d_inode(child), "..", 2); if (ino) - parent = d_obtain_alias(efs_iget(d_inode(child)->i_sb, ino)); + parent = d_obtain_alias(efs_iget(child->d_sb, ino)); return parent; } diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 6658a50530a0..192373653dfb 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -958,7 +958,7 @@ static struct dentry *exofs_get_parent(struct dentry *child) if (!ino) return ERR_PTR(-ESTALE); - return d_obtain_alias(exofs_iget(d_inode(child)->i_sb, ino)); + return d_obtain_alias(exofs_iget(child->d_sb, ino)); } static struct inode *exofs_nfs_get_inode(struct super_block *sb, diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 7a2be8f7f3c3..1a7eb49a115d 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -82,7 +82,7 @@ struct dentry *ext2_get_parent(struct dentry *child) unsigned long ino = ext2_inode_by_name(d_inode(child), &dotdot); if (!ino) return ERR_PTR(-ENOENT); - return d_obtain_alias(ext2_iget(d_inode(child)->i_sb, ino)); + return d_obtain_alias(ext2_iget(child->d_sb, ino)); } /* diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 48e4b8907826..5611ec9348d7 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1638,13 +1638,13 @@ struct dentry *ext4_get_parent(struct dentry *child) ino = le32_to_cpu(de->inode); brelse(bh); - if (!ext4_valid_inum(d_inode(child)->i_sb, ino)) { + if (!ext4_valid_inum(child->d_sb, ino)) { EXT4_ERROR_INODE(d_inode(child), "bad parent inode number: %u", ino); return ERR_PTR(-EFSCORRUPTED); } - return d_obtain_alias(ext4_iget_normal(d_inode(child)->i_sb, ino)); + return d_obtain_alias(ext4_iget_normal(child->d_sb, ino)); } /* diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 7876f1052101..db874ad3514a 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -202,7 +202,7 @@ struct dentry *f2fs_get_parent(struct dentry *child) unsigned long ino = f2fs_inode_by_name(d_inode(child), &dotdot); if (!ino) return ERR_PTR(-ENOENT); - return d_obtain_alias(f2fs_iget(d_inode(child)->i_sb, ino)); + return d_obtain_alias(f2fs_iget(child->d_sb, ino)); } static int __recover_dot_dentries(struct inode *dir, nid_t pino) diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 49b0bff18fe3..c09c63dcd7a2 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1360,7 +1360,7 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type, return ERR_PTR(error); } s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags, - d_inode(path.dentry)->i_sb->s_bdev); + path.dentry->d_sb->s_bdev); path_put(&path); if (IS_ERR(s)) { pr_warn("gfs2 mount does not exist\n"); diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index f8a0cd821290..9b2ff353e45f 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1176,7 +1176,7 @@ static int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *s static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct super_block *sb = d_inode(dentry)->i_sb; + struct super_block *sb = dentry->d_sb; struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_statfs_change_host sc; int error; diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 30c4c9ebb693..7a9579e03dbb 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -241,7 +241,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) { - struct jffs2_sb_info *c = JFFS2_SB_INFO(d_inode(old_dentry)->i_sb); + struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry)); struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); int ret; diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 0a9a114bb9d1..5ef21f4c4c77 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -147,7 +147,7 @@ static struct dentry *jffs2_get_parent(struct dentry *child) JFFS2_DEBUG("Parent of directory ino #%u is #%u\n", f->inocache->ino, pino); - return d_obtain_alias(jffs2_iget(d_inode(child)->i_sb, pino)); + return d_obtain_alias(jffs2_iget(child->d_sb, pino)); } static const struct export_operations jffs2_export_ops = { diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 701f89370de7..8a40941ac9a6 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1524,7 +1524,7 @@ struct dentry *jfs_get_parent(struct dentry *dentry) parent_ino = le32_to_cpu(JFS_IP(d_inode(dentry))->i_dtroot.header.idotdot); - return d_obtain_alias(jfs_iget(d_inode(dentry)->i_sb, parent_ino)); + return d_obtain_alias(jfs_iget(dentry->d_sb, parent_ino)); } const struct inode_operations jfs_dir_inode_operations = { diff --git a/fs/namei.c b/fs/namei.c index 3498d53de26f..c0d551fc43a0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2653,7 +2653,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) return NULL; } - mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex); + mutex_lock(&p1->d_sb->s_vfs_rename_mutex); p = d_ancestor(p2, p1); if (p) { @@ -2680,7 +2680,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) inode_unlock(p1->d_inode); if (p1 != p2) { inode_unlock(p2->d_inode); - mutex_unlock(&p1->d_inode->i_sb->s_vfs_rename_mutex); + mutex_unlock(&p1->d_sb->s_vfs_rename_mutex); } } EXPORT_SYMBOL(unlock_rename); diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 7a0cfd3266e5..e5daa932b823 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -396,7 +396,7 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) static void nfs_direct_readpage_release(struct nfs_page *req) { dprintk("NFS: direct read done (%s/%llu %d@%lld)\n", - d_inode(req->wb_context->dentry)->i_sb->s_id, + req->wb_context->dentry->d_sb->s_id, (unsigned long long)NFS_FILEID(d_inode(req->wb_context->dentry)), req->wb_bytes, (long long)req_offset(req)); diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 51c3b06e8036..d818e4ffd79f 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -552,7 +552,7 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, * different read/write sizes for file systems known to have * problems with large blocks */ if (nfserr == 0) { - struct super_block *sb = d_inode(argp->fh.fh_dentry)->i_sb; + struct super_block *sb = argp->fh.fh_dentry->d_sb; /* Note that we don't care for remote fs's here */ if (sb->s_magic == MSDOS_SUPER_MAGIC) { @@ -588,7 +588,7 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP); if (nfserr == 0) { - struct super_block *sb = d_inode(argp->fh.fh_dentry)->i_sb; + struct super_block *sb = argp->fh.fh_dentry->d_sb; /* Note that we don't care for remote fs's here */ switch (sb->s_magic) { diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 2246454dec76..93d5853f8c99 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -146,7 +146,7 @@ static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp) default: case FSIDSOURCE_DEV: p = xdr_encode_hyper(p, (u64)huge_encode_dev - (d_inode(fhp->fh_dentry)->i_sb->s_dev)); + (fhp->fh_dentry->d_sb->s_dev)); break; case FSIDSOURCE_FSID: p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index c1681ce894c5..a8919444c460 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -426,7 +426,7 @@ static bool is_root_export(struct svc_export *exp) static struct super_block *exp_sb(struct svc_export *exp) { - return d_inode(exp->ex_path.dentry)->i_sb; + return exp->ex_path.dentry->d_sb; } static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp) diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 7ccdb961eea9..38d67f3e25bc 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -457,7 +457,7 @@ static struct dentry *nilfs_get_parent(struct dentry *child) root = NILFS_I(d_inode(child))->i_root; - inode = nilfs_iget(d_inode(child)->i_sb, root, ino); + inode = nilfs_iget(child->d_sb, root, ino); if (IS_ERR(inode)) return ERR_CAST(inode); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index c18ab45f8d21..c6fdcbd46bba 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1290,7 +1290,7 @@ int ocfs2_getattr(struct vfsmount *mnt, struct kstat *stat) { struct inode *inode = d_inode(dentry); - struct super_block *sb = d_inode(dentry)->i_sb; + struct super_block *sb = dentry->d_sb; struct ocfs2_super *osb = sb->s_fs_info; int err; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index a2ba11eca995..c3e5c9679371 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -1250,7 +1250,7 @@ static struct dentry *udf_get_parent(struct dentry *child) brelse(fibh.sbh); tloc = lelb_to_cpu(cfi.icb.extLocation); - inode = udf_iget(d_inode(child)->i_sb, &tloc); + inode = udf_iget(child->d_sb, &tloc); if (IS_ERR(inode)) return ERR_CAST(inode); diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 442fd52ebffe..f04ab232d08d 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -132,7 +132,7 @@ static struct dentry *ufs_get_parent(struct dentry *child) ino = ufs_inode_by_name(d_inode(child), &dot_dot); if (!ino) return ERR_PTR(-ENOENT); - return d_obtain_alias(ufs_iget(d_inode(child)->i_sb, ino)); + return d_obtain_alias(ufs_iget(child->d_sb, ino)); } static const struct export_operations ufs_export_ops = { diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index 4e4b2fa78609..09c71e9aaebf 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h @@ -872,7 +872,7 @@ TRACE_EVENT(ext4_sync_file_enter, TP_fast_assign( struct dentry *dentry = file->f_path.dentry; - __entry->dev = d_inode(dentry)->i_sb->s_dev; + __entry->dev = dentry->d_sb->s_dev; __entry->ino = d_inode(dentry)->i_ino; __entry->datasync = datasync; __entry->parent = d_inode(dentry->d_parent)->i_ino; @@ -1451,7 +1451,7 @@ TRACE_EVENT(ext4_unlink_enter, ), TP_fast_assign( - __entry->dev = d_inode(dentry)->i_sb->s_dev; + __entry->dev = dentry->d_sb->s_dev; __entry->ino = d_inode(dentry)->i_ino; __entry->parent = parent->i_ino; __entry->size = d_inode(dentry)->i_size; @@ -1475,7 +1475,7 @@ TRACE_EVENT(ext4_unlink_exit, ), TP_fast_assign( - __entry->dev = d_inode(dentry)->i_sb->s_dev; + __entry->dev = dentry->d_sb->s_dev; __entry->ino = d_inode(dentry)->i_ino; __entry->ret = ret; ), diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 3cf1c5978d39..d6709eb70970 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -367,7 +367,7 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent) inode_unlock(d_backing_inode(parent->dentry)); if (d_is_positive(d)) { /* update watch filter fields */ - watch->dev = d_backing_inode(d)->i_sb->s_dev; + watch->dev = d->d_sb->s_dev; watch->ino = d_backing_inode(d)->i_ino; } dput(d); diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index e6ea9d4b1de9..84c6d11fc096 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -299,8 +299,8 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, return 0; /* exception for pseudo filesystems */ - if (dentry->d_inode->i_sb->s_magic == TMPFS_MAGIC - || dentry->d_inode->i_sb->s_magic == SYSFS_MAGIC) + if (dentry->d_sb->s_magic == TMPFS_MAGIC + || dentry->d_sb->s_magic == SYSFS_MAGIC) return 0; integrity_audit_msg(AUDIT_INTEGRITY_METADATA, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 912deee3f01e..889cd59ca5a7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1316,7 +1316,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry, u32 *sid) { int rc; - struct super_block *sb = dentry->d_inode->i_sb; + struct super_block *sb = dentry->d_sb; char *buffer, *path; buffer = (char *)__get_free_page(GFP_KERNEL); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 11f79013ae1f..50bcca26c0b7 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1444,7 +1444,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) * XATTR_NAME_SMACKIPOUT */ if (strcmp(name, XATTR_NAME_SMACK) == 0) { - struct super_block *sbp = d_backing_inode(dentry)->i_sb; + struct super_block *sbp = dentry->d_sb; struct superblock_smack *sbsp = sbp->s_security; isp->smk_inode = sbsp->smk_default; -- GitLab From 5fdccfef483d088fcc533b282bf6953579d6d6f4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 Apr 2016 17:07:33 -0400 Subject: [PATCH 1935/9938] cifs: kill more bogus checks in ->...xattr() methods none of that stuff can ever be called for NULL or negative dentry. Signed-off-by: Al Viro --- fs/cifs/xattr.c | 42 ++++++------------------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 612de933431f..159547c8a40b 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -42,19 +42,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) int rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR unsigned int xid; - struct cifs_sb_info *cifs_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); struct tcon_link *tlink; struct cifs_tcon *pTcon; - struct super_block *sb; char *full_path = NULL; - if (direntry == NULL) - return -EIO; - if (d_really_is_negative(direntry)) - return -EIO; - sb = direntry->d_sb; - - cifs_sb = CIFS_SB(sb); tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) return PTR_ERR(tlink); @@ -101,19 +93,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, int rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR unsigned int xid; - struct cifs_sb_info *cifs_sb; + struct super_block *sb = direntry->d_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct tcon_link *tlink; struct cifs_tcon *pTcon; - struct super_block *sb; char *full_path; - if (direntry == NULL) - return -EIO; - if (d_really_is_negative(direntry)) - return -EIO; - sb = direntry->d_sb; - - cifs_sb = CIFS_SB(sb); tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) return PTR_ERR(tlink); @@ -234,19 +219,12 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, ssize_t rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR unsigned int xid; - struct cifs_sb_info *cifs_sb; + struct super_block *sb = direntry->d_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct tcon_link *tlink; struct cifs_tcon *pTcon; - struct super_block *sb; char *full_path; - if (direntry == NULL) - return -EIO; - if (d_really_is_negative(direntry)) - return -EIO; - sb = direntry->d_sb; - - cifs_sb = CIFS_SB(sb); tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) return PTR_ERR(tlink); @@ -368,19 +346,11 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ssize_t rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR unsigned int xid; - struct cifs_sb_info *cifs_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); struct tcon_link *tlink; struct cifs_tcon *pTcon; - struct super_block *sb; char *full_path; - if (direntry == NULL) - return -EIO; - if (d_really_is_negative(direntry)) - return -EIO; - sb = direntry->d_sb; - - cifs_sb = CIFS_SB(sb); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) return -EOPNOTSUPP; -- GitLab From 79a628d14ec7ee9adfdc3ce04343d5ff7ec20c18 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 Apr 2016 18:50:48 -0400 Subject: [PATCH 1936/9938] reiserfs: switch to generic_{get,set,remove}xattr() reiserfs_xattr_[sg]et() will fail with -EOPNOTSUPP for V1 inodes anyway, and all reiserfs instances of ->[sg]et() call it and so does ->set_acl(). Checks for name length in the instances had been bogus; they should've been "bugger off if it's _exactly_ the prefix" (as generic would do on its own) and not "bugger off if it's shorter than the prefix" - that can't happen. xattr_full_name() is needed to adjust for the fact that generic instances will skip the prefix in the name passed to ->[gs]et(); reiserfs homegrown analogues didn't. Signed-off-by: Al Viro --- fs/reiserfs/file.c | 6 ++-- fs/reiserfs/namei.c | 18 ++++++------ fs/reiserfs/xattr.c | 54 ------------------------------------ fs/reiserfs/xattr.h | 9 +----- fs/reiserfs/xattr_security.c | 14 ++++------ fs/reiserfs/xattr_trusted.c | 14 ++++------ fs/reiserfs/xattr_user.c | 14 ++++------ 7 files changed, 31 insertions(+), 98 deletions(-) diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 9424a4ba93a9..9ffaf7145644 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -260,10 +260,10 @@ const struct file_operations reiserfs_file_operations = { const struct inode_operations reiserfs_file_inode_operations = { .setattr = reiserfs_setattr, - .setxattr = reiserfs_setxattr, - .getxattr = reiserfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = reiserfs_listxattr, - .removexattr = reiserfs_removexattr, + .removexattr = generic_removexattr, .permission = reiserfs_permission, .get_acl = reiserfs_get_acl, .set_acl = reiserfs_set_acl, diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 2a12d46d7fb4..8a36696d6df9 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -1650,10 +1650,10 @@ const struct inode_operations reiserfs_dir_inode_operations = { .mknod = reiserfs_mknod, .rename = reiserfs_rename, .setattr = reiserfs_setattr, - .setxattr = reiserfs_setxattr, - .getxattr = reiserfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = reiserfs_listxattr, - .removexattr = reiserfs_removexattr, + .removexattr = generic_removexattr, .permission = reiserfs_permission, .get_acl = reiserfs_get_acl, .set_acl = reiserfs_set_acl, @@ -1667,10 +1667,10 @@ const struct inode_operations reiserfs_symlink_inode_operations = { .readlink = generic_readlink, .get_link = page_get_link, .setattr = reiserfs_setattr, - .setxattr = reiserfs_setxattr, - .getxattr = reiserfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = reiserfs_listxattr, - .removexattr = reiserfs_removexattr, + .removexattr = generic_removexattr, .permission = reiserfs_permission, }; @@ -1679,10 +1679,10 @@ const struct inode_operations reiserfs_symlink_inode_operations = { */ const struct inode_operations reiserfs_special_inode_operations = { .setattr = reiserfs_setattr, - .setxattr = reiserfs_setxattr, - .getxattr = reiserfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = reiserfs_listxattr, - .removexattr = reiserfs_removexattr, + .removexattr = generic_removexattr, .permission = reiserfs_permission, .get_acl = reiserfs_get_acl, .set_acl = reiserfs_set_acl, diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 57e0b2310532..02137bbda0ec 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -764,60 +764,6 @@ find_xattr_handler_prefix(const struct xattr_handler **handlers, return xah; } - -/* - * Inode operation getxattr() - */ -ssize_t -reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, - size_t size) -{ - const struct xattr_handler *handler; - - handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); - - if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1) - return -EOPNOTSUPP; - - return handler->get(handler, dentry, name, buffer, size); -} - -/* - * Inode operation setxattr() - * - * d_inode(dentry)->i_mutex down - */ -int -reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) -{ - const struct xattr_handler *handler; - - handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); - - if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1) - return -EOPNOTSUPP; - - return handler->set(handler, dentry, name, value, size, flags); -} - -/* - * Inode operation removexattr() - * - * d_inode(dentry)->i_mutex down - */ -int reiserfs_removexattr(struct dentry *dentry, const char *name) -{ - const struct xattr_handler *handler; - - handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); - - if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1) - return -EOPNOTSUPP; - - return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE); -} - struct listxattr_buf { struct dir_context ctx; size_t size; diff --git a/fs/reiserfs/xattr.h b/fs/reiserfs/xattr.h index 15dde6262c00..613ff5aef94e 100644 --- a/fs/reiserfs/xattr.h +++ b/fs/reiserfs/xattr.h @@ -2,6 +2,7 @@ #include #include #include +#include struct inode; struct dentry; @@ -18,12 +19,7 @@ int reiserfs_permission(struct inode *inode, int mask); #ifdef CONFIG_REISERFS_FS_XATTR #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir) -ssize_t reiserfs_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size); -int reiserfs_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size); -int reiserfs_removexattr(struct dentry *dentry, const char *name); int reiserfs_xattr_get(struct inode *, const char *, void *, size_t); int reiserfs_xattr_set(struct inode *, const char *, const void *, size_t, int); @@ -92,10 +88,7 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode) #else -#define reiserfs_getxattr NULL -#define reiserfs_setxattr NULL #define reiserfs_listxattr NULL -#define reiserfs_removexattr NULL static inline void reiserfs_init_xattr_rwsem(struct inode *inode) { diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index ab0217d32039..ac7e104ada6b 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c @@ -12,26 +12,24 @@ static int security_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX)) - return -EINVAL; - if (IS_PRIVATE(d_inode(dentry))) return -EPERM; - return reiserfs_xattr_get(d_inode(dentry), name, buffer, size); + return reiserfs_xattr_get(d_inode(dentry), + xattr_full_name(handler, name), + buffer, size); } static int security_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { - if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX)) - return -EINVAL; - if (IS_PRIVATE(d_inode(dentry))) return -EPERM; - return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); + return reiserfs_xattr_set(d_inode(dentry), + xattr_full_name(handler, name), + buffer, size, flags); } static bool security_list(struct dentry *dentry) diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c index 64b67aa643a9..cc248a581b60 100644 --- a/fs/reiserfs/xattr_trusted.c +++ b/fs/reiserfs/xattr_trusted.c @@ -11,26 +11,24 @@ static int trusted_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry))) return -EPERM; - return reiserfs_xattr_get(d_inode(dentry), name, buffer, size); + return reiserfs_xattr_get(d_inode(dentry), + xattr_full_name(handler, name), + buffer, size); } static int trusted_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { - if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry))) return -EPERM; - return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); + return reiserfs_xattr_set(d_inode(dentry), + xattr_full_name(handler, name), + buffer, size, flags); } static bool trusted_list(struct dentry *dentry) diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c index 12e6306f562a..caad583086af 100644 --- a/fs/reiserfs/xattr_user.c +++ b/fs/reiserfs/xattr_user.c @@ -10,24 +10,22 @@ static int user_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - - if (strlen(name) < sizeof(XATTR_USER_PREFIX)) - return -EINVAL; if (!reiserfs_xattrs_user(dentry->d_sb)) return -EOPNOTSUPP; - return reiserfs_xattr_get(d_inode(dentry), name, buffer, size); + return reiserfs_xattr_get(d_inode(dentry), + xattr_full_name(handler, name), + buffer, size); } static int user_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { - if (strlen(name) < sizeof(XATTR_USER_PREFIX)) - return -EINVAL; - if (!reiserfs_xattrs_user(dentry->d_sb)) return -EOPNOTSUPP; - return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); + return reiserfs_xattr_set(d_inode(dentry), + xattr_full_name(handler, name), + buffer, size, flags); } static bool user_list(struct dentry *dentry) -- GitLab From b296821a7c42fa58baa17513b2b7b30ae66f3336 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 Apr 2016 20:48:24 -0400 Subject: [PATCH 1937/9938] xattr_handler: pass dentry and inode as separate arguments of ->get() ... and do not assume they are already attached to each other Signed-off-by: Al Viro --- fs/9p/acl.c | 6 +++--- fs/9p/xattr.c | 4 ++-- fs/btrfs/xattr.c | 6 ++---- fs/ext2/xattr_security.c | 6 +++--- fs/ext2/xattr_trusted.c | 6 +++--- fs/ext2/xattr_user.c | 8 ++++---- fs/ext4/xattr_security.c | 6 +++--- fs/ext4/xattr_trusted.c | 6 +++--- fs/ext4/xattr_user.c | 8 ++++---- fs/f2fs/xattr.c | 14 ++++++-------- fs/gfs2/xattr.c | 6 +++--- fs/hfsplus/xattr.c | 10 +++++----- fs/hfsplus/xattr.h | 2 +- fs/hfsplus/xattr_security.c | 6 +++--- fs/hfsplus/xattr_trusted.c | 6 +++--- fs/hfsplus/xattr_user.c | 6 +++--- fs/jffs2/security.c | 6 +++--- fs/jffs2/xattr_trusted.c | 6 +++--- fs/jffs2/xattr_user.c | 6 +++--- fs/nfs/nfs4proc.c | 12 ++++++------ fs/ocfs2/xattr.c | 20 ++++++++++---------- fs/orangefs/xattr.c | 10 ++++++---- fs/posix_acl.c | 10 +++++----- fs/reiserfs/xattr_security.c | 9 ++++----- fs/reiserfs/xattr_trusted.c | 9 ++++----- fs/reiserfs/xattr_user.c | 9 ++++----- fs/squashfs/xattr.c | 6 ++++-- fs/xattr.c | 3 ++- fs/xfs/xfs_xattr.c | 6 +++--- include/linux/xattr.h | 3 ++- mm/shmem.c | 6 +++--- 31 files changed, 113 insertions(+), 114 deletions(-) diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 2d94e94b6b59..eb3589edf485 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -213,8 +213,8 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep, } static int v9fs_xattr_get_acl(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { struct v9fs_session_info *v9ses; struct posix_acl *acl; @@ -227,7 +227,7 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler, if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) return v9fs_xattr_get(dentry, handler->name, buffer, size); - acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags); + acl = v9fs_get_cached_acl(inode, handler->flags); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index 9dd9b47a6c1a..18c62bae9591 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c @@ -138,8 +138,8 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) } static int v9fs_xattr_handler_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { const char *full_name = xattr_full_name(handler, name); diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 145d2b89e62d..03224b00ea70 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -369,11 +369,9 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) } static int btrfs_xattr_handler_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct inode *inode = d_inode(dentry); - name = xattr_full_name(handler, name); return __btrfs_getxattr(inode, name, buffer, size); } diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index ba97f243b050..7fd3b867ce65 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c @@ -9,10 +9,10 @@ static int ext2_xattr_security_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name, buffer, size); } diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c index 2c94d1930626..0f85705ff519 100644 --- a/fs/ext2/xattr_trusted.c +++ b/fs/ext2/xattr_trusted.c @@ -16,10 +16,10 @@ ext2_xattr_trusted_list(struct dentry *dentry) static int ext2_xattr_trusted_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name, buffer, size); } diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c index 72a2a96d677f..1fafd27037cc 100644 --- a/fs/ext2/xattr_user.c +++ b/fs/ext2/xattr_user.c @@ -18,12 +18,12 @@ ext2_xattr_user_list(struct dentry *dentry) static int ext2_xattr_user_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - if (!test_opt(dentry->d_sb, XATTR_USER)) + if (!test_opt(inode->i_sb, XATTR_USER)) return -EOPNOTSUPP; - return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER, + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, buffer, size); } diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index 3e81bdca071a..123a7d010efe 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c @@ -13,10 +13,10 @@ static int ext4_xattr_security_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY, + return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY, name, buffer, size); } diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c index 2a3c6f9b8cb8..60652fa24cbc 100644 --- a/fs/ext4/xattr_trusted.c +++ b/fs/ext4/xattr_trusted.c @@ -20,10 +20,10 @@ ext4_xattr_trusted_list(struct dentry *dentry) static int ext4_xattr_trusted_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, void *buffer, - size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED, + return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED, name, buffer, size); } diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c index d152f431e432..17a446ffecd3 100644 --- a/fs/ext4/xattr_user.c +++ b/fs/ext4/xattr_user.c @@ -19,12 +19,12 @@ ext4_xattr_user_list(struct dentry *dentry) static int ext4_xattr_user_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - if (!test_opt(dentry->d_sb, XATTR_USER)) + if (!test_opt(inode->i_sb, XATTR_USER)) return -EOPNOTSUPP; - return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER, + return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER, name, buffer, size); } diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 06a72dc0191a..17fd2b1a6848 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -26,10 +26,10 @@ #include "xattr.h" static int f2fs_xattr_generic_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, void *buffer, - size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); switch (handler->flags) { case F2FS_XATTR_INDEX_USER: @@ -45,7 +45,7 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler, default: return -EINVAL; } - return f2fs_getxattr(d_inode(dentry), handler->flags, name, + return f2fs_getxattr(inode, handler->flags, name, buffer, size, NULL); } @@ -86,11 +86,9 @@ static bool f2fs_xattr_trusted_list(struct dentry *dentry) } static int f2fs_xattr_advise_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, void *buffer, - size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct inode *inode = d_inode(dentry); - if (buffer) *((char *)buffer) = F2FS_I(inode)->i_advise; return sizeof(char); diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index e8dfb4740c04..619886ba6e78 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -584,10 +584,10 @@ int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **ppdata) * Returns: actual size of data on success, -errno on error */ static int gfs2_xattr_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct gfs2_inode *ip = GFS2_I(d_inode(dentry)); + struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_ea_location el; int type = handler->flags; int error; diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index ab01530b4930..45dc4ae3791a 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -579,7 +579,7 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, return res; } -ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, +ssize_t hfsplus_getxattr(struct inode *inode, const char *name, void *value, size_t size, const char *prefix, size_t prefixlen) { @@ -594,7 +594,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, strcpy(xattr_name, prefix); strcpy(xattr_name + prefixlen, name); - res = __hfsplus_getxattr(d_inode(dentry), xattr_name, value, size); + res = __hfsplus_getxattr(inode, xattr_name, value, size); kfree(xattr_name); return res; @@ -844,8 +844,8 @@ static int hfsplus_removexattr(struct inode *inode, const char *name) } static int hfsplus_osx_getxattr(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { /* * Don't allow retrieving properly prefixed attributes @@ -860,7 +860,7 @@ static int hfsplus_osx_getxattr(const struct xattr_handler *handler, * creates), so we pass the name through unmodified (after * ensuring it doesn't conflict with another namespace). */ - return __hfsplus_getxattr(d_inode(dentry), name, buffer, size); + return __hfsplus_getxattr(inode, name, buffer, size); } static int hfsplus_osx_setxattr(const struct xattr_handler *handler, diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h index f9b0955b3d28..d04ba6f58df2 100644 --- a/fs/hfsplus/xattr.h +++ b/fs/hfsplus/xattr.h @@ -28,7 +28,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name, ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, void *value, size_t size); -ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, +ssize_t hfsplus_getxattr(struct inode *inode, const char *name, void *value, size_t size, const char *prefix, size_t prefixlen); diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c index 72a68a3a0c99..ae2ca8c2e335 100644 --- a/fs/hfsplus/xattr_security.c +++ b/fs/hfsplus/xattr_security.c @@ -14,10 +14,10 @@ #include "acl.h" static int hfsplus_security_getxattr(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return hfsplus_getxattr(dentry, name, buffer, size, + return hfsplus_getxattr(inode, name, buffer, size, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN); } diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c index 95a7704c7abb..eae2947060aa 100644 --- a/fs/hfsplus/xattr_trusted.c +++ b/fs/hfsplus/xattr_trusted.c @@ -12,10 +12,10 @@ #include "xattr.h" static int hfsplus_trusted_getxattr(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return hfsplus_getxattr(dentry, name, buffer, size, + return hfsplus_getxattr(inode, name, buffer, size, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); } diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c index 6fc269baf959..3c9eec3e4c7b 100644 --- a/fs/hfsplus/xattr_user.c +++ b/fs/hfsplus/xattr_user.c @@ -12,11 +12,11 @@ #include "xattr.h" static int hfsplus_user_getxattr(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return hfsplus_getxattr(dentry, name, buffer, size, + return hfsplus_getxattr(inode, name, buffer, size, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); } diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index 7a28facd7175..3ed9a4b49778 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c @@ -49,10 +49,10 @@ int jffs2_init_security(struct inode *inode, struct inode *dir, /* ---- XATTR Handler for "security.*" ----------------- */ static int jffs2_security_getxattr(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY, + return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size); } diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c index b2555ef07a12..4ebecff1d922 100644 --- a/fs/jffs2/xattr_trusted.c +++ b/fs/jffs2/xattr_trusted.c @@ -17,10 +17,10 @@ #include "nodelist.h" static int jffs2_trusted_getxattr(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED, + return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size); } diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c index 539bd630b5e4..bce249e1b277 100644 --- a/fs/jffs2/xattr_user.c +++ b/fs/jffs2/xattr_user.c @@ -17,10 +17,10 @@ #include "nodelist.h" static int jffs2_user_getxattr(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER, + return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size); } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 327b8c34d360..7a7ac1dafa02 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6263,10 +6263,10 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler, } static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler, - struct dentry *dentry, const char *key, - void *buf, size_t buflen) + struct dentry *unused, struct inode *inode, + const char *key, void *buf, size_t buflen) { - return nfs4_proc_get_acl(d_inode(dentry), buf, buflen); + return nfs4_proc_get_acl(inode, buf, buflen); } static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry) @@ -6288,11 +6288,11 @@ static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler, } static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler, - struct dentry *dentry, const char *key, - void *buf, size_t buflen) + struct dentry *unused, struct inode *inode, + const char *key, void *buf, size_t buflen) { if (security_ismaclabel(key)) - return nfs4_get_security_label(d_inode(dentry), buf, buflen); + return nfs4_get_security_label(inode, buf, buflen); return -EOPNOTSUPP; } diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 7d3d979f57d9..72eef4cfe8a9 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -7250,10 +7250,10 @@ int ocfs2_init_security_and_acl(struct inode *dir, * 'security' attributes support */ static int ocfs2_xattr_security_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY, + return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY, name, buffer, size); } @@ -7321,10 +7321,10 @@ const struct xattr_handler ocfs2_xattr_security_handler = { * 'trusted' attributes support */ static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED, + return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED, name, buffer, size); } @@ -7346,14 +7346,14 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = { * 'user' attributes support */ static int ocfs2_xattr_user_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unusde, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) return -EOPNOTSUPP; - return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name, + return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name, buffer, size); } diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c index ef5da7538cd5..6a4c0f7ce5c1 100644 --- a/fs/orangefs/xattr.c +++ b/fs/orangefs/xattr.c @@ -478,12 +478,13 @@ static int orangefs_xattr_set_default(const struct xattr_handler *handler, } static int orangefs_xattr_get_default(const struct xattr_handler *handler, - struct dentry *dentry, + struct dentry *unused, + struct inode *inode, const char *name, void *buffer, size_t size) { - return orangefs_inode_getxattr(dentry->d_inode, + return orangefs_inode_getxattr(inode, ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, name, buffer, @@ -507,12 +508,13 @@ static int orangefs_xattr_set_trusted(const struct xattr_handler *handler, } static int orangefs_xattr_get_trusted(const struct xattr_handler *handler, - struct dentry *dentry, + struct dentry *unused, + struct inode *inode, const char *name, void *buffer, size_t size) { - return orangefs_inode_getxattr(dentry->d_inode, + return orangefs_inode_getxattr(inode, ORANGEFS_XATTR_NAME_TRUSTED_PREFIX, name, buffer, diff --git a/fs/posix_acl.c b/fs/posix_acl.c index db1fb0f5d9ff..2c60f17e7d92 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -797,18 +797,18 @@ EXPORT_SYMBOL (posix_acl_to_xattr); static int posix_acl_xattr_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *value, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *value, size_t size) { struct posix_acl *acl; int error; - if (!IS_POSIXACL(d_backing_inode(dentry))) + if (!IS_POSIXACL(inode)) return -EOPNOTSUPP; - if (d_is_symlink(dentry)) + if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; - acl = get_acl(d_backing_inode(dentry), handler->flags); + acl = get_acl(inode, handler->flags); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index ac7e104ada6b..86aeb9dd805a 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c @@ -9,14 +9,13 @@ #include static int -security_get(const struct xattr_handler *handler, struct dentry *dentry, - const char *name, void *buffer, size_t size) +security_get(const struct xattr_handler *handler, struct dentry *unused, + struct inode *inode, const char *name, void *buffer, size_t size) { - if (IS_PRIVATE(d_inode(dentry))) + if (IS_PRIVATE(inode)) return -EPERM; - return reiserfs_xattr_get(d_inode(dentry), - xattr_full_name(handler, name), + return reiserfs_xattr_get(inode, xattr_full_name(handler, name), buffer, size); } diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c index cc248a581b60..31837f031f59 100644 --- a/fs/reiserfs/xattr_trusted.c +++ b/fs/reiserfs/xattr_trusted.c @@ -8,14 +8,13 @@ #include static int -trusted_get(const struct xattr_handler *handler, struct dentry *dentry, - const char *name, void *buffer, size_t size) +trusted_get(const struct xattr_handler *handler, struct dentry *unused, + struct inode *inode, const char *name, void *buffer, size_t size) { - if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry))) + if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode)) return -EPERM; - return reiserfs_xattr_get(d_inode(dentry), - xattr_full_name(handler, name), + return reiserfs_xattr_get(inode, xattr_full_name(handler, name), buffer, size); } diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c index caad583086af..f7c39731684b 100644 --- a/fs/reiserfs/xattr_user.c +++ b/fs/reiserfs/xattr_user.c @@ -7,13 +7,12 @@ #include static int -user_get(const struct xattr_handler *handler, struct dentry *dentry, - const char *name, void *buffer, size_t size) +user_get(const struct xattr_handler *handler, struct dentry *unused, + struct inode *inode, const char *name, void *buffer, size_t size) { - if (!reiserfs_xattrs_user(dentry->d_sb)) + if (!reiserfs_xattrs_user(inode->i_sb)) return -EOPNOTSUPP; - return reiserfs_xattr_get(d_inode(dentry), - xattr_full_name(handler, name), + return reiserfs_xattr_get(inode, xattr_full_name(handler, name), buffer, size); } diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c index 1e9de96288d8..1548b3784548 100644 --- a/fs/squashfs/xattr.c +++ b/fs/squashfs/xattr.c @@ -214,10 +214,12 @@ static int squashfs_xattr_get(struct inode *inode, int name_index, static int squashfs_xattr_handler_get(const struct xattr_handler *handler, - struct dentry *d, const char *name, + struct dentry *unused, + struct inode *inode, + const char *name, void *buffer, size_t size) { - return squashfs_xattr_get(d_inode(d), handler->flags, name, + return squashfs_xattr_get(inode, handler->flags, name, buffer, size); } diff --git a/fs/xattr.c b/fs/xattr.c index 4861322e28e8..461ba45b7da9 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -698,7 +698,8 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); if (IS_ERR(handler)) return PTR_ERR(handler); - return handler->get(handler, dentry, name, buffer, size); + return handler->get(handler, dentry, d_inode(dentry), + name, buffer, size); } /* diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 110f1d7d86b0..d111f691f313 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -32,11 +32,11 @@ static int -xfs_xattr_get(const struct xattr_handler *handler, struct dentry *dentry, - const char *name, void *value, size_t size) +xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused, + struct inode *inode, const char *name, void *value, size_t size) { int xflags = handler->flags; - struct xfs_inode *ip = XFS_I(d_inode(dentry)); + struct xfs_inode *ip = XFS_I(inode); int error, asize = size; /* Convert Linux syscall to XFS internal ATTR flags */ diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 4457541de3c9..c11c022298b9 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -30,7 +30,8 @@ struct xattr_handler { int flags; /* fs private flags */ bool (*list)(struct dentry *dentry); int (*get)(const struct xattr_handler *, struct dentry *dentry, - const char *name, void *buffer, size_t size); + struct inode *inode, const char *name, void *buffer, + size_t size); int (*set)(const struct xattr_handler *, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags); diff --git a/mm/shmem.c b/mm/shmem.c index 9428c51ab2d6..00d5d025eece 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2646,10 +2646,10 @@ static int shmem_initxattrs(struct inode *inode, } static int shmem_xattr_handler_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct shmem_inode_info *info = SHMEM_I(d_inode(dentry)); + struct shmem_inode_info *info = SHMEM_I(inode); name = xattr_full_name(handler, name); return simple_xattr_get(&info->xattrs, name, buffer, size); -- GitLab From 4a4bdfea7cb75b5c8b222932796f64a14027d512 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 10 Feb 2016 11:10:44 -0600 Subject: [PATCH 1938/9938] powerpc/pseries: Refactor dlpar_add_lmb() code Re-factor dlpar_lmb_add() routine by moving the validation of the lmb flags and the acquireing of the DRC to a wrapper around the work to add the memory to the system. This is done to make handling of errors during the addition of the memory easier and to facilitate the upcoming addition of updating the lmb's affinity prior to adding the memory. Signed-off-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- .../platforms/pseries/hotplug-memory.c | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index e9ff44cd5d86..294acfd8a422 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -384,43 +384,32 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop) #endif /* CONFIG_MEMORY_HOTREMOVE */ -static int dlpar_add_lmb(struct of_drconf_cell *lmb) +static int dlpar_add_lmb_memory(struct of_drconf_cell *lmb) { struct memory_block *mem_block; unsigned long block_sz; int nid, rc; - if (lmb->flags & DRCONF_MEM_ASSIGNED) - return -EINVAL; - block_sz = memory_block_size_bytes(); - rc = dlpar_acquire_drc(lmb->drc_index); - if (rc) - return rc; - /* Find the node id for this address */ nid = memory_add_physaddr_to_nid(lmb->base_addr); /* Add the memory */ rc = add_memory(nid, lmb->base_addr, block_sz); - if (rc) { - dlpar_release_drc(lmb->drc_index); + if (rc) return rc; - } /* Register this block of memory */ rc = memblock_add(lmb->base_addr, block_sz); if (rc) { remove_memory(nid, lmb->base_addr, block_sz); - dlpar_release_drc(lmb->drc_index); return rc; } mem_block = lmb_to_memblock(lmb); if (!mem_block) { remove_memory(nid, lmb->base_addr, block_sz); - dlpar_release_drc(lmb->drc_index); return -EINVAL; } @@ -428,7 +417,6 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb) put_device(&mem_block->dev); if (rc) { remove_memory(nid, lmb->base_addr, block_sz); - dlpar_release_drc(lmb->drc_index); return rc; } @@ -436,6 +424,24 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb) return 0; } +static int dlpar_add_lmb(struct of_drconf_cell *lmb) +{ + int rc; + + if (lmb->flags & DRCONF_MEM_ASSIGNED) + return -EINVAL; + + rc = dlpar_acquire_drc(lmb->drc_index); + if (rc) + return rc; + + rc = dlpar_add_lmb_memory(lmb); + if (rc) + dlpar_release_drc(lmb->drc_index); + + return rc; +} + static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop) { struct of_drconf_cell *lmbs; -- GitLab From bdf5fc6338047cfeba98d2ab629997f3013e610f Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 10 Feb 2016 11:12:13 -0600 Subject: [PATCH 1939/9938] powerpc/pseries: Update LMB associativity index during DLPAR add/remove The associativity array index specified for a LMB in the device tree, /ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory, needs to be updated prior to DLPAR adding a LMB and after DLPAR removing a LMB. Without doing this step in the DLPAR add process a LMB could be configured with the incorrect affinity. For a LMB that was not present at boot the affinity index is set to 0xffffffff, which defaults to adding the LMB to the first online node since the index is not a valid value. Or, the affinity index could contain a stale value if the LMB was present at boot but later DLPAR removed and is being DLPAR added back to the system. This patch adds a step in the DLPAR add flow to look up the associativity index for a LMB prior to adding a LMB and setting the associativity to 0xffffffff when a LMB is removed. This patch also modifies the DLPAR add/remove flow to no longer do a single update of the device tree property after all of the requested DLPAR operations are complete and now does a property update during the add or remove of each LMB. Signed-off-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- .../platforms/pseries/hotplug-memory.c | 193 +++++++++++++++--- 1 file changed, 162 insertions(+), 31 deletions(-) diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 294acfd8a422..2ce138542083 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -116,6 +116,155 @@ static struct property *dlpar_clone_drconf_property(struct device_node *dn) return new_prop; } +static void dlpar_update_drconf_property(struct device_node *dn, + struct property *prop) +{ + struct of_drconf_cell *lmbs; + u32 num_lmbs, *p; + int i; + + /* Convert the property back to BE */ + p = prop->value; + num_lmbs = *p; + *p = cpu_to_be32(*p); + p++; + + lmbs = (struct of_drconf_cell *)p; + for (i = 0; i < num_lmbs; i++) { + lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr); + lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index); + lmbs[i].flags = cpu_to_be32(lmbs[i].flags); + } + + rtas_hp_event = true; + of_update_property(dn, prop); + rtas_hp_event = false; +} + +static int dlpar_update_device_tree_lmb(struct of_drconf_cell *lmb) +{ + struct device_node *dn; + struct property *prop; + struct of_drconf_cell *lmbs; + u32 *p, num_lmbs; + int i; + + dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); + if (!dn) + return -ENODEV; + + prop = dlpar_clone_drconf_property(dn); + if (!prop) { + of_node_put(dn); + return -ENODEV; + } + + p = prop->value; + num_lmbs = *p++; + lmbs = (struct of_drconf_cell *)p; + + for (i = 0; i < num_lmbs; i++) { + if (lmbs[i].drc_index == lmb->drc_index) { + lmbs[i].flags = lmb->flags; + lmbs[i].aa_index = lmb->aa_index; + + dlpar_update_drconf_property(dn, prop); + break; + } + } + + of_node_put(dn); + return 0; +} + +static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb) +{ + struct device_node *parent, *lmb_node, *dr_node; + const u32 *lmb_assoc; + const u32 *assoc_arrays; + u32 aa_index; + int aa_arrays, aa_array_entries, aa_array_sz; + int i; + + parent = of_find_node_by_path("/"); + if (!parent) + return -ENODEV; + + lmb_node = dlpar_configure_connector(cpu_to_be32(lmb->drc_index), + parent); + of_node_put(parent); + if (!lmb_node) + return -EINVAL; + + lmb_assoc = of_get_property(lmb_node, "ibm,associativity", NULL); + if (!lmb_assoc) { + dlpar_free_cc_nodes(lmb_node); + return -ENODEV; + } + + dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); + if (!dr_node) { + dlpar_free_cc_nodes(lmb_node); + return -ENODEV; + } + + assoc_arrays = of_get_property(dr_node, + "ibm,associativity-lookup-arrays", + NULL); + of_node_put(dr_node); + if (!assoc_arrays) { + dlpar_free_cc_nodes(lmb_node); + return -ENODEV; + } + + /* The ibm,associativity-lookup-arrays property is defined to be + * a 32-bit value specifying the number of associativity arrays + * followed by a 32-bitvalue specifying the number of entries per + * array, followed by the associativity arrays. + */ + aa_arrays = be32_to_cpu(assoc_arrays[0]); + aa_array_entries = be32_to_cpu(assoc_arrays[1]); + aa_array_sz = aa_array_entries * sizeof(u32); + + aa_index = -1; + for (i = 0; i < aa_arrays; i++) { + int indx = (i * aa_array_entries) + 2; + + if (memcmp(&assoc_arrays[indx], &lmb_assoc[1], aa_array_sz)) + continue; + + aa_index = i; + break; + } + + dlpar_free_cc_nodes(lmb_node); + return aa_index; +} + +static int dlpar_add_device_tree_lmb(struct of_drconf_cell *lmb) +{ + int aa_index; + + lmb->flags |= DRCONF_MEM_ASSIGNED; + + aa_index = lookup_lmb_associativity_index(lmb); + if (aa_index < 0) { + pr_err("Couldn't find associativity index for drc index %x\n", + lmb->drc_index); + return aa_index; + } + + lmb->aa_index = aa_index; + return dlpar_update_device_tree_lmb(lmb); +} + +static int dlpar_remove_device_tree_lmb(struct of_drconf_cell *lmb) +{ + lmb->flags &= ~DRCONF_MEM_ASSIGNED; + lmb->aa_index = 0xffffffff; + return dlpar_update_device_tree_lmb(lmb); +} + static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb) { unsigned long section_nr; @@ -243,8 +392,8 @@ static int dlpar_remove_lmb(struct of_drconf_cell *lmb) memblock_remove(lmb->base_addr, block_sz); dlpar_release_drc(lmb->drc_index); + dlpar_remove_device_tree_lmb(lmb); - lmb->flags &= ~DRCONF_MEM_ASSIGNED; return 0; } @@ -435,9 +584,19 @@ static int dlpar_add_lmb(struct of_drconf_cell *lmb) if (rc) return rc; + rc = dlpar_add_device_tree_lmb(lmb); + if (rc) { + pr_err("Couldn't update device tree for drc index %x\n", + lmb->drc_index); + dlpar_release_drc(lmb->drc_index); + return rc; + } + rc = dlpar_add_lmb_memory(lmb); - if (rc) + if (rc) { + dlpar_remove_device_tree_lmb(lmb); dlpar_release_drc(lmb->drc_index); + } return rc; } @@ -542,31 +701,6 @@ static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop) return rc; } -static void dlpar_update_drconf_property(struct device_node *dn, - struct property *prop) -{ - struct of_drconf_cell *lmbs; - u32 num_lmbs, *p; - int i; - - /* Convert the property back to BE */ - p = prop->value; - num_lmbs = *p; - *p = cpu_to_be32(*p); - p++; - - lmbs = (struct of_drconf_cell *)p; - for (i = 0; i < num_lmbs; i++) { - lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr); - lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index); - lmbs[i].flags = cpu_to_be32(lmbs[i].flags); - } - - rtas_hp_event = true; - of_update_property(dn, prop); - rtas_hp_event = false; -} - int dlpar_memory(struct pseries_hp_errorlog *hp_elog) { struct device_node *dn; @@ -614,10 +748,7 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) break; } - if (rc) - dlpar_free_drconf_property(prop); - else - dlpar_update_drconf_property(dn, prop); + dlpar_free_drconf_property(prop); dlpar_memory_out: of_node_put(dn); -- GitLab From d88e397f12ba0c8c672952c4711d7280525c54ed Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Wed, 9 Mar 2016 12:53:13 +0100 Subject: [PATCH 1940/9938] cxl: Remove dead code Function cxl_get_phys_dev() was removed from the kernel API by a previous patch, but it's actually dead code. Remove it. Signed-off-by: Frederic Barrat Acked-by: Ian Munsie Reviewed-by: Andrew Donnellan Acked-by: Michael Neuling Signed-off-by: Michael Ellerman --- drivers/misc/cxl/api.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 2107c948406d..807582335a98 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -68,15 +68,6 @@ struct cxl_context *cxl_get_context(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(cxl_get_context); -struct device *cxl_get_phys_dev(struct pci_dev *dev) -{ - struct cxl_afu *afu; - - afu = cxl_pci_to_afu(dev); - - return afu->adapter->dev.parent; -} - int cxl_release_context(struct cxl_context *ctx) { if (ctx->status >= STARTED) -- GitLab From 3c9d6296b7aee536a96ea2b53a15d23511738c1c Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Fri, 8 Apr 2016 12:20:30 +0200 Subject: [PATCH 1941/9938] security: drop the unused hook skb_owned_by The skb_owned_by hook was added with the commit ca10b9e9a8ca ("selinux: add a skb_owned_by() hook") and later removed when said commit was reverted. Later on, when switching to list of hooks, a field named 'skb_owned_by' was included into the security_hook_head struct, but without any users nor caller. This commit removes the said left-over field. Fixes: b1d9e6b0646d ("LSM: Switch to lists of hooks") Signed-off-by: Paolo Abeni Acked-by: Casey Schaufler Acked-by: Paul Moore Signed-off-by: James Morris --- include/linux/lsm_hooks.h | 1 - security/security.c | 1 - 2 files changed, 2 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index cdee11cbcdf1..ae2537886177 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1804,7 +1804,6 @@ struct security_hook_heads { struct list_head tun_dev_attach_queue; struct list_head tun_dev_attach; struct list_head tun_dev_open; - struct list_head skb_owned_by; #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM struct list_head xfrm_policy_alloc_security; diff --git a/security/security.c b/security/security.c index 3644b0344d29..554c3fb7d4a5 100644 --- a/security/security.c +++ b/security/security.c @@ -1848,7 +1848,6 @@ struct security_hook_heads security_hook_heads = { .tun_dev_attach = LIST_HEAD_INIT(security_hook_heads.tun_dev_attach), .tun_dev_open = LIST_HEAD_INIT(security_hook_heads.tun_dev_open), - .skb_owned_by = LIST_HEAD_INIT(security_hook_heads.skb_owned_by), #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM .xfrm_policy_alloc_security = -- GitLab From 4923ec0b10d998349c2ac4b38aa4674e539e6f92 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 6 Apr 2016 19:39:21 -0700 Subject: [PATCH 1942/9938] bpf: simplify verifier register state assignments verifier is using the following structure to track the state of registers: struct reg_state { enum bpf_reg_type type; union { int imm; struct bpf_map *map_ptr; }; }; and later on in states_equal() does memcmp(&old->regs[i], &cur->regs[i],..) to find equivalent states. Throughout the code of verifier there are assignements to 'imm' and 'map_ptr' fields and it's not obvious that most of the assignments into 'imm' don't need to clear extra 4 bytes (like mark_reg_unknown_value() does) to make sure that memcmp doesn't go over junk left from 'map_ptr' assignment. Simplify the code by converting 'int' into 'long' Suggested-by: Daniel Borkmann Signed-off-by: Alexei Starovoitov Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- kernel/bpf/verifier.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 8233021538d3..6c5d7cd4cb0e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -142,7 +142,7 @@ struct reg_state { enum bpf_reg_type type; union { /* valid when type == CONST_IMM | PTR_TO_STACK */ - int imm; + long imm; /* valid when type == CONST_PTR_TO_MAP | PTR_TO_MAP_VALUE | * PTR_TO_MAP_VALUE_OR_NULL @@ -263,7 +263,7 @@ static void print_verifier_state(struct verifier_env *env) continue; verbose(" R%d=%s", i, reg_type_str[t]); if (t == CONST_IMM || t == PTR_TO_STACK) - verbose("%d", env->cur_state.regs[i].imm); + verbose("%ld", env->cur_state.regs[i].imm); else if (t == CONST_PTR_TO_MAP || t == PTR_TO_MAP_VALUE || t == PTR_TO_MAP_VALUE_OR_NULL) verbose("(ks=%d,vs=%d)", @@ -480,7 +480,6 @@ static void init_reg_state(struct reg_state *regs) for (i = 0; i < MAX_BPF_REG; i++) { regs[i].type = NOT_INIT; regs[i].imm = 0; - regs[i].map_ptr = NULL; } /* frame pointer */ @@ -495,7 +494,6 @@ static void mark_reg_unknown_value(struct reg_state *regs, u32 regno) BUG_ON(regno >= MAX_BPF_REG); regs[regno].type = UNKNOWN_VALUE; regs[regno].imm = 0; - regs[regno].map_ptr = NULL; } enum reg_arg_type { -- GitLab From ce23e640133484eebc20ca7b7668388213e11327 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 11 Apr 2016 00:48:00 -0400 Subject: [PATCH 1943/9938] ->getxattr(): pass dentry and inode as separate arguments Signed-off-by: Al Viro --- Documentation/filesystems/porting | 6 +++++ .../lustre/lustre/llite/llite_internal.h | 4 ++-- drivers/staging/lustre/lustre/llite/xattr.c | 6 ++--- fs/bad_inode.c | 4 ++-- fs/ceph/super.h | 2 +- fs/ceph/xattr.c | 8 +++---- fs/cifs/cifsfs.h | 2 +- fs/cifs/xattr.c | 6 ++--- fs/ecryptfs/crypto.c | 5 +++- fs/ecryptfs/ecryptfs_kernel.h | 4 ++-- fs/ecryptfs/inode.c | 23 ++++++++++--------- fs/ecryptfs/mmap.c | 3 ++- fs/fuse/dir.c | 5 ++-- fs/gfs2/inode.c | 9 ++++---- fs/hfs/attr.c | 5 ++-- fs/hfs/hfs_fs.h | 4 ++-- fs/jfs/jfs_xattr.h | 2 +- fs/jfs/xattr.c | 8 +++---- fs/kernfs/inode.c | 6 ++--- fs/kernfs/kernfs-internal.h | 4 ++-- fs/libfs.c | 4 ++-- fs/overlayfs/inode.c | 4 ++-- fs/overlayfs/overlayfs.h | 4 ++-- fs/overlayfs/super.c | 2 +- fs/ubifs/ubifs.h | 4 ++-- fs/ubifs/xattr.c | 6 ++--- fs/xattr.c | 11 +++++---- include/linux/fs.h | 3 ++- include/linux/xattr.h | 2 +- net/socket.c | 2 +- security/commoncap.c | 6 ++--- security/integrity/evm/evm_main.c | 2 +- security/selinux/hooks.c | 9 ++++---- security/smack/smack_lsm.c | 4 ++-- 34 files changed, 94 insertions(+), 85 deletions(-) diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index f1b87d8aa2da..57bb3754a027 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -525,3 +525,9 @@ in your dentry operations instead. set_delayed_call() where it used to set *cookie. ->put_link() is gone - just give the destructor to set_delayed_call() in ->get_link(). +-- +[mandatory] + ->getxattr() and xattr_handler.get() get dentry and inode passed separately. + dentry might be yet to be attached to inode, so do _not_ use its ->d_inode + in the instances. Rationale: !@#!@# security_d_instantiate() needs to be + called before we attach dentry to inode. diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 3e1572cb457b..d28efd27af57 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1042,8 +1042,8 @@ static inline __u64 ll_file_maxbytes(struct inode *inode) /* llite/xattr.c */ int ll_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -ssize_t ll_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size); +ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size); ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size); int ll_removexattr(struct dentry *dentry, const char *name); diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index b68dcc921ca2..c671f221c28c 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -451,11 +451,9 @@ int ll_getxattr_common(struct inode *inode, const char *name, return rc; } -ssize_t ll_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size) +ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct inode *inode = d_inode(dentry); - LASSERT(inode); LASSERT(name); diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 103f5d7c3083..72e35b721608 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -106,8 +106,8 @@ static int bad_inode_setxattr(struct dentry *dentry, const char *name, return -EIO; } -static ssize_t bad_inode_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size) +static ssize_t bad_inode_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { return -EIO; } diff --git a/fs/ceph/super.h b/fs/ceph/super.h index e705c4d612d7..beb893bb234f 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -795,7 +795,7 @@ extern int ceph_setxattr(struct dentry *, const char *, const void *, int __ceph_setxattr(struct dentry *, const char *, const void *, size_t, int); ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t); int __ceph_removexattr(struct dentry *, const char *); -extern ssize_t ceph_getxattr(struct dentry *, const char *, void *, size_t); +extern ssize_t ceph_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); extern ssize_t ceph_listxattr(struct dentry *, char *, size_t); extern int ceph_removexattr(struct dentry *, const char *); extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 9410abdef3ce..c6e917d360f7 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -804,13 +804,13 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, return err; } -ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, - size_t size) +ssize_t ceph_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) { if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_getxattr(dentry, name, value, size); + return generic_getxattr(dentry, inode, name, value, size); - return __ceph_getxattr(d_inode(dentry), name, value, size); + return __ceph_getxattr(inode, name, value, size); } ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 83aac8ba50b0..c89ecd7a5c39 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -123,7 +123,7 @@ extern int cifs_symlink(struct inode *inode, struct dentry *direntry, extern int cifs_removexattr(struct dentry *, const char *); extern int cifs_setxattr(struct dentry *, const char *, const void *, size_t, int); -extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); +extern ssize_t cifs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); #ifdef CONFIG_CIFS_NFSD_EXPORT diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 159547c8a40b..5d57c85703a9 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -213,8 +213,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, return rc; } -ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, - void *ea_value, size_t buf_size) +ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, + const char *ea_name, void *ea_value, size_t buf_size) { ssize_t rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR @@ -296,7 +296,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, goto get_ea_exit; /* rc already EOPNOTSUPP */ pacl = pTcon->ses->server->ops->get_acl(cifs_sb, - d_inode(direntry), full_path, &acllen); + inode, full_path, &acllen); if (IS_ERR(pacl)) { rc = PTR_ERR(pacl); cifs_dbg(VFS, "%s: error %zd getting sec desc\n", diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 64026e53722a..543a146ee019 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1369,7 +1369,9 @@ int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode) ssize_t size; int rc = 0; - size = ecryptfs_getxattr_lower(lower_dentry, ECRYPTFS_XATTR_NAME, + size = ecryptfs_getxattr_lower(lower_dentry, + ecryptfs_inode_to_lower(ecryptfs_inode), + ECRYPTFS_XATTR_NAME, page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); if (size < 0) { if (unlikely(ecryptfs_verbosity > 0)) @@ -1391,6 +1393,7 @@ int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry, int rc; rc = ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), + ecryptfs_inode_to_lower(inode), ECRYPTFS_XATTR_NAME, file_size, ECRYPTFS_SIZE_AND_MARKER_BYTES); if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index d123fbaa28e0..6ff907f73331 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -607,8 +607,8 @@ ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *src, struct dentry *ecryptfs_dentry); int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); ssize_t -ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name, - void *value, size_t size); +ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode, + const char *name, void *value, size_t size); int ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 121114e9a464..1ac631cd9d84 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -1033,29 +1033,30 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, } ssize_t -ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name, - void *value, size_t size) +ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode, + const char *name, void *value, size_t size) { int rc = 0; - if (!d_inode(lower_dentry)->i_op->getxattr) { + if (!lower_inode->i_op->getxattr) { rc = -EOPNOTSUPP; goto out; } - inode_lock(d_inode(lower_dentry)); - rc = d_inode(lower_dentry)->i_op->getxattr(lower_dentry, name, value, - size); - inode_unlock(d_inode(lower_dentry)); + inode_lock(lower_inode); + rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode, + name, value, size); + inode_unlock(lower_inode); out: return rc; } static ssize_t -ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, - size_t size) +ecryptfs_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) { - return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), name, - value, size); + return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), + ecryptfs_inode_to_lower(inode), + name, value, size); } static ssize_t diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 1f5865263b3e..39e4381d3a65 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -436,7 +436,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) goto out; } inode_lock(lower_inode); - size = lower_inode->i_op->getxattr(lower_dentry, ECRYPTFS_XATTR_NAME, + size = lower_inode->i_op->getxattr(lower_dentry, lower_inode, + ECRYPTFS_XATTR_NAME, xattr_virt, PAGE_CACHE_SIZE); if (size < 0) size = 8; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 4b855b65d457..b618527c05c6 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1759,10 +1759,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name, return err; } -static ssize_t fuse_getxattr(struct dentry *entry, const char *name, - void *value, size_t size) +static ssize_t fuse_getxattr(struct dentry *entry, struct inode *inode, + const char *name, void *value, size_t size) { - struct inode *inode = d_inode(entry); struct fuse_conn *fc = get_fuse_conn(inode); FUSE_ARGS(args); struct fuse_getxattr_in inarg; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index bb30f9a72c65..45f516cada78 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1968,22 +1968,21 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name, return ret; } -static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name, - void *data, size_t size) +static ssize_t gfs2_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *data, size_t size) { - struct inode *inode = d_inode(dentry); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int ret; /* For selinux during lookup */ if (gfs2_glock_is_locked_by_me(ip->i_gl)) - return generic_getxattr(dentry, name, data, size); + return generic_getxattr(dentry, inode, name, data, size); gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); ret = gfs2_glock_nq(&gh); if (ret == 0) { - ret = generic_getxattr(dentry, name, data, size); + ret = generic_getxattr(dentry, inode, name, data, size); gfs2_glock_dq(&gh); } gfs2_holder_uninit(&gh); diff --git a/fs/hfs/attr.c b/fs/hfs/attr.c index 8d931b157bbe..064f92f17efc 100644 --- a/fs/hfs/attr.c +++ b/fs/hfs/attr.c @@ -56,10 +56,9 @@ int hfs_setxattr(struct dentry *dentry, const char *name, return res; } -ssize_t hfs_getxattr(struct dentry *dentry, const char *name, - void *value, size_t size) +ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode, + const char *name, void *value, size_t size) { - struct inode *inode = d_inode(dentry); struct hfs_find_data fd; hfs_cat_rec rec; struct hfs_cat_file *file; diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 1f1c7dcbcc2f..79daa097929a 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -213,8 +213,8 @@ extern void hfs_delete_inode(struct inode *); /* attr.c */ extern int hfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -extern ssize_t hfs_getxattr(struct dentry *dentry, const char *name, - void *value, size_t size); +extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size); extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size); /* mdb.c */ diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h index e8d717dabca3..e69e14f3777b 100644 --- a/fs/jfs/jfs_xattr.h +++ b/fs/jfs/jfs_xattr.h @@ -57,7 +57,7 @@ extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *, extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); -extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t); +extern ssize_t jfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); extern int jfs_removexattr(struct dentry *, const char *); diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 48b15a6e5558..5becc6a3ff8c 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -933,8 +933,8 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, return size; } -ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data, - size_t buf_size) +ssize_t jfs_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *data, size_t buf_size) { int err; @@ -944,7 +944,7 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data, * for it via sb->s_xattr. */ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_getxattr(dentry, name, data, buf_size); + return generic_getxattr(dentry, inode, name, data, buf_size); if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { /* @@ -959,7 +959,7 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data, return -EOPNOTSUPP; } - err = __jfs_getxattr(d_inode(dentry), name, data, buf_size); + err = __jfs_getxattr(inode, name, data, buf_size); return err; } diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 16405ae88d2d..b5247226732b 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -208,10 +208,10 @@ int kernfs_iop_removexattr(struct dentry *dentry, const char *name) return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE); } -ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, - size_t size) +ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode, + const char *name, void *buf, size_t size) { - struct kernfs_node *kn = dentry->d_fsdata; + struct kernfs_node *kn = inode->i_private; struct kernfs_iattrs *attrs; attrs = kernfs_iattrs(kn); diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 6762bfbd8207..45c9192c276e 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -84,8 +84,8 @@ int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, int kernfs_iop_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int kernfs_iop_removexattr(struct dentry *dentry, const char *name); -ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, - size_t size); +ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *buf, size_t size); ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); /* diff --git a/fs/libfs.c b/fs/libfs.c index 0ca80b2af420..03332f4bdedf 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1127,8 +1127,8 @@ static int empty_dir_setxattr(struct dentry *dentry, const char *name, return -EOPNOTSUPP; } -static ssize_t empty_dir_getxattr(struct dentry *dentry, const char *name, - void *value, size_t size) +static ssize_t empty_dir_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) { return -EOPNOTSUPP; } diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index a4ff5d0d7db9..c7b31a03dc9c 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -246,8 +246,8 @@ static bool ovl_need_xattr_filter(struct dentry *dentry, return false; } -ssize_t ovl_getxattr(struct dentry *dentry, const char *name, - void *value, size_t size) +ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) { struct path realpath; enum ovl_path_type type = ovl_path_real(dentry, &realpath); diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 6a7090f4a441..99ec4b035237 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -173,8 +173,8 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr); int ovl_permission(struct inode *inode, int mask); int ovl_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -ssize_t ovl_getxattr(struct dentry *dentry, const char *name, - void *value, size_t size); +ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size); ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); int ovl_removexattr(struct dentry *dentry, const char *name); struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index ef64984c9bbc..14cab381cece 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -274,7 +274,7 @@ static bool ovl_is_opaquedir(struct dentry *dentry) if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr) return false; - res = inode->i_op->getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1); + res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1); if (res == 1 && val == 'y') return true; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index c2a57e193a81..536fb495f2f1 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1734,8 +1734,8 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, /* xattr.c */ int ubifs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, - size_t size); +ssize_t ubifs_getxattr(struct dentry *dentry, struct inode *host, + const char *name, void *buf, size_t size); ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size); int ubifs_removexattr(struct dentry *dentry, const char *name); int ubifs_init_security(struct inode *dentry, struct inode *inode, diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index b043e044121d..413d650c9476 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -372,10 +372,10 @@ int ubifs_setxattr(struct dentry *dentry, const char *name, return setxattr(d_inode(dentry), name, value, size, flags); } -ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, - size_t size) +ssize_t ubifs_getxattr(struct dentry *dentry, struct inode *host, + const char *name, void *buf, size_t size) { - struct inode *inode, *host = d_inode(dentry); + struct inode *inode; struct ubifs_info *c = host->i_sb->s_fs_info; struct qstr nm = QSTR_INIT(name, strlen(name)); struct ubifs_inode *ui; diff --git a/fs/xattr.c b/fs/xattr.c index 461ba45b7da9..b11945e15fde 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -192,7 +192,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, if (!inode->i_op->getxattr) return -EOPNOTSUPP; - error = inode->i_op->getxattr(dentry, name, NULL, 0); + error = inode->i_op->getxattr(dentry, inode, name, NULL, 0); if (error < 0) return error; @@ -203,7 +203,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, memset(value, 0, error + 1); } - error = inode->i_op->getxattr(dentry, name, value, error); + error = inode->i_op->getxattr(dentry, inode, name, value, error); *xattr_value = value; return error; } @@ -236,7 +236,7 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) } nolsm: if (inode->i_op->getxattr) - error = inode->i_op->getxattr(dentry, name, value, size); + error = inode->i_op->getxattr(dentry, inode, name, value, size); else error = -EOPNOTSUPP; @@ -691,14 +691,15 @@ xattr_resolve_name(const struct xattr_handler **handlers, const char **name) * Find the handler for the prefix and dispatch its get() operation. */ ssize_t -generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size) +generic_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { const struct xattr_handler *handler; handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); if (IS_ERR(handler)) return PTR_ERR(handler); - return handler->get(handler, dentry, d_inode(dentry), + return handler->get(handler, dentry, inode, name, buffer, size); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 329ed372d708..1b5fcaeea827 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1702,7 +1702,8 @@ struct inode_operations { int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); + ssize_t (*getxattr) (struct dentry *, struct inode *, + const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, diff --git a/include/linux/xattr.h b/include/linux/xattr.h index c11c022298b9..1cc4c578deb9 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -52,7 +52,7 @@ int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, i int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int); int vfs_removexattr(struct dentry *, const char *); -ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size); +ssize_t generic_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size); ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int generic_removexattr(struct dentry *dentry, const char *name); diff --git a/net/socket.c b/net/socket.c index 5f77a8e93830..35e4523edada 100644 --- a/net/socket.c +++ b/net/socket.c @@ -466,7 +466,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname" #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX) #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1) -static ssize_t sockfs_getxattr(struct dentry *dentry, +static ssize_t sockfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *value, size_t size) { const char *proto_name; diff --git a/security/commoncap.c b/security/commoncap.c index 48071ed7c445..a042077312a5 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -313,7 +313,7 @@ int cap_inode_need_killpriv(struct dentry *dentry) if (!inode->i_op->getxattr) return 0; - error = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0); + error = inode->i_op->getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0); if (error <= 0) return 0; return 1; @@ -397,8 +397,8 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data if (!inode || !inode->i_op->getxattr) return -ENODATA; - size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, - XATTR_CAPS_SZ); + size = inode->i_op->getxattr((struct dentry *)dentry, inode, + XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ); if (size == -ENODATA || size == -EOPNOTSUPP) /* no data, that's ok */ return -ENODATA; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 84c6d11fc096..b9e26288d30c 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -82,7 +82,7 @@ static int evm_find_protected_xattrs(struct dentry *dentry) return -EOPNOTSUPP; for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) { - error = inode->i_op->getxattr(dentry, *xattr, NULL, 0); + error = inode->i_op->getxattr(dentry, inode, *xattr, NULL, 0); if (error < 0) { if (error == -ENODATA) continue; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 889cd59ca5a7..469f5c75bd4b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -506,7 +506,8 @@ static int sb_finish_set_opts(struct super_block *sb) rc = -EOPNOTSUPP; goto out; } - rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0); + rc = root_inode->i_op->getxattr(root, root_inode, + XATTR_NAME_SELINUX, NULL, 0); if (rc < 0 && rc != -ENODATA) { if (rc == -EOPNOTSUPP) printk(KERN_WARNING "SELinux: (dev %s, type " @@ -1412,13 +1413,13 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out_unlock; } context[len] = '\0'; - rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, + rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); if (rc == -ERANGE) { kfree(context); /* Need a larger buffer. Query for the right size. */ - rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, + rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); if (rc < 0) { dput(dentry); @@ -1432,7 +1433,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out_unlock; } context[len] = '\0'; - rc = inode->i_op->getxattr(dentry, + rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 50bcca26c0b7..ff2b8c3cf7a9 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -272,7 +272,7 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip, if (buffer == NULL) return ERR_PTR(-ENOMEM); - rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL); + rc = ip->i_op->getxattr(dp, ip, name, buffer, SMK_LONGLABEL); if (rc < 0) skp = ERR_PTR(rc); else if (rc == 0) @@ -3519,7 +3519,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) TRANS_TRUE, TRANS_TRUE_SIZE, 0); } else { - rc = inode->i_op->getxattr(dp, + rc = inode->i_op->getxattr(dp, inode, XATTR_NAME_SMACKTRANSMUTE, trattr, TRANS_TRUE_SIZE); if (rc >= 0 && strncmp(trattr, TRANS_TRUE, -- GitLab From 43b27d7286737d9af9ebeff0219e38560cb31748 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 8 Apr 2016 16:50:14 +0100 Subject: [PATCH 1944/9938] ASoC: arizona: Do not create OUT4R widget for CS47L24/WM1831 The CS47L24 and WM1831 codecs only use the OUT4L widget so we can skip creation of the OUT4R widget. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 92d22a018d68..d8a682302580 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -221,6 +221,8 @@ int arizona_init_spk(struct snd_soc_codec *codec) switch (arizona->type) { case WM8997: + case CS47L24: + case WM1831: break; default: ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1); -- GitLab From f8a25db47ebc11fe228735d916e480d4b2ebe611 Mon Sep 17 00:00:00 2001 From: Russell Currey Date: Tue, 15 Mar 2016 21:14:12 +1100 Subject: [PATCH 1945/9938] powerpc/powernv: Use the "unknown" checkstop type as a fallback The HMI code knows about three types of errors: CORE, NX and UNKNOWN. If OPAL were to add a new type, it would not be handled at all since there is no fallback case. Instead of explicitly checking for UNKNOWN, treat any checkstop type without a handler as unknown. Signed-off-by: Russell Currey Reviewed-by: Daniel Axtens Reviewed-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/opal-hmi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c index d000f4e21981..c0a8201cb4d9 100644 --- a/arch/powerpc/platforms/powernv/opal-hmi.c +++ b/arch/powerpc/platforms/powernv/opal-hmi.c @@ -150,15 +150,17 @@ static void print_nx_checkstop_reason(const char *level, static void print_checkstop_reason(const char *level, struct OpalHMIEvent *hmi_evt) { - switch (hmi_evt->u.xstop_error.xstop_type) { + uint8_t type = hmi_evt->u.xstop_error.xstop_type; + switch (type) { case CHECKSTOP_TYPE_CORE: print_core_checkstop_reason(level, hmi_evt); break; case CHECKSTOP_TYPE_NX: print_nx_checkstop_reason(level, hmi_evt); break; - case CHECKSTOP_TYPE_UNKNOWN: - printk("%s Unknown Malfunction Alert.\n", level); + default: + printk("%s Unknown Malfunction Alert of type %d\n", + level, type); break; } } -- GitLab From 1f4c66e80574e85aff25179fc71bdadfb1a701ef Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 16 Mar 2016 21:56:20 +1100 Subject: [PATCH 1946/9938] powerpc/mm: Remove long disabled SLB code We have a bunch of SLB related code in the tree which is there to handle dynamic VSIDs - but currently it's all disabled at compile time. The comments say "Keep that around for when we re-implement dynamic VSIDs". But that was over 10 years ago (commit 3c726f8dee6f ("[PATCH] ppc64: support 64k pages")). The chance that it would still work unchanged is minimal, and in the meantime it's confusing to folks browsing/grepping the code. If we ever want to re-instate it, it's in the git history. Signed-off-by: Michael Ellerman Acked-by: Balbir Singh --- arch/powerpc/kernel/exceptions-64s.S | 102 --------------------------- arch/powerpc/mm/slb.c | 1 - arch/powerpc/mm/slb_low.S | 50 ------------- 3 files changed, 153 deletions(-) diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 7716cebf4b8e..e0e1ff463556 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -209,11 +209,6 @@ data_access_slb_pSeries: EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380) std r3,PACA_EXSLB+EX_R3(r13) mfspr r3,SPRN_DAR -#ifdef __DISABLED__ - /* Keep that around for when we re-implement dynamic VSIDs */ - cmpdi r3,0 - bge slb_miss_user_pseries -#endif /* __DISABLED__ */ mfspr r12,SPRN_SRR1 #ifndef CONFIG_RELOCATABLE b slb_miss_realmode @@ -240,11 +235,6 @@ instruction_access_slb_pSeries: EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x480) std r3,PACA_EXSLB+EX_R3(r13) mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ -#ifdef __DISABLED__ - /* Keep that around for when we re-implement dynamic VSIDs */ - cmpdi r3,0 - bge slb_miss_user_pseries -#endif /* __DISABLED__ */ mfspr r12,SPRN_SRR1 #ifndef CONFIG_RELOCATABLE b slb_miss_realmode @@ -709,34 +699,6 @@ system_reset_fwnmi: #endif /* CONFIG_PPC_PSERIES */ -#ifdef __DISABLED__ -/* - * This is used for when the SLB miss handler has to go virtual, - * which doesn't happen for now anymore but will once we re-implement - * dynamic VSIDs for shared page tables - */ -slb_miss_user_pseries: - std r10,PACA_EXGEN+EX_R10(r13) - std r11,PACA_EXGEN+EX_R11(r13) - std r12,PACA_EXGEN+EX_R12(r13) - GET_SCRATCH0(r10) - ld r11,PACA_EXSLB+EX_R9(r13) - ld r12,PACA_EXSLB+EX_R3(r13) - std r10,PACA_EXGEN+EX_R13(r13) - std r11,PACA_EXGEN+EX_R9(r13) - std r12,PACA_EXGEN+EX_R3(r13) - clrrdi r12,r13,32 - mfmsr r10 - mfspr r11,SRR0 /* save SRR0 */ - ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ - ori r10,r10,MSR_IR|MSR_DR|MSR_RI - mtspr SRR0,r12 - mfspr r12,SRR1 /* and SRR1 */ - mtspr SRR1,r10 - rfid - b . /* prevent spec. execution */ -#endif /* __DISABLED__ */ - #ifdef CONFIG_KVM_BOOK3S_64_HANDLER kvmppc_skip_interrupt: /* @@ -1012,70 +974,6 @@ instruction_access_common: STD_EXCEPTION_COMMON(0xe20, h_instr_storage, unknown_exception) -/* - * Here is the common SLB miss user that is used when going to virtual - * mode for SLB misses, that is currently not used - */ -#ifdef __DISABLED__ - .align 7 - .globl slb_miss_user_common -slb_miss_user_common: - mflr r10 - std r3,PACA_EXGEN+EX_DAR(r13) - stw r9,PACA_EXGEN+EX_CCR(r13) - std r10,PACA_EXGEN+EX_LR(r13) - std r11,PACA_EXGEN+EX_SRR0(r13) - bl slb_allocate_user - - ld r10,PACA_EXGEN+EX_LR(r13) - ld r3,PACA_EXGEN+EX_R3(r13) - lwz r9,PACA_EXGEN+EX_CCR(r13) - ld r11,PACA_EXGEN+EX_SRR0(r13) - mtlr r10 - beq- slb_miss_fault - - andi. r10,r12,MSR_RI /* check for unrecoverable exception */ - beq- unrecov_user_slb - mfmsr r10 - -.machine push -.machine "power4" - mtcrf 0x80,r9 -.machine pop - - clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ - mtmsrd r10,1 - - mtspr SRR0,r11 - mtspr SRR1,r12 - - ld r9,PACA_EXGEN+EX_R9(r13) - ld r10,PACA_EXGEN+EX_R10(r13) - ld r11,PACA_EXGEN+EX_R11(r13) - ld r12,PACA_EXGEN+EX_R12(r13) - ld r13,PACA_EXGEN+EX_R13(r13) - rfid - b . - -slb_miss_fault: - EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) - ld r4,PACA_EXGEN+EX_DAR(r13) - li r5,0 - std r4,_DAR(r1) - std r5,_DSISR(r1) - b handle_page_fault - -unrecov_user_slb: - EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) - RECONCILE_IRQ_STATE(r10, r11) - bl save_nvgprs -1: addi r3,r1,STACK_FRAME_OVERHEAD - bl unrecoverable_exception - b 1b - -#endif /* __DISABLED__ */ - - /* * Machine check is different because we use a different * save area: PACA_EXMC instead of PACA_EXGEN. diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 825b6873391f..48fc28bab544 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -32,7 +32,6 @@ enum slb_index { }; extern void slb_allocate_realmode(unsigned long ea); -extern void slb_allocate_user(unsigned long ea); static void slb_allocate(unsigned long ea) { diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index 736d18b3cefd..d3374004d20d 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -179,56 +179,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) li r11,SLB_VSID_USER /* flags don't much matter */ b slb_finish_load -#ifdef __DISABLED__ - -/* void slb_allocate_user(unsigned long ea); - * - * Create an SLB entry for the given EA (user or kernel). - * r3 = faulting address, r13 = PACA - * r9, r10, r11 are clobbered by this function - * No other registers are examined or changed. - * - * It is called with translation enabled in order to be able to walk the - * page tables. This is not currently used. - */ -_GLOBAL(slb_allocate_user) - /* r3 = faulting address */ - srdi r10,r3,28 /* get esid */ - - crset 4*cr7+lt /* set "user" flag for later */ - - /* check if we fit in the range covered by the pagetables*/ - srdi. r9,r3,PGTABLE_EADDR_SIZE - crnot 4*cr0+eq,4*cr0+eq - beqlr - - /* now we need to get to the page tables in order to get the page - * size encoding from the PMD. In the future, we'll be able to deal - * with 1T segments too by getting the encoding from the PGD instead - */ - ld r9,PACAPGDIR(r13) - cmpldi cr0,r9,0 - beqlr - rlwinm r11,r10,8,25,28 - ldx r9,r9,r11 /* get pgd_t */ - cmpldi cr0,r9,0 - beqlr - rlwinm r11,r10,3,17,28 - ldx r9,r9,r11 /* get pmd_t */ - cmpldi cr0,r9,0 - beqlr - - /* build vsid flags */ - andi. r11,r9,SLB_VSID_LLP - ori r11,r11,SLB_VSID_USER - - /* get context to calculate proto-VSID */ - ld r9,PACACONTEXTID(r13) - /* fall through slb_finish_load */ - -#endif /* __DISABLED__ */ - - /* * Finish loading of an SLB entry and return * -- GitLab From b05fac783a75c6e9f3af2ce0824f3a6ff12540ab Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 16 Mar 2016 21:36:05 +1100 Subject: [PATCH 1947/9938] powerpc: Remove orphaned asm implementation of abs() This has been unused since ~2004, remove it. Reported-by: Al Viro Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/misc_32.S | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index bf5160fbf9d8..285ca8c6cc2e 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -599,12 +599,6 @@ _GLOBAL(__bswapdi2) mr r4,r10 blr -_GLOBAL(abs) - srawi r4,r3,31 - xor r3,r3,r4 - sub r3,r3,r4 - blr - #ifdef CONFIG_SMP _GLOBAL(start_secondary_resume) /* Reset stack */ -- GitLab From b4c6afdc3a1ad73542c8e92220c30b8f953c51de Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 16 Mar 2016 21:36:06 +1100 Subject: [PATCH 1948/9938] powerpc: Make generic_memcpy() private to copy_32.S generic_memcpy() is only called from copy_32.S, so there's no reason for it to be global. Reported-by: Al Viro Signed-off-by: Michael Ellerman --- arch/powerpc/lib/copy_32.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S index c44df2dbedd5..99f37f24185c 100644 --- a/arch/powerpc/lib/copy_32.S +++ b/arch/powerpc/lib/copy_32.S @@ -217,7 +217,7 @@ _GLOBAL(memcpy) bdnz 40b 65: blr -_GLOBAL(generic_memcpy) +generic_memcpy: srwi. r7,r5,3 addi r6,r3,-4 addi r4,r4,-4 -- GitLab From 8ee26530bb189909cca6f4b1f36a7577c840c526 Mon Sep 17 00:00:00 2001 From: Russell Currey Date: Tue, 16 Feb 2016 23:06:05 +1100 Subject: [PATCH 1949/9938] powerpc/eeh: rename EEH from "extended" to "enhanced" error handling IBM online documentation for EEH uses "extended error handling" and "enhanced error handling" to refer to the same thing, in different places. The only place mentioning it as "enhanced error handling" in the kernel is the MAINTAINERS file, and it's "extended" in some documentation. IBM originally defined EEH as "enhanced error handling", so standardise all mentions of EEH to use that term. Signed-off-by: Russell Currey Acked-by: Gavin Shan Signed-off-by: Michael Ellerman --- Documentation/powerpc/eeh-pci-error-recovery.txt | 2 +- arch/powerpc/kernel/eeh.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt index 9d4e33df624c..678189280bb4 100644 --- a/Documentation/powerpc/eeh-pci-error-recovery.txt +++ b/Documentation/powerpc/eeh-pci-error-recovery.txt @@ -12,7 +12,7 @@ Overview: The IBM POWER-based pSeries and iSeries computers include PCI bus controller chips that have extended capabilities for detecting and reporting a large variety of PCI bus error conditions. These features -go under the name of "EEH", for "Extended Error Handling". The EEH +go under the name of "EEH", for "Enhanced Error Handling". The EEH hardware features allow PCI bus errors to be cleared and a PCI card to be "rebooted", without also having to reboot the operating system. diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 6544017eb90b..c4e41cf79874 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -48,7 +48,7 @@ /** Overview: - * EEH, or "Extended Error Handling" is a PCI bridge technology for + * EEH, or "Enhanced Error Handling" is a PCI bridge technology for * dealing with PCI bus errors that can't be dealt with within the * usual PCI framework, except by check-stopping the CPU. Systems * that are designed for high-availability/reliability cannot afford -- GitLab From 8038665fb54f1e54785c63be111647abebfe9f20 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 18:08:15 -0400 Subject: [PATCH 1950/9938] powerpc/cell: Make spu_base.c explicitly non-modular The Kconfig currently controlling compilation of this code is: arch/powerpc/platforms/cell/Kconfig:config SPU_BASE arch/powerpc/platforms/cell/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Arnd Bergmann Signed-off-by: Paul Gortmaker Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/cell/spu_base.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index f7af74f83693..3ede04ffdeea 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -805,7 +805,4 @@ static int __init init_spu_base(void) out: return ret; } -module_init(init_spu_base); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Arnd Bergmann "); +device_initcall(init_spu_base); -- GitLab From c0c523897d1f83bc8484cb58d1f51d935b23cee5 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 18:08:16 -0400 Subject: [PATCH 1951/9938] powerpc: make kernel/nvram_64.c explicitly non-modular The Makefile/Kconfig currently controlling compilation of this code is: obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ signal_64.o ptrace32.o \ paca.o nvram_64.o firmware.o arch/powerpc/platforms/Kconfig.cputype:config PPC64 arch/powerpc/platforms/Kconfig.cputype: bool "64-bit kernel" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We don't replace module.h with init.h since the file already has that. We delete the MODULE_LICENSE tag since that information is already contained at the top of the file in the comments. Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Hari Bathini Cc: Nathan Fontenot Cc: Andrzej Hajda Cc: Anton Blanchard Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Paul Gortmaker Reviewed-by: Nathan Fontenot Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/nvram_64.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 0cab9e8c3794..856f9a7944cd 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -15,8 +15,6 @@ * parsing code. */ -#include - #include #include #include @@ -1231,12 +1229,4 @@ static int __init nvram_init(void) return rc; } - -static void __exit nvram_cleanup(void) -{ - misc_deregister( &nvram_dev ); -} - -module_init(nvram_init); -module_exit(nvram_cleanup); -MODULE_LICENSE("GPL"); +device_initcall(nvram_init); -- GitLab From 6a0bcab9c6c337e14689cabd276f00649e980cf1 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 18:08:17 -0400 Subject: [PATCH 1952/9938] drivers/cpufreq: make ppc_cbe_cpufreq_pmi driver explicitly non-modular The Kconfig for this driver is currently: config CPU_FREQ_CBE_PMI bool "CBE frequency scaling using PMI interface" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular and unused code here, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: "Rafael J. Wysocki" Cc: Viresh Kumar Cc: Christian Krafft Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-pm@vger.kernel.org Signed-off-by: Paul Gortmaker Acked-by: Viresh Kumar Signed-off-by: Michael Ellerman --- drivers/cpufreq/ppc_cbe_cpufreq_pmi.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c index 7969f7690498..7c4cd5c634f2 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -142,15 +142,4 @@ static int __init cbe_cpufreq_pmi_init(void) return 0; } - -static void __exit cbe_cpufreq_pmi_exit(void) -{ - cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); - pmi_unregister_handler(&cbe_pmi_handler); -} - -module_init(cbe_cpufreq_pmi_init); -module_exit(cbe_cpufreq_pmi_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Krafft "); +device_initcall(cbe_cpufreq_pmi_init); -- GitLab From a7ee539584acf4a565b7439ceaea8401ec210353 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Fri, 19 Feb 2016 16:38:47 +1100 Subject: [PATCH 1953/9938] powerpc/Kconfig: Update config option based on page size. Currently on PPC64 changing kernel pagesize from 4K to 64K leaves FORCE_MAX_ZONEORDER set to 13 - which produces a compile error. The error occurs because of the following constraint (from include/linux/mmzone.h) being violated: MAX_ORDER -1 + PAGESHIFT <= SECTION_SIZE_BITS. Expanding this out, we get: FORCE_MAX_ZONEBITS <= 25 - PAGESHIFT, which requires, for a 64K page, FORCE_MAX_ZONEBITS <= 9. Thus set max value of FORCE_MAX_ZONEORDER for 64K pages to 9, and 4K pages to 13. Also, check the minimum value: In include/linux/huge_mm.h, we have the constraint HPAGE_PMD_ORDER < MAX_ORDER which expands out to: PTE_INDEX_SIZE < FORCE_MAX_ZONEORDER. PTE_INDEX_SIZE is: 9 (4k hash or no hash 4K pgtable) or 8 (64K hash or no hash 64K pgtable). Thus a min value of 8 for 64K pages and 9 for 4K pages is reasonable. So, update the range of FORCE_MAX_ZONEORDER from 9-64 to 8-9 for 64K pages and from 13-64 to 9-13 for 4K pages. Signed-off-by: Rashmica Gupta Reviewed-by: Balbir Singh Signed-off-by: Michael Ellerman --- arch/powerpc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 7cd32c038286..fbebde0771c8 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -605,9 +605,9 @@ endchoice config FORCE_MAX_ZONEORDER int "Maximum zone order" - range 9 64 if PPC64 && PPC_64K_PAGES + range 8 9 if PPC64 && PPC_64K_PAGES default "9" if PPC64 && PPC_64K_PAGES - range 13 64 if PPC64 && !PPC_64K_PAGES + range 9 13 if PPC64 && !PPC_64K_PAGES default "13" if PPC64 && !PPC_64K_PAGES range 9 64 if PPC32 && PPC_16K_PAGES default "9" if PPC32 && PPC_16K_PAGES -- GitLab From e3824e4281b8e31d55c08a06b20abb4f677a0baf Mon Sep 17 00:00:00 2001 From: Russell Currey Date: Wed, 2 Mar 2016 17:12:45 +1100 Subject: [PATCH 1954/9938] powerpc/swsusp: Only use tlbie in POWER4 mode If CONFIG_HIBERNATION and CONFIG_PPC_BOOK3S_64 are set, code in arch/powerpc/kernel/swsusp_amd64.S which uses the tlbia macro is enabled. tlbia in turn uses tlbie, an instruction which takes more than one operand in newer versions of POWER. As such, the kernel fails to build due to the assembler complaining about missing operands. This can be worked around by assembling the instruction as in POWER4. This fixes the build breakage caused by enabling CONFIG_HIBERNATION. Hibernation is currently only tested on G5 PowerMacs, which should be unaffected by this change. For other platforms it may now build, whether or not it works is a different story. Signed-off-by: Russell Currey Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/ppc_asm.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 499d9f89435a..2b31632376a5 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -427,7 +427,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) li r4,1024; \ mtctr r4; \ lis r4,KERNELBASE@h; \ + .machine push; \ + .machine "power4"; \ 0: tlbie r4; \ + .machine pop; \ addi r4,r4,0x1000; \ bdnz 0b #endif -- GitLab From ef69b03dfd321ffa1bcb4248e9b8744f653e3859 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 2 Mar 2016 12:36:56 +1100 Subject: [PATCH 1955/9938] MAINTAINERS: Add powerpc drivers to the powerpc section We'd like folks working on drivers for powerpc to also Cc linuxppc-dev, so we can be aware of what's going on in drivers and/or review the changes. So add patterns to the powerpc MAINTAINERS section to catch some of the drivers we're interested in. Signed-off-by: Michael Ellerman --- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 61a323a6b2cf..9a955eaefc31 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6608,6 +6608,19 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git S: Supported F: Documentation/powerpc/ F: arch/powerpc/ +F: drivers/char/tpm/tpm_ibmvtpm* +F: drivers/crypto/nx/ +F: drivers/crypto/vmx/ +F: drivers/net/ethernet/ibm/ibmveth.* +F: drivers/net/ethernet/ibm/ibmvnic.* +F: drivers/pci/hotplug/rpa* +F: drivers/scsi/ibmvscsi/ +N: opal +N: /pmac +N: powermac +N: powernv +N: [^a-z0-9]ps3 +N: pseries LINUX FOR POWER MACINTOSH M: Benjamin Herrenschmidt -- GitLab From b3d79eaa6c97b04965fa479652dd0317253f81d1 Mon Sep 17 00:00:00 2001 From: Vipin K Parashar Date: Tue, 1 Sep 2015 04:52:43 +0530 Subject: [PATCH 1956/9938] powerpc/opal: Assign numbers to OPAL_MSG macros of enum opal_msg_type This patch assigns numbers to OPAL_MSG macros of enum opal_msg_type to prevent accidental insertion of any new value in between and thus break OPAL API. This is also helpful while backporting mainline kernel changes to distros which run downlevel kernel and thus don't have all OPAL messages defined, avoiding unnecessary bugs due to enum values order mismatch. Signed-off-by: Vipin K Parashar Acked-by: Stewart Smith Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal-api.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index f8faaaeeca1e..9bb8ddf0be37 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -368,16 +368,16 @@ enum OpalLPCAddressType { }; enum opal_msg_type { - OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc, + OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc, * additional params function-specific */ - OPAL_MSG_MEM_ERR, - OPAL_MSG_EPOW, - OPAL_MSG_SHUTDOWN, /* params[0] = 1 reboot, 0 shutdown */ - OPAL_MSG_HMI_EVT, - OPAL_MSG_DPO, - OPAL_MSG_PRD, - OPAL_MSG_OCC, + OPAL_MSG_MEM_ERR = 1, + OPAL_MSG_EPOW = 2, + OPAL_MSG_SHUTDOWN = 3, /* params[0] = 1 reboot, 0 shutdown */ + OPAL_MSG_HMI_EVT = 4, + OPAL_MSG_DPO = 5, + OPAL_MSG_PRD = 6, + OPAL_MSG_OCC = 7, OPAL_MSG_TYPE_MAX, }; -- GitLab From 86c9ffcc1ed17497a5df473232a7e654fa8cfa1f Mon Sep 17 00:00:00 2001 From: Philippe Bergheaud Date: Thu, 31 Mar 2016 11:19:27 +0200 Subject: [PATCH 1957/9938] powerpc: Define PVR value for POWER8NVL processor Signed-off-by: Philippe Bergheaud Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/reg.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index f5f4c66bbbc9..cf09c6eb5ee7 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1182,6 +1182,7 @@ #define PVR_970GX 0x0045 #define PVR_POWER7p 0x004A #define PVR_POWER8E 0x004B +#define PVR_POWER8NVL 0x004C #define PVR_POWER8 0x004D #define PVR_BE 0x0070 #define PVR_PA6T 0x0090 -- GitLab From aa14138a51ca42eada706d4b9635bd32d1e09ced Mon Sep 17 00:00:00 2001 From: Philippe Bergheaud Date: Thu, 31 Mar 2016 11:19:28 +0200 Subject: [PATCH 1958/9938] cxl: Configure the PSL for two CAPI ports on POWER8NVL The POWER8NVL chip has two CAPI ports. Configure the PSL to route data to the port corresponding to the CAPP unit. Signed-off-by: Philippe Bergheaud Signed-off-by: Michael Ellerman --- drivers/misc/cxl/pci.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 2844e975bf79..94fd3f71f838 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "cxl.h" #include @@ -321,12 +322,43 @@ static void dump_afu_descriptor(struct cxl_afu *afu) #undef show_reg } +#define CAPP_UNIT0_ID 0xBA +#define CAPP_UNIT1_ID 0XBE + +static u64 get_capp_unit_id(struct device_node *np) +{ + u32 phb_index; + + /* + * For chips other than POWER8NVL, we only have CAPP 0, + * irrespective of which PHB is used. + */ + if (!pvr_version_is(PVR_POWER8NVL)) + return CAPP_UNIT0_ID; + + /* + * For POWER8NVL, assume CAPP 0 is attached to PHB0 and + * CAPP 1 is attached to PHB1. + */ + if (of_property_read_u32(np, "ibm,phb-index", &phb_index)) + return 0; + + if (phb_index == 0) + return CAPP_UNIT0_ID; + + if (phb_index == 1) + return CAPP_UNIT1_ID; + + return 0; +} + static int init_implementation_adapter_regs(struct cxl *adapter, struct pci_dev *dev) { struct device_node *np; const __be32 *prop; u64 psl_dsnctl; u64 chipid; + u64 capp_unit_id; if (!(np = pnv_pci_get_phb_node(dev))) return -ENODEV; @@ -336,10 +368,17 @@ static int init_implementation_adapter_regs(struct cxl *adapter, struct pci_dev if (!np) return -ENODEV; chipid = be32_to_cpup(prop); + capp_unit_id = get_capp_unit_id(np); of_node_put(np); + if (!capp_unit_id) { + pr_err("cxl: invalid capp unit id\n"); + return -ENODEV; + } /* Tell PSL where to route data to */ - psl_dsnctl = 0x02E8900002000000ULL | (chipid << (63-5)); + psl_dsnctl = 0x0000900002000000ULL | (chipid << (63-5)); + psl_dsnctl |= (capp_unit_id << (63-13)); + cxl_p1_write(adapter, CXL_PSL_DSNDCTL, psl_dsnctl); cxl_p1_write(adapter, CXL_PSL_RESLCKTO, 0x20000000200ULL); /* snoop write mask */ -- GitLab From 65433fd561f089f232758efc2c6566b6b6febb47 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 20 Mar 2016 18:53:57 +0000 Subject: [PATCH 1959/9938] mfd: da9063: Remove unused array mask_events_buf mask_events_buf is not used, so remove this redundant array. Signed-off-by: Colin Ian King Signed-off-by: Lee Jones --- drivers/mfd/da9063-irq.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index 26302634633c..0aa760e155ec 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c @@ -27,8 +27,6 @@ #define DA9063_REG_EVENT_D_OFFSET 3 #define EVENTS_BUF_LEN 4 -static const u8 mask_events_buf[] = { [0 ... (EVENTS_BUF_LEN - 1)] = ~0 }; - struct da9063_irq_data { u16 reg; u8 mask; -- GitLab From 7f0c5ae18d649ed2f4978cbf07c02a0ff732f23e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 19 Feb 2016 10:42:10 +0200 Subject: [PATCH 1960/9938] mfd: intel_quark_i2c_gpio: Remove clock tree on error path There is a potential resource leak in case when ->probe() fails. We have to unregister and remove clock tree which is done here. This is a follow up to previously pushed commit c4726abce63b ("mfd: intel_quark_i2c_gpio: Use clkdev_create()") that prevents double free() when clkdev_drop() followed by kfree() in devm_kcalloc() release stage. I leave Fixes tag here, but the backporting will require to backport the commit c4726abce63b ("mfd: intel_quark_i2c_gpio: Use clkdev_create()") first. Cc: stable@vger.kernel.org Fixes: 60ae5b9f5cdd (mfd: intel_quark_i2c_gpio: Add Intel Quark X1000 I2C-GPIO MFD Driver) Signed-off-by: Andy Shevchenko Acked-by: Stephen Boyd Signed-off-by: Lee Jones --- drivers/mfd/intel_quark_i2c_gpio.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index bdc5e27222c0..7450f5d8770c 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -139,6 +139,7 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) INTEL_QUARK_I2C_CONTROLLER_CLK); if (!quark_mfd->i2c_clk_lookup) { + clk_unregister(quark_mfd->i2c_clk); dev_err(&pdev->dev, "Fixed clk register failed\n"); return -ENOMEM; } @@ -150,7 +151,7 @@ static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev) { struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev); - if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup) + if (!quark_mfd->i2c_clk_lookup) return; clkdev_drop(quark_mfd->i2c_clk_lookup); @@ -246,25 +247,33 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL); if (!quark_mfd) return -ENOMEM; + quark_mfd->pdev = pdev; + dev_set_drvdata(&pdev->dev, quark_mfd); ret = intel_quark_register_i2c_clk(quark_mfd); if (ret) return ret; - dev_set_drvdata(&pdev->dev, quark_mfd); - ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]); if (ret) - return ret; + goto err_unregister_i2c_clk; ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]); if (ret) - return ret; + goto err_unregister_i2c_clk; - return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, - ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, - NULL); + ret = mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, + ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, + NULL); + if (ret) + goto err_unregister_i2c_clk; + + return 0; + +err_unregister_i2c_clk: + intel_quark_unregister_i2c_clk(pdev); + return ret; } static void intel_quark_mfd_remove(struct pci_dev *pdev) -- GitLab From 9caac886397bdfd6c1a6b48493db6cd95bce313c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 19 Feb 2016 10:42:11 +0200 Subject: [PATCH 1961/9938] mfd: intel_quark_i2c_gpio: Switch to use struct device * There is no need to pass struct pci_dev * to intel_quark_register_i2c_clk() and intel_quark_unregister_i2c_clk(). Change the parameter to struct device *. As a result store it in the private struct instead of struct pci_dev *. Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel_quark_i2c_gpio.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 7450f5d8770c..24c2d291b1dc 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -53,7 +53,7 @@ #define INTEL_QUARK_I2C_CLK_HZ 33000000 struct intel_quark_mfd { - struct pci_dev *pdev; + struct device *dev; struct clk *i2c_clk; struct clk_lookup *i2c_clk_lookup; }; @@ -123,12 +123,12 @@ static const struct pci_device_id intel_quark_mfd_ids[] = { }; MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids); -static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) +static int intel_quark_register_i2c_clk(struct device *dev) { - struct pci_dev *pdev = quark_mfd->pdev; + struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev); struct clk *i2c_clk; - i2c_clk = clk_register_fixed_rate(&pdev->dev, + i2c_clk = clk_register_fixed_rate(dev, INTEL_QUARK_I2C_CONTROLLER_CLK, NULL, CLK_IS_ROOT, INTEL_QUARK_I2C_CLK_HZ); if (IS_ERR(i2c_clk)) @@ -140,16 +140,16 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) if (!quark_mfd->i2c_clk_lookup) { clk_unregister(quark_mfd->i2c_clk); - dev_err(&pdev->dev, "Fixed clk register failed\n"); + dev_err(dev, "Fixed clk register failed\n"); return -ENOMEM; } return 0; } -static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev) +static void intel_quark_unregister_i2c_clk(struct device *dev) { - struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev); + struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev); if (!quark_mfd->i2c_clk_lookup) return; @@ -248,10 +248,10 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, if (!quark_mfd) return -ENOMEM; - quark_mfd->pdev = pdev; + quark_mfd->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, quark_mfd); - ret = intel_quark_register_i2c_clk(quark_mfd); + ret = intel_quark_register_i2c_clk(&pdev->dev); if (ret) return ret; @@ -272,13 +272,13 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, return 0; err_unregister_i2c_clk: - intel_quark_unregister_i2c_clk(pdev); + intel_quark_unregister_i2c_clk(&pdev->dev); return ret; } static void intel_quark_mfd_remove(struct pci_dev *pdev) { - intel_quark_unregister_i2c_clk(pdev); + intel_quark_unregister_i2c_clk(&pdev->dev); mfd_remove_devices(&pdev->dev); } -- GitLab From ee414de525a9abf29e8a1b0c1b6f79f9e875213a Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 13 Mar 2016 03:02:58 +0200 Subject: [PATCH 1962/9938] mfd: core: Fix ACPI child matching by _HID/_CID If MDF child devices have separate ACPI nodes identified by _HID/_CID, they will not be assigned the intended ACPI companion. acpi_match_device_ids will return 0 if a the child device matches the _HID/_CID, so this patch changes the matching condition to check for 0 on success. Signed-off-by: Irina Tirdea Acked-by: Mika Westerberg Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 88bd1b1e47be..409da01effcd 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -107,7 +107,7 @@ static void mfd_acpi_add_device(const struct mfd_cell *cell, strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id)); list_for_each_entry(child, &parent->children, node) { - if (acpi_match_device_ids(child, ids)) { + if (!acpi_match_device_ids(child, ids)) { adev = child; break; } -- GitLab From adae28c59a6a71a971ffed713550911546df0e20 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 23 Mar 2016 11:36:53 +0100 Subject: [PATCH 1963/9938] mfd: syscon: Include errno.h from header The syscon header uses the ENOTSUPP error constant, but doesn't include the header that defines it. This causes a build error after the imx pinctrl driver started using syscon: include/linux/mfd/syscon.h: In function 'syscon_node_to_regmap': include/linux/mfd/syscon.h:32:18: error: 'ENOTSUPP' undeclared (first use in this function) return ERR_PTR(-ENOTSUPP); ^~~~~~~~ This adds the missing #include. Signed-off-by: Arnd Bergmann Fixes: 8626ada871f1 ("pinctrl: imx: attach iomuxc device to gpr syscon") Signed-off-by: Lee Jones --- include/linux/mfd/syscon.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h index 1088149be0c9..40a76b97b7ab 100644 --- a/include/linux/mfd/syscon.h +++ b/include/linux/mfd/syscon.h @@ -16,6 +16,7 @@ #define __LINUX_MFD_SYSCON_H__ #include +#include struct device_node; -- GitLab From 22aab38e7b59fd79ce1045006be69a9abab58e5a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 11 Mar 2016 11:11:39 +0300 Subject: [PATCH 1964/9938] mfd: lp8788-irq: Uninitialized variable in irq handler Instead to being true/false, the "handled" is true/uninitialized. Presumably this doesn't cause that many problems in real life because normally we handle the IRQ. Fixes: eea6b7cc53aa ('mfd: Add lp8788 mfd driver') Signed-off-by: Dan Carpenter Acked-by: Milo Kim Signed-off-by: Lee Jones --- drivers/mfd/lp8788-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c index c7a9825aa4ce..792d51bae20f 100644 --- a/drivers/mfd/lp8788-irq.c +++ b/drivers/mfd/lp8788-irq.c @@ -112,7 +112,7 @@ static irqreturn_t lp8788_irq_handler(int irq, void *ptr) struct lp8788_irq_data *irqd = ptr; struct lp8788 *lp = irqd->lp; u8 status[NUM_REGS], addr, mask; - bool handled; + bool handled = false; int i; if (lp8788_read_multi_bytes(lp, LP8788_INT_1, status, NUM_REGS)) -- GitLab From be70771d4cabe0763e7dacd55400abd38910d634 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 11 Apr 2016 15:35:06 +0200 Subject: [PATCH 1965/9938] arm64: tegra: Remove 0, prefix from unit-addresses When Tegra124 support was first merged the unit-addresses of all devices were listed with a "0," prefix to encode the reg property's second cell. It turns out that this notation is not correct, and the "," separator is only used to separate fields in the unit address (such as the device and function number in PCI devices), not individual cells for addresses with more than one cell. Signed-off-by: Thierry Reding --- .../arm64/boot/dts/nvidia/tegra132-norrin.dts | 46 +++---- arch/arm64/boot/dts/nvidia/tegra132.dtsi | 118 +++++++++--------- .../arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 8 +- .../arm64/boot/dts/nvidia/tegra210-p2530.dtsi | 10 +- arch/arm64/boot/dts/nvidia/tegra210-p2571.dts | 2 +- .../arm64/boot/dts/nvidia/tegra210-p2595.dtsi | 2 +- .../arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 4 +- arch/arm64/boot/dts/nvidia/tegra210.dtsi | 118 +++++++++--------- 8 files changed, 154 insertions(+), 154 deletions(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts index 62f33fc84e3e..ebf8926c72d6 100644 --- a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts +++ b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts @@ -8,8 +8,8 @@ compatible = "nvidia,norrin", "nvidia,tegra132", "nvidia,tegra124"; aliases { - rtc0 = "/i2c@0,7000d000/as3722@40"; - rtc1 = "/rtc@0,7000e000"; + rtc0 = "/i2c@7000d000/as3722@40"; + rtc1 = "/rtc@7000e000"; }; chosen { }; @@ -19,8 +19,8 @@ reg = <0x0 0x80000000 0x0 0x80000000>; }; - host1x@0,50000000 { - hdmi@0,54280000 { + host1x@50000000 { + hdmi@54280000 { status = "disabled"; vdd-supply = <&vdd_3v3_hdmi>; @@ -32,26 +32,26 @@ <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; }; - sor@0,54540000 { + sor@54540000 { status = "okay"; nvidia,dpaux = <&dpaux>; nvidia,panel = <&panel>; }; - dpaux: dpaux@0,545c0000 { + dpaux: dpaux@545c0000 { vdd-supply = <&vdd_3v3_panel>; status = "okay"; }; }; - gpu@0,57000000 { + gpu@57000000 { status = "okay"; vdd-supply = <&vdd_gpu>; }; - pinmux@0,70000868 { + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&pinmux_default>; @@ -523,21 +523,21 @@ }; }; - serial@0,70006000 { + serial@70006000 { status = "okay"; }; - pwm: pwm@0,7000a000 { + pwm: pwm@7000a000 { status = "okay"; }; /* HDMI DDC */ - hdmi_ddc: i2c@0,7000c700 { + hdmi_ddc: i2c@7000c700 { status = "okay"; clock-frequency = <100000>; }; - i2c@0,7000d000 { + i2c@7000d000 { status = "okay"; clock-frequency = <400000>; @@ -744,7 +744,7 @@ }; }; - spi@0,7000d400 { + spi@7000d400 { status = "okay"; ec: cros-ec@0 { @@ -876,7 +876,7 @@ }; }; - pmc@0,7000e400 { + pmc@7000e400 { nvidia,invert-interrupt; nvidia,suspend-mode = <0>; #wake-cells = <3>; @@ -890,12 +890,12 @@ }; /* WIFI/BT module */ - sdhci@0,700b0000 { + sdhci@700b0000 { status = "disabled"; }; /* external SD/MMC */ - sdhci@0,700b0400 { + sdhci@700b0400 { cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>; wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_HIGH>; @@ -905,35 +905,35 @@ }; /* EMMC 4.51 */ - sdhci@0,700b0600 { + sdhci@700b0600 { status = "okay"; bus-width = <8>; non-removable; }; - usb@0,7d000000 { + usb@7d000000 { status = "okay"; }; - usb-phy@0,7d000000 { + usb-phy@7d000000 { status = "okay"; vbus-supply = <&vdd_usb1_vbus>; }; - usb@0,7d004000 { + usb@7d004000 { status = "okay"; }; - usb-phy@0,7d004000 { + usb-phy@7d004000 { status = "okay"; vbus-supply = <&vdd_run_cam>; }; - usb@0,7d008000 { + usb@7d008000 { status = "okay"; }; - usb-phy@0,7d008000 { + usb-phy@7d008000 { status = "okay"; vbus-supply = <&vdd_usb3_vbus>; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi index 6e28e41d7e3e..5d70728dda83 100644 --- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi @@ -11,7 +11,7 @@ #address-cells = <2>; #size-cells = <2>; - pcie-controller@0,01003000 { + pcie-controller@01003000 { compatible = "nvidia,tegra124-pcie"; device_type = "pci"; reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ @@ -77,7 +77,7 @@ }; }; - host1x@0,50000000 { + host1x@50000000 { compatible = "nvidia,tegra124-host1x", "simple-bus"; reg = <0x0 0x50000000 0x0 0x00034000>; interrupts = , /* syncpt */ @@ -92,7 +92,7 @@ ranges = <0 0x54000000 0 0x54000000 0 0x01000000>; - dc@0,54200000 { + dc@54200000 { compatible = "nvidia,tegra124-dc"; reg = <0x0 0x54200000 0x0 0x00040000>; interrupts = ; @@ -107,7 +107,7 @@ nvidia,head = <0>; }; - dc@0,54240000 { + dc@54240000 { compatible = "nvidia,tegra124-dc"; reg = <0x0 0x54240000 0x0 0x00040000>; interrupts = ; @@ -122,7 +122,7 @@ nvidia,head = <1>; }; - hdmi@0,54280000 { + hdmi@54280000 { compatible = "nvidia,tegra124-hdmi"; reg = <0x0 0x54280000 0x0 0x00040000>; interrupts = ; @@ -134,7 +134,7 @@ status = "disabled"; }; - sor@0,54540000 { + sor@54540000 { compatible = "nvidia,tegra124-sor"; reg = <0x0 0x54540000 0x0 0x00040000>; interrupts = ; @@ -148,7 +148,7 @@ status = "disabled"; }; - dpaux: dpaux@0,545c0000 { + dpaux: dpaux@545c0000 { compatible = "nvidia,tegra124-dpaux"; reg = <0x0 0x545c0000 0x0 0x00040000>; interrupts = ; @@ -161,7 +161,7 @@ }; }; - gic: interrupt-controller@0,50041000 { + gic: interrupt-controller@50041000 { compatible = "arm,cortex-a15-gic"; #interrupt-cells = <3>; interrupt-controller; @@ -174,7 +174,7 @@ interrupt-parent = <&gic>; }; - gpu@0,57000000 { + gpu@57000000 { compatible = "nvidia,gk20a"; reg = <0x0 0x57000000 0x0 0x01000000>, <0x0 0x58000000 0x0 0x01000000>; @@ -201,7 +201,7 @@ interrupt-parent = <&gic>; }; - timer@0,60005000 { + timer@60005000 { compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer"; reg = <0x0 0x60005000 0x0 0x400>; interrupts = , @@ -214,7 +214,7 @@ clock-names = "timer"; }; - tegra_car: clock@0,60006000 { + tegra_car: clock@60006000 { compatible = "nvidia,tegra132-car"; reg = <0x0 0x60006000 0x0 0x1000>; #clock-cells = <1>; @@ -222,12 +222,12 @@ nvidia,external-memory-controller = <&emc>; }; - flow-controller@0,60007000 { + flow-controller@60007000 { compatible = "nvidia,tegra124-flowctrl"; reg = <0x0 0x60007000 0x0 0x1000>; }; - actmon@0,6000c800 { + actmon@6000c800 { compatible = "nvidia,tegra124-actmon"; reg = <0x0 0x6000c800 0x0 0x400>; interrupts = ; @@ -238,7 +238,7 @@ reset-names = "actmon"; }; - gpio: gpio@0,6000d000 { + gpio: gpio@6000d000 { compatible = "nvidia,tegra124-gpio", "nvidia,tegra30-gpio"; reg = <0x0 0x6000d000 0x0 0x1000>; interrupts = , @@ -255,7 +255,7 @@ interrupt-controller; }; - apbdma: dma@0,60020000 { + apbdma: dma@60020000 { compatible = "nvidia,tegra124-apbdma", "nvidia,tegra148-apbdma"; reg = <0x0 0x60020000 0x0 0x1400>; interrupts = , @@ -297,13 +297,13 @@ #dma-cells = <1>; }; - apbmisc@0,70000800 { + apbmisc@70000800 { compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc"; reg = <0x0 0x70000800 0x0 0x64>, /* Chip revision */ <0x0 0x7000e864 0x0 0x04>; /* Strapping options */ }; - pinmux: pinmux@0,70000868 { + pinmux: pinmux@70000868 { compatible = "nvidia,tegra124-pinmux"; reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */ <0x0 0x70003000 0x0 0x434>, /* Mux registers */ @@ -318,7 +318,7 @@ * the APB DMA based serial driver, the comptible is * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart". */ - uarta: serial@0,70006000 { + uarta: serial@70006000 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006000 0x0 0x40>; reg-shift = <2>; @@ -332,7 +332,7 @@ status = "disabled"; }; - uartb: serial@0,70006040 { + uartb: serial@70006040 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006040 0x0 0x40>; reg-shift = <2>; @@ -346,7 +346,7 @@ status = "disabled"; }; - uartc: serial@0,70006200 { + uartc: serial@70006200 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006200 0x0 0x40>; reg-shift = <2>; @@ -360,7 +360,7 @@ status = "disabled"; }; - uartd: serial@0,70006300 { + uartd: serial@70006300 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006300 0x0 0x40>; reg-shift = <2>; @@ -374,7 +374,7 @@ status = "disabled"; }; - pwm: pwm@0,7000a000 { + pwm: pwm@7000a000 { compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm"; reg = <0x0 0x7000a000 0x0 0x100>; #pwm-cells = <2>; @@ -385,7 +385,7 @@ status = "disabled"; }; - i2c@0,7000c000 { + i2c@7000c000 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c000 0x0 0x100>; interrupts = ; @@ -400,7 +400,7 @@ status = "disabled"; }; - i2c@0,7000c400 { + i2c@7000c400 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c400 0x0 0x100>; interrupts = ; @@ -415,7 +415,7 @@ status = "disabled"; }; - i2c@0,7000c500 { + i2c@7000c500 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c500 0x0 0x100>; interrupts = ; @@ -430,7 +430,7 @@ status = "disabled"; }; - i2c@0,7000c700 { + i2c@7000c700 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c700 0x0 0x100>; interrupts = ; @@ -445,7 +445,7 @@ status = "disabled"; }; - i2c@0,7000d000 { + i2c@7000d000 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000d000 0x0 0x100>; interrupts = ; @@ -460,7 +460,7 @@ status = "disabled"; }; - i2c@0,7000d100 { + i2c@7000d100 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000d100 0x0 0x100>; interrupts = ; @@ -475,7 +475,7 @@ status = "disabled"; }; - spi@0,7000d400 { + spi@7000d400 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d400 0x0 0x200>; interrupts = ; @@ -490,7 +490,7 @@ status = "disabled"; }; - spi@0,7000d600 { + spi@7000d600 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d600 0x0 0x200>; interrupts = ; @@ -505,7 +505,7 @@ status = "disabled"; }; - spi@0,7000d800 { + spi@7000d800 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d800 0x0 0x200>; interrupts = ; @@ -520,7 +520,7 @@ status = "disabled"; }; - spi@0,7000da00 { + spi@7000da00 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000da00 0x0 0x200>; interrupts = ; @@ -535,7 +535,7 @@ status = "disabled"; }; - spi@0,7000dc00 { + spi@7000dc00 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000dc00 0x0 0x200>; interrupts = ; @@ -550,7 +550,7 @@ status = "disabled"; }; - spi@0,7000de00 { + spi@7000de00 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000de00 0x0 0x200>; interrupts = ; @@ -565,7 +565,7 @@ status = "disabled"; }; - rtc@0,7000e000 { + rtc@7000e000 { compatible = "nvidia,tegra124-rtc", "nvidia,tegra20-rtc"; reg = <0x0 0x7000e000 0x0 0x100>; interrupts = ; @@ -573,14 +573,14 @@ clock-names = "rtc"; }; - pmc@0,7000e400 { + pmc@7000e400 { compatible = "nvidia,tegra124-pmc"; reg = <0x0 0x7000e400 0x0 0x400>; clocks = <&tegra_car TEGRA124_CLK_PCLK>, <&clk32k_in>; clock-names = "pclk", "clk32k_in"; }; - fuse@0,7000f800 { + fuse@7000f800 { compatible = "nvidia,tegra124-efuse"; reg = <0x0 0x7000f800 0x0 0x400>; clocks = <&tegra_car TEGRA124_CLK_FUSE>; @@ -589,7 +589,7 @@ reset-names = "fuse"; }; - mc: memory-controller@0,70019000 { + mc: memory-controller@70019000 { compatible = "nvidia,tegra132-mc"; reg = <0x0 0x70019000 0x0 0x1000>; clocks = <&tegra_car TEGRA124_CLK_MC>; @@ -600,14 +600,14 @@ #iommu-cells = <1>; }; - emc: emc@0,7001b000 { + emc: emc@7001b000 { compatible = "nvidia,tegra132-emc", "nvidia,tegra124-emc"; reg = <0x0 0x7001b000 0x0 0x1000>; nvidia,memory-controller = <&mc>; }; - sata@0,70020000 { + sata@70020000 { compatible = "nvidia,tegra124-ahci"; reg = <0x0 0x70027000 0x0 0x2000>, /* AHCI */ <0x0 0x70020000 0x0 0x7000>; /* SATA */ @@ -626,7 +626,7 @@ status = "disabled"; }; - hda@0,70030000 { + hda@70030000 { compatible = "nvidia,tegra132-hda", "nvidia,tegra124-hda", "nvidia,tegra30-hda"; reg = <0x0 0x70030000 0x0 0x10000>; @@ -642,7 +642,7 @@ status = "disabled"; }; - padctl: padctl@0,7009f000 { + padctl: padctl@7009f000 { compatible = "nvidia,tegra132-xusb-padctl", "nvidia,tegra124-xusb-padctl"; reg = <0x0 0x7009f000 0x0 0x1000>; @@ -682,7 +682,7 @@ }; }; - sdhci@0,700b0000 { + sdhci@700b0000 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0000 0x0 0x200>; interrupts = ; @@ -693,7 +693,7 @@ status = "disabled"; }; - sdhci@0,700b0200 { + sdhci@700b0200 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0200 0x0 0x200>; interrupts = ; @@ -704,7 +704,7 @@ status = "disabled"; }; - sdhci@0,700b0400 { + sdhci@700b0400 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0400 0x0 0x200>; interrupts = ; @@ -715,7 +715,7 @@ status = "disabled"; }; - sdhci@0,700b0600 { + sdhci@700b0600 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0600 0x0 0x200>; interrupts = ; @@ -726,7 +726,7 @@ status = "disabled"; }; - soctherm: thermal-sensor@0,700e2000 { + soctherm: thermal-sensor@700e2000 { compatible = "nvidia,tegra124-soctherm"; reg = <0x0 0x700e2000 0x0 0x1000>; interrupts = ; @@ -738,7 +738,7 @@ #thermal-sensor-cells = <1>; }; - ahub@0,70300000 { + ahub@70300000 { compatible = "nvidia,tegra124-ahub"; reg = <0x0 0x70300000 0x0 0x200>, <0x0 0x70300800 0x0 0x800>, @@ -790,7 +790,7 @@ #address-cells = <2>; #size-cells = <2>; - tegra_i2s0: i2s@0,70301000 { + tegra_i2s0: i2s@70301000 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301000 0x0 0x100>; nvidia,ahub-cif-ids = <4 4>; @@ -801,7 +801,7 @@ status = "disabled"; }; - tegra_i2s1: i2s@0,70301100 { + tegra_i2s1: i2s@70301100 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301100 0x0 0x100>; nvidia,ahub-cif-ids = <5 5>; @@ -812,7 +812,7 @@ status = "disabled"; }; - tegra_i2s2: i2s@0,70301200 { + tegra_i2s2: i2s@70301200 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301200 0x0 0x100>; nvidia,ahub-cif-ids = <6 6>; @@ -823,7 +823,7 @@ status = "disabled"; }; - tegra_i2s3: i2s@0,70301300 { + tegra_i2s3: i2s@70301300 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301300 0x0 0x100>; nvidia,ahub-cif-ids = <7 7>; @@ -834,7 +834,7 @@ status = "disabled"; }; - tegra_i2s4: i2s@0,70301400 { + tegra_i2s4: i2s@70301400 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301400 0x0 0x100>; nvidia,ahub-cif-ids = <8 8>; @@ -846,7 +846,7 @@ }; }; - usb@0,7d000000 { + usb@7d000000 { compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d000000 0x0 0x4000>; interrupts = ; @@ -859,7 +859,7 @@ status = "disabled"; }; - phy1: usb-phy@0,7d000000 { + phy1: usb-phy@7d000000 { compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d000000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; @@ -884,7 +884,7 @@ status = "disabled"; }; - usb@0,7d004000 { + usb@7d004000 { compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d004000 0x0 0x4000>; interrupts = ; @@ -897,7 +897,7 @@ status = "disabled"; }; - phy2: usb-phy@0,7d004000 { + phy2: usb-phy@7d004000 { compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d004000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; @@ -921,7 +921,7 @@ status = "disabled"; }; - usb@0,7d008000 { + usb@7d008000 { compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d008000 0x0 0x4000>; interrupts = ; @@ -934,7 +934,7 @@ status = "disabled"; }; - phy3: usb-phy@0,7d008000 { + phy3: usb-phy@7d008000 { compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d008000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi index 2b7f88950d1e..316c92c03821 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi @@ -5,7 +5,7 @@ compatible = "nvidia,p2180", "nvidia,tegra210"; aliases { - rtc1 = "/rtc@0,7000e000"; + rtc1 = "/rtc@7000e000"; serial0 = &uarta; }; @@ -15,16 +15,16 @@ }; /* debug port */ - serial@0,70006000 { + serial@70006000 { status = "okay"; }; - pmc@0,7000e400 { + pmc@7000e400 { nvidia,invert-interrupt; }; /* eMMC */ - sdhci@0,700b0600 { + sdhci@700b0600 { status = "okay"; bus-width = <8>; non-removable; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi index ece0dec61fae..a8e4b7311071 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi @@ -5,7 +5,7 @@ compatible = "nvidia,p2530", "nvidia,tegra210"; aliases { - rtc1 = "/rtc@0,7000e000"; + rtc1 = "/rtc@7000e000"; serial0 = &uarta; }; @@ -15,21 +15,21 @@ }; /* debug port */ - serial@0,70006000 { + serial@70006000 { status = "okay"; }; - i2c@0,7000d000 { + i2c@7000d000 { status = "okay"; clock-frequency = <400000>; }; - pmc@0,7000e400 { + pmc@7000e400 { nvidia,invert-interrupt; }; /* eMMC */ - sdhci@0,700b0600 { + sdhci@700b0600 { status = "okay"; bus-width = <8>; non-removable; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts b/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts index 58d27ddd57ff..576957a55801 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts @@ -7,7 +7,7 @@ model = "NVIDIA Tegra210 P2571 reference design"; compatible = "nvidia,p2571", "nvidia,tegra210"; - pinmux: pinmux@0,700008d4 { + pinmux: pinmux@700008d4 { pinctrl-names = "boot"; pinctrl-0 = <&state_boot>; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi index f3f91392214e..e008e3364d2a 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi @@ -2,7 +2,7 @@ model = "NVIDIA Tegra210 P2595 I/O board"; compatible = "nvidia,p2595", "nvidia,tegra210"; - pinmux: pinmux@0,700008d4 { + pinmux: pinmux@700008d4 { pinctrl-names = "boot"; pinctrl-0 = <&state_boot>; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi index be3eccbe8013..c662404e78a2 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi @@ -2,7 +2,7 @@ model = "NVIDIA Tegra210 P2597 I/O board"; compatible = "nvidia,p2597", "nvidia,tegra210"; - pinmux: pinmux@0,700008d4 { + pinmux: pinmux@700008d4 { pinctrl-names = "boot"; pinctrl-0 = <&state_boot>; @@ -1260,7 +1260,7 @@ }; /* MMC/SD */ - sdhci@0,700b0000 { + sdhci@700b0000 { status = "okay"; bus-width = <4>; no-1-8-v; diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 23b0630602cf..77d5aba03f8e 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -10,7 +10,7 @@ #address-cells = <2>; #size-cells = <2>; - host1x@0,50000000 { + host1x@50000000 { compatible = "nvidia,tegra210-host1x", "simple-bus"; reg = <0x0 0x50000000 0x0 0x00034000>; interrupts = , /* syncpt */ @@ -25,7 +25,7 @@ ranges = <0x0 0x54000000 0x0 0x54000000 0x0 0x01000000>; - dpaux1: dpaux@0,54040000 { + dpaux1: dpaux@54040000 { compatible = "nvidia,tegra210-dpaux"; reg = <0x0 0x54040000 0x0 0x00040000>; interrupts = ; @@ -37,19 +37,19 @@ status = "disabled"; }; - vi@0,54080000 { + vi@54080000 { compatible = "nvidia,tegra210-vi"; reg = <0x0 0x54080000 0x0 0x00040000>; interrupts = ; status = "disabled"; }; - tsec@0,54100000 { + tsec@54100000 { compatible = "nvidia,tegra210-tsec"; reg = <0x0 0x54100000 0x0 0x00040000>; }; - dc@0,54200000 { + dc@54200000 { compatible = "nvidia,tegra210-dc"; reg = <0x0 0x54200000 0x0 0x00040000>; interrupts = ; @@ -64,7 +64,7 @@ nvidia,head = <0>; }; - dc@0,54240000 { + dc@54240000 { compatible = "nvidia,tegra210-dc"; reg = <0x0 0x54240000 0x0 0x00040000>; interrupts = ; @@ -79,7 +79,7 @@ nvidia,head = <1>; }; - dsi@0,54300000 { + dsi@54300000 { compatible = "nvidia,tegra210-dsi"; reg = <0x0 0x54300000 0x0 0x00040000>; clocks = <&tegra_car TEGRA210_CLK_DSIA>, @@ -96,19 +96,19 @@ #size-cells = <0>; }; - vic@0,54340000 { + vic@54340000 { compatible = "nvidia,tegra210-vic"; reg = <0x0 0x54340000 0x0 0x00040000>; status = "disabled"; }; - nvjpg@0,54380000 { + nvjpg@54380000 { compatible = "nvidia,tegra210-nvjpg"; reg = <0x0 0x54380000 0x0 0x00040000>; status = "disabled"; }; - dsi@0,54400000 { + dsi@54400000 { compatible = "nvidia,tegra210-dsi"; reg = <0x0 0x54400000 0x0 0x00040000>; clocks = <&tegra_car TEGRA210_CLK_DSIB>, @@ -125,25 +125,25 @@ #size-cells = <0>; }; - nvdec@0,54480000 { + nvdec@54480000 { compatible = "nvidia,tegra210-nvdec"; reg = <0x0 0x54480000 0x0 0x00040000>; status = "disabled"; }; - nvenc@0,544c0000 { + nvenc@544c0000 { compatible = "nvidia,tegra210-nvenc"; reg = <0x0 0x544c0000 0x0 0x00040000>; status = "disabled"; }; - tsec@0,54500000 { + tsec@54500000 { compatible = "nvidia,tegra210-tsec"; reg = <0x0 0x54500000 0x0 0x00040000>; status = "disabled"; }; - sor@0,54540000 { + sor@54540000 { compatible = "nvidia,tegra210-sor"; reg = <0x0 0x54540000 0x0 0x00040000>; interrupts = ; @@ -157,7 +157,7 @@ status = "disabled"; }; - sor@0,54580000 { + sor@54580000 { compatible = "nvidia,tegra210-sor1"; reg = <0x0 0x54580000 0x0 0x00040000>; interrupts = ; @@ -171,7 +171,7 @@ status = "disabled"; }; - dpaux: dpaux@0,545c0000 { + dpaux: dpaux@545c0000 { compatible = "nvidia,tegra124-dpaux"; reg = <0x0 0x545c0000 0x0 0x00040000>; interrupts = ; @@ -183,21 +183,21 @@ status = "disabled"; }; - isp@0,54600000 { + isp@54600000 { compatible = "nvidia,tegra210-isp"; reg = <0x0 0x54600000 0x0 0x00040000>; interrupts = ; status = "disabled"; }; - isp@0,54680000 { + isp@54680000 { compatible = "nvidia,tegra210-isp"; reg = <0x0 0x54680000 0x0 0x00040000>; interrupts = ; status = "disabled"; }; - i2c@0,546c0000 { + i2c@546c0000 { compatible = "nvidia,tegra210-i2c-vi"; reg = <0x0 0x546c0000 0x0 0x00040000>; interrupts = ; @@ -205,7 +205,7 @@ }; }; - gic: interrupt-controller@0,50041000 { + gic: interrupt-controller@50041000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; interrupt-controller; @@ -218,7 +218,7 @@ interrupt-parent = <&gic>; }; - gpu@0,57000000 { + gpu@57000000 { compatible = "nvidia,gm20b"; reg = <0x0 0x57000000 0x0 0x01000000>, <0x0 0x58000000 0x0 0x01000000>; @@ -233,7 +233,7 @@ status = "disabled"; }; - lic: interrupt-controller@0,60004000 { + lic: interrupt-controller@60004000 { compatible = "nvidia,tegra210-ictlr"; reg = <0x0 0x60004000 0x0 0x40>, /* primary controller */ <0x0 0x60004100 0x0 0x40>, /* secondary controller */ @@ -246,7 +246,7 @@ interrupt-parent = <&gic>; }; - timer@0,60005000 { + timer@60005000 { compatible = "nvidia,tegra210-timer", "nvidia,tegra20-timer"; reg = <0x0 0x60005000 0x0 0x400>; interrupts = , @@ -259,19 +259,19 @@ clock-names = "timer"; }; - tegra_car: clock@0,60006000 { + tegra_car: clock@60006000 { compatible = "nvidia,tegra210-car"; reg = <0x0 0x60006000 0x0 0x1000>; #clock-cells = <1>; #reset-cells = <1>; }; - flow-controller@0,60007000 { + flow-controller@60007000 { compatible = "nvidia,tegra210-flowctrl"; reg = <0x0 0x60007000 0x0 0x1000>; }; - gpio: gpio@0,6000d000 { + gpio: gpio@6000d000 { compatible = "nvidia,tegra210-gpio", "nvidia,tegra124-gpio", "nvidia,tegra30-gpio"; reg = <0x0 0x6000d000 0x0 0x1000>; interrupts = , @@ -288,7 +288,7 @@ interrupt-controller; }; - apbdma: dma@0,60020000 { + apbdma: dma@60020000 { compatible = "nvidia,tegra210-apbdma", "nvidia,tegra148-apbdma"; reg = <0x0 0x60020000 0x0 0x1400>; interrupts = , @@ -330,13 +330,13 @@ #dma-cells = <1>; }; - apbmisc@0,70000800 { + apbmisc@70000800 { compatible = "nvidia,tegra210-apbmisc", "nvidia,tegra20-apbmisc"; reg = <0x0 0x70000800 0x0 0x64>, /* Chip revision */ <0x0 0x7000e864 0x0 0x04>; /* Strapping options */ }; - pinmux: pinmux@0,700008d4 { + pinmux: pinmux@700008d4 { compatible = "nvidia,tegra210-pinmux"; reg = <0x0 0x700008d4 0x0 0x29c>, /* Pad control registers */ <0x0 0x70003000 0x0 0x294>; /* Mux registers */ @@ -350,7 +350,7 @@ * the APB DMA based serial driver, the comptible is * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart". */ - uarta: serial@0,70006000 { + uarta: serial@70006000 { compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006000 0x0 0x40>; reg-shift = <2>; @@ -364,7 +364,7 @@ status = "disabled"; }; - uartb: serial@0,70006040 { + uartb: serial@70006040 { compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006040 0x0 0x40>; reg-shift = <2>; @@ -378,7 +378,7 @@ status = "disabled"; }; - uartc: serial@0,70006200 { + uartc: serial@70006200 { compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006200 0x0 0x40>; reg-shift = <2>; @@ -392,7 +392,7 @@ status = "disabled"; }; - uartd: serial@0,70006300 { + uartd: serial@70006300 { compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006300 0x0 0x40>; reg-shift = <2>; @@ -406,7 +406,7 @@ status = "disabled"; }; - pwm: pwm@0,7000a000 { + pwm: pwm@7000a000 { compatible = "nvidia,tegra210-pwm", "nvidia,tegra20-pwm"; reg = <0x0 0x7000a000 0x0 0x100>; #pwm-cells = <2>; @@ -417,7 +417,7 @@ status = "disabled"; }; - i2c@0,7000c000 { + i2c@7000c000 { compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c000 0x0 0x100>; interrupts = ; @@ -432,7 +432,7 @@ status = "disabled"; }; - i2c@0,7000c400 { + i2c@7000c400 { compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c400 0x0 0x100>; interrupts = ; @@ -447,7 +447,7 @@ status = "disabled"; }; - i2c@0,7000c500 { + i2c@7000c500 { compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c500 0x0 0x100>; interrupts = ; @@ -462,7 +462,7 @@ status = "disabled"; }; - i2c@0,7000c700 { + i2c@7000c700 { compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c700 0x0 0x100>; interrupts = ; @@ -477,7 +477,7 @@ status = "disabled"; }; - i2c@0,7000d000 { + i2c@7000d000 { compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000d000 0x0 0x100>; interrupts = ; @@ -492,7 +492,7 @@ status = "disabled"; }; - i2c@0,7000d100 { + i2c@7000d100 { compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000d100 0x0 0x100>; interrupts = ; @@ -507,7 +507,7 @@ status = "disabled"; }; - spi@0,7000d400 { + spi@7000d400 { compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d400 0x0 0x200>; interrupts = ; @@ -522,7 +522,7 @@ status = "disabled"; }; - spi@0,7000d600 { + spi@7000d600 { compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d600 0x0 0x200>; interrupts = ; @@ -537,7 +537,7 @@ status = "disabled"; }; - spi@0,7000d800 { + spi@7000d800 { compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d800 0x0 0x200>; interrupts = ; @@ -552,7 +552,7 @@ status = "disabled"; }; - spi@0,7000da00 { + spi@7000da00 { compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000da00 0x0 0x200>; interrupts = ; @@ -567,7 +567,7 @@ status = "disabled"; }; - rtc@0,7000e000 { + rtc@7000e000 { compatible = "nvidia,tegra210-rtc", "nvidia,tegra20-rtc"; reg = <0x0 0x7000e000 0x0 0x100>; interrupts = ; @@ -575,7 +575,7 @@ clock-names = "rtc"; }; - pmc: pmc@0,7000e400 { + pmc: pmc@7000e400 { compatible = "nvidia,tegra210-pmc"; reg = <0x0 0x7000e400 0x0 0x400>; clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; @@ -584,7 +584,7 @@ #power-domain-cells = <1>; }; - fuse@0,7000f800 { + fuse@7000f800 { compatible = "nvidia,tegra210-efuse"; reg = <0x0 0x7000f800 0x0 0x400>; clocks = <&tegra_car TEGRA210_CLK_FUSE>; @@ -593,7 +593,7 @@ reset-names = "fuse"; }; - mc: memory-controller@0,70019000 { + mc: memory-controller@70019000 { compatible = "nvidia,tegra210-mc"; reg = <0x0 0x70019000 0x0 0x1000>; clocks = <&tegra_car TEGRA210_CLK_MC>; @@ -604,7 +604,7 @@ #iommu-cells = <1>; }; - hda@0,70030000 { + hda@70030000 { compatible = "nvidia,tegra210-hda", "nvidia,tegra30-hda"; reg = <0x0 0x70030000 0x0 0x10000>; interrupts = ; @@ -619,7 +619,7 @@ status = "disabled"; }; - sdhci@0,700b0000 { + sdhci@700b0000 { compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0000 0x0 0x200>; interrupts = ; @@ -630,7 +630,7 @@ status = "disabled"; }; - sdhci@0,700b0200 { + sdhci@700b0200 { compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0200 0x0 0x200>; interrupts = ; @@ -641,7 +641,7 @@ status = "disabled"; }; - sdhci@0,700b0400 { + sdhci@700b0400 { compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0400 0x0 0x200>; interrupts = ; @@ -652,7 +652,7 @@ status = "disabled"; }; - sdhci@0,700b0600 { + sdhci@700b0600 { compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0600 0x0 0x200>; interrupts = ; @@ -663,7 +663,7 @@ status = "disabled"; }; - mipi: mipi@0,700e3000 { + mipi: mipi@700e3000 { compatible = "nvidia,tegra210-mipi"; reg = <0x0 0x700e3000 0x0 0x100>; clocks = <&tegra_car TEGRA210_CLK_MIPI_CAL>; @@ -671,7 +671,7 @@ #nvidia,mipi-calibrate-cells = <1>; }; - spi@0,70410000 { + spi@70410000 { compatible = "nvidia,tegra210-qspi"; reg = <0x0 0x70410000 0x0 0x1000>; interrupts = ; @@ -686,7 +686,7 @@ status = "disabled"; }; - usb@0,7d000000 { + usb@7d000000 { compatible = "nvidia,tegra210-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d000000 0x0 0x4000>; interrupts = ; @@ -699,7 +699,7 @@ status = "disabled"; }; - phy1: usb-phy@0,7d000000 { + phy1: usb-phy@7d000000 { compatible = "nvidia,tegra210-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d000000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; @@ -724,7 +724,7 @@ status = "disabled"; }; - usb@0,7d004000 { + usb@7d004000 { compatible = "nvidia,tegra210-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d004000 0x0 0x4000>; interrupts = ; @@ -737,7 +737,7 @@ status = "disabled"; }; - phy2: usb-phy@0,7d004000 { + phy2: usb-phy@7d004000 { compatible = "nvidia,tegra210-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d004000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; -- GitLab From 68cd8b2e271fe9f6b507030eb6831cfa7bb3e40e Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 27 Jan 2016 15:02:20 +0100 Subject: [PATCH 1966/9938] arm64: tegra: Fix copy/paste typo in several DTS includes The comment about the 8250 vs. APB DMA-enabled UART devices that was added for Tegra20 and Tegra30 in commit b6551bb933f9 ("ARM: tegra: dts: add aliases and DMA requestor for serial controller") introduced a typo that has since spread to various other DTS include files. Fix all occurrences of this typo. Suggested-by: Ralf Ramsauer Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra132.dtsi | 2 +- arch/arm64/boot/dts/nvidia/tegra210.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi index 5d70728dda83..2013f8916084 100644 --- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi @@ -315,7 +315,7 @@ * driver and APB DMA based serial driver for higher baudrate * and performance. To enable the 8250 based driver, the compatible * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable - * the APB DMA based serial driver, the comptible is + * the APB DMA based serial driver, the compatible is * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart". */ uarta: serial@70006000 { diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 77d5aba03f8e..4a06a7dd74b1 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -347,7 +347,7 @@ * driver and APB DMA based serial driver for higher baudrate * and performance. To enable the 8250 based driver, the compatible * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable - * the APB DMA based serial driver, the comptible is + * the APB DMA based serial driver, the compatible is * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart". */ uarta: serial@70006000 { -- GitLab From 81d22e89b42668dccba5393737170ae72ed78ff9 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Feb 2016 21:55:43 +0000 Subject: [PATCH 1967/9938] arm64: tegra: Replace legacy *,wakeup property with wakeup-source Though the keyboard and other driver will continue to support the legacy "gpio-key,wakeup", "nvidia,wakeup-source" boolean property to enable the wakeup source, "wakeup-source" is the new standard binding. This patch replaces all the legacy wakeup properties with the unified "wakeup-source" property in order to avoid any further copy-paste duplication. Cc: Stephen Warren Cc: Thierry Reding Cc: Alexandre Courbot Cc: linux-tegra@vger.kernel.org Signed-off-by: Sudeep Holla Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra132-norrin.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts index ebf8926c72d6..01a2fc2a6abf 100644 --- a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts +++ b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts @@ -973,7 +973,7 @@ linux,input-type = <5>; linux,code = <0>; debounce-interval = <1>; - gpio-key,wakeup; + wakeup-source; }; power { @@ -981,7 +981,7 @@ gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <10>; - gpio-key,wakeup; + wakeup-source; }; }; -- GitLab From 5d17ba6e638e45f737c60eb58ae3a0a46ec1100d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 9 Feb 2016 12:26:49 +0000 Subject: [PATCH 1968/9938] arm64: tegra: Add support for Google Pixel C Add initial device-tree support for Google Pixel C (a.k.a. Smaug) based upon Tegra210 SoC with 3 GiB of LPDDR4 RAM. Signed-off-by: Jon Hunter Tested-by: Alexandre Courbot Reviewed-by: Andrew Bresticker Tested-by: Andrew Bresticker Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/Makefile | 1 + arch/arm64/boot/dts/nvidia/tegra210-smaug.dts | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra210-smaug.dts diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile index a7e865da1005..0f7cdf3e05c1 100644 --- a/arch/arm64/boot/dts/nvidia/Makefile +++ b/arch/arm64/boot/dts/nvidia/Makefile @@ -2,6 +2,7 @@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb +dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb always := $(dtb-y) clean-files := *.dtb diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts new file mode 100644 index 000000000000..e687f68149c5 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts @@ -0,0 +1,83 @@ +/dts-v1/; + +#include "tegra210.dtsi" + +/ { + model = "Google Pixel C"; + compatible = "google,smaug-rev8", "google,smaug-rev7", + "google,smaug-rev6", "google,smaug-rev5", + "google,smaug-rev4", "google,smaug-rev3", + "google,smaug-rev1", "google,smaug", "nvidia,tegra210"; + + aliases { + serial0 = &uarta; + }; + + chosen { + bootargs = "earlycon"; + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0xc0000000>; + }; + + serial@70006000 { + status = "okay"; + }; + + pmc@7000e400 { + nvidia,invert-interrupt; + nvidia,suspend-mode = <0>; + nvidia,cpu-pwr-good-time = <0>; + nvidia,cpu-pwr-off-time = <0>; + nvidia,core-pwr-good-time = <12000 6000>; + nvidia,core-pwr-off-time = <39053>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; + status = "okay"; + }; + + sdhci@700b0600 { + bus-width = <8>; + non-removable; + status = "okay"; + }; + + clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + clk32k_in: clock@0 { + compatible = "fixed-clock"; + reg = <0>; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + }; + + cpus { + cpu@0 { + enable-method = "psci"; + }; + + cpu@1 { + enable-method = "psci"; + }; + + cpu@2 { + enable-method = "psci"; + }; + + cpu@3 { + enable-method = "psci"; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; +}; -- GitLab From 0e91ba42be2a7f264b9b4503b99f93060d62172c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 29 Feb 2016 18:36:50 +0530 Subject: [PATCH 1969/9938] arm64: tegra: Enable power and volume keys on Jetson TX1 Add a gpio-keys device tree node to represent the Power, Volume Up and Volume Down keys found on Jetson TX1. Signed-off-by: Laxman Dewangan Signed-off-by: Thierry Reding --- .../arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi index c662404e78a2..a2480c0c7e72 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi @@ -1,3 +1,5 @@ +#include + / { model = "NVIDIA Tegra210 P2597 I/O board"; compatible = "nvidia,p2597", "nvidia,tegra210"; @@ -1267,4 +1269,28 @@ cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>; }; + + gpio-keys { + compatible = "gpio-keys"; + label = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(X, 5) GPIO_ACTIVE_LOW>; + linux,code = ; + wakeup-source; + }; + + volume_down { + label = "Volume Down"; + gpios = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + volume_up { + label = "Volume Up"; + gpios = <&gpio TEGRA_GPIO(X, 6) GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; }; -- GitLab From a26f3963d980ff0d5a33a01b9a93c80b9d370835 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 3 Mar 2016 14:54:25 -0500 Subject: [PATCH 1970/9938] arm64: tegra: Add gpio-keys nodes for Smaug Add gpio-keys nodes for the volumn controls, lid switch, tablet mode and power button. Signed-off-by: Rhyland Klein Reviewed-by: Andrew Bresticker [treding@nvidia.com: use symbolic names for input types and codes] [treding@nvidia.com: use wakeup-source instead of gpio-key,wakeup] Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra210-smaug.dts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts index e687f68149c5..89d16e09c2d7 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts @@ -1,5 +1,7 @@ /dts-v1/; +#include + #include "tegra210.dtsi" / { @@ -76,6 +78,47 @@ }; }; + gpio-keys { + compatible = "gpio-keys"; + gpio-keys,name = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(X, 5) GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <30>; + wakeup-source; + }; + + lid { + label = "Lid"; + gpios = <&gpio TEGRA_GPIO(B, 4) GPIO_ACTIVE_LOW>; + linux,input-type = ; + linux,code = ; + wakeup-source; + }; + + tablet_mode { + label = "Tablet Mode"; + gpios = <&gpio TEGRA_GPIO(Z, 2) GPIO_ACTIVE_HIGH>; + linux,input-type = ; + linux,code = ; + wakeup-source; + }; + + volume_down { + label = "Volume Down"; + gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + volume_up { + label = "Volume Up"; + gpios = <&gpio TEGRA_GPIO(M, 4) GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; -- GitLab From 2c9b050b6c60f3b20303d383eb860b8909ab961e Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 30 Mar 2016 10:15:13 +0100 Subject: [PATCH 1971/9938] arm64: tegra: Remove unused #power-domain-cells property Remove the "#power-domain-cells" property which was incorrectly included by commit e53095857166 ("arm64: tegra: Add Tegra210 support"). Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra210.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 4a06a7dd74b1..ba0462eaf4a4 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -580,8 +580,6 @@ reg = <0x0 0x7000e400 0x0 0x400>; clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; clock-names = "pclk", "clk32k_in"; - - #power-domain-cells = <1>; }; fuse@7000f800 { -- GitLab From 69e29bd1a5564d1cc43cd254ecdd1fbf6bcb8de2 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 9 Feb 2016 13:52:00 +0000 Subject: [PATCH 1972/9938] arm64: tegra: Add stdout-path for various boards For Tegra boards, the device-tree alias serial0 is used for the console and so add the stdout-path information so that the console no longer needs to be passed via the kernel boot parameters. For tegra132-norrin the alias serial0 is not defined and so add this. This has been tested on tegra132-norrin and tegra210-p2371-0000. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra132-norrin.dts | 5 ++++- arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts index 01a2fc2a6abf..759af96a6b49 100644 --- a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts +++ b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts @@ -10,9 +10,12 @@ aliases { rtc0 = "/i2c@7000d000/as3722@40"; rtc1 = "/rtc@7000e000"; + serial0 = &uarta; }; - chosen { }; + chosen { + stdout-path = "serial0:115200n8"; + }; memory { device_type = "memory"; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi index a8e4b7311071..0ec92578cacb 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi @@ -9,6 +9,10 @@ serial0 = &uarta; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { device_type = "memory"; reg = <0x0 0x80000000 0x0 0xc0000000>; -- GitLab From 40a865500c4d408b552cf5899bf091ac72e32bf8 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 7 Apr 2016 16:22:38 +0200 Subject: [PATCH 1973/9938] regulator: as3722: Add bypass support for LDO6 LD06 on the AS3722 power management IC supports a bypass mode. Bypass is enabled for the LDO by writing the value 0x3F to the voltage select field in the control register for the LDO. Note that this is the same register and field that is used to select the voltage as well for the LDO. Add support for bypass on LDO6 by specifying the various bypass parameters for regulator and adding new function pointer tables for the LDO. Note that the bypass OFF value is the same as the ON value simply because there is no actual OFF value and bypass will be disabled when a new voltage is written to the VSEL field. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding Signed-off-by: Mark Brown --- drivers/regulator/as3722-regulator.c | 43 ++++++++++++++++++++++++++++ include/linux/mfd/as3722.h | 1 + 2 files changed, 44 insertions(+) diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c index 8b046eec6ae0..35a7c647f6a9 100644 --- a/drivers/regulator/as3722-regulator.c +++ b/drivers/regulator/as3722-regulator.c @@ -432,6 +432,31 @@ static struct regulator_ops as3722_ldo3_extcntrl_ops = { .get_current_limit = as3722_ldo3_get_current_limit, }; +static struct regulator_ops as3722_ldo6_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .get_current_limit = as3722_ldo_get_current_limit, + .set_current_limit = as3722_ldo_set_current_limit, + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, +}; + +static struct regulator_ops as3722_ldo6_extcntrl_ops = { + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .get_current_limit = as3722_ldo_get_current_limit, + .set_current_limit = as3722_ldo_set_current_limit, + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, +}; + static const struct regulator_linear_range as3722_ldo_ranges[] = { REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0), REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000), @@ -829,6 +854,24 @@ static int as3722_regulator_probe(struct platform_device *pdev) } } break; + case AS3722_REGULATOR_ID_LDO6: + if (reg_config->ext_control) + ops = &as3722_ldo6_extcntrl_ops; + else + ops = &as3722_ldo6_ops; + as3722_regs->desc[id].enable_time = 500; + as3722_regs->desc[id].bypass_reg = + AS3722_LDO6_VOLTAGE_REG; + as3722_regs->desc[id].bypass_mask = + AS3722_LDO_VSEL_MASK; + as3722_regs->desc[id].bypass_val_on = + AS3722_LDO6_VSEL_BYPASS; + as3722_regs->desc[id].bypass_val_off = + AS3722_LDO6_VSEL_BYPASS; + as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges; + as3722_regs->desc[id].n_linear_ranges = + ARRAY_SIZE(as3722_ldo_ranges); + break; case AS3722_REGULATOR_ID_SD0: case AS3722_REGULATOR_ID_SD1: case AS3722_REGULATOR_ID_SD6: diff --git a/include/linux/mfd/as3722.h b/include/linux/mfd/as3722.h index 8d43e9f2a842..51e6f9414575 100644 --- a/include/linux/mfd/as3722.h +++ b/include/linux/mfd/as3722.h @@ -196,6 +196,7 @@ #define AS3722_LDO3_VSEL_MIN 0x01 #define AS3722_LDO3_VSEL_MAX 0x2D #define AS3722_LDO3_NUM_VOLT 0x2D +#define AS3722_LDO6_VSEL_BYPASS 0x3F #define AS3722_LDO_VSEL_MASK 0x7F #define AS3722_LDO_VSEL_MIN 0x01 #define AS3722_LDO_VSEL_MAX 0x7F -- GitLab From 162c5a368fb788f040e9c51a1251ac36d80bff32 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 7 Apr 2016 16:22:39 +0200 Subject: [PATCH 1974/9938] regulator: as3722: Constify regulator ops A const pointer to regulator ops is stored in regulator descriptors. The operations never need to be modified, so define them as const as a hint to the compiler that they can go into .rodata. Signed-off-by: Thierry Reding Signed-off-by: Mark Brown --- drivers/regulator/as3722-regulator.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c index 35a7c647f6a9..66337e12719b 100644 --- a/drivers/regulator/as3722-regulator.c +++ b/drivers/regulator/as3722-regulator.c @@ -372,7 +372,7 @@ static int as3722_ldo_set_current_limit(struct regulator_dev *rdev, AS3722_LDO_ILIMIT_MASK, reg); } -static struct regulator_ops as3722_ldo0_ops = { +static const struct regulator_ops as3722_ldo0_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -383,7 +383,7 @@ static struct regulator_ops as3722_ldo0_ops = { .set_current_limit = as3722_ldo_set_current_limit, }; -static struct regulator_ops as3722_ldo0_extcntrl_ops = { +static const struct regulator_ops as3722_ldo0_extcntrl_ops = { .list_voltage = regulator_list_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -415,7 +415,7 @@ static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev) return 150000; } -static struct regulator_ops as3722_ldo3_ops = { +static const struct regulator_ops as3722_ldo3_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -425,14 +425,14 @@ static struct regulator_ops as3722_ldo3_ops = { .get_current_limit = as3722_ldo3_get_current_limit, }; -static struct regulator_ops as3722_ldo3_extcntrl_ops = { +static const struct regulator_ops as3722_ldo3_extcntrl_ops = { .list_voltage = regulator_list_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_current_limit = as3722_ldo3_get_current_limit, }; -static struct regulator_ops as3722_ldo6_ops = { +static const struct regulator_ops as3722_ldo6_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -446,7 +446,7 @@ static struct regulator_ops as3722_ldo6_ops = { .set_bypass = regulator_set_bypass_regmap, }; -static struct regulator_ops as3722_ldo6_extcntrl_ops = { +static const struct regulator_ops as3722_ldo6_extcntrl_ops = { .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -463,7 +463,7 @@ static const struct regulator_linear_range as3722_ldo_ranges[] = { REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000), }; -static struct regulator_ops as3722_ldo_ops = { +static const struct regulator_ops as3722_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -475,7 +475,7 @@ static struct regulator_ops as3722_ldo_ops = { .set_current_limit = as3722_ldo_set_current_limit, }; -static struct regulator_ops as3722_ldo_extcntrl_ops = { +static const struct regulator_ops as3722_ldo_extcntrl_ops = { .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -641,7 +641,7 @@ static const struct regulator_linear_range as3722_sd2345_ranges[] = { REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000), }; -static struct regulator_ops as3722_sd016_ops = { +static const struct regulator_ops as3722_sd016_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -655,7 +655,7 @@ static struct regulator_ops as3722_sd016_ops = { .set_mode = as3722_sd_set_mode, }; -static struct regulator_ops as3722_sd016_extcntrl_ops = { +static const struct regulator_ops as3722_sd016_extcntrl_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -666,7 +666,7 @@ static struct regulator_ops as3722_sd016_extcntrl_ops = { .set_mode = as3722_sd_set_mode, }; -static struct regulator_ops as3722_sd2345_ops = { +static const struct regulator_ops as3722_sd2345_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -678,7 +678,7 @@ static struct regulator_ops as3722_sd2345_ops = { .set_mode = as3722_sd_set_mode, }; -static struct regulator_ops as3722_sd2345_extcntrl_ops = { +static const struct regulator_ops as3722_sd2345_extcntrl_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -785,7 +785,7 @@ static int as3722_regulator_probe(struct platform_device *pdev) struct as3722_regulator_config_data *reg_config; struct regulator_dev *rdev; struct regulator_config config = { }; - struct regulator_ops *ops; + const struct regulator_ops *ops; int id; int ret; -- GitLab From e28b124564e648d933337a0708dae1323c518af7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:44 +0200 Subject: [PATCH 1975/9938] i2c: guarantee that I2C_M_RD will be 0x0001 forever There is code out there in user space and kernel space which relies on I2C_M_RD being bit 0 to simplify their bit operations. Add a comment to make sure this will never break. Do proper sorting of the defines while we are here. Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- include/uapi/linux/i2c.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h index b0a7dd61eb35..adcbef4bff61 100644 --- a/include/uapi/linux/i2c.h +++ b/include/uapi/linux/i2c.h @@ -68,14 +68,15 @@ struct i2c_msg { __u16 addr; /* slave address */ __u16 flags; -#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ #define I2C_M_RD 0x0001 /* read data, from slave to master */ -#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ -#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ -#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ -#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ -#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ + /* I2C_M_RD is guaranteed to be 0x0001! */ +#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ +#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ __u16 len; /* msg length */ __u8 *buf; /* pointer to msg data */ }; -- GitLab From a16d6ebca6efb73f6402f36e5aebf84f61721856 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:45 +0200 Subject: [PATCH 1976/9938] i2c: introduce helper function to get 8 bit address from a message Drivers do this in various ways, let's use one standard way of doing it. Note: I2C_M_RD is bit 0, so the code could be simplified. To be extremly robust and to advertise good coding practices, I still use the ternary operator and let the compilers do the optimizing job. Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- include/linux/i2c.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 200cf13b00f6..c30833b7b073 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -654,6 +654,11 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap) return adap->nr; } +static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg) +{ + return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0); +} + /** * module_i2c_driver() - Helper macro for registering a modular I2C driver * @__i2c_driver: i2c_driver struct -- GitLab From 041edda8757b5567b4d417e0cc9ade504dd4292f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:46 +0200 Subject: [PATCH 1977/9938] i2c: core: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e584d88ee337..cc3c143b1c6a 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -2646,7 +2646,7 @@ static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) { /* The address will be sent first */ - u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD); + u8 addr = i2c_8bit_addr_from_msg(msg); pec = i2c_smbus_pec(pec, &addr, 1); /* The data buffer follows */ -- GitLab From 32822bff880bd9c3b55145e258d03dc671f0d2ea Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:47 +0200 Subject: [PATCH 1978/9938] i2c: bcm-iproc: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm-iproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index b9f0fff4e723..19c843828fe2 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -267,7 +267,7 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, iproc_i2c->msg = msg; /* format and load slave address into the TX FIFO */ - addr = msg->addr << 1 | (msg->flags & I2C_M_RD ? 1 : 0); + addr = i2c_8bit_addr_from_msg(msg); writel(addr, iproc_i2c->base + M_TX_OFFSET); /* -- GitLab From 191d738d847e63b24da7cacbdfb179e5b5a9145f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:48 +0200 Subject: [PATCH 1979/9938] i2c: bcm-kona: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm-kona.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index 2c9d9b1c8e64..ac9f47679c3a 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -501,10 +501,7 @@ static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev, return -EREMOTEIO; } } else { - addr = msg->addr << 1; - - if (msg->flags & I2C_M_RD) - addr |= 1; + addr = i2c_8bit_addr_from_msg(msg); if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) return -EREMOTEIO; -- GitLab From fa5ce47a994867e79bd595ec2eef5178834c2570 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:49 +0200 Subject: [PATCH 1980/9938] i2c: brcmstb: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-brcmstb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 4a45408dd820..6a8cfc1344b2 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -446,9 +446,7 @@ static int brcmstb_i2c_do_addr(struct brcmstb_i2c_dev *dev, } } else { - addr = msg->addr << 1; - if (msg->flags & I2C_M_RD) - addr |= 1; + addr = i2c_8bit_addr_from_msg(msg); bsc_writel(dev, addr, chip_address); } -- GitLab From 949d0c5b72b94fb58a1d2c48c223658af24f58ee Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:50 +0200 Subject: [PATCH 1981/9938] i2c: cpm: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cpm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 714bdc837769..b6d2821aaabd 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -197,9 +197,7 @@ static void cpm_i2c_parse_message(struct i2c_adapter *adap, tbdf = cpm->tbase + tx; rbdf = cpm->rbase + rx; - addr = pmsg->addr << 1; - if (pmsg->flags & I2C_M_RD) - addr |= 1; + addr = i2c_8bit_addr_from_msg(pmsg); tb = cpm->txbuf[tx]; rb = cpm->rxbuf[rx]; -- GitLab From 73fef2196dd654ffda44486842d336c851d9294d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:51 +0200 Subject: [PATCH 1982/9938] i2c: ibm_iic: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-ibm_iic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index b6c080334297..cdaa7be2cd1b 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -269,7 +269,7 @@ static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p) ndelay(t->hd_sta); /* Send address */ - v = (u8)((p->addr << 1) | ((p->flags & I2C_M_RD) ? 1 : 0)); + v = i2c_8bit_addr_from_msg(p); for (i = 0, mask = 0x80; i < 8; ++i, mask >>= 1){ out_8(&iic->directcntl, sda); ndelay(t->low / 2); -- GitLab From 9c01cae8dd841a3d7b2f7763affd4e3fd16cebcf Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:52 +0200 Subject: [PATCH 1983/9938] i2c: img-scb: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-img-scb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 379ef9c31664..ea20425b6972 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -751,9 +751,7 @@ static unsigned int img_i2c_atomic(struct img_i2c *i2c, switch (i2c->at_cur_cmd) { case CMD_GEN_START: next_cmd = CMD_GEN_DATA; - next_data = (i2c->msg.addr << 1); - if (i2c->msg.flags & I2C_M_RD) - next_data |= 0x1; + next_data = i2c_8bit_addr_from_msg(&i2c->msg); break; case CMD_GEN_DATA: if (i2c->line_status & LINESTAT_INPUT_HELD_V) -- GitLab From 515e240bb54c53195fe0c7a9bad92ffb23e8bc54 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:53 +0200 Subject: [PATCH 1984/9938] i2c: iop3xx: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-iop3xx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 72d6161cf77c..85cbe4b55578 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -50,10 +50,7 @@ iic_cook_addr(struct i2c_msg *msg) { unsigned char addr; - addr = (msg->addr << 1); - - if (msg->flags & I2C_M_RD) - addr |= 1; + addr = i2c_8bit_addr_from_msg(msg); return addr; } -- GitLab From 043f47f49b3646beab84019eefb2c336be87db5f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:54 +0200 Subject: [PATCH 1985/9938] i2c: lpc2k: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-lpc2k.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 8560a13bf1b3..586a15205e61 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -133,9 +133,7 @@ static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c) case M_START: case M_REPSTART: /* Start bit was just sent out, send out addr and dir */ - data = i2c->msg->addr << 1; - if (i2c->msg->flags & I2C_M_RD) - data |= 1; + data = i2c_8bit_addr_from_msg(i2c->msg); writel(data, i2c->base + LPC24XX_I2DAT); writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); -- GitLab From 0d47ce210a5d6733d7bc8cb07f158908bb224629 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:55 +0200 Subject: [PATCH 1986/9938] i2c: mt65xx: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mt65xx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 453358b4d9ca..d9373e60be8a 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -413,10 +413,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, else writew(I2C_FS_START_CON, i2c->base + OFFSET_EXT_CONF); - addr_reg = msgs->addr << 1; - if (i2c->op == I2C_MASTER_RD) - addr_reg |= 0x1; - + addr_reg = i2c_8bit_addr_from_msg(msgs); writew(addr_reg, i2c->base + OFFSET_SLAVE_ADDR); /* Clear interrupt status */ -- GitLab From 380a295c87a6423390898b98e388e1b0a399bb08 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:56 +0200 Subject: [PATCH 1987/9938] i2c: ocores: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-ocores.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 11b7b87311ed..dfa7a4b4a91d 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -178,10 +178,7 @@ static void ocores_process(struct ocores_i2c *i2c) if (i2c->nmsgs) { /* end? */ /* send start? */ if (!(msg->flags & I2C_M_NOSTART)) { - u8 addr = (msg->addr << 1); - - if (msg->flags & I2C_M_RD) - addr |= 1; + u8 addr = i2c_8bit_addr_from_msg(msg); i2c->state = STATE_START; -- GitLab From 7756e1ee78b37ddb98bfcc815002cb885a0449c8 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:57 +0200 Subject: [PATCH 1988/9938] i2c: powermac: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-powermac.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 6abcf696e359..b0d9dee14a7e 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -150,13 +150,11 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap, { struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); int rc = 0; - int read; int addrdir; if (msgs->flags & I2C_M_TEN) return -EINVAL; - read = (msgs->flags & I2C_M_RD) != 0; - addrdir = (msgs->addr << 1) | read; + addrdir = i2c_8bit_addr_from_msg(msgs); rc = pmac_i2c_open(bus, 0); if (rc) { -- GitLab From e3c60f3d2d8bc803806262ecb4ec5b2723bcd606 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:58 +0200 Subject: [PATCH 1989/9938] i2c: qup: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-qup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 23eaabb19f96..cc6439ab3f71 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -515,7 +515,7 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup) static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup, struct i2c_msg *msg, int is_dma) { - u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD); + u16 addr = i2c_8bit_addr_from_msg(msg); int len = 0; int data_len; -- GitLab From 3f8a57bb6d5fb37c0b02d091184b01eab9dcf43a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:44:59 +0200 Subject: [PATCH 1990/9938] i2c: sh_mobile: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 7d2bd3ec2d2d..6fb3e2645992 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -398,8 +398,7 @@ static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd, { switch (pd->pos) { case -1: - *buf = (pd->msg->addr & 0x7f) << 1; - *buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0; + *buf = i2c_8bit_addr_from_msg(pd->msg); break; default: *buf = pd->msg->buf[pd->pos]; -- GitLab From 5c1274fab5c10aa193f5740dd76780010bda77d7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:45:00 +0200 Subject: [PATCH 1991/9938] i2c: sirf: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sirf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 13e51ef6af73..792a42bdd335 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -190,9 +190,7 @@ static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic, writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - addr = msg->addr << 1; /* Generate address */ - if (msg->flags & I2C_M_RD) - addr |= 1; + addr = i2c_8bit_addr_from_msg(msg); /* Reverse direction bit */ if (msg->flags & I2C_M_REV_DIR_ADDR) -- GitLab From a51a79d50ebc21d47f73f1e7f695ef2f86ef3417 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 3 Apr 2016 20:45:01 +0200 Subject: [PATCH 1992/9938] i2c: st: use new 8 bit address helper function Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-st.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index 6ee77159ac57..b3c182fea165 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -614,8 +614,7 @@ static int st_i2c_xfer_msg(struct st_i2c_dev *i2c_dev, struct i2c_msg *msg, unsigned long timeout; int ret; - c->addr = (u8)(msg->addr << 1); - c->addr |= (msg->flags & I2C_M_RD); + c->addr = i2c_8bit_addr_from_msg(msg); c->buf = msg->buf; c->count = msg->len; c->xfered = 0; -- GitLab From 8cc6ddfcafbb7e32ff025f7d9551ecf9649c12cd Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 5 Apr 2016 15:26:50 -0700 Subject: [PATCH 1993/9938] libnvdimm, nfit: report multiple interface codes per-dimm Starting with ACPI 6.1 an NFIT table will report multiple 'NVDIMM Control Region Structure' instances per-dimm, one for each supported format interface. Report that code in the following format in sysfs: nmemX/nfit/formats nmemX/nfit/format nmemX/nfit/format1 nmemX/nfit/format2 ... nmemX/nfit/formatN Where format2 - formatN are theoretical as there are no known DIMMs with support for more than two interface formats. This layout is compatible with existing libndctl binaries that only expect one code per-dimm as they will ignore nmemX/nfit/formats and nmemX/nfit/formatN. Signed-off-by: Dan Williams --- drivers/acpi/nfit.c | 72 +++++++++++++++++++++++++++++++++++++++++++-- drivers/acpi/nfit.h | 1 + 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index d0f35e63640b..db0f806b8388 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c @@ -655,6 +655,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, if (!nfit_mem) return -ENOMEM; INIT_LIST_HEAD(&nfit_mem->list); + nfit_mem->acpi_desc = acpi_desc; list_add(&nfit_mem->list, &acpi_desc->dimms); } @@ -838,6 +839,18 @@ static ssize_t device_show(struct device *dev, } static DEVICE_ATTR_RO(device); +static int num_nvdimm_formats(struct nvdimm *nvdimm) +{ + struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); + int formats = 0; + + if (nfit_mem->memdev_pmem) + formats++; + if (nfit_mem->memdev_bdw) + formats++; + return formats; +} + static ssize_t format_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -847,6 +860,55 @@ static ssize_t format_show(struct device *dev, } static DEVICE_ATTR_RO(format); +static ssize_t format1_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 handle; + ssize_t rc = -ENXIO; + struct nfit_mem *nfit_mem; + struct nfit_memdev *nfit_memdev; + struct acpi_nfit_desc *acpi_desc; + struct nvdimm *nvdimm = to_nvdimm(dev); + struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); + + nfit_mem = nvdimm_provider_data(nvdimm); + acpi_desc = nfit_mem->acpi_desc; + handle = to_nfit_memdev(dev)->device_handle; + + /* assumes DIMMs have at most 2 published interface codes */ + mutex_lock(&acpi_desc->init_mutex); + list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { + struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev; + struct nfit_dcr *nfit_dcr; + + if (memdev->device_handle != handle) + continue; + + list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) { + if (nfit_dcr->dcr->region_index != memdev->region_index) + continue; + if (nfit_dcr->dcr->code == dcr->code) + continue; + rc = sprintf(buf, "%#x\n", nfit_dcr->dcr->code); + break; + } + if (rc != ENXIO) + break; + } + mutex_unlock(&acpi_desc->init_mutex); + return rc; +} +static DEVICE_ATTR_RO(format1); + +static ssize_t formats_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvdimm *nvdimm = to_nvdimm(dev); + + return sprintf(buf, "%d\n", num_nvdimm_formats(nvdimm)); +} +static DEVICE_ATTR_RO(formats); + static ssize_t serial_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -876,6 +938,8 @@ static struct attribute *acpi_nfit_dimm_attributes[] = { &dev_attr_vendor.attr, &dev_attr_device.attr, &dev_attr_format.attr, + &dev_attr_formats.attr, + &dev_attr_format1.attr, &dev_attr_serial.attr, &dev_attr_rev_id.attr, &dev_attr_flags.attr, @@ -886,11 +950,13 @@ static umode_t acpi_nfit_dimm_attr_visible(struct kobject *kobj, struct attribute *a, int n) { struct device *dev = container_of(kobj, struct device, kobj); + struct nvdimm *nvdimm = to_nvdimm(dev); - if (to_nfit_dcr(dev)) - return a->mode; - else + if (!to_nfit_dcr(dev)) + return 0; + if (a == &dev_attr_format1.attr && num_nvdimm_formats(nvdimm) <= 1) return 0; + return a->mode; } static struct attribute_group acpi_nfit_dimm_attribute_group = { diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h index c75576b2d50e..5201840c1147 100644 --- a/drivers/acpi/nfit.h +++ b/drivers/acpi/nfit.h @@ -109,6 +109,7 @@ struct nfit_mem { struct nfit_flush *nfit_flush; struct list_head list; struct acpi_device *adev; + struct acpi_nfit_desc *acpi_desc; unsigned long dsm_mask; }; -- GitLab From baa51277cf5dc844089ea2f6e0f78b1c5ca665d8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 5 Apr 2016 17:40:52 -0700 Subject: [PATCH 1994/9938] libnvdimm, test: add mock SMART data payload Provide simulated SMART data to enable the ndctl implementation of SMART data retrieval and parsing. The payload is defined here, "Section 4.1 SMART and Health Info (Function Index 1)": http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf Signed-off-by: Dan Williams --- drivers/nvdimm/bus.c | 3 +++ include/uapi/linux/ndctl.h | 36 +++++++++++++++++++++++++- tools/testing/nvdimm/test/nfit.c | 44 ++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 19f822d7f652..8111b1299515 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -783,6 +783,9 @@ int __init nvdimm_bus_init(void) { int rc; + BUILD_BUG_ON(sizeof(struct nd_smart_payload) != 128); + BUILD_BUG_ON(sizeof(struct nd_smart_threshold_payload) != 8); + rc = bus_register(&nvdimm_bus_type); if (rc) return rc; diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h index 7cc28ab05b87..59c61e018a86 100644 --- a/include/uapi/linux/ndctl.h +++ b/include/uapi/linux/ndctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, Intel Corporation. + * Copyright (c) 2014-2016, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, @@ -20,11 +20,45 @@ struct nd_cmd_smart { __u8 data[128]; } __packed; +#define ND_SMART_HEALTH_VALID (1 << 0) +#define ND_SMART_TEMP_VALID (1 << 1) +#define ND_SMART_SPARES_VALID (1 << 2) +#define ND_SMART_ALARM_VALID (1 << 3) +#define ND_SMART_USED_VALID (1 << 4) +#define ND_SMART_SHUTDOWN_VALID (1 << 5) +#define ND_SMART_VENDOR_VALID (1 << 6) +#define ND_SMART_TEMP_TRIP (1 << 0) +#define ND_SMART_SPARE_TRIP (1 << 1) +#define ND_SMART_NON_CRITICAL_HEALTH (1 << 0) +#define ND_SMART_CRITICAL_HEALTH (1 << 1) +#define ND_SMART_FATAL_HEALTH (1 << 2) + +struct nd_smart_payload { + __u32 flags; + __u8 reserved0[4]; + __u8 health; + __u16 temperature; + __u8 spares; + __u8 alarm_flags; + __u8 life_used; + __u8 shutdown_state; + __u8 reserved1; + __u32 vendor_size; + __u8 vendor_data[108]; +} __packed; + struct nd_cmd_smart_threshold { __u32 status; __u8 data[8]; } __packed; +struct nd_smart_threshold_payload { + __u16 alarm_control; + __u16 temperature; + __u8 spares; + __u8 reserved[3]; +} __packed; + struct nd_cmd_dimm_flags { __u32 status; __u32 flags; diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 3187322eeed7..d1c98d4386d4 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -330,6 +330,42 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err, return 0; } +static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len) +{ + static const struct nd_smart_payload smart_data = { + .flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID + | ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID + | ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID, + .health = ND_SMART_NON_CRITICAL_HEALTH, + .temperature = 23 * 16, + .spares = 75, + .alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP, + .life_used = 5, + .shutdown_state = 0, + .vendor_size = 0, + }; + + if (buf_len < sizeof(*smart)) + return -EINVAL; + memcpy(smart->data, &smart_data, sizeof(smart_data)); + return 0; +} + +static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t, + unsigned int buf_len) +{ + static const struct nd_smart_threshold_payload smart_t_data = { + .alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP, + .temperature = 40 * 16, + .spares = 5, + }; + + if (buf_len < sizeof(*smart_t)) + return -EINVAL; + memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data)); + return 0; +} + static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) @@ -368,6 +404,12 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, rc = nfit_test_cmd_set_config_data(buf, buf_len, t->label[i]); break; + case ND_CMD_SMART: + rc = nfit_test_cmd_smart(buf, buf_len); + break; + case ND_CMD_SMART_THRESHOLD: + rc = nfit_test_cmd_smart_threshold(buf, buf_len); + break; default: return -ENOTTY; } @@ -1254,10 +1296,12 @@ static void nfit_test0_setup(struct nfit_test *t) set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); + set_bit(ND_CMD_SMART, &acpi_desc->dimm_dsm_force_en); set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); + set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_dsm_force_en); } static void nfit_test1_setup(struct nfit_test *t) -- GitLab From 8259542348d93da6a04eed979047b1fd1ca72abe Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Thu, 21 Jan 2016 20:32:10 +0800 Subject: [PATCH 1995/9938] libnvdimm, nfit: Use ACPI_SIG_NFIT instead of hard coded string It's minor but that's still better to use ACPI_SIG_NFIT instead of hard coded string. Cc: Ross Zwisler Cc: "Rafael J. Wysocki" Cc: Len Brown Signed-off-by: Lee, Chun-Yi Acked-by: Ross Zwisler Signed-off-by: Dan Williams --- drivers/acpi/nfit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index db0f806b8388..a434b58c5e11 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c @@ -2372,7 +2372,7 @@ static int acpi_nfit_add(struct acpi_device *adev) acpi_size sz; int rc; - status = acpi_get_table_with_size("NFIT", 0, &tbl, &sz); + status = acpi_get_table_with_size(ACPI_SIG_NFIT, 0, &tbl, &sz); if (ACPI_FAILURE(status)) { /* This is ok, we could have an nvdimm hotplugged later */ dev_dbg(dev, "failed to find NFIT at startup\n"); -- GitLab From d07e187cf0621891514a47f316597fea8963e5a7 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 5 Jan 2016 14:18:16 -0600 Subject: [PATCH 1996/9938] ARM: dts: socfpga: add cap-sd-highspeed for SD/MMC node Enable SD highspeed support for the SoCFPGA Arria10 devkit. Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts index dbbb751ac1ba..8a7dfa473e98 100644 --- a/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts +++ b/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts @@ -21,6 +21,7 @@ &mmc { status = "okay"; num-slots = <1>; + cap-sd-highspeed; broken-cd; bus-width = <4>; }; -- GitLab From faf68cdfdf6c9f0999686802ad066b1378b89413 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 5 Jan 2016 14:59:38 -0600 Subject: [PATCH 1997/9938] ARM: dts: socfpga: add the clk-phase property for sd/mmc clock The CIU clock for the SD/MMC should be the sdmmc_clk and not the sdmmc_free_clk. Also, add the correct phase shift the sdmmc_clk. Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index 1c5e139e4d05..f75dd232ec2e 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -362,6 +362,7 @@ compatible = "altr,socfpga-a10-gate-clk"; clocks = <&sdmmc_free_clk>; clk-gate = <0xC8 5>; + clk-phase = <0 135>; }; qspi_clk: qspi_clk { @@ -589,7 +590,7 @@ reg = <0xff808000 0x1000>; interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>; fifo-depth = <0x400>; - clocks = <&l4_mp_clk>, <&sdmmc_free_clk>; + clocks = <&l4_mp_clk>, <&sdmmc_clk>; clock-names = "biu", "ciu"; status = "disabled"; }; -- GitLab From 308cfdaf9a9120b88c5f523c755daf464959bf16 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 1 Apr 2016 16:20:18 -0400 Subject: [PATCH 1998/9938] ARM: dts: omap: add missing unit name to pbias regulator nodes This patch fixes the following DTC warnings: "pbias_regulator has a reg or ranges property, but no unit name" Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 2 +- arch/arm/boot/dts/omap2430.dtsi | 2 +- arch/arm/boot/dts/omap3.dtsi | 2 +- arch/arm/boot/dts/omap4.dtsi | 2 +- arch/arm/boot/dts/omap5.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 13ac88279427..ed740d02ec17 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -123,7 +123,7 @@ #size-cells = <1>; ranges = <0 0x0 0x1400>; - pbias_regulator: pbias_regulator { + pbias_regulator: pbias_regulator@e00 { compatible = "ti,pbias-dra7", "ti,pbias-omap"; reg = <0xe00 0x4>; syscon = <&scm_conf>; diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi index 798dda072b2a..59828b0e34f1 100644 --- a/arch/arm/boot/dts/omap2430.dtsi +++ b/arch/arm/boot/dts/omap2430.dtsi @@ -63,7 +63,7 @@ #size-cells = <0>; }; - pbias_regulator: pbias_regulator { + pbias_regulator: pbias_regulator@230 { compatible = "ti,pbias-omap2", "ti,pbias-omap"; reg = <0x230 0x4>; syscon = <&scm_conf>; diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index b41d07e8e765..cbddde5d1e4f 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -119,7 +119,7 @@ #size-cells = <1>; ranges = <0 0x270 0x330>; - pbias_regulator: pbias_regulator { + pbias_regulator: pbias_regulator@2b0 { compatible = "ti,pbias-omap3", "ti,pbias-omap"; reg = <0x2b0 0x4>; syscon = <&scm_conf>; diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 2bd9c83300b2..2d8e95661e0b 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -198,7 +198,7 @@ #size-cells = <1>; ranges = <0 0x5a0 0x170>; - pbias_regulator: pbias_regulator { + pbias_regulator: pbias_regulator@60 { compatible = "ti,pbias-omap4", "ti,pbias-omap"; reg = <0x60 0x4>; syscon = <&omap4_padconf_global>; diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 38805ebbe2ba..b2297a560825 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -187,7 +187,7 @@ #size-cells = <1>; ranges = <0 0x5a0 0xec>; - pbias_regulator: pbias_regulator { + pbias_regulator: pbias_regulator@60 { compatible = "ti,pbias-omap5", "ti,pbias-omap"; reg = <0x60 0x4>; syscon = <&omap5_padconf_global>; -- GitLab From e72c378b8be62e072c067bfcb203dfd20530cd70 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 1 Apr 2016 16:20:19 -0400 Subject: [PATCH 1999/9938] ARM: dts: n8x0: remove unneeded unit name for i2c node This patch fixes the following DTC warnings: "i2c@0 has a unit name, but no reg property" Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap2420-n8x0-common.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi index 8491f46c61b7..db95aadcca70 100644 --- a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi +++ b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi @@ -7,7 +7,7 @@ }; ocp { - i2c@0 { + i2c0 { compatible = "i2c-cbus-gpio"; gpios = <&gpio3 2 GPIO_ACTIVE_HIGH /* gpio66 clk */ &gpio3 1 GPIO_ACTIVE_HIGH /* gpio65 dat */ -- GitLab From 2995a9e7094716bba08ca05f7a58e56d03ea4f9a Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 1 Apr 2016 16:20:20 -0400 Subject: [PATCH 2000/9938] ARM: dts: omap3: add missing unit name to PMU node This patch fixes the following DTC warnings: "pmu has a reg or ranges property, but no unit name" Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index cbddde5d1e4f..e31ea5efb163 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -43,7 +43,7 @@ }; }; - pmu { + pmu@54000000 { compatible = "arm,cortex-a8-pmu"; reg = <0x54000000 0x800000>; interrupts = <3>; -- GitLab From 4e8603eff519a946d6596ab92c380654cf72fedf Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 1 Apr 2016 16:20:21 -0400 Subject: [PATCH 2001/9938] ARM: dts: omap: remove unneeded unit name for sound nodes This patch fixes the following DTC warning: "sound@0 has a unit name, but no reg property" Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-gp-evm.dts | 2 +- arch/arm/boot/dts/am43x-epos-evm.dts | 2 +- arch/arm/boot/dts/am57xx-beagle-x15.dts | 2 +- arch/arm/boot/dts/am57xx-cl-som-am57x.dts | 2 +- arch/arm/boot/dts/dra7-evm.dts | 2 +- arch/arm/boot/dts/dra72-evm.dts | 2 +- arch/arm/boot/dts/omap4-var-som-om44.dtsi | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index 8889be1ca1c3..95ec82a77e67 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -119,7 +119,7 @@ clock-frequency = <32768>; }; - sound0: sound@0 { + sound0: sound0 { compatible = "simple-audio-card"; simple-audio-card,name = "AM437x-GP-EVM"; simple-audio-card,widgets = diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 83dfafaaba1b..d7978236ccad 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -107,7 +107,7 @@ default-brightness-level = <8>; }; - sound0: sound@0 { + sound0: sound0 { compatible = "simple-audio-card"; simple-audio-card,name = "AM43-EPOS-EVM"; simple-audio-card,widgets = diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 0a5fc5d02ce2..75bd09b175cd 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -151,7 +151,7 @@ }; }; - sound0: sound@0 { + sound0: sound0 { compatible = "simple-audio-card"; simple-audio-card,name = "BeagleBoard-X15"; simple-audio-card,widgets = diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts index 14f912a1b4fd..378b142ef88c 100644 --- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts +++ b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts @@ -51,7 +51,7 @@ regulator-max-microvolt = <3300000>; }; - sound0: sound@0 { + sound0: sound0 { compatible = "simple-audio-card"; simple-audio-card,name = "CL-SOM-AM57x-Sound-Card"; simple-audio-card,format = "i2s"; diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index d9b87236019d..074d70b191e2 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -67,7 +67,7 @@ gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>; }; - sound0: sound@0 { + sound0: sound0 { compatible = "simple-audio-card"; simple-audio-card,name = "DRA7xx-EVM"; simple-audio-card,widgets = diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index 6affe2d137da..6006ced8f6b3 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts @@ -104,7 +104,7 @@ }; }; - sound0: sound@0 { + sound0: sound0 { compatible = "simple-audio-card"; simple-audio-card,name = "DRA7xx-EVM"; simple-audio-card,widgets = diff --git a/arch/arm/boot/dts/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/omap4-var-som-om44.dtsi index 49d032b846be..a17997f4e9aa 100644 --- a/arch/arm/boot/dts/omap4-var-som-om44.dtsi +++ b/arch/arm/boot/dts/omap4-var-som-om44.dtsi @@ -17,7 +17,7 @@ reg = <0x80000000 0x40000000>; /* 1 GB */ }; - sound: sound@0 { + sound: sound { compatible = "ti,abe-twl6040"; ti,model = "VAR-SOM-OM44"; -- GitLab From 6905e94d4a100c6883849408e8e13acea98f5563 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 1 Apr 2016 16:20:22 -0400 Subject: [PATCH 2002/9938] ARM: dts: omap: add missing unit names to bandgap nodes This patch fixes the following DTC warnings: "bandgap has a reg or ranges property, but no unit name" Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap34xx.dtsi | 2 +- arch/arm/boot/dts/omap36xx.dtsi | 2 +- arch/arm/boot/dts/omap443x.dtsi | 2 +- arch/arm/boot/dts/omap4460.dtsi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/omap34xx.dtsi b/arch/arm/boot/dts/omap34xx.dtsi index 387dc31822fe..5cdba1f6499f 100644 --- a/arch/arm/boot/dts/omap34xx.dtsi +++ b/arch/arm/boot/dts/omap34xx.dtsi @@ -55,7 +55,7 @@ }; }; - bandgap { + bandgap@48002524 { reg = <0x48002524 0x4>; compatible = "ti,omap34xx-bandgap"; #thermal-sensor-cells = <0>; diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi index f19c87bd6bf3..ce1e242d4dc0 100644 --- a/arch/arm/boot/dts/omap36xx.dtsi +++ b/arch/arm/boot/dts/omap36xx.dtsi @@ -87,7 +87,7 @@ }; }; - bandgap { + bandgap@48002524 { reg = <0x48002524 0x4>; compatible = "ti,omap36xx-bandgap"; #thermal-sensor-cells = <0>; diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi index 0adfa1d1ef20..fc6a8610c24c 100644 --- a/arch/arm/boot/dts/omap443x.dtsi +++ b/arch/arm/boot/dts/omap443x.dtsi @@ -35,7 +35,7 @@ }; ocp { - bandgap: bandgap { + bandgap: bandgap@4a002260 { reg = <0x4a002260 0x4 0x4a00232C 0x4>; compatible = "ti,omap4430-bandgap"; diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi index 5fa68f191af7..ef66e12e0a67 100644 --- a/arch/arm/boot/dts/omap4460.dtsi +++ b/arch/arm/boot/dts/omap4460.dtsi @@ -40,7 +40,7 @@ }; ocp { - bandgap: bandgap { + bandgap: bandgap@4a002260 { reg = <0x4a002260 0x4 0x4a00232C 0x4 0x4a002378 0x18>; -- GitLab From b5b5340d6ecc37db230280241cc776bb9556c8df Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:06 +0300 Subject: [PATCH 2003/9938] ARM: dts: omap3: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for OMAP3 clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am35xx-clocks.dtsi | 20 +- arch/arm/boot/dts/omap3430es1-clocks.dtsi | 30 +- .../boot/dts/omap34xx-omap36xx-clocks.dtsi | 44 +-- ...map36xx-am35xx-omap3430es2plus-clocks.dtsi | 32 +- arch/arm/boot/dts/omap36xx-clocks.dtsi | 14 +- .../dts/omap36xx-omap3430es2plus-clocks.dtsi | 14 +- arch/arm/boot/dts/omap3xxx-clocks.dtsi | 276 +++++++++--------- 7 files changed, 215 insertions(+), 215 deletions(-) diff --git a/arch/arm/boot/dts/am35xx-clocks.dtsi b/arch/arm/boot/dts/am35xx-clocks.dtsi index 18cc826e9db5..00dd1f091be5 100644 --- a/arch/arm/boot/dts/am35xx-clocks.dtsi +++ b/arch/arm/boot/dts/am35xx-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &scm_clocks { - emac_ick: emac_ick { + emac_ick: emac_ick@32c { #clock-cells = <0>; compatible = "ti,am35xx-gate-clock"; clocks = <&ipss_ick>; @@ -16,7 +16,7 @@ ti,bit-shift = <1>; }; - emac_fck: emac_fck { + emac_fck: emac_fck@32c { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&rmii_ck>; @@ -24,7 +24,7 @@ ti,bit-shift = <9>; }; - vpfe_ick: vpfe_ick { + vpfe_ick: vpfe_ick@32c { #clock-cells = <0>; compatible = "ti,am35xx-gate-clock"; clocks = <&ipss_ick>; @@ -32,7 +32,7 @@ ti,bit-shift = <2>; }; - vpfe_fck: vpfe_fck { + vpfe_fck: vpfe_fck@32c { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&pclk_ck>; @@ -40,7 +40,7 @@ ti,bit-shift = <10>; }; - hsotgusb_ick_am35xx: hsotgusb_ick_am35xx { + hsotgusb_ick_am35xx: hsotgusb_ick_am35xx@32c { #clock-cells = <0>; compatible = "ti,am35xx-gate-clock"; clocks = <&ipss_ick>; @@ -48,7 +48,7 @@ ti,bit-shift = <0>; }; - hsotgusb_fck_am35xx: hsotgusb_fck_am35xx { + hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@32c { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_ck>; @@ -56,7 +56,7 @@ ti,bit-shift = <8>; }; - hecc_ck: hecc_ck { + hecc_ck: hecc_ck@32c { #clock-cells = <0>; compatible = "ti,am35xx-gate-clock"; clocks = <&sys_ck>; @@ -65,7 +65,7 @@ }; }; &cm_clocks { - ipss_ick: ipss_ick { + ipss_ick: ipss_ick@a10 { #clock-cells = <0>; compatible = "ti,am35xx-interface-clock"; clocks = <&core_l3_ick>; @@ -85,7 +85,7 @@ clock-frequency = <27000000>; }; - uart4_ick_am35xx: uart4_ick_am35xx { + uart4_ick_am35xx: uart4_ick_am35xx@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -93,7 +93,7 @@ ti,bit-shift = <23>; }; - uart4_fck_am35xx: uart4_fck_am35xx { + uart4_fck_am35xx: uart4_fck_am35xx@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; diff --git a/arch/arm/boot/dts/omap3430es1-clocks.dtsi b/arch/arm/boot/dts/omap3430es1-clocks.dtsi index 4c22f3a7f813..86de819a0dcf 100644 --- a/arch/arm/boot/dts/omap3430es1-clocks.dtsi +++ b/arch/arm/boot/dts/omap3430es1-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &cm_clocks { - gfx_l3_ck: gfx_l3_ck { + gfx_l3_ck: gfx_l3_ck@b10 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&l3_ick>; @@ -16,7 +16,7 @@ ti,bit-shift = <0>; }; - gfx_l3_fck: gfx_l3_fck { + gfx_l3_fck: gfx_l3_fck@b40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&l3_ick>; @@ -33,7 +33,7 @@ clock-div = <1>; }; - gfx_cg1_ck: gfx_cg1_ck { + gfx_cg1_ck: gfx_cg1_ck@b00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&gfx_l3_fck>; @@ -41,7 +41,7 @@ ti,bit-shift = <1>; }; - gfx_cg2_ck: gfx_cg2_ck { + gfx_cg2_ck: gfx_cg2_ck@b00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&gfx_l3_fck>; @@ -49,7 +49,7 @@ ti,bit-shift = <2>; }; - d2d_26m_fck: d2d_26m_fck { + d2d_26m_fck: d2d_26m_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&sys_ck>; @@ -57,7 +57,7 @@ ti,bit-shift = <3>; }; - fshostusb_fck: fshostusb_fck { + fshostusb_fck: fshostusb_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; @@ -65,7 +65,7 @@ ti,bit-shift = <5>; }; - ssi_ssr_gate_fck_3430es1: ssi_ssr_gate_fck_3430es1 { + ssi_ssr_gate_fck_3430es1: ssi_ssr_gate_fck_3430es1@a00 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&corex2_fck>; @@ -73,7 +73,7 @@ reg = <0x0a00>; }; - ssi_ssr_div_fck_3430es1: ssi_ssr_div_fck_3430es1 { + ssi_ssr_div_fck_3430es1: ssi_ssr_div_fck_3430es1@a40 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&corex2_fck>; @@ -96,7 +96,7 @@ clock-div = <2>; }; - hsotgusb_ick_3430es1: hsotgusb_ick_3430es1 { + hsotgusb_ick_3430es1: hsotgusb_ick_3430es1@a10 { #clock-cells = <0>; compatible = "ti,omap3-no-wait-interface-clock"; clocks = <&core_l3_ick>; @@ -104,7 +104,7 @@ ti,bit-shift = <4>; }; - fac_ick: fac_ick { + fac_ick: fac_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -120,7 +120,7 @@ clock-div = <1>; }; - ssi_ick: ssi_ick_3430es1 { + ssi_ick: ssi_ick_3430es1@a10 { #clock-cells = <0>; compatible = "ti,omap3-no-wait-interface-clock"; clocks = <&ssi_l4_ick>; @@ -128,7 +128,7 @@ ti,bit-shift = <0>; }; - usb_l4_gate_ick: usb_l4_gate_ick { + usb_l4_gate_ick: usb_l4_gate_ick@a10 { #clock-cells = <0>; compatible = "ti,composite-interface-clock"; clocks = <&l4_ick>; @@ -136,7 +136,7 @@ reg = <0x0a10>; }; - usb_l4_div_ick: usb_l4_div_ick { + usb_l4_div_ick: usb_l4_div_ick@a40 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&l4_ick>; @@ -152,7 +152,7 @@ clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>; }; - dss1_alwon_fck: dss1_alwon_fck_3430es1 { + dss1_alwon_fck: dss1_alwon_fck_3430es1@e00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll4_m4x2_ck>; @@ -161,7 +161,7 @@ ti,set-rate-parent; }; - dss_ick: dss_ick_3430es1 { + dss_ick: dss_ick_3430es1@e10 { #clock-cells = <0>; compatible = "ti,omap3-no-wait-interface-clock"; clocks = <&l4_ick>; diff --git a/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi b/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi index b02017b7630e..858aa0796ec8 100644 --- a/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi @@ -16,7 +16,7 @@ clock-div = <1>; }; - aes1_ick: aes1_ick { + aes1_ick: aes1_ick@a14 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&security_l4_ick2>; @@ -24,7 +24,7 @@ reg = <0x0a14>; }; - rng_ick: rng_ick { + rng_ick: rng_ick@a14 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&security_l4_ick2>; @@ -32,7 +32,7 @@ ti,bit-shift = <2>; }; - sha11_ick: sha11_ick { + sha11_ick: sha11_ick@a14 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&security_l4_ick2>; @@ -40,7 +40,7 @@ ti,bit-shift = <1>; }; - des1_ick: des1_ick { + des1_ick: des1_ick@a14 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&security_l4_ick2>; @@ -48,7 +48,7 @@ ti,bit-shift = <0>; }; - cam_mclk: cam_mclk { + cam_mclk: cam_mclk@f00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll4_m5x2_ck>; @@ -57,7 +57,7 @@ ti,set-rate-parent; }; - cam_ick: cam_ick { + cam_ick: cam_ick@f10 { #clock-cells = <0>; compatible = "ti,omap3-no-wait-interface-clock"; clocks = <&l4_ick>; @@ -65,7 +65,7 @@ ti,bit-shift = <0>; }; - csi2_96m_fck: csi2_96m_fck { + csi2_96m_fck: csi2_96m_fck@f00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&core_96m_fck>; @@ -81,7 +81,7 @@ clock-div = <1>; }; - pka_ick: pka_ick { + pka_ick: pka_ick@a14 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&security_l3_ick>; @@ -89,7 +89,7 @@ ti,bit-shift = <4>; }; - icr_ick: icr_ick { + icr_ick: icr_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -97,7 +97,7 @@ ti,bit-shift = <29>; }; - des2_ick: des2_ick { + des2_ick: des2_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -105,7 +105,7 @@ ti,bit-shift = <26>; }; - mspro_ick: mspro_ick { + mspro_ick: mspro_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -113,7 +113,7 @@ ti,bit-shift = <23>; }; - mailboxes_ick: mailboxes_ick { + mailboxes_ick: mailboxes_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -129,7 +129,7 @@ clock-div = <1>; }; - sr1_fck: sr1_fck { + sr1_fck: sr1_fck@c00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&sys_ck>; @@ -137,7 +137,7 @@ ti,bit-shift = <6>; }; - sr2_fck: sr2_fck { + sr2_fck: sr2_fck@c00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&sys_ck>; @@ -153,7 +153,7 @@ clock-div = <1>; }; - dpll2_fck: dpll2_fck { + dpll2_fck: dpll2_fck@40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&core_ck>; @@ -163,7 +163,7 @@ ti,index-starts-at-one; }; - dpll2_ck: dpll2_ck { + dpll2_ck: dpll2_ck@4 { #clock-cells = <0>; compatible = "ti,omap3-dpll-clock"; clocks = <&sys_ck>, <&dpll2_fck>; @@ -173,7 +173,7 @@ ti,low-power-bypass; }; - dpll2_m2_ck: dpll2_m2_ck { + dpll2_m2_ck: dpll2_m2_ck@44 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll2_ck>; @@ -182,7 +182,7 @@ ti,index-starts-at-one; }; - iva2_ck: iva2_ck { + iva2_ck: iva2_ck@0 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&dpll2_m2_ck>; @@ -190,7 +190,7 @@ ti,bit-shift = <0>; }; - modem_fck: modem_fck { + modem_fck: modem_fck@a00 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -198,7 +198,7 @@ ti,bit-shift = <31>; }; - sad2d_ick: sad2d_ick { + sad2d_ick: sad2d_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l3_ick>; @@ -206,7 +206,7 @@ ti,bit-shift = <3>; }; - mad2d_ick: mad2d_ick { + mad2d_ick: mad2d_ick@a18 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l3_ick>; @@ -214,7 +214,7 @@ ti,bit-shift = <3>; }; - mspro_fck: mspro_fck { + mspro_fck: mspro_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_96m_fck>; diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi index 080fb3f4e429..15d18669000e 100644 --- a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +++ b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi @@ -25,7 +25,7 @@ }; }; &cm_clocks { - dpll5_ck: dpll5_ck { + dpll5_ck: dpll5_ck@d04 { #clock-cells = <0>; compatible = "ti,omap3-dpll-clock"; clocks = <&sys_ck>, <&sys_ck>; @@ -34,7 +34,7 @@ ti,lock; }; - dpll5_m2_ck: dpll5_m2_ck { + dpll5_m2_ck: dpll5_m2_ck@d50 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll5_ck>; @@ -43,7 +43,7 @@ ti,index-starts-at-one; }; - sgx_gate_fck: sgx_gate_fck { + sgx_gate_fck: sgx_gate_fck@b00 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&core_ck>; @@ -91,7 +91,7 @@ clock-div = <2>; }; - sgx_mux_fck: sgx_mux_fck { + sgx_mux_fck: sgx_mux_fck@b40 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&core_d3_ck>, <&core_d4_ck>, <&core_d6_ck>, <&cm_96m_fck>, <&omap_192m_alwon_fck>, <&core_d2_ck>, <&corex2_d3_fck>, <&corex2_d5_fck>; @@ -104,7 +104,7 @@ clocks = <&sgx_gate_fck>, <&sgx_mux_fck>; }; - sgx_ick: sgx_ick { + sgx_ick: sgx_ick@b10 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&l3_ick>; @@ -112,7 +112,7 @@ ti,bit-shift = <0>; }; - cpefuse_fck: cpefuse_fck { + cpefuse_fck: cpefuse_fck@a08 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_ck>; @@ -120,7 +120,7 @@ ti,bit-shift = <0>; }; - ts_fck: ts_fck { + ts_fck: ts_fck@a08 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&omap_32k_fck>; @@ -128,7 +128,7 @@ ti,bit-shift = <1>; }; - usbtll_fck: usbtll_fck { + usbtll_fck: usbtll_fck@a08 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&dpll5_m2_ck>; @@ -136,7 +136,7 @@ ti,bit-shift = <2>; }; - usbtll_ick: usbtll_ick { + usbtll_ick: usbtll_ick@a18 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -144,7 +144,7 @@ ti,bit-shift = <2>; }; - mmchs3_ick: mmchs3_ick { + mmchs3_ick: mmchs3_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -152,7 +152,7 @@ ti,bit-shift = <30>; }; - mmchs3_fck: mmchs3_fck { + mmchs3_fck: mmchs3_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_96m_fck>; @@ -160,7 +160,7 @@ ti,bit-shift = <30>; }; - dss1_alwon_fck: dss1_alwon_fck_3430es2 { + dss1_alwon_fck: dss1_alwon_fck_3430es2@e00 { #clock-cells = <0>; compatible = "ti,dss-gate-clock"; clocks = <&dpll4_m4x2_ck>; @@ -169,7 +169,7 @@ ti,set-rate-parent; }; - dss_ick: dss_ick_3430es2 { + dss_ick: dss_ick_3430es2@e10 { #clock-cells = <0>; compatible = "ti,omap3-dss-interface-clock"; clocks = <&l4_ick>; @@ -177,7 +177,7 @@ ti,bit-shift = <0>; }; - usbhost_120m_fck: usbhost_120m_fck { + usbhost_120m_fck: usbhost_120m_fck@1400 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll5_m2_ck>; @@ -185,7 +185,7 @@ ti,bit-shift = <1>; }; - usbhost_48m_fck: usbhost_48m_fck { + usbhost_48m_fck: usbhost_48m_fck@1400 { #clock-cells = <0>; compatible = "ti,dss-gate-clock"; clocks = <&omap_48m_fck>; @@ -193,7 +193,7 @@ ti,bit-shift = <0>; }; - usbhost_ick: usbhost_ick { + usbhost_ick: usbhost_ick@1410 { #clock-cells = <0>; compatible = "ti,omap3-dss-interface-clock"; clocks = <&l4_ick>; diff --git a/arch/arm/boot/dts/omap36xx-clocks.dtsi b/arch/arm/boot/dts/omap36xx-clocks.dtsi index 200ae3a5cbbb..a21d1f021267 100644 --- a/arch/arm/boot/dts/omap36xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap36xx-clocks.dtsi @@ -8,14 +8,14 @@ * published by the Free Software Foundation. */ &cm_clocks { - dpll4_ck: dpll4_ck { + dpll4_ck: dpll4_ck@d00 { #clock-cells = <0>; compatible = "ti,omap3-dpll-per-j-type-clock"; clocks = <&sys_ck>, <&sys_ck>; reg = <0x0d00>, <0x0d20>, <0x0d44>, <0x0d30>; }; - dpll4_m5x2_ck: dpll4_m5x2_ck { + dpll4_m5x2_ck: dpll4_m5x2_ck@d00 { #clock-cells = <0>; compatible = "ti,hsdiv-gate-clock"; clocks = <&dpll4_m5x2_mul_ck>; @@ -25,7 +25,7 @@ ti,set-bit-to-disable; }; - dpll4_m2x2_ck: dpll4_m2x2_ck { + dpll4_m2x2_ck: dpll4_m2x2_ck@d00 { #clock-cells = <0>; compatible = "ti,hsdiv-gate-clock"; clocks = <&dpll4_m2x2_mul_ck>; @@ -34,7 +34,7 @@ ti,set-bit-to-disable; }; - dpll3_m3x2_ck: dpll3_m3x2_ck { + dpll3_m3x2_ck: dpll3_m3x2_ck@d00 { #clock-cells = <0>; compatible = "ti,hsdiv-gate-clock"; clocks = <&dpll3_m3x2_mul_ck>; @@ -43,7 +43,7 @@ ti,set-bit-to-disable; }; - dpll4_m3x2_ck: dpll4_m3x2_ck { + dpll4_m3x2_ck: dpll4_m3x2_ck@d00 { #clock-cells = <0>; compatible = "ti,hsdiv-gate-clock"; clocks = <&dpll4_m3x2_mul_ck>; @@ -52,7 +52,7 @@ ti,set-bit-to-disable; }; - dpll4_m6x2_ck: dpll4_m6x2_ck { + dpll4_m6x2_ck: dpll4_m6x2_ck@d00 { #clock-cells = <0>; compatible = "ti,hsdiv-gate-clock"; clocks = <&dpll4_m6x2_mul_ck>; @@ -61,7 +61,7 @@ ti,set-bit-to-disable; }; - uart4_fck: uart4_fck { + uart4_fck: uart4_fck@1000 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&per_48m_fck>; diff --git a/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi index 877318c28364..1a4fbdf0d9cc 100644 --- a/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi +++ b/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &cm_clocks { - ssi_ssr_gate_fck_3430es2: ssi_ssr_gate_fck_3430es2 { + ssi_ssr_gate_fck_3430es2: ssi_ssr_gate_fck_3430es2@a00 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&corex2_fck>; @@ -16,7 +16,7 @@ reg = <0x0a00>; }; - ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2 { + ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2@a40 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&corex2_fck>; @@ -39,7 +39,7 @@ clock-div = <2>; }; - hsotgusb_ick_3430es2: hsotgusb_ick_3430es2 { + hsotgusb_ick_3430es2: hsotgusb_ick_3430es2@a10 { #clock-cells = <0>; compatible = "ti,omap3-hsotgusb-interface-clock"; clocks = <&core_l3_ick>; @@ -55,7 +55,7 @@ clock-div = <1>; }; - ssi_ick: ssi_ick_3430es2 { + ssi_ick: ssi_ick_3430es2@a10 { #clock-cells = <0>; compatible = "ti,omap3-ssi-interface-clock"; clocks = <&ssi_l4_ick>; @@ -63,7 +63,7 @@ ti,bit-shift = <0>; }; - usim_gate_fck: usim_gate_fck { + usim_gate_fck: usim_gate_fck@c00 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&omap_96m_fck>; @@ -143,7 +143,7 @@ clock-div = <20>; }; - usim_mux_fck: usim_mux_fck { + usim_mux_fck: usim_mux_fck@c40 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_ck>, <&sys_d2_ck>, <&omap_96m_d2_fck>, <&omap_96m_d4_fck>, <&omap_96m_d8_fck>, <&omap_96m_d10_fck>, <&dpll5_m2_d4_ck>, <&dpll5_m2_d8_ck>, <&dpll5_m2_d16_ck>, <&dpll5_m2_d20_ck>; @@ -158,7 +158,7 @@ clocks = <&usim_gate_fck>, <&usim_mux_fck>; }; - usim_ick: usim_ick { + usim_ick: usim_ick@c10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&wkup_l4_ick>; diff --git a/arch/arm/boot/dts/omap3xxx-clocks.dtsi b/arch/arm/boot/dts/omap3xxx-clocks.dtsi index bbba5bdc4bc9..9bd91641aa7c 100644 --- a/arch/arm/boot/dts/omap3xxx-clocks.dtsi +++ b/arch/arm/boot/dts/omap3xxx-clocks.dtsi @@ -14,14 +14,14 @@ clock-frequency = <16800000>; }; - osc_sys_ck: osc_sys_ck { + osc_sys_ck: osc_sys_ck@d40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_12m_ck>, <&virt_13m_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_38_4m_ck>, <&virt_16_8m_ck>; reg = <0x0d40>; }; - sys_ck: sys_ck { + sys_ck: sys_ck@1270 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&osc_sys_ck>; @@ -31,7 +31,7 @@ ti,index-starts-at-one; }; - sys_clkout1: sys_clkout1 { + sys_clkout1: sys_clkout1@d70 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&osc_sys_ck>; @@ -81,7 +81,7 @@ }; &scm_clocks { - mcbsp5_mux_fck: mcbsp5_mux_fck { + mcbsp5_mux_fck: mcbsp5_mux_fck@68 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&core_96m_fck>, <&mcbsp_clks>; @@ -95,7 +95,7 @@ clocks = <&mcbsp5_gate_fck>, <&mcbsp5_mux_fck>; }; - mcbsp1_mux_fck: mcbsp1_mux_fck { + mcbsp1_mux_fck: mcbsp1_mux_fck@4 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&core_96m_fck>, <&mcbsp_clks>; @@ -109,7 +109,7 @@ clocks = <&mcbsp1_gate_fck>, <&mcbsp1_mux_fck>; }; - mcbsp2_mux_fck: mcbsp2_mux_fck { + mcbsp2_mux_fck: mcbsp2_mux_fck@4 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&per_96m_fck>, <&mcbsp_clks>; @@ -123,7 +123,7 @@ clocks = <&mcbsp2_gate_fck>, <&mcbsp2_mux_fck>; }; - mcbsp3_mux_fck: mcbsp3_mux_fck { + mcbsp3_mux_fck: mcbsp3_mux_fck@68 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&per_96m_fck>, <&mcbsp_clks>; @@ -136,7 +136,7 @@ clocks = <&mcbsp3_gate_fck>, <&mcbsp3_mux_fck>; }; - mcbsp4_mux_fck: mcbsp4_mux_fck { + mcbsp4_mux_fck: mcbsp4_mux_fck@68 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&per_96m_fck>, <&mcbsp_clks>; @@ -193,14 +193,14 @@ clock-frequency = <38400000>; }; - dpll4_ck: dpll4_ck { + dpll4_ck: dpll4_ck@d00 { #clock-cells = <0>; compatible = "ti,omap3-dpll-per-clock"; clocks = <&sys_ck>, <&sys_ck>; reg = <0x0d00>, <0x0d20>, <0x0d44>, <0x0d30>; }; - dpll4_m2_ck: dpll4_m2_ck { + dpll4_m2_ck: dpll4_m2_ck@d48 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll4_ck>; @@ -217,7 +217,7 @@ clock-div = <1>; }; - dpll4_m2x2_ck: dpll4_m2x2_ck { + dpll4_m2x2_ck: dpll4_m2x2_ck@d00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll4_m2x2_mul_ck>; @@ -234,14 +234,14 @@ clock-div = <1>; }; - dpll3_ck: dpll3_ck { + dpll3_ck: dpll3_ck@d00 { #clock-cells = <0>; compatible = "ti,omap3-dpll-core-clock"; clocks = <&sys_ck>, <&sys_ck>; reg = <0x0d00>, <0x0d20>, <0x0d40>, <0x0d30>; }; - dpll3_m3_ck: dpll3_m3_ck { + dpll3_m3_ck: dpll3_m3_ck@1140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll3_ck>; @@ -259,7 +259,7 @@ clock-div = <1>; }; - dpll3_m3x2_ck: dpll3_m3x2_ck { + dpll3_m3x2_ck: dpll3_m3x2_ck@d00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll3_m3x2_mul_ck>; @@ -288,7 +288,7 @@ clock-frequency = <0x0>; }; - dpll3_m2_ck: dpll3_m2_ck { + dpll3_m2_ck: dpll3_m2_ck@d40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll3_ck>; @@ -306,7 +306,7 @@ clock-div = <1>; }; - dpll1_fck: dpll1_fck { + dpll1_fck: dpll1_fck@940 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&core_ck>; @@ -316,7 +316,7 @@ ti,index-starts-at-one; }; - dpll1_ck: dpll1_ck { + dpll1_ck: dpll1_ck@904 { #clock-cells = <0>; compatible = "ti,omap3-dpll-clock"; clocks = <&sys_ck>, <&dpll1_fck>; @@ -331,7 +331,7 @@ clock-div = <1>; }; - dpll1_x2m2_ck: dpll1_x2m2_ck { + dpll1_x2m2_ck: dpll1_x2m2_ck@944 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll1_x2_ck>; @@ -348,7 +348,7 @@ clock-div = <1>; }; - omap_96m_fck: omap_96m_fck { + omap_96m_fck: omap_96m_fck@d40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&cm_96m_fck>, <&sys_ck>; @@ -356,7 +356,7 @@ reg = <0x0d40>; }; - dpll4_m3_ck: dpll4_m3_ck { + dpll4_m3_ck: dpll4_m3_ck@e40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll4_ck>; @@ -374,7 +374,7 @@ clock-div = <1>; }; - dpll4_m3x2_ck: dpll4_m3x2_ck { + dpll4_m3x2_ck: dpll4_m3x2_ck@d00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll4_m3x2_mul_ck>; @@ -383,7 +383,7 @@ ti,set-bit-to-disable; }; - omap_54m_fck: omap_54m_fck { + omap_54m_fck: omap_54m_fck@d40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll4_m3x2_ck>, <&sys_altclk>; @@ -399,7 +399,7 @@ clock-div = <2>; }; - omap_48m_fck: omap_48m_fck { + omap_48m_fck: omap_48m_fck@d40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&cm_96m_d2_fck>, <&sys_altclk>; @@ -415,7 +415,7 @@ clock-div = <4>; }; - dpll4_m4_ck: dpll4_m4_ck { + dpll4_m4_ck: dpll4_m4_ck@e40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll4_ck>; @@ -433,7 +433,7 @@ ti,set-rate-parent; }; - dpll4_m4x2_ck: dpll4_m4x2_ck { + dpll4_m4x2_ck: dpll4_m4x2_ck@d00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll4_m4x2_mul_ck>; @@ -443,7 +443,7 @@ ti,set-rate-parent; }; - dpll4_m5_ck: dpll4_m5_ck { + dpll4_m5_ck: dpll4_m5_ck@f40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll4_ck>; @@ -461,7 +461,7 @@ ti,set-rate-parent; }; - dpll4_m5x2_ck: dpll4_m5x2_ck { + dpll4_m5x2_ck: dpll4_m5x2_ck@d00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll4_m5x2_mul_ck>; @@ -471,7 +471,7 @@ ti,set-rate-parent; }; - dpll4_m6_ck: dpll4_m6_ck { + dpll4_m6_ck: dpll4_m6_ck@1140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll4_ck>; @@ -489,7 +489,7 @@ clock-div = <1>; }; - dpll4_m6x2_ck: dpll4_m6x2_ck { + dpll4_m6x2_ck: dpll4_m6x2_ck@d00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll4_m6x2_mul_ck>; @@ -506,7 +506,7 @@ clock-div = <1>; }; - clkout2_src_gate_ck: clkout2_src_gate_ck { + clkout2_src_gate_ck: clkout2_src_gate_ck@d70 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&core_ck>; @@ -514,7 +514,7 @@ reg = <0x0d70>; }; - clkout2_src_mux_ck: clkout2_src_mux_ck { + clkout2_src_mux_ck: clkout2_src_mux_ck@d70 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&core_ck>, <&sys_ck>, <&cm_96m_fck>, <&omap_54m_fck>; @@ -527,7 +527,7 @@ clocks = <&clkout2_src_gate_ck>, <&clkout2_src_mux_ck>; }; - sys_clkout2: sys_clkout2 { + sys_clkout2: sys_clkout2@d70 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&clkout2_src_ck>; @@ -545,7 +545,7 @@ clock-div = <1>; }; - arm_fck: arm_fck { + arm_fck: arm_fck@924 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mpu_ck>; @@ -561,7 +561,7 @@ clock-div = <1>; }; - l3_ick: l3_ick { + l3_ick: l3_ick@a40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&core_ck>; @@ -570,7 +570,7 @@ ti,index-starts-at-one; }; - l4_ick: l4_ick { + l4_ick: l4_ick@a40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&l3_ick>; @@ -580,7 +580,7 @@ ti,index-starts-at-one; }; - rm_ick: rm_ick { + rm_ick: rm_ick@c40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&l4_ick>; @@ -590,7 +590,7 @@ ti,index-starts-at-one; }; - gpt10_gate_fck: gpt10_gate_fck { + gpt10_gate_fck: gpt10_gate_fck@a00 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -598,7 +598,7 @@ reg = <0x0a00>; }; - gpt10_mux_fck: gpt10_mux_fck { + gpt10_mux_fck: gpt10_mux_fck@a40 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -612,7 +612,7 @@ clocks = <&gpt10_gate_fck>, <&gpt10_mux_fck>; }; - gpt11_gate_fck: gpt11_gate_fck { + gpt11_gate_fck: gpt11_gate_fck@a00 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -620,7 +620,7 @@ reg = <0x0a00>; }; - gpt11_mux_fck: gpt11_mux_fck { + gpt11_mux_fck: gpt11_mux_fck@a40 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -642,7 +642,7 @@ clock-div = <1>; }; - mmchs2_fck: mmchs2_fck { + mmchs2_fck: mmchs2_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_96m_fck>; @@ -650,7 +650,7 @@ ti,bit-shift = <25>; }; - mmchs1_fck: mmchs1_fck { + mmchs1_fck: mmchs1_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_96m_fck>; @@ -658,7 +658,7 @@ ti,bit-shift = <24>; }; - i2c3_fck: i2c3_fck { + i2c3_fck: i2c3_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_96m_fck>; @@ -666,7 +666,7 @@ ti,bit-shift = <17>; }; - i2c2_fck: i2c2_fck { + i2c2_fck: i2c2_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_96m_fck>; @@ -674,7 +674,7 @@ ti,bit-shift = <16>; }; - i2c1_fck: i2c1_fck { + i2c1_fck: i2c1_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_96m_fck>; @@ -682,7 +682,7 @@ ti,bit-shift = <15>; }; - mcbsp5_gate_fck: mcbsp5_gate_fck { + mcbsp5_gate_fck: mcbsp5_gate_fck@a00 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -690,7 +690,7 @@ reg = <0x0a00>; }; - mcbsp1_gate_fck: mcbsp1_gate_fck { + mcbsp1_gate_fck: mcbsp1_gate_fck@a00 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -706,7 +706,7 @@ clock-div = <1>; }; - mcspi4_fck: mcspi4_fck { + mcspi4_fck: mcspi4_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; @@ -714,7 +714,7 @@ ti,bit-shift = <21>; }; - mcspi3_fck: mcspi3_fck { + mcspi3_fck: mcspi3_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; @@ -722,7 +722,7 @@ ti,bit-shift = <20>; }; - mcspi2_fck: mcspi2_fck { + mcspi2_fck: mcspi2_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; @@ -730,7 +730,7 @@ ti,bit-shift = <19>; }; - mcspi1_fck: mcspi1_fck { + mcspi1_fck: mcspi1_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; @@ -738,7 +738,7 @@ ti,bit-shift = <18>; }; - uart2_fck: uart2_fck { + uart2_fck: uart2_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; @@ -746,7 +746,7 @@ ti,bit-shift = <14>; }; - uart1_fck: uart1_fck { + uart1_fck: uart1_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_48m_fck>; @@ -762,7 +762,7 @@ clock-div = <1>; }; - hdq_fck: hdq_fck { + hdq_fck: hdq_fck@a00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_12m_fck>; @@ -778,7 +778,7 @@ clock-div = <1>; }; - sdrc_ick: sdrc_ick { + sdrc_ick: sdrc_ick@a10 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_l3_ick>; @@ -802,7 +802,7 @@ clock-div = <1>; }; - mmchs2_ick: mmchs2_ick { + mmchs2_ick: mmchs2_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -810,7 +810,7 @@ ti,bit-shift = <25>; }; - mmchs1_ick: mmchs1_ick { + mmchs1_ick: mmchs1_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -818,7 +818,7 @@ ti,bit-shift = <24>; }; - hdq_ick: hdq_ick { + hdq_ick: hdq_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -826,7 +826,7 @@ ti,bit-shift = <22>; }; - mcspi4_ick: mcspi4_ick { + mcspi4_ick: mcspi4_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -834,7 +834,7 @@ ti,bit-shift = <21>; }; - mcspi3_ick: mcspi3_ick { + mcspi3_ick: mcspi3_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -842,7 +842,7 @@ ti,bit-shift = <20>; }; - mcspi2_ick: mcspi2_ick { + mcspi2_ick: mcspi2_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -850,7 +850,7 @@ ti,bit-shift = <19>; }; - mcspi1_ick: mcspi1_ick { + mcspi1_ick: mcspi1_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -858,7 +858,7 @@ ti,bit-shift = <18>; }; - i2c3_ick: i2c3_ick { + i2c3_ick: i2c3_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -866,7 +866,7 @@ ti,bit-shift = <17>; }; - i2c2_ick: i2c2_ick { + i2c2_ick: i2c2_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -874,7 +874,7 @@ ti,bit-shift = <16>; }; - i2c1_ick: i2c1_ick { + i2c1_ick: i2c1_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -882,7 +882,7 @@ ti,bit-shift = <15>; }; - uart2_ick: uart2_ick { + uart2_ick: uart2_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -890,7 +890,7 @@ ti,bit-shift = <14>; }; - uart1_ick: uart1_ick { + uart1_ick: uart1_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -898,7 +898,7 @@ ti,bit-shift = <13>; }; - gpt11_ick: gpt11_ick { + gpt11_ick: gpt11_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -906,7 +906,7 @@ ti,bit-shift = <12>; }; - gpt10_ick: gpt10_ick { + gpt10_ick: gpt10_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -914,7 +914,7 @@ ti,bit-shift = <11>; }; - mcbsp5_ick: mcbsp5_ick { + mcbsp5_ick: mcbsp5_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -922,7 +922,7 @@ ti,bit-shift = <10>; }; - mcbsp1_ick: mcbsp1_ick { + mcbsp1_ick: mcbsp1_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -930,7 +930,7 @@ ti,bit-shift = <9>; }; - omapctrl_ick: omapctrl_ick { + omapctrl_ick: omapctrl_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -938,7 +938,7 @@ ti,bit-shift = <6>; }; - dss_tv_fck: dss_tv_fck { + dss_tv_fck: dss_tv_fck@e00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&omap_54m_fck>; @@ -946,7 +946,7 @@ ti,bit-shift = <2>; }; - dss_96m_fck: dss_96m_fck { + dss_96m_fck: dss_96m_fck@e00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&omap_96m_fck>; @@ -954,7 +954,7 @@ ti,bit-shift = <2>; }; - dss2_alwon_fck: dss2_alwon_fck { + dss2_alwon_fck: dss2_alwon_fck@e00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_ck>; @@ -968,7 +968,7 @@ clock-frequency = <0>; }; - gpt1_gate_fck: gpt1_gate_fck { + gpt1_gate_fck: gpt1_gate_fck@c00 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -976,7 +976,7 @@ reg = <0x0c00>; }; - gpt1_mux_fck: gpt1_mux_fck { + gpt1_mux_fck: gpt1_mux_fck@c40 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -989,7 +989,7 @@ clocks = <&gpt1_gate_fck>, <&gpt1_mux_fck>; }; - aes2_ick: aes2_ick { + aes2_ick: aes2_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -1005,7 +1005,7 @@ clock-div = <1>; }; - gpio1_dbck: gpio1_dbck { + gpio1_dbck: gpio1_dbck@c00 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&wkup_32k_fck>; @@ -1013,7 +1013,7 @@ ti,bit-shift = <3>; }; - sha12_ick: sha12_ick { + sha12_ick: sha12_ick@a10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l4_ick>; @@ -1021,7 +1021,7 @@ ti,bit-shift = <27>; }; - wdt2_fck: wdt2_fck { + wdt2_fck: wdt2_fck@c00 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&wkup_32k_fck>; @@ -1029,7 +1029,7 @@ ti,bit-shift = <5>; }; - wdt2_ick: wdt2_ick { + wdt2_ick: wdt2_ick@c10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&wkup_l4_ick>; @@ -1037,7 +1037,7 @@ ti,bit-shift = <5>; }; - wdt1_ick: wdt1_ick { + wdt1_ick: wdt1_ick@c10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&wkup_l4_ick>; @@ -1045,7 +1045,7 @@ ti,bit-shift = <4>; }; - gpio1_ick: gpio1_ick { + gpio1_ick: gpio1_ick@c10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&wkup_l4_ick>; @@ -1053,7 +1053,7 @@ ti,bit-shift = <3>; }; - omap_32ksync_ick: omap_32ksync_ick { + omap_32ksync_ick: omap_32ksync_ick@c10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&wkup_l4_ick>; @@ -1061,7 +1061,7 @@ ti,bit-shift = <2>; }; - gpt12_ick: gpt12_ick { + gpt12_ick: gpt12_ick@c10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&wkup_l4_ick>; @@ -1069,7 +1069,7 @@ ti,bit-shift = <1>; }; - gpt1_ick: gpt1_ick { + gpt1_ick: gpt1_ick@c10 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&wkup_l4_ick>; @@ -1093,7 +1093,7 @@ clock-div = <1>; }; - uart3_fck: uart3_fck { + uart3_fck: uart3_fck@1000 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&per_48m_fck>; @@ -1101,7 +1101,7 @@ ti,bit-shift = <11>; }; - gpt2_gate_fck: gpt2_gate_fck { + gpt2_gate_fck: gpt2_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1109,7 +1109,7 @@ reg = <0x1000>; }; - gpt2_mux_fck: gpt2_mux_fck { + gpt2_mux_fck: gpt2_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1122,7 +1122,7 @@ clocks = <&gpt2_gate_fck>, <&gpt2_mux_fck>; }; - gpt3_gate_fck: gpt3_gate_fck { + gpt3_gate_fck: gpt3_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1130,7 +1130,7 @@ reg = <0x1000>; }; - gpt3_mux_fck: gpt3_mux_fck { + gpt3_mux_fck: gpt3_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1144,7 +1144,7 @@ clocks = <&gpt3_gate_fck>, <&gpt3_mux_fck>; }; - gpt4_gate_fck: gpt4_gate_fck { + gpt4_gate_fck: gpt4_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1152,7 +1152,7 @@ reg = <0x1000>; }; - gpt4_mux_fck: gpt4_mux_fck { + gpt4_mux_fck: gpt4_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1166,7 +1166,7 @@ clocks = <&gpt4_gate_fck>, <&gpt4_mux_fck>; }; - gpt5_gate_fck: gpt5_gate_fck { + gpt5_gate_fck: gpt5_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1174,7 +1174,7 @@ reg = <0x1000>; }; - gpt5_mux_fck: gpt5_mux_fck { + gpt5_mux_fck: gpt5_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1188,7 +1188,7 @@ clocks = <&gpt5_gate_fck>, <&gpt5_mux_fck>; }; - gpt6_gate_fck: gpt6_gate_fck { + gpt6_gate_fck: gpt6_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1196,7 +1196,7 @@ reg = <0x1000>; }; - gpt6_mux_fck: gpt6_mux_fck { + gpt6_mux_fck: gpt6_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1210,7 +1210,7 @@ clocks = <&gpt6_gate_fck>, <&gpt6_mux_fck>; }; - gpt7_gate_fck: gpt7_gate_fck { + gpt7_gate_fck: gpt7_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1218,7 +1218,7 @@ reg = <0x1000>; }; - gpt7_mux_fck: gpt7_mux_fck { + gpt7_mux_fck: gpt7_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1232,7 +1232,7 @@ clocks = <&gpt7_gate_fck>, <&gpt7_mux_fck>; }; - gpt8_gate_fck: gpt8_gate_fck { + gpt8_gate_fck: gpt8_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1240,7 +1240,7 @@ reg = <0x1000>; }; - gpt8_mux_fck: gpt8_mux_fck { + gpt8_mux_fck: gpt8_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1254,7 +1254,7 @@ clocks = <&gpt8_gate_fck>, <&gpt8_mux_fck>; }; - gpt9_gate_fck: gpt9_gate_fck { + gpt9_gate_fck: gpt9_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&sys_ck>; @@ -1262,7 +1262,7 @@ reg = <0x1000>; }; - gpt9_mux_fck: gpt9_mux_fck { + gpt9_mux_fck: gpt9_mux_fck@1040 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&omap_32k_fck>, <&sys_ck>; @@ -1284,7 +1284,7 @@ clock-div = <1>; }; - gpio6_dbck: gpio6_dbck { + gpio6_dbck: gpio6_dbck@1000 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&per_32k_alwon_fck>; @@ -1292,7 +1292,7 @@ ti,bit-shift = <17>; }; - gpio5_dbck: gpio5_dbck { + gpio5_dbck: gpio5_dbck@1000 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&per_32k_alwon_fck>; @@ -1300,7 +1300,7 @@ ti,bit-shift = <16>; }; - gpio4_dbck: gpio4_dbck { + gpio4_dbck: gpio4_dbck@1000 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&per_32k_alwon_fck>; @@ -1308,7 +1308,7 @@ ti,bit-shift = <15>; }; - gpio3_dbck: gpio3_dbck { + gpio3_dbck: gpio3_dbck@1000 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&per_32k_alwon_fck>; @@ -1316,7 +1316,7 @@ ti,bit-shift = <14>; }; - gpio2_dbck: gpio2_dbck { + gpio2_dbck: gpio2_dbck@1000 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&per_32k_alwon_fck>; @@ -1324,7 +1324,7 @@ ti,bit-shift = <13>; }; - wdt3_fck: wdt3_fck { + wdt3_fck: wdt3_fck@1000 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&per_32k_alwon_fck>; @@ -1340,7 +1340,7 @@ clock-div = <1>; }; - gpio6_ick: gpio6_ick { + gpio6_ick: gpio6_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1348,7 +1348,7 @@ ti,bit-shift = <17>; }; - gpio5_ick: gpio5_ick { + gpio5_ick: gpio5_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1356,7 +1356,7 @@ ti,bit-shift = <16>; }; - gpio4_ick: gpio4_ick { + gpio4_ick: gpio4_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1364,7 +1364,7 @@ ti,bit-shift = <15>; }; - gpio3_ick: gpio3_ick { + gpio3_ick: gpio3_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1372,7 +1372,7 @@ ti,bit-shift = <14>; }; - gpio2_ick: gpio2_ick { + gpio2_ick: gpio2_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1380,7 +1380,7 @@ ti,bit-shift = <13>; }; - wdt3_ick: wdt3_ick { + wdt3_ick: wdt3_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1388,7 +1388,7 @@ ti,bit-shift = <12>; }; - uart3_ick: uart3_ick { + uart3_ick: uart3_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1396,7 +1396,7 @@ ti,bit-shift = <11>; }; - uart4_ick: uart4_ick { + uart4_ick: uart4_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1404,7 +1404,7 @@ ti,bit-shift = <18>; }; - gpt9_ick: gpt9_ick { + gpt9_ick: gpt9_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1412,7 +1412,7 @@ ti,bit-shift = <10>; }; - gpt8_ick: gpt8_ick { + gpt8_ick: gpt8_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1420,7 +1420,7 @@ ti,bit-shift = <9>; }; - gpt7_ick: gpt7_ick { + gpt7_ick: gpt7_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1428,7 +1428,7 @@ ti,bit-shift = <8>; }; - gpt6_ick: gpt6_ick { + gpt6_ick: gpt6_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1436,7 +1436,7 @@ ti,bit-shift = <7>; }; - gpt5_ick: gpt5_ick { + gpt5_ick: gpt5_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1444,7 +1444,7 @@ ti,bit-shift = <6>; }; - gpt4_ick: gpt4_ick { + gpt4_ick: gpt4_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1452,7 +1452,7 @@ ti,bit-shift = <5>; }; - gpt3_ick: gpt3_ick { + gpt3_ick: gpt3_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1460,7 +1460,7 @@ ti,bit-shift = <4>; }; - gpt2_ick: gpt2_ick { + gpt2_ick: gpt2_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1468,7 +1468,7 @@ ti,bit-shift = <3>; }; - mcbsp2_ick: mcbsp2_ick { + mcbsp2_ick: mcbsp2_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1476,7 +1476,7 @@ ti,bit-shift = <0>; }; - mcbsp3_ick: mcbsp3_ick { + mcbsp3_ick: mcbsp3_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1484,7 +1484,7 @@ ti,bit-shift = <1>; }; - mcbsp4_ick: mcbsp4_ick { + mcbsp4_ick: mcbsp4_ick@1010 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&per_l4_ick>; @@ -1492,7 +1492,7 @@ ti,bit-shift = <2>; }; - mcbsp2_gate_fck: mcbsp2_gate_fck { + mcbsp2_gate_fck: mcbsp2_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -1500,7 +1500,7 @@ reg = <0x1000>; }; - mcbsp3_gate_fck: mcbsp3_gate_fck { + mcbsp3_gate_fck: mcbsp3_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -1508,7 +1508,7 @@ reg = <0x1000>; }; - mcbsp4_gate_fck: mcbsp4_gate_fck { + mcbsp4_gate_fck: mcbsp4_gate_fck@1000 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -1516,7 +1516,7 @@ reg = <0x1000>; }; - emu_src_mux_ck: emu_src_mux_ck { + emu_src_mux_ck: emu_src_mux_ck@1140 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>; @@ -1529,7 +1529,7 @@ clocks = <&emu_src_mux_ck>; }; - pclk_fck: pclk_fck { + pclk_fck: pclk_fck@1140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&emu_src_ck>; @@ -1539,7 +1539,7 @@ ti,index-starts-at-one; }; - pclkx2_fck: pclkx2_fck { + pclkx2_fck: pclkx2_fck@1140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&emu_src_ck>; @@ -1549,7 +1549,7 @@ ti,index-starts-at-one; }; - atclk_fck: atclk_fck { + atclk_fck: atclk_fck@1140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&emu_src_ck>; @@ -1559,7 +1559,7 @@ ti,index-starts-at-one; }; - traceclk_src_fck: traceclk_src_fck { + traceclk_src_fck: traceclk_src_fck@1140 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>; @@ -1567,7 +1567,7 @@ reg = <0x1140>; }; - traceclk_fck: traceclk_fck { + traceclk_fck: traceclk_fck@1140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&traceclk_src_fck>; -- GitLab From 1bb5fcb1e2456dc9ae9ffbf82142b3052675b0e9 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:07 +0300 Subject: [PATCH 2004/9938] ARM: dts: omap2: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for OMAP2 clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap2420-clocks.dtsi | 38 ++--- arch/arm/boot/dts/omap2430-clocks.dtsi | 58 +++---- arch/arm/boot/dts/omap24xx-clocks.dtsi | 228 ++++++++++++------------- 3 files changed, 162 insertions(+), 162 deletions(-) diff --git a/arch/arm/boot/dts/omap2420-clocks.dtsi b/arch/arm/boot/dts/omap2420-clocks.dtsi index ce8c742d7e92..f8e5bd3cc628 100644 --- a/arch/arm/boot/dts/omap2420-clocks.dtsi +++ b/arch/arm/boot/dts/omap2420-clocks.dtsi @@ -9,7 +9,7 @@ */ &prcm_clocks { - sys_clkout2_src_gate: sys_clkout2_src_gate { + sys_clkout2_src_gate: sys_clkout2_src_gate@70 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&core_ck>; @@ -17,7 +17,7 @@ reg = <0x0070>; }; - sys_clkout2_src_mux: sys_clkout2_src_mux { + sys_clkout2_src_mux: sys_clkout2_src_mux@70 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&core_ck>, <&sys_ck>, <&func_96m_ck>, <&func_54m_ck>; @@ -31,7 +31,7 @@ clocks = <&sys_clkout2_src_gate>, <&sys_clkout2_src_mux>; }; - sys_clkout2: sys_clkout2 { + sys_clkout2: sys_clkout2@70 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkout2_src>; @@ -41,7 +41,7 @@ ti,index-power-of-two; }; - dsp_gate_ick: dsp_gate_ick { + dsp_gate_ick: dsp_gate_ick@810 { #clock-cells = <0>; compatible = "ti,composite-interface-clock"; clocks = <&dsp_fck>; @@ -49,7 +49,7 @@ reg = <0x0810>; }; - dsp_div_ick: dsp_div_ick { + dsp_div_ick: dsp_div_ick@840 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&dsp_fck>; @@ -65,7 +65,7 @@ clocks = <&dsp_gate_ick>, <&dsp_div_ick>; }; - iva1_gate_ifck: iva1_gate_ifck { + iva1_gate_ifck: iva1_gate_ifck@800 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&core_ck>; @@ -73,7 +73,7 @@ reg = <0x0800>; }; - iva1_div_ifck: iva1_div_ifck { + iva1_div_ifck: iva1_div_ifck@840 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&core_ck>; @@ -96,7 +96,7 @@ clock-div = <2>; }; - iva1_mpu_int_ifck: iva1_mpu_int_ifck { + iva1_mpu_int_ifck: iva1_mpu_int_ifck@800 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&iva1_ifck_div>; @@ -104,7 +104,7 @@ reg = <0x0800>; }; - wdt3_ick: wdt3_ick { + wdt3_ick: wdt3_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -112,7 +112,7 @@ reg = <0x0210>; }; - wdt3_fck: wdt3_fck { + wdt3_fck: wdt3_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_32k_ck>; @@ -120,7 +120,7 @@ reg = <0x0200>; }; - mmc_ick: mmc_ick { + mmc_ick: mmc_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -128,7 +128,7 @@ reg = <0x0210>; }; - mmc_fck: mmc_fck { + mmc_fck: mmc_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_96m_ck>; @@ -136,7 +136,7 @@ reg = <0x0200>; }; - eac_ick: eac_ick { + eac_ick: eac_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -144,7 +144,7 @@ reg = <0x0210>; }; - eac_fck: eac_fck { + eac_fck: eac_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_96m_ck>; @@ -152,7 +152,7 @@ reg = <0x0200>; }; - i2c1_fck: i2c1_fck { + i2c1_fck: i2c1_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_12m_ck>; @@ -160,7 +160,7 @@ reg = <0x0200>; }; - i2c2_fck: i2c2_fck { + i2c2_fck: i2c2_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_12m_ck>; @@ -168,7 +168,7 @@ reg = <0x0200>; }; - vlynq_ick: vlynq_ick { + vlynq_ick: vlynq_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l3_ck>; @@ -176,7 +176,7 @@ reg = <0x0210>; }; - vlynq_gate_fck: vlynq_gate_fck { + vlynq_gate_fck: vlynq_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&core_ck>; @@ -192,7 +192,7 @@ clock-div = <18>; }; - vlynq_mux_fck: vlynq_mux_fck { + vlynq_mux_fck: vlynq_mux_fck@240 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_96m_ck>, <&core_ck>, <&core_d2_ck>, <&core_d3_ck>, <&core_d4_ck>, <&dummy_ck>, <&core_d6_ck>, <&dummy_ck>, <&core_d8_ck>, <&core_d9_ck>, <&dummy_ck>, <&dummy_ck>, <&core_d12_ck>, <&dummy_ck>, <&dummy_ck>, <&dummy_ck>, <&core_d16_ck>, <&dummy_ck>, <&core_d18_ck>; diff --git a/arch/arm/boot/dts/omap2430-clocks.dtsi b/arch/arm/boot/dts/omap2430-clocks.dtsi index 93fed68839b9..a5aa7d619849 100644 --- a/arch/arm/boot/dts/omap2430-clocks.dtsi +++ b/arch/arm/boot/dts/omap2430-clocks.dtsi @@ -9,7 +9,7 @@ */ &scm_clocks { - mcbsp3_mux_fck: mcbsp3_mux_fck { + mcbsp3_mux_fck: mcbsp3_mux_fck@78 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_96m_ck>, <&mcbsp_clks>; @@ -22,7 +22,7 @@ clocks = <&mcbsp3_gate_fck>, <&mcbsp3_mux_fck>; }; - mcbsp4_mux_fck: mcbsp4_mux_fck { + mcbsp4_mux_fck: mcbsp4_mux_fck@78 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_96m_ck>, <&mcbsp_clks>; @@ -36,7 +36,7 @@ clocks = <&mcbsp4_gate_fck>, <&mcbsp4_mux_fck>; }; - mcbsp5_mux_fck: mcbsp5_mux_fck { + mcbsp5_mux_fck: mcbsp5_mux_fck@78 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_96m_ck>, <&mcbsp_clks>; @@ -52,7 +52,7 @@ }; &prcm_clocks { - iva2_1_gate_ick: iva2_1_gate_ick { + iva2_1_gate_ick: iva2_1_gate_ick@800 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&dsp_fck>; @@ -60,7 +60,7 @@ reg = <0x0800>; }; - iva2_1_div_ick: iva2_1_div_ick { + iva2_1_div_ick: iva2_1_div_ick@840 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&dsp_fck>; @@ -76,7 +76,7 @@ clocks = <&iva2_1_gate_ick>, <&iva2_1_div_ick>; }; - mdm_gate_ick: mdm_gate_ick { + mdm_gate_ick: mdm_gate_ick@c10 { #clock-cells = <0>; compatible = "ti,composite-interface-clock"; clocks = <&core_ck>; @@ -84,7 +84,7 @@ reg = <0x0c10>; }; - mdm_div_ick: mdm_div_ick { + mdm_div_ick: mdm_div_ick@c40 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&core_ck>; @@ -98,7 +98,7 @@ clocks = <&mdm_gate_ick>, <&mdm_div_ick>; }; - mdm_osc_ck: mdm_osc_ck { + mdm_osc_ck: mdm_osc_ck@c00 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&osc_ck>; @@ -106,7 +106,7 @@ reg = <0x0c00>; }; - mcbsp3_ick: mcbsp3_ick { + mcbsp3_ick: mcbsp3_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -114,7 +114,7 @@ reg = <0x0214>; }; - mcbsp3_gate_fck: mcbsp3_gate_fck { + mcbsp3_gate_fck: mcbsp3_gate_fck@204 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -122,7 +122,7 @@ reg = <0x0204>; }; - mcbsp4_ick: mcbsp4_ick { + mcbsp4_ick: mcbsp4_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -130,7 +130,7 @@ reg = <0x0214>; }; - mcbsp4_gate_fck: mcbsp4_gate_fck { + mcbsp4_gate_fck: mcbsp4_gate_fck@204 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -138,7 +138,7 @@ reg = <0x0204>; }; - mcbsp5_ick: mcbsp5_ick { + mcbsp5_ick: mcbsp5_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -146,7 +146,7 @@ reg = <0x0214>; }; - mcbsp5_gate_fck: mcbsp5_gate_fck { + mcbsp5_gate_fck: mcbsp5_gate_fck@204 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -154,7 +154,7 @@ reg = <0x0204>; }; - mcspi3_ick: mcspi3_ick { + mcspi3_ick: mcspi3_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -162,7 +162,7 @@ reg = <0x0214>; }; - mcspi3_fck: mcspi3_fck { + mcspi3_fck: mcspi3_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_48m_ck>; @@ -170,7 +170,7 @@ reg = <0x0204>; }; - icr_ick: icr_ick { + icr_ick: icr_ick@410 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -178,7 +178,7 @@ reg = <0x0410>; }; - i2chs1_fck: i2chs1_fck { + i2chs1_fck: i2chs1_fck@204 { #clock-cells = <0>; compatible = "ti,omap2430-interface-clock"; clocks = <&func_96m_ck>; @@ -186,7 +186,7 @@ reg = <0x0204>; }; - i2chs2_fck: i2chs2_fck { + i2chs2_fck: i2chs2_fck@204 { #clock-cells = <0>; compatible = "ti,omap2430-interface-clock"; clocks = <&func_96m_ck>; @@ -194,7 +194,7 @@ reg = <0x0204>; }; - usbhs_ick: usbhs_ick { + usbhs_ick: usbhs_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&core_l3_ck>; @@ -202,7 +202,7 @@ reg = <0x0214>; }; - mmchs1_ick: mmchs1_ick { + mmchs1_ick: mmchs1_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -210,7 +210,7 @@ reg = <0x0214>; }; - mmchs1_fck: mmchs1_fck { + mmchs1_fck: mmchs1_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_96m_ck>; @@ -218,7 +218,7 @@ reg = <0x0204>; }; - mmchs2_ick: mmchs2_ick { + mmchs2_ick: mmchs2_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -226,7 +226,7 @@ reg = <0x0214>; }; - mmchs2_fck: mmchs2_fck { + mmchs2_fck: mmchs2_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_96m_ck>; @@ -234,7 +234,7 @@ reg = <0x0204>; }; - gpio5_ick: gpio5_ick { + gpio5_ick: gpio5_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -242,7 +242,7 @@ reg = <0x0214>; }; - gpio5_fck: gpio5_fck { + gpio5_fck: gpio5_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_32k_ck>; @@ -250,7 +250,7 @@ reg = <0x0204>; }; - mdm_intc_ick: mdm_intc_ick { + mdm_intc_ick: mdm_intc_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -258,7 +258,7 @@ reg = <0x0214>; }; - mmchsdb1_fck: mmchsdb1_fck { + mmchsdb1_fck: mmchsdb1_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_32k_ck>; @@ -266,7 +266,7 @@ reg = <0x0204>; }; - mmchsdb2_fck: mmchsdb2_fck { + mmchsdb2_fck: mmchsdb2_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_32k_ck>; diff --git a/arch/arm/boot/dts/omap24xx-clocks.dtsi b/arch/arm/boot/dts/omap24xx-clocks.dtsi index 63965b876973..ca73722b5ea4 100644 --- a/arch/arm/boot/dts/omap24xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap24xx-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &scm_clocks { - mcbsp1_mux_fck: mcbsp1_mux_fck { + mcbsp1_mux_fck: mcbsp1_mux_fck@4 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_96m_ck>, <&mcbsp_clks>; @@ -22,7 +22,7 @@ clocks = <&mcbsp1_gate_fck>, <&mcbsp1_mux_fck>; }; - mcbsp2_mux_fck: mcbsp2_mux_fck { + mcbsp2_mux_fck: mcbsp2_mux_fck@4 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_96m_ck>, <&mcbsp_clks>; @@ -74,7 +74,7 @@ clock-frequency = <26000000>; }; - aplls_clkin_ck: aplls_clkin_ck { + aplls_clkin_ck: aplls_clkin_ck@540 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_19200000_ck>, <&virt_26m_ck>, <&virt_13m_ck>, <&virt_12m_ck>; @@ -90,7 +90,7 @@ clock-div = <1>; }; - osc_ck: osc_ck { + osc_ck: osc_ck@60 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&aplls_clkin_ck>, <&aplls_clkin_x2_ck>; @@ -99,7 +99,7 @@ ti,index-starts-at-one; }; - sys_ck: sys_ck { + sys_ck: sys_ck@60 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&osc_ck>; @@ -121,14 +121,14 @@ clock-frequency = <0x0>; }; - dpll_ck: dpll_ck { + dpll_ck: dpll_ck@500 { #clock-cells = <0>; compatible = "ti,omap2-dpll-core-clock"; clocks = <&sys_ck>, <&sys_ck>; reg = <0x0500>, <0x0540>; }; - apll96_ck: apll96_ck { + apll96_ck: apll96_ck@500 { #clock-cells = <0>; compatible = "ti,omap2-apll-clock"; clocks = <&sys_ck>; @@ -138,7 +138,7 @@ reg = <0x0500>, <0x0530>, <0x0520>; }; - apll54_ck: apll54_ck { + apll54_ck: apll54_ck@500 { #clock-cells = <0>; compatible = "ti,omap2-apll-clock"; clocks = <&sys_ck>; @@ -148,7 +148,7 @@ reg = <0x0500>, <0x0530>, <0x0520>; }; - func_54m_ck: func_54m_ck { + func_54m_ck: func_54m_ck@540 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&apll54_ck>, <&alt_ck>; @@ -176,7 +176,7 @@ clock-div = <2>; }; - func_48m_ck: func_48m_ck { + func_48m_ck: func_48m_ck@540 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&apll96_d2_ck>, <&alt_ck>; @@ -192,7 +192,7 @@ clock-div = <4>; }; - sys_clkout_src_gate: sys_clkout_src_gate { + sys_clkout_src_gate: sys_clkout_src_gate@70 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&core_ck>; @@ -200,7 +200,7 @@ reg = <0x0070>; }; - sys_clkout_src_mux: sys_clkout_src_mux { + sys_clkout_src_mux: sys_clkout_src_mux@70 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&core_ck>, <&sys_ck>, <&func_96m_ck>, <&func_54m_ck>; @@ -213,7 +213,7 @@ clocks = <&sys_clkout_src_gate>, <&sys_clkout_src_mux>; }; - sys_clkout: sys_clkout { + sys_clkout: sys_clkout@70 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkout_src>; @@ -223,7 +223,7 @@ ti,index-power-of-two; }; - emul_ck: emul_ck { + emul_ck: emul_ck@78 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_54m_ck>; @@ -231,7 +231,7 @@ reg = <0x0078>; }; - mpu_ck: mpu_ck { + mpu_ck: mpu_ck@140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&core_ck>; @@ -240,7 +240,7 @@ ti,index-starts-at-one; }; - dsp_gate_fck: dsp_gate_fck { + dsp_gate_fck: dsp_gate_fck@800 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&core_ck>; @@ -248,7 +248,7 @@ reg = <0x0800>; }; - dsp_div_fck: dsp_div_fck { + dsp_div_fck: dsp_div_fck@840 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&core_ck>; @@ -261,7 +261,7 @@ clocks = <&dsp_gate_fck>, <&dsp_div_fck>; }; - core_l3_ck: core_l3_ck { + core_l3_ck: core_l3_ck@240 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&core_ck>; @@ -270,7 +270,7 @@ ti,index-starts-at-one; }; - gfx_3d_gate_fck: gfx_3d_gate_fck { + gfx_3d_gate_fck: gfx_3d_gate_fck@300 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&core_l3_ck>; @@ -278,7 +278,7 @@ reg = <0x0300>; }; - gfx_3d_div_fck: gfx_3d_div_fck { + gfx_3d_div_fck: gfx_3d_div_fck@340 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&core_l3_ck>; @@ -293,7 +293,7 @@ clocks = <&gfx_3d_gate_fck>, <&gfx_3d_div_fck>; }; - gfx_2d_gate_fck: gfx_2d_gate_fck { + gfx_2d_gate_fck: gfx_2d_gate_fck@300 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&core_l3_ck>; @@ -301,7 +301,7 @@ reg = <0x0300>; }; - gfx_2d_div_fck: gfx_2d_div_fck { + gfx_2d_div_fck: gfx_2d_div_fck@340 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&core_l3_ck>; @@ -316,7 +316,7 @@ clocks = <&gfx_2d_gate_fck>, <&gfx_2d_div_fck>; }; - gfx_ick: gfx_ick { + gfx_ick: gfx_ick@310 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&core_l3_ck>; @@ -324,7 +324,7 @@ reg = <0x0310>; }; - l4_ck: l4_ck { + l4_ck: l4_ck@240 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&core_l3_ck>; @@ -334,7 +334,7 @@ ti,index-starts-at-one; }; - dss_ick: dss_ick { + dss_ick: dss_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-no-wait-interface-clock"; clocks = <&l4_ck>; @@ -342,7 +342,7 @@ reg = <0x0210>; }; - dss1_gate_fck: dss1_gate_fck { + dss1_gate_fck: dss1_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&core_ck>; @@ -428,7 +428,7 @@ clock-div = <16>; }; - dss1_mux_fck: dss1_mux_fck { + dss1_mux_fck: dss1_mux_fck@240 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_ck>, <&core_ck>, <&core_d2_ck>, <&core_d3_ck>, <&core_d4_ck>, <&core_d5_ck>, <&core_d6_ck>, <&core_d8_ck>, <&core_d9_ck>, <&core_d12_ck>, <&core_d16_ck>; @@ -442,7 +442,7 @@ clocks = <&dss1_gate_fck>, <&dss1_mux_fck>; }; - dss2_gate_fck: dss2_gate_fck { + dss2_gate_fck: dss2_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&func_48m_ck>; @@ -450,7 +450,7 @@ reg = <0x0200>; }; - dss2_mux_fck: dss2_mux_fck { + dss2_mux_fck: dss2_mux_fck@240 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_ck>, <&func_48m_ck>; @@ -464,7 +464,7 @@ clocks = <&dss2_gate_fck>, <&dss2_mux_fck>; }; - dss_54m_fck: dss_54m_fck { + dss_54m_fck: dss_54m_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_54m_ck>; @@ -472,7 +472,7 @@ reg = <0x0200>; }; - ssi_ssr_sst_gate_fck: ssi_ssr_sst_gate_fck { + ssi_ssr_sst_gate_fck: ssi_ssr_sst_gate_fck@204 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&core_ck>; @@ -480,7 +480,7 @@ reg = <0x0204>; }; - ssi_ssr_sst_div_fck: ssi_ssr_sst_div_fck { + ssi_ssr_sst_div_fck: ssi_ssr_sst_div_fck@240 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&core_ck>; @@ -494,7 +494,7 @@ clocks = <&ssi_ssr_sst_gate_fck>, <&ssi_ssr_sst_div_fck>; }; - usb_l4_gate_ick: usb_l4_gate_ick { + usb_l4_gate_ick: usb_l4_gate_ick@214 { #clock-cells = <0>; compatible = "ti,composite-interface-clock"; clocks = <&core_l3_ck>; @@ -502,7 +502,7 @@ reg = <0x0214>; }; - usb_l4_div_ick: usb_l4_div_ick { + usb_l4_div_ick: usb_l4_div_ick@240 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&core_l3_ck>; @@ -517,7 +517,7 @@ clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>; }; - ssi_l4_ick: ssi_l4_ick { + ssi_l4_ick: ssi_l4_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -525,7 +525,7 @@ reg = <0x0214>; }; - gpt1_ick: gpt1_ick { + gpt1_ick: gpt1_ick@410 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -533,7 +533,7 @@ reg = <0x0410>; }; - gpt1_gate_fck: gpt1_gate_fck { + gpt1_gate_fck: gpt1_gate_fck@400 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -541,7 +541,7 @@ reg = <0x0400>; }; - gpt1_mux_fck: gpt1_mux_fck { + gpt1_mux_fck: gpt1_mux_fck@440 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -554,7 +554,7 @@ clocks = <&gpt1_gate_fck>, <&gpt1_mux_fck>; }; - gpt2_ick: gpt2_ick { + gpt2_ick: gpt2_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -562,7 +562,7 @@ reg = <0x0210>; }; - gpt2_gate_fck: gpt2_gate_fck { + gpt2_gate_fck: gpt2_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -570,7 +570,7 @@ reg = <0x0200>; }; - gpt2_mux_fck: gpt2_mux_fck { + gpt2_mux_fck: gpt2_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -584,7 +584,7 @@ clocks = <&gpt2_gate_fck>, <&gpt2_mux_fck>; }; - gpt3_ick: gpt3_ick { + gpt3_ick: gpt3_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -592,7 +592,7 @@ reg = <0x0210>; }; - gpt3_gate_fck: gpt3_gate_fck { + gpt3_gate_fck: gpt3_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -600,7 +600,7 @@ reg = <0x0200>; }; - gpt3_mux_fck: gpt3_mux_fck { + gpt3_mux_fck: gpt3_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -614,7 +614,7 @@ clocks = <&gpt3_gate_fck>, <&gpt3_mux_fck>; }; - gpt4_ick: gpt4_ick { + gpt4_ick: gpt4_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -622,7 +622,7 @@ reg = <0x0210>; }; - gpt4_gate_fck: gpt4_gate_fck { + gpt4_gate_fck: gpt4_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -630,7 +630,7 @@ reg = <0x0200>; }; - gpt4_mux_fck: gpt4_mux_fck { + gpt4_mux_fck: gpt4_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -644,7 +644,7 @@ clocks = <&gpt4_gate_fck>, <&gpt4_mux_fck>; }; - gpt5_ick: gpt5_ick { + gpt5_ick: gpt5_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -652,7 +652,7 @@ reg = <0x0210>; }; - gpt5_gate_fck: gpt5_gate_fck { + gpt5_gate_fck: gpt5_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -660,7 +660,7 @@ reg = <0x0200>; }; - gpt5_mux_fck: gpt5_mux_fck { + gpt5_mux_fck: gpt5_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -674,7 +674,7 @@ clocks = <&gpt5_gate_fck>, <&gpt5_mux_fck>; }; - gpt6_ick: gpt6_ick { + gpt6_ick: gpt6_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -682,7 +682,7 @@ reg = <0x0210>; }; - gpt6_gate_fck: gpt6_gate_fck { + gpt6_gate_fck: gpt6_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -690,7 +690,7 @@ reg = <0x0200>; }; - gpt6_mux_fck: gpt6_mux_fck { + gpt6_mux_fck: gpt6_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -704,7 +704,7 @@ clocks = <&gpt6_gate_fck>, <&gpt6_mux_fck>; }; - gpt7_ick: gpt7_ick { + gpt7_ick: gpt7_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -712,7 +712,7 @@ reg = <0x0210>; }; - gpt7_gate_fck: gpt7_gate_fck { + gpt7_gate_fck: gpt7_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -720,7 +720,7 @@ reg = <0x0200>; }; - gpt7_mux_fck: gpt7_mux_fck { + gpt7_mux_fck: gpt7_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -734,7 +734,7 @@ clocks = <&gpt7_gate_fck>, <&gpt7_mux_fck>; }; - gpt8_ick: gpt8_ick { + gpt8_ick: gpt8_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -742,7 +742,7 @@ reg = <0x0210>; }; - gpt8_gate_fck: gpt8_gate_fck { + gpt8_gate_fck: gpt8_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -750,7 +750,7 @@ reg = <0x0200>; }; - gpt8_mux_fck: gpt8_mux_fck { + gpt8_mux_fck: gpt8_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -764,7 +764,7 @@ clocks = <&gpt8_gate_fck>, <&gpt8_mux_fck>; }; - gpt9_ick: gpt9_ick { + gpt9_ick: gpt9_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -772,7 +772,7 @@ reg = <0x0210>; }; - gpt9_gate_fck: gpt9_gate_fck { + gpt9_gate_fck: gpt9_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -780,7 +780,7 @@ reg = <0x0200>; }; - gpt9_mux_fck: gpt9_mux_fck { + gpt9_mux_fck: gpt9_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -794,7 +794,7 @@ clocks = <&gpt9_gate_fck>, <&gpt9_mux_fck>; }; - gpt10_ick: gpt10_ick { + gpt10_ick: gpt10_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -802,7 +802,7 @@ reg = <0x0210>; }; - gpt10_gate_fck: gpt10_gate_fck { + gpt10_gate_fck: gpt10_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -810,7 +810,7 @@ reg = <0x0200>; }; - gpt10_mux_fck: gpt10_mux_fck { + gpt10_mux_fck: gpt10_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -824,7 +824,7 @@ clocks = <&gpt10_gate_fck>, <&gpt10_mux_fck>; }; - gpt11_ick: gpt11_ick { + gpt11_ick: gpt11_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -832,7 +832,7 @@ reg = <0x0210>; }; - gpt11_gate_fck: gpt11_gate_fck { + gpt11_gate_fck: gpt11_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -840,7 +840,7 @@ reg = <0x0200>; }; - gpt11_mux_fck: gpt11_mux_fck { + gpt11_mux_fck: gpt11_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -854,7 +854,7 @@ clocks = <&gpt11_gate_fck>, <&gpt11_mux_fck>; }; - gpt12_ick: gpt12_ick { + gpt12_ick: gpt12_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -862,7 +862,7 @@ reg = <0x0210>; }; - gpt12_gate_fck: gpt12_gate_fck { + gpt12_gate_fck: gpt12_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&func_32k_ck>; @@ -870,7 +870,7 @@ reg = <0x0200>; }; - gpt12_mux_fck: gpt12_mux_fck { + gpt12_mux_fck: gpt12_mux_fck@244 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>; @@ -884,7 +884,7 @@ clocks = <&gpt12_gate_fck>, <&gpt12_mux_fck>; }; - mcbsp1_ick: mcbsp1_ick { + mcbsp1_ick: mcbsp1_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -892,7 +892,7 @@ reg = <0x0210>; }; - mcbsp1_gate_fck: mcbsp1_gate_fck { + mcbsp1_gate_fck: mcbsp1_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -900,7 +900,7 @@ reg = <0x0200>; }; - mcbsp2_ick: mcbsp2_ick { + mcbsp2_ick: mcbsp2_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -908,7 +908,7 @@ reg = <0x0210>; }; - mcbsp2_gate_fck: mcbsp2_gate_fck { + mcbsp2_gate_fck: mcbsp2_gate_fck@200 { #clock-cells = <0>; compatible = "ti,composite-gate-clock"; clocks = <&mcbsp_clks>; @@ -916,7 +916,7 @@ reg = <0x0200>; }; - mcspi1_ick: mcspi1_ick { + mcspi1_ick: mcspi1_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -924,7 +924,7 @@ reg = <0x0210>; }; - mcspi1_fck: mcspi1_fck { + mcspi1_fck: mcspi1_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_48m_ck>; @@ -932,7 +932,7 @@ reg = <0x0200>; }; - mcspi2_ick: mcspi2_ick { + mcspi2_ick: mcspi2_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -940,7 +940,7 @@ reg = <0x0210>; }; - mcspi2_fck: mcspi2_fck { + mcspi2_fck: mcspi2_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_48m_ck>; @@ -948,7 +948,7 @@ reg = <0x0200>; }; - uart1_ick: uart1_ick { + uart1_ick: uart1_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -956,7 +956,7 @@ reg = <0x0210>; }; - uart1_fck: uart1_fck { + uart1_fck: uart1_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_48m_ck>; @@ -964,7 +964,7 @@ reg = <0x0200>; }; - uart2_ick: uart2_ick { + uart2_ick: uart2_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -972,7 +972,7 @@ reg = <0x0210>; }; - uart2_fck: uart2_fck { + uart2_fck: uart2_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_48m_ck>; @@ -980,7 +980,7 @@ reg = <0x0200>; }; - uart3_ick: uart3_ick { + uart3_ick: uart3_ick@214 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -988,7 +988,7 @@ reg = <0x0214>; }; - uart3_fck: uart3_fck { + uart3_fck: uart3_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_48m_ck>; @@ -996,7 +996,7 @@ reg = <0x0204>; }; - gpios_ick: gpios_ick { + gpios_ick: gpios_ick@410 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -1004,7 +1004,7 @@ reg = <0x0410>; }; - gpios_fck: gpios_fck { + gpios_fck: gpios_fck@400 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_32k_ck>; @@ -1012,7 +1012,7 @@ reg = <0x0400>; }; - mpu_wdt_ick: mpu_wdt_ick { + mpu_wdt_ick: mpu_wdt_ick@410 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -1020,7 +1020,7 @@ reg = <0x0410>; }; - mpu_wdt_fck: mpu_wdt_fck { + mpu_wdt_fck: mpu_wdt_fck@400 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_32k_ck>; @@ -1028,7 +1028,7 @@ reg = <0x0400>; }; - sync_32k_ick: sync_32k_ick { + sync_32k_ick: sync_32k_ick@410 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -1036,7 +1036,7 @@ reg = <0x0410>; }; - wdt1_ick: wdt1_ick { + wdt1_ick: wdt1_ick@410 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -1044,7 +1044,7 @@ reg = <0x0410>; }; - omapctrl_ick: omapctrl_ick { + omapctrl_ick: omapctrl_ick@410 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&sys_ck>; @@ -1052,7 +1052,7 @@ reg = <0x0410>; }; - cam_fck: cam_fck { + cam_fck: cam_fck@200 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_96m_ck>; @@ -1060,7 +1060,7 @@ reg = <0x0200>; }; - cam_ick: cam_ick { + cam_ick: cam_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-no-wait-interface-clock"; clocks = <&l4_ck>; @@ -1068,7 +1068,7 @@ reg = <0x0210>; }; - mailboxes_ick: mailboxes_ick { + mailboxes_ick: mailboxes_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1076,7 +1076,7 @@ reg = <0x0210>; }; - wdt4_ick: wdt4_ick { + wdt4_ick: wdt4_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1084,7 +1084,7 @@ reg = <0x0210>; }; - wdt4_fck: wdt4_fck { + wdt4_fck: wdt4_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_32k_ck>; @@ -1092,7 +1092,7 @@ reg = <0x0200>; }; - mspro_ick: mspro_ick { + mspro_ick: mspro_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1100,7 +1100,7 @@ reg = <0x0210>; }; - mspro_fck: mspro_fck { + mspro_fck: mspro_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_96m_ck>; @@ -1108,7 +1108,7 @@ reg = <0x0200>; }; - fac_ick: fac_ick { + fac_ick: fac_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1116,7 +1116,7 @@ reg = <0x0210>; }; - fac_fck: fac_fck { + fac_fck: fac_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_12m_ck>; @@ -1124,7 +1124,7 @@ reg = <0x0200>; }; - hdq_ick: hdq_ick { + hdq_ick: hdq_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1132,7 +1132,7 @@ reg = <0x0210>; }; - hdq_fck: hdq_fck { + hdq_fck: hdq_fck@200 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_12m_ck>; @@ -1140,7 +1140,7 @@ reg = <0x0200>; }; - i2c1_ick: i2c1_ick { + i2c1_ick: i2c1_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1148,7 +1148,7 @@ reg = <0x0210>; }; - i2c2_ick: i2c2_ick { + i2c2_ick: i2c2_ick@210 { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1156,7 +1156,7 @@ reg = <0x0210>; }; - gpmc_fck: gpmc_fck { + gpmc_fck: gpmc_fck@238 { #clock-cells = <0>; compatible = "ti,fixed-factor-clock"; clocks = <&core_l3_ck>; @@ -1174,7 +1174,7 @@ clock-div = <1>; }; - sdma_ick: sdma_ick { + sdma_ick: sdma_ick@238 { #clock-cells = <0>; compatible = "ti,fixed-factor-clock"; clocks = <&core_l3_ck>; @@ -1184,7 +1184,7 @@ ti,clock-mult = <1>; }; - sdrc_ick: sdrc_ick { + sdrc_ick: sdrc_ick@238 { #clock-cells = <0>; compatible = "ti,fixed-factor-clock"; clocks = <&core_l3_ck>; @@ -1194,7 +1194,7 @@ ti,clock-mult = <1>; }; - des_ick: des_ick { + des_ick: des_ick@21c { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1202,7 +1202,7 @@ reg = <0x021c>; }; - sha_ick: sha_ick { + sha_ick: sha_ick@21c { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1210,7 +1210,7 @@ reg = <0x021c>; }; - rng_ick: rng_ick { + rng_ick: rng_ick@21c { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1218,7 +1218,7 @@ reg = <0x021c>; }; - aes_ick: aes_ick { + aes_ick: aes_ick@21c { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1226,7 +1226,7 @@ reg = <0x021c>; }; - pka_ick: pka_ick { + pka_ick: pka_ick@21c { #clock-cells = <0>; compatible = "ti,omap3-interface-clock"; clocks = <&l4_ck>; @@ -1234,7 +1234,7 @@ reg = <0x021c>; }; - usb_fck: usb_fck { + usb_fck: usb_fck@204 { #clock-cells = <0>; compatible = "ti,wait-gate-clock"; clocks = <&func_48m_ck>; -- GitLab From 8f952371accb46d38287956c0f348f205bb7963a Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:08 +0300 Subject: [PATCH 2005/9938] ARM: dts: omap4: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for OMAP4 clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap443x-clocks.dtsi | 2 +- arch/arm/boot/dts/omap446x-clocks.dtsi | 4 +- arch/arm/boot/dts/omap44xx-clocks.dtsi | 316 ++++++++++++------------- 3 files changed, 161 insertions(+), 161 deletions(-) diff --git a/arch/arm/boot/dts/omap443x-clocks.dtsi b/arch/arm/boot/dts/omap443x-clocks.dtsi index 2bd2166f88d3..f370d96a87e5 100644 --- a/arch/arm/boot/dts/omap443x-clocks.dtsi +++ b/arch/arm/boot/dts/omap443x-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &prm_clocks { - bandgap_fclk: bandgap_fclk { + bandgap_fclk: bandgap_fclk@1888 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; diff --git a/arch/arm/boot/dts/omap446x-clocks.dtsi b/arch/arm/boot/dts/omap446x-clocks.dtsi index be033e9803e9..fb5929b742d4 100644 --- a/arch/arm/boot/dts/omap446x-clocks.dtsi +++ b/arch/arm/boot/dts/omap446x-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &prm_clocks { - div_ts_ck: div_ts_ck { + div_ts_ck: div_ts_ck@1888 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&l4_wkup_clk_mux_ck>; @@ -17,7 +17,7 @@ ti,dividers = <8>, <16>, <32>; }; - bandgap_ts_fclk: bandgap_ts_fclk { + bandgap_ts_fclk: bandgap_ts_fclk@1888 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&div_ts_ck>; diff --git a/arch/arm/boot/dts/omap44xx-clocks.dtsi b/arch/arm/boot/dts/omap44xx-clocks.dtsi index f2c48f09824e..9573b37fbaa7 100644 --- a/arch/arm/boot/dts/omap44xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap44xx-clocks.dtsi @@ -20,7 +20,7 @@ clock-frequency = <12000000>; }; - pad_clks_ck: pad_clks_ck { + pad_clks_ck: pad_clks_ck@108 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&pad_clks_src_ck>; @@ -46,7 +46,7 @@ clock-frequency = <12000000>; }; - slimbus_clk: slimbus_clk { + slimbus_clk: slimbus_clk@108 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&slimbus_src_clk>; @@ -132,21 +132,21 @@ clock-frequency = <60000000>; }; - dpll_abe_ck: dpll_abe_ck { + dpll_abe_ck: dpll_abe_ck@1e0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-m4xen-clock"; clocks = <&abe_dpll_refclk_mux_ck>, <&abe_dpll_bypass_clk_mux_ck>; reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>; }; - dpll_abe_x2_ck: dpll_abe_x2_ck { + dpll_abe_x2_ck: dpll_abe_x2_ck@1f0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-x2-clock"; clocks = <&dpll_abe_ck>; reg = <0x01f0>; }; - dpll_abe_m2x2_ck: dpll_abe_m2x2_ck { + dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@1f0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_x2_ck>; @@ -165,7 +165,7 @@ clock-div = <8>; }; - abe_clk: abe_clk { + abe_clk: abe_clk@108 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2x2_ck>; @@ -174,7 +174,7 @@ ti,index-power-of-two; }; - aess_fclk: aess_fclk { + aess_fclk: aess_fclk@528 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&abe_clk>; @@ -183,7 +183,7 @@ reg = <0x0528>; }; - dpll_abe_m3x2_ck: dpll_abe_m3x2_ck { + dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@1f4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_x2_ck>; @@ -194,7 +194,7 @@ ti,invert-autoidle-bit; }; - core_hsd_byp_clk_mux_ck: core_hsd_byp_clk_mux_ck { + core_hsd_byp_clk_mux_ck: core_hsd_byp_clk_mux_ck@12c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_abe_m3x2_ck>; @@ -202,7 +202,7 @@ reg = <0x012c>; }; - dpll_core_ck: dpll_core_ck { + dpll_core_ck: dpll_core_ck@120 { #clock-cells = <0>; compatible = "ti,omap4-dpll-core-clock"; clocks = <&sys_clkin_ck>, <&core_hsd_byp_clk_mux_ck>; @@ -215,7 +215,7 @@ clocks = <&dpll_core_ck>; }; - dpll_core_m6x2_ck: dpll_core_m6x2_ck { + dpll_core_m6x2_ck: dpll_core_m6x2_ck@140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -226,7 +226,7 @@ ti,invert-autoidle-bit; }; - dpll_core_m2_ck: dpll_core_m2_ck { + dpll_core_m2_ck: dpll_core_m2_ck@130 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_ck>; @@ -245,7 +245,7 @@ clock-div = <2>; }; - dpll_core_m5x2_ck: dpll_core_m5x2_ck { + dpll_core_m5x2_ck: dpll_core_m5x2_ck@13c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -256,7 +256,7 @@ ti,invert-autoidle-bit; }; - div_core_ck: div_core_ck { + div_core_ck: div_core_ck@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_m5x2_ck>; @@ -264,7 +264,7 @@ ti,max-div = <2>; }; - div_iva_hs_clk: div_iva_hs_clk { + div_iva_hs_clk: div_iva_hs_clk@1dc { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_m5x2_ck>; @@ -273,7 +273,7 @@ ti,index-power-of-two; }; - div_mpu_hs_clk: div_mpu_hs_clk { + div_mpu_hs_clk: div_mpu_hs_clk@19c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_m5x2_ck>; @@ -282,7 +282,7 @@ ti,index-power-of-two; }; - dpll_core_m4x2_ck: dpll_core_m4x2_ck { + dpll_core_m4x2_ck: dpll_core_m4x2_ck@138 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -301,7 +301,7 @@ clock-div = <2>; }; - dpll_abe_m2_ck: dpll_abe_m2_ck { + dpll_abe_m2_ck: dpll_abe_m2_ck@1f0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_ck>; @@ -310,7 +310,7 @@ ti,index-starts-at-one; }; - dpll_core_m3x2_gate_ck: dpll_core_m3x2_gate_ck { + dpll_core_m3x2_gate_ck: dpll_core_m3x2_gate_ck@134 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_x2_ck>; @@ -318,7 +318,7 @@ reg = <0x0134>; }; - dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck { + dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck@134 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -333,7 +333,7 @@ clocks = <&dpll_core_m3x2_gate_ck>, <&dpll_core_m3x2_div_ck>; }; - dpll_core_m7x2_ck: dpll_core_m7x2_ck { + dpll_core_m7x2_ck: dpll_core_m7x2_ck@144 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -344,7 +344,7 @@ ti,invert-autoidle-bit; }; - iva_hsd_byp_clk_mux_ck: iva_hsd_byp_clk_mux_ck { + iva_hsd_byp_clk_mux_ck: iva_hsd_byp_clk_mux_ck@1ac { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&div_iva_hs_clk>; @@ -352,7 +352,7 @@ reg = <0x01ac>; }; - dpll_iva_ck: dpll_iva_ck { + dpll_iva_ck: dpll_iva_ck@1a0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin_ck>, <&iva_hsd_byp_clk_mux_ck>; @@ -365,7 +365,7 @@ clocks = <&dpll_iva_ck>; }; - dpll_iva_m4x2_ck: dpll_iva_m4x2_ck { + dpll_iva_m4x2_ck: dpll_iva_m4x2_ck@1b8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_iva_x2_ck>; @@ -376,7 +376,7 @@ ti,invert-autoidle-bit; }; - dpll_iva_m5x2_ck: dpll_iva_m5x2_ck { + dpll_iva_m5x2_ck: dpll_iva_m5x2_ck@1bc { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_iva_x2_ck>; @@ -387,14 +387,14 @@ ti,invert-autoidle-bit; }; - dpll_mpu_ck: dpll_mpu_ck { + dpll_mpu_ck: dpll_mpu_ck@160 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin_ck>, <&div_mpu_hs_clk>; reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; }; - dpll_mpu_m2_ck: dpll_mpu_m2_ck { + dpll_mpu_m2_ck: dpll_mpu_m2_ck@170 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_mpu_ck>; @@ -421,7 +421,7 @@ clock-div = <3>; }; - l3_div_ck: l3_div_ck { + l3_div_ck: l3_div_ck@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&div_core_ck>; @@ -430,7 +430,7 @@ reg = <0x0100>; }; - l4_div_ck: l4_div_ck { + l4_div_ck: l4_div_ck@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&l3_div_ck>; @@ -455,7 +455,7 @@ clock-div = <2>; }; - ocp_abe_iclk: ocp_abe_iclk { + ocp_abe_iclk: ocp_abe_iclk@528 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&aess_fclk>; @@ -472,7 +472,7 @@ clock-div = <4>; }; - dmic_sync_mux_ck: dmic_sync_mux_ck { + dmic_sync_mux_ck: dmic_sync_mux_ck@538 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; @@ -480,7 +480,7 @@ reg = <0x0538>; }; - func_dmic_abe_gfclk: func_dmic_abe_gfclk { + func_dmic_abe_gfclk: func_dmic_abe_gfclk@538 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -488,7 +488,7 @@ reg = <0x0538>; }; - mcasp_sync_mux_ck: mcasp_sync_mux_ck { + mcasp_sync_mux_ck: mcasp_sync_mux_ck@540 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; @@ -496,7 +496,7 @@ reg = <0x0540>; }; - func_mcasp_abe_gfclk: func_mcasp_abe_gfclk { + func_mcasp_abe_gfclk: func_mcasp_abe_gfclk@540 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -504,7 +504,7 @@ reg = <0x0540>; }; - mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck { + mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck@548 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; @@ -512,7 +512,7 @@ reg = <0x0548>; }; - func_mcbsp1_gfclk: func_mcbsp1_gfclk { + func_mcbsp1_gfclk: func_mcbsp1_gfclk@548 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -520,7 +520,7 @@ reg = <0x0548>; }; - mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck { + mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck@550 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; @@ -528,7 +528,7 @@ reg = <0x0550>; }; - func_mcbsp2_gfclk: func_mcbsp2_gfclk { + func_mcbsp2_gfclk: func_mcbsp2_gfclk@550 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -536,7 +536,7 @@ reg = <0x0550>; }; - mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck { + mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck@558 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; @@ -544,7 +544,7 @@ reg = <0x0558>; }; - func_mcbsp3_gfclk: func_mcbsp3_gfclk { + func_mcbsp3_gfclk: func_mcbsp3_gfclk@558 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -552,7 +552,7 @@ reg = <0x0558>; }; - slimbus1_fclk_1: slimbus1_fclk_1 { + slimbus1_fclk_1: slimbus1_fclk_1@560 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_24m_clk>; @@ -560,7 +560,7 @@ reg = <0x0560>; }; - slimbus1_fclk_0: slimbus1_fclk_0 { + slimbus1_fclk_0: slimbus1_fclk_0@560 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&abe_24m_fclk>; @@ -568,7 +568,7 @@ reg = <0x0560>; }; - slimbus1_fclk_2: slimbus1_fclk_2 { + slimbus1_fclk_2: slimbus1_fclk_2@560 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&pad_clks_ck>; @@ -576,7 +576,7 @@ reg = <0x0560>; }; - slimbus1_slimbus_clk: slimbus1_slimbus_clk { + slimbus1_slimbus_clk: slimbus1_slimbus_clk@560 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&slimbus_clk>; @@ -584,7 +584,7 @@ reg = <0x0560>; }; - timer5_sync_mux: timer5_sync_mux { + timer5_sync_mux: timer5_sync_mux@568 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; @@ -592,7 +592,7 @@ reg = <0x0568>; }; - timer6_sync_mux: timer6_sync_mux { + timer6_sync_mux: timer6_sync_mux@570 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; @@ -600,7 +600,7 @@ reg = <0x0570>; }; - timer7_sync_mux: timer7_sync_mux { + timer7_sync_mux: timer7_sync_mux@578 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; @@ -608,7 +608,7 @@ reg = <0x0578>; }; - timer8_sync_mux: timer8_sync_mux { + timer8_sync_mux: timer8_sync_mux@580 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; @@ -623,7 +623,7 @@ }; }; &prm_clocks { - sys_clkin_ck: sys_clkin_ck { + sys_clkin_ck: sys_clkin_ck@110 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>; @@ -631,7 +631,7 @@ ti,index-starts-at-one; }; - abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck { + abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck@108 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -639,7 +639,7 @@ reg = <0x0108>; }; - abe_dpll_refclk_mux_ck: abe_dpll_refclk_mux_ck { + abe_dpll_refclk_mux_ck: abe_dpll_refclk_mux_ck@10c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -654,14 +654,14 @@ clock-div = <1>; }; - l4_wkup_clk_mux_ck: l4_wkup_clk_mux_ck { + l4_wkup_clk_mux_ck: l4_wkup_clk_mux_ck@108 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&lp_clk_div_ck>; reg = <0x0108>; }; - syc_clk_div_ck: syc_clk_div_ck { + syc_clk_div_ck: syc_clk_div_ck@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin_ck>; @@ -669,7 +669,7 @@ ti,max-div = <2>; }; - gpio1_dbclk: gpio1_dbclk { + gpio1_dbclk: gpio1_dbclk@1838 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -677,7 +677,7 @@ reg = <0x1838>; }; - dmt1_clk_mux: dmt1_clk_mux { + dmt1_clk_mux: dmt1_clk_mux@1840 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -685,7 +685,7 @@ reg = <0x1840>; }; - usim_ck: usim_ck { + usim_ck: usim_ck@1858 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_m4x2_ck>; @@ -694,7 +694,7 @@ ti,dividers = <14>, <18>; }; - usim_fclk: usim_fclk { + usim_fclk: usim_fclk@1858 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&usim_ck>; @@ -702,7 +702,7 @@ reg = <0x1858>; }; - pmd_stm_clock_mux_ck: pmd_stm_clock_mux_ck { + pmd_stm_clock_mux_ck: pmd_stm_clock_mux_ck@1a20 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>; @@ -710,7 +710,7 @@ reg = <0x1a20>; }; - pmd_trace_clk_mux_ck: pmd_trace_clk_mux_ck { + pmd_trace_clk_mux_ck: pmd_trace_clk_mux_ck@1a20 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>; @@ -718,7 +718,7 @@ reg = <0x1a20>; }; - stm_clk_div_ck: stm_clk_div_ck { + stm_clk_div_ck: stm_clk_div_ck@1a20 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&pmd_stm_clock_mux_ck>; @@ -728,7 +728,7 @@ ti,index-power-of-two; }; - trace_clk_div_div_ck: trace_clk_div_div_ck { + trace_clk_div_div_ck: trace_clk_div_div_ck@1a20 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&pmd_trace_clk_mux_ck>; @@ -752,7 +752,7 @@ }; &cm2_clocks { - per_hsd_byp_clk_mux_ck: per_hsd_byp_clk_mux_ck { + per_hsd_byp_clk_mux_ck: per_hsd_byp_clk_mux_ck@14c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&per_hs_clk_div_ck>; @@ -760,14 +760,14 @@ reg = <0x014c>; }; - dpll_per_ck: dpll_per_ck { + dpll_per_ck: dpll_per_ck@140 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin_ck>, <&per_hsd_byp_clk_mux_ck>; reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>; }; - dpll_per_m2_ck: dpll_per_m2_ck { + dpll_per_m2_ck: dpll_per_m2_ck@150 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_ck>; @@ -776,14 +776,14 @@ ti,index-starts-at-one; }; - dpll_per_x2_ck: dpll_per_x2_ck { + dpll_per_x2_ck: dpll_per_x2_ck@150 { #clock-cells = <0>; compatible = "ti,omap4-dpll-x2-clock"; clocks = <&dpll_per_ck>; reg = <0x0150>; }; - dpll_per_m2x2_ck: dpll_per_m2x2_ck { + dpll_per_m2x2_ck: dpll_per_m2x2_ck@150 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -794,7 +794,7 @@ ti,invert-autoidle-bit; }; - dpll_per_m3x2_gate_ck: dpll_per_m3x2_gate_ck { + dpll_per_m3x2_gate_ck: dpll_per_m3x2_gate_ck@154 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_per_x2_ck>; @@ -802,7 +802,7 @@ reg = <0x0154>; }; - dpll_per_m3x2_div_ck: dpll_per_m3x2_div_ck { + dpll_per_m3x2_div_ck: dpll_per_m3x2_div_ck@154 { #clock-cells = <0>; compatible = "ti,composite-divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -817,7 +817,7 @@ clocks = <&dpll_per_m3x2_gate_ck>, <&dpll_per_m3x2_div_ck>; }; - dpll_per_m4x2_ck: dpll_per_m4x2_ck { + dpll_per_m4x2_ck: dpll_per_m4x2_ck@158 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -828,7 +828,7 @@ ti,invert-autoidle-bit; }; - dpll_per_m5x2_ck: dpll_per_m5x2_ck { + dpll_per_m5x2_ck: dpll_per_m5x2_ck@15c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -839,7 +839,7 @@ ti,invert-autoidle-bit; }; - dpll_per_m6x2_ck: dpll_per_m6x2_ck { + dpll_per_m6x2_ck: dpll_per_m6x2_ck@160 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -850,7 +850,7 @@ ti,invert-autoidle-bit; }; - dpll_per_m7x2_ck: dpll_per_m7x2_ck { + dpll_per_m7x2_ck: dpll_per_m7x2_ck@164 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -861,14 +861,14 @@ ti,invert-autoidle-bit; }; - dpll_usb_ck: dpll_usb_ck { + dpll_usb_ck: dpll_usb_ck@180 { #clock-cells = <0>; compatible = "ti,omap4-dpll-j-type-clock"; clocks = <&sys_clkin_ck>, <&usb_hs_clk_div_ck>; reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>; }; - dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck { + dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck@1b4 { #clock-cells = <0>; compatible = "ti,fixed-factor-clock"; clocks = <&dpll_usb_ck>; @@ -879,7 +879,7 @@ ti,invert-autoidle-bit; }; - dpll_usb_m2_ck: dpll_usb_m2_ck { + dpll_usb_m2_ck: dpll_usb_m2_ck@190 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_usb_ck>; @@ -890,7 +890,7 @@ ti,invert-autoidle-bit; }; - ducati_clk_mux_ck: ducati_clk_mux_ck { + ducati_clk_mux_ck: ducati_clk_mux_ck@100 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&div_core_ck>, <&dpll_per_m6x2_ck>; @@ -921,7 +921,7 @@ clock-div = <8>; }; - func_48m_fclk: func_48m_fclk { + func_48m_fclk: func_48m_fclk@108 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_m2x2_ck>; @@ -937,7 +937,7 @@ clock-div = <4>; }; - func_64m_fclk: func_64m_fclk { + func_64m_fclk: func_64m_fclk@108 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_m4x2_ck>; @@ -945,7 +945,7 @@ ti,dividers = <2>, <4>; }; - func_96m_fclk: func_96m_fclk { + func_96m_fclk: func_96m_fclk@108 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_m2x2_ck>; @@ -953,7 +953,7 @@ ti,dividers = <2>, <4>; }; - init_60m_fclk: init_60m_fclk { + init_60m_fclk: init_60m_fclk@104 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_usb_m2_ck>; @@ -961,7 +961,7 @@ ti,dividers = <1>, <8>; }; - per_abe_nc_fclk: per_abe_nc_fclk { + per_abe_nc_fclk: per_abe_nc_fclk@108 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2_ck>; @@ -969,7 +969,7 @@ ti,max-div = <2>; }; - aes1_fck: aes1_fck { + aes1_fck: aes1_fck@15a0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3_div_ck>; @@ -977,7 +977,7 @@ reg = <0x15a0>; }; - aes2_fck: aes2_fck { + aes2_fck: aes2_fck@15a8 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3_div_ck>; @@ -985,7 +985,7 @@ reg = <0x15a8>; }; - dss_sys_clk: dss_sys_clk { + dss_sys_clk: dss_sys_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&syc_clk_div_ck>; @@ -993,7 +993,7 @@ reg = <0x1120>; }; - dss_tv_clk: dss_tv_clk { + dss_tv_clk: dss_tv_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&extalt_clkin_ck>; @@ -1001,7 +1001,7 @@ reg = <0x1120>; }; - dss_dss_clk: dss_dss_clk { + dss_dss_clk: dss_dss_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_per_m5x2_ck>; @@ -1010,7 +1010,7 @@ ti,set-rate-parent; }; - dss_48mhz_clk: dss_48mhz_clk { + dss_48mhz_clk: dss_48mhz_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_48mc_fclk>; @@ -1018,7 +1018,7 @@ reg = <0x1120>; }; - fdif_fck: fdif_fck { + fdif_fck: fdif_fck@1028 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_m4x2_ck>; @@ -1028,7 +1028,7 @@ ti,index-power-of-two; }; - gpio2_dbclk: gpio2_dbclk { + gpio2_dbclk: gpio2_dbclk@1460 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1036,7 +1036,7 @@ reg = <0x1460>; }; - gpio3_dbclk: gpio3_dbclk { + gpio3_dbclk: gpio3_dbclk@1468 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1044,7 +1044,7 @@ reg = <0x1468>; }; - gpio4_dbclk: gpio4_dbclk { + gpio4_dbclk: gpio4_dbclk@1470 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1052,7 +1052,7 @@ reg = <0x1470>; }; - gpio5_dbclk: gpio5_dbclk { + gpio5_dbclk: gpio5_dbclk@1478 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1060,7 +1060,7 @@ reg = <0x1478>; }; - gpio6_dbclk: gpio6_dbclk { + gpio6_dbclk: gpio6_dbclk@1480 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1068,7 +1068,7 @@ reg = <0x1480>; }; - sgx_clk_mux: sgx_clk_mux { + sgx_clk_mux: sgx_clk_mux@1220 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_core_m7x2_ck>, <&dpll_per_m7x2_ck>; @@ -1076,7 +1076,7 @@ reg = <0x1220>; }; - hsi_fck: hsi_fck { + hsi_fck: hsi_fck@1338 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_m2x2_ck>; @@ -1086,7 +1086,7 @@ ti,index-power-of-two; }; - iss_ctrlclk: iss_ctrlclk { + iss_ctrlclk: iss_ctrlclk@1020 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_96m_fclk>; @@ -1094,7 +1094,7 @@ reg = <0x1020>; }; - mcbsp4_sync_mux_ck: mcbsp4_sync_mux_ck { + mcbsp4_sync_mux_ck: mcbsp4_sync_mux_ck@14e0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_96m_fclk>, <&per_abe_nc_fclk>; @@ -1102,7 +1102,7 @@ reg = <0x14e0>; }; - per_mcbsp4_gfclk: per_mcbsp4_gfclk { + per_mcbsp4_gfclk: per_mcbsp4_gfclk@14e0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcbsp4_sync_mux_ck>, <&pad_clks_ck>; @@ -1110,7 +1110,7 @@ reg = <0x14e0>; }; - hsmmc1_fclk: hsmmc1_fclk { + hsmmc1_fclk: hsmmc1_fclk@1328 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_64m_fclk>, <&func_96m_fclk>; @@ -1118,7 +1118,7 @@ reg = <0x1328>; }; - hsmmc2_fclk: hsmmc2_fclk { + hsmmc2_fclk: hsmmc2_fclk@1330 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_64m_fclk>, <&func_96m_fclk>; @@ -1126,7 +1126,7 @@ reg = <0x1330>; }; - ocp2scp_usb_phy_phy_48m: ocp2scp_usb_phy_phy_48m { + ocp2scp_usb_phy_phy_48m: ocp2scp_usb_phy_phy_48m@13e0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_48m_fclk>; @@ -1134,7 +1134,7 @@ reg = <0x13e0>; }; - sha2md5_fck: sha2md5_fck { + sha2md5_fck: sha2md5_fck@15c8 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3_div_ck>; @@ -1142,7 +1142,7 @@ reg = <0x15c8>; }; - slimbus2_fclk_1: slimbus2_fclk_1 { + slimbus2_fclk_1: slimbus2_fclk_1@1538 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&per_abe_24m_fclk>; @@ -1150,7 +1150,7 @@ reg = <0x1538>; }; - slimbus2_fclk_0: slimbus2_fclk_0 { + slimbus2_fclk_0: slimbus2_fclk_0@1538 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_24mc_fclk>; @@ -1158,7 +1158,7 @@ reg = <0x1538>; }; - slimbus2_slimbus_clk: slimbus2_slimbus_clk { + slimbus2_slimbus_clk: slimbus2_slimbus_clk@1538 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&pad_slimbus_core_clks_ck>; @@ -1166,7 +1166,7 @@ reg = <0x1538>; }; - smartreflex_core_fck: smartreflex_core_fck { + smartreflex_core_fck: smartreflex_core_fck@638 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4_wkup_clk_mux_ck>; @@ -1174,7 +1174,7 @@ reg = <0x0638>; }; - smartreflex_iva_fck: smartreflex_iva_fck { + smartreflex_iva_fck: smartreflex_iva_fck@630 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4_wkup_clk_mux_ck>; @@ -1182,7 +1182,7 @@ reg = <0x0630>; }; - smartreflex_mpu_fck: smartreflex_mpu_fck { + smartreflex_mpu_fck: smartreflex_mpu_fck@628 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4_wkup_clk_mux_ck>; @@ -1190,7 +1190,7 @@ reg = <0x0628>; }; - cm2_dm10_mux: cm2_dm10_mux { + cm2_dm10_mux: cm2_dm10_mux@1428 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -1198,7 +1198,7 @@ reg = <0x1428>; }; - cm2_dm11_mux: cm2_dm11_mux { + cm2_dm11_mux: cm2_dm11_mux@1430 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -1206,7 +1206,7 @@ reg = <0x1430>; }; - cm2_dm2_mux: cm2_dm2_mux { + cm2_dm2_mux: cm2_dm2_mux@1438 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -1214,7 +1214,7 @@ reg = <0x1438>; }; - cm2_dm3_mux: cm2_dm3_mux { + cm2_dm3_mux: cm2_dm3_mux@1440 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -1222,7 +1222,7 @@ reg = <0x1440>; }; - cm2_dm4_mux: cm2_dm4_mux { + cm2_dm4_mux: cm2_dm4_mux@1448 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -1230,7 +1230,7 @@ reg = <0x1448>; }; - cm2_dm9_mux: cm2_dm9_mux { + cm2_dm9_mux: cm2_dm9_mux@1450 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&sys_32k_ck>; @@ -1238,7 +1238,7 @@ reg = <0x1450>; }; - usb_host_fs_fck: usb_host_fs_fck { + usb_host_fs_fck: usb_host_fs_fck@13d0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_48mc_fclk>; @@ -1246,7 +1246,7 @@ reg = <0x13d0>; }; - utmi_p1_gfclk: utmi_p1_gfclk { + utmi_p1_gfclk: utmi_p1_gfclk@1358 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&init_60m_fclk>, <&xclk60mhsp1_ck>; @@ -1254,7 +1254,7 @@ reg = <0x1358>; }; - usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk { + usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&utmi_p1_gfclk>; @@ -1262,7 +1262,7 @@ reg = <0x1358>; }; - utmi_p2_gfclk: utmi_p2_gfclk { + utmi_p2_gfclk: utmi_p2_gfclk@1358 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&init_60m_fclk>, <&xclk60mhsp2_ck>; @@ -1270,7 +1270,7 @@ reg = <0x1358>; }; - usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk { + usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&utmi_p2_gfclk>; @@ -1278,7 +1278,7 @@ reg = <0x1358>; }; - usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk { + usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&init_60m_fclk>; @@ -1286,7 +1286,7 @@ reg = <0x1358>; }; - usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk { + usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_usb_m2_ck>; @@ -1294,7 +1294,7 @@ reg = <0x1358>; }; - usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk { + usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&init_60m_fclk>; @@ -1302,7 +1302,7 @@ reg = <0x1358>; }; - usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk { + usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&init_60m_fclk>; @@ -1310,7 +1310,7 @@ reg = <0x1358>; }; - usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk { + usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_usb_m2_ck>; @@ -1318,7 +1318,7 @@ reg = <0x1358>; }; - usb_host_hs_func48mclk: usb_host_hs_func48mclk { + usb_host_hs_func48mclk: usb_host_hs_func48mclk@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_48mc_fclk>; @@ -1326,7 +1326,7 @@ reg = <0x1358>; }; - usb_host_hs_fck: usb_host_hs_fck { + usb_host_hs_fck: usb_host_hs_fck@1358 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&init_60m_fclk>; @@ -1334,7 +1334,7 @@ reg = <0x1358>; }; - otg_60m_gfclk: otg_60m_gfclk { + otg_60m_gfclk: otg_60m_gfclk@1360 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&utmi_phy_clkout_ck>, <&xclk60motg_ck>; @@ -1342,7 +1342,7 @@ reg = <0x1360>; }; - usb_otg_hs_xclk: usb_otg_hs_xclk { + usb_otg_hs_xclk: usb_otg_hs_xclk@1360 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&otg_60m_gfclk>; @@ -1350,7 +1350,7 @@ reg = <0x1360>; }; - usb_otg_hs_ick: usb_otg_hs_ick { + usb_otg_hs_ick: usb_otg_hs_ick@1360 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3_div_ck>; @@ -1358,7 +1358,7 @@ reg = <0x1360>; }; - usb_phy_cm_clk32k: usb_phy_cm_clk32k { + usb_phy_cm_clk32k: usb_phy_cm_clk32k@640 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1366,7 +1366,7 @@ reg = <0x0640>; }; - usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk { + usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk@1368 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&init_60m_fclk>; @@ -1374,7 +1374,7 @@ reg = <0x1368>; }; - usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk { + usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk@1368 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&init_60m_fclk>; @@ -1382,7 +1382,7 @@ reg = <0x1368>; }; - usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk { + usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk@1368 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&init_60m_fclk>; @@ -1390,7 +1390,7 @@ reg = <0x1368>; }; - usb_tll_hs_ick: usb_tll_hs_ick { + usb_tll_hs_ick: usb_tll_hs_ick@1368 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4_div_ck>; @@ -1407,7 +1407,7 @@ }; &scrm_clocks { - auxclk0_src_gate_ck: auxclk0_src_gate_ck { + auxclk0_src_gate_ck: auxclk0_src_gate_ck@310 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1415,7 +1415,7 @@ reg = <0x0310>; }; - auxclk0_src_mux_ck: auxclk0_src_mux_ck { + auxclk0_src_mux_ck: auxclk0_src_mux_ck@310 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1429,7 +1429,7 @@ clocks = <&auxclk0_src_gate_ck>, <&auxclk0_src_mux_ck>; }; - auxclk0_ck: auxclk0_ck { + auxclk0_ck: auxclk0_ck@310 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk0_src_ck>; @@ -1438,7 +1438,7 @@ reg = <0x0310>; }; - auxclk1_src_gate_ck: auxclk1_src_gate_ck { + auxclk1_src_gate_ck: auxclk1_src_gate_ck@314 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1446,7 +1446,7 @@ reg = <0x0314>; }; - auxclk1_src_mux_ck: auxclk1_src_mux_ck { + auxclk1_src_mux_ck: auxclk1_src_mux_ck@314 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1460,7 +1460,7 @@ clocks = <&auxclk1_src_gate_ck>, <&auxclk1_src_mux_ck>; }; - auxclk1_ck: auxclk1_ck { + auxclk1_ck: auxclk1_ck@314 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk1_src_ck>; @@ -1469,7 +1469,7 @@ reg = <0x0314>; }; - auxclk2_src_gate_ck: auxclk2_src_gate_ck { + auxclk2_src_gate_ck: auxclk2_src_gate_ck@318 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1477,7 +1477,7 @@ reg = <0x0318>; }; - auxclk2_src_mux_ck: auxclk2_src_mux_ck { + auxclk2_src_mux_ck: auxclk2_src_mux_ck@318 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1491,7 +1491,7 @@ clocks = <&auxclk2_src_gate_ck>, <&auxclk2_src_mux_ck>; }; - auxclk2_ck: auxclk2_ck { + auxclk2_ck: auxclk2_ck@318 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk2_src_ck>; @@ -1500,7 +1500,7 @@ reg = <0x0318>; }; - auxclk3_src_gate_ck: auxclk3_src_gate_ck { + auxclk3_src_gate_ck: auxclk3_src_gate_ck@31c { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1508,7 +1508,7 @@ reg = <0x031c>; }; - auxclk3_src_mux_ck: auxclk3_src_mux_ck { + auxclk3_src_mux_ck: auxclk3_src_mux_ck@31c { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1522,7 +1522,7 @@ clocks = <&auxclk3_src_gate_ck>, <&auxclk3_src_mux_ck>; }; - auxclk3_ck: auxclk3_ck { + auxclk3_ck: auxclk3_ck@31c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk3_src_ck>; @@ -1531,7 +1531,7 @@ reg = <0x031c>; }; - auxclk4_src_gate_ck: auxclk4_src_gate_ck { + auxclk4_src_gate_ck: auxclk4_src_gate_ck@320 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1539,7 +1539,7 @@ reg = <0x0320>; }; - auxclk4_src_mux_ck: auxclk4_src_mux_ck { + auxclk4_src_mux_ck: auxclk4_src_mux_ck@320 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1553,7 +1553,7 @@ clocks = <&auxclk4_src_gate_ck>, <&auxclk4_src_mux_ck>; }; - auxclk4_ck: auxclk4_ck { + auxclk4_ck: auxclk4_ck@320 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk4_src_ck>; @@ -1562,7 +1562,7 @@ reg = <0x0320>; }; - auxclk5_src_gate_ck: auxclk5_src_gate_ck { + auxclk5_src_gate_ck: auxclk5_src_gate_ck@324 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1570,7 +1570,7 @@ reg = <0x0324>; }; - auxclk5_src_mux_ck: auxclk5_src_mux_ck { + auxclk5_src_mux_ck: auxclk5_src_mux_ck@324 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1584,7 +1584,7 @@ clocks = <&auxclk5_src_gate_ck>, <&auxclk5_src_mux_ck>; }; - auxclk5_ck: auxclk5_ck { + auxclk5_ck: auxclk5_ck@324 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk5_src_ck>; @@ -1593,7 +1593,7 @@ reg = <0x0324>; }; - auxclkreq0_ck: auxclkreq0_ck { + auxclkreq0_ck: auxclkreq0_ck@210 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; @@ -1601,7 +1601,7 @@ reg = <0x0210>; }; - auxclkreq1_ck: auxclkreq1_ck { + auxclkreq1_ck: auxclkreq1_ck@214 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; @@ -1609,7 +1609,7 @@ reg = <0x0214>; }; - auxclkreq2_ck: auxclkreq2_ck { + auxclkreq2_ck: auxclkreq2_ck@218 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; @@ -1617,7 +1617,7 @@ reg = <0x0218>; }; - auxclkreq3_ck: auxclkreq3_ck { + auxclkreq3_ck: auxclkreq3_ck@21c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; @@ -1625,7 +1625,7 @@ reg = <0x021c>; }; - auxclkreq4_ck: auxclkreq4_ck { + auxclkreq4_ck: auxclkreq4_ck@220 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; @@ -1633,7 +1633,7 @@ reg = <0x0220>; }; - auxclkreq5_ck: auxclkreq5_ck { + auxclkreq5_ck: auxclkreq5_ck@224 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; -- GitLab From b524cab33198ea3d7a6deadf44ff93e8b195df15 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:09 +0300 Subject: [PATCH 2006/9938] ARM: dts: am33xx: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for AM33xx clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx-clocks.dtsi | 90 ++++++++++++++-------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/arch/arm/boot/dts/am33xx-clocks.dtsi b/arch/arm/boot/dts/am33xx-clocks.dtsi index afb4b3a7bab4..8d8319590cde 100644 --- a/arch/arm/boot/dts/am33xx-clocks.dtsi +++ b/arch/arm/boot/dts/am33xx-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &scm_clocks { - sys_clkin_ck: sys_clkin_ck { + sys_clkin_ck: sys_clkin_ck@40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; @@ -163,7 +163,7 @@ clock-frequency = <12000000>; }; - dpll_core_ck: dpll_core_ck { + dpll_core_ck: dpll_core_ck@490 { #clock-cells = <0>; compatible = "ti,am3-dpll-core-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; @@ -176,7 +176,7 @@ clocks = <&dpll_core_ck>; }; - dpll_core_m4_ck: dpll_core_m4_ck { + dpll_core_m4_ck: dpll_core_m4_ck@480 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -185,7 +185,7 @@ ti,index-starts-at-one; }; - dpll_core_m5_ck: dpll_core_m5_ck { + dpll_core_m5_ck: dpll_core_m5_ck@484 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -194,7 +194,7 @@ ti,index-starts-at-one; }; - dpll_core_m6_ck: dpll_core_m6_ck { + dpll_core_m6_ck: dpll_core_m6_ck@4d8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -203,14 +203,14 @@ ti,index-starts-at-one; }; - dpll_mpu_ck: dpll_mpu_ck { + dpll_mpu_ck: dpll_mpu_ck@488 { #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x0488>, <0x0420>, <0x042c>; }; - dpll_mpu_m2_ck: dpll_mpu_m2_ck { + dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_mpu_ck>; @@ -219,14 +219,14 @@ ti,index-starts-at-one; }; - dpll_ddr_ck: dpll_ddr_ck { + dpll_ddr_ck: dpll_ddr_ck@494 { #clock-cells = <0>; compatible = "ti,am3-dpll-no-gate-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x0494>, <0x0434>, <0x0440>; }; - dpll_ddr_m2_ck: dpll_ddr_m2_ck { + dpll_ddr_m2_ck: dpll_ddr_m2_ck@4a0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_ddr_ck>; @@ -243,14 +243,14 @@ clock-div = <2>; }; - dpll_disp_ck: dpll_disp_ck { + dpll_disp_ck: dpll_disp_ck@498 { #clock-cells = <0>; compatible = "ti,am3-dpll-no-gate-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x0498>, <0x0448>, <0x0454>; }; - dpll_disp_m2_ck: dpll_disp_m2_ck { + dpll_disp_m2_ck: dpll_disp_m2_ck@4a4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_disp_ck>; @@ -260,14 +260,14 @@ ti,set-rate-parent; }; - dpll_per_ck: dpll_per_ck { + dpll_per_ck: dpll_per_ck@48c { #clock-cells = <0>; compatible = "ti,am3-dpll-no-gate-j-type-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x048c>, <0x0470>, <0x049c>; }; - dpll_per_m2_ck: dpll_per_m2_ck { + dpll_per_m2_ck: dpll_per_m2_ck@4ac { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_ck>; @@ -292,7 +292,7 @@ clock-div = <4>; }; - cefuse_fck: cefuse_fck { + cefuse_fck: cefuse_fck@a20 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_clkin_ck>; @@ -316,7 +316,7 @@ clock-div = <732>; }; - clkdiv32k_ick: clkdiv32k_ick { + clkdiv32k_ick: clkdiv32k_ick@14c { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ck>; @@ -332,14 +332,14 @@ clock-div = <1>; }; - pruss_ocp_gclk: pruss_ocp_gclk { + pruss_ocp_gclk: pruss_ocp_gclk@530 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&l3_gclk>, <&dpll_disp_m2_ck>; reg = <0x0530>; }; - mmu_fck: mmu_fck { + mmu_fck: mmu_fck@914 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_core_m4_ck>; @@ -347,56 +347,56 @@ reg = <0x0914>; }; - timer1_fck: timer1_fck { + timer1_fck: timer1_fck@528 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>; reg = <0x0528>; }; - timer2_fck: timer2_fck { + timer2_fck: timer2_fck@508 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x0508>; }; - timer3_fck: timer3_fck { + timer3_fck: timer3_fck@50c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x050c>; }; - timer4_fck: timer4_fck { + timer4_fck: timer4_fck@510 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x0510>; }; - timer5_fck: timer5_fck { + timer5_fck: timer5_fck@518 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x0518>; }; - timer6_fck: timer6_fck { + timer6_fck: timer6_fck@51c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x051c>; }; - timer7_fck: timer7_fck { + timer7_fck: timer7_fck@504 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x0504>; }; - usbotg_fck: usbotg_fck { + usbotg_fck: usbotg_fck@47c { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_per_ck>; @@ -412,7 +412,7 @@ clock-div = <2>; }; - ieee5000_fck: ieee5000_fck { + ieee5000_fck: ieee5000_fck@e4 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_core_m4_div2_ck>; @@ -420,7 +420,7 @@ reg = <0x00e4>; }; - wdt1_fck: wdt1_fck { + wdt1_fck: wdt1_fck@538 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>; @@ -483,21 +483,21 @@ clock-div = <2>; }; - cpsw_cpts_rft_clk: cpsw_cpts_rft_clk { + cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@520 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_core_m5_ck>, <&dpll_core_m4_ck>; reg = <0x0520>; }; - gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck { + gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@53c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>; reg = <0x053c>; }; - gpio0_dbclk: gpio0_dbclk { + gpio0_dbclk: gpio0_dbclk@408 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&gpio0_dbclk_mux_ck>; @@ -505,7 +505,7 @@ reg = <0x0408>; }; - gpio1_dbclk: gpio1_dbclk { + gpio1_dbclk: gpio1_dbclk@ac { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -513,7 +513,7 @@ reg = <0x00ac>; }; - gpio2_dbclk: gpio2_dbclk { + gpio2_dbclk: gpio2_dbclk@b0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -521,7 +521,7 @@ reg = <0x00b0>; }; - gpio3_dbclk: gpio3_dbclk { + gpio3_dbclk: gpio3_dbclk@b4 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -529,7 +529,7 @@ reg = <0x00b4>; }; - lcd_gclk: lcd_gclk { + lcd_gclk: lcd_gclk@534 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>; @@ -545,7 +545,7 @@ clock-div = <2>; }; - gfx_fclk_clksel_ck: gfx_fclk_clksel_ck { + gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@52c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>; @@ -553,7 +553,7 @@ reg = <0x052c>; }; - gfx_fck_div_ck: gfx_fck_div_ck { + gfx_fck_div_ck: gfx_fck_div_ck@52c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&gfx_fclk_clksel_ck>; @@ -561,14 +561,14 @@ ti,max-div = <2>; }; - sysclkout_pre_ck: sysclkout_pre_ck { + sysclkout_pre_ck: sysclkout_pre_ck@700 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>; reg = <0x0700>; }; - clkout2_div_ck: clkout2_div_ck { + clkout2_div_ck: clkout2_div_ck@700 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sysclkout_pre_ck>; @@ -577,7 +577,7 @@ reg = <0x0700>; }; - dbg_sysclk_ck: dbg_sysclk_ck { + dbg_sysclk_ck: dbg_sysclk_ck@414 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_clkin_ck>; @@ -585,7 +585,7 @@ reg = <0x0414>; }; - dbg_clka_ck: dbg_clka_ck { + dbg_clka_ck: dbg_clka_ck@414 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_core_m4_ck>; @@ -593,7 +593,7 @@ reg = <0x0414>; }; - stm_pmd_clock_mux_ck: stm_pmd_clock_mux_ck { + stm_pmd_clock_mux_ck: stm_pmd_clock_mux_ck@414 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>; @@ -601,7 +601,7 @@ reg = <0x0414>; }; - trace_pmd_clk_mux_ck: trace_pmd_clk_mux_ck { + trace_pmd_clk_mux_ck: trace_pmd_clk_mux_ck@414 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>; @@ -609,7 +609,7 @@ reg = <0x0414>; }; - stm_clk_div_ck: stm_clk_div_ck { + stm_clk_div_ck: stm_clk_div_ck@414 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&stm_pmd_clock_mux_ck>; @@ -619,7 +619,7 @@ ti,index-power-of-two; }; - trace_clk_div_ck: trace_clk_div_ck { + trace_clk_div_ck: trace_clk_div_ck@414 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&trace_pmd_clk_mux_ck>; @@ -629,7 +629,7 @@ ti,index-power-of-two; }; - clkout2_ck: clkout2_ck { + clkout2_ck: clkout2_ck@700 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkout2_div_ck>; -- GitLab From c567048194b3bb65b9e798cadb9b794e6dc66e05 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:10 +0300 Subject: [PATCH 2007/9938] ARM: dts: am43xx: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for AM43xx clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am43xx-clocks.dtsi | 116 +++++++++++++-------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/arch/arm/boot/dts/am43xx-clocks.dtsi b/arch/arm/boot/dts/am43xx-clocks.dtsi index a38af2bfbfcf..34fecf2ddece 100644 --- a/arch/arm/boot/dts/am43xx-clocks.dtsi +++ b/arch/arm/boot/dts/am43xx-clocks.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ &scm_clocks { - sys_clkin_ck: sys_clkin_ck { + sys_clkin_ck: sys_clkin_ck@40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sysboot_freq_sel_ck>, <&crystal_freq_sel_ck>; @@ -16,7 +16,7 @@ reg = <0x0040>; }; - crystal_freq_sel_ck: crystal_freq_sel_ck { + crystal_freq_sel_ck: crystal_freq_sel_ck@40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; @@ -104,7 +104,7 @@ clock-div = <1>; }; - ehrpwm0_tbclk: ehrpwm0_tbclk { + ehrpwm0_tbclk: ehrpwm0_tbclk@664 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4ls_gclk>; @@ -112,7 +112,7 @@ reg = <0x0664>; }; - ehrpwm1_tbclk: ehrpwm1_tbclk { + ehrpwm1_tbclk: ehrpwm1_tbclk@664 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4ls_gclk>; @@ -120,7 +120,7 @@ reg = <0x0664>; }; - ehrpwm2_tbclk: ehrpwm2_tbclk { + ehrpwm2_tbclk: ehrpwm2_tbclk@664 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4ls_gclk>; @@ -128,7 +128,7 @@ reg = <0x0664>; }; - ehrpwm3_tbclk: ehrpwm3_tbclk { + ehrpwm3_tbclk: ehrpwm3_tbclk@664 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4ls_gclk>; @@ -136,7 +136,7 @@ reg = <0x0664>; }; - ehrpwm4_tbclk: ehrpwm4_tbclk { + ehrpwm4_tbclk: ehrpwm4_tbclk@664 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4ls_gclk>; @@ -144,7 +144,7 @@ reg = <0x0664>; }; - ehrpwm5_tbclk: ehrpwm5_tbclk { + ehrpwm5_tbclk: ehrpwm5_tbclk@664 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4ls_gclk>; @@ -195,7 +195,7 @@ clock-frequency = <26000000>; }; - dpll_core_ck: dpll_core_ck { + dpll_core_ck: dpll_core_ck@2d20 { #clock-cells = <0>; compatible = "ti,am3-dpll-core-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; @@ -208,7 +208,7 @@ clocks = <&dpll_core_ck>; }; - dpll_core_m4_ck: dpll_core_m4_ck { + dpll_core_m4_ck: dpll_core_m4_ck@2d38 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -219,7 +219,7 @@ ti,invert-autoidle-bit; }; - dpll_core_m5_ck: dpll_core_m5_ck { + dpll_core_m5_ck: dpll_core_m5_ck@2d3c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -230,7 +230,7 @@ ti,invert-autoidle-bit; }; - dpll_core_m6_ck: dpll_core_m6_ck { + dpll_core_m6_ck: dpll_core_m6_ck@2d40 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -241,14 +241,14 @@ ti,invert-autoidle-bit; }; - dpll_mpu_ck: dpll_mpu_ck { + dpll_mpu_ck: dpll_mpu_ck@2d60 { #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x2d60>, <0x2d64>, <0x2d6c>; }; - dpll_mpu_m2_ck: dpll_mpu_m2_ck { + dpll_mpu_m2_ck: dpll_mpu_m2_ck@2d70 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_mpu_ck>; @@ -267,14 +267,14 @@ clock-div = <2>; }; - dpll_ddr_ck: dpll_ddr_ck { + dpll_ddr_ck: dpll_ddr_ck@2da0 { #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x2da0>, <0x2da4>, <0x2dac>; }; - dpll_ddr_m2_ck: dpll_ddr_m2_ck { + dpll_ddr_m2_ck: dpll_ddr_m2_ck@2db0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_ddr_ck>; @@ -285,14 +285,14 @@ ti,invert-autoidle-bit; }; - dpll_disp_ck: dpll_disp_ck { + dpll_disp_ck: dpll_disp_ck@2e20 { #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x2e20>, <0x2e24>, <0x2e2c>; }; - dpll_disp_m2_ck: dpll_disp_m2_ck { + dpll_disp_m2_ck: dpll_disp_m2_ck@2e30 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_disp_ck>; @@ -304,14 +304,14 @@ ti,set-rate-parent; }; - dpll_per_ck: dpll_per_ck { + dpll_per_ck: dpll_per_ck@2de0 { #clock-cells = <0>; compatible = "ti,am3-dpll-j-type-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x2de0>, <0x2de4>, <0x2dec>; }; - dpll_per_m2_ck: dpll_per_m2_ck { + dpll_per_m2_ck: dpll_per_m2_ck@2df0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_ck>; @@ -354,7 +354,7 @@ clock-div = <732>; }; - clkdiv32k_ick: clkdiv32k_ick { + clkdiv32k_ick: clkdiv32k_ick@2a38 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ck>; @@ -370,7 +370,7 @@ clock-div = <1>; }; - pruss_ocp_gclk: pruss_ocp_gclk { + pruss_ocp_gclk: pruss_ocp_gclk@4248 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sysclk_div>, <&dpll_disp_m2_ck>; @@ -383,56 +383,56 @@ clock-frequency = <32768>; }; - timer1_fck: timer1_fck { + timer1_fck: timer1_fck@4200 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>, <&clk_32k_tpm_ck>; reg = <0x4200>; }; - timer2_fck: timer2_fck { + timer2_fck: timer2_fck@4204 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x4204>; }; - timer3_fck: timer3_fck { + timer3_fck: timer3_fck@4208 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x4208>; }; - timer4_fck: timer4_fck { + timer4_fck: timer4_fck@420c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x420c>; }; - timer5_fck: timer5_fck { + timer5_fck: timer5_fck@4210 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x4210>; }; - timer6_fck: timer6_fck { + timer6_fck: timer6_fck@4214 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x4214>; }; - timer7_fck: timer7_fck { + timer7_fck: timer7_fck@4218 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; reg = <0x4218>; }; - wdt1_fck: wdt1_fck { + wdt1_fck: wdt1_fck@422c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>; @@ -487,14 +487,14 @@ clock-div = <2>; }; - cpsw_cpts_rft_clk: cpsw_cpts_rft_clk { + cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@4238 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sysclk_div>, <&dpll_core_m5_ck>, <&dpll_disp_m2_ck>; reg = <0x4238>; }; - dpll_clksel_mac_clk: dpll_clksel_mac_clk { + dpll_clksel_mac_clk: dpll_clksel_mac_clk@4234 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_m5_ck>; @@ -509,14 +509,14 @@ clock-frequency = <32768>; }; - gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck { + gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@4240 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>, <&clk_32k_mosc_ck>, <&clk_32k_tpm_ck>; reg = <0x4240>; }; - gpio0_dbclk: gpio0_dbclk { + gpio0_dbclk: gpio0_dbclk@2b68 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&gpio0_dbclk_mux_ck>; @@ -524,7 +524,7 @@ reg = <0x2b68>; }; - gpio1_dbclk: gpio1_dbclk { + gpio1_dbclk: gpio1_dbclk@8c78 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -532,7 +532,7 @@ reg = <0x8c78>; }; - gpio2_dbclk: gpio2_dbclk { + gpio2_dbclk: gpio2_dbclk@8c80 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -540,7 +540,7 @@ reg = <0x8c80>; }; - gpio3_dbclk: gpio3_dbclk { + gpio3_dbclk: gpio3_dbclk@8c88 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -548,7 +548,7 @@ reg = <0x8c88>; }; - gpio4_dbclk: gpio4_dbclk { + gpio4_dbclk: gpio4_dbclk@8c90 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -556,7 +556,7 @@ reg = <0x8c90>; }; - gpio5_dbclk: gpio5_dbclk { + gpio5_dbclk: gpio5_dbclk@8c98 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkdiv32k_ick>; @@ -572,7 +572,7 @@ clock-div = <2>; }; - gfx_fclk_clksel_ck: gfx_fclk_clksel_ck { + gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@423c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sysclk_div>, <&dpll_per_m2_ck>; @@ -580,7 +580,7 @@ reg = <0x423c>; }; - gfx_fck_div_ck: gfx_fck_div_ck { + gfx_fck_div_ck: gfx_fck_div_ck@423c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&gfx_fclk_clksel_ck>; @@ -588,7 +588,7 @@ ti,max-div = <2>; }; - disp_clk: disp_clk { + disp_clk: disp_clk@4244 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>; @@ -596,14 +596,14 @@ ti,set-rate-parent; }; - dpll_extdev_ck: dpll_extdev_ck { + dpll_extdev_ck: dpll_extdev_ck@2e60 { #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; reg = <0x2e60>, <0x2e64>, <0x2e6c>; }; - dpll_extdev_m2_ck: dpll_extdev_m2_ck { + dpll_extdev_m2_ck: dpll_extdev_m2_ck@2e70 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_extdev_ck>; @@ -614,14 +614,14 @@ ti,invert-autoidle-bit; }; - mux_synctimer32k_ck: mux_synctimer32k_ck { + mux_synctimer32k_ck: mux_synctimer32k_ck@4230 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>, <&clkdiv32k_ick>; reg = <0x4230>; }; - synctimer_32kclk: synctimer_32kclk { + synctimer_32kclk: synctimer_32kclk@2a30 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&mux_synctimer32k_ck>; @@ -629,28 +629,28 @@ reg = <0x2a30>; }; - timer8_fck: timer8_fck { + timer8_fck: timer8_fck@421c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; reg = <0x421c>; }; - timer9_fck: timer9_fck { + timer9_fck: timer9_fck@4220 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; reg = <0x4220>; }; - timer10_fck: timer10_fck { + timer10_fck: timer10_fck@4224 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; reg = <0x4224>; }; - timer11_fck: timer11_fck { + timer11_fck: timer11_fck@4228 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; @@ -679,7 +679,7 @@ clocks = <&dpll_ddr_ck>; }; - dpll_ddr_m4_ck: dpll_ddr_m4_ck { + dpll_ddr_m4_ck: dpll_ddr_m4_ck@2db8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_ddr_x2_ck>; @@ -690,7 +690,7 @@ ti,invert-autoidle-bit; }; - dpll_per_clkdcoldo: dpll_per_clkdcoldo { + dpll_per_clkdcoldo: dpll_per_clkdcoldo@2e14 { #clock-cells = <0>; compatible = "ti,fixed-factor-clock"; clocks = <&dpll_per_ck>; @@ -701,7 +701,7 @@ ti,invert-autoidle-bit; }; - dll_aging_clk_div: dll_aging_clk_div { + dll_aging_clk_div: dll_aging_clk_div@4250 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin_ck>; @@ -733,14 +733,14 @@ clock-div = <2>; }; - usbphy_32khz_clkmux: usbphy_32khz_clkmux { + usbphy_32khz_clkmux: usbphy_32khz_clkmux@4260 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>; reg = <0x4260>; }; - usb_phy0_always_on_clk32k: usb_phy0_always_on_clk32k { + usb_phy0_always_on_clk32k: usb_phy0_always_on_clk32k@2a40 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&usbphy_32khz_clkmux>; @@ -748,7 +748,7 @@ reg = <0x2a40>; }; - usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k { + usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k@2a48 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&usbphy_32khz_clkmux>; @@ -756,7 +756,7 @@ reg = <0x2a48>; }; - usb_otg_ss0_refclk960m: usb_otg_ss0_refclk960m { + usb_otg_ss0_refclk960m: usb_otg_ss0_refclk960m@8a60 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_per_clkdcoldo>; @@ -764,7 +764,7 @@ reg = <0x8a60>; }; - usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m { + usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m@8a68 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_per_clkdcoldo>; -- GitLab From 5c440a775e5cb5e5de815771589b252a2dd08e70 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:11 +0300 Subject: [PATCH 2008/9938] ARM: dts: dm81x: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for DM81x clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dm814x-clocks.dtsi | 10 +++---- arch/arm/boot/dts/dm816x-clocks.dtsi | 42 ++++++++++++++-------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/arch/arm/boot/dts/dm814x-clocks.dtsi b/arch/arm/boot/dts/dm814x-clocks.dtsi index e0ea6a93a22e..1e70f7313e1e 100644 --- a/arch/arm/boot/dts/dm814x-clocks.dtsi +++ b/arch/arm/boot/dts/dm814x-clocks.dtsi @@ -5,7 +5,7 @@ */ &pllss_clocks { - timer1_fck: timer1_fck { + timer1_fck: timer1_fck@2e0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sysclk18_ck &aud_clkin0_ck &aud_clkin1_ck @@ -14,7 +14,7 @@ reg = <0x2e0>; }; - timer2_fck: timer2_fck { + timer2_fck: timer2_fck@2e0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sysclk18_ck &aud_clkin0_ck &aud_clkin1_ck @@ -23,7 +23,7 @@ reg = <0x2e0>; }; - sysclk18_ck: sysclk18_ck { + sysclk18_ck: sysclk18_ck@2f0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&rtcosc_ck>, <&rtcdivider_ck>; @@ -33,7 +33,7 @@ }; &scm_clocks { - devosc_ck: devosc_ck { + devosc_ck: devosc_ck@40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_20000000_ck>, <&virt_19200000_ck>; @@ -121,7 +121,7 @@ clock-div = <1>; }; - mpu_clksrc_ck: mpu_clksrc_ck { + mpu_clksrc_ck: mpu_clksrc_ck@40 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&devosc_ck>, <&rtcdivider_ck>; diff --git a/arch/arm/boot/dts/dm816x-clocks.dtsi b/arch/arm/boot/dts/dm816x-clocks.dtsi index 50d9d338fbe9..51865eb84a80 100644 --- a/arch/arm/boot/dts/dm816x-clocks.dtsi +++ b/arch/arm/boot/dts/dm816x-clocks.dtsi @@ -86,7 +86,7 @@ /* 0x48180000 */ &prcm_clocks { - clkout_pre_ck: clkout_pre_ck { + clkout_pre_ck: clkout_pre_ck@100 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&main_fapll 5 &ddr_fapll 1 &video_fapll 1 @@ -94,7 +94,7 @@ reg = <0x100>; }; - clkout_div_ck: clkout_div_ck { + clkout_div_ck: clkout_div_ck@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&clkout_pre_ck>; @@ -103,7 +103,7 @@ reg = <0x100>; }; - clkout_ck: clkout_ck { + clkout_ck: clkout_ck@100 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkout_div_ck>; @@ -112,7 +112,7 @@ }; /* CM_DPLL clocks p1795 */ - sysclk1_ck: sysclk1_ck { + sysclk1_ck: sysclk1_ck@300 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&main_fapll 1>; @@ -120,7 +120,7 @@ reg = <0x0300>; }; - sysclk2_ck: sysclk2_ck { + sysclk2_ck: sysclk2_ck@304 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&main_fapll 2>; @@ -128,7 +128,7 @@ reg = <0x0304>; }; - sysclk3_ck: sysclk3_ck { + sysclk3_ck: sysclk3_ck@308 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&main_fapll 3>; @@ -136,7 +136,7 @@ reg = <0x0308>; }; - sysclk4_ck: sysclk4_ck { + sysclk4_ck: sysclk4_ck@30c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&main_fapll 4>; @@ -144,7 +144,7 @@ reg = <0x030c>; }; - sysclk5_ck: sysclk5_ck { + sysclk5_ck: sysclk5_ck@310 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sysclk4_ck>; @@ -152,7 +152,7 @@ reg = <0x0310>; }; - sysclk6_ck: sysclk6_ck { + sysclk6_ck: sysclk6_ck@314 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&main_fapll 4>; @@ -160,7 +160,7 @@ reg = <0x0314>; }; - sysclk10_ck: sysclk10_ck { + sysclk10_ck: sysclk10_ck@324 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&ddr_fapll 2>; @@ -168,7 +168,7 @@ reg = <0x0324>; }; - sysclk24_ck: sysclk24_ck { + sysclk24_ck: sysclk24_ck@3b4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&main_fapll 5>; @@ -176,7 +176,7 @@ reg = <0x03b4>; }; - mpu_ck: mpu_ck { + mpu_ck: mpu_ck@15dc { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sysclk2_ck>; @@ -184,7 +184,7 @@ reg = <0x15dc>; }; - audio_pll_a_ck: audio_pll_a_ck { + audio_pll_a_ck: audio_pll_a_ck@35c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&audio_fapll 1>; @@ -192,56 +192,56 @@ reg = <0x035c>; }; - sysclk18_ck: sysclk18_ck { + sysclk18_ck: sysclk18_ck@378 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_32k_ck>, <&audio_pll_a_ck>; reg = <0x0378>; }; - timer1_fck: timer1_fck { + timer1_fck: timer1_fck@390 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>; reg = <0x0390>; }; - timer2_fck: timer2_fck { + timer2_fck: timer2_fck@394 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>; reg = <0x0394>; }; - timer3_fck: timer3_fck { + timer3_fck: timer3_fck@398 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>; reg = <0x0398>; }; - timer4_fck: timer4_fck { + timer4_fck: timer4_fck@39c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>; reg = <0x039c>; }; - timer5_fck: timer5_fck { + timer5_fck: timer5_fck@3a0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>; reg = <0x03a0>; }; - timer6_fck: timer6_fck { + timer6_fck: timer6_fck@3a4 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>; reg = <0x03a4>; }; - timer7_fck: timer7_fck { + timer7_fck: timer7_fck@3a8 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>; -- GitLab From ca8a3d4edcc37d06a3d71645e80923dd9d3c44eb Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:12 +0300 Subject: [PATCH 2009/9938] ARM: dts: dra7: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for DRA7 clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7xx-clocks.dtsi | 376 +++++++++++++-------------- 1 file changed, 188 insertions(+), 188 deletions(-) diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi index d0bae06b7eb7..c437c5cb3af4 100644 --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi @@ -188,7 +188,7 @@ clock-frequency = <0>; }; - dpll_abe_ck: dpll_abe_ck { + dpll_abe_ck: dpll_abe_ck@1e0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-m4xen-clock"; clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>; @@ -201,7 +201,7 @@ clocks = <&dpll_abe_ck>; }; - dpll_abe_m2x2_ck: dpll_abe_m2x2_ck { + dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@1f0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_x2_ck>; @@ -212,7 +212,7 @@ ti,invert-autoidle-bit; }; - abe_clk: abe_clk { + abe_clk: abe_clk@108 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2x2_ck>; @@ -221,7 +221,7 @@ ti,index-power-of-two; }; - dpll_abe_m2_ck: dpll_abe_m2_ck { + dpll_abe_m2_ck: dpll_abe_m2_ck@1f0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_ck>; @@ -232,7 +232,7 @@ ti,invert-autoidle-bit; }; - dpll_abe_m3x2_ck: dpll_abe_m3x2_ck { + dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@1f4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_x2_ck>; @@ -243,7 +243,7 @@ ti,invert-autoidle-bit; }; - dpll_core_byp_mux: dpll_core_byp_mux { + dpll_core_byp_mux: dpll_core_byp_mux@12c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; @@ -251,7 +251,7 @@ reg = <0x012c>; }; - dpll_core_ck: dpll_core_ck { + dpll_core_ck: dpll_core_ck@120 { #clock-cells = <0>; compatible = "ti,omap4-dpll-core-clock"; clocks = <&sys_clkin1>, <&dpll_core_byp_mux>; @@ -264,7 +264,7 @@ clocks = <&dpll_core_ck>; }; - dpll_core_h12x2_ck: dpll_core_h12x2_ck { + dpll_core_h12x2_ck: dpll_core_h12x2_ck@13c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -283,14 +283,14 @@ clock-div = <1>; }; - dpll_mpu_ck: dpll_mpu_ck { + dpll_mpu_ck: dpll_mpu_ck@160 { #clock-cells = <0>; compatible = "ti,omap5-mpu-dpll-clock"; clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>; reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; }; - dpll_mpu_m2_ck: dpll_mpu_m2_ck { + dpll_mpu_m2_ck: dpll_mpu_m2_ck@170 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_mpu_ck>; @@ -317,7 +317,7 @@ clock-div = <1>; }; - dpll_dsp_byp_mux: dpll_dsp_byp_mux { + dpll_dsp_byp_mux: dpll_dsp_byp_mux@240 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; @@ -325,14 +325,14 @@ reg = <0x0240>; }; - dpll_dsp_ck: dpll_dsp_ck { + dpll_dsp_ck: dpll_dsp_ck@234 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&dpll_dsp_byp_mux>; reg = <0x0234>, <0x0238>, <0x0240>, <0x023c>; }; - dpll_dsp_m2_ck: dpll_dsp_m2_ck { + dpll_dsp_m2_ck: dpll_dsp_m2_ck@244 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_dsp_ck>; @@ -351,7 +351,7 @@ clock-div = <1>; }; - dpll_iva_byp_mux: dpll_iva_byp_mux { + dpll_iva_byp_mux: dpll_iva_byp_mux@1ac { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; @@ -359,14 +359,14 @@ reg = <0x01ac>; }; - dpll_iva_ck: dpll_iva_ck { + dpll_iva_ck: dpll_iva_ck@1a0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&dpll_iva_byp_mux>; reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>; }; - dpll_iva_m2_ck: dpll_iva_m2_ck { + dpll_iva_m2_ck: dpll_iva_m2_ck@1b0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_iva_ck>; @@ -385,7 +385,7 @@ clock-div = <1>; }; - dpll_gpu_byp_mux: dpll_gpu_byp_mux { + dpll_gpu_byp_mux: dpll_gpu_byp_mux@2e4 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; @@ -393,14 +393,14 @@ reg = <0x02e4>; }; - dpll_gpu_ck: dpll_gpu_ck { + dpll_gpu_ck: dpll_gpu_ck@2d8 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&dpll_gpu_byp_mux>; reg = <0x02d8>, <0x02dc>, <0x02e4>, <0x02e0>; }; - dpll_gpu_m2_ck: dpll_gpu_m2_ck { + dpll_gpu_m2_ck: dpll_gpu_m2_ck@2e8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gpu_ck>; @@ -411,7 +411,7 @@ ti,invert-autoidle-bit; }; - dpll_core_m2_ck: dpll_core_m2_ck { + dpll_core_m2_ck: dpll_core_m2_ck@130 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_ck>; @@ -430,7 +430,7 @@ clock-div = <1>; }; - dpll_ddr_byp_mux: dpll_ddr_byp_mux { + dpll_ddr_byp_mux: dpll_ddr_byp_mux@21c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; @@ -438,14 +438,14 @@ reg = <0x021c>; }; - dpll_ddr_ck: dpll_ddr_ck { + dpll_ddr_ck: dpll_ddr_ck@210 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&dpll_ddr_byp_mux>; reg = <0x0210>, <0x0214>, <0x021c>, <0x0218>; }; - dpll_ddr_m2_ck: dpll_ddr_m2_ck { + dpll_ddr_m2_ck: dpll_ddr_m2_ck@220 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_ddr_ck>; @@ -456,7 +456,7 @@ ti,invert-autoidle-bit; }; - dpll_gmac_byp_mux: dpll_gmac_byp_mux { + dpll_gmac_byp_mux: dpll_gmac_byp_mux@2b4 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; @@ -464,14 +464,14 @@ reg = <0x02b4>; }; - dpll_gmac_ck: dpll_gmac_ck { + dpll_gmac_ck: dpll_gmac_ck@2a8 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&dpll_gmac_byp_mux>; reg = <0x02a8>, <0x02ac>, <0x02b4>, <0x02b0>; }; - dpll_gmac_m2_ck: dpll_gmac_m2_ck { + dpll_gmac_m2_ck: dpll_gmac_m2_ck@2b8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gmac_ck>; @@ -530,7 +530,7 @@ clock-div = <1>; }; - dpll_eve_byp_mux: dpll_eve_byp_mux { + dpll_eve_byp_mux: dpll_eve_byp_mux@290 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; @@ -538,14 +538,14 @@ reg = <0x0290>; }; - dpll_eve_ck: dpll_eve_ck { + dpll_eve_ck: dpll_eve_ck@284 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&dpll_eve_byp_mux>; reg = <0x0284>, <0x0288>, <0x0290>, <0x028c>; }; - dpll_eve_m2_ck: dpll_eve_m2_ck { + dpll_eve_m2_ck: dpll_eve_m2_ck@294 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_eve_ck>; @@ -564,7 +564,7 @@ clock-div = <1>; }; - dpll_core_h13x2_ck: dpll_core_h13x2_ck { + dpll_core_h13x2_ck: dpll_core_h13x2_ck@140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -575,7 +575,7 @@ ti,invert-autoidle-bit; }; - dpll_core_h14x2_ck: dpll_core_h14x2_ck { + dpll_core_h14x2_ck: dpll_core_h14x2_ck@144 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -586,7 +586,7 @@ ti,invert-autoidle-bit; }; - dpll_core_h22x2_ck: dpll_core_h22x2_ck { + dpll_core_h22x2_ck: dpll_core_h22x2_ck@154 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -597,7 +597,7 @@ ti,invert-autoidle-bit; }; - dpll_core_h23x2_ck: dpll_core_h23x2_ck { + dpll_core_h23x2_ck: dpll_core_h23x2_ck@158 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -608,7 +608,7 @@ ti,invert-autoidle-bit; }; - dpll_core_h24x2_ck: dpll_core_h24x2_ck { + dpll_core_h24x2_ck: dpll_core_h24x2_ck@15c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -625,7 +625,7 @@ clocks = <&dpll_ddr_ck>; }; - dpll_ddr_h11x2_ck: dpll_ddr_h11x2_ck { + dpll_ddr_h11x2_ck: dpll_ddr_h11x2_ck@228 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_ddr_x2_ck>; @@ -642,7 +642,7 @@ clocks = <&dpll_dsp_ck>; }; - dpll_dsp_m3x2_ck: dpll_dsp_m3x2_ck { + dpll_dsp_m3x2_ck: dpll_dsp_m3x2_ck@248 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_dsp_x2_ck>; @@ -659,7 +659,7 @@ clocks = <&dpll_gmac_ck>; }; - dpll_gmac_h11x2_ck: dpll_gmac_h11x2_ck { + dpll_gmac_h11x2_ck: dpll_gmac_h11x2_ck@2c0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gmac_x2_ck>; @@ -670,7 +670,7 @@ ti,invert-autoidle-bit; }; - dpll_gmac_h12x2_ck: dpll_gmac_h12x2_ck { + dpll_gmac_h12x2_ck: dpll_gmac_h12x2_ck@2c4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gmac_x2_ck>; @@ -681,7 +681,7 @@ ti,invert-autoidle-bit; }; - dpll_gmac_h13x2_ck: dpll_gmac_h13x2_ck { + dpll_gmac_h13x2_ck: dpll_gmac_h13x2_ck@2c8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gmac_x2_ck>; @@ -692,7 +692,7 @@ ti,invert-autoidle-bit; }; - dpll_gmac_m3x2_ck: dpll_gmac_m3x2_ck { + dpll_gmac_m3x2_ck: dpll_gmac_m3x2_ck@2bc { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gmac_x2_ck>; @@ -727,7 +727,7 @@ clock-div = <1>; }; - l3_iclk_div: l3_iclk_div { + l3_iclk_div: l3_iclk_div@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; ti,max-div = <2>; @@ -777,7 +777,7 @@ clock-div = <1>; }; - ipu1_gfclk_mux: ipu1_gfclk_mux { + ipu1_gfclk_mux: ipu1_gfclk_mux@520 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>; @@ -785,7 +785,7 @@ reg = <0x0520>; }; - mcasp1_ahclkr_mux: mcasp1_ahclkr_mux { + mcasp1_ahclkr_mux: mcasp1_ahclkr_mux@550 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -793,7 +793,7 @@ reg = <0x0550>; }; - mcasp1_ahclkx_mux: mcasp1_ahclkx_mux { + mcasp1_ahclkx_mux: mcasp1_ahclkx_mux@550 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -801,7 +801,7 @@ reg = <0x0550>; }; - mcasp1_aux_gfclk_mux: mcasp1_aux_gfclk_mux { + mcasp1_aux_gfclk_mux: mcasp1_aux_gfclk_mux@550 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -809,7 +809,7 @@ reg = <0x0550>; }; - timer5_gfclk_mux: timer5_gfclk_mux { + timer5_gfclk_mux: timer5_gfclk_mux@558 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; @@ -817,7 +817,7 @@ reg = <0x0558>; }; - timer6_gfclk_mux: timer6_gfclk_mux { + timer6_gfclk_mux: timer6_gfclk_mux@560 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; @@ -825,7 +825,7 @@ reg = <0x0560>; }; - timer7_gfclk_mux: timer7_gfclk_mux { + timer7_gfclk_mux: timer7_gfclk_mux@568 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; @@ -833,7 +833,7 @@ reg = <0x0568>; }; - timer8_gfclk_mux: timer8_gfclk_mux { + timer8_gfclk_mux: timer8_gfclk_mux@570 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; @@ -841,7 +841,7 @@ reg = <0x0570>; }; - uart6_gfclk_mux: uart6_gfclk_mux { + uart6_gfclk_mux: uart6_gfclk_mux@580 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -856,7 +856,7 @@ }; }; &prm_clocks { - sys_clkin1: sys_clkin1 { + sys_clkin1: sys_clkin1@110 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_12000000_ck>, <&virt_20000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>; @@ -864,28 +864,28 @@ ti,index-starts-at-one; }; - abe_dpll_sys_clk_mux: abe_dpll_sys_clk_mux { + abe_dpll_sys_clk_mux: abe_dpll_sys_clk_mux@118 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&sys_clkin2>; reg = <0x0118>; }; - abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux { + abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux@114 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>; reg = <0x0114>; }; - abe_dpll_clk_mux: abe_dpll_clk_mux { + abe_dpll_clk_mux: abe_dpll_clk_mux@10c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>; reg = <0x010c>; }; - abe_24m_fclk: abe_24m_fclk { + abe_24m_fclk: abe_24m_fclk@11c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2x2_ck>; @@ -893,7 +893,7 @@ ti,dividers = <8>, <16>; }; - aess_fclk: aess_fclk { + aess_fclk: aess_fclk@178 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&abe_clk>; @@ -901,7 +901,7 @@ ti,max-div = <2>; }; - abe_giclk_div: abe_giclk_div { + abe_giclk_div: abe_giclk_div@174 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&aess_fclk>; @@ -909,7 +909,7 @@ ti,max-div = <2>; }; - abe_lp_clk_div: abe_lp_clk_div { + abe_lp_clk_div: abe_lp_clk_div@1d8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2x2_ck>; @@ -917,7 +917,7 @@ ti,dividers = <16>, <32>; }; - abe_sys_clk_div: abe_sys_clk_div { + abe_sys_clk_div: abe_sys_clk_div@120 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin1>; @@ -925,14 +925,14 @@ ti,max-div = <2>; }; - adc_gfclk_mux: adc_gfclk_mux { + adc_gfclk_mux: adc_gfclk_mux@1dc { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&sys_clkin2>, <&sys_32k_ck>; reg = <0x01dc>; }; - sys_clk1_dclk_div: sys_clk1_dclk_div { + sys_clk1_dclk_div: sys_clk1_dclk_div@1c8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin1>; @@ -941,7 +941,7 @@ ti,index-power-of-two; }; - sys_clk2_dclk_div: sys_clk2_dclk_div { + sys_clk2_dclk_div: sys_clk2_dclk_div@1cc { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin2>; @@ -950,7 +950,7 @@ ti,index-power-of-two; }; - per_abe_x1_dclk_div: per_abe_x1_dclk_div { + per_abe_x1_dclk_div: per_abe_x1_dclk_div@1bc { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2_ck>; @@ -959,7 +959,7 @@ ti,index-power-of-two; }; - dsp_gclk_div: dsp_gclk_div { + dsp_gclk_div: dsp_gclk_div@18c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_dsp_m2_ck>; @@ -968,7 +968,7 @@ ti,index-power-of-two; }; - gpu_dclk: gpu_dclk { + gpu_dclk: gpu_dclk@1a0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gpu_m2_ck>; @@ -977,7 +977,7 @@ ti,index-power-of-two; }; - emif_phy_dclk_div: emif_phy_dclk_div { + emif_phy_dclk_div: emif_phy_dclk_div@190 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_ddr_m2_ck>; @@ -986,7 +986,7 @@ ti,index-power-of-two; }; - gmac_250m_dclk_div: gmac_250m_dclk_div { + gmac_250m_dclk_div: gmac_250m_dclk_div@19c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gmac_m2_ck>; @@ -995,7 +995,7 @@ ti,index-power-of-two; }; - l3init_480m_dclk_div: l3init_480m_dclk_div { + l3init_480m_dclk_div: l3init_480m_dclk_div@1ac { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_usb_m2_ck>; @@ -1004,7 +1004,7 @@ ti,index-power-of-two; }; - usb_otg_dclk_div: usb_otg_dclk_div { + usb_otg_dclk_div: usb_otg_dclk_div@184 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&usb_otg_clkin_ck>; @@ -1013,7 +1013,7 @@ ti,index-power-of-two; }; - sata_dclk_div: sata_dclk_div { + sata_dclk_div: sata_dclk_div@1c0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin1>; @@ -1022,7 +1022,7 @@ ti,index-power-of-two; }; - pcie2_dclk_div: pcie2_dclk_div { + pcie2_dclk_div: pcie2_dclk_div@1b8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_pcie_ref_m2_ck>; @@ -1031,7 +1031,7 @@ ti,index-power-of-two; }; - pcie_dclk_div: pcie_dclk_div { + pcie_dclk_div: pcie_dclk_div@1b4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&apll_pcie_m2_ck>; @@ -1040,7 +1040,7 @@ ti,index-power-of-two; }; - emu_dclk_div: emu_dclk_div { + emu_dclk_div: emu_dclk_div@194 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin1>; @@ -1049,7 +1049,7 @@ ti,index-power-of-two; }; - secure_32k_dclk_div: secure_32k_dclk_div { + secure_32k_dclk_div: secure_32k_dclk_div@1c4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&secure_32k_clk_src_ck>; @@ -1058,21 +1058,21 @@ ti,index-power-of-two; }; - clkoutmux0_clk_mux: clkoutmux0_clk_mux { + clkoutmux0_clk_mux: clkoutmux0_clk_mux@158 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>; reg = <0x0158>; }; - clkoutmux1_clk_mux: clkoutmux1_clk_mux { + clkoutmux1_clk_mux: clkoutmux1_clk_mux@15c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>; reg = <0x015c>; }; - clkoutmux2_clk_mux: clkoutmux2_clk_mux { + clkoutmux2_clk_mux: clkoutmux2_clk_mux@160 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>; @@ -1087,21 +1087,21 @@ clock-div = <2>; }; - eve_clk: eve_clk { + eve_clk: eve_clk@180 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_eve_m2_ck>, <&dpll_dsp_m3x2_ck>; reg = <0x0180>; }; - hdmi_dpll_clk_mux: hdmi_dpll_clk_mux { + hdmi_dpll_clk_mux: hdmi_dpll_clk_mux@164 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&sys_clkin2>; reg = <0x0164>; }; - mlb_clk: mlb_clk { + mlb_clk: mlb_clk@134 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mlb_clkin_ck>; @@ -1110,7 +1110,7 @@ ti,index-power-of-two; }; - mlbp_clk: mlbp_clk { + mlbp_clk: mlbp_clk@130 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mlbp_clkin_ck>; @@ -1119,7 +1119,7 @@ ti,index-power-of-two; }; - per_abe_x1_gfclk2_div: per_abe_x1_gfclk2_div { + per_abe_x1_gfclk2_div: per_abe_x1_gfclk2_div@138 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2_ck>; @@ -1128,7 +1128,7 @@ ti,index-power-of-two; }; - timer_sys_clk_div: timer_sys_clk_div { + timer_sys_clk_div: timer_sys_clk_div@144 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&sys_clkin1>; @@ -1136,28 +1136,28 @@ ti,max-div = <2>; }; - video1_dpll_clk_mux: video1_dpll_clk_mux { + video1_dpll_clk_mux: video1_dpll_clk_mux@168 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&sys_clkin2>; reg = <0x0168>; }; - video2_dpll_clk_mux: video2_dpll_clk_mux { + video2_dpll_clk_mux: video2_dpll_clk_mux@16c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&sys_clkin2>; reg = <0x016c>; }; - wkupaon_iclk_mux: wkupaon_iclk_mux { + wkupaon_iclk_mux: wkupaon_iclk_mux@108 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&abe_lp_clk_div>; reg = <0x0108>; }; - gpio1_dbclk: gpio1_dbclk { + gpio1_dbclk: gpio1_dbclk@1838 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1165,7 +1165,7 @@ reg = <0x1838>; }; - dcan1_sys_clk_mux: dcan1_sys_clk_mux { + dcan1_sys_clk_mux: dcan1_sys_clk_mux@1888 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&sys_clkin2>; @@ -1173,7 +1173,7 @@ reg = <0x1888>; }; - timer1_gfclk_mux: timer1_gfclk_mux { + timer1_gfclk_mux: timer1_gfclk_mux@1840 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -1181,7 +1181,7 @@ reg = <0x1840>; }; - uart10_gfclk_mux: uart10_gfclk_mux { + uart10_gfclk_mux: uart10_gfclk_mux@1880 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -1190,14 +1190,14 @@ }; }; &cm_core_clocks { - dpll_pcie_ref_ck: dpll_pcie_ref_ck { + dpll_pcie_ref_ck: dpll_pcie_ref_ck@200 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&sys_clkin1>; reg = <0x0200>, <0x0204>, <0x020c>, <0x0208>; }; - dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck { + dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck@210 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_pcie_ref_ck>; @@ -1216,7 +1216,7 @@ ti,bit-shift = <7>; }; - apll_pcie_ck: apll_pcie_ck { + apll_pcie_ck: apll_pcie_ck@21c { #clock-cells = <0>; compatible = "ti,dra7-apll-clock"; clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>; @@ -1305,7 +1305,7 @@ clock-div = <1>; }; - dpll_per_byp_mux: dpll_per_byp_mux { + dpll_per_byp_mux: dpll_per_byp_mux@14c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; @@ -1313,14 +1313,14 @@ reg = <0x014c>; }; - dpll_per_ck: dpll_per_ck { + dpll_per_ck: dpll_per_ck@140 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin1>, <&dpll_per_byp_mux>; reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>; }; - dpll_per_m2_ck: dpll_per_m2_ck { + dpll_per_m2_ck: dpll_per_m2_ck@150 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_ck>; @@ -1339,7 +1339,7 @@ clock-div = <1>; }; - dpll_usb_byp_mux: dpll_usb_byp_mux { + dpll_usb_byp_mux: dpll_usb_byp_mux@18c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; @@ -1347,14 +1347,14 @@ reg = <0x018c>; }; - dpll_usb_ck: dpll_usb_ck { + dpll_usb_ck: dpll_usb_ck@180 { #clock-cells = <0>; compatible = "ti,omap4-dpll-j-type-clock"; clocks = <&sys_clkin1>, <&dpll_usb_byp_mux>; reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>; }; - dpll_usb_m2_ck: dpll_usb_m2_ck { + dpll_usb_m2_ck: dpll_usb_m2_ck@190 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_usb_ck>; @@ -1365,7 +1365,7 @@ ti,invert-autoidle-bit; }; - dpll_pcie_ref_m2_ck: dpll_pcie_ref_m2_ck { + dpll_pcie_ref_m2_ck: dpll_pcie_ref_m2_ck@210 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_pcie_ref_ck>; @@ -1382,7 +1382,7 @@ clocks = <&dpll_per_ck>; }; - dpll_per_h11x2_ck: dpll_per_h11x2_ck { + dpll_per_h11x2_ck: dpll_per_h11x2_ck@158 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -1393,7 +1393,7 @@ ti,invert-autoidle-bit; }; - dpll_per_h12x2_ck: dpll_per_h12x2_ck { + dpll_per_h12x2_ck: dpll_per_h12x2_ck@15c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -1404,7 +1404,7 @@ ti,invert-autoidle-bit; }; - dpll_per_h13x2_ck: dpll_per_h13x2_ck { + dpll_per_h13x2_ck: dpll_per_h13x2_ck@160 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -1415,7 +1415,7 @@ ti,invert-autoidle-bit; }; - dpll_per_h14x2_ck: dpll_per_h14x2_ck { + dpll_per_h14x2_ck: dpll_per_h14x2_ck@164 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -1426,7 +1426,7 @@ ti,invert-autoidle-bit; }; - dpll_per_m2x2_ck: dpll_per_m2x2_ck { + dpll_per_m2x2_ck: dpll_per_m2x2_ck@150 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -1485,7 +1485,7 @@ clock-div = <2>; }; - l3init_60m_fclk: l3init_60m_fclk { + l3init_60m_fclk: l3init_60m_fclk@104 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_usb_m2_ck>; @@ -1493,7 +1493,7 @@ ti,dividers = <1>, <8>; }; - clkout2_clk: clkout2_clk { + clkout2_clk: clkout2_clk@6b0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&clkoutmux2_clk_mux>; @@ -1501,7 +1501,7 @@ reg = <0x06b0>; }; - l3init_960m_gfclk: l3init_960m_gfclk { + l3init_960m_gfclk: l3init_960m_gfclk@6c0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_usb_clkdcoldo>; @@ -1509,7 +1509,7 @@ reg = <0x06c0>; }; - dss_32khz_clk: dss_32khz_clk { + dss_32khz_clk: dss_32khz_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1517,7 +1517,7 @@ reg = <0x1120>; }; - dss_48mhz_clk: dss_48mhz_clk { + dss_48mhz_clk: dss_48mhz_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_48m_fclk>; @@ -1525,7 +1525,7 @@ reg = <0x1120>; }; - dss_dss_clk: dss_dss_clk { + dss_dss_clk: dss_dss_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_per_h12x2_ck>; @@ -1534,7 +1534,7 @@ ti,set-rate-parent; }; - dss_hdmi_clk: dss_hdmi_clk { + dss_hdmi_clk: dss_hdmi_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&hdmi_dpll_clk_mux>; @@ -1542,7 +1542,7 @@ reg = <0x1120>; }; - dss_video1_clk: dss_video1_clk { + dss_video1_clk: dss_video1_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&video1_dpll_clk_mux>; @@ -1550,7 +1550,7 @@ reg = <0x1120>; }; - dss_video2_clk: dss_video2_clk { + dss_video2_clk: dss_video2_clk@1120 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&video2_dpll_clk_mux>; @@ -1558,7 +1558,7 @@ reg = <0x1120>; }; - gpio2_dbclk: gpio2_dbclk { + gpio2_dbclk: gpio2_dbclk@1760 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1566,7 +1566,7 @@ reg = <0x1760>; }; - gpio3_dbclk: gpio3_dbclk { + gpio3_dbclk: gpio3_dbclk@1768 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1574,7 +1574,7 @@ reg = <0x1768>; }; - gpio4_dbclk: gpio4_dbclk { + gpio4_dbclk: gpio4_dbclk@1770 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1582,7 +1582,7 @@ reg = <0x1770>; }; - gpio5_dbclk: gpio5_dbclk { + gpio5_dbclk: gpio5_dbclk@1778 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1590,7 +1590,7 @@ reg = <0x1778>; }; - gpio6_dbclk: gpio6_dbclk { + gpio6_dbclk: gpio6_dbclk@1780 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1598,7 +1598,7 @@ reg = <0x1780>; }; - gpio7_dbclk: gpio7_dbclk { + gpio7_dbclk: gpio7_dbclk@1810 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1606,7 +1606,7 @@ reg = <0x1810>; }; - gpio8_dbclk: gpio8_dbclk { + gpio8_dbclk: gpio8_dbclk@1818 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1614,7 +1614,7 @@ reg = <0x1818>; }; - mmc1_clk32k: mmc1_clk32k { + mmc1_clk32k: mmc1_clk32k@1328 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1622,7 +1622,7 @@ reg = <0x1328>; }; - mmc2_clk32k: mmc2_clk32k { + mmc2_clk32k: mmc2_clk32k@1330 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1630,7 +1630,7 @@ reg = <0x1330>; }; - mmc3_clk32k: mmc3_clk32k { + mmc3_clk32k: mmc3_clk32k@1820 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1638,7 +1638,7 @@ reg = <0x1820>; }; - mmc4_clk32k: mmc4_clk32k { + mmc4_clk32k: mmc4_clk32k@1828 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1646,7 +1646,7 @@ reg = <0x1828>; }; - sata_ref_clk: sata_ref_clk { + sata_ref_clk: sata_ref_clk@1388 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_clkin1>; @@ -1654,7 +1654,7 @@ reg = <0x1388>; }; - usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m { + usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m@13f0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_960m_gfclk>; @@ -1662,7 +1662,7 @@ reg = <0x13f0>; }; - usb_otg_ss2_refclk960m: usb_otg_ss2_refclk960m { + usb_otg_ss2_refclk960m: usb_otg_ss2_refclk960m@1340 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_960m_gfclk>; @@ -1670,7 +1670,7 @@ reg = <0x1340>; }; - usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k { + usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k@640 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1678,7 +1678,7 @@ reg = <0x0640>; }; - usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k { + usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k@688 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1686,7 +1686,7 @@ reg = <0x0688>; }; - usb_phy3_always_on_clk32k: usb_phy3_always_on_clk32k { + usb_phy3_always_on_clk32k: usb_phy3_always_on_clk32k@698 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1694,7 +1694,7 @@ reg = <0x0698>; }; - atl_dpll_clk_mux: atl_dpll_clk_mux { + atl_dpll_clk_mux: atl_dpll_clk_mux@c00 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_32k_ck>, <&video1_clkin_ck>, <&video2_clkin_ck>, <&hdmi_clkin_ck>; @@ -1702,7 +1702,7 @@ reg = <0x0c00>; }; - atl_gfclk_mux: atl_gfclk_mux { + atl_gfclk_mux: atl_gfclk_mux@c00 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&l3_iclk_div>, <&dpll_abe_m2_ck>, <&atl_dpll_clk_mux>; @@ -1710,7 +1710,7 @@ reg = <0x0c00>; }; - gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div { + gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div@13d0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_gmac_m2_ck>; @@ -1719,7 +1719,7 @@ ti,dividers = <2>; }; - gmac_rft_clk_mux: gmac_rft_clk_mux { + gmac_rft_clk_mux: gmac_rft_clk_mux@13d0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&video1_clkin_ck>, <&video2_clkin_ck>, <&dpll_abe_m2_ck>, <&hdmi_clkin_ck>, <&l3_iclk_div>; @@ -1727,7 +1727,7 @@ reg = <0x13d0>; }; - gpu_core_gclk_mux: gpu_core_gclk_mux { + gpu_core_gclk_mux: gpu_core_gclk_mux@1220 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>; @@ -1735,7 +1735,7 @@ reg = <0x1220>; }; - gpu_hyd_gclk_mux: gpu_hyd_gclk_mux { + gpu_hyd_gclk_mux: gpu_hyd_gclk_mux@1220 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>; @@ -1743,7 +1743,7 @@ reg = <0x1220>; }; - l3instr_ts_gclk_div: l3instr_ts_gclk_div { + l3instr_ts_gclk_div: l3instr_ts_gclk_div@e50 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&wkupaon_iclk_mux>; @@ -1752,7 +1752,7 @@ ti,dividers = <8>, <16>, <32>; }; - mcasp2_ahclkr_mux: mcasp2_ahclkr_mux { + mcasp2_ahclkr_mux: mcasp2_ahclkr_mux@1860 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1760,7 +1760,7 @@ reg = <0x1860>; }; - mcasp2_ahclkx_mux: mcasp2_ahclkx_mux { + mcasp2_ahclkx_mux: mcasp2_ahclkx_mux@1860 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1768,7 +1768,7 @@ reg = <0x1860>; }; - mcasp2_aux_gfclk_mux: mcasp2_aux_gfclk_mux { + mcasp2_aux_gfclk_mux: mcasp2_aux_gfclk_mux@1860 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -1776,7 +1776,7 @@ reg = <0x1860>; }; - mcasp3_ahclkx_mux: mcasp3_ahclkx_mux { + mcasp3_ahclkx_mux: mcasp3_ahclkx_mux@1868 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1784,7 +1784,7 @@ reg = <0x1868>; }; - mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux { + mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux@1868 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -1792,7 +1792,7 @@ reg = <0x1868>; }; - mcasp4_ahclkx_mux: mcasp4_ahclkx_mux { + mcasp4_ahclkx_mux: mcasp4_ahclkx_mux@1898 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1800,7 +1800,7 @@ reg = <0x1898>; }; - mcasp4_aux_gfclk_mux: mcasp4_aux_gfclk_mux { + mcasp4_aux_gfclk_mux: mcasp4_aux_gfclk_mux@1898 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -1808,7 +1808,7 @@ reg = <0x1898>; }; - mcasp5_ahclkx_mux: mcasp5_ahclkx_mux { + mcasp5_ahclkx_mux: mcasp5_ahclkx_mux@1878 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1816,7 +1816,7 @@ reg = <0x1878>; }; - mcasp5_aux_gfclk_mux: mcasp5_aux_gfclk_mux { + mcasp5_aux_gfclk_mux: mcasp5_aux_gfclk_mux@1878 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -1824,7 +1824,7 @@ reg = <0x1878>; }; - mcasp6_ahclkx_mux: mcasp6_ahclkx_mux { + mcasp6_ahclkx_mux: mcasp6_ahclkx_mux@1904 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1832,7 +1832,7 @@ reg = <0x1904>; }; - mcasp6_aux_gfclk_mux: mcasp6_aux_gfclk_mux { + mcasp6_aux_gfclk_mux: mcasp6_aux_gfclk_mux@1904 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -1840,7 +1840,7 @@ reg = <0x1904>; }; - mcasp7_ahclkx_mux: mcasp7_ahclkx_mux { + mcasp7_ahclkx_mux: mcasp7_ahclkx_mux@1908 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1848,7 +1848,7 @@ reg = <0x1908>; }; - mcasp7_aux_gfclk_mux: mcasp7_aux_gfclk_mux { + mcasp7_aux_gfclk_mux: mcasp7_aux_gfclk_mux@1908 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -1856,7 +1856,7 @@ reg = <0x1908>; }; - mcasp8_ahclk_mux: mcasp8_ahclk_mux { + mcasp8_ahclk_mux: mcasp8_ahclk_mux@1890 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; @@ -1864,7 +1864,7 @@ reg = <0x1890>; }; - mcasp8_aux_gfclk_mux: mcasp8_aux_gfclk_mux { + mcasp8_aux_gfclk_mux: mcasp8_aux_gfclk_mux@1890 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; @@ -1872,7 +1872,7 @@ reg = <0x1890>; }; - mmc1_fclk_mux: mmc1_fclk_mux { + mmc1_fclk_mux: mmc1_fclk_mux@1328 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; @@ -1880,7 +1880,7 @@ reg = <0x1328>; }; - mmc1_fclk_div: mmc1_fclk_div { + mmc1_fclk_div: mmc1_fclk_div@1328 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mmc1_fclk_mux>; @@ -1890,7 +1890,7 @@ ti,index-power-of-two; }; - mmc2_fclk_mux: mmc2_fclk_mux { + mmc2_fclk_mux: mmc2_fclk_mux@1330 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; @@ -1898,7 +1898,7 @@ reg = <0x1330>; }; - mmc2_fclk_div: mmc2_fclk_div { + mmc2_fclk_div: mmc2_fclk_div@1330 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mmc2_fclk_mux>; @@ -1908,7 +1908,7 @@ ti,index-power-of-two; }; - mmc3_gfclk_mux: mmc3_gfclk_mux { + mmc3_gfclk_mux: mmc3_gfclk_mux@1820 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -1916,7 +1916,7 @@ reg = <0x1820>; }; - mmc3_gfclk_div: mmc3_gfclk_div { + mmc3_gfclk_div: mmc3_gfclk_div@1820 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mmc3_gfclk_mux>; @@ -1926,7 +1926,7 @@ ti,index-power-of-two; }; - mmc4_gfclk_mux: mmc4_gfclk_mux { + mmc4_gfclk_mux: mmc4_gfclk_mux@1828 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -1934,7 +1934,7 @@ reg = <0x1828>; }; - mmc4_gfclk_div: mmc4_gfclk_div { + mmc4_gfclk_div: mmc4_gfclk_div@1828 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mmc4_gfclk_mux>; @@ -1944,7 +1944,7 @@ ti,index-power-of-two; }; - qspi_gfclk_mux: qspi_gfclk_mux { + qspi_gfclk_mux: qspi_gfclk_mux@1838 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_128m_clk>, <&dpll_per_h13x2_ck>; @@ -1952,7 +1952,7 @@ reg = <0x1838>; }; - qspi_gfclk_div: qspi_gfclk_div { + qspi_gfclk_div: qspi_gfclk_div@1838 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&qspi_gfclk_mux>; @@ -1962,7 +1962,7 @@ ti,index-power-of-two; }; - timer10_gfclk_mux: timer10_gfclk_mux { + timer10_gfclk_mux: timer10_gfclk_mux@1728 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -1970,7 +1970,7 @@ reg = <0x1728>; }; - timer11_gfclk_mux: timer11_gfclk_mux { + timer11_gfclk_mux: timer11_gfclk_mux@1730 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -1978,7 +1978,7 @@ reg = <0x1730>; }; - timer13_gfclk_mux: timer13_gfclk_mux { + timer13_gfclk_mux: timer13_gfclk_mux@17c8 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -1986,7 +1986,7 @@ reg = <0x17c8>; }; - timer14_gfclk_mux: timer14_gfclk_mux { + timer14_gfclk_mux: timer14_gfclk_mux@17d0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -1994,7 +1994,7 @@ reg = <0x17d0>; }; - timer15_gfclk_mux: timer15_gfclk_mux { + timer15_gfclk_mux: timer15_gfclk_mux@17d8 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -2002,7 +2002,7 @@ reg = <0x17d8>; }; - timer16_gfclk_mux: timer16_gfclk_mux { + timer16_gfclk_mux: timer16_gfclk_mux@1830 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -2010,7 +2010,7 @@ reg = <0x1830>; }; - timer2_gfclk_mux: timer2_gfclk_mux { + timer2_gfclk_mux: timer2_gfclk_mux@1738 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -2018,7 +2018,7 @@ reg = <0x1738>; }; - timer3_gfclk_mux: timer3_gfclk_mux { + timer3_gfclk_mux: timer3_gfclk_mux@1740 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -2026,7 +2026,7 @@ reg = <0x1740>; }; - timer4_gfclk_mux: timer4_gfclk_mux { + timer4_gfclk_mux: timer4_gfclk_mux@1748 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -2034,7 +2034,7 @@ reg = <0x1748>; }; - timer9_gfclk_mux: timer9_gfclk_mux { + timer9_gfclk_mux: timer9_gfclk_mux@1750 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; @@ -2042,7 +2042,7 @@ reg = <0x1750>; }; - uart1_gfclk_mux: uart1_gfclk_mux { + uart1_gfclk_mux: uart1_gfclk_mux@1840 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2050,7 +2050,7 @@ reg = <0x1840>; }; - uart2_gfclk_mux: uart2_gfclk_mux { + uart2_gfclk_mux: uart2_gfclk_mux@1848 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2058,7 +2058,7 @@ reg = <0x1848>; }; - uart3_gfclk_mux: uart3_gfclk_mux { + uart3_gfclk_mux: uart3_gfclk_mux@1850 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2066,7 +2066,7 @@ reg = <0x1850>; }; - uart4_gfclk_mux: uart4_gfclk_mux { + uart4_gfclk_mux: uart4_gfclk_mux@1858 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2074,7 +2074,7 @@ reg = <0x1858>; }; - uart5_gfclk_mux: uart5_gfclk_mux { + uart5_gfclk_mux: uart5_gfclk_mux@1870 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2082,7 +2082,7 @@ reg = <0x1870>; }; - uart7_gfclk_mux: uart7_gfclk_mux { + uart7_gfclk_mux: uart7_gfclk_mux@18d0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2090,7 +2090,7 @@ reg = <0x18d0>; }; - uart8_gfclk_mux: uart8_gfclk_mux { + uart8_gfclk_mux: uart8_gfclk_mux@18e0 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2098,7 +2098,7 @@ reg = <0x18e0>; }; - uart9_gfclk_mux: uart9_gfclk_mux { + uart9_gfclk_mux: uart9_gfclk_mux@18e8 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; @@ -2106,7 +2106,7 @@ reg = <0x18e8>; }; - vip1_gclk_mux: vip1_gclk_mux { + vip1_gclk_mux: vip1_gclk_mux@1020 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>; @@ -2114,7 +2114,7 @@ reg = <0x1020>; }; - vip2_gclk_mux: vip2_gclk_mux { + vip2_gclk_mux: vip2_gclk_mux@1028 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>; @@ -2122,7 +2122,7 @@ reg = <0x1028>; }; - vip3_gclk_mux: vip3_gclk_mux { + vip3_gclk_mux: vip3_gclk_mux@1030 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>; @@ -2139,7 +2139,7 @@ }; &scm_conf_clocks { - dss_deshdcp_clk: dss_deshdcp_clk { + dss_deshdcp_clk: dss_deshdcp_clk@558 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3_iclk_div>; @@ -2147,7 +2147,7 @@ reg = <0x558>; }; - ehrpwm0_tbclk: ehrpwm0_tbclk { + ehrpwm0_tbclk: ehrpwm0_tbclk@558 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4_root_clk_div>; @@ -2155,7 +2155,7 @@ reg = <0x0558>; }; - ehrpwm1_tbclk: ehrpwm1_tbclk { + ehrpwm1_tbclk: ehrpwm1_tbclk@558 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4_root_clk_div>; @@ -2163,7 +2163,7 @@ reg = <0x0558>; }; - ehrpwm2_tbclk: ehrpwm2_tbclk { + ehrpwm2_tbclk: ehrpwm2_tbclk@558 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l4_root_clk_div>; -- GitLab From ca6fd1c9cf0320946f3e303dba8e8d19fa6c6659 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 4 Apr 2016 18:16:13 +0300 Subject: [PATCH 2010/9938] ARM: dts: omap5: fix clock node definitions to avoid build warnings Upcoming change to DT compiler is going to complain about nodes which have a reg property, but have not defined the address in their name. This patch fixes following type of warnings for OMAP5 clock nodes: Warning (unit_address_vs_reg): Node /ocp/cm@48004000/clocks/dpll3_m2_ck has a reg or ranges property, but no unit name Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap54xx-clocks.dtsi | 260 ++++++++++++------------- 1 file changed, 130 insertions(+), 130 deletions(-) diff --git a/arch/arm/boot/dts/omap54xx-clocks.dtsi b/arch/arm/boot/dts/omap54xx-clocks.dtsi index 83b425fb3ac2..4899c2359d0a 100644 --- a/arch/arm/boot/dts/omap54xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap54xx-clocks.dtsi @@ -14,7 +14,7 @@ clock-frequency = <12000000>; }; - pad_clks_ck: pad_clks_ck { + pad_clks_ck: pad_clks_ck@108 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&pad_clks_src_ck>; @@ -34,7 +34,7 @@ clock-frequency = <12000000>; }; - slimbus_clk: slimbus_clk { + slimbus_clk: slimbus_clk@108 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&slimbus_src_clk>; @@ -102,7 +102,7 @@ clock-frequency = <60000000>; }; - dpll_abe_ck: dpll_abe_ck { + dpll_abe_ck: dpll_abe_ck@1e0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-m4xen-clock"; clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>; @@ -115,7 +115,7 @@ clocks = <&dpll_abe_ck>; }; - dpll_abe_m2x2_ck: dpll_abe_m2x2_ck { + dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@1f0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_x2_ck>; @@ -132,7 +132,7 @@ clock-div = <8>; }; - abe_clk: abe_clk { + abe_clk: abe_clk@108 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_m2x2_ck>; @@ -141,7 +141,7 @@ ti,index-power-of-two; }; - abe_iclk: abe_iclk { + abe_iclk: abe_iclk@528 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&aess_fclk>; @@ -158,7 +158,7 @@ clock-div = <16>; }; - dpll_abe_m3x2_ck: dpll_abe_m3x2_ck { + dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@1f4 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_abe_x2_ck>; @@ -167,7 +167,7 @@ ti,index-starts-at-one; }; - dpll_core_byp_mux: dpll_core_byp_mux { + dpll_core_byp_mux: dpll_core_byp_mux@12c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&dpll_abe_m3x2_ck>; @@ -175,7 +175,7 @@ reg = <0x012c>; }; - dpll_core_ck: dpll_core_ck { + dpll_core_ck: dpll_core_ck@120 { #clock-cells = <0>; compatible = "ti,omap4-dpll-core-clock"; clocks = <&sys_clkin>, <&dpll_core_byp_mux>; @@ -188,7 +188,7 @@ clocks = <&dpll_core_ck>; }; - dpll_core_h21x2_ck: dpll_core_h21x2_ck { + dpll_core_h21x2_ck: dpll_core_h21x2_ck@150 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -213,7 +213,7 @@ clock-div = <2>; }; - dpll_core_h11x2_ck: dpll_core_h11x2_ck { + dpll_core_h11x2_ck: dpll_core_h11x2_ck@138 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -222,7 +222,7 @@ ti,index-starts-at-one; }; - dpll_core_h12x2_ck: dpll_core_h12x2_ck { + dpll_core_h12x2_ck: dpll_core_h12x2_ck@13c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -231,7 +231,7 @@ ti,index-starts-at-one; }; - dpll_core_h13x2_ck: dpll_core_h13x2_ck { + dpll_core_h13x2_ck: dpll_core_h13x2_ck@140 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -240,7 +240,7 @@ ti,index-starts-at-one; }; - dpll_core_h14x2_ck: dpll_core_h14x2_ck { + dpll_core_h14x2_ck: dpll_core_h14x2_ck@144 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -249,7 +249,7 @@ ti,index-starts-at-one; }; - dpll_core_h22x2_ck: dpll_core_h22x2_ck { + dpll_core_h22x2_ck: dpll_core_h22x2_ck@154 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -258,7 +258,7 @@ ti,index-starts-at-one; }; - dpll_core_h23x2_ck: dpll_core_h23x2_ck { + dpll_core_h23x2_ck: dpll_core_h23x2_ck@158 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -267,7 +267,7 @@ ti,index-starts-at-one; }; - dpll_core_h24x2_ck: dpll_core_h24x2_ck { + dpll_core_h24x2_ck: dpll_core_h24x2_ck@15c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -276,7 +276,7 @@ ti,index-starts-at-one; }; - dpll_core_m2_ck: dpll_core_m2_ck { + dpll_core_m2_ck: dpll_core_m2_ck@130 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_ck>; @@ -285,7 +285,7 @@ ti,index-starts-at-one; }; - dpll_core_m3x2_ck: dpll_core_m3x2_ck { + dpll_core_m3x2_ck: dpll_core_m3x2_ck@134 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_core_x2_ck>; @@ -302,7 +302,7 @@ clock-div = <1>; }; - dpll_iva_byp_mux: dpll_iva_byp_mux { + dpll_iva_byp_mux: dpll_iva_byp_mux@1ac { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&iva_dpll_hs_clk_div>; @@ -310,7 +310,7 @@ reg = <0x01ac>; }; - dpll_iva_ck: dpll_iva_ck { + dpll_iva_ck: dpll_iva_ck@1a0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin>, <&dpll_iva_byp_mux>; @@ -323,7 +323,7 @@ clocks = <&dpll_iva_ck>; }; - dpll_iva_h11x2_ck: dpll_iva_h11x2_ck { + dpll_iva_h11x2_ck: dpll_iva_h11x2_ck@1b8 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_iva_x2_ck>; @@ -332,7 +332,7 @@ ti,index-starts-at-one; }; - dpll_iva_h12x2_ck: dpll_iva_h12x2_ck { + dpll_iva_h12x2_ck: dpll_iva_h12x2_ck@1bc { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_iva_x2_ck>; @@ -349,14 +349,14 @@ clock-div = <1>; }; - dpll_mpu_ck: dpll_mpu_ck { + dpll_mpu_ck: dpll_mpu_ck@160 { #clock-cells = <0>; compatible = "ti,omap5-mpu-dpll-clock"; clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>; reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; }; - dpll_mpu_m2_ck: dpll_mpu_m2_ck { + dpll_mpu_m2_ck: dpll_mpu_m2_ck@170 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_mpu_ck>; @@ -381,7 +381,7 @@ clock-div = <3>; }; - l3_iclk_div: l3_iclk_div { + l3_iclk_div: l3_iclk_div@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; ti,max-div = <2>; @@ -399,7 +399,7 @@ clock-div = <1>; }; - l4_root_clk_div: l4_root_clk_div { + l4_root_clk_div: l4_root_clk_div@100 { #clock-cells = <0>; compatible = "ti,divider-clock"; ti,max-div = <2>; @@ -409,7 +409,7 @@ ti,index-power-of-two; }; - slimbus1_slimbus_clk: slimbus1_slimbus_clk { + slimbus1_slimbus_clk: slimbus1_slimbus_clk@560 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&slimbus_clk>; @@ -417,7 +417,7 @@ reg = <0x0560>; }; - aess_fclk: aess_fclk { + aess_fclk: aess_fclk@528 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&abe_clk>; @@ -426,7 +426,7 @@ reg = <0x0528>; }; - dmic_sync_mux_ck: dmic_sync_mux_ck { + dmic_sync_mux_ck: dmic_sync_mux_ck@538 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; @@ -434,7 +434,7 @@ reg = <0x0538>; }; - dmic_gfclk: dmic_gfclk { + dmic_gfclk: dmic_gfclk@538 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -442,7 +442,7 @@ reg = <0x0538>; }; - mcasp_sync_mux_ck: mcasp_sync_mux_ck { + mcasp_sync_mux_ck: mcasp_sync_mux_ck@540 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; @@ -450,7 +450,7 @@ reg = <0x0540>; }; - mcasp_gfclk: mcasp_gfclk { + mcasp_gfclk: mcasp_gfclk@540 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -458,7 +458,7 @@ reg = <0x0540>; }; - mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck { + mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck@548 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; @@ -466,7 +466,7 @@ reg = <0x0548>; }; - mcbsp1_gfclk: mcbsp1_gfclk { + mcbsp1_gfclk: mcbsp1_gfclk@548 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -474,7 +474,7 @@ reg = <0x0548>; }; - mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck { + mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck@550 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; @@ -482,7 +482,7 @@ reg = <0x0550>; }; - mcbsp2_gfclk: mcbsp2_gfclk { + mcbsp2_gfclk: mcbsp2_gfclk@550 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -490,7 +490,7 @@ reg = <0x0550>; }; - mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck { + mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck@558 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; @@ -498,7 +498,7 @@ reg = <0x0558>; }; - mcbsp3_gfclk: mcbsp3_gfclk { + mcbsp3_gfclk: mcbsp3_gfclk@558 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; @@ -506,7 +506,7 @@ reg = <0x0558>; }; - timer5_gfclk_mux: timer5_gfclk_mux { + timer5_gfclk_mux: timer5_gfclk_mux@568 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; @@ -514,7 +514,7 @@ reg = <0x0568>; }; - timer6_gfclk_mux: timer6_gfclk_mux { + timer6_gfclk_mux: timer6_gfclk_mux@570 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; @@ -522,7 +522,7 @@ reg = <0x0570>; }; - timer7_gfclk_mux: timer7_gfclk_mux { + timer7_gfclk_mux: timer7_gfclk_mux@578 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; @@ -530,7 +530,7 @@ reg = <0x0578>; }; - timer8_gfclk_mux: timer8_gfclk_mux { + timer8_gfclk_mux: timer8_gfclk_mux@580 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; @@ -545,7 +545,7 @@ }; }; &prm_clocks { - sys_clkin: sys_clkin { + sys_clkin: sys_clkin@110 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>; @@ -553,14 +553,14 @@ ti,index-starts-at-one; }; - abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux { + abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux@108 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; reg = <0x0108>; }; - abe_dpll_clk_mux: abe_dpll_clk_mux { + abe_dpll_clk_mux: abe_dpll_clk_mux@10c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -583,7 +583,7 @@ clock-div = <1>; }; - wkupaon_iclk_mux: wkupaon_iclk_mux { + wkupaon_iclk_mux: wkupaon_iclk_mux@108 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&abe_lp_clk_div>; @@ -598,7 +598,7 @@ clock-div = <1>; }; - gpio1_dbclk: gpio1_dbclk { + gpio1_dbclk: gpio1_dbclk@1938 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -606,7 +606,7 @@ reg = <0x1938>; }; - timer1_gfclk_mux: timer1_gfclk_mux { + timer1_gfclk_mux: timer1_gfclk_mux@1940 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -616,7 +616,7 @@ }; &cm_core_clocks { - dpll_per_byp_mux: dpll_per_byp_mux { + dpll_per_byp_mux: dpll_per_byp_mux@14c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&per_dpll_hs_clk_div>; @@ -624,7 +624,7 @@ reg = <0x014c>; }; - dpll_per_ck: dpll_per_ck { + dpll_per_ck: dpll_per_ck@140 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin>, <&dpll_per_byp_mux>; @@ -637,7 +637,7 @@ clocks = <&dpll_per_ck>; }; - dpll_per_h11x2_ck: dpll_per_h11x2_ck { + dpll_per_h11x2_ck: dpll_per_h11x2_ck@158 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -646,7 +646,7 @@ ti,index-starts-at-one; }; - dpll_per_h12x2_ck: dpll_per_h12x2_ck { + dpll_per_h12x2_ck: dpll_per_h12x2_ck@15c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -655,7 +655,7 @@ ti,index-starts-at-one; }; - dpll_per_h14x2_ck: dpll_per_h14x2_ck { + dpll_per_h14x2_ck: dpll_per_h14x2_ck@164 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -664,7 +664,7 @@ ti,index-starts-at-one; }; - dpll_per_m2_ck: dpll_per_m2_ck { + dpll_per_m2_ck: dpll_per_m2_ck@150 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_ck>; @@ -673,7 +673,7 @@ ti,index-starts-at-one; }; - dpll_per_m2x2_ck: dpll_per_m2x2_ck { + dpll_per_m2x2_ck: dpll_per_m2x2_ck@150 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -682,7 +682,7 @@ ti,index-starts-at-one; }; - dpll_per_m3x2_ck: dpll_per_m3x2_ck { + dpll_per_m3x2_ck: dpll_per_m3x2_ck@154 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_x2_ck>; @@ -691,7 +691,7 @@ ti,index-starts-at-one; }; - dpll_unipro1_ck: dpll_unipro1_ck { + dpll_unipro1_ck: dpll_unipro1_ck@200 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin>, <&sys_clkin>; @@ -706,7 +706,7 @@ clock-div = <1>; }; - dpll_unipro1_m2_ck: dpll_unipro1_m2_ck { + dpll_unipro1_m2_ck: dpll_unipro1_m2_ck@210 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_unipro1_ck>; @@ -715,7 +715,7 @@ ti,index-starts-at-one; }; - dpll_unipro2_ck: dpll_unipro2_ck { + dpll_unipro2_ck: dpll_unipro2_ck@1c0 { #clock-cells = <0>; compatible = "ti,omap4-dpll-clock"; clocks = <&sys_clkin>, <&sys_clkin>; @@ -730,7 +730,7 @@ clock-div = <1>; }; - dpll_unipro2_m2_ck: dpll_unipro2_m2_ck { + dpll_unipro2_m2_ck: dpll_unipro2_m2_ck@1d0 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_unipro2_ck>; @@ -739,7 +739,7 @@ ti,index-starts-at-one; }; - dpll_usb_byp_mux: dpll_usb_byp_mux { + dpll_usb_byp_mux: dpll_usb_byp_mux@18c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&usb_dpll_hs_clk_div>; @@ -747,7 +747,7 @@ reg = <0x018c>; }; - dpll_usb_ck: dpll_usb_ck { + dpll_usb_ck: dpll_usb_ck@180 { #clock-cells = <0>; compatible = "ti,omap4-dpll-j-type-clock"; clocks = <&sys_clkin>, <&dpll_usb_byp_mux>; @@ -762,7 +762,7 @@ clock-div = <1>; }; - dpll_usb_m2_ck: dpll_usb_m2_ck { + dpll_usb_m2_ck: dpll_usb_m2_ck@190 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_usb_ck>; @@ -811,7 +811,7 @@ clock-div = <2>; }; - l3init_60m_fclk: l3init_60m_fclk { + l3init_60m_fclk: l3init_60m_fclk@104 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_usb_m2_ck>; @@ -819,7 +819,7 @@ ti,dividers = <1>, <8>; }; - dss_32khz_clk: dss_32khz_clk { + dss_32khz_clk: dss_32khz_clk@1420 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -827,7 +827,7 @@ reg = <0x1420>; }; - dss_48mhz_clk: dss_48mhz_clk { + dss_48mhz_clk: dss_48mhz_clk@1420 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_48m_fclk>; @@ -835,7 +835,7 @@ reg = <0x1420>; }; - dss_dss_clk: dss_dss_clk { + dss_dss_clk: dss_dss_clk@1420 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_per_h12x2_ck>; @@ -844,7 +844,7 @@ ti,set-rate-parent; }; - dss_sys_clk: dss_sys_clk { + dss_sys_clk: dss_sys_clk@1420 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dss_syc_gfclk_div>; @@ -852,7 +852,7 @@ reg = <0x1420>; }; - gpio2_dbclk: gpio2_dbclk { + gpio2_dbclk: gpio2_dbclk@1060 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -860,7 +860,7 @@ reg = <0x1060>; }; - gpio3_dbclk: gpio3_dbclk { + gpio3_dbclk: gpio3_dbclk@1068 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -868,7 +868,7 @@ reg = <0x1068>; }; - gpio4_dbclk: gpio4_dbclk { + gpio4_dbclk: gpio4_dbclk@1070 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -876,7 +876,7 @@ reg = <0x1070>; }; - gpio5_dbclk: gpio5_dbclk { + gpio5_dbclk: gpio5_dbclk@1078 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -884,7 +884,7 @@ reg = <0x1078>; }; - gpio6_dbclk: gpio6_dbclk { + gpio6_dbclk: gpio6_dbclk@1080 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -892,7 +892,7 @@ reg = <0x1080>; }; - gpio7_dbclk: gpio7_dbclk { + gpio7_dbclk: gpio7_dbclk@1110 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -900,7 +900,7 @@ reg = <0x1110>; }; - gpio8_dbclk: gpio8_dbclk { + gpio8_dbclk: gpio8_dbclk@1118 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -908,7 +908,7 @@ reg = <0x1118>; }; - iss_ctrlclk: iss_ctrlclk { + iss_ctrlclk: iss_ctrlclk@1320 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&func_96m_fclk>; @@ -916,7 +916,7 @@ reg = <0x1320>; }; - lli_txphy_clk: lli_txphy_clk { + lli_txphy_clk: lli_txphy_clk@f20 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_unipro1_clkdcoldo>; @@ -924,7 +924,7 @@ reg = <0x0f20>; }; - lli_txphy_ls_clk: lli_txphy_ls_clk { + lli_txphy_ls_clk: lli_txphy_ls_clk@f20 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_unipro1_m2_ck>; @@ -932,7 +932,7 @@ reg = <0x0f20>; }; - mmc1_32khz_clk: mmc1_32khz_clk { + mmc1_32khz_clk: mmc1_32khz_clk@1628 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -940,7 +940,7 @@ reg = <0x1628>; }; - sata_ref_clk: sata_ref_clk { + sata_ref_clk: sata_ref_clk@1688 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_clkin>; @@ -948,7 +948,7 @@ reg = <0x1688>; }; - usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk { + usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_usb_m2_ck>; @@ -956,7 +956,7 @@ reg = <0x1658>; }; - usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk { + usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_usb_m2_ck>; @@ -964,7 +964,7 @@ reg = <0x1658>; }; - usb_host_hs_hsic480m_p3_clk: usb_host_hs_hsic480m_p3_clk { + usb_host_hs_hsic480m_p3_clk: usb_host_hs_hsic480m_p3_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_usb_m2_ck>; @@ -972,7 +972,7 @@ reg = <0x1658>; }; - usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk { + usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_60m_fclk>; @@ -980,7 +980,7 @@ reg = <0x1658>; }; - usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk { + usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_60m_fclk>; @@ -988,7 +988,7 @@ reg = <0x1658>; }; - usb_host_hs_hsic60m_p3_clk: usb_host_hs_hsic60m_p3_clk { + usb_host_hs_hsic60m_p3_clk: usb_host_hs_hsic60m_p3_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_60m_fclk>; @@ -996,7 +996,7 @@ reg = <0x1658>; }; - utmi_p1_gfclk: utmi_p1_gfclk { + utmi_p1_gfclk: utmi_p1_gfclk@1658 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&l3init_60m_fclk>, <&xclk60mhsp1_ck>; @@ -1004,7 +1004,7 @@ reg = <0x1658>; }; - usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk { + usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&utmi_p1_gfclk>; @@ -1012,7 +1012,7 @@ reg = <0x1658>; }; - utmi_p2_gfclk: utmi_p2_gfclk { + utmi_p2_gfclk: utmi_p2_gfclk@1658 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&l3init_60m_fclk>, <&xclk60mhsp2_ck>; @@ -1020,7 +1020,7 @@ reg = <0x1658>; }; - usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk { + usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&utmi_p2_gfclk>; @@ -1028,7 +1028,7 @@ reg = <0x1658>; }; - usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk { + usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk@1658 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_60m_fclk>; @@ -1036,7 +1036,7 @@ reg = <0x1658>; }; - usb_otg_ss_refclk960m: usb_otg_ss_refclk960m { + usb_otg_ss_refclk960m: usb_otg_ss_refclk960m@16f0 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&dpll_usb_clkdcoldo>; @@ -1044,7 +1044,7 @@ reg = <0x16f0>; }; - usb_phy_cm_clk32k: usb_phy_cm_clk32k { + usb_phy_cm_clk32k: usb_phy_cm_clk32k@640 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&sys_32k_ck>; @@ -1052,7 +1052,7 @@ reg = <0x0640>; }; - usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk { + usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk@1668 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_60m_fclk>; @@ -1060,7 +1060,7 @@ reg = <0x1668>; }; - usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk { + usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk@1668 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_60m_fclk>; @@ -1068,7 +1068,7 @@ reg = <0x1668>; }; - usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk { + usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk@1668 { #clock-cells = <0>; compatible = "ti,gate-clock"; clocks = <&l3init_60m_fclk>; @@ -1076,7 +1076,7 @@ reg = <0x1668>; }; - fdif_fclk: fdif_fclk { + fdif_fclk: fdif_fclk@1328 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_h11x2_ck>; @@ -1085,7 +1085,7 @@ reg = <0x1328>; }; - gpu_core_gclk_mux: gpu_core_gclk_mux { + gpu_core_gclk_mux: gpu_core_gclk_mux@1520 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>; @@ -1093,7 +1093,7 @@ reg = <0x1520>; }; - gpu_hyd_gclk_mux: gpu_hyd_gclk_mux { + gpu_hyd_gclk_mux: gpu_hyd_gclk_mux@1520 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>; @@ -1101,7 +1101,7 @@ reg = <0x1520>; }; - hsi_fclk: hsi_fclk { + hsi_fclk: hsi_fclk@1638 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&dpll_per_m2x2_ck>; @@ -1110,7 +1110,7 @@ reg = <0x1638>; }; - mmc1_fclk_mux: mmc1_fclk_mux { + mmc1_fclk_mux: mmc1_fclk_mux@1628 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; @@ -1118,7 +1118,7 @@ reg = <0x1628>; }; - mmc1_fclk: mmc1_fclk { + mmc1_fclk: mmc1_fclk@1628 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mmc1_fclk_mux>; @@ -1127,7 +1127,7 @@ reg = <0x1628>; }; - mmc2_fclk_mux: mmc2_fclk_mux { + mmc2_fclk_mux: mmc2_fclk_mux@1630 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; @@ -1135,7 +1135,7 @@ reg = <0x1630>; }; - mmc2_fclk: mmc2_fclk { + mmc2_fclk: mmc2_fclk@1630 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&mmc2_fclk_mux>; @@ -1144,7 +1144,7 @@ reg = <0x1630>; }; - timer10_gfclk_mux: timer10_gfclk_mux { + timer10_gfclk_mux: timer10_gfclk_mux@1028 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -1152,7 +1152,7 @@ reg = <0x1028>; }; - timer11_gfclk_mux: timer11_gfclk_mux { + timer11_gfclk_mux: timer11_gfclk_mux@1030 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -1160,7 +1160,7 @@ reg = <0x1030>; }; - timer2_gfclk_mux: timer2_gfclk_mux { + timer2_gfclk_mux: timer2_gfclk_mux@1038 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -1168,7 +1168,7 @@ reg = <0x1038>; }; - timer3_gfclk_mux: timer3_gfclk_mux { + timer3_gfclk_mux: timer3_gfclk_mux@1040 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -1176,7 +1176,7 @@ reg = <0x1040>; }; - timer4_gfclk_mux: timer4_gfclk_mux { + timer4_gfclk_mux: timer4_gfclk_mux@1048 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -1184,7 +1184,7 @@ reg = <0x1048>; }; - timer9_gfclk_mux: timer9_gfclk_mux { + timer9_gfclk_mux: timer9_gfclk_mux@1050 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&sys_clkin>, <&sys_32k_ck>; @@ -1201,7 +1201,7 @@ }; &scrm_clocks { - auxclk0_src_gate_ck: auxclk0_src_gate_ck { + auxclk0_src_gate_ck: auxclk0_src_gate_ck@310 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1209,7 +1209,7 @@ reg = <0x0310>; }; - auxclk0_src_mux_ck: auxclk0_src_mux_ck { + auxclk0_src_mux_ck: auxclk0_src_mux_ck@310 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1223,7 +1223,7 @@ clocks = <&auxclk0_src_gate_ck>, <&auxclk0_src_mux_ck>; }; - auxclk0_ck: auxclk0_ck { + auxclk0_ck: auxclk0_ck@310 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk0_src_ck>; @@ -1232,7 +1232,7 @@ reg = <0x0310>; }; - auxclk1_src_gate_ck: auxclk1_src_gate_ck { + auxclk1_src_gate_ck: auxclk1_src_gate_ck@314 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1240,7 +1240,7 @@ reg = <0x0314>; }; - auxclk1_src_mux_ck: auxclk1_src_mux_ck { + auxclk1_src_mux_ck: auxclk1_src_mux_ck@314 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1254,7 +1254,7 @@ clocks = <&auxclk1_src_gate_ck>, <&auxclk1_src_mux_ck>; }; - auxclk1_ck: auxclk1_ck { + auxclk1_ck: auxclk1_ck@314 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk1_src_ck>; @@ -1263,7 +1263,7 @@ reg = <0x0314>; }; - auxclk2_src_gate_ck: auxclk2_src_gate_ck { + auxclk2_src_gate_ck: auxclk2_src_gate_ck@318 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1271,7 +1271,7 @@ reg = <0x0318>; }; - auxclk2_src_mux_ck: auxclk2_src_mux_ck { + auxclk2_src_mux_ck: auxclk2_src_mux_ck@318 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1285,7 +1285,7 @@ clocks = <&auxclk2_src_gate_ck>, <&auxclk2_src_mux_ck>; }; - auxclk2_ck: auxclk2_ck { + auxclk2_ck: auxclk2_ck@318 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk2_src_ck>; @@ -1294,7 +1294,7 @@ reg = <0x0318>; }; - auxclk3_src_gate_ck: auxclk3_src_gate_ck { + auxclk3_src_gate_ck: auxclk3_src_gate_ck@31c { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1302,7 +1302,7 @@ reg = <0x031c>; }; - auxclk3_src_mux_ck: auxclk3_src_mux_ck { + auxclk3_src_mux_ck: auxclk3_src_mux_ck@31c { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1316,7 +1316,7 @@ clocks = <&auxclk3_src_gate_ck>, <&auxclk3_src_mux_ck>; }; - auxclk3_ck: auxclk3_ck { + auxclk3_ck: auxclk3_ck@31c { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk3_src_ck>; @@ -1325,7 +1325,7 @@ reg = <0x031c>; }; - auxclk4_src_gate_ck: auxclk4_src_gate_ck { + auxclk4_src_gate_ck: auxclk4_src_gate_ck@320 { #clock-cells = <0>; compatible = "ti,composite-no-wait-gate-clock"; clocks = <&dpll_core_m3x2_ck>; @@ -1333,7 +1333,7 @@ reg = <0x0320>; }; - auxclk4_src_mux_ck: auxclk4_src_mux_ck { + auxclk4_src_mux_ck: auxclk4_src_mux_ck@320 { #clock-cells = <0>; compatible = "ti,composite-mux-clock"; clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; @@ -1347,7 +1347,7 @@ clocks = <&auxclk4_src_gate_ck>, <&auxclk4_src_mux_ck>; }; - auxclk4_ck: auxclk4_ck { + auxclk4_ck: auxclk4_ck@320 { #clock-cells = <0>; compatible = "ti,divider-clock"; clocks = <&auxclk4_src_ck>; @@ -1356,7 +1356,7 @@ reg = <0x0320>; }; - auxclkreq0_ck: auxclkreq0_ck { + auxclkreq0_ck: auxclkreq0_ck@210 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; @@ -1364,7 +1364,7 @@ reg = <0x0210>; }; - auxclkreq1_ck: auxclkreq1_ck { + auxclkreq1_ck: auxclkreq1_ck@214 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; @@ -1372,7 +1372,7 @@ reg = <0x0214>; }; - auxclkreq2_ck: auxclkreq2_ck { + auxclkreq2_ck: auxclkreq2_ck@218 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; @@ -1380,7 +1380,7 @@ reg = <0x0218>; }; - auxclkreq3_ck: auxclkreq3_ck { + auxclkreq3_ck: auxclkreq3_ck@21c { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; -- GitLab From a1e89630ea8b3797f8ecbdc95e210e29ea461bfa Mon Sep 17 00:00:00 2001 From: Graham Moore Date: Tue, 8 Mar 2016 17:02:50 +0000 Subject: [PATCH 2011/9938] ARM: dts: socfpga: Add missing clock and interrupt fields for Arria10 DMA The PL330 DMA driver will not load on Arria10 without devicetree entries for clocks and clock_names. This patch adds those entries. It also adds the ninth interrupt, which is required for error detection. Signed-off-by: Graham Moore Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index f75dd232ec2e..8d102d310212 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -78,10 +78,13 @@ <0 87 IRQ_TYPE_LEVEL_HIGH>, <0 88 IRQ_TYPE_LEVEL_HIGH>, <0 89 IRQ_TYPE_LEVEL_HIGH>, - <0 90 IRQ_TYPE_LEVEL_HIGH>; + <0 90 IRQ_TYPE_LEVEL_HIGH>, + <0 91 IRQ_TYPE_LEVEL_HIGH>; #dma-cells = <1>; #dma-channels = <8>; #dma-requests = <32>; + clocks = <&l4_main_clk>; + clock-names = "apb_pclk"; }; }; -- GitLab From 03efbec03198a0f505c2a6c93268c3c5df321c90 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 11 Apr 2016 04:11:11 -0400 Subject: [PATCH 2012/9938] bnxt_en: Disallow forced speed for 10GBaseT devices. 10GBaseT devices must autonegotiate to determine master/slave clocking. Disallow forced speed in ethtool .set_settings() for these devices. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 + drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 8 ++++++++ 3 files changed, 10 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 597e4724a474..a06dcaa75f6e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4611,6 +4611,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) link_info->phy_ver[1] = resp->phy_min; link_info->phy_ver[2] = resp->phy_bld; link_info->media_type = resp->media_type; + link_info->phy_type = resp->phy_type; link_info->transceiver = resp->xcvr_pkg_type; link_info->phy_addr = resp->eee_config_phy_addr & PORT_PHY_QCFG_RESP_PHY_ADDR_MASK; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index cc8e38a9f684..26dac2f3c63c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -759,6 +759,7 @@ struct bnxt_ntuple_filter { }; struct bnxt_link_info { + u8 phy_type; u8 media_type; u8 transceiver; u8 phy_addr; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index a2e93241b06b..d6e41f237f2c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -850,7 +850,15 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) set_pause = true; } else { u16 fw_speed; + u8 phy_type = link_info->phy_type; + if (phy_type == PORT_PHY_QCFG_RESP_PHY_TYPE_BASET || + phy_type == PORT_PHY_QCFG_RESP_PHY_TYPE_BASETE || + link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { + netdev_err(dev, "10GBase-T devices must autoneg\n"); + rc = -EINVAL; + goto set_setting_exit; + } /* TODO: currently don't support half duplex */ if (cmd->duplex == DUPLEX_HALF) { netdev_err(dev, "HALF DUPLEX is not supported!\n"); -- GitLab From 33f7d55f07ab964055d73d38774346f8d4821f00 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 11 Apr 2016 04:11:12 -0400 Subject: [PATCH 2013/9938] bnxt_en: Shutdown link when device is closed. Let firmware know that the driver is giving up control of the link so that it can be shutdown if no management firmware is running. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index a06dcaa75f6e..e874a564f40b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4790,6 +4790,21 @@ int bnxt_hwrm_set_link_setting(struct bnxt *bp, bool set_pause, bool set_eee) return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); } +static int bnxt_hwrm_shutdown_link(struct bnxt *bp) +{ + struct hwrm_port_phy_cfg_input req = {0}; + + if (BNXT_VF(bp)) + return 0; + + if (pci_num_vf(bp->pdev)) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1); + req.flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN); + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + static bool bnxt_eee_config_ok(struct bnxt *bp) { struct ethtool_eee *eee = &bp->eee; @@ -5044,6 +5059,7 @@ static int bnxt_close(struct net_device *dev) struct bnxt *bp = netdev_priv(dev); bnxt_close_nic(bp, true, true); + bnxt_hwrm_shutdown_link(bp); return 0; } -- GitLab From 84c33dd342ad596a271a61da0119bf34e80bb1c5 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 11 Apr 2016 04:11:13 -0400 Subject: [PATCH 2014/9938] bnxt_en: Call firmware to approve VF MAC address change. Some hypervisors (e.g. ESX) require the VF MAC address to be forwarded to the PF for approval. In Linux PF, the call is not forwarded and the firmware will simply check and approve the MAC address if the PF has not previously administered a valid MAC address for this VF. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 7 ++--- .../net/ethernet/broadcom/bnxt/bnxt_sriov.c | 30 +++++++++++++++++++ .../net/ethernet/broadcom/bnxt/bnxt_sriov.h | 1 + 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index e874a564f40b..c83a5a1862d0 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -5696,10 +5696,9 @@ static int bnxt_change_mac_addr(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; -#ifdef CONFIG_BNXT_SRIOV - if (BNXT_VF(bp) && is_valid_ether_addr(bp->vf.mac_addr)) - return -EADDRNOTAVAIL; -#endif + rc = bnxt_approve_mac(bp, addr->sa_data); + if (rc) + return rc; if (ether_addr_equal(addr->sa_data, dev->dev_addr)) return 0; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index 8457850b0bdd..363884dd9e8a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -865,6 +865,31 @@ void bnxt_update_vf_mac(struct bnxt *bp) mutex_unlock(&bp->hwrm_cmd_lock); } +int bnxt_approve_mac(struct bnxt *bp, u8 *mac) +{ + struct hwrm_func_vf_cfg_input req = {0}; + int rc = 0; + + if (!BNXT_VF(bp)) + return 0; + + if (bp->hwrm_spec_code < 0x10202) { + if (is_valid_ether_addr(bp->vf.mac_addr)) + rc = -EADDRNOTAVAIL; + goto mac_done; + } + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_VF_CFG, -1, -1); + req.enables = cpu_to_le32(FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR); + memcpy(req.dflt_mac_addr, mac, ETH_ALEN); + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +mac_done: + if (rc) { + rc = -EADDRNOTAVAIL; + netdev_warn(bp->dev, "VF MAC address %pM not approved by the PF\n", + mac); + } + return rc; +} #else void bnxt_sriov_disable(struct bnxt *bp) @@ -879,4 +904,9 @@ void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) void bnxt_update_vf_mac(struct bnxt *bp) { } + +int bnxt_approve_mac(struct bnxt *bp, u8 *mac) +{ + return 0; +} #endif diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h index 3f08354a247e..0392670ab49c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h @@ -20,4 +20,5 @@ int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs); void bnxt_sriov_disable(struct bnxt *); void bnxt_hwrm_exec_fwd_req(struct bnxt *); void bnxt_update_vf_mac(struct bnxt *); +int bnxt_approve_mac(struct bnxt *, u8 *); #endif -- GitLab From 8cbde1175e3c8565edbb777cd09cbfdb93c78397 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 11 Apr 2016 04:11:14 -0400 Subject: [PATCH 2015/9938] bnxt_en: Add async event handling for speed config changes. On some dual port cards, link speeds on both ports have to be compatible. Firmware will inform the driver when a certain speed is no longer supported if the other port has linked up at a certain speed. Add logic to handle this event by logging a message and getting the updated list of supported speeds. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index c83a5a1862d0..4645c44e7c15 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -122,6 +122,7 @@ static const u16 bnxt_async_events_arr[] = { HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE, }; static bool bnxt_vf_pciid(enum board_idx idx) @@ -1257,6 +1258,21 @@ static int bnxt_async_event_process(struct bnxt *bp, /* TODO CHIMP_FW: Define event id's for link change, error etc */ switch (event_id) { + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: { + u32 data1 = le32_to_cpu(cmpl->event_data1); + struct bnxt_link_info *link_info = &bp->link_info; + + if (BNXT_VF(bp)) + goto async_event_process_exit; + if (data1 & 0x20000) { + u16 fw_speed = link_info->force_link_speed; + u32 speed = bnxt_fw_to_ethtool_speed(fw_speed); + + netdev_warn(bp->dev, "Link speed %d no longer supported\n", + speed); + } + /* fall thru */ + } case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: set_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event); break; -- GitLab From ebaea3a7852e19bcffcbc8d7de055f2ebacda7ca Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 19 Mar 2016 23:57:04 +0000 Subject: [PATCH 2016/9938] ARM: dts: socfpga: Drop phy-addr OF property from CV dtsi The phy-addr property of stmmac is deprecated and the stmmac driver does not use it either. On the contrary, the driver will warn if this property is defined. Remove it. Signed-off-by: Marek Vasut Cc: Dinh Nguyen Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_cyclone5.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/socfpga_cyclone5.dtsi index 06db951e06f8..418c19eb2b40 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5.dtsi +++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi @@ -40,7 +40,6 @@ ethernet@ff702000 { phy-mode = "rgmii"; - phy-addr = <0xffffffff>; /* probe for phy addr */ status = "okay"; }; -- GitLab From e0897ae3ec720b1653d4ff9aaf48b532c276ab63 Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Mon, 11 Apr 2016 15:58:17 +0530 Subject: [PATCH 2017/9938] net: fjes: Use resource_size Use the function resource_size instead of explicit computation. Problem found using Coccinelle. Signed-off-by: Vaishali Thakkar Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 0ddb54fe3d91..061b4af4ee62 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -1129,7 +1129,7 @@ static int fjes_probe(struct platform_device *plat_dev) res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); hw->hw_res.start = res->start; - hw->hw_res.size = res->end - res->start + 1; + hw->hw_res.size = resource_size(res); hw->hw_res.irq = platform_get_irq(plat_dev, 0); err = fjes_hw_init(&adapter->hw); if (err) -- GitLab From 702744ce8b3ef369ed8f8e257cbee4db44beb415 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 19 Mar 2016 23:57:05 +0000 Subject: [PATCH 2018/9938] ARM: dts: socfpga: Drop gmac0 from CV dtsi The socfpga_cyclone5.dtsi is included by all DTS files which describe boards using the Cyclone V SoC. The Cyclone V SoC has two ethernet controllers and different boards use none, one or both of them. The /soc/ethernet@ff702000/{} node in socfpga_cyclone5.dtsi unconditionaly enabled gmac0 interface, which is clearly wrong for those boards which use gmac1 interface instead. This patch removes the entire /soc/ethernet@ff702000/{} node from the socfpga_cyclone5.dtsi file. This is correct, since all of the board which include this file also have correct gmac0 or gmac1 node present in them. Minor correction had to be done to EBV SoCrates, which didn't define PHY mode explicitly, but inherited it from the socfpga_cyclone5.dtsi . Signed-off-by: Marek Vasut Cc: Dinh Nguyen Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_cyclone5.dtsi | 5 ----- arch/arm/boot/dts/socfpga_cyclone5_socrates.dts | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/socfpga_cyclone5.dtsi index 418c19eb2b40..a05e3df23103 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5.dtsi +++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi @@ -38,11 +38,6 @@ cap-sd-highspeed; }; - ethernet@ff702000 { - phy-mode = "rgmii"; - status = "okay"; - }; - sysmgr@ffd08000 { cpu1-start-addr = <0xffd080c4>; }; diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts index 019dd2fea208..e1a61f20873f 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts @@ -36,6 +36,7 @@ }; &gmac1 { + phy-mode = "rgmii"; status = "okay"; }; -- GitLab From e9f503254a5e0ea6b2b68b4c31491770b47a3ff0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 19 Mar 2016 23:57:45 +0000 Subject: [PATCH 2019/9938] ARM: dts: socfpga: Add support for HPS LEDs on SoCKit Add support for the blue LEDs on the SoCFPGA SoCkit board. Signed-off-by: Marek Vasut Cc: Dinh Nguyen Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_cyclone5_sockit.dts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts index b61f22f9ac9f..146169016f0c 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts @@ -39,6 +39,34 @@ ethernet0 = &gmac1; }; + leds { + compatible = "gpio-leds"; + + hps_led0 { + label = "hps:blue:led0"; + gpios = <&portb 24 0>; /* HPS_GPIO53 */ + linux,default-trigger = "heartbeat"; + }; + + hps_led1 { + label = "hps:blue:led1"; + gpios = <&portb 25 0>; /* HPS_GPIO54 */ + linux,default-trigger = "heartbeat"; + }; + + hps_led2 { + label = "hps:blue:led2"; + gpios = <&portb 26 0>; /* HPS_GPIO55 */ + linux,default-trigger = "heartbeat"; + }; + + hps_led3 { + label = "hps:blue:led3"; + gpios = <&portb 27 0>; /* HPS_GPIO56 */ + linux,default-trigger = "heartbeat"; + }; + }; + regulator_3_3v: vcc3p3-regulator { compatible = "regulator-fixed"; regulator-name = "VCC3P3"; @@ -61,6 +89,10 @@ rxc-skew-ps = <2000>; }; +&gpio1 { /* GPIO 30..57 */ + status = "okay"; +}; + &gpio2 { status = "okay"; }; -- GitLab From 61618eeac3e6165684895481c4f58ea879c3d616 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Mon, 11 Apr 2016 17:06:08 +0200 Subject: [PATCH 2020/9938] vxlan: fix incorrect type The protocol is 16bit, not 32bit. Fixes: e1e5314de08ba ("vxlan: implement GPE") Reported-by: Dan Carpenter Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 9f3634064c92..7f697a3f00a4 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1181,7 +1181,7 @@ static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed, } static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed, - __be32 *protocol, + __be16 *protocol, struct sk_buff *skb, u32 vxflags) { struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed; @@ -1284,7 +1284,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) struct vxlanhdr unparsed; struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; - __be32 protocol = htons(ETH_P_TEB); + __be16 protocol = htons(ETH_P_TEB); bool raw_proto = false; void *oiph; -- GitLab From 95c16caaa8c1ffff2b58007da3989d7c470069eb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 19 Mar 2016 23:57:46 +0000 Subject: [PATCH 2021/9938] ARM: dts: socfpga: Add support for HPS KEYs/SWs on SoCKit Add support for the keys and flip-switches on the SoCFPGA SoCkit board. Signed-off-by: Marek Vasut Cc: Dinh Nguyen Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_cyclone5_sockit.dts | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts index 146169016f0c..02e22f554ef0 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts @@ -67,6 +67,62 @@ }; }; + gpio-keys { + compatible = "gpio-keys"; + + hps_sw0 { + label = "hps_sw0"; + gpios = <&portc 20 0>; /* HPS_GPI7 */ + linux,input-type = <5>; /* EV_SW */ + linux,code = <0x0>; /* SW_LID */ + }; + + hps_sw1 { + label = "hps_sw1"; + gpios = <&portc 19 0>; /* HPS_GPI6 */ + linux,input-type = <5>; /* EV_SW */ + linux,code = <0x5>; /* SW_DOCK */ + }; + + hps_sw2 { + label = "hps_sw2"; + gpios = <&portc 18 0>; /* HPS_GPI5 */ + linux,input-type = <5>; /* EV_SW */ + linux,code = <0xa>; /* SW_KEYPAD_SLIDE */ + }; + + hps_sw3 { + label = "hps_sw3"; + gpios = <&portc 17 0>; /* HPS_GPI4 */ + linux,input-type = <5>; /* EV_SW */ + linux,code = <0xc>; /* SW_ROTATE_LOCK */ + }; + + hps_hkey0 { + label = "hps_hkey0"; + gpios = <&portc 21 1>; /* HPS_GPI8 */ + linux,code = <187>; /* KEY_F17 */ + }; + + hps_hkey1 { + label = "hps_hkey1"; + gpios = <&portc 22 1>; /* HPS_GPI9 */ + linux,code = <188>; /* KEY_F18 */ + }; + + hps_hkey2 { + label = "hps_hkey2"; + gpios = <&portc 23 1>; /* HPS_GPI10 */ + linux,code = <189>; /* KEY_F19 */ + }; + + hps_hkey3 { + label = "hps_hkey3"; + gpios = <&portc 24 1>; /* HPS_GPI11 */ + linux,code = <190>; /* KEY_F20 */ + }; + }; + regulator_3_3v: vcc3p3-regulator { compatible = "regulator-fixed"; regulator-name = "VCC3P3"; @@ -89,11 +145,15 @@ rxc-skew-ps = <2000>; }; +&gpio0 { /* GPIO 0..29 */ + status = "okay"; +}; + &gpio1 { /* GPIO 30..57 */ status = "okay"; }; -&gpio2 { +&gpio2 { /* GPIO 58..66 (HLGPI 0..13 at offset 13) */ status = "okay"; }; -- GitLab From 64ded09d293932621aad94dddf6d14eb0690246a Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 21 Mar 2016 16:01:46 +0000 Subject: [PATCH 2022/9938] ARM: dts: socfpga: Add Altera Arria10 L2 Cache EDAC devicetree entry Add the device tree entries needed to support the Altera L2 cache EDAC on the Arria10 chip. Signed-off-by: Thor Thayer Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index 8d102d310212..04da5eac8376 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -603,6 +603,21 @@ reg = <0xffe00000 0x40000>; }; + eccmgr: eccmgr@ffd06000 { + compatible = "altr,socfpga-a10-ecc-manager"; + altr,sysmgr-syscon = <&sysmgr>; + #address-cells = <1>; + #size-cells = <1>; + interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>, + <0 0 IRQ_TYPE_LEVEL_HIGH>; + ranges; + + l2-ecc@ffd06010 { + compatible = "altr,socfpga-a10-l2-ecc"; + reg = <0xffd06010 0x4>; + }; + }; + rst: rstmgr@ffd05000 { #reset-cells = <1>; compatible = "altr,rst-mgr"; -- GitLab From a44a77115f76a7dd7de4396a7ba159eed1d8be21 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 31 Mar 2016 18:48:07 +0000 Subject: [PATCH 2023/9938] ARM: dts: socfpga: Add Altera Arria10 OCRAM EDAC devicetree entry Add the device tree entries needed to support the Altera On-Chip RAM EDAC on the Arria10 chip. Signed-off-by: Thor Thayer Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index 04da5eac8376..4eec2c7f2167 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -616,6 +616,11 @@ compatible = "altr,socfpga-a10-l2-ecc"; reg = <0xffd06010 0x4>; }; + + ocram-ecc@ff8c3000 { + compatible = "altr,socfpga-a10-ocram-ecc"; + reg = <0xff8c3000 0x400>; + }; }; rst: rstmgr@ffd05000 { -- GitLab From 249ff32e1f8b6ffa92e1390e371702dd8633bcac Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Wed, 23 Mar 2016 15:40:54 -0500 Subject: [PATCH 2024/9938] ARM: dts: socfpga: add reset control for USB Add the resets property for the 2 USB controllers. Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga.dtsi | 4 ++++ arch/arm/boot/dts/socfpga_arria10.dtsi | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index b89cbde3b289..9f48141270b8 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -831,6 +831,8 @@ interrupts = <0 125 4>; clocks = <&usb_mp_clk>; clock-names = "otg"; + resets = <&rst USB0_RESET>; + reset-names = "dwc2"; phys = <&usbphy0>; phy-names = "usb2-phy"; status = "disabled"; @@ -842,6 +844,8 @@ interrupts = <0 128 4>; clocks = <&usb_mp_clk>; clock-names = "otg"; + resets = <&rst USB1_RESET>; + reset-names = "dwc2"; phys = <&usbphy0>; phy-names = "usb2-phy"; status = "disabled"; diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index 4eec2c7f2167..17e81dc9213e 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -713,6 +713,8 @@ interrupts = <0 95 IRQ_TYPE_LEVEL_HIGH>; clocks = <&usb_clk>; clock-names = "otg"; + resets = <&rst USB0_RESET>; + reset-names = "dwc2"; phys = <&usbphy0>; phy-names = "usb2-phy"; status = "disabled"; @@ -724,6 +726,8 @@ interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>; clocks = <&usb_clk>; clock-names = "otg"; + resets = <&rst USB1_RESET>; + reset-names = "dwc2"; phys = <&usbphy0>; phy-names = "usb2-phy"; status = "disabled"; -- GitLab From f0af9593372abfde34460aa1250e670cc535a7d8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 24 Feb 2016 13:43:45 -0600 Subject: [PATCH 2025/9938] PCI: Add pci_add_dma_alias() to abstract implementation Add a pci_add_dma_alias() interface to encapsulate the details of adding an alias. No functional change intended. Signed-off-by: Bjorn Helgaas Reviewed-by: Alex Williamson --- drivers/pci/pci.c | 14 ++++++++++++++ drivers/pci/quirks.c | 19 +++++++------------ include/linux/pci.h | 1 + 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 25e0327d4429..1162118d1093 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4578,6 +4578,20 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, return 0; } +/** + * pci_add_dma_alias - Add a DMA devfn alias for a device + * @dev: the PCI device for which alias is added + * @devfn: alias slot and function + * + * This helper encodes 8-bit devfn as bit number in dma_alias_mask. + * It should be called early, preferably as PCI fixup header quirk. + */ +void pci_add_dma_alias(struct pci_dev *dev, u8 devfn) +{ + dev->dma_alias_devfn = devfn; + dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; +} + bool pci_device_is_present(struct pci_dev *pdev) { u32 v; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8e678027b900..e45a7a8338bb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3610,10 +3610,8 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe) static void quirk_dma_func0_alias(struct pci_dev *dev) { - if (PCI_FUNC(dev->devfn) != 0) { - dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0); - dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; - } + if (PCI_FUNC(dev->devfn) != 0) + pci_add_dma_alias(dev, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); } /* @@ -3626,10 +3624,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe476, quirk_dma_func0_alias); static void quirk_dma_func1_alias(struct pci_dev *dev) { - if (PCI_FUNC(dev->devfn) != 1) { - dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 1); - dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; - } + if (PCI_FUNC(dev->devfn) != 1) + pci_add_dma_alias(dev, PCI_DEVFN(PCI_SLOT(dev->devfn), 1)); } /* @@ -3696,11 +3692,10 @@ static void quirk_fixed_dma_alias(struct pci_dev *dev) id = pci_match_id(fixed_dma_alias_tbl, dev); if (id) { - dev->dma_alias_devfn = id->driver_data; - dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; + pci_add_dma_alias(dev, id->driver_data); dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n", - PCI_SLOT(dev->dma_alias_devfn), - PCI_FUNC(dev->dma_alias_devfn)); + PCI_SLOT(id->driver_data), + PCI_FUNC(id->driver_data)); } } diff --git a/include/linux/pci.h b/include/linux/pci.h index 004b8133417d..7e7019064437 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1988,6 +1988,7 @@ static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev) } #endif +void pci_add_dma_alias(struct pci_dev *dev, u8 devfn); int pci_for_each_dma_alias(struct pci_dev *pdev, int (*fn)(struct pci_dev *pdev, u16 alias, void *data), void *data); -- GitLab From 61f1cef90a18122ff9832a897dc75738c14e710a Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 7 Apr 2016 15:16:43 +0300 Subject: [PATCH 2026/9938] drivers: net: cpsw: fix port_mask parameters in ale calls ALE APIs expect to receive port masks as input values for arguments port_mask, untag, reg_mcast, unreg_mcast. But there are few places in code where port masks are passed left-shifted by cpsw_priv->host_port, like below: cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan, ALE_ALL_PORTS << priv->host_port, ALE_ALL_PORTS << priv->host_port, 0, 0); and cpsw is still working just because priv->host_port == 0 and has never ever been changed. Hence, fix port_mask parameters in ALE APIs calls and drop "<< priv->host_port" from all places where it's used to shift valid port mask. Signed-off-by: Grygorii Strashko Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 42fdfd4d9d4f..5292e70b4825 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -535,7 +535,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = { ALE_VLAN, slave->port_vlan, 0); \ } else { \ cpsw_ale_add_mcast(priv->ale, addr, \ - ALE_ALL_PORTS << priv->host_port, \ + ALE_ALL_PORTS, \ 0, 0, 0); \ } \ } while (0) @@ -602,8 +602,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1); /* Clear all mcast from ALE */ - cpsw_ale_flush_multicast(ale, ALE_ALL_PORTS << - priv->host_port, -1); + cpsw_ale_flush_multicast(ale, ALE_ALL_PORTS, -1); /* Flood All Unicast Packets to Host port */ cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1); @@ -648,8 +647,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) cpsw_ale_set_allmulti(priv->ale, priv->ndev->flags & IFF_ALLMULTI); /* Clear all mcast from ALE */ - cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port, - vid); + cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS, vid); if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; @@ -1172,7 +1170,6 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) { const int vlan = priv->data.default_vlan; - const int port = priv->host_port; u32 reg; int i; int unreg_mcast_mask; @@ -1190,9 +1187,9 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) else unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2; - cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, - ALE_ALL_PORTS << port, ALE_ALL_PORTS << port, - unreg_mcast_mask << port); + cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS, + ALE_ALL_PORTS, ALE_ALL_PORTS, + unreg_mcast_mask); } static void cpsw_init_host_port(struct cpsw_priv *priv) @@ -1273,8 +1270,7 @@ static int cpsw_ndo_open(struct net_device *ndev) cpsw_add_default_vlan(priv); else cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan, - ALE_ALL_PORTS << priv->host_port, - ALE_ALL_PORTS << priv->host_port, 0, 0); + ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0); if (!cpsw_common_res_usage_state(priv)) { struct cpsw_priv *priv_sl0 = cpsw_get_slave_priv(priv, 0); @@ -1666,7 +1662,7 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, } ret = cpsw_ale_add_vlan(priv->ale, vid, port_mask, 0, port_mask, - unreg_mcast_mask << priv->host_port); + unreg_mcast_mask); if (ret != 0) return ret; @@ -1738,7 +1734,7 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, return ret; ret = cpsw_ale_del_ucast(priv->ale, priv->mac_addr, - priv->host_port, ALE_VLAN, vid); + HOST_PORT_NUM, ALE_VLAN, vid); if (ret != 0) return ret; -- GitLab From 71a2cbb72a2bcbf3f1c1b14031870e37ad5e8109 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 7 Apr 2016 15:16:44 +0300 Subject: [PATCH 2027/9938] drivers: net: cpsw: drop host_port field from struct cpsw_priv The host_port field is constantly assigned to 0 and this value has never changed (since time when cpsw driver was introduced. More over, if this field will be assigned to non 0 value it will break current driver functionality. Hence, there are no reasons to continue maintaining this host_port field and it can be removed, and the HOST_PORT_NUM and ALE_PORT_HOST defines can be used instead. Signed-off-by: Grygorii Strashko Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 5292e70b4825..54bcc3851b7e 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -381,7 +381,6 @@ struct cpsw_priv { u32 coal_intvl; u32 bus_freq_mhz; int rx_packet_max; - int host_port; struct clk *clk; u8 mac_addr[ETH_ALEN]; struct cpsw_slave *slaves; @@ -531,7 +530,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = { int slave_port = cpsw_get_slave_port(priv, \ slave->slave_num); \ cpsw_ale_add_mcast(priv->ale, addr, \ - 1 << slave_port | 1 << priv->host_port, \ + 1 << slave_port | ALE_PORT_HOST, \ ALE_VLAN, slave->port_vlan, 0); \ } else { \ cpsw_ale_add_mcast(priv->ale, addr, \ @@ -542,10 +541,7 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = { static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num) { - if (priv->host_port == 0) - return slave_num + 1; - else - return slave_num; + return slave_num + 1; } static void cpsw_set_promiscious(struct net_device *ndev, bool enable) @@ -1090,7 +1086,7 @@ static inline void cpsw_add_dual_emac_def_ale_entries( struct cpsw_priv *priv, struct cpsw_slave *slave, u32 slave_port) { - u32 port_mask = 1 << slave_port | 1 << priv->host_port; + u32 port_mask = 1 << slave_port | ALE_PORT_HOST; if (priv->version == CPSW_VERSION_1) slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN); @@ -1101,7 +1097,7 @@ static inline void cpsw_add_dual_emac_def_ale_entries( cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, port_mask, ALE_VLAN, slave->port_vlan, 0); cpsw_ale_add_ucast(priv->ale, priv->mac_addr, - priv->host_port, ALE_VLAN | ALE_SECURE, slave->port_vlan); + HOST_PORT_NUM, ALE_VLAN | ALE_SECURE, slave->port_vlan); } static void soft_reset_slave(struct cpsw_slave *slave) @@ -1202,7 +1198,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv) cpsw_ale_start(priv->ale); /* switch to vlan unaware mode */ - cpsw_ale_control_set(priv->ale, priv->host_port, ALE_VLAN_AWARE, + cpsw_ale_control_set(priv->ale, HOST_PORT_NUM, ALE_VLAN_AWARE, CPSW_ALE_VLAN_AWARE); control_reg = readl(&priv->regs->control); control_reg |= CPSW_VLAN_AWARE; @@ -1216,14 +1212,14 @@ static void cpsw_init_host_port(struct cpsw_priv *priv) &priv->host_port_regs->cpdma_tx_pri_map); __raw_writel(0, &priv->host_port_regs->cpdma_rx_chan_map); - cpsw_ale_control_set(priv->ale, priv->host_port, + cpsw_ale_control_set(priv->ale, HOST_PORT_NUM, ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); if (!priv->data.dual_emac) { - cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, + cpsw_ale_add_ucast(priv->ale, priv->mac_addr, HOST_PORT_NUM, 0, 0); cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, - 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2); + ALE_PORT_HOST, 0, 0, ALE_MCAST_FWD_2); } } @@ -1616,9 +1612,9 @@ static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p) flags = ALE_VLAN; } - cpsw_ale_del_ucast(priv->ale, priv->mac_addr, priv->host_port, + cpsw_ale_del_ucast(priv->ale, priv->mac_addr, HOST_PORT_NUM, flags, vid); - cpsw_ale_add_ucast(priv->ale, addr->sa_data, priv->host_port, + cpsw_ale_add_ucast(priv->ale, addr->sa_data, HOST_PORT_NUM, flags, vid); memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); @@ -1667,7 +1663,7 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, return ret; ret = cpsw_ale_add_ucast(priv->ale, priv->mac_addr, - priv->host_port, ALE_VLAN, vid); + HOST_PORT_NUM, ALE_VLAN, vid); if (ret != 0) goto clean_vid; @@ -1679,7 +1675,7 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, clean_vlan_ucast: cpsw_ale_del_ucast(priv->ale, priv->mac_addr, - priv->host_port, ALE_VLAN, vid); + HOST_PORT_NUM, ALE_VLAN, vid); clean_vid: cpsw_ale_del_vlan(priv->ale, vid, 0); return ret; @@ -2148,7 +2144,6 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev, priv_sl2->bus_freq_mhz = priv->bus_freq_mhz; priv_sl2->regs = priv->regs; - priv_sl2->host_port = priv->host_port; priv_sl2->host_port_regs = priv->host_port_regs; priv_sl2->wr_regs = priv->wr_regs; priv_sl2->hw_stats = priv->hw_stats; @@ -2317,7 +2312,6 @@ static int cpsw_probe(struct platform_device *pdev) goto clean_runtime_disable_ret; } priv->regs = ss_regs; - priv->host_port = HOST_PORT_NUM; /* Need to enable clocks with runtime PM api to access module * registers -- GitLab From a6db4494d218c2e559173661ee972e048dc04fdd Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 7 Apr 2016 07:21:00 -0700 Subject: [PATCH 2028/9938] net: ipv4: Consider failed nexthops in multipath routes Multipath route lookups should consider knowledge about next hops and not select a hop that is known to be failed. Example: [h2] [h3] 15.0.0.5 | | 3| 3| [SP1] [SP2]--+ 1 2 1 2 | | /-------------+ | | \ / | | X | | / \ | | / \---------------\ | 1 2 1 2 12.0.0.2 [TOR1] 3-----------------3 [TOR2] 12.0.0.3 4 4 \ / \ / \ / -------| |-----/ 1 2 [TOR3] 3| | [h1] 12.0.0.1 host h1 with IP 12.0.0.1 has 2 paths to host h3 at 15.0.0.5: root@h1:~# ip ro ls ... 12.0.0.0/24 dev swp1 proto kernel scope link src 12.0.0.1 15.0.0.0/16 nexthop via 12.0.0.2 dev swp1 weight 1 nexthop via 12.0.0.3 dev swp1 weight 1 ... If the link between tor3 and tor1 is down and the link between tor1 and tor2 then tor1 is effectively cut-off from h1. Yet the route lookups in h1 are alternating between the 2 routes: ping 15.0.0.5 gets one and ssh 15.0.0.5 gets the other. Connections that attempt to use the 12.0.0.2 nexthop fail since that neighbor is not reachable: root@h1:~# ip neigh show ... 12.0.0.3 dev swp1 lladdr 00:02:00:00:00:1b REACHABLE 12.0.0.2 dev swp1 FAILED ... The failed path can be avoided by considering known neighbor information when selecting next hops. If the neighbor lookup fails we have no knowledge about the nexthop, so give it a shot. If there is an entry then only select the nexthop if the state is sane. This is similar to what fib_detect_death does. To maintain backward compatibility use of the neighbor information is based on a new sysctl, fib_multipath_use_neigh. Signed-off-by: David Ahern Reviewed-by: Julian Anastasov Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 10 ++++++++ include/net/netns/ipv4.h | 3 +++ net/ipv4/fib_semantics.c | 34 ++++++++++++++++++++++---- net/ipv4/sysctl_net_ipv4.c | 11 +++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index b183e2b606c8..6c7f365b1515 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -63,6 +63,16 @@ fwmark_reflect - BOOLEAN fwmark of the packet they are replying to. Default: 0 +fib_multipath_use_neigh - BOOLEAN + Use status of existing neighbor entry when determining nexthop for + multipath routes. If disabled, neighbor information is not used and + packets could be directed to a failed nexthop. Only valid for kernels + built with CONFIG_IP_ROUTE_MULTIPATH enabled. + Default: 0 (disabled) + Possible values: + 0 - disabled + 1 - enabled + route/max_size - INTEGER Maximum number of routes allowed in the kernel. Increase this when using large numbers of interfaces and/or routes. diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index a69cde3ce460..d061ffeb1e71 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -132,6 +132,9 @@ struct netns_ipv4 { struct list_head mr_tables; struct fib_rules_ops *mr_rules_ops; #endif +#endif +#ifdef CONFIG_IP_ROUTE_MULTIPATH + int sysctl_fib_multipath_use_neigh; #endif atomic_t rt_genid; }; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index d97268e8ff10..ab64d9f2eef9 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -1559,21 +1559,45 @@ int fib_sync_up(struct net_device *dev, unsigned int nh_flags) } #ifdef CONFIG_IP_ROUTE_MULTIPATH +static bool fib_good_nh(const struct fib_nh *nh) +{ + int state = NUD_REACHABLE; + + if (nh->nh_scope == RT_SCOPE_LINK) { + struct neighbour *n; + + rcu_read_lock_bh(); + + n = __ipv4_neigh_lookup_noref(nh->nh_dev, nh->nh_gw); + if (n) + state = n->nud_state; + + rcu_read_unlock_bh(); + } + + return !!(state & NUD_VALID); +} void fib_select_multipath(struct fib_result *res, int hash) { struct fib_info *fi = res->fi; + struct net *net = fi->fib_net; + bool first = false; for_nexthops(fi) { if (hash > atomic_read(&nh->nh_upper_bound)) continue; - res->nh_sel = nhsel; - return; + if (!net->ipv4.sysctl_fib_multipath_use_neigh || + fib_good_nh(nh)) { + res->nh_sel = nhsel; + return; + } + if (!first) { + res->nh_sel = nhsel; + first = true; + } } endfor_nexthops(fi); - - /* Race condition: route has just become dead. */ - res->nh_sel = 0; } #endif diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 1e1fe6086dd9..bb0419582b8d 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -960,6 +960,17 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, +#ifdef CONFIG_IP_ROUTE_MULTIPATH + { + .procname = "fib_multipath_use_neigh", + .data = &init_net.ipv4.sysctl_fib_multipath_use_neigh, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, +#endif { } }; -- GitLab From 1da8c681d5c122afe9fbadc02e92a0f9e3f7af44 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 7 Apr 2016 11:44:58 -0400 Subject: [PATCH 2029/9938] sunrpc: do not pull udp headers on receive Commit e6afc8ace6dd modified the udp receive path by pulling the udp header before queuing an skbuff onto the receive queue. Sunrpc also calls skb_recv_datagram to dequeue an skb from a udp socket. Modify this receive path to also no longer expect udp headers. Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") Reported-by: Franklin S Cooper Jr. Signed-off-by: Willem de Bruijn Tested-by: Thierry Reding Signed-off-by: David S. Miller --- net/sunrpc/socklib.c | 2 +- net/sunrpc/svcsock.c | 5 ++--- net/sunrpc/xprtsock.c | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index de70c78025d7..f217c348b341 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c @@ -155,7 +155,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) struct xdr_skb_reader desc; desc.skb = skb; - desc.offset = sizeof(struct udphdr); + desc.offset = 0; desc.count = skb->len - desc.offset; if (skb_csum_unnecessary(skb)) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 1413cdcc131c..71d6072664d2 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -617,7 +617,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) svsk->sk_sk->sk_stamp = skb->tstamp; set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); /* there may be more data... */ - len = skb->len - sizeof(struct udphdr); + len = skb->len; rqstp->rq_arg.len = len; rqstp->rq_prot = IPPROTO_UDP; @@ -641,8 +641,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) skb_free_datagram_locked(svsk->sk_sk, skb); } else { /* we can use it in-place */ - rqstp->rq_arg.head[0].iov_base = skb->data + - sizeof(struct udphdr); + rqstp->rq_arg.head[0].iov_base = skb->data; rqstp->rq_arg.head[0].iov_len = len; if (skb_checksum_complete(skb)) goto out_free; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 65e759569e48..c1fc7b20bbc1 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -995,15 +995,14 @@ static void xs_udp_data_read_skb(struct rpc_xprt *xprt, u32 _xid; __be32 *xp; - repsize = skb->len - sizeof(struct udphdr); + repsize = skb->len; if (repsize < 4) { dprintk("RPC: impossible RPC reply size %d!\n", repsize); return; } /* Copy the XID from the skb... */ - xp = skb_header_pointer(skb, sizeof(struct udphdr), - sizeof(_xid), &_xid); + xp = skb_header_pointer(skb, 0, sizeof(_xid), &_xid); if (xp == NULL) return; -- GitLab From 4d0fc73ebe94ac984a187f21fbf4f3a1ac846f5a Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 7 Apr 2016 11:44:59 -0400 Subject: [PATCH 2030/9938] rxrpc: do not pull udp headers on receive Commit e6afc8ace6dd modified the udp receive path by pulling the udp header before queuing an skbuff onto the receive queue. Rxrpc also calls skb_recv_datagram to dequeue an skb from a udp socket. Modify this receive path to also no longer expect udp headers. Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") Signed-off-by: Willem de Bruijn Tested-by: Thierry Reding Signed-off-by: David S. Miller --- net/rxrpc/ar-input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index 63ed75c40e29..4824a827d10d 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c @@ -612,9 +612,9 @@ int rxrpc_extract_header(struct rxrpc_skb_priv *sp, struct sk_buff *skb) struct rxrpc_wire_header whdr; /* dig out the RxRPC connection details */ - if (skb_copy_bits(skb, sizeof(struct udphdr), &whdr, sizeof(whdr)) < 0) + if (skb_copy_bits(skb, 0, &whdr, sizeof(whdr)) < 0) return -EBADMSG; - if (!pskb_pull(skb, sizeof(struct udphdr) + sizeof(whdr))) + if (!pskb_pull(skb, sizeof(whdr))) BUG(); memset(sp, 0, sizeof(*sp)); -- GitLab From 48c830809ce6e143781172c03a9794cb66802b31 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 24 Feb 2016 13:43:54 -0600 Subject: [PATCH 2031/9938] PCI: Move informational printk to pci_add_dma_alias() One of the quirks that adds DMA aliases logs an informational message in dmesg. Move that to pci_add_dma_alias() so all users log the message consistently. No functional change intended (except extra message). Signed-off-by: Bjorn Helgaas Reviewed-by: Alex Williamson --- drivers/pci/pci.c | 2 ++ drivers/pci/quirks.c | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1162118d1093..c82ebd0f6982 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4590,6 +4590,8 @@ void pci_add_dma_alias(struct pci_dev *dev, u8 devfn) { dev->dma_alias_devfn = devfn; dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; + dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n", + PCI_SLOT(devfn), PCI_FUNC(devfn)); } bool pci_device_is_present(struct pci_dev *pdev) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e45a7a8338bb..7559e4024447 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3691,12 +3691,8 @@ static void quirk_fixed_dma_alias(struct pci_dev *dev) const struct pci_device_id *id; id = pci_match_id(fixed_dma_alias_tbl, dev); - if (id) { + if (id) pci_add_dma_alias(dev, id->driver_data); - dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n", - PCI_SLOT(id->driver_data), - PCI_FUNC(id->driver_data)); - } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADAPTEC2, 0x0285, quirk_fixed_dma_alias); -- GitLab From 338c3149a221527e202ee26b1e35f76c965bb6c0 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Thu, 3 Mar 2016 15:38:02 +0100 Subject: [PATCH 2032/9938] PCI: Add support for multiple DMA aliases Solve IOMMU support issues with PCIe non-transparent bridges that use Requester ID look-up tables (RID-LUT), e.g., the PEX8733. The NTB connects devices in two independent PCI domains. Devices separated by the NTB are not able to discover each other. A PCI packet being forwared from one domain to another has to have its RID modified so it appears on correct bus and completions are forwarded back to the original domain through the NTB. The RID is translated using a preprogrammed table (LUT) and the PCI packet propagates upstream away from the NTB. If the destination system has IOMMU enabled, the packet will be discarded because the new RID is unknown to the IOMMU. Adding a DMA alias for the new RID allows IOMMU to properly recognize the packet. Each device behind the NTB has a unique RID assigned in the RID-LUT. The current DMA alias implementation supports only a single alias, so it's not possible to support mutiple devices behind the NTB when IOMMU is enabled. Enable all possible aliases on a given bus (256) that are stored in a bitset. Alias devfn is directly translated to a bit number. The bitset is not allocated for devices that have no need for DMA aliases. More details can be found in the following article: http://www.plxtech.com/files/pdf/technical/expresslane/RTC_Enabling%20MulitHostSystemDesigns.pdf Signed-off-by: Jacek Lawrynowicz Signed-off-by: Bjorn Helgaas Reviewed-by: Alex Williamson Acked-by: David Woodhouse Acked-by: Joerg Roedel --- drivers/iommu/iommu.c | 10 +++------- drivers/pci/pci.c | 19 +++++++++++++++++-- drivers/pci/probe.c | 1 + drivers/pci/search.c | 14 +++++++++----- include/linux/pci.h | 5 ++--- 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index bfd4f7c3b1d8..1b49e940a318 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -660,8 +660,8 @@ static struct iommu_group *get_pci_function_alias_group(struct pci_dev *pdev, } /* - * Look for aliases to or from the given device for exisiting groups. The - * dma_alias_devfn only supports aliases on the same bus, therefore the search + * Look for aliases to or from the given device for existing groups. DMA + * aliases are only supported on the same bus, therefore the search * space is quite small (especially since we're really only looking at pcie * device, and therefore only expect multiple slots on the root complex or * downstream switch ports). It's conceivable though that a pair of @@ -686,11 +686,7 @@ static struct iommu_group *get_pci_alias_group(struct pci_dev *pdev, continue; /* We alias them or they alias us */ - if (((pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) && - pdev->dma_alias_devfn == tmp->devfn) || - ((tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) && - tmp->dma_alias_devfn == pdev->devfn)) { - + if (pci_devs_are_dma_aliases(pdev, tmp)) { group = get_pci_alias_group(tmp, devfns); if (group) { pci_dev_put(tmp); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index c82ebd0f6982..0b90c2186f1c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4588,12 +4588,27 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, */ void pci_add_dma_alias(struct pci_dev *dev, u8 devfn) { - dev->dma_alias_devfn = devfn; - dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; + if (!dev->dma_alias_mask) + dev->dma_alias_mask = kcalloc(BITS_TO_LONGS(U8_MAX), + sizeof(long), GFP_KERNEL); + if (!dev->dma_alias_mask) { + dev_warn(&dev->dev, "Unable to allocate DMA alias mask\n"); + return; + } + + set_bit(devfn, dev->dma_alias_mask); dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n", PCI_SLOT(devfn), PCI_FUNC(devfn)); } +bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2) +{ + return (dev1->dma_alias_mask && + test_bit(dev2->devfn, dev1->dma_alias_mask)) || + (dev2->dma_alias_mask && + test_bit(dev1->devfn, dev2->dma_alias_mask)); +} + bool pci_device_is_present(struct pci_dev *pdev) { u32 v; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 8004f67c57ec..ae7daeb83e21 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1537,6 +1537,7 @@ static void pci_release_dev(struct device *dev) pcibios_release_device(pci_dev); pci_bus_put(pci_dev->bus); kfree(pci_dev->driver_override); + kfree(pci_dev->dma_alias_mask); kfree(pci_dev); } diff --git a/drivers/pci/search.c b/drivers/pci/search.c index a20ce7d5e2a7..33e0f033a48e 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -40,11 +40,15 @@ int pci_for_each_dma_alias(struct pci_dev *pdev, * If the device is broken and uses an alias requester ID for * DMA, iterate over that too. */ - if (unlikely(pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN)) { - ret = fn(pdev, PCI_DEVID(pdev->bus->number, - pdev->dma_alias_devfn), data); - if (ret) - return ret; + if (unlikely(pdev->dma_alias_mask)) { + u8 devfn; + + for_each_set_bit(devfn, pdev->dma_alias_mask, U8_MAX) { + ret = fn(pdev, PCI_DEVID(pdev->bus->number, devfn), + data); + if (ret) + return ret; + } } for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) { diff --git a/include/linux/pci.h b/include/linux/pci.h index 7e7019064437..5581d05f7833 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -166,8 +166,6 @@ enum pci_dev_flags { PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) (1 << 2), /* Flag for quirk use to store if quirk-specific ACS is enabled */ PCI_DEV_FLAGS_ACS_ENABLED_QUIRK = (__force pci_dev_flags_t) (1 << 3), - /* Flag to indicate the device uses dma_alias_devfn */ - PCI_DEV_FLAGS_DMA_ALIAS_DEVFN = (__force pci_dev_flags_t) (1 << 4), /* Use a PCIe-to-PCI bridge alias even if !pci_is_pcie */ PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS = (__force pci_dev_flags_t) (1 << 5), /* Do not use bus resets for device */ @@ -273,7 +271,7 @@ struct pci_dev { u8 rom_base_reg; /* which config register controls the ROM */ u8 pin; /* which interrupt pin this device uses */ u16 pcie_flags_reg; /* cached PCIe Capabilities Register */ - u8 dma_alias_devfn;/* devfn of DMA alias, if any */ + unsigned long *dma_alias_mask;/* mask of enabled devfn aliases */ struct pci_driver *driver; /* which driver has allocated this device */ u64 dma_mask; /* Mask of the bits of bus address this @@ -1989,6 +1987,7 @@ static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev) #endif void pci_add_dma_alias(struct pci_dev *dev, u8 devfn); +bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2); int pci_for_each_dma_alias(struct pci_dev *pdev, int (*fn)(struct pci_dev *pdev, u16 alias, void *data), void *data); -- GitLab From 2f02f7aea7b6c9a9312846c006e076ae6ad026a4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:03 +0100 Subject: [PATCH 2033/9938] afs: Wait for outstanding async calls before closing rxrpc socket The afs filesystem needs to wait for any outstanding asynchronous calls (such as FS.GiveUpCallBacks cleaning up the callbacks lodged with a server) to complete before closing the AF_RXRPC socket when unloading the module. This may occur if the module is removed too quickly after unmounting all filesystems. This will produce an error report that looks like: AFS: Assertion failed 1 == 0 is false 0x1 == 0x0 is false ------------[ cut here ]------------ kernel BUG at ../fs/afs/rxrpc.c:135! ... RIP: 0010:[] afs_close_socket+0xec/0x107 [kafs] ... Call Trace: [] afs_exit+0x1f/0x57 [kafs] [] SyS_delete_module+0xec/0x17d [] entry_SYSCALL_64_fastpath+0x12/0x6b Signed-off-by: David Howells Signed-off-by: David S. Miller --- fs/afs/rxrpc.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index b50642870a43..b4d337ad6e36 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -65,6 +65,12 @@ static void afs_async_workfn(struct work_struct *work) call->async_workfn(call); } +static int afs_wait_atomic_t(atomic_t *p) +{ + schedule(); + return 0; +} + /* * open an RxRPC socket and bind it to be a server for callback notifications * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT @@ -126,13 +132,16 @@ void afs_close_socket(void) { _enter(""); + wait_on_atomic_t(&afs_outstanding_calls, afs_wait_atomic_t, + TASK_UNINTERRUPTIBLE); + _debug("no outstanding calls"); + sock_release(afs_socket); _debug("dework"); destroy_workqueue(afs_async_calls); ASSERTCMP(atomic_read(&afs_outstanding_skbs), ==, 0); - ASSERTCMP(atomic_read(&afs_outstanding_calls), ==, 0); _leave(""); } @@ -178,8 +187,6 @@ static void afs_free_call(struct afs_call *call) { _debug("DONE %p{%s} [%d]", call, call->type->name, atomic_read(&afs_outstanding_calls)); - if (atomic_dec_return(&afs_outstanding_calls) == -1) - BUG(); ASSERTCMP(call->rxcall, ==, NULL); ASSERT(!work_pending(&call->async_work)); @@ -188,6 +195,9 @@ static void afs_free_call(struct afs_call *call) kfree(call->request); kfree(call); + + if (atomic_dec_and_test(&afs_outstanding_calls)) + wake_up_atomic_t(&afs_outstanding_calls); } /* -- GitLab From 8f7e6e75d3074dd1856a6105f7511249ee2f2ffd Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:09 +0100 Subject: [PATCH 2034/9938] rxrpc: Disable a debugging statement that has been left enabled. Disable a debugging statement that has been left enabled Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-ack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index 16d967075eaf..01a017a05f14 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -426,7 +426,7 @@ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, u32 hard) int tail = call->acks_tail, old_tail; int win = CIRC_CNT(call->acks_head, tail, call->acks_winsz); - kenter("{%u,%u},%u", call->acks_hard, win, hard); + _enter("{%u,%u},%u", call->acks_hard, win, hard); ASSERTCMP(hard - call->acks_hard, <=, win); -- GitLab From 8e688d9c166671bb4a6977384de2fe7f46a31ba4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:16 +0100 Subject: [PATCH 2035/9938] rxrpc: Move some miscellaneous bits out into their own file Move some miscellaneous bits out into their own file to make it easier to split the call handling. Signed-off-by: David Howells Signed-off-by: David S. Miller --- include/net/af_rxrpc.h | 1 + net/rxrpc/Makefile | 3 +- net/rxrpc/ar-ack.c | 68 ------------------------------- net/rxrpc/ar-input.c | 6 --- net/rxrpc/ar-internal.h | 24 ++++++----- net/rxrpc/misc.c | 89 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 84 deletions(-) create mode 100644 net/rxrpc/misc.c diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index e797d45a5ae6..4fd3e4a2cadd 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -12,6 +12,7 @@ #ifndef _NET_RXRPC_H #define _NET_RXRPC_H +#include #include struct rxrpc_call; diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index ec126f91276b..5b98c1640d6d 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile @@ -18,7 +18,8 @@ af-rxrpc-y := \ ar-recvmsg.o \ ar-security.o \ ar-skbuff.o \ - ar-transport.o + ar-transport.o \ + misc.o af-rxrpc-$(CONFIG_PROC_FS) += ar-proc.o af-rxrpc-$(CONFIG_SYSCTL) += sysctl.o diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index 01a017a05f14..54bf43ba9aa8 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -19,74 +19,6 @@ #include #include "ar-internal.h" -/* - * How long to wait before scheduling ACK generation after seeing a - * packet with RXRPC_REQUEST_ACK set (in jiffies). - */ -unsigned int rxrpc_requested_ack_delay = 1; - -/* - * How long to wait before scheduling an ACK with subtype DELAY (in jiffies). - * - * We use this when we've received new data packets. If those packets aren't - * all consumed within this time we will send a DELAY ACK if an ACK was not - * requested to let the sender know it doesn't need to resend. - */ -unsigned int rxrpc_soft_ack_delay = 1 * HZ; - -/* - * How long to wait before scheduling an ACK with subtype IDLE (in jiffies). - * - * We use this when we've consumed some previously soft-ACK'd packets when - * further packets aren't immediately received to decide when to send an IDLE - * ACK let the other end know that it can free up its Tx buffer space. - */ -unsigned int rxrpc_idle_ack_delay = 0.5 * HZ; - -/* - * Receive window size in packets. This indicates the maximum number of - * unconsumed received packets we're willing to retain in memory. Once this - * limit is hit, we should generate an EXCEEDS_WINDOW ACK and discard further - * packets. - */ -unsigned int rxrpc_rx_window_size = 32; - -/* - * Maximum Rx MTU size. This indicates to the sender the size of jumbo packet - * made by gluing normal packets together that we're willing to handle. - */ -unsigned int rxrpc_rx_mtu = 5692; - -/* - * The maximum number of fragments in a received jumbo packet that we tell the - * sender that we're willing to handle. - */ -unsigned int rxrpc_rx_jumbo_max = 4; - -static const char *rxrpc_acks(u8 reason) -{ - static const char *const str[] = { - "---", "REQ", "DUP", "OOS", "WIN", "MEM", "PNG", "PNR", "DLY", - "IDL", "-?-" - }; - - if (reason >= ARRAY_SIZE(str)) - reason = ARRAY_SIZE(str) - 1; - return str[reason]; -} - -static const s8 rxrpc_ack_priority[] = { - [0] = 0, - [RXRPC_ACK_DELAY] = 1, - [RXRPC_ACK_REQUESTED] = 2, - [RXRPC_ACK_IDLE] = 3, - [RXRPC_ACK_PING_RESPONSE] = 4, - [RXRPC_ACK_DUPLICATE] = 5, - [RXRPC_ACK_OUT_OF_SEQUENCE] = 6, - [RXRPC_ACK_EXCEEDS_WINDOW] = 7, - [RXRPC_ACK_NOSPACE] = 8, -}; - /* * propose an ACK be sent */ diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index 4824a827d10d..c947cd13f435 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c @@ -25,12 +25,6 @@ #include #include "ar-internal.h" -const char *rxrpc_pkts[] = { - "?00", - "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", - "?09", "?10", "?11", "?12", "VERSION", "?14", "?15" -}; - /* * queue a packet for recvmsg to pass to userspace * - the caller must hold a lock on call->lock diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index cd6cdbe87125..24126d954f38 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -478,13 +478,6 @@ int rxrpc_reject_call(struct rxrpc_sock *); /* * ar-ack.c */ -extern unsigned int rxrpc_requested_ack_delay; -extern unsigned int rxrpc_soft_ack_delay; -extern unsigned int rxrpc_idle_ack_delay; -extern unsigned int rxrpc_rx_window_size; -extern unsigned int rxrpc_rx_mtu; -extern unsigned int rxrpc_rx_jumbo_max; - void __rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool); void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool); void rxrpc_process_call(struct work_struct *); @@ -550,8 +543,6 @@ void rxrpc_UDP_error_handler(struct work_struct *); /* * ar-input.c */ -extern const char *rxrpc_pkts[]; - void rxrpc_data_ready(struct sock *); int rxrpc_queue_rcv_skb(struct rxrpc_call *, struct sk_buff *, bool, bool); void rxrpc_fast_process_packet(struct rxrpc_call *, struct sk_buff *); @@ -636,6 +627,21 @@ void __exit rxrpc_destroy_all_transports(void); struct rxrpc_transport *rxrpc_find_transport(struct rxrpc_local *, struct rxrpc_peer *); +/* + * misc.c + */ +extern unsigned int rxrpc_requested_ack_delay; +extern unsigned int rxrpc_soft_ack_delay; +extern unsigned int rxrpc_idle_ack_delay; +extern unsigned int rxrpc_rx_window_size; +extern unsigned int rxrpc_rx_mtu; +extern unsigned int rxrpc_rx_jumbo_max; + +extern const char *rxrpc_pkts[]; +extern const s8 rxrpc_ack_priority[]; + +extern const char *rxrpc_acks(u8 reason); + /* * sysctl.c */ diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c new file mode 100644 index 000000000000..8ebeec3384e1 --- /dev/null +++ b/net/rxrpc/misc.c @@ -0,0 +1,89 @@ +/* Miscellaneous bits + * + * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include +#include +#include "ar-internal.h" + +/* + * How long to wait before scheduling ACK generation after seeing a + * packet with RXRPC_REQUEST_ACK set (in jiffies). + */ +unsigned int rxrpc_requested_ack_delay = 1; + +/* + * How long to wait before scheduling an ACK with subtype DELAY (in jiffies). + * + * We use this when we've received new data packets. If those packets aren't + * all consumed within this time we will send a DELAY ACK if an ACK was not + * requested to let the sender know it doesn't need to resend. + */ +unsigned int rxrpc_soft_ack_delay = 1 * HZ; + +/* + * How long to wait before scheduling an ACK with subtype IDLE (in jiffies). + * + * We use this when we've consumed some previously soft-ACK'd packets when + * further packets aren't immediately received to decide when to send an IDLE + * ACK let the other end know that it can free up its Tx buffer space. + */ +unsigned int rxrpc_idle_ack_delay = 0.5 * HZ; + +/* + * Receive window size in packets. This indicates the maximum number of + * unconsumed received packets we're willing to retain in memory. Once this + * limit is hit, we should generate an EXCEEDS_WINDOW ACK and discard further + * packets. + */ +unsigned int rxrpc_rx_window_size = 32; + +/* + * Maximum Rx MTU size. This indicates to the sender the size of jumbo packet + * made by gluing normal packets together that we're willing to handle. + */ +unsigned int rxrpc_rx_mtu = 5692; + +/* + * The maximum number of fragments in a received jumbo packet that we tell the + * sender that we're willing to handle. + */ +unsigned int rxrpc_rx_jumbo_max = 4; + +const char *rxrpc_pkts[] = { + "?00", + "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", + "?09", "?10", "?11", "?12", "VERSION", "?14", "?15" +}; + +const s8 rxrpc_ack_priority[] = { + [0] = 0, + [RXRPC_ACK_DELAY] = 1, + [RXRPC_ACK_REQUESTED] = 2, + [RXRPC_ACK_IDLE] = 3, + [RXRPC_ACK_PING_RESPONSE] = 4, + [RXRPC_ACK_DUPLICATE] = 5, + [RXRPC_ACK_OUT_OF_SEQUENCE] = 6, + [RXRPC_ACK_EXCEEDS_WINDOW] = 7, + [RXRPC_ACK_NOSPACE] = 8, +}; + +const char *rxrpc_acks(u8 reason) +{ + static const char *const str[] = { + "---", "REQ", "DUP", "OOS", "WIN", "MEM", "PNG", "PNR", "DLY", + "IDL", "-?-" + }; + + if (reason >= ARRAY_SIZE(str)) + reason = ARRAY_SIZE(str) - 1; + return str[reason]; +} -- GitLab From 5b3e87f19e71b7a2f789c40de04704886932b5cf Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:23 +0100 Subject: [PATCH 2036/9938] rxrpc: Static arrays of strings should be const char *const[] Static arrays of strings should be const char *const[]. Signed-off-by: David Howells Signed-off-by: David S. Miller --- include/rxrpc/packet.h | 2 -- net/rxrpc/ar-internal.h | 2 +- net/rxrpc/misc.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/rxrpc/packet.h b/include/rxrpc/packet.h index 9ebab3a8cf0a..b2017440b765 100644 --- a/include/rxrpc/packet.h +++ b/include/rxrpc/packet.h @@ -68,8 +68,6 @@ struct rxrpc_wire_header { } __packed; -extern const char *rxrpc_pkts[]; - #define RXRPC_SUPPORTED_PACKET_TYPES ( \ (1 << RXRPC_PACKET_TYPE_DATA) | \ (1 << RXRPC_PACKET_TYPE_ACK) | \ diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 24126d954f38..eeb829e837e1 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -637,7 +637,7 @@ extern unsigned int rxrpc_rx_window_size; extern unsigned int rxrpc_rx_mtu; extern unsigned int rxrpc_rx_jumbo_max; -extern const char *rxrpc_pkts[]; +extern const char *const rxrpc_pkts[]; extern const s8 rxrpc_ack_priority[]; extern const char *rxrpc_acks(u8 reason); diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c index 8ebeec3384e1..1afe9876e79f 100644 --- a/net/rxrpc/misc.c +++ b/net/rxrpc/misc.c @@ -58,7 +58,7 @@ unsigned int rxrpc_rx_mtu = 5692; */ unsigned int rxrpc_rx_jumbo_max = 4; -const char *rxrpc_pkts[] = { +const char *const rxrpc_pkts[] = { "?00", "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", "?09", "?10", "?11", "?12", "VERSION", "?14", "?15" -- GitLab From dc44b3a09aec9ac57c1e7410677c87c0e6453624 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:30 +0100 Subject: [PATCH 2037/9938] rxrpc: Differentiate local and remote abort codes in structs In the rxrpc_connection and rxrpc_call structs, there's one field to hold the abort code, no matter whether that value was generated locally to be sent or was received from the peer via an abort packet. Split the abort code fields in two for cleanliness sake and add an error field to hold the Linux error number to the rxrpc_call struct too (sometimes this is generated in a context where we can't return it to userspace directly). Furthermore, add a skb mark to indicate a packet that caused a local abort to be generated so that recvmsg() can pick up the correct abort code. A future addition will need to be to indicate to userspace the difference between aborts via a control message. Signed-off-by: David Howells Signed-off-by: David S. Miller --- fs/afs/rxrpc.c | 14 +++++++++++--- include/net/af_rxrpc.h | 3 ++- net/rxrpc/ar-ack.c | 4 ++-- net/rxrpc/ar-call.c | 4 ++-- net/rxrpc/ar-connevent.c | 12 +++++++----- net/rxrpc/ar-input.c | 6 +++--- net/rxrpc/ar-internal.h | 10 +++++++--- net/rxrpc/ar-output.c | 2 +- net/rxrpc/ar-proc.c | 2 +- net/rxrpc/ar-recvmsg.c | 18 ++++++++++++++---- 10 files changed, 50 insertions(+), 25 deletions(-) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index b4d337ad6e36..63cd9f939f19 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -430,9 +430,11 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, } /* - * handles intercepted messages that were arriving in the socket's Rx queue - * - called with the socket receive queue lock held to ensure message ordering - * - called with softirqs disabled + * Handles intercepted messages that were arriving in the socket's Rx queue. + * + * Called from the AF_RXRPC call processor in waitqueue process context. For + * each call, it is guaranteed this will be called in order of packet to be + * delivered. */ static void afs_rx_interceptor(struct sock *sk, unsigned long user_call_ID, struct sk_buff *skb) @@ -523,6 +525,12 @@ static void afs_deliver_to_call(struct afs_call *call) call->state = AFS_CALL_ABORTED; _debug("Rcv ABORT %u -> %d", abort_code, call->error); break; + case RXRPC_SKB_MARK_LOCAL_ABORT: + abort_code = rxrpc_kernel_get_abort_code(skb); + call->error = call->type->abort_to_error(abort_code); + call->state = AFS_CALL_ABORTED; + _debug("Loc ABORT %u -> %d", abort_code, call->error); + break; case RXRPC_SKB_MARK_NET_ERROR: call->error = -rxrpc_kernel_get_error_number(skb); call->state = AFS_CALL_ERROR; diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 4fd3e4a2cadd..ac1bc3c49fbd 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -20,11 +20,12 @@ struct rxrpc_call; /* * the mark applied to socket buffers that may be intercepted */ -enum { +enum rxrpc_skb_mark { RXRPC_SKB_MARK_DATA, /* data message */ RXRPC_SKB_MARK_FINAL_ACK, /* final ACK received message */ RXRPC_SKB_MARK_BUSY, /* server busy message */ RXRPC_SKB_MARK_REMOTE_ABORT, /* remote abort message */ + RXRPC_SKB_MARK_LOCAL_ABORT, /* local abort message */ RXRPC_SKB_MARK_NET_ERROR, /* network error message */ RXRPC_SKB_MARK_LOCAL_ERROR, /* local error message */ RXRPC_SKB_MARK_NEW_CALL, /* local error message */ diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index 54bf43ba9aa8..d0eb98e1391c 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -905,7 +905,7 @@ void rxrpc_process_call(struct work_struct *work) ECONNABORTED, true) < 0) goto no_mem; whdr.type = RXRPC_PACKET_TYPE_ABORT; - data = htonl(call->abort_code); + data = htonl(call->local_abort); iov[1].iov_base = &data; iov[1].iov_len = sizeof(data); genbit = RXRPC_CALL_EV_ABORT; @@ -968,7 +968,7 @@ void rxrpc_process_call(struct work_struct *work) write_lock_bh(&call->state_lock); if (call->state <= RXRPC_CALL_COMPLETE) { call->state = RXRPC_CALL_LOCALLY_ABORTED; - call->abort_code = RX_CALL_TIMEOUT; + call->local_abort = RX_CALL_TIMEOUT; set_bit(RXRPC_CALL_EV_ABORT, &call->events); } write_unlock_bh(&call->state_lock); diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c index 7c8d300ade9b..67a211f0ebba 100644 --- a/net/rxrpc/ar-call.c +++ b/net/rxrpc/ar-call.c @@ -682,7 +682,7 @@ void rxrpc_release_call(struct rxrpc_call *call) call->state != RXRPC_CALL_CLIENT_FINAL_ACK) { _debug("+++ ABORTING STATE %d +++\n", call->state); call->state = RXRPC_CALL_LOCALLY_ABORTED; - call->abort_code = RX_CALL_DEAD; + call->local_abort = RX_CALL_DEAD; set_bit(RXRPC_CALL_EV_ABORT, &call->events); rxrpc_queue_call(call); } @@ -758,7 +758,7 @@ static void rxrpc_mark_call_released(struct rxrpc_call *call) if (call->state < RXRPC_CALL_COMPLETE) { _debug("abort call %p", call); call->state = RXRPC_CALL_LOCALLY_ABORTED; - call->abort_code = RX_CALL_DEAD; + call->local_abort = RX_CALL_DEAD; if (!test_and_set_bit(RXRPC_CALL_EV_ABORT, &call->events)) sched = true; } diff --git a/net/rxrpc/ar-connevent.c b/net/rxrpc/ar-connevent.c index 1bdaaed8cdc4..4dc6ab81fd2f 100644 --- a/net/rxrpc/ar-connevent.c +++ b/net/rxrpc/ar-connevent.c @@ -40,11 +40,13 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn, int state, write_lock(&call->state_lock); if (call->state <= RXRPC_CALL_COMPLETE) { call->state = state; - call->abort_code = abort_code; - if (state == RXRPC_CALL_LOCALLY_ABORTED) + if (state == RXRPC_CALL_LOCALLY_ABORTED) { + call->local_abort = conn->local_abort; set_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events); - else + } else { + call->remote_abort = conn->remote_abort; set_bit(RXRPC_CALL_EV_RCVD_ABORT, &call->events); + } rxrpc_queue_call(call); } write_unlock(&call->state_lock); @@ -101,7 +103,7 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn, whdr._rsvd = 0; whdr.serviceId = htons(conn->service_id); - word = htonl(abort_code); + word = htonl(conn->local_abort); iov[0].iov_base = &whdr; iov[0].iov_len = sizeof(whdr); @@ -112,7 +114,7 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn, serial = atomic_inc_return(&conn->serial); whdr.serial = htonl(serial); - _proto("Tx CONN ABORT %%%u { %d }", serial, abort_code); + _proto("Tx CONN ABORT %%%u { %d }", serial, conn->local_abort); ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 2, len); if (ret < 0) { diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index c947cd13f435..c6c784d3a3e8 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c @@ -349,7 +349,7 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb) write_lock_bh(&call->state_lock); if (call->state < RXRPC_CALL_COMPLETE) { call->state = RXRPC_CALL_REMOTELY_ABORTED; - call->abort_code = abort_code; + call->remote_abort = abort_code; set_bit(RXRPC_CALL_EV_RCVD_ABORT, &call->events); rxrpc_queue_call(call); } @@ -422,7 +422,7 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb) protocol_error_locked: if (call->state <= RXRPC_CALL_COMPLETE) { call->state = RXRPC_CALL_LOCALLY_ABORTED; - call->abort_code = RX_PROTOCOL_ERROR; + call->local_abort = RX_PROTOCOL_ERROR; set_bit(RXRPC_CALL_EV_ABORT, &call->events); rxrpc_queue_call(call); } @@ -494,7 +494,7 @@ static void rxrpc_process_jumbo_packet(struct rxrpc_call *call, write_lock_bh(&call->state_lock); if (call->state <= RXRPC_CALL_COMPLETE) { call->state = RXRPC_CALL_LOCALLY_ABORTED; - call->abort_code = RX_PROTOCOL_ERROR; + call->local_abort = RX_PROTOCOL_ERROR; set_bit(RXRPC_CALL_EV_ABORT, &call->events); rxrpc_queue_call(call); } diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index eeb829e837e1..258b74a2a23f 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -289,7 +289,9 @@ struct rxrpc_connection { RXRPC_CONN_LOCALLY_ABORTED, /* - conn aborted locally */ RXRPC_CONN_NETWORK_ERROR, /* - conn terminated by network error */ } state; - int error; /* error code for local abort */ + u32 local_abort; /* local abort code */ + u32 remote_abort; /* remote abort code */ + int error; /* local error incurred */ int debug_id; /* debug ID for printks */ unsigned int call_counter; /* call ID counter */ atomic_t serial; /* packet serial number counter */ @@ -399,7 +401,9 @@ struct rxrpc_call { rwlock_t state_lock; /* lock for state transition */ atomic_t usage; atomic_t sequence; /* Tx data packet sequence counter */ - u32 abort_code; /* local/remote abort code */ + u32 local_abort; /* local abort code */ + u32 remote_abort; /* remote abort code */ + int error; /* local error incurred */ enum rxrpc_call_state state : 8; /* current state of call */ int debug_id; /* debug ID for printks */ u8 channel; /* connection channel occupied by this call */ @@ -453,7 +457,7 @@ static inline void rxrpc_abort_call(struct rxrpc_call *call, u32 abort_code) { write_lock_bh(&call->state_lock); if (call->state < RXRPC_CALL_COMPLETE) { - call->abort_code = abort_code; + call->local_abort = abort_code; call->state = RXRPC_CALL_LOCALLY_ABORTED; set_bit(RXRPC_CALL_EV_ABORT, &call->events); } diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index d36fb6e1a29c..94e7d9537437 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c @@ -110,7 +110,7 @@ static void rxrpc_send_abort(struct rxrpc_call *call, u32 abort_code) if (call->state <= RXRPC_CALL_COMPLETE) { call->state = RXRPC_CALL_LOCALLY_ABORTED; - call->abort_code = abort_code; + call->local_abort = abort_code; set_bit(RXRPC_CALL_EV_ABORT, &call->events); del_timer_sync(&call->resend_timer); del_timer_sync(&call->ack_timer); diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c index 525b2ba5a8f4..225163bc658d 100644 --- a/net/rxrpc/ar-proc.c +++ b/net/rxrpc/ar-proc.c @@ -80,7 +80,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) call->conn->in_clientflag ? "Svc" : "Clt", atomic_read(&call->usage), rxrpc_call_states[call->state], - call->abort_code, + call->remote_abort ?: call->local_abort, call->user_call_ID); return 0; diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index 64facba24a45..160f0927aa3e 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c @@ -288,7 +288,11 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ret = put_cmsg(msg, SOL_RXRPC, RXRPC_BUSY, 0, &abort_code); break; case RXRPC_SKB_MARK_REMOTE_ABORT: - abort_code = call->abort_code; + abort_code = call->remote_abort; + ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &abort_code); + break; + case RXRPC_SKB_MARK_LOCAL_ABORT: + abort_code = call->local_abort; ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &abort_code); break; case RXRPC_SKB_MARK_NET_ERROR: @@ -303,6 +307,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, &abort_code); break; default: + pr_err("RxRPC: Unknown packet mark %u\n", skb->mark); BUG(); break; } @@ -401,9 +406,14 @@ u32 rxrpc_kernel_get_abort_code(struct sk_buff *skb) { struct rxrpc_skb_priv *sp = rxrpc_skb(skb); - ASSERTCMP(skb->mark, ==, RXRPC_SKB_MARK_REMOTE_ABORT); - - return sp->call->abort_code; + switch (skb->mark) { + case RXRPC_SKB_MARK_REMOTE_ABORT: + return sp->call->remote_abort; + case RXRPC_SKB_MARK_LOCAL_ABORT: + return sp->call->local_abort; + default: + BUG(); + } } EXPORT_SYMBOL(rxrpc_kernel_get_abort_code); -- GitLab From 843099cac0dbe421d7c3ea1f8662251fd7065731 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:37 +0100 Subject: [PATCH 2038/9938] rxrpc: Don't pass gfp around in incoming call handling functions Don't pass gfp around in incoming call handling functions, but rather hard code it at the points where we actually need it since the value comes from within the rxrpc driver and is always the same. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-accept.c | 4 ++-- net/rxrpc/ar-call.c | 7 +++---- net/rxrpc/ar-connection.c | 5 ++--- net/rxrpc/ar-internal.h | 5 ++--- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/net/rxrpc/ar-accept.c b/net/rxrpc/ar-accept.c index 277731a5e67a..e7a7f05f13e2 100644 --- a/net/rxrpc/ar-accept.c +++ b/net/rxrpc/ar-accept.c @@ -108,7 +108,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, goto error; } - conn = rxrpc_incoming_connection(trans, &sp->hdr, GFP_NOIO); + conn = rxrpc_incoming_connection(trans, &sp->hdr); rxrpc_put_transport(trans); if (IS_ERR(conn)) { _debug("no conn"); @@ -116,7 +116,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, goto error; } - call = rxrpc_incoming_call(rx, conn, &sp->hdr, GFP_NOIO); + call = rxrpc_incoming_call(rx, conn, &sp->hdr); rxrpc_put_connection(conn); if (IS_ERR(call)) { _debug("no call"); diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c index 67a211f0ebba..571a41fd5a32 100644 --- a/net/rxrpc/ar-call.c +++ b/net/rxrpc/ar-call.c @@ -411,18 +411,17 @@ struct rxrpc_call *rxrpc_get_client_call(struct rxrpc_sock *rx, */ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, struct rxrpc_connection *conn, - struct rxrpc_host_header *hdr, - gfp_t gfp) + struct rxrpc_host_header *hdr) { struct rxrpc_call *call, *candidate; struct rb_node **p, *parent; u32 call_id; - _enter(",%d,,%x", conn->debug_id, gfp); + _enter(",%d", conn->debug_id); ASSERT(rx != NULL); - candidate = rxrpc_alloc_call(gfp); + candidate = rxrpc_alloc_call(GFP_NOIO); if (!candidate) return ERR_PTR(-EBUSY); diff --git a/net/rxrpc/ar-connection.c b/net/rxrpc/ar-connection.c index 9942da1edbf6..9b6966777633 100644 --- a/net/rxrpc/ar-connection.c +++ b/net/rxrpc/ar-connection.c @@ -619,8 +619,7 @@ int rxrpc_connect_call(struct rxrpc_sock *rx, */ struct rxrpc_connection * rxrpc_incoming_connection(struct rxrpc_transport *trans, - struct rxrpc_host_header *hdr, - gfp_t gfp) + struct rxrpc_host_header *hdr) { struct rxrpc_connection *conn, *candidate = NULL; struct rb_node *p, **pp; @@ -659,7 +658,7 @@ rxrpc_incoming_connection(struct rxrpc_transport *trans, /* not yet present - create a candidate for a new record and then * redo the search */ - candidate = rxrpc_alloc_connection(gfp); + candidate = rxrpc_alloc_connection(GFP_NOIO); if (!candidate) { _leave(" = -ENOMEM"); return ERR_PTR(-ENOMEM); diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 258b74a2a23f..d38071b09f72 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -503,7 +503,7 @@ struct rxrpc_call *rxrpc_get_client_call(struct rxrpc_sock *, unsigned long, int, gfp_t); struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_connection *, - struct rxrpc_host_header *, gfp_t); + struct rxrpc_host_header *); struct rxrpc_call *rxrpc_find_server_call(struct rxrpc_sock *, unsigned long); void rxrpc_release_call(struct rxrpc_call *); void rxrpc_release_calls_on_socket(struct rxrpc_sock *); @@ -528,8 +528,7 @@ void __exit rxrpc_destroy_all_connections(void); struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_transport *, struct rxrpc_host_header *); extern struct rxrpc_connection * -rxrpc_incoming_connection(struct rxrpc_transport *, struct rxrpc_host_header *, - gfp_t); +rxrpc_incoming_connection(struct rxrpc_transport *, struct rxrpc_host_header *); /* * ar-connevent.c -- GitLab From 6dd050f88d702e2718bd856ea014487563207756 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:44 +0100 Subject: [PATCH 2039/9938] rxrpc: Don't assume transport address family and size when using it Don't assume transport address family and size when using the peer address to send a packet. Instead, use the start of the transport address rather than any particular element of the union and use the transport address length noted inside the sockaddr_rxrpc struct. This will be necessary when IPv6 support is introduced. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-ack.c | 4 ++-- net/rxrpc/ar-connevent.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index d0eb98e1391c..3cd9264806a4 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -833,8 +833,8 @@ void rxrpc_process_call(struct work_struct *work) /* there's a good chance we're going to have to send a message, so set * one up in advance */ - msg.msg_name = &call->conn->trans->peer->srx.transport.sin; - msg.msg_namelen = sizeof(call->conn->trans->peer->srx.transport.sin); + msg.msg_name = &call->conn->trans->peer->srx.transport; + msg.msg_namelen = call->conn->trans->peer->srx.transport_len; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; diff --git a/net/rxrpc/ar-connevent.c b/net/rxrpc/ar-connevent.c index 4dc6ab81fd2f..291522392ac7 100644 --- a/net/rxrpc/ar-connevent.c +++ b/net/rxrpc/ar-connevent.c @@ -86,8 +86,8 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn, rxrpc_abort_calls(conn, RXRPC_CALL_LOCALLY_ABORTED, abort_code); - msg.msg_name = &conn->trans->peer->srx.transport.sin; - msg.msg_namelen = sizeof(conn->trans->peer->srx.transport.sin); + msg.msg_name = &conn->trans->peer->srx.transport; + msg.msg_namelen = conn->trans->peer->srx.transport_len; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; -- GitLab From 648af7fca15901740c7aaafd55904ebd54d01860 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:51 +0100 Subject: [PATCH 2040/9938] rxrpc: Absorb the rxkad security module Absorb the rxkad security module into the af_rxrpc module so that there's only one module file. This avoids a circular dependency whereby rxkad pins af_rxrpc and cached connections pin rxkad but can't be manually evicted (they will expire eventually and cease pinning). With this change, af_rxrpc can just be unloaded, despite having cached connections. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/Kconfig | 2 +- net/rxrpc/Makefile | 3 +- net/rxrpc/af_rxrpc.c | 9 +++ net/rxrpc/ar-internal.h | 21 +++++-- net/rxrpc/ar-security.c | 123 +++++++++++----------------------------- net/rxrpc/rxkad.c | 61 ++++++++------------ 6 files changed, 85 insertions(+), 134 deletions(-) diff --git a/net/rxrpc/Kconfig b/net/rxrpc/Kconfig index 23dcef12b986..784c53163b7b 100644 --- a/net/rxrpc/Kconfig +++ b/net/rxrpc/Kconfig @@ -30,7 +30,7 @@ config AF_RXRPC_DEBUG config RXKAD - tristate "RxRPC Kerberos security" + bool "RxRPC Kerberos security" depends on AF_RXRPC select CRYPTO select CRYPTO_MANAGER diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index 5b98c1640d6d..fa09cb55bfce 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile @@ -22,8 +22,7 @@ af-rxrpc-y := \ misc.o af-rxrpc-$(CONFIG_PROC_FS) += ar-proc.o +af-rxrpc-$(CONFIG_RXKAD) += rxkad.o af-rxrpc-$(CONFIG_SYSCTL) += sysctl.o obj-$(CONFIG_AF_RXRPC) += af-rxrpc.o - -obj-$(CONFIG_RXKAD) += rxkad.o diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 9d935fa5a2a9..e45e94ca030f 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -806,6 +806,12 @@ static int __init af_rxrpc_init(void) goto error_work_queue; } + ret = rxrpc_init_security(); + if (ret < 0) { + printk(KERN_CRIT "RxRPC: Cannot initialise security\n"); + goto error_security; + } + ret = proto_register(&rxrpc_proto, 1); if (ret < 0) { printk(KERN_CRIT "RxRPC: Cannot register protocol\n"); @@ -853,6 +859,8 @@ static int __init af_rxrpc_init(void) proto_unregister(&rxrpc_proto); error_proto: destroy_workqueue(rxrpc_workqueue); +error_security: + rxrpc_exit_security(); error_work_queue: kmem_cache_destroy(rxrpc_call_jar); error_call_jar: @@ -883,6 +891,7 @@ static void __exit af_rxrpc_exit(void) remove_proc_entry("rxrpc_conns", init_net.proc_net); remove_proc_entry("rxrpc_calls", init_net.proc_net); destroy_workqueue(rxrpc_workqueue); + rxrpc_exit_security(); kmem_cache_destroy(rxrpc_call_jar); _leave(""); } diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index d38071b09f72..72fd675a891e 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -124,11 +124,15 @@ enum rxrpc_command { * RxRPC security module interface */ struct rxrpc_security { - struct module *owner; /* providing module */ - struct list_head link; /* link in master list */ const char *name; /* name of this service */ u8 security_index; /* security type provided */ + /* Initialise a security service */ + int (*init)(void); + + /* Clean up a security service */ + void (*exit)(void); + /* initialise a connection's security */ int (*init_connection_security)(struct rxrpc_connection *); @@ -268,7 +272,7 @@ struct rxrpc_connection { struct rb_root calls; /* calls on this connection */ struct sk_buff_head rx_queue; /* received conn-level packets */ struct rxrpc_call *channels[RXRPC_MAXCALLS]; /* channels (active calls) */ - struct rxrpc_security *security; /* applied security module */ + const struct rxrpc_security *security; /* applied security module */ struct key *key; /* security for this connection (client) */ struct key *server_key; /* security for this service */ struct crypto_skcipher *cipher; /* encryption handle */ @@ -604,8 +608,8 @@ int rxrpc_recvmsg(struct socket *, struct msghdr *, size_t, int); /* * ar-security.c */ -int rxrpc_register_security(struct rxrpc_security *); -void rxrpc_unregister_security(struct rxrpc_security *); +int __init rxrpc_init_security(void); +void rxrpc_exit_security(void); int rxrpc_init_client_conn_security(struct rxrpc_connection *); int rxrpc_init_server_conn_security(struct rxrpc_connection *); int rxrpc_secure_packet(const struct rxrpc_call *, struct sk_buff *, size_t, @@ -645,6 +649,13 @@ extern const s8 rxrpc_ack_priority[]; extern const char *rxrpc_acks(u8 reason); +/* + * rxkad.c + */ +#ifdef CONFIG_RXKAD +extern const struct rxrpc_security rxkad; +#endif + /* * sysctl.c */ diff --git a/net/rxrpc/ar-security.c b/net/rxrpc/ar-security.c index ceff6394a65f..6946aec7ab1f 100644 --- a/net/rxrpc/ar-security.c +++ b/net/rxrpc/ar-security.c @@ -22,109 +22,59 @@ static LIST_HEAD(rxrpc_security_methods); static DECLARE_RWSEM(rxrpc_security_sem); -/* - * get an RxRPC security module - */ -static struct rxrpc_security *rxrpc_security_get(struct rxrpc_security *sec) -{ - return try_module_get(sec->owner) ? sec : NULL; -} +static const struct rxrpc_security *rxrpc_security_types[] = { +#ifdef CONFIG_RXKAD + [RXRPC_SECURITY_RXKAD] = &rxkad, +#endif +}; -/* - * release an RxRPC security module - */ -static void rxrpc_security_put(struct rxrpc_security *sec) +int __init rxrpc_init_security(void) { - module_put(sec->owner); -} + int i, ret; -/* - * look up an rxrpc security module - */ -static struct rxrpc_security *rxrpc_security_lookup(u8 security_index) -{ - struct rxrpc_security *sec = NULL; - - _enter(""); - - down_read(&rxrpc_security_sem); - - list_for_each_entry(sec, &rxrpc_security_methods, link) { - if (sec->security_index == security_index) { - if (unlikely(!rxrpc_security_get(sec))) - break; - goto out; + for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) { + if (rxrpc_security_types[i]) { + ret = rxrpc_security_types[i]->init(); + if (ret < 0) + goto failed; } } - sec = NULL; -out: - up_read(&rxrpc_security_sem); - _leave(" = %p [%s]", sec, sec ? sec->name : ""); - return sec; + return 0; + +failed: + for (i--; i >= 0; i--) + if (rxrpc_security_types[i]) + rxrpc_security_types[i]->exit(); + return ret; } -/** - * rxrpc_register_security - register an RxRPC security handler - * @sec: security module - * - * register an RxRPC security handler for use by RxRPC - */ -int rxrpc_register_security(struct rxrpc_security *sec) +void rxrpc_exit_security(void) { - struct rxrpc_security *psec; - int ret; - - _enter(""); - down_write(&rxrpc_security_sem); - - ret = -EEXIST; - list_for_each_entry(psec, &rxrpc_security_methods, link) { - if (psec->security_index == sec->security_index) - goto out; - } - - list_add(&sec->link, &rxrpc_security_methods); - - printk(KERN_NOTICE "RxRPC: Registered security type %d '%s'\n", - sec->security_index, sec->name); - ret = 0; + int i; -out: - up_write(&rxrpc_security_sem); - _leave(" = %d", ret); - return ret; + for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) + if (rxrpc_security_types[i]) + rxrpc_security_types[i]->exit(); } -EXPORT_SYMBOL_GPL(rxrpc_register_security); - -/** - * rxrpc_unregister_security - unregister an RxRPC security handler - * @sec: security module - * - * unregister an RxRPC security handler +/* + * look up an rxrpc security module */ -void rxrpc_unregister_security(struct rxrpc_security *sec) +static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index) { - - _enter(""); - down_write(&rxrpc_security_sem); - list_del_init(&sec->link); - up_write(&rxrpc_security_sem); - - printk(KERN_NOTICE "RxRPC: Unregistered security type %d '%s'\n", - sec->security_index, sec->name); + if (security_index >= ARRAY_SIZE(rxrpc_security_types)) + return NULL; + return rxrpc_security_types[security_index]; } -EXPORT_SYMBOL_GPL(rxrpc_unregister_security); - /* * initialise the security on a client connection */ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) { + const struct rxrpc_security *sec; struct rxrpc_key_token *token; - struct rxrpc_security *sec; struct key *key = conn->key; int ret; @@ -148,7 +98,6 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) ret = conn->security->init_connection_security(conn); if (ret < 0) { - rxrpc_security_put(conn->security); conn->security = NULL; return ret; } @@ -162,7 +111,7 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) */ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) { - struct rxrpc_security *sec; + const struct rxrpc_security *sec; struct rxrpc_local *local = conn->trans->local; struct rxrpc_sock *rx; struct key *key; @@ -188,14 +137,12 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) /* the service appears to have died */ read_unlock_bh(&local->services_lock); - rxrpc_security_put(sec); _leave(" = -ENOENT"); return -ENOENT; found_service: if (!rx->securities) { read_unlock_bh(&local->services_lock); - rxrpc_security_put(sec); _leave(" = -ENOKEY"); return -ENOKEY; } @@ -205,7 +152,6 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) &key_type_rxrpc_s, kdesc); if (IS_ERR(kref)) { read_unlock_bh(&local->services_lock); - rxrpc_security_put(sec); _leave(" = %ld [search]", PTR_ERR(kref)); return PTR_ERR(kref); } @@ -253,11 +199,8 @@ void rxrpc_clear_conn_security(struct rxrpc_connection *conn) { _enter("{%d}", conn->debug_id); - if (conn->security) { + if (conn->security) conn->security->clear(conn); - rxrpc_security_put(conn->security); - conn->security = NULL; - } key_put(conn->key); key_put(conn->server_key); diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index f0aeb8163688..6b726a046a7d 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -20,7 +20,6 @@ #include #include #include -#define rxrpc_debug rxkad_debug #include "ar-internal.h" #define RXKAD_VERSION 2 @@ -31,10 +30,6 @@ #define REALM_SZ 40 /* size of principal's auth domain */ #define SNAME_SZ 40 /* size of service name */ -unsigned int rxrpc_debug; -module_param_named(debug, rxrpc_debug, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(debug, "rxkad debugging mask"); - struct rxkad_level1_hdr { __be32 data_size; /* true data size (excluding padding) */ }; @@ -44,10 +39,6 @@ struct rxkad_level2_hdr { __be32 checksum; /* decrypted data checksum */ }; -MODULE_DESCRIPTION("RxRPC network protocol type-2 security (Kerberos 4)"); -MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); - /* * this holds a pinned cipher so that keventd doesn't get called by the cipher * alloc routine, but since we have it to hand, we use it to decrypt RESPONSE @@ -1163,13 +1154,36 @@ static void rxkad_clear(struct rxrpc_connection *conn) crypto_free_skcipher(conn->cipher); } +/* + * Initialise the rxkad security service. + */ +static int rxkad_init(void) +{ + /* pin the cipher we need so that the crypto layer doesn't invoke + * keventd to go get it */ + rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(rxkad_ci)) + return PTR_ERR(rxkad_ci); + return 0; +} + +/* + * Clean up the rxkad security service. + */ +static void rxkad_exit(void) +{ + if (rxkad_ci) + crypto_free_skcipher(rxkad_ci); +} + /* * RxRPC Kerberos-based security */ -static struct rxrpc_security rxkad = { - .owner = THIS_MODULE, +const struct rxrpc_security rxkad = { .name = "rxkad", .security_index = RXRPC_SECURITY_RXKAD, + .init = rxkad_init, + .exit = rxkad_exit, .init_connection_security = rxkad_init_connection_security, .prime_packet_security = rxkad_prime_packet_security, .secure_packet = rxkad_secure_packet, @@ -1179,28 +1193,3 @@ static struct rxrpc_security rxkad = { .verify_response = rxkad_verify_response, .clear = rxkad_clear, }; - -static __init int rxkad_init(void) -{ - _enter(""); - - /* pin the cipher we need so that the crypto layer doesn't invoke - * keventd to go get it */ - rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(rxkad_ci)) - return PTR_ERR(rxkad_ci); - - return rxrpc_register_security(&rxkad); -} - -module_init(rxkad_init); - -static __exit void rxkad_exit(void) -{ - _enter(""); - - rxrpc_unregister_security(&rxkad); - crypto_free_skcipher(rxkad_ci); -} - -module_exit(rxkad_exit); -- GitLab From e0e4d82f3be60cfe8b10304c6daf3ca5973ae9e3 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 17:23:58 +0100 Subject: [PATCH 2041/9938] rxrpc: Create a null security type and get rid of conditional calls Create a null security type for security index 0 and get rid of all conditional calls to the security operations. We expect normally to be using security, so this should be of little negative impact. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/Makefile | 1 + net/rxrpc/ar-ack.c | 3 +- net/rxrpc/ar-connection.c | 9 +++-- net/rxrpc/ar-connevent.c | 11 +----- net/rxrpc/ar-input.c | 2 +- net/rxrpc/ar-internal.h | 10 +++-- net/rxrpc/ar-output.c | 4 +- net/rxrpc/ar-security.c | 43 +------------------- net/rxrpc/insecure.c | 83 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 105 insertions(+), 61 deletions(-) create mode 100644 net/rxrpc/insecure.c diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index fa09cb55bfce..e05a06ef2254 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile @@ -19,6 +19,7 @@ af-rxrpc-y := \ ar-security.o \ ar-skbuff.o \ ar-transport.o \ + insecure.o \ misc.o af-rxrpc-$(CONFIG_PROC_FS) += ar-proc.o diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index 3cd9264806a4..374478e006e7 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -588,7 +588,8 @@ static int rxrpc_process_rx_queue(struct rxrpc_call *call, _proto("OOSQ DATA %%%u { #%u }", sp->hdr.serial, sp->hdr.seq); /* secured packets must be verified and possibly decrypted */ - if (rxrpc_verify_packet(call, skb, _abort_code) < 0) + if (call->conn->security->verify_packet(call, skb, + _abort_code) < 0) goto protocol_error; rxrpc_insert_oos_packet(call, skb); diff --git a/net/rxrpc/ar-connection.c b/net/rxrpc/ar-connection.c index 9b6966777633..97f4fae74bca 100644 --- a/net/rxrpc/ar-connection.c +++ b/net/rxrpc/ar-connection.c @@ -207,6 +207,7 @@ static struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp) INIT_LIST_HEAD(&conn->bundle_link); conn->calls = RB_ROOT; skb_queue_head_init(&conn->rx_queue); + conn->security = &rxrpc_no_security; rwlock_init(&conn->lock); spin_lock_init(&conn->state_lock); atomic_set(&conn->usage, 1); @@ -564,8 +565,7 @@ int rxrpc_connect_call(struct rxrpc_sock *rx, candidate->debug_id, candidate->trans->debug_id); rxrpc_assign_connection_id(candidate); - if (candidate->security) - candidate->security->prime_packet_security(candidate); + candidate->security->prime_packet_security(candidate); /* leave the candidate lurking in zombie mode attached to the * bundle until we're ready for it */ @@ -830,7 +830,10 @@ static void rxrpc_destroy_connection(struct rxrpc_connection *conn) ASSERT(RB_EMPTY_ROOT(&conn->calls)); rxrpc_purge_queue(&conn->rx_queue); - rxrpc_clear_conn_security(conn); + conn->security->clear(conn); + key_put(conn->key); + key_put(conn->server_key); + rxrpc_put_transport(conn->trans); kfree(conn); _leave(""); diff --git a/net/rxrpc/ar-connevent.c b/net/rxrpc/ar-connevent.c index 291522392ac7..5f9563968a5b 100644 --- a/net/rxrpc/ar-connevent.c +++ b/net/rxrpc/ar-connevent.c @@ -174,15 +174,10 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, return -ECONNABORTED; case RXRPC_PACKET_TYPE_CHALLENGE: - if (conn->security) - return conn->security->respond_to_challenge( - conn, skb, _abort_code); - return -EPROTO; + return conn->security->respond_to_challenge(conn, skb, + _abort_code); case RXRPC_PACKET_TYPE_RESPONSE: - if (!conn->security) - return -EPROTO; - ret = conn->security->verify_response(conn, skb, _abort_code); if (ret < 0) return ret; @@ -238,8 +233,6 @@ static void rxrpc_secure_connection(struct rxrpc_connection *conn) } } - ASSERT(conn->security != NULL); - if (conn->security->issue_challenge(conn) < 0) { abort_code = RX_CALL_DEAD; ret = -ENOMEM; diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index c6c784d3a3e8..01e038146b7c 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c @@ -193,7 +193,7 @@ static int rxrpc_fast_process_data(struct rxrpc_call *call, /* if the packet need security things doing to it, then it goes down * the slow path */ - if (call->conn->security) + if (call->conn->security_ix) goto enqueue_packet; sp->call = call; diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 72fd675a891e..f0b807a163fa 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #if 0 @@ -612,10 +613,6 @@ int __init rxrpc_init_security(void); void rxrpc_exit_security(void); int rxrpc_init_client_conn_security(struct rxrpc_connection *); int rxrpc_init_server_conn_security(struct rxrpc_connection *); -int rxrpc_secure_packet(const struct rxrpc_call *, struct sk_buff *, size_t, - void *); -int rxrpc_verify_packet(const struct rxrpc_call *, struct sk_buff *, u32 *); -void rxrpc_clear_conn_security(struct rxrpc_connection *); /* * ar-skbuff.c @@ -634,6 +631,11 @@ void __exit rxrpc_destroy_all_transports(void); struct rxrpc_transport *rxrpc_find_transport(struct rxrpc_local *, struct rxrpc_peer *); +/* + * insecure.c + */ +extern const struct rxrpc_security rxrpc_no_security; + /* * misc.c */ diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index 94e7d9537437..51cb10062a8d 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c @@ -663,7 +663,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, size_t pad; /* pad out if we're using security */ - if (conn->security) { + if (conn->security_ix) { pad = conn->security_size + skb->mark; pad = conn->size_align - pad; pad &= conn->size_align - 1; @@ -695,7 +695,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, if (more && seq & 1) sp->hdr.flags |= RXRPC_REQUEST_ACK; - ret = rxrpc_secure_packet( + ret = conn->security->secure_packet( call, skb, skb->mark, skb->head + sizeof(struct rxrpc_wire_header)); if (ret < 0) diff --git a/net/rxrpc/ar-security.c b/net/rxrpc/ar-security.c index 6946aec7ab1f..d223253b22fa 100644 --- a/net/rxrpc/ar-security.c +++ b/net/rxrpc/ar-security.c @@ -23,6 +23,7 @@ static LIST_HEAD(rxrpc_security_methods); static DECLARE_RWSEM(rxrpc_security_sem); static const struct rxrpc_security *rxrpc_security_types[] = { + [RXRPC_SECURITY_NONE] = &rxrpc_no_security, #ifdef CONFIG_RXKAD [RXRPC_SECURITY_RXKAD] = &rxkad, #endif @@ -98,7 +99,7 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) ret = conn->security->init_connection_security(conn); if (ret < 0) { - conn->security = NULL; + conn->security = &rxrpc_no_security; return ret; } @@ -165,43 +166,3 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) _leave(" = 0"); return 0; } - -/* - * secure a packet prior to transmission - */ -int rxrpc_secure_packet(const struct rxrpc_call *call, - struct sk_buff *skb, - size_t data_size, - void *sechdr) -{ - if (call->conn->security) - return call->conn->security->secure_packet( - call, skb, data_size, sechdr); - return 0; -} - -/* - * secure a packet prior to transmission - */ -int rxrpc_verify_packet(const struct rxrpc_call *call, struct sk_buff *skb, - u32 *_abort_code) -{ - if (call->conn->security) - return call->conn->security->verify_packet( - call, skb, _abort_code); - return 0; -} - -/* - * clear connection security - */ -void rxrpc_clear_conn_security(struct rxrpc_connection *conn) -{ - _enter("{%d}", conn->debug_id); - - if (conn->security) - conn->security->clear(conn); - - key_put(conn->key); - key_put(conn->server_key); -} diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c new file mode 100644 index 000000000000..e571403613c1 --- /dev/null +++ b/net/rxrpc/insecure.c @@ -0,0 +1,83 @@ +/* Null security operations. + * + * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include "ar-internal.h" + +static int none_init_connection_security(struct rxrpc_connection *conn) +{ + return 0; +} + +static void none_prime_packet_security(struct rxrpc_connection *conn) +{ +} + +static int none_secure_packet(const struct rxrpc_call *call, + struct sk_buff *skb, + size_t data_size, + void *sechdr) +{ + return 0; +} + +static int none_verify_packet(const struct rxrpc_call *call, + struct sk_buff *skb, + u32 *_abort_code) +{ + return 0; +} + +static int none_respond_to_challenge(struct rxrpc_connection *conn, + struct sk_buff *skb, + u32 *_abort_code) +{ + *_abort_code = RX_PROTOCOL_ERROR; + return -EPROTO; +} + +static int none_verify_response(struct rxrpc_connection *conn, + struct sk_buff *skb, + u32 *_abort_code) +{ + *_abort_code = RX_PROTOCOL_ERROR; + return -EPROTO; +} + +static void none_clear(struct rxrpc_connection *conn) +{ +} + +static int none_init(void) +{ + return 0; +} + +static void none_exit(void) +{ +} + +/* + * RxRPC Kerberos-based security + */ +const struct rxrpc_security rxrpc_no_security = { + .name = "none", + .security_index = RXRPC_SECURITY_NONE, + .init = none_init, + .exit = none_exit, + .init_connection_security = none_init_connection_security, + .prime_packet_security = none_prime_packet_security, + .secure_packet = none_secure_packet, + .verify_packet = none_verify_packet, + .respond_to_challenge = none_respond_to_challenge, + .verify_response = none_verify_response, + .clear = none_clear, +}; -- GitLab From 3d2a58bc574cbd349edded07a5f8e9fe0619efb3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:28 +0200 Subject: [PATCH 2042/9938] ARM: dts: dra7: Move the sDMA crossbar node under l4_cfg/scm Move the sDMA xbar nodes under the L4 interconnect node. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index ed740d02ec17..035f9be26337 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -161,6 +161,15 @@ compatible = "syscon"; reg = <0x1c24 0x0024>; }; + + sdma_xbar: dma-router@b78 { + compatible = "ti,dra7-dma-crossbar"; + reg = <0xb78 0xfc>; + #dma-cells = <1>; + dma-requests = <205>; + ti,dma-safe-map = <0>; + dma-masters = <&sdma>; + }; }; cm_core_aon: cm_core_aon@5000 { @@ -315,15 +324,6 @@ dma-requests = <127>; }; - sdma_xbar: dma-router@4a002b78 { - compatible = "ti,dra7-dma-crossbar"; - reg = <0x4a002b78 0xfc>; - #dma-cells = <1>; - dma-requests = <205>; - ti,dma-safe-map = <0>; - dma-masters = <&sdma>; - }; - gpio1: gpio@4ae10000 { compatible = "ti,omap4-gpio"; reg = <0x4ae10000 0x200>; -- GitLab From 248948fbbd048d1ea75f9bb18979a6f33c4dcd5b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:29 +0200 Subject: [PATCH 2043/9938] ARM: dts: dra7: Enable eDMA DRA7 family has eDMA available along with the sDMA and in some cases it is better suited for servicing peripherals. Add the needed nodes for eDMA to be usable: edma-tpcc, edma-tptc0/1 and the edma-xbar. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 035f9be26337..1d54d311c46a 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -170,6 +170,15 @@ ti,dma-safe-map = <0>; dma-masters = <&sdma>; }; + + edma_xbar: dma-router@c78 { + compatible = "ti,dra7-dma-crossbar"; + reg = <0xc78 0x7c>; + #dma-cells = <2>; + dma-requests = <204>; + ti,dma-safe-map = <0>; + dma-masters = <&edma>; + }; }; cm_core_aon: cm_core_aon@5000 { @@ -324,6 +333,45 @@ dma-requests = <127>; }; + edma: edma@43300000 { + compatible = "ti,edma3-tpcc"; + ti,hwmods = "tpcc"; + reg = <0x43300000 0x100000>; + reg-names = "edma3_cc"; + interrupts = , + , + ; + interrupt-names = "edma3_ccint", "emda3_mperr", + "edma3_ccerrint"; + dma-requests = <64>; + #dma-cells = <2>; + + ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 0>; + + /* + * memcpy is disabled, can be enabled with: + * ti,edma-memcpy-channels = <20 21>; + * for example. Note that these channels need to be + * masked in the xbar as well. + */ + }; + + edma_tptc0: tptc@43400000 { + compatible = "ti,edma3-tptc"; + ti,hwmods = "tptc0"; + reg = <0x43400000 0x100000>; + interrupts = ; + interrupt-names = "edma3_tcerrint"; + }; + + edma_tptc1: tptc@43500000 { + compatible = "ti,edma3-tptc"; + ti,hwmods = "tptc1"; + reg = <0x43500000 0x100000>; + interrupts = ; + interrupt-names = "edma3_tcerrint"; + }; + gpio1: gpio@4ae10000 { compatible = "ti,omap4-gpio"; reg = <0x4ae10000 0x200>; -- GitLab From 0c92de2cd56d856af7ab3c82c8f46bb854b81c13 Mon Sep 17 00:00:00 2001 From: Misael Lopez Cruz Date: Mon, 7 Mar 2016 17:17:30 +0200 Subject: [PATCH 2044/9938] ARM: dts: dra7: Use eDMA and add DAT port address for McASP3 McASP3 does not support constant addressing mode on the DAT port, so increment transfers must be used instead. This restriction is also applicable for McASP1 and McASP2. This DMA addressing constraint poses a major problem for sDMA where constant addressing mode is used on the peripheral side. Unfortunately, using increment transfers in sDMA comes with important side effects. The addressing mode used in eDMA is INC, so the silicon limitation described above has no impact and the McASP3 DAT port can be safely added by switching to eDMA instead of sDMA. Signed-off-by: Misael Lopez Cruz Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 1d54d311c46a..19c96f7a72da 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -1469,12 +1469,13 @@ mcasp3: mcasp@48468000 { compatible = "ti,dra7-mcasp-audio"; ti,hwmods = "mcasp3"; - reg = <0x48468000 0x2000>; - reg-names = "mpu"; + reg = <0x48468000 0x2000>, + <0x46000000 0x1000>; + reg-names = "mpu","dat"; interrupts = , ; interrupt-names = "tx", "rx"; - dmas = <&sdma_xbar 133>, <&sdma_xbar 132>; + dmas = <&edma_xbar 133 1>, <&edma_xbar 132 1>; dma-names = "tx", "rx"; clocks = <&mcasp3_aux_gfclk_mux>, <&mcasp3_ahclkx_mux>; clock-names = "fck", "ahclkx"; -- GitLab From 27701fc2517e7653b756d524ec7428e88df0efa3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:31 +0200 Subject: [PATCH 2045/9938] ARM: dts: dra7-evm: Enable AFIFO use for McASP3 Since we switched to use eDMA we can now safely enable the FIFO in McASP. This will reduce the chance of McASP level under/overflow. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7-evm.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 074d70b191e2..a7b4707a0d05 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -904,6 +904,8 @@ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ 1 2 0 0 >; + tx-num-evt = <32>; + rx-num-evt = <32>; }; &mailbox5 { -- GitLab From 6cfec12f25453ad498a7892764a4fe4fc9d3906e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:32 +0200 Subject: [PATCH 2046/9938] ARM: dts: dra72-evm: Enable AFIFO use for McASP3 Since we switched to use eDMA we can now safely enable the FIFO in McASP. This will reduce the chance of McASP level under/overflow. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra72-evm.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index 6006ced8f6b3..21c5cd13b807 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts @@ -834,6 +834,8 @@ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ 1 2 0 0 >; + tx-num-evt = <32>; + rx-num-evt = <32>; }; &mailbox5 { -- GitLab From e80ab5c972797d494d5305e48da6d122a74f747d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:33 +0200 Subject: [PATCH 2047/9938] ARM: dts: am57xx-beagle-x15: Move clkout2 source selection to codec node The assigned-clock* needs to be in the root of the device's node. If it is in the sub-node the CCF will ignore it. Since the clkout2 is used by the codec as MCLK, move the clock parent selection to that node. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 75bd09b175cd..b9c367bb614e 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -173,8 +173,6 @@ sound0_master: simple-audio-card,codec { sound-dai = <&tlv320aic3104>; - assigned-clocks = <&clkoutmux2_clk_mux>; - assigned-clock-parents = <&sys_clk2_dclk_div>; clocks = <&clkout2_clk>; }; }; @@ -584,6 +582,9 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&clkout2_pins_default>; pinctrl-1 = <&clkout2_pins_sleep>; + assigned-clocks = <&clkoutmux2_clk_mux>; + assigned-clock-parents = <&sys_clk2_dclk_div>; + status = "okay"; adc-settle-ms = <40>; -- GitLab From 42b2274da00d924e04e39f1d5c259f0f4b113de9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:34 +0200 Subject: [PATCH 2048/9938] ARM: dts: am57xx-beagle-x15: Enable AFIFO use for McASP3 Since we switched to use eDMA we can now safely enable the FIFO in McASP. This will reduce the chance of McASP level under/overflow. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index b9c367bb614e..75d04b1bbd1b 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -813,6 +813,8 @@ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ 1 2 0 0 >; + tx-num-evt = <32>; + rx-num-evt = <32>; }; &mailbox5 { -- GitLab From e56700b87cb9fe480a4b20b16cf5eb63b49de1e8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:35 +0200 Subject: [PATCH 2049/9938] ARM: dts: dra7xx: Correct mcasp8_ahclkx_mux name rename the mcasp8_ahclk_mux to mcasp8_ahclkx_mux. Signed-off-by: Peter Ujfalusi [tony@atomide.com: updated for the unit offsets] Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7xx-clocks.dtsi | 2 +- drivers/clk/ti/clk-7xx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi index c437c5cb3af4..c01362b4fc34 100644 --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi @@ -1856,7 +1856,7 @@ reg = <0x1908>; }; - mcasp8_ahclk_mux: mcasp8_ahclk_mux@1890 { + mcasp8_ahclkx_mux: mcasp8_ahclkx_mux@1890 { #clock-cells = <0>; compatible = "ti,mux-clock"; clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index a911d7de3377..6b5a309d9939 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -223,7 +223,7 @@ static struct ti_dt_clk dra7xx_clks[] = { DT_CLK(NULL, "mcasp6_aux_gfclk_mux", "mcasp6_aux_gfclk_mux"), DT_CLK(NULL, "mcasp7_ahclkx_mux", "mcasp7_ahclkx_mux"), DT_CLK(NULL, "mcasp7_aux_gfclk_mux", "mcasp7_aux_gfclk_mux"), - DT_CLK(NULL, "mcasp8_ahclk_mux", "mcasp8_ahclk_mux"), + DT_CLK(NULL, "mcasp8_ahclkx_mux", "mcasp8_ahclkx_mux"), DT_CLK(NULL, "mcasp8_aux_gfclk_mux", "mcasp8_aux_gfclk_mux"), DT_CLK(NULL, "mmc1_fclk_mux", "mmc1_fclk_mux"), DT_CLK(NULL, "mmc1_fclk_div", "mmc1_fclk_div"), -- GitLab From 296ea972dc96a78cc26027e879db91273c91f3c4 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 7 Mar 2016 17:17:37 +0200 Subject: [PATCH 2050/9938] ARM: dts: dra7: Add nodes for McASP1/2/4/5/6/7/8 Add nodes to represent all McASP ports in the dra7 family. For system consistency use the eDMA for audio operations. sDMA would be fine for 4/5/6/7/8 since their DAT port is not through L3 interconnect. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 114 ++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 19c96f7a72da..400565978af2 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -1466,6 +1466,40 @@ status = "disabled"; }; + mcasp1: mcasp@48460000 { + compatible = "ti,dra7-mcasp-audio"; + ti,hwmods = "mcasp1"; + reg = <0x48460000 0x2000>, + <0x45800000 0x1000>; + reg-names = "mpu","dat"; + interrupts = , + ; + interrupt-names = "tx", "rx"; + dmas = <&edma_xbar 129 1>, <&edma_xbar 128 1>; + dma-names = "tx", "rx"; + clocks = <&mcasp1_aux_gfclk_mux>, <&mcasp1_ahclkx_mux>, + <&mcasp1_ahclkr_mux>; + clock-names = "fck", "ahclkx", "ahclkr"; + status = "disabled"; + }; + + mcasp2: mcasp@48464000 { + compatible = "ti,dra7-mcasp-audio"; + ti,hwmods = "mcasp2"; + reg = <0x48464000 0x2000>, + <0x45c00000 0x1000>; + reg-names = "mpu","dat"; + interrupts = , + ; + interrupt-names = "tx", "rx"; + dmas = <&edma_xbar 131 1>, <&edma_xbar 130 1>; + dma-names = "tx", "rx"; + clocks = <&mcasp2_aux_gfclk_mux>, <&mcasp2_ahclkx_mux>, + <&mcasp2_ahclkr_mux>; + clock-names = "fck", "ahclkx", "ahclkr"; + status = "disabled"; + }; + mcasp3: mcasp@48468000 { compatible = "ti,dra7-mcasp-audio"; ti,hwmods = "mcasp3"; @@ -1482,6 +1516,86 @@ status = "disabled"; }; + mcasp4: mcasp@4846c000 { + compatible = "ti,dra7-mcasp-audio"; + ti,hwmods = "mcasp4"; + reg = <0x4846c000 0x2000>, + <0x48436000 0x1000>; + reg-names = "mpu","dat"; + interrupts = , + ; + interrupt-names = "tx", "rx"; + dmas = <&edma_xbar 135 1>, <&edma_xbar 134 1>; + dma-names = "tx", "rx"; + clocks = <&mcasp4_aux_gfclk_mux>, <&mcasp4_ahclkx_mux>; + clock-names = "fck", "ahclkx"; + status = "disabled"; + }; + + mcasp5: mcasp@48470000 { + compatible = "ti,dra7-mcasp-audio"; + ti,hwmods = "mcasp5"; + reg = <0x48470000 0x2000>, + <0x4843a000 0x1000>; + reg-names = "mpu","dat"; + interrupts = , + ; + interrupt-names = "tx", "rx"; + dmas = <&edma_xbar 137 1>, <&edma_xbar 136 1>; + dma-names = "tx", "rx"; + clocks = <&mcasp5_aux_gfclk_mux>, <&mcasp5_ahclkx_mux>; + clock-names = "fck", "ahclkx"; + status = "disabled"; + }; + + mcasp6: mcasp@48474000 { + compatible = "ti,dra7-mcasp-audio"; + ti,hwmods = "mcasp6"; + reg = <0x48474000 0x2000>, + <0x4844c000 0x1000>; + reg-names = "mpu","dat"; + interrupts = , + ; + interrupt-names = "tx", "rx"; + dmas = <&edma_xbar 139 1>, <&edma_xbar 138 1>; + dma-names = "tx", "rx"; + clocks = <&mcasp6_aux_gfclk_mux>, <&mcasp6_ahclkx_mux>; + clock-names = "fck", "ahclkx"; + status = "disabled"; + }; + + mcasp7: mcasp@48478000 { + compatible = "ti,dra7-mcasp-audio"; + ti,hwmods = "mcasp7"; + reg = <0x48478000 0x2000>, + <0x48450000 0x1000>; + reg-names = "mpu","dat"; + interrupts = , + ; + interrupt-names = "tx", "rx"; + dmas = <&edma_xbar 141 1>, <&edma_xbar 140 1>; + dma-names = "tx", "rx"; + clocks = <&mcasp7_aux_gfclk_mux>, <&mcasp7_ahclkx_mux>; + clock-names = "fck", "ahclkx"; + status = "disabled"; + }; + + mcasp8: mcasp@4847c000 { + compatible = "ti,dra7-mcasp-audio"; + ti,hwmods = "mcasp8"; + reg = <0x4847c000 0x2000>, + <0x48454000 0x1000>; + reg-names = "mpu","dat"; + interrupts = , + ; + interrupt-names = "tx", "rx"; + dmas = <&edma_xbar 143 1>, <&edma_xbar 142 1>; + dma-names = "tx", "rx"; + clocks = <&mcasp8_aux_gfclk_mux>, <&mcasp8_ahclkx_mux>; + clock-names = "fck", "ahclkx"; + status = "disabled"; + }; + crossbar_mpu: crossbar@4a002a48 { compatible = "ti,irq-crossbar"; reg = <0x4a002a48 0x130>; -- GitLab From 722326c49e0dc2f5c0d4ccd7b69174a63a903e7c Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Tue, 5 Apr 2016 16:44:09 -0500 Subject: [PATCH 2051/9938] ARM: dts: DRA7: Enable Timers 13 through 16 The Timers 13 through 16 have been added previously in disabled state. These timers are common timers that are present on all DRA7 family of SoCs, so enable these devices by default like the rest of the DMTimers. Signed-off-by: Suman Anna Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 400565978af2..95d0adfd959b 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -826,7 +826,6 @@ reg = <0x48828000 0x80>; interrupts = ; ti,hwmods = "timer13"; - status = "disabled"; }; timer14: timer@4882a000 { @@ -834,7 +833,6 @@ reg = <0x4882a000 0x80>; interrupts = ; ti,hwmods = "timer14"; - status = "disabled"; }; timer15: timer@4882c000 { @@ -842,7 +840,6 @@ reg = <0x4882c000 0x80>; interrupts = ; ti,hwmods = "timer15"; - status = "disabled"; }; timer16: timer@4882e000 { @@ -850,7 +847,6 @@ reg = <0x4882e000 0x80>; interrupts = ; ti,hwmods = "timer16"; - status = "disabled"; }; wdt2: wdt@4ae14000 { -- GitLab From d79852a792c971765dd7dfef9a8df883c63937f3 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Tue, 5 Apr 2016 16:44:10 -0500 Subject: [PATCH 2052/9938] ARM: dts: DRA7: Add timer12 node Add the DT node for Timer12 present on DRA7 family of SoCs. Timer12 is present in PD_WKUPAON power domain, and has the same capabilities as the other timers, except for the fact that it serves as a secure timer on HS devices and is clocked only from the secure 32K clock. Signed-off-by: Suman Anna Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 95d0adfd959b..ee92eed58b58 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -821,6 +821,15 @@ ti,hwmods = "timer11"; }; + timer12: timer@4ae20000 { + compatible = "ti,omap5430-timer"; + reg = <0x4ae20000 0x80>; + interrupts = ; + ti,hwmods = "timer12"; + ti,timer-alwon; + ti,timer-secure; + }; + timer13: timer@48828000 { compatible = "ti,omap5430-timer"; reg = <0x48828000 0x80>; -- GitLab From 35a6ae07c663499875309f18730f3440bb59f6fe Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 23 Mar 2016 11:34:29 +0100 Subject: [PATCH 2053/9938] x86/PCI: Refine PCI support check in pcibios_init() Also consider raw_pci_ext_ops when validating if a system has PCI support. This leads to proper resource allocation via pcibios_resource_survey() in the case where PCI config space is exclusively accessed through MMCONFIG. Signed-off-by: Adrian-Ken Rueegsegger Signed-off-by: Bjorn Helgaas --- arch/x86/pci/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 381a43c40bf7..8196054fedb0 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -516,7 +516,7 @@ void __init pcibios_set_cache_line_size(void) int __init pcibios_init(void) { - if (!raw_pci_ops) { + if (!raw_pci_ops && !raw_pci_ext_ops) { printk(KERN_WARNING "PCI: System does not support PCI\n"); return 0; } -- GitLab From 501280f5a043ec73979b94d4c23e7aae1727f32e Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 22 Mar 2016 20:32:03 +0100 Subject: [PATCH 2054/9938] scsi: make some Additional Sense strings more grep'able There's little point in breaking these strings over multiple lines. Signed-off-by: Rasmus Villemoes Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/constants.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index fa09d4be2b53..58d94e3c3713 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -346,11 +346,9 @@ static const struct error_info additional[] = {0x0407, "Logical unit not ready, operation in progress"}, {0x0408, "Logical unit not ready, long write in progress"}, {0x0409, "Logical unit not ready, self-test in progress"}, - {0x040A, "Logical unit not accessible, asymmetric access state " - "transition"}, + {0x040A, "Logical unit not accessible, asymmetric access state transition"}, {0x040B, "Logical unit not accessible, target port in standby state"}, - {0x040C, "Logical unit not accessible, target port in unavailable " - "state"}, + {0x040C, "Logical unit not accessible, target port in unavailable state"}, {0x040D, "Logical unit not ready, structure check required"}, {0x040E, "Logical unit not ready, security session in progress"}, {0x0410, "Logical unit not ready, auxiliary memory not accessible"}, @@ -363,11 +361,9 @@ static const struct error_info additional[] = {0x0417, "Logical unit not ready, calibration required"}, {0x0418, "Logical unit not ready, a door is open"}, {0x0419, "Logical unit not ready, operating in sequential mode"}, - {0x041A, "Logical unit not ready, start stop unit command in " - "progress"}, + {0x041A, "Logical unit not ready, start stop unit command in progress"}, {0x041B, "Logical unit not ready, sanitize in progress"}, - {0x041C, "Logical unit not ready, additional power use not yet " - "granted"}, + {0x041C, "Logical unit not ready, additional power use not yet granted"}, {0x041D, "Logical unit not ready, configuration in progress"}, {0x041E, "Logical unit not ready, microcode activation required"}, {0x041F, "Logical unit not ready, microcode download required"}, @@ -559,8 +555,7 @@ static const struct error_info additional[] = {0x2300, "Invalid token operation, cause not reportable"}, {0x2301, "Invalid token operation, unsupported token type"}, {0x2302, "Invalid token operation, remote token usage not supported"}, - {0x2303, "Invalid token operation, remote rod token creation not " - "supported"}, + {0x2303, "Invalid token operation, remote rod token creation not supported"}, {0x2304, "Invalid token operation, token unknown"}, {0x2305, "Invalid token operation, token corrupt"}, {0x2306, "Invalid token operation, token revoked"}, @@ -641,8 +636,7 @@ static const struct error_info additional[] = {0x2A0D, "Data encryption capabilities changed"}, {0x2A10, "Timestamp changed"}, {0x2A11, "Data encryption parameters changed by another i_t nexus"}, - {0x2A12, "Data encryption parameters changed by vendor specific " - "event"}, + {0x2A12, "Data encryption parameters changed by vendor specific event"}, {0x2A13, "Data encryption key instance counter has changed"}, {0x2A14, "SA creation capabilities data has changed"}, {0x2A15, "Medium removal prevention preempted"}, @@ -759,8 +753,7 @@ static const struct error_info additional[] = {0x3B19, "Element enabled"}, {0x3B1A, "Data transfer device removed"}, {0x3B1B, "Data transfer device inserted"}, - {0x3B1C, "Too many logical objects on partition to support " - "operation"}, + {0x3B1C, "Too many logical objects on partition to support operation"}, {0x3D00, "Invalid bits in identify message"}, @@ -957,8 +950,7 @@ static const struct error_info additional[] = {0x5D39, "Data channel impending failure throughput performance"}, {0x5D3A, "Data channel impending failure seek time performance"}, {0x5D3B, "Data channel impending failure spin-up retry count"}, - {0x5D3C, "Data channel impending failure drive calibration retry " - "count"}, + {0x5D3C, "Data channel impending failure drive calibration retry count"}, {0x5D40, "Servo impending failure general hard drive failure"}, {0x5D41, "Servo impending failure drive error rate too high"}, {0x5D42, "Servo impending failure data error rate too high"}, @@ -1070,8 +1062,7 @@ static const struct error_info additional[] = {0x6E00, "Command to logical unit failed"}, - {0x6F00, "Copy protection key exchange failure - authentication " - "failure"}, + {0x6F00, "Copy protection key exchange failure - authentication failure"}, {0x6F01, "Copy protection key exchange failure - key not present"}, {0x6F02, "Copy protection key exchange failure - key not established"}, {0x6F03, "Read of scrambled sector without authentication"}, -- GitLab From 9d99a2e33a02c3290cb53013150ee06a304588ae Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 22 Mar 2016 20:32:04 +0100 Subject: [PATCH 2055/9938] scsi: move Additional Sense Codes to separate file This is a purely mechanical move of the list of additional sense codes to a separate file, in preparation for reducing the impact of choosing CONFIG_SCSI_CONSTANTS=y by about 8k. Signed-off-by: Rasmus Villemoes Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/constants.c | 830 +------------------------------------ drivers/scsi/sense_codes.h | 826 ++++++++++++++++++++++++++++++++++++ 2 files changed, 829 insertions(+), 827 deletions(-) create mode 100644 drivers/scsi/sense_codes.h diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 58d94e3c3713..6e813eec4f8d 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -295,835 +295,11 @@ struct error_info { const char * text; }; -/* - * The canonical list of T10 Additional Sense Codes is available at: - * http://www.t10.org/lists/asc-num.txt [most recent: 20141221] - */ - static const struct error_info additional[] = { - {0x0000, "No additional sense information"}, - {0x0001, "Filemark detected"}, - {0x0002, "End-of-partition/medium detected"}, - {0x0003, "Setmark detected"}, - {0x0004, "Beginning-of-partition/medium detected"}, - {0x0005, "End-of-data detected"}, - {0x0006, "I/O process terminated"}, - {0x0007, "Programmable early warning detected"}, - {0x0011, "Audio play operation in progress"}, - {0x0012, "Audio play operation paused"}, - {0x0013, "Audio play operation successfully completed"}, - {0x0014, "Audio play operation stopped due to error"}, - {0x0015, "No current audio status to return"}, - {0x0016, "Operation in progress"}, - {0x0017, "Cleaning requested"}, - {0x0018, "Erase operation in progress"}, - {0x0019, "Locate operation in progress"}, - {0x001A, "Rewind operation in progress"}, - {0x001B, "Set capacity operation in progress"}, - {0x001C, "Verify operation in progress"}, - {0x001D, "ATA pass through information available"}, - {0x001E, "Conflicting SA creation request"}, - {0x001F, "Logical unit transitioning to another power condition"}, - {0x0020, "Extended copy information available"}, - {0x0021, "Atomic command aborted due to ACA"}, - - {0x0100, "No index/sector signal"}, - - {0x0200, "No seek complete"}, - - {0x0300, "Peripheral device write fault"}, - {0x0301, "No write current"}, - {0x0302, "Excessive write errors"}, - - {0x0400, "Logical unit not ready, cause not reportable"}, - {0x0401, "Logical unit is in process of becoming ready"}, - {0x0402, "Logical unit not ready, initializing command required"}, - {0x0403, "Logical unit not ready, manual intervention required"}, - {0x0404, "Logical unit not ready, format in progress"}, - {0x0405, "Logical unit not ready, rebuild in progress"}, - {0x0406, "Logical unit not ready, recalculation in progress"}, - {0x0407, "Logical unit not ready, operation in progress"}, - {0x0408, "Logical unit not ready, long write in progress"}, - {0x0409, "Logical unit not ready, self-test in progress"}, - {0x040A, "Logical unit not accessible, asymmetric access state transition"}, - {0x040B, "Logical unit not accessible, target port in standby state"}, - {0x040C, "Logical unit not accessible, target port in unavailable state"}, - {0x040D, "Logical unit not ready, structure check required"}, - {0x040E, "Logical unit not ready, security session in progress"}, - {0x0410, "Logical unit not ready, auxiliary memory not accessible"}, - {0x0411, "Logical unit not ready, notify (enable spinup) required"}, - {0x0412, "Logical unit not ready, offline"}, - {0x0413, "Logical unit not ready, SA creation in progress"}, - {0x0414, "Logical unit not ready, space allocation in progress"}, - {0x0415, "Logical unit not ready, robotics disabled"}, - {0x0416, "Logical unit not ready, configuration required"}, - {0x0417, "Logical unit not ready, calibration required"}, - {0x0418, "Logical unit not ready, a door is open"}, - {0x0419, "Logical unit not ready, operating in sequential mode"}, - {0x041A, "Logical unit not ready, start stop unit command in progress"}, - {0x041B, "Logical unit not ready, sanitize in progress"}, - {0x041C, "Logical unit not ready, additional power use not yet granted"}, - {0x041D, "Logical unit not ready, configuration in progress"}, - {0x041E, "Logical unit not ready, microcode activation required"}, - {0x041F, "Logical unit not ready, microcode download required"}, - {0x0420, "Logical unit not ready, logical unit reset required"}, - {0x0421, "Logical unit not ready, hard reset required"}, - {0x0422, "Logical unit not ready, power cycle required"}, - - {0x0500, "Logical unit does not respond to selection"}, - - {0x0600, "No reference position found"}, - - {0x0700, "Multiple peripheral devices selected"}, - - {0x0800, "Logical unit communication failure"}, - {0x0801, "Logical unit communication time-out"}, - {0x0802, "Logical unit communication parity error"}, - {0x0803, "Logical unit communication CRC error (Ultra-DMA/32)"}, - {0x0804, "Unreachable copy target"}, - - {0x0900, "Track following error"}, - {0x0901, "Tracking servo failure"}, - {0x0902, "Focus servo failure"}, - {0x0903, "Spindle servo failure"}, - {0x0904, "Head select fault"}, - {0x0905, "Vibration induced tracking error"}, - - {0x0A00, "Error log overflow"}, - - {0x0B00, "Warning"}, - {0x0B01, "Warning - specified temperature exceeded"}, - {0x0B02, "Warning - enclosure degraded"}, - {0x0B03, "Warning - background self-test failed"}, - {0x0B04, "Warning - background pre-scan detected medium error"}, - {0x0B05, "Warning - background medium scan detected medium error"}, - {0x0B06, "Warning - non-volatile cache now volatile"}, - {0x0B07, "Warning - degraded power to non-volatile cache"}, - {0x0B08, "Warning - power loss expected"}, - {0x0B09, "Warning - device statistics notification active"}, - - {0x0C00, "Write error"}, - {0x0C01, "Write error - recovered with auto reallocation"}, - {0x0C02, "Write error - auto reallocation failed"}, - {0x0C03, "Write error - recommend reassignment"}, - {0x0C04, "Compression check miscompare error"}, - {0x0C05, "Data expansion occurred during compression"}, - {0x0C06, "Block not compressible"}, - {0x0C07, "Write error - recovery needed"}, - {0x0C08, "Write error - recovery failed"}, - {0x0C09, "Write error - loss of streaming"}, - {0x0C0A, "Write error - padding blocks added"}, - {0x0C0B, "Auxiliary memory write error"}, - {0x0C0C, "Write error - unexpected unsolicited data"}, - {0x0C0D, "Write error - not enough unsolicited data"}, - {0x0C0E, "Multiple write errors"}, - {0x0C0F, "Defects in error window"}, - {0x0C10, "Incomplete multiple atomic write operations"}, - - {0x0D00, "Error detected by third party temporary initiator"}, - {0x0D01, "Third party device failure"}, - {0x0D02, "Copy target device not reachable"}, - {0x0D03, "Incorrect copy target device type"}, - {0x0D04, "Copy target device data underrun"}, - {0x0D05, "Copy target device data overrun"}, - - {0x0E00, "Invalid information unit"}, - {0x0E01, "Information unit too short"}, - {0x0E02, "Information unit too long"}, - {0x0E03, "Invalid field in command information unit"}, - - {0x1000, "Id CRC or ECC error"}, - {0x1001, "Logical block guard check failed"}, - {0x1002, "Logical block application tag check failed"}, - {0x1003, "Logical block reference tag check failed"}, - {0x1004, "Logical block protection error on recover buffered data"}, - {0x1005, "Logical block protection method error"}, - - {0x1100, "Unrecovered read error"}, - {0x1101, "Read retries exhausted"}, - {0x1102, "Error too long to correct"}, - {0x1103, "Multiple read errors"}, - {0x1104, "Unrecovered read error - auto reallocate failed"}, - {0x1105, "L-EC uncorrectable error"}, - {0x1106, "CIRC unrecovered error"}, - {0x1107, "Data re-synchronization error"}, - {0x1108, "Incomplete block read"}, - {0x1109, "No gap found"}, - {0x110A, "Miscorrected error"}, - {0x110B, "Unrecovered read error - recommend reassignment"}, - {0x110C, "Unrecovered read error - recommend rewrite the data"}, - {0x110D, "De-compression CRC error"}, - {0x110E, "Cannot decompress using declared algorithm"}, - {0x110F, "Error reading UPC/EAN number"}, - {0x1110, "Error reading ISRC number"}, - {0x1111, "Read error - loss of streaming"}, - {0x1112, "Auxiliary memory read error"}, - {0x1113, "Read error - failed retransmission request"}, - {0x1114, "Read error - lba marked bad by application client"}, - {0x1115, "Write after sanitize required"}, - - {0x1200, "Address mark not found for id field"}, - - {0x1300, "Address mark not found for data field"}, - - {0x1400, "Recorded entity not found"}, - {0x1401, "Record not found"}, - {0x1402, "Filemark or setmark not found"}, - {0x1403, "End-of-data not found"}, - {0x1404, "Block sequence error"}, - {0x1405, "Record not found - recommend reassignment"}, - {0x1406, "Record not found - data auto-reallocated"}, - {0x1407, "Locate operation failure"}, - - {0x1500, "Random positioning error"}, - {0x1501, "Mechanical positioning error"}, - {0x1502, "Positioning error detected by read of medium"}, - - {0x1600, "Data synchronization mark error"}, - {0x1601, "Data sync error - data rewritten"}, - {0x1602, "Data sync error - recommend rewrite"}, - {0x1603, "Data sync error - data auto-reallocated"}, - {0x1604, "Data sync error - recommend reassignment"}, - - {0x1700, "Recovered data with no error correction applied"}, - {0x1701, "Recovered data with retries"}, - {0x1702, "Recovered data with positive head offset"}, - {0x1703, "Recovered data with negative head offset"}, - {0x1704, "Recovered data with retries and/or circ applied"}, - {0x1705, "Recovered data using previous sector id"}, - {0x1706, "Recovered data without ECC - data auto-reallocated"}, - {0x1707, "Recovered data without ECC - recommend reassignment"}, - {0x1708, "Recovered data without ECC - recommend rewrite"}, - {0x1709, "Recovered data without ECC - data rewritten"}, - - {0x1800, "Recovered data with error correction applied"}, - {0x1801, "Recovered data with error corr. & retries applied"}, - {0x1802, "Recovered data - data auto-reallocated"}, - {0x1803, "Recovered data with CIRC"}, - {0x1804, "Recovered data with L-EC"}, - {0x1805, "Recovered data - recommend reassignment"}, - {0x1806, "Recovered data - recommend rewrite"}, - {0x1807, "Recovered data with ECC - data rewritten"}, - {0x1808, "Recovered data with linking"}, - - {0x1900, "Defect list error"}, - {0x1901, "Defect list not available"}, - {0x1902, "Defect list error in primary list"}, - {0x1903, "Defect list error in grown list"}, - - {0x1A00, "Parameter list length error"}, - - {0x1B00, "Synchronous data transfer error"}, - - {0x1C00, "Defect list not found"}, - {0x1C01, "Primary defect list not found"}, - {0x1C02, "Grown defect list not found"}, - - {0x1D00, "Miscompare during verify operation"}, - {0x1D01, "Miscompare verify of unmapped LBA"}, - - {0x1E00, "Recovered id with ECC correction"}, - - {0x1F00, "Partial defect list transfer"}, - - {0x2000, "Invalid command operation code"}, - {0x2001, "Access denied - initiator pending-enrolled"}, - {0x2002, "Access denied - no access rights"}, - {0x2003, "Access denied - invalid mgmt id key"}, - {0x2004, "Illegal command while in write capable state"}, - {0x2005, "Obsolete"}, - {0x2006, "Illegal command while in explicit address mode"}, - {0x2007, "Illegal command while in implicit address mode"}, - {0x2008, "Access denied - enrollment conflict"}, - {0x2009, "Access denied - invalid LU identifier"}, - {0x200A, "Access denied - invalid proxy token"}, - {0x200B, "Access denied - ACL LUN conflict"}, - {0x200C, "Illegal command when not in append-only mode"}, - - {0x2100, "Logical block address out of range"}, - {0x2101, "Invalid element address"}, - {0x2102, "Invalid address for write"}, - {0x2103, "Invalid write crossing layer jump"}, - {0x2104, "Unaligned write command"}, - {0x2105, "Write boundary violation"}, - {0x2106, "Attempt to read invalid data"}, - {0x2107, "Read boundary violation"}, - - {0x2200, "Illegal function (use 20 00, 24 00, or 26 00)"}, - - {0x2300, "Invalid token operation, cause not reportable"}, - {0x2301, "Invalid token operation, unsupported token type"}, - {0x2302, "Invalid token operation, remote token usage not supported"}, - {0x2303, "Invalid token operation, remote rod token creation not supported"}, - {0x2304, "Invalid token operation, token unknown"}, - {0x2305, "Invalid token operation, token corrupt"}, - {0x2306, "Invalid token operation, token revoked"}, - {0x2307, "Invalid token operation, token expired"}, - {0x2308, "Invalid token operation, token cancelled"}, - {0x2309, "Invalid token operation, token deleted"}, - {0x230A, "Invalid token operation, invalid token length"}, - - {0x2400, "Invalid field in cdb"}, - {0x2401, "CDB decryption error"}, - {0x2402, "Obsolete"}, - {0x2403, "Obsolete"}, - {0x2404, "Security audit value frozen"}, - {0x2405, "Security working key frozen"}, - {0x2406, "Nonce not unique"}, - {0x2407, "Nonce timestamp out of range"}, - {0x2408, "Invalid XCDB"}, - - {0x2500, "Logical unit not supported"}, - - {0x2600, "Invalid field in parameter list"}, - {0x2601, "Parameter not supported"}, - {0x2602, "Parameter value invalid"}, - {0x2603, "Threshold parameters not supported"}, - {0x2604, "Invalid release of persistent reservation"}, - {0x2605, "Data decryption error"}, - {0x2606, "Too many target descriptors"}, - {0x2607, "Unsupported target descriptor type code"}, - {0x2608, "Too many segment descriptors"}, - {0x2609, "Unsupported segment descriptor type code"}, - {0x260A, "Unexpected inexact segment"}, - {0x260B, "Inline data length exceeded"}, - {0x260C, "Invalid operation for copy source or destination"}, - {0x260D, "Copy segment granularity violation"}, - {0x260E, "Invalid parameter while port is enabled"}, - {0x260F, "Invalid data-out buffer integrity check value"}, - {0x2610, "Data decryption key fail limit reached"}, - {0x2611, "Incomplete key-associated data set"}, - {0x2612, "Vendor specific key reference not found"}, - - {0x2700, "Write protected"}, - {0x2701, "Hardware write protected"}, - {0x2702, "Logical unit software write protected"}, - {0x2703, "Associated write protect"}, - {0x2704, "Persistent write protect"}, - {0x2705, "Permanent write protect"}, - {0x2706, "Conditional write protect"}, - {0x2707, "Space allocation failed write protect"}, - {0x2708, "Zone is read only"}, - - {0x2800, "Not ready to ready change, medium may have changed"}, - {0x2801, "Import or export element accessed"}, - {0x2802, "Format-layer may have changed"}, - {0x2803, "Import/export element accessed, medium changed"}, - - {0x2900, "Power on, reset, or bus device reset occurred"}, - {0x2901, "Power on occurred"}, - {0x2902, "Scsi bus reset occurred"}, - {0x2903, "Bus device reset function occurred"}, - {0x2904, "Device internal reset"}, - {0x2905, "Transceiver mode changed to single-ended"}, - {0x2906, "Transceiver mode changed to lvd"}, - {0x2907, "I_T nexus loss occurred"}, - - {0x2A00, "Parameters changed"}, - {0x2A01, "Mode parameters changed"}, - {0x2A02, "Log parameters changed"}, - {0x2A03, "Reservations preempted"}, - {0x2A04, "Reservations released"}, - {0x2A05, "Registrations preempted"}, - {0x2A06, "Asymmetric access state changed"}, - {0x2A07, "Implicit asymmetric access state transition failed"}, - {0x2A08, "Priority changed"}, - {0x2A09, "Capacity data has changed"}, - {0x2A0A, "Error history I_T nexus cleared"}, - {0x2A0B, "Error history snapshot released"}, - {0x2A0C, "Error recovery attributes have changed"}, - {0x2A0D, "Data encryption capabilities changed"}, - {0x2A10, "Timestamp changed"}, - {0x2A11, "Data encryption parameters changed by another i_t nexus"}, - {0x2A12, "Data encryption parameters changed by vendor specific event"}, - {0x2A13, "Data encryption key instance counter has changed"}, - {0x2A14, "SA creation capabilities data has changed"}, - {0x2A15, "Medium removal prevention preempted"}, - - {0x2B00, "Copy cannot execute since host cannot disconnect"}, - - {0x2C00, "Command sequence error"}, - {0x2C01, "Too many windows specified"}, - {0x2C02, "Invalid combination of windows specified"}, - {0x2C03, "Current program area is not empty"}, - {0x2C04, "Current program area is empty"}, - {0x2C05, "Illegal power condition request"}, - {0x2C06, "Persistent prevent conflict"}, - {0x2C07, "Previous busy status"}, - {0x2C08, "Previous task set full status"}, - {0x2C09, "Previous reservation conflict status"}, - {0x2C0A, "Partition or collection contains user objects"}, - {0x2C0B, "Not reserved"}, - {0x2C0C, "Orwrite generation does not match"}, - {0x2C0D, "Reset write pointer not allowed"}, - {0x2C0E, "Zone is offline"}, - - {0x2D00, "Overwrite error on update in place"}, - - {0x2E00, "Insufficient time for operation"}, - {0x2E01, "Command timeout before processing"}, - {0x2E02, "Command timeout during processing"}, - {0x2E03, "Command timeout during processing due to error recovery"}, - - {0x2F00, "Commands cleared by another initiator"}, - {0x2F01, "Commands cleared by power loss notification"}, - {0x2F02, "Commands cleared by device server"}, - {0x2F03, "Some commands cleared by queuing layer event"}, - - {0x3000, "Incompatible medium installed"}, - {0x3001, "Cannot read medium - unknown format"}, - {0x3002, "Cannot read medium - incompatible format"}, - {0x3003, "Cleaning cartridge installed"}, - {0x3004, "Cannot write medium - unknown format"}, - {0x3005, "Cannot write medium - incompatible format"}, - {0x3006, "Cannot format medium - incompatible medium"}, - {0x3007, "Cleaning failure"}, - {0x3008, "Cannot write - application code mismatch"}, - {0x3009, "Current session not fixated for append"}, - {0x300A, "Cleaning request rejected"}, - {0x300C, "WORM medium - overwrite attempted"}, - {0x300D, "WORM medium - integrity check"}, - {0x3010, "Medium not formatted"}, - {0x3011, "Incompatible volume type"}, - {0x3012, "Incompatible volume qualifier"}, - {0x3013, "Cleaning volume expired"}, - - {0x3100, "Medium format corrupted"}, - {0x3101, "Format command failed"}, - {0x3102, "Zoned formatting failed due to spare linking"}, - {0x3103, "Sanitize command failed"}, - - {0x3200, "No defect spare location available"}, - {0x3201, "Defect list update failure"}, - - {0x3300, "Tape length error"}, - - {0x3400, "Enclosure failure"}, - - {0x3500, "Enclosure services failure"}, - {0x3501, "Unsupported enclosure function"}, - {0x3502, "Enclosure services unavailable"}, - {0x3503, "Enclosure services transfer failure"}, - {0x3504, "Enclosure services transfer refused"}, - {0x3505, "Enclosure services checksum error"}, - - {0x3600, "Ribbon, ink, or toner failure"}, - - {0x3700, "Rounded parameter"}, - - {0x3800, "Event status notification"}, - {0x3802, "Esn - power management class event"}, - {0x3804, "Esn - media class event"}, - {0x3806, "Esn - device busy class event"}, - {0x3807, "Thin Provisioning soft threshold reached"}, - - {0x3900, "Saving parameters not supported"}, - - {0x3A00, "Medium not present"}, - {0x3A01, "Medium not present - tray closed"}, - {0x3A02, "Medium not present - tray open"}, - {0x3A03, "Medium not present - loadable"}, - {0x3A04, "Medium not present - medium auxiliary memory accessible"}, - - {0x3B00, "Sequential positioning error"}, - {0x3B01, "Tape position error at beginning-of-medium"}, - {0x3B02, "Tape position error at end-of-medium"}, - {0x3B03, "Tape or electronic vertical forms unit not ready"}, - {0x3B04, "Slew failure"}, - {0x3B05, "Paper jam"}, - {0x3B06, "Failed to sense top-of-form"}, - {0x3B07, "Failed to sense bottom-of-form"}, - {0x3B08, "Reposition error"}, - {0x3B09, "Read past end of medium"}, - {0x3B0A, "Read past beginning of medium"}, - {0x3B0B, "Position past end of medium"}, - {0x3B0C, "Position past beginning of medium"}, - {0x3B0D, "Medium destination element full"}, - {0x3B0E, "Medium source element empty"}, - {0x3B0F, "End of medium reached"}, - {0x3B11, "Medium magazine not accessible"}, - {0x3B12, "Medium magazine removed"}, - {0x3B13, "Medium magazine inserted"}, - {0x3B14, "Medium magazine locked"}, - {0x3B15, "Medium magazine unlocked"}, - {0x3B16, "Mechanical positioning or changer error"}, - {0x3B17, "Read past end of user object"}, - {0x3B18, "Element disabled"}, - {0x3B19, "Element enabled"}, - {0x3B1A, "Data transfer device removed"}, - {0x3B1B, "Data transfer device inserted"}, - {0x3B1C, "Too many logical objects on partition to support operation"}, - - {0x3D00, "Invalid bits in identify message"}, - - {0x3E00, "Logical unit has not self-configured yet"}, - {0x3E01, "Logical unit failure"}, - {0x3E02, "Timeout on logical unit"}, - {0x3E03, "Logical unit failed self-test"}, - {0x3E04, "Logical unit unable to update self-test log"}, - - {0x3F00, "Target operating conditions have changed"}, - {0x3F01, "Microcode has been changed"}, - {0x3F02, "Changed operating definition"}, - {0x3F03, "Inquiry data has changed"}, - {0x3F04, "Component device attached"}, - {0x3F05, "Device identifier changed"}, - {0x3F06, "Redundancy group created or modified"}, - {0x3F07, "Redundancy group deleted"}, - {0x3F08, "Spare created or modified"}, - {0x3F09, "Spare deleted"}, - {0x3F0A, "Volume set created or modified"}, - {0x3F0B, "Volume set deleted"}, - {0x3F0C, "Volume set deassigned"}, - {0x3F0D, "Volume set reassigned"}, - {0x3F0E, "Reported luns data has changed"}, - {0x3F0F, "Echo buffer overwritten"}, - {0x3F10, "Medium loadable"}, - {0x3F11, "Medium auxiliary memory accessible"}, - {0x3F12, "iSCSI IP address added"}, - {0x3F13, "iSCSI IP address removed"}, - {0x3F14, "iSCSI IP address changed"}, - {0x3F15, "Inspect referrals sense descriptors"}, - {0x3F16, "Microcode has been changed without reset"}, -/* - * {0x40NN, "Ram failure"}, - * {0x40NN, "Diagnostic failure on component nn"}, - * {0x41NN, "Data path failure"}, - * {0x42NN, "Power-on or self-test failure"}, - */ - {0x4300, "Message error"}, - - {0x4400, "Internal target failure"}, - {0x4401, "Persistent reservation information lost"}, - {0x4471, "ATA device failed set features"}, - - {0x4500, "Select or reselect failure"}, - - {0x4600, "Unsuccessful soft reset"}, - - {0x4700, "Scsi parity error"}, - {0x4701, "Data phase CRC error detected"}, - {0x4702, "Scsi parity error detected during st data phase"}, - {0x4703, "Information unit iuCRC error detected"}, - {0x4704, "Asynchronous information protection error detected"}, - {0x4705, "Protocol service CRC error"}, - {0x4706, "Phy test function in progress"}, - {0x477f, "Some commands cleared by iSCSI Protocol event"}, - - {0x4800, "Initiator detected error message received"}, - - {0x4900, "Invalid message error"}, - - {0x4A00, "Command phase error"}, - - {0x4B00, "Data phase error"}, - {0x4B01, "Invalid target port transfer tag received"}, - {0x4B02, "Too much write data"}, - {0x4B03, "Ack/nak timeout"}, - {0x4B04, "Nak received"}, - {0x4B05, "Data offset error"}, - {0x4B06, "Initiator response timeout"}, - {0x4B07, "Connection lost"}, - {0x4B08, "Data-in buffer overflow - data buffer size"}, - {0x4B09, "Data-in buffer overflow - data buffer descriptor area"}, - {0x4B0A, "Data-in buffer error"}, - {0x4B0B, "Data-out buffer overflow - data buffer size"}, - {0x4B0C, "Data-out buffer overflow - data buffer descriptor area"}, - {0x4B0D, "Data-out buffer error"}, - {0x4B0E, "PCIe fabric error"}, - {0x4B0F, "PCIe completion timeout"}, - {0x4B10, "PCIe completer abort"}, - {0x4B11, "PCIe poisoned tlp received"}, - {0x4B12, "PCIe eCRC check failed"}, - {0x4B13, "PCIe unsupported request"}, - {0x4B14, "PCIe acs violation"}, - {0x4B15, "PCIe tlp prefix blocked"}, - - {0x4C00, "Logical unit failed self-configuration"}, -/* - * {0x4DNN, "Tagged overlapped commands (nn = queue tag)"}, - */ - {0x4E00, "Overlapped commands attempted"}, - - {0x5000, "Write append error"}, - {0x5001, "Write append position error"}, - {0x5002, "Position error related to timing"}, - - {0x5100, "Erase failure"}, - {0x5101, "Erase failure - incomplete erase operation detected"}, - - {0x5200, "Cartridge fault"}, - - {0x5300, "Media load or eject failed"}, - {0x5301, "Unload tape failure"}, - {0x5302, "Medium removal prevented"}, - {0x5303, "Medium removal prevented by data transfer element"}, - {0x5304, "Medium thread or unthread failure"}, - {0x5305, "Volume identifier invalid"}, - {0x5306, "Volume identifier missing"}, - {0x5307, "Duplicate volume identifier"}, - {0x5308, "Element status unknown"}, - {0x5309, "Data transfer device error - load failed"}, - {0x530a, "Data transfer device error - unload failed"}, - {0x530b, "Data transfer device error - unload missing"}, - {0x530c, "Data transfer device error - eject failed"}, - {0x530d, "Data transfer device error - library communication failed"}, - - {0x5400, "Scsi to host system interface failure"}, - - {0x5500, "System resource failure"}, - {0x5501, "System buffer full"}, - {0x5502, "Insufficient reservation resources"}, - {0x5503, "Insufficient resources"}, - {0x5504, "Insufficient registration resources"}, - {0x5505, "Insufficient access control resources"}, - {0x5506, "Auxiliary memory out of space"}, - {0x5507, "Quota error"}, - {0x5508, "Maximum number of supplemental decryption keys exceeded"}, - {0x5509, "Medium auxiliary memory not accessible"}, - {0x550A, "Data currently unavailable"}, - {0x550B, "Insufficient power for operation"}, - {0x550C, "Insufficient resources to create rod"}, - {0x550D, "Insufficient resources to create rod token"}, - {0x550E, "Insufficient zone resources"}, - - {0x5700, "Unable to recover table-of-contents"}, - - {0x5800, "Generation does not exist"}, - - {0x5900, "Updated block read"}, - - {0x5A00, "Operator request or state change input"}, - {0x5A01, "Operator medium removal request"}, - {0x5A02, "Operator selected write protect"}, - {0x5A03, "Operator selected write permit"}, - - {0x5B00, "Log exception"}, - {0x5B01, "Threshold condition met"}, - {0x5B02, "Log counter at maximum"}, - {0x5B03, "Log list codes exhausted"}, - - {0x5C00, "Rpl status change"}, - {0x5C01, "Spindles synchronized"}, - {0x5C02, "Spindles not synchronized"}, - - {0x5D00, "Failure prediction threshold exceeded"}, - {0x5D01, "Media failure prediction threshold exceeded"}, - {0x5D02, "Logical unit failure prediction threshold exceeded"}, - {0x5D03, "Spare area exhaustion prediction threshold exceeded"}, - {0x5D10, "Hardware impending failure general hard drive failure"}, - {0x5D11, "Hardware impending failure drive error rate too high"}, - {0x5D12, "Hardware impending failure data error rate too high"}, - {0x5D13, "Hardware impending failure seek error rate too high"}, - {0x5D14, "Hardware impending failure too many block reassigns"}, - {0x5D15, "Hardware impending failure access times too high"}, - {0x5D16, "Hardware impending failure start unit times too high"}, - {0x5D17, "Hardware impending failure channel parametrics"}, - {0x5D18, "Hardware impending failure controller detected"}, - {0x5D19, "Hardware impending failure throughput performance"}, - {0x5D1A, "Hardware impending failure seek time performance"}, - {0x5D1B, "Hardware impending failure spin-up retry count"}, - {0x5D1C, "Hardware impending failure drive calibration retry count"}, - {0x5D20, "Controller impending failure general hard drive failure"}, - {0x5D21, "Controller impending failure drive error rate too high"}, - {0x5D22, "Controller impending failure data error rate too high"}, - {0x5D23, "Controller impending failure seek error rate too high"}, - {0x5D24, "Controller impending failure too many block reassigns"}, - {0x5D25, "Controller impending failure access times too high"}, - {0x5D26, "Controller impending failure start unit times too high"}, - {0x5D27, "Controller impending failure channel parametrics"}, - {0x5D28, "Controller impending failure controller detected"}, - {0x5D29, "Controller impending failure throughput performance"}, - {0x5D2A, "Controller impending failure seek time performance"}, - {0x5D2B, "Controller impending failure spin-up retry count"}, - {0x5D2C, "Controller impending failure drive calibration retry count"}, - {0x5D30, "Data channel impending failure general hard drive failure"}, - {0x5D31, "Data channel impending failure drive error rate too high"}, - {0x5D32, "Data channel impending failure data error rate too high"}, - {0x5D33, "Data channel impending failure seek error rate too high"}, - {0x5D34, "Data channel impending failure too many block reassigns"}, - {0x5D35, "Data channel impending failure access times too high"}, - {0x5D36, "Data channel impending failure start unit times too high"}, - {0x5D37, "Data channel impending failure channel parametrics"}, - {0x5D38, "Data channel impending failure controller detected"}, - {0x5D39, "Data channel impending failure throughput performance"}, - {0x5D3A, "Data channel impending failure seek time performance"}, - {0x5D3B, "Data channel impending failure spin-up retry count"}, - {0x5D3C, "Data channel impending failure drive calibration retry count"}, - {0x5D40, "Servo impending failure general hard drive failure"}, - {0x5D41, "Servo impending failure drive error rate too high"}, - {0x5D42, "Servo impending failure data error rate too high"}, - {0x5D43, "Servo impending failure seek error rate too high"}, - {0x5D44, "Servo impending failure too many block reassigns"}, - {0x5D45, "Servo impending failure access times too high"}, - {0x5D46, "Servo impending failure start unit times too high"}, - {0x5D47, "Servo impending failure channel parametrics"}, - {0x5D48, "Servo impending failure controller detected"}, - {0x5D49, "Servo impending failure throughput performance"}, - {0x5D4A, "Servo impending failure seek time performance"}, - {0x5D4B, "Servo impending failure spin-up retry count"}, - {0x5D4C, "Servo impending failure drive calibration retry count"}, - {0x5D50, "Spindle impending failure general hard drive failure"}, - {0x5D51, "Spindle impending failure drive error rate too high"}, - {0x5D52, "Spindle impending failure data error rate too high"}, - {0x5D53, "Spindle impending failure seek error rate too high"}, - {0x5D54, "Spindle impending failure too many block reassigns"}, - {0x5D55, "Spindle impending failure access times too high"}, - {0x5D56, "Spindle impending failure start unit times too high"}, - {0x5D57, "Spindle impending failure channel parametrics"}, - {0x5D58, "Spindle impending failure controller detected"}, - {0x5D59, "Spindle impending failure throughput performance"}, - {0x5D5A, "Spindle impending failure seek time performance"}, - {0x5D5B, "Spindle impending failure spin-up retry count"}, - {0x5D5C, "Spindle impending failure drive calibration retry count"}, - {0x5D60, "Firmware impending failure general hard drive failure"}, - {0x5D61, "Firmware impending failure drive error rate too high"}, - {0x5D62, "Firmware impending failure data error rate too high"}, - {0x5D63, "Firmware impending failure seek error rate too high"}, - {0x5D64, "Firmware impending failure too many block reassigns"}, - {0x5D65, "Firmware impending failure access times too high"}, - {0x5D66, "Firmware impending failure start unit times too high"}, - {0x5D67, "Firmware impending failure channel parametrics"}, - {0x5D68, "Firmware impending failure controller detected"}, - {0x5D69, "Firmware impending failure throughput performance"}, - {0x5D6A, "Firmware impending failure seek time performance"}, - {0x5D6B, "Firmware impending failure spin-up retry count"}, - {0x5D6C, "Firmware impending failure drive calibration retry count"}, - {0x5DFF, "Failure prediction threshold exceeded (false)"}, - - {0x5E00, "Low power condition on"}, - {0x5E01, "Idle condition activated by timer"}, - {0x5E02, "Standby condition activated by timer"}, - {0x5E03, "Idle condition activated by command"}, - {0x5E04, "Standby condition activated by command"}, - {0x5E05, "Idle_b condition activated by timer"}, - {0x5E06, "Idle_b condition activated by command"}, - {0x5E07, "Idle_c condition activated by timer"}, - {0x5E08, "Idle_c condition activated by command"}, - {0x5E09, "Standby_y condition activated by timer"}, - {0x5E0A, "Standby_y condition activated by command"}, - {0x5E41, "Power state change to active"}, - {0x5E42, "Power state change to idle"}, - {0x5E43, "Power state change to standby"}, - {0x5E45, "Power state change to sleep"}, - {0x5E47, "Power state change to device control"}, - - {0x6000, "Lamp failure"}, - - {0x6100, "Video acquisition error"}, - {0x6101, "Unable to acquire video"}, - {0x6102, "Out of focus"}, - - {0x6200, "Scan head positioning error"}, - - {0x6300, "End of user area encountered on this track"}, - {0x6301, "Packet does not fit in available space"}, - - {0x6400, "Illegal mode for this track"}, - {0x6401, "Invalid packet size"}, - - {0x6500, "Voltage fault"}, - - {0x6600, "Automatic document feeder cover up"}, - {0x6601, "Automatic document feeder lift up"}, - {0x6602, "Document jam in automatic document feeder"}, - {0x6603, "Document miss feed automatic in document feeder"}, - - {0x6700, "Configuration failure"}, - {0x6701, "Configuration of incapable logical units failed"}, - {0x6702, "Add logical unit failed"}, - {0x6703, "Modification of logical unit failed"}, - {0x6704, "Exchange of logical unit failed"}, - {0x6705, "Remove of logical unit failed"}, - {0x6706, "Attachment of logical unit failed"}, - {0x6707, "Creation of logical unit failed"}, - {0x6708, "Assign failure occurred"}, - {0x6709, "Multiply assigned logical unit"}, - {0x670A, "Set target port groups command failed"}, - {0x670B, "ATA device feature not enabled"}, - - {0x6800, "Logical unit not configured"}, - {0x6801, "Subsidiary logical unit not configured"}, - - {0x6900, "Data loss on logical unit"}, - {0x6901, "Multiple logical unit failures"}, - {0x6902, "Parity/data mismatch"}, - - {0x6A00, "Informational, refer to log"}, - - {0x6B00, "State change has occurred"}, - {0x6B01, "Redundancy level got better"}, - {0x6B02, "Redundancy level got worse"}, - - {0x6C00, "Rebuild failure occurred"}, - - {0x6D00, "Recalculate failure occurred"}, - - {0x6E00, "Command to logical unit failed"}, - - {0x6F00, "Copy protection key exchange failure - authentication failure"}, - {0x6F01, "Copy protection key exchange failure - key not present"}, - {0x6F02, "Copy protection key exchange failure - key not established"}, - {0x6F03, "Read of scrambled sector without authentication"}, - {0x6F04, "Media region code is mismatched to logical unit region"}, - {0x6F05, "Drive region must be permanent/region reset count error"}, - {0x6F06, "Insufficient block count for binding nonce recording"}, - {0x6F07, "Conflict in binding nonce recording"}, -/* - * {0x70NN, "Decompression exception short algorithm id of nn"}, - */ - {0x7100, "Decompression exception long algorithm id"}, - - {0x7200, "Session fixation error"}, - {0x7201, "Session fixation error writing lead-in"}, - {0x7202, "Session fixation error writing lead-out"}, - {0x7203, "Session fixation error - incomplete track in session"}, - {0x7204, "Empty or partially written reserved track"}, - {0x7205, "No more track reservations allowed"}, - {0x7206, "RMZ extension is not allowed"}, - {0x7207, "No more test zone extensions are allowed"}, - - {0x7300, "Cd control error"}, - {0x7301, "Power calibration area almost full"}, - {0x7302, "Power calibration area is full"}, - {0x7303, "Power calibration area error"}, - {0x7304, "Program memory area update failure"}, - {0x7305, "Program memory area is full"}, - {0x7306, "RMA/PMA is almost full"}, - {0x7310, "Current power calibration area almost full"}, - {0x7311, "Current power calibration area is full"}, - {0x7317, "RDZ is full"}, - - {0x7400, "Security error"}, - {0x7401, "Unable to decrypt data"}, - {0x7402, "Unencrypted data encountered while decrypting"}, - {0x7403, "Incorrect data encryption key"}, - {0x7404, "Cryptographic integrity validation failed"}, - {0x7405, "Error decrypting data"}, - {0x7406, "Unknown signature verification key"}, - {0x7407, "Encryption parameters not useable"}, - {0x7408, "Digital signature validation failure"}, - {0x7409, "Encryption mode mismatch on read"}, - {0x740A, "Encrypted block not raw read enabled"}, - {0x740B, "Incorrect Encryption parameters"}, - {0x740C, "Unable to decrypt parameter list"}, - {0x740D, "Encryption algorithm disabled"}, - {0x7410, "SA creation parameter value invalid"}, - {0x7411, "SA creation parameter value rejected"}, - {0x7412, "Invalid SA usage"}, - {0x7421, "Data Encryption configuration prevented"}, - {0x7430, "SA creation parameter not supported"}, - {0x7440, "Authentication failed"}, - {0x7461, "External data encryption key manager access error"}, - {0x7462, "External data encryption key manager error"}, - {0x7463, "External data encryption key not found"}, - {0x7464, "External data encryption request not authorized"}, - {0x746E, "External data encryption control timeout"}, - {0x746F, "External data encryption control error"}, - {0x7471, "Logical unit access not authorized"}, - {0x7479, "Security conflict in translated device"}, - +#define SENSE_CODE(c, s) {c, s}, +#include "sense_codes.h" +#undef SENSE_CODE {0, NULL} }; diff --git a/drivers/scsi/sense_codes.h b/drivers/scsi/sense_codes.h new file mode 100644 index 000000000000..e4e1dccd1f2f --- /dev/null +++ b/drivers/scsi/sense_codes.h @@ -0,0 +1,826 @@ +/* + * The canonical list of T10 Additional Sense Codes is available at: + * http://www.t10.org/lists/asc-num.txt [most recent: 20141221] + */ + +SENSE_CODE(0x0000, "No additional sense information") +SENSE_CODE(0x0001, "Filemark detected") +SENSE_CODE(0x0002, "End-of-partition/medium detected") +SENSE_CODE(0x0003, "Setmark detected") +SENSE_CODE(0x0004, "Beginning-of-partition/medium detected") +SENSE_CODE(0x0005, "End-of-data detected") +SENSE_CODE(0x0006, "I/O process terminated") +SENSE_CODE(0x0007, "Programmable early warning detected") +SENSE_CODE(0x0011, "Audio play operation in progress") +SENSE_CODE(0x0012, "Audio play operation paused") +SENSE_CODE(0x0013, "Audio play operation successfully completed") +SENSE_CODE(0x0014, "Audio play operation stopped due to error") +SENSE_CODE(0x0015, "No current audio status to return") +SENSE_CODE(0x0016, "Operation in progress") +SENSE_CODE(0x0017, "Cleaning requested") +SENSE_CODE(0x0018, "Erase operation in progress") +SENSE_CODE(0x0019, "Locate operation in progress") +SENSE_CODE(0x001A, "Rewind operation in progress") +SENSE_CODE(0x001B, "Set capacity operation in progress") +SENSE_CODE(0x001C, "Verify operation in progress") +SENSE_CODE(0x001D, "ATA pass through information available") +SENSE_CODE(0x001E, "Conflicting SA creation request") +SENSE_CODE(0x001F, "Logical unit transitioning to another power condition") +SENSE_CODE(0x0020, "Extended copy information available") +SENSE_CODE(0x0021, "Atomic command aborted due to ACA") + +SENSE_CODE(0x0100, "No index/sector signal") + +SENSE_CODE(0x0200, "No seek complete") + +SENSE_CODE(0x0300, "Peripheral device write fault") +SENSE_CODE(0x0301, "No write current") +SENSE_CODE(0x0302, "Excessive write errors") + +SENSE_CODE(0x0400, "Logical unit not ready, cause not reportable") +SENSE_CODE(0x0401, "Logical unit is in process of becoming ready") +SENSE_CODE(0x0402, "Logical unit not ready, initializing command required") +SENSE_CODE(0x0403, "Logical unit not ready, manual intervention required") +SENSE_CODE(0x0404, "Logical unit not ready, format in progress") +SENSE_CODE(0x0405, "Logical unit not ready, rebuild in progress") +SENSE_CODE(0x0406, "Logical unit not ready, recalculation in progress") +SENSE_CODE(0x0407, "Logical unit not ready, operation in progress") +SENSE_CODE(0x0408, "Logical unit not ready, long write in progress") +SENSE_CODE(0x0409, "Logical unit not ready, self-test in progress") +SENSE_CODE(0x040A, "Logical unit not accessible, asymmetric access state transition") +SENSE_CODE(0x040B, "Logical unit not accessible, target port in standby state") +SENSE_CODE(0x040C, "Logical unit not accessible, target port in unavailable state") +SENSE_CODE(0x040D, "Logical unit not ready, structure check required") +SENSE_CODE(0x040E, "Logical unit not ready, security session in progress") +SENSE_CODE(0x0410, "Logical unit not ready, auxiliary memory not accessible") +SENSE_CODE(0x0411, "Logical unit not ready, notify (enable spinup) required") +SENSE_CODE(0x0412, "Logical unit not ready, offline") +SENSE_CODE(0x0413, "Logical unit not ready, SA creation in progress") +SENSE_CODE(0x0414, "Logical unit not ready, space allocation in progress") +SENSE_CODE(0x0415, "Logical unit not ready, robotics disabled") +SENSE_CODE(0x0416, "Logical unit not ready, configuration required") +SENSE_CODE(0x0417, "Logical unit not ready, calibration required") +SENSE_CODE(0x0418, "Logical unit not ready, a door is open") +SENSE_CODE(0x0419, "Logical unit not ready, operating in sequential mode") +SENSE_CODE(0x041A, "Logical unit not ready, start stop unit command in progress") +SENSE_CODE(0x041B, "Logical unit not ready, sanitize in progress") +SENSE_CODE(0x041C, "Logical unit not ready, additional power use not yet granted") +SENSE_CODE(0x041D, "Logical unit not ready, configuration in progress") +SENSE_CODE(0x041E, "Logical unit not ready, microcode activation required") +SENSE_CODE(0x041F, "Logical unit not ready, microcode download required") +SENSE_CODE(0x0420, "Logical unit not ready, logical unit reset required") +SENSE_CODE(0x0421, "Logical unit not ready, hard reset required") +SENSE_CODE(0x0422, "Logical unit not ready, power cycle required") + +SENSE_CODE(0x0500, "Logical unit does not respond to selection") + +SENSE_CODE(0x0600, "No reference position found") + +SENSE_CODE(0x0700, "Multiple peripheral devices selected") + +SENSE_CODE(0x0800, "Logical unit communication failure") +SENSE_CODE(0x0801, "Logical unit communication time-out") +SENSE_CODE(0x0802, "Logical unit communication parity error") +SENSE_CODE(0x0803, "Logical unit communication CRC error (Ultra-DMA/32)") +SENSE_CODE(0x0804, "Unreachable copy target") + +SENSE_CODE(0x0900, "Track following error") +SENSE_CODE(0x0901, "Tracking servo failure") +SENSE_CODE(0x0902, "Focus servo failure") +SENSE_CODE(0x0903, "Spindle servo failure") +SENSE_CODE(0x0904, "Head select fault") +SENSE_CODE(0x0905, "Vibration induced tracking error") + +SENSE_CODE(0x0A00, "Error log overflow") + +SENSE_CODE(0x0B00, "Warning") +SENSE_CODE(0x0B01, "Warning - specified temperature exceeded") +SENSE_CODE(0x0B02, "Warning - enclosure degraded") +SENSE_CODE(0x0B03, "Warning - background self-test failed") +SENSE_CODE(0x0B04, "Warning - background pre-scan detected medium error") +SENSE_CODE(0x0B05, "Warning - background medium scan detected medium error") +SENSE_CODE(0x0B06, "Warning - non-volatile cache now volatile") +SENSE_CODE(0x0B07, "Warning - degraded power to non-volatile cache") +SENSE_CODE(0x0B08, "Warning - power loss expected") +SENSE_CODE(0x0B09, "Warning - device statistics notification active") + +SENSE_CODE(0x0C00, "Write error") +SENSE_CODE(0x0C01, "Write error - recovered with auto reallocation") +SENSE_CODE(0x0C02, "Write error - auto reallocation failed") +SENSE_CODE(0x0C03, "Write error - recommend reassignment") +SENSE_CODE(0x0C04, "Compression check miscompare error") +SENSE_CODE(0x0C05, "Data expansion occurred during compression") +SENSE_CODE(0x0C06, "Block not compressible") +SENSE_CODE(0x0C07, "Write error - recovery needed") +SENSE_CODE(0x0C08, "Write error - recovery failed") +SENSE_CODE(0x0C09, "Write error - loss of streaming") +SENSE_CODE(0x0C0A, "Write error - padding blocks added") +SENSE_CODE(0x0C0B, "Auxiliary memory write error") +SENSE_CODE(0x0C0C, "Write error - unexpected unsolicited data") +SENSE_CODE(0x0C0D, "Write error - not enough unsolicited data") +SENSE_CODE(0x0C0E, "Multiple write errors") +SENSE_CODE(0x0C0F, "Defects in error window") +SENSE_CODE(0x0C10, "Incomplete multiple atomic write operations") + +SENSE_CODE(0x0D00, "Error detected by third party temporary initiator") +SENSE_CODE(0x0D01, "Third party device failure") +SENSE_CODE(0x0D02, "Copy target device not reachable") +SENSE_CODE(0x0D03, "Incorrect copy target device type") +SENSE_CODE(0x0D04, "Copy target device data underrun") +SENSE_CODE(0x0D05, "Copy target device data overrun") + +SENSE_CODE(0x0E00, "Invalid information unit") +SENSE_CODE(0x0E01, "Information unit too short") +SENSE_CODE(0x0E02, "Information unit too long") +SENSE_CODE(0x0E03, "Invalid field in command information unit") + +SENSE_CODE(0x1000, "Id CRC or ECC error") +SENSE_CODE(0x1001, "Logical block guard check failed") +SENSE_CODE(0x1002, "Logical block application tag check failed") +SENSE_CODE(0x1003, "Logical block reference tag check failed") +SENSE_CODE(0x1004, "Logical block protection error on recover buffered data") +SENSE_CODE(0x1005, "Logical block protection method error") + +SENSE_CODE(0x1100, "Unrecovered read error") +SENSE_CODE(0x1101, "Read retries exhausted") +SENSE_CODE(0x1102, "Error too long to correct") +SENSE_CODE(0x1103, "Multiple read errors") +SENSE_CODE(0x1104, "Unrecovered read error - auto reallocate failed") +SENSE_CODE(0x1105, "L-EC uncorrectable error") +SENSE_CODE(0x1106, "CIRC unrecovered error") +SENSE_CODE(0x1107, "Data re-synchronization error") +SENSE_CODE(0x1108, "Incomplete block read") +SENSE_CODE(0x1109, "No gap found") +SENSE_CODE(0x110A, "Miscorrected error") +SENSE_CODE(0x110B, "Unrecovered read error - recommend reassignment") +SENSE_CODE(0x110C, "Unrecovered read error - recommend rewrite the data") +SENSE_CODE(0x110D, "De-compression CRC error") +SENSE_CODE(0x110E, "Cannot decompress using declared algorithm") +SENSE_CODE(0x110F, "Error reading UPC/EAN number") +SENSE_CODE(0x1110, "Error reading ISRC number") +SENSE_CODE(0x1111, "Read error - loss of streaming") +SENSE_CODE(0x1112, "Auxiliary memory read error") +SENSE_CODE(0x1113, "Read error - failed retransmission request") +SENSE_CODE(0x1114, "Read error - lba marked bad by application client") +SENSE_CODE(0x1115, "Write after sanitize required") + +SENSE_CODE(0x1200, "Address mark not found for id field") + +SENSE_CODE(0x1300, "Address mark not found for data field") + +SENSE_CODE(0x1400, "Recorded entity not found") +SENSE_CODE(0x1401, "Record not found") +SENSE_CODE(0x1402, "Filemark or setmark not found") +SENSE_CODE(0x1403, "End-of-data not found") +SENSE_CODE(0x1404, "Block sequence error") +SENSE_CODE(0x1405, "Record not found - recommend reassignment") +SENSE_CODE(0x1406, "Record not found - data auto-reallocated") +SENSE_CODE(0x1407, "Locate operation failure") + +SENSE_CODE(0x1500, "Random positioning error") +SENSE_CODE(0x1501, "Mechanical positioning error") +SENSE_CODE(0x1502, "Positioning error detected by read of medium") + +SENSE_CODE(0x1600, "Data synchronization mark error") +SENSE_CODE(0x1601, "Data sync error - data rewritten") +SENSE_CODE(0x1602, "Data sync error - recommend rewrite") +SENSE_CODE(0x1603, "Data sync error - data auto-reallocated") +SENSE_CODE(0x1604, "Data sync error - recommend reassignment") + +SENSE_CODE(0x1700, "Recovered data with no error correction applied") +SENSE_CODE(0x1701, "Recovered data with retries") +SENSE_CODE(0x1702, "Recovered data with positive head offset") +SENSE_CODE(0x1703, "Recovered data with negative head offset") +SENSE_CODE(0x1704, "Recovered data with retries and/or circ applied") +SENSE_CODE(0x1705, "Recovered data using previous sector id") +SENSE_CODE(0x1706, "Recovered data without ECC - data auto-reallocated") +SENSE_CODE(0x1707, "Recovered data without ECC - recommend reassignment") +SENSE_CODE(0x1708, "Recovered data without ECC - recommend rewrite") +SENSE_CODE(0x1709, "Recovered data without ECC - data rewritten") + +SENSE_CODE(0x1800, "Recovered data with error correction applied") +SENSE_CODE(0x1801, "Recovered data with error corr. & retries applied") +SENSE_CODE(0x1802, "Recovered data - data auto-reallocated") +SENSE_CODE(0x1803, "Recovered data with CIRC") +SENSE_CODE(0x1804, "Recovered data with L-EC") +SENSE_CODE(0x1805, "Recovered data - recommend reassignment") +SENSE_CODE(0x1806, "Recovered data - recommend rewrite") +SENSE_CODE(0x1807, "Recovered data with ECC - data rewritten") +SENSE_CODE(0x1808, "Recovered data with linking") + +SENSE_CODE(0x1900, "Defect list error") +SENSE_CODE(0x1901, "Defect list not available") +SENSE_CODE(0x1902, "Defect list error in primary list") +SENSE_CODE(0x1903, "Defect list error in grown list") + +SENSE_CODE(0x1A00, "Parameter list length error") + +SENSE_CODE(0x1B00, "Synchronous data transfer error") + +SENSE_CODE(0x1C00, "Defect list not found") +SENSE_CODE(0x1C01, "Primary defect list not found") +SENSE_CODE(0x1C02, "Grown defect list not found") + +SENSE_CODE(0x1D00, "Miscompare during verify operation") +SENSE_CODE(0x1D01, "Miscompare verify of unmapped LBA") + +SENSE_CODE(0x1E00, "Recovered id with ECC correction") + +SENSE_CODE(0x1F00, "Partial defect list transfer") + +SENSE_CODE(0x2000, "Invalid command operation code") +SENSE_CODE(0x2001, "Access denied - initiator pending-enrolled") +SENSE_CODE(0x2002, "Access denied - no access rights") +SENSE_CODE(0x2003, "Access denied - invalid mgmt id key") +SENSE_CODE(0x2004, "Illegal command while in write capable state") +SENSE_CODE(0x2005, "Obsolete") +SENSE_CODE(0x2006, "Illegal command while in explicit address mode") +SENSE_CODE(0x2007, "Illegal command while in implicit address mode") +SENSE_CODE(0x2008, "Access denied - enrollment conflict") +SENSE_CODE(0x2009, "Access denied - invalid LU identifier") +SENSE_CODE(0x200A, "Access denied - invalid proxy token") +SENSE_CODE(0x200B, "Access denied - ACL LUN conflict") +SENSE_CODE(0x200C, "Illegal command when not in append-only mode") + +SENSE_CODE(0x2100, "Logical block address out of range") +SENSE_CODE(0x2101, "Invalid element address") +SENSE_CODE(0x2102, "Invalid address for write") +SENSE_CODE(0x2103, "Invalid write crossing layer jump") +SENSE_CODE(0x2104, "Unaligned write command") +SENSE_CODE(0x2105, "Write boundary violation") +SENSE_CODE(0x2106, "Attempt to read invalid data") +SENSE_CODE(0x2107, "Read boundary violation") + +SENSE_CODE(0x2200, "Illegal function (use 20 00, 24 00, or 26 00)") + +SENSE_CODE(0x2300, "Invalid token operation, cause not reportable") +SENSE_CODE(0x2301, "Invalid token operation, unsupported token type") +SENSE_CODE(0x2302, "Invalid token operation, remote token usage not supported") +SENSE_CODE(0x2303, "Invalid token operation, remote rod token creation not supported") +SENSE_CODE(0x2304, "Invalid token operation, token unknown") +SENSE_CODE(0x2305, "Invalid token operation, token corrupt") +SENSE_CODE(0x2306, "Invalid token operation, token revoked") +SENSE_CODE(0x2307, "Invalid token operation, token expired") +SENSE_CODE(0x2308, "Invalid token operation, token cancelled") +SENSE_CODE(0x2309, "Invalid token operation, token deleted") +SENSE_CODE(0x230A, "Invalid token operation, invalid token length") + +SENSE_CODE(0x2400, "Invalid field in cdb") +SENSE_CODE(0x2401, "CDB decryption error") +SENSE_CODE(0x2402, "Obsolete") +SENSE_CODE(0x2403, "Obsolete") +SENSE_CODE(0x2404, "Security audit value frozen") +SENSE_CODE(0x2405, "Security working key frozen") +SENSE_CODE(0x2406, "Nonce not unique") +SENSE_CODE(0x2407, "Nonce timestamp out of range") +SENSE_CODE(0x2408, "Invalid XCDB") + +SENSE_CODE(0x2500, "Logical unit not supported") + +SENSE_CODE(0x2600, "Invalid field in parameter list") +SENSE_CODE(0x2601, "Parameter not supported") +SENSE_CODE(0x2602, "Parameter value invalid") +SENSE_CODE(0x2603, "Threshold parameters not supported") +SENSE_CODE(0x2604, "Invalid release of persistent reservation") +SENSE_CODE(0x2605, "Data decryption error") +SENSE_CODE(0x2606, "Too many target descriptors") +SENSE_CODE(0x2607, "Unsupported target descriptor type code") +SENSE_CODE(0x2608, "Too many segment descriptors") +SENSE_CODE(0x2609, "Unsupported segment descriptor type code") +SENSE_CODE(0x260A, "Unexpected inexact segment") +SENSE_CODE(0x260B, "Inline data length exceeded") +SENSE_CODE(0x260C, "Invalid operation for copy source or destination") +SENSE_CODE(0x260D, "Copy segment granularity violation") +SENSE_CODE(0x260E, "Invalid parameter while port is enabled") +SENSE_CODE(0x260F, "Invalid data-out buffer integrity check value") +SENSE_CODE(0x2610, "Data decryption key fail limit reached") +SENSE_CODE(0x2611, "Incomplete key-associated data set") +SENSE_CODE(0x2612, "Vendor specific key reference not found") + +SENSE_CODE(0x2700, "Write protected") +SENSE_CODE(0x2701, "Hardware write protected") +SENSE_CODE(0x2702, "Logical unit software write protected") +SENSE_CODE(0x2703, "Associated write protect") +SENSE_CODE(0x2704, "Persistent write protect") +SENSE_CODE(0x2705, "Permanent write protect") +SENSE_CODE(0x2706, "Conditional write protect") +SENSE_CODE(0x2707, "Space allocation failed write protect") +SENSE_CODE(0x2708, "Zone is read only") + +SENSE_CODE(0x2800, "Not ready to ready change, medium may have changed") +SENSE_CODE(0x2801, "Import or export element accessed") +SENSE_CODE(0x2802, "Format-layer may have changed") +SENSE_CODE(0x2803, "Import/export element accessed, medium changed") + +SENSE_CODE(0x2900, "Power on, reset, or bus device reset occurred") +SENSE_CODE(0x2901, "Power on occurred") +SENSE_CODE(0x2902, "Scsi bus reset occurred") +SENSE_CODE(0x2903, "Bus device reset function occurred") +SENSE_CODE(0x2904, "Device internal reset") +SENSE_CODE(0x2905, "Transceiver mode changed to single-ended") +SENSE_CODE(0x2906, "Transceiver mode changed to lvd") +SENSE_CODE(0x2907, "I_T nexus loss occurred") + +SENSE_CODE(0x2A00, "Parameters changed") +SENSE_CODE(0x2A01, "Mode parameters changed") +SENSE_CODE(0x2A02, "Log parameters changed") +SENSE_CODE(0x2A03, "Reservations preempted") +SENSE_CODE(0x2A04, "Reservations released") +SENSE_CODE(0x2A05, "Registrations preempted") +SENSE_CODE(0x2A06, "Asymmetric access state changed") +SENSE_CODE(0x2A07, "Implicit asymmetric access state transition failed") +SENSE_CODE(0x2A08, "Priority changed") +SENSE_CODE(0x2A09, "Capacity data has changed") +SENSE_CODE(0x2A0A, "Error history I_T nexus cleared") +SENSE_CODE(0x2A0B, "Error history snapshot released") +SENSE_CODE(0x2A0C, "Error recovery attributes have changed") +SENSE_CODE(0x2A0D, "Data encryption capabilities changed") +SENSE_CODE(0x2A10, "Timestamp changed") +SENSE_CODE(0x2A11, "Data encryption parameters changed by another i_t nexus") +SENSE_CODE(0x2A12, "Data encryption parameters changed by vendor specific event") +SENSE_CODE(0x2A13, "Data encryption key instance counter has changed") +SENSE_CODE(0x2A14, "SA creation capabilities data has changed") +SENSE_CODE(0x2A15, "Medium removal prevention preempted") + +SENSE_CODE(0x2B00, "Copy cannot execute since host cannot disconnect") + +SENSE_CODE(0x2C00, "Command sequence error") +SENSE_CODE(0x2C01, "Too many windows specified") +SENSE_CODE(0x2C02, "Invalid combination of windows specified") +SENSE_CODE(0x2C03, "Current program area is not empty") +SENSE_CODE(0x2C04, "Current program area is empty") +SENSE_CODE(0x2C05, "Illegal power condition request") +SENSE_CODE(0x2C06, "Persistent prevent conflict") +SENSE_CODE(0x2C07, "Previous busy status") +SENSE_CODE(0x2C08, "Previous task set full status") +SENSE_CODE(0x2C09, "Previous reservation conflict status") +SENSE_CODE(0x2C0A, "Partition or collection contains user objects") +SENSE_CODE(0x2C0B, "Not reserved") +SENSE_CODE(0x2C0C, "Orwrite generation does not match") +SENSE_CODE(0x2C0D, "Reset write pointer not allowed") +SENSE_CODE(0x2C0E, "Zone is offline") + +SENSE_CODE(0x2D00, "Overwrite error on update in place") + +SENSE_CODE(0x2E00, "Insufficient time for operation") +SENSE_CODE(0x2E01, "Command timeout before processing") +SENSE_CODE(0x2E02, "Command timeout during processing") +SENSE_CODE(0x2E03, "Command timeout during processing due to error recovery") + +SENSE_CODE(0x2F00, "Commands cleared by another initiator") +SENSE_CODE(0x2F01, "Commands cleared by power loss notification") +SENSE_CODE(0x2F02, "Commands cleared by device server") +SENSE_CODE(0x2F03, "Some commands cleared by queuing layer event") + +SENSE_CODE(0x3000, "Incompatible medium installed") +SENSE_CODE(0x3001, "Cannot read medium - unknown format") +SENSE_CODE(0x3002, "Cannot read medium - incompatible format") +SENSE_CODE(0x3003, "Cleaning cartridge installed") +SENSE_CODE(0x3004, "Cannot write medium - unknown format") +SENSE_CODE(0x3005, "Cannot write medium - incompatible format") +SENSE_CODE(0x3006, "Cannot format medium - incompatible medium") +SENSE_CODE(0x3007, "Cleaning failure") +SENSE_CODE(0x3008, "Cannot write - application code mismatch") +SENSE_CODE(0x3009, "Current session not fixated for append") +SENSE_CODE(0x300A, "Cleaning request rejected") +SENSE_CODE(0x300C, "WORM medium - overwrite attempted") +SENSE_CODE(0x300D, "WORM medium - integrity check") +SENSE_CODE(0x3010, "Medium not formatted") +SENSE_CODE(0x3011, "Incompatible volume type") +SENSE_CODE(0x3012, "Incompatible volume qualifier") +SENSE_CODE(0x3013, "Cleaning volume expired") + +SENSE_CODE(0x3100, "Medium format corrupted") +SENSE_CODE(0x3101, "Format command failed") +SENSE_CODE(0x3102, "Zoned formatting failed due to spare linking") +SENSE_CODE(0x3103, "Sanitize command failed") + +SENSE_CODE(0x3200, "No defect spare location available") +SENSE_CODE(0x3201, "Defect list update failure") + +SENSE_CODE(0x3300, "Tape length error") + +SENSE_CODE(0x3400, "Enclosure failure") + +SENSE_CODE(0x3500, "Enclosure services failure") +SENSE_CODE(0x3501, "Unsupported enclosure function") +SENSE_CODE(0x3502, "Enclosure services unavailable") +SENSE_CODE(0x3503, "Enclosure services transfer failure") +SENSE_CODE(0x3504, "Enclosure services transfer refused") +SENSE_CODE(0x3505, "Enclosure services checksum error") + +SENSE_CODE(0x3600, "Ribbon, ink, or toner failure") + +SENSE_CODE(0x3700, "Rounded parameter") + +SENSE_CODE(0x3800, "Event status notification") +SENSE_CODE(0x3802, "Esn - power management class event") +SENSE_CODE(0x3804, "Esn - media class event") +SENSE_CODE(0x3806, "Esn - device busy class event") +SENSE_CODE(0x3807, "Thin Provisioning soft threshold reached") + +SENSE_CODE(0x3900, "Saving parameters not supported") + +SENSE_CODE(0x3A00, "Medium not present") +SENSE_CODE(0x3A01, "Medium not present - tray closed") +SENSE_CODE(0x3A02, "Medium not present - tray open") +SENSE_CODE(0x3A03, "Medium not present - loadable") +SENSE_CODE(0x3A04, "Medium not present - medium auxiliary memory accessible") + +SENSE_CODE(0x3B00, "Sequential positioning error") +SENSE_CODE(0x3B01, "Tape position error at beginning-of-medium") +SENSE_CODE(0x3B02, "Tape position error at end-of-medium") +SENSE_CODE(0x3B03, "Tape or electronic vertical forms unit not ready") +SENSE_CODE(0x3B04, "Slew failure") +SENSE_CODE(0x3B05, "Paper jam") +SENSE_CODE(0x3B06, "Failed to sense top-of-form") +SENSE_CODE(0x3B07, "Failed to sense bottom-of-form") +SENSE_CODE(0x3B08, "Reposition error") +SENSE_CODE(0x3B09, "Read past end of medium") +SENSE_CODE(0x3B0A, "Read past beginning of medium") +SENSE_CODE(0x3B0B, "Position past end of medium") +SENSE_CODE(0x3B0C, "Position past beginning of medium") +SENSE_CODE(0x3B0D, "Medium destination element full") +SENSE_CODE(0x3B0E, "Medium source element empty") +SENSE_CODE(0x3B0F, "End of medium reached") +SENSE_CODE(0x3B11, "Medium magazine not accessible") +SENSE_CODE(0x3B12, "Medium magazine removed") +SENSE_CODE(0x3B13, "Medium magazine inserted") +SENSE_CODE(0x3B14, "Medium magazine locked") +SENSE_CODE(0x3B15, "Medium magazine unlocked") +SENSE_CODE(0x3B16, "Mechanical positioning or changer error") +SENSE_CODE(0x3B17, "Read past end of user object") +SENSE_CODE(0x3B18, "Element disabled") +SENSE_CODE(0x3B19, "Element enabled") +SENSE_CODE(0x3B1A, "Data transfer device removed") +SENSE_CODE(0x3B1B, "Data transfer device inserted") +SENSE_CODE(0x3B1C, "Too many logical objects on partition to support operation") + +SENSE_CODE(0x3D00, "Invalid bits in identify message") + +SENSE_CODE(0x3E00, "Logical unit has not self-configured yet") +SENSE_CODE(0x3E01, "Logical unit failure") +SENSE_CODE(0x3E02, "Timeout on logical unit") +SENSE_CODE(0x3E03, "Logical unit failed self-test") +SENSE_CODE(0x3E04, "Logical unit unable to update self-test log") + +SENSE_CODE(0x3F00, "Target operating conditions have changed") +SENSE_CODE(0x3F01, "Microcode has been changed") +SENSE_CODE(0x3F02, "Changed operating definition") +SENSE_CODE(0x3F03, "Inquiry data has changed") +SENSE_CODE(0x3F04, "Component device attached") +SENSE_CODE(0x3F05, "Device identifier changed") +SENSE_CODE(0x3F06, "Redundancy group created or modified") +SENSE_CODE(0x3F07, "Redundancy group deleted") +SENSE_CODE(0x3F08, "Spare created or modified") +SENSE_CODE(0x3F09, "Spare deleted") +SENSE_CODE(0x3F0A, "Volume set created or modified") +SENSE_CODE(0x3F0B, "Volume set deleted") +SENSE_CODE(0x3F0C, "Volume set deassigned") +SENSE_CODE(0x3F0D, "Volume set reassigned") +SENSE_CODE(0x3F0E, "Reported luns data has changed") +SENSE_CODE(0x3F0F, "Echo buffer overwritten") +SENSE_CODE(0x3F10, "Medium loadable") +SENSE_CODE(0x3F11, "Medium auxiliary memory accessible") +SENSE_CODE(0x3F12, "iSCSI IP address added") +SENSE_CODE(0x3F13, "iSCSI IP address removed") +SENSE_CODE(0x3F14, "iSCSI IP address changed") +SENSE_CODE(0x3F15, "Inspect referrals sense descriptors") +SENSE_CODE(0x3F16, "Microcode has been changed without reset") +/* + * SENSE_CODE(0x40NN, "Ram failure") + * SENSE_CODE(0x40NN, "Diagnostic failure on component nn") + * SENSE_CODE(0x41NN, "Data path failure") + * SENSE_CODE(0x42NN, "Power-on or self-test failure") + */ +SENSE_CODE(0x4300, "Message error") + +SENSE_CODE(0x4400, "Internal target failure") +SENSE_CODE(0x4401, "Persistent reservation information lost") +SENSE_CODE(0x4471, "ATA device failed set features") + +SENSE_CODE(0x4500, "Select or reselect failure") + +SENSE_CODE(0x4600, "Unsuccessful soft reset") + +SENSE_CODE(0x4700, "Scsi parity error") +SENSE_CODE(0x4701, "Data phase CRC error detected") +SENSE_CODE(0x4702, "Scsi parity error detected during st data phase") +SENSE_CODE(0x4703, "Information unit iuCRC error detected") +SENSE_CODE(0x4704, "Asynchronous information protection error detected") +SENSE_CODE(0x4705, "Protocol service CRC error") +SENSE_CODE(0x4706, "Phy test function in progress") +SENSE_CODE(0x477f, "Some commands cleared by iSCSI Protocol event") + +SENSE_CODE(0x4800, "Initiator detected error message received") + +SENSE_CODE(0x4900, "Invalid message error") + +SENSE_CODE(0x4A00, "Command phase error") + +SENSE_CODE(0x4B00, "Data phase error") +SENSE_CODE(0x4B01, "Invalid target port transfer tag received") +SENSE_CODE(0x4B02, "Too much write data") +SENSE_CODE(0x4B03, "Ack/nak timeout") +SENSE_CODE(0x4B04, "Nak received") +SENSE_CODE(0x4B05, "Data offset error") +SENSE_CODE(0x4B06, "Initiator response timeout") +SENSE_CODE(0x4B07, "Connection lost") +SENSE_CODE(0x4B08, "Data-in buffer overflow - data buffer size") +SENSE_CODE(0x4B09, "Data-in buffer overflow - data buffer descriptor area") +SENSE_CODE(0x4B0A, "Data-in buffer error") +SENSE_CODE(0x4B0B, "Data-out buffer overflow - data buffer size") +SENSE_CODE(0x4B0C, "Data-out buffer overflow - data buffer descriptor area") +SENSE_CODE(0x4B0D, "Data-out buffer error") +SENSE_CODE(0x4B0E, "PCIe fabric error") +SENSE_CODE(0x4B0F, "PCIe completion timeout") +SENSE_CODE(0x4B10, "PCIe completer abort") +SENSE_CODE(0x4B11, "PCIe poisoned tlp received") +SENSE_CODE(0x4B12, "PCIe eCRC check failed") +SENSE_CODE(0x4B13, "PCIe unsupported request") +SENSE_CODE(0x4B14, "PCIe acs violation") +SENSE_CODE(0x4B15, "PCIe tlp prefix blocked") + +SENSE_CODE(0x4C00, "Logical unit failed self-configuration") +/* + * SENSE_CODE(0x4DNN, "Tagged overlapped commands (nn = queue tag)") + */ +SENSE_CODE(0x4E00, "Overlapped commands attempted") + +SENSE_CODE(0x5000, "Write append error") +SENSE_CODE(0x5001, "Write append position error") +SENSE_CODE(0x5002, "Position error related to timing") + +SENSE_CODE(0x5100, "Erase failure") +SENSE_CODE(0x5101, "Erase failure - incomplete erase operation detected") + +SENSE_CODE(0x5200, "Cartridge fault") + +SENSE_CODE(0x5300, "Media load or eject failed") +SENSE_CODE(0x5301, "Unload tape failure") +SENSE_CODE(0x5302, "Medium removal prevented") +SENSE_CODE(0x5303, "Medium removal prevented by data transfer element") +SENSE_CODE(0x5304, "Medium thread or unthread failure") +SENSE_CODE(0x5305, "Volume identifier invalid") +SENSE_CODE(0x5306, "Volume identifier missing") +SENSE_CODE(0x5307, "Duplicate volume identifier") +SENSE_CODE(0x5308, "Element status unknown") +SENSE_CODE(0x5309, "Data transfer device error - load failed") +SENSE_CODE(0x530a, "Data transfer device error - unload failed") +SENSE_CODE(0x530b, "Data transfer device error - unload missing") +SENSE_CODE(0x530c, "Data transfer device error - eject failed") +SENSE_CODE(0x530d, "Data transfer device error - library communication failed") + +SENSE_CODE(0x5400, "Scsi to host system interface failure") + +SENSE_CODE(0x5500, "System resource failure") +SENSE_CODE(0x5501, "System buffer full") +SENSE_CODE(0x5502, "Insufficient reservation resources") +SENSE_CODE(0x5503, "Insufficient resources") +SENSE_CODE(0x5504, "Insufficient registration resources") +SENSE_CODE(0x5505, "Insufficient access control resources") +SENSE_CODE(0x5506, "Auxiliary memory out of space") +SENSE_CODE(0x5507, "Quota error") +SENSE_CODE(0x5508, "Maximum number of supplemental decryption keys exceeded") +SENSE_CODE(0x5509, "Medium auxiliary memory not accessible") +SENSE_CODE(0x550A, "Data currently unavailable") +SENSE_CODE(0x550B, "Insufficient power for operation") +SENSE_CODE(0x550C, "Insufficient resources to create rod") +SENSE_CODE(0x550D, "Insufficient resources to create rod token") +SENSE_CODE(0x550E, "Insufficient zone resources") + +SENSE_CODE(0x5700, "Unable to recover table-of-contents") + +SENSE_CODE(0x5800, "Generation does not exist") + +SENSE_CODE(0x5900, "Updated block read") + +SENSE_CODE(0x5A00, "Operator request or state change input") +SENSE_CODE(0x5A01, "Operator medium removal request") +SENSE_CODE(0x5A02, "Operator selected write protect") +SENSE_CODE(0x5A03, "Operator selected write permit") + +SENSE_CODE(0x5B00, "Log exception") +SENSE_CODE(0x5B01, "Threshold condition met") +SENSE_CODE(0x5B02, "Log counter at maximum") +SENSE_CODE(0x5B03, "Log list codes exhausted") + +SENSE_CODE(0x5C00, "Rpl status change") +SENSE_CODE(0x5C01, "Spindles synchronized") +SENSE_CODE(0x5C02, "Spindles not synchronized") + +SENSE_CODE(0x5D00, "Failure prediction threshold exceeded") +SENSE_CODE(0x5D01, "Media failure prediction threshold exceeded") +SENSE_CODE(0x5D02, "Logical unit failure prediction threshold exceeded") +SENSE_CODE(0x5D03, "Spare area exhaustion prediction threshold exceeded") +SENSE_CODE(0x5D10, "Hardware impending failure general hard drive failure") +SENSE_CODE(0x5D11, "Hardware impending failure drive error rate too high") +SENSE_CODE(0x5D12, "Hardware impending failure data error rate too high") +SENSE_CODE(0x5D13, "Hardware impending failure seek error rate too high") +SENSE_CODE(0x5D14, "Hardware impending failure too many block reassigns") +SENSE_CODE(0x5D15, "Hardware impending failure access times too high") +SENSE_CODE(0x5D16, "Hardware impending failure start unit times too high") +SENSE_CODE(0x5D17, "Hardware impending failure channel parametrics") +SENSE_CODE(0x5D18, "Hardware impending failure controller detected") +SENSE_CODE(0x5D19, "Hardware impending failure throughput performance") +SENSE_CODE(0x5D1A, "Hardware impending failure seek time performance") +SENSE_CODE(0x5D1B, "Hardware impending failure spin-up retry count") +SENSE_CODE(0x5D1C, "Hardware impending failure drive calibration retry count") +SENSE_CODE(0x5D20, "Controller impending failure general hard drive failure") +SENSE_CODE(0x5D21, "Controller impending failure drive error rate too high") +SENSE_CODE(0x5D22, "Controller impending failure data error rate too high") +SENSE_CODE(0x5D23, "Controller impending failure seek error rate too high") +SENSE_CODE(0x5D24, "Controller impending failure too many block reassigns") +SENSE_CODE(0x5D25, "Controller impending failure access times too high") +SENSE_CODE(0x5D26, "Controller impending failure start unit times too high") +SENSE_CODE(0x5D27, "Controller impending failure channel parametrics") +SENSE_CODE(0x5D28, "Controller impending failure controller detected") +SENSE_CODE(0x5D29, "Controller impending failure throughput performance") +SENSE_CODE(0x5D2A, "Controller impending failure seek time performance") +SENSE_CODE(0x5D2B, "Controller impending failure spin-up retry count") +SENSE_CODE(0x5D2C, "Controller impending failure drive calibration retry count") +SENSE_CODE(0x5D30, "Data channel impending failure general hard drive failure") +SENSE_CODE(0x5D31, "Data channel impending failure drive error rate too high") +SENSE_CODE(0x5D32, "Data channel impending failure data error rate too high") +SENSE_CODE(0x5D33, "Data channel impending failure seek error rate too high") +SENSE_CODE(0x5D34, "Data channel impending failure too many block reassigns") +SENSE_CODE(0x5D35, "Data channel impending failure access times too high") +SENSE_CODE(0x5D36, "Data channel impending failure start unit times too high") +SENSE_CODE(0x5D37, "Data channel impending failure channel parametrics") +SENSE_CODE(0x5D38, "Data channel impending failure controller detected") +SENSE_CODE(0x5D39, "Data channel impending failure throughput performance") +SENSE_CODE(0x5D3A, "Data channel impending failure seek time performance") +SENSE_CODE(0x5D3B, "Data channel impending failure spin-up retry count") +SENSE_CODE(0x5D3C, "Data channel impending failure drive calibration retry count") +SENSE_CODE(0x5D40, "Servo impending failure general hard drive failure") +SENSE_CODE(0x5D41, "Servo impending failure drive error rate too high") +SENSE_CODE(0x5D42, "Servo impending failure data error rate too high") +SENSE_CODE(0x5D43, "Servo impending failure seek error rate too high") +SENSE_CODE(0x5D44, "Servo impending failure too many block reassigns") +SENSE_CODE(0x5D45, "Servo impending failure access times too high") +SENSE_CODE(0x5D46, "Servo impending failure start unit times too high") +SENSE_CODE(0x5D47, "Servo impending failure channel parametrics") +SENSE_CODE(0x5D48, "Servo impending failure controller detected") +SENSE_CODE(0x5D49, "Servo impending failure throughput performance") +SENSE_CODE(0x5D4A, "Servo impending failure seek time performance") +SENSE_CODE(0x5D4B, "Servo impending failure spin-up retry count") +SENSE_CODE(0x5D4C, "Servo impending failure drive calibration retry count") +SENSE_CODE(0x5D50, "Spindle impending failure general hard drive failure") +SENSE_CODE(0x5D51, "Spindle impending failure drive error rate too high") +SENSE_CODE(0x5D52, "Spindle impending failure data error rate too high") +SENSE_CODE(0x5D53, "Spindle impending failure seek error rate too high") +SENSE_CODE(0x5D54, "Spindle impending failure too many block reassigns") +SENSE_CODE(0x5D55, "Spindle impending failure access times too high") +SENSE_CODE(0x5D56, "Spindle impending failure start unit times too high") +SENSE_CODE(0x5D57, "Spindle impending failure channel parametrics") +SENSE_CODE(0x5D58, "Spindle impending failure controller detected") +SENSE_CODE(0x5D59, "Spindle impending failure throughput performance") +SENSE_CODE(0x5D5A, "Spindle impending failure seek time performance") +SENSE_CODE(0x5D5B, "Spindle impending failure spin-up retry count") +SENSE_CODE(0x5D5C, "Spindle impending failure drive calibration retry count") +SENSE_CODE(0x5D60, "Firmware impending failure general hard drive failure") +SENSE_CODE(0x5D61, "Firmware impending failure drive error rate too high") +SENSE_CODE(0x5D62, "Firmware impending failure data error rate too high") +SENSE_CODE(0x5D63, "Firmware impending failure seek error rate too high") +SENSE_CODE(0x5D64, "Firmware impending failure too many block reassigns") +SENSE_CODE(0x5D65, "Firmware impending failure access times too high") +SENSE_CODE(0x5D66, "Firmware impending failure start unit times too high") +SENSE_CODE(0x5D67, "Firmware impending failure channel parametrics") +SENSE_CODE(0x5D68, "Firmware impending failure controller detected") +SENSE_CODE(0x5D69, "Firmware impending failure throughput performance") +SENSE_CODE(0x5D6A, "Firmware impending failure seek time performance") +SENSE_CODE(0x5D6B, "Firmware impending failure spin-up retry count") +SENSE_CODE(0x5D6C, "Firmware impending failure drive calibration retry count") +SENSE_CODE(0x5DFF, "Failure prediction threshold exceeded (false)") + +SENSE_CODE(0x5E00, "Low power condition on") +SENSE_CODE(0x5E01, "Idle condition activated by timer") +SENSE_CODE(0x5E02, "Standby condition activated by timer") +SENSE_CODE(0x5E03, "Idle condition activated by command") +SENSE_CODE(0x5E04, "Standby condition activated by command") +SENSE_CODE(0x5E05, "Idle_b condition activated by timer") +SENSE_CODE(0x5E06, "Idle_b condition activated by command") +SENSE_CODE(0x5E07, "Idle_c condition activated by timer") +SENSE_CODE(0x5E08, "Idle_c condition activated by command") +SENSE_CODE(0x5E09, "Standby_y condition activated by timer") +SENSE_CODE(0x5E0A, "Standby_y condition activated by command") +SENSE_CODE(0x5E41, "Power state change to active") +SENSE_CODE(0x5E42, "Power state change to idle") +SENSE_CODE(0x5E43, "Power state change to standby") +SENSE_CODE(0x5E45, "Power state change to sleep") +SENSE_CODE(0x5E47, "Power state change to device control") + +SENSE_CODE(0x6000, "Lamp failure") + +SENSE_CODE(0x6100, "Video acquisition error") +SENSE_CODE(0x6101, "Unable to acquire video") +SENSE_CODE(0x6102, "Out of focus") + +SENSE_CODE(0x6200, "Scan head positioning error") + +SENSE_CODE(0x6300, "End of user area encountered on this track") +SENSE_CODE(0x6301, "Packet does not fit in available space") + +SENSE_CODE(0x6400, "Illegal mode for this track") +SENSE_CODE(0x6401, "Invalid packet size") + +SENSE_CODE(0x6500, "Voltage fault") + +SENSE_CODE(0x6600, "Automatic document feeder cover up") +SENSE_CODE(0x6601, "Automatic document feeder lift up") +SENSE_CODE(0x6602, "Document jam in automatic document feeder") +SENSE_CODE(0x6603, "Document miss feed automatic in document feeder") + +SENSE_CODE(0x6700, "Configuration failure") +SENSE_CODE(0x6701, "Configuration of incapable logical units failed") +SENSE_CODE(0x6702, "Add logical unit failed") +SENSE_CODE(0x6703, "Modification of logical unit failed") +SENSE_CODE(0x6704, "Exchange of logical unit failed") +SENSE_CODE(0x6705, "Remove of logical unit failed") +SENSE_CODE(0x6706, "Attachment of logical unit failed") +SENSE_CODE(0x6707, "Creation of logical unit failed") +SENSE_CODE(0x6708, "Assign failure occurred") +SENSE_CODE(0x6709, "Multiply assigned logical unit") +SENSE_CODE(0x670A, "Set target port groups command failed") +SENSE_CODE(0x670B, "ATA device feature not enabled") + +SENSE_CODE(0x6800, "Logical unit not configured") +SENSE_CODE(0x6801, "Subsidiary logical unit not configured") + +SENSE_CODE(0x6900, "Data loss on logical unit") +SENSE_CODE(0x6901, "Multiple logical unit failures") +SENSE_CODE(0x6902, "Parity/data mismatch") + +SENSE_CODE(0x6A00, "Informational, refer to log") + +SENSE_CODE(0x6B00, "State change has occurred") +SENSE_CODE(0x6B01, "Redundancy level got better") +SENSE_CODE(0x6B02, "Redundancy level got worse") + +SENSE_CODE(0x6C00, "Rebuild failure occurred") + +SENSE_CODE(0x6D00, "Recalculate failure occurred") + +SENSE_CODE(0x6E00, "Command to logical unit failed") + +SENSE_CODE(0x6F00, "Copy protection key exchange failure - authentication failure") +SENSE_CODE(0x6F01, "Copy protection key exchange failure - key not present") +SENSE_CODE(0x6F02, "Copy protection key exchange failure - key not established") +SENSE_CODE(0x6F03, "Read of scrambled sector without authentication") +SENSE_CODE(0x6F04, "Media region code is mismatched to logical unit region") +SENSE_CODE(0x6F05, "Drive region must be permanent/region reset count error") +SENSE_CODE(0x6F06, "Insufficient block count for binding nonce recording") +SENSE_CODE(0x6F07, "Conflict in binding nonce recording") +/* + * SENSE_CODE(0x70NN, "Decompression exception short algorithm id of nn") + */ +SENSE_CODE(0x7100, "Decompression exception long algorithm id") + +SENSE_CODE(0x7200, "Session fixation error") +SENSE_CODE(0x7201, "Session fixation error writing lead-in") +SENSE_CODE(0x7202, "Session fixation error writing lead-out") +SENSE_CODE(0x7203, "Session fixation error - incomplete track in session") +SENSE_CODE(0x7204, "Empty or partially written reserved track") +SENSE_CODE(0x7205, "No more track reservations allowed") +SENSE_CODE(0x7206, "RMZ extension is not allowed") +SENSE_CODE(0x7207, "No more test zone extensions are allowed") + +SENSE_CODE(0x7300, "Cd control error") +SENSE_CODE(0x7301, "Power calibration area almost full") +SENSE_CODE(0x7302, "Power calibration area is full") +SENSE_CODE(0x7303, "Power calibration area error") +SENSE_CODE(0x7304, "Program memory area update failure") +SENSE_CODE(0x7305, "Program memory area is full") +SENSE_CODE(0x7306, "RMA/PMA is almost full") +SENSE_CODE(0x7310, "Current power calibration area almost full") +SENSE_CODE(0x7311, "Current power calibration area is full") +SENSE_CODE(0x7317, "RDZ is full") + +SENSE_CODE(0x7400, "Security error") +SENSE_CODE(0x7401, "Unable to decrypt data") +SENSE_CODE(0x7402, "Unencrypted data encountered while decrypting") +SENSE_CODE(0x7403, "Incorrect data encryption key") +SENSE_CODE(0x7404, "Cryptographic integrity validation failed") +SENSE_CODE(0x7405, "Error decrypting data") +SENSE_CODE(0x7406, "Unknown signature verification key") +SENSE_CODE(0x7407, "Encryption parameters not useable") +SENSE_CODE(0x7408, "Digital signature validation failure") +SENSE_CODE(0x7409, "Encryption mode mismatch on read") +SENSE_CODE(0x740A, "Encrypted block not raw read enabled") +SENSE_CODE(0x740B, "Incorrect Encryption parameters") +SENSE_CODE(0x740C, "Unable to decrypt parameter list") +SENSE_CODE(0x740D, "Encryption algorithm disabled") +SENSE_CODE(0x7410, "SA creation parameter value invalid") +SENSE_CODE(0x7411, "SA creation parameter value rejected") +SENSE_CODE(0x7412, "Invalid SA usage") +SENSE_CODE(0x7421, "Data Encryption configuration prevented") +SENSE_CODE(0x7430, "SA creation parameter not supported") +SENSE_CODE(0x7440, "Authentication failed") +SENSE_CODE(0x7461, "External data encryption key manager access error") +SENSE_CODE(0x7462, "External data encryption key manager error") +SENSE_CODE(0x7463, "External data encryption key not found") +SENSE_CODE(0x7464, "External data encryption request not authorized") +SENSE_CODE(0x746E, "External data encryption control timeout") +SENSE_CODE(0x746F, "External data encryption control error") +SENSE_CODE(0x7471, "Logical unit access not authorized") +SENSE_CODE(0x7479, "Security conflict in translated device") -- GitLab From e1f0bce3a0db95007fec756225801e50477f32fd Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 22 Mar 2016 20:32:05 +0100 Subject: [PATCH 2056/9938] scsi: reduce CONFIG_SCSI_CONSTANTS=y impact by 8k On 64 bit, struct error_info has 6 bytes of padding, which amounts to over 4k of wasted space in the additional[] array. We could easily get rid of that by instead using separate arrays for the codes and the pointers. However, we can do even better than that and save an additional 6 bytes per entry: In the table, just store the sizeof() the corresponding string literal. The cumulative sum of these is then the appropriate offset into additional_text, which is built from the concatenation (with '\0's inbetween) of the strings. $ scripts/bloat-o-meter /tmp/vmlinux vmlinux add/remove: 0/0 grow/shrink: 1/1 up/down: 24/-8488 (-8464) function old new delta scsi_extd_sense_format 136 160 +24 additional 11312 2824 -8488 The Kconfig help text used to say that CONFIG_SCSI_CONSTANTS=y costs around 75 KB, but that was a little exaggerated. The actual number was closer to 44K, and 36K with this patch. Signed-off-by: Rasmus Villemoes Reviewed-by: Hannes Reinecke Tested-by: Douglas Gilbert Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 4 ++-- drivers/scsi/constants.c | 26 +++++++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e80768f8e579..47611bda633f 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -202,12 +202,12 @@ config SCSI_ENCLOSURE certain enclosure conditions to be reported and is not required. config SCSI_CONSTANTS - bool "Verbose SCSI error reporting (kernel size +=75K)" + bool "Verbose SCSI error reporting (kernel size += 36K)" depends on SCSI help The error messages regarding your SCSI hardware will be easier to understand if you say Y here; it will enlarge your kernel by about - 75 KB. If in doubt, say Y. + 36 KB. If in doubt, say Y. config SCSI_LOGGING bool "SCSI logging facility" diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 6e813eec4f8d..83458f7a2824 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -292,17 +292,30 @@ bool scsi_opcode_sa_name(int opcode, int service_action, struct error_info { unsigned short code12; /* 0x0302 looks better than 0x03,0x02 */ - const char * text; + unsigned short size; }; +/* + * There are 700+ entries in this table. To save space, we don't store + * (code, pointer) pairs, which would make sizeof(struct + * error_info)==16 on 64 bits. Rather, the second element just stores + * the size (including \0) of the corresponding string, and we use the + * sum of these to get the appropriate offset into additional_text + * defined below. This approach saves 12 bytes per entry. + */ static const struct error_info additional[] = { -#define SENSE_CODE(c, s) {c, s}, +#define SENSE_CODE(c, s) {c, sizeof(s)}, #include "sense_codes.h" #undef SENSE_CODE - {0, NULL} }; +static const char *additional_text = +#define SENSE_CODE(c, s) s "\0" +#include "sense_codes.h" +#undef SENSE_CODE + ; + struct error_info2 { unsigned char code1, code2_min, code2_max; const char * str; @@ -364,11 +377,14 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt) { int i; unsigned short code = ((asc << 8) | ascq); + unsigned offset = 0; *fmt = NULL; - for (i = 0; additional[i].text; i++) + for (i = 0; i < ARRAY_SIZE(additional); i++) { if (additional[i].code12 == code) - return additional[i].text; + return additional_text + offset; + offset += additional[i].size; + } for (i = 0; additional2[i].fmt; i++) { if (additional2[i].code1 == asc && ascq >= additional2[i].code2_min && -- GitLab From 9d376402c80cfe2356d84577d366ca790e576bd9 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:10 +1100 Subject: [PATCH 2057/9938] g_ncr5380: Remove CONFIG_SCSI_GENERIC_NCR53C400 This change brings a number of improvements: fewer macros, better test coverage, simpler code and sane Kconfig options. The downside is a small chance of incompatibility (which seems unavoidable). CONFIG_SCSI_GENERIC_NCR53C400 exists to enable or inhibit pseudo DMA transfers when the driver is used with 53C400-compatible cards. Thanks to Ondrej Zary's patches, PDMA now works which means it can be enabled unconditionally. Due to bad design, CONFIG_SCSI_GENERIC_NCR53C400 ties together unrelated functionality as it sets both PSEUDO_DMA and BIOSPARAM macros. This patch effectively enables PSEUDO_DMA and disables BIOSPARAM. The defconfigs and the Kconfig default leave CONFIG_SCSI_GENERIC_NCR53C400 undefined. Red Hat 9 and CentOS 2.1 were the same. This leaves both PSEUDO_DMA and BIOSPARAM disabled. The effect of this patch should be better performance from enabling PSEUDO_DMA. On the other hand, Debian 4 and SLES 10 had CONFIG_SCSI_GENERIC_NCR53C400 enabled, so both PSEUDO_DMA and BIOSPARAM were enabled. This patch might affect configurations like this by disabling BIOSPARAM. My best guess is that this could be a problem only in the vanishingly rare case that 1) the CHS values stored in the boot device partition table are wrong and 2) a 5380 card is in use (because PDMA on 53C400 used to be broken). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 11 ------ drivers/scsi/g_NCR5380.c | 75 ++++++++++++---------------------------- drivers/scsi/g_NCR5380.h | 16 ++------- 3 files changed, 25 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 47611bda633f..0950567e6269 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -813,17 +813,6 @@ config SCSI_GENERIC_NCR5380_MMIO To compile this driver as a module, choose M here: the module will be called g_NCR5380_mmio. -config SCSI_GENERIC_NCR53C400 - bool "Enable NCR53c400 extensions" - depends on SCSI_GENERIC_NCR5380 - help - This enables certain optimizations for the NCR53c400 SCSI cards. - You might as well try it out. Note that this driver will only probe - for the Trantor T130B in its default configuration; you might have - to pass a command line option to the kernel at boot time if it does - not detect your card. See the file - for details. - config SCSI_IPS tristate "IBM ServeRAID support" depends on PCI && SCSI diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 90091e693020..85ebe109d15d 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -57,10 +57,7 @@ */ #define AUTOPROBE_IRQ - -#ifdef CONFIG_SCSI_GENERIC_NCR53C400 #define PSEUDO_DMA -#endif #include #include @@ -270,7 +267,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifndef SCSI_G_NCR5380_MEM int i; int port_idx = -1; - unsigned long region_size = 16; + unsigned long region_size; #endif static unsigned int __initdata ncr_53c400a_ports[] = { 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 @@ -290,6 +287,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifdef SCSI_G_NCR5380_MEM unsigned long base; void __iomem *iomem; + resource_size_t iomem_size; #endif if (ncr_irq) @@ -353,9 +351,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) flags = FLAG_NO_PSEUDO_DMA; break; case BOARD_NCR53C400: -#ifdef PSEUDO_DMA flags = FLAG_NO_DMA_FIXUP; -#endif break; case BOARD_NCR53C400A: flags = FLAG_NO_DMA_FIXUP; @@ -381,20 +377,22 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) /* Disable the adapter and look for a free io port */ magic_configure(-1, 0, magic); + region_size = 16; + if (overrides[current_override].NCR5380_map_name != PORT_AUTO) for (i = 0; ports[i]; i++) { - if (!request_region(ports[i], 16, "ncr53c80")) + if (!request_region(ports[i], region_size, "ncr53c80")) continue; if (overrides[current_override].NCR5380_map_name == ports[i]) break; - release_region(ports[i], 16); + release_region(ports[i], region_size); } else for (i = 0; ports[i]; i++) { - if (!request_region(ports[i], 16, "ncr53c80")) + if (!request_region(ports[i], region_size, "ncr53c80")) continue; if (inb(ports[i]) == 0xff) break; - release_region(ports[i], 16); + release_region(ports[i], region_size); } if (ports[i]) { /* At this point we have our region reserved */ @@ -410,17 +408,19 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) else { /* Not a 53C400A style setup - just grab */ - if(!(request_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380"))) + region_size = 8; + if (!request_region(overrides[current_override].NCR5380_map_name, + region_size, "ncr5380")) continue; - region_size = NCR5380_region_size; } #else base = overrides[current_override].NCR5380_map_name; - if (!request_mem_region(base, NCR5380_region_size, "ncr5380")) + iomem_size = NCR53C400_region_size; + if (!request_mem_region(base, iomem_size, "ncr5380")) continue; - iomem = ioremap(base, NCR5380_region_size); + iomem = ioremap(base, iomem_size); if (!iomem) { - release_mem_region(base, NCR5380_region_size); + release_mem_region(base, iomem_size); continue; } #endif @@ -458,6 +458,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #else instance->base = overrides[current_override].NCR5380_map_name; hostdata->iomem = iomem; + hostdata->iomem_size = iomem_size; switch (overrides[current_override].board) { case BOARD_NCR53C400: hostdata->c400_ctl_status = 0x100; @@ -524,7 +525,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) release_region(overrides[current_override].NCR5380_map_name, region_size); #else iounmap(iomem); - release_mem_region(base, NCR5380_region_size); + release_mem_region(base, iomem_size); #endif return count; } @@ -546,42 +547,15 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) #ifndef SCSI_G_NCR5380_MEM release_region(instance->io_port, instance->n_io_port); #else - iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem); - release_mem_region(instance->base, NCR5380_region_size); -#endif - return 0; -} - -#ifdef BIOSPARAM -/** - * generic_NCR5380_biosparam - * @disk: disk to compute geometry for - * @dev: device identifier for this disk - * @ip: sizes to fill in - * - * Generates a BIOS / DOS compatible H-C-S mapping for the specified - * device / size. - * - * XXX Most SCSI boards use this mapping, I could be incorrect. Someone - * using hard disks on a trantor should verify that this mapping - * corresponds to that used by the BIOS / ASPI driver by running the linux - * fdisk program and matching the H_C_S coordinates to what DOS uses. - * - * Locks: none - */ + { + struct NCR5380_hostdata *hostdata = shost_priv(instance); -static int -generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *ip) -{ - ip[0] = 64; - ip[1] = 32; - ip[2] = capacity >> 11; + iounmap(hostdata->iomem); + release_mem_region(instance->base, hostdata->iomem_size); + } +#endif return 0; } -#endif - -#ifdef PSEUDO_DMA /** * NCR5380_pread - pseudo DMA read @@ -756,8 +730,6 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) return transfersize; } -#endif /* PSEUDO_DMA */ - /* * Include the NCR5380 core code that we build our driver around */ @@ -773,7 +745,6 @@ static struct scsi_host_template driver_template = { .queuecommand = generic_NCR5380_queue_command, .eh_abort_handler = generic_NCR5380_abort, .eh_bus_reset_handler = generic_NCR5380_bus_reset, - .bios_param = NCR5380_BIOSPARAM, .can_queue = 16, .this_id = 7, .sg_tablesize = SG_ALL, diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 6f3d2ac4f185..1ca3743a887e 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -14,13 +14,6 @@ #ifndef GENERIC_NCR5380_H #define GENERIC_NCR5380_H -#ifdef CONFIG_SCSI_GENERIC_NCR53C400 -#define BIOSPARAM -#define NCR5380_BIOSPARAM generic_NCR5380_biosparam -#else -#define NCR5380_BIOSPARAM NULL -#endif - #define __STRVAL(x) #x #define STRVAL(x) __STRVAL(x) @@ -30,12 +23,6 @@ #define NCR5380_map_type int #define NCR5380_map_name port -#ifdef CONFIG_SCSI_GENERIC_NCR53C400 -#define NCR5380_region_size 16 -#else -#define NCR5380_region_size 8 -#endif - #define NCR5380_read(reg) \ inb(instance->io_port + (reg)) #define NCR5380_write(reg, value) \ @@ -55,7 +42,7 @@ #define NCR5380_map_name base #define NCR53C400_mem_base 0x3880 #define NCR53C400_host_buffer 0x3900 -#define NCR5380_region_size 0x3a00 +#define NCR53C400_region_size 0x3a00 #define NCR5380_read(reg) \ readb(((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ @@ -66,6 +53,7 @@ #define NCR5380_implementation_fields \ void __iomem *iomem; \ + resource_size_t iomem_size; \ int c400_ctl_status; \ int c400_blk_cnt; \ int c400_host_buf; -- GitLab From 7e9ec8d9cc18a85e8a4c28aef9136867b46aba42 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:11 +1100 Subject: [PATCH 2058/9938] ncr5380: Remove FLAG_NO_PSEUDO_DMA where possible Drivers that define PSEUDO_DMA also define NCR5380_dma_xfer_len. The core driver must call NCR5380_dma_xfer_len which means FLAG_NO_PSEUDO_DMA can be eradicated from the core driver. dmx3191d doesn't define PSEUDO_DMA and has no use for FLAG_NO_PSEUDO_DMA, so remove it there also. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 3 +-- drivers/scsi/dmx3191d.c | 2 +- drivers/scsi/g_NCR5380.c | 7 ++++++- drivers/scsi/g_NCR5380.h | 2 +- drivers/scsi/mac_scsi.c | 15 ++++++++++++++- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 3eff2a69fe08..98840bed05cb 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1833,8 +1833,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) transfersize = 0; - if (!cmd->device->borken && - !(hostdata->flags & FLAG_NO_PSEUDO_DMA)) + if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); if (transfersize) { diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 6c14e68b9e1a..e9e96af96104 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -93,7 +93,7 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, */ shost->irq = NO_IRQ; - error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA); + error = NCR5380_init(shost, 0); if (error) goto out_host_put; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 85ebe109d15d..b8fc26d9231d 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -712,10 +712,15 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, return 0; } -static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) +static int generic_NCR5380_dma_xfer_len(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); int transfersize = cmd->transfersize; + if (hostdata->flags & FLAG_NO_PSEUDO_DMA) + return 0; + /* Limit transfers to 32K, for xx400 & xx406 * pseudoDMA that transfers in 128 bytes blocks. */ diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 1ca3743a887e..3fb0d8529429 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -61,7 +61,7 @@ #endif #define NCR5380_dma_xfer_len(instance, cmd, phase) \ - generic_NCR5380_dma_xfer_len(cmd) + generic_NCR5380_dma_xfer_len(instance, cmd) #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index bb2381314a2b..a8f5433b515e 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -37,7 +37,9 @@ #define NCR5380_pread macscsi_pread #define NCR5380_pwrite macscsi_pwrite -#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) + +#define NCR5380_dma_xfer_len(instance, cmd, phase) \ + macscsi_dma_xfer_len(instance, cmd) #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command @@ -303,6 +305,17 @@ static int macscsi_pwrite(struct Scsi_Host *instance, } #endif +static int macscsi_dma_xfer_len(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + if (hostdata->flags & FLAG_NO_PSEUDO_DMA) + return 0; + + return cmd->transfersize; +} + #include "NCR5380.c" #define DRV_MODULE_NAME "mac_scsi" -- GitLab From e4dec6806aceca768b74c1c6402e6d31ecf3c960 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:12 +1100 Subject: [PATCH 2059/9938] ncr5380: Remove REAL_DMA and REAL_DMA_POLL macros For the NCR5380.c core driver, these macros are never used. If REAL_DMA were to be defined, compilation would fail. For the atari_NCR5380.c core driver, REAL_DMA is always defined. Hence these macros are pointless. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 218 ++--------------------------------- drivers/scsi/NCR5380.h | 112 ------------------ drivers/scsi/atari_NCR5380.c | 62 ++-------- drivers/scsi/atari_scsi.c | 32 +---- drivers/scsi/sun3_scsi.c | 13 +-- 5 files changed, 22 insertions(+), 415 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 98840bed05cb..826b63d1aa84 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -35,18 +35,10 @@ * code so that everything does the same thing that's done at the * end of a pseudo-DMA read operation. * - * 2. Fix REAL_DMA (interrupt driven, polled works fine) - - * basically, transfer size needs to be reduced by one - * and the last byte read as is done with PSEUDO_DMA. - * * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) */ -#ifndef notyet -#undef REAL_DMA -#endif - #ifdef BOARD_REQUIRES_NO_DELAY #define io_recovery_delay(x) #else @@ -131,12 +123,6 @@ * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * - * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. - * - * REAL_DMA_POLL - if defined, REAL DMA is used but the driver doesn't - * rely on phase mismatch and EOP interrupts to determine end - * of phase. - * * These macros MUST be defined : * * NCR5380_read(register) - read from the specified register @@ -147,15 +133,9 @@ * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented - * REAL functions : - * NCR5380_REAL_DMA should be defined if real DMA is to be used. * Note that the DMA setup functions should return the number of bytes * that they were able to program the controller for. * - * Also note that generic i386/PC versions of these macros are - * available as NCR5380_i386_dma_write_setup, - * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. - * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize * NCR5380_dma_residual(instance); - residual count @@ -486,12 +466,6 @@ static void prepare_info(struct Scsi_Host *instance) #ifdef DIFFERENTIAL "DIFFERENTIAL " #endif -#ifdef REAL_DMA - "REAL_DMA " -#endif -#ifdef REAL_DMA_POLL - "REAL_DMA_POLL " -#endif #ifdef PARITY "PARITY " #endif @@ -551,9 +525,8 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->id_higher_mask |= i; for (i = 0; i < 8; ++i) hostdata->busy[i] = 0; -#ifdef REAL_DMA - hostdata->dmalen = 0; -#endif + hostdata->dma_len = 0; + spin_lock_init(&hostdata->lock); hostdata->connected = NULL; hostdata->sensing = NULL; @@ -850,11 +823,7 @@ static void NCR5380_main(struct work_struct *work) requeue_cmd(instance, cmd); } } - if (hostdata->connected -#ifdef REAL_DMA - && !hostdata->dmalen -#endif - ) { + if (hostdata->connected && !hostdata->dma_len) { dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); NCR5380_information_transfer(instance); done = 0; @@ -919,34 +888,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", irq, basr, sr, mr); -#if defined(REAL_DMA) - if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { - /* Probably End of DMA, Phase Mismatch or Loss of BSY. - * We ack IRQ after clearing Mode Register. Workarounds - * for End of DMA errata need to happen in DMA Mode. - */ - - dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); - - int transferred; - - if (!hostdata->connected) - panic("scsi%d : DMA interrupt with no connected cmd\n", - instance->hostno); - - transferred = hostdata->dmalen - NCR5380_dma_residual(instance); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - hostdata->dmalen = 0; - - /* FIXME: we need to poll briefly then defer a workqueue task ! */ - NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2 * HZ); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else -#endif /* REAL_DMA */ if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { /* Probably reselected */ @@ -1495,7 +1436,7 @@ static int do_abort(struct Scsi_Host *instance) return -1; } -#if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL) +#if defined(PSEUDO_DMA) /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) @@ -1525,34 +1466,14 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, register unsigned char *d = *data; unsigned char tmp; int foo; -#if defined(REAL_DMA_POLL) - int cnt, toPIO; - unsigned char saved_data = 0, overrun = 0, residue; -#endif if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; return -1; } -#if defined(REAL_DMA) || defined(REAL_DMA_POLL) - if (p & SR_IO) { - if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) - c -= 2; - } - hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c); - - dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", - (p & SR_IO) ? "receive" : "send", c, *data); -#endif NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); -#ifdef REAL_DMA - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); -#elif defined(REAL_DMA_POLL) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); -#else /* * Note : on my sample board, watch-dog timeouts occurred when interrupts * were not disabled for the duration of a single DMA transfer, from @@ -1564,7 +1485,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, MR_ENABLE_EOP_INTR); else NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); -#endif /* def REAL_DMA */ dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); @@ -1584,14 +1504,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, io_recovery_delay(1); } -#if defined(REAL_DMA_POLL) - do { - tmp = NCR5380_read(BUS_AND_STATUS_REG); - } while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | BASR_END_DMA_TRANSFER))); - /* - * At this point, either we've completed DMA, or we have a phase mismatch, - * or we've unexpectedly lost BUSY (which is a real error). + * A note regarding the DMA errata workarounds for early NMOS silicon. * * For DMA sends, we want to wait until the last byte has been * transferred out over the bus before we turn off DMA mode. Alas, there @@ -1618,79 +1532,18 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * properly, or the target switches to MESSAGE IN phase to signal a * disconnection (either operation bringing the DMA to a clean halt). * However, in order to handle scatter-receive, we must work around the - * problem. The chosen fix is to DMA N-2 bytes, then check for the + * problem. The chosen fix is to DMA fewer bytes, then check for the * condition before taking the NCR5380 out of DMA mode. One or two extra * bytes are transferred via PIO as necessary to fill out the original * request. */ - if (p & SR_IO) { - if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) { - udelay(10); - if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == - (BASR_PHASE_MATCH | BASR_ACK)) { - saved_data = NCR5380_read(INPUT_DATA_REGISTER); - overrun = 1; - } - } - } else { - int limit = 100; - while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || (NCR5380_read(STATUS_REG) & SR_REQ)) { - if (!(tmp & BASR_PHASE_MATCH)) - break; - if (--limit < 0) - break; - } - } - - dsprintk(NDEBUG_DMA, "polled DMA transfer complete, basr 0x%02x, sr 0x%02x\n", - tmp, NCR5380_read(STATUS_REG)); - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - residue = NCR5380_dma_residual(instance); - c -= residue; - *count -= c; - *data += c; - *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; - - if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS) && - *phase == p && (p & SR_IO) && residue == 0) { - if (overrun) { - dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n"); - **data = saved_data; - *data += 1; - *count -= 1; - cnt = toPIO = 1; - } else { - printk("No overrun??\n"); - cnt = toPIO = 2; - } - dprintk(NDEBUG_DMA, "Doing %d-byte PIO to 0x%X\n", cnt, *data); - NCR5380_transfer_pio(instance, phase, &cnt, data); - *count -= toPIO - cnt; - } - - dprintk(NDEBUG_DMA, "Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count)); - return 0; - -#elif defined(REAL_DMA) - return 0; -#else /* defined(REAL_DMA_POLL) */ if (p & SR_IO) { foo = NCR5380_pread(instance, d, hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1); if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { /* - * We can't disable DMA mode after successfully transferring - * what we plan to be the last byte, since that would open up - * a race condition where if the target asserted REQ before - * we got the DMA mode reset, the NCR5380 would have latched - * an additional byte into the INPUT DATA register and we'd - * have dropped it. - * - * The workaround was to transfer one fewer bytes than we + * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for * the chip to latch the last byte, read it, and then disable * pseudo-DMA mode. @@ -1738,9 +1591,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, *count = 0; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; return foo; -#endif /* def REAL_DMA */ } -#endif /* defined(REAL_DMA) | defined(PSEUDO_DMA) */ +#endif /* PSEUDO_DMA */ /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) @@ -1831,7 +1683,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * in an unconditional loop. */ -#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) +#if defined(PSEUDO_DMA) transfersize = 0; if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); @@ -1855,7 +1707,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } else cmd->SCp.this_residual -= transfersize - len; } else -#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ +#endif /* PSEUDO_DMA */ { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. @@ -2202,52 +2054,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) scmd_id(tmp), tmp->device->lun, tmp->tag); } -/* - * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) - * - * Purpose : called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). - * - * Inputs : instance - this instance of the NCR5380. - * - * Returns : pointer to the scsi_cmnd structure for which the I_T_L - * nexus has been reestablished, on failure NULL is returned. - */ - -#ifdef REAL_DMA -static void NCR5380_dma_complete(NCR5380_instance * instance) { - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int transferred; - - /* - * XXX this might not be right. - * - * Wait for final byte to transfer, ie wait for ACK to go false. - * - * We should use the Last Byte Sent bit, unfortunately this is - * not available on the 5380/5381 (only the various CMOS chips) - * - * FIXME: timeout, and need to handle long timeout/irq case - */ - - NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_ACK, 0, 5*HZ); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - /* - * The only places we should see a phase mismatch and have to send - * data from the same set of pointers will be the data transfer - * phases. So, residual, requested length are only important here. - */ - - if (!(hostdata->connected->SCp.phase & SR_CD)) { - transferred = instance->dmalen - NCR5380_dma_residual(); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - } -} -#endif /* def REAL_DMA */ - /** * list_find_cmd - test for presence of a command in a linked list * @haystack: list of commands @@ -2359,9 +2165,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (hostdata->connected == cmd) { dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); hostdata->connected = NULL; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif if (do_abort(instance)) { set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); @@ -2464,9 +2268,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) for (i = 0; i < 8; ++i) hostdata->busy[i] = 0; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif queue_work(hostdata->work_q, &hostdata->main_task); spin_unlock_irqrestore(&hostdata->lock, flags); diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index a79288682a74..0b03ba25bd66 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -239,9 +239,7 @@ struct NCR5380_hostdata { struct Scsi_Host *host; /* Host backpointer */ unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ unsigned char busy[8]; /* index = target, bit = lun */ -#if defined(REAL_DMA) || defined(REAL_DMA_POLL) int dma_len; /* requested length of DMA */ -#endif unsigned char last_message; /* last message OUT */ struct scsi_cmnd *connected; /* currently connected cmnd */ struct scsi_cmnd *selecting; /* cmnd to be connected */ @@ -319,118 +317,8 @@ static void NCR5380_main(struct work_struct *work); static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); -#if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL) static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -#endif static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -#if (defined(REAL_DMA) || defined(REAL_DMA_POLL)) - -#if defined(i386) || defined(__alpha__) - -/** - * NCR5380_pc_dma_setup - setup ISA DMA - * @instance: adapter to set up - * @ptr: block to transfer (virtual address) - * @count: number of bytes to transfer - * @mode: DMA controller mode to use - * - * Program the DMA controller ready to perform an ISA DMA transfer - * on this chip. - * - * Locks: takes and releases the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_setup(struct Scsi_Host *instance, unsigned char *ptr, unsigned int count, unsigned char mode) -{ - unsigned limit; - unsigned long bus_addr = virt_to_bus(ptr); - unsigned long flags; - - if (instance->dma_channel <= 3) { - if (count > 65536) - count = 65536; - limit = 65536 - (bus_addr & 0xFFFF); - } else { - if (count > 65536 * 2) - count = 65536 * 2; - limit = 65536 * 2 - (bus_addr & 0x1FFFF); - } - - if (count > limit) - count = limit; - - if ((count & 1) || (bus_addr & 1)) - panic("scsi%d : attempted unaligned DMA transfer\n", instance->host_no); - - flags=claim_dma_lock(); - disable_dma(instance->dma_channel); - clear_dma_ff(instance->dma_channel); - set_dma_addr(instance->dma_channel, bus_addr); - set_dma_count(instance->dma_channel, count); - set_dma_mode(instance->dma_channel, mode); - enable_dma(instance->dma_channel); - release_dma_lock(flags); - - return count; -} - -/** - * NCR5380_pc_dma_write_setup - setup ISA DMA write - * @instance: adapter to set up - * @ptr: block to transfer (virtual address) - * @count: number of bytes to transfer - * - * Program the DMA controller ready to perform an ISA DMA write to the - * SCSI controller. - * - * Locks: called routines take and release the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_write_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count) -{ - return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_WRITE); -} - -/** - * NCR5380_pc_dma_read_setup - setup ISA DMA read - * @instance: adapter to set up - * @ptr: block to transfer (virtual address) - * @count: number of bytes to transfer - * - * Program the DMA controller ready to perform an ISA DMA read from the - * SCSI controller. - * - * Locks: called routines take and release the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_read_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count) -{ - return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_READ); -} - -/** - * NCR5380_pc_dma_residual - return bytes left - * @instance: adapter - * - * Reports the number of bytes left over after the DMA was terminated. - * - * Locks: takes and releases the ISA DMA lock. - */ - -static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance) -{ - unsigned long flags; - int tmp; - - flags = claim_dma_lock(); - clear_dma_ff(instance->dma_channel); - tmp = get_dma_residue(instance->dma_channel); - release_dma_lock(flags); - - return tmp; -} -#endif /* defined(i386) || defined(__alpha__) */ -#endif /* defined(REAL_DMA) */ #endif /* __KERNEL__ */ #endif /* NCR5380_H */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 389825ba5d96..c669098e34e1 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -112,15 +112,9 @@ * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented - * REAL functions : - * NCR5380_REAL_DMA should be defined if real DMA is to be used. * Note that the DMA setup functions should return the number of bytes * that they were able to program the controller for. * - * Also note that generic i386/PC versions of these macros are - * available as NCR5380_i386_dma_write_setup, - * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. - * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize * NCR5380_dma_residual(instance); - residual count @@ -586,9 +580,6 @@ static void prepare_info(struct Scsi_Host *instance) #ifdef DIFFERENTIAL "DIFFERENTIAL " #endif -#ifdef REAL_DMA - "REAL_DMA " -#endif #ifdef PARITY "PARITY " #endif @@ -629,9 +620,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) #ifdef SUPPORT_TAGS init_tags(hostdata); #endif -#if defined (REAL_DMA) hostdata->dma_len = 0; -#endif + spin_lock_init(&hostdata->lock); hostdata->connected = NULL; hostdata->sensing = NULL; @@ -974,11 +964,7 @@ static void NCR5380_main(struct work_struct *work) #endif } } - if (hostdata->connected -#ifdef REAL_DMA - && !hostdata->dma_len -#endif - ) { + if (hostdata->connected && !hostdata->dma_len) { dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); NCR5380_information_transfer(instance); done = 0; @@ -990,7 +976,6 @@ static void NCR5380_main(struct work_struct *work) } -#ifdef REAL_DMA /* * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) * @@ -1071,7 +1056,6 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } } } -#endif /* REAL_DMA */ /** @@ -1126,7 +1110,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", irq, basr, sr, mr); -#if defined(REAL_DMA) if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { /* Probably End of DMA, Phase Mismatch or Loss of BSY. * We ack IRQ after clearing Mode Register. Workarounds @@ -1142,9 +1125,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) NCR5380_write(MODE_REG, MR_BASE); NCR5380_read(RESET_PARITY_INTERRUPT_REG); } - } else -#endif /* REAL_DMA */ - if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && + } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { /* Probably reselected */ NCR5380_write(SELECT_ENABLE_REG, 0); @@ -1710,7 +1691,7 @@ static int do_abort(struct Scsi_Host *instance) return -1; } -#if defined(REAL_DMA) + /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) @@ -1819,7 +1800,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, return 0; } -#endif /* defined(REAL_DMA) */ /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) @@ -1866,7 +1846,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } #if defined(CONFIG_SUN3) if (phase == PHASE_CMDOUT) { -#if defined(REAL_DMA) void *d; unsigned long count; @@ -1885,7 +1864,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sun3_dma_setup_done = cmd; } } -#endif #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; #endif @@ -1943,12 +1921,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * in an unconditional loop. */ - /* ++roman: I suggest, this should be - * #if def(REAL_DMA) - * instead of leaving REAL_DMA out. - */ - -#if defined(REAL_DMA) #if !defined(CONFIG_SUN3) transfersize = 0; if (!cmd->device->borken) @@ -1972,21 +1944,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) do_abort(instance); cmd->result = DID_ERROR << 16; /* XXX - need to source or sink data here, as appropriate */ - } else { -#ifdef REAL_DMA - /* ++roman: When using real DMA, - * information_transfer() should return after - * starting DMA since it has nothing more to - * do. - */ + } else return; -#else - cmd->SCp.this_residual -= transfersize - len; -#endif - } - } else -#endif /* defined(REAL_DMA) */ - { + } else { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. */ @@ -1997,7 +1957,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) (unsigned char **)&cmd->SCp.ptr); cmd->SCp.this_residual -= transfersize - len; } -#if defined(CONFIG_SUN3) && defined(REAL_DMA) +#if defined(CONFIG_SUN3) /* if we had intended to dma that command clear it */ if (sun3_dma_setup_done == cmd) sun3_dma_setup_done = NULL; @@ -2305,7 +2265,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } -#if defined(CONFIG_SUN3) && defined(REAL_DMA) +#if defined(CONFIG_SUN3) /* acknowledge toggle to MSGIN */ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN)); @@ -2392,7 +2352,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } -#if defined(CONFIG_SUN3) && defined(REAL_DMA) +#if defined(CONFIG_SUN3) /* engage dma setup for the command we just saw */ { void *d; @@ -2555,9 +2515,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (hostdata->connected == cmd) { dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); hostdata->connected = NULL; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif if (do_abort(instance)) { set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); @@ -2664,9 +2622,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) #endif for (i = 0; i < 8; ++i) hostdata->busy[i] = 0; -#ifdef REAL_DMA hostdata->dma_len = 0; -#endif queue_work(hostdata->work_q, &hostdata->main_task); maybe_release_dma_irq(instance); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 78d1b2963f2c..c68e895e971f 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -85,7 +85,6 @@ /* Definitions for the core NCR5380 driver. */ -#define REAL_DMA #define SUPPORT_TAGS #define MAX_TAGS 32 #define DMA_MIN_SIZE 32 @@ -159,14 +158,11 @@ static inline unsigned long SCSI_DMA_GETADR(void) return adr; } -#ifdef REAL_DMA static void atari_scsi_fetch_restbytes(void); -#endif static unsigned char (*atari_scsi_reg_read)(unsigned char reg); static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value); -#ifdef REAL_DMA static unsigned long atari_dma_residual, atari_dma_startaddr; static short atari_dma_active; /* pointer to the dribble buffer */ @@ -185,7 +181,6 @@ static char *atari_dma_orig_addr; /* mask for address bits that can't be used with the ST-DMA */ static unsigned long atari_dma_stram_mask; #define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0) -#endif static int setup_can_queue = -1; module_param(setup_can_queue, int, 0); @@ -201,8 +196,6 @@ static int setup_toshiba_delay = -1; module_param(setup_toshiba_delay, int, 0); -#if defined(REAL_DMA) - static int scsi_dma_is_ignored_buserr(unsigned char dma_stat) { int i; @@ -255,12 +248,9 @@ static void scsi_dma_buserr(int irq, void *dummy) } #endif -#endif - static irqreturn_t scsi_tt_intr(int irq, void *dev) { -#ifdef REAL_DMA struct Scsi_Host *instance = dev; struct NCR5380_hostdata *hostdata = shost_priv(instance); int dma_stat; @@ -342,8 +332,6 @@ static irqreturn_t scsi_tt_intr(int irq, void *dev) tt_scsi_dma.dma_ctrl = 0; } -#endif /* REAL_DMA */ - NCR5380_intr(irq, dev); return IRQ_HANDLED; @@ -352,7 +340,6 @@ static irqreturn_t scsi_tt_intr(int irq, void *dev) static irqreturn_t scsi_falcon_intr(int irq, void *dev) { -#ifdef REAL_DMA struct Scsi_Host *instance = dev; struct NCR5380_hostdata *hostdata = shost_priv(instance); int dma_stat; @@ -405,15 +392,12 @@ static irqreturn_t scsi_falcon_intr(int irq, void *dev) atari_dma_orig_addr = NULL; } -#endif /* REAL_DMA */ - NCR5380_intr(irq, dev); return IRQ_HANDLED; } -#ifdef REAL_DMA static void atari_scsi_fetch_restbytes(void) { int nr; @@ -436,7 +420,6 @@ static void atari_scsi_fetch_restbytes(void) *dst++ = *src++; } } -#endif /* REAL_DMA */ /* This function releases the lock on the DMA chip if there is no @@ -508,8 +491,6 @@ __setup("atascsi=", atari_scsi_setup); #endif /* !MODULE */ -#if defined(REAL_DMA) - static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data, unsigned long count, int dir) @@ -703,9 +684,6 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len, } -#endif /* REAL_DMA */ - - /* NCR5380 register access functions * * There are separate functions for TT and Falcon, because the access @@ -745,7 +723,6 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) local_irq_save(flags); -#ifdef REAL_DMA /* Abort a maybe active DMA transfer */ if (IS_A_TT()) { tt_scsi_dma.dma_ctrl = 0; @@ -754,7 +731,6 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) atari_dma_active = 0; atari_dma_orig_addr = NULL; } -#endif rv = NCR5380_bus_reset(cmd); @@ -850,8 +826,6 @@ static int __init atari_scsi_probe(struct platform_device *pdev) } } - -#ifdef REAL_DMA /* If running on a Falcon and if there's TT-Ram (i.e., more than one * memory block, since there's always ST-Ram in a Falcon), then * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers @@ -867,7 +841,6 @@ static int __init atari_scsi_probe(struct platform_device *pdev) atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); atari_dma_orig_addr = 0; } -#endif instance = scsi_host_alloc(&atari_scsi_template, sizeof(struct NCR5380_hostdata)); @@ -897,7 +870,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev) goto fail_irq; } tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */ -#ifdef REAL_DMA + tt_scsi_dma.dma_ctrl = 0; atari_dma_residual = 0; @@ -919,17 +892,14 @@ static int __init atari_scsi_probe(struct platform_device *pdev) hostdata->read_overruns = 4; } -#endif } else { /* Nothing to do for the interrupt: the ST-DMA is initialized * already. */ -#ifdef REAL_DMA atari_dma_residual = 0; atari_dma_active = 0; atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000); -#endif } NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index b9de487bbd31..5551b1623ed6 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -38,7 +38,6 @@ /* Definitions for the core NCR5380 driver. */ -#define REAL_DMA /* #define SUPPORT_TAGS */ /* minimum number of bytes to do dma on */ #define DMA_MIN_SIZE 129 @@ -527,15 +526,9 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) error = request_irq(instance->irq, scsi_sun3_intr, 0, "NCR5380", instance); if (error) { -#ifdef REAL_DMA pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n", instance->host_no, instance->irq); goto fail_irq; -#else - pr_warn(PFX "scsi%d: IRQ %d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = NO_IRQ; -#endif } dregs->csr = 0; @@ -565,8 +558,7 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) return 0; fail_host: - if (instance->irq != NO_IRQ) - free_irq(instance->irq, instance); + free_irq(instance->irq, instance); fail_irq: NCR5380_exit(instance); fail_init: @@ -583,8 +575,7 @@ static int __exit sun3_scsi_remove(struct platform_device *pdev) struct Scsi_Host *instance = platform_get_drvdata(pdev); scsi_remove_host(instance); - if (instance->irq != NO_IRQ) - free_irq(instance->irq, instance); + free_irq(instance->irq, instance); NCR5380_exit(instance); scsi_host_put(instance); if (udc_regs) -- GitLab From e63449c43a58fc185ff35ace6a842817f57ec6c8 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:13 +1100 Subject: [PATCH 2060/9938] atari_NCR5380: Remove DMA_MIN_SIZE macro Only the atari_scsi and sun3_scsi drivers define DMA_MIN_SIZE. Both drivers also define NCR5380_dma_xfer_len, which means DMA_MIN_SIZE can be removed from the core driver. This removes another discrepancy between the two core drivers. Signed-off-by: Finn Thain Tested-by: Michael Schmitz Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_NCR5380.c | 16 ++++++++-------- drivers/scsi/atari_scsi.c | 6 +++++- drivers/scsi/sun3_scsi.c | 19 +++++++++---------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index c669098e34e1..4101d2de4333 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1857,12 +1857,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) d = cmd->SCp.ptr; } /* this command setup for dma yet? */ - if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != cmd)) { - if (cmd->request->cmd_type == REQ_TYPE_FS) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(cmd->request)); - sun3_dma_setup_done = cmd; - } + if (sun3_dma_setup_done != cmd && + sun3scsi_dma_xfer_len(count, cmd) > 0) { + sun3scsi_dma_setup(instance, d, count, + rq_data_dir(cmd->request)); + sun3_dma_setup_done = cmd; } #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; @@ -1927,7 +1926,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #endif transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); - if (transfersize >= DMA_MIN_SIZE) { + if (transfersize > 0) { len = transfersize; cmd->SCp.phase = phase; if (NCR5380_transfer_dma(instance, &phase, @@ -2366,7 +2365,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) d = tmp->SCp.ptr; } /* setup this command for dma if not already */ - if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != tmp)) { + if (sun3_dma_setup_done != tmp && + sun3scsi_dma_xfer_len(count, tmp) > 0) { sun3scsi_dma_setup(instance, d, count, rq_data_dir(tmp->request)); sun3_dma_setup_done = tmp; diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index c68e895e971f..41ddd95cebe6 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -83,11 +83,12 @@ #include +#define DMA_MIN_SIZE 32 + /* Definitions for the core NCR5380 driver. */ #define SUPPORT_TAGS #define MAX_TAGS 32 -#define DMA_MIN_SIZE 32 #define NCR5380_implementation_fields /* none */ @@ -605,6 +606,9 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len, { unsigned long possible_len, limit; + if (wanted_len < DMA_MIN_SIZE) + return 0; + if (IS_A_TT()) /* TT SCSI DMA can transfer arbitrary #bytes */ return wanted_len; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 5551b1623ed6..fd4fad816ad4 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -36,12 +36,12 @@ #include #include "sun3_scsi.h" -/* Definitions for the core NCR5380 driver. */ - -/* #define SUPPORT_TAGS */ /* minimum number of bytes to do dma on */ #define DMA_MIN_SIZE 129 +/* Definitions for the core NCR5380 driver. */ + +/* #define SUPPORT_TAGS */ /* #define MAX_TAGS 32 */ #define NCR5380_implementation_fields /* none */ @@ -61,7 +61,7 @@ #define NCR5380_dma_residual(instance) \ sun3scsi_dma_residual(instance) #define NCR5380_dma_xfer_len(instance, cmd, phase) \ - sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO)) + sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd) #define NCR5380_acquire_dma_irq(instance) (1) #define NCR5380_release_dma_irq(instance) @@ -262,14 +262,13 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) return last_residual; } -static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, - struct scsi_cmnd *cmd, - int write_flag) +static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted_len, + struct scsi_cmnd *cmd) { - if (cmd->request->cmd_type == REQ_TYPE_FS) - return wanted; - else + if (wanted_len < DMA_MIN_SIZE || cmd->request->cmd_type != REQ_TYPE_FS) return 0; + + return wanted_len; } static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data) -- GitLab From 1bb4600245d4d40245dd505ca17528e0b9a9ba8c Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:14 +1100 Subject: [PATCH 2061/9938] ncr5380: Disable the DMA errata workaround flag by default The only chip that needs the workarounds enabled is an early NMOS device. That means that the common case is to disable them. Unfortunately the sense of the flag is such that it has to be set for the common case. Rename the flag so that zero can be used to mean "no errata workarounds needed". This simplifies the code. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 14 +++++++------- drivers/scsi/NCR5380.h | 2 +- drivers/scsi/arm/cumana_1.c | 2 +- drivers/scsi/arm/oak.c | 2 +- drivers/scsi/dtc.c | 2 +- drivers/scsi/g_NCR5380.c | 8 +------- drivers/scsi/pas16.c | 2 +- drivers/scsi/t128.c | 2 +- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 826b63d1aa84..69c73c36b923 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -457,7 +457,7 @@ static void prepare_info(struct Scsi_Host *instance) instance->base, instance->irq, instance->can_queue, instance->cmd_per_lun, instance->sg_tablesize, instance->this_id, - hostdata->flags & FLAG_NO_DMA_FIXUP ? "NO_DMA_FIXUP " : "", + hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", #ifdef AUTOPROBE_IRQ @@ -1480,11 +1480,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * before the setting of DMA mode to after transfer of the last byte. */ - if (hostdata->flags & FLAG_NO_DMA_FIXUP) + if (hostdata->flags & FLAG_DMA_FIXUP) + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); + else NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | MR_ENABLE_EOP_INTR); - else - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); @@ -1540,8 +1540,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, if (p & SR_IO) { foo = NCR5380_pread(instance, d, - hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1); - if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { + hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); + if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for @@ -1571,7 +1571,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, } } else { foo = NCR5380_pwrite(instance, d, c); - if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { + if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 0b03ba25bd66..7b488a082462 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -220,7 +220,7 @@ #define NO_IRQ 0 #endif -#define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */ +#define FLAG_DMA_FIXUP 1 /* Use DMA errata workarounds */ #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ #define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */ diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 221f18c5df93..76b2d3364d9f 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -239,7 +239,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, host->irq = ec->irq; - ret = NCR5380_init(host, 0); + ret = NCR5380_init(host, FLAG_DMA_FIXUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 1fab1d1896b1..8d8426535e6d 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -143,7 +143,7 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) host->irq = NO_IRQ; host->n_io_port = 255; - ret = NCR5380_init(host, 0); + ret = NCR5380_init(host, FLAG_DMA_FIXUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 6c736b071cf4..30919f42759a 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -229,7 +229,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) instance->base = addr; ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; - if (NCR5380_init(instance, FLAG_NO_DMA_FIXUP)) + if (NCR5380_init(instance, 0)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index b8fc26d9231d..aaeb6b6b4b16 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -348,23 +348,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) flags = 0; switch (overrides[current_override].board) { case BOARD_NCR5380: - flags = FLAG_NO_PSEUDO_DMA; - break; - case BOARD_NCR53C400: - flags = FLAG_NO_DMA_FIXUP; + flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP; break; case BOARD_NCR53C400A: - flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; magic = ncr_53c400a_magic; break; case BOARD_HP_C2502: - flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; magic = hp_c2502_magic; break; case BOARD_DTC3181E: - flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; magic = ncr_53c400a_magic; break; diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 512037e27783..7589fea01186 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -377,7 +377,7 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) instance->io_port = io_port; - if (NCR5380_init(instance, 0)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 4615fda60dbd..6cb8bdd2f4e6 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -210,7 +210,7 @@ static int __init t128_detect(struct scsi_host_template *tpnt) instance->base = base; ((struct NCR5380_hostdata *)instance->hostdata)->base = p; - if (NCR5380_init(instance, 0)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); -- GitLab From f825e40b235f4daf1c9017366809d34c7f5c8c7f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:15 +1100 Subject: [PATCH 2062/9938] ncr5380: Remove PSEUDO_DMA macro For those wrapper drivers which only implement Programmed IO, have NCR5380_dma_xfer_len() evaluate to zero. That allows PDMA to be easily disabled at run-time and so the PSEUDO_DMA macro is no longer needed. Also remove the spin counters used for debugging pseudo DMA drivers. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 32 +------------------------------- drivers/scsi/NCR5380.h | 4 ---- drivers/scsi/arm/cumana_1.c | 2 -- drivers/scsi/arm/oak.c | 3 +-- drivers/scsi/dmx3191d.c | 4 ++++ drivers/scsi/dtc.c | 7 ------- drivers/scsi/dtc.h | 2 -- drivers/scsi/g_NCR5380.c | 1 - drivers/scsi/g_NCR5380.h | 1 - drivers/scsi/mac_scsi.c | 10 ---------- drivers/scsi/pas16.c | 10 ---------- drivers/scsi/pas16.h | 2 -- drivers/scsi/t128.c | 4 ---- drivers/scsi/t128.h | 2 -- 14 files changed, 6 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 69c73c36b923..fc86cde2d28e 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -468,35 +468,10 @@ static void prepare_info(struct Scsi_Host *instance) #endif #ifdef PARITY "PARITY " -#endif -#ifdef PSEUDO_DMA - "PSEUDO_DMA " #endif ""); } -#ifdef PSEUDO_DMA -static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance, - char *buffer, int length) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - hostdata->spin_max_r = 0; - hostdata->spin_max_w = 0; - return 0; -} - -static int __maybe_unused NCR5380_show_info(struct seq_file *m, - struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - seq_printf(m, "Highwater I/O busy spin counts: write %d, read %d\n", - hostdata->spin_max_w, hostdata->spin_max_r); - return 0; -} -#endif - /** * NCR5380_init - initialise an NCR5380 * @instance: adapter to configure @@ -1436,7 +1411,6 @@ static int do_abort(struct Scsi_Host *instance) return -1; } -#if defined(PSEUDO_DMA) /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) @@ -1592,7 +1566,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; return foo; } -#endif /* PSEUDO_DMA */ /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) @@ -1683,7 +1656,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * in an unconditional loop. */ -#if defined(PSEUDO_DMA) transfersize = 0; if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); @@ -1706,9 +1678,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* XXX - need to source or sink data here, as appropriate */ } else cmd->SCp.this_residual -= transfersize - len; - } else -#endif /* PSEUDO_DMA */ - { + } else { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. */ diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 7b488a082462..8adf7377de4c 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -256,10 +256,6 @@ struct NCR5380_hostdata { struct work_struct main_task; #ifdef SUPPORT_TAGS struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */ -#endif -#ifdef PSEUDO_DMA - unsigned spin_max_r; - unsigned spin_max_w; #endif struct workqueue_struct *work_q; unsigned long accesses_per_ms; /* chip register accesses per ms */ diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 76b2d3364d9f..6e9de19fc3c2 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -13,8 +13,6 @@ #include -#define PSEUDO_DMA - #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_read(reg) cumanascsi_read(instance, reg) #define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value) diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 8d8426535e6d..63abd6b248a6 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -14,7 +14,6 @@ #include -/*#define PSEUDO_DMA*/ #define DONT_USE_INTR #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) @@ -24,7 +23,7 @@ #define NCR5380_write(reg, value) \ writeb(value, priv(instance)->base + ((reg) << 2)) -#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index e9e96af96104..929bc1b618f8 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -39,6 +39,10 @@ #define NCR5380_read(reg) inb(instance->io_port + reg) #define NCR5380_write(reg, value) outb(value, instance->io_port + reg) +#define NCR5380_dma_xfer_len(instance, cmd, phase) (0) +#define NCR5380_pread(instance, dst, len) (0) +#define NCR5380_pwrite(instance, src, len) (0) + #define NCR5380_implementation_fields /* none */ #include "NCR5380.h" diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 30919f42759a..30d3e73f70ca 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -1,4 +1,3 @@ -#define PSEUDO_DMA #define DONT_USE_INTR /* @@ -352,8 +351,6 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) ++i; rtrc(0); - if (i > hostdata->spin_max_r) - hostdata->spin_max_r = i; return (0); } @@ -400,8 +397,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, rtrc(7); /* Check for parity error here. fixme. */ rtrc(0); - if (i > hostdata->spin_max_w) - hostdata->spin_max_w = i; return (0); } @@ -440,8 +435,6 @@ static struct scsi_host_template driver_template = { .detect = dtc_detect, .release = dtc_release, .proc_name = "dtc3x80", - .show_info = dtc_show_info, - .write_info = dtc_write_info, .info = dtc_info, .queuecommand = dtc_queue_command, .eh_abort_handler = dtc_abort, diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 56732cba8aba..1bc638730dda 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -27,8 +27,6 @@ #define NCR5380_abort dtc_abort #define NCR5380_bus_reset dtc_bus_reset #define NCR5380_info dtc_info -#define NCR5380_show_info dtc_show_info -#define NCR5380_write_info dtc_write_info /* 15 12 11 10 1001 1100 0000 0000 */ diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index aaeb6b6b4b16..fc7bcbcf3f43 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -57,7 +57,6 @@ */ #define AUTOPROBE_IRQ -#define PSEUDO_DMA #include #include diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 3fb0d8529429..a231a8c52d87 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -70,7 +70,6 @@ #define NCR5380_pread generic_NCR5380_pread #define NCR5380_pwrite generic_NCR5380_pwrite #define NCR5380_info generic_NCR5380_info -#define NCR5380_show_info generic_NCR5380_show_info #define BOARD_NCR5380 0 #define BOARD_NCR53C400 1 diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index a8f5433b515e..1e0d07ac83a1 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -28,8 +28,6 @@ /* Definitions for the core NCR5380 driver. */ -#define PSEUDO_DMA - #define NCR5380_implementation_fields unsigned char *pdma_base #define NCR5380_read(reg) macscsi_read(instance, reg) @@ -46,8 +44,6 @@ #define NCR5380_abort macscsi_abort #define NCR5380_bus_reset macscsi_bus_reset #define NCR5380_info macscsi_info -#define NCR5380_show_info macscsi_show_info -#define NCR5380_write_info macscsi_write_info #include "NCR5380.h" @@ -111,7 +107,6 @@ static int __init mac_scsi_setup(char *str) __setup("mac5380=", mac_scsi_setup); #endif /* !MODULE */ -#ifdef PSEUDO_DMA /* Pseudo-DMA: (Ove Edlund) The code attempts to catch bus errors that occur if one for example @@ -303,7 +298,6 @@ static int macscsi_pwrite(struct Scsi_Host *instance, return 0; } -#endif static int macscsi_dma_xfer_len(struct Scsi_Host *instance, struct scsi_cmnd *cmd) @@ -324,8 +318,6 @@ static int macscsi_dma_xfer_len(struct Scsi_Host *instance, static struct scsi_host_template mac_scsi_template = { .module = THIS_MODULE, .proc_name = DRV_MODULE_NAME, - .show_info = macscsi_show_info, - .write_info = macscsi_write_info, .name = "Macintosh NCR5380 SCSI", .info = macscsi_info, .queuecommand = macscsi_queue_command, @@ -351,9 +343,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev) if (!pio_mem) return -ENODEV; -#ifdef PSEUDO_DMA pdma_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); -#endif irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 7589fea01186..9c06eb637417 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -1,5 +1,3 @@ -#define PSEUDO_DMA - /* * This driver adapted from Drew Eckhardt's Trantor T128 driver * @@ -479,7 +477,6 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, P_DATA_REG_OFFSET); register int i = len; int ii = 0; - struct NCR5380_hostdata *hostdata = shost_priv(instance); while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) ) ++ii; @@ -492,8 +489,6 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, instance->host_no); return -1; } - if (ii > hostdata->spin_max_r) - hostdata->spin_max_r = ii; return 0; } @@ -516,7 +511,6 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET); register int i = len; int ii = 0; - struct NCR5380_hostdata *hostdata = shost_priv(instance); while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) ) ++ii; @@ -529,8 +523,6 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src instance->host_no); return -1; } - if (ii > hostdata->spin_max_w) - hostdata->spin_max_w = ii; return 0; } @@ -550,8 +542,6 @@ static struct scsi_host_template driver_template = { .detect = pas16_detect, .release = pas16_release, .proc_name = "pas16", - .show_info = pas16_show_info, - .write_info = pas16_write_info, .info = pas16_info, .queuecommand = pas16_queue_command, .eh_abort_handler = pas16_abort, diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index d37527717225..1695885ce40c 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -109,8 +109,6 @@ #define NCR5380_abort pas16_abort #define NCR5380_bus_reset pas16_bus_reset #define NCR5380_info pas16_info -#define NCR5380_show_info pas16_show_info -#define NCR5380_write_info pas16_write_info /* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 6cb8bdd2f4e6..ce2395f3fae9 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -1,5 +1,3 @@ -#define PSEUDO_DMA - /* * Trantor T128/T128F/T228 driver * Note : architecturally, the T100 and T130 are different and won't @@ -394,8 +392,6 @@ static struct scsi_host_template driver_template = { .detect = t128_detect, .release = t128_release, .proc_name = "t128", - .show_info = t128_show_info, - .write_info = t128_write_info, .info = t128_info, .queuecommand = t128_queue_command, .eh_abort_handler = t128_abort, diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index dd16d85497e1..c369b50de746 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -83,8 +83,6 @@ #define NCR5380_abort t128_abort #define NCR5380_bus_reset t128_bus_reset #define NCR5380_info t128_info -#define NCR5380_show_info t128_show_info -#define NCR5380_write_info t128_write_info /* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ -- GitLab From e5d55d1abcef09f7440e6211d5bd673baf547630 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:16 +1100 Subject: [PATCH 2063/9938] ncr5380: Remove BOARD_REQUIRES_NO_DELAY macro The io_recovery_delay macro is intended to insert a microsecond delay between the chip register accesses that begin a DMA operation. This is reportedly needed for some ISA boards. Reverse the sense of the macro test so that in the common case, where no delay is required, drivers need not define the macro. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 18 ++++++++---------- drivers/scsi/dtc.h | 2 ++ drivers/scsi/g_NCR5380.h | 2 ++ drivers/scsi/t128.h | 2 ++ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index fc86cde2d28e..014a01f6875f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -39,12 +39,6 @@ * tagged queueing) */ -#ifdef BOARD_REQUIRES_NO_DELAY -#define io_recovery_delay(x) -#else -#define io_recovery_delay(x) udelay(x) -#endif - /* * Design * @@ -150,6 +144,10 @@ * possible) function may be used. */ +#ifndef NCR5380_io_delay +#define NCR5380_io_delay(x) +#endif + static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); @@ -1468,14 +1466,14 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { - io_recovery_delay(1); + NCR5380_io_delay(1); NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); } else { - io_recovery_delay(1); + NCR5380_io_delay(1); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); - io_recovery_delay(1); + NCR5380_io_delay(1); NCR5380_write(START_DMA_SEND_REG, 0); - io_recovery_delay(1); + NCR5380_io_delay(1); } /* diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 1bc638730dda..718f95adcec6 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -28,6 +28,8 @@ #define NCR5380_bus_reset dtc_bus_reset #define NCR5380_info dtc_info +#define NCR5380_io_delay(x) udelay(x) + /* 15 12 11 10 1001 1100 0000 0000 */ diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index a231a8c52d87..637740f4c6c7 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -71,6 +71,8 @@ #define NCR5380_pwrite generic_NCR5380_pwrite #define NCR5380_info generic_NCR5380_info +#define NCR5380_io_delay(x) udelay(x) + #define BOARD_NCR5380 0 #define BOARD_NCR53C400 1 #define BOARD_NCR53C400A 2 diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index c369b50de746..4caea9d62ac4 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -84,6 +84,8 @@ #define NCR5380_bus_reset t128_bus_reset #define NCR5380_info t128_info +#define NCR5380_io_delay(x) udelay(x) + /* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ -- GitLab From 6c4b88ca59ba1a68f707f19dba1744ed19e89fce Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:17 +1100 Subject: [PATCH 2064/9938] ncr5380: Use DMA hooks for PDMA Those wrapper drivers which use DMA define the REAL_DMA macro and those which use pseudo DMA define PSEUDO_DMA. These macros need to be removed for a number of reasons, not least of which is to have drivers share more code. Redefine the PDMA send and receive hooks as DMA setup hooks, so that the DMA code can be shared by all 5380 wrapper drivers. This will help to reunify the forked core driver. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 10 ++-------- drivers/scsi/arm/cumana_1.c | 10 ++++++---- drivers/scsi/arm/oak.c | 10 ++++++---- drivers/scsi/dmx3191d.c | 4 ++-- drivers/scsi/dtc.c | 6 ++++-- drivers/scsi/dtc.h | 2 ++ drivers/scsi/g_NCR5380.c | 10 ++++++---- drivers/scsi/g_NCR5380.h | 4 ++-- drivers/scsi/mac_scsi.c | 5 ++--- drivers/scsi/pas16.c | 14 ++++++++------ drivers/scsi/pas16.h | 2 ++ drivers/scsi/t128.c | 12 ++++++------ drivers/scsi/t128.h | 2 ++ 13 files changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 014a01f6875f..b3e5b6b57d83 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -127,17 +127,11 @@ * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented - * Note that the DMA setup functions should return the number of bytes - * that they were able to program the controller for. * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize * NCR5380_dma_residual(instance); - residual count * - * PSEUDO functions : - * NCR5380_pwrite(instance, src, count) - * NCR5380_pread(instance, dst, count); - * * The generic driver is initialized by calling NCR5380_init(instance), * after setting the appropriate host specific fields and ID. If the * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, @@ -1511,7 +1505,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { - foo = NCR5380_pread(instance, d, + foo = NCR5380_dma_recv_setup(instance, d, hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* @@ -1542,7 +1536,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, d[c - 1] = NCR5380_read(INPUT_DATA_REG); } } else { - foo = NCR5380_pwrite(instance, d, c); + foo = NCR5380_dma_send_setup(instance, d, c); if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * Wait for the last byte to be sent. If REQ is being asserted for diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 6e9de19fc3c2..7bcb66893059 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -18,6 +18,8 @@ #define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value) #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_recv_setup cumanascsi_pread +#define NCR5380_dma_send_setup cumanascsi_pwrite #define NCR5380_intr cumanascsi_intr #define NCR5380_queue_command cumanascsi_queue_command @@ -39,8 +41,8 @@ void cumanascsi_setup(char *str, int *ints) #define L(v) (((v)<<16)|((v) & 0x0000ffff)) #define H(v) (((v)>>16)|((v) & 0xffff0000)) -static inline int -NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) +static inline int cumanascsi_pwrite(struct Scsi_Host *host, + unsigned char *addr, int len) { unsigned long *laddr; void __iomem *dma = priv(host)->dma + 0x2000; @@ -102,8 +104,8 @@ NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) return len; } -static inline int -NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, int len) +static inline int cumanascsi_pread(struct Scsi_Host *host, + unsigned char *addr, int len) { unsigned long *laddr; void __iomem *dma = priv(host)->dma + 0x2000; diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 63abd6b248a6..5d6e0e590638 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -24,6 +24,8 @@ writeb(value, priv(instance)->base + ((reg) << 2)) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) +#define NCR5380_dma_recv_setup oakscsi_pread +#define NCR5380_dma_send_setup oakscsi_pwrite #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info @@ -39,8 +41,8 @@ #define STAT ((128 + 16) << 2) #define DATA ((128 + 8) << 2) -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, - int len) +static inline int oakscsi_pwrite(struct Scsi_Host *instance, + unsigned char *addr, int len) { void __iomem *base = priv(instance)->base; @@ -54,8 +56,8 @@ printk("writing %p len %d\n",addr, len); } } -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, - int len) +static inline int oakscsi_pread(struct Scsi_Host *instance, + unsigned char *addr, int len) { void __iomem *base = priv(instance)->base; printk("reading %p len %d\n", addr, len); diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 929bc1b618f8..4b58fa0c16fe 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -40,8 +40,8 @@ #define NCR5380_write(reg, value) outb(value, instance->io_port + reg) #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) -#define NCR5380_pread(instance, dst, len) (0) -#define NCR5380_pwrite(instance, src, len) (0) +#define NCR5380_dma_recv_setup(instance, dst, len) (0) +#define NCR5380_dma_send_setup(instance, src, len) (0) #define NCR5380_implementation_fields /* none */ diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 30d3e73f70ca..df17904bbe12 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -322,7 +322,8 @@ static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev, * timeout. */ -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) +static inline int dtc_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) { unsigned char *d = dst; int i; /* For counting time spent in the poll-loop */ @@ -367,7 +368,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, * timeout. */ -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) +static inline int dtc_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) { int i; struct NCR5380_hostdata *hostdata = shost_priv(instance); diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 718f95adcec6..65af89e4340c 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -21,6 +21,8 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) \ dtc_dma_xfer_len(cmd) +#define NCR5380_dma_recv_setup dtc_pread +#define NCR5380_dma_send_setup dtc_pwrite #define NCR5380_intr dtc_intr #define NCR5380_queue_command dtc_queue_command diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index fc7bcbcf3f43..f8c00c96a837 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -551,7 +551,7 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) } /** - * NCR5380_pread - pseudo DMA read + * generic_NCR5380_pread - pseudo DMA read * @instance: adapter to read from * @dst: buffer to read into * @len: buffer length @@ -560,7 +560,8 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) * controller */ -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) +static inline int generic_NCR5380_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; @@ -628,7 +629,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } /** - * NCR5380_write - pseudo DMA write + * generic_NCR5380_pwrite - pseudo DMA write * @instance: adapter to read from * @dst: buffer to read into * @len: buffer length @@ -637,7 +638,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, * controller */ -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) +static inline int generic_NCR5380_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 637740f4c6c7..7f4308705532 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -62,13 +62,13 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) \ generic_NCR5380_dma_xfer_len(instance, cmd) +#define NCR5380_dma_recv_setup generic_NCR5380_pread +#define NCR5380_dma_send_setup generic_NCR5380_pwrite #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command #define NCR5380_abort generic_NCR5380_abort #define NCR5380_bus_reset generic_NCR5380_bus_reset -#define NCR5380_pread generic_NCR5380_pread -#define NCR5380_pwrite generic_NCR5380_pwrite #define NCR5380_info generic_NCR5380_info #define NCR5380_io_delay(x) udelay(x) diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 1e0d07ac83a1..99b7bbc3dd94 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -33,11 +33,10 @@ #define NCR5380_read(reg) macscsi_read(instance, reg) #define NCR5380_write(reg, value) macscsi_write(instance, reg, value) -#define NCR5380_pread macscsi_pread -#define NCR5380_pwrite macscsi_pwrite - #define NCR5380_dma_xfer_len(instance, cmd, phase) \ macscsi_dma_xfer_len(instance, cmd) +#define NCR5380_dma_recv_setup macscsi_pread +#define NCR5380_dma_send_setup macscsi_pwrite #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 9c06eb637417..c8fd2230c792 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -458,7 +458,7 @@ static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev, } /* - * Function : int NCR5380_pread (struct Scsi_Host *instance, + * Function : int pas16_pread (struct Scsi_Host *instance, * unsigned char *dst, int len) * * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to @@ -470,8 +470,9 @@ static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev, * timeout. */ -static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, - int len) { +static inline int pas16_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) +{ register unsigned char *d = dst; register unsigned short reg = (unsigned short) (instance->io_port + P_DATA_REG_OFFSET); @@ -493,7 +494,7 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, } /* - * Function : int NCR5380_pwrite (struct Scsi_Host *instance, + * Function : int pas16_pwrite (struct Scsi_Host *instance, * unsigned char *src, int len) * * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from @@ -505,8 +506,9 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, * timeout. */ -static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, - int len) { +static inline int pas16_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) +{ register unsigned char *s = src; register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET); register int i = len; diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index 1695885ce40c..f56f38796bcd 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -103,6 +103,8 @@ #define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_recv_setup pas16_pread +#define NCR5380_dma_send_setup pas16_pwrite #define NCR5380_intr pas16_intr #define NCR5380_queue_command pas16_queue_command diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index ce2395f3fae9..6cc3da8d1d69 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -292,7 +292,7 @@ static int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, } /* - * Function : int NCR5380_pread (struct Scsi_Host *instance, + * Function : int t128_pread (struct Scsi_Host *instance, * unsigned char *dst, int len) * * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to @@ -304,8 +304,8 @@ static int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, * timeout. */ -static inline int -NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) +static inline int t128_pread(struct Scsi_Host *instance, + unsigned char *dst, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); void __iomem *reg, *base = hostdata->base; @@ -338,7 +338,7 @@ NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) } /* - * Function : int NCR5380_pwrite (struct Scsi_Host *instance, + * Function : int t128_pwrite (struct Scsi_Host *instance, * unsigned char *src, int len) * * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from @@ -350,8 +350,8 @@ NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) * timeout. */ -static inline int -NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) +static inline int t128_pwrite(struct Scsi_Host *instance, + unsigned char *src, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); void __iomem *reg, *base = hostdata->base; diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 4caea9d62ac4..b6fe70f0aa4b 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -77,6 +77,8 @@ #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) +#define NCR5380_dma_recv_setup t128_pread +#define NCR5380_dma_send_setup t128_pwrite #define NCR5380_intr t128_intr #define NCR5380_queue_command t128_queue_command -- GitLab From 438af51c642926f1c1844846bee1c3fb568dcd64 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:18 +1100 Subject: [PATCH 2065/9938] ncr5380: Adopt uniform DMA setup convention Standardize the DMA setup hooks so that the DMA implementation in atari_NCR5380.c can be reconciled with pseudo DMA implementation in NCR5380.c. Calls to NCR5380_dma_recv_setup() and NCR5380_dma_send_setup() return a negative value on failure, zero on PDMA transfer success and a positive byte count for DMA setup success. This convention is not entirely new, but is now applied consistently. Also remove a pointless Status Register access: the *phase assignment is redundant because after NCR5380_transfer_dma() returns control to NCR5380_information_transfer(), that routine then returns control to NCR5380_main(), which means *phase is dead. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 21 ++++++++++----------- drivers/scsi/arm/cumana_1.c | 10 ++++++++-- drivers/scsi/arm/oak.c | 4 ++-- drivers/scsi/atari_scsi.c | 3 --- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index b3e5b6b57d83..e05cf505f0d4 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1431,7 +1431,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, register unsigned char p = *phase; register unsigned char *d = *data; unsigned char tmp; - int foo; + int result; if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; @@ -1505,9 +1505,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { - foo = NCR5380_dma_recv_setup(instance, d, + result = NCR5380_dma_recv_setup(instance, d, hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); - if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { + if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for @@ -1525,19 +1525,19 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, HZ) < 0) { - foo = -1; + result = -1; shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n"); } if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, HZ) < 0) { - foo = -1; + result = -1; shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); } d[c - 1] = NCR5380_read(INPUT_DATA_REG); } } else { - foo = NCR5380_dma_send_setup(instance, d, c); - if (!foo && (hostdata->flags & FLAG_DMA_FIXUP)) { + result = NCR5380_dma_send_setup(instance, d, c); + if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { /* * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. @@ -1545,7 +1545,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, if (NCR5380_poll_politely2(instance, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) { - foo = -1; + result = -1; shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n"); } } @@ -1555,8 +1555,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, NCR5380_read(RESET_PARITY_INTERRUPT_REG); *data = d + c; *count = 0; - *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; - return foo; + return result; } /* @@ -1652,7 +1651,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) if (!cmd->device->borken) transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); - if (transfersize) { + if (transfersize > 0) { len = transfersize; if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **)&cmd->SCp.ptr)) { diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 7bcb66893059..402d984aa088 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -101,7 +101,10 @@ static inline int cumanascsi_pwrite(struct Scsi_Host *host, } end: writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); - return len; + + if (len) + return -1; + return 0; } static inline int cumanascsi_pread(struct Scsi_Host *host, @@ -163,7 +166,10 @@ static inline int cumanascsi_pread(struct Scsi_Host *host, } end: writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); - return len; + + if (len) + return -1; + return 0; } static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg) diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 5d6e0e590638..05cf874fc739 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -47,13 +47,13 @@ static inline int oakscsi_pwrite(struct Scsi_Host *instance, void __iomem *base = priv(instance)->base; printk("writing %p len %d\n",addr, len); - if(!len) return -1; while(1) { int status; while (((status = readw(base + STAT)) & 0x100)==0); } + return 0; } static inline int oakscsi_pread(struct Scsi_Host *instance, @@ -74,7 +74,7 @@ printk("reading %p len %d\n", addr, len); if(status & 0x200 || !timeout) { printk("status = %08X\n", status); - return 1; + return -1; } } diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 41ddd95cebe6..5a81cec79a59 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -527,9 +527,6 @@ static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, */ dma_cache_maintenance(addr, count, dir); - if (count == 0) - printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n"); - if (IS_A_TT()) { tt_scsi_dma.dma_ctrl = dir; SCSI_DMA_WRITE_P(dma_addr, addr); -- GitLab From 8053b0ee79c0129e827ce8f222398ff4b332dfd7 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:19 +1100 Subject: [PATCH 2066/9938] ncr5380: Merge DMA implementation from atari_NCR5380 core driver Adopt the DMA implementation from atari_NCR5380.c. This means that atari_scsi and sun3_scsi can make use of the NCR5380.c core driver and the atari_NCR5380.c driver fork can be made redundant. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 170 +++++++++++++++++++++++++++++------- drivers/scsi/arm/cumana_1.c | 3 +- drivers/scsi/arm/oak.c | 3 +- drivers/scsi/dmx3191d.c | 1 + drivers/scsi/dtc.c | 2 +- drivers/scsi/dtc.h | 1 + drivers/scsi/g_NCR5380.c | 2 +- drivers/scsi/g_NCR5380.h | 1 + drivers/scsi/mac_scsi.c | 3 +- drivers/scsi/pas16.c | 2 +- drivers/scsi/pas16.h | 1 + drivers/scsi/t128.c | 2 +- drivers/scsi/t128.h | 1 + 13 files changed, 152 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index e05cf505f0d4..fbd8a98af881 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -31,9 +31,6 @@ /* * Further development / testing that should be done : - * 1. Cleanup the NCR5380_transfer_dma function and DMA operation complete - * code so that everything does the same thing that's done at the - * end of a pseudo-DMA read operation. * * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) @@ -117,6 +114,8 @@ * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * + * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. + * * These macros MUST be defined : * * NCR5380_read(register) - read from the specified register @@ -801,6 +800,72 @@ static void NCR5380_main(struct work_struct *work) } while (!done); } +/* + * NCR5380_dma_complete - finish DMA transfer + * @instance: the scsi host instance + * + * Called by the interrupt handler when DMA finishes or a phase + * mismatch occurs (which would end the DMA transfer). + */ + +static void NCR5380_dma_complete(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + int transferred; + unsigned char **data; + int *count; + int saved_data = 0, overrun = 0; + unsigned char p; + + if (hostdata->read_overruns) { + p = hostdata->connected->SCp.phase; + if (p & SR_IO) { + udelay(10); + if ((NCR5380_read(BUS_AND_STATUS_REG) & + (BASR_PHASE_MATCH | BASR_ACK)) == + (BASR_PHASE_MATCH | BASR_ACK)) { + saved_data = NCR5380_read(INPUT_DATA_REG); + overrun = 1; + dsprintk(NDEBUG_DMA, instance, "read overrun handled\n"); + } + } + } + + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + + transferred = hostdata->dma_len - NCR5380_dma_residual(instance); + hostdata->dma_len = 0; + + data = (unsigned char **)&hostdata->connected->SCp.ptr; + count = &hostdata->connected->SCp.this_residual; + *data += transferred; + *count -= transferred; + + if (hostdata->read_overruns) { + int cnt, toPIO; + + if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) { + cnt = toPIO = hostdata->read_overruns; + if (overrun) { + dsprintk(NDEBUG_DMA, instance, + "Got an input overrun, using saved byte\n"); + *(*data)++ = saved_data; + (*count)--; + cnt--; + toPIO--; + } + if (toPIO > 0) { + dsprintk(NDEBUG_DMA, instance, + "Doing %d byte PIO to 0x%p\n", cnt, *data); + NCR5380_transfer_pio(instance, &p, &cnt, data); + *count -= toPIO - cnt; + } + } + } +} + #ifndef DONT_USE_INTR /** @@ -855,7 +920,22 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", irq, basr, sr, mr); - if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && + if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { + /* Probably End of DMA, Phase Mismatch or Loss of BSY. + * We ack IRQ after clearing Mode Register. Workarounds + * for End of DMA errata need to happen in DMA Mode. + */ + + dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); + + if (hostdata->connected) { + NCR5380_dma_complete(instance); + queue_work(hostdata->work_q, &hostdata->main_task); + } else { + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } + } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { /* Probably reselected */ NCR5380_write(SELECT_ENABLE_REG, 0); @@ -1431,28 +1511,38 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, register unsigned char p = *phase; register unsigned char *d = *data; unsigned char tmp; - int result; + int result = 0; if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; return -1; } - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); + hostdata->connected->SCp.phase = p; - /* - * Note : on my sample board, watch-dog timeouts occurred when interrupts - * were not disabled for the duration of a single DMA transfer, from - * before the setting of DMA mode to after transfer of the last byte. - */ + if (p & SR_IO) { + if (hostdata->read_overruns) + c -= hostdata->read_overruns; + else if (hostdata->flags & FLAG_DMA_FIXUP) + --c; + } - if (hostdata->flags & FLAG_DMA_FIXUP) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); - else - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); + dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", + (p & SR_IO) ? "receive" : "send", c, d); - dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | + MR_ENABLE_EOP_INTR); + + if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) { + /* On the Medusa, it is a must to initialize the DMA before + * starting the NCR. This is also the cleaner way for the TT. + */ + if (p & SR_IO) + result = NCR5380_dma_recv_setup(instance, d, c); + else + result = NCR5380_dma_send_setup(instance, d, c); + } /* * On the PAS16 at least I/O recovery delays are not needed here. @@ -1470,6 +1560,29 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, NCR5380_io_delay(1); } + if (hostdata->flags & FLAG_LATE_DMA_SETUP) { + /* On the Falcon, the DMA setup must be done after the last + * NCR access, else the DMA setup gets trashed! + */ + if (p & SR_IO) + result = NCR5380_dma_recv_setup(instance, d, c); + else + result = NCR5380_dma_send_setup(instance, d, c); + } + + /* On failure, NCR5380_dma_xxxx_setup() returns a negative int. */ + if (result < 0) + return result; + + /* For real DMA, result is the byte count. DMA interrupt is expected. */ + if (result > 0) { + hostdata->dma_len = result; + return 0; + } + + /* The result is zero iff pseudo DMA send/receive was completed. */ + hostdata->dma_len = c; + /* * A note regarding the DMA errata workarounds for early NMOS silicon. * @@ -1504,10 +1617,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * request. */ - if (p & SR_IO) { - result = NCR5380_dma_recv_setup(instance, d, - hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); - if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { + if (hostdata->flags & FLAG_DMA_FIXUP) { + if (p & SR_IO) { /* * The workaround was to transfer fewer bytes than we * intended to with the pseudo-DMA read function, wait for @@ -1533,11 +1644,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, result = -1; shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); } - d[c - 1] = NCR5380_read(INPUT_DATA_REG); - } - } else { - result = NCR5380_dma_send_setup(instance, d, c); - if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { + d[*count - 1] = NCR5380_read(INPUT_DATA_REG); + } else { /* * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. @@ -1550,11 +1658,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, } } } - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - *data = d + c; - *count = 0; + + NCR5380_dma_complete(instance); return result; } @@ -1667,8 +1772,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) do_abort(instance); cmd->result = DID_ERROR << 16; /* XXX - need to source or sink data here, as appropriate */ - } else - cmd->SCp.this_residual -= transfersize - len; + } } else { /* Break up transfer into 3 ms chunks, * presuming 6 accesses per handshake. diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 402d984aa088..8e9cfe8f22f5 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -20,6 +20,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_dma_recv_setup cumanascsi_pread #define NCR5380_dma_send_setup cumanascsi_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr cumanascsi_intr #define NCR5380_queue_command cumanascsi_queue_command @@ -245,7 +246,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, host->irq = ec->irq; - ret = NCR5380_init(host, FLAG_DMA_FIXUP); + ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 05cf874fc739..3aac99c21267 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -26,6 +26,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup oakscsi_pread #define NCR5380_dma_send_setup oakscsi_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info @@ -144,7 +145,7 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) host->irq = NO_IRQ; host->n_io_port = 255; - ret = NCR5380_init(host, FLAG_DMA_FIXUP); + ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP); if (ret) goto out_unmap; diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 4b58fa0c16fe..cc46d67b9f6f 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -42,6 +42,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) #define NCR5380_dma_recv_setup(instance, dst, len) (0) #define NCR5380_dma_send_setup(instance, src, len) (0) +#define NCR5380_dma_residual(instance) (0) #define NCR5380_implementation_fields /* none */ diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index df17904bbe12..e87c632234f3 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -228,7 +228,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) instance->base = addr; ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; - if (NCR5380_init(instance, 0)) + if (NCR5380_init(instance, FLAG_LATE_DMA_SETUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 65af89e4340c..fcb0a8ea7bda 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -23,6 +23,7 @@ dtc_dma_xfer_len(cmd) #define NCR5380_dma_recv_setup dtc_pread #define NCR5380_dma_send_setup dtc_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr dtc_intr #define NCR5380_queue_command dtc_queue_command diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index f8c00c96a837..09e1cf938ecf 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -466,7 +466,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) } #endif - if (NCR5380_init(instance, flags)) + if (NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP)) goto out_unregister; switch (overrides[current_override].board) { diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 7f4308705532..595177428d76 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -64,6 +64,7 @@ generic_NCR5380_dma_xfer_len(instance, cmd) #define NCR5380_dma_recv_setup generic_NCR5380_pread #define NCR5380_dma_send_setup generic_NCR5380_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 99b7bbc3dd94..4de6589fdbfb 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -37,6 +37,7 @@ macscsi_dma_xfer_len(instance, cmd) #define NCR5380_dma_recv_setup macscsi_pread #define NCR5380_dma_send_setup macscsi_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command @@ -386,7 +387,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev) #endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; - error = NCR5380_init(instance, host_flags); + error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); if (error) goto fail_init; diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index c8fd2230c792..62eef3f6d140 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -375,7 +375,7 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) instance->io_port = io_port; - if (NCR5380_init(instance, FLAG_DMA_FIXUP)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index f56f38796bcd..9fe7f33660b4 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -105,6 +105,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_dma_recv_setup pas16_pread #define NCR5380_dma_send_setup pas16_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr pas16_intr #define NCR5380_queue_command pas16_queue_command diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 6cc3da8d1d69..b5beecfaa3d5 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -208,7 +208,7 @@ static int __init t128_detect(struct scsi_host_template *tpnt) instance->base = base; ((struct NCR5380_hostdata *)instance->hostdata)->base = p; - if (NCR5380_init(instance, FLAG_DMA_FIXUP)) + if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index b6fe70f0aa4b..c95bcd839109 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -79,6 +79,7 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_dma_recv_setup t128_pread #define NCR5380_dma_send_setup t128_pwrite +#define NCR5380_dma_residual(instance) (0) #define NCR5380_intr t128_intr #define NCR5380_queue_command t128_queue_command -- GitLab From 52d3e561cb13df431364a69e783469ba8a9ea8eb Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:20 +1100 Subject: [PATCH 2067/9938] atari_scsi: Adopt NCR5380.c core driver Add support for the Atari ST DMA chip to the NCR5380.c core driver. This code is copied from atari_NCR5380.c. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 32 ++++++++++++++++++++++++++++++++ drivers/scsi/atari_scsi.c | 6 +++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index fbd8a98af881..859b32febbb4 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -29,6 +29,8 @@ * Ronald van Cuijlenborg, Alan Cox and others. */ +/* Ported to Atari by Roman Hodek and others. */ + /* * Further development / testing that should be done : * @@ -141,6 +143,14 @@ #define NCR5380_io_delay(x) #endif +#ifndef NCR5380_acquire_dma_irq +#define NCR5380_acquire_dma_irq(x) (1) +#endif + +#ifndef NCR5380_release_dma_irq +#define NCR5380_release_dma_irq(x) +#endif + static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); @@ -658,6 +668,9 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, cmd->result = 0; + if (!NCR5380_acquire_dma_irq(instance)) + return SCSI_MLQUEUE_HOST_BUSY; + spin_lock_irqsave(&hostdata->lock, flags); /* @@ -682,6 +695,19 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, return 0; } +static inline void maybe_release_dma_irq(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + /* Caller does the locking needed to set & test these data atomically */ + if (list_empty(&hostdata->disconnected) && + list_empty(&hostdata->unissued) && + list_empty(&hostdata->autosense) && + !hostdata->connected && + !hostdata->selecting) + NCR5380_release_dma_irq(instance); +} + /** * dequeue_next_cmd - dequeue a command for processing * @instance: the scsi host instance @@ -783,6 +809,7 @@ static void NCR5380_main(struct work_struct *work) if (!NCR5380_select(instance, cmd)) { dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); + maybe_release_dma_irq(instance); } else { dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, "main: select failed, returning %p to queue\n", cmd); @@ -1828,6 +1855,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + + maybe_release_dma_irq(instance); return; case MESSAGE_REJECT: /* Accept message by clearing ACK */ @@ -1963,6 +1992,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->connected = NULL; cmd->result = DID_ERROR << 16; complete_cmd(instance, cmd); + maybe_release_dma_irq(instance); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; } @@ -2256,6 +2286,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd); queue_work(hostdata->work_q, &hostdata->main_task); + maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); return result; @@ -2336,6 +2367,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) hostdata->dma_len = 0; queue_work(hostdata->work_q, &hostdata->main_task); + maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); return SUCCESS; diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 5a81cec79a59..445c26724ba1 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -99,9 +99,9 @@ #define NCR5380_abort atari_scsi_abort #define NCR5380_info atari_scsi_info -#define NCR5380_dma_read_setup(instance, data, count) \ +#define NCR5380_dma_recv_setup(instance, data, count) \ atari_scsi_dma_setup(instance, data, count, 0) -#define NCR5380_dma_write_setup(instance, data, count) \ +#define NCR5380_dma_send_setup(instance, data, count) \ atari_scsi_dma_setup(instance, data, count, 1) #define NCR5380_dma_residual(instance) \ atari_scsi_dma_residual(instance) @@ -715,7 +715,7 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value) } -#include "atari_NCR5380.c" +#include "NCR5380.c" static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) { -- GitLab From e9db3198e08b6a01e2847f732e595bb8e89153c1 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:21 +1100 Subject: [PATCH 2068/9938] sun3_scsi: Adopt NCR5380.c core driver Add support for the custom Sun 3 DMA logic to the NCR5380.c core driver. This code is copied from atari_NCR5380.c. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 131 ++++++++++++++++++++++++++++++++++++--- drivers/scsi/sun3_scsi.c | 8 +-- 2 files changed, 124 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 859b32febbb4..a59b71f96365 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -31,6 +31,8 @@ /* Ported to Atari by Roman Hodek and others. */ +/* Adapted for the Sun 3 by Sam Creasey. */ + /* * Further development / testing that should be done : * @@ -858,6 +860,23 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } } +#ifdef CONFIG_SUN3 + if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) { + pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n", + instance->host_no); + BUG(); + } + + if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == + (BASR_PHASE_MATCH | BASR_ACK)) { + pr_err("scsi%d: BASR %02x\n", instance->host_no, + NCR5380_read(BUS_AND_STATUS_REG)); + pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n", + instance->host_no); + BUG(); + } +#endif + NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_read(RESET_PARITY_INTERRUPT_REG); @@ -981,10 +1000,16 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) NCR5380_read(RESET_PARITY_INTERRUPT_REG); dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif } handled = 1; } else { shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif } spin_unlock_irqrestore(&hostdata->lock, flags); @@ -1274,6 +1299,10 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, hostdata->connected = cmd; hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_INTR; +#endif + initialize_SCp(cmd); cmd = NULL; @@ -1557,6 +1586,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", (p & SR_IO) ? "receive" : "send", c, d); +#ifdef CONFIG_SUN3 + /* send start chain */ + sun3scsi_dma_start(c, *data); +#endif + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | MR_ENABLE_EOP_INTR); @@ -1577,6 +1611,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (p & SR_IO) { + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_io_delay(1); NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); } else { @@ -1587,6 +1622,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, NCR5380_io_delay(1); } +#ifdef CONFIG_SUN3 +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif + sun3_dma_active = 1; +#endif + if (hostdata->flags & FLAG_LATE_DMA_SETUP) { /* On the Falcon, the DMA setup must be done after the last * NCR access, else the DMA setup gets trashed! @@ -1718,6 +1760,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; struct scsi_cmnd *cmd; +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_INTR; +#endif + while ((cmd = hostdata->connected)) { struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); @@ -1729,6 +1775,31 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) old_phase = phase; NCR5380_dprint_phase(NDEBUG_INFORMATION, instance); } +#ifdef CONFIG_SUN3 + if (phase == PHASE_CMDOUT) { + void *d; + unsigned long count; + + if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { + count = cmd->SCp.buffer->length; + d = sg_virt(cmd->SCp.buffer); + } else { + count = cmd->SCp.this_residual; + d = cmd->SCp.ptr; + } + + if (sun3_dma_setup_done != cmd && + sun3scsi_dma_xfer_len(count, cmd) > 0) { + sun3scsi_dma_setup(instance, d, count, + rq_data_dir(cmd->request)); + sun3_dma_setup_done = cmd; + } +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_INTR; +#endif + } +#endif /* CONFIG_SUN3 */ + if (sink && (phase != PHASE_MSGOUT)) { NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); @@ -1811,6 +1882,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) (unsigned char **)&cmd->SCp.ptr); cmd->SCp.this_residual -= transfersize - len; } +#ifdef CONFIG_SUN3 + if (sun3_dma_setup_done == cmd) + sun3_dma_setup_done = NULL; +#endif return; case PHASE_MSGIN: len = 1; @@ -1889,6 +1964,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); +#ifdef SUN3_SCSI_VME + dregs->csr |= CSR_DMA_ENABLE; +#endif return; /* * The SCSI data pointer is *IMPLICITLY* saved on a disconnect @@ -2040,10 +2118,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char target_mask; - unsigned char lun, phase; - int len; + unsigned char lun; unsigned char msg[3]; - unsigned char *data; struct NCR5380_cmd *ncmd; struct scsi_cmnd *tmp; @@ -2085,15 +2161,26 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } - len = 1; - data = msg; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); +#ifdef CONFIG_SUN3 + /* acknowledge toggle to MSGIN */ + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN)); - if (len) { - do_abort(instance); - return; + /* peek at the byte without really hitting the bus */ + msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG); +#else + { + int len = 1; + unsigned char *data = msg; + unsigned char phase = PHASE_MSGIN; + + NCR5380_transfer_pio(instance, &phase, &len, &data); + + if (len) { + do_abort(instance); + return; + } } +#endif /* CONFIG_SUN3 */ if (!(msg[0] & 0x80)) { shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); @@ -2141,6 +2228,30 @@ static void NCR5380_reselect(struct Scsi_Host *instance) return; } +#ifdef CONFIG_SUN3 + { + void *d; + unsigned long count; + + if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) { + count = tmp->SCp.buffer->length; + d = sg_virt(tmp->SCp.buffer); + } else { + count = tmp->SCp.this_residual; + d = tmp->SCp.ptr; + } + + if (sun3_dma_setup_done != tmp && + sun3scsi_dma_xfer_len(count, tmp) > 0) { + sun3scsi_dma_setup(instance, d, count, + rq_data_dir(tmp->request)); + sun3_dma_setup_done = tmp; + } + } + + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); +#endif /* CONFIG_SUN3 */ + /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index fd4fad816ad4..f2fc788cb08b 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -54,10 +54,8 @@ #define NCR5380_abort sun3scsi_abort #define NCR5380_info sun3scsi_info -#define NCR5380_dma_read_setup(instance, data, count) \ - sun3scsi_dma_setup(instance, data, count, 0) -#define NCR5380_dma_write_setup(instance, data, count) \ - sun3scsi_dma_setup(instance, data, count, 1) +#define NCR5380_dma_recv_setup(instance, data, count) (count) +#define NCR5380_dma_send_setup(instance, data, count) (count) #define NCR5380_dma_residual(instance) \ sun3scsi_dma_residual(instance) #define NCR5380_dma_xfer_len(instance, cmd, phase) \ @@ -406,7 +404,7 @@ static int sun3scsi_dma_finish(int write_flag) } -#include "atari_NCR5380.c" +#include "NCR5380.c" #ifdef SUN3_SCSI_VME #define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI" -- GitLab From c4ec6f924f0682e1f40107204152e977d6b1bd07 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:22 +1100 Subject: [PATCH 2069/9938] ncr5380: Remove disused atari_NCR5380.c core driver Now that atari_scsi and sun3_scsi have been converted to use the NCR5380.c core driver, remove atari_NCR5380.c. Also remove the last vestiges of its Tagged Command Queueing implementation from the wrapper drivers. The TCQ support in atari_NCR5380.c is abandoned by this patch. It is not merged into the remaining core driver because, 1) atari_scsi defines SUPPORT_TAGS but leaves FLAG_TAGGED_QUEUING disabled by default, which indicates that it is mostly undesirable. 2) I'm told that it doesn't work correctly when enabled. 3) The algorithm does not make use of block layer tags which it will have to do because scmd->tag is deprecated. 4) sun3_scsi doesn't define SUPPORT_TAGS at all, yet the the SUPPORT_TAGS macro interacts with the CONFIG_SUN3 macro in 'interesting' ways. 5) Compile-time configuration with macros like SUPPORT_TAGS caused the configuration space to explode, leading to untestable and unmaintainable code that is too hard to reason about. The merge_contiguous_buffers() code is also abandoned. This was unused by sun3_scsi. Only atari_scsi used it and then only on TT, because only TT supports scatter/gather. I suspect that the TT would work fine with ENABLE_CLUSTERING instead. If someone can benchmark the difference then perhaps the merge_contiguous_buffers() code can be be justified. Until then we are better off without the extra complexity. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 22 +- drivers/scsi/NCR5380.h | 19 - drivers/scsi/atari_NCR5380.c | 2632 ---------------------------------- drivers/scsi/atari_scsi.c | 11 +- drivers/scsi/mac_scsi.c | 8 +- drivers/scsi/sun3_scsi.c | 11 - 6 files changed, 4 insertions(+), 2699 deletions(-) delete mode 100644 drivers/scsi/atari_NCR5380.c diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a59b71f96365..305330b26349 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -33,13 +33,6 @@ /* Adapted for the Sun 3 by Sam Creasey. */ -/* - * Further development / testing that should be done : - * - * 4. Test SCSI-II tagged queueing (I have no devices which support - * tagged queueing) - */ - /* * Design * @@ -1257,14 +1250,6 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * was true but before BSY was false during selection, the information * transfer phase should be a MESSAGE OUT phase so that we can send the * IDENTIFY message. - * - * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG - * message (2 bytes) with a tag ID that we increment with every command - * until it wraps back to 0. - * - * XXX - it turns out that there are some broken SCSI-II devices, - * which claim to support tagged queuing but fail when more than - * some number of commands are issued at once. */ /* Wait for start of REQ/ACK handshake */ @@ -1287,9 +1272,6 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun); len = 1; - cmd->tag = 0; - - /* Send message(s) */ data = tmp; phase = PHASE_MSGOUT; NCR5380_transfer_pio(instance, &phase, &len, &data); @@ -2256,8 +2238,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = tmp; - dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n", - scmd_id(tmp), tmp->device->lun, tmp->tag); + dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu\n", + scmd_id(tmp), tmp->device->lun); } /** diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 8adf7377de4c..5c2411f05852 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -199,13 +199,6 @@ #define PHASE_SR_TO_TCR(phase) ((phase) >> 2) -/* - * "Special" value for the (unsigned char) command tag, to indicate - * I_T_L nexus instead of I_T_L_Q. - */ - -#define TAG_NONE 0xff - /* * These are "special" values for the irq and dma_channel fields of the * Scsi_Host structure @@ -223,17 +216,8 @@ #define FLAG_DMA_FIXUP 1 /* Use DMA errata workarounds */ #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ -#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */ #define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */ -#ifdef SUPPORT_TAGS -struct tag_alloc { - DECLARE_BITMAP(allocated, MAX_TAGS); - int nr_allocated; - int queue_size; -}; -#endif - struct NCR5380_hostdata { NCR5380_implementation_fields; /* implementation specific */ struct Scsi_Host *host; /* Host backpointer */ @@ -254,9 +238,6 @@ struct NCR5380_hostdata { int read_overruns; /* number of bytes to cut from a * transfer to handle chip overruns */ struct work_struct main_task; -#ifdef SUPPORT_TAGS - struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */ -#endif struct workqueue_struct *work_q; unsigned long accesses_per_ms; /* chip register accesses per ms */ }; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c deleted file mode 100644 index 4101d2de4333..000000000000 --- a/drivers/scsi/atari_NCR5380.c +++ /dev/null @@ -1,2632 +0,0 @@ -/* - * NCR 5380 generic driver routines. These should make it *trivial* - * to implement 5380 SCSI drivers under Linux with a non-trantor - * architecture. - * - * Note that these routines also work with NR53c400 family chips. - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* Ported to Atari by Roman Hodek and others. */ - -/* Adapted for the sun3 by Sam Creasey. */ - -/* - * Design - * - * This is a generic 5380 driver. To use it on a different platform, - * one simply writes appropriate system specific macros (ie, data - * transfer - some PC's will use the I/O bus, 68K's must use - * memory mapped) and drops this file in their 'C' wrapper. - * - * As far as command queueing, two queues are maintained for - * each 5380 in the system - commands that haven't been issued yet, - * and commands that are currently executing. This means that an - * unlimited number of commands may be queued, letting - * more commands propagate from the higher driver levels giving higher - * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported, - * allowing multiple commands to propagate all the way to a SCSI-II device - * while a command is already executing. - * - * - * Issues specific to the NCR5380 : - * - * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead - * piece of hardware that requires you to sit in a loop polling for - * the REQ signal as long as you are connected. Some devices are - * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect - * while doing long seek operations. [...] These - * broken devices are the exception rather than the rule and I'd rather - * spend my time optimizing for the normal case. - * - * Architecture : - * - * At the heart of the design is a coroutine, NCR5380_main, - * which is started from a workqueue for each NCR5380 host in the - * system. It attempts to establish I_T_L or I_T_L_Q nexuses by - * removing the commands from the issue queue and calling - * NCR5380_select() if a nexus is not established. - * - * Once a nexus is established, the NCR5380_information_transfer() - * phase goes through the various phases as instructed by the target. - * if the target goes into MSG IN and sends a DISCONNECT message, - * the command structure is placed into the per instance disconnected - * queue, and NCR5380_main tries to find more work. If the target is - * idle for too long, the system will try to sleep. - * - * If a command has disconnected, eventually an interrupt will trigger, - * calling NCR5380_intr() which will in turn call NCR5380_reselect - * to reestablish a nexus. This will run main if necessary. - * - * On command termination, the done function will be called as - * appropriate. - * - * SCSI pointers are maintained in the SCp field of SCSI command - * structures, being initialized after the command is connected - * in NCR5380_select, and set as appropriate in NCR5380_information_transfer. - * Note that in violation of the standard, an implicit SAVE POINTERS operation - * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS. - */ - -/* - * Using this file : - * This file a skeleton Linux SCSI driver for the NCR 5380 series - * of chips. To use it, you write an architecture specific functions - * and macros and include this file in your driver. - * - * These macros control options : - * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. - * - * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential - * transceivers. - * - * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. - * - * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible - * - * These macros MUST be defined : - * - * NCR5380_read(register) - read from the specified register - * - * NCR5380_write(register, value) - write to the specific register - * - * NCR5380_implementation_fields - additional fields needed for this - * specific implementation of the NCR5380 - * - * Either real DMA *or* pseudo DMA may be implemented - * Note that the DMA setup functions should return the number of bytes - * that they were able to program the controller for. - * - * NCR5380_dma_write_setup(instance, src, count) - initialize - * NCR5380_dma_read_setup(instance, dst, count) - initialize - * NCR5380_dma_residual(instance); - residual count - * - * PSEUDO functions : - * NCR5380_pwrite(instance, src, count) - * NCR5380_pread(instance, dst, count); - * - * The generic driver is initialized by calling NCR5380_init(instance), - * after setting the appropriate host specific fields and ID. If the - * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, - * possible) function may be used. - */ - -static int do_abort(struct Scsi_Host *); -static void do_reset(struct Scsi_Host *); - -#ifdef SUPPORT_TAGS - -/* - * Functions for handling tagged queuing - * ===================================== - * - * ++roman (01/96): Now I've implemented SCSI-2 tagged queuing. Some notes: - * - * Using consecutive numbers for the tags is no good idea in my eyes. There - * could be wrong re-usings if the counter (8 bit!) wraps and some early - * command has been preempted for a long time. My solution: a bitfield for - * remembering used tags. - * - * There's also the problem that each target has a certain queue size, but we - * cannot know it in advance :-( We just see a QUEUE_FULL status being - * returned. So, in this case, the driver internal queue size assumption is - * reduced to the number of active tags if QUEUE_FULL is returned by the - * target. - * - * We're also not allowed running tagged commands as long as an untagged - * command is active. And REQUEST SENSE commands after a contingent allegiance - * condition _must_ be untagged. To keep track whether an untagged command has - * been issued, the host->busy array is still employed, as it is without - * support for tagged queuing. - * - * One could suspect that there are possible race conditions between - * is_lun_busy(), cmd_get_tag() and cmd_free_tag(). But I think this isn't the - * case: is_lun_busy() and cmd_get_tag() are both called from NCR5380_main(), - * which already guaranteed to be running at most once. It is also the only - * place where tags/LUNs are allocated. So no other allocation can slip - * between that pair, there could only happen a reselection, which can free a - * tag, but that doesn't hurt. Only the sequence in cmd_free_tag() becomes - * important: the tag bit must be cleared before 'nr_allocated' is decreased. - */ - -static void __init init_tags(struct NCR5380_hostdata *hostdata) -{ - int target, lun; - struct tag_alloc *ta; - - if (!(hostdata->flags & FLAG_TAGGED_QUEUING)) - return; - - for (target = 0; target < 8; ++target) { - for (lun = 0; lun < 8; ++lun) { - ta = &hostdata->TagAlloc[target][lun]; - bitmap_zero(ta->allocated, MAX_TAGS); - ta->nr_allocated = 0; - /* At the beginning, assume the maximum queue size we could - * support (MAX_TAGS). This value will be decreased if the target - * returns QUEUE_FULL status. - */ - ta->queue_size = MAX_TAGS; - } - } -} - - -/* Check if we can issue a command to this LUN: First see if the LUN is marked - * busy by an untagged command. If the command should use tagged queuing, also - * check that there is a free tag and the target's queue won't overflow. This - * function should be called with interrupts disabled to avoid race - * conditions. - */ - -static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) -{ - u8 lun = cmd->device->lun; - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - if (hostdata->busy[cmd->device->id] & (1 << lun)) - return 1; - if (!should_be_tagged || - !(hostdata->flags & FLAG_TAGGED_QUEUING) || - !cmd->device->tagged_supported) - return 0; - if (hostdata->TagAlloc[scmd_id(cmd)][lun].nr_allocated >= - hostdata->TagAlloc[scmd_id(cmd)][lun].queue_size) { - dsprintk(NDEBUG_TAGS, instance, "target %d lun %d: no free tags\n", - scmd_id(cmd), lun); - return 1; - } - return 0; -} - - -/* Allocate a tag for a command (there are no checks anymore, check_lun_busy() - * must be called before!), or reserve the LUN in 'busy' if the command is - * untagged. - */ - -static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) -{ - u8 lun = cmd->device->lun; - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - /* If we or the target don't support tagged queuing, allocate the LUN for - * an untagged command. - */ - if (!should_be_tagged || - !(hostdata->flags & FLAG_TAGGED_QUEUING) || - !cmd->device->tagged_supported) { - cmd->tag = TAG_NONE; - hostdata->busy[cmd->device->id] |= (1 << lun); - dsprintk(NDEBUG_TAGS, instance, "target %d lun %d now allocated by untagged command\n", - scmd_id(cmd), lun); - } else { - struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; - - cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS); - set_bit(cmd->tag, ta->allocated); - ta->nr_allocated++; - dsprintk(NDEBUG_TAGS, instance, "using tag %d for target %d lun %d (%d tags allocated)\n", - cmd->tag, scmd_id(cmd), lun, ta->nr_allocated); - } -} - - -/* Mark the tag of command 'cmd' as free, or in case of an untagged command, - * unlock the LUN. - */ - -static void cmd_free_tag(struct scsi_cmnd *cmd) -{ - u8 lun = cmd->device->lun; - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->device->id] &= ~(1 << lun); - dsprintk(NDEBUG_TAGS, instance, "target %d lun %d untagged cmd freed\n", - scmd_id(cmd), lun); - } else if (cmd->tag >= MAX_TAGS) { - shost_printk(KERN_NOTICE, instance, - "trying to free bad tag %d!\n", cmd->tag); - } else { - struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; - clear_bit(cmd->tag, ta->allocated); - ta->nr_allocated--; - dsprintk(NDEBUG_TAGS, instance, "freed tag %d for target %d lun %d\n", - cmd->tag, scmd_id(cmd), lun); - } -} - - -static void free_all_tags(struct NCR5380_hostdata *hostdata) -{ - int target, lun; - struct tag_alloc *ta; - - if (!(hostdata->flags & FLAG_TAGGED_QUEUING)) - return; - - for (target = 0; target < 8; ++target) { - for (lun = 0; lun < 8; ++lun) { - ta = &hostdata->TagAlloc[target][lun]; - bitmap_zero(ta->allocated, MAX_TAGS); - ta->nr_allocated = 0; - } - } -} - -#endif /* SUPPORT_TAGS */ - -/** - * merge_contiguous_buffers - coalesce scatter-gather list entries - * @cmd: command requesting IO - * - * Try to merge several scatter-gather buffers into one DMA transfer. - * This is possible if the scatter buffers lie on physically - * contiguous addresses. The first scatter-gather buffer's data are - * assumed to be already transferred into cmd->SCp.this_residual. - * Every buffer merged avoids an interrupt and a DMA setup operation. - */ - -static void merge_contiguous_buffers(struct scsi_cmnd *cmd) -{ -#if !defined(CONFIG_SUN3) - unsigned long endaddr; -#if (NDEBUG & NDEBUG_MERGING) - unsigned long oldlen = cmd->SCp.this_residual; - int cnt = 1; -#endif - - for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; - cmd->SCp.buffers_residual && - virt_to_phys(sg_virt(&cmd->SCp.buffer[1])) == endaddr;) { - dprintk(NDEBUG_MERGING, "VTOP(%p) == %08lx -> merging\n", - page_address(sg_page(&cmd->SCp.buffer[1])), endaddr); -#if (NDEBUG & NDEBUG_MERGING) - ++cnt; -#endif - ++cmd->SCp.buffer; - --cmd->SCp.buffers_residual; - cmd->SCp.this_residual += cmd->SCp.buffer->length; - endaddr += cmd->SCp.buffer->length; - } -#if (NDEBUG & NDEBUG_MERGING) - if (oldlen != cmd->SCp.this_residual) - dprintk(NDEBUG_MERGING, "merged %d buffers from %p, new length %08x\n", - cnt, cmd->SCp.ptr, cmd->SCp.this_residual); -#endif -#endif /* !defined(CONFIG_SUN3) */ -} - -/** - * initialize_SCp - init the scsi pointer field - * @cmd: command block to set up - * - * Set up the internal fields in the SCSI command. - */ - -static inline void initialize_SCp(struct scsi_cmnd *cmd) -{ - /* - * Initialize the Scsi Pointer field so that all of the commands in the - * various queues are valid. - */ - - if (scsi_bufflen(cmd)) { - cmd->SCp.buffer = scsi_sglist(cmd); - cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; - cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); - cmd->SCp.this_residual = cmd->SCp.buffer->length; - - merge_contiguous_buffers(cmd); - } else { - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = NULL; - cmd->SCp.this_residual = 0; - } - - cmd->SCp.Status = 0; - cmd->SCp.Message = 0; -} - -/** - * NCR5380_poll_politely2 - wait for two chip register values - * @instance: controller to poll - * @reg1: 5380 register to poll - * @bit1: Bitmask to check - * @val1: Expected value - * @reg2: Second 5380 register to poll - * @bit2: Second bitmask to check - * @val2: Second expected value - * @wait: Time-out in jiffies - * - * Polls the chip in a reasonably efficient manner waiting for an - * event to occur. After a short quick poll we begin to yield the CPU - * (if possible). In irq contexts the time-out is arbitrarily limited. - * Callers may hold locks as long as they are held in irq mode. - * - * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT. - */ - -static int NCR5380_poll_politely2(struct Scsi_Host *instance, - int reg1, int bit1, int val1, - int reg2, int bit2, int val2, int wait) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned long deadline = jiffies + wait; - unsigned long n; - - /* Busy-wait for up to 10 ms */ - n = min(10000U, jiffies_to_usecs(wait)); - n *= hostdata->accesses_per_ms; - n /= 2000; - do { - if ((NCR5380_read(reg1) & bit1) == val1) - return 0; - if ((NCR5380_read(reg2) & bit2) == val2) - return 0; - cpu_relax(); - } while (n--); - - if (irqs_disabled() || in_interrupt()) - return -ETIMEDOUT; - - /* Repeatedly sleep for 1 ms until deadline */ - while (time_is_after_jiffies(deadline)) { - schedule_timeout_uninterruptible(1); - if ((NCR5380_read(reg1) & bit1) == val1) - return 0; - if ((NCR5380_read(reg2) & bit2) == val2) - return 0; - } - - return -ETIMEDOUT; -} - -static inline int NCR5380_poll_politely(struct Scsi_Host *instance, - int reg, int bit, int val, int wait) -{ - return NCR5380_poll_politely2(instance, reg, bit, val, - reg, bit, val, wait); -} - -#if NDEBUG -static struct { - unsigned char mask; - const char *name; -} signals[] = { - {SR_DBP, "PARITY"}, - {SR_RST, "RST"}, - {SR_BSY, "BSY"}, - {SR_REQ, "REQ"}, - {SR_MSG, "MSG"}, - {SR_CD, "CD"}, - {SR_IO, "IO"}, - {SR_SEL, "SEL"}, - {0, NULL} -}, -basrs[] = { - {BASR_ATN, "ATN"}, - {BASR_ACK, "ACK"}, - {0, NULL} -}, -icrs[] = { - {ICR_ASSERT_RST, "ASSERT RST"}, - {ICR_ASSERT_ACK, "ASSERT ACK"}, - {ICR_ASSERT_BSY, "ASSERT BSY"}, - {ICR_ASSERT_SEL, "ASSERT SEL"}, - {ICR_ASSERT_ATN, "ASSERT ATN"}, - {ICR_ASSERT_DATA, "ASSERT DATA"}, - {0, NULL} -}, -mrs[] = { - {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, - {MR_TARGET, "MODE TARGET"}, - {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, - {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, - {MR_ENABLE_EOP_INTR, "MODE EOP INTR"}, - {MR_MONITOR_BSY, "MODE MONITOR BSY"}, - {MR_DMA_MODE, "MODE DMA"}, - {MR_ARBITRATE, "MODE ARBITRATION"}, - {0, NULL} -}; - -/** - * NCR5380_print - print scsi bus signals - * @instance: adapter state to dump - * - * Print the SCSI bus signals for debugging purposes - */ - -static void NCR5380_print(struct Scsi_Host *instance) -{ - unsigned char status, data, basr, mr, icr, i; - - data = NCR5380_read(CURRENT_SCSI_DATA_REG); - status = NCR5380_read(STATUS_REG); - mr = NCR5380_read(MODE_REG); - icr = NCR5380_read(INITIATOR_COMMAND_REG); - basr = NCR5380_read(BUS_AND_STATUS_REG); - - printk("STATUS_REG: %02x ", status); - for (i = 0; signals[i].mask; ++i) - if (status & signals[i].mask) - printk(",%s", signals[i].name); - printk("\nBASR: %02x ", basr); - for (i = 0; basrs[i].mask; ++i) - if (basr & basrs[i].mask) - printk(",%s", basrs[i].name); - printk("\nICR: %02x ", icr); - for (i = 0; icrs[i].mask; ++i) - if (icr & icrs[i].mask) - printk(",%s", icrs[i].name); - printk("\nMODE: %02x ", mr); - for (i = 0; mrs[i].mask; ++i) - if (mr & mrs[i].mask) - printk(",%s", mrs[i].name); - printk("\n"); -} - -static struct { - unsigned char value; - const char *name; -} phases[] = { - {PHASE_DATAOUT, "DATAOUT"}, - {PHASE_DATAIN, "DATAIN"}, - {PHASE_CMDOUT, "CMDOUT"}, - {PHASE_STATIN, "STATIN"}, - {PHASE_MSGOUT, "MSGOUT"}, - {PHASE_MSGIN, "MSGIN"}, - {PHASE_UNKNOWN, "UNKNOWN"} -}; - -/** - * NCR5380_print_phase - show SCSI phase - * @instance: adapter to dump - * - * Print the current SCSI phase for debugging purposes - */ - -static void NCR5380_print_phase(struct Scsi_Host *instance) -{ - unsigned char status; - int i; - - status = NCR5380_read(STATUS_REG); - if (!(status & SR_REQ)) - shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n"); - else { - for (i = 0; (phases[i].value != PHASE_UNKNOWN) && - (phases[i].value != (status & PHASE_MASK)); ++i) - ; - shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name); - } -} -#endif - -/** - * NCR58380_info - report driver and host information - * @instance: relevant scsi host instance - * - * For use as the host template info() handler. - */ - -static const char *NCR5380_info(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - return hostdata->info; -} - -static void prepare_info(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - snprintf(hostdata->info, sizeof(hostdata->info), - "%s, io_port 0x%lx, n_io_port %d, " - "base 0x%lx, irq %d, " - "can_queue %d, cmd_per_lun %d, " - "sg_tablesize %d, this_id %d, " - "flags { %s%s}, " - "options { %s} ", - instance->hostt->name, instance->io_port, instance->n_io_port, - instance->base, instance->irq, - instance->can_queue, instance->cmd_per_lun, - instance->sg_tablesize, instance->this_id, - hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "", - hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", -#ifdef DIFFERENTIAL - "DIFFERENTIAL " -#endif -#ifdef PARITY - "PARITY " -#endif -#ifdef SUPPORT_TAGS - "SUPPORT_TAGS " -#endif - ""); -} - -/** - * NCR5380_init - initialise an NCR5380 - * @instance: adapter to configure - * @flags: control flags - * - * Initializes *instance and corresponding 5380 chip, - * with flags OR'd into the initial flags value. - * - * Notes : I assume that the host, hostno, and id bits have been - * set correctly. I don't care about the irq and other fields. - * - * Returns 0 for success - */ - -static int __init NCR5380_init(struct Scsi_Host *instance, int flags) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int i; - unsigned long deadline; - - hostdata->host = instance; - hostdata->id_mask = 1 << instance->this_id; - hostdata->id_higher_mask = 0; - for (i = hostdata->id_mask; i <= 0x80; i <<= 1) - if (i > hostdata->id_mask) - hostdata->id_higher_mask |= i; - for (i = 0; i < 8; ++i) - hostdata->busy[i] = 0; -#ifdef SUPPORT_TAGS - init_tags(hostdata); -#endif - hostdata->dma_len = 0; - - spin_lock_init(&hostdata->lock); - hostdata->connected = NULL; - hostdata->sensing = NULL; - INIT_LIST_HEAD(&hostdata->autosense); - INIT_LIST_HEAD(&hostdata->unissued); - INIT_LIST_HEAD(&hostdata->disconnected); - - hostdata->flags = flags; - - INIT_WORK(&hostdata->main_task, NCR5380_main); - hostdata->work_q = alloc_workqueue("ncr5380_%d", - WQ_UNBOUND | WQ_MEM_RECLAIM, - 1, instance->host_no); - if (!hostdata->work_q) - return -ENOMEM; - - prepare_info(instance); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_write(SELECT_ENABLE_REG, 0); - - /* Calibrate register polling loop */ - i = 0; - deadline = jiffies + 1; - do { - cpu_relax(); - } while (time_is_after_jiffies(deadline)); - deadline += msecs_to_jiffies(256); - do { - NCR5380_read(STATUS_REG); - ++i; - cpu_relax(); - } while (time_is_after_jiffies(deadline)); - hostdata->accesses_per_ms = i / 256; - - return 0; -} - -/** - * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems. - * @instance: adapter to check - * - * If the system crashed, it may have crashed with a connected target and - * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the - * currently established nexus, which we know nothing about. Failing that - * do a bus reset. - * - * Note that a bus reset will cause the chip to assert IRQ. - * - * Returns 0 if successful, otherwise -ENXIO. - */ - -static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int pass; - - for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) { - switch (pass) { - case 1: - case 3: - case 5: - shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n"); - NCR5380_poll_politely(instance, - STATUS_REG, SR_BSY, 0, 5 * HZ); - break; - case 2: - shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n"); - do_abort(instance); - break; - case 4: - shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n"); - do_reset(instance); - /* Wait after a reset; the SCSI standard calls for - * 250ms, we wait 500ms to be on the safe side. - * But some Toshiba CD-ROMs need ten times that. - */ - if (hostdata->flags & FLAG_TOSHIBA_DELAY) - msleep(2500); - else - msleep(500); - break; - case 6: - shost_printk(KERN_ERR, instance, "bus locked solid\n"); - return -ENXIO; - } - } - return 0; -} - -/** - * NCR5380_exit - remove an NCR5380 - * @instance: adapter to remove - * - * Assumes that no more work can be queued (e.g. by NCR5380_intr). - */ - -static void NCR5380_exit(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - cancel_work_sync(&hostdata->main_task); - destroy_workqueue(hostdata->work_q); -} - -/** - * complete_cmd - finish processing a command and return it to the SCSI ML - * @instance: the host instance - * @cmd: command to complete - */ - -static void complete_cmd(struct Scsi_Host *instance, - struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd); - - if (hostdata->sensing == cmd) { - /* Autosense processing ends here */ - if ((cmd->result & 0xff) != SAM_STAT_GOOD) { - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - set_host_byte(cmd, DID_ERROR); - } else - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - hostdata->sensing = NULL; - } - -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#else - hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); -#endif - cmd->scsi_done(cmd); -} - -/** - * NCR5380_queue_command - queue a command - * @instance: the relevant SCSI adapter - * @cmd: SCSI command - * - * cmd is added to the per-instance issue queue, with minor - * twiddling done to the host specific fields of cmd. If the - * main coroutine is not running, it is restarted. - */ - -static int NCR5380_queue_command(struct Scsi_Host *instance, - struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - unsigned long flags; - -#if (NDEBUG & NDEBUG_NO_WRITE) - switch (cmd->cmnd[0]) { - case WRITE_6: - case WRITE_10: - shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n"); - cmd->result = (DID_ERROR << 16); - cmd->scsi_done(cmd); - return 0; - } -#endif /* (NDEBUG & NDEBUG_NO_WRITE) */ - - cmd->result = 0; - - /* - * ++roman: Just disabling the NCR interrupt isn't sufficient here, - * because also a timer int can trigger an abort or reset, which would - * alter queues and touch the lock. - */ - if (!NCR5380_acquire_dma_irq(instance)) - return SCSI_MLQUEUE_HOST_BUSY; - - spin_lock_irqsave(&hostdata->lock, flags); - - /* - * Insert the cmd into the issue queue. Note that REQUEST SENSE - * commands are added to the head of the queue since any command will - * clear the contingent allegiance condition that exists and the - * sense data is only guaranteed to be valid while the condition exists. - */ - - if (cmd->cmnd[0] == REQUEST_SENSE) - list_add(&ncmd->list, &hostdata->unissued); - else - list_add_tail(&ncmd->list, &hostdata->unissued); - - spin_unlock_irqrestore(&hostdata->lock, flags); - - dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", - cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); - - /* Kick off command processing */ - queue_work(hostdata->work_q, &hostdata->main_task); - return 0; -} - -static inline void maybe_release_dma_irq(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - /* Caller does the locking needed to set & test these data atomically */ - if (list_empty(&hostdata->disconnected) && - list_empty(&hostdata->unissued) && - list_empty(&hostdata->autosense) && - !hostdata->connected && - !hostdata->selecting) - NCR5380_release_dma_irq(instance); -} - -/** - * dequeue_next_cmd - dequeue a command for processing - * @instance: the scsi host instance - * - * Priority is given to commands on the autosense queue. These commands - * need autosense because of a CHECK CONDITION result. - * - * Returns a command pointer if a command is found for a target that is - * not already busy. Otherwise returns NULL. - */ - -static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct NCR5380_cmd *ncmd; - struct scsi_cmnd *cmd; - - if (hostdata->sensing || list_empty(&hostdata->autosense)) { - list_for_each_entry(ncmd, &hostdata->unissued, list) { - cmd = NCR5380_to_scmd(ncmd); - dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n", - cmd, scmd_id(cmd), hostdata->busy[scmd_id(cmd)], cmd->device->lun); - - if ( -#ifdef SUPPORT_TAGS - !is_lun_busy(cmd, 1) -#else - !(hostdata->busy[scmd_id(cmd)] & (1 << cmd->device->lun)) -#endif - ) { - list_del(&ncmd->list); - dsprintk(NDEBUG_QUEUES, instance, - "dequeue: removed %p from issue queue\n", cmd); - return cmd; - } - } - } else { - /* Autosense processing begins here */ - ncmd = list_first_entry(&hostdata->autosense, - struct NCR5380_cmd, list); - list_del(&ncmd->list); - cmd = NCR5380_to_scmd(ncmd); - dsprintk(NDEBUG_QUEUES, instance, - "dequeue: removed %p from autosense queue\n", cmd); - scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - hostdata->sensing = cmd; - return cmd; - } - return NULL; -} - -static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - - if (hostdata->sensing == cmd) { - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - list_add(&ncmd->list, &hostdata->autosense); - hostdata->sensing = NULL; - } else - list_add(&ncmd->list, &hostdata->unissued); -} - -/** - * NCR5380_main - NCR state machines - * - * NCR5380_main is a coroutine that runs as long as more work can - * be done on the NCR5380 host adapters in a system. Both - * NCR5380_queue_command() and NCR5380_intr() will try to start it - * in case it is not running. - */ - -static void NCR5380_main(struct work_struct *work) -{ - struct NCR5380_hostdata *hostdata = - container_of(work, struct NCR5380_hostdata, main_task); - struct Scsi_Host *instance = hostdata->host; - int done; - - /* - * ++roman: Just disabling the NCR interrupt isn't sufficient here, - * because also a timer int can trigger an abort or reset, which can - * alter queues and touch the Falcon lock. - */ - - do { - done = 1; - - spin_lock_irq(&hostdata->lock); - while (!hostdata->connected && !hostdata->selecting) { - struct scsi_cmnd *cmd = dequeue_next_cmd(instance); - - if (!cmd) - break; - - dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd); - - /* - * Attempt to establish an I_T_L nexus here. - * On success, instance->hostdata->connected is set. - * On failure, we must add the command back to the - * issue queue so we can keep trying. - */ - /* - * REQUEST SENSE commands are issued without tagged - * queueing, even on SCSI-II devices because the - * contingent allegiance condition exists for the - * entire unit. - */ - /* ++roman: ...and the standard also requires that - * REQUEST SENSE command are untagged. - */ - -#ifdef SUPPORT_TAGS - cmd_get_tag(cmd, cmd->cmnd[0] != REQUEST_SENSE); -#endif - if (!NCR5380_select(instance, cmd)) { - dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); - maybe_release_dma_irq(instance); - } else { - dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, - "main: select failed, returning %p to queue\n", cmd); - requeue_cmd(instance, cmd); -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#endif - } - } - if (hostdata->connected && !hostdata->dma_len) { - dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); - NCR5380_information_transfer(instance); - done = 0; - } - spin_unlock_irq(&hostdata->lock); - if (!done) - cond_resched(); - } while (!done); -} - - -/* - * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) - * - * Purpose : Called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). - * - * Inputs : instance - this instance of the NCR5380. - */ - -static void NCR5380_dma_complete(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int transferred; - unsigned char **data; - int *count; - int saved_data = 0, overrun = 0; - unsigned char p; - - if (hostdata->read_overruns) { - p = hostdata->connected->SCp.phase; - if (p & SR_IO) { - udelay(10); - if ((NCR5380_read(BUS_AND_STATUS_REG) & - (BASR_PHASE_MATCH|BASR_ACK)) == - (BASR_PHASE_MATCH|BASR_ACK)) { - saved_data = NCR5380_read(INPUT_DATA_REG); - overrun = 1; - dsprintk(NDEBUG_DMA, instance, "read overrun handled\n"); - } - } - } - -#if defined(CONFIG_SUN3) - if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) { - pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n", - instance->host_no); - BUG(); - } - - /* make sure we're not stuck in a data phase */ - if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == - (BASR_PHASE_MATCH | BASR_ACK)) { - pr_err("scsi%d: BASR %02x\n", instance->host_no, - NCR5380_read(BUS_AND_STATUS_REG)); - pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n", - instance->host_no); - BUG(); - } -#endif - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - transferred = hostdata->dma_len - NCR5380_dma_residual(instance); - hostdata->dma_len = 0; - - data = (unsigned char **)&hostdata->connected->SCp.ptr; - count = &hostdata->connected->SCp.this_residual; - *data += transferred; - *count -= transferred; - - if (hostdata->read_overruns) { - int cnt, toPIO; - - if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) { - cnt = toPIO = hostdata->read_overruns; - if (overrun) { - dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n"); - *(*data)++ = saved_data; - (*count)--; - cnt--; - toPIO--; - } - dprintk(NDEBUG_DMA, "Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data); - NCR5380_transfer_pio(instance, &p, &cnt, data); - *count -= toPIO - cnt; - } - } -} - - -/** - * NCR5380_intr - generic NCR5380 irq handler - * @irq: interrupt number - * @dev_id: device info - * - * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses - * from the disconnected queue, and restarting NCR5380_main() - * as required. - * - * The chip can assert IRQ in any of six different conditions. The IRQ flag - * is then cleared by reading the Reset Parity/Interrupt Register (RPIR). - * Three of these six conditions are latched in the Bus and Status Register: - * - End of DMA (cleared by ending DMA Mode) - * - Parity error (cleared by reading RPIR) - * - Loss of BSY (cleared by reading RPIR) - * Two conditions have flag bits that are not latched: - * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode) - * - Bus reset (non-maskable) - * The remaining condition has no flag bit at all: - * - Selection/reselection - * - * Hence, establishing the cause(s) of any interrupt is partly guesswork. - * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor - * claimed that "the design of the [DP8490] interrupt logic ensures - * interrupts will not be lost (they can be on the DP5380)." - * The L5380/53C80 datasheet from LOGIC Devices has more details. - * - * Checking for bus reset by reading RST is futile because of interrupt - * latency, but a bus reset will reset chip logic. Checking for parity error - * is unnecessary because that interrupt is never enabled. A Loss of BSY - * condition will clear DMA Mode. We can tell when this occurs because the - * the Busy Monitor interrupt is enabled together with DMA Mode. - */ - -static irqreturn_t NCR5380_intr(int irq, void *dev_id) -{ - struct Scsi_Host *instance = dev_id; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int handled = 0; - unsigned char basr; - unsigned long flags; - - spin_lock_irqsave(&hostdata->lock, flags); - - basr = NCR5380_read(BUS_AND_STATUS_REG); - if (basr & BASR_IRQ) { - unsigned char mr = NCR5380_read(MODE_REG); - unsigned char sr = NCR5380_read(STATUS_REG); - - dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", - irq, basr, sr, mr); - - if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { - /* Probably End of DMA, Phase Mismatch or Loss of BSY. - * We ack IRQ after clearing Mode Register. Workarounds - * for End of DMA errata need to happen in DMA Mode. - */ - - dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); - - if (hostdata->connected) { - NCR5380_dma_complete(instance); - queue_work(hostdata->work_q, &hostdata->main_task); - } else { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } - } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && - (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { - /* Probably reselected */ - NCR5380_write(SELECT_ENABLE_REG, 0); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - dsprintk(NDEBUG_INTR, instance, "interrupt with SEL and IO\n"); - - if (!hostdata->connected) { - NCR5380_reselect(instance); - queue_work(hostdata->work_q, &hostdata->main_task); - } - if (!hostdata->connected) - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - } else { - /* Probably Bus Reset */ - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - } - handled = 1; - } else { - shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - } - - spin_unlock_irqrestore(&hostdata->lock, flags); - - return IRQ_RETVAL(handled); -} - -/* - * Function : int NCR5380_select(struct Scsi_Host *instance, - * struct scsi_cmnd *cmd) - * - * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, - * including ARBITRATION, SELECTION, and initial message out for - * IDENTIFY and queue messages. - * - * Inputs : instance - instantiation of the 5380 driver on which this - * target lives, cmd - SCSI command to execute. - * - * Returns cmd if selection failed but should be retried, - * NULL if selection failed and should not be retried, or - * NULL if selection succeeded (hostdata->connected == cmd). - * - * Side effects : - * If bus busy, arbitration failed, etc, NCR5380_select() will exit - * with registers as they should have been on entry - ie - * SELECT_ENABLE will be set appropriately, the NCR5380 - * will cease to drive any SCSI bus signals. - * - * If successful : I_T_L or I_T_L_Q nexus will be established, - * instance->connected will be set to cmd. - * SELECT interrupt will be disabled. - * - * If failed (no target) : cmd->scsi_done() will be called, and the - * cmd->result host byte set to DID_BAD_TARGET. - */ - -static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, - struct scsi_cmnd *cmd) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char tmp[3], phase; - unsigned char *data; - int len; - int err; - - NCR5380_dprint(NDEBUG_ARBITRATION, instance); - dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n", - instance->this_id); - - /* - * Arbitration and selection phases are slow and involve dropping the - * lock, so we have to watch out for EH. An exception handler may - * change 'selecting' to NULL. This function will then return NULL - * so that the caller will forget about 'cmd'. (During information - * transfer phases, EH may change 'connected' to NULL.) - */ - hostdata->selecting = cmd; - - /* - * Set the phase bits to 0, otherwise the NCR5380 won't drive the - * data bus during SELECTION. - */ - - NCR5380_write(TARGET_COMMAND_REG, 0); - - /* - * Start arbitration. - */ - - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); - NCR5380_write(MODE_REG, MR_ARBITRATE); - - /* The chip now waits for BUS FREE phase. Then after the 800 ns - * Bus Free Delay, arbitration will begin. - */ - - spin_unlock_irq(&hostdata->lock); - err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0, - INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, - ICR_ARBITRATION_PROGRESS, HZ); - spin_lock_irq(&hostdata->lock); - if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { - /* Reselection interrupt */ - goto out; - } - if (!hostdata->selecting) { - /* Command was aborted */ - NCR5380_write(MODE_REG, MR_BASE); - goto out; - } - if (err < 0) { - NCR5380_write(MODE_REG, MR_BASE); - shost_printk(KERN_ERR, instance, - "select: arbitration timeout\n"); - goto out; - } - spin_unlock_irq(&hostdata->lock); - - /* The SCSI-2 arbitration delay is 2.4 us */ - udelay(3); - - /* Check for lost arbitration */ - if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || - (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || - (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { - NCR5380_write(MODE_REG, MR_BASE); - dsprintk(NDEBUG_ARBITRATION, instance, "lost arbitration, deasserting MR_ARBITRATE\n"); - spin_lock_irq(&hostdata->lock); - goto out; - } - - /* After/during arbitration, BSY should be asserted. - * IBM DPES-31080 Version S31Q works now - * Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) - */ - NCR5380_write(INITIATOR_COMMAND_REG, - ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); - - /* - * Again, bus clear + bus settle time is 1.2us, however, this is - * a minimum so we'll udelay ceil(1.2) - */ - - if (hostdata->flags & FLAG_TOSHIBA_DELAY) - udelay(15); - else - udelay(2); - - spin_lock_irq(&hostdata->lock); - - /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ - if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) - goto out; - - if (!hostdata->selecting) { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - goto out; - } - - dsprintk(NDEBUG_ARBITRATION, instance, "won arbitration\n"); - - /* - * Now that we have won arbitration, start Selection process, asserting - * the host and target ID's on the SCSI bus. - */ - - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask | (1 << scmd_id(cmd))); - - /* - * Raise ATN while SEL is true before BSY goes false from arbitration, - * since this is the only way to guarantee that we'll get a MESSAGE OUT - * phase immediately after selection. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL); - NCR5380_write(MODE_REG, MR_BASE); - - /* - * Reselect interrupts must be turned off prior to the dropping of BSY, - * otherwise we will trigger an interrupt. - */ - NCR5380_write(SELECT_ENABLE_REG, 0); - - spin_unlock_irq(&hostdata->lock); - - /* - * The initiator shall then wait at least two deskew delays and release - * the BSY signal. - */ - udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ - - /* Reset BSY */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | - ICR_ASSERT_ATN | ICR_ASSERT_SEL); - - /* - * Something weird happens when we cease to drive BSY - looks - * like the board/chip is letting us do another read before the - * appropriate propagation delay has expired, and we're confusing - * a BSY signal from ourselves as the target's response to SELECTION. - * - * A small delay (the 'C++' frontend breaks the pipeline with an - * unnecessary jump, making it work on my 386-33/Trantor T128, the - * tighter 'C' code breaks and requires this) solves the problem - - * the 1 us delay is arbitrary, and only used because this delay will - * be the same on other platforms and since it works here, it should - * work there. - * - * wingel suggests that this could be due to failing to wait - * one deskew delay. - */ - - udelay(1); - - dsprintk(NDEBUG_SELECTION, instance, "selecting target %d\n", scmd_id(cmd)); - - /* - * The SCSI specification calls for a 250 ms timeout for the actual - * selection. - */ - - err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY, - msecs_to_jiffies(250)); - - if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { - spin_lock_irq(&hostdata->lock); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_reselect(instance); - if (!hostdata->connected) - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n"); - goto out; - } - - if (err < 0) { - spin_lock_irq(&hostdata->lock); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* Can't touch cmd if it has been reclaimed by the scsi ML */ - if (hostdata->selecting) { - cmd->result = DID_BAD_TARGET << 16; - complete_cmd(instance, cmd); - dsprintk(NDEBUG_SELECTION, instance, "target did not respond within 250ms\n"); - cmd = NULL; - } - goto out; - } - - /* - * No less than two deskew delays after the initiator detects the - * BSY signal is true, it shall release the SEL signal and may - * change the DATA BUS. -wingel - */ - - udelay(1); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - - /* - * Since we followed the SCSI spec, and raised ATN while SEL - * was true but before BSY was false during selection, the information - * transfer phase should be a MESSAGE OUT phase so that we can send the - * IDENTIFY message. - * - * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG - * message (2 bytes) with a tag ID that we increment with every command - * until it wraps back to 0. - * - * XXX - it turns out that there are some broken SCSI-II devices, - * which claim to support tagged queuing but fail when more than - * some number of commands are issued at once. - */ - - /* Wait for start of REQ/ACK handshake */ - - err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); - spin_lock_irq(&hostdata->lock); - if (err < 0) { - shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - goto out; - } - if (!hostdata->selecting) { - do_abort(instance); - goto out; - } - - dsprintk(NDEBUG_SELECTION, instance, "target %d selected, going into MESSAGE OUT phase.\n", - scmd_id(cmd)); - tmp[0] = IDENTIFY(1, cmd->device->lun); - -#ifdef SUPPORT_TAGS - if (cmd->tag != TAG_NONE) { - tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG; - tmp[2] = cmd->tag; - len = 3; - } else - len = 1; -#else - len = 1; - cmd->tag = 0; -#endif /* SUPPORT_TAGS */ - - /* Send message(s) */ - data = tmp; - phase = PHASE_MSGOUT; - NCR5380_transfer_pio(instance, &phase, &len, &data); - dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n"); - /* XXX need to handle errors here */ - - hostdata->connected = cmd; -#ifndef SUPPORT_TAGS - hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; -#endif -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_INTR; -#endif - - initialize_SCp(cmd); - - cmd = NULL; - -out: - if (!hostdata->selecting) - return NULL; - hostdata->selecting = NULL; - return cmd; -} - -/* - * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) - * - * Purpose : transfers data in given phase using polled I/O - * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. - * - * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes are transferred or exit - * is in same phase. - * - * Also, *phase, *count, *data are modified in place. - * - * XXX Note : handling for bus free may be useful. - */ - -/* - * Note : this code is not as quick as it could be, however it - * IS 100% reliable, and for the actual data transfer where speed - * counts, we will always do a pseudo DMA or DMA transfer. - */ - -static int NCR5380_transfer_pio(struct Scsi_Host *instance, - unsigned char *phase, int *count, - unsigned char **data) -{ - unsigned char p = *phase, tmp; - int c = *count; - unsigned char *d = *data; - - /* - * The NCR5380 chip will only drive the SCSI bus when the - * phase specified in the appropriate bits of the TARGET COMMAND - * REGISTER match the STATUS REGISTER - */ - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - - do { - /* - * Wait for assertion of REQ, after which the phase bits will be - * valid - */ - - if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) - break; - - dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n"); - - /* Check for phase mismatch */ - if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) { - dsprintk(NDEBUG_PIO, instance, "phase mismatch\n"); - NCR5380_dprint_phase(NDEBUG_PIO, instance); - break; - } - - /* Do actual transfer from SCSI bus to / from memory */ - if (!(p & SR_IO)) - NCR5380_write(OUTPUT_DATA_REG, *d); - else - *d = NCR5380_read(CURRENT_SCSI_DATA_REG); - - ++d; - - /* - * The SCSI standard suggests that in MSGOUT phase, the initiator - * should drop ATN on the last byte of the message phase - * after REQ has been asserted for the handshake but before - * the initiator raises ACK. - */ - - if (!(p & SR_IO)) { - if (!((p & SR_MSG) && c > 1)) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); - NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ACK); - } else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN); - NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - } - } else { - NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); - } - - if (NCR5380_poll_politely(instance, - STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) - break; - - dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); - -/* - * We have several special cases to consider during REQ/ACK handshaking : - * 1. We were in MSGOUT phase, and we are on the last byte of the - * message. ATN must be dropped as ACK is dropped. - * - * 2. We are in a MSGIN phase, and we are on the last byte of the - * message. We must exit with ACK asserted, so that the calling - * code may raise ATN before dropping ACK to reject the message. - * - * 3. ACK and ATN are clear and the target may proceed as normal. - */ - if (!(p == PHASE_MSGIN && c == 1)) { - if (p == PHASE_MSGOUT && c > 1) - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - else - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - } - } while (--c); - - dsprintk(NDEBUG_PIO, instance, "residual %d\n", c); - - *count = c; - *data = d; - tmp = NCR5380_read(STATUS_REG); - /* The phase read from the bus is valid if either REQ is (already) - * asserted or if ACK hasn't been released yet. The latter applies if - * we're in MSG IN, DATA IN or STATUS and all bytes have been received. - */ - if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0)) - *phase = tmp & PHASE_MASK; - else - *phase = PHASE_UNKNOWN; - - if (!c || (*phase == p)) - return 0; - else - return -1; -} - -/** - * do_reset - issue a reset command - * @instance: adapter to reset - * - * Issue a reset sequence to the NCR5380 and try and get the bus - * back into sane shape. - * - * This clears the reset interrupt flag because there may be no handler for - * it. When the driver is initialized, the NCR5380_intr() handler has not yet - * been installed. And when in EH we may have released the ST DMA interrupt. - */ - -static void do_reset(struct Scsi_Host *instance) -{ - unsigned long flags; - - local_irq_save(flags); - NCR5380_write(TARGET_COMMAND_REG, - PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK)); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); - udelay(50); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); - local_irq_restore(flags); -} - -/** - * do_abort - abort the currently established nexus by going to - * MESSAGE OUT phase and sending an ABORT message. - * @instance: relevant scsi host instance - * - * Returns 0 on success, -1 on failure. - */ - -static int do_abort(struct Scsi_Host *instance) -{ - unsigned char *msgptr, phase, tmp; - int len; - int rc; - - /* Request message out phase */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - - /* - * Wait for the target to indicate a valid phase by asserting - * REQ. Once this happens, we'll have either a MSGOUT phase - * and can immediately send the ABORT message, or we'll have some - * other phase and will have to source/sink data. - * - * We really don't care what value was on the bus or what value - * the target sees, so we just handshake. - */ - - rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ); - if (rc < 0) - goto timeout; - - tmp = NCR5380_read(STATUS_REG) & PHASE_MASK; - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - - if (tmp != PHASE_MSGOUT) { - NCR5380_write(INITIATOR_COMMAND_REG, - ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); - if (rc < 0) - goto timeout; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - } - - tmp = ABORT; - msgptr = &tmp; - len = 1; - phase = PHASE_MSGOUT; - NCR5380_transfer_pio(instance, &phase, &len, &msgptr); - - /* - * If we got here, and the command completed successfully, - * we're about to go into bus free state. - */ - - return len ? -1 : 0; - -timeout: - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - return -1; -} - - -/* - * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) - * - * Purpose : transfers data in given phase using either real - * or pseudo DMA. - * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. - * - * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transferred or exit - * is in same phase. - * - * Also, *phase, *count, *data are modified in place. - */ - - -static int NCR5380_transfer_dma(struct Scsi_Host *instance, - unsigned char *phase, int *count, - unsigned char **data) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - register int c = *count; - register unsigned char p = *phase; - -#if defined(CONFIG_SUN3) - /* sanity check */ - if (!sun3_dma_setup_done) { - pr_err("scsi%d: transfer_dma without setup!\n", - instance->host_no); - BUG(); - } - hostdata->dma_len = c; - - dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", - (p & SR_IO) ? "receive" : "send", c, *data); - - /* netbsd turns off ints here, why not be safe and do it too */ - - /* send start chain */ - sun3scsi_dma_start(c, *data); - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); - if (p & SR_IO) { - NCR5380_write(INITIATOR_COMMAND_REG, 0); - NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); - } else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_DATA); - NCR5380_write(START_DMA_SEND_REG, 0); - } - -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - - sun3_dma_active = 1; - -#else /* !defined(CONFIG_SUN3) */ - register unsigned char *d = *data; - unsigned char tmp; - - if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { - *phase = tmp; - return -1; - } - - if (hostdata->read_overruns && (p & SR_IO)) - c -= hostdata->read_overruns; - - dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", - (p & SR_IO) ? "receive" : "send", c, d); - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | - MR_ENABLE_EOP_INTR); - - if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) { - /* On the Medusa, it is a must to initialize the DMA before - * starting the NCR. This is also the cleaner way for the TT. - */ - hostdata->dma_len = (p & SR_IO) ? - NCR5380_dma_read_setup(instance, d, c) : - NCR5380_dma_write_setup(instance, d, c); - } - - if (p & SR_IO) - NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); - else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); - NCR5380_write(START_DMA_SEND_REG, 0); - } - - if (hostdata->flags & FLAG_LATE_DMA_SETUP) { - /* On the Falcon, the DMA setup must be done after the last */ - /* NCR access, else the DMA setup gets trashed! - */ - hostdata->dma_len = (p & SR_IO) ? - NCR5380_dma_read_setup(instance, d, c) : - NCR5380_dma_write_setup(instance, d, c); - } -#endif /* !defined(CONFIG_SUN3) */ - - return 0; -} - -/* - * Function : NCR5380_information_transfer (struct Scsi_Host *instance) - * - * Purpose : run through the various SCSI phases and do as the target - * directs us to. Operates on the currently connected command, - * instance->connected. - * - * Inputs : instance, instance for which we are doing commands - * - * Side effects : SCSI things happen, the disconnected queue will be - * modified if a command disconnects, *instance->connected will - * change. - * - * XXX Note : we need to watch for bus free or a reset condition here - * to recover from an unexpected bus free condition. - */ - -static void NCR5380_information_transfer(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char msgout = NOP; - int sink = 0; - int len; - int transfersize; - unsigned char *data; - unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; - struct scsi_cmnd *cmd; - -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_INTR; -#endif - - while ((cmd = hostdata->connected)) { - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - - tmp = NCR5380_read(STATUS_REG); - /* We only have a valid SCSI phase when REQ is asserted */ - if (tmp & SR_REQ) { - phase = (tmp & PHASE_MASK); - if (phase != old_phase) { - old_phase = phase; - NCR5380_dprint_phase(NDEBUG_INFORMATION, instance); - } -#if defined(CONFIG_SUN3) - if (phase == PHASE_CMDOUT) { - void *d; - unsigned long count; - - if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { - count = cmd->SCp.buffer->length; - d = sg_virt(cmd->SCp.buffer); - } else { - count = cmd->SCp.this_residual; - d = cmd->SCp.ptr; - } - /* this command setup for dma yet? */ - if (sun3_dma_setup_done != cmd && - sun3scsi_dma_xfer_len(count, cmd) > 0) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(cmd->request)); - sun3_dma_setup_done = cmd; - } -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_INTR; -#endif - } -#endif /* CONFIG_SUN3 */ - - if (sink && (phase != PHASE_MSGOUT)) { - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | - ICR_ASSERT_ACK); - while (NCR5380_read(STATUS_REG) & SR_REQ) - ; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_ATN); - sink = 0; - continue; - } - - switch (phase) { - case PHASE_DATAOUT: -#if (NDEBUG & NDEBUG_NO_DATAOUT) - shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n"); - sink = 1; - do_abort(instance); - cmd->result = DID_ERROR << 16; - complete_cmd(instance, cmd); - hostdata->connected = NULL; - return; -#endif - case PHASE_DATAIN: - /* - * If there is no room left in the current buffer in the - * scatter-gather list, move onto the next one. - */ - - if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { - ++cmd->SCp.buffer; - --cmd->SCp.buffers_residual; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); - merge_contiguous_buffers(cmd); - dsprintk(NDEBUG_INFORMATION, instance, "%d bytes and %d buffers left\n", - cmd->SCp.this_residual, - cmd->SCp.buffers_residual); - } - - /* - * The preferred transfer method is going to be - * PSEUDO-DMA for systems that are strictly PIO, - * since we can let the hardware do the handshaking. - * - * For this to work, we need to know the transfersize - * ahead of time, since the pseudo-DMA code will sit - * in an unconditional loop. - */ - -#if !defined(CONFIG_SUN3) - transfersize = 0; - if (!cmd->device->borken) -#endif - transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); - - if (transfersize > 0) { - len = transfersize; - cmd->SCp.phase = phase; - if (NCR5380_transfer_dma(instance, &phase, - &len, (unsigned char **)&cmd->SCp.ptr)) { - /* - * If the watchdog timer fires, all future - * accesses to this device will use the - * polled-IO. - */ - scmd_printk(KERN_INFO, cmd, - "switching to slow handshake\n"); - cmd->device->borken = 1; - sink = 1; - do_abort(instance); - cmd->result = DID_ERROR << 16; - /* XXX - need to source or sink data here, as appropriate */ - } else - return; - } else { - /* Break up transfer into 3 ms chunks, - * presuming 6 accesses per handshake. - */ - transfersize = min((unsigned long)cmd->SCp.this_residual, - hostdata->accesses_per_ms / 2); - len = transfersize; - NCR5380_transfer_pio(instance, &phase, &len, - (unsigned char **)&cmd->SCp.ptr); - cmd->SCp.this_residual -= transfersize - len; - } -#if defined(CONFIG_SUN3) - /* if we had intended to dma that command clear it */ - if (sun3_dma_setup_done == cmd) - sun3_dma_setup_done = NULL; -#endif - return; - case PHASE_MSGIN: - len = 1; - data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); - cmd->SCp.Message = tmp; - - switch (tmp) { - case ABORT: - case COMMAND_COMPLETE: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dsprintk(NDEBUG_QUEUES, instance, - "COMMAND COMPLETE %p target %d lun %llu\n", - cmd, scmd_id(cmd), cmd->device->lun); - - hostdata->connected = NULL; -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); - if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { - u8 lun = cmd->device->lun; - struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; - - dsprintk(NDEBUG_TAGS, instance, - "QUEUE_FULL %p target %d lun %d nr_allocated %d\n", - cmd, scmd_id(cmd), lun, ta->nr_allocated); - if (ta->queue_size > ta->nr_allocated) - ta->queue_size = ta->nr_allocated; - } -#endif - - cmd->result &= ~0xffff; - cmd->result |= cmd->SCp.Status; - cmd->result |= cmd->SCp.Message << 8; - - if (cmd->cmnd[0] == REQUEST_SENSE) - complete_cmd(instance, cmd); - else { - if (cmd->SCp.Status == SAM_STAT_CHECK_CONDITION || - cmd->SCp.Status == SAM_STAT_COMMAND_TERMINATED) { - dsprintk(NDEBUG_QUEUES, instance, "autosense: adding cmd %p to tail of autosense queue\n", - cmd); - list_add_tail(&ncmd->list, - &hostdata->autosense); - } else - complete_cmd(instance, cmd); - } - - /* - * Restore phase bits to 0 so an interrupted selection, - * arbitration can resume. - */ - NCR5380_write(TARGET_COMMAND_REG, 0); - - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - - maybe_release_dma_irq(instance); - return; - case MESSAGE_REJECT: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - switch (hostdata->last_message) { - case HEAD_OF_QUEUE_TAG: - case ORDERED_QUEUE_TAG: - case SIMPLE_QUEUE_TAG: - /* The target obviously doesn't support tagged - * queuing, even though it announced this ability in - * its INQUIRY data ?!? (maybe only this LUN?) Ok, - * clear 'tagged_supported' and lock the LUN, since - * the command is treated as untagged further on. - */ - cmd->device->tagged_supported = 0; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); - cmd->tag = TAG_NONE; - dsprintk(NDEBUG_TAGS, instance, "target %d lun %llu rejected QUEUE_TAG message; tagged queuing disabled\n", - scmd_id(cmd), cmd->device->lun); - break; - } - break; - case DISCONNECT: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - hostdata->connected = NULL; - list_add(&ncmd->list, &hostdata->disconnected); - dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, - instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", - cmd, scmd_id(cmd), cmd->device->lun); - - /* - * Restore phase bits to 0 so an interrupted selection, - * arbitration can resume. - */ - NCR5380_write(TARGET_COMMAND_REG, 0); - - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); -#ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; -#endif - return; - /* - * The SCSI data pointer is *IMPLICITLY* saved on a disconnect - * operation, in violation of the SCSI spec so we can safely - * ignore SAVE/RESTORE pointers calls. - * - * Unfortunately, some disks violate the SCSI spec and - * don't issue the required SAVE_POINTERS message before - * disconnecting, and we have to break spec to remain - * compatible. - */ - case SAVE_POINTERS: - case RESTORE_POINTERS: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - break; - case EXTENDED_MESSAGE: - /* - * Start the message buffer with the EXTENDED_MESSAGE - * byte, since spi_print_msg() wants the whole thing. - */ - extended_msg[0] = EXTENDED_MESSAGE; - /* Accept first byte by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - spin_unlock_irq(&hostdata->lock); - - dsprintk(NDEBUG_EXTENDED, instance, "receiving extended message\n"); - - len = 2; - data = extended_msg + 1; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); - dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n", - (int)extended_msg[1], - (int)extended_msg[2]); - - if (!len && extended_msg[1] > 0 && - extended_msg[1] <= sizeof(extended_msg) - 2) { - /* Accept third byte by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - len = extended_msg[1] - 1; - data = extended_msg + 3; - phase = PHASE_MSGIN; - - NCR5380_transfer_pio(instance, &phase, &len, &data); - dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n", - len); - - switch (extended_msg[2]) { - case EXTENDED_SDTR: - case EXTENDED_WDTR: - case EXTENDED_MODIFY_DATA_POINTER: - case EXTENDED_EXTENDED_IDENTIFY: - tmp = 0; - } - } else if (len) { - shost_printk(KERN_ERR, instance, "error receiving extended message\n"); - tmp = 0; - } else { - shost_printk(KERN_NOTICE, instance, "extended message code %02x length %d is too long\n", - extended_msg[2], extended_msg[1]); - tmp = 0; - } - - spin_lock_irq(&hostdata->lock); - if (!hostdata->connected) - return; - - /* Fall through to reject message */ - - /* - * If we get something weird that we aren't expecting, - * reject it. - */ - default: - if (!tmp) { - shost_printk(KERN_ERR, instance, "rejecting message "); - spi_print_msg(extended_msg); - printk("\n"); - } else if (tmp != EXTENDED_MESSAGE) - scmd_printk(KERN_INFO, cmd, - "rejecting unknown message %02x\n", - tmp); - else - scmd_printk(KERN_INFO, cmd, - "rejecting unknown extended message code %02x, length %d\n", - extended_msg[1], extended_msg[0]); - - msgout = MESSAGE_REJECT; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - break; - } /* switch (tmp) */ - break; - case PHASE_MSGOUT: - len = 1; - data = &msgout; - hostdata->last_message = msgout; - NCR5380_transfer_pio(instance, &phase, &len, &data); - if (msgout == ABORT) { - hostdata->connected = NULL; - cmd->result = DID_ERROR << 16; - complete_cmd(instance, cmd); - maybe_release_dma_irq(instance); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return; - } - msgout = NOP; - break; - case PHASE_CMDOUT: - len = cmd->cmd_len; - data = cmd->cmnd; - /* - * XXX for performance reasons, on machines with a - * PSEUDO-DMA architecture we should probably - * use the dma transfer function. - */ - NCR5380_transfer_pio(instance, &phase, &len, &data); - break; - case PHASE_STATIN: - len = 1; - data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); - cmd->SCp.Status = tmp; - break; - default: - shost_printk(KERN_ERR, instance, "unknown phase\n"); - NCR5380_dprint(NDEBUG_ANY, instance); - } /* switch(phase) */ - } else { - spin_unlock_irq(&hostdata->lock); - NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); - spin_lock_irq(&hostdata->lock); - } - } -} - -/* - * Function : void NCR5380_reselect (struct Scsi_Host *instance) - * - * Purpose : does reselection, initializing the instance->connected - * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q - * nexus has been reestablished, - * - * Inputs : instance - this instance of the NCR5380. - */ - - -/* it might eventually prove necessary to do a dma setup on - reselection, but it doesn't seem to be needed now -- sam */ - -static void NCR5380_reselect(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char target_mask; - unsigned char lun; -#ifdef SUPPORT_TAGS - unsigned char tag; -#endif - unsigned char msg[3]; - int __maybe_unused len; - unsigned char __maybe_unused *data, __maybe_unused phase; - struct NCR5380_cmd *ncmd; - struct scsi_cmnd *tmp; - - /* - * Disable arbitration, etc. since the host adapter obviously - * lost, and tell an interrupted NCR5380_select() to restart. - */ - - NCR5380_write(MODE_REG, MR_BASE); - - target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); - - dsprintk(NDEBUG_RESELECTION, instance, "reselect\n"); - - /* - * At this point, we have detected that our SCSI ID is on the bus, - * SEL is true and BSY was false for at least one bus settle delay - * (400 ns). - * - * We must assert BSY ourselves, until the target drops the SEL - * signal. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); - if (NCR5380_poll_politely(instance, - STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - return; - } - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - /* - * Wait for target to go into MSGIN. - */ - - if (NCR5380_poll_politely(instance, - STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) { - do_abort(instance); - return; - } - -#if defined(CONFIG_SUN3) - /* acknowledge toggle to MSGIN */ - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN)); - - /* peek at the byte without really hitting the bus */ - msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG); -#else - len = 1; - data = msg; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); - - if (len) { - do_abort(instance); - return; - } -#endif - - if (!(msg[0] & 0x80)) { - shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); - spi_print_msg(msg); - printk("\n"); - do_abort(instance); - return; - } - lun = msg[0] & 0x07; - -#if defined(SUPPORT_TAGS) && !defined(CONFIG_SUN3) - /* If the phase is still MSGIN, the target wants to send some more - * messages. In case it supports tagged queuing, this is probably a - * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus. - */ - tag = TAG_NONE; - if (phase == PHASE_MSGIN && (hostdata->flags & FLAG_TAGGED_QUEUING)) { - /* Accept previous IDENTIFY message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - len = 2; - data = msg + 1; - if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && - msg[1] == SIMPLE_QUEUE_TAG) - tag = msg[2]; - dsprintk(NDEBUG_TAGS, instance, "reselect: target mask %02x, lun %d sent tag %d\n", - target_mask, lun, tag); - } -#endif - - /* - * Find the command corresponding to the I_T_L or I_T_L_Q nexus we - * just reestablished, and remove it from the disconnected queue. - */ - - tmp = NULL; - list_for_each_entry(ncmd, &hostdata->disconnected, list) { - struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - - if (target_mask == (1 << scmd_id(cmd)) && - lun == (u8)cmd->device->lun -#ifdef SUPPORT_TAGS - && (tag == cmd->tag) -#endif - ) { - list_del(&ncmd->list); - tmp = cmd; - break; - } - } - - if (tmp) { - dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance, - "reselect: removed %p from disconnected queue\n", tmp); - } else { - -#ifdef SUPPORT_TAGS - shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d tag %d not in disconnected queue.\n", - target_mask, lun, tag); -#else - shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n", - target_mask, lun); -#endif - /* - * Since we have an established nexus that we can't do anything - * with, we must abort it. - */ - do_abort(instance); - return; - } - -#if defined(CONFIG_SUN3) - /* engage dma setup for the command we just saw */ - { - void *d; - unsigned long count; - - if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) { - count = tmp->SCp.buffer->length; - d = sg_virt(tmp->SCp.buffer); - } else { - count = tmp->SCp.this_residual; - d = tmp->SCp.ptr; - } - /* setup this command for dma if not already */ - if (sun3_dma_setup_done != tmp && - sun3scsi_dma_xfer_len(count, tmp) > 0) { - sun3scsi_dma_setup(instance, d, count, - rq_data_dir(tmp->request)); - sun3_dma_setup_done = tmp; - } - } - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); -#endif - - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - -#if defined(SUPPORT_TAGS) && defined(CONFIG_SUN3) - /* If the phase is still MSGIN, the target wants to send some more - * messages. In case it supports tagged queuing, this is probably a - * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus. - */ - tag = TAG_NONE; - if (phase == PHASE_MSGIN && setup_use_tagged_queuing) { - /* Accept previous IDENTIFY message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - len = 2; - data = msg + 1; - if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && - msg[1] == SIMPLE_QUEUE_TAG) - tag = msg[2]; - dsprintk(NDEBUG_TAGS, instance, "reselect: target mask %02x, lun %d sent tag %d\n" - target_mask, lun, tag); - } -#endif - - hostdata->connected = tmp; - dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n", - scmd_id(tmp), tmp->device->lun, tmp->tag); -} - - -/** - * list_find_cmd - test for presence of a command in a linked list - * @haystack: list of commands - * @needle: command to search for - */ - -static bool list_find_cmd(struct list_head *haystack, - struct scsi_cmnd *needle) -{ - struct NCR5380_cmd *ncmd; - - list_for_each_entry(ncmd, haystack, list) - if (NCR5380_to_scmd(ncmd) == needle) - return true; - return false; -} - -/** - * list_remove_cmd - remove a command from linked list - * @haystack: list of commands - * @needle: command to remove - */ - -static bool list_del_cmd(struct list_head *haystack, - struct scsi_cmnd *needle) -{ - if (list_find_cmd(haystack, needle)) { - struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle); - - list_del(&ncmd->list); - return true; - } - return false; -} - -/** - * NCR5380_abort - scsi host eh_abort_handler() method - * @cmd: the command to be aborted - * - * Try to abort a given command by removing it from queues and/or sending - * the target an abort message. This may not succeed in causing a target - * to abort the command. Nonetheless, the low-level driver must forget about - * the command because the mid-layer reclaims it and it may be re-issued. - * - * The normal path taken by a command is as follows. For EH we trace this - * same path to locate and abort the command. - * - * unissued -> selecting -> [unissued -> selecting ->]... connected -> - * [disconnected -> connected ->]... - * [autosense -> connected ->] done - * - * If cmd was not found at all then presumably it has already been completed, - * in which case return SUCCESS to try to avoid further EH measures. - * - * If the command has not completed yet, we must not fail to find it. - * We have no option but to forget the aborted command (even if it still - * lacks sense data). The mid-layer may re-issue a command that is in error - * recovery (see scsi_send_eh_cmnd), but the logic and data structures in - * this driver are such that a command can appear on one queue only. - * - * The lock protects driver data structures, but EH handlers also use it - * to serialize their own execution and prevent their own re-entry. - */ - -static int NCR5380_abort(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned long flags; - int result = SUCCESS; - - spin_lock_irqsave(&hostdata->lock, flags); - -#if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, __func__); -#endif - NCR5380_dprint(NDEBUG_ANY, instance); - NCR5380_dprint_phase(NDEBUG_ANY, instance); - - if (list_del_cmd(&hostdata->unissued, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from issue queue\n", cmd); - cmd->result = DID_ABORT << 16; - cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ - goto out; - } - - if (hostdata->selecting == cmd) { - dsprintk(NDEBUG_ABORT, instance, - "abort: cmd %p == selecting\n", cmd); - hostdata->selecting = NULL; - cmd->result = DID_ABORT << 16; - complete_cmd(instance, cmd); - goto out; - } - - if (list_del_cmd(&hostdata->disconnected, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from disconnected list\n", cmd); - /* Can't call NCR5380_select() and send ABORT because that - * means releasing the lock. Need a bus reset. - */ - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } - - if (hostdata->connected == cmd) { - dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); - hostdata->connected = NULL; - hostdata->dma_len = 0; - if (do_abort(instance)) { - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } - set_host_byte(cmd, DID_ABORT); - complete_cmd(instance, cmd); - goto out; - } - - if (list_del_cmd(&hostdata->autosense, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from sense queue\n", cmd); - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - } - -out: - if (result == FAILED) - dsprintk(NDEBUG_ABORT, instance, "abort: failed to abort %p\n", cmd); - else - dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd); - - queue_work(hostdata->work_q, &hostdata->main_task); - maybe_release_dma_irq(instance); - spin_unlock_irqrestore(&hostdata->lock, flags); - - return result; -} - - -/** - * NCR5380_bus_reset - reset the SCSI bus - * @cmd: SCSI command undergoing EH - * - * Returns SUCCESS - */ - -static int NCR5380_bus_reset(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - int i; - unsigned long flags; - struct NCR5380_cmd *ncmd; - - spin_lock_irqsave(&hostdata->lock, flags); - -#if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, __func__); -#endif - NCR5380_dprint(NDEBUG_ANY, instance); - NCR5380_dprint_phase(NDEBUG_ANY, instance); - - do_reset(instance); - - /* reset NCR registers */ - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_write(SELECT_ENABLE_REG, 0); - - /* After the reset, there are no more connected or disconnected commands - * and no busy units; so clear the low-level status here to avoid - * conflicts when the mid-level code tries to wake up the affected - * commands! - */ - - if (list_del_cmd(&hostdata->unissued, cmd)) { - cmd->result = DID_RESET << 16; - cmd->scsi_done(cmd); - } - - if (hostdata->selecting) { - hostdata->selecting->result = DID_RESET << 16; - complete_cmd(instance, hostdata->selecting); - hostdata->selecting = NULL; - } - - list_for_each_entry(ncmd, &hostdata->disconnected, list) { - struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - - set_host_byte(cmd, DID_RESET); - cmd->scsi_done(cmd); - } - INIT_LIST_HEAD(&hostdata->disconnected); - - list_for_each_entry(ncmd, &hostdata->autosense, list) { - struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - - set_host_byte(cmd, DID_RESET); - cmd->scsi_done(cmd); - } - INIT_LIST_HEAD(&hostdata->autosense); - - if (hostdata->connected) { - set_host_byte(hostdata->connected, DID_RESET); - complete_cmd(instance, hostdata->connected); - hostdata->connected = NULL; - } - -#ifdef SUPPORT_TAGS - free_all_tags(hostdata); -#endif - for (i = 0; i < 8; ++i) - hostdata->busy[i] = 0; - hostdata->dma_len = 0; - - queue_work(hostdata->work_q, &hostdata->main_task); - maybe_release_dma_irq(instance); - spin_unlock_irqrestore(&hostdata->lock, flags); - - return SUCCESS; -} diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 445c26724ba1..49b7b14e8913 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -87,9 +87,6 @@ /* Definitions for the core NCR5380 driver. */ -#define SUPPORT_TAGS -#define MAX_TAGS 32 - #define NCR5380_implementation_fields /* none */ #define NCR5380_read(reg) atari_scsi_reg_read(reg) @@ -189,8 +186,6 @@ static int setup_cmd_per_lun = -1; module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; module_param(setup_sg_tablesize, int, 0); -static int setup_use_tagged_queuing = -1; -module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); static int setup_toshiba_delay = -1; @@ -479,8 +474,7 @@ static int __init atari_scsi_setup(char *str) setup_sg_tablesize = ints[3]; if (ints[0] >= 4) setup_hostid = ints[4]; - if (ints[0] >= 5) - setup_use_tagged_queuing = ints[5]; + /* ints[5] (use_tagged_queuing) is ignored */ /* ints[6] (use_pdma) is ignored */ if (ints[0] >= 7) setup_toshiba_delay = ints[7]; @@ -853,9 +847,6 @@ static int __init atari_scsi_probe(struct platform_device *pdev) instance->irq = irq->start; host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP; -#ifdef SUPPORT_TAGS - host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; -#endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; error = NCR5380_init(instance, host_flags); diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 4de6589fdbfb..42feba7e350b 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -55,8 +55,6 @@ static int setup_sg_tablesize = -1; module_param(setup_sg_tablesize, int, 0); static int setup_use_pdma = -1; module_param(setup_use_pdma, int, 0); -static int setup_use_tagged_queuing = -1; -module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); static int setup_toshiba_delay = -1; @@ -95,8 +93,7 @@ static int __init mac_scsi_setup(char *str) setup_sg_tablesize = ints[3]; if (ints[0] >= 4) setup_hostid = ints[4]; - if (ints[0] >= 5) - setup_use_tagged_queuing = ints[5]; + /* ints[5] (use_tagged_queuing) is ignored */ if (ints[0] >= 6) setup_use_pdma = ints[6]; if (ints[0] >= 7) @@ -382,9 +379,6 @@ static int __init mac_scsi_probe(struct platform_device *pdev) } else host_flags |= FLAG_NO_PSEUDO_DMA; -#ifdef SUPPORT_TAGS - host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; -#endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index f2fc788cb08b..3c4c07038948 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -41,9 +41,6 @@ /* Definitions for the core NCR5380 driver. */ -/* #define SUPPORT_TAGS */ -/* #define MAX_TAGS 32 */ - #define NCR5380_implementation_fields /* none */ #define NCR5380_read(reg) sun3scsi_read(reg) @@ -75,10 +72,6 @@ static int setup_cmd_per_lun = -1; module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; module_param(setup_sg_tablesize, int, 0); -#ifdef SUPPORT_TAGS -static int setup_use_tagged_queuing = -1; -module_param(setup_use_tagged_queuing, int, 0); -#endif static int setup_hostid = -1; module_param(setup_hostid, int, 0); @@ -512,10 +505,6 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) instance->io_port = (unsigned long)ioaddr; instance->irq = irq->start; -#ifdef SUPPORT_TAGS - host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; -#endif - error = NCR5380_init(instance, host_flags); if (error) goto fail_init; -- GitLab From ae5e33af42eb1f1262cfc8722072561b908bf914 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:23 +1100 Subject: [PATCH 2070/9938] ncr5380: Reduce max_lun limit The driver has a limit of eight LUs because of the byte-sized bitfield that is used for busy flags. That means the maximum LUN is 7. The default is 8. Signed-off-by: Finn Thain Tested-by: Michael Schmitz Tested-by: Ondrej Zary Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 305330b26349..5187c31a48be 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -488,6 +488,8 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) int i; unsigned long deadline; + instance->max_lun = 7; + hostdata->host = instance; hostdata->id_mask = 1 << instance->this_id; hostdata->id_higher_mask = 0; -- GitLab From 4712bd8d473da5e99d2328654bdba565de8b43ce Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:24 +1100 Subject: [PATCH 2071/9938] dmx3191d: Drop max_sectors limit The dmx3191d driver is not capable of DMA or PDMA so all transfers use PIO. Now that large slow PIO transfers periodically stop and call cond_resched(), the max_sectors limit can go away. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/dmx3191d.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index cc46d67b9f6f..f8d9bd8eaa6f 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -67,7 +67,6 @@ static struct scsi_host_template dmx3191d_driver_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, - .max_sectors = 128, }; static int dmx3191d_probe_one(struct pci_dev *pdev, -- GitLab From 12866b99e57cf9eba809503c687fc1a25c529c4a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:25 +1100 Subject: [PATCH 2072/9938] ncr5380: Fix register decoding for debugging Decode all bits in the chip registers. They are all useful at times. Fix printk severity so that this output can be suppressed along with the other debugging output. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 5187c31a48be..c93d207dafc8 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -256,12 +256,20 @@ static struct { {0, NULL} }, basrs[] = { + {BASR_END_DMA_TRANSFER, "END OF DMA"}, + {BASR_DRQ, "DRQ"}, + {BASR_PARITY_ERROR, "PARITY ERROR"}, + {BASR_IRQ, "IRQ"}, + {BASR_PHASE_MATCH, "PHASE MATCH"}, + {BASR_BUSY_ERROR, "BUSY ERROR"}, {BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL} }, icrs[] = { {ICR_ASSERT_RST, "ASSERT RST"}, + {ICR_ARBITRATION_PROGRESS, "ARB. IN PROGRESS"}, + {ICR_ARBITRATION_LOST, "LOST ARB."}, {ICR_ASSERT_ACK, "ASSERT ACK"}, {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, @@ -270,14 +278,14 @@ icrs[] = { {0, NULL} }, mrs[] = { - {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, - {MR_TARGET, "MODE TARGET"}, - {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, - {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, - {MR_ENABLE_EOP_INTR, "MODE EOP INTR"}, - {MR_MONITOR_BSY, "MODE MONITOR BSY"}, - {MR_DMA_MODE, "MODE DMA"}, - {MR_ARBITRATE, "MODE ARBITRATION"}, + {MR_BLOCK_DMA_MODE, "BLOCK DMA MODE"}, + {MR_TARGET, "TARGET"}, + {MR_ENABLE_PAR_CHECK, "PARITY CHECK"}, + {MR_ENABLE_PAR_INTR, "PARITY INTR"}, + {MR_ENABLE_EOP_INTR, "EOP INTR"}, + {MR_MONITOR_BSY, "MONITOR BSY"}, + {MR_DMA_MODE, "DMA MODE"}, + {MR_ARBITRATE, "ARBITRATE"}, {0, NULL} }; @@ -298,23 +306,23 @@ static void NCR5380_print(struct Scsi_Host *instance) icr = NCR5380_read(INITIATOR_COMMAND_REG); basr = NCR5380_read(BUS_AND_STATUS_REG); - printk("STATUS_REG: %02x ", status); + printk(KERN_DEBUG "SR = 0x%02x : ", status); for (i = 0; signals[i].mask; ++i) if (status & signals[i].mask) - printk(",%s", signals[i].name); - printk("\nBASR: %02x ", basr); + printk(KERN_CONT "%s, ", signals[i].name); + printk(KERN_CONT "\nBASR = 0x%02x : ", basr); for (i = 0; basrs[i].mask; ++i) if (basr & basrs[i].mask) - printk(",%s", basrs[i].name); - printk("\nICR: %02x ", icr); + printk(KERN_CONT "%s, ", basrs[i].name); + printk(KERN_CONT "\nICR = 0x%02x : ", icr); for (i = 0; icrs[i].mask; ++i) if (icr & icrs[i].mask) - printk(",%s", icrs[i].name); - printk("\nMODE: %02x ", mr); + printk(KERN_CONT "%s, ", icrs[i].name); + printk(KERN_CONT "\nMR = 0x%02x : ", mr); for (i = 0; mrs[i].mask; ++i) if (mr & mrs[i].mask) - printk(",%s", mrs[i].name); - printk("\n"); + printk(KERN_CONT "%s, ", mrs[i].name); + printk(KERN_CONT "\n"); } static struct { -- GitLab From f0ea73a4ef4ad86cc8430b6a0463a61b90472718 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:26 +1100 Subject: [PATCH 2073/9938] ncr5380: Remove remaining register storage qualifiers Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index c93d207dafc8..69a0d9d154fe 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1555,9 +1555,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char **data) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - register int c = *count; - register unsigned char p = *phase; - register unsigned char *d = *data; + int c = *count; + unsigned char p = *phase; + unsigned char *d = *data; unsigned char tmp; int result = 0; -- GitLab From a46865dcf1f7166808664ab096678f81d4fbb853 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:27 +1100 Subject: [PATCH 2074/9938] ncr5380: Remove DONT_USE_INTR and AUTOPROBE_IRQ macros Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 12 +----------- drivers/scsi/NCR5380.h | 4 ---- drivers/scsi/arm/oak.c | 2 -- drivers/scsi/dmx3191d.c | 2 -- drivers/scsi/dtc.c | 12 +++--------- drivers/scsi/g_NCR5380.c | 2 -- drivers/scsi/pas16.c | 1 - drivers/scsi/t128.c | 1 - 8 files changed, 4 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 69a0d9d154fe..52e7d2b57902 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -106,9 +106,6 @@ * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential * transceivers. * - * DONT_USE_INTR - if defined, never use interrupts, even if we probe or - * override-configure an IRQ. - * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. @@ -464,9 +461,6 @@ static void prepare_info(struct Scsi_Host *instance) hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", -#ifdef AUTOPROBE_IRQ - "AUTOPROBE_IRQ " -#endif #ifdef DIFFERENTIAL "DIFFERENTIAL " #endif @@ -915,8 +909,6 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } } -#ifndef DONT_USE_INTR - /** * NCR5380_intr - generic NCR5380 irq handler * @irq: interrupt number @@ -951,7 +943,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) * the Busy Monitor interrupt is enabled together with DMA Mode. */ -static irqreturn_t NCR5380_intr(int irq, void *dev_id) +static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id) { struct Scsi_Host *instance = dev_id; struct NCR5380_hostdata *hostdata = shost_priv(instance); @@ -1020,8 +1012,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) return IRQ_RETVAL(handled); } -#endif - /* * Function : int NCR5380_select(struct Scsi_Host *instance, * struct scsi_cmnd *cmd) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 5c2411f05852..076f8969dd22 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -280,16 +280,12 @@ static void NCR5380_print(struct Scsi_Host *instance); #define NCR5380_dprint_phase(flg, arg) do {} while (0) #endif -#if defined(AUTOPROBE_IRQ) static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); -#endif static int NCR5380_init(struct Scsi_Host *instance, int flags); static int NCR5380_maybe_reset_bus(struct Scsi_Host *); static void NCR5380_exit(struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance); -#ifndef DONT_USE_INTR static irqreturn_t NCR5380_intr(int irq, void *dev_id); -#endif static void NCR5380_main(struct work_struct *work); static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 3aac99c21267..a396024a3cae 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -14,8 +14,6 @@ #include -#define DONT_USE_INTR - #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_read(reg) \ diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index f8d9bd8eaa6f..9b5a457d4bca 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -34,8 +34,6 @@ * Definitions for the generic 5380 driver. */ -#define DONT_USE_INTR - #define NCR5380_read(reg) inb(instance->io_port + reg) #define NCR5380_write(reg, value) outb(value, instance->io_port + reg) diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index e87c632234f3..459863f94e46 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -1,5 +1,3 @@ -#define DONT_USE_INTR - /* * DTC 3180/3280 driver, by * Ray Van Tassle rayvt@comm.mot.com @@ -53,7 +51,6 @@ #include #include "dtc.h" -#define AUTOPROBE_IRQ #include "NCR5380.h" /* @@ -243,9 +240,10 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) if (instance->irq == 255) instance->irq = NO_IRQ; -#ifndef DONT_USE_INTR /* With interrupts enabled, it will sometimes hang when doing heavy * reads. So better not enable them until I finger it out. */ + instance->irq = NO_IRQ; + if (instance->irq != NO_IRQ) if (request_irq(instance->irq, dtc_intr, 0, "dtc", instance)) { @@ -257,11 +255,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); } -#else - if (instance->irq != NO_IRQ) - printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no); - instance->irq = NO_IRQ; -#endif + dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", instance->host_no, instance->irq); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 09e1cf938ecf..18f4a4f99336 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -56,8 +56,6 @@ * */ -#define AUTOPROBE_IRQ - #include #include #include diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 62eef3f6d140..2f689ae7a803 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -75,7 +75,6 @@ #include #include "pas16.h" -#define AUTOPROBE_IRQ #include "NCR5380.h" diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index b5beecfaa3d5..8a8608ac62e6 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -74,7 +74,6 @@ #include #include "t128.h" -#define AUTOPROBE_IRQ #include "NCR5380.h" static struct override { -- GitLab From 9c41ab27e3fe0cfec16d3ac23f2067a516e337a4 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:28 +1100 Subject: [PATCH 2075/9938] ncr5380: Update usage documentation Update kernel parameter documentation for atari_scsi, mac_scsi and g_NCR5380 drivers. Remove duplication. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- Documentation/scsi/g_NCR5380.txt | 17 +++++------- Documentation/scsi/scsi-parameters.txt | 11 +++++--- drivers/scsi/g_NCR5380.c | 36 +------------------------- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/Documentation/scsi/g_NCR5380.txt b/Documentation/scsi/g_NCR5380.txt index 3b80f567f818..fd880150aeea 100644 --- a/Documentation/scsi/g_NCR5380.txt +++ b/Documentation/scsi/g_NCR5380.txt @@ -23,11 +23,10 @@ supported by the driver. If the default configuration does not work for you, you can use the kernel command lines (eg using the lilo append command): - ncr5380=port,irq,dma - ncr53c400=port,irq -or - ncr5380=base,irq,dma - ncr53c400=base,irq + ncr5380=addr,irq + ncr53c400=addr,irq + ncr53c400a=addr,irq + dtc3181e=addr,irq The driver does not probe for any addresses or ports other than those in the OVERRIDE or given to the kernel as above. @@ -36,19 +35,17 @@ This driver provides some information on what it has detected in /proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot time. More info to come in the future. -When NCR53c400 support is compiled in, BIOS parameters will be returned by -the driver (the raw 5380 driver does not and I don't plan to fiddle with -it!). - This driver works as a module. When included as a module, parameters can be passed on the insmod/modprobe command line: ncr_irq=xx the interrupt ncr_addr=xx the port or base address (for port or memory mapped, resp.) - ncr_dma=xx the DMA ncr_5380=1 to set up for a NCR5380 board ncr_53c400=1 to set up for a NCR53C400 board + ncr_53c400a=1 to set up for a NCR53C400A board + dtc_3181e=1 to set up for a Domex Technology Corp 3181E board + hp_c2502=1 to set up for a Hewlett Packard C2502 board e.g. modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1 for a port mapped NCR5380 board or diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 2bfd6f6d2d3d..1241ac11edb1 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -27,13 +27,15 @@ parameters may be changed at runtime by the command aic79xx= [HW,SCSI] See Documentation/scsi/aic79xx.txt. - atascsi= [HW,SCSI] Atari SCSI + atascsi= [HW,SCSI] + See drivers/scsi/atari_scsi.c. BusLogic= [HW,SCSI] See drivers/scsi/BusLogic.c, comment before function BusLogic_ParseDriverOptions(). dtc3181e= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. eata= [HW,SCSI] @@ -51,8 +53,8 @@ parameters may be changed at runtime by the command ips= [HW,SCSI] Adaptec / IBM ServeRAID controller See header of drivers/scsi/ips.c. - mac5380= [HW,SCSI] Format: - ,,,, + mac5380= [HW,SCSI] + See drivers/scsi/mac_scsi.c. max_luns= [SCSI] Maximum number of LUNs to probe. Should be between 1 and 2^32-1. @@ -65,10 +67,13 @@ parameters may be changed at runtime by the command See header of drivers/scsi/NCR_D700.c. ncr5380= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. ncr53c400= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. ncr53c400a= [HW,SCSI] + See Documentation/scsi/g_NCR5380.txt. ncr53c406a= [HW,SCSI] diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 18f4a4f99336..516bd6c4f442 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -18,42 +18,8 @@ * * Added ISAPNP support for DTC436 adapters, * Thomas Sailer, sailer@ife.ee.ethz.ch - */ - -/* - * TODO : flesh out DMA support, find some one actually using this (I have - * a memory mapped Trantor board that works fine) - */ - -/* - * The card is detected and initialized in one of several ways : - * 1. With command line overrides - NCR5380=port,irq may be - * used on the LILO command line to override the defaults. - * - * 2. With the GENERIC_NCR5380_OVERRIDE compile time define. This is - * specified as an array of address, irq, dma, board tuples. Ie, for - * one board at 0x350, IRQ5, no dma, I could say - * -DGENERIC_NCR5380_OVERRIDE={{0xcc000, 5, DMA_NONE, BOARD_NCR5380}} - * - * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an - * IRQ line if overridden on the command line. * - * 3. When included as a module, with arguments passed on the command line: - * ncr_irq=xx the interrupt - * ncr_addr=xx the port or base address (for port or memory - * mapped, resp.) - * ncr_dma=xx the DMA - * ncr_5380=1 to set up for a NCR5380 board - * ncr_53c400=1 to set up for a NCR53C400 board - * e.g. - * modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1 - * for a port mapped NCR5380 board or - * modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 - * for a memory mapped NCR53C400 board with interrupts disabled. - * - * 255 should be specified for no or DMA interrupt, 254 to autoprobe for an - * IRQ line if overridden on the command line. - * + * See Documentation/scsi/g_NCR5380.txt for more info. */ #include -- GitLab From a5217a86369083af1f9630d17e9bb9e41ae7405a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:29 +1100 Subject: [PATCH 2076/9938] atari_scsi: Set a reasonable default for cmd_per_lun This setting does not need to be conditional on Atari ST or TT. Signed-off-by: Finn Thain Tested-by: Michael Schmitz Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_scsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 49b7b14e8913..65af08139787 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -752,6 +752,7 @@ static struct scsi_host_template atari_scsi_template = { .eh_abort_handler = atari_scsi_abort, .eh_bus_reset_handler = atari_scsi_bus_reset, .this_id = 7, + .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, }; @@ -788,11 +789,9 @@ static int __init atari_scsi_probe(struct platform_device *pdev) */ if (ATARIHW_PRESENT(TT_SCSI)) { atari_scsi_template.can_queue = 16; - atari_scsi_template.cmd_per_lun = 8; atari_scsi_template.sg_tablesize = SG_ALL; } else { atari_scsi_template.can_queue = 8; - atari_scsi_template.cmd_per_lun = 1; atari_scsi_template.sg_tablesize = SG_NONE; } -- GitLab From ded155b5e4e735bdd654306145dff6491ce85766 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:30 +1100 Subject: [PATCH 2077/9938] atari_scsi: Allow can_queue to be increased for Falcon The benefit of limiting can_queue to 1 is that atari_scsi shares the ST DMA chip more fairly with other drivers (e.g. falcon-ide). Unfortunately, this can limit SCSI bus utilization. On systems without IDE, atari_scsi should issue SCSI commands whenever it can arbitrate for the bus. Make that possible by making can_queue configurable. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_scsi.c | 83 +++++++++++---------------------------- 1 file changed, 22 insertions(+), 61 deletions(-) diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 65af08139787..a59ad94ea52b 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -14,55 +14,23 @@ * */ - -/**************************************************************************/ -/* */ -/* Notes for Falcon SCSI: */ -/* ---------------------- */ -/* */ -/* Since the Falcon SCSI uses the ST-DMA chip, that is shared among */ -/* several device drivers, locking and unlocking the access to this */ -/* chip is required. But locking is not possible from an interrupt, */ -/* since it puts the process to sleep if the lock is not available. */ -/* This prevents "late" locking of the DMA chip, i.e. locking it just */ -/* before using it, since in case of disconnection-reconnection */ -/* commands, the DMA is started from the reselection interrupt. */ -/* */ -/* Two possible schemes for ST-DMA-locking would be: */ -/* 1) The lock is taken for each command separately and disconnecting */ -/* is forbidden (i.e. can_queue = 1). */ -/* 2) The DMA chip is locked when the first command comes in and */ -/* released when the last command is finished and all queues are */ -/* empty. */ -/* The first alternative would result in bad performance, since the */ -/* interleaving of commands would not be used. The second is unfair to */ -/* other drivers using the ST-DMA, because the queues will seldom be */ -/* totally empty if there is a lot of disk traffic. */ -/* */ -/* For this reasons I decided to employ a more elaborate scheme: */ -/* - First, we give up the lock every time we can (for fairness), this */ -/* means every time a command finishes and there are no other commands */ -/* on the disconnected queue. */ -/* - If there are others waiting to lock the DMA chip, we stop */ -/* issuing commands, i.e. moving them onto the issue queue. */ -/* Because of that, the disconnected queue will run empty in a */ -/* while. Instead we go to sleep on a 'fairness_queue'. */ -/* - If the lock is released, all processes waiting on the fairness */ -/* queue will be woken. The first of them tries to re-lock the DMA, */ -/* the others wait for the first to finish this task. After that, */ -/* they can all run on and do their commands... */ -/* This sounds complicated (and it is it :-(), but it seems to be a */ -/* good compromise between fairness and performance: As long as no one */ -/* else wants to work with the ST-DMA chip, SCSI can go along as */ -/* usual. If now someone else comes, this behaviour is changed to a */ -/* "fairness mode": just already initiated commands are finished and */ -/* then the lock is released. The other one waiting will probably win */ -/* the race for locking the DMA, since it was waiting for longer. And */ -/* after it has finished, SCSI can go ahead again. Finally: I hope I */ -/* have not produced any deadlock possibilities! */ -/* */ -/**************************************************************************/ - +/* + * Notes for Falcon SCSI DMA + * + * The 5380 device is one of several that all share the DMA chip. Hence + * "locking" and "unlocking" access to this chip is required. + * + * Two possible schemes for ST DMA acquisition by atari_scsi are: + * 1) The lock is taken for each command separately (i.e. can_queue == 1). + * 2) The lock is taken when the first command arrives and released + * when the last command is finished (i.e. can_queue > 1). + * + * The first alternative limits SCSI bus utilization, since interleaving + * commands is not possible. The second gives better performance but is + * unfair to other drivers needing to use the ST DMA chip. In order to + * allow the IDE and floppy drivers equal access to the ST DMA chip + * the default is can_queue == 1. + */ #include #include @@ -443,6 +411,10 @@ static int falcon_get_lock(struct Scsi_Host *instance) if (IS_A_TT()) return 1; + if (stdma_is_locked_by(scsi_falcon_intr) && + instance->hostt->can_queue > 1) + return 1; + if (in_interrupt()) return stdma_try_lock(scsi_falcon_intr, instance); @@ -776,22 +748,11 @@ static int __init atari_scsi_probe(struct platform_device *pdev) atari_scsi_reg_write = atari_scsi_falcon_reg_write; } - /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. - * Higher values should work, too; try it! - * (But cmd_per_lun costs memory!) - * - * But there seems to be a bug somewhere that requires CAN_QUEUE to be - * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since - * changed CMD_PER_LUN... - * - * Note: The Falcon currently uses 8/1 setting due to unsolved problems - * with cmd_per_lun != 1 - */ if (ATARIHW_PRESENT(TT_SCSI)) { atari_scsi_template.can_queue = 16; atari_scsi_template.sg_tablesize = SG_ALL; } else { - atari_scsi_template.can_queue = 8; + atari_scsi_template.can_queue = 1; atari_scsi_template.sg_tablesize = SG_NONE; } -- GitLab From 3a0f64bfa90700c4fa9db0ed2d701300edd9a0b3 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:31 +1100 Subject: [PATCH 2078/9938] mac_scsi: Fix pseudo DMA implementation Fix various issues: Comments about bus errors are incorrect. The PDMA asm must return the size of the memory access that faulted so the transfer count can be adjusted accordingly. A phase change may cause a bus error but should not be treated as failure. A bus error does not always imply a phase change and generally the transfer may continue. Scatter/gather doesn't seem to work with PDMA due to overruns. This is a pity because peak throughput seems to double with SG_ALL. Tested on a Mac LC III and a PowerBook 520. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 2 + drivers/scsi/mac_scsi.c | 212 ++++++++++++++++++++++------------------ 2 files changed, 119 insertions(+), 95 deletions(-) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 076f8969dd22..c60728785d89 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -292,6 +292,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance); static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); +static int NCR5380_poll_politely(struct Scsi_Host *, int, int, int, int); +static int NCR5380_poll_politely2(struct Scsi_Host *, int, int, int, int, int, int, int); #endif /* __KERNEL__ */ #endif /* NCR5380_H */ diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 42feba7e350b..a590089b9397 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -28,7 +28,8 @@ /* Definitions for the core NCR5380 driver. */ -#define NCR5380_implementation_fields unsigned char *pdma_base +#define NCR5380_implementation_fields unsigned char *pdma_base; \ + int pdma_residual #define NCR5380_read(reg) macscsi_read(instance, reg) #define NCR5380_write(reg, value) macscsi_write(instance, reg, value) @@ -37,7 +38,7 @@ macscsi_dma_xfer_len(instance, cmd) #define NCR5380_dma_recv_setup macscsi_pread #define NCR5380_dma_send_setup macscsi_pwrite -#define NCR5380_dma_residual(instance) (0) +#define NCR5380_dma_residual(instance) (hostdata->pdma_residual) #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command @@ -104,18 +105,9 @@ static int __init mac_scsi_setup(char *str) __setup("mac5380=", mac_scsi_setup); #endif /* !MODULE */ -/* - Pseudo-DMA: (Ove Edlund) - The code attempts to catch bus errors that occur if one for example - "trips over the cable". - XXX: Since bus errors in the PDMA routines never happen on my - computer, the bus error code is untested. - If the code works as intended, a bus error results in Pseudo-DMA - being disabled, meaning that the driver switches to slow handshake. - If bus errors are NOT extremely rare, this has to be changed. -*/ - -#define CP_IO_TO_MEM(s,d,len) \ +/* Pseudo DMA asm originally by Ove Edlund */ + +#define CP_IO_TO_MEM(s,d,n) \ __asm__ __volatile__ \ (" cmp.w #4,%2\n" \ " bls 8f\n" \ @@ -152,61 +144,73 @@ __asm__ __volatile__ \ " 9: \n" \ ".section .fixup,\"ax\"\n" \ " .even\n" \ - "90: moveq.l #1, %2\n" \ + "91: moveq.l #1, %2\n" \ + " jra 9b\n" \ + "94: moveq.l #4, %2\n" \ " jra 9b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ - " .long 1b,90b\n" \ - " .long 3b,90b\n" \ - " .long 31b,90b\n" \ - " .long 32b,90b\n" \ - " .long 33b,90b\n" \ - " .long 34b,90b\n" \ - " .long 35b,90b\n" \ - " .long 36b,90b\n" \ - " .long 37b,90b\n" \ - " .long 5b,90b\n" \ - " .long 7b,90b\n" \ + " .long 1b,91b\n" \ + " .long 3b,94b\n" \ + " .long 31b,94b\n" \ + " .long 32b,94b\n" \ + " .long 33b,94b\n" \ + " .long 34b,94b\n" \ + " .long 35b,94b\n" \ + " .long 36b,94b\n" \ + " .long 37b,94b\n" \ + " .long 5b,94b\n" \ + " .long 7b,91b\n" \ ".previous" \ - : "=a"(s), "=a"(d), "=d"(len) \ - : "0"(s), "1"(d), "2"(len) \ + : "=a"(s), "=a"(d), "=d"(n) \ + : "0"(s), "1"(d), "2"(n) \ : "d0") static int macscsi_pread(struct Scsi_Host *instance, unsigned char *dst, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char *d; - unsigned char *s; - - s = hostdata->pdma_base + (INPUT_DATA_REG << 4); - d = dst; - - /* These conditions are derived from MacOS */ - - while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && - !(NCR5380_read(STATUS_REG) & SR_REQ)) - ; - - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && - (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) { - pr_err("Error in macscsi_pread\n"); - return -1; - } - - CP_IO_TO_MEM(s, d, len); - - if (len != 0) { - pr_notice("Bus error in macscsi_pread\n"); - return -1; + unsigned char *s = hostdata->pdma_base + (INPUT_DATA_REG << 4); + unsigned char *d = dst; + int n = len; + int transferred; + + while (!NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + BASR_DRQ | BASR_PHASE_MATCH, + BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { + CP_IO_TO_MEM(s, d, n); + + transferred = d - dst - n; + hostdata->pdma_residual = len - transferred; + + /* No bus error. */ + if (n == 0) + return 0; + + /* Target changed phase early? */ + if (NCR5380_poll_politely2(instance, STATUS_REG, SR_REQ, SR_REQ, + BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0) + scmd_printk(KERN_ERR, hostdata->connected, + "%s: !REQ and !ACK\n", __func__); + if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) + return 0; + + dsprintk(NDEBUG_PSEUDO_DMA, instance, + "%s: bus error (%d/%d)\n", __func__, transferred, len); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + d = dst + transferred; + n = len - transferred; } - return 0; + scmd_printk(KERN_ERR, hostdata->connected, + "%s: phase mismatch or !DRQ\n", __func__); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + return -1; } -#define CP_MEM_TO_IO(s,d,len) \ +#define CP_MEM_TO_IO(s,d,n) \ __asm__ __volatile__ \ (" cmp.w #4,%2\n" \ " bls 8f\n" \ @@ -243,57 +247,76 @@ __asm__ __volatile__ \ " 9: \n" \ ".section .fixup,\"ax\"\n" \ " .even\n" \ - "90: moveq.l #1, %2\n" \ + "91: moveq.l #1, %2\n" \ + " jra 9b\n" \ + "94: moveq.l #4, %2\n" \ " jra 9b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ - " .long 1b,90b\n" \ - " .long 3b,90b\n" \ - " .long 31b,90b\n" \ - " .long 32b,90b\n" \ - " .long 33b,90b\n" \ - " .long 34b,90b\n" \ - " .long 35b,90b\n" \ - " .long 36b,90b\n" \ - " .long 37b,90b\n" \ - " .long 5b,90b\n" \ - " .long 7b,90b\n" \ + " .long 1b,91b\n" \ + " .long 3b,94b\n" \ + " .long 31b,94b\n" \ + " .long 32b,94b\n" \ + " .long 33b,94b\n" \ + " .long 34b,94b\n" \ + " .long 35b,94b\n" \ + " .long 36b,94b\n" \ + " .long 37b,94b\n" \ + " .long 5b,94b\n" \ + " .long 7b,91b\n" \ ".previous" \ - : "=a"(s), "=a"(d), "=d"(len) \ - : "0"(s), "1"(d), "2"(len) \ + : "=a"(s), "=a"(d), "=d"(n) \ + : "0"(s), "1"(d), "2"(n) \ : "d0") static int macscsi_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned char *s; - unsigned char *d; - - s = src; - d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4); - - /* These conditions are derived from MacOS */ - - while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && - (!(NCR5380_read(STATUS_REG) & SR_REQ) || - (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))) - ; - - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) { - pr_err("Error in macscsi_pwrite\n"); - return -1; + unsigned char *s = src; + unsigned char *d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4); + int n = len; + int transferred; + + while (!NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + BASR_DRQ | BASR_PHASE_MATCH, + BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { + CP_MEM_TO_IO(s, d, n); + + transferred = s - src - n; + hostdata->pdma_residual = len - transferred; + + /* Target changed phase early? */ + if (NCR5380_poll_politely2(instance, STATUS_REG, SR_REQ, SR_REQ, + BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0) + scmd_printk(KERN_ERR, hostdata->connected, + "%s: !REQ and !ACK\n", __func__); + if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) + return 0; + + /* No bus error. */ + if (n == 0) { + if (NCR5380_poll_politely(instance, TARGET_COMMAND_REG, + TCR_LAST_BYTE_SENT, + TCR_LAST_BYTE_SENT, HZ / 64) < 0) + scmd_printk(KERN_ERR, hostdata->connected, + "%s: Last Byte Sent timeout\n", __func__); + return 0; + } + + dsprintk(NDEBUG_PSEUDO_DMA, instance, + "%s: bus error (%d/%d)\n", __func__, transferred, len); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); + s = src + transferred; + n = len - transferred; } - CP_MEM_TO_IO(s, d, len); - - if (len != 0) { - pr_notice("Bus error in macscsi_pwrite\n"); - return -1; - } + scmd_printk(KERN_ERR, hostdata->connected, + "%s: phase mismatch or !DRQ\n", __func__); + NCR5380_dprint(NDEBUG_PSEUDO_DMA, instance); - return 0; + return -1; } static int macscsi_dma_xfer_len(struct Scsi_Host *instance, @@ -301,10 +324,11 @@ static int macscsi_dma_xfer_len(struct Scsi_Host *instance, { struct NCR5380_hostdata *hostdata = shost_priv(instance); - if (hostdata->flags & FLAG_NO_PSEUDO_DMA) + if (hostdata->flags & FLAG_NO_PSEUDO_DMA || + cmd->SCp.this_residual < 16) return 0; - return cmd->transfersize; + return cmd->SCp.this_residual; } #include "NCR5380.c" @@ -322,7 +346,7 @@ static struct scsi_host_template mac_scsi_template = { .eh_bus_reset_handler = macscsi_bus_reset, .can_queue = 16, .this_id = 7, - .sg_tablesize = SG_ALL, + .sg_tablesize = 1, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, @@ -358,8 +382,6 @@ static int __init mac_scsi_probe(struct platform_device *pdev) mac_scsi_template.sg_tablesize = setup_sg_tablesize; if (setup_hostid >= 0) mac_scsi_template.this_id = setup_hostid & 7; - if (setup_use_pdma < 0) - setup_use_pdma = 0; instance = scsi_host_alloc(&mac_scsi_template, sizeof(struct NCR5380_hostdata)); -- GitLab From 216fad91387aab7c9e69fe0854d843f012968748 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 23 Mar 2016 21:10:32 +1100 Subject: [PATCH 2079/9938] ncr5380: Call complete_cmd() for disconnected commands on bus reset I'm told that some targets are liable to disconnect a REQUEST SENSE command. Theoretically this would cause a command undergoing autosense to be moved onto the disconnected list. The bus reset handler must call complete_cmd() for these commands, otherwise the hostdata->sensing pointer will not get cleared. That would cause autosense processing to stall and a timeout or an incorrect scsi_eh_restore_cmnd() would eventually follow. Signed-off-by: Finn Thain Reported-by: Michael Schmitz Tested-by: Ondrej Zary Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 52e7d2b57902..43908bbb3b23 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2437,7 +2437,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); set_host_byte(cmd, DID_RESET); - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); } INIT_LIST_HEAD(&hostdata->disconnected); -- GitLab From 1d64508810d8d15867251c75a68d7250278ce2bd Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 17 Mar 2016 08:39:45 +0100 Subject: [PATCH 2080/9938] scsi: disable automatic target scan On larger installations it is useful to disable automatic LUN scanning, and only add the required LUNs via udev rules. This can speed up bootup dramatically. This patch introduces a new scan module parameter value 'manual', which works like 'none', but can be overridden by setting the 'rescan' value from scsi_scan_target to 'SCSI_SCAN_MANUAL'. And it updates all relevant callers to set the 'rescan' value to 'SCSI_SCAN_MANUAL' if invoked via the 'scan' option in sysfs. Signed-off-by: Hannes Reinecke Reviewed-by: Ewan D. Milne Tested-by: Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/srp/ib_srp.c | 2 +- drivers/message/fusion/mptspi.c | 2 +- drivers/s390/scsi/zfcp_unit.c | 3 +- drivers/scsi/scsi_priv.h | 2 +- drivers/scsi/scsi_proc.c | 3 +- drivers/scsi/scsi_scan.c | 44 ++++++++++++++++++++--------- drivers/scsi/scsi_sysfs.c | 3 +- drivers/scsi/scsi_transport_fc.c | 6 ++-- drivers/scsi/scsi_transport_iscsi.c | 5 +++- drivers/scsi/scsi_transport_sas.c | 7 +++-- drivers/scsi/snic/snic_disc.c | 2 +- include/scsi/scsi_device.h | 9 +++++- 12 files changed, 60 insertions(+), 28 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index b6bf20496021..ff21597aa54d 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -2819,7 +2819,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) spin_unlock(&host->target_lock); scsi_scan_target(&target->scsi_host->shost_gendev, - 0, target->scsi_id, SCAN_WILD_CARD, 0); + 0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL); if (srp_connected_ch(target) < target->ch_count || target->qp_in_error) { diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 613231c16194..031e088edb5e 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1150,7 +1150,7 @@ static void mpt_work_wrapper(struct work_struct *work) } shost_printk(KERN_INFO, shost, MYIOC_s_FMT "Integrated RAID detects new device %d\n", ioc->name, disk); - scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1); + scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, SCSI_SCAN_RESCAN); } diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 157d3d203ba1..08bba7ce7cef 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -26,7 +26,8 @@ void zfcp_unit_scsi_scan(struct zfcp_unit *unit) lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); if (rport && rport->port_state == FC_PORTSTATE_ONLINE) - scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1); + scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, + SCSI_SCAN_RESCAN); } static void zfcp_unit_scsi_scan_work(struct work_struct *work) diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 27b4d0a6a01d..57a4b9973320 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -116,7 +116,7 @@ extern void scsi_exit_procfs(void); extern char scsi_scan_type[]; extern int scsi_complete_async_scans(void); extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, - unsigned int, u64, int); + unsigned int, u64, enum scsi_scan_mode); extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_rescan_device(struct device *); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 251598eb3547..7a74b82e8973 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -251,7 +251,8 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) if (shost->transportt->user_scan) error = shost->transportt->user_scan(shost, channel, id, lun); else - error = scsi_scan_host_selected(shost, channel, id, lun, 1); + error = scsi_scan_host_selected(shost, channel, id, lun, + SCSI_SCAN_MANUAL); scsi_host_put(shost); return error; } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 97074c91e328..6c8ad36560d1 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -96,10 +96,13 @@ MODULE_PARM_DESC(max_luns, #define SCSI_SCAN_TYPE_DEFAULT "sync" #endif -char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT; +char scsi_scan_type[7] = SCSI_SCAN_TYPE_DEFAULT; -module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); -MODULE_PARM_DESC(scan, "sync, async or none"); +module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), + S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(scan, "sync, async, manual, or none. " + "Setting to 'manual' disables automatic scanning, but allows " + "for manual device scan via the 'scan' sysfs attribute."); static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ + 18; @@ -1040,7 +1043,8 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, * @lun: LUN of target device * @bflagsp: store bflags here if not NULL * @sdevp: probe the LUN corresponding to this scsi_device - * @rescan: if nonzero skip some code only needed on first scan + * @rescan: if not equal to SCSI_SCAN_INITIAL skip some code only + * needed on first scan * @hostdata: passed to scsi_alloc_sdev() * * Description: @@ -1055,7 +1059,8 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, **/ static int scsi_probe_and_add_lun(struct scsi_target *starget, u64 lun, int *bflagsp, - struct scsi_device **sdevp, int rescan, + struct scsi_device **sdevp, + enum scsi_scan_mode rescan, void *hostdata) { struct scsi_device *sdev; @@ -1069,7 +1074,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, */ sdev = scsi_device_lookup_by_target(starget, lun); if (sdev) { - if (rescan || !scsi_device_created(sdev)) { + if (rescan != SCSI_SCAN_INITIAL || !scsi_device_created(sdev)) { SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, "scsi scan: device exists on %s\n", dev_name(&sdev->sdev_gendev))); @@ -1205,7 +1210,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * Modifies sdevscan->lun. **/ static void scsi_sequential_lun_scan(struct scsi_target *starget, - int bflags, int scsi_level, int rescan) + int bflags, int scsi_level, + enum scsi_scan_mode rescan) { uint max_dev_lun; u64 sparse_lun, lun; @@ -1300,7 +1306,7 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * 1: could not scan with REPORT LUN **/ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, - int rescan) + enum scsi_scan_mode rescan) { char devname[64]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; @@ -1546,7 +1552,7 @@ void scsi_rescan_device(struct device *dev) EXPORT_SYMBOL(scsi_rescan_device); static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, enum scsi_scan_mode rescan) { struct Scsi_Host *shost = dev_to_shost(parent); int bflags = 0; @@ -1604,7 +1610,10 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * @channel: channel to scan * @id: target id to scan * @lun: Specific LUN to scan or SCAN_WILD_CARD - * @rescan: passed to LUN scanning routines + * @rescan: passed to LUN scanning routines; SCSI_SCAN_INITIAL for + * no rescan, SCSI_SCAN_RESCAN to rescan existing LUNs, + * and SCSI_SCAN_MANUAL to force scanning even if + * 'scan=manual' is set. * * Description: * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, @@ -1614,13 +1623,17 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * sequential scan of LUNs on the target id. **/ void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, enum scsi_scan_mode rescan) { struct Scsi_Host *shost = dev_to_shost(parent); if (strncmp(scsi_scan_type, "none", 4) == 0) return; + if (rescan != SCSI_SCAN_MANUAL && + strncmp(scsi_scan_type, "manual", 6) == 0) + return; + mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); @@ -1634,7 +1647,8 @@ void scsi_scan_target(struct device *parent, unsigned int channel, EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, + enum scsi_scan_mode rescan) { uint order_id; @@ -1665,7 +1679,8 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, } int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, + enum scsi_scan_mode rescan) { SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, "%s: <%u:%u:%llu>\n", @@ -1844,7 +1859,8 @@ void scsi_scan_host(struct Scsi_Host *shost) { struct async_scan_data *data; - if (strncmp(scsi_scan_type, "none", 4) == 0) + if (strncmp(scsi_scan_type, "none", 4) == 0 || + strncmp(scsi_scan_type, "manual", 6) == 0) return; if (scsi_autopm_get_host(shost) < 0) return; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 2b642b145be1..b36544162f2f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -145,7 +145,8 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str) if (shost->transportt->user_scan) res = shost->transportt->user_scan(shost, channel, id, lun); else - res = scsi_scan_host_selected(shost, channel, id, lun, 1); + res = scsi_scan_host_selected(shost, channel, id, lun, + SCSI_SCAN_MANUAL); return res; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 8a8822641b26..bf28c688c72a 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2110,7 +2110,8 @@ fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun) if ((channel == rport->channel) && (id == rport->scsi_target_id)) { spin_unlock_irqrestore(shost->host_lock, flags); - scsi_scan_target(&rport->dev, channel, id, lun, 1); + scsi_scan_target(&rport->dev, channel, id, lun, + SCSI_SCAN_MANUAL); return; } } @@ -3277,7 +3278,8 @@ fc_scsi_scan_rport(struct work_struct *work) (rport->roles & FC_PORT_ROLE_FCP_TARGET) && !(i->f->disable_target_scan)) { scsi_scan_target(&rport->dev, rport->channel, - rport->scsi_target_id, SCAN_WILD_CARD, 1); + rport->scsi_target_id, SCAN_WILD_CARD, + SCSI_SCAN_RESCAN); } spin_lock_irqsave(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 441481623fb9..7a759a9257ea 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1783,6 +1783,7 @@ struct iscsi_scan_data { unsigned int channel; unsigned int id; u64 lun; + enum scsi_scan_mode rescan; }; static int iscsi_user_scan_session(struct device *dev, void *data) @@ -1819,7 +1820,7 @@ static int iscsi_user_scan_session(struct device *dev, void *data) (scan_data->id == SCAN_WILD_CARD || scan_data->id == id)) scsi_scan_target(&session->dev, 0, id, - scan_data->lun, 1); + scan_data->lun, scan_data->rescan); } user_scan_exit: @@ -1836,6 +1837,7 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, scan_data.channel = channel; scan_data.id = id; scan_data.lun = lun; + scan_data.rescan = SCSI_SCAN_MANUAL; return device_for_each_child(&shost->shost_gendev, &scan_data, iscsi_user_scan_session); @@ -1852,6 +1854,7 @@ static void iscsi_scan_session(struct work_struct *work) scan_data.channel = 0; scan_data.id = SCAN_WILD_CARD; scan_data.lun = SCAN_WILD_CARD; + scan_data.rescan = SCSI_SCAN_RESCAN; iscsi_user_scan_session(&session->dev, &scan_data); atomic_dec(&ihost->nr_scans); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index b6f958193dad..3f0ff072184b 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1614,7 +1614,8 @@ int sas_rphy_add(struct sas_rphy *rphy) else lun = 0; - scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0); + scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, + SCSI_SCAN_INITIAL); } return 0; @@ -1739,8 +1740,8 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, if ((channel == SCAN_WILD_CARD || channel == 0) && (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { - scsi_scan_target(&rphy->dev, 0, - rphy->scsi_target_id, lun, 1); + scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, + lun, SCSI_SCAN_MANUAL); } } mutex_unlock(&sas_host->lock); diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c index 5f6321759ad9..5f48795767bd 100644 --- a/drivers/scsi/snic/snic_disc.c +++ b/drivers/scsi/snic/snic_disc.c @@ -171,7 +171,7 @@ snic_scsi_scan_tgt(struct work_struct *work) tgt->channel, tgt->scsi_tgt_id, SCAN_WILD_CARD, - 1); + SCSI_SCAN_RESCAN); spin_lock_irqsave(shost->host_lock, flags); tgt->flags &= ~SNIC_TGT_SCAN_PENDING; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 74d79bde7075..1d4a3297559e 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -50,6 +50,12 @@ enum scsi_device_state { SDEV_CREATED_BLOCK, /* same as above but for created devices */ }; +enum scsi_scan_mode { + SCSI_SCAN_INITIAL = 0, + SCSI_SCAN_RESCAN, + SCSI_SCAN_MANUAL, +}; + enum scsi_device_event { SDEV_EVT_MEDIA_CHANGE = 1, /* media has changed */ SDEV_EVT_INQUIRY_CHANGE_REPORTED, /* 3F 03 UA reported */ @@ -391,7 +397,8 @@ extern void scsi_device_resume(struct scsi_device *sdev); extern void scsi_target_quiesce(struct scsi_target *); extern void scsi_target_resume(struct scsi_target *); extern void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan); + unsigned int id, u64 lun, + enum scsi_scan_mode rescan); extern void scsi_target_reap(struct scsi_target *); extern void scsi_target_block(struct device *); extern void scsi_target_unblock(struct device *, enum scsi_device_state); -- GitLab From b3bc891eab51c98ec83458e2d7f0db629169ad80 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 24 Mar 2016 15:21:18 +0100 Subject: [PATCH 2081/9938] scsi-trace: remove service action definitions scsi_opcode_name() is displaying the opcode, not the service action. Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- include/trace/events/scsi.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h index 079bd10a01b4..5c0d91f16c74 100644 --- a/include/trace/events/scsi.h +++ b/include/trace/events/scsi.h @@ -95,10 +95,6 @@ scsi_opcode_name(VERIFY_16), \ scsi_opcode_name(WRITE_SAME_16), \ scsi_opcode_name(SERVICE_ACTION_IN_16), \ - scsi_opcode_name(SAI_READ_CAPACITY_16), \ - scsi_opcode_name(SAI_GET_LBA_STATUS), \ - scsi_opcode_name(MI_REPORT_TARGET_PGS), \ - scsi_opcode_name(MO_SET_TARGET_PGS), \ scsi_opcode_name(READ_32), \ scsi_opcode_name(WRITE_32), \ scsi_opcode_name(WRITE_SAME_32), \ -- GitLab From 5141f16a8a944f14e4b0348e8cd9e4dd1acb1a86 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 24 Mar 2016 15:21:19 +0100 Subject: [PATCH 2082/9938] scsi-trace: Decode MAINTENANCE_IN and MAINTENANCE_OUT commands Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_trace.c | 91 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index 08bb47b53bc3..76d4e6fd9dc1 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c @@ -17,6 +17,7 @@ */ #include #include +#include #include #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) @@ -230,6 +231,92 @@ scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) return ret; } +static const char * +scsi_trace_maintenance_in(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u32 alloc_len; + + switch (SERVICE_ACTION16(cdb)) { + case MI_REPORT_IDENTIFYING_INFORMATION: + cmd = "REPORT_IDENTIFYING_INFORMATION"; + break; + case MI_REPORT_TARGET_PGS: + cmd = "REPORT_TARGET_PORT_GROUPS"; + break; + case MI_REPORT_ALIASES: + cmd = "REPORT_ALIASES"; + break; + case MI_REPORT_SUPPORTED_OPERATION_CODES: + cmd = "REPORT_SUPPORTED_OPERATION_CODES"; + break; + case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS: + cmd = "REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS"; + break; + case MI_REPORT_PRIORITY: + cmd = "REPORT_PRIORITY"; + break; + case MI_REPORT_TIMESTAMP: + cmd = "REPORT_TIMESTAMP"; + break; + case MI_MANAGEMENT_PROTOCOL_IN: + cmd = "MANAGEMENT_PROTOCOL_IN"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + alloc_len = get_unaligned_be32(&cdb[6]); + + trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len); + +out: + trace_seq_putc(p, 0); + + return ret; +} + +static const char * +scsi_trace_maintenance_out(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u32 alloc_len; + + switch (SERVICE_ACTION16(cdb)) { + case MO_SET_IDENTIFYING_INFORMATION: + cmd = "SET_IDENTIFYING_INFORMATION"; + break; + case MO_SET_TARGET_PGS: + cmd = "SET_TARGET_PORT_GROUPS"; + break; + case MO_CHANGE_ALIASES: + cmd = "CHANGE_ALIASES"; + break; + case MO_SET_PRIORITY: + cmd = "SET_PRIORITY"; + break; + case MO_SET_TIMESTAMP: + cmd = "SET_TIMESTAMP"; + break; + case MO_MANAGEMENT_PROTOCOL_OUT: + cmd = "MANAGEMENT_PROTOCOL_OUT"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + alloc_len = get_unaligned_be32(&cdb[6]); + + trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len); + +out: + trace_seq_putc(p, 0); + + return ret; +} + static const char * scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) { @@ -282,6 +369,10 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) return scsi_trace_service_action_in(p, cdb, len); case VARIABLE_LENGTH_CMD: return scsi_trace_varlen(p, cdb, len); + case MAINTENANCE_IN: + return scsi_trace_maintenance_in(p, cdb, len); + case MAINTENANCE_OUT: + return scsi_trace_maintenance_out(p, cdb, len); default: return scsi_trace_misc(p, cdb, len); } -- GitLab From 0008f1e7230b16989f72042e44bc078e44a69536 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 24 Mar 2016 17:23:56 +0100 Subject: [PATCH 2083/9938] scsi-trace: define ZBC_IN and ZBC_OUT Add new trace functions for ZBC_IN and ZBC_OUT. Reviewed-by: Doug Gilbert Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_trace.c | 70 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_proto.h | 9 +++++ include/trace/events/scsi.h | 2 ++ 3 files changed, 81 insertions(+) diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index 76d4e6fd9dc1..0ff083bbf5b1 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c @@ -317,6 +317,72 @@ scsi_trace_maintenance_out(struct trace_seq *p, unsigned char *cdb, int len) return ret; } +static const char * +scsi_trace_zbc_in(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u64 zone_id; + u32 alloc_len; + u8 options; + + switch (SERVICE_ACTION16(cdb)) { + case ZI_REPORT_ZONES: + cmd = "REPORT_ZONES"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + zone_id = get_unaligned_be64(&cdb[2]); + alloc_len = get_unaligned_be32(&cdb[10]); + options = cdb[14] & 0x3f; + + trace_seq_printf(p, "%s zone=%llu alloc_len=%u options=%u partial=%u", + cmd, (unsigned long long)zone_id, alloc_len, + options, (cdb[14] >> 7) & 1); + +out: + trace_seq_putc(p, 0); + + return ret; +} + +static const char * +scsi_trace_zbc_out(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = trace_seq_buffer_ptr(p), *cmd; + u64 zone_id; + + switch (SERVICE_ACTION16(cdb)) { + case ZO_CLOSE_ZONE: + cmd = "CLOSE_ZONE"; + break; + case ZO_FINISH_ZONE: + cmd = "FINISH_ZONE"; + break; + case ZO_OPEN_ZONE: + cmd = "OPEN_ZONE"; + break; + case ZO_RESET_WRITE_POINTER: + cmd = "RESET_WRITE_POINTER"; + break; + default: + trace_seq_puts(p, "UNKNOWN"); + goto out; + } + + zone_id = get_unaligned_be64(&cdb[2]); + + trace_seq_printf(p, "%s zone=%llu all=%u", cmd, + (unsigned long long)zone_id, cdb[14] & 1); + +out: + trace_seq_putc(p, 0); + + return ret; +} + static const char * scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) { @@ -373,6 +439,10 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) return scsi_trace_maintenance_in(p, cdb, len); case MAINTENANCE_OUT: return scsi_trace_maintenance_out(p, cdb, len); + case ZBC_IN: + return scsi_trace_zbc_in(p, cdb, len); + case ZBC_OUT: + return scsi_trace_zbc_out(p, cdb, len); default: return scsi_trace_misc(p, cdb, len); } diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index c2ae21cbaa2c..d1defd1ebd95 100644 --- a/include/scsi/scsi_proto.h +++ b/include/scsi/scsi_proto.h @@ -115,6 +115,8 @@ #define VERIFY_16 0x8f #define SYNCHRONIZE_CACHE_16 0x91 #define WRITE_SAME_16 0x93 +#define ZBC_OUT 0x94 +#define ZBC_IN 0x95 #define SERVICE_ACTION_BIDIRECTIONAL 0x9d #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f @@ -143,6 +145,13 @@ #define MO_SET_PRIORITY 0x0e #define MO_SET_TIMESTAMP 0x0f #define MO_MANAGEMENT_PROTOCOL_OUT 0x10 +/* values for ZBC_IN */ +#define ZI_REPORT_ZONES 0x00 +/* values for ZBC_OUT */ +#define ZO_CLOSE_ZONE 0x01 +#define ZO_FINISH_ZONE 0x02 +#define ZO_OPEN_ZONE 0x03 +#define ZO_RESET_WRITE_POINTER 0x04 /* values for variable length command */ #define XDREAD_32 0x03 #define XDWRITE_32 0x04 diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h index 5c0d91f16c74..9a9b3e2550af 100644 --- a/include/trace/events/scsi.h +++ b/include/trace/events/scsi.h @@ -94,6 +94,8 @@ scsi_opcode_name(WRITE_16), \ scsi_opcode_name(VERIFY_16), \ scsi_opcode_name(WRITE_SAME_16), \ + scsi_opcode_name(ZBC_OUT), \ + scsi_opcode_name(ZBC_IN), \ scsi_opcode_name(SERVICE_ACTION_IN_16), \ scsi_opcode_name(READ_32), \ scsi_opcode_name(WRITE_32), \ -- GitLab From 691a837c20df0f4eacd49596a4d57fc566a40545 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Fri, 18 Mar 2016 11:22:48 -0700 Subject: [PATCH 2084/9938] fnic: Fix to cleanup aborted IO to avoid device being offlined by mid-layer If an I/O times out and an abort issued by host, if the abort is successful we need to set scsi status as DID_ABORT. Or else the mid-layer error handler which looks for this error code, will offline the device. Also if the original I/O is not found in fnic firmware, we will consider the abort as successful. The start_time assignment is moved because of the new goto. Fnic driver version changed from 1.6.0.17a to 1.6.0.19, version 1.6.0.18 has been skipped [mkp: Fixed checkpatch warning] Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index ce129e595b55..52a53f8a907a 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.17a" +#define DRV_VERSION "1.6.0.19" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index f3032ca5051b..01b480d33d75 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1091,6 +1091,11 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, atomic64_inc( &term_stats->terminate_fw_timeouts); break; + case FCPIO_ITMF_REJECTED: + FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, + "abort reject recd. id %d\n", + (int)(id & FNIC_TAG_MASK)); + break; case FCPIO_IO_NOT_FOUND: if (CMD_FLAGS(sc) & FNIC_IO_ABTS_ISSUED) atomic64_inc(&abts_stats->abort_io_not_found); @@ -1111,9 +1116,15 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, spin_unlock_irqrestore(io_lock, flags); return; } - CMD_ABTS_STATUS(sc) = hdr_status; + CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE; + /* If the status is IO not found consider it as success */ + if (hdr_status == FCPIO_IO_NOT_FOUND) + CMD_ABTS_STATUS(sc) = FCPIO_SUCCESS; + else + CMD_ABTS_STATUS(sc) = hdr_status; + atomic64_dec(&fnic_stats->io_stats.active_ios); if (atomic64_read(&fnic->io_cmpl_skip)) atomic64_dec(&fnic->io_cmpl_skip); @@ -1926,21 +1937,31 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE; + start_time = io_req->start_time; /* * firmware completed the abort, check the status, - * free the io_req irrespective of failure or success + * free the io_req if successful. If abort fails, + * Device reset will clean the I/O. */ - if (CMD_ABTS_STATUS(sc) != FCPIO_SUCCESS) + if (CMD_ABTS_STATUS(sc) == FCPIO_SUCCESS) + CMD_SP(sc) = NULL; + else { ret = FAILED; - - CMD_SP(sc) = NULL; + spin_unlock_irqrestore(io_lock, flags); + goto fnic_abort_cmd_end; + } spin_unlock_irqrestore(io_lock, flags); - start_time = io_req->start_time; fnic_release_ioreq_buf(fnic, io_req, sc); mempool_free(io_req, fnic->io_req_pool); + if (sc->scsi_done) { + /* Call SCSI completion function to complete the IO */ + sc->result = (DID_ABORT << 16); + sc->scsi_done(sc); + } + fnic_abort_cmd_end: FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no, sc->request->tag, sc, -- GitLab From a36f5dd07dd9098d43d1137ec7a2d6b92aa6d591 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Fri, 18 Mar 2016 11:22:49 -0700 Subject: [PATCH 2085/9938] fnic: Cleanup the I/O pending with fw and has timed out and is used to issue LUN reset In case of LUN reset, the device reset command is issued with one of the I/Os that has timed out on that LUN. The change is to also return this I/O with error status set to DID_RESET. In case when the reset is issued using the sg_reset tool (from sg3_utils) it is a new command and new_sc is set to 1. Fnic driver version changed from 1.6.0.19 to 1.6.0.20 [mkp: Fixed checkpatch warning] Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Reviewed-by: Ewan Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 38 ++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 52a53f8a907a..1023eaea17f3 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.19" +#define DRV_VERSION "1.6.0.20" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 01b480d33d75..588ffd9a33d6 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -2039,7 +2039,9 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, * successfully aborted, 1 otherwise */ static int fnic_clean_pending_aborts(struct fnic *fnic, - struct scsi_cmnd *lr_sc) + struct scsi_cmnd *lr_sc, + bool new_sc) + { int tag, abt_tag; struct fnic_io_req *io_req; @@ -2057,10 +2059,10 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, spin_lock_irqsave(io_lock, flags); sc = scsi_host_find_tag(fnic->lport->host, tag); /* - * ignore this lun reset cmd or cmds that do not belong to - * this lun + * ignore this lun reset cmd if issued using new SC + * or cmds that do not belong to this lun */ - if (!sc || sc == lr_sc || sc->device != lun_dev) { + if (!sc || ((sc == lr_sc) && new_sc) || sc->device != lun_dev) { spin_unlock_irqrestore(io_lock, flags); continue; } @@ -2166,11 +2168,27 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, goto clean_pending_aborts_end; } CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE; - CMD_SP(sc) = NULL; + + /* original sc used for lr is handled by dev reset code */ + if (sc != lr_sc) + CMD_SP(sc) = NULL; spin_unlock_irqrestore(io_lock, flags); - fnic_release_ioreq_buf(fnic, io_req, sc); - mempool_free(io_req, fnic->io_req_pool); + /* original sc used for lr is handled by dev reset code */ + if (sc != lr_sc) { + fnic_release_ioreq_buf(fnic, io_req, sc); + mempool_free(io_req, fnic->io_req_pool); + } + + /* + * Any IO is returned during reset, it needs to call scsi_done + * to return the scsi_cmnd to upper layer. + */ + if (sc->scsi_done) { + /* Set result to let upper SCSI layer retry */ + sc->result = DID_RESET << 16; + sc->scsi_done(sc); + } } schedule_timeout(msecs_to_jiffies(2 * fnic->config.ed_tov)); @@ -2264,6 +2282,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) int tag = 0; DECLARE_COMPLETION_ONSTACK(tm_done); int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/ + bool new_sc = 0; /* Wait for rport to unblock */ fc_block_scsi_eh(sc); @@ -2309,13 +2328,12 @@ int fnic_device_reset(struct scsi_cmnd *sc) * fix the way the EH ioctls work for real, but until * that happens we fail these explicit requests here. */ - if (shost_use_blk_mq(sc->device->host)) - goto fnic_device_reset_end; tag = fnic_scsi_host_start_tag(fnic, sc); if (unlikely(tag == SCSI_NO_TAG)) goto fnic_device_reset_end; tag_gen_flag = 1; + new_sc = 1; } io_lock = fnic_io_lock_hash(fnic, sc); spin_lock_irqsave(io_lock, flags); @@ -2450,7 +2468,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) * the lun reset cmd. If all cmds get cleaned, the lun reset * succeeds */ - if (fnic_clean_pending_aborts(fnic, sc)) { + if (fnic_clean_pending_aborts(fnic, sc, new_sc)) { spin_lock_irqsave(io_lock, flags); io_req = (struct fnic_io_req *)CMD_SP(sc); FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, -- GitLab From 1b6ac5e3ff354652ca59240e1ba8b2d22539df07 Mon Sep 17 00:00:00 2001 From: Satish Kharat Date: Fri, 18 Mar 2016 11:22:50 -0700 Subject: [PATCH 2086/9938] fnic: Using rport->dd_data to check rport online instead of rport_lookup. When issuing I/O we check if rport is online through libfc rport_lookup() function which needs to be protected by mutex lock that cannot acquired in I/O context. The change is to use midlayer remote port s dd_data which is preserved until its devloss timeout and no protection is required. The the scsi_cmnd error code is expected to be in the left 16 bits of the result field. Changed to correct this. Fnic driver version changed from 1.6.0.20 to 1.6.0.21 Signed-off-by: Satish Kharat Signed-off-by: Sesidhar Baddela Reviewed-by: Ewan Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 1023eaea17f3..9ddc9200e0a4 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.20" +#define DRV_VERSION "1.6.0.21" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 588ffd9a33d6..d9fd2f841585 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -439,7 +439,6 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ int sg_count = 0; unsigned long flags = 0; unsigned long ptr; - struct fc_rport_priv *rdata; spinlock_t *io_lock = NULL; int io_lock_acquired = 0; @@ -455,14 +454,17 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ return 0; } - rdata = lp->tt.rport_lookup(lp, rport->port_id); - if (!rdata || (rdata->rp_state == RPORT_ST_DELETE)) { - FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, - "returning IO as rport is removed\n"); - atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); - sc->result = DID_NO_CONNECT; - done(sc); - return 0; + if (rport) { + struct fc_rport_libfc_priv *rp = rport->dd_data; + + if (!rp || rp->rp_state != RPORT_ST_READY) { + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + "returning DID_NO_CONNECT for IO as rport is removed\n"); + atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); + sc->result = DID_NO_CONNECT<<16; + done(sc); + return 0; + } } if (lp->state != LPORT_ST_READY || !(lp->link_up)) -- GitLab From 62055172fbcd6055a10b010c6be65088fd7046b3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 28 Mar 2016 14:37:28 -0700 Subject: [PATCH 2087/9938] scsi_transport_fc: Unexport scsi_is_fc_vport() Running the command "git grep -nHw scsi_is_fc_vport" shows that this function is only called from inside scsi_transport_fc.c. Hence unexport this function. Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: James Smart Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index bf28c688c72a..0f3a3869524b 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2027,11 +2027,10 @@ static void fc_vport_dev_release(struct device *dev) kfree(vport); } -int scsi_is_fc_vport(const struct device *dev) +static int scsi_is_fc_vport(const struct device *dev) { return dev->release == fc_vport_dev_release; } -EXPORT_SYMBOL(scsi_is_fc_vport); static int fc_vport_match(struct attribute_container *cont, struct device *dev) -- GitLab From 5cfe8d5b4c6f359a23738bbdc54a6007c6d6bdb1 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 16:25:21 -0700 Subject: [PATCH 2088/9938] qla2xxx: Indicate out-of-memory with -ENOMEM In the Linux kernel it is preferred to return a meaningful error code instead of -1. This patch does not change the behavior of the caller of qla82xx_pinit_from_rom(). Signed-off-by: Bart Van Assche Cc: Quinn Tran Cc: Himanshu Madhani Cc: Christoph Hellwig Reviewed-by: Johannes Thumshirn Acked-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index b6b4cfdd7620..54380b434b30 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1229,7 +1229,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) if (buf == NULL) { ql_log(ql_log_fatal, vha, 0x010c, "Unable to allocate memory.\n"); - return -1; + return -ENOMEM; } for (i = 0; i < n; i++) { -- GitLab From 3907adf67a1559d455f90b0de4c977dd456fe311 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:26:46 -0700 Subject: [PATCH 2089/9938] libiscsi: Unexport iscsi_eh_target_reset() Running "git grep -nHw iscsi_eh_target_reset" shows that this function is only called from inside the drivers/scsi/libiscsi.c source file. Hence unexport this function. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 6bffd91b973a..120150a25dc3 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2423,7 +2423,7 @@ static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) * * This will attempt to send a warm target reset. */ -int iscsi_eh_target_reset(struct scsi_cmnd *sc) +static int iscsi_eh_target_reset(struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; struct iscsi_session *session; @@ -2495,7 +2495,6 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc) mutex_unlock(&session->eh_mutex); return rc; } -EXPORT_SYMBOL_GPL(iscsi_eh_target_reset); /** * iscsi_eh_recover_target - reset target and possibly the session -- GitLab From e9e410e8e8537b383b0325f3d03c522aba36fa0b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:27:08 -0700 Subject: [PATCH 2090/9938] libiscsi: Remove set-but-not-used variables Avoid that building with W=1 causes gcc to report warnings about set-but-not-used variables. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 120150a25dc3..c051694bfcb0 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2127,7 +2127,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) struct iscsi_conn *conn; struct iscsi_task *task; struct iscsi_tm *hdr; - int rc, age; + int age; cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; @@ -2188,10 +2188,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) hdr = &conn->tmhdr; iscsi_prep_abort_task_pdu(task, hdr); - if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) { - rc = FAILED; + if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) goto failed; - } switch (conn->tmf_state) { case TMF_SUCCESS: -- GitLab From 6fe3ed88fe12aeb4ace4877ce1457993ecc196c3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:27:27 -0700 Subject: [PATCH 2091/9938] scsi_transport_iscsi: Remove set-but-not-used variables Avoid that building with W=1 causes gcc to report warnings about set-but-not-used variables. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7a759a9257ea..5a7be7ee9f5d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2070,13 +2070,10 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session); int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) { - struct Scsi_Host *shost = iscsi_session_to_shost(session); - struct iscsi_cls_host *ihost; unsigned long flags; int id = 0; int err; - ihost = shost->shost_data; session->sid = atomic_add_return(1, &iscsi_session_nr); if (target_id == ISCSI_MAX_TARGET) { -- GitLab From 7a15fdfab012dddc00ee2c859cf50669e3dae3df Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:27:47 -0700 Subject: [PATCH 2092/9938] scsi_transport_iscsi: Unexport iscsi_is_flashnode_conn_dev() The output of "git grep -nHw iscsi_is_flashnode_conn_dev" shows that this function is only called from inside source file drivers/scsi/scsi_transport_iscsi.c. Hence unexport this function. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 5a7be7ee9f5d..ea5a9f37c9d2 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1324,11 +1324,10 @@ EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn); * 1 on success * 0 on failure */ -int iscsi_is_flashnode_conn_dev(struct device *dev, void *data) +static int iscsi_is_flashnode_conn_dev(struct device *dev, void *data) { return dev->bus == &iscsi_flashnode_bus; } -EXPORT_SYMBOL_GPL(iscsi_is_flashnode_conn_dev); static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn) { -- GitLab From 4c1340af8854836796bc50555de446286dce4625 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 30 Mar 2016 11:28:11 -0700 Subject: [PATCH 2093/9938] scsi_transport_iscsi: Declare local symbols static Avoid that building with W=1 causes gcc to report warnings about symbols that have not been declared. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index ea5a9f37c9d2..42bca619f854 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1009,7 +1009,7 @@ static void iscsi_flashnode_sess_release(struct device *dev) kfree(fnode_sess); } -struct device_type iscsi_flashnode_sess_dev_type = { +static struct device_type iscsi_flashnode_sess_dev_type = { .name = "iscsi_flashnode_sess_dev_type", .groups = iscsi_flashnode_sess_attr_groups, .release = iscsi_flashnode_sess_release, @@ -1195,13 +1195,13 @@ static void iscsi_flashnode_conn_release(struct device *dev) kfree(fnode_conn); } -struct device_type iscsi_flashnode_conn_dev_type = { +static struct device_type iscsi_flashnode_conn_dev_type = { .name = "iscsi_flashnode_conn_dev_type", .groups = iscsi_flashnode_conn_attr_groups, .release = iscsi_flashnode_conn_release, }; -struct bus_type iscsi_flashnode_bus; +static struct bus_type iscsi_flashnode_bus; int iscsi_flashnode_bus_match(struct device *dev, struct device_driver *drv) @@ -1212,7 +1212,7 @@ int iscsi_flashnode_bus_match(struct device *dev, } EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match); -struct bus_type iscsi_flashnode_bus = { +static struct bus_type iscsi_flashnode_bus = { .name = "iscsi_flashnode", .match = &iscsi_flashnode_bus_match, }; -- GitLab From de96e9c5b82801ea17558c271730fdc2aa5e7e77 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:27 -0700 Subject: [PATCH 2094/9938] lpfc: Correct LOGO handling during login After a link bounce, when a remote port issues a LOGO while a REGLOGIN is pending on that port, the driver does not clean up the ndlp structure. May result in stack traces in the console log. Fix: Clear the NLP_REG_LOGIN_SEND flag on the ndlp in the routine Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 ++ drivers/scsi/lpfc/lpfc_sli.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 193733e8c823..9b539e2e864b 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1512,6 +1512,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, if ((mb = phba->sli.mbox_active)) { if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; lpfc_nlp_put(ndlp); mb->context2 = NULL; mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; @@ -1527,6 +1528,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, __lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); } + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; lpfc_nlp_put(ndlp); list_del(&mb->list); phba->sli.mboxq_cnt--; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 2207726b88ee..035105a24298 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2211,6 +2211,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) rpi = pmb->u.mb.un.varWords[0]; vpi = pmb->u.mb.un.varRegLogin.vpi; lpfc_unreg_login(phba, vpi, rpi, pmb); + pmb->vport = vport; pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if (rc != MBX_NOT_FINISHED) -- GitLab From ae09c765109293b600ba9169aa3d632e1ac1a843 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:28 -0700 Subject: [PATCH 2095/9938] lpfc: Fix DMA faults observed upon plugging loopback connector Driver didn't program the REG_VFI mailbox correctly, giving the adapter bad addresses. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_mbox.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index f87f90e9b7df..1e34b5408a29 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2145,10 +2145,12 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]); reg_vfi->e_d_tov = phba->fc_edtov; reg_vfi->r_a_tov = phba->fc_ratov; - reg_vfi->bde.addrHigh = putPaddrHigh(phys); - reg_vfi->bde.addrLow = putPaddrLow(phys); - reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); - reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + if (phys) { + reg_vfi->bde.addrHigh = putPaddrHigh(phys); + reg_vfi->bde.addrLow = putPaddrLow(phys); + reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); + reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + } bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID); /* Only FC supports upd bit */ -- GitLab From a6517db9006eb618dfde54f4bf6a9a8bc21e16e7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:29 -0700 Subject: [PATCH 2096/9938] lpfc: Fix crash when unregistering default rpi. The default rpi completion handler does back to back puts to force the removal of the ndlp. This ends up calling lpfc_unreg_rpi after the reference count is at 0. Fix: Check the reference count of the ndlp before getting the ref to make sure we are not getting a reference on a removed object. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 25b5dcd1a5c8..b3bf230f714a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4545,7 +4545,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) (!(vport->load_flag & FC_UNLOADING)) && (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == - LPFC_SLI_INTF_IF_TYPE_2)) { + LPFC_SLI_INTF_IF_TYPE_2) && + (atomic_read(&ndlp->kref.refcount) > 0)) { mbox->context1 = lpfc_nlp_get(ndlp); mbox->mbox_cmpl = lpfc_sli4_unreg_rpi_cmpl_clr; -- GitLab From b5c539583988b70bddea73f333c640fc93a62e88 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:30 -0700 Subject: [PATCH 2097/9938] lpfc: Utilize embedded CDB logic to minimize IO latency Pass cmd iu payloads inline to adapter job structure rather than as separate dma buffers. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_attr.c | 1 - drivers/scsi/lpfc/lpfc_hw4.h | 6 ++ drivers/scsi/lpfc/lpfc_init.c | 20 +++++- drivers/scsi/lpfc/lpfc_sli.c | 128 +++++++++++++++++++++++++++++----- 5 files changed, 136 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 90a3ca5a4dbd..da237d9c4b55 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -694,6 +694,7 @@ struct lpfc_hba { uint8_t wwnn[8]; uint8_t wwpn[8]; uint32_t RandomData[7]; + uint32_t fcp_embed_io; /* HBA Config Parameters */ uint32_t cfg_ack0; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 343ae9482891..d4559a6175e2 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5150,7 +5150,6 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); } - /* * Dynamic FC Host Attributes Support */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 608f9415fb08..aea00f8be9ac 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2865,6 +2865,9 @@ struct lpfc_sli4_parameters { uint32_t word17; uint32_t word18; uint32_t word19; +#define cfg_ext_embed_cb_SHIFT 0 +#define cfg_ext_embed_cb_MASK 0x00000001 +#define cfg_ext_embed_cb_WORD word19 }; struct lpfc_mbx_get_sli4_parameters { @@ -3919,6 +3922,9 @@ union lpfc_wqe { union lpfc_wqe128 { uint32_t words[32]; struct lpfc_wqe_generic generic; + struct fcp_icmnd64_wqe fcp_icmd; + struct fcp_iread64_wqe fcp_iread; + struct fcp_iwrite64_wqe fcp_iwrite; struct xmit_seq64_wqe xmit_sequence; struct gen_req64_wqe gen_req; }; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f57d02c3b6cf..f0d0852bee0d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7264,8 +7264,15 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.fcp_cq[idx] = qdesc; /* Create Fast Path FCP WQs */ - qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.wq_esize, - phba->sli4_hba.wq_ecount); + if (phba->fcp_embed_io) { + qdesc = lpfc_sli4_queue_alloc(phba, + LPFC_WQE128_SIZE, + LPFC_WQE128_DEF_COUNT); + } else { + qdesc = lpfc_sli4_queue_alloc(phba, + phba->sli4_hba.wq_esize, + phba->sli4_hba.wq_ecount); + } if (!qdesc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0503 Failed allocate fast-path FCP " @@ -9510,6 +9517,15 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (sli4_params->sge_supp_len > LPFC_MAX_SGE_SIZE) sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE; + /* + * Issue IOs with CDB embedded in WQE to minimized the number + * of DMAs the firmware has to do. Setting this to 1 also forces + * the driver to use 128 bytes WQEs for FCP IOs. + */ + if (bf_get(cfg_ext_embed_cb, mbx_sli4_parameters)) + phba->fcp_embed_io = 1; + else + phba->fcp_embed_io = 0; return 0; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 035105a24298..9c8368a7149a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4689,6 +4689,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) break; } + phba->fcp_embed_io = 0; /* SLI4 FC support only */ rc = lpfc_sli_config_port(phba, mode); @@ -6321,10 +6322,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) mqe = &mboxq->u.mqe; phba->sli_rev = bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev); - if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev)) + if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev)) { phba->hba_flag |= HBA_FCOE_MODE; - else + phba->fcp_embed_io = 0; /* SLI4 FC support only */ + } else { phba->hba_flag &= ~HBA_FCOE_MODE; + } if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) == LPFC_DCBX_CEE_MODE) @@ -8219,12 +8222,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, else command_type = ELS_COMMAND_NON_FIP; + if (phba->fcp_embed_io) + memset(wqe, 0, sizeof(union lpfc_wqe128)); /* Some of the fields are in the right position already */ memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); - abort_tag = (uint32_t) iocbq->iotag; - xritag = iocbq->sli4_xritag; wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */ wqe->generic.wqe_com.word10 = 0; + + abort_tag = (uint32_t) iocbq->iotag; + xritag = iocbq->sli4_xritag; /* words0-2 bpl convert bde */ if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / @@ -8373,11 +8379,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.ulpFCP2Rcvy); bf_set(wqe_lnk, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpXS); /* Always open the exchange */ - bf_set(wqe_xc, &wqe->fcp_iwrite.wqe_com, 0); bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0); bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU); bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1); if (iocbq->iocb_flag & LPFC_IO_OAS) { @@ -8388,6 +8392,35 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, (phba->cfg_XLanePriority << 1)); } } + /* Note, word 10 is already initialized to 0 */ + + if (phba->fcp_embed_io) { + struct lpfc_scsi_buf *lpfc_cmd; + struct sli4_sge *sgl; + union lpfc_wqe128 *wqe128; + struct fcp_cmnd *fcp_cmnd; + uint32_t *ptr; + + /* 128 byte wqe support here */ + wqe128 = (union lpfc_wqe128 *)wqe; + + lpfc_cmd = iocbq->context1; + sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; + fcp_cmnd = lpfc_cmd->fcp_cmnd; + + /* Word 0-2 - FCP_CMND */ + wqe128->generic.bde.tus.f.bdeFlags = + BUFF_TYPE_BDE_IMMED; + wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe128->generic.bde.addrHigh = 0; + wqe128->generic.bde.addrLow = 88; /* Word 22 */ + + bf_set(wqe_wqes, &wqe128->fcp_iwrite.wqe_com, 1); + + /* Word 22-29 FCP CMND Payload */ + ptr = &wqe128->words[22]; + memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); + } break; case CMD_FCP_IREAD64_CR: /* word3 iocb=iotag wqe=payload_offset_len */ @@ -8402,11 +8435,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.ulpFCP2Rcvy); bf_set(wqe_lnk, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpXS); /* Always open the exchange */ - bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0); bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0); bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU); bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); if (iocbq->iocb_flag & LPFC_IO_OAS) { @@ -8417,6 +8448,35 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, (phba->cfg_XLanePriority << 1)); } } + /* Note, word 10 is already initialized to 0 */ + + if (phba->fcp_embed_io) { + struct lpfc_scsi_buf *lpfc_cmd; + struct sli4_sge *sgl; + union lpfc_wqe128 *wqe128; + struct fcp_cmnd *fcp_cmnd; + uint32_t *ptr; + + /* 128 byte wqe support here */ + wqe128 = (union lpfc_wqe128 *)wqe; + + lpfc_cmd = iocbq->context1; + sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; + fcp_cmnd = lpfc_cmd->fcp_cmnd; + + /* Word 0-2 - FCP_CMND */ + wqe128->generic.bde.tus.f.bdeFlags = + BUFF_TYPE_BDE_IMMED; + wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe128->generic.bde.addrHigh = 0; + wqe128->generic.bde.addrLow = 88; /* Word 22 */ + + bf_set(wqe_wqes, &wqe128->fcp_iread.wqe_com, 1); + + /* Word 22-29 FCP CMND Payload */ + ptr = &wqe128->words[22]; + memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); + } break; case CMD_FCP_ICMND64_CR: /* word3 iocb=iotag wqe=payload_offset_len */ @@ -8428,13 +8488,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, /* word3 iocb=IO_TAG wqe=reserved */ bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); /* Always open the exchange */ - bf_set(wqe_xc, &wqe->fcp_icmd.wqe_com, 0); bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 1); bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_WRITE); bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, LPFC_WQE_LENLOC_NONE); - bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0); bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, iocbq->iocb.ulpFCP2Rcvy); if (iocbq->iocb_flag & LPFC_IO_OAS) { @@ -8445,6 +8503,35 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, (phba->cfg_XLanePriority << 1)); } } + /* Note, word 10 is already initialized to 0 */ + + if (phba->fcp_embed_io) { + struct lpfc_scsi_buf *lpfc_cmd; + struct sli4_sge *sgl; + union lpfc_wqe128 *wqe128; + struct fcp_cmnd *fcp_cmnd; + uint32_t *ptr; + + /* 128 byte wqe support here */ + wqe128 = (union lpfc_wqe128 *)wqe; + + lpfc_cmd = iocbq->context1; + sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; + fcp_cmnd = lpfc_cmd->fcp_cmnd; + + /* Word 0-2 - FCP_CMND */ + wqe128->generic.bde.tus.f.bdeFlags = + BUFF_TYPE_BDE_IMMED; + wqe128->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe128->generic.bde.addrHigh = 0; + wqe128->generic.bde.addrLow = 88; /* Word 22 */ + + bf_set(wqe_wqes, &wqe128->fcp_icmd.wqe_com, 1); + + /* Word 22-29 FCP CMND Payload */ + ptr = &wqe128->words[22]; + memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); + } break; case CMD_GEN_REQUEST64_CR: /* For this command calculate the xmit length of the @@ -8676,12 +8763,19 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { struct lpfc_sglq *sglq; - union lpfc_wqe wqe; + union lpfc_wqe *wqe; + union lpfc_wqe128 wqe128; struct lpfc_queue *wq; struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number]; lockdep_assert_held(&phba->hbalock); + /* + * The WQE can be either 64 or 128 bytes, + * so allocate space on the stack assuming the largest. + */ + wqe = (union lpfc_wqe *)&wqe128; + if (piocb->sli4_xritag == NO_XRI) { if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) @@ -8728,7 +8822,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, return IOCB_ERROR; } - if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) + if (lpfc_sli4_iocb2wqe(phba, piocb, wqe)) return IOCB_ERROR; if ((piocb->iocb_flag & LPFC_IO_FCP) || @@ -8738,12 +8832,12 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, } else { wq = phba->sli4_hba.oas_wq; } - if (lpfc_sli4_wq_put(wq, &wqe)) + if (lpfc_sli4_wq_put(wq, wqe)) return IOCB_ERROR; } else { if (unlikely(!phba->sli4_hba.els_wq)) return IOCB_ERROR; - if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) + if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, wqe)) return IOCB_ERROR; } lpfc_sli_ringtxcmpl_put(phba, pring, piocb); @@ -8758,9 +8852,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, * pointer from the lpfc_hba struct. * * Return codes: - * IOCB_ERROR - Error - * IOCB_SUCCESS - Success - * IOCB_BUSY - Busy + * IOCB_ERROR - Error + * IOCB_SUCCESS - Success + * IOCB_BUSY - Busy **/ int __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, -- GitLab From 342b59caa66240b670285d519fdfe2c44289b516 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:31 -0700 Subject: [PATCH 2098/9938] lpfc: Fix Device discovery failures during switch reboot test. When the switch is rebooted, the lpfc driver fails to log into the fabric, and Unexpected timeout message is seen. Fix: Do not issue RegVFI if the FLOGI was internally aborted. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 7f5abb8f52bc..27dcde95ac0f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1069,7 +1069,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_sli4_unreg_all_rpis(vport); } } - lpfc_issue_reg_vfi(vport); + + /* Do not register VFI if the driver aborted FLOGI */ + if (!lpfc_error_lost_link(irsp)) + lpfc_issue_reg_vfi(vport); lpfc_nlp_put(ndlp); goto out; } -- GitLab From 56204984761d80b973a0a534c42566ad78303766 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:32 -0700 Subject: [PATCH 2099/9938] lpfc: Add support for SmartSAN 2.0 Revise versions to reflect SmartSAN 2.0 support RDP updated to support additional descriptors: Credit descriptor Optical Element Data descriptors for Temperature, Voltage, Bias current, TX power and TX power. Optical Product Data descriptor. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 4 +- drivers/scsi/lpfc/lpfc_els.c | 153 +++++++++++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_hw.h | 73 +++++++++++++++-- drivers/scsi/lpfc/lpfc_hw4.h | 21 ++++- 4 files changed, 243 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 79e261d2a0c8..982039e73d33 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -2322,7 +2322,7 @@ lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; memset(ae, 0, 256); - strncpy(ae->un.AttrString, "Smart SAN Version 1.0", + strncpy(ae->un.AttrString, "Smart SAN Version 2.0", sizeof(ae->un.AttrString)); len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString)); @@ -2397,7 +2397,7 @@ lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, uint32_t size; ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - ae->un.AttrInt = cpu_to_be32(0); + ae->un.AttrInt = cpu_to_be32(1); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); ad->AttrType = cpu_to_be16(RPRT_SMART_SECURITY); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 27dcde95ac0f..9459ac451600 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -4708,6 +4708,144 @@ lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc, desc->length = cpu_to_be32(sizeof(desc->info)); } +void +lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat, + struct lpfc_vport *vport) +{ + desc->tag = cpu_to_be32(RDP_BBC_DESC_TAG); + + desc->bbc_info.port_bbc = cpu_to_be32( + vport->fc_sparam.cmn.bbCreditMsb | + vport->fc_sparam.cmn.bbCreditlsb << 8); + if (vport->phba->fc_topology != LPFC_TOPOLOGY_LOOP) + desc->bbc_info.attached_port_bbc = cpu_to_be32( + vport->phba->fc_fabparam.cmn.bbCreditMsb | + vport->phba->fc_fabparam.cmn.bbCreditlsb << 8); + else + desc->bbc_info.attached_port_bbc = 0; + + desc->bbc_info.rtt = 0; + desc->length = cpu_to_be32(sizeof(desc->bbc_info)); +} + +void +lpfc_rdp_res_oed_temp_desc(struct fc_rdp_oed_sfp_desc *desc, uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_TEMP_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_TEMP_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_TEMP_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_TEMP_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_TEMPERATURE) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_oed_voltage_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_VOLTAGE_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_VOLTAGE_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_VOLTAGE_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_VOLTAGE_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_VOLTAGE) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_oed_txbias_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_BIAS_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_BIAS_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_BIAS_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_BIAS_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_TXBIAS) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_oed_txpower_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_TXPOWER_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_TXPOWER_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_TXPOWER_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_TXPOWER_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_TXPOWER) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + + +void +lpfc_rdp_res_oed_rxpower_desc(struct fc_rdp_oed_sfp_desc *desc, + uint8_t *page_a2) +{ + uint32_t flags; + + desc->tag = cpu_to_be32(RDP_OED_DESC_TAG); + + desc->oed_info.hi_alarm = + cpu_to_be16(page_a2[SSF_RXPOWER_HIGH_ALARM]); + desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_RXPOWER_LOW_ALARM]); + desc->oed_info.hi_warning = + cpu_to_be16(page_a2[SSF_RXPOWER_HIGH_WARNING]); + desc->oed_info.lo_warning = + cpu_to_be16(page_a2[SSF_RXPOWER_LOW_WARNING]); + flags = 0xf; /* All four are valid */ + flags |= ((0xf & RDP_OED_RXPOWER) << RDP_OED_TYPE_SHIFT); + desc->oed_info.function_flags = cpu_to_be32(flags); + desc->length = cpu_to_be32(sizeof(desc->oed_info)); +} + +void +lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc, + uint8_t *page_a0, struct lpfc_vport *vport) +{ + desc->tag = cpu_to_be32(RDP_OPD_DESC_TAG); + memcpy(desc->opd_info.vendor_name, &page_a0[SSF_VENDOR_NAME], 16); + memcpy(desc->opd_info.model_number, &page_a0[SSF_VENDOR_PN], 16); + memcpy(desc->opd_info.serial_number, &page_a0[SSF_VENDOR_SN], 16); + memcpy(desc->opd_info.revision, &page_a0[SSF_VENDOR_REV], 2); + memcpy(desc->opd_info.date, &page_a0[SSF_DATE_CODE], 8); + desc->length = cpu_to_be32(sizeof(desc->opd_info)); +} + int lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat) { @@ -4779,6 +4917,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) if (rdp_cap == 0) rdp_cap = RDP_CAP_UNKNOWN; + if (phba->cfg_link_speed != LPFC_USER_LINK_SPEED_AUTO) + rdp_cap |= RDP_CAP_USER_CONFIGURED; desc->info.port_speed.capabilities = cpu_to_be16(rdp_cap); desc->length = cpu_to_be32(sizeof(desc->info)); @@ -4878,6 +5018,19 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, lpfc_rdp_res_diag_port_names(&rdp_res->diag_port_names_desc, phba); lpfc_rdp_res_attach_port_names(&rdp_res->attached_port_names_desc, vport, ndlp); + lpfc_rdp_res_bbc_desc(&rdp_res->bbc_desc, &rdp_context->link_stat, + vport); + lpfc_rdp_res_oed_temp_desc(&rdp_res->oed_temp_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_voltage_desc(&rdp_res->oed_voltage_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_txbias_desc(&rdp_res->oed_txbias_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_txpower_desc(&rdp_res->oed_txpower_desc, + rdp_context->page_a2); + lpfc_rdp_res_oed_rxpower_desc(&rdp_res->oed_rxpower_desc, + rdp_context->page_a2); + lpfc_rdp_res_opd_desc(&rdp_res->opd_desc, rdp_context->page_a0, vport); fec_size = lpfc_rdp_res_fec_desc(&rdp_res->fec_desc, &rdp_context->link_stat); rdp_res->length = cpu_to_be32(fec_size + RDP_DESC_PAYLOAD_SIZE); diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index dd20412c7e4c..41a961e00f29 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1134,9 +1134,10 @@ struct fc_rdp_link_error_status_desc { #define RDP_PS_16GB 0x0400 #define RDP_PS_32GB 0x0200 -#define RDP_CAP_UNKNOWN 0x0001 -#define RDP_PS_UNKNOWN 0x0002 -#define RDP_PS_NOT_ESTABLISHED 0x0001 +#define RDP_CAP_USER_CONFIGURED 0x0002 +#define RDP_CAP_UNKNOWN 0x0001 +#define RDP_PS_UNKNOWN 0x0002 +#define RDP_PS_NOT_ESTABLISHED 0x0001 struct fc_rdp_port_speed { uint16_t capabilities; @@ -1192,6 +1193,58 @@ struct fc_rdp_sfp_desc { struct fc_rdp_sfp_info sfp_info; }; +/* Buffer Credit Descriptor */ +struct fc_rdp_bbc_info { + uint32_t port_bbc; /* FC_Port buffer-to-buffer credit */ + uint32_t attached_port_bbc; + uint32_t rtt; /* Round trip time */ +}; +#define RDP_BBC_DESC_TAG 0x00010006 +struct fc_rdp_bbc_desc { + uint32_t tag; + uint32_t length; + struct fc_rdp_bbc_info bbc_info; +}; + +#define RDP_OED_TEMPERATURE 0x1 +#define RDP_OED_VOLTAGE 0x2 +#define RDP_OED_TXBIAS 0x3 +#define RDP_OED_TXPOWER 0x4 +#define RDP_OED_RXPOWER 0x5 + +#define RDP_OED_TYPE_SHIFT 28 +/* Optical Element Data descriptor */ +struct fc_rdp_oed_info { + uint16_t hi_alarm; + uint16_t lo_alarm; + uint16_t hi_warning; + uint16_t lo_warning; + uint32_t function_flags; +}; +#define RDP_OED_DESC_TAG 0x00010007 +struct fc_rdp_oed_sfp_desc { + uint32_t tag; + uint32_t length; + struct fc_rdp_oed_info oed_info; +}; + +/* Optical Product Data descriptor */ +struct fc_rdp_opd_sfp_info { + uint8_t vendor_name[16]; + uint8_t model_number[16]; + uint8_t serial_number[16]; + uint8_t reserved[2]; + uint8_t revision[2]; + uint8_t date[8]; +}; + +#define RDP_OPD_DESC_TAG 0x00010008 +struct fc_rdp_opd_sfp_desc { + uint32_t tag; + uint32_t length; + struct fc_rdp_opd_sfp_info opd_info; +}; + struct fc_rdp_req_frame { uint32_t rdp_command; /* ELS command opcode (0x18)*/ uint32_t rdp_des_length; /* RDP Payload Word 1 */ @@ -1208,7 +1261,14 @@ struct fc_rdp_res_frame { struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13-21 */ struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22-27 */ struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28-33 */ - struct fc_fec_rdp_desc fec_desc; /* FC Word 34 - 37 */ + struct fc_rdp_bbc_desc bbc_desc; /* FC Word 34-38*/ + struct fc_rdp_oed_sfp_desc oed_temp_desc; /* FC Word 39-43*/ + struct fc_rdp_oed_sfp_desc oed_voltage_desc; /* FC word 44-48*/ + struct fc_rdp_oed_sfp_desc oed_txbias_desc; /* FC word 49-53*/ + struct fc_rdp_oed_sfp_desc oed_txpower_desc; /* FC word 54-58*/ + struct fc_rdp_oed_sfp_desc oed_rxpower_desc; /* FC word 59-63*/ + struct fc_rdp_opd_sfp_desc opd_desc; /* FC word 64-80*/ + struct fc_fec_rdp_desc fec_desc; /* FC word 81-84*/ }; @@ -1216,7 +1276,10 @@ struct fc_rdp_res_frame { + sizeof(struct fc_rdp_sfp_desc) \ + sizeof(struct fc_rdp_port_speed_desc) \ + sizeof(struct fc_rdp_link_error_status_desc) \ - + (sizeof(struct fc_rdp_port_name_desc) * 2)) + + (sizeof(struct fc_rdp_port_name_desc) * 2) \ + + sizeof(struct fc_rdp_bbc_desc) \ + + (sizeof(struct fc_rdp_oed_sfp_desc) * 5) \ + + sizeof(struct fc_rdp_opd_sfp_desc)) /******** FDMI ********/ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index aea00f8be9ac..634c9b1c6710 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2557,7 +2557,26 @@ struct lpfc_mbx_memory_dump_type3 { /* SFF-8472 Table 3.1a Diagnostics: Data Fields Address/Page A2 */ -#define SSF_AW_THRESHOLDS 0 +#define SSF_TEMP_HIGH_ALARM 0 +#define SSF_TEMP_LOW_ALARM 2 +#define SSF_TEMP_HIGH_WARNING 4 +#define SSF_TEMP_LOW_WARNING 6 +#define SSF_VOLTAGE_HIGH_ALARM 8 +#define SSF_VOLTAGE_LOW_ALARM 10 +#define SSF_VOLTAGE_HIGH_WARNING 12 +#define SSF_VOLTAGE_LOW_WARNING 14 +#define SSF_BIAS_HIGH_ALARM 16 +#define SSF_BIAS_LOW_ALARM 18 +#define SSF_BIAS_HIGH_WARNING 20 +#define SSF_BIAS_LOW_WARNING 22 +#define SSF_TXPOWER_HIGH_ALARM 24 +#define SSF_TXPOWER_LOW_ALARM 26 +#define SSF_TXPOWER_HIGH_WARNING 28 +#define SSF_TXPOWER_LOW_WARNING 30 +#define SSF_RXPOWER_HIGH_ALARM 32 +#define SSF_RXPOWER_LOW_ALARM 34 +#define SSF_RXPOWER_HIGH_WARNING 36 +#define SSF_RXPOWER_LOW_WARNING 38 #define SSF_EXT_CAL_CONSTANTS 56 #define SSF_CC_DMI 95 #define SFF_TEMPERATURE_B1 96 -- GitLab From 8663cbbe3ba0d8142faec48bbab0dc3482e3007d Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:33 -0700 Subject: [PATCH 2100/9938] lpfc: Fix interaction between fdmi_on and enable_SmartSAN Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 - drivers/scsi/lpfc/lpfc_attr.c | 23 +++++++---------------- drivers/scsi/lpfc/lpfc_els.c | 16 +++++++++------- drivers/scsi/lpfc/lpfc_init.c | 5 +++-- drivers/scsi/lpfc/lpfc_vport.c | 3 ++- 5 files changed, 21 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index da237d9c4b55..283942a4ae82 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -758,7 +758,6 @@ struct lpfc_hba { uint32_t cfg_fdmi_on; #define LPFC_FDMI_NO_SUPPORT 0 /* FDMI not supported */ #define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */ -#define LPFC_FDMI_SMART_SAN 2 /* SmartSAN supported */ uint32_t cfg_enable_SmartSAN; lpfc_vpd_t vpd; /* vital product data */ diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index d4559a6175e2..9528f863f219 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4584,15 +4584,14 @@ LPFC_ATTR_R(enable_SmartSAN, 0, 0, 1, "Enable SmartSAN functionality"); # lpfc_fdmi_on: Controls FDMI support. # 0 No FDMI support (default) # 1 Traditional FDMI support -# 2 Smart SAN support -# If lpfc_enable_SmartSAN is set 1, the driver sets lpfc_fdmi_on to value 2 -# overwriting the current value. If lpfc_enable_SmartSAN is set 0, the -# driver uses the current value of lpfc_fdmi_on provided it has value 0 or 1. -# A value of 2 with lpfc_enable_SmartSAN set to 0 causes the driver to -# set lpfc_fdmi_on back to 1. -# Value range [0,2]. Default value is 0. +# Traditional FDMI support means the driver will assume FDMI-2 support; +# however, if that fails, it will fallback to FDMI-1. +# If lpfc_enable_SmartSAN is set to 1, the driver ignores lpfc_fdmi_on. +# If lpfc_enable_SmartSAN is set 0, the driver uses the current value of +# lpfc_fdmi_on. +# Value range [0,1]. Default value is 0. */ -LPFC_ATTR_R(fdmi_on, 0, 0, 2, "Enable FDMI support"); +LPFC_ATTR_R(fdmi_on, 0, 0, 1, "Enable FDMI support"); /* # Specifies the maximum number of ELS cmds we can have outstanding (for @@ -5856,14 +5855,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) else phba->cfg_poll = lpfc_poll; - /* Ensure fdmi_on and enable_SmartSAN don't conflict */ - if (phba->cfg_enable_SmartSAN) { - phba->cfg_fdmi_on = LPFC_FDMI_SMART_SAN; - } else { - if (phba->cfg_fdmi_on == LPFC_FDMI_SMART_SAN) - phba->cfg_fdmi_on = LPFC_FDMI_SUPPORT; - } - phba->cfg_soft_wwnn = 0L; phba->cfg_soft_wwpn = 0L; lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 9459ac451600..6cc1af42af36 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -690,16 +690,17 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp); if (fabric_param_changed) { /* Reset FDMI attribute masks based on config parameter */ - if (phba->cfg_fdmi_on == LPFC_FDMI_NO_SUPPORT) { - vport->fdmi_hba_mask = 0; - vport->fdmi_port_mask = 0; - } else { + if (phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) { /* Setup appropriate attribute masks */ vport->fdmi_hba_mask = LPFC_FDMI2_HBA_ATTR; - if (phba->cfg_fdmi_on == LPFC_FDMI_SMART_SAN) + if (phba->cfg_enable_SmartSAN) vport->fdmi_port_mask = LPFC_FDMI2_SMART_ATTR; else vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; + } else { + vport->fdmi_hba_mask = 0; + vport->fdmi_port_mask = 0; } } @@ -8005,8 +8006,9 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) return; } - if ((phba->cfg_fdmi_on > LPFC_FDMI_NO_SUPPORT) && - (vport->load_flag & FC_ALLOW_FDMI)) + if ((phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) && + (vport->load_flag & FC_ALLOW_FDMI)) lpfc_start_fdmi(vport); } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f0d0852bee0d..c922a2b1f864 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6158,11 +6158,12 @@ lpfc_create_shost(struct lpfc_hba *phba) * any initial discovery should be completed. */ vport->load_flag |= FC_ALLOW_FDMI; - if (phba->cfg_fdmi_on > LPFC_FDMI_NO_SUPPORT) { + if (phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) { /* Setup appropriate attribute masks */ vport->fdmi_hba_mask = LPFC_FDMI2_HBA_ATTR; - if (phba->cfg_fdmi_on == LPFC_FDMI_SMART_SAN) + if (phba->cfg_enable_SmartSAN) vport->fdmi_port_mask = LPFC_FDMI2_SMART_ATTR; else vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index b3f85def18cc..9b7adcac5a87 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -395,7 +395,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) /* At this point we are fully registered with SCSI Layer. */ vport->load_flag |= FC_ALLOW_FDMI; - if (phba->cfg_fdmi_on > LPFC_FDMI_NO_SUPPORT) { + if (phba->cfg_enable_SmartSAN || + (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) { /* Setup appropriate attribute masks */ vport->fdmi_hba_mask = phba->pport->fdmi_hba_mask; vport->fdmi_port_mask = phba->pport->fdmi_port_mask; -- GitLab From 506115777af017bfc0968ee1c6aed024cdb6e43b Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:34 -0700 Subject: [PATCH 2101/9938] lpfc: Update modified file copyrights Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 +- drivers/scsi/lpfc/lpfc_attr.c | 2 +- drivers/scsi/lpfc/lpfc_ct.c | 2 +- drivers/scsi/lpfc/lpfc_els.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_hw.h | 2 +- drivers/scsi/lpfc/lpfc_hw4.h | 2 +- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_mbox.c | 2 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 2 +- drivers/scsi/lpfc/lpfc_version.h | 4 ++-- drivers/scsi/lpfc/lpfc_vport.c | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 283942a4ae82..d5bd420595c1 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 9528f863f219..cfec2eca4dd3 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 982039e73d33..a38816e96654 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6cc1af42af36..0498f5760d2b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index b3bf230f714a..ed223937798a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 41a961e00f29..39f0fd000d2c 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 634c9b1c6710..0c7070bf2813 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2009-2015 Emulex. All rights reserved. * + * Copyright (C) 2009-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c922a2b1f864..b43f7ac9812c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 1e34b5408a29..12dbe99ccc50 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 9b539e2e864b..56a3df4fddb0 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9c8368a7149a..6b267b67f845 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 4dc22562aaf1..6b57e0cdb7cf 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2015 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -30,4 +30,4 @@ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright(c) 2004-2015 Emulex. All rights reserved." +#define LPFC_COPYRIGHT "Copyright(c) 2004-2016 Emulex. All rights reserved." diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 9b7adcac5a87..c27f4b724547 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2013 Emulex. All rights reserved. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * -- GitLab From 45cc807291d5fde7a6691a06c0ca9f472fa3fb15 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 31 Mar 2016 14:12:35 -0700 Subject: [PATCH 2102/9938] lpfc: Update driver version to 11.1.0.0 Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 6b57e0cdb7cf..fa0d531bf351 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "11.0.0.10." +#define LPFC_DRIVER_VERSION "11.1.0.0." #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ -- GitLab From 3f5c11a463fd87b912f16976ff0ee3d6bbd1825e Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:10 -0700 Subject: [PATCH 2103/9938] snic: Added additional stats Adding additional stats, and fixed logging messages. - Added qdepth change stats - Added separate isr stats for each type of interrupt - Fixed race in updating active IOs - Suppressed Link event message for DAS backend. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_ctl.c | 8 +++----- drivers/scsi/snic/snic_debugfs.c | 20 ++++++++++++++++---- drivers/scsi/snic/snic_isr.c | 6 +++--- drivers/scsi/snic/snic_main.c | 9 ++++++++- drivers/scsi/snic/snic_scsi.c | 27 ++++++++++++++++++++------- drivers/scsi/snic/snic_stats.h | 12 +++++++++--- 6 files changed, 59 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/snic/snic_ctl.c b/drivers/scsi/snic/snic_ctl.c index ab0e06b0b4ff..449b03f3bbd3 100644 --- a/drivers/scsi/snic/snic_ctl.c +++ b/drivers/scsi/snic/snic_ctl.c @@ -39,17 +39,15 @@ snic_handle_link(struct work_struct *work) { struct snic *snic = container_of(work, struct snic, link_work); - if (snic->config.xpt_type != SNIC_DAS) { - SNIC_HOST_INFO(snic->shost, "Link Event Received.\n"); - SNIC_ASSERT_NOT_IMPL(1); - + if (snic->config.xpt_type == SNIC_DAS) return; - } snic->link_status = svnic_dev_link_status(snic->vdev); snic->link_down_cnt = svnic_dev_link_down_cnt(snic->vdev); SNIC_HOST_INFO(snic->shost, "Link Event: Link %s.\n", ((snic->link_status) ? "Up" : "Down")); + + SNIC_ASSERT_NOT_IMPL(1); } diff --git a/drivers/scsi/snic/snic_debugfs.c b/drivers/scsi/snic/snic_debugfs.c index 1686f0196251..d30280326bde 100644 --- a/drivers/scsi/snic/snic_debugfs.c +++ b/drivers/scsi/snic/snic_debugfs.c @@ -264,12 +264,14 @@ snic_stats_show(struct seq_file *sfp, void *data) "Aborts Fail : %lld\n" "Aborts Driver Timeout : %lld\n" "Abort FW Timeout : %lld\n" - "Abort IO NOT Found : %lld\n", + "Abort IO NOT Found : %lld\n" + "Abort Queuing Failed : %lld\n", (u64) atomic64_read(&stats->abts.num), (u64) atomic64_read(&stats->abts.fail), (u64) atomic64_read(&stats->abts.drv_tmo), (u64) atomic64_read(&stats->abts.fw_tmo), - (u64) atomic64_read(&stats->abts.io_not_found)); + (u64) atomic64_read(&stats->abts.io_not_found), + (u64) atomic64_read(&stats->abts.q_fail)); /* Dump Reset Stats */ seq_printf(sfp, @@ -316,7 +318,9 @@ snic_stats_show(struct seq_file *sfp, void *data) seq_printf(sfp, "Last ISR Time : %llu (%8lu.%8lu)\n" "Last Ack Time : %llu (%8lu.%8lu)\n" - "ISRs : %llu\n" + "Ack ISRs : %llu\n" + "IO Cmpl ISRs : %llu\n" + "Err Notify ISRs : %llu\n" "Max CQ Entries : %lld\n" "Data Count Mismatch : %lld\n" "IOs w/ Timeout Status : %lld\n" @@ -324,12 +328,17 @@ snic_stats_show(struct seq_file *sfp, void *data) "IOs w/ SGL Invalid Stat : %lld\n" "WQ Desc Alloc Fail : %lld\n" "Queue Full : %lld\n" + "Queue Ramp Up : %lld\n" + "Queue Ramp Down : %lld\n" + "Queue Last Queue Depth : %lld\n" "Target Not Ready : %lld\n", (u64) stats->misc.last_isr_time, last_isr_tms.tv_sec, last_isr_tms.tv_nsec, (u64)stats->misc.last_ack_time, last_ack_tms.tv_sec, last_ack_tms.tv_nsec, - (u64) atomic64_read(&stats->misc.isr_cnt), + (u64) atomic64_read(&stats->misc.ack_isr_cnt), + (u64) atomic64_read(&stats->misc.cmpl_isr_cnt), + (u64) atomic64_read(&stats->misc.errnotify_isr_cnt), (u64) atomic64_read(&stats->misc.max_cq_ents), (u64) atomic64_read(&stats->misc.data_cnt_mismat), (u64) atomic64_read(&stats->misc.io_tmo), @@ -337,6 +346,9 @@ snic_stats_show(struct seq_file *sfp, void *data) (u64) atomic64_read(&stats->misc.sgl_inval), (u64) atomic64_read(&stats->misc.wq_alloc_fail), (u64) atomic64_read(&stats->misc.qfull), + (u64) atomic64_read(&stats->misc.qsz_rampup), + (u64) atomic64_read(&stats->misc.qsz_rampdown), + (u64) atomic64_read(&stats->misc.last_qsz), (u64) atomic64_read(&stats->misc.tgt_not_rdy)); return 0; diff --git a/drivers/scsi/snic/snic_isr.c b/drivers/scsi/snic/snic_isr.c index a85fae25ec8c..f552003128c6 100644 --- a/drivers/scsi/snic/snic_isr.c +++ b/drivers/scsi/snic/snic_isr.c @@ -38,7 +38,7 @@ snic_isr_msix_wq(int irq, void *data) unsigned long wq_work_done = 0; snic->s_stats.misc.last_isr_time = jiffies; - atomic64_inc(&snic->s_stats.misc.isr_cnt); + atomic64_inc(&snic->s_stats.misc.ack_isr_cnt); wq_work_done = snic_wq_cmpl_handler(snic, -1); svnic_intr_return_credits(&snic->intr[SNIC_MSIX_WQ], @@ -56,7 +56,7 @@ snic_isr_msix_io_cmpl(int irq, void *data) unsigned long iocmpl_work_done = 0; snic->s_stats.misc.last_isr_time = jiffies; - atomic64_inc(&snic->s_stats.misc.isr_cnt); + atomic64_inc(&snic->s_stats.misc.cmpl_isr_cnt); iocmpl_work_done = snic_fwcq_cmpl_handler(snic, -1); svnic_intr_return_credits(&snic->intr[SNIC_MSIX_IO_CMPL], @@ -73,7 +73,7 @@ snic_isr_msix_err_notify(int irq, void *data) struct snic *snic = data; snic->s_stats.misc.last_isr_time = jiffies; - atomic64_inc(&snic->s_stats.misc.isr_cnt); + atomic64_inc(&snic->s_stats.misc.errnotify_isr_cnt); svnic_intr_return_all_credits(&snic->intr[SNIC_MSIX_ERR_NOTIFY]); snic_log_q_error(snic); diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c index 2b3c25371d76..37ec507b7e67 100644 --- a/drivers/scsi/snic/snic_main.c +++ b/drivers/scsi/snic/snic_main.c @@ -98,11 +98,18 @@ snic_slave_configure(struct scsi_device *sdev) static int snic_change_queue_depth(struct scsi_device *sdev, int qdepth) { + struct snic *snic = shost_priv(sdev->host); int qsz = 0; qsz = min_t(u32, qdepth, SNIC_MAX_QUEUE_DEPTH); + if (qsz < sdev->queue_depth) + atomic64_inc(&snic->s_stats.misc.qsz_rampdown); + else if (qsz > sdev->queue_depth) + atomic64_inc(&snic->s_stats.misc.qsz_rampup); + + atomic64_set(&snic->s_stats.misc.last_qsz, sdev->queue_depth); + scsi_change_queue_depth(sdev, qsz); - SNIC_INFO("QDepth Changed to %d\n", sdev->queue_depth); return sdev->queue_depth; } diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index 2c7b4c321cbe..e423eaacb926 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -221,11 +221,15 @@ snic_queue_icmnd_req(struct snic *snic, pa, /* sense buffer pa */ SCSI_SENSE_BUFFERSIZE); + atomic64_inc(&snic->s_stats.io.active); ret = snic_queue_wq_desc(snic, rqi->req, rqi->req_len); - if (ret) + if (ret) { + atomic64_dec(&snic->s_stats.io.active); SNIC_HOST_ERR(snic->shost, "QIcmnd: Queuing Icmnd Failed. ret = %d\n", ret); + } else + snic_stats_update_active_ios(&snic->s_stats); return ret; } /* end of snic_queue_icmnd_req */ @@ -361,8 +365,7 @@ snic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc) if (ret) { SNIC_HOST_ERR(shost, "Failed to Q, Scsi Req w/ err %d.\n", ret); ret = SCSI_MLQUEUE_HOST_BUSY; - } else - snic_stats_update_active_ios(&snic->s_stats); + } atomic_dec(&snic->ios_inflight); @@ -1001,10 +1004,11 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) unsigned long flags, gflags; int ret = 0; + snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx); SNIC_HOST_INFO(snic->shost, - "reset_cmpl:HBA Reset Completion received.\n"); + "reset_cmpl:Tag %d ctx %lx cmpl status %s HBA Reset Completion received.\n", + cmnd_id, ctx, snic_io_status_to_str(hdr_stat)); - snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx); SNIC_SCSI_DBG(snic->shost, "reset_cmpl: type = %x, hdr_stat = %x, cmnd_id = %x, hid = %x, ctx = %lx\n", typ, hdr_stat, cmnd_id, hid, ctx); @@ -1012,6 +1016,9 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) /* spl case, host reset issued through ioctl */ if (cmnd_id == SCSI_NO_TAG) { rqi = (struct snic_req_info *) ctx; + SNIC_HOST_INFO(snic->shost, + "reset_cmpl:Tag %d ctx %lx cmpl stat %s\n", + cmnd_id, ctx, snic_io_status_to_str(hdr_stat)); sc = rqi->sc; goto ioctl_hba_rst; @@ -1038,6 +1045,10 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) return ret; } + SNIC_HOST_INFO(snic->shost, + "reset_cmpl: sc %p rqi %p Tag %d flags 0x%llx\n", + sc, rqi, cmnd_id, CMD_FLAGS(sc)); + io_lock = snic_io_lock_hash(snic, sc); spin_lock_irqsave(io_lock, flags); @@ -1554,6 +1565,7 @@ snic_send_abort_and_wait(struct snic *snic, struct scsi_cmnd *sc) /* Now Queue the abort command to firmware */ ret = snic_queue_abort_req(snic, rqi, sc, tmf); if (ret) { + atomic64_inc(&snic->s_stats.abts.q_fail); SNIC_HOST_ERR(snic->shost, "send_abt_cmd: IO w/ Tag 0x%x fail w/ err %d flags 0x%llx\n", tag, ret, CMD_FLAGS(sc)); @@ -2459,8 +2471,9 @@ snic_scsi_cleanup(struct snic *snic, int ex_tag) cleanup: sc->result = DID_TRANSPORT_DISRUPTED << 16; SNIC_HOST_INFO(snic->shost, - "sc_clean: DID_TRANSPORT_DISRUPTED for sc %p. rqi %p duration %llu msecs\n", - sc, rqi, (jiffies - st_time)); + "sc_clean: DID_TRANSPORT_DISRUPTED for sc %p, Tag %d flags 0x%llx rqi %p duration %u msecs\n", + sc, sc->request->tag, CMD_FLAGS(sc), rqi, + jiffies_to_msecs(jiffies - st_time)); /* Update IO stats */ snic_stats_update_io_cmpl(&snic->s_stats); diff --git a/drivers/scsi/snic/snic_stats.h b/drivers/scsi/snic/snic_stats.h index 11e614849a82..fd1066b1cad5 100644 --- a/drivers/scsi/snic/snic_stats.h +++ b/drivers/scsi/snic/snic_stats.h @@ -42,6 +42,7 @@ struct snic_abort_stats { atomic64_t drv_tmo; /* Abort Driver Timeouts */ atomic64_t fw_tmo; /* Abort Firmware Timeouts */ atomic64_t io_not_found;/* Abort IO Not Found */ + atomic64_t q_fail; /* Abort Queuing Failed */ }; struct snic_reset_stats { @@ -69,7 +70,9 @@ struct snic_fw_stats { struct snic_misc_stats { u64 last_isr_time; u64 last_ack_time; - atomic64_t isr_cnt; + atomic64_t ack_isr_cnt; + atomic64_t cmpl_isr_cnt; + atomic64_t errnotify_isr_cnt; atomic64_t max_cq_ents; /* Max CQ Entries */ atomic64_t data_cnt_mismat; /* Data Count Mismatch */ atomic64_t io_tmo; @@ -81,6 +84,9 @@ struct snic_misc_stats { atomic64_t no_icmnd_itmf_cmpls; atomic64_t io_under_run; atomic64_t qfull; + atomic64_t qsz_rampup; + atomic64_t qsz_rampdown; + atomic64_t last_qsz; atomic64_t tgt_not_rdy; }; @@ -101,9 +107,9 @@ static inline void snic_stats_update_active_ios(struct snic_stats *s_stats) { struct snic_io_stats *io = &s_stats->io; - u32 nr_active_ios; + int nr_active_ios; - nr_active_ios = atomic64_inc_return(&io->active); + nr_active_ios = atomic64_read(&io->active); if (atomic64_read(&io->max_active) < nr_active_ios) atomic64_set(&io->max_active, nr_active_ios); -- GitLab From f352a0d5bafa62d1f0b044613ea42483a529f9df Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:11 -0700 Subject: [PATCH 2104/9938] snic: LUN goes offline due to scsi cmd timeouts - LUN goes offline if there are at least two scsi command timeouts Completing the IO with scsi_done() fixes the issue. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_scsi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index e423eaacb926..5a709ebdb282 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -1465,11 +1465,19 @@ snic_abort_finish(struct snic *snic, struct scsi_cmnd *sc) case SNIC_STAT_IO_SUCCESS: case SNIC_STAT_IO_NOT_FOUND: ret = SUCCESS; + /* + * If abort path doesn't call scsi_done(), + * the # IO timeouts == 2, will cause the LUN offline. + * Call scsi_done to complete the IO. + */ + sc->result = (DID_ERROR << 16); + sc->scsi_done(sc); break; default: /* Firmware completed abort with error */ ret = FAILED; + rqi = NULL; break; } @@ -1842,6 +1850,9 @@ snic_dr_clean_single_req(struct snic *snic, snic_release_req_buf(snic, rqi, sc); + sc->result = (DID_ERROR << 16); + sc->scsi_done(sc); + ret = 0; return ret; @@ -2396,6 +2407,13 @@ snic_cmpl_pending_tmreq(struct snic *snic, struct scsi_cmnd *sc) "Completing Pending TM Req sc %p, state %s flags 0x%llx\n", sc, snic_io_status_to_str(CMD_STATE(sc)), CMD_FLAGS(sc)); + /* + * CASE : FW didn't post itmf completion due to PCIe Errors. + * Marking the abort status as Success to call scsi completion + * in snic_abort_finish() + */ + CMD_ABTS_STATUS(sc) = SNIC_STAT_IO_SUCCESS; + rqi = (struct snic_req_info *) CMD_SP(sc); if (!rqi) return; -- GitLab From 6e0ae74b5ca2826fa6c86a157ed5227c766156b9 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:12 -0700 Subject: [PATCH 2105/9938] snic: Handling control path queue issues Fix handles control path queue issues such as queue full and sudden removal of hardware. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/vnic_dev.c | 44 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/snic/vnic_dev.c b/drivers/scsi/snic/vnic_dev.c index e0b5549bc9fb..dad5fc66effb 100644 --- a/drivers/scsi/snic/vnic_dev.c +++ b/drivers/scsi/snic/vnic_dev.c @@ -263,12 +263,20 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, int wait) { struct devcmd2_controller *dc2c = vdev->devcmd2; - struct devcmd2_result *result = dc2c->result + dc2c->next_result; + struct devcmd2_result *result = NULL; unsigned int i; int delay; int err; u32 posted; + u32 fetch_idx; u32 new_posted; + u8 color; + + fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index); + if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone */ + /* Hardware surprise removal: return error */ + return -ENODEV; + } posted = ioread32(&dc2c->wq_ctrl->posted_index); @@ -278,6 +286,13 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, } new_posted = (posted + 1) % DEVCMD2_RING_SIZE; + if (new_posted == fetch_idx) { + pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n", + pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted); + + return -EBUSY; + } + dc2c->cmd_ring[posted].cmd = cmd; dc2c->cmd_ring[posted].flags = 0; @@ -299,14 +314,22 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT) return 0; + result = dc2c->result + dc2c->next_result; + color = dc2c->color; + + /* + * Increment next_result, after posting the devcmd, irrespective of + * devcmd result, and it should be done only once. + */ + dc2c->next_result++; + if (dc2c->next_result == dc2c->result_size) { + dc2c->next_result = 0; + dc2c->color = dc2c->color ? 0 : 1; + } + for (delay = 0; delay < wait; delay++) { udelay(100); - if (result->color == dc2c->color) { - dc2c->next_result++; - if (dc2c->next_result == dc2c->result_size) { - dc2c->next_result = 0; - dc2c->color = dc2c->color ? 0 : 1; - } + if (result->color == color) { if (result->error) { err = (int) result->error; if (err != ERR_ECMDUNKNOWN || @@ -317,13 +340,6 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, return err; } if (_CMD_DIR(cmd) & _CMD_DIR_READ) { - /* - * Adding the rmb() prevents the compiler - * and/or CPU from reordering the reads which - * would potentially result in reading stale - * values. - */ - rmb(); for (i = 0; i < VNIC_DEVCMD_NARGS; i++) vdev->args[i] = result->results[i]; } -- GitLab From 58fcf92050cdf7b499ba6169459ec43aa0838662 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:13 -0700 Subject: [PATCH 2106/9938] snic: target cleanup in driver unload path Fix deletes the snic targets synchronously prior to deletion of host. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_disc.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c index 5f48795767bd..b0fefd67cac3 100644 --- a/drivers/scsi/snic/snic_disc.c +++ b/drivers/scsi/snic/snic_disc.c @@ -480,10 +480,21 @@ int snic_disc_start(struct snic *snic) { struct snic_disc *disc = &snic->disc; + unsigned long flags; int ret = 0; SNIC_SCSI_DBG(snic->shost, "Discovery Start.\n"); + spin_lock_irqsave(&snic->snic_lock, flags); + if (snic->in_remove) { + spin_unlock_irqrestore(&snic->snic_lock, flags); + SNIC_ERR("snic driver removal in progress ...\n"); + ret = 0; + + return ret; + } + spin_unlock_irqrestore(&snic->snic_lock, flags); + mutex_lock(&disc->mutex); if (disc->state == SNIC_DISC_PENDING) { disc->req_cnt++; @@ -533,6 +544,8 @@ snic_tgt_del_all(struct snic *snic) struct list_head *cur, *nxt; unsigned long flags; + scsi_flush_work(snic->shost); + mutex_lock(&snic->disc.mutex); spin_lock_irqsave(snic->shost->host_lock, flags); @@ -545,7 +558,7 @@ snic_tgt_del_all(struct snic *snic) tgt = NULL; } spin_unlock_irqrestore(snic->shost->host_lock, flags); - - scsi_flush_work(snic->shost); mutex_unlock(&snic->disc.mutex); + + flush_workqueue(snic_glob->event_q); } /* end of snic_tgt_del_all */ -- GitLab From c9747821f9bbff6c07fa36087b003d89d05245c8 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:14 -0700 Subject: [PATCH 2107/9938] snic: Fix for missing interrupts - On posting an IO to the firmware, adapter generates an interrupt. Due to hardware issues, sometimes the adapter fails to generate the interrupt. This behavior skips updating transmit queue- counters, which in turn causes the queue full condition. The fix addresses the queue full condition. - The fix also reserves a slot in transmit queue for hba reset. when queue full is observed during IO, there will always be room to post hba reset command. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_fwint.h | 4 ++- drivers/scsi/snic/snic_io.c | 62 ++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/snic/snic_fwint.h b/drivers/scsi/snic/snic_fwint.h index 2cfaf2dc915f..c5f9e1917a8e 100644 --- a/drivers/scsi/snic/snic_fwint.h +++ b/drivers/scsi/snic/snic_fwint.h @@ -414,7 +414,7 @@ enum snic_ev_type { /* Payload 88 bytes = 128 - 24 - 16 */ #define SNIC_HOST_REQ_PAYLOAD ((int)(SNIC_HOST_REQ_LEN - \ sizeof(struct snic_io_hdr) - \ - (2 * sizeof(u64)))) + (2 * sizeof(u64)) - sizeof(ulong))) /* * snic_host_req: host -> firmware request @@ -448,6 +448,8 @@ struct snic_host_req { /* hba reset */ struct snic_hba_reset reset; } u; + + ulong req_pa; }; /* end of snic_host_req structure */ diff --git a/drivers/scsi/snic/snic_io.c b/drivers/scsi/snic/snic_io.c index 993db7de4e4b..8e69548395b9 100644 --- a/drivers/scsi/snic/snic_io.c +++ b/drivers/scsi/snic/snic_io.c @@ -48,7 +48,7 @@ snic_wq_cmpl_frame_send(struct vnic_wq *wq, SNIC_TRC(snic->shost->host_no, 0, 0, ((ulong)(buf->os_buf) - sizeof(struct snic_req_info)), 0, 0, 0); - pci_unmap_single(snic->pdev, buf->dma_addr, buf->len, PCI_DMA_TODEVICE); + buf->os_buf = NULL; } @@ -137,13 +137,36 @@ snic_select_wq(struct snic *snic) return 0; } +static int +snic_wqdesc_avail(struct snic *snic, int q_num, int req_type) +{ + int nr_wqdesc = snic->config.wq_enet_desc_count; + + if (q_num > 0) { + /* + * Multi Queue case, additional care is required. + * Per WQ active requests need to be maintained. + */ + SNIC_HOST_INFO(snic->shost, "desc_avail: Multi Queue case.\n"); + SNIC_BUG_ON(q_num > 0); + + return -1; + } + + nr_wqdesc -= atomic64_read(&snic->s_stats.fw.actv_reqs); + + return ((req_type == SNIC_REQ_HBA_RESET) ? nr_wqdesc : nr_wqdesc - 1); +} + int snic_queue_wq_desc(struct snic *snic, void *os_buf, u16 len) { dma_addr_t pa = 0; unsigned long flags; struct snic_fw_stats *fwstats = &snic->s_stats.fw; + struct snic_host_req *req = (struct snic_host_req *) os_buf; long act_reqs; + long desc_avail = 0; int q_num = 0; snic_print_desc(__func__, os_buf, len); @@ -156,11 +179,15 @@ snic_queue_wq_desc(struct snic *snic, void *os_buf, u16 len) return -ENOMEM; } + req->req_pa = (ulong)pa; + q_num = snic_select_wq(snic); spin_lock_irqsave(&snic->wq_lock[q_num], flags); - if (!svnic_wq_desc_avail(snic->wq)) { + desc_avail = snic_wqdesc_avail(snic, q_num, req->hdr.type); + if (desc_avail <= 0) { pci_unmap_single(snic->pdev, pa, len, PCI_DMA_TODEVICE); + req->req_pa = 0; spin_unlock_irqrestore(&snic->wq_lock[q_num], flags); atomic64_inc(&snic->s_stats.misc.wq_alloc_fail); SNIC_DBG("host = %d, WQ is Full\n", snic->shost->host_no); @@ -169,10 +196,13 @@ snic_queue_wq_desc(struct snic *snic, void *os_buf, u16 len) } snic_queue_wq_eth_desc(&snic->wq[q_num], os_buf, pa, len, 0, 0, 1); + /* + * Update stats + * note: when multi queue enabled, fw actv_reqs should be per queue. + */ + act_reqs = atomic64_inc_return(&fwstats->actv_reqs); spin_unlock_irqrestore(&snic->wq_lock[q_num], flags); - /* Update stats */ - act_reqs = atomic64_inc_return(&fwstats->actv_reqs); if (act_reqs > atomic64_read(&fwstats->max_actv_reqs)) atomic64_set(&fwstats->max_actv_reqs, act_reqs); @@ -318,11 +348,31 @@ snic_req_free(struct snic *snic, struct snic_req_info *rqi) "Req_free:rqi %p:ioreq %p:abt %p:dr %p\n", rqi, rqi->req, rqi->abort_req, rqi->dr_req); - if (rqi->abort_req) + if (rqi->abort_req) { + if (rqi->abort_req->req_pa) + pci_unmap_single(snic->pdev, + rqi->abort_req->req_pa, + sizeof(struct snic_host_req), + PCI_DMA_TODEVICE); + mempool_free(rqi->abort_req, snic->req_pool[SNIC_REQ_TM_CACHE]); + } + + if (rqi->dr_req) { + if (rqi->dr_req->req_pa) + pci_unmap_single(snic->pdev, + rqi->dr_req->req_pa, + sizeof(struct snic_host_req), + PCI_DMA_TODEVICE); - if (rqi->dr_req) mempool_free(rqi->dr_req, snic->req_pool[SNIC_REQ_TM_CACHE]); + } + + if (rqi->req->req_pa) + pci_unmap_single(snic->pdev, + rqi->req->req_pa, + rqi->req_len, + PCI_DMA_TODEVICE); mempool_free(rqi, snic->req_pool[rqi->rq_pool_type]); } -- GitLab From 0da8519b2b1f08113cda65af88a4c9e35157dd53 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:15 -0700 Subject: [PATCH 2108/9938] snic: Fixing race in the hba reset and IO/TM completion While HBA reset is in progress, if IO/TM completion is received for the same IO then IO/TM completion path releases the driver private resources associated with IO. This fix prevents releasing the resources in IO and TM completion path if HBA reset is in progress. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic.h | 5 ++++- drivers/scsi/snic/snic_scsi.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/snic/snic.h b/drivers/scsi/snic/snic.h index d7f5ba6ba84c..8ed778d4dbb9 100644 --- a/drivers/scsi/snic/snic.h +++ b/drivers/scsi/snic/snic.h @@ -95,6 +95,8 @@ #define SNIC_DEV_RST_NOTSUP BIT(25) #define SNIC_SCSI_CLEANUP BIT(26) #define SNIC_HOST_RESET_ISSUED BIT(27) +#define SNIC_HOST_RESET_CMD_TERM \ + (SNIC_DEV_RST_NOTSUP | SNIC_SCSI_CLEANUP | SNIC_HOST_RESET_ISSUED) #define SNIC_ABTS_TIMEOUT 30000 /* msec */ #define SNIC_LUN_RESET_TIMEOUT 30000 /* msec */ @@ -216,9 +218,10 @@ enum snic_msix_intr_index { SNIC_MSIX_INTR_MAX, }; +#define SNIC_INTRHDLR_NAMSZ (2 * IFNAMSIZ) struct snic_msix_entry { int requested; - char devname[IFNAMSIZ]; + char devname[SNIC_INTRHDLR_NAMSZ]; irqreturn_t (*isr)(int, void *); void *devid; }; diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index 5a709ebdb282..abada16b375b 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -601,6 +601,12 @@ snic_icmnd_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq) sc->device->lun, sc, sc->cmnd[0], snic_cmd_tag(sc), CMD_FLAGS(sc), rqi); + if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) { + spin_unlock_irqrestore(io_lock, flags); + + return; + } + SNIC_BUG_ON(rqi != (struct snic_req_info *)ctx); WARN_ON_ONCE(req); if (!rqi) { @@ -782,6 +788,11 @@ snic_process_itmf_cmpl(struct snic *snic, io_lock = snic_io_lock_hash(snic, sc); spin_lock_irqsave(io_lock, flags); + if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) { + spin_unlock_irqrestore(io_lock, flags); + + return ret; + } rqi = (struct snic_req_info *) CMD_SP(sc); WARN_ON_ONCE(!rqi); -- GitLab From be2a266d2a163a332666f396ea128a6bcc6882f7 Mon Sep 17 00:00:00 2001 From: Narsimhulu Musini Date: Thu, 17 Mar 2016 00:51:16 -0700 Subject: [PATCH 2109/9938] snic: add scsi host after determining max IOs. scsi host is added after negotiating the max number of IOs with Firmware. Signed-off-by: Narsimhulu Musini Signed-off-by: Sesidhar Baddela Signed-off-by: Martin K. Petersen --- drivers/scsi/snic/snic_main.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c index 37ec507b7e67..396b32dca074 100644 --- a/drivers/scsi/snic/snic_main.c +++ b/drivers/scsi/snic/snic_main.c @@ -631,19 +631,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_free_tmreq_pool; } - /* - * Initialization done with PCI system, hardware, firmware. - * Add shost to SCSI - */ - ret = snic_add_host(shost, pdev); - if (ret) { - SNIC_HOST_ERR(shost, - "Adding scsi host Failed ... exiting. %d\n", - ret); - - goto err_notify_unset; - } - spin_lock_irqsave(&snic_glob->snic_list_lock, flags); list_add_tail(&snic->list, &snic_glob->snic_list); spin_unlock_irqrestore(&snic_glob->snic_list_lock, flags); @@ -676,8 +663,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < snic->intr_count; i++) svnic_intr_unmask(&snic->intr[i]); - snic_set_state(snic, SNIC_ONLINE); - /* Get snic params */ ret = snic_get_conf(snic); if (ret) { @@ -688,6 +673,21 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_get_conf; } + /* + * Initialization done with PCI system, hardware, firmware. + * Add shost to SCSI + */ + ret = snic_add_host(shost, pdev); + if (ret) { + SNIC_HOST_ERR(shost, + "Adding scsi host Failed ... exiting. %d\n", + ret); + + goto err_get_conf; + } + + snic_set_state(snic, SNIC_ONLINE); + ret = snic_disc_start(snic); if (ret) { SNIC_HOST_ERR(shost, "snic_probe:Discovery Failed w err = %d\n", @@ -712,6 +712,8 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) svnic_dev_disable(snic->vdev); err_vdev_enable: + svnic_dev_notify_unset(snic->vdev); + for (i = 0; i < snic->wq_count; i++) { int rc = 0; @@ -725,9 +727,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } snic_del_host(snic->shost); -err_notify_unset: - svnic_dev_notify_unset(snic->vdev); - err_free_tmreq_pool: mempool_destroy(snic->req_pool[SNIC_REQ_TM_CACHE]); -- GitLab From 5ac7eace2d00eab5ae0e9fdee63e38aee6001f7c Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:24 +0100 Subject: [PATCH 2110/9938] KEYS: Add a facility to restrict new links into a keyring Add a facility whereby proposed new links to be added to a keyring can be vetted, permitting them to be rejected if necessary. This can be used to block public keys from which the signature cannot be verified or for which the signature verification fails. It could also be used to provide blacklisting. This affects operations like add_key(), KEYCTL_LINK and KEYCTL_INSTANTIATE. To this end: (1) A function pointer is added to the key struct that, if set, points to the vetting function. This is called as: int (*restrict_link)(struct key *keyring, const struct key_type *key_type, unsigned long key_flags, const union key_payload *key_payload), where 'keyring' will be the keyring being added to, key_type and key_payload will describe the key being added and key_flags[*] can be AND'ed with KEY_FLAG_TRUSTED. [*] This parameter will be removed in a later patch when KEY_FLAG_TRUSTED is removed. The function should return 0 to allow the link to take place or an error (typically -ENOKEY, -ENOPKG or -EKEYREJECTED) to reject the link. The pointer should not be set directly, but rather should be set through keyring_alloc(). Note that if called during add_key(), preparse is called before this method, but a key isn't actually allocated until after this function is called. (2) KEY_ALLOC_BYPASS_RESTRICTION is added. This can be passed to key_create_or_update() or key_instantiate_and_link() to bypass the restriction check. (3) KEY_FLAG_TRUSTED_ONLY is removed. The entire contents of a keyring with this restriction emplaced can be considered 'trustworthy' by virtue of being in the keyring when that keyring is consulted. (4) key_alloc() and keyring_alloc() take an extra argument that will be used to set restrict_link in the new key. This ensures that the pointer is set before the key is published, thus preventing a window of unrestrictedness. Normally this argument will be NULL. (5) As a temporary affair, keyring_restrict_trusted_only() is added. It should be passed to keyring_alloc() as the extra argument instead of setting KEY_FLAG_TRUSTED_ONLY on a keyring. This will be replaced in a later patch with functions that look in the appropriate places for authoritative keys. Signed-off-by: David Howells Reviewed-by: Mimi Zohar --- Documentation/security/keys.txt | 22 ++++++++++ certs/system_keyring.c | 8 ++-- fs/cifs/cifsacl.c | 2 +- fs/nfs/nfs4idmap.c | 2 +- include/linux/key.h | 53 ++++++++++++++++++----- net/dns_resolver/dns_key.c | 2 +- net/rxrpc/ar-key.c | 4 +- security/integrity/digsig.c | 7 ++- security/integrity/ima/ima_mok.c | 8 ++-- security/keys/key.c | 43 ++++++++++++++++--- security/keys/keyring.c | 73 +++++++++++++++++++++++++++++--- security/keys/persistent.c | 4 +- security/keys/process_keys.c | 16 ++++--- security/keys/request_key.c | 4 +- security/keys/request_key_auth.c | 2 +- 15 files changed, 198 insertions(+), 52 deletions(-) diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 8c183873b2b7..a6a50b359025 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt @@ -999,6 +999,10 @@ payload contents" for more information. struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, const struct cred *cred, key_perm_t perm, + int (*restrict_link)(struct key *, + const struct key_type *, + unsigned long, + const union key_payload *), unsigned long flags, struct key *dest); @@ -1010,6 +1014,24 @@ payload contents" for more information. KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted towards the user's quota). Error ENOMEM can also be returned. + If restrict_link not NULL, it should point to a function that will be + called each time an attempt is made to link a key into the new keyring. + This function is called to check whether a key may be added into the keying + or not. Callers of key_create_or_update() within the kernel can pass + KEY_ALLOC_BYPASS_RESTRICTION to suppress the check. An example of using + this is to manage rings of cryptographic keys that are set up when the + kernel boots where userspace is also permitted to add keys - provided they + can be verified by a key the kernel already has. + + When called, the restriction function will be passed the keyring being + added to, the key flags value and the type and payload of the key being + added. Note that when a new key is being created, this is called between + payload preparsing and actual key creation. The function should return 0 + to allow the link or an error to reject it. + + A convenience function, restrict_link_reject, exists to always return + -EPERM to in this case. + (*) To check the validity of a key, this function can be called: diff --git a/certs/system_keyring.c b/certs/system_keyring.c index dc18869ff680..417d65882870 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -36,11 +36,10 @@ static __init int system_trusted_keyring_init(void) KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), - KEY_ALLOC_NOT_IN_QUOTA, NULL); + KEY_ALLOC_NOT_IN_QUOTA, + keyring_restrict_trusted_only, NULL); if (IS_ERR(system_trusted_keyring)) panic("Can't allocate system trusted keyring\n"); - - set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); return 0; } @@ -85,7 +84,8 @@ static __init int load_system_certificate_list(void) KEY_USR_VIEW | KEY_USR_READ), KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_TRUSTED | - KEY_ALLOC_BUILT_IN); + KEY_ALLOC_BUILT_IN | + KEY_ALLOC_BYPASS_RESTRICTION); if (IS_ERR(key)) { pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", PTR_ERR(key)); diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 3f93125916bf..71e8a56e9479 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -360,7 +360,7 @@ init_cifs_idmap(void) GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, - KEY_ALLOC_NOT_IN_QUOTA, NULL); + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c index 5ba22c6b0ffa..c444285bb1b1 100644 --- a/fs/nfs/nfs4idmap.c +++ b/fs/nfs/nfs4idmap.c @@ -201,7 +201,7 @@ int nfs_idmap_init(void) GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, - KEY_ALLOC_NOT_IN_QUOTA, NULL); + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; diff --git a/include/linux/key.h b/include/linux/key.h index 5f5b1129dc92..83b603639d2e 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -174,10 +174,9 @@ struct key { #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ #define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ -#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ -#define KEY_FLAG_BUILTIN 10 /* set if key is builtin */ -#define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */ -#define KEY_FLAG_KEEP 12 /* set if key should not be removed */ +#define KEY_FLAG_BUILTIN 9 /* set if key is built in to the kernel */ +#define KEY_FLAG_ROOT_CAN_INVAL 10 /* set if key can be invalidated by root without permission */ +#define KEY_FLAG_KEEP 11 /* set if key should not be removed */ /* the key type and key description string * - the desc is used to match a key against search criteria @@ -205,6 +204,21 @@ struct key { }; int reject_error; }; + + /* This is set on a keyring to restrict the addition of a link to a key + * to it. If this method isn't provided then it is assumed that the + * keyring is open to any addition. It is ignored for non-keyring + * keys. + * + * This is intended for use with rings of trusted keys whereby addition + * to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION + * overrides this, allowing the kernel to add extra keys without + * restriction. + */ + int (*restrict_link)(struct key *keyring, + const struct key_type *type, + unsigned long flags, + const union key_payload *payload); }; extern struct key *key_alloc(struct key_type *type, @@ -212,14 +226,19 @@ extern struct key *key_alloc(struct key_type *type, kuid_t uid, kgid_t gid, const struct cred *cred, key_perm_t perm, - unsigned long flags); + unsigned long flags, + int (*restrict_link)(struct key *, + const struct key_type *, + unsigned long, + const union key_payload *)); -#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ -#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ -#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ -#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ -#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */ +#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ +#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ +#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ +#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ +#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */ +#define KEY_ALLOC_BYPASS_RESTRICTION 0x0010 /* Override the check on restricted keyrings */ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); @@ -288,8 +307,22 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid const struct cred *cred, key_perm_t perm, unsigned long flags, + int (*restrict_link)(struct key *, + const struct key_type *, + unsigned long, + const union key_payload *), struct key *dest); +extern int keyring_restrict_trusted_only(struct key *keyring, + const struct key_type *type, + unsigned long, + const union key_payload *payload); + +extern int restrict_link_reject(struct key *keyring, + const struct key_type *type, + unsigned long flags, + const union key_payload *payload); + extern int keyring_clear(struct key *keyring); extern key_ref_t keyring_search(key_ref_t keyring, diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index c79b85eb4d4c..8737412c7b27 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -281,7 +281,7 @@ static int __init init_dns_resolver(void) GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, - KEY_ALLOC_NOT_IN_QUOTA, NULL); + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 3fb492eedeb9..1021b4c0bdd2 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -965,7 +965,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn, key = key_alloc(&key_type_rxrpc, "x", GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0, - KEY_ALLOC_NOT_IN_QUOTA); + KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(key)) { _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key)); return -ENOMEM; @@ -1012,7 +1012,7 @@ struct key *rxrpc_get_null_key(const char *keyname) key = key_alloc(&key_type_rxrpc, keyname, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, - KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA); + KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(key)) return key; diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 8ef15118cc78..659566c2200b 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -83,10 +83,9 @@ int __init integrity_init_keyring(const unsigned int id) ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH), - KEY_ALLOC_NOT_IN_QUOTA, NULL); - if (!IS_ERR(keyring[id])) - set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); - else { + KEY_ALLOC_NOT_IN_QUOTA, + NULL, NULL); + if (IS_ERR(keyring[id])) { err = PTR_ERR(keyring[id]); pr_info("Can't allocate %s keyring (%d)\n", keyring_name[id], err); diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index 676885e4320e..ef91248cb934 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c @@ -35,20 +35,20 @@ __init int ima_mok_init(void) (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH, - KEY_ALLOC_NOT_IN_QUOTA, NULL); + KEY_ALLOC_NOT_IN_QUOTA, + keyring_restrict_trusted_only, NULL); ima_blacklist_keyring = keyring_alloc(".ima_blacklist", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH, - KEY_ALLOC_NOT_IN_QUOTA, NULL); + KEY_ALLOC_NOT_IN_QUOTA, + keyring_restrict_trusted_only, NULL); if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring)) panic("Can't allocate IMA MOK or blacklist keyrings."); - set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_mok_keyring->flags); - set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_blacklist_keyring->flags); set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags); return 0; } diff --git a/security/keys/key.c b/security/keys/key.c index b28755131687..deb881754e03 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -201,6 +201,7 @@ static inline void key_alloc_serial(struct key *key) * @cred: The credentials specifying UID namespace. * @perm: The permissions mask of the new key. * @flags: Flags specifying quota properties. + * @restrict_link: Optional link restriction method for new keyrings. * * Allocate a key of the specified type with the attributes given. The key is * returned in an uninstantiated state and the caller needs to instantiate the @@ -223,7 +224,11 @@ static inline void key_alloc_serial(struct key *key) */ struct key *key_alloc(struct key_type *type, const char *desc, kuid_t uid, kgid_t gid, const struct cred *cred, - key_perm_t perm, unsigned long flags) + key_perm_t perm, unsigned long flags, + int (*restrict_link)(struct key *, + const struct key_type *, + unsigned long, + const union key_payload *)) { struct key_user *user = NULL; struct key *key; @@ -291,6 +296,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->uid = uid; key->gid = gid; key->perm = perm; + key->restrict_link = restrict_link; if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) key->flags |= 1 << KEY_FLAG_IN_QUOTA; @@ -496,6 +502,12 @@ int key_instantiate_and_link(struct key *key, } if (keyring) { + if (keyring->restrict_link) { + ret = keyring->restrict_link(keyring, key->type, + key->flags, &prep.payload); + if (ret < 0) + goto error; + } ret = __key_link_begin(keyring, &key->index_key, &edit); if (ret < 0) goto error; @@ -551,8 +563,12 @@ int key_reject_and_link(struct key *key, awaken = 0; ret = -EBUSY; - if (keyring) + if (keyring) { + if (keyring->restrict_link) + return -EPERM; + link_ret = __key_link_begin(keyring, &key->index_key, &edit); + } mutex_lock(&key_construction_mutex); @@ -793,6 +809,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, struct key *keyring, *key = NULL; key_ref_t key_ref; int ret; + int (*restrict_link)(struct key *, + const struct key_type *, + unsigned long, + const union key_payload *) = NULL; /* look up the key type to see if it's one of the registered kernel * types */ @@ -811,6 +831,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_check(keyring); + key_ref = ERR_PTR(-EPERM); + if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION)) + restrict_link = keyring->restrict_link; + key_ref = ERR_PTR(-ENOTDIR); if (keyring->type != &key_type_keyring) goto error_put_type; @@ -835,10 +859,15 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } index_key.desc_len = strlen(index_key.description); - key_ref = ERR_PTR(-EPERM); - if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags)) - goto error_free_prep; - flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0; + if (restrict_link) { + unsigned long kflags = prep.trusted ? KEY_FLAG_TRUSTED : 0; + ret = restrict_link(keyring, + index_key.type, kflags, &prep.payload); + if (ret < 0) { + key_ref = ERR_PTR(ret); + goto error_free_prep; + } + } ret = __key_link_begin(keyring, &index_key, &edit); if (ret < 0) { @@ -879,7 +908,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* allocate a new key */ key = key_alloc(index_key.type, index_key.description, - cred->fsuid, cred->fsgid, cred, perm, flags); + cred->fsuid, cred->fsgid, cred, perm, flags, NULL); if (IS_ERR(key)) { key_ref = ERR_CAST(key); goto error_link_end; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index f931ccfeefb0..d2d1f3378008 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -491,13 +491,18 @@ static long keyring_read(const struct key *keyring, */ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, const struct cred *cred, key_perm_t perm, - unsigned long flags, struct key *dest) + unsigned long flags, + int (*restrict_link)(struct key *, + const struct key_type *, + unsigned long, + const union key_payload *), + struct key *dest) { struct key *keyring; int ret; keyring = key_alloc(&key_type_keyring, description, - uid, gid, cred, perm, flags); + uid, gid, cred, perm, flags, restrict_link); if (!IS_ERR(keyring)) { ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); if (ret < 0) { @@ -510,6 +515,51 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, } EXPORT_SYMBOL(keyring_alloc); +/** + * keyring_restrict_trusted_only - Restrict additions to a keyring to trusted keys only + * @keyring: The keyring being added to. + * @type: The type of key being added. + * @flags: The key flags. + * @payload: The payload of the key intended to be added. + * + * Reject the addition of any links to a keyring that point to keys that aren't + * marked as being trusted. It can be overridden by passing + * KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when adding a key + * to a keyring. + * + * This is meant to be passed as the restrict_link parameter to + * keyring_alloc(). + */ +int keyring_restrict_trusted_only(struct key *keyring, + const struct key_type *type, + unsigned long flags, + const union key_payload *payload) +{ + return flags & KEY_FLAG_TRUSTED ? 0 : -EPERM; +} + +/** + * restrict_link_reject - Give -EPERM to restrict link + * @keyring: The keyring being added to. + * @type: The type of key being added. + * @flags: The key flags. + * @payload: The payload of the key intended to be added. + * + * Reject the addition of any links to a keyring. It can be overridden by + * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when + * adding a key to a keyring. + * + * This is meant to be passed as the restrict_link parameter to + * keyring_alloc(). + */ +int restrict_link_reject(struct key *keyring, + const struct key_type *type, + unsigned long flags, + const union key_payload *payload) +{ + return -EPERM; +} + /* * By default, we keys found by getting an exact match on their descriptions. */ @@ -1191,6 +1241,17 @@ void __key_link_end(struct key *keyring, up_write(&keyring->sem); } +/* + * Check addition of keys to restricted keyrings. + */ +static int __key_link_check_restriction(struct key *keyring, struct key *key) +{ + if (!keyring->restrict_link) + return 0; + return keyring->restrict_link(keyring, + key->type, key->flags, &key->payload); +} + /** * key_link - Link a key to a keyring * @keyring: The keyring to make the link in. @@ -1221,14 +1282,12 @@ int key_link(struct key *keyring, struct key *key) key_check(keyring); key_check(key); - if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) && - !test_bit(KEY_FLAG_TRUSTED, &key->flags)) - return -EPERM; - ret = __key_link_begin(keyring, &key->index_key, &edit); if (ret == 0) { kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); - ret = __key_link_check_live_key(keyring, key); + ret = __key_link_check_restriction(keyring, key); + if (ret == 0) + ret = __key_link_check_live_key(keyring, key); if (ret == 0) __key_link(key, &edit); __key_link_end(keyring, &key->index_key, edit); diff --git a/security/keys/persistent.c b/security/keys/persistent.c index c9fae5ea89fe..2ef45b319dd9 100644 --- a/security/keys/persistent.c +++ b/security/keys/persistent.c @@ -26,7 +26,7 @@ static int key_create_persistent_register(struct user_namespace *ns) current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA, NULL); + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -60,7 +60,7 @@ static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid, uid, INVALID_GID, current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA, + KEY_ALLOC_NOT_IN_QUOTA, NULL, ns->persistent_keyring_register); if (IS_ERR(persistent)) return ERR_CAST(persistent); diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index e6d50172872f..40a885239782 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -76,7 +76,8 @@ int install_user_keyrings(void) if (IS_ERR(uid_keyring)) { uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, - KEY_ALLOC_IN_QUOTA, NULL); + KEY_ALLOC_IN_QUOTA, + NULL, NULL); if (IS_ERR(uid_keyring)) { ret = PTR_ERR(uid_keyring); goto error; @@ -92,7 +93,8 @@ int install_user_keyrings(void) session_keyring = keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, - KEY_ALLOC_IN_QUOTA, NULL); + KEY_ALLOC_IN_QUOTA, + NULL, NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error_release; @@ -134,7 +136,8 @@ int install_thread_keyring_to_cred(struct cred *new) keyring = keyring_alloc("_tid", new->uid, new->gid, new, KEY_POS_ALL | KEY_USR_VIEW, - KEY_ALLOC_QUOTA_OVERRUN, NULL); + KEY_ALLOC_QUOTA_OVERRUN, + NULL, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); @@ -180,7 +183,8 @@ int install_process_keyring_to_cred(struct cred *new) keyring = keyring_alloc("_pid", new->uid, new->gid, new, KEY_POS_ALL | KEY_USR_VIEW, - KEY_ALLOC_QUOTA_OVERRUN, NULL); + KEY_ALLOC_QUOTA_OVERRUN, + NULL, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); @@ -231,7 +235,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, - flags, NULL); + flags, NULL, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); } else { @@ -785,7 +789,7 @@ long join_session_keyring(const char *name) keyring = keyring_alloc( name, old->uid, old->gid, old, KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, - KEY_ALLOC_IN_QUOTA, NULL); + KEY_ALLOC_IN_QUOTA, NULL, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error2; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index c7a117c9a8f3..a29e3554751e 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -116,7 +116,7 @@ static int call_sbin_request_key(struct key_construction *cons, cred = get_current_cred(); keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, - KEY_ALLOC_QUOTA_OVERRUN, NULL); + KEY_ALLOC_QUOTA_OVERRUN, NULL, NULL); put_cred(cred); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); @@ -355,7 +355,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx, key = key_alloc(ctx->index_key.type, ctx->index_key.description, ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred, - perm, flags); + perm, flags, NULL); if (IS_ERR(key)) goto alloc_failed; diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 4f0f112fe276..9db8b4a82787 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -202,7 +202,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, authkey = key_alloc(&key_type_request_key_auth, desc, cred->fsuid, cred->fsgid, cred, KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | - KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); + KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(authkey)) { ret = PTR_ERR(authkey); goto error_alloc; -- GitLab From 983023f28bff62b4462fd3575a86a8947ac592d8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:25 +0100 Subject: [PATCH 2111/9938] KEYS: Move x509_request_asymmetric_key() to asymmetric_type.c Move x509_request_asymmetric_key() to asymmetric_type.c so that it can be generalised. Signed-off-by: David Howells --- crypto/asymmetric_keys/asymmetric_type.c | 89 ++++++++++++++++++++++++ crypto/asymmetric_keys/x509_public_key.c | 89 ------------------------ include/crypto/public_key.h | 6 -- include/keys/asymmetric-type.h | 5 ++ 4 files changed, 94 insertions(+), 95 deletions(-) diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index a79d30128821..c4d66cd82860 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -34,6 +34,95 @@ EXPORT_SYMBOL_GPL(key_being_used_for); static LIST_HEAD(asymmetric_key_parsers); static DECLARE_RWSEM(asymmetric_key_parsers_sem); +/** + * x509_request_asymmetric_key - Request a key by X.509 certificate params. + * @keyring: The keys to search. + * @id: The issuer & serialNumber to look for or NULL. + * @skid: The subjectKeyIdentifier to look for or NULL. + * @partial: Use partial match if true, exact if false. + * + * Find a key in the given keyring by identifier. The preferred identifier is + * the issuer + serialNumber and the fallback identifier is the + * subjectKeyIdentifier. If both are given, the lookup is by the former, but + * the latter must also match. + */ +struct key *x509_request_asymmetric_key(struct key *keyring, + const struct asymmetric_key_id *id, + const struct asymmetric_key_id *skid, + bool partial) +{ + struct key *key; + key_ref_t ref; + const char *lookup; + char *req, *p; + int len; + + if (id) { + lookup = id->data; + len = id->len; + } else { + lookup = skid->data; + len = skid->len; + } + + /* Construct an identifier "id:". */ + p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); + if (!req) + return ERR_PTR(-ENOMEM); + + if (partial) { + *p++ = 'i'; + *p++ = 'd'; + } else { + *p++ = 'e'; + *p++ = 'x'; + } + *p++ = ':'; + p = bin2hex(p, lookup, len); + *p = 0; + + pr_debug("Look up: \"%s\"\n", req); + + ref = keyring_search(make_key_ref(keyring, 1), + &key_type_asymmetric, req); + if (IS_ERR(ref)) + pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); + kfree(req); + + if (IS_ERR(ref)) { + switch (PTR_ERR(ref)) { + /* Hide some search errors */ + case -EACCES: + case -ENOTDIR: + case -EAGAIN: + return ERR_PTR(-ENOKEY); + default: + return ERR_CAST(ref); + } + } + + key = key_ref_to_ptr(ref); + if (id && skid) { + const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); + if (!kids->id[1]) { + pr_debug("issuer+serial match, but expected SKID missing\n"); + goto reject; + } + if (!asymmetric_key_id_same(skid, kids->id[1])) { + pr_debug("issuer+serial match, but SKID does not\n"); + goto reject; + } + } + + pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); + return key; + +reject: + key_put(key); + return ERR_PTR(-EKEYREJECTED); +} +EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); + /** * asymmetric_key_generate_id: Construct an asymmetric key ID * @val_1: First binary blob diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index fc77a2bd70ba..2fb594175cef 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -58,95 +58,6 @@ static int __init ca_keys_setup(char *str) __setup("ca_keys=", ca_keys_setup); #endif -/** - * x509_request_asymmetric_key - Request a key by X.509 certificate params. - * @keyring: The keys to search. - * @id: The issuer & serialNumber to look for or NULL. - * @skid: The subjectKeyIdentifier to look for or NULL. - * @partial: Use partial match if true, exact if false. - * - * Find a key in the given keyring by identifier. The preferred identifier is - * the issuer + serialNumber and the fallback identifier is the - * subjectKeyIdentifier. If both are given, the lookup is by the former, but - * the latter must also match. - */ -struct key *x509_request_asymmetric_key(struct key *keyring, - const struct asymmetric_key_id *id, - const struct asymmetric_key_id *skid, - bool partial) -{ - struct key *key; - key_ref_t ref; - const char *lookup; - char *req, *p; - int len; - - if (id) { - lookup = id->data; - len = id->len; - } else { - lookup = skid->data; - len = skid->len; - } - - /* Construct an identifier "id:". */ - p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); - if (!req) - return ERR_PTR(-ENOMEM); - - if (partial) { - *p++ = 'i'; - *p++ = 'd'; - } else { - *p++ = 'e'; - *p++ = 'x'; - } - *p++ = ':'; - p = bin2hex(p, lookup, len); - *p = 0; - - pr_debug("Look up: \"%s\"\n", req); - - ref = keyring_search(make_key_ref(keyring, 1), - &key_type_asymmetric, req); - if (IS_ERR(ref)) - pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); - kfree(req); - - if (IS_ERR(ref)) { - switch (PTR_ERR(ref)) { - /* Hide some search errors */ - case -EACCES: - case -ENOTDIR: - case -EAGAIN: - return ERR_PTR(-ENOKEY); - default: - return ERR_CAST(ref); - } - } - - key = key_ref_to_ptr(ref); - if (id && skid) { - const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); - if (!kids->id[1]) { - pr_debug("issuer+serial match, but expected SKID missing\n"); - goto reject; - } - if (!asymmetric_key_id_same(skid, kids->id[1])) { - pr_debug("issuer+serial match, but SKID does not\n"); - goto reject; - } - } - - pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); - return key; - -reject: - key_put(key); - return ERR_PTR(-EKEYREJECTED); -} -EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); - /* * Set up the signature parameters in an X.509 certificate. This involves * digesting the signed data and extracting the signature. diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index b3928e801b8c..96ef27b8dd41 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -50,12 +50,6 @@ struct key; extern int verify_signature(const struct key *key, const struct public_key_signature *sig); -struct asymmetric_key_id; -extern struct key *x509_request_asymmetric_key(struct key *keyring, - const struct asymmetric_key_id *id, - const struct asymmetric_key_id *skid, - bool partial); - int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig); diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h index d1e23dda4363..735db697c4d2 100644 --- a/include/keys/asymmetric-type.h +++ b/include/keys/asymmetric-type.h @@ -76,6 +76,11 @@ const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) return key->payload.data[asym_key_ids]; } +extern struct key *x509_request_asymmetric_key(struct key *keyring, + const struct asymmetric_key_id *id, + const struct asymmetric_key_id *skid, + bool partial); + /* * The payload is at the discretion of the subtype. */ -- GitLab From 9eb029893ad5bf9303ed7f145860b312cbe5f889 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:25 +0100 Subject: [PATCH 2112/9938] KEYS: Generalise x509_request_asymmetric_key() Generalise x509_request_asymmetric_key(). It doesn't really have any dependencies on X.509 features as it uses generalised IDs and the public_key structs that contain data extracted from X.509. Signed-off-by: David Howells --- crypto/asymmetric_keys/asymmetric_keys.h | 2 ++ crypto/asymmetric_keys/asymmetric_type.c | 42 ++++++++++++------------ crypto/asymmetric_keys/pkcs7_trust.c | 19 +++++------ crypto/asymmetric_keys/x509_public_key.c | 5 ++- include/keys/asymmetric-type.h | 8 ++--- 5 files changed, 37 insertions(+), 39 deletions(-) diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h index 1d450b580245..ca8e9ac34ce6 100644 --- a/crypto/asymmetric_keys/asymmetric_keys.h +++ b/crypto/asymmetric_keys/asymmetric_keys.h @@ -9,6 +9,8 @@ * 2 of the Licence, or (at your option) any later version. */ +#include + extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); extern int __asymmetric_key_hex_to_key_id(const char *id, diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index c4d66cd82860..6600181d5d01 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -35,21 +35,20 @@ static LIST_HEAD(asymmetric_key_parsers); static DECLARE_RWSEM(asymmetric_key_parsers_sem); /** - * x509_request_asymmetric_key - Request a key by X.509 certificate params. + * find_asymmetric_key - Find a key by ID. * @keyring: The keys to search. - * @id: The issuer & serialNumber to look for or NULL. - * @skid: The subjectKeyIdentifier to look for or NULL. + * @id_0: The first ID to look for or NULL. + * @id_1: The second ID to look for or NULL. * @partial: Use partial match if true, exact if false. * * Find a key in the given keyring by identifier. The preferred identifier is - * the issuer + serialNumber and the fallback identifier is the - * subjectKeyIdentifier. If both are given, the lookup is by the former, but - * the latter must also match. + * the id_0 and the fallback identifier is the id_1. If both are given, the + * lookup is by the former, but the latter must also match. */ -struct key *x509_request_asymmetric_key(struct key *keyring, - const struct asymmetric_key_id *id, - const struct asymmetric_key_id *skid, - bool partial) +struct key *find_asymmetric_key(struct key *keyring, + const struct asymmetric_key_id *id_0, + const struct asymmetric_key_id *id_1, + bool partial) { struct key *key; key_ref_t ref; @@ -57,12 +56,12 @@ struct key *x509_request_asymmetric_key(struct key *keyring, char *req, *p; int len; - if (id) { - lookup = id->data; - len = id->len; + if (id_0) { + lookup = id_0->data; + len = id_0->len; } else { - lookup = skid->data; - len = skid->len; + lookup = id_1->data; + len = id_1->len; } /* Construct an identifier "id:". */ @@ -102,14 +101,15 @@ struct key *x509_request_asymmetric_key(struct key *keyring, } key = key_ref_to_ptr(ref); - if (id && skid) { + if (id_0 && id_1) { const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); - if (!kids->id[1]) { - pr_debug("issuer+serial match, but expected SKID missing\n"); + + if (!kids->id[0]) { + pr_debug("First ID matches, but second is missing\n"); goto reject; } - if (!asymmetric_key_id_same(skid, kids->id[1])) { - pr_debug("issuer+serial match, but SKID does not\n"); + if (!asymmetric_key_id_same(id_1, kids->id[1])) { + pr_debug("First ID matches, but second does not\n"); goto reject; } } @@ -121,7 +121,7 @@ struct key *x509_request_asymmetric_key(struct key *keyring, key_put(key); return ERR_PTR(-EKEYREJECTED); } -EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); +EXPORT_SYMBOL_GPL(find_asymmetric_key); /** * asymmetric_key_generate_id: Construct an asymmetric key ID diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 36e77cb07bd0..f6a009d88a33 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -51,9 +51,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, /* Look to see if this certificate is present in the trusted * keys. */ - key = x509_request_asymmetric_key(trust_keyring, - x509->id, x509->skid, - false); + key = find_asymmetric_key(trust_keyring, + x509->id, x509->skid, false); if (!IS_ERR(key)) { /* One of the X.509 certificates in the PKCS#7 message * is apparently the same as one we already trust. @@ -84,10 +83,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, * trusted keys. */ if (last && (last->sig->auth_ids[0] || last->sig->auth_ids[1])) { - key = x509_request_asymmetric_key(trust_keyring, - last->sig->auth_ids[0], - last->sig->auth_ids[1], - false); + key = find_asymmetric_key(trust_keyring, + last->sig->auth_ids[0], + last->sig->auth_ids[1], + false); if (!IS_ERR(key)) { x509 = last; pr_devel("sinfo %u: Root cert %u signer is key %x\n", @@ -101,10 +100,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, /* As a last resort, see if we have a trusted public key that matches * the signed info directly. */ - key = x509_request_asymmetric_key(trust_keyring, - sinfo->sig->auth_ids[0], - NULL, - false); + key = find_asymmetric_key(trust_keyring, + sinfo->sig->auth_ids[0], NULL, false); if (!IS_ERR(key)) { pr_devel("sinfo %u: Direct signer is key %x\n", sinfo->index, key_serial(key)); diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 2fb594175cef..9c8483ef1cfe 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -213,9 +213,8 @@ static int x509_validate_trust(struct x509_certificate *cert, if (cert->unsupported_sig) return -ENOPKG; - key = x509_request_asymmetric_key(trust_keyring, - sig->auth_ids[0], sig->auth_ids[1], - false); + key = find_asymmetric_key(trust_keyring, + sig->auth_ids[0], sig->auth_ids[1], false); if (IS_ERR(key)) return PTR_ERR(key); diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h index 735db697c4d2..b38240716d41 100644 --- a/include/keys/asymmetric-type.h +++ b/include/keys/asymmetric-type.h @@ -76,10 +76,10 @@ const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) return key->payload.data[asym_key_ids]; } -extern struct key *x509_request_asymmetric_key(struct key *keyring, - const struct asymmetric_key_id *id, - const struct asymmetric_key_id *skid, - bool partial); +extern struct key *find_asymmetric_key(struct key *keyring, + const struct asymmetric_key_id *id_0, + const struct asymmetric_key_id *id_1, + bool partial); /* * The payload is at the discretion of the subtype. -- GitLab From 5f7f5c81e59be5ce262c5b7d0ede9565a2558d80 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:25 +0100 Subject: [PATCH 2113/9938] X.509: Use verify_signature() if we have a struct key * to use We should call verify_signature() rather than directly calling public_key_verify_signature() if we have a struct key to use as we shouldn't be poking around in the private data of the key struct as that's subtype dependent. Signed-off-by: David Howells --- crypto/asymmetric_keys/x509_public_key.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 9c8483ef1cfe..117a6ee71a4d 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -220,8 +220,7 @@ static int x509_validate_trust(struct x509_certificate *cert, if (!use_builtin_keys || test_bit(KEY_FLAG_BUILTIN, &key->flags)) { - ret = public_key_verify_signature( - key->payload.data[asym_crypto], cert->sig); + ret = verify_signature(key, cert->sig); if (ret == -ENOPKG) cert->unsupported_sig = true; } -- GitLab From cfb664ff2b71fbbdc438b8e6db2a1412440432a2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:26 +0100 Subject: [PATCH 2114/9938] X.509: Move the trust validation code out to its own file Move the X.509 trust validation code out to its own file so that it can be generalised. Signed-off-by: David Howells --- crypto/asymmetric_keys/Makefile | 5 +- crypto/asymmetric_keys/restrict.c | 106 +++++++++++++++++++++++ crypto/asymmetric_keys/x509_parser.h | 6 ++ crypto/asymmetric_keys/x509_public_key.c | 79 ----------------- 4 files changed, 116 insertions(+), 80 deletions(-) create mode 100644 crypto/asymmetric_keys/restrict.c diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index f90486256f01..6516855bec18 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -4,7 +4,10 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o -asymmetric_keys-y := asymmetric_type.o signature.o +asymmetric_keys-y := \ + asymmetric_type.o \ + restrict.o \ + signature.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c new file mode 100644 index 000000000000..b4c10f2f5034 --- /dev/null +++ b/crypto/asymmetric_keys/restrict.c @@ -0,0 +1,106 @@ +/* Instantiate a public key crypto key from an X.509 Certificate + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#define pr_fmt(fmt) "X.509: "fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "asymmetric_keys.h" +#include "x509_parser.h" + +static bool use_builtin_keys; +static struct asymmetric_key_id *ca_keyid; + +#ifndef MODULE +static struct { + struct asymmetric_key_id id; + unsigned char data[10]; +} cakey; + +static int __init ca_keys_setup(char *str) +{ + if (!str) /* default system keyring */ + return 1; + + if (strncmp(str, "id:", 3) == 0) { + struct asymmetric_key_id *p = &cakey.id; + size_t hexlen = (strlen(str) - 3) / 2; + int ret; + + if (hexlen == 0 || hexlen > sizeof(cakey.data)) { + pr_err("Missing or invalid ca_keys id\n"); + return 1; + } + + ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen); + if (ret < 0) + pr_err("Unparsable ca_keys id hex string\n"); + else + ca_keyid = p; /* owner key 'id:xxxxxx' */ + } else if (strcmp(str, "builtin") == 0) { + use_builtin_keys = true; + } + + return 1; +} +__setup("ca_keys=", ca_keys_setup); +#endif + +/* + * Check the new certificate against the ones in the trust keyring. If one of + * those is the signing key and validates the new certificate, then mark the + * new certificate as being trusted. + * + * Return 0 if the new certificate was successfully validated, 1 if we couldn't + * find a matching parent certificate in the trusted list and an error if there + * is a matching certificate but the signature check fails. + */ +int x509_validate_trust(struct x509_certificate *cert, + struct key *trust_keyring) +{ + struct public_key_signature *sig = cert->sig; + struct key *key; + int ret = 1; + + if (!sig->auth_ids[0] && !sig->auth_ids[1]) + return 1; + + if (!trust_keyring) + return -EOPNOTSUPP; + if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) + return -EPERM; + if (cert->unsupported_sig) + return -ENOPKG; + + key = find_asymmetric_key(trust_keyring, + sig->auth_ids[0], sig->auth_ids[1], + false); + if (IS_ERR(key)) + return PTR_ERR(key); + + if (!use_builtin_keys || + test_bit(KEY_FLAG_BUILTIN, &key->flags)) { + ret = verify_signature(key, cert->sig); + if (ret == -ENOPKG) + cert->unsupported_sig = true; + } + key_put(key); + return ret; +} +EXPORT_SYMBOL_GPL(x509_validate_trust); diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 05eef1c68881..7a802b09a509 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -58,3 +58,9 @@ extern int x509_decode_time(time64_t *_t, size_t hdrlen, */ extern int x509_get_sig_params(struct x509_certificate *cert); extern int x509_check_for_self_signed(struct x509_certificate *cert); + +/* + * public_key_trust.c + */ +extern int x509_validate_trust(struct x509_certificate *cert, + struct key *trust_keyring); diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 117a6ee71a4d..6d7f42f0de9a 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -20,44 +20,6 @@ #include "asymmetric_keys.h" #include "x509_parser.h" -static bool use_builtin_keys; -static struct asymmetric_key_id *ca_keyid; - -#ifndef MODULE -static struct { - struct asymmetric_key_id id; - unsigned char data[10]; -} cakey; - -static int __init ca_keys_setup(char *str) -{ - if (!str) /* default system keyring */ - return 1; - - if (strncmp(str, "id:", 3) == 0) { - struct asymmetric_key_id *p = &cakey.id; - size_t hexlen = (strlen(str) - 3) / 2; - int ret; - - if (hexlen == 0 || hexlen > sizeof(cakey.data)) { - pr_err("Missing or invalid ca_keys id\n"); - return 1; - } - - ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen); - if (ret < 0) - pr_err("Unparsable ca_keys id hex string\n"); - else - ca_keyid = p; /* owner key 'id:xxxxxx' */ - } else if (strcmp(str, "builtin") == 0) { - use_builtin_keys = true; - } - - return 1; -} -__setup("ca_keys=", ca_keys_setup); -#endif - /* * Set up the signature parameters in an X.509 certificate. This involves * digesting the signed data and extracting the signature. @@ -187,47 +149,6 @@ int x509_check_for_self_signed(struct x509_certificate *cert) return 0; } -/* - * Check the new certificate against the ones in the trust keyring. If one of - * those is the signing key and validates the new certificate, then mark the - * new certificate as being trusted. - * - * Return 0 if the new certificate was successfully validated, 1 if we couldn't - * find a matching parent certificate in the trusted list and an error if there - * is a matching certificate but the signature check fails. - */ -static int x509_validate_trust(struct x509_certificate *cert, - struct key *trust_keyring) -{ - struct public_key_signature *sig = cert->sig; - struct key *key; - int ret = 1; - - if (!sig->auth_ids[0] && !sig->auth_ids[1]) - return 1; - - if (!trust_keyring) - return -EOPNOTSUPP; - if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) - return -EPERM; - if (cert->unsupported_sig) - return -ENOPKG; - - key = find_asymmetric_key(trust_keyring, - sig->auth_ids[0], sig->auth_ids[1], false); - if (IS_ERR(key)) - return PTR_ERR(key); - - if (!use_builtin_keys || - test_bit(KEY_FLAG_BUILTIN, &key->flags)) { - ret = verify_signature(key, cert->sig); - if (ret == -ENOPKG) - cert->unsupported_sig = true; - } - key_put(key); - return ret; -} - /* * Attempt to parse a data blob for a key as an X509 certificate. */ -- GitLab From 99716b7cae8263e1c7e7c1987e95d8f67071ab3e Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:26 +0100 Subject: [PATCH 2115/9938] KEYS: Make the system trusted keyring depend on the asymmetric key type Make the system trusted keyring depend on the asymmetric key type as there's not a lot of point having it if you can't then load asymmetric keys onto it. This requires the ASYMMETRIC_KEY_TYPE to be made a bool, not a tristate, as the Kconfig language doesn't then correctly force ASYMMETRIC_KEY_TYPE to 'y' rather than 'm' if SYSTEM_TRUSTED_KEYRING is 'y'. Making SYSTEM_TRUSTED_KEYRING *select* ASYMMETRIC_KEY_TYPE instead doesn't work as the Kconfig interpreter then wrongly complains about dependency loops. Signed-off-by: David Howells --- certs/Kconfig | 1 + crypto/asymmetric_keys/Kconfig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/certs/Kconfig b/certs/Kconfig index f0f8a4433685..743d480f5f6f 100644 --- a/certs/Kconfig +++ b/certs/Kconfig @@ -17,6 +17,7 @@ config MODULE_SIG_KEY config SYSTEM_TRUSTED_KEYRING bool "Provide system-wide ring of trusted keys" depends on KEYS + depends on ASYMMETRIC_KEY_TYPE help Provide a system keyring to which trusted keys can be added. Keys in the keyring are considered to be trusted. Keys may be added at will diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index f7d2ef9789d8..e28e912000a7 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -1,5 +1,5 @@ menuconfig ASYMMETRIC_KEY_TYPE - tristate "Asymmetric (public-key cryptographic) key type" + bool "Asymmetric (public-key cryptographic) key type" depends on KEYS help This option provides support for a key type that holds the data for -- GitLab From a511e1af8b12f44c6e55786c463c9f093c214fb6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:26 +0100 Subject: [PATCH 2116/9938] KEYS: Move the point of trust determination to __key_link() Move the point at which a key is determined to be trustworthy to __key_link() so that we use the contents of the keyring being linked in to to determine whether the key being linked in is trusted or not. What is 'trusted' then becomes a matter of what's in the keyring. Currently, the test is done when the key is parsed, but given that at that point we can only sensibly refer to the contents of the system trusted keyring, we can only use that as the basis for working out the trustworthiness of a new key. With this change, a trusted keyring is a set of keys that once the trusted-only flag is set cannot be added to except by verification through one of the contained keys. Further, adding a key into a trusted keyring, whilst it might grant trustworthiness in the context of that keyring, does not automatically grant trustworthiness in the context of a second keyring to which it could be secondarily linked. To accomplish this, the authentication data associated with the key source must now be retained. For an X.509 cert, this means the contents of the AuthorityKeyIdentifier and the signature data. If system keyrings are disabled then restrict_link_by_builtin_trusted() resolves to restrict_link_reject(). The integrity digital signature code still works correctly with this as it was previously using KEY_FLAG_TRUSTED_ONLY, which doesn't permit anything to be added if there is no system keyring against which trust can be determined. Signed-off-by: David Howells --- certs/system_keyring.c | 20 ++++++-- crypto/asymmetric_keys/restrict.c | 62 ++++++++++++------------ crypto/asymmetric_keys/x509_parser.h | 6 --- crypto/asymmetric_keys/x509_public_key.c | 21 +------- include/crypto/public_key.h | 7 +++ include/keys/system_keyring.h | 19 +++----- kernel/module_signing.c | 2 +- security/integrity/digsig.c | 33 ++++++++++++- security/integrity/ima/ima_mok.c | 6 +-- 9 files changed, 100 insertions(+), 76 deletions(-) diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 417d65882870..4e2fa8ab01d6 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -18,12 +18,26 @@ #include #include -struct key *system_trusted_keyring; -EXPORT_SYMBOL_GPL(system_trusted_keyring); +static struct key *system_trusted_keyring; extern __initconst const u8 system_certificate_list[]; extern __initconst const unsigned long system_certificate_list_size; +/** + * restrict_link_by_builtin_trusted - Restrict keyring addition by system CA + * + * Restrict the addition of keys into a keyring based on the key-to-be-added + * being vouched for by a key in the system keyring. + */ +int restrict_link_by_builtin_trusted(struct key *keyring, + const struct key_type *type, + unsigned long flags, + const union key_payload *payload) +{ + return restrict_link_by_signature(system_trusted_keyring, + type, payload); +} + /* * Load the compiled-in keys */ @@ -37,7 +51,7 @@ static __init int system_trusted_keyring_init(void) ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, - keyring_restrict_trusted_only, NULL); + restrict_link_by_builtin_trusted, NULL); if (IS_ERR(system_trusted_keyring)) panic("Can't allocate system trusted keyring\n"); return 0; diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index b4c10f2f5034..ac4bddf669de 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c @@ -1,6 +1,6 @@ /* Instantiate a public key crypto key from an X.509 Certificate * - * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -9,20 +9,12 @@ * 2 of the Licence, or (at your option) any later version. */ -#define pr_fmt(fmt) "X.509: "fmt +#define pr_fmt(fmt) "ASYM: "fmt #include #include -#include #include -#include -#include -#include -#include -#include -#include #include #include "asymmetric_keys.h" -#include "x509_parser.h" static bool use_builtin_keys; static struct asymmetric_key_id *ca_keyid; @@ -62,45 +54,55 @@ static int __init ca_keys_setup(char *str) __setup("ca_keys=", ca_keys_setup); #endif -/* +/** + * restrict_link_by_signature - Restrict additions to a ring of public keys + * @trust_keyring: A ring of keys that can be used to vouch for the new cert. + * @type: The type of key being added. + * @payload: The payload of the new key. + * * Check the new certificate against the ones in the trust keyring. If one of * those is the signing key and validates the new certificate, then mark the * new certificate as being trusted. * - * Return 0 if the new certificate was successfully validated, 1 if we couldn't - * find a matching parent certificate in the trusted list and an error if there - * is a matching certificate but the signature check fails. + * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a + * matching parent certificate in the trusted list, -EKEYREJECTED if the + * signature check fails or the key is blacklisted and some other error if + * there is a matching certificate but the signature check cannot be performed. */ -int x509_validate_trust(struct x509_certificate *cert, - struct key *trust_keyring) +int restrict_link_by_signature(struct key *trust_keyring, + const struct key_type *type, + const union key_payload *payload) { - struct public_key_signature *sig = cert->sig; + const struct public_key_signature *sig; struct key *key; - int ret = 1; + int ret; - if (!sig->auth_ids[0] && !sig->auth_ids[1]) - return 1; + pr_devel("==>%s()\n", __func__); if (!trust_keyring) + return -ENOKEY; + + if (type != &key_type_asymmetric) return -EOPNOTSUPP; + + sig = payload->data[asym_auth]; + if (!sig->auth_ids[0] && !sig->auth_ids[1]) + return 0; + if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) return -EPERM; - if (cert->unsupported_sig) - return -ENOPKG; + /* See if we have a key that signed this one. */ key = find_asymmetric_key(trust_keyring, sig->auth_ids[0], sig->auth_ids[1], false); if (IS_ERR(key)) - return PTR_ERR(key); + return -ENOKEY; - if (!use_builtin_keys || - test_bit(KEY_FLAG_BUILTIN, &key->flags)) { - ret = verify_signature(key, cert->sig); - if (ret == -ENOPKG) - cert->unsupported_sig = true; - } + if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags)) + ret = -ENOKEY; + else + ret = verify_signature(key, sig); key_put(key); return ret; } -EXPORT_SYMBOL_GPL(x509_validate_trust); diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 7a802b09a509..05eef1c68881 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -58,9 +58,3 @@ extern int x509_decode_time(time64_t *_t, size_t hdrlen, */ extern int x509_get_sig_params(struct x509_certificate *cert); extern int x509_check_for_self_signed(struct x509_certificate *cert); - -/* - * public_key_trust.c - */ -extern int x509_validate_trust(struct x509_certificate *cert, - struct key *trust_keyring); diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 6d7f42f0de9a..fb732296cd36 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -178,31 +178,12 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) cert->pub->id_type = "X509"; - /* See if we can derive the trustability of this certificate. - * - * When it comes to self-signed certificates, we cannot evaluate - * trustedness except by the fact that we obtained it from a trusted - * location. So we just rely on x509_validate_trust() failing in this - * case. - * - * Note that there's a possibility of a self-signed cert matching a - * cert that we have (most likely a duplicate that we already trust) - - * in which case it will be marked trusted. - */ - if (cert->unsupported_sig || cert->self_signed) { + if (cert->unsupported_sig) { public_key_signature_free(cert->sig); cert->sig = NULL; } else { pr_devel("Cert Signature: %s + %s\n", cert->sig->pkey_algo, cert->sig->hash_algo); - - ret = x509_validate_trust(cert, get_system_trusted_keyring()); - if (ret) - ret = x509_validate_trust(cert, get_ima_mok_keyring()); - if (ret == -EKEYREJECTED) - goto error_free_cert; - if (!ret) - prep->trusted = true; } /* Propose a description */ diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 96ef27b8dd41..882ca0e1e7a5 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -47,6 +47,13 @@ extern void public_key_signature_free(struct public_key_signature *sig); extern struct asymmetric_key_subtype public_key_subtype; struct key; +struct key_type; +union key_payload; + +extern int restrict_link_by_signature(struct key *trust_keyring, + const struct key_type *type, + const union key_payload *payload); + extern int verify_signature(const struct key *key, const struct public_key_signature *sig); diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index b2d645ac35a0..93715913a0b1 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -12,22 +12,17 @@ #ifndef _KEYS_SYSTEM_KEYRING_H #define _KEYS_SYSTEM_KEYRING_H +#include + #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING -#include -#include -#include +extern int restrict_link_by_builtin_trusted(struct key *keyring, + const struct key_type *type, + unsigned long flags, + const union key_payload *payload); -extern struct key *system_trusted_keyring; -static inline struct key *get_system_trusted_keyring(void) -{ - return system_trusted_keyring; -} #else -static inline struct key *get_system_trusted_keyring(void) -{ - return NULL; -} +#define restrict_link_by_builtin_trusted restrict_link_reject #endif #ifdef CONFIG_IMA_MOK_KEYRING diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 6a64e03b9f44..937c844bee4a 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include "module-internal.h" diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 659566c2200b..d647178c6bbd 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "integrity.h" @@ -40,6 +42,35 @@ static bool init_keyring __initdata = true; static bool init_keyring __initdata; #endif +#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING +/* + * Restrict the addition of keys into the IMA keyring. + * + * Any key that needs to go in .ima keyring must be signed by CA in + * either .system or .ima_mok keyrings. + */ +static int restrict_link_by_ima_mok(struct key *keyring, + const struct key_type *type, + unsigned long flags, + const union key_payload *payload) +{ + int ret; + + ret = restrict_link_by_builtin_trusted(keyring, type, flags, payload); + if (ret != -ENOKEY) + return ret; + + return restrict_link_by_signature(get_ima_mok_keyring(), + type, payload); +} +#else +/* + * If there's no system trusted keyring, then keys cannot be loaded into + * .ima_mok and added keys cannot be marked trusted. + */ +#define restrict_link_by_ima_mok restrict_link_reject +#endif + int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, const char *digest, int digestlen) { @@ -84,7 +115,7 @@ int __init integrity_init_keyring(const unsigned int id) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, - NULL, NULL); + restrict_link_by_ima_mok, NULL); if (IS_ERR(keyring[id])) { err = PTR_ERR(keyring[id]); pr_info("Can't allocate %s keyring (%d)\n", diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index ef91248cb934..2988726d30d6 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include struct key *ima_mok_keyring; @@ -36,7 +36,7 @@ __init int ima_mok_init(void) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, - keyring_restrict_trusted_only, NULL); + restrict_link_by_builtin_trusted, NULL); ima_blacklist_keyring = keyring_alloc(".ima_blacklist", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), @@ -44,7 +44,7 @@ __init int ima_mok_init(void) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, - keyring_restrict_trusted_only, NULL); + restrict_link_by_builtin_trusted, NULL); if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring)) panic("Can't allocate IMA MOK or blacklist keyrings."); -- GitLab From 77f68bac9481ad440f4f34dda3d28c2dce6eb87b Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:26 +0100 Subject: [PATCH 2117/9938] KEYS: Remove KEY_FLAG_TRUSTED and KEY_ALLOC_TRUSTED Remove KEY_FLAG_TRUSTED and KEY_ALLOC_TRUSTED as they're no longer meaningful. Also we can drop the trusted flag from the preparse structure. Given this, we no longer need to pass the key flags through to restrict_link(). Further, we can now get rid of keyring_restrict_trusted_only() also. Signed-off-by: David Howells --- certs/system_keyring.c | 2 -- include/keys/system_keyring.h | 1 - include/linux/key-type.h | 1 - include/linux/key.h | 21 +++++---------------- security/integrity/digsig.c | 3 +-- security/keys/key.c | 11 ++--------- security/keys/keyring.c | 29 +---------------------------- 7 files changed, 9 insertions(+), 59 deletions(-) diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 4e2fa8ab01d6..e460d00a7781 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -31,7 +31,6 @@ extern __initconst const unsigned long system_certificate_list_size; */ int restrict_link_by_builtin_trusted(struct key *keyring, const struct key_type *type, - unsigned long flags, const union key_payload *payload) { return restrict_link_by_signature(system_trusted_keyring, @@ -97,7 +96,6 @@ static __init int load_system_certificate_list(void) ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ), KEY_ALLOC_NOT_IN_QUOTA | - KEY_ALLOC_TRUSTED | KEY_ALLOC_BUILT_IN | KEY_ALLOC_BYPASS_RESTRICTION); if (IS_ERR(key)) { diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index 93715913a0b1..c72330ae76df 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -18,7 +18,6 @@ extern int restrict_link_by_builtin_trusted(struct key *keyring, const struct key_type *type, - unsigned long flags, const union key_payload *payload); #else diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 7463355a198b..eaee981c5558 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -45,7 +45,6 @@ struct key_preparsed_payload { size_t datalen; /* Raw datalen */ size_t quotalen; /* Quota length for proposed payload */ time_t expiry; /* Expiry time of key */ - bool trusted; /* True if key is trusted */ }; typedef int (*request_key_actor_t)(struct key_construction *key, diff --git a/include/linux/key.h b/include/linux/key.h index 83b603639d2e..722914798f37 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -173,10 +173,9 @@ struct key { #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ -#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ -#define KEY_FLAG_BUILTIN 9 /* set if key is built in to the kernel */ -#define KEY_FLAG_ROOT_CAN_INVAL 10 /* set if key can be invalidated by root without permission */ -#define KEY_FLAG_KEEP 11 /* set if key should not be removed */ +#define KEY_FLAG_BUILTIN 8 /* set if key is built in to the kernel */ +#define KEY_FLAG_ROOT_CAN_INVAL 9 /* set if key can be invalidated by root without permission */ +#define KEY_FLAG_KEEP 10 /* set if key should not be removed */ /* the key type and key description string * - the desc is used to match a key against search criteria @@ -217,7 +216,6 @@ struct key { */ int (*restrict_link)(struct key *keyring, const struct key_type *type, - unsigned long flags, const union key_payload *payload); }; @@ -229,16 +227,14 @@ extern struct key *key_alloc(struct key_type *type, unsigned long flags, int (*restrict_link)(struct key *, const struct key_type *, - unsigned long, const union key_payload *)); #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ -#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ -#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */ -#define KEY_ALLOC_BYPASS_RESTRICTION 0x0010 /* Override the check on restricted keyrings */ +#define KEY_ALLOC_BUILT_IN 0x0004 /* Key is built into kernel */ +#define KEY_ALLOC_BYPASS_RESTRICTION 0x0008 /* Override the check on restricted keyrings */ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); @@ -309,18 +305,11 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid unsigned long flags, int (*restrict_link)(struct key *, const struct key_type *, - unsigned long, const union key_payload *), struct key *dest); -extern int keyring_restrict_trusted_only(struct key *keyring, - const struct key_type *type, - unsigned long, - const union key_payload *payload); - extern int restrict_link_reject(struct key *keyring, const struct key_type *type, - unsigned long flags, const union key_payload *payload); extern int keyring_clear(struct key *keyring); diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index d647178c6bbd..98ee4c752cf5 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -51,12 +51,11 @@ static bool init_keyring __initdata; */ static int restrict_link_by_ima_mok(struct key *keyring, const struct key_type *type, - unsigned long flags, const union key_payload *payload) { int ret; - ret = restrict_link_by_builtin_trusted(keyring, type, flags, payload); + ret = restrict_link_by_builtin_trusted(keyring, type, payload); if (ret != -ENOKEY) return ret; diff --git a/security/keys/key.c b/security/keys/key.c index deb881754e03..bd5a272f28a6 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -227,7 +227,6 @@ struct key *key_alloc(struct key_type *type, const char *desc, key_perm_t perm, unsigned long flags, int (*restrict_link)(struct key *, const struct key_type *, - unsigned long, const union key_payload *)) { struct key_user *user = NULL; @@ -300,8 +299,6 @@ struct key *key_alloc(struct key_type *type, const char *desc, if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) key->flags |= 1 << KEY_FLAG_IN_QUOTA; - if (flags & KEY_ALLOC_TRUSTED) - key->flags |= 1 << KEY_FLAG_TRUSTED; if (flags & KEY_ALLOC_BUILT_IN) key->flags |= 1 << KEY_FLAG_BUILTIN; @@ -504,7 +501,7 @@ int key_instantiate_and_link(struct key *key, if (keyring) { if (keyring->restrict_link) { ret = keyring->restrict_link(keyring, key->type, - key->flags, &prep.payload); + &prep.payload); if (ret < 0) goto error; } @@ -811,7 +808,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, int ret; int (*restrict_link)(struct key *, const struct key_type *, - unsigned long, const union key_payload *) = NULL; /* look up the key type to see if it's one of the registered kernel @@ -843,7 +839,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, prep.data = payload; prep.datalen = plen; prep.quotalen = index_key.type->def_datalen; - prep.trusted = flags & KEY_ALLOC_TRUSTED; prep.expiry = TIME_T_MAX; if (index_key.type->preparse) { ret = index_key.type->preparse(&prep); @@ -860,9 +855,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, index_key.desc_len = strlen(index_key.description); if (restrict_link) { - unsigned long kflags = prep.trusted ? KEY_FLAG_TRUSTED : 0; - ret = restrict_link(keyring, - index_key.type, kflags, &prep.payload); + ret = restrict_link(keyring, index_key.type, &prep.payload); if (ret < 0) { key_ref = ERR_PTR(ret); goto error_free_prep; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index d2d1f3378008..c91e4e0cea08 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -494,7 +494,6 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, unsigned long flags, int (*restrict_link)(struct key *, const struct key_type *, - unsigned long, const union key_payload *), struct key *dest) { @@ -515,34 +514,10 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, } EXPORT_SYMBOL(keyring_alloc); -/** - * keyring_restrict_trusted_only - Restrict additions to a keyring to trusted keys only - * @keyring: The keyring being added to. - * @type: The type of key being added. - * @flags: The key flags. - * @payload: The payload of the key intended to be added. - * - * Reject the addition of any links to a keyring that point to keys that aren't - * marked as being trusted. It can be overridden by passing - * KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when adding a key - * to a keyring. - * - * This is meant to be passed as the restrict_link parameter to - * keyring_alloc(). - */ -int keyring_restrict_trusted_only(struct key *keyring, - const struct key_type *type, - unsigned long flags, - const union key_payload *payload) -{ - return flags & KEY_FLAG_TRUSTED ? 0 : -EPERM; -} - /** * restrict_link_reject - Give -EPERM to restrict link * @keyring: The keyring being added to. * @type: The type of key being added. - * @flags: The key flags. * @payload: The payload of the key intended to be added. * * Reject the addition of any links to a keyring. It can be overridden by @@ -554,7 +529,6 @@ int keyring_restrict_trusted_only(struct key *keyring, */ int restrict_link_reject(struct key *keyring, const struct key_type *type, - unsigned long flags, const union key_payload *payload) { return -EPERM; @@ -1248,8 +1222,7 @@ static int __key_link_check_restriction(struct key *keyring, struct key *key) { if (!keyring->restrict_link) return 0; - return keyring->restrict_link(keyring, - key->type, key->flags, &key->payload); + return keyring->restrict_link(keyring, key->type, &key->payload); } /** -- GitLab From d3bfe84129f65e0af2450743ebdab33d161d01c9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:27 +0100 Subject: [PATCH 2118/9938] certs: Add a secondary system keyring that can be added to dynamically Add a secondary system keyring that can be added to by root whilst the system is running - provided the key being added is vouched for by a key built into the kernel or already added to the secondary keyring. Rename .system_keyring to .builtin_trusted_keys to distinguish it more obviously from the new keyring (called .secondary_trusted_keys). The new keyring needs to be enabled with CONFIG_SECONDARY_TRUSTED_KEYRING. If the secondary keyring is enabled, a link is created from that to .builtin_trusted_keys so that the the latter will automatically be searched too if the secondary keyring is searched. Signed-off-by: David Howells --- certs/Kconfig | 8 ++++ certs/system_keyring.c | 87 ++++++++++++++++++++++++++++------- include/keys/system_keyring.h | 9 ++++ 3 files changed, 88 insertions(+), 16 deletions(-) diff --git a/certs/Kconfig b/certs/Kconfig index 743d480f5f6f..fc5955f5fc8a 100644 --- a/certs/Kconfig +++ b/certs/Kconfig @@ -56,4 +56,12 @@ config SYSTEM_EXTRA_CERTIFICATE_SIZE This is the number of bytes reserved in the kernel image for a certificate to be inserted. +config SECONDARY_TRUSTED_KEYRING + bool "Provide a keyring to which extra trustable keys may be added" + depends on SYSTEM_TRUSTED_KEYRING + help + If set, provide a keyring to which extra keys may be added, provided + those keys are not blacklisted and are vouched for by a key built + into the kernel or already in the secondary trusted keyring. + endmenu diff --git a/certs/system_keyring.c b/certs/system_keyring.c index e460d00a7781..50979d6dcecd 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -18,41 +18,88 @@ #include #include -static struct key *system_trusted_keyring; +static struct key *builtin_trusted_keys; +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +static struct key *secondary_trusted_keys; +#endif extern __initconst const u8 system_certificate_list[]; extern __initconst const unsigned long system_certificate_list_size; /** - * restrict_link_by_builtin_trusted - Restrict keyring addition by system CA + * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA * * Restrict the addition of keys into a keyring based on the key-to-be-added - * being vouched for by a key in the system keyring. + * being vouched for by a key in the built in system keyring. */ int restrict_link_by_builtin_trusted(struct key *keyring, const struct key_type *type, const union key_payload *payload) { - return restrict_link_by_signature(system_trusted_keyring, - type, payload); + return restrict_link_by_signature(builtin_trusted_keys, type, payload); } +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +/** + * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring + * addition by both builtin and secondary keyrings + * + * Restrict the addition of keys into a keyring based on the key-to-be-added + * being vouched for by a key in either the built-in or the secondary system + * keyrings. + */ +int restrict_link_by_builtin_and_secondary_trusted( + struct key *keyring, + const struct key_type *type, + const union key_payload *payload) +{ + /* If we have a secondary trusted keyring, then that contains a link + * through to the builtin keyring and the search will follow that link. + */ + if (type == &key_type_keyring && + keyring == secondary_trusted_keys && + payload == &builtin_trusted_keys->payload) + /* Allow the builtin keyring to be added to the secondary */ + return 0; + + return restrict_link_by_signature(secondary_trusted_keys, type, payload); +} +#endif + /* - * Load the compiled-in keys + * Create the trusted keyrings */ static __init int system_trusted_keyring_init(void) { - pr_notice("Initialise system trusted keyring\n"); + pr_notice("Initialise system trusted keyrings\n"); - system_trusted_keyring = - keyring_alloc(".system_keyring", + builtin_trusted_keys = + keyring_alloc(".builtin_trusted_keys", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, - restrict_link_by_builtin_trusted, NULL); - if (IS_ERR(system_trusted_keyring)) - panic("Can't allocate system trusted keyring\n"); + NULL, NULL); + if (IS_ERR(builtin_trusted_keys)) + panic("Can't allocate builtin trusted keyring\n"); + +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING + secondary_trusted_keys = + keyring_alloc(".secondary_trusted_keys", + KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH | + KEY_USR_WRITE), + KEY_ALLOC_NOT_IN_QUOTA, + restrict_link_by_builtin_and_secondary_trusted, + NULL); + if (IS_ERR(secondary_trusted_keys)) + panic("Can't allocate secondary trusted keyring\n"); + + if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0) + panic("Can't link trusted keyrings\n"); +#endif + return 0; } @@ -88,7 +135,7 @@ static __init int load_system_certificate_list(void) if (plen > end - p) goto dodgy_cert; - key = key_create_or_update(make_key_ref(system_trusted_keyring, 1), + key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1), "asymmetric", NULL, p, @@ -125,7 +172,8 @@ late_initcall(load_system_certificate_list); * @len: Size of @data. * @raw_pkcs7: The PKCS#7 message that is the signature. * @pkcs7_len: The size of @raw_pkcs7. - * @trusted_keys: Trusted keys to use (NULL for system_trusted_keyring). + * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only, + * (void *)1UL for all trusted keys). * @usage: The use to which the key is being put. * @view_content: Callback to gain access to content. * @ctx: Context for callback. @@ -157,8 +205,15 @@ int verify_pkcs7_signature(const void *data, size_t len, if (ret < 0) goto error; - if (!trusted_keys) - trusted_keys = system_trusted_keyring; + if (!trusted_keys) { + trusted_keys = builtin_trusted_keys; + } else if (trusted_keys == (void *)1UL) { +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING + trusted_keys = secondary_trusted_keys; +#else + trusted_keys = builtin_trusted_keys; +#endif + } ret = pkcs7_validate_trust(pkcs7, trusted_keys); if (ret < 0) { if (ret == -ENOKEY) diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index c72330ae76df..614424029de7 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -24,6 +24,15 @@ extern int restrict_link_by_builtin_trusted(struct key *keyring, #define restrict_link_by_builtin_trusted restrict_link_reject #endif +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +extern int restrict_link_by_builtin_and_secondary_trusted( + struct key *keyring, + const struct key_type *type, + const union key_payload *payload); +#else +#define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted +#endif + #ifdef CONFIG_IMA_MOK_KEYRING extern struct key *ima_mok_keyring; extern struct key *ima_blacklist_keyring; -- GitLab From 56104cf2b8d20eed32c14eac8ac574c35377ab38 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Apr 2016 09:45:23 +0100 Subject: [PATCH 2119/9938] IMA: Use the the system trusted keyrings instead of .ima_mok Add a config option (IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY) that, when enabled, allows keys to be added to the IMA keyrings by userspace - with the restriction that each must be signed by a key in the system trusted keyrings. EPERM will be returned if this option is disabled, ENOKEY will be returned if no authoritative key can be found and EKEYREJECTED will be returned if the signature doesn't match. Other errors such as ENOPKG may also be returned. If this new option is enabled, the builtin system keyring is searched, as is the secondary system keyring if that is also enabled. Intermediate keys between the builtin system keyring and the key being added can be added to the secondary keyring (which replaces .ima_mok) to form a trust chain - provided they are also validly signed by a key in one of the trusted keyrings. The .ima_mok keyring is then removed and the IMA blacklist keyring gets its own config option (IMA_BLACKLIST_KEYRING). Signed-off-by: David Howells Signed-off-by: Mimi Zohar --- include/keys/system_keyring.h | 13 ++---------- security/integrity/digsig.c | 30 ++++---------------------- security/integrity/ima/Kconfig | 36 ++++++++++++++++++++------------ security/integrity/ima/Makefile | 2 +- security/integrity/ima/ima_mok.c | 17 ++++----------- 5 files changed, 34 insertions(+), 64 deletions(-) diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index 614424029de7..fbd4647767e9 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -33,28 +33,19 @@ extern int restrict_link_by_builtin_and_secondary_trusted( #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted #endif -#ifdef CONFIG_IMA_MOK_KEYRING -extern struct key *ima_mok_keyring; +#ifdef CONFIG_IMA_BLACKLIST_KEYRING extern struct key *ima_blacklist_keyring; -static inline struct key *get_ima_mok_keyring(void) -{ - return ima_mok_keyring; -} static inline struct key *get_ima_blacklist_keyring(void) { return ima_blacklist_keyring; } #else -static inline struct key *get_ima_mok_keyring(void) -{ - return NULL; -} static inline struct key *get_ima_blacklist_keyring(void) { return NULL; } -#endif /* CONFIG_IMA_MOK_KEYRING */ +#endif /* CONFIG_IMA_BLACKLIST_KEYRING */ #endif /* _KEYS_SYSTEM_KEYRING_H */ diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 98ee4c752cf5..4304372b323f 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -42,32 +42,10 @@ static bool init_keyring __initdata = true; static bool init_keyring __initdata; #endif -#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING -/* - * Restrict the addition of keys into the IMA keyring. - * - * Any key that needs to go in .ima keyring must be signed by CA in - * either .system or .ima_mok keyrings. - */ -static int restrict_link_by_ima_mok(struct key *keyring, - const struct key_type *type, - const union key_payload *payload) -{ - int ret; - - ret = restrict_link_by_builtin_trusted(keyring, type, payload); - if (ret != -ENOKEY) - return ret; - - return restrict_link_by_signature(get_ima_mok_keyring(), - type, payload); -} +#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY +#define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted #else -/* - * If there's no system trusted keyring, then keys cannot be loaded into - * .ima_mok and added keys cannot be marked trusted. - */ -#define restrict_link_by_ima_mok restrict_link_reject +#define restrict_link_to_ima restrict_link_by_builtin_trusted #endif int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, @@ -114,7 +92,7 @@ int __init integrity_init_keyring(const unsigned int id) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, - restrict_link_by_ima_mok, NULL); + restrict_link_to_ima, NULL); if (IS_ERR(keyring[id])) { err = PTR_ERR(keyring[id]); pr_info("Can't allocate %s keyring (%d)\n", diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index e54a8a8dae94..5487827fa86c 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -155,23 +155,33 @@ config IMA_TRUSTED_KEYRING This option is deprecated in favor of INTEGRITY_TRUSTED_KEYRING -config IMA_MOK_KEYRING - bool "Create IMA machine owner keys (MOK) and blacklist keyrings" +config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY + bool "Permit keys validly signed by a built-in or secondary CA cert (EXPERIMENTAL)" + depends on SYSTEM_TRUSTED_KEYRING + depends on SECONDARY_TRUSTED_KEYRING + depends on INTEGRITY_ASYMMETRIC_KEYS + select INTEGRITY_TRUSTED_KEYRING + default n + help + Keys may be added to the IMA or IMA blacklist keyrings, if the + key is validly signed by a CA cert in the system built-in or + secondary trusted keyrings. + + Intermediate keys between those the kernel has compiled in and the + IMA keys to be added may be added to the system secondary keyring, + provided they are validly signed by a key already resident in the + built-in or secondary trusted keyrings. + +config IMA_BLACKLIST_KEYRING + bool "Create IMA machine owner blacklist keyrings (EXPERIMENTAL)" depends on SYSTEM_TRUSTED_KEYRING depends on IMA_TRUSTED_KEYRING default n help - This option creates IMA MOK and blacklist keyrings. IMA MOK is an - intermediate keyring that sits between .system and .ima keyrings, - effectively forming a simple CA hierarchy. To successfully import a - key into .ima_mok it must be signed by a key which CA is in .system - keyring. On turn any key that needs to go in .ima keyring must be - signed by CA in either .system or .ima_mok keyrings. IMA MOK is empty - at kernel boot. - - IMA blacklist keyring contains all revoked IMA keys. It is consulted - before any other keyring. If the search is successful the requested - operation is rejected and error is returned to the caller. + This option creates an IMA blacklist keyring, which contains all + revoked IMA keys. It is consulted before any other keyring. If + the search is successful the requested operation is rejected and + an error is returned to the caller. config IMA_LOAD_X509 bool "Load X509 certificate onto the '.ima' trusted keyring" diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index a8539f9e060f..9aeaedad1e2b 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_IMA) += ima.o ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ ima_policy.o ima_template.o ima_template_lib.o ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o -obj-$(CONFIG_IMA_MOK_KEYRING) += ima_mok.o +obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index 2988726d30d6..74a279957464 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c @@ -20,23 +20,14 @@ #include -struct key *ima_mok_keyring; struct key *ima_blacklist_keyring; /* - * Allocate the IMA MOK and blacklist keyrings + * Allocate the IMA blacklist keyring */ __init int ima_mok_init(void) { - pr_notice("Allocating IMA MOK and blacklist keyrings.\n"); - - ima_mok_keyring = keyring_alloc(".ima_mok", - KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), - (KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW | KEY_USR_READ | - KEY_USR_WRITE | KEY_USR_SEARCH, - KEY_ALLOC_NOT_IN_QUOTA, - restrict_link_by_builtin_trusted, NULL); + pr_notice("Allocating IMA blacklist keyring.\n"); ima_blacklist_keyring = keyring_alloc(".ima_blacklist", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), @@ -46,8 +37,8 @@ __init int ima_mok_init(void) KEY_ALLOC_NOT_IN_QUOTA, restrict_link_by_builtin_trusted, NULL); - if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring)) - panic("Can't allocate IMA MOK or blacklist keyrings."); + if (IS_ERR(ima_blacklist_keyring)) + panic("Can't allocate IMA blacklist keyring."); set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags); return 0; -- GitLab From c7e16e5257ec46530e3e874af38191746c137c83 Mon Sep 17 00:00:00 2001 From: Jerry Hoemann Date: Mon, 11 Apr 2016 15:02:26 -0700 Subject: [PATCH 2120/9938] acpi: widen acpi_evaluate_dsm() revision and function-index arguments The ACPI specification states that arguments "Revision ID" and "Function Index" to a _DSM are type "Integer." Type Integers are 64 bit quantities. The function evaluate_dsm specifies these types as simple "int" which are 32 bits. Widen type passed to acpi_evaluate_dsm and its callers and derived callers to pass correct type. acpi_check_dsm and acpi_evaluate_dsm_typed had similar issue and were corrected as well. This is in preparation for libnvdimm implementing a generic _DSM passthrough facility to have the capacity to pass 64-bit values as the ACPI specification allows. [djbw: clarify the changelog, add rationale] Signed-off-by: Jerry Hoemann Acked-by: Rafael J. Wysocki Signed-off-by: Dan Williams --- drivers/acpi/utils.c | 4 ++-- include/acpi/acpi_bus.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 050673f0c0b3..e854dea7d5fe 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -625,7 +625,7 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) * some old BIOSes do expect a buffer or an integer etc. */ union acpi_object * -acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func, +acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 func, union acpi_object *argv4) { acpi_status ret; @@ -674,7 +674,7 @@ EXPORT_SYMBOL(acpi_evaluate_dsm); * functions. Currently only support 64 functions at maximum, should be * enough for now. */ -bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) +bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs) { int i; u64 mask = 0; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 14362a84c78e..f092cc6eb1fb 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -61,12 +61,12 @@ bool acpi_ata_match(acpi_handle handle); bool acpi_bay_match(acpi_handle handle); bool acpi_dock_match(acpi_handle handle); -bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs); +bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs); union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, - int rev, int func, union acpi_object *argv4); + u64 rev, u64 func, union acpi_object *argv4); static inline union acpi_object * -acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, +acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, u64 rev, u64 func, union acpi_object *argv4, acpi_object_type type) { union acpi_object *obj; -- GitLab From 9d2597e8c4e593e4a4dbe70837e9396e53a2665a Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Apr 2016 12:30:59 -0400 Subject: [PATCH 2121/9938] MAINTAINERS: Add DT bindings to regulator framework entry The regulators DT bindings docs and shared headers used by regulator drivers and DTS are not listed as files for the regulator subsystem. So developers may not know who should receive patches to these dirs unless they rely on the get_maintainer.pl git-fallback option which usually makes more harm than good. This patch makes the correct recipient to be obtained using commands such as scripts/get_maintainer.pl --no-git-fallback. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a915a32be22b..a5d706699e8a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11778,7 +11778,9 @@ L: linux-kernel@vger.kernel.org W: http://www.slimlogic.co.uk/?p=48 T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git S: Supported +F: Documentation/devicetree/bindings/regulator/ F: drivers/regulator/ +F: include/dt-bindings/regulator/ F: include/linux/regulator/ VRF -- GitLab From 9a6f2b0113c8fce815db7c9d23754bdea4b428a0 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 11 Apr 2016 21:40:05 +0200 Subject: [PATCH 2122/9938] net: mdio: Fix lockdep falls positive splat MDIO devices can be stacked upon each other. The current code supports two levels, which until recently has been enough for a DSA mdio bus on top of another bus. Now we have hardware which has an MDIO mux in the middle. Define an MDIO MUTEX class with three levels. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux.c | 10 ++-------- drivers/net/phy/mdio_bus.c | 4 ++-- include/linux/mdio.h | 11 +++++++++++ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 308ade0eb1b6..5c81d6faf304 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -45,13 +45,7 @@ static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum) struct mdio_mux_parent_bus *pb = cb->parent; int r; - /* In theory multiple mdio_mux could be stacked, thus creating - * more than a single level of nesting. But in practice, - * SINGLE_DEPTH_NESTING will cover the vast majority of use - * cases. We use it, instead of trying to handle the general - * case. - */ - mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING); + mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX); r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); if (r) goto out; @@ -76,7 +70,7 @@ static int mdio_mux_write(struct mii_bus *bus, int phy_id, int r; - mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING); + mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX); r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); if (r) goto out; diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 0cba64f1ecf4..751202a285a6 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -457,7 +457,7 @@ int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum) BUG_ON(in_interrupt()); - mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); retval = bus->read(bus, addr, regnum); mutex_unlock(&bus->mdio_lock); @@ -509,7 +509,7 @@ int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val) BUG_ON(in_interrupt()); - mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); err = bus->write(bus, addr, regnum, val); mutex_unlock(&bus->mdio_lock); diff --git a/include/linux/mdio.h b/include/linux/mdio.h index 5bfd99d1a40a..bf9d1d750693 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -13,6 +13,17 @@ struct mii_bus; +/* Multiple levels of nesting are possible. However typically this is + * limited to nested DSA like layer, a MUX layer, and the normal + * user. Instead of trying to handle the general case, just define + * these cases. + */ +enum mdio_mutex_lock_class { + MDIO_MUTEX_NORMAL, + MDIO_MUTEX_MUX, + MDIO_MUTEX_NESTED, +}; + struct mdio_device { struct device dev; -- GitLab From d78885739a7df111dc7b081f8a09e08a5fcfecc2 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 8 Apr 2016 15:07:24 +0000 Subject: [PATCH 2123/9938] perf bpf: Clone bpf stdout events in multiple bpf scripts This patch allows cloning bpf-output event configuration among multiple bpf scripts. If there exist a map named '__bpf_output__' and not configured using 'map:__bpf_output__.event=', this patch clones the configuration of another '__bpf_stdout__' map. For example, following command: # perf trace --ev bpf-output/no-inherit,name=evt/ \ --ev ./test_bpf_trace.c/map:__bpf_stdout__.event=evt/ \ --ev ./test_bpf_trace2.c usleep 100000 equals to: # perf trace --ev bpf-output/no-inherit,name=evt/ \ --ev ./test_bpf_trace.c/map:__bpf_stdout__.event=evt/ \ --ev ./test_bpf_trace2.c/map:__bpf_stdout__.event=evt/ \ usleep 100000 Signed-off-by: Wang Nan Suggested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460128045-97310-4-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 8 +++ tools/perf/builtin-trace.c | 7 ++ tools/perf/util/bpf-loader.c | 124 +++++++++++++++++++++++++++++++++++ tools/perf/util/bpf-loader.h | 19 ++++++ 4 files changed, 158 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 410035c6e300..e64bd1ee5acb 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1276,6 +1276,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) if (err) return err; + err = bpf__setup_stdout(rec->evlist); + if (err) { + bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); + pr_err("ERROR: Setup BPF stdout failed: %s\n", + errbuf); + return err; + } + err = -ENOMEM; symbol__init(NULL); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 11290b57ce04..27d987030627 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3273,6 +3273,13 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands, trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); + err = bpf__setup_stdout(trace.evlist); + if (err) { + bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf)); + pr_err("ERROR: Setup BPF stdout failed: %s\n", bf); + goto out; + } + if (trace.trace_pgfaults) { trace.opts.sample_address = true; trace.opts.sample_time = true; diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 0967ce601931..67f61a902a08 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -842,6 +842,58 @@ bpf_map_op__new(struct parse_events_term *term) return op; } +static struct bpf_map_op * +bpf_map_op__clone(struct bpf_map_op *op) +{ + struct bpf_map_op *newop; + + newop = memdup(op, sizeof(*op)); + if (!newop) { + pr_debug("Failed to alloc bpf_map_op\n"); + return NULL; + } + + INIT_LIST_HEAD(&newop->list); + if (op->key_type == BPF_MAP_KEY_RANGES) { + size_t memsz = op->k.array.nr_ranges * + sizeof(op->k.array.ranges[0]); + + newop->k.array.ranges = memdup(op->k.array.ranges, memsz); + if (!newop->k.array.ranges) { + pr_debug("Failed to alloc indices for map\n"); + free(newop); + return NULL; + } + } + + return newop; +} + +static struct bpf_map_priv * +bpf_map_priv__clone(struct bpf_map_priv *priv) +{ + struct bpf_map_priv *newpriv; + struct bpf_map_op *pos, *newop; + + newpriv = zalloc(sizeof(*newpriv)); + if (!newpriv) { + pr_debug("No enough memory to alloc map private\n"); + return NULL; + } + INIT_LIST_HEAD(&newpriv->ops_list); + + list_for_each_entry(pos, &priv->ops_list, list) { + newop = bpf_map_op__clone(pos); + if (!newop) { + bpf_map_priv__purge(newpriv); + return NULL; + } + list_add_tail(&newop->list, &newpriv->ops_list); + } + + return newpriv; +} + static int bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) { @@ -1417,6 +1469,70 @@ int bpf__apply_obj_config(void) return 0; } +#define bpf__for_each_map(pos, obj, objtmp) \ + bpf_object__for_each_safe(obj, objtmp) \ + bpf_map__for_each(pos, obj) + +#define bpf__for_each_stdout_map(pos, obj, objtmp) \ + bpf__for_each_map(pos, obj, objtmp) \ + if (bpf_map__get_name(pos) && \ + (strcmp("__bpf_stdout__", \ + bpf_map__get_name(pos)) == 0)) + +int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) +{ + struct bpf_map_priv *tmpl_priv = NULL; + struct bpf_object *obj, *tmp; + struct bpf_map *map; + int err; + bool need_init = false; + + bpf__for_each_stdout_map(map, obj, tmp) { + struct bpf_map_priv *priv; + + err = bpf_map__get_private(map, (void **)&priv); + if (err) + return -BPF_LOADER_ERRNO__INTERNAL; + + /* + * No need to check map type: type should have been + * verified by kernel. + */ + if (!need_init && !priv) + need_init = !priv; + if (!tmpl_priv && priv) + tmpl_priv = priv; + } + + if (!need_init) + return 0; + + if (!tmpl_priv) + return 0; + + bpf__for_each_stdout_map(map, obj, tmp) { + struct bpf_map_priv *priv; + + err = bpf_map__get_private(map, (void **)&priv); + if (err) + return -BPF_LOADER_ERRNO__INTERNAL; + if (priv) + continue; + + priv = bpf_map_priv__clone(tmpl_priv); + if (!priv) + return -ENOMEM; + + err = bpf_map__set_private(map, priv, bpf_map_priv__clear); + if (err) { + bpf_map_priv__clear(map, priv); + return err; + } + } + + return 0; +} + #define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) #define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c) #define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START) @@ -1590,3 +1706,11 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size) bpf__strerror_end(buf, size); return 0; } + +int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused, + int err, char *buf, size_t size) +{ + bpf__strerror_head(err, buf, size); + bpf__strerror_end(buf, size); + return 0; +} diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h index be4311944e3d..941e17275aa7 100644 --- a/tools/perf/util/bpf-loader.h +++ b/tools/perf/util/bpf-loader.h @@ -79,6 +79,11 @@ int bpf__strerror_config_obj(struct bpf_object *obj, size_t size); int bpf__apply_obj_config(void); int bpf__strerror_apply_obj_config(int err, char *buf, size_t size); + +int bpf__setup_stdout(struct perf_evlist *evlist); +int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, + char *buf, size_t size); + #else static inline struct bpf_object * bpf__prepare_load(const char *filename __maybe_unused, @@ -124,6 +129,12 @@ bpf__apply_obj_config(void) return 0; } +static inline int +bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) +{ + return 0; +} + static inline int __bpf_strerror(char *buf, size_t size) { @@ -177,5 +188,13 @@ bpf__strerror_apply_obj_config(int err __maybe_unused, { return __bpf_strerror(buf, size); } + +static inline int +bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused, + int err __maybe_unused, char *buf, + size_t size) +{ + return __bpf_strerror(buf, size); +} #endif #endif -- GitLab From 72c0809856b9174e71eab4e293089f6a114e0d41 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 8 Apr 2016 15:07:25 +0000 Subject: [PATCH 2124/9938] perf bpf: Automatically create bpf-output event __bpf_stdout__ This patch removes the need to set a bpf-output event in cmdline. By referencing a map named '__bpf_stdout__', perf automatically creates an event for it. For example: # perf record -e ./test_bpf_trace.c usleep 100000 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (2 samples) ] # perf script usleep 4639 [000] 261895.307826: 0 __bpf_stdout__: ffffffff810eb9a1 ... BPF output: 0000: 52 61 69 73 65 20 61 20 Raise a 0008: 42 50 46 20 65 76 65 6e BPF even 0010: 74 21 00 00 t!.. BPF string: "Raise a BPF event!" usleep 4639 [000] 261895.407883: 0 __bpf_stdout__: ffffffff8105d609 ... BPF output: 0000: 52 61 69 73 65 20 61 20 Raise a 0008: 42 50 46 20 65 76 65 6e BPF even 0010: 74 21 00 00 t!.. BPF string: "Raise a BPF event!" perf record -e ./test_bpf_trace.c usleep 100000 equals to: perf record -e bpf-output/no-inherit=1,name=__bpf_stdout__/ \ -e ./test_bpf_trace.c/map:__bpf_stdout__.event=__bpf_stdout__/ \ usleep 100000 Where test_bpf_trace.c is: /************************ BEGIN **************************/ #include struct bpf_map_def { unsigned int type; unsigned int key_size; unsigned int value_size; unsigned int max_entries; }; #define SEC(NAME) __attribute__((section(NAME), used)) static u64 (*ktime_get_ns)(void) = (void *)BPF_FUNC_ktime_get_ns; static int (*trace_printk)(const char *fmt, int fmt_size, ...) = (void *)BPF_FUNC_trace_printk; static int (*get_smp_processor_id)(void) = (void *)BPF_FUNC_get_smp_processor_id; static int (*perf_event_output)(void *, struct bpf_map_def *, int, void *, unsigned long) = (void *)BPF_FUNC_perf_event_output; struct bpf_map_def SEC("maps") __bpf_stdout__ = { .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, .key_size = sizeof(int), .value_size = sizeof(u32), .max_entries = __NR_CPUS__, }; static inline int __attribute__((always_inline)) func(void *ctx, int type) { char output_str[] = "Raise a BPF event!"; char err_str[] = "BAD %d\n"; int err; err = perf_event_output(ctx, &__bpf_stdout__, get_smp_processor_id(), &output_str, sizeof(output_str)); if (err) trace_printk(err_str, sizeof(err_str), err); return 1; } SEC("func_begin=sys_nanosleep") int func_begin(void *ctx) {return func(ctx, 1);} SEC("func_end=sys_nanosleep%return") int func_end(void *ctx) { return func(ctx, 2);} char _license[] SEC("license") = "GPL"; int _version SEC("version") = LINUX_VERSION_CODE; /************************* END ***************************/ Committer note: Testing with 'perf trace': # trace -e nanosleep --ev test_bpf_stdout.c usleep 1 0.007 ( 0.007 ms): usleep/729 nanosleep(rqtp: 0x7ffc5bbc5fe0) ... 0.007 ( ): __bpf_stdout__:Raise a BPF event!..) 0.008 ( ): perf_bpf_probe:func_begin:(ffffffff81112460)) 0.069 ( ): __bpf_stdout__:Raise a BPF event!..) 0.070 ( ): perf_bpf_probe:func_end:(ffffffff81112460 <- ffffffff81003d92)) 0.072 ( 0.072 ms): usleep/729 ... [continued]: nanosleep()) = 0 # Suggested-and-Tested-by: Arnaldo Carvalho de Melo Signed-off-by: Wang Nan Cc: Jiri Olsa Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460128045-97310-5-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-loader.c | 37 +++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 67f61a902a08..493307d1414c 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -1483,6 +1483,7 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) { struct bpf_map_priv *tmpl_priv = NULL; struct bpf_object *obj, *tmp; + struct perf_evsel *evsel = NULL; struct bpf_map *map; int err; bool need_init = false; @@ -1507,8 +1508,16 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) if (!need_init) return 0; - if (!tmpl_priv) - return 0; + if (!tmpl_priv) { + err = parse_events(evlist, "bpf-output/no-inherit=1,name=__bpf_stdout__/", + NULL); + if (err) { + pr_debug("ERROR: failed to create bpf-output event\n"); + return -err; + } + + evsel = perf_evlist__last(evlist); + } bpf__for_each_stdout_map(map, obj, tmp) { struct bpf_map_priv *priv; @@ -1519,14 +1528,24 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) if (priv) continue; - priv = bpf_map_priv__clone(tmpl_priv); - if (!priv) - return -ENOMEM; + if (tmpl_priv) { + priv = bpf_map_priv__clone(tmpl_priv); + if (!priv) + return -ENOMEM; - err = bpf_map__set_private(map, priv, bpf_map_priv__clear); - if (err) { - bpf_map_priv__clear(map, priv); - return err; + err = bpf_map__set_private(map, priv, bpf_map_priv__clear); + if (err) { + bpf_map_priv__clear(map, priv); + return err; + } + } else if (evsel) { + struct bpf_map_op *op; + + op = bpf_map__add_newop(map, NULL); + if (IS_ERR(op)) + return PTR_ERR(op); + op->op_type = BPF_MAP_OP_SET_EVSEL; + op->v.evsel = evsel; } } -- GitLab From 6186de9a491af030889b372193fc9f38c248e69a Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Mon, 11 Apr 2016 10:18:11 -0300 Subject: [PATCH 2125/9938] perf evsel: Allow specifying a file to output in perf_evsel__print_ip As this function will be used in 'perf trace'. Cc: Jiri Olsa Link: http://lkml.kernel.org/n/tip-8x297v9utnxq77onikevvlse@git.kernel.org [ Split from a larger patch ] Signed-off-by: Milian Wolff --- tools/perf/builtin-script.c | 4 ++-- tools/perf/util/session.c | 39 ++++++++++++++++++++----------------- tools/perf/util/session.h | 3 ++- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 8f6ab2ac855a..dbf208f0cdc2 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -580,7 +580,7 @@ static void print_sample_bts(struct perf_sample *sample, } } perf_evsel__print_ip(evsel, sample, al, print_opts, - scripting_max_stack); + scripting_max_stack, stdout); } /* print branch_to information */ @@ -790,7 +790,7 @@ static void process_event(struct perf_script *script, perf_evsel__print_ip(evsel, sample, al, output[attr->type].print_ip_opts, - scripting_max_stack); + scripting_max_stack, stdout); } if (PRINT_FIELD(IREGS)) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ef370557fb9a..bbac0efbc10c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1955,7 +1955,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, - unsigned int print_opts, unsigned int stack_depth) + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) { struct callchain_cursor_node *node; int print_ip = print_opts & PRINT_IP_OPT_IP; @@ -1992,33 +1993,35 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, goto next; if (print_ip) - printf("%c%16" PRIx64, s, node->ip); + fprintf(fp, "%c%16" PRIx64, s, node->ip); if (node->map) addr = node->map->map_ip(node->map, node->ip); if (print_sym) { - printf(" "); + fprintf(fp, " "); if (print_symoffset) { node_al.addr = addr; node_al.map = node->map; - symbol__fprintf_symname_offs(node->sym, &node_al, stdout); + symbol__fprintf_symname_offs(node->sym, + &node_al, + fp); } else - symbol__fprintf_symname(node->sym, stdout); + symbol__fprintf_symname(node->sym, fp); } if (print_dso) { - printf(" ("); - map__fprintf_dsoname(node->map, stdout); - printf(")"); + fprintf(fp, " ("); + map__fprintf_dsoname(node->map, fp); + fprintf(fp, ")"); } if (print_srcline) map__fprintf_srcline(node->map, addr, "\n ", - stdout); + fp); if (!print_oneline) - printf("\n"); + fprintf(fp, "\n"); stack_depth--; next: @@ -2030,25 +2033,25 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, return; if (print_ip) - printf("%16" PRIx64, sample->ip); + fprintf(fp, "%16" PRIx64, sample->ip); if (print_sym) { - printf(" "); + fprintf(fp, " "); if (print_symoffset) symbol__fprintf_symname_offs(al->sym, al, - stdout); + fp); else - symbol__fprintf_symname(al->sym, stdout); + symbol__fprintf_symname(al->sym, fp); } if (print_dso) { - printf(" ("); - map__fprintf_dsoname(al->map, stdout); - printf(")"); + fprintf(fp, " ("); + map__fprintf_dsoname(al->map, fp); + fprintf(fp, ")"); } if (print_srcline) - map__fprintf_srcline(al->map, al->addr, "\n ", stdout); + map__fprintf_srcline(al->map, al->addr, "\n ", fp); } } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index f96fc9e8c52e..0ee3d9dbc099 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -106,7 +106,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, - unsigned int print_opts, unsigned int stack_depth); + unsigned int print_opts, unsigned int stack_depth, + FILE *fp); int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap); -- GitLab From db3617f362d7e205621c1ccc22b77d224a81ee14 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 10:53:51 -0300 Subject: [PATCH 2126/9938] perf evsel: Allow passing a left alignment when printing a symbol For callchains, etc where we want it to align just below the syscall name, for instance, in 'perf trace' Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-uk9ekchd67651c625ltaur5y@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 4 ++-- tools/perf/util/session.c | 6 +++++- tools/perf/util/session.h | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index dbf208f0cdc2..60fde9f5025c 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -579,7 +579,7 @@ static void print_sample_bts(struct perf_sample *sample, print_opts &= ~PRINT_IP_OPT_SRCLINE; } } - perf_evsel__print_ip(evsel, sample, al, print_opts, + perf_evsel__print_ip(evsel, sample, al, 0, print_opts, scripting_max_stack, stdout); } @@ -788,7 +788,7 @@ static void process_event(struct perf_script *script, else printf("\n"); - perf_evsel__print_ip(evsel, sample, al, + perf_evsel__print_ip(evsel, sample, al, 0, output[attr->type].print_ip_opts, scripting_max_stack, stdout); } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index bbac0efbc10c..62b6d4051b99 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1954,7 +1954,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, } void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, + struct addr_location *al, int left_alignment, unsigned int print_opts, unsigned int stack_depth, FILE *fp) { @@ -1992,6 +1992,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, if (node->sym && node->sym->ignore) goto next; + fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + if (print_ip) fprintf(fp, "%c%16" PRIx64, s, node->ip); @@ -2032,6 +2034,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, if (al->sym && al->sym->ignore) return; + fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + if (print_ip) fprintf(fp, "%16" PRIx64, sample->ip); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 0ee3d9dbc099..a6bc4ddbae3e 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -105,7 +105,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, + struct addr_location *al, int left_alignment, unsigned int print_opts, unsigned int stack_depth, FILE *fp); -- GitLab From 566a08859f63a33746e25246c5cda0f52528d2e4 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Fri, 8 Apr 2016 13:34:15 +0200 Subject: [PATCH 2127/9938] perf trace: Add support for printing call chains on sys_exit events. Now, one can print the call chain for every encountered sys_exit event, e.g.: $ perf trace -e nanosleep --call-graph dwarf path/to/ex_sleep 1005.757 (1000.090 ms): ex_sleep/13167 nanosleep(...) = 0 syscall_slow_exit_work ([kernel.kallsyms]) syscall_return_slowpath ([kernel.kallsyms]) int_ret_from_sys_call ([kernel.kallsyms]) __nanosleep (/usr/lib/libc-2.23.so) [unknown] (/usr/lib/libQt5Core.so.5.6.0) QThread::sleep (/usr/lib/libQt5Core.so.5.6.0) main (path/to/ex_sleep) __libc_start_main (/usr/lib/libc-2.23.so) _start (path/to/ex_sleep) Note that it is advised to increase the number of mmap pages to prevent event losses when using this new feature. Often, adding `-m 10M` to the `perf trace` invocation is enough. This feature is also available in strace when built with libunwind via `strace -k`. Performance wise, this solution is much better: $ time find path/to/linux &> /dev/null real 0m0.051s user 0m0.013s sys 0m0.037s $ time perf trace -m 800M --call-graph dwarf find path/to/linux &> /dev/null real 0m2.624s user 0m1.203s sys 0m1.333s $ time strace -k find path/to/linux &> /dev/null real 0m35.398s user 0m10.403s sys 0m23.173s Note that it is currently not possible to configure the print output. Adding such a feature, similar to what is available in `perf script` via its `--fields` knob can be added later on. Signed-off-by: Milian Wolff Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan LPU-Reference: 1460115255-17648-1-git-send-email-milian.wolff@kdab.com [ Split from a larger patch, do not print the IP, left align, remove dup call symbol__init(), added man page entry ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 6 ++++++ tools/perf/builtin-trace.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 13293de8869f..ed485df16409 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -117,6 +117,12 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. --syscalls:: Trace system calls. This options is enabled by default. +--call-graph [mode,type,min[,limit],order[,key][,branch]]:: + Setup and enable call-graph (stack chain/backtrace) recording. + See `--call-graph` section in perf-record and perf-report + man pages for details. The ones that are most useful in 'perf trace' + are 'dwarf' and 'lbr', where available, try: 'perf trace --call-graph dwarf'. + --event:: Trace other events, see 'perf list' for a complete list. diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 27d987030627..8c587a8d3742 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -34,6 +34,7 @@ #include "trace-event.h" #include "util/parse-events.h" #include "util/bpf-loader.h" +#include "callchain.h" #include "syscalltbl.h" #include /* FIXME: Still needed for audit_errno_to_name */ @@ -2190,6 +2191,21 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, goto signed_print; fputc('\n', trace->output); + + if (sample->callchain) { + struct addr_location al; + /* TODO: user-configurable print_opts */ + const unsigned int print_opts = PRINT_IP_OPT_SYM + | PRINT_IP_OPT_DSO; + + if (machine__resolve(trace->host, &al, sample) < 0) { + pr_err("problem processing %d event, skipping it.\n", + event->header.type); + goto out_put; + } + perf_evsel__print_ip(evsel, sample, &al, 38, print_opts, + scripting_max_stack, trace->output); + } out: ttrace->entry_pending = false; err = 0; @@ -3250,6 +3266,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) "Trace pagefaults", parse_pagefaults, "maj"), OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"), + OPT_CALLBACK(0, "call-graph", &trace.opts, + "record_mode[,record_size]", record_callchain_help, + &record_parse_callchain_opt), OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, "per thread proc mmap processing timeout in ms"), OPT_END() @@ -3285,6 +3304,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) trace.opts.sample_time = true; } + if (trace.opts.callgraph_set) + symbol_conf.use_callchain = true; + if (trace.evlist->nr_entries > 0) evlist__set_evsel_handler(trace.evlist, trace__event_handler); -- GitLab From ff0c107806cf9d237e50e21de66d6909391071cd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 11:14:06 -0300 Subject: [PATCH 2128/9938] perf evsel: Rename print_ip() to fprintf_sym() As it receives a FILE, and its more than just the IP, which can even be requested not to be printed. For consistency with other similar methods in tools/perf/, name it as perf_evsel__fprintf_sym() and make it return the number of bytes printed, just like 'fprintf(3)' Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-84gawlqa3lhk63nf0t9vnqnn@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 10 +++---- tools/perf/builtin-trace.c | 4 +-- tools/perf/util/session.c | 60 +++++++++++++++++-------------------- tools/perf/util/session.h | 8 ++--- 4 files changed, 39 insertions(+), 43 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 60fde9f5025c..ddd5b79e94c2 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -579,8 +579,8 @@ static void print_sample_bts(struct perf_sample *sample, print_opts &= ~PRINT_IP_OPT_SRCLINE; } } - perf_evsel__print_ip(evsel, sample, al, 0, print_opts, - scripting_max_stack, stdout); + perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts, + scripting_max_stack, stdout); } /* print branch_to information */ @@ -788,9 +788,9 @@ static void process_event(struct perf_script *script, else printf("\n"); - perf_evsel__print_ip(evsel, sample, al, 0, - output[attr->type].print_ip_opts, - scripting_max_stack, stdout); + perf_evsel__fprintf_sym(evsel, sample, al, 0, + output[attr->type].print_ip_opts, + scripting_max_stack, stdout); } if (PRINT_FIELD(IREGS)) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8c587a8d3742..a0d5c680c39e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2203,8 +2203,8 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, event->header.type); goto out_put; } - perf_evsel__print_ip(evsel, sample, &al, 38, print_opts, - scripting_max_stack, trace->output); + perf_evsel__fprintf_sym(evsel, sample, &al, 38, print_opts, + scripting_max_stack, trace->output); } out: ttrace->entry_pending = false; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 62b6d4051b99..0669a088ea0d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1953,11 +1953,12 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, return NULL; } -void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) +int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) { + int printed = 0; struct callchain_cursor_node *node; int print_ip = print_opts & PRINT_IP_OPT_IP; int print_sym = print_opts & PRINT_IP_OPT_SYM; @@ -1975,7 +1976,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, stack_depth) != 0) { if (verbose) error("Failed to resolve callchain. Skipping\n"); - return; + return printed; } callchain_cursor_commit(&callchain_cursor); @@ -1992,71 +1993,66 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, if (node->sym && node->sym->ignore) goto next; - fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); if (print_ip) - fprintf(fp, "%c%16" PRIx64, s, node->ip); + printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); if (node->map) addr = node->map->map_ip(node->map, node->ip); if (print_sym) { - fprintf(fp, " "); + printed += fprintf(fp, " "); if (print_symoffset) { node_al.addr = addr; node_al.map = node->map; - symbol__fprintf_symname_offs(node->sym, - &node_al, - fp); + printed += symbol__fprintf_symname_offs(node->sym, &node_al, fp); } else - symbol__fprintf_symname(node->sym, fp); + printed += symbol__fprintf_symname(node->sym, fp); } if (print_dso) { - fprintf(fp, " ("); - map__fprintf_dsoname(node->map, fp); - fprintf(fp, ")"); + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(node->map, fp); + printed += fprintf(fp, ")"); } if (print_srcline) - map__fprintf_srcline(node->map, addr, "\n ", - fp); + printed += map__fprintf_srcline(node->map, addr, "\n ", fp); if (!print_oneline) - fprintf(fp, "\n"); + printed += fprintf(fp, "\n"); stack_depth--; next: callchain_cursor_advance(&callchain_cursor); } - } else { - if (al->sym && al->sym->ignore) - return; - - fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + } else if (!(al->sym && al->sym->ignore)) { + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); if (print_ip) - fprintf(fp, "%16" PRIx64, sample->ip); + printed += fprintf(fp, "%16" PRIx64, sample->ip); if (print_sym) { - fprintf(fp, " "); + printed += fprintf(fp, " "); if (print_symoffset) - symbol__fprintf_symname_offs(al->sym, al, - fp); + printed += symbol__fprintf_symname_offs(al->sym, al, fp); else - symbol__fprintf_symname(al->sym, fp); + printed += symbol__fprintf_symname(al->sym, fp); } if (print_dso) { - fprintf(fp, " ("); - map__fprintf_dsoname(al->map, fp); - fprintf(fp, ")"); + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(al->map, fp); + printed += fprintf(fp, ")"); } if (print_srcline) - map__fprintf_srcline(al->map, al->addr, "\n ", fp); + printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); } + + return printed; } int perf_session__cpu_bitmap(struct perf_session *session, diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index a6bc4ddbae3e..ac834908bb35 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -104,10 +104,10 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); -void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp); +int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp); int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap); -- GitLab From ea4539652eccc87b14fbcbc90467ebcb87f02ddb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 12:15:48 -0300 Subject: [PATCH 2129/9938] perf evsel: Introduce fprintf_callchain() method out of fprintf_sym() In 'perf trace' we're just interested in printing callchains, and we don't want to use the symbol_conf.use_callchain, so move the callchain part to a new method. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-kcn3romzivcpxb3u75s9nz33@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++-- tools/perf/util/evsel.h | 6 ++++++ tools/perf/util/session.c | 29 ++++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a0d5c680c39e..63a3cc9b717c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2203,8 +2203,8 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, event->header.type); goto out_put; } - perf_evsel__fprintf_sym(evsel, sample, &al, 38, print_opts, - scripting_max_stack, trace->output); + perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts, + scripting_max_stack, trace->output); } out: ttrace->entry_pending = false; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 501ea6e565f1..ab3632caba9f 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -381,6 +381,12 @@ struct perf_attr_details { int perf_evsel__fprintf(struct perf_evsel *evsel, struct perf_attr_details *details, FILE *fp); +int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, + struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, + unsigned int stack_depth, FILE *fp); + bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0669a088ea0d..e384b651a3e8 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1953,10 +1953,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, return NULL; } -int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) +int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) { int printed = 0; struct callchain_cursor_node *node; @@ -1968,7 +1968,7 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; char s = print_oneline ? ' ' : '\t'; - if (symbol_conf.use_callchain && sample->callchain) { + if (sample->callchain) { struct addr_location node_al; if (thread__resolve_callchain(al->thread, evsel, @@ -2027,7 +2027,26 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample next: callchain_cursor_advance(&callchain_cursor); } + } + + return printed; +} + +int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) +{ + int printed = 0; + int print_ip = print_opts & PRINT_IP_OPT_IP; + int print_sym = print_opts & PRINT_IP_OPT_SYM; + int print_dso = print_opts & PRINT_IP_OPT_DSO; + int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; + int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; + if (symbol_conf.use_callchain && sample->callchain) { + printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, + print_opts, stack_depth, fp); } else if (!(al->sym && al->sym->ignore)) { printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); -- GitLab From 44621819ddc9d5d0bfd0b0616c6cf33c94189b67 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 15:49:11 -0300 Subject: [PATCH 2130/9938] perf trace: Exclude the kernel part of the callchain leading to a syscall The kernel parts are not that useful: # trace -m 512 -e nanosleep --call dwarf usleep 1 0.065 ( 0.065 ms): usleep/18732 nanosleep(rqtp: 0x7ffc4ee4e200) = 0 syscall_slow_exit_work ([kernel.kallsyms]) do_syscall_64 ([kernel.kallsyms]) return_from_SYSCALL_64 ([kernel.kallsyms]) __nanosleep (/usr/lib64/libc-2.22.so) usleep (/usr/lib64/libc-2.22.so) main (/usr/bin/usleep) __libc_start_main (/usr/lib64/libc-2.22.so) _start (/usr/bin/usleep) # So lets just use perf_event_attr.exclude_callchain_kernel to avoid collecting it in the ring buffer: # trace -m 512 -e nanosleep --call dwarf usleep 1 0.063 ( 0.063 ms): usleep/19212 nanosleep(rqtp: 0x7ffc3df10fb0) = 0 __nanosleep (/usr/lib64/libc-2.22.so) usleep (/usr/lib64/libc-2.22.so) main (/usr/bin/usleep) __libc_start_main (/usr/lib64/libc-2.22.so) _start (/usr/bin/usleep) # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-qctu3gqhpim0dfbcp9d86c91@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 3 +++ tools/perf/builtin-trace.c | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index ed485df16409..1bbcf305d233 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -123,6 +123,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. man pages for details. The ones that are most useful in 'perf trace' are 'dwarf' and 'lbr', where available, try: 'perf trace --call-graph dwarf'. +--kernel-syscall-graph:: + Show the kernel callchains on the syscall exit path. + --event:: Trace other events, see 'perf list' for a complete list. diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 63a3cc9b717c..cfa5ce8fdb7b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -159,6 +159,7 @@ struct trace { bool show_comm; bool show_tool_stats; bool trace_syscalls; + bool kernel_syscallchains; bool force; bool vfs_getname; int trace_pgfaults; @@ -2661,6 +2662,15 @@ static int trace__add_syscall_newtp(struct trace *trace) perf_evlist__add(evlist, sys_enter); perf_evlist__add(evlist, sys_exit); + if (trace->opts.callgraph_set && !trace->kernel_syscallchains) { + /* + * We're interested only in the user space callchain + * leading to the syscall, allow overriding that for + * debugging reasons using --kernel_syscall_callchains + */ + sys_exit->attr.exclude_callchain_kernel = 1; + } + trace->syscalls.events.sys_enter = sys_enter; trace->syscalls.events.sys_exit = sys_exit; @@ -3221,6 +3231,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) .output = stderr, .show_comm = true, .trace_syscalls = true, + .kernel_syscallchains = false, }; const char *output_name = NULL; const char *ev_qualifier_str = NULL; @@ -3269,6 +3280,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) OPT_CALLBACK(0, "call-graph", &trace.opts, "record_mode[,record_size]", record_callchain_help, &record_parse_callchain_opt), + OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, + "Show the kernel callchains on the syscall exit path"), OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, "per thread proc mmap processing timeout in ms"), OPT_END() -- GitLab From e68ae9cf7d734e669bc0a981b4154f70d29b5059 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 18:15:29 -0300 Subject: [PATCH 2131/9938] perf evsel: Do not use globals in config() Instead receive a callchain_param pointer to configure callchain aspects, not doing so if NULL is passed. This will allow fine grained control over which evsels in an evlist gets callchains enabled. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-2mupip6khc92mh5x4nw9to82@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/bpf.c | 2 +- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/perf-record.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/util/evlist.h | 5 ++++- tools/perf/util/evsel.c | 7 ++++--- tools/perf/util/evsel.h | 5 ++++- tools/perf/util/record.c | 5 +++-- 15 files changed, 26 insertions(+), 18 deletions(-) diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 9d29ee283ac5..d4aa567a29c4 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c @@ -71,7 +71,7 @@ int test__perf_time_to_tsc(int subtest __maybe_unused) CHECK__(parse_events(evlist, "cycles:u", NULL)); - perf_evlist__config(evlist, &opts); + perf_evlist__config(evlist, &opts, NULL); evsel = perf_evlist__first(evlist); diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index bff666458b28..6487c06d2708 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -982,7 +982,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) struct perf_evlist *evlist = kvm->evlist; char sbuf[STRERR_BUFSIZE]; - perf_evlist__config(evlist, &kvm->opts); + perf_evlist__config(evlist, &kvm->opts, NULL); /* * Note: exclude_{guest,host} do not apply here. diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e64bd1ee5acb..eb6a199a833c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -284,7 +284,7 @@ static int record__open(struct record *rec) struct record_opts *opts = &rec->opts; int rc = 0; - perf_evlist__config(evlist, opts); + perf_evlist__config(evlist, opts, &callchain_param); evlist__for_each(evlist, pos) { try_again: diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 833214979c4f..8846df0ec0c3 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -886,7 +886,7 @@ static int perf_top__start_counters(struct perf_top *top) struct perf_evlist *evlist = top->evlist; struct record_opts *opts = &top->record_opts; - perf_evlist__config(evlist, opts); + perf_evlist__config(evlist, opts, &callchain_param); evlist__for_each(evlist, counter) { try_again: diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index cfa5ce8fdb7b..08fb100b91fa 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2749,7 +2749,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_delete_evlist; } - perf_evlist__config(evlist, &trace->opts); + perf_evlist__config(evlist, &trace->opts, &callchain_param); signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index 199501c71e27..f31eed31c1a9 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -138,7 +138,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), perf_evlist__splice_list_tail(evlist, &parse_evlist.list); evlist->nr_groups = parse_evlist.nr_groups; - perf_evlist__config(evlist, &opts); + perf_evlist__config(evlist, &opts, NULL); err = perf_evlist__open(evlist); if (err < 0) { diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index abd3f0ec0c0b..68a69a195545 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -532,7 +532,7 @@ static int do_test_code_reading(bool try_kcore) goto out_put; } - perf_evlist__config(evlist, &opts); + perf_evlist__config(evlist, &opts, NULL); evsel = perf_evlist__first(evlist); diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index ddb78fae064a..614e45a3c603 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -80,7 +80,7 @@ int test__keep_tracking(int subtest __maybe_unused) CHECK__(parse_events(evlist, "dummy:u", NULL)); CHECK__(parse_events(evlist, "cycles:u", NULL)); - perf_evlist__config(evlist, &opts); + perf_evlist__config(evlist, &opts, NULL); evsel = perf_evlist__first(evlist); diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index eb99a105f31c..4344fe482c1d 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -44,7 +44,7 @@ int test__syscall_openat_tp_fields(int subtest __maybe_unused) goto out_delete_evlist; } - perf_evsel__config(evsel, &opts); + perf_evsel__config(evsel, &opts, NULL); thread_map__set_pid(evlist->threads, 0, getpid()); diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 1cc78cefe399..b836ee6a8d9b 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -99,7 +99,7 @@ int test__PERF_RECORD(int subtest __maybe_unused) perf_evsel__set_sample_bit(evsel, CPU); perf_evsel__set_sample_bit(evsel, TID); perf_evsel__set_sample_bit(evsel, TIME); - perf_evlist__config(evlist, &opts); + perf_evlist__config(evlist, &opts, NULL); err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); if (err < 0) { diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index ebd80168d51e..39a689bf7574 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -417,7 +417,7 @@ int test__switch_tracking(int subtest __maybe_unused) perf_evsel__set_sample_bit(tracking_evsel, TIME); /* Config events */ - perf_evlist__config(evlist, &opts); + perf_evlist__config(evlist, &opts, NULL); /* Check moved event is still at the front */ if (cycles_evsel != perf_evlist__first(evlist)) { diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a0d15221db6e..8db9228663d6 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -123,11 +123,14 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); int perf_evlist__open(struct perf_evlist *evlist); void perf_evlist__close(struct perf_evlist *evlist); +struct callchain_param; + void perf_evlist__set_id_pos(struct perf_evlist *evlist); bool perf_can_sample_identifier(void); bool perf_can_record_switch_events(void); bool perf_can_record_cpu_wide(void); -void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts); +void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, + struct callchain_param *callchain); int record_opts__config(struct record_opts *opts); int perf_evlist__prepare_workload(struct perf_evlist *evlist, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3fd7c2c72f4a..84252729222d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -737,7 +737,8 @@ static void apply_config_terms(struct perf_evsel *evsel, * enable/disable events specifically, as there's no * initial traced exec call. */ -void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) +void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, + struct callchain_param *callchain) { struct perf_evsel *leader = evsel->leader; struct perf_event_attr *attr = &evsel->attr; @@ -812,8 +813,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) if (perf_evsel__is_function_event(evsel)) evsel->attr.exclude_callchain_user = 1; - if (callchain_param.enabled && !evsel->no_aux_samples) - perf_evsel__config_callgraph(evsel, opts, &callchain_param); + if (callchain && callchain->enabled && !evsel->no_aux_samples) + perf_evsel__config_callgraph(evsel, opts, callchain); if (opts->sample_intr_regs) { attr->sample_regs_intr = opts->sample_intr_regs; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index ab3632caba9f..7e45d2130a0f 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -178,8 +178,11 @@ void perf_evsel__init(struct perf_evsel *evsel, void perf_evsel__exit(struct perf_evsel *evsel); void perf_evsel__delete(struct perf_evsel *evsel); +struct callchain_param; + void perf_evsel__config(struct perf_evsel *evsel, - struct record_opts *opts); + struct record_opts *opts, + struct callchain_param *callchain); int __perf_evsel__sample_size(u64 sample_type); void perf_evsel__calc_id_pos(struct perf_evsel *evsel); diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 0467367dc315..481792c7484b 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -129,7 +129,8 @@ bool perf_can_record_cpu_wide(void) return true; } -void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) +void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, + struct callchain_param *callchain) { struct perf_evsel *evsel; bool use_sample_identifier = false; @@ -148,7 +149,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) use_comm_exec = perf_can_comm_exec(); evlist__for_each(evlist, evsel) { - perf_evsel__config(evsel, opts); + perf_evsel__config(evsel, opts, callchain); if (evsel->tracking && use_comm_exec) evsel->attr.comm_exec = 1; } -- GitLab From 22c8a376b55f327f7a25a318e87ba9202ba284bf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 18:37:45 -0300 Subject: [PATCH 2132/9938] perf evlist: Add (reset,set)_sample_bit methods For fiddling with sample_type fields in all evsels in an evlist. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-dg6yavctt0hzl2tsgfb43qsr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 18 ++++++++++++++++++ tools/perf/util/evlist.h | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 86a03836a83f..4c9f510ae18d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1192,6 +1192,24 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, perf_evlist__propagate_maps(evlist); } +void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, + enum perf_event_sample_format bit) +{ + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) + __perf_evsel__set_sample_bit(evsel, bit); +} + +void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, + enum perf_event_sample_format bit) +{ + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) + __perf_evsel__reset_sample_bit(evsel, bit); +} + int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) { struct perf_evsel *evsel; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 8db9228663d6..da46423998e8 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -87,6 +87,17 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist); int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler); +void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, + enum perf_event_sample_format bit); +void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, + enum perf_event_sample_format bit); + +#define perf_evlist__set_sample_bit(evlist, bit) \ + __perf_evlist__set_sample_bit(evlist, PERF_SAMPLE_##bit) + +#define perf_evlist__reset_sample_bit(evlist, bit) \ + __perf_evlist__reset_sample_bit(evlist, PERF_SAMPLE_##bit) + int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid); int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids); -- GitLab From 01e0d50c3f95cb1bae2dbfd83173bc2864d6d28c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 18:39:37 -0300 Subject: [PATCH 2133/9938] perf evsel: Rename config_callgraph() to config_callchain() and make it public The rename is for consistency with the parameter name. Make it public for fine grained control of which evsels should have callchains enabled, like, for instance, will be done in the next changesets in 'perf trace', to enable callchains just on the "raw_syscalls:sys_exit" tracepoint. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-og8vup111rn357g4yagus3ao@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 11 +++++------ tools/perf/util/evsel.h | 3 +++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 84252729222d..d475a4ec8b57 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -562,10 +562,9 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) return ret; } -static void -perf_evsel__config_callgraph(struct perf_evsel *evsel, - struct record_opts *opts, - struct callchain_param *param) +void perf_evsel__config_callchain(struct perf_evsel *evsel, + struct record_opts *opts, + struct callchain_param *param) { bool function = perf_evsel__is_function_event(evsel); struct perf_event_attr *attr = &evsel->attr; @@ -705,7 +704,7 @@ static void apply_config_terms(struct perf_evsel *evsel, /* set perf-event callgraph */ if (param.enabled) - perf_evsel__config_callgraph(evsel, opts, ¶m); + perf_evsel__config_callchain(evsel, opts, ¶m); } } @@ -814,7 +813,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, evsel->attr.exclude_callchain_user = 1; if (callchain && callchain->enabled && !evsel->no_aux_samples) - perf_evsel__config_callgraph(evsel, opts, callchain); + perf_evsel__config_callchain(evsel, opts, callchain); if (opts->sample_intr_regs) { attr->sample_regs_intr = opts->sample_intr_regs; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 7e45d2130a0f..1bd6c2e02dfa 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -183,6 +183,9 @@ struct callchain_param; void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, struct callchain_param *callchain); +void perf_evsel__config_callchain(struct perf_evsel *evsel, + struct record_opts *opts, + struct callchain_param *callchain); int __perf_evsel__sample_size(u64 sample_type); void perf_evsel__calc_id_pos(struct perf_evsel *evsel); -- GitLab From fde54b7860ffff1c93e6b9abb3fbc3b8b95f2695 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 18:42:37 -0300 Subject: [PATCH 2134/9938] perf trace: Make "--call-graph" affect just "raw_syscalls:sys_exit" We don't need the callchains at the syscall enter tracepoint, just when finishing it at syscall exit, so reduce the overhead by asking for callchains just at syscall exit. Suggested-by: Milian Wolff Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-fja1ods5vqpg42mdz09xcz3r@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 08fb100b91fa..60ab7ce3bc90 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2749,7 +2749,27 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_delete_evlist; } - perf_evlist__config(evlist, &trace->opts, &callchain_param); + perf_evlist__config(evlist, &trace->opts, NULL); + + if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) { + perf_evsel__config_callchain(trace->syscalls.events.sys_exit, + &trace->opts, &callchain_param); + /* + * Now we have evsels with different sample_ids, use + * PERF_SAMPLE_IDENTIFIER to map from sample to evsel + * from a fixed position in each ring buffer record. + * + * As of this the changeset introducing this comment, this + * isn't strictly needed, as the fields that can come before + * PERF_SAMPLE_ID are all used, but we'll probably disable + * some of those for things like copying the payload of + * pointer syscall arguments, and for vfs_getname we don't + * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this + * here as a warning we need to use PERF_SAMPLE_IDENTIFIER. + */ + perf_evlist__set_sample_bit(evlist, IDENTIFIER); + perf_evlist__reset_sample_bit(evlist, ID); + } signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); -- GitLab From fd4be13067ef65bf33b965a18c717889305d5fea Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 22:03:56 -0300 Subject: [PATCH 2135/9938] perf evsel: Allow unresolved symbol names to be printed as addresses The fprintf_sym() and fprintf_callchain() methods now allow users to change the existing behaviour of showing "[unknown]" as the name of unresolved symbols to instead show "[0x123456]", i.e. its address. The current patch doesn't change tools to use this facility, the results from 'perf trace' and 'perf script' cotinue like: 70.109 ( 0.001 ms): qemu-system-x8/10153 poll(ufds: 0x7f2d93ffe870, nfds: 1) = 0 Timeout [unknown] (/usr/lib64/libc-2.22.so) [unknown] (/usr/lib64/libspice-server.so.1.10.0) [unknown] (/usr/lib64/libspice-server.so.1.10.0) [unknown] (/usr/lib64/libspice-server.so.1.10.0) start_thread+0xca (/usr/lib64/libpthread-2.22.so) __clone+0x6d (/usr/lib64/libc-2.22.so) The next patch will make 'perf trace' use the new formatting. Suggested-by: Milian Wolff Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-fja1ods5vqpg42mdz09xcz3r@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 27 ++++++++++++++++++--------- tools/perf/util/session.h | 1 + tools/perf/util/symbol.c | 25 +++++++++++++++++++++---- tools/perf/util/symbol.h | 6 ++++++ 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e384b651a3e8..0516d06a2741 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1966,6 +1966,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; + int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR; char s = print_oneline ? ' ' : '\t'; if (sample->callchain) { @@ -2003,12 +2004,16 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * if (print_sym) { printed += fprintf(fp, " "); + node_al.addr = addr; + node_al.map = node->map; + if (print_symoffset) { - node_al.addr = addr; - node_al.map = node->map; - printed += symbol__fprintf_symname_offs(node->sym, &node_al, fp); - } else - printed += symbol__fprintf_symname(node->sym, fp); + printed += __symbol__fprintf_symname_offs(node->sym, &node_al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(node->sym, &node_al, + print_unknown_as_addr, fp); + } } if (print_dso) { @@ -2043,6 +2048,7 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample int print_dso = print_opts & PRINT_IP_OPT_DSO; int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; + int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR; if (symbol_conf.use_callchain && sample->callchain) { printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, @@ -2055,10 +2061,13 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample if (print_sym) { printed += fprintf(fp, " "); - if (print_symoffset) - printed += symbol__fprintf_symname_offs(al->sym, al, fp); - else - printed += symbol__fprintf_symname(al->sym, fp); + if (print_symoffset) { + printed += __symbol__fprintf_symname_offs(al->sym, al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(al->sym, al, + print_unknown_as_addr, fp); + } } if (print_dso) { diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index ac834908bb35..4257fac56618 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -42,6 +42,7 @@ struct perf_session { #define PRINT_IP_OPT_SYMOFFSET (1<<3) #define PRINT_IP_OPT_ONELINE (1<<4) #define PRINT_IP_OPT_SRCLINE (1<<5) +#define PRINT_IP_OPT_UNKNOWN_AS_ADDR (1<<6) struct perf_tool; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e7588dc91518..bb162ee433c6 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -264,8 +264,9 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp) sym->name); } -size_t symbol__fprintf_symname_offs(const struct symbol *sym, - const struct addr_location *al, FILE *fp) +size_t __symbol__fprintf_symname_offs(const struct symbol *sym, + const struct addr_location *al, + bool unknown_as_addr, FILE *fp) { unsigned long offset; size_t length; @@ -280,13 +281,29 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym, length += fprintf(fp, "+0x%lx", offset); } return length; - } else + } else if (al && unknown_as_addr) + return fprintf(fp, "[%#" PRIx64 "]", al->addr); + else return fprintf(fp, "[unknown]"); } +size_t symbol__fprintf_symname_offs(const struct symbol *sym, + const struct addr_location *al, + FILE *fp) +{ + return __symbol__fprintf_symname_offs(sym, al, false, fp); +} + +size_t __symbol__fprintf_symname(const struct symbol *sym, + const struct addr_location *al, + bool unknown_as_addr, FILE *fp) +{ + return __symbol__fprintf_symname_offs(sym, al, unknown_as_addr, fp); +} + size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp) { - return symbol__fprintf_symname_offs(sym, NULL, fp); + return __symbol__fprintf_symname_offs(sym, NULL, false, fp); } void symbols__delete(struct rb_root *symbols) diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index c8b7544d9267..e2562568418d 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -262,8 +262,14 @@ int symbol__init(struct perf_env *env); void symbol__exit(void); void symbol__elf_init(void); struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); +size_t __symbol__fprintf_symname_offs(const struct symbol *sym, + const struct addr_location *al, + bool unknown_as_addr, FILE *fp); size_t symbol__fprintf_symname_offs(const struct symbol *sym, const struct addr_location *al, FILE *fp); +size_t __symbol__fprintf_symname(const struct symbol *sym, + const struct addr_location *al, + bool unknown_as_addr, FILE *fp); size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); size_t symbol__fprintf(struct symbol *sym, FILE *fp); bool symbol_type__is_a(char symbol_type, enum map_type map_type); -- GitLab From 00768a2bd3245eace0690fcf2c02776a256b66d7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Apr 2016 22:08:55 -0300 Subject: [PATCH 2136/9938] perf trace: Print unresolved symbol names as addresses Instead of having "[unknown]" as the name used for unresolved symbols, use the address in the callchain, in hexadecimal form: 28.801 ( 0.007 ms): qemu-system-x8/10065 ppoll(ufds: 0x55c98b39e400, nfds: 72, tsp: 0x7fffe4e4fe60, sigsetsize: 8) = 0 Timeout ppoll+0x91 (/usr/lib64/libc-2.22.so) [0x337309] (/usr/bin/qemu-system-x86_64) [0x336ab4] (/usr/bin/qemu-system-x86_64) main+0x1724 (/usr/bin/qemu-system-x86_64) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) [0xc59a9] (/usr/bin/qemu-system-x86_64) 35.265 (14.805 ms): gnome-shell/2287 ... [continued]: poll()) = 1 [0xf6fdd] (/usr/lib64/libc-2.22.so) g_main_context_iterate.isra.29+0x17c (/usr/lib64/libglib-2.0.so.0.4600.2) g_main_loop_run+0xc2 (/usr/lib64/libglib-2.0.so.0.4600.2) meta_run+0x2c (/usr/lib64/libmutter.so.0.0.0) main+0x3f7 (/usr/bin/gnome-shell) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) [0x2909] (/usr/bin/gnome-shell) Suggested-by: Milian Wolff Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-fja1ods5vqpg42mdz09xcz3r@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 60ab7ce3bc90..2ec53edcf649 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2196,8 +2196,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, if (sample->callchain) { struct addr_location al; /* TODO: user-configurable print_opts */ - const unsigned int print_opts = PRINT_IP_OPT_SYM - | PRINT_IP_OPT_DSO; + const unsigned int print_opts = PRINT_IP_OPT_SYM | + PRINT_IP_OPT_DSO | + PRINT_IP_OPT_UNKNOWN_AS_ADDR; if (machine__resolve(trace->host, &al, sample) < 0) { pr_err("problem processing %d event, skipping it.\n", -- GitLab From 8070954d7c9fffa527e785292e901867338f79a9 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 9 Apr 2016 03:43:15 +0900 Subject: [PATCH 2137/9938] spi: omap2-mcspi: Undo broken fix for dma transfer of vmalloced buffer This reverts commit 3525e0aac91c4de5d20b1f22a6c6e2b39db3cc96. The DMA transfer for RX buffer was not handled correctly in this change. The actual transfer length for DMA RX can be less than xfer->len in the specific condition and the last words will be filled after the DMA completion, but the commit doesn't consider it and the dmaengine is started with rx_sg mapped by spi core. The solution for this at least requires more lines than this commit has inserted. So revert it for now. Signed-off-by: Akinobu Mita Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 62 +++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 43a02e377b3b..0caa3c8bef46 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -423,12 +423,16 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi, if (mcspi_dma->dma_tx) { struct dma_async_tx_descriptor *tx; + struct scatterlist sg; dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl, - xfer->tx_sg.nents, DMA_MEM_TO_DEV, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->tx_dma; + sg_dma_len(&sg) = xfer->len; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (tx) { tx->callback = omap2_mcspi_tx_callback; tx->callback_param = spi; @@ -474,15 +478,20 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, if (mcspi_dma->dma_rx) { struct dma_async_tx_descriptor *tx; + struct scatterlist sg; dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) dma_count -= es; - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, xfer->rx_sg.sgl, - xfer->rx_sg.nents, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + sg_init_table(&sg, 1); + sg_dma_address(&sg) = xfer->rx_dma; + sg_dma_len(&sg) = dma_count; + + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | + DMA_CTRL_ACK); if (tx) { tx->callback = omap2_mcspi_rx_callback; tx->callback_param = spi; @@ -496,6 +505,8 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, omap2_mcspi_set_dma_req(spi, 1, 1); wait_for_completion(&mcspi_dma->dma_rx_completion); + dma_unmap_single(mcspi->dev, xfer->rx_dma, count, + DMA_FROM_DEVICE); if (mcspi->fifo_depth > 0) return count; @@ -608,6 +619,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) if (tx != NULL) { wait_for_completion(&mcspi_dma->dma_tx_completion); + dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len, + DMA_TO_DEVICE); if (mcspi->fifo_depth > 0) { irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS; @@ -1074,16 +1087,6 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) gpio_free(spi->cs_gpio); } -static bool omap2_mcspi_can_dma(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *xfer) -{ - if (xfer->len < DMA_MIN_BYTES) - return false; - - return true; -} - static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, struct spi_device *spi, struct spi_transfer *t) { @@ -1265,6 +1268,32 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, return -EINVAL; } + if (len < DMA_MIN_BYTES) + goto skip_dma_map; + + if (mcspi_dma->dma_tx && tx_buf != NULL) { + t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf, + len, DMA_TO_DEVICE); + if (dma_mapping_error(mcspi->dev, t->tx_dma)) { + dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", + 'T', len); + return -EINVAL; + } + } + if (mcspi_dma->dma_rx && rx_buf != NULL) { + t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len, + DMA_FROM_DEVICE); + if (dma_mapping_error(mcspi->dev, t->rx_dma)) { + dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", + 'R', len); + if (tx_buf != NULL) + dma_unmap_single(mcspi->dev, t->tx_dma, + len, DMA_TO_DEVICE); + return -EINVAL; + } + } + +skip_dma_map: return omap2_mcspi_work_one(mcspi, spi, t); } @@ -1348,7 +1377,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev) master->transfer_one = omap2_mcspi_transfer_one; master->set_cs = omap2_mcspi_set_cs; master->cleanup = omap2_mcspi_cleanup; - master->can_dma = omap2_mcspi_can_dma; master->dev.of_node = node; master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ; master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15; -- GitLab From 3218b21ab07f066c99537fbbf2b4dc331b842246 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 4 Apr 2016 22:28:33 -0700 Subject: [PATCH 2138/9938] clk: imx: vf610: fix DCU clock tree Similar to an earlier fix for the SAI clocks, the DCU clock hierarchy mixes the bus clock with the display controllers pixel clock. Tests have shown that the gates in CCM_CCGR3/9 registers do not control the DCU pixel clock, but only the register access clock (bus clock). Fix this by defining the parent clock of VF610_CLK_DCUx to be the bus clock (ipg_bus). Since the clock has not been used far, there are no further changes needed. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-vf610.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 66e6faede8e5..60f14b990c27 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -372,11 +372,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2); clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19); clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3); - clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "dcu0_div", CCM_CCGR3, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus", CCM_CCGR3, CCM_CCGRx_CGn(8)); clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2); clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23); clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3); - clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(8)); clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4); clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30); -- GitLab From afd7350a9ac08da87eb9f38a432a05eca99c10f2 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 12 Apr 2016 08:59:38 +0800 Subject: [PATCH 2139/9938] clk: imx: vf610: add TCON ipg clock Add the ipg (bus) clock for the TCON modules (Timing Controller). This module is required by the new DCU DRM driver, since the display signals pass through TCON. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-vf610.c | 3 +++ include/dt-bindings/clock/vf610-clock.h | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 60f14b990c27..3a1f24475ee4 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -378,6 +378,9 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3); clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(8)); + clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13)); + clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", CCM_CCGR7, CCM_CCGRx_CGn(13)); + clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4); clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30); clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en", CCM_CSCDR2, 24, 4); diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index 7dc1b84fde07..dc5e1790d8cb 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h @@ -197,6 +197,8 @@ #define VF610_CLK_OCOTP 184 #define VF610_CLK_DDRMC 185 #define VF610_CLK_WKPU 186 -#define VF610_CLK_END 187 +#define VF610_CLK_TCON0 187 +#define VF610_CLK_TCON1 188 +#define VF610_CLK_END 189 #endif /* __DT_BINDINGS_CLOCK_VF610_H */ -- GitLab From 4506697d9f8537a8d33e9e002f8efceb32d10757 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Mon, 15 Feb 2016 11:33:57 +0800 Subject: [PATCH 2140/9938] soc: rockchip: power-domain: check the existing of regmap Check return value of syscon_node_to_regmap for rockchip_pm_domain_probe. If err value is returned, probe procedure should abort. Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 2116131528f7..ac729fe42cc9 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -475,6 +475,10 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev) } pmu->regmap = syscon_node_to_regmap(parent->of_node); + if (IS_ERR(pmu->regmap)) { + dev_err(dev, "no regmap available\n"); + return PTR_ERR(pmu->regmap); + } /* * Configure power up and down transition delays for CORE -- GitLab From 26d5192953d88d6231d173281848a1c61f9e5d34 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Thu, 17 Mar 2016 13:43:11 +0000 Subject: [PATCH 2141/9938] ARM: rockchip: Fix use of plain integer as NULL pointer This fixes the following sparse build warning: mach-rockchip/platsmp.c:68:43: Using plain integer as NULL pointer Signed-off-by: Peter Griffin Acked-by: Lee Jones Signed-off-by: Heiko Stuebner --- arch/arm/mach-rockchip/platsmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c index d42a07e33482..4d827a069d49 100644 --- a/arch/arm/mach-rockchip/platsmp.c +++ b/arch/arm/mach-rockchip/platsmp.c @@ -65,7 +65,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu) if (dev) np = dev->of_node; else - np = of_get_cpu_node(cpu, 0); + np = of_get_cpu_node(cpu, NULL); return of_reset_control_get(np, NULL); } -- GitLab From 69c542e8022ca53c5fee664548163809eb1777c3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 12 Apr 2016 09:22:49 +0800 Subject: [PATCH 2142/9938] clk: imx: vf610: fix whitespace in vf610-clock.h There is whitespace in VF610_CLK_OCOTP line. Fix it. Signed-off-by: Shawn Guo --- include/dt-bindings/clock/vf610-clock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index dc5e1790d8cb..45997750c8a0 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h @@ -194,7 +194,7 @@ #define VF610_PLL7_BYPASS 181 #define VF610_CLK_SNVS 182 #define VF610_CLK_DAP 183 -#define VF610_CLK_OCOTP 184 +#define VF610_CLK_OCOTP 184 #define VF610_CLK_DDRMC 185 #define VF610_CLK_WKPU 186 #define VF610_CLK_TCON0 187 -- GitLab From 38535e8e6962405b7d8a365f2f367f62bca98565 Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 7 Apr 2016 11:25:30 +0200 Subject: [PATCH 2143/9938] ASoC: sti: macro for uniperif tdm regs access Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/uniperif.h | 112 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index 1f82faafb869..400788bc9190 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1100,6 +1100,118 @@ UNIPERIF_DBG_STANDBY_LEFT_SP_SHIFT(ip), \ UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip), value) +/* + * UNIPERIF_TDM_ENABLE + */ +#define UNIPERIF_TDM_ENABLE_OFFSET(ip) 0x0118 +#define GET_UNIPERIF_TDM_ENABLE(ip) \ + readl_relaxed(ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip)) +#define SET_UNIPERIF_TDM_ENABLE(ip, value) \ + writel_relaxed(value, ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip)) + +/* TDM_ENABLE */ +#define UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip) 0x0 +#define UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip) 0x1 +#define GET_UNIPERIF_TDM_ENABLE_EN_TDM(ip) \ + GET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_ENABLE_OFFSET(ip), \ + UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \ + UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip)) +#define SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(ip) \ + SET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_ENABLE_OFFSET(ip), \ + UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \ + UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 1) +#define SET_UNIPERIF_TDM_ENABLE_TDM_DISABLE(ip) \ + SET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_ENABLE_OFFSET(ip), \ + UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \ + UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 0) + +/* + * UNIPERIF_TDM_FS_REF_FREQ + */ +#define UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip) 0x011c +#define GET_UNIPERIF_TDM_FS_REF_FREQ(ip) \ + readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip)) +#define SET_UNIPERIF_TDM_FS_REF_FREQ(ip, value) \ + writel_relaxed(value, ip->base + \ + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip)) + +/* REF_FREQ */ +#define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip) 0x0 +#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) 0 +#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) 1 +#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) 2 +#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) 3 +#define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip) 0x3 +#define GET_UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ(ip) \ + GET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip)) +#define SET_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) \ + SET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ + VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip)) +#define SET_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) \ + SET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ + VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip)) +#define SET_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) \ + SET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ + VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip)) +#define SET_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) \ + SET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ + VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip)) + +/* + * UNIPERIF_TDM_FS_REF_DIV + */ +#define UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip) 0x0120 +#define GET_UNIPERIF_TDM_FS_REF_DIV(ip) \ + readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip)) +#define SET_UNIPERIF_TDM_FS_REF_DIV(ip, value) \ + writel_relaxed(value, ip->base + \ + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip)) + +/* NUM_TIMESLOT */ +#define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip) 0x0 +#define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip) 0xff +#define GET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip) \ + GET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \ + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \ + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip)) +#define SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip, value) \ + SET_UNIPERIF_REG(ip, \ + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \ + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \ + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip), value) + +/* + * UNIPERIF_TDM_WORD_POS_X_Y + * 32 bits of UNIPERIF_TDM_WORD_POS_X_Y register shall be set in 1 shot + */ +#define UNIPERIF_TDM_WORD_POS_1_2_OFFSET(ip) 0x013c +#define UNIPERIF_TDM_WORD_POS_3_4_OFFSET(ip) 0x0140 +#define UNIPERIF_TDM_WORD_POS_5_6_OFFSET(ip) 0x0144 +#define UNIPERIF_TDM_WORD_POS_7_8_OFFSET(ip) 0x0148 +#define GET_UNIPERIF_TDM_WORD_POS(ip, words) \ + readl_relaxed(ip->base + UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip)) +#define SET_UNIPERIF_TDM_WORD_POS(ip, words, value) \ + writel_relaxed(value, ip->base + \ + UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip)) /* * uniperipheral IP capabilities */ -- GitLab From 5295a0dc31d5261ff64406ece25e8d9e91530d2e Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 7 Apr 2016 11:25:31 +0200 Subject: [PATCH 2144/9938] ASoC: sti: rename unip player type into common player & reader type Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/uniperif.h | 19 ++++++++++++++----- sound/soc/sti/uniperif_player.c | 31 +++++++++++-------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index 400788bc9190..75116ab3cbc0 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1219,6 +1219,15 @@ #define UNIPERIF_FIFO_SIZE 70 /* FIFO is 70 cells deep */ #define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */ +#define UNIPERIF_TYPE_IS_HDMI(p) \ + ((p)->info->type == SND_ST_UNIPERIF_TYPE_HDMI) +#define UNIPERIF_TYPE_IS_PCM(p) \ + ((p)->info->type == SND_ST_UNIPERIF_TYPE_PCM) +#define UNIPERIF_TYPE_IS_SPDIF(p) \ + ((p)->info->type == SND_ST_UNIPERIF_TYPE_SPDIF) +#define UNIPERIF_TYPE_IS_IEC958(p) \ + (UNIPERIF_TYPE_IS_HDMI(p) || \ + UNIPERIF_TYPE_IS_SPDIF(p)) /* * Uniperipheral IP revisions */ @@ -1237,10 +1246,10 @@ enum uniperif_version { }; enum uniperif_type { - SND_ST_UNIPERIF_PLAYER_TYPE_NONE, - SND_ST_UNIPERIF_PLAYER_TYPE_HDMI, - SND_ST_UNIPERIF_PLAYER_TYPE_PCM, - SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF + SND_ST_UNIPERIF_TYPE_NONE, + SND_ST_UNIPERIF_TYPE_HDMI, + SND_ST_UNIPERIF_TYPE_PCM, + SND_ST_UNIPERIF_TYPE_SPDIF }; enum uniperif_state { @@ -1259,7 +1268,7 @@ enum uniperif_iec958_encoding_mode { struct uniperif_info { int id; /* instance value of the uniperipheral IP */ - enum uniperif_type player_type; + enum uniperif_type type; int underflow_enabled; /* Underflow recovery mode */ }; diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 7aca6b92f718..ab4310a1615e 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -26,15 +26,6 @@ /* * Driver specific types. */ -#define UNIPERIF_PLAYER_TYPE_IS_HDMI(p) \ - ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_HDMI) -#define UNIPERIF_PLAYER_TYPE_IS_PCM(p) \ - ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_PCM) -#define UNIPERIF_PLAYER_TYPE_IS_SPDIF(p) \ - ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF) -#define UNIPERIF_PLAYER_TYPE_IS_IEC958(p) \ - (UNIPERIF_PLAYER_TYPE_IS_HDMI(p) || \ - UNIPERIF_PLAYER_TYPE_IS_SPDIF(p)) #define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999 #define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000 @@ -738,14 +729,14 @@ static int uni_player_prepare(struct snd_pcm_substream *substream, SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit); /* Uniperipheral setup depends on player type */ - switch (player->info->player_type) { - case SND_ST_UNIPERIF_PLAYER_TYPE_HDMI: + switch (player->info->type) { + case SND_ST_UNIPERIF_TYPE_HDMI: ret = uni_player_prepare_iec958(player, runtime); break; - case SND_ST_UNIPERIF_PLAYER_TYPE_PCM: + case SND_ST_UNIPERIF_TYPE_PCM: ret = uni_player_prepare_pcm(player, runtime); break; - case SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF: + case SND_ST_UNIPERIF_TYPE_SPDIF: ret = uni_player_prepare_iec958(player, runtime); break; default: @@ -852,8 +843,8 @@ static int uni_player_start(struct uniperif *player) * will not take affect and hang the player. */ if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) - if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) - SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); + if (UNIPERIF_TYPE_IS_IEC958(player)) + SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); /* Force channel status update (no update if clk disable) */ if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) @@ -1012,13 +1003,13 @@ static int uni_player_parse_dt(struct platform_device *pdev, } if (strcasecmp(mode, "hdmi") == 0) - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_HDMI; + info->type = SND_ST_UNIPERIF_TYPE_HDMI; else if (strcasecmp(mode, "pcm") == 0) - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_PCM; + info->type = SND_ST_UNIPERIF_TYPE_PCM; else if (strcasecmp(mode, "spdif") == 0) - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF; + info->type = SND_ST_UNIPERIF_TYPE_SPDIF; else - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_NONE; + info->type = SND_ST_UNIPERIF_TYPE_NONE; /* Save the info structure */ player->info = info; @@ -1087,7 +1078,7 @@ int uni_player_init(struct platform_device *pdev, SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player); - if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) { + if (UNIPERIF_TYPE_IS_IEC958(player)) { /* Set default iec958 status bits */ /* Consumer, PCM, copyright, 2ch, mode 0 */ -- GitLab From 9a00a3e9fea1ea5affa7bea971299d3a5832daad Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 7 Apr 2016 11:25:32 +0200 Subject: [PATCH 2145/9938] ASoC: sti: define tdm type & default tdm hw config Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/uniperif.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index 75116ab3cbc0..750eb5a07e6c 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1228,6 +1228,9 @@ #define UNIPERIF_TYPE_IS_IEC958(p) \ (UNIPERIF_TYPE_IS_HDMI(p) || \ UNIPERIF_TYPE_IS_SPDIF(p)) +#define UNIPERIF_TYPE_IS_TDM(p) \ + ((p)->info->type == SND_ST_UNIPERIF_TYPE_TDM) + /* * Uniperipheral IP revisions */ @@ -1249,7 +1252,8 @@ enum uniperif_type { SND_ST_UNIPERIF_TYPE_NONE, SND_ST_UNIPERIF_TYPE_HDMI, SND_ST_UNIPERIF_TYPE_PCM, - SND_ST_UNIPERIF_TYPE_SPDIF + SND_ST_UNIPERIF_TYPE_SPDIF, + SND_ST_UNIPERIF_TYPE_TDM }; enum uniperif_state { @@ -1330,6 +1334,28 @@ struct sti_uniperiph_data { struct sti_uniperiph_dai dai_data; }; +static const struct snd_pcm_hardware uni_tdm_hw = { + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID, + + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE, + + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 8000, + .rate_max = 48000, + + .channels_min = 1, + .channels_max = 32, + + .periods_min = 2, + .periods_max = 10, + + .period_bytes_min = 128, + .period_bytes_max = 64 * PAGE_SIZE, + .buffer_bytes_max = 256 * PAGE_SIZE +}; + /* uniperiph player*/ int uni_player_init(struct platform_device *pdev, struct uniperif *uni_player); -- GitLab From da5ecb4dfd84fa4eaba782fc3fa0aa0f807a5804 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 1 Apr 2016 15:18:01 -0400 Subject: [PATCH 2146/9938] staging/lustre: Fix braces {} style This fixes all checkpatch form of this from the Lustre tree: CHECK: braces {} should be used on all arms of this statement Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fld/fld_cache.c | 3 ++- .../lustre/lustre/include/lustre/lustre_idl.h | 3 ++- .../staging/lustre/lustre/include/obd_class.h | 3 ++- drivers/staging/lustre/lustre/llite/dir.c | 20 ++++++++++--------- .../staging/lustre/lustre/llite/llite_close.c | 3 ++- .../staging/lustre/lustre/llite/llite_lib.c | 9 +++++---- drivers/staging/lustre/lustre/llite/lloop.c | 3 ++- drivers/staging/lustre/lustre/llite/namei.c | 6 ++++-- drivers/staging/lustre/lustre/llite/rw.c | 6 ++++-- drivers/staging/lustre/lustre/llite/rw26.c | 3 ++- drivers/staging/lustre/lustre/llite/vvp_dev.c | 12 +++++++---- drivers/staging/lustre/lustre/llite/vvp_io.c | 3 ++- drivers/staging/lustre/lustre/llite/xattr.c | 3 ++- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 3 ++- drivers/staging/lustre/lustre/lov/lov_dev.c | 10 ++++++---- drivers/staging/lustre/lustre/lov/lov_io.c | 9 ++++++--- .../staging/lustre/lustre/lov/lov_object.c | 6 ++++-- drivers/staging/lustre/lustre/lov/lov_pack.c | 4 ++-- .../staging/lustre/lustre/lov/lovsub_dev.c | 9 ++++++--- .../staging/lustre/lustre/lov/lovsub_lock.c | 3 ++- .../staging/lustre/lustre/lov/lovsub_object.c | 6 ++++-- .../staging/lustre/lustre/obdclass/cl_io.c | 13 +++++++----- .../lustre/lustre/obdclass/cl_object.c | 9 ++++++--- .../lustre/lustre/obdclass/lprocfs_status.c | 3 ++- .../lustre/lustre/obdclass/lu_object.c | 3 ++- .../lustre/lustre/obdclass/lustre_peer.c | 3 ++- drivers/staging/lustre/lustre/osc/osc_io.c | 3 ++- drivers/staging/lustre/lustre/osc/osc_lock.c | 3 ++- .../staging/lustre/lustre/osc/osc_object.c | 3 ++- drivers/staging/lustre/lustre/osc/osc_page.c | 3 ++- .../staging/lustre/lustre/osc/osc_request.c | 3 ++- drivers/staging/lustre/lustre/ptlrpc/client.c | 4 ++-- .../lustre/lustre/ptlrpc/lproc_ptlrpc.c | 9 +++++---- 33 files changed, 117 insertions(+), 69 deletions(-) diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 062f388cf38a..5a04e99d9249 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -178,8 +178,9 @@ static void fld_fix_new_list(struct fld_cache *cache) if (n_range->lsr_end <= c_range->lsr_end) { *n_range = *c_range; fld_cache_entry_delete(cache, f_curr); - } else + } else { n_range->lsr_start = c_range->lsr_end; + } } /* we could have overlap over next diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index ae0c48818bb6..23cbdd3bed8e 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1001,8 +1001,9 @@ static inline int lu_dirent_calc_size(int namelen, __u16 attr) size = (sizeof(struct lu_dirent) + namelen + align) & ~align; size += sizeof(struct luda_type); - } else + } else { size = sizeof(struct lu_dirent) + namelen; + } return (size + 7) & ~7; } diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 706869f8c98f..40f7a2374865 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -490,8 +490,9 @@ static inline int obd_setup(struct obd_device *obd, struct lustre_cfg *cfg) obd->obd_lu_dev = d; d->ld_obd = obd; rc = 0; - } else + } else { rc = PTR_ERR(d); + } } lu_context_exit(&session_ctx); lu_context_fini(&session_ctx); diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index d1f25ef51145..eb2e79ec37c0 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1496,8 +1496,9 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) cmd == LL_IOC_MDC_GETINFO)) { rc = 0; goto skip_lmm; - } else + } else { goto out_req; + } } if (cmd == IOC_MDC_GETFILESTRIPE || @@ -1710,15 +1711,16 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ll_flush_ctx(inode); #ifdef CONFIG_FS_POSIX_ACL case LL_IOC_RMTACL: { - if (sbi->ll_flags & LL_SBI_RMT_CLIENT && is_root_inode(inode)) { - struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + if (sbi->ll_flags & LL_SBI_RMT_CLIENT && is_root_inode(inode)) { + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); - rc = rct_add(&sbi->ll_rct, current_pid(), arg); - if (!rc) - fd->fd_flags |= LL_FILE_RMTACL; - return rc; - } else - return 0; + rc = rct_add(&sbi->ll_rct, current_pid(), arg); + if (!rc) + fd->fd_flags |= LL_FILE_RMTACL; + return rc; + } else { + return 0; + } } #endif case LL_IOC_GETOBDCOUNT: { diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index 8d2398003c5a..92b73ef3222c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -323,8 +323,9 @@ static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) lli = list_entry(lcq->lcq_head.next, struct ll_inode_info, lli_close_list); list_del_init(&lli->lli_close_list); - } else if (atomic_read(&lcq->lcq_stop)) + } else if (atomic_read(&lcq->lcq_stop)) { lli = ERR_PTR(-EALREADY); + } spin_unlock(&lcq->lcq_lock); return lli; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 965576750c41..c04d3776a952 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1596,8 +1596,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) " to the "DFID", inode %lu/%u(%p)\n", PFID(&lli->lli_fid), PFID(&body->fid1), inode->i_ino, inode->i_generation, inode); - } else + } else { lli->lli_fid = body->fid1; + } } LASSERT(fid_seq(&lli->lli_fid) != 0); @@ -2065,11 +2066,11 @@ int ll_obd_statfs(struct inode *inode, void __user *arg) } memcpy(&type, data->ioc_inlbuf1, sizeof(__u32)); - if (type & LL_STATFS_LMV) + if (type & LL_STATFS_LMV) { exp = sbi->ll_md_exp; - else if (type & LL_STATFS_LOV) + } else if (type & LL_STATFS_LOV) { exp = sbi->ll_dt_exp; - else { + } else { rc = -ENODEV; goto out_statfs; } diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index f169c0db63b4..813a9a354e5f 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -274,8 +274,9 @@ static void loop_add_bio(struct lloop_device *lo, struct bio *bio) if (lo->lo_biotail) { lo->lo_biotail->bi_next = bio; lo->lo_biotail = bio; - } else + } else { lo->lo_bio = lo->lo_biotail = bio; + } spin_unlock_irqrestore(&lo->lo_lock, flags); atomic_inc(&lo->lo_pending); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index f8f98e4e8258..856170762ef7 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -128,10 +128,12 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, if (rc != 0) { iget_failed(inode); inode = NULL; - } else + } else { unlock_new_inode(inode); - } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) + } + } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) { ll_update_inode(inode, md); + } CDEBUG(D_VFSTRACE, "got inode: %p for "DFID"\n", inode, PFID(&md->body->fid1)); } diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index e3cf640f206c..fee319ce472d 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -132,8 +132,9 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) lcc->lcc_page = page; lu_ref_add(&page->cp_reference, "cl_io", io); result = 0; - } else + } else { result = PTR_ERR(page); + } } if (result) { ll_cl_fini(lcc); @@ -488,8 +489,9 @@ static int ll_read_ahead_pages(const struct lu_env *env, if (rc == 1) { (*reserved_pages)--; count++; - } else if (rc == -ENOLCK) + } else if (rc == -ENOLCK) { break; + } } else if (stride_ria) { /* If it is not in the read-ahead window, and it is * read-ahead mode, then check whether it should skip diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 17dea41acd63..cad6aa935bb2 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -98,8 +98,9 @@ static void ll_invalidatepage(struct page *vmpage, unsigned int offset, cl_page_delete(env, page); cl_page_put(env, page); } - } else + } else { LASSERT(vmpage->private == 0); + } cl_env_put(env, &refcheck); } } diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 08d9b2b6f437..644a31f62464 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -342,8 +342,9 @@ int cl_sb_init(struct super_block *sb) sbi->ll_site = cl2lu_dev(cl)->ld_site; } cl_env_put(env, &refcheck); - } else + } else { rc = PTR_ERR(env); + } return rc; } @@ -588,16 +589,19 @@ static int vvp_pgcache_show(struct seq_file *f, void *v) if (page) { vvp_pgcache_page_show(env, f, page); cl_page_put(env, page); - } else + } else { seq_puts(f, "missing\n"); + } lu_object_ref_del(&clob->co_lu, "dump", current); cl_object_put(env, clob); - } else + } else { seq_printf(f, "%llx missing\n", pos); + } cl_env_put(env, &refcheck); result = 0; - } else + } else { result = PTR_ERR(env); + } return result; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 91ea6fd7bac2..26dfbf1d2345 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -1178,8 +1178,9 @@ static int vvp_io_fault_start(const struct lu_env *env, if (result == -EDQUOT) result = -ENOSPC; goto out; - } else + } else { cl_page_disown(env, io, page); + } } } diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index b68dcc921ca2..be5cb215ed81 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -181,8 +181,9 @@ int ll_setxattr_common(struct inode *inode, const char *name, size = rc; pv = (const char *)new_value; - } else + } else { return -EOPNOTSUPP; + } valid |= rce_ops2valid(rce->rce_ops); } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index f6252c7bf970..a3967771ae07 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1122,8 +1122,9 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, if (!rc) rc = err; } - } else + } else { set = 1; + } } if (!set && !rc) rc = -EIO; diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index dccc63496982..dae8e89bcf6d 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -262,8 +262,9 @@ static int lov_req_init(const struct lu_env *env, struct cl_device *dev, if (lr) { cl_req_slice_add(req, &lr->lr_cl, dev, &lov_req_ops); result = 0; - } else + } else { result = -ENOMEM; + } return result; } @@ -332,14 +333,15 @@ static struct lov_device_emerg **lov_emerg_alloc(int nr) cl_page_list_init(&em->emrg_page_list); em->emrg_env = cl_env_alloc(&em->emrg_refcheck, LCT_REMEMBER | LCT_NOREF); - if (!IS_ERR(em->emrg_env)) + if (!IS_ERR(em->emrg_env)) { em->emrg_env->le_ctx.lc_cookie = 0x2; - else { + } else { result = PTR_ERR(em->emrg_env); em->emrg_env = NULL; } - } else + } else { result = -ENOMEM; + } } if (result != 0) { lov_emerg_free(emerg, nr); diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 41512372c472..f443778c83fd 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -225,8 +225,9 @@ struct lov_io_sub *lov_sub_get(const struct lu_env *env, if (!sub->sub_io_initialized) { sub->sub_stripe = stripe; rc = lov_io_sub_init(env, lio, sub); - } else + } else { rc = 0; + } if (rc == 0) lov_sub_enter(sub); else @@ -294,8 +295,9 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio, lio->lis_single_subio_index = -1; lio->lis_active_subios = 0; result = 0; - } else + } else { result = -ENOMEM; + } return result; } @@ -413,8 +415,9 @@ static int lov_io_iter_init(const struct lu_env *env, lov_sub_put(sub); CDEBUG(D_VFSTRACE, "shrink: %d [%llu, %llu)\n", stripe, start, end); - } else + } else { rc = PTR_ERR(sub); + } if (!rc) list_add_tail(&sub->sub_linkage, &lio->lis_active); diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 6a353d18eefe..561d493b2cdf 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -283,8 +283,9 @@ static int lov_init_raid0(const struct lu_env *env, } if (result == 0) cl_object_header(&lov->lo_cl)->coh_page_bufsize += psz; - } else + } else { result = -ENOMEM; + } out: return result; } @@ -935,8 +936,9 @@ struct lu_object *lov_object_alloc(const struct lu_env *env, * for object with different layouts. */ obj->lo_ops = &lov_lu_obj_ops; - } else + } else { obj = NULL; + } return obj; } diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 3925633a99ec..9723d2e091b1 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -457,9 +457,9 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, } /* User wasn't expecting this many OST entries */ - if (lum.lmm_stripe_count == 0) + if (lum.lmm_stripe_count == 0) { lmm_size = lum_size; - else if (lum.lmm_stripe_count < lmmk->lmm_stripe_count) { + } else if (lum.lmm_stripe_count < lmmk->lmm_stripe_count) { rc = -EOVERFLOW; goto out_set; } diff --git a/drivers/staging/lustre/lustre/lov/lovsub_dev.c b/drivers/staging/lustre/lustre/lov/lovsub_dev.c index c335c020f4f4..35f6b1d66ff4 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_dev.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_dev.c @@ -151,8 +151,9 @@ static int lovsub_req_init(const struct lu_env *env, struct cl_device *dev, if (lsr) { cl_req_slice_add(req, &lsr->lsrq_cl, dev, &lovsub_req_ops); result = 0; - } else + } else { result = -ENOMEM; + } return result; } @@ -182,10 +183,12 @@ static struct lu_device *lovsub_device_alloc(const struct lu_env *env, d = lovsub2lu_dev(lsd); d->ld_ops = &lovsub_lu_ops; lsd->acid_cl.cd_ops = &lovsub_cl_ops; - } else + } else { d = ERR_PTR(result); - } else + } + } else { d = ERR_PTR(-ENOMEM); + } return d; } diff --git a/drivers/staging/lustre/lustre/lov/lovsub_lock.c b/drivers/staging/lustre/lustre/lov/lovsub_lock.c index 670d203ab77e..e92edfb618b7 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_lock.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_lock.c @@ -77,8 +77,9 @@ int lovsub_lock_init(const struct lu_env *env, struct cl_object *obj, INIT_LIST_HEAD(&lsk->lss_parents); cl_lock_slice_add(lock, &lsk->lss_cl, obj, &lovsub_lock_ops); result = 0; - } else + } else { result = -ENOMEM; + } return result; } diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c index 6c5430d938d0..3f51f0db02ad 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_object.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c @@ -67,8 +67,9 @@ int lovsub_object_init(const struct lu_env *env, struct lu_object *obj, lu_object_add(obj, below); cl_object_page_init(lu2cl(obj), sizeof(struct lovsub_page)); result = 0; - } else + } else { result = -ENOMEM; + } return result; } @@ -154,8 +155,9 @@ struct lu_object *lovsub_object_alloc(const struct lu_env *env, lu_object_add_top(&hdr->coh_lu, obj); los->lso_cl.co_ops = &lovsub_ops; obj->lo_ops = &lovsub_lu_obj_ops; - } else + } else { obj = NULL; + } return obj; } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index f4b3178ec043..583fb5f33889 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -504,9 +504,9 @@ int cl_io_lock_add(const struct lu_env *env, struct cl_io *io, { int result; - if (cl_lockset_merge(&io->ci_lockset, &link->cill_descr)) + if (cl_lockset_merge(&io->ci_lockset, &link->cill_descr)) { result = 1; - else { + } else { list_add(&link->cill_linkage, &io->ci_lockset.cls_todo); result = 0; } @@ -536,8 +536,9 @@ int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io, result = cl_io_lock_add(env, io, link); if (result) /* lock match */ link->cill_fini(env, link); - } else + } else { result = -ENOMEM; + } return result; } @@ -1202,14 +1203,16 @@ struct cl_req *cl_req_alloc(const struct lu_env *env, struct cl_page *page, if (req->crq_o) { req->crq_nrobjs = nr_objects; result = cl_req_init(env, req, page); - } else + } else { result = -ENOMEM; + } if (result != 0) { cl_req_completion(env, req, result); req = ERR_PTR(result); } - } else + } else { req = ERR_PTR(-ENOMEM); + } return req; } EXPORT_SYMBOL(cl_req_alloc); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 395b92c6480d..a068e08b2031 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -654,8 +654,9 @@ static struct lu_env *cl_env_new(__u32 ctx_tags, __u32 ses_tags, void *debug) lu_context_enter(&cle->ce_ses); env->le_ses = &cle->ce_ses; cl_env_init0(cle, debug); - } else + } else { lu_env_fini(env); + } } if (rc != 0) { kmem_cache_free(cl_env_kmem, cle); @@ -664,8 +665,9 @@ static struct lu_env *cl_env_new(__u32 ctx_tags, __u32 ses_tags, void *debug) CL_ENV_INC(create); CL_ENV_INC(total); } - } else + } else { env = ERR_PTR(-ENOMEM); + } return env; } @@ -1095,8 +1097,9 @@ struct cl_device *cl_type_setup(const struct lu_env *env, struct lu_site *site, CERROR("can't init device '%s', %d\n", typename, rc); d = ERR_PTR(rc); } - } else + } else { CERROR("Cannot allocate device: '%s'\n", typename); + } return lu2cl_dev(d); } EXPORT_SYMBOL(cl_type_setup); diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index d93f42fee420..9824c8868cdf 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -694,8 +694,9 @@ int lprocfs_rd_import(struct seq_file *m, void *data) do_div(sum, ret.lc_count); ret.lc_sum = sum; - } else + } else { ret.lc_sum = 0; + } seq_printf(m, " rpcs:\n" " inflight: %u\n" diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 3870df53e63d..990e9394c8f1 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -716,8 +716,9 @@ struct lu_object *lu_object_find_slice(const struct lu_env *env, obj = lu_object_locate(top->lo_header, dev->ld_type); if (!obj) lu_object_put(env, top); - } else + } else { obj = top; + } return obj; } EXPORT_SYMBOL(lu_object_find_slice); diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c index 5f812460b3ea..b1abe023bb35 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c @@ -163,8 +163,9 @@ int class_del_uuid(const char *uuid) break; } } - } else + } else { list_splice_init(&g_uuid_list, &deathrow); + } spin_unlock(&g_uuid_lock); if (uuid && list_empty(&deathrow)) { diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 894007854ce7..c1efcb306f24 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -842,8 +842,9 @@ int osc_req_init(const struct lu_env *env, struct cl_device *dev, if (or) { cl_req_slice_add(req, &or->or_cl, dev, &osc_req_ops); result = 0; - } else + } else { result = -ENOMEM; + } return result; } diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 49dfe9f8bc4b..7ea64896a4f6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -624,8 +624,9 @@ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) result = -ELDLM_NO_LOCK_DATA; } cl_env_nested_put(&nest, env); - } else + } else { result = PTR_ERR(env); + } req->rq_status = result; return result; } diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index a06bdf10b6ff..738ab10ab274 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -292,8 +292,9 @@ struct lu_object *osc_object_alloc(const struct lu_env *env, lu_object_init(obj, NULL, dev); osc->oo_cl.co_ops = &osc_ops; obj->lo_ops = &osc_lu_obj_ops; - } else + } else { obj = NULL; + } return obj; } diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index a19badceab61..b55f46739dfa 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -421,8 +421,9 @@ static int osc_cache_too_much(struct client_obd *cli) return lru_shrink_max; else if (pages >= budget / 2) return lru_shrink_min; - } else if (pages >= budget * 2) + } else if (pages >= budget * 2) { return lru_shrink_min; + } return 0; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index a48d9d6ff72a..4d0f831990f2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -3065,8 +3065,9 @@ static int osc_import_event(struct obd_device *obd, ldlm_namespace_cleanup(ns, LDLM_FL_LOCAL_ONLY); cl_env_put(env, &refcheck); - } else + } else { rc = PTR_ERR(env); + } break; } case IMP_EVENT_ACTIVE: { diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 355f108fea01..e02d95d1d537 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -595,9 +595,9 @@ static int __ptlrpc_request_bufs_pack(struct ptlrpc_request *request, struct obd_import *imp = request->rq_import; int rc; - if (unlikely(ctx)) + if (unlikely(ctx)) { request->rq_cli_ctx = sptlrpc_cli_ctx_get(ctx); - else { + } else { rc = sptlrpc_req_get_ctx(request); if (rc) goto out_free; diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index c95a91ce26c9..a35b56ec687e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -679,11 +679,11 @@ static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, /** * The second token is either NULL, or an optional [reg|hp] string */ - if (strcmp(cmd, "reg") == 0) + if (strcmp(cmd, "reg") == 0) { queue = PTLRPC_NRS_QUEUE_REG; - else if (strcmp(cmd, "hp") == 0) + } else if (strcmp(cmd, "hp") == 0) { queue = PTLRPC_NRS_QUEUE_HP; - else { + } else { rc = -EINVAL; goto out; } @@ -693,8 +693,9 @@ static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, if (queue == PTLRPC_NRS_QUEUE_HP && !nrs_svc_has_hp(svc)) { rc = -ENODEV; goto out; - } else if (queue == PTLRPC_NRS_QUEUE_BOTH && !nrs_svc_has_hp(svc)) + } else if (queue == PTLRPC_NRS_QUEUE_BOTH && !nrs_svc_has_hp(svc)) { queue = PTLRPC_NRS_QUEUE_REG; + } /** * Serialize NRS core lprocfs operations with policy registration/ -- GitLab From 7f2d15bb587a8ed8e2ddebd7ffdfcc94b5113f93 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 1 Apr 2016 15:18:03 -0400 Subject: [PATCH 2147/9938] staging/lustre: Get rid of ldlm_policy_res_t typedef Directly use enum ldlm_policy_res everywhere. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/ldlm/ldlm_internal.h | 2 - .../staging/lustre/lustre/ldlm/ldlm_request.c | 49 +++++++++---------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index 351f8b44947f..ba643e68dd2d 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -218,8 +218,6 @@ enum ldlm_policy_res { LDLM_POLICY_SKIP_LOCK }; -typedef enum ldlm_policy_res ldlm_policy_res_t; - #define LDLM_POOL_SYSFS_PRINT_int(v) sprintf(buf, "%d\n", v) #define LDLM_POOL_SYSFS_SET_int(a, b) { a = b; } #define LDLM_POOL_SYSFS_PRINT_u64(v) sprintf(buf, "%lld\n", v) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 8ef28ccfe948..880efdc2fa96 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1131,12 +1131,11 @@ EXPORT_SYMBOL(ldlm_cli_cancel_list_local); * dirty data, to close a file, ...) or waiting for any RPCs in-flight (e.g. * readahead requests, ...) */ -static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, - struct ldlm_lock *lock, - int unused, int added, - int count) +static enum ldlm_policy_res +ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, struct ldlm_lock *lock, + int unused, int added, int count) { - ldlm_policy_res_t result = LDLM_POLICY_CANCEL_LOCK; + enum ldlm_policy_res result = LDLM_POLICY_CANCEL_LOCK; /* don't check added & count since we want to process all locks * from unused list. @@ -1168,10 +1167,10 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns, * * \retval LDLM_POLICY_CANCEL_LOCK cancel lock from LRU */ -static ldlm_policy_res_t ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, - struct ldlm_lock *lock, - int unused, int added, - int count) +static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, + struct ldlm_lock *lock, + int unused, int added, + int count) { unsigned long cur = cfs_time_current(); struct ldlm_pool *pl = &ns->ns_pool; @@ -1214,10 +1213,10 @@ static ldlm_policy_res_t ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, * * \retval LDLM_POLICY_CANCEL_LOCK cancel lock from LRU */ -static ldlm_policy_res_t ldlm_cancel_passed_policy(struct ldlm_namespace *ns, - struct ldlm_lock *lock, - int unused, int added, - int count) +static enum ldlm_policy_res ldlm_cancel_passed_policy(struct ldlm_namespace *ns, + struct ldlm_lock *lock, + int unused, int added, + int count) { /* Stop LRU processing when we reach past @count or have checked all * locks in LRU. @@ -1235,10 +1234,10 @@ static ldlm_policy_res_t ldlm_cancel_passed_policy(struct ldlm_namespace *ns, * * \retval LDLM_POLICY_CANCEL_LOCK cancel lock from LRU */ -static ldlm_policy_res_t ldlm_cancel_aged_policy(struct ldlm_namespace *ns, - struct ldlm_lock *lock, - int unused, int added, - int count) +static enum ldlm_policy_res ldlm_cancel_aged_policy(struct ldlm_namespace *ns, + struct ldlm_lock *lock, + int unused, int added, + int count) { if ((added >= count) && time_before(cfs_time_current(), @@ -1251,13 +1250,13 @@ static ldlm_policy_res_t ldlm_cancel_aged_policy(struct ldlm_namespace *ns, return LDLM_POLICY_CANCEL_LOCK; } -static ldlm_policy_res_t +static enum ldlm_policy_res ldlm_cancel_lrur_no_wait_policy(struct ldlm_namespace *ns, struct ldlm_lock *lock, int unused, int added, int count) { - ldlm_policy_res_t result; + enum ldlm_policy_res result; result = ldlm_cancel_lrur_policy(ns, lock, unused, added, count); if (result == LDLM_POLICY_KEEP_LOCK) @@ -1275,10 +1274,9 @@ ldlm_cancel_lrur_no_wait_policy(struct ldlm_namespace *ns, * * \retval LDLM_POLICY_CANCEL_LOCK cancel lock from LRU */ -static ldlm_policy_res_t ldlm_cancel_default_policy(struct ldlm_namespace *ns, - struct ldlm_lock *lock, - int unused, int added, - int count) +static enum ldlm_policy_res +ldlm_cancel_default_policy(struct ldlm_namespace *ns, struct ldlm_lock *lock, + int unused, int added, int count) { /* Stop LRU processing when we reach past count or have checked all * locks in LRU. @@ -1287,7 +1285,8 @@ static ldlm_policy_res_t ldlm_cancel_default_policy(struct ldlm_namespace *ns, LDLM_POLICY_KEEP_LOCK : LDLM_POLICY_CANCEL_LOCK; } -typedef ldlm_policy_res_t (*ldlm_cancel_lru_policy_t)(struct ldlm_namespace *, +typedef enum ldlm_policy_res (*ldlm_cancel_lru_policy_t)( + struct ldlm_namespace *, struct ldlm_lock *, int, int, int); @@ -1368,7 +1367,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, LASSERT(pf); while (!list_empty(&ns->ns_unused_list)) { - ldlm_policy_res_t result; + enum ldlm_policy_res result; time_t last_use = 0; /* all unused locks */ -- GitLab From 0715f9417ad3581e721d4b2ca6d11aa9fb0e598d Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Mon, 4 Apr 2016 21:36:46 -0400 Subject: [PATCH 2148/9938] staging: lustre: ldlm: fix 'deadcode' errors Fix 'deadcode' issues found by Coverity version 6.5.1: Logically dead code (DEADCODE) Execution cannot reach this statement. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3097 Reviewed-on: http://review.whamcloud.com/7167 Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index b88b78606aee..3f97e1ca7192 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -530,12 +530,6 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) return -EIO; } - if (rc) { - LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)", - rc); - return rc; - } - LDLM_DEBUG(lock, "client-side enqueue granted"); lock_res_and_lock(lock); -- GitLab From d467220e61294a6e30716c3ea55641d7df8d0440 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Mon, 4 Apr 2016 21:36:47 -0400 Subject: [PATCH 2149/9938] staging: lustre: llite: use 64bits flags in ll_lov_setea() In ll_lov_setea(), setting MDS_OPEN_HAS_OBJS to an int flags will result in the flags being overflowed. Signed-off-by: Niu Yawei Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3744 Reviewed-on: http://review.whamcloud.com/7312 Reviewed-by: Emoly Liu Reviewed-by: Jian Yu Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 7 ++++--- drivers/staging/lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/llite/xattr.c | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 69b56a816fcb..02b57835ca04 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1363,7 +1363,8 @@ static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) } int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, - int flags, struct lov_user_md *lum, int lum_size) + __u64 flags, struct lov_user_md *lum, + int lum_size) { struct lov_stripe_md *lsm = NULL; struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags}; @@ -1487,7 +1488,7 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, static int ll_lov_setea(struct inode *inode, struct file *file, unsigned long arg) { - int flags = MDS_OPEN_HAS_OBJS | FMODE_WRITE; + __u64 flags = MDS_OPEN_HAS_OBJS | FMODE_WRITE; struct lov_user_md *lump; int lum_size = sizeof(struct lov_user_md) + sizeof(struct lov_user_ost_data); @@ -1521,7 +1522,7 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, struct lov_user_md_v1 __user *lumv1p = (void __user *)arg; struct lov_user_md_v3 __user *lumv3p = (void __user *)arg; int lum_size, rc; - int flags = FMODE_WRITE; + __u64 flags = FMODE_WRITE; /* first try with v1 which is smaller than v3 */ lum_size = sizeof(struct lov_user_md_v1); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 44ee7ce2ebea..2b8a85f22b34 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -745,7 +745,7 @@ struct posix_acl *ll_get_acl(struct inode *inode, int type); int ll_inode_permission(struct inode *inode, int mask); int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, - int flags, struct lov_user_md *lum, + __u64 flags, struct lov_user_md *lum, int lum_size); int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, struct lov_mds_md **lmm, int *lmm_size, diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index be5cb215ed81..37bc13e351b7 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -244,12 +244,12 @@ int ll_setxattr(struct dentry *dentry, const char *name, lump->lmm_stripe_offset = -1; if (lump && S_ISREG(inode->i_mode)) { - int flags = FMODE_WRITE; + __u64 it_flags = FMODE_WRITE; int lum_size = (lump->lmm_magic == LOV_USER_MAGIC_V1) ? sizeof(*lump) : sizeof(struct lov_user_md_v3); - rc = ll_lov_setstripe_ea_info(inode, dentry, flags, lump, - lum_size); + rc = ll_lov_setstripe_ea_info(inode, dentry, it_flags, + lump, lum_size); /* b10667: rc always be 0 here for now */ rc = 0; } else if (S_ISDIR(inode->i_mode)) { -- GitLab From 66fbe4ef96790b55b4218b0281cc26157993552b Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Mon, 4 Apr 2016 21:36:48 -0400 Subject: [PATCH 2150/9938] staging: lustre: libcfs: remove userland comments in libcfs_debug.h Remove comments about userland use. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3647 Reviewed-on: http://review.whamcloud.com/7243 Reviewed-by: John L. Hammond Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 98430e7108c1..7472a31433ff 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -85,7 +85,6 @@ struct ptldebug_header { #define PH_FLAG_FIRST_RECORD 1 /* Debugging subsystems (32 bits, non-overlapping) */ -/* keep these in sync with lnet/utils/debug.c and lnet/libcfs/debug.c */ #define S_UNDEFINED 0x00000001 #define S_MDC 0x00000002 #define S_MDS 0x00000004 @@ -118,10 +117,8 @@ struct ptldebug_header { #define S_MGS 0x20000000 #define S_FID 0x40000000 /* b_new_cmd */ #define S_FLD 0x80000000 /* b_new_cmd */ -/* keep these in sync with lnet/utils/debug.c and lnet/libcfs/debug.c */ /* Debugging masks (32 bits, non-overlapping) */ -/* keep these in sync with lnet/utils/debug.c and lnet/libcfs/debug.c */ #define D_TRACE 0x00000001 /* ENTRY/EXIT markers */ #define D_INODE 0x00000002 #define D_SUPER 0x00000004 @@ -151,7 +148,6 @@ struct ptldebug_header { #define D_QUOTA 0x04000000 #define D_SEC 0x08000000 #define D_LFSCK 0x10000000 /* For both OI scrub and LFSCK */ -/* keep these in sync with lnet/{utils,libcfs}/debug.c */ #define D_HSM D_TRACE -- GitLab From 6f11cd978e59551de52e018c7bf8fc9d6ae6366c Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Mon, 4 Apr 2016 21:36:49 -0400 Subject: [PATCH 2151/9938] staging: lustre: libcfs: create array of debug names Instead of a using a growing case statement to handle more debugging options create a array to map debug flags to string names. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3647 Reviewed-on: http://review.whamcloud.com/7243 Reviewed-by: John L. Hammond Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_debug.h | 13 ++ drivers/staging/lustre/lnet/libcfs/debug.c | 126 ++---------------- 2 files changed, 23 insertions(+), 116 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 7472a31433ff..5e60c6f50a16 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -118,6 +118,12 @@ struct ptldebug_header { #define S_FID 0x40000000 /* b_new_cmd */ #define S_FLD 0x80000000 /* b_new_cmd */ +#define LIBCFS_DEBUG_SUBSYS_NAMES { \ + "undefined", "mdc", "mds", "osc", "ost", "class", "log", \ + "llite", "rpc", "mgmt", "lnet", "lnd", "pinger", "filter", "", \ + "echo", "ldlm", "lov", "lquota", "osd", "lfsck", "", "", "lmv", \ + "", "sec", "gss", "", "mgc", "mgs", "fid", "fld", NULL } + /* Debugging masks (32 bits, non-overlapping) */ #define D_TRACE 0x00000001 /* ENTRY/EXIT markers */ #define D_INODE 0x00000002 @@ -151,6 +157,13 @@ struct ptldebug_header { #define D_HSM D_TRACE +#define LIBCFS_DEBUG_MASKS_NAMES { \ + "trace", "inode", "super", "ext2", "malloc", "cache", "info", \ + "ioctl", "neterror", "net", "warning", "buffs", "other", \ + "dentry", "nettrace", "page", "dlmtrace", "error", "emerg", \ + "ha", "rpctrace", "vfstrace", "reada", "mmap", "config", \ + "console", "quota", "sec", "lfsck", "hsm", NULL } + #define D_CANTMASK (D_ERROR | D_EMERG | D_WARNING | D_CONSOLE) #ifndef DEBUG_SUBSYSTEM diff --git a/drivers/staging/lustre/lnet/libcfs/debug.c b/drivers/staging/lustre/lnet/libcfs/debug.c index c3d628bac5b8..8c260c3d5da4 100644 --- a/drivers/staging/lustre/lnet/libcfs/debug.c +++ b/drivers/staging/lustre/lnet/libcfs/debug.c @@ -232,130 +232,24 @@ int libcfs_panic_in_progress; static const char * libcfs_debug_subsys2str(int subsys) { - switch (1 << subsys) { - default: + static const char *libcfs_debug_subsystems[] = LIBCFS_DEBUG_SUBSYS_NAMES; + + if (subsys >= ARRAY_SIZE(libcfs_debug_subsystems)) return NULL; - case S_UNDEFINED: - return "undefined"; - case S_MDC: - return "mdc"; - case S_MDS: - return "mds"; - case S_OSC: - return "osc"; - case S_OST: - return "ost"; - case S_CLASS: - return "class"; - case S_LOG: - return "log"; - case S_LLITE: - return "llite"; - case S_RPC: - return "rpc"; - case S_LNET: - return "lnet"; - case S_LND: - return "lnd"; - case S_PINGER: - return "pinger"; - case S_FILTER: - return "filter"; - case S_ECHO: - return "echo"; - case S_LDLM: - return "ldlm"; - case S_LOV: - return "lov"; - case S_LQUOTA: - return "lquota"; - case S_OSD: - return "osd"; - case S_LFSCK: - return "lfsck"; - case S_LMV: - return "lmv"; - case S_SEC: - return "sec"; - case S_GSS: - return "gss"; - case S_MGC: - return "mgc"; - case S_MGS: - return "mgs"; - case S_FID: - return "fid"; - case S_FLD: - return "fld"; - } + + return libcfs_debug_subsystems[subsys]; } /* libcfs_debug_token2mask() expects the returned string in lower-case */ static const char * libcfs_debug_dbg2str(int debug) { - switch (1 << debug) { - default: + static const char *libcfs_debug_masks[] = LIBCFS_DEBUG_MASKS_NAMES; + + if (debug >= ARRAY_SIZE(libcfs_debug_masks)) return NULL; - case D_TRACE: - return "trace"; - case D_INODE: - return "inode"; - case D_SUPER: - return "super"; - case D_EXT2: - return "ext2"; - case D_MALLOC: - return "malloc"; - case D_CACHE: - return "cache"; - case D_INFO: - return "info"; - case D_IOCTL: - return "ioctl"; - case D_NETERROR: - return "neterror"; - case D_NET: - return "net"; - case D_WARNING: - return "warning"; - case D_BUFFS: - return "buffs"; - case D_OTHER: - return "other"; - case D_DENTRY: - return "dentry"; - case D_NETTRACE: - return "nettrace"; - case D_PAGE: - return "page"; - case D_DLMTRACE: - return "dlmtrace"; - case D_ERROR: - return "error"; - case D_EMERG: - return "emerg"; - case D_HA: - return "ha"; - case D_RPCTRACE: - return "rpctrace"; - case D_VFSTRACE: - return "vfstrace"; - case D_READA: - return "reada"; - case D_MMAP: - return "mmap"; - case D_CONFIG: - return "config"; - case D_CONSOLE: - return "console"; - case D_QUOTA: - return "quota"; - case D_SEC: - return "sec"; - case D_LFSCK: - return "lfsck"; - } + + return libcfs_debug_masks[debug]; } int -- GitLab From 83c61a5c54b712e0aea9dba556e661575daf3fcc Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Mon, 4 Apr 2016 21:36:50 -0400 Subject: [PATCH 2152/9938] staging: lustre: libcfs: make D_HSM a unique value Redefine D_HSM. It was defined to D_TRACE. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3647 Reviewed-on: http://review.whamcloud.com/7243 Reviewed-by: John L. Hammond Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 5e60c6f50a16..455c54d0d17c 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -154,8 +154,7 @@ struct ptldebug_header { #define D_QUOTA 0x04000000 #define D_SEC 0x08000000 #define D_LFSCK 0x10000000 /* For both OI scrub and LFSCK */ - -#define D_HSM D_TRACE +#define D_HSM 0x20000000 #define LIBCFS_DEBUG_MASKS_NAMES { \ "trace", "inode", "super", "ext2", "malloc", "cache", "info", \ -- GitLab From ead028083510cd42abc9ae4d3847d53b54a19b15 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Mon, 4 Apr 2016 21:36:51 -0400 Subject: [PATCH 2153/9938] staging: lustre: hsm: Fix lu_ref for lease handle The lu_ref was not being decremented when releasing the lease handle. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3647 Reviewed-on: http://review.whamcloud.com/7243 Reviewed-by: John L. Hammond Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 4 ++-- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 02b57835ca04..000ea58fbdd6 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -908,7 +908,7 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, lock_res_and_lock(lock); cancelled = ldlm_is_cancel(lock); unlock_res_and_lock(lock); - ldlm_lock_put(lock); + LDLM_LOCK_PUT(lock); } CDEBUG(D_INODE, "lease for " DFID " broken? %d\n", @@ -2509,7 +2509,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = och->och_flags & (FMODE_READ | FMODE_WRITE); unlock_res_and_lock(lock); - ldlm_lock_put(lock); + LDLM_LOCK_PUT(lock); } } mutex_unlock(&lli->lli_och_mutex); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index be0acf7feee3..53cd56f286b7 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -454,7 +454,7 @@ static void mdc_hsm_release_pack(struct ptlrpc_request *req, lock = ldlm_handle2lock(&op_data->op_lease_handle); if (lock) { data->cd_handle = lock->l_remote_handle; - ldlm_lock_put(lock); + LDLM_LOCK_PUT(lock); } ldlm_cli_cancel(&op_data->op_lease_handle, LCF_LOCAL); -- GitLab From 18ecab0d95b0bb878cc7e22eb615cef21fcdd8eb Mon Sep 17 00:00:00 2001 From: JC Lafoucriere Date: Mon, 4 Apr 2016 21:36:52 -0400 Subject: [PATCH 2154/9938] staging: lustre: hsm: rename hai_zero() HSM function rename hai_zero() to hai_first(). Use a better name for hai helper Signed-off-by: JC Lafoucriere Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3709 Reviewed-on: http://review.whamcloud.com/7254 Reviewed-by: Jinshan Xiong Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_user.h | 6 +++--- drivers/staging/lustre/lustre/mdc/mdc_request.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 19f2271cc6b9..4672145587cd 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -1095,7 +1095,7 @@ struct hsm_action_list { __u32 padding1; char hal_fsname[0]; /* null-terminated */ /* struct hsm_action_item[hal_count] follows, aligned on 8-byte - * boundaries. See hai_zero + * boundaries. See hai_first */ } __packed; @@ -1109,7 +1109,7 @@ static inline int cfs_size_round(int val) #endif /* Return pointer to first hai in action list */ -static inline struct hsm_action_item *hai_zero(struct hsm_action_list *hal) +static inline struct hsm_action_item *hai_first(struct hsm_action_list *hal) { return (struct hsm_action_item *)(hal->hal_fsname + cfs_size_round(strlen(hal-> \ @@ -1131,7 +1131,7 @@ static inline int hal_size(struct hsm_action_list *hal) struct hsm_action_item *hai; sz = sizeof(*hal) + cfs_size_round(strlen(hal->hal_fsname) + 1); - hai = hai_zero(hal); + hai = hai_first(hal); for (i = 0; i < hal->hal_count; i++, hai = hai_next(hai)) sz += cfs_size_round(hai->hai_len); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index c458f28c1d89..6023c2c1386b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1952,7 +1952,7 @@ static void lustre_swab_hal(struct hsm_action_list *h) __swab32s(&h->hal_count); __swab32s(&h->hal_archive_id); __swab64s(&h->hal_flags); - hai = hai_zero(h); + hai = hai_first(h); for (i = 0; i < h->hal_count; i++, hai = hai_next(hai)) lustre_swab_hai(hai); } -- GitLab From c5300d55e2d5769ff4cffce3e667d991ed30eac8 Mon Sep 17 00:00:00 2001 From: Aurelien Degremont Date: Mon, 4 Apr 2016 21:36:53 -0400 Subject: [PATCH 2155/9938] staging: lustre: hsm: copy start error should set HP_FLAG_COMPLETED If an error occurs when initializing a HSM request, in ll_ioc_copy_start(), the PROGRESS message, sent to coordinator, should carry the error code but also HP_FLAG_COMPLETED to mark the request as finished (with error). If not, the Coordinator will ignore this message and consider the request is still running. Signed-off-by: Aurelien Degremont Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3685 Reviewed-on: http://review.whamcloud.com/7265 Reviewed-by: Jinshan Xiong Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index eb2e79ec37c0..955acd4cdd11 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -958,6 +958,9 @@ static int ll_ioc_copy_start(struct super_block *sb, struct hsm_copy *copy) } progress: + /* On error, the request should be considered as completed */ + if (hpk.hpk_errval > 0) + hpk.hpk_flags |= HP_FLAG_COMPLETED; rc = obd_iocontrol(LL_IOC_HSM_PROGRESS, sbi->ll_md_exp, sizeof(hpk), &hpk, NULL); -- GitLab From 98b29828b71b19963f3b818bdbc3e8b32ffaa761 Mon Sep 17 00:00:00 2001 From: Swapnil Pimpale Date: Mon, 4 Apr 2016 21:36:54 -0400 Subject: [PATCH 2156/9938] staging: lustre: lov: Get the correct address of lmm_objects The introduction of lmm_layout_gen makes the assumption that lmm_objects is present after lmm_stripe_count incorrect. Fixed this to get the correct address of lmm_objects when lmmk is cast to lov_mds_md_v1. Signed-off-by: Swapnil Pimpale Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3162 Reviewed-on: http://review.whamcloud.com/7258 Reviewed-by: John L. Hammond Reviewed-by: Andreas Dilger Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_pack.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 9723d2e091b1..d983a30b1e3a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -444,8 +444,7 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, if (lum.lmm_magic == LOV_USER_MAGIC) { /* User request for v1, we need skip lmm_pool_name */ if (lmmk->lmm_magic == LOV_MAGIC_V3) { - memmove((char *)(&lmmk->lmm_stripe_count) + - sizeof(lmmk->lmm_stripe_count), + memmove(((struct lov_mds_md_v1 *)lmmk)->lmm_objects, ((struct lov_mds_md_v3 *)lmmk)->lmm_objects, lmmk->lmm_stripe_count * sizeof(struct lov_ost_data_v1)); -- GitLab From 46dfb5aa980272230ceee48613aba5bd79951f33 Mon Sep 17 00:00:00 2001 From: Gaurav Mahajan Date: Mon, 4 Apr 2016 21:36:56 -0400 Subject: [PATCH 2157/9938] staging: lustre: llite: Delaying creation of client side proc entries. In client_common_fill_super() proc entries are created before before cl_sb_init() and therefore lu_site is not allocated resulting in client crash when tried reading lu_site stats. Delaying creation of proc entries after creation of all required data structures fixed the problem. Signed-off-by: Gaurav Mahajan Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2941 Reviewed-on: http://review.whamcloud.com/6852 Reviewed-by: Andreas Dilger Reviewed-by: Emoly Liu Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index c04d3776a952..b0948a7b860b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -166,12 +166,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, return -ENOMEM; } - if (llite_root) { - err = ldebugfs_register_mountpoint(llite_root, sb, dt, md); - if (err < 0) - CERROR("could not register mount in /lustre/llite\n"); - } - /* indicate the features supported by this client */ data->ocd_connect_flags = OBD_CONNECT_IBITS | OBD_CONNECT_NODEVOH | OBD_CONNECT_ATTRFID | @@ -552,6 +546,15 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, kfree(data); kfree(osfs); + if (llite_root) { + err = ldebugfs_register_mountpoint(llite_root, sb, dt, md); + if (err < 0) { + CERROR("%s: could not register mount in debugfs: " + "rc = %d\n", ll_get_fsname(sb, NULL, 0), err); + err = 0; + } + } + return err; out_root: iput(root); @@ -570,7 +573,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, out: kfree(data); kfree(osfs); - ldebugfs_unregister_mountpoint(sbi); return err; } -- GitLab From 6a1938d95822f7a160100845035bdc19c5c72182 Mon Sep 17 00:00:00 2001 From: Ned Bass Date: Mon, 4 Apr 2016 21:36:57 -0400 Subject: [PATCH 2158/9938] staging: lustre: mdc: document mdc_rpc_lock As this lock can be a bottleneck, clarifying why it is needed may be helpful to those working on client performance. Signed-off-by: Ned Bass Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3443 Reviewed-on: http://review.whamcloud.com/6593 Reviewed-by: Andreas Dilger Reviewed-by: Keith Mannthey Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/lustre_mdc.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index af77eb359c43..f267ff8a6ec8 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -64,9 +64,27 @@ struct obd_export; struct ptlrpc_request; struct obd_device; +/** + * Serializes in-flight MDT-modifying RPC requests to preserve idempotency. + * + * This mutex is used to implement execute-once semantics on the MDT. + * The MDT stores the last transaction ID and result for every client in + * its last_rcvd file. If the client doesn't get a reply, it can safely + * resend the request and the MDT will reconstruct the reply being aware + * that the request has already been executed. Without this lock, + * execution status of concurrent in-flight requests would be + * overwritten. + * + * This design limits the extent to which we can keep a full pipeline of + * in-flight requests from a single client. This limitation could be + * overcome by allowing multiple slots per client in the last_rcvd file. + */ struct mdc_rpc_lock { + /** Lock protecting in-flight RPC concurrency. */ struct mutex rpcl_mutex; + /** Intent associated with currently executing request. */ struct lookup_intent *rpcl_it; + /** Used for MDS/RPC load testing purposes. */ int rpcl_fakes; }; -- GitLab From a7a9ed4b5d2732f35c54601702d73c1cd1e7ee90 Mon Sep 17 00:00:00 2001 From: JC Lafoucriere Date: Mon, 4 Apr 2016 21:36:58 -0400 Subject: [PATCH 2159/9938] staging: lustre: hsm: Add CLF_RENAME_LAST flag Create a special flag for the last rename event. Signed-off-by: JC Lafoucriere Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3718 Reviewed-on: http://review.whamcloud.com/7260 Reviewed-by: Jinshan Xiong Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_user.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 4672145587cd..e4e42e1ce656 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -676,7 +676,12 @@ static inline const char *changelog_type2str(int type) #define CLF_UNLINK_HSM_EXISTS 0x0002 /* File has something in HSM */ /* HSM cleaning needed */ /* Flags for rename */ -#define CLF_RENAME_LAST 0x0001 /* rename unlink last hardlink of target */ +#define CLF_RENAME_LAST 0x0001 /* rename unlink last hardlink of + * target + */ +#define CLF_RENAME_LAST_EXISTS 0x0002 /* rename unlink last hardlink of target + * has an archive in backend + */ /* Flags for HSM */ /* 12b used (from high weight to low weight): -- GitLab From 0fcd869f9e0947ddb22ba8ba197cbe43e39f97f3 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Mon, 4 Apr 2016 21:36:59 -0400 Subject: [PATCH 2160/9938] staging: lustre: fix 'NULL pointer dereference' errors Fix 'NULL pointer dereference' defects found by Coverity version 6.5.0: Dereference after null check (FORWARD_NULL) For instance, Passing null pointer to a function which dereferences it. Dereference before null check (REVERSE_INULL) Null-checking variable suggests that it may be null, but it has already been dereferenced on all paths leading to the check. Dereference null return value (NULL_RETURNS) Signed-off-by: Sebastien Buisson Signed-off-by: James Nunez Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3042 Reviewed-on: http://review.whamcloud.com/5868 Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 10 ++++++---- drivers/staging/lustre/lustre/lov/lov_io.c | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 955acd4cdd11..7736139141cd 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -611,15 +611,16 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) struct inode *inode = file_inode(filp); struct ll_file_data *lfd = LUSTRE_FPRIVATE(filp); struct ll_sb_info *sbi = ll_i2sbi(inode); + __u64 pos = lfd ? lfd->lfd_pos : 0; int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; int api32 = ll_need_32bit_api(sbi); int rc; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %lu/%llu 32bit_api %d\n", inode->i_ino, inode->i_generation, - inode, (unsigned long)lfd->lfd_pos, i_size_read(inode), api32); + inode, (unsigned long)pos, i_size_read(inode), api32); - if (lfd->lfd_pos == MDS_DIR_END_OFF) { + if (pos == MDS_DIR_END_OFF) { /* * end-of-file. */ @@ -627,9 +628,10 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) goto out; } - ctx->pos = lfd->lfd_pos; + ctx->pos = pos; rc = ll_dir_read(inode, ctx); - lfd->lfd_pos = ctx->pos; + if (lfd) + lfd->lfd_pos = ctx->pos; if (ctx->pos == MDS_DIR_END_OFF) { if (api32) ctx->pos = LL_DIR_END_OFF_32BIT; diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index f443778c83fd..da4784b474e4 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -277,10 +277,11 @@ struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio, static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio, struct cl_io *io) { - struct lov_stripe_md *lsm = lio->lis_object->lo_lsm; + struct lov_stripe_md *lsm; int result; LASSERT(lio->lis_object); + lsm = lio->lis_object->lo_lsm; /* * Need to be optimized, we can't afford to allocate a piece of memory -- GitLab From e55a68b6ea623a501cfe5b74d63f5faa77281701 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Mon, 4 Apr 2016 21:37:00 -0400 Subject: [PATCH 2161/9938] staging: lustre: llite: cancel open lock before closing file In error handling path of ll_lease_open(), och has already been freed in ll_close_inode_openhandle() so the sequence of cancel open lock and close open handle need adjusting. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3647 Reviewed-on: http://review.whamcloud.com/7346 Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 000ea58fbdd6..ac1736092256 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -875,16 +875,19 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, return och; out_close: - rc2 = ll_close_inode_openhandle(sbi->ll_md_exp, inode, och, NULL); - if (rc2) - CERROR("Close openhandle returned %d\n", rc2); - - /* cancel open lock */ + /* Cancel open lock */ if (it.d.lustre.it_lock_mode != 0) { ldlm_lock_decref_and_cancel(&och->och_lease_handle, it.d.lustre.it_lock_mode); it.d.lustre.it_lock_mode = 0; + och->och_lease_handle.cookie = 0ULL; } + rc2 = ll_close_inode_openhandle(sbi->ll_md_exp, inode, och, NULL); + if (rc2 < 0) + CERROR("%s: error closing file "DFID": %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(&ll_i2info(inode)->lli_fid), rc2); + och = NULL; /* och has been freed in ll_close_inode_openhandle() */ out_release_it: ll_intent_release(&it); out: -- GitLab From e179800665228cc8126ddc8b052a57d0155d09f1 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Mon, 4 Apr 2016 21:37:01 -0400 Subject: [PATCH 2162/9938] staging: lustre: hsm: Add support to drop all pages for ll_data_version This will be used by HSM release to get data version and drop all caching pages from all clients, before sending IT_RELEASE close REQ to MDT. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3647 Reviewed-on: http://review.whamcloud.com/6794 Reviewed-by: John L. Hammond Reviewed-by: Aurelien Degremont Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 1 + .../lustre/include/lustre/lustre_user.h | 5 ++- drivers/staging/lustre/lustre/llite/dir.c | 5 ++- drivers/staging/lustre/lustre/llite/file.c | 35 +++++++++++-------- .../lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/lov/lov_merge.c | 11 ++++++ 6 files changed, 38 insertions(+), 21 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 23cbdd3bed8e..c3565bf0e1fb 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1429,6 +1429,7 @@ enum obdo_flags { */ OBD_FL_RECOV_RESEND = 0x00080000, /* recoverable resent */ OBD_FL_NOSPC_BLK = 0x00100000, /* no more block space on OST */ + OBD_FL_FLUSH = 0x00200000, /* flush pages on the OST */ /* Note that while these checksum values are currently separate bits, * in 2.x we can actually allow all values from 1-31 if we wanted. diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index e4e42e1ce656..59ba48ac31a7 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -838,9 +838,8 @@ struct ioc_data_version { __u64 idv_flags; /* See LL_DV_xxx */ }; -#define LL_DV_NOFLUSH 0x01 /* Do not take READ EXTENT LOCK before sampling - * version. Dirty caches are left unchanged. - */ +#define LL_DV_RD_FLUSH BIT(0) /* Flush dirty pages from clients */ +#define LL_DV_WR_FLUSH BIT(1) /* Flush all caching pages from clients */ #ifndef offsetof # define offsetof(typ, memb) ((unsigned long)((char *)&(((typ *)0)->memb))) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 7736139141cd..2f0873ee7824 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -940,7 +940,7 @@ static int ll_ioc_copy_start(struct super_block *sb, struct hsm_copy *copy) } /* Read current file data version */ - rc = ll_data_version(inode, &data_version, 1); + rc = ll_data_version(inode, &data_version, LL_DV_RD_FLUSH); iput(inode); if (rc != 0) { CDEBUG(D_HSM, "Could not read file data version of " @@ -1024,8 +1024,7 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy) goto progress; } - rc = ll_data_version(inode, &data_version, - copy->hc_hai.hai_action == HSMA_ARCHIVE); + rc = ll_data_version(inode, &data_version, LL_DV_RD_FLUSH); iput(inode); if (rc) { CDEBUG(D_HSM, "Could not read file data version. Request could not be confirmed.\n"); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index ac1736092256..9b553d2ab336 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -929,7 +929,7 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, /* Fills the obdo with the attributes for the lsm */ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, - struct obdo *obdo, __u64 ioepoch, int sync) + struct obdo *obdo, __u64 ioepoch, int dv_flags) { struct ptlrpc_request_set *set; struct obd_info oinfo = { }; @@ -948,9 +948,11 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLGROUP | OBD_MD_FLEPOCH | OBD_MD_FLDATAVERSION; - if (sync) { + if (dv_flags & (LL_DV_WR_FLUSH | LL_DV_RD_FLUSH)) { oinfo.oi_oa->o_valid |= OBD_MD_FLFLAGS; oinfo.oi_oa->o_flags |= OBD_FL_SRVLOCK; + if (dv_flags & LL_DV_WR_FLUSH) + oinfo.oi_oa->o_flags |= OBD_FL_FLUSH; } set = ptlrpc_prep_set(); @@ -963,11 +965,16 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, rc = ptlrpc_set_wait(set); ptlrpc_set_destroy(set); } - if (rc == 0) + if (rc == 0) { oinfo.oi_oa->o_valid &= (OBD_MD_FLBLOCKS | OBD_MD_FLBLKSZ | OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLSIZE | - OBD_MD_FLDATAVERSION); + OBD_MD_FLDATAVERSION | OBD_MD_FLFLAGS); + if (dv_flags & LL_DV_WR_FLUSH && + !(oinfo.oi_oa->o_valid & OBD_MD_FLFLAGS && + oinfo.oi_oa->o_flags & OBD_FL_FLUSH)) + return -ENOTSUPP; + } return rc; } @@ -983,7 +990,7 @@ int ll_inode_getattr(struct inode *inode, struct obdo *obdo, lsm = ccc_inode_lsm_get(inode); rc = ll_lsm_getattr(lsm, ll_i2dtexp(inode), - obdo, ioepoch, sync); + obdo, ioepoch, sync ? LL_DV_RD_FLUSH : 0); if (rc == 0) { struct ost_id *oi = lsm ? &lsm->lsm_oi : &obdo->o_oi; @@ -1874,11 +1881,12 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg) * This value is computed using stripe object version on OST. * Version is computed using server side locking. * - * @param extent_lock Take extent lock. Not needed if a process is already - * holding the OST object group locks. + * @param sync if do sync on the OST side; + * 0: no sync + * LL_DV_RD_FLUSH: flush dirty pages, LCK_PR on OSTs + * LL_DV_WR_FLUSH: drop all caching pages, LCK_PW on OSTs */ -int ll_data_version(struct inode *inode, __u64 *data_version, - int extent_lock) +int ll_data_version(struct inode *inode, __u64 *data_version, int flags) { struct lov_stripe_md *lsm = NULL; struct ll_sb_info *sbi = ll_i2sbi(inode); @@ -1900,7 +1908,7 @@ int ll_data_version(struct inode *inode, __u64 *data_version, goto out; } - rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, obdo, 0, extent_lock); + rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, obdo, 0, flags); if (rc == 0) { if (!(obdo->o_valid & OBD_MD_FLDATAVERSION)) rc = -EOPNOTSUPP; @@ -1936,7 +1944,7 @@ int ll_hsm_release(struct inode *inode) } /* Grab latest data_version and [am]time values */ - rc = ll_data_version(inode, &data_version, 1); + rc = ll_data_version(inode, &data_version, LL_DV_WR_FLUSH); if (rc != 0) goto out; @@ -2344,9 +2352,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (copy_from_user(&idv, (char __user *)arg, sizeof(idv))) return -EFAULT; - rc = ll_data_version(inode, &idv.idv_version, - !(idv.idv_flags & LL_DV_NOFLUSH)); - + idv.idv_flags &= LL_DV_RD_FLUSH | LL_DV_WR_FLUSH; + rc = ll_data_version(inode, &idv.idv_version, idv.idv_flags); if (rc == 0 && copy_to_user((char __user *)arg, &idv, sizeof(idv))) return -EFAULT; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 2b8a85f22b34..2a11664325ef 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -757,7 +757,7 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, int ll_fsync(struct file *file, loff_t start, loff_t end, int data); int ll_merge_attr(const struct lu_env *env, struct inode *inode); int ll_fid2path(struct inode *inode, void __user *arg); -int ll_data_version(struct inode *inode, __u64 *data_version, int extent_lock); +int ll_data_version(struct inode *inode, __u64 *data_version, int flags); int ll_hsm_release(struct inode *inode); /* llite/dcache.c */ diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c index 029cd4d62796..56ef41d17ad7 100644 --- a/drivers/staging/lustre/lustre/lov/lov_merge.c +++ b/drivers/staging/lustre/lustre/lov/lov_merge.c @@ -154,6 +154,7 @@ void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, valid &= src->o_valid; if (*set) { + tgt->o_valid &= valid; if (valid & OBD_MD_FLSIZE) { /* this handles sparse files properly */ u64 lov_size; @@ -172,12 +173,22 @@ void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, tgt->o_mtime = src->o_mtime; if (valid & OBD_MD_FLDATAVERSION) tgt->o_data_version += src->o_data_version; + + /* handle flags */ + if (valid & OBD_MD_FLFLAGS) + tgt->o_flags &= src->o_flags; + else + tgt->o_flags = 0; } else { memcpy(tgt, src, sizeof(*tgt)); tgt->o_oi = lsm->lsm_oi; + tgt->o_valid = valid; if (valid & OBD_MD_FLSIZE) tgt->o_size = lov_stripe_size(lsm, src->o_size, stripeno); + tgt->o_flags = 0; + if (valid & OBD_MD_FLFLAGS) + tgt->o_flags = src->o_flags; } /* data_version needs to be valid on all stripes to be correct! */ -- GitLab From 19c551482ad620336afb724bb6cfcf1720fa545c Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Mon, 4 Apr 2016 21:37:02 -0400 Subject: [PATCH 2163/9938] staging: lustre: fix 'no effect' errors Fix 'no effect' issues found by Coverity version 6.5.1: Unsigned compared against 0 (NO_EFFECT) This greater-than-or-equal-to-zero comparison of an unsigned value is always true. Remove useless cast. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3907 Reviewed-on: http://review.whamcloud.com/7166 Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/xattr.c | 3 +-- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 37bc13e351b7..9f6fcfe8b988 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -424,8 +424,7 @@ int ll_getxattr_common(struct inode *inode, const char *name, if (rce && rce->rce_ops == RMT_LSETFACL) { ext_acl_xattr_header *acl; - acl = lustre_posix_acl_xattr_2ext( - (posix_acl_xattr_header *)buffer, rc); + acl = lustre_posix_acl_xattr_2ext(buffer, rc); if (IS_ERR(acl)) { rc = PTR_ERR(acl); goto out; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index a3967771ae07..2f6457f5e98c 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -926,7 +926,7 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, struct obd_quotactl *oqctl; if (qctl->qc_valid == QC_MDTIDX) { - if (qctl->qc_idx < 0 || count <= qctl->qc_idx) + if (count <= qctl->qc_idx) return -EINVAL; tgt = lmv->tgts[qctl->qc_idx]; -- GitLab From d7e2ee257038baeb03baef602500368a51ee9eef Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 11 Apr 2016 13:51:03 +0200 Subject: [PATCH 2164/9938] spi: let SPI masters ignore their children for PM Let all SPI masters ignore their children: when it comes to power management: SPI children have no business doing keeping their parents awake: they are completely autonomous devices that just use their parent to talk, and the latter usecase must be power managed by the host itself on a per-message basis. Reviewed-by: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index de2f2f90d799..6c4c050e6b65 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1764,6 +1764,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size) master->num_chipselect = 1; master->dev.class = &spi_master_class; master->dev.parent = dev; + pm_suspend_ignore_children(&master->dev, true); spi_master_set_devdata(master, &master[1]); return master; -- GitLab From 0888f388e6ac44530473a5abc59ecb1efbc3fe23 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 5 Apr 2016 20:15:34 +0530 Subject: [PATCH 2165/9938] staging/lustre/obdclass: fix build warning While building with W=1 we were getting the warning: drivers/staging/lustre/lustre/obdclass/cl_object.c:1056:16: warning: old-style function definition struct lu_env *cl_env_percpu_get() ^ Signed-off-by: Sudip Mukherjee Acked-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/cl_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index a068e08b2031..5940f30318ec 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -1055,7 +1055,7 @@ void cl_env_percpu_put(struct lu_env *env) } EXPORT_SYMBOL(cl_env_percpu_put); -struct lu_env *cl_env_percpu_get() +struct lu_env *cl_env_percpu_get(void) { struct cl_env *cle; -- GitLab From c22594f6b13193c6f00c31eb8bee9ee05cae16da Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:27 -0400 Subject: [PATCH 2166/9938] staging: lustre: selftest: convert srpc_event_type to proper enum Turn tyepdef srpc_event_type to proper enum Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/selftest.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 4ffadf41e445..1cd5688bb7aa 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -134,7 +134,7 @@ srpc_service2reply(int service) return srpc_service2request(service) + 1; } -typedef enum { +enum srpc_event_type { SRPC_BULK_REQ_RCVD = 1, /* passive bulk request(PUT sink/GET source) * received */ SRPC_BULK_PUT_SENT = 2, /* active bulk PUT sent (source) */ @@ -143,11 +143,11 @@ typedef enum { SRPC_REPLY_SENT = 5, /* outgoing reply sent */ SRPC_REQUEST_RCVD = 6, /* incoming request received */ SRPC_REQUEST_SENT = 7, /* outgoing request sent */ -} srpc_event_type_t; +}; /* RPC event */ typedef struct { - srpc_event_type_t ev_type; /* what's up */ + enum srpc_event_type ev_type; /* what's up */ lnet_event_kind_t ev_lnet; /* LNet event type */ int ev_fired; /* LNet event fired? */ int ev_status; /* LNet event status */ -- GitLab From 8607338f3d9efd7be18b844ac087590e391f653a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:28 -0400 Subject: [PATCH 2167/9938] staging: lustre: selftest: convert srpc_event_t to proper struct Turn typedef srpc_event_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/rpc.c | 20 +++++++++---------- .../staging/lustre/lnet/selftest/selftest.h | 14 ++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index dc10e01a42d6..8d7c0a06c0f8 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -357,7 +357,7 @@ srpc_remove_service(srpc_service_t *sv) static int srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf, int len, int options, lnet_process_id_t peer, - lnet_handle_md_t *mdh, srpc_event_t *ev) + lnet_handle_md_t *mdh, struct srpc_event *ev) { int rc; lnet_md_t md; @@ -396,7 +396,7 @@ srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf, static int srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, int options, lnet_process_id_t peer, lnet_nid_t self, - lnet_handle_md_t *mdh, srpc_event_t *ev) + lnet_handle_md_t *mdh, struct srpc_event *ev) { int rc; lnet_md_t md; @@ -449,7 +449,7 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, static int srpc_post_passive_rqtbuf(int service, int local, void *buf, int len, - lnet_handle_md_t *mdh, srpc_event_t *ev) + lnet_handle_md_t *mdh, struct srpc_event *ev) { lnet_process_id_t any = { 0 }; @@ -794,7 +794,7 @@ srpc_shutdown_service(srpc_service_t *sv) static int srpc_send_request(srpc_client_rpc_t *rpc) { - srpc_event_t *ev = &rpc->crpc_reqstev; + struct srpc_event *ev = &rpc->crpc_reqstev; int rc; ev->ev_fired = 0; @@ -816,7 +816,7 @@ srpc_send_request(srpc_client_rpc_t *rpc) static int srpc_prepare_reply(srpc_client_rpc_t *rpc) { - srpc_event_t *ev = &rpc->crpc_replyev; + struct srpc_event *ev = &rpc->crpc_replyev; __u64 *id = &rpc->crpc_reqstmsg.msg_body.reqst.rpyid; int rc; @@ -841,7 +841,7 @@ static int srpc_prepare_bulk(srpc_client_rpc_t *rpc) { srpc_bulk_t *bk = &rpc->crpc_bulk; - srpc_event_t *ev = &rpc->crpc_bulkev; + struct srpc_event *ev = &rpc->crpc_bulkev; __u64 *id = &rpc->crpc_reqstmsg.msg_body.reqst.bulkid; int rc; int opt; @@ -873,7 +873,7 @@ srpc_prepare_bulk(srpc_client_rpc_t *rpc) static int srpc_do_bulk(struct srpc_server_rpc *rpc) { - srpc_event_t *ev = &rpc->srpc_ev; + struct srpc_event *ev = &rpc->srpc_ev; srpc_bulk_t *bk = rpc->srpc_bulk; __u64 id = rpc->srpc_reqstbuf->buf_msg.msg_body.reqst.bulkid; int rc; @@ -968,7 +968,7 @@ srpc_handle_rpc(swi_workitem_t *wi) struct srpc_server_rpc *rpc = wi->swi_workitem.wi_data; struct srpc_service_cd *scd = rpc->srpc_scd; struct srpc_service *sv = scd->scd_svc; - srpc_event_t *ev = &rpc->srpc_ev; + struct srpc_event *ev = &rpc->srpc_ev; int rc = 0; LASSERT(wi == &rpc->srpc_wi); @@ -1363,7 +1363,7 @@ srpc_post_rpc(srpc_client_rpc_t *rpc) int srpc_send_reply(struct srpc_server_rpc *rpc) { - srpc_event_t *ev = &rpc->srpc_ev; + struct srpc_event *ev = &rpc->srpc_ev; struct srpc_msg *msg = &rpc->srpc_replymsg; struct srpc_buffer *buffer = rpc->srpc_reqstbuf; struct srpc_service_cd *scd = rpc->srpc_scd; @@ -1410,7 +1410,7 @@ static void srpc_lnet_ev_handler(lnet_event_t *ev) { struct srpc_service_cd *scd; - srpc_event_t *rpcev = ev->md.user_ptr; + struct srpc_event *rpcev = ev->md.user_ptr; srpc_client_rpc_t *crpc; struct srpc_server_rpc *srpc; srpc_buffer_t *buffer; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 1cd5688bb7aa..3411e33c0938 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -146,13 +146,13 @@ enum srpc_event_type { }; /* RPC event */ -typedef struct { +struct srpc_event { enum srpc_event_type ev_type; /* what's up */ lnet_event_kind_t ev_lnet; /* LNet event type */ int ev_fired; /* LNet event fired? */ int ev_status; /* LNet event status */ void *ev_data; /* owning server/client RPC */ -} srpc_event_t; +}; typedef struct { int bk_len; /* len of bulk data */ @@ -187,7 +187,7 @@ struct srpc_server_rpc { struct list_head srpc_list; struct srpc_service_cd *srpc_scd; swi_workitem_t srpc_wi; - srpc_event_t srpc_ev; /* bulk/reply event */ + struct srpc_event srpc_ev; /* bulk/reply event */ lnet_nid_t srpc_self; lnet_process_id_t srpc_peer; srpc_msg_t srpc_replymsg; @@ -221,9 +221,9 @@ typedef struct srpc_client_rpc { unsigned int crpc_closed:1; /* completed */ /* RPC events */ - srpc_event_t crpc_bulkev; /* bulk event */ - srpc_event_t crpc_reqstev; /* request event */ - srpc_event_t crpc_replyev; /* reply event */ + struct srpc_event crpc_bulkev; /* bulk event */ + struct srpc_event crpc_reqstev; /* request event */ + struct srpc_event crpc_replyev; /* reply event */ /* bulk, request(reqst), and reply exchanged on wire */ srpc_msg_t crpc_reqstmsg; @@ -266,7 +266,7 @@ struct srpc_service_cd { /** backref to service */ struct srpc_service *scd_svc; /** event buffer */ - srpc_event_t scd_ev; + struct srpc_event scd_ev; /** free RPC descriptors */ struct list_head scd_rpc_free; /** in-flight RPCs */ -- GitLab From 44f948bdb175bf326911c9ba0e47389918161ce5 Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 7 Apr 2016 11:25:33 +0200 Subject: [PATCH 2168/9938] ASoC: sti: helper functions for unip tdm slots configuration - sti_uniperiph_set_tdm_slot: store tdm slot config in unip context - sti_uniperiph_get_tdm_word_pos: configure unip tdm slots pos regs Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/sti_uniperif.c | 90 ++++++++++++++++++++++++++++++++++++ sound/soc/sti/uniperif.h | 23 +++++++++ 2 files changed, 113 insertions(+) diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index 39bcefe5eea0..0c2474c16c11 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c @@ -10,6 +10,96 @@ #include "uniperif.h" +/* + * User frame size shall be 2, 4, 6 or 8 32-bits words length + * (i.e. 8, 16, 24 or 32 bytes) + * This constraint comes from allowed values for + * UNIPERIF_I2S_FMT_NUM_CH register + */ +#define UNIPERIF_MAX_FRAME_SZ 0x20 +#define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ) + +int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, + int slot_width) +{ + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); + struct uniperif *uni = priv->dai_data.uni; + int i, frame_size, avail_slots; + + if (!UNIPERIF_TYPE_IS_TDM(uni)) { + dev_err(uni->dev, "cpu dai not in tdm mode\n"); + return -EINVAL; + } + + /* store info in unip context */ + uni->tdm_slot.slots = slots; + uni->tdm_slot.slot_width = slot_width; + /* unip is unidirectionnal */ + uni->tdm_slot.mask = (tx_mask != 0) ? tx_mask : rx_mask; + + /* number of available timeslots */ + for (i = 0, avail_slots = 0; i < uni->tdm_slot.slots; i++) { + if ((uni->tdm_slot.mask >> i) & 0x01) + avail_slots++; + } + uni->tdm_slot.avail_slots = avail_slots; + + /* frame size in bytes */ + frame_size = uni->tdm_slot.avail_slots * uni->tdm_slot.slot_width / 8; + + /* check frame size is allowed */ + if ((frame_size > UNIPERIF_MAX_FRAME_SZ) || + (frame_size & ~(int)UNIPERIF_ALLOWED_FRAME_SZ)) { + dev_err(uni->dev, "frame size not allowed: %d bytes\n", + frame_size); + return -EINVAL; + } + + return 0; +} + +int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni, + unsigned int *word_pos) +{ + int slot_width = uni->tdm_slot.slot_width / 8; + int slots_num = uni->tdm_slot.slots; + unsigned int slots_mask = uni->tdm_slot.mask; + int i, j, k; + unsigned int word16_pos[4]; + + /* word16_pos: + * word16_pos[0] = WORDX_LSB + * word16_pos[1] = WORDX_MSB, + * word16_pos[2] = WORDX+1_LSB + * word16_pos[3] = WORDX+1_MSB + */ + + /* set unip word position */ + for (i = 0, j = 0, k = 0; (i < slots_num) && (k < WORD_MAX); i++) { + if ((slots_mask >> i) & 0x01) { + word16_pos[j] = i * slot_width; + + if (slot_width == 4) { + word16_pos[j + 1] = word16_pos[j] + 2; + j++; + } + j++; + + if (j > 3) { + word_pos[k] = word16_pos[1] | + (word16_pos[0] << 8) | + (word16_pos[3] << 16) | + (word16_pos[2] << 24); + j = 0; + k++; + } + } + } + + return 0; +} + /* * sti_uniperiph_dai_create_ctrl * This function is used to create Ctrl associated to DAI but also pcm device. diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index 750eb5a07e6c..fb8e427754b6 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1270,6 +1270,14 @@ enum uniperif_iec958_encoding_mode { UNIPERIF_IEC958_ENCODING_MODE_ENCODED }; +enum uniperif_word_pos { + WORD_1_2, + WORD_3_4, + WORD_5_6, + WORD_7_8, + WORD_MAX +}; + struct uniperif_info { int id; /* instance value of the uniperipheral IP */ enum uniperif_type type; @@ -1281,6 +1289,13 @@ struct uniperif_iec958_settings { struct snd_aes_iec958 iec958; }; +struct dai_tdm_slot { + unsigned int mask; + int slots; + int slot_width; + unsigned int avail_slots; +}; + struct uniperif { /* System information */ struct uniperif_info *info; @@ -1317,6 +1332,7 @@ struct uniperif { /* dai properties */ unsigned int daifmt; + struct dai_tdm_slot tdm_slot; /* DAI callbacks */ const struct snd_soc_dai_ops *dai_ops; @@ -1373,4 +1389,11 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); +int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, + int slot_width); + +int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni, + unsigned int *word_pos); + #endif -- GitLab From 72199787662612a7747248f8b56bc5d42694538f Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 7 Apr 2016 11:25:34 +0200 Subject: [PATCH 2169/9938] ASoC: sti: helper functions to fix tdm runtime params Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/sti_uniperif.c | 46 ++++++++++++++++++++++++++++++++++++ sound/soc/sti/uniperif.h | 6 +++++ 2 files changed, 52 insertions(+) diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index 0c2474c16c11..d49badec9e62 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c @@ -59,6 +59,52 @@ int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, return 0; } +int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct uniperif *uni = rule->private; + struct snd_interval t; + + t.min = uni->tdm_slot.avail_slots; + t.max = uni->tdm_slot.avail_slots; + t.openmin = 0; + t.openmax = 0; + t.integer = 0; + + return snd_interval_refine(hw_param_interval(params, rule->var), &t); +} + +int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct uniperif *uni = rule->private; + struct snd_mask *maskp = hw_param_mask(params, rule->var); + u64 format; + + switch (uni->tdm_slot.slot_width) { + case 16: + format = SNDRV_PCM_FMTBIT_S16_LE; + break; + case 32: + format = SNDRV_PCM_FMTBIT_S32_LE; + break; + default: + dev_err(uni->dev, "format not supported: %d bits\n", + uni->tdm_slot.slot_width); + return -EINVAL; + } + + maskp->bits[0] &= (u_int32_t)format; + maskp->bits[1] &= (u_int32_t)(format >> 32); + /* clear remaining indexes */ + memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX - 64) / 8); + + if (!maskp->bits[0] && !maskp->bits[1]) + return -EINVAL; + + return 0; +} + int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni, unsigned int *word_pos) { diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index fb8e427754b6..17d5d1030741 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1396,4 +1396,10 @@ int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni, unsigned int *word_pos); +int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule); + +int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule); + #endif -- GitLab From 8d8b1e2eddaef25ca0a18500dd9425638f1cfd02 Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 7 Apr 2016 11:25:35 +0200 Subject: [PATCH 2170/9938] ASoC: sti: unip player tdm mode here are the changes to enable player tdm mode: - When TDM_ENABLE is set to 1, the i2s format should be automatically configured. Unfortunately this is not the case (HW bug). Then, we shall force DATA_SIZE setting. - Compute the transfer size for tdm mode: transfer size = user frame size - Manage tdm slots configuration given in DT. - Don't use mclk-fs when unip in tdm mode; use tdm slot config to compute frame size and to set mclk rate. - Refine the hw param (channels & format) according to tdm slot config. Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/sti_uniperif.c | 8 ++- sound/soc/sti/uniperif.h | 11 ++++ sound/soc/sti/uniperif_player.c | 109 +++++++++++++++++++++++++++----- 3 files changed, 110 insertions(+), 18 deletions(-) diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index d49badec9e62..488ef4ed8fba 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c @@ -181,10 +181,16 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); + struct uniperif *uni = priv->dai_data.uni; struct snd_dmaengine_dai_dma_data *dma_data; int transfer_size; - transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; + if (uni->info->type == SND_ST_UNIPERIF_TYPE_TDM) + /* transfer size = user frame size (in 32-bits FIFO cell) */ + transfer_size = snd_soc_params_to_frame_size(params) / 32; + else + transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; dma_data = snd_soc_dai_get_dma_data(dai, substream); dma_data->maxburst = transfer_size; diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index 17d5d1030741..d0e24468478c 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1389,6 +1389,17 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); +static inline int sti_uniperiph_get_user_frame_size( + struct snd_pcm_runtime *runtime) +{ + return (runtime->channels * snd_pcm_format_width(runtime->format) / 8); +} + +static inline int sti_uniperiph_get_unip_tdm_frame_size(struct uniperif *uni) +{ + return (uni->tdm_slot.slots * uni->tdm_slot.slot_width / 8); +} + int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index ab4310a1615e..ff2d73597ce3 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -435,18 +435,11 @@ static int uni_player_prepare_pcm(struct uniperif *player, /* Force slot width to 32 in I2S mode (HW constraint) */ if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == - SND_SOC_DAIFMT_I2S) { + SND_SOC_DAIFMT_I2S) slot_width = 32; - } else { - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - slot_width = 16; - break; - default: - slot_width = 32; - break; - } - } + else + slot_width = snd_pcm_format_width(runtime->format); + output_frame_size = slot_width * runtime->channels; clk_div = player->mclk / runtime->rate; @@ -521,7 +514,6 @@ static int uni_player_prepare_pcm(struct uniperif *player, SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); - SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(player); /* No iec958 formatting as outputting to DAC */ SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); @@ -529,6 +521,55 @@ static int uni_player_prepare_pcm(struct uniperif *player, return 0; } +static int uni_player_prepare_tdm(struct uniperif *player, + struct snd_pcm_runtime *runtime) +{ + int tdm_frame_size; /* unip tdm frame size in bytes */ + int user_frame_size; /* user tdm frame size in bytes */ + /* default unip TDM_WORD_POS_X_Y */ + unsigned int word_pos[4] = { + 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A}; + int freq, ret; + + tdm_frame_size = + sti_uniperiph_get_unip_tdm_frame_size(player); + user_frame_size = + sti_uniperiph_get_user_frame_size(runtime); + + /* fix 16/0 format */ + SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player); + SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player); + + /* number of words inserted on the TDM line */ + SET_UNIPERIF_I2S_FMT_NUM_CH(player, user_frame_size / 4 / 2); + + SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); + SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player); + + /* Enable the tdm functionality */ + SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(player); + + /* number of 8 bits timeslots avail in unip tdm frame */ + SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(player, tdm_frame_size); + + /* set the timeslot allocation for words in FIFO */ + sti_uniperiph_get_tdm_word_pos(player, word_pos); + SET_UNIPERIF_TDM_WORD_POS(player, 1_2, word_pos[WORD_1_2]); + SET_UNIPERIF_TDM_WORD_POS(player, 3_4, word_pos[WORD_3_4]); + SET_UNIPERIF_TDM_WORD_POS(player, 5_6, word_pos[WORD_5_6]); + SET_UNIPERIF_TDM_WORD_POS(player, 7_8, word_pos[WORD_7_8]); + + /* set unip clk rate (not done vai set_sysclk ops) */ + freq = runtime->rate * tdm_frame_size * 8; + mutex_lock(&player->ctrl_lock); + ret = uni_player_clk_set_rate(player, freq); + if (!ret) + player->mclk = freq; + mutex_unlock(&player->ctrl_lock); + + return 0; +} + /* * ALSA uniperipheral iec958 controls */ @@ -659,11 +700,29 @@ static int uni_player_startup(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; + int ret; + player->substream = substream; player->clk_adj = 0; - return 0; + if (!UNIPERIF_TYPE_IS_TDM(player)) + return 0; + + /* refine hw constraint in tdm mode */ + ret = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + sti_uniperiph_fix_tdm_chan, + player, SNDRV_PCM_HW_PARAM_CHANNELS, + -1); + if (ret < 0) + return ret; + + return snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + sti_uniperiph_fix_tdm_format, + player, SNDRV_PCM_HW_PARAM_FORMAT, + -1); } static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id, @@ -673,7 +732,7 @@ static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id, struct uniperif *player = priv->dai_data.uni; int ret; - if (dir == SND_SOC_CLOCK_IN) + if (UNIPERIF_TYPE_IS_TDM(player) || (dir == SND_SOC_CLOCK_IN)) return 0; if (clk_id != 0) @@ -705,7 +764,13 @@ static int uni_player_prepare(struct snd_pcm_substream *substream, } /* Calculate transfer size (in fifo cells and bytes) for frame count */ - transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; + if (player->info->type == SND_ST_UNIPERIF_TYPE_TDM) { + /* transfer size = user frame size (in 32 bits FIFO cell) */ + transfer_size = + sti_uniperiph_get_user_frame_size(runtime) / 4; + } else { + transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; + } /* Calculate number of empty cells available before asserting DREQ */ if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) { @@ -739,6 +804,9 @@ static int uni_player_prepare(struct snd_pcm_substream *substream, case SND_ST_UNIPERIF_TYPE_SPDIF: ret = uni_player_prepare_iec958(player, runtime); break; + case SND_ST_UNIPERIF_TYPE_TDM: + ret = uni_player_prepare_tdm(player, runtime); + break; default: dev_err(player->dev, "invalid player type"); return -EINVAL; @@ -1008,6 +1076,8 @@ static int uni_player_parse_dt(struct platform_device *pdev, info->type = SND_ST_UNIPERIF_TYPE_PCM; else if (strcasecmp(mode, "spdif") == 0) info->type = SND_ST_UNIPERIF_TYPE_SPDIF; + else if (strcasecmp(mode, "tdm") == 0) + info->type = SND_ST_UNIPERIF_TYPE_TDM; else info->type = SND_ST_UNIPERIF_TYPE_NONE; @@ -1028,7 +1098,8 @@ static const struct snd_soc_dai_ops uni_player_dai_ops = { .trigger = uni_player_trigger, .hw_params = sti_uniperiph_dai_hw_params, .set_fmt = sti_uniperiph_dai_set_fmt, - .set_sysclk = uni_player_set_sysclk + .set_sysclk = uni_player_set_sysclk, + .set_tdm_slot = sti_uniperiph_set_tdm_slot }; int uni_player_init(struct platform_device *pdev, @@ -1038,7 +1109,6 @@ int uni_player_init(struct platform_device *pdev, player->dev = &pdev->dev; player->state = UNIPERIF_STATE_STOPPED; - player->hw = &uni_player_pcm_hw; player->dai_ops = &uni_player_dai_ops; ret = uni_player_parse_dt(pdev, player); @@ -1048,6 +1118,11 @@ int uni_player_init(struct platform_device *pdev, return ret; } + if (UNIPERIF_TYPE_IS_TDM(player)) + player->hw = &uni_tdm_hw; + else + player->hw = &uni_player_pcm_hw; + /* Get uniperif resource */ player->clk = of_clk_get(pdev->dev.of_node, 0); if (IS_ERR(player->clk)) -- GitLab From 82d4eb91ab1912cb9e8751b9aa0875af2ae36db2 Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 7 Apr 2016 11:25:36 +0200 Subject: [PATCH 2171/9938] ASoC: sti: unip reader tdm mode Here are the changes to enable reader tdm mode: - When TDM_ENABLE is set to 1, the i2s format should be automatically configured. Unfortunately this is not the case (HW bug). Then, we shall force DATA_SIZE setting. - Compute the transfer size for tdm mode: transfer size = user frame size - Manage tdm slots configuration given in DT. - Refine the hw param (channels & format) according to tdm slot config. Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/uniperif_reader.c | 229 +++++++++++++++++++++++--------- 1 file changed, 168 insertions(+), 61 deletions(-) diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c index 8a0eb2050169..eb74a328c928 100644 --- a/sound/soc/sti/uniperif_reader.c +++ b/sound/soc/sti/uniperif_reader.c @@ -73,55 +73,10 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) return ret; } -static int uni_reader_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static int uni_reader_prepare_pcm(struct snd_pcm_runtime *runtime, + struct uniperif *reader) { - struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); - struct uniperif *reader = priv->dai_data.uni; - struct snd_pcm_runtime *runtime = substream->runtime; - int transfer_size, trigger_limit; int slot_width; - int count = 10; - - /* The reader should be stopped */ - if (reader->state != UNIPERIF_STATE_STOPPED) { - dev_err(reader->dev, "%s: invalid reader state %d", __func__, - reader->state); - return -EINVAL; - } - - /* Calculate transfer size (in fifo cells and bytes) for frame count */ - transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; - - /* Calculate number of empty cells available before asserting DREQ */ - if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) - trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; - else - /* - * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 - * FDMA_TRIGGER_LIMIT also controls when the state switches - * from OFF or STANDBY to AUDIO DATA. - */ - trigger_limit = transfer_size; - - /* Trigger limit must be an even number */ - if ((!trigger_limit % 2) || - (trigger_limit != 1 && transfer_size % 2) || - (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) { - dev_err(reader->dev, "invalid trigger limit %d", trigger_limit); - return -EINVAL; - } - - SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit); - - switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - case SND_SOC_DAIFMT_NB_IF: - SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); - break; - default: - SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); - } /* Force slot width to 32 in I2S mode */ if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) @@ -173,6 +128,109 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream, return -EINVAL; } + /* Number of channels must be even */ + if ((runtime->channels % 2) || (runtime->channels < 2) || + (runtime->channels > 10)) { + dev_err(reader->dev, "%s: invalid nb of channels", __func__); + return -EINVAL; + } + + SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2); + SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); + + return 0; +} + +static int uni_reader_prepare_tdm(struct snd_pcm_runtime *runtime, + struct uniperif *reader) +{ + int frame_size; /* user tdm frame size in bytes */ + /* default unip TDM_WORD_POS_X_Y */ + unsigned int word_pos[4] = { + 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A}; + + frame_size = sti_uniperiph_get_user_frame_size(runtime); + + /* fix 16/0 format */ + SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader); + SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader); + + /* number of words inserted on the TDM line */ + SET_UNIPERIF_I2S_FMT_NUM_CH(reader, frame_size / 4 / 2); + + SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); + SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); + SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(reader); + + /* + * set the timeslots allocation for words in FIFO + * + * HW bug: (LSB word < MSB word) => this config is not possible + * So if we want (LSB word < MSB) word, then it shall be + * handled by user + */ + sti_uniperiph_get_tdm_word_pos(reader, word_pos); + SET_UNIPERIF_TDM_WORD_POS(reader, 1_2, word_pos[WORD_1_2]); + SET_UNIPERIF_TDM_WORD_POS(reader, 3_4, word_pos[WORD_3_4]); + SET_UNIPERIF_TDM_WORD_POS(reader, 5_6, word_pos[WORD_5_6]); + SET_UNIPERIF_TDM_WORD_POS(reader, 7_8, word_pos[WORD_7_8]); + + return 0; +} + +static int uni_reader_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); + struct uniperif *reader = priv->dai_data.uni; + struct snd_pcm_runtime *runtime = substream->runtime; + int transfer_size, trigger_limit, ret; + int count = 10; + + /* The reader should be stopped */ + if (reader->state != UNIPERIF_STATE_STOPPED) { + dev_err(reader->dev, "%s: invalid reader state %d", __func__, + reader->state); + return -EINVAL; + } + + /* Calculate transfer size (in fifo cells and bytes) for frame count */ + if (reader->info->type == SND_ST_UNIPERIF_TYPE_TDM) { + /* transfer size = unip frame size (in 32 bits FIFO cell) */ + transfer_size = + sti_uniperiph_get_user_frame_size(runtime) / 4; + } else { + transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; + } + + /* Calculate number of empty cells available before asserting DREQ */ + if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) + trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; + else + /* + * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 + * FDMA_TRIGGER_LIMIT also controls when the state switches + * from OFF or STANDBY to AUDIO DATA. + */ + trigger_limit = transfer_size; + + /* Trigger limit must be an even number */ + if ((!trigger_limit % 2) || + (trigger_limit != 1 && transfer_size % 2) || + (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) { + dev_err(reader->dev, "invalid trigger limit %d", trigger_limit); + return -EINVAL; + } + + SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit); + + if (UNIPERIF_TYPE_IS_TDM(reader)) + ret = uni_reader_prepare_tdm(runtime, reader); + else + ret = uni_reader_prepare_pcm(runtime, reader); + if (ret) + return ret; + switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); @@ -191,21 +249,26 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream, return -EINVAL; } - SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); - - /* Data clocking (changing) on the rising edge */ - SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); - - /* Number of channels must be even */ - - if ((runtime->channels % 2) || (runtime->channels < 2) || - (runtime->channels > 10)) { - dev_err(reader->dev, "%s: invalid nb of channels", __func__); - return -EINVAL; + /* Data clocking (changing) on the rising/falling edge */ + switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); + break; + case SND_SOC_DAIFMT_NB_IF: + SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); + break; + case SND_SOC_DAIFMT_IB_NF: + SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader); + break; + case SND_SOC_DAIFMT_IB_IF: + SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader); + break; } - SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2); - /* Clear any pending interrupts */ SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader)); @@ -293,6 +356,32 @@ static int uni_reader_trigger(struct snd_pcm_substream *substream, } } +static int uni_reader_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); + struct uniperif *reader = priv->dai_data.uni; + int ret; + + if (!UNIPERIF_TYPE_IS_TDM(reader)) + return 0; + + /* refine hw constraint in tdm mode */ + ret = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + sti_uniperiph_fix_tdm_chan, + reader, SNDRV_PCM_HW_PARAM_CHANNELS, + -1); + if (ret < 0) + return ret; + + return snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + sti_uniperiph_fix_tdm_format, + reader, SNDRV_PCM_HW_PARAM_FORMAT, + -1); +} + static void uni_reader_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -310,6 +399,7 @@ static int uni_reader_parse_dt(struct platform_device *pdev, { struct uniperif_info *info; struct device_node *node = pdev->dev.of_node; + const char *mode; /* Allocate memory for the info structure */ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); @@ -322,6 +412,17 @@ static int uni_reader_parse_dt(struct platform_device *pdev, return -EINVAL; } + /* Read the device mode property */ + if (of_property_read_string(node, "st,mode", &mode)) { + dev_err(&pdev->dev, "uniperipheral mode not defined"); + return -EINVAL; + } + + if (strcasecmp(mode, "tdm") == 0) + info->type = SND_ST_UNIPERIF_TYPE_TDM; + else + info->type = SND_ST_UNIPERIF_TYPE_PCM; + /* Save the info structure */ reader->info = info; @@ -329,11 +430,13 @@ static int uni_reader_parse_dt(struct platform_device *pdev, } static const struct snd_soc_dai_ops uni_reader_dai_ops = { + .startup = uni_reader_startup, .shutdown = uni_reader_shutdown, .prepare = uni_reader_prepare, .trigger = uni_reader_trigger, .hw_params = sti_uniperiph_dai_hw_params, .set_fmt = sti_uniperiph_dai_set_fmt, + .set_tdm_slot = sti_uniperiph_set_tdm_slot }; int uni_reader_init(struct platform_device *pdev, @@ -343,7 +446,6 @@ int uni_reader_init(struct platform_device *pdev, reader->dev = &pdev->dev; reader->state = UNIPERIF_STATE_STOPPED; - reader->hw = &uni_reader_pcm_hw; reader->dai_ops = &uni_reader_dai_ops; ret = uni_reader_parse_dt(pdev, reader); @@ -352,6 +454,11 @@ int uni_reader_init(struct platform_device *pdev, return ret; } + if (UNIPERIF_TYPE_IS_TDM(reader)) + reader->hw = &uni_tdm_hw; + else + reader->hw = &uni_reader_pcm_hw; + ret = devm_request_irq(&pdev->dev, reader->irq, uni_reader_irq_handler, IRQF_SHARED, dev_name(&pdev->dev), reader); -- GitLab From eb6e1342eea4576627f143da3163865978c72d1e Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:29 -0400 Subject: [PATCH 2172/9938] staging: lustre: selftest: convert srpc_bulk_t to proper struct Turn typedef srpc_bulk_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 14 +++++++------- drivers/staging/lustre/lnet/selftest/conrpc.c | 4 ++-- .../staging/lustre/lnet/selftest/framework.c | 2 +- drivers/staging/lustre/lnet/selftest/rpc.c | 18 +++++++++--------- .../staging/lustre/lnet/selftest/selftest.h | 17 +++++++++-------- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 96af93f8b0e3..5a161c9c3971 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -51,7 +51,7 @@ MODULE_PARM_DESC(brw_inject_errors, "# data errors to inject randomly, zero by d static void brw_client_fini(sfw_test_instance_t *tsi) { - srpc_bulk_t *bulk; + struct srpc_bulk *bulk; sfw_test_unit_t *tsu; LASSERT(tsi->tsi_is_client); @@ -74,7 +74,7 @@ brw_client_init(sfw_test_instance_t *tsi) int npg; int len; int opc; - srpc_bulk_t *bulk; + struct srpc_bulk *bulk; sfw_test_unit_t *tsu; LASSERT(sn); @@ -224,7 +224,7 @@ brw_check_page(struct page *pg, int pattern, __u64 magic) } static void -brw_fill_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) +brw_fill_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) { int i; struct page *pg; @@ -236,7 +236,7 @@ brw_fill_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) } static int -brw_check_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) +brw_check_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) { int i; struct page *pg; @@ -257,7 +257,7 @@ static int brw_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, srpc_client_rpc_t **rpcpp) { - srpc_bulk_t *bulk = tsu->tsu_private; + struct srpc_bulk *bulk = tsu->tsu_private; sfw_test_instance_t *tsi = tsu->tsu_instance; sfw_session_t *sn = tsi->tsi_batch->bat_session; srpc_client_rpc_t *rpc; @@ -297,7 +297,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, if (rc) return rc; - memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg])); + memcpy(&rpc->crpc_bulk, bulk, offsetof(struct srpc_bulk, bk_iovs[npg])); if (opc == LST_BRW_WRITE) brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC); else @@ -361,7 +361,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) static void brw_server_rpc_done(struct srpc_server_rpc *rpc) { - srpc_bulk_t *blk = rpc->srpc_bulk; + struct srpc_bulk *blk = rpc->srpc_bulk; if (!blk) return; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 2be9451f8c0a..e3574ffaa118 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -150,7 +150,7 @@ lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, void lstcon_rpc_put(lstcon_rpc_t *crpc) { - srpc_bulk_t *bulk = &crpc->crp_rpc->crpc_bulk; + struct srpc_bulk *bulk = &crpc->crp_rpc->crpc_bulk; int i; LASSERT(list_empty(&crpc->crp_link)); @@ -812,7 +812,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, lstcon_group_t *sgrp = test->tes_src_grp; lstcon_group_t *dgrp = test->tes_dst_grp; srpc_test_reqst_t *trq; - srpc_bulk_t *bulk; + struct srpc_bulk *bulk; int i; int npg = 0; int nob = 0; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index ce452b54ab33..6472108f19b5 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -733,7 +733,7 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) { srpc_msg_t *msg = &rpc->srpc_reqstbuf->buf_msg; srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; - srpc_bulk_t *bk = rpc->srpc_bulk; + struct srpc_bulk *bk = rpc->srpc_bulk; int ndest = req->tsr_ndest; sfw_test_unit_t *tsu; sfw_test_instance_t *tsi; diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 8d7c0a06c0f8..633c4db9802f 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -88,7 +88,7 @@ void srpc_set_counters(const srpc_counters_t *cnt) } static int -srpc_add_bulk_page(srpc_bulk_t *bk, struct page *pg, int i, int nob) +srpc_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i, int nob) { nob = min_t(int, nob, PAGE_SIZE); @@ -102,7 +102,7 @@ srpc_add_bulk_page(srpc_bulk_t *bk, struct page *pg, int i, int nob) } void -srpc_free_bulk(srpc_bulk_t *bk) +srpc_free_bulk(struct srpc_bulk *bk) { int i; struct page *pg; @@ -117,25 +117,25 @@ srpc_free_bulk(srpc_bulk_t *bk) __free_page(pg); } - LIBCFS_FREE(bk, offsetof(srpc_bulk_t, bk_iovs[bk->bk_niov])); + LIBCFS_FREE(bk, offsetof(struct srpc_bulk, bk_iovs[bk->bk_niov])); } -srpc_bulk_t * +struct srpc_bulk * srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink) { - srpc_bulk_t *bk; + struct srpc_bulk *bk; int i; LASSERT(bulk_npg > 0 && bulk_npg <= LNET_MAX_IOV); LIBCFS_CPT_ALLOC(bk, lnet_cpt_table(), cpt, - offsetof(srpc_bulk_t, bk_iovs[bulk_npg])); + offsetof(struct srpc_bulk, bk_iovs[bulk_npg])); if (!bk) { CERROR("Can't allocate descriptor for %d pages\n", bulk_npg); return NULL; } - memset(bk, 0, offsetof(srpc_bulk_t, bk_iovs[bulk_npg])); + memset(bk, 0, offsetof(struct srpc_bulk, bk_iovs[bulk_npg])); bk->bk_sink = sink; bk->bk_len = bulk_len; bk->bk_niov = bulk_npg; @@ -840,7 +840,7 @@ srpc_prepare_reply(srpc_client_rpc_t *rpc) static int srpc_prepare_bulk(srpc_client_rpc_t *rpc) { - srpc_bulk_t *bk = &rpc->crpc_bulk; + struct srpc_bulk *bk = &rpc->crpc_bulk; struct srpc_event *ev = &rpc->crpc_bulkev; __u64 *id = &rpc->crpc_reqstmsg.msg_body.reqst.bulkid; int rc; @@ -874,7 +874,7 @@ static int srpc_do_bulk(struct srpc_server_rpc *rpc) { struct srpc_event *ev = &rpc->srpc_ev; - srpc_bulk_t *bk = rpc->srpc_bulk; + struct srpc_bulk *bk = rpc->srpc_bulk; __u64 id = rpc->srpc_reqstbuf->buf_msg.msg_body.reqst.bulkid; int rc; int opt; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 3411e33c0938..4f6af535fecf 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -154,13 +154,14 @@ struct srpc_event { void *ev_data; /* owning server/client RPC */ }; -typedef struct { +/* bulk descriptor */ +struct srpc_bulk { int bk_len; /* len of bulk data */ lnet_handle_md_t bk_mdh; int bk_sink; /* sink/source */ int bk_niov; /* # iov in bk_iovs */ lnet_kiov_t bk_iovs[0]; -} srpc_bulk_t; /* bulk descriptor */ +}; /* message buffer descriptor */ typedef struct srpc_buffer { @@ -193,7 +194,7 @@ struct srpc_server_rpc { srpc_msg_t srpc_replymsg; lnet_handle_md_t srpc_replymdh; srpc_buffer_t *srpc_reqstbuf; - srpc_bulk_t *srpc_bulk; + struct srpc_bulk *srpc_bulk; unsigned int srpc_aborted; /* being given up */ int srpc_status; @@ -230,7 +231,7 @@ typedef struct srpc_client_rpc { srpc_msg_t crpc_replymsg; lnet_handle_md_t crpc_reqstmdh; lnet_handle_md_t crpc_replymdh; - srpc_bulk_t crpc_bulk; + struct srpc_bulk crpc_bulk; } srpc_client_rpc_t; #define srpc_client_rpc_size(rpc) \ @@ -424,7 +425,7 @@ void sfw_post_rpc(srpc_client_rpc_t *rpc); void sfw_client_rpc_done(srpc_client_rpc_t *rpc); void sfw_unpack_message(srpc_msg_t *msg); void sfw_free_pages(struct srpc_server_rpc *rpc); -void sfw_add_bulk_page(srpc_bulk_t *bk, struct page *pg, int i); +void sfw_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i); int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, int sink); int sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply); @@ -436,9 +437,9 @@ srpc_create_client_rpc(lnet_process_id_t peer, int service, void (*rpc_fini)(srpc_client_rpc_t *), void *priv); void srpc_post_rpc(srpc_client_rpc_t *rpc); void srpc_abort_rpc(srpc_client_rpc_t *rpc, int why); -void srpc_free_bulk(srpc_bulk_t *bk); -srpc_bulk_t *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, - int sink); +void srpc_free_bulk(struct srpc_bulk *bk); +struct srpc_bulk *srpc_alloc_bulk(int cpt, unsigned bulk_npg, + unsigned bulk_len, int sink); int srpc_send_rpc(swi_workitem_t *wi); int srpc_send_reply(struct srpc_server_rpc *rpc); int srpc_add_service(srpc_service_t *sv); -- GitLab From 4b064e95282483f5cebc12a2f242212e42192c48 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:30 -0400 Subject: [PATCH 2173/9938] staging: lustre: selftest: convert srpc_buffer_t to proper struct Turn typedef srpc_buffer_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/rpc.c | 12 ++++++------ drivers/staging/lustre/lnet/selftest/selftest.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 633c4db9802f..5dcb892de61d 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -697,7 +697,7 @@ srpc_finish_service(struct srpc_service *sv) /* called with sv->sv_lock held */ static void -srpc_service_recycle_buffer(struct srpc_service_cd *scd, srpc_buffer_t *buf) +srpc_service_recycle_buffer(struct srpc_service_cd *scd, struct srpc_buffer *buf) __must_hold(&scd->scd_lock) { if (!scd->scd_svc->sv_shuttingdown && scd->scd_buf_adjust >= 0) { @@ -759,7 +759,7 @@ srpc_shutdown_service(srpc_service_t *sv) { struct srpc_service_cd *scd; struct srpc_server_rpc *rpc; - srpc_buffer_t *buf; + struct srpc_buffer *buf; int i; CDEBUG(D_NET, "Shutting down service: id %d, name %s\n", @@ -903,7 +903,7 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) { struct srpc_service_cd *scd = rpc->srpc_scd; struct srpc_service *sv = scd->scd_svc; - srpc_buffer_t *buffer; + struct srpc_buffer *buffer; LASSERT(status || rpc->srpc_wi.swi_state == SWI_STATE_DONE); @@ -948,7 +948,7 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) if (!sv->sv_shuttingdown && !list_empty(&scd->scd_buf_blocked)) { buffer = list_entry(scd->scd_buf_blocked.next, - srpc_buffer_t, buf_list); + struct srpc_buffer, buf_list); list_del(&buffer->buf_list); srpc_init_server_rpc(rpc, scd, buffer); @@ -1413,7 +1413,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) struct srpc_event *rpcev = ev->md.user_ptr; srpc_client_rpc_t *crpc; struct srpc_server_rpc *srpc; - srpc_buffer_t *buffer; + struct srpc_buffer *buffer; srpc_service_t *sv; srpc_msg_t *msg; srpc_msg_type_t type; @@ -1486,7 +1486,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) LASSERT(ev->type != LNET_EVENT_UNLINK || sv->sv_shuttingdown); - buffer = container_of(ev->md.start, srpc_buffer_t, buf_msg); + buffer = container_of(ev->md.start, struct srpc_buffer, buf_msg); buffer->buf_peer = ev->initiator; buffer->buf_self = ev->target.nid; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 4f6af535fecf..098231508d2c 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -164,13 +164,13 @@ struct srpc_bulk { }; /* message buffer descriptor */ -typedef struct srpc_buffer { +struct srpc_buffer { struct list_head buf_list; /* chain on srpc_service::*_msgq */ srpc_msg_t buf_msg; lnet_handle_md_t buf_mdh; lnet_nid_t buf_self; lnet_process_id_t buf_peer; -} srpc_buffer_t; +}; struct swi_workitem; typedef int (*swi_action_t) (struct swi_workitem *); @@ -193,7 +193,7 @@ struct srpc_server_rpc { lnet_process_id_t srpc_peer; srpc_msg_t srpc_replymsg; lnet_handle_md_t srpc_replymdh; - srpc_buffer_t *srpc_reqstbuf; + struct srpc_buffer *srpc_reqstbuf; struct srpc_bulk *srpc_bulk; unsigned int srpc_aborted; /* being given up */ -- GitLab From 25a9ca5202e6f8d1e5c9eafc239788d9ebffb02c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:31 -0400 Subject: [PATCH 2174/9938] staging: lustre: selftest: convert swi_workitem_t to proper struct Turn typedef swi_workitem_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/framework.c | 4 +-- drivers/staging/lustre/lnet/selftest/rpc.c | 8 +++--- .../staging/lustre/lnet/selftest/selftest.h | 26 ++++++++++--------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 6472108f19b5..c8f8a8d26a2b 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -942,7 +942,7 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, } static int -sfw_run_test(swi_workitem_t *wi) +sfw_run_test(struct swi_workitem *wi) { sfw_test_unit_t *tsu = wi->swi_workitem.wi_data; sfw_test_instance_t *tsi = tsu->tsu_instance; @@ -993,7 +993,7 @@ sfw_run_test(swi_workitem_t *wi) static int sfw_run_batch(sfw_batch_t *tsb) { - swi_workitem_t *wi; + struct swi_workitem *wi; sfw_test_unit_t *tsu; sfw_test_instance_t *tsi; diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 5dcb892de61d..72a38e430b27 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -71,7 +71,7 @@ srpc_serv_portal(int svc_id) } /* forward ref's */ -int srpc_handle_rpc(swi_workitem_t *wi); +int srpc_handle_rpc(struct swi_workitem *wi); void srpc_get_counters(srpc_counters_t *cnt) { @@ -963,7 +963,7 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) /* handles an incoming RPC */ int -srpc_handle_rpc(swi_workitem_t *wi) +srpc_handle_rpc(struct swi_workitem *wi) { struct srpc_server_rpc *rpc = wi->swi_workitem.wi_data; struct srpc_service_cd *scd = rpc->srpc_scd; @@ -1140,7 +1140,7 @@ srpc_del_client_rpc_timer(srpc_client_rpc_t *rpc) static void srpc_client_rpc_done(srpc_client_rpc_t *rpc, int status) { - swi_workitem_t *wi = &rpc->crpc_wi; + struct swi_workitem *wi = &rpc->crpc_wi; LASSERT(status || wi->swi_state == SWI_STATE_DONE); @@ -1175,7 +1175,7 @@ srpc_client_rpc_done(srpc_client_rpc_t *rpc, int status) /* sends an outgoing RPC */ int -srpc_send_rpc(swi_workitem_t *wi) +srpc_send_rpc(struct swi_workitem *wi) { int rc = 0; srpc_client_rpc_t *rpc; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 098231508d2c..fcbaf5eed601 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -175,19 +175,19 @@ struct srpc_buffer { struct swi_workitem; typedef int (*swi_action_t) (struct swi_workitem *); -typedef struct swi_workitem { +struct swi_workitem { struct cfs_wi_sched *swi_sched; struct cfs_workitem swi_workitem; swi_action_t swi_action; int swi_state; -} swi_workitem_t; +}; /* server-side state of a RPC */ struct srpc_server_rpc { /* chain on srpc_service::*_rpcq */ struct list_head srpc_list; struct srpc_service_cd *srpc_scd; - swi_workitem_t srpc_wi; + struct swi_workitem srpc_wi; struct srpc_event srpc_ev; /* bulk/reply event */ lnet_nid_t srpc_self; lnet_process_id_t srpc_peer; @@ -209,7 +209,7 @@ typedef struct srpc_client_rpc { atomic_t crpc_refcount; int crpc_timeout; /* # seconds to wait for reply */ struct stt_timer crpc_timer; - swi_workitem_t crpc_wi; + struct swi_workitem crpc_wi; lnet_process_id_t crpc_dest; void (*crpc_done)(struct srpc_client_rpc *); @@ -273,7 +273,7 @@ struct srpc_service_cd { /** in-flight RPCs */ struct list_head scd_rpc_active; /** workitem for posting buffer */ - swi_workitem_t scd_buf_wi; + struct swi_workitem scd_buf_wi; /** CPT id */ int scd_cpt; /** error code for scd_buf_wi */ @@ -404,7 +404,7 @@ typedef struct sfw_test_unit { int tsu_loop; /* loop count of the test */ sfw_test_instance_t *tsu_instance; /* pointer to test instance */ void *tsu_private; /* private data */ - swi_workitem_t tsu_worker; /* workitem of the test unit */ + struct swi_workitem tsu_worker; /* workitem of the test unit */ } sfw_test_unit_t; typedef struct sfw_test_case { @@ -440,7 +440,7 @@ void srpc_abort_rpc(srpc_client_rpc_t *rpc, int why); void srpc_free_bulk(struct srpc_bulk *bk); struct srpc_bulk *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink); -int srpc_send_rpc(swi_workitem_t *wi); +int srpc_send_rpc(struct swi_workitem *wi); int srpc_send_reply(struct srpc_server_rpc *rpc); int srpc_add_service(srpc_service_t *sv); int srpc_remove_service(srpc_service_t *sv); @@ -464,13 +464,15 @@ srpc_serv_is_framework(struct srpc_service *svc) static inline int swi_wi_action(struct cfs_workitem *wi) { - swi_workitem_t *swi = container_of(wi, swi_workitem_t, swi_workitem); + struct swi_workitem *swi; + + swi = container_of(wi, struct swi_workitem, swi_workitem); return swi->swi_action(swi); } static inline void -swi_init_workitem(swi_workitem_t *swi, void *data, +swi_init_workitem(struct swi_workitem *swi, void *data, swi_action_t action, struct cfs_wi_sched *sched) { swi->swi_sched = sched; @@ -480,19 +482,19 @@ swi_init_workitem(swi_workitem_t *swi, void *data, } static inline void -swi_schedule_workitem(swi_workitem_t *wi) +swi_schedule_workitem(struct swi_workitem *wi) { cfs_wi_schedule(wi->swi_sched, &wi->swi_workitem); } static inline void -swi_exit_workitem(swi_workitem_t *swi) +swi_exit_workitem(struct swi_workitem *swi) { cfs_wi_exit(swi->swi_sched, &swi->swi_workitem); } static inline int -swi_deschedule_workitem(swi_workitem_t *swi) +swi_deschedule_workitem(struct swi_workitem *swi) { return cfs_wi_deschedule(swi->swi_sched, &swi->swi_workitem); } -- GitLab From 20234da54283d138d2aceba0c4e295d8a8eaae46 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:32 -0400 Subject: [PATCH 2175/9938] staging: lustre: selftest: convert srpc_client_rpc_t to proper struct Turn typedef srpc_client_rpc_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 6 +-- drivers/staging/lustre/lnet/selftest/conrpc.c | 8 ++-- drivers/staging/lustre/lnet/selftest/conrpc.h | 2 +- .../staging/lustre/lnet/selftest/framework.c | 36 ++++++++-------- .../staging/lustre/lnet/selftest/ping_test.c | 4 +- drivers/staging/lustre/lnet/selftest/rpc.c | 32 +++++++------- .../staging/lustre/lnet/selftest/selftest.h | 42 +++++++++---------- 7 files changed, 65 insertions(+), 65 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 5a161c9c3971..6657a58c50b6 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -255,12 +255,12 @@ brw_check_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) static int brw_client_prep_rpc(sfw_test_unit_t *tsu, - lnet_process_id_t dest, srpc_client_rpc_t **rpcpp) + lnet_process_id_t dest, struct srpc_client_rpc **rpcpp) { struct srpc_bulk *bulk = tsu->tsu_private; sfw_test_instance_t *tsi = tsu->tsu_instance; sfw_session_t *sn = tsi->tsi_batch->bat_session; - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; srpc_brw_reqst_t *req; int flags; int npg; @@ -313,7 +313,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, } static void -brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) +brw_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) { __u64 magic = BRW_MAGIC; sfw_test_instance_t *tsi = tsu->tsu_instance; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index e3574ffaa118..2affbeecac40 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -50,7 +50,7 @@ void lstcon_rpc_stat_reply(lstcon_rpc_trans_t *, srpc_msg_t *, lstcon_node_t *, lstcon_trans_stat_t *); static void -lstcon_rpc_done(srpc_client_rpc_t *rpc) +lstcon_rpc_done(struct srpc_client_rpc *rpc) { lstcon_rpc_t *crpc = (lstcon_rpc_t *)rpc->crpc_priv; @@ -287,7 +287,7 @@ lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, lstcon_rpc_t *crpc) void lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) { - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; lstcon_rpc_t *crpc; lstcon_node_t *nd; @@ -389,7 +389,7 @@ static int lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) { lstcon_node_t *nd = crpc->crp_node; - srpc_client_rpc_t *rpc = crpc->crp_rpc; + struct srpc_client_rpc *rpc = crpc->crp_rpc; srpc_generic_reply_t *rep; LASSERT(nd && rpc); @@ -541,7 +541,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, void lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) { - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; lstcon_rpc_t *crpc; lstcon_rpc_t *tmp; int count = 0; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index 3e7839dad5bb..6ddf088e6b91 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -65,7 +65,7 @@ struct lstcon_node; typedef struct lstcon_rpc { struct list_head crp_link; /* chain on rpc transaction */ - srpc_client_rpc_t *crp_rpc; /* client rpc */ + struct srpc_client_rpc *crp_rpc; /* client rpc */ struct lstcon_node *crp_node; /* destination node */ struct lstcon_rpc_trans *crp_trans; /* conrpc transaction */ diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index c8f8a8d26a2b..931a517b9ed0 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -298,7 +298,7 @@ sfw_server_rpc_done(struct srpc_server_rpc *rpc) } static void -sfw_client_rpc_fini(srpc_client_rpc_t *rpc) +sfw_client_rpc_fini(struct srpc_client_rpc *rpc) { LASSERT(!rpc->crpc_bulk.bk_niov); LASSERT(list_empty(&rpc->crpc_list)); @@ -526,7 +526,7 @@ sfw_debug_session(srpc_debug_reqst_t *request, srpc_debug_reply_t *reply) } static void -sfw_test_rpc_fini(srpc_client_rpc_t *rpc) +sfw_test_rpc_fini(struct srpc_client_rpc *rpc) { sfw_test_unit_t *tsu = rpc->crpc_priv; sfw_test_instance_t *tsi = tsu->tsu_instance; @@ -616,7 +616,7 @@ sfw_unload_test(struct sfw_test_instance *tsi) static void sfw_destroy_test_instance(sfw_test_instance_t *tsi) { - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; sfw_test_unit_t *tsu; if (!tsi->tsi_is_client) @@ -637,7 +637,7 @@ sfw_destroy_test_instance(sfw_test_instance_t *tsi) while (!list_empty(&tsi->tsi_free_rpcs)) { rpc = list_entry(tsi->tsi_free_rpcs.next, - srpc_client_rpc_t, crpc_list); + struct srpc_client_rpc, crpc_list); list_del(&rpc->crpc_list); LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc)); } @@ -866,7 +866,7 @@ sfw_test_unit_done(sfw_test_unit_t *tsu) } static void -sfw_test_rpc_done(srpc_client_rpc_t *rpc) +sfw_test_rpc_done(struct srpc_client_rpc *rpc) { sfw_test_unit_t *tsu = rpc->crpc_priv; sfw_test_instance_t *tsi = tsu->tsu_instance; @@ -902,9 +902,9 @@ sfw_test_rpc_done(srpc_client_rpc_t *rpc) int sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, unsigned features, int nblk, int blklen, - srpc_client_rpc_t **rpcpp) + struct srpc_client_rpc **rpcpp) { - srpc_client_rpc_t *rpc = NULL; + struct srpc_client_rpc *rpc = NULL; sfw_test_instance_t *tsi = tsu->tsu_instance; spin_lock(&tsi->tsi_lock); @@ -912,7 +912,7 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, LASSERT(sfw_test_active(tsi)); /* pick request from buffer */ rpc = list_first_entry_or_null(&tsi->tsi_free_rpcs, - srpc_client_rpc_t, crpc_list); + struct srpc_client_rpc, crpc_list); if (rpc) { LASSERT(nblk == rpc->crpc_bulk.bk_niov); list_del_init(&rpc->crpc_list); @@ -946,7 +946,7 @@ sfw_run_test(struct swi_workitem *wi) { sfw_test_unit_t *tsu = wi->swi_workitem.wi_data; sfw_test_instance_t *tsi = tsu->tsu_instance; - srpc_client_rpc_t *rpc = NULL; + struct srpc_client_rpc *rpc = NULL; LASSERT(wi == &tsu->tsu_worker); @@ -1029,7 +1029,7 @@ int sfw_stop_batch(sfw_batch_t *tsb, int force) { sfw_test_instance_t *tsi; - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; if (!sfw_batch_active(tsb)) { CDEBUG(D_NET, "Batch %llu inactive\n", tsb->bat_id.bat_id); @@ -1377,12 +1377,12 @@ sfw_bulk_ready(struct srpc_server_rpc *rpc, int status) return rc; } -srpc_client_rpc_t * +struct srpc_client_rpc * sfw_create_rpc(lnet_process_id_t peer, int service, unsigned features, int nbulkiov, int bulklen, - void (*done)(srpc_client_rpc_t *), void *priv) + void (*done)(struct srpc_client_rpc *), void *priv) { - srpc_client_rpc_t *rpc = NULL; + struct srpc_client_rpc *rpc = NULL; spin_lock(&sfw_data.fw_lock); @@ -1391,7 +1391,7 @@ sfw_create_rpc(lnet_process_id_t peer, int service, if (!nbulkiov && !list_empty(&sfw_data.fw_zombie_rpcs)) { rpc = list_entry(sfw_data.fw_zombie_rpcs.next, - srpc_client_rpc_t, crpc_list); + struct srpc_client_rpc, crpc_list); list_del(&rpc->crpc_list); srpc_init_client_rpc(rpc, peer, service, 0, 0, @@ -1558,7 +1558,7 @@ sfw_unpack_message(srpc_msg_t *msg) } void -sfw_abort_rpc(srpc_client_rpc_t *rpc) +sfw_abort_rpc(struct srpc_client_rpc *rpc) { LASSERT(atomic_read(&rpc->crpc_refcount) > 0); LASSERT(rpc->crpc_service <= SRPC_FRAMEWORK_SERVICE_MAX_ID); @@ -1569,7 +1569,7 @@ sfw_abort_rpc(srpc_client_rpc_t *rpc) } void -sfw_post_rpc(srpc_client_rpc_t *rpc) +sfw_post_rpc(struct srpc_client_rpc *rpc) { spin_lock(&rpc->crpc_lock); @@ -1759,10 +1759,10 @@ sfw_shutdown(void) } while (!list_empty(&sfw_data.fw_zombie_rpcs)) { - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; rpc = list_entry(sfw_data.fw_zombie_rpcs.next, - srpc_client_rpc_t, crpc_list); + struct srpc_client_rpc, crpc_list); list_del(&rpc->crpc_list); LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc)); diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index c7c50be6dab4..1f2ddf6a9f88 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -87,7 +87,7 @@ ping_client_fini(sfw_test_instance_t *tsi) static int ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, - srpc_client_rpc_t **rpc) + struct srpc_client_rpc **rpc) { srpc_ping_reqst_t *req; sfw_test_instance_t *tsi = tsu->tsu_instance; @@ -118,7 +118,7 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, } static void -ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) +ping_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) { sfw_test_instance_t *tsi = tsu->tsu_instance; sfw_session_t *sn = tsi->tsi_batch->bat_session; diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 72a38e430b27..a8f0b2099246 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -792,7 +792,7 @@ srpc_shutdown_service(srpc_service_t *sv) } static int -srpc_send_request(srpc_client_rpc_t *rpc) +srpc_send_request(struct srpc_client_rpc *rpc) { struct srpc_event *ev = &rpc->crpc_reqstev; int rc; @@ -814,7 +814,7 @@ srpc_send_request(srpc_client_rpc_t *rpc) } static int -srpc_prepare_reply(srpc_client_rpc_t *rpc) +srpc_prepare_reply(struct srpc_client_rpc *rpc) { struct srpc_event *ev = &rpc->crpc_replyev; __u64 *id = &rpc->crpc_reqstmsg.msg_body.reqst.rpyid; @@ -838,7 +838,7 @@ srpc_prepare_reply(srpc_client_rpc_t *rpc) } static int -srpc_prepare_bulk(srpc_client_rpc_t *rpc) +srpc_prepare_bulk(struct srpc_client_rpc *rpc) { struct srpc_bulk *bk = &rpc->crpc_bulk; struct srpc_event *ev = &rpc->crpc_bulkev; @@ -1077,7 +1077,7 @@ srpc_handle_rpc(struct swi_workitem *wi) static void srpc_client_rpc_expired(void *data) { - srpc_client_rpc_t *rpc = data; + struct srpc_client_rpc *rpc = data; CWARN("Client RPC expired: service %d, peer %s, timeout %d.\n", rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), @@ -1096,7 +1096,7 @@ srpc_client_rpc_expired(void *data) } static void -srpc_add_client_rpc_timer(srpc_client_rpc_t *rpc) +srpc_add_client_rpc_timer(struct srpc_client_rpc *rpc) { struct stt_timer *timer = &rpc->crpc_timer; @@ -1117,7 +1117,7 @@ srpc_add_client_rpc_timer(srpc_client_rpc_t *rpc) * running on any CPU. */ static void -srpc_del_client_rpc_timer(srpc_client_rpc_t *rpc) +srpc_del_client_rpc_timer(struct srpc_client_rpc *rpc) { /* timer not planted or already exploded */ if (!rpc->crpc_timeout) @@ -1138,7 +1138,7 @@ srpc_del_client_rpc_timer(srpc_client_rpc_t *rpc) } static void -srpc_client_rpc_done(srpc_client_rpc_t *rpc, int status) +srpc_client_rpc_done(struct srpc_client_rpc *rpc, int status) { struct swi_workitem *wi = &rpc->crpc_wi; @@ -1178,7 +1178,7 @@ int srpc_send_rpc(struct swi_workitem *wi) { int rc = 0; - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; srpc_msg_t *reply; int do_bulk; @@ -1308,15 +1308,15 @@ srpc_send_rpc(struct swi_workitem *wi) return 0; } -srpc_client_rpc_t * +struct srpc_client_rpc * srpc_create_client_rpc(lnet_process_id_t peer, int service, int nbulkiov, int bulklen, - void (*rpc_done)(srpc_client_rpc_t *), - void (*rpc_fini)(srpc_client_rpc_t *), void *priv) + void (*rpc_done)(struct srpc_client_rpc *), + void (*rpc_fini)(struct srpc_client_rpc *), void *priv) { - srpc_client_rpc_t *rpc; + struct srpc_client_rpc *rpc; - LIBCFS_ALLOC(rpc, offsetof(srpc_client_rpc_t, + LIBCFS_ALLOC(rpc, offsetof(struct srpc_client_rpc, crpc_bulk.bk_iovs[nbulkiov])); if (!rpc) return NULL; @@ -1328,7 +1328,7 @@ srpc_create_client_rpc(lnet_process_id_t peer, int service, /* called with rpc->crpc_lock held */ void -srpc_abort_rpc(srpc_client_rpc_t *rpc, int why) +srpc_abort_rpc(struct srpc_client_rpc *rpc, int why) { LASSERT(why); @@ -1347,7 +1347,7 @@ srpc_abort_rpc(srpc_client_rpc_t *rpc, int why) /* called with rpc->crpc_lock held */ void -srpc_post_rpc(srpc_client_rpc_t *rpc) +srpc_post_rpc(struct srpc_client_rpc *rpc) { LASSERT(!rpc->crpc_aborted); LASSERT(srpc_data.rpc_state == SRPC_STATE_RUNNING); @@ -1411,7 +1411,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) { struct srpc_service_cd *scd; struct srpc_event *rpcev = ev->md.user_ptr; - srpc_client_rpc_t *crpc; + struct srpc_client_rpc *crpc; struct srpc_server_rpc *srpc; struct srpc_buffer *buffer; srpc_service_t *sv; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index fcbaf5eed601..93040f60a969 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -202,7 +202,7 @@ struct srpc_server_rpc { }; /* client-side state of a RPC */ -typedef struct srpc_client_rpc { +struct srpc_client_rpc { struct list_head crpc_list; /* chain on user's lists */ spinlock_t crpc_lock; /* serialize */ int crpc_service; @@ -232,10 +232,10 @@ typedef struct srpc_client_rpc { lnet_handle_md_t crpc_reqstmdh; lnet_handle_md_t crpc_replymdh; struct srpc_bulk crpc_bulk; -} srpc_client_rpc_t; +}; #define srpc_client_rpc_size(rpc) \ -offsetof(srpc_client_rpc_t, crpc_bulk.bk_iovs[(rpc)->crpc_bulk.bk_niov]) +offsetof(struct srpc_client_rpc, crpc_bulk.bk_iovs[(rpc)->crpc_bulk.bk_niov]) #define srpc_client_rpc_addref(rpc) \ do { \ @@ -357,9 +357,9 @@ typedef struct { * client */ int (*tso_prep_rpc)(struct sfw_test_unit *tsu, lnet_process_id_t dest, - srpc_client_rpc_t **rpc); /* prep a tests rpc */ + struct srpc_client_rpc **rpc); /* prep a tests rpc */ void (*tso_done_rpc)(struct sfw_test_unit *tsu, - srpc_client_rpc_t *rpc); /* done a test rpc */ + struct srpc_client_rpc *rpc); /* done a test rpc */ } sfw_test_client_ops_t; typedef struct sfw_test_instance { @@ -413,16 +413,16 @@ typedef struct sfw_test_case { sfw_test_client_ops_t *tsc_cli_ops; /* ops of test client */ } sfw_test_case_t; -srpc_client_rpc_t * +struct srpc_client_rpc * sfw_create_rpc(lnet_process_id_t peer, int service, unsigned features, int nbulkiov, int bulklen, - void (*done)(srpc_client_rpc_t *), void *priv); + void (*done)(struct srpc_client_rpc *), void *priv); int sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, unsigned features, - int nblk, int blklen, srpc_client_rpc_t **rpc); -void sfw_abort_rpc(srpc_client_rpc_t *rpc); -void sfw_post_rpc(srpc_client_rpc_t *rpc); -void sfw_client_rpc_done(srpc_client_rpc_t *rpc); + int nblk, int blklen, struct srpc_client_rpc **rpc); +void sfw_abort_rpc(struct srpc_client_rpc *rpc); +void sfw_post_rpc(struct srpc_client_rpc *rpc); +void sfw_client_rpc_done(struct srpc_client_rpc *rpc); void sfw_unpack_message(srpc_msg_t *msg); void sfw_free_pages(struct srpc_server_rpc *rpc); void sfw_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i); @@ -430,13 +430,13 @@ int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, int sink); int sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply); -srpc_client_rpc_t * +struct srpc_client_rpc * srpc_create_client_rpc(lnet_process_id_t peer, int service, int nbulkiov, int bulklen, - void (*rpc_done)(srpc_client_rpc_t *), - void (*rpc_fini)(srpc_client_rpc_t *), void *priv); -void srpc_post_rpc(srpc_client_rpc_t *rpc); -void srpc_abort_rpc(srpc_client_rpc_t *rpc, int why); + void (*rpc_done)(struct srpc_client_rpc *), + void (*rpc_fini)(struct srpc_client_rpc *), void *priv); +void srpc_post_rpc(struct srpc_client_rpc *rpc); +void srpc_abort_rpc(struct srpc_client_rpc *rpc, int why); void srpc_free_bulk(struct srpc_bulk *bk); struct srpc_bulk *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink); @@ -505,7 +505,7 @@ void sfw_shutdown(void); void srpc_shutdown(void); static inline void -srpc_destroy_client_rpc(srpc_client_rpc_t *rpc) +srpc_destroy_client_rpc(struct srpc_client_rpc *rpc) { LASSERT(rpc); LASSERT(!srpc_event_pending(rpc)); @@ -518,14 +518,14 @@ srpc_destroy_client_rpc(srpc_client_rpc_t *rpc) } static inline void -srpc_init_client_rpc(srpc_client_rpc_t *rpc, lnet_process_id_t peer, +srpc_init_client_rpc(struct srpc_client_rpc *rpc, lnet_process_id_t peer, int service, int nbulkiov, int bulklen, - void (*rpc_done)(srpc_client_rpc_t *), - void (*rpc_fini)(srpc_client_rpc_t *), void *priv) + void (*rpc_done)(struct srpc_client_rpc *), + void (*rpc_fini)(struct srpc_client_rpc *), void *priv) { LASSERT(nbulkiov <= LNET_MAX_IOV); - memset(rpc, 0, offsetof(srpc_client_rpc_t, + memset(rpc, 0, offsetof(struct srpc_client_rpc, crpc_bulk.bk_iovs[nbulkiov])); INIT_LIST_HEAD(&rpc->crpc_list); -- GitLab From 682513b8634f8d5128ec67551d8ff94aaafd1c5c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:33 -0400 Subject: [PATCH 2176/9938] staging: lustre: selftest: convert srpc_service_t to proper struct Turn typedef srpc_service_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 3 ++- .../staging/lustre/lnet/selftest/console.c | 3 ++- .../staging/lustre/lnet/selftest/framework.c | 8 +++--- .../staging/lustre/lnet/selftest/ping_test.c | 3 ++- drivers/staging/lustre/lnet/selftest/rpc.c | 10 +++---- .../staging/lustre/lnet/selftest/selftest.h | 26 +++++++++---------- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 6657a58c50b6..f2c37b44e1c0 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -497,7 +497,8 @@ void brw_init_test_client(void) brw_test_client.tso_done_rpc = brw_client_done_rpc; }; -srpc_service_t brw_test_service; +struct srpc_service brw_test_service; + void brw_init_test_service(void) { brw_test_service.sv_id = SRPC_SERVICE_BRW; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index dcfc83d0ad41..1352310d2727 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1986,7 +1986,8 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) return rc; } -static srpc_service_t lstcon_acceptor_service; +static struct srpc_service lstcon_acceptor_service; + static void lstcon_init_acceptor_service(void) { /* initialize selftest console acceptor service table */ diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 931a517b9ed0..20015d641c04 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -135,7 +135,7 @@ sfw_find_test_case(int id) } static int -sfw_register_test(srpc_service_t *service, sfw_test_client_ops_t *cliops) +sfw_register_test(struct srpc_service *service, sfw_test_client_ops_t *cliops) { sfw_test_case_t *tsc; @@ -1584,7 +1584,7 @@ sfw_post_rpc(struct srpc_client_rpc *rpc) spin_unlock(&rpc->crpc_lock); } -static srpc_service_t sfw_services[] = { +static struct srpc_service sfw_services[] = { { /* sv_id */ SRPC_SERVICE_DEBUG, /* sv_name */ "debug", @@ -1628,7 +1628,7 @@ sfw_startup(void) int i; int rc; int error; - srpc_service_t *sv; + struct srpc_service *sv; sfw_test_case_t *tsc; if (session_timeout < 0) { @@ -1721,7 +1721,7 @@ sfw_startup(void) void sfw_shutdown(void) { - srpc_service_t *sv; + struct srpc_service *sv; sfw_test_case_t *tsc; int i; diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index 1f2ddf6a9f88..c09b599b06ad 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -219,7 +219,8 @@ void ping_init_test_client(void) ping_test_client.tso_done_rpc = ping_client_done_rpc; } -srpc_service_t ping_test_service; +struct srpc_service ping_test_service; + void ping_init_test_service(void) { ping_test_service.sv_id = SRPC_SERVICE_PING; diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index a8f0b2099246..e3cd40786cac 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -56,7 +56,7 @@ typedef enum { static struct smoketest_rpc { spinlock_t rpc_glock; /* global lock */ - srpc_service_t *rpc_services[SRPC_SERVICE_MAX_ID + 1]; + struct srpc_service *rpc_services[SRPC_SERVICE_MAX_ID + 1]; lnet_handle_eq_t rpc_lnet_eq; /* _the_ LNet event queue */ srpc_state_t rpc_state; srpc_counters_t rpc_counters; @@ -338,7 +338,7 @@ srpc_add_service(struct srpc_service *sv) } int -srpc_remove_service(srpc_service_t *sv) +srpc_remove_service(struct srpc_service *sv) { int id = sv->sv_id; @@ -755,7 +755,7 @@ srpc_abort_service(struct srpc_service *sv) } void -srpc_shutdown_service(srpc_service_t *sv) +srpc_shutdown_service(struct srpc_service *sv) { struct srpc_service_cd *scd; struct srpc_server_rpc *rpc; @@ -1414,7 +1414,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) struct srpc_client_rpc *crpc; struct srpc_server_rpc *srpc; struct srpc_buffer *buffer; - srpc_service_t *sv; + struct srpc_service *sv; srpc_msg_t *msg; srpc_msg_type_t type; @@ -1663,7 +1663,7 @@ srpc_shutdown(void) spin_lock(&srpc_data.rpc_glock); for (i = 0; i <= SRPC_SERVICE_MAX_ID; i++) { - srpc_service_t *sv = srpc_data.rpc_services[i]; + struct srpc_service *sv = srpc_data.rpc_services[i]; LASSERTF(!sv, "service not empty: id %d, name %s\n", i, sv->sv_name); diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 93040f60a969..2052b1191c4f 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -307,7 +307,7 @@ struct srpc_service_cd { #define SFW_FRWK_WI_MIN 16 #define SFW_FRWK_WI_MAX 256 -typedef struct srpc_service { +struct srpc_service { int sv_id; /* service id */ const char *sv_name; /* human readable name */ int sv_wi_total; /* total server workitems */ @@ -321,7 +321,7 @@ typedef struct srpc_service { */ int (*sv_handler)(struct srpc_server_rpc *); int (*sv_bulk_ready)(struct srpc_server_rpc *, int); -} srpc_service_t; +}; typedef struct { struct list_head sn_list; /* chain on fw_zombie_sessions */ @@ -409,7 +409,7 @@ typedef struct sfw_test_unit { typedef struct sfw_test_case { struct list_head tsc_list; /* chain on fw_tests */ - srpc_service_t *tsc_srv_service; /* test service */ + struct srpc_service *tsc_srv_service; /* test service */ sfw_test_client_ops_t *tsc_cli_ops; /* ops of test client */ } sfw_test_case_t; @@ -442,13 +442,13 @@ struct srpc_bulk *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink); int srpc_send_rpc(struct swi_workitem *wi); int srpc_send_reply(struct srpc_server_rpc *rpc); -int srpc_add_service(srpc_service_t *sv); -int srpc_remove_service(srpc_service_t *sv); -void srpc_shutdown_service(srpc_service_t *sv); -void srpc_abort_service(srpc_service_t *sv); -int srpc_finish_service(srpc_service_t *sv); -int srpc_service_add_buffers(srpc_service_t *sv, int nbuffer); -void srpc_service_remove_buffers(srpc_service_t *sv, int nbuffer); +int srpc_add_service(struct srpc_service *sv); +int srpc_remove_service(struct srpc_service *sv); +void srpc_shutdown_service(struct srpc_service *sv); +void srpc_abort_service(struct srpc_service *sv); +int srpc_finish_service(struct srpc_service *sv); +int srpc_service_add_buffers(struct srpc_service *sv, int nbuffer); +void srpc_service_remove_buffers(struct srpc_service *sv, int nbuffer); void srpc_get_counters(srpc_counters_t *cnt); void srpc_set_counters(const srpc_counters_t *cnt); @@ -595,7 +595,7 @@ do { \ } while (0) static inline void -srpc_wait_service_shutdown(srpc_service_t *sv) +srpc_wait_service_shutdown(struct srpc_service *sv) { int i = 2; @@ -613,13 +613,13 @@ srpc_wait_service_shutdown(srpc_service_t *sv) extern sfw_test_client_ops_t brw_test_client; void brw_init_test_client(void); -extern srpc_service_t brw_test_service; +extern struct srpc_service brw_test_service; void brw_init_test_service(void); extern sfw_test_client_ops_t ping_test_client; void ping_init_test_client(void); -extern srpc_service_t ping_test_service; +extern struct srpc_service ping_test_service; void ping_init_test_service(void); #endif /* __SELFTEST_SELFTEST_H__ */ -- GitLab From 693d26648a4dcbb08b8ea77bade6ac02fde8a046 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:34 -0400 Subject: [PATCH 2177/9938] staging: lustre: selftest: convert sfw_session_t to proper struct Turn typedef sfw_session_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 6 +-- .../staging/lustre/lnet/selftest/framework.c | 40 +++++++++---------- .../staging/lustre/lnet/selftest/ping_test.c | 8 ++-- .../staging/lustre/lnet/selftest/selftest.h | 6 +-- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index f2c37b44e1c0..6b020837cdc1 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -69,7 +69,7 @@ brw_client_fini(sfw_test_instance_t *tsi) static int brw_client_init(sfw_test_instance_t *tsi) { - sfw_session_t *sn = tsi->tsi_batch->bat_session; + struct sfw_session *sn = tsi->tsi_batch->bat_session; int flags; int npg; int len; @@ -259,7 +259,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, { struct srpc_bulk *bulk = tsu->tsu_private; sfw_test_instance_t *tsi = tsu->tsu_instance; - sfw_session_t *sn = tsi->tsi_batch->bat_session; + struct sfw_session *sn = tsi->tsi_batch->bat_session; struct srpc_client_rpc *rpc; srpc_brw_reqst_t *req; int flags; @@ -317,7 +317,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) { __u64 magic = BRW_MAGIC; sfw_test_instance_t *tsi = tsu->tsu_instance; - sfw_session_t *sn = tsi->tsi_batch->bat_session; + struct sfw_session *sn = tsi->tsi_batch->bat_session; srpc_msg_t *msg = &rpc->crpc_replymsg; srpc_brw_reply_t *reply = &msg->msg_body.brw_reply; srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 20015d641c04..a637b2bda140 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -109,14 +109,14 @@ static struct smoketest_framework { struct list_head fw_tests; /* registered test cases */ atomic_t fw_nzombies; /* # zombie sessions */ spinlock_t fw_lock; /* serialise */ - sfw_session_t *fw_session; /* _the_ session */ + struct sfw_session *fw_session; /* _the_ session */ int fw_shuttingdown; /* shutdown in progress */ struct srpc_server_rpc *fw_active_srpc;/* running RPC */ } sfw_data; /* forward ref's */ int sfw_stop_batch(sfw_batch_t *tsb, int force); -void sfw_destroy_session(sfw_session_t *sn); +void sfw_destroy_session(struct sfw_session *sn); static inline sfw_test_case_t * sfw_find_test_case(int id) @@ -159,7 +159,7 @@ sfw_register_test(struct srpc_service *service, sfw_test_client_ops_t *cliops) static void sfw_add_session_timer(void) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; struct stt_timer *timer = &sn->sn_timer; LASSERT(!sfw_data.fw_shuttingdown); @@ -177,7 +177,7 @@ sfw_add_session_timer(void) static int sfw_del_session_timer(void) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; if (!sn || !sn->sn_timer_active) return 0; @@ -196,7 +196,7 @@ static void sfw_deactivate_session(void) __must_hold(&sfw_data.fw_lock) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; int nactive = 0; sfw_batch_t *tsb; sfw_test_case_t *tsc; @@ -239,7 +239,7 @@ __must_hold(&sfw_data.fw_lock) static void sfw_session_expired(void *data) { - sfw_session_t *sn = data; + struct sfw_session *sn = data; spin_lock(&sfw_data.fw_lock); @@ -257,12 +257,12 @@ sfw_session_expired(void *data) } static inline void -sfw_init_session(sfw_session_t *sn, lst_sid_t sid, +sfw_init_session(struct sfw_session *sn, lst_sid_t sid, unsigned features, const char *name) { struct stt_timer *timer = &sn->sn_timer; - memset(sn, 0, sizeof(sfw_session_t)); + memset(sn, 0, sizeof(struct sfw_session)); INIT_LIST_HEAD(&sn->sn_list); INIT_LIST_HEAD(&sn->sn_batches); atomic_set(&sn->sn_refcount, 1); /* +1 for caller */ @@ -321,7 +321,7 @@ sfw_client_rpc_fini(struct srpc_client_rpc *rpc) static sfw_batch_t * sfw_find_batch(lst_bid_t bid) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; sfw_batch_t *bat; LASSERT(sn); @@ -337,7 +337,7 @@ sfw_find_batch(lst_bid_t bid) static sfw_batch_t * sfw_bid2batch(lst_bid_t bid) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; sfw_batch_t *bat; LASSERT(sn); @@ -363,7 +363,7 @@ sfw_bid2batch(lst_bid_t bid) static int sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; sfw_counters_t *cnt = &reply->str_fw; sfw_batch_t *bat; @@ -404,7 +404,7 @@ sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply) int sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; srpc_msg_t *msg = container_of(request, srpc_msg_t, msg_body.mksn_reqst); int cplen = 0; @@ -449,7 +449,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) } /* brand new or create by force */ - LIBCFS_ALLOC(sn, sizeof(sfw_session_t)); + LIBCFS_ALLOC(sn, sizeof(struct sfw_session)); if (!sn) { CERROR("dropping RPC mksn under memory pressure\n"); return -ENOMEM; @@ -475,7 +475,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) static int sfw_remove_session(srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; reply->rmsn_sid = !sn ? LST_INVALID_SID : sn->sn_id; @@ -507,7 +507,7 @@ sfw_remove_session(srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply) static int sfw_debug_session(srpc_debug_reqst_t *request, srpc_debug_reply_t *reply) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; if (!sn) { reply->dbg_status = ESRCH; @@ -666,7 +666,7 @@ sfw_destroy_batch(sfw_batch_t *tsb) } void -sfw_destroy_session(sfw_session_t *sn) +sfw_destroy_session(struct sfw_session *sn) { sfw_batch_t *batch; @@ -828,7 +828,7 @@ sfw_test_unit_done(sfw_test_unit_t *tsu) { sfw_test_instance_t *tsi = tsu->tsu_instance; sfw_batch_t *tsb = tsi->tsi_batch; - sfw_session_t *sn = tsb->bat_session; + struct sfw_session *sn = tsb->bat_session; LASSERT(sfw_test_active(tsi)); @@ -1115,7 +1115,7 @@ sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, static int sfw_add_test(struct srpc_server_rpc *rpc) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply; srpc_test_reqst_t *request; int rc; @@ -1185,7 +1185,7 @@ sfw_add_test(struct srpc_server_rpc *rpc) static int sfw_control_batch(srpc_batch_reqst_t *request, srpc_batch_reply_t *reply) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; int rc = 0; sfw_batch_t *bat; @@ -1261,7 +1261,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) if (sv->sv_id != SRPC_SERVICE_MAKE_SESSION && sv->sv_id != SRPC_SERVICE_DEBUG) { - sfw_session_t *sn = sfw_data.fw_session; + struct sfw_session *sn = sfw_data.fw_session; if (sn && sn->sn_features != request->msg_ses_feats) { diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index c09b599b06ad..df33a139ad90 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -58,7 +58,7 @@ static struct lst_ping_data lst_ping_data; static int ping_client_init(sfw_test_instance_t *tsi) { - sfw_session_t *sn = tsi->tsi_batch->bat_session; + struct sfw_session *sn = tsi->tsi_batch->bat_session; LASSERT(tsi->tsi_is_client); LASSERT(sn && !(sn->sn_features & ~LST_FEATS_MASK)); @@ -72,7 +72,7 @@ ping_client_init(sfw_test_instance_t *tsi) static void ping_client_fini(sfw_test_instance_t *tsi) { - sfw_session_t *sn = tsi->tsi_batch->bat_session; + struct sfw_session *sn = tsi->tsi_batch->bat_session; int errors; LASSERT(sn); @@ -91,7 +91,7 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, { srpc_ping_reqst_t *req; sfw_test_instance_t *tsi = tsu->tsu_instance; - sfw_session_t *sn = tsi->tsi_batch->bat_session; + struct sfw_session *sn = tsi->tsi_batch->bat_session; struct timespec64 ts; int rc; @@ -121,7 +121,7 @@ static void ping_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) { sfw_test_instance_t *tsi = tsu->tsu_instance; - sfw_session_t *sn = tsi->tsi_batch->bat_session; + struct sfw_session *sn = tsi->tsi_batch->bat_session; srpc_ping_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.ping_reqst; srpc_ping_reply_t *reply = &rpc->crpc_replymsg.msg_body.ping_reply; struct timespec64 ts; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 2052b1191c4f..18278b8a047c 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -323,7 +323,7 @@ struct srpc_service { int (*sv_bulk_ready)(struct srpc_server_rpc *, int); }; -typedef struct { +struct sfw_session { struct list_head sn_list; /* chain on fw_zombie_sessions */ lst_sid_t sn_id; /* unique identifier */ unsigned int sn_timeout; /* # seconds' inactivity to expire */ @@ -336,7 +336,7 @@ typedef struct { atomic_t sn_brw_errors; atomic_t sn_ping_errors; unsigned long sn_started; -} sfw_session_t; +}; #define sfw_sid_equal(sid0, sid1) ((sid0).ses_nid == (sid1).ses_nid && \ (sid0).ses_stamp == (sid1).ses_stamp) @@ -345,7 +345,7 @@ typedef struct { struct list_head bat_list; /* chain on sn_batches */ lst_bid_t bat_id; /* batch id */ int bat_error; /* error code of batch */ - sfw_session_t *bat_session; /* batch's session */ + struct sfw_session *bat_session; /* batch's session */ atomic_t bat_nactive; /* # of active tests */ struct list_head bat_tests; /* test instances */ } sfw_batch_t; -- GitLab From 074bca96640d91623a6a50d060e05ddd8d7200bc Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:35 -0400 Subject: [PATCH 2178/9938] staging: lustre: selftest: convert sfw_batch_t to proper struct Turn typedef sfw_batch_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/framework.c | 38 +++++++++---------- .../staging/lustre/lnet/selftest/selftest.h | 6 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index a637b2bda140..e1d6996d3c9f 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -115,7 +115,7 @@ static struct smoketest_framework { } sfw_data; /* forward ref's */ -int sfw_stop_batch(sfw_batch_t *tsb, int force); +int sfw_stop_batch(struct sfw_batch *tsb, int force); void sfw_destroy_session(struct sfw_session *sn); static inline sfw_test_case_t * @@ -198,7 +198,7 @@ __must_hold(&sfw_data.fw_lock) { struct sfw_session *sn = sfw_data.fw_session; int nactive = 0; - sfw_batch_t *tsb; + struct sfw_batch *tsb; sfw_test_case_t *tsc; if (!sn) @@ -318,11 +318,11 @@ sfw_client_rpc_fini(struct srpc_client_rpc *rpc) spin_unlock(&sfw_data.fw_lock); } -static sfw_batch_t * +static struct sfw_batch * sfw_find_batch(lst_bid_t bid) { struct sfw_session *sn = sfw_data.fw_session; - sfw_batch_t *bat; + struct sfw_batch *bat; LASSERT(sn); @@ -334,11 +334,11 @@ sfw_find_batch(lst_bid_t bid) return NULL; } -static sfw_batch_t * +static struct sfw_batch * sfw_bid2batch(lst_bid_t bid) { struct sfw_session *sn = sfw_data.fw_session; - sfw_batch_t *bat; + struct sfw_batch *bat; LASSERT(sn); @@ -346,7 +346,7 @@ sfw_bid2batch(lst_bid_t bid) if (bat) return bat; - LIBCFS_ALLOC(bat, sizeof(sfw_batch_t)); + LIBCFS_ALLOC(bat, sizeof(struct sfw_batch)); if (!bat) return NULL; @@ -365,7 +365,7 @@ sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply) { struct sfw_session *sn = sfw_data.fw_session; sfw_counters_t *cnt = &reply->str_fw; - sfw_batch_t *bat; + struct sfw_batch *bat; reply->str_sid = !sn ? LST_INVALID_SID : sn->sn_id; @@ -648,7 +648,7 @@ sfw_destroy_test_instance(sfw_test_instance_t *tsi) } static void -sfw_destroy_batch(sfw_batch_t *tsb) +sfw_destroy_batch(struct sfw_batch *tsb) { sfw_test_instance_t *tsi; @@ -662,20 +662,20 @@ sfw_destroy_batch(sfw_batch_t *tsb) sfw_destroy_test_instance(tsi); } - LIBCFS_FREE(tsb, sizeof(sfw_batch_t)); + LIBCFS_FREE(tsb, sizeof(struct sfw_batch)); } void sfw_destroy_session(struct sfw_session *sn) { - sfw_batch_t *batch; + struct sfw_batch *batch; LASSERT(list_empty(&sn->sn_list)); LASSERT(sn != sfw_data.fw_session); while (!list_empty(&sn->sn_batches)) { batch = list_entry(sn->sn_batches.next, - sfw_batch_t, bat_list); + struct sfw_batch, bat_list); list_del_init(&batch->bat_list); sfw_destroy_batch(batch); } @@ -729,7 +729,7 @@ sfw_unpack_addtest_req(srpc_msg_t *msg) } static int -sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) +sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) { srpc_msg_t *msg = &rpc->srpc_reqstbuf->buf_msg; srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; @@ -827,7 +827,7 @@ static void sfw_test_unit_done(sfw_test_unit_t *tsu) { sfw_test_instance_t *tsi = tsu->tsu_instance; - sfw_batch_t *tsb = tsi->tsi_batch; + struct sfw_batch *tsb = tsi->tsi_batch; struct sfw_session *sn = tsb->bat_session; LASSERT(sfw_test_active(tsi)); @@ -991,7 +991,7 @@ sfw_run_test(struct swi_workitem *wi) } static int -sfw_run_batch(sfw_batch_t *tsb) +sfw_run_batch(struct sfw_batch *tsb) { struct swi_workitem *wi; sfw_test_unit_t *tsu; @@ -1026,7 +1026,7 @@ sfw_run_batch(sfw_batch_t *tsb) } int -sfw_stop_batch(sfw_batch_t *tsb, int force) +sfw_stop_batch(struct sfw_batch *tsb, int force) { sfw_test_instance_t *tsi; struct srpc_client_rpc *rpc; @@ -1068,7 +1068,7 @@ sfw_stop_batch(sfw_batch_t *tsb, int force) } static int -sfw_query_batch(sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply) +sfw_query_batch(struct sfw_batch *tsb, int testidx, srpc_batch_reply_t *reply) { sfw_test_instance_t *tsi; @@ -1119,7 +1119,7 @@ sfw_add_test(struct srpc_server_rpc *rpc) srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply; srpc_test_reqst_t *request; int rc; - sfw_batch_t *bat; + struct sfw_batch *bat; request = &rpc->srpc_reqstbuf->buf_msg.msg_body.tes_reqst; reply->tsr_sid = !sn ? LST_INVALID_SID : sn->sn_id; @@ -1187,7 +1187,7 @@ sfw_control_batch(srpc_batch_reqst_t *request, srpc_batch_reply_t *reply) { struct sfw_session *sn = sfw_data.fw_session; int rc = 0; - sfw_batch_t *bat; + struct sfw_batch *bat; reply->bar_sid = !sn ? LST_INVALID_SID : sn->sn_id; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 18278b8a047c..550fa329fbf8 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -341,14 +341,14 @@ struct sfw_session { #define sfw_sid_equal(sid0, sid1) ((sid0).ses_nid == (sid1).ses_nid && \ (sid0).ses_stamp == (sid1).ses_stamp) -typedef struct { +struct sfw_batch { struct list_head bat_list; /* chain on sn_batches */ lst_bid_t bat_id; /* batch id */ int bat_error; /* error code of batch */ struct sfw_session *bat_session; /* batch's session */ atomic_t bat_nactive; /* # of active tests */ struct list_head bat_tests; /* test instances */ -} sfw_batch_t; +}; typedef struct { int (*tso_init)(struct sfw_test_instance *tsi); /* initialize test @@ -365,7 +365,7 @@ typedef struct { typedef struct sfw_test_instance { struct list_head tsi_list; /* chain on batch */ int tsi_service; /* test type */ - sfw_batch_t *tsi_batch; /* batch */ + struct sfw_batch *tsi_batch; /* batch */ sfw_test_client_ops_t *tsi_ops; /* test client operation */ -- GitLab From d9c460ea761c5be5c5a386416be2517c824bd293 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:36 -0400 Subject: [PATCH 2179/9938] staging: lustre: selftest: convert sfw_test_client_ops_t to proper struct Turn typedef sfw_test_client_ops_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/brw_test.c | 3 ++- drivers/staging/lustre/lnet/selftest/framework.c | 2 +- drivers/staging/lustre/lnet/selftest/ping_test.c | 3 ++- drivers/staging/lustre/lnet/selftest/selftest.h | 14 +++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 6b020837cdc1..558f2a83e3e4 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -488,7 +488,8 @@ brw_server_handle(struct srpc_server_rpc *rpc) return 0; } -sfw_test_client_ops_t brw_test_client; +struct sfw_test_client_ops brw_test_client; + void brw_init_test_client(void) { brw_test_client.tso_init = brw_client_init; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index e1d6996d3c9f..bf52d7a6d7de 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -135,7 +135,7 @@ sfw_find_test_case(int id) } static int -sfw_register_test(struct srpc_service *service, sfw_test_client_ops_t *cliops) +sfw_register_test(struct srpc_service *service, struct sfw_test_client_ops *cliops) { sfw_test_case_t *tsc; diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index df33a139ad90..be13004886f2 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -210,7 +210,8 @@ ping_server_handle(struct srpc_server_rpc *rpc) return 0; } -sfw_test_client_ops_t ping_test_client; +struct sfw_test_client_ops ping_test_client; + void ping_init_test_client(void) { ping_test_client.tso_init = ping_client_init; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 550fa329fbf8..4ab8d10a4458 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -350,7 +350,7 @@ struct sfw_batch { struct list_head bat_tests; /* test instances */ }; -typedef struct { +struct sfw_test_client_ops { int (*tso_init)(struct sfw_test_instance *tsi); /* initialize test * client */ void (*tso_fini)(struct sfw_test_instance *tsi); /* finalize test @@ -360,13 +360,13 @@ typedef struct { struct srpc_client_rpc **rpc); /* prep a tests rpc */ void (*tso_done_rpc)(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc); /* done a test rpc */ -} sfw_test_client_ops_t; +}; typedef struct sfw_test_instance { struct list_head tsi_list; /* chain on batch */ int tsi_service; /* test type */ struct sfw_batch *tsi_batch; /* batch */ - sfw_test_client_ops_t *tsi_ops; /* test client operation + struct sfw_test_client_ops *tsi_ops; /* test client operation */ /* public parameter for all test units */ @@ -409,8 +409,8 @@ typedef struct sfw_test_unit { typedef struct sfw_test_case { struct list_head tsc_list; /* chain on fw_tests */ - struct srpc_service *tsc_srv_service; /* test service */ - sfw_test_client_ops_t *tsc_cli_ops; /* ops of test client */ + struct srpc_service *tsc_srv_service; /* test service */ + struct sfw_test_client_ops *tsc_cli_ops; /* ops of test client */ } sfw_test_case_t; struct srpc_client_rpc * @@ -610,13 +610,13 @@ srpc_wait_service_shutdown(struct srpc_service *sv) } } -extern sfw_test_client_ops_t brw_test_client; +extern struct sfw_test_client_ops brw_test_client; void brw_init_test_client(void); extern struct srpc_service brw_test_service; void brw_init_test_service(void); -extern sfw_test_client_ops_t ping_test_client; +extern struct sfw_test_client_ops ping_test_client; void ping_init_test_client(void); extern struct srpc_service ping_test_service; -- GitLab From 7ca48d8585ee50789e5ae2fa77ffb355ae14cabf Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:37 -0400 Subject: [PATCH 2180/9938] staging: lustre: selftest: convert sfw_test_instance_t to proper struct Turn typedef sfw_test_instance_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 8 +++--- .../staging/lustre/lnet/selftest/framework.c | 26 +++++++++---------- .../staging/lustre/lnet/selftest/ping_test.c | 8 +++--- .../staging/lustre/lnet/selftest/selftest.h | 6 ++--- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 558f2a83e3e4..bb50ee1f836d 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -49,7 +49,7 @@ module_param(brw_inject_errors, int, 0644); MODULE_PARM_DESC(brw_inject_errors, "# data errors to inject randomly, zero by default"); static void -brw_client_fini(sfw_test_instance_t *tsi) +brw_client_fini(struct sfw_test_instance *tsi) { struct srpc_bulk *bulk; sfw_test_unit_t *tsu; @@ -67,7 +67,7 @@ brw_client_fini(sfw_test_instance_t *tsi) } static int -brw_client_init(sfw_test_instance_t *tsi) +brw_client_init(struct sfw_test_instance *tsi) { struct sfw_session *sn = tsi->tsi_batch->bat_session; int flags; @@ -258,7 +258,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, struct srpc_client_rpc **rpcpp) { struct srpc_bulk *bulk = tsu->tsu_private; - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; struct srpc_client_rpc *rpc; srpc_brw_reqst_t *req; @@ -316,7 +316,7 @@ static void brw_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) { __u64 magic = BRW_MAGIC; - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; srpc_msg_t *msg = &rpc->crpc_replymsg; srpc_brw_reply_t *reply = &msg->msg_body.brw_reply; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index bf52d7a6d7de..d783f08d3aed 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -529,7 +529,7 @@ static void sfw_test_rpc_fini(struct srpc_client_rpc *rpc) { sfw_test_unit_t *tsu = rpc->crpc_priv; - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; /* Called with hold of tsi->tsi_lock */ LASSERT(list_empty(&rpc->crpc_list)); @@ -537,7 +537,7 @@ sfw_test_rpc_fini(struct srpc_client_rpc *rpc) } static inline int -sfw_test_buffers(sfw_test_instance_t *tsi) +sfw_test_buffers(struct sfw_test_instance *tsi) { struct sfw_test_case *tsc; struct srpc_service *svc; @@ -614,7 +614,7 @@ sfw_unload_test(struct sfw_test_instance *tsi) } static void -sfw_destroy_test_instance(sfw_test_instance_t *tsi) +sfw_destroy_test_instance(struct sfw_test_instance *tsi) { struct srpc_client_rpc *rpc; sfw_test_unit_t *tsu; @@ -650,14 +650,14 @@ sfw_destroy_test_instance(sfw_test_instance_t *tsi) static void sfw_destroy_batch(struct sfw_batch *tsb) { - sfw_test_instance_t *tsi; + struct sfw_test_instance *tsi; LASSERT(!sfw_batch_active(tsb)); LASSERT(list_empty(&tsb->bat_list)); while (!list_empty(&tsb->bat_tests)) { tsi = list_entry(tsb->bat_tests.next, - sfw_test_instance_t, tsi_list); + struct sfw_test_instance, tsi_list); list_del_init(&tsi->tsi_list); sfw_destroy_test_instance(tsi); } @@ -736,7 +736,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) struct srpc_bulk *bk = rpc->srpc_bulk; int ndest = req->tsr_ndest; sfw_test_unit_t *tsu; - sfw_test_instance_t *tsi; + struct sfw_test_instance *tsi; int i; int rc; @@ -826,7 +826,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) static void sfw_test_unit_done(sfw_test_unit_t *tsu) { - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_batch *tsb = tsi->tsi_batch; struct sfw_session *sn = tsb->bat_session; @@ -869,7 +869,7 @@ static void sfw_test_rpc_done(struct srpc_client_rpc *rpc) { sfw_test_unit_t *tsu = rpc->crpc_priv; - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; int done = 0; tsi->tsi_ops->tso_done_rpc(tsu, rpc); @@ -905,7 +905,7 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, struct srpc_client_rpc **rpcpp) { struct srpc_client_rpc *rpc = NULL; - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; spin_lock(&tsi->tsi_lock); @@ -945,7 +945,7 @@ static int sfw_run_test(struct swi_workitem *wi) { sfw_test_unit_t *tsu = wi->swi_workitem.wi_data; - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; struct srpc_client_rpc *rpc = NULL; LASSERT(wi == &tsu->tsu_worker); @@ -995,7 +995,7 @@ sfw_run_batch(struct sfw_batch *tsb) { struct swi_workitem *wi; sfw_test_unit_t *tsu; - sfw_test_instance_t *tsi; + struct sfw_test_instance *tsi; if (sfw_batch_active(tsb)) { CDEBUG(D_NET, "Batch already active: %llu (%d)\n", @@ -1028,7 +1028,7 @@ sfw_run_batch(struct sfw_batch *tsb) int sfw_stop_batch(struct sfw_batch *tsb, int force) { - sfw_test_instance_t *tsi; + struct sfw_test_instance *tsi; struct srpc_client_rpc *rpc; if (!sfw_batch_active(tsb)) { @@ -1070,7 +1070,7 @@ sfw_stop_batch(struct sfw_batch *tsb, int force) static int sfw_query_batch(struct sfw_batch *tsb, int testidx, srpc_batch_reply_t *reply) { - sfw_test_instance_t *tsi; + struct sfw_test_instance *tsi; if (testidx < 0) return -EINVAL; diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index be13004886f2..4e454283da22 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -56,7 +56,7 @@ struct lst_ping_data { static struct lst_ping_data lst_ping_data; static int -ping_client_init(sfw_test_instance_t *tsi) +ping_client_init(struct sfw_test_instance *tsi) { struct sfw_session *sn = tsi->tsi_batch->bat_session; @@ -70,7 +70,7 @@ ping_client_init(sfw_test_instance_t *tsi) } static void -ping_client_fini(sfw_test_instance_t *tsi) +ping_client_fini(struct sfw_test_instance *tsi) { struct sfw_session *sn = tsi->tsi_batch->bat_session; int errors; @@ -90,7 +90,7 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, struct srpc_client_rpc **rpc) { srpc_ping_reqst_t *req; - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; struct timespec64 ts; int rc; @@ -120,7 +120,7 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, static void ping_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) { - sfw_test_instance_t *tsi = tsu->tsu_instance; + struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; srpc_ping_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.ping_reqst; srpc_ping_reply_t *reply = &rpc->crpc_replymsg.msg_body.ping_reply; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 4ab8d10a4458..a95bdca02c30 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -362,7 +362,7 @@ struct sfw_test_client_ops { struct srpc_client_rpc *rpc); /* done a test rpc */ }; -typedef struct sfw_test_instance { +struct sfw_test_instance { struct list_head tsi_list; /* chain on batch */ int tsi_service; /* test type */ struct sfw_batch *tsi_batch; /* batch */ @@ -389,7 +389,7 @@ typedef struct sfw_test_instance { test_bulk_req_t bulk_v0; /* bulk parameter */ test_bulk_req_v1_t bulk_v1; /* bulk v1 parameter */ } tsi_u; -} sfw_test_instance_t; +}; /* XXX: trailing (PAGE_SIZE % sizeof(lnet_process_id_t)) bytes at the end of * pages are not used */ @@ -402,7 +402,7 @@ typedef struct sfw_test_unit { struct list_head tsu_list; /* chain on lst_test_instance */ lnet_process_id_t tsu_dest; /* id of dest node */ int tsu_loop; /* loop count of the test */ - sfw_test_instance_t *tsu_instance; /* pointer to test instance */ + struct sfw_test_instance *tsu_instance; /* pointer to test instance */ void *tsu_private; /* private data */ struct swi_workitem tsu_worker; /* workitem of the test unit */ } sfw_test_unit_t; -- GitLab From d875b0ce5f218bc9848a93a154b9315c9e5efaf7 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:38 -0400 Subject: [PATCH 2181/9938] staging: lustre: selftest: convert sfw_test_unit_t to proper struct Turn typedef sfw_test_unit_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 8 ++++---- .../staging/lustre/lnet/selftest/framework.c | 20 +++++++++---------- .../staging/lustre/lnet/selftest/ping_test.c | 4 ++-- .../staging/lustre/lnet/selftest/selftest.h | 6 +++--- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index bb50ee1f836d..bbb003da3e3e 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -52,7 +52,7 @@ static void brw_client_fini(struct sfw_test_instance *tsi) { struct srpc_bulk *bulk; - sfw_test_unit_t *tsu; + struct sfw_test_unit *tsu; LASSERT(tsi->tsi_is_client); @@ -75,7 +75,7 @@ brw_client_init(struct sfw_test_instance *tsi) int len; int opc; struct srpc_bulk *bulk; - sfw_test_unit_t *tsu; + struct sfw_test_unit *tsu; LASSERT(sn); LASSERT(tsi->tsi_is_client); @@ -254,7 +254,7 @@ brw_check_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) } static int -brw_client_prep_rpc(sfw_test_unit_t *tsu, +brw_client_prep_rpc(struct sfw_test_unit *tsu, lnet_process_id_t dest, struct srpc_client_rpc **rpcpp) { struct srpc_bulk *bulk = tsu->tsu_private; @@ -313,7 +313,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, } static void -brw_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) +brw_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc) { __u64 magic = BRW_MAGIC; struct sfw_test_instance *tsi = tsu->tsu_instance; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index d783f08d3aed..31b564759d7f 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -528,7 +528,7 @@ sfw_debug_session(srpc_debug_reqst_t *request, srpc_debug_reply_t *reply) static void sfw_test_rpc_fini(struct srpc_client_rpc *rpc) { - sfw_test_unit_t *tsu = rpc->crpc_priv; + struct sfw_test_unit *tsu = rpc->crpc_priv; struct sfw_test_instance *tsi = tsu->tsu_instance; /* Called with hold of tsi->tsi_lock */ @@ -617,7 +617,7 @@ static void sfw_destroy_test_instance(struct sfw_test_instance *tsi) { struct srpc_client_rpc *rpc; - sfw_test_unit_t *tsu; + struct sfw_test_unit *tsu; if (!tsi->tsi_is_client) goto clean; @@ -630,7 +630,7 @@ sfw_destroy_test_instance(struct sfw_test_instance *tsi) while (!list_empty(&tsi->tsi_units)) { tsu = list_entry(tsi->tsi_units.next, - sfw_test_unit_t, tsu_list); + struct sfw_test_unit, tsu_list); list_del(&tsu->tsu_list); LIBCFS_FREE(tsu, sizeof(*tsu)); } @@ -735,7 +735,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; struct srpc_bulk *bk = rpc->srpc_bulk; int ndest = req->tsr_ndest; - sfw_test_unit_t *tsu; + struct sfw_test_unit *tsu; struct sfw_test_instance *tsi; int i; int rc; @@ -795,7 +795,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) sfw_unpack_id(id); for (j = 0; j < tsi->tsi_concur; j++) { - LIBCFS_ALLOC(tsu, sizeof(sfw_test_unit_t)); + LIBCFS_ALLOC(tsu, sizeof(struct sfw_test_unit)); if (!tsu) { rc = -ENOMEM; CERROR("Can't allocate tsu for %d\n", @@ -824,7 +824,7 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) } static void -sfw_test_unit_done(sfw_test_unit_t *tsu) +sfw_test_unit_done(struct sfw_test_unit *tsu) { struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_batch *tsb = tsi->tsi_batch; @@ -868,7 +868,7 @@ sfw_test_unit_done(sfw_test_unit_t *tsu) static void sfw_test_rpc_done(struct srpc_client_rpc *rpc) { - sfw_test_unit_t *tsu = rpc->crpc_priv; + struct sfw_test_unit *tsu = rpc->crpc_priv; struct sfw_test_instance *tsi = tsu->tsu_instance; int done = 0; @@ -900,7 +900,7 @@ sfw_test_rpc_done(struct srpc_client_rpc *rpc) } int -sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, +sfw_create_test_rpc(struct sfw_test_unit *tsu, lnet_process_id_t peer, unsigned features, int nblk, int blklen, struct srpc_client_rpc **rpcpp) { @@ -944,7 +944,7 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, static int sfw_run_test(struct swi_workitem *wi) { - sfw_test_unit_t *tsu = wi->swi_workitem.wi_data; + struct sfw_test_unit *tsu = wi->swi_workitem.wi_data; struct sfw_test_instance *tsi = tsu->tsu_instance; struct srpc_client_rpc *rpc = NULL; @@ -994,7 +994,7 @@ static int sfw_run_batch(struct sfw_batch *tsb) { struct swi_workitem *wi; - sfw_test_unit_t *tsu; + struct sfw_test_unit *tsu; struct sfw_test_instance *tsi; if (sfw_batch_active(tsb)) { diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index 4e454283da22..c6f2caa86d73 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -86,7 +86,7 @@ ping_client_fini(struct sfw_test_instance *tsi) } static int -ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, +ping_client_prep_rpc(struct sfw_test_unit *tsu, lnet_process_id_t dest, struct srpc_client_rpc **rpc) { srpc_ping_reqst_t *req; @@ -118,7 +118,7 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu, lnet_process_id_t dest, } static void -ping_client_done_rpc(sfw_test_unit_t *tsu, struct srpc_client_rpc *rpc) +ping_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc) { struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index a95bdca02c30..ae1a69957cf7 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -398,14 +398,14 @@ struct sfw_test_instance { #define SFW_MAX_NDESTS (LNET_MAX_IOV * SFW_ID_PER_PAGE) #define sfw_id_pages(n) (((n) + SFW_ID_PER_PAGE - 1) / SFW_ID_PER_PAGE) -typedef struct sfw_test_unit { +struct sfw_test_unit { struct list_head tsu_list; /* chain on lst_test_instance */ lnet_process_id_t tsu_dest; /* id of dest node */ int tsu_loop; /* loop count of the test */ struct sfw_test_instance *tsu_instance; /* pointer to test instance */ void *tsu_private; /* private data */ struct swi_workitem tsu_worker; /* workitem of the test unit */ -} sfw_test_unit_t; +}; typedef struct sfw_test_case { struct list_head tsc_list; /* chain on fw_tests */ @@ -417,7 +417,7 @@ struct srpc_client_rpc * sfw_create_rpc(lnet_process_id_t peer, int service, unsigned features, int nbulkiov, int bulklen, void (*done)(struct srpc_client_rpc *), void *priv); -int sfw_create_test_rpc(sfw_test_unit_t *tsu, +int sfw_create_test_rpc(struct sfw_test_unit *tsu, lnet_process_id_t peer, unsigned features, int nblk, int blklen, struct srpc_client_rpc **rpc); void sfw_abort_rpc(struct srpc_client_rpc *rpc); -- GitLab From d6615d143013575012adb0133ec22b07fcce510f Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:39 -0400 Subject: [PATCH 2182/9938] staging: lustre: selftest: convert sfw_test_case_t to proper struct Turn typedef sfw_test_case_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/framework.c | 16 ++++++++-------- drivers/staging/lustre/lnet/selftest/selftest.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 31b564759d7f..84239c30761d 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -118,10 +118,10 @@ static struct smoketest_framework { int sfw_stop_batch(struct sfw_batch *tsb, int force); void sfw_destroy_session(struct sfw_session *sn); -static inline sfw_test_case_t * +static inline struct sfw_test_case * sfw_find_test_case(int id) { - sfw_test_case_t *tsc; + struct sfw_test_case *tsc; LASSERT(id <= SRPC_SERVICE_MAX_ID); LASSERT(id > SRPC_FRAMEWORK_SERVICE_MAX_ID); @@ -137,7 +137,7 @@ sfw_find_test_case(int id) static int sfw_register_test(struct srpc_service *service, struct sfw_test_client_ops *cliops) { - sfw_test_case_t *tsc; + struct sfw_test_case *tsc; if (sfw_find_test_case(service->sv_id)) { CERROR("Failed to register test %s (%d)\n", @@ -145,7 +145,7 @@ sfw_register_test(struct srpc_service *service, struct sfw_test_client_ops *clio return -EEXIST; } - LIBCFS_ALLOC(tsc, sizeof(sfw_test_case_t)); + LIBCFS_ALLOC(tsc, sizeof(struct sfw_test_case)); if (!tsc) return -ENOMEM; @@ -199,7 +199,7 @@ __must_hold(&sfw_data.fw_lock) struct sfw_session *sn = sfw_data.fw_session; int nactive = 0; struct sfw_batch *tsb; - sfw_test_case_t *tsc; + struct sfw_test_case *tsc; if (!sn) return; @@ -1629,7 +1629,7 @@ sfw_startup(void) int rc; int error; struct srpc_service *sv; - sfw_test_case_t *tsc; + struct sfw_test_case *tsc; if (session_timeout < 0) { CERROR("Session timeout must be non-negative: %d\n", @@ -1722,7 +1722,7 @@ void sfw_shutdown(void) { struct srpc_service *sv; - sfw_test_case_t *tsc; + struct sfw_test_case *tsc; int i; spin_lock(&sfw_data.fw_lock); @@ -1778,7 +1778,7 @@ sfw_shutdown(void) while (!list_empty(&sfw_data.fw_tests)) { tsc = list_entry(sfw_data.fw_tests.next, - sfw_test_case_t, tsc_list); + struct sfw_test_case, tsc_list); srpc_wait_service_shutdown(tsc->tsc_srv_service); diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index ae1a69957cf7..bc4c7ac98409 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -407,11 +407,11 @@ struct sfw_test_unit { struct swi_workitem tsu_worker; /* workitem of the test unit */ }; -typedef struct sfw_test_case { +struct sfw_test_case { struct list_head tsc_list; /* chain on fw_tests */ struct srpc_service *tsc_srv_service; /* test service */ struct sfw_test_client_ops *tsc_cli_ops; /* ops of test client */ -} sfw_test_case_t; +}; struct srpc_client_rpc * sfw_create_rpc(lnet_process_id_t peer, int service, -- GitLab From dc4f95fa5998e43df930d8b54807f78fe8cc344b Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:40 -0400 Subject: [PATCH 2183/9938] staging: lustre: selftest: convert lstcon_rpc_t to proper struct Turn typedef lstcon_rpc_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 50 +++++++++---------- drivers/staging/lustre/lnet/selftest/conrpc.h | 18 +++---- .../staging/lustre/lnet/selftest/console.c | 2 +- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 2affbeecac40..3210f04984de 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -52,7 +52,7 @@ void lstcon_rpc_stat_reply(lstcon_rpc_trans_t *, srpc_msg_t *, static void lstcon_rpc_done(struct srpc_client_rpc *rpc) { - lstcon_rpc_t *crpc = (lstcon_rpc_t *)rpc->crpc_priv; + struct lstcon_rpc *crpc = (struct lstcon_rpc *)rpc->crpc_priv; LASSERT(crpc && rpc == crpc->crp_rpc); LASSERT(crpc->crp_posted && !crpc->crp_finished); @@ -91,7 +91,7 @@ lstcon_rpc_done(struct srpc_client_rpc *rpc) static int lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats, - int bulk_npg, int bulk_len, int embedded, lstcon_rpc_t *crpc) + int bulk_npg, int bulk_len, int embedded, struct lstcon_rpc *crpc) { crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service, feats, bulk_npg, bulk_len, @@ -116,15 +116,15 @@ lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats, static int lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, - int bulk_npg, int bulk_len, lstcon_rpc_t **crpcpp) + int bulk_npg, int bulk_len, struct lstcon_rpc **crpcpp) { - lstcon_rpc_t *crpc = NULL; + struct lstcon_rpc *crpc = NULL; int rc; spin_lock(&console_session.ses_rpc_lock); crpc = list_first_entry_or_null(&console_session.ses_rpc_freelist, - lstcon_rpc_t, crp_link); + struct lstcon_rpc, crp_link); if (crpc) list_del_init(&crpc->crp_link); @@ -148,7 +148,7 @@ lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, } void -lstcon_rpc_put(lstcon_rpc_t *crpc) +lstcon_rpc_put(struct lstcon_rpc *crpc) { struct srpc_bulk *bulk = &crpc->crp_rpc->crpc_bulk; int i; @@ -183,7 +183,7 @@ lstcon_rpc_put(lstcon_rpc_t *crpc) } static void -lstcon_rpc_post(lstcon_rpc_t *crpc) +lstcon_rpc_post(struct lstcon_rpc *crpc) { lstcon_rpc_trans_t *trans = crpc->crp_trans; @@ -278,7 +278,7 @@ lstcon_rpc_trans_prep(struct list_head *translist, int transop, } void -lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, lstcon_rpc_t *crpc) +lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, struct lstcon_rpc *crpc) { list_add_tail(&crpc->crp_link, &trans->tas_rpcs_list); crpc->crp_trans = trans; @@ -288,7 +288,7 @@ void lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) { struct srpc_client_rpc *rpc; - lstcon_rpc_t *crpc; + struct lstcon_rpc *crpc; lstcon_node_t *nd; list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { @@ -338,7 +338,7 @@ lstcon_rpc_trans_check(lstcon_rpc_trans_t *trans) int lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout) { - lstcon_rpc_t *crpc; + struct lstcon_rpc *crpc; int rc; if (list_empty(&trans->tas_rpcs_list)) @@ -386,7 +386,7 @@ lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout) } static int -lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) +lstcon_rpc_get_reply(struct lstcon_rpc *crpc, srpc_msg_t **msgpp) { lstcon_node_t *nd = crpc->crp_node; struct srpc_client_rpc *rpc = crpc->crp_rpc; @@ -425,7 +425,7 @@ lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) void lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) { - lstcon_rpc_t *crpc; + struct lstcon_rpc *crpc; srpc_msg_t *rep; int error; @@ -474,7 +474,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, struct list_head __user *next; lstcon_rpc_ent_t *ent; srpc_generic_reply_t *rep; - lstcon_rpc_t *crpc; + struct lstcon_rpc *crpc; srpc_msg_t *msg; lstcon_node_t *nd; long dur; @@ -542,8 +542,8 @@ void lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) { struct srpc_client_rpc *rpc; - lstcon_rpc_t *crpc; - lstcon_rpc_t *tmp; + struct lstcon_rpc *crpc; + struct lstcon_rpc *tmp; int count = 0; list_for_each_entry_safe(crpc, tmp, &trans->tas_rpcs_list, crp_link) { @@ -593,7 +593,7 @@ lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) int lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, - unsigned feats, lstcon_rpc_t **crpc) + unsigned feats, struct lstcon_rpc **crpc) { srpc_mksn_reqst_t *msrq; srpc_rmsn_reqst_t *rsrq; @@ -631,7 +631,7 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, } int -lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) +lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, struct lstcon_rpc **crpc) { srpc_debug_reqst_t *drq; int rc; @@ -650,7 +650,7 @@ lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) int lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, - lstcon_tsb_hdr_t *tsb, lstcon_rpc_t **crpc) + lstcon_tsb_hdr_t *tsb, struct lstcon_rpc **crpc) { lstcon_batch_t *batch; srpc_batch_reqst_t *brq; @@ -682,7 +682,7 @@ lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, } int -lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) +lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, struct lstcon_rpc **crpc) { srpc_stat_reqst_t *srq; int rc; @@ -807,7 +807,7 @@ lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) int lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, - lstcon_test_t *test, lstcon_rpc_t **crpc) + lstcon_test_t *test, struct lstcon_rpc **crpc) { lstcon_group_t *sgrp = test->tes_src_grp; lstcon_group_t *dgrp = test->tes_dst_grp; @@ -1088,7 +1088,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; lstcon_node_t *nd; - lstcon_rpc_t *rpc; + struct lstcon_rpc *rpc; unsigned feats; int rc; @@ -1169,7 +1169,7 @@ lstcon_rpc_pinger(void *arg) { struct stt_timer *ptimer = (struct stt_timer *)arg; lstcon_rpc_trans_t *trans; - lstcon_rpc_t *crpc; + struct lstcon_rpc *crpc; srpc_msg_t *rep; srpc_debug_reqst_t *drq; lstcon_ndlink_t *ndl; @@ -1326,8 +1326,8 @@ void lstcon_rpc_cleanup_wait(void) { lstcon_rpc_trans_t *trans; - lstcon_rpc_t *crpc; - lstcon_rpc_t *temp; + struct lstcon_rpc *crpc; + struct lstcon_rpc *temp; struct list_head *pacer; struct list_head zlist; @@ -1369,7 +1369,7 @@ lstcon_rpc_cleanup_wait(void) list_for_each_entry_safe(crpc, temp, &zlist, crp_link) { list_del(&crpc->crp_link); - LIBCFS_FREE(crpc, sizeof(lstcon_rpc_t)); + LIBCFS_FREE(crpc, sizeof(struct lstcon_rpc)); } } diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index 6ddf088e6b91..abd7bb06a709 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -63,7 +63,7 @@ struct lstcon_tsb_hdr; struct lstcon_test; struct lstcon_node; -typedef struct lstcon_rpc { +struct lstcon_rpc { struct list_head crp_link; /* chain on rpc transaction */ struct srpc_client_rpc *crp_rpc; /* client rpc */ struct lstcon_node *crp_node; /* destination node */ @@ -76,7 +76,7 @@ typedef struct lstcon_rpc { unsigned int crp_embedded:1; int crp_status; /* console rpc errors */ unsigned long crp_stamp; /* replied time stamp */ -} lstcon_rpc_t; +}; typedef struct lstcon_rpc_trans { struct list_head tas_olink; /* link chain on owner list */ @@ -110,16 +110,16 @@ typedef int (*lstcon_rpc_readent_func_t)(int, srpc_msg_t *, lstcon_rpc_ent_t __user *); int lstcon_sesrpc_prep(struct lstcon_node *nd, int transop, - unsigned version, lstcon_rpc_t **crpc); + unsigned version, struct lstcon_rpc **crpc); int lstcon_dbgrpc_prep(struct lstcon_node *nd, - unsigned version, lstcon_rpc_t **crpc); + unsigned version, struct lstcon_rpc **crpc); int lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned version, - struct lstcon_tsb_hdr *tsb, lstcon_rpc_t **crpc); + struct lstcon_tsb_hdr *tsb, struct lstcon_rpc **crpc); int lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned version, - struct lstcon_test *test, lstcon_rpc_t **crpc); + struct lstcon_test *test, struct lstcon_rpc **crpc); int lstcon_statrpc_prep(struct lstcon_node *nd, unsigned version, - lstcon_rpc_t **crpc); -void lstcon_rpc_put(lstcon_rpc_t *crpc); + struct lstcon_rpc **crpc); +void lstcon_rpc_put(struct lstcon_rpc *crpc); int lstcon_rpc_trans_prep(struct list_head *translist, int transop, lstcon_rpc_trans_t **transpp); int lstcon_rpc_trans_ndlist(struct list_head *ndlist, @@ -133,7 +133,7 @@ int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, lstcon_rpc_readent_func_t readent); void lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error); void lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans); -void lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, lstcon_rpc_t *req); +void lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, struct lstcon_rpc *req); int lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout); int lstcon_rpc_pinger_start(void); void lstcon_rpc_pinger_stop(void); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 1352310d2727..23696e7c1a34 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -103,7 +103,7 @@ lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create) ndl->ndl_node->nd_stamp = cfs_time_current(); ndl->ndl_node->nd_state = LST_NODE_UNKNOWN; ndl->ndl_node->nd_timeout = 0; - memset(&ndl->ndl_node->nd_ping, 0, sizeof(lstcon_rpc_t)); + memset(&ndl->ndl_node->nd_ping, 0, sizeof(struct lstcon_rpc)); /* * queued in global hash & list, no refcount is taken by -- GitLab From d8742c855b69b28bdb7119375549c561728e74b3 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:41 -0400 Subject: [PATCH 2184/9938] staging: lustre: selftest: convert lstcon_rpc_trans_t to proper struct Turn typedef lstcon_rpc_trans_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 36 +++++++++---------- drivers/staging/lustre/lnet/selftest/conrpc.h | 20 +++++------ .../staging/lustre/lnet/selftest/console.c | 20 +++++------ .../staging/lustre/lnet/selftest/console.h | 2 +- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 3210f04984de..a58ad8d8ada9 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -46,7 +46,7 @@ #include "conrpc.h" #include "console.h" -void lstcon_rpc_stat_reply(lstcon_rpc_trans_t *, srpc_msg_t *, +void lstcon_rpc_stat_reply(struct lstcon_rpc_trans *, srpc_msg_t *, lstcon_node_t *, lstcon_trans_stat_t *); static void @@ -185,7 +185,7 @@ lstcon_rpc_put(struct lstcon_rpc *crpc) static void lstcon_rpc_post(struct lstcon_rpc *crpc) { - lstcon_rpc_trans_t *trans = crpc->crp_trans; + struct lstcon_rpc_trans *trans = crpc->crp_trans; LASSERT(trans); @@ -236,9 +236,9 @@ lstcon_rpc_trans_name(int transop) int lstcon_rpc_trans_prep(struct list_head *translist, int transop, - lstcon_rpc_trans_t **transpp) + struct lstcon_rpc_trans **transpp) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; if (translist) { list_for_each_entry(trans, translist, tas_link) { @@ -278,14 +278,14 @@ lstcon_rpc_trans_prep(struct list_head *translist, int transop, } void -lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, struct lstcon_rpc *crpc) +lstcon_rpc_trans_addreq(struct lstcon_rpc_trans *trans, struct lstcon_rpc *crpc) { list_add_tail(&crpc->crp_link, &trans->tas_rpcs_list); crpc->crp_trans = trans; } void -lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) +lstcon_rpc_trans_abort(struct lstcon_rpc_trans *trans, int error) { struct srpc_client_rpc *rpc; struct lstcon_rpc *crpc; @@ -326,7 +326,7 @@ lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) } static int -lstcon_rpc_trans_check(lstcon_rpc_trans_t *trans) +lstcon_rpc_trans_check(struct lstcon_rpc_trans *trans) { if (console_session.ses_shutdown && !list_empty(&trans->tas_olink)) /* Not an end session RPC */ @@ -336,7 +336,7 @@ lstcon_rpc_trans_check(lstcon_rpc_trans_t *trans) } int -lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout) +lstcon_rpc_trans_postwait(struct lstcon_rpc_trans *trans, int timeout) { struct lstcon_rpc *crpc; int rc; @@ -423,7 +423,7 @@ lstcon_rpc_get_reply(struct lstcon_rpc *crpc, srpc_msg_t **msgpp) } void -lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) +lstcon_rpc_trans_stat(struct lstcon_rpc_trans *trans, lstcon_trans_stat_t *stat) { struct lstcon_rpc *crpc; srpc_msg_t *rep; @@ -466,7 +466,7 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) } int -lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, +lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans, struct list_head __user *head_up, lstcon_rpc_readent_func_t readent) { @@ -539,7 +539,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, } void -lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) +lstcon_rpc_trans_destroy(struct lstcon_rpc_trans *trans) { struct srpc_client_rpc *rpc; struct lstcon_rpc *crpc; @@ -915,7 +915,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, } static int -lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, +lstcon_sesnew_stat_reply(struct lstcon_rpc_trans *trans, lstcon_node_t *nd, srpc_msg_t *reply) { srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply; @@ -962,7 +962,7 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, } void -lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, +lstcon_rpc_stat_reply(struct lstcon_rpc_trans *trans, srpc_msg_t *msg, lstcon_node_t *nd, lstcon_trans_stat_t *stat) { srpc_rmsn_reply_t *rmsn_rep; @@ -1083,9 +1083,9 @@ int lstcon_rpc_trans_ndlist(struct list_head *ndlist, struct list_head *translist, int transop, void *arg, lstcon_rpc_cond_func_t condition, - lstcon_rpc_trans_t **transpp) + struct lstcon_rpc_trans **transpp) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; lstcon_ndlink_t *ndl; lstcon_node_t *nd; struct lstcon_rpc *rpc; @@ -1168,7 +1168,7 @@ static void lstcon_rpc_pinger(void *arg) { struct stt_timer *ptimer = (struct stt_timer *)arg; - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; struct lstcon_rpc *crpc; srpc_msg_t *rep; srpc_debug_reqst_t *drq; @@ -1325,7 +1325,7 @@ lstcon_rpc_pinger_stop(void) void lstcon_rpc_cleanup_wait(void) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; struct lstcon_rpc *crpc; struct lstcon_rpc *temp; struct list_head *pacer; @@ -1337,7 +1337,7 @@ lstcon_rpc_cleanup_wait(void) while (!list_empty(&console_session.ses_trans_list)) { list_for_each(pacer, &console_session.ses_trans_list) { - trans = list_entry(pacer, lstcon_rpc_trans_t, + trans = list_entry(pacer, struct lstcon_rpc_trans, tas_link); CDEBUG(D_NET, "Session closed, wakeup transaction %s\n", diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index abd7bb06a709..7281abdc4b2a 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -78,7 +78,7 @@ struct lstcon_rpc { unsigned long crp_stamp; /* replied time stamp */ }; -typedef struct lstcon_rpc_trans { +struct lstcon_rpc_trans { struct list_head tas_olink; /* link chain on owner list */ struct list_head tas_link; /* link chain on global list */ int tas_opc; /* operation code of transaction */ @@ -87,7 +87,7 @@ typedef struct lstcon_rpc_trans { wait_queue_head_t tas_waitq; /* wait queue head */ atomic_t tas_remaining; /* # of un-scheduled rpcs */ struct list_head tas_rpcs_list; /* queued requests */ -} lstcon_rpc_trans_t; +}; #define LST_TRANS_PRIVATE 0x1000 @@ -121,20 +121,20 @@ int lstcon_statrpc_prep(struct lstcon_node *nd, unsigned version, struct lstcon_rpc **crpc); void lstcon_rpc_put(struct lstcon_rpc *crpc); int lstcon_rpc_trans_prep(struct list_head *translist, - int transop, lstcon_rpc_trans_t **transpp); + int transop, struct lstcon_rpc_trans **transpp); int lstcon_rpc_trans_ndlist(struct list_head *ndlist, struct list_head *translist, int transop, void *arg, lstcon_rpc_cond_func_t condition, - lstcon_rpc_trans_t **transpp); -void lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, + struct lstcon_rpc_trans **transpp); +void lstcon_rpc_trans_stat(struct lstcon_rpc_trans *trans, lstcon_trans_stat_t *stat); -int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, +int lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans, struct list_head __user *head_up, lstcon_rpc_readent_func_t readent); -void lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error); -void lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans); -void lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, struct lstcon_rpc *req); -int lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout); +void lstcon_rpc_trans_abort(struct lstcon_rpc_trans *trans, int error); +void lstcon_rpc_trans_destroy(struct lstcon_rpc_trans *trans); +void lstcon_rpc_trans_addreq(struct lstcon_rpc_trans *trans, struct lstcon_rpc *req); +int lstcon_rpc_trans_postwait(struct lstcon_rpc_trans *trans, int timeout); int lstcon_rpc_pinger_start(void); void lstcon_rpc_pinger_stop(void); void lstcon_rpc_cleanup_wait(void); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 23696e7c1a34..08de007a7e67 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -403,7 +403,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, int count, lnet_process_id_t __user *ids_up, unsigned *featp, struct list_head __user *result_up) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; lstcon_ndlink_t *ndl; lstcon_group_t *tmp; lnet_process_id_t id; @@ -470,7 +470,7 @@ lstcon_group_nodes_remove(lstcon_group_t *grp, int count, lnet_process_id_t __user *ids_up, struct list_head __user *result_up) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; lstcon_ndlink_t *ndl; lstcon_group_t *tmp; lnet_process_id_t id; @@ -578,7 +578,7 @@ lstcon_nodes_add(char *name, int count, lnet_process_id_t __user *ids_up, int lstcon_group_del(char *name) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; lstcon_group_t *grp; int rc; @@ -683,7 +683,7 @@ lstcon_nodes_remove(char *name, int count, lnet_process_id_t __user *ids_up, int lstcon_group_refresh(char *name, struct list_head __user *result_up) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; lstcon_group_t *grp; int rc; @@ -1023,7 +1023,7 @@ static int lstcon_batch_op(lstcon_batch_t *bat, int transop, struct list_head __user *result_up) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; int rc; rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list, @@ -1187,7 +1187,7 @@ lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg) static int lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; lstcon_group_t *grp; int transop; int rc; @@ -1403,7 +1403,7 @@ int lstcon_test_batch_query(char *name, int testidx, int client, int timeout, struct list_head __user *result_up) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; struct list_head *translist; struct list_head *ndlist; lstcon_tsb_hdr_t *hdr; @@ -1490,7 +1490,7 @@ lstcon_ndlist_stat(struct list_head *ndlist, int timeout, struct list_head __user *result_up) { struct list_head head; - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; int rc; INIT_LIST_HEAD(&head); @@ -1580,7 +1580,7 @@ lstcon_debug_ndlist(struct list_head *ndlist, struct list_head *translist, int timeout, struct list_head __user *result_up) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; int rc; rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY, @@ -1812,7 +1812,7 @@ lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up, int lstcon_session_end(void) { - lstcon_rpc_trans_t *trans; + struct lstcon_rpc_trans *trans; lstcon_group_t *grp; lstcon_batch_t *bat; int rc = 0; diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 554f582441f1..c573b5681ebb 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -152,7 +152,7 @@ struct lstcon_session { unsigned ses_expired:1; /* console is timedout */ __u64 ses_id_cookie; /* batch id cookie */ char ses_name[LST_NAME_SIZE];/* session name */ - lstcon_rpc_trans_t *ses_ping; /* session pinger */ + struct lstcon_rpc_trans *ses_ping; /* session pinger */ struct stt_timer ses_ping_timer; /* timer for pinger */ lstcon_trans_stat_t ses_trans_stat; /* transaction stats */ -- GitLab From f1e34162fe284dd414c2a70f5814867b0f3c2b67 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:42 -0400 Subject: [PATCH 2185/9938] staging: lustre: selftest: convert lstcon_node_t to proper struct Turn typedef lstcon_node_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 32 +++++++++---------- .../staging/lustre/lnet/selftest/console.c | 20 ++++++------ .../staging/lustre/lnet/selftest/console.h | 9 +++--- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index a58ad8d8ada9..cea87dc37d19 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -47,7 +47,7 @@ #include "console.h" void lstcon_rpc_stat_reply(struct lstcon_rpc_trans *, srpc_msg_t *, - lstcon_node_t *, lstcon_trans_stat_t *); + struct lstcon_node *, lstcon_trans_stat_t *); static void lstcon_rpc_done(struct srpc_client_rpc *rpc) @@ -90,7 +90,7 @@ lstcon_rpc_done(struct srpc_client_rpc *rpc) } static int -lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats, +lstcon_rpc_init(struct lstcon_node *nd, int service, unsigned feats, int bulk_npg, int bulk_len, int embedded, struct lstcon_rpc *crpc) { crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service, @@ -115,7 +115,7 @@ lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats, } static int -lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, +lstcon_rpc_prep(struct lstcon_node *nd, int service, unsigned feats, int bulk_npg, int bulk_len, struct lstcon_rpc **crpcpp) { struct lstcon_rpc *crpc = NULL; @@ -289,7 +289,7 @@ lstcon_rpc_trans_abort(struct lstcon_rpc_trans *trans, int error) { struct srpc_client_rpc *rpc; struct lstcon_rpc *crpc; - lstcon_node_t *nd; + struct lstcon_node *nd; list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { rpc = crpc->crp_rpc; @@ -388,7 +388,7 @@ lstcon_rpc_trans_postwait(struct lstcon_rpc_trans *trans, int timeout) static int lstcon_rpc_get_reply(struct lstcon_rpc *crpc, srpc_msg_t **msgpp) { - lstcon_node_t *nd = crpc->crp_node; + struct lstcon_node *nd = crpc->crp_node; struct srpc_client_rpc *rpc = crpc->crp_rpc; srpc_generic_reply_t *rep; @@ -476,7 +476,7 @@ lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans, srpc_generic_reply_t *rep; struct lstcon_rpc *crpc; srpc_msg_t *msg; - lstcon_node_t *nd; + struct lstcon_node *nd; long dur; struct timeval tv; int error; @@ -592,7 +592,7 @@ lstcon_rpc_trans_destroy(struct lstcon_rpc_trans *trans) } int -lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, +lstcon_sesrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, struct lstcon_rpc **crpc) { srpc_mksn_reqst_t *msrq; @@ -631,7 +631,7 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, } int -lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, struct lstcon_rpc **crpc) +lstcon_dbgrpc_prep(struct lstcon_node *nd, unsigned feats, struct lstcon_rpc **crpc) { srpc_debug_reqst_t *drq; int rc; @@ -649,7 +649,7 @@ lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, struct lstcon_rpc **crpc) } int -lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, +lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, lstcon_tsb_hdr_t *tsb, struct lstcon_rpc **crpc) { lstcon_batch_t *batch; @@ -682,7 +682,7 @@ lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, } int -lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, struct lstcon_rpc **crpc) +lstcon_statrpc_prep(struct lstcon_node *nd, unsigned feats, struct lstcon_rpc **crpc) { srpc_stat_reqst_t *srq; int rc; @@ -720,7 +720,7 @@ lstcon_dstnodes_prep(lstcon_group_t *grp, int idx, { lnet_process_id_packed_t *pid; lstcon_ndlink_t *ndl; - lstcon_node_t *nd; + struct lstcon_node *nd; int start; int end; int i = 0; @@ -806,7 +806,7 @@ lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) } int -lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, +lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, lstcon_test_t *test, struct lstcon_rpc **crpc) { lstcon_group_t *sgrp = test->tes_src_grp; @@ -916,7 +916,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, static int lstcon_sesnew_stat_reply(struct lstcon_rpc_trans *trans, - lstcon_node_t *nd, srpc_msg_t *reply) + struct lstcon_node *nd, srpc_msg_t *reply) { srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply; int status = mksn_rep->mksn_status; @@ -963,7 +963,7 @@ lstcon_sesnew_stat_reply(struct lstcon_rpc_trans *trans, void lstcon_rpc_stat_reply(struct lstcon_rpc_trans *trans, srpc_msg_t *msg, - lstcon_node_t *nd, lstcon_trans_stat_t *stat) + struct lstcon_node *nd, lstcon_trans_stat_t *stat) { srpc_rmsn_reply_t *rmsn_rep; srpc_debug_reply_t *dbg_rep; @@ -1087,7 +1087,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, { struct lstcon_rpc_trans *trans; lstcon_ndlink_t *ndl; - lstcon_node_t *nd; + struct lstcon_node *nd; struct lstcon_rpc *rpc; unsigned feats; int rc; @@ -1173,7 +1173,7 @@ lstcon_rpc_pinger(void *arg) srpc_msg_t *rep; srpc_debug_reqst_t *drq; lstcon_ndlink_t *ndl; - lstcon_node_t *nd; + struct lstcon_node *nd; int intv; int count = 0; int rc; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 08de007a7e67..32364b499ef0 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -61,7 +61,7 @@ do { \ struct lstcon_session console_session; static void -lstcon_node_get(lstcon_node_t *nd) +lstcon_node_get(struct lstcon_node *nd) { LASSERT(nd->nd_ref >= 1); @@ -69,7 +69,7 @@ lstcon_node_get(lstcon_node_t *nd) } static int -lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create) +lstcon_node_find(lnet_process_id_t id, struct lstcon_node **ndpp, int create) { lstcon_ndlink_t *ndl; unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE; @@ -90,7 +90,7 @@ lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create) if (!create) return -ENOENT; - LIBCFS_ALLOC(*ndpp, sizeof(lstcon_node_t) + sizeof(lstcon_ndlink_t)); + LIBCFS_ALLOC(*ndpp, sizeof(struct lstcon_node) + sizeof(lstcon_ndlink_t)); if (!*ndpp) return -ENOMEM; @@ -117,7 +117,7 @@ lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create) } static void -lstcon_node_put(lstcon_node_t *nd) +lstcon_node_put(struct lstcon_node *nd) { lstcon_ndlink_t *ndl; @@ -135,7 +135,7 @@ lstcon_node_put(lstcon_node_t *nd) list_del(&ndl->ndl_link); list_del(&ndl->ndl_hlink); - LIBCFS_FREE(nd, sizeof(lstcon_node_t) + sizeof(lstcon_ndlink_t)); + LIBCFS_FREE(nd, sizeof(struct lstcon_node) + sizeof(lstcon_ndlink_t)); } static int @@ -144,7 +144,7 @@ lstcon_ndlink_find(struct list_head *hash, { unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE; lstcon_ndlink_t *ndl; - lstcon_node_t *nd; + struct lstcon_node *nd; int rc; if (id.nid == LNET_NID_ANY) @@ -341,7 +341,7 @@ lstcon_group_move(lstcon_group_t *old, lstcon_group_t *new) } static int -lstcon_sesrpc_condition(int transop, lstcon_node_t *nd, void *arg) +lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg) { lstcon_group_t *grp = (lstcon_group_t *)arg; @@ -745,7 +745,7 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, int *count_p, lstcon_node_ent_t __user *dents_up) { lstcon_ndlink_t *ndl; - lstcon_node_t *nd; + struct lstcon_node *nd; int count = 0; int index = 0; @@ -998,7 +998,7 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, } static int -lstcon_batrpc_condition(int transop, lstcon_node_t *nd, void *arg) +lstcon_batrpc_condition(int transop, struct lstcon_node *nd, void *arg) { switch (transop) { case LST_TRANS_TSBRUN: @@ -1141,7 +1141,7 @@ lstcon_batch_destroy(lstcon_batch_t *bat) } static int -lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg) +lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg) { lstcon_test_t *test; lstcon_batch_t *batch; diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index c573b5681ebb..7c3796721e42 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -50,19 +50,20 @@ #include "selftest.h" #include "conrpc.h" -typedef struct lstcon_node { +/* node descriptor */ +struct lstcon_node { lnet_process_id_t nd_id; /* id of the node */ int nd_ref; /* reference count */ int nd_state; /* state of the node */ int nd_timeout; /* session timeout */ unsigned long nd_stamp; /* timestamp of last replied RPC */ struct lstcon_rpc nd_ping; /* ping rpc */ -} lstcon_node_t; /* node descriptor */ +}; typedef struct { struct list_head ndl_link; /* chain on list */ struct list_head ndl_hlink; /* chain on hash */ - lstcon_node_t *ndl_node; /* pointer to node */ + struct lstcon_node *ndl_node; /* pointer to node */ } lstcon_ndlink_t; /* node link descriptor */ typedef struct { @@ -99,7 +100,7 @@ typedef struct { */ struct list_head bat_trans_list; /* list head of transaction */ struct list_head bat_cli_list; /* list head of client nodes - * (lstcon_node_t) */ + * (struct lstcon_node) */ struct list_head *bat_cli_hash; /* hash table of client nodes */ struct list_head bat_srv_list; /* list head of server nodes */ struct list_head *bat_srv_hash; /* hash table of server nodes */ -- GitLab From e00f978ef5821c0c607a3002babd3a872149d2d4 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:43 -0400 Subject: [PATCH 2186/9938] staging: lustre: selftest: convert lstcon_ndlink_t to proper struct Turn typedef lstcon_ndlink_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 6 +- .../staging/lustre/lnet/selftest/console.c | 64 +++++++++---------- .../staging/lustre/lnet/selftest/console.h | 7 +- 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index cea87dc37d19..6967d5fe91dc 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -719,7 +719,7 @@ lstcon_dstnodes_prep(lstcon_group_t *grp, int idx, int dist, int span, int nkiov, lnet_kiov_t *kiov) { lnet_process_id_packed_t *pid; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; struct lstcon_node *nd; int start; int end; @@ -1086,7 +1086,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, struct lstcon_rpc_trans **transpp) { struct lstcon_rpc_trans *trans; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; struct lstcon_node *nd; struct lstcon_rpc *rpc; unsigned feats; @@ -1172,7 +1172,7 @@ lstcon_rpc_pinger(void *arg) struct lstcon_rpc *crpc; srpc_msg_t *rep; srpc_debug_reqst_t *drq; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; struct lstcon_node *nd; int intv; int count = 0; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 32364b499ef0..e068c134f67a 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -71,7 +71,7 @@ lstcon_node_get(struct lstcon_node *nd) static int lstcon_node_find(lnet_process_id_t id, struct lstcon_node **ndpp, int create) { - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE; LASSERT(id.nid != LNET_NID_ANY); @@ -90,11 +90,11 @@ lstcon_node_find(lnet_process_id_t id, struct lstcon_node **ndpp, int create) if (!create) return -ENOENT; - LIBCFS_ALLOC(*ndpp, sizeof(struct lstcon_node) + sizeof(lstcon_ndlink_t)); + LIBCFS_ALLOC(*ndpp, sizeof(struct lstcon_node) + sizeof(struct lstcon_ndlink)); if (!*ndpp) return -ENOMEM; - ndl = (lstcon_ndlink_t *)(*ndpp + 1); + ndl = (struct lstcon_ndlink *)(*ndpp + 1); ndl->ndl_node = *ndpp; @@ -119,14 +119,14 @@ lstcon_node_find(lnet_process_id_t id, struct lstcon_node **ndpp, int create) static void lstcon_node_put(struct lstcon_node *nd) { - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; LASSERT(nd->nd_ref > 0); if (--nd->nd_ref > 0) return; - ndl = (lstcon_ndlink_t *)(nd + 1); + ndl = (struct lstcon_ndlink *)(nd + 1); LASSERT(!list_empty(&ndl->ndl_link)); LASSERT(!list_empty(&ndl->ndl_hlink)); @@ -135,15 +135,15 @@ lstcon_node_put(struct lstcon_node *nd) list_del(&ndl->ndl_link); list_del(&ndl->ndl_hlink); - LIBCFS_FREE(nd, sizeof(struct lstcon_node) + sizeof(lstcon_ndlink_t)); + LIBCFS_FREE(nd, sizeof(struct lstcon_node) + sizeof(struct lstcon_ndlink)); } static int lstcon_ndlink_find(struct list_head *hash, - lnet_process_id_t id, lstcon_ndlink_t **ndlpp, int create) + lnet_process_id_t id, struct lstcon_ndlink **ndlpp, int create) { unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; struct lstcon_node *nd; int rc; @@ -168,7 +168,7 @@ lstcon_ndlink_find(struct list_head *hash, if (rc) return rc; - LIBCFS_ALLOC(ndl, sizeof(lstcon_ndlink_t)); + LIBCFS_ALLOC(ndl, sizeof(struct lstcon_ndlink)); if (!ndl) { lstcon_node_put(nd); return -ENOMEM; @@ -184,7 +184,7 @@ lstcon_ndlink_find(struct list_head *hash, } static void -lstcon_ndlink_release(lstcon_ndlink_t *ndl) +lstcon_ndlink_release(struct lstcon_ndlink *ndl) { LASSERT(list_empty(&ndl->ndl_link)); LASSERT(!list_empty(&ndl->ndl_hlink)); @@ -234,13 +234,13 @@ lstcon_group_addref(lstcon_group_t *grp) grp->grp_ref++; } -static void lstcon_group_ndlink_release(lstcon_group_t *, lstcon_ndlink_t *); +static void lstcon_group_ndlink_release(lstcon_group_t *, struct lstcon_ndlink *); static void lstcon_group_drain(lstcon_group_t *grp, int keep) { - lstcon_ndlink_t *ndl; - lstcon_ndlink_t *tmp; + struct lstcon_ndlink *ndl; + struct lstcon_ndlink *tmp; list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) { if (!(ndl->ndl_node->nd_state & keep)) @@ -287,7 +287,7 @@ lstcon_group_find(const char *name, lstcon_group_t **grpp) static int lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, - lstcon_ndlink_t **ndlpp, int create) + struct lstcon_ndlink **ndlpp, int create) { int rc; @@ -305,7 +305,7 @@ lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, } static void -lstcon_group_ndlink_release(lstcon_group_t *grp, lstcon_ndlink_t *ndl) +lstcon_group_ndlink_release(lstcon_group_t *grp, struct lstcon_ndlink *ndl) { list_del_init(&ndl->ndl_link); lstcon_ndlink_release(ndl); @@ -314,7 +314,7 @@ lstcon_group_ndlink_release(lstcon_group_t *grp, lstcon_ndlink_t *ndl) static void lstcon_group_ndlink_move(lstcon_group_t *old, - lstcon_group_t *new, lstcon_ndlink_t *ndl) + lstcon_group_t *new, struct lstcon_ndlink *ndl) { unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) % LST_NODE_HASHSIZE; @@ -331,11 +331,11 @@ lstcon_group_ndlink_move(lstcon_group_t *old, static void lstcon_group_move(lstcon_group_t *old, lstcon_group_t *new) { - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; while (!list_empty(&old->grp_ndl_list)) { ndl = list_entry(old->grp_ndl_list.next, - lstcon_ndlink_t, ndl_link); + struct lstcon_ndlink, ndl_link); lstcon_group_ndlink_move(old, new, ndl); } } @@ -404,7 +404,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, unsigned *featp, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; lstcon_group_t *tmp; lnet_process_id_t id; int i; @@ -471,7 +471,7 @@ lstcon_group_nodes_remove(lstcon_group_t *grp, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; lstcon_group_t *tmp; lnet_process_id_t id; int rc; @@ -744,7 +744,7 @@ static int lstcon_nodes_getent(struct list_head *head, int *index_p, int *count_p, lstcon_node_ent_t __user *dents_up) { - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; struct lstcon_node *nd; int count = 0; int index = 0; @@ -787,7 +787,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, { lstcon_ndlist_ent_t *gentp; lstcon_group_t *grp; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; int rc; rc = lstcon_group_find(name, &grp); @@ -936,7 +936,7 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, struct list_head *srvlst; lstcon_test_t *test = NULL; lstcon_batch_t *bat; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; int rc; rc = lstcon_batch_find(name, &bat); @@ -1090,7 +1090,7 @@ lstcon_batch_stop(char *name, int force, struct list_head __user *result_up) static void lstcon_batch_destroy(lstcon_batch_t *bat) { - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; lstcon_test_t *test; int i; @@ -1114,7 +1114,7 @@ lstcon_batch_destroy(lstcon_batch_t *bat) while (!list_empty(&bat->bat_cli_list)) { ndl = list_entry(bat->bat_cli_list.next, - lstcon_ndlink_t, ndl_link); + struct lstcon_ndlink, ndl_link); list_del_init(&ndl->ndl_link); lstcon_ndlink_release(ndl); @@ -1122,7 +1122,7 @@ lstcon_batch_destroy(lstcon_batch_t *bat) while (!list_empty(&bat->bat_srv_list)) { ndl = list_entry(bat->bat_srv_list.next, - lstcon_ndlink_t, ndl_link); + struct lstcon_ndlink, ndl_link); list_del_init(&ndl->ndl_link); lstcon_ndlink_release(ndl); @@ -1145,7 +1145,7 @@ lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg) { lstcon_test_t *test; lstcon_batch_t *batch; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; struct list_head *hash; struct list_head *head; @@ -1258,7 +1258,7 @@ static int lstcon_verify_group(const char *name, lstcon_group_t **grp) { int rc; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; rc = lstcon_group_find(name, grp); if (rc) { @@ -1535,7 +1535,7 @@ int lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, int timeout, struct list_head __user *result_up) { - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; lstcon_group_t *tmp; lnet_process_id_t id; int i; @@ -1648,7 +1648,7 @@ lstcon_nodes_debug(int timeout, struct list_head __user *result_up) { lnet_process_id_t id; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; lstcon_group_t *grp; int i; int rc; @@ -1781,7 +1781,7 @@ lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up, char __user *name_up, int len) { lstcon_ndlist_ent_t *entp; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; int rc = 0; if (console_session.ses_state != LST_SESSION_ACTIVE) @@ -1910,7 +1910,7 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) srpc_join_reqst_t *jreq = &req->msg_body.join_reqst; srpc_join_reply_t *jrep = &rep->msg_body.join_reply; lstcon_group_t *grp = NULL; - lstcon_ndlink_t *ndl; + struct lstcon_ndlink *ndl; int rc = 0; sfw_unpack_message(req); diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 7c3796721e42..dd9674dbc517 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -60,11 +60,12 @@ struct lstcon_node { struct lstcon_rpc nd_ping; /* ping rpc */ }; -typedef struct { +/* node link descriptor */ +struct lstcon_ndlink { struct list_head ndl_link; /* chain on list */ struct list_head ndl_hlink; /* chain on hash */ - struct lstcon_node *ndl_node; /* pointer to node */ -} lstcon_ndlink_t; /* node link descriptor */ + struct lstcon_node *ndl_node; /* pointer to node */ +}; typedef struct { struct list_head grp_link; /* chain on global group list -- GitLab From 6bd88c7ad462ed00d63e508832bad5621d091696 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:44 -0400 Subject: [PATCH 2187/9938] staging: lustre: selftest: convert lstcon_group_t to proper struct Turn typedef lstcon_group_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 6 +- .../staging/lustre/lnet/selftest/console.c | 80 +++++++++---------- .../staging/lustre/lnet/selftest/console.h | 9 ++- 3 files changed, 48 insertions(+), 47 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 6967d5fe91dc..4272a6167ad4 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -715,7 +715,7 @@ lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov) } static int -lstcon_dstnodes_prep(lstcon_group_t *grp, int idx, +lstcon_dstnodes_prep(struct lstcon_group *grp, int idx, int dist, int span, int nkiov, lnet_kiov_t *kiov) { lnet_process_id_packed_t *pid; @@ -809,8 +809,8 @@ int lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, lstcon_test_t *test, struct lstcon_rpc **crpc) { - lstcon_group_t *sgrp = test->tes_src_grp; - lstcon_group_t *dgrp = test->tes_dst_grp; + struct lstcon_group *sgrp = test->tes_src_grp; + struct lstcon_group *dgrp = test->tes_dst_grp; srpc_test_reqst_t *trq; struct srpc_bulk *bulk; int i; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index e068c134f67a..47338f56a62c 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -196,12 +196,12 @@ lstcon_ndlink_release(struct lstcon_ndlink *ndl) } static int -lstcon_group_alloc(char *name, lstcon_group_t **grpp) +lstcon_group_alloc(char *name, struct lstcon_group **grpp) { - lstcon_group_t *grp; + struct lstcon_group *grp; int i; - LIBCFS_ALLOC(grp, offsetof(lstcon_group_t, + LIBCFS_ALLOC(grp, offsetof(struct lstcon_group, grp_ndl_hash[LST_NODE_HASHSIZE])); if (!grp) return -ENOMEM; @@ -209,7 +209,7 @@ lstcon_group_alloc(char *name, lstcon_group_t **grpp) grp->grp_ref = 1; if (name) { if (strlen(name) > sizeof(grp->grp_name) - 1) { - LIBCFS_FREE(grp, offsetof(lstcon_group_t, + LIBCFS_FREE(grp, offsetof(struct lstcon_group, grp_ndl_hash[LST_NODE_HASHSIZE])); return -E2BIG; } @@ -229,15 +229,15 @@ lstcon_group_alloc(char *name, lstcon_group_t **grpp) } static void -lstcon_group_addref(lstcon_group_t *grp) +lstcon_group_addref(struct lstcon_group *grp) { grp->grp_ref++; } -static void lstcon_group_ndlink_release(lstcon_group_t *, struct lstcon_ndlink *); +static void lstcon_group_ndlink_release(struct lstcon_group *, struct lstcon_ndlink *); static void -lstcon_group_drain(lstcon_group_t *grp, int keep) +lstcon_group_drain(struct lstcon_group *grp, int keep) { struct lstcon_ndlink *ndl; struct lstcon_ndlink *tmp; @@ -249,7 +249,7 @@ lstcon_group_drain(lstcon_group_t *grp, int keep) } static void -lstcon_group_decref(lstcon_group_t *grp) +lstcon_group_decref(struct lstcon_group *grp) { int i; @@ -264,14 +264,14 @@ lstcon_group_decref(lstcon_group_t *grp) for (i = 0; i < LST_NODE_HASHSIZE; i++) LASSERT(list_empty(&grp->grp_ndl_hash[i])); - LIBCFS_FREE(grp, offsetof(lstcon_group_t, + LIBCFS_FREE(grp, offsetof(struct lstcon_group, grp_ndl_hash[LST_NODE_HASHSIZE])); } static int -lstcon_group_find(const char *name, lstcon_group_t **grpp) +lstcon_group_find(const char *name, struct lstcon_group **grpp) { - lstcon_group_t *grp; + struct lstcon_group *grp; list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) { if (strncmp(grp->grp_name, name, LST_NAME_SIZE)) @@ -286,7 +286,7 @@ lstcon_group_find(const char *name, lstcon_group_t **grpp) } static int -lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, +lstcon_group_ndlink_find(struct lstcon_group *grp, lnet_process_id_t id, struct lstcon_ndlink **ndlpp, int create) { int rc; @@ -305,7 +305,7 @@ lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, } static void -lstcon_group_ndlink_release(lstcon_group_t *grp, struct lstcon_ndlink *ndl) +lstcon_group_ndlink_release(struct lstcon_group *grp, struct lstcon_ndlink *ndl) { list_del_init(&ndl->ndl_link); lstcon_ndlink_release(ndl); @@ -313,8 +313,8 @@ lstcon_group_ndlink_release(lstcon_group_t *grp, struct lstcon_ndlink *ndl) } static void -lstcon_group_ndlink_move(lstcon_group_t *old, - lstcon_group_t *new, struct lstcon_ndlink *ndl) +lstcon_group_ndlink_move(struct lstcon_group *old, + struct lstcon_group *new, struct lstcon_ndlink *ndl) { unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) % LST_NODE_HASHSIZE; @@ -329,7 +329,7 @@ lstcon_group_ndlink_move(lstcon_group_t *old, } static void -lstcon_group_move(lstcon_group_t *old, lstcon_group_t *new) +lstcon_group_move(struct lstcon_group *old, struct lstcon_group *new) { struct lstcon_ndlink *ndl; @@ -343,7 +343,7 @@ lstcon_group_move(lstcon_group_t *old, lstcon_group_t *new) static int lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg) { - lstcon_group_t *grp = (lstcon_group_t *)arg; + struct lstcon_group *grp = (struct lstcon_group *)arg; switch (transop) { case LST_TRANS_SESNEW: @@ -399,13 +399,13 @@ lstcon_sesrpc_readent(int transop, srpc_msg_t *msg, } static int -lstcon_group_nodes_add(lstcon_group_t *grp, +lstcon_group_nodes_add(struct lstcon_group *grp, int count, lnet_process_id_t __user *ids_up, unsigned *featp, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; struct lstcon_ndlink *ndl; - lstcon_group_t *tmp; + struct lstcon_group *tmp; lnet_process_id_t id; int i; int rc; @@ -466,13 +466,13 @@ lstcon_group_nodes_add(lstcon_group_t *grp, } static int -lstcon_group_nodes_remove(lstcon_group_t *grp, +lstcon_group_nodes_remove(struct lstcon_group *grp, int count, lnet_process_id_t __user *ids_up, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; struct lstcon_ndlink *ndl; - lstcon_group_t *tmp; + struct lstcon_group *tmp; lnet_process_id_t id; int rc; int i; @@ -523,7 +523,7 @@ lstcon_group_nodes_remove(lstcon_group_t *grp, int lstcon_group_add(char *name) { - lstcon_group_t *grp; + struct lstcon_group *grp; int rc; rc = lstcon_group_find(name, &grp) ? 0 : -EEXIST; @@ -548,7 +548,7 @@ int lstcon_nodes_add(char *name, int count, lnet_process_id_t __user *ids_up, unsigned *featp, struct list_head __user *result_up) { - lstcon_group_t *grp; + struct lstcon_group *grp; int rc; LASSERT(count > 0); @@ -579,7 +579,7 @@ int lstcon_group_del(char *name) { struct lstcon_rpc_trans *trans; - lstcon_group_t *grp; + struct lstcon_group *grp; int rc; rc = lstcon_group_find(name, &grp); @@ -621,7 +621,7 @@ lstcon_group_del(char *name) int lstcon_group_clean(char *name, int args) { - lstcon_group_t *grp = NULL; + struct lstcon_group *grp = NULL; int rc; rc = lstcon_group_find(name, &grp); @@ -654,7 +654,7 @@ int lstcon_nodes_remove(char *name, int count, lnet_process_id_t __user *ids_up, struct list_head __user *result_up) { - lstcon_group_t *grp = NULL; + struct lstcon_group *grp = NULL; int rc; rc = lstcon_group_find(name, &grp); @@ -684,7 +684,7 @@ int lstcon_group_refresh(char *name, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; - lstcon_group_t *grp; + struct lstcon_group *grp; int rc; rc = lstcon_group_find(name, &grp); @@ -725,7 +725,7 @@ lstcon_group_refresh(char *name, struct list_head __user *result_up) int lstcon_group_list(int index, int len, char __user *name_up) { - lstcon_group_t *grp; + struct lstcon_group *grp; LASSERT(index >= 0); LASSERT(name_up); @@ -786,7 +786,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, lstcon_node_ent_t __user *dents_up) { lstcon_ndlist_ent_t *gentp; - lstcon_group_t *grp; + struct lstcon_group *grp; struct lstcon_ndlink *ndl; int rc; @@ -1188,7 +1188,7 @@ static int lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; - lstcon_group_t *grp; + struct lstcon_group *grp; int transop; int rc; @@ -1255,7 +1255,7 @@ lstcon_verify_batch(const char *name, lstcon_batch_t **batch) } static int -lstcon_verify_group(const char *name, lstcon_group_t **grp) +lstcon_verify_group(const char *name, struct lstcon_group **grp) { int rc; struct lstcon_ndlink *ndl; @@ -1285,8 +1285,8 @@ lstcon_test_add(char *batch_name, int type, int loop, { lstcon_test_t *test = NULL; int rc; - lstcon_group_t *src_grp = NULL; - lstcon_group_t *dst_grp = NULL; + struct lstcon_group *src_grp = NULL; + struct lstcon_group *dst_grp = NULL; lstcon_batch_t *batch = NULL; /* @@ -1515,7 +1515,7 @@ int lstcon_group_stat(char *grp_name, int timeout, struct list_head __user *result_up) { - lstcon_group_t *grp; + struct lstcon_group *grp; int rc; rc = lstcon_group_find(grp_name, &grp); @@ -1536,7 +1536,7 @@ lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, int timeout, struct list_head __user *result_up) { struct lstcon_ndlink *ndl; - lstcon_group_t *tmp; + struct lstcon_group *tmp; lnet_process_id_t id; int i; int rc; @@ -1628,7 +1628,7 @@ int lstcon_group_debug(int timeout, char *name, struct list_head __user *result_up) { - lstcon_group_t *grp; + struct lstcon_group *grp; int rc; rc = lstcon_group_find(name, &grp); @@ -1649,7 +1649,7 @@ lstcon_nodes_debug(int timeout, { lnet_process_id_t id; struct lstcon_ndlink *ndl; - lstcon_group_t *grp; + struct lstcon_group *grp; int i; int rc; @@ -1813,7 +1813,7 @@ int lstcon_session_end(void) { struct lstcon_rpc_trans *trans; - lstcon_group_t *grp; + struct lstcon_group *grp; lstcon_batch_t *bat; int rc = 0; @@ -1856,7 +1856,7 @@ lstcon_session_end(void) /* destroy all groups */ while (!list_empty(&console_session.ses_grp_list)) { grp = list_entry(console_session.ses_grp_list.next, - lstcon_group_t, grp_link); + struct lstcon_group, grp_link); LASSERT(grp->grp_ref == 1); lstcon_group_decref(grp); @@ -1909,7 +1909,7 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) srpc_msg_t *req = &rpc->srpc_reqstbuf->buf_msg; srpc_join_reqst_t *jreq = &req->msg_body.join_reqst; srpc_join_reply_t *jrep = &rep->msg_body.join_reply; - lstcon_group_t *grp = NULL; + struct lstcon_group *grp = NULL; struct lstcon_ndlink *ndl; int rc = 0; diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index dd9674dbc517..74bfcd865065 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -67,7 +67,8 @@ struct lstcon_ndlink { struct lstcon_node *ndl_node; /* pointer to node */ }; -typedef struct { +/* (alias of nodes) group descriptor */ +struct lstcon_group { struct list_head grp_link; /* chain on global group list */ int grp_ref; /* reference count */ @@ -78,7 +79,7 @@ typedef struct { struct list_head grp_trans_list; /* transaction list */ struct list_head grp_ndl_list; /* nodes list */ struct list_head grp_ndl_hash[0]; /* hash table for nodes */ -} lstcon_group_t; /* (alias of nodes) group descriptor */ +}; #define LST_BATCH_IDLE 0xB0 /* idle batch */ #define LST_BATCH_RUNNING 0xB1 /* running batch */ @@ -122,8 +123,8 @@ typedef struct lstcon_test { int tes_cliidx; /* client index, used for RPC creating */ struct list_head tes_trans_list; /* transaction list */ - lstcon_group_t *tes_src_grp; /* group run the test */ - lstcon_group_t *tes_dst_grp; /* target group */ + struct lstcon_group *tes_src_grp; /* group run the test */ + struct lstcon_group *tes_dst_grp; /* target group */ int tes_paramlen; /* test parameter length */ char tes_param[0]; /* test parameter */ -- GitLab From 7299d186046b6cb285951abe75fa691c24c3a1a8 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:45 -0400 Subject: [PATCH 2188/9938] staging: lustre: selftest: convert lstcon_tsb_hdr_t to proper struct Turn typedef lstcon_tsb_hdr_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 5 +++-- drivers/staging/lustre/lnet/selftest/console.c | 2 +- drivers/staging/lustre/lnet/selftest/console.h | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 4272a6167ad4..651d9ef3abdd 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -650,7 +650,7 @@ lstcon_dbgrpc_prep(struct lstcon_node *nd, unsigned feats, struct lstcon_rpc **c int lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, - lstcon_tsb_hdr_t *tsb, struct lstcon_rpc **crpc) + struct lstcon_tsb_hdr *tsb, struct lstcon_rpc **crpc) { lstcon_batch_t *batch; srpc_batch_reqst_t *brq; @@ -1135,7 +1135,8 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, case LST_TRANS_TSBCLIQRY: case LST_TRANS_TSBSRVQRY: rc = lstcon_batrpc_prep(nd, transop, feats, - (lstcon_tsb_hdr_t *)arg, &rpc); + (struct lstcon_tsb_hdr *)arg, + &rpc); break; case LST_TRANS_STATQRY: rc = lstcon_statrpc_prep(nd, feats, &rpc); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 47338f56a62c..41f732b91c00 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1406,7 +1406,7 @@ lstcon_test_batch_query(char *name, int testidx, int client, struct lstcon_rpc_trans *trans; struct list_head *translist; struct list_head *ndlist; - lstcon_tsb_hdr_t *hdr; + struct lstcon_tsb_hdr *hdr; lstcon_batch_t *batch; lstcon_test_t *test = NULL; int transop; diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 74bfcd865065..427bc9b8c4dc 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -84,13 +84,13 @@ struct lstcon_group { #define LST_BATCH_IDLE 0xB0 /* idle batch */ #define LST_BATCH_RUNNING 0xB1 /* running batch */ -typedef struct lstcon_tsb_hdr { +struct lstcon_tsb_hdr { lst_bid_t tsb_id; /* batch ID */ int tsb_index; /* test index */ -} lstcon_tsb_hdr_t; +}; typedef struct { - lstcon_tsb_hdr_t bat_hdr; /* test_batch header */ + struct lstcon_tsb_hdr bat_hdr; /* test_batch header */ struct list_head bat_link; /* chain on session's batches list */ int bat_ntest; /* # of test */ int bat_state; /* state of the batch */ @@ -109,7 +109,7 @@ typedef struct { } lstcon_batch_t; /* (tests ) batch descriptor */ typedef struct lstcon_test { - lstcon_tsb_hdr_t tes_hdr; /* test batch header */ + struct lstcon_tsb_hdr tes_hdr; /* test batch header */ struct list_head tes_link; /* chain on batch's tests list */ lstcon_batch_t *tes_batch; /* pointer to batch */ -- GitLab From dcdc7c84fbb227f46574a8c656cb4145b744af9c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:46 -0400 Subject: [PATCH 2189/9938] staging: lustre: selftest: convert lstcon_batch_t to proper struct Turn typedef lstcon_batch_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 4 +- .../staging/lustre/lnet/selftest/console.c | 46 +++++++++---------- .../staging/lustre/lnet/selftest/console.h | 7 +-- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 651d9ef3abdd..b64c24ebc4bc 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -652,7 +652,7 @@ int lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, struct lstcon_tsb_hdr *tsb, struct lstcon_rpc **crpc) { - lstcon_batch_t *batch; + struct lstcon_batch *batch; srpc_batch_reqst_t *brq; int rc; @@ -675,7 +675,7 @@ lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, LASSERT(!tsb->tsb_index); - batch = (lstcon_batch_t *)tsb; + batch = (struct lstcon_batch *)tsb; brq->bar_arg = batch->bat_arg; return 0; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 41f732b91c00..deb0bc05780d 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -828,9 +828,9 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, } static int -lstcon_batch_find(const char *name, lstcon_batch_t **batpp) +lstcon_batch_find(const char *name, struct lstcon_batch **batpp) { - lstcon_batch_t *bat; + struct lstcon_batch *bat; list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) { if (!strncmp(bat->bat_name, name, LST_NAME_SIZE)) { @@ -845,7 +845,7 @@ lstcon_batch_find(const char *name, lstcon_batch_t **batpp) int lstcon_batch_add(char *name) { - lstcon_batch_t *bat; + struct lstcon_batch *bat; int i; int rc; @@ -855,7 +855,7 @@ lstcon_batch_add(char *name) return rc; } - LIBCFS_ALLOC(bat, sizeof(lstcon_batch_t)); + LIBCFS_ALLOC(bat, sizeof(struct lstcon_batch)); if (!bat) { CERROR("Can't allocate descriptor for batch %s\n", name); return -ENOMEM; @@ -865,7 +865,7 @@ lstcon_batch_add(char *name) sizeof(struct list_head) * LST_NODE_HASHSIZE); if (!bat->bat_cli_hash) { CERROR("Can't allocate hash for batch %s\n", name); - LIBCFS_FREE(bat, sizeof(lstcon_batch_t)); + LIBCFS_FREE(bat, sizeof(struct lstcon_batch)); return -ENOMEM; } @@ -875,7 +875,7 @@ lstcon_batch_add(char *name) if (!bat->bat_srv_hash) { CERROR("Can't allocate hash for batch %s\n", name); LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE); - LIBCFS_FREE(bat, sizeof(lstcon_batch_t)); + LIBCFS_FREE(bat, sizeof(struct lstcon_batch)); return -ENOMEM; } @@ -883,7 +883,7 @@ lstcon_batch_add(char *name) if (strlen(name) > sizeof(bat->bat_name) - 1) { LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE); LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE); - LIBCFS_FREE(bat, sizeof(lstcon_batch_t)); + LIBCFS_FREE(bat, sizeof(struct lstcon_batch)); return -E2BIG; } strncpy(bat->bat_name, name, sizeof(bat->bat_name)); @@ -911,7 +911,7 @@ lstcon_batch_add(char *name) int lstcon_batch_list(int index, int len, char __user *name_up) { - lstcon_batch_t *bat; + struct lstcon_batch *bat; LASSERT(name_up); LASSERT(index >= 0); @@ -935,7 +935,7 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, struct list_head *clilst; struct list_head *srvlst; lstcon_test_t *test = NULL; - lstcon_batch_t *bat; + struct lstcon_batch *bat; struct lstcon_ndlink *ndl; int rc; @@ -1020,7 +1020,7 @@ lstcon_batrpc_condition(int transop, struct lstcon_node *nd, void *arg) } static int -lstcon_batch_op(lstcon_batch_t *bat, int transop, +lstcon_batch_op(struct lstcon_batch *bat, int transop, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; @@ -1046,7 +1046,7 @@ lstcon_batch_op(lstcon_batch_t *bat, int transop, int lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up) { - lstcon_batch_t *bat; + struct lstcon_batch *bat; int rc; if (lstcon_batch_find(name, &bat)) { @@ -1068,7 +1068,7 @@ lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up) int lstcon_batch_stop(char *name, int force, struct list_head __user *result_up) { - lstcon_batch_t *bat; + struct lstcon_batch *bat; int rc; if (lstcon_batch_find(name, &bat)) { @@ -1088,7 +1088,7 @@ lstcon_batch_stop(char *name, int force, struct list_head __user *result_up) } static void -lstcon_batch_destroy(lstcon_batch_t *bat) +lstcon_batch_destroy(struct lstcon_batch *bat) { struct lstcon_ndlink *ndl; lstcon_test_t *test; @@ -1137,14 +1137,14 @@ lstcon_batch_destroy(lstcon_batch_t *bat) sizeof(struct list_head) * LST_NODE_HASHSIZE); LIBCFS_FREE(bat->bat_srv_hash, sizeof(struct list_head) * LST_NODE_HASHSIZE); - LIBCFS_FREE(bat, sizeof(lstcon_batch_t)); + LIBCFS_FREE(bat, sizeof(struct lstcon_batch)); } static int lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg) { lstcon_test_t *test; - lstcon_batch_t *batch; + struct lstcon_batch *batch; struct lstcon_ndlink *ndl; struct list_head *hash; struct list_head *head; @@ -1236,7 +1236,7 @@ lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up) } static int -lstcon_verify_batch(const char *name, lstcon_batch_t **batch) +lstcon_verify_batch(const char *name, struct lstcon_batch **batch) { int rc; @@ -1287,7 +1287,7 @@ lstcon_test_add(char *batch_name, int type, int loop, int rc; struct lstcon_group *src_grp = NULL; struct lstcon_group *dst_grp = NULL; - lstcon_batch_t *batch = NULL; + struct lstcon_batch *batch = NULL; /* * verify that a batch of the given name exists, and the groups @@ -1368,7 +1368,7 @@ lstcon_test_add(char *batch_name, int type, int loop, } static int -lstcon_test_find(lstcon_batch_t *batch, int idx, lstcon_test_t **testpp) +lstcon_test_find(struct lstcon_batch *batch, int idx, lstcon_test_t **testpp) { lstcon_test_t *test; @@ -1407,7 +1407,7 @@ lstcon_test_batch_query(char *name, int testidx, int client, struct list_head *translist; struct list_head *ndlist; struct lstcon_tsb_hdr *hdr; - lstcon_batch_t *batch; + struct lstcon_batch *batch; lstcon_test_t *test = NULL; int transop; int rc; @@ -1610,7 +1610,7 @@ int lstcon_batch_debug(int timeout, char *name, int client, struct list_head __user *result_up) { - lstcon_batch_t *bat; + struct lstcon_batch *bat; int rc; rc = lstcon_batch_find(name, &bat); @@ -1757,7 +1757,7 @@ lstcon_session_new(char *name, int key, unsigned feats, rc = lstcon_rpc_pinger_start(); if (rc) { - lstcon_batch_t *bat = NULL; + struct lstcon_batch *bat = NULL; lstcon_batch_find(LST_DEFAULT_BATCH, &bat); lstcon_batch_destroy(bat); @@ -1814,7 +1814,7 @@ lstcon_session_end(void) { struct lstcon_rpc_trans *trans; struct lstcon_group *grp; - lstcon_batch_t *bat; + struct lstcon_batch *bat; int rc = 0; LASSERT(console_session.ses_state == LST_SESSION_ACTIVE); @@ -1848,7 +1848,7 @@ lstcon_session_end(void) /* destroy all batches */ while (!list_empty(&console_session.ses_bat_list)) { bat = list_entry(console_session.ses_bat_list.next, - lstcon_batch_t, bat_link); + struct lstcon_batch, bat_link); lstcon_batch_destroy(bat); } diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 427bc9b8c4dc..ccd4982b0cd6 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -89,7 +89,8 @@ struct lstcon_tsb_hdr { int tsb_index; /* test index */ }; -typedef struct { +/* (tests ) batch descriptor */ +struct lstcon_batch { struct lstcon_tsb_hdr bat_hdr; /* test_batch header */ struct list_head bat_link; /* chain on session's batches list */ int bat_ntest; /* # of test */ @@ -106,12 +107,12 @@ typedef struct { struct list_head *bat_cli_hash; /* hash table of client nodes */ struct list_head bat_srv_list; /* list head of server nodes */ struct list_head *bat_srv_hash; /* hash table of server nodes */ -} lstcon_batch_t; /* (tests ) batch descriptor */ +}; typedef struct lstcon_test { struct lstcon_tsb_hdr tes_hdr; /* test batch header */ struct list_head tes_link; /* chain on batch's tests list */ - lstcon_batch_t *tes_batch; /* pointer to batch */ + struct lstcon_batch *tes_batch; /* pointer to batch */ int tes_type; /* type of the test, i.e: bulk, ping */ int tes_stop_onerr; /* stop on error */ -- GitLab From fd7a1a32514c46c1629290aa03d3e1d91c98dab4 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:48 -0400 Subject: [PATCH 2190/9938] staging: lustre: selftest: convert srpc_msg_t to proper struct Turn typedef struct srpc_msg to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/brw_test.c | 8 ++++---- drivers/staging/lustre/lnet/selftest/conrpc.c | 14 +++++++------- drivers/staging/lustre/lnet/selftest/conrpc.h | 2 +- drivers/staging/lustre/lnet/selftest/console.c | 10 +++++----- drivers/staging/lustre/lnet/selftest/framework.c | 14 +++++++------- drivers/staging/lustre/lnet/selftest/ping_test.c | 4 ++-- drivers/staging/lustre/lnet/selftest/rpc.c | 11 ++++++----- drivers/staging/lustre/lnet/selftest/rpc.h | 6 +++--- drivers/staging/lustre/lnet/selftest/selftest.h | 10 +++++----- 9 files changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index bbb003da3e3e..7f539f92321c 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -318,7 +318,7 @@ brw_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc) __u64 magic = BRW_MAGIC; struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; - srpc_msg_t *msg = &rpc->crpc_replymsg; + struct srpc_msg *msg = &rpc->crpc_replymsg; srpc_brw_reply_t *reply = &msg->msg_body.brw_reply; srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; @@ -384,7 +384,7 @@ brw_bulk_ready(struct srpc_server_rpc *rpc, int status) __u64 magic = BRW_MAGIC; srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply; srpc_brw_reqst_t *reqst; - srpc_msg_t *reqstmsg; + struct srpc_msg *reqstmsg; LASSERT(rpc->srpc_bulk); LASSERT(rpc->srpc_reqstbuf); @@ -418,8 +418,8 @@ static int brw_server_handle(struct srpc_server_rpc *rpc) { struct srpc_service *sv = rpc->srpc_scd->scd_svc; - srpc_msg_t *replymsg = &rpc->srpc_replymsg; - srpc_msg_t *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; + struct srpc_msg *replymsg = &rpc->srpc_replymsg; + struct srpc_msg *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply; srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst; int npg; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index b64c24ebc4bc..31d7b4f4a9e4 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -46,7 +46,7 @@ #include "conrpc.h" #include "console.h" -void lstcon_rpc_stat_reply(struct lstcon_rpc_trans *, srpc_msg_t *, +void lstcon_rpc_stat_reply(struct lstcon_rpc_trans *, struct srpc_msg *, struct lstcon_node *, lstcon_trans_stat_t *); static void @@ -386,7 +386,7 @@ lstcon_rpc_trans_postwait(struct lstcon_rpc_trans *trans, int timeout) } static int -lstcon_rpc_get_reply(struct lstcon_rpc *crpc, srpc_msg_t **msgpp) +lstcon_rpc_get_reply(struct lstcon_rpc *crpc, struct srpc_msg **msgpp) { struct lstcon_node *nd = crpc->crp_node; struct srpc_client_rpc *rpc = crpc->crp_rpc; @@ -426,7 +426,7 @@ void lstcon_rpc_trans_stat(struct lstcon_rpc_trans *trans, lstcon_trans_stat_t *stat) { struct lstcon_rpc *crpc; - srpc_msg_t *rep; + struct srpc_msg *rep; int error; LASSERT(stat); @@ -475,7 +475,7 @@ lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans, lstcon_rpc_ent_t *ent; srpc_generic_reply_t *rep; struct lstcon_rpc *crpc; - srpc_msg_t *msg; + struct srpc_msg *msg; struct lstcon_node *nd; long dur; struct timeval tv; @@ -916,7 +916,7 @@ lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, static int lstcon_sesnew_stat_reply(struct lstcon_rpc_trans *trans, - struct lstcon_node *nd, srpc_msg_t *reply) + struct lstcon_node *nd, struct srpc_msg *reply) { srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply; int status = mksn_rep->mksn_status; @@ -962,7 +962,7 @@ lstcon_sesnew_stat_reply(struct lstcon_rpc_trans *trans, } void -lstcon_rpc_stat_reply(struct lstcon_rpc_trans *trans, srpc_msg_t *msg, +lstcon_rpc_stat_reply(struct lstcon_rpc_trans *trans, struct srpc_msg *msg, struct lstcon_node *nd, lstcon_trans_stat_t *stat) { srpc_rmsn_reply_t *rmsn_rep; @@ -1171,7 +1171,7 @@ lstcon_rpc_pinger(void *arg) struct stt_timer *ptimer = (struct stt_timer *)arg; struct lstcon_rpc_trans *trans; struct lstcon_rpc *crpc; - srpc_msg_t *rep; + struct srpc_msg *rep; srpc_debug_reqst_t *drq; struct lstcon_ndlink *ndl; struct lstcon_node *nd; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index 7281abdc4b2a..90c3385a355c 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -106,7 +106,7 @@ struct lstcon_rpc_trans { #define LST_TRANS_STATQRY 0x21 typedef int (*lstcon_rpc_cond_func_t)(int, struct lstcon_node *, void *); -typedef int (*lstcon_rpc_readent_func_t)(int, srpc_msg_t *, +typedef int (*lstcon_rpc_readent_func_t)(int, struct srpc_msg *, lstcon_rpc_ent_t __user *); int lstcon_sesrpc_prep(struct lstcon_node *nd, int transop, diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index deb0bc05780d..03c73b014b2c 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -370,7 +370,7 @@ lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg) } static int -lstcon_sesrpc_readent(int transop, srpc_msg_t *msg, +lstcon_sesrpc_readent(int transop, struct srpc_msg *msg, lstcon_rpc_ent_t __user *ent_up) { srpc_debug_reply_t *rep; @@ -1383,7 +1383,7 @@ lstcon_test_find(struct lstcon_batch *batch, int idx, lstcon_test_t **testpp) } static int -lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg, +lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg, lstcon_rpc_ent_t __user *ent_up) { srpc_batch_reply_t *rep = &msg->msg_body.bat_reply; @@ -1462,7 +1462,7 @@ lstcon_test_batch_query(char *name, int testidx, int client, } static int -lstcon_statrpc_readent(int transop, srpc_msg_t *msg, +lstcon_statrpc_readent(int transop, struct srpc_msg *msg, lstcon_rpc_ent_t __user *ent_up) { srpc_stat_reply_t *rep = &msg->msg_body.stat_reply; @@ -1905,8 +1905,8 @@ lstcon_session_feats_check(unsigned feats) static int lstcon_acceptor_handle(struct srpc_server_rpc *rpc) { - srpc_msg_t *rep = &rpc->srpc_replymsg; - srpc_msg_t *req = &rpc->srpc_reqstbuf->buf_msg; + struct srpc_msg *rep = &rpc->srpc_replymsg; + struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg; srpc_join_reqst_t *jreq = &req->msg_body.join_reqst; srpc_join_reply_t *jrep = &rep->msg_body.join_reply; struct lstcon_group *grp = NULL; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 84239c30761d..ef3cc8264daa 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -405,7 +405,7 @@ int sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) { struct sfw_session *sn = sfw_data.fw_session; - srpc_msg_t *msg = container_of(request, srpc_msg_t, + struct srpc_msg *msg = container_of(request, struct srpc_msg, msg_body.mksn_reqst); int cplen = 0; @@ -438,7 +438,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) /* * reject the request if it requires unknown features * NB: old version will always accept all features because it's not - * aware of srpc_msg_t::msg_ses_feats, it's a defect but it's also + * aware of srpc_msg::msg_ses_feats, it's a defect but it's also * harmless because it will return zero feature to console, and it's * console's responsibility to make sure all nodes in a session have * same feature mask. @@ -685,7 +685,7 @@ sfw_destroy_session(struct sfw_session *sn) } static void -sfw_unpack_addtest_req(srpc_msg_t *msg) +sfw_unpack_addtest_req(struct srpc_msg *msg) { srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; @@ -731,7 +731,7 @@ sfw_unpack_addtest_req(srpc_msg_t *msg) static int sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) { - srpc_msg_t *msg = &rpc->srpc_reqstbuf->buf_msg; + struct srpc_msg *msg = &rpc->srpc_reqstbuf->buf_msg; srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; struct srpc_bulk *bk = rpc->srpc_bulk; int ndest = req->tsr_ndest; @@ -1227,8 +1227,8 @@ static int sfw_handle_server_rpc(struct srpc_server_rpc *rpc) { struct srpc_service *sv = rpc->srpc_scd->scd_svc; - srpc_msg_t *reply = &rpc->srpc_replymsg; - srpc_msg_t *request = &rpc->srpc_reqstbuf->buf_msg; + struct srpc_msg *reply = &rpc->srpc_replymsg; + struct srpc_msg *request = &rpc->srpc_reqstbuf->buf_msg; unsigned features = LST_FEATS_MASK; int rc = 0; @@ -1415,7 +1415,7 @@ sfw_create_rpc(lnet_process_id_t peer, int service, } void -sfw_unpack_message(srpc_msg_t *msg) +sfw_unpack_message(struct srpc_msg *msg) { if (msg->msg_magic == SRPC_MSG_MAGIC) return; /* no flipping needed */ diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index c6f2caa86d73..8a9d7a41f7de 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -171,8 +171,8 @@ static int ping_server_handle(struct srpc_server_rpc *rpc) { struct srpc_service *sv = rpc->srpc_scd->scd_svc; - srpc_msg_t *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; - srpc_msg_t *replymsg = &rpc->srpc_replymsg; + struct srpc_msg *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; + struct srpc_msg *replymsg = &rpc->srpc_replymsg; srpc_ping_reqst_t *req = &reqstmsg->msg_body.ping_reqst; srpc_ping_reply_t *rep = &rpc->srpc_replymsg.msg_body.ping_reply; diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index e3cd40786cac..91af6ba322fb 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -803,7 +803,7 @@ srpc_send_request(struct srpc_client_rpc *rpc) rc = srpc_post_active_rdma(srpc_serv_portal(rpc->crpc_service), rpc->crpc_service, &rpc->crpc_reqstmsg, - sizeof(srpc_msg_t), LNET_MD_OP_PUT, + sizeof(struct srpc_msg), LNET_MD_OP_PUT, rpc->crpc_dest, LNET_NID_ANY, &rpc->crpc_reqstmdh, ev); if (rc) { @@ -827,7 +827,8 @@ srpc_prepare_reply(struct srpc_client_rpc *rpc) *id = srpc_next_id(); rc = srpc_post_passive_rdma(SRPC_RDMA_PORTAL, 0, *id, - &rpc->crpc_replymsg, sizeof(srpc_msg_t), + &rpc->crpc_replymsg, + sizeof(struct srpc_msg), LNET_MD_OP_PUT, rpc->crpc_dest, &rpc->crpc_replymdh, ev); if (rc) { @@ -995,7 +996,7 @@ srpc_handle_rpc(struct swi_workitem *wi) default: LBUG(); case SWI_STATE_NEWBORN: { - srpc_msg_t *msg; + struct srpc_msg *msg; srpc_generic_reply_t *reply; msg = &rpc->srpc_reqstbuf->buf_msg; @@ -1179,7 +1180,7 @@ srpc_send_rpc(struct swi_workitem *wi) { int rc = 0; struct srpc_client_rpc *rpc; - srpc_msg_t *reply; + struct srpc_msg *reply; int do_bulk; LASSERT(wi); @@ -1415,7 +1416,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) struct srpc_server_rpc *srpc; struct srpc_buffer *buffer; struct srpc_service *sv; - srpc_msg_t *msg; + struct srpc_msg *msg; srpc_msg_type_t type; LASSERT(!in_interrupt()); diff --git a/drivers/staging/lustre/lnet/selftest/rpc.h b/drivers/staging/lustre/lnet/selftest/rpc.h index a79c315f2ceb..fdf881ffd9ad 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.h +++ b/drivers/staging/lustre/lnet/selftest/rpc.h @@ -242,7 +242,7 @@ typedef struct { #define SRPC_MSG_MAGIC 0xeeb0f00d #define SRPC_MSG_VERSION 1 -typedef struct srpc_msg { +struct srpc_msg { __u32 msg_magic; /* magic number */ __u32 msg_version; /* message version number */ __u32 msg_type; /* type of message body: srpc_msg_type_t */ @@ -273,10 +273,10 @@ typedef struct srpc_msg { srpc_brw_reqst_t brw_reqst; srpc_brw_reply_t brw_reply; } msg_body; -} WIRE_ATTR srpc_msg_t; +} WIRE_ATTR; static inline void -srpc_unpack_msg_hdr(srpc_msg_t *msg) +srpc_unpack_msg_hdr(struct srpc_msg *msg) { if (msg->msg_magic == SRPC_MSG_MAGIC) return; /* no flipping needed */ diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index bc4c7ac98409..1dac777daf63 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -166,7 +166,7 @@ struct srpc_bulk { /* message buffer descriptor */ struct srpc_buffer { struct list_head buf_list; /* chain on srpc_service::*_msgq */ - srpc_msg_t buf_msg; + struct srpc_msg buf_msg; lnet_handle_md_t buf_mdh; lnet_nid_t buf_self; lnet_process_id_t buf_peer; @@ -191,7 +191,7 @@ struct srpc_server_rpc { struct srpc_event srpc_ev; /* bulk/reply event */ lnet_nid_t srpc_self; lnet_process_id_t srpc_peer; - srpc_msg_t srpc_replymsg; + struct srpc_msg srpc_replymsg; lnet_handle_md_t srpc_replymdh; struct srpc_buffer *srpc_reqstbuf; struct srpc_bulk *srpc_bulk; @@ -227,8 +227,8 @@ struct srpc_client_rpc { struct srpc_event crpc_replyev; /* reply event */ /* bulk, request(reqst), and reply exchanged on wire */ - srpc_msg_t crpc_reqstmsg; - srpc_msg_t crpc_replymsg; + struct srpc_msg crpc_reqstmsg; + struct srpc_msg crpc_replymsg; lnet_handle_md_t crpc_reqstmdh; lnet_handle_md_t crpc_replymdh; struct srpc_bulk crpc_bulk; @@ -423,7 +423,7 @@ int sfw_create_test_rpc(struct sfw_test_unit *tsu, void sfw_abort_rpc(struct srpc_client_rpc *rpc); void sfw_post_rpc(struct srpc_client_rpc *rpc); void sfw_client_rpc_done(struct srpc_client_rpc *rpc); -void sfw_unpack_message(srpc_msg_t *msg); +void sfw_unpack_message(struct srpc_msg *msg); void sfw_free_pages(struct srpc_server_rpc *rpc); void sfw_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i); int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, -- GitLab From c970b6058b60e57c9b831fd69ded4cafb62fa308 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 6 Apr 2016 15:25:50 -0400 Subject: [PATCH 2191/9938] staging: lustre: selftest: change srpc_state_t to proper enum Turn typedef srpc_state_t to proper enum Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/rpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 91af6ba322fb..561e28c644b1 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -46,19 +46,19 @@ #include "selftest.h" -typedef enum { +enum srpc_state { SRPC_STATE_NONE, SRPC_STATE_NI_INIT, SRPC_STATE_EQ_INIT, SRPC_STATE_RUNNING, SRPC_STATE_STOPPING, -} srpc_state_t; +}; static struct smoketest_rpc { spinlock_t rpc_glock; /* global lock */ struct srpc_service *rpc_services[SRPC_SERVICE_MAX_ID + 1]; lnet_handle_eq_t rpc_lnet_eq; /* _the_ LNet event queue */ - srpc_state_t rpc_state; + enum srpc_state rpc_state; srpc_counters_t rpc_counters; __u64 rpc_matchbits; /* matchbits counter */ } srpc_data; -- GitLab From 3726470610327f353e816e21a86bc432dd929584 Mon Sep 17 00:00:00 2001 From: Cihangir Akturk Date: Sat, 9 Apr 2016 21:47:44 +0300 Subject: [PATCH 2192/9938] staging: lustre: split error handling code into multiple labels Instead of using a switch-case statement to find out what kind of error has just happened, split error handling logic into multiple labels and jump right into the appropriate label to do the error handling. This way it is easier to follow different code paths. It also looks easy on the eyes. Additionally silences the following coccinelle warning: drivers/staging/lustre/lustre/obdecho/echo_client.c:762:22-27: ERROR: ed is NULL but dereferenced. Signed-off-by: Cihangir Akturk Acked-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/obdecho/echo_client.c | 54 +++++++------------ 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 4ae4a89fe80f..b271895d4395 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -668,8 +668,7 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, struct obd_device *obd = NULL; /* to keep compiler happy */ struct obd_device *tgt; const char *tgt_type_name; - int rc; - int cleanup = 0; + int rc, err; ed = kzalloc(sizeof(*ed), GFP_NOFS); if (!ed) { @@ -677,16 +676,14 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, goto out; } - cleanup = 1; cd = &ed->ed_cl; rc = cl_device_init(cd, t); if (rc) - goto out; + goto out_free; cd->cd_lu_dev.ld_ops = &echo_device_lu_ops; cd->cd_ops = &echo_device_cl_ops; - cleanup = 2; obd = class_name2obd(lustre_cfg_string(cfg, 0)); LASSERT(obd); LASSERT(env); @@ -696,28 +693,25 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, CERROR("Can not find tgt device %s\n", lustre_cfg_string(cfg, 1)); rc = -ENODEV; - goto out; + goto out_device_fini; } next = tgt->obd_lu_dev; if (!strcmp(tgt->obd_type->typ_name, LUSTRE_MDT_NAME)) { CERROR("echo MDT client must be run on server\n"); rc = -EOPNOTSUPP; - goto out; + goto out_device_fini; } rc = echo_site_init(env, ed); if (rc) - goto out; - - cleanup = 3; + goto out_device_fini; rc = echo_client_setup(env, obd, cfg); if (rc) - goto out; + goto out_site_fini; ed->ed_ec = &obd->u.echo_client; - cleanup = 4; /* if echo client is to be stacked upon ost device, the next is * NULL since ost is not a clio device so far @@ -729,7 +723,7 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, if (next) { if (next->ld_site) { rc = -EBUSY; - goto out; + goto out_cleanup; } next->ld_site = &ed->ed_site->cs_lu; @@ -737,7 +731,7 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, next->ld_type->ldt_name, NULL); if (rc) - goto out; + goto out_cleanup; } else { LASSERT(strcmp(tgt_type_name, LUSTRE_OST_NAME) == 0); @@ -745,27 +739,19 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, ed->ed_next = next; return &cd->cd_lu_dev; -out: - switch (cleanup) { - case 4: { - int rc2; - - rc2 = echo_client_cleanup(obd); - if (rc2) - CERROR("Cleanup obd device %s error(%d)\n", - obd->obd_name, rc2); - } - case 3: - echo_site_fini(env, ed); - case 2: - cl_device_fini(&ed->ed_cl); - case 1: - kfree(ed); - case 0: - default: - break; - } +out_cleanup: + err = echo_client_cleanup(obd); + if (err) + CERROR("Cleanup obd device %s error(%d)\n", + obd->obd_name, err); +out_site_fini: + echo_site_fini(env, ed); +out_device_fini: + cl_device_fini(&ed->ed_cl); +out_free: + kfree(ed); +out: return ERR_PTR(rc); } -- GitLab From e4feb2f257955cd9319f38bc935eda99ca6294b6 Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Mon, 4 Apr 2016 23:31:11 -0400 Subject: [PATCH 2193/9938] staging: unisys: visorbus: 'unsigned' --> 'unsigned int' Fix as recommended by checkpatch. Signed-off-by: Tim Sell Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 61877722b1da..9f0ec171025a 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -66,7 +66,7 @@ static u32 dump_vhba_bus; static int visorchipset_open(struct inode *inode, struct file *file) { - unsigned minor_number = iminor(inode); + unsigned int minor_number = iminor(inode); if (minor_number) return -ENODEV; -- GitLab From a07d7c3858aef317495e061ffc93207c89771fe2 Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Mon, 4 Apr 2016 23:31:12 -0400 Subject: [PATCH 2194/9938] staging: unisys: visorbus: CHECK: Alignment should match open parenthesis Fix 'CHECK: Alignment should match open parenthesis' as recommended by checkpatch. Signed-off-by: Tim Sell Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorchipset.c | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 9f0ec171025a..afcd29135a68 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -530,10 +530,11 @@ static ssize_t toolaction_store(struct device *dev, if (kstrtou8(buf, 10, &tool_action)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), - &tool_action, sizeof(u8)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), + &tool_action, sizeof(u8)); if (ret) return ret; @@ -565,10 +566,11 @@ static ssize_t boottotool_store(struct device *dev, return -EINVAL; efi_spar_indication.boot_to_tool = val; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &(efi_spar_indication), - sizeof(struct efi_spar_indication)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &(efi_spar_indication), + sizeof(struct efi_spar_indication)); if (ret) return ret; @@ -596,10 +598,11 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr, if (kstrtou32(buf, 10, &error)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); if (ret) return ret; return count; @@ -610,10 +613,11 @@ static ssize_t textid_show(struct device *dev, struct device_attribute *attr, { u32 text_id; - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); + visorchannel_read + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); } @@ -626,10 +630,11 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr, if (kstrtou32(buf, 10, &text_id)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); if (ret) return ret; return count; @@ -657,10 +662,11 @@ static ssize_t remaining_steps_store(struct device *dev, if (kstrtou16(buf, 10, &remaining_steps)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); if (ret) return ret; return count; @@ -1226,8 +1232,9 @@ bus_configure(struct controlvm_message *inmsg, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; } else { - visorchannel_set_clientpartition(bus_info->visorchannel, - cmd->configure_bus.guest_handle); + visorchannel_set_clientpartition + (bus_info->visorchannel, + cmd->configure_bus.guest_handle); bus_info->partition_uuid = parser_id_get(parser_ctx); parser_param_start(parser_ctx, PARSERSTRING_NAME); bus_info->name = parser_string_get(parser_ctx); @@ -1709,9 +1716,10 @@ parahotplug_process_message(struct controlvm_message *inmsg) * initialization. */ parahotplug_request_kickoff(req); - controlvm_respond_physdev_changestate(&inmsg->hdr, - CONTROLVM_RESP_SUCCESS, - inmsg->cmd.device_change_state.state); + controlvm_respond_physdev_changestate + (&inmsg->hdr, + CONTROLVM_RESP_SUCCESS, + inmsg->cmd.device_change_state.state); parahotplug_request_destroy(req); } else { /* For disable messages, add the request to the @@ -1823,8 +1831,9 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) break; default: if (inmsg.hdr.flags.response_expected) - controlvm_respond(&inmsg.hdr, - -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); + controlvm_respond + (&inmsg.hdr, + -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); break; } @@ -2177,10 +2186,11 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) if (!*file_controlvm_channel) return -ENXIO; - visorchannel_read(*file_controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - gp_control_channel), - &addr, sizeof(addr)); + visorchannel_read + (*file_controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + gp_control_channel), + &addr, sizeof(addr)); if (!addr) return -ENXIO; -- GitLab From dc38082f0f0967f8badce0ae5ecf07cd5843d65f Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Mon, 4 Apr 2016 23:31:13 -0400 Subject: [PATCH 2195/9938] staging: unisys: visornic: CHECK: Alignment should match open parenthesis Fix 'CHECK: Alignment should match open parenthesis' as recommended by checkpatch. Signed-off-by: Tim Sell Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index be0d057346c3..763738d56c9d 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -436,8 +436,8 @@ post_skb(struct uiscmdrsp *cmdrsp, cmdrsp->net.type = NET_RCV_POST; cmdrsp->cmdtype = CMD_NET_TYPE; if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) { + IOCHAN_TO_IOPART, + cmdrsp)) { atomic_inc(&devdata->num_rcvbuf_in_iovm); devdata->chstat.sent_post++; } else { @@ -465,8 +465,8 @@ send_enbdis(struct net_device *netdev, int state, devdata->cmdrsp_rcv->net.type = NET_RCV_ENBDIS; devdata->cmdrsp_rcv->cmdtype = CMD_NET_TYPE; if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - devdata->cmdrsp_rcv)) + IOCHAN_TO_IOPART, + devdata->cmdrsp_rcv)) devdata->chstat.sent_enbdis++; } @@ -1647,8 +1647,9 @@ service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, * the lower watermark for * netif_wake_queue() */ - if (vnic_hit_low_watermark(devdata, - devdata->lower_threshold_net_xmits)) { + if (vnic_hit_low_watermark + (devdata, + devdata->lower_threshold_net_xmits)) { /* enough NET_XMITs completed * so can restart netif queue */ -- GitLab From 2b9bcf81d37751ebdae8c1456d14c1462e4e8f61 Mon Sep 17 00:00:00 2001 From: David Binder Date: Mon, 4 Apr 2016 23:31:32 -0400 Subject: [PATCH 2196/9938] staging: unisys: visorchannel: remove redundant member size Removes size member from the visorchannel struct, since it was a duplicate of the nbytes member. Signed-off-by: David Binder Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchannel.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index b68a904ac617..43373582cf1d 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -40,7 +40,6 @@ struct visorchannel { bool requested; struct channel_header chan_hdr; uuid_le guid; - ulong size; bool needs_lock; /* channel creator knows if more than one */ /* thread will be inserting or removing */ spinlock_t insert_lock; /* protect head writes in chan_hdr */ @@ -134,8 +133,6 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, } channel->nbytes = channel_bytes; - - channel->size = channel_bytes; channel->guid = guid; return channel; @@ -186,7 +183,7 @@ EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); ulong visorchannel_get_nbytes(struct visorchannel *channel) { - return channel->size; + return channel->nbytes; } EXPORT_SYMBOL_GPL(visorchannel_get_nbytes); -- GitLab From 1366a3db3dcf4d64c5eb0621df79a3d1cf2da5da Mon Sep 17 00:00:00 2001 From: David Kershner Date: Mon, 4 Apr 2016 23:31:37 -0400 Subject: [PATCH 2197/9938] staging: unisys: visorbus: visorchipset_init clean up gotos Several error paths were not logging a message to s-Par during failure. Error paths in visorchipset_init() were corrected so that they now all do proper clean-ups. This made it necessary to move the function visorchipset_file_cleanup() above visorchipset_init so it can be referenced. Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorchipset.c | 68 +++++++++++-------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index afcd29135a68..0583b515171a 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2290,16 +2290,25 @@ visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) return 0; } +static void +visorchipset_file_cleanup(dev_t major_dev) +{ + if (file_cdev.ops) + cdev_del(&file_cdev); + file_cdev.ops = NULL; + unregister_chrdev_region(major_dev, 1); +} + static int visorchipset_init(struct acpi_device *acpi_device) { - int rc = 0; + int err = -ENODEV; u64 addr; uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID; addr = controlvm_get_channel_address(); if (!addr) - return -ENODEV; + goto error; memset(&busdev_notifiers, 0, sizeof(busdev_notifiers)); memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info)); @@ -2307,22 +2316,19 @@ visorchipset_init(struct acpi_device *acpi_device) controlvm_channel = visorchannel_create_with_lock(addr, 0, GFP_KERNEL, uuid); if (!controlvm_channel) - return -ENODEV; + goto error; + if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT( visorchannel_get_header(controlvm_channel))) { initialize_controlvm_payload(); } else { - visorchannel_destroy(controlvm_channel); - controlvm_channel = NULL; - return -ENODEV; + goto error_destroy_channel; } major_dev = MKDEV(visorchipset_major, 0); - rc = visorchipset_file_init(major_dev, &controlvm_channel); - if (rc < 0) { - POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR); - goto cleanup; - } + err = visorchipset_file_init(major_dev, &controlvm_channel); + if (err < 0) + goto error_destroy_payload; memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); @@ -2341,27 +2347,33 @@ visorchipset_init(struct acpi_device *acpi_device) visorchipset_platform_device.dev.devt = major_dev; if (platform_device_register(&visorchipset_platform_device) < 0) { POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR); - rc = -ENODEV; - goto cleanup; + err = -ENODEV; + goto error_cancel_work; } POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO); - rc = visorbus_init(); -cleanup: - if (rc) { - POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc, - POSTCODE_SEVERITY_ERR); - } - return rc; -} + err = visorbus_init(); + if (err < 0) + goto error_unregister; -static void -visorchipset_file_cleanup(dev_t major_dev) -{ - if (file_cdev.ops) - cdev_del(&file_cdev); - file_cdev.ops = NULL; - unregister_chrdev_region(major_dev, 1); + return 0; + +error_unregister: + platform_device_unregister(&visorchipset_platform_device); + +error_cancel_work: + cancel_delayed_work_sync(&periodic_controlvm_work); + visorchipset_file_cleanup(major_dev); + +error_destroy_payload: + destroy_controlvm_payload_info(&controlvm_payload_info); + +error_destroy_channel: + visorchannel_destroy(controlvm_channel); + +error: + POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR); + return err; } static int -- GitLab From 3cb3fa3b7914cd1e3e576059d3034db5c8f3c894 Mon Sep 17 00:00:00 2001 From: David Kershner Date: Mon, 4 Apr 2016 23:31:38 -0400 Subject: [PATCH 2198/9938] staging: unisys: visorbus: device_epilog: clean up gotos The away flag is ambiguous, rename it to out and appropriately call the correct goto. Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorchipset.c | 36 +++++++------------ 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 0583b515171a..a22aec4bcef2 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1041,30 +1041,30 @@ device_epilog(struct visor_device *dev_info, bool need_response, bool for_visorbus) { struct visorchipset_busdev_notifiers *notifiers; - bool notified = false; struct controlvm_message_header *pmsg_hdr = NULL; notifiers = &busdev_notifiers; + down(¬ifier_lock); if (!dev_info) { /* relying on a valid passed in response code */ /* be lazy and re-use msg_hdr for this failure, is this ok?? */ pmsg_hdr = msg_hdr; - goto away; + goto out_respond_and_unlock; } if (dev_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = dev_info->pending_msg_hdr; - goto away; + goto out_respond_and_unlock; } if (need_response) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto away; + goto out_respond_and_unlock; } memcpy(pmsg_hdr, msg_hdr, @@ -1072,13 +1072,12 @@ device_epilog(struct visor_device *dev_info, dev_info->pending_msg_hdr = pmsg_hdr; } - down(¬ifier_lock); if (response >= 0) { switch (cmd) { case CONTROLVM_DEVICE_CREATE: if (notifiers->device_create) { (*notifiers->device_create) (dev_info); - notified = true; + goto out_unlock; } break; case CONTROLVM_DEVICE_CHANGESTATE: @@ -1088,7 +1087,7 @@ device_epilog(struct visor_device *dev_info, segment_state_running.operating) { if (notifiers->device_resume) { (*notifiers->device_resume) (dev_info); - notified = true; + goto out_unlock; } } /* ServerNotReady / ServerLost / SegmentStateStandby */ @@ -1100,32 +1099,23 @@ device_epilog(struct visor_device *dev_info, */ if (notifiers->device_pause) { (*notifiers->device_pause) (dev_info); - notified = true; + goto out_unlock; } } break; case CONTROLVM_DEVICE_DESTROY: if (notifiers->device_destroy) { (*notifiers->device_destroy) (dev_info); - notified = true; + goto out_unlock; } break; } } -away: - if (notified) - /* The callback function just called above is responsible - * for calling the appropriate visorchipset_busdev_responders - * function, which will call device_responder() - */ - ; - else - /* - * Do not kfree(pmsg_hdr) as this is the failure path. - * The success path ('notified') will call the responder - * directly and kfree() there. - */ - device_responder(cmd, pmsg_hdr, response); + +out_respond_and_unlock: + device_responder(cmd, pmsg_hdr, response); + +out_unlock: up(¬ifier_lock); } -- GitLab From 4a185e54e15cbde6df85669b0af53db0575e17d0 Mon Sep 17 00:00:00 2001 From: David Kershner Date: Mon, 4 Apr 2016 23:31:39 -0400 Subject: [PATCH 2199/9938] staging: unisys: visorbus: make bus_epilog match device_epilog The paths in bus_epilog should match device_epilog. Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorchipset.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index a22aec4bcef2..c1b872c02974 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -965,7 +965,6 @@ bus_epilog(struct visor_device *bus_info, u32 cmd, struct controlvm_message_header *msg_hdr, int response, bool need_response) { - bool notified = false; struct controlvm_message_header *pmsg_hdr = NULL; down(¬ifier_lock); @@ -1003,32 +1002,20 @@ bus_epilog(struct visor_device *bus_info, case CONTROLVM_BUS_CREATE: if (busdev_notifiers.bus_create) { (*busdev_notifiers.bus_create) (bus_info); - notified = true; + goto out_unlock; } break; case CONTROLVM_BUS_DESTROY: if (busdev_notifiers.bus_destroy) { (*busdev_notifiers.bus_destroy) (bus_info); - notified = true; + goto out_unlock; } break; } } out_respond_and_unlock: - if (notified) - /* The callback function just called above is responsible - * for calling the appropriate visorchipset_busdev_responders - * function, which will call bus_responder() - */ - ; - else - /* - * Do not kfree(pmsg_hdr) as this is the failure path. - * The success path ('notified') will call the responder - * directly and kfree() there. - */ - bus_responder(cmd, pmsg_hdr, response); + bus_responder(cmd, pmsg_hdr, response); out_unlock: up(¬ifier_lock); -- GitLab From d2de2ffff5d36a6e38753cf4f9d6bd35b83bd6c5 Mon Sep 17 00:00:00 2001 From: Alexander Curtin Date: Wed, 6 Apr 2016 11:20:21 -0400 Subject: [PATCH 2200/9938] staging: unisys: removed unused 'visor_device.respond_to_device_create' The respond_to_device_create flag was used previously when we used to delay responses to create requests until the drivers were finished loading. This behaviour was removed some time ago, yet the field still existed, while never being referenced or even initialized. Signed-off-by: Alexander Curtin Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/visorbus.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 3788d167b3c6..db59d9731ec2 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -134,7 +134,6 @@ struct visor_device { struct list_head list_all; struct periodic_work *periodic_work; bool being_removed; - bool responded_to_device_create; /* the code will detect and behave appropriately) */ struct semaphore visordriver_callback_lock; bool pausing; -- GitLab From 6fac083b8df8450af4550238faa104396ccecf13 Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Fri, 8 Apr 2016 08:48:05 -0400 Subject: [PATCH 2201/9938] staging: unisys: visorinput: remove erroneous 'FIXME' comments These comments were mistakenly carried forward by a previous copy/paste. Signed-off-by: Tim Sell Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorinput/visorinput.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 3299cf502aa0..dc94261b31f9 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -123,9 +123,9 @@ static const unsigned char visorkbd_keycode[KEYCODE_TABLE_BYTES] = { [38] = KEY_L, [39] = KEY_SEMICOLON, [40] = KEY_APOSTROPHE, - [41] = KEY_GRAVE, /* FIXME, '#' */ + [41] = KEY_GRAVE, [42] = KEY_LEFTSHIFT, - [43] = KEY_BACKSLASH, /* FIXME, '~' */ + [43] = KEY_BACKSLASH, [44] = KEY_Z, [45] = KEY_X, [46] = KEY_C, @@ -173,7 +173,7 @@ static const unsigned char visorkbd_keycode[KEYCODE_TABLE_BYTES] = { [88] = KEY_F12, [90] = KEY_KPLEFTPAREN, [91] = KEY_KPRIGHTPAREN, - [92] = KEY_KPASTERISK, /* FIXME */ + [92] = KEY_KPASTERISK, [93] = KEY_KPASTERISK, [94] = KEY_KPPLUS, [95] = KEY_HELP, -- GitLab From 4145ba76b1f7f3296cc673c299084145e1267029 Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Fri, 8 Apr 2016 09:21:10 -0400 Subject: [PATCH 2202/9938] staging: unisys: visornic: prevent double-unlock of priv_lock Previously, devdata->priv_lock was being unlocked in visornic_serverdown() both before calling visornic_serverdown_complete(), then again at the end of the function. This bug was corrected. The structure of visornic_serverdown() was also improved to make it easier to follow and to decrease the chance that such bugs will be introduced again. The main-path logic now falls thru down the left-side of the page, with a common error-exit point to handle error conditions. Signed-off-by: Tim Sell Signed-off-by: David Kershner Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visornic/visornic_main.c | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 763738d56c9d..0ec952ac0dac 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -356,28 +356,38 @@ visornic_serverdown(struct visornic_devdata *devdata, visorbus_state_complete_func complete_func) { unsigned long flags; + int err; spin_lock_irqsave(&devdata->priv_lock, flags); - if (!devdata->server_down && !devdata->server_change_state) { - if (devdata->going_away) { - spin_unlock_irqrestore(&devdata->priv_lock, flags); - dev_dbg(&devdata->dev->device, - "%s aborting because device removal pending\n", - __func__); - return -ENODEV; - } - devdata->server_change_state = true; - devdata->server_down_complete_func = complete_func; - spin_unlock_irqrestore(&devdata->priv_lock, flags); - visornic_serverdown_complete(devdata); - } else if (devdata->server_change_state) { + if (devdata->server_change_state) { dev_dbg(&devdata->dev->device, "%s changing state\n", __func__); - spin_unlock_irqrestore(&devdata->priv_lock, flags); - return -EINVAL; + err = -EINVAL; + goto err_unlock; + } + if (devdata->server_down) { + dev_dbg(&devdata->dev->device, "%s already down\n", + __func__); + err = -EINVAL; + goto err_unlock; } + if (devdata->going_away) { + dev_dbg(&devdata->dev->device, + "%s aborting because device removal pending\n", + __func__); + err = -ENODEV; + goto err_unlock; + } + devdata->server_change_state = true; + devdata->server_down_complete_func = complete_func; spin_unlock_irqrestore(&devdata->priv_lock, flags); + + visornic_serverdown_complete(devdata); return 0; + +err_unlock: + spin_unlock_irqrestore(&devdata->priv_lock, flags); + return err; } /** -- GitLab From fef95019016ac10e250d2c67a3c97af5797e3938 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 7 Apr 2016 16:22:36 +0200 Subject: [PATCH 2203/9938] regulator: core: Use parent voltage from the supply when bypassed When a regulator is in bypass mode it is functioning as a switch returning the voltage set in the regulator will not give the voltage being output by the regulator as it's just passing through its supply. This means that when we are getting the voltage from a regulator we should check to see if it is in bypass mode and if it is we should report the voltage from the supply rather than that which is set on the regulator. Reported-by: Jon Hunter Signed-off-by: Mark Brown [treding@nvidia.com: return early for bypass mode] Signed-off-by: Thierry Reding Signed-off-by: Mark Brown --- drivers/regulator/core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0b764284773..990fd7b3da7d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3109,6 +3109,20 @@ EXPORT_SYMBOL_GPL(regulator_sync_voltage); static int _regulator_get_voltage(struct regulator_dev *rdev) { int sel, ret; + bool bypassed; + + if (rdev->desc->ops->get_bypass) { + ret = rdev->desc->ops->get_bypass(rdev, &bypassed); + if (ret < 0) + return ret; + if (bypassed) { + /* if bypassed the regulator must have a supply */ + if (!rdev->supply) + return -EINVAL; + + return _regulator_get_voltage(rdev->supply->rdev); + } + } if (rdev->desc->ops->get_voltage_sel) { sel = rdev->desc->ops->get_voltage_sel(rdev); -- GitLab From b1a928cdb477037fb7c10fbf94c47f65f2bcce77 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Thu, 3 Mar 2016 15:53:20 +0100 Subject: [PATCH 2204/9938] PCI: Add DMA alias quirk for mic_x200_dma The MIC x200 NTB forwards DMA transactions upstream using multiple alien RIDs. These RIDs have to be added as aliases to the DMA device to allow buffer access when the IOMMU is enabled. Signed-off-by: Jacek Lawrynowicz Signed-off-by: Bjorn Helgaas Reviewed-by: Alex Williamson Acked-by: David Woodhouse --- drivers/pci/quirks.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7559e4024447..8889ac433cf1 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3724,6 +3724,21 @@ DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias); /* Intel 82801, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c49 */ DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias); +/* + * MIC x200 NTB forwards PCIe traffic using multiple alien RIDs. They have to + * be added as aliases to the DMA device in order to allow buffer access + * when IOMMU is enabled. Following devfns have to match RIT-LUT table + * programmed in the EEPROM. + */ +static void quirk_mic_x200_dma_alias(struct pci_dev *pdev) +{ + pci_add_dma_alias(pdev, PCI_DEVFN(0x10, 0x0)); + pci_add_dma_alias(pdev, PCI_DEVFN(0x11, 0x0)); + pci_add_dma_alias(pdev, PCI_DEVFN(0x12, 0x3)); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2260, quirk_mic_x200_dma_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2264, quirk_mic_x200_dma_alias); + /* * Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero) * class code. Fix it. -- GitLab From acc98009b87a811f9f815650274a1044474cd167 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 6 Apr 2016 17:39:07 +0200 Subject: [PATCH 2205/9938] ARM: imx: always use TWD on IMX6Q There is no reason to limit the TWD to be used on SMP kernels only if the hardware has it available. On Wandboard i.MX6SOLO, running PREEMPT-RT and cyclictest I see as max immediately after start in idle: UP : ~90us SMP: ~50us UP + TWD: ~20us. Based on this numbers I prefer the TWD over the slightly slower MXC timer. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Shawn Guo --- arch/arm/mach-imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 8973fae25436..dd905b9602a0 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -526,7 +526,7 @@ config SOC_IMX6Q bool "i.MX6 Quad/DualLite support" select ARM_ERRATA_764369 if SMP select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if SMP + select HAVE_ARM_TWD select PCI_DOMAINS if PCI select PINCTRL_IMX6Q select SOC_IMX6 -- GitLab From 635218c785bef355bc8266a1fdb28f38cdca365d Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Wed, 6 Jan 2016 11:45:50 +1100 Subject: [PATCH 2206/9938] powerpc: sparse: static-ify some things As sparse suggests, these should be made static. Signed-off-by: Daniel Axtens Reviewed-by: Andrew Donnellan Reviewed-by: Stewart Smith Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/eeh_event.c | 2 +- arch/powerpc/kernel/ibmebus.c | 2 +- arch/powerpc/kernel/mce.c | 2 +- arch/powerpc/kernel/rtasd.c | 2 +- arch/powerpc/kernel/vio.c | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/eeh_event.c b/arch/powerpc/kernel/eeh_event.c index 4eefb6e34dbb..82e7327e3cd0 100644 --- a/arch/powerpc/kernel/eeh_event.c +++ b/arch/powerpc/kernel/eeh_event.c @@ -36,7 +36,7 @@ static DEFINE_SPINLOCK(eeh_eventlist_lock); static struct semaphore eeh_eventlist_sem; -LIST_HEAD(eeh_eventlist); +static LIST_HEAD(eeh_eventlist); /** * eeh_event_handler - Dispatch EEH events. diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index ac86c53e2542..a89f4f7a66bd 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -408,7 +408,7 @@ static ssize_t modalias_show(struct device *dev, return len+1; } -struct device_attribute ibmebus_bus_device_attrs[] = { +static struct device_attribute ibmebus_bus_device_attrs[] = { __ATTR_RO(devspec), __ATTR_RO(name), __ATTR_RO(modalias), diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index b2eb4686bd8f..35138225af6e 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -37,7 +37,7 @@ static DEFINE_PER_CPU(int, mce_queue_count); static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue); static void machine_check_process_queued_event(struct irq_work *work); -struct irq_work mce_event_process_work = { +static struct irq_work mce_event_process_work = { .func = machine_check_process_queued_event, }; diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index aa610ce8742f..c638e2487a9c 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -442,7 +442,7 @@ static void do_event_scan(void) } static void rtas_event_scan(struct work_struct *w); -DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan); +static DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan); /* * Delay should be at least one second since some machines have problems if diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 5f8dcdaa2820..8d7358f3a273 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -87,7 +87,7 @@ struct vio_cmo_dev_entry { * @curr: bytes currently allocated * @high: high water mark for IO data usage */ -struct vio_cmo { +static struct vio_cmo { spinlock_t lock; struct delayed_work balance_q; struct list_head device_list; @@ -615,7 +615,7 @@ static u64 vio_dma_get_required_mask(struct device *dev) return dma_iommu_ops.get_required_mask(dev); } -struct dma_map_ops vio_dma_mapping_ops = { +static struct dma_map_ops vio_dma_mapping_ops = { .alloc = vio_dma_iommu_alloc_coherent, .free = vio_dma_iommu_free_coherent, .mmap = dma_direct_mmap_coherent, -- GitLab From 7f92bc5694557dee4cefa90df27feec16c7b62da Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Wed, 6 Jan 2016 11:45:51 +1100 Subject: [PATCH 2207/9938] powerpc: sparse: Include headers for __weak symbols Sometimes when sparse warns about undefined symbols, it isn't because they should have 'static' added, it's because they're overriding __weak symbols defined elsewhere, and the header has been missed. Fix a few of them by adding appropriate headers. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/process.c | 2 ++ arch/powerpc/kernel/prom.c | 1 + arch/powerpc/kernel/time.c | 1 + arch/powerpc/mm/mmap.c | 1 + 4 files changed, 5 insertions(+) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index b8500b4ac7fe..4695088e7dd2 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,7 @@ #include #endif #include +#include #include #include diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 7030b035905d..1b082c729c29 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 81b0900a39ee..3ed9a5a21d77 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index 4087705ba90f..30611f832923 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c @@ -26,6 +26,7 @@ #include #include #include +#include /* * Top of mmap area (just below the process stack). -- GitLab From c796d1d97c3035cf54d4d5a9e75abd094db80e76 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 10 Apr 2016 22:53:47 +0300 Subject: [PATCH 2208/9938] drivers: macintosh: rack-meter: limit idle ticks to total ticks Limit idle ticks to total ticks. This prevents the annoying rackmeter leds fully ON / OFF blinking state that happens on fully idling G5 Xserve systems. Signed-off-by: Aaro Koskinen Signed-off-by: Michael Ellerman --- drivers/macintosh/rack-meter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index caaec654d7ea..ba7e330640fb 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -227,6 +227,7 @@ static void rackmeter_do_timer(struct work_struct *work) total_idle_ticks = get_cpu_idle_time(cpu); idle_ticks = (unsigned int) (total_idle_ticks - rcpu->prev_idle); + idle_ticks = min(idle_ticks, total_ticks); rcpu->prev_idle = total_idle_ticks; /* We do a very dumb calculation to update the LEDs for now, -- GitLab From 4f7bef7a9f69b1c6fe44b9f249b49056288475a4 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 10 Apr 2016 22:53:48 +0300 Subject: [PATCH 2209/9938] drivers: macintosh: rack-meter: fix bogus memsets Fix bogus memsets pointed out by sparse: linux-v4.3/drivers/macintosh/rack-meter.c:157:15: warning: memset with byte count of 0 linux-v4.3/drivers/macintosh/rack-meter.c:158:15: warning: memset with byte count of 0 Probably "&" is mistyped "*"; use ARRAY_SIZE to make it more safe. Signed-off-by: Aaro Koskinen Signed-off-by: Michael Ellerman --- drivers/macintosh/rack-meter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index ba7e330640fb..465c52219639 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -154,8 +154,8 @@ static void rackmeter_do_pause(struct rackmeter *rm, int pause) DBDMA_DO_STOP(rm->dma_regs); return; } - memset(rdma->buf1, 0, SAMPLE_COUNT & sizeof(u32)); - memset(rdma->buf2, 0, SAMPLE_COUNT & sizeof(u32)); + memset(rdma->buf1, 0, ARRAY_SIZE(rdma->buf1)); + memset(rdma->buf2, 0, ARRAY_SIZE(rdma->buf2)); rm->dma_buf_v->mark = 0; -- GitLab From 1050e689a63baffdadcd33498c15d859922504c0 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 6 Nov 2015 11:00:23 +0100 Subject: [PATCH 2210/9938] cxl: Delete an unnecessary check before the function call "kfree" The kfree() function tests whether its argument is NULL and then returns immediately. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Reviewed-by: Andrew Donnellan Acked-by: Ian Munsie Signed-off-by: Michael Ellerman --- drivers/misc/cxl/context.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c index 10370f280500..80203c993b5e 100644 --- a/drivers/misc/cxl/context.c +++ b/drivers/misc/cxl/context.c @@ -290,8 +290,7 @@ static void reclaim_ctx(struct rcu_head *rcu) if (ctx->kernelapi) kfree(ctx->mapping); - if (ctx->irq_bitmap) - kfree(ctx->irq_bitmap); + kfree(ctx->irq_bitmap); /* Drop ref to the afu device taken during cxl_context_init */ cxl_afu_put(ctx->afu); -- GitLab From 4f29efc0ea61de1482a27c580575d860385cd54f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 12 Apr 2016 15:16:24 +0200 Subject: [PATCH 2211/9938] ALSA: hda - Add missing capture_hook calls for dyn-ADC PCM streams The calls for capture_hook were missing in dyn_adc_capture_pcm_prepare and cleanup callbacks. Luckily there are no users of the capture hooks with dyn-adc PCM, so far, thus this doesn't change the behavior of existing devices, but it's a fix for a future usage. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_generic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 7ca5b89f088a..dc2c13687118 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -5432,6 +5432,7 @@ static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_adc_stream_tag = stream_tag; spec->cur_adc_format = format; snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); + call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_PREPARE); return 0; } @@ -5442,6 +5443,7 @@ static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, struct hda_gen_spec *spec = codec->spec; snd_hda_codec_cleanup_stream(codec, spec->cur_adc); spec->cur_adc = 0; + call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLEANUP); return 0; } -- GitLab From fa44b7ec9bc4115513e59f31da1167166bd6346a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 12 Apr 2016 15:23:05 +0200 Subject: [PATCH 2212/9938] ALSA: hda - Update documentation Update the URLs for alsa-info.sh and hda-emu. Also drop the alsa-driver snapshot URL since it's been discontinued recently. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index e7193aac669c..d4510ebf2e8c 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -655,17 +655,6 @@ development branches in general while the development for the current and next kernels are found in for-linus and for-next branches, respectively. -If you are using the latest Linus tree, it'd be better to pull the -above GIT tree onto it. If you are using the older kernels, an easy -way to try the latest ALSA code is to build from the snapshot -tarball. There are daily tarballs and the latest snapshot tarball. -All can be built just like normal alsa-driver release packages, that -is, installed via the usual spells: configure, make and make -install(-modules). See INSTALL in the package. The snapshot tarballs -are found at: - -- ftp://ftp.suse.com/pub/people/tiwai/snapshot/ - Sending a Bug Report ~~~~~~~~~~~~~~~~~~~~ @@ -699,7 +688,12 @@ problems. alsa-info ~~~~~~~~~ The script `alsa-info.sh` is a very useful tool to gather the audio -device information. You can fetch the latest version from: +device information. It's included in alsa-utils package. The latest +version can be found on git repository: + +- git://git.alsa-project.org/alsa-utils.git + +The script can be fetched directly from the following URL, too: - http://www.alsa-project.org/alsa-info.sh @@ -836,15 +830,11 @@ can get a proc-file dump at the current state, get a list of control (mixer) elements, set/get the control element value, simulate the PCM operation, the jack plugging simulation, etc. -The package is found in: - -- ftp://ftp.suse.com/pub/people/tiwai/misc/ - -A git repository is available: +The program is found in the git repository below: - git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git -See README file in the tarball for more details about hda-emu +See README file in the repository for more details about hda-emu program. -- GitLab From 35eb8f7b1a37013d7a38466ae58c39fbd2c57faa Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 Apr 2016 17:38:44 +0300 Subject: [PATCH 2213/9938] cfg80211: Improve Connect/Associate command documentation The roaming cases for the Connect command were not fully covered and neither Connect nor Associate command uses of the prev_bssid parameter were very clear. Add details to describe how the prev_bssid argument is supposed to be used and when the driver should use association or reassociation. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 26 +++++++++++++++++++++++--- include/uapi/linux/nl80211.h | 16 +++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b39277eb251f..5ec20369ceb8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1750,7 +1750,12 @@ enum cfg80211_assoc_req_flags { * @ie_len: Length of ie buffer in octets * @use_mfp: Use management frame protection (IEEE 802.11w) in this association * @crypto: crypto settings - * @prev_bssid: previous BSSID, if not %NULL use reassociate frame + * @prev_bssid: previous BSSID, if not %NULL use reassociate frame. This is used + * to indicate a request to reassociate within the ESS instead of a request + * do the initial association with the ESS. When included, this is set to + * the BSSID of the current association, i.e., to the value that is + * included in the Current AP address field of the Reassociation Request + * frame. * @flags: See &enum cfg80211_assoc_req_flags * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask * will be used in ht_capa. Un-supported values will be ignored. @@ -1925,7 +1930,12 @@ struct cfg80211_bss_selection { * @pbss: if set, connect to a PCP instead of AP. Valid for DMG * networks. * @bss_select: criteria to be used for BSS selection. - * @prev_bssid: previous BSSID, if not %NULL use reassociate frame + * @prev_bssid: previous BSSID, if not %NULL use reassociate frame. This is used + * to indicate a request to reassociate within the ESS instead of a request + * do the initial association with the ESS. When included, this is set to + * the BSSID of the current association, i.e., to the value that is + * included in the Current AP address field of the Reassociation Request + * frame. */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -2377,7 +2387,17 @@ struct cfg80211_qos_map { * @connect: Connect to the ESS with the specified parameters. When connected, * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. * If the connection fails for some reason, call cfg80211_connect_result() - * with the status from the AP. + * with the status from the AP. The driver is allowed to roam to other + * BSSes within the ESS when the other BSS matches the connect parameters. + * When such roaming is initiated by the driver, the driver is expected to + * verify that the target matches the configured security parameters and + * to use Reassociation Request frame instead of Association Request frame. + * The connect function can also be used to request the driver to perform + * a specific roam when connected to an ESS. In that case, the prev_bssid + * parameter is set to the BSSID of the currently associated BSS as an + * indication of requesting reassociation. In both the driver-initiated and + * new connect() call initiated roaming cases, the result of roaming is + * indicated with a call to cfg80211_roamed() or cfg80211_roamed_bss(). * (invoked with the wireless_dev mutex held) * @disconnect: Disconnect from the BSS/ESS. * (invoked with the wireless_dev mutex held) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 6da52d7b48c4..b4606288ef7a 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -429,7 +429,11 @@ * @NL80211_CMD_ASSOCIATE: association request and notification; like * NL80211_CMD_AUTHENTICATE but for Association and Reassociation * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, - * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). + * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). The + * %NL80211_ATTR_PREV_BSSID attribute is used to specify whether the + * request is for the initial association to an ESS (that attribute not + * included) or for reassociation within the ESS (that attribute is + * included). * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication @@ -479,6 +483,9 @@ * set of BSSID,frequency parameters is used (i.e., either the enforcing * %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict * %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT). + * %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within + * the ESS in case the device is already associated and an association with + * a different BSS is desired. * Background scan period can optionally be * specified in %NL80211_ATTR_BG_SCAN_PERIOD, * if not specified default background scan configuration @@ -1287,8 +1294,11 @@ enum nl80211_commands { * @NL80211_ATTR_RESP_IE: (Re)association response information elements as * sent by peer, for ROAM and successful CONNECT events. * - * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE - * commands to specify using a reassociate frame + * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used in ASSOCIATE and CONNECT + * commands to specify a request to reassociate within an ESS, i.e., to use + * Reassociate Request frame (with the value of this attribute in the + * Current AP address field) instead of Association Request frame which is + * used for the initial association to an ESS. * * @NL80211_ATTR_KEY: key information in a nested attribute with * %NL80211_KEY_* sub-attributes -- GitLab From 57fbcce37be7c1d2622b56587c10ade00e96afa3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 12 Apr 2016 15:56:15 +0200 Subject: [PATCH 2214/9938] cfg80211: remove enum ieee80211_band This enum is already perfectly aliased to enum nl80211_band, and the only reason for it is that we get IEEE80211_NUM_BANDS out of it. There's no really good reason to not declare the number of bands in nl80211 though, so do that and remove the cfg80211 one. Signed-off-by: Johannes Berg --- Documentation/DocBook/80211.tmpl | 1 - drivers/net/wireless/admtek/adm8211.c | 4 +- drivers/net/wireless/ath/ar5523/ar5523.c | 4 +- drivers/net/wireless/ath/ath.h | 2 +- drivers/net/wireless/ath/ath10k/core.h | 2 +- drivers/net/wireless/ath/ath10k/htt_rx.c | 8 +- drivers/net/wireless/ath/ath10k/mac.c | 68 +++---- drivers/net/wireless/ath/ath10k/wmi.c | 8 +- drivers/net/wireless/ath/ath5k/ani.c | 2 +- drivers/net/wireless/ath/ath5k/ath5k.h | 10 +- drivers/net/wireless/ath/ath5k/attach.c | 8 +- drivers/net/wireless/ath/ath5k/base.c | 32 ++-- drivers/net/wireless/ath/ath5k/debug.c | 6 +- drivers/net/wireless/ath/ath5k/pcu.c | 6 +- drivers/net/wireless/ath/ath5k/phy.c | 30 +-- drivers/net/wireless/ath/ath5k/qcu.c | 8 +- drivers/net/wireless/ath/ath5k/reset.c | 6 +- drivers/net/wireless/ath/ath6kl/cfg80211.c | 22 +-- drivers/net/wireless/ath/ath6kl/core.h | 2 +- drivers/net/wireless/ath/ath6kl/wmi.c | 22 +-- drivers/net/wireless/ath/ath6kl/wmi.h | 2 +- drivers/net/wireless/ath/ath9k/calib.c | 6 +- drivers/net/wireless/ath/ath9k/channel.c | 8 +- drivers/net/wireless/ath/ath9k/common-init.c | 28 +-- drivers/net/wireless/ath/ath9k/common.c | 4 +- drivers/net/wireless/ath/ath9k/debug_sta.c | 6 +- drivers/net/wireless/ath/ath9k/dynack.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 12 +- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +- drivers/net/wireless/ath/ath9k/init.c | 12 +- drivers/net/wireless/ath/ath9k/main.c | 4 +- drivers/net/wireless/ath/ath9k/xmit.c | 4 +- drivers/net/wireless/ath/carl9170/mac.c | 12 +- drivers/net/wireless/ath/carl9170/main.c | 6 +- drivers/net/wireless/ath/carl9170/phy.c | 18 +- drivers/net/wireless/ath/carl9170/rx.c | 2 +- drivers/net/wireless/ath/carl9170/tx.c | 8 +- drivers/net/wireless/ath/regd.c | 16 +- drivers/net/wireless/ath/regd.h | 2 +- drivers/net/wireless/ath/wcn36xx/main.c | 12 +- drivers/net/wireless/ath/wcn36xx/smd.c | 4 +- drivers/net/wireless/ath/wcn36xx/txrx.c | 2 +- drivers/net/wireless/ath/wil6210/cfg80211.c | 4 +- drivers/net/wireless/ath/wil6210/netdev.c | 2 +- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- drivers/net/wireless/atmel/at76c50x-usb.c | 6 +- drivers/net/wireless/atmel/atmel.c | 2 +- drivers/net/wireless/broadcom/b43/b43.h | 4 +- drivers/net/wireless/broadcom/b43/main.c | 34 ++-- drivers/net/wireless/broadcom/b43/phy_ac.c | 2 +- .../net/wireless/broadcom/b43/phy_common.c | 2 +- drivers/net/wireless/broadcom/b43/phy_ht.c | 16 +- drivers/net/wireless/broadcom/b43/phy_lcn.c | 10 +- drivers/net/wireless/broadcom/b43/phy_lp.c | 30 +-- drivers/net/wireless/broadcom/b43/phy_n.c | 176 +++++++++--------- .../net/wireless/broadcom/b43/tables_lpphy.c | 14 +- .../net/wireless/broadcom/b43/tables_nphy.c | 16 +- .../wireless/broadcom/b43/tables_phy_lcn.c | 2 +- drivers/net/wireless/broadcom/b43/xmit.c | 8 +- .../net/wireless/broadcom/b43legacy/main.c | 12 +- .../net/wireless/broadcom/b43legacy/xmit.c | 2 +- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 74 ++++---- .../broadcom/brcm80211/brcmfmac/p2p.c | 8 +- .../broadcom/brcm80211/brcmsmac/channel.c | 10 +- .../broadcom/brcm80211/brcmsmac/mac80211_if.c | 16 +- .../broadcom/brcm80211/brcmsmac/main.c | 4 +- drivers/net/wireless/cisco/airo.c | 6 +- drivers/net/wireless/intel/ipw2x00/ipw2100.c | 6 +- drivers/net/wireless/intel/ipw2x00/ipw2200.c | 12 +- .../net/wireless/intel/iwlegacy/3945-mac.c | 30 +-- drivers/net/wireless/intel/iwlegacy/3945-rs.c | 22 +-- drivers/net/wireless/intel/iwlegacy/3945.c | 20 +- .../net/wireless/intel/iwlegacy/4965-mac.c | 38 ++-- drivers/net/wireless/intel/iwlegacy/4965-rs.c | 22 +-- drivers/net/wireless/intel/iwlegacy/4965.c | 6 +- drivers/net/wireless/intel/iwlegacy/4965.h | 2 +- drivers/net/wireless/intel/iwlegacy/common.c | 70 +++---- drivers/net/wireless/intel/iwlegacy/common.h | 30 +-- drivers/net/wireless/intel/iwlegacy/debug.c | 4 +- drivers/net/wireless/intel/iwlwifi/dvm/agn.h | 8 +- .../net/wireless/intel/iwlwifi/dvm/debugfs.c | 4 +- drivers/net/wireless/intel/iwlwifi/dvm/dev.h | 6 +- .../net/wireless/intel/iwlwifi/dvm/devices.c | 4 +- drivers/net/wireless/intel/iwlwifi/dvm/lib.c | 6 +- .../net/wireless/intel/iwlwifi/dvm/mac80211.c | 12 +- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 4 +- drivers/net/wireless/intel/iwlwifi/dvm/rs.c | 22 +-- drivers/net/wireless/intel/iwlwifi/dvm/rs.h | 2 +- drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/dvm/rxon.c | 10 +- drivers/net/wireless/intel/iwlwifi/dvm/scan.c | 38 ++-- drivers/net/wireless/intel/iwlwifi/dvm/sta.c | 2 +- drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-2000.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-7000.c | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-8000.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 2 +- .../net/wireless/intel/iwlwifi/iwl-config.h | 2 +- .../wireless/intel/iwlwifi/iwl-eeprom-parse.c | 38 ++-- .../wireless/intel/iwlwifi/iwl-eeprom-parse.h | 6 +- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 26 +-- drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 10 +- .../wireless/intel/iwlwifi/mvm/debugfs-vif.c | 6 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 8 +- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 16 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 +- .../net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 28 +-- drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 36 ++-- drivers/net/wireless/intel/iwlwifi/mvm/tdls.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 6 +- .../net/wireless/intel/iwlwifi/mvm/utils.c | 4 +- drivers/net/wireless/intersil/orinoco/cfg.c | 6 +- drivers/net/wireless/intersil/orinoco/hw.c | 2 +- drivers/net/wireless/intersil/orinoco/scan.c | 4 +- drivers/net/wireless/intersil/p54/eeprom.c | 32 ++-- drivers/net/wireless/intersil/p54/main.c | 4 +- drivers/net/wireless/intersil/p54/p54.h | 2 +- drivers/net/wireless/intersil/p54/txrx.c | 4 +- drivers/net/wireless/mac80211_hwsim.c | 14 +- drivers/net/wireless/marvell/libertas/cfg.c | 10 +- drivers/net/wireless/marvell/libertas/cmd.c | 4 +- .../net/wireless/marvell/libertas_tf/main.c | 4 +- .../net/wireless/marvell/mwifiex/cfg80211.c | 34 ++-- drivers/net/wireless/marvell/mwifiex/cfp.c | 12 +- drivers/net/wireless/marvell/mwifiex/scan.c | 8 +- .../net/wireless/marvell/mwifiex/uap_cmd.c | 2 +- drivers/net/wireless/marvell/mwl8k.c | 88 ++++----- drivers/net/wireless/mediatek/mt7601u/init.c | 4 +- .../net/wireless/ralink/rt2x00/rt2800lib.c | 30 +-- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 4 +- .../net/wireless/ralink/rt2x00/rt2x00dev.c | 40 ++-- drivers/net/wireless/ralink/rt2x00/rt61pci.c | 22 +-- drivers/net/wireless/ralink/rt2x00/rt73usb.c | 22 +-- .../wireless/realtek/rtl818x/rtl8180/dev.c | 8 +- .../wireless/realtek/rtl818x/rtl8187/dev.c | 4 +- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 30 +-- drivers/net/wireless/realtek/rtlwifi/base.c | 44 ++--- drivers/net/wireless/realtek/rtlwifi/regd.c | 16 +- drivers/net/wireless/realtek/rtlwifi/wifi.h | 2 +- drivers/net/wireless/rndis_wlan.c | 4 +- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 100 +++++----- drivers/net/wireless/rsi/rsi_91x_mgmt.c | 8 +- drivers/net/wireless/rsi/rsi_91x_pkt.c | 2 +- drivers/net/wireless/rsi/rsi_main.h | 2 +- drivers/net/wireless/st/cw1200/main.c | 10 +- drivers/net/wireless/st/cw1200/scan.c | 2 +- drivers/net/wireless/st/cw1200/sta.c | 6 +- drivers/net/wireless/st/cw1200/txrx.c | 2 +- drivers/net/wireless/st/cw1200/wsm.c | 4 +- drivers/net/wireless/ti/wl1251/main.c | 2 +- drivers/net/wireless/ti/wl1251/rx.c | 2 +- drivers/net/wireless/ti/wl12xx/main.c | 8 +- drivers/net/wireless/ti/wl12xx/scan.c | 20 +- drivers/net/wireless/ti/wl18xx/cmd.c | 6 +- drivers/net/wireless/ti/wl18xx/event.c | 6 +- drivers/net/wireless/ti/wl18xx/main.c | 22 +-- drivers/net/wireless/ti/wl18xx/scan.c | 8 +- drivers/net/wireless/ti/wl18xx/tx.c | 2 +- drivers/net/wireless/ti/wlcore/cmd.c | 36 ++-- drivers/net/wireless/ti/wlcore/cmd.h | 6 +- drivers/net/wireless/ti/wlcore/main.c | 32 ++-- drivers/net/wireless/ti/wlcore/ps.c | 4 +- drivers/net/wireless/ti/wlcore/rx.c | 4 +- drivers/net/wireless/ti/wlcore/rx.h | 2 +- drivers/net/wireless/ti/wlcore/scan.c | 14 +- drivers/net/wireless/ti/wlcore/tx.c | 2 +- drivers/net/wireless/ti/wlcore/tx.h | 4 +- drivers/net/wireless/ti/wlcore/wlcore.h | 4 +- drivers/net/wireless/ti/wlcore/wlcore_i.h | 2 +- drivers/net/wireless/wl3501_cs.c | 2 +- drivers/net/wireless/zydas/zd1211rw/zd_mac.c | 4 +- drivers/staging/rtl8723au/core/rtw_mlme_ext.c | 4 +- drivers/staging/rtl8723au/include/ieee80211.h | 2 +- .../staging/rtl8723au/os_dep/ioctl_cfg80211.c | 54 +++--- drivers/staging/vt6655/channel.c | 4 +- drivers/staging/vt6655/device_main.c | 4 +- drivers/staging/vt6655/rxtx.c | 2 +- drivers/staging/vt6656/channel.c | 4 +- drivers/staging/vt6656/int.c | 2 +- drivers/staging/vt6656/main_usb.c | 2 +- drivers/staging/vt6656/rxtx.c | 2 +- .../staging/wilc1000/wilc_wfi_cfgoperations.c | 10 +- drivers/staging/wlan-ng/cfg80211.c | 6 +- include/net/cfg80211.h | 44 ++--- include/net/mac80211.h | 12 +- include/uapi/linux/nl80211.h | 4 + net/mac80211/cfg.c | 14 +- net/mac80211/debugfs_netdev.c | 12 +- net/mac80211/ibss.c | 10 +- net/mac80211/ieee80211_i.h | 34 ++-- net/mac80211/iface.c | 2 +- net/mac80211/main.c | 6 +- net/mac80211/mesh.c | 10 +- net/mac80211/mesh_plink.c | 10 +- net/mac80211/mlme.c | 14 +- net/mac80211/rate.c | 2 +- net/mac80211/rc80211_minstrel.c | 6 +- net/mac80211/rc80211_minstrel_ht.c | 4 +- net/mac80211/rx.c | 6 +- net/mac80211/scan.c | 12 +- net/mac80211/spectmgmt.c | 4 +- net/mac80211/tdls.c | 18 +- net/mac80211/trace.h | 6 +- net/mac80211/tx.c | 14 +- net/mac80211/util.c | 24 +-- net/mac80211/vht.c | 4 +- net/wireless/chan.c | 2 +- net/wireless/core.c | 8 +- net/wireless/debugfs.c | 4 +- net/wireless/ibss.c | 6 +- net/wireless/mesh.c | 4 +- net/wireless/mlme.c | 2 +- net/wireless/nl80211.c | 44 ++--- net/wireless/rdev-ops.h | 2 +- net/wireless/reg.c | 30 +-- net/wireless/reg.h | 2 +- net/wireless/scan.c | 14 +- net/wireless/sme.c | 6 +- net/wireless/trace.h | 20 +- net/wireless/util.c | 40 ++-- net/wireless/wext-compat.c | 14 +- 230 files changed, 1420 insertions(+), 1437 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index f9b9ad7894f5..f2a312b35875 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -75,7 +75,6 @@ Device registration !Pinclude/net/cfg80211.h Device registration -!Finclude/net/cfg80211.h ieee80211_band !Finclude/net/cfg80211.h ieee80211_channel_flags !Finclude/net/cfg80211.h ieee80211_channel !Finclude/net/cfg80211.h ieee80211_rate_flags diff --git a/drivers/net/wireless/admtek/adm8211.c b/drivers/net/wireless/admtek/adm8211.c index 15f057ed41ad..70ecd82d674d 100644 --- a/drivers/net/wireless/admtek/adm8211.c +++ b/drivers/net/wireless/admtek/adm8211.c @@ -440,7 +440,7 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) rx_status.rate_idx = rate; rx_status.freq = adm8211_channels[priv->channel - 1].center_freq; - rx_status.band = IEEE80211_BAND_2GHZ; + rx_status.band = NL80211_BAND_2GHZ; memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); ieee80211_rx_irqsafe(dev, skb); @@ -1894,7 +1894,7 @@ static int adm8211_probe(struct pci_dev *pdev, priv->channel = 1; - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + dev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; err = ieee80211_register_hw(dev); if (err) { diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 3b343c63aa52..8aded24bcdf4 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -1471,12 +1471,12 @@ static int ar5523_init_modes(struct ar5523 *ar) memcpy(ar->channels, ar5523_channels, sizeof(ar5523_channels)); memcpy(ar->rates, ar5523_rates, sizeof(ar5523_rates)); - ar->band.band = IEEE80211_BAND_2GHZ; + ar->band.band = NL80211_BAND_2GHZ; ar->band.channels = ar->channels; ar->band.n_channels = ARRAY_SIZE(ar5523_channels); ar->band.bitrates = ar->rates; ar->band.n_bitrates = ARRAY_SIZE(ar5523_rates); - ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar->band; + ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = &ar->band; return 0; } diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 65ef483ebf50..da7a7c8dafb2 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -185,7 +185,7 @@ struct ath_common { bool bt_ant_diversity; int last_rssi; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band sbands[NUM_NL80211_BANDS]; }; static inline const struct ath_ps_ops *ath_ps_ops(struct ath_common *common) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d85b99164212..362bbed8f0e9 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -765,7 +765,7 @@ struct ath10k { } scan; struct { - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band sbands[NUM_NL80211_BANDS]; } mac; /* should never be NULL; needed for regular htt rx */ diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 9390897a00c6..079fef5b7ef2 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2182,9 +2182,9 @@ static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar, ath10k_mac_tx_push_pending(ar); } -static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) +static inline enum nl80211_band phy_mode_to_band(u32 phy_mode) { - enum ieee80211_band band; + enum nl80211_band band; switch (phy_mode) { case MODE_11A: @@ -2193,7 +2193,7 @@ static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) case MODE_11AC_VHT20: case MODE_11AC_VHT40: case MODE_11AC_VHT80: - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; break; case MODE_11G: case MODE_11B: @@ -2204,7 +2204,7 @@ static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) case MODE_11AC_VHT40_2G: case MODE_11AC_VHT80_2G: default: - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; } return band; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b0e613bc10a5..6ace10bc96f5 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -482,7 +482,7 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) enum wmi_phy_mode phymode = MODE_UNKNOWN; switch (chandef->chan->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: switch (chandef->width) { case NL80211_CHAN_WIDTH_20_NOHT: if (chandef->chan->flags & IEEE80211_CHAN_NO_OFDM) @@ -505,7 +505,7 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) break; } break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: switch (chandef->width) { case NL80211_CHAN_WIDTH_20_NOHT: phymode = MODE_11A; @@ -2055,7 +2055,7 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar, struct cfg80211_chan_def def; const struct ieee80211_supported_band *sband; const struct ieee80211_rate *rates; - enum ieee80211_band band; + enum nl80211_band band; u32 ratemask; u8 rate; int i; @@ -2115,7 +2115,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct cfg80211_chan_def def; - enum ieee80211_band band; + enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; int i, n; @@ -2339,7 +2339,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct cfg80211_chan_def def; - enum ieee80211_band band; + enum nl80211_band band; const u16 *vht_mcs_mask; u8 ampdu_factor; @@ -2357,7 +2357,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, arg->peer_flags |= ar->wmi.peer_flags->vht; - if (def.chan->band == IEEE80211_BAND_2GHZ) + if (def.chan->band == NL80211_BAND_2GHZ) arg->peer_flags |= ar->wmi.peer_flags->vht_2g; arg->peer_vht_caps = vht_cap->cap; @@ -2426,7 +2426,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta) { - return sta->supp_rates[IEEE80211_BAND_2GHZ] >> + return sta->supp_rates[NL80211_BAND_2GHZ] >> ATH10K_MAC_FIRST_OFDM_RATE_IDX; } @@ -2437,7 +2437,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, { struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct cfg80211_chan_def def; - enum ieee80211_band band; + enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; enum wmi_phy_mode phymode = MODE_UNKNOWN; @@ -2450,7 +2450,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs; switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: if (sta->vht_cap.vht_supported && !ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) { if (sta->bandwidth == IEEE80211_STA_RX_BW_40) @@ -2470,7 +2470,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, } break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: /* * Check VHT first. */ @@ -2848,7 +2848,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) { struct ieee80211_hw *hw = ar->hw; struct ieee80211_supported_band **bands; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_channel *channel; struct wmi_scan_chan_list_arg arg = {0}; struct wmi_channel_arg *ch; @@ -2860,7 +2860,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) lockdep_assert_held(&ar->conf_mutex); bands = hw->wiphy->bands; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!bands[band]) continue; @@ -2879,7 +2879,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) return -ENOMEM; ch = arg.channels; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!bands[band]) continue; @@ -2917,7 +2917,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) /* FIXME: why use only legacy modes, why not any * HT/VHT modes? Would that even make any * difference? */ - if (channel->band == IEEE80211_BAND_2GHZ) + if (channel->band == NL80211_BAND_2GHZ) ch->mode = MODE_11G; else ch->mode = MODE_11A; @@ -4254,14 +4254,14 @@ static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar) vht_cap = ath10k_create_vht_cap(ar); if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { - band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + band = &ar->mac.sbands[NL80211_BAND_2GHZ]; band->ht_cap = ht_cap; /* Enable the VHT support at 2.4 GHz */ band->vht_cap = vht_cap; } if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { - band = &ar->mac.sbands[IEEE80211_BAND_5GHZ]; + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; band->ht_cap = ht_cap; band->vht_cap = vht_cap; } @@ -5595,7 +5595,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) struct ath10k_sta *arsta; struct ieee80211_sta *sta; struct cfg80211_chan_def def; - enum ieee80211_band band; + enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; u32 changed, bw, nss, smps; @@ -6394,14 +6394,14 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx, mutex_lock(&ar->conf_mutex); - sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = hw->wiphy->bands[NL80211_BAND_2GHZ]; if (sband && idx >= sband->n_channels) { idx -= sband->n_channels; sband = NULL; } if (!sband) - sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = hw->wiphy->bands[NL80211_BAND_5GHZ]; if (!sband || idx >= sband->n_channels) { ret = -ENOENT; @@ -6424,7 +6424,7 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx, static bool ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar, - enum ieee80211_band band, + enum nl80211_band band, const struct cfg80211_bitrate_mask *mask) { int num_rates = 0; @@ -6443,7 +6443,7 @@ ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar, static bool ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar, - enum ieee80211_band band, + enum nl80211_band band, const struct cfg80211_bitrate_mask *mask, int *nss) { @@ -6492,7 +6492,7 @@ ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar, static int ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, - enum ieee80211_band band, + enum nl80211_band band, const struct cfg80211_bitrate_mask *mask, u8 *rate, u8 *nss) { @@ -6593,7 +6593,7 @@ static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif, static bool ath10k_mac_can_set_bitrate_mask(struct ath10k *ar, - enum ieee80211_band band, + enum nl80211_band band, const struct cfg80211_bitrate_mask *mask) { int i; @@ -6645,7 +6645,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct cfg80211_chan_def def; struct ath10k *ar = arvif->ar; - enum ieee80211_band band; + enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; u8 rate; @@ -7275,7 +7275,7 @@ static const struct ieee80211_ops ath10k_ops = { }; #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .hw_value = (_channel), \ .center_freq = (_freq), \ .flags = (_flags), \ @@ -7284,7 +7284,7 @@ static const struct ieee80211_ops ath10k_ops = { } #define CHAN5G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .hw_value = (_channel), \ .center_freq = (_freq), \ .flags = (_flags), \ @@ -7604,13 +7604,13 @@ int ath10k_mac_register(struct ath10k *ar) goto err_free; } - band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + band = &ar->mac.sbands[NL80211_BAND_2GHZ]; band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels); band->channels = channels; band->n_bitrates = ath10k_g_rates_size; band->bitrates = ath10k_g_rates; - ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; + ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; } if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { @@ -7622,12 +7622,12 @@ int ath10k_mac_register(struct ath10k *ar) goto err_free; } - band = &ar->mac.sbands[IEEE80211_BAND_5GHZ]; + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; band->n_channels = ARRAY_SIZE(ath10k_5ghz_channels); band->channels = channels; band->n_bitrates = ath10k_a_rates_size; band->bitrates = ath10k_a_rates; - ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; + ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; } ath10k_mac_setup_ht_vht_cap(ar); @@ -7815,8 +7815,8 @@ int ath10k_mac_register(struct ath10k *ar) ar->dfs_detector->exit(ar->dfs_detector); err_free: - kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels); - kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels); + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); + kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels); SET_IEEE80211_DEV(ar->hw, NULL); return ret; @@ -7829,8 +7829,8 @@ void ath10k_mac_unregister(struct ath10k *ar) if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) ar->dfs_detector->exit(ar->dfs_detector); - kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels); - kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels); + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); + kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels); SET_IEEE80211_DEV(ar->hw, NULL); } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index f7ec65f263a0..4c75c74be5e7 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2281,9 +2281,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) * of mgmt rx. */ if (channel >= 1 && channel <= 14) { - status->band = IEEE80211_BAND_2GHZ; + status->band = NL80211_BAND_2GHZ; } else if (channel >= 36 && channel <= 165) { - status->band = IEEE80211_BAND_5GHZ; + status->band = NL80211_BAND_5GHZ; } else { /* Shouldn't happen unless list of advertised channels to * mac80211 has been changed. @@ -2293,7 +2293,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) return 0; } - if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ) + if (phy_mode == MODE_11B && status->band == NL80211_BAND_5GHZ) ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); sband = &ar->mac.sbands[status->band]; @@ -2352,7 +2352,7 @@ static int freq_to_idx(struct ath10k *ar, int freq) struct ieee80211_supported_band *sband; int band, ch, idx = 0; - for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { + for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { sband = ar->hw->wiphy->bands[band]; if (!sband) continue; diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 38be2702c0e2..0624333f5430 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -279,7 +279,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); return; - } else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) { + } else if (ah->ah_current_channel->band == NL80211_BAND_2GHZ) { /* beacon RSSI is low. in B/G mode turn of OFDM weak signal * detect and zero firstep level to maximize CCK sensitivity */ ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ba12f7f4061d..67fedb61fcc0 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1265,10 +1265,10 @@ struct ath5k_hw { void __iomem *iobase; /* address of the device */ struct mutex lock; /* dev-level lock */ struct ieee80211_hw *hw; /* IEEE 802.11 common */ - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band sbands[NUM_NL80211_BANDS]; struct ieee80211_channel channels[ATH_CHAN_MAX]; - struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; + struct ieee80211_rate rates[NUM_NL80211_BANDS][AR5K_MAX_RATES]; + s8 rate_idx[NUM_NL80211_BANDS][AR5K_MAX_RATES]; enum nl80211_iftype opmode; #ifdef CONFIG_ATH5K_DEBUG @@ -1532,7 +1532,7 @@ int ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, /* Protocol Control Unit Functions */ /* Helpers */ -int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, enum ieee80211_band band, +int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, enum nl80211_band band, int len, struct ieee80211_rate *rate, bool shortpre); unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); @@ -1611,7 +1611,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); /* PHY functions */ /* Misc PHY functions */ -u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band); +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum nl80211_band band); int ath5k_hw_phy_disable(struct ath5k_hw *ah); /* Gain_F optimization */ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 66b6366158b9..233054bd6b52 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -152,7 +152,7 @@ int ath5k_hw_init(struct ath5k_hw *ah) ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & 0xffffffff; ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); /* Try to identify radio chip based on its srev */ switch (ah->ah_radio_5ghz_revision & 0xf0) { @@ -160,14 +160,14 @@ int ath5k_hw_init(struct ath5k_hw *ah) ah->ah_radio = AR5K_RF5111; ah->ah_single_chip = false; ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); break; case AR5K_SREV_RAD_5112: case AR5K_SREV_RAD_2112: ah->ah_radio = AR5K_RF5112; ah->ah_single_chip = false; ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); break; case AR5K_SREV_RAD_2413: ah->ah_radio = AR5K_RF2413; @@ -204,7 +204,7 @@ int ath5k_hw_init(struct ath5k_hw *ah) ah->ah_radio = AR5K_RF5111; ah->ah_single_chip = false; ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || ah->ah_phy_revision == AR5K_SREV_PHY_2425) { diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3d946d8b2db2..d98fd421c7ec 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -268,15 +268,15 @@ static void ath5k_reg_notifier(struct wiphy *wiphy, * Returns true for the channel numbers used. */ #ifdef CONFIG_ATH5K_TEST_CHANNELS -static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) +static bool ath5k_is_standard_channel(short chan, enum nl80211_band band) { return true; } #else -static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) +static bool ath5k_is_standard_channel(short chan, enum nl80211_band band) { - if (band == IEEE80211_BAND_2GHZ && chan <= 14) + if (band == NL80211_BAND_2GHZ && chan <= 14) return true; return /* UNII 1,2 */ @@ -297,18 +297,18 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, unsigned int mode, unsigned int max) { unsigned int count, size, freq, ch; - enum ieee80211_band band; + enum nl80211_band band; switch (mode) { case AR5K_MODE_11A: /* 1..220, but 2GHz frequencies are filtered by check_channel */ size = 220; - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; break; case AR5K_MODE_11B: case AR5K_MODE_11G: size = 26; - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; break; default: ATH5K_WARN(ah, "bad mode, not copying channels\n"); @@ -363,13 +363,13 @@ ath5k_setup_bands(struct ieee80211_hw *hw) int max_c, count_c = 0; int i; - BUILD_BUG_ON(ARRAY_SIZE(ah->sbands) < IEEE80211_NUM_BANDS); + BUILD_BUG_ON(ARRAY_SIZE(ah->sbands) < NUM_NL80211_BANDS); max_c = ARRAY_SIZE(ah->channels); /* 2GHz band */ - sband = &ah->sbands[IEEE80211_BAND_2GHZ]; - sband->band = IEEE80211_BAND_2GHZ; - sband->bitrates = &ah->rates[IEEE80211_BAND_2GHZ][0]; + sband = &ah->sbands[NL80211_BAND_2GHZ]; + sband->band = NL80211_BAND_2GHZ; + sband->bitrates = &ah->rates[NL80211_BAND_2GHZ][0]; if (test_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode)) { /* G mode */ @@ -381,7 +381,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) sband->n_channels = ath5k_setup_channels(ah, sband->channels, AR5K_MODE_11G, max_c); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; count_c = sband->n_channels; max_c -= count_c; } else if (test_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode)) { @@ -407,7 +407,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) sband->n_channels = ath5k_setup_channels(ah, sband->channels, AR5K_MODE_11B, max_c); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; count_c = sband->n_channels; max_c -= count_c; } @@ -415,9 +415,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw) /* 5GHz band, A mode */ if (test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) { - sband = &ah->sbands[IEEE80211_BAND_5GHZ]; - sband->band = IEEE80211_BAND_5GHZ; - sband->bitrates = &ah->rates[IEEE80211_BAND_5GHZ][0]; + sband = &ah->sbands[NL80211_BAND_5GHZ]; + sband->band = NL80211_BAND_5GHZ; + sband->bitrates = &ah->rates[NL80211_BAND_5GHZ][0]; memcpy(sband->bitrates, &ath5k_rates[4], sizeof(struct ieee80211_rate) * 8); @@ -427,7 +427,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) sband->n_channels = ath5k_setup_channels(ah, sband->channels, AR5K_MODE_11A, max_c); - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; } ath5k_setup_rate_idx(ah, sband); diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 654a1e33f827..929d7ccc031c 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -1043,14 +1043,14 @@ ath5k_debug_dump_bands(struct ath5k_hw *ah) BUG_ON(!ah->sbands); - for (b = 0; b < IEEE80211_NUM_BANDS; b++) { + for (b = 0; b < NUM_NL80211_BANDS; b++) { struct ieee80211_supported_band *band = &ah->sbands[b]; char bname[6]; switch (band->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: strcpy(bname, "2 GHz"); break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: strcpy(bname, "5 GHz"); break; default: diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index bf29da5e90da..fc47b70988b1 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -110,7 +110,7 @@ static const unsigned int ack_rates_high[] = * bwmodes. */ int -ath5k_hw_get_frame_duration(struct ath5k_hw *ah, enum ieee80211_band band, +ath5k_hw_get_frame_duration(struct ath5k_hw *ah, enum nl80211_band band, int len, struct ieee80211_rate *rate, bool shortpre) { int sifs, preamble, plcp_bits, sym_time; @@ -221,7 +221,7 @@ ath5k_hw_get_default_sifs(struct ath5k_hw *ah) case AR5K_BWMODE_DEFAULT: sifs = AR5K_INIT_SIFS_DEFAULT_BG; default: - if (channel->band == IEEE80211_BAND_5GHZ) + if (channel->band == NL80211_BAND_5GHZ) sifs = AR5K_INIT_SIFS_DEFAULT_A; break; } @@ -279,7 +279,7 @@ ath5k_hw_write_rate_duration(struct ath5k_hw *ah) struct ieee80211_rate *rate; unsigned int i; /* 802.11g covers both OFDM and CCK */ - u8 band = IEEE80211_BAND_2GHZ; + u8 band = NL80211_BAND_2GHZ; /* Write rate duration table */ for (i = 0; i < ah->sbands[band].n_bitrates; i++) { diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 98ee85456321..641b13a279e1 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -75,13 +75,13 @@ /** * ath5k_hw_radio_revision() - Get the PHY Chip revision * @ah: The &struct ath5k_hw - * @band: One of enum ieee80211_band + * @band: One of enum nl80211_band * * Returns the revision number of a 2GHz, 5GHz or single chip * radio. */ u16 -ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) +ath5k_hw_radio_revision(struct ath5k_hw *ah, enum nl80211_band band) { unsigned int i; u32 srev; @@ -91,10 +91,10 @@ ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) * Set the radio chip access register */ switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); break; default: @@ -138,11 +138,11 @@ ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel) u16 freq = channel->center_freq; /* Check if the channel is in our supported range */ - if (channel->band == IEEE80211_BAND_2GHZ) { + if (channel->band == NL80211_BAND_2GHZ) { if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) return true; - } else if (channel->band == IEEE80211_BAND_5GHZ) + } else if (channel->band == NL80211_BAND_5GHZ) if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) return true; @@ -743,7 +743,7 @@ ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) /** * ath5k_hw_rfgain_init() - Write initial RF gain settings to hw * @ah: The &struct ath5k_hw - * @band: One of enum ieee80211_band + * @band: One of enum nl80211_band * * Write initial RF gain table to set the RF sensitivity. * @@ -751,7 +751,7 @@ ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) * with Gain_F calibration */ static int -ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) +ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum nl80211_band band) { const struct ath5k_ini_rfgain *ath5k_rfg; unsigned int i, size, index; @@ -786,7 +786,7 @@ ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) return -EINVAL; } - index = (band == IEEE80211_BAND_2GHZ) ? 1 : 0; + index = (band == NL80211_BAND_2GHZ) ? 1 : 0; for (i = 0; i < size; i++) { AR5K_REG_WAIT(i); @@ -917,7 +917,7 @@ ath5k_hw_rfregs_init(struct ath5k_hw *ah, } /* Set Output and Driver bias current (OB/DB) */ - if (channel->band == IEEE80211_BAND_2GHZ) { + if (channel->band == NL80211_BAND_2GHZ) { if (channel->hw_value == AR5K_MODE_11B) ee_mode = AR5K_EEPROM_MODE_11B; @@ -944,7 +944,7 @@ ath5k_hw_rfregs_init(struct ath5k_hw *ah, AR5K_RF_DB_2GHZ, true); /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */ - } else if ((channel->band == IEEE80211_BAND_5GHZ) || + } else if ((channel->band == NL80211_BAND_5GHZ) || (ah->ah_radio == AR5K_RF5111)) { /* For 11a, Turbo and XR we need to choose @@ -1145,7 +1145,7 @@ ath5k_hw_rfregs_init(struct ath5k_hw *ah, } if (ah->ah_radio == AR5K_RF5413 && - channel->band == IEEE80211_BAND_2GHZ) { + channel->band == NL80211_BAND_2GHZ) { ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE, true); @@ -1270,7 +1270,7 @@ ath5k_hw_rf5111_channel(struct ath5k_hw *ah, */ data0 = data1 = 0; - if (channel->band == IEEE80211_BAND_2GHZ) { + if (channel->band == NL80211_BAND_2GHZ) { /* Map 2GHz channel to 5GHz Atheros channel ID */ ret = ath5k_hw_rf5111_chan2athchan( ieee80211_frequency_to_channel(channel->center_freq), @@ -1919,7 +1919,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, /* Convert current frequency to fbin value (the same way channels * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale * up by 2 so we can compare it later */ - if (channel->band == IEEE80211_BAND_2GHZ) { + if (channel->band == NL80211_BAND_2GHZ) { chan_fbin = (channel->center_freq - 2300) * 10; freq_band = AR5K_EEPROM_BAND_2GHZ; } else { @@ -1983,7 +1983,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; break; default: - if (channel->band == IEEE80211_BAND_5GHZ) { + if (channel->band == NL80211_BAND_5GHZ) { /* Both sample_freq and chip_freq are 40MHz */ spur_delta_phase = (spur_offset << 17) / 25; spur_freq_sigma_delta = diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index ddaad712c59a..beda11ce34a7 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -559,7 +559,7 @@ ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) { struct ieee80211_channel *channel = ah->ah_current_channel; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; struct ieee80211_rate *rate; u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; @@ -596,10 +596,10 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) * * Also we have different lowest rate for 802.11a */ - if (channel->band == IEEE80211_BAND_5GHZ) - band = IEEE80211_BAND_5GHZ; + if (channel->band == NL80211_BAND_5GHZ) + band = NL80211_BAND_5GHZ; else - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; switch (ah->ah_bwmode) { case AR5K_BWMODE_5MHZ: diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 4b1c87fa15ac..56d7925a0c2c 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -752,7 +752,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) clock = AR5K_PHY_PLL_RF5111; /*Zero*/ } - if (channel->band == IEEE80211_BAND_2GHZ) { + if (channel->band == NL80211_BAND_2GHZ) { mode |= AR5K_PHY_MODE_FREQ_2GHZ; clock |= AR5K_PHY_PLL_44MHZ; @@ -771,7 +771,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) else mode |= AR5K_PHY_MODE_MOD_DYN; } - } else if (channel->band == IEEE80211_BAND_5GHZ) { + } else if (channel->band == NL80211_BAND_5GHZ) { mode |= (AR5K_PHY_MODE_FREQ_5GHZ | AR5K_PHY_MODE_MOD_OFDM); @@ -906,7 +906,7 @@ ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, u32 data; ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, AR5K_PHY_CCKTXCTL); - if (channel->band == IEEE80211_BAND_5GHZ) + if (channel->band == NL80211_BAND_5GHZ) data = 0xffb81020; else data = 0xffb80d20; diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7f3f94fbf157..4e11ba06f089 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -34,7 +34,7 @@ } #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .hw_value = (_channel), \ .center_freq = (_freq), \ .flags = (_flags), \ @@ -43,7 +43,7 @@ } #define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .hw_value = (_channel), \ .center_freq = 5000 + (5 * (_channel)), \ .flags = (_flags), \ @@ -2583,7 +2583,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar) } #endif -static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, +static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum nl80211_band band, bool ht_enable) { struct ath6kl_htcap *htcap = &vif->htcap[band]; @@ -2594,7 +2594,7 @@ static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, if (ht_enable) { /* Set default ht capabilities */ htcap->ht_enable = true; - htcap->cap_info = (band == IEEE80211_BAND_2GHZ) ? + htcap->cap_info = (band == NL80211_BAND_2GHZ) ? ath6kl_g_htcap : ath6kl_a_htcap; htcap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K; } else /* Disable ht */ @@ -2609,7 +2609,7 @@ static int ath6kl_restore_htcap(struct ath6kl_vif *vif) struct wiphy *wiphy = vif->ar->wiphy; int band, ret = 0; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!wiphy->bands[band]) continue; @@ -3530,7 +3530,7 @@ static void ath6kl_cfg80211_reg_notify(struct wiphy *wiphy, struct regulatory_request *request) { struct ath6kl *ar = wiphy_priv(wiphy); - u32 rates[IEEE80211_NUM_BANDS]; + u32 rates[NUM_NL80211_BANDS]; int ret, i; ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, @@ -3555,7 +3555,7 @@ static void ath6kl_cfg80211_reg_notify(struct wiphy *wiphy, * changed. */ - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < NUM_NL80211_BANDS; i++) if (wiphy->bands[i]) rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; @@ -3791,8 +3791,8 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; vif->bg_scan_period = 0; - vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true; - vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true; + vif->htcap[NL80211_BAND_2GHZ].ht_enable = true; + vif->htcap[NL80211_BAND_5GHZ].ht_enable = true; memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); if (fw_vif_idx != 0) { @@ -3943,9 +3943,9 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) wiphy->available_antennas_rx = ar->hw.rx_ant; if (band_2gig) - wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; + wiphy->bands[NL80211_BAND_2GHZ] = &ath6kl_band_2ghz; if (band_5gig) - wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; + wiphy->bands[NL80211_BAND_5GHZ] = &ath6kl_band_5ghz; wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 5f3acfe6015e..713a571a27ce 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -623,7 +623,7 @@ struct ath6kl_vif { struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; struct aggr_info *aggr_cntxt; - struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS]; + struct ath6kl_htcap htcap[NUM_NL80211_BANDS]; struct timer_list disconnect_timer; struct timer_list sched_scan_timer; diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 0b3e9c0293e0..631c3a0c572b 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2048,7 +2048,7 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, sc->no_cck = cpu_to_le32(no_cck); sc->num_ch = num_chan; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { sband = ar->wiphy->bands[band]; if (!sband) @@ -2770,10 +2770,10 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx, memset(&ratemask, 0, sizeof(ratemask)); /* only check 2.4 and 5 GHz bands, skip the rest */ - for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) { + for (band = 0; band <= NL80211_BAND_5GHZ; band++) { /* copy legacy rate mask */ ratemask[band] = mask->control[band].legacy; - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) ratemask[band] = mask->control[band].legacy << 4; @@ -2799,9 +2799,9 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx, if (mode == WMI_RATES_MODE_11A || mode == WMI_RATES_MODE_11A_HT20 || mode == WMI_RATES_MODE_11A_HT40) - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; else - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; cmd->ratemask[mode] = cpu_to_le64(ratemask[band]); } @@ -2822,10 +2822,10 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx, memset(&ratemask, 0, sizeof(ratemask)); /* only check 2.4 and 5 GHz bands, skip the rest */ - for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) { + for (band = 0; band <= NL80211_BAND_5GHZ; band++) { /* copy legacy rate mask */ ratemask[band] = mask->control[band].legacy; - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) ratemask[band] = mask->control[band].legacy << 4; @@ -2849,9 +2849,9 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx, if (mode == WMI_RATES_MODE_11A || mode == WMI_RATES_MODE_11A_HT20 || mode == WMI_RATES_MODE_11A_HT40) - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; else - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; cmd->ratemask[mode] = cpu_to_le32(ratemask[band]); } @@ -3174,7 +3174,7 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, } int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, - enum ieee80211_band band, + enum nl80211_band band, struct ath6kl_htcap *htcap) { struct sk_buff *skb; @@ -3187,7 +3187,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, cmd = (struct wmi_set_htcap_cmd *) skb->data; /* - * NOTE: Band in firmware matches enum ieee80211_band, it is unlikely + * NOTE: Band in firmware matches enum nl80211_band, it is unlikely * this will be changed in firmware. If at all there is any change in * band value, the host needs to be fixed. */ diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 05d25a94c781..3af464a73b58 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -2628,7 +2628,7 @@ int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg); int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, u8 keep_alive_intvl); int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, - enum ieee80211_band band, + enum nl80211_band band, struct ath6kl_htcap *htcap); int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 37f6d66d1671..0f71146b781d 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -145,14 +145,14 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, } static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, - enum ieee80211_band band, + enum nl80211_band band, int16_t *nft) { switch (band) { - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5); break; - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2); break; default: diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 319cb5f25f58..e56bafcf5864 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -107,9 +107,9 @@ void ath_chanctx_init(struct ath_softc *sc) struct ieee80211_channel *chan; int i, j; - sband = &common->sbands[IEEE80211_BAND_2GHZ]; + sband = &common->sbands[NL80211_BAND_2GHZ]; if (!sband->n_channels) - sband = &common->sbands[IEEE80211_BAND_5GHZ]; + sband = &common->sbands[NL80211_BAND_5GHZ]; chan = &sband->channels[0]; for (i = 0; i < ATH9K_NUM_CHANCTX; i++) { @@ -1333,9 +1333,9 @@ void ath9k_offchannel_init(struct ath_softc *sc) struct ieee80211_channel *chan; int i; - sband = &common->sbands[IEEE80211_BAND_2GHZ]; + sband = &common->sbands[NL80211_BAND_2GHZ]; if (!sband->n_channels) - sband = &common->sbands[IEEE80211_BAND_5GHZ]; + sband = &common->sbands[NL80211_BAND_5GHZ]; chan = &sband->channels[0]; diff --git a/drivers/net/wireless/ath/ath9k/common-init.c b/drivers/net/wireless/ath/ath9k/common-init.c index a006c1499728..8b4f7fdabf58 100644 --- a/drivers/net/wireless/ath/ath9k/common-init.c +++ b/drivers/net/wireless/ath/ath9k/common-init.c @@ -19,14 +19,14 @@ #include "common.h" #define CHAN2G(_freq, _idx) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_idx), \ .max_power = 20, \ } #define CHAN5G(_freq, _idx) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = (_freq), \ .hw_value = (_idx), \ .max_power = 20, \ @@ -139,12 +139,12 @@ int ath9k_cmn_init_channels_rates(struct ath_common *common) memcpy(channels, ath9k_2ghz_chantable, sizeof(ath9k_2ghz_chantable)); - common->sbands[IEEE80211_BAND_2GHZ].channels = channels; - common->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - common->sbands[IEEE80211_BAND_2GHZ].n_channels = + common->sbands[NL80211_BAND_2GHZ].channels = channels; + common->sbands[NL80211_BAND_2GHZ].band = NL80211_BAND_2GHZ; + common->sbands[NL80211_BAND_2GHZ].n_channels = ARRAY_SIZE(ath9k_2ghz_chantable); - common->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; - common->sbands[IEEE80211_BAND_2GHZ].n_bitrates = + common->sbands[NL80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; + common->sbands[NL80211_BAND_2GHZ].n_bitrates = ARRAY_SIZE(ath9k_legacy_rates); } @@ -156,13 +156,13 @@ int ath9k_cmn_init_channels_rates(struct ath_common *common) memcpy(channels, ath9k_5ghz_chantable, sizeof(ath9k_5ghz_chantable)); - common->sbands[IEEE80211_BAND_5GHZ].channels = channels; - common->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; - common->sbands[IEEE80211_BAND_5GHZ].n_channels = + common->sbands[NL80211_BAND_5GHZ].channels = channels; + common->sbands[NL80211_BAND_5GHZ].band = NL80211_BAND_5GHZ; + common->sbands[NL80211_BAND_5GHZ].n_channels = ARRAY_SIZE(ath9k_5ghz_chantable); - common->sbands[IEEE80211_BAND_5GHZ].bitrates = + common->sbands[NL80211_BAND_5GHZ].bitrates = ath9k_legacy_rates + 4; - common->sbands[IEEE80211_BAND_5GHZ].n_bitrates = + common->sbands[NL80211_BAND_5GHZ].n_bitrates = ARRAY_SIZE(ath9k_legacy_rates) - 4; } return 0; @@ -236,9 +236,9 @@ void ath9k_cmn_reload_chainmask(struct ath_hw *ah) if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) ath9k_cmn_setup_ht_cap(ah, - &common->sbands[IEEE80211_BAND_2GHZ].ht_cap); + &common->sbands[NL80211_BAND_2GHZ].ht_cap); if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ath9k_cmn_setup_ht_cap(ah, - &common->sbands[IEEE80211_BAND_5GHZ].ht_cap); + &common->sbands[NL80211_BAND_5GHZ].ht_cap); } EXPORT_SYMBOL(ath9k_cmn_reload_chainmask); diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index e8c699446470..b80e08b13b74 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -173,7 +173,7 @@ int ath9k_cmn_process_rate(struct ath_common *common, struct ieee80211_rx_status *rxs) { struct ieee80211_supported_band *sband; - enum ieee80211_band band; + enum nl80211_band band; unsigned int i = 0; struct ath_hw *ah = common->ah; @@ -305,7 +305,7 @@ static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, ichan->channel = chan->center_freq; ichan->chan = chan; - if (chan->band == IEEE80211_BAND_5GHZ) + if (chan->band == NL80211_BAND_5GHZ) flags |= CHANNEL_5GHZ; switch (chandef->width) { diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index c2ca57a2ed09..b66cfa91364f 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -139,7 +139,7 @@ void ath_debug_rate_stats(struct ath_softc *sc, } if (IS_OFDM_RATE(rs->rs_rate)) { - if (ah->curchan->chan->band == IEEE80211_BAND_2GHZ) + if (ah->curchan->chan->band == NL80211_BAND_2GHZ) rstats->ofdm_stats[rxs->rate_idx - 4].ofdm_cnt++; else rstats->ofdm_stats[rxs->rate_idx].ofdm_cnt++; @@ -173,7 +173,7 @@ static ssize_t read_file_node_recv(struct file *file, char __user *user_buf, struct ath_hw *ah = sc->sc_ah; struct ath_rx_rate_stats *rstats; struct ieee80211_sta *sta = an->sta; - enum ieee80211_band band; + enum nl80211_band band; u32 len = 0, size = 4096; char *buf; size_t retval; @@ -206,7 +206,7 @@ static ssize_t read_file_node_recv(struct file *file, char __user *user_buf, len += scnprintf(buf + len, size - len, "\n"); legacy: - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { PRINT_CCK_RATE("CCK-1M/LP", 0, false); PRINT_CCK_RATE("CCK-2M/LP", 1, false); PRINT_CCK_RATE("CCK-5.5M/LP", 2, false); diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c index 22b3cc4c27cd..d2ff0fc0484c 100644 --- a/drivers/net/wireless/ath/ath9k/dynack.c +++ b/drivers/net/wireless/ath/ath9k/dynack.c @@ -212,7 +212,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb, struct ieee80211_tx_rate *rates = info->status.rates; rate = &common->sbands[info->band].bitrates[rates[ridx].idx]; - if (info->band == IEEE80211_BAND_2GHZ && + if (info->band == NL80211_BAND_2GHZ && !(rate->flags & IEEE80211_RATE_ERP_G)) phy = WLAN_RC_PHY_CCK; else diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index c2249ad54085..c148c6c504f7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -765,11 +765,11 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, sizeof(struct htc_frame_hdr) + 4; if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &common->sbands[IEEE80211_BAND_2GHZ]; + hw->wiphy->bands[NL80211_BAND_2GHZ] = + &common->sbands[NL80211_BAND_2GHZ]; if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &common->sbands[IEEE80211_BAND_5GHZ]; + hw->wiphy->bands[NL80211_BAND_5GHZ] = + &common->sbands[NL80211_BAND_5GHZ]; ath9k_cmn_reload_chainmask(ah); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 639294a9e34d..8a8d7853da15 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1770,8 +1770,8 @@ static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); tmask.vif_index = avp->index; - tmask.band = IEEE80211_BAND_2GHZ; - tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy); + tmask.band = NL80211_BAND_2GHZ; + tmask.mask = cpu_to_be32(mask->control[NL80211_BAND_2GHZ].legacy); WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); if (ret) { @@ -1781,8 +1781,8 @@ static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, goto out; } - tmask.band = IEEE80211_BAND_5GHZ; - tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy); + tmask.band = NL80211_BAND_5GHZ; + tmask.mask = cpu_to_be32(mask->control[NL80211_BAND_5GHZ].legacy); WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); if (ret) { @@ -1793,8 +1793,8 @@ static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, } ath_dbg(common, CONFIG, "Set bitrate masks: 0x%x, 0x%x\n", - mask->control[IEEE80211_BAND_2GHZ].legacy, - mask->control[IEEE80211_BAND_5GHZ].legacy); + mask->control[NL80211_BAND_2GHZ].legacy, + mask->control[NL80211_BAND_5GHZ].legacy); out: return ret; } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index cc9648f844ae..f333ef1e3e7b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -494,7 +494,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI) rate->flags |= IEEE80211_TX_RC_SHORT_GI; } else { - if (cur_conf->chandef.chan->band == IEEE80211_BAND_5GHZ) + if (cur_conf->chandef.chan->band == NL80211_BAND_5GHZ) rate->idx += 4; /* No CCK rates */ } diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 77ace8d72d54..4bf1e244b49b 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -705,9 +705,9 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc) struct ath9k_channel *curchan = ah->curchan; if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) - ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); + ath9k_init_band_txpower(sc, NL80211_BAND_2GHZ); if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) - ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); + ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); ah->curchan = curchan; } @@ -879,11 +879,11 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) sc->ant_tx = hw->wiphy->available_antennas_tx; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &common->sbands[IEEE80211_BAND_2GHZ]; + hw->wiphy->bands[NL80211_BAND_2GHZ] = + &common->sbands[NL80211_BAND_2GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &common->sbands[IEEE80211_BAND_5GHZ]; + hw->wiphy->bands[NL80211_BAND_5GHZ] = + &common->sbands[NL80211_BAND_5GHZ]; #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT ath9k_set_mcc_capab(sc, hw); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 50ec4c9a9da7..8b6398850657 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1933,14 +1933,14 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, if (idx == 0) ath_update_survey_stats(sc); - sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = hw->wiphy->bands[NL80211_BAND_2GHZ]; if (sband && idx >= sband->n_channels) { idx -= sband->n_channels; sband = NULL; } if (!sband) - sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = hw->wiphy->bands[NL80211_BAND_5GHZ]; if (!sband || idx >= sband->n_channels) { spin_unlock_bh(&common->cc_lock); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index fe795fc5288c..8ddd604bd00c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1112,7 +1112,7 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, bool is_2ghz; struct modal_eep_header *pmodal; - is_2ghz = info->band == IEEE80211_BAND_2GHZ; + is_2ghz = info->band == NL80211_BAND_2GHZ; pmodal = &eep->modalHeader[is_2ghz]; power_ht40delta = pmodal->ht40PowerIncForPdadc; } else { @@ -1236,7 +1236,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, /* legacy rates */ rate = &common->sbands[tx_info->band].bitrates[rates[i].idx]; - if ((tx_info->band == IEEE80211_BAND_2GHZ) && + if ((tx_info->band == NL80211_BAND_2GHZ) && !(rate->flags & IEEE80211_RATE_ERP_G)) phy = WLAN_RC_PHY_CCK; else diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index a2f005703c04..7d4a72dc98db 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c @@ -48,7 +48,7 @@ int carl9170_set_dyn_sifs_ack(struct ar9170 *ar) if (conf_is_ht40(&ar->hw->conf)) val = 0x010a; else { - if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) + if (ar->hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) val = 0x105; else val = 0x104; @@ -66,7 +66,7 @@ int carl9170_set_rts_cts_rate(struct ar9170 *ar) rts_rate = 0x1da; cts_rate = 0x10a; } else { - if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (ar->hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) { /* 11 mbit CCK */ rts_rate = 033; cts_rate = 003; @@ -93,7 +93,7 @@ int carl9170_set_slot_time(struct ar9170 *ar) return 0; } - if ((ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) || + if ((ar->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ) || vif->bss_conf.use_short_slot) slottime = 9; @@ -120,7 +120,7 @@ int carl9170_set_mac_rates(struct ar9170 *ar) basic |= (vif->bss_conf.basic_rates & 0xff0) << 4; rcu_read_unlock(); - if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) + if (ar->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ) mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */ else mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */ @@ -512,10 +512,10 @@ int carl9170_set_mac_tpc(struct ar9170 *ar, struct ieee80211_channel *channel) chains = AR9170_TX_PHY_TXCHAIN_1; switch (channel->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: power = ar->power_2G_ofdm[0] & 0x3f; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: power = ar->power_5G_leg[0] & 0x3f; break; default: diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 4d1527a2e292..ffb22a04beeb 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1666,7 +1666,7 @@ static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, return err; } - for (b = 0; b < IEEE80211_NUM_BANDS; b++) { + for (b = 0; b < NUM_NL80211_BANDS; b++) { band = ar->hw->wiphy->bands[b]; if (!band) @@ -1941,13 +1941,13 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) } if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = &carl9170_band_2GHz; chans += carl9170_band_2GHz.n_channels; bands++; } if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = &carl9170_band_5GHz; chans += carl9170_band_5GHz.n_channels; bands++; diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index dca6df13fd5b..34d9fd77046e 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -540,11 +540,11 @@ static int carl9170_init_phy_from_eeprom(struct ar9170 *ar, return carl9170_regwrite_result(); } -static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) +static int carl9170_init_phy(struct ar9170 *ar, enum nl80211_band band) { int i, err; u32 val; - bool is_2ghz = band == IEEE80211_BAND_2GHZ; + bool is_2ghz = band == NL80211_BAND_2GHZ; bool is_40mhz = conf_is_ht40(&ar->hw->conf); carl9170_regwrite_begin(ar); @@ -1125,13 +1125,13 @@ static int carl9170_set_freq_cal_data(struct ar9170 *ar, u8 f, tmp; switch (channel->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: f = channel->center_freq - 2300; cal_freq_pier = ar->eeprom.cal_freq_pier_2G; i = AR5416_NUM_2G_CAL_PIERS - 1; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: f = (channel->center_freq - 4800) / 5; cal_freq_pier = ar->eeprom.cal_freq_pier_5G; i = AR5416_NUM_5G_CAL_PIERS - 1; @@ -1158,12 +1158,12 @@ static int carl9170_set_freq_cal_data(struct ar9170 *ar, int j; switch (channel->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: cal_pier_data = &ar->eeprom. cal_pier_data_2G[chain][idx]; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: cal_pier_data = &ar->eeprom. cal_pier_data_5G[chain][idx]; break; @@ -1340,7 +1340,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw) /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ return; - if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (ar->hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) { modes = mode_list_2ghz; nr_modes = ARRAY_SIZE(mode_list_2ghz); } else { @@ -1607,7 +1607,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, return err; err = carl9170_init_rf_banks_0_7(ar, - channel->band == IEEE80211_BAND_5GHZ); + channel->band == NL80211_BAND_5GHZ); if (err) return err; @@ -1621,7 +1621,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, return err; err = carl9170_init_rf_bank4_pwr(ar, - channel->band == IEEE80211_BAND_5GHZ, + channel->band == NL80211_BAND_5GHZ, channel->center_freq, bw); if (err) return err; diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index d66533cbc38a..0c34c8729dc6 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -417,7 +417,7 @@ static int carl9170_rx_mac_status(struct ar9170 *ar, return -EINVAL; } - if (status->band == IEEE80211_BAND_2GHZ) + if (status->band == NL80211_BAND_2GHZ) status->rate_idx += 4; break; diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index ae86a600d920..2bf04c9edc98 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -720,12 +720,12 @@ static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar, /* +1 dBm for HT40 */ *tpc += 2; - if (info->band == IEEE80211_BAND_2GHZ) + if (info->band == NL80211_BAND_2GHZ) txpower = ar->power_2G_ht40; else txpower = ar->power_5G_ht40; } else { - if (info->band == IEEE80211_BAND_2GHZ) + if (info->band == NL80211_BAND_2GHZ) txpower = ar->power_2G_ht20; else txpower = ar->power_5G_ht20; @@ -734,7 +734,7 @@ static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar, *phyrate = txrate->idx; *tpc += txpower[idx & 7]; } else { - if (info->band == IEEE80211_BAND_2GHZ) { + if (info->band == NL80211_BAND_2GHZ) { if (idx < 4) txpower = ar->power_2G_cck; else @@ -797,7 +797,7 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar, * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); */ } else { - if (info->band == IEEE80211_BAND_2GHZ) { + if (info->band == NL80211_BAND_2GHZ) { if (txrate->idx <= AR9170_TX_PHY_RATE_CCK_11M) tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_CCK); else diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 06ea6cc9e30a..7e15ed9ed31f 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -336,12 +336,12 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, struct ath_regulatory *reg, enum nl80211_reg_initiator initiator) { - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; unsigned int i; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!wiphy->bands[band]) continue; sband = wiphy->bands[band]; @@ -374,7 +374,7 @@ ath_reg_apply_ir_flags(struct wiphy *wiphy, { struct ieee80211_supported_band *sband; - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = wiphy->bands[NL80211_BAND_2GHZ]; if (!sband) return; @@ -402,10 +402,10 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy) struct ieee80211_channel *ch; unsigned int i; - if (!wiphy->bands[IEEE80211_BAND_5GHZ]) + if (!wiphy->bands[NL80211_BAND_5GHZ]) return; - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = wiphy->bands[NL80211_BAND_5GHZ]; for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; @@ -772,7 +772,7 @@ ath_regd_init(struct ath_regulatory *reg, EXPORT_SYMBOL(ath_regd_init); u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, - enum ieee80211_band band) + enum nl80211_band band) { if (!reg->regpair || (reg->country_code == CTRY_DEFAULT && @@ -794,9 +794,9 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, } switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: return reg->regpair->reg_2ghz_ctl; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: return reg->regpair->reg_5ghz_ctl; default: return NO_CTL; diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 37f53bd8fcb1..565d3075f06e 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -255,7 +255,7 @@ int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request)); u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, - enum ieee80211_band band); + enum nl80211_band band); void ath_reg_notifier_apply(struct wiphy *wiphy, struct regulatory_request *request, struct ath_regulatory *reg); diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index a27279c2c695..9a1db3bbec4e 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -26,14 +26,14 @@ module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); MODULE_PARM_DESC(debug_mask, "Debugging mask"); #define CHAN2G(_freq, _idx) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_idx), \ .max_power = 25, \ } #define CHAN5G(_freq, _idx) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = (_freq), \ .hw_value = (_idx), \ .max_power = 25, \ @@ -516,7 +516,7 @@ static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, } static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, - enum ieee80211_band band) + enum nl80211_band band) { int i, size; u16 *rates_table; @@ -529,7 +529,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); rates_table = sta_priv->supported_rates.dsss_rates; - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { for (i = 0; i < size; i++) { if (rates & 0x01) { rates_table[i] = wcn_2ghz_rates[i].hw_value; @@ -958,8 +958,8 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); - wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; - wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; + wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz; + wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz; wcn->hw->wiphy->cipher_suites = cipher_suites; wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 74f56a81ad9a..96992a2c4b42 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -104,11 +104,11 @@ static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn, struct ieee80211_sta *sta, struct wcn36xx_hal_config_bss_params *bss_params) { - if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn)) + if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn)) bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE; else if (sta && sta->ht_cap.ht_supported) bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE; - else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f)) + else if (sta && (sta->supp_rates[NL80211_BAND_2GHZ] & 0x7f)) bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE; else bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE; diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 99c21aac68bd..6c47a7336c38 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -225,7 +225,7 @@ static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, /* default rate for unicast */ if (ieee80211_is_mgmt(hdr->frame_control)) - bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ? + bd->bd_rate = (WCN36XX_BAND(wcn) == NL80211_BAND_5GHZ) ? WCN36XX_BD_RATE_CTRL : WCN36XX_BD_RATE_MGMT; else if (ieee80211_is_ctl(hdr->frame_control)) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 12cae3c005fb..0fb3a7941d84 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -21,7 +21,7 @@ #define WIL_MAX_ROC_DURATION_MS 5000 #define CHAN60G(_channel, _flags) { \ - .band = IEEE80211_BAND_60GHZ, \ + .band = NL80211_BAND_60GHZ, \ .center_freq = 56160 + (2160 * (_channel)), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -1411,7 +1411,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; - wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; + wiphy->bands[NL80211_BAND_60GHZ] = &wil_band_60ghz; /* TODO: figure this out */ wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 3bc0e2634db0..098409753d5b 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -157,7 +157,7 @@ void *wil_if_alloc(struct device *dev) wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ /* default monitor channel */ - ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; + ch = wdev->wiphy->bands[NL80211_BAND_60GHZ]->channels; cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, wil_dev_setup); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 3cc4462aec1a..6ca28c3eff0a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -333,7 +333,7 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) } ch_no = data->info.channel + 1; - freq = ieee80211_channel_to_frequency(ch_no, IEEE80211_BAND_60GHZ); + freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ); channel = ieee80211_get_channel(wiphy, freq); signal = data->info.sqi; d_status = le16_to_cpu(data->info.status); diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c index 1efb1d66e0b7..7c108047fb46 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.c +++ b/drivers/net/wireless/atmel/at76c50x-usb.c @@ -1547,7 +1547,7 @@ static inline int at76_guess_freq(struct at76_priv *priv) channel = el[2]; exit: - return ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ); + return ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ); } static void at76_rx_tasklet(unsigned long param) @@ -1590,7 +1590,7 @@ static void at76_rx_tasklet(unsigned long param) rx_status.signal = buf->rssi; rx_status.flag |= RX_FLAG_DECRYPTED; rx_status.flag |= RX_FLAG_IV_STRIPPED; - rx_status.band = IEEE80211_BAND_2GHZ; + rx_status.band = NL80211_BAND_2GHZ; rx_status.freq = at76_guess_freq(priv); at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d", @@ -2359,7 +2359,7 @@ static int at76_init_new_device(struct at76_priv *priv, priv->hw->wiphy->max_scan_ssids = 1; priv->hw->wiphy->max_scan_ie_len = 0; priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band; + priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = &at76_supported_band; ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS); ieee80211_hw_set(priv->hw, SIGNAL_UNSPEC); priv->hw->max_signal = 100; diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c index 6a1f03c271c1..8f8f37f3a00c 100644 --- a/drivers/net/wireless/atmel/atmel.c +++ b/drivers/net/wireless/atmel/atmel.c @@ -2434,7 +2434,7 @@ static int atmel_get_range(struct net_device *dev, /* Values in MHz -> * 10^5 * 10 */ range->freq[k].m = 100000 * - ieee80211_channel_to_frequency(i, IEEE80211_BAND_2GHZ); + ieee80211_channel_to_frequency(i, NL80211_BAND_2GHZ); range->freq[k++].e = 1; } range->num_frequency = k; diff --git a/drivers/net/wireless/broadcom/b43/b43.h b/drivers/net/wireless/broadcom/b43/b43.h index 036552439816..d7d42f0b80c3 100644 --- a/drivers/net/wireless/broadcom/b43/b43.h +++ b/drivers/net/wireless/broadcom/b43/b43.h @@ -992,9 +992,9 @@ static inline int b43_is_mode(struct b43_wl *wl, int type) /** * b43_current_band - Returns the currently used band. - * Returns one of IEEE80211_BAND_2GHZ and IEEE80211_BAND_5GHZ. + * Returns one of NL80211_BAND_2GHZ and NL80211_BAND_5GHZ. */ -static inline enum ieee80211_band b43_current_band(struct b43_wl *wl) +static inline enum nl80211_band b43_current_band(struct b43_wl *wl) { return wl->hw->conf.chandef.chan->band; } diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index b0603e796ad8..4ee5c5853f9f 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -187,7 +187,7 @@ static struct ieee80211_rate __b43_ratetable[] = { #define b43_g_ratetable_size 12 #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -216,7 +216,7 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { #undef CHAN2G #define CHAN4G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = 4000 + (5 * (_channel)), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -224,7 +224,7 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { .max_power = 30, \ } #define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + (5 * (_channel)), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -323,7 +323,7 @@ static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { #undef CHAN5G static struct ieee80211_supported_band b43_band_5GHz_nphy = { - .band = IEEE80211_BAND_5GHZ, + .band = NL80211_BAND_5GHZ, .channels = b43_5ghz_nphy_chantable, .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable), .bitrates = b43_a_ratetable, @@ -331,7 +331,7 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy = { }; static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = { - .band = IEEE80211_BAND_5GHZ, + .band = NL80211_BAND_5GHZ, .channels = b43_5ghz_nphy_chantable_limited, .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable_limited), .bitrates = b43_a_ratetable, @@ -339,7 +339,7 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = { }; static struct ieee80211_supported_band b43_band_5GHz_aphy = { - .band = IEEE80211_BAND_5GHZ, + .band = NL80211_BAND_5GHZ, .channels = b43_5ghz_aphy_chantable, .n_channels = ARRAY_SIZE(b43_5ghz_aphy_chantable), .bitrates = b43_a_ratetable, @@ -347,7 +347,7 @@ static struct ieee80211_supported_band b43_band_5GHz_aphy = { }; static struct ieee80211_supported_band b43_band_2GHz = { - .band = IEEE80211_BAND_2GHZ, + .band = NL80211_BAND_2GHZ, .channels = b43_2ghz_chantable, .n_channels = ARRAY_SIZE(b43_2ghz_chantable), .bitrates = b43_g_ratetable, @@ -355,7 +355,7 @@ static struct ieee80211_supported_band b43_band_2GHz = { }; static struct ieee80211_supported_band b43_band_2ghz_limited = { - .band = IEEE80211_BAND_2GHZ, + .band = NL80211_BAND_2GHZ, .channels = b43_2ghz_chantable, .n_channels = b43_2ghz_chantable_limited_size, .bitrates = b43_g_ratetable, @@ -717,7 +717,7 @@ static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) { /* slot_time is in usec. */ /* This test used to exit for all but a G PHY. */ - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) return; b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time); /* Shared memory location 0x0010 is the slot time and should be @@ -3880,12 +3880,12 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, mutex_unlock(&wl->mutex); } -static const char *band_to_string(enum ieee80211_band band) +static const char *band_to_string(enum nl80211_band band) { switch (band) { - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: return "5"; - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: return "2.4"; default: break; @@ -3903,10 +3903,10 @@ static int b43_switch_band(struct b43_wldev *dev, u32 tmp; switch (chan->band) { - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: gmode = false; break; - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: gmode = true; break; default: @@ -5294,16 +5294,16 @@ static int b43_setup_bands(struct b43_wldev *dev, phy->radio_rev == 9; if (have_2ghz_phy) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ? + hw->wiphy->bands[NL80211_BAND_2GHZ] = limited_2g ? &b43_band_2ghz_limited : &b43_band_2GHz; if (dev->phy.type == B43_PHYTYPE_N) { if (have_5ghz_phy) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = limited_5g ? + hw->wiphy->bands[NL80211_BAND_5GHZ] = limited_5g ? &b43_band_5GHz_nphy_limited : &b43_band_5GHz_nphy; } else { if (have_5ghz_phy) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; + hw->wiphy->bands[NL80211_BAND_5GHZ] = &b43_band_5GHz_aphy; } dev->phy.supports_2ghz = have_2ghz_phy; diff --git a/drivers/net/wireless/broadcom/b43/phy_ac.c b/drivers/net/wireless/broadcom/b43/phy_ac.c index e75633d67938..52f8abad8831 100644 --- a/drivers/net/wireless/broadcom/b43/phy_ac.c +++ b/drivers/net/wireless/broadcom/b43/phy_ac.c @@ -61,7 +61,7 @@ static void b43_phy_ac_op_radio_write(struct b43_wldev *dev, u16 reg, static unsigned int b43_phy_ac_op_get_default_chan(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) return 11; return 36; } diff --git a/drivers/net/wireless/broadcom/b43/phy_common.c b/drivers/net/wireless/broadcom/b43/phy_common.c index ec2b9c577b90..85f2ca989565 100644 --- a/drivers/net/wireless/broadcom/b43/phy_common.c +++ b/drivers/net/wireless/broadcom/b43/phy_common.c @@ -436,7 +436,7 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) * firmware from sending ghost packets. */ channelcookie = new_channel; - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) channelcookie |= B43_SHM_SH_CHAN_5GHZ; /* FIXME: set 40Mhz flag if required */ if (0) diff --git a/drivers/net/wireless/broadcom/b43/phy_ht.c b/drivers/net/wireless/broadcom/b43/phy_ht.c index bd68945965d6..718c90e81696 100644 --- a/drivers/net/wireless/broadcom/b43/phy_ht.c +++ b/drivers/net/wireless/broadcom/b43/phy_ht.c @@ -568,7 +568,7 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable) } else { b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { for (i = 0; i < 3; i++) b43_phy_write(dev, cmd_regs[i], 0x32); } @@ -643,7 +643,7 @@ static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev) u16 freq = dev->phy.chandef->chan->center_freq; int i, c; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { for (c = 0; c < 3; c++) { target[c] = sprom->core_pwr_info[c].maxpwr_2g; a1[c] = sprom->core_pwr_info[c].pa_2g[0]; @@ -777,7 +777,7 @@ static void b43_phy_ht_channel_setup(struct b43_wldev *dev, const struct b43_phy_ht_channeltab_e_phy *e, struct ieee80211_channel *new_channel) { - if (new_channel->band == IEEE80211_BAND_5GHZ) { + if (new_channel->band == NL80211_BAND_5GHZ) { /* Switch to 2 GHz for a moment to access B-PHY regs */ b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ); @@ -805,7 +805,7 @@ static void b43_phy_ht_channel_setup(struct b43_wldev *dev, } else { b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, B43_PHY_HT_CLASS_CTL_OFDM_EN); - if (new_channel->band == IEEE80211_BAND_2GHZ) + if (new_channel->band == NL80211_BAND_2GHZ) b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840); } @@ -916,7 +916,7 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) if (0) /* TODO: condition */ ; /* TODO: PHY op on reg 0x217 */ - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0); else b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, @@ -1005,7 +1005,7 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) b43_phy_ht_classifier(dev, 0, 0); b43_phy_ht_read_clip_detection(dev, clip_state); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) b43_phy_ht_bphy_init(dev); b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), @@ -1077,7 +1077,7 @@ static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev, enum nl80211_channel_type channel_type = cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if ((new_channel < 1) || (new_channel > 14)) return -EINVAL; } else { @@ -1089,7 +1089,7 @@ static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev, static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) return 11; return 36; } diff --git a/drivers/net/wireless/broadcom/b43/phy_lcn.c b/drivers/net/wireless/broadcom/b43/phy_lcn.c index 97461ccf3e1e..63bd29f070f7 100644 --- a/drivers/net/wireless/broadcom/b43/phy_lcn.c +++ b/drivers/net/wireless/broadcom/b43/phy_lcn.c @@ -108,7 +108,7 @@ static void b43_radio_2064_channel_setup(struct b43_wldev *dev) /* wlc_radio_2064_init */ static void b43_radio_2064_init(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_radio_write(dev, 0x09c, 0x0020); b43_radio_write(dev, 0x105, 0x0008); } else { @@ -535,7 +535,7 @@ static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev) b43_mac_suspend(dev); if (!dev->phy.lcn->hw_pwr_ctl_capable) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { tx_gains.gm_gain = 4; tx_gains.pga_gain = 12; tx_gains.pad_gain = 12; @@ -720,7 +720,7 @@ static int b43_phy_lcn_op_init(struct b43_wldev *dev) else B43_WARN_ON(1); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) b43_phy_lcn_tx_pwr_ctl_init(dev); b43_switch_channel(dev, dev->phy.channel); @@ -779,7 +779,7 @@ static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev, enum nl80211_channel_type channel_type = cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if ((new_channel < 1) || (new_channel > 14)) return -EINVAL; } else { @@ -791,7 +791,7 @@ static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev, static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) return 1; return 36; } diff --git a/drivers/net/wireless/broadcom/b43/phy_lp.c b/drivers/net/wireless/broadcom/b43/phy_lp.c index 058a9f232050..6922cbb99a04 100644 --- a/drivers/net/wireless/broadcom/b43/phy_lp.c +++ b/drivers/net/wireless/broadcom/b43/phy_lp.c @@ -46,7 +46,7 @@ static inline u16 channel2freq_lp(u8 channel) static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) return 1; return 36; } @@ -91,7 +91,7 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) u32 ofdmpo; int i; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { lpphy->tx_isolation_med_band = sprom->tri2g; lpphy->bx_arch = sprom->bxa2g; lpphy->rx_pwr_offset = sprom->rxpo2g; @@ -174,7 +174,7 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq) B43_WARN_ON(dev->phy.rev >= 2); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) isolation = lpphy->tx_isolation_med_band; else if (freq <= 5320) isolation = lpphy->tx_isolation_low_band; @@ -238,7 +238,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, 0xFF00, lpphy->rx_pwr_offset); if ((sprom->boardflags_lo & B43_BFL_FEM) && - ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || + ((b43_current_band(dev->wl) == NL80211_BAND_5GHZ) || (sprom->boardflags_hi & B43_BFH_PAREF))) { ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28); ssb_pmu_set_ldo_paref(&bus->chipco, true); @@ -280,7 +280,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900); b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A); b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00); - } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ || + } else if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ || (dev->dev->board_type == SSB_BOARD_BU4312) || (dev->phy.rev == 0 && (sprom->boardflags_lo & B43_BFL_FEM))) { b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001); @@ -326,7 +326,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) //FIXME the Broadcom driver caches & delays this HF write! b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W); } - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000); b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040); b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400); @@ -466,7 +466,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); } - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40); b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0xB00); b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6); @@ -547,7 +547,7 @@ static void lpphy_2062_init(struct b43_wldev *dev) b43_radio_write(dev, B2062_S_BG_CTL1, (b43_radio_read(dev, B2062_N_COMM2) >> 1) | 0x80); } - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1); else b43_radio_mask(dev, B2062_N_TSSI_CTL0, ~0x1); @@ -746,7 +746,7 @@ static void lpphy_clear_deaf(struct b43_wldev *dev, bool user) lpphy->crs_sys_disable = false; if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60); else @@ -807,7 +807,7 @@ static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); if (dev->phy.rev >= 2) { b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7); } @@ -823,7 +823,7 @@ static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); if (dev->phy.rev >= 2) { b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8); } @@ -951,7 +951,7 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) 0xFBFF, ext_lna << 10); b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain); b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { tmp = (gain >> 2) & 0x3; b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xE7FF, tmp<<11); @@ -1344,7 +1344,7 @@ static void lpphy_calibrate_rc(struct b43_wldev *dev) if (dev->phy.rev >= 2) { lpphy_rev2plus_rc_calib(dev); } else if (!lpphy->rc_cap) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) lpphy_rev0_1_rc_calib(dev); } else { lpphy_set_rc_cap(dev); @@ -1548,7 +1548,7 @@ static void lpphy_tx_pctl_init_sw(struct b43_wldev *dev) { struct lpphy_tx_gains gains; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { gains.gm = 4; gains.pad = 12; gains.pga = 12; @@ -1902,7 +1902,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx, lpphy_set_trsw_over(dev, tx, rx); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7, pa << 3); diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c index 9f0bcf3b8414..a5557d70689f 100644 --- a/drivers/net/wireless/broadcom/b43/phy_n.c +++ b/drivers/net/wireless/broadcom/b43/phy_n.c @@ -105,9 +105,9 @@ enum n_rail_type { static inline bool b43_nphy_ipa(struct b43_wldev *dev) { - enum ieee80211_band band = b43_current_band(dev->wl); - return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) || - (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)); + enum nl80211_band band = b43_current_band(dev->wl); + return ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) || + (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ)); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */ @@ -357,7 +357,7 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev, break; case N_INTC_OVERRIDE_PA: tmp = 0x0030; - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) val = value << 5; else val = value << 4; @@ -365,7 +365,7 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev, b43_phy_set(dev, reg, 0x1000); break; case N_INTC_OVERRIDE_EXT_LNA_PU: - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { tmp = 0x0001; tmp2 = 0x0004; val = value; @@ -378,7 +378,7 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev, b43_phy_mask(dev, reg, ~tmp2); break; case N_INTC_OVERRIDE_EXT_LNA_GAIN: - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { tmp = 0x0002; tmp2 = 0x0008; val = value << 1; @@ -465,7 +465,7 @@ static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev, } break; case N_INTC_OVERRIDE_PA: - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { tmp = 0x0020; val = value << 5; } else { @@ -475,7 +475,7 @@ static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev, b43_phy_maskset(dev, reg, ~tmp, val); break; case N_INTC_OVERRIDE_EXT_LNA_PU: - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { tmp = 0x0001; val = value; } else { @@ -485,7 +485,7 @@ static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev, b43_phy_maskset(dev, reg, ~tmp, val); break; case N_INTC_OVERRIDE_EXT_LNA_GAIN: - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { tmp = 0x0002; val = value << 1; } else { @@ -600,7 +600,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 1); if (nphy->gain_boost) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { gain[0] = 6; gain[1] = 6; } else { @@ -736,7 +736,7 @@ static void b43_radio_2057_setup(struct b43_wldev *dev, switch (phy->radio_rev) { case 0 ... 4: case 6: - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f); b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f); b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8); @@ -751,7 +751,7 @@ static void b43_radio_2057_setup(struct b43_wldev *dev, case 9: /* e.g. PHY rev 16 */ b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20); b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38); b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f); @@ -775,7 +775,7 @@ static void b43_radio_2057_setup(struct b43_wldev *dev, break; } - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { u16 txmix2g_tune_boost_pu = 0; u16 pad2g_tune_pus = 0; @@ -1135,7 +1135,7 @@ static void b43_radio_2056_setup(struct b43_wldev *dev, { struct b43_phy *phy = &dev->phy; struct ssb_sprom *sprom = dev->dev->bus_sprom; - enum ieee80211_band band = b43_current_band(dev->wl); + enum nl80211_band band = b43_current_band(dev->wl); u16 offset; u8 i; u16 bias, cbias; @@ -1152,10 +1152,10 @@ static void b43_radio_2056_setup(struct b43_wldev *dev, dev->dev->chip_pkg == BCMA_PKG_ID_BCM43224_FAB_SMIC); b43_chantab_radio_2056_upload(dev, e); - b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ); + b2056_upload_syn_pll_cp2(dev, band == NL80211_BAND_5GHZ); if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR && - b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F); b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F); if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 || @@ -1168,21 +1168,21 @@ static void b43_radio_2056_setup(struct b43_wldev *dev, } } if (sprom->boardflags2_hi & B43_BFH2_GPLL_WAR2 && - b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1f); b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1f); b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0b); b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x20); } if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR && - b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F); b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F); b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05); b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C); } - if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) { + if (dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) { for (i = 0; i < 2; i++) { offset = i ? B2056_TX1 : B2056_TX0; if (dev->phy.rev >= 5) { @@ -1244,7 +1244,7 @@ static void b43_radio_2056_setup(struct b43_wldev *dev, } b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee); } - } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) { + } else if (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ) { u16 freq = phy->chandef->chan->center_freq; if (freq < 5100) { paa_boost = 0xA; @@ -1501,7 +1501,7 @@ static void b43_radio_init2055(struct b43_wldev *dev) /* Follow wl, not specs. Do not force uploading all regs */ b2055_upload_inittab(dev, 0, 0); } else { - bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ; + bool ghz5 = b43_current_band(dev->wl) == NL80211_BAND_5GHZ; b2055_upload_inittab(dev, ghz5, 0); } b43_radio_init2055_post(dev); @@ -1785,7 +1785,7 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, b43_phy_maskset(dev, reg, 0xFFC3, 0); if (rssi_type == N_RSSI_W1) - val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8; + val = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 4 : 8; else if (rssi_type == N_RSSI_W2) val = 16; else @@ -1813,12 +1813,12 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, if (rssi_type != N_RSSI_IQ && rssi_type != N_RSSI_TBD) { - enum ieee80211_band band = + enum nl80211_band band = b43_current_band(dev->wl); if (dev->phy.rev < 7) { if (b43_nphy_ipa(dev)) - val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; + val = (band == NL80211_BAND_5GHZ) ? 0xC : 0xE; else val = 0x11; reg = (i == 0) ? B2056_TX0 : B2056_TX1; @@ -2120,7 +2120,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) 1, 0, false); b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0); b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false, 0); b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false, @@ -2136,7 +2136,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false); b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false); b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { b43_nphy_rf_ctl_override(dev, 0x20, 0, 0, false); b43_nphy_rf_ctl_override(dev, 0x10, 1, 0, false); } else { @@ -2257,7 +2257,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]); /* Store for future configuration */ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; } else { @@ -2289,7 +2289,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y); /* Remember for which channel we store configuration */ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) nphy->rssical_chanspec_2G.center_freq = phy->chandef->chan->center_freq; else nphy->rssical_chanspec_5G.center_freq = phy->chandef->chan->center_freq; @@ -2336,7 +2336,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type) b43_nphy_read_clip_detection(dev, clip_state); b43_nphy_write_clip_detection(dev, clip_off); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) override = 0x140; else override = 0x110; @@ -2629,7 +2629,7 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); if (nphy->gain_boost) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ && + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ && b43_is_40mhz(dev)) code = 4; else @@ -2688,7 +2688,7 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev) ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF, 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4); } @@ -2803,7 +2803,7 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL); if (b43_nphy_ipa(dev)) { - bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ; + bool ghz2 = b43_current_band(dev->wl) == NL80211_BAND_2GHZ; switch (phy->radio_rev) { case 5: @@ -2831,7 +2831,7 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) bcap_val_11b[core] = bcap_val; lpf_ofdm_20mhz[core] = 4; lpf_11b[core] = 1; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { scap_val_11n_20[core] = 0xc; bcap_val_11n_20[core] = 0xc; scap_val_11n_40[core] = 0xa; @@ -2982,7 +2982,7 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) conv = 0x7f; filt = 0xee; } - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { for (core = 0; core < 2; core++) { if (core == 0) { b43_radio_write(dev, 0x5F, bias); @@ -2998,7 +2998,7 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) } if (b43_nphy_ipa(dev)) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) { for (core = 0; core < 2; core++) { @@ -3221,7 +3221,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) ARRAY_SIZE(rx2tx_events)); } - tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? + tmp16 = (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 0x2 : 0x9C40; b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16); @@ -3240,7 +3240,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) b43_ntab_write(dev, B43_NTAB16(8, 0), 2); b43_ntab_write(dev, B43_NTAB16(8, 16), 2); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) pdet_range = sprom->fem.ghz2.pdet_range; else pdet_range = sprom->fem.ghz5.pdet_range; @@ -3249,7 +3249,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) switch (pdet_range) { case 3: if (!(dev->phy.rev >= 4 && - b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) + b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) break; /* FALL THROUGH */ case 0: @@ -3261,7 +3261,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) break; case 2: if (dev->phy.rev >= 6) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) vmid[3] = 0x94; else vmid[3] = 0x8e; @@ -3277,7 +3277,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) break; case 4: case 5: - if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ) { if (pdet_range == 4) { vmid[3] = 0x8e; tmp16 = 0x96; @@ -3322,9 +3322,9 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) /* N PHY WAR TX Chain Update with hw_phytxchain as argument */ if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR && - b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || + b43_current_band(dev->wl) == NL80211_BAND_5GHZ) || (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR && - b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) + b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) tmp32 = 0x00088888; else tmp32 = 0x88888888; @@ -3333,7 +3333,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32); if (dev->phy.rev == 4 && - b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC, 0x70); b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC, @@ -3376,7 +3376,7 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) delays1[5] = 0x14; } - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ && + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ && nphy->band5g_pwrgain) { b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8); @@ -3451,7 +3451,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = phy->n; - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) b43_nphy_classifier(dev, 1, 0); else b43_nphy_classifier(dev, 1, 1); @@ -3586,7 +3586,7 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, gain = (target.pad[core]) | (target.pga[core] << 4) | (target.txgm[core] << 8); - indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? + indx = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 1 : 0; for (i = 0; i < 9; i++) if (tbl_iqcal_gainparams[indx][i][0] == gain) @@ -3614,7 +3614,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) struct b43_phy_n *nphy = dev->phy.n; u8 i; u16 bmask, val, tmp; - enum ieee80211_band band = b43_current_band(dev->wl); + enum nl80211_band band = b43_current_band(dev->wl); if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 1); @@ -3679,7 +3679,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) } b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val); - if (band == IEEE80211_BAND_5GHZ) { + if (band == NL80211_BAND_5GHZ) { if (phy->rev >= 19) { /* TODO */ } else if (phy->rev >= 7) { @@ -3770,7 +3770,7 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) txpi[0] = 72; txpi[1] = 72; } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { txpi[0] = sprom->txpid2g[0]; txpi[1] = sprom->txpid2g[1]; } else if (freq >= 4900 && freq < 5100) { @@ -3868,7 +3868,7 @@ static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev) } else if (phy->rev >= 7) { for (core = 0; core < 2; core++) { r = core ? 0x190 : 0x170; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_radio_write(dev, r + 0x5, 0x5); b43_radio_write(dev, r + 0x9, 0xE); if (phy->rev != 5) @@ -3892,7 +3892,7 @@ static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev) b43_radio_write(dev, r + 0xC, 0); } } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128); else b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80); @@ -3909,7 +3909,7 @@ static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev) b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8); b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0); b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER, 0x5); if (phy->rev != 5) @@ -4098,7 +4098,7 @@ static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev) b0[0] = b0[1] = 5612; b1[0] = b1[1] = -1393; } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { for (c = 0; c < 2; c++) { idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; target[c] = sprom->core_pwr_info[c].maxpwr_2g; @@ -4153,11 +4153,11 @@ static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev) for (c = 0; c < 2; c++) { r = c ? 0x190 : 0x170; if (b43_nphy_ipa(dev)) - b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? 0xE : 0xC); + b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 0xE : 0xC); } } else { if (b43_nphy_ipa(dev)) { - tmp = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; + tmp = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 0xC : 0xE; b43_radio_write(dev, B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); b43_radio_write(dev, @@ -4267,13 +4267,13 @@ static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) } else if (phy->rev >= 7) { pga_gain = (table[i] >> 24) & 0xf; pad_gain = (table[i] >> 19) & 0x1f; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) rfpwr_offset = rf_pwr_offset_table[pad_gain]; else rfpwr_offset = rf_pwr_offset_table[pga_gain]; } else { pga_gain = (table[i] >> 24) & 0xF; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; else rfpwr_offset = 0; /* FIXME */ @@ -4288,7 +4288,7 @@ static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) { struct b43_phy_n *nphy = dev->phy.n; - enum ieee80211_band band; + enum nl80211_band band; u16 tmp; if (!enable) { @@ -4300,12 +4300,12 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) if (dev->phy.rev >= 7) { tmp = 0x1480; } else if (dev->phy.rev >= 3) { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) tmp = 0x600; else tmp = 0x480; } else { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) tmp = 0x180; else tmp = 0x120; @@ -4734,7 +4734,7 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) u16 *rssical_radio_regs = NULL; u16 *rssical_phy_regs = NULL; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if (!nphy->rssical_chanspec_2G.center_freq) return; rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; @@ -4804,7 +4804,7 @@ static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev) save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG); save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA); b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43); b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55); @@ -4864,7 +4864,7 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) save[offset + 9] = b43_radio_read(dev, B2055_XOMISC); save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A); b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40); b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55); @@ -5005,7 +5005,7 @@ static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) b43_nphy_pa_set_tx_dig_filter(dev, 0x186, tbl_tx_filter_coef_rev4[3]); } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) b43_nphy_pa_set_tx_dig_filter(dev, 0x186, tbl_tx_filter_coef_rev4[5]); if (dev->phy.channel == 14) @@ -5185,7 +5185,7 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) false, 0); } else if (phy->rev == 7) { b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0); b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0); } else { @@ -5210,7 +5210,7 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) b43_ntab_write(dev, B43_NTAB16(8, 18), tmp); regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) tmp = 0x0180; else tmp = 0x0120; @@ -5233,7 +5233,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 1); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; iqcal_chanspec = &nphy->iqcal_chanspec_2G; @@ -5304,7 +5304,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) u16 *txcal_radio_regs = NULL; struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if (!nphy->iqcal_chanspec_2G.center_freq) return; table = nphy->cal_cache.txcal_coeffs_2G; @@ -5332,7 +5332,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) if (dev->phy.rev < 2) b43_nphy_tx_iq_workaround(dev); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; } else { @@ -5422,7 +5422,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, phy6or5x = dev->phy.rev >= 6 || (dev->phy.rev == 5 && nphy->ipa2g_on && - b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ); + b43_current_band(dev->wl) == NL80211_BAND_2GHZ); if (phy6or5x) { if (b43_is_40mhz(dev)) { b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, @@ -5657,7 +5657,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, u16 tmp[6]; u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna; u32 real, imag; - enum ieee80211_band band; + enum nl80211_band band; u8 use; u16 cur_hpf; @@ -5712,18 +5712,18 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, band = b43_current_band(dev->wl); if (nphy->rxcalparams & 0xFF000000) { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) b43_phy_write(dev, rfctl[0], 0x140); else b43_phy_write(dev, rfctl[0], 0x110); } else { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) b43_phy_write(dev, rfctl[0], 0x180); else b43_phy_write(dev, rfctl[0], 0x120); } - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) b43_phy_write(dev, rfctl[1], 0x148); else b43_phy_write(dev, rfctl[1], 0x114); @@ -5919,7 +5919,7 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, #if 0 /* Some extra gains */ hw_gain = 6; /* N-PHY specific */ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) hw_gain += sprom->antenna_gain.a0; else hw_gain += sprom->antenna_gain.a1; @@ -6043,7 +6043,7 @@ static int b43_phy_initn(struct b43_wldev *dev) u8 tx_pwr_state; struct nphy_txgains target; u16 tmp; - enum ieee80211_band tmp2; + enum nl80211_band tmp2; bool do_rssi_cal; u16 clip[2]; @@ -6051,7 +6051,7 @@ static int b43_phy_initn(struct b43_wldev *dev) if ((dev->phy.rev >= 3) && (sprom->boardflags_lo & B43_BFL_EXTLNA) && - (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { + (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) { switch (dev->dev->bus_type) { #ifdef CONFIG_B43_BCMA case B43_BUS_BCMA: @@ -6170,7 +6170,7 @@ static int b43_phy_initn(struct b43_wldev *dev) b43_nphy_classifier(dev, 0, 0); b43_nphy_read_clip_detection(dev, clip); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) b43_nphy_bphy_init(dev); tx_pwr_state = nphy->txpwrctrl; @@ -6187,7 +6187,7 @@ static int b43_phy_initn(struct b43_wldev *dev) do_rssi_cal = false; if (phy->rev >= 3) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq; else do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq; @@ -6201,7 +6201,7 @@ static int b43_phy_initn(struct b43_wldev *dev) } if (!((nphy->measure_hold & 0x6) != 0)) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) do_cal = !nphy->iqcal_chanspec_2G.center_freq; else do_cal = !nphy->iqcal_chanspec_5G.center_freq; @@ -6291,7 +6291,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, int ch = new_channel->hw_value; u16 tmp16; - if (new_channel->band == IEEE80211_BAND_5GHZ) { + if (new_channel->band == NL80211_BAND_5GHZ) { /* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */ b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); @@ -6302,7 +6302,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX); b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); - } else if (new_channel->band == IEEE80211_BAND_2GHZ) { + } else if (new_channel->band == NL80211_BAND_2GHZ) { b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); @@ -6319,7 +6319,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); } else { b43_nphy_classifier(dev, 2, 2); - if (new_channel->band == IEEE80211_BAND_2GHZ) + if (new_channel->band == NL80211_BAND_2GHZ) b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); } @@ -6449,7 +6449,7 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); if (phy->radio_rev <= 4 || phy->radio_rev == 6) { - tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 2 : 0; + tmp = (channel->band == NL80211_BAND_5GHZ) ? 2 : 0; b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp); b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp); } @@ -6457,12 +6457,12 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g); b43_nphy_channel_setup(dev, phy_regs, channel); } else if (phy->rev >= 3) { - tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0; + tmp = (channel->band == NL80211_BAND_5GHZ) ? 4 : 0; b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); b43_radio_2056_setup(dev, tabent_r3); b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel); } else { - tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050; + tmp = (channel->band == NL80211_BAND_5GHZ) ? 0x0020 : 0x0050; b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); b43_radio_2055_setup(dev, tabent_r2); b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel); @@ -6692,7 +6692,7 @@ static int b43_nphy_op_switch_channel(struct b43_wldev *dev, enum nl80211_channel_type channel_type = cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if ((new_channel < 1) || (new_channel > 14)) return -EINVAL; } else { @@ -6705,7 +6705,7 @@ static int b43_nphy_op_switch_channel(struct b43_wldev *dev, static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) return 1; return 36; } diff --git a/drivers/net/wireless/broadcom/b43/tables_lpphy.c b/drivers/net/wireless/broadcom/b43/tables_lpphy.c index cff187c5616d..ce01e1645df7 100644 --- a/drivers/net/wireless/broadcom/b43/tables_lpphy.c +++ b/drivers/net/wireless/broadcom/b43/tables_lpphy.c @@ -560,7 +560,7 @@ void b2062_upload_init_table(struct b43_wldev *dev) for (i = 0; i < ARRAY_SIZE(b2062_init_tab); i++) { e = &b2062_init_tab[i]; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if (!(e->flags & B206X_FLAG_G)) continue; b43_radio_write(dev, e->offset, e->value_g); @@ -579,7 +579,7 @@ void b2063_upload_init_table(struct b43_wldev *dev) for (i = 0; i < ARRAY_SIZE(b2063_init_tab); i++) { e = &b2063_init_tab[i]; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if (!(e->flags & B206X_FLAG_G)) continue; b43_radio_write(dev, e->offset, e->value_g); @@ -2379,12 +2379,12 @@ static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset, tmp |= data.pga << 8; tmp |= data.gm; if (dev->phy.rev >= 3) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) tmp |= 0x10 << 24; else tmp |= 0x70 << 24; } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) tmp |= 0x14 << 24; else tmp |= 0x7F << 24; @@ -2423,7 +2423,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev) (sprom->boardflags_lo & B43_BFL_HGPA)) lpphy_write_gain_table_bulk(dev, 0, 128, lpphy_rev0_nopa_tx_gain_table); - else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + else if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) lpphy_write_gain_table_bulk(dev, 0, 128, lpphy_rev0_2ghz_tx_gain_table); else @@ -2435,7 +2435,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev) (sprom->boardflags_lo & B43_BFL_HGPA)) lpphy_write_gain_table_bulk(dev, 0, 128, lpphy_rev1_nopa_tx_gain_table); - else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + else if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) lpphy_write_gain_table_bulk(dev, 0, 128, lpphy_rev1_2ghz_tx_gain_table); else @@ -2446,7 +2446,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev) if (sprom->boardflags_hi & B43_BFH_NOPA) lpphy_write_gain_table_bulk(dev, 0, 128, lpphy_rev2_nopa_tx_gain_table); - else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + else if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) lpphy_write_gain_table_bulk(dev, 0, 128, lpphy_rev2_2ghz_tx_gain_table); else diff --git a/drivers/net/wireless/broadcom/b43/tables_nphy.c b/drivers/net/wireless/broadcom/b43/tables_nphy.c index b2f0d245bcf3..44e0957a70cc 100644 --- a/drivers/net/wireless/broadcom/b43/tables_nphy.c +++ b/drivers/net/wireless/broadcom/b43/tables_nphy.c @@ -3502,7 +3502,7 @@ static void b43_nphy_tables_init_rev7_volatile(struct b43_wldev *dev) { 0x2, 0x18, 0x2 }, /* Core 1 */ }; - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) antswlut = sprom->fem.ghz5.antswlut; else antswlut = sprom->fem.ghz2.antswlut; @@ -3566,7 +3566,7 @@ static void b43_nphy_tables_init_rev3(struct b43_wldev *dev) struct ssb_sprom *sprom = dev->dev->bus_sprom; u8 antswlut; - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) antswlut = sprom->fem.ghz5.antswlut; else antswlut = sprom->fem.ghz2.antswlut; @@ -3651,7 +3651,7 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { switch (phy->rev) { case 17: if (phy->radio_rev == 14) @@ -3698,17 +3698,17 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; - enum ieee80211_band band = b43_current_band(dev->wl); + enum nl80211_band band = b43_current_band(dev->wl); struct ssb_sprom *sprom = dev->dev->bus_sprom; if (dev->phy.rev < 3) return b43_ntab_tx_gain_rev0_1_2; /* rev 3+ */ - if ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) || - (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)) { + if ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) || + (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ)) { return b43_nphy_get_ipa_gain_table(dev); - } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + } else if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { switch (phy->rev) { case 6: case 5: @@ -3746,7 +3746,7 @@ const s16 *b43_ntab_get_rf_pwr_offset_table(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { switch (phy->rev) { case 17: if (phy->radio_rev == 14) diff --git a/drivers/net/wireless/broadcom/b43/tables_phy_lcn.c b/drivers/net/wireless/broadcom/b43/tables_phy_lcn.c index e347b8d80ea4..704ef1bcb5b1 100644 --- a/drivers/net/wireless/broadcom/b43/tables_phy_lcn.c +++ b/drivers/net/wireless/broadcom/b43/tables_phy_lcn.c @@ -701,7 +701,7 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev) b43_phy_lcn_upload_static_tables(dev); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { if (sprom->boardflags_lo & B43_BFL_FEM) b43_phy_lcn_load_tx_gain_tab(dev, b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0); diff --git a/drivers/net/wireless/broadcom/b43/xmit.c b/drivers/net/wireless/broadcom/b43/xmit.c index 426dc13c44cd..f6201264de49 100644 --- a/drivers/net/wireless/broadcom/b43/xmit.c +++ b/drivers/net/wireless/broadcom/b43/xmit.c @@ -803,7 +803,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; switch (chanstat & B43_RX_CHAN_PHYTYPE) { case B43_PHYTYPE_A: - status.band = IEEE80211_BAND_5GHZ; + status.band = NL80211_BAND_5GHZ; B43_WARN_ON(1); /* FIXME: We don't really know which value the "chanid" contains. * So the following assignment might be wrong. */ @@ -811,7 +811,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) ieee80211_channel_to_frequency(chanid, status.band); break; case B43_PHYTYPE_G: - status.band = IEEE80211_BAND_2GHZ; + status.band = NL80211_BAND_2GHZ; /* Somewhere between 478.104 and 508.1084 firmware for G-PHY * has been modified to be compatible with N-PHY and others. */ @@ -826,9 +826,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) /* chanid is the SHM channel cookie. Which is the plain * channel number in b43. */ if (chanstat & B43_RX_CHAN_5GHZ) - status.band = IEEE80211_BAND_5GHZ; + status.band = NL80211_BAND_5GHZ; else - status.band = IEEE80211_BAND_2GHZ; + status.band = NL80211_BAND_2GHZ; status.freq = ieee80211_channel_to_frequency(chanid, status.band); break; diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index afc1fb3e38df..83770d2ea057 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -1056,7 +1056,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, - IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ, size, rate); /* Write PLCP in two parts and timing for packet transfer */ @@ -1122,7 +1122,7 @@ static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, IEEE80211_STYPE_PROBE_RESP); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, - IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ, *dest_size, rate); hdr->duration_id = dur; @@ -2719,7 +2719,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, /* Switch the PHY mode (if necessary). */ switch (conf->chandef.chan->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: if (phy->type == B43legacy_PHYTYPE_B) new_phymode = B43legacy_PHYMODE_B; else @@ -2792,7 +2792,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates) { struct ieee80211_supported_band *sband = - dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; + dev->wl->hw->wiphy->bands[NL80211_BAND_2GHZ]; struct ieee80211_rate *rate; int i; u16 basic, direct, offset, basic_offset, rateptr; @@ -3630,13 +3630,13 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev, phy->possible_phymodes = 0; if (have_bphy) { - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + hw->wiphy->bands[NL80211_BAND_2GHZ] = &b43legacy_band_2GHz_BPHY; phy->possible_phymodes |= B43legacy_PHYMODE_B; } if (have_gphy) { - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + hw->wiphy->bands[NL80211_BAND_2GHZ] = &b43legacy_band_2GHz_GPHY; phy->possible_phymodes |= B43legacy_PHYMODE_G; } diff --git a/drivers/net/wireless/broadcom/b43legacy/xmit.c b/drivers/net/wireless/broadcom/b43legacy/xmit.c index 34bf3f0b729f..35ccf400b02c 100644 --- a/drivers/net/wireless/broadcom/b43legacy/xmit.c +++ b/drivers/net/wireless/broadcom/b43legacy/xmit.c @@ -565,7 +565,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) { case B43legacy_PHYTYPE_B: case B43legacy_PHYTYPE_G: - status.band = IEEE80211_BAND_2GHZ; + status.band = NL80211_BAND_2GHZ; status.freq = chanid + 2400; break; default: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index d5c2a27573b4..9a567e263bb1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -144,7 +144,7 @@ static struct ieee80211_rate __wl_rates[] = { #define wl_a_rates_size (wl_g_rates_size - 4) #define CHAN2G(_channel, _freq) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = IEEE80211_CHAN_DISABLED, \ @@ -153,7 +153,7 @@ static struct ieee80211_rate __wl_rates[] = { } #define CHAN5G(_channel) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + (5 * (_channel)), \ .hw_value = (_channel), \ .flags = IEEE80211_CHAN_DISABLED, \ @@ -181,13 +181,13 @@ static struct ieee80211_channel __wl_5ghz_channels[] = { * above is added to the band during setup. */ static const struct ieee80211_supported_band __wl_band_2ghz = { - .band = IEEE80211_BAND_2GHZ, + .band = NL80211_BAND_2GHZ, .bitrates = wl_g_rates, .n_bitrates = wl_g_rates_size, }; static const struct ieee80211_supported_band __wl_band_5ghz = { - .band = IEEE80211_BAND_5GHZ, + .band = NL80211_BAND_5GHZ, .bitrates = wl_a_rates, .n_bitrates = wl_a_rates_size, }; @@ -292,13 +292,13 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, WARN_ON_ONCE(1); } switch (ch->chan->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: ch_inf.band = BRCMU_CHAN_BAND_2G; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: ch_inf.band = BRCMU_CHAN_BAND_5G; break; - case IEEE80211_BAND_60GHZ: + case NL80211_BAND_60GHZ: default: WARN_ON_ONCE(1); } @@ -2679,9 +2679,9 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, channel = bi->ctl_ch; if (channel <= CH_MAX_2G_CHANNEL) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; + band = wiphy->bands[NL80211_BAND_2GHZ]; else - band = wiphy->bands[IEEE80211_BAND_5GHZ]; + band = wiphy->bands[NL80211_BAND_5GHZ]; freq = ieee80211_channel_to_frequency(channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); @@ -2788,9 +2788,9 @@ static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg, cfg->d11inf.decchspec(&ch); if (ch.band == BRCMU_CHAN_BAND_2G) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; + band = wiphy->bands[NL80211_BAND_2GHZ]; else - band = wiphy->bands[IEEE80211_BAND_5GHZ]; + band = wiphy->bands[NL80211_BAND_5GHZ]; freq = ieee80211_channel_to_frequency(ch.chnum, band->band); cfg->channel = freq; @@ -5215,9 +5215,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, cfg->d11inf.decchspec(&ch); if (ch.band == BRCMU_CHAN_BAND_2G) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; + band = wiphy->bands[NL80211_BAND_2GHZ]; else - band = wiphy->bands[IEEE80211_BAND_5GHZ]; + band = wiphy->bands[NL80211_BAND_5GHZ]; freq = ieee80211_channel_to_frequency(ch.chnum, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); @@ -5707,11 +5707,11 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, } wiphy = cfg_to_wiphy(cfg); - band = wiphy->bands[IEEE80211_BAND_2GHZ]; + band = wiphy->bands[NL80211_BAND_2GHZ]; if (band) for (i = 0; i < band->n_channels; i++) band->channels[i].flags = IEEE80211_CHAN_DISABLED; - band = wiphy->bands[IEEE80211_BAND_5GHZ]; + band = wiphy->bands[NL80211_BAND_5GHZ]; if (band) for (i = 0; i < band->n_channels; i++) band->channels[i].flags = IEEE80211_CHAN_DISABLED; @@ -5722,9 +5722,9 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, cfg->d11inf.decchspec(&ch); if (ch.band == BRCMU_CHAN_BAND_2G) { - band = wiphy->bands[IEEE80211_BAND_2GHZ]; + band = wiphy->bands[NL80211_BAND_2GHZ]; } else if (ch.band == BRCMU_CHAN_BAND_5G) { - band = wiphy->bands[IEEE80211_BAND_5GHZ]; + band = wiphy->bands[NL80211_BAND_5GHZ]; } else { brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); continue; @@ -5839,7 +5839,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) return err; } - band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ]; + band = cfg_to_wiphy(cfg)->bands[NL80211_BAND_2GHZ]; list = (struct brcmf_chanspec_list *)pbuf; num_chan = le32_to_cpu(list->count); for (i = 0; i < num_chan; i++) { @@ -5871,11 +5871,11 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) band = WLC_BAND_2G; err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band); if (!err) { - bw_cap[IEEE80211_BAND_2GHZ] = band; + bw_cap[NL80211_BAND_2GHZ] = band; band = WLC_BAND_5G; err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band); if (!err) { - bw_cap[IEEE80211_BAND_5GHZ] = band; + bw_cap[NL80211_BAND_5GHZ] = band; return; } WARN_ON(1); @@ -5890,14 +5890,14 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) switch (mimo_bwcap) { case WLC_N_BW_40ALL: - bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT; + bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT; /* fall-thru */ case WLC_N_BW_20IN2G_40IN5G: - bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT; + bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT; /* fall-thru */ case WLC_N_BW_20ALL: - bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT; - bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT; + bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT; + bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT; break; default: brcmf_err("invalid mimo_bw_cap value\n"); @@ -5938,7 +5938,7 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, __le16 mcs_map; /* not allowed in 2.4G band */ - if (band->band == IEEE80211_BAND_2GHZ) + if (band->band == NL80211_BAND_2GHZ) return; band->vht_cap.vht_supported = true; @@ -5997,8 +5997,8 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy) brcmf_get_bwcap(ifp, bw_cap); } brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n", - nmode, vhtmode, bw_cap[IEEE80211_BAND_2GHZ], - bw_cap[IEEE80211_BAND_5GHZ]); + nmode, vhtmode, bw_cap[NL80211_BAND_2GHZ], + bw_cap[NL80211_BAND_5GHZ]); err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain); if (err) { @@ -6321,7 +6321,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) } band->n_channels = ARRAY_SIZE(__wl_2ghz_channels); - wiphy->bands[IEEE80211_BAND_2GHZ] = band; + wiphy->bands[NL80211_BAND_2GHZ] = band; } if (bandlist[i] == cpu_to_le32(WLC_BAND_5G)) { band = kmemdup(&__wl_band_5ghz, sizeof(__wl_band_5ghz), @@ -6338,7 +6338,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) } band->n_channels = ARRAY_SIZE(__wl_5ghz_channels); - wiphy->bands[IEEE80211_BAND_5GHZ] = band; + wiphy->bands[NL80211_BAND_5GHZ] = band; } } err = brcmf_setup_wiphybands(wiphy); @@ -6604,13 +6604,13 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) kfree(wiphy->iface_combinations[i].limits); } kfree(wiphy->iface_combinations); - if (wiphy->bands[IEEE80211_BAND_2GHZ]) { - kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); - kfree(wiphy->bands[IEEE80211_BAND_2GHZ]); + if (wiphy->bands[NL80211_BAND_2GHZ]) { + kfree(wiphy->bands[NL80211_BAND_2GHZ]->channels); + kfree(wiphy->bands[NL80211_BAND_2GHZ]); } - if (wiphy->bands[IEEE80211_BAND_5GHZ]) { - kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels); - kfree(wiphy->bands[IEEE80211_BAND_5GHZ]); + if (wiphy->bands[NL80211_BAND_5GHZ]) { + kfree(wiphy->bands[NL80211_BAND_5GHZ]->channels); + kfree(wiphy->bands[NL80211_BAND_5GHZ]); } wiphy_free(wiphy); } @@ -6698,8 +6698,8 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, * cfg80211 here that we do and have it decide we can enable * it. But first check if device does support 2G operation. */ - if (wiphy->bands[IEEE80211_BAND_2GHZ]) { - cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap; + if (wiphy->bands[NL80211_BAND_2GHZ]) { + cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap; *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; } err = wiphy_register(wiphy); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index b5a49e564f25..c2ac91df35ed 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -1430,8 +1430,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, freq = ieee80211_channel_to_frequency(ch.chnum, ch.band == BRCMU_CHAN_BAND_2G ? - IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ); + NL80211_BAND_2GHZ : + NL80211_BAND_5GHZ); wdev = &ifp->vif->wdev; cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, 0); @@ -1900,8 +1900,8 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, mgmt_frame_len = e->datalen - sizeof(*rxframe); freq = ieee80211_channel_to_frequency(ch.chnum, ch.band == BRCMU_CHAN_BAND_2G ? - IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ); + NL80211_BAND_2GHZ : + NL80211_BAND_5GHZ); cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, 0); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c index 38bd5890bd53..3a03287fa912 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c @@ -636,7 +636,7 @@ static void brcms_reg_apply_radar_flags(struct wiphy *wiphy) struct ieee80211_channel *ch; int i; - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = wiphy->bands[NL80211_BAND_5GHZ]; if (!sband) return; @@ -666,7 +666,7 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, const struct ieee80211_reg_rule *rule; int band, i; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { sband = wiphy->bands[band]; if (!sband) continue; @@ -710,7 +710,7 @@ static void brcms_reg_notifier(struct wiphy *wiphy, brcms_reg_apply_beaconing_flags(wiphy, request->initiator); /* Disable radio if all channels disallowed by regulatory */ - for (band = 0; !ch_found && band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; !ch_found && band < NUM_NL80211_BANDS; band++) { sband = wiphy->bands[band]; if (!sband) continue; @@ -755,9 +755,9 @@ void brcms_c_regd_init(struct brcms_c_info *wlc) &sup_chan); if (band_idx == BAND_2G_INDEX) - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = wiphy->bands[NL80211_BAND_2GHZ]; else - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = wiphy->bands[NL80211_BAND_5GHZ]; for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index 61ae2768132a..7c2a9a9bc372 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -49,7 +49,7 @@ FIF_PSPOLL) #define CHAN2GHZ(channel, freqency, chflags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (freqency), \ .hw_value = (channel), \ .flags = chflags, \ @@ -58,7 +58,7 @@ } #define CHAN5GHZ(channel, chflags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + 5*(channel), \ .hw_value = (channel), \ .flags = chflags, \ @@ -217,7 +217,7 @@ static struct ieee80211_rate legacy_ratetable[] = { }; static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = { - .band = IEEE80211_BAND_2GHZ, + .band = NL80211_BAND_2GHZ, .channels = brcms_2ghz_chantable, .n_channels = ARRAY_SIZE(brcms_2ghz_chantable), .bitrates = legacy_ratetable, @@ -238,7 +238,7 @@ static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = { }; static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = { - .band = IEEE80211_BAND_5GHZ, + .band = NL80211_BAND_5GHZ, .channels = brcms_5ghz_nphy_chantable, .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable), .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET, @@ -1026,8 +1026,8 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw) int has_5g = 0; u16 phy_type; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL; phy_type = brcms_c_get_phy_type(wl->wlc, 0); if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { @@ -1038,7 +1038,7 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw) band->ht_cap.mcs.rx_mask[1] = 0; band->ht_cap.mcs.rx_highest = cpu_to_le16(72); } - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; + hw->wiphy->bands[NL80211_BAND_2GHZ] = band; } else { return -EPERM; } @@ -1049,7 +1049,7 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw) if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { band = &wlc->bandstate[BAND_5G_INDEX]->band; *band = brcms_band_5GHz_nphy_template; - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; + hw->wiphy->bands[NL80211_BAND_5GHZ] = band; } else { return -EPERM; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c index 218cbc8bf3a7..e16ee60639f5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c @@ -7076,7 +7076,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, channel = BRCMS_CHAN_CHANNEL(rxh->RxChan); rx_status->band = - channel > 14 ? IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; + channel > 14 ? NL80211_BAND_5GHZ : NL80211_BAND_2GHZ; rx_status->freq = ieee80211_channel_to_frequency(channel, rx_status->band); @@ -7143,7 +7143,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, * a subset of the 2.4G rates. See bitrates field * of brcms_band_5GHz_nphy (in mac80211_if.c). */ - if (rx_status->band == IEEE80211_BAND_5GHZ) + if (rx_status->band == NL80211_BAND_5GHZ) rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET; /* Determine short preamble and rate_idx */ diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index d2353f6e5214..4bd9e2b97e86 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -5836,7 +5836,7 @@ static int airo_get_freq(struct net_device *dev, ch = le16_to_cpu(status_rid.channel); if((ch > 0) && (ch < 15)) { fwrq->m = 100000 * - ieee80211_channel_to_frequency(ch, IEEE80211_BAND_2GHZ); + ieee80211_channel_to_frequency(ch, NL80211_BAND_2GHZ); fwrq->e = 1; } else { fwrq->m = ch; @@ -6894,7 +6894,7 @@ static int airo_get_range(struct net_device *dev, for(i = 0; i < 14; i++) { range->freq[k].i = i + 1; /* List index */ range->freq[k].m = 100000 * - ieee80211_channel_to_frequency(i + 1, IEEE80211_BAND_2GHZ); + ieee80211_channel_to_frequency(i + 1, NL80211_BAND_2GHZ); range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */ } range->num_frequency = k; @@ -7302,7 +7302,7 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = le16_to_cpu(bss->dsChannel); iwe.u.freq.m = 100000 * - ieee80211_channel_to_frequency(iwe.u.freq.m, IEEE80211_BAND_2GHZ); + ieee80211_channel_to_frequency(iwe.u.freq.m, NL80211_BAND_2GHZ); iwe.u.freq.e = 1; current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index 717320b17622..e1e42ed6c412 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -1913,7 +1913,7 @@ static int ipw2100_wdev_init(struct net_device *dev) if (geo->bg_channels) { struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band; - bg_band->band = IEEE80211_BAND_2GHZ; + bg_band->band = NL80211_BAND_2GHZ; bg_band->n_channels = geo->bg_channels; bg_band->channels = kcalloc(geo->bg_channels, sizeof(struct ieee80211_channel), @@ -1924,7 +1924,7 @@ static int ipw2100_wdev_init(struct net_device *dev) } /* translate geo->bg to bg_band.channels */ for (i = 0; i < geo->bg_channels; i++) { - bg_band->channels[i].band = IEEE80211_BAND_2GHZ; + bg_band->channels[i].band = NL80211_BAND_2GHZ; bg_band->channels[i].center_freq = geo->bg[i].freq; bg_band->channels[i].hw_value = geo->bg[i].channel; bg_band->channels[i].max_power = geo->bg[i].max_power; @@ -1945,7 +1945,7 @@ static int ipw2100_wdev_init(struct net_device *dev) bg_band->bitrates = ipw2100_bg_rates; bg_band->n_bitrates = RATE_COUNT; - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; + wdev->wiphy->bands[NL80211_BAND_2GHZ] = bg_band; } wdev->wiphy->cipher_suites = ipw_cipher_suites; diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index ed0adaf1eec4..dac13cf42e9f 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -11359,7 +11359,7 @@ static int ipw_wdev_init(struct net_device *dev) if (geo->bg_channels) { struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band; - bg_band->band = IEEE80211_BAND_2GHZ; + bg_band->band = NL80211_BAND_2GHZ; bg_band->n_channels = geo->bg_channels; bg_band->channels = kcalloc(geo->bg_channels, sizeof(struct ieee80211_channel), @@ -11370,7 +11370,7 @@ static int ipw_wdev_init(struct net_device *dev) } /* translate geo->bg to bg_band.channels */ for (i = 0; i < geo->bg_channels; i++) { - bg_band->channels[i].band = IEEE80211_BAND_2GHZ; + bg_band->channels[i].band = NL80211_BAND_2GHZ; bg_band->channels[i].center_freq = geo->bg[i].freq; bg_band->channels[i].hw_value = geo->bg[i].channel; bg_band->channels[i].max_power = geo->bg[i].max_power; @@ -11391,14 +11391,14 @@ static int ipw_wdev_init(struct net_device *dev) bg_band->bitrates = ipw2200_bg_rates; bg_band->n_bitrates = ipw2200_num_bg_rates; - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; + wdev->wiphy->bands[NL80211_BAND_2GHZ] = bg_band; } /* fill-out priv->ieee->a_band */ if (geo->a_channels) { struct ieee80211_supported_band *a_band = &priv->ieee->a_band; - a_band->band = IEEE80211_BAND_5GHZ; + a_band->band = NL80211_BAND_5GHZ; a_band->n_channels = geo->a_channels; a_band->channels = kcalloc(geo->a_channels, sizeof(struct ieee80211_channel), @@ -11409,7 +11409,7 @@ static int ipw_wdev_init(struct net_device *dev) } /* translate geo->a to a_band.channels */ for (i = 0; i < geo->a_channels; i++) { - a_band->channels[i].band = IEEE80211_BAND_5GHZ; + a_band->channels[i].band = NL80211_BAND_5GHZ; a_band->channels[i].center_freq = geo->a[i].freq; a_band->channels[i].hw_value = geo->a[i].channel; a_band->channels[i].max_power = geo->a[i].max_power; @@ -11430,7 +11430,7 @@ static int ipw_wdev_init(struct net_device *dev) a_band->bitrates = ipw2200_a_rates; a_band->n_bitrates = ipw2200_num_a_rates; - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; + wdev->wiphy->bands[NL80211_BAND_5GHZ] = a_band; } wdev->wiphy->cipher_suites = ipw_cipher_suites; diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c index af1b3e6839fa..466912eb2d87 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c @@ -1547,7 +1547,7 @@ il3945_irq_tasklet(struct il_priv *il) } static int -il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band, +il3945_get_channels_for_scan(struct il_priv *il, enum nl80211_band band, u8 is_active, u8 n_probes, struct il3945_scan_channel *scan_ch, struct ieee80211_vif *vif) @@ -1618,7 +1618,7 @@ il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band, /* scan_pwr_info->tpc.dsp_atten; */ /*scan_pwr_info->tpc.tx_gain; */ - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); @@ -2534,7 +2534,7 @@ il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif) }; struct il3945_scan_cmd *scan; u8 n_probes = 0; - enum ieee80211_band band; + enum nl80211_band band; bool is_active = false; int ret; u16 len; @@ -2615,14 +2615,14 @@ il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif) /* flags + rate selection */ switch (il->scan_band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate = RATE_1M_PLCP; - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: scan->tx_cmd.rate = RATE_6M_PLCP; - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; break; default: IL_WARN("Invalid scan band\n"); @@ -3507,7 +3507,7 @@ il3945_init_drv(struct il_priv *il) il->ieee_channels = NULL; il->ieee_rates = NULL; - il->band = IEEE80211_BAND_2GHZ; + il->band = NL80211_BAND_2GHZ; il->iw_mode = NL80211_IFTYPE_STATION; il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF; @@ -3582,13 +3582,13 @@ il3945_setup_mac(struct il_priv *il) /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; - if (il->bands[IEEE80211_BAND_2GHZ].n_channels) - il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &il->bands[IEEE80211_BAND_2GHZ]; + if (il->bands[NL80211_BAND_2GHZ].n_channels) + il->hw->wiphy->bands[NL80211_BAND_2GHZ] = + &il->bands[NL80211_BAND_2GHZ]; - if (il->bands[IEEE80211_BAND_5GHZ].n_channels) - il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &il->bands[IEEE80211_BAND_5GHZ]; + if (il->bands[NL80211_BAND_5GHZ].n_channels) + il->hw->wiphy->bands[NL80211_BAND_5GHZ] = + &il->bands[NL80211_BAND_5GHZ]; il_leds_init(il); @@ -3761,7 +3761,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_release_irq; } - il_set_rxon_channel(il, &il->bands[IEEE80211_BAND_2GHZ].channels[5]); + il_set_rxon_channel(il, &il->bands[NL80211_BAND_2GHZ].channels[5]); il3945_setup_deferred_work(il); il3945_setup_handlers(il); il_power_initialize(il); diff --git a/drivers/net/wireless/intel/iwlegacy/3945-rs.c b/drivers/net/wireless/intel/iwlegacy/3945-rs.c index 76b0729ade17..03ad9b8b55f4 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-rs.c @@ -97,7 +97,7 @@ static struct il3945_tpt_entry il3945_tpt_table_g[] = { #define RATE_RETRY_TH 15 static u8 -il3945_get_rate_idx_by_rssi(s32 rssi, enum ieee80211_band band) +il3945_get_rate_idx_by_rssi(s32 rssi, enum nl80211_band band) { u32 idx = 0; u32 table_size = 0; @@ -107,11 +107,11 @@ il3945_get_rate_idx_by_rssi(s32 rssi, enum ieee80211_band band) rssi = IL_MIN_RSSI_VAL; switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: tpt_table = il3945_tpt_table_g; table_size = ARRAY_SIZE(il3945_tpt_table_g); break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: tpt_table = il3945_tpt_table_a; table_size = ARRAY_SIZE(il3945_tpt_table_a); break; @@ -380,7 +380,7 @@ il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id) il->_3945.sta_supp_rates = sta->supp_rates[sband->band]; /* For 5 GHz band it start at IL_FIRST_OFDM_RATE */ - if (sband->band == IEEE80211_BAND_5GHZ) { + if (sband->band == NL80211_BAND_5GHZ) { rs_sta->last_txrate_idx += IL_FIRST_OFDM_RATE; il->_3945.sta_supp_rates <<= IL_FIRST_OFDM_RATE; } @@ -541,7 +541,7 @@ il3945_rs_tx_status(void *il_rate, struct ieee80211_supported_band *sband, static u16 il3945_get_adjacent_rate(struct il3945_rs_sta *rs_sta, u8 idx, u16 rate_mask, - enum ieee80211_band band) + enum nl80211_band band) { u8 high = RATE_INVALID; u8 low = RATE_INVALID; @@ -549,7 +549,7 @@ il3945_get_adjacent_rate(struct il3945_rs_sta *rs_sta, u8 idx, u16 rate_mask, /* 802.11A walks to the next literal adjacent rate in * the rate table */ - if (unlikely(band == IEEE80211_BAND_5GHZ)) { + if (unlikely(band == NL80211_BAND_5GHZ)) { int i; u32 mask; @@ -657,14 +657,14 @@ il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, /* get user max rate if set */ max_rate_idx = txrc->max_rate_idx; - if (sband->band == IEEE80211_BAND_5GHZ && max_rate_idx != -1) + if (sband->band == NL80211_BAND_5GHZ && max_rate_idx != -1) max_rate_idx += IL_FIRST_OFDM_RATE; if (max_rate_idx < 0 || max_rate_idx >= RATE_COUNT) max_rate_idx = -1; idx = min(rs_sta->last_txrate_idx & 0xffff, RATE_COUNT_3945 - 1); - if (sband->band == IEEE80211_BAND_5GHZ) + if (sband->band == NL80211_BAND_5GHZ) rate_mask = rate_mask << IL_FIRST_OFDM_RATE; spin_lock_irqsave(&rs_sta->lock, flags); @@ -806,7 +806,7 @@ il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, out: - if (sband->band == IEEE80211_BAND_5GHZ) { + if (sband->band == NL80211_BAND_5GHZ) { if (WARN_ON_ONCE(idx < IL_FIRST_OFDM_RATE)) idx = IL_FIRST_OFDM_RATE; rs_sta->last_txrate_idx = idx; @@ -935,7 +935,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rs_sta->tgg = 0; switch (il->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: /* TODO: this always does G, not a regression */ if (il->active.flags & RXON_FLG_TGG_PROTECT_MSK) { rs_sta->tgg = 1; @@ -943,7 +943,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) } else rs_sta->expected_tpt = il3945_expected_tpt_g; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: rs_sta->expected_tpt = il3945_expected_tpt_a; break; default: diff --git a/drivers/net/wireless/intel/iwlegacy/3945.c b/drivers/net/wireless/intel/iwlegacy/3945.c index 93bdf684babe..7bcedbb53d94 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945.c +++ b/drivers/net/wireless/intel/iwlegacy/3945.c @@ -255,13 +255,13 @@ il3945_rs_next_rate(struct il_priv *il, int rate) int next_rate = il3945_get_prev_ieee_rate(rate); switch (il->band) { - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: if (rate == RATE_12M_IDX) next_rate = RATE_9M_IDX; else if (rate == RATE_6M_IDX) next_rate = RATE_6M_IDX; break; - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: if (!(il->_3945.sta_supp_rates & IL_OFDM_RATES_MASK) && il_is_associated(il)) { if (rate == RATE_11M_IDX) @@ -349,7 +349,7 @@ il3945_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) /* Fill the MRR chain with some info about on-chip retransmissions */ rate_idx = il3945_hwrate_to_plcp_idx(tx_resp->rate); - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) rate_idx -= IL_FIRST_OFDM_RATE; fail = tx_resp->failure_frame; @@ -554,14 +554,14 @@ il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) rx_status.mactime = le64_to_cpu(rx_end->timestamp); rx_status.band = (rx_hdr-> - phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ; + phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? NL80211_BAND_2GHZ : + NL80211_BAND_5GHZ; rx_status.freq = ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel), rx_status.band); rx_status.rate_idx = il3945_hwrate_to_plcp_idx(rx_hdr->rate); - if (rx_status.band == IEEE80211_BAND_5GHZ) + if (rx_status.band == NL80211_BAND_5GHZ) rx_status.rate_idx -= IL_FIRST_OFDM_RATE; rx_status.antenna = @@ -1409,7 +1409,7 @@ il3945_send_tx_power(struct il_priv *il) chan = le16_to_cpu(il->active.channel); - txpower.band = (il->band == IEEE80211_BAND_5GHZ) ? 0 : 1; + txpower.band = (il->band == NL80211_BAND_5GHZ) ? 0 : 1; ch_info = il_get_channel_info(il, il->band, chan); if (!ch_info) { IL_ERR("Failed to get channel info for channel %d [%d]\n", chan, @@ -2310,7 +2310,7 @@ il3945_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif, il3945_sync_sta(il, vif_priv->ibss_bssid_sta_id, (il->band == - IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP : + NL80211_BAND_5GHZ) ? RATE_6M_PLCP : RATE_1M_PLCP); il3945_rate_scale_init(il->hw, vif_priv->ibss_bssid_sta_id); @@ -2343,7 +2343,7 @@ il3945_init_hw_rate_table(struct il_priv *il) } switch (il->band) { - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: D_RATE("Select A mode rate scale\n"); /* If one of the following CCK rates is used, * have it fall back to the 6M OFDM rate */ @@ -2359,7 +2359,7 @@ il3945_init_hw_rate_table(struct il_priv *il) il3945_rates[IL_FIRST_OFDM_RATE].table_rs_idx; break; - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: D_RATE("Select B/G mode rate scale\n"); /* If an OFDM rate is used, have it fall back to the * 1M CCK rates */ diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index f9ed48070e17..a91d170a614b 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -457,7 +457,7 @@ il4965_rxq_stop(struct il_priv *il) } int -il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) +il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band) { int idx = 0; int band_offset = 0; @@ -468,7 +468,7 @@ il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) return idx; /* Legacy rate format, search for match in table */ } else { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) band_offset = IL_FIRST_OFDM_RATE; for (idx = band_offset; idx < RATE_COUNT_LEGACY; idx++) if (il_rates[idx].plcp == (rate_n_flags & 0xFF)) @@ -688,8 +688,8 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) rx_status.mactime = le64_to_cpu(phy_res->timestamp); rx_status.band = (phy_res-> - phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ; + phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? NL80211_BAND_2GHZ : + NL80211_BAND_5GHZ; rx_status.freq = ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel), rx_status.band); @@ -766,7 +766,7 @@ il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb) static int il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif, - enum ieee80211_band band, u8 is_active, + enum nl80211_band band, u8 is_active, u8 n_probes, struct il_scan_channel *scan_ch) { struct ieee80211_channel *chan; @@ -822,7 +822,7 @@ il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif, * power level: * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; */ - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); @@ -870,7 +870,7 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) u32 rate_flags = 0; u16 cmd_len; u16 rx_chain = 0; - enum ieee80211_band band; + enum nl80211_band band; u8 n_probes = 0; u8 rx_ant = il->hw_params.valid_rx_ant; u8 rate; @@ -944,7 +944,7 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; switch (il->scan_band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; chan_mod = le32_to_cpu(il->active.flags & RXON_FLG_CHANNEL_MODE_MSK) >> @@ -956,7 +956,7 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) rate_flags = RATE_MCS_CCK_MSK; } break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: rate = RATE_6M_PLCP; break; default: @@ -1590,7 +1590,7 @@ il4965_tx_cmd_build_rate(struct il_priv *il, || rate_idx > RATE_COUNT_LEGACY) rate_idx = rate_lowest_index(&il->bands[info->band], sta); /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) rate_idx += IL_FIRST_OFDM_RATE; /* Get PLCP rate for tx_cmd->rate_n_flags */ rate_plcp = il_rates[rate_idx].plcp; @@ -3051,7 +3051,7 @@ il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id) } /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ - if (il->band == IEEE80211_BAND_5GHZ) + if (il->band == NL80211_BAND_5GHZ) r = RATE_6M_IDX; else r = RATE_1M_IDX; @@ -5790,12 +5790,12 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) hw->max_listen_interval = IL_CONN_MAX_LISTEN_INTERVAL; - if (il->bands[IEEE80211_BAND_2GHZ].n_channels) - il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &il->bands[IEEE80211_BAND_2GHZ]; - if (il->bands[IEEE80211_BAND_5GHZ].n_channels) - il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &il->bands[IEEE80211_BAND_5GHZ]; + if (il->bands[NL80211_BAND_2GHZ].n_channels) + il->hw->wiphy->bands[NL80211_BAND_2GHZ] = + &il->bands[NL80211_BAND_2GHZ]; + if (il->bands[NL80211_BAND_5GHZ].n_channels) + il->hw->wiphy->bands[NL80211_BAND_5GHZ] = + &il->bands[NL80211_BAND_5GHZ]; il_leds_init(il); @@ -6368,7 +6368,7 @@ il4965_init_drv(struct il_priv *il) il->ieee_channels = NULL; il->ieee_rates = NULL; - il->band = IEEE80211_BAND_2GHZ; + il->band = NL80211_BAND_2GHZ; il->iw_mode = NL80211_IFTYPE_STATION; il->current_ht_config.smps = IEEE80211_SMPS_STATIC; @@ -6480,7 +6480,7 @@ il4965_set_hw_params(struct il_priv *il) il->hw_params.max_data_size = IL49_RTC_DATA_SIZE; il->hw_params.max_inst_size = IL49_RTC_INST_SIZE; il->hw_params.max_bsm_size = BSM_SRAM_SIZE; - il->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ); + il->hw_params.ht40_channel = BIT(NL80211_BAND_5GHZ); il->hw_params.rx_wrt_ptr_reg = FH49_RSCSR_CHNL0_WPTR; diff --git a/drivers/net/wireless/intel/iwlegacy/4965-rs.c b/drivers/net/wireless/intel/iwlegacy/4965-rs.c index bac60b2bc3f0..a867ae7f4095 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-rs.c @@ -549,7 +549,7 @@ il4965_rate_n_flags_from_tbl(struct il_priv *il, struct il_scale_tbl_info *tbl, */ static int il4965_rs_get_tbl_info_from_mcs(const u32 rate_n_flags, - enum ieee80211_band band, + enum nl80211_band band, struct il_scale_tbl_info *tbl, int *rate_idx) { u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); @@ -574,7 +574,7 @@ il4965_rs_get_tbl_info_from_mcs(const u32 rate_n_flags, /* legacy rate format */ if (!(rate_n_flags & RATE_MCS_HT_MSK)) { if (il4965_num_of_ant == 1) { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -743,7 +743,7 @@ il4965_rs_get_lower_rate(struct il_lq_sta *lq_sta, if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_idx)) { switch_to_legacy = 1; scale_idx = rs_ht_to_legacy[scale_idx]; - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -762,7 +762,7 @@ il4965_rs_get_lower_rate(struct il_lq_sta *lq_sta, /* Mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { /* supp_rates has no CCK bits in A mode */ - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) rate_mask = (u16) (rate_mask & (lq_sta->supp_rates << IL_FIRST_OFDM_RATE)); @@ -851,7 +851,7 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband, table = &lq_sta->lq; tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); il4965_rs_get_tbl_info_from_mcs(tx_rate, il->band, &tbl_type, &rs_idx); - if (il->band == IEEE80211_BAND_5GHZ) + if (il->band == NL80211_BAND_5GHZ) rs_idx -= IL_FIRST_OFDM_RATE; mac_flags = info->status.rates[0].flags; mac_idx = info->status.rates[0].idx; @@ -864,7 +864,7 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband, * mac80211 HT idx is always zero-idxed; we need to move * HT OFDM rates after CCK rates in 2.4 GHz band */ - if (il->band == IEEE80211_BAND_2GHZ) + if (il->band == NL80211_BAND_2GHZ) mac_idx += IL_FIRST_OFDM_RATE; } /* Here we actually compare this rate to the latest LQ command */ @@ -1816,7 +1816,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) /* supp_rates has no CCK bits in A mode */ rate_scale_idx_msk = (u16) (rate_mask & @@ -2212,7 +2212,7 @@ il4965_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, /* Get max rate if user set max rate */ if (lq_sta) { lq_sta->max_rate_idx = txrc->max_rate_idx; - if (sband->band == IEEE80211_BAND_5GHZ && + if (sband->band == NL80211_BAND_5GHZ && lq_sta->max_rate_idx != -1) lq_sta->max_rate_idx += IL_FIRST_OFDM_RATE; if (lq_sta->max_rate_idx < 0 || @@ -2258,11 +2258,11 @@ il4965_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, } else { /* Check for invalid rates */ if (rate_idx < 0 || rate_idx >= RATE_COUNT_LEGACY || - (sband->band == IEEE80211_BAND_5GHZ && + (sband->band == NL80211_BAND_5GHZ && rate_idx < IL_FIRST_OFDM_RATE)) rate_idx = rate_lowest_index(sband, sta); /* On valid 5 GHz rate, adjust idx */ - else if (sband->band == IEEE80211_BAND_5GHZ) + else if (sband->band == NL80211_BAND_5GHZ) rate_idx -= IL_FIRST_OFDM_RATE; info->control.rates[0].flags = 0; } @@ -2362,7 +2362,7 @@ il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id) /* Set last_txrate_idx to lowest rate */ lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); - if (sband->band == IEEE80211_BAND_5GHZ) + if (sband->band == NL80211_BAND_5GHZ) lq_sta->last_txrate_idx += IL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; diff --git a/drivers/net/wireless/intel/iwlegacy/4965.c b/drivers/net/wireless/intel/iwlegacy/4965.c index fe47db9c20cd..c3c638ed0ed7 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965.c +++ b/drivers/net/wireless/intel/iwlegacy/4965.c @@ -1267,7 +1267,7 @@ il4965_send_tx_power(struct il_priv *il) "TX Power requested while scanning!\n")) return -EAGAIN; - band = il->band == IEEE80211_BAND_2GHZ; + band = il->band == NL80211_BAND_2GHZ; is_ht40 = iw4965_is_ht40_channel(il->active.flags); @@ -1480,7 +1480,7 @@ il4965_hw_channel_switch(struct il_priv *il, u8 switch_count; u16 beacon_interval = le16_to_cpu(il->timing.beacon_interval); struct ieee80211_vif *vif = il->vif; - band = (il->band == IEEE80211_BAND_2GHZ); + band = (il->band == NL80211_BAND_2GHZ); if (WARN_ON_ONCE(vif == NULL)) return -EIO; @@ -1918,7 +1918,7 @@ struct il_cfg il4965_cfg = { * Force use of chains B and C for scan RX on 5 GHz band * because the device has off-channel reception on chain A. */ - .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, + .scan_rx_antennas[NL80211_BAND_5GHZ] = ANT_BC, .eeprom_size = IL4965_EEPROM_IMG_SIZE, .num_of_queues = IL49_NUM_QUEUES, diff --git a/drivers/net/wireless/intel/iwlegacy/4965.h b/drivers/net/wireless/intel/iwlegacy/4965.h index e432715e02d8..527e8b531aed 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965.h +++ b/drivers/net/wireless/intel/iwlegacy/4965.h @@ -68,7 +68,7 @@ void il4965_rx_replenish(struct il_priv *il); void il4965_rx_replenish_now(struct il_priv *il); void il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq); int il4965_rxq_stop(struct il_priv *il); -int il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); +int il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band); void il4965_rx_handle(struct il_priv *il); /* tx */ diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index 2cc3d42bbab7..eb24b9241bb2 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -860,7 +860,7 @@ il_init_band_reference(const struct il_priv *il, int eep_band, * Does not set up a command, or touch hardware. */ static int -il_mod_ht40_chan_info(struct il_priv *il, enum ieee80211_band band, u16 channel, +il_mod_ht40_chan_info(struct il_priv *il, enum nl80211_band band, u16 channel, const struct il_eeprom_channel *eeprom_ch, u8 clear_ht40_extension_channel) { @@ -945,7 +945,7 @@ il_init_channel_map(struct il_priv *il) ch_info->channel = eeprom_ch_idx[ch]; ch_info->band = (band == - 1) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + 1) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; /* permanently store EEPROM's channel regulatory flags * and max power in channel info database. */ @@ -1003,14 +1003,14 @@ il_init_channel_map(struct il_priv *il) /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ for (band = 6; band <= 7; band++) { - enum ieee80211_band ieeeband; + enum nl80211_band ieeeband; il_init_band_reference(il, band, &eeprom_ch_count, &eeprom_ch_info, &eeprom_ch_idx); /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ ieeeband = - (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + (band == 6) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { @@ -1048,19 +1048,19 @@ EXPORT_SYMBOL(il_free_channel_map); * Based on band and channel number. */ const struct il_channel_info * -il_get_channel_info(const struct il_priv *il, enum ieee80211_band band, +il_get_channel_info(const struct il_priv *il, enum nl80211_band band, u16 channel) { int i; switch (band) { - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: for (i = 14; i < il->channel_count; i++) { if (il->channel_info[i].channel == channel) return &il->channel_info[i]; } break; - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: if (channel >= 1 && channel <= 14) return &il->channel_info[channel - 1]; break; @@ -1457,7 +1457,7 @@ il_hdl_scan_complete(struct il_priv *il, struct il_rx_buf *rxb) clear_bit(S_SCAN_HW, &il->status); D_SCAN("Scan on %sGHz took %dms\n", - (il->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", + (il->scan_band == NL80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(jiffies - il->scan_start)); queue_work(il->workqueue, &il->scan_completed); @@ -1475,10 +1475,10 @@ il_setup_rx_scan_handlers(struct il_priv *il) EXPORT_SYMBOL(il_setup_rx_scan_handlers); u16 -il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band, +il_get_active_dwell_time(struct il_priv *il, enum nl80211_band band, u8 n_probes) { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) return IL_ACTIVE_DWELL_TIME_52 + IL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); else @@ -1488,14 +1488,14 @@ il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band, EXPORT_SYMBOL(il_get_active_dwell_time); u16 -il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band, +il_get_passive_dwell_time(struct il_priv *il, enum nl80211_band band, struct ieee80211_vif *vif) { u16 value; u16 passive = (band == - IEEE80211_BAND_2GHZ) ? IL_PASSIVE_DWELL_BASE + + NL80211_BAND_2GHZ) ? IL_PASSIVE_DWELL_BASE + IL_PASSIVE_DWELL_TIME_24 : IL_PASSIVE_DWELL_BASE + IL_PASSIVE_DWELL_TIME_52; @@ -1520,10 +1520,10 @@ void il_init_scan_params(struct il_priv *il) { u8 ant_idx = fls(il->hw_params.valid_tx_ant) - 1; - if (!il->scan_tx_ant[IEEE80211_BAND_5GHZ]) - il->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; - if (!il->scan_tx_ant[IEEE80211_BAND_2GHZ]) - il->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; + if (!il->scan_tx_ant[NL80211_BAND_5GHZ]) + il->scan_tx_ant[NL80211_BAND_5GHZ] = ant_idx; + if (!il->scan_tx_ant[NL80211_BAND_2GHZ]) + il->scan_tx_ant[NL80211_BAND_2GHZ] = ant_idx; } EXPORT_SYMBOL(il_init_scan_params); @@ -2003,7 +2003,7 @@ il_prep_station(struct il_priv *il, const u8 *addr, bool is_ap, il_set_ht_add_station(il, sta_id, sta); /* 3945 only */ - rate = (il->band == IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP : RATE_1M_PLCP; + rate = (il->band == NL80211_BAND_5GHZ) ? RATE_6M_PLCP : RATE_1M_PLCP; /* Turn on both antennas for the station... */ station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); @@ -3382,7 +3382,7 @@ EXPORT_SYMBOL(il_bcast_addr); static void il_init_ht_hw_capab(const struct il_priv *il, struct ieee80211_sta_ht_cap *ht_info, - enum ieee80211_band band) + enum nl80211_band band) { u16 max_bit_rate = 0; u8 rx_chains_num = il->hw_params.rx_chains_num; @@ -3443,8 +3443,8 @@ il_init_geos(struct il_priv *il) int i = 0; s8 max_tx_power = 0; - if (il->bands[IEEE80211_BAND_2GHZ].n_bitrates || - il->bands[IEEE80211_BAND_5GHZ].n_bitrates) { + if (il->bands[NL80211_BAND_2GHZ].n_bitrates || + il->bands[NL80211_BAND_5GHZ].n_bitrates) { D_INFO("Geography modes already initialized.\n"); set_bit(S_GEO_CONFIGURED, &il->status); return 0; @@ -3465,23 +3465,23 @@ il_init_geos(struct il_priv *il) } /* 5.2GHz channels start after the 2.4GHz channels */ - sband = &il->bands[IEEE80211_BAND_5GHZ]; + sband = &il->bands[NL80211_BAND_5GHZ]; sband->channels = &channels[ARRAY_SIZE(il_eeprom_band_1)]; /* just OFDM */ sband->bitrates = &rates[IL_FIRST_OFDM_RATE]; sband->n_bitrates = RATE_COUNT_LEGACY - IL_FIRST_OFDM_RATE; if (il->cfg->sku & IL_SKU_N) - il_init_ht_hw_capab(il, &sband->ht_cap, IEEE80211_BAND_5GHZ); + il_init_ht_hw_capab(il, &sband->ht_cap, NL80211_BAND_5GHZ); - sband = &il->bands[IEEE80211_BAND_2GHZ]; + sband = &il->bands[NL80211_BAND_2GHZ]; sband->channels = channels; /* OFDM & CCK */ sband->bitrates = rates; sband->n_bitrates = RATE_COUNT_LEGACY; if (il->cfg->sku & IL_SKU_N) - il_init_ht_hw_capab(il, &sband->ht_cap, IEEE80211_BAND_2GHZ); + il_init_ht_hw_capab(il, &sband->ht_cap, NL80211_BAND_2GHZ); il->ieee_channels = channels; il->ieee_rates = rates; @@ -3532,7 +3532,7 @@ il_init_geos(struct il_priv *il) il->tx_power_user_lmt = max_tx_power; il->tx_power_next = max_tx_power; - if (il->bands[IEEE80211_BAND_5GHZ].n_channels == 0 && + if (il->bands[NL80211_BAND_5GHZ].n_channels == 0 && (il->cfg->sku & IL_SKU_A)) { IL_INFO("Incorrectly detected BG card as ABG. " "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n", @@ -3541,8 +3541,8 @@ il_init_geos(struct il_priv *il) } IL_INFO("Tunable channels: %d 802.11bg, %d 802.11a channels\n", - il->bands[IEEE80211_BAND_2GHZ].n_channels, - il->bands[IEEE80211_BAND_5GHZ].n_channels); + il->bands[NL80211_BAND_2GHZ].n_channels, + il->bands[NL80211_BAND_5GHZ].n_channels); set_bit(S_GEO_CONFIGURED, &il->status); @@ -3563,7 +3563,7 @@ il_free_geos(struct il_priv *il) EXPORT_SYMBOL(il_free_geos); static bool -il_is_channel_extension(struct il_priv *il, enum ieee80211_band band, +il_is_channel_extension(struct il_priv *il, enum nl80211_band band, u16 channel, u8 extension_chan_offset) { const struct il_channel_info *ch_info; @@ -3926,14 +3926,14 @@ EXPORT_SYMBOL(il_set_rxon_ht); /* Return valid, unused, channel for a passive scan to reset the RF */ u8 -il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band) +il_get_single_channel_number(struct il_priv *il, enum nl80211_band band) { const struct il_channel_info *ch_info; int i; u8 channel = 0; u8 min, max; - if (band == IEEE80211_BAND_5GHZ) { + if (band == NL80211_BAND_5GHZ) { min = 14; max = il->channel_count; } else { @@ -3965,14 +3965,14 @@ EXPORT_SYMBOL(il_get_single_channel_number); int il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch) { - enum ieee80211_band band = ch->band; + enum nl80211_band band = ch->band; u16 channel = ch->hw_value; if (le16_to_cpu(il->staging.channel) == channel && il->band == band) return 0; il->staging.channel = cpu_to_le16(channel); - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) il->staging.flags &= ~RXON_FLG_BAND_24G_MSK; else il->staging.flags |= RXON_FLG_BAND_24G_MSK; @@ -3986,10 +3986,10 @@ il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch) EXPORT_SYMBOL(il_set_rxon_channel); void -il_set_flags_for_band(struct il_priv *il, enum ieee80211_band band, +il_set_flags_for_band(struct il_priv *il, enum nl80211_band band, struct ieee80211_vif *vif) { - if (band == IEEE80211_BAND_5GHZ) { + if (band == NL80211_BAND_5GHZ) { il->staging.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -5415,7 +5415,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_ERP_CTS_PROT) { D_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && il->band != IEEE80211_BAND_5GHZ) + if (bss_conf->use_cts_prot && il->band != NL80211_BAND_5GHZ) il->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; else il->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h index ce52cf114fde..726ede391cb9 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.h +++ b/drivers/net/wireless/intel/iwlegacy/common.h @@ -432,7 +432,7 @@ u16 il_eeprom_query16(const struct il_priv *il, size_t offset); int il_init_channel_map(struct il_priv *il); void il_free_channel_map(struct il_priv *il); const struct il_channel_info *il_get_channel_info(const struct il_priv *il, - enum ieee80211_band band, + enum nl80211_band band, u16 channel); #define IL_NUM_SCAN_RATES (2) @@ -497,7 +497,7 @@ struct il_channel_info { u8 group_idx; /* 0-4, maps channel to group1/2/3/4/5 */ u8 band_idx; /* 0-4, maps channel to band1/2/3/4/5 */ - enum ieee80211_band band; + enum nl80211_band band; /* HT40 channel info */ s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ @@ -811,7 +811,7 @@ struct il_sensitivity_ranges { * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR * @max_stations: * @ht40_channel: is 40MHz width possible in band 2.4 - * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) + * BIT(NL80211_BAND_5GHZ) BIT(NL80211_BAND_5GHZ) * @sw_crypto: 0 for hw, 1 for sw * @max_xxx_size: for ucode uses * @ct_kill_threshold: temperature threshold @@ -1141,13 +1141,13 @@ struct il_priv { struct list_head free_frames; int frames_count; - enum ieee80211_band band; + enum nl80211_band band; int alloc_rxb_page; void (*handlers[IL_CN_MAX]) (struct il_priv *il, struct il_rx_buf *rxb); - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; /* spectrum measurement report caching */ struct il_spectrum_notification measure_report; @@ -1176,10 +1176,10 @@ struct il_priv { unsigned long scan_start; unsigned long scan_start_tsf; void *scan_cmd; - enum ieee80211_band scan_band; + enum nl80211_band scan_band; struct cfg80211_scan_request *scan_request; struct ieee80211_vif *scan_vif; - u8 scan_tx_ant[IEEE80211_NUM_BANDS]; + u8 scan_tx_ant[NUM_NL80211_BANDS]; u8 mgmt_tx_ant; /* spinlock */ @@ -1479,7 +1479,7 @@ il_is_channel_radar(const struct il_channel_info *ch_info) static inline u8 il_is_channel_a_band(const struct il_channel_info *ch_info) { - return ch_info->band == IEEE80211_BAND_5GHZ; + return ch_info->band == NL80211_BAND_5GHZ; } static inline int @@ -1673,7 +1673,7 @@ struct il_cfg { /* params not likely to change within a device family */ struct il_base_params *base_params; /* params likely to change within a device family */ - u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; + u8 scan_rx_antennas[NUM_NL80211_BANDS]; enum il_led_mode led_mode; int eeprom_size; @@ -1707,9 +1707,9 @@ void il_set_rxon_hwcrypto(struct il_priv *il, int hw_decrypt); int il_check_rxon_cmd(struct il_priv *il); int il_full_rxon_required(struct il_priv *il); int il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch); -void il_set_flags_for_band(struct il_priv *il, enum ieee80211_band band, +void il_set_flags_for_band(struct il_priv *il, enum nl80211_band band, struct ieee80211_vif *vif); -u8 il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band); +u8 il_get_single_channel_number(struct il_priv *il, enum nl80211_band band); void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf); bool il_is_ht40_tx_allowed(struct il_priv *il, struct ieee80211_sta_ht_cap *ht_cap); @@ -1793,9 +1793,9 @@ int il_force_reset(struct il_priv *il, bool external); u16 il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame, const u8 *ta, const u8 *ie, int ie_len, int left); void il_setup_rx_scan_handlers(struct il_priv *il); -u16 il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band, +u16 il_get_active_dwell_time(struct il_priv *il, enum nl80211_band band, u8 n_probes); -u16 il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band, +u16 il_get_passive_dwell_time(struct il_priv *il, enum nl80211_band band, struct ieee80211_vif *vif); void il_setup_scan_deferred_work(struct il_priv *il); void il_cancel_scan_deferred_work(struct il_priv *il); @@ -1955,7 +1955,7 @@ il_commit_rxon(struct il_priv *il) } static inline const struct ieee80211_supported_band * -il_get_hw_mode(struct il_priv *il, enum ieee80211_band band) +il_get_hw_mode(struct il_priv *il, enum nl80211_band band) { return il->hw->wiphy->bands[band]; } @@ -2813,7 +2813,7 @@ struct il_lq_sta { u8 action_counter; /* # mode-switch actions tried */ u8 is_green; u8 is_dup; - enum ieee80211_band band; + enum nl80211_band band; /* The following are bitmaps of rates; RATE_6M_MASK, etc. */ u32 supp_rates; diff --git a/drivers/net/wireless/intel/iwlegacy/debug.c b/drivers/net/wireless/intel/iwlegacy/debug.c index 908b9f4fef6f..6fc6b7ff9849 100644 --- a/drivers/net/wireless/intel/iwlegacy/debug.c +++ b/drivers/net/wireless/intel/iwlegacy/debug.c @@ -544,7 +544,7 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, return -ENOMEM; } - supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ); + supp_band = il_get_hw_mode(il, NL80211_BAND_2GHZ); if (supp_band) { channels = supp_band->channels; @@ -571,7 +571,7 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, flags & IEEE80211_CHAN_NO_IR ? "passive only" : "active/passive"); } - supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); + supp_band = il_get_hw_mode(il, NL80211_BAND_5GHZ); if (supp_band) { channels = supp_band->channels; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h index 9de277c6c420..b79e38734f2f 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h @@ -158,7 +158,7 @@ void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, struct iwl_rxon_context *ctx); void iwl_set_flags_for_band(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - enum ieee80211_band band, + enum nl80211_band band, struct ieee80211_vif *vif); /* uCode */ @@ -186,7 +186,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); static inline const struct ieee80211_supported_band *iwl_get_hw_mode( - struct iwl_priv *priv, enum ieee80211_band band) + struct iwl_priv *priv, enum nl80211_band band) { return priv->hw->wiphy->bands[band]; } @@ -198,7 +198,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan); #endif /* rx */ -int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); +int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band); void iwl_setup_rx_handlers(struct iwl_priv *priv); void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); @@ -258,7 +258,7 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); int __must_check iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif, enum iwl_scan_type scan_type, - enum ieee80211_band band); + enum nl80211_band band); /* For faster active scanning, scan will move to the next channel if fewer than * PLCP_QUIET_THRESH packets are heard on this channel within diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index 74c51615244e..f6591c83d636 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -335,7 +335,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; - supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); + supp_band = iwl_get_hw_mode(priv, NL80211_BAND_2GHZ); if (supp_band) { channels = supp_band->channels; @@ -358,7 +358,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, IEEE80211_CHAN_NO_IR ? "passive only" : "active/passive"); } - supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); + supp_band = iwl_get_hw_mode(priv, NL80211_BAND_5GHZ); if (supp_band) { channels = supp_band->channels; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h index 1a7ead753eee..8148df61a916 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h @@ -677,7 +677,7 @@ struct iwl_priv { struct iwl_hw_params hw_params; - enum ieee80211_band band; + enum nl80211_band band; u8 valid_contexts; void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, @@ -722,11 +722,11 @@ struct iwl_priv { unsigned long scan_start; unsigned long scan_start_tsf; void *scan_cmd; - enum ieee80211_band scan_band; + enum nl80211_band scan_band; struct cfg80211_scan_request *scan_request; struct ieee80211_vif *scan_vif; enum iwl_scan_type scan_type; - u8 scan_tx_ant[IEEE80211_NUM_BANDS]; + u8 scan_tx_ant[NUM_NL80211_BANDS]; u8 mgmt_tx_ant; /* max number of station keys */ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c index cc13c04063a5..f21732ec3b25 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c @@ -420,7 +420,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, .data = { &cmd, }, }; - cmd.band = priv->band == IEEE80211_BAND_2GHZ; + cmd.band = priv->band == NL80211_BAND_2GHZ; ch = ch_switch->chandef.chan->hw_value; IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", ctx->active.channel, ch); @@ -588,7 +588,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, hcmd.data[0] = cmd; - cmd->band = priv->band == IEEE80211_BAND_2GHZ; + cmd->band = priv->band == NL80211_BAND_2GHZ; ch = ch_switch->chandef.chan->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", ctx->active.channel, ch); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c index 1799469268ea..8dda52ae3bb5 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c @@ -94,7 +94,7 @@ void iwlagn_temperature(struct iwl_priv *priv) iwl_tt_handler(priv); } -int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) +int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band) { int idx = 0; int band_offset = 0; @@ -105,7 +105,7 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) return idx; /* Legacy rate format, search for match in table */ } else { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) band_offset = IWL_FIRST_OFDM_RATE; for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) @@ -878,7 +878,7 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) int i; u8 ind = ant; - if (priv->band == IEEE80211_BAND_2GHZ && + if (priv->band == NL80211_BAND_2GHZ && priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index c63ea79571ff..8c0719468d00 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -202,12 +202,12 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; - if (priv->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &priv->nvm_data->bands[IEEE80211_BAND_2GHZ]; - if (priv->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &priv->nvm_data->bands[IEEE80211_BAND_5GHZ]; + if (priv->nvm_data->bands[NL80211_BAND_2GHZ].n_channels) + priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = + &priv->nvm_data->bands[NL80211_BAND_2GHZ]; + if (priv->nvm_data->bands[NL80211_BAND_5GHZ].n_channels) + priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = + &priv->nvm_data->bands[NL80211_BAND_5GHZ]; hw->wiphy->hw_version = priv->trans->hw_id; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 614716251c39..37b32a6f60fd 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -262,7 +262,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); /* In mac80211, rates for 5 GHz start at 0 */ - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) rate += IWL_FIRST_OFDM_RATE; else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE) rate_flags |= RATE_MCS_CCK_MSK; @@ -1117,7 +1117,7 @@ static int iwl_init_drv(struct iwl_priv *priv) INIT_LIST_HEAD(&priv->calib_results); - priv->band = IEEE80211_BAND_2GHZ; + priv->band = NL80211_BAND_2GHZ; priv->plcp_delta_threshold = priv->lib->plcp_delta_threshold; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index ee7505537c96..b95c2d76db33 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -599,7 +599,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_priv *priv, * fill "search" or "active" tx mode table. */ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, - enum ieee80211_band band, + enum nl80211_band band, struct iwl_scale_tbl_info *tbl, int *rate_idx) { @@ -624,7 +624,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, /* legacy rate format */ if (!(rate_n_flags & RATE_MCS_HT_MSK)) { if (num_of_ant == 1) { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -802,7 +802,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { switch_to_legacy = 1; scale_index = rs_ht_to_legacy[scale_index]; - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -821,7 +821,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, /* Mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { /* supp_rates has no CCK bits in A mode */ - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) rate_mask = (u16)(rate_mask & (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); else @@ -939,7 +939,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, table = &lq_sta->lq; tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); - if (priv->band == IEEE80211_BAND_5GHZ) + if (priv->band == NL80211_BAND_5GHZ) rs_index -= IWL_FIRST_OFDM_RATE; mac_flags = info->status.rates[0].flags; mac_index = info->status.rates[0].idx; @@ -952,7 +952,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, * mac80211 HT index is always zero-indexed; we need to move * HT OFDM rates after CCK rates in 2.4 GHz band */ - if (priv->band == IEEE80211_BAND_2GHZ) + if (priv->band == NL80211_BAND_2GHZ) mac_index += IWL_FIRST_OFDM_RATE; } /* Here we actually compare this rate to the latest LQ command */ @@ -2284,7 +2284,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) /* supp_rates has no CCK bits in A mode */ rate_scale_index_msk = (u16) (rate_mask & (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); @@ -2721,7 +2721,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, /* Get max rate if user set max rate */ if (lq_sta) { lq_sta->max_rate_idx = txrc->max_rate_idx; - if ((sband->band == IEEE80211_BAND_5GHZ) && + if ((sband->band == NL80211_BAND_5GHZ) && (lq_sta->max_rate_idx != -1)) lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE; if ((lq_sta->max_rate_idx < 0) || @@ -2763,11 +2763,11 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, } else { /* Check for invalid rates */ if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) || - ((sband->band == IEEE80211_BAND_5GHZ) && + ((sband->band == NL80211_BAND_5GHZ) && (rate_idx < IWL_FIRST_OFDM_RATE))) rate_idx = rate_lowest_index(sband, sta); /* On valid 5 GHz rate, adjust index */ - else if (sband->band == IEEE80211_BAND_5GHZ) + else if (sband->band == NL80211_BAND_5GHZ) rate_idx -= IWL_FIRST_OFDM_RATE; info->control.rates[0].flags = 0; } @@ -2880,7 +2880,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i /* Set last_txrate_idx to lowest rate */ lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); - if (sband->band == IEEE80211_BAND_5GHZ) + if (sband->band == NL80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; #ifdef CONFIG_MAC80211_DEBUGFS diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h index c5fe44584613..50c1e951dd2d 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h @@ -355,7 +355,7 @@ struct iwl_lq_sta { u8 action_counter; /* # mode-switch actions tried */ u8 is_green; u8 is_dup; - enum ieee80211_band band; + enum nl80211_band band; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ u32 supp_rates; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 27ea61e3a390..dfa2041cfdac 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -834,7 +834,7 @@ static void iwlagn_rx_reply_rx(struct iwl_priv *priv, /* rx_status carries information about the packet to mac80211 */ rx_status.mactime = le64_to_cpu(phy_res->timestamp); rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; rx_status.freq = ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel), rx_status.band); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c index 2d47cb24c48b..b228552184b5 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c @@ -719,7 +719,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, struct iwl_rxon_context *ctx) { - enum ieee80211_band band = ch->band; + enum nl80211_band band = ch->band; u16 channel = ch->hw_value; if ((le16_to_cpu(ctx->staging.channel) == channel) && @@ -727,7 +727,7 @@ void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, return; ctx->staging.channel = cpu_to_le16(channel); - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; else ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; @@ -740,10 +740,10 @@ void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, void iwl_set_flags_for_band(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - enum ieee80211_band band, + enum nl80211_band band, struct ieee80211_vif *vif) { - if (band == IEEE80211_BAND_5GHZ) { + if (band == NL80211_BAND_5GHZ) { ctx->staging.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -1476,7 +1476,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, iwlagn_set_rxon_chain(priv, ctx); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + if (bss_conf->use_cts_prot && (priv->band != NL80211_BAND_5GHZ)) ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; else ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c index 81a2ddbe9569..d01766f16175 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c @@ -312,7 +312,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, scan_notif->tsf_high, scan_notif->status); IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", - (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", + (priv->scan_band == NL80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(jiffies - priv->scan_start)); /* @@ -362,9 +362,9 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) } static u16 iwl_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band, u8 n_probes) + enum nl80211_band band, u8 n_probes) { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52 + IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); else @@ -431,9 +431,9 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) } static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) + enum nl80211_band band) { - u16 passive = (band == IEEE80211_BAND_2GHZ) ? + u16 passive = (band == NL80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -442,7 +442,7 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, /* Return valid, unused, channel for a passive scan to reset the RF */ static u8 iwl_get_single_channel_number(struct iwl_priv *priv, - enum ieee80211_band band) + enum nl80211_band band) { struct ieee80211_supported_band *sband = priv->hw->wiphy->bands[band]; struct iwl_rxon_context *ctx; @@ -470,7 +470,7 @@ static u8 iwl_get_single_channel_number(struct iwl_priv *priv, static int iwl_get_channel_for_reset_scan(struct iwl_priv *priv, struct ieee80211_vif *vif, - enum ieee80211_band band, + enum nl80211_band band, struct iwl_scan_channel *scan_ch) { const struct ieee80211_supported_band *sband; @@ -492,7 +492,7 @@ static int iwl_get_channel_for_reset_scan(struct iwl_priv *priv, cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME); /* Set txpower levels to defaults */ scan_ch->dsp_atten = 110; - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); @@ -505,7 +505,7 @@ static int iwl_get_channel_for_reset_scan(struct iwl_priv *priv, static int iwl_get_channels_for_scan(struct iwl_priv *priv, struct ieee80211_vif *vif, - enum ieee80211_band band, + enum nl80211_band band, u8 is_active, u8 n_probes, struct iwl_scan_channel *scan_ch) { @@ -553,7 +553,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, * power level: * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; */ - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); @@ -636,7 +636,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) u32 rate_flags = 0; u16 cmd_len = 0; u16 rx_chain = 0; - enum ieee80211_band band; + enum nl80211_band band; u8 n_probes = 0; u8 rx_ant = priv->nvm_data->valid_rx_ant; u8 rate; @@ -750,7 +750,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; switch (priv->scan_band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; chan_mod = le32_to_cpu( priv->contexts[IWL_RXON_CTX_BSS].active.flags & @@ -771,7 +771,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) priv->lib->bt_params->advanced_bt_coexist) scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: rate = IWL_RATE_6M_PLCP; break; default: @@ -809,7 +809,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) band = priv->scan_band; - if (band == IEEE80211_BAND_2GHZ && + if (band == NL80211_BAND_2GHZ && priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist) { /* transmit 2.4 GHz probes only on first antenna */ @@ -925,16 +925,16 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) void iwl_init_scan_params(struct iwl_priv *priv) { u8 ant_idx = fls(priv->nvm_data->valid_tx_ant) - 1; - if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) - priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; - if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) - priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; + if (!priv->scan_tx_ant[NL80211_BAND_5GHZ]) + priv->scan_tx_ant[NL80211_BAND_5GHZ] = ant_idx; + if (!priv->scan_tx_ant[NL80211_BAND_2GHZ]) + priv->scan_tx_ant[NL80211_BAND_2GHZ] = ant_idx; } int __must_check iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif, enum iwl_scan_type scan_type, - enum ieee80211_band band) + enum nl80211_band band) { int ret; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c index 8e9768a553e4..de6ec9b7ace4 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c @@ -579,7 +579,7 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ - if (priv->band == IEEE80211_BAND_5GHZ) + if (priv->band == NL80211_BAND_5GHZ) r = IWL_RATE_6M_INDEX; else if (ctx && ctx->vif && ctx->vif->p2p) r = IWL_RATE_6M_INDEX; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c index 59e2001c39f8..4b97371c3b42 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c @@ -81,7 +81,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_TSF_MSK; else if (ieee80211_is_back_req(fc)) tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; - else if (info->band == IEEE80211_BAND_2GHZ && + else if (info->band == NL80211_BAND_2GHZ && priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist && (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || @@ -177,7 +177,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, rate_idx = rate_lowest_index( &priv->nvm_data->bands[info->band], sta); /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) rate_idx += IWL_FIRST_OFDM_RATE; /* Get PLCP rate for tx_cmd->rate_n_flags */ rate_plcp = iwl_rates[rate_idx].plcp; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-1000.c b/drivers/net/wireless/intel/iwlwifi/iwl-1000.c index ef22c3d168fc..5c2aae64d59f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-1000.c @@ -64,7 +64,7 @@ static const struct iwl_base_params iwl1000_base_params = { static const struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, .use_rts_for_aggregation = true, /* use rts/cts protection */ - .ht40_bands = BIT(IEEE80211_BAND_2GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ), }; static const struct iwl_eeprom_params iwl1000_eeprom_params = { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-2000.c b/drivers/net/wireless/intel/iwlwifi/iwl-2000.c index dc246c997084..2e823bdc4757 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-2000.c @@ -89,7 +89,7 @@ static const struct iwl_base_params iwl2030_base_params = { static const struct iwl_ht_params iwl2000_ht_params = { .ht_greenfield_support = true, .use_rts_for_aggregation = true, /* use rts/cts protection */ - .ht40_bands = BIT(IEEE80211_BAND_2GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ), }; static const struct iwl_eeprom_params iwl20x0_eeprom_params = { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-5000.c b/drivers/net/wireless/intel/iwlwifi/iwl-5000.c index 4dcdab6781cc..4c3e3cf4c799 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-5000.c @@ -62,7 +62,7 @@ static const struct iwl_base_params iwl5000_base_params = { static const struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, - .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), }; static const struct iwl_eeprom_params iwl5000_eeprom_params = { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c index 9938f5340ac0..5a7b7e1f0aab 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c @@ -110,7 +110,7 @@ static const struct iwl_base_params iwl6000_g2_base_params = { static const struct iwl_ht_params iwl6000_ht_params = { .ht_greenfield_support = true, .use_rts_for_aggregation = true, /* use rts/cts protection */ - .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), }; static const struct iwl_eeprom_params iwl6000_eeprom_params = { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index b6283c881d42..abd2904ecc48 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c @@ -156,7 +156,7 @@ static const struct iwl_tt_params iwl7000_high_temp_tt_params = { static const struct iwl_ht_params iwl7000_ht_params = { .stbc = true, - .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), }; #define IWL_DEVICE_7000_COMMON \ @@ -287,7 +287,7 @@ static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = { static const struct iwl_ht_params iwl7265_ht_params = { .stbc = true, .ldpc = true, - .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), }; const struct iwl_cfg iwl3165_2ac_cfg = { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index 0728a288aa3d..a9212a12f4da 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -124,7 +124,7 @@ static const struct iwl_base_params iwl8000_base_params = { static const struct iwl_ht_params iwl8000_ht_params = { .stbc = true, .ldpc = true, - .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), }; static const struct iwl_tt_params iwl8000_tt_params = { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index a3d35aa291a9..b9aca3795f06 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -93,7 +93,7 @@ static const struct iwl_base_params iwl9000_base_params = { static const struct iwl_ht_params iwl9000_ht_params = { .stbc = true, .ldpc = true, - .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), }; static const struct iwl_tt_params iwl9000_tt_params = { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 08bb4f4e424a..720679889ab3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -185,7 +185,7 @@ struct iwl_base_params { * @stbc: support Tx STBC and 1*SS Rx STBC * @ldpc: support Tx/Rx with LDPC * @use_rts_for_aggregation: use rts/cts protection for HT traffic - * @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40 + * @ht40_bands: bitmap of bands (using %NL80211_BAND_*) that support HT40 */ struct iwl_ht_params { enum ieee80211_smps_mode smps_mode; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c index c15f5be85197..bf1b69aec813 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c @@ -390,10 +390,10 @@ iwl_eeprom_enh_txp_read_element(struct iwl_nvm_data *data, int n_channels, s8 max_txpower_avg) { int ch_idx; - enum ieee80211_band band; + enum nl80211_band band; band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? - IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; + NL80211_BAND_5GHZ : NL80211_BAND_2GHZ; for (ch_idx = 0; ch_idx < n_channels; ch_idx++) { struct ieee80211_channel *chan = &data->channels[ch_idx]; @@ -526,7 +526,7 @@ static void iwl_init_band_reference(const struct iwl_cfg *cfg, static void iwl_mod_ht40_chan_info(struct device *dev, struct iwl_nvm_data *data, int n_channels, - enum ieee80211_band band, u16 channel, + enum nl80211_band band, u16 channel, const struct iwl_eeprom_channel *eeprom_ch, u8 clear_ht40_extension_channel) { @@ -548,7 +548,7 @@ static void iwl_mod_ht40_chan_info(struct device *dev, IWL_DEBUG_EEPROM(dev, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", channel, - band == IEEE80211_BAND_5GHZ ? "5.2" : "2.4", + band == NL80211_BAND_5GHZ ? "5.2" : "2.4", CHECK_AND_PRINT(IBSS), CHECK_AND_PRINT(ACTIVE), CHECK_AND_PRINT(RADAR), @@ -606,8 +606,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, n_channels++; channel->hw_value = eeprom_ch_array[ch_idx]; - channel->band = (band == 1) ? IEEE80211_BAND_2GHZ - : IEEE80211_BAND_5GHZ; + channel->band = (band == 1) ? NL80211_BAND_2GHZ + : NL80211_BAND_5GHZ; channel->center_freq = ieee80211_channel_to_frequency( channel->hw_value, channel->band); @@ -677,15 +677,15 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ for (band = 6; band <= 7; band++) { - enum ieee80211_band ieeeband; + enum nl80211_band ieeeband; iwl_init_band_reference(cfg, eeprom, eeprom_size, band, &eeprom_ch_count, &eeprom_ch_info, &eeprom_ch_array); /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ - ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ - : IEEE80211_BAND_5GHZ; + ieeeband = (band == 6) ? NL80211_BAND_2GHZ + : NL80211_BAND_5GHZ; /* Loop through each band adding each of the channels */ for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { @@ -708,7 +708,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, int iwl_init_sband_channels(struct iwl_nvm_data *data, struct ieee80211_supported_band *sband, - int n_channels, enum ieee80211_band band) + int n_channels, enum nl80211_band band) { struct ieee80211_channel *chan = &data->channels[0]; int n = 0, idx = 0; @@ -734,7 +734,7 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data, void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, struct iwl_nvm_data *data, struct ieee80211_sta_ht_cap *ht_info, - enum ieee80211_band band, + enum nl80211_band band, u8 tx_chains, u8 rx_chains) { int max_bit_rate = 0; @@ -813,22 +813,22 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, int n_used = 0; struct ieee80211_supported_band *sband; - sband = &data->bands[IEEE80211_BAND_2GHZ]; - sband->band = IEEE80211_BAND_2GHZ; + sband = &data->bands[NL80211_BAND_2GHZ]; + sband->band = NL80211_BAND_2GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; sband->n_bitrates = N_RATES_24; n_used += iwl_init_sband_channels(data, sband, n_channels, - IEEE80211_BAND_2GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ, data->valid_tx_ant, data->valid_rx_ant); - sband = &data->bands[IEEE80211_BAND_5GHZ]; - sband->band = IEEE80211_BAND_5GHZ; + sband = &data->bands[NL80211_BAND_5GHZ]; + sband->band = NL80211_BAND_5GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; sband->n_bitrates = N_RATES_52; n_used += iwl_init_sband_channels(data, sband, n_channels, - IEEE80211_BAND_5GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ, data->valid_tx_ant, data->valid_rx_ant); if (n_channels != n_used) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h index ad2b834668ff..53f39a34eca2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h @@ -98,7 +98,7 @@ struct iwl_nvm_data { s8 max_tx_pwr_half_dbm; bool lar_enabled; - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; struct ieee80211_channel channels[]; }; @@ -133,12 +133,12 @@ int iwl_nvm_check_version(struct iwl_nvm_data *data, int iwl_init_sband_channels(struct iwl_nvm_data *data, struct ieee80211_supported_band *sband, - int n_channels, enum ieee80211_band band); + int n_channels, enum nl80211_band band); void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, struct iwl_nvm_data *data, struct ieee80211_sta_ht_cap *ht_info, - enum ieee80211_band band, + enum nl80211_band band, u8 tx_chains, u8 rx_chains); #endif /* __iwl_eeprom_parse_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 93a689583dff..14743c37d976 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -308,7 +308,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, channel->hw_value = nvm_chan[ch_idx]; channel->band = (ch_idx < num_2ghz_channels) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; channel->center_freq = ieee80211_channel_to_frequency( channel->hw_value, channel->band); @@ -320,7 +320,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, * is not used in mvm, and is used for backwards compatibility */ channel->max_power = IWL_DEFAULT_MAX_TX_POWER; - is_5ghz = channel->band == IEEE80211_BAND_5GHZ; + is_5ghz = channel->band == NL80211_BAND_5GHZ; /* don't put limitations in case we're using LAR */ if (!lar_supported) @@ -439,22 +439,22 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, &ch_section[NVM_CHANNELS_FAMILY_8000], lar_supported); - sband = &data->bands[IEEE80211_BAND_2GHZ]; - sband->band = IEEE80211_BAND_2GHZ; + sband = &data->bands[NL80211_BAND_2GHZ]; + sband->band = NL80211_BAND_2GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; sband->n_bitrates = N_RATES_24; n_used += iwl_init_sband_channels(data, sband, n_channels, - IEEE80211_BAND_2GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ, tx_chains, rx_chains); - sband = &data->bands[IEEE80211_BAND_5GHZ]; - sband->band = IEEE80211_BAND_5GHZ; + sband = &data->bands[NL80211_BAND_5GHZ]; + sband->band = NL80211_BAND_5GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; sband->n_bitrates = N_RATES_52; n_used += iwl_init_sband_channels(data, sband, n_channels, - IEEE80211_BAND_5GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ, tx_chains, rx_chains); if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac) iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, @@ -781,7 +781,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, struct ieee80211_regdomain *regd; int size_of_regd; struct ieee80211_reg_rule *rule; - enum ieee80211_band band; + enum nl80211_band band; int center_freq, prev_center_freq = 0; int valid_rules = 0; bool new_rule; @@ -809,7 +809,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { ch_flags = (u16)__le32_to_cpup(channels + ch_idx); band = (ch_idx < NUM_2GHZ_CHANNELS) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; center_freq = ieee80211_channel_to_frequency(nvm_chan[ch_idx], band); new_rule = false; @@ -857,7 +857,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, IWL_DEBUG_DEV(dev, IWL_DL_LAR, "Ch. %d [%sGHz] %s%s%s%s%s%s%s%s%s(0x%02x): Ad-Hoc %ssupported\n", center_freq, - band == IEEE80211_BAND_5GHZ ? "5.2" : "2.4", + band == NL80211_BAND_5GHZ ? "5.2" : "2.4", CHECK_AND_PRINT_I(VALID), CHECK_AND_PRINT_I(ACTIVE), CHECK_AND_PRINT_I(RADAR), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 35cdeca3d61e..a63f5bbb1ba7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c @@ -378,7 +378,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) chanctx_conf = rcu_dereference(vif->chanctx_conf); if (!chanctx_conf || - chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { + chanctx_conf->def.chan->band != NL80211_BAND_2GHZ) { rcu_read_unlock(); return BT_COEX_INVALID_LUT; } @@ -537,7 +537,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, /* If channel context is invalid or not on 2.4GHz .. */ if ((!chanctx_conf || - chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { + chanctx_conf->def.chan->band != NL80211_BAND_2GHZ)) { if (vif->type == NL80211_IFTYPE_STATION) { /* ... relax constraints and disable rssi events */ iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, @@ -857,11 +857,11 @@ bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm) } bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, - enum ieee80211_band band) + enum nl80211_band band) { u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading); - if (band != IEEE80211_BAND_2GHZ) + if (band != NL80211_BAND_2GHZ) return false; return bt_activity >= BT_LOW_TRAFFIC; @@ -873,7 +873,7 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, __le16 fc = hdr->frame_control; bool mplut_enabled = iwl_mvm_is_mplut_supported(mvm); - if (info->band != IEEE80211_BAND_2GHZ) + if (info->band != NL80211_BAND_2GHZ) return 0; if (unlikely(mvm->bt_tx_prio)) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 3a279d3403ef..fb96bc00f022 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -724,9 +724,9 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, ret = kstrtou32(data, 10, &value); if (ret == 0 && value) { - enum ieee80211_band band = (cmd->channel_num <= 14) ? - IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ; + enum nl80211_band band = (cmd->channel_num <= 14) ? + NL80211_BAND_2GHZ : + NL80211_BAND_5GHZ; struct ieee80211_channel chn = { .band = band, .center_freq = ieee80211_channel_to_frequency( diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 6ad5c602e84c..9e97cf4ff1c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -980,7 +980,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) goto error; /* Add all the PHY contexts */ - chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0]; + chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0]; cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); for (i = 0; i < NUM_PHY_CTX; i++) { /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 923d19112e0c..456067b2f48d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -559,7 +559,7 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) static void iwl_mvm_ack_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - enum ieee80211_band band, + enum nl80211_band band, u8 *cck_rates, u8 *ofdm_rates) { struct ieee80211_supported_band *sband; @@ -730,7 +730,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, rcu_read_lock(); chanctx = rcu_dereference(vif->chanctx_conf); iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band - : IEEE80211_BAND_2GHZ, + : NL80211_BAND_2GHZ, &cck_ack_rates, &ofdm_ack_rates); rcu_read_unlock(); @@ -1065,7 +1065,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS); - if (info->band == IEEE80211_BAND_5GHZ || vif->p2p) { + if (info->band == NL80211_BAND_5GHZ || vif->p2p) { rate = IWL_FIRST_OFDM_RATE; } else { rate = IWL_FIRST_CCK_RATE; @@ -1516,7 +1516,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, rx_status.device_timestamp = le32_to_cpu(sb->system_time); rx_status.band = (sb->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; rx_status.freq = ieee80211_channel_to_frequency(le16_to_cpu(sb->channel), rx_status.band); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 4f5ec495b460..ef91b3770703 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -550,18 +550,18 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) else mvm->max_scans = IWL_MVM_MAX_LMAC_SCANS; - if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; - if (mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels) { - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; + if (mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels) + hw->wiphy->bands[NL80211_BAND_2GHZ] = + &mvm->nvm_data->bands[NL80211_BAND_2GHZ]; + if (mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels) { + hw->wiphy->bands[NL80211_BAND_5GHZ] = + &mvm->nvm_data->bands[NL80211_BAND_5GHZ]; if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BEAMFORMER) && fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_LQ_SS_PARAMS)) - hw->wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |= + hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; } @@ -2911,7 +2911,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)), .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id), /* Set the channel info data */ - .channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ? + .channel_info.band = (channel->band == NL80211_BAND_2GHZ) ? PHY_BAND_24 : PHY_BAND_5, .channel_info.channel = channel->hw_value, .channel_info.width = PHY_VHT_CHANNEL_MODE20, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 2d685e02d488..85800ba0c667 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1133,9 +1133,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm); /* Utils */ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, - enum ieee80211_band band); + enum nl80211_band band); void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, - enum ieee80211_band band, + enum nl80211_band band, struct ieee80211_tx_rate *r); u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); @@ -1468,7 +1468,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant); bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm); bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, - enum ieee80211_band band); + enum nl80211_band band); u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *info, u8 ac); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index 6e6a56f2153d..95138830b9f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c @@ -147,7 +147,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, u8 active_cnt, idle_cnt; /* Set the channel info data */ - cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? + cmd->ci.band = (chandef->chan->band == NL80211_BAND_2GHZ ? PHY_BAND_24 : PHY_BAND_5); cmd->ci.channel = chandef->chan->hw_value; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 61d0a8cd13f9..81dd2f6a48a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -829,7 +829,7 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, /* Convert a ucode rate into an rs_rate object */ static int rs_rate_from_ucode_rate(const u32 ucode_rate, - enum ieee80211_band band, + enum nl80211_band band, struct rs_rate *rate) { u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK; @@ -848,7 +848,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, if (!(ucode_rate & RATE_MCS_HT_MSK) && !(ucode_rate & RATE_MCS_VHT_MSK)) { if (num_of_ant == 1) { - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) rate->type = LQ_LEGACY_A; else rate->type = LQ_LEGACY_G; @@ -1043,7 +1043,7 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, return; } else if (is_siso(rate)) { /* Downgrade to Legacy if we were in SISO */ - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) rate->type = LQ_LEGACY_A; else rate->type = LQ_LEGACY_G; @@ -1850,7 +1850,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, rate->ant = column->ant; if (column->mode == RS_LEGACY) { - if (lq_sta->band == IEEE80211_BAND_5GHZ) + if (lq_sta->band == NL80211_BAND_5GHZ) rate->type = LQ_LEGACY_A; else rate->type = LQ_LEGACY_G; @@ -2020,7 +2020,7 @@ static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, } static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct rs_rate *rate, enum ieee80211_band band) + struct rs_rate *rate, enum nl80211_band band) { int index = rate->index; bool cam = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM); @@ -2126,7 +2126,7 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); struct ieee80211_vif *vif = mvm_sta->vif; struct ieee80211_chanctx_conf *chanctx_conf; - enum ieee80211_band band; + enum nl80211_band band; struct iwl_rate_scale_data *window; struct rs_rate *rate = &tbl->rate; enum tpc_action action; @@ -2148,7 +2148,7 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm, rcu_read_lock(); chanctx_conf = rcu_dereference(vif->chanctx_conf); if (WARN_ON(!chanctx_conf)) - band = IEEE80211_NUM_BANDS; + band = NUM_NL80211_BANDS; else band = chanctx_conf->def.chan->band; rcu_read_unlock(); @@ -2606,7 +2606,7 @@ static void rs_init_optimal_rate(struct iwl_mvm *mvm, rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; else if (lq_sta->max_siso_rate_idx != IWL_RATE_INVALID) rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; - else if (lq_sta->band == IEEE80211_BAND_5GHZ) + else if (lq_sta->band == NL80211_BAND_5GHZ) rate->type = LQ_LEGACY_A; else rate->type = LQ_LEGACY_G; @@ -2623,7 +2623,7 @@ static void rs_init_optimal_rate(struct iwl_mvm *mvm, } else { lq_sta->optimal_rate_mask = lq_sta->active_legacy_rate; - if (lq_sta->band == IEEE80211_BAND_5GHZ) { + if (lq_sta->band == NL80211_BAND_5GHZ) { lq_sta->optimal_rates = rs_optimal_rates_5ghz_legacy; lq_sta->optimal_nentries = ARRAY_SIZE(rs_optimal_rates_5ghz_legacy); @@ -2679,7 +2679,7 @@ static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm, static void rs_get_initial_rate(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, - enum ieee80211_band band, + enum nl80211_band band, struct rs_rate *rate) { int i, nentries; @@ -2714,7 +2714,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, rate->index = find_first_bit(&lq_sta->active_legacy_rate, BITS_PER_LONG); - if (band == IEEE80211_BAND_5GHZ) { + if (band == NL80211_BAND_5GHZ) { rate->type = LQ_LEGACY_A; initial_rates = rs_optimal_rates_5ghz_legacy; nentries = ARRAY_SIZE(rs_optimal_rates_5ghz_legacy); @@ -2814,7 +2814,7 @@ void rs_update_last_rssi(struct iwl_mvm *mvm, static void rs_initialize_lq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, - enum ieee80211_band band, + enum nl80211_band band, bool init) { struct iwl_scale_tbl_info *tbl; @@ -3097,7 +3097,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg) * Called after adding a new station to initialize rate scaling */ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - enum ieee80211_band band, bool init) + enum nl80211_band band, bool init) { int i, j; struct ieee80211_hw *hw = mvm->hw; @@ -3203,7 +3203,7 @@ static void rs_rate_update(void *mvm_r, #ifdef CONFIG_MAC80211_DEBUGFS static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq_cmd, - enum ieee80211_band band, + enum nl80211_band band, u32 ucode_rate) { struct rs_rate rate; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h index bdb6f2d8d854..90d046fb24a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h @@ -305,7 +305,7 @@ struct iwl_lq_sta { bool stbc_capable; /* Tx STBC is supported by chip and Rx by STA */ bool bfer_capable; /* Remote supports beamformee and we BFer */ - enum ieee80211_band band; + enum nl80211_band band; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ unsigned long active_legacy_rate; @@ -358,7 +358,7 @@ struct iwl_lq_sta { /* Initialize station's rate scaling information after adding station */ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - enum ieee80211_band band, bool init); + enum nl80211_band band, bool init); /* Notify RS about Tx status */ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index d8cadf2fe098..263e8a8576b7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -319,7 +319,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->device_timestamp = le32_to_cpu(phy_info->system_timestamp); rx_status->band = (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; rx_status->freq = ieee80211_channel_to_frequency(le16_to_cpu(phy_info->channel), rx_status->band); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index d4a4c13400cb..651604d18a32 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -456,8 +456,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->mactime = le64_to_cpu(desc->tsf_on_air_rise); rx_status->device_timestamp = le32_to_cpu(desc->gp2_on_air_rise); - rx_status->band = desc->channel > 14 ? IEEE80211_BAND_5GHZ : - IEEE80211_BAND_2GHZ; + rx_status->band = desc->channel > 14 ? NL80211_BAND_5GHZ : + NL80211_BAND_2GHZ; rx_status->freq = ieee80211_channel_to_frequency(desc->channel, rx_status->band); iwl_mvm_get_signal_strength(mvm, desc, rx_status); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index c1d1be9c5d01..6f609dd5c222 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -163,16 +163,16 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) return cpu_to_le16(rx_chain); } -static __le32 iwl_mvm_scan_rxon_flags(enum ieee80211_band band) +static __le32 iwl_mvm_scan_rxon_flags(enum nl80211_band band) { - if (band == IEEE80211_BAND_2GHZ) + if (band == NL80211_BAND_2GHZ) return cpu_to_le32(PHY_BAND_24); else return cpu_to_le32(PHY_BAND_5); } static inline __le32 -iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, +iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band, bool no_cck) { u32 tx_ant; @@ -182,7 +182,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, mvm->scan_last_antenna_idx); tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; - if (band == IEEE80211_BAND_2GHZ && !no_cck) + if (band == NL80211_BAND_2GHZ && !no_cck) return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK | tx_ant); else @@ -591,14 +591,14 @@ static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm *mvm, tx_cmd[0].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_BT_DIS); tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, - IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ, no_cck); tx_cmd[0].sta_id = mvm->aux_sta.sta_id; tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_BT_DIS); tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, - IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ, no_cck); tx_cmd[1].sta_id = mvm->aux_sta.sta_id; } @@ -695,19 +695,19 @@ iwl_mvm_build_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* Insert ds parameter set element on 2.4 GHz band */ newpos = iwl_mvm_copy_and_insert_ds_elem(mvm, - ies->ies[IEEE80211_BAND_2GHZ], - ies->len[IEEE80211_BAND_2GHZ], + ies->ies[NL80211_BAND_2GHZ], + ies->len[NL80211_BAND_2GHZ], pos); params->preq.band_data[0].offset = cpu_to_le16(pos - params->preq.buf); params->preq.band_data[0].len = cpu_to_le16(newpos - pos); pos = newpos; - memcpy(pos, ies->ies[IEEE80211_BAND_5GHZ], - ies->len[IEEE80211_BAND_5GHZ]); + memcpy(pos, ies->ies[NL80211_BAND_5GHZ], + ies->len[NL80211_BAND_5GHZ]); params->preq.band_data[1].offset = cpu_to_le16(pos - params->preq.buf); params->preq.band_data[1].len = - cpu_to_le16(ies->len[IEEE80211_BAND_5GHZ]); - pos += ies->len[IEEE80211_BAND_5GHZ]; + cpu_to_le16(ies->len[NL80211_BAND_5GHZ]); + pos += ies->len[NL80211_BAND_5GHZ]; memcpy(pos, ies->common_ies, ies->common_ie_len); params->preq.common_data.offset = cpu_to_le16(pos - params->preq.buf); @@ -921,10 +921,10 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm) unsigned int rates = 0; int i; - band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; + band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ]; for (i = 0; i < band->n_bitrates; i++) rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value); - band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; + band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ]; for (i = 0; i < band->n_bitrates; i++) rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value); @@ -939,8 +939,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) struct iwl_scan_config *scan_config; struct ieee80211_supported_band *band; int num_channels = - mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + - mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; + mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels + + mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels; int ret, i, j = 0, cmd_size; struct iwl_host_cmd cmd = { .id = iwl_cmd_id(SCAN_CFG_CMD, IWL_ALWAYS_LONG_GROUP, 0), @@ -994,10 +994,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) IWL_CHANNEL_FLAG_EBS_ADD | IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE; - band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; + band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ]; for (i = 0; i < band->n_channels; i++, j++) scan_config->channel_array[j] = band->channels[i].hw_value; - band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; + band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ]; for (i = 0; i < band->n_channels; i++, j++) scan_config->channel_array[j] = band->channels[i].hw_value; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c index 18711c5de35a..9f160fc58cd0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c @@ -444,7 +444,7 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, } if (chandef) { - cmd.ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? + cmd.ci.band = (chandef->chan->band == NL80211_BAND_2GHZ ? PHY_BAND_24 : PHY_BAND_5); cmd.ci.channel = chandef->chan->hw_value; cmd.ci.width = iwl_mvm_get_channel_width(chandef); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index efb9b98c4c98..bd286fca3776 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -359,7 +359,7 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, &mvm->nvm_data->bands[info->band], sta); /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) rate_idx += IWL_FIRST_OFDM_RATE; /* For 2.4 GHZ band, check that there is no need to remap */ @@ -372,7 +372,7 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm), mvm->mgmt_last_antenna_idx); - if (info->band == IEEE80211_BAND_2GHZ && + if (info->band == NL80211_BAND_2GHZ && !iwl_mvm_bt_coex_is_shared_ant_avail(mvm)) rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS; else @@ -1052,7 +1052,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status) #endif /* CONFIG_IWLWIFI_DEBUG */ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, - enum ieee80211_band band, + enum nl80211_band band, struct ieee80211_tx_rate *r) { if (rate_n_flags & RATE_HT_MCS_GF_MSK) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 486c98541afc..f0ffd62f02d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -217,14 +217,14 @@ static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = { }; int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, - enum ieee80211_band band) + enum nl80211_band band) { int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; int idx; int band_offset = 0; /* Legacy rate format, search for match in table */ - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) band_offset = IWL_FIRST_OFDM_RATE; for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) if (fw_rate_idx_to_plcp[idx] == rate) diff --git a/drivers/net/wireless/intersil/orinoco/cfg.c b/drivers/net/wireless/intersil/orinoco/cfg.c index 0f6ea316e38e..7aa47069af0a 100644 --- a/drivers/net/wireless/intersil/orinoco/cfg.c +++ b/drivers/net/wireless/intersil/orinoco/cfg.c @@ -60,14 +60,14 @@ int orinoco_wiphy_register(struct wiphy *wiphy) if (priv->channel_mask & (1 << i)) { priv->channels[i].center_freq = ieee80211_channel_to_frequency(i + 1, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); channels++; } } priv->band.channels = priv->channels; priv->band.n_channels = channels; - wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; i = 0; @@ -175,7 +175,7 @@ static int orinoco_set_monitor_channel(struct wiphy *wiphy, if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT) return -EINVAL; - if (chandef->chan->band != IEEE80211_BAND_2GHZ) + if (chandef->chan->band != NL80211_BAND_2GHZ) return -EINVAL; channel = ieee80211_frequency_to_channel(chandef->chan->center_freq); diff --git a/drivers/net/wireless/intersil/orinoco/hw.c b/drivers/net/wireless/intersil/orinoco/hw.c index e27e32851f1e..61af5a28f269 100644 --- a/drivers/net/wireless/intersil/orinoco/hw.c +++ b/drivers/net/wireless/intersil/orinoco/hw.c @@ -1193,7 +1193,7 @@ int orinoco_hw_get_freq(struct orinoco_private *priv) goto out; } - freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ); out: orinoco_unlock(priv, &flags); diff --git a/drivers/net/wireless/intersil/orinoco/scan.c b/drivers/net/wireless/intersil/orinoco/scan.c index 2c66166add70..d0ceb06c72d0 100644 --- a/drivers/net/wireless/intersil/orinoco/scan.c +++ b/drivers/net/wireless/intersil/orinoco/scan.c @@ -111,7 +111,7 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv, } freq = ieee80211_channel_to_frequency( - le16_to_cpu(bss->a.channel), IEEE80211_BAND_2GHZ); + le16_to_cpu(bss->a.channel), NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); if (!channel) { printk(KERN_DEBUG "Invalid channel designation %04X(%04X)", @@ -148,7 +148,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv, ie_len = len - sizeof(*bss); ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len); chan = ie ? ie[2] : 0; - freq = ieee80211_channel_to_frequency(chan, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency(chan, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); timestamp = le64_to_cpu(bss->timestamp); diff --git a/drivers/net/wireless/intersil/p54/eeprom.c b/drivers/net/wireless/intersil/p54/eeprom.c index 2fe713eda7ad..d4c73d39336f 100644 --- a/drivers/net/wireless/intersil/p54/eeprom.c +++ b/drivers/net/wireless/intersil/p54/eeprom.c @@ -76,14 +76,14 @@ struct p54_channel_entry { u16 data; int index; int max_power; - enum ieee80211_band band; + enum nl80211_band band; }; struct p54_channel_list { struct p54_channel_entry *channels; size_t entries; size_t max_entries; - size_t band_channel_num[IEEE80211_NUM_BANDS]; + size_t band_channel_num[NUM_NL80211_BANDS]; }; static int p54_get_band_from_freq(u16 freq) @@ -91,10 +91,10 @@ static int p54_get_band_from_freq(u16 freq) /* FIXME: sync these values with the 802.11 spec */ if ((freq >= 2412) && (freq <= 2484)) - return IEEE80211_BAND_2GHZ; + return NL80211_BAND_2GHZ; if ((freq >= 4920) && (freq <= 5825)) - return IEEE80211_BAND_5GHZ; + return NL80211_BAND_5GHZ; return -1; } @@ -124,16 +124,16 @@ static int p54_compare_rssichan(const void *_a, static int p54_fill_band_bitrates(struct ieee80211_hw *dev, struct ieee80211_supported_band *band_entry, - enum ieee80211_band band) + enum nl80211_band band) { /* TODO: generate rate array dynamically */ switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: band_entry->bitrates = p54_bgrates; band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates); break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: band_entry->bitrates = p54_arates; band_entry->n_bitrates = ARRAY_SIZE(p54_arates); break; @@ -147,7 +147,7 @@ static int p54_fill_band_bitrates(struct ieee80211_hw *dev, static int p54_generate_band(struct ieee80211_hw *dev, struct p54_channel_list *list, unsigned int *chan_num, - enum ieee80211_band band) + enum nl80211_band band) { struct p54_common *priv = dev->priv; struct ieee80211_supported_band *tmp, *old; @@ -206,7 +206,7 @@ static int p54_generate_band(struct ieee80211_hw *dev, if (j == 0) { wiphy_err(dev->wiphy, "Disabling totally damaged %d GHz band\n", - (band == IEEE80211_BAND_2GHZ) ? 2 : 5); + (band == NL80211_BAND_2GHZ) ? 2 : 5); ret = -ENODATA; goto err_out; @@ -396,7 +396,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) p54_compare_channels, NULL); k = 0; - for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0, j = 0; i < NUM_NL80211_BANDS; i++) { if (p54_generate_band(dev, list, &k, i) == 0) j++; } @@ -573,10 +573,10 @@ static int p54_parse_rssical(struct ieee80211_hw *dev, for (i = 0; i < entries; i++) { u16 freq = 0; switch (i) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: freq = 2437; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: freq = 5240; break; } @@ -902,11 +902,11 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) p54_init_xbow_synth(priv); if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = - priv->band_table[IEEE80211_BAND_2GHZ]; + dev->wiphy->bands[NL80211_BAND_2GHZ] = + priv->band_table[NL80211_BAND_2GHZ]; if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) - dev->wiphy->bands[IEEE80211_BAND_5GHZ] = - priv->band_table[IEEE80211_BAND_5GHZ]; + dev->wiphy->bands[NL80211_BAND_5GHZ] = + priv->band_table[NL80211_BAND_5GHZ]; if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED) priv->rx_diversity_mask = 3; if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED) diff --git a/drivers/net/wireless/intersil/p54/main.c b/drivers/net/wireless/intersil/p54/main.c index 7805864e76f9..d5a3bf91a03e 100644 --- a/drivers/net/wireless/intersil/p54/main.c +++ b/drivers/net/wireless/intersil/p54/main.c @@ -477,7 +477,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, p54_set_edcf(priv); } if (changed & BSS_CHANGED_BASIC_RATES) { - if (dev->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) + if (dev->conf.chandef.chan->band == NL80211_BAND_5GHZ) priv->basic_rate_mask = (info->basic_rates << 4); else priv->basic_rate_mask = info->basic_rates; @@ -829,7 +829,7 @@ void p54_free_common(struct ieee80211_hw *dev) struct p54_common *priv = dev->priv; unsigned int i; - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < NUM_NL80211_BANDS; i++) kfree(priv->band_table[i]); kfree(priv->iq_autocal); diff --git a/drivers/net/wireless/intersil/p54/p54.h b/drivers/net/wireless/intersil/p54/p54.h index 40b401ed6845..529939e611cd 100644 --- a/drivers/net/wireless/intersil/p54/p54.h +++ b/drivers/net/wireless/intersil/p54/p54.h @@ -223,7 +223,7 @@ struct p54_common { struct p54_cal_database *curve_data; struct p54_cal_database *output_limit; struct p54_cal_database *rssi_db; - struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band *band_table[NUM_NL80211_BANDS]; /* BBP/MAC state */ u8 mac_addr[ETH_ALEN]; diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c index 24e5ff9a9272..1af7da0b386e 100644 --- a/drivers/net/wireless/intersil/p54/txrx.c +++ b/drivers/net/wireless/intersil/p54/txrx.c @@ -353,7 +353,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi); if (hdr->rate & 0x10) rx_status->flag |= RX_FLAG_SHORTPRE; - if (priv->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) + if (priv->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ) rx_status->rate_idx = (rate < 4) ? 0 : rate - 4; else rx_status->rate_idx = rate; @@ -867,7 +867,7 @@ void p54_tx_80211(struct ieee80211_hw *dev, for (i = 0; i < nrates && ridx < 8; i++) { /* we register the rates in perfect order */ rate = info->control.rates[i].idx; - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) rate += 4; /* store the count we actually calculated for TX status */ diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 2b185feb1aa0..c757f14c4c00 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -255,14 +255,14 @@ static struct class *hwsim_class; static struct net_device *hwsim_mon; /* global monitor netdev */ #define CHAN2G(_freq) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_freq), \ .max_power = 20, \ } #define CHAN5G(_freq) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = (_freq), \ .hw_value = (_freq), \ .max_power = 20, \ @@ -479,7 +479,7 @@ struct mac80211_hwsim_data { struct list_head list; struct ieee80211_hw *hw; struct device *dev; - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; @@ -2347,7 +2347,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, u8 addr[ETH_ALEN]; struct mac80211_hwsim_data *data; struct ieee80211_hw *hw; - enum ieee80211_band band; + enum nl80211_band band; const struct ieee80211_ops *ops = &mac80211_hwsim_ops; int idx; @@ -2476,16 +2476,16 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, sizeof(hwsim_channels_5ghz)); memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); - for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { + for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { struct ieee80211_supported_band *sband = &data->bands[band]; switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: sband->channels = data->channels_2ghz; sband->n_channels = ARRAY_SIZE(hwsim_channels_2ghz); sband->bitrates = data->rates; sband->n_bitrates = ARRAY_SIZE(hwsim_rates); break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: sband->channels = data->channels_5ghz; sband->n_channels = ARRAY_SIZE(hwsim_channels_5ghz); sband->bitrates = data->rates + 4; diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c index 2eea76a340b7..776b44bfd93a 100644 --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c @@ -23,7 +23,7 @@ #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -639,7 +639,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, if (chan_no != -1) { struct wiphy *wiphy = priv->wdev->wiphy; int freq = ieee80211_channel_to_frequency(chan_no, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); @@ -1266,7 +1266,7 @@ _new_connect_scan_req(struct wiphy *wiphy, struct cfg80211_connect_params *sme) { struct cfg80211_scan_request *creq = NULL; int i, n_channels = ieee80211_get_num_supported_channels(wiphy); - enum ieee80211_band band; + enum nl80211_band band; creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + n_channels * sizeof(void *), @@ -1281,7 +1281,7 @@ _new_connect_scan_req(struct wiphy *wiphy, struct cfg80211_connect_params *sme) /* Scan all available channels */ i = 0; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { int j; if (!wiphy->bands[band]) @@ -2200,7 +2200,7 @@ int lbs_cfg_register(struct lbs_private *priv) if (lbs_mesh_activated(priv)) wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT); - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; + wdev->wiphy->bands[NL80211_BAND_2GHZ] = &lbs_band_2ghz; /* * We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c index 4ddd0e5a6b85..301170cccfff 100644 --- a/drivers/net/wireless/marvell/libertas/cmd.c +++ b/drivers/net/wireless/marvell/libertas/cmd.c @@ -743,7 +743,7 @@ int lbs_set_11d_domain_info(struct lbs_private *priv) struct cmd_ds_802_11d_domain_info cmd; struct mrvl_ie_domain_param_set *domain = &cmd.domain; struct ieee80211_country_ie_triplet *t; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_channel *ch; u8 num_triplet = 0; u8 num_parsed_chan = 0; @@ -777,7 +777,7 @@ int lbs_set_11d_domain_info(struct lbs_private *priv) * etc. */ for (band = 0; - (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS); + (band < NUM_NL80211_BANDS) && (num_triplet < MAX_11D_TRIPLETS); band++) { if (!bands[band]) diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index a47f0acc099a..0bf8916a02cf 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -570,7 +570,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) stats.flag |= RX_FLAG_FAILED_FCS_CRC; stats.freq = priv->cur_freq; - stats.band = IEEE80211_BAND_2GHZ; + stats.band = NL80211_BAND_2GHZ; stats.signal = prxpd->snr; priv->noise = prxpd->nf; /* Marvell rate index has a hole at value 4 */ @@ -642,7 +642,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) priv->band.bitrates = priv->rates; priv->band.n_channels = ARRAY_SIZE(lbtf_channels); priv->band.channels = priv->channels; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + hw->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 49661e087811..6db202fa7157 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -474,7 +474,7 @@ int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) u8 no_of_parsed_chan = 0; u8 first_chan = 0, next_chan = 0, max_pwr = 0; u8 i, flag = 0; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); @@ -1410,7 +1410,7 @@ mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats; - enum ieee80211_band band; + enum nl80211_band band; mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx); @@ -1586,7 +1586,7 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; - enum ieee80211_band band; + enum nl80211_band band; struct mwifiex_adapter *adapter = priv->adapter; if (!priv->media_connected) { @@ -1600,11 +1600,11 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, memset(bitmap_rates, 0, sizeof(bitmap_rates)); /* Fill HR/DSSS rates. */ - if (band == IEEE80211_BAND_2GHZ) + if (band == NL80211_BAND_2GHZ) bitmap_rates[0] = mask->control[band].legacy & 0x000f; /* Fill OFDM rates */ - if (band == IEEE80211_BAND_2GHZ) + if (band == NL80211_BAND_2GHZ) bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4; else bitmap_rates[1] = mask->control[band].legacy; @@ -1771,7 +1771,7 @@ mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) } else { struct ieee80211_sta_ht_cap *ht_info; int rx_mcs_supp; - enum ieee80211_band band; + enum nl80211_band band; if ((tx_ant == 0x1 && rx_ant == 0x1)) { adapter->user_dev_mcs_support = HT_STREAM_1X1; @@ -1785,7 +1785,7 @@ mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) MWIFIEX_11AC_MCS_MAP_2X2; } - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!adapter->wiphy->bands[band]) continue; @@ -1997,7 +1997,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) struct cfg80211_bss *bss; int ie_len; u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; - enum ieee80211_band band; + enum nl80211_band band; if (mwifiex_get_bss_info(priv, &bss_info)) return -1; @@ -2271,7 +2271,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, int index = 0, i; u8 config_bands = 0; - if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (params->chandef.chan->band == NL80211_BAND_2GHZ) { if (!params->basic_rates) { config_bands = BAND_B | BAND_G; } else { @@ -2859,18 +2859,18 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, mwifiex_init_priv_params(priv, dev); priv->netdev = dev; - mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); + mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv); if (adapter->is_hw_11ac_capable) mwifiex_setup_vht_caps( - &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv); + &wiphy->bands[NL80211_BAND_2GHZ]->vht_cap, priv); if (adapter->config_bands & BAND_A) mwifiex_setup_ht_caps( - &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); + &wiphy->bands[NL80211_BAND_5GHZ]->ht_cap, priv); if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable) mwifiex_setup_vht_caps( - &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv); + &wiphy->bands[NL80211_BAND_5GHZ]->vht_cap, priv); dev_net_set(dev, wiphy_net(wiphy)); dev->ieee80211_ptr = &priv->wdev; @@ -3821,7 +3821,7 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, struct ieee80211_channel *chan; u8 second_chan_offset; enum nl80211_channel_type chan_type; - enum ieee80211_band band; + enum nl80211_band band; int freq; int ret = -ENODATA; @@ -4053,11 +4053,11 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_AP); - wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; + wiphy->bands[NL80211_BAND_2GHZ] = &mwifiex_band_2ghz; if (adapter->config_bands & BAND_A) - wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; + wiphy->bands[NL80211_BAND_5GHZ] = &mwifiex_band_5ghz; else - wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + wiphy->bands[NL80211_BAND_5GHZ] = NULL; if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info)) wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs; diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c index 09fae27140f7..1ff22055e54f 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfp.c +++ b/drivers/net/wireless/marvell/mwifiex/cfp.c @@ -322,9 +322,9 @@ mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq) return cfp; if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) - sband = priv->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = priv->wdev.wiphy->bands[NL80211_BAND_2GHZ]; else - sband = priv->wdev.wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = priv->wdev.wiphy->bands[NL80211_BAND_5GHZ]; if (!sband) { mwifiex_dbg(priv->adapter, ERROR, @@ -399,15 +399,15 @@ u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv, int i; if (radio_type) { - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = wiphy->bands[NL80211_BAND_5GHZ]; if (WARN_ON_ONCE(!sband)) return 0; - rate_mask = request->rates[IEEE80211_BAND_5GHZ]; + rate_mask = request->rates[NL80211_BAND_5GHZ]; } else { - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = wiphy->bands[NL80211_BAND_2GHZ]; if (WARN_ON_ONCE(!sband)) return 0; - rate_mask = request->rates[IEEE80211_BAND_2GHZ]; + rate_mask = request->rates[NL80211_BAND_2GHZ]; } num_rates = 0; diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 489f7a911a83..624b0a95c64e 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -494,13 +494,13 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, *scan_chan_list, u8 filtered_scan) { - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; struct mwifiex_adapter *adapter = priv->adapter; int chan_idx = 0, i; - for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { + for (band = 0; (band < NUM_NL80211_BANDS) ; band++) { if (!priv->wdev.wiphy->bands[band]) continue; @@ -557,13 +557,13 @@ mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv, struct mwifiex_chan_scan_param_set *scan_chan_list) { - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; struct mwifiex_adapter *adapter = priv->adapter; int chan_idx = 0, i; - for (band = 0; (band < IEEE80211_NUM_BANDS); band++) { + for (band = 0; (band < NUM_NL80211_BANDS); band++) { if (!priv->wdev.wiphy->bands[band]) continue; diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c index 92ce32f5bb13..f79d00d1e294 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c @@ -816,7 +816,7 @@ void mwifiex_uap_set_channel(struct mwifiex_private *priv, chandef.chan->center_freq); /* Set appropriate bands */ - if (chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (chandef.chan->band == NL80211_BAND_2GHZ) { bss_cfg->band_cfg = BAND_CONFIG_BG; config_bands = BAND_B | BAND_G; diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index 088429d0a634..b1b400b59d86 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -346,20 +346,20 @@ struct mwl8k_sta { #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) static const struct ieee80211_channel mwl8k_channels_24[] = { - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, }, + { .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, }, }; static const struct ieee80211_rate mwl8k_rates_24[] = { @@ -379,10 +379,10 @@ static const struct ieee80211_rate mwl8k_rates_24[] = { }; static const struct ieee80211_channel mwl8k_channels_50[] = { - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, }, - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, }, - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, }, - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, }, + { .band = NL80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, }, + { .band = NL80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, }, + { .band = NL80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, }, + { .band = NL80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, }, }; static const struct ieee80211_rate mwl8k_rates_50[] = { @@ -1010,11 +1010,11 @@ mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, } if (rxd->channel > 14) { - status->band = IEEE80211_BAND_5GHZ; + status->band = NL80211_BAND_5GHZ; if (!(status->flag & RX_FLAG_HT)) status->rate_idx -= 5; } else { - status->band = IEEE80211_BAND_2GHZ; + status->band = NL80211_BAND_2GHZ; } status->freq = ieee80211_channel_to_frequency(rxd->channel, status->band); @@ -1118,11 +1118,11 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, status->flag |= RX_FLAG_HT; if (rxd->channel > 14) { - status->band = IEEE80211_BAND_5GHZ; + status->band = NL80211_BAND_5GHZ; if (!(status->flag & RX_FLAG_HT)) status->rate_idx -= 5; } else { - status->band = IEEE80211_BAND_2GHZ; + status->band = NL80211_BAND_2GHZ; } status->freq = ieee80211_channel_to_frequency(rxd->channel, status->band); @@ -2300,13 +2300,13 @@ static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw) BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24)); memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24)); - priv->band_24.band = IEEE80211_BAND_2GHZ; + priv->band_24.band = NL80211_BAND_2GHZ; priv->band_24.channels = priv->channels_24; priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24); priv->band_24.bitrates = priv->rates_24; priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; + hw->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band_24; } static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw) @@ -2319,13 +2319,13 @@ static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw) BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl8k_rates_50)); memcpy(priv->rates_50, mwl8k_rates_50, sizeof(mwl8k_rates_50)); - priv->band_50.band = IEEE80211_BAND_5GHZ; + priv->band_50.band = NL80211_BAND_5GHZ; priv->band_50.channels = priv->channels_50; priv->band_50.n_channels = ARRAY_SIZE(mwl8k_channels_50); priv->band_50.bitrates = priv->rates_50; priv->band_50.n_bitrates = ARRAY_SIZE(mwl8k_rates_50); - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; + hw->wiphy->bands[NL80211_BAND_5GHZ] = &priv->band_50; } /* @@ -2876,9 +2876,9 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw, cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le16(MWL8K_CMD_SET_LIST); - if (channel->band == IEEE80211_BAND_2GHZ) + if (channel->band == NL80211_BAND_2GHZ) cmd->band = cpu_to_le16(0x1); - else if (channel->band == IEEE80211_BAND_5GHZ) + else if (channel->band == NL80211_BAND_5GHZ) cmd->band = cpu_to_le16(0x4); cmd->channel = cpu_to_le16(channel->hw_value); @@ -3067,7 +3067,7 @@ static int freq_to_idx(struct mwl8k_priv *priv, int freq) struct ieee80211_supported_band *sband; int band, ch, idx = 0; - for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { + for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { sband = priv->hw->wiphy->bands[band]; if (!sband) continue; @@ -3149,9 +3149,9 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, cmd->action = cpu_to_le16(MWL8K_CMD_SET); cmd->current_channel = channel->hw_value; - if (channel->band == IEEE80211_BAND_2GHZ) + if (channel->band == NL80211_BAND_2GHZ) cmd->channel_flags |= cpu_to_le32(0x00000001); - else if (channel->band == IEEE80211_BAND_5GHZ) + else if (channel->band == NL80211_BAND_5GHZ) cmd->channel_flags |= cpu_to_le32(0x00000004); if (!priv->sw_scan_start) { @@ -4094,10 +4094,10 @@ static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, memcpy(cmd->mac_addr, sta->addr, ETH_ALEN); cmd->stn_id = cpu_to_le16(sta->aid); cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD); - if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) - rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; + if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) + rates = sta->supp_rates[NL80211_BAND_2GHZ]; else - rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; + rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5; cmd->legacy_rates = cpu_to_le32(rates); if (sta->ht_cap.ht_supported) { cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0]; @@ -4529,10 +4529,10 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, p->ht_caps = cpu_to_le16(sta->ht_cap.cap); p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) | ((sta->ht_cap.ampdu_density & 7) << 2); - if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) - rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; + if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) + rates = sta->supp_rates[NL80211_BAND_2GHZ]; else - rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; + rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5; legacy_rate_mask_to_array(p->legacy_rates, rates); memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16); p->interop = 1; @@ -5010,11 +5010,11 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; } - if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) { - ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; + if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) { + ap_legacy_rates = ap->supp_rates[NL80211_BAND_2GHZ]; } else { ap_legacy_rates = - ap->supp_rates[IEEE80211_BAND_5GHZ] << 5; + ap->supp_rates[NL80211_BAND_5GHZ] << 5; } memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16); @@ -5042,7 +5042,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, idx--; if (hw->conf.chandef.chan->band == - IEEE80211_BAND_2GHZ) + NL80211_BAND_2GHZ) rate = mwl8k_rates_24[idx].hw_value; else rate = mwl8k_rates_50[idx].hw_value; @@ -5116,7 +5116,7 @@ mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (idx) idx--; - if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) + if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) rate = mwl8k_rates_24[idx].hw_value; else rate = mwl8k_rates_50[idx].hw_value; @@ -5388,7 +5388,7 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, struct ieee80211_supported_band *sband; if (priv->ap_fw) { - sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = hw->wiphy->bands[NL80211_BAND_2GHZ]; if (sband && idx >= sband->n_channels) { idx -= sband->n_channels; @@ -5396,7 +5396,7 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, } if (!sband) - sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = hw->wiphy->bands[NL80211_BAND_5GHZ]; if (!sband || idx >= sband->n_channels) return -ENOENT; diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c index 26190fd33407..8fa78d7156be 100644 --- a/drivers/net/wireless/mediatek/mt7601u/init.c +++ b/drivers/net/wireless/mediatek/mt7601u/init.c @@ -469,7 +469,7 @@ struct mt7601u_dev *mt7601u_alloc_device(struct device *pdev) } #define CHAN2G(_idx, _freq) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_idx), \ .max_power = 30, \ @@ -563,7 +563,7 @@ mt76_init_sband_2g(struct mt7601u_dev *dev) { dev->sband_2g = devm_kzalloc(dev->dev, sizeof(*dev->sband_2g), GFP_KERNEL); - dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = dev->sband_2g; + dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = dev->sband_2g; WARN_ON(dev->ee->reg.start - 1 + dev->ee->reg.num > ARRAY_SIZE(mt76_channels_2ghz)); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 7fa0128de7e3..c36fa4e03fb6 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -777,7 +777,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2) u8 offset1; u8 offset2; - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) { rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); @@ -1174,7 +1174,7 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev, container_of(led_cdev, struct rt2x00_led, led_dev); unsigned int enabled = brightness != LED_OFF; unsigned int bg_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + (enabled && led->rt2x00dev->curr_band == NL80211_BAND_2GHZ); unsigned int polarity = rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, EEPROM_FREQ_LED_POLARITY); @@ -1741,7 +1741,7 @@ static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev) u8 led_ctrl, led_g_mode, led_r_mode; rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) { rt2x00_set_field32(®, GPIO_SWITCH_0, 1); rt2x00_set_field32(®, GPIO_SWITCH_1, 1); } else { @@ -1844,7 +1844,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) rt2x00_has_cap_bt_coexist(rt2x00dev)) { rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, - rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); + rt2x00dev->curr_band == NL80211_BAND_5GHZ); rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B); } else { rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); @@ -3451,7 +3451,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) * Matching Delta value -4 -3 -2 -1 0 +1 +2 +3 +4 * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 */ - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) { rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); tssi_bounds[0] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG1_MINUS4); @@ -3546,7 +3546,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) } static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, - enum ieee80211_band band) + enum nl80211_band band) { u16 eeprom; u8 comp_en; @@ -3562,7 +3562,7 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) return 0; - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { comp_en = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_DELTA_ENABLE_2G); if (comp_en) { @@ -3611,7 +3611,7 @@ static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev, } static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, - enum ieee80211_band band, int power_level, + enum nl80211_band band, int power_level, u8 txpower, int delta) { u16 eeprom; @@ -3639,7 +3639,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); - if (band == IEEE80211_BAND_2GHZ) + if (band == NL80211_BAND_2GHZ) eirp_txpower_criterion = rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ); else @@ -3686,7 +3686,7 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev, u16 eeprom; u32 regs[TX_PWR_CFG_IDX_COUNT]; unsigned int offset; - enum ieee80211_band band = chan->band; + enum nl80211_band band = chan->band; int delta; int i; @@ -3697,7 +3697,7 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev, /* calculate temperature compensation delta */ delta = rt2800_get_gain_calibration_delta(rt2x00dev); - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) offset = 16; else offset = 0; @@ -4055,7 +4055,7 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev, for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++) rt2x00_dbg(rt2x00dev, "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n", - (band == IEEE80211_BAND_5GHZ) ? '5' : '2', + (band == NL80211_BAND_5GHZ) ? '5' : '2', (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ? '4' : '2', (i > TX_PWR_CFG_9_IDX) ? @@ -4081,7 +4081,7 @@ static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev, u16 eeprom; u32 reg, offset; int i, is_rate_b, delta, power_ctrl; - enum ieee80211_band band = chan->band; + enum nl80211_band band = chan->band; /* * Calculate HT40 compensation. For 40MHz we need to add or subtract @@ -4436,7 +4436,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { u8 vgc; - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) { if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3090) || @@ -4511,7 +4511,7 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, case RT3572: case RT3593: if (qual->rssi > -65) { - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) + if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) vgc += 0x20; else vgc += 0x10; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 3dacede7da5e..f68d492129c6 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -753,8 +753,8 @@ struct rt2x00_dev { * IEEE80211 control structure. */ struct ieee80211_hw *hw; - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; - enum ieee80211_band curr_band; + struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; + enum nl80211_band curr_band; int curr_freq; /* diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c index b2f7c586045d..4e0c5653054b 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c @@ -911,7 +911,7 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, const int value) { /* XXX: this assumption about the band is wrong for 802.11j */ - entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + entry->band = channel <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; entry->center_freq = ieee80211_channel_to_frequency(channel, entry->band); entry->hw_value = value; @@ -975,13 +975,13 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Channels: 2.4 GHz */ if (spec->supported_bands & SUPPORT_BAND_2GHZ) { - rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14; - rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates; - rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels; - rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; - memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap, + rt2x00dev->bands[NL80211_BAND_2GHZ].n_channels = 14; + rt2x00dev->bands[NL80211_BAND_2GHZ].n_bitrates = num_rates; + rt2x00dev->bands[NL80211_BAND_2GHZ].channels = channels; + rt2x00dev->bands[NL80211_BAND_2GHZ].bitrates = rates; + hw->wiphy->bands[NL80211_BAND_2GHZ] = + &rt2x00dev->bands[NL80211_BAND_2GHZ]; + memcpy(&rt2x00dev->bands[NL80211_BAND_2GHZ].ht_cap, &spec->ht, sizeof(spec->ht)); } @@ -991,15 +991,15 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Channels: OFDM, UNII, HiperLAN2. */ if (spec->supported_bands & SUPPORT_BAND_5GHZ) { - rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels = + rt2x00dev->bands[NL80211_BAND_5GHZ].n_channels = spec->num_channels - 14; - rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates = + rt2x00dev->bands[NL80211_BAND_5GHZ].n_bitrates = num_rates - 4; - rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14]; - rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; - memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap, + rt2x00dev->bands[NL80211_BAND_5GHZ].channels = &channels[14]; + rt2x00dev->bands[NL80211_BAND_5GHZ].bitrates = &rates[4]; + hw->wiphy->bands[NL80211_BAND_5GHZ] = + &rt2x00dev->bands[NL80211_BAND_5GHZ]; + memcpy(&rt2x00dev->bands[NL80211_BAND_5GHZ].ht_cap, &spec->ht, sizeof(spec->ht)); } @@ -1016,11 +1016,11 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev) if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags)) ieee80211_unregister_hw(rt2x00dev->hw); - if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) { - kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels); - kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates); - rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; - rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + if (likely(rt2x00dev->hw->wiphy->bands[NL80211_BAND_2GHZ])) { + kfree(rt2x00dev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels); + kfree(rt2x00dev->hw->wiphy->bands[NL80211_BAND_2GHZ]->bitrates); + rt2x00dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + rt2x00dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL; } kfree(rt2x00dev->spec.channels_info); diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c index 24a3436ef952..03013eb2f642 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c @@ -252,9 +252,9 @@ static void rt61pci_brightness_set(struct led_classdev *led_cdev, container_of(led_cdev, struct rt2x00_led, led_dev); unsigned int enabled = brightness != LED_OFF; unsigned int a_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); + (enabled && led->rt2x00dev->curr_band == NL80211_BAND_5GHZ); unsigned int bg_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + (enabled && led->rt2x00dev->curr_band == NL80211_BAND_2GHZ); if (led->type == LED_TYPE_RADIO) { rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, @@ -643,12 +643,12 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ)); + (rt2x00dev->curr_band != NL80211_BAND_5GHZ)); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); @@ -657,7 +657,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, default: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); @@ -808,7 +808,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || ant->tx == ANTENNA_SW_DIVERSITY); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) { sel = antenna_sel_a; lna = rt2x00_has_cap_external_lna_a(rt2x00dev); } else { @@ -822,9 +822,9 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, ®); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + rt2x00dev->curr_band == NL80211_BAND_2GHZ); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); + rt2x00dev->curr_band == NL80211_BAND_5GHZ); rt2x00mmio_register_write(rt2x00dev, PHY_CSR0, reg); @@ -846,7 +846,7 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, u16 eeprom; short lna_gain = 0; - if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (libconf->conf->chandef.chan->band == NL80211_BAND_2GHZ) { if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) lna_gain += 14; @@ -1048,7 +1048,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, /* * Determine r17 bounds. */ - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { @@ -2077,7 +2077,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) { if (lna == 3 || lna == 2) offset += 10; } diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c index 7bbc86931168..c1397a6d3cee 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c @@ -197,9 +197,9 @@ static void rt73usb_brightness_set(struct led_classdev *led_cdev, container_of(led_cdev, struct rt2x00_led, led_dev); unsigned int enabled = brightness != LED_OFF; unsigned int a_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); + (enabled && led->rt2x00dev->curr_band == NL80211_BAND_5GHZ); unsigned int bg_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + (enabled && led->rt2x00dev->curr_band == NL80211_BAND_2GHZ); if (led->type == LED_TYPE_RADIO) { rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, @@ -593,13 +593,13 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); temp = !rt2x00_has_cap_frame_type(rt2x00dev) && - (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); + (rt2x00dev->curr_band != NL80211_BAND_5GHZ); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); @@ -608,7 +608,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, default: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); @@ -704,7 +704,7 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || ant->tx == ANTENNA_SW_DIVERSITY); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) { sel = antenna_sel_a; lna = rt2x00_has_cap_external_lna_a(rt2x00dev); } else { @@ -718,9 +718,9 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, rt2x00usb_register_read(rt2x00dev, PHY_CSR0, ®); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)); + (rt2x00dev->curr_band == NL80211_BAND_2GHZ)); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)); + (rt2x00dev->curr_band == NL80211_BAND_5GHZ)); rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); @@ -736,7 +736,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, u16 eeprom; short lna_gain = 0; - if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (libconf->conf->chandef.chan->band == NL80211_BAND_2GHZ) { if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) lna_gain += 14; @@ -923,7 +923,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, /* * Determine r17 bounds. */ - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; @@ -1657,7 +1657,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) { if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { if (lna == 3 || lna == 2) offset += 10; diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index c76af5d8b8e0..ba242d0160ec 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -526,7 +526,7 @@ static void rtl8180_tx(struct ieee80211_hw *dev, * ieee80211_generic_frame_duration */ duration = ieee80211_generic_frame_duration(dev, priv->vif, - IEEE80211_BAND_2GHZ, skb->len, + NL80211_BAND_2GHZ, skb->len, ieee80211_get_tx_rate(dev, info)); frame_duration = priv->ack_time + le16_to_cpu(duration); @@ -1529,7 +1529,7 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, priv->ack_time = le16_to_cpu(ieee80211_generic_frame_duration(dev, priv->vif, - IEEE80211_BAND_2GHZ, 10, + NL80211_BAND_2GHZ, 10, &priv->rates[0])) - 10; rtl8180_conf_erp(dev, info); @@ -1795,12 +1795,12 @@ static int rtl8180_probe(struct pci_dev *pdev, memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); - priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.band = NL80211_BAND_2GHZ; priv->band.channels = priv->channels; priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = 4; - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + dev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; ieee80211_hw_set(dev, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(dev, RX_INCLUDES_FCS); diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c index b7f72f9c7988..231f84db9ab0 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c @@ -1470,12 +1470,12 @@ static int rtl8187_probe(struct usb_interface *intf, memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); priv->map = (struct rtl818x_csr *)0xFF00; - priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.band = NL80211_BAND_2GHZ; priv->band.channels = priv->channels; priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + dev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; ieee80211_hw_set(dev, RX_INCLUDES_FCS); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 333addd3d46a..db8433a9efe2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -91,33 +91,33 @@ static struct ieee80211_rate rtl8xxxu_rates[] = { }; static struct ieee80211_channel rtl8xxxu_channels_2g[] = { - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, + { .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, + { .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, + { .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, + { .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, + { .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, + { .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, + { .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, + { .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, + { .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, + { .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, + { .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, + { .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, + { .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, .max_power = 30 }, - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, + { .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, .max_power = 30 } }; @@ -8378,7 +8378,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, dev_info(&udev->dev, "Enabling HT_20_40 on the 2.4GHz band\n"); sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; } - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; hw->wiphy->rts_threshold = 2347; diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 0517a4f2d3f2..c74eb139bfa1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -131,7 +131,7 @@ static struct ieee80211_rate rtl_ratetable_5g[] = { }; static const struct ieee80211_supported_band rtl_band_2ghz = { - .band = IEEE80211_BAND_2GHZ, + .band = NL80211_BAND_2GHZ, .channels = rtl_channeltable_2g, .n_channels = ARRAY_SIZE(rtl_channeltable_2g), @@ -143,7 +143,7 @@ static const struct ieee80211_supported_band rtl_band_2ghz = { }; static struct ieee80211_supported_band rtl_band_5ghz = { - .band = IEEE80211_BAND_5GHZ, + .band = NL80211_BAND_5GHZ, .channels = rtl_channeltable_5g, .n_channels = ARRAY_SIZE(rtl_channeltable_5g), @@ -197,7 +197,7 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - /*hw->wiphy->bands[IEEE80211_BAND_2GHZ] + /*hw->wiphy->bands[NL80211_BAND_2GHZ] *base on ant_num *rx_mask: RX mask *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 @@ -328,26 +328,26 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) rtlhal->bandset == BAND_ON_BOTH) { /* 1: 2.4 G bands */ /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + sband = &(rtlmac->bands[NL80211_BAND_2GHZ]); - /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + /* <2> set hw->wiphy->bands[NL80211_BAND_2GHZ] * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, + memcpy(&(rtlmac->bands[NL80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; /* 2: 5 G bands */ /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + sband = &(rtlmac->bands[NL80211_BAND_5GHZ]); - /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + /* <2> set hw->wiphy->bands[NL80211_BAND_5GHZ] * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, + memcpy(&(rtlmac->bands[NL80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); /* <3> init ht cap base on ant_num */ @@ -355,15 +355,15 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) _rtl_init_hw_vht_capab(hw, &sband->vht_cap); /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; } else { if (rtlhal->current_bandtype == BAND_ON_2_4G) { /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + sband = &(rtlmac->bands[NL80211_BAND_2GHZ]); - /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + /* <2> set hw->wiphy->bands[NL80211_BAND_2GHZ] * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), + memcpy(&(rtlmac->bands[NL80211_BAND_2GHZ]), &rtl_band_2ghz, sizeof(struct ieee80211_supported_band)); @@ -371,14 +371,14 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) _rtl_init_hw_ht_capab(hw, &sband->ht_cap); /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; } else if (rtlhal->current_bandtype == BAND_ON_5G) { /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + sband = &(rtlmac->bands[NL80211_BAND_5GHZ]); - /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + /* <2> set hw->wiphy->bands[NL80211_BAND_5GHZ] * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), + memcpy(&(rtlmac->bands[NL80211_BAND_5GHZ]), &rtl_band_5ghz, sizeof(struct ieee80211_supported_band)); @@ -387,7 +387,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) _rtl_init_hw_vht_capab(hw, &sband->vht_cap); /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Err BAND %d\n", rtlhal->current_bandtype); @@ -861,7 +861,7 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw, /* mac80211's rate_idx is like this: * - * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ + * 2.4G band:rx_status->band == NL80211_BAND_2GHZ * * B/G rate: * (rx_status->flag & RX_FLAG_HT) = 0, @@ -871,7 +871,7 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw, * (rx_status->flag & RX_FLAG_HT) = 1, * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 * - * 5G band:rx_status->band == IEEE80211_BAND_5GHZ + * 5G band:rx_status->band == NL80211_BAND_5GHZ * A rate: * (rx_status->flag & RX_FLAG_HT) = 0, * DESC_RATE6M-->DESC_RATE54M ==> idx is 0-->7, @@ -958,7 +958,7 @@ int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, bool isvht, return rate_idx; } if (false == isht) { - if (IEEE80211_BAND_2GHZ == hw->conf.chandef.chan->band) { + if (NL80211_BAND_2GHZ == hw->conf.chandef.chan->band) { switch (desc_rate) { case DESC_RATE1M: rate_idx = 0; diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index 5be34118e0af..3524441fd516 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -154,13 +154,13 @@ static bool _rtl_is_radar_freq(u16 center_freq) static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; const struct ieee80211_reg_rule *reg_rule; struct ieee80211_channel *ch; unsigned int i; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!wiphy->bands[band]) continue; @@ -210,9 +210,9 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, struct ieee80211_channel *ch; const struct ieee80211_reg_rule *reg_rule; - if (!wiphy->bands[IEEE80211_BAND_2GHZ]) + if (!wiphy->bands[NL80211_BAND_2GHZ]) return; - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = wiphy->bands[NL80211_BAND_2GHZ]; /* *If no country IE has been received always enable active scan @@ -262,10 +262,10 @@ static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy) struct ieee80211_channel *ch; unsigned int i; - if (!wiphy->bands[IEEE80211_BAND_5GHZ]) + if (!wiphy->bands[NL80211_BAND_5GHZ]) return; - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = wiphy->bands[NL80211_BAND_5GHZ]; for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; @@ -301,12 +301,12 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy, static void _rtl_dump_channel_map(struct wiphy *wiphy) { - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; unsigned int i; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!wiphy->bands[band]) continue; sband = wiphy->bands[band]; diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 389dc47776c0..11d9c2307e2f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1359,7 +1359,7 @@ struct rtl_mac { u32 tx_ss_num; u32 rx_ss_num; - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; struct ieee80211_hw *hw; struct ieee80211_vif *vif; enum nl80211_iftype opmode; diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index a13d1f2b5912..569918c485b4 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1291,7 +1291,7 @@ static int set_channel(struct usbnet *usbdev, int channel) return 0; dsconfig = 1000 * - ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ); + ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ); len = sizeof(config); ret = rndis_query_oid(usbdev, @@ -3476,7 +3476,7 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) priv->band.n_channels = ARRAY_SIZE(rndis_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = ARRAY_SIZE(rndis_rates); - wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; memcpy(priv->cipher_suites, rndis_cipher_suites, diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 4df992de7d07..dbb23899ddcb 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -20,84 +20,84 @@ #include "rsi_common.h" static const struct ieee80211_channel rsi_2ghz_channels[] = { - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, + { .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1 }, /* Channel 1 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, + { .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2 }, /* Channel 2 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, + { .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3 }, /* Channel 3 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, + { .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4 }, /* Channel 4 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, + { .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5 }, /* Channel 5 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, + { .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6 }, /* Channel 6 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, + { .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7 }, /* Channel 7 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, + { .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8 }, /* Channel 8 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, + { .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9 }, /* Channel 9 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, + { .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10 }, /* Channel 10 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, + { .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11 }, /* Channel 11 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, + { .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12 }, /* Channel 12 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, + { .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13 }, /* Channel 13 */ - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, + { .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14 }, /* Channel 14 */ }; static const struct ieee80211_channel rsi_5ghz_channels[] = { - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, + { .band = NL80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, }, /* Channel 36 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, + { .band = NL80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, }, /* Channel 40 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, + { .band = NL80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, }, /* Channel 44 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5240, + { .band = NL80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, }, /* Channel 48 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5260, + { .band = NL80211_BAND_5GHZ, .center_freq = 5260, .hw_value = 52, }, /* Channel 52 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5280, + { .band = NL80211_BAND_5GHZ, .center_freq = 5280, .hw_value = 56, }, /* Channel 56 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5300, + { .band = NL80211_BAND_5GHZ, .center_freq = 5300, .hw_value = 60, }, /* Channel 60 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5320, + { .band = NL80211_BAND_5GHZ, .center_freq = 5320, .hw_value = 64, }, /* Channel 64 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5500, + { .band = NL80211_BAND_5GHZ, .center_freq = 5500, .hw_value = 100, }, /* Channel 100 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5520, + { .band = NL80211_BAND_5GHZ, .center_freq = 5520, .hw_value = 104, }, /* Channel 104 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5540, + { .band = NL80211_BAND_5GHZ, .center_freq = 5540, .hw_value = 108, }, /* Channel 108 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5560, + { .band = NL80211_BAND_5GHZ, .center_freq = 5560, .hw_value = 112, }, /* Channel 112 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5580, + { .band = NL80211_BAND_5GHZ, .center_freq = 5580, .hw_value = 116, }, /* Channel 116 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5600, + { .band = NL80211_BAND_5GHZ, .center_freq = 5600, .hw_value = 120, }, /* Channel 120 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5620, + { .band = NL80211_BAND_5GHZ, .center_freq = 5620, .hw_value = 124, }, /* Channel 124 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5640, + { .band = NL80211_BAND_5GHZ, .center_freq = 5640, .hw_value = 128, }, /* Channel 128 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5660, + { .band = NL80211_BAND_5GHZ, .center_freq = 5660, .hw_value = 132, }, /* Channel 132 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5680, + { .band = NL80211_BAND_5GHZ, .center_freq = 5680, .hw_value = 136, }, /* Channel 136 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5700, + { .band = NL80211_BAND_5GHZ, .center_freq = 5700, .hw_value = 140, }, /* Channel 140 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5745, + { .band = NL80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, }, /* Channel 149 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5765, + { .band = NL80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, }, /* Channel 153 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5785, + { .band = NL80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, }, /* Channel 157 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5805, + { .band = NL80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, }, /* Channel 161 */ - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5825, + { .band = NL80211_BAND_5GHZ, .center_freq = 5825, .hw_value = 165, }, /* Channel 165 */ }; @@ -150,12 +150,12 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) struct ieee80211_supported_band *sbands = &adapter->sbands[band]; void *channels = NULL; - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL); memcpy(channels, rsi_2ghz_channels, sizeof(rsi_2ghz_channels)); - sbands->band = IEEE80211_BAND_2GHZ; + sbands->band = NL80211_BAND_2GHZ; sbands->n_channels = ARRAY_SIZE(rsi_2ghz_channels); sbands->bitrates = rsi_rates; sbands->n_bitrates = ARRAY_SIZE(rsi_rates); @@ -164,7 +164,7 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) memcpy(channels, rsi_5ghz_channels, sizeof(rsi_5ghz_channels)); - sbands->band = IEEE80211_BAND_5GHZ; + sbands->band = NL80211_BAND_5GHZ; sbands->n_channels = ARRAY_SIZE(rsi_5ghz_channels); sbands->bitrates = &rsi_rates[4]; sbands->n_bitrates = ARRAY_SIZE(rsi_rates) - 4; @@ -775,7 +775,7 @@ static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw, { struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; - enum ieee80211_band band = hw->conf.chandef.chan->band; + enum nl80211_band band = hw->conf.chandef.chan->band; mutex_lock(&common->mutex); common->fixedrate_mask[band] = 0; @@ -999,8 +999,8 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw, mutex_lock(&common->mutex); /* Resetting all the fields to default values */ - common->bitrate_mask[IEEE80211_BAND_2GHZ] = 0; - common->bitrate_mask[IEEE80211_BAND_5GHZ] = 0; + common->bitrate_mask[NL80211_BAND_2GHZ] = 0; + common->bitrate_mask[NL80211_BAND_5GHZ] = 0; common->min_rate = 0xffff; common->vif_info[0].is_ht = false; common->vif_info[0].sgi = false; @@ -1070,8 +1070,8 @@ int rsi_mac80211_attach(struct rsi_common *common) hw->max_rate_tries = MAX_RETRIES; hw->max_tx_aggregation_subframes = 6; - rsi_register_rates_channels(adapter, IEEE80211_BAND_2GHZ); - rsi_register_rates_channels(adapter, IEEE80211_BAND_5GHZ); + rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ); + rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ); hw->rate_control_algorithm = "AARF"; SET_IEEE80211_PERM_ADDR(hw, common->mac_addr); @@ -1087,10 +1087,10 @@ int rsi_mac80211_attach(struct rsi_common *common) wiphy->available_antennas_rx = 1; wiphy->available_antennas_tx = 1; - wiphy->bands[IEEE80211_BAND_2GHZ] = - &adapter->sbands[IEEE80211_BAND_2GHZ]; - wiphy->bands[IEEE80211_BAND_5GHZ] = - &adapter->sbands[IEEE80211_BAND_5GHZ]; + wiphy->bands[NL80211_BAND_2GHZ] = + &adapter->sbands[NL80211_BAND_2GHZ]; + wiphy->bands[NL80211_BAND_5GHZ] = + &adapter->sbands[NL80211_BAND_5GHZ]; status = ieee80211_register_hw(hw); if (status) diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index e43b59d5b53b..40658b62d077 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -210,7 +210,7 @@ static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130}; */ static void rsi_set_default_parameters(struct rsi_common *common) { - common->band = IEEE80211_BAND_2GHZ; + common->band = NL80211_BAND_2GHZ; common->channel_width = BW_20MHZ; common->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; common->channel = 1; @@ -655,7 +655,7 @@ int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode) vap_caps->rts_threshold = cpu_to_le16(common->rts_threshold); vap_caps->default_mgmt_rate = cpu_to_le32(RSI_RATE_6); - if (common->band == IEEE80211_BAND_5GHZ) { + if (common->band == NL80211_BAND_5GHZ) { vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_6); if (conf_is_ht40(&common->priv->hw->conf)) { vap_caps->default_ctrl_rate |= @@ -872,7 +872,7 @@ int rsi_band_check(struct rsi_common *common) else common->channel_width = BW_40MHZ; - if (common->band == IEEE80211_BAND_2GHZ) { + if (common->band == NL80211_BAND_2GHZ) { if (common->channel_width) common->endpoint = EP_2GHZ_40MHZ; else @@ -1046,7 +1046,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common) if (common->channel_width == BW_40MHZ) auto_rate->desc_word[7] |= cpu_to_le16(1); - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { min_rate = RSI_RATE_1; rate_table_offset = 0; } else { diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c index a0b31c0cf25b..02920c93e82d 100644 --- a/drivers/net/wireless/rsi/rsi_91x_pkt.c +++ b/drivers/net/wireless/rsi/rsi_91x_pkt.c @@ -184,7 +184,7 @@ int rsi_send_mgmt_pkt(struct rsi_common *common, if (wh->addr1[0] & BIT(0)) msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT); - if (common->band == IEEE80211_BAND_2GHZ) + if (common->band == NL80211_BAND_2GHZ) msg[4] = cpu_to_le16(RSI_11B_MODE); else msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE); diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 5baed945f60e..dcd095787166 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -211,7 +211,7 @@ struct rsi_hw { struct ieee80211_hw *hw; struct ieee80211_vif *vifs[RSI_MAX_VIFS]; struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES]; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band sbands[NUM_NL80211_BANDS]; struct device *device; u8 sc_nvifs; diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c index 0e51e27d2e3f..dc478cedbde0 100644 --- a/drivers/net/wireless/st/cw1200/main.c +++ b/drivers/net/wireless/st/cw1200/main.c @@ -102,7 +102,7 @@ static struct ieee80211_rate cw1200_mcs_rates[] = { #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -111,7 +111,7 @@ static struct ieee80211_rate cw1200_mcs_rates[] = { } #define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + (5 * (_channel)), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -311,12 +311,12 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, hw->sta_data_size = sizeof(struct cw1200_sta_priv); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &cw1200_band_2ghz; + hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz; if (have_5ghz) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &cw1200_band_5ghz; + hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz; /* Channel params have to be cleared before registering wiphy again */ - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { struct ieee80211_supported_band *sband = hw->wiphy->bands[band]; if (!sband) continue; diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c index bff81b8d4164..983788156bb0 100644 --- a/drivers/net/wireless/st/cw1200/scan.c +++ b/drivers/net/wireless/st/cw1200/scan.c @@ -402,7 +402,7 @@ void cw1200_probe_work(struct work_struct *work) } wsm = (struct wsm_tx *)frame.skb->data; scan.max_tx_rate = wsm->max_tx_rate; - scan.band = (priv->channel->band == IEEE80211_BAND_5GHZ) ? + scan.band = (priv->channel->band == NL80211_BAND_5GHZ) ? WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G; if (priv->join_status == CW1200_JOIN_STATUS_STA || priv->join_status == CW1200_JOIN_STATUS_IBSS) { diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index d0ddcde6c695..daf06a4f842e 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c @@ -1278,7 +1278,7 @@ static void cw1200_do_join(struct cw1200_common *priv) join.dtim_period = priv->join_dtim_period; join.channel_number = priv->channel->hw_value; - join.band = (priv->channel->band == IEEE80211_BAND_5GHZ) ? + join.band = (priv->channel->band == NL80211_BAND_5GHZ) ? WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G; memcpy(join.bssid, bssid, sizeof(join.bssid)); @@ -1462,7 +1462,7 @@ int cw1200_enable_listening(struct cw1200_common *priv) }; if (priv->channel) { - start.band = priv->channel->band == IEEE80211_BAND_5GHZ ? + start.band = priv->channel->band == NL80211_BAND_5GHZ ? WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G; start.channel_number = priv->channel->hw_value; } else { @@ -2315,7 +2315,7 @@ static int cw1200_start_ap(struct cw1200_common *priv) struct wsm_start start = { .mode = priv->vif->p2p ? WSM_START_MODE_P2P_GO : WSM_START_MODE_AP, - .band = (priv->channel->band == IEEE80211_BAND_5GHZ) ? + .band = (priv->channel->band == NL80211_BAND_5GHZ) ? WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G, .channel_number = priv->channel->hw_value, .beacon_interval = conf->beacon_int, diff --git a/drivers/net/wireless/st/cw1200/txrx.c b/drivers/net/wireless/st/cw1200/txrx.c index d28bd49cb5fd..3d170287cd0b 100644 --- a/drivers/net/wireless/st/cw1200/txrx.c +++ b/drivers/net/wireless/st/cw1200/txrx.c @@ -1079,7 +1079,7 @@ void cw1200_rx_cb(struct cw1200_common *priv, hdr->band = ((arg->channel_number & 0xff00) || (arg->channel_number > 14)) ? - IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; + NL80211_BAND_5GHZ : NL80211_BAND_2GHZ; hdr->freq = ieee80211_channel_to_frequency( arg->channel_number, hdr->band); diff --git a/drivers/net/wireless/st/cw1200/wsm.c b/drivers/net/wireless/st/cw1200/wsm.c index 9e0ca3048657..680d60eabc75 100644 --- a/drivers/net/wireless/st/cw1200/wsm.c +++ b/drivers/net/wireless/st/cw1200/wsm.c @@ -849,9 +849,9 @@ static int wsm_startup_indication(struct cw1200_common *priv, /* Disable unsupported frequency bands */ if (!(priv->wsm_caps.fw_cap & 0x1)) - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; if (!(priv->wsm_caps.fw_cap & 0x2)) - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL; priv->firmware_ready = 1; wake_up(&priv->wsm_startup_done); diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index cd4777954f87..56384a4e2a35 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c @@ -1482,7 +1482,7 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); wl->hw->wiphy->max_scan_ssids = 1; - wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; + wl->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wl1251_band_2ghz; wl->hw->queues = 4; diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c index cde0eaf99714..a27d4c22b6e8 100644 --- a/drivers/net/wireless/ti/wl1251/rx.c +++ b/drivers/net/wireless/ti/wl1251/rx.c @@ -53,7 +53,7 @@ static void wl1251_rx_status(struct wl1251 *wl, memset(status, 0, sizeof(struct ieee80211_rx_status)); - status->band = IEEE80211_BAND_2GHZ; + status->band = NL80211_BAND_2GHZ; status->mactime = desc->timestamp; /* diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index a0d6cccc56f3..58b9d3c3a833 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -469,8 +469,8 @@ static const u8 wl12xx_rate_to_idx_5ghz[] = { }; static const u8 *wl12xx_band_rate_to_idx[] = { - [IEEE80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz, - [IEEE80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz + [NL80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz, + [NL80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz }; enum wl12xx_hw_rates { @@ -1827,8 +1827,8 @@ static int wl12xx_setup(struct wl1271 *wl) wl->fw_status_priv_len = 0; wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); wl->ofdm_only_ap = true; - wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap); - wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap); + wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ, &wl12xx_ht_cap); + wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ, &wl12xx_ht_cap); wl12xx_conf_init(wl); if (!fref_param) { diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c index a0dfc59e9644..8d475393f9e3 100644 --- a/drivers/net/wireless/ti/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wl12xx/scan.c @@ -27,7 +27,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, struct cfg80211_scan_request *req, struct basic_scan_channel_params *channels, - enum ieee80211_band band, bool passive) + enum nl80211_band band, bool passive) { struct conf_scan_settings *c = &wl->conf.scan; int i, j; @@ -92,7 +92,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, #define WL1271_NOTHING_TO_SCAN 1 static int wl1271_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum ieee80211_band band, + enum nl80211_band band, bool passive, u32 basic_rate) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); @@ -144,7 +144,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif, cmd->params.tid_trigger = CONF_TX_AC_ANY_TID; cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; - if (band == IEEE80211_BAND_2GHZ) + if (band == NL80211_BAND_2GHZ) cmd->params.band = WL1271_SCAN_BAND_2_4_GHZ; else cmd->params.band = WL1271_SCAN_BAND_5_GHZ; @@ -218,7 +218,7 @@ int wl12xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret = 0; - enum ieee80211_band band; + enum nl80211_band band; u32 rate, mask; switch (wl->scan.state) { @@ -226,7 +226,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif) break; case WL1271_SCAN_STATE_2GHZ_ACTIVE: - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; mask = wlvif->bitrate_masks[band]; if (wl->scan.req->no_cck) { mask &= ~CONF_TX_CCK_RATES; @@ -243,7 +243,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif) break; case WL1271_SCAN_STATE_2GHZ_PASSIVE: - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; mask = wlvif->bitrate_masks[band]; if (wl->scan.req->no_cck) { mask &= ~CONF_TX_CCK_RATES; @@ -263,7 +263,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif) break; case WL1271_SCAN_STATE_5GHZ_ACTIVE: - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, wlvif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { @@ -274,7 +274,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif) break; case WL1271_SCAN_STATE_5GHZ_PASSIVE: - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, wlvif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { @@ -378,7 +378,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, wl12xx_adjust_channels(cfg, cfg_channels); if (!force_passive && cfg->active[0]) { - u8 band = IEEE80211_BAND_2GHZ; + u8 band = NL80211_BAND_2GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, wlvif->role_id, band, req->ssids[0].ssid, @@ -395,7 +395,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, } if (!force_passive && cfg->active[1]) { - u8 band = IEEE80211_BAND_5GHZ; + u8 band = NL80211_BAND_5GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, wlvif->role_id, band, req->ssids[0].ssid, diff --git a/drivers/net/wireless/ti/wl18xx/cmd.c b/drivers/net/wireless/ti/wl18xx/cmd.c index a8d176ddc73c..63e95ba744fd 100644 --- a/drivers/net/wireless/ti/wl18xx/cmd.c +++ b/drivers/net/wireless/ti/wl18xx/cmd.c @@ -48,10 +48,10 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl, cmd->stop_tx = ch_switch->block_tx; switch (ch_switch->chandef.chan->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: cmd->band = WLCORE_BAND_2_4GHZ; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: cmd->band = WLCORE_BAND_5GHZ; break; default: @@ -187,7 +187,7 @@ int wl18xx_cmd_set_cac(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool start) cmd->role_id = wlvif->role_id; cmd->channel = wlvif->channel; - if (wlvif->band == IEEE80211_BAND_5GHZ) + if (wlvif->band == NL80211_BAND_5GHZ) cmd->band = WLCORE_BAND_5GHZ; cmd->bandwidth = wlcore_get_native_channel_type(wlvif->channel_type); diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c index ff6e46dd61f8..ef811848d141 100644 --- a/drivers/net/wireless/ti/wl18xx/event.c +++ b/drivers/net/wireless/ti/wl18xx/event.c @@ -64,13 +64,13 @@ static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel, u8 sync_band) { struct sk_buff *skb; - enum ieee80211_band band; + enum nl80211_band band; int freq; if (sync_band == WLCORE_BAND_5GHZ) - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; else - band = IEEE80211_BAND_2GHZ; + band = NL80211_BAND_2GHZ; freq = ieee80211_channel_to_frequency(sync_channel, band); diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 1bf26cc7374e..ae47c79cb9b6 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -137,8 +137,8 @@ static const u8 wl18xx_rate_to_idx_5ghz[] = { }; static const u8 *wl18xx_band_rate_to_idx[] = { - [IEEE80211_BAND_2GHZ] = wl18xx_rate_to_idx_2ghz, - [IEEE80211_BAND_5GHZ] = wl18xx_rate_to_idx_5ghz + [NL80211_BAND_2GHZ] = wl18xx_rate_to_idx_2ghz, + [NL80211_BAND_5GHZ] = wl18xx_rate_to_idx_5ghz }; enum wl18xx_hw_rates { @@ -1302,12 +1302,12 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); /* sanity check - we don't support this */ - if (WARN_ON(wlvif->band != IEEE80211_BAND_5GHZ)) + if (WARN_ON(wlvif->band != NL80211_BAND_5GHZ)) return 0; return CONF_TX_RATE_USE_WIDE_CHAN; } else if (wl18xx_is_mimo_supported(wl) && - wlvif->band == IEEE80211_BAND_2GHZ) { + wlvif->band == NL80211_BAND_2GHZ) { wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); /* * we don't care about HT channel here - if a peer doesn't @@ -1996,24 +1996,24 @@ static int wl18xx_setup(struct wl1271 *wl) * siso40. */ if (wl18xx_is_mimo_supported(wl)) - wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, + wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ, &wl18xx_mimo_ht_cap_2ghz); else - wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, + wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ, &wl18xx_siso40_ht_cap_2ghz); /* 5Ghz is always wide */ - wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, + wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ, &wl18xx_siso40_ht_cap_5ghz); } else if (priv->conf.ht.mode == HT_MODE_WIDE) { - wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, + wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ, &wl18xx_siso40_ht_cap_2ghz); - wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, + wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ, &wl18xx_siso40_ht_cap_5ghz); } else if (priv->conf.ht.mode == HT_MODE_SISO20) { - wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, + wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ, &wl18xx_siso20_ht_cap); - wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, + wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ, &wl18xx_siso20_ht_cap); } diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c index bc15aa2c3efa..4e5221544354 100644 --- a/drivers/net/wireless/ti/wl18xx/scan.c +++ b/drivers/net/wireless/ti/wl18xx/scan.c @@ -110,7 +110,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* TODO: per-band ies? */ if (cmd->active[0]) { - u8 band = IEEE80211_BAND_2GHZ; + u8 band = NL80211_BAND_2GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, cmd->role_id, band, req->ssids ? req->ssids[0].ssid : NULL, @@ -127,7 +127,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif, } if (cmd->active[1] || cmd->dfs) { - u8 band = IEEE80211_BAND_5GHZ; + u8 band = NL80211_BAND_5GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, cmd->role_id, band, req->ssids ? req->ssids[0].ssid : NULL, @@ -253,7 +253,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl, cmd->terminate_on_report = 0; if (cmd->active[0]) { - u8 band = IEEE80211_BAND_2GHZ; + u8 band = NL80211_BAND_2GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, cmd->role_id, band, req->ssids ? req->ssids[0].ssid : NULL, @@ -270,7 +270,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl, } if (cmd->active[1] || cmd->dfs) { - u8 band = IEEE80211_BAND_5GHZ; + u8 band = NL80211_BAND_5GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, cmd->role_id, band, req->ssids ? req->ssids[0].ssid : NULL, diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c index 3406ffb53325..ebaf66ef3f84 100644 --- a/drivers/net/wireless/ti/wl18xx/tx.c +++ b/drivers/net/wireless/ti/wl18xx/tx.c @@ -43,7 +43,7 @@ void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) { rate->idx = fw_rate; - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) rate->idx -= CONF_HW_RATE_INDEX_6MBPS; rate->flags = 0; } else { diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index f01d24baff7c..33153565ad62 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -423,7 +423,7 @@ EXPORT_SYMBOL_GPL(wlcore_get_native_channel_type); static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum ieee80211_band band, + enum nl80211_band band, int channel) { struct wl12xx_cmd_role_start *cmd; @@ -438,7 +438,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); cmd->role_id = wlvif->dev_role_id; - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) cmd->band = WLCORE_BAND_5GHZ; cmd->channel = channel; @@ -524,7 +524,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id); cmd->role_id = wlvif->role_id; - if (wlvif->band == IEEE80211_BAND_5GHZ) + if (wlvif->band == NL80211_BAND_5GHZ) cmd->band = WLCORE_BAND_5GHZ; cmd->channel = wlvif->channel; cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); @@ -693,10 +693,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ap.local_rates = cpu_to_le32(supported_rates); switch (wlvif->band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: cmd->band = WLCORE_BAND_2_4GHZ; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: cmd->band = WLCORE_BAND_5GHZ; break; default: @@ -773,7 +773,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wlvif->role_id); cmd->role_id = wlvif->role_id; - if (wlvif->band == IEEE80211_BAND_5GHZ) + if (wlvif->band == NL80211_BAND_5GHZ) cmd->band = WLCORE_BAND_5GHZ; cmd->channel = wlvif->channel; cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); @@ -1164,7 +1164,7 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, } rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); - if (band == IEEE80211_BAND_2GHZ) + if (band == NL80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, role_id, template_id_2_4, skb->data, skb->len, 0, rate); @@ -1195,7 +1195,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, wl1271_debug(DEBUG_SCAN, "set ap probe request template"); rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); - if (wlvif->band == IEEE80211_BAND_2GHZ) + if (wlvif->band == NL80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); @@ -1628,19 +1628,19 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -static int wlcore_get_reg_conf_ch_idx(enum ieee80211_band band, u16 ch) +static int wlcore_get_reg_conf_ch_idx(enum nl80211_band band, u16 ch) { /* * map the given band/channel to the respective predefined * bit expected by the fw */ switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: /* channels 1..14 are mapped to 0..13 */ if (ch >= 1 && ch <= 14) return ch - 1; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: switch (ch) { case 8 ... 16: /* channels 8,12,16 are mapped to 18,19,20 */ @@ -1670,7 +1670,7 @@ static int wlcore_get_reg_conf_ch_idx(enum ieee80211_band band, u16 ch) } void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, - enum ieee80211_band band) + enum nl80211_band band) { int ch_bit_idx = 0; @@ -1699,7 +1699,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) memset(tmp_ch_bitmap, 0, sizeof(tmp_ch_bitmap)); - for (b = IEEE80211_BAND_2GHZ; b <= IEEE80211_BAND_5GHZ; b++) { + for (b = NL80211_BAND_2GHZ; b <= NL80211_BAND_5GHZ; b++) { band = wiphy->bands[b]; for (i = 0; i < band->n_channels; i++) { struct ieee80211_channel *channel = &band->channels[i]; @@ -1851,7 +1851,7 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) } static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 role_id, enum ieee80211_band band, u8 channel) + u8 role_id, enum nl80211_band band, u8 channel) { struct wl12xx_cmd_roc *cmd; int ret = 0; @@ -1870,10 +1870,10 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, cmd->role_id = role_id; cmd->channel = channel; switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: cmd->band = WLCORE_BAND_2_4GHZ; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: cmd->band = WLCORE_BAND_5GHZ; break; default: @@ -1925,7 +1925,7 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id) } int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id, - enum ieee80211_band band, u8 channel) + enum nl80211_band band, u8 channel) { int ret = 0; @@ -1995,7 +1995,7 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl, struct wl12xx_vif *wlvif) /* start dev role and roc on its channel */ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum ieee80211_band band, int channel) + enum nl80211_band band, int channel) { int ret; diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index e28e2f2303ce..52c3b4860461 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -40,7 +40,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum ieee80211_band band, int channel); + enum nl80211_band band, int channel); int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, @@ -83,14 +83,14 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, int wl12xx_cmd_set_peer_state(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id, - enum ieee80211_band band, u8 channel); + enum nl80211_band band, u8 channel); int wl12xx_croc(struct wl1271 *wl, u8 role_id); int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct ieee80211_sta *sta, u8 hlid); int wl12xx_cmd_remove_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, - enum ieee80211_band band); + enum nl80211_band band); int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl); int wlcore_cmd_generic_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 feature, u8 enable, u8 value); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index a872a07a484c..10fd24c28ece 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1930,7 +1930,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) wlcore_enable_interrupts(wl); - wl->band = IEEE80211_BAND_2GHZ; + wl->band = NL80211_BAND_2GHZ; wl->rx_counter = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; @@ -2240,8 +2240,8 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wlvif->rate_set = CONF_TX_ENABLED_RATES; } - wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; - wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; + wlvif->bitrate_masks[NL80211_BAND_2GHZ] = wl->conf.tx.basic_rate; + wlvif->bitrate_masks[NL80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; /* @@ -2330,7 +2330,7 @@ static int wl12xx_init_fw(struct wl1271 *wl) * 11a channels if not supported */ if (!wl->enable_11a) - wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels = 0; + wiphy->bands[NL80211_BAND_5GHZ]->n_channels = 0; wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", wl->enable_11a ? "" : "not "); @@ -5871,7 +5871,7 @@ static const struct ieee80211_ops wl1271_ops = { }; -u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band) +u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum nl80211_band band) { u8 idx; @@ -6096,21 +6096,21 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) * We keep local copies of the band structs because we need to * modify them on a per-device basis. */ - memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, + memcpy(&wl->bands[NL80211_BAND_2GHZ], &wl1271_band_2ghz, sizeof(wl1271_band_2ghz)); - memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, - &wl->ht_cap[IEEE80211_BAND_2GHZ], + memcpy(&wl->bands[NL80211_BAND_2GHZ].ht_cap, + &wl->ht_cap[NL80211_BAND_2GHZ], sizeof(*wl->ht_cap)); - memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, + memcpy(&wl->bands[NL80211_BAND_5GHZ], &wl1271_band_5ghz, sizeof(wl1271_band_5ghz)); - memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, - &wl->ht_cap[IEEE80211_BAND_5GHZ], + memcpy(&wl->bands[NL80211_BAND_5GHZ].ht_cap, + &wl->ht_cap[NL80211_BAND_5GHZ], sizeof(*wl->ht_cap)); - wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &wl->bands[IEEE80211_BAND_2GHZ]; - wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &wl->bands[IEEE80211_BAND_5GHZ]; + wl->hw->wiphy->bands[NL80211_BAND_2GHZ] = + &wl->bands[NL80211_BAND_2GHZ]; + wl->hw->wiphy->bands[NL80211_BAND_5GHZ] = + &wl->bands[NL80211_BAND_5GHZ]; /* * allow 4 queues per mac address we support + @@ -6205,7 +6205,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size, wl->channel = 0; wl->rx_counter = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->band = IEEE80211_BAND_2GHZ; + wl->band = NL80211_BAND_2GHZ; wl->channel_type = NL80211_CHAN_NO_HT; wl->flags = 0; wl->sg_enabled = true; diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index d4420da637d8..b36133b739cb 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c @@ -202,7 +202,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, * enable beacon early termination. * Not relevant for 5GHz and for high rates. */ - if ((wlvif->band == IEEE80211_BAND_2GHZ) && + if ((wlvif->band == NL80211_BAND_2GHZ) && (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) { ret = wl1271_acx_bet_enable(wl, wlvif, true); if (ret < 0) @@ -213,7 +213,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_debug(DEBUG_PSM, "leaving psm"); /* disable beacon early termination */ - if ((wlvif->band == IEEE80211_BAND_2GHZ) && + if ((wlvif->band == NL80211_BAND_2GHZ) && (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) { ret = wl1271_acx_bet_enable(wl, wlvif, false); if (ret < 0) diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 34e7e938ede4..c9bd294a0aa6 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c @@ -64,9 +64,9 @@ static void wl1271_rx_status(struct wl1271 *wl, memset(status, 0, sizeof(struct ieee80211_rx_status)); if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) - status->band = IEEE80211_BAND_2GHZ; + status->band = NL80211_BAND_2GHZ; else - status->band = IEEE80211_BAND_5GHZ; + status->band = NL80211_BAND_5GHZ; status->rate_idx = wlcore_rate_to_idx(wl, desc->rate, status->band); diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index f5a7087cfb97..57c0565637d6 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h @@ -146,7 +146,7 @@ struct wl1271_rx_descriptor { } __packed; int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status); -u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); +u8 wl1271_rate_to_idx(int rate, enum nl80211_band band); int wl1271_rx_filter_enable(struct wl1271 *wl, int index, bool enable, struct wl12xx_rx_filter *filter); diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index a384f3f83099..23343643207a 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -164,7 +164,7 @@ wlcore_scan_get_channels(struct wl1271 *wl, struct conf_sched_scan_settings *c = &wl->conf.sched_scan; u32 delta_per_probe; - if (band == IEEE80211_BAND_5GHZ) + if (band == NL80211_BAND_5GHZ) delta_per_probe = c->dwell_time_delta_per_probe_5; else delta_per_probe = c->dwell_time_delta_per_probe; @@ -215,7 +215,7 @@ wlcore_scan_get_channels(struct wl1271 *wl, channels[j].channel = req_channels[i]->hw_value; if (n_pactive_ch && - (band == IEEE80211_BAND_2GHZ) && + (band == NL80211_BAND_2GHZ) && (channels[j].channel >= 12) && (channels[j].channel <= 14) && (flags & IEEE80211_CHAN_NO_IR) && @@ -266,7 +266,7 @@ wlcore_set_scan_chan_params(struct wl1271 *wl, n_channels, n_ssids, cfg->channels_2, - IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ, false, true, 0, MAX_CHANNELS_2GHZ, &n_pactive_ch, @@ -277,7 +277,7 @@ wlcore_set_scan_chan_params(struct wl1271 *wl, n_channels, n_ssids, cfg->channels_2, - IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ, false, false, cfg->passive[0], MAX_CHANNELS_2GHZ, @@ -289,7 +289,7 @@ wlcore_set_scan_chan_params(struct wl1271 *wl, n_channels, n_ssids, cfg->channels_5, - IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ, false, true, 0, wl->max_channels_5, &n_pactive_ch, @@ -300,7 +300,7 @@ wlcore_set_scan_chan_params(struct wl1271 *wl, n_channels, n_ssids, cfg->channels_5, - IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ, true, true, cfg->passive[1], wl->max_channels_5, @@ -312,7 +312,7 @@ wlcore_set_scan_chan_params(struct wl1271 *wl, n_channels, n_ssids, cfg->channels_5, - IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ, false, false, cfg->passive[1] + cfg->dfs, wl->max_channels_5, diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index f0ac36139bcc..c1b8e4e9d70b 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -453,7 +453,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, } u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, - enum ieee80211_band rate_band) + enum nl80211_band rate_band) { struct ieee80211_supported_band *band; u32 enabled_rates = 0; diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index 79cb3ff8b71f..e2ba62d92d7a 100644 --- a/drivers/net/wireless/ti/wlcore/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h @@ -246,9 +246,9 @@ int wlcore_tx_complete(struct wl1271 *wl); void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); void wl12xx_tx_reset(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl); -u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band); +u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum nl80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, - enum ieee80211_band rate_band); + enum nl80211_band rate_band); u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb, struct ieee80211_sta *sta); diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 72c31a8edcfb..8f28aa02230c 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -342,7 +342,7 @@ struct wl1271 { struct wl12xx_vif *sched_vif; /* The current band */ - enum ieee80211_band band; + enum nl80211_band band; struct completion *elp_compl; struct delayed_work elp_work; @@ -517,7 +517,7 @@ void wlcore_update_inconn_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct wl1271_station *wl_sta, bool in_conn); static inline void -wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, +wlcore_set_ht_cap(struct wl1271 *wl, enum nl80211_band band, struct ieee80211_sta_ht_cap *ht_cap) { memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 27c56876b2c1..5c4199f3a19a 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -392,7 +392,7 @@ struct wl12xx_vif { u8 ssid_len; /* The current band */ - enum ieee80211_band band; + enum nl80211_band band; int channel; enum nl80211_channel_type channel_type; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index d5c371d77ddf..99de07d14939 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1454,7 +1454,7 @@ static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info, struct wl3501_card *this = netdev_priv(dev); wrqu->freq.m = 100000 * - ieee80211_channel_to_frequency(this->chan, IEEE80211_BAND_2GHZ); + ieee80211_channel_to_frequency(this->chan, NL80211_BAND_2GHZ); wrqu->freq.e = 1; return 0; } diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c index e539d9b1b562..3e37a045f702 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c @@ -1068,7 +1068,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) } stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; - stats.band = IEEE80211_BAND_2GHZ; + stats.band = NL80211_BAND_2GHZ; stats.signal = zd_check_signal(hw, status->signal_strength); rate = zd_rx_rate(buffer, status); @@ -1395,7 +1395,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) mac->band.n_channels = ARRAY_SIZE(zd_channels); mac->band.channels = mac->channels; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; + hw->wiphy->bands[NL80211_BAND_2GHZ] = &mac->band; ieee80211_hw_set(hw, MFP_CAPABLE); ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c index f4fff385aeb2..7dd1540ebedd 100644 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c @@ -2113,10 +2113,10 @@ static int on_action_public23a(struct rtw_adapter *padapter, if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe, skb->len, 0)) diff --git a/drivers/staging/rtl8723au/include/ieee80211.h b/drivers/staging/rtl8723au/include/ieee80211.h index 3aa40a32555e..634102e1bda6 100644 --- a/drivers/staging/rtl8723au/include/ieee80211.h +++ b/drivers/staging/rtl8723au/include/ieee80211.h @@ -266,7 +266,7 @@ struct ieee80211_snap_hdr { /* Represent channel details, subset of ieee80211_channel */ struct rtw_ieee80211_channel { - /* enum ieee80211_band band; */ + /* enum nl80211_band band; */ /* u16 center_freq; */ u16 hw_value; u32 flags; diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c index 12d18440e824..0da559d929bc 100644 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c @@ -39,7 +39,7 @@ static const u32 rtw_cipher_suites[] = { } #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -48,7 +48,7 @@ static const u32 rtw_cipher_suites[] = { } #define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + (5 * (_channel)), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -143,15 +143,15 @@ static void rtw_5g_rates_init(struct ieee80211_rate *rates) } static struct ieee80211_supported_band * -rtw_spt_band_alloc(enum ieee80211_band band) +rtw_spt_band_alloc(enum nl80211_band band) { struct ieee80211_supported_band *spt_band = NULL; int n_channels, n_bitrates; - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { n_channels = RTW_2G_CHANNELS_NUM; n_bitrates = RTW_G_RATES_NUM; - } else if (band == IEEE80211_BAND_5GHZ) { + } else if (band == NL80211_BAND_5GHZ) { n_channels = RTW_5G_CHANNELS_NUM; n_bitrates = RTW_A_RATES_NUM; } else { @@ -176,10 +176,10 @@ rtw_spt_band_alloc(enum ieee80211_band band) spt_band->n_channels = n_channels; spt_band->n_bitrates = n_bitrates; - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { rtw_2g_channels_init(spt_band->channels); rtw_2g_rates_init(spt_band->bitrates); - } else if (band == IEEE80211_BAND_5GHZ) { + } else if (band == NL80211_BAND_5GHZ) { rtw_5g_channels_init(spt_band->channels); rtw_5g_rates_init(spt_band->bitrates); } @@ -257,10 +257,10 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, channel = pnetwork->network.DSConfig; if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); notify_channel = ieee80211_get_channel(wiphy, freq); @@ -322,11 +322,11 @@ void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter) if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); notify_channel = ieee80211_get_channel(wiphy, freq); @@ -2360,10 +2360,10 @@ void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, channel = pmlmeext->cur_channel; if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len, 0); @@ -2392,10 +2392,10 @@ void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, channel = pmlmeext->cur_channel; if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); mgmt.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); @@ -3109,7 +3109,7 @@ static struct cfg80211_ops rtw_cfg80211_ops = { }; static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, - enum ieee80211_band band, u8 rf_type) + enum nl80211_band band, u8 rf_type) { #define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ @@ -3133,7 +3133,7 @@ static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; /* - *hw->wiphy->bands[IEEE80211_BAND_2GHZ] + *hw->wiphy->bands[NL80211_BAND_2GHZ] *base on ant_num *rx_mask: RX mask *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 @@ -3173,19 +3173,19 @@ void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter) /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ { - bands = wiphy->bands[IEEE80211_BAND_2GHZ]; + bands = wiphy->bands[NL80211_BAND_2GHZ]; if (bands) rtw_cfg80211_init_ht_capab(&bands->ht_cap, - IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ, rf_type); } /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ { - bands = wiphy->bands[IEEE80211_BAND_5GHZ]; + bands = wiphy->bands[NL80211_BAND_5GHZ]; if (bands) rtw_cfg80211_init_ht_capab(&bands->ht_cap, - IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ, rf_type); } } @@ -3224,11 +3224,11 @@ static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter, wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites); /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ - wiphy->bands[IEEE80211_BAND_2GHZ] = - rtw_spt_band_alloc(IEEE80211_BAND_2GHZ); + wiphy->bands[NL80211_BAND_2GHZ] = + rtw_spt_band_alloc(NL80211_BAND_2GHZ); /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ - wiphy->bands[IEEE80211_BAND_5GHZ] = - rtw_spt_band_alloc(IEEE80211_BAND_5GHZ); + wiphy->bands[NL80211_BAND_5GHZ] = + rtw_spt_band_alloc(NL80211_BAND_5GHZ); wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME; @@ -3313,8 +3313,8 @@ void rtw_wdev_free(struct wireless_dev *wdev) if (!wdev) return; - kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]); - kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]); + kfree(wdev->wiphy->bands[NL80211_BAND_2GHZ]); + kfree(wdev->wiphy->bands[NL80211_BAND_5GHZ]); wiphy_free(wdev->wiphy); diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 9ac1ef9d0d51..b7d43a5622ba 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -144,7 +144,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = &vnt_supported_5ghz_band; /* fallthrough */ case RF_RFMD2959: @@ -159,7 +159,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = &vnt_supported_2ghz_band; break; } diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index c3eea07ca97e..494164045a0f 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -812,7 +812,7 @@ static int vnt_int_report_rate(struct vnt_private *priv, else if (fb_option & FIFOCTL_AUTO_FB_1) tx_rate = fallback_rate1[tx_rate][retry]; - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) idx = tx_rate - RATE_6M; else idx = tx_rate; @@ -1290,7 +1290,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed) (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { set_channel(priv, conf->chandef.chan); - if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) + if (conf->chandef.chan->band == NL80211_BAND_5GHZ) bb_type = BB_TYPE_11A; else bb_type = BB_TYPE_11G; diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 1a2dda09b69d..e4c3165ae027 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1307,7 +1307,7 @@ int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx, } if (current_rate > RATE_11M) { - if (info->band == IEEE80211_BAND_5GHZ) { + if (info->band == NL80211_BAND_5GHZ) { pkt_type = PK_TYPE_11A; } else { if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index a0fe288c1322..a4299f405d7f 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -153,7 +153,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = &vnt_supported_5ghz_band; /* fallthrough */ case RF_AL2230: @@ -167,7 +167,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = &vnt_supported_2ghz_band; break; } diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 8d05acbc0e23..73538fb4e4e2 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -97,7 +97,7 @@ static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr) else if (context->fb_option == AUTO_FB_1) tx_rate = fallback_rate1[tx_rate][retry]; - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) idx = tx_rate - RATE_6M; else idx = tx_rate; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index f9afab77b79f..fc5fe4ec6d05 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -662,7 +662,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed) (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { vnt_set_channel(priv, conf->chandef.chan->hw_value); - if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) + if (conf->chandef.chan->band == NL80211_BAND_5GHZ) bb_type = BB_TYPE_11A; else bb_type = BB_TYPE_11G; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index b74e32001318..aa59e7f14ab3 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -813,7 +813,7 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) } if (current_rate > RATE_11M) { - if (info->band == IEEE80211_BAND_5GHZ) { + if (info->band == NL80211_BAND_5GHZ) { pkt_type = PK_TYPE_11A; } else { if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 448a5c8c4514..544917d8b2df 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -102,7 +102,7 @@ static u8 op_ifcs; u8 wilc_initialized = 1; #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -241,7 +241,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) struct ieee80211_channel *channel; if (network_info) { - freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); rssi = get_rssi_avg(network_info); @@ -409,7 +409,7 @@ static void CfgScanResult(enum scan_event scan_event, return; if (network_info) { - s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); + s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, s32Freq); if (!channel) @@ -1451,7 +1451,7 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size) return; } } else { - s32Freq = ieee80211_channel_to_frequency(curr_channel, IEEE80211_BAND_2GHZ); + s32Freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ); if (ieee80211_is_action(buff[FRAME_TYPE_ID])) { if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) { @@ -2246,7 +2246,7 @@ static struct wireless_dev *WILC_WFI_CfgAlloc(void) WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K; WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &WILC_WFI_band_2ghz; + wdev->wiphy->bands[NL80211_BAND_2GHZ] = &WILC_WFI_band_2ghz; return wdev; diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8bad018eda47..2438cf7cc695 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -415,7 +415,7 @@ static int prism2_scan(struct wiphy *wiphy, ie_len = ie_buf[1] + 2; memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); freq = ieee80211_channel_to_frequency(msg2.dschannel.data, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); bss = cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, freq), CFG80211_BSS_FTYPE_UNKNOWN, @@ -758,9 +758,9 @@ static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev priv->band.n_channels = ARRAY_SIZE(prism2_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); - priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.band = NL80211_BAND_2GHZ; priv->band.ht_cap.ht_supported = false; - wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; set_wiphy_dev(wiphy, dev); wiphy->privid = prism2_wiphy_privid; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5ec20369ceb8..183916e168f1 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -67,26 +67,6 @@ struct wiphy; * wireless hardware capability structures */ -/** - * enum ieee80211_band - supported frequency bands - * - * The bands are assigned this way because the supported - * bitrates differ in these bands. - * - * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band - * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) - * @IEEE80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) - * @IEEE80211_NUM_BANDS: number of defined bands - */ -enum ieee80211_band { - IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ, - IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ, - IEEE80211_BAND_60GHZ = NL80211_BAND_60GHZ, - - /* keep last */ - IEEE80211_NUM_BANDS -}; - /** * enum ieee80211_channel_flags - channel flags * @@ -167,7 +147,7 @@ enum ieee80211_channel_flags { * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels. */ struct ieee80211_channel { - enum ieee80211_band band; + enum nl80211_band band; u16 center_freq; u16 hw_value; u32 flags; @@ -324,7 +304,7 @@ struct ieee80211_sta_vht_cap { struct ieee80211_supported_band { struct ieee80211_channel *channels; struct ieee80211_rate *bitrates; - enum ieee80211_band band; + enum nl80211_band band; int n_channels; int n_bitrates; struct ieee80211_sta_ht_cap ht_cap; @@ -1370,7 +1350,7 @@ struct mesh_setup { bool user_mpm; u8 dtim_period; u16 beacon_interval; - int mcast_rate[IEEE80211_NUM_BANDS]; + int mcast_rate[NUM_NL80211_BANDS]; u32 basic_rates; }; @@ -1468,7 +1448,7 @@ struct cfg80211_scan_request { size_t ie_len; u32 flags; - u32 rates[IEEE80211_NUM_BANDS]; + u32 rates[NUM_NL80211_BANDS]; struct wireless_dev *wdev; @@ -1860,7 +1840,7 @@ struct cfg80211_ibss_params { bool privacy; bool control_port; bool userspace_handles_dfs; - int mcast_rate[IEEE80211_NUM_BANDS]; + int mcast_rate[NUM_NL80211_BANDS]; struct ieee80211_ht_cap ht_capa; struct ieee80211_ht_cap ht_capa_mask; }; @@ -1872,7 +1852,7 @@ struct cfg80211_ibss_params { * @delta: value of RSSI level adjustment. */ struct cfg80211_bss_select_adjust { - enum ieee80211_band band; + enum nl80211_band band; s8 delta; }; @@ -1887,7 +1867,7 @@ struct cfg80211_bss_select_adjust { struct cfg80211_bss_selection { enum nl80211_bss_select_attr behaviour; union { - enum ieee80211_band band_pref; + enum nl80211_band band_pref; struct cfg80211_bss_select_adjust adjust; } param; }; @@ -1990,7 +1970,7 @@ struct cfg80211_bitrate_mask { u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN]; u16 vht_mcs[NL80211_VHT_NSS_MAX]; enum nl80211_txrate_gi gi; - } control[IEEE80211_NUM_BANDS]; + } control[NUM_NL80211_BANDS]; }; /** * struct cfg80211_pmksa - PMK Security Association @@ -2677,7 +2657,7 @@ struct cfg80211_ops { int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev); int (*set_mcast_rate)(struct wiphy *wiphy, struct net_device *dev, - int rate[IEEE80211_NUM_BANDS]); + int rate[NUM_NL80211_BANDS]); int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed); @@ -3323,7 +3303,7 @@ struct wiphy { * help determine whether you own this wiphy or not. */ const void *privid; - struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band *bands[NUM_NL80211_BANDS]; /* Lets us get back the wiphy on the callback */ void (*reg_notifier)(struct wiphy *wiphy, @@ -3658,7 +3638,7 @@ static inline void *wdev_priv(struct wireless_dev *wdev) * @band: band, necessary due to channel number overlap * Return: The corresponding frequency (in MHz), or 0 if the conversion failed. */ -int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band); +int ieee80211_channel_to_frequency(int chan, enum nl80211_band band); /** * ieee80211_frequency_to_channel - convert frequency to channel number @@ -5089,7 +5069,7 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev, * Returns %true if the conversion was successful, %false otherwise. */ bool ieee80211_operating_class_to_band(u8 operating_class, - enum ieee80211_band *band); + enum nl80211_band *band); /** * ieee80211_chandef_to_operating_class - convert chandef to operation class diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ebc5a408acc2..07ef9378df2b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -549,7 +549,7 @@ struct ieee80211_bss_conf { u8 sync_dtim_count; u32 basic_rates; struct ieee80211_rate *beacon_rate; - int mcast_rate[IEEE80211_NUM_BANDS]; + int mcast_rate[NUM_NL80211_BANDS]; u16 ht_operation_mode; s32 cqm_rssi_thold; u32 cqm_rssi_hyst; @@ -938,8 +938,8 @@ struct ieee80211_tx_info { * @common_ie_len: length of the common_ies */ struct ieee80211_scan_ies { - const u8 *ies[IEEE80211_NUM_BANDS]; - size_t len[IEEE80211_NUM_BANDS]; + const u8 *ies[NUM_NL80211_BANDS]; + size_t len[NUM_NL80211_BANDS]; const u8 *common_ies; size_t common_ie_len; }; @@ -1754,7 +1754,7 @@ struct ieee80211_sta_rates { * @txq: per-TID data TX queues (if driver uses the TXQ abstraction) */ struct ieee80211_sta { - u32 supp_rates[IEEE80211_NUM_BANDS]; + u32 supp_rates[NUM_NL80211_BANDS]; u8 addr[ETH_ALEN]; u16 aid; struct ieee80211_sta_ht_cap ht_cap; @@ -4404,7 +4404,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, */ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_band band, + enum nl80211_band band, size_t frame_len, struct ieee80211_rate *rate); @@ -5357,7 +5357,7 @@ struct rate_control_ops { }; static inline int rate_supported(struct ieee80211_sta *sta, - enum ieee80211_band band, + enum nl80211_band band, int index) { return (sta == NULL || sta->supp_rates[band] & BIT(index)); diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b4606288ef7a..1df655d8aa52 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3653,11 +3653,15 @@ enum nl80211_txrate_gi { * @NL80211_BAND_2GHZ: 2.4 GHz ISM band * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands */ enum nl80211_band { NL80211_BAND_2GHZ, NL80211_BAND_5GHZ, NL80211_BAND_60GHZ, + + NUM_NL80211_BANDS, }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index fc4730b938d0..0c12e4001f19 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1049,7 +1049,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, int ret = 0; struct ieee80211_supported_band *sband; struct ieee80211_sub_if_data *sdata = sta->sdata; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); u32 mask, set; sband = local->hw.wiphy->bands[band]; @@ -1848,7 +1848,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, struct bss_parameters *params) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - enum ieee80211_band band; + enum nl80211_band band; u32 changed = 0; if (!sdata_dereference(sdata->u.ap.beacon, sdata)) @@ -1867,7 +1867,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, } if (!sdata->vif.bss_conf.use_short_slot && - band == IEEE80211_BAND_5GHZ) { + band == NL80211_BAND_5GHZ) { sdata->vif.bss_conf.use_short_slot = true; changed |= BSS_CHANGED_ERP_SLOT; } @@ -2097,12 +2097,12 @@ static int ieee80211_leave_ocb(struct wiphy *wiphy, struct net_device *dev) } static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, - int rate[IEEE80211_NUM_BANDS]) + int rate[NUM_NL80211_BANDS]) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); memcpy(sdata->vif.bss_conf.mcast_rate, rate, - sizeof(int) * IEEE80211_NUM_BANDS); + sizeof(int) * NUM_NL80211_BANDS); return 0; } @@ -2507,7 +2507,7 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, return ret; } - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0; i < NUM_NL80211_BANDS; i++) { struct ieee80211_supported_band *sband = wiphy->bands[i]; int j; @@ -3135,7 +3135,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_tx_info *info; struct sta_info *sta; struct ieee80211_chanctx_conf *chanctx_conf; - enum ieee80211_band band; + enum nl80211_band band; int ret; /* the lock is needed to assign the cookie later */ diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 37ea30e0754c..a5ba739cd2a7 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -169,21 +169,21 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \ IEEE80211_IF_FILE_R(name) /* common attributes */ -IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], +IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[NL80211_BAND_2GHZ], HEX); -IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], +IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[NL80211_BAND_5GHZ], HEX); IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz, - rc_rateidx_mcs_mask[IEEE80211_BAND_2GHZ], HEXARRAY); + rc_rateidx_mcs_mask[NL80211_BAND_2GHZ], HEXARRAY); IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, - rc_rateidx_mcs_mask[IEEE80211_BAND_5GHZ], HEXARRAY); + rc_rateidx_mcs_mask[NL80211_BAND_5GHZ], HEXARRAY); static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_2ghz( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) { int i, len = 0; - const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[IEEE80211_BAND_2GHZ]; + const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_2GHZ]; for (i = 0; i < NL80211_VHT_NSS_MAX; i++) len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]); @@ -199,7 +199,7 @@ static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_5ghz( char *buf, int buflen) { int i, len = 0; - const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[IEEE80211_BAND_5GHZ]; + const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_5GHZ]; for (i = 0; i < NL80211_VHT_NSS_MAX; i++) len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]); diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c6d4b75eb60b..a31d30713d08 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -126,7 +126,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, } } - if (sband->band == IEEE80211_BAND_2GHZ) { + if (sband->band == NL80211_BAND_2GHZ) { *pos++ = WLAN_EID_DS_PARAMS; *pos++ = 1; *pos++ = ieee80211_frequency_to_channel( @@ -348,11 +348,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, * * HT follows these specifications (IEEE 802.11-2012 20.3.18) */ - sdata->vif.bss_conf.use_short_slot = chan->band == IEEE80211_BAND_5GHZ; + sdata->vif.bss_conf.use_short_slot = chan->band == NL80211_BAND_5GHZ; bss_change |= BSS_CHANGED_ERP_SLOT; /* cf. IEEE 802.11 9.2.12 */ - if (chan->band == IEEE80211_BAND_2GHZ && have_higher_than_11mbit) + if (chan->band == NL80211_BAND_2GHZ && have_higher_than_11mbit) sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; else sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; @@ -989,7 +989,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel) { struct sta_info *sta; - enum ieee80211_band band = rx_status->band; + enum nl80211_band band = rx_status->band; enum nl80211_bss_scan_width scan_width; struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; @@ -1109,7 +1109,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel; u64 beacon_timestamp, rx_timestamp; u32 supp_rates = 0; - enum ieee80211_band band = rx_status->band; + enum nl80211_band band = rx_status->band; channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); if (!channel) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8857b01b82d0..9438c9406687 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -896,13 +896,13 @@ struct ieee80211_sub_if_data { struct ieee80211_if_ap *bss; /* bitmap of allowed (non-MCS) rate indexes for rate control */ - u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; + u32 rc_rateidx_mask[NUM_NL80211_BANDS]; - bool rc_has_mcs_mask[IEEE80211_NUM_BANDS]; - u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN]; + bool rc_has_mcs_mask[NUM_NL80211_BANDS]; + u8 rc_rateidx_mcs_mask[NUM_NL80211_BANDS][IEEE80211_HT_MCS_MASK_LEN]; - bool rc_has_vht_mcs_mask[IEEE80211_NUM_BANDS]; - u16 rc_rateidx_vht_mcs_mask[IEEE80211_NUM_BANDS][NL80211_VHT_NSS_MAX]; + bool rc_has_vht_mcs_mask[NUM_NL80211_BANDS]; + u16 rc_rateidx_vht_mcs_mask[NUM_NL80211_BANDS][NL80211_VHT_NSS_MAX]; union { struct ieee80211_if_ap ap; @@ -957,10 +957,10 @@ sdata_assert_lock(struct ieee80211_sub_if_data *sdata) lockdep_assert_held(&sdata->wdev.mtx); } -static inline enum ieee80211_band +static inline enum nl80211_band ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) { - enum ieee80211_band band = IEEE80211_BAND_2GHZ; + enum nl80211_band band = NL80211_BAND_2GHZ; struct ieee80211_chanctx_conf *chanctx_conf; rcu_read_lock(); @@ -1231,7 +1231,7 @@ struct ieee80211_local { struct cfg80211_scan_request __rcu *scan_req; struct ieee80211_scan_request *hw_scan_req; struct cfg80211_chan_def scan_chandef; - enum ieee80211_band hw_scan_band; + enum nl80211_band hw_scan_band; int scan_channel_idx; int scan_ies_len; int hw_scan_ies_bufsize; @@ -1738,10 +1738,10 @@ void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt); u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, u8 opmode, - enum ieee80211_band band); + enum nl80211_band band); void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, u8 opmode, - enum ieee80211_band band); + enum nl80211_band band); void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_vht_cap *vht_cap); void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, @@ -1769,7 +1769,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, */ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems *elems, - enum ieee80211_band current_band, + enum nl80211_band current_band, u32 sta_flags, u8 *bssid, struct ieee80211_csa_ie *csa_ie); @@ -1794,7 +1794,7 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) /* utility functions/constants */ extern const void *const mac80211_wiphy_privid; /* for wiphy privid */ -int ieee80211_frame_duration(enum ieee80211_band band, size_t len, +int ieee80211_frame_duration(enum nl80211_band band, size_t len, int rate, int erp, int short_preamble, int shift); void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, @@ -1804,12 +1804,12 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int tid, - enum ieee80211_band band); + enum nl80211_band band); static inline void ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int tid, - enum ieee80211_band band) + enum nl80211_band band) { rcu_read_lock(); __ieee80211_tx_skb_tid_band(sdata, skb, tid, band); @@ -1964,7 +1964,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems *elems, - enum ieee80211_band band, u32 *basic_rates); + enum nl80211_band band, u32 *basic_rates); int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps_mode); int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, @@ -1987,10 +1987,10 @@ int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, const u8 *srates, int srates_len, u32 *rates); int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, bool need_basic, - enum ieee80211_band band); + enum nl80211_band band); int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, bool need_basic, - enum ieee80211_band band); + enum nl80211_band band); u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo); /* channel management */ diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 097ece8b5c02..6a33f0b4d839 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1800,7 +1800,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, ieee80211_delayed_tailroom_dec); - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0; i < NUM_NL80211_BANDS; i++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[i]; sdata->rc_rateidx_mask[i] = diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 33c80de61eca..7ee91d6151d1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -801,7 +801,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); int result, i; - enum ieee80211_band band; + enum nl80211_band band; int channels, max_bitrates; bool supp_ht, supp_vht; netdev_features_t feature_whitelist; @@ -874,7 +874,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) max_bitrates = 0; supp_ht = false; supp_vht = false; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[band]; @@ -936,7 +936,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (!local->int_scan_req) return -ENOMEM; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!local->hw.wiphy->bands[band]) continue; local->int_scan_req->rates[band] = (u32) -1; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index dcc1facc807c..4c6404e1ad6e 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -415,7 +415,7 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_local *local = sdata->local; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); struct ieee80211_supported_band *sband; u8 *pos; @@ -478,7 +478,7 @@ int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_local *local = sdata->local; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); struct ieee80211_supported_band *sband; u8 *pos; @@ -680,7 +680,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) struct ieee80211_mgmt *mgmt; struct ieee80211_chanctx_conf *chanctx_conf; struct mesh_csa_settings *csa; - enum ieee80211_band band; + enum nl80211_band band; u8 *pos; struct ieee80211_sub_if_data *sdata; int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) + @@ -930,7 +930,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, struct cfg80211_csa_settings params; struct ieee80211_csa_ie csa_ie; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); int err; u32 sta_flags; @@ -1084,7 +1084,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel; size_t baselen; int freq; - enum ieee80211_band band = rx_status->band; + enum nl80211_band band = rx_status->band; /* ignore ProbeResp to foreign address */ if (stype == IEEE80211_STYPE_PROBE_RESP && diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 563bea050383..79f2a0a13db8 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -93,18 +93,18 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; struct sta_info *sta; u32 erp_rates = 0, changed = 0; int i; bool short_slot = false; - if (band == IEEE80211_BAND_5GHZ) { + if (band == NL80211_BAND_5GHZ) { /* (IEEE 802.11-2012 19.4.5) */ short_slot = true; goto out; - } else if (band != IEEE80211_BAND_2GHZ) + } else if (band != NL80211_BAND_2GHZ) goto out; for (i = 0; i < sband->n_bitrates; i++) @@ -247,7 +247,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, mgmt->u.action.u.self_prot.action_code = action; if (action != WLAN_SP_MESH_PEERING_CLOSE) { - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); /* capability info */ pos = skb_put(skb, 2); @@ -385,7 +385,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems *elems, bool insert) { struct ieee80211_local *local = sdata->local; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); struct ieee80211_supported_band *sband; u32 rates, basic_rates = 0, changed = 0; enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d3c75ac8a029..885f4ca0888d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -661,7 +661,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) capab = WLAN_CAPABILITY_ESS; - if (sband->band == IEEE80211_BAND_2GHZ) { + if (sband->band == NL80211_BAND_2GHZ) { capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; } @@ -1100,7 +1100,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, struct cfg80211_bss *cbss = ifmgd->associated; struct ieee80211_chanctx_conf *conf; struct ieee80211_chanctx *chanctx; - enum ieee80211_band current_band; + enum nl80211_band current_band; struct ieee80211_csa_ie csa_ie; struct ieee80211_channel_switch ch_switch; int res; @@ -1257,11 +1257,11 @@ ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata, default: WARN_ON_ONCE(1); /* fall through */ - case IEEE80211_BAND_2GHZ: - case IEEE80211_BAND_60GHZ: + case NL80211_BAND_2GHZ: + case NL80211_BAND_60GHZ: chan_increment = 1; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: chan_increment = 4; break; } @@ -1861,7 +1861,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, } use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); - if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_5GHZ) + if (ieee80211_get_sdata_band(sdata) == NL80211_BAND_5GHZ) use_short_slot = true; if (use_protection != bss_conf->use_cts_prot) { @@ -4375,7 +4375,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.basic_rates = basic_rates; /* cf. IEEE 802.11 9.2.12 */ - if (cbss->channel->band == IEEE80211_BAND_2GHZ && + if (cbss->channel->band == NL80211_BAND_2GHZ && have_higher_than_11mbit) sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; else diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index a4e2f4e67f94..206698bc93f4 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -287,7 +287,7 @@ static void __rate_control_send_low(struct ieee80211_hw *hw, u32 rate_flags = ieee80211_chandef_rate_flags(&hw->conf.chandef); - if ((sband->band == IEEE80211_BAND_2GHZ) && + if ((sband->band == NL80211_BAND_2GHZ) && (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) rate_flags |= IEEE80211_RATE_ERP_G; diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index b54f398cda5d..14c5ba3a1b1c 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -436,7 +436,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, static void -calc_rate_durations(enum ieee80211_band band, +calc_rate_durations(enum nl80211_band band, struct minstrel_rate *d, struct ieee80211_rate *rate, struct cfg80211_chan_def *chandef) @@ -579,7 +579,7 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) if (!mi) return NULL; - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0; i < NUM_NL80211_BANDS; i++) { sband = hw->wiphy->bands[i]; if (sband && sband->n_bitrates > max_rates) max_rates = sband->n_bitrates; @@ -621,7 +621,7 @@ minstrel_init_cck_rates(struct minstrel_priv *mp) u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); int i, j; - sband = mp->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; if (!sband) return; diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index d77a9a842338..30fbabf4bcbc 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -1137,7 +1137,7 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, { int i; - if (sband->band != IEEE80211_BAND_2GHZ) + if (sband->band != NL80211_BAND_2GHZ) return; if (!ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES)) @@ -1335,7 +1335,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) int max_rates = 0; int i; - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0; i < NUM_NL80211_BANDS; i++) { sband = hw->wiphy->bands[i]; if (sband && sband->n_bitrates > max_rates) max_rates = sband->n_bitrates; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c2b659e9a9f9..c5678703921e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -322,7 +322,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, else if (status->flag & RX_FLAG_5MHZ) channel_flags |= IEEE80211_CHAN_QUARTER; - if (status->band == IEEE80211_BAND_5GHZ) + if (status->band == NL80211_BAND_5GHZ) channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ; else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) channel_flags |= IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; @@ -2823,7 +2823,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) switch (mgmt->u.action.u.measurement.action_code) { case WLAN_ACTION_SPCT_MSR_REQ: - if (status->band != IEEE80211_BAND_5GHZ) + if (status->band != NL80211_BAND_5GHZ) break; if (len < (IEEE80211_MIN_ACTION_SIZE + @@ -4043,7 +4043,7 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, WARN_ON_ONCE(softirq_count() == 0); - if (WARN_ON(status->band >= IEEE80211_NUM_BANDS)) + if (WARN_ON(status->band >= NUM_NL80211_BANDS)) goto drop; sband = local->hw.wiphy->bands[status->band]; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 41aa728e5468..f9648ef9e31f 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -272,7 +272,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) n_chans = req->n_channels; } else { do { - if (local->hw_scan_band == IEEE80211_NUM_BANDS) + if (local->hw_scan_band == NUM_NL80211_BANDS) return false; n_chans = 0; @@ -485,7 +485,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, int i; struct ieee80211_sub_if_data *sdata; struct cfg80211_scan_request *scan_req; - enum ieee80211_band band = local->hw.conf.chandef.chan->band; + enum nl80211_band band = local->hw.conf.chandef.chan->band; u32 tx_flags; scan_req = rcu_dereference_protected(local->scan_req, @@ -953,7 +953,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; int ret = -EBUSY, i, n_ch = 0; - enum ieee80211_band band; + enum nl80211_band band; mutex_lock(&local->mtx); @@ -965,7 +965,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, if (!channels) { int max_n; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!local->hw.wiphy->bands[band]) continue; @@ -1085,7 +1085,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, struct ieee80211_scan_ies sched_scan_ies = {}; struct cfg80211_chan_def chandef; int ret, i, iebufsz, num_bands = 0; - u32 rate_masks[IEEE80211_NUM_BANDS] = {}; + u32 rate_masks[NUM_NL80211_BANDS] = {}; u8 bands_used = 0; u8 *ie; size_t len; @@ -1097,7 +1097,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, if (!local->ops->sched_scan_start) return -ENOTSUPP; - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0; i < NUM_NL80211_BANDS; i++) { if (local->hw.wiphy->bands[i]) { bands_used |= BIT(i); rate_masks[i] = (u32) -1; diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 06e6ac8cc693..2ddc661f0988 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -23,11 +23,11 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems *elems, - enum ieee80211_band current_band, + enum nl80211_band current_band, u32 sta_flags, u8 *bssid, struct ieee80211_csa_ie *csa_ie) { - enum ieee80211_band new_band; + enum nl80211_band new_band; int new_freq; u8 new_chan_no; struct ieee80211_channel *new_chan; diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index a29ea813b7d5..1c7d45a6d93e 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -47,7 +47,7 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata, NL80211_FEATURE_TDLS_CHANNEL_SWITCH; bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) && !ifmgd->tdls_wider_bw_prohibited; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; bool vht = sband && sband->vht_cap.vht_supported; u8 *pos = (void *)skb_put(skb, 10); @@ -184,7 +184,7 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata, if (status_code != 0) return 0; - if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_2GHZ) { + if (ieee80211_get_sdata_band(sdata) == NL80211_BAND_2GHZ) { return WLAN_CAPABILITY_SHORT_SLOT_TIME | WLAN_CAPABILITY_SHORT_PREAMBLE; } @@ -357,7 +357,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, u8 action_code, bool initiator, const u8 *extra_ies, size_t extra_ies_len) { - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct ieee80211_sta_ht_cap ht_cap; @@ -544,7 +544,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; size_t offset = 0, noffset; struct sta_info *sta, *ap_sta; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + enum nl80211_band band = ieee80211_get_sdata_band(sdata); u8 *pos; mutex_lock(&local->sta_mtx); @@ -611,7 +611,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); /* only include VHT-operation if not on the 2.4GHz band */ - if (band != IEEE80211_BAND_2GHZ && sta->sta.vht_cap.vht_supported) { + if (band != NL80211_BAND_2GHZ && sta->sta.vht_cap.vht_supported) { /* * if both peers support WIDER_BW, we can expand the chandef to * a wider compatible one, up to 80MHz @@ -1773,7 +1773,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, u8 target_channel, oper_class; bool local_initiator; struct sta_info *sta; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_tdls_data *tf = (void *)skb->data; struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); int baselen = offsetof(typeof(*tf), u.chan_switch_req.variable); @@ -1805,10 +1805,10 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, if ((oper_class == 112 || oper_class == 2 || oper_class == 3 || oper_class == 4 || oper_class == 5 || oper_class == 6) && target_channel < 14) - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; else - band = target_channel < 14 ? IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ; + band = target_channel < 14 ? NL80211_BAND_2GHZ : + NL80211_BAND_5GHZ; freq = ieee80211_channel_to_frequency(target_channel, band); if (freq == 0) { diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 8c3b7ae103bc..77e4c53baefb 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -401,7 +401,7 @@ TRACE_EVENT(drv_bss_info_changed, __field(u32, sync_device_ts) __field(u8, sync_dtim_count) __field(u32, basic_rates) - __array(int, mcast_rate, IEEE80211_NUM_BANDS) + __array(int, mcast_rate, NUM_NL80211_BANDS) __field(u16, ht_operation_mode) __field(s32, cqm_rssi_thold); __field(s32, cqm_rssi_hyst); @@ -1265,8 +1265,8 @@ TRACE_EVENT(drv_set_bitrate_mask, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - __entry->legacy_2g = mask->control[IEEE80211_BAND_2GHZ].legacy; - __entry->legacy_5g = mask->control[IEEE80211_BAND_5GHZ].legacy; + __entry->legacy_2g = mask->control[NL80211_BAND_2GHZ].legacy; + __entry->legacy_5g = mask->control[NL80211_BAND_5GHZ].legacy; ), TP_printk( diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e04d850726c5..203044379ce0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -150,7 +150,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, rate = DIV_ROUND_UP(r->bitrate, 1 << shift); switch (sband->band) { - case IEEE80211_BAND_2GHZ: { + case NL80211_BAND_2GHZ: { u32 flag; if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) flag = IEEE80211_RATE_MANDATORY_G; @@ -160,13 +160,13 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, mrate = r->bitrate; break; } - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: if (r->flags & IEEE80211_RATE_MANDATORY_A) mrate = r->bitrate; break; - case IEEE80211_BAND_60GHZ: + case NL80211_BAND_60GHZ: /* TODO, for now fall through */ - case IEEE80211_NUM_BANDS: + case NUM_NL80211_BANDS: WARN_ON(1); break; } @@ -2138,7 +2138,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, u16 info_id = 0; struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_sub_if_data *ap_sdata; - enum ieee80211_band band; + enum nl80211_band band; int ret; if (IS_ERR(sta)) @@ -3597,7 +3597,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, struct sk_buff *skb = NULL; struct ieee80211_tx_info *info; struct ieee80211_sub_if_data *sdata = NULL; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_tx_rate_control txrc; struct ieee80211_chanctx_conf *chanctx_conf; int csa_off_base = 0; @@ -4165,7 +4165,7 @@ EXPORT_SYMBOL(ieee80211_unreserve_tid); void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int tid, - enum ieee80211_band band) + enum nl80211_band band) { int ac = ieee802_1d_to_ac[tid & 7]; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0319d6d4f863..905003f75c4d 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -59,7 +59,7 @@ void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) } } -int ieee80211_frame_duration(enum ieee80211_band band, size_t len, +int ieee80211_frame_duration(enum nl80211_band band, size_t len, int rate, int erp, int short_preamble, int shift) { @@ -77,7 +77,7 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len, * is assumed to be 0 otherwise. */ - if (band == IEEE80211_BAND_5GHZ || erp) { + if (band == NL80211_BAND_5GHZ || erp) { /* * OFDM: * @@ -129,7 +129,7 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len, /* Exported duration function for driver use */ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_band band, + enum nl80211_band band, size_t frame_len, struct ieee80211_rate *rate) { @@ -1129,7 +1129,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); use_11b = (chanctx_conf && - chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ) && + chanctx_conf->def.chan->band == NL80211_BAND_2GHZ) && !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); rcu_read_unlock(); @@ -1301,7 +1301,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, u8 *buffer, size_t buffer_len, const u8 *ie, size_t ie_len, - enum ieee80211_band band, + enum nl80211_band band, u32 rate_mask, struct cfg80211_chan_def *chandef, size_t *offset) @@ -1375,7 +1375,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, pos += ext_rates_len; } - if (chandef->chan && sband->band == IEEE80211_BAND_2GHZ) { + if (chandef->chan && sband->band == NL80211_BAND_2GHZ) { if (end - pos < 3) goto out_err; *pos++ = WLAN_EID_DS_PARAMS; @@ -1479,7 +1479,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, memset(ie_desc, 0, sizeof(*ie_desc)); - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0; i < NUM_NL80211_BANDS; i++) { if (bands_used & BIT(i)) { pos += ieee80211_build_preq_ies_band(local, buffer + pos, @@ -1522,7 +1522,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb; struct ieee80211_mgmt *mgmt; int ies_len; - u32 rate_masks[IEEE80211_NUM_BANDS] = {}; + u32 rate_masks[NUM_NL80211_BANDS] = {}; struct ieee80211_scan_ies dummy_ie_desc; /* @@ -1582,7 +1582,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems *elems, - enum ieee80211_band band, u32 *basic_rates) + enum nl80211_band band, u32 *basic_rates) { struct ieee80211_supported_band *sband; size_t num_rates; @@ -2520,7 +2520,7 @@ int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, bool need_basic, - enum ieee80211_band band) + enum nl80211_band band) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; @@ -2565,7 +2565,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, bool need_basic, - enum ieee80211_band band) + enum nl80211_band band) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; @@ -2711,7 +2711,7 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, if (status->flag & RX_FLAG_MACTIME_PLCP_START) { /* TODO: handle HT/VHT preambles */ - if (status->band == IEEE80211_BAND_5GHZ) { + if (status->band == NL80211_BAND_5GHZ) { ts += 20 << shift; mpdu_offset += 2; } else if (status->flag & RX_FLAG_SHORTPRE) { diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index e590e2ef9eaf..ee715764a828 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -418,7 +418,7 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, u8 opmode, - enum ieee80211_band band) + enum nl80211_band band) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; @@ -504,7 +504,7 @@ EXPORT_SYMBOL_GPL(ieee80211_update_mu_groups); void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, u8 opmode, - enum ieee80211_band band) + enum nl80211_band band) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 59cabc9bce69..a6631fb319c1 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -768,7 +768,7 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy, if (chan == other_chan) return true; - if (chan->band != IEEE80211_BAND_5GHZ) + if (chan->band != NL80211_BAND_5GHZ) continue; r1 = cfg80211_get_unii(chan->center_freq); diff --git a/net/wireless/core.c b/net/wireless/core.c index 5327e4b974fa..7f7b9409bf4c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -557,7 +557,7 @@ int wiphy_register(struct wiphy *wiphy) { struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); int res; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; bool have_band = false; int i; @@ -647,7 +647,7 @@ int wiphy_register(struct wiphy *wiphy) return res; /* sanity check supported bands/channels */ - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { sband = wiphy->bands[band]; if (!sband) continue; @@ -659,7 +659,7 @@ int wiphy_register(struct wiphy *wiphy) * on 60GHz band, there are no legacy rates, so * n_bitrates is 0 */ - if (WARN_ON(band != IEEE80211_BAND_60GHZ && + if (WARN_ON(band != NL80211_BAND_60GHZ && !sband->n_bitrates)) return -EINVAL; @@ -669,7 +669,7 @@ int wiphy_register(struct wiphy *wiphy) * global structure for that. */ if (cfg80211_disable_40mhz_24ghz && - band == IEEE80211_BAND_2GHZ && + band == NL80211_BAND_2GHZ && sband->ht_cap.ht_supported) { sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 454157717efa..5d453916a417 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c @@ -69,7 +69,7 @@ static ssize_t ht40allow_map_read(struct file *file, struct wiphy *wiphy = file->private_data; char *buf; unsigned int offset = 0, buf_size = PAGE_SIZE, i, r; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; buf = kzalloc(buf_size, GFP_KERNEL); @@ -78,7 +78,7 @@ static ssize_t ht40allow_map_read(struct file *file, rtnl_lock(); - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { sband = wiphy->bands[band]; if (!sband) continue; diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 4c55fab9b4e4..4a4dda53bdf1 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -104,7 +104,7 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, struct ieee80211_supported_band *sband = rdev->wiphy.bands[params->chandef.chan->band]; int j; - u32 flag = params->chandef.chan->band == IEEE80211_BAND_5GHZ ? + u32 flag = params->chandef.chan->band == NL80211_BAND_5GHZ ? IEEE80211_RATE_MANDATORY_A : IEEE80211_RATE_MANDATORY_B; @@ -236,7 +236,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev) { struct cfg80211_cached_keys *ck = NULL; - enum ieee80211_band band; + enum nl80211_band band; int i, err; ASSERT_WDEV_LOCK(wdev); @@ -248,7 +248,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, if (!wdev->wext.ibss.chandef.chan) { struct ieee80211_channel *new_chan = NULL; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 092300b30c37..fa2066b56f36 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -128,9 +128,9 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, if (!setup->chandef.chan) { /* if we don't have that either, use the first usable channel */ - enum ieee80211_band band; + enum nl80211_band band; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; int i; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index ff328250bc44..c284d883c349 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -726,7 +726,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) wiphy = &rdev->wiphy; rtnl_lock(); - for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) { + for (bandid = 0; bandid < NUM_NL80211_BANDS; bandid++) { sband = wiphy->bands[bandid]; if (!sband) continue; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4f45a2913104..13ef553b99d4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1277,7 +1277,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, struct nlattr *nl_bands, *nl_band; struct nlattr *nl_freqs, *nl_freq; struct nlattr *nl_cmds; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_channel *chan; int i; const struct ieee80211_txrx_stypes *mgmt_stypes = @@ -1410,7 +1410,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, goto nla_put_failure; for (band = state->band_start; - band < IEEE80211_NUM_BANDS; band++) { + band < NUM_NL80211_BANDS; band++) { struct ieee80211_supported_band *sband; sband = rdev->wiphy.bands[band]; @@ -1472,7 +1472,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, } nla_nest_end(msg, nl_bands); - if (band < IEEE80211_NUM_BANDS) + if (band < NUM_NL80211_BANDS) state->band_start = band + 1; else state->band_start = 0; @@ -3493,7 +3493,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) } params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]); - if (params.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ]) + if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) return -EOPNOTSUPP; wdev_lock(wdev); @@ -5821,9 +5821,9 @@ static int validate_scan_freqs(struct nlattr *freqs) return n_channels; } -static bool is_band_valid(struct wiphy *wiphy, enum ieee80211_band b) +static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b) { - return b < IEEE80211_NUM_BANDS && wiphy->bands[b]; + return b < NUM_NL80211_BANDS && wiphy->bands[b]; } static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy, @@ -6018,10 +6018,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) i++; } } else { - enum ieee80211_band band; + enum nl80211_band band; /* all channels */ - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { int j; if (!wiphy->bands[band]) continue; @@ -6066,7 +6066,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->ie_len); } - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < NUM_NL80211_BANDS; i++) if (wiphy->bands[i]) request->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; @@ -6075,9 +6075,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SUPP_RATES], tmp) { - enum ieee80211_band band = nla_type(attr); + enum nl80211_band band = nla_type(attr); - if (band < 0 || band >= IEEE80211_NUM_BANDS) { + if (band < 0 || band >= NUM_NL80211_BANDS) { err = -EINVAL; goto out_free; } @@ -6265,7 +6265,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_sched_scan_request *request; struct nlattr *attr; int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0; - enum ieee80211_band band; + enum nl80211_band band; size_t ie_len; struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF; @@ -6430,7 +6430,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, } } else { /* all channels */ - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { int j; if (!wiphy->bands[band]) continue; @@ -7538,14 +7538,14 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) static bool nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev, - int mcast_rate[IEEE80211_NUM_BANDS], + int mcast_rate[NUM_NL80211_BANDS], int rateval) { struct wiphy *wiphy = &rdev->wiphy; bool found = false; int band, i; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { struct ieee80211_supported_band *sband; sband = wiphy->bands[band]; @@ -7725,7 +7725,7 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; - int mcast_rate[IEEE80211_NUM_BANDS]; + int mcast_rate[NUM_NL80211_BANDS]; u32 nla_rate; int err; @@ -8130,7 +8130,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) } connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]); - if (connect.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ]) { + if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) { kzfree(connkeys); return -EOPNOTSUPP; } @@ -8550,7 +8550,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, memset(&mask, 0, sizeof(mask)); /* Default to all rates enabled */ - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + for (i = 0; i < NUM_NL80211_BANDS; i++) { sband = rdev->wiphy.bands[i]; if (!sband) @@ -8574,14 +8574,14 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, /* * The nested attribute uses enum nl80211_band as the index. This maps - * directly to the enum ieee80211_band values used in cfg80211. + * directly to the enum nl80211_band values used in cfg80211. */ BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) { - enum ieee80211_band band = nla_type(tx_rates); + enum nl80211_band band = nla_type(tx_rates); int err; - if (band < 0 || band >= IEEE80211_NUM_BANDS) + if (band < 0 || band >= NUM_NL80211_BANDS) return -EINVAL; sband = rdev->wiphy.bands[band]; if (sband == NULL) @@ -10746,7 +10746,7 @@ static int nl80211_tdls_channel_switch(struct sk_buff *skb, * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the * specification is not defined for them. */ - if (chandef.chan->band == IEEE80211_BAND_2GHZ && + if (chandef.chan->band == NL80211_BAND_2GHZ && chandef.width != NL80211_CHAN_WIDTH_20_NOHT && chandef.width != NL80211_CHAN_WIDTH_20) return -EINVAL; diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 8ae0c04f9fc7..85ff30bee2b9 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -1048,7 +1048,7 @@ rdev_start_radar_detection(struct cfg80211_registered_device *rdev, static inline int rdev_set_mcast_rate(struct cfg80211_registered_device *rdev, struct net_device *dev, - int mcast_rate[IEEE80211_NUM_BANDS]) + int mcast_rate[NUM_NL80211_BANDS]) { int ret = -ENOTSUPP; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c5fb317eee68..e271dea6bc02 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1546,12 +1546,12 @@ static void reg_process_ht_flags_band(struct wiphy *wiphy, static void reg_process_ht_flags(struct wiphy *wiphy) { - enum ieee80211_band band; + enum nl80211_band band; if (!wiphy) return; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) + for (band = 0; band < NUM_NL80211_BANDS; band++) reg_process_ht_flags_band(wiphy, wiphy->bands[band]); } @@ -1673,7 +1673,7 @@ static void reg_check_channels(void) static void wiphy_update_regulatory(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { - enum ieee80211_band band; + enum nl80211_band band; struct regulatory_request *lr = get_last_request(); if (ignore_reg_update(wiphy, initiator)) { @@ -1690,7 +1690,7 @@ static void wiphy_update_regulatory(struct wiphy *wiphy, lr->dfs_region = get_cfg80211_regdom()->dfs_region; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) + for (band = 0; band < NUM_NL80211_BANDS; band++) handle_band(wiphy, initiator, wiphy->bands[band]); reg_process_beacons(wiphy); @@ -1786,14 +1786,14 @@ static void handle_band_custom(struct wiphy *wiphy, void wiphy_apply_custom_regulatory(struct wiphy *wiphy, const struct ieee80211_regdomain *regd) { - enum ieee80211_band band; + enum nl80211_band band; unsigned int bands_set = 0; WARN(!(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG), "wiphy should have REGULATORY_CUSTOM_REG\n"); wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!wiphy->bands[band]) continue; handle_band_custom(wiphy, wiphy->bands[band], regd); @@ -2228,7 +2228,7 @@ static void reg_process_self_managed_hints(void) struct wiphy *wiphy; const struct ieee80211_regdomain *tmp; const struct ieee80211_regdomain *regd; - enum ieee80211_band band; + enum nl80211_band band; struct regulatory_request request = {}; list_for_each_entry(rdev, &cfg80211_rdev_list, list) { @@ -2246,7 +2246,7 @@ static void reg_process_self_managed_hints(void) rcu_assign_pointer(wiphy->regd, regd); rcu_free_regdom(tmp); - for (band = 0; band < IEEE80211_NUM_BANDS; band++) + for (band = 0; band < NUM_NL80211_BANDS; band++) handle_band_custom(wiphy, wiphy->bands[band], regd); reg_process_ht_flags(wiphy); @@ -2404,7 +2404,7 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) } EXPORT_SYMBOL(regulatory_hint); -void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band, +void regulatory_hint_country_ie(struct wiphy *wiphy, enum nl80211_band band, const u8 *country_ie, u8 country_ie_len) { char alpha2[2]; @@ -2504,11 +2504,11 @@ static void restore_alpha2(char *alpha2, bool reset_user) static void restore_custom_reg_settings(struct wiphy *wiphy) { struct ieee80211_supported_band *sband; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_channel *chan; int i; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { sband = wiphy->bands[band]; if (!sband) continue; @@ -2623,9 +2623,9 @@ void regulatory_hint_disconnect(void) static bool freq_is_chan_12_13_14(u16 freq) { - if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) || - freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) || - freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ)) + if (freq == ieee80211_channel_to_frequency(12, NL80211_BAND_2GHZ) || + freq == ieee80211_channel_to_frequency(13, NL80211_BAND_2GHZ) || + freq == ieee80211_channel_to_frequency(14, NL80211_BAND_2GHZ)) return true; return false; } @@ -2650,7 +2650,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, if (beacon_chan->beacon_found || beacon_chan->flags & IEEE80211_CHAN_RADAR || - (beacon_chan->band == IEEE80211_BAND_2GHZ && + (beacon_chan->band == NL80211_BAND_2GHZ && !freq_is_chan_12_13_14(beacon_chan->center_freq))) return 0; diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 9f495d76eca0..f6ced316b5a4 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -104,7 +104,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, * information for a band the BSS is not present in it will be ignored. */ void regulatory_hint_country_ie(struct wiphy *wiphy, - enum ieee80211_band band, + enum nl80211_band band, const u8 *country_ie, u8 country_ie_len); diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 50ea8e3fcbeb..abdf651a70d9 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -531,7 +531,7 @@ static int cmp_bss(struct cfg80211_bss *a, } static bool cfg80211_bss_type_match(u16 capability, - enum ieee80211_band band, + enum nl80211_band band, enum ieee80211_bss_type bss_type) { bool ret = true; @@ -540,7 +540,7 @@ static bool cfg80211_bss_type_match(u16 capability, if (bss_type == IEEE80211_BSS_TYPE_ANY) return ret; - if (band == IEEE80211_BAND_60GHZ) { + if (band == NL80211_BAND_60GHZ) { mask = WLAN_CAPABILITY_DMG_TYPE_MASK; switch (bss_type) { case IEEE80211_BSS_TYPE_ESS: @@ -1006,7 +1006,7 @@ cfg80211_inform_bss_data(struct wiphy *wiphy, if (!res) return NULL; - if (channel->band == IEEE80211_BAND_60GHZ) { + if (channel->band == NL80211_BAND_60GHZ) { bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK; if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP || bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS) @@ -1089,7 +1089,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, if (!res) return NULL; - if (channel->band == IEEE80211_BAND_60GHZ) { + if (channel->band == NL80211_BAND_60GHZ) { bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK; if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP || bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS) @@ -1185,7 +1185,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, struct iw_scan_req *wreq = NULL; struct cfg80211_scan_request *creq = NULL; int i, err, n_channels = 0; - enum ieee80211_band band; + enum nl80211_band band; if (!netif_running(dev)) return -ENETDOWN; @@ -1229,7 +1229,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, /* translate "Scan on frequencies" request */ i = 0; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { int j; if (!wiphy->bands[band]) @@ -1289,7 +1289,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, creq->n_ssids = 0; } - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < NUM_NL80211_BANDS; i++) if (wiphy->bands[i]) creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 1fba41676428..e22e5b83cfa9 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -81,7 +81,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) return -ENOMEM; if (wdev->conn->params.channel) { - enum ieee80211_band band = wdev->conn->params.channel->band; + enum nl80211_band band = wdev->conn->params.channel->band; struct ieee80211_supported_band *sband = wdev->wiphy->bands[band]; @@ -93,11 +93,11 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) request->rates[band] = (1 << sband->n_bitrates) - 1; } else { int i = 0, j; - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *bands; struct ieee80211_channel *channel; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { bands = wdev->wiphy->bands[band]; if (!bands) continue; diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 8da1fae23cfb..3c1091ae6c36 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -110,7 +110,7 @@ conf->dot11MeshHWMPconfirmationInterval; \ } while (0) -#define CHAN_ENTRY __field(enum ieee80211_band, band) \ +#define CHAN_ENTRY __field(enum nl80211_band, band) \ __field(u16, center_freq) #define CHAN_ASSIGN(chan) \ do { \ @@ -125,7 +125,7 @@ #define CHAN_PR_FMT "band: %d, freq: %u" #define CHAN_PR_ARG __entry->band, __entry->center_freq -#define CHAN_DEF_ENTRY __field(enum ieee80211_band, band) \ +#define CHAN_DEF_ENTRY __field(enum nl80211_band, band) \ __field(u32, control_freq) \ __field(u32, width) \ __field(u32, center_freq1) \ @@ -2647,7 +2647,7 @@ TRACE_EVENT(cfg80211_scan_done, TP_STRUCT__entry( __field(u32, n_channels) __dynamic_array(u8, ie, request ? request->ie_len : 0) - __array(u32, rates, IEEE80211_NUM_BANDS) + __array(u32, rates, NUM_NL80211_BANDS) __field(u32, wdev_id) MAC_ENTRY(wiphy_mac) __field(bool, no_cck) @@ -2658,7 +2658,7 @@ TRACE_EVENT(cfg80211_scan_done, memcpy(__get_dynamic_array(ie), request->ie, request->ie_len); memcpy(__entry->rates, request->rates, - IEEE80211_NUM_BANDS); + NUM_NL80211_BANDS); __entry->wdev_id = request->wdev ? request->wdev->identifier : 0; if (request->wiphy) @@ -2883,25 +2883,25 @@ TRACE_EVENT(rdev_start_radar_detection, TRACE_EVENT(rdev_set_mcast_rate, TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, - int mcast_rate[IEEE80211_NUM_BANDS]), + int mcast_rate[NUM_NL80211_BANDS]), TP_ARGS(wiphy, netdev, mcast_rate), TP_STRUCT__entry( WIPHY_ENTRY NETDEV_ENTRY - __array(int, mcast_rate, IEEE80211_NUM_BANDS) + __array(int, mcast_rate, NUM_NL80211_BANDS) ), TP_fast_assign( WIPHY_ASSIGN; NETDEV_ASSIGN; memcpy(__entry->mcast_rate, mcast_rate, - sizeof(int) * IEEE80211_NUM_BANDS); + sizeof(int) * NUM_NL80211_BANDS); ), TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]", WIPHY_PR_ARG, NETDEV_PR_ARG, - __entry->mcast_rate[IEEE80211_BAND_2GHZ], - __entry->mcast_rate[IEEE80211_BAND_5GHZ], - __entry->mcast_rate[IEEE80211_BAND_60GHZ]) + __entry->mcast_rate[NL80211_BAND_2GHZ], + __entry->mcast_rate[NL80211_BAND_5GHZ], + __entry->mcast_rate[NL80211_BAND_60GHZ]) ); TRACE_EVENT(rdev_set_coalesce, diff --git a/net/wireless/util.c b/net/wireless/util.c index 9f440a9de63b..f36039888eb5 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -47,7 +47,7 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband, if (WARN_ON(!sband)) return 1; - if (sband->band == IEEE80211_BAND_2GHZ) { + if (sband->band == NL80211_BAND_2GHZ) { if (scan_width == NL80211_BSS_CHAN_WIDTH_5 || scan_width == NL80211_BSS_CHAN_WIDTH_10) mandatory_flag = IEEE80211_RATE_MANDATORY_G; @@ -65,26 +65,26 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband, } EXPORT_SYMBOL(ieee80211_mandatory_rates); -int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band) +int ieee80211_channel_to_frequency(int chan, enum nl80211_band band) { /* see 802.11 17.3.8.3.2 and Annex J * there are overlapping channel numbers in 5GHz and 2GHz bands */ if (chan <= 0) return 0; /* not supported */ switch (band) { - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: if (chan == 14) return 2484; else if (chan < 14) return 2407 + chan * 5; break; - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: if (chan >= 182 && chan <= 196) return 4000 + chan * 5; else return 5000 + chan * 5; break; - case IEEE80211_BAND_60GHZ: + case NL80211_BAND_60GHZ: if (chan < 5) return 56160 + chan * 2160; break; @@ -116,11 +116,11 @@ EXPORT_SYMBOL(ieee80211_frequency_to_channel); struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, int freq) { - enum ieee80211_band band; + enum nl80211_band band; struct ieee80211_supported_band *sband; int i; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { sband = wiphy->bands[band]; if (!sband) @@ -137,12 +137,12 @@ struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, EXPORT_SYMBOL(__ieee80211_get_channel); static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, - enum ieee80211_band band) + enum nl80211_band band) { int i, want; switch (band) { - case IEEE80211_BAND_5GHZ: + case NL80211_BAND_5GHZ: want = 3; for (i = 0; i < sband->n_bitrates; i++) { if (sband->bitrates[i].bitrate == 60 || @@ -155,7 +155,7 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, } WARN_ON(want); break; - case IEEE80211_BAND_2GHZ: + case NL80211_BAND_2GHZ: want = 7; for (i = 0; i < sband->n_bitrates; i++) { if (sband->bitrates[i].bitrate == 10) { @@ -185,12 +185,12 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, } WARN_ON(want != 0 && want != 3 && want != 6); break; - case IEEE80211_BAND_60GHZ: + case NL80211_BAND_60GHZ: /* check for mandatory HT MCS 1..4 */ WARN_ON(!sband->ht_cap.ht_supported); WARN_ON((sband->ht_cap.mcs.rx_mask[0] & 0x1e) != 0x1e); break; - case IEEE80211_NUM_BANDS: + case NUM_NL80211_BANDS: WARN_ON(1); break; } @@ -198,9 +198,9 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, void ieee80211_set_bitrate_flags(struct wiphy *wiphy) { - enum ieee80211_band band; + enum nl80211_band band; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) + for (band = 0; band < NUM_NL80211_BANDS; band++) if (wiphy->bands[band]) set_mandatory_flags_band(wiphy->bands[band], band); } @@ -1399,22 +1399,22 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen, EXPORT_SYMBOL(ieee80211_ie_split_ric); bool ieee80211_operating_class_to_band(u8 operating_class, - enum ieee80211_band *band) + enum nl80211_band *band) { switch (operating_class) { case 112: case 115 ... 127: case 128 ... 130: - *band = IEEE80211_BAND_5GHZ; + *band = NL80211_BAND_5GHZ; return true; case 81: case 82: case 83: case 84: - *band = IEEE80211_BAND_2GHZ; + *band = NL80211_BAND_2GHZ; return true; case 180: - *band = IEEE80211_BAND_60GHZ; + *band = NL80211_BAND_60GHZ; return true; } @@ -1726,10 +1726,10 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy) { - enum ieee80211_band band; + enum nl80211_band band; unsigned int n_channels = 0; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) + for (band = 0; band < NUM_NL80211_BANDS; band++) if (wiphy->bands[band]) n_channels += wiphy->bands[band]->n_channels; diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index fd682832a0e3..4c89f0ca61ba 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -32,13 +32,13 @@ int cfg80211_wext_giwname(struct net_device *dev, if (!wdev) return -EOPNOTSUPP; - sband = wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; + sband = wdev->wiphy->bands[NL80211_BAND_5GHZ]; if (sband) { is_a = true; is_ht |= sband->ht_cap.ht_supported; } - sband = wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; + sband = wdev->wiphy->bands[NL80211_BAND_2GHZ]; if (sband) { int i; /* Check for mandatory rates */ @@ -143,7 +143,7 @@ int cfg80211_wext_giwrange(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct iw_range *range = (struct iw_range *) extra; - enum ieee80211_band band; + enum nl80211_band band; int i, c = 0; if (!wdev) @@ -215,7 +215,7 @@ int cfg80211_wext_giwrange(struct net_device *dev, } } - for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { + for (band = 0; band < NUM_NL80211_BANDS; band ++) { struct ieee80211_supported_band *sband; sband = wdev->wiphy->bands[band]; @@ -265,11 +265,11 @@ int cfg80211_wext_freq(struct iw_freq *freq) * -EINVAL for impossible things. */ if (freq->e == 0) { - enum ieee80211_band band = IEEE80211_BAND_2GHZ; + enum nl80211_band band = NL80211_BAND_2GHZ; if (freq->m < 0) return 0; if (freq->m > 14) - band = IEEE80211_BAND_5GHZ; + band = NL80211_BAND_5GHZ; return ieee80211_channel_to_frequency(freq->m, band); } else { int i, div = 1000000; @@ -1245,7 +1245,7 @@ static int cfg80211_wext_siwrate(struct net_device *dev, maxrate = rate->value / 100000; } - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + for (band = 0; band < NUM_NL80211_BANDS; band++) { sband = wdev->wiphy->bands[band]; if (sband == NULL) continue; -- GitLab From e0bef81db1d089c53ba001acac01d0b375078cb7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 4 Apr 2016 16:43:50 +0900 Subject: [PATCH 2215/9938] ARM: exynos_defconfig: Enable Trats2 audio codec, touchscreen and sensors The Exynos4412-based Trats2 board has Asahi Kasei AK 3-Axis Magnetometer, CM36651 proximity/ambient light sensor, MMS114 touchscreen and Wolfson Microelectronics WM1811 CODEC. Enable them in defconfig to get some testing coverage and use its features. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/configs/exynos_defconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 6ffd7e76f3ce..d8f09e5558bf 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -74,6 +74,7 @@ CONFIG_KEYBOARD_CROS_EC=y CONFIG_MOUSE_CYAPA=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y +CONFIG_TOUCHSCREEN_MMS114=y CONFIG_INPUT_MISC=y CONFIG_INPUT_MAX77693_HAPTIC=y CONFIG_INPUT_MAX8997_HAPTIC=y @@ -93,6 +94,7 @@ CONFIG_SPI=y CONFIG_SPI_GPIO=y CONFIG_SPI_S3C64XX=y CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_WM8994=y CONFIG_POWER_SUPPLY=y CONFIG_BATTERY_SBS=y CONFIG_BATTERY_MAX17040=y @@ -134,6 +136,7 @@ CONFIG_REGULATOR_S2MPA01=y CONFIG_REGULATOR_S2MPS11=y CONFIG_REGULATOR_S5M8767=y CONFIG_REGULATOR_TPS65090=y +CONFIG_REGULATOR_WM8994=y CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y @@ -160,6 +163,8 @@ CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y CONFIG_SND_SOC_SAMSUNG=y +CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994=y +CONFIG_SND_SOC_SMDK_WM8994_PCM=y CONFIG_SND_SOC_SNOW=y CONFIG_SND_SOC_ODROIDX2=y CONFIG_SND_SIMPLE_CARD=y @@ -210,6 +215,8 @@ CONFIG_EXTCON_MAX77693=y CONFIG_EXTCON_MAX8997=y CONFIG_IIO=y CONFIG_EXYNOS_ADC=y +CONFIG_CM36651=y +CONFIG_AK8975=y CONFIG_PWM=y CONFIG_PWM_SAMSUNG=y CONFIG_PHY_EXYNOS5250_SATA=y -- GitLab From 98d729c4b2e7ecf6ad775b7d1ff4c866e4f01b6c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 8 Apr 2016 15:02:09 -0400 Subject: [PATCH 2216/9938] ARM: exynos_defconfig: Enable CPUFreq governors as modules Currently only the ondemand and performance CPUFreq policy governors are enabled in the Exynos defconfig. But the other governors are also useful for some cases, enable them to allow users change the default if needed. The options are enabled as module to keep the kernel image size minimal. Signed-off-by: Javier Martinez Canillas Signed-off-by: Krzysztof Kozlowski --- arch/arm/configs/exynos_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index d8f09e5558bf..10f49ab5328e 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -28,6 +28,10 @@ CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttyS CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=m CONFIG_CPUFREQ_DT=y CONFIG_CPU_IDLE=y CONFIG_ARM_EXYNOS_CPUIDLE=y -- GitLab From 0fe3ff4454c9ba2c9d6774ecafed799fe009d145 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 8 Apr 2016 15:02:10 -0400 Subject: [PATCH 2217/9938] ARM: multi_v7_defconfig: Enable CPUFreq governors as modules Currently only the ondemand and performance CPUFreq policy governors are enabled in multi_v7 defconfig. But the other governors are also useful for some cases, enable them to allow users change the default if needed. The options are enabled as module to keep the kernel image size minimal. Signed-off-by: Javier Martinez Canillas Signed-off-by: Krzysztof Kozlowski --- arch/arm/configs/multi_v7_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 28234906a064..68726bdba01c 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -131,6 +131,10 @@ CONFIG_KEXEC=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=m CONFIG_QORIQ_CPUFREQ=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y -- GitLab From 2556247dea686d6fd21f1b4249ec527b9b285201 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Sat, 26 Mar 2016 12:28:26 +0100 Subject: [PATCH 2218/9938] ARM: multi_v5_defconfig: Enable recommended options for systemd Enable FHANDLE, CGROUPS, BLK_DEV_BSG and DEVTMPFS as recommended by systemd (which also matches the multi_v7 defconfig). Also enable IPV6, which defaults to 'y' by now. Signed-off-by: Jan Luebbe Signed-off-by: Shawn Guo --- arch/arm/configs/multi_v5_defconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig index bb8d60998b70..a822dd346fb2 100644 --- a/arch/arm/configs/multi_v5_defconfig +++ b/arch/arm/configs/multi_v5_defconfig @@ -1,14 +1,15 @@ CONFIG_SYSVIPC=y +CONFIG_FHANDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=19 +CONFIG_CGROUPS=y CONFIG_BLK_DEV_INITRD=y CONFIG_PROFILING=y CONFIG_OPROFILE=y CONFIG_KPROBES=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set # CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_MVEBU=y CONFIG_MACH_KIRKWOOD=y @@ -65,13 +66,14 @@ CONFIG_IP_MULTICAST=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y -# CONFIG_IPV6 is not set CONFIG_NET_DSA=y CONFIG_NET_SWITCHDEV=y CONFIG_NET_PKTGEN=m CONFIG_CFG80211=y CONFIG_MAC80211=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_IMX_WEIM=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y -- GitLab From 955d809bdeaea3663cf6ac1ee72cd50775bbab9d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 23 Jan 2016 17:55:30 +0900 Subject: [PATCH 2219/9938] ARM: tegra: Remove redundant ARM_L1_CACHE_SHIFT_6 select These two are both ARMv7 SoCs. They need not explicitly select ARM_L1_CACHE_SHIFT_6 because it is enabled along with CPU_V7. Refer to commit a092f2b15399 ("ARM: 7291/1: cache: assume 64-byte L1 cachelines for ARMv7 CPUs"). Signed-off-by: Masahiro Yamada Signed-off-by: Thierry Reding --- drivers/soc/tegra/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index d0c3c3e085e3..03089ad2fc65 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -31,7 +31,6 @@ config ARCH_TEGRA_3x_SOC config ARCH_TEGRA_114_SOC bool "Enable support for Tegra114 family" select ARM_ERRATA_798181 if SMP - select ARM_L1_CACHE_SHIFT_6 select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA114 select TEGRA_TIMER @@ -41,7 +40,6 @@ config ARCH_TEGRA_114_SOC config ARCH_TEGRA_124_SOC bool "Enable support for Tegra124 family" - select ARM_L1_CACHE_SHIFT_6 select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA124 select TEGRA_TIMER -- GitLab From e10982487d3bd84d8a7170a38a8ed07ea431322d Mon Sep 17 00:00:00 2001 From: Ralf Ramsauer Date: Tue, 26 Jan 2016 17:59:17 +0100 Subject: [PATCH 2220/9938] ARM: tegra: Fix copy/paste typo in several DTS includes The comment about the 8250 vs. APB DMA-enabled UART devices that was added for Tegra20 and Tegra30 in commit b6551bb933f9 ("ARM: tegra: dts: add aliases and DMA requestor for serial controller") introduced a typo that has since spread to various other DTS include files. Fix all occurrences of this typo. Signed-off-by: Ralf Ramsauer Acked-by: Stephen Warren [treding@nvidia.com: amend subject, add commit message] Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra114.dtsi | 2 +- arch/arm/boot/dts/tegra124.dtsi | 2 +- arch/arm/boot/dts/tegra20.dtsi | 2 +- arch/arm/boot/dts/tegra30.dtsi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index d845bd1448b5..5017ed8ad5c4 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi @@ -256,7 +256,7 @@ * driver and APB DMA based serial driver for higher baudrate * and performace. To enable the 8250 based driver, the compatible * is "nvidia,tegra114-uart", "nvidia,tegra20-uart" and to enable - * the APB DMA based serial driver, the comptible is + * the APB DMA based serial driver, the compatible is * "nvidia,tegra114-hsuart", "nvidia,tegra30-hsuart". */ uarta: serial@70006000 { diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi index 68669f791c8b..995289b59e11 100644 --- a/arch/arm/boot/dts/tegra124.dtsi +++ b/arch/arm/boot/dts/tegra124.dtsi @@ -322,7 +322,7 @@ * driver and APB DMA based serial driver for higher baudrate * and performace. To enable the 8250 based driver, the compatible * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable - * the APB DMA based serial driver, the comptible is + * the APB DMA based serial driver, the compatible is * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart". */ uarta: serial@0,70006000 { diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 33173e1bace9..8fb61b93c226 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -309,7 +309,7 @@ * driver and APB DMA based serial driver for higher baudrate * and performace. To enable the 8250 based driver, the compatible * is "nvidia,tegra20-uart" and to enable the APB DMA based serial - * driver, the comptible is "nvidia,tegra20-hsuart". + * driver, the compatible is "nvidia,tegra20-hsuart". */ uarta: serial@70006000 { compatible = "nvidia,tegra20-uart"; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index 313e260529a3..c6edc8cea34e 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -371,7 +371,7 @@ * driver and APB DMA based serial driver for higher baudrate * and performace. To enable the 8250 based driver, the compatible * is "nvidia,tegra30-uart", "nvidia,tegra20-uart" and to enable - * the APB DMA based serial driver, the comptible is + * the APB DMA based serial driver, the compatible is * "nvidia,tegra30-hsuart", "nvidia,tegra20-hsuart". */ uarta: serial@70006000 { -- GitLab From c90bb7b9b968272aa4ee7fed605105b00407395a Mon Sep 17 00:00:00 2001 From: Ralf Ramsauer Date: Tue, 26 Jan 2016 17:59:18 +0100 Subject: [PATCH 2221/9938] ARM: tegra: Add high speed UARTs to Jetson TK1 device tree This patch enables the APB DMA high speed UARTs of the Jetson TK1. So far, they were only enabled in NVidia's official BSP. Those additional UARTs are exposed on the expansion connector J3A2: UART1: Pin 41: BR_UART1_TXD Pin 44: BR_UART1_RXD UART2: Pin 65: UART2_RXD Pin 68: UART2_TXD Pin 71: UART2_CTS_L Pin 74: UART2_RTS_L Signed-off-by: Ralf Ramsauer Acked-by: Stephen Warren Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra124-jetson-tk1.dts | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts index 66b4451eb2ca..67e96f7d5654 100644 --- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts @@ -12,7 +12,11 @@ aliases { rtc0 = "/i2c@0,7000d000/pmic@40"; rtc1 = "/rtc@0,7000e000"; + + /* This order keeps the mapping DB9 connector <-> ttyS0 */ serial0 = &uartd; + serial1 = &uarta; + serial2 = &uartb; }; memory { @@ -1367,6 +1371,28 @@ }; }; + /* + * First high speed UART, exposed on the expansion connector J3A2 + * Pin 41: BR_UART1_TXD + * Pin 44: BR_UART1_RXD + */ + serial@70006000 { + compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart"; + status = "okay"; + }; + + /* + * Second high speed UART, exposed on the expansion connector J3A2 + * Pin 65: UART2_RXD + * Pin 68: UART2_TXD + * Pin 71: UART2_CTS_L + * Pin 74: UART2_RTS_L + */ + serial@70006040 { + compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart"; + status = "okay"; + }; + /* DB9 serial port */ serial@0,70006300 { status = "okay"; -- GitLab From b664129459f529d403d05570115254534611b52d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 17 Nov 2015 11:15:45 +0100 Subject: [PATCH 2222/9938] ARM: tegra: Enable watchdog support for Tegra114 and Tegra124 Watchdog support was added to the timer block with Tegra30. Tegra20 did not have this yet. However, the Tegra114 and Tegra124 DTSI files had an entry in the compatible string list for "nvidia,tegra20-timer", but not for "nvidia,tegra30-timer", which is why watchdog support isn't enabled on them. Fix this by adding an entry for "nvidia,tegra30-timer" to the compatible string list of the timer block on Tegra114 and Tegra124. This allows the watchdog to work on Jetson TK1. Signed-off-by: Maarten Lankhorst Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra114.dtsi | 2 +- arch/arm/boot/dts/tegra124.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index 5017ed8ad5c4..cb9393a53422 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi @@ -150,7 +150,7 @@ }; timer@60005000 { - compatible = "nvidia,tegra114-timer", "nvidia,tegra20-timer"; + compatible = "nvidia,tegra114-timer", "nvidia,tegra30-timer", "nvidia,tegra20-timer"; reg = <0x60005000 0x400>; interrupts = , , diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi index 995289b59e11..e4eac1f01e64 100644 --- a/arch/arm/boot/dts/tegra124.dtsi +++ b/arch/arm/boot/dts/tegra124.dtsi @@ -208,7 +208,7 @@ }; timer@0,60005000 { - compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer"; + compatible = "nvidia,tegra124-timer", "nvidia,tegra30-timer", "nvidia,tegra20-timer"; reg = <0x0 0x60005000 0x0 0x400>; interrupts = , , -- GitLab From d1c04d30c3973df6ec0933f21ff8a56028e47ce7 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 8 Feb 2016 21:55:43 +0000 Subject: [PATCH 2223/9938] ARM: tegra: Replace legacy *,wakeup property with wakeup-source Though the keyboard and other driver will continue to support the legacy "gpio-key,wakeup", "nvidia,wakeup-source" boolean property to enable the wakeup source, "wakeup-source" is the new standard binding. This patch replaces all the legacy wakeup properties with the unified "wakeup-source" property in order to avoid any further copy-paste duplication. Cc: Stephen Warren Cc: Thierry Reding Cc: Alexandre Courbot Cc: linux-tegra@vger.kernel.org Signed-off-by: Sudeep Holla Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra114-dalmore.dts | 2 +- arch/arm/boot/dts/tegra114-roth.dts | 2 +- arch/arm/boot/dts/tegra114-tn7.dts | 2 +- arch/arm/boot/dts/tegra124-jetson-tk1.dts | 2 +- arch/arm/boot/dts/tegra124-nyan.dtsi | 4 ++-- arch/arm/boot/dts/tegra124-venice2.dts | 2 +- arch/arm/boot/dts/tegra20-harmony.dts | 2 +- arch/arm/boot/dts/tegra20-paz00.dts | 2 +- arch/arm/boot/dts/tegra20-seaboard.dts | 4 ++-- arch/arm/boot/dts/tegra20-trimslice.dts | 2 +- arch/arm/boot/dts/tegra20-ventana.dts | 2 +- arch/arm/boot/dts/tegra20-whistler.dts | 2 +- arch/arm/boot/dts/tegra30-apalis-eval.dts | 2 +- arch/arm/boot/dts/tegra30-cardhu.dtsi | 2 +- arch/arm/boot/dts/tegra30-colibri-eval-v3.dts | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts index 8b7aa0dcdc6e..40b88051ea3e 100644 --- a/arch/arm/boot/dts/tegra114-dalmore.dts +++ b/arch/arm/boot/dts/tegra114-dalmore.dts @@ -1164,7 +1164,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; volume_down { diff --git a/arch/arm/boot/dts/tegra114-roth.dts b/arch/arm/boot/dts/tegra114-roth.dts index 38acf78d7815..9d868af97b8e 100644 --- a/arch/arm/boot/dts/tegra114-roth.dts +++ b/arch/arm/boot/dts/tegra114-roth.dts @@ -1047,7 +1047,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra114-tn7.dts b/arch/arm/boot/dts/tegra114-tn7.dts index f91c2c9b2f94..89047edb5c5f 100644 --- a/arch/arm/boot/dts/tegra114-tn7.dts +++ b/arch/arm/boot/dts/tegra114-tn7.dts @@ -292,7 +292,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; volume_down { diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts index 67e96f7d5654..95b580a9369b 100644 --- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts @@ -1787,7 +1787,7 @@ gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <10>; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/tegra124-nyan.dtsi index ec1aa64ded68..c8495eb41fdd 100644 --- a/arch/arm/boot/dts/tegra124-nyan.dtsi +++ b/arch/arm/boot/dts/tegra124-nyan.dtsi @@ -509,7 +509,7 @@ linux,input-type = <5>; linux,code = ; debounce-interval = <1>; - gpio-key,wakeup; + wakeup-source; }; power { @@ -517,7 +517,7 @@ gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <30>; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts index cfbdf429b45d..4a5f23c5d893 100644 --- a/arch/arm/boot/dts/tegra124-venice2.dts +++ b/arch/arm/boot/dts/tegra124-venice2.dts @@ -975,7 +975,7 @@ gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <10>; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts index b926a07b9443..679f9c49e9f4 100644 --- a/arch/arm/boot/dts/tegra20-harmony.dts +++ b/arch/arm/boot/dts/tegra20-harmony.dts @@ -655,7 +655,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index ed7e1009326c..fce397e3e2ce 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -521,7 +521,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(J, 7) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index aea8994b35f2..a112a415ecd5 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -807,7 +807,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; lid { @@ -816,7 +816,7 @@ linux,input-type = <5>; /* EV_SW */ linux,code = <0>; /* SW_LID */ debounce-interval = <1>; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index d99af4ef9c64..a4aaff326f99 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -392,7 +392,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(X, 6) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts index 04c58e9ca490..b205935a1236 100644 --- a/arch/arm/boot/dts/tegra20-ventana.dts +++ b/arch/arm/boot/dts/tegra20-ventana.dts @@ -601,7 +601,7 @@ label = "Power"; gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; linux,code = ; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts index 340d81108df1..5564d6e975d8 100644 --- a/arch/arm/boot/dts/tegra20-whistler.dts +++ b/arch/arm/boot/dts/tegra20-whistler.dts @@ -508,7 +508,7 @@ nvidia,repeat-delay-ms = <160>; nvidia,kbc-row-pins = <0 1 2>; nvidia,kbc-col-pins = <16 17>; - nvidia,wakeup-source; + wakeup-source; linux,keymap = ; linux,code = ; debounce-interval = <10>; - gpio-key,wakeup; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index bb1ca158273c..1714e755c3de 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -626,7 +626,7 @@ interrupts = <2 0>; linux,code = ; debounce-interval = <100>; - gpio-key,wakeup; + wakeup-source; }; volume-down { diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts index 3ff019f47d00..72c79ac9a72f 100644 --- a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts @@ -142,7 +142,7 @@ gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>; linux,code = ; debounce-interval = <10>; - gpio-key,wakeup; + wakeup-source; }; }; -- GitLab From f5bbb327a4e896a7f353762068b786852d98187b Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 9 Feb 2016 13:51:59 +0000 Subject: [PATCH 2224/9938] ARM: tegra: Add stdout-path for various boards For Tegra boards, the device-tree alias serial0 is used for the console and so add the stdout-path information so that the console no longer needs to be passed via the kernel boot parameters. This has been tested on boards, tegra20-trimslice, tegra30-beaver, tegra114-dalmore and tegra124-jetson-tk1. Signed-off-by: Jon Hunter Acked-by: Stefan Agner Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra114-dalmore.dts | 4 ++++ arch/arm/boot/dts/tegra124-jetson-tk1.dts | 4 ++++ arch/arm/boot/dts/tegra124-nyan.dtsi | 4 ++++ arch/arm/boot/dts/tegra124-venice2.dts | 4 ++++ arch/arm/boot/dts/tegra20-harmony.dts | 4 ++++ arch/arm/boot/dts/tegra20-iris-512.dts | 4 ++++ arch/arm/boot/dts/tegra20-medcom-wide.dts | 4 ++++ arch/arm/boot/dts/tegra20-paz00.dts | 4 ++++ arch/arm/boot/dts/tegra20-seaboard.dts | 4 ++++ arch/arm/boot/dts/tegra20-tamonten.dtsi | 4 ++++ arch/arm/boot/dts/tegra20-trimslice.dts | 4 ++++ arch/arm/boot/dts/tegra20-ventana.dts | 4 ++++ arch/arm/boot/dts/tegra20-whistler.dts | 4 ++++ arch/arm/boot/dts/tegra30-apalis-eval.dts | 4 ++++ arch/arm/boot/dts/tegra30-beaver.dts | 4 ++++ arch/arm/boot/dts/tegra30-cardhu.dtsi | 4 ++++ arch/arm/boot/dts/tegra30-colibri-eval-v3.dts | 4 ++++ 17 files changed, 68 insertions(+) diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts index 40b88051ea3e..c970bf65c74c 100644 --- a/arch/arm/boot/dts/tegra114-dalmore.dts +++ b/arch/arm/boot/dts/tegra114-dalmore.dts @@ -18,6 +18,10 @@ serial0 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x80000000 0x40000000>; }; diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts index 95b580a9369b..a99f07ad6312 100644 --- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts @@ -19,6 +19,10 @@ serial2 = &uartb; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x0 0x80000000 0x0 0x80000000>; }; diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/tegra124-nyan.dtsi index c8495eb41fdd..5f1fc1410bd0 100644 --- a/arch/arm/boot/dts/tegra124-nyan.dtsi +++ b/arch/arm/boot/dts/tegra124-nyan.dtsi @@ -8,6 +8,10 @@ serial0 = &uarta; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x0 0x80000000 0x0 0x80000000>; }; diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts index 4a5f23c5d893..0318258dde3e 100644 --- a/arch/arm/boot/dts/tegra124-venice2.dts +++ b/arch/arm/boot/dts/tegra124-venice2.dts @@ -13,6 +13,10 @@ serial0 = &uarta; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x0 0x80000000 0x0 0x80000000>; }; diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts index 679f9c49e9f4..d2e960cbc001 100644 --- a/arch/arm/boot/dts/tegra20-harmony.dts +++ b/arch/arm/boot/dts/tegra20-harmony.dts @@ -13,6 +13,10 @@ serial0 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x00000000 0x40000000>; }; diff --git a/arch/arm/boot/dts/tegra20-iris-512.dts b/arch/arm/boot/dts/tegra20-iris-512.dts index 1dd7d7bfdfcc..bb56dfe9e10c 100644 --- a/arch/arm/boot/dts/tegra20-iris-512.dts +++ b/arch/arm/boot/dts/tegra20-iris-512.dts @@ -11,6 +11,10 @@ serial1 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + host1x@50000000 { hdmi@54280000 { status = "okay"; diff --git a/arch/arm/boot/dts/tegra20-medcom-wide.dts b/arch/arm/boot/dts/tegra20-medcom-wide.dts index 9b87526ab0b7..34c6588e92ef 100644 --- a/arch/arm/boot/dts/tegra20-medcom-wide.dts +++ b/arch/arm/boot/dts/tegra20-medcom-wide.dts @@ -10,6 +10,10 @@ serial0 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + pwm@7000a000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index fce397e3e2ce..33ed2b23026b 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -14,6 +14,10 @@ serial1 = &uartc; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x00000000 0x20000000>; }; diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index a112a415ecd5..94b60a710dd8 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -13,6 +13,10 @@ serial0 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x00000000 0x40000000>; }; diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi index 13d4e6185275..025e9e8037da 100644 --- a/arch/arm/boot/dts/tegra20-tamonten.dtsi +++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi @@ -10,6 +10,10 @@ serial0 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x00000000 0x20000000>; }; diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index a4aaff326f99..4a035f74043a 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -13,6 +13,10 @@ serial0 = &uarta; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x00000000 0x40000000>; }; diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts index b205935a1236..a28c060a839b 100644 --- a/arch/arm/boot/dts/tegra20-ventana.dts +++ b/arch/arm/boot/dts/tegra20-ventana.dts @@ -13,6 +13,10 @@ serial0 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x00000000 0x40000000>; }; diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts index 5564d6e975d8..073806d07b2b 100644 --- a/arch/arm/boot/dts/tegra20-whistler.dts +++ b/arch/arm/boot/dts/tegra20-whistler.dts @@ -13,6 +13,10 @@ serial0 = &uarta; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x00000000 0x20000000>; }; diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts index 3ca3b4c6975b..99a69457dbf5 100644 --- a/arch/arm/boot/dts/tegra30-apalis-eval.dts +++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts @@ -17,6 +17,10 @@ serial3 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + pcie-controller@00003000 { status = "okay"; diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts index 3dede3934446..1eca3b28ac64 100644 --- a/arch/arm/boot/dts/tegra30-beaver.dts +++ b/arch/arm/boot/dts/tegra30-beaver.dts @@ -12,6 +12,10 @@ serial0 = &uarta; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x80000000 0x7ff00000>; }; diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index 1714e755c3de..4721c1c9c780 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -35,6 +35,10 @@ serial1 = &uartc; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x80000000 0x40000000>; }; diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts index 72c79ac9a72f..76875c3160fe 100644 --- a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts @@ -15,6 +15,10 @@ serial2 = &uartd; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + host1x@50000000 { dc@54200000 { rgb { -- GitLab From e7d9b2709ab04059b6a5f0ff016826dc4d4f96e4 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 17 Mar 2016 14:19:05 +0000 Subject: [PATCH 2225/9938] ARM: tegra: Correct interrupt type for ARM TWD The ARM TWD interrupt is a private peripheral interrupt (PPI) and per the ARM GIC documentation, whether the type for PPIs can be set is IMPLEMENTATION DEFINED. For Tegra20/30 devices the PPI type cannot be set and so when we attempt to set the type for the ARM TWD interrupt it fails. This has gone unnoticed because it fails silently and because we cannot re-configure the type it has had no impact. Nevertheless fix the type for the TWD interrupt so that it matches the hardware configuration. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra20.dtsi | 2 +- arch/arm/boot/dts/tegra30.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 8fb61b93c226..2207c08e3fa3 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -145,7 +145,7 @@ interrupt-parent = <&intc>; reg = <0x50040600 0x20>; interrupts = ; + (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>; clocks = <&tegra_car TEGRA20_CLK_TWD>; }; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index c6edc8cea34e..5030065cbdfe 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -230,7 +230,7 @@ reg = <0x50040600 0x20>; interrupt-parent = <&intc>; interrupts = ; + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>; clocks = <&tegra_car TEGRA30_CLK_TWD>; }; -- GitLab From c1fd85b445d99236dc174b08b371de1a15a3d337 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 11 Apr 2016 17:53:02 -0400 Subject: [PATCH 2226/9938] arm64: tegra: Add pinmux for Smaug board Add pinmux node for Tegra210 Smaug board. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra210-smaug.dts | 1271 +++++++++++++++++ 1 file changed, 1271 insertions(+) diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts index 89d16e09c2d7..3d01af78cfb3 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts @@ -1,6 +1,7 @@ /dts-v1/; #include +#include #include "tegra210.dtsi" @@ -25,6 +26,1276 @@ reg = <0x0 0x80000000 0x0 0xc0000000>; }; + pinmux: pinmux@700008d4 { + pinctrl-names = "boot"; + pinctrl-0 = <&state_boot>; + + state_boot: pinmux { + pex_l0_rst_n_pa0 { + nvidia,pins = "pex_l0_rst_n_pa0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + pex_l0_clkreq_n_pa1 { + nvidia,pins = "pex_l0_clkreq_n_pa1"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + pex_wake_n_pa2 { + nvidia,pins = "pex_wake_n_pa2"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + pex_l1_rst_n_pa3 { + nvidia,pins = "pex_l1_rst_n_pa3"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + pex_l1_clkreq_n_pa4 { + nvidia,pins = "pex_l1_clkreq_n_pa4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + sata_led_active_pa5 { + nvidia,pins = "sata_led_active_pa5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pa6 { + nvidia,pins = "pa6"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap1_fs_pb0 { + nvidia,pins = "dap1_fs_pb0"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap1_din_pb1 { + nvidia,pins = "dap1_din_pb1"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap1_dout_pb2 { + nvidia,pins = "dap1_dout_pb2"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap1_sclk_pb3 { + nvidia,pins = "dap1_sclk_pb3"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi2_mosi_pb4 { + nvidia,pins = "spi2_mosi_pb4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi2_miso_pb5 { + nvidia,pins = "spi2_miso_pb5"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi2_sck_pb6 { + nvidia,pins = "spi2_sck_pb6"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi2_cs0_pb7 { + nvidia,pins = "spi2_cs0_pb7"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi1_mosi_pc0 { + nvidia,pins = "spi1_mosi_pc0"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi1_miso_pc1 { + nvidia,pins = "spi1_miso_pc1"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi1_sck_pc2 { + nvidia,pins = "spi1_sck_pc2"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi1_cs0_pc3 { + nvidia,pins = "spi1_cs0_pc3"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi1_cs1_pc4 { + nvidia,pins = "spi1_cs1_pc4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi4_sck_pc5 { + nvidia,pins = "spi4_sck_pc5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi4_cs0_pc6 { + nvidia,pins = "spi4_cs0_pc6"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi4_mosi_pc7 { + nvidia,pins = "spi4_mosi_pc7"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spi4_miso_pd0 { + nvidia,pins = "spi4_miso_pd0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart3_tx_pd1 { + nvidia,pins = "uart3_tx_pd1"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart3_rx_pd2 { + nvidia,pins = "uart3_rx_pd2"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart3_rts_pd3 { + nvidia,pins = "uart3_rts_pd3"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart3_cts_pd4 { + nvidia,pins = "uart3_cts_pd4"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dmic1_clk_pe0 { + nvidia,pins = "dmic1_clk_pe0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dmic1_dat_pe1 { + nvidia,pins = "dmic1_dat_pe1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dmic2_clk_pe2 { + nvidia,pins = "dmic2_clk_pe2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dmic2_dat_pe3 { + nvidia,pins = "dmic2_dat_pe3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dmic3_clk_pe4 { + nvidia,pins = "dmic3_clk_pe4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dmic3_dat_pe5 { + nvidia,pins = "dmic3_dat_pe5"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pe6 { + nvidia,pins = "pe6"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pe7 { + nvidia,pins = "pe7"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + gen3_i2c_scl_pf0 { + nvidia,pins = "gen3_i2c_scl_pf0"; + nvidia,function = "i2c3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + gen3_i2c_sda_pf1 { + nvidia,pins = "gen3_i2c_sda_pf1"; + nvidia,function = "i2c3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + uart2_tx_pg0 { + nvidia,pins = "uart2_tx_pg0"; + nvidia,function = "uartb"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart2_rx_pg1 { + nvidia,pins = "uart2_rx_pg1"; + nvidia,function = "uartb"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart2_rts_pg2 { + nvidia,pins = "uart2_rts_pg2"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart2_cts_pg3 { + nvidia,pins = "uart2_cts_pg3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + wifi_en_ph0 { + nvidia,pins = "wifi_en_ph0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + wifi_rst_ph1 { + nvidia,pins = "wifi_rst_ph1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + wifi_wake_ap_ph2 { + nvidia,pins = "wifi_wake_ap_ph2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + ap_wake_bt_ph3 { + nvidia,pins = "ap_wake_bt_ph3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + bt_rst_ph4 { + nvidia,pins = "bt_rst_ph4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + bt_wake_ap_ph5 { + nvidia,pins = "bt_wake_ap_ph5"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + ph6 { + nvidia,pins = "ph6"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + ap_wake_nfc_ph7 { + nvidia,pins = "ap_wake_nfc_ph7"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + nfc_en_pi0 { + nvidia,pins = "nfc_en_pi0"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + nfc_int_pi1 { + nvidia,pins = "nfc_int_pi1"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + gps_en_pi2 { + nvidia,pins = "gps_en_pi2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + gps_rst_pi3 { + nvidia,pins = "gps_rst_pi3"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart4_tx_pi4 { + nvidia,pins = "uart4_tx_pi4"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart4_rx_pi5 { + nvidia,pins = "uart4_rx_pi5"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart4_rts_pi6 { + nvidia,pins = "uart4_rts_pi6"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart4_cts_pi7 { + nvidia,pins = "uart4_cts_pi7"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + gen1_i2c_sda_pj0 { + nvidia,pins = "gen1_i2c_sda_pj0"; + nvidia,function = "i2c1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + gen1_i2c_scl_pj1 { + nvidia,pins = "gen1_i2c_scl_pj1"; + nvidia,function = "i2c1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + gen2_i2c_scl_pj2 { + nvidia,pins = "gen2_i2c_scl_pj2"; + nvidia,function = "i2c2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + gen2_i2c_sda_pj3 { + nvidia,pins = "gen2_i2c_sda_pj3"; + nvidia,function = "i2c2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + dap4_fs_pj4 { + nvidia,pins = "dap4_fs_pj4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap4_din_pj5 { + nvidia,pins = "dap4_din_pj5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap4_dout_pj6 { + nvidia,pins = "dap4_dout_pj6"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap4_sclk_pj7 { + nvidia,pins = "dap4_sclk_pj7"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk0 { + nvidia,pins = "pk0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk1 { + nvidia,pins = "pk1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk2 { + nvidia,pins = "pk2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk3 { + nvidia,pins = "pk3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk4 { + nvidia,pins = "pk4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk5 { + nvidia,pins = "pk5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk6 { + nvidia,pins = "pk6"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pk7 { + nvidia,pins = "pk7"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pl0 { + nvidia,pins = "pl0"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pl1 { + nvidia,pins = "pl1"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc1_clk_pm0 { + nvidia,pins = "sdmmc1_clk_pm0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc1_cmd_pm1 { + nvidia,pins = "sdmmc1_cmd_pm1"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc1_dat3_pm2 { + nvidia,pins = "sdmmc1_dat3_pm2"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc1_dat2_pm3 { + nvidia,pins = "sdmmc1_dat2_pm3"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc1_dat1_pm4 { + nvidia,pins = "sdmmc1_dat1_pm4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc1_dat0_pm5 { + nvidia,pins = "sdmmc1_dat0_pm5"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc3_clk_pp0 { + nvidia,pins = "sdmmc3_clk_pp0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc3_cmd_pp1 { + nvidia,pins = "sdmmc3_cmd_pp1"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc3_dat3_pp2 { + nvidia,pins = "sdmmc3_dat3_pp2"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc3_dat2_pp3 { + nvidia,pins = "sdmmc3_dat2_pp3"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc3_dat1_pp4 { + nvidia,pins = "sdmmc3_dat1_pp4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + sdmmc3_dat0_pp5 { + nvidia,pins = "sdmmc3_dat0_pp5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam1_mclk_ps0 { + nvidia,pins = "cam1_mclk_ps0"; + nvidia,function = "extperiph3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam2_mclk_ps1 { + nvidia,pins = "cam2_mclk_ps1"; + nvidia,function = "extperiph3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam_i2c_scl_ps2 { + nvidia,pins = "cam_i2c_scl_ps2"; + nvidia,function = "i2cvi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + cam_i2c_sda_ps3 { + nvidia,pins = "cam_i2c_sda_ps3"; + nvidia,function = "i2cvi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + cam_rst_ps4 { + nvidia,pins = "cam_rst_ps4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam_af_en_ps5 { + nvidia,pins = "cam_af_en_ps5"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam_flash_en_ps6 { + nvidia,pins = "cam_flash_en_ps6"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam1_pwdn_ps7 { + nvidia,pins = "cam1_pwdn_ps7"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam2_pwdn_pt0 { + nvidia,pins = "cam2_pwdn_pt0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cam1_strobe_pt1 { + nvidia,pins = "cam1_strobe_pt1"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart1_tx_pu0 { + nvidia,pins = "uart1_tx_pu0"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart1_rx_pu1 { + nvidia,pins = "uart1_rx_pu1"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart1_rts_pu2 { + nvidia,pins = "uart1_rts_pu2"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + uart1_cts_pu3 { + nvidia,pins = "uart1_cts_pu3"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + lcd_bl_pwm_pv0 { + nvidia,pins = "lcd_bl_pwm_pv0"; + nvidia,function = "rsvd3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + lcd_bl_en_pv1 { + nvidia,pins = "lcd_bl_en_pv1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + lcd_rst_pv2 { + nvidia,pins = "lcd_rst_pv2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + lcd_gpio1_pv3 { + nvidia,pins = "lcd_gpio1_pv3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + lcd_gpio2_pv4 { + nvidia,pins = "lcd_gpio2_pv4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + ap_ready_pv5 { + nvidia,pins = "ap_ready_pv5"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + touch_rst_pv6 { + nvidia,pins = "touch_rst_pv6"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + touch_clk_pv7 { + nvidia,pins = "touch_clk_pv7"; + nvidia,function = "touch"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + modem_wake_ap_px0 { + nvidia,pins = "modem_wake_ap_px0"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + touch_int_px1 { + nvidia,pins = "touch_int_px1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + motion_int_px2 { + nvidia,pins = "motion_int_px2"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + als_prox_int_px3 { + nvidia,pins = "als_prox_int_px3"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + temp_alert_px4 { + nvidia,pins = "temp_alert_px4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + button_power_on_px5 { + nvidia,pins = "button_power_on_px5"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + button_vol_up_px6 { + nvidia,pins = "button_vol_up_px6"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + button_vol_down_px7 { + nvidia,pins = "button_vol_down_px7"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + button_slide_sw_py0 { + nvidia,pins = "button_slide_sw_py0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + button_home_py1 { + nvidia,pins = "button_home_py1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + lcd_te_py2 { + nvidia,pins = "lcd_te_py2"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pwr_i2c_scl_py3 { + nvidia,pins = "pwr_i2c_scl_py3"; + nvidia,function = "i2cpmu"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + pwr_i2c_sda_py4 { + nvidia,pins = "pwr_i2c_sda_py4"; + nvidia,function = "i2cpmu"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + clk_32k_out_py5 { + nvidia,pins = "clk_32k_out_py5"; + nvidia,function = "soc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pz0 { + nvidia,pins = "pz0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pz1 { + nvidia,pins = "pz1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pz2 { + nvidia,pins = "pz2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pz3 { + nvidia,pins = "pz3"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pz4 { + nvidia,pins = "pz4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pz5 { + nvidia,pins = "pz5"; + nvidia,function = "soc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap2_fs_paa0 { + nvidia,pins = "dap2_fs_paa0"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap2_sclk_paa1 { + nvidia,pins = "dap2_sclk_paa1"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap2_din_paa2 { + nvidia,pins = "dap2_din_paa2"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dap2_dout_paa3 { + nvidia,pins = "dap2_dout_paa3"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + aud_mclk_pbb0 { + nvidia,pins = "aud_mclk_pbb0"; + nvidia,function = "aud"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dvfs_pwm_pbb1 { + nvidia,pins = "dvfs_pwm_pbb1"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + dvfs_clk_pbb2 { + nvidia,pins = "dvfs_clk_pbb2"; + nvidia,function = "rsvd0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + gpio_x1_aud_pbb3 { + nvidia,pins = "gpio_x1_aud_pbb3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + gpio_x3_aud_pbb4 { + nvidia,pins = "gpio_x3_aud_pbb4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + hdmi_cec_pcc0 { + nvidia,pins = "hdmi_cec_pcc0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + hdmi_int_dp_hpd_pcc1 { + nvidia,pins = "hdmi_int_dp_hpd_pcc1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + spdif_out_pcc2 { + nvidia,pins = "spdif_out_pcc2"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + spdif_in_pcc3 { + nvidia,pins = "spdif_in_pcc3"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + usb_vbus_en0_pcc4 { + nvidia,pins = "usb_vbus_en0_pcc4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + usb_vbus_en1_pcc5 { + nvidia,pins = "usb_vbus_en1_pcc5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + dp_hpd0_pcc6 { + nvidia,pins = "dp_hpd0_pcc6"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pcc7 { + nvidia,pins = "pcc7"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + nvidia,io-hv = ; + }; + spi2_cs1_pdd0 { + nvidia,pins = "spi2_cs1_pdd0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + qspi_sck_pee0 { + nvidia,pins = "qspi_sck_pee0"; + nvidia,function = "qspi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + qspi_cs_n_pee1 { + nvidia,pins = "qspi_cs_n_pee1"; + nvidia,function = "qspi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + qspi_io0_pee2 { + nvidia,pins = "qspi_io0_pee2"; + nvidia,function = "qspi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + qspi_io1_pee3 { + nvidia,pins = "qspi_io1_pee3"; + nvidia,function = "qspi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + qspi_io2_pee4 { + nvidia,pins = "qspi_io2_pee4"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + qspi_io3_pee5 { + nvidia,pins = "qspi_io3_pee5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + core_pwr_req { + nvidia,pins = "core_pwr_req"; + nvidia,function = "core"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + cpu_pwr_req { + nvidia,pins = "cpu_pwr_req"; + nvidia,function = "cpu"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + pwr_int_n { + nvidia,pins = "pwr_int_n"; + nvidia,function = "pmi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + clk_32k_in { + nvidia,pins = "clk_32k_in"; + nvidia,function = "clk"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + jtag_rtck { + nvidia,pins = "jtag_rtck"; + nvidia,function = "jtag"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + clk_req { + nvidia,pins = "clk_req"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + shutdown { + nvidia,pins = "shutdown"; + nvidia,function = "shutdown"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + }; + }; + serial@70006000 { status = "okay"; }; -- GitLab From 757d12e5849be549076901b0d33c60d5f360269c Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 12 Apr 2016 21:07:06 +0530 Subject: [PATCH 2227/9938] dmaengine: ensure dmaengine helpers check valid callback dmaengine has various device callbacks and exposes helper functions to invoke these. These helpers should check if channel, device and callback is valid or not before invoking them. Reported-by: Jon Hunter Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 017433712833..30de0197263a 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -804,6 +804,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( sg_dma_address(&sg) = buf; sg_dma_len(&sg) = len; + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags, NULL); } @@ -812,6 +815,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction dir, unsigned long flags) { + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, dir, flags, NULL); } @@ -823,6 +829,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg( enum dma_transfer_direction dir, unsigned long flags, struct rio_dma_ext *rio_ext) { + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, dir, flags, rio_ext); } @@ -833,6 +842,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction dir, unsigned long flags) { + if (!chan || !chan->device || !chan->device->device_prep_dma_cyclic) + return NULL; + return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, period_len, dir, flags); } @@ -841,6 +853,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( struct dma_chan *chan, struct dma_interleaved_template *xt, unsigned long flags) { + if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma) + return NULL; + return chan->device->device_prep_interleaved_dma(chan, xt, flags); } @@ -848,7 +863,7 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memset( struct dma_chan *chan, dma_addr_t dest, int value, size_t len, unsigned long flags) { - if (!chan || !chan->device) + if (!chan || !chan->device || !chan->device->device_prep_dma_memset) return NULL; return chan->device->device_prep_dma_memset(chan, dest, value, @@ -861,6 +876,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_sg( struct scatterlist *src_sg, unsigned int src_nents, unsigned long flags) { + if (!chan || !chan->device || !chan->device->device_prep_dma_sg) + return NULL; + return chan->device->device_prep_dma_sg(chan, dst_sg, dst_nents, src_sg, src_nents, flags); } -- GitLab From 81b76485afb54e3efeb1de5edbef761f4ad2830e Mon Sep 17 00:00:00 2001 From: Howard Cochran Date: Thu, 10 Mar 2016 01:12:39 -0500 Subject: [PATCH 2228/9938] writeback: Fix performance regression in wb_over_bg_thresh() Commit 947e9762a8dd ("writeback: update wb_over_bg_thresh() to use wb_domain aware operations") unintentionally changed this function's meaning from "are there more dirty pages than the background writeback threshold" to "are there more dirty pages than the writeback threshold". The background writeback threshold is typically half of the writeback threshold, so this had the effect of raising the number of dirty pages required to cause a writeback worker to perform background writeout. This can cause a very severe performance regression when a BDI uses BDI_CAP_STRICTLIMIT because balance_dirty_pages() and the writeback worker can now disagree on whether writeback should be initiated. For example, in a system having 1GB of RAM, a single spinning disk, and a "pass-through" FUSE filesystem mounted over the disk, application code mmapped a 128MB file on the disk and was randomly dirtying pages in that mapping. Because FUSE uses strictlimit and has a default max_ratio of only 1%, in balance_dirty_pages, thresh is ~200, bg_thresh is ~100, and the dirty_freerun_ceiling is the average of those, ~150. So, it pauses the dirtying processes when we have 151 dirty pages and wakes up a background writeback worker. But the worker tests the wrong threshold (200 instead of 100), so it does not initiate writeback and just returns. Thus, balance_dirty_pages keeps looping, sleeping and then waking up the worker who will do nothing. It remains stuck in this state until the few dirty pages that we have finally expire and we write them back for that reason. Then the whole process repeats, resulting in near-zero throughput through the FUSE BDI. The fix is to call the parameterized variant of wb_calc_thresh, so that the worker will do writeback if the bg_thresh is exceeded which was the bahavior before the referenced commit. Fixes: 947e9762a8dd ("writeback: update wb_over_bg_thresh() to use wb_domain aware operations") Signed-off-by: Howard Cochran Acked-by: Tejun Heo Signed-off-by: Jens Axboe --- mm/page-writeback.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 999792d35ccc..bc5149d5ec38 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1910,7 +1910,8 @@ bool wb_over_bg_thresh(struct bdi_writeback *wb) if (gdtc->dirty > gdtc->bg_thresh) return true; - if (wb_stat(wb, WB_RECLAIMABLE) > __wb_calc_thresh(gdtc)) + if (wb_stat(wb, WB_RECLAIMABLE) > + wb_calc_thresh(gdtc->wb, gdtc->bg_thresh)) return true; if (mdtc) { @@ -1924,7 +1925,8 @@ bool wb_over_bg_thresh(struct bdi_writeback *wb) if (mdtc->dirty > mdtc->bg_thresh) return true; - if (wb_stat(wb, WB_RECLAIMABLE) > __wb_calc_thresh(mdtc)) + if (wb_stat(wb, WB_RECLAIMABLE) > + wb_calc_thresh(mdtc->wb, mdtc->bg_thresh)) return true; } -- GitLab From a527b38e1475211b67eb59b3fadb40689f035529 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Apr 2016 12:39:12 -0400 Subject: [PATCH 2229/9938] GFS2: fs/gfs2/glock.c: Deinline do_error, save 1856 bytes This function compiles to 522 bytes of machine code. Error paths are not very time critical. Signed-off-by: Denys Vlasenko Signed-off-by: Bob Peterson --- fs/gfs2/glock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 2897ced5fca0..3910cea1aa51 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -218,7 +218,7 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) * */ -static inline void do_error(struct gfs2_glock *gl, const int ret) +static void do_error(struct gfs2_glock *gl, const int ret) { struct gfs2_holder *gh, *tmp; -- GitLab From 169ff6db3a81fad3011e4c0b0114dbe9de1cd517 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 5 Feb 2016 15:10:02 -0800 Subject: [PATCH 2230/9938] ath10k: Document alloc_frag_desc_for_data_pkt config option. This will help anyone trying to use the ack-rssi reporting feature with the host-specified TX-rate option in 10.4 firmware. Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index feebd19ff08c..0fae0daa9215 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -2661,9 +2661,14 @@ struct wmi_resource_config_10_4 { */ __le32 iphdr_pad_config; - /* qwrap configuration + /* qwrap configuration (bits 15-0) * 1 - This is qwrap configuration * 0 - This is not qwrap + * + * Bits 31-16 is alloc_frag_desc_for_data_pkt (1 enables, 0 disables) + * In order to get ack-RSSI reporting and to specify the tx-rate for + * individual frames, this option must be enabled. This uses an extra + * 4 bytes per tx-msdu descriptor, so don't enable it unless you need it. */ __le32 qwrap_config; } __packed; -- GitLab From 9f0b7e7dea7c3cedba315d44816070fcc692c748 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 4 Apr 2016 16:19:14 -0700 Subject: [PATCH 2231/9938] ath10k: add a support of set_tsf on vdev interface 10.2.4.70.24 firmware introduces new feature to set TSF via vdev parameter, hence implement relevant function. set_tsf function can be used to shift TBTT that will help avoid its clockdrift which happens when beacons are collided. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 27 +++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 4 ++++ drivers/net/wireless/ath/ath10k/wmi.h | 2 ++ 4 files changed, 34 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b0e613bc10a5..c30a3944b612 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6796,6 +6796,32 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return 0; } +static void ath10k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 tsf) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + u32 tsf_offset, vdev_param = ar->wmi.vdev_param->set_tsf; + int ret; + + /* Workaround: + * + * Given tsf argument is entire TSF value, but firmware accepts + * only TSF offset to current TSF. + * + * get_tsf function is used to get offset value, however since + * ath10k_get_tsf is not implemented properly, it will return 0 always. + * Luckily all the caller functions to set_tsf, as of now, also rely on + * get_tsf function to get entire tsf value such get_tsf() + tsf_delta, + * final tsf offset value to firmware will be arithmetically correct. + */ + tsf_offset = tsf - ath10k_get_tsf(hw, vif); + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + vdev_param, tsf_offset); + if (ret && ret != -EOPNOTSUPP) + ath10k_warn(ar, "failed to set tsf offset: %d\n", ret); +} + static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) @@ -7252,6 +7278,7 @@ static const struct ieee80211_ops ath10k_ops = { .set_bitrate_mask = ath10k_mac_op_set_bitrate_mask, .sta_rc_update = ath10k_sta_rc_update, .get_tsf = ath10k_get_tsf, + .set_tsf = ath10k_set_tsf, .ampdu_action = ath10k_ampdu_action, .get_et_sset_count = ath10k_debug_get_et_sset_count, .get_et_stats = ath10k_debug_get_et_stats, diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 108593202052..e09337ee7c96 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3409,6 +3409,7 @@ static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; static const struct wmi_ops wmi_tlv_ops = { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index f7ec65f263a0..db3e9a4be564 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -781,6 +781,7 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; /* 10.X WMI VDEV param map */ @@ -856,6 +857,7 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { @@ -930,6 +932,7 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_10X_VDEV_PARAM_TSF_INCREMENT, }; static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { @@ -1005,6 +1008,7 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { .meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC, .rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, .bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; static struct wmi_pdev_param_map wmi_pdev_param_map = { diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0fae0daa9215..137edb4d451d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4635,6 +4635,7 @@ struct wmi_vdev_param_map { u32 meru_vc; u32 rx_decap_type; u32 bw_nss_ratemask; + u32 set_tsf; }; #define WMI_VDEV_PARAM_UNSUPPORTED 0 @@ -4891,6 +4892,7 @@ enum wmi_10x_vdev_param { WMI_10X_VDEV_PARAM_RTS_FIXED_RATE, WMI_10X_VDEV_PARAM_VHT_SGIMASK, WMI_10X_VDEV_PARAM_VHT80_RATEMASK, + WMI_10X_VDEV_PARAM_TSF_INCREMENT, }; enum wmi_10_4_vdev_param { -- GitLab From 4857dd14ec3720d25c33ea0186c55b849d891b0f Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 4 Apr 2016 16:19:15 -0700 Subject: [PATCH 2232/9938] ath10k: update 10.4 WMI vdev parameters Update 10.4 WMI vdev param to sync to current 10.4 firmware as of 2/23/2016. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 137edb4d451d..c83e1e39f8cc 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4962,6 +4962,12 @@ enum wmi_10_4_vdev_param { WMI_10_4_VDEV_PARAM_MERU_VC, WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, + WMI_10_4_VDEV_PARAM_SENSOR_AP, + WMI_10_4_VDEV_PARAM_BEACON_RATE, + WMI_10_4_VDEV_PARAM_DTIM_ENABLE_CTS, + WMI_10_4_VDEV_PARAM_STA_KICKOUT, + WMI_10_4_VDEV_PARAM_CAPABILITIES, + WMI_10_4_VDEV_PARAM_TSF_INCREMENT, }; #define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0) -- GitLab From a606c0ee9d5c12eb1a0e86837db622969956b825 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 4 Apr 2016 16:19:16 -0700 Subject: [PATCH 2233/9938] ath10k: enable set_tsf vdev command to WMI 10.4 10.4 firmware has addeded set_tsf vdev parameter, hence enable it. set_tsf function can be used to shift TBTT that will help avoid its clockdrift which happens when beacons are collided. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index db3e9a4be564..e8d9a3e5c2df 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1008,7 +1008,7 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { .meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC, .rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, .bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, - .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT, }; static struct wmi_pdev_param_map wmi_pdev_param_map = { -- GitLab From cfe9011a05a8de56f97d15a24977639fe6534e9c Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Apr 2016 12:10:58 +0530 Subject: [PATCH 2234/9938] ath10k: remove MSI range support MSI-X is never well-tested, might contain bugs and generally isn't really all that useful to maintain. Also ath10k is mainly used with shared/singly-MSI interrupt systems. Hence removing MSI range support. This change will be useful for further cleanup in copy engine lock and to add NAPI support. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 164 +++----------------------- drivers/net/wireless/ath/ath10k/pci.h | 17 ++- 2 files changed, 24 insertions(+), 157 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0b305efe6c94..cdd8a307c55b 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -33,12 +33,6 @@ #include "ce.h" #include "pci.h" -enum ath10k_pci_irq_mode { - ATH10K_PCI_IRQ_AUTO = 0, - ATH10K_PCI_IRQ_LEGACY = 1, - ATH10K_PCI_IRQ_MSI = 2, -}; - enum ath10k_pci_reset_mode { ATH10K_PCI_RESET_AUTO = 0, ATH10K_PCI_RESET_WARM_ONLY = 1, @@ -745,10 +739,7 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - if (ar_pci->num_msi_intrs > 1) - return "msi-x"; - - if (ar_pci->num_msi_intrs == 1) + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_MSI) return "msi"; return "legacy"; @@ -1502,13 +1493,8 @@ void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; tasklet_kill(&ar_pci->intr_tq); - tasklet_kill(&ar_pci->msi_fw_err); - - for (i = 0; i < CE_COUNT; i++) - tasklet_kill(&ar_pci->pipe_info[i].intr); del_timer_sync(&ar_pci->rx_post_retry); } @@ -1624,10 +1610,8 @@ static void ath10k_pci_irq_disable(struct ath10k *ar) static void ath10k_pci_irq_sync(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; - for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) - synchronize_irq(ar_pci->pdev->irq + i); + synchronize_irq(ar_pci->pdev->irq); } static void ath10k_pci_irq_enable(struct ath10k *ar) @@ -2596,65 +2580,6 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = { #endif }; -static void ath10k_pci_ce_tasklet(unsigned long ptr) -{ - struct ath10k_pci_pipe *pipe = (struct ath10k_pci_pipe *)ptr; - struct ath10k_pci *ar_pci = pipe->ar_pci; - - ath10k_ce_per_engine_service(ar_pci->ar, pipe->pipe_num); -} - -static void ath10k_msi_err_tasklet(unsigned long data) -{ - struct ath10k *ar = (struct ath10k *)data; - - if (!ath10k_pci_has_fw_crashed(ar)) { - ath10k_warn(ar, "received unsolicited fw crash interrupt\n"); - return; - } - - ath10k_pci_irq_disable(ar); - ath10k_pci_fw_crashed_clear(ar); - ath10k_pci_fw_crashed_dump(ar); -} - -/* - * Handler for a per-engine interrupt on a PARTICULAR CE. - * This is used in cases where each CE has a private MSI interrupt. - */ -static irqreturn_t ath10k_pci_per_engine_handler(int irq, void *arg) -{ - struct ath10k *ar = arg; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int ce_id = irq - ar_pci->pdev->irq - MSI_ASSIGN_CE_INITIAL; - - if (ce_id < 0 || ce_id >= ARRAY_SIZE(ar_pci->pipe_info)) { - ath10k_warn(ar, "unexpected/invalid irq %d ce_id %d\n", irq, - ce_id); - return IRQ_HANDLED; - } - - /* - * NOTE: We are able to derive ce_id from irq because we - * use a one-to-one mapping for CE's 0..5. - * CE's 6 & 7 do not use interrupts at all. - * - * This mapping must be kept in sync with the mapping - * used by firmware. - */ - tasklet_schedule(&ar_pci->pipe_info[ce_id].intr); - return IRQ_HANDLED; -} - -static irqreturn_t ath10k_pci_msi_fw_handler(int irq, void *arg) -{ - struct ath10k *ar = arg; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - - tasklet_schedule(&ar_pci->msi_fw_err); - return IRQ_HANDLED; -} - /* * Top-level interrupt handler for all PCI interrupts from a Target. * When a block of MSI interrupts is allocated, this top-level handler @@ -2672,7 +2597,7 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) return IRQ_NONE; } - if (ar_pci->num_msi_intrs == 0) { + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) { if (!ath10k_pci_irq_pending(ar)) return IRQ_NONE; @@ -2699,43 +2624,10 @@ static void ath10k_pci_tasklet(unsigned long data) ath10k_ce_per_engine_service_any(ar); /* Re-enable legacy irq that was disabled in the irq handler */ - if (ar_pci->num_msi_intrs == 0) + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) ath10k_pci_enable_legacy_irq(ar); } -static int ath10k_pci_request_irq_msix(struct ath10k *ar) -{ - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int ret, i; - - ret = request_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, - ath10k_pci_msi_fw_handler, - IRQF_SHARED, "ath10k_pci", ar); - if (ret) { - ath10k_warn(ar, "failed to request MSI-X fw irq %d: %d\n", - ar_pci->pdev->irq + MSI_ASSIGN_FW, ret); - return ret; - } - - for (i = MSI_ASSIGN_CE_INITIAL; i <= MSI_ASSIGN_CE_MAX; i++) { - ret = request_irq(ar_pci->pdev->irq + i, - ath10k_pci_per_engine_handler, - IRQF_SHARED, "ath10k_pci", ar); - if (ret) { - ath10k_warn(ar, "failed to request MSI-X ce irq %d: %d\n", - ar_pci->pdev->irq + i, ret); - - for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--) - free_irq(ar_pci->pdev->irq + i, ar); - - free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar); - return ret; - } - } - - return 0; -} - static int ath10k_pci_request_irq_msi(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -2774,41 +2666,28 @@ static int ath10k_pci_request_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - switch (ar_pci->num_msi_intrs) { - case 0: + switch (ar_pci->oper_irq_mode) { + case ATH10K_PCI_IRQ_LEGACY: return ath10k_pci_request_irq_legacy(ar); - case 1: + case ATH10K_PCI_IRQ_MSI: return ath10k_pci_request_irq_msi(ar); default: - return ath10k_pci_request_irq_msix(ar); + return -EINVAL; } } static void ath10k_pci_free_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; - /* There's at least one interrupt irregardless whether its legacy INTR - * or MSI or MSI-X */ - for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) - free_irq(ar_pci->pdev->irq + i, ar); + free_irq(ar_pci->pdev->irq, ar); } void ath10k_pci_init_irq_tasklets(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar); - tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet, - (unsigned long)ar); - - for (i = 0; i < CE_COUNT; i++) { - ar_pci->pipe_info[i].ar_pci = ar_pci; - tasklet_init(&ar_pci->pipe_info[i].intr, ath10k_pci_ce_tasklet, - (unsigned long)&ar_pci->pipe_info[i]); - } } static int ath10k_pci_init_irq(struct ath10k *ar) @@ -2822,20 +2701,9 @@ static int ath10k_pci_init_irq(struct ath10k *ar) ath10k_info(ar, "limiting irq mode to: %d\n", ath10k_pci_irq_mode); - /* Try MSI-X */ - if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) { - ar_pci->num_msi_intrs = MSI_ASSIGN_CE_MAX + 1; - ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs, - ar_pci->num_msi_intrs); - if (ret > 0) - return 0; - - /* fall-through */ - } - /* Try MSI */ if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_LEGACY) { - ar_pci->num_msi_intrs = 1; + ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_MSI; ret = pci_enable_msi(ar_pci->pdev); if (ret == 0) return 0; @@ -2851,7 +2719,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar) * This write might get lost if target has NOT written BAR. * For now, fix the race by repeating the write in below * synchronization checking. */ - ar_pci->num_msi_intrs = 0; + ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_LEGACY; ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS, PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); @@ -2869,8 +2737,8 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - switch (ar_pci->num_msi_intrs) { - case 0: + switch (ar_pci->oper_irq_mode) { + case ATH10K_PCI_IRQ_LEGACY: ath10k_pci_deinit_irq_legacy(ar); break; default: @@ -2908,7 +2776,7 @@ int ath10k_pci_wait_for_target_init(struct ath10k *ar) if (val & FW_IND_INITIALIZED) break; - if (ar_pci->num_msi_intrs == 0) + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) /* Fix potential race by repeating CORE_BASE writes */ ath10k_pci_enable_legacy_irq(ar); @@ -3186,8 +3054,8 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_sleep; } - ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", - ath10k_pci_get_irq_method(ar), ar_pci->num_msi_intrs, + ath10k_info(ar, "pci irq %s oper_irq_mode %d irq_mode %d reset_mode %d\n", + ath10k_pci_get_irq_method(ar), ar_pci->oper_irq_mode, ath10k_pci_irq_mode, ath10k_pci_reset_mode); ret = ath10k_pci_request_irq(ar); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 249c73a69800..959dc321b75e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -148,9 +148,6 @@ struct ath10k_pci_pipe { /* protects compl_free and num_send_allowed */ spinlock_t pipe_lock; - - struct ath10k_pci *ar_pci; - struct tasklet_struct intr; }; struct ath10k_pci_supp_chip { @@ -164,6 +161,12 @@ struct ath10k_bus_ops { int (*get_num_banks)(struct ath10k *ar); }; +enum ath10k_pci_irq_mode { + ATH10K_PCI_IRQ_AUTO = 0, + ATH10K_PCI_IRQ_LEGACY = 1, + ATH10K_PCI_IRQ_MSI = 2, +}; + struct ath10k_pci { struct pci_dev *pdev; struct device *dev; @@ -171,14 +174,10 @@ struct ath10k_pci { void __iomem *mem; size_t mem_len; - /* - * Number of MSI interrupts granted, 0 --> using legacy PCI line - * interrupts. - */ - int num_msi_intrs; + /* Operating interrupt mode */ + enum ath10k_pci_irq_mode oper_irq_mode; struct tasklet_struct intr_tq; - struct tasklet_struct msi_fw_err; struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; -- GitLab From 93da17b18539cb021f1075f8620ee8f6da9b42aa Mon Sep 17 00:00:00 2001 From: Andreas Ziegler Date: Tue, 12 Apr 2016 19:54:58 +0100 Subject: [PATCH 2235/9938] security: integrity: Remove select to deleted option PUBLIC_KEY_ALGO_RSA Commit d43de6c780a8 ("akcipher: Move the RSA DER encoding check to the crypto layer") removed the Kconfig option PUBLIC_KEY_ALGO_RSA, but forgot to remove a 'select' to this option in the definition of INTEGRITY_ASYMMETRIC_KEYS. Let's remove the select, as it's ineffective now. Signed-off-by: Andreas Ziegler Signed-off-by: David Howells --- security/integrity/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 979be65d22c4..da9565891738 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig @@ -35,7 +35,6 @@ config INTEGRITY_ASYMMETRIC_KEYS default n select ASYMMETRIC_KEY_TYPE select ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select PUBLIC_KEY_ALGO_RSA select CRYPTO_RSA select X509_CERTIFICATE_PARSER help -- GitLab From 898de7d0f298e53568891f0ec3547b14fe8bb5d5 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 12 Apr 2016 19:54:58 +0100 Subject: [PATCH 2236/9938] KEYS: user_update should use copy of payload made during preparsing The payload preparsing routine for user keys makes a copy of the payload provided by the caller and stashes it in the key_preparsed_payload struct for ->instantiate() or ->update() to use. However, ->update() takes another copy of this to attach to the keyring. ->update() should be using this directly and clearing the pointer in the preparse data. Signed-off-by: David Howells --- security/keys/user_defined.c | 42 ++++++++++-------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 8705d79b2c6f..66b1840b4110 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -96,45 +96,25 @@ EXPORT_SYMBOL_GPL(user_free_preparse); */ int user_update(struct key *key, struct key_preparsed_payload *prep) { - struct user_key_payload *upayload, *zap; - size_t datalen = prep->datalen; + struct user_key_payload *zap = NULL; int ret; - ret = -EINVAL; - if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - /* construct a replacement payload */ - ret = -ENOMEM; - upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); - if (!upayload) - goto error; - - upayload->datalen = datalen; - memcpy(upayload->data, prep->data, datalen); - /* check the quota and attach the new data */ - zap = upayload; - - ret = key_payload_reserve(key, datalen); - - if (ret == 0) { - /* attach the new data, displacing the old */ - if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) - zap = key->payload.data[0]; - else - zap = NULL; - rcu_assign_keypointer(key, upayload); - key->expiry = 0; - } + ret = key_payload_reserve(key, prep->datalen); + if (ret < 0) + return ret; + + /* attach the new data, displacing the old */ + key->expiry = prep->expiry; + if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) + zap = rcu_dereference_key(key); + rcu_assign_keypointer(key, prep->payload.data[0]); + prep->payload.data[0] = NULL; if (zap) kfree_rcu(zap, rcu); - -error: return ret; } - EXPORT_SYMBOL_GPL(user_update); /* -- GitLab From 13100a72f40f5748a04017e0ab3df4cf27c809ef Mon Sep 17 00:00:00 2001 From: Kirill Marinushkin Date: Tue, 12 Apr 2016 19:54:58 +0100 Subject: [PATCH 2237/9938] Security: Keys: Big keys stored encrypted Solved TODO task: big keys saved to shmem file are now stored encrypted. The encryption key is randomly generated and saved to payload[big_key_data]. Signed-off-by: Kirill Marinushkin Signed-off-by: David Howells --- security/keys/Kconfig | 4 + security/keys/big_key.c | 198 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 184 insertions(+), 18 deletions(-) diff --git a/security/keys/Kconfig b/security/keys/Kconfig index fe4d74e126a7..45828095080d 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -41,6 +41,10 @@ config BIG_KEYS bool "Large payload keys" depends on KEYS depends on TMPFS + select CRYPTO + select CRYPTO_AES + select CRYPTO_ECB + select CRYPTO_RNG help This option provides support for holding large keys within the kernel (for example Kerberos ticket caches). The data may be stored out to diff --git a/security/keys/big_key.c b/security/keys/big_key.c index c721e398893a..9e443fccad4c 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include /* * Layout of key payload words. @@ -27,6 +29,14 @@ enum { big_key_len, }; +/* + * Crypto operation with big_key data + */ +enum big_key_op { + BIG_KEY_ENC, + BIG_KEY_DEC, +}; + /* * If the data is under this limit, there's no point creating a shm file to * hold it as the permanently resident metadata for the shmem fs will be at @@ -34,6 +44,11 @@ enum { */ #define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry)) +/* + * Key size for big_key data encryption + */ +#define ENC_KEY_SIZE 16 + /* * big_key defined keys take an arbitrary string as the description and an * arbitrary blob of data as the payload @@ -49,6 +64,54 @@ struct key_type key_type_big_key = { .read = big_key_read, }; +/* + * Crypto names for big_key data encryption + */ +static const char big_key_rng_name[] = "stdrng"; +static const char big_key_alg_name[] = "ecb(aes)"; + +/* + * Crypto algorithms for big_key data encryption + */ +static struct crypto_rng *big_key_rng; +static struct crypto_blkcipher *big_key_blkcipher; + +/* + * Generate random key to encrypt big_key data + */ +static inline int big_key_gen_enckey(u8 *key) +{ + return crypto_rng_get_bytes(big_key_rng, key, ENC_KEY_SIZE); +} + +/* + * Encrypt/decrypt big_key data + */ +static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) +{ + int ret = -EINVAL; + struct scatterlist sgio; + struct blkcipher_desc desc; + + if (crypto_blkcipher_setkey(big_key_blkcipher, key, ENC_KEY_SIZE)) { + ret = -EAGAIN; + goto error; + } + + desc.flags = 0; + desc.tfm = big_key_blkcipher; + + sg_init_one(&sgio, data, datalen); + + if (op == BIG_KEY_ENC) + ret = crypto_blkcipher_encrypt(&desc, &sgio, &sgio, datalen); + else + ret = crypto_blkcipher_decrypt(&desc, &sgio, &sgio, datalen); + +error: + return ret; +} + /* * Preparse a big key */ @@ -56,6 +119,8 @@ int big_key_preparse(struct key_preparsed_payload *prep) { struct path *path = (struct path *)&prep->payload.data[big_key_path]; struct file *file; + u8 *enckey; + u8 *data = NULL; ssize_t written; size_t datalen = prep->datalen; int ret; @@ -73,16 +138,43 @@ int big_key_preparse(struct key_preparsed_payload *prep) /* Create a shmem file to store the data in. This will permit the data * to be swapped out if needed. * - * TODO: Encrypt the stored data with a temporary key. + * File content is stored encrypted with randomly generated key. */ - file = shmem_kernel_file_setup("", datalen, 0); + size_t enclen = ALIGN(datalen, crypto_blkcipher_blocksize(big_key_blkcipher)); + + /* prepare aligned data to encrypt */ + data = kmalloc(enclen, GFP_KERNEL); + if (!data) + return -ENOMEM; + + memcpy(data, prep->data, datalen); + memset(data + datalen, 0x00, enclen - datalen); + + /* generate random key */ + enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL); + if (!enckey) { + ret = -ENOMEM; + goto error; + } + + ret = big_key_gen_enckey(enckey); + if (ret) + goto err_enckey; + + /* encrypt aligned data */ + ret = big_key_crypt(BIG_KEY_ENC, data, enclen, enckey); + if (ret) + goto err_enckey; + + /* save aligned data to file */ + file = shmem_kernel_file_setup("", enclen, 0); if (IS_ERR(file)) { ret = PTR_ERR(file); - goto error; + goto err_enckey; } - written = kernel_write(file, prep->data, prep->datalen, 0); - if (written != datalen) { + written = kernel_write(file, data, enclen, 0); + if (written != enclen) { ret = written; if (written >= 0) ret = -ENOMEM; @@ -92,12 +184,15 @@ int big_key_preparse(struct key_preparsed_payload *prep) /* Pin the mount and dentry to the key so that we can open it again * later */ + prep->payload.data[big_key_data] = enckey; *path = file->f_path; path_get(path); fput(file); + kfree(data); } else { /* Just store the data in a buffer */ void *data = kmalloc(datalen, GFP_KERNEL); + if (!data) return -ENOMEM; @@ -108,7 +203,10 @@ int big_key_preparse(struct key_preparsed_payload *prep) err_fput: fput(file); +err_enckey: + kfree(enckey); error: + kfree(data); return ret; } @@ -119,10 +217,10 @@ void big_key_free_preparse(struct key_preparsed_payload *prep) { if (prep->datalen > BIG_KEY_FILE_THRESHOLD) { struct path *path = (struct path *)&prep->payload.data[big_key_path]; + path_put(path); - } else { - kfree(prep->payload.data[big_key_data]); } + kfree(prep->payload.data[big_key_data]); } /* @@ -147,15 +245,15 @@ void big_key_destroy(struct key *key) { size_t datalen = (size_t)key->payload.data[big_key_len]; - if (datalen) { + if (datalen > BIG_KEY_FILE_THRESHOLD) { struct path *path = (struct path *)&key->payload.data[big_key_path]; + path_put(path); path->mnt = NULL; path->dentry = NULL; - } else { - kfree(key->payload.data[big_key_data]); - key->payload.data[big_key_data] = NULL; } + kfree(key->payload.data[big_key_data]); + key->payload.data[big_key_data] = NULL; } /* @@ -188,17 +286,41 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) if (datalen > BIG_KEY_FILE_THRESHOLD) { struct path *path = (struct path *)&key->payload.data[big_key_path]; struct file *file; - loff_t pos; + u8 *data; + u8 *enckey = (u8 *)key->payload.data[big_key_data]; + size_t enclen = ALIGN(datalen, crypto_blkcipher_blocksize(big_key_blkcipher)); + + data = kmalloc(enclen, GFP_KERNEL); + if (!data) + return -ENOMEM; file = dentry_open(path, O_RDONLY, current_cred()); - if (IS_ERR(file)) - return PTR_ERR(file); + if (IS_ERR(file)) { + ret = PTR_ERR(file); + goto error; + } - pos = 0; - ret = vfs_read(file, buffer, datalen, &pos); - fput(file); - if (ret >= 0 && ret != datalen) + /* read file to kernel and decrypt */ + ret = kernel_read(file, 0, data, enclen); + if (ret >= 0 && ret != enclen) { ret = -EIO; + goto err_fput; + } + + ret = big_key_crypt(BIG_KEY_DEC, data, enclen, enckey); + if (ret) + goto err_fput; + + ret = datalen; + + /* copy decrypted data to user */ + if (copy_to_user(buffer, data, datalen) != 0) + ret = -EFAULT; + +err_fput: + fput(file); +error: + kfree(data); } else { ret = datalen; if (copy_to_user(buffer, key->payload.data[big_key_data], @@ -209,8 +331,48 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) return ret; } +/* + * Register key type + */ static int __init big_key_init(void) { return register_key_type(&key_type_big_key); } + +/* + * Initialize big_key crypto and RNG algorithms + */ +static int __init big_key_crypto_init(void) +{ + int ret = -EINVAL; + + /* init RNG */ + big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0); + if (IS_ERR(big_key_rng)) { + big_key_rng = NULL; + return -EFAULT; + } + + /* seed RNG */ + ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng)); + if (ret) + goto error; + + /* init block cipher */ + big_key_blkcipher = crypto_alloc_blkcipher(big_key_alg_name, 0, 0); + if (IS_ERR(big_key_blkcipher)) { + big_key_blkcipher = NULL; + ret = -EFAULT; + goto error; + } + + return 0; + +error: + crypto_free_rng(big_key_rng); + big_key_rng = NULL; + return ret; +} + device_initcall(big_key_init); +late_initcall(big_key_crypto_init); -- GitLab From ddbb41148724367394d0880c516bfaeed127b52e Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Tue, 12 Apr 2016 19:54:58 +0100 Subject: [PATCH 2238/9938] KEYS: Add KEYCTL_DH_COMPUTE command This adds userspace access to Diffie-Hellman computations through a new keyctl() syscall command to calculate shared secrets or public keys using input parameters stored in the keyring. Input key ids are provided in a struct due to the current 5-arg limit for the keyctl syscall. Only user keys are supported in order to avoid exposing the content of logon or encrypted keys. The output is written to the provided buffer, based on the assumption that the values are only needed in userspace. Future support for other types of key derivation would involve a new command, like KEYCTL_ECDH_COMPUTE. Once Diffie-Hellman support is included in the crypto API, this code can be converted to use the crypto API to take advantage of possible hardware acceleration and reduce redundant code. Signed-off-by: Mat Martineau Signed-off-by: David Howells --- Documentation/security/keys.txt | 30 ++++++ include/uapi/linux/keyctl.h | 10 ++ security/keys/Kconfig | 11 +++ security/keys/Makefile | 1 + security/keys/compat.c | 4 + security/keys/dh.c | 160 ++++++++++++++++++++++++++++++++ security/keys/internal.h | 12 +++ security/keys/keyctl.c | 5 + 8 files changed, 233 insertions(+) create mode 100644 security/keys/dh.c diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 8c183873b2b7..a2f70cf6763a 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt @@ -823,6 +823,36 @@ The keyctl syscall functions are: A process must have search permission on the key for this function to be successful. + (*) Compute a Diffie-Hellman shared secret or public key + + long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params, + char *buffer, size_t buflen); + + The params struct contains serial numbers for three keys: + + - The prime, p, known to both parties + - The local private key + - The base integer, which is either a shared generator or the + remote public key + + The value computed is: + + result = base ^ private (mod prime) + + If the base is the shared generator, the result is the local + public key. If the base is the remote public key, the result is + the shared secret. + + The buffer length must be at least the length of the prime, or zero. + + If the buffer length is nonzero, the length of the result is + returned when it is successfully calculated and copied in to the + buffer. When the buffer length is zero, the minimum required + buffer length is returned. + + This function will return error EOPNOTSUPP if the key type is not + supported, error ENOKEY if the key could not be found, or error + EACCES if the key is not readable by the caller. =============== KERNEL SERVICES diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h index 840cb990abe2..86eddd6241f3 100644 --- a/include/uapi/linux/keyctl.h +++ b/include/uapi/linux/keyctl.h @@ -12,6 +12,8 @@ #ifndef _LINUX_KEYCTL_H #define _LINUX_KEYCTL_H +#include + /* special process keyring shortcut IDs */ #define KEY_SPEC_THREAD_KEYRING -1 /* - key ID for thread-specific keyring */ #define KEY_SPEC_PROCESS_KEYRING -2 /* - key ID for process-specific keyring */ @@ -57,5 +59,13 @@ #define KEYCTL_INSTANTIATE_IOV 20 /* instantiate a partially constructed key */ #define KEYCTL_INVALIDATE 21 /* invalidate a key */ #define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */ +#define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */ + +/* keyctl structures */ +struct keyctl_dh_params { + __s32 private; + __s32 prime; + __s32 base; +}; #endif /* _LINUX_KEYCTL_H */ diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 45828095080d..f826e8739023 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -85,3 +85,14 @@ config ENCRYPTED_KEYS Userspace only ever sees/stores encrypted blobs. If you are unsure as to whether this is required, answer N. + +config KEY_DH_OPERATIONS + bool "Diffie-Hellman operations on retained keys" + depends on KEYS + select MPILIB + help + This option provides support for calculating Diffie-Hellman + public keys and shared secrets using values stored as keys + in the kernel. + + If you are unsure as to whether this is required, answer N. diff --git a/security/keys/Makefile b/security/keys/Makefile index dfb3a7bededf..1fd4a16e6daf 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o +obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o # # Key types diff --git a/security/keys/compat.c b/security/keys/compat.c index 25430a3aa7f7..c8783b3b628c 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -132,6 +132,10 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option, case KEYCTL_GET_PERSISTENT: return keyctl_get_persistent(arg2, arg3); + case KEYCTL_DH_COMPUTE: + return keyctl_dh_compute(compat_ptr(arg2), compat_ptr(arg3), + arg4); + default: return -EOPNOTSUPP; } diff --git a/security/keys/dh.c b/security/keys/dh.c new file mode 100644 index 000000000000..880505a4b9f1 --- /dev/null +++ b/security/keys/dh.c @@ -0,0 +1,160 @@ +/* Crypto operations using stored keys + * + * Copyright (c) 2016, Intel Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include "internal.h" + +/* + * Public key or shared secret generation function [RFC2631 sec 2.1.1] + * + * ya = g^xa mod p; + * or + * ZZ = yb^xa mod p; + * + * where xa is the local private key, ya is the local public key, g is + * the generator, p is the prime, yb is the remote public key, and ZZ + * is the shared secret. + * + * Both are the same calculation, so g or yb are the "base" and ya or + * ZZ are the "result". + */ +static int do_dh(MPI result, MPI base, MPI xa, MPI p) +{ + return mpi_powm(result, base, xa, p); +} + +static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) +{ + struct key *key; + key_ref_t key_ref; + long status; + ssize_t ret; + + key_ref = lookup_user_key(keyid, 0, KEY_NEED_READ); + if (IS_ERR(key_ref)) { + ret = -ENOKEY; + goto error; + } + + key = key_ref_to_ptr(key_ref); + + ret = -EOPNOTSUPP; + if (key->type == &key_type_user) { + down_read(&key->sem); + status = key_validate(key); + if (status == 0) { + const struct user_key_payload *payload; + + payload = user_key_payload(key); + + if (maxlen == 0) { + *mpi = NULL; + ret = payload->datalen; + } else if (payload->datalen <= maxlen) { + *mpi = mpi_read_raw_data(payload->data, + payload->datalen); + if (*mpi) + ret = payload->datalen; + } else { + ret = -EINVAL; + } + } + up_read(&key->sem); + } + + key_put(key); +error: + return ret; +} + +long keyctl_dh_compute(struct keyctl_dh_params __user *params, + char __user *buffer, size_t buflen) +{ + long ret; + MPI base, private, prime, result; + unsigned nbytes; + struct keyctl_dh_params pcopy; + uint8_t *kbuf; + ssize_t keylen; + size_t resultlen; + + if (!params || (!buffer && buflen)) { + ret = -EINVAL; + goto out; + } + if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { + ret = -EFAULT; + goto out; + } + + keylen = mpi_from_key(pcopy.prime, buflen, &prime); + if (keylen < 0 || !prime) { + /* buflen == 0 may be used to query the required buffer size, + * which is the prime key length. + */ + ret = keylen; + goto out; + } + + /* The result is never longer than the prime */ + resultlen = keylen; + + keylen = mpi_from_key(pcopy.base, SIZE_MAX, &base); + if (keylen < 0 || !base) { + ret = keylen; + goto error1; + } + + keylen = mpi_from_key(pcopy.private, SIZE_MAX, &private); + if (keylen < 0 || !private) { + ret = keylen; + goto error2; + } + + result = mpi_alloc(0); + if (!result) { + ret = -ENOMEM; + goto error3; + } + + kbuf = kmalloc(resultlen, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto error4; + } + + ret = do_dh(result, base, private, prime); + if (ret) + goto error5; + + ret = mpi_read_buffer(result, kbuf, resultlen, &nbytes, NULL); + if (ret != 0) + goto error5; + + ret = nbytes; + if (copy_to_user(buffer, kbuf, nbytes) != 0) + ret = -EFAULT; + +error5: + kfree(kbuf); +error4: + mpi_free(result); +error3: + mpi_free(private); +error2: + mpi_free(base); +error1: + mpi_free(prime); +out: + return ret; +} diff --git a/security/keys/internal.h b/security/keys/internal.h index 5105c2c2da75..8ec7a528365d 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -15,6 +15,7 @@ #include #include #include +#include struct iovec; @@ -257,6 +258,17 @@ static inline long keyctl_get_persistent(uid_t uid, key_serial_t destring) } #endif +#ifdef CONFIG_KEY_DH_OPERATIONS +extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *, + size_t); +#else +static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params, + char __user *buffer, size_t buflen) +{ + return -EOPNOTSUPP; +} +#endif + /* * Debugging key validation */ diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index ed73c6c1c326..3b135a0af344 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1686,6 +1686,11 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, case KEYCTL_GET_PERSISTENT: return keyctl_get_persistent((uid_t)arg2, (key_serial_t)arg3); + case KEYCTL_DH_COMPUTE: + return keyctl_dh_compute((struct keyctl_dh_params __user *) arg2, + (char __user *) arg3, + (size_t) arg4); + default: return -EOPNOTSUPP; } -- GitLab From 37e58237a16b94fcd2c2d1b7e9c6e1ca661c231b Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Tue, 22 Mar 2016 00:24:44 -0700 Subject: [PATCH 2239/9938] block: add offset in blk_add_request_payload() We could kmalloc() the payload, so need the offset in page. Signed-off-by: Ming Lin Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-core.c | 5 +++-- drivers/block/skd_main.c | 2 +- drivers/scsi/sd.c | 2 +- include/linux/blkdev.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index b60537b2c35b..c50227796a26 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1523,6 +1523,7 @@ EXPORT_SYMBOL(blk_put_request); * blk_add_request_payload - add a payload to a request * @rq: request to update * @page: page backing the payload + * @offset: offset in page * @len: length of the payload. * * This allows to later add a payload to an already submitted request by @@ -1533,12 +1534,12 @@ EXPORT_SYMBOL(blk_put_request); * discard requests should ever use it. */ void blk_add_request_payload(struct request *rq, struct page *page, - unsigned int len) + int offset, unsigned int len) { struct bio *bio = rq->bio; bio->bi_io_vec->bv_page = page; - bio->bi_io_vec->bv_offset = 0; + bio->bi_io_vec->bv_offset = offset; bio->bi_io_vec->bv_len = len; bio->bi_iter.bi_size = len; diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 586f9168ffa4..9a9ec212fab8 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -562,7 +562,7 @@ skd_prep_discard_cdb(struct skd_scsi_request *scsi_req, put_unaligned_be32(count, &buf[16]); req = skreq->req; - blk_add_request_payload(req, page, len); + blk_add_request_payload(req, page, 0, len); } static void skd_request_fn_not_online(struct request_queue *q); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index f52b74cf8d1e..69b0a4a7a15f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -779,7 +779,7 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd) * discarded on disk. This allows us to report completion on the full * amount of blocks described by the request. */ - blk_add_request_payload(rq, page, len); + blk_add_request_payload(rq, page, 0, len); ret = scsi_init_io(cmd); rq->__data_len = nr_bytes; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 669e419d6234..bbaa76757018 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -779,7 +779,7 @@ extern struct request *blk_make_request(struct request_queue *, struct bio *, extern void blk_rq_set_block_pc(struct request *); extern void blk_requeue_request(struct request_queue *, struct request *); extern void blk_add_request_payload(struct request *rq, struct page *page, - unsigned int len); + int offset, unsigned int len); extern int blk_lld_busy(struct request_queue *q); extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src, struct bio_set *bs, gfp_t gfp_mask, -- GitLab From e0489487ec9cd79ee1fa0dc5d3789c08b0e51a2c Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Thu, 10 Mar 2016 13:58:46 +0200 Subject: [PATCH 2240/9938] blk-mq: Export tagset iter function Its useful to iterate on all the active tags in cases where we will need to fail all the queues IO. Signed-off-by: Sagi Grimberg [hch: carefully check for valid tagsets] Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- block/blk-mq-tag.c | 12 ++++++++++++ include/linux/blk-mq.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index abdbb47405cb..2fd04286f103 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -474,6 +474,18 @@ void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, } EXPORT_SYMBOL(blk_mq_all_tag_busy_iter); +void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, + busy_tag_iter_fn *fn, void *priv) +{ + int i; + + for (i = 0; i < tagset->nr_hw_queues; i++) { + if (tagset->tags && tagset->tags[i]) + blk_mq_all_tag_busy_iter(tagset->tags[i], fn, priv); + } +} +EXPORT_SYMBOL(blk_mq_tagset_busy_iter); + void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn, void *priv) { diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 9ac9799b702b..c808fec1ce44 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -240,6 +240,8 @@ void blk_mq_run_hw_queues(struct request_queue *q, bool async); void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs); void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, void *priv); +void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, + busy_tag_iter_fn *fn, void *priv); void blk_mq_freeze_queue(struct request_queue *q); void blk_mq_unfreeze_queue(struct request_queue *q); void blk_mq_freeze_queue_start(struct request_queue *q); -- GitLab From 788e15abbb9408c9399d7e3445ac9afb3b2fd7d6 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Fri, 8 Apr 2016 16:09:10 -0600 Subject: [PATCH 2241/9938] NVMe: Always use MSI/MSI-x interrupts Multiple users have reported device initialization failure due the driver not receiving legacy PCI interrupts. This is not unique to any particular controller, but has been observed on multiple platforms. There have been no issues reported or observed when with message signaled interrupts, so this patch attempts to use MSI-x during initialization, falling back to MSI. If that fails, legacy would become the default. The setup_io_queues error handling had to change as a result: the admin queue's msix_entry used to be initialized to the legacy IRQ. The case where nr_io_queues is 0 would fail request_irq when setting up the admin queue's interrupt since re-enabling MSI-x fails with 0 vectors, leaving the admin queue's msix_entry invalid. Instead, return success immediately. Reported-by: Tim Muhlemmer Reported-by: Jon Derrick Signed-off-by: Keith Busch Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 24ccda303efb..94d45b00d40f 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1478,8 +1478,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) if (result > 0) { dev_err(dev->ctrl.device, "Could not set queue count (%d)\n", result); - nr_io_queues = 0; - result = 0; + return 0; } if (dev->cmb && NVME_CMB_SQS(dev->cmbsz)) { @@ -1513,7 +1512,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) * If we enable msix early due to not intx, disable it again before * setting up the full range we need. */ - if (!pdev->irq) + if (pdev->msi_enabled) + pci_disable_msi(pdev); + else if (pdev->msix_enabled) pci_disable_msix(pdev); for (i = 0; i < nr_io_queues; i++) @@ -1696,7 +1697,6 @@ static int nvme_pci_enable(struct nvme_dev *dev) if (pci_enable_device_mem(pdev)) return result; - dev->entry[0].vector = pdev->irq; pci_set_master(pdev); if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) && @@ -1709,13 +1709,18 @@ static int nvme_pci_enable(struct nvme_dev *dev) } /* - * Some devices don't advertse INTx interrupts, pre-enable a single - * MSIX vec for setup. We'll adjust this later. + * Some devices and/or platforms don't advertise or work with INTx + * interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll + * adjust this later. */ - if (!pdev->irq) { - result = pci_enable_msix(pdev, dev->entry, 1); - if (result < 0) - goto disable; + if (pci_enable_msix(pdev, dev->entry, 1)) { + pci_enable_msi(pdev); + dev->entry[0].vector = pdev->irq; + } + + if (!dev->entry[0].vector) { + result = -ENODEV; + goto disable; } cap = lo_hi_readq(dev->bar + NVME_REG_CAP); -- GitLab From 2e39e0f608c130411f52c9fe5648dbcda5e28528 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Tue, 5 Apr 2016 10:32:04 -0700 Subject: [PATCH 2242/9938] nvme: add missing lock nesting notation When unloading driver, nvme_disable_io_queues() calls nvme_delete_queue() that sends nvme_admin_delete_cq command to admin sq. So when the command completed, the lock acquired by nvme_irq() actually belongs to admin queue. While the lock that nvme_del_cq_end() trying to acquire belongs to io queue. So it will not deadlock. This patch adds lock nesting notation to fix following report. [ 109.840952] ============================================= [ 109.846379] [ INFO: possible recursive locking detected ] [ 109.851806] 4.5.0+ #180 Tainted: G E [ 109.856533] --------------------------------------------- [ 109.861958] swapper/0/0 is trying to acquire lock: [ 109.866771] (&(&nvmeq->q_lock)->rlock){-.....}, at: [] nvme_del_cq_end+0x26/0x70 [nvme] [ 109.876535] [ 109.876535] but task is already holding lock: [ 109.882398] (&(&nvmeq->q_lock)->rlock){-.....}, at: [] nvme_irq+0x1b/0x50 [nvme] [ 109.891547] [ 109.891547] other info that might help us debug this: [ 109.898107] Possible unsafe locking scenario: [ 109.898107] [ 109.904056] CPU0 [ 109.906515] ---- [ 109.908974] lock(&(&nvmeq->q_lock)->rlock); [ 109.913381] lock(&(&nvmeq->q_lock)->rlock); [ 109.917787] [ 109.917787] *** DEADLOCK *** [ 109.917787] [ 109.923738] May be due to missing lock nesting notation [ 109.923738] [ 109.930558] 1 lock held by swapper/0/0: [ 109.934413] #0: (&(&nvmeq->q_lock)->rlock){-.....}, at: [] nvme_irq+0x1b/0x50 [nvme] [ 109.944010] [ 109.944010] stack backtrace: [ 109.948389] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G E 4.5.0+ #180 [ 109.955734] Hardware name: Dell Inc. OptiPlex 7010/0YXT71, BIOS A15 08/12/2013 [ 109.962989] 0000000000000000 ffff88011e203c38 ffffffff81383d9c ffffffff81c13540 [ 109.970478] ffffffff826711d0 ffff88011e203ce8 ffffffff810bb429 0000000000000046 [ 109.977964] 0000000000000046 0000000000000000 0000000000b2e597 ffffffff81f4cb00 [ 109.985453] Call Trace: [ 109.987911] [] dump_stack+0x85/0xc9 [ 109.993711] [] __lock_acquire+0x19b9/0x1c60 [ 109.999575] [] ? trace_hardirqs_off+0xd/0x10 [ 110.005524] [] ? complete+0x3d/0x50 [ 110.010688] [] lock_acquire+0x90/0xf0 [ 110.016029] [] ? nvme_del_cq_end+0x26/0x70 [nvme] [ 110.022418] [] _raw_spin_lock_irqsave+0x4b/0x60 [ 110.028632] [] ? nvme_del_cq_end+0x26/0x70 [nvme] [ 110.035019] [] nvme_del_cq_end+0x26/0x70 [nvme] [ 110.041232] [] blk_mq_end_request+0x35/0x60 [ 110.047095] [] nvme_complete_rq+0x68/0x190 [nvme] [ 110.053481] [] __blk_mq_complete_request+0x8f/0x130 [ 110.060043] [] blk_mq_complete_request+0x31/0x40 [ 110.066343] [] __nvme_process_cq+0x83/0x240 [nvme] [ 110.072818] [] nvme_irq+0x25/0x50 [nvme] [ 110.078419] [] handle_irq_event_percpu+0x36/0x110 [ 110.084804] [] handle_irq_event+0x37/0x60 [ 110.090491] [] handle_edge_irq+0x93/0x150 [ 110.096180] [] handle_irq+0xa6/0x130 [ 110.101431] [] do_IRQ+0x5e/0x120 [ 110.106333] [] common_interrupt+0x8c/0x8c Reviewed-by: Johannes Thumshirn Signed-off-by: Ming Lin Reviewed-by: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 94d45b00d40f..154194e33c31 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1592,7 +1592,13 @@ static void nvme_del_cq_end(struct request *req, int error) if (!error) { unsigned long flags; - spin_lock_irqsave(&nvmeq->q_lock, flags); + /* + * We might be called with the AQ q_lock held + * and the I/O queue q_lock should always + * nest inside the AQ one. + */ + spin_lock_irqsave_nested(&nvmeq->q_lock, flags, + SINGLE_DEPTH_NESTING); nvme_process_cq(nvmeq); spin_unlock_irqrestore(&nvmeq->q_lock, flags); } -- GitLab From 58b45602751ddf16e57170656670aa5a8f78eeca Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Tue, 22 Mar 2016 00:24:43 -0700 Subject: [PATCH 2243/9938] nvme: add helper nvme_map_len() The helper returns the number of bytes that need to be mapped using PRPs/SGL entries. Signed-off-by: Ming Lin Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/nvme.h | 8 ++++++++ drivers/nvme/host/pci.c | 13 +++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index f846da4eb338..6376cd71cc9f 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -173,6 +173,14 @@ static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector) return (sector >> (ns->lba_shift - 9)); } +static inline unsigned nvme_map_len(struct request *rq) +{ + if (rq->cmd_flags & REQ_DISCARD) + return sizeof(struct nvme_dsm_range); + else + return blk_rq_bytes(rq); +} + static inline void nvme_setup_flush(struct nvme_ns *ns, struct nvme_command *cmnd) { diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 154194e33c31..d23ede73537d 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -334,16 +334,11 @@ static __le64 **iod_list(struct request *req) return (__le64 **)(iod->sg + req->nr_phys_segments); } -static int nvme_init_iod(struct request *rq, struct nvme_dev *dev) +static int nvme_init_iod(struct request *rq, unsigned size, + struct nvme_dev *dev) { struct nvme_iod *iod = blk_mq_rq_to_pdu(rq); int nseg = rq->nr_phys_segments; - unsigned size; - - if (rq->cmd_flags & REQ_DISCARD) - size = sizeof(struct nvme_dsm_range); - else - size = blk_rq_bytes(rq); if (nseg > NVME_INT_PAGES || size > NVME_INT_BYTES(dev)) { iod->sg = kmalloc(nvme_iod_alloc_size(dev, size, nseg), GFP_ATOMIC); @@ -637,6 +632,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, struct nvme_dev *dev = nvmeq->dev; struct request *req = bd->rq; struct nvme_command cmnd; + unsigned map_len; int ret = BLK_MQ_RQ_QUEUE_OK; /* @@ -652,7 +648,8 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, } } - ret = nvme_init_iod(req, dev); + map_len = nvme_map_len(req); + ret = nvme_init_iod(req, map_len, dev); if (ret) return ret; -- GitLab From 03b5929ebb20457e2fd13a701954efa2b2fb7ded Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Tue, 22 Mar 2016 00:24:45 -0700 Subject: [PATCH 2244/9938] nvme: rewrite discard support This rewrites nvme_setup_discard() with blk_add_request_payload(). It allocates only the necessary amount(16 bytes) for the payload. Signed-off-by: Ming Lin Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 68 +++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index d23ede73537d..0bf7f61a0a89 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -363,6 +363,9 @@ static void nvme_free_iod(struct nvme_dev *dev, struct request *req) __le64 **list = iod_list(req); dma_addr_t prp_dma = iod->first_dma; + if (req->cmd_flags & REQ_DISCARD) + kfree(req->completion_data); + if (iod->npages == 0) dma_pool_free(dev->prp_small_pool, list[0], prp_dma); for (i = 0; i < iod->npages; i++) { @@ -524,7 +527,7 @@ static bool nvme_setup_prps(struct nvme_dev *dev, struct request *req, } static int nvme_map_data(struct nvme_dev *dev, struct request *req, - struct nvme_command *cmnd) + unsigned size, struct nvme_command *cmnd) { struct nvme_iod *iod = blk_mq_rq_to_pdu(req); struct request_queue *q = req->q; @@ -541,7 +544,7 @@ static int nvme_map_data(struct nvme_dev *dev, struct request *req, if (!dma_map_sg(dev->dev, iod->sg, iod->nents, dma_dir)) goto out; - if (!nvme_setup_prps(dev, req, blk_rq_bytes(req))) + if (!nvme_setup_prps(dev, req, size)) goto out_unmap; ret = BLK_MQ_RQ_QUEUE_ERROR; @@ -590,35 +593,41 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req) nvme_free_iod(dev, req); } -/* - * We reuse the small pool to allocate the 16-byte range here as it is not - * worth having a special pool for these or additional cases to handle freeing - * the iod. - */ -static int nvme_setup_discard(struct nvme_queue *nvmeq, struct nvme_ns *ns, - struct request *req, struct nvme_command *cmnd) +static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req, + struct nvme_command *cmnd) { - struct nvme_iod *iod = blk_mq_rq_to_pdu(req); struct nvme_dsm_range *range; + struct page *page; + int offset; + unsigned int nr_bytes = blk_rq_bytes(req); - range = dma_pool_alloc(nvmeq->dev->prp_small_pool, GFP_ATOMIC, - &iod->first_dma); + range = kmalloc(sizeof(*range), GFP_ATOMIC); if (!range) return BLK_MQ_RQ_QUEUE_BUSY; - iod_list(req)[0] = (__le64 *)range; - iod->npages = 0; range->cattr = cpu_to_le32(0); - range->nlb = cpu_to_le32(blk_rq_bytes(req) >> ns->lba_shift); + range->nlb = cpu_to_le32(nr_bytes >> ns->lba_shift); range->slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req))); memset(cmnd, 0, sizeof(*cmnd)); cmnd->dsm.opcode = nvme_cmd_dsm; cmnd->dsm.nsid = cpu_to_le32(ns->ns_id); - cmnd->dsm.prp1 = cpu_to_le64(iod->first_dma); cmnd->dsm.nr = 0; cmnd->dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD); - return BLK_MQ_RQ_QUEUE_OK; + + req->completion_data = range; + page = virt_to_page(range); + offset = offset_in_page(range); + blk_add_request_payload(req, page, offset, sizeof(*range)); + + /* + * we set __data_len back to the size of the area to be discarded + * on disk. This allows us to report completion on the full amount + * of blocks described by the request. + */ + req->__data_len = nr_bytes; + + return 0; } /* @@ -653,19 +662,20 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, if (ret) return ret; - if (req->cmd_flags & REQ_DISCARD) { - ret = nvme_setup_discard(nvmeq, ns, req, &cmnd); - } else { - if (req->cmd_type == REQ_TYPE_DRV_PRIV) - memcpy(&cmnd, req->cmd, sizeof(cmnd)); - else if (req->cmd_flags & REQ_FLUSH) - nvme_setup_flush(ns, &cmnd); - else - nvme_setup_rw(ns, req, &cmnd); + if (req->cmd_type == REQ_TYPE_DRV_PRIV) + memcpy(&cmnd, req->cmd, sizeof(cmnd)); + else if (req->cmd_flags & REQ_FLUSH) + nvme_setup_flush(ns, &cmnd); + else if (req->cmd_flags & REQ_DISCARD) + ret = nvme_setup_discard(ns, req, &cmnd); + else + nvme_setup_rw(ns, req, &cmnd); - if (req->nr_phys_segments) - ret = nvme_map_data(dev, req, &cmnd); - } + if (ret) + goto out; + + if (req->nr_phys_segments) + ret = nvme_map_data(dev, req, map_len, &cmnd); if (ret) goto out; -- GitLab From 8093f7ca73c1633e458c16a74b51bcc3c94564c4 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Tue, 12 Apr 2016 13:10:14 -0600 Subject: [PATCH 2245/9938] nvme: add helper nvme_setup_cmd() This moves nvme_setup_{flush,discard,rw} calls into a common nvme_setup_cmd() helper. So we can eventually hide all the command setup in the core module and don't even need to update the fabrics drivers for any specific command type. Signed-off-by: Ming Lin Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 105 +++++++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 53 +------------------- drivers/nvme/host/pci.c | 47 +----------------- 3 files changed, 108 insertions(+), 97 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 643f457131c2..6631f38aebca 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -138,6 +138,111 @@ struct request *nvme_alloc_request(struct request_queue *q, } EXPORT_SYMBOL_GPL(nvme_alloc_request); +static inline void nvme_setup_flush(struct nvme_ns *ns, + struct nvme_command *cmnd) +{ + memset(cmnd, 0, sizeof(*cmnd)); + cmnd->common.opcode = nvme_cmd_flush; + cmnd->common.nsid = cpu_to_le32(ns->ns_id); +} + +static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req, + struct nvme_command *cmnd) +{ + struct nvme_dsm_range *range; + struct page *page; + int offset; + unsigned int nr_bytes = blk_rq_bytes(req); + + range = kmalloc(sizeof(*range), GFP_ATOMIC); + if (!range) + return BLK_MQ_RQ_QUEUE_BUSY; + + range->cattr = cpu_to_le32(0); + range->nlb = cpu_to_le32(nr_bytes >> ns->lba_shift); + range->slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req))); + + memset(cmnd, 0, sizeof(*cmnd)); + cmnd->dsm.opcode = nvme_cmd_dsm; + cmnd->dsm.nsid = cpu_to_le32(ns->ns_id); + cmnd->dsm.nr = 0; + cmnd->dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD); + + req->completion_data = range; + page = virt_to_page(range); + offset = offset_in_page(range); + blk_add_request_payload(req, page, offset, sizeof(*range)); + + /* + * we set __data_len back to the size of the area to be discarded + * on disk. This allows us to report completion on the full amount + * of blocks described by the request. + */ + req->__data_len = nr_bytes; + + return 0; +} + +static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req, + struct nvme_command *cmnd) +{ + u16 control = 0; + u32 dsmgmt = 0; + + if (req->cmd_flags & REQ_FUA) + control |= NVME_RW_FUA; + if (req->cmd_flags & (REQ_FAILFAST_DEV | REQ_RAHEAD)) + control |= NVME_RW_LR; + + if (req->cmd_flags & REQ_RAHEAD) + dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH; + + memset(cmnd, 0, sizeof(*cmnd)); + cmnd->rw.opcode = (rq_data_dir(req) ? nvme_cmd_write : nvme_cmd_read); + cmnd->rw.command_id = req->tag; + cmnd->rw.nsid = cpu_to_le32(ns->ns_id); + cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req))); + cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1); + + if (ns->ms) { + switch (ns->pi_type) { + case NVME_NS_DPS_PI_TYPE3: + control |= NVME_RW_PRINFO_PRCHK_GUARD; + break; + case NVME_NS_DPS_PI_TYPE1: + case NVME_NS_DPS_PI_TYPE2: + control |= NVME_RW_PRINFO_PRCHK_GUARD | + NVME_RW_PRINFO_PRCHK_REF; + cmnd->rw.reftag = cpu_to_le32( + nvme_block_nr(ns, blk_rq_pos(req))); + break; + } + if (!blk_integrity_rq(req)) + control |= NVME_RW_PRINFO_PRACT; + } + + cmnd->rw.control = cpu_to_le16(control); + cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); +} + +int nvme_setup_cmd(struct nvme_ns *ns, struct request *req, + struct nvme_command *cmd) +{ + int ret = 0; + + if (req->cmd_type == REQ_TYPE_DRV_PRIV) + memcpy(cmd, req->cmd, sizeof(*cmd)); + else if (req->cmd_flags & REQ_FLUSH) + nvme_setup_flush(ns, cmd); + else if (req->cmd_flags & REQ_DISCARD) + ret = nvme_setup_discard(ns, req, cmd); + else + nvme_setup_rw(ns, req, cmd); + + return ret; +} +EXPORT_SYMBOL_GPL(nvme_setup_cmd); + /* * Returns 0 on success. If the result is negative, it's a Linux error code; * if the result is positive, it's an NVM Express status code diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 6376cd71cc9f..8e8fae8722f8 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -181,57 +181,6 @@ static inline unsigned nvme_map_len(struct request *rq) return blk_rq_bytes(rq); } -static inline void nvme_setup_flush(struct nvme_ns *ns, - struct nvme_command *cmnd) -{ - memset(cmnd, 0, sizeof(*cmnd)); - cmnd->common.opcode = nvme_cmd_flush; - cmnd->common.nsid = cpu_to_le32(ns->ns_id); -} - -static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req, - struct nvme_command *cmnd) -{ - u16 control = 0; - u32 dsmgmt = 0; - - if (req->cmd_flags & REQ_FUA) - control |= NVME_RW_FUA; - if (req->cmd_flags & (REQ_FAILFAST_DEV | REQ_RAHEAD)) - control |= NVME_RW_LR; - - if (req->cmd_flags & REQ_RAHEAD) - dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH; - - memset(cmnd, 0, sizeof(*cmnd)); - cmnd->rw.opcode = (rq_data_dir(req) ? nvme_cmd_write : nvme_cmd_read); - cmnd->rw.command_id = req->tag; - cmnd->rw.nsid = cpu_to_le32(ns->ns_id); - cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req))); - cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1); - - if (ns->ms) { - switch (ns->pi_type) { - case NVME_NS_DPS_PI_TYPE3: - control |= NVME_RW_PRINFO_PRCHK_GUARD; - break; - case NVME_NS_DPS_PI_TYPE1: - case NVME_NS_DPS_PI_TYPE2: - control |= NVME_RW_PRINFO_PRCHK_GUARD | - NVME_RW_PRINFO_PRCHK_REF; - cmnd->rw.reftag = cpu_to_le32( - nvme_block_nr(ns, blk_rq_pos(req))); - break; - } - if (!blk_integrity_rq(req)) - control |= NVME_RW_PRINFO_PRACT; - } - - cmnd->rw.control = cpu_to_le16(control); - cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); -} - - static inline int nvme_error_status(u16 status) { switch (status & 0x7ff) { @@ -269,6 +218,8 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl); struct request *nvme_alloc_request(struct request_queue *q, struct nvme_command *cmd, unsigned int flags); void nvme_requeue_req(struct request *req); +int nvme_setup_cmd(struct nvme_ns *ns, struct request *req, + struct nvme_command *cmd); int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, void *buf, unsigned bufflen); int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 0bf7f61a0a89..008c9eec437a 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -593,43 +593,6 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req) nvme_free_iod(dev, req); } -static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req, - struct nvme_command *cmnd) -{ - struct nvme_dsm_range *range; - struct page *page; - int offset; - unsigned int nr_bytes = blk_rq_bytes(req); - - range = kmalloc(sizeof(*range), GFP_ATOMIC); - if (!range) - return BLK_MQ_RQ_QUEUE_BUSY; - - range->cattr = cpu_to_le32(0); - range->nlb = cpu_to_le32(nr_bytes >> ns->lba_shift); - range->slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req))); - - memset(cmnd, 0, sizeof(*cmnd)); - cmnd->dsm.opcode = nvme_cmd_dsm; - cmnd->dsm.nsid = cpu_to_le32(ns->ns_id); - cmnd->dsm.nr = 0; - cmnd->dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD); - - req->completion_data = range; - page = virt_to_page(range); - offset = offset_in_page(range); - blk_add_request_payload(req, page, offset, sizeof(*range)); - - /* - * we set __data_len back to the size of the area to be discarded - * on disk. This allows us to report completion on the full amount - * of blocks described by the request. - */ - req->__data_len = nr_bytes; - - return 0; -} - /* * NOTE: ns is NULL when called on the admin queue. */ @@ -662,15 +625,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx, if (ret) return ret; - if (req->cmd_type == REQ_TYPE_DRV_PRIV) - memcpy(&cmnd, req->cmd, sizeof(cmnd)); - else if (req->cmd_flags & REQ_FLUSH) - nvme_setup_flush(ns, &cmnd); - else if (req->cmd_flags & REQ_DISCARD) - ret = nvme_setup_discard(ns, req, &cmnd); - else - nvme_setup_rw(ns, req, &cmnd); - + ret = nvme_setup_cmd(ns, req, &cmnd); if (ret) goto out; -- GitLab From 21f033f7c72e9505c46c6555b019b907dc39dfcd Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Tue, 12 Apr 2016 11:13:11 -0600 Subject: [PATCH 2246/9938] NVMe: Skip async events for degraded controllers If the controller is degraded, the driver should stay out of the way so the user can recover the drive. This patch skips driver initiated async event requests when the drive is in this state. Signed-off-by: Keith Busch Reviewed-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 008c9eec437a..7508a0ae57ff 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1855,8 +1855,16 @@ static void nvme_reset_work(struct work_struct *work) if (result) goto out; - dev->ctrl.event_limit = NVME_NR_AEN_COMMANDS; - queue_work(nvme_workq, &dev->async_work); + /* + * A controller that can not execute IO typically requires user + * intervention to correct. For such degraded controllers, the driver + * should not submit commands the user did not request, so skip + * registering for asynchronous event notification on this condition. + */ + if (dev->online_queues > 1) { + dev->ctrl.event_limit = NVME_NR_AEN_COMMANDS; + queue_work(nvme_workq, &dev->async_work); + } mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + HZ)); -- GitLab From 8695add6c3ac272677cd6e4414a4b3ed26f8a1f7 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 3 Mar 2016 08:49:48 +0530 Subject: [PATCH 2247/9938] ARM: dts: dra7-evm: Add missing regulators Few regulators information were missing from DT. Add those missing regulators. Signed-off-by: Lokesh Vutla Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7-evm.dts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index a7b4707a0d05..6e61cfa12326 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -33,6 +33,7 @@ evm_3v3_sw: fixedregulator-evm_3v3_sw { compatible = "regulator-fixed"; regulator-name = "evm_3v3_sw"; + vin-supply = <&sysen1>; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; @@ -64,6 +65,7 @@ regulator-always-on; regulator-boot-on; enable-active-high; + vin-supply = <&sysen2>; gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>; }; @@ -523,6 +525,31 @@ regulator-max-microvolt = <3300000>; regulator-boot-on; }; + + /* REGEN1 is unused */ + + regen2: regen2 { + /* Needed for PMIC internal resources */ + regulator-name = "regen2"; + regulator-boot-on; + regulator-always-on; + }; + + /* REGEN3 is unused */ + + sysen1: sysen1 { + /* PMIC_REGEN_3V3 */ + regulator-name = "sysen1"; + regulator-boot-on; + regulator-always-on; + }; + + sysen2: sysen2 { + /* PMIC_REGEN_DDR */ + regulator-name = "sysen2"; + regulator-boot-on; + regulator-always-on; + }; }; }; }; -- GitLab From 3c435e2e414e82ec6c0e96a1dfc2be3ddc3c23b4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Apr 2016 21:52:35 +0200 Subject: [PATCH 2248/9938] netfilter: conntrack: de-inline nf_conntrack_eventmask_report Way too large; move it to nf_conntrack_ecache.c. Reduces total object size by 1216 byte on my machine. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_ecache.h | 66 ++++----------------- net/netfilter/nf_conntrack_ecache.c | 54 +++++++++++++++++ 2 files changed, 66 insertions(+), 54 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 57c880378443..019a5b859868 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -73,6 +73,8 @@ void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb); void nf_ct_deliver_cached_events(struct nf_conn *ct); +int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, + u32 portid, int report); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) @@ -90,70 +92,26 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) set_bit(event, &e->cache); } -static inline int -nf_conntrack_eventmask_report(unsigned int eventmask, - struct nf_conn *ct, - u32 portid, - int report) -{ - int ret = 0; - struct net *net = nf_ct_net(ct); - struct nf_ct_event_notifier *notify; - struct nf_conntrack_ecache *e; - - rcu_read_lock(); - notify = rcu_dereference(net->ct.nf_conntrack_event_cb); - if (notify == NULL) - goto out_unlock; - - e = nf_ct_ecache_find(ct); - if (e == NULL) - goto out_unlock; - - if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { - struct nf_ct_event item = { - .ct = ct, - .portid = e->portid ? e->portid : portid, - .report = report - }; - /* This is a resent of a destroy event? If so, skip missed */ - unsigned long missed = e->portid ? 0 : e->missed; - - if (!((eventmask | missed) & e->ctmask)) - goto out_unlock; - - ret = notify->fcn(eventmask | missed, &item); - if (unlikely(ret < 0 || missed)) { - spin_lock_bh(&ct->lock); - if (ret < 0) { - /* This is a destroy event that has been - * triggered by a process, we store the PORTID - * to include it in the retransmission. */ - if (eventmask & (1 << IPCT_DESTROY) && - e->portid == 0 && portid != 0) - e->portid = portid; - else - e->missed |= eventmask; - } else - e->missed &= ~missed; - spin_unlock_bh(&ct->lock); - } - } -out_unlock: - rcu_read_unlock(); - return ret; -} - static inline int nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, u32 portid, int report) { + const struct net *net = nf_ct_net(ct); + + if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) + return 0; + return nf_conntrack_eventmask_report(1 << event, ct, portid, report); } static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { + const struct net *net = nf_ct_net(ct); + + if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) + return 0; + return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); } diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 4e78c57b818f..a0ebab96a92f 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -113,6 +113,60 @@ static void ecache_work(struct work_struct *work) schedule_delayed_work(&ctnet->ecache_dwork, delay); } +int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, + u32 portid, int report) +{ + int ret = 0; + struct net *net = nf_ct_net(ct); + struct nf_ct_event_notifier *notify; + struct nf_conntrack_ecache *e; + + rcu_read_lock(); + notify = rcu_dereference(net->ct.nf_conntrack_event_cb); + if (!notify) + goto out_unlock; + + e = nf_ct_ecache_find(ct); + if (!e) + goto out_unlock; + + if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { + struct nf_ct_event item = { + .ct = ct, + .portid = e->portid ? e->portid : portid, + .report = report + }; + /* This is a resent of a destroy event? If so, skip missed */ + unsigned long missed = e->portid ? 0 : e->missed; + + if (!((eventmask | missed) & e->ctmask)) + goto out_unlock; + + ret = notify->fcn(eventmask | missed, &item); + if (unlikely(ret < 0 || missed)) { + spin_lock_bh(&ct->lock); + if (ret < 0) { + /* This is a destroy event that has been + * triggered by a process, we store the PORTID + * to include it in the retransmission. + */ + if (eventmask & (1 << IPCT_DESTROY) && + e->portid == 0 && portid != 0) + e->portid = portid; + else + e->missed |= eventmask; + } else { + e->missed &= ~missed; + } + spin_unlock_bh(&ct->lock); + } + } +out_unlock: + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL_GPL(nf_conntrack_eventmask_report); + /* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ void nf_ct_deliver_cached_events(struct nf_conn *ct) -- GitLab From ecdfb48cddfd1096343148113d5b1bd789033aa8 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Apr 2016 21:52:36 +0200 Subject: [PATCH 2249/9938] netfilter: conntrack: move expectation event helper to ecache.c Not performance critical, it is only invoked when an expectation is added/destroyed. While at it, kill unused nf_ct_expect_event() wrapper. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_ecache.h | 42 ++------------------- net/netfilter/nf_conntrack_ecache.c | 30 +++++++++++++++ 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 019a5b859868..fa36447371c6 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -130,43 +130,9 @@ int nf_ct_expect_register_notifier(struct net *net, void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb); -static inline void -nf_ct_expect_event_report(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp, - u32 portid, - int report) -{ - struct net *net = nf_ct_exp_net(exp); - struct nf_exp_event_notifier *notify; - struct nf_conntrack_ecache *e; - - rcu_read_lock(); - notify = rcu_dereference(net->ct.nf_expect_event_cb); - if (notify == NULL) - goto out_unlock; - - e = nf_ct_ecache_find(exp->master); - if (e == NULL) - goto out_unlock; - - if (e->expmask & (1 << event)) { - struct nf_exp_event item = { - .exp = exp, - .portid = portid, - .report = report - }; - notify->fcn(1 << event, &item); - } -out_unlock: - rcu_read_unlock(); -} - -static inline void -nf_ct_expect_event(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp) -{ - nf_ct_expect_event_report(event, exp, 0, 0); -} +void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, + struct nf_conntrack_expect *exp, + u32 portid, int report); int nf_conntrack_ecache_pernet_init(struct net *net); void nf_conntrack_ecache_pernet_fini(struct net *net); @@ -203,8 +169,6 @@ static inline int nf_conntrack_event_report(enum ip_conntrack_events event, u32 portid, int report) { return 0; } static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} -static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp) {} static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, struct nf_conntrack_expect *exp, u32 portid, diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index a0ebab96a92f..d28011b42845 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -221,6 +221,36 @@ void nf_ct_deliver_cached_events(struct nf_conn *ct) } EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); +void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, + struct nf_conntrack_expect *exp, + u32 portid, int report) + +{ + struct net *net = nf_ct_exp_net(exp); + struct nf_exp_event_notifier *notify; + struct nf_conntrack_ecache *e; + + rcu_read_lock(); + notify = rcu_dereference(net->ct.nf_expect_event_cb); + if (!notify) + goto out_unlock; + + e = nf_ct_ecache_find(exp->master); + if (!e) + goto out_unlock; + + if (e->expmask & (1 << event)) { + struct nf_exp_event item = { + .exp = exp, + .portid = portid, + .report = report + }; + notify->fcn(1 << event, &item); + } +out_unlock: + rcu_read_unlock(); +} + int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *new) { -- GitLab From 82b4552b91c40626a90a20291aab1137c638b512 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Tue, 12 Apr 2016 15:07:15 -0600 Subject: [PATCH 2250/9938] nvme: Use blk-mq helper for IO termination blk-mq offers a tagset iterator so let's use that instead of using nvme_clear_queues. Note, we changed nvme_queue_cancel_ios name to nvme_cancel_io as there is no concept of a queue now in this function (we also lost the print). Signed-off-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Acked-by: Keith Busch Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 7508a0ae57ff..bd0d39482e83 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -965,16 +965,15 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved) return BLK_EH_RESET_TIMER; } -static void nvme_cancel_queue_ios(struct request *req, void *data, bool reserved) +static void nvme_cancel_io(struct request *req, void *data, bool reserved) { - struct nvme_queue *nvmeq = data; + struct nvme_dev *dev = data; int status; if (!blk_mq_request_started(req)) return; - dev_dbg_ratelimited(nvmeq->dev->ctrl.device, - "Cancelling I/O %d QID %d\n", req->tag, nvmeq->qid); + dev_dbg_ratelimited(dev->ctrl.device, "Cancelling I/O %d", req->tag); status = NVME_SC_ABORT_REQ; if (blk_queue_dying(req->q)) @@ -1031,14 +1030,6 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq) return 0; } -static void nvme_clear_queue(struct nvme_queue *nvmeq) -{ - spin_lock_irq(&nvmeq->q_lock); - if (nvmeq->tags && *nvmeq->tags) - blk_mq_all_tag_busy_iter(*nvmeq->tags, nvme_cancel_queue_ios, nvmeq); - spin_unlock_irq(&nvmeq->q_lock); -} - static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown) { struct nvme_queue *nvmeq = dev->queues[0]; @@ -1765,8 +1756,8 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) } nvme_pci_disable(dev); - for (i = dev->queue_count - 1; i >= 0; i--) - nvme_clear_queue(dev->queues[i]); + blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_io, dev); + blk_mq_tagset_busy_iter(&dev->admin_tagset, nvme_cancel_io, dev); mutex_unlock(&dev->shutdown_lock); } -- GitLab From 04f59143b571161d25315dd52d7a2ecc022cb71a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 12 Apr 2016 09:57:35 +0200 Subject: [PATCH 2251/9938] i2c: let I2C masters ignore their children for PM When using a certain I2C device with runtime PM enabled on a certain I2C bus adaper the following happens: struct amba_device *foo \ struct i2c_adapter *bar \ struct i2c_client *baz The AMBA device foo has its device PM struct set to ignore children with pm_suspend_ignore_children(&foo->dev, true). This makes runtime PM work just fine locally in the driver: the fact that devices on the bus are suspended or resumed individually does not affect its operation, and the hardware does not power up unless transferring messages. However this child ignorance property is not inherited into the struct i2c_adapter *bar. On system suspend things will work fine. On system resume the following annoying phenomenon occurs: - In the pm_runtime_force_resume() path of struct i2c_client *baz, pm_runtime_set_active(&baz->dev); is eventually called. - This becomes __pm_runtime_set_status(&baz->dev, RPM_ACTIVE); - __pm_runtime_set_status() detects that RPM state is changed, and checks whether the parent is: not active (RPM_ACTIVE) and not ignoring its children If this happens it concludes something is wrong, because a parent that is not ignoring its children must be active before any children activate. - Since the struct i2c_adapter *bar does not ignore its children, the PM core thinks that it must indeed go online before its children, the check bails out with -EBUSY, i.e. the i2c_client *baz thinks it can't work because it's parent is not online, and it respects its parent. - In the driver the .resume() callback returns -EBUSY from the runtime_force_resume() call as per above. This leaves the device in a suspended state, leading to bad behaviour later when the device is used. The following debug print is made with an extra printg patch but illustrates the problem: [ 17.040832] bh1780 2-0029: parent (i2c-2) is not active parent->power.ignore_children = 0 [ 17.040832] bh1780 2-0029: pm_runtime_force_resume: pm_runtime_set_active() failed (-16) [ 17.040863] dpm_run_callback(): pm_runtime_force_resume+0x0/0x88 returns -16 [ 17.040863] PM: Device 2-0029 failed to resume: error -16 Fix this by letting all struct i2c_adapter:s ignore their children: i2c children have no business doing keeping their parents awake: they are completely autonomous devices that just use their parent to talk, a usecase which must be power managed in the host on a per-message basis. Signed-off-by: Linus Walleij Reviewed-by: Ulf Hansson Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index cc3c143b1c6a..4979728f7fb2 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1559,6 +1559,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); pm_runtime_no_callbacks(&adap->dev); + pm_suspend_ignore_children(&adap->dev, true); pm_runtime_enable(&adap->dev); #ifdef CONFIG_I2C_COMPAT -- GitLab From 6d125de40bbc5b29fd8e6dce74e1a661a085dab1 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Thu, 10 Mar 2016 13:58:48 +0200 Subject: [PATCH 2252/9938] mtip32xx: Convert to use blk_mq_tagset_busy_iter Only a single tags array anyway. Signed-off-by: Keith Busch Reviewed-by: Johannes Thumshirn Signed-off-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/block/mtip32xx/mtip32xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 25824c1697c5..404ae98b2fc4 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -3000,14 +3000,14 @@ static int mtip_service_thread(void *data) "Completion workers still active!"); spin_lock(dd->queue->queue_lock); - blk_mq_all_tag_busy_iter(*dd->tags.tags, + blk_mq_tagset_busy_iter(&dd->tags, mtip_queue_cmd, dd); spin_unlock(dd->queue->queue_lock); set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags); if (mtip_device_reset(dd)) - blk_mq_all_tag_busy_iter(*dd->tags.tags, + blk_mq_tagset_busy_iter(&dd->tags, mtip_abort_cmd, dd); clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags); @@ -4174,7 +4174,7 @@ static int mtip_block_remove(struct driver_data *dd) blk_mq_freeze_queue_start(dd->queue); blk_mq_stop_hw_queues(dd->queue); - blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd); + blk_mq_tagset_busy_iter(&dd->tags, mtip_no_dev_cleanup, dd); /* * Delete our gendisk structure. This also removes the device -- GitLab From e8f1e1630b0a98685d1a3521e8aba0dc7e68082c Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Thu, 10 Mar 2016 13:58:49 +0200 Subject: [PATCH 2253/9938] blk-mq: Make blk_mq_all_tag_busy_iter static No caller outside the blk-mq code so we can settle with it static. Signed-off-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- block/blk-mq-tag.c | 5 ++--- include/linux/blk-mq.h | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 2fd04286f103..56a0c37a3d06 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -464,15 +464,14 @@ static void bt_tags_for_each(struct blk_mq_tags *tags, } } -void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, - void *priv) +static void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, + busy_tag_iter_fn *fn, void *priv) { if (tags->nr_reserved_tags) bt_tags_for_each(tags, &tags->breserved_tags, 0, fn, priv, true); bt_tags_for_each(tags, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv, false); } -EXPORT_SYMBOL(blk_mq_all_tag_busy_iter); void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, busy_tag_iter_fn *fn, void *priv) diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index c808fec1ce44..2498fdf3a503 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -238,8 +238,6 @@ void blk_mq_start_hw_queues(struct request_queue *q); void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async); void blk_mq_run_hw_queues(struct request_queue *q, bool async); void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs); -void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, - void *priv); void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, busy_tag_iter_fn *fn, void *priv); void blk_mq_freeze_queue(struct request_queue *q); -- GitLab From 9fd4dcece43a53e5a9e65a973df5693702ee6401 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:13 +0100 Subject: [PATCH 2254/9938] debugfs: prevent access to possibly dead file_operations at file open Nothing prevents a dentry found by path lookup before a return of __debugfs_remove() to actually get opened after that return. Now, after the return of __debugfs_remove(), there are no guarantees whatsoever regarding the memory the corresponding inode's file_operations object had been kept in. Since __debugfs_remove() is seldomly invoked, usually from module exit handlers only, the race is hard to trigger and the impact is very low. A discussion of the problem outlined above as well as a suggested solution can be found in the (sub-)thread rooted at http://lkml.kernel.org/g/20130401203445.GA20862@ZenIV.linux.org.uk ("Yet another pipe related oops.") Basically, Greg KH suggests to introduce an intermediate fops and Al Viro points out that a pointer to the original ones may be stored in ->d_fsdata. Follow this line of reasoning: - Add SRCU as a reverse dependency of DEBUG_FS. - Introduce a srcu_struct object for the debugfs subsystem. - In debugfs_create_file(), store a pointer to the original file_operations object in ->d_fsdata. - Make debugfs_remove() and debugfs_remove_recursive() wait for a SRCU grace period after the dentry has been delete()'d and before they return to their callers. - Introduce an intermediate file_operations object named "debugfs_open_proxy_file_operations". It's ->open() functions checks, under the protection of a SRCU read lock, whether the dentry is still alive, i.e. has not been d_delete()'d and if so, tries to acquire a reference on the owning module. On success, it sets the file object's ->f_op to the original file_operations and forwards the ongoing open() call to the original ->open(). - For clarity, rename the former debugfs_file_operations to debugfs_noop_file_operations -- they are in no way canonical. The choice of SRCU over "normal" RCU is justified by the fact, that the former may also be used to protect ->i_private data from going away during the execution of a file's readers and writers which may (and do) sleep. Finally, introduce the fs/debugfs/internal.h header containing some declarations internal to the debugfs implementation. Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 91 ++++++++++++++++++++++++++++++++++++++++- fs/debugfs/inode.c | 13 +++++- fs/debugfs/internal.h | 24 +++++++++++ include/linux/debugfs.h | 3 -- lib/Kconfig.debug | 1 + 5 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 fs/debugfs/internal.h diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index d2ba12e23ed9..736ab3c988f2 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -22,6 +22,9 @@ #include #include #include +#include + +#include "internal.h" static ssize_t default_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -35,13 +38,99 @@ static ssize_t default_write_file(struct file *file, const char __user *buf, return count; } -const struct file_operations debugfs_file_operations = { +const struct file_operations debugfs_noop_file_operations = { .read = default_read_file, .write = default_write_file, .open = simple_open, .llseek = noop_llseek, }; +/** + * debugfs_use_file_start - mark the beginning of file data access + * @dentry: the dentry object whose data is being accessed. + * @srcu_idx: a pointer to some memory to store a SRCU index in. + * + * Up to a matching call to debugfs_use_file_finish(), any + * successive call into the file removing functions debugfs_remove() + * and debugfs_remove_recursive() will block. Since associated private + * file data may only get freed after a successful return of any of + * the removal functions, you may safely access it after a successful + * call to debugfs_use_file_start() without worrying about + * lifetime issues. + * + * If -%EIO is returned, the file has already been removed and thus, + * it is not safe to access any of its data. If, on the other hand, + * it is allowed to access the file data, zero is returned. + * + * Regardless of the return code, any call to + * debugfs_use_file_start() must be followed by a matching call + * to debugfs_use_file_finish(). + */ +static int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) + __acquires(&debugfs_srcu) +{ + *srcu_idx = srcu_read_lock(&debugfs_srcu); + barrier(); + if (d_unlinked(dentry)) + return -EIO; + return 0; +} + +/** + * debugfs_use_file_finish - mark the end of file data access + * @srcu_idx: the SRCU index "created" by a former call to + * debugfs_use_file_start(). + * + * Allow any ongoing concurrent call into debugfs_remove() or + * debugfs_remove_recursive() blocked by a former call to + * debugfs_use_file_start() to proceed and return to its caller. + */ +static void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) +{ + srcu_read_unlock(&debugfs_srcu, srcu_idx); +} + +#define F_DENTRY(filp) ((filp)->f_path.dentry) + +#define REAL_FOPS_DEREF(dentry) \ + ((const struct file_operations *)(dentry)->d_fsdata) + +static int open_proxy_open(struct inode *inode, struct file *filp) +{ + const struct dentry *dentry = F_DENTRY(filp); + const struct file_operations *real_fops = NULL; + int srcu_idx, r; + + r = debugfs_use_file_start(dentry, &srcu_idx); + if (r) { + r = -ENOENT; + goto out; + } + + real_fops = REAL_FOPS_DEREF(dentry); + real_fops = fops_get(real_fops); + if (!real_fops) { + /* Huh? Module did not clean up after itself at exit? */ + WARN(1, "debugfs file owner did not clean up at exit: %pd", + dentry); + r = -ENXIO; + goto out; + } + replace_fops(filp, real_fops); + + if (real_fops->open) + r = real_fops->open(inode, filp); + +out: + fops_put(real_fops); + debugfs_use_file_finish(srcu_idx); + return r; +} + +const struct file_operations debugfs_open_proxy_file_operations = { + .open = open_proxy_open, +}; + static struct dentry *debugfs_create_mode(const char *name, umode_t mode, struct dentry *parent, void *value, const struct file_operations *fops, diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b1e7f35f3cd4..2905dd160575 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -27,9 +27,14 @@ #include #include #include +#include + +#include "internal.h" #define DEBUGFS_DEFAULT_MODE 0700 +DEFINE_SRCU(debugfs_srcu); + static struct vfsmount *debugfs_mount; static int debugfs_mount_count; static bool debugfs_registered; @@ -341,8 +346,12 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, return failed_creating(dentry); inode->i_mode = mode; - inode->i_fop = fops ? fops : &debugfs_file_operations; inode->i_private = data; + + inode->i_fop = fops ? &debugfs_open_proxy_file_operations + : &debugfs_noop_file_operations; + dentry->d_fsdata = (void *)fops; + d_instantiate(dentry, inode); fsnotify_create(d_inode(dentry->d_parent), dentry); return end_creating(dentry); @@ -570,6 +579,7 @@ void debugfs_remove(struct dentry *dentry) inode_unlock(d_inode(parent)); if (!ret) simple_release_fs(&debugfs_mount, &debugfs_mount_count); + synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove); @@ -647,6 +657,7 @@ void debugfs_remove_recursive(struct dentry *dentry) if (!__debugfs_remove(child, parent)) simple_release_fs(&debugfs_mount, &debugfs_mount_count); inode_unlock(d_inode(parent)); + synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove_recursive); diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h new file mode 100644 index 000000000000..c7aaa5cb6685 --- /dev/null +++ b/fs/debugfs/internal.h @@ -0,0 +1,24 @@ +/* + * internal.h - declarations internal to debugfs + * + * Copyright (C) 2016 Nicolai Stange + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + */ + +#ifndef _DEBUGFS_INTERNAL_H_ +#define _DEBUGFS_INTERNAL_H_ + +struct file_operations; +struct srcu_struct; + +/* declared over in file.c */ +extern const struct file_operations debugfs_noop_file_operations; +extern const struct file_operations debugfs_open_proxy_file_operations; + +extern struct srcu_struct debugfs_srcu; + +#endif /* _DEBUGFS_INTERNAL_H_ */ diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 981e53ab84e8..fcafe2d389f9 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -43,9 +43,6 @@ extern struct dentry *arch_debugfs_dir; #if defined(CONFIG_DEBUG_FS) -/* declared over in file.c */ -extern const struct file_operations debugfs_file_operations; - struct dentry *debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1e9a607534ca..ddb0e8337aae 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -257,6 +257,7 @@ config PAGE_OWNER config DEBUG_FS bool "Debug Filesystem" + select SRCU help debugfs is a virtual file system that kernel developers use to put debugging files into. Enable this option to be able to read and -- GitLab From 49d200deaa680501f19a247b1fffb29301e51d2b Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:14 +0100 Subject: [PATCH 2255/9938] debugfs: prevent access to removed files' private data Upon return of debugfs_remove()/debugfs_remove_recursive(), it might still be attempted to access associated private file data through previously opened struct file objects. If that data has been freed by the caller of debugfs_remove*() in the meanwhile, the reading/writing process would either encounter a fault or, if the memory address in question has been reassigned again, unrelated data structures could get overwritten. However, since debugfs files are seldomly removed, usually from module exit handlers only, the impact is very low. Currently, there are ~1000 call sites of debugfs_create_file() spread throughout the whole tree and touching all of those struct file_operations in order to make them file removal aware by means of checking the result of debugfs_use_file_start() from within their methods is unfeasible. Instead, wrap the struct file_operations by a lifetime managing proxy at file open: - In debugfs_create_file(), the original fops handed in has got stashed away in ->d_fsdata already. - In debugfs_create_file(), install a proxy file_operations factory, debugfs_full_proxy_file_operations, at ->i_fop. This proxy factory has got an ->open() method only. It carries out some lifetime checks and if successful, dynamically allocates and sets up a new struct file_operations proxy at ->f_op. Afterwards, it forwards to the ->open() of the original struct file_operations in ->d_fsdata, if any. The dynamically set up proxy at ->f_op has got a lifetime managing wrapper set for each of the methods defined in the original struct file_operations in ->d_fsdata. Its ->release()er frees the proxy again and forwards to the original ->release(), if any. In order not to mislead the VFS layer, it is strictly necessary to leave those fields blank in the proxy that have been NULL in the original struct file_operations also, i.e. aren't supported. This is why there is a need for dynamically allocated proxies. The choice made not to allocate a proxy instance for every dentry at file creation, but for every struct file object instantiated thereof is justified by the expected usage pattern of debugfs, namely that in general very few files get opened more than once at a time. The wrapper methods set in the struct file_operations implement lifetime managing by means of the SRCU protection facilities already in place for debugfs: They set up a SRCU read side critical section and check whether the dentry is still alive by means of debugfs_use_file_start(). If so, they forward the call to the original struct file_operation stored in ->d_fsdata, still under the protection of the SRCU read side critical section. This SRCU read side critical section prevents any pending debugfs_remove() and friends to return to their callers. Since a file's private data must only be freed after the return of debugfs_remove(), the ongoing proxied call is guarded against any file removal race. If, on the other hand, the initial call to debugfs_use_file_start() detects that the dentry is dead, the wrapper simply returns -EIO and does not forward the call. Note that the ->poll() wrapper is special in that its signature does not allow for the return of arbitrary -EXXX values and thus, POLLHUP is returned here. In order not to pollute debugfs with wrapper definitions that aren't ever needed, I chose not to define a wrapper for every struct file_operations method possible. Instead, a wrapper is defined only for the subset of methods which are actually set by any debugfs users. Currently, these are: ->llseek() ->read() ->write() ->unlocked_ioctl() ->poll() The ->release() wrapper is special in that it does not protect the original ->release() in any way from dead files in order not to leak resources. Thus, any ->release() handed to debugfs must implement file lifetime management manually, if needed. For only 33 out of a total of 434 releasers handed in to debugfs, it could not be verified immediately whether they access data structures that might have been freed upon a debugfs_remove() return in the meanwhile. Export debugfs_use_file_start() and debugfs_use_file_finish() in order to allow any ->release() to manually implement file lifetime management. For a set of common cases of struct file_operations implemented by the debugfs_core itself, future patches will incorporate file lifetime management directly within those in order to allow for their unproxied operation. Rename the original, non-proxying "debugfs_create_file()" to "debugfs_create_file_unsafe()" and keep it for future internal use by debugfs itself. Factor out code common to both into the new __debugfs_create_file(). Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 157 +++++++++++++++++++++++++++++++++++++++- fs/debugfs/inode.c | 70 ++++++++++++------ fs/debugfs/internal.h | 6 +- include/linux/debugfs.h | 20 +++++ 4 files changed, 226 insertions(+), 27 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 736ab3c988f2..6eb58a8ed03c 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -23,9 +23,12 @@ #include #include #include +#include #include "internal.h" +struct poll_table_struct; + static ssize_t default_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -66,7 +69,7 @@ const struct file_operations debugfs_noop_file_operations = { * debugfs_use_file_start() must be followed by a matching call * to debugfs_use_file_finish(). */ -static int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) +int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) __acquires(&debugfs_srcu) { *srcu_idx = srcu_read_lock(&debugfs_srcu); @@ -75,6 +78,7 @@ static int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) return -EIO; return 0; } +EXPORT_SYMBOL_GPL(debugfs_use_file_start); /** * debugfs_use_file_finish - mark the end of file data access @@ -85,10 +89,11 @@ static int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) * debugfs_remove_recursive() blocked by a former call to * debugfs_use_file_start() to proceed and return to its caller. */ -static void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) +void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) { srcu_read_unlock(&debugfs_srcu, srcu_idx); } +EXPORT_SYMBOL_GPL(debugfs_use_file_finish); #define F_DENTRY(filp) ((filp)->f_path.dentry) @@ -131,6 +136,154 @@ const struct file_operations debugfs_open_proxy_file_operations = { .open = open_proxy_open, }; +#define PROTO(args...) args +#define ARGS(args...) args + +#define FULL_PROXY_FUNC(name, ret_type, filp, proto, args) \ +static ret_type full_proxy_ ## name(proto) \ +{ \ + const struct dentry *dentry = F_DENTRY(filp); \ + const struct file_operations *real_fops = \ + REAL_FOPS_DEREF(dentry); \ + int srcu_idx; \ + ret_type r; \ + \ + r = debugfs_use_file_start(dentry, &srcu_idx); \ + if (likely(!r)) \ + r = real_fops->name(args); \ + debugfs_use_file_finish(srcu_idx); \ + return r; \ +} + +FULL_PROXY_FUNC(llseek, loff_t, filp, + PROTO(struct file *filp, loff_t offset, int whence), + ARGS(filp, offset, whence)); + +FULL_PROXY_FUNC(read, ssize_t, filp, + PROTO(struct file *filp, char __user *buf, size_t size, + loff_t *ppos), + ARGS(filp, buf, size, ppos)); + +FULL_PROXY_FUNC(write, ssize_t, filp, + PROTO(struct file *filp, const char __user *buf, size_t size, + loff_t *ppos), + ARGS(filp, buf, size, ppos)); + +FULL_PROXY_FUNC(unlocked_ioctl, long, filp, + PROTO(struct file *filp, unsigned int cmd, unsigned long arg), + ARGS(filp, cmd, arg)); + +static unsigned int full_proxy_poll(struct file *filp, + struct poll_table_struct *wait) +{ + const struct dentry *dentry = F_DENTRY(filp); + const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); + int srcu_idx; + unsigned int r = 0; + + if (debugfs_use_file_start(dentry, &srcu_idx)) { + debugfs_use_file_finish(srcu_idx); + return POLLHUP; + } + + r = real_fops->poll(filp, wait); + debugfs_use_file_finish(srcu_idx); + return r; +} + +static int full_proxy_release(struct inode *inode, struct file *filp) +{ + const struct dentry *dentry = F_DENTRY(filp); + const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); + const struct file_operations *proxy_fops = filp->f_op; + int r = 0; + + /* + * We must not protect this against removal races here: the + * original releaser should be called unconditionally in order + * not to leak any resources. Releasers must not assume that + * ->i_private is still being meaningful here. + */ + if (real_fops->release) + r = real_fops->release(inode, filp); + + replace_fops(filp, d_inode(dentry)->i_fop); + kfree((void *)proxy_fops); + fops_put(real_fops); + return 0; +} + +static void __full_proxy_fops_init(struct file_operations *proxy_fops, + const struct file_operations *real_fops) +{ + proxy_fops->release = full_proxy_release; + if (real_fops->llseek) + proxy_fops->llseek = full_proxy_llseek; + if (real_fops->read) + proxy_fops->read = full_proxy_read; + if (real_fops->write) + proxy_fops->write = full_proxy_write; + if (real_fops->poll) + proxy_fops->poll = full_proxy_poll; + if (real_fops->unlocked_ioctl) + proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl; +} + +static int full_proxy_open(struct inode *inode, struct file *filp) +{ + const struct dentry *dentry = F_DENTRY(filp); + const struct file_operations *real_fops = NULL; + struct file_operations *proxy_fops = NULL; + int srcu_idx, r; + + r = debugfs_use_file_start(dentry, &srcu_idx); + if (r) { + r = -ENOENT; + goto out; + } + + real_fops = REAL_FOPS_DEREF(dentry); + real_fops = fops_get(real_fops); + if (!real_fops) { + /* Huh? Module did not cleanup after itself at exit? */ + WARN(1, "debugfs file owner did not clean up at exit: %pd", + dentry); + r = -ENXIO; + goto out; + } + + proxy_fops = kzalloc(sizeof(*proxy_fops), GFP_KERNEL); + if (!proxy_fops) { + r = -ENOMEM; + goto free_proxy; + } + __full_proxy_fops_init(proxy_fops, real_fops); + replace_fops(filp, proxy_fops); + + if (real_fops->open) { + r = real_fops->open(inode, filp); + + if (filp->f_op != proxy_fops) { + /* No protection against file removal anymore. */ + WARN(1, "debugfs file owner replaced proxy fops: %pd", + dentry); + goto free_proxy; + } + } + + goto out; +free_proxy: + kfree(proxy_fops); + fops_put(real_fops); +out: + debugfs_use_file_finish(srcu_idx); + return r; +} + +const struct file_operations debugfs_full_proxy_file_operations = { + .open = full_proxy_open, +}; + static struct dentry *debugfs_create_mode(const char *name, umode_t mode, struct dentry *parent, void *value, const struct file_operations *fops, diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 2905dd160575..136f269f01de 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -300,6 +300,37 @@ static struct dentry *end_creating(struct dentry *dentry) return dentry; } +static struct dentry *__debugfs_create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *proxy_fops, + const struct file_operations *real_fops) +{ + struct dentry *dentry; + struct inode *inode; + + if (!(mode & S_IFMT)) + mode |= S_IFREG; + BUG_ON(!S_ISREG(mode)); + dentry = start_creating(name, parent); + + if (IS_ERR(dentry)) + return NULL; + + inode = debugfs_get_inode(dentry->d_sb); + if (unlikely(!inode)) + return failed_creating(dentry); + + inode->i_mode = mode; + inode->i_private = data; + + inode->i_fop = proxy_fops; + dentry->d_fsdata = (void *)real_fops; + + d_instantiate(dentry, inode); + fsnotify_create(d_inode(dentry->d_parent), dentry); + return end_creating(dentry); +} + /** * debugfs_create_file - create a file in the debugfs filesystem * @name: a pointer to a string containing the name of the file to create. @@ -330,33 +361,24 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops) { - struct dentry *dentry; - struct inode *inode; - - if (!(mode & S_IFMT)) - mode |= S_IFREG; - BUG_ON(!S_ISREG(mode)); - dentry = start_creating(name, parent); - - if (IS_ERR(dentry)) - return NULL; - - inode = debugfs_get_inode(dentry->d_sb); - if (unlikely(!inode)) - return failed_creating(dentry); - inode->i_mode = mode; - inode->i_private = data; + return __debugfs_create_file(name, mode, parent, data, + fops ? &debugfs_full_proxy_file_operations : + &debugfs_noop_file_operations, + fops); +} +EXPORT_SYMBOL_GPL(debugfs_create_file); - inode->i_fop = fops ? &debugfs_open_proxy_file_operations - : &debugfs_noop_file_operations; - dentry->d_fsdata = (void *)fops; +struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) +{ - d_instantiate(dentry, inode); - fsnotify_create(d_inode(dentry->d_parent), dentry); - return end_creating(dentry); + return __debugfs_create_file(name, mode, parent, data, + fops ? &debugfs_open_proxy_file_operations : + &debugfs_noop_file_operations, + fops); } -EXPORT_SYMBOL_GPL(debugfs_create_file); /** * debugfs_create_file_size - create a file in the debugfs filesystem @@ -579,6 +601,7 @@ void debugfs_remove(struct dentry *dentry) inode_unlock(d_inode(parent)); if (!ret) simple_release_fs(&debugfs_mount, &debugfs_mount_count); + synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove); @@ -657,6 +680,7 @@ void debugfs_remove_recursive(struct dentry *dentry) if (!__debugfs_remove(child, parent)) simple_release_fs(&debugfs_mount, &debugfs_mount_count); inode_unlock(d_inode(parent)); + synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove_recursive); diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h index c7aaa5cb6685..bba52634b995 100644 --- a/fs/debugfs/internal.h +++ b/fs/debugfs/internal.h @@ -13,12 +13,14 @@ #define _DEBUGFS_INTERNAL_H_ struct file_operations; -struct srcu_struct; /* declared over in file.c */ extern const struct file_operations debugfs_noop_file_operations; extern const struct file_operations debugfs_open_proxy_file_operations; +extern const struct file_operations debugfs_full_proxy_file_operations; -extern struct srcu_struct debugfs_srcu; +struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops); #endif /* _DEBUGFS_INTERNAL_H_ */ diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index fcafe2d389f9..a63e6ea3321c 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -19,9 +19,11 @@ #include #include +#include struct device; struct file_operations; +struct srcu_struct; struct debugfs_blob_wrapper { void *data; @@ -41,6 +43,8 @@ struct debugfs_regset32 { extern struct dentry *arch_debugfs_dir; +extern struct srcu_struct debugfs_srcu; + #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_create_file(const char *name, umode_t mode, @@ -65,6 +69,11 @@ struct dentry *debugfs_create_automount(const char *name, void debugfs_remove(struct dentry *dentry); void debugfs_remove_recursive(struct dentry *dentry); +int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) + __acquires(&debugfs_srcu); + +void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu); + struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, const char *new_name); @@ -173,6 +182,17 @@ static inline void debugfs_remove(struct dentry *dentry) static inline void debugfs_remove_recursive(struct dentry *dentry) { } +static inline int debugfs_use_file_start(const struct dentry *dentry, + int *srcu_idx) + __acquires(&debugfs_srcu) +{ + return 0; +} + +static inline void debugfs_use_file_finish(int srcu_idx) + __releases(&debugfs_srcu) +{ } + static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, char *new_name) { -- GitLab From c64688081490321f2d23a292ef24e60bb321f3f1 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:15 +0100 Subject: [PATCH 2256/9938] debugfs: add support for self-protecting attribute file fops In order to protect them against file removal issues, debugfs_create_file() creates a lifetime managing proxy around each struct file_operations handed in. In cases where this struct file_operations is able to manage file lifetime by itself already, the proxy created by debugfs is a waste of resources. The most common class of struct file_operations given to debugfs are those defined by means of the DEFINE_SIMPLE_ATTRIBUTE() macro. Introduce a DEFINE_DEBUGFS_ATTRIBUTE() macro to allow any struct file_operations of this class to be easily made file lifetime aware and thus, to be operated unproxied. Specifically, introduce debugfs_attr_read() and debugfs_attr_write() which wrap simple_attr_read() and simple_attr_write() under the protection of a debugfs_use_file_start()/debugfs_use_file_finish() pair. Make DEFINE_DEBUGFS_ATTRIBUTE() set the defined struct file_operations' ->read() and ->write() members to these wrappers. Export debugfs_create_file_unsafe() in order to allow debugfs users to create their files in non-proxying operation mode. Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 28 ++++++++++++++++++++++++++++ fs/debugfs/inode.c | 28 ++++++++++++++++++++++++++++ include/linux/debugfs.h | 26 ++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 6eb58a8ed03c..8ef56d9499a4 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -284,6 +284,34 @@ const struct file_operations debugfs_full_proxy_file_operations = { .open = full_proxy_open, }; +ssize_t debugfs_attr_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + int srcu_idx; + + ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); + if (likely(!ret)) + ret = simple_attr_read(file, buf, len, ppos); + debugfs_use_file_finish(srcu_idx); + return ret; +} +EXPORT_SYMBOL_GPL(debugfs_attr_read); + +ssize_t debugfs_attr_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + int srcu_idx; + + ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); + if (likely(!ret)) + ret = simple_attr_write(file, buf, len, ppos); + debugfs_use_file_finish(srcu_idx); + return ret; +} +EXPORT_SYMBOL_GPL(debugfs_attr_write); + static struct dentry *debugfs_create_mode(const char *name, umode_t mode, struct dentry *parent, void *value, const struct file_operations *fops, diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 136f269f01de..41e079a8da26 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -369,6 +369,33 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, } EXPORT_SYMBOL_GPL(debugfs_create_file); +/** + * debugfs_create_file_unsafe - create a file in the debugfs filesystem + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have. + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is NULL, then the + * file will be created in the root of the debugfs filesystem. + * @data: a pointer to something that the caller will want to get to later + * on. The inode.i_private pointer will point to this value on + * the open() call. + * @fops: a pointer to a struct file_operations that should be used for + * this file. + * + * debugfs_create_file_unsafe() is completely analogous to + * debugfs_create_file(), the only difference being that the fops + * handed it will not get protected against file removals by the + * debugfs core. + * + * It is your responsibility to protect your struct file_operation + * methods against file removals by means of debugfs_use_file_start() + * and debugfs_use_file_finish(). ->open() is still protected by + * debugfs though. + * + * Any struct file_operations defined by means of + * DEFINE_DEBUGFS_ATTRIBUTE() is protected against file removals and + * thus, may be used here. + */ struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops) @@ -379,6 +406,7 @@ struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, &debugfs_noop_file_operations, fops); } +EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe); /** * debugfs_create_file_size - create a file in the debugfs filesystem diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index a63e6ea3321c..1438e2322d5c 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -50,6 +50,9 @@ extern struct srcu_struct debugfs_srcu; struct dentry *debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); +struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops); struct dentry *debugfs_create_file_size(const char *name, umode_t mode, struct dentry *parent, void *data, @@ -74,6 +77,26 @@ int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu); +ssize_t debugfs_attr_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos); +ssize_t debugfs_attr_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos); + +#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ +static int __fops ## _open(struct inode *inode, struct file *file) \ +{ \ + __simple_attr_check_format(__fmt, 0ull); \ + return simple_attr_open(inode, file, __get, __set, __fmt); \ +} \ +static const struct file_operations __fops = { \ + .owner = THIS_MODULE, \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = debugfs_attr_read, \ + .write = debugfs_attr_write, \ + .llseek = generic_file_llseek, \ +} + struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, const char *new_name); @@ -193,6 +216,9 @@ static inline void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) { } +#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ + static const struct file_operations __fops = { 0 } + static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, char *new_name) { -- GitLab From 5103068eaca290f890a30aae70085fac44cecaf6 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:16 +0100 Subject: [PATCH 2257/9938] debugfs, coccinelle: check for obsolete DEFINE_SIMPLE_ATTRIBUTE() usage In order to protect against file removal races, debugfs files created via debugfs_create_file() now get wrapped by a struct file_operations at their opening. If the original struct file_operations are known to be safe against removal races by themselves already, the proxy creation may be bypassed by creating the files through debugfs_create_file_unsafe(). In order to help debugfs users who use the common DEFINE_SIMPLE_ATTRIBUTE() + debugfs_create_file() idiom to transition to removal safe struct file_operations, the helper macro DEFINE_DEBUGFS_ATTRIBUTE() has been introduced. Thus, the preferred strategy is to use DEFINE_DEBUGFS_ATTRIBUTE() + debugfs_create_file_unsafe() now. Introduce a Coccinelle script that searches for DEFINE_SIMPLE_ATTRIBUTE()-defined struct file_operations handed into debugfs_create_file(). Suggest to turn these usages into the DEFINE_DEBUGFS_ATTRIBUTE() + debugfs_create_file_unsafe() pattern. Signed-off-by: Nicolai Stange Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- .../api/debugfs/debugfs_simple_attr.cocci | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci diff --git a/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci b/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci new file mode 100644 index 000000000000..85cf5408d378 --- /dev/null +++ b/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci @@ -0,0 +1,67 @@ +/// Use DEFINE_DEBUGFS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTRIBUTE +/// for debugfs files. +/// +//# Rationale: DEFINE_SIMPLE_ATTRIBUTE + debugfs_create_file() +//# imposes some significant overhead as compared to +//# DEFINE_DEBUGFS_ATTRIBUTE + debugfs_create_file_unsafe(). +// +// Copyright (C): 2016 Nicolai Stange +// Options: --no-includes +// + +virtual context +virtual patch +virtual org +virtual report + +@dsa@ +declarer name DEFINE_SIMPLE_ATTRIBUTE; +identifier dsa_fops; +expression dsa_get, dsa_set, dsa_fmt; +position p; +@@ +DEFINE_SIMPLE_ATTRIBUTE@p(dsa_fops, dsa_get, dsa_set, dsa_fmt); + +@dcf@ +expression name, mode, parent, data; +identifier dsa.dsa_fops; +@@ +debugfs_create_file(name, mode, parent, data, &dsa_fops) + + +@context_dsa depends on context && dcf@ +declarer name DEFINE_DEBUGFS_ATTRIBUTE; +identifier dsa.dsa_fops; +expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt; +@@ +* DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); + + +@patch_dcf depends on patch expression@ +expression name, mode, parent, data; +identifier dsa.dsa_fops; +@@ +- debugfs_create_file(name, mode, parent, data, &dsa_fops) ++ debugfs_create_file_unsafe(name, mode, parent, data, &dsa_fops) + +@patch_dsa depends on patch_dcf && patch@ +identifier dsa.dsa_fops; +expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt; +@@ +- DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); ++ DEFINE_DEBUGFS_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); + + +@script:python depends on org && dcf@ +fops << dsa.dsa_fops; +p << dsa.p; +@@ +msg="%s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops) +coccilib.org.print_todo(p[0], msg) + +@script:python depends on report && dcf@ +fops << dsa.dsa_fops; +p << dsa.p; +@@ +msg="WARNING: %s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops) +coccilib.report.print_report(p[0], msg) -- GitLab From 4909f168104b24f592fb8d502e2a6520346a3927 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:17 +0100 Subject: [PATCH 2258/9938] debugfs: unproxify integer attribute files Currently, the struct file_operations associated with the integer attribute style files created through the debugfs_create_*() helpers are not file lifetime aware as they are defined by means of DEFINE_SIMPLE_ATTRIBUTE(). Thus, a lifetime managing proxy is created around the original fops each time such a file is opened which is an unnecessary waste of resources. Migrate all usages of DEFINE_SIMPLE_ATTRIBUTE() within debugfs itself to DEFINE_DEBUGFS_ATTRIBUTE() in order to implement file lifetime managing within the struct file_operations thus defined. Introduce the debugfs_create_mode_unsafe() helper, analogous to debugfs_create_mode(), but distinct in that it creates the files in non-proxying operation mode through debugfs_create_file_unsafe(). Feed all struct file_operations migrated to DEFINE_DEBUGFS_ATTRIBUTE() into debugfs_create_mode_unsafe() instead of former debugfs_create_mode(). Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 123 ++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 8ef56d9499a4..4b3967e86e97 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -328,6 +328,24 @@ static struct dentry *debugfs_create_mode(const char *name, umode_t mode, return debugfs_create_file(name, mode, parent, value, fops); } +static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *value, + const struct file_operations *fops, + const struct file_operations *fops_ro, + const struct file_operations *fops_wo) +{ + /* if there are no write bits set, make read only */ + if (!(mode & S_IWUGO)) + return debugfs_create_file_unsafe(name, mode, parent, value, + fops_ro); + /* if there are no read bits set, make write only */ + if (!(mode & S_IRUGO)) + return debugfs_create_file_unsafe(name, mode, parent, value, + fops_wo); + + return debugfs_create_file_unsafe(name, mode, parent, value, fops); +} + static int debugfs_u8_set(void *data, u64 val) { *(u8 *)data = val; @@ -338,9 +356,9 @@ static int debugfs_u8_get(void *data, u64 *val) *val = *(u8 *)data; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); /** * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value @@ -369,7 +387,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); struct dentry *debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, u8 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_u8, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8, &fops_u8_ro, &fops_u8_wo); } EXPORT_SYMBOL_GPL(debugfs_create_u8); @@ -384,9 +402,9 @@ static int debugfs_u16_get(void *data, u64 *val) *val = *(u16 *)data; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); /** * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value @@ -415,7 +433,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); struct dentry *debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, u16 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_u16, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16, &fops_u16_ro, &fops_u16_wo); } EXPORT_SYMBOL_GPL(debugfs_create_u16); @@ -430,9 +448,9 @@ static int debugfs_u32_get(void *data, u64 *val) *val = *(u32 *)data; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); /** * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value @@ -461,7 +479,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); struct dentry *debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, u32 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_u32, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, &fops_u32_ro, &fops_u32_wo); } EXPORT_SYMBOL_GPL(debugfs_create_u32); @@ -477,9 +495,9 @@ static int debugfs_u64_get(void *data, u64 *val) *val = *(u64 *)data; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); /** * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value @@ -508,7 +526,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); struct dentry *debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, u64 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_u64, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64, &fops_u64_ro, &fops_u64_wo); } EXPORT_SYMBOL_GPL(debugfs_create_u64); @@ -524,9 +542,10 @@ static int debugfs_ulong_get(void *data, u64 *val) *val = *(unsigned long *)data; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, + "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); /** * debugfs_create_ulong - create a debugfs file that is used to read and write @@ -556,26 +575,30 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); struct dentry *debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent, unsigned long *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_ulong, - &fops_ulong_ro, &fops_ulong_wo); + return debugfs_create_mode_unsafe(name, mode, parent, value, + &fops_ulong, &fops_ulong_ro, + &fops_ulong_wo); } EXPORT_SYMBOL_GPL(debugfs_create_ulong); -DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, + "0x%04llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, + "0x%08llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, "0x%016llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, + "0x%016llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n"); /* * debugfs_create_x{8,16,32,64} - create a debugfs file that is used to read and write an unsigned {8,16,32,64}-bit value @@ -598,7 +621,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n"); struct dentry *debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, u8 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_x8, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8, &fops_x8_ro, &fops_x8_wo); } EXPORT_SYMBOL_GPL(debugfs_create_x8); @@ -616,7 +639,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_x8); struct dentry *debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_x16, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16, &fops_x16_ro, &fops_x16_wo); } EXPORT_SYMBOL_GPL(debugfs_create_x16); @@ -634,7 +657,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_x16); struct dentry *debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, u32 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_x32, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32, &fops_x32_ro, &fops_x32_wo); } EXPORT_SYMBOL_GPL(debugfs_create_x32); @@ -652,7 +675,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_x32); struct dentry *debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, u64 *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_x64, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64, &fops_x64_ro, &fops_x64_wo); } EXPORT_SYMBOL_GPL(debugfs_create_x64); @@ -668,10 +691,10 @@ static int debugfs_size_t_get(void *data, u64 *val) *val = *(size_t *)data; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_size_t, debugfs_size_t_get, debugfs_size_t_set, - "%llu\n"); /* %llu and %zu are more or less the same */ -DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_ro, debugfs_size_t_get, NULL, "%llu\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t, debugfs_size_t_get, debugfs_size_t_set, + "%llu\n"); /* %llu and %zu are more or less the same */ +DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t_ro, debugfs_size_t_get, NULL, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n"); /** * debugfs_create_size_t - create a debugfs file that is used to read and write an size_t value @@ -686,8 +709,9 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n"); struct dentry *debugfs_create_size_t(const char *name, umode_t mode, struct dentry *parent, size_t *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_size_t, - &fops_size_t_ro, &fops_size_t_wo); + return debugfs_create_mode_unsafe(name, mode, parent, value, + &fops_size_t, &fops_size_t_ro, + &fops_size_t_wo); } EXPORT_SYMBOL_GPL(debugfs_create_size_t); @@ -701,10 +725,12 @@ static int debugfs_atomic_t_get(void *data, u64 *val) *val = atomic_read((atomic_t *)data); return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, +DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, debugfs_atomic_t_set, "%lld\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, "%lld\n"); -DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%lld\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, + "%lld\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, + "%lld\n"); /** * debugfs_create_atomic_t - create a debugfs file that is used to read and @@ -720,8 +746,9 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%lld\n"); struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode, struct dentry *parent, atomic_t *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_atomic_t, - &fops_atomic_t_ro, &fops_atomic_t_wo); + return debugfs_create_mode_unsafe(name, mode, parent, value, + &fops_atomic_t, &fops_atomic_t_ro, + &fops_atomic_t_wo); } EXPORT_SYMBOL_GPL(debugfs_create_atomic_t); -- GitLab From 4d45f7974ccf0aa783034fef2661573b3a28609e Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:18 +0100 Subject: [PATCH 2259/9938] debugfs: unproxify files created through debugfs_create_bool() Currently, the struct file_operations fops_bool associated with files created through the debugfs_create_bool() helpers are not file lifetime aware. Thus, a lifetime managing proxy is created around fops_bool each time such a file is opened which is an unnecessary waste of resources. Implement file lifetime management for the fops_bool file_operations. Namely, make debugfs_read_file_bool() and debugfs_write_file_bool() safe against file removals by means of debugfs_use_file_start() and debugfs_use_file_finish(). Make debugfs_create_bool() create its files in non-proxying operation mode through debugfs_create_mode_unsafe(). Finally, purge debugfs_create_mode() as debugfs_create_bool() had been its last user. Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 4b3967e86e97..8a548bee1b3d 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -312,22 +312,6 @@ ssize_t debugfs_attr_write(struct file *file, const char __user *buf, } EXPORT_SYMBOL_GPL(debugfs_attr_write); -static struct dentry *debugfs_create_mode(const char *name, umode_t mode, - struct dentry *parent, void *value, - const struct file_operations *fops, - const struct file_operations *fops_ro, - const struct file_operations *fops_wo) -{ - /* if there are no write bits set, make read only */ - if (!(mode & S_IWUGO)) - return debugfs_create_file(name, mode, parent, value, fops_ro); - /* if there are no read bits set, make write only */ - if (!(mode & S_IRUGO)) - return debugfs_create_file(name, mode, parent, value, fops_wo); - - return debugfs_create_file(name, mode, parent, value, fops); -} - static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, struct dentry *parent, void *value, const struct file_operations *fops, @@ -756,9 +740,17 @@ ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { char buf[3]; - bool *val = file->private_data; + bool val; + int r, srcu_idx; + + r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); + if (likely(!r)) + val = *(bool *)file->private_data; + debugfs_use_file_finish(srcu_idx); + if (r) + return r; - if (*val) + if (val) buf[0] = 'Y'; else buf[0] = 'N'; @@ -774,6 +766,7 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, char buf[32]; size_t buf_size; bool bv; + int r, srcu_idx; bool *val = file->private_data; buf_size = min(count, (sizeof(buf)-1)); @@ -781,8 +774,14 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, return -EFAULT; buf[buf_size] = '\0'; - if (strtobool(buf, &bv) == 0) - *val = bv; + if (strtobool(buf, &bv) == 0) { + r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); + if (likely(!r)) + *val = bv; + debugfs_use_file_finish(srcu_idx); + if (r) + return r; + } return count; } @@ -834,7 +833,7 @@ static const struct file_operations fops_bool_wo = { struct dentry *debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, bool *value) { - return debugfs_create_mode(name, mode, parent, value, &fops_bool, + return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_bool, &fops_bool_ro, &fops_bool_wo); } EXPORT_SYMBOL_GPL(debugfs_create_bool); -- GitLab From 83b711cbf4ff42a9996c5f092762b3967d307d73 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:19 +0100 Subject: [PATCH 2260/9938] debugfs: unproxify files created through debugfs_create_blob() Currently, the struct file_operations fops_blob associated with files created through the debugfs_create_blob() helpers are not file lifetime aware. Thus, a lifetime managing proxy is created around fops_blob each time such a file is opened which is an unnecessary waste of resources. Implement file lifetime management for the fops_bool file_operations. Namely, make read_file_blob() safe gainst file removals by means of debugfs_use_file_start() and debugfs_use_file_finish(). Make debugfs_create_blob() create its files in non-proxying operation mode by means of debugfs_create_file_unsafe(). Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 8a548bee1b3d..2e86d66f7850 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -842,8 +842,15 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct debugfs_blob_wrapper *blob = file->private_data; - return simple_read_from_buffer(user_buf, count, ppos, blob->data, - blob->size); + ssize_t r; + int srcu_idx; + + r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); + if (likely(!r)) + r = simple_read_from_buffer(user_buf, count, ppos, blob->data, + blob->size); + debugfs_use_file_finish(srcu_idx); + return r; } static const struct file_operations fops_blob = { @@ -880,7 +887,7 @@ struct dentry *debugfs_create_blob(const char *name, umode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob) { - return debugfs_create_file(name, mode, parent, blob, &fops_blob); + return debugfs_create_file_unsafe(name, mode, parent, blob, &fops_blob); } EXPORT_SYMBOL_GPL(debugfs_create_blob); -- GitLab From c4a74f63dfd2e75e7d40a9aaa4052b0ef26e617c Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 22 Mar 2016 14:11:20 +0100 Subject: [PATCH 2261/9938] debugfs: unproxify files created through debugfs_create_u32_array() The struct file_operations u32_array_fops associated with files created through debugfs_create_u32_array() has been lifetime aware already: everything needed for subsequent operation is copied to a ->f_private buffer at file opening time in u32_array_open(). Now, ->open() is always protected against file removal issues by the debugfs core. There is no need for the debugfs core to wrap the u32_array_fops with a file lifetime managing proxy. Make debugfs_create_u32_array() create its files in non-proxying operation mode by means of debugfs_create_file_unsafe(). Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 2e86d66f7850..9c1c9a01b7e5 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -992,7 +992,8 @@ struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, data->array = array; data->elements = elements; - return debugfs_create_file(name, mode, parent, data, &u32_array_fops); + return debugfs_create_file_unsafe(name, mode, parent, data, + &u32_array_fops); } EXPORT_SYMBOL_GPL(debugfs_create_u32_array); -- GitLab From 2ee73c484dc4b8831b745a5feed56382b8741a72 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 10 Mar 2016 14:12:21 +0200 Subject: [PATCH 2262/9938] i2c: i801: Convert to struct dev_pm_ops for suspend/resume Stop using legacy PCI PM support and convert to standard dev_pm_ops. This provides more straightforward path to add runtime PM. While at it remove explicit PCI power state control and configuration space save/restore as the PCI core does it. Signed-off-by: Jarkko Nikula Tested-by: Reinette Chatre Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 585a3b7915bd..7a29f1436ddb 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1433,34 +1433,32 @@ static void i801_remove(struct pci_dev *dev) } #ifdef CONFIG_PM -static int i801_suspend(struct pci_dev *dev, pm_message_t mesg) +static int i801_suspend(struct device *dev) { - struct i801_priv *priv = pci_get_drvdata(dev); + struct pci_dev *pci_dev = to_pci_dev(dev); + struct i801_priv *priv = pci_get_drvdata(pci_dev); - pci_save_state(dev); - pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); - pci_set_power_state(dev, pci_choose_state(dev, mesg)); + pci_write_config_byte(pci_dev, SMBHSTCFG, priv->original_hstcfg); return 0; } -static int i801_resume(struct pci_dev *dev) +static int i801_resume(struct device *dev) { - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); return 0; } -#else -#define i801_suspend NULL -#define i801_resume NULL #endif +static UNIVERSAL_DEV_PM_OPS(i801_pm_ops, i801_suspend, + i801_resume, NULL); + static struct pci_driver i801_driver = { .name = "i801_smbus", .id_table = i801_ids, .probe = i801_probe, .remove = i801_remove, - .suspend = i801_suspend, - .resume = i801_resume, + .driver = { + .pm = &i801_pm_ops, + }, }; static int __init i2c_i801_init(void) -- GitLab From a7401ca5596e246f17b087b84fe55a429b666132 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 10 Mar 2016 14:12:22 +0200 Subject: [PATCH 2263/9938] i2c: i801: Add runtime PM support with autosuspend Allow runtime PM so that PM and PCI core can put the device into low-power state when idle and resume it back when needed in those platforms that support PM for i801 device. Enable also autosuspend with 1 second delay in order to not needlessly toggle power state on and off if there are multiple transactions during short time. Device is resumed at the beginning of bus access and marked idle ready for autosuspend at the end of it. Signed-off-by: Jarkko Nikula Tested-by: Reinette Chatre Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 7a29f1436ddb..64b1208bca5e 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -94,6 +94,7 @@ #include #include #include +#include #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ defined CONFIG_DMI @@ -714,9 +715,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, { int hwpec; int block = 0; - int ret, xact = 0; + int ret = 0, xact = 0; struct i801_priv *priv = i2c_get_adapdata(adap); + pm_runtime_get_sync(&priv->pci_dev->dev); + hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA; @@ -773,7 +776,8 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, default: dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto out; } if (hwpec) /* enable/disable hardware PEC */ @@ -796,11 +800,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); if (block) - return ret; + goto out; if (ret) - return ret; + goto out; if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) - return 0; + goto out; switch (xact & 0x7f) { case I801_BYTE: /* Result put in SMBHSTDAT0 */ @@ -812,7 +816,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, (inb_p(SMBHSTDAT1(priv)) << 8); break; } - return 0; + +out: + pm_runtime_mark_last_busy(&priv->pci_dev->dev); + pm_runtime_put_autosuspend(&priv->pci_dev->dev); + return ret; } @@ -1413,6 +1421,11 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) pci_set_drvdata(dev, priv); + pm_runtime_set_autosuspend_delay(&dev->dev, 1000); + pm_runtime_use_autosuspend(&dev->dev); + pm_runtime_put_autosuspend(&dev->dev); + pm_runtime_allow(&dev->dev); + return 0; } @@ -1420,6 +1433,9 @@ static void i801_remove(struct pci_dev *dev) { struct i801_priv *priv = pci_get_drvdata(dev); + pm_runtime_forbid(&dev->dev); + pm_runtime_get_noresume(&dev->dev); + i801_del_mux(priv); i2c_del_adapter(&priv->adapter); pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); -- GitLab From 91d075c7cf2cf621142c0a69f2acc690b81cb8a2 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 3 Mar 2016 13:28:20 +0200 Subject: [PATCH 2264/9938] ARM: dts: dra7-evm: Fix comment about NAND configuration The switch configuration for NAND is actually the other way round. Also mention ON/OFF states as that is more natural to understand (without the help of schematics) when compared to HIGH/LOW. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7-evm.dts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 6e61cfa12326..05c135d84374 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -256,8 +256,9 @@ nand_flash_x16: nand_flash_x16 { /* On DRA7 EVM, GPMC_WPN and NAND_BOOTn comes from DIP switch * So NAND flash requires following switch settings: - * SW5.9 (GPMC_WPN) = LOW - * SW5.1 (NAND_BOOTn) = HIGH */ + * SW5.1 (NAND_BOOTn) = ON (LOW) + * SW5.9 (GPMC_WPN) = OFF (HIGH) + */ pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT | MUX_MODE0) /* gpmc_ad0 */ DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT | MUX_MODE0) /* gpmc_ad1 */ -- GitLab From 50413b9d659414d71c0d53d9ac131257326a8528 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 13 Mar 2016 01:06:14 +0100 Subject: [PATCH 2265/9938] ARM: dts: n9/n950: regulator configuration Add regulator configuration as found in the board files of Nokia's kernel. Signed-off-By: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950-n9.dtsi | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi index 858a25048102..924cc9358cba 100644 --- a/arch/arm/boot/dts/omap3-n950-n9.dtsi +++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi @@ -129,6 +129,30 @@ ti,pulldowns = <0x008106>; /* BIT(1) | BIT(2) | BIT(8) | BIT(15) */ }; +&vdac { + regulator-name = "vdac"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + +&vpll1 { + regulator-name = "vpll1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + +&vpll2 { + regulator-name = "vpll2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + +&vaux1 { + regulator-name = "vaux1"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; +}; + /* CSI-2 receiver */ &vaux2 { regulator-name = "vaux2"; @@ -143,6 +167,54 @@ regulator-max-microvolt = <2800000>; }; +&vaux4 { + regulator-name = "vaux4"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; +}; + +&vmmc1 { + regulator-name = "vmmc1"; + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <3150000>; +}; + +&vmmc2 { + regulator-name = "vmmc2"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; +}; + +&vintana1 { + regulator-name = "vintana1"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; +}; + +&vintana2 { + regulator-name = "vintana2"; + regulator-min-microvolt = <2750000>; + regulator-max-microvolt = <2750000>; +}; + +&vintdig { + regulator-name = "vintdig"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; +}; + +&vsim { + regulator-name = "vsim"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + +&vio { + regulator-name = "vio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + &i2c2 { clock-frequency = <400000>; }; -- GitLab From 536b20113f04068386ec247e08a9a1fea994c28b Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 13 Mar 2016 01:06:15 +0100 Subject: [PATCH 2266/9938] ARM: dts: OMAP3-N950: Add Keypad Matrix Add keypad matrix information based on data from Nokia N950 Kernel. Signed-off-by: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950.dts | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts index 7f219a9dc5be..d429329786ab 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/omap3-n950.dts @@ -11,6 +11,7 @@ /dts-v1/; #include "omap3-n950-n9.dtsi" +#include / { model = "Nokia N950"; @@ -86,3 +87,58 @@ &modem { compatible = "nokia,n950-modem"; }; + +&twl_keypad { + linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_BACKSLASH) + MATRIX_KEY(0x01, 0x00, KEY_LEFTSHIFT) + MATRIX_KEY(0x02, 0x00, KEY_COMPOSE) + MATRIX_KEY(0x03, 0x00, KEY_LEFTMETA) + MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL) + MATRIX_KEY(0x05, 0x00, KEY_BACKSPACE) + MATRIX_KEY(0x06, 0x00, KEY_VOLUMEDOWN) + MATRIX_KEY(0x07, 0x00, KEY_VOLUMEUP) + + MATRIX_KEY(0x03, 0x01, KEY_Z) + MATRIX_KEY(0x04, 0x01, KEY_A) + MATRIX_KEY(0x05, 0x01, KEY_Q) + MATRIX_KEY(0x06, 0x01, KEY_W) + MATRIX_KEY(0x07, 0x01, KEY_E) + + MATRIX_KEY(0x03, 0x02, KEY_X) + MATRIX_KEY(0x04, 0x02, KEY_S) + MATRIX_KEY(0x05, 0x02, KEY_D) + MATRIX_KEY(0x06, 0x02, KEY_C) + MATRIX_KEY(0x07, 0x02, KEY_V) + + MATRIX_KEY(0x03, 0x03, KEY_O) + MATRIX_KEY(0x04, 0x03, KEY_I) + MATRIX_KEY(0x05, 0x03, KEY_U) + MATRIX_KEY(0x06, 0x03, KEY_L) + MATRIX_KEY(0x07, 0x03, KEY_APOSTROPHE) + + MATRIX_KEY(0x03, 0x04, KEY_Y) + MATRIX_KEY(0x04, 0x04, KEY_K) + MATRIX_KEY(0x05, 0x04, KEY_J) + MATRIX_KEY(0x06, 0x04, KEY_H) + MATRIX_KEY(0x07, 0x04, KEY_G) + + MATRIX_KEY(0x03, 0x05, KEY_B) + MATRIX_KEY(0x04, 0x05, KEY_COMMA) + MATRIX_KEY(0x05, 0x05, KEY_M) + MATRIX_KEY(0x06, 0x05, KEY_N) + MATRIX_KEY(0x07, 0x05, KEY_DOT) + + MATRIX_KEY(0x00, 0x06, KEY_SPACE) + MATRIX_KEY(0x03, 0x06, KEY_T) + MATRIX_KEY(0x04, 0x06, KEY_UP) + MATRIX_KEY(0x05, 0x06, KEY_LEFT) + MATRIX_KEY(0x06, 0x06, KEY_RIGHT) + MATRIX_KEY(0x07, 0x06, KEY_DOWN) + + MATRIX_KEY(0x03, 0x07, KEY_P) + MATRIX_KEY(0x04, 0x07, KEY_ENTER) + MATRIX_KEY(0x05, 0x07, KEY_SLASH) + MATRIX_KEY(0x06, 0x07, KEY_F) + MATRIX_KEY(0x07, 0x07, KEY_R) + >; +}; -- GitLab From d9546a189cd02b73eb9a8236699ad1a3ca86536b Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 13 Mar 2016 01:06:16 +0100 Subject: [PATCH 2267/9938] ARM: dts: OMAP3-N950: Add Vibrator Signed-off-by: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts index d429329786ab..b6cea8c2d78f 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/omap3-n950.dts @@ -88,6 +88,13 @@ compatible = "nokia,n950-modem"; }; +&twl { + twl_audio: audio { + compatible = "ti,twl4030-audio"; + ti,enable-vibra = <1>; + }; +}; + &twl_keypad { linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_BACKSLASH) MATRIX_KEY(0x01, 0x00, KEY_LEFTSHIFT) -- GitLab From d5b0eab7ffaeccc286f791fab252293dc2e8bb90 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 13 Mar 2016 01:06:17 +0100 Subject: [PATCH 2268/9938] ARM: dts: Enable N950 keyboard sleep leds by default Like the Nokia N900, the N950 has leds to show the state of sys_clkreq and sys_off_mode pins. A detailed description for the LEDs and OMAP's sleep states can be found in Tony's commit for the Nokia N900: c1be2032f66df9e1238bd5bc4ca666de88a62abc Signed-off-by: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950-n9.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi index 924cc9358cba..b9d72110b285 100644 --- a/arch/arm/boot/dts/omap3-n950-n9.dtsi +++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi @@ -39,9 +39,27 @@ enable-active-high; regulator-boot-off; }; + + leds { + compatible = "gpio-leds"; + + heartbeat { + label = "debug::sleep"; + gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>; /* gpio92 */ + linux,default-trigger = "default-on"; + pinctrl-names = "default"; + pinctrl-0 = <&debug_leds>; + }; + }; }; &omap3_pmx_core { + debug_leds: pinmux_debug_led_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE4) /* dss_data22.gpio_92 */ + >; + }; + mmc2_pins: pinmux_mmc2_pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk */ -- GitLab From 8d1ddfce060202cca5a8a7f6c971e41c567edc14 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 13 Mar 2016 01:06:18 +0100 Subject: [PATCH 2269/9938] ARM: dts: OMAP3-N950: Add Keypad Slide Switch Signed-off-by: Sebastian Reichel Acked-by: Pavel Machek Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950.dts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts index b6cea8c2d78f..67041305a0f1 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/omap3-n950.dts @@ -16,6 +16,28 @@ / { model = "Nokia N950"; compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3"; + + keys { + compatible = "gpio-keys"; + + keypad_slide { + label = "Keypad Slide"; + gpios = <&gpio4 13 GPIO_ACTIVE_LOW>; /* 109 */ + linux,input-type = ; + linux,code = ; + wakeup-source; + pinctrl-names = "default"; + pinctrl-0 = <&keypad_slide_pins>; + }; + }; +}; + +&omap3_pmx_core { + keypad_slide_pins: pinmux_debug_led_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x212a, PIN_INPUT | MUX_MODE4) /* cam_d10.gpio_109 */ + >; + }; }; &omap3_pmx_core { -- GitLab From 0f4f1542ea0928f4840d308e411797c0dacac239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Matijevi=C4=87?= Date: Sun, 13 Mar 2016 01:06:19 +0100 Subject: [PATCH 2270/9938] ARM: dts: N9/N950: Add support for 1GHz CPU clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filip Matijević Signed-off-by: Sebastian Reichel Acked-by: Pavel Machek Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950-n9.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi index b9d72110b285..01632c382467 100644 --- a/arch/arm/boot/dts/omap3-n950-n9.dtsi +++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi @@ -14,6 +14,13 @@ cpus { cpu@0 { cpu0-supply = <&vcc>; + operating-points = < + /* kHz uV */ + 300000 1012500 + 600000 1200000 + 800000 1325000 + 1000000 1375000 + >; }; }; -- GitLab From 83faf920659386608cc63a7206cd91dba31cd443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Matijevi=C4=87?= Date: Sun, 13 Mar 2016 01:06:20 +0100 Subject: [PATCH 2271/9938] ARM: dts: N9/N950: Add support for accelerometer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filip Matijević Signed-off-by: Sebastian Reichel Acked-by: Pavel Machek Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n9.dts | 14 ++++++++ arch/arm/boot/dts/omap3-n950-n9.dtsi | 54 ++++++++++++++++++++++++++++ arch/arm/boot/dts/omap3-n950.dts | 14 ++++++++ 3 files changed, 82 insertions(+) diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts index 5c67429a4da7..b9e58c536afd 100644 --- a/arch/arm/boot/dts/omap3-n9.dts +++ b/arch/arm/boot/dts/omap3-n9.dts @@ -57,3 +57,17 @@ &modem { compatible = "nokia,n9-modem"; }; + +&lis302 { + st,axis-x = <1>; /* LIS3_DEV_X */ + st,axis-y = <(-2)>; /* LIS3_INV_DEV_Y */ + st,axis-z = <(-3)>; /* LIS3_INV_DEV_Z */ + + st,min-limit-x = <(-46)>; + st,min-limit-y = <3>; + st,min-limit-z = <3>; + + st,max-limit-x = <(-3)>; + st,max-limit-y = <46>; + st,max-limit-z = <46>; +}; diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi index 01632c382467..a00ca761675d 100644 --- a/arch/arm/boot/dts/omap3-n950-n9.dtsi +++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi @@ -61,6 +61,13 @@ }; &omap3_pmx_core { + accelerator_pins: pinmux_accelerator_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21da, PIN_INPUT | MUX_MODE4) /* mcspi2_somi.gpio_180 -> LIS302 INT1 */ + OMAP3_CORE1_IOPAD(0x21dc, PIN_INPUT | MUX_MODE4) /* mcspi2_cs0.gpio_181 -> LIS302 INT2 */ + >; + }; + debug_leds: pinmux_debug_led_pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE4) /* dss_data22.gpio_92 */ @@ -246,6 +253,53 @@ &i2c3 { clock-frequency = <400000>; + + lis302: lis302@1d { + compatible = "st,lis3lv02d"; + reg = <0x1d>; + + Vdd-supply = <&vaux1>; + Vdd_IO-supply = <&vio>; + + pinctrl-names = "default"; + pinctrl-0 = <&accelerator_pins>; + + interrupts-extended = <&gpio6 20 IRQ_TYPE_EDGE_FALLING>, <&gpio6 21 IRQ_TYPE_EDGE_FALLING>; /* 180, 181 */ + + /* click flags */ + st,click-single-x; + st,click-single-y; + st,click-single-z; + + /* Limits are 0.5g * value */ + st,click-threshold-x = <8>; + st,click-threshold-y = <8>; + st,click-threshold-z = <10>; + + /* Click must be longer than time limit */ + st,click-time-limit = <9>; + + /* Kind of debounce filter */ + st,click-latency = <50>; + + st,wakeup-x-hi; + st,wakeup-y-hi; + st,wakeup-threshold = <(800/18)>; /* millig-value / 18 to get HW values */ + + st,wakeup2-z-hi; + st,wakeup2-threshold = <(1000/18)>; /* millig-value / 18 to get HW values */ + + st,highpass-cutoff-hz = <2>; + + /* Interrupt line 1 for thresholds */ + st,irq1-ff-wu-1; + st,irq1-ff-wu-2; + /* Interrupt line 2 for click detection */ + st,irq2-click; + + st,wu-duration-1 = <8>; + st,wu-duration-2 = <8>; + }; }; &mmc1 { diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts index 67041305a0f1..646601a3ebd8 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/omap3-n950.dts @@ -171,3 +171,17 @@ MATRIX_KEY(0x07, 0x07, KEY_R) >; }; + +&lis302 { + st,axis-x = <(-2)>; /* LIS3_INV_DEV_Y */ + st,axis-y = <(-1)>; /* LIS3_INV_DEV_X */ + st,axis-z = <(-3)>; /* LIS3_INV_DEV_Z */ + + st,min-limit-x = <(-32)>; + st,min-limit-y = <3>; + st,min-limit-z = <3>; + + st,max-limit-x = <(-3)>; + st,max-limit-y = <32>; + st,max-limit-z = <32>; +}; -- GitLab From 3a1de8082405e5c7bd38f4d71605ca85efecf071 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Mar 2016 16:52:30 +0000 Subject: [PATCH 2272/9938] ARM: dts: dra7xx: Fix compatible string for PCF8575 chip The binding definition for the PCF857x GPIO expanders doesn't mention a "ti,pcf8575" compatible string. This is apparently because TI is only a second source - there is no functional difference between PCF8575 chips manufactured by TI and NXP, and the same board might be populated with either depending on availability. This is not a problem in practice because the I2C core uses of_modalias_node() before matching drivers and this strips the manufacturer name. Signed-off-by: Ben Hutchings Acked-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7-evm.dts | 2 +- arch/arm/boot/dts/dra72-evm.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 05c135d84374..7fda602868d7 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -567,7 +567,7 @@ }; pcf_gpio_21: gpio@21 { - compatible = "ti,pcf8575"; + compatible = "nxp,pcf8575"; reg = <0x21>; lines-initial-states = <0x1408>; gpio-controller; diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index 21c5cd13b807..4bd639b9ff91 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts @@ -422,7 +422,7 @@ }; pcf_gpio_21: gpio@21 { - compatible = "ti,pcf8575"; + compatible = "nxp,pcf8575"; reg = <0x21>; lines-initial-states = <0x1408>; gpio-controller; -- GitLab From dce2a6524963f58e7fd0b8888b2d3791c150f42c Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Thu, 17 Mar 2016 20:15:22 -0500 Subject: [PATCH 2273/9938] ARM: dts: da850/am4372/am33xx: Use generic node name for ehrpwm When possible generic node names should be used. So change the node name from ehrpwm to pwm. Signed-off-by: Franklin S Cooper Jr Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-shc.dts | 2 +- arch/arm/boot/dts/am33xx.dtsi | 6 +++--- arch/arm/boot/dts/am4372.dtsi | 12 ++++++------ arch/arm/boot/dts/da850.dtsi | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/am335x-shc.dts b/arch/arm/boot/dts/am335x-shc.dts index 865de8500f1c..837d5b80ea1d 100644 --- a/arch/arm/boot/dts/am335x-shc.dts +++ b/arch/arm/boot/dts/am335x-shc.dts @@ -138,7 +138,7 @@ &epwmss1 { status = "okay"; - ehrpwm1: ehrpwm@48302200 { + ehrpwm1: pwm@48302200 { pinctrl-names = "default"; pinctrl-0 = <&ehrpwm1_pins>; status = "okay"; diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 55ca9c7dcf6a..b3f9c48492db 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -688,7 +688,7 @@ status = "disabled"; }; - ehrpwm0: ehrpwm@48300200 { + ehrpwm0: pwm@48300200 { compatible = "ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48300200 0x80>; @@ -718,7 +718,7 @@ status = "disabled"; }; - ehrpwm1: ehrpwm@48302200 { + ehrpwm1: pwm@48302200 { compatible = "ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48302200 0x80>; @@ -748,7 +748,7 @@ status = "disabled"; }; - ehrpwm2: ehrpwm@48304200 { + ehrpwm2: pwm@48304200 { compatible = "ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48304200 0x80>; diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 6e4f5af3d8f8..a979e44ac94c 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -679,7 +679,7 @@ status = "disabled"; }; - ehrpwm0: ehrpwm@48300200 { + ehrpwm0: pwm@48300200 { compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48300200 0x80>; @@ -705,7 +705,7 @@ status = "disabled"; }; - ehrpwm1: ehrpwm@48302200 { + ehrpwm1: pwm@48302200 { compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48302200 0x80>; @@ -731,7 +731,7 @@ status = "disabled"; }; - ehrpwm2: ehrpwm@48304200 { + ehrpwm2: pwm@48304200 { compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48304200 0x80>; @@ -749,7 +749,7 @@ ti,hwmods = "epwmss3"; status = "disabled"; - ehrpwm3: ehrpwm@48306200 { + ehrpwm3: pwm@48306200 { compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48306200 0x80>; @@ -767,7 +767,7 @@ ti,hwmods = "epwmss4"; status = "disabled"; - ehrpwm4: ehrpwm@48308200 { + ehrpwm4: pwm@48308200 { compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x48308200 0x80>; @@ -785,7 +785,7 @@ ti,hwmods = "epwmss5"; status = "disabled"; - ehrpwm5: ehrpwm@4830a200 { + ehrpwm5: pwm@4830a200 { compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x4830a200 0x80>; diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index 226cda76e77c..c3910e285dde 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -247,13 +247,13 @@ dma-names = "rx", "tx"; status = "disabled"; }; - ehrpwm0: ehrpwm@01f00000 { + ehrpwm0: pwm@01f00000 { compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x300000 0x2000>; status = "disabled"; }; - ehrpwm1: ehrpwm@01f02000 { + ehrpwm1: pwm@01f02000 { compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x302000 0x2000>; -- GitLab From 2061d74d38cbc94ebabede7e2ac196afa12ce6c4 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 23 Mar 2016 09:04:13 +0530 Subject: [PATCH 2274/9938] ARM: dts: am335x: Add initial support for ICEv2 board TI's Industrial Communication Engine EVM is a low cost hardware mainly developed for industrial communication type applications using serial or Ethernet based interfaces. This platform features TI's AM3359 with 800MHz single core Cortex-A8 processor, 256MB DDR3, 64MB SPI flash, 8MB NOR Flash, mmc, usb, can, dual Ethernet ports. For more information, look at HW user guide[1], Data manual[2]. Just add basic support for the moment. [1] http://processors.wiki.ti.com/index.php/AM335x_Industrial_Communication_Engine_EVM_Rev2_1_HW_User_Guide [2] http://www.ti.com/lit/ds/symlink/am3359.pdf Signed-off-by: Lokesh Vutla Reviewed-by: Grygorii Strashko Signed-off-by: Tony Lindgren --- .../devicetree/bindings/arm/omap/omap.txt | 3 + arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/am335x-icev2.dts | 306 ++++++++++++++++++ 3 files changed, 310 insertions(+) create mode 100644 arch/arm/boot/dts/am335x-icev2.dts diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt index 21e71a5e866e..20f6d71b59a7 100644 --- a/Documentation/devicetree/bindings/arm/omap/omap.txt +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -133,6 +133,9 @@ Boards: - AM335X Bone : Low cost community board compatible = "ti,am335x-bone", "ti,am33xx", "ti,omap3" +- AM3359 ICEv2 : Low cost Industrial Communication Engine EVM. + compatible = "ti,am3359-icev2", "ti,am33xx", "ti,omap3" + - AM335X OrionLXm : Substation Automation Platform compatible = "novatech,am335x-lxm", "ti,am33xx" diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..9e560f310ad5 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -494,6 +494,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \ am335x-cm-t335.dtb \ am335x-evm.dtb \ am335x-evmsk.dtb \ + am335x-icev2.dtb \ am335x-lxm.dtb \ am335x-nano.dtb \ am335x-pepper.dtb \ diff --git a/arch/arm/boot/dts/am335x-icev2.dts b/arch/arm/boot/dts/am335x-icev2.dts new file mode 100644 index 000000000000..e271013e78a6 --- /dev/null +++ b/arch/arm/boot/dts/am335x-icev2.dts @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * AM335x ICE V2 board + * http://www.ti.com/tool/tmdsice3359 + */ + +/dts-v1/; + +#include "am33xx.dtsi" + +/ { + model = "TI AM3359 ICE-V2"; + compatible = "ti,am3359-icev2", "ti,am33xx"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + vtt_fixed: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "vtt"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + gpio = <&gpio0 18 GPIO_ACTIVE_HIGH>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + }; + + leds@0 { + compatible = "gpio-leds"; + + led@0 { + label = "out0"; + gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@1 { + label = "out1"; + gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@2 { + label = "out2"; + gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@3 { + label = "out3"; + gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@4 { + label = "out4"; + gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@5 { + label = "out5"; + gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@6 { + label = "out6"; + gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@7 { + label = "out7"; + gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + /* Tricolor status LEDs */ + leds@1 { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&user_leds>; + + led@0 { + label = "status0:red:cpu0"; + gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "cpu0"; + }; + + led@1 { + label = "status0:green:usr"; + gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@2 { + label = "status0:yellow:usr"; + gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@3 { + label = "status1:red:mmc0"; + gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc0"; + }; + + led@4 { + label = "status1:green:usr"; + gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@5 { + label = "status1:yellow:usr"; + gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; + +&am33xx_pinmux { + user_leds: user_leds { + pinctrl-single,pins = < + AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */ + AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */ + AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] */ + AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7) /* (D14) xdma_event_intr1.gpio0[20] */ + AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE7) /* (U9) gpmc_csn1.gpio1[30] */ + AM33XX_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] */ + >; + }; + + mmc0_pins_default: mmc0_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */ + AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */ + AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */ + AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */ + AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */ + AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */ + AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* (C15) spi0_cs1.mmc0_sdcd */ + >; + }; + + i2c0_pins_default: i2c0_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */ + AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */ + >; + }; + + spi0_pins_default: spi0_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */ + AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */ + AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */ + AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */ + >; + }; + + uart3_pins_default: uart3_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */ + AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLUP | MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */ + >; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_default>; + + status = "okay"; + clock-frequency = <400000>; + + tps: power-controller@2d { + reg = <0x2d>; + }; + + tpic2810: gpio@60 { + compatible = "ti,tpic2810"; + reg = <0x60>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1326000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1144000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_default>; +}; + +&gpio0 { + /* Do not idle the GPIO used for holding the VTT regulator */ + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_default>; + status = "okay"; +}; -- GitLab From a7cac713f90a7f00601e67d34961c0417783b6db Mon Sep 17 00:00:00 2001 From: Schuyler Patton Date: Mon, 28 Mar 2016 11:35:09 -0500 Subject: [PATCH 2275/9938] ARM: dts: AM572x-IDK Initial Support The AM572x-IDK board is a board based on TI's AM5728 SOC which has a dual core 1.5GHz A15 processor. This board is a development platform for the Industrial market with: - 2GB of DDR3L - Dual 1Gbps Ethernet - HDMI, - PRU-ICSS - uSD - 16GB eMMC - CAN - RS-485 - PCIe - USB3.0 - Video Input Port - Industrial IO port and expansion connector The link to the data sheet and TRM can be found here: http://www.ti.com/product/AM5728 This patch creates a common dtsi file that will provide a common board dtsi file to define the nodes that are common to AM57xx (including the upcoming AM5718) IDK boards. Initial support is only for basic peripherals Signed-off-by: Schuyler Patton Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- .../devicetree/bindings/arm/omap/omap.txt | 3 + arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/am572x-idk.dts | 85 +++++ arch/arm/boot/dts/am57xx-idk-common.dtsi | 302 ++++++++++++++++++ 4 files changed, 391 insertions(+) create mode 100644 arch/arm/boot/dts/am572x-idk.dts create mode 100644 arch/arm/boot/dts/am57xx-idk-common.dtsi diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt index 20f6d71b59a7..94b57f247615 100644 --- a/Documentation/devicetree/bindings/arm/omap/omap.txt +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -172,6 +172,9 @@ Boards: - AM57XX SBC-AM57x compatible = "compulab,sbc-am57x", "compulab,cl-som-am57x", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7" +- AM5728 IDK + compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7" + - DRA742 EVM: Software Development Board for DRA742 compatible = "ti,dra7-evm", "ti,dra742", "ti,dra74", "ti,dra7" diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9e560f310ad5..832d28ee21bc 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -527,6 +527,7 @@ dtb-$(CONFIG_SOC_DRA7XX) += \ am57xx-beagle-x15.dtb \ am57xx-cl-som-am57x.dtb \ am57xx-sbc-am57x.dtb \ + am572x-idk.dtb \ dra7-evm.dtb \ dra72-evm.dtb dtb-$(CONFIG_ARCH_ORION5X) += \ diff --git a/arch/arm/boot/dts/am572x-idk.dts b/arch/arm/boot/dts/am572x-idk.dts new file mode 100644 index 000000000000..e3acb99703e1 --- /dev/null +++ b/arch/arm/boot/dts/am572x-idk.dts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; + +#include "dra74x.dtsi" +#include +#include +#include "am57xx-idk-common.dtsi" + +/ { + model = "TI AM5728 IDK"; + compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74", + "ti,dra7"; + + memory { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x80000000>; + }; + + extcon_usb2: extcon_usb2 { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>; + }; + + status-leds { + compatible = "gpio-leds"; + cpu0-led { + label = "status0:red:cpu0"; + gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "cpu0"; + }; + + usr0-led { + label = "status0:green:usr"; + gpios = <&gpio3 11 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + heartbeat-led { + label = "status0:blue:heartbeat"; + gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "heartbeat"; + }; + + cpu1-led { + label = "status1:red:cpu1"; + gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "cpu1"; + }; + + usr1-led { + label = "status1:green:usr"; + gpios = <&gpio7 23 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + mmc0-led { + label = "status1:blue:mmc0"; + gpios = <&gpio7 22 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc0"; + }; + }; +}; + +&omap_dwc3_2 { + extcon = <&extcon_usb2>; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&v3_3d>; + vmmc_aux-supply = <&ldo1_reg>; + bus-width = <4>; + cd-gpios = <&gpio6 27 0>; /* gpio 219 */ +}; diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi new file mode 100644 index 000000000000..2805b68f3e0b --- /dev/null +++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/ { + aliases { + rtc0 = &tps659038_rtc; + rtc1 = &rtc; + }; + + vmain: fixedregulator-vmain { + compatible = "regulator-fixed"; + regulator-name = "VMAIN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + v3_3d: fixedregulator-v3_3d { + compatible = "regulator-fixed"; + regulator-name = "V3_3D"; + vin-supply = <&smps9_reg>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + vtt_fixed: fixedregulator-vtt { + /* TPS51200 */ + compatible = "regulator-fixed"; + regulator-name = "vtt_fixed"; + vin-supply = <&v3_3d>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <400000>; + + tps659038: tps659038@58 { + compatible = "ti,tps659038"; + reg = <0x58>; + interrupts-extended = <&gpio6 16 IRQ_TYPE_LEVEL_HIGH + &dra7_pmx_core 0x418>; + #interrupt-cells = <2>; + interrupt-controller; + ti,system-power-controller; + + tps659038_pmic { + compatible = "ti,tps659038-pmic"; + regulators { + smps12_reg: smps12 { + /* VDD_MPU */ + vin-supply = <&vmain>; + regulator-name = "smps12"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps3_reg: smps3 { + /* VDD_DDR EMIF1 EMIF2 */ + vin-supply = <&vmain>; + regulator-name = "smps3"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + }; + + smps45_reg: smps45 { + /* VDD_DSPEVE on AM572 */ + /* VDD_IVA + VDD_DSP on AM571 */ + vin-supply = <&vmain>; + regulator-name = "smps45"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps6_reg: smps6 { + /* VDD_GPU */ + vin-supply = <&vmain>; + regulator-name = "smps6"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps7_reg: smps7 { + /* VDD_CORE */ + vin-supply = <&vmain>; + regulator-name = "smps7"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1150000>; + regulator-always-on; + regulator-boot-on; + }; + + smps8_reg: smps8 { + /* 5728 - VDD_IVAHD */ + /* 5718 - N.C. test point */ + vin-supply = <&vmain>; + regulator-name = "smps8"; + }; + + smps9_reg: smps9 { + /* VDD_3_3D */ + vin-supply = <&vmain>; + regulator-name = "smps9"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo1_reg: ldo1 { + /* VDDSHV8 - VSDMMC */ + /* NOTE: on rev 1.3a, data supply */ + vin-supply = <&vmain>; + regulator-name = "ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2_reg: ldo2 { + /* VDDSH18V */ + vin-supply = <&vmain>; + regulator-name = "ldo2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo3_reg: ldo3 { + /* R1.3a 572x V1_8PHY_LDO3: USB, SATA */ + vin-supply = <&vmain>; + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo4_reg: ldo4 { + /* R1.3a 572x V1_8PHY_LDO4: PCIE, HDMI*/ + vin-supply = <&vmain>; + regulator-name = "ldo4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* LDO5-8 unused */ + + ldo9_reg: ldo9 { + /* VDD_RTC */ + vin-supply = <&vmain>; + regulator-name = "ldo9"; + regulator-min-microvolt = <840000>; + regulator-max-microvolt = <1160000>; + regulator-always-on; + regulator-boot-on; + }; + + ldoln_reg: ldoln { + /* VDDA_1V8_PLL */ + vin-supply = <&vmain>; + regulator-name = "ldoln"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldousb_reg: ldousb { + /* VDDA_3V_USB: VDDA_USBHS33 */ + vin-supply = <&vmain>; + regulator-name = "ldousb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + ldortc_reg: ldortc { + /* VDDA_RTC */ + vin-supply = <&vmain>; + regulator-name = "ldortc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + regen1: regen1 { + /* VDD_3V3_ON */ + regulator-name = "regen1"; + regulator-boot-on; + regulator-always-on; + }; + + regen2: regen2 { + /* Needed for PMIC internal resource */ + regulator-name = "regen2"; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + + tps659038_rtc: tps659038_rtc { + compatible = "ti,palmas-rtc"; + interrupt-parent = <&tps659038>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + }; + + tps659038_pwr_button: tps659038_pwr_button { + compatible = "ti,palmas-pwrbutton"; + interrupt-parent = <&tps659038>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + ti,palmas-long-press-seconds = <12>; + }; + + tps659038_gpio: tps659038_gpio { + compatible = "ti,palmas-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + }; +}; + +&uart3 { + status = "okay"; + interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH + &dra7_pmx_core 0x248>; +}; + +&rtc { + status = "okay"; + ext-clk-src; +}; + +&mac { + status = "okay"; + dual_emac; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <2>; +}; + +&usb2_phy1 { + phy-supply = <&ldousb_reg>; +}; + +&usb2_phy2 { + phy-supply = <&ldousb_reg>; +}; + +&usb1 { + dr_mode = "host"; +}; + +&usb2 { + dr_mode = "otg"; +}; + +&mmc2 { + status = "okay"; + vmmc-supply = <&v3_3d>; + bus-width = <8>; + ti,non-removable; + max-frequency = <96000000>; +}; -- GitLab From 5e0884a48672616e856ae344fca53174258c6ab7 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Tue, 29 Mar 2016 12:08:08 +0200 Subject: [PATCH 2276/9938] ARM: dts: am335x-baltos-ir5221: use dedicated RTS/CTS signals Before "tty: Add software emulated RS485 support for 8250" patch Baltos devices relied on MCTRL_GPIO framework to handle both modem signals and RS485 mode. With emulated RS485 support for 8250 we can now use these pins as dedicated RTS/CTS signals taking advantage of hardware flow control etc. when operating in RS232 mode. Signed-off-by: Yegor Yefremov Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-baltos-ir5221.dts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts index 6c667fb35449..f2ad35e73859 100644 --- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts +++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts @@ -109,8 +109,8 @@ pinctrl-single,pins = < AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd */ AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0) /* uart1_txd */ - AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE7) /* uart1_ctsn, INPUT | MODE0 */ - AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart1_rtsn, OUTPUT | MODE0 */ + AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart1_ctsn */ + AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn */ AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.gpio2[22] DTR */ AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2[23] DSR */ AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.gpio2[24] DCD */ @@ -122,8 +122,8 @@ pinctrl-single,pins = < AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd_mux3 */ AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd_mux3 */ - AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE7) /* i2c0_sda.uart2_ctsn_mux0 */ - AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* i2c0_scl.uart2_rtsn_mux0 */ + AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2) /* i2c0_sda.uart2_ctsn_mux0 */ + AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* i2c0_scl.uart2_rtsn_mux0 */ AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.gpio1[12] DTR */ AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.gpio1[13] DSR */ AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.gpio1[14] DCD */ @@ -287,8 +287,6 @@ dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>; rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; - cts-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; - rts-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; status = "okay"; }; @@ -300,8 +298,6 @@ dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; - cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>; - rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; status = "okay"; }; -- GitLab From da843ad0f332d42132b64d204bc2b8e03f173107 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 29 Mar 2016 21:28:23 +0200 Subject: [PATCH 2277/9938] devicetree: bindings: Add vendor prefix for Amazon.com, Inc. This adds the amazon vendor prefix for Amazon.com, Inc. Signed-off-by: Paul Kocialkowski Acked-by: Rob Herring Signed-off-by: Tony Lindgren --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 86740d4a270d..54b647c78550 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -16,6 +16,7 @@ al Annapurna Labs allwinner Allwinner Technology Co., Ltd. alphascale AlphaScale Integrated Circuits Systems, Inc. altr Altera Corp. +amazon Amazon.com, Inc. amcc Applied Micro Circuits Corporation (APM, formally AMCC) amd Advanced Micro Devices (AMD), Inc. amlogic Amlogic, Inc. -- GitLab From f81ad0544749f6c6cfa2fb48b752d5654fe5f5fb Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 29 Mar 2016 21:28:24 +0200 Subject: [PATCH 2278/9938] ARM: dts: Amazon Kindle Fire (first generation) codename kc1 basic support The Amazon Kindle Fire (first generation) codename kc1 is a tablet that was released by Amazon back in 2011. It is using an OMAP4430 SoC GP version. This adds devicetree support for the device, with only a few basic features supported, such as debug uart, i2c and internal emmc. Signed-off-by: Paul Kocialkowski Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/omap4-kc1.dts | 140 ++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 arch/arm/boot/dts/omap4-kc1.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 832d28ee21bc..a721c4cc3548 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -504,6 +504,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \ am335x-wega-rdk.dtb dtb-$(CONFIG_ARCH_OMAP4) += \ omap4-duovero-parlor.dtb \ + omap4-kc1.dtb \ omap4-panda.dtb \ omap4-panda-a4.dtb \ omap4-panda-es.dtb \ diff --git a/arch/arm/boot/dts/omap4-kc1.dts b/arch/arm/boot/dts/omap4-kc1.dts new file mode 100644 index 000000000000..9fe4441b815c --- /dev/null +++ b/arch/arm/boot/dts/omap4-kc1.dts @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +/dts-v1/; + +#include "omap443x.dtsi" + +/ { + model = "Amazon Kindle Fire (first generation)"; + compatible = "amazon,omap4-kc1", "ti,omap4430", "ti,omap4"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x20000000>; /* 512 MB */ + }; +}; + +&omap4_pmx_core { + pinctrl-names = "default"; + + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x144, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx */ + OMAP4_IOPAD(0x146, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ + OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ + OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ + >; + }; + + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ + OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ + >; + }; + + i2c4_pins: pinmux_i2c4_pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_scl */ + OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ + >; + }; + + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x040, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat0 */ + OMAP4_IOPAD(0x042, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat1 */ + OMAP4_IOPAD(0x044, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat2 */ + OMAP4_IOPAD(0x046, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat3 */ + OMAP4_IOPAD(0x048, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat4 */ + OMAP4_IOPAD(0x04a, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat5 */ + OMAP4_IOPAD(0x04c, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat6 */ + OMAP4_IOPAD(0x04e, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat7 */ + OMAP4_IOPAD(0x082, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_clk */ + OMAP4_IOPAD(0x084, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_cmd */ + >; + }; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + + interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH + &omap4_pmx_core OMAP4_UART3_RX>; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + clock-frequency = <400000>; + + twl: twl@48 { + reg = <0x48>; + /* IRQ# = 7 */ + interrupts = ; /* IRQ_SYS_1N cascaded to gic */ + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + + clock-frequency = <400000>; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + + clock-frequency = <400000>; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins>; + + clock-frequency = <400000>; +}; + +&mmc1 { + status = "disabled"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + + vmmc-supply = <&vaux1>; + ti,non-removable; + bus-width = <8>; +}; + +&mmc3 { + status = "disabled"; +}; + +&mmc4 { + status = "disabled"; +}; + +#include "twl6030.dtsi" +#include "twl6030_omap4.dtsi" -- GitLab From abb68f64ce34e7665f88e4c3f0bcd94f3d7a743c Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 29 Mar 2016 21:28:25 +0200 Subject: [PATCH 2279/9938] ARM: dts: omap4-kc1: USB OTG support This adds support for USB OTG on the Kindle Fire (first generation). Signed-off-by: Paul Kocialkowski Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4-kc1.dts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm/boot/dts/omap4-kc1.dts b/arch/arm/boot/dts/omap4-kc1.dts index 9fe4441b815c..0d08f9fddd3e 100644 --- a/arch/arm/boot/dts/omap4-kc1.dts +++ b/arch/arm/boot/dts/omap4-kc1.dts @@ -71,6 +71,14 @@ OMAP4_IOPAD(0x084, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_cmd */ >; }; + + usb_otg_hs_pins: pinmux_usb_otg_hs_pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x194, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usba0_otg_ce */ + OMAP4_IOPAD(0x196, PIN_INPUT | MUX_MODE0) /* usba0_otg_dp */ + OMAP4_IOPAD(0x198, PIN_INPUT | MUX_MODE0) /* usba0_otg_dm */ + >; + }; }; &uart3 { @@ -136,5 +144,18 @@ status = "disabled"; }; +&usb_otg_hs { + pinctrl-names = "default"; + pinctrl-0 = <&usb_otg_hs_pins>; + + interface-type = <1>; + mode = <3>; + power = <50>; +}; + #include "twl6030.dtsi" #include "twl6030_omap4.dtsi" + +&twl_usb_comparator { + usb-supply = <&vusb>; +}; -- GitLab From ab8e2f8c5d15f070a8cba2e0593ede5ef54d25b5 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 29 Mar 2016 21:28:26 +0200 Subject: [PATCH 2280/9938] ARM: dts: omap4-kc1: LEDs support This adds support for the Kindle Fire (first generation) power button LEDs, that are wired to the TWL6030 PWM outputs. Signed-off-by: Paul Kocialkowski Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4-kc1.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/omap4-kc1.dts b/arch/arm/boot/dts/omap4-kc1.dts index 0d08f9fddd3e..3681414232ed 100644 --- a/arch/arm/boot/dts/omap4-kc1.dts +++ b/arch/arm/boot/dts/omap4-kc1.dts @@ -17,6 +17,22 @@ device_type = "memory"; reg = <0x80000000 0x20000000>; /* 512 MB */ }; + + pwmleds { + compatible = "pwm-leds"; + + green { + label = "green"; + pwms = <&twl_pwm 0 7812500>; + max-brightness = <127>; + }; + + orange { + label = "orange"; + pwms = <&twl_pwm 1 7812500>; + max-brightness = <127>; + }; + }; }; &omap4_pmx_core { -- GitLab From 354fe2e74b3be653f2a0a850a9bce437c5f9bddb Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 29 Mar 2016 21:28:27 +0200 Subject: [PATCH 2281/9938] ARM: dts: omap4-kc1: Power off support This adds support for turning off the main power supply via the TWL6030 on the Kindle Fire (first generation). Signed-off-by: Paul Kocialkowski Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4-kc1.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/omap4-kc1.dts b/arch/arm/boot/dts/omap4-kc1.dts index 3681414232ed..2251bd54e4e6 100644 --- a/arch/arm/boot/dts/omap4-kc1.dts +++ b/arch/arm/boot/dts/omap4-kc1.dts @@ -115,6 +115,11 @@ reg = <0x48>; /* IRQ# = 7 */ interrupts = ; /* IRQ_SYS_1N cascaded to gic */ + + twl_power: power { + compatible = "ti,twl6030-power"; + ti,system-power-controller; + }; }; }; -- GitLab From ffee5bf3186ef5226d2202c6142c74af74dfa88b Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:28 +0300 Subject: [PATCH 2282/9938] ARM: dts: omap24xx: Enable gpio and interrupt controller for GPMC GPMC driver provides interrupts and gpio for the GPMC_WAIT pins. Mark it as gpio and interrupt capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap2420.dtsi | 4 ++++ arch/arm/boot/dts/omap2430.dtsi | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi index 5b9a376cc31e..fb712b9aa874 100644 --- a/arch/arm/boot/dts/omap2420.dtsi +++ b/arch/arm/boot/dts/omap2420.dtsi @@ -130,6 +130,10 @@ gpmc,num-cs = <8>; gpmc,num-waitpins = <4>; ti,hwmods = "gpmc"; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; }; mcbsp1: mcbsp@48074000 { diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi index 59828b0e34f1..455aaea407dd 100644 --- a/arch/arm/boot/dts/omap2430.dtsi +++ b/arch/arm/boot/dts/omap2430.dtsi @@ -154,6 +154,10 @@ gpmc,num-cs = <8>; gpmc,num-waitpins = <4>; ti,hwmods = "gpmc"; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; }; mcbsp1: mcbsp@48074000 { -- GitLab From 8c75b766010c6fdca7a213f6b384fdfa02e2636a Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:29 +0300 Subject: [PATCH 2283/9938] ARM: dts: omap4: Enable gpio and interrupt controller for GPMC GPMC driver provides interrupts and gpio for the GPMC_WAIT pins. Mark it as gpio and interrupt capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 2d8e95661e0b..6ca61a2f3642 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -370,6 +370,10 @@ ti,no-idle-on-init; clocks = <&l3_div_ck>; clock-names = "fck"; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; }; uart1: serial@4806a000 { -- GitLab From e99d413fab9e7d08aa84acfdf1fb456c2a177bc6 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:30 +0300 Subject: [PATCH 2284/9938] ARM: dts: omap5: Enable gpio and interrupt controller for GPMC GPMC driver provides interrupts and gpio for the GPMC_WAIT pins. Mark it as gpio and interrupt capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index b2297a560825..ca1db07330f4 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -398,6 +398,10 @@ ti,hwmods = "gpmc"; clocks = <&l3_iclk_div>; clock-names = "fck"; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; }; i2c1: i2c@48070000 { -- GitLab From 845b1a260c75285641653aca8d4df0f1c6f3fab4 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:31 +0300 Subject: [PATCH 2285/9938] ARM: dts: dra7: Enable gpio controller for GPMC GPMC driver provides GPI support for the GPMC_WAIT pins. Mark it gpio controller capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index ee92eed58b58..e0074014385a 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -1457,6 +1457,8 @@ #size-cells = <1>; interrupt-controller; #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; status = "disabled"; }; -- GitLab From 4eb4dd570d177e8e17b607241b23a4008bd877e8 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:32 +0300 Subject: [PATCH 2286/9938] ARM: dts: am335x: Enable gpio controller for GPMC GPMC driver provides GPI support for the GPMC_WAIT pins. Mark it gpio controller capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index b3f9c48492db..63e333a80a24 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -868,6 +868,8 @@ #size-cells = <1>; interrupt-controller; #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; status = "disabled"; }; -- GitLab From 9e08c2da4234385dd26a567675beaf056b49f4ce Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:33 +0300 Subject: [PATCH 2287/9938] ARM: dts: am4372: Enable gpio controller for GPMC GPMC driver provides GPI support for the GPMC_WAIT pins. Mark it gpio controller capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index a979e44ac94c..e338c9f4c061 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -896,6 +896,8 @@ #size-cells = <1>; interrupt-controller; #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; status = "disabled"; }; -- GitLab From 94f56c8b82f4c7061f3152617fc8433e6a1b15cb Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:34 +0300 Subject: [PATCH 2288/9938] ARM: dts: omap3: Enable gpio controller for GPMC GPMC driver provides GPI support for the GPMC_WAIT pins. Mark it gpio controller capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index e31ea5efb163..9fbda38528dc 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -725,6 +725,8 @@ #size-cells = <1>; interrupt-controller; #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; }; usb_otg_hs: usb_otg_hs@480ab000 { -- GitLab From 0cac398b2b5d4e62b660857e103194bb1cac136c Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:35 +0300 Subject: [PATCH 2289/9938] ARM: dts: dm814x: Enable gpio controller for GPMC GPMC driver provides GPI support for the GPMC_WAIT pins. Mark it gpio controller capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dm814x.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/dm814x.dtsi b/arch/arm/boot/dts/dm814x.dtsi index 4a6ce8c8bf8f..d4537dc61497 100644 --- a/arch/arm/boot/dts/dm814x.dtsi +++ b/arch/arm/boot/dts/dm814x.dtsi @@ -568,6 +568,8 @@ #size-cells = <1>; interrupt-controller; #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; }; }; }; -- GitLab From 8675afe574049ed3f7b0874cd365cc0118a0749a Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:36 +0300 Subject: [PATCH 2290/9938] ARM: dts: dm816x: Enable gpio controller for GPMC GPMC driver provides GPI support for the GPMC_WAIT pins. Mark it gpio controller capable. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dm816x.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/dm816x.dtsi b/arch/arm/boot/dts/dm816x.dtsi index d9309a016117..44e39c743b53 100644 --- a/arch/arm/boot/dts/dm816x.dtsi +++ b/arch/arm/boot/dts/dm816x.dtsi @@ -185,6 +185,8 @@ gpmc,num-waitpins = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; }; i2c1: i2c@48028000 { -- GitLab From a23fc15584871ad5a5b6621768a2b17b645ff22d Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:37 +0300 Subject: [PATCH 2291/9938] ARM: dts: dra7x-evm: Provide NAND ready pin On these boards NAND ready pin status is avilable over GPMC_WAIT0 pin. Read speed increases from 13768 KiB/ to 17246 KiB/s. Write speed was unchanged at 7123 KiB/s. Measured using mtd_speedtest.ko. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7-evm.dts | 1 + arch/arm/boot/dts/dra72-evm.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 7fda602868d7..d272cf140197 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -776,6 +776,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */ ti,nand-ecc-opt = "bch8"; ti,elm-id = <&elm>; nand-bus-width = <16>; diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index 4bd639b9ff91..3e63f660cd7c 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts @@ -503,6 +503,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */ ti,nand-ecc-opt = "bch8"; ti,elm-id = <&elm>; nand-bus-width = <16>; -- GitLab From 99a4101182d6107af869fb6d41cb375c717c66ad Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:38 +0300 Subject: [PATCH 2292/9938] ARM: dts: am437x: Provide NAND ready pin On these boards NAND ready pin status is avilable over GPMC_WAIT0 pin. For NAND we don't use GPMC wait pin monitoring but get the NAND Ready/Busy# status using GPIOlib. GPMC driver provides the WAIT0 pin status over GPIOlib. Read speed increases from 16516 KiB/ to 18813 KiB/s and write speed was unchanged at 9941 KiB/s. Measured using mtd_speedtest.ko. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-gp-evm.dts | 1 + arch/arm/boot/dts/am43x-epos-evm.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index 95ec82a77e67..5bcd3aa025bc 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -817,6 +817,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ ti,nand-ecc-opt = "bch16"; ti,elm-id = <&elm>; nand-bus-width = <8>; diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index d7978236ccad..965d548037ef 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -568,6 +568,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ ti,nand-ecc-opt = "bch16"; ti,elm-id = <&elm>; nand-bus-width = <8>; -- GitLab From 63015d73f345a9196e910b84c3f329a22556bcf4 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:39 +0300 Subject: [PATCH 2293/9938] ARM: dts: am335x: Provide NAND ready pin On these boards NAND ready pin status is avilable over GPMC_WAIT0 pin. For NAND we don't use GPMC wait pin monitoring but get the NAND Ready/Busy# status using GPIOlib. GPMC driver provides the WAIT0 pin status over GPIOlib. Read speed increases from 7869 KiB/ to 8875 KiB/s and write speed was unchanged at 5100 KiB/s. Measured using mtd_speedtest.ko on am335x-evm. Cc: Teresa Remmet Cc: Ilya Ledvich Cc: Yegor Yefremov Cc: Rostislav Lisovy Cc: Enric Balletbo i Serra Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-baltos-ir5221.dts | 1 + arch/arm/boot/dts/am335x-chilisom.dtsi | 1 + arch/arm/boot/dts/am335x-cm-t335.dts | 1 + arch/arm/boot/dts/am335x-evm.dts | 1 + arch/arm/boot/dts/am335x-igep0033.dtsi | 1 + arch/arm/boot/dts/am335x-phycore-som.dtsi | 1 + 6 files changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts index f2ad35e73859..c743d5db1064 100644 --- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts +++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts @@ -241,6 +241,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ nand-bus-width = <8>; ti,nand-ecc-opt = "bch8"; ti,nand-xfer-type = "polled"; diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/am335x-chilisom.dtsi index 95461a28bc98..e48c28236baa 100644 --- a/arch/arm/boot/dts/am335x-chilisom.dtsi +++ b/arch/arm/boot/dts/am335x-chilisom.dtsi @@ -214,6 +214,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ ti,nand-ecc-opt = "bch8"; ti,elm-id = <&elm>; nand-bus-width = <8>; diff --git a/arch/arm/boot/dts/am335x-cm-t335.dts b/arch/arm/boot/dts/am335x-cm-t335.dts index e835644c5054..817b1dec0683 100644 --- a/arch/arm/boot/dts/am335x-cm-t335.dts +++ b/arch/arm/boot/dts/am335x-cm-t335.dts @@ -411,6 +411,7 @@ status = "okay"; interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ ti,nand-ecc-opt = "bch8"; ti,elm-id = <&elm>; nand-bus-width = <8>; diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts index 28b916210271..516673bb023d 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/am335x-evm.dts @@ -524,6 +524,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ ti,nand-ecc-opt = "bch8"; ti,elm-id = <&elm>; nand-bus-width = <8>; diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi index 6c3a9bf3638a..df63484ef9b3 100644 --- a/arch/arm/boot/dts/am335x-igep0033.dtsi +++ b/arch/arm/boot/dts/am335x-igep0033.dtsi @@ -135,6 +135,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ nand-bus-width = <8>; ti,nand-ecc-opt = "bch8"; gpmc,device-width = <1>; diff --git a/arch/arm/boot/dts/am335x-phycore-som.dtsi b/arch/arm/boot/dts/am335x-phycore-som.dtsi index d4b7f3bd553f..86f773165d5c 100644 --- a/arch/arm/boot/dts/am335x-phycore-som.dtsi +++ b/arch/arm/boot/dts/am335x-phycore-som.dtsi @@ -171,6 +171,7 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ nand-bus-width = <8>; ti,nand-ecc-opt = "bch8"; gpmc,device-nand = "true"; -- GitLab From 4cb53a2308a96d97854b166780dace58737446ed Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 7 Apr 2016 13:25:40 +0300 Subject: [PATCH 2294/9938] ARM: dts: omap3-beagle: Provide NAND ready pin On these boards NAND ready pin status is avilable over GPMC_WAIT0 pin. For NAND we don't use GPMC wait pin monitoring but get the NAND Ready/Busy# status using GPIOlib. GPMC driver provides the WAIT0 pin status over GPIOlib. Read speed increases from 13212 KiB/ to 15753 KiB/s and write speed was unchanged at 4404 KiB/s. Measured using mtd_speedtest.ko on omap3-beagle-c4. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-beagle.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts index 4602866792be..a4deff0e2d52 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -390,6 +390,7 @@ interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ ti,nand-ecc-opt = "ham1"; + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ nand-bus-width = <16>; #address-cells = <1>; #size-cells = <1>; -- GitLab From 93e9d8e836cb1a9a58b33eb6643bf061c6119ef2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 12 Apr 2016 12:32:46 -0600 Subject: [PATCH 2295/9938] block: add ability to flag write back caching on a device Add an internal helper and flag for setting whether a queue has write back caching, or write through (or none). Add a sysfs file to show this as well, and make it changeable from user space. This will replace the (awkward) blk_queue_flush() interface that drivers currently use to inform the block layer of write cache state and capabilities. Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- Documentation/block/queue-sysfs.txt | 9 +++++++ block/blk-settings.c | 26 +++++++++++++++++++ block/blk-sysfs.c | 39 +++++++++++++++++++++++++++++ include/linux/blkdev.h | 3 +++ 4 files changed, 77 insertions(+) diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt index e5d914845be6..dce25d848d92 100644 --- a/Documentation/block/queue-sysfs.txt +++ b/Documentation/block/queue-sysfs.txt @@ -141,6 +141,15 @@ control of this block device to that new IO scheduler. Note that writing an IO scheduler name to this file will attempt to load that IO scheduler module, if it isn't already present in the system. +write_cache (RW) +---------------- +When read, this file will display whether the device has write back +caching enabled or not. It will return "write back" for the former +case, and "write through" for the latter. Writing to this file can +change the kernels view of the device, but it doesn't alter the +device state. This means that it might not be safe to toggle the +setting from "write back" to "write through", since that will also +eliminate cache flushes issued by the kernel. Jens Axboe , February 2009 diff --git a/block/blk-settings.c b/block/blk-settings.c index 331e4eee0dda..c903bee43cf8 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -846,6 +846,32 @@ void blk_queue_flush_queueable(struct request_queue *q, bool queueable) } EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); +/** + * blk_queue_write_cache - configure queue's write cache + * @q: the request queue for the device + * @wc: write back cache on or off + * @fua: device supports FUA writes, if true + * + * Tell the block layer about the write cache of @q. + */ +void blk_queue_write_cache(struct request_queue *q, bool wc, bool fua) +{ + spin_lock_irq(q->queue_lock); + if (wc) { + queue_flag_set(QUEUE_FLAG_WC, q); + q->flush_flags = REQ_FLUSH; + } else + queue_flag_clear(QUEUE_FLAG_WC, q); + if (fua) { + if (wc) + q->flush_flags |= REQ_FUA; + queue_flag_set(QUEUE_FLAG_FUA, q); + } else + queue_flag_clear(QUEUE_FLAG_FUA, q); + spin_unlock_irq(q->queue_lock); +} +EXPORT_SYMBOL_GPL(blk_queue_write_cache); + static int __init blk_settings_init(void) { blk_max_low_pfn = max_low_pfn - 1; diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 995b58d46ed1..99205965f559 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -347,6 +347,38 @@ static ssize_t queue_poll_store(struct request_queue *q, const char *page, return ret; } +static ssize_t queue_wc_show(struct request_queue *q, char *page) +{ + if (test_bit(QUEUE_FLAG_WC, &q->queue_flags)) + return sprintf(page, "write back\n"); + + return sprintf(page, "write through\n"); +} + +static ssize_t queue_wc_store(struct request_queue *q, const char *page, + size_t count) +{ + int set = -1; + + if (!strncmp(page, "write back", 10)) + set = 1; + else if (!strncmp(page, "write through", 13) || + !strncmp(page, "none", 4)) + set = 0; + + if (set == -1) + return -EINVAL; + + spin_lock_irq(q->queue_lock); + if (set) + queue_flag_set(QUEUE_FLAG_WC, q); + else + queue_flag_clear(QUEUE_FLAG_WC, q); + spin_unlock_irq(q->queue_lock); + + return count; +} + static struct queue_sysfs_entry queue_requests_entry = { .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, .show = queue_requests_show, @@ -478,6 +510,12 @@ static struct queue_sysfs_entry queue_poll_entry = { .store = queue_poll_store, }; +static struct queue_sysfs_entry queue_wc_entry = { + .attr = {.name = "write_cache", .mode = S_IRUGO | S_IWUSR }, + .show = queue_wc_show, + .store = queue_wc_store, +}; + static struct attribute *default_attrs[] = { &queue_requests_entry.attr, &queue_ra_entry.attr, @@ -503,6 +541,7 @@ static struct attribute *default_attrs[] = { &queue_iostats_entry.attr, &queue_random_entry.attr, &queue_poll_entry.attr, + &queue_wc_entry.attr, NULL, }; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bbaa76757018..ba72687c5654 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -491,6 +491,8 @@ struct request_queue { #define QUEUE_FLAG_INIT_DONE 20 /* queue is initialized */ #define QUEUE_FLAG_NO_SG_MERGE 21 /* don't attempt to merge SG segments*/ #define QUEUE_FLAG_POLL 22 /* IO polling enabled if set */ +#define QUEUE_FLAG_WC 23 /* Write back caching */ +#define QUEUE_FLAG_FUA 24 /* device supports FUA writes */ #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_STACKABLE) | \ @@ -1009,6 +1011,7 @@ extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); extern void blk_queue_flush(struct request_queue *q, unsigned int flush); extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable); +extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *); -- GitLab From 497fbe24987bd24ee271c67c212ec681995188b6 Mon Sep 17 00:00:00 2001 From: Shardar Shariff Md Date: Mon, 14 Mar 2016 18:52:18 +0530 Subject: [PATCH 2296/9938] i2c: tegra: enable multi master mode for tegra210 Enable multi-master mode in I2C_CNFG reg based on hw features. Using single/multi-master mode bit introduced for Tegra210, whereas multi-master mode is enabled by default in HW for T124 and earlier Tegra SOC. Enabling this bit doesn't explicitly start treating the bus has having multiple masters, but will start checking for arbitration lost and reporting when it occurs. The Tegra210 I2C controller supports single/multi master mode. Add chipdata for Tegra210 and its compatibility string so that Tegra210 will select data that enables multi master mode correctly. Do below prerequisites for multi-master bus if "multi-master" dt property entry is added. 1. Enable 1st level clock always set. 2. Disable 2nd level clock gating (slcg which is supported from T124 SOC and later chips) Signed-off-by: Shardar Shariff Md Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 74 +++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 929185a7296c..d764d64e9d2c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -38,6 +38,7 @@ #define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12 #define I2C_CNFG_PACKET_MODE_EN (1<<10) #define I2C_CNFG_NEW_MASTER_FSM (1<<11) +#define I2C_CNFG_MULTI_MASTER_MODE (1<<17) #define I2C_STATUS 0x01C #define I2C_SL_CNFG 0x020 #define I2C_SL_CNFG_NACK (1<<1) @@ -106,6 +107,9 @@ #define I2C_SLV_CONFIG_LOAD (1 << 1) #define I2C_TIMEOUT_CONFIG_LOAD (1 << 2) +#define I2C_CLKEN_OVERRIDE 0x090 +#define I2C_MST_CORE_CLKEN_OVR (1 << 0) + /* * msg_end_type: The bus control which need to be send at end of transfer. * @MSG_END_STOP: Send stop pulse at end of transfer. @@ -143,6 +147,8 @@ struct tegra_i2c_hw_feature { int clk_divisor_hs_mode; int clk_divisor_std_fast_mode; u16 clk_divisor_fast_plus_mode; + bool has_multi_master_mode; + bool has_slcg_override_reg; }; /** @@ -184,6 +190,7 @@ struct tegra_i2c_dev { u32 bus_clk_rate; u16 clk_divisor_non_hs_mode; bool is_suspended; + bool is_multimaster_mode; }; static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) @@ -438,6 +445,10 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN | (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); + + if (i2c_dev->hw->has_multi_master_mode) + val |= I2C_CNFG_MULTI_MASTER_MODE; + i2c_writel(i2c_dev, val, I2C_CNFG); i2c_writel(i2c_dev, 0, I2C_INT_MASK); @@ -463,6 +474,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (tegra_i2c_flush_fifos(i2c_dev)) err = -ETIMEDOUT; + if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg) + i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE); + if (i2c_dev->hw->has_config_load_reg) { i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); while (i2c_readl(i2c_dev, I2C_CONFIG_LOAD) != 0) { @@ -688,6 +702,20 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap) return ret; } +static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) +{ + struct device_node *np = i2c_dev->dev->of_node; + int ret; + + ret = of_property_read_u32(np, "clock-frequency", + &i2c_dev->bus_clk_rate); + if (ret) + i2c_dev->bus_clk_rate = 100000; /* default clock rate */ + + i2c_dev->is_multimaster_mode = of_property_read_bool(np, + "multi-master"); +} + static const struct i2c_algorithm tegra_i2c_algo = { .master_xfer = tegra_i2c_xfer, .functionality = tegra_i2c_func, @@ -707,6 +735,8 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { .clk_divisor_std_fast_mode = 0, .clk_divisor_fast_plus_mode = 0, .has_config_load_reg = false, + .has_multi_master_mode = false, + .has_slcg_override_reg = false, }; static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { @@ -717,6 +747,8 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { .clk_divisor_std_fast_mode = 0, .clk_divisor_fast_plus_mode = 0, .has_config_load_reg = false, + .has_multi_master_mode = false, + .has_slcg_override_reg = false, }; static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { @@ -727,6 +759,8 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { .clk_divisor_std_fast_mode = 0x19, .clk_divisor_fast_plus_mode = 0x10, .has_config_load_reg = false, + .has_multi_master_mode = false, + .has_slcg_override_reg = false, }; static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { @@ -737,10 +771,25 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { .clk_divisor_std_fast_mode = 0x19, .clk_divisor_fast_plus_mode = 0x10, .has_config_load_reg = true, + .has_multi_master_mode = false, + .has_slcg_override_reg = true, +}; + +static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { + .has_continue_xfer_support = true, + .has_per_pkt_xfer_complete_irq = true, + .has_single_clk_source = true, + .clk_divisor_hs_mode = 1, + .clk_divisor_std_fast_mode = 0x19, + .clk_divisor_fast_plus_mode = 0x10, + .has_config_load_reg = true, + .has_multi_master_mode = true, + .has_slcg_override_reg = true, }; /* Match table for of_platform binding */ static const struct of_device_id tegra_i2c_of_match[] = { + { .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, }, { .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, }, { .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, }, { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, @@ -797,10 +846,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) return PTR_ERR(i2c_dev->rst); } - ret = of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency", - &i2c_dev->bus_clk_rate); - if (ret) - i2c_dev->bus_clk_rate = 100000; /* default clock rate */ + tegra_i2c_parse_dt(i2c_dev); i2c_dev->hw = &tegra20_i2c_hw; @@ -853,6 +899,15 @@ static int tegra_i2c_probe(struct platform_device *pdev) goto unprepare_fast_clk; } + if (i2c_dev->is_multimaster_mode) { + ret = clk_enable(i2c_dev->div_clk); + if (ret < 0) { + dev_err(i2c_dev->dev, "div_clk enable failed %d\n", + ret); + goto unprepare_div_clk; + } + } + ret = tegra_i2c_init(i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to initialize i2c controller"); @@ -863,7 +918,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); - goto unprepare_div_clk; + goto disable_div_clk; } i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); @@ -878,11 +933,15 @@ static int tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(&i2c_dev->adapter); if (ret) { dev_err(&pdev->dev, "Failed to add I2C adapter\n"); - goto unprepare_div_clk; + goto disable_div_clk; } return 0; +disable_div_clk: + if (i2c_dev->is_multimaster_mode) + clk_disable(i2c_dev->div_clk); + unprepare_div_clk: clk_unprepare(i2c_dev->div_clk); @@ -898,6 +957,9 @@ static int tegra_i2c_remove(struct platform_device *pdev) struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adapter); + if (i2c_dev->is_multimaster_mode) + clk_disable(i2c_dev->div_clk); + clk_unprepare(i2c_dev->div_clk); if (!i2c_dev->hw->has_single_clk_source) clk_unprepare(i2c_dev->fast_clk); -- GitLab From eb310e23dbafa5f4010df37f35999622af2cf795 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:06:11 -0600 Subject: [PATCH 2297/9938] sd: switch to using blk_queue_write_cache() Switch to the newer interface, instead of using blk_queue_flush() directly. Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig Acked-by: Martin K. Petersen --- drivers/scsi/sd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 69b0a4a7a15f..428c03ef02b2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -137,15 +137,15 @@ static const char *sd_cache_types[] = { static void sd_set_flush_flag(struct scsi_disk *sdkp) { - unsigned flush = 0; + bool wc = false, fua = false; if (sdkp->WCE) { - flush |= REQ_FLUSH; + wc = true; if (sdkp->DPOFUA) - flush |= REQ_FUA; + fua = true; } - blk_queue_flush(sdkp->disk->queue, flush); + blk_queue_write_cache(sdkp->disk->queue, wc, fua); } static ssize_t -- GitLab From 7c88cb00f2a26637bade6c62a17d17f31a954e30 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 12 Apr 2016 15:43:09 -0600 Subject: [PATCH 2298/9938] NVMe: switch to using blk_queue_write_cache() Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 6631f38aebca..4eb575933587 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -999,6 +999,8 @@ EXPORT_SYMBOL_GPL(nvme_shutdown_ctrl); static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, struct request_queue *q) { + bool vwc = false; + if (ctrl->max_hw_sectors) { u32 max_segments = (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1; @@ -1008,9 +1010,10 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, } if (ctrl->stripe_size) blk_queue_chunk_sectors(q, ctrl->stripe_size >> 9); - if (ctrl->vwc & NVME_CTRL_VWC_PRESENT) - blk_queue_flush(q, REQ_FLUSH | REQ_FUA); blk_queue_virt_boundary(q, ctrl->page_size - 1); + if (ctrl->vwc & NVME_CTRL_VWC_PRESENT) + vwc = true; + blk_queue_write_cache(q, vwc, vwc); } /* -- GitLab From fe8fb75e3a1f6f7fac8dc68024eb0062191fe424 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:09:01 -0600 Subject: [PATCH 2299/9938] drbd: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/drbd/drbd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index fa209773d494..2ba1494b2799 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2761,7 +2761,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig q->backing_dev_info.congested_data = device; blk_queue_make_request(q, drbd_make_request); - blk_queue_flush(q, REQ_FLUSH | REQ_FUA); + blk_queue_write_cache(q, true, true); /* Setting the max_hw_sectors to an odd value of 8kibyte here This triggers a max_bio_size message upon first attach or connect */ blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8); -- GitLab From 21d0727f639e4ba2bd194b2eb9b38ac840bbbc87 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:09:35 -0600 Subject: [PATCH 2300/9938] loop: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 423f4ca7d712..7e5e27ac45bb 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -937,7 +937,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) - blk_queue_flush(lo->lo_queue, REQ_FLUSH); + blk_queue_write_cache(lo->lo_queue, true, false); loop_update_dio(lo); set_capacity(lo->lo_disk, size); -- GitLab From 17fe95f4605c3a2ec3df763876e3abf2eca790a7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 12 Apr 2016 15:45:39 -0600 Subject: [PATCH 2301/9938] mtip32xx: remove call to blk_queue_flush() The driver calls it with 0 for flags, since it doesn't have a writeback cache. Just remove the call, as it's a no-op right now. Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/mtip32xx/mtip32xx.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 404ae98b2fc4..6053e4659fa2 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -4023,12 +4023,6 @@ static int mtip_block_initialize(struct driver_data *dd) blk_queue_io_min(dd->queue, 4096); blk_queue_bounce_limit(dd->queue, dd->pdev->dma_mask); - /* - * write back cache is not supported in the device. FUA depends on - * write back cache support, hence setting flush support to zero. - */ - blk_queue_flush(dd->queue, 0); - /* Signal trim support */ if (dd->trim_supp == true) { set_bit(QUEUE_FLAG_DISCARD, &dd->queue->queue_flags); -- GitLab From aafb1eecbb79ac135fa8028f961596333ecbb80b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:10:53 -0600 Subject: [PATCH 2302/9938] nbd: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/nbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 08afbc7a2bb8..31e73a7a40f2 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -693,9 +693,9 @@ static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev) if (nbd->flags & NBD_FLAG_SEND_TRIM) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); if (nbd->flags & NBD_FLAG_SEND_FLUSH) - blk_queue_flush(nbd->disk->queue, REQ_FLUSH); + blk_queue_write_cache(nbd->disk->queue, true, false); else - blk_queue_flush(nbd->disk->queue, 0); + blk_queue_write_cache(nbd->disk->queue, false, false); } static int nbd_dev_dbg_init(struct nbd_device *nbd); -- GitLab From 177febc8430e0efa808caca721a59898c5422668 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:11:15 -0600 Subject: [PATCH 2303/9938] osdblk: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/osdblk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index 1b709a4e3b5e..c2854a2bfdb0 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c @@ -437,7 +437,7 @@ static int osdblk_init_disk(struct osdblk_device *osdev) blk_queue_stack_limits(q, osd_request_queue(osdev->osd)); blk_queue_prep_rq(q, blk_queue_start_tag); - blk_queue_flush(q, REQ_FLUSH); + blk_queue_write_cache(q, true, false); disk->queue = q; -- GitLab From 6975f7327f62b7c545aeada57c40ba018d66c93c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:11:42 -0600 Subject: [PATCH 2304/9938] skd_main: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/skd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 9a9ec212fab8..41aaae30c005 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -4412,7 +4412,7 @@ static int skd_cons_disk(struct skd_device *skdev) disk->queue = q; q->queuedata = skdev; - blk_queue_flush(q, REQ_FLUSH | REQ_FUA); + blk_queue_write_cache(q, true, true); blk_queue_max_segments(q, skdev->sgs_per_request); blk_queue_max_hw_sectors(q, SKD_N_MAX_SECTORS); -- GitLab From 12c95f137d09450b2c2e86fb12da5c7cf585b322 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:12:13 -0600 Subject: [PATCH 2305/9938] ps3disk: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/ps3disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index c120d70d3fb3..4b7e405830d7 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -468,7 +468,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) blk_queue_dma_alignment(queue, dev->blk_size-1); blk_queue_logical_block_size(queue, dev->blk_size); - blk_queue_flush(queue, REQ_FLUSH); + blk_queue_write_cache(queue, true, false); blk_queue_max_segments(queue, -1); blk_queue_max_segment_size(queue, dev->bounce_size); -- GitLab From ad9126ac723f9e8ed900194d226a0608ffeae45e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:12:58 -0600 Subject: [PATCH 2306/9938] virtio_blk: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/virtio_blk.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 28cff0d23d82..42758b52768c 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -493,11 +493,7 @@ static void virtblk_update_cache_mode(struct virtio_device *vdev) u8 writeback = virtblk_get_cache_mode(vdev); struct virtio_blk *vblk = vdev->priv; - if (writeback) - blk_queue_flush(vblk->disk->queue, REQ_FLUSH); - else - blk_queue_flush(vblk->disk->queue, 0); - + blk_queue_write_cache(vblk->disk->queue, writeback, false); revalidate_disk(vblk->disk); } -- GitLab From 84b4ff9ef22a97231e5d6aeca544a243d0ac5d81 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:13:22 -0600 Subject: [PATCH 2307/9938] bcache: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/md/bcache/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index a296425a7270..f5dbb4e884d8 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -816,7 +816,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size, clear_bit(QUEUE_FLAG_ADD_RANDOM, &d->disk->queue->queue_flags); set_bit(QUEUE_FLAG_DISCARD, &d->disk->queue->queue_flags); - blk_queue_flush(q, REQ_FLUSH|REQ_FUA); + blk_queue_write_cache(q, true, true); return 0; } -- GitLab From 519a7e16f9bea99c77fbf549c4b3ef7916199a33 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:14:14 -0600 Subject: [PATCH 2308/9938] dm: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/md/dm-table.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index f9e8f0bef332..4b1ffc0abe11 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1506,7 +1506,7 @@ static bool dm_table_supports_discards(struct dm_table *t) void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits) { - unsigned flush = 0; + bool wc = false, fua = false; /* * Copy table's limits to the DM device's request_queue @@ -1519,11 +1519,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); if (dm_table_supports_flush(t, REQ_FLUSH)) { - flush |= REQ_FLUSH; + wc = true; if (dm_table_supports_flush(t, REQ_FUA)) - flush |= REQ_FUA; + fua = true; } - blk_queue_flush(q, flush); + blk_queue_write_cache(q, wc, fua); if (!dm_table_discard_zeroes_data(t)) q->limits.discard_zeroes_data = 0; -- GitLab From bfd230ac4e592f3c03cabdf1e69f170a70aaeef7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:15:21 -0600 Subject: [PATCH 2309/9938] xen-blkfront: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/block/xen-blkfront.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 6405b6557792..ca13df854639 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -998,7 +998,8 @@ static const char *flush_info(unsigned int feature_flush) static void xlvbd_flush(struct blkfront_info *info) { - blk_queue_flush(info->rq, info->feature_flush); + blk_queue_write_cache(info->rq, info->feature_flush & REQ_FLUSH, + info->feature_flush & REQ_FUA); pr_info("blkfront: %s: %s %s %s %s %s\n", info->gd->disk_name, flush_info(info->feature_flush), "persistent grants:", info->feature_persistent ? -- GitLab From a98239dec6b20cff7b10b670c5d650538f8c3bcb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:16:25 -0600 Subject: [PATCH 2310/9938] ide-disk: update to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/ide/ide-disk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 37a8a907febe..05dbcce70b0e 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -522,7 +522,7 @@ static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect) static void update_flush(ide_drive_t *drive) { u16 *id = drive->id; - unsigned flush = 0; + bool wc = false; if (drive->dev_flags & IDE_DFLAG_WCACHE) { unsigned long long capacity; @@ -546,12 +546,12 @@ static void update_flush(ide_drive_t *drive) drive->name, barrier ? "" : "not "); if (barrier) { - flush = REQ_FLUSH; + wc = true; blk_queue_prep_rq(drive->queue, idedisk_prep_fn); } } - blk_queue_flush(drive->queue, flush); + blk_queue_write_cache(drive->queue, wc, false); } ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE); -- GitLab From 56883a7ec85f5bc2da7eca67905de54a475daebc Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:16:53 -0600 Subject: [PATCH 2311/9938] md: update to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 194580fba7fd..5d61e76cec34 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5037,7 +5037,7 @@ static int md_alloc(dev_t dev, char *name) disk->fops = &md_fops; disk->private_data = mddev; disk->queue = mddev->queue; - blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA); + blk_queue_write_cache(mddev->queue, true, true); /* Allow extended partitions. This makes the * 'mdp' device redundant, but we can't really * remove it now. -- GitLab From e9d5c746246c88a891b0ed21980535909cb39af7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:17:20 -0600 Subject: [PATCH 2312/9938] mmc/block: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/mmc/card/block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 3bdbe50a363f..32daf433a9fb 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2286,7 +2286,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || card->ext_csd.rel_sectors)) { md->flags |= MMC_BLK_REL_WR; - blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA); + blk_queue_write_cache(md->queue.queue, true, true); } if (mmc_card_mmc(card) && -- GitLab From fec3ff5d1eef8d81b2922deb4eb5a5e84a93bf4c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:17:47 -0600 Subject: [PATCH 2313/9938] mtd: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- drivers/mtd/mtd_blkdevs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index f4701182b558..74ae24364a8d 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -409,7 +409,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) goto error3; if (tr->flush) - blk_queue_flush(new->rq, REQ_FLUSH); + blk_queue_write_cache(new->rq, true, false); new->rq->queuedata = new; blk_queue_logical_block_size(new->rq, tr->blksize); -- GitLab From f935a8ce0a60acf0a7fe4da8d2a1e5a70c598e55 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:19:17 -0600 Subject: [PATCH 2314/9938] um: switch to using blk_queue_write_cache() Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- arch/um/drivers/ubd_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 39ba20755e03..17e96dc29596 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -862,7 +862,7 @@ static int ubd_add(int n, char **error_out) goto out; } ubd_dev->queue->queuedata = ubd_dev; - blk_queue_flush(ubd_dev->queue, REQ_FLUSH); + blk_queue_write_cache(ubd_dev->queue, true, false); blk_queue_max_segments(ubd_dev->queue, MAX_SG); err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, &ubd_gendisk[n]); -- GitLab From 2245f6de6c68b225986229a2de78c240536f7f38 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:19:30 -0600 Subject: [PATCH 2315/9938] block: kill blk_queue_flush() We don't have any drivers left using it, so kill it off. Update documentation to use the newer blk_queue_write_cache(). Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- .../block/writeback_cache_control.txt | 4 ++-- block/blk-settings.c | 20 ------------------- include/linux/blkdev.h | 1 - 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/Documentation/block/writeback_cache_control.txt b/Documentation/block/writeback_cache_control.txt index 83407d36630a..59e0516cbf6b 100644 --- a/Documentation/block/writeback_cache_control.txt +++ b/Documentation/block/writeback_cache_control.txt @@ -71,7 +71,7 @@ requests that have a payload. For devices with volatile write caches the driver needs to tell the block layer that it supports flushing caches by doing: - blk_queue_flush(sdkp->disk->queue, REQ_FLUSH); + blk_queue_write_cache(sdkp->disk->queue, true, false); and handle empty REQ_FLUSH requests in its prep_fn/request_fn. Note that REQ_FLUSH requests with a payload are automatically turned into a sequence @@ -79,7 +79,7 @@ of an empty REQ_FLUSH request followed by the actual write by the block layer. For devices that also support the FUA bit the block layer needs to be told to pass through the REQ_FUA bit using: - blk_queue_flush(sdkp->disk->queue, REQ_FLUSH | REQ_FUA); + blk_queue_write_cache(sdkp->disk->queue, true, true); and the driver must handle write requests that have the REQ_FUA bit set in prep_fn/request_fn. If the FUA bit is not natively supported the block diff --git a/block/blk-settings.c b/block/blk-settings.c index c903bee43cf8..80d9327a214b 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -820,26 +820,6 @@ void blk_queue_update_dma_alignment(struct request_queue *q, int mask) } EXPORT_SYMBOL(blk_queue_update_dma_alignment); -/** - * blk_queue_flush - configure queue's cache flush capability - * @q: the request queue for the device - * @flush: 0, REQ_FLUSH or REQ_FLUSH | REQ_FUA - * - * Tell block layer cache flush capability of @q. If it supports - * flushing, REQ_FLUSH should be set. If it supports bypassing - * write cache for individual writes, REQ_FUA should be set. - */ -void blk_queue_flush(struct request_queue *q, unsigned int flush) -{ - WARN_ON_ONCE(flush & ~(REQ_FLUSH | REQ_FUA)); - - if (WARN_ON_ONCE(!(flush & REQ_FLUSH) && (flush & REQ_FUA))) - flush &= ~REQ_FUA; - - q->flush_flags = flush & (REQ_FLUSH | REQ_FUA); -} -EXPORT_SYMBOL_GPL(blk_queue_flush); - void blk_queue_flush_queueable(struct request_queue *q, bool queueable) { q->flush_not_queueable = !queueable; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ba72687c5654..f3f232fa505d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1009,7 +1009,6 @@ extern void blk_queue_update_dma_alignment(struct request_queue *, int); extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); -extern void blk_queue_flush(struct request_queue *q, unsigned int flush); extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable); extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); -- GitLab From 7e19793096994d43d213f440f4bbea926828a727 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 12 Apr 2016 16:11:11 -0600 Subject: [PATCH 2316/9938] NVMe: silence warning about unused 'dev' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depending on options, we might not be using dev in nvme_cancel_io(): drivers/nvme/host/pci.c: In function ‘nvme_cancel_io’: drivers/nvme/host/pci.c:970:19: warning: unused variable ‘dev’ [-Wunused-variable] struct nvme_dev *dev = data; ^ So get rid of it, and just cast for the dev_dbg_ratelimited() call. Fixes: 82b4552b91c4 ("nvme: Use blk-mq helper for IO termination") Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index bd0d39482e83..36b6cdf22de3 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -967,13 +967,13 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved) static void nvme_cancel_io(struct request *req, void *data, bool reserved) { - struct nvme_dev *dev = data; int status; if (!blk_mq_request_started(req)) return; - dev_dbg_ratelimited(dev->ctrl.device, "Cancelling I/O %d", req->tag); + dev_dbg_ratelimited(((struct nvme_dev *) data)->ctrl.device, + "Cancelling I/O %d", req->tag); status = NVME_SC_ABORT_REQ; if (blk_queue_dying(req->q)) -- GitLab From 730628f00c906cb5a1ba44352bd8095295c74029 Mon Sep 17 00:00:00 2001 From: Yunhui Cui Date: Wed, 2 Mar 2016 13:52:15 +0800 Subject: [PATCH 2317/9938] arm64: dts: ls1043a-rdb: add the DTS for DSPI support This patch adds dts nodes for DSPI on LS1043A-RDB. Signed-off-by: Yunhui Cui Signed-off-by: Yuan Yao Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts index ce235577e90f..f895fc02ab06 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts @@ -107,6 +107,19 @@ }; }; +&dspi0 { + bus-num = <0>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13", "jedec,spi-nor"; /* 16MB */ + reg = <0>; + spi-max-frequency = <1000000>; /* input clock */ + }; +}; + &duart0 { status = "okay"; }; -- GitLab From 6f1060e338c2cbaf8df7e5a8609f43dfe497954b Mon Sep 17 00:00:00 2001 From: Yuan Yao Date: Wed, 9 Mar 2016 18:22:05 +0800 Subject: [PATCH 2318/9938] Documentation: fsl: dspi: Add fsl,ls2080a-dspi compatible string new compatible string: "fsl,ls2080a-dspi". Signed-off-by: Yuan Yao Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt index fa77f874e321..1ad0fe310ff9 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt @@ -1,7 +1,10 @@ ARM Freescale DSPI controller Required properties: -- compatible : "fsl,vf610-dspi", "fsl,ls1021a-v1.0-dspi", "fsl,ls2085a-dspi" +- compatible : "fsl,vf610-dspi", "fsl,ls1021a-v1.0-dspi", + "fsl,ls2085a-dspi" + or + "fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi" - reg : Offset and length of the register set for the device - interrupts : Should contain SPI controller interrupt - clocks: from common clock binding: handle to dspi clock. -- GitLab From b3f85aba7b87594213e728d13f6c325feea0b66b Mon Sep 17 00:00:00 2001 From: Yuan Yao Date: Wed, 9 Mar 2016 18:22:06 +0800 Subject: [PATCH 2319/9938] arm64: dts: ls2080a: update the DTS for QSPI and DSPI support Signed-off-by: Yuan Yao Acked-by: Han xu Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts | 9 ++++++++- arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts index 4cb996d6e686..e8801faca996 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts @@ -178,7 +178,14 @@ &qspi { status = "okay"; - qflash0: s25fl008k { + flash0: s25fl256s1@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p80"; + spi-max-frequency = <20000000>; + reg = <0>; + }; + flash2: s25fl256s1@2 { #address-cells = <1>; #size-cells = <1>; compatible = "st,m25p80"; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi index 9d746c69a789..eb2cc8554578 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi @@ -318,7 +318,7 @@ dspi: dspi@2100000 { status = "disabled"; - compatible = "fsl,vf610-dspi"; + compatible = "fsl,ls2080a-dspi", "fsl,ls2085a-dspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2100000 0x0 0x10000>; @@ -444,7 +444,7 @@ qspi: quadspi@20c0000 { status = "disabled"; - compatible = "fsl,vf610-qspi"; + compatible = "fsl,ls2080a-qspi", "fsl,ls1021a-qspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x20c0000 0x0 0x10000>, -- GitLab From 82500aa01ad12eff41a9a68ad01f1d40db8921f9 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:04 +0200 Subject: [PATCH 2320/9938] net: mediatek: watchdog_timeo was not set The original commit failed to set watchdog_timeo. This patch sets watchdog_timeo to HZ. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index e0b68afea56e..bb10d57c9999 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1645,6 +1645,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET; SET_NETDEV_DEV(eth->netdev[id], eth->dev); + eth->netdev[id]->watchdog_timeo = HZ; eth->netdev[id]->netdev_ops = &mtk_netdev_ops; eth->netdev[id]->base_addr = (unsigned long)eth->base; eth->netdev[id]->vlan_features = MTK_HW_FEATURES & -- GitLab From beeb4ca466fa1c399d69e34c30ddf04e0b7cbefd Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:05 +0200 Subject: [PATCH 2321/9938] net: mediatek: mtk_cal_txd_req() returns bad value The code used to also support the PDMA engine, which had 2 packet pointers per descriptor. Because of this we had to divide the result by 2 and round it up. This is no longer needed as the code only supports QDMA. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index bb10d57c9999..94cceb83b569 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -681,7 +681,7 @@ static inline int mtk_cal_txd_req(struct sk_buff *skb) nfrags += skb_shinfo(skb)->nr_frags; } - return DIV_ROUND_UP(nfrags, 2); + return nfrags; } static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) -- GitLab From 13439eec7af24b0800e654ee03c57ab985083ae4 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:06 +0200 Subject: [PATCH 2322/9938] net: mediatek: remove superfluous reset call HW reset is triggered in the mtk_hw_init() function. There is no need to also reset the core during probe. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 94cceb83b569..a4982e497ea6 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1679,10 +1679,6 @@ static int mtk_probe(struct platform_device *pdev) struct mtk_eth *eth; int err; - err = device_reset(&pdev->dev); - if (err) - return err; - match = of_match_device(of_mtk_match, &pdev->dev); soc = (struct mtk_soc_data *)match->data; -- GitLab From 13c822f6d468ca5a16da4d9432b067d54245c5b9 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:07 +0200 Subject: [PATCH 2323/9938] net: mediatek: fix stop and wakeup of queue The driver supports 2 MACs. Both run on the same DMA ring. If we go above/below the TX rings threshold value, we always need to wake/stop the queue of both devices. Not doing to can cause TX stalls and packet drops on one of the devices. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 37 +++++++++++++++------ 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index a4982e497ea6..4ebc42e0271a 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -684,6 +684,28 @@ static inline int mtk_cal_txd_req(struct sk_buff *skb) return nfrags; } +static void mtk_wake_queue(struct mtk_eth *eth) +{ + int i; + + for (i = 0; i < MTK_MAC_COUNT; i++) { + if (!eth->netdev[i]) + continue; + netif_wake_queue(eth->netdev[i]); + } +} + +static void mtk_stop_queue(struct mtk_eth *eth) +{ + int i; + + for (i = 0; i < MTK_MAC_COUNT; i++) { + if (!eth->netdev[i]) + continue; + netif_stop_queue(eth->netdev[i]); + } +} + static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct mtk_mac *mac = netdev_priv(dev); @@ -695,7 +717,7 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_num = mtk_cal_txd_req(skb); if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { - netif_stop_queue(dev); + mtk_stop_queue(eth); netif_err(eth, tx_queued, dev, "Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; @@ -720,10 +742,10 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) goto drop; if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) { - netif_stop_queue(dev); + mtk_stop_queue(eth); if (unlikely(atomic_read(&ring->free_count) > ring->thresh)) - netif_wake_queue(dev); + mtk_wake_queue(eth); } return NETDEV_TX_OK; @@ -897,13 +919,8 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget, bool *tx_again) if (!total) return 0; - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!eth->netdev[i] || - unlikely(!netif_queue_stopped(eth->netdev[i]))) - continue; - if (atomic_read(&ring->free_count) > ring->thresh) - netif_wake_queue(eth->netdev[i]); - } + if (atomic_read(&ring->free_count) > ring->thresh) + mtk_wake_queue(eth); return total; } -- GitLab From 34c2e4c9e9b3e434a31f67eecf603dc1496c8cc9 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:08 +0200 Subject: [PATCH 2324/9938] net: mediatek: fix TX locking Inside the TX path there is a lock inside the tx_map function. This is however too late. The patch moves the lock to the start of the xmit function right before the free count check of the DMA ring happens. If we do not do this, the code becomes racy leading to TX stalls and dropped packets. This happens as there are 2 netdevs running on the same physical DMA ring. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 4ebc42e0271a..7b760752d2c1 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -536,7 +536,6 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, struct mtk_eth *eth = mac->hw; struct mtk_tx_dma *itxd, *txd; struct mtk_tx_buf *tx_buf; - unsigned long flags; dma_addr_t mapped_addr; unsigned int nr_frags; int i, n_desc = 1; @@ -568,11 +567,6 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, if (unlikely(dma_mapping_error(&dev->dev, mapped_addr))) return -ENOMEM; - /* normally we can rely on the stack not calling this more than once, - * however we have 2 queues running ont he same ring so we need to lock - * the ring access - */ - spin_lock_irqsave(ð->page_lock, flags); WRITE_ONCE(itxd->txd1, mapped_addr); tx_buf->flags |= MTK_TX_FLAGS_SINGLE0; dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr); @@ -632,8 +626,6 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) | (!nr_frags * TX_DMA_LS0))); - spin_unlock_irqrestore(ð->page_lock, flags); - netdev_sent_queue(dev, skb->len); skb_tx_timestamp(skb); @@ -661,8 +653,6 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, itxd = mtk_qdma_phys_to_virt(ring, itxd->txd2); } while (itxd != txd); - spin_unlock_irqrestore(ð->page_lock, flags); - return -ENOMEM; } @@ -712,14 +702,22 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) struct mtk_eth *eth = mac->hw; struct mtk_tx_ring *ring = ð->tx_ring; struct net_device_stats *stats = &dev->stats; + unsigned long flags; bool gso = false; int tx_num; + /* normally we can rely on the stack not calling this more than once, + * however we have 2 queues running on the same ring so we need to lock + * the ring access + */ + spin_lock_irqsave(ð->page_lock, flags); + tx_num = mtk_cal_txd_req(skb); if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { mtk_stop_queue(eth); netif_err(eth, tx_queued, dev, "Tx Ring full when queue awake!\n"); + spin_unlock_irqrestore(ð->page_lock, flags); return NETDEV_TX_BUSY; } @@ -747,10 +745,12 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) ring->thresh)) mtk_wake_queue(eth); } + spin_unlock_irqrestore(ð->page_lock, flags); return NETDEV_TX_OK; drop: + spin_unlock_irqrestore(ð->page_lock, flags); stats->tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; -- GitLab From e7d425dcea032f1d0b44b6fa4c6735f13882de6e Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:09 +0200 Subject: [PATCH 2325/9938] net: mediatek: fix mtk_pending_work The driver supports 2 MACs. Both run on the same DMA ring. If we hit a TX timeout we need to stop both netdevs before restarting them again. If we don't do this, mtk_stop() wont shutdown DMA and the consecutive call to mtk_open() wont restart DMA and enable IRQs. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 28 +++++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 7b760752d2c1..cd5d0c97f0ce 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1432,17 +1432,29 @@ static void mtk_pending_work(struct work_struct *work) { struct mtk_mac *mac = container_of(work, struct mtk_mac, pending_work); struct mtk_eth *eth = mac->hw; - struct net_device *dev = eth->netdev[mac->id]; - int err; + int err, i; + unsigned long restart = 0; rtnl_lock(); - mtk_stop(dev); - err = mtk_open(dev); - if (err) { - netif_alert(eth, ifup, dev, - "Driver up/down cycle failed, closing device.\n"); - dev_close(dev); + /* stop all devices to make sure that dma is properly shut down */ + for (i = 0; i < MTK_MAC_COUNT; i++) { + if (!netif_oper_up(eth->netdev[i])) + continue; + mtk_stop(eth->netdev[i]); + __set_bit(i, &restart); + } + + /* restart DMA and enable IRQs */ + for (i = 0; i < MTK_MAC_COUNT; i++) { + if (!test_bit(i, &restart)) + continue; + err = mtk_open(eth->netdev[i]); + if (err) { + netif_alert(eth, ifup, eth->netdev[i], + "Driver up/down cycle failed, closing device.\n"); + dev_close(eth->netdev[i]); + } } rtnl_unlock(); } -- GitLab From 7c78b4ad9bbdbe0bb4fbc98841ad9d904ee116e9 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:10 +0200 Subject: [PATCH 2326/9938] net: mediatek: move the pending_work struct to the device generic struct The worker always touches both netdevs. It is ethernet core and not MAC specific. We only need one worker, which belongs into the ethernets core struct. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 13 +++++-------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index cd5d0c97f0ce..eb0d5544787a 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1193,7 +1193,7 @@ static void mtk_tx_timeout(struct net_device *dev) eth->netdev[mac->id]->stats.tx_errors++; netif_err(eth, tx_err, dev, "transmit timed out\n"); - schedule_work(&mac->pending_work); + schedule_work(ð->pending_work); } static irqreturn_t mtk_handle_irq(int irq, void *_eth) @@ -1430,8 +1430,7 @@ static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static void mtk_pending_work(struct work_struct *work) { - struct mtk_mac *mac = container_of(work, struct mtk_mac, pending_work); - struct mtk_eth *eth = mac->hw; + struct mtk_eth *eth = container_of(work, struct mtk_eth, pending_work); int err, i; unsigned long restart = 0; @@ -1439,7 +1438,7 @@ static void mtk_pending_work(struct work_struct *work) /* stop all devices to make sure that dma is properly shut down */ for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!netif_oper_up(eth->netdev[i])) + if (!eth->netdev[i]) continue; mtk_stop(eth->netdev[i]); __set_bit(i, &restart); @@ -1464,15 +1463,13 @@ static int mtk_cleanup(struct mtk_eth *eth) int i; for (i = 0; i < MTK_MAC_COUNT; i++) { - struct mtk_mac *mac = netdev_priv(eth->netdev[i]); - if (!eth->netdev[i]) continue; unregister_netdev(eth->netdev[i]); free_netdev(eth->netdev[i]); - cancel_work_sync(&mac->pending_work); } + cancel_work_sync(ð->pending_work); return 0; } @@ -1660,7 +1657,6 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) mac->id = id; mac->hw = eth; mac->of_node = np; - INIT_WORK(&mac->pending_work, mtk_pending_work); mac->hw_stats = devm_kzalloc(eth->dev, sizeof(*mac->hw_stats), @@ -1762,6 +1758,7 @@ static int mtk_probe(struct platform_device *pdev) eth->dev = &pdev->dev; eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); + INIT_WORK(ð->pending_work, mtk_pending_work); err = mtk_hw_init(eth); if (err) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 48a5292c8ed8..eed626d56ea4 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -363,6 +363,7 @@ struct mtk_rx_ring { * @clk_gp1: The gmac1 clock * @clk_gp2: The gmac2 clock * @mii_bus: If there is a bus we need to create an instance for it + * @pending_work: The workqueue used to reset the dma ring */ struct mtk_eth { @@ -389,6 +390,7 @@ struct mtk_eth { struct clk *clk_gp1; struct clk *clk_gp2; struct mii_bus *mii_bus; + struct work_struct pending_work; }; /* struct mtk_mac - the structure that holds the info about the MACs of the @@ -398,7 +400,6 @@ struct mtk_eth { * @hw: Backpointer to our main datastruture * @hw_stats: Packet statistics counter * @phy_dev: The attached PHY if available - * @pending_work: The workqueue used to reset the dma ring */ struct mtk_mac { int id; @@ -406,7 +407,6 @@ struct mtk_mac { struct mtk_eth *hw; struct mtk_hw_stats *hw_stats; struct phy_device *phy_dev; - struct work_struct pending_work; }; /* the struct describing the SoC. these are declared in the soc_xyz.c files */ -- GitLab From 369f04531f80c5e5d194a193a2b9e7676a77328d Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Apr 2016 00:54:11 +0200 Subject: [PATCH 2327/9938] net: mediatek: do not set the QID field in the TX DMA descriptors The QID field gets set to the mac id. This made the DMA linked list queue the traffic of each MAC on a different internal queue. However during long term testing we found that this will cause traffic stalls as the multi queue setup requires a more complete initialisation which is not part of the upstream driver yet. This patch removes the code setting the QID field, resulting in all traffic ending up in queue 0 which works without any special setup. Signed-off-by: John Crispin Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index eb0d5544787a..c984462fad2a 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -603,8 +603,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, WRITE_ONCE(txd->txd1, mapped_addr); WRITE_ONCE(txd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(frag_map_size) | - last_frag * TX_DMA_LS0) | - mac->id); + last_frag * TX_DMA_LS0)); WRITE_ONCE(txd->txd4, 0); tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC; -- GitLab From c21de87db05b555a8110c0d8889943c1fe0c6ef1 Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Wed, 23 Mar 2016 17:47:21 +0800 Subject: [PATCH 2328/9938] arm64: dts: ls1043a: Add compatible "fsl,qoriq-gpio" for ls1043a gpio nodes The compatible "fsl,qoriq-gpio" is used by gpio driver: drivers/gpio/gpio-mpc8xxx.c to implement general gpio functionalities. The chip-specific compatible "fsl,ls1043a-gpio" may be used to fix potential gpio IP block errata or other chip-specific gpio issues. Signed-off-by: Liu Gang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index be72bf5b58b5..bf70b276f09b 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -284,7 +284,7 @@ }; gpio1: gpio@2300000 { - compatible = "fsl,ls1043a-gpio"; + compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = <0 66 0x4>; gpio-controller; @@ -294,7 +294,7 @@ }; gpio2: gpio@2310000 { - compatible = "fsl,ls1043a-gpio"; + compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2310000 0x0 0x10000>; interrupts = <0 67 0x4>; gpio-controller; @@ -304,7 +304,7 @@ }; gpio3: gpio@2320000 { - compatible = "fsl,ls1043a-gpio"; + compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2320000 0x0 0x10000>; interrupts = <0 68 0x4>; gpio-controller; @@ -314,7 +314,7 @@ }; gpio4: gpio@2330000 { - compatible = "fsl,ls1043a-gpio"; + compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2330000 0x0 0x10000>; interrupts = <0 134 0x4>; gpio-controller; -- GitLab From 22088b6ac3e5687f766326d4ec8d5c2ea9e903c1 Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Wed, 23 Mar 2016 17:47:22 +0800 Subject: [PATCH 2329/9938] arm64: dts: ls2080a: Add compatible "fsl,ls2080a-gpio" for ls2080a gpio nodes The compatible "fsl,qoriq-gpio" is used by gpio driver: drivers/gpio/gpio-mpc8xxx.c to implement general gpio functionalities. The chip-specific compatible "fsl,ls2080a-gpio" may be used to fix potential gpio IP block errata or other chip-specific gpio issues. Signed-off-by: Liu Gang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi index eb2cc8554578..6195916fc448 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi @@ -342,7 +342,7 @@ }; gpio0: gpio@2300000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = <0 36 0x4>; /* Level high type */ gpio-controller; @@ -353,7 +353,7 @@ }; gpio1: gpio@2310000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2310000 0x0 0x10000>; interrupts = <0 36 0x4>; /* Level high type */ gpio-controller; @@ -364,7 +364,7 @@ }; gpio2: gpio@2320000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2320000 0x0 0x10000>; interrupts = <0 37 0x4>; /* Level high type */ gpio-controller; @@ -375,7 +375,7 @@ }; gpio3: gpio@2330000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2330000 0x0 0x10000>; interrupts = <0 37 0x4>; /* Level high type */ gpio-controller; -- GitLab From e92077c3f45395881ad8c690bb86a85ffe5198ba Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 12 Apr 2016 22:51:03 +0200 Subject: [PATCH 2330/9938] ASoC: fsl: imx-pcm-fiq: use correct format specifier Documentation/printk-formats.txt has size_t: use %zu or %zx runtime->dma_bytes is of type size_t. Signed-off-by: Heinrich Schuchardt Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-fiq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index e63cd5ecfd8f..dac6688540dc 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c @@ -220,7 +220,7 @@ static int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, ret = dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); - pr_debug("%s: ret: %d %p %pad 0x%08x\n", __func__, ret, + pr_debug("%s: ret: %d %p %pad 0x%08zx\n", __func__, ret, runtime->dma_area, &runtime->dma_addr, runtime->dma_bytes); -- GitLab From 896491b304f956d3e87208a242db4fdfa952cdc5 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 13 Apr 2016 01:54:01 +0200 Subject: [PATCH 2331/9938] ASoC: au1x: use correct format specifier Documentation/printk-formats.txt has unsigned long: use %lu or %lx size_t: use %zu or %zx runtime->dma_bytes is of type size_t. runtime->min_align is of type unsigned long. Signed-off-by: Heinrich Schuchardt Signed-off-by: Mark Brown --- sound/soc/au1x/dbdma2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 5741c0aa6c03..b5d1caa04d8e 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -206,8 +206,8 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, stype = substream->stream; pcd = to_dmadata(substream); - DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " - "runtime->min_align %d\n", + DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %zu " + "runtime->min_align %lu\n", (unsigned long)runtime->dma_area, (unsigned long)runtime->dma_addr, runtime->dma_bytes, runtime->min_align); -- GitLab From 469b640e4f4a28bdd50f0ac1d2b310907afb464c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 12 Apr 2016 12:31:00 +0200 Subject: [PATCH 2332/9938] regulator: reorder initialization steps in regulator_register() device_register() is calling ->get_voltage() as part of it's sysfs attribute initialization process, and this functions might need to know the regulator constraints to return a valid value. This is at least true for the pwm regulator driver (when operating in continuous mode) which needs to know the minimum and maximum voltage values to calculate the current voltage: min_uV + (((max_uV - min_uV) * dutycycle) / 100); Move device_register() after set_machine_constraints() to make sure those constraints are correctly initialized when ->get_voltage() is called. Signed-off-by: Boris Brezillon Reported-by: Stephen Barber Tested-by: Caesar Wang Signed-off-by: Mark Brown --- drivers/regulator/core.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0b764284773..8258568c793a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3950,13 +3950,6 @@ regulator_register(const struct regulator_desc *regulator_desc, rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%lu", (unsigned long) atomic_inc_return(®ulator_no)); - ret = device_register(&rdev->dev); - if (ret != 0) { - put_device(&rdev->dev); - goto wash; - } - - dev_set_drvdata(&rdev->dev, rdev); /* set regulator constraints */ if (init_data) @@ -3964,7 +3957,15 @@ regulator_register(const struct regulator_desc *regulator_desc, ret = set_machine_constraints(rdev, constraints); if (ret < 0) - goto scrub; + goto wash; + + ret = device_register(&rdev->dev); + if (ret != 0) { + put_device(&rdev->dev); + goto wash; + } + + dev_set_drvdata(&rdev->dev, rdev); if (init_data && init_data->supply_regulator) rdev->supply_name = init_data->supply_regulator; @@ -3993,8 +3994,6 @@ regulator_register(const struct regulator_desc *regulator_desc, unset_supplies: unset_regulator_supplies(rdev); - -scrub: regulator_ena_gpio_free(rdev); device_unregister(&rdev->dev); /* device core frees rdev */ @@ -4002,6 +4001,7 @@ regulator_register(const struct regulator_desc *regulator_desc, goto out; wash: + kfree(rdev->constraints); regulator_ena_gpio_free(rdev); clean: kfree(rdev); -- GitLab From 2c0a303a128cbef54a7b58dc2e413b874d760097 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 12 Apr 2016 08:05:43 +0100 Subject: [PATCH 2333/9938] regulator: core: Fix locking of GPIO list on free When we acquire a shareable enable GPIO on probe we do so with the regulator_list_mutex held. However when we release the GPIOs we do this immediately after dropping the mutex meaning that the list could become corrupted. Move the release into the locked region to avoid this. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 1cff11205642..e414c24b2906 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -4021,8 +4021,8 @@ void regulator_unregister(struct regulator_dev *rdev) WARN_ON(rdev->open_count); unset_regulator_supplies(rdev); list_del(&rdev->list); - mutex_unlock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); + mutex_unlock(®ulator_list_mutex); device_unregister(&rdev->dev); } EXPORT_SYMBOL_GPL(regulator_unregister); -- GitLab From a5052657c164107032d521f0d9e92703d78845f2 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 12 Apr 2016 08:52:49 -0700 Subject: [PATCH 2334/9938] locking/Documentation: Clarify relationship of barrier() to control dependencies The current documentation claims that the compiler ignores barrier(), which is not the case. Instead, the compiler carefully pays attention to barrier(), but in a creative way that still manages to destroy the control dependency. This commit sets the story straight. Reported-by: Mathieu Desnoyers Signed-off-by: Paul E. McKenney Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dhowells@redhat.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476375-27803-1-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 3729cbe60e41..ec1289042396 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -813,9 +813,10 @@ In summary: the same variable, then those stores must be ordered, either by preceding both of them with smp_mb() or by using smp_store_release() to carry out the stores. Please note that it is -not- sufficient - to use barrier() at beginning of each leg of the "if" statement, - as optimizing compilers do not necessarily respect barrier() - in this case. + to use barrier() at beginning of each leg of the "if" statement + because, as shown by the example above, optimizing compilers can + destroy the control dependency while respecting the letter of the + barrier() law. (*) Control dependencies require at least one run-time conditional between the prior load and the subsequent store, and this -- GitLab From 166bda7122c8e817f039bf738cf05ab3b7278732 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 12 Apr 2016 08:52:50 -0700 Subject: [PATCH 2335/9938] locking/Documentation: Fix missed s/lock/acquire renames The terms 'lock'/'unlock' were changed to 'acquire'/'release' by the following commit: 2e4f5382d12a4 ("locking/doc: Rename LOCK/UNLOCK to ACQUIRE/RELEASE") However, the commit missed to change the table of contents - fix that. Also, the dumb rename changed the section name 'Locking functions' to an actively misleading 'Acquiring functions' section name. Rename it to 'Lock acquisition functions' instead. Suggested-by: David Howells Signed-off-by: SeongJae Park Signed-off-by: Paul E. McKenney Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: mathieu.desnoyers@efficios.com Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476375-27803-2-git-send-email-paulmck@linux.vnet.ibm.com [ Rewrote the changelog. ] Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index ec1289042396..38b1ce161afb 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -31,15 +31,15 @@ Contents: (*) Implicit kernel memory barriers. - - Locking functions. + - Lock acquisition functions. - Interrupt disabling functions. - Sleep and wake-up functions. - Miscellaneous functions. - (*) Inter-CPU locking barrier effects. + (*) Inter-CPU acquiring barrier effects. - - Locks vs memory accesses. - - Locks vs I/O accesses. + - Acquires vs memory accesses. + - Acquires vs I/O accesses. (*) Where are memory barriers needed? @@ -1859,7 +1859,7 @@ This is a variation on the mandatory write barrier that causes writes to weakly ordered I/O regions to be partially ordered. Its effects may go beyond the CPU->Hardware interface and actually affect the hardware at some level. -See the subsection "Locks vs I/O accesses" for more information. +See the subsection "Acquires vs I/O accesses" for more information. =============================== @@ -1874,8 +1874,8 @@ provide more substantial guarantees, but these may not be relied upon outside of arch specific code. -ACQUIRING FUNCTIONS -------------------- +LOCK ACQUISITION FUNCTIONS +-------------------------- The Linux kernel has a number of locking constructs: -- GitLab From 01e1cd6de8e75fa28c268b4dc566bc1a39486e71 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 12 Apr 2016 08:52:51 -0700 Subject: [PATCH 2336/9938] locking/Documentation: Add missed subsection in TOC A 'Virtual Machine Guests' subsection was added by this commit: 6a65d26385bf487 ("asm-generic: implement virt_xxx memory barriers") but the TOC was not updated - update it. Signed-off-by: SeongJae Park Signed-off-by: Paul E. McKenney Acked-by: David Howells Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: mathieu.desnoyers@efficios.com Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476375-27803-3-git-send-email-paulmck@linux.vnet.ibm.com [ Rewrote the changelog. ] Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 38b1ce161afb..718ef2564fa0 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -61,6 +61,7 @@ Contents: (*) The things CPUs get up to. - And then there's the Alpha. + - Virtual Machine Guests. (*) Example uses. -- GitLab From 3dbf0913f6cac722805a94f16b1e61ffc3483eaf Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 12 Apr 2016 08:52:52 -0700 Subject: [PATCH 2337/9938] locking/Documentation: Fix formatting inconsistencies Signed-off-by: SeongJae Park Signed-off-by: Paul E. McKenney Acked-by: David Howells Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: mathieu.desnoyers@efficios.com Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476375-27803-4-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 718ef2564fa0..1f1541862239 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -149,7 +149,7 @@ As a further example, consider this sequence of events: CPU 1 CPU 2 =============== =============== - { A == 1, B == 2, C = 3, P == &A, Q == &C } + { A == 1, B == 2, C == 3, P == &A, Q == &C } B = 4; Q = P; P = &B D = *Q; @@ -518,7 +518,7 @@ following sequence of events: CPU 1 CPU 2 =============== =============== - { A == 1, B == 2, C = 3, P == &A, Q == &C } + { A == 1, B == 2, C == 3, P == &A, Q == &C } B = 4; WRITE_ONCE(P, &B) @@ -545,7 +545,7 @@ between the address load and the data load: CPU 1 CPU 2 =============== =============== - { A == 1, B == 2, C = 3, P == &A, Q == &C } + { A == 1, B == 2, C == 3, P == &A, Q == &C } B = 4; WRITE_ONCE(P, &B); @@ -3043,7 +3043,7 @@ The Alpha defines the Linux kernel's memory barrier model. See the subsection on "Cache Coherency" above. VIRTUAL MACHINE GUESTS -------------------- +---------------------- Guests running within virtual machines might be affected by SMP effects even if the guest itself is compiled without SMP support. This is an artifact of -- GitLab From 0b6fa347dc08c6f757a35f3a180269b3ffc4cd28 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 12 Apr 2016 08:52:53 -0700 Subject: [PATCH 2338/9938] locking/Documentation: Insert white spaces consistently The document uses two newlines between sections, one newline between item and its detailed description, and two spaces between sentences. There are a few places that used these rules inconsistently - fix them. Signed-off-by: SeongJae Park Signed-off-by: Paul E. McKenney Acked-by: David Howells Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: mathieu.desnoyers@efficios.com Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476375-27803-5-git-send-email-paulmck@linux.vnet.ibm.com [ Fixed the changelog. ] Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 43 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 1f1541862239..7133626a61d0 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -1733,15 +1733,15 @@ The Linux kernel has eight basic CPU memory barriers: All memory barriers except the data dependency barriers imply a compiler -barrier. Data dependencies do not impose any additional compiler ordering. +barrier. Data dependencies do not impose any additional compiler ordering. Aside: In the case of data dependencies, the compiler would be expected to issue the loads in the correct order (eg. `a[b]` would have to load the value of b before loading a[b]), however there is no guarantee in the C specification that the compiler may not speculate the value of b (eg. is equal to 1) and load a before b (eg. tmp = a[1]; if (b != 1) -tmp = a[b]; ). There is also the problem of a compiler reloading b after -having loaded a[b], thus having a newer copy of b than a[b]. A consensus +tmp = a[b]; ). There is also the problem of a compiler reloading b after +having loaded a[b], thus having a newer copy of b than a[b]. A consensus has not yet been reached about these problems, however the READ_ONCE() macro is a good place to start looking. @@ -1796,6 +1796,7 @@ There are some more advanced barrier functions: (*) lockless_dereference(); + This can be thought of as a pointer-fetch wrapper around the smp_read_barrier_depends() data-dependency barrier. @@ -1897,7 +1898,7 @@ for each construct. These operations all imply certain barriers: Memory operations issued before the ACQUIRE may be completed after the ACQUIRE operation has completed. An smp_mb__before_spinlock(), combined with a following ACQUIRE, orders prior stores against - subsequent loads and stores. Note that this is weaker than smp_mb()! + subsequent loads and stores. Note that this is weaker than smp_mb()! The smp_mb__before_spinlock() primitive is free on many architectures. (2) RELEASE operation implication: @@ -2092,9 +2093,9 @@ or: event_indicated = 1; wake_up_process(event_daemon); -A write memory barrier is implied by wake_up() and co. if and only if they wake -something up. The barrier occurs before the task state is cleared, and so sits -between the STORE to indicate the event and the STORE to set TASK_RUNNING: +A write memory barrier is implied by wake_up() and co. if and only if they +wake something up. The barrier occurs before the task state is cleared, and so +sits between the STORE to indicate the event and the STORE to set TASK_RUNNING: CPU 1 CPU 2 =============================== =============================== @@ -2208,7 +2209,7 @@ three CPUs; then should the following sequence of events occur: Then there is no guarantee as to what order CPU 3 will see the accesses to *A through *H occur in, other than the constraints imposed by the separate locks -on the separate CPUs. It might, for example, see: +on the separate CPUs. It might, for example, see: *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M @@ -2488,9 +2489,9 @@ The following operations are special locking primitives: clear_bit_unlock(); __clear_bit_unlock(); -These implement ACQUIRE-class and RELEASE-class operations. These should be used in -preference to other operations when implementing locking primitives, because -their implementations can be optimised on many architectures. +These implement ACQUIRE-class and RELEASE-class operations. These should be +used in preference to other operations when implementing locking primitives, +because their implementations can be optimised on many architectures. [!] Note that special memory barrier primitives are available for these situations because on some CPUs the atomic instructions used imply full memory @@ -2570,12 +2571,12 @@ explicit barriers are used. Normally this won't be a problem because the I/O accesses done inside such sections will include synchronous load operations on strictly ordered I/O -registers that form implicit I/O barriers. If this isn't sufficient then an +registers that form implicit I/O barriers. If this isn't sufficient then an mmiowb() may need to be used explicitly. A similar situation may occur between an interrupt routine and two routines -running on separate CPUs that communicate with each other. If such a case is +running on separate CPUs that communicate with each other. If such a case is likely, then interrupt-disabling locks should be used to guarantee ordering. @@ -2589,8 +2590,8 @@ functions: (*) inX(), outX(): These are intended to talk to I/O space rather than memory space, but - that's primarily a CPU-specific concept. The i386 and x86_64 processors do - indeed have special I/O space access cycles and instructions, but many + that's primarily a CPU-specific concept. The i386 and x86_64 processors + do indeed have special I/O space access cycles and instructions, but many CPUs don't have such a concept. The PCI bus, amongst others, defines an I/O space concept which - on such @@ -2612,7 +2613,7 @@ functions: Whether these are guaranteed to be fully ordered and uncombined with respect to each other on the issuing CPU depends on the characteristics - defined for the memory window through which they're accessing. On later + defined for the memory window through which they're accessing. On later i386 architecture machines, for example, this is controlled by way of the MTRR registers. @@ -2637,10 +2638,10 @@ functions: (*) readX_relaxed(), writeX_relaxed() These are similar to readX() and writeX(), but provide weaker memory - ordering guarantees. Specifically, they do not guarantee ordering with + ordering guarantees. Specifically, they do not guarantee ordering with respect to normal memory accesses (e.g. DMA buffers) nor do they guarantee - ordering with respect to LOCK or UNLOCK operations. If the latter is - required, an mmiowb() barrier can be used. Note that relaxed accesses to + ordering with respect to LOCK or UNLOCK operations. If the latter is + required, an mmiowb() barrier can be used. Note that relaxed accesses to the same peripheral are guaranteed to be ordered with respect to each other. @@ -3042,6 +3043,7 @@ The Alpha defines the Linux kernel's memory barrier model. See the subsection on "Cache Coherency" above. + VIRTUAL MACHINE GUESTS ---------------------- @@ -3052,7 +3054,7 @@ barriers for this use-case would be possible but is often suboptimal. To handle this case optimally, low-level virt_mb() etc macros are available. These have the same effect as smp_mb() etc when SMP is enabled, but generate -identical code for SMP and non-SMP systems. For example, virtual machine guests +identical code for SMP and non-SMP systems. For example, virtual machine guests should use virt_mb() rather than smp_mb() when synchronizing against a (possibly SMP) host. @@ -3060,6 +3062,7 @@ These are equivalent to smp_mb() etc counterparts in all other respects, in particular, they do not control MMIO effects: to control MMIO effects, use mandatory barriers. + ============ EXAMPLE USES ============ -- GitLab From 787df6383caa1338a4f6640d71917bc2d8c068b1 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Tue, 12 Apr 2016 08:52:55 -0700 Subject: [PATCH 2339/9938] locking/Documentation: Mention smp_cond_acquire() ... do this next to smp_load_acquire() when first mentioning ACQUIRE. While this call is briefly explained and control dependencies are mentioned later, it does not hurt the reader. Signed-off-by: Davidlohr Bueso Signed-off-by: Paul E. McKenney Cc: Andrew Morton Cc: Davidlohr Bueso Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dhowells@redhat.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: mathieu.desnoyers@efficios.com Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476375-27803-7-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 7133626a61d0..a9454b1c73bd 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -431,8 +431,9 @@ And a couple of implicit varieties: This acts as a one-way permeable barrier. It guarantees that all memory operations after the ACQUIRE operation will appear to happen after the ACQUIRE operation with respect to the other components of the system. - ACQUIRE operations include LOCK operations and smp_load_acquire() - operations. + ACQUIRE operations include LOCK operations and both smp_load_acquire() + and smp_cond_acquire() operations. The later builds the necessary ACQUIRE + semantics from relying on a control dependency and smp_rmb(). Memory operations that occur before an ACQUIRE operation may appear to happen after it completes. -- GitLab From 1f190931893a98ffd5d4cfdfbfc2452ad0ed3e1b Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Tue, 12 Apr 2016 08:47:17 -0700 Subject: [PATCH 2340/9938] locking/locktorture: Fix deboosting NULL pointer dereference For the case of rtmutex torturing we will randomly call into the boost() handler, including upon module exiting when the tasks are deboosted before stopping. In such cases the task may or may not have already been boosted, and therefore the NULL being explicitly passed can occur anywhere. Currently we only assume that the task will is at a higher prio, and in consequence, dereference a NULL pointer. This patch fixes the case of a rmmod locktorture exploding while pounding on the rtmutex lock (partial trace): task: ffff88081026cf80 ti: ffff880816120000 task.ti: ffff880816120000 RSP: 0018:ffff880816123eb0 EFLAGS: 00010206 RAX: ffff88081026cf80 RBX: ffff880816bfa630 RCX: 0000000000160d1b RDX: 0000000000000000 RSI: 0000000000000202 RDI: 0000000000000000 RBP: ffff88081026cf80 R08: 000000000000001f R09: ffff88017c20ca80 R10: 0000000000000000 R11: 000000000048c316 R12: ffffffffa05d1840 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88203f880000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000008 CR3: 0000000001c0a000 CR4: 00000000000406e0 Stack: ffffffffa05d141d ffff880816bfa630 ffffffffa05d1922 ffff88081e70c2c0 ffff880816bfa630 ffffffff81095fed 0000000000000000 ffffffff8107bf60 ffff880816bfa630 ffffffff00000000 ffff880800000000 ffff880816123f08 Call Trace: [] kthread+0xbd/0xe0 [] ret_from_fork+0x3f/0x70 This patch ensures that if the random state pointer is not NULL and current is not boosted, then do nothing. RIP: 0010:[] [] torture_random+0x5/0x60 [torture] [] torture_rtmutex_boost+0x1d/0x90 [locktorture] [] lock_torture_writer+0xe2/0x170 [locktorture] Signed-off-by: Davidlohr Bueso Signed-off-by: Paul E. McKenney Cc: Andrew Morton Cc: Davidlohr Bueso Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dhowells@redhat.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: mathieu.desnoyers@efficios.com Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476038-27060-1-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- kernel/locking/locktorture.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index 8ef1919d63b2..9e9c5f454f5c 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -394,12 +394,12 @@ static void torture_rtmutex_boost(struct torture_random_state *trsp) if (!rt_task(current)) { /* - * (1) Boost priority once every ~50k operations. When the + * Boost priority once every ~50k operations. When the * task tries to take the lock, the rtmutex it will account * for the new priority, and do any corresponding pi-dance. */ - if (!(torture_random(trsp) % - (cxt.nrealwriters_stress * factor))) { + if (trsp && !(torture_random(trsp) % + (cxt.nrealwriters_stress * factor))) { policy = SCHED_FIFO; param.sched_priority = MAX_RT_PRIO - 1; } else /* common case, do nothing */ -- GitLab From c1c33b92db4fb274dfbff778ccf2459e4bebd48e Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Tue, 12 Apr 2016 08:47:18 -0700 Subject: [PATCH 2341/9938] locking/locktorture: Fix NULL pointer dereference for cleanup paths It has been found that paths that invoke cleanups through lock_torture_cleanup() can trigger NULL pointer dereferencing bugs during the statistics printing phase. This is mainly because we should not be calling into statistics before we are sure things have been set up correctly. Specifically, early checks (and the need for handling this in the cleanup call) only include parameter checks and basic statistics allocation. Once we start write/read kthreads we then consider the test as started. As such, update the function in question to check for cxt.lwsa writer stats, if not set, we either have a bogus parameter or -ENOMEM situation and therefore only need to deal with general torture calls. Reported-and-tested-by: Kefeng Wang Signed-off-by: Davidlohr Bueso Signed-off-by: Paul E. McKenney Cc: Andrew Morton Cc: Davidlohr Bueso Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bobby.prani@gmail.com Cc: dhowells@redhat.com Cc: dipankar@in.ibm.com Cc: dvhart@linux.intel.com Cc: edumazet@google.com Cc: fweisbec@gmail.com Cc: jiangshanlai@gmail.com Cc: josh@joshtriplett.org Cc: mathieu.desnoyers@efficios.com Cc: oleg@redhat.com Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1460476038-27060-2-git-send-email-paulmck@linux.vnet.ibm.com [ Improved the changelog. ] Signed-off-by: Ingo Molnar --- kernel/locking/locktorture.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index 9e9c5f454f5c..d066a50dc87e 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -748,6 +748,15 @@ static void lock_torture_cleanup(void) if (torture_cleanup_begin()) return; + /* + * Indicates early cleanup, meaning that the test has not run, + * such as when passing bogus args when loading the module. As + * such, only perform the underlying torture-specific cleanups, + * and avoid anything related to locktorture. + */ + if (!cxt.lwsa) + goto end; + if (writer_tasks) { for (i = 0; i < cxt.nrealwriters_stress; i++) torture_stop_kthread(lock_torture_writer, @@ -776,6 +785,7 @@ static void lock_torture_cleanup(void) else lock_torture_print_module_parms(cxt.cur_ops, "End of test: SUCCESS"); +end: torture_cleanup_end(); } @@ -870,6 +880,7 @@ static int __init lock_torture_init(void) VERBOSE_TOROUT_STRING("cxt.lrsa: Out of memory"); firsterr = -ENOMEM; kfree(cxt.lwsa); + cxt.lwsa = NULL; goto unwind; } @@ -878,6 +889,7 @@ static int __init lock_torture_init(void) cxt.lrsa[i].n_lock_acquired = 0; } } + lock_torture_print_module_parms(cxt.cur_ops, "Start of test"); /* Prepare torture context. */ -- GitLab From ea1b60fb085839a9544cb3a0069992991beabb7f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 12 Apr 2016 12:56:25 +0100 Subject: [PATCH 2342/9938] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden Each transfer can specify 8, 16 or 32 bits per word independently of the default for the device being addressed. However, currently we calculate the number of words in the frame assuming that the word size is the device default. If multiple transfers in the same message have differing bits_per_word, we bitwise-or the different values in the WLEN register field. Fix both of these. Also rename 'frame_length' to 'frame_len_words' to make clear that it's not a byte count like spi_message::frame_length. Signed-off-by: Ben Hutchings Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-ti-qspi.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index eac3c960b2de..0ee4139dec48 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -94,6 +94,7 @@ struct ti_qspi { #define QSPI_FLEN(n) ((n - 1) << 0) #define QSPI_WLEN_MAX_BITS 128 #define QSPI_WLEN_MAX_BYTES 16 +#define QSPI_WLEN_MASK QSPI_WLEN(QSPI_WLEN_MAX_BITS) /* STATUS REGISTER */ #define BUSY 0x01 @@ -450,7 +451,7 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, struct spi_device *spi = m->spi; struct spi_transfer *t; int status = 0, ret; - int frame_length; + unsigned int frame_len_words; /* setup device control reg */ qspi->dc = 0; @@ -462,14 +463,15 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, if (spi->mode & SPI_CS_HIGH) qspi->dc |= QSPI_CSPOL(spi->chip_select); - frame_length = (m->frame_length << 3) / spi->bits_per_word; - - frame_length = clamp(frame_length, 0, QSPI_FRAME); + frame_len_words = 0; + list_for_each_entry(t, &m->transfers, transfer_list) + frame_len_words += t->len / (t->bits_per_word >> 3); + frame_len_words = min_t(unsigned int, frame_len_words, QSPI_FRAME); /* setup command reg */ qspi->cmd = 0; qspi->cmd |= QSPI_EN_CS(spi->chip_select); - qspi->cmd |= QSPI_FLEN(frame_length); + qspi->cmd |= QSPI_FLEN(frame_len_words); ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG); @@ -479,7 +481,8 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, ti_qspi_disable_memory_map(spi); list_for_each_entry(t, &m->transfers, transfer_list) { - qspi->cmd |= QSPI_WLEN(t->bits_per_word); + qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) | + QSPI_WLEN(t->bits_per_word)); ret = qspi_transfer_msg(qspi, t); if (ret) { -- GitLab From 1ff7760ff66b98ef244bf0e5e2bd5310651205ad Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 12 Apr 2016 12:58:14 +0100 Subject: [PATCH 2343/9938] spi: spi-ti-qspi: Handle truncated frames properly We clamp frame_len_words to a maximum of 4096, but do not actually limit the number of words written or read through the DATA registers or the length added to spi_message::actual_length. This results in silent data corruption for commands longer than this maximum. Recalculate the length of each transfer, taking frame_len_words into account. Use this length in qspi_{read,write}_msg(), and to increment spi_message::actual_length. Signed-off-by: Ben Hutchings Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-ti-qspi.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 0ee4139dec48..443f664534e1 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -236,16 +236,16 @@ static inline int ti_qspi_poll_wc(struct ti_qspi *qspi) return -ETIMEDOUT; } -static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) +static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t, + int count) { - int wlen, count, xfer_len; + int wlen, xfer_len; unsigned int cmd; const u8 *txbuf; u32 data; txbuf = t->tx_buf; cmd = qspi->cmd | QSPI_WR_SNGL; - count = t->len; wlen = t->bits_per_word >> 3; /* in bytes */ xfer_len = wlen; @@ -305,9 +305,10 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) return 0; } -static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t) +static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, + int count) { - int wlen, count; + int wlen; unsigned int cmd; u8 *rxbuf; @@ -324,7 +325,6 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t) cmd |= QSPI_RD_SNGL; break; } - count = t->len; wlen = t->bits_per_word >> 3; /* in bytes */ while (count) { @@ -355,12 +355,13 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t) return 0; } -static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t) +static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t, + int count) { int ret; if (t->tx_buf) { - ret = qspi_write_msg(qspi, t); + ret = qspi_write_msg(qspi, t, count); if (ret) { dev_dbg(qspi->dev, "Error while writing\n"); return ret; @@ -368,7 +369,7 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t) } if (t->rx_buf) { - ret = qspi_read_msg(qspi, t); + ret = qspi_read_msg(qspi, t, count); if (ret) { dev_dbg(qspi->dev, "Error while reading\n"); return ret; @@ -451,7 +452,8 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, struct spi_device *spi = m->spi; struct spi_transfer *t; int status = 0, ret; - unsigned int frame_len_words; + unsigned int frame_len_words, transfer_len_words; + int wlen; /* setup device control reg */ qspi->dc = 0; @@ -484,14 +486,20 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) | QSPI_WLEN(t->bits_per_word)); - ret = qspi_transfer_msg(qspi, t); + wlen = t->bits_per_word >> 3; + transfer_len_words = min(t->len / wlen, frame_len_words); + + ret = qspi_transfer_msg(qspi, t, transfer_len_words * wlen); if (ret) { dev_dbg(qspi->dev, "transfer message failed\n"); mutex_unlock(&qspi->list_lock); return -EINVAL; } - m->actual_length += t->len; + m->actual_length += transfer_len_words * wlen; + frame_len_words -= transfer_len_words; + if (frame_len_words == 0) + break; } mutex_unlock(&qspi->list_lock); -- GitLab From cd97a449a7cedf7d9a61882a672d317429b5d599 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 12 Apr 2016 17:57:53 +0200 Subject: [PATCH 2344/9938] MAINTAINERS: gpio: add DT bindings directory Helps get_maintainer.pl to find the right people. Signed-off-by: Wolfram Sang Signed-off-by: Linus Walleij --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..a023775b58d7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4884,6 +4884,7 @@ M: Alexandre Courbot L: linux-gpio@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git S: Maintained +F: Documentation/devicetree/bindings/gpio/ F: Documentation/gpio/ F: Documentation/ABI/testing/gpio-cdev F: Documentation/ABI/obsolete/sysfs-gpio -- GitLab From dac429874d8156d97460c61049e202b2dcc15df8 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 9 Apr 2016 13:17:29 +0200 Subject: [PATCH 2345/9938] uprobes/x86: Constify uprobe_xol_ops structures The uprobe_xol_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Cc: Andrew Morton Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: kernel-janitors@vger.kernel.org Link: http://lkml.kernel.org/r/1460200649-32526-1-git-send-email-Julia.Lawall@lip6.fr Signed-off-by: Ingo Molnar --- arch/x86/kernel/uprobes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index bf4db6eaec8f..bd074151bfd6 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -578,7 +578,7 @@ static void default_abort_op(struct arch_uprobe *auprobe, struct pt_regs *regs) riprel_post_xol(auprobe, regs); } -static struct uprobe_xol_ops default_xol_ops = { +static const struct uprobe_xol_ops default_xol_ops = { .pre_xol = default_pre_xol_op, .post_xol = default_post_xol_op, .abort = default_abort_op, @@ -695,7 +695,7 @@ static void branch_clear_offset(struct arch_uprobe *auprobe, struct insn *insn) 0, insn->immediate.nbytes); } -static struct uprobe_xol_ops branch_xol_ops = { +static const struct uprobe_xol_ops branch_xol_ops = { .emulate = branch_emulate_op, .post_xol = branch_post_xol_op, }; -- GitLab From c003ed928962a55eb446e78c544b1d7c4f6cb88a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 8 Apr 2016 20:58:46 +0200 Subject: [PATCH 2346/9938] locking/lockdep: Deinline register_lock_class(), save 2328 bytes This function compiles to 1328 bytes of machine code. Three callsites. Registering a new lock class is definitely not *that* time-critical to inline it. Signed-off-by: Denys Vlasenko Cc: Andrew Morton Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/1460141926-13069-5-git-send-email-dvlasenk@redhat.com Signed-off-by: Ingo Molnar --- kernel/locking/lockdep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index ed9410936a22..7cc43ef856c1 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -708,7 +708,7 @@ look_up_lock_class(struct lockdep_map *lock, unsigned int subclass) * yet. Otherwise we look it up. We cache the result in the lock object * itself, so actual lookup of the hash should be once per lock object. */ -static inline struct lock_class * +static struct lock_class * register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) { struct lockdep_subclass_key *key; -- GitLab From 0051202f6ad5fd9c04d220343e66d1eb890f7b81 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 7 Apr 2016 17:31:44 -0700 Subject: [PATCH 2347/9938] selftests/x86: Test the FSBASE/GSBASE API and context switching This catches two distinct bugs in the current code. I'll fix them. Signed-off-by: Andy Lutomirski Reviewed-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rudolf Marek Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/7e5941148d1e2199f070dadcdf7355959f5f8e85.1460075211.git.luto@kernel.org Signed-off-by: Ingo Molnar --- tools/testing/selftests/x86/Makefile | 1 + tools/testing/selftests/x86/fsgsbase.c | 398 +++++++++++++++++++++++++ 2 files changed, 399 insertions(+) create mode 100644 tools/testing/selftests/x86/fsgsbase.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index b47ebd170690..c73425de3cfe 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -9,6 +9,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer +TARGETS_C_64BIT_ONLY := fsgsbase TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c new file mode 100644 index 000000000000..5b2b4b3c634c --- /dev/null +++ b/tools/testing/selftests/x86/fsgsbase.c @@ -0,0 +1,398 @@ +/* + * fsgsbase.c, an fsgsbase test + * Copyright (c) 2014-2016 Andy Lutomirski + * GPL v2 + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __x86_64__ +# error This test is 64-bit only +#endif + +static volatile sig_atomic_t want_segv; +static volatile unsigned long segv_addr; + +static int nerrs; + +static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), + int flags) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO | flags; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + +static void clearhandler(int sig) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + +static void sigsegv(int sig, siginfo_t *si, void *ctx_void) +{ + ucontext_t *ctx = (ucontext_t*)ctx_void; + + if (!want_segv) { + clearhandler(SIGSEGV); + return; /* Crash cleanly. */ + } + + want_segv = false; + segv_addr = (unsigned long)si->si_addr; + + ctx->uc_mcontext.gregs[REG_RIP] += 4; /* Skip the faulting mov */ + +} + +enum which_base { FS, GS }; + +static unsigned long read_base(enum which_base which) +{ + unsigned long offset; + /* + * Unless we have FSGSBASE, there's no direct way to do this from + * user mode. We can get at it indirectly using signals, though. + */ + + want_segv = true; + + offset = 0; + if (which == FS) { + /* Use a constant-length instruction here. */ + asm volatile ("mov %%fs:(%%rcx), %%rax" : : "c" (offset) : "rax"); + } else { + asm volatile ("mov %%gs:(%%rcx), %%rax" : : "c" (offset) : "rax"); + } + if (!want_segv) + return segv_addr + offset; + + /* + * If that didn't segfault, try the other end of the address space. + * Unless we get really unlucky and run into the vsyscall page, this + * is guaranteed to segfault. + */ + + offset = (ULONG_MAX >> 1) + 1; + if (which == FS) { + asm volatile ("mov %%fs:(%%rcx), %%rax" + : : "c" (offset) : "rax"); + } else { + asm volatile ("mov %%gs:(%%rcx), %%rax" + : : "c" (offset) : "rax"); + } + if (!want_segv) + return segv_addr + offset; + + abort(); +} + +static void check_gs_value(unsigned long value) +{ + unsigned long base; + unsigned short sel; + + printf("[RUN]\tARCH_SET_GS to 0x%lx\n", value); + if (syscall(SYS_arch_prctl, ARCH_SET_GS, value) != 0) + err(1, "ARCH_SET_GS"); + + asm volatile ("mov %%gs, %0" : "=rm" (sel)); + base = read_base(GS); + if (base == value) { + printf("[OK]\tGSBASE was set as expected (selector 0x%hx)\n", + sel); + } else { + nerrs++; + printf("[FAIL]\tGSBASE was not as expected: got 0x%lx (selector 0x%hx)\n", + base, sel); + } + + if (syscall(SYS_arch_prctl, ARCH_GET_GS, &base) != 0) + err(1, "ARCH_GET_GS"); + if (base == value) { + printf("[OK]\tARCH_GET_GS worked as expected (selector 0x%hx)\n", + sel); + } else { + nerrs++; + printf("[FAIL]\tARCH_GET_GS was not as expected: got 0x%lx (selector 0x%hx)\n", + base, sel); + } +} + +static void mov_0_gs(unsigned long initial_base, bool schedule) +{ + unsigned long base, arch_base; + + printf("[RUN]\tARCH_SET_GS to 0x%lx then mov 0 to %%gs%s\n", initial_base, schedule ? " and schedule " : ""); + if (syscall(SYS_arch_prctl, ARCH_SET_GS, initial_base) != 0) + err(1, "ARCH_SET_GS"); + + if (schedule) + usleep(10); + + asm volatile ("mov %0, %%gs" : : "rm" (0)); + base = read_base(GS); + if (syscall(SYS_arch_prctl, ARCH_GET_GS, &arch_base) != 0) + err(1, "ARCH_GET_GS"); + if (base == arch_base) { + printf("[OK]\tGSBASE is 0x%lx\n", base); + } else { + nerrs++; + printf("[FAIL]\tGSBASE changed to 0x%lx but kernel reports 0x%lx\n", base, arch_base); + } +} + +static volatile unsigned long remote_base; +static volatile bool remote_hard_zero; +static volatile unsigned int ftx; + +/* + * ARCH_SET_FS/GS(0) may or may not program a selector of zero. HARD_ZERO + * means to force the selector to zero to improve test coverage. + */ +#define HARD_ZERO 0xa1fa5f343cb85fa4 + +static void do_remote_base() +{ + unsigned long to_set = remote_base; + bool hard_zero = false; + if (to_set == HARD_ZERO) { + to_set = 0; + hard_zero = true; + } + + if (syscall(SYS_arch_prctl, ARCH_SET_GS, to_set) != 0) + err(1, "ARCH_SET_GS"); + + if (hard_zero) + asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0)); + + unsigned short sel; + asm volatile ("mov %%gs, %0" : "=rm" (sel)); + printf("\tother thread: ARCH_SET_GS(0x%lx)%s -- sel is 0x%hx\n", + to_set, hard_zero ? " and clear gs" : "", sel); +} + +void do_unexpected_base(void) +{ + /* + * The goal here is to try to arrange for GS == 0, GSBASE != + * 0, and for the the kernel the think that GSBASE == 0. + * + * To make the test as reliable as possible, this uses + * explicit descriptorss. (This is not the only way. This + * could use ARCH_SET_GS with a low, nonzero base, but the + * relevant side effect of ARCH_SET_GS could change.) + */ + + /* Step 1: tell the kernel that we have GSBASE == 0. */ + if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0) + err(1, "ARCH_SET_GS"); + + /* Step 2: change GSBASE without telling the kernel. */ + struct user_desc desc = { + .entry_number = 0, + .base_addr = 0xBAADF00D, + .limit = 0xfffff, + .seg_32bit = 1, + .contents = 0, /* Data, grow-up */ + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 0 + }; + if (syscall(SYS_modify_ldt, 1, &desc, sizeof(desc)) == 0) { + printf("\tother thread: using LDT slot 0\n"); + asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0x7)); + } else { + /* No modify_ldt for us (configured out, perhaps) */ + + struct user_desc *low_desc = mmap( + NULL, sizeof(desc), + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + memcpy(low_desc, &desc, sizeof(desc)); + + low_desc->entry_number = -1; + + /* 32-bit set_thread_area */ + long ret; + asm volatile ("int $0x80" + : "=a" (ret) : "a" (243), "b" (low_desc) + : "flags"); + memcpy(&desc, low_desc, sizeof(desc)); + munmap(low_desc, sizeof(desc)); + + if (ret != 0) { + printf("[NOTE]\tcould not create a segment -- test won't do anything\n"); + return; + } + printf("\tother thread: using GDT slot %d\n", desc.entry_number); + asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)((desc.entry_number << 3) | 0x3))); + } + + /* + * Step 3: set the selector back to zero. On AMD chips, this will + * preserve GSBASE. + */ + + asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0)); +} + +static void *threadproc(void *ctx) +{ + while (1) { + while (ftx == 0) + syscall(SYS_futex, &ftx, FUTEX_WAIT, 0, NULL, NULL, 0); + if (ftx == 3) + return NULL; + + if (ftx == 1) + do_remote_base(); + else if (ftx == 2) + do_unexpected_base(); + else + errx(1, "helper thread got bad command"); + + ftx = 0; + syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + } +} + +static void set_gs_and_switch_to(unsigned long local, unsigned long remote) +{ + unsigned long base; + + bool hard_zero = false; + if (local == HARD_ZERO) { + hard_zero = true; + local = 0; + } + + printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n", + local, hard_zero ? " and clear gs" : "", remote); + if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0) + err(1, "ARCH_SET_GS"); + if (hard_zero) + asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0)); + + if (read_base(GS) != local) { + nerrs++; + printf("[FAIL]\tGSBASE wasn't set as expected\n"); + } + + remote_base = remote; + ftx = 1; + syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + while (ftx != 0) + syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); + + base = read_base(GS); + if (base == local) { + printf("[OK]\tGSBASE remained 0x%lx\n", local); + } else { + nerrs++; + printf("[FAIL]\tGSBASE changed to 0x%lx\n", base); + } +} + +static void test_unexpected_base(void) +{ + unsigned long base; + + printf("[RUN]\tARCH_SET_GS(0), clear gs, then manipulate GSBASE in a different thread\n"); + if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0) + err(1, "ARCH_SET_GS"); + asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0)); + + ftx = 2; + syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + while (ftx != 0) + syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); + + base = read_base(GS); + if (base == 0) { + printf("[OK]\tGSBASE remained 0\n"); + } else { + nerrs++; + printf("[FAIL]\tGSBASE changed to 0x%lx\n", base); + } +} + +int main() +{ + pthread_t thread; + + sethandler(SIGSEGV, sigsegv, 0); + + check_gs_value(0); + check_gs_value(1); + check_gs_value(0x200000000); + check_gs_value(0); + check_gs_value(0x200000000); + check_gs_value(1); + + for (int sched = 0; sched < 2; sched++) { + mov_0_gs(0, !!sched); + mov_0_gs(1, !!sched); + mov_0_gs(0x200000000, !!sched); + } + + /* Set up for multithreading. */ + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(0, &cpuset); + if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) + err(1, "sched_setaffinity to CPU 0"); /* should never fail */ + + if (pthread_create(&thread, 0, threadproc, 0) != 0) + err(1, "pthread_create"); + + static unsigned long bases_with_hard_zero[] = { + 0, HARD_ZERO, 1, 0x200000000, + }; + + for (int local = 0; local < 4; local++) { + for (int remote = 0; remote < 4; remote++) { + set_gs_and_switch_to(bases_with_hard_zero[local], + bases_with_hard_zero[remote]); + } + } + + test_unexpected_base(); + + ftx = 3; /* Kill the thread. */ + syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + + if (pthread_join(thread, NULL) != 0) + err(1, "pthread_join"); + + return nerrs == 0 ? 0 : 1; +} -- GitLab From d47b50e7a111bb7a56fb1c974728b56209d7f515 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 7 Apr 2016 17:31:45 -0700 Subject: [PATCH 2348/9938] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS ARCH_GET_FS and ARCH_GET_GS attempted to figure out the fsbase and gsbase respectively from saved thread state. This was wrong: fsbase and gsbase live in registers while a thread is running, not in memory. For reasons I can't fathom, the fsbase and gsbase code were different. Since neither was correct, I didn't try to figure out what the point of the difference was. Change it to simply read the MSRs. The code for reading the base for a remote thread is also completely wrong if the target thread uses its own descriptors (which is the case for all 32-bit threaded programs), but fixing that is a different story. Signed-off-by: Andy Lutomirski Reviewed-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rudolf Marek Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/c6e7b507c72ca3bdbf6c7a8a3ceaa0334e873bd9.1460075211.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 6cbab31ac23a..c671b9b015c0 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -566,10 +566,10 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) break; case ARCH_GET_FS: { unsigned long base; - if (task->thread.fsindex == FS_TLS_SEL) - base = read_32bit_tls(task, FS_TLS); - else if (doit) + if (doit) rdmsrl(MSR_FS_BASE, base); + else if (task->thread.fsindex == FS_TLS_SEL) + base = read_32bit_tls(task, FS_TLS); else base = task->thread.fs; ret = put_user(base, (unsigned long __user *)addr); @@ -577,16 +577,11 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) } case ARCH_GET_GS: { unsigned long base; - unsigned gsindex; - if (task->thread.gsindex == GS_TLS_SEL) + if (doit) + rdmsrl(MSR_KERNEL_GS_BASE, base); + else if (task->thread.gsindex == GS_TLS_SEL) base = read_32bit_tls(task, GS_TLS); - else if (doit) { - savesegment(gs, gsindex); - if (gsindex) - rdmsrl(MSR_KERNEL_GS_BASE, base); - else - base = task->thread.gs; - } else + else base = task->thread.gs; ret = put_user(base, (unsigned long __user *)addr); break; -- GitLab From 7a5d67048745e3eab62779c6d043a2e3d95dc848 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 7 Apr 2016 17:31:46 -0700 Subject: [PATCH 2349/9938] x86/cpu: Probe the behavior of nulling out a segment at boot time AMD and Intel do different things when writing zero to a segment selector. Since neither vendor documents the behavior well and it's easy to test the behavior, try nulling fs to see what happens. Signed-off-by: Andy Lutomirski Reviewed-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rudolf Marek Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/61588ba0e0df35beafd363dc8b68a4c5878ef095.1460075211.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/kernel/cpu/common.c | 31 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 8f9afefd2dc5..2a052302bc43 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -294,6 +294,7 @@ #define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */ #define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */ #define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */ +#define X86_BUG_NULL_SEG X86_BUG(9) /* Nulling a selector preserves the base */ #ifdef CONFIG_X86_32 /* diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7fea4079d102..8e40eee5843a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -889,6 +889,35 @@ static void detect_nopl(struct cpuinfo_x86 *c) #endif } +static void detect_null_seg_behavior(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_64 + /* + * Empirically, writing zero to a segment selector on AMD does + * not clear the base, whereas writing zero to a segment + * selector on Intel does clear the base. Intel's behavior + * allows slightly faster context switches in the common case + * where GS is unused by the prev and next threads. + * + * Since neither vendor documents this anywhere that I can see, + * detect it directly instead of hardcoding the choice by + * vendor. + * + * I've designated AMD's behavior as the "bug" because it's + * counterintuitive and less friendly. + */ + + unsigned long old_base, tmp; + rdmsrl(MSR_FS_BASE, old_base); + wrmsrl(MSR_FS_BASE, 1); + loadsegment(fs, 0); + rdmsrl(MSR_FS_BASE, tmp); + if (tmp != 0) + set_cpu_bug(c, X86_BUG_NULL_SEG); + wrmsrl(MSR_FS_BASE, old_base); +#endif +} + static void generic_identify(struct cpuinfo_x86 *c) { c->extended_cpuid_level = 0; @@ -921,6 +950,8 @@ static void generic_identify(struct cpuinfo_x86 *c) get_model_name(c); /* Default name */ detect_nopl(c); + + detect_null_seg_behavior(c); } static void x86_init_cache_qos(struct cpuinfo_x86 *c) -- GitLab From 3e2b68d752c9e09c40d76442aa94d3b8e421b0f1 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 7 Apr 2016 17:31:47 -0700 Subject: [PATCH 2350/9938] x86/asm, sched/x86: Rewrite the FS and GS context switch code The old code was incomprehensible and was buggy on AMD CPUs. Signed-off-by: Andy Lutomirski Reviewed-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rudolf Marek Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/5f6bde874c6fe6831c6711b5b1522a238ba035b4.1460075211.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 148 ++++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 55 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index c671b9b015c0..50337eac1ca2 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -282,7 +282,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) struct fpu *next_fpu = &next->fpu; int cpu = smp_processor_id(); struct tss_struct *tss = &per_cpu(cpu_tss, cpu); - unsigned fsindex, gsindex; + unsigned prev_fsindex, prev_gsindex; fpu_switch_t fpu_switch; fpu_switch = switch_fpu_prepare(prev_fpu, next_fpu, cpu); @@ -292,8 +292,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) * * (e.g. xen_load_tls()) */ - savesegment(fs, fsindex); - savesegment(gs, gsindex); + savesegment(fs, prev_fsindex); + savesegment(gs, prev_gsindex); /* * Load TLS before restoring any segments so that segment loads @@ -336,66 +336,104 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) * Switch FS and GS. * * These are even more complicated than DS and ES: they have - * 64-bit bases are that controlled by arch_prctl. Those bases - * only differ from the values in the GDT or LDT if the selector - * is 0. + * 64-bit bases are that controlled by arch_prctl. The bases + * don't necessarily match the selectors, as user code can do + * any number of things to cause them to be inconsistent. * - * Loading the segment register resets the hidden base part of - * the register to 0 or the value from the GDT / LDT. If the - * next base address zero, writing 0 to the segment register is - * much faster than using wrmsr to explicitly zero the base. + * We don't promise to preserve the bases if the selectors are + * nonzero. We also don't promise to preserve the base if the + * selector is zero and the base doesn't match whatever was + * most recently passed to ARCH_SET_FS/GS. (If/when the + * FSGSBASE instructions are enabled, we'll need to offer + * stronger guarantees.) * - * The thread_struct.fs and thread_struct.gs values are 0 - * if the fs and gs bases respectively are not overridden - * from the values implied by fsindex and gsindex. They - * are nonzero, and store the nonzero base addresses, if - * the bases are overridden. - * - * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should - * be impossible. - * - * Therefore we need to reload the segment registers if either - * the old or new selector is nonzero, and we need to override - * the base address if next thread expects it to be overridden. - * - * This code is unnecessarily slow in the case where the old and - * new indexes are zero and the new base is nonzero -- it will - * unnecessarily write 0 to the selector before writing the new - * base address. - * - * Note: This all depends on arch_prctl being the only way that - * user code can override the segment base. Once wrfsbase and - * wrgsbase are enabled, most of this code will need to change. + * As an invariant, + * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) is + * impossible. */ - if (unlikely(fsindex | next->fsindex | prev->fs)) { + if (next->fsindex) { + /* Loading a nonzero value into FS sets the index and base. */ loadsegment(fs, next->fsindex); - - /* - * If user code wrote a nonzero value to FS, then it also - * cleared the overridden base address. - * - * XXX: if user code wrote 0 to FS and cleared the base - * address itself, we won't notice and we'll incorrectly - * restore the prior base address next time we reschdule - * the process. - */ - if (fsindex) - prev->fs = 0; + } else { + if (next->fs) { + /* Next index is zero but next base is nonzero. */ + if (prev_fsindex) + loadsegment(fs, 0); + wrmsrl(MSR_FS_BASE, next->fs); + } else { + /* Next base and index are both zero. */ + if (static_cpu_has_bug(X86_BUG_NULL_SEG)) { + /* + * We don't know the previous base and can't + * find out without RDMSR. Forcibly clear it. + */ + loadsegment(fs, __USER_DS); + loadsegment(fs, 0); + } else { + /* + * If the previous index is zero and ARCH_SET_FS + * didn't change the base, then the base is + * also zero and we don't need to do anything. + */ + if (prev->fs || prev_fsindex) + loadsegment(fs, 0); + } + } } - if (next->fs) - wrmsrl(MSR_FS_BASE, next->fs); - prev->fsindex = fsindex; + /* + * Save the old state and preserve the invariant. + * NB: if prev_fsindex == 0, then we can't reliably learn the base + * without RDMSR because Intel user code can zero it without telling + * us and AMD user code can program any 32-bit value without telling + * us. + */ + if (prev_fsindex) + prev->fs = 0; + prev->fsindex = prev_fsindex; - if (unlikely(gsindex | next->gsindex | prev->gs)) { + if (next->gsindex) { + /* Loading a nonzero value into GS sets the index and base. */ load_gs_index(next->gsindex); - - /* This works (and fails) the same way as fsindex above. */ - if (gsindex) - prev->gs = 0; + } else { + if (next->gs) { + /* Next index is zero but next base is nonzero. */ + if (prev_gsindex) + load_gs_index(0); + wrmsrl(MSR_KERNEL_GS_BASE, next->gs); + } else { + /* Next base and index are both zero. */ + if (static_cpu_has_bug(X86_BUG_NULL_SEG)) { + /* + * We don't know the previous base and can't + * find out without RDMSR. Forcibly clear it. + * + * This contains a pointless SWAPGS pair. + * Fixing it would involve an explicit check + * for Xen or a new pvop. + */ + load_gs_index(__USER_DS); + load_gs_index(0); + } else { + /* + * If the previous index is zero and ARCH_SET_GS + * didn't change the base, then the base is + * also zero and we don't need to do anything. + */ + if (prev->gs || prev_gsindex) + load_gs_index(0); + } + } } - if (next->gs) - wrmsrl(MSR_KERNEL_GS_BASE, next->gs); - prev->gsindex = gsindex; + /* + * Save the old state and preserve the invariant. + * NB: if prev_gsindex == 0, then we can't reliably learn the base + * without RDMSR because Intel user code can zero it without telling + * us and AMD user code can program any 32-bit value without telling + * us. + */ + if (prev_gsindex) + prev->gs = 0; + prev->gsindex = prev_gsindex; switch_fpu_finish(next_fpu, fpu_switch); -- GitLab From 0230bb038fa99af0c425fc4cffed307e545a9642 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 7 Apr 2016 17:31:48 -0700 Subject: [PATCH 2351/9938] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify() It was in detect_nopl(), which was either a mistake by me or some kind of mis-merge. Signed-off-by: Andy Lutomirski Reviewed-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rudolf Marek Cc: Thomas Gleixner Fixes: ff236456f072 ("x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify") Link: http://lkml.kernel.org/r/0949337f13660461edca08ab67d1a841441289c9.1460075211.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/common.c | 50 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 8e40eee5843a..28d3255edf00 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -861,31 +861,6 @@ static void detect_nopl(struct cpuinfo_x86 *c) clear_cpu_cap(c, X86_FEATURE_NOPL); #else set_cpu_cap(c, X86_FEATURE_NOPL); -#endif - - /* - * ESPFIX is a strange bug. All real CPUs have it. Paravirt - * systems that run Linux at CPL > 0 may or may not have the - * issue, but, even if they have the issue, there's absolutely - * nothing we can do about it because we can't use the real IRET - * instruction. - * - * NB: For the time being, only 32-bit kernels support - * X86_BUG_ESPFIX as such. 64-bit kernels directly choose - * whether to apply espfix using paravirt hooks. If any - * non-paravirt system ever shows up that does *not* have the - * ESPFIX issue, we can change this. - */ -#ifdef CONFIG_X86_32 -#ifdef CONFIG_PARAVIRT - do { - extern void native_iret(void); - if (pv_cpu_ops.iret == native_iret) - set_cpu_bug(c, X86_BUG_ESPFIX); - } while (0); -#else - set_cpu_bug(c, X86_BUG_ESPFIX); -#endif #endif } @@ -952,6 +927,31 @@ static void generic_identify(struct cpuinfo_x86 *c) detect_nopl(c); detect_null_seg_behavior(c); + + /* + * ESPFIX is a strange bug. All real CPUs have it. Paravirt + * systems that run Linux at CPL > 0 may or may not have the + * issue, but, even if they have the issue, there's absolutely + * nothing we can do about it because we can't use the real IRET + * instruction. + * + * NB: For the time being, only 32-bit kernels support + * X86_BUG_ESPFIX as such. 64-bit kernels directly choose + * whether to apply espfix using paravirt hooks. If any + * non-paravirt system ever shows up that does *not* have the + * ESPFIX issue, we can change this. + */ +#ifdef CONFIG_X86_32 +# ifdef CONFIG_PARAVIRT + do { + extern void native_iret(void); + if (pv_cpu_ops.iret == native_iret) + set_cpu_bug(c, X86_BUG_ESPFIX); + } while (0); +# else + set_cpu_bug(c, X86_BUG_ESPFIX); +# endif +#endif } static void x86_init_cache_qos(struct cpuinfo_x86 *c) -- GitLab From 96e5d28ae7a5250f3deb2434f1895c9daf48b1bd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 7 Apr 2016 17:31:49 -0700 Subject: [PATCH 2352/9938] x86/cpu: Add Erratum 88 detection on AMD Erratum 88 affects old AMD K8s, where a SWAPGS fails to cause an input dependency on GS. Therefore, we need to MFENCE before it. But that MFENCE is expensive and unnecessary on the remaining x86 CPUs out there so patch it out on the CPUs which don't require it. Signed-off-by: Borislav Petkov Signed-off-by: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rudolf Marek Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/aec6b2df1bfc56101d4e9e2e5d5d570bf41663c6.1460075211.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_64.S | 2 +- arch/x86/include/asm/cpufeatures.h | 2 ++ arch/x86/kernel/cpu/amd.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 858b555e274b..64d2033d1e49 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -783,7 +783,7 @@ ENTRY(native_load_gs_index) SWAPGS gs_change: movl %edi, %gs -2: mfence /* workaround */ +2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE SWAPGS popfq ret diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 2a052302bc43..7bfb6b70c745 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -295,6 +295,8 @@ #define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */ #define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */ #define X86_BUG_NULL_SEG X86_BUG(9) /* Nulling a selector preserves the base */ +#define X86_BUG_SWAPGS_FENCE X86_BUG(10) /* SWAPGS without input dep on GS */ + #ifdef CONFIG_X86_32 /* diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 6e47e3a916f1..b7cc9efe08b5 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -632,6 +632,7 @@ static void init_amd_k8(struct cpuinfo_x86 *c) */ msr_set_bit(MSR_K7_HWCR, 6); #endif + set_cpu_bug(c, X86_BUG_SWAPGS_FENCE); } static void init_amd_gh(struct cpuinfo_x86 *c) -- GitLab From 42c748bb2544f21c3d115240527fe4478e193641 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 7 Apr 2016 17:31:50 -0700 Subject: [PATCH 2353/9938] x86/entry/64: Make gs_change a local label ... so that it doesn't appear in objdump output. Signed-off-by: Borislav Petkov Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rudolf Marek Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/b9c532a0e5f8d56dede2bd59767d40024d5a75e2.1460075211.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_64.S | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 64d2033d1e49..1693c17dbf81 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -781,7 +781,7 @@ ENTRY(native_load_gs_index) pushfq DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI) SWAPGS -gs_change: +.Lgs_change: movl %edi, %gs 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE SWAPGS @@ -789,7 +789,7 @@ gs_change: ret END(native_load_gs_index) - _ASM_EXTABLE(gs_change, bad_gs) + _ASM_EXTABLE(.Lgs_change, bad_gs) .section .fixup, "ax" /* running with kernelgs */ bad_gs: @@ -1019,13 +1019,13 @@ ENTRY(error_entry) movl %ecx, %eax /* zero extend */ cmpq %rax, RIP+8(%rsp) je .Lbstep_iret - cmpq $gs_change, RIP+8(%rsp) + cmpq $.Lgs_change, RIP+8(%rsp) jne .Lerror_entry_done /* - * hack: gs_change can fail with user gsbase. If this happens, fix up + * hack: .Lgs_change can fail with user gsbase. If this happens, fix up * gsbase and proceed. We'll fix up the exception and land in - * gs_change's error handler with kernel gsbase. + * .Lgs_change's error handler with kernel gsbase. */ jmp .Lerror_entry_from_usermode_swapgs -- GitLab From 0c034fe37718990e0ffdd9622bd6cc5b4f93111f Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 12 Apr 2016 17:46:39 -0300 Subject: [PATCH 2354/9938] mtd: Uninline mtd_write_oob and move it to mtdcore.c There's no reason for having mtd_write_oob inlined in mtd.h header. Move it to mtdcore.c where it belongs. Signed-off-by: Ezequiel Garcia Acked-by: Boris Brezillon Signed-off-by: Jacek Anaszewski --- drivers/mtd/mtdcore.c | 12 ++++++++++++ include/linux/mtd/mtd.h | 12 +----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 309625130b21..99d83f3331b0 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -997,6 +997,18 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) } EXPORT_SYMBOL_GPL(mtd_read_oob); +int mtd_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + ops->retlen = ops->oobretlen = 0; + if (!mtd->_write_oob) + return -EOPNOTSUPP; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + return mtd->_write_oob(mtd, to, ops); +} +EXPORT_SYMBOL_GPL(mtd_write_oob); + /* * Method to access the protection register area, present in some flash * devices. The user data is one time programmable but the factory data is read diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 771272187316..ef9fea4fc400 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -283,17 +283,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); - -static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops) -{ - ops->retlen = ops->oobretlen = 0; - if (!mtd->_write_oob) - return -EOPNOTSUPP; - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - return mtd->_write_oob(mtd, to, ops); -} +int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, struct otp_info *buf); -- GitLab From 4b721174c7976f26300e39aa42714fb5a54bebb5 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 12 Apr 2016 17:46:40 -0300 Subject: [PATCH 2355/9938] leds: trigger: Introduce a MTD (NAND/NOR) trigger This commit introduces a MTD trigger for flash (NAND/NOR) device activity. The implementation is copied from IDE disk. This trigger deprecates the "nand-disk" LED trigger, but for backwards compatibility, we still keep the "nand-disk" trigger around. The motivation for deprecating the "nand-disk" LED trigger is that it only works for NAND drivers, whereas the "mtd" LED trigger is more generic (in fact, "nand-disk" currently only works for certain NAND drivers). Signed-off-by: Ezequiel Garcia Acked-by: Boris Brezillon Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/Kconfig | 8 ++++++ drivers/leds/trigger/Makefile | 1 + drivers/leds/trigger/ledtrig-mtd.c | 45 ++++++++++++++++++++++++++++++ include/linux/leds.h | 6 ++++ 4 files changed, 60 insertions(+) create mode 100644 drivers/leds/trigger/ledtrig-mtd.c diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 554f5bfbeced..beac8c31c51b 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_MTD + bool "LED MTD (NAND/NOR) Trigger" + depends on MTD + depends on LEDS_TRIGGERS + help + This allows LEDs to be controlled by MTD activity. + If unsure, say N. + config LEDS_TRIGGER_HEARTBEAT tristate "LED Heartbeat Trigger" depends on LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 547bf5c80e52..8cc64a4f4e25 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o +obj-$(CONFIG_LEDS_TRIGGER_MTD) += ledtrig-mtd.o obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o diff --git a/drivers/leds/trigger/ledtrig-mtd.c b/drivers/leds/trigger/ledtrig-mtd.c new file mode 100644 index 000000000000..99b5b0a4d826 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-mtd.c @@ -0,0 +1,45 @@ +/* + * LED MTD trigger + * + * Copyright 2016 Ezequiel Garcia + * + * Based on LED IDE-Disk Activity Trigger + * + * Copyright 2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include + +#define BLINK_DELAY 30 + +DEFINE_LED_TRIGGER(ledtrig_mtd); +DEFINE_LED_TRIGGER(ledtrig_nand); + +void ledtrig_mtd_activity(void) +{ + unsigned long blink_delay = BLINK_DELAY; + + led_trigger_blink_oneshot(ledtrig_mtd, + &blink_delay, &blink_delay, 0); + led_trigger_blink_oneshot(ledtrig_nand, + &blink_delay, &blink_delay, 0); +} +EXPORT_SYMBOL(ledtrig_mtd_activity); + +static int __init ledtrig_mtd_init(void) +{ + led_trigger_register_simple("mtd", &ledtrig_mtd); + led_trigger_register_simple("nand-disk", &ledtrig_nand); + + return 0; +} +device_initcall(ledtrig_mtd_init); diff --git a/include/linux/leds.h b/include/linux/leds.h index f203a8f89d30..19eb10278bea 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -329,6 +329,12 @@ extern void ledtrig_ide_activity(void); static inline void ledtrig_ide_activity(void) {} #endif +#ifdef CONFIG_LEDS_TRIGGER_MTD +extern void ledtrig_mtd_activity(void); +#else +static inline void ledtrig_mtd_activity(void) {} +#endif + #if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE) extern void ledtrig_flash_ctrl(bool on); extern void ledtrig_torch_ctrl(bool on); -- GitLab From 4c7e054f08822dc7539d33dbd3e5b9b67297bed5 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 12 Apr 2016 17:46:41 -0300 Subject: [PATCH 2356/9938] mtd: nand: Remove the "nand-disk" LED trigger This commit removes the "nand-disk" LED trigger from the NAND code. A trigger with the same name is already available selecting LEDS_TRIGGER_MTD. Note that "nand-disk" trigger is being deprecated in favor of the "mtd" trigger. Signed-off-by: Ezequiel Garcia Acked-by: Boris Brezillon Signed-off-by: Jacek Anaszewski --- drivers/mtd/nand/nand_base.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b6facac54fc0..8d6287ef3926 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -97,12 +96,6 @@ static int nand_get_device(struct mtd_info *mtd, int new_state); static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); -/* - * For devices which display every fart in the system on a separate LED. Is - * compiled away when LED support is disabled. - */ -DEFINE_LED_TRIGGER(nand_led_trigger); - static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) { @@ -540,19 +533,16 @@ void nand_wait_ready(struct mtd_info *mtd) if (in_interrupt() || oops_in_progress) return panic_nand_wait_ready(mtd, timeo); - led_trigger_event(nand_led_trigger, LED_FULL); /* Wait until command is processed or timeout occurs */ timeo = jiffies + msecs_to_jiffies(timeo); do { if (chip->dev_ready(mtd)) - goto out; + return; cond_resched(); } while (time_before(jiffies, timeo)); if (!chip->dev_ready(mtd)) pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); -out: - led_trigger_event(nand_led_trigger, LED_OFF); } EXPORT_SYMBOL_GPL(nand_wait_ready); @@ -885,8 +875,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) int status; unsigned long timeo = 400; - led_trigger_event(nand_led_trigger, LED_FULL); - /* * Apply this short delay always to ensure that we do wait tWB in any * case on any machine. @@ -910,7 +898,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) cond_resched(); } while (time_before(jiffies, timeo)); } - led_trigger_event(nand_led_trigger, LED_OFF); status = (int)chip->read_byte(mtd); /* This can happen if in case of timeout or buggy dev_ready */ @@ -4474,20 +4461,6 @@ void nand_release(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(nand_release); -static int __init nand_base_init(void) -{ - led_trigger_register_simple("nand-disk", &nand_led_trigger); - return 0; -} - -static void __exit nand_base_exit(void) -{ - led_trigger_unregister_simple(nand_led_trigger); -} - -module_init(nand_base_init); -module_exit(nand_base_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Steven J. Hill "); MODULE_AUTHOR("Thomas Gleixner "); -- GitLab From fea728c098ee1e6a4a2855962390487ee5d1cdc2 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 12 Apr 2016 17:46:42 -0300 Subject: [PATCH 2357/9938] mtd: Hook I/O activity to the MTD LED trigger Now that we've added the MTD LED trigger, we need to call each I/O path to ledtrig_mtd_activity. Signed-off-by: Ezequiel Garcia Acked-by: Boris Brezillon Signed-off-by: Jacek Anaszewski --- drivers/mtd/mtdcore.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 99d83f3331b0..bee180bd11e7 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -862,6 +863,7 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) mtd_erase_callback(instr); return 0; } + ledtrig_mtd_activity(); return mtd->_erase(mtd, instr); } EXPORT_SYMBOL_GPL(mtd_erase); @@ -925,6 +927,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, if (!len) return 0; + ledtrig_mtd_activity(); /* * In the absence of an error, drivers return a non-negative integer * representing the maximum number of bitflips that were corrected on @@ -949,6 +952,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, return -EROFS; if (!len) return 0; + ledtrig_mtd_activity(); return mtd->_write(mtd, to, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_write); @@ -982,6 +986,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) ops->retlen = ops->oobretlen = 0; if (!mtd->_read_oob) return -EOPNOTSUPP; + + ledtrig_mtd_activity(); /* * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics * similar to mtd->_read(), returning a non-negative integer @@ -1005,6 +1011,7 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to, return -EOPNOTSUPP; if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; + ledtrig_mtd_activity(); return mtd->_write_oob(mtd, to, ops); } EXPORT_SYMBOL_GPL(mtd_write_oob); -- GitLab From 1ed95e52d902035e39a715ff3a314a893a96e5b7 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 7 Apr 2016 17:16:59 -0700 Subject: [PATCH 2358/9938] x86/vdso: Remove direct HPET access through the vDSO Allowing user code to map the HPET is problematic. HPET implementations are notoriously buggy, and there are probably many machines on which even MMIO reads from bogus HPET addresses are problematic. We have a report that the Dell Precision M2800 with: ACPI: HPET 0x00000000C8FE6238 000038 (v01 DELL CBX3 01072009 AMI. 00000005) is either so slow when accessing the HPET or actually hangs in some regard, causing soft lockups to be reported if users do unexpected things to the HPET. The vclock HPET code has also always been a questionable speedup. Accessing an HPET is exceedingly slow (on the order of several microseconds), so the added overhead in requiring a syscall to read the HPET is a small fraction of the total code of accessing it. To avoid future problems, let's just delete the code entirely. In the long run, this could actually be a speedup. Waiman Long as a patch to optimize the case where multiple CPUs contend for the HPET, but that won't help unless all the accesses are mediated by the kernel. Reported-by: Rasmus Villemoes Signed-off-by: Andy Lutomirski Reviewed-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Waiman Long Cc: Waiman Long Link: http://lkml.kernel.org/r/d2f90bba98db9905041cff294646d290d378f67a.1460074438.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/vdso/vclock_gettime.c | 15 --------------- arch/x86/entry/vdso/vdso-layout.lds.S | 5 ++--- arch/x86/entry/vdso/vma.c | 11 ----------- arch/x86/include/asm/clocksource.h | 9 ++++----- arch/x86/kernel/hpet.c | 1 - arch/x86/kvm/trace.h | 3 +-- 6 files changed, 7 insertions(+), 37 deletions(-) diff --git a/arch/x86/entry/vdso/vclock_gettime.c b/arch/x86/entry/vdso/vclock_gettime.c index 03c3eb77bfce..2f02d23a05ef 100644 --- a/arch/x86/entry/vdso/vclock_gettime.c +++ b/arch/x86/entry/vdso/vclock_gettime.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -28,16 +27,6 @@ extern int __vdso_clock_gettime(clockid_t clock, struct timespec *ts); extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); extern time_t __vdso_time(time_t *t); -#ifdef CONFIG_HPET_TIMER -extern u8 hpet_page - __attribute__((visibility("hidden"))); - -static notrace cycle_t vread_hpet(void) -{ - return *(const volatile u32 *)(&hpet_page + HPET_COUNTER); -} -#endif - #ifdef CONFIG_PARAVIRT_CLOCK extern u8 pvclock_page __attribute__((visibility("hidden"))); @@ -195,10 +184,6 @@ notrace static inline u64 vgetsns(int *mode) if (gtod->vclock_mode == VCLOCK_TSC) cycles = vread_tsc(); -#ifdef CONFIG_HPET_TIMER - else if (gtod->vclock_mode == VCLOCK_HPET) - cycles = vread_hpet(); -#endif #ifdef CONFIG_PARAVIRT_CLOCK else if (gtod->vclock_mode == VCLOCK_PVCLOCK) cycles = vread_pvclock(mode); diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S index 4158acc17df0..a708aa90b507 100644 --- a/arch/x86/entry/vdso/vdso-layout.lds.S +++ b/arch/x86/entry/vdso/vdso-layout.lds.S @@ -25,7 +25,7 @@ SECTIONS * segment. */ - vvar_start = . - 3 * PAGE_SIZE; + vvar_start = . - 2 * PAGE_SIZE; vvar_page = vvar_start; /* Place all vvars at the offsets in asm/vvar.h. */ @@ -35,8 +35,7 @@ SECTIONS #undef __VVAR_KERNEL_LDS #undef EMIT_VVAR - hpet_page = vvar_start + PAGE_SIZE; - pvclock_page = vvar_start + 2 * PAGE_SIZE; + pvclock_page = vvar_start + PAGE_SIZE; . = SIZEOF_HEADERS; diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 10f704584922..b3cf81333a54 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -129,16 +128,6 @@ static int vvar_fault(const struct vm_special_mapping *sm, if (sym_offset == image->sym_vvar_page) { ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, __pa_symbol(&__vvar_page) >> PAGE_SHIFT); - } else if (sym_offset == image->sym_hpet_page) { -#ifdef CONFIG_HPET_TIMER - if (hpet_address && vclock_was_used(VCLOCK_HPET)) { - ret = vm_insert_pfn_prot( - vma, - (unsigned long)vmf->virtual_address, - hpet_address >> PAGE_SHIFT, - pgprot_noncached(PAGE_READONLY)); - } -#endif } else if (sym_offset == image->sym_pvclock_page) { struct pvclock_vsyscall_time_info *pvti = pvclock_pvti_cpu0_va(); diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h index d194266acb28..eae33c7170c8 100644 --- a/arch/x86/include/asm/clocksource.h +++ b/arch/x86/include/asm/clocksource.h @@ -3,11 +3,10 @@ #ifndef _ASM_X86_CLOCKSOURCE_H #define _ASM_X86_CLOCKSOURCE_H -#define VCLOCK_NONE 0 /* No vDSO clock available. */ -#define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */ -#define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */ -#define VCLOCK_PVCLOCK 3 /* vDSO should use vread_pvclock. */ -#define VCLOCK_MAX 3 +#define VCLOCK_NONE 0 /* No vDSO clock available. */ +#define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */ +#define VCLOCK_PVCLOCK 2 /* vDSO should use vread_pvclock. */ +#define VCLOCK_MAX 2 struct arch_clocksource_data { int vclock_mode; diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index a1f0e4a5c47e..7282c2e3858e 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -773,7 +773,6 @@ static struct clocksource clocksource_hpet = { .mask = HPET_MASK, .flags = CLOCK_SOURCE_IS_CONTINUOUS, .resume = hpet_resume_counter, - .archdata = { .vclock_mode = VCLOCK_HPET }, }; static int hpet_clocksource_register(void) diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 2f1ea2f61e1f..b72743c5668d 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -809,8 +809,7 @@ TRACE_EVENT(kvm_write_tsc_offset, #define host_clocks \ {VCLOCK_NONE, "none"}, \ - {VCLOCK_TSC, "tsc"}, \ - {VCLOCK_HPET, "hpet"} \ + {VCLOCK_TSC, "tsc"} \ TRACE_EVENT(kvm_update_master_clock, TP_PROTO(bool use_master_clock, unsigned int host_clock, bool offset_matched), -- GitLab From a035d71b1205f880d85752869053b14813366108 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 11 Apr 2016 17:28:32 +0200 Subject: [PATCH 2359/9938] i2c: octeon: Increase retry default and use fixed timeout value Convert the adapter timeout to 2 ms independently of depending on CONFIG_HZ. CONFIG_HZ is 100 for MIPS Cavium-Octeon so the timeout value is not changed. Also set retries to 5 to improve robustness. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 46fb6c42934f..c4abf16468ca 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -426,7 +426,6 @@ static struct i2c_adapter octeon_i2c_ops = { .owner = THIS_MODULE, .name = "OCTEON adapter", .algo = &octeon_i2c_algo, - .timeout = HZ / 50, }; /* calculate and set clock divisors */ @@ -553,6 +552,8 @@ static int octeon_i2c_probe(struct platform_device *pdev) octeon_i2c_set_clock(i2c); i2c->adap = octeon_i2c_ops; + i2c->adap.timeout = msecs_to_jiffies(2); + i2c->adap.retries = 5; i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.of_node = node; i2c_set_adapdata(&i2c->adap, i2c); -- GitLab From 482dd2ef124484601adea82e5e806e81e2bc5521 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 7 Apr 2016 22:43:59 +0200 Subject: [PATCH 2360/9938] x86/syscalls: Wire up compat readv2/writev2 syscalls Reported-by: David Smith Tested-by: David Smith Signed-off-by: Christoph Hellwig Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160407204359.GA3720@lst.de Signed-off-by: Ingo Molnar --- arch/x86/entry/syscalls/syscall_32.tbl | 4 ++-- arch/x86/entry/syscalls/syscall_64.tbl | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index b30dd8154cc2..4cddd17153fb 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -384,5 +384,5 @@ 375 i386 membarrier sys_membarrier 376 i386 mlock2 sys_mlock2 377 i386 copy_file_range sys_copy_file_range -378 i386 preadv2 sys_preadv2 -379 i386 pwritev2 sys_pwritev2 +378 i386 preadv2 sys_preadv2 compat_sys_preadv2 +379 i386 pwritev2 sys_pwritev2 compat_sys_pwritev2 diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index cac6d17ce5db..555263e385c9 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -374,3 +374,5 @@ 543 x32 io_setup compat_sys_io_setup 544 x32 io_submit compat_sys_io_submit 545 x32 execveat compat_sys_execveat/ptregs +534 x32 preadv2 compat_sys_preadv2 +535 x32 pwritev2 compat_sys_pwritev2 -- GitLab From 371feaff9980a7060f9fea5c795381aaea5f941d Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Tue, 12 Apr 2016 18:20:58 +0530 Subject: [PATCH 2361/9938] arm64: defconfig: Enable PL330 DMA controller This patch enables PL330 DMA controller found on exynos7 SoCs. Signed-off-by: Alim Akhtar Signed-off-by: Krzysztof Kozlowski --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f70505186820..60e5886309d9 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -230,6 +230,7 @@ CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_XGENE=y CONFIG_DMADEVICES=y CONFIG_QCOM_BAM_DMA=y +CONFIG_PL330_DMA=y CONFIG_TEGRA20_APB_DMA=y CONFIG_RCAR_DMAC=y CONFIG_VFIO=y -- GitLab From f541bb382fd6b4cd60c9f1fcc2afca1d1d8ab84c Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 11 Apr 2016 17:28:33 +0200 Subject: [PATCH 2362/9938] i2c: octeon: Move set-clock and init-lowlevel upward No functional change, just moving the functions upward in preparation of improving the recovery. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 126 ++++++++++++++++---------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index c4abf16468ca..f647667a3a47 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -214,6 +214,69 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) return 0; } +/* calculate and set clock divisors */ +static void octeon_i2c_set_clock(struct octeon_i2c *i2c) +{ + int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff; + int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; + + for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) { + /* + * An mdiv value of less than 2 seems to not work well + * with ds1337 RTCs, so we constrain it to larger values. + */ + for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) { + /* + * For given ndiv and mdiv values check the + * two closest thp values. + */ + tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10; + tclk *= (1 << ndiv_idx); + thp_base = (i2c->sys_freq / (tclk * 2)) - 1; + + for (inc = 0; inc <= 1; inc++) { + thp_idx = thp_base + inc; + if (thp_idx < 5 || thp_idx > 0xff) + continue; + + foscl = i2c->sys_freq / (2 * (thp_idx + 1)); + foscl = foscl / (1 << ndiv_idx); + foscl = foscl / (mdiv_idx + 1) / 10; + diff = abs(foscl - i2c->twsi_freq); + if (diff < delta_hz) { + delta_hz = diff; + thp = thp_idx; + mdiv = mdiv_idx; + ndiv = ndiv_idx; + } + } + } + } + octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp); + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); +} + +static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) +{ + u8 status; + int tries; + + /* disable high level controller, enable bus access */ + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + + /* reset controller */ + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0); + + for (tries = 10; tries; tries--) { + udelay(1); + status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + if (status == STAT_IDLE) + return 0; + } + dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status); + return -EIO; +} + /** * octeon_i2c_start - send START to the bus * @i2c: The struct octeon_i2c @@ -428,69 +491,6 @@ static struct i2c_adapter octeon_i2c_ops = { .algo = &octeon_i2c_algo, }; -/* calculate and set clock divisors */ -static void octeon_i2c_set_clock(struct octeon_i2c *i2c) -{ - int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff; - int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; - - for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) { - /* - * An mdiv value of less than 2 seems to not work well - * with ds1337 RTCs, so we constrain it to larger values. - */ - for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) { - /* - * For given ndiv and mdiv values check the - * two closest thp values. - */ - tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10; - tclk *= (1 << ndiv_idx); - thp_base = (i2c->sys_freq / (tclk * 2)) - 1; - - for (inc = 0; inc <= 1; inc++) { - thp_idx = thp_base + inc; - if (thp_idx < 5 || thp_idx > 0xff) - continue; - - foscl = i2c->sys_freq / (2 * (thp_idx + 1)); - foscl = foscl / (1 << ndiv_idx); - foscl = foscl / (mdiv_idx + 1) / 10; - diff = abs(foscl - i2c->twsi_freq); - if (diff < delta_hz) { - delta_hz = diff; - thp = thp_idx; - mdiv = mdiv_idx; - ndiv = ndiv_idx; - } - } - } - } - octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); -} - -static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) -{ - u8 status; - int tries; - - /* disable high level controller, enable bus access */ - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); - - /* reset controller */ - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0); - - for (tries = 10; tries; tries--) { - udelay(1); - status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); - if (status == STAT_IDLE) - return 0; - } - dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status); - return -EIO; -} - static int octeon_i2c_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; -- GitLab From bc405cd69a728d0a82bae8395fe43ec7b0afd1c6 Mon Sep 17 00:00:00 2001 From: Alexandre Macabies Date: Tue, 12 Apr 2016 18:53:00 +0200 Subject: [PATCH 2363/9938] ieee802154: add security bit check function ieee802154_is_secen checks if the 802.15.4 security bit is set in the frame control field. Signed-off-by: Alexander Aring Signed-off-by: Alexandre Macabies Reviewed-by: Stefan Schmidt Acked-by: Alan Ott Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index d3e415674dac..56090f195339 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -218,6 +218,7 @@ enum { /* frame control handling */ #define IEEE802154_FCTL_FTYPE 0x0003 #define IEEE802154_FCTL_ACKREQ 0x0020 +#define IEEE802154_FCTL_SECEN 0x0004 #define IEEE802154_FCTL_INTRA_PAN 0x0040 #define IEEE802154_FTYPE_DATA 0x0001 @@ -232,6 +233,15 @@ static inline int ieee802154_is_data(__le16 fc) cpu_to_le16(IEEE802154_FTYPE_DATA); } +/** + * ieee802154_is_secen - check if Security bit is set + * @fc: frame control bytes in little-endian byteorder + */ +static inline bool ieee802154_is_secen(__le16 fc) +{ + return fc & cpu_to_le16(IEEE802154_FCTL_SECEN); +} + /** * ieee802154_is_ackreq - check if acknowledgment request bit is set * @fc: frame control bytes in little-endian byteorder -- GitLab From 5a62f3c6de73bd0b4ac40a33674d20f1bfb586d5 Mon Sep 17 00:00:00 2001 From: Alexandre Macabies Date: Tue, 12 Apr 2016 18:53:01 +0200 Subject: [PATCH 2364/9938] mrf24j40: fix security-enabled processing on inbound frames When receiving a security-enabled IEEE 802.15.4 frame, the MRF24J40 triggers a SECIF interrupt that needs to be handled for RX processing to keep functioning properly. This patch enables the SECIF interrupt and makes the MRF ignores all hardware processing of security-enabled frames, that is handled by the ieee802154 stack instead. Signed-off-by: Alexander Aring Signed-off-by: Alexandre Macabies Reviewed-by: Stefan Schmidt Acked-by: Alan Ott Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 764a2bddfaee..adc67be2e04f 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -85,10 +85,13 @@ #define REG_INTSTAT 0x31 /* Interrupt Status */ #define BIT_TXNIF BIT(0) #define BIT_RXIF BIT(3) +#define BIT_SECIF BIT(4) +#define BIT_SECIGNORE BIT(7) #define REG_INTCON 0x32 /* Interrupt Control */ #define BIT_TXNIE BIT(0) #define BIT_RXIE BIT(3) +#define BIT_SECIE BIT(4) #define REG_GPIO 0x33 /* GPIO */ #define REG_TRISGPIO 0x34 /* GPIO direction */ @@ -616,7 +619,7 @@ static int mrf24j40_start(struct ieee802154_hw *hw) /* Clear TXNIE and RXIE. Enable interrupts */ return regmap_update_bits(devrec->regmap_short, REG_INTCON, - BIT_TXNIE | BIT_RXIE, 0); + BIT_TXNIE | BIT_RXIE | BIT_SECIE, 0); } static void mrf24j40_stop(struct ieee802154_hw *hw) @@ -1025,6 +1028,11 @@ static void mrf24j40_intstat_complete(void *context) enable_irq(devrec->spi->irq); + /* Ignore Rx security decryption */ + if (intstat & BIT_SECIF) + regmap_write_async(devrec->regmap_short, REG_SECCON0, + BIT_SECIGNORE); + /* Check for TX complete */ if (intstat & BIT_TXNIF) ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false); -- GitLab From 87820441c402f5fde42a84ae96ffb4cbd4109510 Mon Sep 17 00:00:00 2001 From: Alexandre Macabies Date: Tue, 12 Apr 2016 18:53:02 +0200 Subject: [PATCH 2365/9938] mrf24j40: apply the security-enabled bit on secured outbound frames We set the TXNSECEN bit of register TXNCON to on when transmitting a security-enabled frame, as described in section 3.12.2 of the MRF datasheet. Signed-off-by: Alexander Aring Signed-off-by: Alexandre Macabies Reviewed-by: Stefan Schmidt Acked-by: Alan Ott Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index adc67be2e04f..f446db828561 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -61,6 +61,7 @@ #define REG_TXBCON0 0x1A #define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */ #define BIT_TXNTRIG BIT(0) +#define BIT_TXNSECEN BIT(1) #define BIT_TXNACKREQ BIT(2) #define REG_TXG1CON 0x1C @@ -551,6 +552,9 @@ static void write_tx_buf_complete(void *context) u8 val = BIT_TXNTRIG; int ret; + if (ieee802154_is_secen(fc)) + val |= BIT_TXNSECEN; + if (ieee802154_is_ackreq(fc)) val |= BIT_TXNACKREQ; -- GitLab From b7594148c73cb506487b5f00a6574beceea0e3a0 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:14 +0200 Subject: [PATCH 2366/9938] ieee802154: cleanups for ieee802154.h This patch removes some const from non-pointer types and fixes the function name for the ieee802154_is_valid_extended_unicast_addr comment. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 56090f195339..9d84a924b747 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -270,17 +270,17 @@ static inline bool ieee802154_is_intra_pan(__le16 fc) * * @len: psdu len with (MHR + payload + MFR) */ -static inline bool ieee802154_is_valid_psdu_len(const u8 len) +static inline bool ieee802154_is_valid_psdu_len(u8 len) { return (len == IEEE802154_ACK_PSDU_LEN || (len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU)); } /** - * ieee802154_is_valid_psdu_len - check if extended addr is valid + * ieee802154_is_valid_extended_unicast_addr - check if extended addr is valid * @addr: extended addr to check */ -static inline bool ieee802154_is_valid_extended_unicast_addr(const __le64 addr) +static inline bool ieee802154_is_valid_extended_unicast_addr(__le64 addr) { /* Bail out if the address is all zero, or if the group * address bit is set. -- GitLab From 118a5cf8ae236cdfa1eb4f21530843a8494722ef Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:15 +0200 Subject: [PATCH 2367/9938] ieee802154: add short address helpers This patch introduce some short address handling functionality into ieee802154 headers. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 29 +++++++++++++++++++++++++++++ include/net/mac802154.h | 10 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 9d84a924b747..acedbb68a5a3 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -47,6 +47,7 @@ #define IEEE802154_ADDR_SHORT_UNSPEC 0xfffe #define IEEE802154_EXTENDED_ADDR_LEN 8 +#define IEEE802154_SHORT_ADDR_LEN 2 #define IEEE802154_LIFS_PERIOD 40 #define IEEE802154_SIFS_PERIOD 12 @@ -289,6 +290,34 @@ static inline bool ieee802154_is_valid_extended_unicast_addr(__le64 addr) !(addr & cpu_to_le64(0x0100000000000000ULL))); } +/** + * ieee802154_is_broadcast_short_addr - check if short addr is broadcast + * @addr: short addr to check + */ +static inline bool ieee802154_is_broadcast_short_addr(__le16 addr) +{ + return (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST)); +} + +/** + * ieee802154_is_unspec_short_addr - check if short addr is unspecified + * @addr: short addr to check + */ +static inline bool ieee802154_is_unspec_short_addr(__le16 addr) +{ + return (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC)); +} + +/** + * ieee802154_is_valid_src_short_addr - check if source short address is valid + * @addr: short addr to check + */ +static inline bool ieee802154_is_valid_src_short_addr(__le16 addr) +{ + return !(ieee802154_is_broadcast_short_addr(addr) || + ieee802154_is_unspec_short_addr(addr)); +} + /** * ieee802154_random_extended_addr - generates a random extended address * @addr: extended addr pointer to place the random address diff --git a/include/net/mac802154.h b/include/net/mac802154.h index 6cd7a70706a9..e465c8551ac3 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -287,6 +287,16 @@ static inline void ieee802154_le16_to_be16(void *be16_dst, const void *le16_src) put_unaligned_be16(get_unaligned_le16(le16_src), be16_dst); } +/** + * ieee802154_be16_to_le16 - copies and convert be16 to le16 + * @le16_dst: le16 destination pointer + * @be16_src: be16 source pointer + */ +static inline void ieee802154_be16_to_le16(void *le16_dst, const void *be16_src) +{ + put_unaligned_le16(get_unaligned_be16(be16_src), le16_dst); +} + /** * ieee802154_alloc_hw - Allocate a new hardware device * -- GitLab From 9e3b71f3436415f917eb569cde792b223cceebc0 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:16 +0200 Subject: [PATCH 2368/9938] nl802154: avoid address change while running lowpan The generation of autoconfigured IPv6 link-local addresses starts with a notification on interface up. To handle autoconfiguration according to RFC 4944 requires pan id and short address to generate an autoconfigured link-local address. This patch will avoid changing of these link-layer address configuration while lowpan interface is up. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- net/ieee802154/nl802154.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 16ef0d9f566e..5f1dc4bfeed5 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1074,6 +1074,11 @@ static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info) if (netif_running(dev)) return -EBUSY; + if (wpan_dev->lowpan_dev) { + if (netif_running(wpan_dev->lowpan_dev)) + return -EBUSY; + } + /* don't change address fields on monitor */ if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || !info->attrs[NL802154_ATTR_PAN_ID]) @@ -1105,6 +1110,11 @@ static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info) if (netif_running(dev)) return -EBUSY; + if (wpan_dev->lowpan_dev) { + if (netif_running(wpan_dev->lowpan_dev)) + return -EBUSY; + } + /* don't change address fields on monitor */ if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || !info->attrs[NL802154_ATTR_SHORT_ADDR]) -- GitLab From 5a7f97e570fbe0ae7e6fd035f7af0cd6a1a9baa1 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:17 +0200 Subject: [PATCH 2369/9938] ieee802154: 6lowpan: fix short addr hash The short address is unique in combination with the panid. This patch will add the panid for generating an ieee802154 address hash. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- net/ieee802154/6lowpan/6lowpan_i.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h index b4e17a7c0df0..b4092a9ff24a 100644 --- a/net/ieee802154/6lowpan/6lowpan_i.h +++ b/net/ieee802154/6lowpan/6lowpan_i.h @@ -41,7 +41,7 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a) return (((__force u64)a->extended_addr) >> 32) ^ (((__force u64)a->extended_addr) & 0xffffffff); case IEEE802154_ADDR_SHORT: - return (__force u32)(a->short_addr); + return (__force u32)(a->short_addr + (a->pan_id << 16)); default: return 0; } -- GitLab From 2e4d60cbcfc2d16a2a2efaae3fe08f2e457d59a1 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:18 +0200 Subject: [PATCH 2370/9938] 6lowpan: change naming for lowpan private data This patch changes the naming for interface private data for lowpan intefaces. The current private data scheme is: ------------------------------------------------- | 6LoWPAN Generic | LinkLayer 6LoWPAN | ------------------------------------------------- the current naming schemes are: - 6LoWPAN Generic: - lowpan_priv - LinkLayer 6LoWPAN: - BTLE - lowpan_dev - 802.15.4: - lowpan_dev_info the new naming scheme with this patch will be: - 6LoWPAN Generic: - lowpan_dev - LinkLayer 6LoWPAN: - BTLE - lowpan_btle_dev - 802.15.4: - lowpan_802154_dev Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- include/net/6lowpan.h | 6 +-- net/6lowpan/core.c | 8 +-- net/6lowpan/debugfs.c | 22 ++++---- net/6lowpan/iphc.c | 38 +++++++------- net/6lowpan/nhc_udp.c | 2 +- net/bluetooth/6lowpan.c | 82 ++++++++++++++++-------------- net/ieee802154/6lowpan/6lowpan_i.h | 6 +-- net/ieee802154/6lowpan/core.c | 6 +-- net/ieee802154/6lowpan/tx.c | 14 ++--- 9 files changed, 94 insertions(+), 90 deletions(-) diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index da3a77d25fcb..f204664f37ab 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -93,7 +93,7 @@ static inline bool lowpan_is_iphc(u8 dispatch) } #define LOWPAN_PRIV_SIZE(llpriv_size) \ - (sizeof(struct lowpan_priv) + llpriv_size) + (sizeof(struct lowpan_dev) + llpriv_size) enum lowpan_lltypes { LOWPAN_LLTYPE_BTLE, @@ -129,7 +129,7 @@ lowpan_iphc_ctx_is_compression(const struct lowpan_iphc_ctx *ctx) return test_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags); } -struct lowpan_priv { +struct lowpan_dev { enum lowpan_lltypes lltype; struct dentry *iface_debugfs; struct lowpan_iphc_ctx_table ctx; @@ -139,7 +139,7 @@ struct lowpan_priv { }; static inline -struct lowpan_priv *lowpan_priv(const struct net_device *dev) +struct lowpan_dev *lowpan_dev(const struct net_device *dev) { return netdev_priv(dev); } diff --git a/net/6lowpan/core.c b/net/6lowpan/core.c index 34e44c0c0836..7a240b3eaed1 100644 --- a/net/6lowpan/core.c +++ b/net/6lowpan/core.c @@ -27,11 +27,11 @@ int lowpan_register_netdevice(struct net_device *dev, dev->mtu = IPV6_MIN_MTU; dev->priv_flags |= IFF_NO_QUEUE; - lowpan_priv(dev)->lltype = lltype; + lowpan_dev(dev)->lltype = lltype; - spin_lock_init(&lowpan_priv(dev)->ctx.lock); + spin_lock_init(&lowpan_dev(dev)->ctx.lock); for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) - lowpan_priv(dev)->ctx.table[i].id = i; + lowpan_dev(dev)->ctx.table[i].id = i; ret = register_netdevice(dev); if (ret < 0) @@ -85,7 +85,7 @@ static int lowpan_event(struct notifier_block *unused, case NETDEV_DOWN: for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, - &lowpan_priv(dev)->ctx.table[i].flags); + &lowpan_dev(dev)->ctx.table[i].flags); break; default: return NOTIFY_DONE; diff --git a/net/6lowpan/debugfs.c b/net/6lowpan/debugfs.c index 0793a8157472..acbaa3db493b 100644 --- a/net/6lowpan/debugfs.c +++ b/net/6lowpan/debugfs.c @@ -172,7 +172,7 @@ static const struct file_operations lowpan_ctx_pfx_fops = { static int lowpan_dev_debugfs_ctx_init(struct net_device *dev, struct dentry *ctx, u8 id) { - struct lowpan_priv *lpriv = lowpan_priv(dev); + struct lowpan_dev *ldev = lowpan_dev(dev); struct dentry *dentry, *root; char buf[32]; @@ -185,25 +185,25 @@ static int lowpan_dev_debugfs_ctx_init(struct net_device *dev, return -EINVAL; dentry = debugfs_create_file("active", 0644, root, - &lpriv->ctx.table[id], + &ldev->ctx.table[id], &lowpan_ctx_flag_active_fops); if (!dentry) return -EINVAL; dentry = debugfs_create_file("compression", 0644, root, - &lpriv->ctx.table[id], + &ldev->ctx.table[id], &lowpan_ctx_flag_c_fops); if (!dentry) return -EINVAL; dentry = debugfs_create_file("prefix", 0644, root, - &lpriv->ctx.table[id], + &ldev->ctx.table[id], &lowpan_ctx_pfx_fops); if (!dentry) return -EINVAL; dentry = debugfs_create_file("prefix_len", 0644, root, - &lpriv->ctx.table[id], + &ldev->ctx.table[id], &lowpan_ctx_plen_fops); if (!dentry) return -EINVAL; @@ -247,21 +247,21 @@ static const struct file_operations lowpan_context_fops = { int lowpan_dev_debugfs_init(struct net_device *dev) { - struct lowpan_priv *lpriv = lowpan_priv(dev); + struct lowpan_dev *ldev = lowpan_dev(dev); struct dentry *contexts, *dentry; int ret, i; /* creating the root */ - lpriv->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs); - if (!lpriv->iface_debugfs) + ldev->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs); + if (!ldev->iface_debugfs) goto fail; - contexts = debugfs_create_dir("contexts", lpriv->iface_debugfs); + contexts = debugfs_create_dir("contexts", ldev->iface_debugfs); if (!contexts) goto remove_root; dentry = debugfs_create_file("show", 0644, contexts, - &lowpan_priv(dev)->ctx, + &lowpan_dev(dev)->ctx, &lowpan_context_fops); if (!dentry) goto remove_root; @@ -282,7 +282,7 @@ int lowpan_dev_debugfs_init(struct net_device *dev) void lowpan_dev_debugfs_exit(struct net_device *dev) { - debugfs_remove_recursive(lowpan_priv(dev)->iface_debugfs); + debugfs_remove_recursive(lowpan_dev(dev)->iface_debugfs); } int __init lowpan_debugfs_init(void) diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 68c80f3c9add..5fb764e45d80 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -207,7 +207,7 @@ static inline void iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr, static struct lowpan_iphc_ctx * lowpan_iphc_ctx_get_by_id(const struct net_device *dev, u8 id) { - struct lowpan_iphc_ctx *ret = &lowpan_priv(dev)->ctx.table[id]; + struct lowpan_iphc_ctx *ret = &lowpan_dev(dev)->ctx.table[id]; if (!lowpan_iphc_ctx_is_active(ret)) return NULL; @@ -219,7 +219,7 @@ static struct lowpan_iphc_ctx * lowpan_iphc_ctx_get_by_addr(const struct net_device *dev, const struct in6_addr *addr) { - struct lowpan_iphc_ctx *table = lowpan_priv(dev)->ctx.table; + struct lowpan_iphc_ctx *table = lowpan_dev(dev)->ctx.table; struct lowpan_iphc_ctx *ret = NULL; struct in6_addr addr_pfx; u8 addr_plen; @@ -263,7 +263,7 @@ static struct lowpan_iphc_ctx * lowpan_iphc_ctx_get_by_mcast_addr(const struct net_device *dev, const struct in6_addr *addr) { - struct lowpan_iphc_ctx *table = lowpan_priv(dev)->ctx.table; + struct lowpan_iphc_ctx *table = lowpan_dev(dev)->ctx.table; struct lowpan_iphc_ctx *ret = NULL; struct in6_addr addr_mcast, network_pfx = {}; int i; @@ -332,7 +332,7 @@ static int uncompress_addr(struct sk_buff *skb, const struct net_device *dev, case LOWPAN_IPHC_SAM_11: case LOWPAN_IPHC_DAM_11: fail = false; - switch (lowpan_priv(dev)->lltype) { + switch (lowpan_dev(dev)->lltype) { case LOWPAN_LLTYPE_IEEE802154: iphc_uncompress_802154_lladdr(ipaddr, lladdr); break; @@ -393,7 +393,7 @@ static int uncompress_ctx_addr(struct sk_buff *skb, case LOWPAN_IPHC_SAM_11: case LOWPAN_IPHC_DAM_11: fail = false; - switch (lowpan_priv(dev)->lltype) { + switch (lowpan_dev(dev)->lltype) { case LOWPAN_LLTYPE_IEEE802154: iphc_uncompress_802154_lladdr(ipaddr, lladdr); break; @@ -657,17 +657,17 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, } if (iphc1 & LOWPAN_IPHC_SAC) { - spin_lock_bh(&lowpan_priv(dev)->ctx.lock); + spin_lock_bh(&lowpan_dev(dev)->ctx.lock); ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_SCI(cid)); if (!ci) { - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); return -EINVAL; } pr_debug("SAC bit is set. Handle context based source address.\n"); err = uncompress_ctx_addr(skb, dev, ci, &hdr.saddr, iphc1 & LOWPAN_IPHC_SAM_MASK, saddr); - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); } else { /* Source address uncompression */ pr_debug("source address stateless compression\n"); @@ -681,10 +681,10 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, switch (iphc1 & (LOWPAN_IPHC_M | LOWPAN_IPHC_DAC)) { case LOWPAN_IPHC_M | LOWPAN_IPHC_DAC: - spin_lock_bh(&lowpan_priv(dev)->ctx.lock); + spin_lock_bh(&lowpan_dev(dev)->ctx.lock); ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_DCI(cid)); if (!ci) { - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); return -EINVAL; } @@ -693,7 +693,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, err = lowpan_uncompress_multicast_ctx_daddr(skb, ci, &hdr.daddr, iphc1 & LOWPAN_IPHC_DAM_MASK); - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); break; case LOWPAN_IPHC_M: /* multicast */ @@ -701,10 +701,10 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, iphc1 & LOWPAN_IPHC_DAM_MASK); break; case LOWPAN_IPHC_DAC: - spin_lock_bh(&lowpan_priv(dev)->ctx.lock); + spin_lock_bh(&lowpan_dev(dev)->ctx.lock); ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_DCI(cid)); if (!ci) { - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); return -EINVAL; } @@ -712,7 +712,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, pr_debug("DAC bit is set. Handle context based destination address.\n"); err = uncompress_ctx_addr(skb, dev, ci, &hdr.daddr, iphc1 & LOWPAN_IPHC_DAM_MASK, daddr); - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); break; default: err = uncompress_addr(skb, dev, &hdr.daddr, @@ -736,7 +736,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, return err; } - switch (lowpan_priv(dev)->lltype) { + switch (lowpan_dev(dev)->lltype) { case LOWPAN_LLTYPE_IEEE802154: if (lowpan_802154_cb(skb)->d_size) hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size - @@ -1033,7 +1033,7 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev, skb->data, skb->len); ipv6_daddr_type = ipv6_addr_type(&hdr->daddr); - spin_lock_bh(&lowpan_priv(dev)->ctx.lock); + spin_lock_bh(&lowpan_dev(dev)->ctx.lock); if (ipv6_daddr_type & IPV6_ADDR_MULTICAST) dci = lowpan_iphc_ctx_get_by_mcast_addr(dev, &hdr->daddr); else @@ -1042,15 +1042,15 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev, memcpy(&dci_entry, dci, sizeof(*dci)); cid |= dci->id; } - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); - spin_lock_bh(&lowpan_priv(dev)->ctx.lock); + spin_lock_bh(&lowpan_dev(dev)->ctx.lock); sci = lowpan_iphc_ctx_get_by_addr(dev, &hdr->saddr); if (sci) { memcpy(&sci_entry, sci, sizeof(*sci)); cid |= (sci->id << 4); } - spin_unlock_bh(&lowpan_priv(dev)->ctx.lock); + spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); /* if cid is zero it will be compressed */ if (cid) { diff --git a/net/6lowpan/nhc_udp.c b/net/6lowpan/nhc_udp.c index 69537a2eaab1..225d91906dfa 100644 --- a/net/6lowpan/nhc_udp.c +++ b/net/6lowpan/nhc_udp.c @@ -91,7 +91,7 @@ static int udp_uncompress(struct sk_buff *skb, size_t needed) * here, we obtain the hint from the remaining size of the * frame */ - switch (lowpan_priv(skb->dev)->lltype) { + switch (lowpan_dev(skb->dev)->lltype) { case LOWPAN_LLTYPE_IEEE802154: if (lowpan_802154_cb(skb)->d_size) uh.len = htons(lowpan_802154_cb(skb)->d_size - diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 8a4cc2f7f0db..38e82ddd7ccd 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -68,7 +68,7 @@ struct lowpan_peer { struct in6_addr peer_addr; }; -struct lowpan_dev { +struct lowpan_btle_dev { struct list_head list; struct hci_dev *hdev; @@ -80,18 +80,21 @@ struct lowpan_dev { struct delayed_work notify_peers; }; -static inline struct lowpan_dev *lowpan_dev(const struct net_device *netdev) +static inline struct lowpan_btle_dev * +lowpan_btle_dev(const struct net_device *netdev) { - return (struct lowpan_dev *)lowpan_priv(netdev)->priv; + return (struct lowpan_btle_dev *)lowpan_dev(netdev)->priv; } -static inline void peer_add(struct lowpan_dev *dev, struct lowpan_peer *peer) +static inline void peer_add(struct lowpan_btle_dev *dev, + struct lowpan_peer *peer) { list_add_rcu(&peer->list, &dev->peers); atomic_inc(&dev->peer_count); } -static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer) +static inline bool peer_del(struct lowpan_btle_dev *dev, + struct lowpan_peer *peer) { list_del_rcu(&peer->list); kfree_rcu(peer, rcu); @@ -106,7 +109,7 @@ static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer) return false; } -static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev, +static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_btle_dev *dev, bdaddr_t *ba, __u8 type) { struct lowpan_peer *peer; @@ -134,8 +137,8 @@ static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev, return NULL; } -static inline struct lowpan_peer *__peer_lookup_chan(struct lowpan_dev *dev, - struct l2cap_chan *chan) +static inline struct lowpan_peer * +__peer_lookup_chan(struct lowpan_btle_dev *dev, struct l2cap_chan *chan) { struct lowpan_peer *peer; @@ -147,8 +150,8 @@ static inline struct lowpan_peer *__peer_lookup_chan(struct lowpan_dev *dev, return NULL; } -static inline struct lowpan_peer *__peer_lookup_conn(struct lowpan_dev *dev, - struct l2cap_conn *conn) +static inline struct lowpan_peer * +__peer_lookup_conn(struct lowpan_btle_dev *dev, struct l2cap_conn *conn) { struct lowpan_peer *peer; @@ -160,7 +163,7 @@ static inline struct lowpan_peer *__peer_lookup_conn(struct lowpan_dev *dev, return NULL; } -static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_dev *dev, +static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev, struct in6_addr *daddr, struct sk_buff *skb) { @@ -220,7 +223,7 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_dev *dev, static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn) { - struct lowpan_dev *entry; + struct lowpan_btle_dev *entry; struct lowpan_peer *peer = NULL; rcu_read_lock(); @@ -236,10 +239,10 @@ static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn) return peer; } -static struct lowpan_dev *lookup_dev(struct l2cap_conn *conn) +static struct lowpan_btle_dev *lookup_dev(struct l2cap_conn *conn) { - struct lowpan_dev *entry; - struct lowpan_dev *dev = NULL; + struct lowpan_btle_dev *entry; + struct lowpan_btle_dev *dev = NULL; rcu_read_lock(); @@ -270,10 +273,10 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev, struct l2cap_chan *chan) { const u8 *saddr, *daddr; - struct lowpan_dev *dev; + struct lowpan_btle_dev *dev; struct lowpan_peer *peer; - dev = lowpan_dev(netdev); + dev = lowpan_btle_dev(netdev); rcu_read_lock(); peer = __peer_lookup_chan(dev, chan); @@ -375,7 +378,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, /* Packet from BT LE device */ static int chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) { - struct lowpan_dev *dev; + struct lowpan_btle_dev *dev; struct lowpan_peer *peer; int err; @@ -431,13 +434,13 @@ static int setup_header(struct sk_buff *skb, struct net_device *netdev, bdaddr_t *peer_addr, u8 *peer_addr_type) { struct in6_addr ipv6_daddr; - struct lowpan_dev *dev; + struct lowpan_btle_dev *dev; struct lowpan_peer *peer; bdaddr_t addr, *any = BDADDR_ANY; u8 *daddr = any->b; int err, status = 0; - dev = lowpan_dev(netdev); + dev = lowpan_btle_dev(netdev); memcpy(&ipv6_daddr, &lowpan_cb(skb)->addr, sizeof(ipv6_daddr)); @@ -543,19 +546,19 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) { struct sk_buff *local_skb; - struct lowpan_dev *entry; + struct lowpan_btle_dev *entry; int err = 0; rcu_read_lock(); list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { struct lowpan_peer *pentry; - struct lowpan_dev *dev; + struct lowpan_btle_dev *dev; if (entry->netdev != netdev) continue; - dev = lowpan_dev(entry->netdev); + dev = lowpan_btle_dev(entry->netdev); list_for_each_entry_rcu(pentry, &dev->peers, list) { int ret; @@ -723,8 +726,8 @@ static void ifdown(struct net_device *netdev) static void do_notify_peers(struct work_struct *work) { - struct lowpan_dev *dev = container_of(work, struct lowpan_dev, - notify_peers.work); + struct lowpan_btle_dev *dev = container_of(work, struct lowpan_btle_dev, + notify_peers.work); netdev_notify_peers(dev->netdev); /* send neighbour adv at startup */ } @@ -766,7 +769,7 @@ static void set_ip_addr_bits(u8 addr_type, u8 *addr) } static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan, - struct lowpan_dev *dev) + struct lowpan_btle_dev *dev) { struct lowpan_peer *peer; @@ -803,12 +806,12 @@ static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan, return peer->chan; } -static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) +static int setup_netdev(struct l2cap_chan *chan, struct lowpan_btle_dev **dev) { struct net_device *netdev; int err = 0; - netdev = alloc_netdev(LOWPAN_PRIV_SIZE(sizeof(struct lowpan_dev)), + netdev = alloc_netdev(LOWPAN_PRIV_SIZE(sizeof(struct lowpan_btle_dev)), IFACE_NAME_TEMPLATE, NET_NAME_UNKNOWN, netdev_setup); if (!netdev) @@ -820,7 +823,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) SET_NETDEV_DEV(netdev, &chan->conn->hcon->hdev->dev); SET_NETDEV_DEVTYPE(netdev, &bt_type); - *dev = lowpan_dev(netdev); + *dev = lowpan_btle_dev(netdev); (*dev)->netdev = netdev; (*dev)->hdev = chan->conn->hcon->hdev; INIT_LIST_HEAD(&(*dev)->peers); @@ -853,7 +856,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) static inline void chan_ready_cb(struct l2cap_chan *chan) { - struct lowpan_dev *dev; + struct lowpan_btle_dev *dev; dev = lookup_dev(chan->conn); @@ -890,8 +893,9 @@ static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan) static void delete_netdev(struct work_struct *work) { - struct lowpan_dev *entry = container_of(work, struct lowpan_dev, - delete_netdev); + struct lowpan_btle_dev *entry = container_of(work, + struct lowpan_btle_dev, + delete_netdev); lowpan_unregister_netdev(entry->netdev); @@ -900,8 +904,8 @@ static void delete_netdev(struct work_struct *work) static void chan_close_cb(struct l2cap_chan *chan) { - struct lowpan_dev *entry; - struct lowpan_dev *dev = NULL; + struct lowpan_btle_dev *entry; + struct lowpan_btle_dev *dev = NULL; struct lowpan_peer *peer; int err = -ENOENT; bool last = false, remove = true; @@ -921,7 +925,7 @@ static void chan_close_cb(struct l2cap_chan *chan) spin_lock(&devices_lock); list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { - dev = lowpan_dev(entry->netdev); + dev = lowpan_btle_dev(entry->netdev); peer = __peer_lookup_chan(dev, chan); if (peer) { last = peer_del(dev, peer); @@ -1131,7 +1135,7 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, static void disconnect_all_peers(void) { - struct lowpan_dev *entry; + struct lowpan_btle_dev *entry; struct lowpan_peer *peer, *tmp_peer, *new_peer; struct list_head peers; @@ -1291,7 +1295,7 @@ static ssize_t lowpan_control_write(struct file *fp, static int lowpan_control_show(struct seq_file *f, void *ptr) { - struct lowpan_dev *entry; + struct lowpan_btle_dev *entry; struct lowpan_peer *peer; spin_lock(&devices_lock); @@ -1322,7 +1326,7 @@ static const struct file_operations lowpan_control_fops = { static void disconnect_devices(void) { - struct lowpan_dev *entry, *tmp, *new_dev; + struct lowpan_btle_dev *entry, *tmp, *new_dev; struct list_head devices; INIT_LIST_HEAD(&devices); @@ -1360,7 +1364,7 @@ static int device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *netdev = netdev_notifier_info_to_dev(ptr); - struct lowpan_dev *entry; + struct lowpan_btle_dev *entry; if (netdev->type != ARPHRD_6LOWPAN) return NOTIFY_DONE; diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h index b4092a9ff24a..b02b74de8ffa 100644 --- a/net/ieee802154/6lowpan/6lowpan_i.h +++ b/net/ieee802154/6lowpan/6lowpan_i.h @@ -48,15 +48,15 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a) } /* private device info */ -struct lowpan_dev_info { +struct lowpan_802154_dev { struct net_device *wdev; /* wpan device ptr */ u16 fragment_tag; }; static inline struct -lowpan_dev_info *lowpan_dev_info(const struct net_device *dev) +lowpan_802154_dev *lowpan_802154_dev(const struct net_device *dev) { - return (struct lowpan_dev_info *)lowpan_priv(dev)->priv; + return (struct lowpan_802154_dev *)lowpan_dev(dev)->priv; } int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type); diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 0023c9048812..dd085db8580e 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -148,7 +148,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev, return -EBUSY; } - lowpan_dev_info(ldev)->wdev = wdev; + lowpan_802154_dev(ldev)->wdev = wdev; /* Set the lowpan hardware address to the wpan hardware address. */ memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN); /* We need headroom for possible wpan_dev_hard_header call and tailroom @@ -173,7 +173,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev, static void lowpan_dellink(struct net_device *ldev, struct list_head *head) { - struct net_device *wdev = lowpan_dev_info(ldev)->wdev; + struct net_device *wdev = lowpan_802154_dev(ldev)->wdev; ASSERT_RTNL(); @@ -184,7 +184,7 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head) static struct rtnl_link_ops lowpan_link_ops __read_mostly = { .kind = "lowpan", - .priv_size = LOWPAN_PRIV_SIZE(sizeof(struct lowpan_dev_info)), + .priv_size = LOWPAN_PRIV_SIZE(sizeof(struct lowpan_802154_dev)), .setup = lowpan_setup, .newlink = lowpan_newlink, .dellink = lowpan_dellink, diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c index d4353faced35..e459afd16bb3 100644 --- a/net/ieee802154/6lowpan/tx.c +++ b/net/ieee802154/6lowpan/tx.c @@ -84,7 +84,7 @@ static struct sk_buff* lowpan_alloc_frag(struct sk_buff *skb, int size, const struct ieee802154_hdr *master_hdr, bool frag1) { - struct net_device *wdev = lowpan_dev_info(skb->dev)->wdev; + struct net_device *wdev = lowpan_802154_dev(skb->dev)->wdev; struct sk_buff *frag; int rc; @@ -148,8 +148,8 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev, int frag_cap, frag_len, payload_cap, rc; int skb_unprocessed, skb_offset; - frag_tag = htons(lowpan_dev_info(ldev)->fragment_tag); - lowpan_dev_info(ldev)->fragment_tag++; + frag_tag = htons(lowpan_802154_dev(ldev)->fragment_tag); + lowpan_802154_dev(ldev)->fragment_tag++; frag_hdr[0] = LOWPAN_DISPATCH_FRAG1 | ((dgram_size >> 8) & 0x07); frag_hdr[1] = dgram_size & 0xff; @@ -208,7 +208,7 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev, static int lowpan_header(struct sk_buff *skb, struct net_device *ldev, u16 *dgram_size, u16 *dgram_offset) { - struct wpan_dev *wpan_dev = lowpan_dev_info(ldev)->wdev->ieee802154_ptr; + struct wpan_dev *wpan_dev = lowpan_802154_dev(ldev)->wdev->ieee802154_ptr; struct ieee802154_addr sa, da; struct ieee802154_mac_cb *cb = mac_cb_init(skb); struct lowpan_addr_info info; @@ -248,8 +248,8 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *ldev, cb->ackreq = wpan_dev->ackreq; } - return wpan_dev_hard_header(skb, lowpan_dev_info(ldev)->wdev, &da, &sa, - 0); + return wpan_dev_hard_header(skb, lowpan_802154_dev(ldev)->wdev, &da, + &sa, 0); } netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev) @@ -283,7 +283,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev) max_single = ieee802154_max_payload(&wpan_hdr); if (skb_tail_pointer(skb) - skb_network_header(skb) <= max_single) { - skb->dev = lowpan_dev_info(ldev)->wdev; + skb->dev = lowpan_802154_dev(ldev)->wdev; ldev->stats.tx_packets++; ldev->stats.tx_bytes += dgram_size; return dev_queue_xmit(skb); -- GitLab From 353c224e28eb73e65720e5b2be224052569c0764 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:19 +0200 Subject: [PATCH 2371/9938] 6lowpan: move lowpan_802154_dev to 6lowpan This patch moves the 802.15.4 link layer specific structures to generic 6lowpan. This is necessary for special 802.15.4 6lowpan handling in 6lowpan generic layer. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- include/net/6lowpan.h | 12 ++++++++++++ net/ieee802154/6lowpan/6lowpan_i.h | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index f204664f37ab..a0c01f55e0d3 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -144,6 +144,18 @@ struct lowpan_dev *lowpan_dev(const struct net_device *dev) return netdev_priv(dev); } +/* private device info */ +struct lowpan_802154_dev { + struct net_device *wdev; /* wpan device ptr */ + u16 fragment_tag; +}; + +static inline struct +lowpan_802154_dev *lowpan_802154_dev(const struct net_device *dev) +{ + return (struct lowpan_802154_dev *)lowpan_dev(dev)->priv; +} + struct lowpan_802154_cb { u16 d_tag; unsigned int d_size; diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h index b02b74de8ffa..5ac778962e4e 100644 --- a/net/ieee802154/6lowpan/6lowpan_i.h +++ b/net/ieee802154/6lowpan/6lowpan_i.h @@ -47,18 +47,6 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a) } } -/* private device info */ -struct lowpan_802154_dev { - struct net_device *wdev; /* wpan device ptr */ - u16 fragment_tag; -}; - -static inline struct -lowpan_802154_dev *lowpan_802154_dev(const struct net_device *dev) -{ - return (struct lowpan_802154_dev *)lowpan_dev(dev)->priv; -} - int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type); void lowpan_net_frag_exit(void); int lowpan_net_frag_init(void); -- GitLab From 7115a968b75e9f81f6f8f45b2f97b1b43e024703 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:20 +0200 Subject: [PATCH 2372/9938] 6lowpan: iphc: rename add lowpan prefix This patch adds a lowpan prefix to each functions which doesn't have such prefix currently. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- net/6lowpan/iphc.c | 56 +++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 5fb764e45d80..66b41395ab80 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -156,8 +156,8 @@ #define LOWPAN_IPHC_CID_DCI(cid) (cid & 0x0f) #define LOWPAN_IPHC_CID_SCI(cid) ((cid & 0xf0) >> 4) -static inline void iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr, - const void *lladdr) +static inline void lowpan_iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr, + const void *lladdr) { /* fe:80::XXXX:XXXX:XXXX:XXXX * \_________________/ @@ -172,8 +172,9 @@ static inline void iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr, ipaddr->s6_addr[8] ^= 0x02; } -static inline void iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr, - const void *lladdr) +static inline void +lowpan_iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr, + const void *lladdr) { const struct ieee802154_addr *addr = lladdr; u8 eui64[EUI64_ADDR_LEN] = { }; @@ -181,7 +182,7 @@ static inline void iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr, switch (addr->mode) { case IEEE802154_ADDR_LONG: ieee802154_le64_to_be64(eui64, &addr->extended_addr); - iphc_uncompress_eui64_lladdr(ipaddr, eui64); + lowpan_iphc_uncompress_eui64_lladdr(ipaddr, eui64); break; case IEEE802154_ADDR_SHORT: /* fe:80::ff:fe00:XXXX @@ -301,9 +302,10 @@ lowpan_iphc_ctx_get_by_mcast_addr(const struct net_device *dev, * * address_mode is the masked value for sam or dam value */ -static int uncompress_addr(struct sk_buff *skb, const struct net_device *dev, - struct in6_addr *ipaddr, u8 address_mode, - const void *lladdr) +static int lowpan_iphc_uncompress_addr(struct sk_buff *skb, + const struct net_device *dev, + struct in6_addr *ipaddr, + u8 address_mode, const void *lladdr) { bool fail; @@ -334,10 +336,10 @@ static int uncompress_addr(struct sk_buff *skb, const struct net_device *dev, fail = false; switch (lowpan_dev(dev)->lltype) { case LOWPAN_LLTYPE_IEEE802154: - iphc_uncompress_802154_lladdr(ipaddr, lladdr); + lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr); break; default: - iphc_uncompress_eui64_lladdr(ipaddr, lladdr); + lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr); break; } break; @@ -360,11 +362,11 @@ static int uncompress_addr(struct sk_buff *skb, const struct net_device *dev, /* Uncompress address function for source context * based address(non-multicast). */ -static int uncompress_ctx_addr(struct sk_buff *skb, - const struct net_device *dev, - const struct lowpan_iphc_ctx *ctx, - struct in6_addr *ipaddr, u8 address_mode, - const void *lladdr) +static int lowpan_iphc_uncompress_ctx_addr(struct sk_buff *skb, + const struct net_device *dev, + const struct lowpan_iphc_ctx *ctx, + struct in6_addr *ipaddr, + u8 address_mode, const void *lladdr) { bool fail; @@ -395,10 +397,10 @@ static int uncompress_ctx_addr(struct sk_buff *skb, fail = false; switch (lowpan_dev(dev)->lltype) { case LOWPAN_LLTYPE_IEEE802154: - iphc_uncompress_802154_lladdr(ipaddr, lladdr); + lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr); break; default: - iphc_uncompress_eui64_lladdr(ipaddr, lladdr); + lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr); break; } ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen); @@ -665,14 +667,16 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, } pr_debug("SAC bit is set. Handle context based source address.\n"); - err = uncompress_ctx_addr(skb, dev, ci, &hdr.saddr, - iphc1 & LOWPAN_IPHC_SAM_MASK, saddr); + err = lowpan_iphc_uncompress_ctx_addr(skb, dev, ci, &hdr.saddr, + iphc1 & LOWPAN_IPHC_SAM_MASK, + saddr); spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); } else { /* Source address uncompression */ pr_debug("source address stateless compression\n"); - err = uncompress_addr(skb, dev, &hdr.saddr, - iphc1 & LOWPAN_IPHC_SAM_MASK, saddr); + err = lowpan_iphc_uncompress_addr(skb, dev, &hdr.saddr, + iphc1 & LOWPAN_IPHC_SAM_MASK, + saddr); } /* Check on error of previous branch */ @@ -710,13 +714,15 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, /* Destination address context based uncompression */ pr_debug("DAC bit is set. Handle context based destination address.\n"); - err = uncompress_ctx_addr(skb, dev, ci, &hdr.daddr, - iphc1 & LOWPAN_IPHC_DAM_MASK, daddr); + err = lowpan_iphc_uncompress_ctx_addr(skb, dev, ci, &hdr.daddr, + iphc1 & LOWPAN_IPHC_DAM_MASK, + daddr); spin_unlock_bh(&lowpan_dev(dev)->ctx.lock); break; default: - err = uncompress_addr(skb, dev, &hdr.daddr, - iphc1 & LOWPAN_IPHC_DAM_MASK, daddr); + err = lowpan_iphc_uncompress_addr(skb, dev, &hdr.daddr, + iphc1 & LOWPAN_IPHC_DAM_MASK, + daddr); pr_debug("dest: stateless compression mode %d dest %pI6c\n", iphc1 & LOWPAN_IPHC_DAM_MASK, &hdr.daddr); break; -- GitLab From 2bc068c3d6e1212d09c11169c699560747ef8c2b Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:21 +0200 Subject: [PATCH 2373/9938] 6lowpan: iphc: remove unnecessary zero data This patch removes unnecessary zero data for a stack variable. Signed-off-by: Alexander Aring Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- net/6lowpan/iphc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 66b41395ab80..29992405c816 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -177,7 +177,7 @@ lowpan_iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr, const void *lladdr) { const struct ieee802154_addr *addr = lladdr; - u8 eui64[EUI64_ADDR_LEN] = { }; + u8 eui64[EUI64_ADDR_LEN]; switch (addr->mode) { case IEEE802154_ADDR_LONG: -- GitLab From a5862f2aba4ba53d461450685a67ae252935ab94 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:22 +0200 Subject: [PATCH 2374/9938] 6lowpan: move eui64 uncompress function This function will be use in later functionality in other branches than generic 6lowpan, so we move it to the global 6lowpan header. Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- include/net/6lowpan.h | 16 ++++++++++++++++ net/6lowpan/iphc.c | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index a0c01f55e0d3..04b877c5baff 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -169,6 +169,22 @@ struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb) return (struct lowpan_802154_cb *)skb->cb; } +static inline void lowpan_iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr, + const void *lladdr) +{ + /* fe:80::XXXX:XXXX:XXXX:XXXX + * \_________________/ + * hwaddr + */ + ipaddr->s6_addr[0] = 0xFE; + ipaddr->s6_addr[1] = 0x80; + memcpy(&ipaddr->s6_addr[8], lladdr, EUI64_ADDR_LEN); + /* second bit-flip (Universe/Local) + * is done according RFC2464 + */ + ipaddr->s6_addr[8] ^= 0x02; +} + #ifdef DEBUG /* print data in line */ static inline void raw_dump_inline(const char *caller, char *msg, diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 29992405c816..dff15911bd04 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -156,22 +156,6 @@ #define LOWPAN_IPHC_CID_DCI(cid) (cid & 0x0f) #define LOWPAN_IPHC_CID_SCI(cid) ((cid & 0xf0) >> 4) -static inline void lowpan_iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr, - const void *lladdr) -{ - /* fe:80::XXXX:XXXX:XXXX:XXXX - * \_________________/ - * hwaddr - */ - ipaddr->s6_addr[0] = 0xFE; - ipaddr->s6_addr[1] = 0x80; - memcpy(&ipaddr->s6_addr[8], lladdr, EUI64_ADDR_LEN); - /* second bit-flip (Universe/Local) - * is done according RFC2464 - */ - ipaddr->s6_addr[8] ^= 0x02; -} - static inline void lowpan_iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr, const void *lladdr) -- GitLab From 2732363181766533af65e9ced3dc04a30502c5d1 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:23 +0200 Subject: [PATCH 2375/9938] 6lowpan: add lowpan_is_ll function This patch adds the lowpan_is_ll function, which can be used to make a special 6lowpan linklayer handling for a specific 6lowpan linklayer type. Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- net/6lowpan/6lowpan_i.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/6lowpan/6lowpan_i.h b/net/6lowpan/6lowpan_i.h index d16bb4b14aa1..97ecc27aeca6 100644 --- a/net/6lowpan/6lowpan_i.h +++ b/net/6lowpan/6lowpan_i.h @@ -3,6 +3,15 @@ #include +#include + +/* caller need to be sure it's dev->type is ARPHRD_6LOWPAN */ +static inline bool lowpan_is_ll(const struct net_device *dev, + enum lowpan_lltypes lltype) +{ + return lowpan_dev(dev)->lltype == lltype; +} + #ifdef CONFIG_6LOWPAN_DEBUGFS int lowpan_dev_debugfs_init(struct net_device *dev); void lowpan_dev_debugfs_exit(struct net_device *dev); -- GitLab From edc73417d8f33a1dd329295275168923298d9a7b Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 11 Apr 2016 11:04:24 +0200 Subject: [PATCH 2376/9938] 6lowpan: move mac802154 header In case of link-layer specific handling for 802.15.4 we need to cast to 802.15.4 sepcific structures. Simple add this header when include the 6lowpan header. Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann --- include/net/6lowpan.h | 3 +++ net/6lowpan/iphc.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index 04b877c5baff..da84cf920b78 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -58,6 +58,9 @@ #include #include +/* special link-layer handling */ +#include + #define EUI64_ADDR_LEN 8 #define LOWPAN_NHC_MAX_ID_LEN 1 diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index dff15911bd04..8501dd532fe1 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -53,9 +53,6 @@ #include #include -/* special link-layer handling */ -#include - #include "6lowpan_i.h" #include "nhc.h" -- GitLab From f8e04d854506ddfeba9cb41b601972b28521f104 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:21 +0200 Subject: [PATCH 2377/9938] locking/rwsem: Get rid of __down_write_nested() This is no longer used anywhere and all callers (__down_write()) use 0 as a subclass. Ditch __down_write_nested() to make the code easier to follow. This shouldn't introduce any functional change. Signed-off-by: Michal Hocko Acked-by: Davidlohr Bueso Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-2-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/s390/include/asm/rwsem.h | 7 +------ arch/sh/include/asm/rwsem.h | 5 ----- arch/sparc/include/asm/rwsem.h | 7 +------ arch/x86/include/asm/rwsem.h | 7 +------ include/asm-generic/rwsem.h | 7 +------ include/linux/rwsem-spinlock.h | 1 - kernel/locking/rwsem-spinlock.c | 7 +------ 7 files changed, 5 insertions(+), 36 deletions(-) diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h index fead491dfc28..555d23b6b6d1 100644 --- a/arch/s390/include/asm/rwsem.h +++ b/arch/s390/include/asm/rwsem.h @@ -90,7 +90,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) /* * lock for writing */ -static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) +static inline void __down_write(struct rw_semaphore *sem) { signed long old, new, tmp; @@ -108,11 +108,6 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) rwsem_down_write_failed(sem); } -static inline void __down_write(struct rw_semaphore *sem) -{ - __down_write_nested(sem, 0); -} - /* * trylock for writing -- returns 1 if successful, 0 if contention */ diff --git a/arch/sh/include/asm/rwsem.h b/arch/sh/include/asm/rwsem.h index edab57265293..a5104bebd1eb 100644 --- a/arch/sh/include/asm/rwsem.h +++ b/arch/sh/include/asm/rwsem.h @@ -114,11 +114,6 @@ static inline void __downgrade_write(struct rw_semaphore *sem) rwsem_downgrade_wake(sem); } -static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) -{ - __down_write(sem); -} - /* * implement exchange and add functionality */ diff --git a/arch/sparc/include/asm/rwsem.h b/arch/sparc/include/asm/rwsem.h index 069bf4d663a1..e5a0d575bc7f 100644 --- a/arch/sparc/include/asm/rwsem.h +++ b/arch/sparc/include/asm/rwsem.h @@ -45,7 +45,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) /* * lock for writing */ -static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) +static inline void __down_write(struct rw_semaphore *sem) { long tmp; @@ -55,11 +55,6 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) rwsem_down_write_failed(sem); } -static inline void __down_write(struct rw_semaphore *sem) -{ - __down_write_nested(sem, 0); -} - static inline int __down_write_trylock(struct rw_semaphore *sem) { long tmp; diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h index ceec86eb68e9..4a8292a0d6e1 100644 --- a/arch/x86/include/asm/rwsem.h +++ b/arch/x86/include/asm/rwsem.h @@ -99,7 +99,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) /* * lock for writing */ -static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) +static inline void __down_write(struct rw_semaphore *sem) { long tmp; asm volatile("# beginning down_write\n\t" @@ -116,11 +116,6 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) : "memory", "cc"); } -static inline void __down_write(struct rw_semaphore *sem) -{ - __down_write_nested(sem, 0); -} - /* * trylock for writing -- returns 1 if successful, 0 if contention */ diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h index d6d5dc98d7da..b8d8a6cf4ca8 100644 --- a/include/asm-generic/rwsem.h +++ b/include/asm-generic/rwsem.h @@ -53,7 +53,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) /* * lock for writing */ -static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) +static inline void __down_write(struct rw_semaphore *sem) { long tmp; @@ -63,11 +63,6 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) rwsem_down_write_failed(sem); } -static inline void __down_write(struct rw_semaphore *sem) -{ - __down_write_nested(sem, 0); -} - static inline int __down_write_trylock(struct rw_semaphore *sem) { long tmp; diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h index 561e8615528d..a733a5467e6c 100644 --- a/include/linux/rwsem-spinlock.h +++ b/include/linux/rwsem-spinlock.h @@ -34,7 +34,6 @@ struct rw_semaphore { extern void __down_read(struct rw_semaphore *sem); extern int __down_read_trylock(struct rw_semaphore *sem); extern void __down_write(struct rw_semaphore *sem); -extern void __down_write_nested(struct rw_semaphore *sem, int subclass); extern int __down_write_trylock(struct rw_semaphore *sem); extern void __up_read(struct rw_semaphore *sem); extern void __up_write(struct rw_semaphore *sem); diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c index 3a5048572065..bab26104a5d0 100644 --- a/kernel/locking/rwsem-spinlock.c +++ b/kernel/locking/rwsem-spinlock.c @@ -191,7 +191,7 @@ int __down_read_trylock(struct rw_semaphore *sem) /* * get a write lock on the semaphore */ -void __sched __down_write_nested(struct rw_semaphore *sem, int subclass) +void __sched __down_write(struct rw_semaphore *sem) { struct rwsem_waiter waiter; struct task_struct *tsk; @@ -227,11 +227,6 @@ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass) raw_spin_unlock_irqrestore(&sem->wait_lock, flags); } -void __sched __down_write(struct rw_semaphore *sem) -{ - __down_write_nested(sem, 0); -} - /* * trylock for writing -- returns 1 if successful, 0 if contention */ -- GitLab From 2e927c6422fea5ce36b24b00c2c84f2e9ead31b6 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:22 +0200 Subject: [PATCH 2378/9938] locking/rwsem: Drop explicit memory barriers sh and xtensa seem to be the only architectures which use explicit memory barriers for rw_semaphore operations even though they are not really needed because there is the full memory barrier is always implied by atomic_{inc,dec,add,sub}_return() resp. cmpxchg(). Remove them. Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-3-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/sh/include/asm/rwsem.h | 14 ++------------ arch/xtensa/include/asm/rwsem.h | 14 ++------------ 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/arch/sh/include/asm/rwsem.h b/arch/sh/include/asm/rwsem.h index a5104bebd1eb..f6c951c7a875 100644 --- a/arch/sh/include/asm/rwsem.h +++ b/arch/sh/include/asm/rwsem.h @@ -24,9 +24,7 @@ */ static inline void __down_read(struct rw_semaphore *sem) { - if (atomic_inc_return((atomic_t *)(&sem->count)) > 0) - smp_wmb(); - else + if (atomic_inc_return((atomic_t *)(&sem->count)) <= 0) rwsem_down_read_failed(sem); } @@ -37,7 +35,6 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) while ((tmp = sem->count) >= 0) { if (tmp == cmpxchg(&sem->count, tmp, tmp + RWSEM_ACTIVE_READ_BIAS)) { - smp_wmb(); return 1; } } @@ -53,9 +50,7 @@ static inline void __down_write(struct rw_semaphore *sem) tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, (atomic_t *)(&sem->count)); - if (tmp == RWSEM_ACTIVE_WRITE_BIAS) - smp_wmb(); - else + if (tmp != RWSEM_ACTIVE_WRITE_BIAS) rwsem_down_write_failed(sem); } @@ -65,7 +60,6 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS); - smp_wmb(); return tmp == RWSEM_UNLOCKED_VALUE; } @@ -76,7 +70,6 @@ static inline void __up_read(struct rw_semaphore *sem) { int tmp; - smp_wmb(); tmp = atomic_dec_return((atomic_t *)(&sem->count)); if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0) rwsem_wake(sem); @@ -87,7 +80,6 @@ static inline void __up_read(struct rw_semaphore *sem) */ static inline void __up_write(struct rw_semaphore *sem) { - smp_wmb(); if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, (atomic_t *)(&sem->count)) < 0) rwsem_wake(sem); @@ -108,7 +100,6 @@ static inline void __downgrade_write(struct rw_semaphore *sem) { int tmp; - smp_wmb(); tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); if (tmp < 0) rwsem_downgrade_wake(sem); @@ -119,7 +110,6 @@ static inline void __downgrade_write(struct rw_semaphore *sem) */ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) { - smp_mb(); return atomic_add_return(delta, (atomic_t *)(&sem->count)); } diff --git a/arch/xtensa/include/asm/rwsem.h b/arch/xtensa/include/asm/rwsem.h index 249619e7e7f2..593483f6e1ff 100644 --- a/arch/xtensa/include/asm/rwsem.h +++ b/arch/xtensa/include/asm/rwsem.h @@ -29,9 +29,7 @@ */ static inline void __down_read(struct rw_semaphore *sem) { - if (atomic_add_return(1,(atomic_t *)(&sem->count)) > 0) - smp_wmb(); - else + if (atomic_add_return(1,(atomic_t *)(&sem->count)) <= 0) rwsem_down_read_failed(sem); } @@ -42,7 +40,6 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) while ((tmp = sem->count) >= 0) { if (tmp == cmpxchg(&sem->count, tmp, tmp + RWSEM_ACTIVE_READ_BIAS)) { - smp_wmb(); return 1; } } @@ -58,9 +55,7 @@ static inline void __down_write(struct rw_semaphore *sem) tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, (atomic_t *)(&sem->count)); - if (tmp == RWSEM_ACTIVE_WRITE_BIAS) - smp_wmb(); - else + if (tmp != RWSEM_ACTIVE_WRITE_BIAS) rwsem_down_write_failed(sem); } @@ -70,7 +65,6 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS); - smp_wmb(); return tmp == RWSEM_UNLOCKED_VALUE; } @@ -81,7 +75,6 @@ static inline void __up_read(struct rw_semaphore *sem) { int tmp; - smp_wmb(); tmp = atomic_sub_return(1,(atomic_t *)(&sem->count)); if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0) rwsem_wake(sem); @@ -92,7 +85,6 @@ static inline void __up_read(struct rw_semaphore *sem) */ static inline void __up_write(struct rw_semaphore *sem) { - smp_wmb(); if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, (atomic_t *)(&sem->count)) < 0) rwsem_wake(sem); @@ -113,7 +105,6 @@ static inline void __downgrade_write(struct rw_semaphore *sem) { int tmp; - smp_wmb(); tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); if (tmp < 0) rwsem_downgrade_wake(sem); @@ -124,7 +115,6 @@ static inline void __downgrade_write(struct rw_semaphore *sem) */ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) { - smp_mb(); return atomic_add_return(delta, (atomic_t *)(&sem->count)); } -- GitLab From 3aa2591dc2ea292d068dc3a263f1976806c2c281 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:23 +0200 Subject: [PATCH 2379/9938] locking/rwsem, xtensa: Drop superfluous arch specific implementation Since "locking, rwsem: drop explicit memory barriers" the arch specific code is basically same as the the generic one so we can drop the superfluous code. Suggested-by: Davidlohr Bueso Signed-off-by: Michal Hocko Acked-by: Max Filippov Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-4-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/xtensa/include/asm/Kbuild | 1 + arch/xtensa/include/asm/rwsem.h | 121 -------------------------------- 2 files changed, 1 insertion(+), 121 deletions(-) delete mode 100644 arch/xtensa/include/asm/rwsem.h diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index b56855a1382a..28cf4c5d65ef 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -22,6 +22,7 @@ generic-y += mm-arch-hooks.h generic-y += percpu.h generic-y += preempt.h generic-y += resource.h +generic-y += rwsem.h generic-y += sections.h generic-y += siginfo.h generic-y += statfs.h diff --git a/arch/xtensa/include/asm/rwsem.h b/arch/xtensa/include/asm/rwsem.h deleted file mode 100644 index 593483f6e1ff..000000000000 --- a/arch/xtensa/include/asm/rwsem.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * include/asm-xtensa/rwsem.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Largely copied from include/asm-ppc/rwsem.h - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_RWSEM_H -#define _XTENSA_RWSEM_H - -#ifndef _LINUX_RWSEM_H -#error "Please don't include directly, use instead." -#endif - -#define RWSEM_UNLOCKED_VALUE 0x00000000 -#define RWSEM_ACTIVE_BIAS 0x00000001 -#define RWSEM_ACTIVE_MASK 0x0000ffff -#define RWSEM_WAITING_BIAS (-0x00010000) -#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) - -/* - * lock for reading - */ -static inline void __down_read(struct rw_semaphore *sem) -{ - if (atomic_add_return(1,(atomic_t *)(&sem->count)) <= 0) - rwsem_down_read_failed(sem); -} - -static inline int __down_read_trylock(struct rw_semaphore *sem) -{ - int tmp; - - while ((tmp = sem->count) >= 0) { - if (tmp == cmpxchg(&sem->count, tmp, - tmp + RWSEM_ACTIVE_READ_BIAS)) { - return 1; - } - } - return 0; -} - -/* - * lock for writing - */ -static inline void __down_write(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)); - if (tmp != RWSEM_ACTIVE_WRITE_BIAS) - rwsem_down_write_failed(sem); -} - -static inline int __down_write_trylock(struct rw_semaphore *sem) -{ - int tmp; - - tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, - RWSEM_ACTIVE_WRITE_BIAS); - return tmp == RWSEM_UNLOCKED_VALUE; -} - -/* - * unlock after reading - */ -static inline void __up_read(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_sub_return(1,(atomic_t *)(&sem->count)); - if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0) - rwsem_wake(sem); -} - -/* - * unlock after writing - */ -static inline void __up_write(struct rw_semaphore *sem) -{ - if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)) < 0) - rwsem_wake(sem); -} - -/* - * implement atomic add functionality - */ -static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) -{ - atomic_add(delta, (atomic_t *)(&sem->count)); -} - -/* - * downgrade write lock to read lock - */ -static inline void __downgrade_write(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); - if (tmp < 0) - rwsem_downgrade_wake(sem); -} - -/* - * implement exchange and add functionality - */ -static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) -{ - return atomic_add_return(delta, (atomic_t *)(&sem->count)); -} - -#endif /* _XTENSA_RWSEM_H */ -- GitLab From e4a2b01ed3d1591437f93a42f6c4c039b60e0c0a Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:24 +0200 Subject: [PATCH 2380/9938] locking/rwsem, sh: Drop superfluous arch specific implementation Since "locking, rwsem: drop explicit memory barriers" the arch specific code is basically same as the the generic one so we can drop the superfluous code. Suggested-by: Davidlohr Bueso Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-5-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/sh/include/asm/Kbuild | 1 + arch/sh/include/asm/rwsem.h | 117 ------------------------------------ 2 files changed, 1 insertion(+), 117 deletions(-) delete mode 100644 arch/sh/include/asm/rwsem.h diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index a319745a7b63..751c3373a92c 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -26,6 +26,7 @@ generic-y += percpu.h generic-y += poll.h generic-y += preempt.h generic-y += resource.h +generic-y += rwsem.h generic-y += sembuf.h generic-y += serial.h generic-y += shmbuf.h diff --git a/arch/sh/include/asm/rwsem.h b/arch/sh/include/asm/rwsem.h deleted file mode 100644 index f6c951c7a875..000000000000 --- a/arch/sh/include/asm/rwsem.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * include/asm-sh/rwsem.h: R/W semaphores for SH using the stuff - * in lib/rwsem.c. - */ - -#ifndef _ASM_SH_RWSEM_H -#define _ASM_SH_RWSEM_H - -#ifndef _LINUX_RWSEM_H -#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead" -#endif - -#ifdef __KERNEL__ - -#define RWSEM_UNLOCKED_VALUE 0x00000000 -#define RWSEM_ACTIVE_BIAS 0x00000001 -#define RWSEM_ACTIVE_MASK 0x0000ffff -#define RWSEM_WAITING_BIAS (-0x00010000) -#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) - -/* - * lock for reading - */ -static inline void __down_read(struct rw_semaphore *sem) -{ - if (atomic_inc_return((atomic_t *)(&sem->count)) <= 0) - rwsem_down_read_failed(sem); -} - -static inline int __down_read_trylock(struct rw_semaphore *sem) -{ - int tmp; - - while ((tmp = sem->count) >= 0) { - if (tmp == cmpxchg(&sem->count, tmp, - tmp + RWSEM_ACTIVE_READ_BIAS)) { - return 1; - } - } - return 0; -} - -/* - * lock for writing - */ -static inline void __down_write(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)); - if (tmp != RWSEM_ACTIVE_WRITE_BIAS) - rwsem_down_write_failed(sem); -} - -static inline int __down_write_trylock(struct rw_semaphore *sem) -{ - int tmp; - - tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, - RWSEM_ACTIVE_WRITE_BIAS); - return tmp == RWSEM_UNLOCKED_VALUE; -} - -/* - * unlock after reading - */ -static inline void __up_read(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_dec_return((atomic_t *)(&sem->count)); - if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0) - rwsem_wake(sem); -} - -/* - * unlock after writing - */ -static inline void __up_write(struct rw_semaphore *sem) -{ - if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)) < 0) - rwsem_wake(sem); -} - -/* - * implement atomic add functionality - */ -static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) -{ - atomic_add(delta, (atomic_t *)(&sem->count)); -} - -/* - * downgrade write lock to read lock - */ -static inline void __downgrade_write(struct rw_semaphore *sem) -{ - int tmp; - - tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); - if (tmp < 0) - rwsem_downgrade_wake(sem); -} - -/* - * implement exchange and add functionality - */ -static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) -{ - return atomic_add_return(delta, (atomic_t *)(&sem->count)); -} - -#endif /* __KERNEL__ */ -#endif /* _ASM_SH_RWSEM_H */ -- GitLab From 938072e32ce13e5537ef001cdabcb8a6932b09a0 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:25 +0200 Subject: [PATCH 2381/9938] locking/rwsem, sparc: Drop superfluous arch specific implementation sparc basically reuses the generic implementation of rwsem so we can reuse the code rather than duplicate it. Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-6-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/sparc/include/asm/Kbuild | 1 + arch/sparc/include/asm/rwsem.h | 119 --------------------------------- 2 files changed, 1 insertion(+), 119 deletions(-) delete mode 100644 arch/sparc/include/asm/rwsem.h diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index e928618838bc..6024c26c0585 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -16,6 +16,7 @@ generic-y += mm-arch-hooks.h generic-y += module.h generic-y += mutex.h generic-y += preempt.h +generic-y += rwsem.h generic-y += serial.h generic-y += trace_clock.h generic-y += types.h diff --git a/arch/sparc/include/asm/rwsem.h b/arch/sparc/include/asm/rwsem.h deleted file mode 100644 index e5a0d575bc7f..000000000000 --- a/arch/sparc/include/asm/rwsem.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * rwsem.h: R/W semaphores implemented using CAS - * - * Written by David S. Miller (davem@redhat.com), 2001. - * Derived from asm-i386/rwsem.h - */ -#ifndef _SPARC64_RWSEM_H -#define _SPARC64_RWSEM_H - -#ifndef _LINUX_RWSEM_H -#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead" -#endif - -#ifdef __KERNEL__ - -#define RWSEM_UNLOCKED_VALUE 0x00000000L -#define RWSEM_ACTIVE_BIAS 0x00000001L -#define RWSEM_ACTIVE_MASK 0xffffffffL -#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1) -#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) - -/* - * lock for reading - */ -static inline void __down_read(struct rw_semaphore *sem) -{ - if (unlikely(atomic64_inc_return((atomic64_t *)(&sem->count)) <= 0L)) - rwsem_down_read_failed(sem); -} - -static inline int __down_read_trylock(struct rw_semaphore *sem) -{ - long tmp; - - while ((tmp = sem->count) >= 0L) { - if (tmp == cmpxchg(&sem->count, tmp, - tmp + RWSEM_ACTIVE_READ_BIAS)) { - return 1; - } - } - return 0; -} - -/* - * lock for writing - */ -static inline void __down_write(struct rw_semaphore *sem) -{ - long tmp; - - tmp = atomic64_add_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic64_t *)(&sem->count)); - if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) - rwsem_down_write_failed(sem); -} - -static inline int __down_write_trylock(struct rw_semaphore *sem) -{ - long tmp; - - tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, - RWSEM_ACTIVE_WRITE_BIAS); - return tmp == RWSEM_UNLOCKED_VALUE; -} - -/* - * unlock after reading - */ -static inline void __up_read(struct rw_semaphore *sem) -{ - long tmp; - - tmp = atomic64_dec_return((atomic64_t *)(&sem->count)); - if (unlikely(tmp < -1L && (tmp & RWSEM_ACTIVE_MASK) == 0L)) - rwsem_wake(sem); -} - -/* - * unlock after writing - */ -static inline void __up_write(struct rw_semaphore *sem) -{ - if (unlikely(atomic64_sub_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic64_t *)(&sem->count)) < 0L)) - rwsem_wake(sem); -} - -/* - * implement atomic add functionality - */ -static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) -{ - atomic64_add(delta, (atomic64_t *)(&sem->count)); -} - -/* - * downgrade write lock to read lock - */ -static inline void __downgrade_write(struct rw_semaphore *sem) -{ - long tmp; - - tmp = atomic64_add_return(-RWSEM_WAITING_BIAS, (atomic64_t *)(&sem->count)); - if (tmp < 0L) - rwsem_downgrade_wake(sem); -} - -/* - * implement exchange and add functionality - */ -static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) -{ - return atomic64_add_return(delta, (atomic64_t *)(&sem->count)); -} - -#endif /* __KERNEL__ */ - -#endif /* _SPARC64_RWSEM_H */ -- GitLab From d47996082f52baa0ca8b48d26b3cbef5ede70a73 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:26 +0200 Subject: [PATCH 2382/9938] locking/rwsem: Introduce basis for down_write_killable() Introduce a generic implementation necessary for down_write_killable(). This is a trivial extension of the already existing down_write() call which can be interrupted by SIGKILL. This patch doesn't provide down_write_killable() yet because arches have to provide the necessary pieces before. rwsem_down_write_failed() which is a generic slow path for the write lock is extended to take a task state and renamed to __rwsem_down_write_failed_common(). The return value is either a valid semaphore pointer or ERR_PTR(-EINTR). rwsem_down_write_failed_killable() is exported as a new way to wait for the lock and be killable. For rwsem-spinlock implementation the current __down_write() it updated in a similar way as __rwsem_down_write_failed_common() except it doesn't need new exports just visible __down_write_killable(). Architectures which are not using the generic rwsem implementation are supposed to provide their __down_write_killable() implementation and use rwsem_down_write_failed_killable() for the slow path. Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-7-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- include/asm-generic/rwsem.h | 12 ++++++++++++ include/linux/rwsem-spinlock.h | 1 + include/linux/rwsem.h | 2 ++ kernel/locking/rwsem-spinlock.c | 22 ++++++++++++++++++++-- kernel/locking/rwsem-xadd.c | 31 +++++++++++++++++++++++++------ 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h index b8d8a6cf4ca8..3fc94a046bf5 100644 --- a/include/asm-generic/rwsem.h +++ b/include/asm-generic/rwsem.h @@ -63,6 +63,18 @@ static inline void __down_write(struct rw_semaphore *sem) rwsem_down_write_failed(sem); } +static inline int __down_write_killable(struct rw_semaphore *sem) +{ + long tmp; + + tmp = atomic_long_add_return_acquire(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_long_t *)&sem->count); + if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) + if (IS_ERR(rwsem_down_write_failed_killable(sem))) + return -EINTR; + return 0; +} + static inline int __down_write_trylock(struct rw_semaphore *sem) { long tmp; diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h index a733a5467e6c..ae0528b834cd 100644 --- a/include/linux/rwsem-spinlock.h +++ b/include/linux/rwsem-spinlock.h @@ -34,6 +34,7 @@ struct rw_semaphore { extern void __down_read(struct rw_semaphore *sem); extern int __down_read_trylock(struct rw_semaphore *sem); extern void __down_write(struct rw_semaphore *sem); +extern int __must_check __down_write_killable(struct rw_semaphore *sem); extern int __down_write_trylock(struct rw_semaphore *sem); extern void __up_read(struct rw_semaphore *sem); extern void __up_write(struct rw_semaphore *sem); diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 8f498cdde280..7d7ae029dac5 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_RWSEM_SPIN_ON_OWNER #include #endif @@ -43,6 +44,7 @@ struct rw_semaphore { extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_down_write_failed_killable(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *); extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c index bab26104a5d0..1591f6b3539f 100644 --- a/kernel/locking/rwsem-spinlock.c +++ b/kernel/locking/rwsem-spinlock.c @@ -191,11 +191,12 @@ int __down_read_trylock(struct rw_semaphore *sem) /* * get a write lock on the semaphore */ -void __sched __down_write(struct rw_semaphore *sem) +int __sched __down_write_common(struct rw_semaphore *sem, int state) { struct rwsem_waiter waiter; struct task_struct *tsk; unsigned long flags; + int ret = 0; raw_spin_lock_irqsave(&sem->wait_lock, flags); @@ -215,16 +216,33 @@ void __sched __down_write(struct rw_semaphore *sem) */ if (sem->count == 0) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (signal_pending_state(state, current)) { + ret = -EINTR; + goto out; + } + set_task_state(tsk, state); raw_spin_unlock_irqrestore(&sem->wait_lock, flags); schedule(); raw_spin_lock_irqsave(&sem->wait_lock, flags); } /* got the lock */ sem->count = -1; +out: list_del(&waiter.list); raw_spin_unlock_irqrestore(&sem->wait_lock, flags); + + return ret; +} + +void __sched __down_write(struct rw_semaphore *sem) +{ + __down_write_common(sem, TASK_UNINTERRUPTIBLE); +} + +int __sched __down_write_killable(struct rw_semaphore *sem) +{ + return __down_write_common(sem, TASK_KILLABLE); } /* diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index a4d4de05b2d1..df4dcb883b50 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -433,12 +433,13 @@ static inline bool rwsem_has_spinner(struct rw_semaphore *sem) /* * Wait until we successfully acquire the write lock */ -__visible -struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem) +static inline struct rw_semaphore * +__rwsem_down_write_failed_common(struct rw_semaphore *sem, int state) { long count; bool waiting = true; /* any queued threads before us */ struct rwsem_waiter waiter; + struct rw_semaphore *ret = sem; /* undo write bias from down_write operation, stop active locking */ count = rwsem_atomic_update(-RWSEM_ACTIVE_WRITE_BIAS, sem); @@ -478,7 +479,7 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem) count = rwsem_atomic_update(RWSEM_WAITING_BIAS, sem); /* wait until we successfully acquire the lock */ - set_current_state(TASK_UNINTERRUPTIBLE); + set_current_state(state); while (true) { if (rwsem_try_write_lock(count, sem)) break; @@ -486,21 +487,39 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem) /* Block until there are no active lockers. */ do { + if (signal_pending_state(state, current)) { + raw_spin_lock_irq(&sem->wait_lock); + ret = ERR_PTR(-EINTR); + goto out; + } schedule(); - set_current_state(TASK_UNINTERRUPTIBLE); + set_current_state(state); } while ((count = sem->count) & RWSEM_ACTIVE_MASK); raw_spin_lock_irq(&sem->wait_lock); } +out: __set_current_state(TASK_RUNNING); - list_del(&waiter.list); raw_spin_unlock_irq(&sem->wait_lock); - return sem; + return ret; +} + +__visible struct rw_semaphore * __sched +rwsem_down_write_failed(struct rw_semaphore *sem) +{ + return __rwsem_down_write_failed_common(sem, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(rwsem_down_write_failed); +__visible struct rw_semaphore * __sched +rwsem_down_write_failed_killable(struct rw_semaphore *sem) +{ + return __rwsem_down_write_failed_common(sem, TASK_KILLABLE); +} +EXPORT_SYMBOL(rwsem_down_write_failed_killable); + /* * handle waking up a waiter on the semaphore * - up_read/up_write has decremented the active part of count if we come here -- GitLab From 7deb5eebc1e61b15c5c7f1ef19f216b20d7f7d00 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:27 +0200 Subject: [PATCH 2383/9938] locking/rwsem, alpha: Provide __down_write_killable() Introduce ___down_write() for the fast path and reuse it for __down_write() resp. __down_write_killable() each using the respective generic slow path (rwsem_down_write_failed() resp. rwsem_down_write_failed_killable()). Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-8-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/alpha/include/asm/rwsem.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/alpha/include/asm/rwsem.h b/arch/alpha/include/asm/rwsem.h index a83bbea62c67..0131a7058778 100644 --- a/arch/alpha/include/asm/rwsem.h +++ b/arch/alpha/include/asm/rwsem.h @@ -63,7 +63,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) return res >= 0 ? 1 : 0; } -static inline void __down_write(struct rw_semaphore *sem) +static inline long ___down_write(struct rw_semaphore *sem) { long oldcount; #ifndef CONFIG_SMP @@ -83,10 +83,24 @@ static inline void __down_write(struct rw_semaphore *sem) :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp) :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory"); #endif - if (unlikely(oldcount)) + return oldcount; +} + +static inline void __down_write(struct rw_semaphore *sem) +{ + if (unlikely(___down_write(sem))) rwsem_down_write_failed(sem); } +static inline int __down_write_killable(struct rw_semaphore *sem) +{ + if (unlikely(___down_write(sem))) + if (IS_ERR(rwsem_down_write_failed_killable(sem))) + return -EINTR; + + return 0; +} + /* * trylock for writing -- returns 1 if successful, 0 if contention */ -- GitLab From a02137eb5177e7afc8dfa52a2888c1f2f4840739 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:28 +0200 Subject: [PATCH 2384/9938] locking/rwsem, ia64: Provide __down_write_killable() Introduce ___down_write() for the fast path and reuse it for __down_write() resp. __down_write_killable() each using the respective generic slow path (rwsem_down_write_failed() resp. rwsem_down_write_failed_killable()). Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-9-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/ia64/include/asm/rwsem.h | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h index ce112472bdd6..8b23e070b844 100644 --- a/arch/ia64/include/asm/rwsem.h +++ b/arch/ia64/include/asm/rwsem.h @@ -49,8 +49,8 @@ __down_read (struct rw_semaphore *sem) /* * lock for writing */ -static inline void -__down_write (struct rw_semaphore *sem) +static inline long +___down_write (struct rw_semaphore *sem) { long old, new; @@ -59,10 +59,26 @@ __down_write (struct rw_semaphore *sem) new = old + RWSEM_ACTIVE_WRITE_BIAS; } while (cmpxchg_acq(&sem->count, old, new) != old); - if (old != 0) + return old; +} + +static inline void +__down_write (struct rw_semaphore *sem) +{ + if (___down_write(sem)) rwsem_down_write_failed(sem); } +static inline int +__down_write_killable (struct rw_semaphore *sem) +{ + if (___down_write(sem)) + if (IS_ERR(rwsem_down_write_failed_killable(sem))) + return -EINTR; + + return 0; +} + /* * unlock after reading */ -- GitLab From 4edab14ec66fae5b3c7c4969295facf70365f39d Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:29 +0200 Subject: [PATCH 2385/9938] locking/rwsem, s390: Provide __down_write_killable() Introduce ___down_write() for the fast path and reuse it for __down_write() resp. __down_write_killable() each using the respective generic slow path (rwsem_down_write_failed() resp. rwsem_down_write_failed_killable()). Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-10-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/s390/include/asm/rwsem.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h index 555d23b6b6d1..c75e4471e618 100644 --- a/arch/s390/include/asm/rwsem.h +++ b/arch/s390/include/asm/rwsem.h @@ -90,7 +90,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) /* * lock for writing */ -static inline void __down_write(struct rw_semaphore *sem) +static inline long ___down_write(struct rw_semaphore *sem) { signed long old, new, tmp; @@ -104,10 +104,25 @@ static inline void __down_write(struct rw_semaphore *sem) : "=&d" (old), "=&d" (new), "=Q" (sem->count) : "Q" (sem->count), "m" (tmp) : "cc", "memory"); - if (old != 0) + + return old; +} + +static inline void __down_write(struct rw_semaphore *sem) +{ + if (___down_write(sem)) rwsem_down_write_failed(sem); } +static inline int __down_write_killable(struct rw_semaphore *sem) +{ + if (___down_write(sem)) + if (IS_ERR(rwsem_down_write_failed_killable(sem))) + return -EINTR; + + return 0; +} + /* * trylock for writing -- returns 1 if successful, 0 if contention */ -- GitLab From 664b4e24c6145830885e854195376351b0eb3eee Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:30 +0200 Subject: [PATCH 2386/9938] locking/rwsem, x86: Provide __down_write_killable() which uses the same fast path as __down_write() except it falls back to call_rwsem_down_write_failed_killable() slow path and return -EINTR if killed. To prevent from code duplication extract the skeleton of __down_write() into a helper macro which just takes the semaphore and the slow path function to be called. Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-11-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/rwsem.h | 41 ++++++++++++++++++++++++------------ arch/x86/lib/rwsem.S | 8 +++++++ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h index 4a8292a0d6e1..d759c5f70f49 100644 --- a/arch/x86/include/asm/rwsem.h +++ b/arch/x86/include/asm/rwsem.h @@ -99,21 +99,36 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) /* * lock for writing */ +#define ____down_write(sem, slow_path) \ +({ \ + long tmp; \ + struct rw_semaphore* ret = sem; \ + asm volatile("# beginning down_write\n\t" \ + LOCK_PREFIX " xadd %1,(%2)\n\t" \ + /* adds 0xffff0001, returns the old value */ \ + " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \ + /* was the active mask 0 before? */\ + " jz 1f\n" \ + " call " slow_path "\n" \ + "1:\n" \ + "# ending down_write" \ + : "+m" (sem->count), "=d" (tmp), "+a" (ret) \ + : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \ + : "memory", "cc"); \ + ret; \ +}) + static inline void __down_write(struct rw_semaphore *sem) { - long tmp; - asm volatile("# beginning down_write\n\t" - LOCK_PREFIX " xadd %1,(%2)\n\t" - /* adds 0xffff0001, returns the old value */ - " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" - /* was the active mask 0 before? */ - " jz 1f\n" - " call call_rwsem_down_write_failed\n" - "1:\n" - "# ending down_write" - : "+m" (sem->count), "=d" (tmp) - : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) - : "memory", "cc"); + ____down_write(sem, "call_rwsem_down_write_failed"); +} + +static inline int __down_write_killable(struct rw_semaphore *sem) +{ + if (IS_ERR(____down_write(sem, "call_rwsem_down_write_failed_killable"))) + return -EINTR; + + return 0; } /* diff --git a/arch/x86/lib/rwsem.S b/arch/x86/lib/rwsem.S index be110efa0096..4534a7e912f3 100644 --- a/arch/x86/lib/rwsem.S +++ b/arch/x86/lib/rwsem.S @@ -106,6 +106,14 @@ ENTRY(call_rwsem_down_write_failed) ret ENDPROC(call_rwsem_down_write_failed) +ENTRY(call_rwsem_down_write_failed_killable) + save_common_regs + movq %rax,%rdi + call rwsem_down_write_failed_killable + restore_common_regs + ret +ENDPROC(call_rwsem_down_write_failed_killable) + ENTRY(call_rwsem_wake) FRAME_BEGIN /* do nothing if still outstanding active readers */ -- GitLab From e465de1cd5e1759e40f077bac287de60d56ad06c Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 6 Apr 2016 17:35:07 +0300 Subject: [PATCH 2387/9938] perf/x86/intel/pt: Use boot_cpu_has() because it's there At the moment, initialization path is using test_cpu_cap(&boot_cpu_data), to detect PT, which is just open coding boot_cpu_has(). Use the latter instead. Signed-off-by: Alexander Shishkin Acked-by: Borislav Petkov Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: eranian@google.com Cc: vince@deater.net Link: http://lkml.kernel.org/r/1459953307-14372-1-git-send-email-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/pt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index 127f58c17976..1aefd430e752 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -1106,7 +1106,7 @@ static __init int pt_init(void) BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE); - if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT)) + if (!boot_cpu_has(X86_FEATURE_INTEL_PT)) return -ENODEV; get_online_cpus(); -- GitLab From 69385f8879344f4a1f078f761bd3523fcf697131 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 6 Apr 2016 10:05:14 +0200 Subject: [PATCH 2388/9938] x86/RAS: Rename AMD MCE injector config item ... to be the same like the file name of injection module itself to avoid confusion when grepping. No functionality change. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Link: http://lkml.kernel.org/r/1459929916-12852-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/ras/Kconfig | 2 +- arch/x86/ras/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/ras/Kconfig b/arch/x86/ras/Kconfig index df280da34825..d957d5f21a86 100644 --- a/arch/x86/ras/Kconfig +++ b/arch/x86/ras/Kconfig @@ -1,4 +1,4 @@ -config AMD_MCE_INJ +config MCE_AMD_INJ tristate "Simple MCE injection interface for AMD processors" depends on RAS && EDAC_DECODE_MCE && DEBUG_FS && AMD_NB default n diff --git a/arch/x86/ras/Makefile b/arch/x86/ras/Makefile index dd2c98b84037..5f94546db280 100644 --- a/arch/x86/ras/Makefile +++ b/arch/x86/ras/Makefile @@ -1,2 +1,2 @@ -obj-$(CONFIG_AMD_MCE_INJ) += mce_amd_inj.o +obj-$(CONFIG_MCE_AMD_INJ) += mce_amd_inj.o -- GitLab From bf92b1feb658f6a262daf3a87d790997a1dca0ff Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Wed, 6 Apr 2016 10:05:15 +0200 Subject: [PATCH 2389/9938] x86/mce: Remove explicit smp_rmb() when starting CPUs sync mce_start() has an explicit smp_wmb() to serialize writes to global_nwo and mce_callin. However, atomic_inc_return() implies barriers on both sides of the call, as such simply rely on this full SMP barrier. Signed-off-by: Davidlohr Bueso Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1458602396-840-1-git-send-email-dave@stgolabs.net Link: http://lkml.kernel.org/r/1459929916-12852-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mcheck/mce.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index f0c921b03e42..6b7039c166b8 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -830,9 +830,9 @@ static int mce_start(int *no_way_out) atomic_add(*no_way_out, &global_nwo); /* - * global_nwo should be updated before mce_callin + * Rely on the implied barrier below, such that global_nwo + * is updated before mce_callin. */ - smp_wmb(); order = atomic_inc_return(&mce_callin); /* -- GitLab From 399fc1847c62b4a4b8f6bc446f1bd352234c64a1 Mon Sep 17 00:00:00 2001 From: Markus Reichl Date: Mon, 4 Apr 2016 11:55:13 +0200 Subject: [PATCH 2390/9938] ARM: dts: exynos: Add eMMC and SD regulator supplies to Odroid XU3/XU4 Add vmmc and vqmmc supplies from MF circuit sheets for eMMC and SD on odroid XU3 and XU4 to avoid warnings: dwmmc_exynos 12200000.mmc: Looking up vmmc-supply property in node /mmc@12200000 failed Also remove their always_on properties so the regulators could be disabled when not used. Signed-off-by: Markus Reichl Signed-off-by: Krzysztof Kozlowski --- .../boot/dts/exynos5422-odroidxu3-common.dtsi | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 1bd507bfa750..0e71d4253205 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -121,10 +121,9 @@ }; ldo3_reg: LDO3 { - regulator-name = "vdd_ldo3"; + regulator-name = "vddq_mmc0"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; - regulator-always-on; }; ldo5_reg: LDO5 { @@ -184,10 +183,9 @@ }; ldo13_reg: LDO13 { - regulator-name = "vdd_ldo13"; + regulator-name = "vddq_mmc2"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - regulator-always-on; }; ldo15_reg: LDO15 { @@ -211,11 +209,16 @@ regulator-always-on; }; + ldo18_reg: LDO18 { + regulator-name = "vdd_emmc_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + ldo19_reg: LDO19 { regulator-name = "vdd_sd"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - regulator-always-on; }; ldo24_reg: LDO24 { @@ -347,6 +350,8 @@ cap-mmc-highspeed; mmc-hs200-1_8v; mmc-hs400-1_8v; + vmmc-supply = <&ldo18_reg>; + vqmmc-supply = <&ldo3_reg>; }; &mmc_2 { @@ -359,6 +364,8 @@ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>; bus-width = <4>; cap-sd-highspeed; + vmmc-supply = <&ldo19_reg>; + vqmmc-supply = <&ldo13_reg>; }; &pinctrl_0 { -- GitLab From 31d3f3241e74e085f4736699b8b10d17f95c1aac Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:40 +0900 Subject: [PATCH 2391/9938] ARM: dts: exynos: Fix DTC unit name warnings in cros-adc-thermistors Fix following DTC warnings in cros-adc-thermistors: Warning (unit_address_vs_reg): Node /adc@12D10000/ncp15wb473@3 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /adc@12D10000/ncp15wb473@4 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /adc@12D10000/ncp15wb473@5 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /adc@12D10000/ncp15wb473@6 has a unit name, but no reg property Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/cros-adc-thermistors.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/cros-adc-thermistors.dtsi b/arch/arm/boot/dts/cros-adc-thermistors.dtsi index acd4fe1833f2..ce7fca76b0d6 100644 --- a/arch/arm/boot/dts/cros-adc-thermistors.dtsi +++ b/arch/arm/boot/dts/cros-adc-thermistors.dtsi @@ -13,28 +13,28 @@ */ &adc { - ncp15wb473@3 { + thermistor3 { compatible = "murata,ncp15wb473"; pullup-uv = <1800000>; pullup-ohm = <47000>; pulldown-ohm = <0>; io-channels = <&adc 3>; }; - ncp15wb473@4 { + thermistor4 { compatible = "murata,ncp15wb473"; pullup-uv = <1800000>; pullup-ohm = <47000>; pulldown-ohm = <0>; io-channels = <&adc 4>; }; - ncp15wb473@5 { + thermistor5 { compatible = "murata,ncp15wb473"; pullup-uv = <1800000>; pullup-ohm = <47000>; pulldown-ohm = <0>; io-channels = <&adc 5>; }; - ncp15wb473@6 { + thermistor6 { compatible = "murata,ncp15wb473"; pullup-uv = <1800000>; pullup-ohm = <47000>; -- GitLab From bb72cadef952525844bff169ddb4af016666fedc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:41 +0900 Subject: [PATCH 2392/9938] ARM: dts: exynos: Fix DTC unit name warnings in Exynos3250 Fix following DTC warnings in Exynos3250 boards: Warning (unit_address_vs_reg): Node /soc/video-phy@10020710 has a unit name, but no reg property Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos3250.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi index 13d00f94cb81..094782b207ee 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/exynos3250.dtsi @@ -155,7 +155,7 @@ interrupt-parent = <&gic>; }; - mipi_phy: video-phy@10020710 { + mipi_phy: video-phy { compatible = "samsung,s5pv210-mipi-video-phy"; #phy-cells = <1>; syscon = <&pmu_system_controller>; -- GitLab From 72c4b2b6be454e0be8fbbe3beb55b6dce4c0978f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:42 +0900 Subject: [PATCH 2393/9938] ARM: dts: exynos: Fix DTC unit name warnings in Exynos4 Fix following DTC warnings in all Exynos4 boards: Warning (unit_address_vs_reg): Node /soc/video-phy@10020710 has a unit name, but no reg property Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos4.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 000d506c027b..021f52d43ff7 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -82,7 +82,7 @@ reg = <0x12570000 0x14>; }; - mipi_phy: video-phy@10020710 { + mipi_phy: video-phy { compatible = "samsung,s5pv210-mipi-video-phy"; #phy-cells = <1>; syscon = <&pmu_system_controller>; -- GitLab From 26ee29a657aa849da308bda94562c6d6bd398a3f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:43 +0900 Subject: [PATCH 2394/9938] ARM: dts: exynos: Fix DTC unit name warnings in Trats2 board Fix following DTC warnings in Trats2 board: Warning (unit_address_vs_reg): Node /i2c-gpio-1/max77693@66/regulators/ESAFEOUT1@1 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /i2c-gpio-1/max77693@66/regulators/ESAFEOUT2@2 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /i2c-gpio-1/max77693@66/regulators/CHARGER@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /thermistor-ap@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /thermistor-battery@1 has a unit name, but no reg property Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos4412-trats2.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 2bf363c3bf62..27dbf1687754 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -146,13 +146,13 @@ reg = <0x66>; regulators { - esafeout1_reg: ESAFEOUT1@1 { + esafeout1_reg: ESAFEOUT1 { regulator-name = "ESAFEOUT1"; }; - esafeout2_reg: ESAFEOUT2@2 { + esafeout2_reg: ESAFEOUT2 { regulator-name = "ESAFEOUT2"; }; - charger_reg: CHARGER@0 { + charger_reg: CHARGER { regulator-name = "CHARGER"; regulator-min-microamp = <60000>; regulator-max-microamp = <2580000>; @@ -251,7 +251,7 @@ "SPK", "SPKOUTRP"; }; - thermistor-ap@0 { + thermistor-ap { compatible = "ntc,ncp15wb473"; pullup-uv = <1800000>; /* VCC_1.8V_AP */ pullup-ohm = <100000>; /* 100K */ @@ -259,7 +259,7 @@ io-channels = <&adc 1>; /* AP temperature */ }; - thermistor-battery@1 { + thermistor-battery { compatible = "ntc,ncp15wb473"; pullup-uv = <1800000>; /* VCC_1.8V_AP */ pullup-ohm = <100000>; /* 100K */ @@ -1276,7 +1276,7 @@ cs-gpios = <&gpb 5 GPIO_ACTIVE_HIGH>; status = "okay"; - s5c73m3_spi: s5c73m3 { + s5c73m3_spi: s5c73m3@0 { compatible = "samsung,s5c73m3"; spi-max-frequency = <50000000>; reg = <0>; -- GitLab From c344c724eb16df5b5d864ce864bc24dc3c7ddd58 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:44 +0900 Subject: [PATCH 2395/9938] ARM: dts: exynos: Fix DTC unit name warnings in Exynos4x12 Fix following DTC warnings in Exynos4x12 boards: Warning (unit_address_vs_reg): Node /camera/fimc-is@12000000/pmu has a reg or ranges property, but no unit name Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos4x12.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi index 84a23f962946..b7490ea0c75c 100644 --- a/arch/arm/boot/dts/exynos4x12.dtsi +++ b/arch/arm/boot/dts/exynos4x12.dtsi @@ -179,7 +179,7 @@ ranges; status = "disabled"; - pmu { + pmu@10020000 { reg = <0x10020000 0x3000>; }; -- GitLab From 5c9cbade0629a7752acb87c16c1f25112aecc69f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:45 +0900 Subject: [PATCH 2396/9938] ARM: dts: exynos: Fix DTC unit name warnings in Exynos5250 Fix following DTC warnings in all Exynos5250 boards: Warning (unit_address_vs_reg): Node /dp-controller@145B0000/display-timings/timing@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /usb@12000000 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /usb@12000000/dwc3 has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /hdmi has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /mixer has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /video-phy@10040720 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /fixed-regulator@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /fixed-regulator@1 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /fixed-regulator@2 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /i2c@12C70000/trackpad has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /i2c@12CD0000/lvds-bridge@20/ports/port@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /i2c@12CD0000/lvds-bridge@20/ports/port@1 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /i2c-arbitrator/i2c@0/embedded-controller has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /i2c-arbitrator/i2c@0/power-regulator has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /i2c@12CA0000/embedded-controller has a reg or ranges property, but no unit name Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos5250-arndale.dts | 2 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 8 ++++---- arch/arm/boot/dts/exynos5250-snow-common.dtsi | 12 ++++++------ arch/arm/boot/dts/exynos5250-spring.dts | 2 +- arch/arm/boot/dts/exynos5250.dtsi | 10 +++++----- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 8b2acc74aa76..1e25152dc0f6 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -133,7 +133,7 @@ display-timings { native-mode = <&timing0>; - timing0: timing@0 { + timing0: timing { /* 2560x1600 DP panel */ clock-frequency = <50000>; hactive = <2560>; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 0f5dcd418af8..0e2eb3f6b590 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -29,7 +29,7 @@ bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc"; }; - vdd: fixed-regulator@0 { + vdd: fixed-regulator-vdd { compatible = "regulator-fixed"; regulator-name = "vdd-supply"; regulator-min-microvolt = <1800000>; @@ -37,7 +37,7 @@ regulator-always-on; }; - dbvdd: fixed-regulator@1 { + dbvdd: fixed-regulator-dbvdd { compatible = "regulator-fixed"; regulator-name = "dbvdd-supply"; regulator-min-microvolt = <3300000>; @@ -45,7 +45,7 @@ regulator-always-on; }; - spkvdd: fixed-regulator@2 { + spkvdd: fixed-regulator-spkvdd { compatible = "regulator-fixed"; regulator-name = "spkvdd-supply"; regulator-min-microvolt = <5000000>; @@ -93,7 +93,7 @@ display-timings { native-mode = <&timing0>; - timing0: timing@0 { + timing0: timing { /* 1280x800 */ clock-frequency = <50000>; hactive = <1280>; diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi index 95210ef6a6b5..c9889b1f530a 100644 --- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi +++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi @@ -84,7 +84,7 @@ sbs,poll-retry-count = <1>; }; - cros_ec: embedded-controller { + cros_ec: embedded-controller@1e { compatible = "google,cros-ec-i2c"; reg = <0x1e>; interrupts = <6 IRQ_TYPE_NONE>; @@ -94,7 +94,7 @@ wakeup-source; }; - power-regulator { + power-regulator@48 { compatible = "ti,tps65090"; reg = <0x48>; @@ -244,7 +244,7 @@ samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; ports { - port@0 { + port0 { dp_out: endpoint { remote-endpoint = <&bridge_in>; }; @@ -428,7 +428,7 @@ samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <378000>; - trackpad { + trackpad@67 { reg = <0x67>; compatible = "cypress,cyapa"; interrupts = <2 IRQ_TYPE_NONE>; @@ -487,13 +487,13 @@ edid-emulation = <5>; ports { - port@0 { + port0 { bridge_out: endpoint { remote-endpoint = <&panel_in>; }; }; - port@1 { + port1 { bridge_in: endpoint { remote-endpoint = <&dp_out>; }; diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index 0f500cb1eb2d..273d66282ebc 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -383,7 +383,7 @@ samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <66000>; - cros_ec: embedded-controller { + cros_ec: embedded-controller@1e { compatible = "google,cros-ec-i2c"; reg = <0x1e>; interrupts = <6 IRQ_TYPE_NONE>; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index e653ae04015a..c7158b2fb213 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -596,7 +596,7 @@ pinctrl-0 = <&i2s2_bus>; }; - usb@12000000 { + usb_dwc3 { compatible = "samsung,exynos5250-dwusb3"; clocks = <&clock CLK_USB3>; clock-names = "usbdrd30"; @@ -604,7 +604,7 @@ #size-cells = <1>; ranges; - usbdrd_dwc3: dwc3 { + usbdrd_dwc3: dwc3@12000000 { compatible = "synopsys,dwc3"; reg = <0x12000000 0x10000>; interrupts = <0 72 0>; @@ -763,7 +763,7 @@ iommu = <&sysmmu_gsc3>; }; - hdmi: hdmi { + hdmi: hdmi@14530000 { compatible = "samsung,exynos4212-hdmi"; reg = <0x14530000 0x70000>; power-domains = <&pd_disp1>; @@ -776,7 +776,7 @@ samsung,syscon-phandle = <&pmu_system_controller>; }; - mixer { + mixer@14450000 { compatible = "samsung,exynos5250-mixer"; reg = <0x14450000 0x10000>; power-domains = <&pd_disp1>; @@ -787,7 +787,7 @@ iommus = <&sysmmu_tv>; }; - dp_phy: video-phy@10040720 { + dp_phy: video-phy { compatible = "samsung,exynos5250-dp-video-phy"; samsung,pmu-syscon = <&pmu_system_controller>; #phy-cells = <0>; -- GitLab From 938d02932e95cc900f3c11ba978d16bb8e8a11b6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:46 +0900 Subject: [PATCH 2397/9938] ARM: dts: exynos: Fix DTC unit name warnings in Exynos542x Fix following DTC warnings in all Exynos542x/5800 boards: Warning (unit_address_vs_reg): Node /video-phy@10040728 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /video-phy@10040714 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /usb@12000000 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /usb@12000000/dwc3 has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /usb@12400000 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /usb@12400000/dwc3 has a reg or ranges property, but no unit name Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos5420.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 7b99cb58d82d..385491aa539a 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -551,13 +551,13 @@ clock-names = "timers"; }; - dp_phy: video-phy@10040728 { + dp_phy: dp-video-phy { compatible = "samsung,exynos5420-dp-video-phy"; samsung,pmu-syscon = <&pmu_system_controller>; #phy-cells = <0>; }; - mipi_phy: video-phy@10040714 { + mipi_phy: mipi-video-phy { compatible = "samsung,s5pv210-mipi-video-phy"; syscon = <&pmu_system_controller>; #phy-cells = <1>; @@ -913,7 +913,7 @@ clock-names = "secss"; }; - usbdrd3_0: usb@12000000 { + usbdrd3_0: usb3-0 { compatible = "samsung,exynos5250-dwusb3"; clocks = <&clock CLK_USBD300>; clock-names = "usbdrd30"; @@ -921,7 +921,7 @@ #size-cells = <1>; ranges; - usbdrd_dwc3_0: dwc3 { + usbdrd_dwc3_0: dwc3@12000000 { compatible = "snps,dwc3"; reg = <0x12000000 0x10000>; interrupts = <0 72 0>; @@ -939,7 +939,7 @@ #phy-cells = <1>; }; - usbdrd3_1: usb@12400000 { + usbdrd3_1: usb3-1 { compatible = "samsung,exynos5250-dwusb3"; clocks = <&clock CLK_USBD301>; clock-names = "usbdrd30"; @@ -947,7 +947,7 @@ #size-cells = <1>; ranges; - usbdrd_dwc3_1: dwc3 { + usbdrd_dwc3_1: dwc3@12400000 { compatible = "snps,dwc3"; reg = <0x12400000 0x10000>; interrupts = <0 73 0>; -- GitLab From bea7eef6949ca613b49bddd39d108f90f75c95fd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:47 +0900 Subject: [PATCH 2398/9938] ARM: dts: exynos: Fix DTC unit name warnings in Peach Pit Fix following DTC warnings in Exynos5420 Peach Pit: Warning (unit_address_vs_reg): Node /dp-controller@145B0000/ports/port@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /i2c@12CD0000/lvds-bridge@48/ports/port@0 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /i2c@12CD0000/lvds-bridge@48/ports/port@1 has a unit name, but no reg property Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos5420-peach-pit.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 3981ddb25036..e36975b6f625 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -165,7 +165,7 @@ samsung,hpd-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>; ports { - port@0 { + port0 { dp_out: endpoint { remote-endpoint = <&bridge_in>; }; @@ -633,13 +633,13 @@ use-external-pwm; ports { - port@0 { + port0 { bridge_out: endpoint { remote-endpoint = <&panel_in>; }; }; - port@1 { + port1 { bridge_in: endpoint { remote-endpoint = <&dp_out>; }; -- GitLab From fed3b4aa0ac5bcb29f844186182d4fca2af460ed Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:48 +0900 Subject: [PATCH 2399/9938] ARM: dts: exynos: Fix DTC unit name warnings in SMDK5420 Fix following DTC warnings in Exynos5420 SMDK5420: Warning (unit_address_vs_reg): Node /dp-controller@145B0000/display-timings/timing@0 has a unit name, but no reg property Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos5420-smdk5420.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 0785fedf441e..99160f796851 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -111,7 +111,7 @@ display-timings { native-mode = <&timing0>; - timing0: timing@0 { + timing0: timing { clock-frequency = <50000>; hactive = <2560>; vactive = <1600>; -- GitLab From 4185c53f0127229079303c194fe6a668fc337c8f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:49 +0900 Subject: [PATCH 2400/9938] ARM: dts: exynos: Fix DTC unit name warnings in Exynos5440 Fix following DTC warnings in Exynos5440 boards: Warning (unit_address_vs_reg): Node /pinctrl has a reg or ranges property, but no unit name Warning (unit_address_vs_reg): Node /rtc has a reg or ranges property, but no unit name Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos5440.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi index b9342ec5b9cf..fd176819b4bf 100644 --- a/arch/arm/boot/dts/exynos5440.dtsi +++ b/arch/arm/boot/dts/exynos5440.dtsi @@ -132,7 +132,7 @@ clock-names = "spi", "spi_busclk0"; }; - pin_ctrl: pinctrl { + pin_ctrl: pinctrl@E0000 { compatible = "samsung,exynos5440-pinctrl"; reg = <0xE0000 0x1000>; interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, @@ -205,7 +205,7 @@ ranges; }; - rtc { + rtc@130000 { compatible = "samsung,s3c6410-rtc"; reg = <0x130000 0x1000>; interrupts = <0 17 0>, <0 16 0>; -- GitLab From 06e520c4f067e7284fded10656acca924123c58e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 Apr 2016 11:00:50 +0900 Subject: [PATCH 2401/9938] ARM: dts: s5p: Fix DTC unit name warnings in SMDKv210 board Fix following DTC warnings in SMDKv210 board: Warning (unit_address_vs_reg): Node /soc/fimd@f8000000/display-timings/timing@0 has a unit name, but no reg property Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/s5pv210-smdkv210.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/s5pv210-smdkv210.dts b/arch/arm/boot/dts/s5pv210-smdkv210.dts index 54fcc3fc82e2..9eb6aff3e38f 100644 --- a/arch/arm/boot/dts/s5pv210-smdkv210.dts +++ b/arch/arm/boot/dts/s5pv210-smdkv210.dts @@ -197,7 +197,7 @@ display-timings { native-mode = <&timing0>; - timing0: timing@0 { + timing0: timing { /* 800x480@60Hz */ clock-frequency = <24373920>; hactive = <800>; -- GitLab From fb90a6e93c0684ab2629a42462400603aa829b9c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 4 Apr 2016 15:42:02 +0200 Subject: [PATCH 2402/9938] sched/debug: Don't dump sched debug info in SysRq-W sysrq_sched_debug_show() can dump a lot of information. Don't print out all that if we're just trying to get a list of blocked tasks (SysRq-W). The information is still accessible with SysRq-T. Signed-off-by: Rabin Vincent Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Steven Rostedt Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459777322-30902-1-git-send-email-rabin.vincent@axis.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 11594230ef4d..06efbb9c9544 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5050,7 +5050,8 @@ void show_state_filter(unsigned long state_filter) touch_all_softlockup_watchdogs(); #ifdef CONFIG_SCHED_DEBUG - sysrq_sched_debug_show(); + if (!state_filter) + sysrq_sched_debug_show(); #endif rcu_read_unlock(); /* -- GitLab From 8369337e5563245307671208ad555ed1e8b4bb5a Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Wed, 27 Jan 2016 09:24:43 +0800 Subject: [PATCH 2403/9938] arm: dts: Add pinctrl/GPIO/EINT node for mt2701 Add pinctrl and GPIO node to mt2701.dtsi Signed-off-by: Biao Huang Acked-by: Linus Walleij Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt2701.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi index 83437683aa60..18596a2c58a1 100644 --- a/arch/arm/boot/dts/mt2701.dtsi +++ b/arch/arm/boot/dts/mt2701.dtsi @@ -15,6 +15,7 @@ #include #include #include "skeleton64.dtsi" +#include "mt2701-pinfunc.h" / { compatible = "mediatek,mt2701"; @@ -85,6 +86,24 @@ ; }; + pio: pinctrl@10005000 { + compatible = "mediatek,mt2701-pinctrl"; + reg = <0 0x1000b000 0 0x1000>; + mediatek,pctl-regmap = <&syscfg_pctl_a>; + pins-are-numbered; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = , + ; + }; + + syscfg_pctl_a: syscfg@10005000 { + compatible = "mediatek,mt2701-pctl-a-syscfg", "syscon"; + reg = <0 0x10005000 0 0x1000>; + }; + watchdog: watchdog@10007000 { compatible = "mediatek,mt2701-wdt", "mediatek,mt6589-wdt"; -- GitLab From afa05e55a047f8aa7c865dde5353d96d136aeab2 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Wed, 13 Apr 2016 10:12:03 +0530 Subject: [PATCH 2404/9938] arm64: dts: Add nodes for pdma0 and pdma1 for exynos7 This patch adds device tree nodes for pdma0 and pdma1 controllers found on exynos7 SoCs. Signed-off-by: Alim Akhtar Signed-off-by: Krzysztof Kozlowski --- arch/arm64/boot/dts/exynos/exynos7.dtsi | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 2450d0a06da5..ca663dfe5189 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -96,6 +96,35 @@ <0x11006000 0x2000>; }; + amba { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pdma0: pdma@10E10000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x10E10000 0x1000>; + interrupts = <0 225 0>; + clocks = <&clock_fsys0 ACLK_PDMA0>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + }; + + pdma1: pdma@10EB0000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x10EB0000 0x1000>; + interrupts = <0 226 0>; + clocks = <&clock_fsys0 ACLK_PDMA1>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + }; + }; + clock_topc: clock-controller@10570000 { compatible = "samsung,exynos7-clock-topc"; reg = <0x10570000 0x10000>; -- GitLab From d86786474babdf1a2b0dfe245e38f18afc203cc2 Mon Sep 17 00:00:00 2001 From: Erin Lo Date: Wed, 13 Apr 2016 15:07:43 +0800 Subject: [PATCH 2405/9938] ARM: mediatek: Add MT2701 config options for mediatek SoCs. The upcoming MTK pinctrl driver have a big pin table for each SoC and we don't want to bloat the kernel binary if we don't need it. Add config options so we can build for one SoC only. Add MT2701. Signed-off-by: Erin Lo Acked-by: Linus Walleij Signed-off-by: Matthias Brugger --- arch/arm/mach-mediatek/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig index 8ced4ad94af0..70e49d54434e 100644 --- a/arch/arm/mach-mediatek/Kconfig +++ b/arch/arm/mach-mediatek/Kconfig @@ -10,6 +10,10 @@ menuconfig ARCH_MEDIATEK if ARCH_MEDIATEK +config MACH_MT2701 + bool "MediaTek MT2701 SoCs support" + default ARCH_MEDIATEK + config MACH_MT6589 bool "MediaTek MT6589 SoCs support" default ARCH_MEDIATEK -- GitLab From 1886297ce0c8d563a08c8a8c4c0b97743e06cd37 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Mon, 11 Apr 2016 13:36:00 -0600 Subject: [PATCH 2406/9938] x86/mm/pat: Fix BUG_ON() in mmap_mem() on QEMU/i386 The following BUG_ON() crash was reported on QEMU/i386: kernel BUG at arch/x86/mm/physaddr.c:79! Call Trace: phys_mem_access_prot_allowed mmap_mem ? mmap_region mmap_region do_mmap vm_mmap_pgoff SyS_mmap_pgoff do_int80_syscall_32 entry_INT80_32 after commit: edfe63ec97ed ("x86/mtrr: Fix Xorg crashes in Qemu sessions") PAT is now set to disabled state when MTRRs are disabled. Thus, reactivating the __pa(high_memory) check in phys_mem_access_prot_allowed(). When CONFIG_DEBUG_VIRTUAL is set, __pa() calls __phys_addr(), which in turn calls slow_virt_to_phys() for 'high_memory'. Because 'high_memory' is set to (the max direct mapped virt addr + 1), it is not a valid virtual address. Hence, slow_virt_to_phys() returns 0 and hit the BUG_ON. Using __pa_nodebug() instead of __pa() will fix this BUG_ON. However, this code block, originally written for Pentiums and earlier, is no longer adequate since a 32-bit Xen guest has MTRRs disabled and supports ZONE_HIGHMEM. In this setup, this code sets UC attribute for accessing RAM in high memory range. Delete this code block as it has been unused for a long time. Reported-by: kernel test robot Reviewed-by: Borislav Petkov Signed-off-by: Toshi Kani Cc: Andrew Morton Cc: David Vrabel Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1460403360-25441-1-git-send-email-toshi.kani@hpe.com Link: https://lkml.org/lkml/2016/4/1/608 Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index c4c3ddcc9069..fb0604f11eec 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -778,25 +778,6 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, if (file->f_flags & O_DSYNC) pcm = _PAGE_CACHE_MODE_UC_MINUS; -#ifdef CONFIG_X86_32 - /* - * On the PPro and successors, the MTRRs are used to set - * memory types for physical addresses outside main memory, - * so blindly setting UC or PWT on those pages is wrong. - * For Pentiums and earlier, the surround logic should disable - * caching for the high addresses through the KEN pin, but - * we maintain the tradition of paranoia in this code. - */ - if (!pat_enabled() && - !(boot_cpu_has(X86_FEATURE_MTRR) || - boot_cpu_has(X86_FEATURE_K6_MTRR) || - boot_cpu_has(X86_FEATURE_CYRIX_ARR) || - boot_cpu_has(X86_FEATURE_CENTAUR_MCR)) && - (pfn << PAGE_SHIFT) >= __pa(high_memory)) { - pcm = _PAGE_CACHE_MODE_UC; - } -#endif - *vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) | cachemode2protval(pcm)); return 1; -- GitLab From abcfdfe07de75f830cbec1aa3eb17833a0166697 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:24:54 +0200 Subject: [PATCH 2407/9938] x86/cpufeature: Replace cpu_has_avx2 with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-crypto@vger.kernel.org Link: http://lkml.kernel.org/r/1459801503-15600-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/crypto/camellia_aesni_avx2_glue.c | 2 +- arch/x86/crypto/chacha20_glue.c | 2 +- arch/x86/crypto/poly1305_glue.c | 2 +- arch/x86/crypto/serpent_avx2_glue.c | 2 +- arch/x86/include/asm/cpufeature.h | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c index c37f7028c85a..39389662e29b 100644 --- a/arch/x86/crypto/camellia_aesni_avx2_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c @@ -562,7 +562,7 @@ static int __init camellia_aesni_init(void) { const char *feature_name; - if (!cpu_has_avx2 || !cpu_has_avx || !cpu_has_aes || + if (!boot_cpu_has(X86_FEATURE_AVX2) || !cpu_has_avx || !cpu_has_aes || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX2 or AES-NI instructions are not detected.\n"); return -ENODEV; diff --git a/arch/x86/crypto/chacha20_glue.c b/arch/x86/crypto/chacha20_glue.c index 8baaff5af0b5..cea061e137da 100644 --- a/arch/x86/crypto/chacha20_glue.c +++ b/arch/x86/crypto/chacha20_glue.c @@ -129,7 +129,7 @@ static int __init chacha20_simd_mod_init(void) return -ENODEV; #ifdef CONFIG_AS_AVX2 - chacha20_use_avx2 = cpu_has_avx && cpu_has_avx2 && + chacha20_use_avx2 = cpu_has_avx && boot_cpu_has(X86_FEATURE_AVX2) && cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL); #endif return crypto_register_alg(&alg); diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c index b283868acdf8..ea21d2e440f7 100644 --- a/arch/x86/crypto/poly1305_glue.c +++ b/arch/x86/crypto/poly1305_glue.c @@ -183,7 +183,7 @@ static int __init poly1305_simd_mod_init(void) return -ENODEV; #ifdef CONFIG_AS_AVX2 - poly1305_use_avx2 = cpu_has_avx && cpu_has_avx2 && + poly1305_use_avx2 = cpu_has_avx && boot_cpu_has(X86_FEATURE_AVX2) && cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL); alg.descsize = sizeof(struct poly1305_simd_desc_ctx); if (poly1305_use_avx2) diff --git a/arch/x86/crypto/serpent_avx2_glue.c b/arch/x86/crypto/serpent_avx2_glue.c index 408cae2b3543..870f6d812a2d 100644 --- a/arch/x86/crypto/serpent_avx2_glue.c +++ b/arch/x86/crypto/serpent_avx2_glue.c @@ -538,7 +538,7 @@ static int __init init(void) { const char *feature_name; - if (!cpu_has_avx2 || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { + if (!boot_cpu_has(X86_FEATURE_AVX2) || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX2 instructions are not detected.\n"); return -ENODEV; } diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index c594e04bf529..810166530cbf 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -125,7 +125,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) #define cpu_has_aes boot_cpu_has(X86_FEATURE_AES) #define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) -#define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) /* -- GitLab From 1f4dd7938ea575a2d1972e180eaef31e6edb1808 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:24:55 +0200 Subject: [PATCH 2408/9938] x86/cpufeature: Replace cpu_has_aes with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-crypto@vger.kernel.org Link: http://lkml.kernel.org/r/1459801503-15600-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/crypto/camellia_aesni_avx2_glue.c | 3 ++- arch/x86/crypto/camellia_aesni_avx_glue.c | 4 +++- arch/x86/include/asm/cpufeature.h | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c index 39389662e29b..c07f699826a0 100644 --- a/arch/x86/crypto/camellia_aesni_avx2_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c @@ -562,7 +562,8 @@ static int __init camellia_aesni_init(void) { const char *feature_name; - if (!boot_cpu_has(X86_FEATURE_AVX2) || !cpu_has_avx || !cpu_has_aes || + if (!boot_cpu_has(X86_FEATURE_AVX2) || !cpu_has_avx || + !boot_cpu_has(X86_FEATURE_AES) || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX2 or AES-NI instructions are not detected.\n"); return -ENODEV; diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c index 65f64556725b..6d256d59c5fd 100644 --- a/arch/x86/crypto/camellia_aesni_avx_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx_glue.c @@ -554,7 +554,9 @@ static int __init camellia_aesni_init(void) { const char *feature_name; - if (!cpu_has_avx || !cpu_has_aes || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { + if (!cpu_has_avx || + !boot_cpu_has(X86_FEATURE_AES) || + !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX or AES-NI instructions are not detected.\n"); return -ENODEV; } diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 810166530cbf..a6627b30bf45 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -123,7 +123,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) -#define cpu_has_aes boot_cpu_has(X86_FEATURE_AES) #define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) -- GitLab From da154e82af4d0c63e2334d5b3822426600b0490f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:24:56 +0200 Subject: [PATCH 2409/9938] x86/cpufeature: Replace cpu_has_avx with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-crypto@vger.kernel.org Link: http://lkml.kernel.org/r/1459801503-15600-4-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/crypto/aesni-intel_glue.c | 2 +- arch/x86/crypto/camellia_aesni_avx2_glue.c | 3 ++- arch/x86/crypto/camellia_aesni_avx_glue.c | 2 +- arch/x86/crypto/chacha20_glue.c | 3 ++- arch/x86/crypto/poly1305_glue.c | 3 ++- arch/x86/crypto/sha1_ssse3_glue.c | 2 +- arch/x86/crypto/sha256_ssse3_glue.c | 2 +- arch/x86/crypto/sha512_ssse3_glue.c | 2 +- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/include/asm/xor_avx.h | 4 ++-- 10 files changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 064c7e2bd7c8..5b7fa1471007 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -1477,7 +1477,7 @@ static int __init aesni_init(void) } aesni_ctr_enc_tfm = aesni_ctr_enc; #ifdef CONFIG_AS_AVX - if (cpu_has_avx) { + if (boot_cpu_has(X86_FEATURE_AVX)) { /* optimize performance of ctr mode encryption transform */ aesni_ctr_enc_tfm = aesni_ctr_enc_avx_tfm; pr_info("AES CTR mode by8 optimization enabled\n"); diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c index c07f699826a0..60907c139c4e 100644 --- a/arch/x86/crypto/camellia_aesni_avx2_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c @@ -562,7 +562,8 @@ static int __init camellia_aesni_init(void) { const char *feature_name; - if (!boot_cpu_has(X86_FEATURE_AVX2) || !cpu_has_avx || + if (!boot_cpu_has(X86_FEATURE_AVX) || + !boot_cpu_has(X86_FEATURE_AVX2) || !boot_cpu_has(X86_FEATURE_AES) || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX2 or AES-NI instructions are not detected.\n"); diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c index 6d256d59c5fd..d96429da88eb 100644 --- a/arch/x86/crypto/camellia_aesni_avx_glue.c +++ b/arch/x86/crypto/camellia_aesni_avx_glue.c @@ -554,7 +554,7 @@ static int __init camellia_aesni_init(void) { const char *feature_name; - if (!cpu_has_avx || + if (!boot_cpu_has(X86_FEATURE_AVX) || !boot_cpu_has(X86_FEATURE_AES) || !boot_cpu_has(X86_FEATURE_OSXSAVE)) { pr_info("AVX or AES-NI instructions are not detected.\n"); diff --git a/arch/x86/crypto/chacha20_glue.c b/arch/x86/crypto/chacha20_glue.c index cea061e137da..2d5c2e0bd939 100644 --- a/arch/x86/crypto/chacha20_glue.c +++ b/arch/x86/crypto/chacha20_glue.c @@ -129,7 +129,8 @@ static int __init chacha20_simd_mod_init(void) return -ENODEV; #ifdef CONFIG_AS_AVX2 - chacha20_use_avx2 = cpu_has_avx && boot_cpu_has(X86_FEATURE_AVX2) && + chacha20_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) && + boot_cpu_has(X86_FEATURE_AVX2) && cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL); #endif return crypto_register_alg(&alg); diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c index ea21d2e440f7..e32142bc071d 100644 --- a/arch/x86/crypto/poly1305_glue.c +++ b/arch/x86/crypto/poly1305_glue.c @@ -183,7 +183,8 @@ static int __init poly1305_simd_mod_init(void) return -ENODEV; #ifdef CONFIG_AS_AVX2 - poly1305_use_avx2 = cpu_has_avx && boot_cpu_has(X86_FEATURE_AVX2) && + poly1305_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) && + boot_cpu_has(X86_FEATURE_AVX2) && cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL); alg.descsize = sizeof(struct poly1305_simd_desc_ctx); if (poly1305_use_avx2) diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c index dd14616b7739..1024e378a358 100644 --- a/arch/x86/crypto/sha1_ssse3_glue.c +++ b/arch/x86/crypto/sha1_ssse3_glue.c @@ -166,7 +166,7 @@ static struct shash_alg sha1_avx_alg = { static bool avx_usable(void) { if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) { - if (cpu_has_avx) + if (boot_cpu_has(X86_FEATURE_AVX)) pr_info("AVX detected but unusable.\n"); return false; } diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c index 5f4d6086dc59..3ae0f43ebd37 100644 --- a/arch/x86/crypto/sha256_ssse3_glue.c +++ b/arch/x86/crypto/sha256_ssse3_glue.c @@ -201,7 +201,7 @@ static struct shash_alg sha256_avx_algs[] = { { static bool avx_usable(void) { if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) { - if (cpu_has_avx) + if (boot_cpu_has(X86_FEATURE_AVX)) pr_info("AVX detected but unusable.\n"); return false; } diff --git a/arch/x86/crypto/sha512_ssse3_glue.c b/arch/x86/crypto/sha512_ssse3_glue.c index 34e5083d6f36..0b17c83d027d 100644 --- a/arch/x86/crypto/sha512_ssse3_glue.c +++ b/arch/x86/crypto/sha512_ssse3_glue.c @@ -151,7 +151,7 @@ asmlinkage void sha512_transform_avx(u64 *digest, const char *data, static bool avx_usable(void) { if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) { - if (cpu_has_avx) + if (boot_cpu_has(X86_FEATURE_AVX)) pr_info("AVX detected but unusable.\n"); return false; } diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index a6627b30bf45..3b232a120a5d 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -123,7 +123,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) -#define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) /* diff --git a/arch/x86/include/asm/xor_avx.h b/arch/x86/include/asm/xor_avx.h index e45e556140af..22a7b1870a31 100644 --- a/arch/x86/include/asm/xor_avx.h +++ b/arch/x86/include/asm/xor_avx.h @@ -167,12 +167,12 @@ static struct xor_block_template xor_block_avx = { #define AVX_XOR_SPEED \ do { \ - if (cpu_has_avx && boot_cpu_has(X86_FEATURE_OSXSAVE)) \ + if (boot_cpu_has(X86_FEATURE_AVX) && boot_cpu_has(X86_FEATURE_OSXSAVE)) \ xor_speed(&xor_block_avx); \ } while (0) #define AVX_SELECT(FASTEST) \ - (cpu_has_avx && boot_cpu_has(X86_FEATURE_OSXSAVE) ? &xor_block_avx : FASTEST) + (boot_cpu_has(X86_FEATURE_AVX) && boot_cpu_has(X86_FEATURE_OSXSAVE) ? &xor_block_avx : FASTEST) #else -- GitLab From dda9edf7c1fdc0d7a7ed7f46299a26282190fb6d Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:24:57 +0200 Subject: [PATCH 2410/9938] x86/cpufeature: Replace cpu_has_xmm with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459801503-15600-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/include/asm/xor_32.h | 2 +- arch/x86/kernel/fpu/core.c | 2 +- arch/x86/kernel/fpu/init.c | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3b232a120a5d..6463258b4619 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -122,7 +122,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) -#define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) /* diff --git a/arch/x86/include/asm/xor_32.h b/arch/x86/include/asm/xor_32.h index c54beb44c4c1..635eac543922 100644 --- a/arch/x86/include/asm/xor_32.h +++ b/arch/x86/include/asm/xor_32.h @@ -550,7 +550,7 @@ static struct xor_block_template xor_block_pIII_sse = { #define XOR_TRY_TEMPLATES \ do { \ AVX_XOR_SPEED; \ - if (cpu_has_xmm) { \ + if (boot_cpu_has(X86_FEATURE_XMM)) { \ xor_speed(&xor_block_pIII_sse); \ xor_speed(&xor_block_sse_pf64); \ } else if (boot_cpu_has(X86_FEATURE_MMX)) { \ diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 8e37cc8a539a..b05aa68f88c0 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -526,7 +526,7 @@ static inline unsigned short get_fpu_swd(struct fpu *fpu) static inline unsigned short get_fpu_mxcsr(struct fpu *fpu) { - if (cpu_has_xmm) { + if (boot_cpu_has(X86_FEATURE_XMM)) { return fpu->state.fxsave.mxcsr; } else { return MXCSR_DEFAULT; diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 54c86fffbf9f..9bbb332a71ff 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -31,7 +31,7 @@ static void fpu__init_cpu_generic(void) if (cpu_has_fxsr) cr4_mask |= X86_CR4_OSFXSR; - if (cpu_has_xmm) + if (boot_cpu_has(X86_FEATURE_XMM)) cr4_mask |= X86_CR4_OSXMMEXCPT; if (cr4_mask) cr4_set_bits(cr4_mask); -- GitLab From a402a8dffc9f838b413c5ee0317d2d3184968f5b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:24:58 +0200 Subject: [PATCH 2411/9938] x86/cpufeature: Replace cpu_has_fpu with boot_cpu_has() usage Use static_cpu_has() in the timing-sensitive paths in fpstate_init() and fpu__copy(). While at it, simplify the use in init_cyrix() and get rid of the ternary operator. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459801503-15600-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kernel/cpu/cyrix.c | 2 +- arch/x86/kernel/fpu/bugs.c | 2 +- arch/x86/kernel/fpu/core.c | 4 ++-- arch/x86/kernel/fpu/init.c | 8 ++++---- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 6463258b4619..b23d5570a5f4 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -118,7 +118,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; set_bit(bit, (unsigned long *)cpu_caps_set); \ } while (0) -#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU) #define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 6adef9cac23e..bd9dcd6b712d 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -333,7 +333,7 @@ static void init_cyrix(struct cpuinfo_x86 *c) switch (dir0_lsn) { case 0xd: /* either a 486SLC or DLC w/o DEVID */ dir0_msn = 0; - p = Cx486_name[(cpu_has_fpu ? 1 : 0)]; + p = Cx486_name[!!boot_cpu_has(X86_FEATURE_FPU)]; break; case 0xe: /* a 486S A step */ diff --git a/arch/x86/kernel/fpu/bugs.c b/arch/x86/kernel/fpu/bugs.c index dd9ca9b60ff3..224b5ec52195 100644 --- a/arch/x86/kernel/fpu/bugs.c +++ b/arch/x86/kernel/fpu/bugs.c @@ -66,6 +66,6 @@ void __init fpu__init_check_bugs(void) * kernel_fpu_begin/end() in check_fpu() relies on the patched * alternative instructions. */ - if (cpu_has_fpu) + if (boot_cpu_has(X86_FEATURE_FPU)) check_fpu(); } diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index b05aa68f88c0..0e7859f9aedc 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -217,7 +217,7 @@ static inline void fpstate_init_fstate(struct fregs_state *fp) void fpstate_init(union fpregs_state *state) { - if (!cpu_has_fpu) { + if (!static_cpu_has(X86_FEATURE_FPU)) { fpstate_init_soft(&state->soft); return; } @@ -237,7 +237,7 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu) dst_fpu->fpregs_active = 0; dst_fpu->last_cpu = -1; - if (!src_fpu->fpstate_active || !cpu_has_fpu) + if (!src_fpu->fpstate_active || !static_cpu_has(X86_FEATURE_FPU)) return 0; WARN_ON_FPU(src_fpu != ¤t->thread.fpu); diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 9bbb332a71ff..3a84275f012e 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -38,13 +38,13 @@ static void fpu__init_cpu_generic(void) cr0 = read_cr0(); cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */ - if (!cpu_has_fpu) + if (!boot_cpu_has(X86_FEATURE_FPU)) cr0 |= X86_CR0_EM; write_cr0(cr0); /* Flush out any pending x87 state: */ #ifdef CONFIG_MATH_EMULATION - if (!cpu_has_fpu) + if (!boot_cpu_has(X86_FEATURE_FPU)) fpstate_init_soft(¤t->thread.fpu.state.soft); else #endif @@ -89,7 +89,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c) } #ifndef CONFIG_MATH_EMULATION - if (!cpu_has_fpu) { + if (!boot_cpu_has(X86_FEATURE_FPU)) { pr_emerg("x86/fpu: Giving up, no FPU found and no math emulation present\n"); for (;;) asm volatile("hlt"); @@ -212,7 +212,7 @@ static void __init fpu__init_system_xstate_size_legacy(void) * fpu__init_system_xstate(). */ - if (!cpu_has_fpu) { + if (!boot_cpu_has(X86_FEATURE_FPU)) { /* * Disable xsave as we do not support it if i387 * emulation is enabled. -- GitLab From 59e21e3d00e6bc23186763c3e0bf11baf8924124 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:24:59 +0200 Subject: [PATCH 2412/9938] x86/cpufeature: Replace cpu_has_tsc with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Torokhov Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Thomas Sailer Link: http://lkml.kernel.org/r/1459801503-15600-7-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/include/asm/tsc.h | 2 +- arch/x86/kernel/apic/apic.c | 10 +++++----- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/tsc.c | 12 ++++++------ drivers/input/joystick/analog.c | 6 +++--- drivers/net/hamradio/baycom_epp.c | 8 ++++---- 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index b23d5570a5f4..8f58cd215f6d 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -118,7 +118,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; set_bit(bit, (unsigned long *)cpu_caps_set); \ } while (0) -#define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index 174c4212780a..7428697c5b8d 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -22,7 +22,7 @@ extern void disable_TSC(void); static inline cycles_t get_cycles(void) { #ifndef CONFIG_X86_TSC - if (!cpu_has_tsc) + if (!boot_cpu_has(X86_FEATURE_TSC)) return 0; #endif diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index d7867c885bf8..0b6509f1a4fe 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -607,7 +607,7 @@ static void __init lapic_cal_handler(struct clock_event_device *dev) long tapic = apic_read(APIC_TMCCT); unsigned long pm = acpi_pm_read_early(); - if (cpu_has_tsc) + if (boot_cpu_has(X86_FEATURE_TSC)) tsc = rdtsc(); switch (lapic_cal_loops++) { @@ -668,7 +668,7 @@ calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) *delta = (long)res; /* Correct the tsc counter value */ - if (cpu_has_tsc) { + if (boot_cpu_has(X86_FEATURE_TSC)) { res = (((u64)(*deltatsc)) * pm_100ms); do_div(res, deltapm); apic_printk(APIC_VERBOSE, "TSC delta adjusted to " @@ -760,7 +760,7 @@ static int __init calibrate_APIC_clock(void) apic_printk(APIC_VERBOSE, "..... calibration result: %u\n", lapic_timer_frequency); - if (cpu_has_tsc) { + if (boot_cpu_has(X86_FEATURE_TSC)) { apic_printk(APIC_VERBOSE, "..... CPU clock speed is " "%ld.%04ld MHz.\n", (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ), @@ -1227,7 +1227,7 @@ void setup_local_APIC(void) unsigned long long tsc = 0, ntsc; long long max_loops = cpu_khz ? cpu_khz : 1000000; - if (cpu_has_tsc) + if (boot_cpu_has(X86_FEATURE_TSC)) tsc = rdtsc(); if (disable_apic) { @@ -1311,7 +1311,7 @@ void setup_local_APIC(void) break; } if (queued) { - if (cpu_has_tsc && cpu_khz) { + if (boot_cpu_has(X86_FEATURE_TSC) && cpu_khz) { ntsc = rdtsc(); max_loops = (cpu_khz << 10) - (ntsc - tsc); } else diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 28d3255edf00..6bfa36de6d9f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1558,7 +1558,7 @@ void cpu_init(void) pr_info("Initializing CPU#%d\n", cpu); if (cpu_feature_enabled(X86_FEATURE_VME) || - cpu_has_tsc || + boot_cpu_has(X86_FEATURE_TSC) || boot_cpu_has(X86_FEATURE_DE)) cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index c9c4c7ce3eb2..a0346bc51833 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -36,7 +36,7 @@ static int __read_mostly tsc_unstable; /* native_sched_clock() is called before tsc_init(), so we must start with the TSC soft disabled to prevent - erroneous rdtsc usage on !cpu_has_tsc processors */ + erroneous rdtsc usage on !boot_cpu_has(X86_FEATURE_TSC) processors */ static int __read_mostly tsc_disabled = -1; static DEFINE_STATIC_KEY_FALSE(__use_tsc); @@ -834,7 +834,7 @@ int recalibrate_cpu_khz(void) #ifndef CONFIG_SMP unsigned long cpu_khz_old = cpu_khz; - if (cpu_has_tsc) { + if (boot_cpu_has(X86_FEATURE_TSC)) { tsc_khz = x86_platform.calibrate_tsc(); cpu_khz = tsc_khz; cpu_data(0).loops_per_jiffy = @@ -956,7 +956,7 @@ static struct notifier_block time_cpufreq_notifier_block = { static int __init cpufreq_tsc(void) { - if (!cpu_has_tsc) + if (!boot_cpu_has(X86_FEATURE_TSC)) return 0; if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) return 0; @@ -1081,7 +1081,7 @@ static void __init check_system_tsc_reliable(void) */ int unsynchronized_tsc(void) { - if (!cpu_has_tsc || tsc_unstable) + if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_unstable) return 1; #ifdef CONFIG_SMP @@ -1205,7 +1205,7 @@ static void tsc_refine_calibration_work(struct work_struct *work) static int __init init_tsc_clocksource(void) { - if (!cpu_has_tsc || tsc_disabled > 0 || !tsc_khz) + if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz) return 0; if (tsc_clocksource_reliable) @@ -1242,7 +1242,7 @@ void __init tsc_init(void) u64 lpj; int cpu; - if (!cpu_has_tsc) { + if (!boot_cpu_has(X86_FEATURE_TSC)) { setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); return; } diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 6f8b084e13d0..3d8ff09eba57 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -143,9 +143,9 @@ struct analog_port { #include -#define GET_TIME(x) do { if (cpu_has_tsc) x = (unsigned int)rdtsc(); else x = get_time_pit(); } while (0) -#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0))) -#define TIME_NAME (cpu_has_tsc?"TSC":"PIT") +#define GET_TIME(x) do { if (boot_cpu_has(X86_FEATURE_TSC)) x = (unsigned int)rdtsc(); else x = get_time_pit(); } while (0) +#define DELTA(x,y) (boot_cpu_has(X86_FEATURE_TSC) ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0))) +#define TIME_NAME (boot_cpu_has(X86_FEATURE_TSC)?"TSC":"PIT") static unsigned int get_time_pit(void) { unsigned long flags; diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 72c9f1f352b4..7c7830722ea2 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -635,10 +635,10 @@ static int receive(struct net_device *dev, int cnt) #ifdef __i386__ #include -#define GETTICK(x) \ -({ \ - if (cpu_has_tsc) \ - x = (unsigned int)rdtsc(); \ +#define GETTICK(x) \ +({ \ + if (boot_cpu_has(X86_FEATURE_TSC)) \ + x = (unsigned int)rdtsc(); \ }) #else /* __i386__ */ #define GETTICK(x) -- GitLab From 93984fbd4e33cc861d5b49caed02a02cbfb01340 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:25:00 +0200 Subject: [PATCH 2413/9938] x86/cpufeature: Replace cpu_has_apic with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: iommu@lists.linux-foundation.org Cc: linux-pm@vger.kernel.org Cc: oprofile-list@lists.sf.net Link: http://lkml.kernel.org/r/1459801503-15600-8-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/events/core.c | 2 +- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/include/asm/irq_work.h | 2 +- arch/x86/kernel/acpi/boot.c | 8 ++++---- arch/x86/kernel/apic/apic.c | 20 ++++++++++---------- arch/x86/kernel/apic/apic_noop.c | 4 ++-- arch/x86/kernel/apic/io_apic.c | 2 +- arch/x86/kernel/apic/ipi.c | 2 +- arch/x86/kernel/apic/vector.c | 2 +- arch/x86/kernel/cpu/amd.c | 4 ++-- arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/cpu/mcheck/mce_intel.c | 2 +- arch/x86/kernel/cpu/mcheck/therm_throt.c | 2 +- arch/x86/kernel/devicetree.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/oprofile/nmi_int.c | 2 +- arch/x86/pci/xen.c | 2 +- drivers/cpufreq/longhaul.c | 2 +- drivers/iommu/irq_remapping.c | 2 +- 19 files changed, 32 insertions(+), 33 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 041e442a3e28..54c17455600e 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1518,7 +1518,7 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) static void __init pmu_check_apic(void) { - if (cpu_has_apic) + if (boot_cpu_has(X86_FEATURE_APIC)) return; x86_pmu.apic = 0; diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 8f58cd215f6d..c532961c7439 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -118,7 +118,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; set_bit(bit, (unsigned long *)cpu_caps_set); \ } while (0) -#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) diff --git a/arch/x86/include/asm/irq_work.h b/arch/x86/include/asm/irq_work.h index d0afb05c84fc..f70604125286 100644 --- a/arch/x86/include/asm/irq_work.h +++ b/arch/x86/include/asm/irq_work.h @@ -5,7 +5,7 @@ static inline bool arch_irq_work_has_interrupt(void) { - return cpu_has_apic; + return boot_cpu_has(X86_FEATURE_APIC); } #endif /* _ASM_IRQ_WORK_H */ diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8c2f1ef6ca23..2522e564269e 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -136,7 +136,7 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) { struct acpi_table_madt *madt = NULL; - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return -EINVAL; madt = (struct acpi_table_madt *)table; @@ -951,7 +951,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void) { int count; - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return -ENODEV; /* @@ -979,7 +979,7 @@ static int __init acpi_parse_madt_lapic_entries(void) int ret; struct acpi_subtable_proc madt_proc[2]; - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return -ENODEV; /* @@ -1125,7 +1125,7 @@ static int __init acpi_parse_madt_ioapic_entries(void) if (acpi_disabled || acpi_noirq) return -ENODEV; - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return -ENODEV; /* diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 0b6509f1a4fe..60078a67d7e3 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1085,7 +1085,7 @@ void lapic_shutdown(void) { unsigned long flags; - if (!cpu_has_apic && !apic_from_smp_config()) + if (!boot_cpu_has(X86_FEATURE_APIC) && !apic_from_smp_config()) return; local_irq_save(flags); @@ -1134,7 +1134,7 @@ void __init init_bsp_APIC(void) * Don't do the setup now if we have a SMP BIOS as the * through-I/O-APIC virtual wire mode might be active. */ - if (smp_found_config || !cpu_has_apic) + if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC)) return; /* @@ -1445,7 +1445,7 @@ static void __x2apic_disable(void) { u64 msr; - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return; rdmsrl(MSR_IA32_APICBASE, msr); @@ -1632,7 +1632,7 @@ void __init enable_IR_x2apic(void) */ static int __init detect_init_APIC(void) { - if (!cpu_has_apic) { + if (!boot_cpu_has(X86_FEATURE_APIC)) { pr_info("No local APIC present\n"); return -1; } @@ -1711,14 +1711,14 @@ static int __init detect_init_APIC(void) goto no_apic; case X86_VENDOR_INTEL: if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 || - (boot_cpu_data.x86 == 5 && cpu_has_apic)) + (boot_cpu_data.x86 == 5 && boot_cpu_has(X86_FEATURE_APIC))) break; goto no_apic; default: goto no_apic; } - if (!cpu_has_apic) { + if (!boot_cpu_has(X86_FEATURE_APIC)) { /* * Over-ride BIOS and try to enable the local APIC only if * "lapic" specified. @@ -2233,19 +2233,19 @@ int __init APIC_init_uniprocessor(void) return -1; } #ifdef CONFIG_X86_64 - if (!cpu_has_apic) { + if (!boot_cpu_has(X86_FEATURE_APIC)) { disable_apic = 1; pr_info("Apic disabled by BIOS\n"); return -1; } #else - if (!smp_found_config && !cpu_has_apic) + if (!smp_found_config && !boot_cpu_has(X86_FEATURE_APIC)) return -1; /* * Complain if the BIOS pretends there is one. */ - if (!cpu_has_apic && + if (!boot_cpu_has(X86_FEATURE_APIC) && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { pr_err("BIOS bug, local APIC 0x%x not detected!...\n", boot_cpu_physical_apicid); @@ -2426,7 +2426,7 @@ static void apic_pm_activate(void) static int __init init_lapic_sysfs(void) { /* XXX: remove suspend/resume procs if !apic_pm_state.active? */ - if (cpu_has_apic) + if (boot_cpu_has(X86_FEATURE_APIC)) register_syscore_ops(&lapic_syscore_ops); return 0; diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 331a7a07c48f..13d19ed58514 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -100,13 +100,13 @@ static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask, static u32 noop_apic_read(u32 reg) { - WARN_ON_ONCE((cpu_has_apic && !disable_apic)); + WARN_ON_ONCE(boot_cpu_has(X86_FEATURE_APIC) && !disable_apic); return 0; } static void noop_apic_write(u32 reg, u32 v) { - WARN_ON_ONCE(cpu_has_apic && !disable_apic); + WARN_ON_ONCE(boot_cpu_has(X86_FEATURE_APIC) && !disable_apic); } struct apic apic_noop = { diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index fdb0fbfb1197..84e33ff5a6d5 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1454,7 +1454,7 @@ void native_disable_io_apic(void) ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry); } - if (cpu_has_apic || apic_from_smp_config()) + if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config()) disconnect_bsp_APIC(ioapic_i8259.pin != -1); } diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 28bde88b0085..2a0f225afebd 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -230,7 +230,7 @@ int safe_smp_processor_id(void) { int apicid, cpuid; - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return 0; apicid = hard_smp_processor_id(); diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index ad59d70bcb1a..26d3ccc63e40 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -943,7 +943,7 @@ static int __init print_ICs(void) print_PIC(); /* don't print out if apic is not there */ - if (!cpu_has_apic && !apic_from_smp_config()) + if (!boot_cpu_has(X86_FEATURE_APIC) && !apic_from_smp_config()) return 0; print_local_APICs(show_lapic); diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 19d7dcfc8b3e..54f7b44dcf01 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -565,9 +565,9 @@ static void early_init_amd(struct cpuinfo_x86 *c) * can safely set X86_FEATURE_EXTD_APICID unconditionally for families * after 16h. */ - if (cpu_has_apic && c->x86 > 0x16) { + if (boot_cpu_has(X86_FEATURE_APIC) && c->x86 > 0x16) { set_cpu_cap(c, X86_FEATURE_EXTD_APICID); - } else if (cpu_has_apic && c->x86 >= 0xf) { + } else if (boot_cpu_has(X86_FEATURE_APIC) && c->x86 >= 0xf) { /* check CPU config space for extended APIC ID */ unsigned int val; val = read_pci_config(0, 24, 0, 0x68); diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index f71a34944b56..1d5582259b20 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -281,7 +281,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c) * integrated APIC (see 11AP erratum in "Pentium Processor * Specification Update"). */ - if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 && + if (boot_cpu_has(X86_FEATURE_APIC) && (c->x86<<8 | c->x86_model<<4) == 0x520 && (c->x86_mask < 0x6 || c->x86_mask == 0xb)) set_cpu_bug(c, X86_BUG_11AP); diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 1e8bb6c94f14..1defb8ea882c 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -84,7 +84,7 @@ static int cmci_supported(int *banks) */ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) return 0; - if (!cpu_has_apic || lapic_get_maxlvt() < 6) + if (!boot_cpu_has(X86_FEATURE_APIC) || lapic_get_maxlvt() < 6) return 0; rdmsrl(MSR_IA32_MCG_CAP, cap); *banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff); diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 0b445c2ff735..615793321c49 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -447,7 +447,7 @@ asmlinkage __visible void smp_trace_thermal_interrupt(struct pt_regs *regs) /* Thermal monitoring depends on APIC, ACPI and clock modulation */ static int intel_thermal_supported(struct cpuinfo_x86 *c) { - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return 0; if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC)) return 0; diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 1f4acd68b98b..3fe45f84ced4 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -151,7 +151,7 @@ static void __init dtb_lapic_setup(void) return; /* Did the boot loader setup the local APIC ? */ - if (!cpu_has_apic) { + if (!boot_cpu_has(X86_FEATURE_APIC)) { if (apic_force_enable(r.start)) return; } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index a2065d3b3b39..1fe4130b14d9 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1231,7 +1231,7 @@ static int __init smp_sanity_check(unsigned max_cpus) * If we couldn't find a local APIC, then get out of here now! */ if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && - !cpu_has_apic) { + !boot_cpu_has(X86_FEATURE_APIC)) { if (!disable_apic) { pr_err("BIOS bug, local APIC #%d not detected!...\n", boot_cpu_physical_apicid); diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 25171e9595f7..28c04123b6dd 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -700,7 +700,7 @@ int __init op_nmi_init(struct oprofile_operations *ops) char *cpu_type = NULL; int ret = 0; - if (!cpu_has_apic) + if (!boot_cpu_has(X86_FEATURE_APIC)) return -ENODEV; if (force_cpu_type == timer) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index beac4dfdade6..4bd08b0fc8ea 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -445,7 +445,7 @@ void __init xen_msi_init(void) uint32_t eax = cpuid_eax(xen_cpuid_base() + 4); if (((eax & XEN_HVM_CPUID_X2APIC_VIRT) && x2apic_mode) || - ((eax & XEN_HVM_CPUID_APIC_ACCESS_VIRT) && cpu_has_apic)) + ((eax & XEN_HVM_CPUID_APIC_ACCESS_VIRT) && boot_cpu_has(X86_FEATURE_APIC))) return; } diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 0f6b229afcb9..247bfa8eaddb 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -945,7 +945,7 @@ static int __init longhaul_init(void) } #endif #ifdef CONFIG_X86_IO_APIC - if (cpu_has_apic) { + if (boot_cpu_has(X86_FEATURE_APIC)) { printk(KERN_ERR PFX "APIC detected. Longhaul is currently " "broken in this configuration.\n"); return -ENODEV; diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 8adaaeae3268..49721b4e1975 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -36,7 +36,7 @@ static void irq_remapping_disable_io_apic(void) * As this gets called during crash dump, keep this simple for * now. */ - if (cpu_has_apic || apic_from_smp_config()) + if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config()) disconnect_bsp_APIC(0); } -- GitLab From 01f8fd7379149fb9a4046e76617958bf771f856f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:25:01 +0200 Subject: [PATCH 2414/9938] x86/cpufeature: Replace cpu_has_fxsr with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459801503-15600-9-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kernel/fpu/core.c | 6 +++--- arch/x86/kernel/fpu/init.c | 6 +++--- arch/x86/kernel/fpu/regset.c | 13 ++++++++----- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index c532961c7439..526381a14546 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -118,7 +118,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; set_bit(bit, (unsigned long *)cpu_caps_set); \ } while (0) -#define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) /* diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 0e7859f9aedc..1551b28398a4 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -224,7 +224,7 @@ void fpstate_init(union fpregs_state *state) memset(state, 0, xstate_size); - if (cpu_has_fxsr) + if (static_cpu_has(X86_FEATURE_FXSR)) fpstate_init_fxstate(&state->fxsave); else fpstate_init_fstate(&state->fsave); @@ -508,7 +508,7 @@ void fpu__clear(struct fpu *fpu) static inline unsigned short get_fpu_cwd(struct fpu *fpu) { - if (cpu_has_fxsr) { + if (boot_cpu_has(X86_FEATURE_FXSR)) { return fpu->state.fxsave.cwd; } else { return (unsigned short)fpu->state.fsave.cwd; @@ -517,7 +517,7 @@ static inline unsigned short get_fpu_cwd(struct fpu *fpu) static inline unsigned short get_fpu_swd(struct fpu *fpu) { - if (cpu_has_fxsr) { + if (boot_cpu_has(X86_FEATURE_FXSR)) { return fpu->state.fxsave.swd; } else { return (unsigned short)fpu->state.fsave.swd; diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 3a84275f012e..aacfd7a82cec 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -29,7 +29,7 @@ static void fpu__init_cpu_generic(void) unsigned long cr0; unsigned long cr4_mask = 0; - if (cpu_has_fxsr) + if (boot_cpu_has(X86_FEATURE_FXSR)) cr4_mask |= X86_CR4_OSFXSR; if (boot_cpu_has(X86_FEATURE_XMM)) cr4_mask |= X86_CR4_OSXMMEXCPT; @@ -106,7 +106,7 @@ static void __init fpu__init_system_mxcsr(void) { unsigned int mask = 0; - if (cpu_has_fxsr) { + if (boot_cpu_has(X86_FEATURE_FXSR)) { /* Static because GCC does not get 16-byte stack alignment right: */ static struct fxregs_state fxregs __initdata; @@ -221,7 +221,7 @@ static void __init fpu__init_system_xstate_size_legacy(void) setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); xstate_size = sizeof(struct swregs_state); } else { - if (cpu_has_fxsr) + if (boot_cpu_has(X86_FEATURE_FXSR)) xstate_size = sizeof(struct fxregs_state); else xstate_size = sizeof(struct fregs_state); diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c index 8bd1c003942a..4cff7af735c5 100644 --- a/arch/x86/kernel/fpu/regset.c +++ b/arch/x86/kernel/fpu/regset.c @@ -21,7 +21,10 @@ int regset_xregset_fpregs_active(struct task_struct *target, const struct user_r { struct fpu *target_fpu = &target->thread.fpu; - return (cpu_has_fxsr && target_fpu->fpstate_active) ? regset->n : 0; + if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->fpstate_active) + return regset->n; + else + return 0; } int xfpregs_get(struct task_struct *target, const struct user_regset *regset, @@ -30,7 +33,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset, { struct fpu *fpu = &target->thread.fpu; - if (!cpu_has_fxsr) + if (!boot_cpu_has(X86_FEATURE_FXSR)) return -ENODEV; fpu__activate_fpstate_read(fpu); @@ -47,7 +50,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, struct fpu *fpu = &target->thread.fpu; int ret; - if (!cpu_has_fxsr) + if (!boot_cpu_has(X86_FEATURE_FXSR)) return -ENODEV; fpu__activate_fpstate_write(fpu); @@ -278,7 +281,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset, if (!static_cpu_has(X86_FEATURE_FPU)) return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf); - if (!cpu_has_fxsr) + if (!boot_cpu_has(X86_FEATURE_FXSR)) return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &fpu->state.fsave, 0, -1); @@ -309,7 +312,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, if (!static_cpu_has(X86_FEATURE_FPU)) return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf); - if (!cpu_has_fxsr) + if (!boot_cpu_has(X86_FEATURE_FXSR)) return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fpu->state.fsave, 0, -1); -- GitLab From d366bf7eb99d0644e47ecd52c184d7ad95df02f2 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:25:02 +0200 Subject: [PATCH 2415/9938] x86/cpufeature: Replace cpu_has_xsave with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: kvm@vger.kernel.org Link: http://lkml.kernel.org/r/1459801503-15600-10-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 2 +- arch/x86/include/asm/cpufeature.h | 1 - arch/x86/kernel/fpu/regset.c | 8 ++++---- arch/x86/kernel/fpu/xstate.c | 8 ++++---- arch/x86/kernel/signal.c | 4 ++-- arch/x86/kvm/cpuid.c | 2 +- arch/x86/kvm/x86.c | 12 ++++++------ 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 0552884da18d..2f29f4e407c3 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -357,7 +357,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); /* Create the ucontext. */ - if (cpu_has_xsave) + if (boot_cpu_has(X86_FEATURE_XSAVE)) put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); else put_user_ex(0, &frame->uc.uc_flags); diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 526381a14546..732a00f12ac0 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -118,7 +118,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; set_bit(bit, (unsigned long *)cpu_caps_set); \ } while (0) -#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) /* * Do not add any more of those clumsy macros - use static_cpu_has() for diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c index 4cff7af735c5..bc5e76c1d7c5 100644 --- a/arch/x86/kernel/fpu/regset.c +++ b/arch/x86/kernel/fpu/regset.c @@ -68,7 +68,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, * update the header bits in the xsave header, indicating the * presence of FP and SSE state. */ - if (cpu_has_xsave) + if (boot_cpu_has(X86_FEATURE_XSAVE)) fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FPSSE; return ret; @@ -82,7 +82,7 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset, struct xregs_state *xsave; int ret; - if (!cpu_has_xsave) + if (!boot_cpu_has(X86_FEATURE_XSAVE)) return -ENODEV; fpu__activate_fpstate_read(fpu); @@ -111,7 +111,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, struct xregs_state *xsave; int ret; - if (!cpu_has_xsave) + if (!boot_cpu_has(X86_FEATURE_XSAVE)) return -ENODEV; fpu__activate_fpstate_write(fpu); @@ -328,7 +328,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, * update the header bit in the xsave header, indicating the * presence of FP. */ - if (cpu_has_xsave) + if (boot_cpu_has(X86_FEATURE_XSAVE)) fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FP; return ret; } diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index b48ef35b28d4..18b9fd809fe7 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -190,7 +190,7 @@ void fpstate_sanitize_xstate(struct fpu *fpu) */ void fpu__init_cpu_xstate(void) { - if (!cpu_has_xsave || !xfeatures_mask) + if (!boot_cpu_has(X86_FEATURE_XSAVE) || !xfeatures_mask) return; cr4_set_bits(X86_CR4_OSXSAVE); @@ -316,7 +316,7 @@ static void __init setup_init_fpu_buf(void) WARN_ON_FPU(!on_boot_cpu); on_boot_cpu = 0; - if (!cpu_has_xsave) + if (!boot_cpu_has(X86_FEATURE_XSAVE)) return; setup_xstate_features(); @@ -630,7 +630,7 @@ void __init fpu__init_system_xstate(void) WARN_ON_FPU(!on_boot_cpu); on_boot_cpu = 0; - if (!cpu_has_xsave) { + if (!boot_cpu_has(X86_FEATURE_XSAVE)) { pr_info("x86/fpu: Legacy x87 FPU detected.\n"); return; } @@ -678,7 +678,7 @@ void fpu__resume_cpu(void) /* * Restore XCR0 on xsave capable CPUs: */ - if (cpu_has_xsave) + if (boot_cpu_has(X86_FEATURE_XSAVE)) xsetbv(XCR_XFEATURE_ENABLED_MASK, xfeatures_mask); } diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 548ddf7d6fd2..6408c09bbcd4 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -391,7 +391,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, put_user_ex(&frame->uc, &frame->puc); /* Create the ucontext. */ - if (cpu_has_xsave) + if (boot_cpu_has(X86_FEATURE_XSAVE)) put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); else put_user_ex(0, &frame->uc.uc_flags); @@ -442,7 +442,7 @@ static unsigned long frame_uc_flags(struct pt_regs *regs) { unsigned long flags; - if (cpu_has_xsave) + if (boot_cpu_has(X86_FEATURE_XSAVE)) flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS; else flags = UC_SIGCONTEXT_SS; diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 8efb839948e5..a056b72c2f33 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -75,7 +75,7 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) return 0; /* Update OSXSAVE bit */ - if (cpu_has_xsave && best->function == 0x1) { + if (boot_cpu_has(X86_FEATURE_XSAVE) && best->function == 0x1) { best->ecx &= ~F(OSXSAVE); if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE)) best->ecx |= F(OSXSAVE); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 742d0f7d3556..4eb2fca335c9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2612,7 +2612,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = KVM_MAX_MCE_BANKS; break; case KVM_CAP_XCRS: - r = cpu_has_xsave; + r = boot_cpu_has(X86_FEATURE_XSAVE); break; case KVM_CAP_TSC_CONTROL: r = kvm_has_tsc_control; @@ -3122,7 +3122,7 @@ static void load_xsave(struct kvm_vcpu *vcpu, u8 *src) static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu, struct kvm_xsave *guest_xsave) { - if (cpu_has_xsave) { + if (boot_cpu_has(X86_FEATURE_XSAVE)) { memset(guest_xsave, 0, sizeof(struct kvm_xsave)); fill_xsave((u8 *) guest_xsave->region, vcpu); } else { @@ -3140,7 +3140,7 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, u64 xstate_bv = *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)]; - if (cpu_has_xsave) { + if (boot_cpu_has(X86_FEATURE_XSAVE)) { /* * Here we allow setting states that are not present in * CPUID leaf 0xD, index 0, EDX:EAX. This is for compatibility @@ -3161,7 +3161,7 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, static void kvm_vcpu_ioctl_x86_get_xcrs(struct kvm_vcpu *vcpu, struct kvm_xcrs *guest_xcrs) { - if (!cpu_has_xsave) { + if (!boot_cpu_has(X86_FEATURE_XSAVE)) { guest_xcrs->nr_xcrs = 0; return; } @@ -3177,7 +3177,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu, { int i, r = 0; - if (!cpu_has_xsave) + if (!boot_cpu_has(X86_FEATURE_XSAVE)) return -EINVAL; if (guest_xcrs->nr_xcrs > KVM_MAX_XCRS || guest_xcrs->flags) @@ -5866,7 +5866,7 @@ int kvm_arch_init(void *opaque) perf_register_guest_info_callbacks(&kvm_guest_cbs); - if (cpu_has_xsave) + if (boot_cpu_has(X86_FEATURE_XSAVE)) host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); kvm_lapic_init(); -- GitLab From 782511b00f749cfebc0cb5d6ce960de5410c221d Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 4 Apr 2016 22:25:03 +0200 Subject: [PATCH 2416/9938] x86/cpufeature: Replace cpu_has_xsaves with boot_cpu_has() usage Signed-off-by: Borislav Petkov Cc: Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459801503-15600-11-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 6 ------ arch/x86/kernel/fpu/xstate.c | 10 +++++----- arch/x86/kvm/vmx.c | 2 +- arch/x86/kvm/x86.c | 4 ++-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 732a00f12ac0..07c942d84662 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -118,12 +118,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; set_bit(bit, (unsigned long *)cpu_caps_set); \ } while (0) -#define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) -/* - * Do not add any more of those clumsy macros - use static_cpu_has() for - * fast paths and boot_cpu_has() otherwise! - */ - #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_X86_FAST_FEATURE_TESTS) /* * Static testing of CPU features. Used the same as boot_cpu_has(). diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 18b9fd809fe7..4ea2a59483c7 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -280,7 +280,7 @@ static void __init setup_xstate_comp(void) xstate_comp_offsets[0] = 0; xstate_comp_offsets[1] = offsetof(struct fxregs_state, xmm_space); - if (!cpu_has_xsaves) { + if (!boot_cpu_has(X86_FEATURE_XSAVES)) { for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { if (xfeature_enabled(i)) { xstate_comp_offsets[i] = xstate_offsets[i]; @@ -322,7 +322,7 @@ static void __init setup_init_fpu_buf(void) setup_xstate_features(); print_xstate_features(); - if (cpu_has_xsaves) { + if (boot_cpu_has(X86_FEATURE_XSAVES)) { init_fpstate.xsave.header.xcomp_bv = (u64)1 << 63 | xfeatures_mask; init_fpstate.xsave.header.xfeatures = xfeatures_mask; } @@ -417,7 +417,7 @@ static int xfeature_size(int xfeature_nr) */ static int using_compacted_format(void) { - return cpu_has_xsaves; + return boot_cpu_has(X86_FEATURE_XSAVES); } static void __xstate_dump_leaves(void) @@ -549,7 +549,7 @@ static unsigned int __init calculate_xstate_size(void) unsigned int eax, ebx, ecx, edx; unsigned int calculated_xstate_size; - if (!cpu_has_xsaves) { + if (!boot_cpu_has(X86_FEATURE_XSAVES)) { /* * - CPUID function 0DH, sub-function 0: * EBX enumerates the size (in bytes) required by @@ -667,7 +667,7 @@ void __init fpu__init_system_xstate(void) pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n", xfeatures_mask, xstate_size, - cpu_has_xsaves ? "compacted" : "standard"); + boot_cpu_has(X86_FEATURE_XSAVES) ? "compacted" : "standard"); } /* diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ee1c8a93871c..d5908bde9342 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3386,7 +3386,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) } } - if (cpu_has_xsaves) + if (boot_cpu_has(X86_FEATURE_XSAVES)) rdmsrl(MSR_IA32_XSS, host_xss); return 0; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4eb2fca335c9..33102ded1398 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3095,7 +3095,7 @@ static void load_xsave(struct kvm_vcpu *vcpu, u8 *src) /* Set XSTATE_BV and possibly XCOMP_BV. */ xsave->header.xfeatures = xstate_bv; - if (cpu_has_xsaves) + if (boot_cpu_has(X86_FEATURE_XSAVES)) xsave->header.xcomp_bv = host_xcr0 | XSTATE_COMPACTION_ENABLED; /* @@ -7292,7 +7292,7 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) static void fx_init(struct kvm_vcpu *vcpu) { fpstate_init(&vcpu->arch.guest_fpu.state); - if (cpu_has_xsaves) + if (boot_cpu_has(X86_FEATURE_XSAVES)) vcpu->arch.guest_fpu.state.xsave.header.xcomp_bv = host_xcr0 | XSTATE_COMPACTION_ENABLED; -- GitLab From 78df526c74a4db696e1e058b9869471937d0773b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 5 Apr 2016 08:29:50 +0200 Subject: [PATCH 2417/9938] x86/fpu/regset: Replace static_cpu_has() usage with boot_cpu_has() fpregs_{g,s}et() are not sizzling-hot paths to justify the need for static_cpu_has(). Use the normal boot_cpu_has() helper. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459837795-2588-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/fpu/regset.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c index bc5e76c1d7c5..81422dfb152b 100644 --- a/arch/x86/kernel/fpu/regset.c +++ b/arch/x86/kernel/fpu/regset.c @@ -278,7 +278,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset, fpu__activate_fpstate_read(fpu); - if (!static_cpu_has(X86_FEATURE_FPU)) + if (!boot_cpu_has(X86_FEATURE_FPU)) return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf); if (!boot_cpu_has(X86_FEATURE_FXSR)) @@ -309,7 +309,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, fpu__activate_fpstate_write(fpu); fpstate_sanitize_xstate(fpu); - if (!static_cpu_has(X86_FEATURE_FPU)) + if (!boot_cpu_has(X86_FEATURE_FPU)) return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf); if (!boot_cpu_has(X86_FEATURE_FXSR)) -- GitLab From 425d8c2fc5e6dddbad083502bb77c7beae545620 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 5 Apr 2016 08:29:51 +0200 Subject: [PATCH 2418/9938] x86/cpu: Simplify extended APIC ID detection on AMD Both if-branches are under if (boot_cpu_has(X86_FEATURE_APIC)), unify them. Also, simplify the test for bits: - 17 ("ApicExtBrdCst: APIC extended broadcast enable") and - 18 ("ApicExtId: APIC extended ID enable.") in "D18F0x68 Link Transaction Control." No functionality change. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459837795-2588-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 54f7b44dcf01..c343a54bed39 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -565,14 +565,17 @@ static void early_init_amd(struct cpuinfo_x86 *c) * can safely set X86_FEATURE_EXTD_APICID unconditionally for families * after 16h. */ - if (boot_cpu_has(X86_FEATURE_APIC) && c->x86 > 0x16) { - set_cpu_cap(c, X86_FEATURE_EXTD_APICID); - } else if (boot_cpu_has(X86_FEATURE_APIC) && c->x86 >= 0xf) { - /* check CPU config space for extended APIC ID */ - unsigned int val; - val = read_pci_config(0, 24, 0, 0x68); - if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18))) + if (boot_cpu_has(X86_FEATURE_APIC)) { + if (c->x86 > 0x16) set_cpu_cap(c, X86_FEATURE_EXTD_APICID); + else if (c->x86 >= 0xf) { + /* check CPU config space for extended APIC ID */ + unsigned int val; + + val = read_pci_config(0, 24, 0, 0x68); + if ((val >> 17 & 0x3) == 0x3) + set_cpu_cap(c, X86_FEATURE_EXTD_APICID); + } } #endif -- GitLab From a841cca74ea7612508aee161c89987b2646ed769 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 5 Apr 2016 08:29:52 +0200 Subject: [PATCH 2419/9938] x86/tsc: Do not check X86_FEATURE_CONSTANT_TSC in notifier call ... because the notifier-registering routine already does that. Also, rename cpufreq_tsc() init call to something more telling. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459837795-2588-4-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index a0346bc51833..5bb702c77e8f 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -922,9 +922,6 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, struct cpufreq_freqs *freq = data; unsigned long *lpj; - if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC)) - return 0; - lpj = &boot_cpu_data.loops_per_jiffy; #ifdef CONFIG_SMP if (!(freq->flags & CPUFREQ_CONST_LOOPS)) @@ -954,7 +951,7 @@ static struct notifier_block time_cpufreq_notifier_block = { .notifier_call = time_cpufreq_notifier }; -static int __init cpufreq_tsc(void) +static int __init cpufreq_register_tsc_scaling(void) { if (!boot_cpu_has(X86_FEATURE_TSC)) return 0; @@ -965,7 +962,7 @@ static int __init cpufreq_tsc(void) return 0; } -core_initcall(cpufreq_tsc); +core_initcall(cpufreq_register_tsc_scaling); #endif /* CONFIG_CPU_FREQ */ -- GitLab From eff4677e9fb9b680d1d5f6ba079116548d072b7e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 5 Apr 2016 08:29:53 +0200 Subject: [PATCH 2420/9938] x86/tsc: Save an indentation level in recalibrate_cpu_khz() ... by flipping the check. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459837795-2588-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 5bb702c77e8f..38ba6de56ede 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -834,15 +834,15 @@ int recalibrate_cpu_khz(void) #ifndef CONFIG_SMP unsigned long cpu_khz_old = cpu_khz; - if (boot_cpu_has(X86_FEATURE_TSC)) { - tsc_khz = x86_platform.calibrate_tsc(); - cpu_khz = tsc_khz; - cpu_data(0).loops_per_jiffy = - cpufreq_scale(cpu_data(0).loops_per_jiffy, - cpu_khz_old, cpu_khz); - return 0; - } else + if (!boot_cpu_has(X86_FEATURE_TSC)) return -ENODEV; + + tsc_khz = x86_platform.calibrate_tsc(); + cpu_khz = tsc_khz; + cpu_data(0).loops_per_jiffy = cpufreq_scale(cpu_data(0).loops_per_jiffy, + cpu_khz_old, cpu_khz); + + return 0; #else return -ENODEV; #endif -- GitLab From de82fbc3823b7b15ee03466ebfb1c5ec7cc1a941 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 5 Apr 2016 08:29:54 +0200 Subject: [PATCH 2421/9938] x86/fpu: Remove check_fpu() indirection Rename it to fpu__init_check_bugs() and do the CPU feature check at entry, thus getting rid of the old fpu__init_check_bugs() wrapper. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459837795-2588-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/fpu/bugs.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/fpu/bugs.c b/arch/x86/kernel/fpu/bugs.c index 224b5ec52195..aad34aafc0e0 100644 --- a/arch/x86/kernel/fpu/bugs.c +++ b/arch/x86/kernel/fpu/bugs.c @@ -21,11 +21,15 @@ static double __initdata y = 3145727.0; * We should really only care about bugs here * anyway. Not features. */ -static void __init check_fpu(void) +void __init fpu__init_check_bugs(void) { u32 cr0_saved; s32 fdiv_bug; + /* kernel_fpu_begin/end() relies on patched alternative instructions. */ + if (!boot_cpu_has(X86_FEATURE_FPU)) + return; + /* We might have CR0::TS set already, clear it: */ cr0_saved = read_cr0(); write_cr0(cr0_saved & ~X86_CR0_TS); @@ -59,13 +63,3 @@ static void __init check_fpu(void) pr_warn("Hmm, FPU with FDIV bug\n"); } } - -void __init fpu__init_check_bugs(void) -{ - /* - * kernel_fpu_begin/end() in check_fpu() relies on the patched - * alternative instructions. - */ - if (boot_cpu_has(X86_FEATURE_FPU)) - check_fpu(); -} -- GitLab From 6aa6dbfced51dec6cde159c6167ad3dad6add823 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 5 Apr 2016 08:29:55 +0200 Subject: [PATCH 2422/9938] x86/fpu: Get rid of x87 math exception helpers ... and integrate their functionality into their single user fpu__exception_code(). No functionality change. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459837795-2588-7-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/fpu/core.c | 44 +++++++++++--------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 1551b28398a4..97027545a72d 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -506,33 +506,6 @@ void fpu__clear(struct fpu *fpu) * x87 math exception handling: */ -static inline unsigned short get_fpu_cwd(struct fpu *fpu) -{ - if (boot_cpu_has(X86_FEATURE_FXSR)) { - return fpu->state.fxsave.cwd; - } else { - return (unsigned short)fpu->state.fsave.cwd; - } -} - -static inline unsigned short get_fpu_swd(struct fpu *fpu) -{ - if (boot_cpu_has(X86_FEATURE_FXSR)) { - return fpu->state.fxsave.swd; - } else { - return (unsigned short)fpu->state.fsave.swd; - } -} - -static inline unsigned short get_fpu_mxcsr(struct fpu *fpu) -{ - if (boot_cpu_has(X86_FEATURE_XMM)) { - return fpu->state.fxsave.mxcsr; - } else { - return MXCSR_DEFAULT; - } -} - int fpu__exception_code(struct fpu *fpu, int trap_nr) { int err; @@ -547,10 +520,15 @@ int fpu__exception_code(struct fpu *fpu, int trap_nr) * so if this combination doesn't produce any single exception, * then we have a bad program that isn't synchronizing its FPU usage * and it will suffer the consequences since we won't be able to - * fully reproduce the context of the exception + * fully reproduce the context of the exception. */ - cwd = get_fpu_cwd(fpu); - swd = get_fpu_swd(fpu); + if (boot_cpu_has(X86_FEATURE_FXSR)) { + cwd = fpu->state.fxsave.cwd; + swd = fpu->state.fxsave.swd; + } else { + cwd = (unsigned short)fpu->state.fsave.cwd; + swd = (unsigned short)fpu->state.fsave.swd; + } err = swd & ~cwd; } else { @@ -560,7 +538,11 @@ int fpu__exception_code(struct fpu *fpu, int trap_nr) * unmasked exception was caught we must mask the exception mask bits * at 0x1f80, and then use these to mask the exception bits at 0x3f. */ - unsigned short mxcsr = get_fpu_mxcsr(fpu); + unsigned short mxcsr = MXCSR_DEFAULT; + + if (boot_cpu_has(X86_FEATURE_XMM)) + mxcsr = fpu->state.fxsave.mxcsr; + err = ~(mxcsr >> 7) & mxcsr; } -- GitLab From 7bbcdb1ca4d2fd69094ee89c18601b396531ca9f Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:32 -0700 Subject: [PATCH 2423/9938] x86/head: Pass a real pt_regs and trapnr to early_fixup_exception() early_fixup_exception() is limited by the fact that it doesn't have a real struct pt_regs. Change both the 32-bit and 64-bit asm and the C code to pass and accept a real pt_regs. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/e3fb680fcfd5e23e38237e8328b64a25cc121d37.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uaccess.h | 2 +- arch/x86/kernel/head_32.S | 74 +++++++++++++++++++++++----------- arch/x86/kernel/head_64.S | 68 +++++++++++++++++-------------- arch/x86/mm/extable.c | 6 +-- 4 files changed, 92 insertions(+), 58 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index a969ae607be8..b6fb311b7d75 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -110,7 +110,7 @@ struct exception_table_entry { extern int fixup_exception(struct pt_regs *regs, int trapnr); extern bool ex_has_fault_handler(unsigned long ip); -extern int early_fixup_exception(unsigned long *ip); +extern int early_fixup_exception(struct pt_regs *regs, int trapnr); /* * These are the main single-value transfer routines. They automatically diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 54cdbd2003fe..0904536cd45c 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -568,29 +568,64 @@ early_idt_handler_common: je hlt_loop incl %ss:early_recursion_flag - push %eax # 16(%esp) - push %ecx # 12(%esp) - push %edx # 8(%esp) - push %ds # 4(%esp) - push %es # 0(%esp) - movl $(__KERNEL_DS),%eax - movl %eax,%ds - movl %eax,%es + /* The vector number is in pt_regs->gs */ - cmpl $(__KERNEL_CS),32(%esp) + cld + pushl %fs /* pt_regs->fs */ + movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */ + pushl %es /* pt_regs->es */ + movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */ + pushl %ds /* pt_regs->ds */ + movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */ + pushl %eax /* pt_regs->ax */ + pushl %ebp /* pt_regs->bp */ + pushl %edi /* pt_regs->di */ + pushl %esi /* pt_regs->si */ + pushl %edx /* pt_regs->dx */ + pushl %ecx /* pt_regs->cx */ + pushl %ebx /* pt_regs->bx */ + + /* Fix up DS and ES */ + movl $(__KERNEL_DS), %ecx + movl %ecx, %ds + movl %ecx, %es + + /* Load the vector number into EDX */ + movl PT_GS(%esp), %edx + + /* Load GS into pt_regs->gs and clear high bits */ + movw %gs, PT_GS(%esp) + movw $0, PT_GS+2(%esp) + + cmpl $(__KERNEL_CS),PT_CS(%esp) jne 10f - leal 28(%esp),%eax # Pointer to %eip - call early_fixup_exception - andl %eax,%eax - jnz ex_entry /* found an exception entry */ + movl %esp, %eax /* args are pt_regs (EAX), trapnr (EDX) */ + call early_fixup_exception + andl %eax,%eax + jz 10f /* Exception wasn't fixed up */ + + popl %ebx /* pt_regs->bx */ + popl %ecx /* pt_regs->cx */ + popl %edx /* pt_regs->dx */ + popl %esi /* pt_regs->si */ + popl %edi /* pt_regs->di */ + popl %ebp /* pt_regs->bp */ + popl %eax /* pt_regs->ax */ + popl %ds /* pt_regs->ds */ + popl %es /* pt_regs->es */ + popl %fs /* pt_regs->fs */ + popl %gs /* pt_regs->gs */ + decl %ss:early_recursion_flag + addl $4, %esp /* pop pt_regs->orig_ax */ + iret 10: #ifdef CONFIG_PRINTK xorl %eax,%eax - movw %ax,2(%esp) /* clean up the segment values on some cpus */ - movw %ax,6(%esp) - movw %ax,34(%esp) + movw %ax,PT_FS+2(%esp) /* clean up the segment values on some cpus */ + movw %ax,PT_DS+2(%esp) + movw %ax,PT_ES+2(%esp) leal 40(%esp),%eax pushl %eax /* %esp before the exception */ pushl %ebx @@ -608,13 +643,6 @@ hlt_loop: hlt jmp hlt_loop -ex_entry: - pop %es - pop %ds - pop %edx - pop %ecx - pop %eax - decl %ss:early_recursion_flag .Lis_nmi: addl $8,%esp /* drop vector number and error code */ iret diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 22fbf9df61bb..9e8636d2cedd 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -20,6 +20,7 @@ #include #include #include +#include "../entry/calling.h" #ifdef CONFIG_PARAVIRT #include @@ -357,39 +358,52 @@ early_idt_handler_common: jz 1f incl early_recursion_flag(%rip) - pushq %rax # 64(%rsp) - pushq %rcx # 56(%rsp) - pushq %rdx # 48(%rsp) - pushq %rsi # 40(%rsp) - pushq %rdi # 32(%rsp) - pushq %r8 # 24(%rsp) - pushq %r9 # 16(%rsp) - pushq %r10 # 8(%rsp) - pushq %r11 # 0(%rsp) - - cmpl $__KERNEL_CS,96(%rsp) + /* The vector number is currently in the pt_regs->di slot. */ + pushq %rsi /* pt_regs->si */ + movq 8(%rsp), %rsi /* RSI = vector number */ + movq %rdi, 8(%rsp) /* pt_regs->di = RDI */ + pushq %rdx /* pt_regs->dx */ + pushq %rcx /* pt_regs->cx */ + pushq %rax /* pt_regs->ax */ + pushq %r8 /* pt_regs->r8 */ + pushq %r9 /* pt_regs->r9 */ + pushq %r10 /* pt_regs->r10 */ + pushq %r11 /* pt_regs->r11 */ + pushq %rbx /* pt_regs->bx */ + pushq %rbp /* pt_regs->bp */ + pushq %r12 /* pt_regs->r12 */ + pushq %r13 /* pt_regs->r13 */ + pushq %r14 /* pt_regs->r14 */ + pushq %r15 /* pt_regs->r15 */ + + cmpl $__KERNEL_CS,CS(%rsp) jne 11f - cmpl $14,72(%rsp) # Page fault? + cmpq $14,%rsi /* Page fault? */ jnz 10f - GET_CR2_INTO(%rdi) # can clobber any volatile register if pv + GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */ call early_make_pgtable andl %eax,%eax - jz 20f # All good + jz 20f /* All good */ 10: - leaq 88(%rsp),%rdi # Pointer to %rip + movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */ call early_fixup_exception andl %eax,%eax jnz 20f # Found an exception entry 11: #ifdef CONFIG_EARLY_PRINTK - GET_CR2_INTO(%r9) # can clobber any volatile register if pv - movl 80(%rsp),%r8d # error code - movl 72(%rsp),%esi # vector number - movl 96(%rsp),%edx # %cs - movq 88(%rsp),%rcx # %rip + /* + * On paravirt kernels, GET_CR2_INTO clobbers callee-clobbered regs. + * We only care about RSI, so we need to save it. + */ + movq %rsi,%rbx /* Save vector number */ + GET_CR2_INTO(%r9) + movq ORIG_RAX(%rsp),%r8 /* error code */ + movq %rbx,%rsi /* vector number */ + movq CS(%rsp),%rdx + movq RIP(%rsp),%rcx xorl %eax,%eax leaq early_idt_msg(%rip),%rdi call early_printk @@ -398,24 +412,16 @@ early_idt_handler_common: call dump_stack #ifdef CONFIG_KALLSYMS leaq early_idt_ripmsg(%rip),%rdi - movq 40(%rsp),%rsi # %rip again + movq RIP(%rsp),%rsi # %rip again call __print_symbol #endif #endif /* EARLY_PRINTK */ 1: hlt jmp 1b -20: # Exception table entry found or page table generated - popq %r11 - popq %r10 - popq %r9 - popq %r8 - popq %rdi - popq %rsi - popq %rdx - popq %rcx - popq %rax +20: /* Exception table entry found or page table generated */ decl early_recursion_flag(%rip) + jmp restore_regs_and_iret .Lis_nmi: addq $16,%rsp # drop vector number and error code INTERRUPT_RETURN diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 82447b3fba38..1366e067a796 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -83,13 +83,13 @@ int fixup_exception(struct pt_regs *regs, int trapnr) } /* Restricted version used during very early boot */ -int __init early_fixup_exception(unsigned long *ip) +int __init early_fixup_exception(struct pt_regs *regs, int trapnr) { const struct exception_table_entry *e; unsigned long new_ip; ex_handler_t handler; - e = search_exception_tables(*ip); + e = search_exception_tables(regs->ip); if (!e) return 0; @@ -100,6 +100,6 @@ int __init early_fixup_exception(unsigned long *ip) if (handler != ex_handler_default) return 0; - *ip = new_ip; + regs->ip = new_ip; return 1; } -- GitLab From 0d0efc07f3df677d7622bb760f8e2920b5e33f42 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:33 -0700 Subject: [PATCH 2424/9938] x86/head: Move the early NMI fixup into C C is nicer than asm. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/dd068269f8d59fe44e9e43a50d0efd67da65c2b5.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_32.S | 7 ------- arch/x86/kernel/head_64.S | 6 ------ arch/x86/mm/extable.c | 5 +++++ 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 0904536cd45c..184291c72c22 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -561,9 +561,6 @@ early_idt_handler_common: */ cld - cmpl $2,(%esp) # X86_TRAP_NMI - je .Lis_nmi # Ignore NMI - cmpl $2,%ss:early_recursion_flag je hlt_loop incl %ss:early_recursion_flag @@ -642,10 +639,6 @@ early_idt_handler_common: hlt_loop: hlt jmp hlt_loop - -.Lis_nmi: - addl $8,%esp /* drop vector number and error code */ - iret ENDPROC(early_idt_handler_common) /* This is the default interrupt "handler" :-) */ diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 9e8636d2cedd..230843781dd4 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -351,9 +351,6 @@ early_idt_handler_common: */ cld - cmpl $2,(%rsp) # X86_TRAP_NMI - je .Lis_nmi # Ignore NMI - cmpl $2,early_recursion_flag(%rip) jz 1f incl early_recursion_flag(%rip) @@ -422,9 +419,6 @@ early_idt_handler_common: 20: /* Exception table entry found or page table generated */ decl early_recursion_flag(%rip) jmp restore_regs_and_iret -.Lis_nmi: - addq $16,%rsp # drop vector number and error code - INTERRUPT_RETURN ENDPROC(early_idt_handler_common) __INITDATA diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 1366e067a796..4be041910c2f 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -1,5 +1,6 @@ #include #include +#include typedef bool (*ex_handler_t)(const struct exception_table_entry *, struct pt_regs *, int); @@ -89,6 +90,10 @@ int __init early_fixup_exception(struct pt_regs *regs, int trapnr) unsigned long new_ip; ex_handler_t handler; + /* Ignore early NMIs. */ + if (trapnr == X86_TRAP_NMI) + return 1; + e = search_exception_tables(regs->ip); if (!e) return 0; -- GitLab From 0e861fbb5bda79b871341ef2a9a8059765cbe8a4 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:34 -0700 Subject: [PATCH 2425/9938] x86/head: Move early exception panic code into early_fixup_exception() This removes a bunch of assembly and adds some C code instead. It changes the actual printouts on both 32-bit and 64-bit kernels, but they still seem okay. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/4085070316fc3ab29538d3fcfe282648d1d4ee2e.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uaccess.h | 2 +- arch/x86/kernel/head_32.S | 49 ++++------------------------------ arch/x86/kernel/head_64.S | 45 ++----------------------------- arch/x86/mm/extable.c | 29 ++++++++++++++++---- 4 files changed, 32 insertions(+), 93 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index b6fb311b7d75..d794fd1f582f 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -110,7 +110,7 @@ struct exception_table_entry { extern int fixup_exception(struct pt_regs *regs, int trapnr); extern bool ex_has_fault_handler(unsigned long ip); -extern int early_fixup_exception(struct pt_regs *regs, int trapnr); +extern void early_fixup_exception(struct pt_regs *regs, int trapnr); /* * These are the main single-value transfer routines. They automatically diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 184291c72c22..6770865fde6b 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -561,8 +561,6 @@ early_idt_handler_common: */ cld - cmpl $2,%ss:early_recursion_flag - je hlt_loop incl %ss:early_recursion_flag /* The vector number is in pt_regs->gs */ @@ -594,13 +592,8 @@ early_idt_handler_common: movw %gs, PT_GS(%esp) movw $0, PT_GS+2(%esp) - cmpl $(__KERNEL_CS),PT_CS(%esp) - jne 10f - movl %esp, %eax /* args are pt_regs (EAX), trapnr (EDX) */ call early_fixup_exception - andl %eax,%eax - jz 10f /* Exception wasn't fixed up */ popl %ebx /* pt_regs->bx */ popl %ecx /* pt_regs->cx */ @@ -616,29 +609,6 @@ early_idt_handler_common: decl %ss:early_recursion_flag addl $4, %esp /* pop pt_regs->orig_ax */ iret - -10: -#ifdef CONFIG_PRINTK - xorl %eax,%eax - movw %ax,PT_FS+2(%esp) /* clean up the segment values on some cpus */ - movw %ax,PT_DS+2(%esp) - movw %ax,PT_ES+2(%esp) - leal 40(%esp),%eax - pushl %eax /* %esp before the exception */ - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - movl %cr2,%eax - pushl %eax - pushl (20+6*4)(%esp) /* trapno */ - pushl $fault_msg - call printk -#endif - call dump_stack -hlt_loop: - hlt - jmp hlt_loop ENDPROC(early_idt_handler_common) /* This is the default interrupt "handler" :-) */ @@ -674,10 +644,14 @@ ignore_int: popl %eax #endif iret + +hlt_loop: + hlt + jmp hlt_loop ENDPROC(ignore_int) __INITDATA .align 4 -early_recursion_flag: +GLOBAL(early_recursion_flag) .long 0 __REFDATA @@ -742,19 +716,6 @@ __INITRODATA int_msg: .asciz "Unknown interrupt or fault at: %p %p %p\n" -fault_msg: -/* fault info: */ - .ascii "BUG: Int %d: CR2 %p\n" -/* regs pushed in early_idt_handler: */ - .ascii " EDI %p ESI %p EBP %p EBX %p\n" - .ascii " ESP %p ES %p DS %p\n" - .ascii " EDX %p ECX %p EAX %p\n" -/* fault frame: */ - .ascii " vec %p err %p EIP %p CS %p flg %p\n" - .ascii "Stack: %p %p %p %p %p %p %p %p\n" - .ascii " %p %p %p %p %p %p %p %p\n" - .asciz " %p %p %p %p %p %p %p %p\n" - #include "../../x86/xen/xen-head.S" /* diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 230843781dd4..3de91a7e6c99 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -351,8 +351,6 @@ early_idt_handler_common: */ cld - cmpl $2,early_recursion_flag(%rip) - jz 1f incl early_recursion_flag(%rip) /* The vector number is currently in the pt_regs->di slot. */ @@ -373,9 +371,6 @@ early_idt_handler_common: pushq %r14 /* pt_regs->r14 */ pushq %r15 /* pt_regs->r15 */ - cmpl $__KERNEL_CS,CS(%rsp) - jne 11f - cmpq $14,%rsi /* Page fault? */ jnz 10f GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */ @@ -386,37 +381,8 @@ early_idt_handler_common: 10: movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */ call early_fixup_exception - andl %eax,%eax - jnz 20f # Found an exception entry - -11: -#ifdef CONFIG_EARLY_PRINTK - /* - * On paravirt kernels, GET_CR2_INTO clobbers callee-clobbered regs. - * We only care about RSI, so we need to save it. - */ - movq %rsi,%rbx /* Save vector number */ - GET_CR2_INTO(%r9) - movq ORIG_RAX(%rsp),%r8 /* error code */ - movq %rbx,%rsi /* vector number */ - movq CS(%rsp),%rdx - movq RIP(%rsp),%rcx - xorl %eax,%eax - leaq early_idt_msg(%rip),%rdi - call early_printk - cmpl $2,early_recursion_flag(%rip) - jz 1f - call dump_stack -#ifdef CONFIG_KALLSYMS - leaq early_idt_ripmsg(%rip),%rdi - movq RIP(%rsp),%rsi # %rip again - call __print_symbol -#endif -#endif /* EARLY_PRINTK */ -1: hlt - jmp 1b -20: /* Exception table entry found or page table generated */ +20: decl early_recursion_flag(%rip) jmp restore_regs_and_iret ENDPROC(early_idt_handler_common) @@ -424,16 +390,9 @@ ENDPROC(early_idt_handler_common) __INITDATA .balign 4 -early_recursion_flag: +GLOBAL(early_recursion_flag) .long 0 -#ifdef CONFIG_EARLY_PRINTK -early_idt_msg: - .asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n" -early_idt_ripmsg: - .asciz "RIP %s\n" -#endif /* CONFIG_EARLY_PRINTK */ - #define NEXT_PAGE(name) \ .balign PAGE_SIZE; \ GLOBAL(name) diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 4be041910c2f..da442f37ca8b 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -83,8 +83,10 @@ int fixup_exception(struct pt_regs *regs, int trapnr) return handler(e, regs, trapnr); } +extern unsigned int early_recursion_flag; + /* Restricted version used during very early boot */ -int __init early_fixup_exception(struct pt_regs *regs, int trapnr) +void __init early_fixup_exception(struct pt_regs *regs, int trapnr) { const struct exception_table_entry *e; unsigned long new_ip; @@ -92,19 +94,36 @@ int __init early_fixup_exception(struct pt_regs *regs, int trapnr) /* Ignore early NMIs. */ if (trapnr == X86_TRAP_NMI) - return 1; + return; + + if (early_recursion_flag > 2) + goto halt_loop; + + if (regs->cs != __KERNEL_CS) + goto fail; e = search_exception_tables(regs->ip); if (!e) - return 0; + goto fail; new_ip = ex_fixup_addr(e); handler = ex_fixup_handler(e); /* special handling not supported during early boot */ if (handler != ex_handler_default) - return 0; + goto fail; regs->ip = new_ip; - return 1; + return; + +fail: + early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n", + (unsigned)trapnr, (unsigned long)regs->cs, regs->ip, + regs->orig_ax, read_cr2()); + + show_regs(regs); + +halt_loop: + while (true) + halt(); } -- GitLab From ae7ef45e12354a1e2f6013b46df0c9f5bbb6ffbe Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:35 -0700 Subject: [PATCH 2426/9938] x86/traps: Enable all exception handler callbacks early Now that early_fixup_exception() has pt_regs, we can just call fixup_exception() from it. This will make fancy exception handlers work early. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/20fc047d926150cb08cb9b9f2923519b07ec1a15.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/mm/extable.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index da442f37ca8b..061a23758354 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -88,10 +88,6 @@ extern unsigned int early_recursion_flag; /* Restricted version used during very early boot */ void __init early_fixup_exception(struct pt_regs *regs, int trapnr) { - const struct exception_table_entry *e; - unsigned long new_ip; - ex_handler_t handler; - /* Ignore early NMIs. */ if (trapnr == X86_TRAP_NMI) return; @@ -102,19 +98,8 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr) if (regs->cs != __KERNEL_CS) goto fail; - e = search_exception_tables(regs->ip); - if (!e) - goto fail; - - new_ip = ex_fixup_addr(e); - handler = ex_fixup_handler(e); - - /* special handling not supported during early boot */ - if (handler != ex_handler_default) - goto fail; - - regs->ip = new_ip; - return; + if (fixup_exception(regs, trapnr)) + return; fail: early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n", -- GitLab From c2ee03b2a94d7ba692cf6206bbe069d5bfcc20ed Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:36 -0700 Subject: [PATCH 2427/9938] x86/paravirt: Add _safe to the read_ms()r and write_msr() PV callbacks These callbacks match the _safe variants, so name them accordingly. This will make room for unsafe PV callbacks. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/9ee3fb6a196a514c93325bdfa15594beecf04876.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/paravirt.h | 33 ++++++++++++++------------- arch/x86/include/asm/paravirt_types.h | 8 +++---- arch/x86/kernel/paravirt.c | 4 ++-- arch/x86/xen/enlighten.c | 4 ++-- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 601f1b8f9961..81ef2d5c2a24 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -130,34 +130,35 @@ static inline void wbinvd(void) #define get_kernel_rpl() (pv_info.kernel_rpl) -static inline u64 paravirt_read_msr(unsigned msr, int *err) +static inline u64 paravirt_read_msr_safe(unsigned msr, int *err) { - return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err); + return PVOP_CALL2(u64, pv_cpu_ops.read_msr_safe, msr, err); } -static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high) +static inline int paravirt_write_msr_safe(unsigned msr, + unsigned low, unsigned high) { - return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high); + return PVOP_CALL3(int, pv_cpu_ops.write_msr_safe, msr, low, high); } /* These should all do BUG_ON(_err), but our headers are too tangled. */ #define rdmsr(msr, val1, val2) \ do { \ int _err; \ - u64 _l = paravirt_read_msr(msr, &_err); \ + u64 _l = paravirt_read_msr_safe(msr, &_err); \ val1 = (u32)_l; \ val2 = _l >> 32; \ } while (0) #define wrmsr(msr, val1, val2) \ do { \ - paravirt_write_msr(msr, val1, val2); \ + paravirt_write_msr_safe(msr, val1, val2); \ } while (0) #define rdmsrl(msr, val) \ do { \ int _err; \ - val = paravirt_read_msr(msr, &_err); \ + val = paravirt_read_msr_safe(msr, &_err); \ } while (0) static inline void wrmsrl(unsigned msr, u64 val) @@ -165,23 +166,23 @@ static inline void wrmsrl(unsigned msr, u64 val) wrmsr(msr, (u32)val, (u32)(val>>32)); } -#define wrmsr_safe(msr, a, b) paravirt_write_msr(msr, a, b) +#define wrmsr_safe(msr, a, b) paravirt_write_msr_safe(msr, a, b) /* rdmsr with exception handling */ -#define rdmsr_safe(msr, a, b) \ -({ \ - int _err; \ - u64 _l = paravirt_read_msr(msr, &_err); \ - (*a) = (u32)_l; \ - (*b) = _l >> 32; \ - _err; \ +#define rdmsr_safe(msr, a, b) \ +({ \ + int _err; \ + u64 _l = paravirt_read_msr_safe(msr, &_err); \ + (*a) = (u32)_l; \ + (*b) = _l >> 32; \ + _err; \ }) static inline int rdmsrl_safe(unsigned msr, unsigned long long *p) { int err; - *p = paravirt_read_msr(msr, &err); + *p = paravirt_read_msr_safe(msr, &err); return err; } diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index e8c2326478c8..09c9e1dd81ce 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -155,10 +155,10 @@ struct pv_cpu_ops { void (*cpuid)(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx); - /* MSR, PMC and TSR operations. - err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */ - u64 (*read_msr)(unsigned int msr, int *err); - int (*write_msr)(unsigned int msr, unsigned low, unsigned high); + /* MSR operations. + err = 0/-EIO. wrmsr returns 0/-EIO. */ + u64 (*read_msr_safe)(unsigned int msr, int *err); + int (*write_msr_safe)(unsigned int msr, unsigned low, unsigned high); u64 (*read_pmc)(int counter); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index f08ac28b8136..8aad95478ae5 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -339,8 +339,8 @@ __visible struct pv_cpu_ops pv_cpu_ops = { .write_cr8 = native_write_cr8, #endif .wbinvd = native_wbinvd, - .read_msr = native_read_msr_safe, - .write_msr = native_write_msr_safe, + .read_msr_safe = native_read_msr_safe, + .write_msr_safe = native_write_msr_safe, .read_pmc = native_read_pmc, .load_tr_desc = native_load_tr_desc, .set_ldt = native_set_ldt, diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 9b8f1eacc110..13f756fdcb33 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1222,8 +1222,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .wbinvd = native_wbinvd, - .read_msr = xen_read_msr_safe, - .write_msr = xen_write_msr_safe, + .read_msr_safe = xen_read_msr_safe, + .write_msr_safe = xen_write_msr_safe, .read_pmc = xen_read_pmc, -- GitLab From fbd704374d111bed16a19261176fa30e2379c87c Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:37 -0700 Subject: [PATCH 2428/9938] x86/msr: Carry on after a non-"safe" MSR access fails This demotes an OOPS and likely panic due to a failed non-"safe" MSR access to a WARN_ONCE() and, for RDMSR, a return value of zero. To be clear, this type of failure should *not* happen. This patch exists to minimize the chance of nasty undebuggable failures happening when a CONFIG_PARAVIRT=y bug in the non-"safe" MSR helpers gets fixed. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/26567b216aae70e795938f4b567eace5a0eb90ba.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/msr.h | 10 ++++++++-- arch/x86/mm/extable.c | 27 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 7a79ee2778b3..25f169c6eb95 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -84,7 +84,10 @@ static inline unsigned long long native_read_msr(unsigned int msr) { DECLARE_ARGS(val, low, high); - asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); + asm volatile("1: rdmsr\n" + "2:\n" + _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_unsafe) + : EAX_EDX_RET(val, low, high) : "c" (msr)); if (msr_tracepoint_active(__tracepoint_read_msr)) do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), 0); return EAX_EDX_VAL(val, low, high); @@ -111,7 +114,10 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, static inline void native_write_msr(unsigned int msr, unsigned low, unsigned high) { - asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); + asm volatile("1: wrmsr\n" + "2:\n" + _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe) + : : "c" (msr), "a"(low), "d" (high) : "memory"); if (msr_tracepoint_active(__tracepoint_read_msr)) do_trace_write_msr(msr, ((u64)high << 32 | low), 0); } diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 061a23758354..fd9eb98c4f58 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -43,6 +43,33 @@ bool ex_handler_ext(const struct exception_table_entry *fixup, } EXPORT_SYMBOL(ex_handler_ext); +bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup, + struct pt_regs *regs, int trapnr) +{ + WARN_ONCE(1, "unchecked MSR access error: RDMSR from 0x%x\n", + (unsigned int)regs->cx); + + /* Pretend that the read succeeded and returned 0. */ + regs->ip = ex_fixup_addr(fixup); + regs->ax = 0; + regs->dx = 0; + return true; +} +EXPORT_SYMBOL(ex_handler_rdmsr_unsafe); + +bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup, + struct pt_regs *regs, int trapnr) +{ + WARN_ONCE(1, "unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x)\n", + (unsigned int)regs->cx, + (unsigned int)regs->dx, (unsigned int)regs->ax); + + /* Pretend that the write succeeded. */ + regs->ip = ex_fixup_addr(fixup); + return true; +} +EXPORT_SYMBOL(ex_handler_wrmsr_unsafe); + bool ex_has_fault_handler(unsigned long ip) { const struct exception_table_entry *e; -- GitLab From dd2f4a004b016bbfb64f1de49cb45e66232e40a6 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:38 -0700 Subject: [PATCH 2429/9938] x86/paravirt: Add paravirt_{read,write}_msr() This adds paravirt callbacks for unsafe MSR access. On native, they call native_{read,write}_msr(). On Xen, they use xen_{read,write}_msr_safe(). Nothing uses them yet for ease of bisection. The next patch will use them in rdmsrl(), wrmsrl(), etc. I intentionally didn't make them warn on #GP on Xen. I think that should be done separately by the Xen maintainers. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/880eebc5dcd2ad9f310d41345f82061ea500e9fa.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/msr.h | 5 +++-- arch/x86/include/asm/paravirt.h | 11 +++++++++++ arch/x86/include/asm/paravirt_types.h | 10 ++++++++-- arch/x86/kernel/paravirt.c | 2 ++ arch/x86/xen/enlighten.c | 23 +++++++++++++++++++++++ 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 25f169c6eb95..00050c034a13 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -111,8 +111,9 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, return EAX_EDX_VAL(val, low, high); } -static inline void native_write_msr(unsigned int msr, - unsigned low, unsigned high) +/* Can be uninlined because referenced by paravirt */ +notrace static inline void native_write_msr(unsigned int msr, + unsigned low, unsigned high) { asm volatile("1: wrmsr\n" "2:\n" diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 81ef2d5c2a24..97839fa8b8aa 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -130,6 +130,17 @@ static inline void wbinvd(void) #define get_kernel_rpl() (pv_info.kernel_rpl) +static inline u64 paravirt_read_msr(unsigned msr) +{ + return PVOP_CALL1(u64, pv_cpu_ops.read_msr, msr); +} + +static inline void paravirt_write_msr(unsigned msr, + unsigned low, unsigned high) +{ + return PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high); +} + static inline u64 paravirt_read_msr_safe(unsigned msr, int *err) { return PVOP_CALL2(u64, pv_cpu_ops.read_msr_safe, msr, err); diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 09c9e1dd81ce..b4a23eafa1b9 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -155,8 +155,14 @@ struct pv_cpu_ops { void (*cpuid)(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx); - /* MSR operations. - err = 0/-EIO. wrmsr returns 0/-EIO. */ + /* Unsafe MSR operations. These will warn or panic on failure. */ + u64 (*read_msr)(unsigned int msr); + void (*write_msr)(unsigned int msr, unsigned low, unsigned high); + + /* + * Safe MSR operations. + * read sets err to 0 or -EIO. write returns 0 or -EIO. + */ u64 (*read_msr_safe)(unsigned int msr, int *err); int (*write_msr_safe)(unsigned int msr, unsigned low, unsigned high); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 8aad95478ae5..f9583917c7c4 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -339,6 +339,8 @@ __visible struct pv_cpu_ops pv_cpu_ops = { .write_cr8 = native_write_cr8, #endif .wbinvd = native_wbinvd, + .read_msr = native_read_msr, + .write_msr = native_write_msr, .read_msr_safe = native_read_msr_safe, .write_msr_safe = native_write_msr_safe, .read_pmc = native_read_pmc, diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 13f756fdcb33..6ab672233ac9 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1092,6 +1092,26 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) return ret; } +static u64 xen_read_msr(unsigned int msr) +{ + /* + * This will silently swallow a #GP from RDMSR. It may be worth + * changing that. + */ + int err; + + return xen_read_msr_safe(msr, &err); +} + +static void xen_write_msr(unsigned int msr, unsigned low, unsigned high) +{ + /* + * This will silently swallow a #GP from WRMSR. It may be worth + * changing that. + */ + xen_write_msr_safe(msr, low, high); +} + void xen_setup_shared_info(void) { if (!xen_feature(XENFEAT_auto_translated_physmap)) { @@ -1222,6 +1242,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .wbinvd = native_wbinvd, + .read_msr = xen_read_msr, + .write_msr = xen_write_msr, + .read_msr_safe = xen_read_msr_safe, .write_msr_safe = xen_write_msr_safe, -- GitLab From 4985ce15a397e9b6541548efe3b9ffac2dda9127 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:39 -0700 Subject: [PATCH 2430/9938] x86/paravirt: Make "unsafe" MSR accesses unsafe even if PARAVIRT=y Enabling CONFIG_PARAVIRT had an unintended side effect: rdmsr() turned into rdmsr_safe() and wrmsr() turned into wrmsr_safe(), even on bare metal. Undo that by using the new unsafe paravirt MSR callbacks. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/414fabd6d3527703077c6c2a797223d0a9c3b081.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/paravirt.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 97839fa8b8aa..3c731413f1de 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -152,24 +152,21 @@ static inline int paravirt_write_msr_safe(unsigned msr, return PVOP_CALL3(int, pv_cpu_ops.write_msr_safe, msr, low, high); } -/* These should all do BUG_ON(_err), but our headers are too tangled. */ #define rdmsr(msr, val1, val2) \ do { \ - int _err; \ - u64 _l = paravirt_read_msr_safe(msr, &_err); \ + u64 _l = paravirt_read_msr(msr); \ val1 = (u32)_l; \ val2 = _l >> 32; \ } while (0) #define wrmsr(msr, val1, val2) \ do { \ - paravirt_write_msr_safe(msr, val1, val2); \ + paravirt_write_msr(msr, val1, val2); \ } while (0) #define rdmsrl(msr, val) \ do { \ - int _err; \ - val = paravirt_read_msr_safe(msr, &_err); \ + val = paravirt_read_msr(msr); \ } while (0) static inline void wrmsrl(unsigned msr, u64 val) -- GitLab From b828b79fcced0e66492590707649dbfaea6435e6 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 2 Apr 2016 07:01:40 -0700 Subject: [PATCH 2431/9938] x86/msr: Set the return value to zero when native_rdmsr_safe() fails This will cause unchecked native_rdmsr_safe() failures to return deterministic results. Tested-by: Boris Ostrovsky Signed-off-by: Andy Lutomirski Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/515fb611449a755312a476cfe11675906e7ddf6c.1459605520.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/msr.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 00050c034a13..7dc1d8fef7fd 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -101,7 +101,10 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, asm volatile("2: rdmsr ; xor %[err],%[err]\n" "1:\n\t" ".section .fixup,\"ax\"\n\t" - "3: mov %[fault],%[err] ; jmp 1b\n\t" + "3: mov %[fault],%[err]\n\t" + "xorl %%eax, %%eax\n\t" + "xorl %%edx, %%edx\n\t" + "jmp 1b\n\t" ".previous\n\t" _ASM_EXTABLE(2b, 3b) : [err] "=r" (*err), EAX_EDX_RET(val, low, high) -- GitLab From 60a0e2039e3df6c0a2b896bd78af36ff36fb629c Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Mon, 4 Apr 2016 08:46:22 -0700 Subject: [PATCH 2432/9938] x86/extable: Add a comment about early exception handlers Borislav asked for a comment explaining why all exception handlers are allowed early. Signed-off-by: Andy Lutomirski Reviewed-by: Borislav Petkov Acked-by: Linus Torvalds Cc: Andrew Morton Cc: Arjan van de Ven Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: KVM list Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: xen-devel Link: http://lkml.kernel.org/r/5f1dcd6919f4a5923959a8065cb2c04d9dac1412.1459784772.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/mm/extable.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index fd9eb98c4f58..aaeda3ffaafe 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -125,6 +125,20 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr) if (regs->cs != __KERNEL_CS) goto fail; + /* + * The full exception fixup machinery is available as soon as + * the early IDT is loaded. This means that it is the + * responsibility of extable users to either function correctly + * when handlers are invoked early or to simply avoid causing + * exceptions before they're ready to handle them. + * + * This is better than filtering which handlers can be used, + * because refusing to call a handler here is guaranteed to + * result in a hard-to-debug panic. + * + * Keep in mind that not all vectors actually get here. Early + * fage faults, for example, are special. + */ if (fixup_exception(regs, trapnr)) return; -- GitLab From e8ed73f691bdbfaed02ad63a42e8332d7cafa8bd Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Sat, 2 Apr 2016 18:25:43 +0200 Subject: [PATCH 2433/9938] ARM: dts: imx7d: add lcdif support Add the device node for the i.MX7 eLCDIF interface. Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7d.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi index b5a50e0e7ff1..2547e16a0a17 100644 --- a/arch/arm/boot/dts/imx7d.dtsi +++ b/arch/arm/boot/dts/imx7d.dtsi @@ -651,6 +651,17 @@ #pwm-cells = <2>; status = "disabled"; }; + + lcdif: lcdif@30730000 { + compatible = "fsl,imx7d-lcdif", "fsl,imx28-lcdif"; + reg = <0x30730000 0x10000>; + interrupts = ; + clocks = <&clks IMX7D_LCDIF_PIXEL_ROOT_CLK>, + <&clks IMX7D_CLK_DUMMY>, + <&clks IMX7D_CLK_DUMMY>; + clock-names = "pix", "axi", "disp_axi"; + status = "disabled"; + }; }; aips3: aips-bus@30800000 { -- GitLab From c147401d45b84a66efa8cea6c74e130dc1ac3e3b Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Sat, 2 Apr 2016 18:25:44 +0200 Subject: [PATCH 2434/9938] ARM: dts: imx7d: add flexcan support Add the device nodes for the i.MX7 FlexCAN buses. Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7d.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi index 2547e16a0a17..6b3faa298417 100644 --- a/arch/arm/boot/dts/imx7d.dtsi +++ b/arch/arm/boot/dts/imx7d.dtsi @@ -704,6 +704,26 @@ status = "disabled"; }; + flexcan1: can@30a00000 { + compatible = "fsl,imx7d-flexcan", "fsl,imx6q-flexcan"; + reg = <0x30a00000 0x10000>; + interrupts = ; + clocks = <&clks IMX7D_CLK_DUMMY>, + <&clks IMX7D_CAN1_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + flexcan2: can@30a10000 { + compatible = "fsl,imx7d-flexcan", "fsl,imx6q-flexcan"; + reg = <0x30a10000 0x10000>; + interrupts = ; + clocks = <&clks IMX7D_CLK_DUMMY>, + <&clks IMX7D_CAN2_ROOT_CLK>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + i2c1: i2c@30a20000 { #address-cells = <1>; #size-cells = <0>; -- GitLab From 56354959cfecd6501cd69c49edca483a7b11d461 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Thu, 7 Apr 2016 15:50:57 +0200 Subject: [PATCH 2435/9938] ARM: dts: imx: add Boundary Devices Nitrogen7 board Based on i.MX7 Dual with 1GB of RAM. https://boundarydevices.com/product/nitrogen7/ Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx7d-nitrogen7.dts | 745 ++++++++++++++++++++++++++ 2 files changed, 746 insertions(+) create mode 100644 arch/arm/boot/dts/imx7d-nitrogen7.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..65e99f80e77c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -377,6 +377,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-14x14-evk.dtb dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ + imx7d-nitrogen7.dtb \ imx7d-sbc-imx7.dtb \ imx7d-sdb.dtb dtb-$(CONFIG_SOC_LS1021A) += \ diff --git a/arch/arm/boot/dts/imx7d-nitrogen7.dts b/arch/arm/boot/dts/imx7d-nitrogen7.dts new file mode 100644 index 000000000000..1ce97800f0c5 --- /dev/null +++ b/arch/arm/boot/dts/imx7d-nitrogen7.dts @@ -0,0 +1,745 @@ +/* + * Copyright 2016 Boundary Devices, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include +#include "imx7d.dtsi" + +/ { + model = "Boundary Devices i.MX7 Nitrogen7 Board"; + compatible = "boundary,imx7d-nitrogen7", "fsl,imx7d"; + + aliases { + fb_lcd = &lcdif; + t_lcd = &t_lcd; + }; + + memory { + reg = <0x80000000 0x40000000>; + }; + + backlight-j9 { + compatible = "gpio-backlight"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_backlight_j9>; + gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + default-on; + }; + + backlight-j20 { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 5000000>; + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <6>; + status = "okay"; + }; + + reg_usb_otg1_vbus: regulator-usb-otg1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_otg1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usb_otg2_vbus: regulator-usb-otg2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_otg2_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio4 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_can2_3v3: regulator-can2-3v3 { + compatible = "regulator-fixed"; + regulator-name = "can2-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 14 GPIO_ACTIVE_LOW>; + }; + + reg_vref_1v8: regulator-vref-1v8 { + compatible = "regulator-fixed"; + regulator-name = "vref-1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + reg_vref_3v3: regulator-vref-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vref-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_wlan: regulator-wlan { + compatible = "regulator-fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + clocks = <&clks IMX7D_CLKO2_ROOT_DIV>; + clock-names = "slow"; + regulator-name = "reg_wlan"; + startup-delay-us = <70000>; + gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&adc1 { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&adc2 { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&clks { + assigned-clocks = <&clks IMX7D_CLKO2_ROOT_SRC>, + <&clks IMX7D_CLKO2_ROOT_DIV>; + assigned-clock-parents = <&clks IMX7D_CKIL>; + assigned-clock-rates = <0>, <32768>; +}; + +&cpu0 { + arm-supply = <&sw1a_reg>; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>, + <&clks IMX7D_ENET1_TIME_ROOT_CLK>; + assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>; + assigned-clock-rates = <0>, <100000000>; + phy-mode = "rgmii"; + phy-handle = <ðphy0>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@4 { + reg = <4>; + }; + }; +}; + +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <®_can2_3v3>; + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + pmic: pfuze3000@08 { + compatible = "fsl,pfuze3000"; + reg = <0x08>; + + regulators { + sw1a_reg: sw1a { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1475000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + /* use sw1c_reg to align with pfuze100/pfuze200 */ + sw1c_reg: sw1b { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1475000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1850000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3a_reg: sw3 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1650000>; + regulator-boot-on; + regulator-always-on; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-boot-on; + regulator-always-on; + }; + + vgen1_reg: vldo1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen2_reg: vldo2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + regulator-always-on; + }; + + vgen3_reg: vccsd { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen4_reg: v33 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen5_reg: vldo3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen6_reg: vldo4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + rtc@68 { + compatible = "rv4162"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2_rv4162>; + reg = <0x68>; + interrupts-extended = <&gpio2 15 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; + + touch@48 { + compatible = "ti,tsc2004"; + reg = <0x48>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3_tsc2004>; + interrupts-extended = <&gpio3 4 IRQ_TYPE_EDGE_FALLING>; + wakeup-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; + }; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c4>; + status = "okay"; + + codec: wm8960@1a { + compatible = "wlf,wm8960"; + reg = <0x1a>; + clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>; + clock-names = "mclk"; + wlf,shared-lrclk; + }; +}; + +&lcdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcdif_dat + &pinctrl_lcdif_ctrl>; + lcd-supply = <®_vref_3v3>; + display = <&display0>; + status = "okay"; + + display0: lcd-display { + bits-per-pixel = <16>; + bus-width = <18>; + + display-timings { + native-mode = <&t_lcd>; + t_lcd: t_lcd_default { + /* default to Okaya display */ + clock-frequency = <30000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <40>; + hsync-len = <48>; + vback-porch = <29>; + vfront-porch = <13>; + vsync-len = <3>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; +}; + +&pwm1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; + status = "okay"; +}; + +&pwm2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + assigned-clocks = <&clks IMX7D_UART3_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; + status = "okay"; +}; + +&uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart6>; + assigned-clocks = <&clks IMX7D_UART6_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&usbotg1 { + vbus-supply = <®_usb_otg1_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg1>; + status = "okay"; +}; + +&usbotg2 { + vbus-supply = <®_usb_otg2_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg2>; + dr_mode = "host"; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vgen3_reg>; + bus-width = <4>; + fsl,tuning-step = <2>; + wakeup-source; + keep-power-in-suspend; + status = "okay"; +}; + +&usdhc2 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + bus-width = <4>; + non-removable; + vmmc-supply = <®_wlan>; + cap-power-off-card; + keep-power-in-suspend; + status = "okay"; + + wlcore: wlcore@2 { + compatible = "ti,wl1271"; + reg = <2>; + interrupt-parent = <&gpio4>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + ref-clock-frequency = <38400000>; + }; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>; + assigned-clock-rates = <400000000>; + bus-width = <8>; + fsl,tuning-step = <2>; + non-removable; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog1>; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog_1 &pinctrl_j2>; + + pinctrl_hog_1: hoggrp-1 { + fsl,pins = < + MX7D_PAD_SD3_RESET_B__GPIO6_IO11 0x5d + MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x7d + MX7D_PAD_ECSPI2_MISO__GPIO4_IO22 0x7d + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO10__ENET1_MDIO 0x3 + MX7D_PAD_GPIO1_IO11__ENET1_MDC 0x3 + MX7D_PAD_GPIO1_IO12__CCM_ENET_REF_CLK1 0x3 + MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x71 + MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 0x71 + MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 0x71 + MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 0x71 + MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 0x71 + MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x71 + MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC 0x71 + MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x11 + MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x11 + MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 0x11 + MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 0x71 + MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x11 + MX7D_PAD_SD3_STROBE__GPIO6_IO10 0x75 + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX 0x7d + MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX 0x7d + MX7D_PAD_EPDC_DATA14__GPIO2_IO14 0x7d + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f + MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX7D_PAD_I2C2_SDA__I2C2_SDA 0x4000007f + MX7D_PAD_I2C2_SCL__I2C2_SCL 0x4000007f + >; + }; + + pinctrl_i2c2_rv4162: i2c2-rv4162grp { + fsl,pins = < + MX7D_PAD_EPDC_DATA15__GPIO2_IO15 0x7d + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX7D_PAD_I2C3_SDA__I2C3_SDA 0x4000007f + MX7D_PAD_I2C3_SCL__I2C3_SCL 0x4000007f + >; + }; + + pinctrl_i2c3_tsc2004: i2c3tsc2004grp { + fsl,pins = < + MX7D_PAD_LCD_RESET__GPIO3_IO4 0x79 + MX7D_PAD_SD2_WP__GPIO5_IO10 0x7d + >; + }; + + pinctrl_i2c4: i2c4grp { + fsl,pins = < + MX7D_PAD_I2C4_SDA__I2C4_SDA 0x4000007f + MX7D_PAD_I2C4_SCL__I2C4_SCL 0x4000007f + >; + }; + + pinctrl_j2: j2grp { + fsl,pins = < + MX7D_PAD_SAI1_TX_DATA__GPIO6_IO15 0x7d + MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x7d + MX7D_PAD_SAI1_RX_DATA__GPIO6_IO12 0x7d + MX7D_PAD_EPDC_BDR1__GPIO2_IO29 0x7d + MX7D_PAD_SD1_WP__GPIO5_IO1 0x7d + MX7D_PAD_EPDC_SDSHR__GPIO2_IO19 0x7d + MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x7d + MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x7d + MX7D_PAD_EPDC_DATA07__GPIO2_IO7 0x7d + MX7D_PAD_EPDC_DATA08__GPIO2_IO8 0x7d + MX7D_PAD_EPDC_DATA09__GPIO2_IO9 0x7d + MX7D_PAD_EPDC_DATA10__GPIO2_IO10 0x7d + MX7D_PAD_EPDC_DATA11__GPIO2_IO11 0x7d + MX7D_PAD_EPDC_DATA12__GPIO2_IO12 0x7d + MX7D_PAD_SAI1_TX_SYNC__GPIO6_IO14 0x7d + MX7D_PAD_EPDC_DATA13__GPIO2_IO13 0x7d + MX7D_PAD_SAI1_TX_BCLK__GPIO6_IO13 0x7d + MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x7d + MX7D_PAD_EPDC_GDCLK__GPIO2_IO24 0x7d + MX7D_PAD_SAI2_RX_DATA__GPIO6_IO21 0x7d + MX7D_PAD_EPDC_GDOE__GPIO2_IO25 0x7d + MX7D_PAD_EPDC_GDRL__GPIO2_IO26 0x7d + MX7D_PAD_SAI2_TX_DATA__GPIO6_IO22 0x7d + MX7D_PAD_EPDC_SDCE0__GPIO2_IO20 0x7d + MX7D_PAD_SAI2_TX_BCLK__GPIO6_IO20 0x7d + MX7D_PAD_EPDC_SDCE1__GPIO2_IO21 0x7d + MX7D_PAD_SAI2_TX_SYNC__GPIO6_IO19 0x7d + MX7D_PAD_EPDC_SDCE2__GPIO2_IO22 0x7d + MX7D_PAD_EPDC_SDCE3__GPIO2_IO23 0x7d + MX7D_PAD_EPDC_GDSP__GPIO2_IO27 0x7d + MX7D_PAD_EPDC_SDCLK__GPIO2_IO16 0x7d + MX7D_PAD_EPDC_SDLE__GPIO2_IO17 0x7d + MX7D_PAD_EPDC_SDOE__GPIO2_IO18 0x7d + MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30 0x7d + MX7D_PAD_EPDC_PWR_STAT__GPIO2_IO31 0x7d + >; + }; + + pinctrl_lcdif_dat: lcdifdatgrp { + fsl,pins = < + MX7D_PAD_LCD_DATA00__LCD_DATA0 0x79 + MX7D_PAD_LCD_DATA01__LCD_DATA1 0x79 + MX7D_PAD_LCD_DATA02__LCD_DATA2 0x79 + MX7D_PAD_LCD_DATA03__LCD_DATA3 0x79 + MX7D_PAD_LCD_DATA04__LCD_DATA4 0x79 + MX7D_PAD_LCD_DATA05__LCD_DATA5 0x79 + MX7D_PAD_LCD_DATA06__LCD_DATA6 0x79 + MX7D_PAD_LCD_DATA07__LCD_DATA7 0x79 + MX7D_PAD_LCD_DATA08__LCD_DATA8 0x79 + MX7D_PAD_LCD_DATA09__LCD_DATA9 0x79 + MX7D_PAD_LCD_DATA10__LCD_DATA10 0x79 + MX7D_PAD_LCD_DATA11__LCD_DATA11 0x79 + MX7D_PAD_LCD_DATA12__LCD_DATA12 0x79 + MX7D_PAD_LCD_DATA13__LCD_DATA13 0x79 + MX7D_PAD_LCD_DATA14__LCD_DATA14 0x79 + MX7D_PAD_LCD_DATA15__LCD_DATA15 0x79 + MX7D_PAD_LCD_DATA16__LCD_DATA16 0x79 + MX7D_PAD_LCD_DATA17__LCD_DATA17 0x79 + MX7D_PAD_LCD_DATA18__LCD_DATA18 0x79 + MX7D_PAD_LCD_DATA19__LCD_DATA19 0x79 + MX7D_PAD_LCD_DATA20__LCD_DATA20 0x79 + MX7D_PAD_LCD_DATA21__LCD_DATA21 0x79 + MX7D_PAD_LCD_DATA22__LCD_DATA22 0x79 + MX7D_PAD_LCD_DATA23__LCD_DATA23 0x79 + >; + }; + + pinctrl_lcdif_ctrl: lcdifctrlgrp { + fsl,pins = < + MX7D_PAD_LCD_CLK__LCD_CLK 0x79 + MX7D_PAD_LCD_ENABLE__LCD_ENABLE 0x79 + MX7D_PAD_LCD_VSYNC__LCD_VSYNC 0x79 + MX7D_PAD_LCD_HSYNC__LCD_HSYNC 0x79 + >; + }; + + pinctrl_pwm2: pwm2grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO09__PWM2_OUT 0x7d + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79 + MX7D_PAD_UART1_RX_DATA__UART1_DCE_RX 0x79 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX 0x79 + MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 0x79 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX7D_PAD_UART3_TX_DATA__UART3_DCE_TX 0x79 + MX7D_PAD_UART3_RX_DATA__UART3_DCE_RX 0x79 + MX7D_PAD_EPDC_DATA04__GPIO2_IO4 0x7d + >; + }; + + pinctrl_uart6: uart6grp { + fsl,pins = < + MX7D_PAD_ECSPI1_MOSI__UART6_DCE_TX 0x79 + MX7D_PAD_ECSPI1_SCLK__UART6_DCE_RX 0x79 + MX7D_PAD_ECSPI1_SS0__UART6_DCE_CTS 0x79 + MX7D_PAD_ECSPI1_MISO__UART6_DCE_RTS 0x79 + >; + }; + + pinctrl_usbotg2: usbotg2grp { + fsl,pins = < + MX7D_PAD_UART3_RTS_B__USB_OTG2_OC 0x7d + MX7D_PAD_UART3_CTS_B__GPIO4_IO7 0x14 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x59 + MX7D_PAD_SD1_CLK__SD1_CLK 0x19 + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59 + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59 + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59 + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59 + MX7D_PAD_GPIO1_IO08__SD1_VSELECT 0x75 + MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x75 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX7D_PAD_SD2_CMD__SD2_CMD 0x59 + MX7D_PAD_SD2_CLK__SD2_CLK 0x19 + MX7D_PAD_SD2_DATA0__SD2_DATA0 0x59 + MX7D_PAD_SD2_DATA1__SD2_DATA1 0x59 + MX7D_PAD_SD2_DATA2__SD2_DATA2 0x59 + MX7D_PAD_SD2_DATA3__SD2_DATA3 0x59 + MX7D_PAD_ECSPI2_SCLK__GPIO4_IO20 0x59 + MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 0x59 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX7D_PAD_SD3_CMD__SD3_CMD 0x59 + MX7D_PAD_SD3_CLK__SD3_CLK 0x19 + MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59 + MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59 + MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59 + MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59 + MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59 + MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59 + MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59 + MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59 + >; + }; +}; + +&iomuxc_lpsr { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog_2>; + + pinctrl_hog_2: hoggrp-2 { + fsl,pins = < + MX7D_PAD_GPIO1_IO02__GPIO1_IO2 0x7d + MX7D_PAD_GPIO1_IO03__CCM_CLKO2 0x7d + >; + }; + + pinctrl_backlight_j9: backlightj9grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO07__GPIO1_IO7 0x7d + >; + }; + + pinctrl_pwm1: pwm1grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO01__PWM1_OUT 0x7d + >; + }; + + pinctrl_usbotg1: usbotg1grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO04__USB_OTG1_OC 0x7d + MX7D_PAD_GPIO1_IO05__GPIO1_IO5 0x14 + >; + }; + + pinctrl_wdog1: wdog1grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x75 + >; + }; +}; -- GitLab From 1d0fc33f4666f1bd29990f154767aa5d374c9e19 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 4 Apr 2016 22:28:39 -0700 Subject: [PATCH 2436/9938] ARM: dts: vf610: add display nodes Add the dcu and tcon nodes to enable the Display Controller Unit and Timing Controller in Vybrid's SoC level device-tree file. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vfxxx.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 5c0975451d4e..d7d002d0cc5f 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -310,6 +310,14 @@ <20000000>; }; + tcon0: timing-controller@4003d000 { + compatible = "fsl,vf610-tcon"; + reg = <0x4003d000 0x1000>; + clocks = <&clks VF610_CLK_TCON0>; + clock-names = "ipg"; + status = "disabled"; + }; + wdoga5: wdog@4003e000 { compatible = "fsl,vf610-wdt", "fsl,imx21-wdt"; reg = <0x4003e000 0x1000>; @@ -415,6 +423,17 @@ status = "disabled"; }; + dcu0: dcu@40058000 { + compatible = "fsl,vf610-dcu"; + reg = <0x40058000 0x1200>; + interrupts = <30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks VF610_CLK_DCU0>, + <&clks VF610_CLK_DCU0_DIV>; + clock-names = "dcu", "pix"; + fsl,tcon = <&tcon0>; + status = "disabled"; + }; + i2c0: i2c@40066000 { #address-cells = <1>; #size-cells = <0>; -- GitLab From 77f0862d0d6874a73f83032b7ffd6d204fc8646c Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 4 Apr 2016 22:28:40 -0700 Subject: [PATCH 2437/9938] ARM: dts: vf610-colibri: enable display controller Enable dcu node which is used by the DCU DRM driver. Assign the 5.7" EDT panel with VGA resolution which Toradex sells often with the evaluation board. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf-colibri-eval-v3.dtsi | 16 +++++++++++ arch/arm/boot/dts/vf-colibri.dtsi | 33 +++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi index 4d8b7f693535..a8a8e434fb27 100644 --- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi +++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi @@ -50,6 +50,11 @@ clock-frequency = <16000000>; }; + panel: panel { + compatible = "edt,et057090dhu"; + backlight = <&bl>; + }; + reg_3v3: regulator-3v3 { compatible = "regulator-fixed"; regulator-name = "3.3V"; @@ -83,6 +88,13 @@ status = "okay"; }; +&dcu0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dcu0_1>; + fsl,panel = <&panel>; + status = "okay"; +}; + &dspi1 { status = "okay"; @@ -134,6 +146,10 @@ vin-supply = <®_3v3>; }; +&tcon0 { + status = "okay"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi index fda7f28101e1..afcc43d2fa5c 100644 --- a/arch/arm/boot/dts/vf-colibri.dtsi +++ b/arch/arm/boot/dts/vf-colibri.dtsi @@ -219,6 +219,39 @@ >; }; + pinctrl_dcu0_1: dcu0grp_1 { + fsl,pins = < + VF610_PAD_PTE0__DCU0_HSYNC 0x1902 + VF610_PAD_PTE1__DCU0_VSYNC 0x1902 + VF610_PAD_PTE2__DCU0_PCLK 0x1902 + VF610_PAD_PTE4__DCU0_DE 0x1902 + VF610_PAD_PTE5__DCU0_R0 0x1902 + VF610_PAD_PTE6__DCU0_R1 0x1902 + VF610_PAD_PTE7__DCU0_R2 0x1902 + VF610_PAD_PTE8__DCU0_R3 0x1902 + VF610_PAD_PTE9__DCU0_R4 0x1902 + VF610_PAD_PTE10__DCU0_R5 0x1902 + VF610_PAD_PTE11__DCU0_R6 0x1902 + VF610_PAD_PTE12__DCU0_R7 0x1902 + VF610_PAD_PTE13__DCU0_G0 0x1902 + VF610_PAD_PTE14__DCU0_G1 0x1902 + VF610_PAD_PTE15__DCU0_G2 0x1902 + VF610_PAD_PTE16__DCU0_G3 0x1902 + VF610_PAD_PTE17__DCU0_G4 0x1902 + VF610_PAD_PTE18__DCU0_G5 0x1902 + VF610_PAD_PTE19__DCU0_G6 0x1902 + VF610_PAD_PTE20__DCU0_G7 0x1902 + VF610_PAD_PTE21__DCU0_B0 0x1902 + VF610_PAD_PTE22__DCU0_B1 0x1902 + VF610_PAD_PTE23__DCU0_B2 0x1902 + VF610_PAD_PTE24__DCU0_B3 0x1902 + VF610_PAD_PTE25__DCU0_B4 0x1902 + VF610_PAD_PTE26__DCU0_B5 0x1902 + VF610_PAD_PTE27__DCU0_B6 0x1902 + VF610_PAD_PTE28__DCU0_B7 0x1902 + >; + }; + pinctrl_dspi1: dspi1grp { fsl,pins = < VF610_PAD_PTD5__DSPI1_CS0 0x33e2 -- GitLab From 47a541c3e19374ec9f5d3d96730a922e8480dda5 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 1 Apr 2016 17:51:54 -0700 Subject: [PATCH 2438/9938] x86/platform: Remove unused get_bios_ebda_length() function get_bios_ebda_length() uses min_t() without including linux/kernel.h. This may result in build errors with some configurations. Since the function is not used anywhere in the kernel, let's just drop it. Signed-off-by: Guenter Roeck Cc: Linus Torvalds Cc: Mike Waychison Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459558314-5625-1-git-send-email-linux@roeck-us.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bios_ebda.h | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/arch/x86/include/asm/bios_ebda.h b/arch/x86/include/asm/bios_ebda.h index aa6a3170ab5a..2b00c776f223 100644 --- a/arch/x86/include/asm/bios_ebda.h +++ b/arch/x86/include/asm/bios_ebda.h @@ -17,27 +17,6 @@ static inline unsigned int get_bios_ebda(void) return address; /* 0 means none */ } -/* - * Return the sanitized length of the EBDA in bytes, if it exists. - */ -static inline unsigned int get_bios_ebda_length(void) -{ - unsigned int address; - unsigned int length; - - address = get_bios_ebda(); - if (!address) - return 0; - - /* EBDA length is byte 0 of the EBDA (stored in KiB) */ - length = *(unsigned char *)phys_to_virt(address); - length <<= 10; - - /* Trim the length if it extends beyond 640KiB */ - length = min_t(unsigned int, (640 * 1024) - address, length); - return length; -} - void reserve_ebda_region(void); #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION -- GitLab From 5434c913b6cc3339b95140eb9075eb1ca4cb6ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Fri, 4 Mar 2016 13:37:22 +0100 Subject: [PATCH 2439/9938] ARM: dts: imx6ul: add support for Ka-Ro electronics TXUL modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TXUL-0010/-0011 modules are Computers On Module manufactured by Ka-Ro electronics GmbH with the following characteristics: Processor Freescale i.MX 6UltraLite MCIMX6G2, 528 MHz RAM 256MB 16-bit DDR3 SDRAM ROM 128MB NAND Flash (TXUL-0010) / 4GB eMMC (TXUL-0011) Power supply Single 3.3 to 5V Size 26mm SO-DIMM Temp. Range -40°C to 85°C Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 4 +- arch/arm/boot/dts/imx6ul-tx6ul-0010.dts | 53 ++ arch/arm/boot/dts/imx6ul-tx6ul-0011.dts | 68 ++ arch/arm/boot/dts/imx6ul-tx6ul.dtsi | 973 ++++++++++++++++++++++++ 4 files changed, 1097 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul-0010.dts create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul-0011.dts create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..f5daae16a74c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -374,7 +374,9 @@ dtb-$(CONFIG_SOC_IMX6SX) += \ imx6sx-sdb-reva.dtb \ imx6sx-sdb.dtb dtb-$(CONFIG_SOC_IMX6UL) += \ - imx6ul-14x14-evk.dtb + imx6ul-14x14-evk.dtb \ + imx6ul-tx6ul-0010.dtb \ + imx6ul-tx6ul-0011.dtb dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ imx7d-sbc-imx7.dtb \ diff --git a/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts b/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts new file mode 100644 index 000000000000..8c2f3df79b47 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts @@ -0,0 +1,53 @@ +/* + * Copyright 2015 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6ul.dtsi" +#include "imx6ul-tx6ul.dtsi" + +/ { + model = "Ka-Ro electronics TXUL-0010 Module"; + compatible = "karo,imx6ul-tx6ul", "fsl,imx6ul"; + + aliases { + /delete-property/ mmc1; + }; +}; diff --git a/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts b/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts new file mode 100644 index 000000000000..d82698e7d50f --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts @@ -0,0 +1,68 @@ +/* + * Copyright 2015 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6ul.dtsi" +#include "imx6ul-tx6ul.dtsi" + +/ { + model = "Ka-Ro electronics TXUL-0011 Module"; + compatible = "karo,imx6ul-tx6ul", "fsl,imx6ul"; + + aliases { + mmc0 = &usdhc2; + mmc1 = &usdhc1; + }; +}; + +&gpmi { + status = "disabled"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + bus-width = <4>; + no-1-8-v; + non-removable; + fsl,wp-controller; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/imx6ul-tx6ul.dtsi new file mode 100644 index 000000000000..437e9aad5920 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-tx6ul.dtsi @@ -0,0 +1,973 @@ +/* + * Copyright 2015 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +/ { + aliases { + can0 = &can2; + can1 = &can1; + display = &display; + i2c0 = &i2c2; + i2c1 = &i2c_gpio; + i2c2 = &i2c1; + i2c3 = &i2c3; + i2c4 = &i2c4; + lcdif_23bit_pins_a = &pinctrl_disp0_1; + lcdif_24bit_pins_a = &pinctrl_disp0_2; + pwm0 = &pwm5; + reg_can_xcvr = ®_can_xcvr; + serial2 = &uart5; + serial4 = &uart3; + spi0 = &ecspi2; + spi1 = &spi_gpio; + stk5led = &user_led; + usbh1 = &usbotg2; + usbotg = &usbotg1; + }; + + chosen { + stdout-path = &uart1; + }; + + memory { + reg = <0 0>; /* will be filled by U-Boot */ + }; + + clocks { + mclk: mclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd_rst>; + enable-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>; + pwms = <&pwm5 0 500000 PWM_POLARITY_INVERTED>; + power-supply = <®_lcd_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; + + i2c_gpio: i2c-gpio { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c_gpio>; + gpios = < + &gpio5 1 GPIO_ACTIVE_HIGH /* SDA */ + &gpio5 0 GPIO_ACTIVE_HIGH /* SCL */ + >; + clock-frequency = <400000>; + status = "okay"; + + ds1339: rtc@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + status = "disabled"; + }; + }; + + leds { + compatible = "gpio-leds"; + + user_led: user { + label = "Heartbeat"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_led>; + gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_3v3_etn: regulator-3v3etn { + compatible = "regulator-fixed"; + regulator-name = "3V3_ETN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_etnphy_power>; + gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_2v5: regulator-2v5 { + compatible = "regulator-fixed"; + regulator-name = "2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_can_xcvr: regulator-canxcvr { + compatible = "regulator-fixed"; + regulator-name = "CAN XCVR"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan_xcvr>; + gpio = <&gpio3 5 GPIO_ACTIVE_HIGH>; + enable-active-low; + }; + + reg_lcd_pwr: regulator-lcdpwr { + compatible = "regulator-fixed"; + regulator-name = "LCD POWER"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd_pwr>; + gpio = <&gpio5 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + + reg_usbh1_vbus: regulator-usbh1vbus { + compatible = "regulator-fixed"; + regulator-name = "usbh1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh1_vbus &pinctrl_usbh1_oc>; + gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usbotg_vbus: regulator-usbotgvbus { + compatible = "regulator-fixed"; + regulator-name = "usbotg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg_vbus &pinctrl_usbotg_oc>; + gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + spi_gpio: spi-gpio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "spi-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi_gpio>; + gpio-mosi = <&gpio1 30 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio1 31 GPIO_ACTIVE_HIGH>; + gpio-sck = <&gpio1 28 GPIO_ACTIVE_HIGH>; + num-chipselects = <2>; + cs-gpios = < + &gpio1 29 GPIO_ACTIVE_HIGH + &gpio1 10 GPIO_ACTIVE_HIGH + >; + status = "disabled"; + + spi@0 { + compatible = "spidev"; + reg = <0>; + spi-max-frequency = <660000>; + }; + + spi@1 { + compatible = "spidev"; + reg = <1>; + spi-max-frequency = <660000>; + }; + }; + + sound { + compatible = "karo,imx6ul-tx6ul-sgtl5000", + "simple-audio-card"; + simple-audio-card,name = "imx6ul-tx6ul-sgtl5000-audio"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&codec_dai>; + simple-audio-card,frame-master = <&codec_dai>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Line", "Line In", + "Line", "Line Out", + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + + cpu_dai: simple-audio-card,cpu { + sound-dai = <&sai2>; + }; + + codec_dai: simple-audio-card,codec { + sound-dai = <&sgtl5000>; + }; + }; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + xceiver-supply = <®_can_xcvr>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <®_can_xcvr>; + status = "okay"; +}; + +&ecspi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi2>; + fsl,spi-num-chipselects = <2>; + cs-gpios = < + &gpio1 29 GPIO_ACTIVE_HIGH + &gpio1 10 GPIO_ACTIVE_HIGH + >; + status = "disabled"; + + spidev0: spi@0 { + compatible = "spidev"; + reg = <0>; + spi-max-frequency = <60000000>; + }; + + spidev1: spi@1 { + compatible = "spidev"; + reg = <1>; + spi-max-frequency = <60000000>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_mdio &pinctrl_etnphy0_rst>; + phy-mode = "rmii"; + phy-reset-gpios = <&gpio5 6 GPIO_ACTIVE_HIGH>; + phy-supply = <®_3v3_etn>; + phy-handle = <&etnphy0>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + etnphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_etnphy0_int>; + interrupt-parent = <&gpio5>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; + status = "okay"; + }; + + etnphy1: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_etnphy1_int>; + interrupt-parent = <&gpio4>; + interrupts = <27 IRQ_TYPE_EDGE_FALLING>; + status = "okay"; + }; + }; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2 &pinctrl_etnphy1_rst>; + phy-mode = "rmii"; + phy-reset-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>; + phy-supply = <®_3v3_etn>; + phy-handle = <&etnphy1>; + status = "disabled"; +}; + +&gpmi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpmi_nand>; + nand-on-flash-bbt; + fsl,no-blockmark-swap; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + clock-frequency = <400000>; + status = "okay"; + + sgtl5000: codec@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + #sound-dai-cells = <0>; + VDDA-supply = <®_2v5>; + VDDIO-supply = <®_3v3>; + clocks = <&mclk>; + }; + + polytouch: polytouch@38 { + compatible = "edt,edt-ft5x06"; + reg = <0x38>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_edt_ft5x06>; + interrupt-parent = <&gpio5>; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>; + wake-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>; + wakeup-source; + }; + + touchscreen: touchscreen@48 { + compatible = "ti,tsc2007"; + reg = <0x48>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tsc2007>; + interrupt-parent = <&gpio3>; + interrupts = <26 IRQ_TYPE_NONE>; + gpios = <&gpio3 26 GPIO_ACTIVE_LOW>; + ti,x-plate-ohms = <660>; + wakeup-source; + }; +}; + +&kpp { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_kpp>; + /* sample keymap */ + /* row/col 0..3 are mapped to KPP row/col 4..7 */ + linux,keymap = < + MATRIX_KEY(4, 4, KEY_POWER) + MATRIX_KEY(4, 5, KEY_KP0) + MATRIX_KEY(4, 6, KEY_KP1) + MATRIX_KEY(4, 7, KEY_KP2) + MATRIX_KEY(5, 4, KEY_KP3) + MATRIX_KEY(5, 5, KEY_KP4) + MATRIX_KEY(5, 6, KEY_KP5) + MATRIX_KEY(5, 7, KEY_KP6) + MATRIX_KEY(6, 4, KEY_KP7) + MATRIX_KEY(6, 5, KEY_KP8) + MATRIX_KEY(6, 6, KEY_KP9) + >; + status = "okay"; +}; + +&lcdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_disp0_1>; + lcd-supply = <®_lcd_pwr>; + display = <&display>; + status = "okay"; + + display: display@di0 { + bits-per-pixel = <32>; + bus-width = <24>; + status = "okay"; + + display-timings { + VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; +}; + +&pwm5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm5>; + #pwm-cells = <3>; + status = "okay"; +}; + +&sai2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai2>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_rtscts>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2 &pinctrl_uart2_rtscts>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5 &pinctrl_uart5_rtscts>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&usbotg1 { + vbus-supply = <®_usbotg_vbus>; + dr_mode = "peripheral"; + disable-over-current; + status = "okay"; +}; + +&usbotg2 { + vbus-supply = <®_usbh1_vbus>; + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_usdhc1_cd>; + bus-width = <4>; + no-1-8-v; + cd-gpios = <&gpio4 14 GPIO_ACTIVE_LOW>; + fsl,wp-controller; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + }; + + pinctrl_led: ledgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x0b0b0 /* LED */ + >; + }; + + pinctrl_disp0_1: disp0grp-1 { + fsl,pins = < + MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x10 /* LSCLK */ + MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x10 /* OE_ACD */ + MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x10 /* HSYNC */ + MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x10 /* VSYNC */ + /* PAD DISP0_DAT0 is used for the Flexcan transceiver control on STK5-v5 */ + MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x10 + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x10 + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x10 + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x10 + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x10 + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x10 + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x10 + MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x10 + MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x10 + MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x10 + MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x10 + MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x10 + MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x10 + MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x10 + MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x10 + MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x10 + MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x10 + MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x10 + MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x10 + MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x10 + MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x10 + MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x10 + MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x10 + >; + }; + + pinctrl_disp0_2: disp0grp-2 { + fsl,pins = < + MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x10 /* LSCLK */ + MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x10 /* OE_ACD */ + MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x10 /* HSYNC */ + MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x10 /* VSYNC */ + MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x10 + MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x10 + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x10 + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x10 + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x10 + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x10 + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x10 + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x10 + MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x10 + MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x10 + MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x10 + MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x10 + MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x10 + MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x10 + MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x10 + MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x10 + MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x10 + MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x10 + MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x10 + MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x10 + MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x10 + MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x10 + MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x10 + MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x10 + >; + }; + + pinctrl_ecspi2: ecspi2grp { + fsl,pins = < + MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29 0x0b0b0 /* CSPI_SS */ + MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x0b0b0 /* CSPI_SS */ + MX6UL_PAD_UART5_TX_DATA__ECSPI2_MOSI 0x0b0b0 /* CSPI_MOSI */ + MX6UL_PAD_UART5_RX_DATA__ECSPI2_MISO 0x0b0b0 /* CSPI_MISO */ + MX6UL_PAD_UART4_TX_DATA__ECSPI2_SCLK 0x0b0b0 /* CSPI_SCLK */ + >; + }; + + pinctrl_edt_ft5x06: edt-ft5x06grp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0 /* Interrupt */ + MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0b0 /* Reset */ + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1b0b0 /* Wake */ + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x000b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x000b0 + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x000b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x000b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x000b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x000b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x000b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x400000b1 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x000b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x000b0 + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x000b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x000b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x000b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x000b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x000b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x400000b1 + >; + }; + + pinctrl_enet1_mdio: enet1-mdiogrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x0b0b0 + MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0 + >; + }; + + pinctrl_etnphy_power: etnphy-pwrgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x0b0b0 /* ETN PHY POWER */ + >; + }; + + pinctrl_etnphy0_int: etnphy-intgrp-0 { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x0b0b0 /* ETN PHY INT */ + >; + }; + + pinctrl_etnphy0_rst: etnphy-rstgrp-0 { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x0b0b0 /* ETN PHY RESET */ + >; + }; + + pinctrl_etnphy1_int: etnphy-intgrp-1 { + fsl,pins = < + MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x0b0b0 /* ETN PHY INT */ + >; + }; + + pinctrl_etnphy1_rst: etnphy-rstgrp-1 { + fsl,pins = < + MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x0b0b0 /* ETN PHY RESET */ + >; + }; + + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x0b0b0 + MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x0b0b0 + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x0b0b0 + MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x0b0b0 + >; + }; + + pinctrl_flexcan_xcvr: flexcan-xcvrgrp { + fsl,pins = < + MX6UL_PAD_LCD_DATA00__GPIO3_IO05 0x0b0b0 /* Flexcan XCVR enable */ + >; + }; + + pinctrl_gpmi_nand: gpminandgrp { + fsl,pins = < + MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0x0b0b1 + MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0x0b0b1 + MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B 0x0b0b1 + MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0x0b000 + MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B 0x0b0b1 + MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0x0b0b1 + MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0x0b0b1 + MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0x0b0b1 + MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0x0b0b1 + MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0x0b0b1 + MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0x0b0b1 + MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04 0x0b0b1 + MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05 0x0b0b1 + MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06 0x0b0b1 + MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0x0b0b1 + >; + }; + + pinctrl_i2c_gpio: i2c-gpiogrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x4001b8b1 /* I2C SCL */ + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x4001b8b1 /* I2C SDA */ + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__I2C2_SCL 0x4001b8b1 + MX6UL_PAD_GPIO1_IO01__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_kpp: kppgrp { + fsl,pins = < + MX6UL_PAD_ENET2_RX_DATA1__KPP_COL04 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__KPP_COL05 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__KPP_COL06 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__KPP_COL07 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__KPP_ROW04 0x1b0b0 + MX6UL_PAD_ENET2_RX_EN__KPP_ROW05 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__KPP_ROW06 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__KPP_ROW07 0x1b0b0 + >; + }; + + pinctrl_lcd_pwr: lcd-pwrgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x0b0b0 /* LCD Power Enable */ + >; + }; + + pinctrl_lcd_rst: lcd-rstgrp { + fsl,pins = < + MX6UL_PAD_LCD_RESET__GPIO3_IO04 0x0b0b0 /* LCD Reset */ + >; + }; + + pinctrl_pwm5: pwm5grp { + fsl,pins = < + MX6UL_PAD_NAND_DQS__PWM5_OUT 0x0b0b0 + >; + }; + + pinctrl_sai2: sai2grp { + fsl,pins = < + MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x0b0b0 /* SSI1_RXD */ + MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x0b0b0 /* SSI1_TXD */ + MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK 0x0b0b0 /* SSI1_CLK */ + MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x0b0b0 /* SSI1_FS */ + >; + }; + + pinctrl_spi_gpio: spi-gpiogrp { + fsl,pins = < + MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29 0x0b0b0 /* CSPI_SS */ + MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x0b0b0 /* CSPI_SS */ + MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x0b0b0 /* CSPI_MOSI */ + MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31 0x0b0b0 /* CSPI_MISO */ + MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28 0x0b0b0 /* CSPI_SCLK */ + >; + }; + + pinctrl_tsc2007: tsc2007grp { + fsl,pins = < + MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x1b0b0 /* Interrupt */ + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x0b0b0 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x0b0b0 + >; + }; + + pinctrl_uart1_rtscts: uart1-rtsctsgrp { + fsl,pins = < + MX6UL_PAD_UART1_RTS_B__UART1_DCE_RTS 0x0b0b0 + MX6UL_PAD_UART1_CTS_B__UART1_DCE_CTS 0x0b0b0 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x0b0b0 + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x0b0b0 + >; + }; + + pinctrl_uart2_rtscts: uart2-rtsctsgrp { + fsl,pins = < + MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS 0x0b0b0 + MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS 0x0b0b0 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO04__UART5_DCE_TX 0x0b0b0 + MX6UL_PAD_GPIO1_IO05__UART5_DCE_RX 0x0b0b0 + >; + }; + + pinctrl_uart5_rtscts: uart5-rtsctsgrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS 0x0b0b0 + MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS 0x0b0b0 + >; + }; + + pinctrl_usbh1_oc: usbh1-ocgrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x17059 /* USBH1_OC */ + >; + }; + + pinctrl_usbh1_vbus: usbh1-vbusgrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x0b0b0 /* USBH1_VBUSEN */ + >; + }; + + pinctrl_usbotg_oc: usbotg-ocgrp { + fsl,pins = < + MX6UL_PAD_UART3_RTS_B__GPIO1_IO27 0x17059 /* USBOTG_OC */ + >; + }; + + pinctrl_usbotg_vbus: usbotg-vbusgrp { + fsl,pins = < + MX6UL_PAD_UART3_CTS_B__GPIO1_IO26 0x1b0b0 /* USBOTG_VBUSEN */ + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x070b1 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x07099 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x070b1 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x070b1 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x070b1 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x070b1 + >; + }; + + pinctrl_usdhc1_cd: usdhc1cdgrp { + fsl,pins = < + MX6UL_PAD_NAND_CE1_B__GPIO4_IO14 0x170b0 /* SD1 CD */ + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x070b1 + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x070b1 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x070b1 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x070b1 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x070b1 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x070b1 + /* eMMC RESET */ + MX6UL_PAD_NAND_ALE__USDHC2_RESET_B 0x170b0 + >; + }; +}; -- GitLab From cf4534824f8ddea1ac9535b7a465821cd2fbe933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Fri, 4 Mar 2016 13:37:23 +0100 Subject: [PATCH 2440/9938] ARM: dts: imx6ul: add support for Ka-Ro electronics TXUL mainboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts | 271 +++++++++++++++++++ 2 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f5daae16a74c..81e7f92683ff 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -376,7 +376,8 @@ dtb-$(CONFIG_SOC_IMX6SX) += \ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-14x14-evk.dtb \ imx6ul-tx6ul-0010.dtb \ - imx6ul-tx6ul-0011.dtb + imx6ul-tx6ul-0011.dtb \ + imx6ul-tx6ul-mainboard.dtb dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ imx7d-sbc-imx7.dtb \ diff --git a/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts b/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts new file mode 100644 index 000000000000..d25899b71575 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts @@ -0,0 +1,271 @@ +/* + * Copyright 2015 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6ul.dtsi" +#include "imx6ul-tx6ul.dtsi" + +/ { + model = "Ka-Ro electronics TXUL-0010 Module on TXUL Mainboard"; + compatible = "karo,imx6ul-tx6ul", "fsl,imx6ul"; + + aliases { + lcdif_24bit_pins_a = &pinctrl_disp0_3; + mmc0 = &usdhc1; + /delete-property/ mmc1; + serial2 = &uart3; + serial4 = &uart5; + }; + /delete-node/ sound; +}; + +&can1 { + xceiver-supply = <®_3v3>; +}; + +&can2 { + xceiver-supply = <®_3v3>; +}; + +&ds1339 { + status = "disabled"; +}; + +&fec1 { + pinctrl-0 = <&pinctrl_enet1 &pinctrl_etnphy0_rst>; + /delete-node/ mdio; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_mdio &pinctrl_etnphy1_rst>; + phy-mode = "rmii"; + phy-reset-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>; + phy-supply = <®_3v3_etn>; + phy-handle = <&etnphy1>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + etnphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_etnphy0_int>; + interrupt-parent = <&gpio5>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; + interrupts-extended = <&gpio5 5 IRQ_TYPE_EDGE_FALLING>; + status = "okay"; + }; + + etnphy1: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_etnphy1_int>; + interrupt-parent = <&gpio4>; + interrupts = <27 IRQ_TYPE_EDGE_FALLING>; + interrupts-extended = <&gpio4 27 IRQ_TYPE_EDGE_FALLING>; + status = "okay"; + }; + }; +}; + +&i2c_gpio { + status = "disabled"; +}; + +&i2c2 { + /delete-node/ codec@0a; + /delete-node/ touchscreen@48; + + rtc: mcp7940x@6f { + compatible = "microchip,mcp7940x"; + reg = <0x6f>; + }; +}; + +&kpp { + status = "disabled"; +}; + +&lcdif { + pinctrl-0 = <&pinctrl_disp0_3>; +}; + +®_usbotg_vbus{ + status = "disabled"; +}; + +&usdhc1 { + pinctrl-0 = <&pinctrl_usdhc1>; + non-removable; + /delete-property/ cd-gpios; + cap-sdio-irq; +}; + +&uart1 { + pinctrl-0 = <&pinctrl_uart1>; + /delete-property/ fsl,uart-has-rtscts; +}; + +&uart2 { + pinctrl-0 = <&pinctrl_uart2>; + /delete-property/ fsl,uart-has-rtscts; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart6>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart7>; + status = "okay"; +}; + +&uart8 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart8>; + status = "disabled"; /* conflicts with LCDIF */ +}; + +&iomuxc { + hoggrp { + fsl,pins = < + MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x0b0b0 /* WLAN_RESET */ + >; + }; + + pinctrl_disp0_3: disp0grp-3 { + fsl,pins = < + MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x10 /* LSCLK */ + MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x10 /* OE_ACD */ + MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x10 /* HSYNC */ + MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x10 /* VSYNC */ + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x10 + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x10 + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x10 + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x10 + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x10 + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x10 + /* LCD_DATA08..09 not wired */ + MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x10 + MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x10 + MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x10 + MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x10 + MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x10 + MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x10 + /* LCD_DATA16..17 not wired */ + MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x10 + MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x10 + MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x10 + MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x10 + MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x10 + MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x10 + >; + }; + + pinctrl_enet2_mdio: enet2-mdiogrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x0b0b0 + MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x0b0b0 + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x0b0b0 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x0b0b0 + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x0b0b0 + >; + }; + + pinctrl_uart6: uart6grp { + fsl,pins = < + MX6UL_PAD_CSI_MCLK__UART6_DCE_TX 0x0b0b0 + MX6UL_PAD_CSI_PIXCLK__UART6_DCE_RX 0x0b0b0 + >; + }; + + pinctrl_uart7: uart7grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x0b0b0 + MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x0b0b0 + >; + }; + + pinctrl_uart8: uart8grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA20__UART8_DCE_TX 0x0b0b0 + MX6UL_PAD_LCD_DATA21__UART8_DCE_RX 0x0b0b0 + >; + }; +}; -- GitLab From e85225d70831e5b4c2f0fcc928714da68f9ddac3 Mon Sep 17 00:00:00 2001 From: Justin Waters Date: Wed, 2 Mar 2016 11:29:13 -0500 Subject: [PATCH 2441/9938] ARM: dts: imx: ba16: Add correct PCIe Tx Values Utilize the new PCIe Tx configuration to properly support the correct values. Signed-off-by: Justin Waters Signed-off-by: Akshay Bhat Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-ba16.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/imx6q-ba16.dtsi b/arch/arm/boot/dts/imx6q-ba16.dtsi index 8f6e6035f3f7..fcc7b5000511 100644 --- a/arch/arm/boot/dts/imx6q-ba16.dtsi +++ b/arch/arm/boot/dts/imx6q-ba16.dtsi @@ -323,6 +323,8 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcie>; reset-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>; + fsl,tx-swing-full = <103>; + fsl,tx-swing-low = <103>; status = "okay"; }; -- GitLab From 2fcc786bf545f7218412cdc501b34cb98668df6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 9 Mar 2016 20:44:33 +0100 Subject: [PATCH 2442/9938] ARM: dts: imx25-pinfunc: add all UART mux modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apart from a few additions this also contains two fixes where the daisy chain input selection register was missing. Moreover dropped _MUX from some pins for consistency. Signed-off-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-pinfunc.h | 32 +++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/imx25-pinfunc.h b/arch/arm/boot/dts/imx25-pinfunc.h index 848ffa785b63..a050f0f2a57f 100644 --- a/arch/arm/boot/dts/imx25-pinfunc.h +++ b/arch/arm/boot/dts/imx25-pinfunc.h @@ -119,11 +119,11 @@ #define MX25_PAD_NF_CE0__GPIO_3_22 0x05c 0x26c 0x000 0x15 0x000 #define MX25_PAD_ECB__ECB 0x060 0x270 0x000 0x10 0x000 -#define MX25_PAD_ECB__UART5_TXD_MUX 0x060 0x270 0x000 0x13 0x000 +#define MX25_PAD_ECB__UART5_TXD 0x060 0x270 0x000 0x13 0x000 #define MX25_PAD_ECB__GPIO_3_23 0x060 0x270 0x000 0x15 0x000 #define MX25_PAD_LBA__LBA 0x064 0x274 0x000 0x10 0x000 -#define MX25_PAD_LBA__UART5_RXD_MUX 0x064 0x274 0x578 0x13 0x000 +#define MX25_PAD_LBA__UART5_RXD 0x064 0x274 0x578 0x13 0x000 #define MX25_PAD_LBA__GPIO_3_24 0x064 0x274 0x000 0x15 0x000 #define MX25_PAD_BCLK__BCLK 0x068 0x000 0x000 0x00 0x000 @@ -237,17 +237,21 @@ #define MX25_PAD_LD7__GPIO_1_21 0x0e4 0x2dc 0x000 0x15 0x000 #define MX25_PAD_LD8__LD8 0x0e8 0x2e0 0x000 0x10 0x000 +#define MX25_PAD_LD8__UART4_RXD 0x0e8 0x2e0 0x570 0x12 0x000 #define MX25_PAD_LD8__FEC_TX_ERR 0x0e8 0x2e0 0x000 0x15 0x000 #define MX25_PAD_LD8__SDHC2_CMD 0x0e8 0x2e0 0x4e0 0x06 0x000 #define MX25_PAD_LD9__LD9 0x0ec 0x2e4 0x000 0x10 0x000 +#define MX25_PAD_LD9__UART4_TXD 0x0ec 0x2e4 0x000 0x12 0x000 #define MX25_PAD_LD9__FEC_COL 0x0ec 0x2e4 0x504 0x15 0x001 #define MX25_PAD_LD9__SDHC2_CLK 0x0ec 0x2e4 0x4dc 0x06 0x000 #define MX25_PAD_LD10__LD10 0x0f0 0x2e8 0x000 0x10 0x000 +#define MX25_PAD_LD10__UART4_RTS 0x0f0 0x2e8 0x56c 0x12 0x000 #define MX25_PAD_LD10__FEC_RX_ERR 0x0f0 0x2e8 0x518 0x15 0x001 #define MX25_PAD_LD11__LD11 0x0f4 0x2ec 0x000 0x10 0x000 +#define MX25_PAD_LD11__UART4_CTS 0x0f4 0x2ec 0x000 0x12 0x000 #define MX25_PAD_LD11__FEC_RDATA2 0x0f4 0x2ec 0x50c 0x15 0x001 #define MX25_PAD_LD11__SDHC2_DAT1 0x0f4 0x2ec 0x4e8 0x06 0x000 @@ -291,13 +295,13 @@ #define MX25_PAD_PWM__USBH2_OC 0x11c 0x314 0x580 0x16 0x001 #define MX25_PAD_CSI_D2__CSI_D2 0x120 0x318 0x000 0x10 0x000 -#define MX25_PAD_CSI_D2__UART5_RXD_MUX 0x120 0x318 0x578 0x11 0x001 +#define MX25_PAD_CSI_D2__UART5_RXD 0x120 0x318 0x578 0x11 0x001 #define MX25_PAD_CSI_D2__SIM1_CLK0 0x120 0x318 0x000 0x04 0x000 #define MX25_PAD_CSI_D2__GPIO_1_27 0x120 0x318 0x000 0x15 0x000 #define MX25_PAD_CSI_D2__CSPI3_MOSI 0x120 0x318 0x000 0x17 0x000 #define MX25_PAD_CSI_D3__CSI_D3 0x124 0x31c 0x000 0x10 0x000 -#define MX25_PAD_CSI_D3__UART5_TXD_MUX 0x124 0x31c 0x000 0x11 0x000 +#define MX25_PAD_CSI_D3__UART5_TXD 0x124 0x31c 0x000 0x11 0x000 #define MX25_PAD_CSI_D3__SIM1_RST0 0x124 0x31c 0x000 0x04 0x000 #define MX25_PAD_CSI_D3__GPIO_1_28 0x124 0x31c 0x000 0x15 0x000 #define MX25_PAD_CSI_D3__CSPI3_MISO 0x124 0x31c 0x4b4 0x17 0x001 @@ -360,7 +364,7 @@ #define MX25_PAD_I2C1_DAT__GPIO_1_13 0x154 0x34c 0x000 0x15 0x000 #define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI 0x158 0x350 0x000 0x10 0x000 -#define MX25_PAD_CSPI1_MOSI__UART3_RXD 0x158 0x350 0x000 0x12 0x000 +#define MX25_PAD_CSPI1_MOSI__UART3_RXD 0x158 0x350 0x568 0x12 0x000 #define MX25_PAD_CSPI1_MOSI__GPIO_1_14 0x158 0x350 0x000 0x15 0x000 #define MX25_PAD_CSPI1_MISO__CSPI1_MISO 0x15c 0x354 0x000 0x10 0x000 @@ -384,18 +388,22 @@ #define MX25_PAD_CSPI1_RDY__GPIO_2_22 0x16c 0x364 0x000 0x15 0x000 #define MX25_PAD_UART1_RXD__UART1_RXD 0x170 0x368 0x000 0x10 0x000 +#define MX25_PAD_UART1_RXD__UART2_DTR 0x170 0x368 0x000 0x13 0x000 #define MX25_PAD_UART1_RXD__GPIO_4_22 0x170 0x368 0x000 0x15 0x000 #define MX25_PAD_UART1_TXD__UART1_TXD 0x174 0x36c 0x000 0x10 0x000 +#define MX25_PAD_UART1_TXD__UART2_DSR 0x174 0x36c 0x000 0x13 0x000 #define MX25_PAD_UART1_TXD__GPIO_4_23 0x174 0x36c 0x000 0x15 0x000 #define MX25_PAD_UART1_RTS__UART1_RTS 0x178 0x370 0x000 0x10 0x000 #define MX25_PAD_UART1_RTS__CSI_D0 0x178 0x370 0x488 0x11 0x001 #define MX25_PAD_UART1_RTS__CC3 0x178 0x370 0x000 0x12 0x000 +#define MX25_PAD_UART1_RTS__UART2_DCD 0x178 0x370 0x000 0x13 0x000 #define MX25_PAD_UART1_RTS__GPIO_4_24 0x178 0x370 0x000 0x15 0x000 #define MX25_PAD_UART1_CTS__UART1_CTS 0x17c 0x374 0x000 0x10 0x000 #define MX25_PAD_UART1_CTS__CSI_D1 0x17c 0x374 0x48c 0x11 0x001 +#define MX25_PAD_UART1_CTS__UART2_RI 0x17c 0x374 0x000 0x13 0x001 #define MX25_PAD_UART1_CTS__GPIO_4_25 0x17c 0x374 0x000 0x15 0x000 #define MX25_PAD_UART2_RXD__UART2_RXD 0x180 0x378 0x000 0x10 0x000 @@ -440,33 +448,39 @@ #define MX25_PAD_SD1_DATA3__GPIO_2_28 0x1a4 0x39c 0x000 0x15 0x000 #define MX25_PAD_KPP_ROW0__KPP_ROW0 0x1a8 0x3a0 0x000 0x10 0x000 +#define MX25_PAD_KPP_ROW0__UART3_RXD 0x1a8 0x3a0 0x568 0x11 0x001 #define MX25_PAD_KPP_ROW0__UART1_DTR 0x1a8 0x3a0 0x000 0x14 0x000 #define MX25_PAD_KPP_ROW0__GPIO_2_29 0x1a8 0x3a0 0x000 0x15 0x000 #define MX25_PAD_KPP_ROW1__KPP_ROW1 0x1ac 0x3a4 0x000 0x10 0x000 +#define MX25_PAD_KPP_ROW1__UART3_TXD 0x1ac 0x3a4 0x000 0x11 0x000 +#define MX25_PAD_KPP_ROW1__UART1_DSR 0x1ac 0x3a4 0x000 0x14 0x000 #define MX25_PAD_KPP_ROW1__GPIO_2_30 0x1ac 0x3a4 0x000 0x15 0x000 #define MX25_PAD_KPP_ROW2__KPP_ROW2 0x1b0 0x3a8 0x000 0x10 0x000 +#define MX25_PAD_KPP_ROW2__UART3_RTS 0x1b0 0x3a8 0x000 0x11 0x000 #define MX25_PAD_KPP_ROW2__CSI_D0 0x1b0 0x3a8 0x488 0x13 0x002 #define MX25_PAD_KPP_ROW2__UART1_DCD 0x1b0 0x3a8 0x000 0x14 0x000 #define MX25_PAD_KPP_ROW2__GPIO_2_31 0x1b0 0x3a8 0x000 0x15 0x000 #define MX25_PAD_KPP_ROW3__KPP_ROW3 0x1b4 0x3ac 0x000 0x10 0x000 +#define MX25_PAD_KPP_ROW3__UART3_CTS 0x1b4 0x3ac 0x000 0x11 0x000 #define MX25_PAD_KPP_ROW3__CSI_D1 0x1b4 0x3ac 0x48c 0x13 0x002 +#define MX25_PAD_KPP_ROW3__UART1_RI 0x1b4 0x3ac 0x000 0x14 0x000 #define MX25_PAD_KPP_ROW3__GPIO_3_0 0x1b4 0x3ac 0x000 0x15 0x000 #define MX25_PAD_KPP_COL0__KPP_COL0 0x1b8 0x3b0 0x000 0x10 0x000 -#define MX25_PAD_KPP_COL0__UART4_RXD_MUX 0x1b8 0x3b0 0x570 0x11 0x001 +#define MX25_PAD_KPP_COL0__UART4_RXD 0x1b8 0x3b0 0x570 0x11 0x001 #define MX25_PAD_KPP_COL0__AUD5_TXD 0x1b8 0x3b0 0x000 0x12 0x000 #define MX25_PAD_KPP_COL0__GPIO_3_1 0x1b8 0x3b0 0x000 0x15 0x000 #define MX25_PAD_KPP_COL1__KPP_COL1 0x1bc 0x3b4 0x000 0x10 0x000 -#define MX25_PAD_KPP_COL1__UART4_TXD_MUX 0x1bc 0x3b4 0x000 0x11 0x000 +#define MX25_PAD_KPP_COL1__UART4_TXD 0x1bc 0x3b4 0x000 0x11 0x000 #define MX25_PAD_KPP_COL1__AUD5_RXD 0x1bc 0x3b4 0x000 0x12 0x000 #define MX25_PAD_KPP_COL1__GPIO_3_2 0x1bc 0x3b4 0x000 0x15 0x000 #define MX25_PAD_KPP_COL2__KPP_COL2 0x1c0 0x3b8 0x000 0x10 0x000 -#define MX25_PAD_KPP_COL2__UART4_RTS 0x1c0 0x3b8 0x000 0x11 0x000 +#define MX25_PAD_KPP_COL2__UART4_RTS 0x1c0 0x3b8 0x56c 0x11 0x001 #define MX25_PAD_KPP_COL2__AUD5_TXC 0x1c0 0x3b8 0x000 0x12 0x000 #define MX25_PAD_KPP_COL2__GPIO_3_3 0x1c0 0x3b8 0x000 0x15 0x000 @@ -560,6 +574,7 @@ #define MX25_PAD_VSTBY_REQ__VSTBY_REQ 0x214 0x408 0x000 0x10 0x000 #define MX25_PAD_VSTBY_REQ__AUD7_TXFS 0x214 0x408 0x000 0x14 0x000 #define MX25_PAD_VSTBY_REQ__GPIO_3_17 0x214 0x408 0x000 0x15 0x000 +#define MX25_PAD_VSTBY_REQ__UART4_RTS 0x214 0x408 0x56c 0x16 0x002 #define MX25_PAD_VSTBY_ACK__VSTBY_ACK 0x218 0x40c 0x000 0x10 0x000 #define MX25_PAD_VSTBY_ACK__GPIO_3_18 0x218 0x40c 0x000 0x15 0x000 @@ -567,6 +582,7 @@ #define MX25_PAD_POWER_FAIL__POWER_FAIL 0x21c 0x410 0x000 0x10 0x000 #define MX25_PAD_POWER_FAIL__AUD7_RXD 0x21c 0x410 0x478 0x14 0x001 #define MX25_PAD_POWER_FAIL__GPIO_3_19 0x21c 0x410 0x000 0x15 0x000 +#define MX25_PAD_POWER_FAIL__UART4_CTS 0x21c 0x410 0x000 0x16 0x000 #define MX25_PAD_CLKO__CLKO 0x220 0x414 0x000 0x10 0x000 #define MX25_PAD_CLKO__GPIO_2_21 0x220 0x414 0x000 0x15 0x000 -- GitLab From 78e62436d552c9a3127916efaca185ac3c9bd593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 9 Mar 2016 20:44:34 +0100 Subject: [PATCH 2443/9938] ARM: dts: imx25-pinfunc: remove SION for pins with an UART handshaking input mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With SION set the level on such a pin is reported to the UART. So for example when the CS5 pin is configured for GPIO mode and the level changes this triggers an RTS interrupt on uart5. Adding some severity to this issue: The imx uart driver currently doesn't handle correctly irqs for changes on RI and DCD which are enabled automatically when the respective UART is driven in DTE mode (that is, has the fsl,dte-mode property set in the device tree). This results in a stuck machine because the irq isn't cleared and so stalls the CPU. Signed-off-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-pinfunc.h | 118 +++++++++++++++--------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/arch/arm/boot/dts/imx25-pinfunc.h b/arch/arm/boot/dts/imx25-pinfunc.h index a050f0f2a57f..f96fa2df8f11 100644 --- a/arch/arm/boot/dts/imx25-pinfunc.h +++ b/arch/arm/boot/dts/imx25-pinfunc.h @@ -110,10 +110,10 @@ #define MX25_PAD_CS4__UART5_CTS 0x054 0x264 0x000 0x13 0x000 #define MX25_PAD_CS4__GPIO_3_20 0x054 0x264 0x000 0x15 0x000 -#define MX25_PAD_CS5__CS5 0x058 0x268 0x000 0x10 0x000 +#define MX25_PAD_CS5__CS5 0x058 0x268 0x000 0x00 0x000 #define MX25_PAD_CS5__NF_CE2 0x058 0x268 0x000 0x01 0x000 -#define MX25_PAD_CS5__UART5_RTS 0x058 0x268 0x574 0x13 0x000 -#define MX25_PAD_CS5__GPIO_3_21 0x058 0x268 0x000 0x15 0x000 +#define MX25_PAD_CS5__UART5_RTS 0x058 0x268 0x574 0x03 0x000 +#define MX25_PAD_CS5__GPIO_3_21 0x058 0x268 0x000 0x05 0x000 #define MX25_PAD_NF_CE0__NF_CE0 0x05c 0x26c 0x000 0x10 0x000 #define MX25_PAD_NF_CE0__GPIO_3_22 0x05c 0x26c 0x000 0x15 0x000 @@ -246,9 +246,9 @@ #define MX25_PAD_LD9__FEC_COL 0x0ec 0x2e4 0x504 0x15 0x001 #define MX25_PAD_LD9__SDHC2_CLK 0x0ec 0x2e4 0x4dc 0x06 0x000 -#define MX25_PAD_LD10__LD10 0x0f0 0x2e8 0x000 0x10 0x000 -#define MX25_PAD_LD10__UART4_RTS 0x0f0 0x2e8 0x56c 0x12 0x000 -#define MX25_PAD_LD10__FEC_RX_ERR 0x0f0 0x2e8 0x518 0x15 0x001 +#define MX25_PAD_LD10__LD10 0x0f0 0x2e8 0x000 0x00 0x000 +#define MX25_PAD_LD10__UART4_RTS 0x0f0 0x2e8 0x56c 0x02 0x000 +#define MX25_PAD_LD10__FEC_RX_ERR 0x0f0 0x2e8 0x518 0x05 0x001 #define MX25_PAD_LD11__LD11 0x0f4 0x2ec 0x000 0x10 0x000 #define MX25_PAD_LD11__UART4_CTS 0x0f4 0x2ec 0x000 0x12 0x000 @@ -306,11 +306,11 @@ #define MX25_PAD_CSI_D3__GPIO_1_28 0x124 0x31c 0x000 0x15 0x000 #define MX25_PAD_CSI_D3__CSPI3_MISO 0x124 0x31c 0x4b4 0x17 0x001 -#define MX25_PAD_CSI_D4__CSI_D4 0x128 0x320 0x000 0x10 0x000 -#define MX25_PAD_CSI_D4__UART5_RTS 0x128 0x320 0x574 0x11 0x001 +#define MX25_PAD_CSI_D4__CSI_D4 0x128 0x320 0x000 0x00 0x000 +#define MX25_PAD_CSI_D4__UART5_RTS 0x128 0x320 0x574 0x01 0x001 #define MX25_PAD_CSI_D4__SIM1_VEN0 0x128 0x320 0x000 0x04 0x000 -#define MX25_PAD_CSI_D4__GPIO_1_29 0x128 0x320 0x000 0x15 0x000 -#define MX25_PAD_CSI_D4__CSPI3_SCLK 0x128 0x320 0x000 0x17 0x000 +#define MX25_PAD_CSI_D4__GPIO_1_29 0x128 0x320 0x000 0x05 0x000 +#define MX25_PAD_CSI_D4__CSPI3_SCLK 0x128 0x320 0x000 0x07 0x000 #define MX25_PAD_CSI_D5__CSI_D5 0x12c 0x324 0x000 0x10 0x000 #define MX25_PAD_CSI_D5__UART5_CTS 0x12c 0x324 0x000 0x11 0x000 @@ -375,10 +375,10 @@ #define MX25_PAD_CSPI1_SS0__PWM2_PWMO 0x160 0x358 0x000 0x12 0x000 #define MX25_PAD_CSPI1_SS0__GPIO_1_16 0x160 0x358 0x000 0x15 0x000 -#define MX25_PAD_CSPI1_SS1__CSPI1_SS1 0x164 0x35c 0x000 0x10 0x000 -#define MX25_PAD_CSPI1_SS1__I2C3_DAT 0x164 0x35C 0x528 0x11 0x001 -#define MX25_PAD_CSPI1_SS1__UART3_RTS 0x164 0x35c 0x000 0x12 0x000 -#define MX25_PAD_CSPI1_SS1__GPIO_1_17 0x164 0x35c 0x000 0x15 0x000 +#define MX25_PAD_CSPI1_SS1__CSPI1_SS1 0x164 0x35c 0x000 0x00 0x000 +#define MX25_PAD_CSPI1_SS1__I2C3_DAT 0x164 0x35C 0x528 0x01 0x001 +#define MX25_PAD_CSPI1_SS1__UART3_RTS 0x164 0x35c 0x000 0x02 0x000 +#define MX25_PAD_CSPI1_SS1__GPIO_1_17 0x164 0x35c 0x000 0x05 0x000 #define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK 0x168 0x360 0x000 0x10 0x000 #define MX25_PAD_CSPI1_SCLK__UART3_CTS 0x168 0x360 0x000 0x12 0x000 @@ -387,24 +387,24 @@ #define MX25_PAD_CSPI1_RDY__CSPI1_RDY 0x16c 0x364 0x000 0x10 0x000 #define MX25_PAD_CSPI1_RDY__GPIO_2_22 0x16c 0x364 0x000 0x15 0x000 -#define MX25_PAD_UART1_RXD__UART1_RXD 0x170 0x368 0x000 0x10 0x000 -#define MX25_PAD_UART1_RXD__UART2_DTR 0x170 0x368 0x000 0x13 0x000 -#define MX25_PAD_UART1_RXD__GPIO_4_22 0x170 0x368 0x000 0x15 0x000 +#define MX25_PAD_UART1_RXD__UART1_RXD 0x170 0x368 0x000 0x00 0x000 +#define MX25_PAD_UART1_RXD__UART2_DTR 0x170 0x368 0x000 0x03 0x000 +#define MX25_PAD_UART1_RXD__GPIO_4_22 0x170 0x368 0x000 0x05 0x000 -#define MX25_PAD_UART1_TXD__UART1_TXD 0x174 0x36c 0x000 0x10 0x000 -#define MX25_PAD_UART1_TXD__UART2_DSR 0x174 0x36c 0x000 0x13 0x000 -#define MX25_PAD_UART1_TXD__GPIO_4_23 0x174 0x36c 0x000 0x15 0x000 +#define MX25_PAD_UART1_TXD__UART1_TXD 0x174 0x36c 0x000 0x00 0x000 +#define MX25_PAD_UART1_TXD__UART2_DSR 0x174 0x36c 0x000 0x03 0x000 +#define MX25_PAD_UART1_TXD__GPIO_4_23 0x174 0x36c 0x000 0x05 0x000 -#define MX25_PAD_UART1_RTS__UART1_RTS 0x178 0x370 0x000 0x10 0x000 -#define MX25_PAD_UART1_RTS__CSI_D0 0x178 0x370 0x488 0x11 0x001 -#define MX25_PAD_UART1_RTS__CC3 0x178 0x370 0x000 0x12 0x000 -#define MX25_PAD_UART1_RTS__UART2_DCD 0x178 0x370 0x000 0x13 0x000 -#define MX25_PAD_UART1_RTS__GPIO_4_24 0x178 0x370 0x000 0x15 0x000 +#define MX25_PAD_UART1_RTS__UART1_RTS 0x178 0x370 0x000 0x00 0x000 +#define MX25_PAD_UART1_RTS__CSI_D0 0x178 0x370 0x488 0x01 0x001 +#define MX25_PAD_UART1_RTS__CC3 0x178 0x370 0x000 0x02 0x000 +#define MX25_PAD_UART1_RTS__UART2_DCD 0x178 0x370 0x000 0x03 0x000 +#define MX25_PAD_UART1_RTS__GPIO_4_24 0x178 0x370 0x000 0x05 0x000 -#define MX25_PAD_UART1_CTS__UART1_CTS 0x17c 0x374 0x000 0x10 0x000 -#define MX25_PAD_UART1_CTS__CSI_D1 0x17c 0x374 0x48c 0x11 0x001 -#define MX25_PAD_UART1_CTS__UART2_RI 0x17c 0x374 0x000 0x13 0x001 -#define MX25_PAD_UART1_CTS__GPIO_4_25 0x17c 0x374 0x000 0x15 0x000 +#define MX25_PAD_UART1_CTS__UART1_CTS 0x17c 0x374 0x000 0x00 0x000 +#define MX25_PAD_UART1_CTS__CSI_D1 0x17c 0x374 0x48c 0x01 0x001 +#define MX25_PAD_UART1_CTS__UART2_RI 0x17c 0x374 0x000 0x03 0x001 +#define MX25_PAD_UART1_CTS__GPIO_4_25 0x17c 0x374 0x000 0x05 0x000 #define MX25_PAD_UART2_RXD__UART2_RXD 0x180 0x378 0x000 0x10 0x000 #define MX25_PAD_UART2_RXD__GPIO_4_26 0x180 0x378 0x000 0x15 0x000 @@ -412,10 +412,10 @@ #define MX25_PAD_UART2_TXD__UART2_TXD 0x184 0x37c 0x000 0x10 0x000 #define MX25_PAD_UART2_TXD__GPIO_4_27 0x184 0x37c 0x000 0x15 0x000 -#define MX25_PAD_UART2_RTS__UART2_RTS 0x188 0x380 0x000 0x10 0x000 -#define MX25_PAD_UART2_RTS__FEC_COL 0x188 0x380 0x504 0x12 0x002 -#define MX25_PAD_UART2_RTS__CC1 0x188 0x380 0x000 0x13 0x000 -#define MX25_PAD_UART2_RTS__GPIO_4_28 0x188 0x380 0x000 0x15 0x000 +#define MX25_PAD_UART2_RTS__UART2_RTS 0x188 0x380 0x000 0x00 0x000 +#define MX25_PAD_UART2_RTS__FEC_COL 0x188 0x380 0x504 0x02 0x002 +#define MX25_PAD_UART2_RTS__CC1 0x188 0x380 0x000 0x03 0x000 +#define MX25_PAD_UART2_RTS__GPIO_4_28 0x188 0x380 0x000 0x05 0x000 #define MX25_PAD_UART2_CTS__UART2_CTS 0x18c 0x384 0x000 0x10 0x000 #define MX25_PAD_UART2_CTS__FEC_RX_ERR 0x18c 0x384 0x518 0x12 0x002 @@ -447,27 +447,27 @@ #define MX25_PAD_SD1_DATA3__FEC_CRS 0x1a4 0x39c 0x508 0x12 0x002 #define MX25_PAD_SD1_DATA3__GPIO_2_28 0x1a4 0x39c 0x000 0x15 0x000 -#define MX25_PAD_KPP_ROW0__KPP_ROW0 0x1a8 0x3a0 0x000 0x10 0x000 -#define MX25_PAD_KPP_ROW0__UART3_RXD 0x1a8 0x3a0 0x568 0x11 0x001 -#define MX25_PAD_KPP_ROW0__UART1_DTR 0x1a8 0x3a0 0x000 0x14 0x000 -#define MX25_PAD_KPP_ROW0__GPIO_2_29 0x1a8 0x3a0 0x000 0x15 0x000 +#define MX25_PAD_KPP_ROW0__KPP_ROW0 0x1a8 0x3a0 0x000 0x00 0x000 +#define MX25_PAD_KPP_ROW0__UART3_RXD 0x1a8 0x3a0 0x568 0x01 0x001 +#define MX25_PAD_KPP_ROW0__UART1_DTR 0x1a8 0x3a0 0x000 0x04 0x000 +#define MX25_PAD_KPP_ROW0__GPIO_2_29 0x1a8 0x3a0 0x000 0x05 0x000 -#define MX25_PAD_KPP_ROW1__KPP_ROW1 0x1ac 0x3a4 0x000 0x10 0x000 -#define MX25_PAD_KPP_ROW1__UART3_TXD 0x1ac 0x3a4 0x000 0x11 0x000 -#define MX25_PAD_KPP_ROW1__UART1_DSR 0x1ac 0x3a4 0x000 0x14 0x000 -#define MX25_PAD_KPP_ROW1__GPIO_2_30 0x1ac 0x3a4 0x000 0x15 0x000 +#define MX25_PAD_KPP_ROW1__KPP_ROW1 0x1ac 0x3a4 0x000 0x00 0x000 +#define MX25_PAD_KPP_ROW1__UART3_TXD 0x1ac 0x3a4 0x000 0x01 0x000 +#define MX25_PAD_KPP_ROW1__UART1_DSR 0x1ac 0x3a4 0x000 0x04 0x000 +#define MX25_PAD_KPP_ROW1__GPIO_2_30 0x1ac 0x3a4 0x000 0x05 0x000 -#define MX25_PAD_KPP_ROW2__KPP_ROW2 0x1b0 0x3a8 0x000 0x10 0x000 -#define MX25_PAD_KPP_ROW2__UART3_RTS 0x1b0 0x3a8 0x000 0x11 0x000 -#define MX25_PAD_KPP_ROW2__CSI_D0 0x1b0 0x3a8 0x488 0x13 0x002 -#define MX25_PAD_KPP_ROW2__UART1_DCD 0x1b0 0x3a8 0x000 0x14 0x000 -#define MX25_PAD_KPP_ROW2__GPIO_2_31 0x1b0 0x3a8 0x000 0x15 0x000 +#define MX25_PAD_KPP_ROW2__KPP_ROW2 0x1b0 0x3a8 0x000 0x00 0x000 +#define MX25_PAD_KPP_ROW2__UART3_RTS 0x1b0 0x3a8 0x000 0x01 0x000 +#define MX25_PAD_KPP_ROW2__CSI_D0 0x1b0 0x3a8 0x488 0x03 0x002 +#define MX25_PAD_KPP_ROW2__UART1_DCD 0x1b0 0x3a8 0x000 0x04 0x000 +#define MX25_PAD_KPP_ROW2__GPIO_2_31 0x1b0 0x3a8 0x000 0x05 0x000 -#define MX25_PAD_KPP_ROW3__KPP_ROW3 0x1b4 0x3ac 0x000 0x10 0x000 -#define MX25_PAD_KPP_ROW3__UART3_CTS 0x1b4 0x3ac 0x000 0x11 0x000 -#define MX25_PAD_KPP_ROW3__CSI_D1 0x1b4 0x3ac 0x48c 0x13 0x002 -#define MX25_PAD_KPP_ROW3__UART1_RI 0x1b4 0x3ac 0x000 0x14 0x000 -#define MX25_PAD_KPP_ROW3__GPIO_3_0 0x1b4 0x3ac 0x000 0x15 0x000 +#define MX25_PAD_KPP_ROW3__KPP_ROW3 0x1b4 0x3ac 0x000 0x00 0x000 +#define MX25_PAD_KPP_ROW3__UART3_CTS 0x1b4 0x3ac 0x000 0x01 0x000 +#define MX25_PAD_KPP_ROW3__CSI_D1 0x1b4 0x3ac 0x48c 0x03 0x002 +#define MX25_PAD_KPP_ROW3__UART1_RI 0x1b4 0x3ac 0x000 0x04 0x000 +#define MX25_PAD_KPP_ROW3__GPIO_3_0 0x1b4 0x3ac 0x000 0x05 0x000 #define MX25_PAD_KPP_COL0__KPP_COL0 0x1b8 0x3b0 0x000 0x10 0x000 #define MX25_PAD_KPP_COL0__UART4_RXD 0x1b8 0x3b0 0x570 0x11 0x001 @@ -479,10 +479,10 @@ #define MX25_PAD_KPP_COL1__AUD5_RXD 0x1bc 0x3b4 0x000 0x12 0x000 #define MX25_PAD_KPP_COL1__GPIO_3_2 0x1bc 0x3b4 0x000 0x15 0x000 -#define MX25_PAD_KPP_COL2__KPP_COL2 0x1c0 0x3b8 0x000 0x10 0x000 -#define MX25_PAD_KPP_COL2__UART4_RTS 0x1c0 0x3b8 0x56c 0x11 0x001 -#define MX25_PAD_KPP_COL2__AUD5_TXC 0x1c0 0x3b8 0x000 0x12 0x000 -#define MX25_PAD_KPP_COL2__GPIO_3_3 0x1c0 0x3b8 0x000 0x15 0x000 +#define MX25_PAD_KPP_COL2__KPP_COL2 0x1c0 0x3b8 0x000 0x00 0x000 +#define MX25_PAD_KPP_COL2__UART4_RTS 0x1c0 0x3b8 0x56c 0x01 0x001 +#define MX25_PAD_KPP_COL2__AUD5_TXC 0x1c0 0x3b8 0x000 0x02 0x000 +#define MX25_PAD_KPP_COL2__GPIO_3_3 0x1c0 0x3b8 0x000 0x05 0x000 #define MX25_PAD_KPP_COL3__KPP_COL3 0x1c4 0x3bc 0x000 0x10 0x000 #define MX25_PAD_KPP_COL3__UART4_CTS 0x1c4 0x3bc 0x000 0x11 0x000 @@ -571,10 +571,10 @@ #define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK 0x210 0x000 0x000 0x10 0x000 #define MX25_PAD_UPLL_BYPCLK__GPIO_3_16 0x210 0x000 0x000 0x15 0x000 -#define MX25_PAD_VSTBY_REQ__VSTBY_REQ 0x214 0x408 0x000 0x10 0x000 -#define MX25_PAD_VSTBY_REQ__AUD7_TXFS 0x214 0x408 0x000 0x14 0x000 -#define MX25_PAD_VSTBY_REQ__GPIO_3_17 0x214 0x408 0x000 0x15 0x000 -#define MX25_PAD_VSTBY_REQ__UART4_RTS 0x214 0x408 0x56c 0x16 0x002 +#define MX25_PAD_VSTBY_REQ__VSTBY_REQ 0x214 0x408 0x000 0x00 0x000 +#define MX25_PAD_VSTBY_REQ__AUD7_TXFS 0x214 0x408 0x000 0x04 0x000 +#define MX25_PAD_VSTBY_REQ__GPIO_3_17 0x214 0x408 0x000 0x05 0x000 +#define MX25_PAD_VSTBY_REQ__UART4_RTS 0x214 0x408 0x56c 0x06 0x002 #define MX25_PAD_VSTBY_ACK__VSTBY_ACK 0x218 0x40c 0x000 0x10 0x000 #define MX25_PAD_VSTBY_ACK__GPIO_3_18 0x218 0x40c 0x000 0x15 0x000 -- GitLab From e06dd63024a70316318bc737a601ea0c93d07f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Tue, 8 Mar 2016 09:03:57 +0100 Subject: [PATCH 2444/9938] ARM: dts: imx6-tx6: Relicense the Ka-Ro DT files under GPLv2/X11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPLv2-only devicetrees make reuse difficult for software components licensed under a different license. The consensus is that a GPL/X11 dual-license should allow all necessary uses, so relicense the imx6*-tx6* files to this combination. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6dl-tx6u-801x.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6dl-tx6u-811x.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6q-tx6q-1010.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6q-tx6q-1020.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6q-tx6q-1110.dts | 42 +++++++++++++++++--- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 42 +++++++++++++++++--- 9 files changed, 324 insertions(+), 54 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts b/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts index 913bb9a0466a..063fe7510da5 100644 --- a/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts +++ b/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6dl-tx6u-801x.dts b/arch/arm/boot/dts/imx6dl-tx6u-801x.dts index 5fe465c2814e..b7a72840b7f0 100644 --- a/arch/arm/boot/dts/imx6dl-tx6u-801x.dts +++ b/arch/arm/boot/dts/imx6dl-tx6u-801x.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6dl-tx6u-811x.dts b/arch/arm/boot/dts/imx6dl-tx6u-811x.dts index d35a5cdc3229..a1b755a8fc96 100644 --- a/arch/arm/boot/dts/imx6dl-tx6u-811x.dts +++ b/arch/arm/boot/dts/imx6dl-tx6u-811x.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts b/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts index b18fae10b2e3..65e95ae7509a 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010.dts b/arch/arm/boot/dts/imx6q-tx6q-1010.dts index b58ec9c966c8..20cd0e7b3e21 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1010.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1010.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts index 0bb9a9de62a9..19231a08191e 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020.dts b/arch/arm/boot/dts/imx6q-tx6q-1020.dts index b96d80a35d39..4217282b12ea 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1020.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1020.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1110.dts b/arch/arm/boot/dts/imx6q-tx6q-1110.dts index 2792da93db1f..45ceee77a23e 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1110.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1110.dts @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index efd06b576f1d..5d348d9edc1e 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -1,12 +1,42 @@ /* - * Copyright 2014 Lothar Waßmann + * Copyright 2014-2016 Lothar Waßmann * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include -- GitLab From abe3e2b9025068c36b0cf5091464545071c3fcfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Tue, 8 Mar 2016 09:03:58 +0100 Subject: [PATCH 2445/9938] ARM: dts: imx6-tx6: cleanup; no functional change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an empty line between properties and subnode in the clocks node. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index 5d348d9edc1e..912f28406cb9 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -67,6 +67,7 @@ clocks { #address-cells = <1>; #size-cells = <0>; + mclk: clock@0 { compatible = "fixed-clock"; reg = <0>; -- GitLab From 0fd646d0e7dff4054cb43f4ac87271da6151a070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Tue, 8 Mar 2016 09:04:00 +0100 Subject: [PATCH 2446/9938] ARM: dts: imx6-tx6: disable the spi node by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spidev driver doesn't like to be instantiated via a naked 'spidev' compatible, though it is very convenient to invoke it this way without a dedicated SPI device for basic functional testing. Disable the spi node by default to silence the WARN_ON() from the spidev driver, but leave the configuration intact otherwise. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index 912f28406cb9..371a38026bc4 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -240,7 +240,7 @@ &gpio2 30 GPIO_ACTIVE_HIGH &gpio3 19 GPIO_ACTIVE_HIGH >; - status = "okay"; + status = "disabled"; spidev0: spi@0 { compatible = "spidev"; -- GitLab From c4aca663aebf2d1de3e7b6ab15680bf67ad0d678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Tue, 8 Mar 2016 09:04:01 +0100 Subject: [PATCH 2447/9938] ARM: dts: imx6-tx6: remove container node around pinctrl nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the function node around the pinctrl nodes that was obsoleted by commit 5fcdf6a7ed95 ("pinctrl: imx: Allow parsing DT without function nodes"), we can save this container node. Also move the iomux node to the bottom of the file to improve readability of the file. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl-tx6u-811x.dts | 18 +- arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts | 30 +- arch/arm/boot/dts/imx6q-tx6q-1020.dts | 30 +- arch/arm/boot/dts/imx6q-tx6q-1110.dts | 18 +- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 551 ++++++++++--------- 5 files changed, 321 insertions(+), 326 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl-tx6u-811x.dts b/arch/arm/boot/dts/imx6dl-tx6u-811x.dts index a1b755a8fc96..5e0c6bb49f37 100644 --- a/arch/arm/boot/dts/imx6dl-tx6u-811x.dts +++ b/arch/arm/boot/dts/imx6dl-tx6u-811x.dts @@ -111,16 +111,6 @@ }; }; -&iomuxc { - imx6dl-tx6u-811x { - pinctrl_eeti: eetigrp { - fsl,pins = < - MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */ - >; - }; - }; -}; - &kpp { status = "disabled"; /* pad conflict with backlight1 PWM */ }; @@ -178,3 +168,11 @@ &pwm1 { status = "okay"; }; + +&iomuxc { + pinctrl_eeti: eetigrp { + fsl,pins = < + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */ + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts index 19231a08191e..9ed243b704ff 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts @@ -124,22 +124,6 @@ status = "disabled"; }; -&iomuxc { - imx6qdl-tx6 { - pinctrl_usdhc4: usdhc4grp { - fsl,pins = < - MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 - MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 - MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 - MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 - MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 - MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 - MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 - >; - }; - }; -}; - &ipu1_di0_disp0 { remote-endpoint = <&display0_in>; }; @@ -164,3 +148,17 @@ fsl,wp-controller; status = "okay"; }; + +&iomuxc { + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 + MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020.dts b/arch/arm/boot/dts/imx6q-tx6q-1020.dts index 4217282b12ea..347b531d3763 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1020.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1020.dts @@ -210,22 +210,6 @@ status = "disabled"; }; -&iomuxc { - imx6qdl-tx6 { - pinctrl_usdhc4: usdhc4grp { - fsl,pins = < - MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 - MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 - MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 - MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 - MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 - MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 - MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 - >; - }; - }; -}; - &ipu1_di0_disp0 { remote-endpoint = <&display0_in>; }; @@ -238,3 +222,17 @@ fsl,wp-controller; status = "okay"; }; + +&iomuxc { + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 + MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1110.dts b/arch/arm/boot/dts/imx6q-tx6q-1110.dts index 45ceee77a23e..0433e220a931 100644 --- a/arch/arm/boot/dts/imx6q-tx6q-1110.dts +++ b/arch/arm/boot/dts/imx6q-tx6q-1110.dts @@ -111,16 +111,6 @@ }; }; -&iomuxc { - imx6q-tx6q-1110 { - pinctrl_eeti: eetigrp { - fsl,pins = < - MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */ - >; - }; - }; -}; - &kpp { status = "disabled"; /* pad conflict with backlight1 PWM */ }; @@ -182,3 +172,11 @@ &sata { status = "okay"; }; + +&iomuxc { + pinctrl_eeti: eetigrp { + fsl,pins = < + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */ + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index 371a38026bc4..1b1c39ebfe54 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -332,310 +332,313 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; - imx6qdl-tx6 { - pinctrl_hog: hoggrp { - fsl,pins = < - MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* LED */ - MX6QDL_PAD_SD3_DAT2__GPIO7_IO06 0x1b0b1 /* ETN PHY RESET */ - MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b1 /* ETN PHY INT */ - MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* PWR BTN */ - >; - }; + pinctrl_hog: hoggrp { + fsl,pins = < + MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* LED */ + MX6QDL_PAD_SD3_DAT2__GPIO7_IO06 0x1b0b1 /* ETN PHY RESET */ + MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b1 /* ETN PHY INT */ + MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* PWR BTN */ + >; + }; - pinctrl_audmux: audmuxgrp { - fsl,pins = < - MX6QDL_PAD_KEY_ROW1__AUD5_RXD 0x130b0 /* SSI1_RXD */ - MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0 /* SSI1_TXD */ - MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 /* SSI1_CLK */ - MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 /* SSI1_FS */ - >; - }; + pinctrl_audmux: audmuxgrp { + fsl,pins = < + MX6QDL_PAD_KEY_ROW1__AUD5_RXD 0x130b0 /* SSI1_RXD */ + MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0 /* SSI1_TXD */ + MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 /* SSI1_CLK */ + MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 /* SSI1_FS */ + >; + }; - pinctrl_disp0_1: disp0grp-1 { - fsl,pins = < - MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 - MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 - MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 - MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 - /* PAD DISP0_DAT0 is used for the Flexcan transceiver control */ - MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10 - MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10 - MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10 - MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10 - MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10 - MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10 - MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10 - MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10 - MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10 - MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10 - MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10 - MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10 - MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10 - MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10 - MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10 - MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10 - MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10 - MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10 - MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10 - MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10 - MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10 - MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10 - MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10 - >; - }; + pinctrl_disp0_1: disp0grp-1 { + fsl,pins = < + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 + MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 + MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 + MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 + /* PAD DISP0_DAT0 is used for the Flexcan transceiver control */ + MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10 + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10 + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10 + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10 + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10 + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10 + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10 + MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10 + MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10 + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10 + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10 + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10 + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10 + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10 + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10 + MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10 + MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10 + MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10 + MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10 + MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10 + MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10 + MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10 + MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10 + >; + }; - pinctrl_disp0_2: disp0grp-2 { - fsl,pins = < - MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 - MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 - MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 - MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 - MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10 - MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10 - MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10 - MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10 - MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10 - MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10 - MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10 - MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10 - MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10 - MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10 - MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10 - MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10 - MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10 - MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10 - MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10 - MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10 - MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10 - MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10 - MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10 - MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10 - MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10 - MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10 - MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10 - MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10 - >; - }; + pinctrl_disp0_2: disp0grp-2 { + fsl,pins = < + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 + MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 + MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 + MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 + MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10 + MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10 + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10 + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10 + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10 + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10 + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10 + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10 + MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10 + MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10 + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10 + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10 + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10 + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10 + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10 + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10 + MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10 + MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10 + MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10 + MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10 + MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10 + MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10 + MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10 + MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10 + >; + }; - pinctrl_ecspi1: ecspi1grp { - fsl,pins = < - MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x0b0b0 - MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x0b0b0 - MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x0b0b0 - MX6QDL_PAD_GPIO_19__ECSPI1_RDY 0x0b0b0 - MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x0b0b0 /* SPI CS0 */ - MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x0b0b0 /* SPI CS1 */ - >; - }; + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x0b0b0 + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x0b0b0 + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x0b0b0 + MX6QDL_PAD_GPIO_19__ECSPI1_RDY 0x0b0b0 + MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x0b0b0 /* SPI CS0 */ + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x0b0b0 /* SPI CS1 */ + >; + }; - pinctrl_edt_ft5x06: edt-ft5x06grp { - fsl,pins = < - MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0 /* Interrupt */ - MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b0 /* Reset */ - MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0 /* Wake */ - >; - }; + pinctrl_edt_ft5x06: edt-ft5x06grp { + fsl,pins = < + MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0 /* Interrupt */ + MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b0 /* Reset */ + MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0 /* Wake */ + >; + }; - pinctrl_enet: enetgrp { - fsl,pins = < - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 - MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0 - MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0 - MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0 - MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 - MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0 - MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0 - MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0 - >; - }; + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0 + MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 + MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0 + >; + }; - pinctrl_etnphy_power: etnphy-pwrgrp { - fsl,pins = < - MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x1b0b1 /* ETN PHY POWER */ - >; - }; + pinctrl_enet_mdio: enet-mdiogrp { + fsl,pins = < + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + >; + }; - pinctrl_flexcan1: flexcan1grp { - fsl,pins = < - MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0 - MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0 - >; - }; + pinctrl_etnphy_power: etnphy-pwrgrp { + fsl,pins = < + MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x1b0b1 /* ETN PHY POWER */ + >; + }; - pinctrl_flexcan2: flexcan2grp { - fsl,pins = < - MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b0 - MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b0 - >; - }; + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0 + MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0 + >; + }; - pinctrl_flexcan_xcvr: flexcan-xcvrgrp { - fsl,pins = < - MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21 0x1b0b0 /* Flexcan XCVR enable */ - >; - }; + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b0 + MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b0 + >; + }; - pinctrl_gpmi_nand: gpminandgrp { - fsl,pins = < - MX6QDL_PAD_NANDF_CLE__NAND_CLE 0x0b0b1 - MX6QDL_PAD_NANDF_ALE__NAND_ALE 0x0b0b1 - MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0x0b0b1 - MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0x0b000 - MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0x0b0b1 - MX6QDL_PAD_SD4_CMD__NAND_RE_B 0x0b0b1 - MX6QDL_PAD_SD4_CLK__NAND_WE_B 0x0b0b1 - MX6QDL_PAD_NANDF_D0__NAND_DATA00 0x0b0b1 - MX6QDL_PAD_NANDF_D1__NAND_DATA01 0x0b0b1 - MX6QDL_PAD_NANDF_D2__NAND_DATA02 0x0b0b1 - MX6QDL_PAD_NANDF_D3__NAND_DATA03 0x0b0b1 - MX6QDL_PAD_NANDF_D4__NAND_DATA04 0x0b0b1 - MX6QDL_PAD_NANDF_D5__NAND_DATA05 0x0b0b1 - MX6QDL_PAD_NANDF_D6__NAND_DATA06 0x0b0b1 - MX6QDL_PAD_NANDF_D7__NAND_DATA07 0x0b0b1 - >; - }; + pinctrl_flexcan_xcvr: flexcan-xcvrgrp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21 0x1b0b0 /* Flexcan XCVR enable */ + >; + }; - pinctrl_i2c1: i2c1grp { - fsl,pins = < - MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 - MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 - >; - }; + pinctrl_gpmi_nand: gpminandgrp { + fsl,pins = < + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0x0b0b1 + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0x0b0b1 + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0x0b0b1 + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0x0b000 + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0x0b0b1 + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0x0b0b1 + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0x0b0b1 + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0x0b0b1 + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0x0b0b1 + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0x0b0b1 + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0x0b0b1 + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0x0b0b1 + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0x0b0b1 + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0x0b0b1 + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0x0b0b1 + >; + }; - pinctrl_i2c3: i2c3grp { - fsl,pins = < - MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 - MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 - >; - }; + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 + >; + }; - pinctrl_kpp: kppgrp { - fsl,pins = < - MX6QDL_PAD_GPIO_9__KEY_COL6 0x1b0b1 - MX6QDL_PAD_GPIO_4__KEY_COL7 0x1b0b1 - MX6QDL_PAD_KEY_COL2__KEY_COL2 0x1b0b1 - MX6QDL_PAD_KEY_COL3__KEY_COL3 0x1b0b1 - MX6QDL_PAD_GPIO_2__KEY_ROW6 0x1b0b1 - MX6QDL_PAD_GPIO_5__KEY_ROW7 0x1b0b1 - MX6QDL_PAD_KEY_ROW2__KEY_ROW2 0x1b0b1 - MX6QDL_PAD_KEY_ROW3__KEY_ROW3 0x1b0b1 - >; - }; + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 + >; + }; - pinctrl_lcd0_pwr: lcd0-pwrgrp { - fsl,pins = < - MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b1 /* LCD Reset */ - >; - }; + pinctrl_kpp: kppgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_9__KEY_COL6 0x1b0b1 + MX6QDL_PAD_GPIO_4__KEY_COL7 0x1b0b1 + MX6QDL_PAD_KEY_COL2__KEY_COL2 0x1b0b1 + MX6QDL_PAD_KEY_COL3__KEY_COL3 0x1b0b1 + MX6QDL_PAD_GPIO_2__KEY_ROW6 0x1b0b1 + MX6QDL_PAD_GPIO_5__KEY_ROW7 0x1b0b1 + MX6QDL_PAD_KEY_ROW2__KEY_ROW2 0x1b0b1 + MX6QDL_PAD_KEY_ROW3__KEY_ROW3 0x1b0b1 + >; + }; - pinctrl_lcd1_pwr: lcd1-pwrgrp { - fsl,pins = < - MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b1 /* LCD Power Enable */ - >; - }; + pinctrl_lcd0_pwr: lcd0-pwrgrp { + fsl,pins = < + MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b1 /* LCD Reset */ + >; + }; - pinctrl_pwm1: pwm1grp { - fsl,pins = < - MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b1 - >; - }; + pinctrl_lcd1_pwr: lcd-pwrgrp { + fsl,pins = < + MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b1 /* LCD Power Enable */ + >; + }; - pinctrl_pwm2: pwm2grp { - fsl,pins = < - MX6QDL_PAD_GPIO_1__PWM2_OUT 0x1b0b1 - >; - }; + pinctrl_pwm1: pwm1grp { + fsl,pins = < + MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b1 + >; + }; - pinctrl_tsc2007: tsc2007grp { - fsl,pins = < - MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x1b0b0 /* Interrupt */ - >; - }; + pinctrl_pwm2: pwm2grp { + fsl,pins = < + MX6QDL_PAD_GPIO_1__PWM2_OUT 0x1b0b1 + >; + }; - pinctrl_uart1: uart1grp { - fsl,pins = < - MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 - MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 - >; - }; + pinctrl_tsc2007: tsc2007grp { + fsl,pins = < + MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x1b0b0 /* Interrupt */ + >; + }; - pinctrl_uart1_rtscts: uart1_rtsctsgrp { - fsl,pins = < - MX6QDL_PAD_SD3_DAT1__UART1_RTS_B 0x1b0b1 - MX6QDL_PAD_SD3_DAT0__UART1_CTS_B 0x1b0b1 - >; - }; + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 + >; + }; - pinctrl_uart2: uart2grp { - fsl,pins = < - MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 - MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 - >; - }; + pinctrl_uart1_rtscts: uart1_rtsctsgrp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT1__UART1_RTS_B 0x1b0b1 + MX6QDL_PAD_SD3_DAT0__UART1_CTS_B 0x1b0b1 + >; + }; - pinctrl_uart2_rtscts: uart2_rtsctsgrp { - fsl,pins = < - MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1 - MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1 - >; - }; + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 + >; + }; - pinctrl_uart3: uart3grp { - fsl,pins = < - MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 - MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 - >; - }; + pinctrl_uart2_rtscts: uart2_rtsctsgrp { + fsl,pins = < + MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1 + MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1 + >; + }; - pinctrl_uart3_rtscts: uart3_rtsctsgrp { - fsl,pins = < - MX6QDL_PAD_SD3_DAT3__UART3_CTS_B 0x1b0b1 - MX6QDL_PAD_SD3_RST__UART3_RTS_B 0x1b0b1 - >; - }; + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + >; + }; - pinctrl_usbh1_vbus: usbh1-vbusgrp { - fsl,pins = < - MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b0 /* USBH1_VBUSEN */ - >; - }; + pinctrl_uart3_rtscts: uart3_rtsctsgrp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT3__UART3_CTS_B 0x1b0b1 + MX6QDL_PAD_SD3_RST__UART3_RTS_B 0x1b0b1 + >; + }; - pinctrl_usbotg: usbotggrp { - fsl,pins = < - MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x17059 - >; - }; + pinctrl_usbh1_vbus: usbh1-vbusgrp { + fsl,pins = < + MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b0 /* USBH1_VBUSEN */ + >; + }; - pinctrl_usbotg_vbus: usbotg-vbusgrp { - fsl,pins = < - MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* USBOTG_VBUSEN */ - >; - }; + pinctrl_usbotg: usbotggrp { + fsl,pins = < + MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x17059 + >; + }; - pinctrl_usdhc1: usdhc1grp { - fsl,pins = < - MX6QDL_PAD_SD1_CMD__SD1_CMD 0x070b1 - MX6QDL_PAD_SD1_CLK__SD1_CLK 0x070b1 - MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x070b1 - MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x070b1 - MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x070b1 - MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x070b1 - MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x170b0 /* SD1 CD */ - >; - }; + pinctrl_usbotg_vbus: usbotg-vbusgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* USBOTG_VBUSEN */ + >; + }; - pinctrl_usdhc2: usdhc2grp { - fsl,pins = < - MX6QDL_PAD_SD2_CMD__SD2_CMD 0x070b1 - MX6QDL_PAD_SD2_CLK__SD2_CLK 0x070b1 - MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x070b1 - MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x070b1 - MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x070b1 - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x070b1 - MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x170b0 /* SD2 CD */ - >; - }; + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x070b1 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x070b1 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x070b1 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x070b1 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x070b1 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x070b1 + MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x170b0 /* SD1 CD */ + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x070b1 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x070b1 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x070b1 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x070b1 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x070b1 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x070b1 + MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x170b0 /* SD2 CD */ + >; }; }; -- GitLab From 9cbda37b8730c91c5960f333db9ea1bc9813d46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Tue, 8 Mar 2016 09:04:02 +0100 Subject: [PATCH 2448/9938] ARM: dts: imx6qdl-tx6: add mdio node for ethernet phy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add mdio node and an appropriate PHY configuration to enable use of the PHY interrupt for link status changes. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index 1b1c39ebfe54..5988889cee45 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -265,8 +265,22 @@ clock-names = "ipg", "ahb", "ptp", "enet_out"; phy-mode = "rmii"; phy-reset-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>; + phy-handle = <&etnphy>; phy-supply = <®_3v3_etn>; status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + etnphy: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet_mdio>; + interrupts-extended = <&gpio7 1 IRQ_TYPE_EDGE_FALLING>; + }; + }; }; &gpmi { -- GitLab From a7574ab01c4f6954fc9c5bd9d5d5cdd401618c88 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Sat, 2 Apr 2016 18:25:47 +0200 Subject: [PATCH 2449/9938] ARM: dts: imx: add Boundary Devices Nitrogen6_MAX QP board Based on i.MX6 Quad Plus with 4GB of RAM. https://boundarydevices.com/product/nitrogen6max/ Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6qp-nitrogen6_max.dts | 59 ++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 arch/arm/boot/dts/imx6qp-nitrogen6_max.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 81e7f92683ff..84008a7bf892 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -364,6 +364,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6q-udoo.dtb \ imx6q-wandboard.dtb \ imx6q-wandboard-revb1.dtb \ + imx6qp-nitrogen6_max.dtb \ imx6qp-sabreauto.dtb \ imx6qp-sabresd.dtb dtb-$(CONFIG_SOC_IMX6SL) += \ diff --git a/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts b/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts new file mode 100644 index 000000000000..a39b86036581 --- /dev/null +++ b/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts @@ -0,0 +1,59 @@ +/* + * Copyright 2016 Boundary Devices, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "imx6qp.dtsi" +#include "imx6qdl-nitrogen6_max.dtsi" + +/ { + model = "Boundary Devices i.MX6 Quad Plus Nitrogen6_MAX Board"; + compatible = "boundary,imx6qp-nitrogen6_max", "fsl,imx6qp"; +}; + +&pcie { + status = "disabled"; +}; + +&sata { + status = "okay"; +}; -- GitLab From 7281795fa40b92011567592a1c3c54f673a80ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 31 Mar 2016 14:33:41 +0200 Subject: [PATCH 2450/9938] ARM: dts: imx6-tx6: remove regulator bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DT maintainers don't like the 'simple-bus' container around the regulator nodes. So remove it. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 166 +++++++++++++---------------- 1 file changed, 75 insertions(+), 91 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index 5988889cee45..c0612662db61 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -97,104 +97,88 @@ }; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - reg_3v3_etn: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "3V3_ETN"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_etnphy_power>; - gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; + reg_3v3_etn: regulator-3v3-etn { + compatible = "regulator-fixed"; + regulator-name = "3V3_ETN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_etnphy_power>; + gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; - reg_2v5: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "2V5"; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2500000>; - regulator-always-on; - }; + reg_2v5: regulator-2v5 { + compatible = "regulator-fixed"; + regulator-name = "2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; - reg_3v3: regulator@2 { - compatible = "regulator-fixed"; - reg = <2>; - regulator-name = "3V3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; - reg_can_xcvr: regulator@3 { - compatible = "regulator-fixed"; - reg = <3>; - regulator-name = "CAN XCVR"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_flexcan_xcvr>; - gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>; - enable-active-low; - }; + reg_can_xcvr: regulator-can-xcvr { + compatible = "regulator-fixed"; + regulator-name = "CAN XCVR"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan_xcvr>; + gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>; + enable-active-low; + }; - reg_lcd0_pwr: regulator@4 { - compatible = "regulator-fixed"; - reg = <4>; - regulator-name = "LCD0 POWER"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_lcd0_pwr>; - gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>; - enable-active-high; - regulator-boot-on; - regulator-always-on; - }; + reg_lcd0_pwr: regulator-lcd0-pwr { + compatible = "regulator-fixed"; + regulator-name = "LCD0 POWER"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + }; - reg_lcd1_pwr: regulator@5 { - compatible = "regulator-fixed"; - reg = <5>; - regulator-name = "LCD1 POWER"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_lcd1_pwr>; - gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>; - enable-active-high; - regulator-boot-on; - regulator-always-on; - }; + reg_lcd1_pwr: regulator-lcd1-pwr { + compatible = "regulator-fixed"; + regulator-name = "LCD1 POWER"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd1_pwr>; + gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + }; - reg_usbh1_vbus: regulator@6 { - compatible = "regulator-fixed"; - reg = <6>; - regulator-name = "usbh1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usbh1_vbus>; - gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; + reg_usbh1_vbus: regulator-usbh1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usbh1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh1_vbus>; + gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; - reg_usbotg_vbus: regulator@7 { - compatible = "regulator-fixed"; - reg = <7>; - regulator-name = "usbotg_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usbotg_vbus>; - gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; + reg_usbotg_vbus: regulator-usbotg-vbus { + compatible = "regulator-fixed"; + regulator-name = "usbotg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg_vbus>; + gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>; + enable-active-high; }; sound { -- GitLab From 96de03677f57fa1455d94fa289cfafff58727d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 31 Mar 2016 14:33:42 +0200 Subject: [PATCH 2451/9938] ARM: dts: imx6-tx6: remove LED pinctrl setting from hoggrp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the pinctrl setting for the board LED from the hoggrp node to a separate node referenced by the LED driver, so that the pin is free to be used for different purpose when the LED driver is disabled. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index c0612662db61..ddf58b80d81c 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -92,6 +92,8 @@ user_led: user { label = "Heartbeat"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_user_led>; gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; @@ -332,7 +334,6 @@ pinctrl_hog: hoggrp { fsl,pins = < - MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* LED */ MX6QDL_PAD_SD3_DAT2__GPIO7_IO06 0x1b0b1 /* ETN PHY RESET */ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b1 /* ETN PHY INT */ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* PWR BTN */ @@ -638,6 +639,12 @@ MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x170b0 /* SD2 CD */ >; }; + + pinctrl_user_led: user-ledgrp { + fsl,pins = < + MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* LED */ + >; + }; }; &kpp { -- GitLab From 720f4340e40a03f6f063083e20f90403632ff031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 31 Mar 2016 14:33:43 +0200 Subject: [PATCH 2452/9938] ARM: dts: imx6-tx6: enable support for rtscts on UARTs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing pinctrl for the RTS/CTS lines to uart1 and set the fsl,uart-has-rtscts property on all UARTs to enable support for HW handshake. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index ddf58b80d81c..39b85aef93e1 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -688,19 +688,22 @@ &uart1 { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; + pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_rtscts>; + fsl,uart-has-rtscts; status = "okay"; }; &uart2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart2 &pinctrl_uart2_rtscts>; + fsl,uart-has-rtscts; status = "okay"; }; &uart3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>; + fsl,uart-has-rtscts; status = "okay"; }; -- GitLab From 168e0461367b33ebef2a9f0e88014b572ce41cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 31 Mar 2016 14:33:44 +0200 Subject: [PATCH 2453/9938] ARM: dts: imx6: add support for more Ka-Ro electronics modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the following i.MX6 based modules from Ka-Ro electronics GmbH: TX6S-8034: Processor Freescale i.MX 6 Solo, 800MHz RAM 256MiB DDR3 SDRAM ROM 128MiB NAND Flash Power supply Single 3.1V to 5.5V Size 31mm SO-DIMM Temp. Range industrial grade (-40°C/-25°C to 105°C Tj) TX6S-8035: Processor Freescale i.MX 6 Solo, 800MHz RAM 512MiB DDR3 SDRAM ROM 4GiB eMMC Power supply Single 3.1V to 5.5V Size 31mm SO-DIMM Temp. Range industrial grade (-40°C/-25°C to 105°C Tj) TX6U-8033: Processor Freescale i.MX 6 Dual Lite, 800MHz RAM 1GiB DDR3 SDRAM ROM 4GiB eMMC Power supply Single 3.1V to 5.5V Size 31mm SO-DIMM Temp. Range industrial grade (-40°C/-25°C to 105°C Tj) TX6Q-1036: Processor Freescale i.MX 6Quad, 1GHz RAM 1GB DDR3 SDRAM 64-bit ROM 8GiB eMMC Power supply Single 3.1V to 5.5V Size 31mm SO-DIMM Temp. Range Extended Consumer Grade (-20°C to 105°C Tj) Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 4 + arch/arm/boot/dts/imx6dl-tx6s-8034.dts | 237 +++++++++++++++++++++++ arch/arm/boot/dts/imx6dl-tx6s-8035.dts | 253 +++++++++++++++++++++++++ arch/arm/boot/dts/imx6dl-tx6u-8033.dts | 248 ++++++++++++++++++++++++ arch/arm/boot/dts/imx6q-tx6q-1036.dts | 252 ++++++++++++++++++++++++ 5 files changed, 994 insertions(+) create mode 100644 arch/arm/boot/dts/imx6dl-tx6s-8034.dts create mode 100644 arch/arm/boot/dts/imx6dl-tx6s-8035.dts create mode 100644 arch/arm/boot/dts/imx6dl-tx6u-8033.dts create mode 100644 arch/arm/boot/dts/imx6q-tx6q-1036.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 84008a7bf892..f3a9469f9c8d 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -320,7 +320,10 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6dl-sabrelite.dtb \ imx6dl-sabresd.dtb \ imx6dl-tx6dl-comtft.dtb \ + imx6dl-tx6s-8034.dtb \ + imx6dl-tx6s-8035.dtb \ imx6dl-tx6u-801x.dtb \ + imx6dl-tx6u-8033.dtb \ imx6dl-tx6u-811x.dtb \ imx6dl-udoo.dtb \ imx6dl-wandboard.dtb \ @@ -360,6 +363,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6q-tx6q-1010-comtft.dtb \ imx6q-tx6q-1020.dtb \ imx6q-tx6q-1020-comtft.dtb \ + imx6q-tx6q-1036.dtb \ imx6q-tx6q-1110.dtb \ imx6q-udoo.dtb \ imx6q-wandboard.dtb \ diff --git a/arch/arm/boot/dts/imx6dl-tx6s-8034.dts b/arch/arm/boot/dts/imx6dl-tx6s-8034.dts new file mode 100644 index 000000000000..ff8f7b1c4282 --- /dev/null +++ b/arch/arm/boot/dts/imx6dl-tx6s-8034.dts @@ -0,0 +1,237 @@ +/* + * Copyright 2015-2016 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" + +/ { + model = "Ka-Ro electronics TX6S-8034 Module"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + aliases { + display = &display; + ipu1 = &ipu1; + }; + + cpus { + /delete-node/ cpu@1; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>; + power-supply = <®_lcd1_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; + + display: display@di0 { + compatible = "fsl,imx-parallel-display"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_disp0_2>; + interface-pix-fmt = "rgb24"; + status = "okay"; + + port { + display0_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + + display-timings { + native-mode = <&vga>; + + vga: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; +}; + +&ds1339 { + status = "disabled"; +}; + +&pinctrl_usdhc1 { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x070b1 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x070b1 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x070b1 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x070b1 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x070b1 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x070b1 + MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x170b0 /* SD1 CD */ + >; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&display0_in>; +}; + +®_lcd0_pwr { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/imx6dl-tx6s-8035.dts b/arch/arm/boot/dts/imx6dl-tx6s-8035.dts new file mode 100644 index 000000000000..f988950e9443 --- /dev/null +++ b/arch/arm/boot/dts/imx6dl-tx6s-8035.dts @@ -0,0 +1,253 @@ +/* + * Copyright 2015-2016 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" + +/ { + model = "Ka-Ro electronics TX6S-8035 Module"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + aliases { + display = &display; + ipu1 = &ipu1; + }; + + cpus { + /delete-node/ cpu@1; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>; + power-supply = <®_lcd1_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; + + display: display@di0 { + compatible = "fsl,imx-parallel-display"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_disp0_2>; + interface-pix-fmt = "rgb24"; + status = "okay"; + + port { + display0_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + + display-timings { + native-mode = <&vga>; + + vga: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; +}; + +&ds1339 { + status = "disabled"; +}; + +&gpmi { + status = "disabled"; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&display0_in>; +}; + +®_lcd0_pwr { + status = "disabled"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + bus-width = <4>; + non-removable; + no-1-8-v; + fsl,wp-controller; + status = "okay"; +}; + +&iomuxc { + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 + MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6dl-tx6u-8033.dts b/arch/arm/boot/dts/imx6dl-tx6u-8033.dts new file mode 100644 index 000000000000..4d3204a56f46 --- /dev/null +++ b/arch/arm/boot/dts/imx6dl-tx6u-8033.dts @@ -0,0 +1,248 @@ +/* + * Copyright 2014-2016 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" + +/ { + model = "Ka-Ro electronics TX6U-8033 Module"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + aliases { + display = &display; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>; + power-supply = <®_lcd1_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; + + display: display@di0 { + compatible = "fsl,imx-parallel-display"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_disp0_2>; + interface-pix-fmt = "rgb24"; + status = "okay"; + + port { + display0_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + + display-timings { + native-mode = <&vga>; + + vga: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; +}; + +&ds1339 { + status = "disabled"; +}; + +&gpmi { + status = "disabled"; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&display0_in>; +}; + +®_lcd0_pwr { + status = "disabled"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + bus-width = <4>; + non-removable; + no-1-8-v; + fsl,wp-controller; + status = "okay"; +}; + +&iomuxc { + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 + MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6q-tx6q-1036.dts b/arch/arm/boot/dts/imx6q-tx6q-1036.dts new file mode 100644 index 000000000000..7c152e32758c --- /dev/null +++ b/arch/arm/boot/dts/imx6q-tx6q-1036.dts @@ -0,0 +1,252 @@ +/* + * Copyright 2014-2016 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q-1036 Module"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; + + aliases { + display = &display; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>; + power-supply = <®_lcd1_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; + + display: display@di0 { + compatible = "fsl,imx-parallel-display"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_disp0_2>; + interface-pix-fmt = "rgb24"; + status = "okay"; + + port { + display0_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + + display-timings { + native-mode = <&vga>; + + vga: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; +}; + +&ds1339 { + status = "disabled"; +}; + +&gpmi { + status = "disabled"; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&display0_in>; +}; + +&ipu2 { + status = "disabled"; +}; + +®_lcd0_pwr { + status = "disabled"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + bus-width = <4>; + non-removable; + no-1-8-v; + fsl,wp-controller; + status = "okay"; +}; + +&iomuxc { + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 + MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 + >; + }; +}; -- GitLab From 8630743bbe05ae8bd37a5396e49c7beb1736a311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 31 Mar 2016 14:33:45 +0200 Subject: [PATCH 2454/9938] ARM: dts: imx6: add support for the Ka-Ro electronics 'MB7' baseboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This baseboard can be used with all TX6 SoMs, but only a certain set of combinations can be ordered by default. Add support for these combinations in mainline, so that users can easily adopt their own combination of SoM and baseboard themselves. Signed-off-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 2 + arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts | 255 ++++++++++++++++++++ arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts | 264 +++++++++++++++++++++ 3 files changed, 521 insertions(+) create mode 100644 arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts create mode 100644 arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f3a9469f9c8d..f54c5187c78f 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -325,6 +325,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6dl-tx6u-801x.dtb \ imx6dl-tx6u-8033.dtb \ imx6dl-tx6u-811x.dtb \ + imx6dl-tx6u-81xx-mb7.dtb \ imx6dl-udoo.dtb \ imx6dl-wandboard.dtb \ imx6dl-wandboard-revb1.dtb \ @@ -365,6 +366,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6q-tx6q-1020-comtft.dtb \ imx6q-tx6q-1036.dtb \ imx6q-tx6q-1110.dtb \ + imx6q-tx6q-11x0-mb7.dtb \ imx6q-udoo.dtb \ imx6q-wandboard.dtb \ imx6q-wandboard-revb1.dtb \ diff --git a/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts b/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts new file mode 100644 index 000000000000..b9a783f7160e --- /dev/null +++ b/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts @@ -0,0 +1,255 @@ +/* + * Copyright 2016 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" + +/ { + model = "Ka-Ro electronics TX6U-81xx Module on MB7 baseboard"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + aliases { + display = &lvds0; + lvds0 = &lvds0; + lvds1 = &lvds1; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>; + power-supply = <®_lcd0_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; + + backlight1: backlight1 { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 500000 PWM_POLARITY_INVERTED>; + power-supply = <®_lcd1_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; +}; + +&can1 { + status = "disabled"; +}; + +&can2 { + xceiver-supply = <®_3v3>; +}; + +&i2c3 { + polytouch1: eeti@04 { + compatible = "eeti,egalax_ts"; + reg = <0x04>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eeti>; + interrupts-extended = <&gpio3 22 IRQ_TYPE_EDGE_FALLING>; + wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>; + wakeup-source; + }; +}; + +&kpp { + status = "disabled"; /* pads partially clash with backlight1 PWM */ +}; + +&ldb { + status = "okay"; + + lvds0: lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + status = "okay"; + + display-timings { + native-mode = <&lvds0_timing1>; + + lvds0_timing0: hsd100pxn1 { + clock-frequency = <65000000>; + hactive = <1024>; + vactive = <768>; + hback-porch = <220>; + hfront-porch = <40>; + vback-porch = <21>; + vfront-porch = <7>; + hsync-len = <60>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + lvds0_timing1: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hfront-porch = <16>; + vback-porch = <31>; + vfront-porch = <12>; + hsync-len = <96>; + vsync-len = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + lvds0_timing2: nl12880bc20 { + clock-frequency = <71000000>; + hactive = <1280>; + vactive = <800>; + hback-porch = <50>; + hfront-porch = <50>; + vback-porch = <5>; + vfront-porch = <5>; + hsync-len = <60>; + vsync-len = <13>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; + + lvds1: lvds-channel@1 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + status = "okay"; + + display-timings { + native-mode = <&lvds1_timing2>; + + lvds1_timing0: hsd100pxn1 { + clock-frequency = <65000000>; + hactive = <1024>; + vactive = <768>; + hback-porch = <220>; + hfront-porch = <40>; + vback-porch = <21>; + vfront-porch = <7>; + hsync-len = <60>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + lvds1_timing1: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hfront-porch = <16>; + vback-porch = <31>; + vfront-porch = <12>; + hsync-len = <96>; + vsync-len = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + lvds1_timing2: nl12880bc20 { + clock-frequency = <71000000>; + hactive = <1280>; + vactive = <800>; + hback-porch = <50>; + hfront-porch = <50>; + vback-porch = <5>; + vfront-porch = <5>; + hsync-len = <60>; + vsync-len = <13>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +&iomuxc { + pinctrl_eeti: eetigrp { + fsl,pins = < + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */ + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts b/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts new file mode 100644 index 000000000000..d78b129d01ea --- /dev/null +++ b/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts @@ -0,0 +1,264 @@ +/* + * Copyright 2016 Lothar Waßmann + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q-1110/-1130 Module on MB7 baseboard"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; + + aliases { + display = &lvds0; + ipu1 = &ipu2; + lvds0 = &lvds0; + lvds1 = &lvds1; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>; + power-supply = <®_lcd0_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; + + backlight1: backlight1 { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 500000 PWM_POLARITY_INVERTED>; + power-supply = <®_lcd1_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + }; +}; + +&can1 { + status = "disabled"; +}; + +&can2 { + xceiver-supply = <®_3v3>; +}; + +&i2c3 { + polytouch1: eeti@04 { + compatible = "eeti,egalax_ts"; + reg = <0x04>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eeti>; + interrupts-extended = <&gpio3 22 IRQ_TYPE_EDGE_FALLING>; + wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>; + wakeup-source; + }; +}; + +&ipu2 { + status = "disabled"; +}; + +&kpp { + status = "disabled"; /* pads partially clash with backlight1 PWM */ +}; + +&ldb { + status = "okay"; + + lvds0: lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + status = "okay"; + + display-timings { + native-mode = <&lvds0_timing1>; + + lvds0_timing0: hsd100pxn1 { + clock-frequency = <65000000>; + hactive = <1024>; + vactive = <768>; + hback-porch = <220>; + hfront-porch = <40>; + vback-porch = <21>; + vfront-porch = <7>; + hsync-len = <60>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + lvds0_timing1: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hfront-porch = <16>; + vback-porch = <31>; + vfront-porch = <12>; + hsync-len = <96>; + vsync-len = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + lvds0_timing2: nl12880bc20 { + clock-frequency = <71000000>; + hactive = <1280>; + vactive = <800>; + hback-porch = <50>; + hfront-porch = <50>; + vback-porch = <5>; + vfront-porch = <5>; + hsync-len = <60>; + vsync-len = <13>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; + + lvds1: lvds-channel@1 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + status = "okay"; + + display-timings { + native-mode = <&lvds1_timing2>; + + lvds1_timing0: hsd100pxn1 { + clock-frequency = <65000000>; + hactive = <1024>; + vactive = <768>; + hback-porch = <220>; + hfront-porch = <40>; + vback-porch = <21>; + vfront-porch = <7>; + hsync-len = <60>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + lvds1_timing1: VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hfront-porch = <16>; + vback-porch = <31>; + vfront-porch = <12>; + hsync-len = <96>; + vsync-len = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + lvds1_timing2: nl12880bc20 { + clock-frequency = <71000000>; + hactive = <1280>; + vactive = <800>; + hback-porch = <50>; + hfront-porch = <50>; + vback-porch = <5>; + vfront-porch = <5>; + hsync-len = <60>; + vsync-len = <13>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +&sata { + status = "okay"; +}; + +&iomuxc { + pinctrl_eeti: eetigrp { + fsl,pins = < + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */ + >; + }; +}; -- GitLab From e0884948a48013bb2097f3e61c4f2122b22f6eb1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 28 Mar 2016 14:10:48 -0300 Subject: [PATCH 2455/9938] ARM: dts: imx6qdl-sabresd: Pass the hannstar panel compatible string It is preferred to use the panel compatible string rather than passing the LCD timings in the device tree. So pass the "hannstar,hsd100pxn1" compatible string to describe the LVDS panel on this board. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 30 +++++++++++++++----------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi index 0b5c4de74485..5248e7bd2b06 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi @@ -115,7 +115,7 @@ mux-ext-port = <3>; }; - backlight { + backlight_lvds: backlight-lvds { compatible = "pwm-backlight"; pwms = <&pwm1 0 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; @@ -133,6 +133,17 @@ default-state = "on"; }; }; + + panel { + compatible = "hannstar,hsd100pxn1"; + backlight = <&backlight_lvds>; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; }; &audmux { @@ -509,18 +520,11 @@ fsl,data-width = <18>; status = "okay"; - display-timings { - native-mode = <&timing0>; - timing0: hsd100pxn1 { - clock-frequency = <65000000>; - hactive = <1024>; - vactive = <768>; - hback-porch = <220>; - hfront-porch = <40>; - vback-porch = <21>; - vfront-porch = <7>; - hsync-len = <60>; - vsync-len = <10>; + port@4 { + reg = <4>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; }; }; }; -- GitLab From 36853f9c6134633a4f4dcbbdeb29e3daf84d2a9f Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Mon, 11 Apr 2016 23:01:36 +0200 Subject: [PATCH 2456/9938] ARM: dts: imx: add Boundary Devices Nitrogen6_SoloX board Based on i.MX6 SoloX with 1GB of RAM. https://boundarydevices.com/product/nit6_solox-imx6/ Signed-off-by: Gary Bisson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6sx-nitrogen6sx.dts | 709 +++++++++++++++++++++++ 2 files changed, 710 insertions(+) create mode 100644 arch/arm/boot/dts/imx6sx-nitrogen6sx.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f54c5187c78f..eaf82b9b9f10 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -377,6 +377,7 @@ dtb-$(CONFIG_SOC_IMX6SL) += \ imx6sl-evk.dtb \ imx6sl-warp.dtb dtb-$(CONFIG_SOC_IMX6SX) += \ + imx6sx-nitrogen6sx.dtb \ imx6sx-sabreauto.dtb \ imx6sx-sdb-reva.dtb \ imx6sx-sdb.dtb diff --git a/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts b/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts new file mode 100644 index 000000000000..ba62348d8284 --- /dev/null +++ b/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts @@ -0,0 +1,709 @@ +/* + * Copyright (C) 2016 Boundary Devices, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "imx6sx.dtsi" + +/ { + model = "Boundary Devices i.MX6 SoloX Nitrogen6sx Board"; + compatible = "boundary,imx6sx-nitrogen6sx", "fsl,imx6sx"; + + aliases { + fb_lcd = &lcdif1; + t_lcd = &t_lcd; + }; + + memory { + reg = <0x80000000 0x40000000>; + }; + + backlight-lvds { + compatible = "pwm-backlight"; + pwms = <&pwm4 0 5000000>; + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <6>; + power-supply = <®_3p3v>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "1P8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_can1_3v3: regulator-can1-3v3 { + compatible = "regulator-fixed"; + regulator-name = "can1-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio4 27 GPIO_ACTIVE_LOW>; + }; + + reg_can2_3v3: regulator-can2-3v3 { + compatible = "regulator-fixed"; + regulator-name = "can2-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio4 24 GPIO_ACTIVE_LOW>; + }; + + reg_usb_otg1_vbus: regulator-usb-otg1-vbus { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg1_vbus>; + compatible = "regulator-fixed"; + regulator-name = "usb_otg1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_wlan: regulator-wlan { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_wlan>; + compatible = "regulator-fixed"; + clocks = <&clks IMX6SX_CLK_CKO>; + clock-names = "slow"; + regulator-name = "wlan-en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <70000>; + gpio = <&gpio7 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + sound { + compatible = "fsl,imx-audio-sgtl5000"; + model = "imx6sx-nitrogen6sx-sgtl5000"; + cpu-dai = <&ssi1>; + audio-codec = <&codec>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + mux-int-port = <1>; + mux-ext-port = <5>; + }; +}; + +&audmux { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux>; + status = "okay"; +}; + +&ecspi1 { + fsl,spi-num-chipselects = <1>; + cs-gpios = <&gpio2 16 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + status = "okay"; + + flash: m25p80@0 { + compatible = "microchip,sst25vf016b"; + spi-max-frequency = <20000000>; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0xc0000>; + read-only; + }; + + partition@c0000 { + label = "env"; + reg = <0xc0000 0x2000>; + read-only; + }; + + partition@c2000 { + label = "Kernel"; + reg = <0xc2000 0x11e000>; + }; + + partition@1e0000 { + label = "M4"; + reg = <0x1e0000 0x20000>; + }; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + phy-mode = "rgmii"; + phy-handle = <ðphy1>; + phy-supply = <®_3p3v>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy1: ethernet-phy@4 { + reg = <4>; + }; + + ethphy2: ethernet-phy@5 { + reg = <5>; + }; + }; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2>; + phy-mode = "rgmii"; + phy-handle = <ðphy2>; + phy-supply = <®_3p3v>; + fsl,magic-packet; + status = "okay"; +}; + +&flexcan1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + xceiver-supply = <®_can1_3v3>; + status = "okay"; +}; + +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <®_can2_3v3>; + status = "okay"; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sgtl5000>; + reg = <0x0a>; + clocks = <&clks IMX6SX_CLK_CKO2>; + VDDA-supply = <®_1p8v>; + VDDIO-supply = <®_1p8v>; + VDDD-supply = <®_1p8v>; + assigned-clocks = <&clks IMX6SX_CLK_CKO2_SEL>, + <&clks IMX6SX_CLK_CKO2>; + assigned-clock-parents = <&clks IMX6SX_CLK_OSC>; + assigned-clock-rates = <0>, <24000000>; + }; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + +&lcdif1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcdif1>; + lcd-supply = <®_3p3v>; + display = <&display0>; + status = "okay"; + + display0: display0 { + bits-per-pixel = <16>; + bus-width = <24>; + + display-timings { + native-mode = <&t_lcd>; + t_lcd: t_lcd_default { + clock-frequency = <74160000>; + hactive = <1280>; + vactive = <720>; + hback-porch = <220>; + hfront-porch = <110>; + vback-porch = <20>; + vfront-porch = <5>; + hsync-len = <40>; + vsync-len = <5>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + reset-gpio = <&gpio4 10 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pwm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm4>; + status = "okay"; +}; + +&ssi1 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&usbotg1 { + vbus-supply = <®_usb_otg1_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg1>; + status = "okay"; +}; + +&usbotg2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg2>; + dr_mode = "host"; + disable-over-current; + reset-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + bus-width = <4>; + cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + keep-power-in-suspend; + wakeup-source; + status = "okay"; +}; + +&usdhc3 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + bus-width = <4>; + non-removable; + keep-power-in-suspend; + vmmc-supply = <®_wlan>; + cap-power-off-card; + cap-sdio-irq; + status = "okay"; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&gpio7>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + }; + + wlcore: wlcore@2 { + compatible = "ti,wl1271"; + reg = <2>; + interrupt-parent = <&gpio7>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + ref-clock-frequency = <38400000>; + }; +}; + +&usdhc4 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc4_50mhz>; + pinctrl-1 = <&pinctrl_usdhc4_100mhz>; + pinctrl-2 = <&pinctrl_usdhc4_200mhz>; + bus-width = <8>; + non-removable; + vmmc-supply = <®_1p8v>; + keep-power-in-suspend; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_audmux: audmuxgrp { + fsl,pins = < + MX6SX_PAD_SD1_DATA0__AUDMUX_AUD5_RXD 0x1b0b0 + MX6SX_PAD_SD1_DATA1__AUDMUX_AUD5_TXC 0x1b0b0 + MX6SX_PAD_SD1_DATA2__AUDMUX_AUD5_TXFS 0x1b0b0 + MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_TXD 0x1b0b0 + >; + }; + + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6SX_PAD_KEY_COL1__ECSPI1_MISO 0x100b1 + MX6SX_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1 + MX6SX_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1 + MX6SX_PAD_KEY_ROW1__GPIO2_IO_16 0x0b0b1 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0x1b0b0 + MX6SX_PAD_ENET1_MDC__ENET1_MDC 0x1b0b0 + MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0x30b1 + MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0x30b1 + MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0x30b1 + MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0x30b1 + MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0x30b1 + MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0x30b1 + MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081 + MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081 + MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081 + MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081 + MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081 + MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081 + MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 0xb0b0 + MX6SX_PAD_ENET1_RX_CLK__GPIO2_IO_4 0xb0b0 + MX6SX_PAD_ENET1_TX_CLK__GPIO2_IO_5 0xb0b0 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0x30b1 + MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0x30b1 + MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0x30b1 + MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0x30b1 + MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0x30b1 + MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0x30b1 + MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081 + MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081 + MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081 + MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081 + MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081 + MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081 + MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0xb0b0 + MX6SX_PAD_ENET2_RX_CLK__GPIO2_IO_8 0xb0b0 + MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9 0xb0b0 + >; + }; + + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b0b0 + MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b0b0 + MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27 0x1b0b0 + MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27 0x0b0b0 + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b0b0 + MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b0b0 + MX6SX_PAD_QSPI1B_DATA0__GPIO4_IO_24 0x0b0b0 + >; + }; + + pinctrl_hog: hoggrp { + fsl,pins = < + MX6SX_PAD_NAND_CE0_B__GPIO4_IO_1 0x1b0b0 + MX6SX_PAD_NAND_CLE__GPIO4_IO_3 0x1b0b0 + MX6SX_PAD_NAND_RE_B__GPIO4_IO_12 0x1b0b0 + MX6SX_PAD_NAND_WE_B__GPIO4_IO_14 0x1b0b0 + MX6SX_PAD_NAND_WP_B__GPIO4_IO_15 0x1b0b0 + MX6SX_PAD_NAND_READY_B__GPIO4_IO_13 0x1b0b0 + MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x1b0b0 + MX6SX_PAD_QSPI1A_DATA1__GPIO4_IO_17 0x1b0b0 + MX6SX_PAD_QSPI1A_DATA2__GPIO4_IO_18 0x1b0b0 + MX6SX_PAD_QSPI1A_DATA3__GPIO4_IO_19 0x1b0b0 + MX6SX_PAD_SD1_CMD__CCM_CLKO1 0x000b0 + MX6SX_PAD_SD3_DATA5__GPIO7_IO_7 0x1b0b0 + /* Test points */ + MX6SX_PAD_NAND_DATA04__GPIO4_IO_8 0x1b0b0 + MX6SX_PAD_QSPI1B_DATA1__GPIO4_IO_25 0x1b0b0 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1 + MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO02__I2C2_SCL 0x4001b8b1 + MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1 + MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1 + >; + }; + + pinctrl_lcdif1: lcdif1grp { + fsl,pins = < + MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x4001b0b0 + MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0 + MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0 + MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0 + MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0 + MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0 + MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0 + MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0 + MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0 + MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0 + MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0 + MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0 + MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0 + MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0 + MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0 + MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0 + MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0 + MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0 + MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0 + MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0 + MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0 + MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0 + MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0 + MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0 + MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0 + MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0 + MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0 + MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0 + MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0 + >; + }; + + pinctrl_pcie: pciegrp { + fsl,pins = < + MX6SX_PAD_NAND_DATA05__GPIO4_IO_9 0xb0b0 + MX6SX_PAD_NAND_DATA06__GPIO4_IO_10 0xb0b0 + MX6SX_PAD_NAND_DATA07__GPIO4_IO_11 0xb0b0 + >; + }; + + pinctrl_pwm4: pwm4grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO13__PWM4_OUT 0x110b0 + >; + }; + + pinctrl_reg_wlan: reg-wlangrp { + fsl,pins = < + MX6SX_PAD_SD3_DATA4__GPIO7_IO_6 0x1b0b0 + MX6SX_PAD_GPIO1_IO11__CCM_CLKO1 0x000b0 + >; + }; + + pinctrl_sgtl5000: sgtl5000grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO12__CCM_CLKO2 0x000b0 + MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x1b0b0 + MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 0x1b0b0 + MX6SX_PAD_QSPI1A_SS0_B__GPIO4_IO_22 0xb0b0 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO06__UART2_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO07__UART2_RX 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6SX_PAD_QSPI1B_SS0_B__UART3_TX 0x1b0b1 + MX6SX_PAD_QSPI1B_SCLK__UART3_RX 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6SX_PAD_KEY_COL3__UART5_TX 0x1b0b1 + MX6SX_PAD_KEY_ROW3__UART5_RX 0x1b0b1 + MX6SX_PAD_SD3_DATA6__UART3_RTS_B 0x1b0b1 + MX6SX_PAD_SD3_DATA7__UART3_CTS_B 0x1b0b1 + >; + }; + + pinctrl_usbotg1: usbotg1grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO08__USB_OTG1_OC 0x1b0b0 + MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x170b1 + >; + }; + + pinctrl_usbotg1_vbus: usbotg1-vbusgrp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x1b0b0 + >; + }; + + pinctrl_usbotg2: usbotg2grp { + fsl,pins = < + MX6SX_PAD_QSPI1B_DATA2__GPIO4_IO_26 0xb0b0 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059 + MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059 + MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059 + MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059 + MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059 + MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059 + MX6SX_PAD_KEY_COL2__GPIO2_IO_12 0x1b0b0 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10071 + MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17071 + MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17071 + MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17071 + MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17071 + MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17071 + >; + }; + + pinctrl_usdhc4_50mhz: usdhc4-50mhzgrp { + fsl,pins = < + MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10071 + MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17071 + MX6SX_PAD_SD4_RESET_B__USDHC4_RESET_B 0x17071 + MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17071 + MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17071 + MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17071 + MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17071 + MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x17071 + MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x17071 + MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x17071 + MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x17071 + >; + }; + + pinctrl_usdhc4_100mhz: usdhc4-100mhzgrp { + fsl,pins = < + MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x100b9 + MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x170b9 + MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x170b9 + MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x170b9 + MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x170b9 + MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x170b9 + MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x170b9 + MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x170b9 + MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x170b9 + MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x170b9 + >; + }; + + pinctrl_usdhc4_200mhz: usdhc4-200mhzgrp { + fsl,pins = < + MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x100f9 + MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x170f9 + MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x170f9 + MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x170f9 + MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x170f9 + MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x170f9 + MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x170f9 + MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x170f9 + MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x170f9 + MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x170f9 + >; + }; +}; -- GitLab From 890b53ef86da0db030059a04db8b5501ea619dc0 Mon Sep 17 00:00:00 2001 From: Justin Waters Date: Fri, 1 Apr 2016 17:19:30 -0400 Subject: [PATCH 2457/9938] ARM: dts: imx6q-ba16: Disable pwm2 by default pwm2 is provided on the BA16 Q7 module, but is not used on any of the current configurations. However, future platforms may utilize this device, so we are simply disabling the node rather than removing it completely. Signed-off-by: Justin Waters Signed-off-by: Akshay Bhat Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-ba16.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6q-ba16.dtsi b/arch/arm/boot/dts/imx6q-ba16.dtsi index fcc7b5000511..3f33a2a2dfd4 100644 --- a/arch/arm/boot/dts/imx6q-ba16.dtsi +++ b/arch/arm/boot/dts/imx6q-ba16.dtsi @@ -337,7 +337,7 @@ &pwm2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm2>; - status = "okay"; + status = "disabled"; }; &sata { -- GitLab From 78f31b0b01aea2d21ad2cc9da4a196c6785b6600 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 1 Apr 2016 20:52:14 -0300 Subject: [PATCH 2458/9938] ARM: dts: imx6sx: Fix SAI DMA index According to sdma_peripheral_type in include/linux/platform_data/dma-imx.h IMX_DMATYPE_SAI corresponds to index 24, so fix it accordingly. Suggested-by: Zidan Wang Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index a5f76025a0ce..c8269e79e21d 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -970,7 +970,7 @@ <&clks 0>, <&clks 0>; clock-names = "bus", "mclk1", "mclk2", "mclk3"; dma-names = "rx", "tx"; - dmas = <&sdma 31 23 0>, <&sdma 32 23 0>; + dmas = <&sdma 31 24 0>, <&sdma 32 24 0>; dma-source = <&gpr 0 15 0 16>; status = "disabled"; }; @@ -990,7 +990,7 @@ <&clks 0>, <&clks 0>; clock-names = "bus", "mclk1", "mclk2", "mclk3"; dma-names = "rx", "tx"; - dmas = <&sdma 33 23 0>, <&sdma 34 23 0>; + dmas = <&sdma 33 24 0>, <&sdma 34 24 0>; dma-source = <&gpr 0 17 0 18>; status = "disabled"; }; -- GitLab From 88b53b9c1f2da681a5fb08c79437b8cd17b356ff Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 1 Apr 2016 20:52:15 -0300 Subject: [PATCH 2459/9938] ARM: dts: imx6sx: Remove unused property Property 'dma-source' is not used anywhere, nor it is documented, so let's just get rid of it. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index c8269e79e21d..d02ab324c7ba 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -971,7 +971,6 @@ clock-names = "bus", "mclk1", "mclk2", "mclk3"; dma-names = "rx", "tx"; dmas = <&sdma 31 24 0>, <&sdma 32 24 0>; - dma-source = <&gpr 0 15 0 16>; status = "disabled"; }; @@ -991,7 +990,6 @@ clock-names = "bus", "mclk1", "mclk2", "mclk3"; dma-names = "rx", "tx"; dmas = <&sdma 33 24 0>, <&sdma 34 24 0>; - dma-source = <&gpr 0 17 0 18>; status = "disabled"; }; -- GitLab From 3883dd74f0101d3ec94b213456c5965467ac8da9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 1 Apr 2016 20:52:16 -0300 Subject: [PATCH 2460/9938] bindings: fsl-imx-sdma: Document 'fsl,sdma-event-remap' property Document the 'fsl,sdma-event-remap' property and provide an example of its usage. Cc: Vinod Koul Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- .../devicetree/bindings/dma/fsl-imx-sdma.txt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt index dc8d3aac1aa9..175f0e44ed85 100644 --- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt @@ -58,6 +58,15 @@ The third cell specifies the transfer priority as below. 1 Medium 2 Low +Optional properties: + +- gpr : The phandle to the General Purpose Register (GPR) node. +- fsl,sdma-event-remap : Register bits of sdma event remap, the format is + . + reg is the GPR register offset. + shift is the bit position inside the GPR register. + val is the value of the bit (0 or 1). + Examples: sdma@83fb0000 { @@ -83,3 +92,21 @@ ssi2: ssi@70014000 { dma-names = "rx", "tx"; fsl,fifo-depth = <15>; }; + +Using the fsl,sdma-event-remap property: + +If we want to use SDMA on the SAI1 port on a MX6SX: + +&sdma { + gpr = <&gpr>; + /* SDMA events remap for SAI1_RX and SAI1_TX */ + fsl,sdma-event-remap = <0 15 1>, <0 16 1>; +}; + +The fsl,sdma-event-remap property in this case has two values: +- <0 15 1> means that the offset is 0, so GPR0 is the register of the +SDMA remap. Bit 15 of GPR0 selects between UART4_RX and SAI1_RX. +Setting bit 15 to 1 selects SAI1_RX. +- <0 16 1> means that the offset is 0, so GPR0 is the register of the +SDMA remap. Bit 16 of GPR0 selects between UART4_TX and SAI1_TX. +Setting bit 16 to 1 selects SAI1_TX. -- GitLab From 29e88b6de00da70eba9b905919427c8e8b9e88d6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 12 Apr 2016 13:43:43 +0800 Subject: [PATCH 2461/9938] ARM: dts: imx6sx-sdb: Add SAI support Introduce imx6sx-sdb-sai.dts so that it is possible to use the SAI interface. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6sx-sdb-sai.dts | 67 ++++++++++++++++++++++++++++ arch/arm/boot/dts/imx6sx-sdb.dtsi | 16 +++++++ 3 files changed, 84 insertions(+) create mode 100644 arch/arm/boot/dts/imx6sx-sdb-sai.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index eaf82b9b9f10..1c92e9df80df 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -380,6 +380,7 @@ dtb-$(CONFIG_SOC_IMX6SX) += \ imx6sx-nitrogen6sx.dtb \ imx6sx-sabreauto.dtb \ imx6sx-sdb-reva.dtb \ + imx6sx-sdb-sai.dtb \ imx6sx-sdb.dtb dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-14x14-evk.dtb \ diff --git a/arch/arm/boot/dts/imx6sx-sdb-sai.dts b/arch/arm/boot/dts/imx6sx-sdb-sai.dts new file mode 100644 index 000000000000..0155450d680e --- /dev/null +++ b/arch/arm/boot/dts/imx6sx-sdb-sai.dts @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 NXP Semiconductors + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "imx6sx-sdb.dts" + +/ { + sound { + audio-cpu = <&sai1>; + }; +}; + +&audmux { + /* pin conflict with sai */ + status = "disabled"; +}; + +&sai1 { + status = "okay"; +}; + +&sdma { + gpr = <&gpr>; + /* SDMA event remap for SAI1 */ + fsl,sdma-event-remap = <0 15 1>, <0 16 1>; +}; + +&ssi2 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi index f1d37306e8bf..e5eafe4d9a70 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dtsi +++ b/arch/arm/boot/dts/imx6sx-sdb.dtsi @@ -254,6 +254,12 @@ status = "okay"; }; +&sai1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai1>; + status = "disabled"; +}; + &ssi2 { status = "okay"; }; @@ -468,6 +474,16 @@ >; }; + pinctrl_sai1: sai1grp { + fsl,pins = < + MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130b0 + MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x130b0 + MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x120b0 + MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x130b0 + MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0 + >; + }; + pinctrl_uart1: uart1grp { fsl,pins = < MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 -- GitLab From 9b1a1779e97c8152d52159c4887fdef560c550e1 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 1 Apr 2016 23:13:39 -0700 Subject: [PATCH 2462/9938] ARM: dts: vf-colibri: alias the primary FEC as ethernet0 The Vybrid based Colibri modules provide a on-module PHY which is connected to the second FEC instance FEC1. Since the on-module Ethernet port is considered as primary ethernet interface, alias fec1 as ethernet0. This also makes sure that the first MAC address provided by the boot loader gets assigned to the FEC instance used for the on-module PHY. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf-colibri.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi index fda7f28101e1..7529dd7f6db1 100644 --- a/arch/arm/boot/dts/vf-colibri.dtsi +++ b/arch/arm/boot/dts/vf-colibri.dtsi @@ -40,6 +40,11 @@ */ / { + aliases { + ethernet0 = &fec1; + ethernet1 = &fec0; + }; + bl: backlight { compatible = "pwm-backlight"; pinctrl-names = "default"; -- GitLab From 6d20b24a2b3edc361e651ab87de5071d4b1b24c3 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 1 Apr 2016 23:13:40 -0700 Subject: [PATCH 2463/9938] ARM: dts: vf-colibri: increase NAND clock speed The NAND flash memory populated on Colibri VF61 allows faster NAND timings than the flash memory on VF50. Additionally, due to divider limitations, VF61 did clock the flash even slower than VF50. Assign the NFC clock in the module specific device trees vf500-colibri.dtsi and vf610-colibri.dtsi respectively. This increases raw read speed on Colibri VF61 by about 20%. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf-colibri.dtsi | 2 -- arch/arm/boot/dts/vf500-colibri.dtsi | 5 +++++ arch/arm/boot/dts/vf610-colibri.dtsi | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi index 7529dd7f6db1..226a86ffd3c9 100644 --- a/arch/arm/boot/dts/vf-colibri.dtsi +++ b/arch/arm/boot/dts/vf-colibri.dtsi @@ -130,8 +130,6 @@ }; &nfc { - assigned-clocks = <&clks VF610_CLK_NFC>; - assigned-clock-rates = <33000000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nfc>; status = "okay"; diff --git a/arch/arm/boot/dts/vf500-colibri.dtsi b/arch/arm/boot/dts/vf500-colibri.dtsi index 3fe1f48c2aec..1a8a0efa19a6 100644 --- a/arch/arm/boot/dts/vf500-colibri.dtsi +++ b/arch/arm/boot/dts/vf500-colibri.dtsi @@ -69,6 +69,11 @@ }; }; +&nfc { + assigned-clocks = <&clks VF610_CLK_NFC>; + assigned-clock-rates = <33000000>; +}; + &iomuxc { vf610-colibri { pinctrl_touchctrl_idle: touchctrl_idle { diff --git a/arch/arm/boot/dts/vf610-colibri.dtsi b/arch/arm/boot/dts/vf610-colibri.dtsi index ab4a29f95593..9ec9e337f5a8 100644 --- a/arch/arm/boot/dts/vf610-colibri.dtsi +++ b/arch/arm/boot/dts/vf610-colibri.dtsi @@ -50,3 +50,8 @@ reg = <0x80000000 0x10000000>; }; }; + +&nfc { + assigned-clocks = <&clks VF610_CLK_NFC>; + assigned-clock-rates = <50000000>; +}; -- GitLab From ef4a4e14ceeaec542e71d97e38912cbf83691541 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 1 Apr 2016 23:13:41 -0700 Subject: [PATCH 2464/9938] ARM: dts: vfxxx: add missing reg properties Add missing reg properties to AIPS bus and Cortex-A5's PMU unit. This change avoids the following warnings: Warning (unit_address_vs_reg): Node /soc/aips-bus@40000000 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /soc/aips-bus@40080000 has a unit name, but no reg property Warning (unit_address_vs_reg): Node /soc/aips-bus@40080000/pmu@40089000 has a unit name, but no reg property Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf500.dtsi | 1 + arch/arm/boot/dts/vfxxx.dtsi | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index 9d372720ad3f..a3824e61bd72 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -81,6 +81,7 @@ compatible = "arm,cortex-a5-pmu"; interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; interrupt-affinity = <&a5_cpu>; + reg = <0x40089000 0x1000>; }; }; diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 5c0975451d4e..04ef54d45a91 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -95,6 +95,7 @@ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; + reg = <0x40000000 0x00070000>; ranges; mscm_cpucfg: cpucfg@40001000 { @@ -481,6 +482,7 @@ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; + reg = <0x40080000 0x0007f000>; ranges; edma1: dma-controller@40098000 { -- GitLab From 1556063fde421ed17b017de3ba5c546f0524a15b Mon Sep 17 00:00:00 2001 From: Cory Tusar Date: Mon, 4 Apr 2016 23:53:12 +0200 Subject: [PATCH 2465/9938] ARM: dts: vf610-zii-dev: Add ZII development board. This commit adds support for Rev. B of a Zodiac Inflight Innovations development board, mainly intended for DSA and ARINC 429 development work. Signed-off-by: Cory Tusar Signed-off-by: Andrew Lunn Acked-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/vf610-zii-dev-rev-b.dts | 734 ++++++++++++++++++++++ 2 files changed, 736 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/vf610-zii-dev-rev-b.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 1c92e9df80df..a7d40426c141 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -400,7 +400,8 @@ dtb-$(CONFIG_SOC_VF610) += \ vf610m4-colibri.dtb \ vf610-cosmic.dtb \ vf610m4-cosmic.dtb \ - vf610-twr.dtb + vf610-twr.dtb \ + vf610-zii-dev-rev-b.dtb dtb-$(CONFIG_ARCH_MXS) += \ imx23-evk.dtb \ imx23-olinuxino.dtb \ diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts new file mode 100644 index 000000000000..6c60b7f91104 --- /dev/null +++ b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts @@ -0,0 +1,734 @@ +/* + * Copyright (C) 2015, 2016 Zodiac Inflight Innovations + * + * Based on an original 'vf610-twr.dts' which is Copyright 2015, + * Freescale Semiconductor, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "vf610.dtsi" + +/ { + model = "ZII VF610 Development Board, Rev B"; + compatible = "zii,vf610dev-b", "zii,vf610dev", "fsl,vf610"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0x80000000 0x20000000>; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&pinctrl_leds_debug>; + pinctrl-names = "default"; + + debug { + label = "zii:green:debug1"; + gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + mdio-mux { + compatible = "mdio-mux-gpio"; + pinctrl-0 = <&pinctrl_mdio_mux>; + pinctrl-names = "default"; + gpios = <&gpio0 8 GPIO_ACTIVE_HIGH + &gpio0 9 GPIO_ACTIVE_HIGH + &gpio0 24 GPIO_ACTIVE_HIGH + &gpio0 25 GPIO_ACTIVE_HIGH>; + mdio-parent-bus = <&mdio1>; + #address-cells = <1>; + #size-cells = <0>; + + mdio_mux_1: mdio@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio_mux_2: mdio@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio_mux_4: mdio@4 { + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio_mux_8: mdio@8 { + reg = <8>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + dsa { + compatible = "marvell,dsa"; + #address-cells = <2>; + #size-cells = <0>; + dsa,ethernet = <&fec1>; + dsa,mii-bus = <&mdio_mux_1>; + + /* 6352 - Primary - 7 ports */ + switch0: switch@0-0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x00 0>; + eeprom-length = <512>; + + port@0 { + reg = <0>; + label = "lan0"; + }; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + switch0port5: port@5 { + reg = <5>; + label = "dsa"; + phy-mode = "rgmii-txid"; + link = <&switch1port6 + &switch2port9>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + port@6 { + reg = <6>; + label = "cpu"; + + fixed-link { + speed = <100>; + full-duplex; + }; + }; + + }; + + /* 6352 - Secondary - 7 ports */ + switch1: switch@0-1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x00 1>; + eeprom-length = <512>; + mii-bus = <&mdio_mux_2>; + + port@0 { + reg = <0>; + label = "lan3"; + }; + + port@1 { + reg = <1>; + label = "lan4"; + }; + + port@2 { + reg = <2>; + label = "lan5"; + }; + + switch1port5: port@5 { + reg = <5>; + label = "dsa"; + link = <&switch2port9>; + phy-mode = "rgmii-txid"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + switch1port6: port@6 { + reg = <6>; + label = "dsa"; + phy-mode = "rgmii-txid"; + link = <&switch0port5>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + + /* 6185 - 10 ports */ + switch2: switch@0-2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x00 2>; + mii-bus = <&mdio_mux_4>; + + port@0 { + reg = <0>; + label = "lan6"; + }; + + port@1 { + reg = <1>; + label = "lan7"; + }; + + port@2 { + reg = <2>; + label = "lan8"; + }; + + port@3 { + reg = <3>; + label = "optical3"; + + fixed-link { + speed = <1000>; + full-duplex; + link-gpios = <&gpio6 2 + GPIO_ACTIVE_HIGH>; + }; + }; + + port@4 { + reg = <4>; + label = "optical4"; + + fixed-link { + speed = <1000>; + full-duplex; + link-gpios = <&gpio6 3 + GPIO_ACTIVE_HIGH>; + }; + }; + + switch2port9: port@9 { + reg = <9>; + label = "dsa"; + phy-mode = "rgmii-txid"; + link = <&switch1port5 + &switch0port5>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; + + reg_vcc_3v3_mcu: regulator-vcc-3v3-mcu { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_mcu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + usb0_vbus: regulator-usb0-vbus { + compatible = "regulator-fixed"; + pinctrl-0 = <&pinctrl_usb_vbus>; + regulator-name = "usb_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 6 0>; + }; + + spi0 { + compatible = "spi-gpio"; + pinctrl-0 = <&pinctrl_gpio_spi0>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + gpio-sck = <&gpio1 12 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio1 11 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio1 10 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH + &gpio1 8 GPIO_ACTIVE_HIGH>; + num-chipselects = <2>; + + m25p128@0 { + compatible = "m25p128", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <1000000>; + }; + + at93c46d@1 { + compatible = "atmel,at93c46d"; + pinctrl-0 = <&pinctrl_gpio_e6185_eeprom_sel>; + pinctrl-names = "default"; + #address-cells = <0>; + #size-cells = <0>; + reg = <1>; + spi-max-frequency = <500000>; + spi-cs-high; + data-size = <16>; + select-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&adc0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc0_ad5>; + vref-supply = <®_vcc_3v3_mcu>; + status = "okay"; +}; + +&edma0 { + status = "okay"; +}; + +&esdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_esdhc1>; + bus-width = <4>; + status = "okay"; +}; + +&fec0 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec0>; + status = "okay"; +}; + +&fec1 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + status = "okay"; + + fixed-link { + speed = <100>; + full-duplex; + }; + + mdio1: mdio { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + }; +}; + +&i2c0 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0>; + status = "okay"; + + gpio5: pca9554@20 { + compatible = "nxp,pca9554"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + + }; + + gpio6: pca9554@22 { + compatible = "nxp,pca9554"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pca9554_22>; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio2>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + }; + + lm75@48 { + compatible = "national,lm75"; + reg = <0x48>; + }; + + at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + + at24c04@52 { + compatible = "atmel,24c04"; + reg = <0x52>; + }; + + ds1682@6b { + compatible = "dallas,ds1682"; + reg = <0x6b>; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + tca9548@70 { + compatible = "nxp,pca9548"; + pinctrl-0 = <&pinctrl_i2c_mux_reset>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + sfp1: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + sfp2: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + sfp3: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + sfp4: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + }; +}; + +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&usbdev0 { + disable-over-current; + vbus-supply = <&usb0_vbus>; + dr_mode = "host"; + status = "okay"; +}; + +&usbh1 { + disable-over-current; + status = "okay"; +}; + +&usbmisc0 { + status = "okay"; +}; + +&usbmisc1 { + status = "okay"; +}; + +&usbphy0 { + status = "okay"; +}; + +&usbphy1 { + status = "okay"; +}; + +&iomuxc { + pinctrl_adc0_ad5: adc0ad5grp { + fsl,pins = < + VF610_PAD_PTC30__ADC0_SE5 0x00a1 + >; + }; + + pinctrl_dspi0: dspi0grp { + fsl,pins = < + VF610_PAD_PTB18__DSPI0_CS1 0x1182 + VF610_PAD_PTB19__DSPI0_CS0 0x1182 + VF610_PAD_PTB20__DSPI0_SIN 0x1181 + VF610_PAD_PTB21__DSPI0_SOUT 0x1182 + VF610_PAD_PTB22__DSPI0_SCK 0x1182 + >; + }; + + pinctrl_dspi2: dspi2grp { + fsl,pins = < + VF610_PAD_PTD31__DSPI2_CS1 0x1182 + VF610_PAD_PTD30__DSPI2_CS0 0x1182 + VF610_PAD_PTD29__DSPI2_SIN 0x1181 + VF610_PAD_PTD28__DSPI2_SOUT 0x1182 + VF610_PAD_PTD27__DSPI2_SCK 0x1182 + >; + }; + + pinctrl_esdhc1: esdhc1grp { + fsl,pins = < + VF610_PAD_PTA24__ESDHC1_CLK 0x31ef + VF610_PAD_PTA25__ESDHC1_CMD 0x31ef + VF610_PAD_PTA26__ESDHC1_DAT0 0x31ef + VF610_PAD_PTA27__ESDHC1_DAT1 0x31ef + VF610_PAD_PTA28__ESDHC1_DATA2 0x31ef + VF610_PAD_PTA29__ESDHC1_DAT3 0x31ef + VF610_PAD_PTA7__GPIO_134 0x219d + >; + }; + + pinctrl_fec0: fec0grp { + fsl,pins = < + VF610_PAD_PTC0__ENET_RMII0_MDC 0x30d2 + VF610_PAD_PTC1__ENET_RMII0_MDIO 0x30d3 + VF610_PAD_PTC2__ENET_RMII0_CRS 0x30d1 + VF610_PAD_PTC3__ENET_RMII0_RXD1 0x30d1 + VF610_PAD_PTC4__ENET_RMII0_RXD0 0x30d1 + VF610_PAD_PTC5__ENET_RMII0_RXER 0x30d1 + VF610_PAD_PTC6__ENET_RMII0_TXD1 0x30d2 + VF610_PAD_PTC7__ENET_RMII0_TXD0 0x30d2 + VF610_PAD_PTC8__ENET_RMII0_TXEN 0x30d2 + >; + }; + + pinctrl_fec1: fec1grp { + fsl,pins = < + VF610_PAD_PTA6__RMII_CLKIN 0x30d1 + VF610_PAD_PTC9__ENET_RMII1_MDC 0x30d2 + VF610_PAD_PTC10__ENET_RMII1_MDIO 0x30d3 + VF610_PAD_PTC11__ENET_RMII1_CRS 0x30d1 + VF610_PAD_PTC12__ENET_RMII1_RXD1 0x30d1 + VF610_PAD_PTC13__ENET_RMII1_RXD0 0x30d1 + VF610_PAD_PTC14__ENET_RMII1_RXER 0x30d1 + VF610_PAD_PTC15__ENET_RMII1_TXD1 0x30d2 + VF610_PAD_PTC16__ENET_RMII1_TXD0 0x30d2 + VF610_PAD_PTC17__ENET_RMII1_TXEN 0x30d2 + >; + }; + + pinctrl_gpio_e6185_eeprom_sel: pinctrl-gpio-e6185-eeprom-spi0 { + fsl,pins = < + VF610_PAD_PTE27__GPIO_132 0x33e2 + >; + }; + + pinctrl_gpio_spi0: pinctrl-gpio-spi0 { + fsl,pins = < + VF610_PAD_PTB22__GPIO_44 0x33e2 + VF610_PAD_PTB21__GPIO_43 0x33e2 + VF610_PAD_PTB20__GPIO_42 0x33e1 + VF610_PAD_PTB19__GPIO_41 0x33e2 + VF610_PAD_PTB18__GPIO_40 0x33e2 + >; + }; + + pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset { + fsl,pins = < + VF610_PAD_PTE14__GPIO_119 0x31c2 + >; + }; + + pinctrl_i2c0: i2c0grp { + fsl,pins = < + VF610_PAD_PTB14__I2C0_SCL 0x37ff + VF610_PAD_PTB15__I2C0_SDA 0x37ff + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + VF610_PAD_PTB16__I2C1_SCL 0x37ff + VF610_PAD_PTB17__I2C1_SDA 0x37ff + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + VF610_PAD_PTA22__I2C2_SCL 0x37ff + VF610_PAD_PTA23__I2C2_SDA 0x37ff + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + VF610_PAD_PTA30__I2C3_SCL 0x37ff + VF610_PAD_PTA31__I2C3_SDA 0x37ff + >; + }; + + pinctrl_leds_debug: pinctrl-leds-debug { + fsl,pins = < + VF610_PAD_PTD20__GPIO_74 0x31c2 + >; + }; + + pinctrl_mdio_mux: pinctrl-mdio-mux { + fsl,pins = < + VF610_PAD_PTA18__GPIO_8 0x31c2 + VF610_PAD_PTA19__GPIO_9 0x31c2 + VF610_PAD_PTB2__GPIO_24 0x31c2 + VF610_PAD_PTB3__GPIO_25 0x31c2 + >; + }; + + pinctrl_pca9554_22: pinctrl-pca95540-22 { + fsl,pins = < + VF610_PAD_PTB28__GPIO_98 0x219d + >; + }; + + pinctrl_pwm0: pwm0grp { + fsl,pins = < + VF610_PAD_PTB0__FTM0_CH0 0x1582 + VF610_PAD_PTB1__FTM0_CH1 0x1582 + VF610_PAD_PTB2__FTM0_CH2 0x1582 + VF610_PAD_PTB3__FTM0_CH3 0x1582 + >; + }; + + pinctrl_qspi0: qspi0grp { + fsl,pins = < + VF610_PAD_PTD7__QSPI0_B_QSCK 0x31c3 + VF610_PAD_PTD8__QSPI0_B_CS0 0x31ff + VF610_PAD_PTD9__QSPI0_B_DATA3 0x31c3 + VF610_PAD_PTD10__QSPI0_B_DATA2 0x31c3 + VF610_PAD_PTD11__QSPI0_B_DATA1 0x31c3 + VF610_PAD_PTD12__QSPI0_B_DATA0 0x31c3 + >; + }; + + pinctrl_uart0: uart0grp { + fsl,pins = < + VF610_PAD_PTB10__UART0_TX 0x21a2 + VF610_PAD_PTB11__UART0_RX 0x21a1 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + VF610_PAD_PTB23__UART1_TX 0x21a2 + VF610_PAD_PTB24__UART1_RX 0x21a1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + VF610_PAD_PTD0__UART2_TX 0x21a2 + VF610_PAD_PTD1__UART2_RX 0x21a1 + >; + }; + + pinctrl_usb_vbus: pinctrl-usb-vbus { + fsl,pins = < + VF610_PAD_PTA16__GPIO_6 0x31c2 + >; + }; + + pinctrl_usb0_host: usb0-host-grp { + fsl,pins = < + VF610_PAD_PTD6__GPIO_85 0x0062 + >; + }; +}; -- GitLab From cc1fb3e1f291c1fc1784619fbb84efab1d677e6c Mon Sep 17 00:00:00 2001 From: Soeren Moch Date: Tue, 5 Apr 2016 16:55:04 +0200 Subject: [PATCH 2466/9938] ARM: dts: imx6q-tbs2910: fix fec reset polarity According to Documentation/devicetree/bindings/net/fsl-fec.txt the polarity of "phy-reset-gpios" is assumed to be active-low unless a separate property "phy-reset-active-high" is available. So replace the inconsistent polarity description to make the correct active-low reset behavior more obvious. Signed-off-by: Soeren Moch Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-tbs2910.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts index 0da81bc2c68a..2401c6b54361 100644 --- a/arch/arm/boot/dts/imx6q-tbs2910.dts +++ b/arch/arm/boot/dts/imx6q-tbs2910.dts @@ -141,7 +141,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet>; phy-mode = "rgmii"; - phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>; + phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; status = "okay"; }; -- GitLab From 9eb7db1c352ad2048c952639aded7f67eec9c7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 6 Apr 2016 09:32:59 +0200 Subject: [PATCH 2467/9938] ARM: dts: imx28: add alternative pinmuxing for mac0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx28.dtsi | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index f637ec900cc8..74aa151cdb45 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -434,6 +434,32 @@ fsl,pull-up = ; }; + mac0_pins_b: mac0@1 { + reg = <1>; + fsl,pinmux-ids = < + MX28_PAD_ENET0_MDC__ENET0_MDC + MX28_PAD_ENET0_MDIO__ENET0_MDIO + MX28_PAD_ENET0_RX_EN__ENET0_RX_EN + MX28_PAD_ENET0_RXD0__ENET0_RXD0 + MX28_PAD_ENET0_RXD1__ENET0_RXD1 + MX28_PAD_ENET0_RXD2__ENET0_RXD2 + MX28_PAD_ENET0_RXD3__ENET0_RXD3 + MX28_PAD_ENET0_TX_EN__ENET0_TX_EN + MX28_PAD_ENET0_TXD0__ENET0_TXD0 + MX28_PAD_ENET0_TXD1__ENET0_TXD1 + MX28_PAD_ENET0_TXD2__ENET0_TXD2 + MX28_PAD_ENET0_TXD3__ENET0_TXD3 + MX28_PAD_ENET_CLK__CLKCTRL_ENET + MX28_PAD_ENET0_COL__ENET0_COL + MX28_PAD_ENET0_CRS__ENET0_CRS + MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK + MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + mac1_pins_a: mac1@0 { reg = <0>; fsl,pinmux-ids = < -- GitLab From f4a458fd83246a52e86628cb49dc11de8be823e2 Mon Sep 17 00:00:00 2001 From: Minghuan Lian Date: Wed, 6 Apr 2016 19:02:07 +0800 Subject: [PATCH 2468/9938] ARM: dts: ls1021a: add SCFG MSI dts node Add SCFG MSI dts node and add msi-parent property to PCIe dts node that points to the corresponding MSI node. Signed-off-by: Minghuan Lian Tested-by: Alexander Stein Signed-off-by: Shawn Guo --- arch/arm/boot/dts/ls1021a.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index 726372d3adc0..c0dee50b0185 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -119,6 +119,20 @@ }; + msi1: msi-controller@1570e00 { + compatible = "fsl,1s1021a-msi"; + reg = <0x0 0x1570e00 0x0 0x8>; + msi-controller; + interrupts = ; + }; + + msi2: msi-controller@1570e08 { + compatible = "fsl,1s1021a-msi"; + reg = <0x0 0x1570e08 0x0 0x8>; + msi-controller; + interrupts = ; + }; + ifc: ifc@1530000 { compatible = "fsl,ifc", "simple-bus"; reg = <0x0 0x1530000 0x0 0x10000>; @@ -587,6 +601,7 @@ bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&msi1>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, @@ -609,6 +624,7 @@ bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x48 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x48 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&msi2>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, -- GitLab From 027309fc856dd6cb50d890cf65136700f62f991c Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Tue, 12 Apr 2016 12:01:24 -0400 Subject: [PATCH 2469/9938] ARM: dts: imx6q-ba16: Remove unused vqmmc-supply The vqmmc supply is not connected to bio supply on the BA16 module. Hence remove vqmmc-supply property in usdhc3 node. Signed-off-by: Akshay Bhat Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-ba16.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6q-ba16.dtsi b/arch/arm/boot/dts/imx6q-ba16.dtsi index 3f33a2a2dfd4..8122e5bbfebe 100644 --- a/arch/arm/boot/dts/imx6q-ba16.dtsi +++ b/arch/arm/boot/dts/imx6q-ba16.dtsi @@ -392,7 +392,6 @@ pinctrl-0 = <&pinctrl_usdhc3 &pinctrl_usdhc3_reset>; bus-width = <8>; vmmc-supply = <&vdd_bperi>; - vqmmc-supply = <&vdd_bio>; non-removable; keep-power-in-suspend; status = "okay"; -- GitLab From c54dd442b489116234ec27a1d3575f274060b68f Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Wed, 23 Mar 2016 17:47:20 +0800 Subject: [PATCH 2470/9938] ARM: dts: ls1021a: Add gpio support for ls1021a platform Add gpio nodes for ls1021a platform dts file. The gpio IP block of the ls1021a can be supported by the code drivers/gpio/gpio-mpc8xxx.c. The compatible "fsl,qoriq-gpio" is used by gpio driver: drivers/gpio/gpio-mpc8xxx.c to implement general gpio functionalities. The chip-specific compatible "fsl,ls1021a-gpio" may be used to fix potential gpio IP block errata or other chip-specific gpio issues. Signed-off-by: Liu Gang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/ls1021a.dtsi | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index c0dee50b0185..a5204a5f99ba 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -346,6 +346,46 @@ status = "disabled"; }; + gpio0: gpio@2300000 { + compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio@2310000 { + compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio"; + reg = <0x0 0x2310000 0x0 0x10000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio@2320000 { + compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio"; + reg = <0x0 0x2320000 0x0 0x10000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@2330000 { + compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio"; + reg = <0x0 0x2330000 0x0 0x10000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + lpuart0: serial@2950000 { compatible = "fsl,ls1021a-lpuart"; reg = <0x0 0x2950000 0x0 0x1000>; -- GitLab From 5b9f967c074007b37874e63dbc56babb8501fb4b Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 23 Mar 2016 10:49:06 +0100 Subject: [PATCH 2471/9938] ARM: dts: ls1021a: DSPI has 6 chip-selects Both DSPI have signals SPIn_PCS[0:5] so in summary 6 chip-selects, not 5. Fix that. Signed-off-by: Alexander Stein Signed-off-by: Shawn Guo --- arch/arm/boot/dts/ls1021a.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index a5204a5f99ba..068393ed8e7b 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -259,7 +259,7 @@ interrupts = ; clock-names = "dspi"; clocks = <&platform_clk 1>; - spi-num-chipselects = <5>; + spi-num-chipselects = <6>; big-endian; status = "disabled"; }; @@ -272,7 +272,7 @@ interrupts = ; clock-names = "dspi"; clocks = <&platform_clk 1>; - spi-num-chipselects = <5>; + spi-num-chipselects = <6>; big-endian; status = "disabled"; }; -- GitLab From 5d01e99ebf91ff2b72b2bcb81976eab14addf143 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 4 Apr 2016 22:28:41 -0700 Subject: [PATCH 2472/9938] ARM: dts: ls1021a: add pix clock to DCU dts node The DCU IP has distinct clock inputs for register access and the pixel clocks, at least in some implementations. LS1021a seems to use the same clock, therefore specify the same clock for "dcu" and "pix". Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/ls1021a.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index 068393ed8e7b..5ae8e9297e9a 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -497,8 +497,9 @@ compatible = "fsl,ls1021a-dcu"; reg = <0x0 0x2ce0000 0x0 0x10000>; interrupts = ; - clocks = <&platform_clk 0>; - clock-names = "dcu"; + clocks = <&platform_clk 0>, + <&platform_clk 0>; + clock-names = "dcu", "pix"; big-endian; status = "disabled"; }; -- GitLab From 91ed140d6c1e168b11bbbddac4f6066f40a0c6b5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 31 Mar 2016 16:21:02 +0200 Subject: [PATCH 2473/9938] x86/asm: Make sure verify_cpu() has a good stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 04633df0c43d ("x86/cpu: Call verify_cpu() after having entered long mode too") added the call to verify_cpu() for sanitizing CPU configuration. The latter uses the stack minimally and it can happen that we land in startup_64() directly from a 64-bit bootloader. Then we want to use our own, known good stack. Do that. APs don't need this as the trampoline sets up a stack for them. Reported-by: Tom Lendacky Signed-off-by: Borislav Petkov Cc: Brian Gerst Cc: Linus Torvalds Cc: Mika Penttilä Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1459434062-31055-1-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_64.S | 8 ++++++++ include/asm-generic/vmlinux.lds.h | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 3de91a7e6c99..5df831ef1442 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -65,6 +65,14 @@ startup_64: * tables and then reload them. */ + /* + * Setup stack for verify_cpu(). "-8" because stack_start is defined + * this way, see below. Our best guess is a NULL ptr for stack + * termination heuristics and we don't want to break anything which + * might depend on it (kgdb, ...). + */ + leaq (__end_init_task - 8)(%rip), %rsp + /* Sanitize CPU configuration */ call verify_cpu diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 339125bb4d2c..6a67ab94b553 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -245,7 +245,9 @@ #define INIT_TASK_DATA(align) \ . = ALIGN(align); \ - *(.data..init_task) + VMLINUX_SYMBOL(__start_init_task) = .; \ + *(.data..init_task) \ + VMLINUX_SYMBOL(__end_init_task) = .; /* * Read only Data -- GitLab From 31d50c551e30923b86a1b5b420920dd1927fa63b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 4 Apr 2016 16:02:08 +0200 Subject: [PATCH 2474/9938] perf/x86/amd/uncore: Do not register a task ctx for uncore PMUs The new sanity check introduced by: 26657848502b ("perf/core: Verify we have a single perf_hw_context PMU") ... triggered on the AMD uncore driver. Uncore PMUs are per node, they cannot have per-task counters. Fix it. Reported-by: Borislav Petkov Reported-by: Ingo Molnar Tested-by: Borislav Petkov Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: acme@redhat.com Cc: alexander.shishkin@linux.intel.com Cc: eranian@google.com Cc: jolsa@redhat.com Cc: linux-tip-commits@vger.kernel.org Cc: vincent.weaver@maine.edu Link: http://lkml.kernel.org/r/20160404140208.GA3448@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- arch/x86/events/amd/uncore.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c index 3db9569e658c..98ac57381bf9 100644 --- a/arch/x86/events/amd/uncore.c +++ b/arch/x86/events/amd/uncore.c @@ -263,6 +263,7 @@ static const struct attribute_group *amd_uncore_attr_groups[] = { }; static struct pmu amd_nb_pmu = { + .task_ctx_nr = perf_invalid_context, .attr_groups = amd_uncore_attr_groups, .name = "amd_nb", .event_init = amd_uncore_event_init, @@ -274,6 +275,7 @@ static struct pmu amd_nb_pmu = { }; static struct pmu amd_l2_pmu = { + .task_ctx_nr = perf_invalid_context, .attr_groups = amd_uncore_attr_groups, .name = "amd_l2", .event_init = amd_uncore_event_init, -- GitLab From c78b17e28cc2c2df74264afc408bdc6aaf3fbcc8 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 11 Apr 2016 16:38:33 +0200 Subject: [PATCH 2475/9938] sched/clock: Remove pointless test in cpu_clock/local_clock In case the HAVE_UNSTABLE_SCHED_CLOCK config is set, the cpu_clock() version checks if sched_clock_stable() is not set and calls sched_clock_cpu(), otherwise it calls sched_clock(). sched_clock_cpu() checks also if sched_clock_stable() is set and, if true, calls sched_clock(). sched_clock() will be called in sched_clock_cpu() if sched_clock_stable() is true. Remove the duplicate test by directly calling sched_clock_cpu() and let the static key act in this function instead. Signed-off-by: Daniel Lezcano Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1460385514-14700-1-git-send-email-daniel.lezcano@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/clock.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index fedb967a9841..30c4b202f0ba 100644 --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c @@ -375,10 +375,7 @@ EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event); */ u64 cpu_clock(int cpu) { - if (!sched_clock_stable()) - return sched_clock_cpu(cpu); - - return sched_clock(); + return sched_clock_cpu(cpu); } /* @@ -390,10 +387,7 @@ u64 cpu_clock(int cpu) */ u64 local_clock(void) { - if (!sched_clock_stable()) - return sched_clock_cpu(raw_smp_processor_id()); - - return sched_clock(); + return sched_clock_cpu(raw_smp_processor_id()); } #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ -- GitLab From 2c923e94cd9c6acff3b22f0ae29cfe65e2658b40 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 11 Apr 2016 16:38:34 +0200 Subject: [PATCH 2476/9938] sched/clock: Make local_clock()/cpu_clock() inline The local_clock/cpu_clock functions were changed to prevent a double identical test with sched_clock_cpu() when HAVE_UNSTABLE_SCHED_CLOCK is set. That resulted in one line functions. As these functions are in all the cases one line functions and in the hot path, it is useful to specify them as static inline in order to give a strong hint to the compiler. After verification, it appears the compiler does not inline them without this hint. Change those functions to static inline. sched_clock_cpu() is called via the inlined local_clock()/cpu_clock() functions from sched.h. So any module code including sched.h will reference sched_clock_cpu(). Thus it must be exported with the EXPORT_SYMBOL_GPL macro. Signed-off-by: Daniel Lezcano Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1460385514-14700-2-git-send-email-daniel.lezcano@linaro.org Signed-off-by: Ingo Molnar --- include/linux/sched.h | 32 ++++++++++++++++++++++++++++++-- kernel/sched/clock.c | 42 +----------------------------------------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 52c4847b05e2..13c1c1d07270 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2303,8 +2303,6 @@ extern unsigned long long notrace sched_clock(void); /* * See the comment in kernel/sched/clock.c */ -extern u64 cpu_clock(int cpu); -extern u64 local_clock(void); extern u64 running_clock(void); extern u64 sched_clock_cpu(int cpu); @@ -2323,6 +2321,16 @@ static inline void sched_clock_idle_sleep_event(void) static inline void sched_clock_idle_wakeup_event(u64 delta_ns) { } + +static inline u64 cpu_clock(int cpu) +{ + return sched_clock(); +} + +static inline u64 local_clock(void) +{ + return sched_clock(); +} #else /* * Architectures can set this to 1 if they have specified @@ -2337,6 +2345,26 @@ extern void clear_sched_clock_stable(void); extern void sched_clock_tick(void); extern void sched_clock_idle_sleep_event(void); extern void sched_clock_idle_wakeup_event(u64 delta_ns); + +/* + * As outlined in clock.c, provides a fast, high resolution, nanosecond + * time source that is monotonic per cpu argument and has bounded drift + * between cpus. + * + * ######################### BIG FAT WARNING ########################## + * # when comparing cpu_clock(i) to cpu_clock(j) for i != j, time can # + * # go backwards !! # + * #################################################################### + */ +static inline u64 cpu_clock(int cpu) +{ + return sched_clock_cpu(cpu); +} + +static inline u64 local_clock(void) +{ + return sched_clock_cpu(raw_smp_processor_id()); +} #endif #ifdef CONFIG_IRQ_TIME_ACCOUNTING diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index 30c4b202f0ba..e85a725e5c34 100644 --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c @@ -318,6 +318,7 @@ u64 sched_clock_cpu(int cpu) return clock; } +EXPORT_SYMBOL_GPL(sched_clock_cpu); void sched_clock_tick(void) { @@ -363,33 +364,6 @@ void sched_clock_idle_wakeup_event(u64 delta_ns) } EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event); -/* - * As outlined at the top, provides a fast, high resolution, nanosecond - * time source that is monotonic per cpu argument and has bounded drift - * between cpus. - * - * ######################### BIG FAT WARNING ########################## - * # when comparing cpu_clock(i) to cpu_clock(j) for i != j, time can # - * # go backwards !! # - * #################################################################### - */ -u64 cpu_clock(int cpu) -{ - return sched_clock_cpu(cpu); -} - -/* - * Similar to cpu_clock() for the current cpu. Time will only be observed - * to be monotonic if care is taken to only compare timestampt taken on the - * same CPU. - * - * See cpu_clock(). - */ -u64 local_clock(void) -{ - return sched_clock_cpu(raw_smp_processor_id()); -} - #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ void sched_clock_init(void) @@ -404,22 +378,8 @@ u64 sched_clock_cpu(int cpu) return sched_clock(); } - -u64 cpu_clock(int cpu) -{ - return sched_clock(); -} - -u64 local_clock(void) -{ - return sched_clock(); -} - #endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ -EXPORT_SYMBOL_GPL(cpu_clock); -EXPORT_SYMBOL_GPL(local_clock); - /* * Running clock - returns the time that has elapsed while a guest has been * running. -- GitLab From bd92883051a0228cc34996b8e766111ba10c9aac Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 6 Apr 2016 21:59:50 +1000 Subject: [PATCH 2477/9938] sched/cpuacct: Check for NULL when using task_pt_regs() task_pt_regs() can return NULL for kernel threads, so add a check. This fixes an oops at boot on ppc64. Reported-and-Tested-by: Srikar Dronamraju Tested-by: Zhao Lei Signed-off-by: Anton Blanchard Acked-by: Zhao Lei Cc: Linus Torvalds Cc: Michael Ellerman Cc: Peter Zijlstra Cc: Stephen Rothwell Cc: Thomas Gleixner Cc: efault@gmx.de Cc: htejun@gmail.com Cc: linuxppc-dev@lists.ozlabs.org Cc: tj@kernel.org Cc: yangds.fnst@cn.fujitsu.com Link: http://lkml.kernel.org/r/20160406215950.04bc3f0b@kryten Signed-off-by: Ingo Molnar --- kernel/sched/cpuacct.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c index df947e07aac1..41f85c4d0938 100644 --- a/kernel/sched/cpuacct.c +++ b/kernel/sched/cpuacct.c @@ -316,12 +316,11 @@ static struct cftype files[] = { void cpuacct_charge(struct task_struct *tsk, u64 cputime) { struct cpuacct *ca; - int index; + int index = CPUACCT_USAGE_SYSTEM; + struct pt_regs *regs = task_pt_regs(tsk); - if (user_mode(task_pt_regs(tsk))) + if (regs && user_mode(regs)) index = CPUACCT_USAGE_USER; - else - index = CPUACCT_USAGE_SYSTEM; rcu_read_lock(); -- GitLab From dfbd379ba9b7431eec46f1dbc2603491be98619a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 Mar 2016 19:13:22 +0530 Subject: [PATCH 2478/9938] gpio: of: Return error if gpio hog configuration failed If GPIO hog configuration failed while adding OF based gpiochip() then return the error instead of ignoring it. This helps of properly handling the gpio driver dependency. When adding the gpio hog nodes for NVIDIA's Tegra210 platforms, the gpio_hogd() fails with EPROBE_DEFER because pinctrl is not ready at this time and gpio_request() for Tegra GPIO driver returns error. The error was not causing the Tegra GPIO driver to fail as the error was getting ignored. Signed-off-by: Laxman Dewangan Cc: Benoit Parrot Cc: Alexandre Courbot Reviewed-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 42a4bb7cf49a..a2485093d10d 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -201,14 +201,16 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, * * This is only used by of_gpiochip_add to request/set GPIO initial * configuration. + * It retures error if it fails otherwise 0 on success. */ -static void of_gpiochip_scan_gpios(struct gpio_chip *chip) +static int of_gpiochip_scan_gpios(struct gpio_chip *chip) { struct gpio_desc *desc = NULL; struct device_node *np; const char *name; enum gpio_lookup_flags lflags; enum gpiod_flags dflags; + int ret; for_each_child_of_node(chip->of_node, np) { if (!of_property_read_bool(np, "gpio-hog")) @@ -218,9 +220,12 @@ static void of_gpiochip_scan_gpios(struct gpio_chip *chip) if (IS_ERR(desc)) continue; - if (gpiod_hog(desc, name, lflags, dflags)) - continue; + ret = gpiod_hog(desc, name, lflags, dflags); + if (ret < 0) + return ret; } + + return 0; } /** @@ -442,9 +447,7 @@ int of_gpiochip_add(struct gpio_chip *chip) of_node_get(chip->of_node); - of_gpiochip_scan_gpios(chip); - - return 0; + return of_gpiochip_scan_gpios(chip); } void of_gpiochip_remove(struct gpio_chip *chip) -- GitLab From 202ff9684a912c96e0f2fac65e34280a97ad3611 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 12 Apr 2016 10:11:07 -0300 Subject: [PATCH 2479/9938] perf trace: Support callchains for --event too We already were able to ask for callchains for a specific event: # trace -e nanosleep --call dwarf --event sched:sched_switch/call-graph=fp/ usleep 1 This would enable tracing just the "nanosleep" syscall, with callchains at syscall exit and would ask the kernel for frame pointer callchains to be enabled for the "sched:sched_switch" tracepoint event, its just that we were not resolving the callchain and printing it in 'perf trace', do it: # trace -e nanosleep --call dwarf --event sched:sched_switch/call-graph=fp/ usleep 1 0.425 ( 0.013 ms): usleep/6718 nanosleep(rqtp: 0x7ffcc1d16e20) ... 0.425 ( ): sched:sched_switch:usleep:6718 [120] S ==> swapper/2:0 [120]) __schedule+0xfe200402 ([kernel.kallsyms]) schedule+0xfe200035 ([kernel.kallsyms]) do_nanosleep+0xfe20006f ([kernel.kallsyms]) hrtimer_nanosleep+0xfe2000dc ([kernel.kallsyms]) sys_nanosleep+0xfe20007a ([kernel.kallsyms]) do_syscall_64+0xfe200062 ([kernel.kallsyms]) return_from_SYSCALL_64+0xfe200000 ([kernel.kallsyms]) __nanosleep+0xffff008b8cbe2010 (/usr/lib64/libc-2.22.so) 0.486 ( 0.073 ms): usleep/6718 ... [continued]: nanosleep()) = 0 __nanosleep+0x10 (/usr/lib64/libc-2.22.so) usleep+0x34 (/usr/lib64/libc-2.22.so) main+0x1eb (/usr/bin/usleep) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) _start+0x29 (/usr/bin/usleep) # Pretty compact, huh? DWARF callchains for raw_syscalls:sys_exit + frame pointer callchains for a tracepoint, if your hardware supports LBR, go wild with /call-graph=lbr/, guess the next step is to lift this from 'perf script': -F, --fields comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr,symoff,period,iregs,brstack,brstacksym,flags Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-2e7yiv5hqdm8jywlmfivvx2v@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 41 ++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2ec53edcf649..a6e05e1bb350 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2114,6 +2114,28 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, return err; } +static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel, + struct perf_sample *sample) +{ + struct addr_location al; + /* TODO: user-configurable print_opts */ + const unsigned int print_opts = PRINT_IP_OPT_SYM | + PRINT_IP_OPT_DSO | + PRINT_IP_OPT_UNKNOWN_AS_ADDR; + + if (sample->callchain == NULL) + return 0; + + if (machine__resolve(trace->host, &al, sample) < 0) { + pr_err("Problem processing %s callchain, skipping...\n", + perf_evsel__name(evsel)); + return 0; + } + + return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts, + scripting_max_stack, trace->output); +} + static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) @@ -2193,21 +2215,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, fputc('\n', trace->output); - if (sample->callchain) { - struct addr_location al; - /* TODO: user-configurable print_opts */ - const unsigned int print_opts = PRINT_IP_OPT_SYM | - PRINT_IP_OPT_DSO | - PRINT_IP_OPT_UNKNOWN_AS_ADDR; - - if (machine__resolve(trace->host, &al, sample) < 0) { - pr_err("problem processing %d event, skipping it.\n", - event->header.type); - goto out_put; - } - perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts, - scripting_max_stack, trace->output); - } + trace__fprintf_callchain(trace, evsel, sample); out: ttrace->entry_pending = false; err = 0; @@ -2355,6 +2363,9 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, } fprintf(trace->output, ")\n"); + + trace__fprintf_callchain(trace, evsel, sample); + return 0; } -- GitLab From 3407df8bbc3a91d9aa4910130026ab6b3a261b87 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:24 +0200 Subject: [PATCH 2480/9938] perf thread_map: Add has() method Adding thread_map__has() to return bool of pid presence in threads map. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.c | 12 ++++++++++++ tools/perf/util/thread_map.h | 1 + 2 files changed, 13 insertions(+) diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 267112b4e3db..878ac0687b0a 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -436,3 +436,15 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event) return threads; } + +bool thread_map__has(struct thread_map *threads, pid_t pid) +{ + int i; + + for (i = 0; i < threads->nr; ++i) { + if (threads->map[i].pid == pid) + return true; + } + + return false; +} diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 85e4c7c4fbde..9a065ea69ff1 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -55,4 +55,5 @@ static inline char *thread_map__comm(struct thread_map *map, int thread) } void thread_map__read_comms(struct thread_map *threads); +bool thread_map__has(struct thread_map *threads, pid_t pid); #endif /* __PERF_THREAD_MAP_H */ -- GitLab From e632aa69c919462a7f93c8799b97c8a9ddd48fc2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:25 +0200 Subject: [PATCH 2481/9938] perf cpu_map: Add has() method Adding cpu_map__has() to return bool of cpu presence in cpus map. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 12 ++++++++++++ tools/perf/util/cpumap.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 9bcf2bed3a6d..02d801670f30 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -587,3 +587,15 @@ int cpu__setup_cpunode_map(void) closedir(dir1); return 0; } + +bool cpu_map__has(struct cpu_map *cpus, int cpu) +{ + int i; + + for (i = 0; i < cpus->nr; ++i) { + if (cpus->map[i] == cpu) + return true; + } + + return false; +} diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 81a2562aaa2b..1a0a35073ce1 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -66,4 +66,6 @@ int cpu__get_node(int cpu); int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, int (*f)(struct cpu_map *map, int cpu, void *data), void *data); + +bool cpu_map__has(struct cpu_map *cpus, int cpu); #endif /* __PERF_CPUMAP_H */ -- GitLab From 99623c628f5425f09b5321cf621af1da29c0c47d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:26 +0200 Subject: [PATCH 2482/9938] perf sched: Add compact display option Add compact map display that does not output the whole cpu matrix, only cpus that got event. $ perf sched map --compact *A0 1082427.094098 secs A0 => perf:19404 (CPU 2) A0 *. 1082427.094127 secs . => swapper:0 (CPU 1) A0 . *B0 1082427.094174 secs B0 => rcuos/2:25 (CPU 3) A0 . *. 1082427.094177 secs *C0 . . 1082427.094187 secs C0 => migration/2:21 C0 *A0 . 1082427.094193 secs *. A0 . 1082427.094195 secs *D0 A0 . 1082427.094402 secs D0 => rngd:968 *. A0 . 1082427.094406 secs . *E0 . 1082427.095221 secs E0 => kworker/1:1:5333 . E0 *F0 1082427.095227 secs F0 => xterm:3342 It helps to display sane output for small thread loads on big cpu servers. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-4-git-send-email-jolsa@kernel.org [ Add entry in 'perf sched' man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 7 +++ tools/perf/builtin-sched.c | 62 ++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 8ff4df956951..89b0c5b7fe84 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -50,6 +50,13 @@ OPTIONS --dump-raw-trace=:: Display verbose dump of the sched data. +OPTIONS for 'perf sched map' +---------------------------- + +--compact:: + Show only CPUs with activity. Helps visualizing on high core + count systems. + SEE ALSO -------- linkperf:perf-record[1] diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 871b55ae22a4..64dd94667055 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -122,6 +122,12 @@ struct trace_sched_handler { struct machine *machine); }; +struct perf_sched_map { + DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS); + int *comp_cpus; + bool comp; +}; + struct perf_sched { struct perf_tool tool; const char *sort_order; @@ -173,6 +179,7 @@ struct perf_sched { struct list_head sort_list, cmp_pid; bool force; bool skip_merge; + struct perf_sched_map map; }; static u64 get_nsecs(void) @@ -1347,13 +1354,24 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int new_shortname; u64 timestamp0, timestamp = sample->time; s64 delta; - int cpu, this_cpu = sample->cpu; + int i, this_cpu = sample->cpu; + int cpus_nr; + bool new_cpu = false; BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); if (this_cpu > sched->max_cpu) sched->max_cpu = this_cpu; + if (sched->map.comp) { + cpus_nr = bitmap_weight(sched->map.comp_cpus_mask, MAX_CPUS); + if (!test_and_set_bit(this_cpu, sched->map.comp_cpus_mask)) { + sched->map.comp_cpus[cpus_nr++] = this_cpu; + new_cpu = true; + } + } else + cpus_nr = sched->max_cpu; + timestamp0 = sched->cpu_last_switched[this_cpu]; sched->cpu_last_switched[this_cpu] = timestamp; if (timestamp0) @@ -1400,7 +1418,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, new_shortname = 1; } - for (cpu = 0; cpu <= sched->max_cpu; cpu++) { + for (i = 0; i < cpus_nr; i++) { + int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; + if (cpu != this_cpu) printf(" "); else @@ -1414,12 +1434,15 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, printf(" %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { - printf("%s => %s:%d\n", + printf("%s => %s:%d", sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); - } else { - printf("\n"); } + if (sched->map.comp && new_cpu) + printf(" (CPU %d)", this_cpu); + + printf("\n"); + thread__put(sched_in); return 0; @@ -1675,9 +1698,22 @@ static int perf_sched__lat(struct perf_sched *sched) return 0; } +static int setup_map_cpus(struct perf_sched *sched) +{ + sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); + + if (sched->map.comp) { + sched->map.comp_cpus = zalloc(sched->max_cpu * sizeof(int)); + return sched->map.comp_cpus ? 0 : -1; + } + + return 0; +} + static int perf_sched__map(struct perf_sched *sched) { - sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); + if (setup_map_cpus(sched)) + return -1; setup_pager(); if (perf_sched__read_events(sched)) @@ -1831,6 +1867,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "dump raw trace in ASCII"), OPT_END() }; + const struct option map_options[] = { + OPT_BOOLEAN(0, "compact", &sched.map.comp, + "map output in compact mode"), + OPT_END() + }; const char * const latency_usage[] = { "perf sched latency []", NULL @@ -1839,6 +1880,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "perf sched replay []", NULL }; + const char * const map_usage[] = { + "perf sched map []", + NULL + }; const char *const sched_subcommands[] = { "record", "latency", "map", "replay", "script", NULL }; const char *sched_usage[] = { @@ -1887,6 +1932,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) setup_sorting(&sched, latency_options, latency_usage); return perf_sched__lat(&sched); } else if (!strcmp(argv[0], "map")) { + if (argc) { + argc = parse_options(argc, argv, map_options, replay_usage, 0); + if (argc) + usage_with_options(map_usage, map_options); + } sched.tp_handler = &map_ops; setup_sorting(&sched, latency_options, latency_usage); return perf_sched__map(&sched); -- GitLab From 8cd91195e5efc5166fc48eec6cf83ef93133b7b6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:27 +0200 Subject: [PATCH 2483/9938] perf sched: Use color_fprintf for output As preparation for next patch. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 64dd94667055..9ef28973f198 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -11,6 +11,7 @@ #include "util/session.h" #include "util/tool.h" #include "util/cloexec.h" +#include "util/color.h" #include #include "util/trace-event.h" @@ -1357,6 +1358,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int i, this_cpu = sample->cpu; int cpus_nr; bool new_cpu = false; + const char *color = PERF_COLOR_NORMAL; BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); @@ -1422,26 +1424,26 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; if (cpu != this_cpu) - printf(" "); + color_fprintf(stdout, color, " "); else - printf("*"); + color_fprintf(stdout, color, "*"); if (sched->curr_thread[cpu]) - printf("%2s ", sched->curr_thread[cpu]->shortname); + color_fprintf(stdout, color, "%2s ", sched->curr_thread[cpu]->shortname); else - printf(" "); + color_fprintf(stdout, color, " "); } - printf(" %12.6f secs ", (double)timestamp/1e9); + color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { - printf("%s => %s:%d", + color_fprintf(stdout, color, "%s => %s:%d", sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); } if (sched->map.comp && new_cpu) - printf(" (CPU %d)", this_cpu); + color_fprintf(stdout, color, " (CPU %d)", this_cpu); - printf("\n"); + color_fprintf(stdout, color, "\n"); thread__put(sched_in); -- GitLab From 097be0f5034fc9edaf84253b773b14bc2af9a708 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:28 +0200 Subject: [PATCH 2484/9938] perf thread_map: Make new_by_tid_str constructor public It will be used in following patch. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.c | 2 +- tools/perf/util/thread_map.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 878ac0687b0a..5654fe15e036 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -260,7 +260,7 @@ struct thread_map *thread_map__new_dummy(void) return threads; } -static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) +struct thread_map *thread_map__new_by_tid_str(const char *tid_str) { struct thread_map *threads = NULL, *nt; int ntasks = 0; diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 9a065ea69ff1..bd3b971588da 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -31,6 +31,8 @@ void thread_map__put(struct thread_map *map); struct thread_map *thread_map__new_str(const char *pid, const char *tid, uid_t uid); +struct thread_map *thread_map__new_by_tid_str(const char *tid_str); + size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); static inline int thread_map__nr(struct thread_map *threads) -- GitLab From a151a37a760aab41c115af8d5016e449228e8d2e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:29 +0200 Subject: [PATCH 2485/9938] perf sched map: Color given pids Adding --color-pids option to display selected pids in color (blue by default). It helps on navigating through the 'perf sched map' output. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-7-git-send-email-jolsa@kernel.org [ Added entry to man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 3 + tools/perf/builtin-sched.c | 77 +++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 89b0c5b7fe84..67913de3aee7 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -57,6 +57,9 @@ OPTIONS for 'perf sched map' Show only CPUs with activity. Helps visualizing on high core count systems. +--color-pids:: + Highlight the given pids. + SEE ALSO -------- linkperf:perf-record[1] diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 9ef28973f198..b5361a1d20e1 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -11,6 +11,7 @@ #include "util/session.h" #include "util/tool.h" #include "util/cloexec.h" +#include "util/thread_map.h" #include "util/color.h" #include @@ -123,10 +124,14 @@ struct trace_sched_handler { struct machine *machine); }; +#define COLOR_PIDS PERF_COLOR_BLUE + struct perf_sched_map { DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS); int *comp_cpus; bool comp; + struct thread_map *color_pids; + const char *color_pids_str; }; struct perf_sched { @@ -1347,6 +1352,38 @@ static int process_sched_wakeup_event(struct perf_tool *tool, return 0; } +union map_priv { + void *ptr; + bool color; +}; + +static bool thread__has_color(struct thread *thread) +{ + union map_priv priv = { + .ptr = thread__priv(thread), + }; + + return priv.color; +} + +static struct thread* +map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid) +{ + struct thread *thread = machine__findnew_thread(machine, pid, tid); + union map_priv priv = { + .color = false, + }; + + if (!sched->map.color_pids || !thread || thread__priv(thread)) + return thread; + + if (thread_map__has(sched->map.color_pids, tid)) + priv.color = true; + + thread__set_priv(thread, priv.ptr); + return thread; +} + static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1386,7 +1423,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, return -1; } - sched_in = machine__findnew_thread(machine, -1, next_pid); + sched_in = map__findnew_thread(sched, machine, -1, next_pid); if (sched_in == NULL) return -1; @@ -1422,6 +1459,11 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, for (i = 0; i < cpus_nr; i++) { int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; + struct thread *curr_thread = sched->curr_thread[cpu]; + const char *pid_color = color; + + if (curr_thread && thread__has_color(curr_thread)) + pid_color = COLOR_PIDS; if (cpu != this_cpu) color_fprintf(stdout, color, " "); @@ -1429,14 +1471,19 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, color_fprintf(stdout, color, "*"); if (sched->curr_thread[cpu]) - color_fprintf(stdout, color, "%2s ", sched->curr_thread[cpu]->shortname); + color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); else color_fprintf(stdout, color, " "); } color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { - color_fprintf(stdout, color, "%s => %s:%d", + const char *pid_color = color; + + if (thread__has_color(sched_in)) + pid_color = COLOR_PIDS; + + color_fprintf(stdout, pid_color, "%s => %s:%d", sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); } @@ -1712,11 +1759,31 @@ static int setup_map_cpus(struct perf_sched *sched) return 0; } +static int setup_color_pids(struct perf_sched *sched) +{ + struct thread_map *map; + + if (!sched->map.color_pids_str) + return 0; + + map = thread_map__new_by_tid_str(sched->map.color_pids_str); + if (!map) { + pr_err("failed to get thread map from %s\n", sched->map.color_pids_str); + return -1; + } + + sched->map.color_pids = map; + return 0; +} + static int perf_sched__map(struct perf_sched *sched) { if (setup_map_cpus(sched)) return -1; + if (setup_color_pids(sched)) + return -1; + setup_pager(); if (perf_sched__read_events(sched)) return -1; @@ -1872,6 +1939,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) const struct option map_options[] = { OPT_BOOLEAN(0, "compact", &sched.map.comp, "map output in compact mode"), + OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids", + "highlight given pids in map"), OPT_END() }; const char * const latency_usage[] = { @@ -1935,7 +2004,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) return perf_sched__lat(&sched); } else if (!strcmp(argv[0], "map")) { if (argc) { - argc = parse_options(argc, argv, map_options, replay_usage, 0); + argc = parse_options(argc, argv, map_options, map_usage, 0); if (argc) usage_with_options(map_usage, map_options); } -- GitLab From cf294f24f8c83bca6aa8e96b5cc4f78bed887f92 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:30 +0200 Subject: [PATCH 2486/9938] perf sched map: Color given cpus Adding --color-cpus option to display selected cpus with background color (red by default). It helps on navigating through the perf sched map output. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-8-git-send-email-jolsa@kernel.org [ Added entry to man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 3 +++ tools/perf/builtin-sched.c | 36 ++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 67913de3aee7..58bff6cbc3f3 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -57,6 +57,9 @@ OPTIONS for 'perf sched map' Show only CPUs with activity. Helps visualizing on high core count systems. +--color-cpus:: + Highlight the given cpus. + --color-pids:: Highlight the given pids. diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index b5361a1d20e1..7de04b297c14 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -125,6 +125,7 @@ struct trace_sched_handler { }; #define COLOR_PIDS PERF_COLOR_BLUE +#define COLOR_CPUS PERF_COLOR_BG_RED struct perf_sched_map { DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS); @@ -132,6 +133,8 @@ struct perf_sched_map { bool comp; struct thread_map *color_pids; const char *color_pids_str; + struct cpu_map *color_cpus; + const char *color_cpus_str; }; struct perf_sched { @@ -1461,14 +1464,18 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; struct thread *curr_thread = sched->curr_thread[cpu]; const char *pid_color = color; + const char *cpu_color = color; if (curr_thread && thread__has_color(curr_thread)) pid_color = COLOR_PIDS; + if (sched->map.color_cpus && cpu_map__has(sched->map.color_cpus, cpu)) + cpu_color = COLOR_CPUS; + if (cpu != this_cpu) - color_fprintf(stdout, color, " "); + color_fprintf(stdout, cpu_color, " "); else - color_fprintf(stdout, color, "*"); + color_fprintf(stdout, cpu_color, "*"); if (sched->curr_thread[cpu]) color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); @@ -1753,7 +1760,8 @@ static int setup_map_cpus(struct perf_sched *sched) if (sched->map.comp) { sched->map.comp_cpus = zalloc(sched->max_cpu * sizeof(int)); - return sched->map.comp_cpus ? 0 : -1; + if (!sched->map.comp_cpus) + return -1; } return 0; @@ -1776,6 +1784,23 @@ static int setup_color_pids(struct perf_sched *sched) return 0; } +static int setup_color_cpus(struct perf_sched *sched) +{ + struct cpu_map *map; + + if (!sched->map.color_cpus_str) + return 0; + + map = cpu_map__new(sched->map.color_cpus_str); + if (!map) { + pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str); + return -1; + } + + sched->map.color_cpus = map; + return 0; +} + static int perf_sched__map(struct perf_sched *sched) { if (setup_map_cpus(sched)) @@ -1784,6 +1809,9 @@ static int perf_sched__map(struct perf_sched *sched) if (setup_color_pids(sched)) return -1; + if (setup_color_cpus(sched)) + return -1; + setup_pager(); if (perf_sched__read_events(sched)) return -1; @@ -1941,6 +1969,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "map output in compact mode"), OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids", "highlight given pids in map"), + OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus", + "highlight given CPUs in map"), OPT_END() }; const char * const latency_usage[] = { -- GitLab From 73643bb6a21c85509c7ae4c316f502c5a19cce65 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:31 +0200 Subject: [PATCH 2487/9938] perf sched map: Display only given cpus Introducing --cpus option that will display only given cpus. Could be used together with color-cpus option. $ perf sched map --cpus 0,1 *A0 309999.786924 secs A0 => rcu_sched:7 *. 309999.786930 secs *B0 . 309999.786931 secs B0 => rcuos/2:25 B0 *A0 309999.786947 secs Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-9-git-send-email-jolsa@kernel.org [ Added entry to man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 3 +++ tools/perf/builtin-sched.c | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 58bff6cbc3f3..1cc08cc47ac5 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -57,6 +57,9 @@ OPTIONS for 'perf sched map' Show only CPUs with activity. Helps visualizing on high core count systems. +--cpus:: + Show just entries with activities for the given CPUs. + --color-cpus:: Highlight the given cpus. diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 7de04b297c14..afa057666c2a 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -135,6 +135,8 @@ struct perf_sched_map { const char *color_pids_str; struct cpu_map *color_cpus; const char *color_cpus_str; + struct cpu_map *cpus; + const char *cpus_str; }; struct perf_sched { @@ -1469,6 +1471,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, if (curr_thread && thread__has_color(curr_thread)) pid_color = COLOR_PIDS; + if (sched->map.cpus && !cpu_map__has(sched->map.cpus, cpu)) + continue; + if (sched->map.color_cpus && cpu_map__has(sched->map.color_cpus, cpu)) cpu_color = COLOR_CPUS; @@ -1483,6 +1488,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, color_fprintf(stdout, color, " "); } + if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu)) + goto out; + color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { const char *pid_color = color; @@ -1497,6 +1505,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, if (sched->map.comp && new_cpu) color_fprintf(stdout, color, " (CPU %d)", this_cpu); +out: color_fprintf(stdout, color, "\n"); thread__put(sched_in); @@ -1756,6 +1765,8 @@ static int perf_sched__lat(struct perf_sched *sched) static int setup_map_cpus(struct perf_sched *sched) { + struct cpu_map *map; + sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); if (sched->map.comp) { @@ -1764,6 +1775,16 @@ static int setup_map_cpus(struct perf_sched *sched) return -1; } + if (!sched->map.cpus_str) + return 0; + + map = cpu_map__new(sched->map.cpus_str); + if (!map) { + pr_err("failed to get cpus map from %s\n", sched->map.cpus_str); + return -1; + } + + sched->map.cpus = map; return 0; } @@ -1971,6 +1992,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "highlight given pids in map"), OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus", "highlight given CPUs in map"), + OPT_STRING(0, "cpus", &sched.map.cpus_str, "cpus", + "display given CPUs in map"), OPT_END() }; const char * const latency_usage[] = { -- GitLab From e20ab86e51218f9949f41fb39a6c4f63b662f135 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 12 Apr 2016 15:16:15 -0300 Subject: [PATCH 2488/9938] perf evsel: Move some methods from session.[ch] to evsel.[ch] Those were converted to be evsel methods long ago, move the source to where it belongs. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-vja8rjmkw3gd5ungaeyb5s2j@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 14 ++-- tools/perf/builtin-trace.c | 6 +- tools/perf/util/evsel.c | 131 ++++++++++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 13 ++++ tools/perf/util/session.c | 130 ----------------------------------- tools/perf/util/session.h | 13 ---- 6 files changed, 154 insertions(+), 153 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index ddd5b79e94c2..838c0bc38105 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -317,19 +317,19 @@ static void set_print_ip_opts(struct perf_event_attr *attr) output[type].print_ip_opts = 0; if (PRINT_FIELD(IP)) - output[type].print_ip_opts |= PRINT_IP_OPT_IP; + output[type].print_ip_opts |= EVSEL__PRINT_IP; if (PRINT_FIELD(SYM)) - output[type].print_ip_opts |= PRINT_IP_OPT_SYM; + output[type].print_ip_opts |= EVSEL__PRINT_SYM; if (PRINT_FIELD(DSO)) - output[type].print_ip_opts |= PRINT_IP_OPT_DSO; + output[type].print_ip_opts |= EVSEL__PRINT_DSO; if (PRINT_FIELD(SYMOFFSET)) - output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; + output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET; if (PRINT_FIELD(SRCLINE)) - output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; + output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE; } /* @@ -574,9 +574,9 @@ static void print_sample_bts(struct perf_sample *sample, printf("\n"); } else { printf(" "); - if (print_opts & PRINT_IP_OPT_SRCLINE) { + if (print_opts & EVSEL__PRINT_SRCLINE) { print_srcline_last = true; - print_opts &= ~PRINT_IP_OPT_SRCLINE; + print_opts &= ~EVSEL__PRINT_SRCLINE; } } perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts, diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a6e05e1bb350..b842ddd3ad0c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2119,9 +2119,9 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evse { struct addr_location al; /* TODO: user-configurable print_opts */ - const unsigned int print_opts = PRINT_IP_OPT_SYM | - PRINT_IP_OPT_DSO | - PRINT_IP_OPT_UNKNOWN_AS_ADDR; + const unsigned int print_opts = EVSEL__PRINT_SYM | + EVSEL__PRINT_DSO | + EVSEL__PRINT_UNKNOWN_AS_ADDR; if (sample->callchain == NULL) return 0; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d475a4ec8b57..6e86598682be 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2343,6 +2343,137 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, return ++printed; } +int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) +{ + int printed = 0; + struct callchain_cursor_node *node; + int print_ip = print_opts & EVSEL__PRINT_IP; + int print_sym = print_opts & EVSEL__PRINT_SYM; + int print_dso = print_opts & EVSEL__PRINT_DSO; + int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; + int print_oneline = print_opts & EVSEL__PRINT_ONELINE; + int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; + int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; + char s = print_oneline ? ' ' : '\t'; + + if (sample->callchain) { + struct addr_location node_al; + + if (thread__resolve_callchain(al->thread, evsel, + sample, NULL, NULL, + stack_depth) != 0) { + if (verbose) + error("Failed to resolve callchain. Skipping\n"); + return printed; + } + callchain_cursor_commit(&callchain_cursor); + + if (print_symoffset) + node_al = *al; + + while (stack_depth) { + u64 addr = 0; + + node = callchain_cursor_current(&callchain_cursor); + if (!node) + break; + + if (node->sym && node->sym->ignore) + goto next; + + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + + if (print_ip) + printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); + + if (node->map) + addr = node->map->map_ip(node->map, node->ip); + + if (print_sym) { + printed += fprintf(fp, " "); + node_al.addr = addr; + node_al.map = node->map; + + if (print_symoffset) { + printed += __symbol__fprintf_symname_offs(node->sym, &node_al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(node->sym, &node_al, + print_unknown_as_addr, fp); + } + } + + if (print_dso) { + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(node->map, fp); + printed += fprintf(fp, ")"); + } + + if (print_srcline) + printed += map__fprintf_srcline(node->map, addr, "\n ", fp); + + if (!print_oneline) + printed += fprintf(fp, "\n"); + + stack_depth--; +next: + callchain_cursor_advance(&callchain_cursor); + } + } + + return printed; +} + +int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) +{ + int printed = 0; + int print_ip = print_opts & EVSEL__PRINT_IP; + int print_sym = print_opts & EVSEL__PRINT_SYM; + int print_dso = print_opts & EVSEL__PRINT_DSO; + int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; + int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; + int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; + + if (symbol_conf.use_callchain && sample->callchain) { + printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, + print_opts, stack_depth, fp); + } else if (!(al->sym && al->sym->ignore)) { + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + + if (print_ip) + printed += fprintf(fp, "%16" PRIx64, sample->ip); + + if (print_sym) { + printed += fprintf(fp, " "); + if (print_symoffset) { + printed += __symbol__fprintf_symname_offs(al->sym, al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(al->sym, al, + print_unknown_as_addr, fp); + } + } + + if (print_dso) { + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(al->map, fp); + printed += fprintf(fp, ")"); + } + + if (print_srcline) + printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); + } + + return printed; +} + + bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1bd6c2e02dfa..36edd3c91d5c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -387,12 +387,25 @@ struct perf_attr_details { int perf_evsel__fprintf(struct perf_evsel *evsel, struct perf_attr_details *details, FILE *fp); +#define EVSEL__PRINT_IP (1<<0) +#define EVSEL__PRINT_SYM (1<<1) +#define EVSEL__PRINT_DSO (1<<2) +#define EVSEL__PRINT_SYMOFFSET (1<<3) +#define EVSEL__PRINT_ONELINE (1<<4) +#define EVSEL__PRINT_SRCLINE (1<<5) +#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6) + int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, int left_alignment, unsigned int print_opts, unsigned int stack_depth, FILE *fp); +int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp); + bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0516d06a2741..91d4528d71fa 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1953,136 +1953,6 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, return NULL; } -int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) -{ - int printed = 0; - struct callchain_cursor_node *node; - int print_ip = print_opts & PRINT_IP_OPT_IP; - int print_sym = print_opts & PRINT_IP_OPT_SYM; - int print_dso = print_opts & PRINT_IP_OPT_DSO; - int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; - int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; - int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; - int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR; - char s = print_oneline ? ' ' : '\t'; - - if (sample->callchain) { - struct addr_location node_al; - - if (thread__resolve_callchain(al->thread, evsel, - sample, NULL, NULL, - stack_depth) != 0) { - if (verbose) - error("Failed to resolve callchain. Skipping\n"); - return printed; - } - callchain_cursor_commit(&callchain_cursor); - - if (print_symoffset) - node_al = *al; - - while (stack_depth) { - u64 addr = 0; - - node = callchain_cursor_current(&callchain_cursor); - if (!node) - break; - - if (node->sym && node->sym->ignore) - goto next; - - printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); - - if (print_ip) - printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); - - if (node->map) - addr = node->map->map_ip(node->map, node->ip); - - if (print_sym) { - printed += fprintf(fp, " "); - node_al.addr = addr; - node_al.map = node->map; - - if (print_symoffset) { - printed += __symbol__fprintf_symname_offs(node->sym, &node_al, - print_unknown_as_addr, fp); - } else { - printed += __symbol__fprintf_symname(node->sym, &node_al, - print_unknown_as_addr, fp); - } - } - - if (print_dso) { - printed += fprintf(fp, " ("); - printed += map__fprintf_dsoname(node->map, fp); - printed += fprintf(fp, ")"); - } - - if (print_srcline) - printed += map__fprintf_srcline(node->map, addr, "\n ", fp); - - if (!print_oneline) - printed += fprintf(fp, "\n"); - - stack_depth--; -next: - callchain_cursor_advance(&callchain_cursor); - } - } - - return printed; -} - -int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) -{ - int printed = 0; - int print_ip = print_opts & PRINT_IP_OPT_IP; - int print_sym = print_opts & PRINT_IP_OPT_SYM; - int print_dso = print_opts & PRINT_IP_OPT_DSO; - int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; - int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; - int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR; - - if (symbol_conf.use_callchain && sample->callchain) { - printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, - print_opts, stack_depth, fp); - } else if (!(al->sym && al->sym->ignore)) { - printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); - - if (print_ip) - printed += fprintf(fp, "%16" PRIx64, sample->ip); - - if (print_sym) { - printed += fprintf(fp, " "); - if (print_symoffset) { - printed += __symbol__fprintf_symname_offs(al->sym, al, - print_unknown_as_addr, fp); - } else { - printed += __symbol__fprintf_symname(al->sym, al, - print_unknown_as_addr, fp); - } - } - - if (print_dso) { - printed += fprintf(fp, " ("); - printed += map__fprintf_dsoname(al->map, fp); - printed += fprintf(fp, ")"); - } - - if (print_srcline) - printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); - } - - return printed; -} - int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap) { diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 4257fac56618..4bd758553450 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -36,14 +36,6 @@ struct perf_session { struct perf_tool *tool; }; -#define PRINT_IP_OPT_IP (1<<0) -#define PRINT_IP_OPT_SYM (1<<1) -#define PRINT_IP_OPT_DSO (1<<2) -#define PRINT_IP_OPT_SYMOFFSET (1<<3) -#define PRINT_IP_OPT_ONELINE (1<<4) -#define PRINT_IP_OPT_SRCLINE (1<<5) -#define PRINT_IP_OPT_UNKNOWN_AS_ADDR (1<<6) - struct perf_tool; struct perf_session *perf_session__new(struct perf_data_file *file, @@ -105,11 +97,6 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); -int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp); - int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap); -- GitLab From 59247e33ff494e3643cdff54b64bf72575052b76 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 12 Apr 2016 16:05:02 -0300 Subject: [PATCH 2489/9938] perf trace: Do not accept --no-syscalls together with -e Doesn't make sense and was causing a segfault, fix it. # trace -e clone --no-syscalls --event sched:*exec firefox The -e option can't be used with --no-syscalls. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-ccrahezikdk2uebptzr1eyyi@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b842ddd3ad0c..d49c131bb5de 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3344,6 +3344,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) goto out; } + err = -1; + if (trace.trace_pgfaults) { trace.opts.sample_address = true; trace.opts.sample_time = true; @@ -3368,6 +3370,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) return -1; } + if (!trace.trace_syscalls && ev_qualifier_str) { + pr_err("The -e option can't be used with --no-syscalls.\n"); + goto out; + } + if (output_name != NULL) { err = trace__open_output(&trace, output_name); if (err < 0) { -- GitLab From 6ba20a00a36bb47c64581bfa08f1606d4bf0589f Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Tue, 15 Mar 2016 15:55:45 +0800 Subject: [PATCH 2490/9938] pinctrl: rockchip: add support the get_direction This patch adds the get_direction to support the gpio interface. The gpio direction is not used on rockchip platform when use the gpio debugfs. Tested on kylin board. (RK3036 SoCs) The repro steps: $/sys/class/gpio/ echo 53 > export $/sys/class/gpio/gpio53# cat direction in In general, the gpio53 should be out value, but the direction is the default value 'in', since the get_direction didn't supported in rockchip pinctrl. So, we should add this patch to support it. Cc: linux-gpio@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Reported-by: Jeffy Chen Signed-off-by: Caesar Wang Reviewed-by: Heiko Stuebner Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-rockchip.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index bf032b9b4c57..0b3fd02c069f 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -1208,6 +1208,16 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, return 0; } +static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(chip); + u32 data; + + data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); + + return !(data & BIT(offset)); +} + /* * The calls to gpio_direction_output() and gpio_direction_input() * leads to this function call (via the pinctrl_gpio_direction_{input|output}() @@ -1741,6 +1751,7 @@ static const struct gpio_chip rockchip_gpiolib_chip = { .free = gpiochip_generic_free, .set = rockchip_gpio_set, .get = rockchip_gpio_get, + .get_direction = rockchip_gpio_get_direction, .direction_input = rockchip_gpio_direction_input, .direction_output = rockchip_gpio_direction_output, .to_irq = rockchip_gpio_to_irq, -- GitLab From 7d7b4ae418728916456c6fd03a97ef35345ff30d Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Fri, 25 Mar 2016 17:30:07 +0800 Subject: [PATCH 2491/9938] arm64: cpufeature: append additional id_aa64mmfr2 fields to cpufeature There are some new cpu features which can be identified by id_aa64mmfr2, this patch appends all fields of it. Signed-off-by: Kefeng Wang Signed-off-by: Will Deacon --- arch/arm64/include/asm/sysreg.h | 4 ++++ arch/arm64/kernel/cpufeature.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 12874164b0ae..19182ef18f8f 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -145,7 +145,11 @@ #define ID_AA64MMFR1_VMIDBITS_16 2 /* id_aa64mmfr2 */ +#define ID_AA64MMFR2_LVA_SHIFT 16 +#define ID_AA64MMFR2_IESB_SHIFT 12 +#define ID_AA64MMFR2_LSM_SHIFT 8 #define ID_AA64MMFR2_UAO_SHIFT 4 +#define ID_AA64MMFR2_CNP_SHIFT 0 /* id_aa64dfr0 */ #define ID_AA64DFR0_CTX_CMPS_SHIFT 28 diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 943f5140e0f3..677f17cd05d1 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -130,7 +130,11 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { }; static struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { + ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LVA_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_IESB_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LSM_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_UAO_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_CNP_SHIFT, 4, 0), ARM64_FTR_END, }; -- GitLab From b5fda7ed5c63297d0f43e608b455d82ceabdebf0 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 25 Mar 2016 11:08:55 +0800 Subject: [PATCH 2492/9938] arm64: cpuidle: make arm_cpuidle_suspend() a bit more efficient Currently, we check two pointers: cpu_ops and cpu_suspend on every idle state entry. These pointers check can be avoided: If cpu_ops has not been registered, arm_cpuidle_init() will return -EOPNOTSUPP, so arm_cpuidle_suspend() will never have chance to run. In other word, the cpu_ops check can be avoid. Similarly, the cpu_suspend check could be avoided in this hot path by moving it into arm_cpuidle_init(). I measured the 4096 * time from arm_cpuidle_suspend entry point to the cpu_psci_cpu_suspend entry point. HW platform is Marvell BG4CT STB board. 1. only one shell, no other process, hot-unplug secondary cpus, execute the following cmd while true do sleep 0.2 done before the patch: 1581220ns after the patch: 1579630ns reduced by 0.1% 2. only one shell, no other process, hot-unplug secondary cpus, execute the following cmd while true do md5sum /tmp/testfile sleep 0.2 done NOTE: the testfile size should be larger than L1+L2 cache size before the patch: 1961960ns after the patch: 1912500ns reduced by 2.5% So the more complex the system load, the bigger the improvement. Signed-off-by: Jisheng Zhang Acked-by: Lorenzo Pieralisi Signed-off-by: Will Deacon --- arch/arm64/kernel/cpuidle.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c index 9047cab68fd3..e11857fce05f 100644 --- a/arch/arm64/kernel/cpuidle.c +++ b/arch/arm64/kernel/cpuidle.c @@ -19,7 +19,8 @@ int __init arm_cpuidle_init(unsigned int cpu) { int ret = -EOPNOTSUPP; - if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_init_idle) + if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_suspend && + cpu_ops[cpu]->cpu_init_idle) ret = cpu_ops[cpu]->cpu_init_idle(cpu); return ret; @@ -36,11 +37,5 @@ int arm_cpuidle_suspend(int index) { int cpu = smp_processor_id(); - /* - * If cpu_ops have not been registered or suspend - * has not been initialized, cpu_suspend call fails early. - */ - if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend) - return -EOPNOTSUPP; return cpu_ops[cpu]->cpu_suspend(index); } -- GitLab From c875a7093f0479215cf9bf51356d7638f2ec5746 Mon Sep 17 00:00:00 2001 From: "Guilherme G. Piccoli" Date: Wed, 13 Apr 2016 11:08:20 -0300 Subject: [PATCH 2493/9938] nvme: Avoid reset work on watchdog timer function during error recovery This patch adds a check on nvme_watchdog_timer() function to avoid the call to reset_work() when an error recovery process is ongoing on controller. The check is made by looking at pci_channel_offline() result. If we don't check for this on nvme_watchdog_timer(), error recovery mechanism can't recover well, because reset_work() won't be able to do its job (since we're in the middle of an error) and so the controller is removed from the system before error recovery mechanism can perform slot reset (which would allow the adapter to recover). In this patch we also have split the huge condition expression on nvme_watchdog_timer() by introducing an auxiliary function to help make the code more readable. Reviewed-by: Keith Busch Reviewed-by: Johannes Thumshirn Signed-off-by: Guilherme G. Piccoli Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 36b6cdf22de3..ff3c8d7ca882 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1303,22 +1303,44 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev) return result; } +static bool nvme_should_reset(struct nvme_dev *dev, u32 csts) +{ + + /* If true, indicates loss of adapter communication, possibly by a + * NVMe Subsystem reset. + */ + bool nssro = dev->subsystem && (csts & NVME_CSTS_NSSRO); + + /* If there is a reset ongoing, we shouldn't reset again. */ + if (work_busy(&dev->reset_work)) + return false; + + /* We shouldn't reset unless the controller is on fatal error state + * _or_ if we lost the communication with it. + */ + if (!(csts & NVME_CSTS_CFS) && !nssro) + return false; + + /* If PCI error recovery process is happening, we cannot reset or + * the recovery mechanism will surely fail. + */ + if (pci_channel_offline(to_pci_dev(dev->dev))) + return false; + + return true; +} + static void nvme_watchdog_timer(unsigned long data) { struct nvme_dev *dev = (struct nvme_dev *)data; u32 csts = readl(dev->bar + NVME_REG_CSTS); - /* - * Skip controllers currently under reset. - */ - if (!work_pending(&dev->reset_work) && !work_busy(&dev->reset_work) && - ((csts & NVME_CSTS_CFS) || - (dev->subsystem && (csts & NVME_CSTS_NSSRO)))) { - if (queue_work(nvme_workq, &dev->reset_work)) { + /* Skip controllers under certain specific conditions. */ + if (nvme_should_reset(dev, csts)) { + if (queue_work(nvme_workq, &dev->reset_work)) dev_warn(dev->dev, "Failed status: 0x%x, reset controller.\n", csts); - } return; } -- GitLab From 4c4d7f878589585d32b81aab6ed4a5066fae1091 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 7 Apr 2016 16:49:43 +0300 Subject: [PATCH 2494/9938] dmaengine: core: Revert back to pr_debug in __dma_request_channel() Commit ef859312c3a1 ("dmaengine: core: Use dev_ functions for debug and error prints") wasn't quite right in __dma_request_channel() by claiming that all pr_ prints have valid DMA channel pointer. Obviously it is not true as __dma_request_channel() is looking for a channel and returns NULL if it does not find it. Prevent this potential NULL pointer dereference by reverting back to pr_debug(). Signed-off-by: Jarkko Nikula Reported-by: Dan Carpenter Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index a7131d4141d8..ca1400d66957 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -664,7 +664,7 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, } mutex_unlock(&dma_list_mutex); - dev_dbg(chan->device->dev, "%s: %s (%s)\n", + pr_debug("%s: %s (%s)\n", __func__, chan ? "success" : "fail", chan ? dma_chan_name(chan) : NULL); -- GitLab From 5edafc29829bc2a134c22f667c9ac5cb808a1c82 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 22 Mar 2016 09:06:22 -0700 Subject: [PATCH 2495/9938] ARM: dts: k2*: Rename the k2* files to keystone-k2* files As reported in [1], rename the k2* dts files to keystone-* files this will force consistency throughout. Script for the same (and hand modified for Makefile and MAINTAINERS files): for i in arch/arm/boot/dts/k2* do b=`basename $i`; git mv $i arch/arm/boot/dts/keystone-$b; sed -i -e "s/$b/keystone-$b/g" arch/arm/boot/dts/*[si] done NOTE: bootloaders that depend on older dtb names will need to be updated as well. [1] http://marc.info/?l=linux-arm-kernel&m=145637407804754&w=2 Reported-by: Olof Johansson Signed-off-by: Nishanth Menon Signed-off-by: Santosh Shilimkar --- MAINTAINERS | 2 +- arch/arm/boot/dts/Makefile | 6 +++--- .../boot/dts/{k2e-clocks.dtsi => keystone-k2e-clocks.dtsi} | 0 arch/arm/boot/dts/{k2e-evm.dts => keystone-k2e-evm.dts} | 2 +- .../boot/dts/{k2e-netcp.dtsi => keystone-k2e-netcp.dtsi} | 0 arch/arm/boot/dts/{k2e.dtsi => keystone-k2e.dtsi} | 4 ++-- .../dts/{k2hk-clocks.dtsi => keystone-k2hk-clocks.dtsi} | 0 arch/arm/boot/dts/{k2hk-evm.dts => keystone-k2hk-evm.dts} | 2 +- .../boot/dts/{k2hk-netcp.dtsi => keystone-k2hk-netcp.dtsi} | 0 arch/arm/boot/dts/{k2hk.dtsi => keystone-k2hk.dtsi} | 4 ++-- .../boot/dts/{k2l-clocks.dtsi => keystone-k2l-clocks.dtsi} | 0 arch/arm/boot/dts/{k2l-evm.dts => keystone-k2l-evm.dts} | 2 +- .../boot/dts/{k2l-netcp.dtsi => keystone-k2l-netcp.dtsi} | 0 arch/arm/boot/dts/{k2l.dtsi => keystone-k2l.dtsi} | 4 ++-- 14 files changed, 13 insertions(+), 13 deletions(-) rename arch/arm/boot/dts/{k2e-clocks.dtsi => keystone-k2e-clocks.dtsi} (100%) rename arch/arm/boot/dts/{k2e-evm.dts => keystone-k2e-evm.dts} (98%) rename arch/arm/boot/dts/{k2e-netcp.dtsi => keystone-k2e-netcp.dtsi} (100%) rename arch/arm/boot/dts/{k2e.dtsi => keystone-k2e.dtsi} (97%) rename arch/arm/boot/dts/{k2hk-clocks.dtsi => keystone-k2hk-clocks.dtsi} (100%) rename arch/arm/boot/dts/{k2hk-evm.dts => keystone-k2hk-evm.dts} (99%) rename arch/arm/boot/dts/{k2hk-netcp.dtsi => keystone-k2hk-netcp.dtsi} (100%) rename arch/arm/boot/dts/{k2hk.dtsi => keystone-k2hk.dtsi} (96%) rename arch/arm/boot/dts/{k2l-clocks.dtsi => keystone-k2l-clocks.dtsi} (100%) rename arch/arm/boot/dts/{k2l-evm.dts => keystone-k2l-evm.dts} (98%) rename arch/arm/boot/dts/{k2l-netcp.dtsi => keystone-k2l-netcp.dtsi} (100%) rename arch/arm/boot/dts/{k2l.dtsi => keystone-k2l.dtsi} (96%) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..b618aa92eeed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1260,7 +1260,7 @@ M: Santosh Shilimkar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-keystone/ -F: arch/arm/boot/dts/k2* +F: arch/arm/boot/dts/keystone-* T: git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git ARM/TEXAS INSTRUMENT KEYSTONE CLOCK FRAMEWORK diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..b25621ae2ff7 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -158,9 +158,9 @@ dtb-$(CONFIG_ARCH_INTEGRATOR) += \ integratorap.dtb \ integratorcp.dtb dtb-$(CONFIG_ARCH_KEYSTONE) += \ - k2hk-evm.dtb \ - k2l-evm.dtb \ - k2e-evm.dtb \ + keystone-k2hk-evm.dtb \ + keystone-k2l-evm.dtb \ + keystone-k2e-evm.dtb \ keystone-k2g-evm.dtb dtb-$(CONFIG_MACH_KIRKWOOD) += \ kirkwood-b3.dtb \ diff --git a/arch/arm/boot/dts/k2e-clocks.dtsi b/arch/arm/boot/dts/keystone-k2e-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/k2e-clocks.dtsi rename to arch/arm/boot/dts/keystone-k2e-clocks.dtsi diff --git a/arch/arm/boot/dts/k2e-evm.dts b/arch/arm/boot/dts/keystone-k2e-evm.dts similarity index 98% rename from arch/arm/boot/dts/k2e-evm.dts rename to arch/arm/boot/dts/keystone-k2e-evm.dts index b7e99807f5c2..4c32ebc1425a 100644 --- a/arch/arm/boot/dts/k2e-evm.dts +++ b/arch/arm/boot/dts/keystone-k2e-evm.dts @@ -10,7 +10,7 @@ /dts-v1/; #include "keystone.dtsi" -#include "k2e.dtsi" +#include "keystone-k2e.dtsi" / { compatible = "ti,k2e-evm", "ti,k2e", "ti,keystone"; diff --git a/arch/arm/boot/dts/k2e-netcp.dtsi b/arch/arm/boot/dts/keystone-k2e-netcp.dtsi similarity index 100% rename from arch/arm/boot/dts/k2e-netcp.dtsi rename to arch/arm/boot/dts/keystone-k2e-netcp.dtsi diff --git a/arch/arm/boot/dts/k2e.dtsi b/arch/arm/boot/dts/keystone-k2e.dtsi similarity index 97% rename from arch/arm/boot/dts/k2e.dtsi rename to arch/arm/boot/dts/keystone-k2e.dtsi index 1097dada56d2..96b349fb0430 100644 --- a/arch/arm/boot/dts/k2e.dtsi +++ b/arch/arm/boot/dts/keystone-k2e.dtsi @@ -44,7 +44,7 @@ }; soc { - /include/ "k2e-clocks.dtsi" + /include/ "keystone-k2e-clocks.dtsi" usb: usb@2680000 { interrupts = ; @@ -145,6 +145,6 @@ clock-names = "fck"; bus_freq = <2500000>; }; - /include/ "k2e-netcp.dtsi" + /include/ "keystone-k2e-netcp.dtsi" }; }; diff --git a/arch/arm/boot/dts/k2hk-clocks.dtsi b/arch/arm/boot/dts/keystone-k2hk-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/k2hk-clocks.dtsi rename to arch/arm/boot/dts/keystone-k2hk-clocks.dtsi diff --git a/arch/arm/boot/dts/k2hk-evm.dts b/arch/arm/boot/dts/keystone-k2hk-evm.dts similarity index 99% rename from arch/arm/boot/dts/k2hk-evm.dts rename to arch/arm/boot/dts/keystone-k2hk-evm.dts index 8161bf53271b..b38b3441818b 100644 --- a/arch/arm/boot/dts/k2hk-evm.dts +++ b/arch/arm/boot/dts/keystone-k2hk-evm.dts @@ -10,7 +10,7 @@ /dts-v1/; #include "keystone.dtsi" -#include "k2hk.dtsi" +#include "keystone-k2hk.dtsi" / { compatible = "ti,k2hk-evm", "ti,k2hk", "ti,keystone"; diff --git a/arch/arm/boot/dts/k2hk-netcp.dtsi b/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi similarity index 100% rename from arch/arm/boot/dts/k2hk-netcp.dtsi rename to arch/arm/boot/dts/keystone-k2hk-netcp.dtsi diff --git a/arch/arm/boot/dts/k2hk.dtsi b/arch/arm/boot/dts/keystone-k2hk.dtsi similarity index 96% rename from arch/arm/boot/dts/k2hk.dtsi rename to arch/arm/boot/dts/keystone-k2hk.dtsi index ada4c7ac96e7..8f67fa8df936 100644 --- a/arch/arm/boot/dts/k2hk.dtsi +++ b/arch/arm/boot/dts/keystone-k2hk.dtsi @@ -44,7 +44,7 @@ }; soc { - /include/ "k2hk-clocks.dtsi" + /include/ "keystone-k2hk-clocks.dtsi" dspgpio0: keystone_dsp_gpio@02620240 { compatible = "ti,keystone-dsp-gpio"; @@ -112,6 +112,6 @@ clock-names = "fck"; bus_freq = <2500000>; }; - /include/ "k2hk-netcp.dtsi" + /include/ "keystone-k2hk-netcp.dtsi" }; }; diff --git a/arch/arm/boot/dts/k2l-clocks.dtsi b/arch/arm/boot/dts/keystone-k2l-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/k2l-clocks.dtsi rename to arch/arm/boot/dts/keystone-k2l-clocks.dtsi diff --git a/arch/arm/boot/dts/k2l-evm.dts b/arch/arm/boot/dts/keystone-k2l-evm.dts similarity index 98% rename from arch/arm/boot/dts/k2l-evm.dts rename to arch/arm/boot/dts/keystone-k2l-evm.dts index 00861244d788..7f9c2e94d605 100644 --- a/arch/arm/boot/dts/k2l-evm.dts +++ b/arch/arm/boot/dts/keystone-k2l-evm.dts @@ -10,7 +10,7 @@ /dts-v1/; #include "keystone.dtsi" -#include "k2l.dtsi" +#include "keystone-k2l.dtsi" / { compatible = "ti,k2l-evm", "ti,k2l", "ti,keystone"; diff --git a/arch/arm/boot/dts/k2l-netcp.dtsi b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi similarity index 100% rename from arch/arm/boot/dts/k2l-netcp.dtsi rename to arch/arm/boot/dts/keystone-k2l-netcp.dtsi diff --git a/arch/arm/boot/dts/k2l.dtsi b/arch/arm/boot/dts/keystone-k2l.dtsi similarity index 96% rename from arch/arm/boot/dts/k2l.dtsi rename to arch/arm/boot/dts/keystone-k2l.dtsi index 4446da72b0ae..ff22ffc3dee7 100644 --- a/arch/arm/boot/dts/k2l.dtsi +++ b/arch/arm/boot/dts/keystone-k2l.dtsi @@ -32,7 +32,7 @@ }; soc { - /include/ "k2l-clocks.dtsi" + /include/ "keystone-k2l-clocks.dtsi" uart2: serial@02348400 { compatible = "ns16550a"; @@ -92,7 +92,7 @@ clock-names = "fck"; bus_freq = <2500000>; }; - /include/ "k2l-netcp.dtsi" + /include/ "keystone-k2l-netcp.dtsi" }; }; -- GitLab From 72f7e9596087ecece7e80bb674f7070bef4edc29 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Wed, 13 Apr 2016 08:53:56 -0700 Subject: [PATCH 2496/9938] ARM: dts: keystone: Add aliases for SPI nodes Add aliases for SPI nodes, this is required to probe the SPI devices in U-Boot. Signed-off-by: Vignesh R Signed-off-by: Santosh Shilimkar --- arch/arm/boot/dts/keystone.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi index 3f272826f537..94d4e45138ce 100644 --- a/arch/arm/boot/dts/keystone.dtsi +++ b/arch/arm/boot/dts/keystone.dtsi @@ -20,6 +20,9 @@ aliases { serial0 = &uart0; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; }; memory { -- GitLab From 14de48a412f00f8e0a5413844d846bc5657db327 Mon Sep 17 00:00:00 2001 From: Vitaly Andrianov Date: Wed, 13 Apr 2016 08:55:17 -0700 Subject: [PATCH 2497/9938] ARM: keystone: dts: add psci command definition This commit adds definition for cpu_on, cpu_off and cpu_suspend commands. These definitions must match the corresponding PSCI definitions in boot monitor. Having those command and corresponding PSCI support in boot monitor allows run time CPU hot plugin. Signed-off-by: Vitaly Andrianov Signed-off-by: Keerthy Signed-off-by: Santosh Shilimkar --- arch/arm/boot/dts/keystone.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi index 94d4e45138ce..e34b2265458a 100644 --- a/arch/arm/boot/dts/keystone.dtsi +++ b/arch/arm/boot/dts/keystone.dtsi @@ -62,6 +62,14 @@ ; }; + psci { + compatible = "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + }; + soc { #address-cells = <1>; #size-cells = <1>; -- GitLab From 9120abdcdb7fd3a51d3135ff37c9dad358dde9ee Mon Sep 17 00:00:00 2001 From: Keerthy Date: Wed, 13 Apr 2016 08:54:52 -0700 Subject: [PATCH 2498/9938] ARM: configs: keystone: Add CPU Hotplug related options Add the config options needed to get CPU hotplug functional. Signed-off-by: Keerthy Signed-off-by: Santosh Shilimkar --- arch/arm/configs/keystone_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig index 5bcc9cf9d8f1..faba04d93ad5 100644 --- a/arch/arm/configs/keystone_defconfig +++ b/arch/arm/configs/keystone_defconfig @@ -30,6 +30,8 @@ CONFIG_PCI=y CONFIG_PCI_MSI=y CONFIG_PCI_KEYSTONE=y CONFIG_SMP=y +CONFIG_HOTPLUG_CPU=y +CONFIG_ARM_PSCI=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_HIGHMEM=y -- GitLab From c422025c185fb2bb28df65b1bbed7953480c7f87 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:24:41 +0200 Subject: [PATCH 2499/9938] dmaengine: dw: rename masters to reflect actual topology The source and destination masters are reflecting buses or their layers to where the different devices can be connected. The patch changes the master names to reflect which one is related to which independently on the transfer direction. The outcome of the change is that the memory data width is now always limited by a data width of the master which is dedicated to communicate to memory. The patch will not break anything since all current users have the same data width for all masters. Though it would be nice to revisit avr32 platforms to check what is the actual hardware topology in use there. It seems that it has one bus and two masters on it as stated by Table 8-2, that's why everything works independently on the master in use. The purpose of the sequential patch is to fix the driver for configuration of more than one bus. The change is done in the assumption that src_master and dst_master are reflecting a connection to the memory and peripheral correspondently on avr32 and otherwise on the rest. Acked-by: Hans-Christian Egtvedt Acked-by: Mark Brown Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/snps-dma.txt | 4 ++-- arch/avr32/mach-at32ap/at32ap700x.c | 16 ++++++++-------- drivers/ata/sata_dwc_460ex.c | 4 ++-- drivers/dma/dw/core.c | 19 +++++++++---------- drivers/dma/dw/platform.c | 12 ++++++------ drivers/dma/dw/regs.h | 4 ++-- drivers/spi/spi-pxa2xx-pci.c | 8 ++++---- drivers/tty/serial/8250/8250_pci.c | 8 ++++---- include/linux/platform_data/dma-dw.h | 8 ++++---- 9 files changed, 41 insertions(+), 42 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt index c261598164a7..c99c1ffac199 100644 --- a/Documentation/devicetree/bindings/dma/snps-dma.txt +++ b/Documentation/devicetree/bindings/dma/snps-dma.txt @@ -47,8 +47,8 @@ The four cells in order are: 1. A phandle pointing to the DMA controller 2. The DMA request line number -3. Source master for transfers on allocated channel -4. Destination master for transfers on allocated channel +3. Memory master for transfers on allocated channel +4. Peripheral master for transfers on allocated channel Example: diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index bf445aa48282..00d6dcc1d9b6 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1365,8 +1365,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) slave->dma_dev = &dw_dmac0_device.dev; slave->src_id = 0; slave->dst_id = 1; - slave->src_master = 1; - slave->dst_master = 0; + slave->m_master = 1; + slave->p_master = 0; data->dma_slave = slave; data->dma_filter = at32_mci_dma_filter; @@ -2061,16 +2061,16 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data, if (flags & AC97C_CAPTURE) { rx_dws->dma_dev = &dw_dmac0_device.dev; rx_dws->src_id = 3; - rx_dws->src_master = 0; - rx_dws->dst_master = 1; + rx_dws->m_master = 0; + rx_dws->p_master = 1; } /* Check if DMA slave interface for playback should be configured. */ if (flags & AC97C_PLAYBACK) { tx_dws->dma_dev = &dw_dmac0_device.dev; tx_dws->dst_id = 4; - tx_dws->src_master = 0; - tx_dws->dst_master = 1; + tx_dws->m_master = 0; + tx_dws->p_master = 1; } if (platform_device_add_data(pdev, data, @@ -2141,8 +2141,8 @@ at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data) dws->dma_dev = &dw_dmac0_device.dev; dws->dst_id = 2; - dws->src_master = 0; - dws->dst_master = 1; + dws->m_master = 0; + dws->p_master = 1; if (platform_device_add_data(pdev, data, sizeof(struct atmel_abdac_pdata))) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 902034991517..80bdcabc293f 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -201,8 +201,8 @@ static struct sata_dwc_host_priv host_pvt; static struct dw_dma_slave sata_dwc_dma_dws = { .src_id = 0, .dst_id = 0, - .src_master = 0, - .dst_master = 1, + .m_master = 1, + .p_master = 0, }; /* diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 97199b3c25a2..5bd7873a02c6 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -50,8 +50,8 @@ | DWC_CTLL_SRC_MSIZE(_smsize) \ | DWC_CTLL_LLP_D_EN \ | DWC_CTLL_LLP_S_EN \ - | DWC_CTLL_DMS(_dwc->dst_master) \ - | DWC_CTLL_SMS(_dwc->src_master)); \ + | DWC_CTLL_DMS(_dwc->p_master) \ + | DWC_CTLL_SMS(_dwc->m_master)); \ }) /* @@ -709,8 +709,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, dwc->direction = DMA_MEM_TO_MEM; - data_width = min_t(unsigned int, dw->data_width[dwc->src_master], - dw->data_width[dwc->dst_master]); + data_width = dw->data_width[dwc->m_master]; src_width = dst_width = min_t(unsigned int, data_width, dwc_fast_ffs(src | dest | len)); @@ -802,7 +801,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : DWC_CTLL_FC(DW_DMA_FC_D_M2P); - data_width = dw->data_width[dwc->src_master]; + data_width = dw->data_width[dwc->m_master]; for_each_sg(sgl, sg, sg_len, i) { struct dw_desc *desc; @@ -859,7 +858,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : DWC_CTLL_FC(DW_DMA_FC_D_P2M); - data_width = dw->data_width[dwc->dst_master]; + data_width = dw->data_width[dwc->m_master]; for_each_sg(sgl, sg, sg_len, i) { struct dw_desc *desc; @@ -937,8 +936,8 @@ bool dw_dma_filter(struct dma_chan *chan, void *param) dwc->src_id = dws->src_id; dwc->dst_id = dws->dst_id; - dwc->src_master = dws->src_master; - dwc->dst_master = dws->dst_master; + dwc->m_master = dws->m_master; + dwc->p_master = dws->p_master; return true; } @@ -1227,8 +1226,8 @@ static void dwc_free_chan_resources(struct dma_chan *chan) dwc->src_id = 0; dwc->dst_id = 0; - dwc->src_master = 0; - dwc->dst_master = 0; + dwc->m_master = 0; + dwc->p_master = 0; dwc->initialized = false; diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 26edbe3a27ac..23616c57645c 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -42,13 +42,13 @@ static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, slave.src_id = dma_spec->args[0]; slave.dst_id = dma_spec->args[0]; - slave.src_master = dma_spec->args[1]; - slave.dst_master = dma_spec->args[2]; + slave.m_master = dma_spec->args[1]; + slave.p_master = dma_spec->args[2]; if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS || slave.dst_id >= DW_DMA_MAX_NR_REQUESTS || - slave.src_master >= dw->nr_masters || - slave.dst_master >= dw->nr_masters)) + slave.m_master >= dw->nr_masters || + slave.p_master >= dw->nr_masters)) return NULL; dma_cap_zero(cap); @@ -66,8 +66,8 @@ static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) .dma_dev = dma_spec->dev, .src_id = dma_spec->slave_id, .dst_id = dma_spec->slave_id, - .src_master = 1, - .dst_master = 0, + .m_master = 0, + .p_master = 1, }; return dw_dma_filter(chan, &slave); diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 0a50c18d85b8..a63d62bbffe2 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -249,8 +249,8 @@ struct dw_dma_chan { /* custom slave configuration */ u8 src_id; u8 dst_id; - u8 src_master; - u8 dst_master; + u8 m_master; + u8 p_master; /* configuration passed via .device_config */ struct dma_slave_config dma_sconfig; diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 520ed1dd5780..4fd7f9802f1b 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -144,16 +144,16 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, struct dw_dma_slave *slave = c->tx_param; slave->dma_dev = &dma_dev->dev; - slave->src_master = 1; - slave->dst_master = 0; + slave->m_master = 0; + slave->p_master = 1; } if (c->rx_param) { struct dw_dma_slave *slave = c->rx_param; slave->dma_dev = &dma_dev->dev; - slave->src_master = 1; - slave->dst_master = 0; + slave->m_master = 0; + slave->p_master = 1; } spi_pdata.dma_filter = lpss_dma_filter; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 98862aa5bb58..5eea74d7f9f4 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1454,13 +1454,13 @@ byt_serial_setup(struct serial_private *priv, return -EINVAL; } - rx_param->src_master = 1; - rx_param->dst_master = 0; + rx_param->m_master = 0; + rx_param->p_master = 1; dma->rxconf.src_maxburst = 16; - tx_param->src_master = 1; - tx_param->dst_master = 0; + tx_param->m_master = 0; + tx_param->p_master = 1; dma->txconf.dst_maxburst = 16; diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h index 03b6095d3b18..b881b978e486 100644 --- a/include/linux/platform_data/dma-dw.h +++ b/include/linux/platform_data/dma-dw.h @@ -21,15 +21,15 @@ * @dma_dev: required DMA master device * @src_id: src request line * @dst_id: dst request line - * @src_master: src master for transfers on allocated channel. - * @dst_master: dest master for transfers on allocated channel. + * @m_master: memory master for transfers on allocated channel + * @p_master: peripheral master for transfers on allocated channel */ struct dw_dma_slave { struct device *dma_dev; u8 src_id; u8 dst_id; - u8 src_master; - u8 dst_master; + u8 m_master; + u8 p_master; }; /** -- GitLab From bb3450ad0ed618fda84fbd2e28065bd7791fd7f9 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 18 Mar 2016 16:24:42 +0200 Subject: [PATCH 2500/9938] dmaengine: dw: set src and dst master select according to xfer direction On some architectures the DMA controller can have two masters connected to different buses and thus access to memory is possible only through one and to peripheral through the other. This patch changes the src and dst master setting to match the direction of the transfer. Signed-off-by: Mans Rullgard Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 5bd7873a02c6..d810980e652d 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -45,13 +45,17 @@ DW_DMA_MSIZE_16; \ u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \ DW_DMA_MSIZE_16; \ + u8 _dms = (_dwc->direction == DMA_MEM_TO_DEV) ? \ + _dwc->p_master : _dwc->m_master; \ + u8 _sms = (_dwc->direction == DMA_DEV_TO_MEM) ? \ + _dwc->p_master : _dwc->m_master; \ \ (DWC_CTLL_DST_MSIZE(_dmsize) \ | DWC_CTLL_SRC_MSIZE(_smsize) \ | DWC_CTLL_LLP_D_EN \ | DWC_CTLL_LLP_S_EN \ - | DWC_CTLL_DMS(_dwc->p_master) \ - | DWC_CTLL_SMS(_dwc->m_master)); \ + | DWC_CTLL_DMS(_dms) \ + | DWC_CTLL_SMS(_sms)); \ }) /* -- GitLab From df1f3a2305d72cbf470758999785f08bcd642d5d Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 18 Mar 2016 16:24:43 +0200 Subject: [PATCH 2501/9938] dmaengine: dw: fix byte order of hw descriptor fields If the DMA controller uses a different byte order than the host CPU, the hardware linked list descriptor fields need to be byte-swapped. This patch makes the driver write these fields using the same byte order it uses for mmio accesses to the DMA engine. I do not know if this is guaranteed to always be correct. Signed-off-by: Mans Rullgard Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 123 +++++++++++++++++++++--------------------- drivers/dma/dw/regs.h | 32 ++++++++--- 2 files changed, 87 insertions(+), 68 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index d810980e652d..be48051502aa 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -201,12 +201,12 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc, * Software emulation of LLP mode relies on interrupts to continue * multi block transfer. */ - ctllo = desc->lli.ctllo | DWC_CTLL_INT_EN; + ctllo = lli_read(desc, ctllo) | DWC_CTLL_INT_EN; - channel_writel(dwc, SAR, desc->lli.sar); - channel_writel(dwc, DAR, desc->lli.dar); + channel_writel(dwc, SAR, lli_read(desc, sar)); + channel_writel(dwc, DAR, lli_read(desc, dar)); channel_writel(dwc, CTL_LO, ctllo); - channel_writel(dwc, CTL_HI, desc->lli.ctlhi); + channel_writel(dwc, CTL_HI, lli_read(desc, ctlhi)); channel_set_bit(dw, CH_EN, dwc->mask); /* Move pointer to next descriptor */ @@ -424,7 +424,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) } /* Check first descriptors llp */ - if (desc->lli.llp == llp) { + if (lli_read(desc, llp) == llp) { /* This one is currently in progress */ dwc->residue -= dwc_get_sent(dwc); spin_unlock_irqrestore(&dwc->lock, flags); @@ -433,7 +433,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) dwc->residue -= desc->len; list_for_each_entry(child, &desc->tx_list, desc_node) { - if (child->lli.llp == llp) { + if (lli_read(child, llp) == llp) { /* Currently in progress */ dwc->residue -= dwc_get_sent(dwc); spin_unlock_irqrestore(&dwc->lock, flags); @@ -461,10 +461,14 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) spin_unlock_irqrestore(&dwc->lock, flags); } -static inline void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli) +static inline void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_desc *desc) { dev_crit(chan2dev(&dwc->chan), " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", - lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo); + lli_read(desc, sar), + lli_read(desc, dar), + lli_read(desc, llp), + lli_read(desc, ctlhi), + lli_read(desc, ctllo)); } static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) @@ -500,9 +504,9 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) */ dev_WARN(chan2dev(&dwc->chan), "Bad descriptor submitted for DMA!\n" " cookie: %d\n", bad_desc->txd.cookie); - dwc_dump_lli(dwc, &bad_desc->lli); + dwc_dump_lli(dwc, bad_desc); list_for_each_entry(child, &bad_desc->tx_list, desc_node) - dwc_dump_lli(dwc, &child->lli); + dwc_dump_lli(dwc, child); spin_unlock_irqrestore(&dwc->lock, flags); @@ -575,7 +579,7 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, dma_writel(dw, CLEAR.XFER, dwc->mask); for (i = 0; i < dwc->cdesc->periods; i++) - dwc_dump_lli(dwc, &dwc->cdesc->desc[i]->lli); + dwc_dump_lli(dwc, dwc->cdesc->desc[i]); spin_unlock_irqrestore(&dwc->lock, flags); } @@ -734,25 +738,24 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, if (!desc) goto err_desc_get; - desc->lli.sar = src + offset; - desc->lli.dar = dest + offset; - desc->lli.ctllo = ctllo; - desc->lli.ctlhi = xfer_count; + lli_write(desc, sar, src + offset); + lli_write(desc, dar, dest + offset); + lli_write(desc, ctllo, ctllo); + lli_write(desc, ctlhi, xfer_count); desc->len = xfer_count << src_width; if (!first) { first = desc; } else { - prev->lli.llp = desc->txd.phys; - list_add_tail(&desc->desc_node, - &first->tx_list); + lli_write(prev, llp, desc->txd.phys); + list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; } if (flags & DMA_PREP_INTERRUPT) /* Trigger interrupt after last block */ - prev->lli.ctllo |= DWC_CTLL_INT_EN; + lli_set(prev, ctllo, DWC_CTLL_INT_EN); prev->lli.llp = 0; first->txd.flags = flags; @@ -822,9 +825,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (!desc) goto err_desc_get; - desc->lli.sar = mem; - desc->lli.dar = reg; - desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width); + lli_write(desc, sar, mem); + lli_write(desc, dar, reg); + lli_write(desc, ctllo, ctllo | DWC_CTLL_SRC_WIDTH(mem_width)); if ((len >> mem_width) > dwc->block_size) { dlen = dwc->block_size << mem_width; mem += dlen; @@ -834,15 +837,14 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, len = 0; } - desc->lli.ctlhi = dlen >> mem_width; + lli_write(desc, ctlhi, dlen >> mem_width); desc->len = dlen; if (!first) { first = desc; } else { - prev->lli.llp = desc->txd.phys; - list_add_tail(&desc->desc_node, - &first->tx_list); + lli_write(prev, llp, desc->txd.phys); + list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; total_len += dlen; @@ -879,9 +881,9 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (!desc) goto err_desc_get; - desc->lli.sar = reg; - desc->lli.dar = mem; - desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width); + lli_write(desc, sar, reg); + lli_write(desc, dar, mem); + lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width)); if ((len >> reg_width) > dwc->block_size) { dlen = dwc->block_size << reg_width; mem += dlen; @@ -890,15 +892,14 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, dlen = len; len = 0; } - desc->lli.ctlhi = dlen >> reg_width; + lli_write(desc, ctlhi, dlen >> reg_width); desc->len = dlen; if (!first) { first = desc; } else { - prev->lli.llp = desc->txd.phys; - list_add_tail(&desc->desc_node, - &first->tx_list); + lli_write(prev, llp, desc->txd.phys); + list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; total_len += dlen; @@ -913,7 +914,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (flags & DMA_PREP_INTERRUPT) /* Trigger interrupt after last block */ - prev->lli.ctllo |= DWC_CTLL_INT_EN; + lli_set(prev, ctllo, DWC_CTLL_INT_EN); prev->lli.llp = 0; first->total_len = total_len; @@ -1400,50 +1401,50 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, switch (direction) { case DMA_MEM_TO_DEV: - desc->lli.dar = sconfig->dst_addr; - desc->lli.sar = buf_addr + (period_len * i); - desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan) - | DWC_CTLL_DST_WIDTH(reg_width) - | DWC_CTLL_SRC_WIDTH(reg_width) - | DWC_CTLL_DST_FIX - | DWC_CTLL_SRC_INC - | DWC_CTLL_INT_EN); - - desc->lli.ctllo |= sconfig->device_fc ? - DWC_CTLL_FC(DW_DMA_FC_P_M2P) : - DWC_CTLL_FC(DW_DMA_FC_D_M2P); + lli_write(desc, dar, sconfig->dst_addr); + lli_write(desc, sar, buf_addr + period_len * i); + lli_write(desc, ctllo, (DWC_DEFAULT_CTLLO(chan) + | DWC_CTLL_DST_WIDTH(reg_width) + | DWC_CTLL_SRC_WIDTH(reg_width) + | DWC_CTLL_DST_FIX + | DWC_CTLL_SRC_INC + | DWC_CTLL_INT_EN)); + + lli_set(desc, ctllo, sconfig->device_fc ? + DWC_CTLL_FC(DW_DMA_FC_P_M2P) : + DWC_CTLL_FC(DW_DMA_FC_D_M2P)); break; case DMA_DEV_TO_MEM: - desc->lli.dar = buf_addr + (period_len * i); - desc->lli.sar = sconfig->src_addr; - desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan) - | DWC_CTLL_SRC_WIDTH(reg_width) - | DWC_CTLL_DST_WIDTH(reg_width) - | DWC_CTLL_DST_INC - | DWC_CTLL_SRC_FIX - | DWC_CTLL_INT_EN); - - desc->lli.ctllo |= sconfig->device_fc ? - DWC_CTLL_FC(DW_DMA_FC_P_P2M) : - DWC_CTLL_FC(DW_DMA_FC_D_P2M); + lli_write(desc, dar, buf_addr + period_len * i); + lli_write(desc, sar, sconfig->src_addr); + lli_write(desc, ctllo, (DWC_DEFAULT_CTLLO(chan) + | DWC_CTLL_SRC_WIDTH(reg_width) + | DWC_CTLL_DST_WIDTH(reg_width) + | DWC_CTLL_DST_INC + | DWC_CTLL_SRC_FIX + | DWC_CTLL_INT_EN)); + + lli_set(desc, ctllo, sconfig->device_fc ? + DWC_CTLL_FC(DW_DMA_FC_P_P2M) : + DWC_CTLL_FC(DW_DMA_FC_D_P2M)); break; default: break; } - desc->lli.ctlhi = (period_len >> reg_width); + lli_write(desc, ctlhi, period_len >> reg_width); cdesc->desc[i] = desc; if (last) - last->lli.llp = desc->txd.phys; + lli_write(last, llp, desc->txd.phys); last = desc; } /* Let's make a cyclic list */ - last->lli.llp = cdesc->desc[0]->txd.phys; + lli_write(last, llp, cdesc->desc[0]->txd.phys); dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf %pad len %zu period %zu periods %d\n", diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index a63d62bbffe2..6571100a07e4 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -308,26 +308,44 @@ static inline struct dw_dma *to_dw_dma(struct dma_device *ddev) return container_of(ddev, struct dw_dma, dma); } +#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO +typedef __be32 __dw32; +#else +typedef __le32 __dw32; +#endif + /* LLI == Linked List Item; a.k.a. DMA block descriptor */ struct dw_lli { /* values that are not changed by hardware */ - u32 sar; - u32 dar; - u32 llp; /* chain to next lli */ - u32 ctllo; + __dw32 sar; + __dw32 dar; + __dw32 llp; /* chain to next lli */ + __dw32 ctllo; /* values that may get written back: */ - u32 ctlhi; + __dw32 ctlhi; /* sstat and dstat can snapshot peripheral register state. * silicon config may discard either or both... */ - u32 sstat; - u32 dstat; + __dw32 sstat; + __dw32 dstat; }; struct dw_desc { /* FIRST values the hardware uses */ struct dw_lli lli; +#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO +#define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_be32(v)) +#define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_be32(v)) +#define lli_read(d, reg) be32_to_cpu((d)->lli.reg) +#define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_be32(v)) +#else +#define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_le32(v)) +#define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_le32(v)) +#define lli_read(d, reg) le32_to_cpu((d)->lli.reg) +#define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_le32(v)) +#endif + /* THEN values for driver housekeeping */ struct list_head desc_node; struct list_head tx_list; -- GitLab From 2a0fae025e56afbe38441d411f57667b08f44d0e Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 18 Mar 2016 16:24:44 +0200 Subject: [PATCH 2502/9938] dmaengine: dw: set LMS field in descriptors The LMS field indicates from which master the descriptor is to be read. This patch assumes this is always the same as the memory side in a peripheral transfer which is true for all known systems. Signed-off-by: Mans Rullgard Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 26 ++++++++++++++------------ drivers/dma/dw/regs.h | 4 ++++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index be48051502aa..23bb460fff6a 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -217,6 +217,7 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc, static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) { struct dw_dma *dw = to_dw_dma(dwc->chan.device); + u8 lms = DWC_LLP_LMS(dwc->m_master); unsigned long was_soft_llp; /* ASSERT: channel is idle */ @@ -252,9 +253,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) dwc_initialize(dwc); - channel_writel(dwc, LLP, first->txd.phys); - channel_writel(dwc, CTL_LO, - DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); + channel_writel(dwc, LLP, first->txd.phys | lms); + channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); channel_writel(dwc, CTL_HI, 0); channel_set_bit(dw, CH_EN, dwc->mask); } @@ -418,7 +418,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) dwc->residue = desc->total_len; /* Check first descriptors addr */ - if (desc->txd.phys == llp) { + if (desc->txd.phys == DWC_LLP_LOC(llp)) { spin_unlock_irqrestore(&dwc->lock, flags); return; } @@ -705,6 +705,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, unsigned int dst_width; unsigned int data_width; u32 ctllo; + u8 lms = DWC_LLP_LMS(dwc->m_master); dev_vdbg(chan2dev(chan), "%s: d%pad s%pad l0x%zx f0x%lx\n", __func__, @@ -747,7 +748,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, if (!first) { first = desc; } else { - lli_write(prev, llp, desc->txd.phys); + lli_write(prev, llp, desc->txd.phys | lms); list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; @@ -779,6 +780,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, struct dw_desc *prev; struct dw_desc *first; u32 ctllo; + u8 lms = DWC_LLP_LMS(dwc->m_master); dma_addr_t reg; unsigned int reg_width; unsigned int mem_width; @@ -843,7 +845,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (!first) { first = desc; } else { - lli_write(prev, llp, desc->txd.phys); + lli_write(prev, llp, desc->txd.phys | lms); list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; @@ -898,7 +900,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (!first) { first = desc; } else { - lli_write(prev, llp, desc->txd.phys); + lli_write(prev, llp, desc->txd.phys | lms); list_add_tail(&desc->desc_node, &first->tx_list); } prev = desc; @@ -1330,6 +1332,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, struct dw_cyclic_desc *retval = NULL; struct dw_desc *desc; struct dw_desc *last = NULL; + u8 lms = DWC_LLP_LMS(dwc->m_master); unsigned long was_cyclic; unsigned int reg_width; unsigned int periods; @@ -1438,13 +1441,13 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, cdesc->desc[i] = desc; if (last) - lli_write(last, llp, desc->txd.phys); + lli_write(last, llp, desc->txd.phys | lms); last = desc; } /* Let's make a cyclic list */ - lli_write(last, llp, cdesc->desc[0]->txd.phys); + lli_write(last, llp, cdesc->desc[0]->txd.phys | lms); dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf %pad len %zu period %zu periods %d\n", @@ -1646,9 +1649,8 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dwc->block_size = pdata->block_size; /* Check if channel supports multi block transfer */ - channel_writel(dwc, LLP, 0xfffffffc); - dwc->nollp = - (channel_readl(dwc, LLP) & 0xfffffffc) == 0; + channel_writel(dwc, LLP, DWC_LLP_LOC(0xffffffff)); + dwc->nollp = DWC_LLP_LOC(channel_readl(dwc, LLP)) == 0; channel_writel(dwc, LLP, 0); } } diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 6571100a07e4..59d6cec01dca 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -143,6 +143,10 @@ enum dw_dma_msize { DW_DMA_MSIZE_256, }; +/* Bitfields in LLP */ +#define DWC_LLP_LMS(x) ((x) & 3) /* list master select */ +#define DWC_LLP_LOC(x) ((x) & ~3) /* next lli */ + /* Bitfields in CTL_LO */ #define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ #define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ -- GitLab From a3e557999be74810e02be1d0c107096b7aa48ece Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 18 Mar 2016 16:24:45 +0200 Subject: [PATCH 2503/9938] dmaengine: dw: clear LLP_[SD]_EN bits in last descriptor of a chain The datasheet requires that the LLP_[SD]_EN bits be cleared whenever LLP.LOC is zero, i.e. in the last descriptor of a multi-block chain. Make the driver do this. Signed-off-by: Mans Rullgard Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 23bb460fff6a..db9b6f433148 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -759,6 +759,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, lli_set(prev, ctllo, DWC_CTLL_INT_EN); prev->lli.llp = 0; + lli_clear(prev, ctllo, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); first->txd.flags = flags; first->total_len = len; @@ -919,6 +920,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, lli_set(prev, ctllo, DWC_CTLL_INT_EN); prev->lli.llp = 0; + lli_clear(prev, ctllo, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); first->total_len = total_len; return &first->txd; -- GitLab From 897e40d3b19c9ea2013aee419302c0f6e9ae287e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:24:46 +0200 Subject: [PATCH 2504/9938] dmaengine: dw: substitute dma_read_byaddr by dma_readl_native Since struct dw_dma is allocated and regs member is assigned properly we can use standard IO accessors to the DMA registers. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 8 +++----- drivers/dma/dw/regs.h | 4 ---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index db9b6f433148..93d8d553c686 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -1529,7 +1529,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) pm_runtime_get_sync(chip->dev); if (!pdata) { - dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); + dw_params = dma_readl(dw, DW_PARAMS); dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params); autocfg = dw_params >> DW_PARAMS_EN & 1; @@ -1629,11 +1629,9 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) /* Hardware configuration */ if (autocfg) { - unsigned int dwc_params; unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1; - void __iomem *addr = chip->regs + r * sizeof(u32); - - dwc_params = dma_read_byaddr(addr, DWC_PARAMS); + void __iomem *addr = &__dw_regs(dw)->DWC_PARAMS[r]; + unsigned int dwc_params = dma_readl_native(addr); dev_dbg(chip->dev, "DWC_PARAMS[%d]: 0x%08x\n", i, dwc_params); diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 59d6cec01dca..feb3a4a7623b 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -114,10 +114,6 @@ struct dw_dma_regs { #define dma_writel_native writel #endif -/* To access the registers in early stage of probe */ -#define dma_read_byaddr(addr, name) \ - dma_readl_native((addr) + offsetof(struct dw_dma_regs, name)) - /* Bitfields in DW_PARAMS */ #define DW_PARAMS_NR_CHAN 8 /* number of channels */ #define DW_PARAMS_NR_MASTER 11 /* number of AHB masters */ -- GitLab From 7794e5b920a2586d7f3258aade0ca90cb01cdbd4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:24:48 +0200 Subject: [PATCH 2505/9938] dmaengine: dw: define counter variables as unsigned int MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code is fixed to satisfy a compiler otherwise we have drivers/dma/dw/core.c: In function ‘dwc_handle_cyclic’: drivers/dma/dw/core.c:568: warning: comparison between signed and unsigned drivers/dma/dw/core.c: In function ‘dw_dma_tasklet’: drivers/dma/dw/core.c:590: warning: comparison between signed and unsigned drivers/dma/dw/core.c: In function ‘dw_dma_off’: drivers/dma/dw/core.c:1103: warning: comparison between signed and unsigned drivers/dma/dw/core.c: In function ‘dw_dma_cyclic_free’: drivers/dma/dw/core.c:1469: warning: comparison between signed and unsigned drivers/dma/dw/core.c: In function ‘dw_dma_probe’: drivers/dma/dw/core.c:1574: warning: comparison between signed and unsigned There is no functional change. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 93d8d553c686..63502241703a 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -557,7 +557,7 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, */ if (unlikely(status_err & dwc->mask) || unlikely(status_xfer & dwc->mask)) { - int i; + unsigned int i; dev_err(chan2dev(&dwc->chan), "cyclic DMA unexpected %s interrupt, stopping DMA transfer\n", @@ -597,7 +597,7 @@ static void dw_dma_tasklet(unsigned long data) u32 status_block; u32 status_xfer; u32 status_err; - int i; + unsigned int i; status_block = dma_readl(dw, RAW.BLOCK); status_xfer = dma_readl(dw, RAW.XFER); @@ -1115,7 +1115,7 @@ static void dwc_issue_pending(struct dma_chan *chan) static void dw_dma_off(struct dw_dma *dw) { - int i; + unsigned int i; dma_writel(dw, CFG, 0); @@ -1480,7 +1480,7 @@ void dw_dma_cyclic_free(struct dma_chan *chan) struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(dwc->chan.device); struct dw_cyclic_desc *cdesc = dwc->cdesc; - int i; + unsigned int i; unsigned long flags; dev_dbg(chan2dev(&dwc->chan), "%s\n", __func__); @@ -1516,8 +1516,8 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) bool autocfg = false; unsigned int dw_params; unsigned int max_blk_size = 0; + unsigned int i; int err; - int i; dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL); if (!dw) -- GitLab From 5e09f98e77e9bd500e3d930bfd46b1924cca01ca Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:24:51 +0200 Subject: [PATCH 2506/9938] dmaengine: dw: move dwc->paused to dwc->flags We have already dedicated variable for flags, therefore no need to create an additional storage for that. Convert dwc->paused to use dwc->flags. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 12 +++++------- drivers/dma/dw/regs.h | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 63502241703a..2ee3acc68a61 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -999,7 +999,7 @@ static int dwc_pause(struct dma_chan *chan) while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY) && count--) udelay(2); - dwc->paused = true; + set_bit(DW_DMA_IS_PAUSED, &dwc->flags); spin_unlock_irqrestore(&dwc->lock, flags); @@ -1012,7 +1012,7 @@ static inline void dwc_chan_resume(struct dw_dma_chan *dwc) channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP); - dwc->paused = false; + clear_bit(DW_DMA_IS_PAUSED, &dwc->flags); } static int dwc_resume(struct dma_chan *chan) @@ -1020,12 +1020,10 @@ static int dwc_resume(struct dma_chan *chan) struct dw_dma_chan *dwc = to_dw_dma_chan(chan); unsigned long flags; - if (!dwc->paused) - return 0; - spin_lock_irqsave(&dwc->lock, flags); - dwc_chan_resume(dwc); + if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags)) + dwc_chan_resume(dwc); spin_unlock_irqrestore(&dwc->lock, flags); @@ -1094,7 +1092,7 @@ dwc_tx_status(struct dma_chan *chan, if (ret != DMA_COMPLETE) dma_set_residue(txstate, dwc_get_residue(dwc)); - if (dwc->paused && ret == DMA_IN_PROGRESS) + if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags) && ret == DMA_IN_PROGRESS) return DMA_PAUSED; return ret; diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index feb3a4a7623b..94f8f62ff884 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -216,6 +216,7 @@ enum dw_dma_msize { enum dw_dmac_flags { DW_DMA_IS_CYCLIC = 0, DW_DMA_IS_SOFT_LLP = 1, + DW_DMA_IS_PAUSED = 2, }; struct dw_dma_chan { @@ -224,7 +225,6 @@ struct dw_dma_chan { u8 mask; u8 priority; enum dma_transfer_direction direction; - bool paused; bool initialized; /* software emulation of the LLP transfers */ -- GitLab From 423f9cbf2da8110e01eee56b8f755332432e82c7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:24:52 +0200 Subject: [PATCH 2507/9938] dmaengine: dw: move dwc->initialized to dwc->flags We have already dedicated variable for flags, therefore no need to create an additional storage for that. Covert dwc->initialized to use dwc->flags. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 8 ++++---- drivers/dma/dw/regs.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 2ee3acc68a61..848d33507df9 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -137,7 +137,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc) u32 cfghi = DWC_CFGH_FIFO_MODE; u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); - if (dwc->initialized == true) + if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags)) return; cfghi |= DWC_CFGH_DST_PER(dwc->dst_id); @@ -150,7 +150,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc) channel_set_bit(dw, MASK.XFER, dwc->mask); channel_set_bit(dw, MASK.ERROR, dwc->mask); - dwc->initialized = true; + set_bit(DW_DMA_IS_INITIALIZED, &dwc->flags); } /*----------------------------------------------------------------------*/ @@ -1127,7 +1127,7 @@ static void dw_dma_off(struct dw_dma *dw) cpu_relax(); for (i = 0; i < dw->dma.chancnt; i++) - dw->chan[i].initialized = false; + clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags); } static void dw_dma_on(struct dw_dma *dw) @@ -1236,7 +1236,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) dwc->m_master = 0; dwc->p_master = 0; - dwc->initialized = false; + clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags); /* Disable interrupts */ channel_clear_bit(dw, MASK.XFER, dwc->mask); diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 94f8f62ff884..89178641e80b 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -217,6 +217,7 @@ enum dw_dmac_flags { DW_DMA_IS_CYCLIC = 0, DW_DMA_IS_SOFT_LLP = 1, DW_DMA_IS_PAUSED = 2, + DW_DMA_IS_INITIALIZED = 3, }; struct dw_dma_chan { @@ -225,7 +226,6 @@ struct dw_dma_chan { u8 mask; u8 priority; enum dma_transfer_direction direction; - bool initialized; /* software emulation of the LLP transfers */ struct list_head *tx_node_active; -- GitLab From b68fd0976286e0cc4e163a83b8b68d6efca814dd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:24:53 +0200 Subject: [PATCH 2508/9938] dmaengine: dw: move residue to a descriptor Residue is a property of any active descriptor. So, any descriptor may be in different state but residue is a feature of active descriptor. Check if the asked descriptor is active and return proper residue value for it. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 60 ++++++++++++++++++++++++++++--------------- drivers/dma/dw/regs.h | 2 +- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 848d33507df9..a6d96f32f4f9 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -242,7 +242,7 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) dwc_initialize(dwc); - dwc->residue = first->total_len; + first->residue = first->total_len; dwc->tx_node_active = &first->tx_list; /* Submit first block */ @@ -372,11 +372,11 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) head = &desc->tx_list; if (active != head) { - /* Update desc to reflect last sent one */ - if (active != head->next) - desc = to_dw_desc(active->prev); - - dwc->residue -= desc->len; + /* Update residue to reflect last sent descriptor */ + if (active == head->next) + desc->residue -= desc->len; + else + desc->residue -= to_dw_desc(active->prev)->len; child = to_dw_desc(active); @@ -391,8 +391,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags); } - dwc->residue = 0; - spin_unlock_irqrestore(&dwc->lock, flags); dwc_complete_all(dw, dwc); @@ -400,7 +398,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) } if (list_empty(&dwc->active_list)) { - dwc->residue = 0; spin_unlock_irqrestore(&dwc->lock, flags); return; } @@ -415,7 +412,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) { /* Initial residue value */ - dwc->residue = desc->total_len; + desc->residue = desc->total_len; /* Check first descriptors addr */ if (desc->txd.phys == DWC_LLP_LOC(llp)) { @@ -426,20 +423,20 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) /* Check first descriptors llp */ if (lli_read(desc, llp) == llp) { /* This one is currently in progress */ - dwc->residue -= dwc_get_sent(dwc); + desc->residue -= dwc_get_sent(dwc); spin_unlock_irqrestore(&dwc->lock, flags); return; } - dwc->residue -= desc->len; + desc->residue -= desc->len; list_for_each_entry(child, &desc->tx_list, desc_node) { if (lli_read(child, llp) == llp) { /* Currently in progress */ - dwc->residue -= dwc_get_sent(dwc); + desc->residue -= dwc_get_sent(dwc); spin_unlock_irqrestore(&dwc->lock, flags); return; } - dwc->residue -= child->len; + desc->residue -= child->len; } /* @@ -1059,16 +1056,37 @@ static int dwc_terminate_all(struct dma_chan *chan) return 0; } -static inline u32 dwc_get_residue(struct dw_dma_chan *dwc) +static struct dw_desc *dwc_find_desc(struct dw_dma_chan *dwc, dma_cookie_t c) +{ + struct dw_desc *desc; + + list_for_each_entry(desc, &dwc->active_list, desc_node) + if (desc->txd.cookie == c) + return desc; + + return NULL; +} + +static u32 dwc_get_residue(struct dw_dma_chan *dwc, dma_cookie_t cookie) { + struct dw_desc *desc; unsigned long flags; u32 residue; spin_lock_irqsave(&dwc->lock, flags); - residue = dwc->residue; - if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags) && residue) - residue -= dwc_get_sent(dwc); + desc = dwc_find_desc(dwc, cookie); + if (desc) { + if (desc == dwc_first_active(dwc)) { + residue = desc->residue; + if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags) && residue) + residue -= dwc_get_sent(dwc); + } else { + residue = desc->total_len; + } + } else { + residue = 0; + } spin_unlock_irqrestore(&dwc->lock, flags); return residue; @@ -1089,8 +1107,10 @@ dwc_tx_status(struct dma_chan *chan, dwc_scan_descriptors(to_dw_dma(chan->device), dwc); ret = dma_cookie_status(chan, cookie, txstate); - if (ret != DMA_COMPLETE) - dma_set_residue(txstate, dwc_get_residue(dwc)); + if (ret == DMA_COMPLETE) + return ret; + + dma_set_residue(txstate, dwc_get_residue(dwc, cookie)); if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags) && ret == DMA_IN_PROGRESS) return DMA_PAUSED; diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 89178641e80b..96f498188257 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -237,7 +237,6 @@ struct dw_dma_chan { struct list_head active_list; struct list_head queue; struct list_head free_list; - u32 residue; struct dw_cyclic_desc *cdesc; unsigned int descs_allocated; @@ -352,6 +351,7 @@ struct dw_desc { struct dma_async_tx_descriptor txd; size_t len; size_t total_len; + u32 residue; }; #define to_dw_desc(h) list_entry(h, struct dw_desc, desc_node) -- GitLab From 925a7d045e6f0129bc58ccd4c3a8dcef62486345 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:24:54 +0200 Subject: [PATCH 2509/9938] dmaengine: dw: set cdesc to NULL when free cyclic transfers To be sure we have the cyclic transfers already gone we set cdesc to NULL. It will prevent the double free. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index a6d96f32f4f9..dd47d4b8aad6 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -1522,6 +1522,8 @@ void dw_dma_cyclic_free(struct dma_chan *chan) kfree(cdesc->desc); kfree(cdesc); + dwc->cdesc = NULL; + clear_bit(DW_DMA_IS_CYCLIC, &dwc->flags); } EXPORT_SYMBOL(dw_dma_cyclic_free); -- GitLab From dd70ccfaa79189feaa78609d44f7c3e7fa1dc6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 23 Mar 2016 16:52:47 +0100 Subject: [PATCH 2510/9938] ARM: BCM5301X: Set vcc-gpio for USB controllers of few devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are few devices that have USB power controlled using GPIO. Linux USB host driver (bcma-hcd) already supports this by reading vcc-gpio from DT. Set it properly for all known devices. Signed-off-by: Rafał Miłecki Signed-off-by: Florian Fainelli --- arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 8 ++++++++ arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 15 ++++----------- arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts | 5 +++++ arch/arm/boot/dts/bcm4709-netgear-r8000.dts | 8 ++++++++ arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts | 4 ++++ arch/arm/boot/dts/bcm5301x.dtsi | 14 ++++++++++++++ 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts index 42dcdfb769b2..fb62ed6705d4 100644 --- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts @@ -139,3 +139,11 @@ &uart0 { status = "okay"; }; + +&usb2 { + vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>; +}; + +&usb3 { + vcc-gpio = <&chipcommon 10 GPIO_ACTIVE_LOW>; +}; diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts index ca92bba6a8c5..6bebfa60f45f 100644 --- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts @@ -24,17 +24,6 @@ reg = <0x00000000 0x08000000>; }; - axi@18000000 { - usb3@23000 { - reg = <0x00023000 0x1000>; - - #address-cells = <1>; - #size-cells = <1>; - - vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; - }; - }; - leds { compatible = "gpio-leds"; @@ -97,3 +86,7 @@ &uart0 { status = "okay"; }; + +&usb3 { + vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts index 2a92e8d5ab34..791d7225c733 100644 --- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts @@ -126,3 +126,8 @@ }; }; }; + + +&usb2 { + vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts index b52927c94e35..ca181516c28a 100644 --- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts @@ -106,3 +106,11 @@ }; }; }; + +&usb2 { + vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; +}; + +&usb3 { + vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts index 6c83538bc2d7..9205c0398cf2 100644 --- a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts +++ b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts @@ -109,3 +109,7 @@ status = "okay"; clock-frequency = <125000000>; }; + +&usb3 { + vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index 65a1309bd6e2..b3e9d28ed87b 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -207,6 +207,20 @@ gpio-controller; #gpio-cells = <2>; }; + + usb2: usb2@21000 { + reg = <0x00021000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + }; + + usb3: usb3@23000 { + reg = <0x00023000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + }; }; lcpll0: lcpll0@1800c100 { -- GitLab From 5a6516ff135555aa53c7d156cd3973b826e011f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 6 Apr 2016 18:49:55 +0200 Subject: [PATCH 2511/9938] ARM: BCM5301X: Enable earlycon on tested devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows reporting & debugging problems occurring early in the boot process. Signed-off-by: Rafał Miłecki Acked-by: Hauke Mehrtens Signed-off-by: Florian Fainelli --- arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 2 +- arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts | 2 +- arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 2 +- arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts | 2 +- arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 2 +- arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts | 2 +- arch/arm/boot/dts/bcm5301x.dtsi | 4 ++++ 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts index fb62ed6705d4..5087aa81efb1 100644 --- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts @@ -17,7 +17,7 @@ model = "Buffalo WZR-1750DHP (BCM4708)"; chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "console=ttyS0,115200 earlycon"; }; memory { diff --git a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts index f18e80e0b61d..c973f768dd14 100644 --- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts +++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts @@ -17,7 +17,7 @@ model = "Luxul XWC-1000 (BCM4708)"; chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "console=ttyS0,115200 earlycon"; }; memory { diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts index 6bebfa60f45f..1049ab108b32 100644 --- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts @@ -17,7 +17,7 @@ model = "Netgear R6250 V1 (BCM4708)"; chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "console=ttyS0,115200 earlycon"; }; memory { diff --git a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts index 64a5e8ab65e0..4d610ff40e1b 100644 --- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts @@ -17,7 +17,7 @@ model = "SmartRG SR400ac"; chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "console=ttyS0,115200 earlycon"; }; memory { diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts index 38f0c00d1aca..a9c8defed4d3 100644 --- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts +++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts @@ -17,7 +17,7 @@ model = "Buffalo WZR-600DHP2 (BCM47081)"; chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "console=ttyS0,115200 earlycon"; }; memory { diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts index 9205c0398cf2..ace38efd2db3 100644 --- a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts +++ b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts @@ -17,7 +17,7 @@ model = "D-Link DIR-885L"; chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "console=ttyS0,115200 earlycon"; }; memory { diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index b3e9d28ed87b..9c06d91e0c8a 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -18,6 +18,10 @@ / { interrupt-parent = <&gic>; + chosen { + stdout-path = &uart0; + }; + chipcommonA { compatible = "simple-bus"; ranges = <0x00000000 0x18000000 0x00001000>; -- GitLab From 19dd159ce8086293b70bd8e1aeebe06aff8d7df8 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 13 Apr 2016 15:29:44 +0530 Subject: [PATCH 2512/9938] regulator: max8973: add DT binding details for junction warn temp The driver MAX8973 supports the driver for Maxim MAX77621. MAX77621 supports the junction temp warning at 120 degC and 140 degC which is configurable. It generates alert signal when junction temperature crosses these threshold. Add DT properties and its binding details to make this configuration from DT. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/max8973-regulator.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/max8973-regulator.txt b/Documentation/devicetree/bindings/regulator/max8973-regulator.txt index f80ea2fe27e6..c2c68fcc1b41 100644 --- a/Documentation/devicetree/bindings/regulator/max8973-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/max8973-regulator.txt @@ -32,6 +32,13 @@ Optional properties: Enhanced transient response (ETR) will affect the configuration of CKADV. +-junction-warn-millicelsius: u32, junction warning temperature threshold + in millicelsius. If die temperature crosses this level then + device generates the warning interrupts. + +Please note that thermal functionality is only supported on MAX77621. The +supported threshold warning temperature for MAX77621 are 120 degC and 140 degC. + Example: max8973@1b { -- GitLab From d2d5437bdfdde20a75bdf59db1c1a77721613b22 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 13 Apr 2016 15:29:45 +0530 Subject: [PATCH 2513/9938] regulator: max8973: add support for junction thermal warning The driver MAX8973 supports the driver for Maxim PMIC MAX77621. MAX77621 supports the junction temp warning at 120 degC and 140 degC which is configurable. It generates alert signal when junction temperature crosses these threshold. MAX77621 does not support the continuous temp monitoring of junction temperature. It just report whether junction temperature crossed the threshold or not. Add support to - Configure junction temp warning threshold via DT property to generate alert when it crosses the threshold. - Add support to interrupt the host from this device when alert occurred. - read the junction temp via thermal framework. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 1 + drivers/regulator/max8973-regulator.c | 97 +++++++++++++++++++++ include/linux/regulator/max8973-regulator.h | 5 ++ 3 files changed, 103 insertions(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c77dc08b1202..129359f775d0 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -409,6 +409,7 @@ config REGULATOR_MAX8952 config REGULATOR_MAX8973 tristate "Maxim MAX8973 voltage regulator " depends on I2C + depends on THERMAL && THERMAL_OF select REGMAP_I2C help The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index 5b75b7c2e3ea..08d2f13eca00 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include /* Register definitions */ #define MAX8973_VOUT 0x0 @@ -74,6 +77,7 @@ #define MAX8973_WDTMR_ENABLE BIT(6) #define MAX8973_DISCH_ENBABLE BIT(5) #define MAX8973_FT_ENABLE BIT(4) +#define MAX77621_T_JUNCTION_120 BIT(7) #define MAX8973_CKKADV_TRIP_MASK 0xC #define MAX8973_CKKADV_TRIP_DISABLE 0xC @@ -93,6 +97,12 @@ #define MAX8973_VOLATGE_STEP 6250 #define MAX8973_BUCK_N_VOLTAGE 0x80 +#define MAX77621_CHIPID_TJINT_S BIT(0) + +#define MAX77621_NORMAL_OPERATING_TEMP 100000 +#define MAX77621_TJINT_WARNING_TEMP_120 120000 +#define MAX77621_TJINT_WARNING_TEMP_140 140000 + enum device_id { MAX8973, MAX77621 @@ -112,6 +122,9 @@ struct max8973_chip { int curr_gpio_val; struct regulator_ops ops; enum device_id id; + int junction_temp_warning; + int irq; + struct thermal_zone_device *tz_device; }; /* @@ -391,6 +404,10 @@ static int max8973_init_dcdc(struct max8973_chip *max, if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE) control1 |= MAX8973_FREQSHIFT_9PER; + if ((pdata->junction_temp_warning == MAX77621_TJINT_WARNING_TEMP_120) && + (max->id == MAX77621)) + control2 |= MAX77621_T_JUNCTION_120; + if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE)) control2 |= MAX8973_DISCH_ENBABLE; @@ -457,6 +474,79 @@ static int max8973_init_dcdc(struct max8973_chip *max, return ret; } +static int max8973_thermal_read_temp(void *data, int *temp) +{ + struct max8973_chip *mchip = data; + unsigned int val; + int ret; + + ret = regmap_read(mchip->regmap, MAX8973_CHIPID1, &val); + if (ret < 0) { + dev_err(mchip->dev, "Failed to read register CHIPID1, %d", ret); + return ret; + } + + /* +1 degC to trigger cool devive */ + if (val & MAX77621_CHIPID_TJINT_S) + *temp = mchip->junction_temp_warning + 1000; + else + *temp = MAX77621_NORMAL_OPERATING_TEMP; + + return 0; +} + +static irqreturn_t max8973_thermal_irq(int irq, void *data) +{ + struct max8973_chip *mchip = data; + + thermal_zone_device_update(mchip->tz_device); + + return IRQ_HANDLED; +} + +static const struct thermal_zone_of_device_ops max77621_tz_ops = { + .get_temp = max8973_thermal_read_temp, +}; + +static int max8973_thermal_init(struct max8973_chip *mchip) +{ + struct thermal_zone_device *tzd; + struct irq_data *irq_data; + unsigned long irq_flags = 0; + int ret; + + if (mchip->id != MAX77621) + return 0; + + tzd = devm_thermal_zone_of_sensor_register(mchip->dev, 0, mchip, + &max77621_tz_ops); + if (IS_ERR(tzd)) { + ret = PTR_ERR(tzd); + dev_err(mchip->dev, "Failed to register thermal sensor: %d\n", + ret); + return ret; + } + + if (mchip->irq <= 0) + return 0; + + irq_data = irq_get_irq_data(mchip->irq); + if (irq_data) + irq_flags = irqd_get_trigger_type(irq_data); + + ret = devm_request_threaded_irq(mchip->dev, mchip->irq, NULL, + max8973_thermal_irq, + IRQF_ONESHOT | IRQF_SHARED | irq_flags, + dev_name(mchip->dev), mchip); + if (ret < 0) { + dev_err(mchip->dev, "Failed to request irq %d, %d\n", + mchip->irq, ret); + return ret; + } + + return 0; +} + static const struct regmap_config max8973_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -521,6 +611,11 @@ static struct max8973_regulator_platform_data *max8973_parse_dt( pdata->control_flags |= MAX8973_CONTROL_CLKADV_TRIP_DISABLED; } + pdata->junction_temp_warning = MAX77621_TJINT_WARNING_TEMP_140; + ret = of_property_read_u32(np, "junction-warn-millicelsius", &pval); + if (!ret && (pval <= MAX77621_TJINT_WARNING_TEMP_120)) + pdata->junction_temp_warning = MAX77621_TJINT_WARNING_TEMP_120; + return pdata; } @@ -608,6 +703,7 @@ static int max8973_probe(struct i2c_client *client, max->enable_external_control = pdata->enable_ext_control; max->curr_gpio_val = pdata->dvs_def_state; max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state; + max->junction_temp_warning = pdata->junction_temp_warning; if (gpio_is_valid(max->enable_gpio)) max->enable_external_control = true; @@ -718,6 +814,7 @@ static int max8973_probe(struct i2c_client *client, return ret; } + max8973_thermal_init(max); return 0; } diff --git a/include/linux/regulator/max8973-regulator.h b/include/linux/regulator/max8973-regulator.h index f6a8a16a0d4d..2fcb9980262a 100644 --- a/include/linux/regulator/max8973-regulator.h +++ b/include/linux/regulator/max8973-regulator.h @@ -54,6 +54,10 @@ * @reg_init_data: The regulator init data. * @control_flags: Control flags which are ORed value of above flags to * configure device. + * @junction_temp_warning: Junction temp in millicelcius on which warning need + * to be set. Thermal functionality is only supported on + * MAX77621. The threshold warning supported by MAX77621 + * are 120C and 140C. * @enable_ext_control: Enable the voltage enable/disable through external * control signal from EN input pin. If it is false then * voltage output will be enabled/disabled through EN bit of @@ -67,6 +71,7 @@ struct max8973_regulator_platform_data { struct regulator_init_data *reg_init_data; unsigned long control_flags; + unsigned long junction_temp_warning; bool enable_ext_control; int enable_gpio; int dvs_gpio; -- GitLab From 538fb37c1304c0edc14ad19a6b0311d840314c2a Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Tue, 29 Mar 2016 12:57:31 +0530 Subject: [PATCH 2514/9938] arm64: dts: Add ARM PL330 DMA DT node for NS2 We have one ARM PL330 DMA instance with 8 channels in NS2 SoC. Let's enable it for NS2 in NS2 DT. Signed-off-by: Anup Patel Reviewed-by: Ray Jui Reviewed-by: Pramod KUMAR Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli --- arch/arm64/boot/dts/broadcom/ns2.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index 6f81c9d7fb06..a9f45850b491 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -217,6 +217,25 @@ #size-cells = <1>; ranges = <0 0 0 0xffffffff>; + dma0: dma@61360000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x61360000 0x1000>; + interrupts = , + , + , + , + , + , + , + , + ; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + clocks = <&iprocslow>; + clock-names = "apb_pclk"; + }; + smmu: mmu@64000000 { compatible = "arm,mmu-500"; reg = <0x64000000 0x40000>; -- GitLab From b2f9cd484513b773b238e3de870912e39a0286ba Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Tue, 29 Mar 2016 12:57:32 +0530 Subject: [PATCH 2515/9938] arm64: dts: Add maintenance interrupt for GIC in NS2 DT The KVM ARM64 requires GIC maintenance interrupt for VGIC emulation so this patch adds the missing "interrupts" attribute to GIC node in NS2 DT. Signed-off-by: Anup Patel Reviewed-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli --- arch/arm64/boot/dts/broadcom/ns2.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index a9f45850b491..940ed526aa26 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -347,6 +347,8 @@ <0x65220000 0x1000>, <0x65240000 0x2000>, <0x65260000 0x1000>; + interrupts = ; }; timer0: timer@66030000 { -- GitLab From 59a5bedead948db8827df865ced3cb3ea2595256 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Tue, 29 Mar 2016 12:57:33 +0530 Subject: [PATCH 2516/9938] arm64: dts: Move NS2 clock DT nodes to separate DT file For more readabilty and consistency with other Broadcom SoCs, we move all NS2 clock DT nodes from main SoC DT file to a separate DT file. We also update the license header in ns2.dtsi as-per new Broadcom convention. Signed-off-by: Anup Patel Reviewed-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli --- arch/arm64/boot/dts/broadcom/ns2-clock.dtsi | 105 ++++++++++++++++++++ arch/arm64/boot/dts/broadcom/ns2.dtsi | 81 +-------------- 2 files changed, 108 insertions(+), 78 deletions(-) create mode 100644 arch/arm64/boot/dts/broadcom/ns2-clock.dtsi diff --git a/arch/arm64/boot/dts/broadcom/ns2-clock.dtsi b/arch/arm64/boot/dts/broadcom/ns2-clock.dtsi new file mode 100644 index 000000000000..99009fdf10a4 --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/ns2-clock.dtsi @@ -0,0 +1,105 @@ +/* + * BSD LICENSE + * + * Copyright (c) 2016 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Broadcom Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + osc: oscillator { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + }; + + lcpll_ddr: lcpll_ddr@6501d058 { + #clock-cells = <1>; + compatible = "brcm,ns2-lcpll-ddr"; + reg = <0x6501d058 0x20>, + <0x6501c020 0x4>, + <0x6501d04c 0x4>; + clocks = <&osc>; + clock-output-names = "lcpll_ddr", "pcie_sata_usb", + "ddr", "ddr_ch2_unused", + "ddr_ch3_unused", "ddr_ch4_unused", + "ddr_ch5_unused"; + }; + + lcpll_ports: lcpll_ports@6501d078 { + #clock-cells = <1>; + compatible = "brcm,ns2-lcpll-ports"; + reg = <0x6501d078 0x20>, + <0x6501c020 0x4>, + <0x6501d054 0x4>; + clocks = <&osc>; + clock-output-names = "lcpll_ports", "wan", "rgmii", + "ports_ch2_unused", + "ports_ch3_unused", + "ports_ch4_unused", + "ports_ch5_unused"; + }; + + genpll_scr: genpll_scr@6501d098 { + #clock-cells = <1>; + compatible = "brcm,ns2-genpll-scr"; + reg = <0x6501d098 0x32>, + <0x6501c020 0x4>, + <0x6501d044 0x4>; + clocks = <&osc>; + clock-output-names = "genpll_scr", "scr", "fs", + "audio_ref", "scr_ch3_unused", + "scr_ch4_unused", "scr_ch5_unused"; + }; + + iprocmed: iprocmed { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>; + clock-div = <2>; + clock-mult = <1>; + }; + + iprocslow: iprocslow { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>; + clock-div = <4>; + clock-mult = <1>; + }; + + genpll_sw: genpll_sw@6501d0c4 { + #clock-cells = <1>; + compatible = "brcm,ns2-genpll-sw"; + reg = <0x6501d0c4 0x32>, + <0x6501c020 0x4>, + <0x6501d044 0x4>; + clocks = <&osc>; + clock-output-names = "genpll_sw", "rpe", "250", "nic", + "chimp", "port", "sdio"; + }; diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index 940ed526aa26..0a92a6887147 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2015 Broadcom Corporation. All rights reserved. + * Copyright (c) 2015 Broadcom. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -110,33 +110,6 @@ <&A57_3>; }; - clocks { - #address-cells = <1>; - #size-cells = <1>; - - osc: oscillator { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <25000000>; - }; - - iprocmed: iprocmed { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>; - clock-div = <2>; - clock-mult = <1>; - }; - - iprocslow: iprocslow { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>; - clock-div = <4>; - clock-mult = <1>; - }; - }; - pcie0: pcie@20020000 { compatible = "brcm,iproc-pcie"; reg = <0 0x20020000 0 0x1000>; @@ -217,6 +190,8 @@ #size-cells = <1>; ranges = <0 0 0 0xffffffff>; + #include "ns2-clock.dtsi" + dma0: dma@61360000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x61360000 0x1000>; @@ -277,56 +252,6 @@ mmu-masters; }; - lcpll_ddr: lcpll_ddr@6501d058 { - #clock-cells = <1>; - compatible = "brcm,ns2-lcpll-ddr"; - reg = <0x6501d058 0x20>, - <0x6501c020 0x4>, - <0x6501d04c 0x4>; - clocks = <&osc>; - clock-output-names = "lcpll_ddr", "pcie_sata_usb", - "ddr", "ddr_ch2_unused", - "ddr_ch3_unused", "ddr_ch4_unused", - "ddr_ch5_unused"; - }; - - lcpll_ports: lcpll_ports@6501d078 { - #clock-cells = <1>; - compatible = "brcm,ns2-lcpll-ports"; - reg = <0x6501d078 0x20>, - <0x6501c020 0x4>, - <0x6501d054 0x4>; - clocks = <&osc>; - clock-output-names = "lcpll_ports", "wan", "rgmii", - "ports_ch2_unused", - "ports_ch3_unused", - "ports_ch4_unused", - "ports_ch5_unused"; - }; - - genpll_scr: genpll_scr@6501d098 { - #clock-cells = <1>; - compatible = "brcm,ns2-genpll-scr"; - reg = <0x6501d098 0x32>, - <0x6501c020 0x4>, - <0x6501d044 0x4>; - clocks = <&osc>; - clock-output-names = "genpll_scr", "scr", "fs", - "audio_ref", "scr_ch3_unused", - "scr_ch4_unused", "scr_ch5_unused"; - }; - - genpll_sw: genpll_sw@6501d0c4 { - #clock-cells = <1>; - compatible = "brcm,ns2-genpll-sw"; - reg = <0x6501d0c4 0x32>, - <0x6501c020 0x4>, - <0x6501d044 0x4>; - clocks = <&osc>; - clock-output-names = "genpll_sw", "rpe", "250", "nic", - "chimp", "port", "sdio"; - }; - crmu: crmu@65024000 { compatible = "syscon"; reg = <0x65024000 0x100>; -- GitLab From d69dbd9f41a7ca343091d6ba9848a284de6059fa Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Tue, 29 Mar 2016 12:57:34 +0530 Subject: [PATCH 2517/9938] arm64: dts: Add ARM PL022 SPI DT nodes for NS2 We have two ARM PL022 SPI instances in NS2 SoC. On NS2 SVK, one of the ARM PL022 SPI host has Silabs si3226x slic connected to chip-select #0 whereas second ARM PL022 SPI host has Atmel AT25 EEPROM connected to chip-select #0. This patch adds ARM PL022, Silabs si3226x, and Atmel AT25 DT nodes in NS2 DT and NS2 SVK DT respectively. Signed-off-by: Anup Patel Reviewed-by: Ray Jui Reviewed-by: Scott Branden Signed-off-by: Florian Fainelli --- arch/arm64/boot/dts/broadcom/ns2-svk.dts | 45 ++++++++++++++++++++++++ arch/arm64/boot/dts/broadcom/ns2.dtsi | 22 ++++++++++++ 2 files changed, 67 insertions(+) diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts index ce0ab84e0f2d..54ca40c9f711 100644 --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts @@ -72,6 +72,51 @@ status = "ok"; }; +&ssp0 { + status = "ok"; + + slic@0 { + compatible = "silabs,si3226x"; + reg = <0>; + spi-max-frequency = <5000000>; + spi-cpha = <1>; + spi-cpol = <1>; + pl022,hierarchy = <0>; + pl022,interface = <0>; + pl022,slave-tx-disable = <0>; + pl022,com-mode = <0>; + pl022,rx-level-trig = <1>; + pl022,tx-level-trig = <1>; + pl022,ctrl-len = <11>; + pl022,wait-state = <0>; + pl022,duplex = <0>; + }; +}; + +&ssp1 { + status = "ok"; + + at25@0 { + compatible = "atmel,at25"; + reg = <0>; + spi-max-frequency = <5000000>; + at25,byte-len = <0x8000>; + at25,addr-mode = <2>; + at25,page-size = <64>; + spi-cpha = <1>; + spi-cpol = <1>; + pl022,hierarchy = <0>; + pl022,interface = <0>; + pl022,slave-tx-disable = <0>; + pl022,com-mode = <0>; + pl022,rx-level-trig = <1>; + pl022,tx-level-trig = <1>; + pl022,ctrl-len = <11>; + pl022,wait-state = <0>; + pl022,duplex = <0>; + }; +}; + &sdio0 { status = "ok"; }; diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index 0a92a6887147..123cd9c6a01b 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -354,6 +354,28 @@ status = "disabled"; }; + ssp0: ssp@66180000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x66180000 0x1000>; + interrupts = ; + clocks = <&iprocslow>, <&iprocslow>; + clock-names = "spiclk", "apb_pclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + ssp1: ssp@66190000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x66190000 0x1000>; + interrupts = ; + clocks = <&iprocslow>, <&iprocslow>; + clock-names = "spiclk", "apb_pclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + hwrng: hwrng@66220000 { compatible = "brcm,iproc-rng200"; reg = <0x66220000 0x28>; -- GitLab From c9b5560aac7aa774143ce16c1fe7e0007dea79e2 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 13 Apr 2016 23:36:27 +0900 Subject: [PATCH 2518/9938] treewide: Fix typos in libata.xml This patch fix spelling typos found in Documentation/Docbook/libata.xml. It is because the file was generated from comments in source, I had to fix comments in libata-core.c Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 16 ++++++++-------- drivers/ata/libata-scsi.c | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 7b21021dbf7d..6f33ace33daf 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -884,7 +884,7 @@ unsigned long ata_pack_xfermask(unsigned long pio_mask, * @udma_mask: resulting udma_mask * * Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask. - * Any NULL distination masks will be ignored. + * Any NULL destination masks will be ignored. */ void ata_unpack_xfermask(unsigned long xfer_mask, unsigned long *pio_mask, unsigned long *mwdma_mask, unsigned long *udma_mask) @@ -3399,7 +3399,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) * EH context. * * RETURNS: - * 0 if @linke is ready before @deadline; otherwise, -errno. + * 0 if @link is ready before @deadline; otherwise, -errno. */ int ata_wait_ready(struct ata_link *link, unsigned long deadline, int (*check_ready)(struct ata_link *link)) @@ -3480,7 +3480,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline, * EH context. * * RETURNS: - * 0 if @linke is ready before @deadline; otherwise, -errno. + * 0 if @link is ready before @deadline; otherwise, -errno. */ int ata_wait_after_reset(struct ata_link *link, unsigned long deadline, int (*check_ready)(struct ata_link *link)) @@ -3493,7 +3493,7 @@ int ata_wait_after_reset(struct ata_link *link, unsigned long deadline, /** * sata_link_debounce - debounce SATA phy status * @link: ATA link to debounce SATA phy status for - * @params: timing parameters { interval, duratinon, timeout } in msec + * @params: timing parameters { interval, duration, timeout } in msec * @deadline: deadline jiffies for the operation * * Make sure SStatus of @link reaches stable state, determined by @@ -3563,7 +3563,7 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params, /** * sata_link_resume - resume SATA link * @link: ATA link to resume SATA - * @params: timing parameters { interval, duratinon, timeout } in msec + * @params: timing parameters { interval, duration, timeout } in msec * @deadline: deadline jiffies for the operation * * Resume SATA phy @link and debounce it. @@ -3746,7 +3746,7 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline) /** * sata_link_hardreset - reset link via SATA phy reset * @link: link to reset - * @timing: timing parameters { interval, duratinon, timeout } in msec + * @timing: timing parameters { interval, duration, timeout } in msec * @deadline: deadline jiffies for the operation * @online: optional out parameter indicating link onlineness * @check_ready: optional callback to check link readiness @@ -6212,7 +6212,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) * * After allocating an ATA host and initializing it, most libata * LLDs perform three steps to activate the host - start host, - * request IRQ and register it. This helper takes necessasry + * request IRQ and register it. This helper takes necessary * arguments and performs the three steps in one go. * * An invalid IRQ skips the IRQ registration and expects the host to @@ -6265,7 +6265,7 @@ int ata_host_activate(struct ata_host *host, int irq, } /** - * ata_port_detach - Detach ATA port in prepration of device removal + * ata_port_detach - Detach ATA port in preparation of device removal * @ap: ATA port to be detached * * Detach all ATA devices and the associated SCSI devices of @ap; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 567859ce0512..90397baaa5f1 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1109,7 +1109,7 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) * @rq: request to be checked * * ATAPI commands which transfer variable length data to host - * might overflow due to application error or hardare bug. This + * might overflow due to application error or hardware bug. This * function checks whether overflow should be drained and ignored * for @request. * -- GitLab From 8010f13a40d3920d30c824e4b3ee0c6d298a7a8a Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 16 Mar 2016 21:54:57 +0200 Subject: [PATCH 2519/9938] ARM: dts: am43xx: add support for clkout1 clock clkout1 clock node and its generation tree was missing. Add this based on the data on TRM and PRCM functional spec. Signed-off-by: Tero Kristo Tested-by: Benoit Parrot Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am43xx-clocks.dtsi | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/arch/arm/boot/dts/am43xx-clocks.dtsi b/arch/arm/boot/dts/am43xx-clocks.dtsi index 34fecf2ddece..7630ba1d89e4 100644 --- a/arch/arm/boot/dts/am43xx-clocks.dtsi +++ b/arch/arm/boot/dts/am43xx-clocks.dtsi @@ -771,4 +771,58 @@ ti,bit-shift = <8>; reg = <0x8a68>; }; + + clkout1_osc_div_ck: clkout1_osc_div_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&sys_clkin_ck>; + ti,bit-shift = <20>; + ti,max-div = <4>; + reg = <0x4100>; + }; + + clkout1_src2_mux_ck: clkout1_src2_mux_ck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_rc32k_ck>, <&sysclk_div>, <&dpll_ddr_m2_ck>, + <&dpll_per_m2_ck>, <&dpll_disp_m2_ck>, + <&dpll_mpu_m2_ck>; + reg = <0x4100>; + }; + + clkout1_src2_pre_div_ck: clkout1_src2_pre_div_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&clkout1_src2_mux_ck>; + ti,bit-shift = <4>; + ti,max-div = <8>; + reg = <0x4100>; + }; + + clkout1_src2_post_div_ck: clkout1_src2_post_div_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&clkout1_src2_pre_div_ck>; + ti,bit-shift = <8>; + ti,max-div = <32>; + ti,index-power-of-two; + reg = <0x4100>; + }; + + clkout1_mux_ck: clkout1_mux_ck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clkout1_osc_div_ck>, <&clk_rc32k_ck>, + <&clkout1_src2_post_div_ck>, <&dpll_extdev_m2_ck>; + ti,bit-shift = <16>; + reg = <0x4100>; + }; + + clkout1_ck: clkout1_ck { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkout1_mux_ck>; + ti,bit-shift = <23>; + reg = <0x4100>; + }; }; -- GitLab From 7e8da343a31623decc7fd0ee66700ba50260aca7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 25 Jan 2016 22:41:46 -0200 Subject: [PATCH 2520/9938] [media] exynos4-is: Add missing port parent of_node_put on error paths In fimc_md_parse_port_node() remote port parent node is acquired with of_graph_get_remote_port_parent() but it is not put on error path. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index feb521f28e14..48f62dc4453e 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -446,8 +446,10 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, else pd->fimc_bus_type = pd->sensor_bus_type; - if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) + if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) { + of_node_put(rem); return -EINVAL; + } fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_OF; fmd->sensor[index].asd.match.of.node = rem; -- GitLab From 5790a1589f746d5648825d3bc8367f0ce7b12784 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 4 Mar 2016 17:20:12 -0300 Subject: [PATCH 2521/9938] [media] exynos4-is: Put node before s5pcsis_parse_dt() return error The MIPI CSIS DT parse function return an -ENXIO errno if the port # is outside of the supported values. But it doesn't call of_node_put() to decrement the node's reference counter, that's incremented inside the of_graph_get_next_endpoint() function that was called before. Instead of just returning, go to the error path that already does it. Signed-off-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/mipi-csis.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index bd5c46c3d4b7..bf954424e7be 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -757,8 +757,10 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, goto err; state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0; - if (state->index >= CSIS_MAX_ENTITIES) - return -ENXIO; + if (state->index >= CSIS_MAX_ENTITIES) { + ret = -ENXIO; + goto err; + } /* Get MIPI CSI-2 bus configration from the endpoint node. */ of_property_read_u32(node, "samsung,csis-hs-settle", -- GitLab From 77401dd7394c5d7b593718361ac6bb8f1aa4db62 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 8 Dec 2015 12:39:08 -0200 Subject: [PATCH 2522/9938] [media] s5p-jpeg: Adjust buffer size for Exynos 4412 Eliminate iommu fault during encoding by adjusting image size used for buffer size computation and ensuring that the buffer is not overrun. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index c3b13a630edf..caa19b408551 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1548,8 +1548,10 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx, struct v4l2_pix_format *pix = &f->fmt.pix; u32 pix_fmt = f->fmt.pix.pixelformat; int w = pix->width, h = pix->height, wh_align; + int padding = 0; if (pix_fmt == V4L2_PIX_FMT_RGB32 || + pix_fmt == V4L2_PIX_FMT_RGB565 || pix_fmt == V4L2_PIX_FMT_NV24 || pix_fmt == V4L2_PIX_FMT_NV42 || pix_fmt == V4L2_PIX_FMT_NV12 || @@ -1564,7 +1566,10 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx, &h, S5P_JPEG_MIN_HEIGHT, S5P_JPEG_MAX_HEIGHT, wh_align); - return w * h * fmt_depth >> 3; + if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) + padding = PAGE_SIZE; + + return (w * h * fmt_depth >> 3) + padding; } static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, -- GitLab From c1ac057173ba674d93afc8ddc5c91da1c61a951a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 9 Dec 2015 12:00:13 -0200 Subject: [PATCH 2523/9938] [media] exynos-gsc: remove non-device-tree init code Exynos platform has been fully converted to device tree, so old platform device based init data can be now removed. Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos-gsc/gsc-core.c | 33 ++++---------------- drivers/media/platform/exynos-gsc/gsc-core.h | 1 - 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 9b9e423e4fc4..032a423fb892 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -967,15 +967,6 @@ static struct gsc_driverdata gsc_v_100_drvdata = { .lclk_frequency = 266000000UL, }; -static const struct platform_device_id gsc_driver_ids[] = { - { - .name = "exynos-gsc", - .driver_data = (unsigned long)&gsc_v_100_drvdata, - }, - {}, -}; -MODULE_DEVICE_TABLE(platform, gsc_driver_ids); - static const struct of_device_id exynos_gsc_match[] = { { .compatible = "samsung,exynos5-gsc", @@ -988,17 +979,11 @@ MODULE_DEVICE_TABLE(of, exynos_gsc_match); static void *gsc_get_drv_data(struct platform_device *pdev) { struct gsc_driverdata *driver_data = NULL; + const struct of_device_id *match; - if (pdev->dev.of_node) { - const struct of_device_id *match; - match = of_match_node(exynos_gsc_match, - pdev->dev.of_node); - if (match) - driver_data = (struct gsc_driverdata *)match->data; - } else { - driver_data = (struct gsc_driverdata *) - platform_get_device_id(pdev)->driver_data; - } + match = of_match_node(exynos_gsc_match, pdev->dev.of_node); + if (match) + driver_data = (struct gsc_driverdata *)match->data; return driver_data; } @@ -1084,19 +1069,14 @@ static int gsc_probe(struct platform_device *pdev) if (!gsc) return -ENOMEM; - if (dev->of_node) - gsc->id = of_alias_get_id(pdev->dev.of_node, "gsc"); - else - gsc->id = pdev->id; - - if (gsc->id >= drv_data->num_entities) { + gsc->id = of_alias_get_id(pdev->dev.of_node, "gsc"); + if (gsc->id >= drv_data->num_entities || gsc->id < 0) { dev_err(dev, "Invalid platform device id: %d\n", gsc->id); return -EINVAL; } gsc->variant = drv_data->variant[gsc->id]; gsc->pdev = pdev; - gsc->pdata = dev->platform_data; init_waitqueue_head(&gsc->irq_queue); spin_lock_init(&gsc->slock); @@ -1253,7 +1233,6 @@ static const struct dev_pm_ops gsc_pm_ops = { static struct platform_driver gsc_driver = { .probe = gsc_probe, .remove = gsc_remove, - .id_table = gsc_driver_ids, .driver = { .name = GSC_MODULE_NAME, .pm = &gsc_pm_ops, diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index e93a2336cfa2..ec4000c72172 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h @@ -340,7 +340,6 @@ struct gsc_dev { void __iomem *regs; wait_queue_head_t irq_queue; struct gsc_m2m_device m2m; - struct exynos_platform_gscaler *pdata; unsigned long state; struct vb2_alloc_ctx *alloc_ctx; struct video_device vdev; -- GitLab From ef3617c4b887a9b176210b4b80c0fe964cbe8c2a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 9 Dec 2015 12:00:14 -0200 Subject: [PATCH 2524/9938] [media] s5p-g2d: remove non-device-tree init code Exynos and Samsung S5P platforms has been fully converted to device tree, so old platform device based init data can be now removed. Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-g2d/g2d.c | 27 +++++---------------------- drivers/media/platform/s5p-g2d/g2d.h | 5 ----- 2 files changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 74bd46ca7942..612d1ea514f1 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -719,16 +719,12 @@ static int g2d_probe(struct platform_device *pdev) def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; - if (!pdev->dev.of_node) { - dev->variant = g2d_get_drv_data(pdev); - } else { - of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node); - if (!of_id) { - ret = -ENODEV; - goto unreg_video_dev; - } - dev->variant = (struct g2d_variant *)of_id->data; + of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node); + if (!of_id) { + ret = -ENODEV; + goto unreg_video_dev; } + dev->variant = (struct g2d_variant *)of_id->data; return 0; @@ -788,22 +784,9 @@ static const struct of_device_id exynos_g2d_match[] = { }; MODULE_DEVICE_TABLE(of, exynos_g2d_match); -static const struct platform_device_id g2d_driver_ids[] = { - { - .name = "s5p-g2d", - .driver_data = (unsigned long)&g2d_drvdata_v3x, - }, { - .name = "s5p-g2d-v4x", - .driver_data = (unsigned long)&g2d_drvdata_v4x, - }, - {}, -}; -MODULE_DEVICE_TABLE(platform, g2d_driver_ids); - static struct platform_driver g2d_pdrv = { .probe = g2d_probe, .remove = g2d_remove, - .id_table = g2d_driver_ids, .driver = { .name = G2D_NAME, .of_match_table = exynos_g2d_match, diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h index b0e52ab7ecdb..e31df541aa62 100644 --- a/drivers/media/platform/s5p-g2d/g2d.h +++ b/drivers/media/platform/s5p-g2d/g2d.h @@ -89,8 +89,3 @@ void g2d_set_flip(struct g2d_dev *d, u32 r); void g2d_set_v41_stretch(struct g2d_dev *d, struct g2d_frame *src, struct g2d_frame *dst); void g2d_set_cmd(struct g2d_dev *d, u32 c); - -static inline struct g2d_variant *g2d_get_drv_data(struct platform_device *pdev) -{ - return (struct g2d_variant *)platform_get_device_id(pdev)->driver_data; -} -- GitLab From ed3e34ed828c00ac7eafd24079d90a8fabcf07cc Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 9 Dec 2015 12:00:15 -0200 Subject: [PATCH 2525/9938] [media] s5p-mfc: remove non-device-tree init code Exynos and Samsung S5P platforms has been fully converted to device tree, so old platform device based init data can be now removed. Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 37 ++++-------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 927ab4928779..b16466fe35ee 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1489,27 +1489,6 @@ static struct s5p_mfc_variant mfc_drvdata_v8 = { .fw_name[0] = "s5p-mfc-v8.fw", }; -static const struct platform_device_id mfc_driver_ids[] = { - { - .name = "s5p-mfc", - .driver_data = (unsigned long)&mfc_drvdata_v5, - }, { - .name = "s5p-mfc-v5", - .driver_data = (unsigned long)&mfc_drvdata_v5, - }, { - .name = "s5p-mfc-v6", - .driver_data = (unsigned long)&mfc_drvdata_v6, - }, { - .name = "s5p-mfc-v7", - .driver_data = (unsigned long)&mfc_drvdata_v7, - }, { - .name = "s5p-mfc-v8", - .driver_data = (unsigned long)&mfc_drvdata_v8, - }, - {}, -}; -MODULE_DEVICE_TABLE(platform, mfc_driver_ids); - static const struct of_device_id exynos_mfc_match[] = { { .compatible = "samsung,mfc-v5", @@ -1531,24 +1510,18 @@ MODULE_DEVICE_TABLE(of, exynos_mfc_match); static void *mfc_get_drv_data(struct platform_device *pdev) { struct s5p_mfc_variant *driver_data = NULL; + const struct of_device_id *match; + + match = of_match_node(exynos_mfc_match, pdev->dev.of_node); + if (match) + driver_data = (struct s5p_mfc_variant *)match->data; - if (pdev->dev.of_node) { - const struct of_device_id *match; - match = of_match_node(exynos_mfc_match, - pdev->dev.of_node); - if (match) - driver_data = (struct s5p_mfc_variant *)match->data; - } else { - driver_data = (struct s5p_mfc_variant *) - platform_get_device_id(pdev)->driver_data; - } return driver_data; } static struct platform_driver s5p_mfc_driver = { .probe = s5p_mfc_probe, .remove = s5p_mfc_remove, - .id_table = mfc_driver_ids, .driver = { .name = S5P_MFC_NAME, .pm = &s5p_mfc_pm_ops, -- GitLab From 4c9c6d86d190caa00028dcb3e9864e57aa9a1df6 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 9 Dec 2015 12:00:16 -0200 Subject: [PATCH 2526/9938] [media] exynos4-is: remove non-device-tree init code Exynos and Samsung S5P platforms has been fully converted to device tree, so old platform device based init data can be now removed. Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-core.c | 50 ------------------- 1 file changed, 50 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index cef2a7f07cdb..b1c1cea82a27 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -1154,26 +1154,6 @@ static const struct fimc_pix_limit s5p_pix_limit[4] = { }, }; -static const struct fimc_variant fimc0_variant_s5p = { - .has_inp_rot = 1, - .has_out_rot = 1, - .has_cam_if = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 8, - .min_vsize_align = 16, - .pix_limit = &s5p_pix_limit[0], -}; - -static const struct fimc_variant fimc2_variant_s5p = { - .has_cam_if = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 8, - .min_vsize_align = 16, - .pix_limit = &s5p_pix_limit[1], -}; - static const struct fimc_variant fimc0_variant_s5pv210 = { .has_inp_rot = 1, .has_out_rot = 1, @@ -1206,18 +1186,6 @@ static const struct fimc_variant fimc2_variant_s5pv210 = { .pix_limit = &s5p_pix_limit[2], }; -/* S5PC100 */ -static const struct fimc_drvdata fimc_drvdata_s5p = { - .variant = { - [0] = &fimc0_variant_s5p, - [1] = &fimc0_variant_s5p, - [2] = &fimc2_variant_s5p, - }, - .num_entities = 3, - .lclk_frequency = 133000000UL, - .out_buf_count = 4, -}; - /* S5PV210, S5PC110 */ static const struct fimc_drvdata fimc_drvdata_s5pv210 = { .variant = { @@ -1251,23 +1219,6 @@ static const struct fimc_drvdata fimc_drvdata_exynos4x12 = { .out_buf_count = 32, }; -static const struct platform_device_id fimc_driver_ids[] = { - { - .name = "s5p-fimc", - .driver_data = (unsigned long)&fimc_drvdata_s5p, - }, { - .name = "s5pv210-fimc", - .driver_data = (unsigned long)&fimc_drvdata_s5pv210, - }, { - .name = "exynos4-fimc", - .driver_data = (unsigned long)&fimc_drvdata_exynos4210, - }, { - .name = "exynos4x12-fimc", - .driver_data = (unsigned long)&fimc_drvdata_exynos4x12, - }, - { }, -}; - static const struct of_device_id fimc_of_match[] = { { .compatible = "samsung,s5pv210-fimc", @@ -1290,7 +1241,6 @@ static const struct dev_pm_ops fimc_pm_ops = { static struct platform_driver fimc_driver = { .probe = fimc_probe, .remove = fimc_remove, - .id_table = fimc_driver_ids, .driver = { .of_match_table = fimc_of_match, .name = FIMC_DRIVER_NAME, -- GitLab From adbedc29524a31cc6196d991acc04ee797abc11b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 15 Nov 2015 18:08:23 -0200 Subject: [PATCH 2527/9938] [media] s5p-tv: constify mxr_layer_ops structures The mxr_layer_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/mixer.h | 2 +- drivers/media/platform/s5p-tv/mixer_grp_layer.c | 2 +- drivers/media/platform/s5p-tv/mixer_video.c | 2 +- drivers/media/platform/s5p-tv/mixer_vp_layer.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h index 42cd2709c41c..4dd62a918fcf 100644 --- a/drivers/media/platform/s5p-tv/mixer.h +++ b/drivers/media/platform/s5p-tv/mixer.h @@ -300,7 +300,7 @@ void mxr_release_video(struct mxr_device *mdev); struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx); struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx); struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, - int idx, char *name, struct mxr_layer_ops *ops); + int idx, char *name, const struct mxr_layer_ops *ops); void mxr_base_layer_release(struct mxr_layer *layer); void mxr_layer_release(struct mxr_layer *layer); diff --git a/drivers/media/platform/s5p-tv/mixer_grp_layer.c b/drivers/media/platform/s5p-tv/mixer_grp_layer.c index db3163b23ea0..d4d2564f7de7 100644 --- a/drivers/media/platform/s5p-tv/mixer_grp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_grp_layer.c @@ -235,7 +235,7 @@ struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx) { struct mxr_layer *layer; int ret; - struct mxr_layer_ops ops = { + const struct mxr_layer_ops ops = { .release = mxr_graph_layer_release, .buffer_set = mxr_graph_buffer_set, .stream_set = mxr_graph_stream_set, diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index d9e7f030294c..7ab5578a0405 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -1070,7 +1070,7 @@ static void mxr_vfd_release(struct video_device *vdev) } struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, - int idx, char *name, struct mxr_layer_ops *ops) + int idx, char *name, const struct mxr_layer_ops *ops) { struct mxr_layer *layer; diff --git a/drivers/media/platform/s5p-tv/mixer_vp_layer.c b/drivers/media/platform/s5p-tv/mixer_vp_layer.c index dd002a497dbb..6fa6f673f53b 100644 --- a/drivers/media/platform/s5p-tv/mixer_vp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_vp_layer.c @@ -207,7 +207,7 @@ struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx) { struct mxr_layer *layer; int ret; - struct mxr_layer_ops ops = { + const struct mxr_layer_ops ops = { .release = mxr_vp_layer_release, .buffer_set = mxr_vp_buffer_set, .stream_set = mxr_vp_stream_set, -- GitLab From 26a7ed9c18193dc7a3dfba33e3c711822f4bdd29 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 Apr 2016 16:29:31 -0300 Subject: [PATCH 2528/9938] [media] exynos-gsc: remove an always false condition As reported by smatch: drivers/media/platform/exynos-gsc/gsc-core.c:1073 gsc_probe() warn: impossible condition '(gsc->id < 0) => (0-65535 < 0)' drivers/media/platform/exynos-gsc/gsc-core.c: In function 'gsc_probe': drivers/media/platform/exynos-gsc/gsc-core.c:1073:51: warning: comparison is always false due to limited range of data type [-Wtype-limits] if (gsc->id >= drv_data->num_entities || gsc->id < 0) { ^ gsc->id is an u16, so it can never be a negative number. So, remove the always false condition. Fixes: c1ac057173ba "[media] exynos-gsc: remove non-device-tree init code" Cc: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos-gsc/gsc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 032a423fb892..c595723f5031 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -1070,7 +1070,7 @@ static int gsc_probe(struct platform_device *pdev) return -ENOMEM; gsc->id = of_alias_get_id(pdev->dev.of_node, "gsc"); - if (gsc->id >= drv_data->num_entities || gsc->id < 0) { + if (gsc->id >= drv_data->num_entities) { dev_err(dev, "Invalid platform device id: %d\n", gsc->id); return -EINVAL; } -- GitLab From c888a8f95ae5b1067855235b3b71c1ebccf504f5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 13 Apr 2016 13:33:19 -0600 Subject: [PATCH 2529/9938] block: kill off q->flush_flags Now that we converted everything to the newer block write cache interface, kill off the queue flush_flags and queueable flush entries. Signed-off-by: Jens Axboe --- block/blk-core.c | 3 ++- block/blk-flush.c | 11 ++++++----- block/blk-settings.c | 18 ++++++++++-------- drivers/block/xen-blkback/xenbus.c | 2 +- drivers/md/dm-table.c | 12 ++++++------ drivers/md/raid5-cache.c | 3 ++- drivers/target/target_core_iblock.c | 6 +++--- include/linux/blkdev.h | 5 ++--- 8 files changed, 32 insertions(+), 28 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index c50227796a26..2475b1c72773 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1964,7 +1964,8 @@ generic_make_request_checks(struct bio *bio) * drivers without flush support don't have to worry * about them. */ - if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) { + if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && + !test_bit(QUEUE_FLAG_WC, &q->queue_flags)) { bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA); if (!nr_sectors) { err = 0; diff --git a/block/blk-flush.c b/block/blk-flush.c index 9c423e53324a..b1c91d229e5e 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -95,17 +95,18 @@ enum { static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq); -static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq) +static unsigned int blk_flush_policy(unsigned long fflags, struct request *rq) { unsigned int policy = 0; if (blk_rq_sectors(rq)) policy |= REQ_FSEQ_DATA; - if (fflags & REQ_FLUSH) { + if (fflags & (1UL << QUEUE_FLAG_WC)) { if (rq->cmd_flags & REQ_FLUSH) policy |= REQ_FSEQ_PREFLUSH; - if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) + if (!(fflags & (1UL << QUEUE_FLAG_FUA)) && + (rq->cmd_flags & REQ_FUA)) policy |= REQ_FSEQ_POSTFLUSH; } return policy; @@ -384,7 +385,7 @@ static void mq_flush_data_end_io(struct request *rq, int error) void blk_insert_flush(struct request *rq) { struct request_queue *q = rq->q; - unsigned int fflags = q->flush_flags; /* may change, cache */ + unsigned long fflags = q->queue_flags; /* may change, cache */ unsigned int policy = blk_flush_policy(fflags, rq); struct blk_flush_queue *fq = blk_get_flush_queue(q, rq->mq_ctx); @@ -393,7 +394,7 @@ void blk_insert_flush(struct request *rq) * REQ_FLUSH and FUA for the driver. */ rq->cmd_flags &= ~REQ_FLUSH; - if (!(fflags & REQ_FUA)) + if (!(fflags & (1UL << QUEUE_FLAG_FUA))) rq->cmd_flags &= ~REQ_FUA; /* diff --git a/block/blk-settings.c b/block/blk-settings.c index 80d9327a214b..f679ae122843 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -822,7 +822,12 @@ EXPORT_SYMBOL(blk_queue_update_dma_alignment); void blk_queue_flush_queueable(struct request_queue *q, bool queueable) { - q->flush_not_queueable = !queueable; + spin_lock_irq(q->queue_lock); + if (queueable) + clear_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags); + else + set_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags); + spin_unlock_irq(q->queue_lock); } EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); @@ -837,16 +842,13 @@ EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); void blk_queue_write_cache(struct request_queue *q, bool wc, bool fua) { spin_lock_irq(q->queue_lock); - if (wc) { + if (wc) queue_flag_set(QUEUE_FLAG_WC, q); - q->flush_flags = REQ_FLUSH; - } else + else queue_flag_clear(QUEUE_FLAG_WC, q); - if (fua) { - if (wc) - q->flush_flags |= REQ_FUA; + if (fua) queue_flag_set(QUEUE_FLAG_FUA, q); - } else + else queue_flag_clear(QUEUE_FLAG_FUA, q); spin_unlock_irq(q->queue_lock); } diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 26aa080e243c..3355f1cdd4e5 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -477,7 +477,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, vbd->type |= VDISK_REMOVABLE; q = bdev_get_queue(bdev); - if (q && q->flush_flags) + if (q && test_bit(QUEUE_FLAG_WC, &q->queue_flags)) vbd->flush_support = true; if (q && blk_queue_secdiscard(q)) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 4b1ffc0abe11..626a5ec04466 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1348,13 +1348,13 @@ static void dm_table_verify_integrity(struct dm_table *t) static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { - unsigned flush = (*(unsigned *)data); + unsigned long flush = (unsigned long) data; struct request_queue *q = bdev_get_queue(dev->bdev); - return q && (q->flush_flags & flush); + return q && (q->queue_flags & flush); } -static bool dm_table_supports_flush(struct dm_table *t, unsigned flush) +static bool dm_table_supports_flush(struct dm_table *t, unsigned long flush) { struct dm_target *ti; unsigned i = 0; @@ -1375,7 +1375,7 @@ static bool dm_table_supports_flush(struct dm_table *t, unsigned flush) return true; if (ti->type->iterate_devices && - ti->type->iterate_devices(ti, device_flush_capable, &flush)) + ti->type->iterate_devices(ti, device_flush_capable, (void *) flush)) return true; } @@ -1518,9 +1518,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, else queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); - if (dm_table_supports_flush(t, REQ_FLUSH)) { + if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_WC))) { wc = true; - if (dm_table_supports_flush(t, REQ_FUA)) + if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_FUA))) fua = true; } blk_queue_write_cache(q, wc, fua); diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 9531f5f05b93..26f14970a858 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -1188,6 +1188,7 @@ static int r5l_load_log(struct r5l_log *log) int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) { + struct request_queue *q = bdev_get_queue(rdev->bdev); struct r5l_log *log; if (PAGE_SIZE != 4096) @@ -1197,7 +1198,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) return -ENOMEM; log->rdev = rdev; - log->need_cache_flush = (rdev->bdev->bd_disk->queue->flush_flags != 0); + log->need_cache_flush = test_bit(QUEUE_FLAG_WC, &q->queue_flags) != 0; log->uuid_checksum = crc32c_le(~0, rdev->mddev->uuid, sizeof(rdev->mddev->uuid)); diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 026a758e5778..7c4efb4417b0 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -687,10 +687,10 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, * Force writethrough using WRITE_FUA if a volatile write cache * is not enabled, or if initiator set the Force Unit Access bit. */ - if (q->flush_flags & REQ_FUA) { + if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { if (cmd->se_cmd_flags & SCF_FUA) rw = WRITE_FUA; - else if (!(q->flush_flags & REQ_FLUSH)) + else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) rw = WRITE_FUA; else rw = WRITE; @@ -836,7 +836,7 @@ static bool iblock_get_write_cache(struct se_device *dev) struct block_device *bd = ib_dev->ibd_bd; struct request_queue *q = bdev_get_queue(bd); - return q->flush_flags & REQ_FLUSH; + return test_bit(QUEUE_FLAG_WC, &q->queue_flags); } static const struct target_backend_ops iblock_ops = { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f3f232fa505d..57c085917da6 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -433,8 +433,6 @@ struct request_queue { /* * for flush operations */ - unsigned int flush_flags; - unsigned int flush_not_queueable:1; struct blk_flush_queue *fq; struct list_head requeue_list; @@ -493,6 +491,7 @@ struct request_queue { #define QUEUE_FLAG_POLL 22 /* IO polling enabled if set */ #define QUEUE_FLAG_WC 23 /* Write back caching */ #define QUEUE_FLAG_FUA 24 /* device supports FUA writes */ +#define QUEUE_FLAG_FLUSH_NQ 25 /* flush not queueuable */ #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_STACKABLE) | \ @@ -1365,7 +1364,7 @@ static inline unsigned int block_size(struct block_device *bdev) static inline bool queue_flush_queueable(struct request_queue *q) { - return !q->flush_not_queueable; + return !test_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags); } typedef struct {struct page *v;} Sector; -- GitLab From 7bbe7813290df9fda0c175b7a703325720594912 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 1 Mar 2016 11:57:23 -0300 Subject: [PATCH 2530/9938] [media] v4l2: add device_caps to struct video_device Instead of letting drivers fill in device_caps at querycap time, let them fill it in when the video device is registered. This has the advantage that in the future the v4l2 core can access the video device's capabilities and take decisions based on that. Signed-off-by: Hans Verkuil Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 3 +++ include/media/v4l2-dev.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 170dd68d27f4..6bf5a3ecd126 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1020,9 +1020,12 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_capability *cap = (struct v4l2_capability *)arg; + struct video_device *vfd = video_devdata(file); int ret; cap->version = LINUX_VERSION_CODE; + cap->device_caps = vfd->device_caps; + cap->capabilities = vfd->device_caps | V4L2_CAP_DEVICE_CAPS; ret = ops->vidioc_querycap(file, fh, cap); diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 76056ab5c5bd..25a3190308fb 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -92,6 +92,9 @@ struct video_device /* device ops */ const struct v4l2_file_operations *fops; + /* device capabilities as used in v4l2_capabilities */ + u32 device_caps; + /* sysfs */ struct device dev; /* v4l device */ struct cdev *cdev; /* character device */ -- GitLab From 3e43cb33f637d77405ccddc81a6d76acd57ff71c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 1 Mar 2016 11:57:24 -0300 Subject: [PATCH 2531/9938] [media] v4l2-pci-skeleton.c: fill in device_caps in video_device With the new core support for the caps the driver no longer needs to set device_caps and capabilities in the querycap call. Signed-off-by: Hans Verkuil Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-pci-skeleton.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/Documentation/video4linux/v4l2-pci-skeleton.c index 79af0c041056..a55cf94ac907 100644 --- a/Documentation/video4linux/v4l2-pci-skeleton.c +++ b/Documentation/video4linux/v4l2-pci-skeleton.c @@ -308,9 +308,6 @@ static int skeleton_querycap(struct file *file, void *priv, strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(skel->pdev)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -872,6 +869,8 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) vdev->release = video_device_release_empty; vdev->fops = &skel_fops, vdev->ioctl_ops = &skel_ioctl_ops, + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; /* * The main serialization lock. All ioctls are serialized by this * lock. Exception: if q->lock is set, then the streaming ioctls -- GitLab From 9765a32cd802709d152a0d73d0cbfd07c9f49808 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 1 Mar 2016 11:57:25 -0300 Subject: [PATCH 2532/9938] [media] vivid: set device_caps in video_device This simplifies the querycap function. Signed-off-by: Hans Verkuil Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-core.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index ec125becb7af..c14da84af09b 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -200,27 +200,12 @@ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct vivid_dev *dev = video_drvdata(file); - struct video_device *vdev = video_devdata(file); strcpy(cap->driver, "vivid"); strcpy(cap->card, "vivid"); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev->v4l2_dev.name); - if (vdev->vfl_type == VFL_TYPE_GRABBER && vdev->vfl_dir == VFL_DIR_RX) - cap->device_caps = dev->vid_cap_caps; - if (vdev->vfl_type == VFL_TYPE_GRABBER && vdev->vfl_dir == VFL_DIR_TX) - cap->device_caps = dev->vid_out_caps; - else if (vdev->vfl_type == VFL_TYPE_VBI && vdev->vfl_dir == VFL_DIR_RX) - cap->device_caps = dev->vbi_cap_caps; - else if (vdev->vfl_type == VFL_TYPE_VBI && vdev->vfl_dir == VFL_DIR_TX) - cap->device_caps = dev->vbi_out_caps; - else if (vdev->vfl_type == VFL_TYPE_SDR) - cap->device_caps = dev->sdr_cap_caps; - else if (vdev->vfl_type == VFL_TYPE_RADIO && vdev->vfl_dir == VFL_DIR_RX) - cap->device_caps = dev->radio_rx_caps; - else if (vdev->vfl_type == VFL_TYPE_RADIO && vdev->vfl_dir == VFL_DIR_TX) - cap->device_caps = dev->radio_tx_caps; cap->capabilities = dev->vid_cap_caps | dev->vid_out_caps | dev->vbi_cap_caps | dev->vbi_out_caps | dev->radio_rx_caps | dev->radio_tx_caps | @@ -1135,6 +1120,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) strlcpy(vfd->name, "vivid-vid-cap", sizeof(vfd->name)); vfd->fops = &vivid_fops; vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->vid_cap_caps; vfd->release = video_device_release_empty; vfd->v4l2_dev = &dev->v4l2_dev; vfd->queue = &dev->vb_vid_cap_q; @@ -1160,6 +1146,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) vfd->vfl_dir = VFL_DIR_TX; vfd->fops = &vivid_fops; vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->vid_out_caps; vfd->release = video_device_release_empty; vfd->v4l2_dev = &dev->v4l2_dev; vfd->queue = &dev->vb_vid_out_q; @@ -1184,6 +1171,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) strlcpy(vfd->name, "vivid-vbi-cap", sizeof(vfd->name)); vfd->fops = &vivid_fops; vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->vbi_cap_caps; vfd->release = video_device_release_empty; vfd->v4l2_dev = &dev->v4l2_dev; vfd->queue = &dev->vb_vbi_cap_q; @@ -1207,6 +1195,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) vfd->vfl_dir = VFL_DIR_TX; vfd->fops = &vivid_fops; vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->vbi_out_caps; vfd->release = video_device_release_empty; vfd->v4l2_dev = &dev->v4l2_dev; vfd->queue = &dev->vb_vbi_out_q; @@ -1229,6 +1218,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) strlcpy(vfd->name, "vivid-sdr-cap", sizeof(vfd->name)); vfd->fops = &vivid_fops; vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->sdr_cap_caps; vfd->release = video_device_release_empty; vfd->v4l2_dev = &dev->v4l2_dev; vfd->queue = &dev->vb_sdr_cap_q; @@ -1247,6 +1237,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) strlcpy(vfd->name, "vivid-rad-rx", sizeof(vfd->name)); vfd->fops = &vivid_radio_fops; vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->radio_rx_caps; vfd->release = video_device_release_empty; vfd->v4l2_dev = &dev->v4l2_dev; vfd->lock = &dev->mutex; @@ -1265,6 +1256,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) vfd->vfl_dir = VFL_DIR_TX; vfd->fops = &vivid_radio_fops; vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->radio_tx_caps; vfd->release = video_device_release_empty; vfd->v4l2_dev = &dev->v4l2_dev; vfd->lock = &dev->mutex; -- GitLab From 54ace1cfd4358fd11112f17cc711eea234d5ab9e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 29 Feb 2016 07:16:39 -0300 Subject: [PATCH 2533/9938] [media] v4l2-ioctl: simplify code Instead of a big if at the beginning, just check if g_selection == NULL and call the cropcap op immediately and return the result. No functional changes in this patch. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 51 ++++++++++++++++------------ 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 6bf5a3ecd126..3cf8d3adab03 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2160,33 +2160,40 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_cropcap *p = arg; + struct v4l2_selection s = { .type = p->type }; + int ret; - if (ops->vidioc_g_selection) { - struct v4l2_selection s = { .type = p->type }; - int ret; + if (ops->vidioc_g_selection == NULL) { + /* + * The determine_valid_ioctls() call already should ensure + * that ops->vidioc_cropcap != NULL, but just in case... + */ + if (ops->vidioc_cropcap) + return ops->vidioc_cropcap(file, fh, p); + return -ENOTTY; + } - /* obtaining bounds */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; - else - s.target = V4L2_SEL_TGT_CROP_BOUNDS; + /* obtaining bounds */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; + else + s.target = V4L2_SEL_TGT_CROP_BOUNDS; - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - return ret; - p->bounds = s.r; + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->bounds = s.r; - /* obtaining defrect */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; - else - s.target = V4L2_SEL_TGT_CROP_DEFAULT; + /* obtaining defrect */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; + else + s.target = V4L2_SEL_TGT_CROP_DEFAULT; - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - return ret; - p->defrect = s.r; - } + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->defrect = s.r; /* setting trivial pixelaspect */ p->pixelaspect.numerator = 1; -- GitLab From 1254880834d08ad288b9706b5bd791dc11516e40 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 7 Mar 2016 07:22:23 -0300 Subject: [PATCH 2534/9938] [media] cx231xx: fix memory leak When we returned on error we missed freeing p_current_fw and p_buffer. Signed-off-by: Sudip Mukherjee Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-417.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index c9320d6c6131..3636d8d0abd3 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -966,6 +966,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev) p_buffer = vmalloc(4096); if (p_buffer == NULL) { dprintk(2, "FAIL!!!\n"); + vfree(p_current_fw); return -1; } @@ -989,6 +990,8 @@ static int cx231xx_load_firmware(struct cx231xx *dev) if (retval != 0) { dev_err(dev->dev, "%s: Error with mc417_register_write\n", __func__); + vfree(p_current_fw); + vfree(p_buffer); return -1; } @@ -1001,6 +1004,8 @@ static int cx231xx_load_firmware(struct cx231xx *dev) CX231xx_FIRM_IMAGE_NAME); dev_err(dev->dev, "Please fix your hotplug setup, the board will not work without firmware loaded!\n"); + vfree(p_current_fw); + vfree(p_buffer); return -1; } @@ -1009,6 +1014,8 @@ static int cx231xx_load_firmware(struct cx231xx *dev) "ERROR: Firmware size mismatch (have %zd, expected %d)\n", firmware->size, CX231xx_FIRM_IMAGE_SIZE); release_firmware(firmware); + vfree(p_current_fw); + vfree(p_buffer); return -1; } @@ -1016,6 +1023,8 @@ static int cx231xx_load_firmware(struct cx231xx *dev) dev_err(dev->dev, "ERROR: Firmware magic mismatch, wrong file?\n"); release_firmware(firmware); + vfree(p_current_fw); + vfree(p_buffer); return -1; } -- GitLab From ccc5429f7bf9c78d64f1bb03c578f1641ca72fe4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 Apr 2016 17:02:20 -0300 Subject: [PATCH 2535/9938] [media] cx231xx: return proper error codes at cx231xx-417.c Instead of returning -1, return valid error codes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-417.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 3636d8d0abd3..00da024b47a6 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -360,7 +360,7 @@ static int wait_for_mci_complete(struct cx231xx *dev) if (count++ > 100) { dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio); - return -1; + return -EIO; } } return 0; @@ -856,7 +856,7 @@ static int cx231xx_find_mailbox(struct cx231xx *dev) } } dprintk(3, "Mailbox signature values not found!\n"); - return -1; + return -EIO; } static void mci_write_memory_to_gpio(struct cx231xx *dev, u32 address, u32 value, @@ -960,14 +960,14 @@ static int cx231xx_load_firmware(struct cx231xx *dev) p_fw = p_current_fw; if (p_current_fw == NULL) { dprintk(2, "FAIL!!!\n"); - return -1; + return -ENOMEM; } p_buffer = vmalloc(4096); if (p_buffer == NULL) { dprintk(2, "FAIL!!!\n"); vfree(p_current_fw); - return -1; + return -ENOMEM; } dprintk(2, "%s()\n", __func__); @@ -992,7 +992,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev) "%s: Error with mc417_register_write\n", __func__); vfree(p_current_fw); vfree(p_buffer); - return -1; + return retval; } retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME, @@ -1006,7 +1006,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev) "Please fix your hotplug setup, the board will not work without firmware loaded!\n"); vfree(p_current_fw); vfree(p_buffer); - return -1; + return retval; } if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) { @@ -1016,7 +1016,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev) release_firmware(firmware); vfree(p_current_fw); vfree(p_buffer); - return -1; + return -EINVAL; } if (0 != memcmp(firmware->data, magic, 8)) { @@ -1025,7 +1025,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev) release_firmware(firmware); vfree(p_current_fw); vfree(p_buffer); - return -1; + return -EINVAL; } initGPIO(dev); @@ -1140,21 +1140,21 @@ static int cx231xx_initialize_codec(struct cx231xx *dev) if (retval < 0) { dev_err(dev->dev, "%s: mailbox < 0, error\n", __func__); - return -1; + return retval; } dev->cx23417_mailbox = retval; retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); if (retval < 0) { dev_err(dev->dev, "ERROR: cx23417 firmware ping failed!\n"); - return -1; + return retval; } retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version); if (retval < 0) { dev_err(dev->dev, "ERROR: cx23417 firmware get encoder: version failed!\n"); - return -1; + return retval; } dprintk(1, "cx23417 firmware version is 0x%08x\n", version); msleep(200); -- GitLab From 2a518f8e87a718b482a5ac7ffa9590cc7d86004f Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 7 Mar 2016 07:26:55 -0300 Subject: [PATCH 2536/9938] [media] dw2102: fix unreleased firmware On the particular case when the product id is 0x2101 we have requested for a firmware but after processing it we missed releasing it. Signed-off-by: Sudip Mukherjee Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 6d0dd859d684..1f35f3decf39 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1843,6 +1843,9 @@ static int dw2102_load_firmware(struct usb_device *dev, msleep(100); kfree(p); } + + if (le16_to_cpu(dev->descriptor.idProduct) == 0x2101) + release_firmware(fw); return ret; } -- GitLab From baf43c6eace43868e490f18560287fa3481b2159 Mon Sep 17 00:00:00 2001 From: Tiffany Lin Date: Mon, 14 Mar 2016 08:16:14 -0300 Subject: [PATCH 2537/9938] [media] media: v4l2-compat-ioctl32: fix missing reserved field copy in put_v4l2_create32 In v4l2-compliance utility, test VIDIOC_CREATE_BUFS will check whether reserved filed of v4l2_create_buffers filled with zero Reserved field is filled with zero in v4l_create_bufs. This patch copy reserved field of v4l2_create_buffer from kernel space to user space Signed-off-by: Tiffany Lin Signed-off-by: Hans Verkuil Cc: # for v3.19 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 019644ff627d..bacecbd68a6d 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -280,7 +280,8 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || - copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format))) + copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) || + copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) return -EFAULT; return __put_v4l2_format32(&kp->format, &up->format); } -- GitLab From c16352b5b35d8f619028ebf855ce42c1f99649e6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 14 Mar 2016 19:40:07 -0300 Subject: [PATCH 2538/9938] [media] cobalt: add MTD dependency The cobalt driver fails to link when it is built-in and MTD is disabled or a loadable module: drivers/media/built-in.o: In function `cobalt_flash_probe': :(.text+0xb8b46): undefined reference to `mtd_device_parse_register' :(.text+0xb8b88): undefined reference to `do_map_probe' drivers/media/built-in.o: In function `cobalt_flash_remove': :(.text+0xb8bb4): undefined reference to `mtd_device_unregister' :(.text+0xb8bbe): undefined reference to `map_destroy' This adds a Kconfig dependency to ensure we can call the API. Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cobalt/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/pci/cobalt/Kconfig b/drivers/media/pci/cobalt/Kconfig index a01f0cc745cc..70343829a125 100644 --- a/drivers/media/pci/cobalt/Kconfig +++ b/drivers/media/pci/cobalt/Kconfig @@ -4,6 +4,7 @@ config VIDEO_COBALT depends on PCI_MSI && MTD_COMPLEX_MAPPINGS depends on GPIOLIB || COMPILE_TEST depends on SND + depends on MTD select I2C_ALGOBIT select VIDEO_ADV7604 select VIDEO_ADV7511 -- GitLab From 0fb504001192c1df62c847a8bb6558753c36ebef Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 14 Mar 2016 19:40:08 -0300 Subject: [PATCH 2539/9938] [media] am437x-vfpe: fix typo in vpfe_get_app_input_index gcc-6 points out an obviously silly comparison in vpfe_get_app_input_index(): drivers/media/platform/am437x/am437x-vpfe.c: In function 'vpfe_get_app_input_index': drivers/media/platform/am437x/am437x-vpfe.c:1709:27: warning: self-comparison always evaluats to true [-Wtautological-compare] client->adapter->nr == client->adapter->nr) { ^~ This was introduced in a slighly incorrect conversion, and it's clear that the comparison was meant to compare the iterator to the current subdev instead, as we do in the line above. Fixes: d37232390fd4 ("[media] media: am437x-vpfe: match the OF node/i2c addr instead of name") Signed-off-by: Arnd Bergmann Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index de32e3a3d4d1..e6a7bff4650c 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1706,7 +1706,7 @@ static int vpfe_get_app_input_index(struct vpfe_device *vpfe, sdinfo = &cfg->sub_devs[i]; client = v4l2_get_subdevdata(sdinfo->sd); if (client->addr == curr_client->addr && - client->adapter->nr == client->adapter->nr) { + client->adapter->nr == curr_client->adapter->nr) { if (vpfe->current_input >= 1) return -1; *app_input_index = j + vpfe->current_input; -- GitLab From e4bccada44c177cde31b9a236b7dfd7f76d403ed Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 15 Mar 2016 04:04:12 -0300 Subject: [PATCH 2540/9938] [media] am437x-vpfe: fix an uninitialized variable bug If we are doing V4L2_FIELD_NONE then "ret" is used uninitialized. Fixes: 417d2e507edc ('[media] media: platform: add VPFE capture driver support for AM437X') Signed-off-by: Dan Carpenter Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index e6a7bff4650c..e749eb7c3be9 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1047,7 +1047,7 @@ static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe, static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe) { enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED; - int ret; + int ret = 0; vpfe_dbg(2, vpfe, "vpfe_config_ccdc_image_format\n"); -- GitLab From 60587bd0680507f48ae3a7360983228fd207de8a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 15 Mar 2016 04:05:20 -0300 Subject: [PATCH 2541/9938] [media] cx23885: uninitialized variable in cx23885_av_work_handler() The "handled" variable could be uninitialized if the interrupt_service_routine() call back hasn't been implimented or if it has been implemented but doesn't initialize "handled" to zero at the start. For example, adv76xx_isr() only sets "handled" to true. Fixes: 44b153ca639f ('[media] m5mols: Add ISO sensitivity controls') Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-av.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c index 877dad89107e..e7d4406f9abd 100644 --- a/drivers/media/pci/cx23885/cx23885-av.c +++ b/drivers/media/pci/cx23885/cx23885-av.c @@ -24,7 +24,7 @@ void cx23885_av_work_handler(struct work_struct *work) { struct cx23885_dev *dev = container_of(work, struct cx23885_dev, cx25840_work); - bool handled; + bool handled = false; v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine, PCI_MSK_AV_CORE, &handled); -- GitLab From cc7666a3948c6a554fa4c39b4fb4ccbdbdce1343 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 15 Mar 2016 04:07:10 -0300 Subject: [PATCH 2542/9938] [media] m5mols: potential uninitialized variable Smatch complains that there are some paths where "status" isn't initialized. The code does assume that m5mols_read_u8() can fail so it seems as if Smatch is correct. Let's initialize it to REG_ISO_AUTO which is zero. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/m5mols/m5mols_controls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c index a60931e66312..c2218c0a9e6f 100644 --- a/drivers/media/i2c/m5mols/m5mols_controls.c +++ b/drivers/media/i2c/m5mols/m5mols_controls.c @@ -405,7 +405,7 @@ static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl) struct v4l2_subdev *sd = to_sd(ctrl); struct m5mols_info *info = to_m5mols(sd); int ret = 0; - u8 status; + u8 status = REG_ISO_AUTO; v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n", __func__, ctrl->name, info->isp_ready); -- GitLab From 20674818c4a32ad1bfb1ea798e8c1fbed338ad71 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 6 Apr 2016 00:26:56 -0300 Subject: [PATCH 2543/9938] [media] au0828: remove unused macro An V4L2_CID_PRIVATE_SHARPNESS macro is defined in the au0828 driver, but never used. Remove it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 87f32846f1c0..dd7b378fe070 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -55,7 +55,6 @@ #define NTSC_STD_H 480 #define AU0828_INTERLACED_DEFAULT 1 -#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) /* Defination for AU0828 USB transfer */ #define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ -- GitLab From f343f8484aa9a925b9536b676633af1b9604553e Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 7 Mar 2016 22:03:55 -0300 Subject: [PATCH 2544/9938] [media] rcar_vin: Use ARCH_RENESAS Make use of ARCH_RENESAS in place of ARCH_SHMOBILE. This is part of an ongoing process to migrate from ARCH_SHMOBILE to ARCH_RENESAS the motivation for which being that RENESAS seems to be a more appropriate name than SHMOBILE for the majority of Renesas ARM based SoCs. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index 355298989dd8..08db3b040bbe 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -28,7 +28,7 @@ config VIDEO_PXA27x config VIDEO_RCAR_VIN tristate "R-Car Video Input (VIN) support" depends on VIDEO_DEV && SOC_CAMERA - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG select SOC_CAMERA_SCALE_CROP -- GitLab From 345900be580b52d6993d262ca7052cf9d449ba6c Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 7 Mar 2016 22:03:58 -0300 Subject: [PATCH 2545/9938] [media] sh_mobile_ceu_camera: Remove dependency on SUPERH A dependency on ARCH_SHMOBILE seems to be the best option for sh_mobile_ceu_camera: * For Super H based SoCs: sh_mobile_ceu is used on SH_AP325RXA, SH_ECOVEC, SH_KFR2R09, SH_MIGOR, and SH_7724_SOLUTION_ENGINE which depend on CPU_SUBTYPE_SH7722, CPU_SUBTYPE_SH7723, or CPU_SUBTYPE_SH7724 which all select ARCH_SHMOBILE. * For ARM Based SoCs: Since the removal of legacy (non-multiplatform) support this driver has not been used by any Renesas ARM based SoCs. The Renesas ARM based SoCs currently select ARCH_SHMOBILE, however, it is planned that this will no longer be the case. This is part of an ongoing process to migrate from ARCH_SHMOBILE to ARCH_RENESAS the motivation for which being that RENESAS seems to be a more appropriate name than SHMOBILE for the majority of Renesas ARM based SoCs. Thanks to Geert Uytterhoeven for analysis and portions of the change log text. Cc: Geert Uytterhoeven Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index 08db3b040bbe..83029a4854ae 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -45,7 +45,7 @@ config VIDEO_SH_MOBILE_CSI2 config VIDEO_SH_MOBILE_CEU tristate "SuperH Mobile CEU Interface driver" depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK - depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST + depends on ARCH_SHMOBILE || COMPILE_TEST depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG select SOC_CAMERA_SCALE_CROP -- GitLab From bd546882ff3476718d6df872c1c95aedcc5ed37d Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 14 Mar 2016 21:40:26 -0300 Subject: [PATCH 2546/9938] [media] soc_camera: rcar_vin: add R-Car Gen 2 and 3 fallback compatibility strings Add fallback compatibility string for R-Car Gen 1 and 2. In the case of Renesas R-Car hardware we know that there are generations of SoCs, e.g. Gen 2 and 3. But beyond that it's unclear what the relationship between IP blocks might be. For example, I believe that r8a7790 is older than r8a7791 but that doesn't imply that the latter is a descendant of the former or vice versa. We can, however, by examining the documentation and behaviour of the hardware at run-time observe that the current driver implementation appears to be compatible with the IP blocks on SoCs within a given generation. For the above reasons and convenience when enabling new SoCs a per-generation fallback compatibility string scheme being adopted for drivers for Renesas SoCs. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 11 +++++++++-- drivers/media/platform/soc_camera/rcar_vin.c | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 619193ccf7ff..4266123888ed 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -5,7 +5,7 @@ The rcar_vin device provides video input capabilities for the Renesas R-Car family of devices. The current blocks are always slaves and suppot one input channel which can be either RGB, YUYV or BT656. - - compatible: Must be one of the following + - compatible: Must be one or more of the following - "renesas,vin-r8a7795" for the R8A7795 device - "renesas,vin-r8a7794" for the R8A7794 device - "renesas,vin-r8a7793" for the R8A7793 device @@ -13,6 +13,13 @@ channel which can be either RGB, YUYV or BT656. - "renesas,vin-r8a7790" for the R8A7790 device - "renesas,vin-r8a7779" for the R8A7779 device - "renesas,vin-r8a7778" for the R8A7778 device + - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 compatible device. + - "renesas,rcar-gen3-vin" for a generic R-Car Gen3 compatible device. + + When compatible with the generic version nodes must list the + SoC-specific version corresponding to the platform first + followed by the generic version. + - reg: the register base and size for the device registers - interrupts: the interrupt for the device - clocks: Reference to the parent clock @@ -37,7 +44,7 @@ Device node example }; vin0: vin@0xe6ef0000 { - compatible = "renesas,vin-r8a7790"; + compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin"; clocks = <&mstp8_clks R8A7790_CLK_VIN0>; reg = <0 0xe6ef0000 0 0x1000>; interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>; diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index 3b8edf458964..3f9c1b8456c3 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -1845,6 +1845,8 @@ static const struct of_device_id rcar_vin_of_table[] = { { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 }, { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 }, + { .compatible = "renesas,rcar-gen3-vin", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,rcar-gen2-vin", .data = (void *)RCAR_GEN2 }, { }, }; MODULE_DEVICE_TABLE(of, rcar_vin_of_table); -- GitLab From 1d260123cb5c88574de9b5147eddc243f83b77a8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 14 Mar 2016 21:40:27 -0300 Subject: [PATCH 2547/9938] [media] soc_camera: rcar_vin: add device tree support for r8a7792 Simply document new compatibility string. As a previous patch adds a generic R-Car Gen2 compatibility string there appears to be no need for a driver updates. By documenting this compat string it may be used in DTSs shipped, for example as part of ROMs. It must be used in conjunction with the Gen2 fallback compat string. At this time there are no known differences between the r8a7792 IP block and that implemented by the driver for the Gen2 fallback compat string. Thus there is no need to update the driver as the use of the Gen2 fallback compat string will activate the correct code in the current driver while leaving the option for r8a7792-specific driver code to be activated in an updated driver should the need arise. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 4266123888ed..6a4e61cbe011 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -9,6 +9,7 @@ channel which can be either RGB, YUYV or BT656. - "renesas,vin-r8a7795" for the R8A7795 device - "renesas,vin-r8a7794" for the R8A7794 device - "renesas,vin-r8a7793" for the R8A7793 device + - "renesas,vin-r8a7792" for the R8A7792 device - "renesas,vin-r8a7791" for the R8A7791 device - "renesas,vin-r8a7790" for the R8A7790 device - "renesas,vin-r8a7779" for the R8A7779 device -- GitLab From b76a2a8cb6f6d9da711305d805156b40c698e94f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 29 Feb 2016 08:45:44 -0300 Subject: [PATCH 2548/9938] [media] media: Add obj_type field to struct media_entity Code that processes media entities can require knowledge of the structure type that embeds a particular media entity instance in order to cast the entity to the proper object type. This needs is shown by the presence of the is_media_entity_v4l2_io and is_media_entity_v4l2_subdev functions. The implementation of those two functions relies on the entity function field, which is both a wrong and an inefficient design, without even mentioning the maintenance issue involved in updating the functions every time a new entity function is added. Fix this by adding add an obj_type field to the media entity structure to carry the information. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 1 + drivers/media/v4l2-core/v4l2-subdev.c | 1 + include/media/media-entity.h | 76 ++++++++++++++------------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index d8e5994cccf1..70b559d7ca80 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -735,6 +735,7 @@ static int video_register_media_controller(struct video_device *vdev, int type) if (!vdev->v4l2_dev->mdev) return 0; + vdev->entity.obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE; vdev->entity.function = MEDIA_ENT_F_UNKNOWN; switch (type) { diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index d63083803144..0fa60801a428 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -584,6 +584,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) sd->host_priv = NULL; #if defined(CONFIG_MEDIA_CONTROLLER) sd->entity.name = sd->name; + sd->entity.obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV; sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; #endif } diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 6dc9e4e8cbd4..1986340a8cf2 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -187,11 +187,39 @@ struct media_entity_operations { int (*link_validate)(struct media_link *link); }; +/** + * enum media_entity_type - Media entity type + * + * @MEDIA_ENTITY_TYPE_BASE: + * The entity isn't embedded in another subsystem structure. + * @MEDIA_ENTITY_TYPE_VIDEO_DEVICE: + * The entity is embedded in a struct video_device instance. + * @MEDIA_ENTITY_TYPE_V4L2_SUBDEV: + * The entity is embedded in a struct v4l2_subdev instance. + * + * Media entity objects are often not instantiated directly, but the media + * entity structure is inherited by (through embedding) other subsystem-specific + * structures. The media entity type identifies the type of the subclass + * structure that implements a media entity instance. + * + * This allows runtime type identification of media entities and safe casting to + * the correct object type. For instance, a media entity structure instance + * embedded in a v4l2_subdev structure instance will have the type + * MEDIA_ENTITY_TYPE_V4L2_SUBDEV and can safely be cast to a v4l2_subdev + * structure using the container_of() macro. + */ +enum media_entity_type { + MEDIA_ENTITY_TYPE_BASE, + MEDIA_ENTITY_TYPE_VIDEO_DEVICE, + MEDIA_ENTITY_TYPE_V4L2_SUBDEV, +}; + /** * struct media_entity - A media entity graph object. * * @graph_obj: Embedded structure containing the media object common data. * @name: Entity name. + * @obj_type: Type of the object that implements the media_entity. * @function: Entity main function, as defined in uapi/media.h * (MEDIA_ENT_F_*) * @flags: Entity flags, as defined in uapi/media.h (MEDIA_ENT_FL_*) @@ -220,6 +248,7 @@ struct media_entity_operations { struct media_entity { struct media_gobj graph_obj; /* must be first field in struct */ const char *name; + enum media_entity_type obj_type; u32 function; unsigned long flags; @@ -329,56 +358,29 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u64 local_id) } /** - * is_media_entity_v4l2_io() - identify if the entity main function - * is a V4L2 I/O - * + * is_media_entity_v4l2_io() - Check if the entity is a video_device * @entity: pointer to entity * - * Return: true if the entity main function is one of the V4L2 I/O types - * (video, VBI or SDR radio); false otherwise. + * Return: true if the entity is an instance of a video_device object and can + * safely be cast to a struct video_device using the container_of() macro, or + * false otherwise. */ static inline bool is_media_entity_v4l2_io(struct media_entity *entity) { - if (!entity) - return false; - - switch (entity->function) { - case MEDIA_ENT_F_IO_V4L: - case MEDIA_ENT_F_IO_VBI: - case MEDIA_ENT_F_IO_SWRADIO: - return true; - default: - return false; - } + return entity && entity->obj_type == MEDIA_ENTITY_TYPE_VIDEO_DEVICE; } /** - * is_media_entity_v4l2_subdev - return true if the entity main function is - * associated with the V4L2 API subdev usage - * + * is_media_entity_v4l2_subdev() - Check if the entity is a v4l2_subdev * @entity: pointer to entity * - * This is an ancillary function used by subdev-based V4L2 drivers. - * It checks if the entity function is one of functions used by a V4L2 subdev, - * e. g. camera-relatef functions, analog TV decoder, TV tuner, V4L2 DSPs. + * Return: true if the entity is an instance of a v4l2_subdev object and can + * safely be cast to a struct v4l2_subdev using the container_of() macro, or + * false otherwise. */ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) { - if (!entity) - return false; - - switch (entity->function) { - case MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN: - case MEDIA_ENT_F_CAM_SENSOR: - case MEDIA_ENT_F_FLASH: - case MEDIA_ENT_F_LENS: - case MEDIA_ENT_F_ATV_DECODER: - case MEDIA_ENT_F_TUNER: - return true; - - default: - return false; - } + return entity && entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV; } /** -- GitLab From 45b46879a785678e08953c8f97df945bf634e472 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 29 Feb 2016 08:45:45 -0300 Subject: [PATCH 2549/9938] [media] media: Rename is_media_entity_v4l2_io to is_media_entity_v4l2_video_device All users of is_media_entity_v4l2_io() (the exynos4-is, omap3isp, davince_vpfe and omap4iss drivers and the v4l2-mc power management code) use the function to check whether entities are video_device instances, either to ensure they can cast the entity to a struct video_device, or to count the number of video nodes users. The purpose of the function is thus to identify whether the media entity instance is an instance of the video_device object, not to check whether it can perform I/O. Rename it accordingly, we will introduce a more specific is_media_entity_v4l2_io() check when needed. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 4 ++-- drivers/media/platform/omap3isp/ispvideo.c | 2 +- drivers/media/v4l2-core/v4l2-mc.c | 2 +- drivers/staging/media/davinci_vpfe/vpfe_video.c | 2 +- drivers/staging/media/omap4iss/iss_video.c | 2 +- include/media/media-entity.h | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 48f62dc4453e..04348b502232 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1132,7 +1132,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable, media_entity_graph_walk_start(graph, entity); while ((entity = media_entity_graph_walk_next(graph))) { - if (!is_media_entity_v4l2_io(entity)) + if (!is_media_entity_v4l2_video_device(entity)) continue; ret = __fimc_md_modify_pipeline(entity, enable); @@ -1147,7 +1147,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable, media_entity_graph_walk_start(graph, entity_err); while ((entity_err = media_entity_graph_walk_next(graph))) { - if (!is_media_entity_v4l2_io(entity_err)) + if (!is_media_entity_v4l2_video_device(entity_err)) continue; __fimc_md_modify_pipeline(entity_err, !enable); diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index ac76d2901501..1b1a95d546f6 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -251,7 +251,7 @@ static int isp_video_get_graph_data(struct isp_video *video, if (entity == &video->video.entity) continue; - if (!is_media_entity_v4l2_io(entity)) + if (!is_media_entity_v4l2_video_device(entity)) continue; __video = to_isp_video(media_entity_to_video_device(entity)); diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 2228cd3a846e..ca94bded3386 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -263,7 +263,7 @@ static int pipeline_pm_use_count(struct media_entity *entity, media_entity_graph_walk_start(graph, entity); while ((entity = media_entity_graph_walk_next(graph))) { - if (is_media_entity_v4l2_io(entity)) + if (is_media_entity_v4l2_video_device(entity)) use += entity->use_count; } diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index b793c04028a3..df4f298617c0 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -154,7 +154,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video) while ((entity = media_entity_graph_walk_next(&graph))) { if (entity == &video->video_dev.entity) continue; - if (!is_media_entity_v4l2_io(entity)) + if (!is_media_entity_v4l2_video_device(entity)) continue; far_end = to_vpfe_video(media_entity_to_video_device(entity)); if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index f54349bce4de..cf8da23558bb 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -223,7 +223,7 @@ iss_video_far_end(struct iss_video *video) if (entity == &video->video.entity) continue; - if (!is_media_entity_v4l2_io(entity)) + if (!is_media_entity_v4l2_video_device(entity)) continue; far_end = to_iss_video(media_entity_to_video_device(entity)); diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 1986340a8cf2..e0295eefd702 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -358,14 +358,14 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u64 local_id) } /** - * is_media_entity_v4l2_io() - Check if the entity is a video_device + * is_media_entity_v4l2_video_device() - Check if the entity is a video_device * @entity: pointer to entity * * Return: true if the entity is an instance of a video_device object and can * safely be cast to a struct video_device using the container_of() macro, or * false otherwise. */ -static inline bool is_media_entity_v4l2_io(struct media_entity *entity) +static inline bool is_media_entity_v4l2_video_device(struct media_entity *entity) { return entity && entity->obj_type == MEDIA_ENTITY_TYPE_VIDEO_DEVICE; } -- GitLab From e60ba933bc94b778425612c039a16b3acd4bf756 Mon Sep 17 00:00:00 2001 From: Jonas Rabenstein Date: Wed, 6 Apr 2016 10:14:08 +0200 Subject: [PATCH 2550/9938] ARM: OMAP2+: remove redundant multiplatform checks The directory arch/arm/mach-omap2 is only selected for compilation if CONFIG_ARCH_OMAP2PLUS is selected. CONFIG_ARCH_OMAP2PLUS itself is a silent option and all machines selecting this option are multiplatform devices. As a consequence checks for CONFIG_ARCH_MULTIPLATFORM as well as CONFIG_ARCH_OMAP2PLUS within that directory are superfluous and can be removed. Signed-off-by: Jonas Rabenstein Reviewed-by: Lokesh Vutla Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/soc.h | 140 ++++++----------------------------- 2 files changed, 22 insertions(+), 120 deletions(-) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 0ba6a0e6fa19..04e276ce8413 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ +ccflags-y := -I$(srctree)/$(src)/include \ -I$(srctree)/arch/arm/plat-omap/include # Common support diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h index 70df8f6cddcc..8862c095095f 100644 --- a/arch/arm/mach-omap2/soc.h +++ b/arch/arm/mach-omap2/soc.h @@ -39,82 +39,10 @@ #include /* - * Test if multicore OMAP support is needed + * OMAP2+ is always defined as ARCH_MULTIPLATFORM in Kconfig */ #undef MULTI_OMAP2 -#undef OMAP_NAME - -#ifdef CONFIG_ARCH_MULTIPLATFORM #define MULTI_OMAP2 -#endif -#ifdef CONFIG_SOC_OMAP2420 -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME omap2420 -# endif -#endif -#ifdef CONFIG_SOC_OMAP2430 -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME omap2430 -# endif -#endif -#ifdef CONFIG_ARCH_OMAP3 -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME omap3 -# endif -#endif -#ifdef CONFIG_ARCH_OMAP4 -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME omap4 -# endif -#endif - -#ifdef CONFIG_SOC_OMAP5 -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME omap5 -# endif -#endif - -#ifdef CONFIG_SOC_AM33XX -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME am33xx -# endif -#endif - -#ifdef CONFIG_SOC_AM43XX -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME am43xx -# endif -#endif - -#ifdef CONFIG_SOC_DRA7XX -# ifdef OMAP_NAME -# undef MULTI_OMAP2 -# define MULTI_OMAP2 -# else -# define OMAP_NAME DRA7XX -# endif -#endif /* * Omap device type i.e. EMU/HS/TST/GP/BAD @@ -242,11 +170,6 @@ IS_AM_SUBCLASS(437x, 0x437) IS_DRA_SUBCLASS(75x, 0x75) IS_DRA_SUBCLASS(72x, 0x72) -#define soc_is_omap24xx() 0 -#define soc_is_omap242x() 0 -#define soc_is_omap243x() 0 -#define soc_is_omap34xx() 0 -#define soc_is_omap343x() 0 #define soc_is_ti81xx() 0 #define soc_is_ti816x() 0 #define soc_is_ti814x() 0 @@ -265,46 +188,27 @@ IS_DRA_SUBCLASS(72x, 0x72) #define soc_is_dra74x() 0 #define soc_is_dra72x() 0 -#if defined(MULTI_OMAP2) -# if defined(CONFIG_ARCH_OMAP2) -# undef soc_is_omap24xx -# define soc_is_omap24xx() is_omap24xx() -# endif -# if defined (CONFIG_SOC_OMAP2420) -# undef soc_is_omap242x -# define soc_is_omap242x() is_omap242x() -# endif -# if defined (CONFIG_SOC_OMAP2430) -# undef soc_is_omap243x -# define soc_is_omap243x() is_omap243x() -# endif -# if defined(CONFIG_ARCH_OMAP3) -# undef soc_is_omap34xx -# undef soc_is_omap343x -# define soc_is_omap34xx() is_omap34xx() -# define soc_is_omap343x() is_omap343x() -# endif +#if defined(CONFIG_ARCH_OMAP2) +# define soc_is_omap24xx() is_omap24xx() #else -# if defined(CONFIG_ARCH_OMAP2) -# undef soc_is_omap24xx -# define soc_is_omap24xx() 1 -# endif -# if defined(CONFIG_SOC_OMAP2420) -# undef soc_is_omap242x -# define soc_is_omap242x() 1 -# endif -# if defined(CONFIG_SOC_OMAP2430) -# undef soc_is_omap243x -# define soc_is_omap243x() 1 -# endif -# if defined(CONFIG_ARCH_OMAP3) -# undef soc_is_omap34xx -# define soc_is_omap34xx() 1 -# endif -# if defined(CONFIG_SOC_OMAP3430) -# undef soc_is_omap343x -# define soc_is_omap343x() 1 -# endif +# define soc_is_omap24xx() 0 +#endif +#if defined(CONFIG_SOC_OMAP2420) +# define soc_is_omap242x() is_omap242x() +#else +# define soc_is_omap242x() 0 +#endif +#if defined(CONFIG_SOC_OMAP2430) +# define soc_is_omap243x() is_omap243x() +#else +# define soc_is_omap243x() 0 +#endif +#if defined(CONFIG_ARCH_OMAP3) +# define soc_is_omap34xx() is_omap34xx() +# define soc_is_omap343x() is_omap343x() +#else +# define soc_is_omap34xx() 0 +# define soc_is_omap343x() 0 #endif /* @@ -339,7 +243,6 @@ IS_OMAP_TYPE(3430, 0x3430) #define soc_is_omap5430() 0 /* These are needed for the common code */ -#ifdef CONFIG_ARCH_OMAP2PLUS #define soc_is_omap7xx() 0 #define soc_is_omap15xx() 0 #define soc_is_omap16xx() 0 @@ -350,7 +253,6 @@ IS_OMAP_TYPE(3430, 0x3430) #define soc_is_omap1710() 0 #define cpu_class_is_omap1() 0 #define cpu_class_is_omap2() 1 -#endif #if defined(CONFIG_ARCH_OMAP2) # undef soc_is_omap2420 -- GitLab From 9b02cbb3ede89b5cd84bbe4ef493bd130d76b070 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 24 Apr 2015 20:06:31 -0300 Subject: [PATCH 2551/9938] [media] v4l: subdev: Add pad config allocator and init Add a new subdev operation to initialize a subdev pad config array, and a helper function to allocate and initialize the array. This can be used by bridge drivers to implement try format based on subdev pad operations. Signed-off-by: Laurent Pinchart Acked-by: Vaibhav Hiremath Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-subdev.c | 39 ++++++++++++++++++++++++--- include/media/v4l2-subdev.h | 8 ++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 0fa60801a428..224ea6028b55 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -35,9 +35,11 @@ static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) { #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - fh->pad = kzalloc(sizeof(*fh->pad) * sd->entity.num_pads, GFP_KERNEL); - if (fh->pad == NULL) - return -ENOMEM; + if (sd->entity.num_pads) { + fh->pad = v4l2_subdev_alloc_pad_config(sd); + if (fh->pad == NULL) + return -ENOMEM; + } #endif return 0; } @@ -45,7 +47,7 @@ static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) static void subdev_fh_free(struct v4l2_subdev_fh *fh) { #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - kfree(fh->pad); + v4l2_subdev_free_pad_config(fh->pad); fh->pad = NULL; #endif } @@ -569,6 +571,35 @@ int v4l2_subdev_link_validate(struct media_link *link) sink, link, &source_fmt, &sink_fmt); } EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate); + +struct v4l2_subdev_pad_config * +v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd) +{ + struct v4l2_subdev_pad_config *cfg; + int ret; + + if (!sd->entity.num_pads) + return NULL; + + cfg = kcalloc(sd->entity.num_pads, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return NULL; + + ret = v4l2_subdev_call(sd, pad, init_cfg, cfg); + if (ret < 0 && ret != -ENOIOCTLCMD) { + kfree(cfg); + return NULL; + } + + return cfg; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config); + +void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg) +{ + kfree(cfg); +} +EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config); #endif /* CONFIG_MEDIA_CONTROLLER */ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 11e2dfec0198..32fc7a4beb5e 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -572,6 +572,7 @@ struct v4l2_subdev_pad_config { /** * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations * + * @init_cfg: initialize the pad config to default values * @enum_mbus_code: callback for VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl handler * code. * @enum_frame_size: callback for VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl handler @@ -607,6 +608,8 @@ struct v4l2_subdev_pad_config { * may be adjusted by the subdev driver to device capabilities. */ struct v4l2_subdev_pad_ops { + int (*init_cfg)(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg); int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code); @@ -801,7 +804,12 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt); int v4l2_subdev_link_validate(struct media_link *link); + +struct v4l2_subdev_pad_config * +v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd); +void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg); #endif /* CONFIG_MEDIA_CONTROLLER */ + void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops); -- GitLab From fa369c9366c1c695a02ccd88abd76d7f68162810 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 19 Feb 2016 23:12:26 -0200 Subject: [PATCH 2552/9938] [media] v4l: vsp1: Fix vsp1_du_atomic_(begin|flush) declarations The functions are void, make the declaration match the definition. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- include/media/vsp1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/media/vsp1.h b/include/media/vsp1.h index cc541753896f..d01f7cb8f691 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -23,11 +23,11 @@ int vsp1_du_init(struct device *dev); int vsp1_du_setup_lif(struct device *dev, unsigned int width, unsigned int height); -int vsp1_du_atomic_begin(struct device *dev); +void vsp1_du_atomic_begin(struct device *dev); int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat, unsigned int pitch, dma_addr_t mem[2], const struct v4l2_rect *src, const struct v4l2_rect *dst); -int vsp1_du_atomic_flush(struct device *dev); +void vsp1_du_atomic_flush(struct device *dev); #endif /* __MEDIA_VSP1_H__ */ -- GitLab From c1741af7d1d0f2f9d748939678c4d4cc33783069 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 19 Feb 2016 23:13:45 -0200 Subject: [PATCH 2553/9938] [media] v4l: vsp1: drm: Include correct header file The VSP1 DRM API is declared in , not . Fix it. This also reverts commit 18922936dc28 ("[media] vsp1_drm.h: add missing prototypes") that added the same declarations in a different header file. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 2 +- drivers/media/platform/vsp1/vsp1_drm.h | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 021fe5778cd1..8cf7c19f4344 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -13,10 +13,10 @@ #include #include -#include #include #include +#include #include "vsp1.h" #include "vsp1_bru.h" diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index f68056838319..7704038c3add 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -35,15 +35,4 @@ int vsp1_drm_init(struct vsp1_device *vsp1); void vsp1_drm_cleanup(struct vsp1_device *vsp1); int vsp1_drm_create_links(struct vsp1_device *vsp1); -int vsp1_du_init(struct device *dev); -int vsp1_du_setup_lif(struct device *dev, unsigned int width, - unsigned int height); -void vsp1_du_atomic_begin(struct device *dev); -int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, - u32 pixelformat, unsigned int pitch, - dma_addr_t mem[2], const struct v4l2_rect *src, - const struct v4l2_rect *dst); -void vsp1_du_atomic_flush(struct device *dev); - - #endif /* __VSP1_DRM_H__ */ -- GitLab From 6b1446bc7c89025e07037f9c238a60b6fbe3c207 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 28 Feb 2016 23:28:38 -0300 Subject: [PATCH 2554/9938] [media] v4l: vsp1: video: Fix coding style Commit 54b5a749b4f3 ("[media] v4l: vsp1: Use media entity enumeration interface") wasn't aligned with the driver coding style. Fix it by renaming the rval variable to ret. Furthermore shorten lines by accessing the media_device instance in a more straightforward fashion. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 72cc7d3729f8..b97bbdb1a256 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -175,31 +175,30 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, struct vsp1_rwpf *input, struct vsp1_rwpf *output) { - struct vsp1_entity *entity; struct media_entity_enum ent_enum; + struct vsp1_entity *entity; struct media_pad *pad; - int rval; bool bru_found = false; + int ret; input->location.left = 0; input->location.top = 0; - rval = media_entity_enum_init( - &ent_enum, input->entity.pads[RWPF_PAD_SOURCE].graph_obj.mdev); - if (rval) - return rval; + ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev); + if (ret < 0) + return ret; pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); while (1) { if (pad == NULL) { - rval = -EPIPE; + ret = -EPIPE; goto out; } /* We've reached a video node, that shouldn't have happened. */ if (!is_media_entity_v4l2_subdev(pad->entity)) { - rval = -EPIPE; + ret = -EPIPE; goto out; } @@ -229,14 +228,14 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, /* Ensure the branch has no loop. */ if (media_entity_enum_test_and_set(&ent_enum, &entity->subdev.entity)) { - rval = -EPIPE; + ret = -EPIPE; goto out; } /* UDS can't be chained. */ if (entity->type == VSP1_ENTITY_UDS) { if (pipe->uds) { - rval = -EPIPE; + ret = -EPIPE; goto out; } @@ -256,12 +255,12 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, /* The last entity must be the output WPF. */ if (entity != &output->entity) - rval = -EPIPE; + ret = -EPIPE; out: media_entity_enum_cleanup(&ent_enum); - return rval; + return ret; } static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, -- GitLab From 94d48e56d388f60d045f41749f89ba385f107d69 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 11 Feb 2016 19:32:00 -0200 Subject: [PATCH 2555/9938] [media] v4l: vsp1: VSPD instances have no LUT on Gen3 Remove the HAS_LUT flag in the corresponding device information entry. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 25750a0e4631..da43e3f35610 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -623,7 +623,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPD_GEN3, - .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT, + .features = VSP1_HAS_BRU | VSP1_HAS_LIF, .rpf_count = 5, .wpf_count = 2, .num_bru_inputs = 5, -- GitLab From aa380ea0c54e491f7f31e8180514766dd3e6cd91 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 10:46:25 -0200 Subject: [PATCH 2556/9938] [media] v4l: vsp1: Use pipeline display list to decide how to write to modules This allows getting rid of the vsp1_device::use_dl field. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 12 ------------ drivers/media/platform/vsp1/vsp1_dl.c | 5 +---- drivers/media/platform/vsp1/vsp1_dl.h | 12 ++---------- drivers/media/platform/vsp1/vsp1_drv.c | 9 +++------ drivers/media/platform/vsp1/vsp1_entity.c | 12 ++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 2 ++ 6 files changed, 20 insertions(+), 32 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 910d6b8e8b50..bea232820ead 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -85,8 +85,6 @@ struct vsp1_device { struct media_entity_operations media_ops; struct vsp1_drm *drm; - - bool use_dl; }; int vsp1_device_get(struct vsp1_device *vsp1); @@ -104,14 +102,4 @@ static inline void vsp1_write(struct vsp1_device *vsp1, u32 reg, u32 data) iowrite32(data, vsp1->mmio + reg); } -#include "vsp1_dl.h" - -static inline void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data) -{ - if (e->vsp1->use_dl) - vsp1_dl_add(e, reg, data); - else - vsp1_write(e->vsp1, reg, data); -} - #endif /* __VSP1_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 1a9a58588f84..5518a81f5792 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -18,7 +18,6 @@ #include "vsp1.h" #include "vsp1_dl.h" -#include "vsp1_pipe.h" /* * Global resources @@ -129,10 +128,8 @@ void vsp1_dl_begin(struct vsp1_dl *dl) list->reg_count = 0; } -void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data) +void vsp1_dl_add(struct vsp1_dl *dl, u32 reg, u32 data) { - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity); - struct vsp1_dl *dl = pipe->dl; struct vsp1_dl_list *list = dl->lists.write; list->body[list->reg_count].addr = reg; diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 448c4250e54c..f4116ca59c28 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -13,7 +13,7 @@ #ifndef __VSP1_DL_H__ #define __VSP1_DL_H__ -#include "vsp1_entity.h" +#include struct vsp1_device; struct vsp1_dl; @@ -25,18 +25,10 @@ void vsp1_dl_setup(struct vsp1_device *vsp1); void vsp1_dl_reset(struct vsp1_dl *dl); void vsp1_dl_begin(struct vsp1_dl *dl); -void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data); +void vsp1_dl_add(struct vsp1_dl *dl, u32 reg, u32 data); void vsp1_dl_commit(struct vsp1_dl *dl); void vsp1_dl_irq_display_start(struct vsp1_dl *dl); void vsp1_dl_irq_frame_end(struct vsp1_dl *dl); -static inline void vsp1_dl_mod_write(struct vsp1_entity *e, u32 reg, u32 data) -{ - if (e->vsp1->use_dl) - vsp1_dl_add(e, reg, data); - else - vsp1_write(e->vsp1, reg, data); -} - #endif /* __VSP1_DL_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index da43e3f35610..58632d766a2a 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -387,13 +387,10 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) /* Register subdev nodes if the userspace API is enabled or initialize * the DRM pipeline otherwise. */ - if (vsp1->info->uapi) { - vsp1->use_dl = false; + if (vsp1->info->uapi) ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); - } else { - vsp1->use_dl = true; + else ret = vsp1_drm_init(vsp1); - } if (ret < 0) goto done; @@ -465,7 +462,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1) vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); - if (vsp1->use_dl) + if (!vsp1->info->uapi) vsp1_dl_setup(vsp1); return 0; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 20a78fbd3691..4006f0d28bac 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -19,7 +19,19 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_entity.h" +#include "vsp1_pipe.h" + +void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data) +{ + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity); + + if (pipe->dl) + vsp1_dl_add(pipe->dl, reg, data); + else + vsp1_write(e->vsp1, reg, data); +} bool vsp1_entity_is_streaming(struct vsp1_entity *entity) { diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 83570dfde8ec..311d5b64c9a5 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -103,4 +103,6 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); void vsp1_entity_route_setup(struct vsp1_entity *source); +void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data); + #endif /* __VSP1_ENTITY_H__ */ -- GitLab From 7939fef4d3911695c78cb067f1e4c16056a9f113 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 10:53:22 -0200 Subject: [PATCH 2557/9938] [media] v4l: vsp1: Always setup the display list Make sure display list usage is correctly disabled by always setting up the corresponding registers, including when the display list feature isn't used. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 7 +++---- drivers/media/platform/vsp1/vsp1_drv.c | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 5518a81f5792..9587c37743b0 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -243,15 +243,14 @@ void vsp1_dl_irq_frame_end(struct vsp1_dl *dl) void vsp1_dl_setup(struct vsp1_device *vsp1) { - u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT) - | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0 - | VI6_DL_CTRL_DLE; + u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT); /* The DRM pipeline operates with header-less display lists in * Continuous Frame Mode. */ if (vsp1->drm) - ctrl |= VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0; + ctrl |= VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0 + | VI6_DL_CTRL_DLE | VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0; vsp1_write(vsp1, VI6_DL_CTRL, ctrl); vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS); diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 58632d766a2a..d657949bac3b 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -462,8 +462,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1) vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); - if (!vsp1->info->uapi) - vsp1_dl_setup(vsp1); + vsp1_dl_setup(vsp1); return 0; } -- GitLab From f9df34f8cd0da731f65728480fe2e669391adbd0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 14 Nov 2015 16:33:40 -0200 Subject: [PATCH 2558/9938] [media] v4l: vsp1: Simplify frame end processing The DRM pipeline, as it runs in automatic restart mode, never sees the pipeline state set to VSP1_PIPELINE_STOPPING or VSP1_PIPELINE_STOPPED when running the frame end interrupt handler. We can thus skip the checks various checks in the handler and return immediately. Similarly the DRM frame end handler calls vsp1_pipeline_run() unnecessarily, as the state there is never VSP1_PIPELINE_STOPPED. Remove the function call and the frame end handler is it's now empty. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 15 --------------- drivers/media/platform/vsp1/vsp1_pipe.c | 9 ++++++--- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 8cf7c19f4344..9ecba4c1332e 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -26,20 +26,6 @@ #include "vsp1_pipe.h" #include "vsp1_rwpf.h" -/* ----------------------------------------------------------------------------- - * Runtime Handling - */ - -static void vsp1_drm_pipeline_frame_end(struct vsp1_pipeline *pipe) -{ - unsigned long flags; - - spin_lock_irqsave(&pipe->irqlock, flags); - if (pipe->num_inputs) - vsp1_pipeline_run(pipe); - spin_unlock_irqrestore(&pipe->irqlock, flags); -} - /* ----------------------------------------------------------------------------- * DU Driver API */ @@ -569,7 +555,6 @@ int vsp1_drm_init(struct vsp1_device *vsp1) pipe = &vsp1->drm->pipe; vsp1_pipeline_init(pipe); - pipe->frame_end = vsp1_drm_pipeline_frame_end; /* The DRM pipeline is static, add entities manually. */ for (i = 0; i < vsp1->info->rpf_count; ++i) { diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 6659f06b1643..78096122a22d 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -289,7 +289,8 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) vsp1_dl_irq_frame_end(pipe->dl); /* Signal frame end to the pipeline handler. */ - pipe->frame_end(pipe); + if (pipe->frame_end) + pipe->frame_end(pipe); spin_lock_irqsave(&pipe->irqlock, flags); @@ -298,8 +299,10 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) /* When using display lists in continuous frame mode the pipeline is * automatically restarted by the hardware. */ - if (!pipe->dl) - pipe->state = VSP1_PIPELINE_STOPPED; + if (pipe->dl) + goto done; + + pipe->state = VSP1_PIPELINE_STOPPED; /* If a stop has been requested, mark the pipeline as stopped and * return. -- GitLab From c2dd2513ea7aafe5cca2460aecaf83cb46128faf Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 8 Nov 2015 20:06:57 -0200 Subject: [PATCH 2559/9938] [media] v4l: vsp1: Split display list manager from display list This clarifies the API and prepares display list support for being used to implement the request API. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 1 - drivers/media/platform/vsp1/vsp1_dl.c | 263 +++++++++++----------- drivers/media/platform/vsp1/vsp1_dl.h | 40 +++- drivers/media/platform/vsp1/vsp1_drm.c | 32 ++- drivers/media/platform/vsp1/vsp1_drm.h | 12 +- drivers/media/platform/vsp1/vsp1_drv.c | 11 +- drivers/media/platform/vsp1/vsp1_entity.c | 2 +- drivers/media/platform/vsp1/vsp1_pipe.c | 13 +- drivers/media/platform/vsp1/vsp1_pipe.h | 5 +- 9 files changed, 193 insertions(+), 186 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index bea232820ead..dae987a11a70 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -26,7 +26,6 @@ struct clk; struct device; -struct vsp1_dl; struct vsp1_drm; struct vsp1_entity; struct vsp1_platform_data; diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 9587c37743b0..14b2ee3c5fba 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -37,117 +37,108 @@ struct vsp1_dl_entry { } __attribute__((__packed__)); struct vsp1_dl_list { - size_t size; - int reg_count; + struct list_head list; - bool in_use; + struct vsp1_dl_manager *dlm; struct vsp1_dl_entry *body; dma_addr_t dma; -}; - -/** - * struct vsp1_dl - Display List manager - * @vsp1: the VSP1 device - * @lock: protects the active, queued and pending lists - * @lists.all: array of all allocate display lists - * @lists.active: list currently being processed (loaded) by hardware - * @lists.queued: list queued to the hardware (written to the DL registers) - * @lists.pending: list waiting to be queued to the hardware - * @lists.write: list being written to by software - */ -struct vsp1_dl { - struct vsp1_device *vsp1; - - spinlock_t lock; - size_t size; - dma_addr_t dma; - void *mem; - struct { - struct vsp1_dl_list all[VSP1_DL_NUM_LISTS]; - - struct vsp1_dl_list *active; - struct vsp1_dl_list *queued; - struct vsp1_dl_list *pending; - struct vsp1_dl_list *write; - } lists; + int reg_count; }; /* ----------------------------------------------------------------------------- * Display List Transaction Management */ -static void vsp1_dl_free_list(struct vsp1_dl_list *list) +static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) { - if (!list) - return; + struct vsp1_dl_list *dl; - list->in_use = false; -} + dl = kzalloc(sizeof(*dl), GFP_KERNEL); + if (!dl) + return NULL; -void vsp1_dl_reset(struct vsp1_dl *dl) -{ - unsigned int i; + dl->dlm = dlm; + dl->size = VSP1_DL_BODY_SIZE; + + dl->body = dma_alloc_wc(dlm->vsp1->dev, dl->size, &dl->dma, GFP_KERNEL); + if (!dl->body) { + kfree(dl); + return NULL; + } - dl->lists.active = NULL; - dl->lists.queued = NULL; - dl->lists.pending = NULL; - dl->lists.write = NULL; + return dl; +} - for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) - dl->lists.all[i].in_use = false; +static void vsp1_dl_list_free(struct vsp1_dl_list *dl) +{ + dma_free_wc(dl->dlm->vsp1->dev, dl->size, dl->body, dl->dma); + kfree(dl); } -void vsp1_dl_begin(struct vsp1_dl *dl) +/** + * vsp1_dl_list_get - Get a free display list + * @dlm: The display list manager + * + * Get a display list from the pool of free lists and return it. + * + * This function must be called without the display list manager lock held. + */ +struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm) { - struct vsp1_dl_list *list = NULL; + struct vsp1_dl_list *dl = NULL; unsigned long flags; - unsigned int i; - spin_lock_irqsave(&dl->lock, flags); + spin_lock_irqsave(&dlm->lock, flags); - for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) { - if (!dl->lists.all[i].in_use) { - list = &dl->lists.all[i]; - break; - } + if (!list_empty(&dlm->free)) { + dl = list_first_entry(&dlm->free, struct vsp1_dl_list, list); + list_del(&dl->list); } - if (!list) { - list = dl->lists.pending; - dl->lists.pending = NULL; - } + spin_unlock_irqrestore(&dlm->lock, flags); + + return dl; +} - spin_unlock_irqrestore(&dl->lock, flags); +/** + * vsp1_dl_list_put - Release a display list + * @dl: The display list + * + * Release the display list and return it to the pool of free lists. + * + * This function must be called with the display list manager lock held. + * + * Passing a NULL pointer to this function is safe, in that case no operation + * will be performed. + */ +void vsp1_dl_list_put(struct vsp1_dl_list *dl) +{ + if (!dl) + return; - dl->lists.write = list; + dl->reg_count = 0; - list->in_use = true; - list->reg_count = 0; + list_add_tail(&dl->list, &dl->dlm->free); } -void vsp1_dl_add(struct vsp1_dl *dl, u32 reg, u32 data) +void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data) { - struct vsp1_dl_list *list = dl->lists.write; - - list->body[list->reg_count].addr = reg; - list->body[list->reg_count].data = data; - list->reg_count++; + dl->body[dl->reg_count].addr = reg; + dl->body[dl->reg_count].data = data; + dl->reg_count++; } -void vsp1_dl_commit(struct vsp1_dl *dl) +void vsp1_dl_list_commit(struct vsp1_dl_list *dl) { - struct vsp1_device *vsp1 = dl->vsp1; - struct vsp1_dl_list *list; + struct vsp1_dl_manager *dlm = dl->dlm; + struct vsp1_device *vsp1 = dlm->vsp1; unsigned long flags; bool update; - list = dl->lists.write; - dl->lists.write = NULL; - - spin_lock_irqsave(&dl->lock, flags); + spin_lock_irqsave(&dlm->lock, flags); /* Once the UPD bit has been set the hardware can start processing the * display list at any time and we can't touch the address and size @@ -156,8 +147,8 @@ void vsp1_dl_commit(struct vsp1_dl *dl) */ update = !!(vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD); if (update) { - vsp1_dl_free_list(dl->lists.pending); - dl->lists.pending = list; + vsp1_dl_list_put(dlm->pending); + dlm->pending = dl; goto done; } @@ -165,42 +156,44 @@ void vsp1_dl_commit(struct vsp1_dl *dl) * The UPD bit will be cleared by the device when the display list is * processed. */ - vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma); + vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->dma); vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | - (list->reg_count * 8)); + (dl->reg_count * 8)); - vsp1_dl_free_list(dl->lists.queued); - dl->lists.queued = list; + vsp1_dl_list_put(dlm->queued); + dlm->queued = dl; done: - spin_unlock_irqrestore(&dl->lock, flags); + spin_unlock_irqrestore(&dlm->lock, flags); } /* ----------------------------------------------------------------------------- - * Interrupt Handling + * Display List Manager */ -void vsp1_dl_irq_display_start(struct vsp1_dl *dl) +/* Interrupt Handling */ +void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm) { - spin_lock(&dl->lock); + spin_lock(&dlm->lock); /* The display start interrupt signals the end of the display list * processing by the device. The active display list, if any, won't be * accessed anymore and can be reused. */ - if (dl->lists.active) { - vsp1_dl_free_list(dl->lists.active); - dl->lists.active = NULL; - } + vsp1_dl_list_put(dlm->active); + dlm->active = NULL; - spin_unlock(&dl->lock); + spin_unlock(&dlm->lock); } -void vsp1_dl_irq_frame_end(struct vsp1_dl *dl) +void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) { - struct vsp1_device *vsp1 = dl->vsp1; + struct vsp1_device *vsp1 = dlm->vsp1; - spin_lock(&dl->lock); + spin_lock(&dlm->lock); + + vsp1_dl_list_put(dlm->active); + dlm->active = NULL; /* The UPD bit set indicates that the commit operation raced with the * interrupt and occurred after the frame end event and UPD clear but @@ -213,35 +206,31 @@ void vsp1_dl_irq_frame_end(struct vsp1_dl *dl) /* The device starts processing the queued display list right after the * frame end interrupt. The display list thus becomes active. */ - if (dl->lists.queued) { - WARN_ON(dl->lists.active); - dl->lists.active = dl->lists.queued; - dl->lists.queued = NULL; + if (dlm->queued) { + dlm->active = dlm->queued; + dlm->queued = NULL; } /* Now that the UPD bit has been cleared we can queue the next display * list to the hardware if one has been prepared. */ - if (dl->lists.pending) { - struct vsp1_dl_list *list = dl->lists.pending; + if (dlm->pending) { + struct vsp1_dl_list *dl = dlm->pending; - vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma); + vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->dma); vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | - (list->reg_count * 8)); + (dl->reg_count * 8)); - dl->lists.queued = list; - dl->lists.pending = NULL; + dlm->queued = dl; + dlm->pending = NULL; } done: - spin_unlock(&dl->lock); + spin_unlock(&dlm->lock); } -/* ----------------------------------------------------------------------------- - * Hardware Setup - */ - -void vsp1_dl_setup(struct vsp1_device *vsp1) +/* Hardware Setup */ +void vsp1_dlm_setup(struct vsp1_device *vsp1) { u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT); @@ -256,46 +245,46 @@ void vsp1_dl_setup(struct vsp1_device *vsp1) vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS); } -/* ----------------------------------------------------------------------------- - * Initialization and Cleanup - */ +void vsp1_dlm_reset(struct vsp1_dl_manager *dlm) +{ + vsp1_dl_list_put(dlm->active); + vsp1_dl_list_put(dlm->queued); + vsp1_dl_list_put(dlm->pending); + + dlm->active = NULL; + dlm->queued = NULL; + dlm->pending = NULL; +} -struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1) +int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm, + unsigned int prealloc) { - struct vsp1_dl *dl; unsigned int i; - dl = kzalloc(sizeof(*dl), GFP_KERNEL); - if (!dl) - return NULL; - - spin_lock_init(&dl->lock); + dlm->vsp1 = vsp1; - dl->vsp1 = vsp1; - dl->size = VSP1_DL_BODY_SIZE * ARRAY_SIZE(dl->lists.all); + spin_lock_init(&dlm->lock); + INIT_LIST_HEAD(&dlm->free); - dl->mem = dma_alloc_wc(vsp1->dev, dl->size, &dl->dma, - GFP_KERNEL); - if (!dl->mem) { - kfree(dl); - return NULL; - } + for (i = 0; i < prealloc; ++i) { + struct vsp1_dl_list *dl; - for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) { - struct vsp1_dl_list *list = &dl->lists.all[i]; + dl = vsp1_dl_list_alloc(dlm); + if (!dl) + return -ENOMEM; - list->size = VSP1_DL_BODY_SIZE; - list->reg_count = 0; - list->in_use = false; - list->dma = dl->dma + VSP1_DL_BODY_SIZE * i; - list->body = dl->mem + VSP1_DL_BODY_SIZE * i; + list_add_tail(&dl->list, &dlm->free); } - return dl; + return 0; } -void vsp1_dl_destroy(struct vsp1_dl *dl) +void vsp1_dlm_cleanup(struct vsp1_dl_manager *dlm) { - dma_free_wc(dl->vsp1->dev, dl->size, dl->mem, dl->dma); - kfree(dl); + struct vsp1_dl_list *dl, *next; + + list_for_each_entry_safe(dl, next, &dlm->free, list) { + list_del(&dl->list); + vsp1_dl_list_free(dl); + } } diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index f4116ca59c28..caa6a85f6825 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -16,19 +16,39 @@ #include struct vsp1_device; -struct vsp1_dl; +struct vsp1_dl_list; -struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1); -void vsp1_dl_destroy(struct vsp1_dl *dl); +/** + * struct vsp1_dl_manager - Display List manager + * @vsp1: the VSP1 device + * @lock: protects the active, queued and pending lists + * @free: array of all free display lists + * @active: list currently being processed (loaded) by hardware + * @queued: list queued to the hardware (written to the DL registers) + * @pending: list waiting to be queued to the hardware + */ +struct vsp1_dl_manager { + struct vsp1_device *vsp1; + + spinlock_t lock; + struct list_head free; + struct vsp1_dl_list *active; + struct vsp1_dl_list *queued; + struct vsp1_dl_list *pending; +}; -void vsp1_dl_setup(struct vsp1_device *vsp1); +void vsp1_dlm_setup(struct vsp1_device *vsp1); -void vsp1_dl_reset(struct vsp1_dl *dl); -void vsp1_dl_begin(struct vsp1_dl *dl); -void vsp1_dl_add(struct vsp1_dl *dl, u32 reg, u32 data); -void vsp1_dl_commit(struct vsp1_dl *dl); +int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm, + unsigned int prealloc); +void vsp1_dlm_cleanup(struct vsp1_dl_manager *dlm); +void vsp1_dlm_reset(struct vsp1_dl_manager *dlm); +void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm); +void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); -void vsp1_dl_irq_display_start(struct vsp1_dl *dl); -void vsp1_dl_irq_frame_end(struct vsp1_dl *dl); +struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm); +void vsp1_dl_list_put(struct vsp1_dl_list *dl); +void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data); +void vsp1_dl_list_commit(struct vsp1_dl_list *dl); #endif /* __VSP1_DL_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 9ecba4c1332e..a8cd74335f20 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -26,6 +26,18 @@ #include "vsp1_pipe.h" #include "vsp1_rwpf.h" + +/* ----------------------------------------------------------------------------- + * Interrupt Handling + */ + +void vsp1_drm_frame_end(struct vsp1_pipeline *pipe) +{ + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + + vsp1_dlm_irq_frame_end(&vsp1->drm->dlm); +} + /* ----------------------------------------------------------------------------- * DU Driver API */ @@ -89,6 +101,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, pipe->num_inputs = 0; + vsp1_dlm_reset(&vsp1->drm->dlm); vsp1_device_put(vsp1); dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__); @@ -96,8 +109,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, return 0; } - vsp1_dl_reset(vsp1->drm->dl); - /* Configure the format at the BRU sinks and propagate it through the * pipeline. */ @@ -217,7 +228,7 @@ void vsp1_du_atomic_begin(struct device *dev) spin_unlock_irqrestore(&pipe->irqlock, flags); /* Prepare the display list. */ - vsp1_dl_begin(vsp1->drm->dl); + pipe->dl = vsp1_dl_list_get(&vsp1->drm->dlm); } EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); @@ -467,7 +478,8 @@ void vsp1_du_atomic_flush(struct device *dev) } } - vsp1_dl_commit(vsp1->drm->dl); + vsp1_dl_list_commit(pipe->dl); + pipe->dl = NULL; spin_lock_irqsave(&pipe->irqlock, flags); @@ -543,18 +555,20 @@ int vsp1_drm_init(struct vsp1_device *vsp1) { struct vsp1_pipeline *pipe; unsigned int i; + int ret; vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL); if (!vsp1->drm) return -ENOMEM; - vsp1->drm->dl = vsp1_dl_create(vsp1); - if (!vsp1->drm->dl) - return -ENOMEM; + ret = vsp1_dlm_init(vsp1, &vsp1->drm->dlm, 4); + if (ret < 0) + return ret; pipe = &vsp1->drm->pipe; vsp1_pipeline_init(pipe); + pipe->frame_end = vsp1_drm_frame_end; /* The DRM pipeline is static, add entities manually. */ for (i = 0; i < vsp1->info->rpf_count; ++i) { @@ -571,12 +585,10 @@ int vsp1_drm_init(struct vsp1_device *vsp1) pipe->lif = &vsp1->lif->entity; pipe->output = vsp1->wpf[0]; - pipe->dl = vsp1->drm->dl; - return 0; } void vsp1_drm_cleanup(struct vsp1_device *vsp1) { - vsp1_dl_destroy(vsp1->drm->dl); + vsp1_dlm_cleanup(&vsp1->drm->dlm); } diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 7704038c3add..5ef32cff9601 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -13,26 +13,30 @@ #ifndef __VSP1_DRM_H__ #define __VSP1_DRM_H__ +#include "vsp1_dl.h" #include "vsp1_pipe.h" -struct vsp1_dl; - /** * vsp1_drm - State for the API exposed to the DRM driver - * @dl: display list for DRM pipeline operation * @pipe: the VSP1 pipeline used for display * @num_inputs: number of active pipeline inputs at the beginning of an update * @update: the pipeline configuration has been updated + * @dlm: display list manager used for DRM operation */ struct vsp1_drm { - struct vsp1_dl *dl; struct vsp1_pipeline pipe; unsigned int num_inputs; bool update; + struct vsp1_dl_manager dlm; }; int vsp1_drm_init(struct vsp1_device *vsp1); void vsp1_drm_cleanup(struct vsp1_device *vsp1); int vsp1_drm_create_links(struct vsp1_device *vsp1); +static inline void vsp1_drm_display_start(struct vsp1_device *vsp1) +{ + vsp1_dlm_irq_display_start(&vsp1->drm->dlm); +} + #endif /* __VSP1_DRM_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index d657949bac3b..bfdc01c9172d 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -68,14 +68,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) vsp1_write(vsp1, VI6_DISP_IRQ_STA, ~status & VI6_DISP_IRQ_STA_DST); if (status & VI6_DISP_IRQ_STA_DST) { - struct vsp1_rwpf *wpf = vsp1->wpf[0]; - struct vsp1_pipeline *pipe; - - if (wpf) { - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); - vsp1_pipeline_display_start(pipe); - } - + vsp1_drm_display_start(vsp1); ret = IRQ_HANDLED; } @@ -462,7 +455,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1) vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); - vsp1_dl_setup(vsp1); + vsp1_dlm_setup(vsp1); return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 4006f0d28bac..83689588900a 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -28,7 +28,7 @@ void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data) struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity); if (pipe->dl) - vsp1_dl_add(pipe->dl, reg, data); + vsp1_dl_list_write(pipe->dl, reg, data); else vsp1_write(e->vsp1, reg, data); } diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 78096122a22d..cb67b8f80635 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -226,7 +226,7 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) unsigned long flags; int ret; - if (pipe->dl) { + if (pipe->lif) { /* When using display lists in continuous frame mode the only * way to stop the pipeline is to reset the hardware. */ @@ -271,12 +271,6 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) return pipe->buffers_ready == mask; } -void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe) -{ - if (pipe->dl) - vsp1_dl_irq_display_start(pipe->dl); -} - void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) { enum vsp1_pipeline_state state; @@ -285,9 +279,6 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) if (pipe == NULL) return; - if (pipe->dl) - vsp1_dl_irq_frame_end(pipe->dl); - /* Signal frame end to the pipeline handler. */ if (pipe->frame_end) pipe->frame_end(pipe); @@ -299,7 +290,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) /* When using display lists in continuous frame mode the pipeline is * automatically restarted by the hardware. */ - if (pipe->dl) + if (pipe->lif) goto done; pipe->state = VSP1_PIPELINE_STOPPED; diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index b2f3a8a896c9..f4bdfc943add 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -19,7 +19,7 @@ #include -struct vsp1_dl; +struct vsp1_dl_list; struct vsp1_rwpf; /* @@ -100,7 +100,7 @@ struct vsp1_pipeline { struct list_head entities; - struct vsp1_dl *dl; + struct vsp1_dl_list *dl; }; static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) @@ -119,7 +119,6 @@ bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe); int vsp1_pipeline_stop(struct vsp1_pipeline *pipe); bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe); -void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe); void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, -- GitLab From ef9621bcd6640d48834ec9315dae06e9d7cb5283 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 14 Nov 2015 22:27:52 -0200 Subject: [PATCH 2560/9938] [media] v4l: vsp1: Store the display list manager in the WPF Each WPF can process display lists independently, move the manager to the WPF to reflect that and prepare for display list support for non-DRM pipelines. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 37 ++++++++++++++++++++--- drivers/media/platform/vsp1/vsp1_dl.h | 26 +++------------- drivers/media/platform/vsp1/vsp1_drm.c | 19 +++++------- drivers/media/platform/vsp1/vsp1_drm.h | 8 +---- drivers/media/platform/vsp1/vsp1_entity.c | 2 ++ drivers/media/platform/vsp1/vsp1_entity.h | 2 ++ drivers/media/platform/vsp1/vsp1_rwpf.h | 3 ++ drivers/media/platform/vsp1/vsp1_wpf.c | 18 +++++++++++ 8 files changed, 70 insertions(+), 45 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 14b2ee3c5fba..e0f4816925d5 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -48,6 +48,25 @@ struct vsp1_dl_list { int reg_count; }; +/** + * struct vsp1_dl_manager - Display List manager + * @vsp1: the VSP1 device + * @lock: protects the active, queued and pending lists + * @free: array of all free display lists + * @active: list currently being processed (loaded) by hardware + * @queued: list queued to the hardware (written to the DL registers) + * @pending: list waiting to be queued to the hardware + */ +struct vsp1_dl_manager { + struct vsp1_device *vsp1; + + spinlock_t lock; + struct list_head free; + struct vsp1_dl_list *active; + struct vsp1_dl_list *queued; + struct vsp1_dl_list *pending; +}; + /* ----------------------------------------------------------------------------- * Display List Transaction Management */ @@ -256,11 +275,16 @@ void vsp1_dlm_reset(struct vsp1_dl_manager *dlm) dlm->pending = NULL; } -int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm, - unsigned int prealloc) +struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, + unsigned int prealloc) { + struct vsp1_dl_manager *dlm; unsigned int i; + dlm = devm_kzalloc(vsp1->dev, sizeof(*dlm), GFP_KERNEL); + if (!dlm) + return NULL; + dlm->vsp1 = vsp1; spin_lock_init(&dlm->lock); @@ -271,18 +295,21 @@ int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm, dl = vsp1_dl_list_alloc(dlm); if (!dl) - return -ENOMEM; + return NULL; list_add_tail(&dl->list, &dlm->free); } - return 0; + return dlm; } -void vsp1_dlm_cleanup(struct vsp1_dl_manager *dlm) +void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm) { struct vsp1_dl_list *dl, *next; + if (!dlm) + return; + list_for_each_entry_safe(dl, next, &dlm->free, list) { list_del(&dl->list); vsp1_dl_list_free(dl); diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index caa6a85f6825..46f7ae337374 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -17,31 +17,13 @@ struct vsp1_device; struct vsp1_dl_list; - -/** - * struct vsp1_dl_manager - Display List manager - * @vsp1: the VSP1 device - * @lock: protects the active, queued and pending lists - * @free: array of all free display lists - * @active: list currently being processed (loaded) by hardware - * @queued: list queued to the hardware (written to the DL registers) - * @pending: list waiting to be queued to the hardware - */ -struct vsp1_dl_manager { - struct vsp1_device *vsp1; - - spinlock_t lock; - struct list_head free; - struct vsp1_dl_list *active; - struct vsp1_dl_list *queued; - struct vsp1_dl_list *pending; -}; +struct vsp1_dl_manager; void vsp1_dlm_setup(struct vsp1_device *vsp1); -int vsp1_dlm_init(struct vsp1_device *vsp1, struct vsp1_dl_manager *dlm, - unsigned int prealloc); -void vsp1_dlm_cleanup(struct vsp1_dl_manager *dlm); +struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, + unsigned int prealloc); +void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm); void vsp1_dlm_reset(struct vsp1_dl_manager *dlm); void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm); void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index a8cd74335f20..22f67360b750 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -31,11 +31,14 @@ * Interrupt Handling */ -void vsp1_drm_frame_end(struct vsp1_pipeline *pipe) +void vsp1_drm_display_start(struct vsp1_device *vsp1) { - struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm); +} - vsp1_dlm_irq_frame_end(&vsp1->drm->dlm); +void vsp1_drm_frame_end(struct vsp1_pipeline *pipe) +{ + vsp1_dlm_irq_frame_end(pipe->output->dlm); } /* ----------------------------------------------------------------------------- @@ -101,7 +104,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, pipe->num_inputs = 0; - vsp1_dlm_reset(&vsp1->drm->dlm); + vsp1_dlm_reset(pipe->output->dlm); vsp1_device_put(vsp1); dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__); @@ -228,7 +231,7 @@ void vsp1_du_atomic_begin(struct device *dev) spin_unlock_irqrestore(&pipe->irqlock, flags); /* Prepare the display list. */ - pipe->dl = vsp1_dl_list_get(&vsp1->drm->dlm); + pipe->dl = vsp1_dl_list_get(pipe->output->dlm); } EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); @@ -555,16 +558,11 @@ int vsp1_drm_init(struct vsp1_device *vsp1) { struct vsp1_pipeline *pipe; unsigned int i; - int ret; vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL); if (!vsp1->drm) return -ENOMEM; - ret = vsp1_dlm_init(vsp1, &vsp1->drm->dlm, 4); - if (ret < 0) - return ret; - pipe = &vsp1->drm->pipe; vsp1_pipeline_init(pipe); @@ -590,5 +588,4 @@ int vsp1_drm_init(struct vsp1_device *vsp1) void vsp1_drm_cleanup(struct vsp1_device *vsp1) { - vsp1_dlm_cleanup(&vsp1->drm->dlm); } diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 5ef32cff9601..e9242f2c870e 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -13,7 +13,6 @@ #ifndef __VSP1_DRM_H__ #define __VSP1_DRM_H__ -#include "vsp1_dl.h" #include "vsp1_pipe.h" /** @@ -21,22 +20,17 @@ * @pipe: the VSP1 pipeline used for display * @num_inputs: number of active pipeline inputs at the beginning of an update * @update: the pipeline configuration has been updated - * @dlm: display list manager used for DRM operation */ struct vsp1_drm { struct vsp1_pipeline pipe; unsigned int num_inputs; bool update; - struct vsp1_dl_manager dlm; }; int vsp1_drm_init(struct vsp1_device *vsp1); void vsp1_drm_cleanup(struct vsp1_device *vsp1); int vsp1_drm_create_links(struct vsp1_device *vsp1); -static inline void vsp1_drm_display_start(struct vsp1_device *vsp1) -{ - vsp1_dlm_irq_display_start(&vsp1->drm->dlm); -} +void vsp1_drm_display_start(struct vsp1_device *vsp1); #endif /* __VSP1_DRM_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 83689588900a..a94f544dcc77 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -244,6 +244,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, void vsp1_entity_destroy(struct vsp1_entity *entity) { + if (entity->destroy) + entity->destroy(entity); if (entity->subdev.ctrl_handler) v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); media_entity_cleanup(&entity->subdev.entity); diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 311d5b64c9a5..259880e524fe 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -56,6 +56,8 @@ struct vsp1_route { struct vsp1_entity { struct vsp1_device *vsp1; + void (*destroy)(struct vsp1_entity *); + enum vsp1_entity_type type; unsigned int index; const struct vsp1_route *route; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 8e8235682ada..d04df39b2737 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -24,6 +24,7 @@ #define RWPF_PAD_SOURCE 1 struct v4l2_ctrl; +struct vsp1_dl_manager; struct vsp1_rwpf; struct vsp1_video; @@ -60,6 +61,8 @@ struct vsp1_rwpf { unsigned int offsets[2]; dma_addr_t buf_addr[3]; + + struct vsp1_dl_manager *dlm; }; static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index c78d4af50fcf..6afc9c8d9adc 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -16,6 +16,7 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_rwpf.h" #include "vsp1_video.h" @@ -218,6 +219,13 @@ static const struct vsp1_rwpf_operations wpf_vdev_ops = { * Initialization and Cleanup */ +static void vsp1_wpf_destroy(struct vsp1_entity *entity) +{ + struct vsp1_rwpf *wpf = container_of(entity, struct vsp1_rwpf, entity); + + vsp1_dlm_destroy(wpf->dlm); +} + struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) { struct v4l2_subdev *subdev; @@ -233,6 +241,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) wpf->max_width = WPF_MAX_WIDTH; wpf->max_height = WPF_MAX_HEIGHT; + wpf->entity.destroy = vsp1_wpf_destroy; wpf->entity.type = VSP1_ENTITY_WPF; wpf->entity.index = index; @@ -240,6 +249,15 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) if (ret < 0) return ERR_PTR(ret); + /* Initialize the display list manager if the WPF is used for display */ + if ((vsp1->info->features & VSP1_HAS_LIF) && index == 0) { + wpf->dlm = vsp1_dlm_create(vsp1, 4); + if (!wpf->dlm) { + ret = -ENOMEM; + goto error; + } + } + /* Initialize the V4L2 subdev. */ subdev = &wpf->entity.subdev; v4l2_subdev_init(subdev, &wpf_ops); -- GitLab From f22af945f79a2bd68941efdb57d52e8d81db4d45 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 12:19:42 -0200 Subject: [PATCH 2561/9938] [media] v4l: vsp1: bru: Don't program background color in control set handler The datasheet clearly states that all but a few registers can't be modified when the device is running. Programming the background color in the control set handler is thus prohibited. Program it when starting the module instead. This requires storing the background color value internally as the module can be started from the frame completion interrupt handler, and accessing control values requires taking a mutex. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 15 +++++++++------ drivers/media/platform/vsp1/vsp1_bru.h | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index cb0dbc15ddad..4c1bd0419e12 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -42,13 +42,9 @@ static int bru_s_ctrl(struct v4l2_ctrl *ctrl) struct vsp1_bru *bru = container_of(ctrl->handler, struct vsp1_bru, ctrls); - if (!vsp1_entity_is_streaming(&bru->entity)) - return 0; - switch (ctrl->id) { case V4L2_CID_BG_COLOR: - vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, ctrl->val | - (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT)); + bru->bgcolor = ctrl->val; break; } @@ -95,12 +91,17 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? 0 : VI6_BRU_INCTRL_NRM); - /* Set the background position to cover the whole output image. */ + /* Set the background position to cover the whole output image and + * configure its color. + */ vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); + vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, bru->bgcolor | + (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT)); + /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP * unit with a NOP operation to make BRU input 1 available as the * Blend/ROP unit B SRC input. @@ -438,6 +439,8 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR, 0, 0xffffff, 1, 0); + bru->bgcolor = 0; + bru->entity.subdev.ctrl_handler = &bru->ctrls; if (bru->ctrls.error) { diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h index dbac9686ea69..4e7d2e79b940 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.h +++ b/drivers/media/platform/vsp1/vsp1_bru.h @@ -33,6 +33,8 @@ struct vsp1_bru { struct vsp1_rwpf *rpf; struct v4l2_rect compose; } inputs[VSP1_MAX_RPF]; + + u32 bgcolor; }; static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev) -- GitLab From 5fb2107346cfc6d8fe62117a2cbf91fc1f92cc84 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 Apr 2016 17:40:48 -0300 Subject: [PATCH 2562/9938] [media] vsp1: make vsp1_drm_frame_end static As reported by smatch: drivers/media/platform/vsp1/vsp1_drm.c:39:6: warning: no previous prototype for 'vsp1_drm_frame_end' [-Wmissing-prototypes] void vsp1_drm_frame_end(struct vsp1_pipeline *pipe) Fixes: ef9621bcd664 ("[media] v4l: vsp1: Store the display list manager in the WPF") Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 22f67360b750..1f08da4b933b 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -36,7 +36,7 @@ void vsp1_drm_display_start(struct vsp1_device *vsp1) vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm); } -void vsp1_drm_frame_end(struct vsp1_pipeline *pipe) +static void vsp1_drm_frame_end(struct vsp1_pipeline *pipe) { vsp1_dlm_irq_frame_end(pipe->output->dlm); } -- GitLab From bd2fdd5aa919e3cb750147c9270034f11d106d94 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 12:19:42 -0200 Subject: [PATCH 2563/9938] [media] v4l: vsp1: rwpf: Don't program alpha value in control set handler The datasheet clearly states that all but a few registers can't be modified when the device is running. Programming the alpha value in the control set handler is thus prohibited. Program it when starting the module instead. This requires storing the alpha value internally as the module can be started from the frame completion interrupt handler, and accessing control values requires taking a mutex. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 51 +++-------------------- drivers/media/platform/vsp1/vsp1_rwpf.c | 35 ++++++++++++++++ drivers/media/platform/vsp1/vsp1_rwpf.h | 5 ++- drivers/media/platform/vsp1/vsp1_wpf.c | 55 ++----------------------- 4 files changed, 47 insertions(+), 99 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 5bc1d1574a43..9ccfb572b4a5 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -32,36 +32,6 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) data); } -/* ----------------------------------------------------------------------------- - * Controls - */ - -static int rpf_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vsp1_rwpf *rpf = - container_of(ctrl->handler, struct vsp1_rwpf, ctrls); - struct vsp1_pipeline *pipe; - - if (!vsp1_entity_is_streaming(&rpf->entity)) - return 0; - - switch (ctrl->id) { - case V4L2_CID_ALPHA_COMPONENT: - vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, - ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); - - pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity); - vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val); - break; - } - - return 0; -} - -static const struct v4l2_ctrl_ops rpf_ctrl_ops = { - .s_ctrl = rpf_s_ctrl, -}; - /* ----------------------------------------------------------------------------- * V4L2 Subdevice Core Operations */ @@ -70,7 +40,6 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); struct vsp1_rwpf *rpf = to_rwpf(subdev); - struct vsp1_device *vsp1 = rpf->entity.vsp1; const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; const struct v4l2_pix_format_mplane *format = &rpf->format; const struct v4l2_rect *crop = &rpf->crop; @@ -151,13 +120,10 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED : VI6_RPF_ALPH_SEL_ASEL_FIXED)); - if (vsp1->info->uapi) - mutex_lock(rpf->ctrls.lock); vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, - rpf->alpha->cur.val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); - vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha->cur.val); - if (vsp1->info->uapi) - mutex_unlock(rpf->ctrls.lock); + rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); + + vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha); vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); @@ -255,17 +221,10 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) vsp1_entity_init_formats(subdev, NULL); /* Initialize the control handler. */ - v4l2_ctrl_handler_init(&rpf->ctrls, 1); - rpf->alpha = v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, - V4L2_CID_ALPHA_COMPONENT, - 0, 255, 1, 255); - - rpf->entity.subdev.ctrl_handler = &rpf->ctrls; - - if (rpf->ctrls.error) { + ret = vsp1_rwpf_init_ctrls(rpf); + if (ret < 0) { dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n", index); - ret = rpf->ctrls.error; goto error; } diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 9688c219b30e..ba50386db35c 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -230,3 +230,38 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, return 0; } + +/* ----------------------------------------------------------------------------- + * Controls + */ + +static int vsp1_rwpf_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct vsp1_rwpf *rwpf = + container_of(ctrl->handler, struct vsp1_rwpf, ctrls); + + switch (ctrl->id) { + case V4L2_CID_ALPHA_COMPONENT: + rwpf->alpha = ctrl->val; + break; + } + + return 0; +} + +static const struct v4l2_ctrl_ops vsp1_rwpf_ctrl_ops = { + .s_ctrl = vsp1_rwpf_s_ctrl, +}; + +int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf) +{ + rwpf->alpha = 255; + + v4l2_ctrl_handler_init(&rwpf->ctrls, 1); + v4l2_ctrl_new_std(&rwpf->ctrls, &vsp1_rwpf_ctrl_ops, + V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255); + + rwpf->entity.subdev.ctrl_handler = &rwpf->ctrls; + + return rwpf->ctrls.error; +} diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index d04df39b2737..66af2a06dd8b 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -42,7 +42,6 @@ struct vsp1_rwpf_operations { struct vsp1_rwpf { struct vsp1_entity entity; struct v4l2_ctrl_handler ctrls; - struct v4l2_ctrl *alpha; struct vsp1_video *video; @@ -59,6 +58,8 @@ struct vsp1_rwpf { } location; struct v4l2_rect crop; + unsigned int alpha; + unsigned int offsets[2]; dma_addr_t buf_addr[3]; @@ -73,6 +74,8 @@ static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); +int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf); + int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 6afc9c8d9adc..2135cca2490e 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -27,47 +27,12 @@ * Device Access */ -static inline u32 vsp1_wpf_read(struct vsp1_rwpf *wpf, u32 reg) -{ - return vsp1_read(wpf->entity.vsp1, - reg + wpf->entity.index * VI6_WPF_OFFSET); -} - static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) { vsp1_mod_write(&wpf->entity, reg + wpf->entity.index * VI6_WPF_OFFSET, data); } -/* ----------------------------------------------------------------------------- - * Controls - */ - -static int wpf_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vsp1_rwpf *wpf = - container_of(ctrl->handler, struct vsp1_rwpf, ctrls); - u32 value; - - if (!vsp1_entity_is_streaming(&wpf->entity)) - return 0; - - switch (ctrl->id) { - case V4L2_CID_ALPHA_COMPONENT: - value = vsp1_wpf_read(wpf, VI6_WPF_OUTFMT); - value &= ~VI6_WPF_OUTFMT_PDV_MASK; - value |= ctrl->val << VI6_WPF_OUTFMT_PDV_SHIFT; - vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, value); - break; - } - - return 0; -} - -static const struct v4l2_ctrl_ops wpf_ctrl_ops = { - .s_ctrl = wpf_s_ctrl, -}; - /* ----------------------------------------------------------------------------- * V4L2 Subdevice Core Operations */ @@ -153,15 +118,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) wpf->entity.formats[RWPF_PAD_SOURCE].code) outfmt |= VI6_WPF_OUTFMT_CSC; - /* Take the control handler lock to ensure that the PDV value won't be - * changed behind our back by a set control operation. - */ - if (vsp1->info->uapi) - mutex_lock(wpf->ctrls.lock); - outfmt |= wpf->alpha->cur.val << VI6_WPF_OUTFMT_PDV_SHIFT; + outfmt |= wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT; vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); - if (vsp1->info->uapi) - mutex_unlock(wpf->ctrls.lock); vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index), VI6_DPR_WPF_FPORCH_FP_WPFN); @@ -272,17 +230,10 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) vsp1_entity_init_formats(subdev, NULL); /* Initialize the control handler. */ - v4l2_ctrl_handler_init(&wpf->ctrls, 1); - wpf->alpha = v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, - V4L2_CID_ALPHA_COMPONENT, - 0, 255, 1, 255); - - wpf->entity.subdev.ctrl_handler = &wpf->ctrls; - - if (wpf->ctrls.error) { + ret = vsp1_rwpf_init_ctrls(wpf); + if (ret < 0) { dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", index); - ret = wpf->ctrls.error; goto error; } -- GitLab From d884a8b2a5dc2fad784a60f356d1d8d90cecb436 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 12:19:42 -0200 Subject: [PATCH 2564/9938] [media] v4l: vsp1: sru: Don't program intensity in control set handler The datasheet clearly states that all but a few registers can't be modified when the device is running. Programming the intensity parameters in the control set handler is thus prohibited. Program it when starting the module instead. This requires storing the intensity value internally as the module can be started from the frame completion interrupt handler, and accessing control values requires taking a mutex. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_sru.c | 35 +++++++------------------- drivers/media/platform/vsp1/vsp1_sru.h | 2 ++ 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index cc09efbfb24f..ec4741efc7f8 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -26,11 +26,6 @@ * Device Access */ -static inline u32 vsp1_sru_read(struct vsp1_sru *sru, u32 reg) -{ - return vsp1_read(sru->entity.vsp1, reg); -} - static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data) { vsp1_write(sru->entity.vsp1, reg, data); @@ -82,20 +77,10 @@ static int sru_s_ctrl(struct v4l2_ctrl *ctrl) { struct vsp1_sru *sru = container_of(ctrl->handler, struct vsp1_sru, ctrls); - const struct vsp1_sru_param *param; - u32 value; switch (ctrl->id) { case V4L2_CID_VSP1_SRU_INTENSITY: - param = &vsp1_sru_params[ctrl->val - 1]; - - value = vsp1_sru_read(sru, VI6_SRU_CTRL0); - value &= ~(VI6_SRU_CTRL0_PARAM0_MASK | - VI6_SRU_CTRL0_PARAM1_MASK); - value |= param->ctrl0; - vsp1_sru_write(sru, VI6_SRU_CTRL0, value); - - vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); + sru->intensity = ctrl->val; break; } @@ -123,6 +108,7 @@ static const struct v4l2_ctrl_config sru_intensity_control = { static int sru_s_stream(struct v4l2_subdev *subdev, int enable) { + const struct vsp1_sru_param *param; struct vsp1_sru *sru = to_sru(subdev); struct v4l2_mbus_framefmt *input; struct v4l2_mbus_framefmt *output; @@ -148,18 +134,13 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) if (input->width != output->width) ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE; - /* Take the control handler lock to ensure that the CTRL0 value won't be - * changed behind our back by a set control operation. - */ - if (sru->entity.vsp1->info->uapi) - mutex_lock(sru->ctrls.lock); - ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0) - & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK); - vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); - if (sru->entity.vsp1->info->uapi) - mutex_unlock(sru->ctrls.lock); + param = &vsp1_sru_params[sru->intensity - 1]; + + ctrl0 |= param->ctrl0; + vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); + vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); return 0; } @@ -376,6 +357,8 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) v4l2_ctrl_handler_init(&sru->ctrls, 1); v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL); + sru->intensity = 1; + sru->entity.subdev.ctrl_handler = &sru->ctrls; if (sru->ctrls.error) { diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h index b6768bf3dc47..85e241457af2 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.h +++ b/drivers/media/platform/vsp1/vsp1_sru.h @@ -28,6 +28,8 @@ struct vsp1_sru { struct vsp1_entity entity; struct v4l2_ctrl_handler ctrls; + + unsigned int intensity; }; static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev) -- GitLab From 59d0b2bf1d8de62d3ee8cce5c5b9463608095642 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 12:58:29 -0200 Subject: [PATCH 2565/9938] [media] v4l: vsp1: Don't setup control handler when starting streaming The control handler set operations don't program the hardware anymore, there's thus no need to call them when starting the stream. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 5 +---- drivers/media/platform/vsp1/vsp1_entity.c | 18 +----------------- drivers/media/platform/vsp1/vsp1_entity.h | 2 +- drivers/media/platform/vsp1/vsp1_rpf.c | 5 +---- drivers/media/platform/vsp1/vsp1_sru.c | 5 +---- drivers/media/platform/vsp1/vsp1_wpf.c | 5 +---- 6 files changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 4c1bd0419e12..27a9043b11e2 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -66,11 +66,8 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) struct v4l2_mbus_framefmt *format; unsigned int flags; unsigned int i; - int ret; - ret = vsp1_entity_set_streaming(&bru->entity, enable); - if (ret < 0) - return ret; + vsp1_entity_set_streaming(&bru->entity, enable); if (!enable) return 0; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index a94f544dcc77..6b425ae9aba3 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -45,29 +45,13 @@ bool vsp1_entity_is_streaming(struct vsp1_entity *entity) return streaming; } -int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) +void vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) { unsigned long flags; - int ret; spin_lock_irqsave(&entity->lock, flags); entity->streaming = streaming; spin_unlock_irqrestore(&entity->lock, flags); - - if (!streaming) - return 0; - - if (!entity->vsp1->info->uapi || !entity->subdev.ctrl_handler) - return 0; - - ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler); - if (ret < 0) { - spin_lock_irqsave(&entity->lock, flags); - entity->streaming = false; - spin_unlock_irqrestore(&entity->lock, flags); - } - - return ret; } void vsp1_entity_route_setup(struct vsp1_entity *source) diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 259880e524fe..c0d6db82ebfb 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -101,7 +101,7 @@ void vsp1_entity_init_formats(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg); bool vsp1_entity_is_streaming(struct vsp1_entity *entity); -int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); +void vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); void vsp1_entity_route_setup(struct vsp1_entity *source); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 9ccfb572b4a5..48870b257a81 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -45,11 +45,8 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) const struct v4l2_rect *crop = &rpf->crop; u32 pstride; u32 infmt; - int ret; - ret = vsp1_entity_set_streaming(&rpf->entity, enable); - if (ret < 0) - return ret; + vsp1_entity_set_streaming(&rpf->entity, enable); if (!enable) return 0; diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index ec4741efc7f8..15fc562a52da 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -113,11 +113,8 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) struct v4l2_mbus_framefmt *input; struct v4l2_mbus_framefmt *output; u32 ctrl0; - int ret; - ret = vsp1_entity_set_streaming(&sru->entity, enable); - if (ret < 0) - return ret; + vsp1_entity_set_streaming(&sru->entity, enable); if (!enable) return 0; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 2135cca2490e..d68c90d45232 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -46,11 +46,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) unsigned int i; u32 srcrpf = 0; u32 outfmt = 0; - int ret; - ret = vsp1_entity_set_streaming(&wpf->entity, enable); - if (ret < 0) - return ret; + vsp1_entity_set_streaming(&wpf->entity, enable); if (!enable) { vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); -- GitLab From 773abafe6f7b81f2ff51aaa1d137efdc54c30354 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 12:26:14 -0200 Subject: [PATCH 2566/9938] [media] v4l: vsp1: Enable display list support for the HS[IT], LUT, SRU and UDS Those modules were left out of display list integration as they're not used by the DRM pipeline. To prepare for display list support in non-DRM pipelines use the module write API to set registers. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_hsit.c | 2 +- drivers/media/platform/vsp1/vsp1_lut.c | 2 +- drivers/media/platform/vsp1/vsp1_sru.c | 2 +- drivers/media/platform/vsp1/vsp1_uds.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index c1087cff31a0..e820fe0b4f00 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -28,7 +28,7 @@ static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data) { - vsp1_write(hsit->entity.vsp1, reg, data); + vsp1_mod_write(&hsit->entity, reg, data); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 4b89095e7b5f..fc9011b12993 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -29,7 +29,7 @@ static inline void vsp1_lut_write(struct vsp1_lut *lut, u32 reg, u32 data) { - vsp1_write(lut->entity.vsp1, reg, data); + vsp1_mod_write(&lut->entity, reg, data); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 15fc562a52da..810c6b376e14 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -28,7 +28,7 @@ static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data) { - vsp1_write(sru->entity.vsp1, reg, data); + vsp1_mod_write(&sru->entity, reg, data); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index bba67770cf95..c608b06ed677 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -31,8 +31,8 @@ static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data) { - vsp1_write(uds->entity.vsp1, - reg + uds->entity.index * VI6_UDS_OFFSET, data); + vsp1_mod_write(&uds->entity, reg + uds->entity.index * VI6_UDS_OFFSET, + data); } /* ----------------------------------------------------------------------------- -- GitLab From 4d346be55d415114faf19c0f79c2c15c7cc11242 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 13:48:11 -0200 Subject: [PATCH 2567/9938] [media] v4l: vsp1: Don't configure RPF memory buffers before calculating offsets The RPF source memory pointers need to be offset to take the crop rectangle into account. Offsets are computed in the RPF stream start, which can happen (when using the DRM pipeline) after calling the RPF .set_memory() operation that programs the buffer addresses. The .set_memory() operation tries to guard against the problem by skipping programming of the registers when the module isn't streaming. This will however only protect the first use of an RPF in a DRM pipeline, as in all subsequent uses the module streaming flag will be set and the .set_memory() operation will use potentially incorrect offsets. Fix this by allowing the caller to decide whether to program the hardware immediately or just cache the addresses. While at it refactor the memory set code and create a new vsp1_rwpf_set_memory() that cache addresses and calls the .set_memory() operation to apply them to the hardware. As a side effect the driver now writes all three DMA address registers regardless of the number of planes, and initializes unused addresses to zero. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 7 +++-- drivers/media/platform/vsp1/vsp1_rpf.c | 37 +++++++----------------- drivers/media/platform/vsp1/vsp1_rwpf.c | 26 +++++++++++++++++ drivers/media/platform/vsp1/vsp1_rwpf.h | 11 +++++-- drivers/media/platform/vsp1/vsp1_video.c | 9 ++++-- drivers/media/platform/vsp1/vsp1_wpf.c | 10 +++---- 6 files changed, 62 insertions(+), 38 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 1f08da4b933b..9193b7b7d183 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -420,12 +420,15 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, rpf->location.left = dst->left; rpf->location.top = dst->top; - /* Set the memory buffer address. */ + /* Set the memory buffer address but don't apply the values to the + * hardware as the crop offsets haven't been computed yet. + */ memory.num_planes = fmtinfo->planes; memory.addr[0] = mem[0]; memory.addr[1] = mem[1]; + memory.addr[2] = 0; - rpf->ops->set_memory(rpf, &memory); + vsp1_rwpf_set_memory(rpf, &memory, false); spin_lock_irqsave(&pipe->irqlock, flags); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 48870b257a81..62d898c0ad65 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -69,25 +69,20 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) pstride = format->plane_fmt[0].bytesperline << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, - rpf->buf_addr[0] + rpf->offsets[0]); - if (format->num_planes > 1) { rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline + crop->left * fmtinfo->bpp[1] / 8; pstride |= format->plane_fmt[1].bytesperline << VI6_RPF_SRCM_PSTRIDE_C_SHIFT; - - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, - rpf->buf_addr[1] + rpf->offsets[1]); - - if (format->num_planes > 2) - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, - rpf->buf_addr[2] + rpf->offsets[1]); + } else { + rpf->offsets[1] = 0; } vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); + /* Now that the offsets have been computed program the DMA addresses. */ + rpf->ops->set_memory(rpf); + /* Format */ infmt = VI6_RPF_INFMT_CIPM | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT); @@ -154,24 +149,14 @@ static struct v4l2_subdev_ops rpf_ops = { * Video Device Operations */ -static void rpf_set_memory(struct vsp1_rwpf *rpf, struct vsp1_rwpf_memory *mem) +static void rpf_set_memory(struct vsp1_rwpf *rpf) { - unsigned int i; - - for (i = 0; i < 3; ++i) - rpf->buf_addr[i] = mem->addr[i]; - - if (!vsp1_entity_is_streaming(&rpf->entity)) - return; - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, - mem->addr[0] + rpf->offsets[0]); - if (mem->num_planes > 1) - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, - mem->addr[1] + rpf->offsets[1]); - if (mem->num_planes > 2) - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, - mem->addr[2] + rpf->offsets[1]); + rpf->buf_addr[0] + rpf->offsets[0]); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, + rpf->buf_addr[1] + rpf->offsets[1]); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, + rpf->buf_addr[2] + rpf->offsets[1]); } static const struct vsp1_rwpf_operations rpf_vdev_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index ba50386db35c..54070ccdc2ff 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -265,3 +265,29 @@ int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf) return rwpf->ctrls.error; } + +/* ----------------------------------------------------------------------------- + * Buffers + */ + +/** + * vsp1_rwpf_set_memory - Configure DMA addresses for a [RW]PF + * @rwpf: the [RW]PF instance + * @mem: DMA memory addresses + * @apply: whether to apply the configuration to the hardware + * + * This function stores the DMA addresses for all planes in the rwpf instance + * and optionally applies the configuration to hardware registers if the apply + * argument is set to true. + */ +void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf, struct vsp1_rwpf_memory *mem, + bool apply) +{ + unsigned int i; + + for (i = 0; i < 3; ++i) + rwpf->buf_addr[i] = mem->addr[i]; + + if (apply) + rwpf->ops->set_memory(rwpf); +} diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 66af2a06dd8b..bda0416dc7db 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -34,9 +34,13 @@ struct vsp1_rwpf_memory { unsigned int length[3]; }; +/** + * struct vsp1_rwpf_operations - RPF and WPF operations + * @set_memory: Setup memory buffer access. This operation applies the settings + * stored in the rwpf buf_addr field to the hardware. + */ struct vsp1_rwpf_operations { - void (*set_memory)(struct vsp1_rwpf *rwpf, - struct vsp1_rwpf_memory *mem); + void (*set_memory)(struct vsp1_rwpf *rwpf); }; struct vsp1_rwpf { @@ -93,4 +97,7 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel); +void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf, struct vsp1_rwpf_memory *mem, + bool apply); + #endif /* __VSP1_RWPF_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index b97bbdb1a256..96b04fcd33ae 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -443,7 +443,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, spin_lock_irqsave(&pipe->irqlock, flags); - video->rwpf->ops->set_memory(video->rwpf, &buf->mem); + vsp1_rwpf_set_memory(video->rwpf, &buf->mem, true); pipe->buffers_ready |= 1 << video->pipe_index; spin_unlock_irqrestore(&pipe->irqlock, flags); @@ -522,6 +522,11 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) return -EINVAL; } + for ( ; i < 3; ++i) { + buf->mem.addr[i] = 0; + buf->mem.length[i] = 0; + } + return 0; } @@ -544,7 +549,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) spin_lock_irqsave(&pipe->irqlock, flags); - video->rwpf->ops->set_memory(video->rwpf, &buf->mem); + vsp1_rwpf_set_memory(video->rwpf, &buf->mem, true); pipe->buffers_ready |= 1 << video->pipe_index; if (vb2_is_streaming(&video->queue) && diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index d68c90d45232..28654cffeeca 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -157,13 +157,11 @@ static struct v4l2_subdev_ops wpf_ops = { * Video Device Operations */ -static void wpf_set_memory(struct vsp1_rwpf *wpf, struct vsp1_rwpf_memory *mem) +static void wpf_set_memory(struct vsp1_rwpf *wpf) { - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, mem->addr[0]); - if (mem->num_planes > 1) - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, mem->addr[1]); - if (mem->num_planes > 2) - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, mem->addr[2]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->buf_addr[0]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->buf_addr[1]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->buf_addr[2]); } static const struct vsp1_rwpf_operations wpf_vdev_ops = { -- GitLab From 2b09ee4093e98e8eaa908554aa36a5b2ceba6e3d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 13:54:34 -0200 Subject: [PATCH 2568/9938] [media] v4l: vsp1: Remove unneeded entity streaming flag The flag is set but never read, remove it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 2 -- drivers/media/platform/vsp1/vsp1_entity.c | 23 ----------------------- drivers/media/platform/vsp1/vsp1_entity.h | 6 ------ drivers/media/platform/vsp1/vsp1_rpf.c | 2 -- drivers/media/platform/vsp1/vsp1_sru.c | 2 -- drivers/media/platform/vsp1/vsp1_wpf.c | 2 -- 6 files changed, 37 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 27a9043b11e2..74cc4903e858 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -67,8 +67,6 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) unsigned int flags; unsigned int i; - vsp1_entity_set_streaming(&bru->entity, enable); - if (!enable) return 0; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 6b425ae9aba3..be67727f6f78 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -33,27 +33,6 @@ void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data) vsp1_write(e->vsp1, reg, data); } -bool vsp1_entity_is_streaming(struct vsp1_entity *entity) -{ - unsigned long flags; - bool streaming; - - spin_lock_irqsave(&entity->lock, flags); - streaming = entity->streaming; - spin_unlock_irqrestore(&entity->lock, flags); - - return streaming; -} - -void vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) -{ - unsigned long flags; - - spin_lock_irqsave(&entity->lock, flags); - entity->streaming = streaming; - spin_unlock_irqrestore(&entity->lock, flags); -} - void vsp1_entity_route_setup(struct vsp1_entity *source) { struct vsp1_entity *sink; @@ -198,8 +177,6 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, if (i == ARRAY_SIZE(vsp1_routes)) return -EINVAL; - spin_lock_init(&entity->lock); - entity->vsp1 = vsp1; entity->source_pad = num_pads - 1; diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index c0d6db82ebfb..203872164f8e 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -73,9 +73,6 @@ struct vsp1_entity { struct v4l2_subdev subdev; struct v4l2_mbus_framefmt *formats; - - spinlock_t lock; /* Protects the streaming field */ - bool streaming; }; static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) @@ -100,9 +97,6 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity, void vsp1_entity_init_formats(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg); -bool vsp1_entity_is_streaming(struct vsp1_entity *entity); -void vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); - void vsp1_entity_route_setup(struct vsp1_entity *source); void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 62d898c0ad65..ffe097b27a77 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -46,8 +46,6 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) u32 pstride; u32 infmt; - vsp1_entity_set_streaming(&rpf->entity, enable); - if (!enable) return 0; diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 810c6b376e14..371b20ec5d1b 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -114,8 +114,6 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) struct v4l2_mbus_framefmt *output; u32 ctrl0; - vsp1_entity_set_streaming(&sru->entity, enable); - if (!enable) return 0; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 28654cffeeca..1013190e440b 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -47,8 +47,6 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) u32 srcrpf = 0; u32 outfmt = 0; - vsp1_entity_set_streaming(&wpf->entity, enable); - if (!enable) { vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + -- GitLab From c9e645a534744029d5d465d9b7bfae3de9123031 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 14:01:51 -0200 Subject: [PATCH 2569/9938] [media] v4l: vsp1: Document calling context of vsp1_pipeline_propagate_alpha() The function can only be called from a s_stream handler as it requires a valid display list context (due to calling vsp1_uds_set_alpha() which writes to module registers). Document the requirement. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index cb67b8f80635..a9a754e17e8d 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -318,6 +318,9 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha * value. The UDS then outputs a fixed alpha value which needs to be programmed * from the input RPF alpha. + * + * This function can only be called from a subdev s_stream handler as it + * requires a valid display list context. */ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, struct vsp1_entity *input, -- GitLab From 1bd0a1bd3462f2b04f969f649875b28eaa85c97d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 15:18:32 -0200 Subject: [PATCH 2570/9938] [media] v4l: vsp1: Fix 80 characters per line violations Commit f7234138f14c ("v4l2-subdev: replace v4l2_subdev_fh by v4l2_subdev_pad_config") introduced lots of 80 characters per line violations. Fix them. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 12 ++++++++---- drivers/media/platform/vsp1/vsp1_lif.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_lut.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_rwpf.c | 12 ++++++++---- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 ++++-- drivers/media/platform/vsp1/vsp1_sru.c | 9 ++++++--- drivers/media/platform/vsp1/vsp1_uds.c | 9 ++++++--- 7 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 74cc4903e858..6a6e9d84f1ca 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -195,7 +195,8 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev, return -EINVAL; format = vsp1_entity_get_pad_format(&bru->entity, cfg, - BRU_PAD_SINK(0), code->which); + BRU_PAD_SINK(0), + code->which); code->code = format->code; } @@ -235,7 +236,8 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, } } -static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int bru_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_bru *bru = to_bru(subdev); @@ -246,7 +248,8 @@ static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con return 0; } -static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *cfg, +static void bru_try_format(struct vsp1_bru *bru, + struct v4l2_subdev_pad_config *cfg, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { @@ -274,7 +277,8 @@ static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config * fmt->colorspace = V4L2_COLORSPACE_SRGB; } -static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int bru_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_bru *bru = to_bru(subdev); diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 433853ce8dbf..be0ea166016c 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -128,7 +128,8 @@ static int lif_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int lif_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_lif *lif = to_lif(subdev); @@ -139,7 +140,8 @@ static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con return 0; } -static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int lif_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_lif *lif = to_lif(subdev); diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index fc9011b12993..3af849dbee5a 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -139,7 +139,8 @@ static int lut_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int lut_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_lut *lut = to_lut(subdev); @@ -150,7 +151,8 @@ static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con return 0; } -static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int lut_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_lut *lut = to_lut(subdev); diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 54070ccdc2ff..0924079b920c 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -73,11 +73,13 @@ int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, } static struct v4l2_rect * -vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_pad_config *cfg, u32 which) +vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_pad_config *cfg, + u32 which) { switch (which) { case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, cfg, RWPF_PAD_SINK); + return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, cfg, + RWPF_PAD_SINK); case V4L2_SUBDEV_FORMAT_ACTIVE: return &rwpf->crop; default: @@ -85,7 +87,8 @@ vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_pad_config *cfg, u } } -int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); @@ -96,7 +99,8 @@ int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_conf return 0; } -int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index bda0416dc7db..57f15d45f8bb 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -86,9 +86,11 @@ int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse); -int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt); -int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt); int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 371b20ec5d1b..19b7923cb137 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -209,7 +209,8 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int sru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int sru_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_sru *sru = to_sru(subdev); @@ -220,7 +221,8 @@ static int sru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con return 0; } -static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_pad_config *cfg, +static void sru_try_format(struct vsp1_sru *sru, + struct v4l2_subdev_pad_config *cfg, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { @@ -271,7 +273,8 @@ static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_pad_config * fmt->colorspace = V4L2_COLORSPACE_SRGB; } -static int sru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int sru_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_sru *sru = to_sru(subdev); diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index c608b06ed677..83ec8942f8e7 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -222,7 +222,8 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int uds_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_uds *uds = to_uds(subdev); @@ -233,7 +234,8 @@ static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con return 0; } -static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *cfg, +static void uds_try_format(struct vsp1_uds *uds, + struct v4l2_subdev_pad_config *cfg, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { @@ -269,7 +271,8 @@ static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config * fmt->colorspace = V4L2_COLORSPACE_SRGB; } -static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, +static int uds_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_uds *uds = to_uds(subdev); -- GitLab From 1216198935d476e33affd104f0b4210c1fcc2477 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 14 Nov 2015 22:48:27 -0200 Subject: [PATCH 2571/9938] [media] v4l: vsp1: Add header display list support Display lists can operate in header or headerless mode. The headerless mode is only available on WPF0, to be used with the display engine. All other WPF instances can only use display lists in header mode. Implement support for header mode to prepare for display list usage on WPFs other than 0. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 72 ++++++++++++++++++++++++-- drivers/media/platform/vsp1/vsp1_dl.h | 1 + drivers/media/platform/vsp1/vsp1_wpf.c | 2 +- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index e0f4816925d5..81ea1b2ce00d 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -28,9 +28,23 @@ * - DL swap */ +#define VSP1_DL_HEADER_SIZE 76 #define VSP1_DL_BODY_SIZE (2 * 4 * 256) #define VSP1_DL_NUM_LISTS 3 +#define VSP1_DLH_INT_ENABLE (1 << 1) +#define VSP1_DLH_AUTO_START (1 << 0) + +struct vsp1_dl_header { + u32 num_lists; + struct { + u32 num_bytes; + u32 addr; + } lists[8]; + u32 next_header; + u32 flags; +} __attribute__((__packed__)); + struct vsp1_dl_entry { u32 addr; u32 data; @@ -41,6 +55,7 @@ struct vsp1_dl_list { struct vsp1_dl_manager *dlm; + struct vsp1_dl_header *header; struct vsp1_dl_entry *body; dma_addr_t dma; size_t size; @@ -48,8 +63,15 @@ struct vsp1_dl_list { int reg_count; }; +enum vsp1_dl_mode { + VSP1_DL_MODE_HEADER, + VSP1_DL_MODE_HEADERLESS, +}; + /** * struct vsp1_dl_manager - Display List manager + * @index: index of the related WPF + * @mode: display list operation mode (header or headerless) * @vsp1: the VSP1 device * @lock: protects the active, queued and pending lists * @free: array of all free display lists @@ -58,6 +80,8 @@ struct vsp1_dl_list { * @pending: list waiting to be queued to the hardware */ struct vsp1_dl_manager { + unsigned int index; + enum vsp1_dl_mode mode; struct vsp1_device *vsp1; spinlock_t lock; @@ -74,26 +98,43 @@ struct vsp1_dl_manager { static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) { struct vsp1_dl_list *dl; + size_t header_size; + + /* The body needs to be aligned on a 8 bytes boundary, pad the header + * size to allow allocating both in a single operation. + */ + header_size = dlm->mode == VSP1_DL_MODE_HEADER + ? ALIGN(sizeof(struct vsp1_dl_header), 8) + : 0; dl = kzalloc(sizeof(*dl), GFP_KERNEL); if (!dl) return NULL; dl->dlm = dlm; - dl->size = VSP1_DL_BODY_SIZE; + dl->size = header_size + VSP1_DL_BODY_SIZE; - dl->body = dma_alloc_wc(dlm->vsp1->dev, dl->size, &dl->dma, GFP_KERNEL); - if (!dl->body) { + dl->header = dma_alloc_wc(dlm->vsp1->dev, dl->size, &dl->dma, + GFP_KERNEL); + if (!dl->header) { kfree(dl); return NULL; } + if (dlm->mode == VSP1_DL_MODE_HEADER) { + memset(dl->header, 0, sizeof(*dl->header)); + dl->header->lists[0].addr = dl->dma + header_size; + dl->header->flags = VSP1_DLH_INT_ENABLE; + } + + dl->body = ((void *)dl->header) + header_size; + return dl; } static void vsp1_dl_list_free(struct vsp1_dl_list *dl) { - dma_free_wc(dl->dlm->vsp1->dev, dl->size, dl->body, dl->dma); + dma_free_wc(dl->dlm->vsp1->dev, dl->size, dl->header, dl->dma); kfree(dl); } @@ -159,6 +200,18 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl) spin_lock_irqsave(&dlm->lock, flags); + if (dl->dlm->mode == VSP1_DL_MODE_HEADER) { + /* Program the hardware with the display list body address and + * size. In header mode the caller guarantees that the hardware + * is idle at this point. + */ + dl->header->lists[0].num_bytes = dl->reg_count * 8; + vsp1_write(vsp1, VI6_DL_HDR_ADDR(dlm->index), dl->dma); + + dlm->active = dl; + goto done; + } + /* Once the UPD bit has been set the hardware can start processing the * display list at any time and we can't touch the address and size * registers. In that case mark the update as pending, it will be @@ -214,6 +267,13 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) vsp1_dl_list_put(dlm->active); dlm->active = NULL; + /* Header mode is used for mem-to-mem pipelines only. We don't need to + * perform any operation as there can't be any new display list queued + * in that case. + */ + if (dlm->mode == VSP1_DL_MODE_HEADER) + goto done; + /* The UPD bit set indicates that the commit operation raced with the * interrupt and occurred after the frame end event and UPD clear but * before interrupt processing. The hardware hasn't taken the update @@ -276,6 +336,7 @@ void vsp1_dlm_reset(struct vsp1_dl_manager *dlm) } struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, + unsigned int index, unsigned int prealloc) { struct vsp1_dl_manager *dlm; @@ -285,6 +346,9 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, if (!dlm) return NULL; + dlm->index = index; + dlm->mode = index == 0 && !vsp1->info->uapi + ? VSP1_DL_MODE_HEADERLESS : VSP1_DL_MODE_HEADER; dlm->vsp1 = vsp1; spin_lock_init(&dlm->lock); diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 46f7ae337374..571ed6d8e7c2 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -22,6 +22,7 @@ struct vsp1_dl_manager; void vsp1_dlm_setup(struct vsp1_device *vsp1); struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, + unsigned int index, unsigned int prealloc); void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm); void vsp1_dlm_reset(struct vsp1_dl_manager *dlm); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 1013190e440b..d1fad9effb9b 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -202,7 +202,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) /* Initialize the display list manager if the WPF is used for display */ if ((vsp1->info->features & VSP1_HAS_LIF) && index == 0) { - wpf->dlm = vsp1_dlm_create(vsp1, 4); + wpf->dlm = vsp1_dlm_create(vsp1, index, 4); if (!wpf->dlm) { ret = -ENOMEM; goto error; -- GitLab From 351bbf99f245f4bada0edec3b0863146d71f06a9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Nov 2015 15:18:56 -0200 Subject: [PATCH 2572/9938] [media] v4l: vsp1: Use display lists with the userspace API Don't restrict display list usage to the DRM pipeline, use them unconditionally. This prepares the driver to support the request API. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 11 +- drivers/media/platform/vsp1/vsp1_drm.c | 23 ++-- drivers/media/platform/vsp1/vsp1_entity.c | 5 +- drivers/media/platform/vsp1/vsp1_pipe.c | 33 +---- drivers/media/platform/vsp1/vsp1_rpf.c | 9 +- drivers/media/platform/vsp1/vsp1_rwpf.c | 26 ---- drivers/media/platform/vsp1/vsp1_rwpf.h | 18 ++- drivers/media/platform/vsp1/vsp1_video.c | 145 +++++++++++++++------- drivers/media/platform/vsp1/vsp1_wpf.c | 18 ++- 9 files changed, 142 insertions(+), 146 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 81ea1b2ce00d..54f8f4719276 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -311,14 +311,15 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) /* Hardware Setup */ void vsp1_dlm_setup(struct vsp1_device *vsp1) { - u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT); + u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT) + | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0 + | VI6_DL_CTRL_DLE; - /* The DRM pipeline operates with header-less display lists in - * Continuous Frame Mode. + /* The DRM pipeline operates with display lists in Continuous Frame + * Mode, all other pipelines use manual start. */ if (vsp1->drm) - ctrl |= VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0 - | VI6_DL_CTRL_DLE | VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0; + ctrl |= VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0; vsp1_write(vsp1, VI6_DL_CTRL, ctrl); vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 9193b7b7d183..a73018c9e8b5 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -36,11 +36,6 @@ void vsp1_drm_display_start(struct vsp1_device *vsp1) vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm); } -static void vsp1_drm_frame_end(struct vsp1_pipeline *pipe) -{ - vsp1_dlm_irq_frame_end(pipe->output->dlm); -} - /* ----------------------------------------------------------------------------- * DU Driver API */ @@ -280,7 +275,6 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, const struct vsp1_format_info *fmtinfo; struct v4l2_subdev_selection sel; struct v4l2_subdev_format format; - struct vsp1_rwpf_memory memory; struct vsp1_rwpf *rpf; unsigned long flags; int ret; @@ -420,15 +414,12 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, rpf->location.left = dst->left; rpf->location.top = dst->top; - /* Set the memory buffer address but don't apply the values to the + /* Cache the memory buffer address but don't apply the values to the * hardware as the crop offsets haven't been computed yet. */ - memory.num_planes = fmtinfo->planes; - memory.addr[0] = mem[0]; - memory.addr[1] = mem[1]; - memory.addr[2] = 0; - - vsp1_rwpf_set_memory(rpf, &memory, false); + rpf->mem.addr[0] = mem[0]; + rpf->mem.addr[1] = mem[1]; + rpf->mem.addr[2] = 0; spin_lock_irqsave(&pipe->irqlock, flags); @@ -482,14 +473,17 @@ void vsp1_du_atomic_flush(struct device *dev) entity->subdev.name); return; } + + if (entity->type == VSP1_ENTITY_RPF) + vsp1_rwpf_set_memory(to_rwpf(&entity->subdev)); } vsp1_dl_list_commit(pipe->dl); pipe->dl = NULL; + /* Start or stop the pipeline if needed. */ spin_lock_irqsave(&pipe->irqlock, flags); - /* Start or stop the pipeline if needed. */ if (!vsp1->drm->num_inputs && pipe->num_inputs) { vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0); vsp1_write(vsp1, VI6_DISP_IRQ_ENB, VI6_DISP_IRQ_ENB_DSTE); @@ -569,7 +563,6 @@ int vsp1_drm_init(struct vsp1_device *vsp1) pipe = &vsp1->drm->pipe; vsp1_pipeline_init(pipe); - pipe->frame_end = vsp1_drm_frame_end; /* The DRM pipeline is static, add entities manually. */ for (i = 0; i < vsp1->info->rpf_count; ++i) { diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index be67727f6f78..7b2301dbd584 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -27,10 +27,7 @@ void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity); - if (pipe->dl) - vsp1_dl_list_write(pipe->dl, reg, data); - else - vsp1_write(e->vsp1, reg, data); + vsp1_dl_list_write(pipe->dl, reg, data); } void vsp1_entity_route_setup(struct vsp1_entity *source) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index a9a754e17e8d..3311db18f40b 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -273,42 +273,13 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) { - enum vsp1_pipeline_state state; - unsigned long flags; - if (pipe == NULL) return; - /* Signal frame end to the pipeline handler. */ + vsp1_dlm_irq_frame_end(pipe->output->dlm); + if (pipe->frame_end) pipe->frame_end(pipe); - - spin_lock_irqsave(&pipe->irqlock, flags); - - state = pipe->state; - - /* When using display lists in continuous frame mode the pipeline is - * automatically restarted by the hardware. - */ - if (pipe->lif) - goto done; - - pipe->state = VSP1_PIPELINE_STOPPED; - - /* If a stop has been requested, mark the pipeline as stopped and - * return. - */ - if (state == VSP1_PIPELINE_STOPPING) { - wake_up(&pipe->wq); - goto done; - } - - /* Restart the pipeline if ready. */ - if (vsp1_pipeline_ready(pipe)) - vsp1_pipeline_run(pipe); - -done: - spin_unlock_irqrestore(&pipe->irqlock, flags); } /* diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index ffe097b27a77..09919db7e0ea 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -78,9 +78,6 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); - /* Now that the offsets have been computed program the DMA addresses. */ - rpf->ops->set_memory(rpf); - /* Format */ infmt = VI6_RPF_INFMT_CIPM | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT); @@ -150,11 +147,11 @@ static struct v4l2_subdev_ops rpf_ops = { static void rpf_set_memory(struct vsp1_rwpf *rpf) { vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, - rpf->buf_addr[0] + rpf->offsets[0]); + rpf->mem.addr[0] + rpf->offsets[0]); vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, - rpf->buf_addr[1] + rpf->offsets[1]); + rpf->mem.addr[1] + rpf->offsets[1]); vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, - rpf->buf_addr[2] + rpf->offsets[1]); + rpf->mem.addr[2] + rpf->offsets[1]); } static const struct vsp1_rwpf_operations rpf_vdev_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 0924079b920c..38893ab06cd9 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -269,29 +269,3 @@ int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf) return rwpf->ctrls.error; } - -/* ----------------------------------------------------------------------------- - * Buffers - */ - -/** - * vsp1_rwpf_set_memory - Configure DMA addresses for a [RW]PF - * @rwpf: the [RW]PF instance - * @mem: DMA memory addresses - * @apply: whether to apply the configuration to the hardware - * - * This function stores the DMA addresses for all planes in the rwpf instance - * and optionally applies the configuration to hardware registers if the apply - * argument is set to true. - */ -void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf, struct vsp1_rwpf_memory *mem, - bool apply) -{ - unsigned int i; - - for (i = 0; i < 3; ++i) - rwpf->buf_addr[i] = mem->addr[i]; - - if (apply) - rwpf->ops->set_memory(rwpf); -} diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 57f15d45f8bb..2bbcc331959b 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -29,15 +29,13 @@ struct vsp1_rwpf; struct vsp1_video; struct vsp1_rwpf_memory { - unsigned int num_planes; dma_addr_t addr[3]; - unsigned int length[3]; }; /** * struct vsp1_rwpf_operations - RPF and WPF operations * @set_memory: Setup memory buffer access. This operation applies the settings - * stored in the rwpf buf_addr field to the hardware. + * stored in the rwpf mem field to the hardware. */ struct vsp1_rwpf_operations { void (*set_memory)(struct vsp1_rwpf *rwpf); @@ -65,7 +63,7 @@ struct vsp1_rwpf { unsigned int alpha; unsigned int offsets[2]; - dma_addr_t buf_addr[3]; + struct vsp1_rwpf_memory mem; struct vsp1_dl_manager *dlm; }; @@ -99,7 +97,15 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel); -void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf, struct vsp1_rwpf_memory *mem, - bool apply); +/** + * vsp1_rwpf_set_memory - Configure DMA addresses for a [RW]PF + * @rwpf: the [RW]PF instance + * + * This function applies the cached memory buffer address to the hardware. + */ +static inline void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf) +{ + rwpf->ops->set_memory(rwpf); +} #endif /* __VSP1_RWPF_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 96b04fcd33ae..7cb270f57f62 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -29,6 +29,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_dl.h" #include "vsp1_entity.h" #include "vsp1_pipe.h" #include "vsp1_rwpf.h" @@ -424,7 +425,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video) done->buf.vb2_buf.timestamp = ktime_get_ns(); for (i = 0; i < done->buf.vb2_buf.num_planes; ++i) vb2_set_plane_payload(&done->buf.vb2_buf, i, - done->mem.length[i]); + vb2_plane_size(&done->buf.vb2_buf, i)); vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE); return next; @@ -443,15 +444,41 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, spin_lock_irqsave(&pipe->irqlock, flags); - vsp1_rwpf_set_memory(video->rwpf, &buf->mem, true); + video->rwpf->mem = buf->mem; pipe->buffers_ready |= 1 << video->pipe_index; spin_unlock_irqrestore(&pipe->irqlock, flags); } +static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) +{ + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + unsigned int i; + + if (!pipe->dl) + pipe->dl = vsp1_dl_list_get(pipe->output->dlm); + + for (i = 0; i < vsp1->info->rpf_count; ++i) { + struct vsp1_rwpf *rwpf = pipe->inputs[i]; + + if (rwpf) + vsp1_rwpf_set_memory(rwpf); + } + + if (!pipe->lif) + vsp1_rwpf_set_memory(pipe->output); + + vsp1_dl_list_commit(pipe->dl); + pipe->dl = NULL; + + vsp1_pipeline_run(pipe); +} + static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) { struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + enum vsp1_pipeline_state state; + unsigned long flags; unsigned int i; /* Complete buffers on all video nodes. */ @@ -462,8 +489,22 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) vsp1_video_frame_end(pipe, pipe->inputs[i]); } - if (!pipe->lif) - vsp1_video_frame_end(pipe, pipe->output); + vsp1_video_frame_end(pipe, pipe->output); + + spin_lock_irqsave(&pipe->irqlock, flags); + + state = pipe->state; + pipe->state = VSP1_PIPELINE_STOPPED; + + /* If a stop has been requested, mark the pipeline as stopped and + * return. Otherwise restart the pipeline if ready. + */ + if (state == VSP1_PIPELINE_STOPPING) + wake_up(&pipe->wq); + else if (vsp1_pipeline_ready(pipe)) + vsp1_video_pipeline_run(pipe); + + spin_unlock_irqrestore(&pipe->irqlock, flags); } /* ----------------------------------------------------------------------------- @@ -512,20 +553,15 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) if (vb->num_planes < format->num_planes) return -EINVAL; - buf->mem.num_planes = vb->num_planes; - for (i = 0; i < vb->num_planes; ++i) { buf->mem.addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); - buf->mem.length[i] = vb2_plane_size(vb, i); - if (buf->mem.length[i] < format->plane_fmt[i].sizeimage) + if (vb2_plane_size(vb, i) < format->plane_fmt[i].sizeimage) return -EINVAL; } - for ( ; i < 3; ++i) { + for ( ; i < 3; ++i) buf->mem.addr[i] = 0; - buf->mem.length[i] = 0; - } return 0; } @@ -549,54 +585,74 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) spin_lock_irqsave(&pipe->irqlock, flags); - vsp1_rwpf_set_memory(video->rwpf, &buf->mem, true); + video->rwpf->mem = buf->mem; pipe->buffers_ready |= 1 << video->pipe_index; if (vb2_is_streaming(&video->queue) && vsp1_pipeline_ready(pipe)) - vsp1_pipeline_run(pipe); + vsp1_video_pipeline_run(pipe); spin_unlock_irqrestore(&pipe->irqlock, flags); } +static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) +{ + struct vsp1_entity *entity; + int ret; + + /* Prepare the display list. */ + pipe->dl = vsp1_dl_list_get(pipe->output->dlm); + if (!pipe->dl) + return -ENOMEM; + + if (pipe->uds) { + struct vsp1_uds *uds = to_uds(&pipe->uds->subdev); + + /* If a BRU is present in the pipeline before the UDS, the alpha + * component doesn't need to be scaled as the BRU output alpha + * value is fixed to 255. Otherwise we need to scale the alpha + * component only when available at the input RPF. + */ + if (pipe->uds_input->type == VSP1_ENTITY_BRU) { + uds->scale_alpha = false; + } else { + struct vsp1_rwpf *rpf = + to_rwpf(&pipe->uds_input->subdev); + + uds->scale_alpha = rpf->fmtinfo->alpha; + } + } + + list_for_each_entry(entity, &pipe->entities, list_pipe) { + vsp1_entity_route_setup(entity); + + ret = v4l2_subdev_call(&entity->subdev, video, s_stream, 1); + if (ret < 0) + goto error; + } + + return 0; + +error: + vsp1_dl_list_put(pipe->dl); + pipe->dl = NULL; + + return ret; +} + static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) { struct vsp1_video *video = vb2_get_drv_priv(vq); struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); - struct vsp1_entity *entity; unsigned long flags; int ret; mutex_lock(&pipe->lock); if (pipe->stream_count == pipe->num_inputs) { - if (pipe->uds) { - struct vsp1_uds *uds = to_uds(&pipe->uds->subdev); - - /* If a BRU is present in the pipeline before the UDS, - * the alpha component doesn't need to be scaled as the - * BRU output alpha value is fixed to 255. Otherwise we - * need to scale the alpha component only when available - * at the input RPF. - */ - if (pipe->uds_input->type == VSP1_ENTITY_BRU) { - uds->scale_alpha = false; - } else { - struct vsp1_rwpf *rpf = - to_rwpf(&pipe->uds_input->subdev); - - uds->scale_alpha = rpf->fmtinfo->alpha; - } - } - - list_for_each_entry(entity, &pipe->entities, list_pipe) { - vsp1_entity_route_setup(entity); - - ret = v4l2_subdev_call(&entity->subdev, video, - s_stream, 1); - if (ret < 0) { - mutex_unlock(&pipe->lock); - return ret; - } + ret = vsp1_video_setup_pipeline(pipe); + if (ret < 0) { + mutex_unlock(&pipe->lock); + return ret; } } @@ -605,7 +661,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) spin_lock_irqsave(&pipe->irqlock, flags); if (vsp1_pipeline_ready(pipe)) - vsp1_pipeline_run(pipe); + vsp1_video_pipeline_run(pipe); spin_unlock_irqrestore(&pipe->irqlock, flags); return 0; @@ -625,6 +681,9 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) ret = vsp1_pipeline_stop(pipe); if (ret == -ETIMEDOUT) dev_err(video->vsp1->dev, "pipeline stop timeout\n"); + + vsp1_dl_list_put(pipe->dl); + pipe->dl = NULL; } mutex_unlock(&pipe->lock); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index d1fad9effb9b..d889997b7948 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -157,9 +157,9 @@ static struct v4l2_subdev_ops wpf_ops = { static void wpf_set_memory(struct vsp1_rwpf *wpf) { - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->buf_addr[0]); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->buf_addr[1]); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->buf_addr[2]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); } static const struct vsp1_rwpf_operations wpf_vdev_ops = { @@ -200,13 +200,11 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) if (ret < 0) return ERR_PTR(ret); - /* Initialize the display list manager if the WPF is used for display */ - if ((vsp1->info->features & VSP1_HAS_LIF) && index == 0) { - wpf->dlm = vsp1_dlm_create(vsp1, index, 4); - if (!wpf->dlm) { - ret = -ENOMEM; - goto error; - } + /* Initialize the display list manager. */ + wpf->dlm = vsp1_dlm_create(vsp1, index, 4); + if (!wpf->dlm) { + ret = -ENOMEM; + goto error; } /* Initialize the V4L2 subdev. */ -- GitLab From 823329dfee7224712569cc4899720bc470a2fe56 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 15 Nov 2015 19:42:01 -0200 Subject: [PATCH 2573/9938] [media] v4l: vsp1: Move subdev initialization code to vsp1_entity_init() Don't duplicate the code in every module driver, centralize it in a single place. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 18 ++------------ drivers/media/platform/vsp1/vsp1_entity.c | 30 +++++++++++++++++++---- drivers/media/platform/vsp1/vsp1_entity.h | 5 ++-- drivers/media/platform/vsp1/vsp1_hsit.c | 17 ++----------- drivers/media/platform/vsp1/vsp1_lif.c | 16 +----------- drivers/media/platform/vsp1/vsp1_lut.c | 16 +----------- drivers/media/platform/vsp1/vsp1_rpf.c | 18 +++----------- drivers/media/platform/vsp1/vsp1_sru.c | 16 +----------- drivers/media/platform/vsp1/vsp1_uds.c | 18 +++----------- drivers/media/platform/vsp1/vsp1_wpf.c | 18 +++----------- 10 files changed, 43 insertions(+), 129 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 6a6e9d84f1ca..2ca80d3dda1f 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -405,7 +405,6 @@ static struct v4l2_subdev_ops bru_ops = { struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) { - struct v4l2_subdev *subdev; struct vsp1_bru *bru; int ret; @@ -415,24 +414,11 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) bru->entity.type = VSP1_ENTITY_BRU; - ret = vsp1_entity_init(vsp1, &bru->entity, - vsp1->info->num_bru_inputs + 1); + ret = vsp1_entity_init(vsp1, &bru->entity, "bru", + vsp1->info->num_bru_inputs + 1, &bru_ops); if (ret < 0) return ERR_PTR(ret); - /* Initialize the V4L2 subdev. */ - subdev = &bru->entity.subdev; - v4l2_subdev_init(subdev, &bru_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s bru", - dev_name(vsp1->dev)); - v4l2_set_subdevdata(subdev, bru); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - /* Initialize the control handler. */ v4l2_ctrl_handler_init(&bru->ctrls, 1); v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR, diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 7b2301dbd584..8432c49fbd75 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -70,8 +70,8 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity, * formats are initialized on the file handle. Otherwise active formats are * initialized on the device. */ -void vsp1_entity_init_formats(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg) +static void vsp1_entity_init_formats(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg) { struct v4l2_subdev_format format; unsigned int pad; @@ -159,9 +159,12 @@ static const struct vsp1_route vsp1_routes[] = { }; int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, - unsigned int num_pads) + const char *name, unsigned int num_pads, + const struct v4l2_subdev_ops *ops) { + struct v4l2_subdev *subdev; unsigned int i; + int ret; for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) { if (vsp1_routes[i].type == entity->type && @@ -196,8 +199,25 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE; /* Initialize the media entity. */ - return media_entity_pads_init(&entity->subdev.entity, num_pads, - entity->pads); + ret = media_entity_pads_init(&entity->subdev.entity, num_pads, + entity->pads); + if (ret < 0) + return ret; + + /* Initialize the V4L2 subdev. */ + subdev = &entity->subdev; + v4l2_subdev_init(subdev, ops); + + subdev->entity.ops = &vsp1->media_ops; + subdev->internal_ops = &vsp1_subdev_internal_ops; + subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + snprintf(subdev->name, sizeof(subdev->name), "%s %s", + dev_name(vsp1->dev), name); + + vsp1_entity_init_formats(subdev, NULL); + + return 0; } void vsp1_entity_destroy(struct vsp1_entity *entity) diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 203872164f8e..d76090059ced 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -81,7 +81,8 @@ static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) } int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, - unsigned int num_pads); + const char *name, unsigned int num_pads, + const struct v4l2_subdev_ops *ops); void vsp1_entity_destroy(struct vsp1_entity *entity); extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops; @@ -94,8 +95,6 @@ struct v4l2_mbus_framefmt * vsp1_entity_get_pad_format(struct vsp1_entity *entity, struct v4l2_subdev_pad_config *cfg, unsigned int pad, u32 which); -void vsp1_entity_init_formats(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg); void vsp1_entity_route_setup(struct vsp1_entity *source); diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index e820fe0b4f00..49ff74b51e03 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -180,7 +180,6 @@ static struct v4l2_subdev_ops hsit_ops = { struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) { - struct v4l2_subdev *subdev; struct vsp1_hsit *hsit; int ret; @@ -195,22 +194,10 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) else hsit->entity.type = VSP1_ENTITY_HST; - ret = vsp1_entity_init(vsp1, &hsit->entity, 2); + ret = vsp1_entity_init(vsp1, &hsit->entity, inverse ? "hsi" : "hst", 2, + &hsit_ops); if (ret < 0) return ERR_PTR(ret); - /* Initialize the V4L2 subdev. */ - subdev = &hsit->entity.subdev; - v4l2_subdev_init(subdev, &hsit_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s %s", - dev_name(vsp1->dev), inverse ? "hsi" : "hst"); - v4l2_set_subdevdata(subdev, hsit); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - return hsit; } diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index be0ea166016c..ead6cc3aa3fa 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -207,7 +207,6 @@ static struct v4l2_subdev_ops lif_ops = { struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1) { - struct v4l2_subdev *subdev; struct vsp1_lif *lif; int ret; @@ -217,22 +216,9 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1) lif->entity.type = VSP1_ENTITY_LIF; - ret = vsp1_entity_init(vsp1, &lif->entity, 2); + ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 2, &lif_ops); if (ret < 0) return ERR_PTR(ret); - /* Initialize the V4L2 subdev. */ - subdev = &lif->entity.subdev; - v4l2_subdev_init(subdev, &lif_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s lif", - dev_name(vsp1->dev)); - v4l2_set_subdevdata(subdev, lif); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - return lif; } diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 3af849dbee5a..6ba6a58fbac6 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -221,7 +221,6 @@ static struct v4l2_subdev_ops lut_ops = { struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) { - struct v4l2_subdev *subdev; struct vsp1_lut *lut; int ret; @@ -231,22 +230,9 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) lut->entity.type = VSP1_ENTITY_LUT; - ret = vsp1_entity_init(vsp1, &lut->entity, 2); + ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops); if (ret < 0) return ERR_PTR(ret); - /* Initialize the V4L2 subdev. */ - subdev = &lut->entity.subdev; - v4l2_subdev_init(subdev, &lut_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s lut", - dev_name(vsp1->dev)); - v4l2_set_subdevdata(subdev, lut); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - return lut; } diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 09919db7e0ea..8d9e511fd61a 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -164,8 +164,8 @@ static const struct vsp1_rwpf_operations rpf_vdev_ops = { struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) { - struct v4l2_subdev *subdev; struct vsp1_rwpf *rpf; + char name[6]; int ret; rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL); @@ -180,23 +180,11 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) rpf->entity.type = VSP1_ENTITY_RPF; rpf->entity.index = index; - ret = vsp1_entity_init(vsp1, &rpf->entity, 2); + sprintf(name, "rpf.%u", index); + ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops); if (ret < 0) return ERR_PTR(ret); - /* Initialize the V4L2 subdev. */ - subdev = &rpf->entity.subdev; - v4l2_subdev_init(subdev, &rpf_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u", - dev_name(vsp1->dev), index); - v4l2_set_subdevdata(subdev, rpf); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - /* Initialize the control handler. */ ret = vsp1_rwpf_init_ctrls(rpf); if (ret < 0) { diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 19b7923cb137..c8642bf8b1a1 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -324,7 +324,6 @@ static struct v4l2_subdev_ops sru_ops = { struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) { - struct v4l2_subdev *subdev; struct vsp1_sru *sru; int ret; @@ -334,23 +333,10 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) sru->entity.type = VSP1_ENTITY_SRU; - ret = vsp1_entity_init(vsp1, &sru->entity, 2); + ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 2, &sru_ops); if (ret < 0) return ERR_PTR(ret); - /* Initialize the V4L2 subdev. */ - subdev = &sru->entity.subdev; - v4l2_subdev_init(subdev, &sru_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s sru", - dev_name(vsp1->dev)); - v4l2_set_subdevdata(subdev, sru); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - /* Initialize the control handler. */ v4l2_ctrl_handler_init(&sru->ctrls, 1); v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL); diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 83ec8942f8e7..34689adda810 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -322,8 +322,8 @@ static struct v4l2_subdev_ops uds_ops = { struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index) { - struct v4l2_subdev *subdev; struct vsp1_uds *uds; + char name[6]; int ret; uds = devm_kzalloc(vsp1->dev, sizeof(*uds), GFP_KERNEL); @@ -333,22 +333,10 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index) uds->entity.type = VSP1_ENTITY_UDS; uds->entity.index = index; - ret = vsp1_entity_init(vsp1, &uds->entity, 2); + sprintf(name, "uds.%u", index); + ret = vsp1_entity_init(vsp1, &uds->entity, name, 2, &uds_ops); if (ret < 0) return ERR_PTR(ret); - /* Initialize the V4L2 subdev. */ - subdev = &uds->entity.subdev; - v4l2_subdev_init(subdev, &uds_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s uds.%u", - dev_name(vsp1->dev), index); - v4l2_set_subdevdata(subdev, uds); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - return uds; } diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index d889997b7948..b81595eb51dc 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -179,8 +179,8 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity) struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) { - struct v4l2_subdev *subdev; struct vsp1_rwpf *wpf; + char name[6]; int ret; wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); @@ -196,7 +196,8 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) wpf->entity.type = VSP1_ENTITY_WPF; wpf->entity.index = index; - ret = vsp1_entity_init(vsp1, &wpf->entity, 2); + sprintf(name, "wpf.%u", index); + ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops); if (ret < 0) return ERR_PTR(ret); @@ -207,19 +208,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) goto error; } - /* Initialize the V4L2 subdev. */ - subdev = &wpf->entity.subdev; - v4l2_subdev_init(subdev, &wpf_ops); - - subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; - snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u", - dev_name(vsp1->dev), index); - v4l2_set_subdevdata(subdev, wpf); - subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - vsp1_entity_init_formats(subdev, NULL); - /* Initialize the control handler. */ ret = vsp1_rwpf_init_ctrls(wpf); if (ret < 0) { -- GitLab From 5243453472e7bce74764ddf9f206450dcc8769c5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 17 Nov 2015 12:23:23 -0200 Subject: [PATCH 2574/9938] [media] v4l: vsp1: Consolidate entity ops in a struct vsp1_entity_operations Entities have two operations, a destroy operation stored directly in vsp1_entity and a set_memory operation stored in a vsp1_rwpf_operations structure. Move the two to a more generic vsp1_entity_operations structure that will serve to implement additional operations. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_entity.c | 4 ++-- drivers/media/platform/vsp1/vsp1_entity.h | 14 +++++++++++- drivers/media/platform/vsp1/vsp1_rpf.c | 11 ++++----- drivers/media/platform/vsp1/vsp1_rwpf.h | 18 +++++---------- drivers/media/platform/vsp1/vsp1_wpf.c | 27 ++++++++++++----------- 5 files changed, 41 insertions(+), 33 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 8432c49fbd75..2676f6723994 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -222,8 +222,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, void vsp1_entity_destroy(struct vsp1_entity *entity) { - if (entity->destroy) - entity->destroy(entity); + if (entity->ops && entity->ops->destroy) + entity->ops->destroy(entity); if (entity->subdev.ctrl_handler) v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); media_entity_cleanup(&entity->subdev.entity); diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index d76090059ced..0fdda82a8d9a 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -53,10 +53,22 @@ struct vsp1_route { unsigned int inputs[VSP1_ENTITY_MAX_INPUTS]; }; +/** + * struct vsp1_entity_operations - Entity operations + * @destroy: Destroy the entity. + * @set_memory: Setup memory buffer access. This operation applies the settings + * stored in the rwpf mem field to the hardware. Valid for RPF and + * WPF only. + */ +struct vsp1_entity_operations { + void (*destroy)(struct vsp1_entity *); + void (*set_memory)(struct vsp1_entity *); +}; + struct vsp1_entity { struct vsp1_device *vsp1; - void (*destroy)(struct vsp1_entity *); + const struct vsp1_entity_operations *ops; enum vsp1_entity_type type; unsigned int index; diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 8d9e511fd61a..a68f26db9b3f 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -141,11 +141,13 @@ static struct v4l2_subdev_ops rpf_ops = { }; /* ----------------------------------------------------------------------------- - * Video Device Operations + * VSP1 Entity Operations */ -static void rpf_set_memory(struct vsp1_rwpf *rpf) +static void rpf_set_memory(struct vsp1_entity *entity) { + struct vsp1_rwpf *rpf = entity_to_rwpf(entity); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, rpf->mem.addr[0] + rpf->offsets[0]); vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, @@ -154,7 +156,7 @@ static void rpf_set_memory(struct vsp1_rwpf *rpf) rpf->mem.addr[2] + rpf->offsets[1]); } -static const struct vsp1_rwpf_operations rpf_vdev_ops = { +static const struct vsp1_entity_operations rpf_entity_ops = { .set_memory = rpf_set_memory, }; @@ -172,11 +174,10 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) if (rpf == NULL) return ERR_PTR(-ENOMEM); - rpf->ops = &rpf_vdev_ops; - rpf->max_width = RPF_MAX_WIDTH; rpf->max_height = RPF_MAX_HEIGHT; + rpf->entity.ops = &rpf_entity_ops; rpf->entity.type = VSP1_ENTITY_RPF; rpf->entity.index = index; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 2bbcc331959b..e8ca9b6ee689 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -32,23 +32,12 @@ struct vsp1_rwpf_memory { dma_addr_t addr[3]; }; -/** - * struct vsp1_rwpf_operations - RPF and WPF operations - * @set_memory: Setup memory buffer access. This operation applies the settings - * stored in the rwpf mem field to the hardware. - */ -struct vsp1_rwpf_operations { - void (*set_memory)(struct vsp1_rwpf *rwpf); -}; - struct vsp1_rwpf { struct vsp1_entity entity; struct v4l2_ctrl_handler ctrls; struct vsp1_video *video; - const struct vsp1_rwpf_operations *ops; - unsigned int max_width; unsigned int max_height; @@ -73,6 +62,11 @@ static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) return container_of(subdev, struct vsp1_rwpf, entity.subdev); } +static inline struct vsp1_rwpf *entity_to_rwpf(struct vsp1_entity *entity) +{ + return container_of(entity, struct vsp1_rwpf, entity); +} + struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); @@ -105,7 +99,7 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, */ static inline void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf) { - rwpf->ops->set_memory(rwpf); + rwpf->entity.ops->set_memory(&rwpf->entity); } #endif /* __VSP1_RWPF_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index b81595eb51dc..84772fa258a5 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -152,17 +152,27 @@ static struct v4l2_subdev_ops wpf_ops = { }; /* ----------------------------------------------------------------------------- - * Video Device Operations + * VSP1 Entity Operations */ -static void wpf_set_memory(struct vsp1_rwpf *wpf) +static void vsp1_wpf_destroy(struct vsp1_entity *entity) { + struct vsp1_rwpf *wpf = entity_to_rwpf(entity); + + vsp1_dlm_destroy(wpf->dlm); +} + +static void wpf_set_memory(struct vsp1_entity *entity) +{ + struct vsp1_rwpf *wpf = entity_to_rwpf(entity); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); } -static const struct vsp1_rwpf_operations wpf_vdev_ops = { +static const struct vsp1_entity_operations wpf_entity_ops = { + .destroy = vsp1_wpf_destroy, .set_memory = wpf_set_memory, }; @@ -170,13 +180,6 @@ static const struct vsp1_rwpf_operations wpf_vdev_ops = { * Initialization and Cleanup */ -static void vsp1_wpf_destroy(struct vsp1_entity *entity) -{ - struct vsp1_rwpf *wpf = container_of(entity, struct vsp1_rwpf, entity); - - vsp1_dlm_destroy(wpf->dlm); -} - struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) { struct vsp1_rwpf *wpf; @@ -187,12 +190,10 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) if (wpf == NULL) return ERR_PTR(-ENOMEM); - wpf->ops = &wpf_vdev_ops; - wpf->max_width = WPF_MAX_WIDTH; wpf->max_height = WPF_MAX_HEIGHT; - wpf->entity.destroy = vsp1_wpf_destroy; + wpf->entity.ops = &wpf_entity_ops; wpf->entity.type = VSP1_ENTITY_WPF; wpf->entity.index = index; -- GitLab From 21b3d7365f4fa7865568823ba844ce056c1fcf9b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 15 Nov 2015 21:51:01 -0200 Subject: [PATCH 2575/9938] [media] v4l: vsp1: Fix BRU try compose rectangle storage Fix a typo that stored the try compose rectangle in the crop rectangle. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 2ca80d3dda1f..d8b7bdeb5af5 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -228,7 +228,8 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, { switch (which) { case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_crop(&bru->entity.subdev, cfg, pad); + return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, + pad); case V4L2_SUBDEV_FORMAT_ACTIVE: return &bru->inputs[pad].compose; default: -- GitLab From 613721265ab8d3df784488e3073d92fcb466df34 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 5 Nov 2015 10:28:56 -0200 Subject: [PATCH 2576/9938] [media] v4l: vsp1: Add race condition FIXME comment Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 7cb270f57f62..102977ae1daa 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -813,6 +813,9 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) * * Use the VSP1 pipeline object embedded in the first video object that * starts streaming. + * + * FIXME: This is racy, the ioctl is only protected by the video node + * lock. */ pipe = video->video.entity.pipe ? to_vsp1_pipeline(&video->video.entity) : &video->pipe; -- GitLab From 0efdf0f5eaaff6c18d1e645a8e1fdebf73400fe1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 15 Nov 2015 20:09:08 -0200 Subject: [PATCH 2577/9938] [media] v4l: vsp1: Implement and use the subdev pad::init_cfg configuration Turn the custom formats initialization function into a standard pad::init_cfg handler and use it in subdevs instead of initializing formats in the subdev open handler. This makes the subdev open handler empty, so remove it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 1 + drivers/media/platform/vsp1/vsp1_entity.c | 24 ++++++----------------- drivers/media/platform/vsp1/vsp1_entity.h | 2 ++ drivers/media/platform/vsp1/vsp1_hsit.c | 1 + drivers/media/platform/vsp1/vsp1_lif.c | 1 + drivers/media/platform/vsp1/vsp1_lut.c | 1 + drivers/media/platform/vsp1/vsp1_rpf.c | 1 + drivers/media/platform/vsp1/vsp1_sru.c | 1 + drivers/media/platform/vsp1/vsp1_uds.c | 1 + drivers/media/platform/vsp1/vsp1_wpf.c | 1 + 10 files changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index d8b7bdeb5af5..879dc9c9d3f0 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -387,6 +387,7 @@ static struct v4l2_subdev_video_ops bru_video_ops = { }; static struct v4l2_subdev_pad_ops bru_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = bru_enum_mbus_code, .enum_frame_size = bru_enum_frame_size, .get_fmt = bru_get_format, diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 2676f6723994..5423e29e0d49 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -62,16 +62,15 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity, } /* - * vsp1_entity_init_formats - Initialize formats on all pads + * vsp1_entity_init_cfg - Initialize formats on all pads * @subdev: V4L2 subdevice * @cfg: V4L2 subdev pad configuration * - * Initialize all pad formats with default values. If cfg is not NULL, try - * formats are initialized on the file handle. Otherwise active formats are - * initialized on the device. + * Initialize all pad formats with default values in the given pad config. This + * function can be used as a handler for the subdev pad::init_cfg operation. */ -static void vsp1_entity_init_formats(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg) +int vsp1_entity_init_cfg(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg) { struct v4l2_subdev_format format; unsigned int pad; @@ -85,20 +84,10 @@ static void vsp1_entity_init_formats(struct v4l2_subdev *subdev, v4l2_subdev_call(subdev, pad, set_fmt, cfg, &format); } -} - -static int vsp1_entity_open(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh) -{ - vsp1_entity_init_formats(subdev, fh->pad); return 0; } -const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops = { - .open = vsp1_entity_open, -}; - /* ----------------------------------------------------------------------------- * Media Operations */ @@ -209,13 +198,12 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, v4l2_subdev_init(subdev, ops); subdev->entity.ops = &vsp1->media_ops; - subdev->internal_ops = &vsp1_subdev_internal_ops; subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(subdev->name, sizeof(subdev->name), "%s %s", dev_name(vsp1->dev), name); - vsp1_entity_init_formats(subdev, NULL); + vsp1_entity_init_cfg(subdev, NULL); return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 0fdda82a8d9a..8e6cf776e990 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -107,6 +107,8 @@ struct v4l2_mbus_framefmt * vsp1_entity_get_pad_format(struct vsp1_entity *entity, struct v4l2_subdev_pad_config *cfg, unsigned int pad, u32 which); +int vsp1_entity_init_cfg(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg); void vsp1_entity_route_setup(struct vsp1_entity *source); diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 49ff74b51e03..3e36755c8c2a 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -163,6 +163,7 @@ static struct v4l2_subdev_video_ops hsit_video_ops = { }; static struct v4l2_subdev_pad_ops hsit_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = hsit_enum_mbus_code, .enum_frame_size = hsit_enum_frame_size, .get_fmt = hsit_get_format, diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index ead6cc3aa3fa..5edf6a742c5b 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -190,6 +190,7 @@ static struct v4l2_subdev_video_ops lif_video_ops = { }; static struct v4l2_subdev_pad_ops lif_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = lif_enum_mbus_code, .enum_frame_size = lif_enum_frame_size, .get_fmt = lif_get_format, diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 6ba6a58fbac6..f0afc4291387 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -203,6 +203,7 @@ static struct v4l2_subdev_video_ops lut_video_ops = { }; static struct v4l2_subdev_pad_ops lut_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = lut_enum_mbus_code, .enum_frame_size = lut_enum_frame_size, .get_fmt = lut_get_format, diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index a68f26db9b3f..69fd76eed0bb 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -127,6 +127,7 @@ static struct v4l2_subdev_video_ops rpf_video_ops = { }; static struct v4l2_subdev_pad_ops rpf_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = vsp1_rwpf_enum_mbus_code, .enum_frame_size = vsp1_rwpf_enum_frame_size, .get_fmt = vsp1_rwpf_get_format, diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index c8642bf8b1a1..043dac6644c1 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -307,6 +307,7 @@ static struct v4l2_subdev_video_ops sru_video_ops = { }; static struct v4l2_subdev_pad_ops sru_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = sru_enum_mbus_code, .enum_frame_size = sru_enum_frame_size, .get_fmt = sru_get_format, diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 34689adda810..666fabcd0382 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -305,6 +305,7 @@ static struct v4l2_subdev_video_ops uds_video_ops = { }; static struct v4l2_subdev_pad_ops uds_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = uds_enum_mbus_code, .enum_frame_size = uds_enum_frame_size, .get_fmt = uds_get_format, diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 84772fa258a5..d46910db7e08 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -138,6 +138,7 @@ static struct v4l2_subdev_video_ops wpf_video_ops = { }; static struct v4l2_subdev_pad_ops wpf_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = vsp1_rwpf_enum_mbus_code, .enum_frame_size = vsp1_rwpf_enum_frame_size, .get_fmt = vsp1_rwpf_get_format, -- GitLab From d549df4b225ad2386cbf59254eab2ec116babdca Mon Sep 17 00:00:00 2001 From: Yakir Yang Date: Mon, 14 Mar 2016 11:11:42 +0800 Subject: [PATCH 2578/9938] ARM: dts: rockchip: add i2c nodes for RK3228 SoCs This patch add the i2c dt nodes for rk3228 SoCs. Signed-off-by: Yakir Yang Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3228.dtsi | 80 +++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/arch/arm/boot/dts/rk3228.dtsi b/arch/arm/boot/dts/rk3228.dtsi index f9c34124ccc3..e23a22e29155 100644 --- a/arch/arm/boot/dts/rk3228.dtsi +++ b/arch/arm/boot/dts/rk3228.dtsi @@ -187,6 +187,58 @@ status = "disabled"; }; + i2c0: i2c@11050000 { + compatible = "rockchip,rk3228-i2c"; + reg = <0x11050000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_xfer>; + status = "disabled"; + }; + + i2c1: i2c@11060000 { + compatible = "rockchip,rk3228-i2c"; + reg = <0x11060000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C1>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_xfer>; + status = "disabled"; + }; + + i2c2: i2c@11070000 { + compatible = "rockchip,rk3228-i2c"; + reg = <0x11070000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C2>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_xfer>; + status = "disabled"; + }; + + i2c3: i2c@11080000 { + compatible = "rockchip,rk3228-i2c"; + reg = <0x11080000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "i2c"; + clocks = <&cru PCLK_I2C3>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_xfer>; + status = "disabled"; + }; + pwm0: pwm@110b0000 { compatible = "rockchip,rk3288-pwm"; reg = <0x110b0000 0x10>; @@ -429,6 +481,34 @@ }; }; + i2c0 { + i2c0_xfer: i2c0-xfer { + rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>, + <0 1 RK_FUNC_1 &pcfg_pull_none>; + }; + }; + + i2c1 { + i2c1_xfer: i2c1-xfer { + rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_none>, + <0 3 RK_FUNC_1 &pcfg_pull_none>; + }; + }; + + i2c2 { + i2c2_xfer: i2c2-xfer { + rockchip,pins = <2 20 RK_FUNC_1 &pcfg_pull_none>, + <2 21 RK_FUNC_1 &pcfg_pull_none>; + }; + }; + + i2c3 { + i2c3_xfer: i2c3-xfer { + rockchip,pins = <0 6 RK_FUNC_1 &pcfg_pull_none>, + <0 7 RK_FUNC_1 &pcfg_pull_none>; + }; + }; + pwm0 { pwm0_pin: pwm0-pin { rockchip,pins = <3 21 RK_FUNC_1 &pcfg_pull_none>; -- GitLab From f971512c78ee675c0308f1cda483a57e5de6769f Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 31 Mar 2016 16:58:33 -0500 Subject: [PATCH 2579/9938] ARM: OMAP: DRA7: powerdomain data: Erratum i892 workaround: Disable core INA Erratum i892 as will be documented in the upcoming G or later revision of DRA7xx/ AM57xx errata documentation (SPRZ398F) states that L3 clock needs to be kept active all the time to ensure that asymmetric aging degradation is minimal and within the design allowed margin. By allowing core domain to transition to INA and allowing L3 clock to be turned off for extended periods of time, there is a risk of functional issues and device failure as a result. Ref: http://www.ti.com/lit/er/sprz429h/sprz429h.pdf Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/powerdomains7xx_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c index 287a2037aa16..f2b4557124f3 100644 --- a/arch/arm/mach-omap2/powerdomains7xx_data.c +++ b/arch/arm/mach-omap2/powerdomains7xx_data.c @@ -160,7 +160,7 @@ static struct powerdomain core_7xx_pwrdm = { .name = "core_pwrdm", .prcm_offs = DRA7XX_PRM_CORE_INST, .prcm_partition = DRA7XX_PRM_PARTITION, - .pwrsts = PWRSTS_INA_ON, + .pwrsts = PWRSTS_ON, .pwrsts_logic_ret = PWRSTS_RET, .banks = 5, .pwrsts_mem_ret = { -- GitLab From 41feb8efd636c99ff73a2e6b8b4a57e2dd569b4b Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 31 Mar 2016 16:58:34 -0500 Subject: [PATCH 2580/9938] ARM: OMAP: DRA7: powerdomain data: Fix "ON" state for memories When the power domain is in "ON" state, the memories should be always in "ON", even though the hardware register allows other states to be written, wrong states may confuse certain hardware blocks. Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/powerdomains7xx_data.c | 66 +++++++++++----------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c index f2b4557124f3..81e883d972b9 100644 --- a/arch/arm/mach-omap2/powerdomains7xx_data.c +++ b/arch/arm/mach-omap2/powerdomains7xx_data.c @@ -45,10 +45,10 @@ static struct powerdomain iva_7xx_pwrdm = { [3] = PWRSTS_OFF_RET, /* tcm2_mem */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* hwa_mem */ - [1] = PWRSTS_OFF_RET, /* sl2_mem */ - [2] = PWRSTS_OFF_RET, /* tcm1_mem */ - [3] = PWRSTS_OFF_RET, /* tcm2_mem */ + [0] = PWRSTS_ON, /* hwa_mem */ + [1] = PWRSTS_ON, /* sl2_mem */ + [2] = PWRSTS_ON, /* tcm1_mem */ + [3] = PWRSTS_ON, /* tcm2_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -83,8 +83,8 @@ static struct powerdomain ipu_7xx_pwrdm = { [1] = PWRSTS_OFF_RET, /* periphmem */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* aessmem */ - [1] = PWRSTS_OFF_RET, /* periphmem */ + [0] = PWRSTS_ON, /* aessmem */ + [1] = PWRSTS_ON, /* periphmem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -101,7 +101,7 @@ static struct powerdomain dss_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* dss_mem */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* dss_mem */ + [0] = PWRSTS_ON, /* dss_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -119,8 +119,8 @@ static struct powerdomain l4per_7xx_pwrdm = { [1] = PWRSTS_OFF_RET, /* retained_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* nonretained_bank */ - [1] = PWRSTS_OFF_RET, /* retained_bank */ + [0] = PWRSTS_ON, /* nonretained_bank */ + [1] = PWRSTS_ON, /* retained_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -136,7 +136,7 @@ static struct powerdomain gpu_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* gpu_mem */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* gpu_mem */ + [0] = PWRSTS_ON, /* gpu_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -171,11 +171,11 @@ static struct powerdomain core_7xx_pwrdm = { [4] = PWRSTS_OFF_RET, /* ipu_unicache */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* core_nret_bank */ - [1] = PWRSTS_OFF_RET, /* core_ocmram */ - [2] = PWRSTS_OFF_RET, /* core_other_bank */ - [3] = PWRSTS_OFF_RET, /* ipu_l2ram */ - [4] = PWRSTS_OFF_RET, /* ipu_unicache */ + [0] = PWRSTS_ON, /* core_nret_bank */ + [1] = PWRSTS_ON, /* core_ocmram */ + [2] = PWRSTS_ON, /* core_other_bank */ + [3] = PWRSTS_ON, /* ipu_l2ram */ + [4] = PWRSTS_ON, /* ipu_unicache */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -232,7 +232,7 @@ static struct powerdomain vpe_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* vpe_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* vpe_bank */ + [0] = PWRSTS_ON, /* vpe_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -250,8 +250,8 @@ static struct powerdomain mpu_7xx_pwrdm = { [1] = PWRSTS_RET, /* mpu_ram */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* mpu_l2 */ - [1] = PWRSTS_OFF_RET, /* mpu_ram */ + [0] = PWRSTS_ON, /* mpu_l2 */ + [1] = PWRSTS_ON, /* mpu_ram */ }, }; @@ -269,9 +269,9 @@ static struct powerdomain l3init_7xx_pwrdm = { [2] = PWRSTS_OFF_RET, /* l3init_bank2 */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* gmac_bank */ - [1] = PWRSTS_OFF_RET, /* l3init_bank1 */ - [2] = PWRSTS_OFF_RET, /* l3init_bank2 */ + [0] = PWRSTS_ON, /* gmac_bank */ + [1] = PWRSTS_ON, /* l3init_bank1 */ + [2] = PWRSTS_ON, /* l3init_bank2 */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -287,7 +287,7 @@ static struct powerdomain eve3_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* eve3_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* eve3_bank */ + [0] = PWRSTS_ON, /* eve3_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -303,7 +303,7 @@ static struct powerdomain emu_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* emu_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* emu_bank */ + [0] = PWRSTS_ON, /* emu_bank */ }, }; @@ -320,9 +320,9 @@ static struct powerdomain dsp2_7xx_pwrdm = { [2] = PWRSTS_OFF_RET, /* dsp2_l2 */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* dsp2_edma */ - [1] = PWRSTS_OFF_RET, /* dsp2_l1 */ - [2] = PWRSTS_OFF_RET, /* dsp2_l2 */ + [0] = PWRSTS_ON, /* dsp2_edma */ + [1] = PWRSTS_ON, /* dsp2_l1 */ + [2] = PWRSTS_ON, /* dsp2_l2 */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -340,9 +340,9 @@ static struct powerdomain dsp1_7xx_pwrdm = { [2] = PWRSTS_OFF_RET, /* dsp1_l2 */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* dsp1_edma */ - [1] = PWRSTS_OFF_RET, /* dsp1_l1 */ - [2] = PWRSTS_OFF_RET, /* dsp1_l2 */ + [0] = PWRSTS_ON, /* dsp1_edma */ + [1] = PWRSTS_ON, /* dsp1_l1 */ + [2] = PWRSTS_ON, /* dsp1_l2 */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -358,7 +358,7 @@ static struct powerdomain cam_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* vip_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* vip_bank */ + [0] = PWRSTS_ON, /* vip_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -374,7 +374,7 @@ static struct powerdomain eve4_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* eve4_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* eve4_bank */ + [0] = PWRSTS_ON, /* eve4_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -390,7 +390,7 @@ static struct powerdomain eve2_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* eve2_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* eve2_bank */ + [0] = PWRSTS_ON, /* eve2_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -406,7 +406,7 @@ static struct powerdomain eve1_7xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* eve1_bank */ }, .pwrsts_mem_on = { - [0] = PWRSTS_OFF_RET, /* eve1_bank */ + [0] = PWRSTS_ON, /* eve1_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; -- GitLab From dac4fba2cd8b34e175e54e4740816a1a4de3dcc9 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 31 Mar 2016 16:58:35 -0500 Subject: [PATCH 2581/9938] ARM: OMAP: DRA7: powerdomain data: Remove wrong OSWR capability Open Switch Retention(OSWR) is a retention state which is unsupported in DRA7 SoC. This state is achieved when power state is set to retention and logic power state is set to OFF. Even though DRA7 architecture is a OMAP derivative, none of the powerdomains are actually implemented to achieve OSWR in the SoC. Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/powerdomains7xx_data.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c index 81e883d972b9..0ec2d00f4237 100644 --- a/arch/arm/mach-omap2/powerdomains7xx_data.c +++ b/arch/arm/mach-omap2/powerdomains7xx_data.c @@ -35,7 +35,7 @@ static struct powerdomain iva_7xx_pwrdm = { .name = "iva_pwrdm", .prcm_offs = DRA7XX_PRM_IVA_INST, .prcm_partition = DRA7XX_PRM_PARTITION, - .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts = PWRSTS_OFF_ON, .pwrsts_logic_ret = PWRSTS_OFF, .banks = 4, .pwrsts_mem_ret = { @@ -75,7 +75,7 @@ static struct powerdomain ipu_7xx_pwrdm = { .name = "ipu_pwrdm", .prcm_offs = DRA7XX_PRM_IPU_INST, .prcm_partition = DRA7XX_PRM_PARTITION, - .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts = PWRSTS_OFF_ON, .pwrsts_logic_ret = PWRSTS_OFF, .banks = 2, .pwrsts_mem_ret = { @@ -94,7 +94,7 @@ static struct powerdomain dss_7xx_pwrdm = { .name = "dss_pwrdm", .prcm_offs = DRA7XX_PRM_DSS_INST, .prcm_partition = DRA7XX_PRM_PARTITION, - .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts = PWRSTS_OFF_ON, .pwrsts_logic_ret = PWRSTS_OFF, .banks = 1, .pwrsts_mem_ret = { @@ -112,7 +112,7 @@ static struct powerdomain l4per_7xx_pwrdm = { .prcm_offs = DRA7XX_PRM_L4PER_INST, .prcm_partition = DRA7XX_PRM_PARTITION, .pwrsts = PWRSTS_RET_ON, - .pwrsts_logic_ret = PWRSTS_OFF_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 2, .pwrsts_mem_ret = { [0] = PWRSTS_OFF_RET, /* nonretained_bank */ @@ -225,8 +225,8 @@ static struct powerdomain vpe_7xx_pwrdm = { .name = "vpe_pwrdm", .prcm_offs = DRA7XX_PRM_VPE_INST, .prcm_partition = DRA7XX_PRM_PARTITION, - .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRSTS_OFF_RET, + .pwrsts = PWRSTS_OFF_ON, + .pwrsts_logic_ret = PWRSTS_OFF, .banks = 1, .pwrsts_mem_ret = { [0] = PWRSTS_OFF_RET, /* vpe_bank */ @@ -261,7 +261,7 @@ static struct powerdomain l3init_7xx_pwrdm = { .prcm_offs = DRA7XX_PRM_L3INIT_INST, .prcm_partition = DRA7XX_PRM_PARTITION, .pwrsts = PWRSTS_RET_ON, - .pwrsts_logic_ret = PWRSTS_OFF_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 3, .pwrsts_mem_ret = { [0] = PWRSTS_OFF_RET, /* gmac_bank */ -- GitLab From 814a9586fdeb8cce4f6661288fada4a6ae94a94f Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Mon, 4 Apr 2016 14:55:17 +0200 Subject: [PATCH 2582/9938] ARM: OMAP2+: wakeupgen: Add comment for unhandled FROZEN transitions FROZEN hotplug notifiers are not handled and do not have to be. Insert a comment to remember that the lack of the FROZEN transitions is no accident. Cc: Tony Lindgren Cc: Santosh Shilimkar Cc: linux-omap@vger.kernel.org Signed-off-by: Anna-Maria Gleixner Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap-wakeupgen.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index f397bd6bd6e3..f436ccb6137b 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -320,6 +320,11 @@ static int irq_cpu_hotplug_notify(struct notifier_block *self, { unsigned int cpu = (unsigned int)hcpu; + /* + * Corresponding FROZEN transitions do not have to be handled, + * they are handled by at a higher level + * (drivers/cpuidle/coupled.c). + */ switch (action) { case CPU_ONLINE: wakeupgen_irqmask_all(cpu, 0); -- GitLab From 7e09d775e8fd2f08fe6dc92691c3fceab561074d Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Wed, 23 Mar 2016 09:04:14 +0530 Subject: [PATCH 2583/9938] ARM: omap2plus_defconfig: Enable GPIO_TPIC2810 Enable the TI TPIC2810 8-Bit LED Driver with I2C Interface. This is used in AM335x ICEv2 Boards. Signed-off-by: Lokesh Vutla Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 156bc88b8523..b4f17a4c8b24 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -245,6 +245,7 @@ CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_PCA953X=m CONFIG_GPIO_PCF857X=y +CONFIG_GPIO_TPIC2810=m CONFIG_GPIO_TWL4030=y CONFIG_GPIO_PALMAS=y CONFIG_W1=m -- GitLab From 73489eead20520d5de6dee3527b9a6d0435611c1 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 24 Mar 2016 17:52:49 -0500 Subject: [PATCH 2584/9938] ARM: omap2plus_defconfig: Enable DP83867 support Enable DP83867 Ethernet phy for supporting networking on DRA72-EVM rev C (SR2.0). Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index b4f17a4c8b24..c61fb57fc363 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -178,6 +178,7 @@ CONFIG_TI_CPTS=y # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_AT803X_PHY=y CONFIG_SMSC_PHY=y +CONFIG_DP83867_PHY=y CONFIG_USB_USBNET=m CONFIG_USB_NET_SMSC75XX=m CONFIG_USB_NET_SMSC95XX=m -- GitLab From df4b461dcce518e39136cdd7ea6d32188c85146a Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Fri, 8 Apr 2016 12:11:59 +0200 Subject: [PATCH 2585/9938] ARM: omap2plus_defconfig: Enable MDIO Bus/PHY emulation support MDIO Bus/PHY emulation with fixed speed/link PHYs will be used in Baltos iR5221 devices to connect to ICPlus IP175D switch IC. Signed-off-by: Yegor Yefremov Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c61fb57fc363..c48404c7bce5 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -178,6 +178,7 @@ CONFIG_TI_CPTS=y # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_AT803X_PHY=y CONFIG_SMSC_PHY=y +CONFIG_FIXED_PHY=y CONFIG_DP83867_PHY=y CONFIG_USB_USBNET=m CONFIG_USB_NET_SMSC75XX=m -- GitLab From 0eafc36b7bb23d8be56b73f91a474028ef3e693d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 13 Apr 2016 14:39:45 -0700 Subject: [PATCH 2586/9938] ARM: omap2plus_defconfig: Update with make savedefconfig This shrinks the defconfig a bit and makes it easier to generate minimal patches against it. Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 61 +++++++++++----------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c48404c7bce5..9edf8a493f07 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -10,18 +10,17 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 CONFIG_CGROUPS=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CPUSETS=y -CONFIG_CGROUP_CPUACCT=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y -CONFIG_MEMCG_KMEM=y -CONFIG_CGROUP_PERF=y +CONFIG_BLK_CGROUP=y CONFIG_CGROUP_SCHED=y CONFIG_CFS_BANDWIDTH=y CONFIG_RT_GROUP_SCHED=y -CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y CONFIG_NAMESPACES=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y @@ -50,7 +49,6 @@ CONFIG_SOC_AM33XX=y CONFIG_SOC_AM43XX=y CONFIG_SOC_DRA7XX=y CONFIG_ARM_THUMBEE=y -CONFIG_ARM_KERNMEM_PERMS=y CONFIG_ARM_ERRATA_411920=y CONFIG_ARM_ERRATA_430973=y CONFIG_SMP=y @@ -69,7 +67,7 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT=m # CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set CONFIG_CPU_IDLE=y CONFIG_BINFMT_MISC=y @@ -86,7 +84,6 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y CONFIG_IP_PNP_RARP=y -# CONFIG_INET_LRO is not set CONFIG_NETFILTER=y CONFIG_PHONET=m CONFIG_CAN=m @@ -102,19 +99,18 @@ CONFIG_BT_HIDP=m CONFIG_BT_HCIBTUSB=m CONFIG_BT_HCIBTSDIO=m CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_BCSP=y CONFIG_BT_HCIUART_LL=y CONFIG_BT_HCIUART_3WIRE=y CONFIG_BT_HCIBCM203X=m CONFIG_BT_HCIBPA10X=m -CONFIG_CFG80211=m CONFIG_BT_HCIBFUSB=m CONFIG_BT_HCIVHCI=m CONFIG_BT_MRVL=m CONFIG_BT_MRVL_SDIO=m CONFIG_AF_RXRPC=m CONFIG_RXKAD=m +CONFIG_CFG80211=m CONFIG_MAC80211=m CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -129,6 +125,7 @@ CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_M25P80=m CONFIG_MTD_NAND=y CONFIG_MTD_NAND_ECC_BCH=y CONFIG_MTD_NAND_OMAP2=y @@ -136,9 +133,8 @@ CONFIG_MTD_NAND_OMAP_BCH=y CONFIG_MTD_ONENAND=y CONFIG_MTD_ONENAND_VERIFY_WRITE=y CONFIG_MTD_ONENAND_OMAP2=y -CONFIG_MTD_UBI=y CONFIG_MTD_SPI_NOR=m -CONFIG_MTD_M25P80=m +CONFIG_MTD_UBI=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=16384 @@ -178,30 +174,25 @@ CONFIG_TI_CPTS=y # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_AT803X_PHY=y CONFIG_SMSC_PHY=y -CONFIG_FIXED_PHY=y -CONFIG_DP83867_PHY=y CONFIG_USB_USBNET=m CONFIG_USB_NET_SMSC75XX=m CONFIG_USB_NET_SMSC95XX=m CONFIG_USB_ALI_M5632=y CONFIG_USB_AN2720=y CONFIG_USB_EPSON2888=y -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_OHCI_HCD=m CONFIG_USB_KC2190=y CONFIG_USB_CDC_PHONET=m CONFIG_LIBERTAS=m CONFIG_LIBERTAS_USB=m CONFIG_LIBERTAS_SDIO=m CONFIG_LIBERTAS_DEBUG=y -CONFIG_WL_TI=y +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_USB=m CONFIG_WL12XX=m CONFIG_WL18XX=m CONFIG_WLCORE_SPI=m CONFIG_WLCORE_SDIO=m -CONFIG_MWIFIEX=m -CONFIG_MWIFIEX_SDIO=m -CONFIG_MWIFIEX_USB=m CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=m CONFIG_KEYBOARD_ATKBD=m @@ -213,10 +204,10 @@ CONFIG_KEYBOARD_TWL4030=m CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ADS7846=m CONFIG_TOUCHSCREEN_EDT_FT5X06=m +CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m CONFIG_TOUCHSCREEN_PIXCIR=m CONFIG_TOUCHSCREEN_TSC2005=m CONFIG_TOUCHSCREEN_TSC2007=m -CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m CONFIG_INPUT_MISC=y CONFIG_INPUT_TPS65218_PWRBUTTON=m CONFIG_INPUT_TWL4030_PWRBUTTON=m @@ -240,16 +231,14 @@ CONFIG_SPI_OMAP24XX=y CONFIG_SPI_TI_QSPI=m CONFIG_HSI=m CONFIG_OMAP_SSI=m -CONFIG_NOKIA_MODEM=m CONFIG_SSI_PROTOCOL=m CONFIG_PINCTRL_SINGLE=y CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_PCA953X=m CONFIG_GPIO_PCF857X=y -CONFIG_GPIO_TPIC2810=m -CONFIG_GPIO_TWL4030=y CONFIG_GPIO_PALMAS=y +CONFIG_GPIO_TWL4030=y CONFIG_W1=m CONFIG_HDQ_MASTER_OMAP=m CONFIG_BATTERY_BQ27XXX=m @@ -276,11 +265,11 @@ CONFIG_DRA752_THERMAL=y CONFIG_WATCHDOG=y CONFIG_OMAP_WATCHDOG=m CONFIG_TWL4030_WATCHDOG=m +CONFIG_MFD_TI_AM335X_TSCADC=m CONFIG_MFD_PALMAS=y CONFIG_MFD_TPS65217=y CONFIG_MFD_TPS65218=y CONFIG_MFD_TPS65910=y -CONFIG_MFD_TI_AM335X_TSCADC=m CONFIG_TWL6040_CORE=y CONFIG_REGULATOR_LP872X=y CONFIG_REGULATOR_PALMAS=y @@ -305,10 +294,10 @@ CONFIG_FB=y CONFIG_FIRMWARE_EDID=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y +CONFIG_FB_OMAP2=m CONFIG_FB_OMAP5_DSS_HDMI=y CONFIG_FB_OMAP2_DSS_SDI=y CONFIG_FB_OMAP2_DSS_DSI=y -CONFIG_FB_OMAP2=m CONFIG_FB_OMAP2_ENCODER_TFP410=m CONFIG_FB_OMAP2_ENCODER_TPD12S015=m CONFIG_FB_OMAP2_CONNECTOR_DVI=m @@ -344,13 +333,11 @@ CONFIG_SND_USB_AUDIO=m CONFIG_SND_SOC=m CONFIG_SND_EDMA_SOC=m CONFIG_SND_AM33XX_SOC_EVM=m -CONFIG_SND_DAVINCI_SOC_MCASP=m CONFIG_SND_OMAP_SOC=m CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m CONFIG_SND_SIMPLE_CARD=m -CONFIG_SND_SOC_TLV320AIC3X=m CONFIG_HID_GENERIC=m CONFIG_USB_HIDDEV=y CONFIG_USB_KBD=m @@ -359,6 +346,8 @@ CONFIG_USB=m CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_MON=m CONFIG_USB_XHCI_HCD=m +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_OHCI_HCD=m CONFIG_USB_WDM=m CONFIG_USB_STORAGE=m CONFIG_USB_MUSB_HDRC=m @@ -405,8 +394,8 @@ CONFIG_MMC_OMAP_HS=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=m CONFIG_LEDS_GPIO=m -CONFIG_LEDS_PWM=m CONFIG_LEDS_PCA963X=m +CONFIG_LEDS_PWM=m CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_ONESHOT=m @@ -417,18 +406,17 @@ CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=m -CONFIG_RTC_DRV_PALMAS=m CONFIG_RTC_DRV_TWL92330=y CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_DRV_PALMAS=m CONFIG_RTC_DRV_OMAP=m CONFIG_DMADEVICES=y -CONFIG_TI_EDMA=y CONFIG_DMA_OMAP=y -CONFIG_IOMMU_SUPPORT=y +CONFIG_TI_EDMA=y CONFIG_OMAP_IOMMU=y CONFIG_EXTCON=m -CONFIG_EXTCON_USB_GPIO=m CONFIG_EXTCON_PALMAS=m +CONFIG_EXTCON_USB_GPIO=m CONFIG_TI_EMIF=m CONFIG_IIO=m CONFIG_TI_AM335X_ADC=m @@ -443,8 +431,6 @@ CONFIG_TI_PIPE3=y CONFIG_TWL4030_USB=m CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y CONFIG_FANOTIFY=y CONFIG_QUOTA=y CONFIG_QFMT_V2=y @@ -479,7 +465,6 @@ CONFIG_PROVE_LOCKING=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_SECURITY=y CONFIG_CRYPTO_MICHAEL_MIC=y -# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRC_CCITT=y CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=y -- GitLab From 7d45a04cbc2683f9552572850f1c711d9b96dd26 Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Wed, 13 Apr 2016 11:45:47 -0400 Subject: [PATCH 2587/9938] tipc: remove remnants of old broadcast code We remove a couple of leftover fields in struct tipc_bearer. Those were used by the old broadcast implementation, and are not needed any longer. There is no functional changes in this commit. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/bearer.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index e31820516774..f686e41b5abb 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -42,8 +42,6 @@ #include #define MAX_MEDIA 3 -#define MAX_NODES 4096 -#define WSIZE 32 /* Identifiers associated with TIPC message header media address info * - address info field is 32 bytes long @@ -61,16 +59,6 @@ #define TIPC_MEDIA_TYPE_IB 2 #define TIPC_MEDIA_TYPE_UDP 3 -/** - * struct tipc_node_map - set of node identifiers - * @count: # of nodes in set - * @map: bitmap of node identifiers that are in the set - */ -struct tipc_node_map { - u32 count; - u32 map[MAX_NODES / WSIZE]; -}; - /** * struct tipc_media_addr - destination address used by TIPC bearers * @value: address info (format defined by media) @@ -142,7 +130,6 @@ struct tipc_media { * @identity: array index of this bearer within TIPC bearer array * @link_req: ptr to (optional) structure making periodic link setup requests * @net_plane: network plane ('A' through 'H') currently associated with bearer - * @nodes: indicates which nodes in cluster can be reached through bearer * * Note: media-specific code is responsible for initialization of the fields * indicated below when a bearer is enabled; TIPC's generic bearer code takes @@ -163,8 +150,6 @@ struct tipc_bearer { u32 identity; struct tipc_link_req *link_req; char net_plane; - int node_cnt; - struct tipc_node_map nodes; }; struct tipc_bearer_names { -- GitLab From e790c3cb8d904c4bad0d4a37885bece2eb848eeb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 15 Nov 2015 19:14:22 -0200 Subject: [PATCH 2588/9938] [media] v4l: vsp1: Store active formats in a pad config structure Add a pad config structure field to the vsp1_entity structure and use it to store all active pad formats. This generalizes the code to operate on pad config structures. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 59 ++++++++++++++-------- drivers/media/platform/vsp1/vsp1_entity.c | 60 ++++++++++++++++------ drivers/media/platform/vsp1/vsp1_entity.h | 8 ++- drivers/media/platform/vsp1/vsp1_hsit.c | 29 ++++++++--- drivers/media/platform/vsp1/vsp1_lif.c | 42 ++++++++++++---- drivers/media/platform/vsp1/vsp1_lut.c | 42 ++++++++++++---- drivers/media/platform/vsp1/vsp1_rpf.c | 12 ++++- drivers/media/platform/vsp1/vsp1_rwpf.c | 51 +++++++++++++------ drivers/media/platform/vsp1/vsp1_sru.c | 61 +++++++++++++++-------- drivers/media/platform/vsp1/vsp1_uds.c | 59 +++++++++++++++------- drivers/media/platform/vsp1/vsp1_wpf.c | 12 ++++- 11 files changed, 311 insertions(+), 124 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 879dc9c9d3f0..a0aa0fb2a5e1 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -70,7 +70,8 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) if (!enable) return 0; - format = &bru->entity.formats[bru->entity.source_pad]; + format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config, + bru->entity.source_pad); /* The hardware is extremely flexible but we have no userspace API to * expose all the parameters, nor is it clear whether we would have use @@ -183,7 +184,6 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_AYUV8_1X32, }; struct vsp1_bru *bru = to_bru(subdev); - struct v4l2_mbus_framefmt *format; if (code->pad == BRU_PAD_SINK(0)) { if (code->index >= ARRAY_SIZE(codes)) @@ -191,12 +191,19 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev, code->code = codes[code->index]; } else { + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + if (code->index) return -EINVAL; - format = vsp1_entity_get_pad_format(&bru->entity, cfg, - BRU_PAD_SINK(0), + config = vsp1_entity_get_pad_config(&bru->entity, cfg, code->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&bru->entity, config, + BRU_PAD_SINK(0)); code->code = format->code; } @@ -242,17 +249,21 @@ static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_bru *bru = to_bru(subdev); + struct v4l2_subdev_pad_config *config; + + config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which); + if (!config) + return -EINVAL; - fmt->format = *vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad, - fmt->which); + fmt->format = *vsp1_entity_get_pad_format(&bru->entity, config, + fmt->pad); return 0; } static void bru_try_format(struct vsp1_bru *bru, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) + struct v4l2_subdev_pad_config *config, + unsigned int pad, struct v4l2_mbus_framefmt *fmt) { struct v4l2_mbus_framefmt *format; @@ -266,8 +277,8 @@ static void bru_try_format(struct vsp1_bru *bru, default: /* The BRU can't perform format conversion. */ - format = vsp1_entity_get_pad_format(&bru->entity, cfg, - BRU_PAD_SINK(0), which); + format = vsp1_entity_get_pad_format(&bru->entity, config, + BRU_PAD_SINK(0)); fmt->code = format->code; break; } @@ -283,12 +294,16 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_bru *bru = to_bru(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - bru_try_format(bru, cfg, fmt->pad, &fmt->format, fmt->which); + config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + bru_try_format(bru, config, fmt->pad, &fmt->format); - format = vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad, - fmt->which); + format = vsp1_entity_get_pad_format(&bru->entity, config, fmt->pad); *format = fmt->format; /* Reset the compose rectangle */ @@ -307,8 +322,8 @@ static int bru_set_format(struct v4l2_subdev *subdev, unsigned int i; for (i = 0; i <= bru->entity.source_pad; ++i) { - format = vsp1_entity_get_pad_format(&bru->entity, cfg, - i, fmt->which); + format = vsp1_entity_get_pad_format(&bru->entity, + config, i); format->code = fmt->format.code; } } @@ -347,6 +362,7 @@ static int bru_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_selection *sel) { struct vsp1_bru *bru = to_bru(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; struct v4l2_rect *compose; @@ -356,19 +372,22 @@ static int bru_set_selection(struct v4l2_subdev *subdev, if (sel->target != V4L2_SEL_TGT_COMPOSE) return -EINVAL; + config = vsp1_entity_get_pad_config(&bru->entity, cfg, sel->which); + if (!config) + return -EINVAL; + /* The compose rectangle top left corner must be inside the output * frame. */ - format = vsp1_entity_get_pad_format(&bru->entity, cfg, - bru->entity.source_pad, sel->which); + format = vsp1_entity_get_pad_format(&bru->entity, config, + bru->entity.source_pad); sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); /* Scaling isn't supported, the compose rectangle size must be identical * to the sink format size. */ - format = vsp1_entity_get_pad_format(&bru->entity, cfg, sel->pad, - sel->which); + format = vsp1_entity_get_pad_format(&bru->entity, config, sel->pad); sel->r.width = format->width; sel->r.height = format->height; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 5423e29e0d49..5185a1f5d3b8 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -46,21 +46,48 @@ void vsp1_entity_route_setup(struct vsp1_entity *source) * V4L2 Subdevice Operations */ -struct v4l2_mbus_framefmt * -vsp1_entity_get_pad_format(struct vsp1_entity *entity, +/** + * vsp1_entity_get_pad_config - Get the pad configuration for an entity + * @entity: the entity + * @cfg: the TRY pad configuration + * @which: configuration selector (ACTIVE or TRY) + * + * Return the pad configuration requested by the which argument. The TRY + * configuration is passed explicitly to the function through the cfg argument + * and simply returned when requested. The ACTIVE configuration comes from the + * entity structure. + */ +struct v4l2_subdev_pad_config * +vsp1_entity_get_pad_config(struct vsp1_entity *entity, struct v4l2_subdev_pad_config *cfg, - unsigned int pad, u32 which) + enum v4l2_subdev_format_whence which) { switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_format(&entity->subdev, cfg, pad); case V4L2_SUBDEV_FORMAT_ACTIVE: - return &entity->formats[pad]; + return entity->config; + case V4L2_SUBDEV_FORMAT_TRY: default: - return NULL; + return cfg; } } +/** + * vsp1_entity_get_pad_format - Get a pad format from storage for an entity + * @entity: the entity + * @cfg: the configuration storage + * @pad: the pad number + * + * Return the format stored in the given configuration for an entity's pad. The + * configuration can be an ACTIVE or TRY configuration. + */ +struct v4l2_mbus_framefmt * +vsp1_entity_get_pad_format(struct vsp1_entity *entity, + struct v4l2_subdev_pad_config *cfg, + unsigned int pad) +{ + return v4l2_subdev_get_try_format(&entity->subdev, cfg, pad); +} + /* * vsp1_entity_init_cfg - Initialize formats on all pads * @subdev: V4L2 subdevice @@ -169,19 +196,12 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, entity->vsp1 = vsp1; entity->source_pad = num_pads - 1; - /* Allocate formats and pads. */ - entity->formats = devm_kzalloc(vsp1->dev, - num_pads * sizeof(*entity->formats), - GFP_KERNEL); - if (entity->formats == NULL) - return -ENOMEM; - + /* Allocate and initialize pads. */ entity->pads = devm_kzalloc(vsp1->dev, num_pads * sizeof(*entity->pads), GFP_KERNEL); if (entity->pads == NULL) return -ENOMEM; - /* Initialize pads. */ for (i = 0; i < num_pads - 1; ++i) entity->pads[i].flags = MEDIA_PAD_FL_SINK; @@ -205,6 +225,15 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, vsp1_entity_init_cfg(subdev, NULL); + /* Allocate the pad configuration to store formats and selection + * rectangles. + */ + entity->config = v4l2_subdev_alloc_pad_config(&entity->subdev); + if (entity->config == NULL) { + media_entity_cleanup(&entity->subdev.entity); + return -ENOMEM; + } + return 0; } @@ -214,5 +243,6 @@ void vsp1_entity_destroy(struct vsp1_entity *entity) entity->ops->destroy(entity); if (entity->subdev.ctrl_handler) v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); + v4l2_subdev_free_pad_config(entity->config); media_entity_cleanup(&entity->subdev.entity); } diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 8e6cf776e990..7b2081aff869 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -84,7 +84,7 @@ struct vsp1_entity { unsigned int sink_pad; struct v4l2_subdev subdev; - struct v4l2_mbus_framefmt *formats; + struct v4l2_subdev_pad_config *config; }; static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) @@ -103,10 +103,14 @@ int vsp1_entity_link_setup(struct media_entity *entity, const struct media_pad *local, const struct media_pad *remote, u32 flags); +struct v4l2_subdev_pad_config * +vsp1_entity_get_pad_config(struct vsp1_entity *entity, + struct v4l2_subdev_pad_config *cfg, + enum v4l2_subdev_format_whence which); struct v4l2_mbus_framefmt * vsp1_entity_get_pad_format(struct vsp1_entity *entity, struct v4l2_subdev_pad_config *cfg, - unsigned int pad, u32 which); + unsigned int pad); int vsp1_entity_init_cfg(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg); diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 3e36755c8c2a..4f87f6f8ee38 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -77,10 +77,14 @@ static int hsit_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_hsit *hsit = to_hsit(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - format = vsp1_entity_get_pad_format(&hsit->entity, cfg, fse->pad, - fse->which); + config = vsp1_entity_get_pad_config(&hsit->entity, cfg, fse->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&hsit->entity, config, fse->pad); if (fse->index || fse->code != format->code) return -EINVAL; @@ -108,9 +112,14 @@ static int hsit_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_hsit *hsit = to_hsit(subdev); + struct v4l2_subdev_pad_config *config; + + config = vsp1_entity_get_pad_config(&hsit->entity, cfg, fmt->which); + if (!config) + return -EINVAL; - fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, cfg, fmt->pad, - fmt->which); + fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, config, + fmt->pad); return 0; } @@ -120,10 +129,14 @@ static int hsit_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_hsit *hsit = to_hsit(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - format = vsp1_entity_get_pad_format(&hsit->entity, cfg, fmt->pad, - fmt->which); + config = vsp1_entity_get_pad_config(&hsit->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&hsit->entity, config, fmt->pad); if (fmt->pad == HSIT_PAD_SOURCE) { /* The HST and HSI output format code and resolution can't be @@ -145,8 +158,8 @@ static int hsit_set_format(struct v4l2_subdev *subdev, fmt->format = *format; /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&hsit->entity, cfg, HSIT_PAD_SOURCE, - fmt->which); + format = vsp1_entity_get_pad_format(&hsit->entity, config, + HSIT_PAD_SOURCE); *format = fmt->format; format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32 : MEDIA_BUS_FMT_AHSV8888_1X32; diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 5edf6a742c5b..4090a0351263 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -48,7 +48,8 @@ static int lif_s_stream(struct v4l2_subdev *subdev, int enable) return 0; } - format = &lif->entity.formats[LIF_PAD_SOURCE]; + format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, + LIF_PAD_SOURCE); obth = min(obth, (format->width + 1) / 2 * format->height - 4); @@ -84,6 +85,7 @@ static int lif_enum_mbus_code(struct v4l2_subdev *subdev, code->code = codes[code->index]; } else { + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; /* The LIF can't perform format conversion, the sink format is @@ -92,8 +94,13 @@ static int lif_enum_mbus_code(struct v4l2_subdev *subdev, if (code->index) return -EINVAL; - format = vsp1_entity_get_pad_format(&lif->entity, cfg, - LIF_PAD_SINK, code->which); + config = vsp1_entity_get_pad_config(&lif->entity, cfg, + code->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&lif->entity, config, + LIF_PAD_SINK); code->code = format->code; } @@ -105,10 +112,14 @@ static int lif_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_lif *lif = to_lif(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - format = vsp1_entity_get_pad_format(&lif->entity, cfg, LIF_PAD_SINK, - fse->which); + config = vsp1_entity_get_pad_config(&lif->entity, cfg, fse->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&lif->entity, config, LIF_PAD_SINK); if (fse->index || fse->code != format->code) return -EINVAL; @@ -133,9 +144,14 @@ static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_lif *lif = to_lif(subdev); + struct v4l2_subdev_pad_config *config; - fmt->format = *vsp1_entity_get_pad_format(&lif->entity, cfg, fmt->pad, - fmt->which); + config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + fmt->format = *vsp1_entity_get_pad_format(&lif->entity, config, + fmt->pad); return 0; } @@ -145,15 +161,19 @@ static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_lif *lif = to_lif(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; + config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; - format = vsp1_entity_get_pad_format(&lif->entity, cfg, fmt->pad, - fmt->which); + format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad); if (fmt->pad == LIF_PAD_SOURCE) { /* The LIF source format is always identical to its sink @@ -174,8 +194,8 @@ static int lif_set_format(struct v4l2_subdev *subdev, fmt->format = *format; /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&lif->entity, cfg, LIF_PAD_SOURCE, - fmt->which); + format = vsp1_entity_get_pad_format(&lif->entity, config, + LIF_PAD_SOURCE); *format = fmt->format; return 0; diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index f0afc4291387..a5b839b28320 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -86,7 +86,6 @@ static int lut_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_AYUV8_1X32, }; struct vsp1_lut *lut = to_lut(subdev); - struct v4l2_mbus_framefmt *format; if (code->pad == LUT_PAD_SINK) { if (code->index >= ARRAY_SIZE(codes)) @@ -94,14 +93,22 @@ static int lut_enum_mbus_code(struct v4l2_subdev *subdev, code->code = codes[code->index]; } else { + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + /* The LUT can't perform format conversion, the sink format is * always identical to the source format. */ if (code->index) return -EINVAL; - format = vsp1_entity_get_pad_format(&lut->entity, cfg, - LUT_PAD_SINK, code->which); + config = vsp1_entity_get_pad_config(&lut->entity, cfg, + code->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&lut->entity, config, + LUT_PAD_SINK); code->code = format->code; } @@ -113,10 +120,14 @@ static int lut_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_lut *lut = to_lut(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - format = vsp1_entity_get_pad_format(&lut->entity, cfg, - fse->pad, fse->which); + config = vsp1_entity_get_pad_config(&lut->entity, cfg, fse->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&lut->entity, config, fse->pad); if (fse->index || fse->code != format->code) return -EINVAL; @@ -144,9 +155,14 @@ static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_lut *lut = to_lut(subdev); + struct v4l2_subdev_pad_config *config; + + config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which); + if (!config) + return -EINVAL; - fmt->format = *vsp1_entity_get_pad_format(&lut->entity, cfg, fmt->pad, - fmt->which); + fmt->format = *vsp1_entity_get_pad_format(&lut->entity, config, + fmt->pad); return 0; } @@ -156,16 +172,20 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_lut *lut = to_lut(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; + config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; - format = vsp1_entity_get_pad_format(&lut->entity, cfg, fmt->pad, - fmt->which); + format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad); if (fmt->pad == LUT_PAD_SOURCE) { /* The LUT output format can't be modified. */ @@ -183,8 +203,8 @@ static int lut_set_format(struct v4l2_subdev *subdev, fmt->format = *format; /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&lut->entity, cfg, LUT_PAD_SOURCE, - fmt->which); + format = vsp1_entity_get_pad_format(&lut->entity, config, + LUT_PAD_SOURCE); *format = fmt->format; return 0; diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 69fd76eed0bb..3b55cd93983f 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -42,6 +42,8 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) struct vsp1_rwpf *rpf = to_rwpf(subdev); const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; const struct v4l2_pix_format_mplane *format = &rpf->format; + const struct v4l2_mbus_framefmt *source_format; + const struct v4l2_mbus_framefmt *sink_format; const struct v4l2_rect *crop = &rpf->crop; u32 pstride; u32 infmt; @@ -79,6 +81,13 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); /* Format */ + sink_format = vsp1_entity_get_pad_format(&rpf->entity, + rpf->entity.config, + RWPF_PAD_SINK); + source_format = vsp1_entity_get_pad_format(&rpf->entity, + rpf->entity.config, + RWPF_PAD_SOURCE); + infmt = VI6_RPF_INFMT_CIPM | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT); @@ -87,8 +96,7 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) if (fmtinfo->swap_uv) infmt |= VI6_RPF_INFMT_SPUVS; - if (rpf->entity.formats[RWPF_PAD_SINK].code != - rpf->entity.formats[RWPF_PAD_SOURCE].code) + if (sink_format->code != source_format->code) infmt |= VI6_RPF_INFMT_CSC; vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 38893ab06cd9..e5216d39723e 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -46,10 +46,14 @@ int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fse->pad, - fse->which); + config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, fse->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&rwpf->entity, config, fse->pad); if (fse->index || fse->code != format->code) return -EINVAL; @@ -92,9 +96,14 @@ int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); + struct v4l2_subdev_pad_config *config; - fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad, - fmt->which); + config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, config, + fmt->pad); return 0; } @@ -104,16 +113,20 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; + config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; - format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad, - fmt->which); + format = vsp1_entity_get_pad_format(&rwpf->entity, config, fmt->pad); if (fmt->pad == RWPF_PAD_SOURCE) { /* The RWPF performs format conversion but can't scale, only the @@ -142,8 +155,8 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, crop->height = fmt->format.height; /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SOURCE, - fmt->which); + format = vsp1_entity_get_pad_format(&rwpf->entity, config, + RWPF_PAD_SOURCE); *format = fmt->format; return 0; @@ -154,20 +167,25 @@ int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_selection *sel) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; /* Cropping is implemented on the sink pad. */ if (sel->pad != RWPF_PAD_SINK) return -EINVAL; + config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, sel->which); + if (!config) + return -EINVAL; + switch (sel->target) { case V4L2_SEL_TGT_CROP: sel->r = *vsp1_rwpf_get_crop(rwpf, cfg, sel->which); break; case V4L2_SEL_TGT_CROP_BOUNDS: - format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, - RWPF_PAD_SINK, sel->which); + format = vsp1_entity_get_pad_format(&rwpf->entity, config, + RWPF_PAD_SINK); sel->r.left = 0; sel->r.top = 0; sel->r.width = format->width; @@ -186,6 +204,7 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_selection *sel) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; @@ -196,11 +215,15 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, if (sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; + config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, sel->which); + if (!config) + return -EINVAL; + /* Make sure the crop rectangle is entirely contained in the image. The * WPF top and left offsets are limited to 255. */ - format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SINK, - sel->which); + format = vsp1_entity_get_pad_format(&rwpf->entity, config, + RWPF_PAD_SINK); /* Restrict the crop rectangle coordinates to multiples of 2 to avoid * shifting the color plane. @@ -227,8 +250,8 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, *crop = sel->r; /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SOURCE, - sel->which); + format = vsp1_entity_get_pad_format(&rwpf->entity, config, + RWPF_PAD_SOURCE); format->width = crop->width; format->height = crop->height; diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 043dac6644c1..c9a97ba5a042 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -117,8 +117,10 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) if (!enable) return 0; - input = &sru->entity.formats[SRU_PAD_SINK]; - output = &sru->entity.formats[SRU_PAD_SOURCE]; + input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, + SRU_PAD_SINK); + output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, + SRU_PAD_SOURCE); if (input->code == MEDIA_BUS_FMT_ARGB8888_1X32) ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3 @@ -153,7 +155,6 @@ static int sru_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_AYUV8_1X32, }; struct vsp1_sru *sru = to_sru(subdev); - struct v4l2_mbus_framefmt *format; if (code->pad == SRU_PAD_SINK) { if (code->index >= ARRAY_SIZE(codes)) @@ -161,14 +162,22 @@ static int sru_enum_mbus_code(struct v4l2_subdev *subdev, code->code = codes[code->index]; } else { + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + /* The SRU can't perform format conversion, the sink format is * always identical to the source format. */ if (code->index) return -EINVAL; - format = vsp1_entity_get_pad_format(&sru->entity, cfg, - SRU_PAD_SINK, code->which); + config = vsp1_entity_get_pad_config(&sru->entity, cfg, + code->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&sru->entity, config, + SRU_PAD_SINK); code->code = format->code; } @@ -180,10 +189,14 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_sru *sru = to_sru(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - format = vsp1_entity_get_pad_format(&sru->entity, cfg, - SRU_PAD_SINK, fse->which); + config = vsp1_entity_get_pad_config(&sru->entity, cfg, fse->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&sru->entity, config, SRU_PAD_SINK); if (fse->index || fse->code != format->code) return -EINVAL; @@ -214,17 +227,21 @@ static int sru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_sru *sru = to_sru(subdev); + struct v4l2_subdev_pad_config *config; + + config = vsp1_entity_get_pad_config(&sru->entity, cfg, fmt->which); + if (!config) + return -EINVAL; - fmt->format = *vsp1_entity_get_pad_format(&sru->entity, cfg, fmt->pad, - fmt->which); + fmt->format = *vsp1_entity_get_pad_format(&sru->entity, config, + fmt->pad); return 0; } static void sru_try_format(struct vsp1_sru *sru, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) + struct v4l2_subdev_pad_config *config, + unsigned int pad, struct v4l2_mbus_framefmt *fmt) { struct v4l2_mbus_framefmt *format; unsigned int input_area; @@ -243,8 +260,8 @@ static void sru_try_format(struct vsp1_sru *sru, case SRU_PAD_SOURCE: /* The SRU can't perform format conversion. */ - format = vsp1_entity_get_pad_format(&sru->entity, cfg, - SRU_PAD_SINK, which); + format = vsp1_entity_get_pad_format(&sru->entity, config, + SRU_PAD_SINK); fmt->code = format->code; /* We can upscale by 2 in both direction, but not independently. @@ -278,21 +295,25 @@ static int sru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_sru *sru = to_sru(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - sru_try_format(sru, cfg, fmt->pad, &fmt->format, fmt->which); + config = vsp1_entity_get_pad_config(&sru->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + sru_try_format(sru, config, fmt->pad, &fmt->format); - format = vsp1_entity_get_pad_format(&sru->entity, cfg, fmt->pad, - fmt->which); + format = vsp1_entity_get_pad_format(&sru->entity, config, fmt->pad); *format = fmt->format; if (fmt->pad == SRU_PAD_SINK) { /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&sru->entity, cfg, - SRU_PAD_SOURCE, fmt->which); + format = vsp1_entity_get_pad_format(&sru->entity, config, + SRU_PAD_SOURCE); *format = fmt->format; - sru_try_format(sru, cfg, SRU_PAD_SOURCE, format, fmt->which); + sru_try_format(sru, config, SRU_PAD_SOURCE, format); } return 0; diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 666fabcd0382..3ba0f6844d1d 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -120,8 +120,10 @@ static int uds_s_stream(struct v4l2_subdev *subdev, int enable) if (!enable) return 0; - input = &uds->entity.formats[UDS_PAD_SINK]; - output = &uds->entity.formats[UDS_PAD_SOURCE]; + input = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, + UDS_PAD_SINK); + output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, + UDS_PAD_SOURCE); hscale = uds_compute_ratio(input->width, output->width); vscale = uds_compute_ratio(input->height, output->height); @@ -178,16 +180,22 @@ static int uds_enum_mbus_code(struct v4l2_subdev *subdev, code->code = codes[code->index]; } else { + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; + config = vsp1_entity_get_pad_config(&uds->entity, cfg, + code->which); + if (!config) + return -EINVAL; + /* The UDS can't perform format conversion, the sink format is * always identical to the source format. */ if (code->index) return -EINVAL; - format = vsp1_entity_get_pad_format(&uds->entity, cfg, - UDS_PAD_SINK, code->which); + format = vsp1_entity_get_pad_format(&uds->entity, config, + UDS_PAD_SINK); code->code = format->code; } @@ -199,10 +207,15 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_uds *uds = to_uds(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - format = vsp1_entity_get_pad_format(&uds->entity, cfg, - UDS_PAD_SINK, fse->which); + config = vsp1_entity_get_pad_config(&uds->entity, cfg, fse->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(&uds->entity, config, + UDS_PAD_SINK); if (fse->index || fse->code != format->code) return -EINVAL; @@ -227,17 +240,21 @@ static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_uds *uds = to_uds(subdev); + struct v4l2_subdev_pad_config *config; - fmt->format = *vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad, - fmt->which); + config = vsp1_entity_get_pad_config(&uds->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + fmt->format = *vsp1_entity_get_pad_format(&uds->entity, config, + fmt->pad); return 0; } static void uds_try_format(struct vsp1_uds *uds, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) + struct v4l2_subdev_pad_config *config, + unsigned int pad, struct v4l2_mbus_framefmt *fmt) { struct v4l2_mbus_framefmt *format; unsigned int minimum; @@ -256,8 +273,8 @@ static void uds_try_format(struct vsp1_uds *uds, case UDS_PAD_SOURCE: /* The UDS scales but can't perform format conversion. */ - format = vsp1_entity_get_pad_format(&uds->entity, cfg, - UDS_PAD_SINK, which); + format = vsp1_entity_get_pad_format(&uds->entity, config, + UDS_PAD_SINK); fmt->code = format->code; uds_output_limits(format->width, &minimum, &maximum); @@ -276,21 +293,25 @@ static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_uds *uds = to_uds(subdev); + struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; - uds_try_format(uds, cfg, fmt->pad, &fmt->format, fmt->which); + config = vsp1_entity_get_pad_config(&uds->entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + uds_try_format(uds, config, fmt->pad, &fmt->format); - format = vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad, - fmt->which); + format = vsp1_entity_get_pad_format(&uds->entity, config, fmt->pad); *format = fmt->format; if (fmt->pad == UDS_PAD_SINK) { /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&uds->entity, cfg, - UDS_PAD_SOURCE, fmt->which); + format = vsp1_entity_get_pad_format(&uds->entity, config, + UDS_PAD_SOURCE); *format = fmt->format; - uds_try_format(uds, cfg, UDS_PAD_SOURCE, format, fmt->which); + uds_try_format(uds, config, UDS_PAD_SOURCE, format); } return 0; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index d46910db7e08..c86d31f274bf 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -42,6 +42,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); struct vsp1_rwpf *wpf = to_rwpf(subdev); struct vsp1_device *vsp1 = wpf->entity.vsp1; + const struct v4l2_mbus_framefmt *source_format; + const struct v4l2_mbus_framefmt *sink_format; const struct v4l2_rect *crop = &wpf->crop; unsigned int i; u32 srcrpf = 0; @@ -94,6 +96,13 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) (crop->height << VI6_WPF_SZCLIP_SIZE_SHIFT)); /* Format */ + sink_format = vsp1_entity_get_pad_format(&wpf->entity, + wpf->entity.config, + RWPF_PAD_SINK); + source_format = vsp1_entity_get_pad_format(&wpf->entity, + wpf->entity.config, + RWPF_PAD_SOURCE); + if (!pipe->lif) { const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; @@ -109,8 +118,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_wpf_write(wpf, VI6_WPF_DSWAP, fmtinfo->swap); } - if (wpf->entity.formats[RWPF_PAD_SINK].code != - wpf->entity.formats[RWPF_PAD_SOURCE].code) + if (sink_format->code != source_format->code) outfmt |= VI6_WPF_OUTFMT_CSC; outfmt |= wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT; -- GitLab From b7e5107eebb73d27affed95c20cedbf4784bf17c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 15 Nov 2015 19:14:22 -0200 Subject: [PATCH 2589/9938] [media] v4l: vsp1: Store active selection rectangles in a pad config structure Use the pad config structure part of the vsp1_entity to store all active pad selection rectangles. This generalizes the code to operate on pad config structures. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 24 +++++++++++------------ drivers/media/platform/vsp1/vsp1_bru.h | 1 - drivers/media/platform/vsp1/vsp1_drm.c | 5 ++--- drivers/media/platform/vsp1/vsp1_entity.c | 8 ++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 4 ++++ drivers/media/platform/vsp1/vsp1_rpf.c | 20 ++++++++++++++++--- drivers/media/platform/vsp1/vsp1_rwpf.c | 22 +++++++-------------- drivers/media/platform/vsp1/vsp1_rwpf.h | 8 +++----- drivers/media/platform/vsp1/vsp1_video.c | 13 +++--------- drivers/media/platform/vsp1/vsp1_wpf.c | 4 +++- 10 files changed, 58 insertions(+), 51 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index a0aa0fb2a5e1..c1848a3ac010 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -231,17 +231,9 @@ static int bru_enum_frame_size(struct v4l2_subdev *subdev, static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *cfg, - unsigned int pad, u32 which) + unsigned int pad) { - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, - pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &bru->inputs[pad].compose; - default: - return NULL; - } + return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, pad); } static int bru_get_format(struct v4l2_subdev *subdev, @@ -310,7 +302,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, if (fmt->pad != bru->entity.source_pad) { struct v4l2_rect *compose; - compose = bru_get_compose(bru, cfg, fmt->pad, fmt->which); + compose = bru_get_compose(bru, config, fmt->pad); compose->left = 0; compose->top = 0; compose->width = format->width; @@ -336,6 +328,7 @@ static int bru_get_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_selection *sel) { struct vsp1_bru *bru = to_bru(subdev); + struct v4l2_subdev_pad_config *config; if (sel->pad == bru->entity.source_pad) return -EINVAL; @@ -349,7 +342,12 @@ static int bru_get_selection(struct v4l2_subdev *subdev, return 0; case V4L2_SEL_TGT_COMPOSE: - sel->r = *bru_get_compose(bru, cfg, sel->pad, sel->which); + config = vsp1_entity_get_pad_config(&bru->entity, cfg, + sel->which); + if (!config) + return -EINVAL; + + sel->r = *bru_get_compose(bru, config, sel->pad); return 0; default: @@ -391,7 +389,7 @@ static int bru_set_selection(struct v4l2_subdev *subdev, sel->r.width = format->width; sel->r.height = format->height; - compose = bru_get_compose(bru, cfg, sel->pad, sel->which); + compose = bru_get_compose(bru, config, sel->pad); *compose = sel->r; return 0; diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h index 4e7d2e79b940..828a3fcadea8 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.h +++ b/drivers/media/platform/vsp1/vsp1_bru.h @@ -31,7 +31,6 @@ struct vsp1_bru { struct { struct vsp1_rwpf *rpf; - struct v4l2_rect compose; } inputs[VSP1_MAX_RPF]; u32 bgcolor; diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index a73018c9e8b5..acbf36d315b9 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -410,9 +410,8 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, sel.pad); - /* Store the compose rectangle coordinates in the RPF. */ - rpf->location.left = dst->left; - rpf->location.top = dst->top; + /* Store the BRU input pad number in the RPF. */ + rpf->bru_input = rpf->entity.index; /* Cache the memory buffer address but don't apply the values to the * hardware as the crop offsets haven't been computed yet. diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 5185a1f5d3b8..09c9a1b86e3a 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -88,6 +88,14 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity, return v4l2_subdev_get_try_format(&entity->subdev, cfg, pad); } +struct v4l2_rect * +vsp1_entity_get_pad_compose(struct vsp1_entity *entity, + struct v4l2_subdev_pad_config *cfg, + unsigned int pad) +{ + return v4l2_subdev_get_try_compose(&entity->subdev, cfg, pad); +} + /* * vsp1_entity_init_cfg - Initialize formats on all pads * @subdev: V4L2 subdevice diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 7b2081aff869..f7a360823373 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -111,6 +111,10 @@ struct v4l2_mbus_framefmt * vsp1_entity_get_pad_format(struct vsp1_entity *entity, struct v4l2_subdev_pad_config *cfg, unsigned int pad); +struct v4l2_rect * +vsp1_entity_get_pad_compose(struct vsp1_entity *entity, + struct v4l2_subdev_pad_config *cfg, + unsigned int pad); int vsp1_entity_init_cfg(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 3b55cd93983f..cb3d5ed148cc 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -44,7 +44,9 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) const struct v4l2_pix_format_mplane *format = &rpf->format; const struct v4l2_mbus_framefmt *source_format; const struct v4l2_mbus_framefmt *sink_format; - const struct v4l2_rect *crop = &rpf->crop; + const struct v4l2_rect *crop; + unsigned int left = 0; + unsigned int top = 0; u32 pstride; u32 infmt; @@ -57,6 +59,8 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) * left corner in the plane buffer. Only two offsets are needed, as * planes 2 and 3 always have identical strides. */ + crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config); + vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE, (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); @@ -103,9 +107,19 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); /* Output location */ + if (pipe->bru) { + const struct v4l2_rect *compose; + + compose = vsp1_entity_get_pad_compose(pipe->bru, + pipe->bru->config, + rpf->bru_input); + left = compose->left; + top = compose->top; + } + vsp1_rpf_write(rpf, VI6_RPF_LOC, - (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) | - (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT)); + (left << VI6_RPF_LOC_HCOORD_SHIFT) | + (top << VI6_RPF_LOC_VCOORD_SHIFT)); /* Use the alpha channel (extended to 8 bits) when available or an * alpha value set through the V4L2_CID_ALPHA_COMPONENT control diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index e5216d39723e..0c5ad023adfb 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -76,19 +76,11 @@ int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static struct v4l2_rect * -vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_pad_config *cfg, - u32 which) +struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, + struct v4l2_subdev_pad_config *config) { - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, cfg, - RWPF_PAD_SINK); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &rwpf->crop; - default: - return NULL; - } + return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, config, + RWPF_PAD_SINK); } int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, @@ -148,7 +140,7 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, fmt->format = *format; /* Update the sink crop rectangle. */ - crop = vsp1_rwpf_get_crop(rwpf, cfg, fmt->which); + crop = vsp1_rwpf_get_crop(rwpf, config); crop->left = 0; crop->top = 0; crop->width = fmt->format.width; @@ -180,7 +172,7 @@ int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, switch (sel->target) { case V4L2_SEL_TGT_CROP: - sel->r = *vsp1_rwpf_get_crop(rwpf, cfg, sel->which); + sel->r = *vsp1_rwpf_get_crop(rwpf, config); break; case V4L2_SEL_TGT_CROP_BOUNDS: @@ -246,7 +238,7 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, sel->r.height = min_t(unsigned int, sel->r.height, format->height - sel->r.top); - crop = vsp1_rwpf_get_crop(rwpf, cfg, sel->which); + crop = vsp1_rwpf_get_crop(rwpf, config); *crop = sel->r; /* Propagate the format to the source pad. */ diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index e8ca9b6ee689..4ebfab61e0ef 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -43,11 +43,7 @@ struct vsp1_rwpf { struct v4l2_pix_format_mplane format; const struct vsp1_format_info *fmtinfo; - struct { - unsigned int left; - unsigned int top; - } location; - struct v4l2_rect crop; + unsigned int bru_input; unsigned int alpha; @@ -91,6 +87,8 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel); +struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, + struct v4l2_subdev_pad_config *config); /** * vsp1_rwpf_set_memory - Configure DMA addresses for a [RW]PF * @rwpf: the [RW]PF instance diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 102977ae1daa..d4a092c8ece3 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -182,9 +182,6 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, bool bru_found = false; int ret; - input->location.left = 0; - input->location.top = 0; - ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev); if (ret < 0) return ret; @@ -206,18 +203,14 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, entity = to_vsp1_entity( media_entity_to_v4l2_subdev(pad->entity)); - /* A BRU is present in the pipeline, store the compose rectangle - * location in the input RPF for use when configuring the RPF. + /* A BRU is present in the pipeline, store the BRU input pad + * number in the input RPF for use when configuring the RPF. */ if (entity->type == VSP1_ENTITY_BRU) { struct vsp1_bru *bru = to_bru(&entity->subdev); - struct v4l2_rect *rect = - &bru->inputs[pad->index].compose; bru->inputs[pad->index].rpf = input; - - input->location.left = rect->left; - input->location.top = rect->top; + input->bru_input = pad->index; bru_found = true; } diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index c86d31f274bf..0797927d14cf 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -44,7 +44,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) struct vsp1_device *vsp1 = wpf->entity.vsp1; const struct v4l2_mbus_framefmt *source_format; const struct v4l2_mbus_framefmt *sink_format; - const struct v4l2_rect *crop = &wpf->crop; + const struct v4l2_rect *crop; unsigned int i; u32 srcrpf = 0; u32 outfmt = 0; @@ -88,6 +88,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) format->plane_fmt[1].bytesperline); } + crop = vsp1_rwpf_get_crop(wpf, wpf->entity.config); + vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | (crop->left << VI6_WPF_SZCLIP_OFST_SHIFT) | (crop->width << VI6_WPF_SZCLIP_SIZE_SHIFT)); -- GitLab From 7b905f0583b2e6fe1494a85303a89aa0cd30b0b3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 17 Nov 2015 13:10:26 -0200 Subject: [PATCH 2590/9938] [media] v4l: vsp1: Create a new configure operation to setup modules The subdev s_stream operation is abused as a generic way to setup modules at every frame. Move the code out to a new VSP1 entity configure operation. Most modules now have an empty s_stream operation that can be removed. The only exception is the WPF module that needs to perform hardware configuration when stopping the stream. The code can be simplified accordingly as we know that that operation never fails. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 231 +++++++++++----------- drivers/media/platform/vsp1/vsp1_drm.c | 14 +- drivers/media/platform/vsp1/vsp1_entity.h | 3 + drivers/media/platform/vsp1/vsp1_hsit.c | 50 ++--- drivers/media/platform/vsp1/vsp1_lif.c | 77 ++++---- drivers/media/platform/vsp1/vsp1_lut.c | 41 ++-- drivers/media/platform/vsp1/vsp1_pipe.c | 4 +- drivers/media/platform/vsp1/vsp1_rpf.c | 83 ++++---- drivers/media/platform/vsp1/vsp1_sru.c | 91 ++++----- drivers/media/platform/vsp1/vsp1_uds.c | 117 ++++++----- drivers/media/platform/vsp1/vsp1_video.c | 15 +- drivers/media/platform/vsp1/vsp1_wpf.c | 168 ++++++++-------- 12 files changed, 418 insertions(+), 476 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index c1848a3ac010..4ab0a805d4b2 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -56,117 +56,7 @@ static const struct v4l2_ctrl_ops bru_ctrl_ops = { }; /* ----------------------------------------------------------------------------- - * V4L2 Subdevice Core Operations - */ - -static int bru_s_stream(struct v4l2_subdev *subdev, int enable) -{ - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); - struct vsp1_bru *bru = to_bru(subdev); - struct v4l2_mbus_framefmt *format; - unsigned int flags; - unsigned int i; - - if (!enable) - return 0; - - format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config, - bru->entity.source_pad); - - /* The hardware is extremely flexible but we have no userspace API to - * expose all the parameters, nor is it clear whether we would have use - * cases for all the supported modes. Let's just harcode the parameters - * to sane default values for now. - */ - - /* Disable dithering and enable color data normalization unless the - * format at the pipeline output is premultiplied. - */ - flags = pipe->output ? pipe->output->format.flags : 0; - vsp1_bru_write(bru, VI6_BRU_INCTRL, - flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? - 0 : VI6_BRU_INCTRL_NRM); - - /* Set the background position to cover the whole output image and - * configure its color. - */ - vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, - (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | - (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); - vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); - - vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, bru->bgcolor | - (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT)); - - /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP - * unit with a NOP operation to make BRU input 1 available as the - * Blend/ROP unit B SRC input. - */ - vsp1_bru_write(bru, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) | - VI6_BRU_ROP_CROP(VI6_ROP_NOP) | - VI6_BRU_ROP_AROP(VI6_ROP_NOP)); - - for (i = 0; i < bru->entity.source_pad; ++i) { - bool premultiplied = false; - u32 ctrl = 0; - - /* Configure all Blend/ROP units corresponding to an enabled BRU - * input for alpha blending. Blend/ROP units corresponding to - * disabled BRU inputs are used in ROP NOP mode to ignore the - * SRC input. - */ - if (bru->inputs[i].rpf) { - ctrl |= VI6_BRU_CTRL_RBC; - - premultiplied = bru->inputs[i].rpf->format.flags - & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; - } else { - ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) - | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); - } - - /* Select the virtual RPF as the Blend/ROP unit A DST input to - * serve as a background color. - */ - if (i == 0) - ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF; - - /* Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to - * D in that order. The Blend/ROP unit B SRC is hardwired to the - * ROP unit output, the corresponding register bits must be set - * to 0. - */ - if (i != 1) - ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); - - vsp1_bru_write(bru, VI6_BRU_CTRL(i), ctrl); - - /* Harcode the blending formula to - * - * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa - * DSTa = DSTa * (1 - SRCa) + SRCa - * - * when the SRC input isn't premultiplied, and to - * - * DSTc = DSTc * (1 - SRCa) + SRCc - * DSTa = DSTa * (1 - SRCa) + SRCa - * - * otherwise. - */ - vsp1_bru_write(bru, VI6_BRU_BLD(i), - VI6_BRU_BLD_CCMDX_255_SRC_A | - (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY : - VI6_BRU_BLD_CCMDY_SRC_A) | - VI6_BRU_BLD_ACMDX_255_SRC_A | - VI6_BRU_BLD_ACMDY_COEFY | - (0xff << VI6_BRU_BLD_COEFY_SHIFT)); - } - - return 0; -} - -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Pad Operations + * V4L2 Subdevice Operations */ /* @@ -395,14 +285,6 @@ static int bru_set_selection(struct v4l2_subdev *subdev, return 0; } -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Operations - */ - -static struct v4l2_subdev_video_ops bru_video_ops = { - .s_stream = bru_s_stream, -}; - static struct v4l2_subdev_pad_ops bru_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = bru_enum_mbus_code, @@ -414,10 +296,118 @@ static struct v4l2_subdev_pad_ops bru_pad_ops = { }; static struct v4l2_subdev_ops bru_ops = { - .video = &bru_video_ops, .pad = &bru_pad_ops, }; +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void bru_configure(struct vsp1_entity *entity) +{ + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); + struct vsp1_bru *bru = to_bru(&entity->subdev); + struct v4l2_mbus_framefmt *format; + unsigned int flags; + unsigned int i; + + format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config, + bru->entity.source_pad); + + /* The hardware is extremely flexible but we have no userspace API to + * expose all the parameters, nor is it clear whether we would have use + * cases for all the supported modes. Let's just harcode the parameters + * to sane default values for now. + */ + + /* Disable dithering and enable color data normalization unless the + * format at the pipeline output is premultiplied. + */ + flags = pipe->output ? pipe->output->format.flags : 0; + vsp1_bru_write(bru, VI6_BRU_INCTRL, + flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? + 0 : VI6_BRU_INCTRL_NRM); + + /* Set the background position to cover the whole output image and + * configure its color. + */ + vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, + (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | + (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); + vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); + + vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, bru->bgcolor | + (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT)); + + /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP + * unit with a NOP operation to make BRU input 1 available as the + * Blend/ROP unit B SRC input. + */ + vsp1_bru_write(bru, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) | + VI6_BRU_ROP_CROP(VI6_ROP_NOP) | + VI6_BRU_ROP_AROP(VI6_ROP_NOP)); + + for (i = 0; i < bru->entity.source_pad; ++i) { + bool premultiplied = false; + u32 ctrl = 0; + + /* Configure all Blend/ROP units corresponding to an enabled BRU + * input for alpha blending. Blend/ROP units corresponding to + * disabled BRU inputs are used in ROP NOP mode to ignore the + * SRC input. + */ + if (bru->inputs[i].rpf) { + ctrl |= VI6_BRU_CTRL_RBC; + + premultiplied = bru->inputs[i].rpf->format.flags + & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; + } else { + ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) + | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); + } + + /* Select the virtual RPF as the Blend/ROP unit A DST input to + * serve as a background color. + */ + if (i == 0) + ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF; + + /* Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to + * D in that order. The Blend/ROP unit B SRC is hardwired to the + * ROP unit output, the corresponding register bits must be set + * to 0. + */ + if (i != 1) + ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); + + vsp1_bru_write(bru, VI6_BRU_CTRL(i), ctrl); + + /* Harcode the blending formula to + * + * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa + * DSTa = DSTa * (1 - SRCa) + SRCa + * + * when the SRC input isn't premultiplied, and to + * + * DSTc = DSTc * (1 - SRCa) + SRCc + * DSTa = DSTa * (1 - SRCa) + SRCa + * + * otherwise. + */ + vsp1_bru_write(bru, VI6_BRU_BLD(i), + VI6_BRU_BLD_CCMDX_255_SRC_A | + (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY : + VI6_BRU_BLD_CCMDY_SRC_A) | + VI6_BRU_BLD_ACMDX_255_SRC_A | + VI6_BRU_BLD_ACMDY_COEFY | + (0xff << VI6_BRU_BLD_COEFY_SHIFT)); + } +} + +static const struct vsp1_entity_operations bru_entity_ops = { + .configure = bru_configure, +}; + /* ----------------------------------------------------------------------------- * Initialization and Cleanup */ @@ -431,6 +421,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) if (bru == NULL) return ERR_PTR(-ENOMEM); + bru->entity.ops = &bru_entity_ops; bru->entity.type = VSP1_ENTITY_BRU; ret = vsp1_entity_init(vsp1, &bru->entity, "bru", diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index acbf36d315b9..bec7a651d152 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -448,7 +448,6 @@ void vsp1_du_atomic_flush(struct device *dev) struct vsp1_entity *entity; unsigned long flags; bool stop = false; - int ret; list_for_each_entry(entity, &pipe->entities, list_pipe) { /* Disconnect unused RPFs from the pipeline. */ @@ -464,19 +463,16 @@ void vsp1_du_atomic_flush(struct device *dev) vsp1_entity_route_setup(entity); - ret = v4l2_subdev_call(&entity->subdev, video, - s_stream, 1); - if (ret < 0) { - dev_err(vsp1->dev, - "DRM pipeline start failure on entity %s\n", - entity->subdev.name); - return; - } + if (entity->ops->configure) + entity->ops->configure(entity); if (entity->type == VSP1_ENTITY_RPF) vsp1_rwpf_set_memory(to_rwpf(&entity->subdev)); } + /* We know that the WPF s_stream operation never fails. */ + v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 1); + vsp1_dl_list_commit(pipe->dl); pipe->dl = NULL; diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index f7a360823373..fe164f3163bc 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -59,10 +59,13 @@ struct vsp1_route { * @set_memory: Setup memory buffer access. This operation applies the settings * stored in the rwpf mem field to the hardware. Valid for RPF and * WPF only. + * @configure: Setup the hardware based on the entity state (pipeline, formats, + * selection rectangles, ...) */ struct vsp1_entity_operations { void (*destroy)(struct vsp1_entity *); void (*set_memory)(struct vsp1_entity *); + void (*configure)(struct vsp1_entity *); }; struct vsp1_entity { diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 4f87f6f8ee38..7360586c902a 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -32,26 +32,7 @@ static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data) } /* ----------------------------------------------------------------------------- - * V4L2 Subdevice Core Operations - */ - -static int hsit_s_stream(struct v4l2_subdev *subdev, int enable) -{ - struct vsp1_hsit *hsit = to_hsit(subdev); - - if (!enable) - return 0; - - if (hsit->inverse) - vsp1_hsit_write(hsit, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); - else - vsp1_hsit_write(hsit, VI6_HST_CTRL, VI6_HST_CTRL_EN); - - return 0; -} - -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Pad Operations + * V4L2 Subdevice Operations */ static int hsit_enum_mbus_code(struct v4l2_subdev *subdev, @@ -167,14 +148,6 @@ static int hsit_set_format(struct v4l2_subdev *subdev, return 0; } -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Operations - */ - -static struct v4l2_subdev_video_ops hsit_video_ops = { - .s_stream = hsit_s_stream, -}; - static struct v4l2_subdev_pad_ops hsit_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = hsit_enum_mbus_code, @@ -184,10 +157,27 @@ static struct v4l2_subdev_pad_ops hsit_pad_ops = { }; static struct v4l2_subdev_ops hsit_ops = { - .video = &hsit_video_ops, .pad = &hsit_pad_ops, }; +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void hsit_configure(struct vsp1_entity *entity) +{ + struct vsp1_hsit *hsit = to_hsit(&entity->subdev); + + if (hsit->inverse) + vsp1_hsit_write(hsit, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); + else + vsp1_hsit_write(hsit, VI6_HST_CTRL, VI6_HST_CTRL_EN); +} + +static const struct vsp1_entity_operations hsit_entity_ops = { + .configure = hsit_configure, +}; + /* ----------------------------------------------------------------------------- * Initialization and Cleanup */ @@ -203,6 +193,8 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) hsit->inverse = inverse; + hsit->entity.ops = &hsit_entity_ops; + if (inverse) hsit->entity.type = VSP1_ENTITY_HSI; else diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 4090a0351263..d8d8d3b6c129 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -32,41 +32,7 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data) } /* ----------------------------------------------------------------------------- - * V4L2 Subdevice Core Operations - */ - -static int lif_s_stream(struct v4l2_subdev *subdev, int enable) -{ - const struct v4l2_mbus_framefmt *format; - struct vsp1_lif *lif = to_lif(subdev); - unsigned int hbth = 1300; - unsigned int obth = 400; - unsigned int lbth = 200; - - if (!enable) { - vsp1_write(lif->entity.vsp1, VI6_LIF_CTRL, 0); - return 0; - } - - format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, - LIF_PAD_SOURCE); - - obth = min(obth, (format->width + 1) / 2 * format->height - 4); - - vsp1_lif_write(lif, VI6_LIF_CSBTH, - (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | - (lbth << VI6_LIF_CSBTH_LBTH_SHIFT)); - - vsp1_lif_write(lif, VI6_LIF_CTRL, - (obth << VI6_LIF_CTRL_OBTH_SHIFT) | - (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | - VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); - - return 0; -} - -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Pad Operations + * V4L2 Subdevice Operations */ static int lif_enum_mbus_code(struct v4l2_subdev *subdev, @@ -201,14 +167,6 @@ static int lif_set_format(struct v4l2_subdev *subdev, return 0; } -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Operations - */ - -static struct v4l2_subdev_video_ops lif_video_ops = { - .s_stream = lif_s_stream, -}; - static struct v4l2_subdev_pad_ops lif_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = lif_enum_mbus_code, @@ -218,10 +176,40 @@ static struct v4l2_subdev_pad_ops lif_pad_ops = { }; static struct v4l2_subdev_ops lif_ops = { - .video = &lif_video_ops, .pad = &lif_pad_ops, }; +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void lif_configure(struct vsp1_entity *entity) +{ + const struct v4l2_mbus_framefmt *format; + struct vsp1_lif *lif = to_lif(&entity->subdev); + unsigned int hbth = 1300; + unsigned int obth = 400; + unsigned int lbth = 200; + + format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, + LIF_PAD_SOURCE); + + obth = min(obth, (format->width + 1) / 2 * format->height - 4); + + vsp1_lif_write(lif, VI6_LIF_CSBTH, + (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | + (lbth << VI6_LIF_CSBTH_LBTH_SHIFT)); + + vsp1_lif_write(lif, VI6_LIF_CTRL, + (obth << VI6_LIF_CTRL_OBTH_SHIFT) | + (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | + VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); +} + +static const struct vsp1_entity_operations lif_entity_ops = { + .configure = lif_configure, +}; + /* ----------------------------------------------------------------------------- * Initialization and Cleanup */ @@ -235,6 +223,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1) if (lif == NULL) return ERR_PTR(-ENOMEM); + lif->entity.ops = &lif_entity_ops; lif->entity.type = VSP1_ENTITY_LIF; ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 2, &lif_ops); diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index a5b839b28320..d5d32ce10f41 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -36,7 +36,7 @@ static inline void vsp1_lut_write(struct vsp1_lut *lut, u32 reg, u32 data) * V4L2 Subdevice Core Operations */ -static void lut_configure(struct vsp1_lut *lut, struct vsp1_lut_config *config) +static void lut_set_table(struct vsp1_lut *lut, struct vsp1_lut_config *config) { memcpy_toio(lut->entity.vsp1->mmio + VI6_LUT_TABLE, config->lut, sizeof(config->lut)); @@ -48,7 +48,7 @@ static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) switch (cmd) { case VIDIOC_VSP1_LUT_CONFIG: - lut_configure(lut, arg); + lut_set_table(lut, arg); return 0; default: @@ -56,22 +56,6 @@ static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) } } -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Video Operations - */ - -static int lut_s_stream(struct v4l2_subdev *subdev, int enable) -{ - struct vsp1_lut *lut = to_lut(subdev); - - if (!enable) - return 0; - - vsp1_lut_write(lut, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); - - return 0; -} - /* ----------------------------------------------------------------------------- * V4L2 Subdevice Pad Operations */ @@ -218,10 +202,6 @@ static struct v4l2_subdev_core_ops lut_core_ops = { .ioctl = lut_ioctl, }; -static struct v4l2_subdev_video_ops lut_video_ops = { - .s_stream = lut_s_stream, -}; - static struct v4l2_subdev_pad_ops lut_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = lut_enum_mbus_code, @@ -232,10 +212,24 @@ static struct v4l2_subdev_pad_ops lut_pad_ops = { static struct v4l2_subdev_ops lut_ops = { .core = &lut_core_ops, - .video = &lut_video_ops, .pad = &lut_pad_ops, }; +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void lut_configure(struct vsp1_entity *entity) +{ + struct vsp1_lut *lut = to_lut(&entity->subdev); + + vsp1_lut_write(lut, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); +} + +static const struct vsp1_entity_operations lut_entity_ops = { + .configure = lut_configure, +}; + /* ----------------------------------------------------------------------------- * Initialization and Cleanup */ @@ -249,6 +243,7 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) if (lut == NULL) return ERR_PTR(-ENOMEM); + lut->entity.ops = &lut_entity_ops; lut->entity.type = VSP1_ENTITY_LUT; ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops); diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 3311db18f40b..fe2538d5bed1 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -253,10 +253,10 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) if (entity->route && entity->route->reg) vsp1_write(entity->vsp1, entity->route->reg, VI6_DPR_NODE_UNUSED); - - v4l2_subdev_call(&entity->subdev, video, s_stream, 0); } + v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 0); + return ret; } diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index cb3d5ed148cc..eb17fa134750 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -33,13 +33,43 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) } /* ----------------------------------------------------------------------------- - * V4L2 Subdevice Core Operations + * V4L2 Subdevice Operations */ -static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) +static struct v4l2_subdev_pad_ops rpf_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, + .enum_mbus_code = vsp1_rwpf_enum_mbus_code, + .enum_frame_size = vsp1_rwpf_enum_frame_size, + .get_fmt = vsp1_rwpf_get_format, + .set_fmt = vsp1_rwpf_set_format, + .get_selection = vsp1_rwpf_get_selection, + .set_selection = vsp1_rwpf_set_selection, +}; + +static struct v4l2_subdev_ops rpf_ops = { + .pad = &rpf_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void rpf_set_memory(struct vsp1_entity *entity) { - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); - struct vsp1_rwpf *rpf = to_rwpf(subdev); + struct vsp1_rwpf *rpf = entity_to_rwpf(entity); + + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, + rpf->mem.addr[0] + rpf->offsets[0]); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, + rpf->mem.addr[1] + rpf->offsets[1]); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, + rpf->mem.addr[2] + rpf->offsets[1]); +} + +static void rpf_configure(struct vsp1_entity *entity) +{ + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); + struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; const struct v4l2_pix_format_mplane *format = &rpf->format; const struct v4l2_mbus_framefmt *source_format; @@ -50,9 +80,6 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) u32 pstride; u32 infmt; - if (!enable) - return 0; - /* Source size, stride and crop offsets. * * The crop offsets correspond to the location of the crop rectangle top @@ -136,51 +163,11 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); - - return 0; -} - -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Operations - */ - -static struct v4l2_subdev_video_ops rpf_video_ops = { - .s_stream = rpf_s_stream, -}; - -static struct v4l2_subdev_pad_ops rpf_pad_ops = { - .init_cfg = vsp1_entity_init_cfg, - .enum_mbus_code = vsp1_rwpf_enum_mbus_code, - .enum_frame_size = vsp1_rwpf_enum_frame_size, - .get_fmt = vsp1_rwpf_get_format, - .set_fmt = vsp1_rwpf_set_format, - .get_selection = vsp1_rwpf_get_selection, - .set_selection = vsp1_rwpf_set_selection, -}; - -static struct v4l2_subdev_ops rpf_ops = { - .video = &rpf_video_ops, - .pad = &rpf_pad_ops, -}; - -/* ----------------------------------------------------------------------------- - * VSP1 Entity Operations - */ - -static void rpf_set_memory(struct vsp1_entity *entity) -{ - struct vsp1_rwpf *rpf = entity_to_rwpf(entity); - - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, - rpf->mem.addr[0] + rpf->offsets[0]); - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, - rpf->mem.addr[1] + rpf->offsets[1]); - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, - rpf->mem.addr[2] + rpf->offsets[1]); } static const struct vsp1_entity_operations rpf_entity_ops = { .set_memory = rpf_set_memory, + .configure = rpf_configure, }; /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index c9a97ba5a042..e05149eabde9 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -103,47 +103,7 @@ static const struct v4l2_ctrl_config sru_intensity_control = { }; /* ----------------------------------------------------------------------------- - * V4L2 Subdevice Core Operations - */ - -static int sru_s_stream(struct v4l2_subdev *subdev, int enable) -{ - const struct vsp1_sru_param *param; - struct vsp1_sru *sru = to_sru(subdev); - struct v4l2_mbus_framefmt *input; - struct v4l2_mbus_framefmt *output; - u32 ctrl0; - - if (!enable) - return 0; - - input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, - SRU_PAD_SINK); - output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, - SRU_PAD_SOURCE); - - if (input->code == MEDIA_BUS_FMT_ARGB8888_1X32) - ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3 - | VI6_SRU_CTRL0_PARAM4; - else - ctrl0 = VI6_SRU_CTRL0_PARAM3; - - if (input->width != output->width) - ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE; - - param = &vsp1_sru_params[sru->intensity - 1]; - - ctrl0 |= param->ctrl0; - - vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); - vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); - vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); - - return 0; -} - -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Pad Operations + * V4L2 Subdevice Operations */ static int sru_enum_mbus_code(struct v4l2_subdev *subdev, @@ -319,14 +279,6 @@ static int sru_set_format(struct v4l2_subdev *subdev, return 0; } -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Operations - */ - -static struct v4l2_subdev_video_ops sru_video_ops = { - .s_stream = sru_s_stream, -}; - static struct v4l2_subdev_pad_ops sru_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = sru_enum_mbus_code, @@ -336,10 +288,48 @@ static struct v4l2_subdev_pad_ops sru_pad_ops = { }; static struct v4l2_subdev_ops sru_ops = { - .video = &sru_video_ops, .pad = &sru_pad_ops, }; +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void sru_configure(struct vsp1_entity *entity) +{ + const struct vsp1_sru_param *param; + struct vsp1_sru *sru = to_sru(&entity->subdev); + struct v4l2_mbus_framefmt *input; + struct v4l2_mbus_framefmt *output; + u32 ctrl0; + + input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, + SRU_PAD_SINK); + output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, + SRU_PAD_SOURCE); + + if (input->code == MEDIA_BUS_FMT_ARGB8888_1X32) + ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3 + | VI6_SRU_CTRL0_PARAM4; + else + ctrl0 = VI6_SRU_CTRL0_PARAM3; + + if (input->width != output->width) + ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE; + + param = &vsp1_sru_params[sru->intensity - 1]; + + ctrl0 |= param->ctrl0; + + vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); + vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); + vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); +} + +static const struct vsp1_entity_operations sru_entity_ops = { + .configure = sru_configure, +}; + /* ----------------------------------------------------------------------------- * Initialization and Cleanup */ @@ -353,6 +343,7 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) if (sru == NULL) return ERR_PTR(-ENOMEM); + sru->entity.ops = &sru_entity_ops; sru->entity.type = VSP1_ENTITY_SRU; ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 2, &sru_ops); diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 3ba0f6844d1d..1acbdd6d537f 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -104,62 +104,6 @@ static unsigned int uds_compute_ratio(unsigned int input, unsigned int output) return (input - 1) * 4096 / (output - 1); } -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Core Operations - */ - -static int uds_s_stream(struct v4l2_subdev *subdev, int enable) -{ - struct vsp1_uds *uds = to_uds(subdev); - const struct v4l2_mbus_framefmt *output; - const struct v4l2_mbus_framefmt *input; - unsigned int hscale; - unsigned int vscale; - bool multitap; - - if (!enable) - return 0; - - input = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, - UDS_PAD_SINK); - output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, - UDS_PAD_SOURCE); - - hscale = uds_compute_ratio(input->width, output->width); - vscale = uds_compute_ratio(input->height, output->height); - - dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale); - - /* Multi-tap scaling can't be enabled along with alpha scaling when - * scaling down with a factor lower than or equal to 1/2 in either - * direction. - */ - if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192)) - multitap = false; - else - multitap = true; - - vsp1_uds_write(uds, VI6_UDS_CTRL, - (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) | - (multitap ? VI6_UDS_CTRL_BC : 0)); - - vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH, - (uds_passband_width(hscale) - << VI6_UDS_PASS_BWIDTH_H_SHIFT) | - (uds_passband_width(vscale) - << VI6_UDS_PASS_BWIDTH_V_SHIFT)); - - /* Set the scaling ratios and the output size. */ - vsp1_uds_write(uds, VI6_UDS_SCALE, - (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) | - (vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); - vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE, - (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | - (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); - - return 0; -} - /* ----------------------------------------------------------------------------- * V4L2 Subdevice Pad Operations */ @@ -321,10 +265,6 @@ static int uds_set_format(struct v4l2_subdev *subdev, * V4L2 Subdevice Operations */ -static struct v4l2_subdev_video_ops uds_video_ops = { - .s_stream = uds_s_stream, -}; - static struct v4l2_subdev_pad_ops uds_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = uds_enum_mbus_code, @@ -334,10 +274,64 @@ static struct v4l2_subdev_pad_ops uds_pad_ops = { }; static struct v4l2_subdev_ops uds_ops = { - .video = &uds_video_ops, .pad = &uds_pad_ops, }; +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void uds_configure(struct vsp1_entity *entity) +{ + struct vsp1_uds *uds = to_uds(&entity->subdev); + const struct v4l2_mbus_framefmt *output; + const struct v4l2_mbus_framefmt *input; + unsigned int hscale; + unsigned int vscale; + bool multitap; + + input = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, + UDS_PAD_SINK); + output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, + UDS_PAD_SOURCE); + + hscale = uds_compute_ratio(input->width, output->width); + vscale = uds_compute_ratio(input->height, output->height); + + dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale); + + /* Multi-tap scaling can't be enabled along with alpha scaling when + * scaling down with a factor lower than or equal to 1/2 in either + * direction. + */ + if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192)) + multitap = false; + else + multitap = true; + + vsp1_uds_write(uds, VI6_UDS_CTRL, + (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) | + (multitap ? VI6_UDS_CTRL_BC : 0)); + + vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH, + (uds_passband_width(hscale) + << VI6_UDS_PASS_BWIDTH_H_SHIFT) | + (uds_passband_width(vscale) + << VI6_UDS_PASS_BWIDTH_V_SHIFT)); + + /* Set the scaling ratios and the output size. */ + vsp1_uds_write(uds, VI6_UDS_SCALE, + (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) | + (vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); + vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE, + (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | + (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); +} + +static const struct vsp1_entity_operations uds_entity_ops = { + .configure = uds_configure, +}; + /* ----------------------------------------------------------------------------- * Initialization and Cleanup */ @@ -352,6 +346,7 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index) if (uds == NULL) return ERR_PTR(-ENOMEM); + uds->entity.ops = &uds_entity_ops; uds->entity.type = VSP1_ENTITY_UDS; uds->entity.index = index; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index d4a092c8ece3..a3f1145c8a79 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -591,7 +591,6 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) { struct vsp1_entity *entity; - int ret; /* Prepare the display list. */ pipe->dl = vsp1_dl_list_get(pipe->output->dlm); @@ -619,18 +618,14 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) list_for_each_entry(entity, &pipe->entities, list_pipe) { vsp1_entity_route_setup(entity); - ret = v4l2_subdev_call(&entity->subdev, video, s_stream, 1); - if (ret < 0) - goto error; + if (entity->ops->configure) + entity->ops->configure(entity); } - return 0; + /* We know that the WPF s_stream operation never fails. */ + v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 1); -error: - vsp1_dl_list_put(pipe->dl); - pipe->dl = NULL; - - return ret; + return 0; } static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 0797927d14cf..ccf1f960c46a 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -39,55 +39,78 @@ static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) { - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); struct vsp1_rwpf *wpf = to_rwpf(subdev); struct vsp1_device *vsp1 = wpf->entity.vsp1; - const struct v4l2_mbus_framefmt *source_format; - const struct v4l2_mbus_framefmt *sink_format; - const struct v4l2_rect *crop; - unsigned int i; - u32 srcrpf = 0; - u32 outfmt = 0; - if (!enable) { - vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); - vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + - VI6_WPF_SRCRPF, 0); + if (enable) return 0; - } - /* Sources. If the pipeline has a single input and BRU is not used, - * configure it as the master layer. Otherwise configure all - * inputs as sub-layers and select the virtual RPF as the master - * layer. + /* Write to registers directly when stopping the stream as there will be + * no pipeline run to apply the display list. */ - for (i = 0; i < vsp1->info->rpf_count; ++i) { - struct vsp1_rwpf *input = pipe->inputs[i]; + vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); + vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + + VI6_WPF_SRCRPF, 0); - if (!input) - continue; + return 0; +} - srcrpf |= (!pipe->bru && pipe->num_inputs == 1) - ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) - : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); - } +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Operations + */ - if (pipe->bru || pipe->num_inputs > 1) - srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST; +static struct v4l2_subdev_video_ops wpf_video_ops = { + .s_stream = wpf_s_stream, +}; - vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); +static struct v4l2_subdev_pad_ops wpf_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, + .enum_mbus_code = vsp1_rwpf_enum_mbus_code, + .enum_frame_size = vsp1_rwpf_enum_frame_size, + .get_fmt = vsp1_rwpf_get_format, + .set_fmt = vsp1_rwpf_set_format, + .get_selection = vsp1_rwpf_get_selection, + .set_selection = vsp1_rwpf_set_selection, +}; - /* Destination stride. */ - if (!pipe->lif) { - struct v4l2_pix_format_mplane *format = &wpf->format; +static struct v4l2_subdev_ops wpf_ops = { + .video = &wpf_video_ops, + .pad = &wpf_pad_ops, +}; - vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, - format->plane_fmt[0].bytesperline); - if (format->num_planes > 1) - vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_C, - format->plane_fmt[1].bytesperline); - } +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void vsp1_wpf_destroy(struct vsp1_entity *entity) +{ + struct vsp1_rwpf *wpf = entity_to_rwpf(entity); + + vsp1_dlm_destroy(wpf->dlm); +} + +static void wpf_set_memory(struct vsp1_entity *entity) +{ + struct vsp1_rwpf *wpf = entity_to_rwpf(entity); + + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); +} + +static void wpf_configure(struct vsp1_entity *entity) +{ + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); + struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); + struct vsp1_device *vsp1 = wpf->entity.vsp1; + const struct v4l2_mbus_framefmt *source_format; + const struct v4l2_mbus_framefmt *sink_format; + const struct v4l2_rect *crop; + unsigned int i; + u32 outfmt = 0; + u32 srcrpf = 0; + /* Cropping */ crop = vsp1_rwpf_get_crop(wpf, wpf->entity.config); vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | @@ -106,6 +129,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) RWPF_PAD_SOURCE); if (!pipe->lif) { + const struct v4l2_pix_format_mplane *format = &wpf->format; const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; @@ -117,6 +141,13 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) if (fmtinfo->swap_uv) outfmt |= VI6_WPF_OUTFMT_SPUVS; + /* Destination stride and byte swapping. */ + vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, + format->plane_fmt[0].bytesperline); + if (format->num_planes > 1) + vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_C, + format->plane_fmt[1].bytesperline); + vsp1_wpf_write(wpf, VI6_WPF_DSWAP, fmtinfo->swap); } @@ -131,60 +162,37 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_mod_write(&wpf->entity, VI6_WPF_WRBCK_CTRL, 0); - /* Enable interrupts */ - vsp1_write(vsp1, VI6_WPF_IRQ_STA(wpf->entity.index), 0); - vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), - VI6_WFP_IRQ_ENB_FREE); - - return 0; -} - -/* ----------------------------------------------------------------------------- - * V4L2 Subdevice Operations - */ - -static struct v4l2_subdev_video_ops wpf_video_ops = { - .s_stream = wpf_s_stream, -}; - -static struct v4l2_subdev_pad_ops wpf_pad_ops = { - .init_cfg = vsp1_entity_init_cfg, - .enum_mbus_code = vsp1_rwpf_enum_mbus_code, - .enum_frame_size = vsp1_rwpf_enum_frame_size, - .get_fmt = vsp1_rwpf_get_format, - .set_fmt = vsp1_rwpf_set_format, - .get_selection = vsp1_rwpf_get_selection, - .set_selection = vsp1_rwpf_set_selection, -}; - -static struct v4l2_subdev_ops wpf_ops = { - .video = &wpf_video_ops, - .pad = &wpf_pad_ops, -}; + /* Sources. If the pipeline has a single input and BRU is not used, + * configure it as the master layer. Otherwise configure all + * inputs as sub-layers and select the virtual RPF as the master + * layer. + */ + for (i = 0; i < vsp1->info->rpf_count; ++i) { + struct vsp1_rwpf *input = pipe->inputs[i]; -/* ----------------------------------------------------------------------------- - * VSP1 Entity Operations - */ + if (!input) + continue; -static void vsp1_wpf_destroy(struct vsp1_entity *entity) -{ - struct vsp1_rwpf *wpf = entity_to_rwpf(entity); + srcrpf |= (!pipe->bru && pipe->num_inputs == 1) + ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) + : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); + } - vsp1_dlm_destroy(wpf->dlm); -} + if (pipe->bru || pipe->num_inputs > 1) + srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST; -static void wpf_set_memory(struct vsp1_entity *entity) -{ - struct vsp1_rwpf *wpf = entity_to_rwpf(entity); + vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); + /* Enable interrupts */ + vsp1_mod_write(&wpf->entity, VI6_WPF_IRQ_STA(wpf->entity.index), 0); + vsp1_mod_write(&wpf->entity, VI6_WPF_IRQ_ENB(wpf->entity.index), + VI6_WFP_IRQ_ENB_FREE); } static const struct vsp1_entity_operations wpf_entity_ops = { .destroy = vsp1_wpf_destroy, .set_memory = wpf_set_memory, + .configure = wpf_configure, }; /* ----------------------------------------------------------------------------- -- GitLab From c6c8efb656ff213a4d32776c12454b9c9f0c14e4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 22 Nov 2015 13:37:45 -0200 Subject: [PATCH 2591/9938] [media] v4l: vsp1: Merge RPF and WPF pad ops structures The two structures are identical, merge them and move the result to vsp1_rwpf.c. All rwpf pad operations can now be declared static. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 12 +---- drivers/media/platform/vsp1/vsp1_rwpf.c | 60 ++++++++++++++----------- drivers/media/platform/vsp1/vsp1_rwpf.h | 19 +------- drivers/media/platform/vsp1/vsp1_wpf.c | 12 +---- 4 files changed, 38 insertions(+), 65 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index eb17fa134750..84a3aedae768 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -36,18 +36,8 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) * V4L2 Subdevice Operations */ -static struct v4l2_subdev_pad_ops rpf_pad_ops = { - .init_cfg = vsp1_entity_init_cfg, - .enum_mbus_code = vsp1_rwpf_enum_mbus_code, - .enum_frame_size = vsp1_rwpf_enum_frame_size, - .get_fmt = vsp1_rwpf_get_format, - .set_fmt = vsp1_rwpf_set_format, - .get_selection = vsp1_rwpf_get_selection, - .set_selection = vsp1_rwpf_set_selection, -}; - static struct v4l2_subdev_ops rpf_ops = { - .pad = &rpf_pad_ops, + .pad = &vsp1_rwpf_pad_ops, }; /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 0c5ad023adfb..4d302f5cccb2 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -20,13 +20,20 @@ #define RWPF_MIN_WIDTH 1 #define RWPF_MIN_HEIGHT 1 +struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, + struct v4l2_subdev_pad_config *config) +{ + return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, config, + RWPF_PAD_SINK); +} + /* ----------------------------------------------------------------------------- * V4L2 Subdevice Pad Operations */ -int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) +static int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) { static const unsigned int codes[] = { MEDIA_BUS_FMT_ARGB8888_1X32, @@ -41,9 +48,9 @@ int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, return 0; } -int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) +static int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_subdev_pad_config *config; @@ -76,16 +83,9 @@ int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, - struct v4l2_subdev_pad_config *config) -{ - return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, config, - RWPF_PAD_SINK); -} - -int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) +static int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_subdev_pad_config *config; @@ -100,9 +100,9 @@ int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, return 0; } -int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) +static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_subdev_pad_config *config; @@ -154,9 +154,9 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, return 0; } -int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) +static int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_subdev_pad_config *config; @@ -191,9 +191,9 @@ int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, return 0; } -int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) +static int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_subdev_pad_config *config; @@ -250,6 +250,16 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, return 0; } +const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, + .enum_mbus_code = vsp1_rwpf_enum_mbus_code, + .enum_frame_size = vsp1_rwpf_enum_frame_size, + .get_fmt = vsp1_rwpf_get_format, + .set_fmt = vsp1_rwpf_set_format, + .get_selection = vsp1_rwpf_get_selection, + .set_selection = vsp1_rwpf_set_selection, +}; + /* ----------------------------------------------------------------------------- * Controls */ diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 4ebfab61e0ef..9502710977e8 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -68,24 +68,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf); -int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code); -int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse); -int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt); -int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt); -int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel); -int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel); +extern const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops; struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_pad_config *config); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index ccf1f960c46a..80a87f39f06c 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -63,19 +63,9 @@ static struct v4l2_subdev_video_ops wpf_video_ops = { .s_stream = wpf_s_stream, }; -static struct v4l2_subdev_pad_ops wpf_pad_ops = { - .init_cfg = vsp1_entity_init_cfg, - .enum_mbus_code = vsp1_rwpf_enum_mbus_code, - .enum_frame_size = vsp1_rwpf_enum_frame_size, - .get_fmt = vsp1_rwpf_get_format, - .set_fmt = vsp1_rwpf_set_format, - .get_selection = vsp1_rwpf_get_selection, - .set_selection = vsp1_rwpf_set_selection, -}; - static struct v4l2_subdev_ops wpf_ops = { .video = &wpf_video_ops, - .pad = &wpf_pad_ops, + .pad = &vsp1_rwpf_pad_ops, }; /* ----------------------------------------------------------------------------- -- GitLab From b911605dcce9f7ebfea2e8f8833fb73782f55c22 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 22 Nov 2015 14:08:18 -0200 Subject: [PATCH 2592/9938] [media] v4l: vsp1: Use __vsp1_video_try_format to initialize format at init time Reuse the runtime logic to initialize the default format instead of open-coding it. This ensures coherency between intialization and runtime. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index a3f1145c8a79..4dcc892977df 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -958,17 +958,10 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, return ERR_PTR(ret); /* ... and the format ... */ - rwpf->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); - rwpf->format.pixelformat = rwpf->fmtinfo->fourcc; - rwpf->format.colorspace = V4L2_COLORSPACE_SRGB; - rwpf->format.field = V4L2_FIELD_NONE; + rwpf->format.pixelformat = VSP1_VIDEO_DEF_FORMAT; rwpf->format.width = VSP1_VIDEO_DEF_WIDTH; rwpf->format.height = VSP1_VIDEO_DEF_HEIGHT; - rwpf->format.num_planes = 1; - rwpf->format.plane_fmt[0].bytesperline = - rwpf->format.width * rwpf->fmtinfo->bpp[0] / 8; - rwpf->format.plane_fmt[0].sizeimage = - rwpf->format.plane_fmt[0].bytesperline * rwpf->format.height; + __vsp1_video_try_format(video, &rwpf->format, &rwpf->fmtinfo); /* ... and the video node... */ video->video.v4l2_dev = &video->vsp1->v4l2_dev; -- GitLab From 5e8dbbf372fc187de564a8aab635e2da2f7c2153 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 22 Nov 2015 20:29:25 -0200 Subject: [PATCH 2593/9938] [media] v4l: vsp1: Pass display list explicitly to configure functions Modules write register values to the active display list pointed to by the pipeline. In order to support preparing display lists ahead of time, pass them explicitly to all configuration functions. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 22 ++++++------ drivers/media/platform/vsp1/vsp1_drm.c | 14 ++++---- drivers/media/platform/vsp1/vsp1_entity.c | 15 +++----- drivers/media/platform/vsp1/vsp1_entity.h | 14 ++++---- drivers/media/platform/vsp1/vsp1_hsit.c | 12 ++++--- drivers/media/platform/vsp1/vsp1_lif.c | 12 ++++--- drivers/media/platform/vsp1/vsp1_lut.c | 10 +++--- drivers/media/platform/vsp1/vsp1_pipe.c | 3 +- drivers/media/platform/vsp1/vsp1_pipe.h | 1 + drivers/media/platform/vsp1/vsp1_rpf.c | 39 +++++++++++---------- drivers/media/platform/vsp1/vsp1_rwpf.h | 8 +++-- drivers/media/platform/vsp1/vsp1_sru.c | 14 ++++---- drivers/media/platform/vsp1/vsp1_uds.c | 23 +++++++------ drivers/media/platform/vsp1/vsp1_uds.h | 3 +- drivers/media/platform/vsp1/vsp1_video.c | 11 +++--- drivers/media/platform/vsp1/vsp1_wpf.c | 42 +++++++++++------------ 16 files changed, 125 insertions(+), 118 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 4ab0a805d4b2..9795e621eb8e 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -18,6 +18,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_dl.h" #include "vsp1_rwpf.h" #include "vsp1_video.h" @@ -28,9 +29,10 @@ * Device Access */ -static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data) +static inline void vsp1_bru_write(struct vsp1_bru *bru, struct vsp1_dl_list *dl, + u32 reg, u32 data) { - vsp1_mod_write(&bru->entity, reg, data); + vsp1_dl_list_write(dl, reg, data); } /* ----------------------------------------------------------------------------- @@ -303,7 +305,7 @@ static struct v4l2_subdev_ops bru_ops = { * VSP1 Entity Operations */ -static void bru_configure(struct vsp1_entity *entity) +static void bru_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); struct vsp1_bru *bru = to_bru(&entity->subdev); @@ -324,26 +326,26 @@ static void bru_configure(struct vsp1_entity *entity) * format at the pipeline output is premultiplied. */ flags = pipe->output ? pipe->output->format.flags : 0; - vsp1_bru_write(bru, VI6_BRU_INCTRL, + vsp1_bru_write(bru, dl, VI6_BRU_INCTRL, flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? 0 : VI6_BRU_INCTRL_NRM); /* Set the background position to cover the whole output image and * configure its color. */ - vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, + vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_SIZE, (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); - vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); + vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_LOC, 0); - vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, bru->bgcolor | + vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_COL, bru->bgcolor | (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT)); /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP * unit with a NOP operation to make BRU input 1 available as the * Blend/ROP unit B SRC input. */ - vsp1_bru_write(bru, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) | + vsp1_bru_write(bru, dl, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) | VI6_BRU_ROP_CROP(VI6_ROP_NOP) | VI6_BRU_ROP_AROP(VI6_ROP_NOP)); @@ -380,7 +382,7 @@ static void bru_configure(struct vsp1_entity *entity) if (i != 1) ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); - vsp1_bru_write(bru, VI6_BRU_CTRL(i), ctrl); + vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl); /* Harcode the blending formula to * @@ -394,7 +396,7 @@ static void bru_configure(struct vsp1_entity *entity) * * otherwise. */ - vsp1_bru_write(bru, VI6_BRU_BLD(i), + vsp1_bru_write(bru, dl, VI6_BRU_BLD(i), VI6_BRU_BLD_CCMDX_255_SRC_A | (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY : VI6_BRU_BLD_CCMDY_SRC_A) | diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index bec7a651d152..a9735b199a4b 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -455,24 +455,22 @@ void vsp1_du_atomic_flush(struct device *dev) struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); if (!pipe->inputs[rpf->entity.index]) { - vsp1_mod_write(entity, entity->route->reg, - VI6_DPR_NODE_UNUSED); + vsp1_dl_list_write(pipe->dl, entity->route->reg, + VI6_DPR_NODE_UNUSED); continue; } } - vsp1_entity_route_setup(entity); + vsp1_entity_route_setup(entity, pipe->dl); if (entity->ops->configure) - entity->ops->configure(entity); + entity->ops->configure(entity, pipe->dl); if (entity->type == VSP1_ENTITY_RPF) - vsp1_rwpf_set_memory(to_rwpf(&entity->subdev)); + vsp1_rwpf_set_memory(to_rwpf(&entity->subdev), + pipe->dl); } - /* We know that the WPF s_stream operation never fails. */ - v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 1); - vsp1_dl_list_commit(pipe->dl); pipe->dl = NULL; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 09c9a1b86e3a..e9dd4dbda2dc 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -21,16 +21,9 @@ #include "vsp1.h" #include "vsp1_dl.h" #include "vsp1_entity.h" -#include "vsp1_pipe.h" -void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data) -{ - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity); - - vsp1_dl_list_write(pipe->dl, reg, data); -} - -void vsp1_entity_route_setup(struct vsp1_entity *source) +void vsp1_entity_route_setup(struct vsp1_entity *source, + struct vsp1_dl_list *dl) { struct vsp1_entity *sink; @@ -38,8 +31,8 @@ void vsp1_entity_route_setup(struct vsp1_entity *source) return; sink = container_of(source->sink, struct vsp1_entity, subdev.entity); - vsp1_mod_write(source, source->route->reg, - sink->route->inputs[source->sink_pad]); + vsp1_dl_list_write(dl, source->route->reg, + sink->route->inputs[source->sink_pad]); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index fe164f3163bc..f0a718ceaefe 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -19,6 +19,7 @@ #include struct vsp1_device; +struct vsp1_dl_list; enum vsp1_entity_type { VSP1_ENTITY_BRU, @@ -57,15 +58,15 @@ struct vsp1_route { * struct vsp1_entity_operations - Entity operations * @destroy: Destroy the entity. * @set_memory: Setup memory buffer access. This operation applies the settings - * stored in the rwpf mem field to the hardware. Valid for RPF and - * WPF only. + * stored in the rwpf mem field to the display list. Valid for RPF + * and WPF only. * @configure: Setup the hardware based on the entity state (pipeline, formats, * selection rectangles, ...) */ struct vsp1_entity_operations { void (*destroy)(struct vsp1_entity *); - void (*set_memory)(struct vsp1_entity *); - void (*configure)(struct vsp1_entity *); + void (*set_memory)(struct vsp1_entity *, struct vsp1_dl_list *dl); + void (*configure)(struct vsp1_entity *, struct vsp1_dl_list *dl); }; struct vsp1_entity { @@ -121,8 +122,7 @@ vsp1_entity_get_pad_compose(struct vsp1_entity *entity, int vsp1_entity_init_cfg(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg); -void vsp1_entity_route_setup(struct vsp1_entity *source); - -void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data); +void vsp1_entity_route_setup(struct vsp1_entity *source, + struct vsp1_dl_list *dl); #endif /* __VSP1_ENTITY_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 7360586c902a..4fcdb30d08c4 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -17,6 +17,7 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_hsit.h" #define HSIT_MIN_SIZE 4U @@ -26,9 +27,10 @@ * Device Access */ -static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data) +static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, + struct vsp1_dl_list *dl, u32 reg, u32 data) { - vsp1_mod_write(&hsit->entity, reg, data); + vsp1_dl_list_write(dl, reg, data); } /* ----------------------------------------------------------------------------- @@ -164,14 +166,14 @@ static struct v4l2_subdev_ops hsit_ops = { * VSP1 Entity Operations */ -static void hsit_configure(struct vsp1_entity *entity) +static void hsit_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_hsit *hsit = to_hsit(&entity->subdev); if (hsit->inverse) - vsp1_hsit_write(hsit, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); + vsp1_hsit_write(hsit, dl, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); else - vsp1_hsit_write(hsit, VI6_HST_CTRL, VI6_HST_CTRL_EN); + vsp1_hsit_write(hsit, dl, VI6_HST_CTRL, VI6_HST_CTRL_EN); } static const struct vsp1_entity_operations hsit_entity_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index d8d8d3b6c129..bed1784cccb9 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -17,6 +17,7 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_lif.h" #define LIF_MIN_SIZE 2U @@ -26,9 +27,10 @@ * Device Access */ -static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data) +static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl, + u32 reg, u32 data) { - vsp1_mod_write(&lif->entity, reg, data); + vsp1_dl_list_write(dl, reg, data); } /* ----------------------------------------------------------------------------- @@ -183,7 +185,7 @@ static struct v4l2_subdev_ops lif_ops = { * VSP1 Entity Operations */ -static void lif_configure(struct vsp1_entity *entity) +static void lif_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { const struct v4l2_mbus_framefmt *format; struct vsp1_lif *lif = to_lif(&entity->subdev); @@ -196,11 +198,11 @@ static void lif_configure(struct vsp1_entity *entity) obth = min(obth, (format->width + 1) / 2 * format->height - 4); - vsp1_lif_write(lif, VI6_LIF_CSBTH, + vsp1_lif_write(lif, dl, VI6_LIF_CSBTH, (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | (lbth << VI6_LIF_CSBTH_LBTH_SHIFT)); - vsp1_lif_write(lif, VI6_LIF_CTRL, + vsp1_lif_write(lif, dl, VI6_LIF_CTRL, (obth << VI6_LIF_CTRL_OBTH_SHIFT) | (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index d5d32ce10f41..ec0b9bf53d1f 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -18,6 +18,7 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_lut.h" #define LUT_MIN_SIZE 4U @@ -27,9 +28,10 @@ * Device Access */ -static inline void vsp1_lut_write(struct vsp1_lut *lut, u32 reg, u32 data) +static inline void vsp1_lut_write(struct vsp1_lut *lut, struct vsp1_dl_list *dl, + u32 reg, u32 data) { - vsp1_mod_write(&lut->entity, reg, data); + vsp1_dl_list_write(dl, reg, data); } /* ----------------------------------------------------------------------------- @@ -219,11 +221,11 @@ static struct v4l2_subdev_ops lut_ops = { * VSP1 Entity Operations */ -static void lut_configure(struct vsp1_entity *entity) +static void lut_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_lut *lut = to_lut(&entity->subdev); - vsp1_lut_write(lut, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); + vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); } static const struct vsp1_entity_operations lut_entity_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index fe2538d5bed1..4d06519f717d 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -295,6 +295,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) */ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, struct vsp1_entity *input, + struct vsp1_dl_list *dl, unsigned int alpha) { struct vsp1_entity *entity; @@ -317,7 +318,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, if (entity->type == VSP1_ENTITY_UDS) { struct vsp1_uds *uds = to_uds(&entity->subdev); - vsp1_uds_set_alpha(uds, alpha); + vsp1_uds_set_alpha(uds, dl, alpha); break; } diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index f4bdfc943add..1100229a1ed2 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -123,6 +123,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, struct vsp1_entity *input, + struct vsp1_dl_list *dl, unsigned int alpha); void vsp1_pipelines_suspend(struct vsp1_device *vsp1); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 84a3aedae768..ce408e4467af 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -16,6 +16,7 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_rwpf.h" #include "vsp1_video.h" @@ -26,10 +27,10 @@ * Device Access */ -static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) +static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, + struct vsp1_dl_list *dl, u32 reg, u32 data) { - vsp1_mod_write(&rpf->entity, reg + rpf->entity.index * VI6_RPF_OFFSET, - data); + vsp1_dl_list_write(dl, reg + rpf->entity.index * VI6_RPF_OFFSET, data); } /* ----------------------------------------------------------------------------- @@ -44,19 +45,19 @@ static struct v4l2_subdev_ops rpf_ops = { * VSP1 Entity Operations */ -static void rpf_set_memory(struct vsp1_entity *entity) +static void rpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_rwpf *rpf = entity_to_rwpf(entity); - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y, rpf->mem.addr[0] + rpf->offsets[0]); - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0, rpf->mem.addr[1] + rpf->offsets[1]); - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1, rpf->mem.addr[2] + rpf->offsets[1]); } -static void rpf_configure(struct vsp1_entity *entity) +static void rpf_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); @@ -78,10 +79,10 @@ static void rpf_configure(struct vsp1_entity *entity) */ crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config); - vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE, + vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE, (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); - vsp1_rpf_write(rpf, VI6_RPF_SRC_ESIZE, + vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE, (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); @@ -99,7 +100,7 @@ static void rpf_configure(struct vsp1_entity *entity) rpf->offsets[1] = 0; } - vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_PSTRIDE, pstride); /* Format */ sink_format = vsp1_entity_get_pad_format(&rpf->entity, @@ -120,8 +121,8 @@ static void rpf_configure(struct vsp1_entity *entity) if (sink_format->code != source_format->code) infmt |= VI6_RPF_INFMT_CSC; - vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); - vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); + vsp1_rpf_write(rpf, dl, VI6_RPF_INFMT, infmt); + vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap); /* Output location */ if (pipe->bru) { @@ -134,7 +135,7 @@ static void rpf_configure(struct vsp1_entity *entity) top = compose->top; } - vsp1_rpf_write(rpf, VI6_RPF_LOC, + vsp1_rpf_write(rpf, dl, VI6_RPF_LOC, (left << VI6_RPF_LOC_HCOORD_SHIFT) | (top << VI6_RPF_LOC_VCOORD_SHIFT)); @@ -142,17 +143,17 @@ static void rpf_configure(struct vsp1_entity *entity) * alpha value set through the V4L2_CID_ALPHA_COMPONENT control * otherwise. Disable color keying. */ - vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT | + vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT | (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED : VI6_RPF_ALPH_SEL_ASEL_FIXED)); - vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, + vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET, rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); - vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha); + vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, dl, rpf->alpha); - vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); - vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); + vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0); + vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0); } static const struct vsp1_entity_operations rpf_entity_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 9502710977e8..38c8c902db52 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -75,12 +75,14 @@ struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, /** * vsp1_rwpf_set_memory - Configure DMA addresses for a [RW]PF * @rwpf: the [RW]PF instance + * @dl: the display list * - * This function applies the cached memory buffer address to the hardware. + * This function applies the cached memory buffer address to the display list. */ -static inline void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf) +static inline void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf, + struct vsp1_dl_list *dl) { - rwpf->entity.ops->set_memory(&rwpf->entity); + rwpf->entity.ops->set_memory(&rwpf->entity, dl); } #endif /* __VSP1_RWPF_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index e05149eabde9..6c1cb4ccba22 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -17,6 +17,7 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_sru.h" #define SRU_MIN_SIZE 4U @@ -26,9 +27,10 @@ * Device Access */ -static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data) +static inline void vsp1_sru_write(struct vsp1_sru *sru, struct vsp1_dl_list *dl, + u32 reg, u32 data) { - vsp1_mod_write(&sru->entity, reg, data); + vsp1_dl_list_write(dl, reg, data); } /* ----------------------------------------------------------------------------- @@ -295,7 +297,7 @@ static struct v4l2_subdev_ops sru_ops = { * VSP1 Entity Operations */ -static void sru_configure(struct vsp1_entity *entity) +static void sru_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { const struct vsp1_sru_param *param; struct vsp1_sru *sru = to_sru(&entity->subdev); @@ -321,9 +323,9 @@ static void sru_configure(struct vsp1_entity *entity) ctrl0 |= param->ctrl0; - vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); - vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); - vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); + vsp1_sru_write(sru, dl, VI6_SRU_CTRL0, ctrl0); + vsp1_sru_write(sru, dl, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); + vsp1_sru_write(sru, dl, VI6_SRU_CTRL2, param->ctrl2); } static const struct vsp1_entity_operations sru_entity_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 1acbdd6d537f..90e7d7141160 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -17,6 +17,7 @@ #include #include "vsp1.h" +#include "vsp1_dl.h" #include "vsp1_uds.h" #define UDS_MIN_SIZE 4U @@ -29,19 +30,21 @@ * Device Access */ -static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data) +static inline void vsp1_uds_write(struct vsp1_uds *uds, struct vsp1_dl_list *dl, + u32 reg, u32 data) { - vsp1_mod_write(&uds->entity, reg + uds->entity.index * VI6_UDS_OFFSET, - data); + vsp1_dl_list_write(dl, reg + uds->entity.index * VI6_UDS_OFFSET, data); } /* ----------------------------------------------------------------------------- * Scaling Computation */ -void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha) +void vsp1_uds_set_alpha(struct vsp1_uds *uds, struct vsp1_dl_list *dl, + unsigned int alpha) { - vsp1_uds_write(uds, VI6_UDS_ALPVAL, alpha << VI6_UDS_ALPVAL_VAL0_SHIFT); + vsp1_uds_write(uds, dl, VI6_UDS_ALPVAL, + alpha << VI6_UDS_ALPVAL_VAL0_SHIFT); } /* @@ -281,7 +284,7 @@ static struct v4l2_subdev_ops uds_ops = { * VSP1 Entity Operations */ -static void uds_configure(struct vsp1_entity *entity) +static void uds_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_uds *uds = to_uds(&entity->subdev); const struct v4l2_mbus_framefmt *output; @@ -309,21 +312,21 @@ static void uds_configure(struct vsp1_entity *entity) else multitap = true; - vsp1_uds_write(uds, VI6_UDS_CTRL, + vsp1_uds_write(uds, dl, VI6_UDS_CTRL, (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) | (multitap ? VI6_UDS_CTRL_BC : 0)); - vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH, + vsp1_uds_write(uds, dl, VI6_UDS_PASS_BWIDTH, (uds_passband_width(hscale) << VI6_UDS_PASS_BWIDTH_H_SHIFT) | (uds_passband_width(vscale) << VI6_UDS_PASS_BWIDTH_V_SHIFT)); /* Set the scaling ratios and the output size. */ - vsp1_uds_write(uds, VI6_UDS_SCALE, + vsp1_uds_write(uds, dl, VI6_UDS_SCALE, (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) | (vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); - vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE, + vsp1_uds_write(uds, dl, VI6_UDS_CLIP_SIZE, (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); } diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h index 031ac0da1b66..5c8cbfcad4cc 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.h +++ b/drivers/media/platform/vsp1/vsp1_uds.h @@ -35,6 +35,7 @@ static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev) struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index); -void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha); +void vsp1_uds_set_alpha(struct vsp1_uds *uds, struct vsp1_dl_list *dl, + unsigned int alpha); #endif /* __VSP1_UDS_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 4dcc892977df..a45bf68e0ba1 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -455,11 +455,11 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) struct vsp1_rwpf *rwpf = pipe->inputs[i]; if (rwpf) - vsp1_rwpf_set_memory(rwpf); + vsp1_rwpf_set_memory(rwpf, pipe->dl); } if (!pipe->lif) - vsp1_rwpf_set_memory(pipe->output); + vsp1_rwpf_set_memory(pipe->output, pipe->dl); vsp1_dl_list_commit(pipe->dl); pipe->dl = NULL; @@ -616,15 +616,12 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) } list_for_each_entry(entity, &pipe->entities, list_pipe) { - vsp1_entity_route_setup(entity); + vsp1_entity_route_setup(entity, pipe->dl); if (entity->ops->configure) - entity->ops->configure(entity); + entity->ops->configure(entity, pipe->dl); } - /* We know that the WPF s_stream operation never fails. */ - v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 1); - return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 80a87f39f06c..e2c558dbac13 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -27,10 +27,10 @@ * Device Access */ -static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) +static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, + struct vsp1_dl_list *dl, u32 reg, u32 data) { - vsp1_mod_write(&wpf->entity, - reg + wpf->entity.index * VI6_WPF_OFFSET, data); + vsp1_dl_list_write(dl, reg + wpf->entity.index * VI6_WPF_OFFSET, data); } /* ----------------------------------------------------------------------------- @@ -79,16 +79,16 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity) vsp1_dlm_destroy(wpf->dlm); } -static void wpf_set_memory(struct vsp1_entity *entity) +static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_rwpf *wpf = entity_to_rwpf(entity); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]); + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]); + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); } -static void wpf_configure(struct vsp1_entity *entity) +static void wpf_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); @@ -103,10 +103,10 @@ static void wpf_configure(struct vsp1_entity *entity) /* Cropping */ crop = vsp1_rwpf_get_crop(wpf, wpf->entity.config); - vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | + vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | (crop->left << VI6_WPF_SZCLIP_OFST_SHIFT) | (crop->width << VI6_WPF_SZCLIP_SIZE_SHIFT)); - vsp1_wpf_write(wpf, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN | + vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN | (crop->top << VI6_WPF_SZCLIP_OFST_SHIFT) | (crop->height << VI6_WPF_SZCLIP_SIZE_SHIFT)); @@ -132,25 +132,25 @@ static void wpf_configure(struct vsp1_entity *entity) outfmt |= VI6_WPF_OUTFMT_SPUVS; /* Destination stride and byte swapping. */ - vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_Y, format->plane_fmt[0].bytesperline); if (format->num_planes > 1) - vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_C, + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_C, format->plane_fmt[1].bytesperline); - vsp1_wpf_write(wpf, VI6_WPF_DSWAP, fmtinfo->swap); + vsp1_wpf_write(wpf, dl, VI6_WPF_DSWAP, fmtinfo->swap); } if (sink_format->code != source_format->code) outfmt |= VI6_WPF_OUTFMT_CSC; outfmt |= wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT; - vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); + vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt); - vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index), - VI6_DPR_WPF_FPORCH_FP_WPFN); + vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index), + VI6_DPR_WPF_FPORCH_FP_WPFN); - vsp1_mod_write(&wpf->entity, VI6_WPF_WRBCK_CTRL, 0); + vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0); /* Sources. If the pipeline has a single input and BRU is not used, * configure it as the master layer. Otherwise configure all @@ -171,12 +171,12 @@ static void wpf_configure(struct vsp1_entity *entity) if (pipe->bru || pipe->num_inputs > 1) srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST; - vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); + vsp1_wpf_write(wpf, dl, VI6_WPF_SRCRPF, srcrpf); /* Enable interrupts */ - vsp1_mod_write(&wpf->entity, VI6_WPF_IRQ_STA(wpf->entity.index), 0); - vsp1_mod_write(&wpf->entity, VI6_WPF_IRQ_ENB(wpf->entity.index), - VI6_WFP_IRQ_ENB_FREE); + vsp1_dl_list_write(dl, VI6_WPF_IRQ_STA(wpf->entity.index), 0); + vsp1_dl_list_write(dl, VI6_WPF_IRQ_ENB(wpf->entity.index), + VI6_WFP_IRQ_ENB_FREE); } static const struct vsp1_entity_operations wpf_entity_ops = { -- GitLab From d2219824cb4a41013292590c1b00a047f356afa4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 19 Jan 2016 19:42:56 -0200 Subject: [PATCH 2594/9938] [media] v4l: vsp1: Rename pipeline validate functions to pipeline build The primary purpose of those functions is to build the pipeline, rename them to make this clearer. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index a45bf68e0ba1..ddf440dc9a9c 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -172,9 +172,9 @@ static int __vsp1_video_try_format(struct vsp1_video *video, * Pipeline Management */ -static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, - struct vsp1_rwpf *input, - struct vsp1_rwpf *output) +static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe, + struct vsp1_rwpf *input, + struct vsp1_rwpf *output) { struct media_entity_enum ent_enum; struct vsp1_entity *entity; @@ -257,8 +257,8 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, return ret; } -static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, - struct vsp1_video *video) +static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe, + struct vsp1_video *video) { struct media_entity_graph graph; struct media_entity *entity = &video->video.entity; @@ -321,8 +321,8 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, if (!pipe->inputs[i]) continue; - ret = vsp1_video_pipeline_validate_branch(pipe, pipe->inputs[i], - pipe->output); + ret = vsp1_video_pipeline_build_branch(pipe, pipe->inputs[i], + pipe->output); if (ret < 0) goto error; } @@ -341,9 +341,9 @@ static int vsp1_video_pipeline_init(struct vsp1_pipeline *pipe, mutex_lock(&pipe->lock); - /* If we're the first user validate and initialize the pipeline. */ + /* If we're the first user build and validate the pipeline. */ if (pipe->use_count == 0) { - ret = vsp1_video_pipeline_validate(pipe, video); + ret = vsp1_video_pipeline_build(pipe, video); if (ret < 0) goto done; } -- GitLab From 83dd019d308d3c1529df1c7da96c3bdb895947e4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 14 Jan 2016 14:17:32 -0200 Subject: [PATCH 2595/9938] [media] v4l: vsp1: Pass pipe pointer to entity configure functions Pass the pipe explicitly instead of retrieving it through media entities. This decouples device state stored in the pipeline from the active state stored in entities, preparing for dynamic pipeline creation. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 5 +++-- drivers/media/platform/vsp1/vsp1_drm.c | 2 +- drivers/media/platform/vsp1/vsp1_entity.h | 4 +++- drivers/media/platform/vsp1/vsp1_hsit.c | 4 +++- drivers/media/platform/vsp1/vsp1_lif.c | 4 +++- drivers/media/platform/vsp1/vsp1_lut.c | 4 +++- drivers/media/platform/vsp1/vsp1_rpf.c | 5 +++-- drivers/media/platform/vsp1/vsp1_sru.c | 4 +++- drivers/media/platform/vsp1/vsp1_uds.c | 4 +++- drivers/media/platform/vsp1/vsp1_video.c | 2 +- drivers/media/platform/vsp1/vsp1_wpf.c | 5 +++-- 11 files changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 9795e621eb8e..3ece40245396 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -305,9 +305,10 @@ static struct v4l2_subdev_ops bru_ops = { * VSP1 Entity Operations */ -static void bru_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void bru_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); struct vsp1_bru *bru = to_bru(&entity->subdev); struct v4l2_mbus_framefmt *format; unsigned int flags; diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index a9735b199a4b..7cde2d970dba 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -464,7 +464,7 @@ void vsp1_du_atomic_flush(struct device *dev) vsp1_entity_route_setup(entity, pipe->dl); if (entity->ops->configure) - entity->ops->configure(entity, pipe->dl); + entity->ops->configure(entity, pipe, pipe->dl); if (entity->type == VSP1_ENTITY_RPF) vsp1_rwpf_set_memory(to_rwpf(&entity->subdev), diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index f0a718ceaefe..bbf378437c3b 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -20,6 +20,7 @@ struct vsp1_device; struct vsp1_dl_list; +struct vsp1_pipeline; enum vsp1_entity_type { VSP1_ENTITY_BRU, @@ -66,7 +67,8 @@ struct vsp1_route { struct vsp1_entity_operations { void (*destroy)(struct vsp1_entity *); void (*set_memory)(struct vsp1_entity *, struct vsp1_dl_list *dl); - void (*configure)(struct vsp1_entity *, struct vsp1_dl_list *dl); + void (*configure)(struct vsp1_entity *, struct vsp1_pipeline *, + struct vsp1_dl_list *); }; struct vsp1_entity { diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 4fcdb30d08c4..f02e4ca77a7c 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -166,7 +166,9 @@ static struct v4l2_subdev_ops hsit_ops = { * VSP1 Entity Operations */ -static void hsit_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void hsit_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { struct vsp1_hsit *hsit = to_hsit(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index bed1784cccb9..42ed8f80cc88 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -185,7 +185,9 @@ static struct v4l2_subdev_ops lif_ops = { * VSP1 Entity Operations */ -static void lif_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void lif_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { const struct v4l2_mbus_framefmt *format; struct vsp1_lif *lif = to_lif(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index ec0b9bf53d1f..596537a95210 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -221,7 +221,9 @@ static struct v4l2_subdev_ops lut_ops = { * VSP1 Entity Operations */ -static void lut_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void lut_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { struct vsp1_lut *lut = to_lut(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index ce408e4467af..e7b6abbb0024 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -57,9 +57,10 @@ static void rpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl) rpf->mem.addr[2] + rpf->offsets[1]); } -static void rpf_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void rpf_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; const struct v4l2_pix_format_mplane *format = &rpf->format; diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 6c1cb4ccba22..00edd95093e3 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -297,7 +297,9 @@ static struct v4l2_subdev_ops sru_ops = { * VSP1 Entity Operations */ -static void sru_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void sru_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { const struct vsp1_sru_param *param; struct vsp1_sru *sru = to_sru(&entity->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 90e7d7141160..42f2d0465bd6 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -284,7 +284,9 @@ static struct v4l2_subdev_ops uds_ops = { * VSP1 Entity Operations */ -static void uds_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void uds_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { struct vsp1_uds *uds = to_uds(&entity->subdev); const struct v4l2_mbus_framefmt *output; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index ddf440dc9a9c..a16a661e5b69 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -619,7 +619,7 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) vsp1_entity_route_setup(entity, pipe->dl); if (entity->ops->configure) - entity->ops->configure(entity, pipe->dl); + entity->ops->configure(entity, pipe, pipe->dl); } return 0; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index e2c558dbac13..d1d5c08ca35e 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -88,9 +88,10 @@ static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl) vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]); } -static void wpf_configure(struct vsp1_entity *entity, struct vsp1_dl_list *dl) +static void wpf_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl) { - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&entity->subdev.entity); struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); struct vsp1_device *vsp1 = wpf->entity.vsp1; const struct v4l2_mbus_framefmt *source_format; -- GitLab From ff7e97c94d9f7f370fe3ce2a72e85361ca22a605 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 19 Jan 2016 19:16:36 -0200 Subject: [PATCH 2596/9938] [media] v4l: vsp1: Store pipeline pointer in rwpf This prepares for dynamic pipeline allocation by providing a field that can be used to store the pipeline pointer atomically under driver control. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drv.c | 4 +--- drivers/media/platform/vsp1/vsp1_pipe.c | 14 +++++++++----- drivers/media/platform/vsp1/vsp1_pipe.h | 8 -------- drivers/media/platform/vsp1/vsp1_rwpf.h | 2 ++ drivers/media/platform/vsp1/vsp1_video.c | 13 +++++++------ 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index bfdc01c9172d..f1be2680013d 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -49,17 +49,15 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf = vsp1->wpf[i]; - struct vsp1_pipeline *pipe; if (wpf == NULL) continue; - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i)); vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask); if (status & VI6_WFP_IRQ_STA_FRE) { - vsp1_pipeline_frame_end(pipe); + vsp1_pipeline_frame_end(wpf->pipe); ret = IRQ_HANDLED; } } diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 4d06519f717d..8ac080f87b08 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -172,14 +172,18 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe) bru->inputs[i].rpf = NULL; } - for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) + for (i = 0; i < pipe->num_inputs; ++i) { + pipe->inputs[i]->pipe = NULL; pipe->inputs[i] = NULL; + } + + pipe->output->pipe = NULL; + pipe->output = NULL; INIT_LIST_HEAD(&pipe->entities); pipe->state = VSP1_PIPELINE_STOPPED; pipe->buffers_ready = 0; pipe->num_inputs = 0; - pipe->output = NULL; pipe->bru = NULL; pipe->lif = NULL; pipe->uds = NULL; @@ -344,7 +348,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1) if (wpf == NULL) continue; - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); + pipe = wpf->pipe; if (pipe == NULL) continue; @@ -361,7 +365,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1) if (wpf == NULL) continue; - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); + pipe = wpf->pipe; if (pipe == NULL) continue; @@ -385,7 +389,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1) if (wpf == NULL) continue; - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); + pipe = wpf->pipe; if (pipe == NULL) continue; diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index 1100229a1ed2..9fd688bfe638 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -103,14 +103,6 @@ struct vsp1_pipeline { struct vsp1_dl_list *dl; }; -static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) -{ - if (likely(e->pipe)) - return container_of(e->pipe, struct vsp1_pipeline, pipe); - else - return NULL; -} - void vsp1_pipeline_reset(struct vsp1_pipeline *pipe); void vsp1_pipeline_init(struct vsp1_pipeline *pipe); diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 38c8c902db52..9ff7c78f239e 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -25,6 +25,7 @@ struct v4l2_ctrl; struct vsp1_dl_manager; +struct vsp1_pipeline; struct vsp1_rwpf; struct vsp1_video; @@ -36,6 +37,7 @@ struct vsp1_rwpf { struct vsp1_entity entity; struct v4l2_ctrl_handler ctrls; + struct vsp1_pipeline *pipe; struct vsp1_video *video; unsigned int max_width; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index a16a661e5b69..2c642726a259 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -293,10 +293,12 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe, rwpf = to_rwpf(subdev); pipe->inputs[rwpf->entity.index] = rwpf; rwpf->video->pipe_index = ++pipe->num_inputs; + rwpf->pipe = pipe; } else if (e->type == VSP1_ENTITY_WPF) { rwpf = to_rwpf(subdev); pipe->output = rwpf; rwpf->video->pipe_index = 0; + rwpf->pipe = pipe; } else if (e->type == VSP1_ENTITY_LIF) { pipe->lif = e; } else if (e->type == VSP1_ENTITY_BRU) { @@ -384,7 +386,7 @@ static void vsp1_video_pipeline_cleanup(struct vsp1_pipeline *pipe) static struct vsp1_vb2_buffer * vsp1_video_complete_buffer(struct vsp1_video *video) { - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); + struct vsp1_pipeline *pipe = video->rwpf->pipe; struct vsp1_vb2_buffer *next = NULL; struct vsp1_vb2_buffer *done; unsigned long flags; @@ -563,7 +565,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); + struct vsp1_pipeline *pipe = video->rwpf->pipe; struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf); unsigned long flags; bool empty; @@ -628,7 +630,7 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) { struct vsp1_video *video = vb2_get_drv_priv(vq); - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); + struct vsp1_pipeline *pipe = video->rwpf->pipe; unsigned long flags; int ret; @@ -655,7 +657,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) static void vsp1_video_stop_streaming(struct vb2_queue *vq) { struct vsp1_video *video = vb2_get_drv_priv(vq); - struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); + struct vsp1_pipeline *pipe = video->rwpf->pipe; struct vsp1_vb2_buffer *buffer; unsigned long flags; int ret; @@ -802,8 +804,7 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) * FIXME: This is racy, the ioctl is only protected by the video node * lock. */ - pipe = video->video.entity.pipe - ? to_vsp1_pipeline(&video->video.entity) : &video->pipe; + pipe = video->rwpf->pipe ? video->rwpf->pipe : &video->pipe; ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe); if (ret < 0) -- GitLab From 76c29755960c911b4e1bec3da90d4d5f6b44d3f3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 17 Jan 2016 19:55:18 -0200 Subject: [PATCH 2597/9938] [media] v4l: vsp1: video: Reorder functions Move the pipeline initialization and cleanup functions to prepare for the next commit. No functional code change is performed here. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 266 +++++++++++------------ 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 2c642726a259..4396018d1408 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -172,6 +172,139 @@ static int __vsp1_video_try_format(struct vsp1_video *video, * Pipeline Management */ +/* + * vsp1_video_complete_buffer - Complete the current buffer + * @video: the video node + * + * This function completes the current buffer by filling its sequence number, + * time stamp and payload size, and hands it back to the videobuf core. + * + * When operating in DU output mode (deep pipeline to the DU through the LIF), + * the VSP1 needs to constantly supply frames to the display. In that case, if + * no other buffer is queued, reuse the one that has just been processed instead + * of handing it back to the videobuf core. + * + * Return the next queued buffer or NULL if the queue is empty. + */ +static struct vsp1_vb2_buffer * +vsp1_video_complete_buffer(struct vsp1_video *video) +{ + struct vsp1_pipeline *pipe = video->rwpf->pipe; + struct vsp1_vb2_buffer *next = NULL; + struct vsp1_vb2_buffer *done; + unsigned long flags; + unsigned int i; + + spin_lock_irqsave(&video->irqlock, flags); + + if (list_empty(&video->irqqueue)) { + spin_unlock_irqrestore(&video->irqlock, flags); + return NULL; + } + + done = list_first_entry(&video->irqqueue, + struct vsp1_vb2_buffer, queue); + + /* In DU output mode reuse the buffer if the list is singular. */ + if (pipe->lif && list_is_singular(&video->irqqueue)) { + spin_unlock_irqrestore(&video->irqlock, flags); + return done; + } + + list_del(&done->queue); + + if (!list_empty(&video->irqqueue)) + next = list_first_entry(&video->irqqueue, + struct vsp1_vb2_buffer, queue); + + spin_unlock_irqrestore(&video->irqlock, flags); + + done->buf.sequence = video->sequence++; + done->buf.vb2_buf.timestamp = ktime_get_ns(); + for (i = 0; i < done->buf.vb2_buf.num_planes; ++i) + vb2_set_plane_payload(&done->buf.vb2_buf, i, + vb2_plane_size(&done->buf.vb2_buf, i)); + vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE); + + return next; +} + +static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, + struct vsp1_rwpf *rwpf) +{ + struct vsp1_video *video = rwpf->video; + struct vsp1_vb2_buffer *buf; + unsigned long flags; + + buf = vsp1_video_complete_buffer(video); + if (buf == NULL) + return; + + spin_lock_irqsave(&pipe->irqlock, flags); + + video->rwpf->mem = buf->mem; + pipe->buffers_ready |= 1 << video->pipe_index; + + spin_unlock_irqrestore(&pipe->irqlock, flags); +} + +static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) +{ + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + unsigned int i; + + if (!pipe->dl) + pipe->dl = vsp1_dl_list_get(pipe->output->dlm); + + for (i = 0; i < vsp1->info->rpf_count; ++i) { + struct vsp1_rwpf *rwpf = pipe->inputs[i]; + + if (rwpf) + vsp1_rwpf_set_memory(rwpf, pipe->dl); + } + + if (!pipe->lif) + vsp1_rwpf_set_memory(pipe->output, pipe->dl); + + vsp1_dl_list_commit(pipe->dl); + pipe->dl = NULL; + + vsp1_pipeline_run(pipe); +} + +static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) +{ + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + enum vsp1_pipeline_state state; + unsigned long flags; + unsigned int i; + + /* Complete buffers on all video nodes. */ + for (i = 0; i < vsp1->info->rpf_count; ++i) { + if (!pipe->inputs[i]) + continue; + + vsp1_video_frame_end(pipe, pipe->inputs[i]); + } + + vsp1_video_frame_end(pipe, pipe->output); + + spin_lock_irqsave(&pipe->irqlock, flags); + + state = pipe->state; + pipe->state = VSP1_PIPELINE_STOPPED; + + /* If a stop has been requested, mark the pipeline as stopped and + * return. Otherwise restart the pipeline if ready. + */ + if (state == VSP1_PIPELINE_STOPPING) + wake_up(&pipe->wq); + else if (vsp1_pipeline_ready(pipe)) + vsp1_video_pipeline_run(pipe); + + spin_unlock_irqrestore(&pipe->irqlock, flags); +} + static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe, struct vsp1_rwpf *input, struct vsp1_rwpf *output) @@ -369,139 +502,6 @@ static void vsp1_video_pipeline_cleanup(struct vsp1_pipeline *pipe) mutex_unlock(&pipe->lock); } -/* - * vsp1_video_complete_buffer - Complete the current buffer - * @video: the video node - * - * This function completes the current buffer by filling its sequence number, - * time stamp and payload size, and hands it back to the videobuf core. - * - * When operating in DU output mode (deep pipeline to the DU through the LIF), - * the VSP1 needs to constantly supply frames to the display. In that case, if - * no other buffer is queued, reuse the one that has just been processed instead - * of handing it back to the videobuf core. - * - * Return the next queued buffer or NULL if the queue is empty. - */ -static struct vsp1_vb2_buffer * -vsp1_video_complete_buffer(struct vsp1_video *video) -{ - struct vsp1_pipeline *pipe = video->rwpf->pipe; - struct vsp1_vb2_buffer *next = NULL; - struct vsp1_vb2_buffer *done; - unsigned long flags; - unsigned int i; - - spin_lock_irqsave(&video->irqlock, flags); - - if (list_empty(&video->irqqueue)) { - spin_unlock_irqrestore(&video->irqlock, flags); - return NULL; - } - - done = list_first_entry(&video->irqqueue, - struct vsp1_vb2_buffer, queue); - - /* In DU output mode reuse the buffer if the list is singular. */ - if (pipe->lif && list_is_singular(&video->irqqueue)) { - spin_unlock_irqrestore(&video->irqlock, flags); - return done; - } - - list_del(&done->queue); - - if (!list_empty(&video->irqqueue)) - next = list_first_entry(&video->irqqueue, - struct vsp1_vb2_buffer, queue); - - spin_unlock_irqrestore(&video->irqlock, flags); - - done->buf.sequence = video->sequence++; - done->buf.vb2_buf.timestamp = ktime_get_ns(); - for (i = 0; i < done->buf.vb2_buf.num_planes; ++i) - vb2_set_plane_payload(&done->buf.vb2_buf, i, - vb2_plane_size(&done->buf.vb2_buf, i)); - vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE); - - return next; -} - -static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, - struct vsp1_rwpf *rwpf) -{ - struct vsp1_video *video = rwpf->video; - struct vsp1_vb2_buffer *buf; - unsigned long flags; - - buf = vsp1_video_complete_buffer(video); - if (buf == NULL) - return; - - spin_lock_irqsave(&pipe->irqlock, flags); - - video->rwpf->mem = buf->mem; - pipe->buffers_ready |= 1 << video->pipe_index; - - spin_unlock_irqrestore(&pipe->irqlock, flags); -} - -static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) -{ - struct vsp1_device *vsp1 = pipe->output->entity.vsp1; - unsigned int i; - - if (!pipe->dl) - pipe->dl = vsp1_dl_list_get(pipe->output->dlm); - - for (i = 0; i < vsp1->info->rpf_count; ++i) { - struct vsp1_rwpf *rwpf = pipe->inputs[i]; - - if (rwpf) - vsp1_rwpf_set_memory(rwpf, pipe->dl); - } - - if (!pipe->lif) - vsp1_rwpf_set_memory(pipe->output, pipe->dl); - - vsp1_dl_list_commit(pipe->dl); - pipe->dl = NULL; - - vsp1_pipeline_run(pipe); -} - -static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) -{ - struct vsp1_device *vsp1 = pipe->output->entity.vsp1; - enum vsp1_pipeline_state state; - unsigned long flags; - unsigned int i; - - /* Complete buffers on all video nodes. */ - for (i = 0; i < vsp1->info->rpf_count; ++i) { - if (!pipe->inputs[i]) - continue; - - vsp1_video_frame_end(pipe, pipe->inputs[i]); - } - - vsp1_video_frame_end(pipe, pipe->output); - - spin_lock_irqsave(&pipe->irqlock, flags); - - state = pipe->state; - pipe->state = VSP1_PIPELINE_STOPPED; - - /* If a stop has been requested, mark the pipeline as stopped and - * return. Otherwise restart the pipeline if ready. - */ - if (state == VSP1_PIPELINE_STOPPING) - wake_up(&pipe->wq); - else if (vsp1_pipeline_ready(pipe)) - vsp1_video_pipeline_run(pipe); - - spin_unlock_irqrestore(&pipe->irqlock, flags); -} - /* ----------------------------------------------------------------------------- * videobuf2 Queue Operations */ -- GitLab From a0cdac5610ea900dcf6a78d4d0216aef2bca7b80 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 17 Jan 2016 19:53:56 -0200 Subject: [PATCH 2598/9938] [media] v4l: vsp1: Allocate pipelines on demand Instead of embedding pipelines in the vsp1_video objects allocate them on demand when they are needed. This fixes the streamon race condition where pipelines objects from different video nodes could be used for the same pipeline. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 1 + drivers/media/platform/vsp1/vsp1_drv.c | 1 + drivers/media/platform/vsp1/vsp1_pipe.c | 1 + drivers/media/platform/vsp1/vsp1_pipe.h | 5 +- drivers/media/platform/vsp1/vsp1_rpf.c | 1 + drivers/media/platform/vsp1/vsp1_video.c | 124 ++++++++++++----------- drivers/media/platform/vsp1/vsp1_video.h | 2 - drivers/media/platform/vsp1/vsp1_wpf.c | 1 + 8 files changed, 75 insertions(+), 61 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 3ece40245396..d27de5363c5a 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -19,6 +19,7 @@ #include "vsp1.h" #include "vsp1_bru.h" #include "vsp1_dl.h" +#include "vsp1_pipe.h" #include "vsp1_rwpf.h" #include "vsp1_video.h" diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index f1be2680013d..596f26d81494 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -30,6 +30,7 @@ #include "vsp1_hsit.h" #include "vsp1_lif.h" #include "vsp1_lut.h" +#include "vsp1_pipe.h" #include "vsp1_rwpf.h" #include "vsp1_sru.h" #include "vsp1_uds.h" diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 8ac080f87b08..4913b933562c 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -194,6 +194,7 @@ void vsp1_pipeline_init(struct vsp1_pipeline *pipe) mutex_init(&pipe->lock); spin_lock_init(&pipe->irqlock); init_waitqueue_head(&pipe->wq); + kref_init(&pipe->kref); INIT_LIST_HEAD(&pipe->entities); pipe->state = VSP1_PIPELINE_STOPPED; diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index 9fd688bfe638..7b56113511dd 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -13,6 +13,7 @@ #ifndef __VSP1_PIPE_H__ #define __VSP1_PIPE_H__ +#include #include #include #include @@ -63,7 +64,7 @@ enum vsp1_pipeline_state { * @wq: work queue to wait for state change completion * @frame_end: frame end interrupt handler * @lock: protects the pipeline use count and stream count - * @use_count: number of video nodes using the pipeline + * @kref: pipeline reference count * @stream_count: number of streaming video nodes * @buffers_ready: bitmask of RPFs and WPFs with at least one buffer available * @num_inputs: number of RPFs @@ -86,7 +87,7 @@ struct vsp1_pipeline { void (*frame_end)(struct vsp1_pipeline *pipe); struct mutex lock; - unsigned int use_count; + struct kref kref; unsigned int stream_count; unsigned int buffers_ready; diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index e7b6abbb0024..5486ff54a2b3 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -17,6 +17,7 @@ #include "vsp1.h" #include "vsp1_dl.h" +#include "vsp1_pipe.h" #include "vsp1_rwpf.h" #include "vsp1_video.h" diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 4396018d1408..a9aec5c0bec6 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -399,14 +399,10 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe, unsigned int i; int ret; - mutex_lock(&mdev->graph_mutex); - /* Walk the graph to locate the entities and video nodes. */ ret = media_entity_graph_walk_init(&graph, mdev); - if (ret) { - mutex_unlock(&mdev->graph_mutex); + if (ret) return ret; - } media_entity_graph_walk_start(&graph, entity); @@ -439,15 +435,11 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe, } } - mutex_unlock(&mdev->graph_mutex); - media_entity_graph_walk_cleanup(&graph); /* We need one output and at least one input. */ - if (pipe->num_inputs == 0 || !pipe->output) { - ret = -EPIPE; - goto error; - } + if (pipe->num_inputs == 0 || !pipe->output) + return -EPIPE; /* Follow links downstream for each input and make sure the graph * contains no loop and that all branches end at the output WPF. @@ -459,47 +451,66 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe, ret = vsp1_video_pipeline_build_branch(pipe, pipe->inputs[i], pipe->output); if (ret < 0) - goto error; + return ret; } return 0; - -error: - vsp1_pipeline_reset(pipe); - return ret; } static int vsp1_video_pipeline_init(struct vsp1_pipeline *pipe, struct vsp1_video *video) { + vsp1_pipeline_init(pipe); + + pipe->frame_end = vsp1_video_pipeline_frame_end; + + return vsp1_video_pipeline_build(pipe, video); +} + +static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video) +{ + struct vsp1_pipeline *pipe; int ret; - mutex_lock(&pipe->lock); + /* Get a pipeline object for the video node. If a pipeline has already + * been allocated just increment its reference count and return it. + * Otherwise allocate a new pipeline and initialize it, it will be freed + * when the last reference is released. + */ + if (!video->rwpf->pipe) { + pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); + if (!pipe) + return ERR_PTR(-ENOMEM); - /* If we're the first user build and validate the pipeline. */ - if (pipe->use_count == 0) { - ret = vsp1_video_pipeline_build(pipe, video); - if (ret < 0) - goto done; + ret = vsp1_video_pipeline_init(pipe, video); + if (ret < 0) { + vsp1_pipeline_reset(pipe); + kfree(pipe); + return ERR_PTR(ret); + } + } else { + pipe = video->rwpf->pipe; + kref_get(&pipe->kref); } - pipe->use_count++; - ret = 0; - -done: - mutex_unlock(&pipe->lock); - return ret; + return pipe; } -static void vsp1_video_pipeline_cleanup(struct vsp1_pipeline *pipe) +static void vsp1_video_pipeline_release(struct kref *kref) { - mutex_lock(&pipe->lock); + struct vsp1_pipeline *pipe = container_of(kref, typeof(*pipe), kref); - /* If we're the last user clean up the pipeline. */ - if (--pipe->use_count == 0) - vsp1_pipeline_reset(pipe); + vsp1_pipeline_reset(pipe); + kfree(pipe); +} - mutex_unlock(&pipe->lock); +static void vsp1_video_pipeline_put(struct vsp1_pipeline *pipe) +{ + struct media_device *mdev = &pipe->output->entity.vsp1->media_dev; + + mutex_lock(&mdev->graph_mutex); + kref_put(&pipe->kref, vsp1_video_pipeline_release); + mutex_unlock(&mdev->graph_mutex); } /* ----------------------------------------------------------------------------- @@ -674,8 +685,8 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) } mutex_unlock(&pipe->lock); - vsp1_video_pipeline_cleanup(pipe); media_entity_pipeline_stop(&video->video.entity); + vsp1_video_pipeline_put(pipe); /* Remove all buffers from the IRQ queue. */ spin_lock_irqsave(&video->irqlock, flags); @@ -787,6 +798,7 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { struct v4l2_fh *vfh = file->private_data; struct vsp1_video *video = to_vsp1_video(vfh->vdev); + struct media_device *mdev = &video->vsp1->media_dev; struct vsp1_pipeline *pipe; int ret; @@ -795,20 +807,25 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) video->sequence = 0; - /* Start streaming on the pipeline. No link touching an entity in the - * pipeline can be activated or deactivated once streaming is started. - * - * Use the VSP1 pipeline object embedded in the first video object that - * starts streaming. - * - * FIXME: This is racy, the ioctl is only protected by the video node - * lock. + /* Get a pipeline for the video node and start streaming on it. No link + * touching an entity in the pipeline can be activated or deactivated + * once streaming is started. */ - pipe = video->rwpf->pipe ? video->rwpf->pipe : &video->pipe; + mutex_lock(&mdev->graph_mutex); - ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe); - if (ret < 0) - return ret; + pipe = vsp1_video_pipeline_get(video); + if (IS_ERR(pipe)) { + mutex_unlock(&mdev->graph_mutex); + return PTR_ERR(pipe); + } + + ret = __media_entity_pipeline_start(&video->video.entity, &pipe->pipe); + if (ret < 0) { + mutex_unlock(&mdev->graph_mutex); + goto err_pipe; + } + + mutex_unlock(&mdev->graph_mutex); /* Verify that the configured format matches the output of the connected * subdev. @@ -817,21 +834,17 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) goto err_stop; - ret = vsp1_video_pipeline_init(pipe, video); - if (ret < 0) - goto err_stop; - /* Start the queue. */ ret = vb2_streamon(&video->queue, type); if (ret < 0) - goto err_cleanup; + goto err_stop; return 0; -err_cleanup: - vsp1_video_pipeline_cleanup(pipe); err_stop: media_entity_pipeline_stop(&video->video.entity); +err_pipe: + vsp1_video_pipeline_put(pipe); return ret; } @@ -947,9 +960,6 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, spin_lock_init(&video->irqlock); INIT_LIST_HEAD(&video->irqqueue); - vsp1_pipeline_init(&video->pipe); - video->pipe.frame_end = vsp1_video_pipeline_frame_end; - /* Initialize the media entity... */ ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); if (ret < 0) diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 64abd39ee1e7..867b00807c46 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -18,7 +18,6 @@ #include -#include "vsp1_pipe.h" #include "vsp1_rwpf.h" struct vsp1_vb2_buffer { @@ -44,7 +43,6 @@ struct vsp1_video { struct mutex lock; - struct vsp1_pipeline pipe; unsigned int pipe_index; struct vb2_queue queue; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index d1d5c08ca35e..ce1d0b4094db 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -17,6 +17,7 @@ #include "vsp1.h" #include "vsp1_dl.h" +#include "vsp1_pipe.h" #include "vsp1_rwpf.h" #include "vsp1_video.h" -- GitLab From 5b22a11e0b21e7da8fcefd913688c4cfcdf08825 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 24 Feb 2016 18:40:12 -0300 Subject: [PATCH 2599/9938] [media] v4l: vsp1: RPF entities can't be target nodes The RPF entities are located at the very beginning of pipelines, they can't be target nodes in the Data Path Router matrix. Remove their input ID from the routing table. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_entity.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index e9dd4dbda2dc..dfecddffbc81 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -160,11 +160,11 @@ static const struct vsp1_route vsp1_routes[] = { { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } }, { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } }, { VSP1_ENTITY_LUT, 0, VI6_DPR_LUT_ROUTE, { VI6_DPR_NODE_LUT, } }, - { VSP1_ENTITY_RPF, 0, VI6_DPR_RPF_ROUTE(0), { VI6_DPR_NODE_RPF(0), } }, - { VSP1_ENTITY_RPF, 1, VI6_DPR_RPF_ROUTE(1), { VI6_DPR_NODE_RPF(1), } }, - { VSP1_ENTITY_RPF, 2, VI6_DPR_RPF_ROUTE(2), { VI6_DPR_NODE_RPF(2), } }, - { VSP1_ENTITY_RPF, 3, VI6_DPR_RPF_ROUTE(3), { VI6_DPR_NODE_RPF(3), } }, - { VSP1_ENTITY_RPF, 4, VI6_DPR_RPF_ROUTE(4), { VI6_DPR_NODE_RPF(4), } }, + { VSP1_ENTITY_RPF, 0, VI6_DPR_RPF_ROUTE(0), { 0, } }, + { VSP1_ENTITY_RPF, 1, VI6_DPR_RPF_ROUTE(1), { 0, } }, + { VSP1_ENTITY_RPF, 2, VI6_DPR_RPF_ROUTE(2), { 0, } }, + { VSP1_ENTITY_RPF, 3, VI6_DPR_RPF_ROUTE(3), { 0, } }, + { VSP1_ENTITY_RPF, 4, VI6_DPR_RPF_ROUTE(4), { 0, } }, { VSP1_ENTITY_SRU, 0, VI6_DPR_SRU_ROUTE, { VI6_DPR_NODE_SRU, } }, { VSP1_ENTITY_UDS, 0, VI6_DPR_UDS_ROUTE(0), { VI6_DPR_NODE_UDS(0), } }, { VSP1_ENTITY_UDS, 1, VI6_DPR_UDS_ROUTE(1), { VI6_DPR_NODE_UDS(1), } }, -- GitLab From 3f557220cc29d1961ef9efa2a8db04c7c5f6e6d4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 24 Feb 2016 21:10:13 -0300 Subject: [PATCH 2600/9938] [media] v4l: vsp1: Factorize get pad format code All entities implement the same get pad format handler, factorize it into a common function. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 19 +---------------- drivers/media/platform/vsp1/vsp1_entity.c | 25 +++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 4 ++++ drivers/media/platform/vsp1/vsp1_hsit.c | 19 +---------------- drivers/media/platform/vsp1/vsp1_lif.c | 19 +---------------- drivers/media/platform/vsp1/vsp1_lut.c | 19 +---------------- drivers/media/platform/vsp1/vsp1_rwpf.c | 19 +---------------- drivers/media/platform/vsp1/vsp1_sru.c | 19 +---------------- drivers/media/platform/vsp1/vsp1_uds.c | 19 +---------------- 9 files changed, 36 insertions(+), 126 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index d27de5363c5a..fb32f87d4625 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -129,23 +129,6 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, pad); } -static int bru_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vsp1_bru *bru = to_bru(subdev); - struct v4l2_subdev_pad_config *config; - - config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which); - if (!config) - return -EINVAL; - - fmt->format = *vsp1_entity_get_pad_format(&bru->entity, config, - fmt->pad); - - return 0; -} - static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *config, unsigned int pad, struct v4l2_mbus_framefmt *fmt) @@ -292,7 +275,7 @@ static struct v4l2_subdev_pad_ops bru_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = bru_enum_mbus_code, .enum_frame_size = bru_enum_frame_size, - .get_fmt = bru_get_format, + .get_fmt = vsp1_subdev_get_pad_format, .set_fmt = bru_set_format, .get_selection = bru_get_selection, .set_selection = bru_set_selection, diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index dfecddffbc81..e4d6c7a1ed77 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -116,6 +116,31 @@ int vsp1_entity_init_cfg(struct v4l2_subdev *subdev, return 0; } +/* + * vsp1_subdev_get_pad_format - Subdev pad get_fmt handler + * @subdev: V4L2 subdevice + * @cfg: V4L2 subdev pad configuration + * @fmt: V4L2 subdev format + * + * This function implements the subdev get_fmt pad operation. It can be used as + * a direct drop-in for the operation handler. + */ +int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct vsp1_entity *entity = to_vsp1_entity(subdev); + struct v4l2_subdev_pad_config *config; + + config = vsp1_entity_get_pad_config(entity, cfg, fmt->which); + if (!config) + return -EINVAL; + + fmt->format = *vsp1_entity_get_pad_format(entity, config, fmt->pad); + + return 0; +} + /* ----------------------------------------------------------------------------- * Media Operations */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index bbf378437c3b..d2bb970e72b2 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -127,4 +127,8 @@ int vsp1_entity_init_cfg(struct v4l2_subdev *subdev, void vsp1_entity_route_setup(struct vsp1_entity *source, struct vsp1_dl_list *dl); +int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt); + #endif /* __VSP1_ENTITY_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index f02e4ca77a7c..7cf2add51bf9 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -90,23 +90,6 @@ static int hsit_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int hsit_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vsp1_hsit *hsit = to_hsit(subdev); - struct v4l2_subdev_pad_config *config; - - config = vsp1_entity_get_pad_config(&hsit->entity, cfg, fmt->which); - if (!config) - return -EINVAL; - - fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, config, - fmt->pad); - - return 0; -} - static int hsit_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) @@ -154,7 +137,7 @@ static struct v4l2_subdev_pad_ops hsit_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = hsit_enum_mbus_code, .enum_frame_size = hsit_enum_frame_size, - .get_fmt = hsit_get_format, + .get_fmt = vsp1_subdev_get_pad_format, .set_fmt = hsit_set_format, }; diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 42ed8f80cc88..730db64bd4d3 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -107,23 +107,6 @@ static int lif_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int lif_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vsp1_lif *lif = to_lif(subdev); - struct v4l2_subdev_pad_config *config; - - config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which); - if (!config) - return -EINVAL; - - fmt->format = *vsp1_entity_get_pad_format(&lif->entity, config, - fmt->pad); - - return 0; -} - static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) @@ -173,7 +156,7 @@ static struct v4l2_subdev_pad_ops lif_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = lif_enum_mbus_code, .enum_frame_size = lif_enum_frame_size, - .get_fmt = lif_get_format, + .get_fmt = vsp1_subdev_get_pad_format, .set_fmt = lif_set_format, }; diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 596537a95210..f84ee8878858 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -136,23 +136,6 @@ static int lut_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int lut_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vsp1_lut *lut = to_lut(subdev); - struct v4l2_subdev_pad_config *config; - - config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which); - if (!config) - return -EINVAL; - - fmt->format = *vsp1_entity_get_pad_format(&lut->entity, config, - fmt->pad); - - return 0; -} - static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) @@ -208,7 +191,7 @@ static struct v4l2_subdev_pad_ops lut_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = lut_enum_mbus_code, .enum_frame_size = lut_enum_frame_size, - .get_fmt = lut_get_format, + .get_fmt = vsp1_subdev_get_pad_format, .set_fmt = lut_set_format, }; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 4d302f5cccb2..64d649a1bcf5 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -83,23 +83,6 @@ static int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vsp1_rwpf *rwpf = to_rwpf(subdev); - struct v4l2_subdev_pad_config *config; - - config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, fmt->which); - if (!config) - return -EINVAL; - - fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, config, - fmt->pad); - - return 0; -} - static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) @@ -254,7 +237,7 @@ const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = vsp1_rwpf_enum_mbus_code, .enum_frame_size = vsp1_rwpf_enum_frame_size, - .get_fmt = vsp1_rwpf_get_format, + .get_fmt = vsp1_subdev_get_pad_format, .set_fmt = vsp1_rwpf_set_format, .get_selection = vsp1_rwpf_get_selection, .set_selection = vsp1_rwpf_set_selection, diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 00edd95093e3..51b017d841f5 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -184,23 +184,6 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int sru_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vsp1_sru *sru = to_sru(subdev); - struct v4l2_subdev_pad_config *config; - - config = vsp1_entity_get_pad_config(&sru->entity, cfg, fmt->which); - if (!config) - return -EINVAL; - - fmt->format = *vsp1_entity_get_pad_format(&sru->entity, config, - fmt->pad); - - return 0; -} - static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_pad_config *config, unsigned int pad, struct v4l2_mbus_framefmt *fmt) @@ -285,7 +268,7 @@ static struct v4l2_subdev_pad_ops sru_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = sru_enum_mbus_code, .enum_frame_size = sru_enum_frame_size, - .get_fmt = sru_get_format, + .get_fmt = vsp1_subdev_get_pad_format, .set_fmt = sru_set_format, }; diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 42f2d0465bd6..59dd53c0d2be 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -182,23 +182,6 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int uds_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vsp1_uds *uds = to_uds(subdev); - struct v4l2_subdev_pad_config *config; - - config = vsp1_entity_get_pad_config(&uds->entity, cfg, fmt->which); - if (!config) - return -EINVAL; - - fmt->format = *vsp1_entity_get_pad_format(&uds->entity, config, - fmt->pad); - - return 0; -} - static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *config, unsigned int pad, struct v4l2_mbus_framefmt *fmt) @@ -272,7 +255,7 @@ static struct v4l2_subdev_pad_ops uds_pad_ops = { .init_cfg = vsp1_entity_init_cfg, .enum_mbus_code = uds_enum_mbus_code, .enum_frame_size = uds_enum_frame_size, - .get_fmt = uds_get_format, + .get_fmt = vsp1_subdev_get_pad_format, .set_fmt = uds_set_format, }; -- GitLab From 6ad9ba9c14fad546b91d654c5b4e870d009ace28 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 24 Feb 2016 20:25:42 -0300 Subject: [PATCH 2601/9938] [media] v4l: vsp1: Factorize media bus codes enumeration code Most of the entities can't perform format conversion and implement the same media bus enumeration function. Factorize the code into a single implementation. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 26 +------------ drivers/media/platform/vsp1/vsp1_entity.c | 46 +++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 4 ++ drivers/media/platform/vsp1/vsp1_lif.c | 29 +------------- drivers/media/platform/vsp1/vsp1_lut.c | 29 +------------- drivers/media/platform/vsp1/vsp1_sru.c | 29 +------------- drivers/media/platform/vsp1/vsp1_uds.c | 29 +------------- 7 files changed, 60 insertions(+), 132 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index fb32f87d4625..b1068c018011 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -76,31 +76,9 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_AYUV8_1X32, }; - struct vsp1_bru *bru = to_bru(subdev); - - if (code->pad == BRU_PAD_SINK(0)) { - if (code->index >= ARRAY_SIZE(codes)) - return -EINVAL; - - code->code = codes[code->index]; - } else { - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - if (code->index) - return -EINVAL; - - config = vsp1_entity_get_pad_config(&bru->entity, cfg, - code->which); - if (!config) - return -EINVAL; - - format = vsp1_entity_get_pad_format(&bru->entity, config, - BRU_PAD_SINK(0)); - code->code = format->code; - } - - return 0; + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, + ARRAY_SIZE(codes)); } static int bru_enum_frame_size(struct v4l2_subdev *subdev, diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index e4d6c7a1ed77..9e848260d85e 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -141,6 +141,52 @@ int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, return 0; } +/* + * vsp1_subdev_enum_mbus_code - Subdev pad enum_mbus_code handler + * @subdev: V4L2 subdevice + * @cfg: V4L2 subdev pad configuration + * @code: Media bus code enumeration + * @codes: Array of supported media bus codes + * @ncodes: Number of supported media bus codes + * + * This function implements the subdev enum_mbus_code pad operation for entities + * that do not support format conversion. It enumerates the given supported + * media bus codes on the sink pad and reports a source pad format identical to + * the sink pad. + */ +int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code, + const unsigned int *codes, unsigned int ncodes) +{ + struct vsp1_entity *entity = to_vsp1_entity(subdev); + + if (code->pad == 0) { + if (code->index >= ncodes) + return -EINVAL; + + code->code = codes[code->index]; + } else { + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + + /* The entity can't perform format conversion, the sink format + * is always identical to the source format. + */ + if (code->index) + return -EINVAL; + + config = vsp1_entity_get_pad_config(entity, cfg, code->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(entity, config, 0); + code->code = format->code; + } + + return 0; +} + /* ----------------------------------------------------------------------------- * Media Operations */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index d2bb970e72b2..ab7cc498d139 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -130,5 +130,9 @@ void vsp1_entity_route_setup(struct vsp1_entity *source, int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt); +int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code, + const unsigned int *codes, unsigned int ncodes); #endif /* __VSP1_ENTITY_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 730db64bd4d3..59a8017f39af 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -45,34 +45,9 @@ static int lif_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_AYUV8_1X32, }; - struct vsp1_lif *lif = to_lif(subdev); - - if (code->pad == LIF_PAD_SINK) { - if (code->index >= ARRAY_SIZE(codes)) - return -EINVAL; - - code->code = codes[code->index]; - } else { - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - /* The LIF can't perform format conversion, the sink format is - * always identical to the source format. - */ - if (code->index) - return -EINVAL; - - config = vsp1_entity_get_pad_config(&lif->entity, cfg, - code->which); - if (!config) - return -EINVAL; - format = vsp1_entity_get_pad_format(&lif->entity, config, - LIF_PAD_SINK); - code->code = format->code; - } - - return 0; + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, + ARRAY_SIZE(codes)); } static int lif_enum_frame_size(struct v4l2_subdev *subdev, diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index f84ee8878858..12a069adf567 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -71,34 +71,9 @@ static int lut_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_AHSV8888_1X32, MEDIA_BUS_FMT_AYUV8_1X32, }; - struct vsp1_lut *lut = to_lut(subdev); - - if (code->pad == LUT_PAD_SINK) { - if (code->index >= ARRAY_SIZE(codes)) - return -EINVAL; - - code->code = codes[code->index]; - } else { - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - /* The LUT can't perform format conversion, the sink format is - * always identical to the source format. - */ - if (code->index) - return -EINVAL; - - config = vsp1_entity_get_pad_config(&lut->entity, cfg, - code->which); - if (!config) - return -EINVAL; - format = vsp1_entity_get_pad_format(&lut->entity, config, - LUT_PAD_SINK); - code->code = format->code; - } - - return 0; + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, + ARRAY_SIZE(codes)); } static int lut_enum_frame_size(struct v4l2_subdev *subdev, diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 51b017d841f5..97ef997ae735 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -116,34 +116,9 @@ static int sru_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_AYUV8_1X32, }; - struct vsp1_sru *sru = to_sru(subdev); - - if (code->pad == SRU_PAD_SINK) { - if (code->index >= ARRAY_SIZE(codes)) - return -EINVAL; - - code->code = codes[code->index]; - } else { - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - /* The SRU can't perform format conversion, the sink format is - * always identical to the source format. - */ - if (code->index) - return -EINVAL; - config = vsp1_entity_get_pad_config(&sru->entity, cfg, - code->which); - if (!config) - return -EINVAL; - - format = vsp1_entity_get_pad_format(&sru->entity, config, - SRU_PAD_SINK); - code->code = format->code; - } - - return 0; + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, + ARRAY_SIZE(codes)); } static int sru_enum_frame_size(struct v4l2_subdev *subdev, diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 59dd53c0d2be..1875e29da184 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -119,34 +119,9 @@ static int uds_enum_mbus_code(struct v4l2_subdev *subdev, MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_AYUV8_1X32, }; - struct vsp1_uds *uds = to_uds(subdev); - - if (code->pad == UDS_PAD_SINK) { - if (code->index >= ARRAY_SIZE(codes)) - return -EINVAL; - - code->code = codes[code->index]; - } else { - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - config = vsp1_entity_get_pad_config(&uds->entity, cfg, - code->which); - if (!config) - return -EINVAL; - - /* The UDS can't perform format conversion, the sink format is - * always identical to the source format. - */ - if (code->index) - return -EINVAL; - format = vsp1_entity_get_pad_format(&uds->entity, config, - UDS_PAD_SINK); - code->code = format->code; - } - - return 0; + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, + ARRAY_SIZE(codes)); } static int uds_enum_frame_size(struct v4l2_subdev *subdev, -- GitLab From c431cbbb446851ecb17095812e049119b2be17ed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 Apr 2016 19:08:55 -0300 Subject: [PATCH 2602/9938] Revert "[media] v4l2-ioctl: simplify code" There are some issues rised on this patch during patch review. I ended by merging this one by mistake. So, let's revert it. This reverts commit 54ace1cfd4358fd11112f17cc711eea234d5ab9e. Cc: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 51 ++++++++++++---------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 3cf8d3adab03..6bf5a3ecd126 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2160,40 +2160,33 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_cropcap *p = arg; - struct v4l2_selection s = { .type = p->type }; - int ret; - if (ops->vidioc_g_selection == NULL) { - /* - * The determine_valid_ioctls() call already should ensure - * that ops->vidioc_cropcap != NULL, but just in case... - */ - if (ops->vidioc_cropcap) - return ops->vidioc_cropcap(file, fh, p); - return -ENOTTY; - } + if (ops->vidioc_g_selection) { + struct v4l2_selection s = { .type = p->type }; + int ret; - /* obtaining bounds */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; - else - s.target = V4L2_SEL_TGT_CROP_BOUNDS; + /* obtaining bounds */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; + else + s.target = V4L2_SEL_TGT_CROP_BOUNDS; - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - return ret; - p->bounds = s.r; + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->bounds = s.r; - /* obtaining defrect */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; - else - s.target = V4L2_SEL_TGT_CROP_DEFAULT; + /* obtaining defrect */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; + else + s.target = V4L2_SEL_TGT_CROP_DEFAULT; - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - return ret; - p->defrect = s.r; + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->defrect = s.r; + } /* setting trivial pixelaspect */ p->pixelaspect.numerator = 1; -- GitLab From 076e834fee91db7e9df4fe2d3ecf3ed67eadbe88 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 24 Feb 2016 20:25:42 -0300 Subject: [PATCH 2603/9938] [media] v4l: vsp1: Factorize frame size enumeration code Most of the entities can't perform scaling and implement the same frame size enumeration function. Factorize the code into a single implementation. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_entity.c | 52 +++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 5 +++ drivers/media/platform/vsp1/vsp1_hsit.c | 32 ++------------ drivers/media/platform/vsp1/vsp1_lif.c | 29 ++----------- drivers/media/platform/vsp1/vsp1_lut.c | 32 ++------------ drivers/media/platform/vsp1/vsp1_rwpf.c | 30 ++----------- 6 files changed, 69 insertions(+), 111 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 9e848260d85e..3d070bcc6053 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -187,6 +187,58 @@ int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev, return 0; } +/* + * vsp1_subdev_enum_frame_size - Subdev pad enum_frame_size handler + * @subdev: V4L2 subdevice + * @cfg: V4L2 subdev pad configuration + * @fse: Frame size enumeration + * @min_width: Minimum image width + * @min_height: Minimum image height + * @max_width: Maximum image width + * @max_height: Maximum image height + * + * This function implements the subdev enum_frame_size pad operation for + * entities that do not support scaling or cropping. It reports the given + * minimum and maximum frame width and height on the sink pad, and a fixed + * source pad size identical to the sink pad. + */ +int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse, + unsigned int min_width, unsigned int min_height, + unsigned int max_width, unsigned int max_height) +{ + struct vsp1_entity *entity = to_vsp1_entity(subdev); + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + + config = vsp1_entity_get_pad_config(entity, cfg, fse->which); + if (!config) + return -EINVAL; + + format = vsp1_entity_get_pad_format(entity, config, fse->pad); + + if (fse->index || fse->code != format->code) + return -EINVAL; + + if (fse->pad == 0) { + fse->min_width = min_width; + fse->max_width = max_width; + fse->min_height = min_height; + fse->max_height = max_height; + } else { + /* The size on the source pad are fixed and always identical to + * the size on the sink pad. + */ + fse->min_width = format->width; + fse->max_width = format->width; + fse->min_height = format->height; + fse->max_height = format->height; + } + + return 0; +} + /* ----------------------------------------------------------------------------- * Media Operations */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index ab7cc498d139..69eff4e17350 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -134,5 +134,10 @@ int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code, const unsigned int *codes, unsigned int ncodes); +int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse, + unsigned int min_w, unsigned int min_h, + unsigned int max_w, unsigned int max_h); #endif /* __VSP1_ENTITY_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 7cf2add51bf9..68b8567b374d 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -59,35 +59,9 @@ static int hsit_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { - struct vsp1_hsit *hsit = to_hsit(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - config = vsp1_entity_get_pad_config(&hsit->entity, cfg, fse->which); - if (!config) - return -EINVAL; - - format = vsp1_entity_get_pad_format(&hsit->entity, config, fse->pad); - - if (fse->index || fse->code != format->code) - return -EINVAL; - - if (fse->pad == HSIT_PAD_SINK) { - fse->min_width = HSIT_MIN_SIZE; - fse->max_width = HSIT_MAX_SIZE; - fse->min_height = HSIT_MIN_SIZE; - fse->max_height = HSIT_MAX_SIZE; - } else { - /* The size on the source pad are fixed and always identical to - * the size on the sink pad. - */ - fse->min_width = format->width; - fse->max_width = format->width; - fse->min_height = format->height; - fse->max_height = format->height; - } - - return 0; + return vsp1_subdev_enum_frame_size(subdev, cfg, fse, HSIT_MIN_SIZE, + HSIT_MIN_SIZE, HSIT_MAX_SIZE, + HSIT_MAX_SIZE); } static int hsit_set_format(struct v4l2_subdev *subdev, diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 59a8017f39af..579e142b4e94 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -54,32 +54,9 @@ static int lif_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { - struct vsp1_lif *lif = to_lif(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - config = vsp1_entity_get_pad_config(&lif->entity, cfg, fse->which); - if (!config) - return -EINVAL; - - format = vsp1_entity_get_pad_format(&lif->entity, config, LIF_PAD_SINK); - - if (fse->index || fse->code != format->code) - return -EINVAL; - - if (fse->pad == LIF_PAD_SINK) { - fse->min_width = LIF_MIN_SIZE; - fse->max_width = LIF_MAX_SIZE; - fse->min_height = LIF_MIN_SIZE; - fse->max_height = LIF_MAX_SIZE; - } else { - fse->min_width = format->width; - fse->max_width = format->width; - fse->min_height = format->height; - fse->max_height = format->height; - } - - return 0; + return vsp1_subdev_enum_frame_size(subdev, cfg, fse, LIF_MIN_SIZE, + LIF_MIN_SIZE, LIF_MAX_SIZE, + LIF_MAX_SIZE); } static int lif_set_format(struct v4l2_subdev *subdev, diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 12a069adf567..c779648882ab 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -80,35 +80,9 @@ static int lut_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { - struct vsp1_lut *lut = to_lut(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - config = vsp1_entity_get_pad_config(&lut->entity, cfg, fse->which); - if (!config) - return -EINVAL; - - format = vsp1_entity_get_pad_format(&lut->entity, config, fse->pad); - - if (fse->index || fse->code != format->code) - return -EINVAL; - - if (fse->pad == LUT_PAD_SINK) { - fse->min_width = LUT_MIN_SIZE; - fse->max_width = LUT_MAX_SIZE; - fse->min_height = LUT_MIN_SIZE; - fse->max_height = LUT_MAX_SIZE; - } else { - /* The size on the source pad are fixed and always identical to - * the size on the sink pad. - */ - fse->min_width = format->width; - fse->max_width = format->width; - fse->min_height = format->height; - fse->max_height = format->height; - } - - return 0; + return vsp1_subdev_enum_frame_size(subdev, cfg, fse, LUT_MIN_SIZE, + LUT_MIN_SIZE, LUT_MAX_SIZE, + LUT_MAX_SIZE); } static int lut_set_format(struct v4l2_subdev *subdev, diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 64d649a1bcf5..3b6e032e7806 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -53,34 +53,10 @@ static int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - - config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, fse->which); - if (!config) - return -EINVAL; - - format = vsp1_entity_get_pad_format(&rwpf->entity, config, fse->pad); - if (fse->index || fse->code != format->code) - return -EINVAL; - - if (fse->pad == RWPF_PAD_SINK) { - fse->min_width = RWPF_MIN_WIDTH; - fse->max_width = rwpf->max_width; - fse->min_height = RWPF_MIN_HEIGHT; - fse->max_height = rwpf->max_height; - } else { - /* The size on the source pad are fixed and always identical to - * the size on the sink pad. - */ - fse->min_width = format->width; - fse->max_width = format->width; - fse->min_height = format->height; - fse->max_height = format->height; - } - - return 0; + return vsp1_subdev_enum_frame_size(subdev, cfg, fse, RWPF_MIN_WIDTH, + RWPF_MIN_HEIGHT, rwpf->max_width, + rwpf->max_height); } static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, -- GitLab From e2b6d7b38c8d2082bacb72a322db9e6a6216ae15 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 16 Nov 2015 02:07:58 -0200 Subject: [PATCH 2604/9938] [media] v4l: vsp1: Fix LUT format setting The LUT set format handler overrides the requested format by mistake. Fix it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_lut.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index c779648882ab..33e3b5cc9c9b 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -111,6 +111,7 @@ static int lut_set_format(struct v4l2_subdev *subdev, return 0; } + format->code = fmt->format.code; format->width = clamp_t(unsigned int, fmt->format.width, LUT_MIN_SIZE, LUT_MAX_SIZE); format->height = clamp_t(unsigned int, fmt->format.height, -- GitLab From b25854e134e9a28c600937ac2320d65c1530283e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 3 Mar 2016 09:25:47 -0300 Subject: [PATCH 2605/9938] [media] v4l: vsp1: dl: Make reg_count field unsigned The field takes positive values only, make it unsigned. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 54f8f4719276..51d14c4a4231 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -60,7 +60,7 @@ struct vsp1_dl_list { dma_addr_t dma; size_t size; - int reg_count; + unsigned int reg_count; }; enum vsp1_dl_mode { -- GitLab From d2c1b028db2e0b153f1aff28e3010a494c8aadc1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 3 Mar 2016 09:26:47 -0300 Subject: [PATCH 2606/9938] [media] v4l: vsp1: dl: Fix race conditions The vsp1_dl_list_put() function expects to be called with the display list manager lock held. This assumption is correct for calls from within the vsp1_dl.c file, but not for the external calls. Fix it by taking the lock inside the function and providing an unlocked version for the internal callers. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 41 +++++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 51d14c4a4231..a931cced9a57 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -163,25 +163,36 @@ struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm) return dl; } +/* This function must be called with the display list manager lock held.*/ +static void __vsp1_dl_list_put(struct vsp1_dl_list *dl) +{ + if (!dl) + return; + + dl->reg_count = 0; + + list_add_tail(&dl->list, &dl->dlm->free); +} + /** * vsp1_dl_list_put - Release a display list * @dl: The display list * * Release the display list and return it to the pool of free lists. * - * This function must be called with the display list manager lock held. - * * Passing a NULL pointer to this function is safe, in that case no operation * will be performed. */ void vsp1_dl_list_put(struct vsp1_dl_list *dl) { + unsigned long flags; + if (!dl) return; - dl->reg_count = 0; - - list_add_tail(&dl->list, &dl->dlm->free); + spin_lock_irqsave(&dl->dlm->lock, flags); + __vsp1_dl_list_put(dl); + spin_unlock_irqrestore(&dl->dlm->lock, flags); } void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data) @@ -219,7 +230,7 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl) */ update = !!(vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD); if (update) { - vsp1_dl_list_put(dlm->pending); + __vsp1_dl_list_put(dlm->pending); dlm->pending = dl; goto done; } @@ -232,7 +243,7 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl) vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | (dl->reg_count * 8)); - vsp1_dl_list_put(dlm->queued); + __vsp1_dl_list_put(dlm->queued); dlm->queued = dl; done: @@ -252,7 +263,7 @@ void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm) * processing by the device. The active display list, if any, won't be * accessed anymore and can be reused. */ - vsp1_dl_list_put(dlm->active); + __vsp1_dl_list_put(dlm->active); dlm->active = NULL; spin_unlock(&dlm->lock); @@ -264,7 +275,7 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) spin_lock(&dlm->lock); - vsp1_dl_list_put(dlm->active); + __vsp1_dl_list_put(dlm->active); dlm->active = NULL; /* Header mode is used for mem-to-mem pipelines only. We don't need to @@ -327,9 +338,15 @@ void vsp1_dlm_setup(struct vsp1_device *vsp1) void vsp1_dlm_reset(struct vsp1_dl_manager *dlm) { - vsp1_dl_list_put(dlm->active); - vsp1_dl_list_put(dlm->queued); - vsp1_dl_list_put(dlm->pending); + unsigned long flags; + + spin_lock_irqsave(&dlm->lock, flags); + + __vsp1_dl_list_put(dlm->active); + __vsp1_dl_list_put(dlm->queued); + __vsp1_dl_list_put(dlm->pending); + + spin_unlock_irqrestore(&dlm->lock, flags); dlm->active = NULL; dlm->queued = NULL; -- GitLab From f81e83c418b0d59c036e071e11a7c143bc507781 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 3 Mar 2016 13:36:34 -0300 Subject: [PATCH 2607/9938] [media] v4l: vsp1: dl: Add support for multi-body display lists Display lists support up to 8 bodies but we currently use a single one. To support preparing display lists for large look-up tables, add support for multi-body display lists. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_dl.c | 289 ++++++++++++++++++++++---- drivers/media/platform/vsp1/vsp1_dl.h | 8 + 2 files changed, 251 insertions(+), 46 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index a931cced9a57..e238d9b9376b 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -19,28 +19,20 @@ #include "vsp1.h" #include "vsp1_dl.h" -/* - * Global resources - * - * - Display-related interrupts (can be used for vblank evasion ?) - * - Display-list enable - * - Header-less for WPF0 - * - DL swap - */ - -#define VSP1_DL_HEADER_SIZE 76 -#define VSP1_DL_BODY_SIZE (2 * 4 * 256) +#define VSP1_DL_NUM_ENTRIES 256 #define VSP1_DL_NUM_LISTS 3 #define VSP1_DLH_INT_ENABLE (1 << 1) #define VSP1_DLH_AUTO_START (1 << 0) +struct vsp1_dl_header_list { + u32 num_bytes; + u32 addr; +} __attribute__((__packed__)); + struct vsp1_dl_header { u32 num_lists; - struct { - u32 num_bytes; - u32 addr; - } lists[8]; + struct vsp1_dl_header_list lists[8]; u32 next_header; u32 flags; } __attribute__((__packed__)); @@ -50,17 +42,44 @@ struct vsp1_dl_entry { u32 data; } __attribute__((__packed__)); -struct vsp1_dl_list { +/** + * struct vsp1_dl_body - Display list body + * @list: entry in the display list list of bodies + * @vsp1: the VSP1 device + * @entries: array of entries + * @dma: DMA address of the entries + * @size: size of the DMA memory in bytes + * @num_entries: number of stored entries + */ +struct vsp1_dl_body { struct list_head list; + struct vsp1_device *vsp1; + + struct vsp1_dl_entry *entries; + dma_addr_t dma; + size_t size; + + unsigned int num_entries; +}; +/** + * struct vsp1_dl_list - Display list + * @list: entry in the display list manager lists + * @dlm: the display list manager + * @header: display list header, NULL for headerless lists + * @dma: DMA address for the header + * @body0: first display list body + * @fragments: list of extra display list bodies + */ +struct vsp1_dl_list { + struct list_head list; struct vsp1_dl_manager *dlm; struct vsp1_dl_header *header; - struct vsp1_dl_entry *body; dma_addr_t dma; - size_t size; - unsigned int reg_count; + struct vsp1_dl_body body0; + struct list_head fragments; }; enum vsp1_dl_mode { @@ -91,6 +110,110 @@ struct vsp1_dl_manager { struct vsp1_dl_list *pending; }; +/* ----------------------------------------------------------------------------- + * Display List Body Management + */ + +/* + * Initialize a display list body object and allocate DMA memory for the body + * data. The display list body object is expected to have been initialized to + * 0 when allocated. + */ +static int vsp1_dl_body_init(struct vsp1_device *vsp1, + struct vsp1_dl_body *dlb, unsigned int num_entries, + size_t extra_size) +{ + size_t size = num_entries * sizeof(*dlb->entries) + extra_size; + + dlb->vsp1 = vsp1; + dlb->size = size; + + dlb->entries = dma_alloc_wc(vsp1->dev, dlb->size, &dlb->dma, + GFP_KERNEL); + if (!dlb->entries) + return -ENOMEM; + + return 0; +} + +/* + * Cleanup a display list body and free allocated DMA memory allocated. + */ +static void vsp1_dl_body_cleanup(struct vsp1_dl_body *dlb) +{ + dma_free_wc(dlb->vsp1->dev, dlb->size, dlb->entries, dlb->dma); +} + +/** + * vsp1_dl_fragment_alloc - Allocate a display list fragment + * @vsp1: The VSP1 device + * @num_entries: The maximum number of entries that the fragment can contain + * + * Allocate a display list fragment with enough memory to contain the requested + * number of entries. + * + * Return a pointer to a fragment on success or NULL if memory can't be + * allocated. + */ +struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1, + unsigned int num_entries) +{ + struct vsp1_dl_body *dlb; + int ret; + + dlb = kzalloc(sizeof(*dlb), GFP_KERNEL); + if (!dlb) + return NULL; + + ret = vsp1_dl_body_init(vsp1, dlb, num_entries, 0); + if (ret < 0) { + kfree(dlb); + return NULL; + } + + return dlb; +} + +/** + * vsp1_dl_fragment_free - Free a display list fragment + * @dlb: The fragment + * + * Free the given display list fragment and the associated DMA memory. + * + * Fragments must only be freed explicitly if they are not added to a display + * list, as the display list will take ownership of them and free them + * otherwise. Manual free typically happens at cleanup time for fragments that + * have been allocated but not used. + * + * Passing a NULL pointer to this function is safe, in that case no operation + * will be performed. + */ +void vsp1_dl_fragment_free(struct vsp1_dl_body *dlb) +{ + if (!dlb) + return; + + vsp1_dl_body_cleanup(dlb); + kfree(dlb); +} + +/** + * vsp1_dl_fragment_write - Write a register to a display list fragment + * @dlb: The fragment + * @reg: The register address + * @data: The register value + * + * Write the given register and value to the display list fragment. The maximum + * number of entries that can be written in a fragment is specified when the + * fragment is allocated by vsp1_dl_fragment_alloc(). + */ +void vsp1_dl_fragment_write(struct vsp1_dl_body *dlb, u32 reg, u32 data) +{ + dlb->entries[dlb->num_entries].addr = reg; + dlb->entries[dlb->num_entries].data = data; + dlb->num_entries++; +} + /* ----------------------------------------------------------------------------- * Display List Transaction Management */ @@ -99,42 +222,61 @@ static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) { struct vsp1_dl_list *dl; size_t header_size; - - /* The body needs to be aligned on a 8 bytes boundary, pad the header - * size to allow allocating both in a single operation. - */ - header_size = dlm->mode == VSP1_DL_MODE_HEADER - ? ALIGN(sizeof(struct vsp1_dl_header), 8) - : 0; + int ret; dl = kzalloc(sizeof(*dl), GFP_KERNEL); if (!dl) return NULL; + INIT_LIST_HEAD(&dl->fragments); dl->dlm = dlm; - dl->size = header_size + VSP1_DL_BODY_SIZE; - dl->header = dma_alloc_wc(dlm->vsp1->dev, dl->size, &dl->dma, - GFP_KERNEL); - if (!dl->header) { + /* Initialize the display list body and allocate DMA memory for the body + * and the optional header. Both are allocated together to avoid memory + * fragmentation, with the header located right after the body in + * memory. + */ + header_size = dlm->mode == VSP1_DL_MODE_HEADER + ? ALIGN(sizeof(struct vsp1_dl_header), 8) + : 0; + + ret = vsp1_dl_body_init(dlm->vsp1, &dl->body0, VSP1_DL_NUM_ENTRIES, + header_size); + if (ret < 0) { kfree(dl); return NULL; } if (dlm->mode == VSP1_DL_MODE_HEADER) { + size_t header_offset = VSP1_DL_NUM_ENTRIES + * sizeof(*dl->body0.entries); + + dl->header = ((void *)dl->body0.entries) + header_offset; + dl->dma = dl->body0.dma + header_offset; + memset(dl->header, 0, sizeof(*dl->header)); - dl->header->lists[0].addr = dl->dma + header_size; + dl->header->lists[0].addr = dl->body0.dma; dl->header->flags = VSP1_DLH_INT_ENABLE; } - dl->body = ((void *)dl->header) + header_size; - return dl; } +static void vsp1_dl_list_free_fragments(struct vsp1_dl_list *dl) +{ + struct vsp1_dl_body *dlb, *next; + + list_for_each_entry_safe(dlb, next, &dl->fragments, list) { + list_del(&dlb->list); + vsp1_dl_body_cleanup(dlb); + kfree(dlb); + } +} + static void vsp1_dl_list_free(struct vsp1_dl_list *dl) { - dma_free_wc(dl->dlm->vsp1->dev, dl->size, dl->header, dl->dma); + vsp1_dl_body_cleanup(&dl->body0); + vsp1_dl_list_free_fragments(dl); kfree(dl); } @@ -169,7 +311,8 @@ static void __vsp1_dl_list_put(struct vsp1_dl_list *dl) if (!dl) return; - dl->reg_count = 0; + vsp1_dl_list_free_fragments(dl); + dl->body0.num_entries = 0; list_add_tail(&dl->list, &dl->dlm->free); } @@ -195,11 +338,45 @@ void vsp1_dl_list_put(struct vsp1_dl_list *dl) spin_unlock_irqrestore(&dl->dlm->lock, flags); } +/** + * vsp1_dl_list_write - Write a register to the display list + * @dl: The display list + * @reg: The register address + * @data: The register value + * + * Write the given register and value to the display list. Up to 256 registers + * can be written per display list. + */ void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data) { - dl->body[dl->reg_count].addr = reg; - dl->body[dl->reg_count].data = data; - dl->reg_count++; + vsp1_dl_fragment_write(&dl->body0, reg, data); +} + +/** + * vsp1_dl_list_add_fragment - Add a fragment to the display list + * @dl: The display list + * @dlb: The fragment + * + * Add a display list body as a fragment to a display list. Registers contained + * in fragments are processed after registers contained in the main display + * list, in the order in which fragments are added. + * + * Adding a fragment to a display list passes ownership of the fragment to the + * list. The caller must not touch the fragment after this call, and must not + * free it explicitly with vsp1_dl_fragment_free(). + * + * Fragments are only usable for display lists in header mode. Attempt to + * add a fragment to a header-less display list will return an error. + */ +int vsp1_dl_list_add_fragment(struct vsp1_dl_list *dl, + struct vsp1_dl_body *dlb) +{ + /* Multi-body lists are only available in header mode. */ + if (dl->dlm->mode != VSP1_DL_MODE_HEADER) + return -EINVAL; + + list_add_tail(&dlb->list, &dl->fragments); + return 0; } void vsp1_dl_list_commit(struct vsp1_dl_list *dl) @@ -212,11 +389,30 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl) spin_lock_irqsave(&dlm->lock, flags); if (dl->dlm->mode == VSP1_DL_MODE_HEADER) { - /* Program the hardware with the display list body address and - * size. In header mode the caller guarantees that the hardware - * is idle at this point. + struct vsp1_dl_header_list *hdr = dl->header->lists; + struct vsp1_dl_body *dlb; + unsigned int num_lists = 0; + + /* Fill the header with the display list bodies addresses and + * sizes. The address of the first body has already been filled + * when the display list was allocated. + * + * In header mode the caller guarantees that the hardware is + * idle at this point. */ - dl->header->lists[0].num_bytes = dl->reg_count * 8; + hdr->num_bytes = dl->body0.num_entries + * sizeof(*dl->header->lists); + + list_for_each_entry(dlb, &dl->fragments, list) { + num_lists++; + hdr++; + + hdr->addr = dlb->dma; + hdr->num_bytes = dlb->num_entries + * sizeof(*dl->header->lists); + } + + dl->header->num_lists = num_lists; vsp1_write(vsp1, VI6_DL_HDR_ADDR(dlm->index), dl->dma); dlm->active = dl; @@ -239,9 +435,9 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl) * The UPD bit will be cleared by the device when the display list is * processed. */ - vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->dma); + vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->body0.dma); vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | - (dl->reg_count * 8)); + (dl->body0.num_entries * sizeof(*dl->header->lists))); __vsp1_dl_list_put(dlm->queued); dlm->queued = dl; @@ -307,9 +503,10 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) if (dlm->pending) { struct vsp1_dl_list *dl = dlm->pending; - vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->dma); + vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->body0.dma); vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | - (dl->reg_count * 8)); + (dl->body0.num_entries * + sizeof(*dl->header->lists))); dlm->queued = dl; dlm->pending = NULL; diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 571ed6d8e7c2..de387cd4d745 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -16,6 +16,7 @@ #include struct vsp1_device; +struct vsp1_dl_fragment; struct vsp1_dl_list; struct vsp1_dl_manager; @@ -34,4 +35,11 @@ void vsp1_dl_list_put(struct vsp1_dl_list *dl); void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data); void vsp1_dl_list_commit(struct vsp1_dl_list *dl); +struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1, + unsigned int num_entries); +void vsp1_dl_fragment_free(struct vsp1_dl_body *dlb); +void vsp1_dl_fragment_write(struct vsp1_dl_body *dlb, u32 reg, u32 data); +int vsp1_dl_list_add_fragment(struct vsp1_dl_list *dl, + struct vsp1_dl_body *dlb); + #endif /* __VSP1_DL_H__ */ -- GitLab From 0e6b9c565f33cd8b22879947647abd6c076cd73e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 3 Mar 2016 14:17:11 -0300 Subject: [PATCH 2608/9938] [media] v4l: vsp1: lut: Use display list fragments to fill LUT Synchronize the userspace LUT setup with the pipeline operation by using a display list fragment to store LUT data. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_lut.c | 31 +++++++++++++++++++++----- drivers/media/platform/vsp1/vsp1_lut.h | 6 ++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 33e3b5cc9c9b..aa09e59f0ab8 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -38,10 +38,25 @@ static inline void vsp1_lut_write(struct vsp1_lut *lut, struct vsp1_dl_list *dl, * V4L2 Subdevice Core Operations */ -static void lut_set_table(struct vsp1_lut *lut, struct vsp1_lut_config *config) +static int lut_set_table(struct vsp1_lut *lut, struct vsp1_lut_config *config) { - memcpy_toio(lut->entity.vsp1->mmio + VI6_LUT_TABLE, config->lut, - sizeof(config->lut)); + struct vsp1_dl_body *dlb; + unsigned int i; + + dlb = vsp1_dl_fragment_alloc(lut->entity.vsp1, ARRAY_SIZE(config->lut)); + if (!dlb) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(config->lut); ++i) + vsp1_dl_fragment_write(dlb, VI6_LUT_TABLE + 4 * i, + config->lut[i]); + + mutex_lock(&lut->lock); + swap(lut->lut, dlb); + mutex_unlock(&lut->lock); + + vsp1_dl_fragment_free(dlb); + return 0; } static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) @@ -50,8 +65,7 @@ static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) switch (cmd) { case VIDIOC_VSP1_LUT_CONFIG: - lut_set_table(lut, arg); - return 0; + return lut_set_table(lut, arg); default: return -ENOIOCTLCMD; @@ -161,6 +175,13 @@ static void lut_configure(struct vsp1_entity *entity, struct vsp1_lut *lut = to_lut(&entity->subdev); vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); + + mutex_lock(&lut->lock); + if (lut->lut) { + vsp1_dl_list_add_fragment(dl, lut->lut); + lut->lut = NULL; + } + mutex_unlock(&lut->lock); } static const struct vsp1_entity_operations lut_entity_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_lut.h b/drivers/media/platform/vsp1/vsp1_lut.h index f92ffb867350..cef874f22b6a 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.h +++ b/drivers/media/platform/vsp1/vsp1_lut.h @@ -13,6 +13,8 @@ #ifndef __VSP1_LUT_H__ #define __VSP1_LUT_H__ +#include + #include #include @@ -25,7 +27,9 @@ struct vsp1_device; struct vsp1_lut { struct vsp1_entity entity; - u32 lut[256]; + + struct mutex lock; + struct vsp1_dl_body *lut; }; static inline struct vsp1_lut *to_lut(struct v4l2_subdev *subdev) -- GitLab From 30276a731a9c14123c95070197a08bafc148f7bc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 22 Mar 2016 11:10:27 -0300 Subject: [PATCH 2609/9938] [media] v4l: vsp1: Add support for the RPF alpha multiplier on Gen3 The Gen3 RPF includes an alpha multiplier that can both multiply the alpha channel by a fixed global alpha value, and multiply the pixel components to convert the input to premultiplied alpha. As alpha premultiplication is available in the BRU for both Gen2 and Gen3 we handle it there and use the Gen3 alpha multiplier for global alpha multiplication only. This prevents conversion to premultiplied alpha if no BRU is present in the pipeline, that use case will be implemented later if needed. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 1 + drivers/media/platform/vsp1/vsp1_drv.c | 8 ++++ drivers/media/platform/vsp1/vsp1_regs.h | 10 +++++ drivers/media/platform/vsp1/vsp1_rpf.c | 57 +++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index dae987a11a70..46738b6c5f72 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -48,6 +48,7 @@ struct vsp1_uds; struct vsp1_device_info { u32 version; + unsigned int gen; unsigned int features; unsigned int rpf_count; unsigned int uds_count; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 596f26d81494..e2d779fac0eb 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -558,6 +558,7 @@ static const struct dev_pm_ops vsp1_pm_ops = { static const struct vsp1_device_info vsp1_device_infos[] = { { .version = VI6_IP_VERSION_MODEL_VSPS_H2, + .gen = 2, .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU, .rpf_count = 5, .uds_count = 3, @@ -566,6 +567,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPR_H2, + .gen = 2, .features = VSP1_HAS_BRU | VSP1_HAS_SRU, .rpf_count = 5, .uds_count = 1, @@ -574,6 +576,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPD_GEN2, + .gen = 2, .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT, .rpf_count = 4, .uds_count = 1, @@ -582,6 +585,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPS_M2, + .gen = 2, .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU, .rpf_count = 5, .uds_count = 3, @@ -590,6 +594,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPI_GEN3, + .gen = 3, .features = VSP1_HAS_LUT | VSP1_HAS_SRU, .rpf_count = 1, .uds_count = 1, @@ -597,6 +602,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3, + .gen = 3, .features = VSP1_HAS_BRU, .rpf_count = 5, .wpf_count = 1, @@ -604,6 +610,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3, + .gen = 3, .features = VSP1_HAS_BRU | VSP1_HAS_LUT, .rpf_count = 5, .wpf_count = 1, @@ -611,6 +618,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .uapi = true, }, { .version = VI6_IP_VERSION_MODEL_VSPD_GEN3, + .gen = 3, .features = VSP1_HAS_BRU | VSP1_HAS_LIF, .rpf_count = 5, .wpf_count = 2, diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 069216f0eb44..927b5fb94c48 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -217,6 +217,16 @@ #define VI6_RPF_SRCM_ADDR_C1 0x0344 #define VI6_RPF_SRCM_ADDR_AI 0x0348 +#define VI6_RPF_MULT_ALPHA 0x036c +#define VI6_RPF_MULT_ALPHA_A_MMD_NONE (0 << 12) +#define VI6_RPF_MULT_ALPHA_A_MMD_RATIO (1 << 12) +#define VI6_RPF_MULT_ALPHA_P_MMD_NONE (0 << 8) +#define VI6_RPF_MULT_ALPHA_P_MMD_RATIO (1 << 8) +#define VI6_RPF_MULT_ALPHA_P_MMD_IMAGE (2 << 8) +#define VI6_RPF_MULT_ALPHA_P_MMD_BOTH (3 << 8) +#define VI6_RPF_MULT_ALPHA_RATIO_MASK (0xff < 0) +#define VI6_RPF_MULT_ALPHA_RATIO_SHIFT 0 + /* ----------------------------------------------------------------------------- * WPF Control Registers */ diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 5486ff54a2b3..49168db3f529 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -141,9 +141,27 @@ static void rpf_configure(struct vsp1_entity *entity, (left << VI6_RPF_LOC_HCOORD_SHIFT) | (top << VI6_RPF_LOC_VCOORD_SHIFT)); - /* Use the alpha channel (extended to 8 bits) when available or an - * alpha value set through the V4L2_CID_ALPHA_COMPONENT control - * otherwise. Disable color keying. + /* On Gen2 use the alpha channel (extended to 8 bits) when available or + * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control + * otherwise. + * + * The Gen3 RPF has extended alpha capability and can both multiply the + * alpha channel by a fixed global alpha value, and multiply the pixel + * components to convert the input to premultiplied alpha. + * + * As alpha premultiplication is available in the BRU for both Gen2 and + * Gen3 we handle it there and use the Gen3 alpha multiplier for global + * alpha multiplication only. This however prevents conversion to + * premultiplied alpha if no BRU is present in the pipeline. If that use + * case turns out to be useful we will revisit the implementation (for + * Gen3 only). + * + * We enable alpha multiplication on Gen3 using the fixed alpha value + * set through the V4L2_CID_ALPHA_COMPONENT control when the input + * contains an alpha channel. On Gen2 the global alpha is ignored in + * that case. + * + * In all cases, disable color keying. */ vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT | (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED @@ -152,10 +170,43 @@ static void rpf_configure(struct vsp1_entity *entity, vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET, rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); + if (entity->vsp1->info->gen == 3) { + u32 mult; + + if (fmtinfo->alpha) { + /* When the input contains an alpha channel enable the + * alpha multiplier. If the input is premultiplied we + * need to multiply both the alpha channel and the pixel + * components by the global alpha value to keep them + * premultiplied. Otherwise multiply the alpha channel + * only. + */ + bool premultiplied = format->flags + & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; + + mult = VI6_RPF_MULT_ALPHA_A_MMD_RATIO + | (premultiplied ? + VI6_RPF_MULT_ALPHA_P_MMD_RATIO : + VI6_RPF_MULT_ALPHA_P_MMD_NONE) + | (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT); + } else { + /* When the input doesn't contain an alpha channel the + * global alpha value is applied in the unpacking unit, + * the alpha multiplier isn't needed and must be + * disabled. + */ + mult = VI6_RPF_MULT_ALPHA_A_MMD_NONE + | VI6_RPF_MULT_ALPHA_P_MMD_NONE; + } + + vsp1_rpf_write(rpf, dl, VI6_RPF_MULT_ALPHA, mult); + } + vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, dl, rpf->alpha); vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0); vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0); + } static const struct vsp1_entity_operations rpf_entity_ops = { -- GitLab From 198ed9625a1c8d5a8f43a4888075c048d9488dc8 Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Mon, 11 Apr 2016 20:54:44 +0900 Subject: [PATCH 2610/9938] arm64: add Kconfig entry for LG1K SoC family This patch introduces ARCH_LG1K to enable LG Electronics's LG1K SoC family in Kconfig. Signed-off-by: Chanho Min Signed-off-by: Olof Johansson --- arch/arm64/Kconfig.platforms | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index efa77c146415..be543c0b863d 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -43,6 +43,11 @@ config ARCH_LAYERSCAPE help This enables support for the Freescale Layerscape SoC family. +config ARCH_LG1K + bool "LG Electronics LG1K SoC Family" + help + This enables support for LG Electronics LG1K SoC Family + config ARCH_HISI bool "Hisilicon SoC Family" select HISILICON_IRQ_MBIGEN -- GitLab From b824a954814130995df4ca2a3266c1a3ca3de986 Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Mon, 11 Apr 2016 20:54:45 +0900 Subject: [PATCH 2611/9938] arm64: defconfig: enable ARCH_LG1K Enable building LG1K support in the defconfig. Signed-off-by: Chanho Min Signed-off-by: Olof Johansson --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 6d15d453fcb9..5091d3577e75 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -36,6 +36,7 @@ CONFIG_ARCH_BCM_IPROC=y CONFIG_ARCH_BERLIN=y CONFIG_ARCH_EXYNOS=y CONFIG_ARCH_LAYERSCAPE=y +CONFIG_ARCH_LG1K=y CONFIG_ARCH_HISI=y CONFIG_ARCH_MEDIATEK=y CONFIG_ARCH_MESON=y -- GitLab From f5e04e7ea7bebbed77c6438c7f007c354a40ce22 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 24 Mar 2016 05:15:59 -0300 Subject: [PATCH 2612/9938] [media] v4l: vsp1: Add Z-order support for DRM pipeline Make the Z-order of planes configurable by assigning RPFs to BRU inputs dynamically based on the Z-order position. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 180 ++++++++++++++---------- drivers/media/platform/vsp1/vsp1_drm.h | 12 +- drivers/media/platform/vsp1/vsp1_pipe.c | 1 + include/media/vsp1.h | 18 ++- 4 files changed, 130 insertions(+), 81 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 7cde2d970dba..d85cb0e258c9 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -93,6 +93,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, media_entity_pipeline_stop(&pipe->output->entity.subdev.entity); for (i = 0; i < bru->entity.source_pad; ++i) { + vsp1->drm->inputs[i].enabled = false; bru->inputs[i].rpf = NULL; pipe->inputs[i] = NULL; } @@ -217,14 +218,9 @@ void vsp1_du_atomic_begin(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_pipeline *pipe = &vsp1->drm->pipe; - unsigned long flags; - - spin_lock_irqsave(&pipe->irqlock, flags); vsp1->drm->num_inputs = pipe->num_inputs; - spin_unlock_irqrestore(&pipe->irqlock, flags); - /* Prepare the display list. */ pipe->dl = vsp1_dl_list_get(pipe->output->dlm); } @@ -239,10 +235,12 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); * @mem: DMA addresses of the memory buffers (one per plane) * @src: the source crop rectangle for the RPF * @dst: the destination compose rectangle for the BRU input + * @zpos: the Z-order position of the input * * Configure the VSP to perform composition of the image referenced by @mem * through RPF @rpf_index, using the @src crop rectangle and the @dst - * composition rectangle. The Z-order is fixed with RPF 0 at the bottom. + * composition rectangle. The Z-order is configurable with higher @zpos values + * displayed on top. * * Image format as stored in memory is expressed as a V4L2 @pixelformat value. * As a special case, setting the pixel format to 0 will disable the RPF. The @@ -260,24 +258,16 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); * * This function isn't reentrant, the caller needs to serialize calls. * - * TODO: Implement Z-order control by decoupling the RPF index from the BRU - * input index. - * * Return 0 on success or a negative error code on failure. */ -int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, - u32 pixelformat, unsigned int pitch, - dma_addr_t mem[2], const struct v4l2_rect *src, - const struct v4l2_rect *dst) +int vsp1_du_atomic_update_ext(struct device *dev, unsigned int rpf_index, + u32 pixelformat, unsigned int pitch, + dma_addr_t mem[2], const struct v4l2_rect *src, + const struct v4l2_rect *dst, unsigned int zpos) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); - struct vsp1_pipeline *pipe = &vsp1->drm->pipe; const struct vsp1_format_info *fmtinfo; - struct v4l2_subdev_selection sel; - struct v4l2_subdev_format format; struct vsp1_rwpf *rpf; - unsigned long flags; - int ret; if (rpf_index >= vsp1->info->rpf_count) return -EINVAL; @@ -288,31 +278,20 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__, rpf_index); - spin_lock_irqsave(&pipe->irqlock, flags); - - if (pipe->inputs[rpf_index]) { - /* Remove the RPF from the pipeline if it was previously - * enabled. - */ - vsp1->bru->inputs[rpf_index].rpf = NULL; - pipe->inputs[rpf_index] = NULL; - - pipe->num_inputs--; - } - - spin_unlock_irqrestore(&pipe->irqlock, flags); - + vsp1->drm->inputs[rpf_index].enabled = false; return 0; } dev_dbg(vsp1->dev, - "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad }\n", + "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad } zpos %u\n", __func__, rpf_index, src->left, src->top, src->width, src->height, dst->left, dst->top, dst->width, dst->height, - pixelformat, pitch, &mem[0], &mem[1]); + pixelformat, pitch, &mem[0], &mem[1], zpos); - /* Set the stride at the RPF input. */ + /* Store the format, stride, memory buffer address, crop and compose + * rectangles and Z-order position and for the input. + */ fmtinfo = vsp1_get_format_info(pixelformat); if (!fmtinfo) { dev_dbg(vsp1->dev, "Unsupport pixel format %08x for RPF\n", @@ -325,15 +304,38 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, rpf->format.plane_fmt[0].bytesperline = pitch; rpf->format.plane_fmt[1].bytesperline = pitch; + rpf->mem.addr[0] = mem[0]; + rpf->mem.addr[1] = mem[1]; + rpf->mem.addr[2] = 0; + + vsp1->drm->inputs[rpf_index].crop = *src; + vsp1->drm->inputs[rpf_index].compose = *dst; + vsp1->drm->inputs[rpf_index].zpos = zpos; + vsp1->drm->inputs[rpf_index].enabled = true; + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_atomic_update_ext); + +static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1, + struct vsp1_rwpf *rpf, unsigned int bru_input) +{ + struct v4l2_subdev_selection sel; + struct v4l2_subdev_format format; + const struct v4l2_rect *crop; + int ret; + /* Configure the format on the RPF sink pad and propagate it up to the * BRU sink pad. */ + crop = &vsp1->drm->inputs[rpf->entity.index].crop; + memset(&format, 0, sizeof(format)); format.which = V4L2_SUBDEV_FORMAT_ACTIVE; format.pad = RWPF_PAD_SINK; - format.format.width = src->width + src->left; - format.format.height = src->height + src->top; - format.format.code = fmtinfo->mbus; + format.format.width = crop->width + crop->left; + format.format.height = crop->height + crop->top; + format.format.code = rpf->fmtinfo->mbus; format.format.field = V4L2_FIELD_NONE; ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, @@ -350,7 +352,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; sel.pad = RWPF_PAD_SINK; sel.target = V4L2_SEL_TGT_CROP; - sel.r = *src; + sel.r = *crop; ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL, &sel); @@ -385,7 +387,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, return ret; /* BRU sink, propagate the format from the RPF source. */ - format.pad = rpf->entity.index; + format.pad = bru_input; ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_fmt, NULL, &format); @@ -396,9 +398,9 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, __func__, format.format.width, format.format.height, format.format.code, format.pad); - sel.pad = rpf->entity.index; + sel.pad = bru_input; sel.target = V4L2_SEL_TGT_COMPOSE; - sel.r = *dst; + sel.r = vsp1->drm->inputs[rpf->entity.index].compose; ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_selection, NULL, &sel); @@ -410,32 +412,13 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, sel.pad); - /* Store the BRU input pad number in the RPF. */ - rpf->bru_input = rpf->entity.index; - - /* Cache the memory buffer address but don't apply the values to the - * hardware as the crop offsets haven't been computed yet. - */ - rpf->mem.addr[0] = mem[0]; - rpf->mem.addr[1] = mem[1]; - rpf->mem.addr[2] = 0; - - spin_lock_irqsave(&pipe->irqlock, flags); - - /* If the RPF was previously stopped set the BRU input to the RPF and - * store the RPF in the pipeline inputs array. - */ - if (!pipe->inputs[rpf->entity.index]) { - vsp1->bru->inputs[rpf_index].rpf = rpf; - pipe->inputs[rpf->entity.index] = rpf; - pipe->num_inputs++; - } - - spin_unlock_irqrestore(&pipe->irqlock, flags); - return 0; } -EXPORT_SYMBOL_GPL(vsp1_du_atomic_update); + +static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf) +{ + return vsp1->drm->inputs[rpf->entity.index].zpos; +} /** * vsp1_du_atomic_flush - Commit an atomic update @@ -445,10 +428,60 @@ void vsp1_du_atomic_flush(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, }; struct vsp1_entity *entity; unsigned long flags; - bool stop = false; + unsigned int i; + int ret; + + /* Count the number of enabled inputs and sort them by Z-order. */ + pipe->num_inputs = 0; + + for (i = 0; i < vsp1->info->rpf_count; ++i) { + struct vsp1_rwpf *rpf = vsp1->rpf[i]; + unsigned int j; + + if (!vsp1->drm->inputs[i].enabled) { + pipe->inputs[i] = NULL; + continue; + } + + pipe->inputs[i] = rpf; + + /* Insert the RPF in the sorted RPFs array. */ + for (j = pipe->num_inputs++; j > 0; --j) { + if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf)) + break; + inputs[j] = inputs[j-1]; + } + inputs[j] = rpf; + } + + /* Setup the RPF input pipeline for every enabled input. */ + for (i = 0; i < vsp1->info->num_bru_inputs; ++i) { + struct vsp1_rwpf *rpf = inputs[i]; + + if (!rpf) { + vsp1->bru->inputs[i].rpf = NULL; + continue; + } + + vsp1->bru->inputs[i].rpf = rpf; + rpf->bru_input = i; + rpf->entity.sink_pad = i; + + dev_dbg(vsp1->dev, "%s: connecting RPF.%u to BRU:%u\n", + __func__, rpf->entity.index, i); + + ret = vsp1_du_setup_rpf_pipe(vsp1, rpf, i); + if (ret < 0) + dev_err(vsp1->dev, + "%s: failed to setup RPF.%u\n", + __func__, rpf->entity.index); + } + + /* Configure all entities in the pipeline. */ list_for_each_entry(entity, &pipe->entities, list_pipe) { /* Disconnect unused RPFs from the pipeline. */ if (entity->type == VSP1_ENTITY_RPF) { @@ -466,6 +499,9 @@ void vsp1_du_atomic_flush(struct device *dev) if (entity->ops->configure) entity->ops->configure(entity, pipe, pipe->dl); + /* The memory buffer address must be applied after configuring + * the RPF to make sure the crop offset are computed. + */ if (entity->type == VSP1_ENTITY_RPF) vsp1_rwpf_set_memory(to_rwpf(&entity->subdev), pipe->dl); @@ -475,19 +511,13 @@ void vsp1_du_atomic_flush(struct device *dev) pipe->dl = NULL; /* Start or stop the pipeline if needed. */ - spin_lock_irqsave(&pipe->irqlock, flags); - if (!vsp1->drm->num_inputs && pipe->num_inputs) { vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0); vsp1_write(vsp1, VI6_DISP_IRQ_ENB, VI6_DISP_IRQ_ENB_DSTE); + spin_lock_irqsave(&pipe->irqlock, flags); vsp1_pipeline_run(pipe); + spin_unlock_irqrestore(&pipe->irqlock, flags); } else if (vsp1->drm->num_inputs && !pipe->num_inputs) { - stop = true; - } - - spin_unlock_irqrestore(&pipe->irqlock, flags); - - if (stop) { vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0); vsp1_pipeline_stop(pipe); } diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index e9242f2c870e..9e28ab9254ba 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -13,18 +13,26 @@ #ifndef __VSP1_DRM_H__ #define __VSP1_DRM_H__ +#include + #include "vsp1_pipe.h" /** * vsp1_drm - State for the API exposed to the DRM driver * @pipe: the VSP1 pipeline used for display * @num_inputs: number of active pipeline inputs at the beginning of an update - * @update: the pipeline configuration has been updated + * @planes: source crop rectangle, destination compose rectangle and z-order + * position for every input */ struct vsp1_drm { struct vsp1_pipeline pipe; unsigned int num_inputs; - bool update; + struct { + bool enabled; + struct v4l2_rect crop; + struct v4l2_rect compose; + unsigned int zpos; + } inputs[VSP1_MAX_RPF]; }; int vsp1_drm_init(struct vsp1_device *vsp1); diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 4913b933562c..15e028321fa1 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -200,6 +200,7 @@ void vsp1_pipeline_init(struct vsp1_pipeline *pipe) pipe->state = VSP1_PIPELINE_STOPPED; } +/* Must be called with the pipe irqlock held. */ void vsp1_pipeline_run(struct vsp1_pipeline *pipe) { struct vsp1_device *vsp1 = pipe->output->entity.vsp1; diff --git a/include/media/vsp1.h b/include/media/vsp1.h index d01f7cb8f691..e54a493bd3ff 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -24,10 +24,20 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, unsigned int height); void vsp1_du_atomic_begin(struct device *dev); -int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat, - unsigned int pitch, dma_addr_t mem[2], - const struct v4l2_rect *src, - const struct v4l2_rect *dst); +int vsp1_du_atomic_update_ext(struct device *dev, unsigned int rpf, + u32 pixelformat, unsigned int pitch, + dma_addr_t mem[2], const struct v4l2_rect *src, + const struct v4l2_rect *dst, unsigned int zpos); void vsp1_du_atomic_flush(struct device *dev); +static inline int vsp1_du_atomic_update(struct device *dev, + unsigned int rpf_index, u32 pixelformat, + unsigned int pitch, dma_addr_t mem[2], + const struct v4l2_rect *src, + const struct v4l2_rect *dst) +{ + return vsp1_du_atomic_update_ext(dev, rpf_index, pixelformat, pitch, + mem, src, dst, 0); +} + #endif /* __MEDIA_VSP1_H__ */ -- GitLab From bbb8d793994c894eef2a48a35fac6de3c6b4fa93 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Apr 2016 02:40:39 +0200 Subject: [PATCH 2613/9938] net: dsa: Pass the dsa device to the switch drivers By passing a device structure to the switch devices, it allows them to use devm_* methods for resource management. Signed-off-by: Andrew Lunn Acked-by: Florian Fainelli Tested-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 3 ++- drivers/net/dsa/mv88e6060.c | 3 ++- drivers/net/dsa/mv88e6123.c | 3 ++- drivers/net/dsa/mv88e6131.c | 3 ++- drivers/net/dsa/mv88e6171.c | 3 ++- drivers/net/dsa/mv88e6352.c | 3 ++- include/net/dsa.h | 3 ++- net/dsa/dsa.c | 7 ++++--- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 780f22876538..18a79579141f 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -135,7 +135,8 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds) return BCM_SF2_STATS_SIZE; } -static char *bcm_sf2_sw_probe(struct device *host_dev, int sw_addr) +static char *bcm_sf2_sw_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr) { return "Broadcom Starfighter 2"; } diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 0527f485c3dc..34d0f9fe19db 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -57,7 +57,8 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) return __ret; \ }) -static char *mv88e6060_probe(struct device *host_dev, int sw_addr) +static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); int ret; diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 69a6f79dcb10..ede4c6f0b31a 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -29,7 +29,8 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = { { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, }; -static char *mv88e6123_probe(struct device *host_dev, int sw_addr) +static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr) { return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table, ARRAY_SIZE(mv88e6123_table)); diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 24070287c2bc..bfadfd2cbb8d 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -25,7 +25,8 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = { { PORT_SWITCH_ID_6185, "Marvell 88E6185" }, }; -static char *mv88e6131_probe(struct device *host_dev, int sw_addr) +static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr) { return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table, ARRAY_SIZE(mv88e6131_table)); diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 0e62f3b5bc81..fb35d3ac1644 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -24,7 +24,8 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = { { PORT_SWITCH_ID_6351, "Marvell 88E6351" }, }; -static char *mv88e6171_probe(struct device *host_dev, int sw_addr) +static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr) { return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table, ARRAY_SIZE(mv88e6171_table)); diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 7f452e4a04a5..577ab2cfa944 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -37,7 +37,8 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" }, }; -static char *mv88e6352_probe(struct device *host_dev, int sw_addr) +static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr) { return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table, ARRAY_SIZE(mv88e6352_table)); diff --git a/include/net/dsa.h b/include/net/dsa.h index 18d1be3ad62d..0f9f6f38f255 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -212,7 +212,8 @@ struct dsa_switch_driver { /* * Probing and setup. */ - char *(*probe)(struct device *host_dev, int sw_addr); + char *(*probe)(struct device *dsa_dev, struct device *host_dev, + int sw_addr); int (*setup)(struct dsa_switch *ds); int (*set_addr)(struct dsa_switch *ds, u8 *addr); u32 (*get_phy_flags)(struct dsa_switch *ds, int port); diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index c28c47463b7e..c06275311cb2 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -51,7 +51,8 @@ void unregister_switch_driver(struct dsa_switch_driver *drv) EXPORT_SYMBOL_GPL(unregister_switch_driver); static struct dsa_switch_driver * -dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name) +dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr, + char **_name) { struct dsa_switch_driver *ret; struct list_head *list; @@ -66,7 +67,7 @@ dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name) drv = list_entry(list, struct dsa_switch_driver, list); - name = drv->probe(host_dev, sw_addr); + name = drv->probe(parent, host_dev, sw_addr); if (name != NULL) { ret = drv; break; @@ -387,7 +388,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, /* * Probe for switch model. */ - drv = dsa_switch_probe(host_dev, pd->sw_addr, &name); + drv = dsa_switch_probe(parent, host_dev, pd->sw_addr, &name); if (drv == NULL) { netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n", index); -- GitLab From 7543a6d5359e371ce9434955dbe6a79f548ea321 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Apr 2016 02:40:40 +0200 Subject: [PATCH 2614/9938] net: dsa: Have the switch driver allocate there own private memory Now the switch devices have a dev pointer, make use of it for allocating the drivers private data structures using a devm_kzalloc(). Signed-off-by: Andrew Lunn Acked-by: Florian Fainelli Tested-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 10 ++++++++-- drivers/net/dsa/mv88e6060.c | 3 ++- drivers/net/dsa/mv88e6123.c | 17 ++++++++++++++--- drivers/net/dsa/mv88e6131.c | 17 ++++++++++++++--- drivers/net/dsa/mv88e6171.c | 17 ++++++++++++++--- drivers/net/dsa/mv88e6352.c | 17 ++++++++++++++--- drivers/net/dsa/mv88e6xxx.c | 6 ++++-- drivers/net/dsa/mv88e6xxx.h | 3 +++ include/net/dsa.h | 10 ++++++++-- net/dsa/dsa.c | 8 +++++--- 10 files changed, 86 insertions(+), 22 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 18a79579141f..7d62802a66d5 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -136,8 +136,15 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds) } static char *bcm_sf2_sw_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr) + int sw_addr, void **_priv) { + struct bcm_sf2_priv *priv; + + priv = devm_kzalloc(dsa_dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return NULL; + *_priv = priv; + return "Broadcom Starfighter 2"; } @@ -1363,7 +1370,6 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port, static struct dsa_switch_driver bcm_sf2_switch_driver = { .tag_protocol = DSA_TAG_PROTO_BRCM, - .priv_size = sizeof(struct bcm_sf2_priv), .probe = bcm_sf2_sw_probe, .setup = bcm_sf2_sw_setup, .set_addr = bcm_sf2_sw_set_addr, diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 34d0f9fe19db..41195f1417f1 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -58,11 +58,12 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) }) static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr) + int sw_addr, void **priv) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); int ret; + *priv = NULL; if (bus == NULL) return NULL; diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index ede4c6f0b31a..bcab3ef22448 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -30,10 +30,20 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = { }; static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr) + int sw_addr, void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table, + struct mv88e6xxx_priv_state *ps; + char *name; + + name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table, ARRAY_SIZE(mv88e6123_table)); + if (name) { + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); + if (!ps) + return NULL; + *priv = ps; + } + return name; } static int mv88e6123_setup_global(struct dsa_switch *ds) @@ -74,6 +84,8 @@ static int mv88e6123_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; + ps->ds = ds; + ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; @@ -103,7 +115,6 @@ static int mv88e6123_setup(struct dsa_switch *ds) struct dsa_switch_driver mv88e6123_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6123_probe, .setup = mv88e6123_setup, .set_addr = mv88e6xxx_set_addr_indirect, diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index bfadfd2cbb8d..b9f9b009f65a 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -26,10 +26,20 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = { }; static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr) + int sw_addr, void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table, + struct mv88e6xxx_priv_state *ps; + char *name; + + name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table, ARRAY_SIZE(mv88e6131_table)); + if (name) { + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); + if (!ps) + return NULL; + *priv = ps; + } + return name; } static int mv88e6131_setup_global(struct dsa_switch *ds) @@ -92,6 +102,8 @@ static int mv88e6131_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; + ps->ds = ds; + ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; @@ -160,7 +172,6 @@ mv88e6131_phy_write(struct dsa_switch *ds, struct dsa_switch_driver mv88e6131_switch_driver = { .tag_protocol = DSA_TAG_PROTO_DSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6131_probe, .setup = mv88e6131_setup, .set_addr = mv88e6xxx_set_addr_direct, diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index fb35d3ac1644..15200928cecc 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -25,10 +25,20 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = { }; static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr) + int sw_addr, void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table, + struct mv88e6xxx_priv_state *ps; + char *name; + + name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table, ARRAY_SIZE(mv88e6171_table)); + if (name) { + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); + if (!ps) + return NULL; + *priv = ps; + } + return name; } static int mv88e6171_setup_global(struct dsa_switch *ds) @@ -70,6 +80,8 @@ static int mv88e6171_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; + ps->ds = ds; + ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; @@ -89,7 +101,6 @@ static int mv88e6171_setup(struct dsa_switch *ds) struct dsa_switch_driver mv88e6171_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6171_probe, .setup = mv88e6171_setup, .set_addr = mv88e6xxx_set_addr_indirect, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 577ab2cfa944..7081a78a67e1 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -38,10 +38,20 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { }; static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr) + int sw_addr, void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table, + struct mv88e6xxx_priv_state *ps; + char *name; + + name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table, ARRAY_SIZE(mv88e6352_table)); + if (name) { + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); + if (!ps) + return NULL; + *priv = ps; + } + return name; } static int mv88e6352_setup_global(struct dsa_switch *ds) @@ -82,6 +92,8 @@ static int mv88e6352_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; + ps->ds = ds; + ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; @@ -303,7 +315,6 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds, struct dsa_switch_driver mv88e6352_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6352_probe, .setup = mv88e6352_setup, .set_addr = mv88e6xxx_set_addr_indirect, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 62320fca6712..085fc4a49eb2 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -281,7 +281,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly) ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work); if (mutex_trylock(&ps->ppu_mutex)) { - struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1; + struct dsa_switch *ds = ps->ds; if (mv88e6xxx_ppu_enable(ds) == 0) ps->ppu_disabled = 0; @@ -2322,7 +2322,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) int port; ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work); - ds = ((struct dsa_switch *)ps) - 1; + ds = ps->ds; mutex_lock(&ps->smi_mutex); @@ -2670,6 +2670,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + ps->ds = ds; + mutex_init(&ps->smi_mutex); ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 236bcaa606e7..0322e3e0e7d9 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -397,6 +397,9 @@ struct mv88e6xxx_priv_port { }; struct mv88e6xxx_priv_state { + /* The dsa_switch this private structure is related to */ + struct dsa_switch *ds; + /* When using multi-chip addressing, this mutex protects * access to the indirect access registers. (In single-chip * mode, this mutex is effectively useless.) diff --git a/include/net/dsa.h b/include/net/dsa.h index 0f9f6f38f255..7bc7bd9b5ded 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -129,6 +129,12 @@ struct dsa_switch { struct dsa_switch_tree *dst; int index; + /* + * Give the switch driver somewhere to hang its private data + * structure. + */ + void *priv; + /* * Tagging protocol understood by this switch */ @@ -213,7 +219,7 @@ struct dsa_switch_driver { * Probing and setup. */ char *(*probe)(struct device *dsa_dev, struct device *host_dev, - int sw_addr); + int sw_addr, void **priv); int (*setup)(struct dsa_switch *ds); int (*set_addr)(struct dsa_switch *ds, u8 *addr); u32 (*get_phy_flags)(struct dsa_switch *ds, int port); @@ -342,7 +348,7 @@ struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev); static inline void *ds_to_priv(struct dsa_switch *ds) { - return (void *)(ds + 1); + return ds->priv; } static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index c06275311cb2..7ef8a92a9e39 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -52,7 +52,7 @@ EXPORT_SYMBOL_GPL(unregister_switch_driver); static struct dsa_switch_driver * dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr, - char **_name) + char **_name, void **priv) { struct dsa_switch_driver *ret; struct list_head *list; @@ -67,7 +67,7 @@ dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr, drv = list_entry(list, struct dsa_switch_driver, list); - name = drv->probe(parent, host_dev, sw_addr); + name = drv->probe(parent, host_dev, sw_addr, priv); if (name != NULL) { ret = drv; break; @@ -384,11 +384,12 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, struct dsa_switch *ds; int ret; char *name; + void *priv; /* * Probe for switch model. */ - drv = dsa_switch_probe(parent, host_dev, pd->sw_addr, &name); + drv = dsa_switch_probe(parent, host_dev, pd->sw_addr, &name, &priv); if (drv == NULL) { netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n", index); @@ -409,6 +410,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ds->index = index; ds->pd = pd; ds->drv = drv; + ds->priv = priv; ds->tag_protocol = drv->tag_protocol; ds->master_dev = host_dev; -- GitLab From 5feebd0a8a799fe076c606b7c3bc267ae8c4344a Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Apr 2016 02:40:41 +0200 Subject: [PATCH 2615/9938] net: dsa: Remove allocation of driver private memory The drivers now allocate their own memory for private usage. Remove the allocation from the core code. Signed-off-by: Andrew Lunn Acked-by: Florian Fainelli Tested-by: Vivien Didelot Signed-off-by: David S. Miller --- include/net/dsa.h | 1 - net/dsa/dsa.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 7bc7bd9b5ded..165c2e10615c 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -213,7 +213,6 @@ struct dsa_switch_driver { struct list_head list; enum dsa_tag_protocol tag_protocol; - int priv_size; /* * Probing and setup. diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 7ef8a92a9e39..14bf12f637d2 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -402,7 +402,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, /* * Allocate and initialise switch state. */ - ds = devm_kzalloc(parent, sizeof(*ds) + drv->priv_size, GFP_KERNEL); + ds = devm_kzalloc(parent, sizeof(*ds), GFP_KERNEL); if (ds == NULL) return ERR_PTR(-ENOMEM); -- GitLab From a77d43f1e9d59791b138b9903c58b89fffb0df97 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Apr 2016 02:40:42 +0200 Subject: [PATCH 2616/9938] net: dsa: Keep the mii bus and address in the private structure Rather than looking up the mii bus and address every time, do it once at probe, and keep it in the private structure. Centralise this probe code in mv88e6xxx. Signed-off-by: Andrew Lunn Acked-by: Florian Fainelli Tested-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.c | 44 ++++++++++++++++++++++--------------- drivers/net/dsa/mv88e6060.h | 11 ++++++++++ drivers/net/dsa/mv88e6123.c | 15 +++---------- drivers/net/dsa/mv88e6131.c | 15 +++---------- drivers/net/dsa/mv88e6171.c | 15 +++---------- drivers/net/dsa/mv88e6352.c | 15 +++---------- drivers/net/dsa/mv88e6xxx.c | 43 ++++++++++++++++++++++++------------ drivers/net/dsa/mv88e6xxx.h | 14 +++++++++--- 8 files changed, 89 insertions(+), 83 deletions(-) diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 41195f1417f1..46fe5dc65a99 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -19,12 +19,9 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); + struct mv88e6060_priv *priv = ds_to_priv(ds); - if (bus == NULL) - return -EINVAL; - - return mdiobus_read_nested(bus, ds->pd->sw_addr + addr, reg); + return mdiobus_read_nested(priv->bus, priv->sw_addr + addr, reg); } #define REG_READ(addr, reg) \ @@ -40,12 +37,9 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg) static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); - - if (bus == NULL) - return -EINVAL; + struct mv88e6060_priv *priv = ds_to_priv(ds); - return mdiobus_write_nested(bus, ds->pd->sw_addr + addr, reg, val); + return mdiobus_write_nested(priv->bus, priv->sw_addr + addr, reg, val); } #define REG_WRITE(addr, reg, val) \ @@ -57,16 +51,10 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) return __ret; \ }) -static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv) +static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); int ret; - *priv = NULL; - if (bus == NULL) - return NULL; - ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID); if (ret >= 0) { if (ret == PORT_SWITCH_ID_6060) @@ -81,6 +69,26 @@ static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev, return NULL; } +static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr, void **_priv) +{ + struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); + struct mv88e6060_priv *priv; + char *name; + + name = mv88e6060_get_name(bus, sw_addr); + if (name) { + priv = devm_kzalloc(dsa_dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return NULL; + *_priv = priv; + priv->bus = bus; + priv->sw_addr = sw_addr; + } + + return name; +} + static int mv88e6060_switch_reset(struct dsa_switch *ds) { int i; @@ -176,8 +184,8 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) static int mv88e6060_setup(struct dsa_switch *ds) { - int i; int ret; + int i; ret = mv88e6060_switch_reset(ds); if (ret < 0) diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h index cc9b2ed4aff4..10249bd16292 100644 --- a/drivers/net/dsa/mv88e6060.h +++ b/drivers/net/dsa/mv88e6060.h @@ -108,4 +108,15 @@ #define GLOBAL_ATU_MAC_23 0x0e #define GLOBAL_ATU_MAC_45 0x0f +struct mv88e6060_priv { + /* MDIO bus and address on bus to use. When in single chip + * mode, address is 0, and the switch uses multiple addresses + * on the bus. When in multi-chip mode, the switch uses a + * single address which contains two registers used for + * indirect access to more registers. + */ + struct mii_bus *bus; + int sw_addr; +}; + #endif diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index bcab3ef22448..8aaac0894752 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -32,18 +32,9 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = { static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev, int sw_addr, void **priv) { - struct mv88e6xxx_priv_state *ps; - char *name; - - name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table, - ARRAY_SIZE(mv88e6123_table)); - if (name) { - ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); - if (!ps) - return NULL; - *priv = ps; - } - return name; + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6123_table, + ARRAY_SIZE(mv88e6123_table)); } static int mv88e6123_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index b9f9b009f65a..9e6edf94a855 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -28,18 +28,9 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = { static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev, int sw_addr, void **priv) { - struct mv88e6xxx_priv_state *ps; - char *name; - - name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table, - ARRAY_SIZE(mv88e6131_table)); - if (name) { - ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); - if (!ps) - return NULL; - *priv = ps; - } - return name; + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6131_table, + ARRAY_SIZE(mv88e6131_table)); } static int mv88e6131_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 15200928cecc..6ab86071391f 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -27,18 +27,9 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = { static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev, int sw_addr, void **priv) { - struct mv88e6xxx_priv_state *ps; - char *name; - - name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table, - ARRAY_SIZE(mv88e6171_table)); - if (name) { - ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); - if (!ps) - return NULL; - *priv = ps; - } - return name; + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6171_table, + ARRAY_SIZE(mv88e6171_table)); } static int mv88e6171_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 7081a78a67e1..764b10ffb631 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -40,18 +40,9 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev, int sw_addr, void **priv) { - struct mv88e6xxx_priv_state *ps; - char *name; - - name = mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table, - ARRAY_SIZE(mv88e6352_table)); - if (name) { - ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); - if (!ps) - return NULL; - *priv = ps; - } - return name; + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6352_table, + ARRAY_SIZE(mv88e6352_table)); } static int mv88e6352_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 085fc4a49eb2..c242ffd8eb09 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -94,15 +94,12 @@ static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; assert_smi_lock(ds); - if (bus == NULL) - return -EINVAL; - - ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg); + ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg); if (ret < 0) return ret; @@ -159,17 +156,14 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); assert_smi_lock(ds); - if (bus == NULL) - return -EINVAL; - dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", addr, reg, val); - return __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val); + return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val); } int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) @@ -2671,7 +2665,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); ps->ds = ds; - mutex_init(&ps->smi_mutex); ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; @@ -3075,9 +3068,9 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) } #endif /* CONFIG_NET_DSA_HWMON */ -char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, - const struct mv88e6xxx_switch_id *table, - unsigned int num) +static char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, + const struct mv88e6xxx_switch_id *table, + unsigned int num) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); int i, ret; @@ -3107,6 +3100,28 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, return NULL; } +char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr, void **priv, + const struct mv88e6xxx_switch_id *table, + unsigned int num) +{ + struct mv88e6xxx_priv_state *ps; + char *name; + + name = mv88e6xxx_lookup_name(host_dev, sw_addr, table, num); + if (name) { + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); + if (!ps) + return NULL; + *priv = ps; + ps->bus = dsa_host_dev_to_mii_bus(host_dev); + if (!ps->bus) + return NULL; + ps->sw_addr = sw_addr; + } + return name; +} + static int __init mv88e6xxx_init(void) { #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 0322e3e0e7d9..5d27decc85cb 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -406,6 +406,12 @@ struct mv88e6xxx_priv_state { */ struct mutex smi_mutex; + /* The MII bus and the address on the bus that is used to + * communication with the switch + */ + struct mii_bus *bus; + int sw_addr; + #ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU /* Handles automatic disabling and re-enabling of the PHY * polling unit. @@ -456,9 +462,11 @@ struct mv88e6xxx_hw_stat { }; int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); -char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, - const struct mv88e6xxx_switch_id *table, - unsigned int num); +char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr, void **priv, + const struct mv88e6xxx_switch_id *table, + unsigned int num); + int mv88e6xxx_setup_ports(struct dsa_switch *ds); int mv88e6xxx_setup_common(struct dsa_switch *ds); int mv88e6xxx_setup_global(struct dsa_switch *ds); -- GitLab From e49bad319630dedeeda3a638a707ec7b5d402ad5 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Apr 2016 02:40:43 +0200 Subject: [PATCH 2617/9938] net: dsa: Rename DSA probe function. Rename the function called from the DSA to perform a probe for the switch. This makes the normal _probe() name available for a standard Linux device driver probe function. Signed-off-by: Andrew Lunn Tested-by: Vivien Didelot Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 7 ++++--- drivers/net/dsa/mv88e6060.c | 7 ++++--- drivers/net/dsa/mv88e6123.c | 7 ++++--- drivers/net/dsa/mv88e6131.c | 7 ++++--- drivers/net/dsa/mv88e6171.c | 7 ++++--- drivers/net/dsa/mv88e6352.c | 7 ++++--- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 7d62802a66d5..50caa525cda3 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -135,8 +135,9 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds) return BCM_SF2_STATS_SIZE; } -static char *bcm_sf2_sw_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **_priv) +static char *bcm_sf2_sw_drv_probe(struct device *dsa_dev, + struct device *host_dev, + int sw_addr, void **_priv) { struct bcm_sf2_priv *priv; @@ -1370,7 +1371,7 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port, static struct dsa_switch_driver bcm_sf2_switch_driver = { .tag_protocol = DSA_TAG_PROTO_BRCM, - .probe = bcm_sf2_sw_probe, + .probe = bcm_sf2_sw_drv_probe, .setup = bcm_sf2_sw_setup, .set_addr = bcm_sf2_sw_set_addr, .get_phy_flags = bcm_sf2_sw_get_phy_flags, diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 46fe5dc65a99..adb608ccd9aa 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -69,8 +69,9 @@ static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) return NULL; } -static char *mv88e6060_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **_priv) +static char *mv88e6060_drv_probe(struct device *dsa_dev, + struct device *host_dev, + int sw_addr, void **_priv) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); struct mv88e6060_priv *priv; @@ -248,7 +249,7 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) static struct dsa_switch_driver mv88e6060_switch_driver = { .tag_protocol = DSA_TAG_PROTO_TRAILER, - .probe = mv88e6060_probe, + .probe = mv88e6060_drv_probe, .setup = mv88e6060_setup, .set_addr = mv88e6060_set_addr, .phy_read = mv88e6060_phy_read, diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 8aaac0894752..c34283d929c4 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -29,8 +29,9 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = { { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, }; -static char *mv88e6123_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv) +static char *mv88e6123_drv_probe(struct device *dsa_dev, + struct device *host_dev, + int sw_addr, void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6123_table, @@ -106,7 +107,7 @@ static int mv88e6123_setup(struct dsa_switch *ds) struct dsa_switch_driver mv88e6123_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .probe = mv88e6123_probe, + .probe = mv88e6123_drv_probe, .setup = mv88e6123_setup, .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read, diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 9e6edf94a855..f5d75fce1e96 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -25,8 +25,9 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = { { PORT_SWITCH_ID_6185, "Marvell 88E6185" }, }; -static char *mv88e6131_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv) +static char *mv88e6131_drv_probe(struct device *dsa_dev, + struct device *host_dev, + int sw_addr, void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6131_table, @@ -163,7 +164,7 @@ mv88e6131_phy_write(struct dsa_switch *ds, struct dsa_switch_driver mv88e6131_switch_driver = { .tag_protocol = DSA_TAG_PROTO_DSA, - .probe = mv88e6131_probe, + .probe = mv88e6131_drv_probe, .setup = mv88e6131_setup, .set_addr = mv88e6xxx_set_addr_direct, .phy_read = mv88e6131_phy_read, diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 6ab86071391f..f5622506cdfa 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -24,8 +24,9 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = { { PORT_SWITCH_ID_6351, "Marvell 88E6351" }, }; -static char *mv88e6171_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv) +static char *mv88e6171_drv_probe(struct device *dsa_dev, + struct device *host_dev, + int sw_addr, void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6171_table, @@ -92,7 +93,7 @@ static int mv88e6171_setup(struct dsa_switch *ds) struct dsa_switch_driver mv88e6171_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .probe = mv88e6171_probe, + .probe = mv88e6171_drv_probe, .setup = mv88e6171_setup, .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read_indirect, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 764b10ffb631..e54ee27db129 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -37,8 +37,9 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" }, }; -static char *mv88e6352_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv) +static char *mv88e6352_drv_probe(struct device *dsa_dev, + struct device *host_dev, + int sw_addr, void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6352_table, @@ -306,7 +307,7 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds, struct dsa_switch_driver mv88e6352_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .probe = mv88e6352_probe, + .probe = mv88e6352_drv_probe, .setup = mv88e6352_setup, .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read_indirect, -- GitLab From 74c3e2a54b7d9eb57f23fb0e157b90bb6dae629f Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Apr 2016 02:40:44 +0200 Subject: [PATCH 2618/9938] dsa: Rename phys_port_mask to enabled_port_mask The phys in phys_port_mask suggests this mask is about PHYs. In fact, it means physical ports. Rename to enabled_port_mask, indicating external enabled ports of the switch, which is hopefully less confusing. Signed-off-by: Andrew Lunn Tested-by: Vivien Didelot Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 19 ++++++++++--------- drivers/net/dsa/mv88e6060.c | 2 +- include/net/dsa.h | 4 ++-- net/dsa/dsa.c | 8 ++++---- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 50caa525cda3..7a5f0ef46bd6 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -160,7 +160,7 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port) * the same VLAN. */ for (i = 0; i < priv->hw_params.num_ports; i++) { - if (!((1 << i) & ds->phys_port_mask)) + if (!((1 << i) & ds->enabled_port_mask)) continue; reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i)); @@ -1009,7 +1009,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) /* Enable all valid ports and disable those unused */ for (port = 0; port < priv->hw_params.num_ports; port++) { /* IMP port receives special treatment */ - if ((1 << port) & ds->phys_port_mask) + if ((1 << port) & ds->enabled_port_mask) bcm_sf2_port_setup(ds, port, NULL); else if (dsa_is_cpu_port(ds, port)) bcm_sf2_imp_setup(ds, port); @@ -1022,11 +1022,12 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such * that we can use the regular SWITCH_MDIO master controller instead. * - * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask - * to have a 1:1 mapping between Port address and PHY address in order - * to utilize the slave_mii_bus instance to read from Port PHYs. This is - * not what we want here, so we initialize phys_mii_mask 0 to always - * utilize the "master" MDIO bus backed by the "mdio-unimac" driver. + * By default, DSA initializes ds->phys_mii_mask to + * ds->enabled_port_mask to have a 1:1 mapping between Port address + * and PHY address in order to utilize the slave_mii_bus instance to + * read from Port PHYs. This is not what we want here, so we + * initialize phys_mii_mask 0 to always utilize the "master" MDIO + * bus backed by the "mdio-unimac" driver. */ if (of_machine_is_compatible("brcm,bcm7445d0")) ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); @@ -1284,7 +1285,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) * bcm_sf2_sw_setup */ for (port = 0; port < DSA_MAX_PORTS; port++) { - if ((1 << port) & ds->phys_port_mask || + if ((1 << port) & ds->enabled_port_mask || dsa_is_cpu_port(ds, port)) bcm_sf2_port_disable(ds, port, NULL); } @@ -1308,7 +1309,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) bcm_sf2_gphy_enable_set(ds, true); for (port = 0; port < DSA_MAX_PORTS; port++) { - if ((1 << port) & ds->phys_port_mask) + if ((1 << port) & ds->enabled_port_mask) bcm_sf2_port_setup(ds, port, NULL); else if (dsa_is_cpu_port(ds, port)) bcm_sf2_imp_setup(ds, port); diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index adb608ccd9aa..92cebab9383e 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -170,7 +170,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) REG_WRITE(addr, PORT_VLAN_MAP, ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) | (dsa_is_cpu_port(ds, p) ? - ds->phys_port_mask : + ds->enabled_port_mask : BIT(ds->dst->cpu_port))); /* Port Association Vector: when learning source addresses diff --git a/include/net/dsa.h b/include/net/dsa.h index 165c2e10615c..689ebd3542ba 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -167,7 +167,7 @@ struct dsa_switch { * Slave mii_bus and devices for the individual ports. */ u32 dsa_port_mask; - u32 phys_port_mask; + u32 enabled_port_mask; u32 phys_mii_mask; struct mii_bus *slave_mii_bus; struct net_device *ports[DSA_MAX_PORTS]; @@ -185,7 +185,7 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p) static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p) { - return ds->phys_port_mask & (1 << p) && ds->ports[p]; + return ds->enabled_port_mask & (1 << p) && ds->ports[p]; } static inline u8 dsa_upstream_port(struct dsa_switch *ds) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 14bf12f637d2..60ea98481806 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -246,7 +246,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) } else if (!strcmp(name, "dsa")) { ds->dsa_port_mask |= 1 << i; } else { - ds->phys_port_mask |= 1 << i; + ds->enabled_port_mask |= 1 << i; } valid_name_found = true; } @@ -259,7 +259,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) /* Make the built-in MII bus mask match the number of ports, * switch drivers can override this later */ - ds->phys_mii_mask = ds->phys_port_mask; + ds->phys_mii_mask = ds->enabled_port_mask; /* * If the CPU connects to this switch, set the switch tree @@ -325,7 +325,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) * Create network devices for physical switch ports. */ for (i = 0; i < DSA_MAX_PORTS; i++) { - if (!(ds->phys_port_mask & (1 << i))) + if (!(ds->enabled_port_mask & (1 << i))) continue; ret = dsa_slave_create(ds, parent, i, pd->port_names[i]); @@ -435,7 +435,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds) /* Destroy network devices for physical switch ports. */ for (port = 0; port < DSA_MAX_PORTS; port++) { - if (!(ds->phys_port_mask & (1 << port))) + if (!(ds->enabled_port_mask & (1 << port))) continue; if (!ds->ports[port]) -- GitLab From c156913b5d62cbaa0e3be29409de562b7d2e006e Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 13 Apr 2016 02:40:45 +0200 Subject: [PATCH 2619/9938] dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name() mv88e6xxx_lookup_name() returns the model name of a switch at a given address on an MII bus. Using mii_bus to identify the bus rather than the host device is more logical, so change the parameter. Signed-off-by: Andrew Lunn Tested-by: Vivien Didelot Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index c242ffd8eb09..9985a0cf31f1 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -3068,11 +3068,10 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) } #endif /* CONFIG_NET_DSA_HWMON */ -static char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, +static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr, const struct mv88e6xxx_switch_id *table, unsigned int num) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); int i, ret; if (!bus) @@ -3090,7 +3089,8 @@ static char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, /* Look up only the product number */ for (i = 0; i < num; ++i) { if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) { - dev_warn(host_dev, "unknown revision %d, using base switch 0x%x\n", + dev_warn(&bus->dev, + "unknown revision %d, using base switch 0x%x\n", ret & PORT_SWITCH_ID_REV_MASK, ret & PORT_SWITCH_ID_PROD_NUM_MASK); return table[i].name; @@ -3106,9 +3106,13 @@ char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, unsigned int num) { struct mv88e6xxx_priv_state *ps; + struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); char *name; - name = mv88e6xxx_lookup_name(host_dev, sw_addr, table, num); + if (!bus) + return NULL; + + name = mv88e6xxx_lookup_name(bus, sw_addr, table, num); if (name) { ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); if (!ps) -- GitLab From 04738e7f336376f28adb6c0cad2a5788dcbc8e1d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 24 Mar 2016 05:15:59 -0300 Subject: [PATCH 2620/9938] [media] v4l: vsp1: Add global alpha support for DRM pipeline Make the global alpha multiplier of DRM planes configurable. All the necessary infrastructure is there, we just need to store the alpha value passed through the DRM API. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 5 ++++- include/media/vsp1.h | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index d85cb0e258c9..fc4bbc401e67 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -235,6 +235,7 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); * @mem: DMA addresses of the memory buffers (one per plane) * @src: the source crop rectangle for the RPF * @dst: the destination compose rectangle for the BRU input + * @alpha: global alpha value for the input * @zpos: the Z-order position of the input * * Configure the VSP to perform composition of the image referenced by @mem @@ -263,7 +264,8 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); int vsp1_du_atomic_update_ext(struct device *dev, unsigned int rpf_index, u32 pixelformat, unsigned int pitch, dma_addr_t mem[2], const struct v4l2_rect *src, - const struct v4l2_rect *dst, unsigned int zpos) + const struct v4l2_rect *dst, unsigned int alpha, + unsigned int zpos) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); const struct vsp1_format_info *fmtinfo; @@ -303,6 +305,7 @@ int vsp1_du_atomic_update_ext(struct device *dev, unsigned int rpf_index, rpf->format.num_planes = fmtinfo->planes; rpf->format.plane_fmt[0].bytesperline = pitch; rpf->format.plane_fmt[1].bytesperline = pitch; + rpf->alpha = alpha; rpf->mem.addr[0] = mem[0]; rpf->mem.addr[1] = mem[1]; diff --git a/include/media/vsp1.h b/include/media/vsp1.h index e54a493bd3ff..3e654a0455bd 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -27,7 +27,8 @@ void vsp1_du_atomic_begin(struct device *dev); int vsp1_du_atomic_update_ext(struct device *dev, unsigned int rpf, u32 pixelformat, unsigned int pitch, dma_addr_t mem[2], const struct v4l2_rect *src, - const struct v4l2_rect *dst, unsigned int zpos); + const struct v4l2_rect *dst, unsigned int alpha, + unsigned int zpos); void vsp1_du_atomic_flush(struct device *dev); static inline int vsp1_du_atomic_update(struct device *dev, @@ -37,7 +38,7 @@ static inline int vsp1_du_atomic_update(struct device *dev, const struct v4l2_rect *dst) { return vsp1_du_atomic_update_ext(dev, rpf_index, pixelformat, pitch, - mem, src, dst, 0); + mem, src, dst, 255, 0); } #endif /* __MEDIA_VSP1_H__ */ -- GitLab From 2d2f99451d4b32f69abd6ff59e229974e2fbe386 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 25 Mar 2016 05:50:02 -0300 Subject: [PATCH 2621/9938] [media] v4l: vsp1: Fix V4L2_PIX_FMT_XRGB444 format definition The format is erroneously defined with an alpha channel. Fix it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 15e028321fa1..4f3b4a1d028a 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -43,7 +43,7 @@ static const struct vsp1_format_info vsp1_video_formats[] = { { V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32, VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS, - 1, { 16, 0, 0 }, false, false, 1, 1, true }, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32, VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS, -- GitLab From 56a0eccdc0dec223d4625c80de31514f04390159 Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Mon, 11 Apr 2016 20:54:46 +0900 Subject: [PATCH 2622/9938] arm64: dts: Add dts files for LG Electronics's lg1312 SoC Add initial dtsi file to support lg1312 SoC which based on Cortex-A53. Also add dts file to support lg1312 reference board which based on lg1312 SoC. Signed-off-by: Chanho Min Signed-off-by: Olof Johansson --- arch/arm64/boot/dts/Makefile | 1 + arch/arm64/boot/dts/lg/Makefile | 5 + arch/arm64/boot/dts/lg/lg1312-ref.dts | 36 +++ arch/arm64/boot/dts/lg/lg1312.dtsi | 351 ++++++++++++++++++++++++++ 4 files changed, 393 insertions(+) create mode 100644 arch/arm64/boot/dts/lg/Makefile create mode 100644 arch/arm64/boot/dts/lg/lg1312-ref.dts create mode 100644 arch/arm64/boot/dts/lg/lg1312.dtsi diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 330fae966cf3..6e199c903676 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -18,6 +18,7 @@ dts-dirs += rockchip dts-dirs += socionext dts-dirs += sprd dts-dirs += xilinx +dts-dirs += lg subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/lg/Makefile b/arch/arm64/boot/dts/lg/Makefile new file mode 100644 index 000000000000..b0cc64964171 --- /dev/null +++ b/arch/arm64/boot/dts/lg/Makefile @@ -0,0 +1,5 @@ +dtb-$(CONFIG_ARCH_LG1K) += lg1312-ref.dtb + +always := $(dtb-y) +subdir-y := $(dts-dirs) +clean-files := *.dtb diff --git a/arch/arm64/boot/dts/lg/lg1312-ref.dts b/arch/arm64/boot/dts/lg/lg1312-ref.dts new file mode 100644 index 000000000000..6d78d6bc7f9c --- /dev/null +++ b/arch/arm64/boot/dts/lg/lg1312-ref.dts @@ -0,0 +1,36 @@ +/* + * dts file for lg1312 Reference Board. + * + * Copyright (C) 2016, LG Electronics + */ + +/dts-v1/; + +#include "lg1312.dtsi" + +/ { + #address-cells = <2>; + #size-cells = <1>; + + model = "LG Electronics, DTV SoC LG1312 Reference Board"; + compatible = "lge,lg1312-ref", "lge,lg1312"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x00000000 0x20000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/lg/lg1312.dtsi b/arch/arm64/boot/dts/lg/lg1312.dtsi new file mode 100644 index 000000000000..3a4e9a2ab313 --- /dev/null +++ b/arch/arm64/boot/dts/lg/lg1312.dtsi @@ -0,0 +1,351 @@ +/* + * dts file for lg1312 SoC + * + * Copyright (C) 2016, LG Electronics + */ + +#include +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + + compatible = "lge,lg1312"; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x0>; + next-level-cache = <&L2_0>; + }; + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + psci { + compatible = "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + }; + + gic: interrupt-controller@c0001000 { + #interrupt-cells = <3>; + compatible = "arm,gic-400"; + interrupt-controller; + reg = <0x0 0xc0001000 0x1000>, + <0x0 0xc0002000 0x2000>, + <0x0 0xc0004000 0x2000>, + <0x0 0xc0006000 0x2000>; + }; + + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = , + , + , + ; + interrupt-affinity = <&cpu0>, + <&cpu1>, + <&cpu2>, + <&cpu3>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + clk_bus: clk_bus { + #clock-cells = <0>; + + compatible = "fixed-clock"; + clock-frequency = <198000000>; + clock-output-names = "BUSCLK"; + }; + + soc { + #address-cells = <2>; + #size-cells = <1>; + + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + eth0: ethernet@c1b00000 { + compatible = "cdns,gem"; + reg = <0x0 0xc1b00000 0x1000>; + interrupts = ; + clocks = <&clk_bus>, <&clk_bus>; + clock-names = "hclk", "pclk"; + phy-mode = "rmii"; + /* Filled in by boot */ + mac-address = [ 00 00 00 00 00 00 ]; + }; + }; + + amba { + #address-cells = <2>; + #size-cells = <1>; + #interrupts-cells = <3>; + + compatible = "arm,amba-bus"; + interrupt-parent = <&gic>; + ranges; + + timers: timer@fd100000 { + compatible = "arm,sp804"; + reg = <0x0 0xfd100000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + wdog: watchdog@fd200000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xfd200000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + uart0: serial@fe000000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0xfe000000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + uart1: serial@fe100000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0xfe100000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + uart2: serial@fe200000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0xfe200000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + spi0: ssp@fe800000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x0 0xfe800000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + spi1: ssp@fe900000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x0 0xfe900000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + dmac0: dma@c1128000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xc1128000 0x1000>; + interrupts = ; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + gpio0: gpio@fd400000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd400000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio1: gpio@fd410000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd410000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio2: gpio@fd420000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd420000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio3: gpio@fd430000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd430000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + gpio4: gpio@fd440000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd440000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio5: gpio@fd450000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd450000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio6: gpio@fd460000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd460000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio7: gpio@fd470000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd470000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio8: gpio@fd480000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd480000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio9: gpio@fd490000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd490000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio10: gpio@fd4a0000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd4a0000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio11: gpio@fd4b0000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd4b0000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + gpio12: gpio@fd4c0000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd4c0000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio13: gpio@fd4d0000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd4d0000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio14: gpio@fd4e0000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd4e0000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio15: gpio@fd4f0000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd4f0000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio16: gpio@fd500000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd500000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + status="disabled"; + }; + gpio17: gpio@fd510000 { + #gpio-cells = <2>; + compatible = "arm,pl061", "arm,primecell"; + gpio-controller; + reg = <0x0 0xfd510000 0x1000>; + clocks = <&clk_bus>; + clock-names = "apb_pclk"; + }; + }; +}; -- GitLab From 0d268dcc693a56efb009316d83e0d732cafb9f9c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 25 Mar 2016 06:51:06 -0300 Subject: [PATCH 2623/9938] [media] v4l: vsp1: Update WPF and LIF maximum sizes for Gen3 The maximum image size supported by the WPF is 2048x2048 on Gen2 and 8190x8190 on Gen3. Update the code accordingly, and fix the maximum LIF size for both Gen2 and Gen3. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_lif.c | 2 +- drivers/media/platform/vsp1/vsp1_wpf.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 579e142b4e94..0217393f22df 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -21,7 +21,7 @@ #include "vsp1_lif.h" #define LIF_MIN_SIZE 2U -#define LIF_MAX_SIZE 2048U +#define LIF_MAX_SIZE 8190U /* ----------------------------------------------------------------------------- * Device Access diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index ce1d0b4094db..6c91eaa35e75 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -21,8 +21,10 @@ #include "vsp1_rwpf.h" #include "vsp1_video.h" -#define WPF_MAX_WIDTH 2048 -#define WPF_MAX_HEIGHT 2048 +#define WPF_GEN2_MAX_WIDTH 2048U +#define WPF_GEN2_MAX_HEIGHT 2048U +#define WPF_GEN3_MAX_WIDTH 8190U +#define WPF_GEN3_MAX_HEIGHT 8190U /* ----------------------------------------------------------------------------- * Device Access @@ -201,8 +203,13 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) if (wpf == NULL) return ERR_PTR(-ENOMEM); - wpf->max_width = WPF_MAX_WIDTH; - wpf->max_height = WPF_MAX_HEIGHT; + if (vsp1->info->gen == 2) { + wpf->max_width = WPF_GEN2_MAX_WIDTH; + wpf->max_height = WPF_GEN2_MAX_HEIGHT; + } else { + wpf->max_width = WPF_GEN3_MAX_WIDTH; + wpf->max_height = WPF_GEN3_MAX_HEIGHT; + } wpf->entity.ops = &wpf_entity_ops; wpf->entity.type = VSP1_ENTITY_WPF; -- GitLab From 71c5daba0546c456c5589bcf52eb2641abf42a85 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 24 Mar 2016 22:46:45 -0300 Subject: [PATCH 2624/9938] [media] media: platform: rcar_jpu, vsp1: Use ARCH_RENESAS Make use of ARCH_RENESAS in place of ARCH_SHMOBILE. This is part of an ongoing process to migrate from ARCH_SHMOBILE to ARCH_RENESAS the motivation for which being that RENESAS seems to be a more appropriate name than SHMOBILE for the majority of Renesas ARM based SoCs. Acked-by: Geert Uytterhoeven Acked-by: Hans Verkuil Signed-off-by: Simon Horman Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 201f5c296a95..84e041c0a70e 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -238,7 +238,7 @@ config VIDEO_SH_VEU config VIDEO_RENESAS_JPU tristate "Renesas JPEG Processing Unit" depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV ---help--- @@ -250,7 +250,7 @@ config VIDEO_RENESAS_JPU config VIDEO_RENESAS_VSP1 tristate "Renesas VSP1 Video Processing Engine" depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA - depends on (ARCH_SHMOBILE && OF) || COMPILE_TEST + depends on (ARCH_RENESAS && OF) || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG ---help--- This is a V4L2 driver for the Renesas VSP1 video processing engine. -- GitLab From 8cb555b603f386cdde77d0377318eb7051918045 Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Mon, 11 Apr 2016 20:54:47 +0900 Subject: [PATCH 2625/9938] MAINTAINERS: add Chanho Min as ARM/LG1K maintainer Signed-off-by: Chanho Min Signed-off-by: Olof Johansson --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 61a323a6b2cf..cb3582f460e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1288,6 +1288,12 @@ L: linux-kernel@vger.kernel.org S: Maintained F: drivers/memory/*emif* +ARM/LG1K ARCHITECTURE +M: Chanho Min +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm64/boot/dts/lg/ + ARM/LOGICPD PXA270 MACHINE SUPPORT M: Lennert Buytenhek L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -- GitLab From ecb7b0183a89613c154d1bea48b494907efbf8f9 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 16 Mar 2016 09:14:13 -0300 Subject: [PATCH 2626/9938] [media] m88ds3103: fix undefined division s32tmp in the below code may be negative, and dev->mclk_khz is an unsigned type. s32tmp = 0x10000 * (tuner_frequency - c->frequency); s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk_khz); This is undefined, as DIV_ROUND_CLOSEST is undefined for negative dividends when the divisor is of unsigned type. So, change mclk_khz to be signed (s32). Signed-off-by: Peter Rosin Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/m88ds3103_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h index eee8c22c51ec..651e005146b2 100644 --- a/drivers/media/dvb-frontends/m88ds3103_priv.h +++ b/drivers/media/dvb-frontends/m88ds3103_priv.h @@ -46,7 +46,7 @@ struct m88ds3103_dev { /* auto detect chip id to do different config */ u8 chip_id; /* main mclk is calculated for M88RS6000 dynamically */ - u32 mclk_khz; + s32 mclk_khz; u64 post_bit_error; u64 post_bit_count; }; -- GitLab From 0d14513bc241e70b4e0fa1b1eb3cf634c4017998 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 12 Apr 2016 03:18:39 +0200 Subject: [PATCH 2627/9938] ARM: multi_v7_defconfig: Enable Rockchip displayport phy The displayport phy controls the output of the Analogix displayport controller on Rockchip SoCs and is therefore one component to enable veyron devices to use their internal display. Signed-off-by: Heiko Stuebner Signed-off-by: Olof Johansson --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 434f86b110bb..0192d0ad694c 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -792,6 +792,7 @@ CONFIG_OMAP_USB2=y CONFIG_TI_PIPE3=y CONFIG_PHY_BERLIN_USB=y CONFIG_PHY_BERLIN_SATA=y +CONFIG_PHY_ROCKCHIP_DP=m CONFIG_PHY_ROCKCHIP_USB=m CONFIG_PHY_QCOM_APQ8064_SATA=m CONFIG_PHY_MIPHY28LP=y -- GitLab From b6ac00bb9fa4f979f40030e8218a3dd03f9260b7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 12 Apr 2016 03:20:04 +0200 Subject: [PATCH 2628/9938] ARM: multi_v7_defconfig: Enable new Rockchip display-controller drivers Three types of display controller-drivers where added recently. The Analogix Displayport variant and Designware MIPI DSI used for example on the rk3288 as well as the Innosilicon HDMI controller used on the rk3036. Signed-off-by: Heiko Stuebner Signed-off-by: Olof Johansson --- arch/arm/configs/multi_v7_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 0192d0ad694c..0c43f421e36d 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -534,7 +534,10 @@ CONFIG_DRM_EXYNOS_DSI=y CONFIG_DRM_EXYNOS_FIMD=y CONFIG_DRM_EXYNOS_HDMI=y CONFIG_DRM_ROCKCHIP=m +CONFIG_ROCKCHIP_ANALOGIX_DP=m CONFIG_ROCKCHIP_DW_HDMI=m +CONFIG_ROCKCHIP_DW_MIPI_DSI=m +CONFIG_ROCKCHIP_INNO_HDMI=m CONFIG_DRM_RCAR_DU=m CONFIG_DRM_RCAR_HDMI=y CONFIG_DRM_RCAR_LVDS=y -- GitLab From f24e230d257af1ad7476c6e81a8dc3127a74204e Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:21 +0200 Subject: [PATCH 2629/9938] netfilter: x_tables: don't move to non-existent next rule Ben Hawkes says: In the mark_source_chains function (net/ipv4/netfilter/ip_tables.c) it is possible for a user-supplied ipt_entry structure to have a large next_offset field. This field is not bounds checked prior to writing a counter value at the supplied offset. Base chains enforce absolute verdict. User defined chains are supposed to end with an unconditional return, xtables userspace adds them automatically. But if such return is missing we will move to non-existent next rule. Reported-by: Ben Hawkes Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 8 +++++--- net/ipv4/netfilter/ip_tables.c | 4 ++++ net/ipv6/netfilter/ip6_tables.c | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4133b0f513af..82a434bf8653 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -439,6 +439,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo, size = e->next_offset; e = (struct arpt_entry *) (entry0 + pos + size); + if (pos + size >= newinfo->size) + return 0; e->counters.pcnt = pos; pos += size; } else { @@ -461,6 +463,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo, } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; + if (newpos >= newinfo->size) + return 0; } e = (struct arpt_entry *) (entry0 + newpos); @@ -691,10 +695,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, } } - if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) { - duprintf("Looping hook\n"); + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) return -ELOOP; - } /* Finally, each sanity check must pass */ i = 0; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 631c100a1338..e301a3db4717 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -520,6 +520,8 @@ mark_source_chains(const struct xt_table_info *newinfo, size = e->next_offset; e = (struct ipt_entry *) (entry0 + pos + size); + if (pos + size >= newinfo->size) + return 0; e->counters.pcnt = pos; pos += size; } else { @@ -541,6 +543,8 @@ mark_source_chains(const struct xt_table_info *newinfo, } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; + if (newpos >= newinfo->size) + return 0; } e = (struct ipt_entry *) (entry0 + newpos); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 86b67b70b626..7b3335bce3fd 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -532,6 +532,8 @@ mark_source_chains(const struct xt_table_info *newinfo, size = e->next_offset; e = (struct ip6t_entry *) (entry0 + pos + size); + if (pos + size >= newinfo->size) + return 0; e->counters.pcnt = pos; pos += size; } else { @@ -553,6 +555,8 @@ mark_source_chains(const struct xt_table_info *newinfo, } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; + if (newpos >= newinfo->size) + return 0; } e = (struct ip6t_entry *) (entry0 + newpos); -- GitLab From 36472341017529e2b12573093cc0f68719300997 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:22 +0200 Subject: [PATCH 2630/9938] netfilter: x_tables: validate targets of jumps When we see a jump also check that the offset gets us to beginning of a rule (an ipt_entry). The extra overhead is negible, even with absurd cases. 300k custom rules, 300k jumps to 'next' user chain: [ plus one jump from INPUT to first userchain ]: Before: real 0m24.874s user 0m7.532s sys 0m16.076s After: real 0m27.464s user 0m7.436s sys 0m18.840s Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 16 ++++++++++++++++ net/ipv4/netfilter/ip_tables.c | 16 ++++++++++++++++ net/ipv6/netfilter/ip6_tables.c | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 82a434bf8653..ec37f7c3a033 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -367,6 +367,18 @@ static inline bool unconditional(const struct arpt_entry *e) memcmp(&e->arp, &uncond, sizeof(uncond)) == 0; } +static bool find_jump_target(const struct xt_table_info *t, + const struct arpt_entry *target) +{ + struct arpt_entry *iter; + + xt_entry_foreach(iter, t->entries, t->size) { + if (iter == target) + return true; + } + return false; +} + /* Figures out from what hook each rule can be called: returns 0 if * there are loops. Puts hook bitmask in comefrom. */ @@ -460,6 +472,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); + e = (struct arpt_entry *) + (entry0 + newpos); + if (!find_jump_target(newinfo, e)) + return 0; } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index e301a3db4717..503038ea7735 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -443,6 +443,18 @@ ipt_do_table(struct sk_buff *skb, #endif } +static bool find_jump_target(const struct xt_table_info *t, + const struct ipt_entry *target) +{ + struct ipt_entry *iter; + + xt_entry_foreach(iter, t->entries, t->size) { + if (iter == target) + return true; + } + return false; +} + /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int @@ -540,6 +552,10 @@ mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); + e = (struct ipt_entry *) + (entry0 + newpos); + if (!find_jump_target(newinfo, e)) + return 0; } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 7b3335bce3fd..126f2a0f006a 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -455,6 +455,18 @@ ip6t_do_table(struct sk_buff *skb, #endif } +static bool find_jump_target(const struct xt_table_info *t, + const struct ip6t_entry *target) +{ + struct ip6t_entry *iter; + + xt_entry_foreach(iter, t->entries, t->size) { + if (iter == target) + return true; + } + return false; +} + /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int @@ -552,6 +564,10 @@ mark_source_chains(const struct xt_table_info *newinfo, /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); + e = (struct ip6t_entry *) + (entry0 + newpos); + if (!find_jump_target(newinfo, e)) + return 0; } else { /* ... this is a fallthru */ newpos = pos + e->next_offset; -- GitLab From 7d35812c3214afa5b37a675113555259cfd67b98 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:23 +0200 Subject: [PATCH 2631/9938] netfilter: x_tables: add and use xt_check_entry_offsets Currently arp/ip and ip6tables each implement a short helper to check that the target offset is large enough to hold one xt_entry_target struct and that t->u.target_size fits within the current rule. Unfortunately these checks are not sufficient. To avoid adding new tests to all of ip/ip6/arptables move the current checks into a helper, then extend this helper in followup patches. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/x_tables.h | 4 ++++ net/ipv4/netfilter/arp_tables.c | 11 +--------- net/ipv4/netfilter/ip_tables.c | 12 +---------- net/ipv6/netfilter/ip6_tables.c | 12 +---------- net/netfilter/x_tables.c | 34 ++++++++++++++++++++++++++++++ 5 files changed, 41 insertions(+), 32 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 80a305b85323..0de0862897a4 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -242,6 +242,10 @@ void xt_unregister_match(struct xt_match *target); int xt_register_matches(struct xt_match *match, unsigned int n); void xt_unregister_matches(struct xt_match *match, unsigned int n); +int xt_check_entry_offsets(const void *base, + unsigned int target_offset, + unsigned int next_offset); + int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto, bool inv_proto); int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto, diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index ec37f7c3a033..74668c1d3243 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -496,19 +496,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo, static inline int check_entry(const struct arpt_entry *e) { - const struct xt_entry_target *t; - if (!arp_checkentry(&e->arp)) return -EINVAL; - if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset) - return -EINVAL; - - t = arpt_get_target_c(e); - if (e->target_offset + t->u.target_size > e->next_offset) - return -EINVAL; - - return 0; + return xt_check_entry_offsets(e, e->target_offset, e->next_offset); } static inline int check_target(struct arpt_entry *e, const char *name) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 503038ea7735..71c204d4ca5f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -590,20 +590,10 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) static int check_entry(const struct ipt_entry *e) { - const struct xt_entry_target *t; - if (!ip_checkentry(&e->ip)) return -EINVAL; - if (e->target_offset + sizeof(struct xt_entry_target) > - e->next_offset) - return -EINVAL; - - t = ipt_get_target_c(e); - if (e->target_offset + t->u.target_size > e->next_offset) - return -EINVAL; - - return 0; + return xt_check_entry_offsets(e, e->target_offset, e->next_offset); } static int diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 126f2a0f006a..24ae7f458b3b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -602,20 +602,10 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) static int check_entry(const struct ip6t_entry *e) { - const struct xt_entry_target *t; - if (!ip6_checkentry(&e->ipv6)) return -EINVAL; - if (e->target_offset + sizeof(struct xt_entry_target) > - e->next_offset) - return -EINVAL; - - t = ip6t_get_target_c(e); - if (e->target_offset + t->u.target_size > e->next_offset) - return -EINVAL; - - return 0; + return xt_check_entry_offsets(e, e->target_offset, e->next_offset); } static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 582c9cfd6567..1f44bfa8dd94 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -541,6 +541,40 @@ int xt_compat_match_to_user(const struct xt_entry_match *m, EXPORT_SYMBOL_GPL(xt_compat_match_to_user); #endif /* CONFIG_COMPAT */ +/** + * xt_check_entry_offsets - validate arp/ip/ip6t_entry + * + * @base: pointer to arp/ip/ip6t_entry + * @target_offset: the arp/ip/ip6_t->target_offset + * @next_offset: the arp/ip/ip6_t->next_offset + * + * validates that target_offset and next_offset are sane. + * + * The arp/ip/ip6t_entry structure @base must have passed following tests: + * - it must point to a valid memory location + * - base to base + next_offset must be accessible, i.e. not exceed allocated + * length. + * + * Return: 0 on success, negative errno on failure. + */ +int xt_check_entry_offsets(const void *base, + unsigned int target_offset, + unsigned int next_offset) +{ + const struct xt_entry_target *t; + const char *e = base; + + if (target_offset + sizeof(*t) > next_offset) + return -EINVAL; + + t = (void *)(e + target_offset); + if (target_offset + t->u.target_size > next_offset) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(xt_check_entry_offsets); + int xt_check_target(struct xt_tgchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { -- GitLab From aa412ba225dd3bc36d404c28cdc3d674850d80d0 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:24 +0200 Subject: [PATCH 2632/9938] netfilter: x_tables: kill check_entry helper Once we add more sanity testing to xt_check_entry_offsets it becomes relvant if we're expecting a 32bit 'config_compat' blob or a normal one. Since we already have a lot of similar-named functions (check_entry, compat_check_entry, find_and_check_entry, etc.) and the current incarnation is short just fold its contents into the callers. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 19 ++++++++----------- net/ipv4/netfilter/ip_tables.c | 20 ++++++++------------ net/ipv6/netfilter/ip6_tables.c | 20 ++++++++------------ 3 files changed, 24 insertions(+), 35 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 74668c1d3243..24ad92a60b7a 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -494,14 +494,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo, return 1; } -static inline int check_entry(const struct arpt_entry *e) -{ - if (!arp_checkentry(&e->arp)) - return -EINVAL; - - return xt_check_entry_offsets(e, e->target_offset, e->next_offset); -} - static inline int check_target(struct arpt_entry *e, const char *name) { struct xt_entry_target *t = arpt_get_target(e); @@ -597,7 +589,10 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, return -EINVAL; } - err = check_entry(e); + if (!arp_checkentry(&e->arp)) + return -EINVAL; + + err = xt_check_entry_offsets(e, e->target_offset, e->next_offset); if (err) return err; @@ -1256,8 +1251,10 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, return -EINVAL; } - /* For purposes of check_entry casting the compat entry is fine */ - ret = check_entry((struct arpt_entry *)e); + if (!arp_checkentry(&e->arp)) + return -EINVAL; + + ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset); if (ret) return ret; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 71c204d4ca5f..cdf18502a047 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -587,15 +587,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) module_put(par.match->me); } -static int -check_entry(const struct ipt_entry *e) -{ - if (!ip_checkentry(&e->ip)) - return -EINVAL; - - return xt_check_entry_offsets(e, e->target_offset, e->next_offset); -} - static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) { @@ -760,7 +751,10 @@ check_entry_size_and_hooks(struct ipt_entry *e, return -EINVAL; } - err = check_entry(e); + if (!ip_checkentry(&e->ip)) + return -EINVAL; + + err = xt_check_entry_offsets(e, e->target_offset, e->next_offset); if (err) return err; @@ -1516,8 +1510,10 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, return -EINVAL; } - /* For purposes of check_entry casting the compat entry is fine */ - ret = check_entry((struct ipt_entry *)e); + if (!ip_checkentry(&e->ip)) + return -EINVAL; + + ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset); if (ret) return ret; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 24ae7f458b3b..e3783116ed48 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -599,15 +599,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) module_put(par.match->me); } -static int -check_entry(const struct ip6t_entry *e) -{ - if (!ip6_checkentry(&e->ipv6)) - return -EINVAL; - - return xt_check_entry_offsets(e, e->target_offset, e->next_offset); -} - static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) { const struct ip6t_ip6 *ipv6 = par->entryinfo; @@ -772,7 +763,10 @@ check_entry_size_and_hooks(struct ip6t_entry *e, return -EINVAL; } - err = check_entry(e); + if (!ip6_checkentry(&e->ipv6)) + return -EINVAL; + + err = xt_check_entry_offsets(e, e->target_offset, e->next_offset); if (err) return err; @@ -1528,8 +1522,10 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, return -EINVAL; } - /* For purposes of check_entry casting the compat entry is fine */ - ret = check_entry((struct ip6t_entry *)e); + if (!ip6_checkentry(&e->ipv6)) + return -EINVAL; + + ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset); if (ret) return ret; -- GitLab From a08e4e190b866579896c09af59b3bdca821da2cd Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:25 +0200 Subject: [PATCH 2633/9938] netfilter: x_tables: assert minimum target size The target size includes the size of the xt_entry_target struct. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/x_tables.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 1f44bfa8dd94..ec1b7183fff9 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -568,6 +568,9 @@ int xt_check_entry_offsets(const void *base, return -EINVAL; t = (void *)(e + target_offset); + if (t->u.target_size < sizeof(*t)) + return -EINVAL; + if (target_offset + t->u.target_size > next_offset) return -EINVAL; -- GitLab From fc1221b3a163d1386d1052184202d5dc50d302d1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:26 +0200 Subject: [PATCH 2634/9938] netfilter: x_tables: add compat version of xt_check_entry_offsets 32bit rulesets have different layout and alignment requirements, so once more integrity checks get added to xt_check_entry_offsets it will reject well-formed 32bit rulesets. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/x_tables.h | 3 +++ net/ipv4/netfilter/arp_tables.c | 3 ++- net/ipv4/netfilter/ip_tables.c | 3 ++- net/ipv6/netfilter/ip6_tables.c | 3 ++- net/netfilter/x_tables.c | 22 ++++++++++++++++++++++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 0de0862897a4..08de48bbe92e 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -494,6 +494,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, unsigned int *size); int xt_compat_target_to_user(const struct xt_entry_target *t, void __user **dstptr, unsigned int *size); +int xt_compat_check_entry_offsets(const void *base, + unsigned int target_offset, + unsigned int next_offset); #endif /* CONFIG_COMPAT */ #endif /* _X_TABLES_H */ diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 24ad92a60b7a..ab8952a49bfa 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1254,7 +1254,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, if (!arp_checkentry(&e->arp)) return -EINVAL; - ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset); + ret = xt_compat_check_entry_offsets(e, e->target_offset, + e->next_offset); if (ret) return ret; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index cdf18502a047..7d24c872723f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1513,7 +1513,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, if (!ip_checkentry(&e->ip)) return -EINVAL; - ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset); + ret = xt_compat_check_entry_offsets(e, + e->target_offset, e->next_offset); if (ret) return ret; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index e3783116ed48..73eee7b5fd60 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1525,7 +1525,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, if (!ip6_checkentry(&e->ipv6)) return -EINVAL; - ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset); + ret = xt_compat_check_entry_offsets(e, + e->target_offset, e->next_offset); if (ret) return ret; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index ec1b7183fff9..fa206ceb269f 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -539,6 +539,27 @@ int xt_compat_match_to_user(const struct xt_entry_match *m, return 0; } EXPORT_SYMBOL_GPL(xt_compat_match_to_user); + +int xt_compat_check_entry_offsets(const void *base, + unsigned int target_offset, + unsigned int next_offset) +{ + const struct compat_xt_entry_target *t; + const char *e = base; + + if (target_offset + sizeof(*t) > next_offset) + return -EINVAL; + + t = (void *)(e + target_offset); + if (t->u.target_size < sizeof(*t)) + return -EINVAL; + + if (target_offset + t->u.target_size > next_offset) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(xt_compat_check_entry_offsets); #endif /* CONFIG_COMPAT */ /** @@ -549,6 +570,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user); * @next_offset: the arp/ip/ip6_t->next_offset * * validates that target_offset and next_offset are sane. + * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. * * The arp/ip/ip6t_entry structure @base must have passed following tests: * - it must point to a valid memory location -- GitLab From 7ed2abddd20cf8f6bd27f65bd218f26fa5bf7f44 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:27 +0200 Subject: [PATCH 2635/9938] netfilter: x_tables: check standard target size too We have targets and standard targets -- the latter carries a verdict. The ip/ip6tables validation functions will access t->verdict for the standard targets to fetch the jump offset or verdict for chainloop detection, but this happens before the targets get checked/validated. Thus we also need to check for verdict presence here, else t->verdict can point right after a blob. Spotted with UBSAN while testing malformed blobs. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/x_tables.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index fa206ceb269f..1cb7a271c024 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -540,6 +540,13 @@ int xt_compat_match_to_user(const struct xt_entry_match *m, } EXPORT_SYMBOL_GPL(xt_compat_match_to_user); +/* non-compat version may have padding after verdict */ +struct compat_xt_standard_target { + struct compat_xt_entry_target t; + compat_uint_t verdict; +}; + +/* see xt_check_entry_offsets */ int xt_compat_check_entry_offsets(const void *base, unsigned int target_offset, unsigned int next_offset) @@ -557,6 +564,10 @@ int xt_compat_check_entry_offsets(const void *base, if (target_offset + t->u.target_size > next_offset) return -EINVAL; + if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && + target_offset + sizeof(struct compat_xt_standard_target) != next_offset) + return -EINVAL; + return 0; } EXPORT_SYMBOL(xt_compat_check_entry_offsets); @@ -596,6 +607,10 @@ int xt_check_entry_offsets(const void *base, if (target_offset + t->u.target_size > next_offset) return -EINVAL; + if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && + target_offset + sizeof(struct xt_standard_target) != next_offset) + return -EINVAL; + return 0; } EXPORT_SYMBOL(xt_check_entry_offsets); -- GitLab From ce683e5f9d045e5d67d1312a42b359cb2ab2a13c Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:28 +0200 Subject: [PATCH 2636/9938] netfilter: x_tables: check for bogus target offset We're currently asserting that targetoff + targetsize <= nextoff. Extend it to also check that targetoff is >= sizeof(xt_entry). Since this is generic code, add an argument pointing to the start of the match/target, we can then derive the base structure size from the delta. We also need the e->elems pointer in a followup change to validate matches. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/x_tables.h | 4 ++-- net/ipv4/netfilter/arp_tables.c | 5 +++-- net/ipv4/netfilter/ip_tables.c | 5 +++-- net/ipv6/netfilter/ip6_tables.c | 5 +++-- net/netfilter/x_tables.c | 17 +++++++++++++++-- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 08de48bbe92e..30cfb1e943fb 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -242,7 +242,7 @@ void xt_unregister_match(struct xt_match *target); int xt_register_matches(struct xt_match *match, unsigned int n); void xt_unregister_matches(struct xt_match *match, unsigned int n); -int xt_check_entry_offsets(const void *base, +int xt_check_entry_offsets(const void *base, const char *elems, unsigned int target_offset, unsigned int next_offset); @@ -494,7 +494,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, unsigned int *size); int xt_compat_target_to_user(const struct xt_entry_target *t, void __user **dstptr, unsigned int *size); -int xt_compat_check_entry_offsets(const void *base, +int xt_compat_check_entry_offsets(const void *base, const char *elems, unsigned int target_offset, unsigned int next_offset); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index ab8952a49bfa..95ed4e454c60 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -592,7 +592,8 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, if (!arp_checkentry(&e->arp)) return -EINVAL; - err = xt_check_entry_offsets(e, e->target_offset, e->next_offset); + err = xt_check_entry_offsets(e, e->elems, e->target_offset, + e->next_offset); if (err) return err; @@ -1254,7 +1255,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, if (!arp_checkentry(&e->arp)) return -EINVAL; - ret = xt_compat_check_entry_offsets(e, e->target_offset, + ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset, e->next_offset); if (ret) return ret; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 7d24c872723f..baab033d74e0 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -754,7 +754,8 @@ check_entry_size_and_hooks(struct ipt_entry *e, if (!ip_checkentry(&e->ip)) return -EINVAL; - err = xt_check_entry_offsets(e, e->target_offset, e->next_offset); + err = xt_check_entry_offsets(e, e->elems, e->target_offset, + e->next_offset); if (err) return err; @@ -1513,7 +1514,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, if (!ip_checkentry(&e->ip)) return -EINVAL; - ret = xt_compat_check_entry_offsets(e, + ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset, e->next_offset); if (ret) return ret; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 73eee7b5fd60..6957627c7931 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -766,7 +766,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e, if (!ip6_checkentry(&e->ipv6)) return -EINVAL; - err = xt_check_entry_offsets(e, e->target_offset, e->next_offset); + err = xt_check_entry_offsets(e, e->elems, e->target_offset, + e->next_offset); if (err) return err; @@ -1525,7 +1526,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, if (!ip6_checkentry(&e->ipv6)) return -EINVAL; - ret = xt_compat_check_entry_offsets(e, + ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset, e->next_offset); if (ret) return ret; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 1cb7a271c024..e2a6f2a9051b 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -546,14 +546,17 @@ struct compat_xt_standard_target { compat_uint_t verdict; }; -/* see xt_check_entry_offsets */ -int xt_compat_check_entry_offsets(const void *base, +int xt_compat_check_entry_offsets(const void *base, const char *elems, unsigned int target_offset, unsigned int next_offset) { + long size_of_base_struct = elems - (const char *)base; const struct compat_xt_entry_target *t; const char *e = base; + if (target_offset < size_of_base_struct) + return -EINVAL; + if (target_offset + sizeof(*t) > next_offset) return -EINVAL; @@ -577,12 +580,16 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets); * xt_check_entry_offsets - validate arp/ip/ip6t_entry * * @base: pointer to arp/ip/ip6t_entry + * @elems: pointer to first xt_entry_match, i.e. ip(6)t_entry->elems * @target_offset: the arp/ip/ip6_t->target_offset * @next_offset: the arp/ip/ip6_t->next_offset * * validates that target_offset and next_offset are sane. * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. * + * This function does not validate the targets or matches themselves, it + * only tests that all the offsets and sizes are correct. + * * The arp/ip/ip6t_entry structure @base must have passed following tests: * - it must point to a valid memory location * - base to base + next_offset must be accessible, i.e. not exceed allocated @@ -591,12 +598,18 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets); * Return: 0 on success, negative errno on failure. */ int xt_check_entry_offsets(const void *base, + const char *elems, unsigned int target_offset, unsigned int next_offset) { + long size_of_base_struct = elems - (const char *)base; const struct xt_entry_target *t; const char *e = base; + /* target start is within the ip/ip6/arpt_entry struct */ + if (target_offset < size_of_base_struct) + return -EINVAL; + if (target_offset + sizeof(*t) > next_offset) return -EINVAL; -- GitLab From 13631bfc604161a9d69cd68991dff8603edd66f9 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:29 +0200 Subject: [PATCH 2637/9938] netfilter: x_tables: validate all offsets and sizes in a rule Validate that all matches (if any) add up to the beginning of the target and that each match covers at least the base structure size. The compat path should be able to safely re-use the function as the structures only differ in alignment; added a BUILD_BUG_ON just in case we have an arch that adds padding as well. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/x_tables.c | 81 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index e2a6f2a9051b..f9aa9715c32e 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -416,6 +416,47 @@ int xt_check_match(struct xt_mtchk_param *par, } EXPORT_SYMBOL_GPL(xt_check_match); +/** xt_check_entry_match - check that matches end before start of target + * + * @match: beginning of xt_entry_match + * @target: beginning of this rules target (alleged end of matches) + * @alignment: alignment requirement of match structures + * + * Validates that all matches add up to the beginning of the target, + * and that each match covers at least the base structure size. + * + * Return: 0 on success, negative errno on failure. + */ +static int xt_check_entry_match(const char *match, const char *target, + const size_t alignment) +{ + const struct xt_entry_match *pos; + int length = target - match; + + if (length == 0) /* no matches */ + return 0; + + pos = (struct xt_entry_match *)match; + do { + if ((unsigned long)pos % alignment) + return -EINVAL; + + if (length < (int)sizeof(struct xt_entry_match)) + return -EINVAL; + + if (pos->u.match_size < sizeof(struct xt_entry_match)) + return -EINVAL; + + if (pos->u.match_size > length) + return -EINVAL; + + length -= pos->u.match_size; + pos = ((void *)((char *)(pos) + (pos)->u.match_size)); + } while (length > 0); + + return 0; +} + #ifdef CONFIG_COMPAT int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta) { @@ -571,7 +612,14 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems, target_offset + sizeof(struct compat_xt_standard_target) != next_offset) return -EINVAL; - return 0; + /* compat_xt_entry match has less strict aligment requirements, + * otherwise they are identical. In case of padding differences + * we need to add compat version of xt_check_entry_match. + */ + BUILD_BUG_ON(sizeof(struct compat_xt_entry_match) != sizeof(struct xt_entry_match)); + + return xt_check_entry_match(elems, base + target_offset, + __alignof__(struct compat_xt_entry_match)); } EXPORT_SYMBOL(xt_compat_check_entry_offsets); #endif /* CONFIG_COMPAT */ @@ -584,17 +632,39 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets); * @target_offset: the arp/ip/ip6_t->target_offset * @next_offset: the arp/ip/ip6_t->next_offset * - * validates that target_offset and next_offset are sane. - * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. + * validates that target_offset and next_offset are sane and that all + * match sizes (if any) align with the target offset. * * This function does not validate the targets or matches themselves, it - * only tests that all the offsets and sizes are correct. + * only tests that all the offsets and sizes are correct, that all + * match structures are aligned, and that the last structure ends where + * the target structure begins. + * + * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. * * The arp/ip/ip6t_entry structure @base must have passed following tests: * - it must point to a valid memory location * - base to base + next_offset must be accessible, i.e. not exceed allocated * length. * + * A well-formed entry looks like this: + * + * ip(6)t_entry match [mtdata] match [mtdata] target [tgdata] ip(6)t_entry + * e->elems[]-----' | | + * matchsize | | + * matchsize | | + * | | + * target_offset---------------------------------' | + * next_offset---------------------------------------------------' + * + * elems[]: flexible array member at end of ip(6)/arpt_entry struct. + * This is where matches (if any) and the target reside. + * target_offset: beginning of target. + * next_offset: start of the next rule; also: size of this rule. + * Since targets have a minimum size, target_offset + minlen <= next_offset. + * + * Every match stores its size, sum of sizes must not exceed target_offset. + * * Return: 0 on success, negative errno on failure. */ int xt_check_entry_offsets(const void *base, @@ -624,7 +694,8 @@ int xt_check_entry_offsets(const void *base, target_offset + sizeof(struct xt_standard_target) != next_offset) return -EINVAL; - return 0; + return xt_check_entry_match(elems, base + target_offset, + __alignof__(struct xt_entry_match)); } EXPORT_SYMBOL(xt_check_entry_offsets); -- GitLab From 7d3f843eed29222254c9feab481f55175a1afcc9 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:30 +0200 Subject: [PATCH 2638/9938] netfilter: ip_tables: simplify translate_compat_table args Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/ip_tables.c | 59 ++++++++++++++-------------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index baab033d74e0..d70418604503 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1449,7 +1449,6 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, static int compat_find_calc_match(struct xt_entry_match *m, - const char *name, const struct ipt_ip *ip, int *size) { @@ -1486,8 +1485,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, const unsigned char *base, const unsigned char *limit, const unsigned int *hook_entries, - const unsigned int *underflows, - const char *name) + const unsigned int *underflows) { struct xt_entry_match *ematch; struct xt_entry_target *t; @@ -1523,7 +1521,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, entry_offset = (void *)e - (void *)base; j = 0; xt_ematch_foreach(ematch, e) { - ret = compat_find_calc_match(ematch, name, &e->ip, &off); + ret = compat_find_calc_match(ematch, &e->ip, &off); if (ret != 0) goto release_matches; ++j; @@ -1572,7 +1570,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, static int compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, - unsigned int *size, const char *name, + unsigned int *size, struct xt_table_info *newinfo, unsigned char *base) { struct xt_entry_target *t; @@ -1655,14 +1653,9 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) static int translate_compat_table(struct net *net, - const char *name, - unsigned int valid_hooks, struct xt_table_info **pinfo, void **pentry0, - unsigned int total_size, - unsigned int number, - unsigned int *hook_entries, - unsigned int *underflows) + const struct compat_ipt_replace *compatr) { unsigned int i, j; struct xt_table_info *newinfo, *info; @@ -1674,8 +1667,8 @@ translate_compat_table(struct net *net, info = *pinfo; entry0 = *pentry0; - size = total_size; - info->number = number; + size = compatr->size; + info->number = compatr->num_entries; /* Init all hooks to impossible value. */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { @@ -1686,40 +1679,39 @@ translate_compat_table(struct net *net, duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(AF_INET); - xt_compat_init_offsets(AF_INET, number); + xt_compat_init_offsets(AF_INET, compatr->num_entries); /* Walk through entries, checking offsets. */ - xt_entry_foreach(iter0, entry0, total_size) { + xt_entry_foreach(iter0, entry0, compatr->size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + total_size, - hook_entries, - underflows, - name); + entry0 + compatr->size, + compatr->hook_entry, + compatr->underflow); if (ret != 0) goto out_unlock; ++j; } ret = -EINVAL; - if (j != number) { + if (j != compatr->num_entries) { duprintf("translate_compat_table: %u not %u entries\n", - j, number); + j, compatr->num_entries); goto out_unlock; } /* Check hooks all assigned */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { /* Only hooks which are valid */ - if (!(valid_hooks & (1 << i))) + if (!(compatr->valid_hooks & (1 << i))) continue; if (info->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", - i, hook_entries[i]); + i, info->hook_entry[i]); goto out_unlock; } if (info->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", - i, underflows[i]); + i, info->underflow[i]); goto out_unlock; } } @@ -1729,17 +1721,17 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; - newinfo->number = number; + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = info->hook_entry[i]; newinfo->underflow[i] = info->underflow[i]; } entry1 = newinfo->entries; pos = entry1; - size = total_size; - xt_entry_foreach(iter0, entry0, total_size) { + size = compatr->size; + xt_entry_foreach(iter0, entry0, compatr->size) { ret = compat_copy_entry_from_user(iter0, &pos, &size, - name, newinfo, entry1); + newinfo, entry1); if (ret != 0) break; } @@ -1749,12 +1741,12 @@ translate_compat_table(struct net *net, goto free_newinfo; ret = -ELOOP; - if (!mark_source_chains(newinfo, valid_hooks, entry1)) + if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) goto free_newinfo; i = 0; xt_entry_foreach(iter1, entry1, newinfo->size) { - ret = compat_check_entry(iter1, net, name); + ret = compat_check_entry(iter1, net, compatr->name); if (ret != 0) break; ++i; @@ -1794,7 +1786,7 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); out: - xt_entry_foreach(iter0, entry0, total_size) { + xt_entry_foreach(iter0, entry0, compatr->size) { if (j-- == 0) break; compat_release_entry(iter0); @@ -1839,10 +1831,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, - &newinfo, &loc_cpu_entry, tmp.size, - tmp.num_entries, tmp.hook_entry, - tmp.underflow); + ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; -- GitLab From 329a0807124f12fe1c8032f95d8a8eb47047fb0e Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:31 +0200 Subject: [PATCH 2639/9938] netfilter: ip6_tables: simplify translate_compat_table args Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/ip6_tables.c | 59 ++++++++++++++------------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 6957627c7931..8d082c557771 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1461,7 +1461,6 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, static int compat_find_calc_match(struct xt_entry_match *m, - const char *name, const struct ip6t_ip6 *ipv6, int *size) { @@ -1498,8 +1497,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, const unsigned char *base, const unsigned char *limit, const unsigned int *hook_entries, - const unsigned int *underflows, - const char *name) + const unsigned int *underflows) { struct xt_entry_match *ematch; struct xt_entry_target *t; @@ -1535,7 +1533,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, entry_offset = (void *)e - (void *)base; j = 0; xt_ematch_foreach(ematch, e) { - ret = compat_find_calc_match(ematch, name, &e->ipv6, &off); + ret = compat_find_calc_match(ematch, &e->ipv6, &off); if (ret != 0) goto release_matches; ++j; @@ -1584,7 +1582,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, static int compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, - unsigned int *size, const char *name, + unsigned int *size, struct xt_table_info *newinfo, unsigned char *base) { struct xt_entry_target *t; @@ -1664,14 +1662,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, static int translate_compat_table(struct net *net, - const char *name, - unsigned int valid_hooks, struct xt_table_info **pinfo, void **pentry0, - unsigned int total_size, - unsigned int number, - unsigned int *hook_entries, - unsigned int *underflows) + const struct compat_ip6t_replace *compatr) { unsigned int i, j; struct xt_table_info *newinfo, *info; @@ -1683,8 +1676,8 @@ translate_compat_table(struct net *net, info = *pinfo; entry0 = *pentry0; - size = total_size; - info->number = number; + size = compatr->size; + info->number = compatr->num_entries; /* Init all hooks to impossible value. */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { @@ -1695,40 +1688,39 @@ translate_compat_table(struct net *net, duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(AF_INET6); - xt_compat_init_offsets(AF_INET6, number); + xt_compat_init_offsets(AF_INET6, compatr->num_entries); /* Walk through entries, checking offsets. */ - xt_entry_foreach(iter0, entry0, total_size) { + xt_entry_foreach(iter0, entry0, compatr->size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + total_size, - hook_entries, - underflows, - name); + entry0 + compatr->size, + compatr->hook_entry, + compatr->underflow); if (ret != 0) goto out_unlock; ++j; } ret = -EINVAL; - if (j != number) { + if (j != compatr->num_entries) { duprintf("translate_compat_table: %u not %u entries\n", - j, number); + j, compatr->num_entries); goto out_unlock; } /* Check hooks all assigned */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { /* Only hooks which are valid */ - if (!(valid_hooks & (1 << i))) + if (!(compatr->valid_hooks & (1 << i))) continue; if (info->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", - i, hook_entries[i]); + i, info->hook_entry[i]); goto out_unlock; } if (info->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", - i, underflows[i]); + i, info->underflow[i]); goto out_unlock; } } @@ -1738,17 +1730,17 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; - newinfo->number = number; + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = info->hook_entry[i]; newinfo->underflow[i] = info->underflow[i]; } entry1 = newinfo->entries; pos = entry1; - size = total_size; - xt_entry_foreach(iter0, entry0, total_size) { + size = compatr->size; + xt_entry_foreach(iter0, entry0, compatr->size) { ret = compat_copy_entry_from_user(iter0, &pos, &size, - name, newinfo, entry1); + newinfo, entry1); if (ret != 0) break; } @@ -1758,12 +1750,12 @@ translate_compat_table(struct net *net, goto free_newinfo; ret = -ELOOP; - if (!mark_source_chains(newinfo, valid_hooks, entry1)) + if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) goto free_newinfo; i = 0; xt_entry_foreach(iter1, entry1, newinfo->size) { - ret = compat_check_entry(iter1, net, name); + ret = compat_check_entry(iter1, net, compatr->name); if (ret != 0) break; ++i; @@ -1803,7 +1795,7 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); out: - xt_entry_foreach(iter0, entry0, total_size) { + xt_entry_foreach(iter0, entry0, compatr->size) { if (j-- == 0) break; compat_release_entry(iter0); @@ -1848,10 +1840,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, - &newinfo, &loc_cpu_entry, tmp.size, - tmp.num_entries, tmp.hook_entry, - tmp.underflow); + ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; -- GitLab From 8dddd32756f6fe8e4e82a63361119b7e2384e02f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:32 +0200 Subject: [PATCH 2640/9938] netfilter: arp_tables: simplify translate_compat_table args Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 82 +++++++++++++++------------------ 1 file changed, 36 insertions(+), 46 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 95ed4e454c60..1d1386dc159b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1214,6 +1214,18 @@ static int do_add_counters(struct net *net, const void __user *user, } #ifdef CONFIG_COMPAT +struct compat_arpt_replace { + char name[XT_TABLE_MAXNAMELEN]; + u32 valid_hooks; + u32 num_entries; + u32 size; + u32 hook_entry[NF_ARP_NUMHOOKS]; + u32 underflow[NF_ARP_NUMHOOKS]; + u32 num_counters; + compat_uptr_t counters; + struct compat_arpt_entry entries[0]; +}; + static inline void compat_release_entry(struct compat_arpt_entry *e) { struct xt_entry_target *t; @@ -1229,8 +1241,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, const unsigned char *base, const unsigned char *limit, const unsigned int *hook_entries, - const unsigned int *underflows, - const char *name) + const unsigned int *underflows) { struct xt_entry_target *t; struct xt_target *target; @@ -1301,7 +1312,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, static int compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, - unsigned int *size, const char *name, + unsigned int *size, struct xt_table_info *newinfo, unsigned char *base) { struct xt_entry_target *t; @@ -1334,14 +1345,9 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, return ret; } -static int translate_compat_table(const char *name, - unsigned int valid_hooks, - struct xt_table_info **pinfo, +static int translate_compat_table(struct xt_table_info **pinfo, void **pentry0, - unsigned int total_size, - unsigned int number, - unsigned int *hook_entries, - unsigned int *underflows) + const struct compat_arpt_replace *compatr) { unsigned int i, j; struct xt_table_info *newinfo, *info; @@ -1353,8 +1359,8 @@ static int translate_compat_table(const char *name, info = *pinfo; entry0 = *pentry0; - size = total_size; - info->number = number; + size = compatr->size; + info->number = compatr->num_entries; /* Init all hooks to impossible value. */ for (i = 0; i < NF_ARP_NUMHOOKS; i++) { @@ -1365,40 +1371,39 @@ static int translate_compat_table(const char *name, duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(NFPROTO_ARP); - xt_compat_init_offsets(NFPROTO_ARP, number); + xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries); /* Walk through entries, checking offsets. */ - xt_entry_foreach(iter0, entry0, total_size) { + xt_entry_foreach(iter0, entry0, compatr->size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + total_size, - hook_entries, - underflows, - name); + entry0 + compatr->size, + compatr->hook_entry, + compatr->underflow); if (ret != 0) goto out_unlock; ++j; } ret = -EINVAL; - if (j != number) { + if (j != compatr->num_entries) { duprintf("translate_compat_table: %u not %u entries\n", - j, number); + j, compatr->num_entries); goto out_unlock; } /* Check hooks all assigned */ for (i = 0; i < NF_ARP_NUMHOOKS; i++) { /* Only hooks which are valid */ - if (!(valid_hooks & (1 << i))) + if (!(compatr->valid_hooks & (1 << i))) continue; if (info->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", - i, hook_entries[i]); + i, info->hook_entry[i]); goto out_unlock; } if (info->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", - i, underflows[i]); + i, info->underflow[i]); goto out_unlock; } } @@ -1408,17 +1413,17 @@ static int translate_compat_table(const char *name, if (!newinfo) goto out_unlock; - newinfo->number = number; + newinfo->number = compatr->num_entries; for (i = 0; i < NF_ARP_NUMHOOKS; i++) { newinfo->hook_entry[i] = info->hook_entry[i]; newinfo->underflow[i] = info->underflow[i]; } entry1 = newinfo->entries; pos = entry1; - size = total_size; - xt_entry_foreach(iter0, entry0, total_size) { + size = compatr->size; + xt_entry_foreach(iter0, entry0, compatr->size) { ret = compat_copy_entry_from_user(iter0, &pos, &size, - name, newinfo, entry1); + newinfo, entry1); if (ret != 0) break; } @@ -1428,7 +1433,7 @@ static int translate_compat_table(const char *name, goto free_newinfo; ret = -ELOOP; - if (!mark_source_chains(newinfo, valid_hooks, entry1)) + if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) goto free_newinfo; i = 0; @@ -1439,7 +1444,7 @@ static int translate_compat_table(const char *name, break; } - ret = check_target(iter1, name); + ret = check_target(iter1, compatr->name); if (ret != 0) { xt_percpu_counter_free(iter1->counters.pcnt); break; @@ -1481,7 +1486,7 @@ static int translate_compat_table(const char *name, free_newinfo: xt_free_table_info(newinfo); out: - xt_entry_foreach(iter0, entry0, total_size) { + xt_entry_foreach(iter0, entry0, compatr->size) { if (j-- == 0) break; compat_release_entry(iter0); @@ -1493,18 +1498,6 @@ static int translate_compat_table(const char *name, goto out; } -struct compat_arpt_replace { - char name[XT_TABLE_MAXNAMELEN]; - u32 valid_hooks; - u32 num_entries; - u32 size; - u32 hook_entry[NF_ARP_NUMHOOKS]; - u32 underflow[NF_ARP_NUMHOOKS]; - u32 num_counters; - compat_uptr_t counters; - struct compat_arpt_entry entries[0]; -}; - static int compat_do_replace(struct net *net, void __user *user, unsigned int len) { @@ -1537,10 +1530,7 @@ static int compat_do_replace(struct net *net, void __user *user, goto free_newinfo; } - ret = translate_compat_table(tmp.name, tmp.valid_hooks, - &newinfo, &loc_cpu_entry, tmp.size, - tmp.num_entries, tmp.hook_entry, - tmp.underflow); + ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; -- GitLab From 0188346f21e6546498c2a0f84888797ad4063fc5 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:33 +0200 Subject: [PATCH 2641/9938] netfilter: x_tables: xt_compat_match_from_user doesn't need a retval Always returned 0. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/x_tables.h | 2 +- net/ipv4/netfilter/arp_tables.c | 17 +++++------------ net/ipv4/netfilter/ip_tables.c | 26 +++++++++----------------- net/ipv6/netfilter/ip6_tables.c | 27 +++++++++------------------ net/netfilter/x_tables.c | 5 ++--- 5 files changed, 26 insertions(+), 51 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 30cfb1e943fb..e2da9b90f1b8 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -484,7 +484,7 @@ void xt_compat_init_offsets(u_int8_t af, unsigned int number); int xt_compat_calc_jump(u_int8_t af, unsigned int offset); int xt_compat_match_offset(const struct xt_match *match); -int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, +void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, unsigned int *size); int xt_compat_match_to_user(const struct xt_entry_match *m, void __user **dstptr, unsigned int *size); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 1d1386dc159b..be514c676fad 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1310,7 +1310,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, return ret; } -static int +static void compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, unsigned int *size, struct xt_table_info *newinfo, unsigned char *base) @@ -1319,9 +1319,8 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, struct xt_target *target; struct arpt_entry *de; unsigned int origsize; - int ret, h; + int h; - ret = 0; origsize = *size; de = (struct arpt_entry *)*dstptr; memcpy(de, e, sizeof(struct arpt_entry)); @@ -1342,7 +1341,6 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, if ((unsigned char *)de - base < newinfo->underflow[h]) newinfo->underflow[h] -= origsize - *size; } - return ret; } static int translate_compat_table(struct xt_table_info **pinfo, @@ -1421,16 +1419,11 @@ static int translate_compat_table(struct xt_table_info **pinfo, entry1 = newinfo->entries; pos = entry1; size = compatr->size; - xt_entry_foreach(iter0, entry0, compatr->size) { - ret = compat_copy_entry_from_user(iter0, &pos, &size, - newinfo, entry1); - if (ret != 0) - break; - } + xt_entry_foreach(iter0, entry0, compatr->size) + compat_copy_entry_from_user(iter0, &pos, &size, + newinfo, entry1); xt_compat_flush_offsets(NFPROTO_ARP); xt_compat_unlock(NFPROTO_ARP); - if (ret) - goto free_newinfo; ret = -ELOOP; if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index d70418604503..5c20eef980c1 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1568,7 +1568,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, return ret; } -static int +static void compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, unsigned int *size, struct xt_table_info *newinfo, unsigned char *base) @@ -1577,10 +1577,9 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, struct xt_target *target; struct ipt_entry *de; unsigned int origsize; - int ret, h; + int h; struct xt_entry_match *ematch; - ret = 0; origsize = *size; de = (struct ipt_entry *)*dstptr; memcpy(de, e, sizeof(struct ipt_entry)); @@ -1589,11 +1588,9 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, *dstptr += sizeof(struct ipt_entry); *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); - xt_ematch_foreach(ematch, e) { - ret = xt_compat_match_from_user(ematch, dstptr, size); - if (ret != 0) - return ret; - } + xt_ematch_foreach(ematch, e) + xt_compat_match_from_user(ematch, dstptr, size); + de->target_offset = e->target_offset - (origsize - *size); t = compat_ipt_get_target(e); target = t->u.kernel.target; @@ -1606,7 +1603,6 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, if ((unsigned char *)de - base < newinfo->underflow[h]) newinfo->underflow[h] -= origsize - *size; } - return ret; } static int @@ -1729,16 +1725,12 @@ translate_compat_table(struct net *net, entry1 = newinfo->entries; pos = entry1; size = compatr->size; - xt_entry_foreach(iter0, entry0, compatr->size) { - ret = compat_copy_entry_from_user(iter0, &pos, &size, - newinfo, entry1); - if (ret != 0) - break; - } + xt_entry_foreach(iter0, entry0, compatr->size) + compat_copy_entry_from_user(iter0, &pos, &size, + newinfo, entry1); + xt_compat_flush_offsets(AF_INET); xt_compat_unlock(AF_INET); - if (ret) - goto free_newinfo; ret = -ELOOP; if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 8d082c557771..620d54c1c119 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1580,7 +1580,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, return ret; } -static int +static void compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, unsigned int *size, struct xt_table_info *newinfo, unsigned char *base) @@ -1588,10 +1588,9 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, struct xt_entry_target *t; struct ip6t_entry *de; unsigned int origsize; - int ret, h; + int h; struct xt_entry_match *ematch; - ret = 0; origsize = *size; de = (struct ip6t_entry *)*dstptr; memcpy(de, e, sizeof(struct ip6t_entry)); @@ -1600,11 +1599,9 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, *dstptr += sizeof(struct ip6t_entry); *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); - xt_ematch_foreach(ematch, e) { - ret = xt_compat_match_from_user(ematch, dstptr, size); - if (ret != 0) - return ret; - } + xt_ematch_foreach(ematch, e) + xt_compat_match_from_user(ematch, dstptr, size); + de->target_offset = e->target_offset - (origsize - *size); t = compat_ip6t_get_target(e); xt_compat_target_from_user(t, dstptr, size); @@ -1616,7 +1613,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, if ((unsigned char *)de - base < newinfo->underflow[h]) newinfo->underflow[h] -= origsize - *size; } - return ret; } static int compat_check_entry(struct ip6t_entry *e, struct net *net, @@ -1737,17 +1733,12 @@ translate_compat_table(struct net *net, } entry1 = newinfo->entries; pos = entry1; - size = compatr->size; - xt_entry_foreach(iter0, entry0, compatr->size) { - ret = compat_copy_entry_from_user(iter0, &pos, &size, - newinfo, entry1); - if (ret != 0) - break; - } + xt_entry_foreach(iter0, entry0, compatr->size) + compat_copy_entry_from_user(iter0, &pos, &size, + newinfo, entry1); + xt_compat_flush_offsets(AF_INET6); xt_compat_unlock(AF_INET6); - if (ret) - goto free_newinfo; ret = -ELOOP; if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index f9aa9715c32e..7e7173b68344 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -526,8 +526,8 @@ int xt_compat_match_offset(const struct xt_match *match) } EXPORT_SYMBOL_GPL(xt_compat_match_offset); -int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, - unsigned int *size) +void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, + unsigned int *size) { const struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; @@ -549,7 +549,6 @@ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, *size += off; *dstptr += msize; - return 0; } EXPORT_SYMBOL_GPL(xt_compat_match_from_user); -- GitLab From 09d9686047dbbe1cf4faa558d3ecc4aae2046054 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:34 +0200 Subject: [PATCH 2642/9938] netfilter: x_tables: do compat validation via translate_table This looks like refactoring, but its also a bug fix. Problem is that the compat path (32bit iptables, 64bit kernel) lacks a few sanity tests that are done in the normal path. For example, we do not check for underflows and the base chain policies. While its possible to also add such checks to the compat path, its more copy&pastry, for instance we cannot reuse check_underflow() helper as e->target_offset differs in the compat case. Other problem is that it makes auditing for validation errors harder; two places need to be checked and kept in sync. At a high level 32 bit compat works like this: 1- initial pass over blob: validate match/entry offsets, bounds checking lookup all matches and targets do bookkeeping wrt. size delta of 32/64bit structures assign match/target.u.kernel pointer (points at kernel implementation, needed to access ->compatsize etc.) 2- allocate memory according to the total bookkeeping size to contain the translated ruleset 3- second pass over original blob: for each entry, copy the 32bit representation to the newly allocated memory. This also does any special match translations (e.g. adjust 32bit to 64bit longs, etc). 4- check if ruleset is free of loops (chase all jumps) 5-first pass over translated blob: call the checkentry function of all matches and targets. The alternative implemented by this patch is to drop steps 3&4 from the compat process, the translation is changed into an intermediate step rather than a full 1:1 translate_table replacement. In the 2nd pass (step #3), change the 64bit ruleset back to a kernel representation, i.e. put() the kernel pointer and restore ->u.user.name . This gets us a 64bit ruleset that is in the format generated by a 64bit iptables userspace -- we can then use translate_table() to get the 'native' sanity checks. This has two drawbacks: 1. we re-validate all the match and target entry structure sizes even though compat translation is supposed to never generate bogus offsets. 2. we put and then re-lookup each match and target. THe upside is that we get all sanity tests and ruleset validations provided by the normal path and can remove some duplicated compat code. iptables-restore time of autogenerated ruleset with 300k chains of form -A CHAIN0001 -m limit --limit 1/s -j CHAIN0002 -A CHAIN0002 -m limit --limit 1/s -j CHAIN0003 shows no noticeable differences in restore times: old: 0m30.796s new: 0m31.521s 64bit: 0m25.674s Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 114 +++++------------------ net/ipv4/netfilter/ip_tables.c | 155 ++++++-------------------------- net/ipv6/netfilter/ip6_tables.c | 148 +++++------------------------- net/netfilter/x_tables.c | 8 ++ 4 files changed, 83 insertions(+), 342 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index be514c676fad..705179b0fd23 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1234,19 +1234,17 @@ static inline void compat_release_entry(struct compat_arpt_entry *e) module_put(t->u.kernel.target->me); } -static inline int +static int check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, struct xt_table_info *newinfo, unsigned int *size, const unsigned char *base, - const unsigned char *limit, - const unsigned int *hook_entries, - const unsigned int *underflows) + const unsigned char *limit) { struct xt_entry_target *t; struct xt_target *target; unsigned int entry_offset; - int ret, off, h; + int ret, off; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 || @@ -1291,17 +1289,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, if (ret) goto release_target; - /* Check hooks & underflows */ - for (h = 0; h < NF_ARP_NUMHOOKS; h++) { - if ((unsigned char *)e - base == hook_entries[h]) - newinfo->hook_entry[h] = hook_entries[h]; - if ((unsigned char *)e - base == underflows[h]) - newinfo->underflow[h] = underflows[h]; - } - - /* Clear counters and comefrom */ - memset(&e->counters, 0, sizeof(e->counters)); - e->comefrom = 0; return 0; release_target: @@ -1351,7 +1338,7 @@ static int translate_compat_table(struct xt_table_info **pinfo, struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; struct compat_arpt_entry *iter0; - struct arpt_entry *iter1; + struct arpt_replace repl; unsigned int size; int ret = 0; @@ -1360,12 +1347,6 @@ static int translate_compat_table(struct xt_table_info **pinfo, size = compatr->size; info->number = compatr->num_entries; - /* Init all hooks to impossible value. */ - for (i = 0; i < NF_ARP_NUMHOOKS; i++) { - info->hook_entry[i] = 0xFFFFFFFF; - info->underflow[i] = 0xFFFFFFFF; - } - duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(NFPROTO_ARP); @@ -1374,9 +1355,7 @@ static int translate_compat_table(struct xt_table_info **pinfo, xt_entry_foreach(iter0, entry0, compatr->size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + compatr->size, - compatr->hook_entry, - compatr->underflow); + entry0 + compatr->size); if (ret != 0) goto out_unlock; ++j; @@ -1389,23 +1368,6 @@ static int translate_compat_table(struct xt_table_info **pinfo, goto out_unlock; } - /* Check hooks all assigned */ - for (i = 0; i < NF_ARP_NUMHOOKS; i++) { - /* Only hooks which are valid */ - if (!(compatr->valid_hooks & (1 << i))) - continue; - if (info->hook_entry[i] == 0xFFFFFFFF) { - duprintf("Invalid hook entry %u %u\n", - i, info->hook_entry[i]); - goto out_unlock; - } - if (info->underflow[i] == 0xFFFFFFFF) { - duprintf("Invalid underflow %u %u\n", - i, info->underflow[i]); - goto out_unlock; - } - } - ret = -ENOMEM; newinfo = xt_alloc_table_info(size); if (!newinfo) @@ -1422,55 +1384,26 @@ static int translate_compat_table(struct xt_table_info **pinfo, xt_entry_foreach(iter0, entry0, compatr->size) compat_copy_entry_from_user(iter0, &pos, &size, newinfo, entry1); + + /* all module references in entry0 are now gone */ + xt_compat_flush_offsets(NFPROTO_ARP); xt_compat_unlock(NFPROTO_ARP); - ret = -ELOOP; - if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) - goto free_newinfo; - - i = 0; - xt_entry_foreach(iter1, entry1, newinfo->size) { - iter1->counters.pcnt = xt_percpu_counter_alloc(); - if (IS_ERR_VALUE(iter1->counters.pcnt)) { - ret = -ENOMEM; - break; - } + memcpy(&repl, compatr, sizeof(*compatr)); - ret = check_target(iter1, compatr->name); - if (ret != 0) { - xt_percpu_counter_free(iter1->counters.pcnt); - break; - } - ++i; - if (strcmp(arpt_get_target(iter1)->u.user.name, - XT_ERROR_TARGET) == 0) - ++newinfo->stacksize; - } - if (ret) { - /* - * The first i matches need cleanup_entry (calls ->destroy) - * because they had called ->check already. The other j-i - * entries need only release. - */ - int skip = i; - j -= i; - xt_entry_foreach(iter0, entry0, newinfo->size) { - if (skip-- > 0) - continue; - if (j-- == 0) - break; - compat_release_entry(iter0); - } - xt_entry_foreach(iter1, entry1, newinfo->size) { - if (i-- == 0) - break; - cleanup_entry(iter1); - } - xt_free_table_info(newinfo); - return ret; + for (i = 0; i < NF_ARP_NUMHOOKS; i++) { + repl.hook_entry[i] = newinfo->hook_entry[i]; + repl.underflow[i] = newinfo->underflow[i]; } + repl.num_counters = 0; + repl.counters = NULL; + repl.size = newinfo->size; + ret = translate_table(newinfo, entry1, &repl); + if (ret) + goto free_newinfo; + *pinfo = newinfo; *pentry0 = entry1; xt_free_table_info(info); @@ -1478,17 +1411,16 @@ static int translate_compat_table(struct xt_table_info **pinfo, free_newinfo: xt_free_table_info(newinfo); -out: + return ret; +out_unlock: + xt_compat_flush_offsets(NFPROTO_ARP); + xt_compat_unlock(NFPROTO_ARP); xt_entry_foreach(iter0, entry0, compatr->size) { if (j-- == 0) break; compat_release_entry(iter0); } return ret; -out_unlock: - xt_compat_flush_offsets(NFPROTO_ARP); - xt_compat_unlock(NFPROTO_ARP); - goto out; } static int compat_do_replace(struct net *net, void __user *user, diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 5c20eef980c1..c26ccd818e8f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1483,16 +1483,14 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, struct xt_table_info *newinfo, unsigned int *size, const unsigned char *base, - const unsigned char *limit, - const unsigned int *hook_entries, - const unsigned int *underflows) + const unsigned char *limit) { struct xt_entry_match *ematch; struct xt_entry_target *t; struct xt_target *target; unsigned int entry_offset; unsigned int j; - int ret, off, h; + int ret, off; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 || @@ -1544,17 +1542,6 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, if (ret) goto out; - /* Check hooks & underflows */ - for (h = 0; h < NF_INET_NUMHOOKS; h++) { - if ((unsigned char *)e - base == hook_entries[h]) - newinfo->hook_entry[h] = hook_entries[h]; - if ((unsigned char *)e - base == underflows[h]) - newinfo->underflow[h] = underflows[h]; - } - - /* Clear counters and comefrom */ - memset(&e->counters, 0, sizeof(e->counters)); - e->comefrom = 0; return 0; out: @@ -1597,6 +1584,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, xt_compat_target_from_user(t, dstptr, size); de->next_offset = e->next_offset - (origsize - *size); + for (h = 0; h < NF_INET_NUMHOOKS; h++) { if ((unsigned char *)de - base < newinfo->hook_entry[h]) newinfo->hook_entry[h] -= origsize - *size; @@ -1605,48 +1593,6 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, } } -static int -compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) -{ - struct xt_entry_match *ematch; - struct xt_mtchk_param mtpar; - unsigned int j; - int ret = 0; - - e->counters.pcnt = xt_percpu_counter_alloc(); - if (IS_ERR_VALUE(e->counters.pcnt)) - return -ENOMEM; - - j = 0; - mtpar.net = net; - mtpar.table = name; - mtpar.entryinfo = &e->ip; - mtpar.hook_mask = e->comefrom; - mtpar.family = NFPROTO_IPV4; - xt_ematch_foreach(ematch, e) { - ret = check_match(ematch, &mtpar); - if (ret != 0) - goto cleanup_matches; - ++j; - } - - ret = check_target(e, net, name); - if (ret) - goto cleanup_matches; - return 0; - - cleanup_matches: - xt_ematch_foreach(ematch, e) { - if (j-- == 0) - break; - cleanup_match(ematch, net); - } - - xt_percpu_counter_free(e->counters.pcnt); - - return ret; -} - static int translate_compat_table(struct net *net, struct xt_table_info **pinfo, @@ -1657,7 +1603,7 @@ translate_compat_table(struct net *net, struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; struct compat_ipt_entry *iter0; - struct ipt_entry *iter1; + struct ipt_replace repl; unsigned int size; int ret; @@ -1666,12 +1612,6 @@ translate_compat_table(struct net *net, size = compatr->size; info->number = compatr->num_entries; - /* Init all hooks to impossible value. */ - for (i = 0; i < NF_INET_NUMHOOKS; i++) { - info->hook_entry[i] = 0xFFFFFFFF; - info->underflow[i] = 0xFFFFFFFF; - } - duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(AF_INET); @@ -1680,9 +1620,7 @@ translate_compat_table(struct net *net, xt_entry_foreach(iter0, entry0, compatr->size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + compatr->size, - compatr->hook_entry, - compatr->underflow); + entry0 + compatr->size); if (ret != 0) goto out_unlock; ++j; @@ -1695,23 +1633,6 @@ translate_compat_table(struct net *net, goto out_unlock; } - /* Check hooks all assigned */ - for (i = 0; i < NF_INET_NUMHOOKS; i++) { - /* Only hooks which are valid */ - if (!(compatr->valid_hooks & (1 << i))) - continue; - if (info->hook_entry[i] == 0xFFFFFFFF) { - duprintf("Invalid hook entry %u %u\n", - i, info->hook_entry[i]); - goto out_unlock; - } - if (info->underflow[i] == 0xFFFFFFFF) { - duprintf("Invalid underflow %u %u\n", - i, info->underflow[i]); - goto out_unlock; - } - } - ret = -ENOMEM; newinfo = xt_alloc_table_info(size); if (!newinfo) @@ -1719,8 +1640,8 @@ translate_compat_table(struct net *net, newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { - newinfo->hook_entry[i] = info->hook_entry[i]; - newinfo->underflow[i] = info->underflow[i]; + newinfo->hook_entry[i] = compatr->hook_entry[i]; + newinfo->underflow[i] = compatr->underflow[i]; } entry1 = newinfo->entries; pos = entry1; @@ -1729,47 +1650,30 @@ translate_compat_table(struct net *net, compat_copy_entry_from_user(iter0, &pos, &size, newinfo, entry1); + /* all module references in entry0 are now gone. + * entry1/newinfo contains a 64bit ruleset that looks exactly as + * generated by 64bit userspace. + * + * Call standard translate_table() to validate all hook_entrys, + * underflows, check for loops, etc. + */ xt_compat_flush_offsets(AF_INET); xt_compat_unlock(AF_INET); - ret = -ELOOP; - if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) - goto free_newinfo; + memcpy(&repl, compatr, sizeof(*compatr)); - i = 0; - xt_entry_foreach(iter1, entry1, newinfo->size) { - ret = compat_check_entry(iter1, net, compatr->name); - if (ret != 0) - break; - ++i; - if (strcmp(ipt_get_target(iter1)->u.user.name, - XT_ERROR_TARGET) == 0) - ++newinfo->stacksize; - } - if (ret) { - /* - * The first i matches need cleanup_entry (calls ->destroy) - * because they had called ->check already. The other j-i - * entries need only release. - */ - int skip = i; - j -= i; - xt_entry_foreach(iter0, entry0, newinfo->size) { - if (skip-- > 0) - continue; - if (j-- == 0) - break; - compat_release_entry(iter0); - } - xt_entry_foreach(iter1, entry1, newinfo->size) { - if (i-- == 0) - break; - cleanup_entry(iter1, net); - } - xt_free_table_info(newinfo); - return ret; + for (i = 0; i < NF_INET_NUMHOOKS; i++) { + repl.hook_entry[i] = newinfo->hook_entry[i]; + repl.underflow[i] = newinfo->underflow[i]; } + repl.num_counters = 0; + repl.counters = NULL; + repl.size = newinfo->size; + ret = translate_table(net, newinfo, entry1, &repl); + if (ret) + goto free_newinfo; + *pinfo = newinfo; *pentry0 = entry1; xt_free_table_info(info); @@ -1777,17 +1681,16 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); -out: + return ret; +out_unlock: + xt_compat_flush_offsets(AF_INET); + xt_compat_unlock(AF_INET); xt_entry_foreach(iter0, entry0, compatr->size) { if (j-- == 0) break; compat_release_entry(iter0); } return ret; -out_unlock: - xt_compat_flush_offsets(AF_INET); - xt_compat_unlock(AF_INET); - goto out; } static int diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 620d54c1c119..f5a4eb2d5084 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1495,16 +1495,14 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, struct xt_table_info *newinfo, unsigned int *size, const unsigned char *base, - const unsigned char *limit, - const unsigned int *hook_entries, - const unsigned int *underflows) + const unsigned char *limit) { struct xt_entry_match *ematch; struct xt_entry_target *t; struct xt_target *target; unsigned int entry_offset; unsigned int j; - int ret, off, h; + int ret, off; duprintf("check_compat_entry_size_and_hooks %p\n", e); if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 || @@ -1556,17 +1554,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, if (ret) goto out; - /* Check hooks & underflows */ - for (h = 0; h < NF_INET_NUMHOOKS; h++) { - if ((unsigned char *)e - base == hook_entries[h]) - newinfo->hook_entry[h] = hook_entries[h]; - if ((unsigned char *)e - base == underflows[h]) - newinfo->underflow[h] = underflows[h]; - } - - /* Clear counters and comefrom */ - memset(&e->counters, 0, sizeof(e->counters)); - e->comefrom = 0; return 0; out: @@ -1615,47 +1602,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, } } -static int compat_check_entry(struct ip6t_entry *e, struct net *net, - const char *name) -{ - unsigned int j; - int ret = 0; - struct xt_mtchk_param mtpar; - struct xt_entry_match *ematch; - - e->counters.pcnt = xt_percpu_counter_alloc(); - if (IS_ERR_VALUE(e->counters.pcnt)) - return -ENOMEM; - j = 0; - mtpar.net = net; - mtpar.table = name; - mtpar.entryinfo = &e->ipv6; - mtpar.hook_mask = e->comefrom; - mtpar.family = NFPROTO_IPV6; - xt_ematch_foreach(ematch, e) { - ret = check_match(ematch, &mtpar); - if (ret != 0) - goto cleanup_matches; - ++j; - } - - ret = check_target(e, net, name); - if (ret) - goto cleanup_matches; - return 0; - - cleanup_matches: - xt_ematch_foreach(ematch, e) { - if (j-- == 0) - break; - cleanup_match(ematch, net); - } - - xt_percpu_counter_free(e->counters.pcnt); - - return ret; -} - static int translate_compat_table(struct net *net, struct xt_table_info **pinfo, @@ -1666,7 +1612,7 @@ translate_compat_table(struct net *net, struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; struct compat_ip6t_entry *iter0; - struct ip6t_entry *iter1; + struct ip6t_replace repl; unsigned int size; int ret = 0; @@ -1675,12 +1621,6 @@ translate_compat_table(struct net *net, size = compatr->size; info->number = compatr->num_entries; - /* Init all hooks to impossible value. */ - for (i = 0; i < NF_INET_NUMHOOKS; i++) { - info->hook_entry[i] = 0xFFFFFFFF; - info->underflow[i] = 0xFFFFFFFF; - } - duprintf("translate_compat_table: size %u\n", info->size); j = 0; xt_compat_lock(AF_INET6); @@ -1689,9 +1629,7 @@ translate_compat_table(struct net *net, xt_entry_foreach(iter0, entry0, compatr->size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, - entry0 + compatr->size, - compatr->hook_entry, - compatr->underflow); + entry0 + compatr->size); if (ret != 0) goto out_unlock; ++j; @@ -1704,23 +1642,6 @@ translate_compat_table(struct net *net, goto out_unlock; } - /* Check hooks all assigned */ - for (i = 0; i < NF_INET_NUMHOOKS; i++) { - /* Only hooks which are valid */ - if (!(compatr->valid_hooks & (1 << i))) - continue; - if (info->hook_entry[i] == 0xFFFFFFFF) { - duprintf("Invalid hook entry %u %u\n", - i, info->hook_entry[i]); - goto out_unlock; - } - if (info->underflow[i] == 0xFFFFFFFF) { - duprintf("Invalid underflow %u %u\n", - i, info->underflow[i]); - goto out_unlock; - } - } - ret = -ENOMEM; newinfo = xt_alloc_table_info(size); if (!newinfo) @@ -1728,56 +1649,34 @@ translate_compat_table(struct net *net, newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { - newinfo->hook_entry[i] = info->hook_entry[i]; - newinfo->underflow[i] = info->underflow[i]; + newinfo->hook_entry[i] = compatr->hook_entry[i]; + newinfo->underflow[i] = compatr->underflow[i]; } entry1 = newinfo->entries; pos = entry1; + size = compatr->size; xt_entry_foreach(iter0, entry0, compatr->size) compat_copy_entry_from_user(iter0, &pos, &size, newinfo, entry1); + /* all module references in entry0 are now gone. */ xt_compat_flush_offsets(AF_INET6); xt_compat_unlock(AF_INET6); - ret = -ELOOP; - if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1)) - goto free_newinfo; + memcpy(&repl, compatr, sizeof(*compatr)); - i = 0; - xt_entry_foreach(iter1, entry1, newinfo->size) { - ret = compat_check_entry(iter1, net, compatr->name); - if (ret != 0) - break; - ++i; - if (strcmp(ip6t_get_target(iter1)->u.user.name, - XT_ERROR_TARGET) == 0) - ++newinfo->stacksize; - } - if (ret) { - /* - * The first i matches need cleanup_entry (calls ->destroy) - * because they had called ->check already. The other j-i - * entries need only release. - */ - int skip = i; - j -= i; - xt_entry_foreach(iter0, entry0, newinfo->size) { - if (skip-- > 0) - continue; - if (j-- == 0) - break; - compat_release_entry(iter0); - } - xt_entry_foreach(iter1, entry1, newinfo->size) { - if (i-- == 0) - break; - cleanup_entry(iter1, net); - } - xt_free_table_info(newinfo); - return ret; + for (i = 0; i < NF_INET_NUMHOOKS; i++) { + repl.hook_entry[i] = newinfo->hook_entry[i]; + repl.underflow[i] = newinfo->underflow[i]; } + repl.num_counters = 0; + repl.counters = NULL; + repl.size = newinfo->size; + ret = translate_table(net, newinfo, entry1, &repl); + if (ret) + goto free_newinfo; + *pinfo = newinfo; *pentry0 = entry1; xt_free_table_info(info); @@ -1785,17 +1684,16 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); -out: + return ret; +out_unlock: + xt_compat_flush_offsets(AF_INET6); + xt_compat_unlock(AF_INET6); xt_entry_foreach(iter0, entry0, compatr->size) { if (j-- == 0) break; compat_release_entry(iter0); } return ret; -out_unlock: - xt_compat_flush_offsets(AF_INET6); - xt_compat_unlock(AF_INET6); - goto out; } static int diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 7e7173b68344..9ec23ffa43b4 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -533,6 +533,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; int pad, off = xt_compat_match_offset(match); u_int16_t msize = cm->u.user.match_size; + char name[sizeof(m->u.user.name)]; m = *dstptr; memcpy(m, cm, sizeof(*cm)); @@ -546,6 +547,9 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, msize += off; m->u.user.match_size = msize; + strlcpy(name, match->name, sizeof(name)); + module_put(match->me); + strncpy(m->u.user.name, name, sizeof(m->u.user.name)); *size += off; *dstptr += msize; @@ -763,6 +767,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; int pad, off = xt_compat_target_offset(target); u_int16_t tsize = ct->u.user.target_size; + char name[sizeof(t->u.user.name)]; t = *dstptr; memcpy(t, ct, sizeof(*ct)); @@ -776,6 +781,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, tsize += off; t->u.user.target_size = tsize; + strlcpy(name, target->name, sizeof(name)); + module_put(target->me); + strncpy(t->u.user.name, name, sizeof(t->u.user.name)); *size += off; *dstptr += tsize; -- GitLab From 95609155d7fa08cc2e71d494acad39f72f0b4495 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:35 +0200 Subject: [PATCH 2643/9938] netfilter: x_tables: remove obsolete overflow check for compat case too commit 9e67d5a739327c44885adebb4f3a538050be73e4 ("[NETFILTER]: x_tables: remove obsolete overflow check") left the compat parts alone, but we can kill it there as well. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 2 -- net/ipv4/netfilter/ip_tables.c | 2 -- net/ipv6/netfilter/ip6_tables.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 705179b0fd23..668c5dcb3a5f 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1436,8 +1436,6 @@ static int compat_do_replace(struct net *net, void __user *user, return -EFAULT; /* overflow check */ - if (tmp.size >= INT_MAX / num_possible_cpus()) - return -ENOMEM; if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; if (tmp.num_counters == 0) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index c26ccd818e8f..4585aa78c4ca 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1706,8 +1706,6 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return -EFAULT; /* overflow check */ - if (tmp.size >= INT_MAX / num_possible_cpus()) - return -ENOMEM; if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; if (tmp.num_counters == 0) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index f5a4eb2d5084..fd06251f504c 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1709,8 +1709,6 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return -EFAULT; /* overflow check */ - if (tmp.size >= INT_MAX / num_possible_cpus()) - return -ENOMEM; if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) return -ENOMEM; if (tmp.num_counters == 0) -- GitLab From aded9f3e9fa8db559c5b7661bbb497754270e754 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 14:17:36 +0200 Subject: [PATCH 2644/9938] netfilter: x_tables: remove obsolete check Since 'netfilter: x_tables: validate targets of jumps' change we validate that the target aligns exactly with beginning of a rule, so offset test is now redundant. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 8 -------- net/ipv4/netfilter/ip_tables.c | 7 ------- net/ipv6/netfilter/ip6_tables.c | 7 ------- 3 files changed, 22 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 668c5dcb3a5f..8cefb7a2606b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -461,14 +461,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo, if (strcmp(t->target.u.user.name, XT_STANDARD_TARGET) == 0 && newpos >= 0) { - if (newpos > newinfo->size - - sizeof(struct arpt_entry)) { - duprintf("mark_source_chains: " - "bad verdict (%i)\n", - newpos); - return 0; - } - /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 4585aa78c4ca..9340ce0a7549 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -542,13 +542,6 @@ mark_source_chains(const struct xt_table_info *newinfo, if (strcmp(t->target.u.user.name, XT_STANDARD_TARGET) == 0 && newpos >= 0) { - if (newpos > newinfo->size - - sizeof(struct ipt_entry)) { - duprintf("mark_source_chains: " - "bad verdict (%i)\n", - newpos); - return 0; - } /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index fd06251f504c..aa010856a255 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -554,13 +554,6 @@ mark_source_chains(const struct xt_table_info *newinfo, if (strcmp(t->target.u.user.name, XT_STANDARD_TARGET) == 0 && newpos >= 0) { - if (newpos > newinfo->size - - sizeof(struct ip6t_entry)) { - duprintf("mark_source_chains: " - "bad verdict (%i)\n", - newpos); - return 0; - } /* This a jump; chase it. */ duprintf("Jump rule %u -> %u\n", pos, newpos); -- GitLab From d7591f0c41ce3e67600a982bab6989ef0f07b3ce Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 1 Apr 2016 15:37:59 +0200 Subject: [PATCH 2645/9938] netfilter: x_tables: introduce and use xt_copy_counters_from_user The three variants use same copy&pasted code, condense this into a helper and use that. Make sure info.name is 0-terminated. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/x_tables.h | 3 ++ net/ipv4/netfilter/arp_tables.c | 48 ++----------------- net/ipv4/netfilter/ip_tables.c | 48 ++----------------- net/ipv6/netfilter/ip6_tables.c | 49 ++------------------ net/netfilter/x_tables.c | 74 ++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 130 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index e2da9b90f1b8..4dd9306c9d56 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -251,6 +251,9 @@ int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto, int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto, bool inv_proto); +void *xt_copy_counters_from_user(const void __user *user, unsigned int len, + struct xt_counters_info *info, bool compat); + struct xt_table *xt_register_table(struct net *net, const struct xt_table *table, struct xt_table_info *bootstrap, diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 8cefb7a2606b..60f5161abcb4 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1123,55 +1123,17 @@ static int do_add_counters(struct net *net, const void __user *user, unsigned int i; struct xt_counters_info tmp; struct xt_counters *paddc; - unsigned int num_counters; - const char *name; - int size; - void *ptmp; struct xt_table *t; const struct xt_table_info *private; int ret = 0; struct arpt_entry *iter; unsigned int addend; -#ifdef CONFIG_COMPAT - struct compat_xt_counters_info compat_tmp; - - if (compat) { - ptmp = &compat_tmp; - size = sizeof(struct compat_xt_counters_info); - } else -#endif - { - ptmp = &tmp; - size = sizeof(struct xt_counters_info); - } - if (copy_from_user(ptmp, user, size) != 0) - return -EFAULT; - -#ifdef CONFIG_COMPAT - if (compat) { - num_counters = compat_tmp.num_counters; - name = compat_tmp.name; - } else -#endif - { - num_counters = tmp.num_counters; - name = tmp.name; - } - - if (len != size + num_counters * sizeof(struct xt_counters)) - return -EINVAL; - - paddc = vmalloc(len - size); - if (!paddc) - return -ENOMEM; - - if (copy_from_user(paddc, user + size, len - size) != 0) { - ret = -EFAULT; - goto free; - } + paddc = xt_copy_counters_from_user(user, len, &tmp, compat); + if (IS_ERR(paddc)) + return PTR_ERR(paddc); - t = xt_find_table_lock(net, NFPROTO_ARP, name); + t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name); if (IS_ERR_OR_NULL(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1179,7 +1141,7 @@ static int do_add_counters(struct net *net, const void __user *user, local_bh_disable(); private = t->private; - if (private->number != num_counters) { + if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 9340ce0a7549..735d1ee8c1ab 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1307,55 +1307,17 @@ do_add_counters(struct net *net, const void __user *user, unsigned int i; struct xt_counters_info tmp; struct xt_counters *paddc; - unsigned int num_counters; - const char *name; - int size; - void *ptmp; struct xt_table *t; const struct xt_table_info *private; int ret = 0; struct ipt_entry *iter; unsigned int addend; -#ifdef CONFIG_COMPAT - struct compat_xt_counters_info compat_tmp; - - if (compat) { - ptmp = &compat_tmp; - size = sizeof(struct compat_xt_counters_info); - } else -#endif - { - ptmp = &tmp; - size = sizeof(struct xt_counters_info); - } - if (copy_from_user(ptmp, user, size) != 0) - return -EFAULT; - -#ifdef CONFIG_COMPAT - if (compat) { - num_counters = compat_tmp.num_counters; - name = compat_tmp.name; - } else -#endif - { - num_counters = tmp.num_counters; - name = tmp.name; - } - - if (len != size + num_counters * sizeof(struct xt_counters)) - return -EINVAL; - - paddc = vmalloc(len - size); - if (!paddc) - return -ENOMEM; - - if (copy_from_user(paddc, user + size, len - size) != 0) { - ret = -EFAULT; - goto free; - } + paddc = xt_copy_counters_from_user(user, len, &tmp, compat); + if (IS_ERR(paddc)) + return PTR_ERR(paddc); - t = xt_find_table_lock(net, AF_INET, name); + t = xt_find_table_lock(net, AF_INET, tmp.name); if (IS_ERR_OR_NULL(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1363,7 +1325,7 @@ do_add_counters(struct net *net, const void __user *user, local_bh_disable(); private = t->private; - if (private->number != num_counters) { + if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index aa010856a255..73e606c719ef 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1319,55 +1319,16 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, unsigned int i; struct xt_counters_info tmp; struct xt_counters *paddc; - unsigned int num_counters; - char *name; - int size; - void *ptmp; struct xt_table *t; const struct xt_table_info *private; int ret = 0; struct ip6t_entry *iter; unsigned int addend; -#ifdef CONFIG_COMPAT - struct compat_xt_counters_info compat_tmp; - - if (compat) { - ptmp = &compat_tmp; - size = sizeof(struct compat_xt_counters_info); - } else -#endif - { - ptmp = &tmp; - size = sizeof(struct xt_counters_info); - } - - if (copy_from_user(ptmp, user, size) != 0) - return -EFAULT; - -#ifdef CONFIG_COMPAT - if (compat) { - num_counters = compat_tmp.num_counters; - name = compat_tmp.name; - } else -#endif - { - num_counters = tmp.num_counters; - name = tmp.name; - } - - if (len != size + num_counters * sizeof(struct xt_counters)) - return -EINVAL; - - paddc = vmalloc(len - size); - if (!paddc) - return -ENOMEM; - - if (copy_from_user(paddc, user + size, len - size) != 0) { - ret = -EFAULT; - goto free; - } - t = xt_find_table_lock(net, AF_INET6, name); + paddc = xt_copy_counters_from_user(user, len, &tmp, compat); + if (IS_ERR(paddc)) + return PTR_ERR(paddc); + t = xt_find_table_lock(net, AF_INET6, tmp.name); if (IS_ERR_OR_NULL(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1375,7 +1336,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, local_bh_disable(); private = t->private; - if (private->number != num_counters) { + if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 9ec23ffa43b4..c69c892231d7 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -752,6 +752,80 @@ int xt_check_target(struct xt_tgchk_param *par, } EXPORT_SYMBOL_GPL(xt_check_target); +/** + * xt_copy_counters_from_user - copy counters and metadata from userspace + * + * @user: src pointer to userspace memory + * @len: alleged size of userspace memory + * @info: where to store the xt_counters_info metadata + * @compat: true if we setsockopt call is done by 32bit task on 64bit kernel + * + * Copies counter meta data from @user and stores it in @info. + * + * vmallocs memory to hold the counters, then copies the counter data + * from @user to the new memory and returns a pointer to it. + * + * If @compat is true, @info gets converted automatically to the 64bit + * representation. + * + * The metadata associated with the counters is stored in @info. + * + * Return: returns pointer that caller has to test via IS_ERR(). + * If IS_ERR is false, caller has to vfree the pointer. + */ +void *xt_copy_counters_from_user(const void __user *user, unsigned int len, + struct xt_counters_info *info, bool compat) +{ + void *mem; + u64 size; + +#ifdef CONFIG_COMPAT + if (compat) { + /* structures only differ in size due to alignment */ + struct compat_xt_counters_info compat_tmp; + + if (len <= sizeof(compat_tmp)) + return ERR_PTR(-EINVAL); + + len -= sizeof(compat_tmp); + if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0) + return ERR_PTR(-EFAULT); + + strlcpy(info->name, compat_tmp.name, sizeof(info->name)); + info->num_counters = compat_tmp.num_counters; + user += sizeof(compat_tmp); + } else +#endif + { + if (len <= sizeof(*info)) + return ERR_PTR(-EINVAL); + + len -= sizeof(*info); + if (copy_from_user(info, user, sizeof(*info)) != 0) + return ERR_PTR(-EFAULT); + + info->name[sizeof(info->name) - 1] = '\0'; + user += sizeof(*info); + } + + size = sizeof(struct xt_counters); + size *= info->num_counters; + + if (size != (u64)len) + return ERR_PTR(-EINVAL); + + mem = vmalloc(len); + if (!mem) + return ERR_PTR(-ENOMEM); + + if (copy_from_user(mem, user, len) == 0) + return mem; + + vfree(mem); + return ERR_PTR(-EFAULT); +} +EXPORT_SYMBOL_GPL(xt_copy_counters_from_user); + #ifdef CONFIG_COMPAT int xt_compat_target_offset(const struct xt_target *target) { -- GitLab From 4054ff45454a9a4652e29ac750a6600f6fdcc216 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 12 Apr 2016 23:32:34 +0200 Subject: [PATCH 2646/9938] netfilter: ctnetlink: remove unnecessary inlining Many of these functions are called from control plane path. Move ctnetlink_nlmsg_size() under CONFIG_NF_CONNTRACK_EVENTS to avoid a compilation warning when CONFIG_NF_CONNTRACK_EVENTS=n. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 117 +++++++++++---------------- 1 file changed, 48 insertions(+), 69 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 355e8552fd5b..caa4efe5930b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -58,10 +58,9 @@ MODULE_LICENSE("GPL"); static char __initdata version[] = "0.93"; -static inline int -ctnetlink_dump_tuples_proto(struct sk_buff *skb, - const struct nf_conntrack_tuple *tuple, - struct nf_conntrack_l4proto *l4proto) +static int ctnetlink_dump_tuples_proto(struct sk_buff *skb, + const struct nf_conntrack_tuple *tuple, + struct nf_conntrack_l4proto *l4proto) { int ret = 0; struct nlattr *nest_parms; @@ -83,10 +82,9 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb, return -1; } -static inline int -ctnetlink_dump_tuples_ip(struct sk_buff *skb, - const struct nf_conntrack_tuple *tuple, - struct nf_conntrack_l3proto *l3proto) +static int ctnetlink_dump_tuples_ip(struct sk_buff *skb, + const struct nf_conntrack_tuple *tuple, + struct nf_conntrack_l3proto *l3proto) { int ret = 0; struct nlattr *nest_parms; @@ -106,9 +104,8 @@ ctnetlink_dump_tuples_ip(struct sk_buff *skb, return -1; } -static int -ctnetlink_dump_tuples(struct sk_buff *skb, - const struct nf_conntrack_tuple *tuple) +static int ctnetlink_dump_tuples(struct sk_buff *skb, + const struct nf_conntrack_tuple *tuple) { int ret; struct nf_conntrack_l3proto *l3proto; @@ -127,9 +124,8 @@ ctnetlink_dump_tuples(struct sk_buff *skb, return ret; } -static inline int -ctnetlink_dump_zone_id(struct sk_buff *skb, int attrtype, - const struct nf_conntrack_zone *zone, int dir) +static int ctnetlink_dump_zone_id(struct sk_buff *skb, int attrtype, + const struct nf_conntrack_zone *zone, int dir) { if (zone->id == NF_CT_DEFAULT_ZONE_ID || zone->dir != dir) return 0; @@ -141,8 +137,7 @@ ctnetlink_dump_zone_id(struct sk_buff *skb, int attrtype, return -1; } -static inline int -ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct) { if (nla_put_be32(skb, CTA_STATUS, htonl(ct->status))) goto nla_put_failure; @@ -152,8 +147,7 @@ ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct) return -1; } -static inline int -ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) { long timeout = ((long)ct->timeout.expires - (long)jiffies) / HZ; @@ -168,8 +162,7 @@ ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) return -1; } -static inline int -ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct) +static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct) { struct nf_conntrack_l4proto *l4proto; struct nlattr *nest_proto; @@ -193,8 +186,8 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct) return -1; } -static inline int -ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_helpinfo(struct sk_buff *skb, + const struct nf_conn *ct) { struct nlattr *nest_helper; const struct nf_conn_help *help = nfct_help(ct); @@ -300,8 +293,7 @@ ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) } #ifdef CONFIG_NF_CONNTRACK_MARK -static inline int -ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) { if (nla_put_be32(skb, CTA_MARK, htonl(ct->mark))) goto nla_put_failure; @@ -315,8 +307,7 @@ ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK -static inline int -ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) { struct nlattr *nest_secctx; int len, ret; @@ -380,8 +371,7 @@ ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple) -static inline int -ctnetlink_dump_master(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_master(struct sk_buff *skb, const struct nf_conn *ct) { struct nlattr *nest_parms; @@ -426,8 +416,8 @@ dump_ct_seq_adj(struct sk_buff *skb, const struct nf_ct_seqadj *seq, int type) return -1; } -static inline int -ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, + const struct nf_conn *ct) { struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); struct nf_ct_seqadj *seq; @@ -446,8 +436,7 @@ ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, const struct nf_conn *ct) return 0; } -static inline int -ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) { if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct))) goto nla_put_failure; @@ -457,8 +446,7 @@ ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) return -1; } -static inline int -ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct) +static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct) { if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use)))) goto nla_put_failure; @@ -538,8 +526,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, return -1; } -static inline size_t -ctnetlink_proto_size(const struct nf_conn *ct) +static size_t ctnetlink_proto_size(const struct nf_conn *ct) { struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; @@ -556,8 +543,7 @@ ctnetlink_proto_size(const struct nf_conn *ct) return len; } -static inline size_t -ctnetlink_acct_size(const struct nf_conn *ct) +static size_t ctnetlink_acct_size(const struct nf_conn *ct) { if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT)) return 0; @@ -567,8 +553,7 @@ ctnetlink_acct_size(const struct nf_conn *ct) ; } -static inline int -ctnetlink_secctx_size(const struct nf_conn *ct) +static int ctnetlink_secctx_size(const struct nf_conn *ct) { #ifdef CONFIG_NF_CONNTRACK_SECMARK int len, ret; @@ -584,8 +569,7 @@ ctnetlink_secctx_size(const struct nf_conn *ct) #endif } -static inline size_t -ctnetlink_timestamp_size(const struct nf_conn *ct) +static size_t ctnetlink_timestamp_size(const struct nf_conn *ct) { #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP)) @@ -596,8 +580,8 @@ ctnetlink_timestamp_size(const struct nf_conn *ct) #endif } -static inline size_t -ctnetlink_nlmsg_size(const struct nf_conn *ct) +#ifdef CONFIG_NF_CONNTRACK_EVENTS +static size_t ctnetlink_nlmsg_size(const struct nf_conn *ct) { return NLMSG_ALIGN(sizeof(struct nfgenmsg)) + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ @@ -628,7 +612,6 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct) ; } -#ifdef CONFIG_NF_CONNTRACK_EVENTS static int ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) { @@ -891,8 +874,8 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; } -static inline int -ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple) +static int ctnetlink_parse_tuple_ip(struct nlattr *attr, + struct nf_conntrack_tuple *tuple) { struct nlattr *tb[CTA_IP_MAX+1]; struct nf_conntrack_l3proto *l3proto; @@ -921,9 +904,8 @@ static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = { [CTA_PROTO_NUM] = { .type = NLA_U8 }, }; -static inline int -ctnetlink_parse_tuple_proto(struct nlattr *attr, - struct nf_conntrack_tuple *tuple) +static int ctnetlink_parse_tuple_proto(struct nlattr *attr, + struct nf_conntrack_tuple *tuple) { struct nlattr *tb[CTA_PROTO_MAX+1]; struct nf_conntrack_l4proto *l4proto; @@ -1050,9 +1032,8 @@ static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = { .len = NF_CT_HELPER_NAME_LEN - 1 }, }; -static inline int -ctnetlink_parse_help(const struct nlattr *attr, char **helper_name, - struct nlattr **helpinfo) +static int ctnetlink_parse_help(const struct nlattr *attr, char **helper_name, + struct nlattr **helpinfo) { int err; struct nlattr *tb[CTA_HELP_MAX+1]; @@ -1463,8 +1444,8 @@ ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[]) #endif } -static inline int -ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) +static int ctnetlink_change_helper(struct nf_conn *ct, + const struct nlattr * const cda[]) { struct nf_conntrack_helper *helper; struct nf_conn_help *help = nfct_help(ct); @@ -1524,8 +1505,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) return -EOPNOTSUPP; } -static inline int -ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[]) +static int ctnetlink_change_timeout(struct nf_conn *ct, + const struct nlattr * const cda[]) { u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); @@ -1544,8 +1525,8 @@ static const struct nla_policy protoinfo_policy[CTA_PROTOINFO_MAX+1] = { [CTA_PROTOINFO_SCTP] = { .type = NLA_NESTED }, }; -static inline int -ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[]) +static int ctnetlink_change_protoinfo(struct nf_conn *ct, + const struct nlattr * const cda[]) { const struct nlattr *attr = cda[CTA_PROTOINFO]; struct nlattr *tb[CTA_PROTOINFO_MAX+1]; @@ -1571,8 +1552,8 @@ static const struct nla_policy seqadj_policy[CTA_SEQADJ_MAX+1] = { [CTA_SEQADJ_OFFSET_AFTER] = { .type = NLA_U32 }, }; -static inline int -change_seq_adj(struct nf_ct_seqadj *seq, const struct nlattr * const attr) +static int change_seq_adj(struct nf_ct_seqadj *seq, + const struct nlattr * const attr) { int err; struct nlattr *cda[CTA_SEQADJ_MAX+1]; @@ -2405,10 +2386,9 @@ static struct nfnl_ct_hook ctnetlink_glue_hook = { * EXPECT ***********************************************************************/ -static inline int -ctnetlink_exp_dump_tuple(struct sk_buff *skb, - const struct nf_conntrack_tuple *tuple, - enum ctattr_expect type) +static int ctnetlink_exp_dump_tuple(struct sk_buff *skb, + const struct nf_conntrack_tuple *tuple, + enum ctattr_expect type) { struct nlattr *nest_parms; @@ -2425,10 +2405,9 @@ ctnetlink_exp_dump_tuple(struct sk_buff *skb, return -1; } -static inline int -ctnetlink_exp_dump_mask(struct sk_buff *skb, - const struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_tuple_mask *mask) +static int ctnetlink_exp_dump_mask(struct sk_buff *skb, + const struct nf_conntrack_tuple *tuple, + const struct nf_conntrack_tuple_mask *mask) { int ret; struct nf_conntrack_l3proto *l3proto; -- GitLab From 9f9a45beaa96188085d52d273c2ecb052c7d8d27 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 7 Apr 2016 18:12:58 -0400 Subject: [PATCH 2647/9938] udp: do not expect udp headers on ioctl SIOCINQ On udp sockets, ioctl SIOCINQ returns the payload size of the first packet. Since commit e6afc8ace6dd pulled the headers, the result is incorrect when subtracting header length. Remove that operation. Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/ipv4/udp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 3563788d064f..d2d294b0a1f1 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1282,8 +1282,6 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) * of this packet since that is all * that will be read. */ - amount -= sizeof(struct udphdr); - return put_user(amount, (int __user *)arg); } -- GitLab From 31c2e4926fe912f88388bcaa8450fcaa8f2ece47 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 7 Apr 2016 18:12:59 -0400 Subject: [PATCH 2648/9938] udp: do not expect udp headers in recv cmsg IP_CMSG_CHECKSUM On udp sockets, recv cmsg IP_CMSG_CHECKSUM returns a checksum over the packet payload. Since commit e6afc8ace6dd pulled the headers, taking skb->data as the start of transport header is incorrect. Use the transport header pointer. Also, when peeking at an offset from the start of the packet, only return a checksum from the start of the peeked data. Note that the cmsg does not subtract a tail checkum when reading truncated data. Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/ipv4/ip_sockglue.c | 3 ++- net/ipv4/udp.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 89b5f3bd6694..279471c4e58f 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -106,7 +106,8 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, return; if (offset != 0) - csum = csum_sub(csum, csum_partial(skb->data, offset, 0)); + csum = csum_sub(csum, csum_partial(skb_transport_header(skb), + offset, 0)); put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d2d294b0a1f1..f1863136d3e4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1375,7 +1375,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, *addr_len = sizeof(*sin); } if (inet->cmsg_flags) - ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr)); + ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr) + off); err = copied; if (flags & MSG_TRUNC) -- GitLab From 18b46810eb61f1d1a66c5511d12e84ea8cb7f35c Mon Sep 17 00:00:00 2001 From: Alexandre TORGUE Date: Fri, 8 Apr 2016 11:18:03 +0200 Subject: [PATCH 2649/9938] net: ethernet: stmmac: GMAC4.xx: Fix TX descriptor preparation On GMAC4.xx each descriptor contains 2 buffers of 16KB (each). Initially, those 2 buffers was filled in dwmac4_rd_prepare_tx_desc but it is actually not needed. Indeed, stmmac driver supports frame up to 9000 bytes (jumbo). So only one buffer is needed. Reported-by: Dan Carpenter Signed-off-by: Alexandre TORGUE Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index d4952c7a836d..4ec7397e7fb3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -254,14 +254,7 @@ static void dwmac4_rd_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, { unsigned int tdes3 = p->des3; - if (unlikely(len > BUF_SIZE_16KiB)) { - p->des2 |= (((len - BUF_SIZE_16KiB) << - TDES2_BUFFER2_SIZE_MASK_SHIFT) - & TDES2_BUFFER2_SIZE_MASK) - | (BUF_SIZE_16KiB & TDES2_BUFFER1_SIZE_MASK); - } else { - p->des2 |= (len & TDES2_BUFFER1_SIZE_MASK); - } + p->des2 |= (len & TDES2_BUFFER1_SIZE_MASK); if (is_fs) tdes3 |= TDES3_FIRST_DESCRIPTOR; -- GitLab From fafc4e1ea1a4c1eb13a30c9426fb799f5efacbc3 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 8 Apr 2016 15:11:27 +0200 Subject: [PATCH 2650/9938] sock: tigthen lockdep checks for sock_owned_by_user sock_owned_by_user should not be used without socket lock held. It seems to be a common practice to check .owned before lock reclassification, so provide a little help to abstract this check away. Cc: linux-cifs@vger.kernel.org Cc: linux-bluetooth@vger.kernel.org Cc: linux-nfs@vger.kernel.org Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- fs/cifs/connect.c | 4 ++-- include/net/sock.h | 44 ++++++++++++++++++++++++------------ net/bluetooth/af_bluetooth.c | 2 +- net/llc/llc_proc.c | 2 +- net/sunrpc/svcsock.c | 3 +-- net/sunrpc/xprtsock.c | 3 +-- 6 files changed, 35 insertions(+), 23 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6f62ac821a84..2e2e0a6242d6 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2918,7 +2918,7 @@ static inline void cifs_reclassify_socket4(struct socket *sock) { struct sock *sk = sock->sk; - BUG_ON(sock_owned_by_user(sk)); + BUG_ON(!sock_allow_reclassification(sk)); sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS", &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]); } @@ -2927,7 +2927,7 @@ static inline void cifs_reclassify_socket6(struct socket *sock) { struct sock *sk = sock->sk; - BUG_ON(sock_owned_by_user(sk)); + BUG_ON(!sock_allow_reclassification(sk)); sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS", &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]); } diff --git a/include/net/sock.h b/include/net/sock.h index 81d6fecec0a2..baba58770ac5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1316,21 +1316,6 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) __kfree_skb(skb); } -/* Used by processes to "lock" a socket state, so that - * interrupts and bottom half handlers won't change it - * from under us. It essentially blocks any incoming - * packets, so that we won't get any new data or any - * packets that change the state of the socket. - * - * While locked, BH processing will add new packets to - * the backlog queue. This queue is processed by the - * owner of the socket lock right before it is released. - * - * Since ~2.3.5 it is also exclusive sleep lock serializing - * accesses from user process context. - */ -#define sock_owned_by_user(sk) ((sk)->sk_lock.owned) - static inline void sock_release_ownership(struct sock *sk) { if (sk->sk_lock.owned) { @@ -1403,6 +1388,35 @@ static inline void unlock_sock_fast(struct sock *sk, bool slow) spin_unlock_bh(&sk->sk_lock.slock); } +/* Used by processes to "lock" a socket state, so that + * interrupts and bottom half handlers won't change it + * from under us. It essentially blocks any incoming + * packets, so that we won't get any new data or any + * packets that change the state of the socket. + * + * While locked, BH processing will add new packets to + * the backlog queue. This queue is processed by the + * owner of the socket lock right before it is released. + * + * Since ~2.3.5 it is also exclusive sleep lock serializing + * accesses from user process context. + */ + +static inline bool sock_owned_by_user(const struct sock *sk) +{ +#ifdef CONFIG_LOCKDEP + WARN_ON(!lockdep_sock_is_held(sk)); +#endif + return sk->sk_lock.owned; +} + +/* no reclassification while locks are held */ +static inline bool sock_allow_reclassification(const struct sock *csk) +{ + struct sock *sk = (struct sock *)csk; + + return !sk->sk_lock.owned && !spin_is_locked(&sk->sk_lock.slock); +} struct sock *sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot, int kern); diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 955eda93e66f..3df7aefb7663 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -65,7 +65,7 @@ static const char *const bt_slock_key_strings[BT_MAX_PROTO] = { void bt_sock_reclassify_lock(struct sock *sk, int proto) { BUG_ON(!sk); - BUG_ON(sock_owned_by_user(sk)); + BUG_ON(!sock_allow_reclassification(sk)); sock_lock_init_class_and_name(sk, bt_slock_key_strings[proto], &bt_slock_key[proto], diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index 1a3c7e0f5d0d..29c509c54bb2 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c @@ -195,7 +195,7 @@ static int llc_seq_core_show(struct seq_file *seq, void *v) timer_pending(&llc->pf_cycle_timer.timer), timer_pending(&llc->rej_sent_timer.timer), timer_pending(&llc->busy_state_timer.timer), - !!sk->sk_backlog.tail, !!sock_owned_by_user(sk)); + !!sk->sk_backlog.tail, !!sk->sk_lock.owned); out: return 0; } diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 71d6072664d2..dadfec66dbd8 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -85,8 +85,7 @@ static void svc_reclassify_socket(struct socket *sock) { struct sock *sk = sock->sk; - WARN_ON_ONCE(sock_owned_by_user(sk)); - if (sock_owned_by_user(sk)) + if (WARN_ON_ONCE(!sock_allow_reclassification(sk))) return; switch (sk->sk_family) { diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c1fc7b20bbc1..d0756ac5c0f2 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1880,8 +1880,7 @@ static inline void xs_reclassify_socket6(struct socket *sock) static inline void xs_reclassify_socket(int family, struct socket *sock) { - WARN_ON_ONCE(sock_owned_by_user(sock->sk)); - if (sock_owned_by_user(sock->sk)) + if (WARN_ON_ONCE(!sock_allow_reclassification(sock->sk))) return; switch (family) { -- GitLab From 47e27d5e92c46a3a62d4dfd8895b1ddb8613f531 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 8 Apr 2016 15:55:00 +0200 Subject: [PATCH 2651/9938] ipv6, token: allow for clearing the current device token The original tokenized iid support implemented via f53adae4eae5 ("net: ipv6: add tokenized interface identifier support") didn't allow for clearing a device token as it was intended that this addressing mode was the only one active for globally scoped IPv6 addresses. Later we relaxed that restriction via 617fe29d45bd ("net: ipv6: only invalidate previously tokenized addresses"), and we should also allow for clearing tokens as there's no good reason why it shouldn't be allowed. Fixes: 617fe29d45bd ("net: ipv6: only invalidate previously tokenized addresses") Reported-by: Robin H. Johnson Signed-off-by: Daniel Borkmann Cc: Hannes Frederic Sowa Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 27aed1afcf81..a6c99275bd8c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4995,15 +4995,13 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) { struct inet6_ifaddr *ifp; struct net_device *dev = idev->dev; - bool update_rs = false; + bool clear_token, update_rs = false; struct in6_addr ll_addr; ASSERT_RTNL(); if (!token) return -EINVAL; - if (ipv6_addr_any(token)) - return -EINVAL; if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) return -EINVAL; if (!ipv6_accept_ra(idev)) @@ -5018,10 +5016,13 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) write_unlock_bh(&idev->lock); + clear_token = ipv6_addr_any(token); + if (clear_token) + goto update_lft; + if (!idev->dead && (idev->if_flags & IF_READY) && !ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE | IFA_F_OPTIMISTIC)) { - /* If we're not ready, then normal ifup will take care * of this. Otherwise, we need to request our rs here. */ @@ -5029,6 +5030,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) update_rs = true; } +update_lft: write_lock_bh(&idev->lock); if (update_rs) { -- GitLab From bf91795e4a77eb75602702e4c4d9b98b155039e9 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sat, 9 Apr 2016 00:00:25 +0900 Subject: [PATCH 2652/9938] Doc: networking: Fix typo in dsa This patch fix typos in Documentation/networking/dsa. Signed-off-by: Masanari Iida Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- Documentation/networking/dsa/bcm_sf2.txt | 2 +- Documentation/networking/dsa/dsa.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/dsa/bcm_sf2.txt b/Documentation/networking/dsa/bcm_sf2.txt index d999d0c1c5b8..eba3a2431e91 100644 --- a/Documentation/networking/dsa/bcm_sf2.txt +++ b/Documentation/networking/dsa/bcm_sf2.txt @@ -38,7 +38,7 @@ Implementation details ====================== The driver is located in drivers/net/dsa/bcm_sf2.c and is implemented as a DSA -driver; see Documentation/networking/dsa/dsa.txt for details on the subsytem +driver; see Documentation/networking/dsa/dsa.txt for details on the subsystem and what it provides. The SF2 switch is configured to enable a Broadcom specific 4-bytes switch tag diff --git a/Documentation/networking/dsa/dsa.txt b/Documentation/networking/dsa/dsa.txt index ba698c56919d..631b0f7ae16f 100644 --- a/Documentation/networking/dsa/dsa.txt +++ b/Documentation/networking/dsa/dsa.txt @@ -334,7 +334,7 @@ more specifically with its VLAN filtering portion when configuring VLANs on top of per-port slave network devices. Since DSA primarily deals with MDIO-connected switches, although not exclusively, SWITCHDEV's prepare/abort/commit phases are often simplified into a prepare phase which -checks whether the operation is supporte by the DSA switch driver, and a commit +checks whether the operation is supported by the DSA switch driver, and a commit phase which applies the changes. As of today, the only SWITCHDEV objects supported by DSA are the FDB and VLAN -- GitLab From f9a7cbbf18f1640907d6ca345b8337e4b50ea56f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 8 Apr 2016 17:51:54 +0200 Subject: [PATCH 2653/9938] net: force inlining of netif_tx_start/stop_queue, sock_hold, __sock_put Sometimes gcc mysteriously doesn't inline very small functions we expect to be inlined. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66122 Arguably, gcc should do better, but gcc people aren't willing to invest time into it, asking to use __always_inline instead. With this .config: http://busybox.net/~vda/kernel_config_OPTIMIZE_INLINING_and_Os, the following functions get deinlined many times. netif_tx_stop_queue: 207 copies, 590 calls: 55 push %rbp 48 89 e5 mov %rsp,%rbp f0 80 8f e0 01 00 00 01 lock orb $0x1,0x1e0(%rdi) 5d pop %rbp c3 retq netif_tx_start_queue: 47 copies, 111 calls 55 push %rbp 48 89 e5 mov %rsp,%rbp f0 80 a7 e0 01 00 00 fe lock andb $0xfe,0x1e0(%rdi) 5d pop %rbp c3 retq sock_hold: 39 copies, 124 calls 55 push %rbp 48 89 e5 mov %rsp,%rbp f0 ff 87 80 00 00 00 lock incl 0x80(%rdi) 5d pop %rbp c3 retq __sock_put: 6 copies, 13 calls 55 push %rbp 48 89 e5 mov %rsp,%rbp f0 ff 8f 80 00 00 00 lock decl 0x80(%rdi) 5d pop %rbp c3 retq This patch fixes this via s/inline/__always_inline/. Code size decrease after the patch is ~2.5k: text data bss dec hex filename 56719876 56364551 36196352 149280779 8e5d80b vmlinux_before 56717440 56364551 36196352 149278343 8e5ce87 vmlinux Signed-off-by: Denys Vlasenko CC: David S. Miller CC: linux-kernel@vger.kernel.org CC: netdev@vger.kernel.org CC: netfilter-devel@vger.kernel.org Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 ++-- include/net/sock.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 166402ae3324..e906c6570b38 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2787,7 +2787,7 @@ static inline void netif_tx_schedule_all(struct net_device *dev) netif_schedule_queue(netdev_get_tx_queue(dev, i)); } -static inline void netif_tx_start_queue(struct netdev_queue *dev_queue) +static __always_inline void netif_tx_start_queue(struct netdev_queue *dev_queue) { clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state); } @@ -2837,7 +2837,7 @@ static inline void netif_tx_wake_all_queues(struct net_device *dev) } } -static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue) +static __always_inline void netif_tx_stop_queue(struct netdev_queue *dev_queue) { set_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state); } diff --git a/include/net/sock.h b/include/net/sock.h index baba58770ac5..d997ec13a643 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -569,7 +569,7 @@ static inline bool __sk_del_node_init(struct sock *sk) modifications. */ -static inline void sock_hold(struct sock *sk) +static __always_inline void sock_hold(struct sock *sk) { atomic_inc(&sk->sk_refcnt); } @@ -577,7 +577,7 @@ static inline void sock_hold(struct sock *sk) /* Ungrab socket in the context, which assumes that socket refcnt cannot hit zero, f.e. it is true in context of any socketcall. */ -static inline void __sock_put(struct sock *sk) +static __always_inline void __sock_put(struct sock *sk) { atomic_dec(&sk->sk_refcnt); } -- GitLab From 14f31bb39f5d4b69c179d219833d7edb9b36ebd9 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 9 Apr 2016 00:03:28 +0800 Subject: [PATCH 2654/9938] bridge: simplify the flush_store by calling store_bridge_parm There are some repetitive codes in flush_store, we can remove them by calling store_bridge_parm, also, it would send rtnl notification after we add it in store_bridge_parm in the following patches. Signed-off-by: Xin Long Reviewed-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_sysfs_br.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 6b8091407ca3..c48f6b0b2022 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -336,17 +336,17 @@ static ssize_t group_addr_store(struct device *d, static DEVICE_ATTR_RW(group_addr); +static int set_flush(struct net_bridge *br, unsigned long val) +{ + br_fdb_flush(br); + return 0; +} + static ssize_t flush_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - struct net_bridge *br = to_bridge(d); - - if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) - return -EPERM; - - br_fdb_flush(br); - return len; + return store_bridge_parm(d, buf, len, set_flush); } static DEVICE_ATTR_WO(flush); -- GitLab From 347db6b49ec0ba5ee3c9d946d45b7db59cf40480 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 9 Apr 2016 00:03:29 +0800 Subject: [PATCH 2655/9938] bridge: simplify the forward_delay_store by calling store_bridge_parm There are some repetitive codes in forward_delay_store, we can remove them by calling store_bridge_parm. Signed-off-by: Xin Long Reviewed-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_sysfs_br.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index c48f6b0b2022..137cd3bf2565 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -160,29 +160,22 @@ static ssize_t group_fwd_mask_show(struct device *d, return sprintf(buf, "%#x\n", br->group_fwd_mask); } - -static ssize_t group_fwd_mask_store(struct device *d, - struct device_attribute *attr, - const char *buf, - size_t len) +static int set_group_fwd_mask(struct net_bridge *br, unsigned long val) { - struct net_bridge *br = to_bridge(d); - char *endp; - unsigned long val; - - if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) - return -EPERM; - - val = simple_strtoul(buf, &endp, 0); - if (endp == buf) - return -EINVAL; - if (val & BR_GROUPFWD_RESTRICTED) return -EINVAL; br->group_fwd_mask = val; - return len; + return 0; +} + +static ssize_t group_fwd_mask_store(struct device *d, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return store_bridge_parm(d, buf, len, set_group_fwd_mask); } static DEVICE_ATTR_RW(group_fwd_mask); -- GitLab From 4436156b6fbec746108d45431a9f1885de810ec1 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 9 Apr 2016 00:03:30 +0800 Subject: [PATCH 2656/9938] bridge: simplify the stp_state_store by calling store_bridge_parm There are some repetitive codes in stp_state_store, we can remove them by calling store_bridge_parm. Signed-off-by: Xin Long Reviewed-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_sysfs_br.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 137cd3bf2565..f9d484ecae07 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -128,27 +128,21 @@ static ssize_t stp_state_show(struct device *d, } -static ssize_t stp_state_store(struct device *d, - struct device_attribute *attr, const char *buf, - size_t len) +static int set_stp_state(struct net_bridge *br, unsigned long val) { - struct net_bridge *br = to_bridge(d); - char *endp; - unsigned long val; - - if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) - return -EPERM; - - val = simple_strtoul(buf, &endp, 0); - if (endp == buf) - return -EINVAL; - if (!rtnl_trylock()) return restart_syscall(); br_stp_set_enabled(br, val); rtnl_unlock(); - return len; + return 0; +} + +static ssize_t stp_state_store(struct device *d, + struct device_attribute *attr, const char *buf, + size_t len) +{ + return store_bridge_parm(d, buf, len, set_stp_state); } static DEVICE_ATTR_RW(stp_state); -- GitLab From 047831a9b9c3e34410025df84f629c005f437e42 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 9 Apr 2016 00:03:31 +0800 Subject: [PATCH 2657/9938] bridge: a netlink notification should be sent when those attributes are changed by br_sysfs_br Now when we change the attributes of bridge or br_port by netlink, a relevant netlink notification will be sent, but if we change them by ioctl or sysfs, no notification will be sent. We should ensure that whenever those attributes change internally or from sysfs/ioctl, that a netlink notification is sent out to listeners. Also, NetworkManager will use this in the future to listen for out-of-band bridge master attribute updates and incorporate them into the runtime configuration. This patch is used for br_sysfs_br. and we also need to remove some rtnl_trylock in old functions so that we can call it in a common one. For group_addr_store, we cannot make it use store_bridge_parm, because it's not a string-to-long convert, we will add notification on it individually. Signed-off-by: Xin Long Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_sysfs_br.c | 21 +++++++++------------ net/bridge/br_vlan.c | 30 +++++------------------------- 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index f9d484ecae07..70bddfd0f3e9 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -43,7 +43,14 @@ static ssize_t store_bridge_parm(struct device *d, if (endp == buf) return -EINVAL; + if (!rtnl_trylock()) + return restart_syscall(); + err = (*set)(br, val); + if (!err) + netdev_state_change(br->dev); + rtnl_unlock(); + return err ? err : len; } @@ -101,15 +108,7 @@ static ssize_t ageing_time_show(struct device *d, static int set_ageing_time(struct net_bridge *br, unsigned long val) { - int ret; - - if (!rtnl_trylock()) - return restart_syscall(); - - ret = br_set_ageing_time(br, val); - rtnl_unlock(); - - return ret; + return br_set_ageing_time(br, val); } static ssize_t ageing_time_store(struct device *d, @@ -130,10 +129,7 @@ static ssize_t stp_state_show(struct device *d, static int set_stp_state(struct net_bridge *br, unsigned long val) { - if (!rtnl_trylock()) - return restart_syscall(); br_stp_set_enabled(br, val); - rtnl_unlock(); return 0; } @@ -315,6 +311,7 @@ static ssize_t group_addr_store(struct device *d, br->group_addr_set = true; br_recalculate_fwd_mask(br); + netdev_state_change(br->dev); rtnl_unlock(); diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 9309bb4f2a5b..e001152d6ad1 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -651,15 +651,7 @@ int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) { - int err; - - if (!rtnl_trylock()) - return restart_syscall(); - - err = __br_vlan_filter_toggle(br, val); - rtnl_unlock(); - - return err; + return __br_vlan_filter_toggle(br, val); } int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) @@ -713,18 +705,10 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) int br_vlan_set_proto(struct net_bridge *br, unsigned long val) { - int err; - if (val != ETH_P_8021Q && val != ETH_P_8021AD) return -EPROTONOSUPPORT; - if (!rtnl_trylock()) - return restart_syscall(); - - err = __br_vlan_set_proto(br, htons(val)); - rtnl_unlock(); - - return err; + return __br_vlan_set_proto(br, htons(val)); } static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid) @@ -855,21 +839,17 @@ int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) if (val >= VLAN_VID_MASK) return -EINVAL; - if (!rtnl_trylock()) - return restart_syscall(); - if (pvid == br->default_pvid) - goto unlock; + goto out; /* Only allow default pvid change when filtering is disabled */ if (br->vlan_enabled) { pr_info_once("Please disable vlan filtering to change default_pvid\n"); err = -EPERM; - goto unlock; + goto out; } err = __br_vlan_set_default_pvid(br, pvid); -unlock: - rtnl_unlock(); +out: return err; } -- GitLab From bdaf0d5d98e1c42d3a48c5ce6db9d013cb882781 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 9 Apr 2016 00:03:32 +0800 Subject: [PATCH 2658/9938] bridge: a netlink notification should be sent when those attributes are changed by br_sysfs_if Now when we change the attributes of bridge or br_port by netlink, a relevant netlink notification will be sent, but if we change them by ioctl or sysfs, no notification will be sent. We should ensure that whenever those attributes change internally or from sysfs/ioctl, that a netlink notification is sent out to listeners. Also, NetworkManager will use this in the future to listen for out-of-band bridge master attribute updates and incorporate them into the runtime configuration. This patch is used for br_sysfs_if, and we also move br_ifinfo_notify out of store_flag. Signed-off-by: Xin Long Reviewed-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_sysfs_if.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index efe415ad842a..1e04d4d44273 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -61,7 +61,6 @@ static int store_flag(struct net_bridge_port *p, unsigned long v, if (flags != p->flags) { p->flags = flags; br_port_flags_change(p, mask); - br_ifinfo_notify(RTM_NEWLINK, p); } return 0; } @@ -253,8 +252,10 @@ static ssize_t brport_store(struct kobject *kobj, spin_lock_bh(&p->br->lock); ret = brport_attr->store(p, val); spin_unlock_bh(&p->br->lock); - if (ret == 0) + if (!ret) { + br_ifinfo_notify(RTM_NEWLINK, p); ret = count; + } } rtnl_unlock(); } -- GitLab From bf871ad792e3c9f5dda0ef5bd519e0a2f1564001 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 9 Apr 2016 00:03:33 +0800 Subject: [PATCH 2659/9938] bridge: a netlink notification should be sent when those attributes are changed by ioctl Now when we change the attributes of bridge or br_port by netlink, a relevant netlink notification will be sent, but if we change them by ioctl or sysfs, no notification will be sent. We should ensure that whenever those attributes change internally or from sysfs/ioctl, that a netlink notification is sent out to listeners. Also, NetworkManager will use this in the future to listen for out-of-band bridge master attribute updates and incorporate them into the runtime configuration. This patch is used for ioctl. Signed-off-by: Xin Long Reviewed-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_ioctl.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 263b4de4de57..f8fc6241469a 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -112,7 +112,9 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct net_bridge *br = netdev_priv(dev); + struct net_bridge_port *p = NULL; unsigned long args[4]; + int ret = -EOPNOTSUPP; if (copy_from_user(args, rq->ifr_data, sizeof(args))) return -EFAULT; @@ -182,25 +184,29 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; - return br_set_forward_delay(br, args[1]); + ret = br_set_forward_delay(br, args[1]); + break; case BRCTL_SET_BRIDGE_HELLO_TIME: if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; - return br_set_hello_time(br, args[1]); + ret = br_set_hello_time(br, args[1]); + break; case BRCTL_SET_BRIDGE_MAX_AGE: if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; - return br_set_max_age(br, args[1]); + ret = br_set_max_age(br, args[1]); + break; case BRCTL_SET_AGEING_TIME: if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; - return br_set_ageing_time(br, args[1]); + ret = br_set_ageing_time(br, args[1]); + break; case BRCTL_GET_PORT_INFO: { @@ -240,20 +246,19 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EPERM; br_stp_set_enabled(br, args[1]); - return 0; + ret = 0; + break; case BRCTL_SET_BRIDGE_PRIORITY: if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; br_stp_set_bridge_priority(br, args[1]); - return 0; + ret = 0; + break; case BRCTL_SET_PORT_PRIORITY: { - struct net_bridge_port *p; - int ret; - if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; @@ -263,14 +268,11 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) else ret = br_stp_set_port_priority(p, args[2]); spin_unlock_bh(&br->lock); - return ret; + break; } case BRCTL_SET_PATH_COST: { - struct net_bridge_port *p; - int ret; - if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; @@ -280,8 +282,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) else ret = br_stp_set_path_cost(p, args[2]); spin_unlock_bh(&br->lock); - - return ret; + break; } case BRCTL_GET_FDB_ENTRIES: @@ -289,7 +290,14 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) args[2], args[3]); } - return -EOPNOTSUPP; + if (!ret) { + if (p) + br_ifinfo_notify(RTM_NEWLINK, p); + else + netdev_state_change(br->dev); + } + + return ret; } static int old_deviceless(struct net *net, void __user *uarg) -- GitLab From ea019649c37b8aa0d1ac5727d122b2e8ed74f536 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 8 Apr 2016 20:39:47 +0200 Subject: [PATCH 2660/9938] drivers/net/ethernet/jme.c: Deinline jme_reset_mac_processor, save 2816 bytes This function compiles to 895 bytes of machine code. Clearly, this isn't a time-critical function. For one, it has a number of udelay(1) calls. Signed-off-by: Denys Vlasenko CC: David S. Miller CC: linux-kernel@vger.kernel.org CC: netdev@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/ethernet/jme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 3ddf657bc10b..836ebd8ee768 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -222,7 +222,7 @@ jme_clear_ghc_reset(struct jme_adapter *jme) jwrite32f(jme, JME_GHC, jme->reg_ghc); } -static inline void +static void jme_reset_mac_processor(struct jme_adapter *jme) { static const u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0}; -- GitLab From 250eb1f8815303f71c94a5680f8e4f2dcfa25cf5 Mon Sep 17 00:00:00 2001 From: Marcelo Ricardo Leitner Date: Fri, 8 Apr 2016 16:41:27 -0300 Subject: [PATCH 2661/9938] sctp: compress bit-wide flags to a bitfield on sctp_sock It wastes space and gets worse as we add new flags, so convert bit-wide flags to a bitfield. Currently it already saves 4 bytes in sctp_sock, which are left as holes in it for now. The whole struct needs packing, which should be done in another patch. Note that do_auto_asconf cannot be merged, as explained in the comment before it. Signed-off-by: Marcelo Ricardo Leitner Acked-by: Neil Horman Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 6df1ce7a411c..1a6a626904bb 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -210,14 +210,14 @@ struct sctp_sock { int user_frag; __u32 autoclose; - __u8 nodelay; - __u8 disable_fragments; - __u8 v4mapped; - __u8 frag_interleave; __u32 adaptation_ind; __u32 pd_point; - __u8 recvrcvinfo; - __u8 recvnxtinfo; + __u16 nodelay:1, + disable_fragments:1, + v4mapped:1, + frag_interleave:1, + recvrcvinfo:1, + recvnxtinfo:1; atomic_t pd_mode; /* Receive to here while partial delivery is in effect. */ -- GitLab From fb586f25300f4587c7ebd097a604bf269b25bfa7 Mon Sep 17 00:00:00 2001 From: Marcelo Ricardo Leitner Date: Fri, 8 Apr 2016 16:41:28 -0300 Subject: [PATCH 2662/9938] sctp: delay calls to sk_data_ready() as much as possible Currently processing of multiple chunks in a single SCTP packet leads to multiple calls to sk_data_ready, causing multiple wake up signals which are costy and doesn't make it wake up any faster. With this patch it will note that the wake up is pending and will do it before leaving the state machine interpreter, latest place possible to do it realiably and cleanly. Note that sk_data_ready events are not dependent on asocs, unlike waking up writers. v2: series re-checked v3: use local vars to cleanup the code, suggested by Jakub Sitnicki Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 3 ++- net/sctp/sm_sideeffect.c | 7 +++++++ net/sctp/ulpqueue.c | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 1a6a626904bb..21cb11107e37 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -217,7 +217,8 @@ struct sctp_sock { v4mapped:1, frag_interleave:1, recvrcvinfo:1, - recvnxtinfo:1; + recvnxtinfo:1, + pending_data_ready:1; atomic_t pd_mode; /* Receive to here while partial delivery is in effect. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 7fe56d0acabf..d06317de8730 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1222,6 +1222,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sctp_cmd_seq_t *commands, gfp_t gfp) { + struct sock *sk = ep->base.sk; + struct sctp_sock *sp = sctp_sk(sk); int error = 0; int force; sctp_cmd_t *cmd; @@ -1742,6 +1744,11 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, error = sctp_outq_uncork(&asoc->outqueue, gfp); } else if (local_cork) error = sctp_outq_uncork(&asoc->outqueue, gfp); + + if (sp->pending_data_ready) { + sk->sk_data_ready(sk); + sp->pending_data_ready = 0; + } return error; nomem: error = -ENOMEM; diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index ce469d648ffb..72e5b3e41cdd 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -264,7 +264,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) sctp_ulpq_clear_pd(ulpq); if (queue == &sk->sk_receive_queue) - sk->sk_data_ready(sk); + sctp_sk(sk)->pending_data_ready = 1; return 1; out_free: @@ -1140,5 +1140,5 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) /* If there is data waiting, send it up the socket now. */ if (sctp_ulpq_clear_pd(ulpq) || ev) - sk->sk_data_ready(sk); + sctp_sk(sk)->pending_data_ready = 1; } -- GitLab From eb96ce01bab7af55d983feaae069c18792d427ef Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 8 Apr 2016 22:06:40 -0700 Subject: [PATCH 2663/9938] net: bcmgenet: use napi_complete_done() By using napi_complete_done(), we allow fine tuning of /sys/class/net/ethX/gro_flush_timeout for higher GRO aggregation efficiency for a Gbit NIC. Check commit 24d2e4a50737 ("tg3: use napi_complete_done()") for details. Signed-off-by: Eric Dumazet Cc: Petri Gynther Cc: Florian Fainelli Acked-by: Florian Fainelli Acked-by: Petri Gynther Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index f7b42b9fc979..e823013d3125 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1735,7 +1735,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget) work_done = bcmgenet_desc_rx(ring, budget); if (work_done < budget) { - napi_complete(napi); + napi_complete_done(napi, work_done); ring->int_enable(ring); } -- GitLab From dac916f8fbd1ea514a61f4dcecaa97a5e7bac4c0 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 8 Apr 2016 22:30:56 -0700 Subject: [PATCH 2664/9938] net: bcmgenet: use __napi_schedule_irqoff() bcmgenet_isr1() and bcmgenet_isr0() run in hard irq context, we do not need to block irq again. Signed-off-by: Florian Fainelli Signed-off-by: Eric Dumazet Acked-by: Petri Gynther Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index e823013d3125..49f132c7ed99 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2493,7 +2493,7 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id) if (likely(napi_schedule_prep(&rx_ring->napi))) { rx_ring->int_disable(rx_ring); - __napi_schedule(&rx_ring->napi); + __napi_schedule_irqoff(&rx_ring->napi); } } @@ -2506,7 +2506,7 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id) if (likely(napi_schedule_prep(&tx_ring->napi))) { tx_ring->int_disable(tx_ring); - __napi_schedule(&tx_ring->napi); + __napi_schedule_irqoff(&tx_ring->napi); } } @@ -2536,7 +2536,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) if (likely(napi_schedule_prep(&rx_ring->napi))) { rx_ring->int_disable(rx_ring); - __napi_schedule(&rx_ring->napi); + __napi_schedule_irqoff(&rx_ring->napi); } } @@ -2545,7 +2545,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) if (likely(napi_schedule_prep(&tx_ring->napi))) { tx_ring->int_disable(tx_ring); - __napi_schedule(&tx_ring->napi); + __napi_schedule_irqoff(&tx_ring->napi); } } -- GitLab From e178c8c2306ebff13aee365de703e6b8b2bea066 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Sat, 9 Apr 2016 00:20:36 -0700 Subject: [PATCH 2665/9938] net: bcmgenet: add BQL support Add Byte Queue Limits (BQL) support to bcmgenet driver. Signed-off-by: Petri Gynther Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 49f132c7ed99..8150c74f054a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1221,8 +1221,10 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, dev->stats.tx_packets += pkts_compl; dev->stats.tx_bytes += bytes_compl; + txq = netdev_get_tx_queue(dev, ring->queue); + netdev_tx_completed_queue(txq, pkts_compl, bytes_compl); + if (ring->free_bds > (MAX_SKB_FRAGS + 1)) { - txq = netdev_get_tx_queue(dev, ring->queue); if (netif_tx_queue_stopped(txq)) netif_tx_wake_queue(txq); } @@ -1516,6 +1518,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) ring->prod_index += nr_frags + 1; ring->prod_index &= DMA_P_INDEX_MASK; + netdev_tx_sent_queue(txq, GENET_CB(skb)->bytes_sent); + if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) netif_tx_stop_queue(txq); @@ -2364,6 +2368,7 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv) static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) { int i; + struct netdev_queue *txq; bcmgenet_fini_rx_napi(priv); bcmgenet_fini_tx_napi(priv); @@ -2378,6 +2383,14 @@ static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) } } + for (i = 0; i < priv->hw_params->tx_queues; i++) { + txq = netdev_get_tx_queue(priv->dev, priv->tx_rings[i].queue); + netdev_tx_reset_queue(txq); + } + + txq = netdev_get_tx_queue(priv->dev, priv->tx_rings[DESC_INDEX].queue); + netdev_tx_reset_queue(txq); + bcmgenet_free_rx_buffers(priv); kfree(priv->rx_cbs); kfree(priv->tx_cbs); -- GitLab From cfe2f14c72b0266a9f3573427f206a98ad3d409c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 9 Apr 2016 10:49:22 +0200 Subject: [PATCH 2666/9938] qdisc: constify meta_type_ops structures The meta_type_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- net/sched/em_meta.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index f2aabc0089da..a309a07ccb35 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -796,7 +796,7 @@ struct meta_type_ops { int (*dump)(struct sk_buff *, struct meta_value *, int); }; -static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX + 1] = { +static const struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX + 1] = { [TCF_META_TYPE_VAR] = { .destroy = meta_var_destroy, .compare = meta_var_compare, @@ -812,7 +812,7 @@ static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX + 1] = { } }; -static inline struct meta_type_ops *meta_type_ops(struct meta_value *v) +static inline const struct meta_type_ops *meta_type_ops(struct meta_value *v) { return &__meta_type_ops[meta_type(v)]; } @@ -870,7 +870,7 @@ static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m, static void meta_delete(struct meta_match *meta) { if (meta) { - struct meta_type_ops *ops = meta_type_ops(&meta->lvalue); + const struct meta_type_ops *ops = meta_type_ops(&meta->lvalue); if (ops && ops->destroy) { ops->destroy(&meta->lvalue); @@ -964,7 +964,7 @@ static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em) { struct meta_match *meta = (struct meta_match *) em->data; struct tcf_meta_hdr hdr; - struct meta_type_ops *ops; + const struct meta_type_ops *ops; memset(&hdr, 0, sizeof(hdr)); memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left)); -- GitLab From 743b03a83297690f0bd38c452a3bbb47d2be300a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 9 Apr 2016 11:29:58 -0700 Subject: [PATCH 2667/9938] net: remove netdevice gso_min_segs After introduction of ndo_features_check(), we believe that very specific checks for rare features should not be done in core networking stack. No driver uses gso_min_segs yet, so we revert this feature and save few instructions per tx packet in fast path. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 +--- net/core/dev.c | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e906c6570b38..9884fe9a6552 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1586,8 +1586,6 @@ enum netdev_priv_flags { * @gso_max_size: Maximum size of generic segmentation offload * @gso_max_segs: Maximum number of segments that can be passed to the * NIC for GSO - * @gso_min_segs: Minimum number of segments that can be passed to the - * NIC for GSO * * @dcbnl_ops: Data Center Bridging netlink ops * @num_tc: Number of traffic classes in the net device @@ -1858,7 +1856,7 @@ struct net_device { unsigned int gso_max_size; #define GSO_MAX_SEGS 65535 u16 gso_max_segs; - u16 gso_min_segs; + #ifdef CONFIG_DCB const struct dcbnl_rtnl_ops *dcbnl_ops; #endif diff --git a/net/core/dev.c b/net/core/dev.c index d51343a821ed..09fb1ace9dc8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2831,7 +2831,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) netdev_features_t features = dev->features; u16 gso_segs = skb_shinfo(skb)->gso_segs; - if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) + if (gso_segs > dev->gso_max_segs) features &= ~NETIF_F_GSO_MASK; /* If encapsulation offload request, verify we are testing @@ -7429,7 +7429,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev->gso_max_size = GSO_MAX_SIZE; dev->gso_max_segs = GSO_MAX_SEGS; - dev->gso_min_segs = 0; INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); -- GitLab From 95114344ea78649b1797d00ab6e88147bef66fa4 Mon Sep 17 00:00:00 2001 From: Rahul Verma Date: Sun, 10 Apr 2016 12:42:59 +0300 Subject: [PATCH 2668/9938] qed*: remove version dependency Inbox drivers don't need versioning scheme in order to guarantee compatibility, as both qed and qede are compiled from same codebase. Signed-off-by: Rahul Verma Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 2 -- drivers/net/ethernet/qlogic/qed/qed_l2.c | 8 +------- drivers/net/ethernet/qlogic/qed/qed_main.c | 11 ----------- drivers/net/ethernet/qlogic/qede/qede.h | 2 -- drivers/net/ethernet/qlogic/qede/qede_main.c | 11 +---------- include/linux/qed/qed_eth_if.h | 2 +- include/linux/qed/qed_if.h | 9 --------- 7 files changed, 3 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index fcb8e9ba51d9..a3ee9df16dfe 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -507,6 +507,4 @@ u32 qed_unzip_data(struct qed_hwfn *p_hwfn, int qed_slowpath_irq_req(struct qed_hwfn *hwfn); -#define QED_ETH_INTERFACE_VERSION 300 - #endif /* _QED_H */ diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 3f35c6ca9252..e848d5a1f7f6 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -2043,14 +2043,8 @@ static const struct qed_eth_ops qed_eth_ops_pass = { .get_vport_stats = &qed_get_vport_stats, }; -const struct qed_eth_ops *qed_get_eth_ops(u32 version) +const struct qed_eth_ops *qed_get_eth_ops(void) { - if (version != QED_ETH_INTERFACE_VERSION) { - pr_notice("Cannot supply ethtool operations [%08x != %08x]\n", - version, QED_ETH_INTERFACE_VERSION); - return NULL; - } - return &qed_eth_ops_pass; } EXPORT_SYMBOL(qed_get_eth_ops); diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 26d40db07ddd..c31d485f72d6 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1172,14 +1172,3 @@ const struct qed_common_ops qed_common_ops_pass = { .chain_free = &qed_chain_free, .set_led = &qed_set_led, }; - -u32 qed_get_protocol_version(enum qed_protocol protocol) -{ - switch (protocol) { - case QED_PROTOCOL_ETH: - return QED_ETH_INTERFACE_VERSION; - default: - return 0; - } -} -EXPORT_SYMBOL(qed_get_protocol_version); diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index d023251544d9..e0a696a57d4d 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -32,8 +32,6 @@ __stringify(QEDE_REVISION_VERSION) "." \ __stringify(QEDE_ENGINEERING_VERSION) -#define QEDE_ETH_INTERFACE_VERSION 300 - #define DRV_MODULE_SYM qede struct qede_stats { diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 518af329502d..a55d93eb41fa 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -141,19 +141,10 @@ static int __init qede_init(void) { int ret; - u32 qed_ver; pr_notice("qede_init: %s\n", version); - qed_ver = qed_get_protocol_version(QED_PROTOCOL_ETH); - if (qed_ver != QEDE_ETH_INTERFACE_VERSION) { - pr_notice("Version mismatch [%08x != %08x]\n", - qed_ver, - QEDE_ETH_INTERFACE_VERSION); - return -EINVAL; - } - - qed_ops = qed_get_eth_ops(QEDE_ETH_INTERFACE_VERSION); + qed_ops = qed_get_eth_ops(); if (!qed_ops) { pr_notice("Failed to get qed ethtool operations\n"); return -EINVAL; diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index e1d69834a11f..e00c8dbfc324 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -167,7 +167,7 @@ struct qed_eth_ops { struct qed_eth_stats *stats); }; -const struct qed_eth_ops *qed_get_eth_ops(u32 version); +const struct qed_eth_ops *qed_get_eth_ops(void); void qed_put_eth_ops(void); #endif diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 1f7599c77cd4..b007011e1c82 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -271,15 +271,6 @@ struct qed_common_ops { enum qed_led_mode mode); }; -/** - * @brief qed_get_protocol_version - * - * @param protocol - * - * @return version supported by qed for given protocol driver - */ -u32 qed_get_protocol_version(enum qed_protocol protocol); - #define MASK_FIELD(_name, _value) \ ((_value) &= (_name ## _MASK)) -- GitLab From 8c5ebd0c792a097fcc0e526debbe0887ee378ae5 Mon Sep 17 00:00:00 2001 From: Sudarsana Reddy Kalluru Date: Sun, 10 Apr 2016 12:43:00 +0300 Subject: [PATCH 2669/9938] qed: add Rx flow hash/indirection support. Adds the required API for passing RSS-related configuration from qede. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_l2.c | 17 +---------------- include/linux/qed/qed_eth_if.h | 1 + include/linux/qed/qed_if.h | 11 +++++++++++ 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index e848d5a1f7f6..5005497ee23e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -35,19 +35,6 @@ #include "qed_reg_addr.h" #include "qed_sp.h" -enum qed_rss_caps { - QED_RSS_IPV4 = 0x1, - QED_RSS_IPV6 = 0x2, - QED_RSS_IPV4_TCP = 0x4, - QED_RSS_IPV6_TCP = 0x8, - QED_RSS_IPV4_UDP = 0x10, - QED_RSS_IPV6_UDP = 0x20, -}; - -/* Should be the same as ETH_RSS_IND_TABLE_ENTRIES_NUM */ -#define QED_RSS_IND_TABLE_SIZE 128 -#define QED_RSS_KEY_SIZE 10 /* size in 32b chunks */ - struct qed_rss_params { u8 update_rss_config; u8 rss_enable; @@ -1744,9 +1731,7 @@ static int qed_update_vport(struct qed_dev *cdev, sp_rss_params.update_rss_capabilities = 1; sp_rss_params.update_rss_ind_table = 1; sp_rss_params.update_rss_key = 1; - sp_rss_params.rss_caps = QED_RSS_IPV4 | - QED_RSS_IPV6 | - QED_RSS_IPV4_TCP | QED_RSS_IPV6_TCP; + sp_rss_params.rss_caps = params->rss_params.rss_caps; sp_rss_params.rss_table_size_log = 7; /* 2^7 = 128 */ memcpy(sp_rss_params.rss_ind_table, params->rss_params.rss_ind_table, diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index e00c8dbfc324..795c9902e02f 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -27,6 +27,7 @@ struct qed_dev_eth_info { struct qed_update_vport_rss_params { u16 rss_ind_table[128]; u32 rss_key[10]; + u8 rss_caps; }; struct qed_update_vport_params { diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index b007011e1c82..67e8c206b2c1 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -515,4 +515,15 @@ static inline void internal_ram_wr(void __iomem *addr, __internal_ram_wr(NULL, addr, size, data); } +enum qed_rss_caps { + QED_RSS_IPV4 = 0x1, + QED_RSS_IPV6 = 0x2, + QED_RSS_IPV4_TCP = 0x4, + QED_RSS_IPV6_TCP = 0x8, + QED_RSS_IPV4_UDP = 0x10, + QED_RSS_IPV6_UDP = 0x20, +}; + +#define QED_RSS_IND_TABLE_SIZE 128 +#define QED_RSS_KEY_SIZE 10 /* size in 32b chunks */ #endif -- GitLab From 961acdeafd8f369a9e99b3d08f66eec5d8f93a8e Mon Sep 17 00:00:00 2001 From: Sudarsana Reddy Kalluru Date: Sun, 10 Apr 2016 12:43:01 +0300 Subject: [PATCH 2670/9938] qede: add Rx flow hash/indirection support. Adds support for the following via ethtool: - UDP configuration of RSS based on 2-tuple/4-tuple. - RSS hash key. - RSS indirection table. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede.h | 4 + .../net/ethernet/qlogic/qede/qede_ethtool.c | 237 +++++++++++++++++- drivers/net/ethernet/qlogic/qede/qede_main.c | 52 +++- 3 files changed, 283 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index e0a696a57d4d..80dbb7352ee3 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -154,6 +154,10 @@ struct qede_dev { SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) struct qede_stats stats; +#define QEDE_RSS_INDIR_INITED BIT(0) +#define QEDE_RSS_KEY_INITED BIT(1) +#define QEDE_RSS_CAPS_INITED BIT(2) + u32 rss_params_inited; /* bit-field to track initialized rss params */ struct qed_update_vport_rss_params rss_params; u16 q_num_rx_buffers; /* Must be a power of two */ u16 q_num_tx_buffers; /* Must be a power of two */ diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index c49dc10ce151..f0982f163670 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -569,6 +569,236 @@ static int qede_set_phys_id(struct net_device *dev, return 0; } +static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) +{ + info->data = RXH_IP_SRC | RXH_IP_DST; + + switch (info->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + break; + case UDP_V4_FLOW: + if (edev->rss_params.rss_caps & QED_RSS_IPV4_UDP) + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + break; + case UDP_V6_FLOW: + if (edev->rss_params.rss_caps & QED_RSS_IPV6_UDP) + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + break; + case IPV4_FLOW: + case IPV6_FLOW: + break; + default: + info->data = 0; + break; + } + + return 0; +} + +static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, + u32 *rules __always_unused) +{ + struct qede_dev *edev = netdev_priv(dev); + + switch (info->cmd) { + case ETHTOOL_GRXRINGS: + info->data = edev->num_rss; + return 0; + case ETHTOOL_GRXFH: + return qede_get_rss_flags(edev, info); + default: + DP_ERR(edev, "Command parameters not supported\n"); + return -EOPNOTSUPP; + } +} + +static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) +{ + struct qed_update_vport_params vport_update_params; + u8 set_caps = 0, clr_caps = 0; + + DP_VERBOSE(edev, QED_MSG_DEBUG, + "Set rss flags command parameters: flow type = %d, data = %llu\n", + info->flow_type, info->data); + + switch (info->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + /* For TCP only 4-tuple hash is supported */ + if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + DP_INFO(edev, "Command parameters not supported\n"); + return -EINVAL; + } + return 0; + case UDP_V4_FLOW: + /* For UDP either 2-tuple hash or 4-tuple hash is supported */ + if (info->data == (RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + set_caps = QED_RSS_IPV4_UDP; + DP_VERBOSE(edev, QED_MSG_DEBUG, + "UDP 4-tuple enabled\n"); + } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { + clr_caps = QED_RSS_IPV4_UDP; + DP_VERBOSE(edev, QED_MSG_DEBUG, + "UDP 4-tuple disabled\n"); + } else { + return -EINVAL; + } + break; + case UDP_V6_FLOW: + /* For UDP either 2-tuple hash or 4-tuple hash is supported */ + if (info->data == (RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + set_caps = QED_RSS_IPV6_UDP; + DP_VERBOSE(edev, QED_MSG_DEBUG, + "UDP 4-tuple enabled\n"); + } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { + clr_caps = QED_RSS_IPV6_UDP; + DP_VERBOSE(edev, QED_MSG_DEBUG, + "UDP 4-tuple disabled\n"); + } else { + return -EINVAL; + } + break; + case IPV4_FLOW: + case IPV6_FLOW: + /* For IP only 2-tuple hash is supported */ + if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { + DP_INFO(edev, "Command parameters not supported\n"); + return -EINVAL; + } + return 0; + case SCTP_V4_FLOW: + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case SCTP_V6_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case IP_USER_FLOW: + case ETHER_FLOW: + /* RSS is not supported for these protocols */ + if (info->data) { + DP_INFO(edev, "Command parameters not supported\n"); + return -EINVAL; + } + return 0; + default: + return -EINVAL; + } + + /* No action is needed if there is no change in the rss capability */ + if (edev->rss_params.rss_caps == ((edev->rss_params.rss_caps & + ~clr_caps) | set_caps)) + return 0; + + /* Update internal configuration */ + edev->rss_params.rss_caps = (edev->rss_params.rss_caps & ~clr_caps) | + set_caps; + edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; + + /* Re-configure if possible */ + if (netif_running(edev->ndev)) { + memset(&vport_update_params, 0, sizeof(vport_update_params)); + vport_update_params.update_rss_flg = 1; + vport_update_params.vport_id = 0; + memcpy(&vport_update_params.rss_params, &edev->rss_params, + sizeof(vport_update_params.rss_params)); + return edev->ops->vport_update(edev->cdev, + &vport_update_params); + } + + return 0; +} + +static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) +{ + struct qede_dev *edev = netdev_priv(dev); + + switch (info->cmd) { + case ETHTOOL_SRXFH: + return qede_set_rss_flags(edev, info); + default: + DP_INFO(edev, "Command parameters not supported\n"); + return -EOPNOTSUPP; + } +} + +static u32 qede_get_rxfh_indir_size(struct net_device *dev) +{ + return QED_RSS_IND_TABLE_SIZE; +} + +static u32 qede_get_rxfh_key_size(struct net_device *dev) +{ + struct qede_dev *edev = netdev_priv(dev); + + return sizeof(edev->rss_params.rss_key); +} + +static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) +{ + struct qede_dev *edev = netdev_priv(dev); + int i; + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + if (!indir) + return 0; + + for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) + indir[i] = edev->rss_params.rss_ind_table[i]; + + if (key) + memcpy(key, edev->rss_params.rss_key, + qede_get_rxfh_key_size(dev)); + + return 0; +} + +static int qede_set_rxfh(struct net_device *dev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct qed_update_vport_params vport_update_params; + struct qede_dev *edev = netdev_priv(dev); + int i; + + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + if (!indir && !key) + return 0; + + if (indir) { + for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) + edev->rss_params.rss_ind_table[i] = indir[i]; + edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; + } + + if (key) { + memcpy(&edev->rss_params.rss_key, key, + qede_get_rxfh_key_size(dev)); + edev->rss_params_inited |= QEDE_RSS_KEY_INITED; + } + + if (netif_running(edev->ndev)) { + memset(&vport_update_params, 0, sizeof(vport_update_params)); + vport_update_params.update_rss_flg = 1; + vport_update_params.vport_id = 0; + memcpy(&vport_update_params.rss_params, &edev->rss_params, + sizeof(vport_update_params.rss_params)); + return edev->ops->vport_update(edev->cdev, + &vport_update_params); + } + + return 0; +} + static const struct ethtool_ops qede_ethtool_ops = { .get_settings = qede_get_settings, .set_settings = qede_set_settings, @@ -585,7 +815,12 @@ static const struct ethtool_ops qede_ethtool_ops = { .set_phys_id = qede_set_phys_id, .get_ethtool_stats = qede_get_ethtool_stats, .get_sset_count = qede_get_sset_count, - + .get_rxnfc = qede_get_rxnfc, + .set_rxnfc = qede_set_rxnfc, + .get_rxfh_indir_size = qede_get_rxfh_indir_size, + .get_rxfh_key_size = qede_get_rxfh_key_size, + .get_rxfh = qede_get_rxfh, + .set_rxfh = qede_set_rxfh, .get_channels = qede_get_channels, .set_channels = qede_set_channels, }; diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index a55d93eb41fa..457caad2e752 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -2826,10 +2826,10 @@ static int qede_start_queues(struct qede_dev *edev) int rc, tc, i; int vlan_removal_en = 1; struct qed_dev *cdev = edev->cdev; - struct qed_update_vport_rss_params *rss_params = &edev->rss_params; struct qed_update_vport_params vport_update_params; struct qed_queue_start_common_params q_params; struct qed_start_vport_params start = {0}; + bool reset_rss_indir = false; if (!edev->num_rss) { DP_ERR(edev, @@ -2924,16 +2924,50 @@ static int qede_start_queues(struct qede_dev *edev) /* Fill struct with RSS params */ if (QEDE_RSS_CNT(edev) > 1) { vport_update_params.update_rss_flg = 1; - for (i = 0; i < 128; i++) - rss_params->rss_ind_table[i] = - ethtool_rxfh_indir_default(i, QEDE_RSS_CNT(edev)); - netdev_rss_key_fill(rss_params->rss_key, - sizeof(rss_params->rss_key)); + + /* Need to validate current RSS config uses valid entries */ + for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) { + if (edev->rss_params.rss_ind_table[i] >= + edev->num_rss) { + reset_rss_indir = true; + break; + } + } + + if (!(edev->rss_params_inited & QEDE_RSS_INDIR_INITED) || + reset_rss_indir) { + u16 val; + + for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) { + u16 indir_val; + + val = QEDE_RSS_CNT(edev); + indir_val = ethtool_rxfh_indir_default(i, val); + edev->rss_params.rss_ind_table[i] = indir_val; + } + edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; + } + + if (!(edev->rss_params_inited & QEDE_RSS_KEY_INITED)) { + netdev_rss_key_fill(edev->rss_params.rss_key, + sizeof(edev->rss_params.rss_key)); + edev->rss_params_inited |= QEDE_RSS_KEY_INITED; + } + + if (!(edev->rss_params_inited & QEDE_RSS_CAPS_INITED)) { + edev->rss_params.rss_caps = QED_RSS_IPV4 | + QED_RSS_IPV6 | + QED_RSS_IPV4_TCP | + QED_RSS_IPV6_TCP; + edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; + } + + memcpy(&vport_update_params.rss_params, &edev->rss_params, + sizeof(vport_update_params.rss_params)); } else { - memset(rss_params, 0, sizeof(*rss_params)); + memset(&vport_update_params.rss_params, 0, + sizeof(vport_update_params.rss_params)); } - memcpy(&vport_update_params.rss_params, rss_params, - sizeof(*rss_params)); rc = edev->ops->vport_update(cdev, &vport_update_params); if (rc) { -- GitLab From 7c2d7d7438c9808cff1c34decc80c49f87a764e7 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 10 Apr 2016 12:43:02 +0300 Subject: [PATCH 2671/9938] qed* - bump driver versions to 8.7.1.20 Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 2 +- drivers/net/ethernet/qlogic/qede/qede.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index a3ee9df16dfe..0f0d2d1d77e5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -26,7 +26,7 @@ #include "qed_hsi.h" extern const struct qed_common_ops qed_common_ops_pass; -#define DRV_MODULE_VERSION "8.7.0.0" +#define DRV_MODULE_VERSION "8.7.1.20" #define MAX_HWFNS_PER_DEVICE (4) #define NAME_SIZE 16 diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 80dbb7352ee3..41c418909a5c 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -25,8 +25,8 @@ #define QEDE_MAJOR_VERSION 8 #define QEDE_MINOR_VERSION 7 -#define QEDE_REVISION_VERSION 0 -#define QEDE_ENGINEERING_VERSION 0 +#define QEDE_REVISION_VERSION 1 +#define QEDE_ENGINEERING_VERSION 20 #define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \ __stringify(QEDE_MINOR_VERSION) "." \ __stringify(QEDE_REVISION_VERSION) "." \ -- GitLab From d0988a5f77e7a399ac579e629f1dcc23059246e9 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 10 Apr 2016 23:55:15 +0300 Subject: [PATCH 2672/9938] ravb: make ravb_ptp_interrupt() *void* When we have the ISS.CGIS bit set, we already know that gPTP interrupt has happened, so an extra GIS register check at the end of ravb_ptp_interrupt() seems superfluous. We can model the gPTP interrupt handler like all other dedicated interrupt handlers in the driver and make it *void*. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb.h | 2 +- drivers/net/ethernet/renesas/ravb_main.c | 8 ++++++-- drivers/net/ethernet/renesas/ravb_ptp.c | 9 ++------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h index 5c1624147778..4e5d5e953e15 100644 --- a/drivers/net/ethernet/renesas/ravb.h +++ b/drivers/net/ethernet/renesas/ravb.h @@ -1045,7 +1045,7 @@ void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear, u32 set); int ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value); -irqreturn_t ravb_ptp_interrupt(struct net_device *ndev); +void ravb_ptp_interrupt(struct net_device *ndev); void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev); void ravb_ptp_stop(struct net_device *ndev); diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 4b71951e185d..0f1b314f4d64 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -807,8 +807,10 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id) } /* gPTP interrupt status summary */ - if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED) + if (iss & ISS_CGIS) { + ravb_ptp_interrupt(ndev); result = IRQ_HANDLED; + } mmiowb(); spin_unlock(&priv->lock); @@ -838,8 +840,10 @@ static irqreturn_t ravb_multi_interrupt(int irq, void *dev_id) } /* gPTP interrupt status summary */ - if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED) + if (iss & ISS_CGIS) { + ravb_ptp_interrupt(ndev); result = IRQ_HANDLED; + } mmiowb(); spin_unlock(&priv->lock); diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c index f1b2cbb336e8..eede70ec37f8 100644 --- a/drivers/net/ethernet/renesas/ravb_ptp.c +++ b/drivers/net/ethernet/renesas/ravb_ptp.c @@ -296,7 +296,7 @@ static const struct ptp_clock_info ravb_ptp_info = { }; /* Caller must hold the lock */ -irqreturn_t ravb_ptp_interrupt(struct net_device *ndev) +void ravb_ptp_interrupt(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); u32 gis = ravb_read(ndev, GIS); @@ -319,12 +319,7 @@ irqreturn_t ravb_ptp_interrupt(struct net_device *ndev) } } - if (gis) { - ravb_write(ndev, ~gis, GIS); - return IRQ_HANDLED; - } - - return IRQ_NONE; + ravb_write(ndev, ~gis, GIS); } void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev) -- GitLab From f38ba953bee01887d520f7abba536721a1d16477 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 13 Apr 2016 17:02:21 -0700 Subject: [PATCH 2673/9938] gre: eliminate holes in ip_tunnel The structure can be packed denser by doing minor rearrangement of existing elements. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/ip_tunnels.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 16435d8b1f93..9ae9fbbccd67 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -105,24 +105,23 @@ struct ip_tunnel { struct net_device *dev; struct net *net; /* netns for packet i/o */ - int err_count; /* Number of arrived ICMP errors */ unsigned long err_time; /* Time when the last ICMP error * arrived */ + int err_count; /* Number of arrived ICMP errors */ /* These four fields used only by GRE */ u32 i_seqno; /* The last seen seqno */ u32 o_seqno; /* The last output seqno */ int tun_hlen; /* Precalculated header length */ - int mlink; struct dst_cache dst_cache; struct ip_tunnel_parm parms; + int mlink; int encap_hlen; /* Encap header length (FOU,GUE) */ - struct ip_tunnel_encap encap; - int hlen; /* tun_hlen + encap_hlen */ + struct ip_tunnel_encap encap; /* for SIT */ #ifdef CONFIG_IPV6_SIT_6RD -- GitLab From 04cf31a759ef575f750a63777cee95500e410994 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 24 Mar 2016 22:04:01 +1100 Subject: [PATCH 2674/9938] ftrace: Make ftrace_location_range() global In order to support live patching on powerpc we would like to call ftrace_location_range(), so make it global. Signed-off-by: Torsten Duwe Signed-off-by: Balbir Singh Signed-off-by: Michael Ellerman --- include/linux/ftrace.h | 1 + kernel/trace/ftrace.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 81de7123959d..3481a8e405f9 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -455,6 +455,7 @@ int ftrace_update_record(struct dyn_ftrace *rec, int enable); int ftrace_test_record(struct dyn_ftrace *rec, int enable); void ftrace_run_stop_machine(int command); unsigned long ftrace_location(unsigned long ip); +unsigned long ftrace_location_range(unsigned long start, unsigned long end); unsigned long ftrace_get_addr_new(struct dyn_ftrace *rec); unsigned long ftrace_get_addr_curr(struct dyn_ftrace *rec); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index eca592f977b2..e1b3f2312db0 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1533,7 +1533,19 @@ static int ftrace_cmp_recs(const void *a, const void *b) return 0; } -static unsigned long ftrace_location_range(unsigned long start, unsigned long end) +/** + * ftrace_location_range - return the first address of a traced location + * if it touches the given ip range + * @start: start of range to search. + * @end: end of range to search (inclusive). @end points to the last byte + * to check. + * + * Returns rec->ip if the related ftrace location is a least partly within + * the given address range. That is, the first address of the instruction + * that is either a NOP or call to the function tracer. It checks the ftrace + * internal tables to determine if the address belongs or not. + */ +unsigned long ftrace_location_range(unsigned long start, unsigned long end) { struct ftrace_page *pg; struct dyn_ftrace *rec; -- GitLab From 28e7cbd3e0f5fefec892842d1391ebd508fdb5ce Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 24 Mar 2016 22:04:02 +1100 Subject: [PATCH 2675/9938] livepatch: Allow architectures to specify an alternate ftrace location When livepatch tries to patch a function it takes the function address and asks ftrace to install the livepatch handler at that location. ftrace will look for an mcount call site at that exact address. On powerpc the mcount location is not the first instruction of the function, and in fact it's not at a constant offset from the start of the function. To accommodate this add a hook which arch code can override to customise the behaviour. Signed-off-by: Torsten Duwe Signed-off-by: Balbir Singh Signed-off-by: Petr Mladek Signed-off-by: Michael Ellerman --- kernel/livepatch/core.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index bc2c85c064c1..35ee2c5b7176 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -298,6 +298,19 @@ static void notrace klp_ftrace_handler(unsigned long ip, rcu_read_unlock(); } +/* + * Convert a function address into the appropriate ftrace location. + * + * Usually this is just the address of the function, but on some architectures + * it's more complicated so allow them to provide a custom behaviour. + */ +#ifndef klp_get_ftrace_location +static unsigned long klp_get_ftrace_location(unsigned long faddr) +{ + return faddr; +} +#endif + static void klp_disable_func(struct klp_func *func) { struct klp_ops *ops; @@ -312,8 +325,14 @@ static void klp_disable_func(struct klp_func *func) return; if (list_is_singular(&ops->func_stack)) { + unsigned long ftrace_loc; + + ftrace_loc = klp_get_ftrace_location(func->old_addr); + if (WARN_ON(!ftrace_loc)) + return; + WARN_ON(unregister_ftrace_function(&ops->fops)); - WARN_ON(ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0)); + WARN_ON(ftrace_set_filter_ip(&ops->fops, ftrace_loc, 1, 0)); list_del_rcu(&func->stack_node); list_del(&ops->node); @@ -338,6 +357,15 @@ static int klp_enable_func(struct klp_func *func) ops = klp_find_ops(func->old_addr); if (!ops) { + unsigned long ftrace_loc; + + ftrace_loc = klp_get_ftrace_location(func->old_addr); + if (!ftrace_loc) { + pr_err("failed to find location for function '%s'\n", + func->old_name); + return -EINVAL; + } + ops = kzalloc(sizeof(*ops), GFP_KERNEL); if (!ops) return -ENOMEM; @@ -352,7 +380,7 @@ static int klp_enable_func(struct klp_func *func) INIT_LIST_HEAD(&ops->func_stack); list_add_rcu(&func->stack_node, &ops->func_stack); - ret = ftrace_set_filter_ip(&ops->fops, func->old_addr, 0, 0); + ret = ftrace_set_filter_ip(&ops->fops, ftrace_loc, 0, 0); if (ret) { pr_err("failed to set ftrace filter for function '%s' (%d)\n", func->old_name, ret); @@ -363,7 +391,7 @@ static int klp_enable_func(struct klp_func *func) if (ret) { pr_err("failed to register ftrace handler for function '%s' (%d)\n", func->old_name, ret); - ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0); + ftrace_set_filter_ip(&ops->fops, ftrace_loc, 1, 0); goto err; } -- GitLab From f63e6d89876034c21ecd18bb1cd0d6c5b8da11a5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 24 Mar 2016 22:04:03 +1100 Subject: [PATCH 2676/9938] powerpc/livepatch: Add livepatch header Add the powerpc specific livepatch definitions. In particular we provide a non-default implementation of klp_get_ftrace_location(). This is required because the location of the mcount call is not constant when using -mprofile-kernel (which we always do for live patching). Signed-off-by: Torsten Duwe Signed-off-by: Balbir Singh Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/livepatch.h | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 arch/powerpc/include/asm/livepatch.h diff --git a/arch/powerpc/include/asm/livepatch.h b/arch/powerpc/include/asm/livepatch.h new file mode 100644 index 000000000000..ad36e8e34fa1 --- /dev/null +++ b/arch/powerpc/include/asm/livepatch.h @@ -0,0 +1,54 @@ +/* + * livepatch.h - powerpc-specific Kernel Live Patching Core + * + * Copyright (C) 2015-2016, SUSE, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#ifndef _ASM_POWERPC_LIVEPATCH_H +#define _ASM_POWERPC_LIVEPATCH_H + +#include +#include + +#ifdef CONFIG_LIVEPATCH +static inline int klp_check_compiler_support(void) +{ + return 0; +} + +static inline int klp_write_module_reloc(struct module *mod, unsigned long + type, unsigned long loc, unsigned long value) +{ + /* This requires infrastructure changes; we need the loadinfos. */ + return -ENOSYS; +} + +static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) +{ + regs->nip = ip; +} + +#define klp_get_ftrace_location klp_get_ftrace_location +static inline unsigned long klp_get_ftrace_location(unsigned long faddr) +{ + /* + * Live patch works only with -mprofile-kernel on PPC. In this case, + * the ftrace location is always within the first 16 bytes. + */ + return ftrace_location_range(faddr, faddr + 16); +} +#endif /* CONFIG_LIVEPATCH */ + +#endif /* _ASM_POWERPC_LIVEPATCH_H */ -- GitLab From 5d31a96e6c0187f2c5d7004e005fd094a1277e9e Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 24 Mar 2016 22:04:04 +1100 Subject: [PATCH 2677/9938] powerpc/livepatch: Add livepatch stack to struct thread_info In order to support live patching we need to maintain an alternate stack of TOC & LR values. We use the base of the stack for this, and store the "live patch stack pointer" in struct thread_info. Unlike the other fields of thread_info, we can not statically initialise that value, so it must be done at run time. This patch just adds the code to support that, it is not enabled until the next patch which actually adds live patch support. Signed-off-by: Michael Ellerman Acked-by: Balbir Singh --- arch/powerpc/include/asm/livepatch.h | 8 ++++++++ arch/powerpc/include/asm/thread_info.h | 4 +++- arch/powerpc/kernel/irq.c | 3 +++ arch/powerpc/kernel/process.c | 6 +++++- arch/powerpc/kernel/setup_64.c | 17 ++++++++++------- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/include/asm/livepatch.h b/arch/powerpc/include/asm/livepatch.h index ad36e8e34fa1..a402f7f94896 100644 --- a/arch/powerpc/include/asm/livepatch.h +++ b/arch/powerpc/include/asm/livepatch.h @@ -49,6 +49,14 @@ static inline unsigned long klp_get_ftrace_location(unsigned long faddr) */ return ftrace_location_range(faddr, faddr + 16); } + +static inline void klp_init_thread_info(struct thread_info *ti) +{ + /* + 1 to account for STACK_END_MAGIC */ + ti->livepatch_sp = (unsigned long *)(ti + 1) + 1; +} +#else +static void klp_init_thread_info(struct thread_info *ti) { } #endif /* CONFIG_LIVEPATCH */ #endif /* _ASM_POWERPC_LIVEPATCH_H */ diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 7efee4a3240b..8febc3f66d53 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -43,7 +43,9 @@ struct thread_info { int preempt_count; /* 0 => preemptable, <0 => BUG */ unsigned long local_flags; /* private flags for thread */ - +#ifdef CONFIG_LIVEPATCH + unsigned long *livepatch_sp; +#endif /* low level flags - has atomic operations done on it */ unsigned long flags ____cacheline_aligned_in_smp; }; diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 290559df1e8b..3cb46a3b1de7 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -66,6 +66,7 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include @@ -607,10 +608,12 @@ void irq_ctx_init(void) memset((void *)softirq_ctx[i], 0, THREAD_SIZE); tp = softirq_ctx[i]; tp->cpu = i; + klp_init_thread_info(tp); memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); tp = hardirq_ctx[i]; tp->cpu = i; + klp_init_thread_info(tp); } } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dccc87e8fee5..a38ce49648cb 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -55,6 +55,8 @@ #include #endif #include +#include + #include #include @@ -1267,13 +1269,15 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, extern void ret_from_kernel_thread(void); void (*f)(void); unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; + struct thread_info *ti = task_thread_info(p); + + klp_init_thread_info(ti); /* Copy registers */ sp -= sizeof(struct pt_regs); childregs = (struct pt_regs *) sp; if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ - struct thread_info *ti = (void *)task_stack_page(p); memset(childregs, 0, sizeof(struct pt_regs)); childregs->gpr[1] = sp + sizeof(struct pt_regs); /* function */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 5c03a6a9b054..e37b92ebb315 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -69,6 +69,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -670,16 +671,16 @@ static void __init emergency_stack_init(void) limit = min(safe_stack_limit(), ppc64_rma_size); for_each_possible_cpu(i) { - unsigned long sp; - sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); - sp += THREAD_SIZE; - paca[i].emergency_sp = __va(sp); + struct thread_info *ti; + ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit)); + klp_init_thread_info(ti); + paca[i].emergency_sp = (void *)ti + THREAD_SIZE; #ifdef CONFIG_PPC_BOOK3S_64 /* emergency stack for machine check exception handling. */ - sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); - sp += THREAD_SIZE; - paca[i].mc_emergency_sp = __va(sp); + ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit)); + klp_init_thread_info(ti); + paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE; #endif } } @@ -703,6 +704,8 @@ void __init setup_arch(char **cmdline_p) if (ppc_md.panic) setup_panic(); + klp_init_thread_info(&init_thread_info); + init_mm.start_code = (unsigned long)_stext; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; -- GitLab From 85baa095497f3e590df9f6c8932121f123efca5c Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 24 Mar 2016 22:04:05 +1100 Subject: [PATCH 2678/9938] powerpc/livepatch: Add live patching support on ppc64le Add the kconfig logic & assembly support for handling live patched functions. This depends on DYNAMIC_FTRACE_WITH_REGS, which in turn depends on the new -mprofile-kernel ftrace ABI, which is only supported currently on ppc64le. Live patching is handled by a special ftrace handler. This means it runs from ftrace_caller(). The live patch handler modifies the NIP so as to redirect the return from ftrace_caller() to the new patched function. However there is one particularly tricky case we need to handle. If a function A calls another function B, and it is known at link time that they share the same TOC, then A will not save or restore its TOC, and will call the local entry point of B. When we live patch B, we replace it with a new function C, which may not have the same TOC as A. At live patch time it's too late to modify A to do the TOC save/restore, so the live patching code must interpose itself between A and C, and do the TOC save/restore that A omitted. An additionaly complication is that the livepatch code can not create a stack frame in order to save the TOC. That is because if C takes > 8 arguments, or is varargs, A will have written the arguments for C in A's stack frame. To solve this, we introduce a "livepatch stack" which grows upward from the base of the regular stack, and is used to store the TOC & LR when calling a live patched function. When the patched function returns, we retrieve the real LR & TOC from the livepatch stack, restore them, and pop the livepatch "stack frame". Signed-off-by: Michael Ellerman Reviewed-by: Torsten Duwe Reviewed-by: Balbir Singh --- arch/powerpc/Kconfig | 3 + arch/powerpc/kernel/asm-offsets.c | 4 ++ arch/powerpc/kernel/entry_64.S | 97 +++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 91da283cd658..926c0eafbee3 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -159,6 +159,7 @@ config PPC select ARCH_HAS_DEVMEM_IS_ALLOWED select HAVE_ARCH_SECCOMP_FILTER select ARCH_HAS_UBSAN_SANITIZE_ALL + select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS config GENERIC_CSUM def_bool CPU_LITTLE_ENDIAN @@ -1110,3 +1111,5 @@ config PPC_LIB_RHEAP bool source "arch/powerpc/kvm/Kconfig" + +source "kernel/livepatch/Kconfig" diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 07cebc3514f3..723efac2d917 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -86,6 +86,10 @@ int main(void) DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit)); #endif /* CONFIG_PPC64 */ +#ifdef CONFIG_LIVEPATCH + DEFINE(TI_livepatch_sp, offsetof(struct thread_info, livepatch_sp)); +#endif + DEFINE(KSP, offsetof(struct thread_struct, ksp)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); #ifdef CONFIG_BOOKE diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index ec7f8aada697..47dbede3bddd 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -1224,6 +1225,9 @@ _GLOBAL(ftrace_caller) addi r3,r3,function_trace_op@toc@l ld r5,0(r3) +#ifdef CONFIG_LIVEPATCH + mr r14,r7 /* remember old NIP */ +#endif /* Calculate ip from nip-4 into r3 for call below */ subi r3, r7, MCOUNT_INSN_SIZE @@ -1248,6 +1252,9 @@ ftrace_call: /* Load ctr with the possibly modified NIP */ ld r3, _NIP(r1) mtctr r3 +#ifdef CONFIG_LIVEPATCH + cmpd r14,r3 /* has NIP been altered? */ +#endif /* Restore gprs */ REST_8GPRS(0,r1) @@ -1265,6 +1272,11 @@ ftrace_call: ld r0, LRSAVE(r1) mtlr r0 +#ifdef CONFIG_LIVEPATCH + /* Based on the cmpd above, if the NIP was altered handle livepatch */ + bne- livepatch_handler +#endif + #ifdef CONFIG_FUNCTION_GRAPH_TRACER stdu r1, -112(r1) .globl ftrace_graph_call @@ -1281,6 +1293,91 @@ _GLOBAL(ftrace_graph_stub) _GLOBAL(ftrace_stub) blr + +#ifdef CONFIG_LIVEPATCH + /* + * This function runs in the mcount context, between two functions. As + * such it can only clobber registers which are volatile and used in + * function linkage. + * + * We get here when a function A, calls another function B, but B has + * been live patched with a new function C. + * + * On entry: + * - we have no stack frame and can not allocate one + * - LR points back to the original caller (in A) + * - CTR holds the new NIP in C + * - r0 & r12 are free + * + * r0 can't be used as the base register for a DS-form load or store, so + * we temporarily shuffle r1 (stack pointer) into r0 and then put it back. + */ +livepatch_handler: + CURRENT_THREAD_INFO(r12, r1) + + /* Save stack pointer into r0 */ + mr r0, r1 + + /* Allocate 3 x 8 bytes */ + ld r1, TI_livepatch_sp(r12) + addi r1, r1, 24 + std r1, TI_livepatch_sp(r12) + + /* Save toc & real LR on livepatch stack */ + std r2, -24(r1) + mflr r12 + std r12, -16(r1) + + /* Store stack end marker */ + lis r12, STACK_END_MAGIC@h + ori r12, r12, STACK_END_MAGIC@l + std r12, -8(r1) + + /* Restore real stack pointer */ + mr r1, r0 + + /* Put ctr in r12 for global entry and branch there */ + mfctr r12 + bctrl + + /* + * Now we are returning from the patched function to the original + * caller A. We are free to use r0 and r12, and we can use r2 until we + * restore it. + */ + + CURRENT_THREAD_INFO(r12, r1) + + /* Save stack pointer into r0 */ + mr r0, r1 + + ld r1, TI_livepatch_sp(r12) + + /* Check stack marker hasn't been trashed */ + lis r2, STACK_END_MAGIC@h + ori r2, r2, STACK_END_MAGIC@l + ld r12, -8(r1) +1: tdne r12, r2 + EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0 + + /* Restore LR & toc from livepatch stack */ + ld r12, -16(r1) + mtlr r12 + ld r2, -24(r1) + + /* Pop livepatch stack frame */ + CURRENT_THREAD_INFO(r12, r0) + subi r1, r1, 24 + std r1, TI_livepatch_sp(r12) + + /* Restore real stack pointer */ + mr r1, r0 + + /* Return to original caller of live patched function */ + blr +#endif + + #else _GLOBAL_TOC(_mcount) /* Taken from output of objdump from lib64/glibc */ -- GitLab From 497762b852bd167d56a884bc3259eaf977e3db3f Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Tue, 5 Apr 2016 11:31:37 +0200 Subject: [PATCH 2679/9938] ARM: DTS: da850: fix missing #gpio-cells in gpio node The gpio node is missing the mandatory property #gpio-cells, which is causing runtime errors when using GPIOs e.g. with gpio-leds or gpio-keys: "could not get #gpio-cells for /soc/gpio@1e26000" This fixes the problem and adds the missing parameter. The value is 2 according to the gpio-davinci.txt binding. Signed-off-by: Petr Kulhavy Signed-off-by: Sekhar Nori --- arch/arm/boot/dts/da850.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index 226cda76e77c..b0e3a4c833c3 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -312,6 +312,7 @@ gpio: gpio@1e26000 { compatible = "ti,dm6441-gpio"; gpio-controller; + #gpio-cells = <2>; reg = <0x226000 0x1000>; interrupts = <42 IRQ_TYPE_EDGE_BOTH 43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH -- GitLab From c2a3b4bca53a59f4f1a36233f0f71ad6462678b6 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 1 Apr 2016 17:42:03 +0200 Subject: [PATCH 2680/9938] ARM: dts: davinci: use proper address after @ TI has been using the physical address in DT after the @ in device nodes. The device tree convention is to use the same address that is used for the reg property. This updates all davinci DT files to use the proper convention. Signed-off-by: David Lechner Acked-by: Rob Herring Signed-off-by: Sekhar Nori --- arch/arm/boot/dts/da850-enbw-cmc.dts | 8 ++--- arch/arm/boot/dts/da850-evm.dts | 26 +++++++------- arch/arm/boot/dts/da850.dtsi | 52 ++++++++++++++-------------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/arch/arm/boot/dts/da850-enbw-cmc.dts b/arch/arm/boot/dts/da850-enbw-cmc.dts index 645549e14237..101d1a16b0ac 100644 --- a/arch/arm/boot/dts/da850-enbw-cmc.dts +++ b/arch/arm/boot/dts/da850-enbw-cmc.dts @@ -16,14 +16,14 @@ compatible = "enbw,cmc", "ti,da850"; model = "EnBW CMC"; - soc { - serial0: serial@1c42000 { + soc@1c00000 { + serial0: serial@42000 { status = "okay"; }; - serial1: serial@1d0c000 { + serial1: serial@10c000 { status = "okay"; }; - serial2: serial@1d0d000 { + serial2: serial@10d000 { status = "okay"; }; }; diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts index ef061e9a2315..1a15db8e376b 100644 --- a/arch/arm/boot/dts/da850-evm.dts +++ b/arch/arm/boot/dts/da850-evm.dts @@ -14,8 +14,8 @@ compatible = "ti,da850-evm", "ti,da850"; model = "DA850/AM1808/OMAP-L138 EVM"; - soc { - pmx_core: pinmux@1c14120 { + soc@1c00000 { + pmx_core: pinmux@14120 { status = "okay"; mcasp0_pins: pinmux_mcasp0_pins { @@ -30,19 +30,19 @@ >; }; }; - serial0: serial@1c42000 { + serial0: serial@42000 { status = "okay"; }; - serial1: serial@1d0c000 { + serial1: serial@10c000 { status = "okay"; }; - serial2: serial@1d0d000 { + serial2: serial@10d000 { status = "okay"; }; - rtc0: rtc@1c23000 { + rtc0: rtc@23000 { status = "okay"; }; - i2c0: i2c@1c22000 { + i2c0: i2c@22000 { status = "okay"; clock-frequency = <100000>; pinctrl-names = "default"; @@ -66,17 +66,17 @@ }; }; - wdt: wdt@1c21000 { + wdt: wdt@21000 { status = "okay"; }; - mmc0: mmc@1c40000 { + mmc0: mmc@40000 { max-frequency = <50000000>; bus-width = <4>; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; }; - spi1: spi@1f0e000 { + spi1: spi@30e000 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&spi1_pins &spi1_cs0_pin>; @@ -116,18 +116,18 @@ }; }; }; - mdio: mdio@1e24000 { + mdio: mdio@224000 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&mdio_pins>; bus_freq = <2200000>; }; - eth0: ethernet@1e20000 { + eth0: ethernet@220000 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&mii_pins>; }; - gpio: gpio@1e26000 { + gpio: gpio@226000 { status = "okay"; }; }; diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index b0e3a4c833c3..f05cbe070141 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -15,7 +15,7 @@ #address-cells = <1>; #size-cells = <1>; ranges; - intc: interrupt-controller { + intc: interrupt-controller@fffee000 { compatible = "ti,cp-intc"; interrupt-controller; #interrupt-cells = <1>; @@ -23,7 +23,7 @@ reg = <0xfffee000 0x2000>; }; }; - soc { + soc@1c00000 { compatible = "simple-bus"; model = "da850"; #address-cells = <1>; @@ -31,7 +31,7 @@ ranges = <0x0 0x01c00000 0x400000>; interrupt-parent = <&intc>; - pmx_core: pinmux@1c14120 { + pmx_core: pinmux@14120 { compatible = "pinctrl-single"; reg = <0x14120 0x50>; #address-cells = <1>; @@ -150,7 +150,7 @@ }; }; - edma0: edma@01c00000 { + edma0: edma@0 { compatible = "ti,edma3-tpcc"; /* eDMA3 CC0: 0x01c0 0000 - 0x01c0 7fff */ reg = <0x0 0x8000>; @@ -161,19 +161,19 @@ ti,tptcs = <&edma0_tptc0 7>, <&edma0_tptc1 0>; }; - edma0_tptc0: tptc@01c08000 { + edma0_tptc0: tptc@8000 { compatible = "ti,edma3-tptc"; reg = <0x8000 0x400>; interrupts = <13>; interrupt-names = "edm3_tcerrint"; }; - edma0_tptc1: tptc@01c08400 { + edma0_tptc1: tptc@8400 { compatible = "ti,edma3-tptc"; reg = <0x8400 0x400>; interrupts = <32>; interrupt-names = "edm3_tcerrint"; }; - edma1: edma@01e30000 { + edma1: edma@230000 { compatible = "ti,edma3-tpcc"; /* eDMA3 CC1: 0x01e3 0000 - 0x01e3 7fff */ reg = <0x230000 0x8000>; @@ -184,41 +184,41 @@ ti,tptcs = <&edma1_tptc0 7>; }; - edma1_tptc0: tptc@01e38000 { + edma1_tptc0: tptc@238000 { compatible = "ti,edma3-tptc"; reg = <0x238000 0x400>; interrupts = <95>; interrupt-names = "edm3_tcerrint"; }; - serial0: serial@1c42000 { + serial0: serial@42000 { compatible = "ns16550a"; reg = <0x42000 0x100>; reg-shift = <2>; interrupts = <25>; status = "disabled"; }; - serial1: serial@1d0c000 { + serial1: serial@10c000 { compatible = "ns16550a"; reg = <0x10c000 0x100>; reg-shift = <2>; interrupts = <53>; status = "disabled"; }; - serial2: serial@1d0d000 { + serial2: serial@10d000 { compatible = "ns16550a"; reg = <0x10d000 0x100>; reg-shift = <2>; interrupts = <61>; status = "disabled"; }; - rtc0: rtc@1c23000 { + rtc0: rtc@23000 { compatible = "ti,da830-rtc"; reg = <0x23000 0x1000>; interrupts = <19 19>; status = "disabled"; }; - i2c0: i2c@1c22000 { + i2c0: i2c@22000 { compatible = "ti,davinci-i2c"; reg = <0x22000 0x1000>; interrupts = <15>; @@ -226,12 +226,12 @@ #size-cells = <0>; status = "disabled"; }; - wdt: wdt@1c21000 { + wdt: wdt@21000 { compatible = "ti,davinci-wdt"; reg = <0x21000 0x1000>; status = "disabled"; }; - mmc0: mmc@1c40000 { + mmc0: mmc@40000 { compatible = "ti,da830-mmc"; reg = <0x40000 0x1000>; interrupts = <16>; @@ -239,7 +239,7 @@ dma-names = "rx", "tx"; status = "disabled"; }; - mmc1: mmc@1e1b000 { + mmc1: mmc@21b000 { compatible = "ti,da830-mmc"; reg = <0x21b000 0x1000>; interrupts = <72>; @@ -247,37 +247,37 @@ dma-names = "rx", "tx"; status = "disabled"; }; - ehrpwm0: ehrpwm@01f00000 { + ehrpwm0: ehrpwm@300000 { compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x300000 0x2000>; status = "disabled"; }; - ehrpwm1: ehrpwm@01f02000 { + ehrpwm1: ehrpwm@302000 { compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm"; #pwm-cells = <3>; reg = <0x302000 0x2000>; status = "disabled"; }; - ecap0: ecap@01f06000 { + ecap0: ecap@306000 { compatible = "ti,da850-ecap", "ti,am33xx-ecap"; #pwm-cells = <3>; reg = <0x306000 0x80>; status = "disabled"; }; - ecap1: ecap@01f07000 { + ecap1: ecap@307000 { compatible = "ti,da850-ecap", "ti,am33xx-ecap"; #pwm-cells = <3>; reg = <0x307000 0x80>; status = "disabled"; }; - ecap2: ecap@01f08000 { + ecap2: ecap@308000 { compatible = "ti,da850-ecap", "ti,am33xx-ecap"; #pwm-cells = <3>; reg = <0x308000 0x80>; status = "disabled"; }; - spi1: spi@1f0e000 { + spi1: spi@30e000 { #address-cells = <1>; #size-cells = <0>; compatible = "ti,da830-spi"; @@ -289,13 +289,13 @@ dma-names = "rx", "tx"; status = "disabled"; }; - mdio: mdio@1e24000 { + mdio: mdio@224000 { compatible = "ti,davinci_mdio"; #address-cells = <1>; #size-cells = <0>; reg = <0x224000 0x1000>; }; - eth0: ethernet@1e20000 { + eth0: ethernet@220000 { compatible = "ti,davinci-dm6467-emac"; reg = <0x220000 0x4000>; ti,davinci-ctrl-reg-offset = <0x3000>; @@ -309,7 +309,7 @@ 36 >; }; - gpio: gpio@1e26000 { + gpio: gpio@226000 { compatible = "ti,dm6441-gpio"; gpio-controller; #gpio-cells = <2>; @@ -324,7 +324,7 @@ status = "disabled"; }; - mcasp0: mcasp@01d00000 { + mcasp0: mcasp@100000 { compatible = "ti,da830-mcasp-audio"; reg = <0x100000 0x2000>, <0x102000 0x400000>; -- GitLab From 92d6464297d5a5f1f403cca5ec17c7427bdf18c3 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Fri, 1 Apr 2016 17:42:04 +0200 Subject: [PATCH 2681/9938] ARM: DTS: da850: add node for i2c1 da850 has two I2C controllers, but the node for i2c1 was missing. Add node for i2c1 controller and i2c1 pinmux pins. Signed-off-by: Petr Kulhavy [nsekhar@ti.com: fix indentation] Signed-off-by: Sekhar Nori --- arch/arm/boot/dts/da850.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index f05cbe070141..c9bf27d5ee9c 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -63,6 +63,12 @@ 0x10 0x00002200 0x0000ff00 >; }; + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,bits = < + /* I2C1_SDA, I2C1_SCL */ + 0x10 0x00440000 0x00ff0000 + >; + }; mmc0_pins: pinmux_mmc_pins { pinctrl-single,bits = < /* MMCSD0_DAT[3] MMCSD0_DAT[2] @@ -226,6 +232,14 @@ #size-cells = <0>; status = "disabled"; }; + i2c1: i2c@228000 { + compatible = "ti,davinci-i2c"; + reg = <0x228000 0x1000>; + interrupts = <51>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; wdt: wdt@21000 { compatible = "ti,davinci-wdt"; reg = <0x21000 0x1000>; -- GitLab From 6c8f73592203b8611c6ba5d4c670c82a059ecf27 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Fri, 1 Apr 2016 17:42:05 +0200 Subject: [PATCH 2682/9938] ARM: davinci: da8xx-dt: add OF_DEV_AUXDATA entry for i2c1 Add OF_DEV_AUXDATA entry for second i2c on the da850 DT board driver to use i2c clock. Signed-off-by: Petr Kulhavy Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da8xx-dt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index c4b5808ca7c1..880b94e64816 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -32,6 +32,7 @@ static void __init da8xx_init_irq(void) static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL), + OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL), OF_DEV_AUXDATA("ti,davinci-wdt", 0x01c21000, "davinci-wdt", NULL), OF_DEV_AUXDATA("ti,da830-mmc", 0x01c40000, "da830-mmc.0", NULL), OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f00000, "ehrpwm", NULL), -- GitLab From c03225fd6b6467ac027bfdb153e4a3a6d8b2c90e Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 7 Apr 2016 16:45:22 +0530 Subject: [PATCH 2683/9938] ARM: davinci_all_defconfig: enable GPIO_SYSFS CONFIG_GPIO_SYSFS provides a convenient way to access GPIOs from userspace. Enable it for DaVinci. Signed-off-by: Sekhar Nori --- arch/arm/configs/davinci_all_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index 235842c9ba96..c5bccd9d010e 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -118,6 +118,7 @@ CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_DAVINCI=y CONFIG_PINCTRL_SINGLE=y +CONFIG_GPIO_SYSFS=y CONFIG_GPIO_PCF857X=y CONFIG_WATCHDOG=y CONFIG_DAVINCI_WATCHDOG=m -- GitLab From 371a13d41599dd86e74625d542a6dc345ed1f312 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Wed, 24 Feb 2016 16:41:49 +0100 Subject: [PATCH 2684/9938] ARM: DaVinci USB: removed deprecated properties from MUSB config The following properties of the musb_hdrc_config structure are deprecated and no longer required/used by the MUSB driver: .dyn_fifo .soft_con .dma .dma_channels .eps_bits Signed-off-by: Petr Kulhavy Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/usb.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index b0a6b522575f..6ed5a54ae74d 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c @@ -19,27 +19,11 @@ #define DA8XX_USB1_BASE 0x01e25000 #if IS_ENABLED(CONFIG_USB_MUSB_HDRC) -static struct musb_hdrc_eps_bits musb_eps[] = { - { "ep1_tx", 8, }, - { "ep1_rx", 8, }, - { "ep2_tx", 8, }, - { "ep2_rx", 8, }, - { "ep3_tx", 5, }, - { "ep3_rx", 5, }, - { "ep4_tx", 5, }, - { "ep4_rx", 5, }, -}; - static struct musb_hdrc_config musb_config = { .multipoint = true, - .dyn_fifo = true, - .soft_con = true, - .dma = true, .num_eps = 5, - .dma_channels = 8, .ram_bits = 10, - .eps_bits = musb_eps, }; static struct musb_hdrc_platform_data usb_data = { -- GitLab From bc5081617faeb3b2f0c126dc37264b87af7da47f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Feb 2016 14:18:01 +0200 Subject: [PATCH 2685/9938] usb: dwc3: drop FIFO resizing logic That FIFO resizing logic was added to support OMAP5 ES1.0 which had a bogus default FIFO size. I can't remember the exact size of default FIFO, but it was less than one bulk superspeed packet (<1024) which would prevent USB3 from ever working on OMAP5 ES1.0. However, OMAP5 ES1.0 support has been dropped by commit aa2f4b16f830 ("ARM: OMAP5: id: Remove ES1.0 support") which renders FIFO resizing unnecessary. Tested-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/dwc3.txt | 4 +- .../devicetree/bindings/usb/qcom,dwc3.txt | 1 - drivers/usb/dwc3/core.c | 4 - drivers/usb/dwc3/core.h | 5 -- drivers/usb/dwc3/ep0.c | 9 -- drivers/usb/dwc3/gadget.c | 86 ------------------- drivers/usb/dwc3/platform_data.h | 1 - 7 files changed, 2 insertions(+), 108 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index fb2ad0acedbd..15695682a480 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -14,7 +14,6 @@ Optional properties: the second element is expected to be a handle to the USB3/SS PHY - phys: from the *Generic PHY* bindings - phy-names: from the *Generic PHY* bindings - - tx-fifo-resize: determines if the FIFO *has* to be reallocated. - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable - snps,disable_scramble_quirk: true when SW should disable data scrambling. Only really useful for FPGA builds. @@ -47,6 +46,8 @@ Optional properties: register for post-silicon frame length adjustment when the fladj_30mhz_sdbnd signal is invalid or incorrect. + - tx-fifo-resize: determines if the FIFO *has* to be reallocated. + This is usually a subnode to DWC3 glue to which it is connected. dwc3@4a030000 { @@ -54,5 +55,4 @@ dwc3@4a030000 { reg = <0x4a030000 0xcfff>; interrupts = <0 92 4> usb-phy = <&usb2_phy>, <&usb3,phy>; - tx-fifo-resize; }; diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt index ca164e71dd50..39acb084bce9 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt @@ -59,7 +59,6 @@ Example device nodes: interrupts = <0 205 0x4>; phys = <&hs_phy>, <&ss_phy>; phy-names = "usb2-phy", "usb3-phy"; - tx-fifo-resize; dr_mode = "host"; }; }; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index fa20f5a99d12..67d183a18baa 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -882,9 +882,6 @@ static int dwc3_probe(struct platform_device *pdev) dwc->usb3_lpm_capable = device_property_read_bool(dev, "snps,usb3_lpm_capable"); - dwc->needs_fifo_resize = device_property_read_bool(dev, - "tx-fifo-resize"); - dwc->disable_scramble_quirk = device_property_read_bool(dev, "snps,disable_scramble_quirk"); dwc->u2exit_lfps_quirk = device_property_read_bool(dev, @@ -926,7 +923,6 @@ static int dwc3_probe(struct platform_device *pdev) if (pdata->hird_threshold) hird_threshold = pdata->hird_threshold; - dwc->needs_fifo_resize = pdata->tx_fifo_resize; dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; dwc->dr_mode = pdata->dr_mode; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6254b2ff9080..7cbe9e93a6b2 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -709,9 +709,7 @@ struct dwc3_scratchpad_array { * 0 - utmi_sleep_n * 1 - utmi_l1_suspend_n * @is_fpga: true when we are using the FPGA board - * @needs_fifo_resize: not all users might want fifo resizing, flag it * @pullups_connected: true when Run/Stop bit is set - * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes. * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround * @start_config_issued: true when StartConfig command has been issued * @three_stage_setup: set if we perform a three phase setup @@ -855,9 +853,7 @@ struct dwc3 { unsigned has_lpm_erratum:1; unsigned is_utmi_l1_suspend:1; unsigned is_fpga:1; - unsigned needs_fifo_resize:1; unsigned pullups_connected:1; - unsigned resize_fifos:1; unsigned setup_packet_pending:1; unsigned three_stage_setup:1; unsigned usb3_lpm_capable:1; @@ -1025,7 +1021,6 @@ struct dwc3_gadget_ep_cmd_params { /* prototypes */ void dwc3_set_mode(struct dwc3 *dwc, u32 mode); -int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); /* check whether we are on the DWC_usb31 core */ static inline bool dwc3_is_usb31(struct dwc3 *dwc) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index eca2e6d8e041..4454de0d810c 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -586,9 +586,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - dwc->resize_fifos = true; - dwc3_trace(trace_dwc3_ep0, "resize FIFOs flag SET"); } break; @@ -1027,12 +1024,6 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) { - if (dwc->resize_fifos) { - dwc3_trace(trace_dwc3_ep0, "Resizing FIFOs"); - dwc3_gadget_resize_tx_fifos(dwc); - dwc->resize_fifos = 0; - } - WARN_ON(dwc3_ep0_start_control_status(dep)); } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d54a028cdfeb..3a5c2715a3b5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -145,92 +145,6 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) return -ETIMEDOUT; } -/** - * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case - * @dwc: pointer to our context structure - * - * This function will a best effort FIFO allocation in order - * to improve FIFO usage and throughput, while still allowing - * us to enable as many endpoints as possible. - * - * Keep in mind that this operation will be highly dependent - * on the configured size for RAM1 - which contains TxFifo -, - * the amount of endpoints enabled on coreConsultant tool, and - * the width of the Master Bus. - * - * In the ideal world, we would always be able to satisfy the - * following equation: - * - * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \ - * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes - * - * Unfortunately, due to many variables that's not always the case. - */ -int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) -{ - int last_fifo_depth = 0; - int ram1_depth; - int fifo_size; - int mdwidth; - int num; - - if (!dwc->needs_fifo_resize) - return 0; - - ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); - mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); - - /* MDWIDTH is represented in bits, we need it in bytes */ - mdwidth >>= 3; - - /* - * FIXME For now we will only allocate 1 wMaxPacketSize space - * for each enabled endpoint, later patches will come to - * improve this algorithm so that we better use the internal - * FIFO space - */ - for (num = 0; num < dwc->num_in_eps; num++) { - /* bit0 indicates direction; 1 means IN ep */ - struct dwc3_ep *dep = dwc->eps[(num << 1) | 1]; - int mult = 1; - int tmp; - - if (!(dep->flags & DWC3_EP_ENABLED)) - continue; - - if (usb_endpoint_xfer_bulk(dep->endpoint.desc) - || usb_endpoint_xfer_isoc(dep->endpoint.desc)) - mult = 3; - - /* - * REVISIT: the following assumes we will always have enough - * space available on the FIFO RAM for all possible use cases. - * Make sure that's true somehow and change FIFO allocation - * accordingly. - * - * If we have Bulk or Isochronous endpoints, we want - * them to be able to be very, very fast. So we're giving - * those endpoints a fifo_size which is enough for 3 full - * packets - */ - tmp = mult * (dep->endpoint.maxpacket + mdwidth); - tmp += mdwidth; - - fifo_size = DIV_ROUND_UP(tmp, mdwidth); - - fifo_size |= (last_fifo_depth << 16); - - dwc3_trace(trace_dwc3_gadget, "%s: Fifo Addr %04x Size %d", - dep->name, last_fifo_depth, fifo_size & 0xffff); - - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num), fifo_size); - - last_fifo_depth += (fifo_size & 0xffff); - } - - return 0; -} - void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status) { diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h index 2bb4d3ad0e6b..aaa6f00df755 100644 --- a/drivers/usb/dwc3/platform_data.h +++ b/drivers/usb/dwc3/platform_data.h @@ -23,7 +23,6 @@ struct dwc3_platform_data { enum usb_device_speed maximum_speed; enum usb_dr_mode dr_mode; - bool tx_fifo_resize; bool usb3_lpm_capable; unsigned is_utmi_l1_suspend:1; -- GitLab From ca4d44ea2a91b922e1514f5ed77f6bcf3657fd67 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 10 Mar 2016 13:53:27 +0200 Subject: [PATCH 2686/9938] usb: dwc3: gadget: always enable CSP CSP bit of TRB Control is useful for protocols such CDC EEM/ECM/NCM where we're transferring in blocks of MTU-sized requests (usually MTU is 1500 bytes). We know we will always have a short packet after two (for HS) wMaxPacketSize packets and, usually, we will have a long(-ish) queue of requests (for our g_ether gadget, we have at least 10 requests). Instead of always stopping the queue processing to interrupt, giveback and restart, let's tell dwc3 to interrupt but continue processing following request if we have anything already pending in the queue. This gave me a considerable improvement of 40% on my test setup. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3a5c2715a3b5..28d512a65ada 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -726,6 +726,9 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; else trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS; + + /* always enable Interrupt on Missed ISOC */ + trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; break; case USB_ENDPOINT_XFER_BULK: @@ -740,15 +743,14 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); } - if (!req->request.no_interrupt && !chain) - trb->ctrl |= DWC3_TRB_CTRL_IOC; + /* always enable Continue on Short Packet */ + trb->ctrl |= DWC3_TRB_CTRL_CSP; - if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; - trb->ctrl |= DWC3_TRB_CTRL_CSP; - } else if (last) { + if (!req->request.no_interrupt) + trb->ctrl |= DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI; + + if (last) trb->ctrl |= DWC3_TRB_CTRL_LST; - } if (chain) trb->ctrl |= DWC3_TRB_CTRL_CHN; -- GitLab From 8495036e986bdc7e82523d47097e7833d2782ff9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 10 Mar 2016 14:40:31 +0200 Subject: [PATCH 2687/9938] usb: dwc3: increase maximum number of TRBs per endpoint previously we were using a maximum of 32 TRBs per endpoint. With each TRB being 16 bytes long, we were using 512 bytes of memory for each endpoint. However, SLAB/SLUB will always allocate PAGE_SIZE chunks. In order to better utilize the memory we allocate and to allow deeper queues for gadgets which would benefit from it (g_ether comes to mind), let's increase the maximum to 256 TRBs which rounds up to 4096 bytes for each endpoint. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 7cbe9e93a6b2..5e17c02d3e92 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -438,7 +438,7 @@ struct dwc3_event_buffer { #define DWC3_EP_DIRECTION_TX true #define DWC3_EP_DIRECTION_RX false -#define DWC3_TRB_NUM 32 +#define DWC3_TRB_NUM 256 #define DWC3_TRB_MASK (DWC3_TRB_NUM - 1) /** -- GitLab From aa3342c8bb618ae25beccddacc3efb415c3a987b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 14 Mar 2016 11:01:31 +0200 Subject: [PATCH 2688/9938] usb: dwc3: better name for our request management lists request_list and req_queued were, well, weird naming choices. Let's give those better names and call them, respectively, pending_list and started_list. These new names better reflect what these lists are supposed to do. While at that also rename req->queued to req->started. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 10 +++---- drivers/usb/dwc3/ep0.c | 14 +++++----- drivers/usb/dwc3/gadget.c | 58 +++++++++++++++++++-------------------- drivers/usb/dwc3/gadget.h | 6 ++-- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5e17c02d3e92..4ea4b51688c1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -444,8 +444,8 @@ struct dwc3_event_buffer { /** * struct dwc3_ep - device side endpoint representation * @endpoint: usb endpoint - * @request_list: list of requests for this endpoint - * @req_queued: list of requests on this ep which have TRBs setup + * @pending_list: list of pending requests for this endpoint + * @started_list: list of started requests on this endpoint * @trb_pool: array of transaction buffers * @trb_pool_dma: dma address of @trb_pool * @free_slot: next slot which is going to be used @@ -464,8 +464,8 @@ struct dwc3_event_buffer { */ struct dwc3_ep { struct usb_ep endpoint; - struct list_head request_list; - struct list_head req_queued; + struct list_head pending_list; + struct list_head started_list; struct dwc3_trb *trb_pool; dma_addr_t trb_pool_dma; @@ -635,7 +635,7 @@ struct dwc3_request { unsigned direction:1; unsigned mapped:1; - unsigned queued:1; + unsigned started:1; }; /* diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 4454de0d810c..5e0a21b65053 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -124,7 +124,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, req->request.status = -EINPROGRESS; req->epnum = dep->number; - list_add_tail(&req->list, &dep->request_list); + list_add_tail(&req->list, &dep->pending_list); /* * Gadget driver might not be quick enough to queue a request @@ -240,7 +240,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, } /* we share one TRB for ep0/1 */ - if (!list_empty(&dep->request_list)) { + if (!list_empty(&dep->pending_list)) { ret = -EBUSY; goto out; } @@ -272,10 +272,10 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) dep->flags = DWC3_EP_ENABLED; dwc->delayed_status = false; - if (!list_empty(&dep->request_list)) { + if (!list_empty(&dep->pending_list)) { struct dwc3_request *req; - req = next_request(&dep->request_list); + req = next_request(&dep->pending_list); dwc3_gadget_giveback(dep, req, -ECONNRESET); } @@ -806,7 +806,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, trace_dwc3_complete_trb(ep0, trb); - r = next_request(&ep0->request_list); + r = next_request(&ep0->pending_list); if (!r) return; @@ -894,8 +894,8 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc, trace_dwc3_complete_trb(dep, trb); - if (!list_empty(&dep->request_list)) { - r = next_request(&dep->request_list); + if (!list_empty(&dep->pending_list)) { + r = next_request(&dep->pending_list); dwc3_gadget_giveback(dep, r, 0); } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 28d512a65ada..e6bd3a976ad9 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -151,7 +151,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, struct dwc3 *dwc = dep->dwc; int i; - if (req->queued) { + if (req->started) { i = 0; do { dep->busy_slot++; @@ -165,7 +165,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, usb_endpoint_xfer_isoc(dep->endpoint.desc)) dep->busy_slot++; } while(++i < req->request.num_mapped_sgs); - req->queued = false; + req->started = false; } list_del(&req->list); req->trb = NULL; @@ -522,19 +522,19 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) { struct dwc3_request *req; - if (!list_empty(&dep->req_queued)) { + if (!list_empty(&dep->started_list)) { dwc3_stop_active_transfer(dwc, dep->number, true); /* - giveback all requests to gadget driver */ - while (!list_empty(&dep->req_queued)) { - req = next_request(&dep->req_queued); + while (!list_empty(&dep->started_list)) { + req = next_request(&dep->started_list); dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } } - while (!list_empty(&dep->request_list)) { - req = next_request(&dep->request_list); + while (!list_empty(&dep->pending_list)) { + req = next_request(&dep->pending_list); dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } @@ -700,7 +700,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; if (!req->trb) { - dwc3_gadget_move_request_queued(req); + dwc3_gadget_move_started_request(req); req->trb = trb; req->trb_dma = dwc3_trb_dma_offset(dep, trb); req->start_slot = dep->free_slot & DWC3_TRB_MASK; @@ -824,7 +824,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) return; - list_for_each_entry_safe(req, n, &dep->request_list, list) { + list_for_each_entry_safe(req, n, &dep->pending_list, list) { unsigned length; dma_addr_t dma; last_one = false; @@ -843,7 +843,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) if (i == (request->num_mapped_sgs - 1) || sg_is_last(s)) { - if (list_empty(&dep->request_list)) + if (list_empty(&dep->pending_list)) last_one = true; chain = false; } @@ -873,7 +873,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) last_one = 1; /* Is this the last request? */ - if (list_is_last(&req->list, &dep->request_list)) + if (list_is_last(&req->list, &dep->pending_list)) last_one = 1; dwc3_prepare_one_trb(dep, req, dma, length, @@ -904,18 +904,18 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, * new requests as we try to set the IOC bit only on the last request. */ if (start_new) { - if (list_empty(&dep->req_queued)) + if (list_empty(&dep->started_list)) dwc3_prepare_trbs(dep, start_new); /* req points to the first request which will be sent */ - req = next_request(&dep->req_queued); + req = next_request(&dep->started_list); } else { dwc3_prepare_trbs(dep, start_new); /* * req points to the first request where HWO changed from 0 to 1 */ - req = next_request(&dep->req_queued); + req = next_request(&dep->started_list); } if (!req) { dep->flags |= DWC3_EP_PENDING_REQUEST; @@ -962,7 +962,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, { u32 uf; - if (list_empty(&dep->request_list)) { + if (list_empty(&dep->pending_list)) { dwc3_trace(trace_dwc3_gadget, "ISOC ep %s run out for requests", dep->name); @@ -1030,7 +1030,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (ret) return ret; - list_add_tail(&req->list, &dep->request_list); + list_add_tail(&req->list, &dep->pending_list); /* * If there are no pending requests and the endpoint isn't already @@ -1065,7 +1065,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * notion of current microframe. */ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - if (list_empty(&dep->req_queued)) { + if (list_empty(&dep->started_list)) { dwc3_stop_active_transfer(dwc, dep->number, true); dep->flags = DWC3_EP_ENABLED; } @@ -1183,13 +1183,13 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, spin_lock_irqsave(&dwc->lock, flags); - list_for_each_entry(r, &dep->request_list, list) { + list_for_each_entry(r, &dep->pending_list, list) { if (r == req) break; } if (r != req) { - list_for_each_entry(r, &dep->req_queued, list) { + list_for_each_entry(r, &dep->started_list, list) { if (r == req) break; } @@ -1229,8 +1229,8 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) if (value) { if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) || - (!list_empty(&dep->req_queued) || - !list_empty(&dep->request_list)))) { + (!list_empty(&dep->started_list) || + !list_empty(&dep->pending_list)))) { dwc3_trace(trace_dwc3_gadget, "%s: pending request, cannot halt\n", dep->name); @@ -1731,8 +1731,8 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, dep->endpoint.caps.dir_in = !!direction; dep->endpoint.caps.dir_out = !direction; - INIT_LIST_HEAD(&dep->request_list); - INIT_LIST_HEAD(&dep->req_queued); + INIT_LIST_HEAD(&dep->pending_list); + INIT_LIST_HEAD(&dep->started_list); } return 0; @@ -1829,11 +1829,11 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, * If there are still queued request * then wait, do not issue either END * or UPDATE TRANSFER, just attach next - * request in request_list during + * request in pending_list during * giveback.If any future queued request * is successfully transferred then we * will issue UPDATE TRANSFER for all - * request in the request_list. + * request in the pending_list. */ dep->flags |= DWC3_EP_MISSED_ISOC; } else { @@ -1879,7 +1879,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, int ret; do { - req = next_request(&dep->req_queued); + req = next_request(&dep->started_list); if (WARN_ON_ONCE(!req)) return 1; @@ -1905,8 +1905,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, } while (1); if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && - list_empty(&dep->req_queued)) { - if (list_empty(&dep->request_list)) { + list_empty(&dep->started_list)) { + if (list_empty(&dep->pending_list)) { /* * If there is no entry in request list then do * not issue END TRANSFER now. Just set PENDING @@ -1955,7 +1955,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, if (!(dep->flags & DWC3_EP_ENABLED)) continue; - if (!list_empty(&dep->req_queued)) + if (!list_empty(&dep->started_list)) return; } diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 18ae3eaa8b6f..f21c0fccbebd 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -68,12 +68,12 @@ static inline struct dwc3_request *next_request(struct list_head *list) return list_first_entry(list, struct dwc3_request, list); } -static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req) +static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) { struct dwc3_ep *dep = req->dep; - req->queued = true; - list_move_tail(&req->list, &dep->req_queued); + req->started = true; + list_move_tail(&req->list, &dep->started_list); } void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, -- GitLab From 46cdd1900fa7a1d7afd1f8d051e513105d0cea98 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 Mar 2016 12:26:06 +0300 Subject: [PATCH 2689/9938] usb: gadget: udc: at91: use PTR_ERR_OR_ZERO() coccicheck found this pattern which could be converted to PTR_ERR_OR_ZERO(). No functional changes. Acked-by: Nicolas Ferre Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/at91_udc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c index d0d18947f58b..8bc78418d40e 100644 --- a/drivers/usb/gadget/udc/at91_udc.c +++ b/drivers/usb/gadget/udc/at91_udc.c @@ -1726,10 +1726,7 @@ static int at91sam9261_udc_init(struct at91_udc *udc) udc->matrix = syscon_regmap_lookup_by_phandle(udc->pdev->dev.of_node, "atmel,matrix"); - if (IS_ERR(udc->matrix)) - return PTR_ERR(udc->matrix); - - return 0; + return PTR_ERR_OR_ZERO(udc->matrix); } static void at91sam9261_udc_pullup(struct at91_udc *udc, int is_on) -- GitLab From acd877f4ec69639c825725091eb3749d36fd11b3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 Mar 2016 12:27:14 +0300 Subject: [PATCH 2690/9938] usb: phy: qcom: use PTR_ERR_OR_ZERO() coccicheck found this pattern which could be converted to PTR_ERR_OR_ZERO(). No functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-qcom-8x16-usb.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c index 3d7af85aecb9..d8593adb3621 100644 --- a/drivers/usb/phy/phy-qcom-8x16-usb.c +++ b/drivers/usb/phy/phy-qcom-8x16-usb.c @@ -240,10 +240,7 @@ static int phy_8x16_read_devicetree(struct phy_8x16 *qphy) qphy->switch_gpio = devm_gpiod_get_optional(dev, "switch", GPIOD_OUT_LOW); - if (IS_ERR(qphy->switch_gpio)) - return PTR_ERR(qphy->switch_gpio); - - return 0; + return PTR_ERR_OR_ZERO(qphy->switch_gpio); } static int phy_8x16_reboot_notify(struct notifier_block *this, -- GitLab From 660e9bde74d6915227d7ee3485b11e5f52637b26 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 30 Mar 2016 09:26:24 +0300 Subject: [PATCH 2691/9938] usb: dwc3: remove num_event_buffers We never, ever route any of the other event buffers so we might as well drop support for them. Until someone has a real, proper benefit for multiple event buffers, we will rely on a single one. This also helps reduce memory footprint of dwc3.ko which won't allocate memory for the extra event buffers. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 81 ++++++++++++++++----------------------- drivers/usb/dwc3/core.h | 2 - drivers/usb/dwc3/gadget.c | 38 ++++++------------ 3 files changed, 44 insertions(+), 77 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 67d183a18baa..9e5c57c7943d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -203,13 +203,10 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, static void dwc3_free_event_buffers(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; - int i; - for (i = 0; i < dwc->num_event_buffers; i++) { - evt = dwc->ev_buffs[i]; - if (evt) - dwc3_free_one_event_buffer(dwc, evt); - } + evt = dwc->ev_buffs[0]; + if (evt) + dwc3_free_one_event_buffer(dwc, evt); } /** @@ -222,27 +219,19 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) */ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) { - int num; - int i; - - num = DWC3_NUM_INT(dwc->hwparams.hwparams1); - dwc->num_event_buffers = num; + struct dwc3_event_buffer *evt; - dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, + dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs), GFP_KERNEL); if (!dwc->ev_buffs) return -ENOMEM; - for (i = 0; i < num; i++) { - struct dwc3_event_buffer *evt; - - evt = dwc3_alloc_one_event_buffer(dwc, length); - if (IS_ERR(evt)) { - dev_err(dwc->dev, "can't allocate event buffer\n"); - return PTR_ERR(evt); - } - dwc->ev_buffs[i] = evt; + evt = dwc3_alloc_one_event_buffer(dwc, length); + if (IS_ERR(evt)) { + dev_err(dwc->dev, "can't allocate event buffer\n"); + return PTR_ERR(evt); } + dwc->ev_buffs[0] = evt; return 0; } @@ -256,25 +245,22 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) static int dwc3_event_buffers_setup(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; - int n; - for (n = 0; n < dwc->num_event_buffers; n++) { - evt = dwc->ev_buffs[n]; - dwc3_trace(trace_dwc3_core, - "Event buf %p dma %08llx length %d\n", - evt->buf, (unsigned long long) evt->dma, - evt->length); - - evt->lpos = 0; - - dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), - lower_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), - upper_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), - DWC3_GEVNTSIZ_SIZE(evt->length)); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); - } + evt = dwc->ev_buffs[0]; + dwc3_trace(trace_dwc3_core, + "Event buf %p dma %08llx length %d\n", + evt->buf, (unsigned long long) evt->dma, + evt->length); + + evt->lpos = 0; + + dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), + lower_32_bits(evt->dma)); + dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), + upper_32_bits(evt->dma)); + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), + DWC3_GEVNTSIZ_SIZE(evt->length)); + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); return 0; } @@ -282,19 +268,16 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc) static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; - int n; - for (n = 0; n < dwc->num_event_buffers; n++) { - evt = dwc->ev_buffs[n]; + evt = dwc->ev_buffs[0]; - evt->lpos = 0; + evt->lpos = 0; - dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK - | DWC3_GEVNTSIZ_SIZE(0)); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); - } + dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); + dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK + | DWC3_GEVNTSIZ_SIZE(0)); + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); } static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4ea4b51688c1..be03999e2dfd 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -667,7 +667,6 @@ struct dwc3_scratchpad_array { * @regs: base address for our registers * @regs_size: address space size * @nr_scratch: number of scratch buffers - * @num_event_buffers: calculated number of event buffers * @u1u2: only used on revisions <1.83a for workaround * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents @@ -778,7 +777,6 @@ struct dwc3 { u32 gctl; u32 nr_scratch; - u32 num_event_buffers; u32 u1u2; u32 maximum_speed; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e6bd3a976ad9..5e6a4956655d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2602,14 +2602,14 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, } } -static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) +static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; irqreturn_t ret = IRQ_NONE; int left; u32 reg; - evt = dwc->ev_buffs[buf]; + evt = dwc->ev_buffs[0]; left = evt->count; if (!(evt->flags & DWC3_EVENT_PENDING)) @@ -2634,7 +2634,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; left -= 4; - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 4); } evt->count = 0; @@ -2642,9 +2642,9 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) ret = IRQ_HANDLED; /* Unmask interrupt */ - reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf)); + reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); reg &= ~DWC3_GEVNTSIZ_INTMASK; - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg); + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg); return ret; } @@ -2654,27 +2654,23 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) struct dwc3 *dwc = _dwc; unsigned long flags; irqreturn_t ret = IRQ_NONE; - int i; spin_lock_irqsave(&dwc->lock, flags); - - for (i = 0; i < dwc->num_event_buffers; i++) - ret |= dwc3_process_event_buf(dwc, i); - + ret = dwc3_process_event_buf(dwc); spin_unlock_irqrestore(&dwc->lock, flags); return ret; } -static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf) +static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; u32 count; u32 reg; - evt = dwc->ev_buffs[buf]; + evt = dwc->ev_buffs[0]; - count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); + count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; if (!count) return IRQ_NONE; @@ -2683,9 +2679,9 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf) evt->flags |= DWC3_EVENT_PENDING; /* Mask interrupt */ - reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf)); + reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); reg |= DWC3_GEVNTSIZ_INTMASK; - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg); + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg); return IRQ_WAKE_THREAD; } @@ -2693,18 +2689,8 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf) static irqreturn_t dwc3_interrupt(int irq, void *_dwc) { struct dwc3 *dwc = _dwc; - int i; - irqreturn_t ret = IRQ_NONE; - - for (i = 0; i < dwc->num_event_buffers; i++) { - irqreturn_t status; - status = dwc3_check_event_buf(dwc, i); - if (status == IRQ_WAKE_THREAD) - ret = status; - } - - return ret; + return dwc3_check_event_buf(dwc); } /** -- GitLab From 696c8b1282205caa5206264449f80ef756f14ef7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 30 Mar 2016 09:37:03 +0300 Subject: [PATCH 2692/9938] usb: dwc3: drop ev_buffs array we will be using a single event buffer and that renders ev_buffs array unnecessary. Let's remove it in favor of a single pointer to a single event buffer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 13 ++++--------- drivers/usb/dwc3/core.h | 2 +- drivers/usb/dwc3/gadget.c | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 9e5c57c7943d..05b7ec30266f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -204,7 +204,7 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; - evt = dwc->ev_buffs[0]; + evt = dwc->ev_buf; if (evt) dwc3_free_one_event_buffer(dwc, evt); } @@ -221,17 +221,12 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) { struct dwc3_event_buffer *evt; - dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs), - GFP_KERNEL); - if (!dwc->ev_buffs) - return -ENOMEM; - evt = dwc3_alloc_one_event_buffer(dwc, length); if (IS_ERR(evt)) { dev_err(dwc->dev, "can't allocate event buffer\n"); return PTR_ERR(evt); } - dwc->ev_buffs[0] = evt; + dwc->ev_buf = evt; return 0; } @@ -246,7 +241,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; - evt = dwc->ev_buffs[0]; + evt = dwc->ev_buf; dwc3_trace(trace_dwc3_core, "Event buf %p dma %08llx length %d\n", evt->buf, (unsigned long long) evt->dma, @@ -269,7 +264,7 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) { struct dwc3_event_buffer *evt; - evt = dwc->ev_buffs[0]; + evt = dwc->ev_buf; evt->lpos = 0; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index be03999e2dfd..df72234a805b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -753,7 +753,7 @@ struct dwc3 { struct platform_device *xhci; struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM]; - struct dwc3_event_buffer **ev_buffs; + struct dwc3_event_buffer *ev_buf; struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; struct usb_gadget gadget; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5e6a4956655d..96dfde011c76 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2609,7 +2609,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc) int left; u32 reg; - evt = dwc->ev_buffs[0]; + evt = dwc->ev_buf; left = evt->count; if (!(evt->flags & DWC3_EVENT_PENDING)) @@ -2668,7 +2668,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) u32 count; u32 reg; - evt = dwc->ev_buffs[0]; + evt = dwc->ev_buf; count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; -- GitLab From 2f44a8d141bcfc866d7f3672563a7da735dacce6 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 29 Feb 2016 16:33:24 -0600 Subject: [PATCH 2693/9938] ARM: davinci: simplify call to of populate Take advantage of of_platoform_default_populate convience function. Signed-off-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da8xx-dt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index c4b5808ca7c1..358ab34c4f94 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -54,9 +54,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { static void __init da850_init_machine(void) { - of_platform_populate(NULL, of_default_bus_match_table, - da850_auxdata_lookup, NULL); - + of_platform_default_populate(NULL, da850_auxdata_lookup, NULL); } static const char *const da850_boards_compat[] __initconst = { -- GitLab From 9fb69a27e938ca1079c16c213f5e8c8d90d6e2f3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 29 Feb 2016 16:33:25 -0600 Subject: [PATCH 2694/9938] ARM: davinci: remove unused DA8XX_NUM_UARTS DA8X_NUM_UARTS not used in the code anywhere and should be determined by DT anyway. Signed-off-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da8xx-dt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index 358ab34c4f94..08880e70bc03 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -18,8 +18,6 @@ #include "cp_intc.h" #include -#define DA8XX_NUM_UARTS 3 - static const struct of_device_id const da8xx_irq_match[] __initconst = { { .compatible = "ti,cp-intc", .data = cp_intc_of_init, }, { } -- GitLab From 9a7f2fc8408fdc0e3b417f670c17ed70d5d1c114 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 29 Feb 2016 16:33:26 -0600 Subject: [PATCH 2695/9938] ARM: davinci: use IRQCHIP_DECLARE for cp_intc Remove boilerplate code by using IRQCHIP_DECLARE macro. Signed-off-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/cp_intc.c | 3 +++ arch/arm/mach-davinci/da8xx-dt.c | 11 ----------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index 1a68d2477de6..94085d21018e 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -210,3 +211,5 @@ void __init cp_intc_init(void) { cp_intc_of_init(NULL, NULL); } + +IRQCHIP_DECLARE(cp_intc, "ti,cp-intc", cp_intc_of_init); diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index 08880e70bc03..fac6d43e7fdb 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -18,16 +18,6 @@ #include "cp_intc.h" #include -static const struct of_device_id const da8xx_irq_match[] __initconst = { - { .compatible = "ti,cp-intc", .data = cp_intc_of_init, }, - { } -}; - -static void __init da8xx_init_irq(void) -{ - of_irq_init(da8xx_irq_match); -} - static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL), OF_DEV_AUXDATA("ti,davinci-wdt", 0x01c21000, "davinci-wdt", NULL), @@ -64,7 +54,6 @@ static const char *const da850_boards_compat[] __initconst = { DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x") .map_io = da850_init, - .init_irq = da8xx_init_irq, .init_time = davinci_timer_init, .init_machine = da850_init_machine, .dt_compat = da850_boards_compat, -- GitLab From 9cb9480e473b910e226312574f997bec29f47ae4 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 11 Apr 2016 17:28:34 +0200 Subject: [PATCH 2696/9938] i2c: octeon: Rename [read|write]_sw to reg_[read|write] Rename the [read|write]_sw functions to make it clearer they access the TWSI registers. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 52 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index f647667a3a47..43498a427d16 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -80,14 +80,14 @@ struct octeon_i2c { }; /** - * octeon_i2c_write_sw - write an I2C core register + * octeon_i2c_reg_write - write an I2C core register * @i2c: The struct octeon_i2c * @eop_reg: Register selector * @data: Value to be written * * The I2C core registers are accessed indirectly via the SW_TWSI CSR. */ -static void octeon_i2c_write_sw(struct octeon_i2c *i2c, u64 eop_reg, u8 data) +static void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data) { u64 tmp; @@ -98,7 +98,7 @@ static void octeon_i2c_write_sw(struct octeon_i2c *i2c, u64 eop_reg, u8 data) } /** - * octeon_i2c_read_sw - read lower bits of an I2C core register + * octeon_i2c_reg_read - read lower bits of an I2C core register * @i2c: The struct octeon_i2c * @eop_reg: Register selector * @@ -106,7 +106,7 @@ static void octeon_i2c_write_sw(struct octeon_i2c *i2c, u64 eop_reg, u8 data) * * The I2C core registers are accessed indirectly via the SW_TWSI CSR. */ -static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg) +static u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) { u64 tmp; @@ -189,7 +189,7 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) static int octeon_i2c_test_iflg(struct octeon_i2c *i2c) { - return (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_CTL) & TWSI_CTL_IFLG) != 0; + return (octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) & TWSI_CTL_IFLG) != 0; } /** @@ -252,8 +252,8 @@ static void octeon_i2c_set_clock(struct octeon_i2c *i2c) } } } - octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); + octeon_i2c_reg_write(i2c, SW_TWSI_OP_TWSI_CLK, thp); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); } static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) @@ -262,14 +262,14 @@ static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) int tries; /* disable high level controller, enable bus access */ - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); /* reset controller */ - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0); for (tries = 10; tries; tries--) { udelay(1); - status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + status = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); if (status == STAT_IDLE) return 0; } @@ -288,19 +288,19 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) int result; u8 data; - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB | TWSI_CTL_STA); result = octeon_i2c_wait(i2c); if (result) { - if (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT) == STAT_IDLE) { + if (octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) == STAT_IDLE) { /* * Controller refused to send start flag May * be a client is holding SDA low - let's try * to free it. */ octeon_i2c_unblock(i2c); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB | TWSI_CTL_STA); result = octeon_i2c_wait(i2c); } @@ -308,7 +308,7 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) return result; } - data = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + data = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); if ((data != STAT_START) && (data != STAT_RSTART)) { dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data); return -EIO; @@ -320,7 +320,7 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) /* send STOP to the bus */ static void octeon_i2c_stop(struct octeon_i2c *i2c) { - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB | TWSI_CTL_STP); } @@ -345,15 +345,15 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, if (result) return result; - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, target << 1); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, target << 1); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) return result; for (i = 0; i < length; i++) { - tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + tmp = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) { dev_err(i2c->dev, @@ -362,8 +362,8 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, return -EIO; } - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, data[i]); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, data[i]); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) @@ -398,15 +398,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, if (result) return result; - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, (target << 1) | 1); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, (target << 1) | 1); + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) return result; for (i = 0; i < length; i++) { - tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + tmp = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) { dev_err(i2c->dev, @@ -416,17 +416,17 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, } if (i + 1 < length) - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB | TWSI_CTL_AAK); else - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) return result; - data[i] = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_DATA); + data[i] = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA); if (recv_len && i == 0) { if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) { dev_err(i2c->dev, -- GitLab From c57db7098b72f406a4834b4b74268db54eae3fb7 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 11 Apr 2016 17:28:35 +0200 Subject: [PATCH 2697/9938] i2c: octeon: Introduce helper functions for register access Add helper functions for control, data and status register access. This simplifies the code and makes the purpose of the register access clearer. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 56 ++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 43498a427d16..b25c49151ea4 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -97,6 +97,11 @@ static void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data) } while ((tmp & SW_TWSI_V) != 0); } +#define octeon_i2c_ctl_write(i2c, val) \ + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, val) +#define octeon_i2c_data_write(i2c, val) \ + octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, val) + /** * octeon_i2c_reg_read - read lower bits of an I2C core register * @i2c: The struct octeon_i2c @@ -118,6 +123,13 @@ static u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) return tmp & 0xFF; } +#define octeon_i2c_ctl_read(i2c) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) +#define octeon_i2c_data_read(i2c) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA) +#define octeon_i2c_stat_read(i2c) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) + /** * octeon_i2c_write_int - write the TWSI_INT register * @i2c: The struct octeon_i2c @@ -189,7 +201,7 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) static int octeon_i2c_test_iflg(struct octeon_i2c *i2c) { - return (octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) & TWSI_CTL_IFLG) != 0; + return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG) != 0; } /** @@ -262,14 +274,14 @@ static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) int tries; /* disable high level controller, enable bus access */ - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); /* reset controller */ octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0); for (tries = 10; tries; tries--) { udelay(1); - status = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); + status = octeon_i2c_stat_read(i2c); if (status == STAT_IDLE) return 0; } @@ -288,27 +300,25 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) int result; u8 data; - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_STA); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); result = octeon_i2c_wait(i2c); if (result) { - if (octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) == STAT_IDLE) { + if (octeon_i2c_stat_read(i2c) == STAT_IDLE) { /* * Controller refused to send start flag May * be a client is holding SDA low - let's try * to free it. */ octeon_i2c_unblock(i2c); - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_STA); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); result = octeon_i2c_wait(i2c); } if (result) return result; } - data = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); + data = octeon_i2c_stat_read(i2c); if ((data != STAT_START) && (data != STAT_RSTART)) { dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data); return -EIO; @@ -320,8 +330,7 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) /* send STOP to the bus */ static void octeon_i2c_stop(struct octeon_i2c *i2c) { - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_STP); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STP); } /** @@ -345,15 +354,15 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, if (result) return result; - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, target << 1); - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_data_write(i2c, target << 1); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) return result; for (i = 0; i < length; i++) { - tmp = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); + tmp = octeon_i2c_stat_read(i2c); if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) { dev_err(i2c->dev, @@ -362,8 +371,8 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, return -EIO; } - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, data[i]); - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_data_write(i2c, data[i]); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) @@ -398,16 +407,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, if (result) return result; - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, (target << 1) | 1); - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + octeon_i2c_data_write(i2c, (target << 1) | 1); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) return result; for (i = 0; i < length; i++) { - tmp = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT); - + tmp = octeon_i2c_stat_read(i2c); if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) { dev_err(i2c->dev, "%s: bad status before read (0x%x)\n", @@ -416,17 +424,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, } if (i + 1 < length) - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_AAK); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK); else - octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); result = octeon_i2c_wait(i2c); if (result) return result; - data[i] = octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA); + data[i] = octeon_i2c_data_read(i2c); if (recv_len && i == 0) { if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) { dev_err(i2c->dev, -- GitLab From b69e5c672d57fa300fef368106ab61c9214a760d Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 11 Apr 2016 17:28:36 +0200 Subject: [PATCH 2698/9938] i2c: octeon: Remove superfluous check in octeon_i2c_test_iflg Remove superfluous check and stray newline. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index b25c49151ea4..4275007c2907 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -198,10 +198,9 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) return IRQ_HANDLED; } - static int octeon_i2c_test_iflg(struct octeon_i2c *i2c) { - return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG) != 0; + return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG); } /** -- GitLab From 5f1a7ab28e92e082dd8155961a0fe26db04c4f49 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 12 Apr 2016 14:02:28 +0930 Subject: [PATCH 2699/9938] doc/devicetree: Add Aspeed and Tyan to vendor-prefixes ASPEED Technology Inc is a fabless IC-design company. Their web site is http://www.aspeedtech.com/. Tyan is a manufactuer of server and workstation platforms. Signed-off-by: Joel Stanley --- Documentation/devicetree/bindings/vendor-prefixes.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 86740d4a270d..192843189ceb 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -29,6 +29,7 @@ arm ARM Ltd. armadeus ARMadeus Systems SARL artesyn Artesyn Embedded Technologies Inc. asahi-kasei Asahi Kasei Corp. +aspeed ASPEED Technology Inc. atlas Atlas Scientific LLC atmel Atmel Corporation auo AU Optronics Corporation @@ -250,6 +251,7 @@ tplink TP-LINK Technologies Co., Ltd. tronfy Tronfy tronsmart Tronsmart truly Truly Semiconductors Limited +tyan Tyan Computer Corporation upisemi uPI Semiconductor Corp. urt United Radiant Technology Corporation usi Universal Scientific Industrial Co., Ltd. -- GitLab From 86cad16087a8cdad88c1ac124afde4de01500c21 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 24 Mar 2016 18:51:28 -0500 Subject: [PATCH 2700/9938] ARM: davinci: da8xx: move usb code to new file We will be adding more da8xx-specific code for phy and clocks, so it will be better to have this in a separate file. This way we don't have a bunch of #ifdefs for all of the da8xx stuff. While at it, fix some checkpatch warnings coming from existing code. Signed-off-by: David Lechner [nsekhar@ti.com: typo and checkpatch fixes] Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/Makefile | 4 +- arch/arm/mach-davinci/usb-da8xx.c | 107 ++++++++++++++++++++++++++++++ arch/arm/mach-davinci/usb.c | 73 -------------------- 3 files changed, 109 insertions(+), 75 deletions(-) create mode 100644 arch/arm/mach-davinci/usb-da8xx.c diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 2e3464b8bab4..da4c336b4637 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -14,8 +14,8 @@ obj-$(CONFIG_ARCH_DAVINCI_DM644x) += dm644x.o devices.o obj-$(CONFIG_ARCH_DAVINCI_DM355) += dm355.o devices.o obj-$(CONFIG_ARCH_DAVINCI_DM646x) += dm646x.o devices.o obj-$(CONFIG_ARCH_DAVINCI_DM365) += dm365.o devices.o -obj-$(CONFIG_ARCH_DAVINCI_DA830) += da830.o devices-da8xx.o -obj-$(CONFIG_ARCH_DAVINCI_DA850) += da850.o devices-da8xx.o +obj-$(CONFIG_ARCH_DAVINCI_DA830) += da830.o devices-da8xx.o usb-da8xx.o +obj-$(CONFIG_ARCH_DAVINCI_DA850) += da850.o devices-da8xx.o usb-da8xx.o obj-$(CONFIG_AINTC) += irq.o obj-$(CONFIG_CP_INTC) += cp_intc.o diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c new file mode 100644 index 000000000000..f141f5171906 --- /dev/null +++ b/arch/arm/mach-davinci/usb-da8xx.c @@ -0,0 +1,107 @@ +/* + * DA8xx USB + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DA8XX_USB0_BASE 0x01e00000 +#define DA8XX_USB1_BASE 0x01e25000 + +#if IS_ENABLED(CONFIG_USB_MUSB_HDRC) + +static struct musb_hdrc_config musb_config = { + .multipoint = true, + .num_eps = 5, + .ram_bits = 10, +}; + +static struct musb_hdrc_platform_data usb_data = { + /* OTG requires a Mini-AB connector */ + .mode = MUSB_OTG, + .clock = "usb20", + .config = &musb_config, +}; + +static struct resource da8xx_usb20_resources[] = { + { + .start = DA8XX_USB0_BASE, + .end = DA8XX_USB0_BASE + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_DA8XX_USB_INT, + .flags = IORESOURCE_IRQ, + .name = "mc", + }, +}; + +static u64 usb_dmamask = DMA_BIT_MASK(32); + +static struct platform_device usb_dev = { + .name = "musb-da8xx", + .id = -1, + .dev = { + .platform_data = &usb_data, + .dma_mask = &usb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = da8xx_usb20_resources, + .num_resources = ARRAY_SIZE(da8xx_usb20_resources), +}; + +int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt) +{ + usb_data.power = mA > 510 ? 255 : mA / 2; + usb_data.potpgt = (potpgt + 1) / 2; + + return platform_device_register(&usb_dev); +} + +#else + +int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt) +{ + return 0; +} + +#endif /* CONFIG_USB_MUSB_HDRC */ + +static struct resource da8xx_usb11_resources[] = { + [0] = { + .start = DA8XX_USB1_BASE, + .end = DA8XX_USB1_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_DA8XX_IRQN, + .end = IRQ_DA8XX_IRQN, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device da8xx_usb11_device = { + .name = "ohci", + .id = 0, + .dev = { + .dma_mask = &da8xx_usb11_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(da8xx_usb11_resources), + .resource = da8xx_usb11_resources, +}; + +int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata) +{ + da8xx_usb11_device.dev.platform_data = pdata; + return platform_device_register(&da8xx_usb11_device); +} diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index 6ed5a54ae74d..0e7e89c1f331 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c @@ -10,14 +10,10 @@ #include #include #include -#include #include #define DAVINCI_USB_OTG_BASE 0x01c64000 -#define DA8XX_USB0_BASE 0x01e00000 -#define DA8XX_USB1_BASE 0x01e25000 - #if IS_ENABLED(CONFIG_USB_MUSB_HDRC) static struct musb_hdrc_config musb_config = { .multipoint = true, @@ -81,79 +77,10 @@ void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms) platform_device_register(&usb_dev); } -#ifdef CONFIG_ARCH_DAVINCI_DA8XX -static struct resource da8xx_usb20_resources[] = { - { - .start = DA8XX_USB0_BASE, - .end = DA8XX_USB0_BASE + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_DA8XX_USB_INT, - .flags = IORESOURCE_IRQ, - .name = "mc", - }, -}; - -int __init da8xx_register_usb20(unsigned mA, unsigned potpgt) -{ - usb_data.clock = "usb20"; - usb_data.power = mA > 510 ? 255 : mA / 2; - usb_data.potpgt = (potpgt + 1) / 2; - - usb_dev.resource = da8xx_usb20_resources; - usb_dev.num_resources = ARRAY_SIZE(da8xx_usb20_resources); - usb_dev.name = "musb-da8xx"; - - return platform_device_register(&usb_dev); -} -#endif /* CONFIG_DAVINCI_DA8XX */ - #else void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms) { } -#ifdef CONFIG_ARCH_DAVINCI_DA8XX -int __init da8xx_register_usb20(unsigned mA, unsigned potpgt) -{ - return 0; -} -#endif - #endif /* CONFIG_USB_MUSB_HDRC */ - -#ifdef CONFIG_ARCH_DAVINCI_DA8XX -static struct resource da8xx_usb11_resources[] = { - [0] = { - .start = DA8XX_USB1_BASE, - .end = DA8XX_USB1_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_DA8XX_IRQN, - .end = IRQ_DA8XX_IRQN, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device da8xx_usb11_device = { - .name = "ohci", - .id = 0, - .dev = { - .dma_mask = &da8xx_usb11_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(da8xx_usb11_resources), - .resource = da8xx_usb11_resources, -}; - -int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata) -{ - da8xx_usb11_device.dev.platform_data = pdata; - return platform_device_register(&da8xx_usb11_device); -} -#endif /* CONFIG_DAVINCI_DA8XX */ -- GitLab From 8a9d088f66f84d7317b4adc64d3d3114f1ee8583 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 24 Mar 2016 18:51:30 -0500 Subject: [PATCH 2701/9938] ARM: davinci: clk: add set_parent callback for mux clocks Introduce a set_parent callback that will be used for mux clocks, such as the USB PHY muxes and the async3 clock domain mux. Signed-off-by: David Lechner [nsekhar@ti.com: checkpatch fixes] Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/clock.c | 19 ++++++++++++++++++- arch/arm/mach-davinci/clock.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 3424eac6b588..34b4f9fda35d 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -195,6 +195,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent) return -EINVAL; mutex_lock(&clocks_mutex); + if (clk->set_parent) { + int ret = clk->set_parent(clk, parent); + + if (ret) { + mutex_unlock(&clocks_mutex); + return ret; + } + } clk->parent = parent; list_del_init(&clk->childnode); list_add(&clk->childnode, &clk->parent->children); @@ -224,8 +232,17 @@ int clk_register(struct clk *clk) mutex_lock(&clocks_mutex); list_add_tail(&clk->node, &clocks); - if (clk->parent) + if (clk->parent) { + if (clk->set_parent) { + int ret = clk->set_parent(clk, clk->parent); + + if (ret) { + mutex_unlock(&clocks_mutex); + return ret; + } + } list_add_tail(&clk->childnode, &clk->parent->children); + } mutex_unlock(&clocks_mutex); /* If rate is already set, use it */ diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 1e4e836173a1..e2a5437a1aee 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -106,6 +106,7 @@ struct clk { int (*reset) (struct clk *clk, bool reset); void (*clk_enable) (struct clk *clk); void (*clk_disable) (struct clk *clk); + int (*set_parent) (struct clk *clk, struct clk *parent); }; /* Clock flags: SoC-specific flags start at BIT(16) */ -- GitLab From 4a91c45ea57c4974c797b89dfed19e946a774787 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Apr 2016 12:36:16 +0300 Subject: [PATCH 2702/9938] leds: tca6507: silence an uninitialized variable warning If choose_times() returns -EINVAL that means "c1" and "c2" haven't been initialized. I've added a check for that. Signed-off-by: Dan Carpenter Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-tca6507.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c index c548ea10f0f0..45222a7f4f75 100644 --- a/drivers/leds/leds-tca6507.c +++ b/drivers/leds/leds-tca6507.c @@ -327,6 +327,8 @@ static void set_times(struct tca6507_chip *tca, int bank) int result; result = choose_times(tca->bank[bank].ontime, &c1, &c2); + if (result < 0) + return; dev_dbg(&tca->client->dev, "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], -- GitLab From 6fb35b9515c6300cb25022ac74f5f5617a349e18 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 13 Apr 2016 11:50:23 -0300 Subject: [PATCH 2703/9938] perf trace: Add seccomp beautifier related defines for older systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Were the detached tarball (make perf-tar-src-pkg) build was failing because those definitions aren't available in the system headers. On RHEL7, for instance: builtin-trace.c: In function ‘syscall_arg__scnprintf_seccomp_op’: builtin-trace.c:1069:7: error: ‘SECCOMP_SET_MODE_STRICT’ undeclared (first use in this function) P_SECCOMP_SET_MODE_OP(STRICT); ^ builtin-trace.c:1069:7: note: each undeclared identifier is reported only once for each function it appears in builtin-trace.c:1070:7: error: ‘SECCOMP_SET_MODE_FILTER’ undeclared (first use in this function) P_SECCOMP_SET_MODE_OP(FILTER); ^ builtin-trace.c: In function ‘syscall_arg__scnprintf_seccomp_flags’: builtin-trace.c:1091:14: error: ‘SECCOMP_FILTER_FLAG_TSYNC’ undeclared (first use in this function) P_FLAG(TSYNC); ^ Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-4f8dzzwd7g6l5dzz693u7kul@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d49c131bb5de..246866c63e5e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1059,6 +1059,13 @@ static const char *tioctls[] = { static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401); #endif /* defined(__i386__) || defined(__x86_64__) */ +#ifndef SECCOMP_SET_MODE_STRICT +#define SECCOMP_SET_MODE_STRICT 0 +#endif +#ifndef SECCOMP_SET_MODE_FILTER +#define SECCOMP_SET_MODE_FILTER 1 +#endif + static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg) { int op = arg->val; @@ -1077,6 +1084,10 @@ static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct sy #define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op +#ifndef SECCOMP_FILTER_FLAG_TSYNC +#define SECCOMP_FILTER_FLAG_TSYNC 1 +#endif + static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, struct syscall_arg *arg) { -- GitLab From a355a61e43484ac02553b34b5f84ee84ca765fd6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 13 Apr 2016 11:55:18 -0300 Subject: [PATCH 2704/9938] perf trace: Add getrandom beautifier related defines for older systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Were the detached tarball (make perf-tar-src-pkg) build was failing because those definitions aren't available in the system headers. On RHEL7, for instance: builtin-trace.c: In function ‘syscall_arg__scnprintf_getrandom_flags’: builtin-trace.c:1113:14: error: ‘GRND_RANDOM’ undeclared (first use in this function) P_FLAG(RANDOM); ^ builtin-trace.c:1114:14: error: ‘GRND_NONBLOCK’ undeclared (first use in this function) P_FLAG(NONBLOCK); ^ Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-r8496g24a3kbqynvk6617b0e@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 246866c63e5e..653d4c7422e9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1110,6 +1110,13 @@ static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, #define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags +#ifndef GRND_NONBLOCK +#define GRND_NONBLOCK 0x0001 +#endif +#ifndef GRND_RANDOM +#define GRND_RANDOM 0x0002 +#endif + static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, struct syscall_arg *arg) { -- GitLab From df4cb1678e2ea91eb66665f00c4a43d898a12697 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 13 Apr 2016 12:05:44 -0300 Subject: [PATCH 2705/9938] perf trace: Move mmap beautifiers to trace/beauty/ directory To better organize all these beautifiers. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-zbr27mdy9ssdhux3ib2nfa7j@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 159 +-------------------------------- tools/perf/trace/beauty/mmap.c | 158 ++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 158 deletions(-) create mode 100644 tools/perf/trace/beauty/mmap.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 653d4c7422e9..abd5a94f5dbe 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -39,7 +39,6 @@ #include /* FIXME: Still needed for audit_errno_to_name */ #include -#include #include #include #include @@ -49,22 +48,6 @@ #include /* For older distros: */ -#ifndef MAP_STACK -# define MAP_STACK 0x20000 -#endif - -#ifndef MADV_HWPOISON -# define MADV_HWPOISON 100 - -#endif - -#ifndef MADV_MERGEABLE -# define MADV_MERGEABLE 12 -#endif - -#ifndef MADV_UNMERGEABLE -# define MADV_UNMERGEABLE 13 -#endif #ifndef EFD_SEMAPHORE # define EFD_SEMAPHORE 1 @@ -429,147 +412,6 @@ static size_t syscall_arg__scnprintf_int(char *bf, size_t size, #define SCA_INT syscall_arg__scnprintf_int -static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, - struct syscall_arg *arg) -{ - int printed = 0, prot = arg->val; - - if (prot == PROT_NONE) - return scnprintf(bf, size, "NONE"); -#define P_MMAP_PROT(n) \ - if (prot & PROT_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ - prot &= ~PROT_##n; \ - } - - P_MMAP_PROT(EXEC); - P_MMAP_PROT(READ); - P_MMAP_PROT(WRITE); -#ifdef PROT_SEM - P_MMAP_PROT(SEM); -#endif - P_MMAP_PROT(GROWSDOWN); - P_MMAP_PROT(GROWSUP); -#undef P_MMAP_PROT - - if (prot) - printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot); - - return printed; -} - -#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot - -static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, - struct syscall_arg *arg) -{ - int printed = 0, flags = arg->val; - -#define P_MMAP_FLAG(n) \ - if (flags & MAP_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ - flags &= ~MAP_##n; \ - } - - P_MMAP_FLAG(SHARED); - P_MMAP_FLAG(PRIVATE); -#ifdef MAP_32BIT - P_MMAP_FLAG(32BIT); -#endif - P_MMAP_FLAG(ANONYMOUS); - P_MMAP_FLAG(DENYWRITE); - P_MMAP_FLAG(EXECUTABLE); - P_MMAP_FLAG(FILE); - P_MMAP_FLAG(FIXED); - P_MMAP_FLAG(GROWSDOWN); -#ifdef MAP_HUGETLB - P_MMAP_FLAG(HUGETLB); -#endif - P_MMAP_FLAG(LOCKED); - P_MMAP_FLAG(NONBLOCK); - P_MMAP_FLAG(NORESERVE); - P_MMAP_FLAG(POPULATE); - P_MMAP_FLAG(STACK); -#ifdef MAP_UNINITIALIZED - P_MMAP_FLAG(UNINITIALIZED); -#endif -#undef P_MMAP_FLAG - - if (flags) - printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); - - return printed; -} - -#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags - -static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, - struct syscall_arg *arg) -{ - int printed = 0, flags = arg->val; - -#define P_MREMAP_FLAG(n) \ - if (flags & MREMAP_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ - flags &= ~MREMAP_##n; \ - } - - P_MREMAP_FLAG(MAYMOVE); -#ifdef MREMAP_FIXED - P_MREMAP_FLAG(FIXED); -#endif -#undef P_MREMAP_FLAG - - if (flags) - printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); - - return printed; -} - -#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags - -static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, - struct syscall_arg *arg) -{ - int behavior = arg->val; - - switch (behavior) { -#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n) - P_MADV_BHV(NORMAL); - P_MADV_BHV(RANDOM); - P_MADV_BHV(SEQUENTIAL); - P_MADV_BHV(WILLNEED); - P_MADV_BHV(DONTNEED); - P_MADV_BHV(REMOVE); - P_MADV_BHV(DONTFORK); - P_MADV_BHV(DOFORK); - P_MADV_BHV(HWPOISON); -#ifdef MADV_SOFT_OFFLINE - P_MADV_BHV(SOFT_OFFLINE); -#endif - P_MADV_BHV(MERGEABLE); - P_MADV_BHV(UNMERGEABLE); -#ifdef MADV_HUGEPAGE - P_MADV_BHV(HUGEPAGE); -#endif -#ifdef MADV_NOHUGEPAGE - P_MADV_BHV(NOHUGEPAGE); -#endif -#ifdef MADV_DONTDUMP - P_MADV_BHV(DONTDUMP); -#endif -#ifdef MADV_DODUMP - P_MADV_BHV(DODUMP); -#endif -#undef P_MADV_PHV - default: break; - } - - return scnprintf(bf, size, "%#x", behavior); -} - -#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior - static size_t syscall_arg__scnprintf_flock(char *bf, size_t size, struct syscall_arg *arg) { @@ -1145,6 +987,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, .arg_parm = { [arg] = &strarray__##array, } #include "trace/beauty/pid.c" +#include "trace/beauty/mmap.c" #include "trace/beauty/mode_t.c" #include "trace/beauty/sched_policy.c" #include "trace/beauty/waitid_options.c" diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c new file mode 100644 index 000000000000..3444a4d5382d --- /dev/null +++ b/tools/perf/trace/beauty/mmap.c @@ -0,0 +1,158 @@ +#include + +static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, + struct syscall_arg *arg) +{ + int printed = 0, prot = arg->val; + + if (prot == PROT_NONE) + return scnprintf(bf, size, "NONE"); +#define P_MMAP_PROT(n) \ + if (prot & PROT_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + prot &= ~PROT_##n; \ + } + + P_MMAP_PROT(EXEC); + P_MMAP_PROT(READ); + P_MMAP_PROT(WRITE); +#ifdef PROT_SEM + P_MMAP_PROT(SEM); +#endif + P_MMAP_PROT(GROWSDOWN); + P_MMAP_PROT(GROWSUP); +#undef P_MMAP_PROT + + if (prot) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot); + + return printed; +} + +#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot + +#ifndef MAP_STACK +# define MAP_STACK 0x20000 +#endif + +static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, + struct syscall_arg *arg) +{ + int printed = 0, flags = arg->val; + +#define P_MMAP_FLAG(n) \ + if (flags & MAP_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + flags &= ~MAP_##n; \ + } + + P_MMAP_FLAG(SHARED); + P_MMAP_FLAG(PRIVATE); +#ifdef MAP_32BIT + P_MMAP_FLAG(32BIT); +#endif + P_MMAP_FLAG(ANONYMOUS); + P_MMAP_FLAG(DENYWRITE); + P_MMAP_FLAG(EXECUTABLE); + P_MMAP_FLAG(FILE); + P_MMAP_FLAG(FIXED); + P_MMAP_FLAG(GROWSDOWN); +#ifdef MAP_HUGETLB + P_MMAP_FLAG(HUGETLB); +#endif + P_MMAP_FLAG(LOCKED); + P_MMAP_FLAG(NONBLOCK); + P_MMAP_FLAG(NORESERVE); + P_MMAP_FLAG(POPULATE); + P_MMAP_FLAG(STACK); +#ifdef MAP_UNINITIALIZED + P_MMAP_FLAG(UNINITIALIZED); +#endif +#undef P_MMAP_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); + + return printed; +} + +#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags + +static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, + struct syscall_arg *arg) +{ + int printed = 0, flags = arg->val; + +#define P_MREMAP_FLAG(n) \ + if (flags & MREMAP_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + flags &= ~MREMAP_##n; \ + } + + P_MREMAP_FLAG(MAYMOVE); +#ifdef MREMAP_FIXED + P_MREMAP_FLAG(FIXED); +#endif +#undef P_MREMAP_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); + + return printed; +} + +#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags + +#ifndef MADV_HWPOISON +#define MADV_HWPOISON 100 +#endif + +#ifndef MADV_MERGEABLE +#define MADV_MERGEABLE 12 +#endif + +#ifndef MADV_UNMERGEABLE +#define MADV_UNMERGEABLE 13 +#endif + +static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, + struct syscall_arg *arg) +{ + int behavior = arg->val; + + switch (behavior) { +#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n) + P_MADV_BHV(NORMAL); + P_MADV_BHV(RANDOM); + P_MADV_BHV(SEQUENTIAL); + P_MADV_BHV(WILLNEED); + P_MADV_BHV(DONTNEED); + P_MADV_BHV(REMOVE); + P_MADV_BHV(DONTFORK); + P_MADV_BHV(DOFORK); + P_MADV_BHV(HWPOISON); +#ifdef MADV_SOFT_OFFLINE + P_MADV_BHV(SOFT_OFFLINE); +#endif + P_MADV_BHV(MERGEABLE); + P_MADV_BHV(UNMERGEABLE); +#ifdef MADV_HUGEPAGE + P_MADV_BHV(HUGEPAGE); +#endif +#ifdef MADV_NOHUGEPAGE + P_MADV_BHV(NOHUGEPAGE); +#endif +#ifdef MADV_DONTDUMP + P_MADV_BHV(DONTDUMP); +#endif +#ifdef MADV_DODUMP + P_MADV_BHV(DODUMP); +#endif +#undef P_MADV_PHV + default: break; + } + + return scnprintf(bf, size, "%#x", behavior); +} + +#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior -- GitLab From ea8dc3cefba0a0decaedc710b218a6ceffe0194a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 13 Apr 2016 12:10:19 -0300 Subject: [PATCH 2706/9938] perf trace: Move eventfd beautifiers to trace/beauty/ directory To better organize all these beautifiers. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-zrw5zz7cnrs44o5osouyutvt@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 41 +------------------------------ tools/perf/trace/beauty/eventfd.c | 38 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 40 deletions(-) create mode 100644 tools/perf/trace/beauty/eventfd.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index abd5a94f5dbe..8e090a785c5e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -47,20 +47,6 @@ #include #include -/* For older distros: */ - -#ifndef EFD_SEMAPHORE -# define EFD_SEMAPHORE 1 -#endif - -#ifndef EFD_NONBLOCK -# define EFD_NONBLOCK 00004000 -#endif - -#ifndef EFD_CLOEXEC -# define EFD_CLOEXEC 02000000 -#endif - #ifndef O_CLOEXEC # define O_CLOEXEC 02000000 #endif @@ -772,32 +758,6 @@ static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, #define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags -static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, - struct syscall_arg *arg) -{ - int printed = 0, flags = arg->val; - - if (flags == 0) - return scnprintf(bf, size, "NONE"); -#define P_FLAG(n) \ - if (flags & EFD_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ - flags &= ~EFD_##n; \ - } - - P_FLAG(SEMAPHORE); - P_FLAG(CLOEXEC); - P_FLAG(NONBLOCK); -#undef P_FLAG - - if (flags) - printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); - - return printed; -} - -#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags - static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, struct syscall_arg *arg) { @@ -986,6 +946,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ .arg_parm = { [arg] = &strarray__##array, } +#include "trace/beauty/eventfd.c" #include "trace/beauty/pid.c" #include "trace/beauty/mmap.c" #include "trace/beauty/mode_t.c" diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c new file mode 100644 index 000000000000..d64f4a9128a1 --- /dev/null +++ b/tools/perf/trace/beauty/eventfd.c @@ -0,0 +1,38 @@ +#include + +#ifndef EFD_SEMAPHORE +#define EFD_SEMAPHORE 1 +#endif + +#ifndef EFD_NONBLOCK +#define EFD_NONBLOCK 00004000 +#endif + +#ifndef EFD_CLOEXEC +#define EFD_CLOEXEC 02000000 +#endif + +static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg) +{ + int printed = 0, flags = arg->val; + + if (flags == 0) + return scnprintf(bf, size, "NONE"); +#define P_FLAG(n) \ + if (flags & EFD_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + flags &= ~EFD_##n; \ + } + + P_FLAG(SEMAPHORE); + P_FLAG(CLOEXEC); + P_FLAG(NONBLOCK); +#undef P_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); + + return printed; +} + +#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags -- GitLab From 4532f642974d871f9a50e9a09bc482eaed5394f6 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Wed, 13 Apr 2016 08:21:04 +0000 Subject: [PATCH 2707/9938] perf ordered_events: Introduce reinit() 'perf record' will use this when outputting multiple perf.data files. Signed-off-by: Wang Nan Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460535673-159866-2-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang [ Split from larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ordered-events.c | 9 +++++++++ tools/perf/util/ordered-events.h | 1 + 2 files changed, 10 insertions(+) diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index b1b9e2385f4b..fe84df1875aa 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c @@ -308,3 +308,12 @@ void ordered_events__free(struct ordered_events *oe) free(event); } } + +void ordered_events__reinit(struct ordered_events *oe) +{ + ordered_events__deliver_t old_deliver = oe->deliver; + + ordered_events__free(oe); + memset(oe, '\0', sizeof(*oe)); + ordered_events__init(oe, old_deliver); +} diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h index f403991e3bfd..e11468a9a6e4 100644 --- a/tools/perf/util/ordered-events.h +++ b/tools/perf/util/ordered-events.h @@ -49,6 +49,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve int ordered_events__flush(struct ordered_events *oe, enum oe_flush how); void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver); void ordered_events__free(struct ordered_events *oe); +void ordered_events__reinit(struct ordered_events *oe); static inline void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size) -- GitLab From b26dc73018d2e3a68cad0cf0bad902a8637f9bdf Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Wed, 13 Apr 2016 08:21:04 +0000 Subject: [PATCH 2708/9938] perf session: Make ordered_events reusable ordered_events__free() leaves linked lists and timestamps not cleared, so unable to be reused after ordered_events__free(). Which is inconvenient after 'perf record' supports generating multiple perf.data output and process build-ids for each of them. Use ordered_events__reinit() for this. Signed-off-by: Wang Nan Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460535673-159866-2-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang [ Split from larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 91d4528d71fa..ca1827c4af4a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1836,7 +1836,11 @@ static int __perf_session__process_events(struct perf_session *session, out_err: ui_progress__finish(); perf_session__warn_about_errors(session); - ordered_events__free(&session->ordered_events); + /* + * We may switching perf.data output, make ordered_events + * reusable. + */ + ordered_events__reinit(&session->ordered_events); auxtrace__free_events(session); session->one_mmap = false; return err; -- GitLab From 040f9915e99e604688c2880e0b1e5b59dbfefa54 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Wed, 13 Apr 2016 08:21:05 +0000 Subject: [PATCH 2709/9938] perf data: Add perf_data_file__switch() helper perf_data_file__switch() closes current output file, renames it, then open a new one to continue recording. It will be used by 'perf record' to split output into multiple perf.data files. Signed-off-by: Wang Nan Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460535673-159866-3-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data.c | 41 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/data.h | 11 ++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index 1921942fc2e0..be83516155ee 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c @@ -136,3 +136,44 @@ ssize_t perf_data_file__write(struct perf_data_file *file, { return writen(file->fd, buf, size); } + +int perf_data_file__switch(struct perf_data_file *file, + const char *postfix, + size_t pos, bool at_exit) +{ + char *new_filepath; + int ret; + + if (check_pipe(file)) + return -EINVAL; + if (perf_data_file__is_read(file)) + return -EINVAL; + + if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0) + return -ENOMEM; + + /* + * Only fire a warning, don't return error, continue fill + * original file. + */ + if (rename(file->path, new_filepath)) + pr_warning("Failed to rename %s to %s\n", file->path, new_filepath); + + if (!at_exit) { + close(file->fd); + ret = perf_data_file__open(file); + if (ret < 0) + goto out; + + if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) { + ret = -errno; + pr_debug("Failed to lseek to %zu: %s", + pos, strerror(errno)); + goto out; + } + } + ret = file->fd; +out: + free(new_filepath); + return ret; +} diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h index 2b15d0c95c7f..ae510ce16cb1 100644 --- a/tools/perf/util/data.h +++ b/tools/perf/util/data.h @@ -46,5 +46,14 @@ int perf_data_file__open(struct perf_data_file *file); void perf_data_file__close(struct perf_data_file *file); ssize_t perf_data_file__write(struct perf_data_file *file, void *buf, size_t size); - +/* + * If at_exit is set, only rename current perf.data to + * perf.data., continue write on original file. + * Set at_exit when flushing the last output. + * + * Return value is fd of new output. + */ +int perf_data_file__switch(struct perf_data_file *file, + const char *postfix, + size_t pos, bool at_exit); #endif /* __PERF_DATA_H */ -- GitLab From c0bdc1c461dd5b2e492c0746708a3e0da6b13515 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Wed, 13 Apr 2016 08:21:06 +0000 Subject: [PATCH 2710/9938] perf record: Turns auxtrace_snapshot_enable into 3 states auxtrace_snapshot_enable has only two states (0/1). Turns it into a triple states enum so SIGUSR2 handler can safely do other works without triggering auxtrace snapshot. Signed-off-by: Wang Nan Acked-by: Adrian Hunter Acked-by: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460535673-159866-4-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 59 ++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index eb6a199a833c..480033fb9b20 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -125,7 +125,43 @@ static int record__mmap_read(struct record *rec, int idx) static volatile int done; static volatile int signr = -1; static volatile int child_finished; -static volatile int auxtrace_snapshot_enabled; + +static volatile enum { + AUXTRACE_SNAPSHOT_OFF = -1, + AUXTRACE_SNAPSHOT_DISABLED = 0, + AUXTRACE_SNAPSHOT_ENABLED = 1, +} auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_OFF; + +static inline void +auxtrace_snapshot_on(void) +{ + auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED; +} + +static inline void +auxtrace_snapshot_enable(void) +{ + if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) + return; + auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_ENABLED; +} + +static inline void +auxtrace_snapshot_disable(void) +{ + if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) + return; + auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED; +} + +static inline bool +auxtrace_snapshot_is_enabled(void) +{ + if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) + return false; + return auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_ENABLED; +} + static volatile int auxtrace_snapshot_err; static volatile int auxtrace_record__snapshot_started; @@ -249,7 +285,7 @@ static void record__read_auxtrace_snapshot(struct record *rec) } else { auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); if (!auxtrace_snapshot_err) - auxtrace_snapshot_enabled = 1; + auxtrace_snapshot_enable(); } } @@ -615,10 +651,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); - if (rec->opts.auxtrace_snapshot_mode) + + if (rec->opts.auxtrace_snapshot_mode) { signal(SIGUSR2, snapshot_sig_handler); - else + auxtrace_snapshot_on(); + } else { signal(SIGUSR2, SIG_IGN); + } session = perf_session__new(file, false, tool); if (session == NULL) { @@ -744,12 +783,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) perf_evlist__enable(rec->evlist); } - auxtrace_snapshot_enabled = 1; + auxtrace_snapshot_enable(); for (;;) { unsigned long long hits = rec->samples; if (record__mmap_read_all(rec) < 0) { - auxtrace_snapshot_enabled = 0; + auxtrace_snapshot_disable(); err = -1; goto out_child; } @@ -787,12 +826,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * disable events in this case. */ if (done && !disabled && !target__none(&opts->target)) { - auxtrace_snapshot_enabled = 0; + auxtrace_snapshot_disable(); perf_evlist__disable(rec->evlist); disabled = true; } } - auxtrace_snapshot_enabled = 0; + auxtrace_snapshot_disable(); if (forks && workload_exec_errno) { char msg[STRERR_BUFSIZE]; @@ -1358,9 +1397,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) static void snapshot_sig_handler(int sig __maybe_unused) { - if (!auxtrace_snapshot_enabled) + if (!auxtrace_snapshot_is_enabled()) return; - auxtrace_snapshot_enabled = 0; + auxtrace_snapshot_disable(); auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); auxtrace_record__snapshot_started = 1; } -- GitLab From ecfd7a9c044e98fc3da8937e652080bc5abe7918 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Wed, 13 Apr 2016 08:21:07 +0000 Subject: [PATCH 2711/9938] perf record: Add '--timestamp-filename' option to append timestamp to output file name This option appends current timestamp to the output file name. For example: # perf record -a --timestamp-filename ^C[ perf record: Woken up 1 times to write data ] [ perf record: Dump perf.data.2015122622265847 ] [ perf record: Captured and wrote 0.742 MB perf.data. (90 samples) ] # ls perf.data.201512262226584 The timestamp will be useful for identifying each perf.data after the 'perf record' support for generating multiple output files gets introduced. Signed-off-by: Wang Nan Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1460535673-159866-5-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 53 ++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 480033fb9b20..3239a6ec9d23 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -56,6 +56,7 @@ struct record { bool no_buildid_cache; bool no_buildid_cache_set; bool buildid_all; + bool timestamp_filename; unsigned long long samples; }; @@ -531,6 +532,37 @@ record__finish_output(struct record *rec) return; } +static int +record__switch_output(struct record *rec, bool at_exit) +{ + struct perf_data_file *file = &rec->file; + int fd, err; + + /* Same Size: "2015122520103046"*/ + char timestamp[] = "InvalidTimestamp"; + + rec->samples = 0; + record__finish_output(rec); + err = fetch_current_timestamp(timestamp, sizeof(timestamp)); + if (err) { + pr_err("Failed to get current timestamp\n"); + return -EINVAL; + } + + fd = perf_data_file__switch(file, timestamp, + rec->session->header.data_offset, + at_exit); + if (fd >= 0 && !at_exit) { + rec->bytes_written = 0; + rec->session->header.data_size = 0; + } + + if (!quiet) + fprintf(stderr, "[ perf record: Dump %s.%s ]\n", + file->path, timestamp); + return fd; +} + static volatile int workload_exec_errno; /* @@ -865,11 +897,22 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) /* this will be recalculated during process_buildids() */ rec->samples = 0; - if (!err) - record__finish_output(rec); + if (!err) { + if (!rec->timestamp_filename) { + record__finish_output(rec); + } else { + fd = record__switch_output(rec, true); + if (fd < 0) { + status = fd; + goto out_delete_session; + } + } + } if (!err && !quiet) { char samples[128]; + const char *postfix = rec->timestamp_filename ? + "." : ""; if (rec->samples && !rec->opts.full_auxtrace) scnprintf(samples, sizeof(samples), @@ -877,9 +920,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) else samples[0] = '\0'; - fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", + fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", perf_data_file__size(file) / 1024.0 / 1024.0, - file->path, samples); + file->path, postfix, samples); } out_delete_session: @@ -1249,6 +1292,8 @@ struct option __record_options[] = { "file", "vmlinux pathname"), OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, "Record build-id of all DSOs regardless of hits"), + OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, + "append timestamp to output filename"), OPT_END() }; -- GitLab From 20105ca1240c3d3ac8cc79bf195022e5e5c1c3fb Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 14 Apr 2016 16:53:18 +0900 Subject: [PATCH 2712/9938] perf config: Introduce perf_config_set class This infrastructure code was designed for upcoming features of 'perf config'. That collect config key-value pairs from user and system config files (i.e. user wide ~/.perfconfig and system wide $(sysconfdir)/perfconfig) to manage perf's configs. Reviewed-by: Masami Hiramatsu Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460620401-23430-2-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/config.c | 173 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/config.h | 26 ++++++ 2 files changed, 199 insertions(+) create mode 100644 tools/perf/util/config.h diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 664490b8b327..dad7d8272168 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -13,6 +13,7 @@ #include #include "util/hist.h" /* perf_hist_config */ #include "util/llvm-utils.h" /* perf_llvm_config */ +#include "config.h" #define MAXNAME (256) @@ -524,6 +525,178 @@ int perf_config(config_fn_t fn, void *data) return ret; } +static struct perf_config_section *find_section(struct list_head *sections, + const char *section_name) +{ + struct perf_config_section *section; + + list_for_each_entry(section, sections, node) + if (!strcmp(section->name, section_name)) + return section; + + return NULL; +} + +static struct perf_config_item *find_config_item(const char *name, + struct perf_config_section *section) +{ + struct perf_config_item *item; + + list_for_each_entry(item, §ion->items, node) + if (!strcmp(item->name, name)) + return item; + + return NULL; +} + +static struct perf_config_section *add_section(struct list_head *sections, + const char *section_name) +{ + struct perf_config_section *section = zalloc(sizeof(*section)); + + if (!section) + return NULL; + + INIT_LIST_HEAD(§ion->items); + section->name = strdup(section_name); + if (!section->name) { + pr_debug("%s: strdup failed\n", __func__); + free(section); + return NULL; + } + + list_add_tail(§ion->node, sections); + return section; +} + +static struct perf_config_item *add_config_item(struct perf_config_section *section, + const char *name) +{ + struct perf_config_item *item = zalloc(sizeof(*item)); + + if (!item) + return NULL; + + item->name = strdup(name); + if (!item->name) { + pr_debug("%s: strdup failed\n", __func__); + free(item); + return NULL; + } + + list_add_tail(&item->node, §ion->items); + return item; +} + +static int set_value(struct perf_config_item *item, const char *value) +{ + char *val = strdup(value); + + if (!val) + return -1; + + zfree(&item->value); + item->value = val; + return 0; +} + +static int collect_config(const char *var, const char *value, + void *perf_config_set) +{ + int ret = -1; + char *ptr, *key; + char *section_name, *name; + struct perf_config_section *section = NULL; + struct perf_config_item *item = NULL; + struct perf_config_set *set = perf_config_set; + struct list_head *sections = &set->sections; + + key = ptr = strdup(var); + if (!key) { + pr_debug("%s: strdup failed\n", __func__); + return -1; + } + + section_name = strsep(&ptr, "."); + name = ptr; + if (name == NULL || value == NULL) + goto out_free; + + section = find_section(sections, section_name); + if (!section) { + section = add_section(sections, section_name); + if (!section) + goto out_free; + } + + item = find_config_item(name, section); + if (!item) { + item = add_config_item(section, name); + if (!item) + goto out_free; + } + + ret = set_value(item, value); + return ret; + +out_free: + free(key); + perf_config_set__delete(set); + return -1; +} + +struct perf_config_set *perf_config_set__new(void) +{ + struct perf_config_set *set = zalloc(sizeof(*set)); + + if (set) { + INIT_LIST_HEAD(&set->sections); + perf_config(collect_config, set); + } + + return set; +} + +static void perf_config_item__delete(struct perf_config_item *item) +{ + zfree(&item->name); + zfree(&item->value); + free(item); +} + +static void perf_config_section__purge(struct perf_config_section *section) +{ + struct perf_config_item *item, *tmp; + + list_for_each_entry_safe(item, tmp, §ion->items, node) { + list_del_init(&item->node); + perf_config_item__delete(item); + } +} + +static void perf_config_section__delete(struct perf_config_section *section) +{ + perf_config_section__purge(section); + zfree(§ion->name); + free(section); +} + +static void perf_config_set__purge(struct perf_config_set *set) +{ + struct perf_config_section *section, *tmp; + + list_for_each_entry_safe(section, tmp, &set->sections, node) { + list_del_init(§ion->node); + perf_config_section__delete(section); + } +} + +void perf_config_set__delete(struct perf_config_set *set) +{ + perf_config_set__purge(set); + free(set); +} + /* * Call this to report error for your variable that should not * get a boolean value (i.e. "[my] var" means "true"). diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h new file mode 100644 index 000000000000..22ec626ac718 --- /dev/null +++ b/tools/perf/util/config.h @@ -0,0 +1,26 @@ +#ifndef __PERF_CONFIG_H +#define __PERF_CONFIG_H + +#include +#include + +struct perf_config_item { + char *name; + char *value; + struct list_head node; +}; + +struct perf_config_section { + char *name; + struct list_head items; + struct list_head node; +}; + +struct perf_config_set { + struct list_head sections; +}; + +struct perf_config_set *perf_config_set__new(void); +void perf_config_set__delete(struct perf_config_set *set); + +#endif /* __PERF_CONFIG_H */ -- GitLab From 26e6aaafc8a1e862437003d6e06ba748e7177ea8 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 7 Apr 2016 17:37:08 -0400 Subject: [PATCH 2713/9938] pinctrl: tegra: clear park bit for all pins Parking bits might not be cleared by the bootloader properly (if for instance it doesn't use the device configured by that pin). Clear the park bits for all the pins during pinctrl probe. This is present on T210 platforms but not earlier ones, so for earlier generations, set parked_reg = -1 to disable. The park bit is used to prevent glitching when reprogramming pinctrl registers. Based on work by: Shravani Dingari Signed-off-by: Rhyland Klein Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/tegra/pinctrl-tegra.c | 18 ++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra.h | 6 ++++++ drivers/pinctrl/tegra/pinctrl-tegra114.c | 2 ++ drivers/pinctrl/tegra/pinctrl-tegra124.c | 2 ++ drivers/pinctrl/tegra/pinctrl-tegra20.c | 3 +++ drivers/pinctrl/tegra/pinctrl-tegra210.c | 4 ++++ drivers/pinctrl/tegra/pinctrl-tegra30.c | 2 ++ 7 files changed, 37 insertions(+) diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index 3f7fce9075ab..053d62016e5a 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -625,6 +625,22 @@ static struct pinctrl_desc tegra_pinctrl_desc = { .owner = THIS_MODULE, }; +static void tegra_pinctrl_clear_parked_bits(struct tegra_pmx *pmx) +{ + int i = 0; + const struct tegra_pingroup *g; + u32 val; + + for (i = 0; i < pmx->soc->ngroups; ++i) { + if (pmx->soc->groups[i].parked_reg >= 0) { + g = &pmx->soc->groups[i]; + val = pmx_readl(pmx, g->parked_bank, g->parked_reg); + val &= ~(1 << g->parked_bit); + pmx_writel(pmx, val, g->parked_bank, g->parked_reg); + } + } +} + static bool gpio_node_has_range(void) { struct device_node *np; @@ -725,6 +741,8 @@ int tegra_pinctrl_probe(struct platform_device *pdev, return PTR_ERR(pmx->pctl); } + tegra_pinctrl_clear_parked_bits(pmx); + if (!gpio_node_has_range()) pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h index 1615db7e3a4b..20b893443d0b 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.h +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h @@ -93,6 +93,9 @@ struct tegra_function { * @tri_reg: Tri-state register offset. * @tri_bank: Tri-state register bank. * @tri_bit: Tri-state register bit. + * @parked_reg: Parked register offset. -1 if unsupported. + * @parked_bank: Parked register bank. 0 if unsupported. + * @parked_bit: Parked register bit. 0 if unsupported. * @einput_bit: Enable-input register bit. * @odrain_bit: Open-drain register bit. * @lock_bit: Lock register bit. @@ -135,13 +138,16 @@ struct tegra_pingroup { s16 pupd_reg; s16 tri_reg; s16 drv_reg; + s16 parked_reg; u32 mux_bank:2; u32 pupd_bank:2; u32 tri_bank:2; u32 drv_bank:2; + u32 parked_bank:2; s32 mux_bit:6; s32 pupd_bit:6; s32 tri_bit:6; + s32 parked_bit:6; s32 einput_bit:6; s32 odrain_bit:6; s32 lock_bit:6; diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c index 05e49d5137ab..b831dcfa5359 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra114.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c @@ -1578,6 +1578,7 @@ static struct tegra_function tegra114_functions[] = { .lock_bit = 7, \ .ioreset_bit = PINGROUP_BIT_##ior(8), \ .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ + .parked_reg = -1, \ .drv_reg = -1, \ } @@ -1598,6 +1599,7 @@ static struct tegra_function tegra114_functions[] = { .rcv_sel_bit = -1, \ .drv_reg = DRV_PINGROUP_REG(r), \ .drv_bank = 0, \ + .parked_reg = -1, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c index 7cd44c7c296d..199d301f7c3e 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra124.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c @@ -1747,6 +1747,7 @@ static struct tegra_function tegra124_functions[] = { .lock_bit = 7, \ .ioreset_bit = PINGROUP_BIT_##ior(8), \ .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ + .parked_reg = -1, \ .drv_reg = -1, \ } @@ -1767,6 +1768,7 @@ static struct tegra_function tegra124_functions[] = { .rcv_sel_bit = -1, \ .drv_reg = DRV_PINGROUP_REG(r), \ .drv_bank = 0, \ + .parked_reg = -1, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c index 4833db4433d9..a2d0b98d72b3 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra20.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -1994,6 +1994,7 @@ static struct tegra_function tegra20_functions[] = { .tri_reg = ((tri_r) - TRISTATE_REG_A), \ .tri_bank = 0, \ .tri_bit = tri_b, \ + .parked_reg = -1, \ .einput_bit = -1, \ .odrain_bit = -1, \ .lock_bit = -1, \ @@ -2013,6 +2014,7 @@ static struct tegra_function tegra20_functions[] = { .pupd_bank = 2, \ .pupd_bit = pupd_b, \ .drv_reg = -1, \ + .parked_reg = -1, \ } /* Pin groups for drive strength registers (configurable version) */ @@ -2028,6 +2030,7 @@ static struct tegra_function tegra20_functions[] = { .tri_reg = -1, \ .drv_reg = ((r) - PINGROUP_REG_A), \ .drv_bank = 3, \ + .parked_reg = -1, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c index 252b464901c0..825bf62d939a 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra210.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c @@ -1310,6 +1310,9 @@ static struct tegra_function tegra210_functions[] = { .lock_bit = 7, \ .ioreset_bit = -1, \ .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10), \ + .parked_reg = PINGROUP_REG(r), \ + .parked_bank = 1, \ + .parked_bit = 5, \ .hsm_bit = PINGROUP_BIT_##hsm(9), \ .schmitt_bit = 12, \ .drvtype_bit = PINGROUP_BIT_##drvtype(13), \ @@ -1342,6 +1345,7 @@ static struct tegra_function tegra210_functions[] = { .rcv_sel_bit = -1, \ .drv_reg = DRV_PINGROUP_REG(r), \ .drv_bank = 0, \ + .parked_reg = -1, \ .hsm_bit = -1, \ .schmitt_bit = -1, \ .lpmd_bit = -1, \ diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c index 47b2fd8bb2e9..4dc9642c914a 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra30.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c @@ -2139,6 +2139,7 @@ static struct tegra_function tegra30_functions[] = { .lock_bit = 7, \ .ioreset_bit = PINGROUP_BIT_##ior(8), \ .rcv_sel_bit = -1, \ + .parked_reg = -1, \ .drv_reg = -1, \ } @@ -2159,6 +2160,7 @@ static struct tegra_function tegra30_functions[] = { .rcv_sel_bit = -1, \ .drv_reg = DRV_PINGROUP_REG(r), \ .drv_bank = 0, \ + .parked_reg = -1, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ -- GitLab From f30e49f1291bc309865f88126005d526421d7e3a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 8 Apr 2016 14:13:53 +0200 Subject: [PATCH 2714/9938] gpio: tps65218: use the new open drain callback The TPS65218 supports open drain mode on its three pins, with one of them configurable also as push-pull. Use the new .set_single_ended() callback to set this up properly from the core, so the core actually see it can drive the pin(s) as open drain, and does not attempt to emulate open drain by switching the pin to an input. Acked-by: Nicolas Saenz Julienne Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tps65218.c | 45 ++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index 313c0e484607..0eaeac8de9de 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -101,16 +101,6 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset) break; case 1: - /* GP02 is push-pull by default, can be set as open drain. */ - if (gpiochip_line_is_open_drain(gc, offset)) { - ret = tps65218_clear_bits(tps65218, - TPS65218_REG_CONFIG1, - TPS65218_CONFIG1_GPO2_BUF, - TPS65218_PROTECT_L1); - if (ret) - return ret; - } - /* Setup GPO2 */ ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1, TPS65218_CONFIG1_IO1_SEL, @@ -148,6 +138,40 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset) return 0; } +static int tps65218_gpio_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode) +{ + struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc); + struct tps65218 *tps65218 = tps65218_gpio->tps65218; + + switch (offset) { + case 0: + case 2: + /* GPO1 is hardwired to be open drain */ + if (mode == LINE_MODE_OPEN_DRAIN) + return 0; + return -ENOTSUPP; + case 1: + /* GPO2 is push-pull by default, can be set as open drain. */ + if (mode == LINE_MODE_OPEN_DRAIN) + return tps65218_clear_bits(tps65218, + TPS65218_REG_CONFIG1, + TPS65218_CONFIG1_GPO2_BUF, + TPS65218_PROTECT_L1); + if (mode == LINE_MODE_PUSH_PULL) + return tps65218_set_bits(tps65218, + TPS65218_REG_CONFIG1, + TPS65218_CONFIG1_GPO2_BUF, + TPS65218_CONFIG1_GPO2_BUF, + TPS65218_PROTECT_L1); + return -ENOTSUPP; + default: + break; + } + return -ENOTSUPP; +} + static struct gpio_chip template_chip = { .label = "gpio-tps65218", .owner = THIS_MODULE, @@ -156,6 +180,7 @@ static struct gpio_chip template_chip = { .direction_input = tps65218_gpio_input, .get = tps65218_gpio_get, .set = tps65218_gpio_set, + .set_single_ended = tps65218_gpio_set_single_ended, .can_sleep = true, .ngpio = 3, .base = -1, -- GitLab From d17322feecf80152303426dd724577025d1fbd7e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 10:52:26 +0200 Subject: [PATCH 2715/9938] gpio: sx150x: move platform data into driver The sx150x has some platform data definition in but this file is only included from the driver in the whole kernel so move its contents into the driver. Cc: Wei Chen Cc: Peter Rosin Acked-by: Wolfram Sang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sx150x.c | 60 +++++++++++++++++++++++++++- include/linux/i2c/sx150x.h | 82 -------------------------------------- 2 files changed, 59 insertions(+), 83 deletions(-) delete mode 100644 include/linux/i2c/sx150x.h diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d57e8ad0bfd2..d4501d5f8b8e 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -85,6 +84,65 @@ struct sx150x_device_data { } pri; }; +/** + * struct sx150x_platform_data - config data for SX150x driver + * @gpio_base: The index number of the first GPIO assigned to this + * GPIO expander. The expander will create a block of + * consecutively numbered gpios beginning at the given base, + * with the size of the block depending on the model of the + * expander chip. + * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO + * instead of as an oscillator, increasing the size of the + * GP(I)O pool created by this expander by one. The + * output-only GPO pin will be added at the end of the block. + * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor + * for each IO line in the expander. Setting the bit at + * position n will enable the pull-up for the IO at + * the corresponding offset. For chips with fewer than + * 16 IO pins, high-end bits are ignored. + * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down + * resistor for each IO line in the expander. Setting the + * bit at position n will enable the pull-down for the IO at + * the corresponding offset. For chips with fewer than + * 16 IO pins, high-end bits are ignored. + * @io_open_drain_ena: A bit-mask which enables-or disables open-drain + * operation for each IO line in the expander. Setting the + * bit at position n enables open-drain operation for + * the IO at the corresponding offset. Clearing the bit + * enables regular push-pull operation for that IO. + * For chips with fewer than 16 IO pins, high-end bits + * are ignored. + * @io_polarity: A bit-mask which enables polarity inversion for each IO line + * in the expander. Setting the bit at position n inverts + * the polarity of that IO line, while clearing it results + * in normal polarity. For chips with fewer than 16 IO pins, + * high-end bits are ignored. + * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line + * is connected, via which it reports interrupt events + * across all GPIO lines. This must be a real, + * pre-existing IRQ line. + * Setting this value < 0 disables the irq_chip functionality + * of the driver. + * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based + * IRQ lines will appear. Similarly to gpio_base, the expander + * will create a block of irqs beginning at this number. + * This value is ignored if irq_summary is < 0. + * @reset_during_probe: If set to true, the driver will trigger a full + * reset of the chip at the beginning of the probe + * in order to place it in a known state. + */ +struct sx150x_platform_data { + unsigned gpio_base; + bool oscio_is_gpo; + u16 io_pullup_ena; + u16 io_pulldn_ena; + u16 io_open_drain_ena; + u16 io_polarity; + int irq_summary; + unsigned irq_base; + bool reset_during_probe; +}; + struct sx150x_chip { struct gpio_chip gpio_chip; struct i2c_client *client; diff --git a/include/linux/i2c/sx150x.h b/include/linux/i2c/sx150x.h deleted file mode 100644 index 52baa79d69a7..000000000000 --- a/include/linux/i2c/sx150x.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Driver for the Semtech SX150x I2C GPIO Expanders - * - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -#ifndef __LINUX_I2C_SX150X_H -#define __LINUX_I2C_SX150X_H - -/** - * struct sx150x_platform_data - config data for SX150x driver - * @gpio_base: The index number of the first GPIO assigned to this - * GPIO expander. The expander will create a block of - * consecutively numbered gpios beginning at the given base, - * with the size of the block depending on the model of the - * expander chip. - * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO - * instead of as an oscillator, increasing the size of the - * GP(I)O pool created by this expander by one. The - * output-only GPO pin will be added at the end of the block. - * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor - * for each IO line in the expander. Setting the bit at - * position n will enable the pull-up for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down - * resistor for each IO line in the expander. Setting the - * bit at position n will enable the pull-down for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_open_drain_ena: A bit-mask which enables-or disables open-drain - * operation for each IO line in the expander. Setting the - * bit at position n enables open-drain operation for - * the IO at the corresponding offset. Clearing the bit - * enables regular push-pull operation for that IO. - * For chips with fewer than 16 IO pins, high-end bits - * are ignored. - * @io_polarity: A bit-mask which enables polarity inversion for each IO line - * in the expander. Setting the bit at position n inverts - * the polarity of that IO line, while clearing it results - * in normal polarity. For chips with fewer than 16 IO pins, - * high-end bits are ignored. - * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line - * is connected, via which it reports interrupt events - * across all GPIO lines. This must be a real, - * pre-existing IRQ line. - * Setting this value < 0 disables the irq_chip functionality - * of the driver. - * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based - * IRQ lines will appear. Similarly to gpio_base, the expander - * will create a block of irqs beginning at this number. - * This value is ignored if irq_summary is < 0. - * @reset_during_probe: If set to true, the driver will trigger a full - * reset of the chip at the beginning of the probe - * in order to place it in a known state. - */ -struct sx150x_platform_data { - unsigned gpio_base; - bool oscio_is_gpo; - u16 io_pullup_ena; - u16 io_pulldn_ena; - u16 io_open_drain_ena; - u16 io_polarity; - int irq_summary; - unsigned irq_base; - bool reset_during_probe; -}; - -#endif /* __LINUX_I2C_SX150X_H */ -- GitLab From 04b8695617fe6efeba5ca20e8be3a5c1879fd74a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 13:13:36 +0200 Subject: [PATCH 2716/9938] gpio: sx150x: use the new open drain callback One variant of the SX150X GPIO chip supports setting the pins in open drain mode. This is currently available to set from platform data, but completely unused in the kernel. Activate the new .set_single_ended() callback so users can set this up from e.g. device tree or board files using the new GPIO descriptors. As part of this, delete the platform data open drain setting method. Cc: Wei Chen Cc: Peter Rosin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sx150x.c | 41 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d4501d5f8b8e..a177ebd921d5 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -105,13 +105,6 @@ struct sx150x_device_data { * bit at position n will enable the pull-down for the IO at * the corresponding offset. For chips with fewer than * 16 IO pins, high-end bits are ignored. - * @io_open_drain_ena: A bit-mask which enables-or disables open-drain - * operation for each IO line in the expander. Setting the - * bit at position n enables open-drain operation for - * the IO at the corresponding offset. Clearing the bit - * enables regular push-pull operation for that IO. - * For chips with fewer than 16 IO pins, high-end bits - * are ignored. * @io_polarity: A bit-mask which enables polarity inversion for each IO line * in the expander. Setting the bit at position n inverts * the polarity of that IO line, while clearing it results @@ -136,7 +129,6 @@ struct sx150x_platform_data { bool oscio_is_gpo; u16 io_pullup_ena; u16 io_pulldn_ena; - u16 io_open_drain_ena; u16 io_polarity; int irq_summary; unsigned irq_base; @@ -415,6 +407,32 @@ static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) mutex_unlock(&chip->lock); } +static int sx150x_gpio_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode) +{ + struct sx150x_chip *chip = gpiochip_get_data(gc); + + /* On the SX160X 789 we can set open drain */ + if (chip->dev_cfg->model != SX150X_789) + return -ENOTSUPP; + + if (mode == LINE_MODE_PUSH_PULL) + return sx150x_write_cfg(chip, + offset, + 1, + chip->dev_cfg->pri.x789.reg_drain, + 0); + + if (mode == LINE_MODE_OPEN_DRAIN) + return sx150x_write_cfg(chip, + offset, + 1, + chip->dev_cfg->pri.x789.reg_drain, + 1); + return -ENOTSUPP; +} + static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) { struct sx150x_chip *chip = gpiochip_get_data(gc); @@ -569,6 +587,7 @@ static void sx150x_init_chip(struct sx150x_chip *chip, chip->gpio_chip.direction_output = sx150x_gpio_direction_output; chip->gpio_chip.get = sx150x_gpio_get; chip->gpio_chip.set = sx150x_gpio_set; + chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended; chip->gpio_chip.base = pdata->gpio_base; chip->gpio_chip.can_sleep = true; chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; @@ -657,12 +676,6 @@ static int sx150x_init_hw(struct sx150x_chip *chip, return err; if (chip->dev_cfg->model == SX150X_789) { - err = sx150x_init_io(chip, - chip->dev_cfg->pri.x789.reg_drain, - pdata->io_open_drain_ena); - if (err < 0) - return err; - err = sx150x_init_io(chip, chip->dev_cfg->pri.x789.reg_polarity, pdata->io_polarity); -- GitLab From 148c864260dad94dd037d342679cd62f664a9b21 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 15:59:41 +0200 Subject: [PATCH 2717/9938] gpio: f7188x: use BIT() macro Align to how we handle bitmasks in most drivers in the subsystem: using the BIT(n) macro over (1 << n). Cc: Peter Hung Cc: Andreas Bofjall Cc: Simon Guinot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-f7188x.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index daac2d480db1..8b10fbf787f8 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -15,7 +15,8 @@ #include #include #include -#include +#include +#include #define DRVNAME "gpio-f7188x" @@ -217,7 +218,7 @@ static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) superio_select(sio->addr, SIO_LD_GPIO); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir &= ~(1 << offset); + dir &= ~BIT(offset); superio_outb(sio->addr, gpio_dir(bank->regbase), dir); superio_exit(sio->addr); @@ -238,7 +239,7 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset) superio_select(sio->addr, SIO_LD_GPIO); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir = !!(dir & (1 << offset)); + dir = !!(dir & BIT(offset)); if (dir) data = superio_inb(sio->addr, gpio_data_out(bank->regbase)); else @@ -246,7 +247,7 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset) superio_exit(sio->addr); - return !!(data & 1 << offset); + return !!(data & BIT(offset)); } static int f7188x_gpio_direction_out(struct gpio_chip *chip, @@ -264,13 +265,13 @@ static int f7188x_gpio_direction_out(struct gpio_chip *chip, data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase)); if (value) - data_out |= (1 << offset); + data_out |= BIT(offset); else - data_out &= ~(1 << offset); + data_out &= ~BIT(offset); superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir |= (1 << offset); + dir |= BIT(offset); superio_outb(sio->addr, gpio_dir(bank->regbase), dir); superio_exit(sio->addr); @@ -292,9 +293,9 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase)); if (value) - data_out |= (1 << offset); + data_out |= BIT(offset); else - data_out &= ~(1 << offset); + data_out &= ~BIT(offset); superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out); superio_exit(sio->addr); -- GitLab From f90c6bdb690bb12f3dbe8eaa5650a9ce952d0290 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 16:11:37 +0200 Subject: [PATCH 2718/9938] gpio: f7188x: use the new open drain callback The F7188x chips supports setting the pins in open drain mode. Activate the new .set_single_ended() callback. Cc: Peter Hung Cc: Andreas Bofjall Cc: Simon Guinot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-f7188x.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 8b10fbf787f8..58674ff75097 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -130,6 +130,9 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset); static int f7188x_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value); static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value); +static int f7188x_gpio_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode); #define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \ { \ @@ -140,6 +143,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value); .get = f7188x_gpio_get, \ .direction_output = f7188x_gpio_direction_out, \ .set = f7188x_gpio_set, \ + .set_single_ended = f7188x_gpio_set_single_ended, \ .base = _base, \ .ngpio = _ngpio, \ .can_sleep = true, \ @@ -301,6 +305,35 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) superio_exit(sio->addr); } +static int f7188x_gpio_set_single_ended(struct gpio_chip *chip, + unsigned offset, + enum single_ended_mode mode) +{ + int err; + struct f7188x_gpio_bank *bank = gpiochip_get_data(chip); + struct f7188x_sio *sio = bank->data->sio; + u8 data; + + if (mode != LINE_MODE_OPEN_DRAIN && + mode != LINE_MODE_PUSH_PULL) + return -ENOTSUPP; + + err = superio_enter(sio->addr); + if (err) + return err; + superio_select(sio->addr, SIO_LD_GPIO); + + data = superio_inb(sio->addr, gpio_out_mode(bank->regbase)); + if (mode == LINE_MODE_OPEN_DRAIN) + data &= ~BIT(offset); + else + data |= BIT(offset); + superio_outb(sio->addr, gpio_data_mode(bank->regbase), data); + + superio_exit(sio->addr); + return 0; +} + /* * Platform device and driver. */ -- GitLab From 811a1882b12bbbcbd447ad8c4d16d170e196c58f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Apr 2016 21:53:39 +0200 Subject: [PATCH 2719/9938] gpio: menz127: use the new open drain callback The menz127 driver tries to support open drain by detecting it at request time. However: without the new callbacks from the gpiolib it is not really working: the core will still just emulate the open drain mode by switching the line to an input. By adding a hook into the new .set_single_ended() call rather than trying to autodetect at request() time, proper open drain can be supported. Cc: Andreas Werner Signed-off-by: Linus Walleij --- drivers/gpio/gpio-menz127.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index 8c1ab8e1974f..334fe270dcf1 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -88,21 +88,25 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, return 0; } -static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin) +static int men_z127_set_single_ended(struct gpio_chip *gc, + unsigned offset, + enum single_ended_mode mode) { struct men_z127_gpio *priv = gpiochip_get_data(gc); u32 od_en; - if (gpio_pin >= gc->ngpio) - return -EINVAL; + if (mode != LINE_MODE_OPEN_DRAIN && + mode != LINE_MODE_PUSH_PULL) + return -ENOTSUPP; spin_lock(&priv->lock); od_en = readl(priv->reg_base + MEN_Z127_ODER); - if (gpiochip_line_is_open_drain(gc, gpio_pin)) - od_en |= BIT(gpio_pin); + if (mode == LINE_MODE_OPEN_DRAIN) + od_en |= BIT(offset); else - od_en &= ~BIT(gpio_pin); + /* Implicitly LINE_MODE_PUSH_PULL */ + od_en &= ~BIT(offset); writel(od_en, priv->reg_base + MEN_Z127_ODER); spin_unlock(&priv->lock); @@ -147,7 +151,7 @@ static int men_z127_probe(struct mcb_device *mdev, goto err_unmap; men_z127_gpio->gc.set_debounce = men_z127_debounce; - men_z127_gpio->gc.request = men_z127_request; + men_z127_gpio->gc.set_single_ended = men_z127_set_single_ended; ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio); if (ret) { -- GitLab From 640b9135c888f02afd058c213303ffbd10d3908d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Apr 2016 12:26:08 +0200 Subject: [PATCH 2720/9938] gpio: vx855: use the new open drain callback The vx855 driver clearly states it has three groups of lines: GPI, GPO and GPIO. The GPO are assumedly push-pull. The GPIO are implicit open drain, but if the GPIO subsystem ask for them to be explicitly open drain (i.e. set the flag on a machine table that we want open drain) it will currently misbehave: it will switch the GPIOs to input mode (emulate open drain). Instead: indicate in the .set_single_ended() callback that we support open drain and open drain only. Cc: Daniel Drake Signed-off-by: Linus Walleij --- drivers/gpio/gpio-vx855.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c index 8cdb9f7ec7e0..4e450121129b 100644 --- a/drivers/gpio/gpio-vx855.c +++ b/drivers/gpio/gpio-vx855.c @@ -186,6 +186,28 @@ static int vx855gpio_direction_output(struct gpio_chip *gpio, return 0; } +static int vx855gpio_set_single_ended(struct gpio_chip *gpio, + unsigned int nr, + enum single_ended_mode mode) +{ + /* The GPI cannot be single-ended */ + if (nr < NR_VX855_GPI) + return -EINVAL; + + /* The GPO's are push-pull */ + if (nr < NR_VX855_GPInO) { + if (mode != LINE_MODE_PUSH_PULL) + return -ENOTSUPP; + return 0; + } + + /* The GPIO's are open drain */ + if (mode != LINE_MODE_OPEN_DRAIN) + return -ENOTSUPP; + + return 0; +} + static const char *vx855gpio_names[NR_VX855_GP] = { "VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4", "VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9", @@ -209,6 +231,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg) c->direction_output = vx855gpio_direction_output; c->get = vx855gpio_get; c->set = vx855gpio_set; + c->set_single_ended = vx855gpio_set_single_ended; c->dbg_show = NULL; c->base = 0; c->ngpio = NR_VX855_GP; -- GitLab From 51c27da19d3dbf3219afb225e1626e193c5e1c72 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Apr 2016 14:52:33 +0200 Subject: [PATCH 2721/9938] gpio: wm831x: use the new open drain callback The WM831x GPIOs clearly have a dedicated open drain control register. Implement support for controlling this from GPIO descriptor tables or other hardware descriptions such as device tree by implementing the .set_single_ended() callback. Before this patch, lines requesting open drain will just be switched to input mode by the framework, thus emulating open drain. But the hardware can do the real thing, so let's support that. As part of this, rename the debugfs string for output mode from "CMOS" to "push-pull" because it is the term used in the framework to signify a tomem-pole CMOS output. Cc: patches@opensource.wolfsonmicro.com Cc: Mark Brown Acked-by: Charles Keepax Signed-off-by: Linus Walleij --- drivers/gpio/gpio-wm831x.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index 18cb0f534b91..41ec7834059a 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -132,6 +132,28 @@ static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); } +static int wm831x_set_single_ended(struct gpio_chip *chip, + unsigned int offset, + enum single_ended_mode mode) +{ + struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip); + struct wm831x *wm831x = wm831x_gpio->wm831x; + int reg = WM831X_GPIO1_CONTROL + offset; + + switch (mode) { + case LINE_MODE_OPEN_DRAIN: + return wm831x_set_bits(wm831x, reg, + WM831X_GPN_OD_MASK, WM831X_GPN_OD); + case LINE_MODE_PUSH_PULL: + return wm831x_set_bits(wm831x, reg, + WM831X_GPN_OD_MASK, 0); + default: + break; + } + + return -ENOTSUPP; +} + #ifdef CONFIG_DEBUG_FS static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { @@ -216,7 +238,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) pull, powerdomain, reg & WM831X_GPN_POL ? "" : " inverted", - reg & WM831X_GPN_OD ? "open-drain" : "CMOS", + reg & WM831X_GPN_OD ? "open-drain" : "push-pull", tristated ? " tristated" : "", reg); } @@ -234,6 +256,7 @@ static struct gpio_chip template_chip = { .set = wm831x_gpio_set, .to_irq = wm831x_gpio_to_irq, .set_debounce = wm831x_gpio_set_debounce, + .set_single_ended = wm831x_set_single_ended, .dbg_show = wm831x_gpio_dbg_show, .can_sleep = true, }; -- GitLab From 190ea4344bc3fb97c40befd1653a92e9a59fe0f7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Apr 2016 15:07:23 +0200 Subject: [PATCH 2722/9938] gpio: wm8994: use the new open drain callback The WM8994 GPIOs clearly have a dedicated open drain control register. Implement support for controlling this from GPIO descriptor tables or other hardware descriptions such as device tree by implementing the .set_single_ended() callback. Before this patch, lines requesting open drain will just be switched to input mode by the framework, thus emulating open drain. But the hardware can do the real thing, so let's support that. As part of this, rename the debugfs string for output mode from "CMOS" to "push-pull" because it is the term used in the framework to signify a tomem-pole CMOS output. Cc: patches@opensource.wolfsonmicro.com Cc: Mark Brown Acked-by: Charles Keepax Signed-off-by: Linus Walleij --- drivers/gpio/gpio-wm8994.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index b089df99a0d0..744af388c949 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -103,6 +103,28 @@ static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value) wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value); } +static int wm8994_gpio_set_single_ended(struct gpio_chip *chip, + unsigned int offset, + enum single_ended_mode mode) +{ + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); + struct wm8994 *wm8994 = wm8994_gpio->wm8994; + + switch (mode) { + case LINE_MODE_OPEN_DRAIN: + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, + WM8994_GPN_OP_CFG_MASK, + WM8994_GPN_OP_CFG); + case LINE_MODE_PUSH_PULL: + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, + WM8994_GPN_OP_CFG_MASK, 0); + default: + break; + } + + return -ENOTSUPP; +} + static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); @@ -217,7 +239,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) if (reg & WM8994_GPN_OP_CFG) seq_printf(s, "open drain "); else - seq_printf(s, "CMOS "); + seq_printf(s, "push-pull "); seq_printf(s, "%s (%x)\n", wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg); @@ -235,6 +257,7 @@ static struct gpio_chip template_chip = { .get = wm8994_gpio_get, .direction_output = wm8994_gpio_direction_out, .set = wm8994_gpio_set, + .set_single_ended = wm8994_gpio_set_single_ended, .to_irq = wm8994_gpio_to_irq, .dbg_show = wm8994_gpio_dbg_show, .can_sleep = true, -- GitLab From 1e4a80640338924b9f9fd7a121ac31d08134410a Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 24 Feb 2016 22:05:19 +0100 Subject: [PATCH 2723/9938] gpio: gpiolib-of: Allow compile testing Lower dependencies for compile testing. Signed-off-by: Alexander Stein --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 37f03786b0e6..9776ea547a4d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -49,7 +49,7 @@ config GPIO_DEVRES config OF_GPIO def_bool y - depends on OF + depends on OF || COMPILE_TEST config GPIO_ACPI def_bool y -- GitLab From 4dd4dd1d21206cd05f5da031d709e9de8567957f Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 24 Feb 2016 20:54:32 +0100 Subject: [PATCH 2724/9938] gpio: tegra: Allow compile test Allow compile testing this driver by adding a new config option which is enabled by default and depends on the old symbol or COMPILE_TEST. Signed-off-by: Alexander Stein --- drivers/gpio/Kconfig | 5 +++++ drivers/gpio/Makefile | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9776ea547a4d..f73f26b43532 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -400,6 +400,11 @@ config GPIO_TB10X select GENERIC_IRQ_CHIP select OF_GPIO +config GPIO_TEGRA + bool + default y + depends on ARCH_TEGRA || COMPILE_TEST + config GPIO_TS4800 tristate "TS-4800 DIO blocks and compatibles" depends on OF_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 40ab9134a40c..74eb1a7b20c5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -95,7 +95,7 @@ obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o -obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o +obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o -- GitLab From 1951384cb16e50c40cc714bbaaae3cee364ba763 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 10 Apr 2016 21:39:51 +0200 Subject: [PATCH 2725/9938] pinctrl: pxa: add pxa25x architecture Add the pxa25x architecture, which is a pxa2xx with 85 pins. The registers spacing, and pins logic is common to pxa2xx, only the pins and their alternate function are specific to pxa25x. Signed-off-by: Robert Jarzmik Signed-off-by: Linus Walleij --- drivers/pinctrl/pxa/Kconfig | 10 +- drivers/pinctrl/pxa/Makefile | 1 + drivers/pinctrl/pxa/pinctrl-pxa25x.c | 274 +++++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/pxa/pinctrl-pxa25x.c diff --git a/drivers/pinctrl/pxa/Kconfig b/drivers/pinctrl/pxa/Kconfig index 990667ff772c..c29bdcfa80af 100644 --- a/drivers/pinctrl/pxa/Kconfig +++ b/drivers/pinctrl/pxa/Kconfig @@ -6,12 +6,20 @@ config PINCTRL_PXA select PINCONF select GENERIC_PINCONF +config PINCTRL_PXA25X + tristate "Marvell PXA25x pin controller driver" + select PINCTRL_PXA + default y if PXA25x + help + This is the pinctrl, pinmux, pinconf driver for the Marvell + PXA2xx block found in the pxa25x platforms. + config PINCTRL_PXA27X tristate "Marvell PXA27x pin controller driver" select PINCTRL_PXA default y if PXA27x help This is the pinctrl, pinmux, pinconf driver for the Marvell - PXA2xx block found in the pxa25x and pxa27x platforms. + PXA2xx block found in the pxa27x platforms. endif diff --git a/drivers/pinctrl/pxa/Makefile b/drivers/pinctrl/pxa/Makefile index f1d56af2bfc0..ca2ade1a177b 100644 --- a/drivers/pinctrl/pxa/Makefile +++ b/drivers/pinctrl/pxa/Makefile @@ -1,2 +1,3 @@ # Marvell PXA pin control drivers +obj-$(CONFIG_PINCTRL_PXA25X) += pinctrl-pxa2xx.o pinctrl-pxa25x.o obj-$(CONFIG_PINCTRL_PXA27X) += pinctrl-pxa2xx.o pinctrl-pxa27x.o diff --git a/drivers/pinctrl/pxa/pinctrl-pxa25x.c b/drivers/pinctrl/pxa/pinctrl-pxa25x.c new file mode 100644 index 000000000000..b98ecb3c0683 --- /dev/null +++ b/drivers/pinctrl/pxa/pinctrl-pxa25x.c @@ -0,0 +1,274 @@ +/* + * Marvell PXA25x family pin control + * + * Copyright (C) 2016 Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + */ +#include +#include +#include +#include +#include + +#include "pinctrl-pxa2xx.h" + +static const struct pxa_desc_pin pxa25x_pins[] = { + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(0)), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(1), + PXA_FUNCTION(0, 1, "GP_RST")), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(2)), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(3)), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(4)), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(5)), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(6), + PXA_FUNCTION(1, 1, "MMCCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(7), + PXA_FUNCTION(1, 1, "48_MHz")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(8), + PXA_FUNCTION(1, 1, "MMCCS0")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(9), + PXA_FUNCTION(1, 1, "MMCCS1")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(10), + PXA_FUNCTION(1, 1, "RTCCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(11), + PXA_FUNCTION(1, 1, "3_6_MHz")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(12), + PXA_FUNCTION(1, 1, "32_kHz")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(13), + PXA_FUNCTION(1, 2, "MBGNT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(14), + PXA_FUNCTION(0, 1, "MBREQ")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(15), + PXA_FUNCTION(1, 2, "nCS_1")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(16), + PXA_FUNCTION(1, 2, "PWM0")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(17), + PXA_FUNCTION(1, 2, "PWM1")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(18), + PXA_FUNCTION(0, 1, "RDY")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(19), + PXA_FUNCTION(0, 1, "DREQ[1]")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(20), + PXA_FUNCTION(0, 1, "DREQ[0]")), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(21)), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(22)), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(23), + PXA_FUNCTION(1, 2, "SCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(24), + PXA_FUNCTION(1, 2, "SFRM")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(25), + PXA_FUNCTION(1, 2, "TXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(26), + PXA_FUNCTION(0, 1, "RXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(27), + PXA_FUNCTION(0, 1, "EXTCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(28), + PXA_FUNCTION(0, 1, "BITCLK"), + PXA_FUNCTION(0, 2, "BITCLK"), + PXA_FUNCTION(1, 1, "BITCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(29), + PXA_FUNCTION(0, 1, "SDATA_IN0"), + PXA_FUNCTION(0, 2, "SDATA_IN")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(30), + PXA_FUNCTION(1, 1, "SDATA_OUT"), + PXA_FUNCTION(1, 2, "SDATA_OUT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(31), + PXA_FUNCTION(1, 1, "SYNC"), + PXA_FUNCTION(1, 2, "SYNC")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(32), + PXA_FUNCTION(0, 1, "SDATA_IN1"), + PXA_FUNCTION(1, 1, "SYSCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(33), + PXA_FUNCTION(1, 2, "nCS[5]")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(34), + PXA_FUNCTION(0, 1, "FFRXD"), + PXA_FUNCTION(1, 2, "MMCCS0")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(35), + PXA_FUNCTION(0, 1, "CTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(36), + PXA_FUNCTION(0, 1, "DCD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(37), + PXA_FUNCTION(0, 1, "DSR")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(38), + PXA_FUNCTION(0, 1, "RI")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(39), + PXA_FUNCTION(1, 1, "MMCC1"), + PXA_FUNCTION(1, 2, "FFTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(40), + PXA_FUNCTION(1, 2, "DTR")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(41), + PXA_FUNCTION(1, 2, "RTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(42), + PXA_FUNCTION(0, 1, "BTRXD"), + PXA_FUNCTION(0, 3, "HWRXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(43), + PXA_FUNCTION(1, 2, "BTTXD"), + PXA_FUNCTION(1, 3, "HWTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(44), + PXA_FUNCTION(0, 1, "BTCTS"), + PXA_FUNCTION(0, 3, "HWCTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(45), + PXA_FUNCTION(1, 2, "BTRTS"), + PXA_FUNCTION(1, 3, "HWRTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(46), + PXA_FUNCTION(0, 1, "ICP_RXD"), + PXA_FUNCTION(0, 2, "RXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(47), + PXA_FUNCTION(1, 1, "TXD"), + PXA_FUNCTION(1, 2, "ICP_TXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(48), + PXA_FUNCTION(1, 1, "HWTXD"), + PXA_FUNCTION(1, 2, "nPOE")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(49), + PXA_FUNCTION(0, 1, "HWRXD"), + PXA_FUNCTION(1, 2, "nPWE")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(50), + PXA_FUNCTION(0, 1, "HWCTS"), + PXA_FUNCTION(1, 2, "nPIOR")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(51), + PXA_FUNCTION(1, 1, "HWRTS"), + PXA_FUNCTION(1, 2, "nPIOW")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(52), + PXA_FUNCTION(1, 2, "nPCE[1]")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(53), + PXA_FUNCTION(1, 1, "MMCCLK"), + PXA_FUNCTION(1, 2, "nPCE[2]")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(54), + PXA_FUNCTION(1, 1, "MMCCLK"), + PXA_FUNCTION(1, 2, "nPSKTSEL")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(55), + PXA_FUNCTION(1, 2, "nPREG")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(56), + PXA_FUNCTION(0, 1, "nPWAIT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(57), + PXA_FUNCTION(0, 1, "nIOIS16")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(58), + PXA_FUNCTION(1, 2, "LDD<0>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(59), + PXA_FUNCTION(1, 2, "LDD<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(60), + PXA_FUNCTION(1, 2, "LDD<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(61), + PXA_FUNCTION(1, 2, "LDD<3>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(62), + PXA_FUNCTION(1, 2, "LDD<4>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(63), + PXA_FUNCTION(1, 2, "LDD<5>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(64), + PXA_FUNCTION(1, 2, "LDD<6>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(65), + PXA_FUNCTION(1, 2, "LDD<7>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(66), + PXA_FUNCTION(0, 1, "MBREQ"), + PXA_FUNCTION(1, 2, "LDD<8>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(67), + PXA_FUNCTION(1, 1, "MMCCS0"), + PXA_FUNCTION(1, 2, "LDD<9>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(68), + PXA_FUNCTION(1, 1, "MMCCS1"), + PXA_FUNCTION(1, 2, "LDD<10>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(69), + PXA_FUNCTION(1, 1, "MMCCLK"), + PXA_FUNCTION(1, 2, "LDD<11>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(70), + PXA_FUNCTION(1, 1, "RTCCLK"), + PXA_FUNCTION(1, 2, "LDD<12>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(71), + PXA_FUNCTION(1, 1, "3_6_MHz"), + PXA_FUNCTION(1, 2, "LDD<13>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(72), + PXA_FUNCTION(1, 1, "32_kHz"), + PXA_FUNCTION(1, 2, "LDD<14>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(73), + PXA_FUNCTION(1, 1, "MBGNT"), + PXA_FUNCTION(1, 2, "LDD<15>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(74), + PXA_FUNCTION(1, 2, "LCD_FCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(75), + PXA_FUNCTION(1, 2, "LCD_LCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(76), + PXA_FUNCTION(1, 2, "LCD_PCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(77), + PXA_FUNCTION(1, 2, "LCD_ACBIAS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(78), + PXA_FUNCTION(1, 2, "nCS<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(79), + PXA_FUNCTION(1, 2, "nCS<3>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(80), + PXA_FUNCTION(1, 2, "nCS<4>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(81), + PXA_FUNCTION(0, 1, "NSSPSCLK"), + PXA_FUNCTION(1, 1, "NSSPSCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(82), + PXA_FUNCTION(0, 1, "NSSPSFRM"), + PXA_FUNCTION(1, 1, "NSSPSFRM")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(83), + PXA_FUNCTION(0, 2, "NSSPRXD"), + PXA_FUNCTION(1, 1, "NSSPTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(84), + PXA_FUNCTION(0, 2, "NSSPRXD"), + PXA_FUNCTION(1, 1, "NSSPTXD")), +}; + +static int pxa25x_pinctrl_probe(struct platform_device *pdev) +{ + int ret, i; + void __iomem *base_af[8]; + void __iomem *base_dir[4]; + void __iomem *base_sleep[4]; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base_af[0] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_af[0])) + return PTR_ERR(base_af[0]); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + base_dir[0] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_dir[0])) + return PTR_ERR(base_dir[0]); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + base_dir[3] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_dir[3])) + return PTR_ERR(base_dir[3]); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 3); + base_sleep[0] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_sleep[0])) + return PTR_ERR(base_sleep[0]); + + for (i = 0; i < ARRAY_SIZE(base_af); i++) + base_af[i] = base_af[0] + sizeof(base_af[0]) * i; + for (i = 0; i < 3; i++) + base_dir[i] = base_dir[0] + sizeof(base_dir[0]) * i; + for (i = 0; i < ARRAY_SIZE(base_sleep); i++) + base_sleep[i] = base_sleep[0] + sizeof(base_af[0]) * i; + + ret = pxa2xx_pinctrl_init(pdev, pxa25x_pins, ARRAY_SIZE(pxa25x_pins), + base_af, base_dir, base_sleep); + return ret; +} + +static const struct of_device_id pxa25x_pinctrl_match[] = { + { .compatible = "marvell,pxa25x-pinctrl", }, + {} +}; +MODULE_DEVICE_TABLE(of, pxa25x_pinctrl_match); + +static struct platform_driver pxa25x_pinctrl_driver = { + .probe = pxa25x_pinctrl_probe, + .driver = { + .name = "pxa25x-pinctrl", + .of_match_table = pxa25x_pinctrl_match, + }, +}; +module_platform_driver(pxa25x_pinctrl_driver); + +MODULE_AUTHOR("Robert Jarzmik "); +MODULE_DESCRIPTION("Marvell PXA25x pinctrl driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 860b8d4b3f893c97f905b978ecf62f48816dc5de Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 14 Apr 2016 16:53:19 +0900 Subject: [PATCH 2726/9938] perf config: Make show_config() use perf_config_set Currently show_config() has a problem when user and system config files have the same config variables i.e.: # cat ~/.perfconfig [top] children = false When $(sysconfdir) is /usr/local/etc # cat /usr/local/etc/perfconfig [top] children = true Before: # perf config --user --list top.children=false # perf config --system --list top.children=true # perf config --list top.children=true top.children=false Because perf_config() can call show_config() each the config file (user and system). Fix it. After: # perf config --user --list top.children=false # perf config --system --list top.children=true # perf config --list top.children=false Signed-off-by: Taeung Song Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460620401-23430-3-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-config.c | 39 ++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index c42448ed5dfe..fe1b77fa21f9 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -12,6 +12,7 @@ #include #include "util/util.h" #include "util/debug.h" +#include "util/config.h" static bool use_system_config, use_user_config; @@ -32,13 +33,28 @@ static struct option config_options[] = { OPT_END() }; -static int show_config(const char *key, const char *value, - void *cb __maybe_unused) +static int show_config(struct perf_config_set *set) { - if (value) - printf("%s=%s\n", key, value); - else - printf("%s\n", key); + struct perf_config_section *section; + struct perf_config_item *item; + struct list_head *sections; + + if (set == NULL) + return -1; + + sections = &set->sections; + if (list_empty(sections)) + return -1; + + list_for_each_entry(section, sections, node) { + list_for_each_entry(item, §ion->items, node) { + char *value = item->value; + + if (value) + printf("%s.%s=%s\n", section->name, + item->name, value); + } + } return 0; } @@ -46,6 +62,7 @@ static int show_config(const char *key, const char *value, int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) { int ret = 0; + struct perf_config_set *set; char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); argc = parse_options(argc, argv, config_options, config_usage, @@ -63,13 +80,19 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) else if (use_user_config) config_exclusive_filename = user_config; + set = perf_config_set__new(); + if (!set) { + ret = -1; + goto out_err; + } + switch (actions) { case ACTION_LIST: if (argc) { pr_err("Error: takes no arguments\n"); parse_options_usage(config_usage, config_options, "l", 1); } else { - ret = perf_config(show_config, NULL); + ret = show_config(set); if (ret < 0) { const char * config_filename = config_exclusive_filename; if (!config_exclusive_filename) @@ -83,5 +106,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) usage_with_options(config_usage, config_options); } + perf_config_set__delete(set); +out_err: return ret; } -- GitLab From c606e662a5c8e9caa7183e7d88b7c24dadb3adea Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:16 -0400 Subject: [PATCH 2727/9938] rtl8xxxu: Add MAC init table for 8192eu The 8192eu requires a different MAC init table. Add the missing table and specify the table to use in the fileops structure. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 45 ++++++++++++++++--- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index db8433a9efe2..2869376c0e86 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -184,6 +184,36 @@ static struct rtl8xxxu_reg8val rtl8723b_mac_init_table[] = { {0xffff, 0xff}, }; +static struct rtl8xxxu_reg8val rtl8192e_mac_init_table[] = { + {0x011, 0xeb}, {0x012, 0x07}, {0x014, 0x75}, {0x303, 0xa7}, + {0x428, 0x0a}, {0x429, 0x10}, {0x430, 0x00}, {0x431, 0x00}, + {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05}, + {0x436, 0x07}, {0x437, 0x08}, {0x43c, 0x04}, {0x43d, 0x05}, + {0x43e, 0x07}, {0x43f, 0x08}, {0x440, 0x5d}, {0x441, 0x01}, + {0x442, 0x00}, {0x444, 0x10}, {0x445, 0x00}, {0x446, 0x00}, + {0x447, 0x00}, {0x448, 0x00}, {0x449, 0xf0}, {0x44a, 0x0f}, + {0x44b, 0x3e}, {0x44c, 0x10}, {0x44d, 0x00}, {0x44e, 0x00}, + {0x44f, 0x00}, {0x450, 0x00}, {0x451, 0xf0}, {0x452, 0x0f}, + {0x453, 0x00}, {0x456, 0x5e}, {0x460, 0x66}, {0x461, 0x66}, + {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff}, {0x4cd, 0xff}, + {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2}, {0x502, 0x2f}, + {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3}, {0x506, 0x5e}, + {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4}, {0x50a, 0x5e}, + {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4}, {0x50e, 0x00}, + {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a}, {0x516, 0x0a}, + {0x525, 0x4f}, {0x540, 0x12}, {0x541, 0x64}, {0x550, 0x10}, + {0x551, 0x10}, {0x559, 0x02}, {0x55c, 0x50}, {0x55d, 0xff}, + {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a}, {0x620, 0xff}, + {0x621, 0xff}, {0x622, 0xff}, {0x623, 0xff}, {0x624, 0xff}, + {0x625, 0xff}, {0x626, 0xff}, {0x627, 0xff}, {0x638, 0x50}, + {0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e}, {0x63f, 0x0e}, + {0x640, 0x40}, {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xc8}, + {0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43}, {0x702, 0x65}, + {0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43}, {0x70a, 0x65}, + {0x70b, 0x87}, + {0xffff, 0xff}, +}; + static struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = { {0x800, 0x80040000}, {0x804, 0x00000003}, {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, @@ -3087,8 +3117,9 @@ static void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv) } static int -rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array) +rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv) { + struct rtl8xxxu_reg8val *array = priv->fops->mactable; int i, ret; u16 reg; u8 val; @@ -3103,7 +3134,8 @@ rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array) ret = rtl8xxxu_write8(priv, reg, val); if (ret != 1) { dev_warn(&priv->udev->dev, - "Failed to initialize MAC\n"); + "Failed to initialize MAC " + "(reg: %04x, val %02x)\n", reg, val); return -EAGAIN; } } @@ -6369,10 +6401,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->fops->phy_init_antenna_selection) priv->fops->phy_init_antenna_selection(priv); - if (priv->rtl_chip == RTL8723B) - ret = rtl8xxxu_init_mac(priv, rtl8723b_mac_init_table); - else - ret = rtl8xxxu_init_mac(priv, rtl8723a_mac_init_table); + ret = rtl8xxxu_init_mac(priv); dev_dbg(dev, "%s: init_mac %i\n", __func__, ret); if (ret) @@ -8452,6 +8481,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .mactable = rtl8723a_mac_init_table, }; static struct rtl8xxxu_fileops rtl8723bu_fops = { @@ -8481,6 +8511,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, .adda_2t_path_on_b = 0x01c00014, + .mactable = rtl8723b_mac_init_table, }; #ifdef CONFIG_RTL8XXXU_UNTESTED @@ -8508,6 +8539,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .mactable = rtl8723a_mac_init_table, }; #endif @@ -8536,6 +8568,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, .adda_2t_path_on_b = 0x0fc01616, + .mactable = rtl8192e_mac_init_table, }; static struct usb_device_id dev_table[] = { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 455e1122dbb5..94fc2172c0d0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1308,4 +1308,5 @@ struct rtl8xxxu_fileops { u32 adda_1t_path_on; u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; + struct rtl8xxxu_reg8val *mactable; }; -- GitLab From 2ca73dc786c4ffb9c618e7b868d69d9faf5a755d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:17 -0400 Subject: [PATCH 2728/9938] rtl8xxxu: Do not mess with AFE_XTAL_CTRL on 8192eu To match the vendor driver, do not mess with AFE_XTAL_CTRL on 8192eu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 2869376c0e86..63fa4c66794f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3208,7 +3208,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); } - if (priv->rtl_chip != RTL8723B) { + if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) { /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */ val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); val32 &= ~AFE_XTAL_RF_GATE; -- GitLab From 80805aa5f33e315df23b6420c64f96a28dfcbb9a Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:18 -0400 Subject: [PATCH 2729/9938] rtl8xxxu: Set TX page boundaries for 8192eu The 8192eu also has it's own TRXFF boundary value to set. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 7 ++++++- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 63fa4c66794f..5b2c1c80e49d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6495,7 +6495,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Set TX buffer boundary */ - val8 = TX_TOTAL_PAGE_NUM + 1; + if (priv->rtl_chip == RTL8192E) + val8 = TX_TOTAL_PAGE_NUM_8192E + 1; + else + val8 = TX_TOTAL_PAGE_NUM + 1; if (priv->rtl_chip == RTL8723B) val8 -= 1; @@ -6532,6 +6535,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) */ if (priv->rtl_chip == RTL8723B) rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); + else if (priv->rtl_chip == RTL8192E) + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); else rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); /* diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 94fc2172c0d0..63d72689481d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -42,6 +42,7 @@ #define REALTEK_USB_CMD_IDX 0x00 #define TX_TOTAL_PAGE_NUM 0xf8 +#define TX_TOTAL_PAGE_NUM_8192E 0xf3 /* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */ #define TX_PAGE_NUM_PUBQ 0xe7 #define TX_PAGE_NUM_HI_PQ 0x0c -- GitLab From 19102f8419342a3cdd0efb25539a268f2d095319 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:19 -0400 Subject: [PATCH 2730/9938] rtl8xxxu: Add radio init tables for 8192eu Add the required radio init tables for 8192eu devices. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 5b2c1c80e49d..0667aa77a2fd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1242,6 +1242,152 @@ static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = { {0xff, 0xffffffff} }; +static struct rtl8xxxu_rfregval rtl8192eu_radioa_init_table[] = { + {0x7f, 0x00000082}, {0x81, 0x0003fc00}, + {0x00, 0x00030000}, {0x08, 0x00008400}, + {0x18, 0x00000407}, {0x19, 0x00000012}, + {0x1b, 0x00000064}, {0x1e, 0x00080009}, + {0x1f, 0x00000880}, {0x2f, 0x0001a060}, + {0x3f, 0x00000000}, {0x42, 0x000060c0}, + {0x57, 0x000d0000}, {0x58, 0x000be180}, + {0x67, 0x00001552}, {0x83, 0x00000000}, + {0xb0, 0x000ff9f1}, {0xb1, 0x00055418}, + {0xb2, 0x0008cc00}, {0xb4, 0x00043083}, + {0xb5, 0x00008166}, {0xb6, 0x0000803e}, + {0xb7, 0x0001c69f}, {0xb8, 0x0000407f}, + {0xb9, 0x00080001}, {0xba, 0x00040001}, + {0xbb, 0x00000400}, {0xbf, 0x000c0000}, + {0xc2, 0x00002400}, {0xc3, 0x00000009}, + {0xc4, 0x00040c91}, {0xc5, 0x00099999}, + {0xc6, 0x000000a3}, {0xc7, 0x00088820}, + {0xc8, 0x00076c06}, {0xc9, 0x00000000}, + {0xca, 0x00080000}, {0xdf, 0x00000180}, + {0xef, 0x000001a0}, {0x51, 0x00069545}, + {0x52, 0x0007e45e}, {0x53, 0x00000071}, + {0x56, 0x00051ff3}, {0x35, 0x000000a8}, + {0x35, 0x000001e2}, {0x35, 0x000002a8}, + {0x36, 0x00001c24}, {0x36, 0x00009c24}, + {0x36, 0x00011c24}, {0x36, 0x00019c24}, + {0x18, 0x00000c07}, {0x5a, 0x00048000}, + {0x19, 0x000739d0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x34, 0x0000a093}, {0x34, 0x0000908f}, + {0x34, 0x0000808c}, {0x34, 0x0000704d}, + {0x34, 0x0000604a}, {0x34, 0x00005047}, + {0x34, 0x0000400a}, {0x34, 0x00003007}, + {0x34, 0x00002004}, {0x34, 0x00001001}, + {0x34, 0x00000000}, +#else + /* Regular */ + {0x34, 0x0000add7}, {0x34, 0x00009dd4}, + {0x34, 0x00008dd1}, {0x34, 0x00007dce}, + {0x34, 0x00006dcb}, {0x34, 0x00005dc8}, + {0x34, 0x00004dc5}, {0x34, 0x000034cc}, + {0x34, 0x0000244f}, {0x34, 0x0000144c}, + {0x34, 0x00000014}, +#endif + {0x00, 0x00030159}, + {0x84, 0x00068180}, + {0x86, 0x0000014e}, + {0x87, 0x00048e00}, + {0x8e, 0x00065540}, + {0x8f, 0x00088000}, + {0xef, 0x000020a0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000f07b0}, +#else + {0x3b, 0x000f02b0}, +#endif + {0x3b, 0x000ef7b0}, {0x3b, 0x000d4fb0}, + {0x3b, 0x000cf060}, {0x3b, 0x000b0090}, + {0x3b, 0x000a0080}, {0x3b, 0x00090080}, + {0x3b, 0x0008f780}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000787b0}, +#else + {0x3b, 0x00078730}, +#endif + {0x3b, 0x00060fb0}, {0x3b, 0x0005ffa0}, + {0x3b, 0x00040620}, {0x3b, 0x00037090}, + {0x3b, 0x00020080}, {0x3b, 0x0001f060}, + {0x3b, 0x0000ffb0}, {0xef, 0x000000a0}, + {0xfe, 0x00000000}, {0x18, 0x0000fc07}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00000001}, {0x1f, 0x00080000}, + {0x00, 0x00033e70}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192eu_radiob_init_table[] = { + {0x7f, 0x00000082}, {0x81, 0x0003fc00}, + {0x00, 0x00030000}, {0x08, 0x00008400}, + {0x18, 0x00000407}, {0x19, 0x00000012}, + {0x1b, 0x00000064}, {0x1e, 0x00080009}, + {0x1f, 0x00000880}, {0x2f, 0x0001a060}, + {0x3f, 0x00000000}, {0x42, 0x000060c0}, + {0x57, 0x000d0000}, {0x58, 0x000be180}, + {0x67, 0x00001552}, {0x7f, 0x00000082}, + {0x81, 0x0003f000}, {0x83, 0x00000000}, + {0xdf, 0x00000180}, {0xef, 0x000001a0}, + {0x51, 0x00069545}, {0x52, 0x0007e42e}, + {0x53, 0x00000071}, {0x56, 0x00051ff3}, + {0x35, 0x000000a8}, {0x35, 0x000001e0}, + {0x35, 0x000002a8}, {0x36, 0x00001ca8}, + {0x36, 0x00009c24}, {0x36, 0x00011c24}, + {0x36, 0x00019c24}, {0x18, 0x00000c07}, + {0x5a, 0x00048000}, {0x19, 0x000739d0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x34, 0x0000a093}, {0x34, 0x0000908f}, + {0x34, 0x0000808c}, {0x34, 0x0000704d}, + {0x34, 0x0000604a}, {0x34, 0x00005047}, + {0x34, 0x0000400a}, {0x34, 0x00003007}, + {0x34, 0x00002004}, {0x34, 0x00001001}, + {0x34, 0x00000000}, +#else + {0x34, 0x0000add7}, {0x34, 0x00009dd4}, + {0x34, 0x00008dd1}, {0x34, 0x00007dce}, + {0x34, 0x00006dcb}, {0x34, 0x00005dc8}, + {0x34, 0x00004dc5}, {0x34, 0x000034cc}, + {0x34, 0x0000244f}, {0x34, 0x0000144c}, + {0x34, 0x00000014}, +#endif + {0x00, 0x00030159}, {0x84, 0x00068180}, + {0x86, 0x000000ce}, {0x87, 0x00048a00}, + {0x8e, 0x00065540}, {0x8f, 0x00088000}, + {0xef, 0x000020a0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000f07b0}, +#else + {0x3b, 0x000f02b0}, +#endif + + {0x3b, 0x000ef7b0}, {0x3b, 0x000d4fb0}, + {0x3b, 0x000cf060}, {0x3b, 0x000b0090}, + {0x3b, 0x000a0080}, {0x3b, 0x00090080}, + {0x3b, 0x0008f780}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000787b0}, +#else + {0x3b, 0x00078730}, +#endif + {0x3b, 0x00060fb0}, {0x3b, 0x0005ffa0}, + {0x3b, 0x00040620}, {0x3b, 0x00037090}, + {0x3b, 0x00020080}, {0x3b, 0x0001f060}, + {0x3b, 0x0000ffb0}, {0xef, 0x000000a0}, + {0x00, 0x00010159}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1e, 0x00000001}, + {0x1f, 0x00080000}, {0x00, 0x00033e70}, + {0xff, 0xffffffff} +}; + static struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = { { /* RF_A */ .hssiparm1 = REG_FPGA0_XA_HSSI_PARM1, @@ -6447,6 +6593,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rftable = rtl8192cu_radiob_2t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); break; + case RTL8192E: + rftable = rtl8192eu_radioa_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + if (ret) + break; + rftable = rtl8192eu_radiob_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); + break; default: ret = -EINVAL; } -- GitLab From e293278debe7c1d3112aa8ec10373d73f171d75d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:20 -0400 Subject: [PATCH 2731/9938] rtl8xxxu: Add 8192eu AGC tables A device specific AGC table is required for the 8192eu as well. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 147 +++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 0667aa77a2fd..650ebcbe7a2b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -849,6 +849,144 @@ static struct rtl8xxxu_reg32val rtl8xxx_agc_8723bu_table[] = { {0xffff, 0xffffffff} }; +static struct rtl8xxxu_reg32val rtl8xxx_agc_8192eu_std_table[] = { + {0xc78, 0xfb000001}, {0xc78, 0xfb010001}, + {0xc78, 0xfb020001}, {0xc78, 0xfb030001}, + {0xc78, 0xfb040001}, {0xc78, 0xfb050001}, + {0xc78, 0xfa060001}, {0xc78, 0xf9070001}, + {0xc78, 0xf8080001}, {0xc78, 0xf7090001}, + {0xc78, 0xf60a0001}, {0xc78, 0xf50b0001}, + {0xc78, 0xf40c0001}, {0xc78, 0xf30d0001}, + {0xc78, 0xf20e0001}, {0xc78, 0xf10f0001}, + {0xc78, 0xf0100001}, {0xc78, 0xef110001}, + {0xc78, 0xee120001}, {0xc78, 0xed130001}, + {0xc78, 0xec140001}, {0xc78, 0xeb150001}, + {0xc78, 0xea160001}, {0xc78, 0xe9170001}, + {0xc78, 0xe8180001}, {0xc78, 0xe7190001}, + {0xc78, 0xc81a0001}, {0xc78, 0xc71b0001}, + {0xc78, 0xc61c0001}, {0xc78, 0x071d0001}, + {0xc78, 0x061e0001}, {0xc78, 0x051f0001}, + {0xc78, 0x04200001}, {0xc78, 0x03210001}, + {0xc78, 0xaa220001}, {0xc78, 0xa9230001}, + {0xc78, 0xa8240001}, {0xc78, 0xa7250001}, + {0xc78, 0xa6260001}, {0xc78, 0x85270001}, + {0xc78, 0x84280001}, {0xc78, 0x83290001}, + {0xc78, 0x252a0001}, {0xc78, 0x242b0001}, + {0xc78, 0x232c0001}, {0xc78, 0x222d0001}, + {0xc78, 0x672e0001}, {0xc78, 0x662f0001}, + {0xc78, 0x65300001}, {0xc78, 0x64310001}, + {0xc78, 0x63320001}, {0xc78, 0x62330001}, + {0xc78, 0x61340001}, {0xc78, 0x45350001}, + {0xc78, 0x44360001}, {0xc78, 0x43370001}, + {0xc78, 0x42380001}, {0xc78, 0x41390001}, + {0xc78, 0x403a0001}, {0xc78, 0x403b0001}, + {0xc78, 0x403c0001}, {0xc78, 0x403d0001}, + {0xc78, 0x403e0001}, {0xc78, 0x403f0001}, + {0xc78, 0xfb400001}, {0xc78, 0xfb410001}, + {0xc78, 0xfb420001}, {0xc78, 0xfb430001}, + {0xc78, 0xfb440001}, {0xc78, 0xfb450001}, + {0xc78, 0xfa460001}, {0xc78, 0xf9470001}, + {0xc78, 0xf8480001}, {0xc78, 0xf7490001}, + {0xc78, 0xf64a0001}, {0xc78, 0xf54b0001}, + {0xc78, 0xf44c0001}, {0xc78, 0xf34d0001}, + {0xc78, 0xf24e0001}, {0xc78, 0xf14f0001}, + {0xc78, 0xf0500001}, {0xc78, 0xef510001}, + {0xc78, 0xee520001}, {0xc78, 0xed530001}, + {0xc78, 0xec540001}, {0xc78, 0xeb550001}, + {0xc78, 0xea560001}, {0xc78, 0xe9570001}, + {0xc78, 0xe8580001}, {0xc78, 0xe7590001}, + {0xc78, 0xe65a0001}, {0xc78, 0xe55b0001}, + {0xc78, 0xe45c0001}, {0xc78, 0xe35d0001}, + {0xc78, 0xe25e0001}, {0xc78, 0xe15f0001}, + {0xc78, 0x8a600001}, {0xc78, 0x89610001}, + {0xc78, 0x88620001}, {0xc78, 0x87630001}, + {0xc78, 0x86640001}, {0xc78, 0x85650001}, + {0xc78, 0x84660001}, {0xc78, 0x83670001}, + {0xc78, 0x82680001}, {0xc78, 0x6b690001}, + {0xc78, 0x6a6a0001}, {0xc78, 0x696b0001}, + {0xc78, 0x686c0001}, {0xc78, 0x676d0001}, + {0xc78, 0x666e0001}, {0xc78, 0x656f0001}, + {0xc78, 0x64700001}, {0xc78, 0x63710001}, + {0xc78, 0x62720001}, {0xc78, 0x61730001}, + {0xc78, 0x49740001}, {0xc78, 0x48750001}, + {0xc78, 0x47760001}, {0xc78, 0x46770001}, + {0xc78, 0x45780001}, {0xc78, 0x44790001}, + {0xc78, 0x437a0001}, {0xc78, 0x427b0001}, + {0xc78, 0x417c0001}, {0xc78, 0x407d0001}, + {0xc78, 0x407e0001}, {0xc78, 0x407f0001}, + {0xc50, 0x00040022}, {0xc50, 0x00040020}, + {0xffff, 0xffffffff} +}; + +static struct rtl8xxxu_reg32val rtl8xxx_agc_8192eu_highpa_table[] = { + {0xc78, 0xfa000001}, {0xc78, 0xf9010001}, + {0xc78, 0xf8020001}, {0xc78, 0xf7030001}, + {0xc78, 0xf6040001}, {0xc78, 0xf5050001}, + {0xc78, 0xf4060001}, {0xc78, 0xf3070001}, + {0xc78, 0xf2080001}, {0xc78, 0xf1090001}, + {0xc78, 0xf00a0001}, {0xc78, 0xef0b0001}, + {0xc78, 0xee0c0001}, {0xc78, 0xed0d0001}, + {0xc78, 0xec0e0001}, {0xc78, 0xeb0f0001}, + {0xc78, 0xea100001}, {0xc78, 0xe9110001}, + {0xc78, 0xe8120001}, {0xc78, 0xe7130001}, + {0xc78, 0xe6140001}, {0xc78, 0xe5150001}, + {0xc78, 0xe4160001}, {0xc78, 0xe3170001}, + {0xc78, 0xe2180001}, {0xc78, 0xe1190001}, + {0xc78, 0x8a1a0001}, {0xc78, 0x891b0001}, + {0xc78, 0x881c0001}, {0xc78, 0x871d0001}, + {0xc78, 0x861e0001}, {0xc78, 0x851f0001}, + {0xc78, 0x84200001}, {0xc78, 0x83210001}, + {0xc78, 0x82220001}, {0xc78, 0x6a230001}, + {0xc78, 0x69240001}, {0xc78, 0x68250001}, + {0xc78, 0x67260001}, {0xc78, 0x66270001}, + {0xc78, 0x65280001}, {0xc78, 0x64290001}, + {0xc78, 0x632a0001}, {0xc78, 0x622b0001}, + {0xc78, 0x612c0001}, {0xc78, 0x602d0001}, + {0xc78, 0x472e0001}, {0xc78, 0x462f0001}, + {0xc78, 0x45300001}, {0xc78, 0x44310001}, + {0xc78, 0x43320001}, {0xc78, 0x42330001}, + {0xc78, 0x41340001}, {0xc78, 0x40350001}, + {0xc78, 0x40360001}, {0xc78, 0x40370001}, + {0xc78, 0x40380001}, {0xc78, 0x40390001}, + {0xc78, 0x403a0001}, {0xc78, 0x403b0001}, + {0xc78, 0x403c0001}, {0xc78, 0x403d0001}, + {0xc78, 0x403e0001}, {0xc78, 0x403f0001}, + {0xc78, 0xfa400001}, {0xc78, 0xf9410001}, + {0xc78, 0xf8420001}, {0xc78, 0xf7430001}, + {0xc78, 0xf6440001}, {0xc78, 0xf5450001}, + {0xc78, 0xf4460001}, {0xc78, 0xf3470001}, + {0xc78, 0xf2480001}, {0xc78, 0xf1490001}, + {0xc78, 0xf04a0001}, {0xc78, 0xef4b0001}, + {0xc78, 0xee4c0001}, {0xc78, 0xed4d0001}, + {0xc78, 0xec4e0001}, {0xc78, 0xeb4f0001}, + {0xc78, 0xea500001}, {0xc78, 0xe9510001}, + {0xc78, 0xe8520001}, {0xc78, 0xe7530001}, + {0xc78, 0xe6540001}, {0xc78, 0xe5550001}, + {0xc78, 0xe4560001}, {0xc78, 0xe3570001}, + {0xc78, 0xe2580001}, {0xc78, 0xe1590001}, + {0xc78, 0x8a5a0001}, {0xc78, 0x895b0001}, + {0xc78, 0x885c0001}, {0xc78, 0x875d0001}, + {0xc78, 0x865e0001}, {0xc78, 0x855f0001}, + {0xc78, 0x84600001}, {0xc78, 0x83610001}, + {0xc78, 0x82620001}, {0xc78, 0x6a630001}, + {0xc78, 0x69640001}, {0xc78, 0x68650001}, + {0xc78, 0x67660001}, {0xc78, 0x66670001}, + {0xc78, 0x65680001}, {0xc78, 0x64690001}, + {0xc78, 0x636a0001}, {0xc78, 0x626b0001}, + {0xc78, 0x616c0001}, {0xc78, 0x606d0001}, + {0xc78, 0x476e0001}, {0xc78, 0x466f0001}, + {0xc78, 0x45700001}, {0xc78, 0x44710001}, + {0xc78, 0x43720001}, {0xc78, 0x42730001}, + {0xc78, 0x41740001}, {0xc78, 0x40750001}, + {0xc78, 0x40760001}, {0xc78, 0x40770001}, + {0xc78, 0x40780001}, {0xc78, 0x40790001}, + {0xc78, 0x407a0001}, {0xc78, 0x407b0001}, + {0xc78, 0x407c0001}, {0xc78, 0x407d0001}, + {0xc78, 0x407e0001}, {0xc78, 0x407f0001}, + {0xc50, 0x00040222}, {0xc50, 0x00040220}, + {0xffff, 0xffffffff} +}; + static struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = { {0x00, 0x00030159}, {0x01, 0x00031284}, {0x02, 0x00098000}, {0x03, 0x00039c63}, @@ -3446,7 +3584,14 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) if (priv->rtl_chip == RTL8723B) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); - else if (priv->hi_pa) + else if (priv->rtl_chip == RTL8192E) { + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_std_table); + } else if (priv->hi_pa) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); else rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); -- GitLab From ae14c5d20dc9e5e66681a7e3045b61eb9348d9f4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:21 -0400 Subject: [PATCH 2732/9938] rtl8xxxu: Add 8192eu PHY init table The 8192eu also requires it's own PHY init table. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 650ebcbe7a2b..48d2d56ec224 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -610,6 +610,138 @@ static struct rtl8xxxu_reg32val rtl8188ru_phy_1t_highpa_table[] = { {0xffff, 0xffffffff}, }; +static struct rtl8xxxu_reg32val rtl8192eu_phy_init_table[] = { + {0x800, 0x80040000}, {0x804, 0x00000003}, + {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, + {0x810, 0x10001331}, {0x814, 0x020c3d10}, + {0x818, 0x02220385}, {0x81c, 0x00000000}, + {0x820, 0x01000100}, {0x824, 0x00390204}, + {0x828, 0x01000100}, {0x82c, 0x00390204}, + {0x830, 0x32323232}, {0x834, 0x30303030}, + {0x838, 0x30303030}, {0x83c, 0x30303030}, + {0x840, 0x00010000}, {0x844, 0x00010000}, + {0x848, 0x28282828}, {0x84c, 0x28282828}, + {0x850, 0x00000000}, {0x854, 0x00000000}, + {0x858, 0x009a009a}, {0x85c, 0x01000014}, + {0x860, 0x66f60000}, {0x864, 0x061f0000}, + {0x868, 0x30303030}, {0x86c, 0x30303030}, + {0x870, 0x00000000}, {0x874, 0x55004200}, + {0x878, 0x08080808}, {0x87c, 0x00000000}, + {0x880, 0xb0000c1c}, {0x884, 0x00000001}, + {0x888, 0x00000000}, {0x88c, 0xcc0000c0}, + {0x890, 0x00000800}, {0x894, 0xfffffffe}, + {0x898, 0x40302010}, {0x900, 0x00000000}, + {0x904, 0x00000023}, {0x908, 0x00000000}, + {0x90c, 0x81121313}, {0x910, 0x806c0001}, + {0x914, 0x00000001}, {0x918, 0x00000000}, + {0x91c, 0x00010000}, {0x924, 0x00000001}, + {0x928, 0x00000000}, {0x92c, 0x00000000}, + {0x930, 0x00000000}, {0x934, 0x00000000}, + {0x938, 0x00000000}, {0x93c, 0x00000000}, + {0x940, 0x00000000}, {0x944, 0x00000000}, + {0x94c, 0x00000008}, {0xa00, 0x00d0c7c8}, + {0xa04, 0x81ff000c}, {0xa08, 0x8c838300}, + {0xa0c, 0x2e68120f}, {0xa10, 0x95009b78}, + {0xa14, 0x1114d028}, {0xa18, 0x00881117}, + {0xa1c, 0x89140f00}, {0xa20, 0x1a1b0000}, + {0xa24, 0x090e1317}, {0xa28, 0x00000204}, + {0xa2c, 0x00d30000}, {0xa70, 0x101fff00}, + {0xa74, 0x00000007}, {0xa78, 0x00000900}, + {0xa7c, 0x225b0606}, {0xa80, 0x218075b1}, + {0xb38, 0x00000000}, {0xc00, 0x48071d40}, + {0xc04, 0x03a05633}, {0xc08, 0x000000e4}, + {0xc0c, 0x6c6c6c6c}, {0xc10, 0x08800000}, + {0xc14, 0x40000100}, {0xc18, 0x08800000}, + {0xc1c, 0x40000100}, {0xc20, 0x00000000}, + {0xc24, 0x00000000}, {0xc28, 0x00000000}, + {0xc2c, 0x00000000}, {0xc30, 0x69e9ac47}, + {0xc34, 0x469652af}, {0xc38, 0x49795994}, + {0xc3c, 0x0a97971c}, {0xc40, 0x1f7c403f}, + {0xc44, 0x000100b7}, {0xc48, 0xec020107}, + {0xc4c, 0x007f037f}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc50, 0x00340220}, +#else + {0xc50, 0x00340020}, +#endif + {0xc54, 0x0080801f}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc58, 0x00000220}, +#else + {0xc58, 0x00000020}, +#endif + {0xc5c, 0x00248492}, {0xc60, 0x00000000}, + {0xc64, 0x7112848b}, {0xc68, 0x47c00bff}, + {0xc6c, 0x00000036}, {0xc70, 0x00000600}, + {0xc74, 0x02013169}, {0xc78, 0x0000001f}, + {0xc7c, 0x00b91612}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc80, 0x2d4000b5}, +#else + {0xc80, 0x40000100}, +#endif + {0xc84, 0x21f60000}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc88, 0x2d4000b5}, +#else + {0xc88, 0x40000100}, +#endif + {0xc8c, 0xa0e40000}, {0xc90, 0x00121820}, + {0xc94, 0x00000000}, {0xc98, 0x00121820}, + {0xc9c, 0x00007f7f}, {0xca0, 0x00000000}, + {0xca4, 0x000300a0}, {0xca8, 0x00000000}, + {0xcac, 0x00000000}, {0xcb0, 0x00000000}, + {0xcb4, 0x00000000}, {0xcb8, 0x00000000}, + {0xcbc, 0x28000000}, {0xcc0, 0x00000000}, + {0xcc4, 0x00000000}, {0xcc8, 0x00000000}, + {0xccc, 0x00000000}, {0xcd0, 0x00000000}, + {0xcd4, 0x00000000}, {0xcd8, 0x64b22427}, + {0xcdc, 0x00766932}, {0xce0, 0x00222222}, + {0xce4, 0x00040000}, {0xce8, 0x77644302}, + {0xcec, 0x2f97d40c}, {0xd00, 0x00080740}, + {0xd04, 0x00020403}, {0xd08, 0x0000907f}, + {0xd0c, 0x20010201}, {0xd10, 0xa0633333}, + {0xd14, 0x3333bc43}, {0xd18, 0x7a8f5b6b}, + {0xd1c, 0x0000007f}, {0xd2c, 0xcc979975}, + {0xd30, 0x00000000}, {0xd34, 0x80608000}, + {0xd38, 0x00000000}, {0xd3c, 0x00127353}, + {0xd40, 0x00000000}, {0xd44, 0x00000000}, + {0xd48, 0x00000000}, {0xd4c, 0x00000000}, + {0xd50, 0x6437140a}, {0xd54, 0x00000000}, + {0xd58, 0x00000282}, {0xd5c, 0x30032064}, + {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, + {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, + {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, + {0xd78, 0x000e3c24}, {0xd80, 0x01081008}, + {0xd84, 0x00000800}, {0xd88, 0xf0b50000}, + {0xe00, 0x30303030}, {0xe04, 0x30303030}, + {0xe08, 0x03903030}, {0xe10, 0x30303030}, + {0xe14, 0x30303030}, {0xe18, 0x30303030}, + {0xe1c, 0x30303030}, {0xe28, 0x00000000}, + {0xe30, 0x1000dc1f}, {0xe34, 0x10008c1f}, + {0xe38, 0x02140102}, {0xe3c, 0x681604c2}, + {0xe40, 0x01007c00}, {0xe44, 0x01004800}, + {0xe48, 0xfb000000}, {0xe4c, 0x000028d1}, + {0xe50, 0x1000dc1f}, {0xe54, 0x10008c1f}, + {0xe58, 0x02140102}, {0xe5c, 0x28160d05}, + {0xe60, 0x00000008}, {0xe68, 0x0fc05656}, + {0xe6c, 0x03c09696}, {0xe70, 0x03c09696}, + {0xe74, 0x0c005656}, {0xe78, 0x0c005656}, + {0xe7c, 0x0c005656}, {0xe80, 0x0c005656}, + {0xe84, 0x03c09696}, {0xe88, 0x0c005656}, + {0xe8c, 0x03c09696}, {0xed0, 0x03c09696}, + {0xed4, 0x03c09696}, {0xed8, 0x03c09696}, + {0xedc, 0x0000d6d6}, {0xee0, 0x0000d6d6}, + {0xeec, 0x0fc01616}, {0xee4, 0xb0000c1c}, + {0xee8, 0x00000001}, {0xf14, 0x00000003}, + {0xf4c, 0x00000000}, {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + static struct rtl8xxxu_reg32val rtl8xxx_agc_standard_table[] = { {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, @@ -3516,6 +3648,14 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); + } else if (priv->rtl_chip == RTL8192E) { + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= (SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_DIO_RF | + SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB); + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); } else rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); -- GitLab From abd71bdb94c3c4cd6bf4837ce568cb189fdb7f7a Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:22 -0400 Subject: [PATCH 2733/9938] rtl8xxxu: Pick PHY init table based on chip version first Pick PHY init table based on device before distinguishing between 1T/2T/high PA tables. The latter is only currently used for 8188cu/8192cu/8188ru. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 48d2d56ec224..fcbb67936112 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3637,11 +3637,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); - if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); - else if (priv->tx_paths == 2) - rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); - else if (priv->rtl_chip == RTL8723B) { + if (priv->rtl_chip == RTL8723B) { /* * Why? */ @@ -3656,10 +3652,13 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); - } else + } else if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); + else if (priv->tx_paths == 2) + rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); + else rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); - if (priv->rtl_chip == RTL8188C && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); -- GitLab From 9e24772ae222a867f98efc5502a5a01b3916db83 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:23 -0400 Subject: [PATCH 2734/9938] rtl8xxxu: Correctly parse 8192eu efuse The 8192eu efuse only has power data for path A and B. It follows the same layout as 8723bu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 40 +++++++++++++++++++ .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 38 ++++++++---------- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index fcbb67936112..539f7b58bbf7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2122,6 +2122,9 @@ static int rtl8723a_channel_to_group(int channel) return group; } +/* + * Valid for rtl8723bu and rtl8192eu + */ static int rtl8723b_channel_to_group(int channel) { int group; @@ -2987,6 +2990,43 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) ether_addr_copy(priv->mac_addr, efuse->mac_addr); + memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base, + sizeof(efuse->tx_power_index_A.cck_base)); + memcpy(priv->cck_tx_power_index_B, efuse->tx_power_index_B.cck_base, + sizeof(efuse->tx_power_index_B.cck_base)); + + memcpy(priv->ht40_1s_tx_power_index_A, + efuse->tx_power_index_A.ht40_base, + sizeof(efuse->tx_power_index_A.ht40_base)); + memcpy(priv->ht40_1s_tx_power_index_B, + efuse->tx_power_index_B.ht40_base, + sizeof(efuse->tx_power_index_B.ht40_base)); + + priv->ht20_tx_power_diff[0].a = + efuse->tx_power_index_A.ht20_ofdm_1s_diff.b; + priv->ht20_tx_power_diff[0].b = + efuse->tx_power_index_B.ht20_ofdm_1s_diff.b; + + priv->ht40_tx_power_diff[0].a = 0; + priv->ht40_tx_power_diff[0].b = 0; + + for (i = 1; i < RTL8723B_TX_COUNT; i++) { + priv->ofdm_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ofdm; + priv->ofdm_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ofdm; + + priv->ht20_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht20; + priv->ht20_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht20; + + priv->ht40_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht40; + priv->ht40_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht40; + } + priv->has_xtalk = 1; priv->xtalk = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 63d72689481d..48a80fa9eac2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -788,55 +788,49 @@ struct rtl8192eu_efuse_tx_power { u8 cck_base[6]; u8 ht40_base[5]; struct rtl8723au_idx ht20_ofdm_1s_diff; - struct rtl8723au_idx ht40_ht20_2s_diff; - struct rtl8723au_idx ofdm_cck_2s_diff; /* not used */ - struct rtl8723au_idx ht40_ht20_3s_diff; - struct rtl8723au_idx ofdm_cck_3s_diff; /* not used */ - struct rtl8723au_idx ht40_ht20_4s_diff; - struct rtl8723au_idx ofdm_cck_4s_diff; /* not used */ + struct rtl8723bu_pwr_idx pwr_diff[3]; + u8 dummy5g[24]; /* max channel group (14) + power diff offset (10) */ }; struct rtl8192eu_efuse { __le16 rtl_id; u8 res0[0x0e]; struct rtl8192eu_efuse_tx_power tx_power_index_A; /* 0x10 */ - struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x22 */ - struct rtl8192eu_efuse_tx_power tx_power_index_C; /* 0x34 */ - struct rtl8192eu_efuse_tx_power tx_power_index_D; /* 0x46 */ - u8 res1[0x60]; + struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x3a */ + u8 res2[0x54]; u8 channel_plan; /* 0xb8 */ u8 xtal_k; u8 thermal_meter; u8 iqk_lck; u8 pa_type; /* 0xbc */ u8 lna_type_2g; /* 0xbd */ - u8 res2[1]; + u8 res3[1]; u8 lna_type_5g; /* 0xbf */ - u8 res13[1]; + u8 res4[1]; u8 rf_board_option; u8 rf_feature_option; u8 rf_bt_setting; u8 eeprom_version; u8 eeprom_customer_id; - u8 res3[3]; + u8 res5[3]; u8 rf_antenna_option; /* 0xc9 */ - u8 res4[6]; + u8 res6[6]; u8 vid; /* 0xd0 */ - u8 res5[1]; + u8 res7[1]; u8 pid; /* 0xd2 */ - u8 res6[1]; + u8 res8[1]; u8 usb_optional_function; - u8 res7[2]; + u8 res9[2]; u8 mac_addr[ETH_ALEN]; /* 0xd7 */ - u8 res8[2]; + u8 res10[2]; u8 vendor_name[7]; - u8 res9[2]; + u8 res11[2]; u8 device_name[0x0b]; /* 0xe8 */ - u8 res10[2]; + u8 res12[2]; u8 serial[0x0b]; /* 0xf5 */ - u8 res11[0x30]; + u8 res13[0x30]; u8 unknown[0x0d]; /* 0x130 */ - u8 res12[0xc3]; + u8 res14[0xc3]; }; struct rtl8xxxu_reg8val { -- GitLab From 444004bd134990456329267ac6365e71d73aeb85 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:24 -0400 Subject: [PATCH 2735/9938] rtl8xxxu: Handle BB init for 8192eu The 8192eu does not use REG_AFE_PLL_CTRL in it's BB init sequence, so provide device specific handling. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 539f7b58bbf7..dc67f5b2dbae 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3649,6 +3649,11 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00); + } else if (priv->rtl_chip == RTL8192E) { + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | + SYS_FUNC_DIO_RF; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); } else { val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); udelay(2); -- GitLab From 2949b9ee77b819b90d23096ef44744244283e630 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:25 -0400 Subject: [PATCH 2736/9938] rtl8xxxu: Provide special handling when writing RF regs on 8192eu The 8192eu requires clearing/restoring bit 17 in REG_FPGA0_POWER_SAVE before/after writing RF registers. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index dc67f5b2dbae..ad5b3d3f7084 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1896,7 +1896,7 @@ static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, enum rtl8xxxu_rfpath path, u8 reg, u32 data) { int ret, retval; - u32 dataaddr; + u32 dataaddr, val32; if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_WRITE) dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n", @@ -1905,6 +1905,12 @@ static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, data &= FPGA0_LSSI_PARM_DATA_MASK; dataaddr = (reg << FPGA0_LSSI_PARM_ADDR_SHIFT) | data; + if (priv->rtl_chip == RTL8192E) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); + val32 &= ~0x20000; + rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32); + } + /* Use XB for path B */ ret = rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].lssiparm, dataaddr); if (ret != sizeof(dataaddr)) @@ -1914,6 +1920,12 @@ static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, udelay(1); + if (priv->rtl_chip == RTL8192E) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); + val32 |= 0x20000; + rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32); + } + return retval; } -- GitLab From 8a59485c8ee911e77ace1622520976321aaf3820 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:26 -0400 Subject: [PATCH 2737/9938] rtl8xxxu: Handle XTAL value setting on 8192eu Set REG_AFE_XTAL_CTRL on 8192eu to the vendor driver value, and do not skip setting REG_MAX_AGGR_NUM on 8192eu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ad5b3d3f7084..e77019256c61 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3608,7 +3608,7 @@ rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv) } } - if (priv->rtl_chip != RTL8723B) + if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) rtl8xxxu_write8(priv, REG_MAX_AGGR_NUM, 0x0a); return 0; @@ -3813,6 +3813,9 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); } + if (priv->rtl_chip == RTL8192E) + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x000f81fb); + return 0; } -- GitLab From 57e5e2e650fb7ad1fe32e1c5e5b1bd01faa238fc Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:27 -0400 Subject: [PATCH 2738/9938] rtl8xxxu: Set correct interrupt masking registers on 8192eu Set HIMR[01] on 8192eu instead of HISR/HIMR. It's not obvious this really matters for USB devices, but this matches the register writes performed by the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index e77019256c61..bcf229d2055b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6883,11 +6883,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, 0xfe42, 0x80); } - if (priv->rtl_chip == RTL8192E) { - rtl8xxxu_write32(priv, REG_HIMR0, 0x00); - rtl8xxxu_write32(priv, REG_HIMR1, 0x00); - } - if (priv->fops->phy_init_antenna_selection) priv->fops->phy_init_antenna_selection(priv); @@ -7053,11 +7048,16 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) */ rtl8xxxu_write8(priv, REG_RX_DRVINFO_SZ, 4); - /* - * Enable all interrupts - not obvious USB needs to do this - */ - rtl8xxxu_write32(priv, REG_HISR, 0xffffffff); - rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff); + if (priv->rtl_chip == RTL8192E) { + rtl8xxxu_write32(priv, REG_HIMR0, 0x00); + rtl8xxxu_write32(priv, REG_HIMR1, 0x00); + } else { + /* + * Enable all interrupts - not obvious USB needs to do this + */ + rtl8xxxu_write32(priv, REG_HISR, 0xffffffff); + rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff); + } rtl8xxxu_set_mac(priv); rtl8xxxu_set_linktype(priv, NL80211_IFTYPE_STATION); -- GitLab From 3021e51f2b2f62a2fa6f49c2d14d103b5a8c331c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:28 -0400 Subject: [PATCH 2739/9938] rtl8xxxu: Set REG_USB_HRPWM for 8192eu The vendor driver set register 0xfe58 REG_USB_HWPWM in it's init sequence for 8192eu. Do the same here. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 ++ drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index bcf229d2055b..fdd11ece3806 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7225,6 +7225,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) val32 |= FPGA_RF_MODE_CCK; rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); } + } else if (priv->rtl_chip == RTL8192E) { + rtl8xxxu_write8(priv, REG_USB_HRPWM, 0x00); } val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index ade42fe7e742..82cbe856694a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -1043,6 +1043,7 @@ #define USB_HIMR_ROK BIT(0) /* Receive DMA OK Interrupt */ #define REG_USB_SPECIAL_OPTION 0xfe55 +#define REG_USB_HRPWM 0xfe58 #define REG_USB_DMA_AGG_TO 0xfe5b #define REG_USB_AGG_TO 0xfe5c #define REG_USB_AGG_TH 0xfe5d -- GitLab From e1394fe5f98638ac0231063245614bb20e94e57f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:29 -0400 Subject: [PATCH 2740/9938] rtl8xxxu: Fix LDPC RX hang issue on 8192eu Implement workaround for LDPC RX hands on 8192eu. This was inspired by workaround found in the 8192eu vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index fdd11ece3806..ed266f081fd0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7234,6 +7234,16 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* ack for xmit mgmt frames. */ rtl8xxxu_write32(priv, REG_FWHW_TXQ_CTRL, val32); + if (priv->rtl_chip == RTL8192E) { + /* + * Fix LDPC rx hang issue. + */ + val32 = rtl8xxxu_read32(priv, REG_AFE_MISC); + rtl8xxxu_write8(priv, REG_8192E_LDOV12_CTRL, 0x75); + val32 &= 0xfff00fff; + val32 |= 0x0007e000; + rtl8xxxu_write32(priv, REG_8192E_LDOV12_CTRL, val32); + } exit: return ret; } -- GitLab From b052b7fc7d25f7c783ffcd87c42b767f6c166724 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:30 -0400 Subject: [PATCH 2741/9938] rtl8xxxu: Implement 8192eu device specific quirks Set REG_QUEUE_CTRL and REG_ACLK_MON for 8192eu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 14 ++++++++++++++ .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ed266f081fd0..3e96ba25bf91 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7197,6 +7197,20 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->fops->init_statistics) priv->fops->init_statistics(priv); + if (priv->rtl_chip == RTL8192E) { + /* + * 0x4c6[3] 1: RTS BW = Data BW + * 0: RTS BW depends on CCA / secondary CCA result. + */ + val8 = rtl8xxxu_read8(priv, REG_QUEUE_CTRL); + val8 &= ~BIT(3); + rtl8xxxu_write8(priv, REG_QUEUE_CTRL, val8); + /* + * Reset USB mode switch setting + */ + rtl8xxxu_write8(priv, REG_ACLK_MON, 0x00); + } + rtl8723a_phy_lc_calibrate(priv); priv->fops->phy_iq_calibrate(priv); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 82cbe856694a..c19f234f1934 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -512,6 +512,7 @@ #define REG_PKT_VO_VI_LIFE_TIME 0x04c0 #define REG_PKT_BE_BK_LIFE_TIME 0x04c2 #define REG_STBC_SETTING 0x04c4 +#define REG_QUEUE_CTRL 0x04c6 #define REG_HT_SINGLE_AMPDU_8723B 0x04c7 #define REG_PROT_MODE_CTRL 0x04c8 #define REG_MAX_AGGR_NUM 0x04ca -- GitLab From 70bc1e24d9e2df3002d714348ca600db83de4c64 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:31 -0400 Subject: [PATCH 2742/9938] rtl8xxxu: Use proper register name for REG_PAD_CTRL1 Fixup another case where the hard coded register value was used instead of the name. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3e96ba25bf91..cd536c0a2387 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3550,9 +3550,9 @@ static void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv) { u32 val32; - val32 = rtl8xxxu_read32(priv, 0x64); + val32 = rtl8xxxu_read32(priv, REG_PAD_CTRL1); val32 &= ~(BIT(20) | BIT(24)); - rtl8xxxu_write32(priv, 0x64, val32); + rtl8xxxu_write32(priv, REG_PAD_CTRL1, val32); val32 = rtl8xxxu_read32(priv, REG_GPIO_MUXCFG); val32 &= ~BIT(4); -- GitLab From f991f4e9147b1b7c9546c08f80d8d8f0aa53df2e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:32 -0400 Subject: [PATCH 2743/9938] rtl8xxxu: Implement IQK calibration for 8192eu 8192eu has it's own IQK calibration procedure, and notably uses undocumented RF register 0x56 in the process. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 608 +++++++++++++++++- .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 + 2 files changed, 608 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index cd536c0a2387..c08bbcbe4a0d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4955,6 +4955,334 @@ static int rtl8723bu_iqk_path_b(struct rtl8xxxu_priv *priv) } #endif +static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_e94, reg_e9c; + int result = 0; + + /* + * TX IQK + * PA/PAD controlled by 0x0 + */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Path A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82140303); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x68160000); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) + result |= 0x01; + + return result; +} + +static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32; + int result = 0; + + /* Leave IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00); + + /* Enable path A PA in TX IQK mode */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf117b); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* TX IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x68160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + goto out; + } + + val32 = 0x80007c00 | + (reg_e94 & 0x03ff0000) | ((reg_e9c >> 16) & 0x03ff); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ffa); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* Path A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + + if (!(reg_eac & BIT(27)) && + ((reg_ea4 & 0x03ff0000) != 0x01320000) && + ((reg_eac & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n", + __func__); + +out: + return result; +} + +static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc; + int result = 0; + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Path B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x821403e2); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x68160000); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00492911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(1); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else + dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n", + __func__); + + return result; +} + +static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32; + int result = 0; + + /* Leave IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + /* Enable path A PA in TX IQK mode */ + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf117b); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* TX IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x68160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { + /* + * PA/PAD controlled by 0x0 + * Vendor driver restores RF_A here which I believe is a bug + */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + goto out; + } + + val32 = 0x80007c00 | + (reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ffa); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* Path A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + + if (!(reg_eac & BIT(30)) && + ((reg_ec4 & 0x03ff0000) != 0x01320000) && + ((reg_ecc & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", + __func__); + +out: + return result; +} + static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, int result[][8], int t) { @@ -5385,6 +5713,194 @@ static void rtl8723bu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, } } +static void rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, + int result[][8], int t) +{ + struct device *dev = &priv->udev->dev; + u32 i, val32; + int path_a_ok, path_b_ok; + int retry = 2; + const u32 adda_regs[RTL8XXXU_ADDA_REGS] = { + REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH, + REG_RX_WAIT_CCA, REG_TX_CCK_RFON, + REG_TX_CCK_BBON, REG_TX_OFDM_RFON, + REG_TX_OFDM_BBON, REG_TX_TO_RX, + REG_TX_TO_TX, REG_RX_CCK, + REG_RX_OFDM, REG_RX_WAIT_RIFS, + REG_RX_TO_RX, REG_STANDBY, + REG_SLEEP, REG_PMPD_ANAEN + }; + const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { + REG_TXPAUSE, REG_BEACON_CTRL, + REG_BEACON_CTRL_1, REG_GPIO_MUXCFG + }; + const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { + REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, + REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE, + REG_FPGA0_XB_RF_INT_OE, REG_CCK0_AFE_SETTING + }; + u8 xa_agc = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1) & 0xff; + u8 xb_agc = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1) & 0xff; + + /* + * Note: IQ calibration must be performed after loading + * PHY_REG.txt , and radio_a, radio_b.txt + */ + + if (t == 0) { + /* Save ADDA parameters, turn Path A ADDA on */ + rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + rtl8xxxu_save_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + } + + rtl8xxxu_path_adda_on(priv, adda_regs, true); + + /* MAC settings */ + rtl8xxxu_mac_calibration(priv, iqk_mac_regs, priv->mac_backup); + + val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); + val32 |= 0x0f000000; + rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); + + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22208200); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); + val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE); + val32 |= BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val32); + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE); + val32 |= BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val32); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192eu_iqk_path_a(priv); + if (path_a_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + + break; + } + } + + if (!path_a_ok) + dev_dbg(dev, "%s: Path A TX IQK failed!\n", __func__); + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192eu_rx_iqk_path_a(priv); + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_BEFORE_IQK_A_2); + result[t][2] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_AFTER_IQK_A_2); + result[t][3] = (val32 >> 16) & 0x3ff; + + break; + } + } + + if (!path_a_ok) + dev_dbg(dev, "%s: Path A RX IQK failed!\n", __func__); + + if (priv->rf_paths > 1) { + dev_warn(dev, "%s: Path B ongoing\n", __func__); + + /* Path A into standby */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x10000); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Turn Path B ADDA on */ + rtl8xxxu_path_adda_on(priv, adda_regs, false); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192eu_iqk_path_b(priv); + if (path_b_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + break; + } + } + + if (!path_b_ok) + dev_dbg(dev, "%s: Path B IQK failed!\n", __func__); + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192eu_rx_iqk_path_b(priv); + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_BEFORE_IQK_B_2); + result[t][6] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_AFTER_IQK_B_2); + result[t][7] = (val32 >> 16) & 0x3ff; + break; + } + } + + if (!path_b_ok) + dev_dbg(dev, "%s: Path B RX IQK failed!\n", __func__); + } + + /* Back to BB mode, load original value */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + if (t) { + /* Reload ADDA power saving parameters */ + rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + + /* Reload MAC parameters */ + rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + + /* Reload BB parameters */ + rtl8xxxu_restore_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + + /* Restore RX initial gain */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1); + val32 &= 0xffffff00; + rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32 | 0x50); + rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32 | xa_agc); + + if (priv->rf_paths > 1) { + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1); + val32 &= 0xffffff00; + rtl8xxxu_write32(priv, REG_OFDM0_XB_AGC_CORE1, + val32 | 0x50); + rtl8xxxu_write32(priv, REG_OFDM0_XB_AGC_CORE1, + val32 | xb_agc); + } + + /* Load 0xe30 IQC default value */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00); + } +} + static void rtl8xxxu_prepare_calibrate(struct rtl8xxxu_priv *priv, u8 start) { struct h2c_cmd h2c; @@ -5630,6 +6146,96 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_prepare_calibrate(priv, 0); } +static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int result[4][8]; /* last is final result */ + int i, candidate; + bool path_a_ok, path_b_ok; + u32 reg_e94, reg_e9c, reg_ea4, reg_eac; + u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; + bool simu; + + memset(result, 0, sizeof(result)); + candidate = -1; + + path_a_ok = false; + path_b_ok = false; + + for (i = 0; i < 3; i++) { + rtl8192eu_phy_iqcalibrate(priv, result, i); + + if (i == 1) { + simu = rtl8723bu_simularity_compare(priv, result, 0, 1); + if (simu) { + candidate = 0; + break; + } + } + + if (i == 2) { + simu = rtl8723bu_simularity_compare(priv, result, 0, 2); + if (simu) { + candidate = 0; + break; + } + + simu = rtl8723bu_simularity_compare(priv, result, 1, 2); + if (simu) + candidate = 1; + else + candidate = 3; + } + } + + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + + if (candidate >= 0) { + reg_e94 = result[candidate][0]; + priv->rege94 = reg_e94; + reg_e9c = result[candidate][1]; + priv->rege9c = reg_e9c; + reg_ea4 = result[candidate][2]; + reg_eac = result[candidate][3]; + reg_eb4 = result[candidate][4]; + priv->regeb4 = reg_eb4; + reg_ebc = result[candidate][5]; + priv->regebc = reg_ebc; + reg_ec4 = result[candidate][6]; + reg_ecc = result[candidate][7]; + dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate); + dev_dbg(dev, + "%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x " + "ecc=%x\n ", __func__, reg_e94, reg_e9c, + reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc); + path_a_ok = true; + path_b_ok = true; + } else { + reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100; + reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0; + } + + if (reg_e94 && candidate >= 0) + rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result, + candidate, (reg_ea4 == 0)); + + if (priv->rf_paths > 1) + rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, + candidate, (reg_ec4 == 0)); + + rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + priv->bb_recovery_backup, RTL8XXXU_BB_REGS); +} + static void rtl8723a_phy_lc_calibrate(struct rtl8xxxu_priv *priv) { u32 val32; @@ -9080,7 +9686,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, - .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, + .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8723bu_parse_rx_desc, .enable_rf = rtl8723b_enable_rf, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index c19f234f1934..2aa14b14a0a5 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -1130,6 +1130,7 @@ #define RF6052_REG_T_METER_8723B 0x42 #define RF6052_REG_UNKNOWN_43 0x43 #define RF6052_REG_UNKNOWN_55 0x55 +#define RF6052_REG_UNKNOWN_56 0x56 #define RF6052_REG_S0S1 0xb0 #define RF6052_REG_UNKNOWN_DF 0xdf #define RF6052_REG_UNKNOWN_ED 0xed -- GitLab From 28e460b02c66116354ced05b570503d252b996e9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:33 -0400 Subject: [PATCH 2744/9938] rtl8xxxu: Adjust AFE crystal value on 8192eu Adjust AFE before enabling PLL on 8192eu, probably also needed for 8723bu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 39 +++++++++++++++++++ .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 4 ++ 2 files changed, 43 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c08bbcbe4a0d..e36fda8c1ad3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7093,6 +7093,41 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) #endif +/* + * This is needed for 8723bu as well, presumable + */ +static void rtl8192e_crystal_afe_adjust(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + + /* + * 40Mhz crystal source, MAC 0x28[2]=0 + */ + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + val8 &= 0xfb; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + + val32 = rtl8xxxu_read32(priv, REG_AFE_CTRL4); + val32 &= 0xfffffc7f; + rtl8xxxu_write32(priv, REG_AFE_CTRL4, val32); + + /* + * 92e AFE parameter + * AFE PLL KVCO selection, MAC 0x28[6]=1 + */ + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + val8 &= 0xbf; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + + /* + * AFE PLL KVCO selection, MAC 0x78[21]=0 + */ + val32 = rtl8xxxu_read32(priv, REG_AFE_CTRL4); + val32 &= 0xffdfffff; + rtl8xxxu_write32(priv, REG_AFE_CTRL4, val32); +} + static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv) { u16 val16; @@ -7115,6 +7150,10 @@ static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_LDO_SW_CTRL, 0x83); } + /* + * Adjust AFE before enabling PLL + */ + rtl8192e_crystal_afe_adjust(priv); rtl8192e_disabled_to_emu(priv); ret = rtl8192e_emu_to_active(priv); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 2aa14b14a0a5..bb08a3939e46 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -109,6 +109,9 @@ #define AFE_XTAL_GATE_DIG BIT(17) #define AFE_XTAL_BT_GATE BIT(20) +/* + * 0x0028 is also known as REG_AFE_CTRL2 on 8723bu/8192eu + */ #define REG_AFE_PLL_CTRL 0x0028 #define AFE_PLL_ENABLE BIT(0) #define AFE_PLL_320_ENABLE BIT(1) @@ -192,6 +195,7 @@ control */ #define MULTI_GPS_FUNC_EN BIT(22) /* GPS function enable */ +#define REG_AFE_CTRL4 0x0078 /* 8192eu/8723bu */ #define REG_LDO_SW_CTRL 0x007c /* 8192eu */ #define REG_MCU_FW_DL 0x0080 -- GitLab From d1279d94b4e47c3684f936ed6b6c89d3dd2cd5b9 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 Mar 2016 19:13:20 +0530 Subject: [PATCH 2745/9938] gpio: of: Scan available child node for gpio-hog Look for child node which are available when iterating for gpio hog node for request/set GPIO initial configuration during OF gpio chip registration. All it really does is make it possible to set status = "disabled"; in the hog nodes, and then they will not be applied. Signed-off-by: Laxman Dewangan Reviewed-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a2485093d10d..d81dbd8e90d9 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -212,7 +212,7 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) enum gpiod_flags dflags; int ret; - for_each_child_of_node(chip->of_node, np) { + for_each_available_child_of_node(chip->of_node, np) { if (!of_property_read_bool(np, "gpio-hog")) continue; -- GitLab From c31a571d4360a7765613615709627e83059ce946 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 Mar 2016 19:13:21 +0530 Subject: [PATCH 2746/9938] gpio: gpiolib: Print error number if gpio hog failed Print the error number of GPIO hog failed during its configurations. This helps in identifying the failure without instrumenting the code. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1edc830a1b51..59a0d8e98a04 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2702,15 +2702,16 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, local_desc = gpiochip_request_own_desc(chip, hwnum, name); if (IS_ERR(local_desc)) { - pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n", - name, chip->label, hwnum); - return PTR_ERR(local_desc); + status = PTR_ERR(local_desc); + pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n", + name, chip->label, hwnum, status); + return status; } status = gpiod_configure_flags(desc, name, dflags); if (status < 0) { - pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n", - name, chip->label, hwnum); + pr_err("setup of hog GPIO %s (chip %s, offset %d) failed, %d\n", + name, chip->label, hwnum, status); gpiochip_free_own_desc(desc); return status; } -- GitLab From 7fde010d473d7eb98a2af3dd91e83838a1f24cdf Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:21 +0200 Subject: [PATCH 2747/9938] brcmfmac: clear eventmask array before using it When the event_msgs iovar is set an array is used to configure the enabled events. This arrays needs to nulled before configuring otherwise unhandled events will be enabled. This solves a problem where in case of wowl the host got woken by an incorrectly enabled event. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index d414fbbcc814..b390561255b3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -371,6 +371,7 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp) int i, err; s8 eventmask[BRCMF_EVENTING_MASK_LEN]; + memset(eventmask, 0, sizeof(eventmask)); for (i = 0; i < BRCMF_E_LAST; i++) { if (ifp->drvr->fweh.evt_handler[i]) { brcmf_dbg(EVENT, "enable event %s\n", -- GitLab From 28b285a6129d0c19bcf9e40bb7767da0fd62974f Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:22 +0200 Subject: [PATCH 2748/9938] brcmfmac: fix clearing wowl wake indicators Newer firmwares require the usage of the wowl wakeind struct as size for the iovar to clear the wake indicators. Older firmwares do not care, so change the used size. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 9a567e263bb1..8daad782b3c3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3608,7 +3608,8 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) wowl_config |= BRCMF_WOWL_UNASSOC; - brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear")); + brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", + sizeof(struct brcmf_wowl_wakeind_le)); brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); brcmf_bus_wowl_config(cfg->pub->bus_if, true); -- GitLab From 46f2b38a91b08ec7faf1839c3cdcec3cfcc6ad50 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:23 +0200 Subject: [PATCH 2749/9938] brcmfmac: insert default boardrev in nvram data if missing Some nvram files/stores come without the boardrev information, but firmware requires this to be set. When not found in nvram then add a default boardrev string to the nvram data. Reported-by: Rafal Milecki Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/firmware.c | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 7269056d0044..c7c1e9906500 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -29,6 +29,7 @@ #define BRCMF_FW_MAX_NVRAM_SIZE 64000 #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */ +#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff" enum nvram_parser_state { IDLE, @@ -51,6 +52,7 @@ enum nvram_parser_state { * @entry: start position of key,value entry. * @multi_dev_v1: detect pcie multi device v1 (compressed). * @multi_dev_v2: detect pcie multi device v2. + * @boardrev_found: nvram contains boardrev information. */ struct nvram_parser { enum nvram_parser_state state; @@ -63,6 +65,7 @@ struct nvram_parser { u32 entry; bool multi_dev_v1; bool multi_dev_v2; + bool boardrev_found; }; /** @@ -125,6 +128,8 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) nvp->multi_dev_v1 = true; if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0) nvp->multi_dev_v2 = true; + if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0) + nvp->boardrev_found = true; } else if (!is_nvram_char(c) || c == ' ') { brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", nvp->line, nvp->column); @@ -284,6 +289,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, while (i < nvp->nvram_len) { if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) { i += 2; + if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0) + nvp->boardrev_found = true; while (nvp->nvram[i] != 0) { nvram[j] = nvp->nvram[i]; i++; @@ -335,6 +342,8 @@ static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr, while (i < nvp->nvram_len - len) { if (strncmp(&nvp->nvram[i], prefix, len) == 0) { i += len; + if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0) + nvp->boardrev_found = true; while (nvp->nvram[i] != 0) { nvram[j] = nvp->nvram[i]; i++; @@ -356,6 +365,18 @@ static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr, nvp->nvram_len = 0; } +static void brcmf_fw_add_defaults(struct nvram_parser *nvp) +{ + if (nvp->boardrev_found) + return; + + memcpy(&nvp->nvram[nvp->nvram_len], &BRCMF_FW_DEFAULT_BOARDREV, + strlen(BRCMF_FW_DEFAULT_BOARDREV)); + nvp->nvram_len += strlen(BRCMF_FW_DEFAULT_BOARDREV); + nvp->nvram[nvp->nvram_len] = '\0'; + nvp->nvram_len++; +} + /* brcmf_nvram_strip :Takes a buffer of "=\n" lines read from a fil * and ending in a NUL. Removes carriage returns, empty lines, comment lines, * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. @@ -377,16 +398,21 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, if (nvp.state == END) break; } - if (nvp.multi_dev_v1) + if (nvp.multi_dev_v1) { + nvp.boardrev_found = false; brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr); - else if (nvp.multi_dev_v2) + } else if (nvp.multi_dev_v2) { + nvp.boardrev_found = false; brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr); + } if (nvp.nvram_len == 0) { kfree(nvp.nvram); return NULL; } + brcmf_fw_add_defaults(&nvp); + pad = nvp.nvram_len; *new_length = roundup(nvp.nvram_len + 1, 4); while (pad != *new_length) { -- GitLab From 2aec2c9d42aa9ac4b31583cf4e1c7774e040e57d Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:24 +0200 Subject: [PATCH 2750/9938] brcmfmac: fix p2p scan abort null pointer exception When p2p connection setup is performed without having ever done an escan a null pointer exception can occur. This is because the ifp to abort scanning is taken from escan struct while it was never initialized. Fix this by using the primary ifp for scan abort. The abort should still be performed and all scan related commands are performed on primary ifp. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index c2ac91df35ed..a70cda6c0592 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -1266,7 +1266,7 @@ static void brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) { struct brcmf_p2p_info *p2p = &cfg->p2p; - struct brcmf_if *ifp = cfg->escan_info.ifp; + struct brcmf_if *ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || -- GitLab From c56caa9db8abbbfb9e31325e0897705aa897db37 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Mon, 11 Apr 2016 11:35:25 +0200 Subject: [PATCH 2751/9938] brcmfmac: screening firmware event packet Firmware uses asynchronized events as a communication method to the host. The event packets are marked as ETH_P_LINK_CTL protocol type. For SDIO and PCIe bus, this kind of packets are delivered through virtual event channel not data channel. This patch adds a screening logic to make sure the event handler only processes the events coming from the correct channel. Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/bus.h | 4 +- .../broadcom/brcm80211/brcmfmac/core.c | 46 +++++++++++++++---- .../broadcom/brcm80211/brcmfmac/core.h | 3 +- .../broadcom/brcm80211/brcmfmac/msgbuf.c | 42 +++++++++-------- .../broadcom/brcm80211/brcmfmac/sdio.c | 32 +++++++++---- .../broadcom/brcm80211/brcmfmac/usb.c | 2 +- 6 files changed, 90 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 8e02a478e889..31856eb57bc4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -216,7 +216,9 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, int prec); /* Receive frame for delivery to OS. Callee disposes of rxp. */ -void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); +void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt); +/* Receive async event packet from firmware. Callee disposes of rxp. */ +void brcmf_rx_event(struct device *dev, struct sk_buff *rxp); /* Indication from bus module regarding presence/insertion of dongle. */ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index ff825cd7739e..8a91a517478b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -311,16 +311,17 @@ void brcmf_txflowblock(struct device *dev, bool state) brcmf_fws_bus_blocked(drvr, state); } -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, + bool handle_event) { - skb->dev = ifp->ndev; - skb->protocol = eth_type_trans(skb, skb->dev); + skb->protocol = eth_type_trans(skb, ifp->ndev); if (skb->pkt_type == PACKET_MULTICAST) ifp->stats.multicast++; /* Process special event packets */ - brcmf_fweh_process_skb(ifp->drvr, skb); + if (handle_event) + brcmf_fweh_process_skb(ifp->drvr, skb); if (!(ifp->ndev->flags & IFF_UP)) { brcmu_pkt_buf_free_skb(skb); @@ -381,7 +382,7 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, /* validate flags and flow id */ if (flags == 0xFF) { brcmf_err("invalid flags...so ignore this packet\n"); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); return; } @@ -393,7 +394,7 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, if (rfi == NULL) { brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", flow_id); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); return; } @@ -418,7 +419,7 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, rfi = kzalloc(buf_size, GFP_ATOMIC); if (rfi == NULL) { brcmf_err("failed to alloc buffer\n"); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); return; } @@ -532,11 +533,11 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, netif_rx: skb_queue_walk_safe(&reorder_list, pkt, pnext) { __skb_unlink(pkt, &reorder_list); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); } } -void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) +void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -560,7 +561,32 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) if (rd->reorder) brcmf_rxreorder_process_info(ifp, rd->reorder, skb); else - brcmf_netif_rx(ifp, skb); + brcmf_netif_rx(ifp, skb, handle_evnt); +} + +void brcmf_rx_event(struct device *dev, struct sk_buff *skb) +{ + struct brcmf_if *ifp; + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pub *drvr = bus_if->drvr; + int ret; + + brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb); + + /* process and remove protocol-specific header */ + ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); + + if (ret || !ifp || !ifp->ndev) { + if (ret != -ENODATA && ifp) + ifp->stats.rx_errors++; + brcmu_pkt_buf_free_skb(skb); + return; + } + + skb->protocol = eth_type_trans(skb, ifp->ndev); + + brcmf_fweh_process_skb(ifp->drvr, skb); + brcmu_pkt_buf_free_skb(skb); } void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 7bdb6fef99c3..d3497e8bd59c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -225,7 +225,8 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, + bool handle_event); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 922966734a7f..3795354b7f12 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -1075,28 +1076,13 @@ static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf) } -static void -brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb, - u8 ifidx) -{ - struct brcmf_if *ifp; - - ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); - if (!ifp || !ifp->ndev) { - brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); - brcmu_pkt_buf_free_skb(skb); - return; - } - brcmf_netif_rx(ifp, skb); -} - - static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) { struct msgbuf_rx_event *event; u32 idx; u16 buflen; struct sk_buff *skb; + struct brcmf_if *ifp; event = (struct msgbuf_rx_event *)buf; idx = le32_to_cpu(event->msg.request_id); @@ -1116,7 +1102,19 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) skb_trim(skb, buflen); - brcmf_msgbuf_rx_skb(msgbuf, skb, event->msg.ifidx); + ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx); + if (!ifp || !ifp->ndev) { + brcmf_err("Received pkt for invalid ifidx %d\n", + event->msg.ifidx); + goto exit; + } + + skb->protocol = eth_type_trans(skb, ifp->ndev); + + brcmf_fweh_process_skb(ifp->drvr, skb); + +exit: + brcmu_pkt_buf_free_skb(skb); } @@ -1128,6 +1126,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) u16 data_offset; u16 buflen; u32 idx; + struct brcmf_if *ifp; brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1); @@ -1148,7 +1147,14 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) skb_trim(skb, buflen); - brcmf_msgbuf_rx_skb(msgbuf, skb, rx_complete->msg.ifidx); + ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx); + if (!ifp || !ifp->ndev) { + brcmf_err("Received pkt for invalid ifidx %d\n", + rx_complete->msg.ifidx); + brcmu_pkt_buf_free_skb(skb); + return; + } + brcmf_netif_rx(ifp, skb, false); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 48d7467d270e..4252fa82b89c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1294,6 +1294,17 @@ static inline u8 brcmf_sdio_getdatoffset(u8 *swheader) return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT); } +static inline bool brcmf_sdio_fromevntchan(u8 *swheader) +{ + u32 hdrvalue; + u8 ret; + + hdrvalue = *(u32 *)swheader; + ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT); + + return (ret == SDPCM_EVENT_CHANNEL); +} + static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, struct brcmf_sdio_hdrinfo *rd, enum brcmf_sdio_frmtype type) @@ -1641,7 +1652,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq) pfirst->len, pfirst->next, pfirst->prev); skb_unlink(pfirst, &bus->glom); - brcmf_rx_frame(bus->sdiodev->dev, pfirst); + if (brcmf_sdio_fromevntchan(pfirst->data)) + brcmf_rx_event(bus->sdiodev->dev, pfirst); + else + brcmf_rx_frame(bus->sdiodev->dev, pfirst, + false); bus->sdcnt.rxglompkts++; } @@ -1967,18 +1982,19 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) __skb_trim(pkt, rd->len); skb_pull(pkt, rd->dat_offset); + if (pkt->len == 0) + brcmu_pkt_buf_free_skb(pkt); + else if (rd->channel == SDPCM_EVENT_CHANNEL) + brcmf_rx_event(bus->sdiodev->dev, pkt); + else + brcmf_rx_frame(bus->sdiodev->dev, pkt, + false); + /* prepare the descriptor for the next read */ rd->len = rd->len_nxtfrm << 4; rd->len_nxtfrm = 0; /* treat all packet as event if we don't know */ rd->channel = SDPCM_EVENT_CHANNEL; - - if (pkt->len == 0) { - brcmu_pkt_buf_free_skb(pkt); - continue; - } - - brcmf_rx_frame(bus->sdiodev->dev, pkt); } rxcount = maxframes - rxleft; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 869eb82db8b1..aa0b2a192faa 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -514,7 +514,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { skb_put(skb, urb->actual_length); - brcmf_rx_frame(devinfo->dev, skb); + brcmf_rx_frame(devinfo->dev, skb, true); brcmf_usb_rx_refill(devinfo, req); } else { brcmu_pkt_buf_free_skb(skb); -- GitLab From bbd1f932e7c45ef173468ae2b49edefe52a8c835 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 11 Apr 2016 11:35:26 +0200 Subject: [PATCH 2752/9938] brcmfmac: cleanup ampdu-rx host reorder code The code for ampdu-rx host reorder is related to the firmware signalling supported in BCDC protocol. This change moves the code to fwsignal module. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/bcdc.c | 7 + .../broadcom/brcm80211/brcmfmac/core.c | 214 +----------------- .../broadcom/brcm80211/brcmfmac/core.h | 4 - .../broadcom/brcm80211/brcmfmac/fwsignal.c | 209 +++++++++++++++++ .../broadcom/brcm80211/brcmfmac/fwsignal.h | 1 + .../broadcom/brcm80211/brcmfmac/msgbuf.c | 4 + .../broadcom/brcm80211/brcmfmac/proto.h | 16 ++ 7 files changed, 239 insertions(+), 216 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 6af658e443e4..288fe906c80e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -351,6 +351,12 @@ brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, { } +static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp, + struct sk_buff *skb) +{ + brcmf_fws_rxreorder(ifp, skb); +} + int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { struct brcmf_bcdc *bcdc; @@ -372,6 +378,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode; drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer; drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer; + drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder; drvr->proto->pd = bcdc; drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 8a91a517478b..a30841bbc5a1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -40,19 +40,6 @@ #define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950) -/* AMPDU rx reordering definitions */ -#define BRCMF_RXREORDER_FLOWID_OFFSET 0 -#define BRCMF_RXREORDER_MAXIDX_OFFSET 2 -#define BRCMF_RXREORDER_FLAGS_OFFSET 4 -#define BRCMF_RXREORDER_CURIDX_OFFSET 6 -#define BRCMF_RXREORDER_EXPIDX_OFFSET 8 - -#define BRCMF_RXREORDER_DEL_FLOW 0x01 -#define BRCMF_RXREORDER_FLUSH_ALL 0x02 -#define BRCMF_RXREORDER_CURIDX_VALID 0x04 -#define BRCMF_RXREORDER_EXPIDX_VALID 0x08 -#define BRCMF_RXREORDER_NEW_HOLE 0x10 - #define BRCMF_BSSIDX_INVALID -1 char *brcmf_ifname(struct brcmf_if *ifp) @@ -342,207 +329,11 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, netif_rx_ni(skb); } -static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi, - u8 start, u8 end, - struct sk_buff_head *skb_list) -{ - /* initialize return list */ - __skb_queue_head_init(skb_list); - - if (rfi->pend_pkts == 0) { - brcmf_dbg(INFO, "no packets in reorder queue\n"); - return; - } - - do { - if (rfi->pktslots[start]) { - __skb_queue_tail(skb_list, rfi->pktslots[start]); - rfi->pktslots[start] = NULL; - } - start++; - if (start > rfi->max_idx) - start = 0; - } while (start != end); - rfi->pend_pkts -= skb_queue_len(skb_list); -} - -static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, - struct sk_buff *pkt) -{ - u8 flow_id, max_idx, cur_idx, exp_idx, end_idx; - struct brcmf_ampdu_rx_reorder *rfi; - struct sk_buff_head reorder_list; - struct sk_buff *pnext; - u8 flags; - u32 buf_size; - - flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET]; - flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET]; - - /* validate flags and flow id */ - if (flags == 0xFF) { - brcmf_err("invalid flags...so ignore this packet\n"); - brcmf_netif_rx(ifp, pkt, false); - return; - } - - rfi = ifp->drvr->reorder_flows[flow_id]; - if (flags & BRCMF_RXREORDER_DEL_FLOW) { - brcmf_dbg(INFO, "flow-%d: delete\n", - flow_id); - - if (rfi == NULL) { - brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", - flow_id); - brcmf_netif_rx(ifp, pkt, false); - return; - } - - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx, - &reorder_list); - /* add the last packet */ - __skb_queue_tail(&reorder_list, pkt); - kfree(rfi); - ifp->drvr->reorder_flows[flow_id] = NULL; - goto netif_rx; - } - /* from here on we need a flow reorder instance */ - if (rfi == NULL) { - buf_size = sizeof(*rfi); - max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; - - buf_size += (max_idx + 1) * sizeof(pkt); - - /* allocate space for flow reorder info */ - brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n", - flow_id, max_idx); - rfi = kzalloc(buf_size, GFP_ATOMIC); - if (rfi == NULL) { - brcmf_err("failed to alloc buffer\n"); - brcmf_netif_rx(ifp, pkt, false); - return; - } - - ifp->drvr->reorder_flows[flow_id] = rfi; - rfi->pktslots = (struct sk_buff **)(rfi+1); - rfi->max_idx = max_idx; - } - if (flags & BRCMF_RXREORDER_NEW_HOLE) { - if (rfi->pend_pkts) { - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, - rfi->exp_idx, - &reorder_list); - WARN_ON(rfi->pend_pkts); - } else { - __skb_queue_head_init(&reorder_list); - } - rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; - rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; - rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; - rfi->pktslots[rfi->cur_idx] = pkt; - rfi->pend_pkts++; - brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n", - flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts); - } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) { - cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; - exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; - - if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) { - /* still in the current hole */ - /* enqueue the current on the buffer chain */ - if (rfi->pktslots[cur_idx] != NULL) { - brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n"); - brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); - rfi->pktslots[cur_idx] = NULL; - } - rfi->pktslots[cur_idx] = pkt; - rfi->pend_pkts++; - rfi->cur_idx = cur_idx; - brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n", - flow_id, cur_idx, exp_idx, rfi->pend_pkts); - - /* can return now as there is no reorder - * list to process. - */ - return; - } - if (rfi->exp_idx == cur_idx) { - if (rfi->pktslots[cur_idx] != NULL) { - brcmf_dbg(INFO, "error buffer pending..free it\n"); - brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); - rfi->pktslots[cur_idx] = NULL; - } - rfi->pktslots[cur_idx] = pkt; - rfi->pend_pkts++; - - /* got the expected one. flush from current to expected - * and update expected - */ - brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n", - flow_id, cur_idx, exp_idx, rfi->pend_pkts); - - rfi->cur_idx = cur_idx; - rfi->exp_idx = exp_idx; - - brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx, - &reorder_list); - brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n", - flow_id, skb_queue_len(&reorder_list), - rfi->pend_pkts); - } else { - u8 end_idx; - - brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n", - flow_id, flags, rfi->cur_idx, rfi->exp_idx, - cur_idx, exp_idx); - if (flags & BRCMF_RXREORDER_FLUSH_ALL) - end_idx = rfi->exp_idx; - else - end_idx = exp_idx; - - /* flush pkts first */ - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, - &reorder_list); - - if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) { - __skb_queue_tail(&reorder_list, pkt); - } else { - rfi->pktslots[cur_idx] = pkt; - rfi->pend_pkts++; - } - rfi->exp_idx = exp_idx; - rfi->cur_idx = cur_idx; - } - } else { - /* explicity window move updating the expected index */ - exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; - - brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n", - flow_id, flags, rfi->exp_idx, exp_idx); - if (flags & BRCMF_RXREORDER_FLUSH_ALL) - end_idx = rfi->exp_idx; - else - end_idx = exp_idx; - - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, - &reorder_list); - __skb_queue_tail(&reorder_list, pkt); - /* set the new expected idx */ - rfi->exp_idx = exp_idx; - } -netif_rx: - skb_queue_walk_safe(&reorder_list, pkt, pnext) { - __skb_unlink(pkt, &reorder_list); - brcmf_netif_rx(ifp, pkt, false); - } -} - void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - struct brcmf_skb_reorder_data *rd; int ret; brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); @@ -557,9 +348,8 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) return; } - rd = (struct brcmf_skb_reorder_data *)skb->cb; - if (rd->reorder) - brcmf_rxreorder_process_info(ifp, rd->reorder, skb); + if (brcmf_proto_is_reorder_skb(skb)) + brcmf_proto_rxreorder(ifp, skb); else brcmf_netif_rx(ifp, skb, handle_evnt); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index d3497e8bd59c..394ae050b960 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -208,10 +208,6 @@ struct brcmf_if { u8 ipv6addr_idx; }; -struct brcmf_skb_reorder_data { - u8 *reorder; -}; - int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); /* Return pointer to interface name */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index f82c9ab5480b..8a07687b46f8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -92,6 +92,19 @@ enum brcmf_fws_tlv_len { }; #undef BRCMF_FWS_TLV_DEF +/* AMPDU rx reordering definitions */ +#define BRCMF_RXREORDER_FLOWID_OFFSET 0 +#define BRCMF_RXREORDER_MAXIDX_OFFSET 2 +#define BRCMF_RXREORDER_FLAGS_OFFSET 4 +#define BRCMF_RXREORDER_CURIDX_OFFSET 6 +#define BRCMF_RXREORDER_EXPIDX_OFFSET 8 + +#define BRCMF_RXREORDER_DEL_FLOW 0x01 +#define BRCMF_RXREORDER_FLUSH_ALL 0x02 +#define BRCMF_RXREORDER_CURIDX_VALID 0x04 +#define BRCMF_RXREORDER_EXPIDX_VALID 0x08 +#define BRCMF_RXREORDER_NEW_HOLE 0x10 + #ifdef DEBUG /* * brcmf_fws_tlv_names - array of tlv names. @@ -1614,6 +1627,202 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp, return 0; } +static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi, + u8 start, u8 end, + struct sk_buff_head *skb_list) +{ + /* initialize return list */ + __skb_queue_head_init(skb_list); + + if (rfi->pend_pkts == 0) { + brcmf_dbg(INFO, "no packets in reorder queue\n"); + return; + } + + do { + if (rfi->pktslots[start]) { + __skb_queue_tail(skb_list, rfi->pktslots[start]); + rfi->pktslots[start] = NULL; + } + start++; + if (start > rfi->max_idx) + start = 0; + } while (start != end); + rfi->pend_pkts -= skb_queue_len(skb_list); +} + +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) +{ + u8 *reorder_data; + u8 flow_id, max_idx, cur_idx, exp_idx, end_idx; + struct brcmf_ampdu_rx_reorder *rfi; + struct sk_buff_head reorder_list; + struct sk_buff *pnext; + u8 flags; + u32 buf_size; + + reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder; + flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET]; + flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET]; + + /* validate flags and flow id */ + if (flags == 0xFF) { + brcmf_err("invalid flags...so ignore this packet\n"); + brcmf_netif_rx(ifp, pkt, false); + return; + } + + rfi = ifp->drvr->reorder_flows[flow_id]; + if (flags & BRCMF_RXREORDER_DEL_FLOW) { + brcmf_dbg(INFO, "flow-%d: delete\n", + flow_id); + + if (rfi == NULL) { + brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", + flow_id); + brcmf_netif_rx(ifp, pkt, false); + return; + } + + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx, + &reorder_list); + /* add the last packet */ + __skb_queue_tail(&reorder_list, pkt); + kfree(rfi); + ifp->drvr->reorder_flows[flow_id] = NULL; + goto netif_rx; + } + /* from here on we need a flow reorder instance */ + if (rfi == NULL) { + buf_size = sizeof(*rfi); + max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; + + buf_size += (max_idx + 1) * sizeof(pkt); + + /* allocate space for flow reorder info */ + brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n", + flow_id, max_idx); + rfi = kzalloc(buf_size, GFP_ATOMIC); + if (rfi == NULL) { + brcmf_err("failed to alloc buffer\n"); + brcmf_netif_rx(ifp, pkt, false); + return; + } + + ifp->drvr->reorder_flows[flow_id] = rfi; + rfi->pktslots = (struct sk_buff **)(rfi + 1); + rfi->max_idx = max_idx; + } + if (flags & BRCMF_RXREORDER_NEW_HOLE) { + if (rfi->pend_pkts) { + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, + rfi->exp_idx, + &reorder_list); + WARN_ON(rfi->pend_pkts); + } else { + __skb_queue_head_init(&reorder_list); + } + rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; + rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; + rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; + rfi->pktslots[rfi->cur_idx] = pkt; + rfi->pend_pkts++; + brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n", + flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts); + } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) { + cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; + exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; + + if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) { + /* still in the current hole */ + /* enqueue the current on the buffer chain */ + if (rfi->pktslots[cur_idx] != NULL) { + brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n"); + brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); + rfi->pktslots[cur_idx] = NULL; + } + rfi->pktslots[cur_idx] = pkt; + rfi->pend_pkts++; + rfi->cur_idx = cur_idx; + brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n", + flow_id, cur_idx, exp_idx, rfi->pend_pkts); + + /* can return now as there is no reorder + * list to process. + */ + return; + } + if (rfi->exp_idx == cur_idx) { + if (rfi->pktslots[cur_idx] != NULL) { + brcmf_dbg(INFO, "error buffer pending..free it\n"); + brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); + rfi->pktslots[cur_idx] = NULL; + } + rfi->pktslots[cur_idx] = pkt; + rfi->pend_pkts++; + + /* got the expected one. flush from current to expected + * and update expected + */ + brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n", + flow_id, cur_idx, exp_idx, rfi->pend_pkts); + + rfi->cur_idx = cur_idx; + rfi->exp_idx = exp_idx; + + brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx, + &reorder_list); + brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n", + flow_id, skb_queue_len(&reorder_list), + rfi->pend_pkts); + } else { + u8 end_idx; + + brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n", + flow_id, flags, rfi->cur_idx, rfi->exp_idx, + cur_idx, exp_idx); + if (flags & BRCMF_RXREORDER_FLUSH_ALL) + end_idx = rfi->exp_idx; + else + end_idx = exp_idx; + + /* flush pkts first */ + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, + &reorder_list); + + if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) { + __skb_queue_tail(&reorder_list, pkt); + } else { + rfi->pktslots[cur_idx] = pkt; + rfi->pend_pkts++; + } + rfi->exp_idx = exp_idx; + rfi->cur_idx = cur_idx; + } + } else { + /* explicity window move updating the expected index */ + exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; + + brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n", + flow_id, flags, rfi->exp_idx, exp_idx); + if (flags & BRCMF_RXREORDER_FLUSH_ALL) + end_idx = rfi->exp_idx; + else + end_idx = exp_idx; + + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, + &reorder_list); + __skb_queue_tail(&reorder_list, pkt); + /* set the new expected idx */ + rfi->exp_idx = exp_idx; + } +netif_rx: + skb_queue_walk_safe(&reorder_list, pkt, pnext) { + __skb_unlink(pkt, &reorder_list); + brcmf_netif_rx(ifp, pkt, false); + } +} + void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb) { struct brcmf_skb_reorder_data *rd; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index a36bac17eafd..ef0ad8597c8a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -29,5 +29,6 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp); void brcmf_fws_del_interface(struct brcmf_if *ifp); void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb); void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked); +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb); #endif /* FWSIGNAL_H_ */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 3795354b7f12..8c064ab24b83 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -527,6 +527,9 @@ static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws, return -ENODEV; } +static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb) +{ +} static void brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid) @@ -1466,6 +1469,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode; drvr->proto->delete_peer = brcmf_msgbuf_delete_peer; drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer; + drvr->proto->rxreorder = brcmf_msgbuf_rxreorder; drvr->proto->pd = msgbuf; init_waitqueue_head(&msgbuf->ioctl_resp_wait); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index d55119d36755..57531f42190e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -22,6 +22,9 @@ enum proto_addr_mode { ADDR_DIRECT }; +struct brcmf_skb_reorder_data { + u8 *reorder; +}; struct brcmf_proto { int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, @@ -38,6 +41,7 @@ struct brcmf_proto { u8 peer[ETH_ALEN]); void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN]); + void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb); void *pd; }; @@ -91,6 +95,18 @@ brcmf_proto_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN]) { drvr->proto->add_tdls_peer(drvr, ifidx, peer); } +static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb) +{ + struct brcmf_skb_reorder_data *rd; + + rd = (struct brcmf_skb_reorder_data *)skb->cb; + return !!rd->reorder; +} +static inline void +brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb) +{ + ifp->drvr->proto->rxreorder(ifp, skb); +} #endif /* BRCMFMAC_PROTO_H */ -- GitLab From 9c349892ccc90c6de2baaa69cc78449f58082273 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 11 Apr 2016 11:35:27 +0200 Subject: [PATCH 2753/9938] brcmfmac: revise handling events in receive path Move event handling out of brcmf_netif_rx() avoiding the need to pass a flag. This flag is only ever true for USB hosts as other interface use separate brcmf_rx_event() function. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/bus.h | 2 +- .../broadcom/brcm80211/brcmfmac/core.c | 24 +++++++++---------- .../broadcom/brcm80211/brcmfmac/core.h | 3 +-- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 8 +++---- .../broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 31856eb57bc4..2b246545647a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -216,7 +216,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, int prec); /* Receive frame for delivery to OS. Callee disposes of rxp. */ -void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt); +void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event); /* Receive async event packet from firmware. Callee disposes of rxp. */ void brcmf_rx_event(struct device *dev, struct sk_buff *rxp); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index a30841bbc5a1..9b53555cf85c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -298,18 +298,11 @@ void brcmf_txflowblock(struct device *dev, bool state) brcmf_fws_bus_blocked(drvr, state); } -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, - bool handle_event) +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) { - skb->protocol = eth_type_trans(skb, ifp->ndev); - if (skb->pkt_type == PACKET_MULTICAST) ifp->stats.multicast++; - /* Process special event packets */ - if (handle_event) - brcmf_fweh_process_skb(ifp->drvr, skb); - if (!(ifp->ndev->flags & IFF_UP)) { brcmu_pkt_buf_free_skb(skb); return; @@ -329,7 +322,7 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, netif_rx_ni(skb); } -void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) +void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -348,10 +341,17 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) return; } - if (brcmf_proto_is_reorder_skb(skb)) + skb->protocol = eth_type_trans(skb, ifp->ndev); + + if (brcmf_proto_is_reorder_skb(skb)) { brcmf_proto_rxreorder(ifp, skb); - else - brcmf_netif_rx(ifp, skb, handle_evnt); + } else { + /* Process special event packets */ + if (handle_event) + brcmf_fweh_process_skb(ifp->drvr, skb); + + brcmf_netif_rx(ifp, skb); + } } void brcmf_rx_event(struct device *dev, struct sk_buff *skb) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 394ae050b960..241ee8d13e54 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -221,8 +221,7 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, - bool handle_event); +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 8a07687b46f8..5b30922b67ec 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -1668,7 +1668,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) /* validate flags and flow id */ if (flags == 0xFF) { brcmf_err("invalid flags...so ignore this packet\n"); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); return; } @@ -1680,7 +1680,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) if (rfi == NULL) { brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", flow_id); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); return; } @@ -1705,7 +1705,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) rfi = kzalloc(buf_size, GFP_ATOMIC); if (rfi == NULL) { brcmf_err("failed to alloc buffer\n"); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); return; } @@ -1819,7 +1819,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) netif_rx: skb_queue_walk_safe(&reorder_list, pkt, pnext) { __skb_unlink(pkt, &reorder_list); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); } } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 8c064ab24b83..68f1ce02f4bf 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1157,7 +1157,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) brcmu_pkt_buf_free_skb(skb); return; } - brcmf_netif_rx(ifp, skb, false); + brcmf_netif_rx(ifp, skb); } -- GitLab From c462ebcdfe425a132aaba950d114ac32de3cdf44 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 11 Apr 2016 11:35:28 +0200 Subject: [PATCH 2754/9938] brcmfmac: create common function for handling brcmf_proto_hdrpull() In receive path brcmf_proto_hdrpull() needs to be called and handled similar in brcmf_rx_frame() and brcmf_rx_event(). Move that duplicated code in separate function. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/core.c | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 9b53555cf85c..1b476d1fec2c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -322,26 +322,35 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) netif_rx_ni(skb); } -void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) +static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb, + struct brcmf_if **ifp) { - struct brcmf_if *ifp; - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_pub *drvr = bus_if->drvr; int ret; - brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); - /* process and remove protocol-specific header */ - ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); + ret = brcmf_proto_hdrpull(drvr, true, skb, ifp); - if (ret || !ifp || !ifp->ndev) { + if (ret || !(*ifp) || !(*ifp)->ndev) { if (ret != -ENODATA && ifp) - ifp->stats.rx_errors++; + (*ifp)->stats.rx_errors++; brcmu_pkt_buf_free_skb(skb); - return; + return -ENODATA; } - skb->protocol = eth_type_trans(skb, ifp->ndev); + skb->protocol = eth_type_trans(skb, (*ifp)->ndev); + return 0; +} + +void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) +{ + struct brcmf_if *ifp; + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pub *drvr = bus_if->drvr; + + brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); + + if (brcmf_rx_hdrpull(drvr, skb, &ifp)) + return; if (brcmf_proto_is_reorder_skb(skb)) { brcmf_proto_rxreorder(ifp, skb); @@ -359,21 +368,11 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb) struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - int ret; brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb); - /* process and remove protocol-specific header */ - ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); - - if (ret || !ifp || !ifp->ndev) { - if (ret != -ENODATA && ifp) - ifp->stats.rx_errors++; - brcmu_pkt_buf_free_skb(skb); + if (brcmf_rx_hdrpull(drvr, skb, &ifp)) return; - } - - skb->protocol = eth_type_trans(skb, ifp->ndev); brcmf_fweh_process_skb(ifp->drvr, skb); brcmu_pkt_buf_free_skb(skb); -- GitLab From c865a70098d9419d154f6d1ad97cd0150af968d1 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 11 Apr 2016 07:52:37 -0700 Subject: [PATCH 2755/9938] mwifiex: missing break statement This patch adds missing break statement at the end of PCIE_DEVICE_ID_MARVELL_88W8897 switch section. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index edf8b070f665..c28edbb73d8f 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2831,6 +2831,7 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) default: break; } + break; case PCIE_DEVICE_ID_MARVELL_88W8997: mwifiex_read_reg(adapter, 0x0c48, &revision_id); switch (revision_id) { -- GitLab From e87650bce9a5499f133341db99c9293bfb8a0282 Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Mon, 11 Apr 2016 07:52:38 -0700 Subject: [PATCH 2756/9938] mwifiex: add pcie usb/uart firmware download support This patch adds support for downloading usb/uart firmware for 8997 chipset by reading the chip version. Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 17 +++++++++++++++-- drivers/net/wireless/marvell/mwifiex/pcie.h | 7 +++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index c28edbb73d8f..1d888b501e16 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2811,6 +2811,7 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) { int revision_id = 0; + int version; struct pcie_service_card *card = adapter->card; switch (card->dev->device) { @@ -2834,12 +2835,24 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) break; case PCIE_DEVICE_ID_MARVELL_88W8997: mwifiex_read_reg(adapter, 0x0c48, &revision_id); + mwifiex_read_reg(adapter, 0x0cd0, &version); + version &= 0x7; switch (revision_id) { case PCIE8997_V2: - strcpy(adapter->fw_name, PCIE8997_FW_NAME_V2); + if (version == CHIP_VER_PCIEUSB) + strcpy(adapter->fw_name, + PCIEUSB8997_FW_NAME_V2); + else + strcpy(adapter->fw_name, + PCIEUART8997_FW_NAME_V2); break; case PCIE8997_Z: - strcpy(adapter->fw_name, PCIE8997_FW_NAME_Z); + if (version == CHIP_VER_PCIEUSB) + strcpy(adapter->fw_name, + PCIEUSB8997_FW_NAME_Z); + else + strcpy(adapter->fw_name, + PCIEUART8997_FW_NAME_Z); break; default: break; diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index cc7a5df903be..bbabfb01a10a 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -32,8 +32,10 @@ #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" #define PCIE8897_A0_FW_NAME "mrvl/pcie8897_uapsta_a0.bin" #define PCIE8897_B0_FW_NAME "mrvl/pcie8897_uapsta.bin" -#define PCIE8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin" -#define PCIE8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin" +#define PCIEUART8997_FW_NAME_Z "mrvl/pcieuart8997_combo.bin" +#define PCIEUART8997_FW_NAME_V2 "mrvl/pcieuart8997_combo_v2.bin" +#define PCIEUSB8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin" +#define PCIEUSB8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin" #define PCIE_VENDOR_ID_MARVELL (0x11ab) #define PCIE_VENDOR_ID_V2_MARVELL (0x1b4b) @@ -45,6 +47,7 @@ #define PCIE8897_B0 0x1200 #define PCIE8997_Z 0x0 #define PCIE8997_V2 0x471 +#define CHIP_VER_PCIEUSB 0x2 /* Constants for Buffer Descriptor (BD) rings */ #define MWIFIEX_MAX_TXRX_BD 0x20 -- GitLab From b9db397879333c272f2bc888cd713773e7d2604f Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Mon, 11 Apr 2016 07:52:39 -0700 Subject: [PATCH 2757/9938] mwifiex: add default setting for pcie firmware download This patch adds default setting for pcie firmware download name in case that there are newer chipset version. Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 3 +++ drivers/net/wireless/marvell/mwifiex/pcie.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 1d888b501e16..0c7937eb6b77 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2830,6 +2830,8 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) strcpy(adapter->fw_name, PCIE8897_B0_FW_NAME); break; default: + strcpy(adapter->fw_name, PCIE8897_DEFAULT_FW_NAME); + break; } break; @@ -2855,6 +2857,7 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) PCIEUART8997_FW_NAME_Z); break; default: + strcpy(adapter->fw_name, PCIE8997_DEFAULT_FW_NAME); break; } default: diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index bbabfb01a10a..5770b4396b21 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -30,8 +30,10 @@ #include "main.h" #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" +#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin" #define PCIE8897_A0_FW_NAME "mrvl/pcie8897_uapsta_a0.bin" #define PCIE8897_B0_FW_NAME "mrvl/pcie8897_uapsta.bin" +#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcieuart8997_combo_v2.bin" #define PCIEUART8997_FW_NAME_Z "mrvl/pcieuart8997_combo.bin" #define PCIEUART8997_FW_NAME_V2 "mrvl/pcieuart8997_combo_v2.bin" #define PCIEUSB8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin" -- GitLab From c3ec0ff6425b86655aa34b5c6cb0f7b6d559c6b2 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 11 Apr 2016 07:52:40 -0700 Subject: [PATCH 2758/9938] mwifiex: do not wait on semaphore during card removal Host hang is observed if card is removed before firmware download gets completed. In this case, firmware will be failed to download and adapter structure gets freed. In other thread, mwifiex_remove_card() waits on semaphore until the firmware download fails. This wait is not necessary and may result in invalid adapter access. This patch uses down_trylock to return immediately so that hang issue won't occur. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 04b975cbb330..b459c70dc43f 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1434,7 +1434,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) struct mwifiex_private *priv = NULL; int i; - if (down_interruptible(sem)) + if (down_trylock(sem)) goto exit_sem_err; if (!adapter) -- GitLab From bcc920e8f08336cbbdcdba7c4449c27137e6b4b9 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 11 Apr 2016 07:52:41 -0700 Subject: [PATCH 2759/9938] mwifiex: fix incorrect ht capability problem IEEE80211_CHAN_NO_HT40PLUS and IEEE80211_CHAN_NO_HT40PLUS channel flags tell if HT40 operation is allowed on a channel or not. This patch ensures ht_capability information is modified accordingly so that we don't end up creating a HT40 connection when it's not allowed for current regulatory domain. Signed-off-by: Amitkumar Karwar Signed-off-by: Cathy Luo Signed-off-by: Kalle Valo --- .../net/wireless/marvell/mwifiex/sta_ioctl.c | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index d8de432d46a2..8e0862657122 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -146,6 +146,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, size_t beacon_ie_len; struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; const struct cfg80211_bss_ies *ies; + int ret; rcu_read_lock(); ies = rcu_dereference(bss->ies); @@ -189,7 +190,48 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT) bss_desc->sensed_11h = true; - return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); + ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); + if (ret) + return ret; + + /* Update HT40 capability based on current channel information */ + if (bss_desc->bcn_ht_oper && bss_desc->bcn_ht_cap) { + u8 ht_param = bss_desc->bcn_ht_oper->ht_param; + u8 radio = mwifiex_band_to_radio_type(bss_desc->bss_band); + struct ieee80211_supported_band *sband = + priv->wdev.wiphy->bands[radio]; + int freq = ieee80211_channel_to_frequency(bss_desc->channel, + radio); + struct ieee80211_channel *chan = + ieee80211_get_channel(priv->adapter->wiphy, freq); + + switch (ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) { + sband->ht_cap.cap &= + ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } else { + sband->ht_cap.cap |= + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SGI_40; + } + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) { + sband->ht_cap.cap &= + ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } else { + sband->ht_cap.cap |= + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SGI_40; + } + break; + } + } + + return 0; } void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv) -- GitLab From 84349698f05dc7ed6df6772d43175eb3703ed8dc Mon Sep 17 00:00:00 2001 From: Vishal Thanki Date: Thu, 7 Apr 2016 23:37:12 +0200 Subject: [PATCH 2760/9938] mwifiex: fix the incorrect WARN_ON during suspend During system suspend, there is a kernel WARNING issued if there is a pending command present. By marking the wait queue disabled after calling the command completion routine fixes it. Signed-off-by: Vishal Thanki Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index a12adee776c6..6f0470646483 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -1009,9 +1009,9 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); /* Cancel current cmd */ if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { - adapter->curr_cmd->wait_q_enabled = false; adapter->cmd_wait_q.status = -1; mwifiex_complete_cmd(adapter, adapter->curr_cmd); + adapter->curr_cmd->wait_q_enabled = false; /* no recycle probably wait for response */ } /* Cancel all pending command */ -- GitLab From 40e1d79ee16968bff7b3cf12c65d5740c02be1b6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Apr 2016 12:34:41 +0300 Subject: [PATCH 2761/9938] regulator: lp3971: Silence uninitialized variable warning This is harmless but if lp3971_i2c_read() fails then "tmp" can be uninitialized. Silence the warning by moving the error handling up a line. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/regulator/lp3971.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 15c25c622edf..204b5c5270e0 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -365,8 +365,8 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val) mutex_lock(&lp3971->io_lock); ret = lp3971_i2c_read(lp3971->i2c, reg, 1, &tmp); - tmp = (tmp & ~mask) | val; if (ret == 0) { + tmp = (tmp & ~mask) | val; ret = lp3971_i2c_write(lp3971->i2c, reg, 1, &tmp); dev_dbg(lp3971->dev, "reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); -- GitLab From 7cb7348f75e442e2ea4bc0b2430a232b13998abf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Apr 2016 12:34:07 +0300 Subject: [PATCH 2762/9938] regulator: lp3972: Silence uninitialized variable warning This is harmless but my static checker complains that "tmp" is uninitialized if lp3972_i2c_read() fails. I have moved the line of code below the error handling to silence the warning. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/regulator/lp3972.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 3a7e96e2c7b3..ff0c275f902e 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -211,8 +211,8 @@ static int lp3972_set_bits(struct lp3972 *lp3972, u8 reg, u16 mask, u16 val) mutex_lock(&lp3972->io_lock); ret = lp3972_i2c_read(lp3972->i2c, reg, 1, &tmp); - tmp = (tmp & ~mask) | val; if (ret == 0) { + tmp = (tmp & ~mask) | val; ret = lp3972_i2c_write(lp3972->i2c, reg, 1, &tmp); dev_dbg(lp3972->dev, "reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val & 0xff); -- GitLab From e97321fa095f1ea7110d4d2ba446bd6141ed9a03 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Tue, 12 Apr 2016 16:14:26 -0400 Subject: [PATCH 2763/9938] GFS2: Don't dereference inode in gfs2_inode_lookup until it's valid Function gfs2_inode_lookup was dereferencing the inode, and after, it checks for the value being NULL. We need to check that first. Signed-off-by: Bob Peterson --- fs/gfs2/inode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index bb30f9a72c65..aea002ea94a6 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -93,12 +93,12 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, int error; inode = iget_locked(sb, (unsigned long)no_addr); - ip = GFS2_I(inode); - ip->i_no_addr = no_addr; - if (!inode) return ERR_PTR(-ENOMEM); + ip = GFS2_I(inode); + ip->i_no_addr = no_addr; + if (inode->i_state & I_NEW) { struct gfs2_sbd *sdp = GFS2_SB(inode); ip->i_no_formal_ino = no_formal_ino; -- GitLab From 14e105cd4085c7bbf42f0eef8c677ad6c7d78a83 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:13:21 +0300 Subject: [PATCH 2764/9938] ath10k: fix checkpatch warnings related to spaces Fix checkpatch warnings about use of spaces with operators: spaces preferred around that '*' (ctx:VxV) This has been recently added to checkpatch. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 6 +++--- drivers/net/wireless/ath/ath10k/ce.h | 2 +- drivers/net/wireless/ath/ath10k/core.h | 6 +++--- drivers/net/wireless/ath/ath10k/debug.h | 2 +- drivers/net/wireless/ath/ath10k/htc.h | 4 ++-- drivers/net/wireless/ath/ath10k/htt.c | 2 +- drivers/net/wireless/ath/ath10k/mac.c | 8 ++++---- drivers/net/wireless/ath/ath10k/targaddrs.h | 2 +- drivers/net/wireless/ath/ath10k/thermal.h | 2 +- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 4 ++-- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.h | 18 +++++++++--------- 13 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 7212802eb327..9fb8d7472d18 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1050,11 +1050,11 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, * * For the lack of a better place do the check here. */ - BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > + BUILD_BUG_ON(2 * TARGET_NUM_MSDU_DESC > (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); - BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > + BUILD_BUG_ON(2 * TARGET_10X_NUM_MSDU_DESC > (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); - BUILD_BUG_ON(2*TARGET_TLV_NUM_MSDU_DESC > + BUILD_BUG_ON(2 * TARGET_TLV_NUM_MSDU_DESC > (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); ce_state->ar = ar; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 25cafcfd6b12..dfc098606bee 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -408,7 +408,7 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) /* Ring arithmetic (modulus number of entries in ring, which is a pwr of 2). */ #define CE_RING_DELTA(nentries_mask, fromidx, toidx) \ - (((int)(toidx)-(int)(fromidx)) & (nentries_mask)) + (((int)(toidx) - (int)(fromidx)) & (nentries_mask)) #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) #define CE_RING_IDX_ADD(nentries_mask, idx, num) \ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d85b99164212..e6f889df1e0d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -44,8 +44,8 @@ #define ATH10K_SCAN_ID 0 #define WMI_READY_TIMEOUT (5 * HZ) -#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ) -#define ATH10K_CONNECTION_LOSS_HZ (3*HZ) +#define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ) +#define ATH10K_CONNECTION_LOSS_HZ (3 * HZ) #define ATH10K_NUM_CHANS 39 /* Antenna noise floor */ @@ -334,7 +334,7 @@ struct ath10k_sta { #endif }; -#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) +#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) enum ath10k_beacon_state { ATH10K_BEACON_SCHEDULED = 0, diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 6206edd7c49f..75c89e3625ef 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -57,7 +57,7 @@ enum ath10k_dbg_aggr_mode { }; /* FIXME: How to calculate the buffer size sanely? */ -#define ATH10K_FW_STATS_BUF_SIZE (1024*1024) +#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024) extern unsigned int ath10k_debug_mask; diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index e70aa38e6e05..cc827185d3e9 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -297,10 +297,10 @@ struct ath10k_htc_svc_conn_resp { #define ATH10K_NUM_CONTROL_TX_BUFFERS 2 #define ATH10K_HTC_MAX_LEN 4096 #define ATH10K_HTC_MAX_CTRL_MSG_LEN 256 -#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1*HZ) +#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1 * HZ) #define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \ sizeof(struct ath10k_htc_hdr)) -#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1*HZ) +#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1 * HZ) struct ath10k_htc_ep { struct ath10k_htc *htc; diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 17a3008d9ab1..ee79512b1fcc 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -208,7 +208,7 @@ int ath10k_htt_init(struct ath10k *ar) return 0; } -#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ) +#define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ) static int ath10k_htt_verify_version(struct ath10k_htt *htt) { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c30a3944b612..4300410ecddf 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3846,7 +3846,7 @@ static int ath10k_scan_stop(struct ath10k *ar) goto out; } - ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ); + ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ); if (ret == 0) { ath10k_warn(ar, "failed to receive scan abortion completion: timed out\n"); ret = -ETIMEDOUT; @@ -3926,7 +3926,7 @@ static int ath10k_start_scan(struct ath10k *ar, if (ret) return ret; - ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ); + ret = wait_for_completion_timeout(&ar->scan.started, 1 * HZ); if (ret == 0) { ret = ath10k_scan_stop(ar); if (ret) @@ -6168,7 +6168,7 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw, return ret; } -#define ATH10K_ROC_TIMEOUT_HZ (2*HZ) +#define ATH10K_ROC_TIMEOUT_HZ (2 * HZ) static int ath10k_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -6232,7 +6232,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw, goto exit; } - ret = wait_for_completion_timeout(&ar->scan.on_channel, 3*HZ); + ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ); if (ret == 0) { ath10k_warn(ar, "failed to switch to channel for roc scan\n"); diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 361f143b019c..8e24099fa936 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -438,7 +438,7 @@ Fw Mode/SubMode Mask ((HOST_INTEREST->hi_pwr_save_flags & HI_PWR_SAVE_LPL_ENABLED)) #define HI_DEV_LPL_TYPE_GET(_devix) \ (HOST_INTEREST->hi_pwr_save_flags & ((HI_PWR_SAVE_LPL_DEV_MASK) << \ - (HI_PWR_SAVE_LPL_DEV0_LSB + (_devix)*2))) + (HI_PWR_SAVE_LPL_DEV0_LSB + (_devix) * 2))) #define HOST_INTEREST_SMPS_IS_ALLOWED() \ ((HOST_INTEREST->hi_smps_options & HI_SMPS_ALLOW_MASK)) diff --git a/drivers/net/wireless/ath/ath10k/thermal.h b/drivers/net/wireless/ath/ath10k/thermal.h index c9223e9e962f..3abb97f63b1e 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.h +++ b/drivers/net/wireless/ath/ath10k/thermal.h @@ -20,7 +20,7 @@ #define ATH10K_QUIET_PERIOD_MIN 25 #define ATH10K_QUIET_START_OFFSET 10 #define ATH10K_HWMON_NAME_LEN 15 -#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5*HZ) +#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5 * HZ) #define ATH10K_THERMAL_THROTTLE_MAX 100 struct ath10k_thermal { diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 9369411a9ac0..c503ff601a54 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -166,7 +166,7 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id, (mapped == expect_mapped || test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)); - }), 3*HZ); + }), 3 * HZ); if (time_left == 0) return -ETIMEDOUT; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index dd678590531a..b8aa6000573c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -968,8 +968,8 @@ enum wmi_tlv_service { #define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \ ((svc_id) < (len) && \ - __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \ - BIT((svc_id)%(sizeof(u32)))) + __le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \ + BIT((svc_id) % (sizeof(u32)))) #define SVCMAP(x, y, len) \ do { \ diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index e8d9a3e5c2df..d64e8681898d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1808,7 +1808,7 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id) ret = -ESHUTDOWN; (ret != -EAGAIN); - }), 3*HZ); + }), 3 * HZ); if (ret) dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index c83e1e39f8cc..378f2998cd5a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -405,8 +405,8 @@ static inline char *wmi_service_name(int service_id) #define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \ ((svc_id) < (len) && \ - __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \ - BIT((svc_id)%(sizeof(u32)))) + __le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \ + BIT((svc_id) % (sizeof(u32)))) #define SVCMAP(x, y, len) \ do { \ @@ -1309,7 +1309,7 @@ enum wmi_10x_event_id { WMI_10X_PDEV_TPC_CONFIG_EVENTID, WMI_10X_GPIO_INPUT_EVENTID, - WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1, + WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID - 1, }; enum wmi_10_2_cmd_id { @@ -2042,8 +2042,8 @@ struct wmi_10x_service_ready_event { struct wlan_host_mem_req mem_reqs[0]; } __packed; -#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) -#define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) +#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ) +#define WMI_UNIFIED_READY_TIMEOUT_HZ (5 * HZ) struct wmi_ready_event { __le32 sw_version; @@ -4389,14 +4389,14 @@ enum wmi_vdev_subtype_10_4 { /* * Indicates that AP VDEV uses hidden ssid. only valid for * AP/GO */ -#define WMI_VDEV_START_HIDDEN_SSID (1<<0) +#define WMI_VDEV_START_HIDDEN_SSID (1 << 0) /* * Indicates if robust management frame/management frame * protection is enabled. For GO/AP vdevs, it indicates that * it may support station/client associations with RMF enabled. * For STA/client vdevs, it indicates that sta will * associate with AP with RMF enabled. */ -#define WMI_VDEV_START_PMF_ENABLED (1<<1) +#define WMI_VDEV_START_PMF_ENABLED (1 << 1) struct wmi_p2p_noa_descriptor { __le32 type_count; /* 255: continuous schedule, 0: reserved */ @@ -5342,7 +5342,7 @@ enum wmi_sta_ps_param_pspoll_count { #define WMI_UAPSD_AC_TYPE_TRIG 1 #define WMI_UAPSD_AC_BIT_MASK(ac, type) \ - ((type == WMI_UAPSD_AC_TYPE_DELI) ? (1<<(ac<<1)) : (1<<((ac<<1)+1))) + ((type == WMI_UAPSD_AC_TYPE_DELI) ? (1 << (ac << 1)) : (1 << ((ac << 1) + 1))) enum wmi_sta_ps_param_uapsd { WMI_STA_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0), @@ -5757,7 +5757,7 @@ struct wmi_rate_set { * the rates are filled from least significant byte to most * significant byte. */ - __le32 rates[(MAX_SUPPORTED_RATES/4)+1]; + __le32 rates[(MAX_SUPPORTED_RATES / 4) + 1]; } __packed; struct wmi_rate_set_arg { -- GitLab From beeb1a302f783b0ddeabafebf03f30d589df15eb Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:13:35 +0300 Subject: [PATCH 2765/9938] ath10k: prefer kernel type 'u64' over 'u_int64_t' Fixes checkpatch warnings: drivers/net/wireless/ath/ath10k/htt.h:1477: Prefer kernel type 'u64' over 'u_int64_t' drivers/net/wireless/ath/ath10k/htt.h:1480: Prefer kernel type 'u64' over 'u_int64_t' Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 60bd9fe4b2d9..ee7c8f8f8073 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1475,10 +1475,10 @@ union htt_rx_pn_t { u32 pn24; /* TKIP or CCMP: 48-bit PN */ - u_int64_t pn48; + u64 pn48; /* WAPI: 128-bit PN */ - u_int64_t pn128[2]; + u64 pn128[2]; }; struct htt_cmd { -- GitLab From c178da58c7aa73d1442ce10cc61df41224115d19 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:13:49 +0300 Subject: [PATCH 2766/9938] ath10k: prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() Fixes checkpatch warnings: drivers/net/wireless/ath/ath10k/mac.c:452: Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() drivers/net/wireless/ath/ath10k/mac.c:455: Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() drivers/net/wireless/ath/ath10k/txrx.c:133: Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 4 ++-- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4300410ecddf..76ea1ccb59c5 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -449,10 +449,10 @@ static int ath10k_mac_vif_update_wep_key(struct ath10k_vif *arvif, lockdep_assert_held(&ar->conf_mutex); list_for_each_entry(peer, &ar->peers, list) { - if (!memcmp(peer->addr, arvif->vif->addr, ETH_ALEN)) + if (ether_addr_equal(peer->addr, arvif->vif->addr)) continue; - if (!memcmp(peer->addr, arvif->bssid, ETH_ALEN)) + if (ether_addr_equal(peer->addr, arvif->bssid)) continue; if (peer->keys[key->keyidx] == key) diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index c503ff601a54..8c7086989a71 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -130,7 +130,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, list_for_each_entry(peer, &ar->peers, list) { if (peer->vdev_id != vdev_id) continue; - if (memcmp(peer->addr, addr, ETH_ALEN)) + if (!ether_addr_equal(peer->addr, addr)) continue; return peer; -- GitLab From 8f4ffb7de9630065040e8142d651708e85eeb863 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:14:02 +0300 Subject: [PATCH 2767/9938] ath10k: prefer ether_addr_copy() over memcpy() Fixes checkpatch warning: drivers/net/wireless/ath/ath10k/wmi.c:5800: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index d64e8681898d..7eb40f54fdb5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5827,9 +5827,8 @@ ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs, bssids->num_bssid = __cpu_to_le32(arg->n_bssids); for (i = 0; i < arg->n_bssids; i++) - memcpy(&bssids->bssid_list[i], - arg->bssids[i].bssid, - ETH_ALEN); + ether_addr_copy(bssids->bssid_list[i].addr, + arg->bssids[i].bssid); ptr += sizeof(*bssids); ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids; -- GitLab From 4d16544d0bde4b19da30789a8715635fd9c3889d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:14:16 +0300 Subject: [PATCH 2768/9938] ath10k: fix parenthesis alignment Found by checkpatch: drivers/net/wireless/ath/ath10k/mac.c:6800: Alignment should match open parent Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 76ea1ccb59c5..d9d98bf22b3e 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6797,7 +6797,7 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } static void ath10k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 tsf) + u64 tsf) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); -- GitLab From 2958987f5da2ebcf6a237c5f154d7e3340e60945 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 14:25:46 +0200 Subject: [PATCH 2769/9938] arm64/mm: ensure memstart_addr remains sufficiently aligned After choosing memstart_addr to be the highest multiple of ARM64_MEMSTART_ALIGN less than or equal to the first usable physical memory address, we clip the memblocks to the maximum size of the linear region. Since the kernel may be high up in memory, we take care not to clip the kernel itself, which means we have to clip some memory from the bottom if this occurs, to ensure that the distance between the first and the last usable physical memory address can be covered by the linear region. However, we fail to update memstart_addr if this clipping from the bottom occurs, which means that we may still end up with virtual addresses that wrap into the userland range. So increment memstart_addr as appropriate to prevent this from happening. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/mm/init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index ea989d83ea9b..83ae8b5e5666 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -190,8 +190,12 @@ void __init arm64_memblock_init(void) */ memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)), ULLONG_MAX); - if (memblock_end_of_DRAM() > linear_region_size) - memblock_remove(0, memblock_end_of_DRAM() - linear_region_size); + if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) { + /* ensure that memstart_addr remains sufficiently aligned */ + memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size, + ARM64_MEMSTART_ALIGN); + memblock_remove(0, memstart_addr); + } /* * Apply the memory limit if it was set. Since the kernel may be loaded -- GitLab From 06e9bf2fd9b372bc1c757995b6ca1cfab0720acb Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 14:25:47 +0200 Subject: [PATCH 2770/9938] arm64: choose memstart_addr based on minimum sparsemem section alignment This redefines ARM64_MEMSTART_ALIGN in terms of the minimal alignment required by sparsemem vmemmap. This comes down to using 1 GB for all translation granules if CONFIG_SPARSEMEM_VMEMMAP is enabled. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/include/asm/kernel-pgtable.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h index 5c6375d8528b..7e51d1b57c0c 100644 --- a/arch/arm64/include/asm/kernel-pgtable.h +++ b/arch/arm64/include/asm/kernel-pgtable.h @@ -19,6 +19,7 @@ #ifndef __ASM_KERNEL_PGTABLE_H #define __ASM_KERNEL_PGTABLE_H +#include /* * The linear mapping and the start of memory are both 2M aligned (per @@ -86,10 +87,24 @@ * (64k granule), or a multiple that can be mapped using contiguous bits * in the page tables: 32 * PMD_SIZE (16k granule) */ -#ifdef CONFIG_ARM64_64K_PAGES -#define ARM64_MEMSTART_ALIGN SZ_512M +#if defined(CONFIG_ARM64_4K_PAGES) +#define ARM64_MEMSTART_SHIFT PUD_SHIFT +#elif defined(CONFIG_ARM64_16K_PAGES) +#define ARM64_MEMSTART_SHIFT (PMD_SHIFT + 5) #else -#define ARM64_MEMSTART_ALIGN SZ_1G +#define ARM64_MEMSTART_SHIFT PMD_SHIFT +#endif + +/* + * sparsemem vmemmap imposes an additional requirement on the alignment of + * memstart_addr, due to the fact that the base of the vmemmap region + * has a direct correspondence, and needs to appear sufficiently aligned + * in the virtual address space. + */ +#if defined(CONFIG_SPARSEMEM_VMEMMAP) && ARM64_MEMSTART_SHIFT < SECTION_SIZE_BITS +#define ARM64_MEMSTART_ALIGN (1UL << SECTION_SIZE_BITS) +#else +#define ARM64_MEMSTART_ALIGN (1UL << ARM64_MEMSTART_SHIFT) #endif #endif /* __ASM_KERNEL_PGTABLE_H */ -- GitLab From 3bab79edc67152cb6cadb12773b7c7d05228eb77 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 14:25:48 +0200 Subject: [PATCH 2771/9938] Revert "arm64: account for sparsemem section alignment when choosing vmemmap offset" This reverts commit 36e5cd6b897e17d03008f81e075625d8e43e52d0, since the section alignment is now guaranteed by construction when choosing the value of memstart_addr. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/include/asm/pgtable.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 989fef16d461..aa6106ac050c 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -32,14 +32,13 @@ * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space, * fixed mappings and modules */ -#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE) +#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT - 1)) * sizeof(struct page), PUD_SIZE) #define VMALLOC_START (MODULES_END) #define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K) #define VMEMMAP_START (VMALLOC_END + SZ_64K) -#define vmemmap ((struct page *)VMEMMAP_START - \ - SECTION_ALIGN_DOWN(memstart_addr >> PAGE_SHIFT)) +#define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)) #define FIRST_USER_ADDRESS 0UL -- GitLab From 177e15f0c1444cd392374ec7175c4787fd911369 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 15:18:42 +0200 Subject: [PATCH 2772/9938] arm64: add the initrd region to the linear mapping explicitly Instead of going out of our way to relocate the initrd if it turns out to occupy memory that is not covered by the linear mapping, just add the initrd to the linear mapping. This puts the burden on the bootloader to pass initrd= and mem= options that are mutually consistent. Note that, since the placement of the linear region in the PA space is also dependent on the placement of the kernel Image, which may reside anywhere in memory, we may still end up with a situation where the initrd and the kernel Image are simply too far apart to be covered by the linear region. Since we now leave it up to the bootloader to pass the initrd in memory that is guaranteed to be accessible by the kernel, add a mention of this to the arm64 boot protocol specification as well. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- Documentation/arm64/booting.txt | 4 ++++ arch/arm64/mm/init.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt index 56d6d8b796db..8d0df62c3fe0 100644 --- a/Documentation/arm64/booting.txt +++ b/Documentation/arm64/booting.txt @@ -132,6 +132,10 @@ NOTE: versions prior to v4.6 cannot make use of memory below the physical offset of the Image so it is recommended that the Image be placed as close as possible to the start of system RAM. +If an initrd/initramfs is passed to the kernel at boot, it must reside +entirely within a 1 GB aligned physical memory window of up to 32 GB in +size that fully covers the kernel Image as well. + Any memory described to the kernel (even that below the start of the image) which is not marked as reserved from the kernel (e.g., with a memreserve region in the device tree) will be considered as available to diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 83ae8b5e5666..82ced5fa1e66 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -207,6 +207,35 @@ void __init arm64_memblock_init(void) memblock_add(__pa(_text), (u64)(_end - _text)); } + if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) { + /* + * Add back the memory we just removed if it results in the + * initrd to become inaccessible via the linear mapping. + * Otherwise, this is a no-op + */ + u64 base = initrd_start & PAGE_MASK; + u64 size = PAGE_ALIGN(initrd_end) - base; + + /* + * We can only add back the initrd memory if we don't end up + * with more memory than we can address via the linear mapping. + * It is up to the bootloader to position the kernel and the + * initrd reasonably close to each other (i.e., within 32 GB of + * each other) so that all granule/#levels combinations can + * always access both. + */ + if (WARN(base < memblock_start_of_DRAM() || + base + size > memblock_start_of_DRAM() + + linear_region_size, + "initrd not fully accessible via the linear mapping -- please check your bootloader ...\n")) { + initrd_start = 0; + } else { + memblock_remove(base, size); /* clear MEMBLOCK_ flags */ + memblock_add(base, size); + memblock_reserve(base, size); + } + } + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { extern u16 memstart_offset_seed; u64 range = linear_region_size - -- GitLab From 8923a16686569375bfa25b877769f9a3093e9f22 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 15:18:43 +0200 Subject: [PATCH 2773/9938] arm64: remove the now unneeded relocate_initrd() This removes the relocate_initrd() implementation and invocation, which are no longer needed now that the placement of the initrd is guaranteed to be covered by the linear mapping. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/setup.c | 64 --------------------------------------- 1 file changed, 64 deletions(-) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 9dc67769b6a4..7b85b1d6a6fb 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -224,69 +224,6 @@ static void __init request_standard_resources(void) } } -#ifdef CONFIG_BLK_DEV_INITRD -/* - * Relocate initrd if it is not completely within the linear mapping. - * This would be the case if mem= cuts out all or part of it. - */ -static void __init relocate_initrd(void) -{ - phys_addr_t orig_start = __virt_to_phys(initrd_start); - phys_addr_t orig_end = __virt_to_phys(initrd_end); - phys_addr_t ram_end = memblock_end_of_DRAM(); - phys_addr_t new_start; - unsigned long size, to_free = 0; - void *dest; - - if (orig_end <= ram_end) - return; - - /* - * Any of the original initrd which overlaps the linear map should - * be freed after relocating. - */ - if (orig_start < ram_end) - to_free = ram_end - orig_start; - - size = orig_end - orig_start; - if (!size) - return; - - /* initrd needs to be relocated completely inside linear mapping */ - new_start = memblock_find_in_range(0, PFN_PHYS(max_pfn), - size, PAGE_SIZE); - if (!new_start) - panic("Cannot relocate initrd of size %ld\n", size); - memblock_reserve(new_start, size); - - initrd_start = __phys_to_virt(new_start); - initrd_end = initrd_start + size; - - pr_info("Moving initrd from [%llx-%llx] to [%llx-%llx]\n", - orig_start, orig_start + size - 1, - new_start, new_start + size - 1); - - dest = (void *)initrd_start; - - if (to_free) { - memcpy(dest, (void *)__phys_to_virt(orig_start), to_free); - dest += to_free; - } - - copy_from_early_mem(dest, orig_start + to_free, size - to_free); - - if (to_free) { - pr_info("Freeing original RAMDISK from [%llx-%llx]\n", - orig_start, orig_start + to_free - 1); - memblock_free(orig_start, to_free); - } -} -#else -static inline void __init relocate_initrd(void) -{ -} -#endif - u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; void __init setup_arch(char **cmdline_p) @@ -327,7 +264,6 @@ void __init setup_arch(char **cmdline_p) acpi_boot_table_init(); paging_init(); - relocate_initrd(); kasan_init(); -- GitLab From 0fd71a620be8648486a126fccadf9f7c2a818676 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 14 Apr 2016 10:40:57 -0400 Subject: [PATCH 2774/9938] selinux: Change bool variable name to index. security_get_bool_value(int bool) argument "bool" conflicts with in-kernel macros such as BUILD_BUG(). This patch changes this to index which isn't a type. Cc: Paul Moore Cc: Stephen Smalley Cc: Eric Paris Cc: James Morris Cc: "Serge E. Hallyn" Cc: Rasmus Villemoes Cc: Andrew Perepechko Cc: Jeff Vander Stoep Cc: selinux@tycho.nsa.gov Cc: Eric Paris Cc: Paul Moore Cc: David Howells Signed-off-by: Prarit Bhargava Acked-by: David Howells [PM: wrapped description for checkpatch.pl, use "selinux:..." as subj] Signed-off-by: Paul Moore --- security/selinux/include/conditional.h | 2 +- security/selinux/ss/services.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/security/selinux/include/conditional.h b/security/selinux/include/conditional.h index 67ce7a8d8301..ff4fddca9050 100644 --- a/security/selinux/include/conditional.h +++ b/security/selinux/include/conditional.h @@ -17,6 +17,6 @@ int security_get_bools(int *len, char ***names, int **values); int security_set_bools(int len, int *values); -int security_get_bool_value(int bool); +int security_get_bool_value(int index); #endif diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ebda97333f1b..89df64672b89 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2696,7 +2696,7 @@ int security_set_bools(int len, int *values) return rc; } -int security_get_bool_value(int bool) +int security_get_bool_value(int index) { int rc; int len; @@ -2705,10 +2705,10 @@ int security_get_bool_value(int bool) rc = -EFAULT; len = policydb.p_bools.nprim; - if (bool >= len) + if (index >= len) goto out; - rc = policydb.bool_val_to_struct[bool]->state; + rc = policydb.bool_val_to_struct[index]->state; out: read_unlock(&policy_rwlock); return rc; -- GitLab From 97bbb54e4f27f4c63645f603bf767183ee0dd549 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 16:45:56 +0200 Subject: [PATCH 2775/9938] arm64: vdso: avoid virt_to_page() translations on kernel symbols The translation performed by virt_to_page() is only valid for linear addresses, and kernel symbols are no longer in the linear mapping. So perform the __pa() translation explicitly, which does the right thing in either case, and only then translate to a struct page offset. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/vdso.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 97bc68f4c689..64fc030be0f2 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -131,11 +131,11 @@ static int __init vdso_init(void) return -ENOMEM; /* Grab the vDSO data page. */ - vdso_pagelist[0] = virt_to_page(vdso_data); + vdso_pagelist[0] = pfn_to_page(PHYS_PFN(__pa(vdso_data))); /* Grab the vDSO code pages. */ for (i = 0; i < vdso_pages; i++) - vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE); + vdso_pagelist[i + 1] = pfn_to_page(PHYS_PFN(__pa(&vdso_start)) + i); /* Populate the special mapping structures */ vdso_spec[0] = (struct vm_special_mapping) { -- GitLab From d386825c959efeaae3315c25dd2d2874c68829c7 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 16:45:57 +0200 Subject: [PATCH 2776/9938] arm64: mm: free __init memory via the linear mapping The implementation of free_initmem_default() expects __init_begin and __init_end to be covered by the linear mapping, which is no longer the case. So open code it instead, using addresses that are explicitly translated from kernel virtual to linear virtual. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/mm/init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 82ced5fa1e66..89376f3c65a3 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -452,7 +452,8 @@ void __init mem_init(void) void free_initmem(void) { - free_initmem_default(0); + free_reserved_area(__va(__pa(__init_begin)), __va(__pa(__init_end)), + 0, "unused kernel"); fixup_init(); } -- GitLab From 22b6f3b0549be61a2d5fe8210ff7628e6d2d8185 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 16:45:58 +0200 Subject: [PATCH 2777/9938] arm64: mm: avoid virt_to_page() translation for the zero page The zero page is statically allocated, so grab its struct page pointer without using virt_to_page(), which will be restricted to the linear mapping later. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/include/asm/pgtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index aa6106ac050c..377257a8d393 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -57,7 +57,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); * for zero-mapped memory areas etc.. */ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; -#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page) +#define ZERO_PAGE(vaddr) pfn_to_page(PHYS_PFN(__pa(empty_zero_page))) #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte)) -- GitLab From e44308e62e19b42810207780a2a32148af0cb5d9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 16:45:59 +0200 Subject: [PATCH 2778/9938] arm64: insn: avoid virt_to_page() translations on core kernel symbols Before restricting virt_to_page() to the linear mapping, ensure that the text patching code does not use it to resolve references into the core kernel text, which is mapped in the vmalloc area. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/insn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 7371455160e5..368c08290dd8 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -96,7 +96,7 @@ static void __kprobes *patch_map(void *addr, int fixmap) if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX)) page = vmalloc_to_page(addr); else if (!module && IS_ENABLED(CONFIG_DEBUG_RODATA)) - page = virt_to_page(addr); + page = pfn_to_page(PHYS_PFN(__pa(addr))); else return addr; -- GitLab From 3e1907d5bf5a1e0b182ee599f92586f0165029e2 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 16:46:00 +0200 Subject: [PATCH 2779/9938] arm64: mm: move vmemmap region right below the linear region This moves the vmemmap region right below PAGE_OFFSET, aka the start of the linear region, and redefines its size to be a power of two. Due to the placement of PAGE_OFFSET in the middle of the address space, whose size is a power of two as well, this guarantees that virt to page conversions and vice versa can be implemented efficiently, by masking and shifting rather than ordinary arithmetic. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 18 +++++++++++++++++- arch/arm64/include/asm/pgtable.h | 11 +++-------- arch/arm64/mm/dump.c | 16 ++++++++-------- arch/arm64/mm/init.c | 14 ++++++++++---- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 12f8a00fb3f1..8a2ab195ca77 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -39,6 +39,21 @@ */ #define PCI_IO_SIZE SZ_16M +/* + * Log2 of the upper bound of the size of a struct page. Used for sizing + * the vmemmap region only, does not affect actual memory footprint. + * We don't use sizeof(struct page) directly since taking its size here + * requires its definition to be available at this point in the inclusion + * chain, and it may not be a power of 2 in the first place. + */ +#define STRUCT_PAGE_MAX_SHIFT 6 + +/* + * VMEMMAP_SIZE - allows the whole linear region to be covered by + * a struct page array + */ +#define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)) + /* * PAGE_OFFSET - the virtual address of the start of the kernel image (top * (VA_BITS - 1)) @@ -54,7 +69,8 @@ #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) #define MODULES_VADDR (VA_START + KASAN_SHADOW_SIZE) #define MODULES_VSIZE (SZ_128M) -#define PCI_IO_END (PAGE_OFFSET - SZ_2M) +#define VMEMMAP_START (PAGE_OFFSET - VMEMMAP_SIZE) +#define PCI_IO_END (VMEMMAP_START - SZ_2M) #define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) #define FIXADDR_TOP (PCI_IO_START - SZ_2M) #define TASK_SIZE_64 (UL(1) << VA_BITS) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 377257a8d393..2abfa4d09e65 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -24,20 +24,15 @@ #include /* - * VMALLOC and SPARSEMEM_VMEMMAP ranges. + * VMALLOC range. * - * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array - * (rounded up to PUD_SIZE). * VMALLOC_START: beginning of the kernel vmalloc space - * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space, - * fixed mappings and modules + * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space + * and fixed mappings */ -#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT - 1)) * sizeof(struct page), PUD_SIZE) - #define VMALLOC_START (MODULES_END) #define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K) -#define VMEMMAP_START (VMALLOC_END + SZ_64K) #define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)) #define FIRST_USER_ADDRESS 0UL diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c index f9271cb2f5e3..a21f47421b0c 100644 --- a/arch/arm64/mm/dump.c +++ b/arch/arm64/mm/dump.c @@ -37,14 +37,14 @@ enum address_markers_idx { MODULES_END_NR, VMALLOC_START_NR, VMALLOC_END_NR, -#ifdef CONFIG_SPARSEMEM_VMEMMAP - VMEMMAP_START_NR, - VMEMMAP_END_NR, -#endif FIXADDR_START_NR, FIXADDR_END_NR, PCI_START_NR, PCI_END_NR, +#ifdef CONFIG_SPARSEMEM_VMEMMAP + VMEMMAP_START_NR, + VMEMMAP_END_NR, +#endif KERNEL_SPACE_NR, }; @@ -53,14 +53,14 @@ static struct addr_marker address_markers[] = { { MODULES_END, "Modules end" }, { VMALLOC_START, "vmalloc() Area" }, { VMALLOC_END, "vmalloc() End" }, -#ifdef CONFIG_SPARSEMEM_VMEMMAP - { 0, "vmemmap start" }, - { 0, "vmemmap end" }, -#endif { FIXADDR_START, "Fixmap start" }, { FIXADDR_TOP, "Fixmap end" }, { PCI_IO_START, "PCI I/O start" }, { PCI_IO_END, "PCI I/O end" }, +#ifdef CONFIG_SPARSEMEM_VMEMMAP + { 0, "vmemmap start" }, + { 0, "vmemmap end" }, +#endif { PAGE_OFFSET, "Linear Mapping" }, { -1, NULL }, }; diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 89376f3c65a3..d55d720dba79 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -412,6 +412,10 @@ void __init mem_init(void) MLK_ROUNDUP(__start_rodata, _etext), MLK_ROUNDUP(__init_begin, __init_end), MLK_ROUNDUP(_sdata, _edata)); + pr_cont(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", + MLK(FIXADDR_START, FIXADDR_TOP)); + pr_cont(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", + MLM(PCI_IO_START, PCI_IO_END)); #ifdef CONFIG_SPARSEMEM_VMEMMAP pr_cont(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n" " 0x%16lx - 0x%16lx (%6ld MB actual)\n", @@ -420,10 +424,6 @@ void __init mem_init(void) MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()), (unsigned long)virt_to_page(high_memory))); #endif - pr_cont(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", - MLK(FIXADDR_START, FIXADDR_TOP)); - pr_cont(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", - MLM(PCI_IO_START, PCI_IO_END)); pr_cont(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(__phys_to_virt(memblock_start_of_DRAM()), (unsigned long)high_memory)); @@ -440,6 +440,12 @@ void __init mem_init(void) BUILD_BUG_ON(TASK_SIZE_32 > TASK_SIZE_64); #endif + /* + * Make sure we chose the upper bound of sizeof(struct page) + * correctly. + */ + BUILD_BUG_ON(sizeof(struct page) > (1 << STRUCT_PAGE_MAX_SHIFT)); + if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) { extern int sysctl_overcommit_memory; /* -- GitLab From 9f2875912dac35d9272a82ea9eec9e5884b42cd2 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 16:46:01 +0200 Subject: [PATCH 2780/9938] arm64: mm: restrict virt_to_page() to the linear mapping Now that the vmemmap region has been redefined to cover the linear region rather than the entire physical address space, we no longer need to perform a virtual-to-physical translation in the implementaion of virt_to_page(). This restricts virt_to_page() translations to the linear region, so redefine virt_addr_valid() as well. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/include/asm/memory.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 8a2ab195ca77..f412f502ccdd 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -208,9 +208,19 @@ static inline void *phys_to_virt(phys_addr_t x) */ #define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET) +#ifndef CONFIG_SPARSEMEM_VMEMMAP #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) +#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) +#else +#define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page)) +#define __page_to_voff(kaddr) (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page)) + +#define page_to_virt(page) ((void *)((__page_to_voff(page)) | PAGE_OFFSET)) +#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START)) +#define virt_addr_valid(kaddr) pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \ + + PHYS_OFFSET) >> PAGE_SHIFT) +#endif #endif #include -- GitLab From 3aa02cb664c5fb1042958c8d1aa8c35055a2ebc4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Apr 2016 18:02:37 +0200 Subject: [PATCH 2781/9938] ALSA: pcm : Call kill_fasync() in stream lock Currently kill_fasync() is called outside the stream lock in snd_pcm_period_elapsed(). This is potentially racy, since the stream may get released even during the irq handler is running. Although snd_pcm_release_substream() calls snd_pcm_drop(), this doesn't guarantee that the irq handler finishes, thus the kill_fasync() call outside the stream spin lock may be invoked after the substream is detached, as recently reported by KASAN. As a quick workaround, move kill_fasync() call inside the stream lock. The fasync is rarely used interface, so this shouldn't have a big impact from the performance POV. Ideally, we should implement some sync mechanism for the proper finish of stream and irq handler. But this oneliner should suffice for most cases, so far. Reported-by: Baozeng Ding Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 3a9b66c6e09c..0aca39762ed0 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1886,8 +1886,8 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) snd_timer_interrupt(substream->timer, 1); #endif _end: - snd_pcm_stream_unlock_irqrestore(substream, flags); kill_fasync(&runtime->fasync, SIGIO, POLL_IN); + snd_pcm_stream_unlock_irqrestore(substream, flags); } EXPORT_SYMBOL(snd_pcm_period_elapsed); -- GitLab From bbf86c43eace367e805199f94ad8b5a45636f805 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 13:53:10 -0300 Subject: [PATCH 2782/9938] perf trace: Move socket_type beautifier to tools/perf/trace/beauty/ To reduce the size of builtin-trace.c. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-ao91htwxdqwlwxr47gbluou1@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 60 +-------------------------- tools/perf/trace/beauty/socket_type.c | 60 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 59 deletions(-) create mode 100644 tools/perf/trace/beauty/socket_type.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8e090a785c5e..e5f0cc16bb93 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -51,18 +51,6 @@ # define O_CLOEXEC 02000000 #endif -#ifndef SOCK_DCCP -# define SOCK_DCCP 6 -#endif - -#ifndef SOCK_CLOEXEC -# define SOCK_CLOEXEC 02000000 -#endif - -#ifndef SOCK_NONBLOCK -# define SOCK_NONBLOCK 00004000 -#endif - #ifndef MSG_CMSG_CLOEXEC # define MSG_CMSG_CLOEXEC 0x40000000 #endif @@ -538,53 +526,6 @@ static const char *socket_families[] = { }; static DEFINE_STRARRAY(socket_families); -#ifndef SOCK_TYPE_MASK -#define SOCK_TYPE_MASK 0xf -#endif - -static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, - struct syscall_arg *arg) -{ - size_t printed; - int type = arg->val, - flags = type & ~SOCK_TYPE_MASK; - - type &= SOCK_TYPE_MASK; - /* - * Can't use a strarray, MIPS may override for ABI reasons. - */ - switch (type) { -#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break; - P_SK_TYPE(STREAM); - P_SK_TYPE(DGRAM); - P_SK_TYPE(RAW); - P_SK_TYPE(RDM); - P_SK_TYPE(SEQPACKET); - P_SK_TYPE(DCCP); - P_SK_TYPE(PACKET); -#undef P_SK_TYPE - default: - printed = scnprintf(bf, size, "%#x", type); - } - -#define P_SK_FLAG(n) \ - if (flags & SOCK_##n) { \ - printed += scnprintf(bf + printed, size - printed, "|%s", #n); \ - flags &= ~SOCK_##n; \ - } - - P_SK_FLAG(CLOEXEC); - P_SK_FLAG(NONBLOCK); -#undef P_SK_FLAG - - if (flags) - printed += scnprintf(bf + printed, size - printed, "|%#x", flags); - - return printed; -} - -#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type - #ifndef MSG_PROBE #define MSG_PROBE 0x10 #endif @@ -951,6 +892,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, #include "trace/beauty/mmap.c" #include "trace/beauty/mode_t.c" #include "trace/beauty/sched_policy.c" +#include "trace/beauty/socket_type.c" #include "trace/beauty/waitid_options.c" static struct syscall_fmt { diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c new file mode 100644 index 000000000000..0a5ce818131c --- /dev/null +++ b/tools/perf/trace/beauty/socket_type.c @@ -0,0 +1,60 @@ +#include +#include + +#ifndef SOCK_DCCP +# define SOCK_DCCP 6 +#endif + +#ifndef SOCK_CLOEXEC +# define SOCK_CLOEXEC 02000000 +#endif + +#ifndef SOCK_NONBLOCK +# define SOCK_NONBLOCK 00004000 +#endif + +#ifndef SOCK_TYPE_MASK +#define SOCK_TYPE_MASK 0xf +#endif + +static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct syscall_arg *arg) +{ + size_t printed; + int type = arg->val, + flags = type & ~SOCK_TYPE_MASK; + + type &= SOCK_TYPE_MASK; + /* + * Can't use a strarray, MIPS may override for ABI reasons. + */ + switch (type) { +#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break; + P_SK_TYPE(STREAM); + P_SK_TYPE(DGRAM); + P_SK_TYPE(RAW); + P_SK_TYPE(RDM); + P_SK_TYPE(SEQPACKET); + P_SK_TYPE(DCCP); + P_SK_TYPE(PACKET); +#undef P_SK_TYPE + default: + printed = scnprintf(bf, size, "%#x", type); + } + +#define P_SK_FLAG(n) \ + if (flags & SOCK_##n) { \ + printed += scnprintf(bf + printed, size - printed, "|%s", #n); \ + flags &= ~SOCK_##n; \ + } + + P_SK_FLAG(CLOEXEC); + P_SK_FLAG(NONBLOCK); +#undef P_SK_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "|%#x", flags); + + return printed; +} + +#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type -- GitLab From a354d958d42ae65eca6f5524506e8a9783db198a Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Sun, 20 Mar 2016 20:19:16 +0100 Subject: [PATCH 2783/9938] ARM: mvebu_v7_defconfig: Enabling the new Marvell's cryptographic engine driver This enables the new driver for Marvell CESA crypto engines on all mvebu v7. Signed-off-by: Romain Perier Signed-off-by: Gregory CLEMENT --- arch/arm/configs/mvebu_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig index dc5797a2efab..bedfa95d8d64 100644 --- a/arch/arm/configs/mvebu_v7_defconfig +++ b/arch/arm/configs/mvebu_v7_defconfig @@ -155,3 +155,4 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_TIMER_STATS=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_USER=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=y -- GitLab From e269777f72b32db6200f6d925cc40d8613c5c308 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 29 Mar 2016 18:17:40 +0200 Subject: [PATCH 2784/9938] MAINTAINERS: attach arch/arm/configs/mvebu_*_defconfig to relevant maintainers The arch/arm/configs/mvebu_*_defconfig currently don't belong to any maintainer, so get_maintainer returns only information based on commits, which is not completely accurate. Therefore, this commit replaces a useless empty newline in MAINTAINERS by a line attaching those defconfigs to the appropriate Marvell EBU maintainers. Signed-off-by: Thomas Petazzoni Acked-by: Jason Cooper Signed-off-by: Gregory CLEMENT --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..5bb9f3e47548 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1322,7 +1322,7 @@ F: drivers/rtc/rtc-armada38x.c F: arch/arm/boot/dts/armada* F: arch/arm/boot/dts/kirkwood* F: arch/arm64/boot/dts/marvell/armada* - +F: arch/arm/configs/mvebu_*_defconfig ARM/Marvell Berlin SoC support M: Sebastian Hesselbarth -- GitLab From f092d438018d60fc2a5b507963ae107041c699ea Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 18 Mar 2016 09:44:54 +0100 Subject: [PATCH 2785/9938] ARM: multi_v7_defconfig: Enabling the new Marvell's cryptographic engine driver This enables the new driver for Marvell CESA crypto engines on all ARMv7. Signed-off-by: Romain Perier Signed-off-by: Gregory CLEMENT --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 28234906a064..392e970b60c7 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -829,6 +829,7 @@ CONFIG_LOCKUP_DETECTOR=y CONFIG_CRYPTO_DEV_TEGRA_AES=y CONFIG_CPUFREQ_DT=y CONFIG_KEYSTONE_IRQ=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=m CONFIG_CRYPTO_DEV_SUN4I_SS=m CONFIG_CRYPTO_DEV_ROCKCHIP=m CONFIG_ARM_CRYPTO=y -- GitLab From 23d2af622de748bf57d31a4125d06d183c29e908 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Tue, 29 Mar 2016 10:02:28 +0200 Subject: [PATCH 2786/9938] ARM: mvebu_v5_defconfig: Switching to the new Marvell's cryptographic engine driver This enables the new driver for Marvell CESA crypto engines on all mvebu v5. The old driver is no longer used, but it is still in the tree for fallback. Signed-off-by: Romain Perier Signed-off-by: Gregory CLEMENT --- arch/arm/configs/mvebu_v5_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/mvebu_v5_defconfig b/arch/arm/configs/mvebu_v5_defconfig index 4562006aae68..6051c51ca188 100644 --- a/arch/arm/configs/mvebu_v5_defconfig +++ b/arch/arm/configs/mvebu_v5_defconfig @@ -208,8 +208,8 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_PREEMPT is not set # CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=y CONFIG_CRYPTO_CBC=m CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_DEV_MV_CESA=y CONFIG_CRC_CCITT=y CONFIG_LIBCRC32C=y -- GitLab From 395c755fb874e8af1d3f5eff69a954093002c9d8 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:43 +0200 Subject: [PATCH 2787/9938] ARM: dts: kirkwood: Remove button address and fixup names The DT compiler is now warning about unit names with addresses but not reg property. Fix all the gpio-key buttons which causes warnings. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts | 4 ++-- arch/arm/boot/dts/kirkwood-cloudbox.dts | 2 +- arch/arm/boot/dts/kirkwood-dnskw.dtsi | 6 +++--- arch/arm/boot/dts/kirkwood-ib62x0.dts | 4 ++-- arch/arm/boot/dts/kirkwood-iconnect.dts | 4 ++-- arch/arm/boot/dts/kirkwood-laplug.dts | 2 +- arch/arm/boot/dts/kirkwood-lsxl.dtsi | 6 +++--- arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts | 4 ++-- arch/arm/boot/dts/kirkwood-netxbig.dtsi | 8 ++++---- arch/arm/boot/dts/kirkwood-ns2-common.dtsi | 2 +- arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi | 6 +++--- arch/arm/boot/dts/kirkwood-openblocks_a6.dts | 2 +- arch/arm/boot/dts/kirkwood-openblocks_a7.dts | 2 +- arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts | 2 +- arch/arm/boot/dts/kirkwood-t5325.dts | 2 +- arch/arm/boot/dts/kirkwood-ts219-6281.dts | 4 ++-- arch/arm/boot/dts/kirkwood-ts219-6282.dts | 4 ++-- arch/arm/boot/dts/kirkwood-ts419.dtsi | 4 ++-- 18 files changed, 34 insertions(+), 34 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts b/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts index fa02a9aff05e..f16a73e49a88 100644 --- a/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts +++ b/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts @@ -36,13 +36,13 @@ gpio_keys { compatible = "gpio-keys"; - button@1{ + reset { label = "Reset"; linux,code = ; gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; }; - button@2{ + button { label = "Power"; linux,code = ; gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-cloudbox.dts b/arch/arm/boot/dts/kirkwood-cloudbox.dts index 7ec76566acf2..555b7e4c58a5 100644 --- a/arch/arm/boot/dts/kirkwood-cloudbox.dts +++ b/arch/arm/boot/dts/kirkwood-cloudbox.dts @@ -60,7 +60,7 @@ #address-cells = <1>; #size-cells = <0>; - button@1 { + power { label = "Power push button"; linux,code = ; gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi index 113dcf056dcf..d8fca9db46d0 100644 --- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi +++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi @@ -13,17 +13,17 @@ &pmx_button_reset>; pinctrl-names = "default"; - button@1 { + power { label = "Power button"; linux,code = ; gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; }; - button@2 { + eject { label = "USB unmount button"; linux,code = ; gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; }; - button@3 { + reset { label = "Reset button"; linux,code = ; gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/kirkwood-ib62x0.dts index bfa5edde179c..ef84d8699a76 100644 --- a/arch/arm/boot/dts/kirkwood-ib62x0.dts +++ b/arch/arm/boot/dts/kirkwood-ib62x0.dts @@ -62,12 +62,12 @@ pinctrl-0 = <&pmx_button_reset &pmx_button_usb_copy>; pinctrl-names = "default"; - button@1 { + copy { label = "USB Copy"; linux,code = ; gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; }; - button@2 { + reset { label = "Reset"; linux,code = ; gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts index 38e31d15a62d..674306746dec 100644 --- a/arch/arm/boot/dts/kirkwood-iconnect.dts +++ b/arch/arm/boot/dts/kirkwood-iconnect.dts @@ -136,13 +136,13 @@ pinctrl-0 = < &pmx_button_reset &pmx_button_otb >; pinctrl-names = "default"; - button@1 { + otb { label = "OTB Button"; linux,code = ; gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; debounce-interval = <100>; }; - button@2 { + reset { label = "Reset"; linux,code = ; gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-laplug.dts b/arch/arm/boot/dts/kirkwood-laplug.dts index 24425660e973..c39e17a89f4e 100644 --- a/arch/arm/boot/dts/kirkwood-laplug.dts +++ b/arch/arm/boot/dts/kirkwood-laplug.dts @@ -62,7 +62,7 @@ gpio_keys { compatible = "gpio-keys"; - button@1{ + power { label = "Power push button"; linux,code = ; gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi index 1d6528d82969..2869c5dbc1ad 100644 --- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi +++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi @@ -107,18 +107,18 @@ &pmx_power_auto_switch>; pinctrl-names = "default"; - button@1 { + option { label = "Function Button"; linux,code = ; gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; }; - button@2 { + reserved { label = "Power-on Switch"; linux,code = ; linux,input-type = <5>; gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; }; - button@3 { + power { label = "Power-auto Switch"; linux,code = ; linux,input-type = <5>; diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts index b7e7d78c484e..6a8f59acb539 100644 --- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts +++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts @@ -109,12 +109,12 @@ pinctrl-0 = <&pmx_keys>; pinctrl-names = "default"; - button@1 { + restart { label = "SWR Button"; linux,code = ; gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; }; - button@2 { + wps { label = "WPS Button"; linux,code = ; gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-netxbig.dtsi b/arch/arm/boot/dts/kirkwood-netxbig.dtsi index 62515a8b99b9..52b58fe0c4fe 100644 --- a/arch/arm/boot/dts/kirkwood-netxbig.dtsi +++ b/arch/arm/boot/dts/kirkwood-netxbig.dtsi @@ -59,22 +59,22 @@ #size-cells = <0>; /* - * button@1 and button@2 represent a three position rocker + * esc and power represent a three position rocker * switch. Thus the conventional KEY_POWER does not fit */ - button@1 { + exc { label = "Back power switch (on|auto)"; linux,code = ; linux,input-type = <5>; gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; }; - button@2 { + power { label = "Back power switch (auto|off)"; linux,code = ; linux,input-type = <5>; gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; }; - button@3 { + option { label = "Function button"; linux,code = ; gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi index e832b6320264..b4d59261eddc 100644 --- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi @@ -57,7 +57,7 @@ #address-cells = <1>; #size-cells = <0>; - button@1 { + power { label = "Power push button"; linux,code = ; gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi b/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi index 2075a2e828f1..5ccc46190079 100644 --- a/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi @@ -77,17 +77,17 @@ pinctrl-0 = <&pmx_btn_reset &pmx_btn_copy &pmx_btn_power>; pinctrl-names = "default"; - button@1 { + power { label = "Power Button"; linux,code = ; gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; }; - button@2 { + copy { label = "Copy Button"; linux,code = ; gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; }; - button@3 { + reset { label = "Reset Button"; linux,code = ; gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts index fb9dc227255d..0db0e3edc88f 100644 --- a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts +++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts @@ -117,7 +117,7 @@ #address-cells = <1>; #size-cells = <0>; - button@1 { + power { label = "Init Button"; linux,code = ; gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts index d5e3bc518968..cf2f5240e176 100644 --- a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts +++ b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts @@ -135,7 +135,7 @@ #address-cells = <1>; #size-cells = <0>; - button@1 { + button { label = "Init Button"; linux,code = ; gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts b/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts index 8082d64266a3..b2f26239d298 100644 --- a/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts +++ b/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts @@ -33,7 +33,7 @@ pinctrl-0 = <&pmx_button_eject>; pinctrl-names = "default"; - button@1 { + eject { debounce_interval = <50>; wakeup-source; linux,code = ; diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/kirkwood-t5325.dts index ed956b849a71..af5ce85b2c38 100644 --- a/arch/arm/boot/dts/kirkwood-t5325.dts +++ b/arch/arm/boot/dts/kirkwood-t5325.dts @@ -173,7 +173,7 @@ pinctrl-0 = <&pmx_button_power>; pinctrl-names = "default"; - button@1 { + power { label = "Power Button"; linux,code = ; gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/kirkwood-ts219-6281.dts b/arch/arm/boot/dts/kirkwood-ts219-6281.dts index 9767d73f3857..ee62204e4ecd 100644 --- a/arch/arm/boot/dts/kirkwood-ts219-6281.dts +++ b/arch/arm/boot/dts/kirkwood-ts219-6281.dts @@ -39,12 +39,12 @@ pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>; pinctrl-names = "default"; - button@1 { + copy { label = "USB Copy"; linux,code = ; gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; }; - button@2 { + reset { label = "Reset"; linux,code = ; gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/kirkwood-ts219-6282.dts index bfc1a32d4e42..1d291f620869 100644 --- a/arch/arm/boot/dts/kirkwood-ts219-6282.dts +++ b/arch/arm/boot/dts/kirkwood-ts219-6282.dts @@ -49,12 +49,12 @@ pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>; pinctrl-names = "default"; - button@1 { + copy { label = "USB Copy"; linux,code = ; gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; }; - button@2 { + reset { label = "Reset"; linux,code = ; gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/kirkwood-ts419.dtsi b/arch/arm/boot/dts/kirkwood-ts419.dtsi index 30ab93bfb1e4..02bd53762705 100644 --- a/arch/arm/boot/dts/kirkwood-ts419.dtsi +++ b/arch/arm/boot/dts/kirkwood-ts419.dtsi @@ -45,12 +45,12 @@ pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>; pinctrl-names = "default"; - button@1 { + copy { label = "USB Copy"; linux,code = ; gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; }; - button@2 { + reset { label = "Reset"; linux,code = ; gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; -- GitLab From dab08333993942090b2f0190a83d2de557db2e6c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:44 +0200 Subject: [PATCH 2788/9938] ARM: dts: kirkwood: Remove node address from leds leds don't have a reg property, so remove the address from the unit name. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-lsxl.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi index 2869c5dbc1ad..8b7c6ce79a41 100644 --- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi +++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi @@ -133,28 +133,28 @@ &pmx_led_function_blue>; pinctrl-names = "default"; - led@1 { + func_blue { label = "lsxl:blue:func"; gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; }; - led@2 { + alarm { label = "lsxl:red:alarm"; gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; }; - led@3 { + info { label = "lsxl:amber:info"; gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; }; - led@4 { + power { label = "lsxl:blue:power"; gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; default-state = "keep"; }; - led@5 { + func_red { label = "lsxl:red:func"; gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; }; -- GitLab From 689168aae9de15706bb9f6fea87dbeaab30f162e Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:45 +0200 Subject: [PATCH 2789/9938] ARM: dts: kirkwood: Remove address from dsa unit name The dsa node does not have a reg property, so remove the address from the unit name. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-dir665.dts | 2 +- arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts | 2 +- arch/arm/boot/dts/kirkwood-rd88f6281-a.dts | 2 +- arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts | 2 +- arch/arm/boot/dts/kirkwood-rd88f6281.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-dir665.dts b/arch/arm/boot/dts/kirkwood-dir665.dts index 0473fcc260f7..f548363060ea 100644 --- a/arch/arm/boot/dts/kirkwood-dir665.dts +++ b/arch/arm/boot/dts/kirkwood-dir665.dts @@ -203,7 +203,7 @@ }; }; - dsa@0 { + dsa { compatible = "marvell,dsa"; #address-cells = <2>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts index 6a8f59acb539..26fb610b2af7 100644 --- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts +++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts @@ -121,7 +121,7 @@ }; }; - dsa@0 { + dsa { compatible = "marvell,dsa"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts b/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts index f2e08b3b33ea..6f771a99cb02 100644 --- a/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts +++ b/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts @@ -19,7 +19,7 @@ model = "Marvell RD88f6281 Reference design, with A0 or higher SoC"; compatible = "marvell,rd88f6281-a", "marvell,rd88f6281","marvell,kirkwood-88f6281", "marvell,kirkwood"; - dsa@0 { + dsa { switch@0 { reg = <10 0>; /* MDIO address 10, switch 0 in tree */ }; diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts b/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts index f4272b64ed7f..1a797381d3d4 100644 --- a/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts +++ b/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts @@ -19,7 +19,7 @@ model = "Marvell RD88f6281 Reference design, with Z0 SoC"; compatible = "marvell,rd88f6281-z0", "marvell,rd88f6281","marvell,kirkwood-88f6281", "marvell,kirkwood"; - dsa@0 { + dsa { switch@0 { reg = <0 0>; /* MDIO address 0, switch 0 in tree */ port@4 { diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi index d195e884b3b5..5521426d101b 100644 --- a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi +++ b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi @@ -63,7 +63,7 @@ }; }; - dsa@0 { + dsa { compatible = "marvell,dsa"; #address-cells = <2>; #size-cells = <0>; -- GitLab From 8b1750de6a6a73f5d8796894c8d1858a97f0c77c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:46 +0200 Subject: [PATCH 2790/9938] ARM: dts: kirkwood: Add address to ethernet-phy unit name PHYs have an address on the mdio bus. So the unit name should contain an address. This is complicated in that some .dtsi files contain the node, but the reg is set in the .dts file. In this case, use the abstract address X. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-ns2-common.dtsi | 2 +- arch/arm/boot/dts/kirkwood-t5325.dts | 2 +- arch/arm/boot/dts/kirkwood-ts219.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi index b4d59261eddc..282605f4c92c 100644 --- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi @@ -83,7 +83,7 @@ &mdio { status = "okay"; - ethphy0: ethernet-phy { + ethphy0: ethernet-phy@X { /* overwrite reg property in board file */ }; }; diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/kirkwood-t5325.dts index af5ce85b2c38..860c6d778d47 100644 --- a/arch/arm/boot/dts/kirkwood-t5325.dts +++ b/arch/arm/boot/dts/kirkwood-t5325.dts @@ -217,7 +217,7 @@ &mdio { status = "okay"; - ethphy0: ethernet-phy { + ethphy0: ethernet-phy@8 { device_type = "ethernet-phy"; reg = <8>; }; diff --git a/arch/arm/boot/dts/kirkwood-ts219.dtsi b/arch/arm/boot/dts/kirkwood-ts219.dtsi index 0e46560551f4..b3f75382cb06 100644 --- a/arch/arm/boot/dts/kirkwood-ts219.dtsi +++ b/arch/arm/boot/dts/kirkwood-ts219.dtsi @@ -94,7 +94,7 @@ &mdio { status = "okay"; - ethphy0: ethernet-phy { + ethphy0: ethernet-phy@X { /* overwrite reg property in board file */ }; }; -- GitLab From eb13cf8345e94a02e9872ca3e909596a5ddb5f90 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:47 +0200 Subject: [PATCH 2791/9938] ARM: dts: kirkwood: Fixup pcie DT warnings PCIe has a range property, so the unit name should contain an address. Make use of the label to enable individual PCIe busses. Also, fixup the synology dtsi file which added a label pcie2 rather than using the existing pcie1 label. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-6192.dtsi | 2 +- arch/arm/boot/dts/kirkwood-6281.dtsi | 2 +- arch/arm/boot/dts/kirkwood-6282.dtsi | 2 +- arch/arm/boot/dts/kirkwood-98dx4122.dtsi | 2 +- arch/arm/boot/dts/kirkwood-b3.dts | 19 +++++++--------- arch/arm/boot/dts/kirkwood-db-88f6281.dts | 14 +++++------- arch/arm/boot/dts/kirkwood-db-88f6282.dts | 20 ++++++++--------- arch/arm/boot/dts/kirkwood-dir665.dts | 18 +++++++-------- arch/arm/boot/dts/kirkwood-ds111.dts | 2 +- arch/arm/boot/dts/kirkwood-ds112.dts | 6 ++++- arch/arm/boot/dts/kirkwood-ds212.dts | 2 +- arch/arm/boot/dts/kirkwood-ds411.dts | 6 ++++- arch/arm/boot/dts/kirkwood-ds411slim.dts | 2 +- arch/arm/boot/dts/kirkwood-iconnect.dts | 18 +++++++-------- arch/arm/boot/dts/kirkwood-km_common.dtsi | 18 +++++++-------- arch/arm/boot/dts/kirkwood-laplug.dts | 17 +++++++------- arch/arm/boot/dts/kirkwood-linkstation.dtsi | 17 +++++++------- arch/arm/boot/dts/kirkwood-mplcec4.dts | 18 +++++++-------- .../arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts | 18 +++++++-------- arch/arm/boot/dts/kirkwood-nas2big.dts | 18 +++++++-------- .../dts/kirkwood-netgear_readynas_duo_v2.dts | 18 +++++++-------- .../dts/kirkwood-netgear_readynas_nv+_v2.dts | 21 ++++++++---------- arch/arm/boot/dts/kirkwood-nsa310.dts | 18 +++++++-------- arch/arm/boot/dts/kirkwood-nsa320.dts | 18 +++++++-------- arch/arm/boot/dts/kirkwood-nsa325.dts | 17 ++++++-------- arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi | 18 +++++++-------- arch/arm/boot/dts/kirkwood-openrd.dtsi | 14 ++++-------- arch/arm/boot/dts/kirkwood-rd88f6192.dts | 20 ++++++++--------- arch/arm/boot/dts/kirkwood-rd88f6281.dtsi | 18 +++++++-------- arch/arm/boot/dts/kirkwood-rs212.dts | 6 ++++- arch/arm/boot/dts/kirkwood-synology.dtsi | 22 +++++++------------ arch/arm/boot/dts/kirkwood-t5325.dts | 18 +++++++-------- arch/arm/boot/dts/kirkwood-ts219-6282.dts | 12 ++-------- arch/arm/boot/dts/kirkwood-ts219.dtsi | 18 +++++++-------- arch/arm/boot/dts/kirkwood-ts419-6282.dts | 15 +++---------- 35 files changed, 207 insertions(+), 267 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-6192.dtsi b/arch/arm/boot/dts/kirkwood-6192.dtsi index 9e6e9e2691d5..1014a5dd9035 100644 --- a/arch/arm/boot/dts/kirkwood-6192.dtsi +++ b/arch/arm/boot/dts/kirkwood-6192.dtsi @@ -1,6 +1,6 @@ / { mbus { - pciec: pcie-controller { + pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; device_type = "pci"; diff --git a/arch/arm/boot/dts/kirkwood-6281.dtsi b/arch/arm/boot/dts/kirkwood-6281.dtsi index 7dc7d6782e83..fad201551304 100644 --- a/arch/arm/boot/dts/kirkwood-6281.dtsi +++ b/arch/arm/boot/dts/kirkwood-6281.dtsi @@ -1,6 +1,6 @@ / { mbus { - pciec: pcie-controller { + pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; device_type = "pci"; diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi index 4680eec990f0..27434c35eb66 100644 --- a/arch/arm/boot/dts/kirkwood-6282.dtsi +++ b/arch/arm/boot/dts/kirkwood-6282.dtsi @@ -1,6 +1,6 @@ / { mbus { - pciec: pcie-controller { + pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; device_type = "pci"; diff --git a/arch/arm/boot/dts/kirkwood-98dx4122.dtsi b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi index 9e1f741d74ff..17eb92733310 100644 --- a/arch/arm/boot/dts/kirkwood-98dx4122.dtsi +++ b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi @@ -1,6 +1,6 @@ / { mbus { - pciec: pcie-controller { + pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; device_type = "pci"; diff --git a/arch/arm/boot/dts/kirkwood-b3.dts b/arch/arm/boot/dts/kirkwood-b3.dts index d2936ad3af1d..d091ecb61cd2 100644 --- a/arch/arm/boot/dts/kirkwood-b3.dts +++ b/arch/arm/boot/dts/kirkwood-b3.dts @@ -33,17 +33,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - /* Wifi model has Atheros chipset on pcie port */ - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pmx_button_power: pmx-button-power { @@ -199,3 +188,11 @@ }; }; +/* Wifi model has Atheros chipset on pcie port */ +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-db-88f6281.dts b/arch/arm/boot/dts/kirkwood-db-88f6281.dts index c39dd766c75a..aee6f02b1c80 100644 --- a/arch/arm/boot/dts/kirkwood-db-88f6281.dts +++ b/arch/arm/boot/dts/kirkwood-db-88f6281.dts @@ -17,14 +17,12 @@ / { model = "Marvell DB-88F6281-BP Development Board"; compatible = "marvell,db-88f6281-bp", "marvell,kirkwood-88f6281", "marvell,kirkwood"; +}; - mbus { - pcie-controller { - status = "okay"; +&pciec { + status = "okay"; +}; - pcie@1,0 { - status = "okay"; - }; - }; - }; +&pcie0 { + status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-db-88f6282.dts b/arch/arm/boot/dts/kirkwood-db-88f6282.dts index 701c6b6cdaa2..e8b23e13ec0c 100644 --- a/arch/arm/boot/dts/kirkwood-db-88f6282.dts +++ b/arch/arm/boot/dts/kirkwood-db-88f6282.dts @@ -17,18 +17,16 @@ / { model = "Marvell DB-88F6282-BP Development Board"; compatible = "marvell,db-88f6282-bp", "marvell,kirkwood-88f6282", "marvell,kirkwood"; +}; - mbus { - pcie-controller { - status = "okay"; +&pciec { + status = "okay"; +}; - pcie@1,0 { - status = "okay"; - }; +&pcie0 { + status = "okay"; +}; - pcie@2,0 { - status = "okay"; - }; - }; - }; +&pcie1 { + status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-dir665.dts b/arch/arm/boot/dts/kirkwood-dir665.dts index f548363060ea..41acbb6dd6ab 100644 --- a/arch/arm/boot/dts/kirkwood-dir665.dts +++ b/arch/arm/boot/dts/kirkwood-dir665.dts @@ -25,16 +25,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-0 =< &pmx_led_usb @@ -276,3 +266,11 @@ &rtc { status = "disabled"; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-ds111.dts b/arch/arm/boot/dts/kirkwood-ds111.dts index 61f47fbe44d0..a85a4664431b 100644 --- a/arch/arm/boot/dts/kirkwood-ds111.dts +++ b/arch/arm/boot/dts/kirkwood-ds111.dts @@ -40,6 +40,6 @@ status = "okay"; }; -&pcie2 { +&pcie1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-ds112.dts b/arch/arm/boot/dts/kirkwood-ds112.dts index b84af3da8c84..6cef4bdbc01b 100644 --- a/arch/arm/boot/dts/kirkwood-ds112.dts +++ b/arch/arm/boot/dts/kirkwood-ds112.dts @@ -44,6 +44,10 @@ status = "okay"; }; -&pcie2 { +&pciec { + status = "okay"; +}; + +&pcie1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-ds212.dts b/arch/arm/boot/dts/kirkwood-ds212.dts index 99afd462f956..7f32e7abffac 100644 --- a/arch/arm/boot/dts/kirkwood-ds212.dts +++ b/arch/arm/boot/dts/kirkwood-ds212.dts @@ -43,6 +43,6 @@ status = "okay"; }; -&pcie2 { +&pcie1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-ds411.dts b/arch/arm/boot/dts/kirkwood-ds411.dts index 623cd4a37d71..72e58307416d 100644 --- a/arch/arm/boot/dts/kirkwood-ds411.dts +++ b/arch/arm/boot/dts/kirkwood-ds411.dts @@ -48,6 +48,10 @@ status = "okay"; }; -&pcie2 { +&pciec { + status = "okay"; +}; + +&pcie1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-ds411slim.dts b/arch/arm/boot/dts/kirkwood-ds411slim.dts index a0a1fad8b4de..aaaf31b81522 100644 --- a/arch/arm/boot/dts/kirkwood-ds411slim.dts +++ b/arch/arm/boot/dts/kirkwood-ds411slim.dts @@ -44,6 +44,6 @@ status = "okay"; }; -&pcie2 { +&pcie1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts index 674306746dec..d25184ae4af3 100644 --- a/arch/arm/boot/dts/kirkwood-iconnect.dts +++ b/arch/arm/boot/dts/kirkwood-iconnect.dts @@ -19,16 +19,6 @@ linux,initrd-end = <0x4800000>; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pmx_button_reset: pmx-button-reset { @@ -194,3 +184,11 @@ phy-handle = <ðphy0>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-km_common.dtsi b/arch/arm/boot/dts/kirkwood-km_common.dtsi index 8367c772c764..f6096f56046d 100644 --- a/arch/arm/boot/dts/kirkwood-km_common.dtsi +++ b/arch/arm/boot/dts/kirkwood-km_common.dtsi @@ -4,16 +4,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-0 = < &pmx_i2c_gpio_sda &pmx_i2c_gpio_scl >; @@ -46,3 +36,11 @@ status = "okay"; chip-delay = <25>; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-laplug.dts b/arch/arm/boot/dts/kirkwood-laplug.dts index c39e17a89f4e..1b0f070c2676 100644 --- a/arch/arm/boot/dts/kirkwood-laplug.dts +++ b/arch/arm/boot/dts/kirkwood-laplug.dts @@ -27,15 +27,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { serial@12000 { status = "okay"; @@ -169,3 +160,11 @@ phy-handle = <ðphy0>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-linkstation.dtsi b/arch/arm/boot/dts/kirkwood-linkstation.dtsi index 69061b6e987b..36c54c9dfa30 100644 --- a/arch/arm/boot/dts/kirkwood-linkstation.dtsi +++ b/arch/arm/boot/dts/kirkwood-linkstation.dtsi @@ -49,15 +49,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pmx_power_hdd0: pmx-power-hdd0 { @@ -200,3 +191,11 @@ }; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/kirkwood-mplcec4.dts index f3a991837515..aa413b0bcce2 100644 --- a/arch/arm/boot/dts/kirkwood-mplcec4.dts +++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts @@ -17,16 +17,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pmx_led_health: pmx-led-health { @@ -215,3 +205,11 @@ phy-handle = <ðphy1>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts index 26fb610b2af7..172a38c0b8a9 100644 --- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts +++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts @@ -31,16 +31,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pin-controller@10000 { pmx_usb_led: pmx-usb-led { @@ -179,3 +169,11 @@ duplex = <1>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-nas2big.dts b/arch/arm/boot/dts/kirkwood-nas2big.dts index 7427ec50b829..f53bcacf6b63 100644 --- a/arch/arm/boot/dts/kirkwood-nas2big.dts +++ b/arch/arm/boot/dts/kirkwood-nas2big.dts @@ -28,16 +28,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { rtc@10300 { /* The on-chip RTC is not powered (no supercap). */ @@ -141,3 +131,11 @@ reg = <0x9100000 0x6f00000>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts index fd733c63bc27..8745484912d2 100644 --- a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts +++ b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts @@ -28,16 +28,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pmx_button_power: pmx-button-power { @@ -251,3 +241,11 @@ phy-handle = <ðphy0>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts index b514d643fb6c..a4e97f7f5804 100644 --- a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts +++ b/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts @@ -28,18 +28,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - /* Connected to NEC uPD720200 USB 3.0 controller */ - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pmx_button_power: pmx-button-power { @@ -265,3 +253,12 @@ phy-handle = <ðphy0>; }; }; + +/* Connected to NEC uPD720200 USB 3.0 controller */ +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts index 6139df0f376c..0b69ee4934fa 100644 --- a/arch/arm/boot/dts/kirkwood-nsa310.dts +++ b/arch/arm/boot/dts/kirkwood-nsa310.dts @@ -15,16 +15,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-0 = <&pmx_unknown>; @@ -138,3 +128,11 @@ }; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-nsa320.dts b/arch/arm/boot/dts/kirkwood-nsa320.dts index 2a935e94f96f..6ab104b4bb42 100644 --- a/arch/arm/boot/dts/kirkwood-nsa320.dts +++ b/arch/arm/boot/dts/kirkwood-nsa320.dts @@ -27,16 +27,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-names = "default"; @@ -222,3 +212,11 @@ phy-handle = <ðphy0>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-nsa325.dts b/arch/arm/boot/dts/kirkwood-nsa325.dts index bc4ec9332387..36c64816bf7f 100644 --- a/arch/arm/boot/dts/kirkwood-nsa325.dts +++ b/arch/arm/boot/dts/kirkwood-nsa325.dts @@ -28,16 +28,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-names = "default"; @@ -236,3 +226,10 @@ }; }; +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi b/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi index 5ccc46190079..e09b79ac73fd 100644 --- a/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi @@ -4,16 +4,6 @@ / { model = "ZyXEL NSA310"; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { @@ -157,3 +147,11 @@ reg = <0x5040000 0x2fc0000>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-openrd.dtsi b/arch/arm/boot/dts/kirkwood-openrd.dtsi index 24f1d30970a0..e4ecab112601 100644 --- a/arch/arm/boot/dts/kirkwood-openrd.dtsi +++ b/arch/arm/boot/dts/kirkwood-openrd.dtsi @@ -25,16 +25,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-0 = <&pmx_select28 &pmx_sdio_cd &pmx_select34>; @@ -125,3 +115,7 @@ reg = <0x0600000 0x1FA00000>; }; }; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-rd88f6192.dts b/arch/arm/boot/dts/kirkwood-rd88f6192.dts index e0b959396ca2..b8af907249fb 100644 --- a/arch/arm/boot/dts/kirkwood-rd88f6192.dts +++ b/arch/arm/boot/dts/kirkwood-rd88f6192.dts @@ -29,16 +29,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-0 = <&pmx_usb_power>; @@ -108,4 +98,12 @@ ethernet0-port@0 { phy-handle = <ðphy0>; }; -}; \ No newline at end of file +}; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi index 5521426d101b..d5aacf137e40 100644 --- a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi +++ b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi @@ -25,16 +25,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-names = "default"; @@ -134,3 +124,11 @@ duplex = <1>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-rs212.dts b/arch/arm/boot/dts/kirkwood-rs212.dts index 3b19f1fd4cac..2c722ecd5331 100644 --- a/arch/arm/boot/dts/kirkwood-rs212.dts +++ b/arch/arm/boot/dts/kirkwood-rs212.dts @@ -44,6 +44,10 @@ status = "okay"; }; -&pcie2 { +&pciec { + status = "okay"; +}; + +&pcie1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-synology.dtsi b/arch/arm/boot/dts/kirkwood-synology.dtsi index 04015c174b99..65e9524e852a 100644 --- a/arch/arm/boot/dts/kirkwood-synology.dtsi +++ b/arch/arm/boot/dts/kirkwood-synology.dtsi @@ -10,20 +10,6 @@ */ / { - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - - pcie2: pcie@2,0 { - status = "disabled"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pmx_alarmled_12: pmx-alarmled-12 { @@ -861,3 +847,11 @@ phy-handle = <ðphy1>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/kirkwood-t5325.dts index 860c6d778d47..3500f4738fb0 100644 --- a/arch/arm/boot/dts/kirkwood-t5325.dts +++ b/arch/arm/boot/dts/kirkwood-t5325.dts @@ -30,16 +30,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { pinctrl-0 = <&pmx_i2s &pmx_sysrst>; @@ -229,3 +219,11 @@ phy-handle = <ðphy0>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/kirkwood-ts219-6282.dts index 1d291f620869..3437bb396844 100644 --- a/arch/arm/boot/dts/kirkwood-ts219-6282.dts +++ b/arch/arm/boot/dts/kirkwood-ts219-6282.dts @@ -5,16 +5,6 @@ #include "kirkwood-ts219.dtsi" / { - mbus { - pcie-controller { - status = "okay"; - - pcie@2,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { pinctrl: pin-controller@10000 { @@ -63,3 +53,5 @@ }; ðphy0 { reg = <0>; }; + +&pcie1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-ts219.dtsi b/arch/arm/boot/dts/kirkwood-ts219.dtsi index b3f75382cb06..62e5e2d5c348 100644 --- a/arch/arm/boot/dts/kirkwood-ts219.dtsi +++ b/arch/arm/boot/dts/kirkwood-ts219.dtsi @@ -12,16 +12,6 @@ stdout-path = &uart0; }; - mbus { - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; - }; - ocp@f1000000 { i2c@11000 { status = "okay"; @@ -105,3 +95,11 @@ phy-handle = <ðphy0>; }; }; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-ts419-6282.dts b/arch/arm/boot/dts/kirkwood-ts419-6282.dts index d7512d4cdced..e3e71f48acc8 100644 --- a/arch/arm/boot/dts/kirkwood-ts419-6282.dts +++ b/arch/arm/boot/dts/kirkwood-ts419-6282.dts @@ -16,17 +16,8 @@ #include "kirkwood-ts219.dtsi" #include "kirkwood-ts419.dtsi" -/ { - mbus { - pcie-controller { - status = "okay"; - - pcie@2,0 { - status = "okay"; - }; - }; - }; -}; - ðphy0 { reg = <0>; }; ðphy1 { reg = <1>; }; + +&pciec { status = "okay"; }; +&pcie1 { status = "okay"; }; -- GitLab From 57910a3e0e4641255624d5e75839ea00a0f2bd96 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:48 +0200 Subject: [PATCH 2792/9938] ARM: dts: kirkwood: Remove address from gpio-i2c unit name gpio-i2c does not have a reg property, just a list of gpios. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-km_common.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/kirkwood-km_common.dtsi b/arch/arm/boot/dts/kirkwood-km_common.dtsi index f6096f56046d..7962bdefde49 100644 --- a/arch/arm/boot/dts/kirkwood-km_common.dtsi +++ b/arch/arm/boot/dts/kirkwood-km_common.dtsi @@ -24,7 +24,7 @@ }; }; - i2c@0 { + i2c { compatible = "i2c-gpio"; gpios = < &gpio0 8 GPIO_ACTIVE_HIGH /* sda */ &gpio0 9 GPIO_ACTIVE_HIGH>; /* scl */ -- GitLab From 5d7fd6563348252871db218be438fad05ae3ef7c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:49 +0200 Subject: [PATCH 2793/9938] ARM: dts: kirkwood: Add address to mbus unit name The mbus node has a ranges property. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-6192.dtsi | 2 +- arch/arm/boot/dts/kirkwood-6281.dtsi | 2 +- arch/arm/boot/dts/kirkwood-6282.dtsi | 2 +- arch/arm/boot/dts/kirkwood-98dx4122.dtsi | 2 +- arch/arm/boot/dts/kirkwood.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-6192.dtsi b/arch/arm/boot/dts/kirkwood-6192.dtsi index 1014a5dd9035..d573e03f3134 100644 --- a/arch/arm/boot/dts/kirkwood-6192.dtsi +++ b/arch/arm/boot/dts/kirkwood-6192.dtsi @@ -1,5 +1,5 @@ / { - mbus { + mbus@f1000000 { pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; diff --git a/arch/arm/boot/dts/kirkwood-6281.dtsi b/arch/arm/boot/dts/kirkwood-6281.dtsi index fad201551304..748d0b62f233 100644 --- a/arch/arm/boot/dts/kirkwood-6281.dtsi +++ b/arch/arm/boot/dts/kirkwood-6281.dtsi @@ -1,5 +1,5 @@ / { - mbus { + mbus@f1000000 { pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi index 27434c35eb66..bb63d2d50fc5 100644 --- a/arch/arm/boot/dts/kirkwood-6282.dtsi +++ b/arch/arm/boot/dts/kirkwood-6282.dtsi @@ -1,5 +1,5 @@ / { - mbus { + mbus@f1000000 { pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; diff --git a/arch/arm/boot/dts/kirkwood-98dx4122.dtsi b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi index 17eb92733310..720c210d491d 100644 --- a/arch/arm/boot/dts/kirkwood-98dx4122.dtsi +++ b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi @@ -1,5 +1,5 @@ / { - mbus { + mbus@f1000000 { pciec: pcie-controller@82000000 { compatible = "marvell,kirkwood-pcie"; status = "disabled"; diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi index 7445a15e259d..29b8bd7e0d93 100644 --- a/arch/arm/boot/dts/kirkwood.dtsi +++ b/arch/arm/boot/dts/kirkwood.dtsi @@ -27,7 +27,7 @@ i2c0 = &i2c0; }; - mbus { + mbus@f1000000 { compatible = "marvell,kirkwood-mbus", "simple-bus"; #address-cells = <2>; #size-cells = <1>; -- GitLab From 49ad48c83a016850c754192d2b520e782e91ea20 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Apr 2016 04:03:50 +0200 Subject: [PATCH 2794/9938] ARM: dts: kirkwood: Add address go regulator unit name The regulator has a reg property so include it in the unit name. Signed-off-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts | 2 +- arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts index 8745484912d2..c0413b63cf2e 100644 --- a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts +++ b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts @@ -183,7 +183,7 @@ #address-cells = <1>; #size-cells = <0>; - usb3_regulator: usb3-regulator { + usb3_regulator: usb3-regulator@1 { compatible = "regulator-fixed"; reg = <1>; regulator-name = "USB 3.0 Power"; diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts index a4e97f7f5804..2bfc6cfa151d 100644 --- a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts +++ b/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts @@ -193,7 +193,7 @@ #address-cells = <1>; #size-cells = <0>; - usb3_regulator: usb3-regulator { + usb3_regulator: usb3-regulator@1 { compatible = "regulator-fixed"; reg = <1>; regulator-name = "USB 3.0 Power"; -- GitLab From 864140d981b589c125eebcca3b11d4a7a3d232e6 Mon Sep 17 00:00:00 2001 From: Roger Shimizu Date: Wed, 30 Mar 2016 01:11:45 +0900 Subject: [PATCH 2795/9938] ARM: dts: orion5x: add device tree for kurobox-pro Add dts file to support Buffalo/Revogear Kurobox-Pro, which is marvell orion5x based 3.5" HDD NAS. It's a quite old product and already discontinued. So there's no official website for it. But it was an early product which used marvell orion5x 88F5182 chipset, it's popular in the community. Some unofficial site: - http://buffalo.nas-central.org/wiki/Category:KuroboxPro - http://nice.kaze.com/KUROPRO_ProductSpecifications.pdf This device tree is based on the board file: arch/arm/mach-orion5x/kurobox_pro-setup.c However, the probing order of NAND and JEDEC-Flash are different from the original board file, this results in incompatible minor number for a few /dev/mtdX and /dev/mtdblockX devices. So I still want to keep the board file for the time being. Signed-off-by: Roger Shimizu Reviewed-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/orion5x-kuroboxpro.dts | 127 +++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 arch/arm/boot/dts/orion5x-kuroboxpro.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index e9083a95a7cc..8ec28748a9ba 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -531,6 +531,7 @@ dtb-$(CONFIG_SOC_DRA7XX) += \ dra7-evm.dtb \ dra72-evm.dtb dtb-$(CONFIG_ARCH_ORION5X) += \ + orion5x-kuroboxpro.dtb \ orion5x-lacie-d2-network.dtb \ orion5x-lacie-ethernet-disk-mini-v2.dtb \ orion5x-linkstation-lsgl.dtb \ diff --git a/arch/arm/boot/dts/orion5x-kuroboxpro.dts b/arch/arm/boot/dts/orion5x-kuroboxpro.dts new file mode 100644 index 000000000000..1a672b098d0b --- /dev/null +++ b/arch/arm/boot/dts/orion5x-kuroboxpro.dts @@ -0,0 +1,127 @@ +/* + * Device Tree file for Buffalo/Revogear Kurobox Pro + * + * Copyright (C) 2016 + * Roger Shimizu + * + * Based on the board file arch/arm/mach-orion5x/kurobox_pro-setup.c + * Copyright (C) Ronen Shitrit + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "orion5x-linkstation.dtsi" +#include + +/ { + model = "Buffalo/Revogear Kurobox Pro"; + compatible = "buffalo,kurobox-pro", "marvell,orion5x-88f5182", "marvell,orion5x"; + + soc { + ranges = , + , + , + ; + }; + + memory { /* 128 MB */ + device_type = "memory"; + reg = <0x00000000 0x8000000>; + }; +}; + +&pinctrl { + pmx_power_hdd: pmx-power-hdd { + marvell,pins = "mpp1"; + marvell,function = "gpio"; + }; + + pmx_power_usb: pmx-power-usb { + marvell,pins = "mpp9"; + marvell,function = "gpio"; + }; +}; + +&devbus_cs0 { + status = "okay"; + compatible = "marvell,orion-nand"; + reg = ; + cle = <0>; + ale = <1>; + bank-width = <1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + uImage@0 { /* 4 MB */ + reg = <0 0x400000>; + read-only; + }; + + rootfs@400000 { /* 64 MB */ + reg = <0x400000 0x4000000>; + read-only; + }; + + extra@4400000 { /* 188 MB */ + reg = <0x4400000 0xBC00000>; + read-only; + }; + }; +}; + +&hdd_power { + gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; +}; + +&usb_power { + gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; +}; + +&sata { + nr-ports = <2>; +}; + +&ehci1 { + status = "okay"; +}; -- GitLab From c134043ed396b06addf5866d977fed7ba6a393a9 Mon Sep 17 00:00:00 2001 From: Bert Vermeulen Date: Mon, 4 Apr 2016 16:46:07 +0200 Subject: [PATCH 2796/9938] ARM: dts: kirkwood: Add DTS for Linksys EA4200v2/EA4500 This platform is based on a Marvell 88E6282 SoC and 88E6171 switch. [gregory.clement@free-electrons.com: fix block comment style] Signed-off-by: Bert Vermeulen Reviewed-by: Andrew Lunn Reviewed-by: Imre Kaloz Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/kirkwood-linksys-viper.dts | 240 +++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 arch/arm/boot/dts/kirkwood-linksys-viper.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 8ec28748a9ba..a8dbf0228bf8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -200,6 +200,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \ kirkwood-linkstation-lswsxl.dtb \ kirkwood-linkstation-lswvl.dtb \ kirkwood-linkstation-lswxl.dtb \ + kirkwood-linksys-viper.dtb \ kirkwood-lschlv2.dtb \ kirkwood-lsxhl.dtb \ kirkwood-mplcec4.dtb \ diff --git a/arch/arm/boot/dts/kirkwood-linksys-viper.dts b/arch/arm/boot/dts/kirkwood-linksys-viper.dts new file mode 100644 index 000000000000..345fcac48dc7 --- /dev/null +++ b/arch/arm/boot/dts/kirkwood-linksys-viper.dts @@ -0,0 +1,240 @@ +/* + * kirkwood-viper.dts - Device Tree file for Linksys viper (E4200v2 / EA4500) + * + * (c) 2013 Jonas Gorski + * (c) 2013 Deutsche Telekom Innovation Laboratories + * (c) 2014 Luka Perkov + * (c) 2014 Randy C. Will + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/dts-v1/; + +#include "kirkwood.dtsi" +#include "kirkwood-6282.dtsi" + +/ { + model = "Linksys Viper (E4200v2 / EA4500)"; + compatible = "linksys,viper", "marvell,kirkwood-88f6282", "marvell,kirkwood"; + + memory { + device_type = "memory"; + reg = <0x00000000 0x8000000>; + }; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = < &pmx_btn_wps &pmx_btn_reset >; + pinctrl-names = "default"; + + wps { + label = "WPS Button"; + linux,code = ; + gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "Reset Button"; + linux,code = ; + gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = < &pmx_led_white_health &pmx_led_white_pulse >; + pinctrl-names = "default"; + + white-health { + label = "viper:white:health"; + gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + }; + + white-pulse { + label = "viper:white:pulse"; + gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + }; + }; + + dsa { + compatible = "marvell,dsa"; + #address-cells = <2>; + #size-cells = <0>; + + dsa,ethernet = <ð0port>; + dsa,mii-bus = <&mdio>; + + switch@16,0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <16 0>; /* MDIO address 16, switch 0 in tree */ + + port@0 { + reg = <0>; + label = "ethernet1"; + }; + + port@1 { + reg = <1>; + label = "ethernet2"; + }; + + port@2 { + reg = <2>; + label = "ethernet3"; + }; + + port@3 { + reg = <3>; + label = "ethernet4"; + }; + + port@4 { + reg = <4>; + label = "internet"; + }; + + port@5 { + reg = <5>; + label = "cpu"; + }; + }; + }; +}; + +&pinctrl { + pmx_led_white_health: pmx-led-white-health { + marvell,pins = "mpp7"; + marvell,function = "gpo"; + }; + pmx_led_white_pulse: pmx-led-white-pulse { + marvell,pins = "mpp14"; + marvell,function = "gpio"; + }; + pmx_btn_wps: pmx-btn-wps { + marvell,pins = "mpp47"; + marvell,function = "gpio"; + }; + pmx_btn_reset: pmx-btn-reset { + marvell,pins = "mpp48"; + marvell,function = "gpio"; + }; +}; + +&nand { + status = "okay"; + pinctrl-0 = <&pmx_nand>; + pinctrl-names = "default"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "u_env"; + reg = <0x80000 0x20000>; + }; + + partition@A0000 { + label = "s_env"; + reg = <0xA0000 0x20000>; + }; + + partition@200000 { + label = "kernel"; + reg = <0x200000 0x2A0000>; + }; + + partition@4A0000 { + label = "rootfs"; + reg = <0x4A0000 0x1760000>; + }; + + partition@1C00000 { + label = "alt_kernel"; + reg = <0x1C00000 0x2A0000>; + }; + + partition@1EA0000 { + label = "alt_rootfs"; + reg = <0x1EA0000 0x1760000>; + }; + + partition@3600000 { + label = "syscfg"; + reg = <0x3600000 0x4A00000>; + }; + + partition@C0000 { + label = "unused"; + reg = <0xC0000 0x140000>; + }; + + }; +}; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie1 { + status = "okay"; +}; + +&mdio { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +/* eth0 is connected to a Marvell 88E6171 switch, without a PHY. So set + * fixed speed and duplex. + */ +ð0 { + status = "okay"; + ethernet0-port@0 { + speed = <1000>; + duplex = <1>; + }; +}; + +/* eth1 is connected to the switch at port 6. However DSA only supports a + * single CPU port. So leave this port disabled to avoid confusion. + */ +ð1 { + status = "disabled"; +}; + +/* There is no battery on the board, so the RTC does not keep + * time when there is no power, making it useless. + */ +&rtc { + status = "disabled"; +}; + -- GitLab From 2c09ec06bc39fc85a2b3856524348c301def27af Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 17:43:06 +0200 Subject: [PATCH 2797/9938] arm64: use 'segment' rather than 'chunk' to describe mapped kernel regions Replace the poorly defined term chunk with segment, which is a term that is already used by the ELF spec to describe contiguous mappings with the same permission attributes of statically allocated ranges of an executable. Acked-by: Mark Rutland Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/mm/mmu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index f3e5c74233f3..9be2065f8ddb 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -471,8 +471,8 @@ void fixup_init(void) unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin)); } -static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end, - pgprot_t prot, struct vm_struct *vma) +static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end, + pgprot_t prot, struct vm_struct *vma) { phys_addr_t pa_start = __pa(va_start); unsigned long size = va_end - va_start; @@ -499,11 +499,11 @@ static void __init map_kernel(pgd_t *pgd) { static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data; - map_kernel_chunk(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text); - map_kernel_chunk(pgd, __start_rodata, _etext, PAGE_KERNEL, &vmlinux_rodata); - map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC, - &vmlinux_init); - map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data); + map_kernel_segment(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text); + map_kernel_segment(pgd, __start_rodata, _etext, PAGE_KERNEL, &vmlinux_rodata); + map_kernel_segment(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC, + &vmlinux_init); + map_kernel_segment(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data); if (!pgd_val(*pgd_offset_raw(pgd, FIXADDR_START))) { /* -- GitLab From 546c8c44f092b2f23291fe499c221efc8cabbb67 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 17:43:07 +0200 Subject: [PATCH 2798/9938] arm64: move early boot code to the .init segment Apart from the arm64/linux and EFI header data structures, there is nothing in the .head.text section that must reside at the beginning of the Image. So let's move it to the .init section where it belongs. Note that this involves some minor tweaking of the EFI header, primarily because the address of 'stext' no longer coincides with the start of the .text section. It also requires a couple of relocated symbol references to be slightly rewritten or their definition moved to the linker script. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/efi-entry.S | 2 +- arch/arm64/kernel/head.S | 32 +++++++++++++++----------------- arch/arm64/kernel/image.h | 4 ++++ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S index cae3112f7791..e88c064b845c 100644 --- a/arch/arm64/kernel/efi-entry.S +++ b/arch/arm64/kernel/efi-entry.S @@ -62,7 +62,7 @@ ENTRY(entry) */ mov x20, x0 // DTB address ldr x0, [sp, #16] // relocated _text address - movz x21, #:abs_g0:stext_offset + ldr w21, =stext_offset add x21, x0, x21 /* diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 4203d5f257bc..b43417618847 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -102,8 +102,6 @@ _head: #endif #ifdef CONFIG_EFI - .globl __efistub_stext_offset - .set __efistub_stext_offset, stext - _head .align 3 pe_header: .ascii "PE" @@ -123,11 +121,11 @@ optional_header: .short 0x20b // PE32+ format .byte 0x02 // MajorLinkerVersion .byte 0x14 // MinorLinkerVersion - .long _end - stext // SizeOfCode + .long _end - efi_header_end // SizeOfCode .long 0 // SizeOfInitializedData .long 0 // SizeOfUninitializedData .long __efistub_entry - _head // AddressOfEntryPoint - .long __efistub_stext_offset // BaseOfCode + .long efi_header_end - _head // BaseOfCode extra_header_fields: .quad 0 // ImageBase @@ -144,7 +142,7 @@ extra_header_fields: .long _end - _head // SizeOfImage // Everything before the kernel image is considered part of the header - .long __efistub_stext_offset // SizeOfHeaders + .long efi_header_end - _head // SizeOfHeaders .long 0 // CheckSum .short 0xa // Subsystem (EFI application) .short 0 // DllCharacteristics @@ -188,10 +186,10 @@ section_table: .byte 0 .byte 0 .byte 0 // end of 0 padding of section name - .long _end - stext // VirtualSize - .long __efistub_stext_offset // VirtualAddress - .long _edata - stext // SizeOfRawData - .long __efistub_stext_offset // PointerToRawData + .long _end - efi_header_end // VirtualSize + .long efi_header_end - _head // VirtualAddress + .long _edata - efi_header_end // SizeOfRawData + .long efi_header_end - _head // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) @@ -200,15 +198,18 @@ section_table: .long 0xe0500020 // Characteristics (section flags) /* - * EFI will load stext onwards at the 4k section alignment + * EFI will load .text onwards at the 4k section alignment * described in the PE/COFF header. To ensure that instruction * sequences using an adrp and a :lo12: immediate will function - * correctly at this alignment, we must ensure that stext is + * correctly at this alignment, we must ensure that .text is * placed at a 4k boundary in the Image to begin with. */ .align 12 +efi_header_end: #endif + __INIT + ENTRY(stext) bl preserve_boot_args bl el2_setup // Drop to EL1, w20=cpu_boot_mode @@ -223,12 +224,12 @@ ENTRY(stext) * the TCR will have been set. */ ldr x27, 0f // address to jump to after - // MMU has been enabled + neg x27, x27 // MMU has been enabled adr_l lr, __enable_mmu // return (PIC) address b __cpu_setup // initialise processor ENDPROC(stext) .align 3 -0: .quad __mmap_switched - (_head - TEXT_OFFSET) + KIMAGE_VADDR +0: .quad (_text - TEXT_OFFSET) - __mmap_switched - KIMAGE_VADDR /* * Preserve the arguments passed by the bootloader in x0 .. x3 @@ -397,7 +398,7 @@ __create_page_tables: ldr x5, =KIMAGE_VADDR add x5, x5, x23 // add KASLR displacement create_pgd_entry x0, x5, x3, x6 - ldr w6, kernel_img_size + ldr w6, =kernel_img_size add x6, x6, x5 mov x3, x24 // phys offset create_block_map x0, x7, x3, x5, x6 @@ -414,9 +415,6 @@ __create_page_tables: ret x28 ENDPROC(__create_page_tables) - -kernel_img_size: - .long _end - (_head - TEXT_OFFSET) .ltorg /* diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h index 5e360ce88f10..4fd72da646a3 100644 --- a/arch/arm64/kernel/image.h +++ b/arch/arm64/kernel/image.h @@ -71,8 +71,12 @@ DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \ DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS); +kernel_img_size = _end - (_text - TEXT_OFFSET); + #ifdef CONFIG_EFI +__efistub_stext_offset = stext - _text; + /* * Prevent the symbol aliases below from being emitted into the kallsyms * table, by forcing them to be absolute symbols (which are conveniently -- GitLab From 7eb90f2ff7e3ee814ff12f3cd909b965cdd4a869 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 17:43:08 +0200 Subject: [PATCH 2799/9938] arm64: cover the .head.text section in the .text segment mapping Keeping .head.text out of the .text mapping buys us very little: its actual payload is only 4 KB, most of which is padding, but the page alignment may add up to 2 MB (in case of CONFIG_DEBUG_ALIGN_RODATA=y) of additional padding to the uncompressed kernel Image. Also, on 4 KB granule kernels, the 4 KB misalignment of .text forces us to map the adjacent 56 KB of code without the PTE_CONT attribute, and since this region contains things like the vector table and the GIC interrupt handling entry point, this region is likely to benefit from the reduced TLB pressure that results from PTE_CONT mappings. So remove the alignment between the .head.text and .text sections, and use the [_text, _etext) rather than the [_stext, _etext) interval for mapping the .text segment. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/vmlinux.lds.S | 1 - arch/arm64/mm/mmu.c | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 5a1939a74ff3..61a1075b9c30 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -96,7 +96,6 @@ SECTIONS _text = .; HEAD_TEXT } - ALIGN_DEBUG_RO_MIN(PAGE_SIZE) .text : { /* Real text segment */ _stext = .; /* Text and read-only data */ __exception_text_start = .; diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 9be2065f8ddb..dbad533076d1 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -385,7 +385,7 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt, static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end) { - unsigned long kernel_start = __pa(_stext); + unsigned long kernel_start = __pa(_text); unsigned long kernel_end = __pa(_etext); /* @@ -417,7 +417,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end early_pgtable_alloc); /* - * Map the linear alias of the [_stext, _etext) interval as + * Map the linear alias of the [_text, _etext) interval as * read-only/non-executable. This makes the contents of the * region accessible to subsystems such as hibernate, but * protects it from inadvertent modification or execution. @@ -449,8 +449,8 @@ void mark_rodata_ro(void) { unsigned long section_size; - section_size = (unsigned long)__start_rodata - (unsigned long)_stext; - create_mapping_late(__pa(_stext), (unsigned long)_stext, + section_size = (unsigned long)__start_rodata - (unsigned long)_text; + create_mapping_late(__pa(_text), (unsigned long)_text, section_size, PAGE_KERNEL_ROX); /* * mark .rodata as read only. Use _etext rather than __end_rodata to @@ -499,7 +499,7 @@ static void __init map_kernel(pgd_t *pgd) { static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data; - map_kernel_segment(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text); + map_kernel_segment(pgd, _text, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text); map_kernel_segment(pgd, __start_rodata, _etext, PAGE_KERNEL, &vmlinux_rodata); map_kernel_segment(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC, &vmlinux_init); -- GitLab From 97740051dd31d200a0efaa84544fe5e4713aac40 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 30 Mar 2016 17:43:09 +0200 Subject: [PATCH 2800/9938] arm64: simplify kernel segment mapping granularity The mapping of the kernel consist of four segments, each of which is mapped with different permission attributes and/or lifetimes. To optimize the TLB and translation table footprint, we define various opaque constants in the linker script that resolve to different aligment values depending on the page size and whether CONFIG_DEBUG_ALIGN_RODATA is set. Considering that - a 4 KB granule kernel benefits from a 64 KB segment alignment (due to the fact that it allows the use of the contiguous bit), - the minimum alignment of the .data segment is THREAD_SIZE already, not PAGE_SIZE (i.e., we already have padding between _data and the start of the .data payload in many cases), - 2 MB is a suitable alignment value on all granule sizes, either for mapping directly (level 2 on 4 KB), or via the contiguous bit (level 3 on 16 KB and 64 KB), - anything beyond 2 MB exceeds the minimum alignment mandated by the boot protocol, and can only be mapped efficiently if the physical alignment happens to be the same, we can simplify this by standardizing on 64 KB (or 2 MB) explicitly, i.e., regardless of granule size, all segments are aligned either to 64 KB, or to 2 MB if CONFIG_DEBUG_ALIGN_RODATA=y. This also means we can drop the Kconfig dependency of CONFIG_DEBUG_ALIGN_RODATA on CONFIG_ARM64_4K_PAGES. Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/Kconfig.debug | 2 +- arch/arm64/kernel/vmlinux.lds.S | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug index 7e76845a0434..710fde4ad0f0 100644 --- a/arch/arm64/Kconfig.debug +++ b/arch/arm64/Kconfig.debug @@ -59,7 +59,7 @@ config DEBUG_RODATA If in doubt, say Y config DEBUG_ALIGN_RODATA - depends on DEBUG_RODATA && ARM64_4K_PAGES + depends on DEBUG_RODATA bool "Align linker sections up to SECTION_SIZE" help If this option is enabled, sections that may potentially be marked as diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 61a1075b9c30..77d86c976abd 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -63,14 +63,19 @@ PECOFF_FILE_ALIGNMENT = 0x200; #endif #if defined(CONFIG_DEBUG_ALIGN_RODATA) -#define ALIGN_DEBUG_RO . = ALIGN(1< Date: Wed, 6 Apr 2016 10:42:28 +0200 Subject: [PATCH 2801/9938] arm64/debug: Remove superfluous SMP function call Since commit 1cf4f629d9d2 ("cpu/hotplug: Move online calls to hotplugged cpu") it is ensured that callbacks of CPU_ONLINE and CPU_DOWN_PREPARE are processed on the hotplugged CPU. Due to this SMP function calls are no longer required. Replace smp_call_function_single() with a direct call to clear_os_lock(). The function writes the OSLAR register to clear OS locking. This does not require to be called with interrupts disabled, therefore the smp_call_function_single() calling convention is not preserved. Cc: Catalin Marinas Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Anna-Maria Gleixner Signed-off-by: Will Deacon --- arch/arm64/kernel/debug-monitors.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index c45f2968bc8c..4fbf3c54275c 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -135,9 +135,8 @@ static void clear_os_lock(void *unused) static int os_lock_notify(struct notifier_block *self, unsigned long action, void *data) { - int cpu = (unsigned long)data; if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) - smp_call_function_single(cpu, clear_os_lock, NULL, 1); + clear_os_lock(NULL); return NOTIFY_OK; } -- GitLab From 4bc49274403395db41dc4ae7d2080346b2319d34 Mon Sep 17 00:00:00 2001 From: Anna-Maria Gleixner Date: Wed, 6 Apr 2016 10:42:49 +0200 Subject: [PATCH 2802/9938] arm64: hw-breakpoint: Remove superfluous SMP function call Since commit 1cf4f629d9d2 ("cpu/hotplug: Move online calls to hotplugged cpu") it is ensured that callbacks of CPU_ONLINE and CPU_DOWN_PREPARE are processed on the hotplugged CPU. Due to this SMP function calls are no longer required. Replace smp_call_function_single() with a direct call of hw_breakpoint_reset(). To keep the calling convention, interrupts are explicitly disabled around the call. Cc: Catalin Marinas Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Anna-Maria Gleixner Signed-off-by: Will Deacon --- arch/arm64/kernel/hw_breakpoint.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index b45c95d34b83..11dc50ac643a 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -886,9 +886,11 @@ static int hw_breakpoint_reset_notify(struct notifier_block *self, unsigned long action, void *hcpu) { - int cpu = (long)hcpu; - if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) - smp_call_function_single(cpu, hw_breakpoint_reset, NULL, 1); + if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) { + local_irq_disable(); + hw_breakpoint_reset(NULL); + local_irq_enable(); + } return NOTIFY_OK; } -- GitLab From 6afedcd23cfd7ac56c011069e4a8db37b46e4623 Mon Sep 17 00:00:00 2001 From: James Morse Date: Wed, 13 Apr 2016 13:40:00 +0100 Subject: [PATCH 2803/9938] arm64: mm: Add trace_irqflags annotations to do_debug_exception() With CONFIG_PROVE_LOCKING, CONFIG_DEBUG_LOCKDEP and CONFIG_TRACE_IRQFLAGS enabled, lockdep will compare current->hardirqs_enabled with the flags from local_irq_save(). When a debug exception occurs, interrupts are disabled in entry.S, but lockdep isn't told, resulting in: DEBUG_LOCKS_WARN_ON(current->hardirqs_enabled) ------------[ cut here ]------------ WARNING: at ../kernel/locking/lockdep.c:3523 Modules linked in: CPU: 3 PID: 1752 Comm: perf Not tainted 4.5.0-rc4+ #2204 Hardware name: ARM Juno development board (r1) (DT) task: ffffffc974868000 ti: ffffffc975f40000 task.ti: ffffffc975f40000 PC is at check_flags.part.35+0x17c/0x184 LR is at check_flags.part.35+0x17c/0x184 pc : [] lr : [] pstate: 600003c5 [...] ---[ end trace 74631f9305ef5020 ]--- Call trace: [] check_flags.part.35+0x17c/0x184 [] lock_acquire+0xa8/0xc4 [] breakpoint_handler+0x118/0x288 [] do_debug_exception+0x3c/0xa8 [] el1_dbg+0x18/0x6c [] do_filp_open+0x64/0xdc [] do_sys_open+0x140/0x204 [] SyS_openat+0x10/0x18 [] el0_svc_naked+0x24/0x28 possible reason: unannotated irqs-off. irq event stamp: 65857 hardirqs last enabled at (65857): [] lookup_mnt+0xf4/0x1b4 hardirqs last disabled at (65856): [] lookup_mnt+0xbc/0x1b4 softirqs last enabled at (65790): [] __do_softirq+0x1f8/0x290 softirqs last disabled at (65757): [] irq_exit+0x9c/0xd0 This patch adds the annotations to do_debug_exception(), while trying not to call trace_hardirqs_off() if el1_dbg() interrupted a task that already had irqs disabled. Signed-off-by: James Morse Signed-off-by: Will Deacon --- arch/arm64/mm/fault.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 95df28bc875f..c12e96753de9 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -555,20 +555,33 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, { const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr); struct siginfo info; + int rv; - if (!inf->fn(addr, esr, regs)) - return 1; + /* + * Tell lockdep we disabled irqs in entry.S. Do nothing if they were + * already disabled to preserve the last enabled/disabled addresses. + */ + if (interrupts_enabled(regs)) + trace_hardirqs_off(); - pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n", - inf->name, esr, addr); + if (!inf->fn(addr, esr, regs)) { + rv = 1; + } else { + pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n", + inf->name, esr, addr); + + info.si_signo = inf->sig; + info.si_errno = 0; + info.si_code = inf->code; + info.si_addr = (void __user *)addr; + arm64_notify_die("", regs, &info, 0); + rv = 0; + } - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - arm64_notify_die("", regs, &info, 0); + if (interrupts_enabled(regs)) + trace_hardirqs_on(); - return 0; + return rv; } #ifdef CONFIG_ARM64_PAN -- GitLab From 91d7b2de318ff701451dfc7ede1c029b150ef0e9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 14:48:07 -0300 Subject: [PATCH 2804/9938] perf callchain: Start moving away from global per thread cursors The recent perf_evsel__fprintf_callchain() move to evsel.c added several new symbol requirements to the python binding, for instance: # perf test -v python 16: Try 'import perf' in python, checking link problems : --- start --- test child forked, pid 18030 Traceback (most recent call last): File "", line 1, in ImportError: /tmp/build/perf/python/perf.so: undefined symbol: callchain_cursor test child finished with -1 ---- end ---- Try 'import perf' in python, checking link problems: FAILED! # This would require linking against callchain.c to access to the global callchain_cursor variables. Since lots of functions already receive as a parameter a callchain_cursor struct pointer, make that be the case for some more function so that we can start phasing out usage of yet another global variable. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-djko3097eyg2rn66v2qcqfvn@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 2 +- tools/perf/util/callchain.c | 5 ++-- tools/perf/util/callchain.h | 3 ++- tools/perf/util/evsel.c | 9 ++++--- tools/perf/util/hist.c | 2 +- tools/perf/util/machine.c | 26 +++++++++++-------- tools/perf/util/machine.h | 4 +++ .../util/scripting-engines/trace-event-perl.c | 2 +- .../scripting-engines/trace-event-python.c | 2 +- 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index c9cb3be47cff..58adfee230de 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -375,7 +375,7 @@ static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample) } al.thread = machine__findnew_thread(machine, sample->pid, sample->tid); - sample__resolve_callchain(sample, NULL, evsel, &al, 16); + sample__resolve_callchain(sample, &callchain_cursor, NULL, evsel, &al, 16); callchain_cursor_commit(&callchain_cursor); while (true) { diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 24b4bd0d7754..2b4ceaf058bb 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -788,7 +788,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor, return 0; } -int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, +int sample__resolve_callchain(struct perf_sample *sample, + struct callchain_cursor *cursor, struct symbol **parent, struct perf_evsel *evsel, struct addr_location *al, int max_stack) { @@ -797,7 +798,7 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || sort__has_parent) { - return thread__resolve_callchain(al->thread, evsel, sample, + return thread__resolve_callchain(al->thread, cursor, evsel, sample, parent, al, max_stack); } return 0; diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index d2a9e694810c..cae5a7b1f5c8 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -212,7 +212,8 @@ struct hist_entry; int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); int record_callchain_opt(const struct option *opt, const char *arg, int unset); -int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, +int sample__resolve_callchain(struct perf_sample *sample, + struct callchain_cursor *cursor, struct symbol **parent, struct perf_evsel *evsel, struct addr_location *al, int max_stack); int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 6e86598682be..38f464a4fa04 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2349,6 +2349,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * FILE *fp) { int printed = 0; + struct callchain_cursor cursor; struct callchain_cursor_node *node; int print_ip = print_opts & EVSEL__PRINT_IP; int print_sym = print_opts & EVSEL__PRINT_SYM; @@ -2362,14 +2363,14 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * if (sample->callchain) { struct addr_location node_al; - if (thread__resolve_callchain(al->thread, evsel, + if (thread__resolve_callchain(al->thread, &cursor, evsel, sample, NULL, NULL, stack_depth) != 0) { if (verbose) error("Failed to resolve callchain. Skipping\n"); return printed; } - callchain_cursor_commit(&callchain_cursor); + callchain_cursor_commit(&cursor); if (print_symoffset) node_al = *al; @@ -2377,7 +2378,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * while (stack_depth) { u64 addr = 0; - node = callchain_cursor_current(&callchain_cursor); + node = callchain_cursor_current(&cursor); if (!node) break; @@ -2420,7 +2421,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * stack_depth--; next: - callchain_cursor_advance(&callchain_cursor); + callchain_cursor_advance(&cursor); } } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 3d34c57dfbe2..991a351a8a41 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -953,7 +953,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, { int err, err2; - err = sample__resolve_callchain(iter->sample, &iter->parent, + err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, iter->evsel, al, max_stack_depth); if (err) return err; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 80b9b6a87990..0c4dabc69932 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1599,6 +1599,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, } static int add_callchain_ip(struct thread *thread, + struct callchain_cursor *cursor, struct symbol **parent, struct addr_location *root_al, u8 *cpumode, @@ -1630,7 +1631,7 @@ static int add_callchain_ip(struct thread *thread, * It seems the callchain is corrupted. * Discard all. */ - callchain_cursor_reset(&callchain_cursor); + callchain_cursor_reset(cursor); return 1; } return 0; @@ -1648,13 +1649,13 @@ static int add_callchain_ip(struct thread *thread, /* Treat this symbol as the root, forgetting its callees. */ *root_al = al; - callchain_cursor_reset(&callchain_cursor); + callchain_cursor_reset(cursor); } } if (symbol_conf.hide_unresolved && al.sym == NULL) return 0; - return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym); + return callchain_cursor_append(cursor, al.addr, al.map, al.sym); } struct branch_info *sample__resolve_bstack(struct perf_sample *sample, @@ -1724,6 +1725,7 @@ static int remove_loops(struct branch_entry *l, int nr) * negative error code on other errors. */ static int resolve_lbr_callchain_sample(struct thread *thread, + struct callchain_cursor *cursor, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, @@ -1778,7 +1780,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, ip = lbr_stack->entries[0].to; } - err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); + err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); if (err) return (err < 0) ? err : 0; } @@ -1789,6 +1791,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, } static int thread__resolve_callchain_sample(struct thread *thread, + struct callchain_cursor *cursor, struct perf_evsel *evsel, struct perf_sample *sample, struct symbol **parent, @@ -1803,10 +1806,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, int skip_idx = -1; int first_call = 0; - callchain_cursor_reset(&callchain_cursor); + callchain_cursor_reset(cursor); if (has_branch_callstack(evsel)) { - err = resolve_lbr_callchain_sample(thread, sample, parent, + err = resolve_lbr_callchain_sample(thread, cursor, sample, parent, root_al, max_stack); if (err) return (err < 0) ? err : 0; @@ -1863,10 +1866,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, nr = remove_loops(be, nr); for (i = 0; i < nr; i++) { - err = add_callchain_ip(thread, parent, root_al, + err = add_callchain_ip(thread, cursor, parent, root_al, NULL, be[i].to); if (!err) - err = add_callchain_ip(thread, parent, root_al, + err = add_callchain_ip(thread, cursor, parent, root_al, NULL, be[i].from); if (err == -EINVAL) break; @@ -1896,7 +1899,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, #endif ip = chain->ips[j]; - err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); + err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); if (err) return (err < 0) ? err : 0; @@ -1916,13 +1919,14 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) } int thread__resolve_callchain(struct thread *thread, + struct callchain_cursor *cursor, struct perf_evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, int max_stack) { - int ret = thread__resolve_callchain_sample(thread, evsel, + int ret = thread__resolve_callchain_sample(thread, cursor, evsel, sample, parent, root_al, max_stack); if (ret) @@ -1938,7 +1942,7 @@ int thread__resolve_callchain(struct thread *thread, (!sample->user_stack.size)) return 0; - return unwind__get_entries(unwind_entry, &callchain_cursor, + return unwind__get_entries(unwind_entry, cursor, thread, sample, max_stack); } diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 8499db281158..382873bdc563 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -141,7 +141,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample, struct addr_location *al); struct mem_info *sample__resolve_mem(struct perf_sample *sample, struct addr_location *al); + +struct callchain_cursor; + int thread__resolve_callchain(struct thread *thread, + struct callchain_cursor *cursor, struct perf_evsel *evsel, struct perf_sample *sample, struct symbol **parent, diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 35ed00a600fb..ae1cebc307c5 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -263,7 +263,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, if (!symbol_conf.use_callchain || !sample->callchain) goto exit; - if (thread__resolve_callchain(al->thread, evsel, + if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, sample, NULL, NULL, PERF_MAX_STACK_DEPTH) != 0) { pr_err("Failed to resolve callchain. Skipping\n"); diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index fbd05242b4e5..525eb49e7ba6 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -323,7 +323,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, if (!symbol_conf.use_callchain || !sample->callchain) goto exit; - if (thread__resolve_callchain(al->thread, evsel, + if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, sample, NULL, NULL, scripting_max_stack) != 0) { pr_err("Failed to resolve callchain. Skipping\n"); -- GitLab From de446b40d5ddb2c3f1fe453ac405543663f9ac5d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 14:56:06 -0300 Subject: [PATCH 2805/9938] perf evsel: Remove symbol_conf usage # perf test -v python 16: Try 'import perf' in python, checking link problems : --- start --- test child forked, pid 672 Traceback (most recent call last): File "", line 1, in ImportError: /tmp/build/perf/python/perf.so: undefined symbol: symbol_conf test child finished with -1 ---- end ---- Try 'import perf' in python, checking link problems: FAILED! # To fix it just pass a parameter to perf_evsel__fprintf_sym telling if callchains should be printed. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-comrsr20bsnr8bg0n6rfwv12@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 2 ++ tools/perf/util/evsel.c | 6 +++--- tools/perf/util/evsel.h | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 838c0bc38105..717ba0215234 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -580,6 +580,7 @@ static void print_sample_bts(struct perf_sample *sample, } } perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts, + symbol_conf.use_callchain, scripting_max_stack, stdout); } @@ -790,6 +791,7 @@ static void process_event(struct perf_script *script, perf_evsel__fprintf_sym(evsel, sample, al, 0, output[attr->type].print_ip_opts, + symbol_conf.use_callchain, scripting_max_stack, stdout); } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 38f464a4fa04..60bba67e6959 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2430,8 +2430,8 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) + unsigned int print_opts, bool print_callchain, + unsigned int stack_depth, FILE *fp) { int printed = 0; int print_ip = print_opts & EVSEL__PRINT_IP; @@ -2441,7 +2441,7 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; - if (symbol_conf.use_callchain && sample->callchain) { + if (print_callchain && sample->callchain) { printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, print_opts, stack_depth, fp); } else if (!(al->sym && al->sym->ignore)) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 36edd3c91d5c..013f3615730b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -403,8 +403,8 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp); + unsigned int print_opts, bool print_callchain, + unsigned int stack_depth, FILE *fp); bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); -- GitLab From 1ab92956d4aac52d0c59c229a0790a672063ece0 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 17 Mar 2016 00:57:17 +0800 Subject: [PATCH 2806/9938] i2c: rk3x: switch to i2c generic dt parsing Switch to the new generic functions: i2c_parse_fw_timings(). Signed-off-by: David Wu Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rk3x.c | 87 ++++++++++------------------------- 1 file changed, 24 insertions(+), 63 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 9096d17beb5b..c4b0d8973694 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -101,10 +101,7 @@ struct rk3x_i2c { struct notifier_block clk_rate_nb; /* Settings */ - unsigned int scl_frequency; - unsigned int scl_rise_ns; - unsigned int scl_fall_ns; - unsigned int sda_fall_ns; + struct i2c_timings t; /* Synchronization & notification */ spinlock_t lock; @@ -437,10 +434,7 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id) * Calculate divider values for desired SCL frequency * * @clk_rate: I2C input clock rate - * @scl_rate: Desired SCL rate - * @scl_rise_ns: How many ns it takes for SCL to rise. - * @scl_fall_ns: How many ns it takes for SCL to fall. - * @sda_fall_ns: How many ns it takes for SDA to fall. + * @t: Known I2C timing information. * @div_low: Divider output for low * @div_high: Divider output for high * @@ -448,11 +442,10 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id) * a best-effort divider value is returned in divs. If the target rate is * too high, we silently use the highest possible rate. */ -static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate, - unsigned long scl_rise_ns, - unsigned long scl_fall_ns, - unsigned long sda_fall_ns, - unsigned long *div_low, unsigned long *div_high) +static int rk3x_i2c_calc_divs(unsigned long clk_rate, + struct i2c_timings *t, + unsigned long *div_low, + unsigned long *div_high) { unsigned long spec_min_low_ns, spec_min_high_ns; unsigned long spec_setup_start, spec_max_data_hold_ns; @@ -472,12 +465,12 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate, int ret = 0; /* Only support standard-mode and fast-mode */ - if (WARN_ON(scl_rate > 400000)) - scl_rate = 400000; + if (WARN_ON(t->bus_freq_hz > 400000)) + t->bus_freq_hz = 400000; /* prevent scl_rate_khz from becoming 0 */ - if (WARN_ON(scl_rate < 1000)) - scl_rate = 1000; + if (WARN_ON(t->bus_freq_hz < 1000)) + t->bus_freq_hz = 1000; /* * min_low_ns: The minimum number of ns we need to hold low to @@ -491,7 +484,7 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate, * This is because the i2c host on Rockchip holds the data line * for half the low time. */ - if (scl_rate <= 100000) { + if (t->bus_freq_hz <= 100000) { /* Standard-mode */ spec_min_low_ns = 4700; spec_setup_start = 4700; @@ -506,7 +499,7 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate, spec_max_data_hold_ns = 900; data_hold_buffer_ns = 50; } - min_high_ns = scl_rise_ns + spec_min_high_ns; + min_high_ns = t->scl_rise_ns + spec_min_high_ns; /* * Timings for repeated start: @@ -517,18 +510,18 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate, * we meet tSU;STA and tHD;STA times. */ min_high_ns = max(min_high_ns, - DIV_ROUND_UP((scl_rise_ns + spec_setup_start) * 1000, 875)); + DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start) * 1000, 875)); min_high_ns = max(min_high_ns, - DIV_ROUND_UP((scl_rise_ns + spec_setup_start + - sda_fall_ns + spec_min_high_ns), 2)); + DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start + + t->sda_fall_ns + spec_min_high_ns), 2)); - min_low_ns = scl_fall_ns + spec_min_low_ns; + min_low_ns = t->scl_fall_ns + spec_min_low_ns; max_low_ns = spec_max_data_hold_ns * 2 - data_hold_buffer_ns; min_total_ns = min_low_ns + min_high_ns; /* Adjust to avoid overflow */ clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000); - scl_rate_khz = scl_rate / 1000; + scl_rate_khz = t->bus_freq_hz / 1000; /* * We need the total div to be >= this number @@ -616,14 +609,13 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate, static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate) { + struct i2c_timings *t = &i2c->t; unsigned long div_low, div_high; u64 t_low_ns, t_high_ns; int ret; - ret = rk3x_i2c_calc_divs(clk_rate, i2c->scl_frequency, i2c->scl_rise_ns, - i2c->scl_fall_ns, i2c->sda_fall_ns, - &div_low, &div_high); - WARN_ONCE(ret != 0, "Could not reach SCL freq %u", i2c->scl_frequency); + ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high); + WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz); clk_enable(i2c->clk); i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV); @@ -634,7 +626,7 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate) dev_dbg(i2c->dev, "CLK %lukhz, Req %uns, Act low %lluns high %lluns\n", clk_rate / 1000, - 1000000000 / i2c->scl_frequency, + 1000000000 / t->bus_freq_hz, t_low_ns, t_high_ns); } @@ -664,9 +656,7 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long switch (event) { case PRE_RATE_CHANGE: - if (rk3x_i2c_calc_divs(ndata->new_rate, i2c->scl_frequency, - i2c->scl_rise_ns, i2c->scl_fall_ns, - i2c->sda_fall_ns, + if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &div_low, &div_high) != 0) return NOTIFY_STOP; @@ -879,37 +869,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev) match = of_match_node(rk3x_i2c_match, np); i2c->soc_data = (struct rk3x_i2c_soc_data *)match->data; - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &i2c->scl_frequency)) { - dev_info(&pdev->dev, "using default SCL frequency: %d\n", - DEFAULT_SCL_RATE); - i2c->scl_frequency = DEFAULT_SCL_RATE; - } - - if (i2c->scl_frequency == 0 || i2c->scl_frequency > 400 * 1000) { - dev_warn(&pdev->dev, "invalid SCL frequency specified.\n"); - dev_warn(&pdev->dev, "using default SCL frequency: %d\n", - DEFAULT_SCL_RATE); - i2c->scl_frequency = DEFAULT_SCL_RATE; - } - - /* - * Read rise and fall time from device tree. If not available use - * the default maximum timing from the specification. - */ - if (of_property_read_u32(pdev->dev.of_node, "i2c-scl-rising-time-ns", - &i2c->scl_rise_ns)) { - if (i2c->scl_frequency <= 100000) - i2c->scl_rise_ns = 1000; - else - i2c->scl_rise_ns = 300; - } - if (of_property_read_u32(pdev->dev.of_node, "i2c-scl-falling-time-ns", - &i2c->scl_fall_ns)) - i2c->scl_fall_ns = 300; - if (of_property_read_u32(pdev->dev.of_node, "i2c-sda-falling-time-ns", - &i2c->sda_fall_ns)) - i2c->sda_fall_ns = i2c->scl_fall_ns; + /* use common interface to get I2C timing properties */ + i2c_parse_fw_timings(&pdev->dev, &i2c->t, true); strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name)); i2c->adap.owner = THIS_MODULE; -- GitLab From 025dd3daeda77f61a280da87ae7015a6808dfe1f Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Mon, 11 Apr 2016 10:50:30 -0400 Subject: [PATCH 2807/9938] PCI: keystone: Add error IRQ handler Keystone PCI hardware generates error interrupts at RC using a platform IRQ instead of a standard MSI or legacy IRQ. Add a simple error handler that logs the fatal interrupt status to the console. [bhelgaas: s/node/dev->of_node/, tidy comments, return irqreturn_t directly] Signed-off-by: Murali Karicheri Signed-off-by: Bjorn Helgaas Acked-by: Rob Herring CC: Pawel Moll CC: Mark Rutland CC: Ian Campbell CC: Kumar Gala --- .../devicetree/bindings/pci/pci-keystone.txt | 1 + drivers/pci/host/pci-keystone-dw.c | 38 +++++++++++++++++++ drivers/pci/host/pci-keystone.c | 29 ++++++++++++++ drivers/pci/host/pci-keystone.h | 6 +++ 4 files changed, 74 insertions(+) diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt index 54eae2938174..d08a4d51108f 100644 --- a/Documentation/devicetree/bindings/pci/pci-keystone.txt +++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt @@ -56,6 +56,7 @@ Optional properties:- phy-names: name of the Generic Keystine SerDes phy for PCI - If boot loader already does PCI link establishment, then phys and phy-names shouldn't be present. + interrupts: platform interrupt for error interrupts. Designware DT Properties not applicable for Keystone PCI diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c index 6153853ca9c3..41515092eb0d 100644 --- a/drivers/pci/host/pci-keystone-dw.c +++ b/drivers/pci/host/pci-keystone-dw.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -53,6 +54,21 @@ #define IRQ_STATUS 0x184 #define MSI_IRQ_OFFSET 4 +/* Error IRQ bits */ +#define ERR_AER BIT(5) /* ECRC error */ +#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */ +#define ERR_CORR BIT(3) /* Correctable error */ +#define ERR_NONFATAL BIT(2) /* Non-fatal error */ +#define ERR_FATAL BIT(1) /* Fatal error */ +#define ERR_SYS BIT(0) /* System (fatal, non-fatal, or correctable) */ +#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \ + ERR_NONFATAL | ERR_FATAL | ERR_SYS) +#define ERR_FATAL_IRQ (ERR_FATAL | ERR_AXI) +#define ERR_IRQ_STATUS_RAW 0x1c0 +#define ERR_IRQ_STATUS 0x1c4 +#define ERR_IRQ_ENABLE_SET 0x1c8 +#define ERR_IRQ_ENABLE_CLR 0x1cc + /* Config space registers */ #define DEBUG0 0x728 @@ -243,6 +259,28 @@ void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset) writel(offset, ks_pcie->va_app_base + IRQ_EOI); } +void ks_dw_pcie_enable_error_irq(void __iomem *reg_base) +{ + writel(ERR_IRQ_ALL, reg_base + ERR_IRQ_ENABLE_SET); +} + +irqreturn_t ks_dw_pcie_handle_error_irq(struct device *dev, + void __iomem *reg_base) +{ + u32 status; + + status = readl(reg_base + ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL; + if (!status) + return IRQ_NONE; + + if (status & ERR_FATAL_IRQ) + dev_err(dev, "fatal error (status %#010x)\n", status); + + /* Ack the IRQ; status bits are RW1C */ + writel(status, reg_base + ERR_IRQ_STATUS); + return IRQ_HANDLED; +} + static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d) { } diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c index b71f55bb0315..58120009c819 100644 --- a/drivers/pci/host/pci-keystone.c +++ b/drivers/pci/host/pci-keystone.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -226,6 +227,9 @@ static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie) ks_pcie); } } + + if (ks_pcie->error_irq > 0) + ks_dw_pcie_enable_error_irq(ks_pcie->va_app_base); } /* @@ -289,6 +293,14 @@ static struct pcie_host_ops keystone_pcie_host_ops = { .scan_bus = ks_dw_pcie_v3_65_scan_bus, }; +static irqreturn_t pcie_err_irq_handler(int irq, void *priv) +{ + struct keystone_pcie *ks_pcie = priv; + + return ks_dw_pcie_handle_error_irq(ks_pcie->pp.dev, + ks_pcie->va_app_base); +} + static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie, struct platform_device *pdev) { @@ -309,6 +321,22 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie, return ret; } + /* + * Index 0 is the platform interrupt for error interrupt + * from RC. This is optional. + */ + ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0); + if (ks_pcie->error_irq <= 0) + dev_info(&pdev->dev, "no error IRQ defined\n"); + else { + if (request_irq(ks_pcie->error_irq, pcie_err_irq_handler, + IRQF_SHARED, "pcie-error-irq", ks_pcie) < 0) { + dev_err(&pdev->dev, "failed to request error IRQ %d\n", + ks_pcie->error_irq); + return ret; + } + } + pp->root_bus_nr = -1; pp->ops = &keystone_pcie_host_ops; ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np); @@ -376,6 +404,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev) devm_release_mem_region(dev, res->start, resource_size(res)); pp->dev = dev; + ks_pcie->np = dev->of_node; platform_set_drvdata(pdev, ks_pcie); ks_pcie->clk = devm_clk_get(dev, "pcie"); if (IS_ERR(ks_pcie->clk)) { diff --git a/drivers/pci/host/pci-keystone.h b/drivers/pci/host/pci-keystone.h index f0944e8c4b02..a5b0cb2ba4d7 100644 --- a/drivers/pci/host/pci-keystone.h +++ b/drivers/pci/host/pci-keystone.h @@ -29,6 +29,9 @@ struct keystone_pcie { int msi_host_irqs[MAX_MSI_HOST_IRQS]; struct device_node *msi_intc_np; struct irq_domain *legacy_irq_domain; + struct device_node *np; + + int error_irq; /* Application register space */ void __iomem *va_app_base; @@ -42,6 +45,9 @@ phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp); /* Keystone specific PCI controller APIs */ void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie); void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset); +void ks_dw_pcie_enable_error_irq(void __iomem *reg_base); +irqreturn_t ks_dw_pcie_handle_error_irq(struct device *dev, + void __iomem *reg_base); int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie, struct device_node *msi_intc_np); int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, -- GitLab From e249fc7d9b1cfa046bc448b27c3fde5619442a7a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 2 Sep 2015 22:30:51 +0200 Subject: [PATCH 2808/9938] ARM: dts: nomadik: add accelerometer IRQ and pin setting The LIS3LV02DL accelerometer on the Nomadik NHK15 can generate IRQs by the DRDY line. Map this in the DTS file and set up the pin as input to the SoC. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-nomadik-nhk15.dts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/ste-nomadik-nhk15.dts b/arch/arm/boot/dts/ste-nomadik-nhk15.dts index 4a21c6492dbb..d35aa88791ad 100644 --- a/arch/arm/boot/dts/ste-nomadik-nhk15.dts +++ b/arch/arm/boot/dts/ste-nomadik-nhk15.dts @@ -57,8 +57,15 @@ }; }; }; + lis3lv02dl { + lis3lv02dl_nhk_mode: lis3lv02dl_nhk { + nhk_cfg1 { + pins = "GPIO82_C10"; // IRQ line + ste,input = <0>; + }; + }; + }; }; - src@101e0000 { /* These chrystal outputs are not used on this board */ disable-sxtalo; @@ -86,6 +93,10 @@ lis3lv02dl@1d { /* Accelerometer */ compatible = "st,lis3lv02dl-accel"; + interrupt-parent = <&gpio2>; + interrupts = <18 IRQ_TYPE_EDGE_RISING>; // GPIO 82 + pinctrl-0 = <&lis3lv02dl_nhk_mode>; + pinctrl-names = "default"; reg = <0x1d>; }; stmpe0: stmpe2401@43 { -- GitLab From a22d7768860aedcd9c4011075c4d3bc1eaaddd63 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 6 Oct 2015 12:03:27 +0200 Subject: [PATCH 2809/9938] ARM: dts: nomadik: add DMA engine and some channels This adds the DMA engine to the Nomadik and assigns the UART DMA channels. Both slave DMA for UARTs and the memcpy engine works fine, tested on the Nomadik NHK15. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi index e2be53343064..d2d532a9d783 100644 --- a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi +++ b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi @@ -748,6 +748,9 @@ clocks = <&uart0clk>, <&pclkuart0>; clock-names = "uartclk", "apb_pclk"; status = "disabled"; + dmas = <&dmac0 14 1>, + <&dmac0 15 1>; + dma-names = "rx", "tx"; }; uart1: uart@101fb000 { @@ -759,6 +762,9 @@ clock-names = "uartclk", "apb_pclk"; pinctrl-names = "default"; pinctrl-0 = <&uart1_default_mux>; + dmas = <&dmac1 22 1>, + <&dmac1 23 1>; + dma-names = "rx", "tx"; }; uart2: uart@101f2000 { @@ -769,6 +775,9 @@ clocks = <&uart2clk>, <&pclkuart2>; clock-names = "uartclk", "apb_pclk"; status = "disabled"; + dmas = <&dmac1 30 1>, + <&dmac1 31 1>; + dma-names = "rx", "tx"; }; rng: rng@101b0000 { @@ -813,5 +822,34 @@ pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>; vmmc-supply = <&vmmc_regulator>; }; + + dmac0: dma-controller@10130000 { + compatible = "arm,pl080", "arm,primecell"; + reg = <0x10130000 0x1000>; + interrupt-parent = <&vica>; + interrupts = <15>; + clocks = <&hclkdma0>; + clock-names = "apb_pclk"; + lli-bus-interface-ahb1; + lli-bus-interface-ahb2; + mem-bus-interface-ahb2; + memcpy-burst-size = <256>; + memcpy-bus-width = <32>; + #dma-cells = <2>; + }; + dmac1: dma-controller@10150000 { + compatible = "arm,pl080", "arm,primecell"; + reg = <0x10150000 0x1000>; + interrupt-parent = <&vica>; + interrupts = <13>; + clocks = <&hclkdma1>; + clock-names = "apb_pclk"; + lli-bus-interface-ahb1; + lli-bus-interface-ahb2; + mem-bus-interface-ahb2; + memcpy-burst-size = <256>; + memcpy-bus-width = <32>; + #dma-cells = <2>; + }; }; }; -- GitLab From bf7974710a40aaeb69dee7f62d91048bdaf79c76 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:13 +0200 Subject: [PATCH 2810/9938] devlink: add shared buffer configuration Define userspace API and drivers API for configuration of shared buffers. Four basic objects are defined: shared buffer - attributes are size, number of pools and TCs pool - chunk of sharedbuffer definition, it has some size and either static or dynamic threshold port pool threshold - to set per-port threshold for each pool port tc threshold bind - to bind port and TC to specified pool with threshold. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/devlink.h | 47 ++ include/uapi/linux/devlink.h | 57 +++ net/core/devlink.c | 940 +++++++++++++++++++++++++++++++++++ 3 files changed, 1044 insertions(+) diff --git a/include/net/devlink.h b/include/net/devlink.h index c37d257891d6..e4c27473ee4f 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -24,6 +24,7 @@ struct devlink_ops; struct devlink { struct list_head list; struct list_head port_list; + struct list_head sb_list; const struct devlink_ops *ops; struct device *dev; possible_net_t _net; @@ -42,6 +43,12 @@ struct devlink_port { u32 split_group; }; +struct devlink_sb_pool_info { + enum devlink_sb_pool_type pool_type; + u32 size; + enum devlink_sb_threshold_type threshold_type; +}; + struct devlink_ops { size_t priv_size; int (*port_type_set)(struct devlink_port *devlink_port, @@ -49,6 +56,28 @@ struct devlink_ops { int (*port_split)(struct devlink *devlink, unsigned int port_index, unsigned int count); int (*port_unsplit)(struct devlink *devlink, unsigned int port_index); + int (*sb_pool_get)(struct devlink *devlink, unsigned int sb_index, + u16 pool_index, + struct devlink_sb_pool_info *pool_info); + int (*sb_pool_set)(struct devlink *devlink, unsigned int sb_index, + u16 pool_index, u32 size, + enum devlink_sb_threshold_type threshold_type); + int (*sb_port_pool_get)(struct devlink_port *devlink_port, + unsigned int sb_index, u16 pool_index, + u32 *p_threshold); + int (*sb_port_pool_set)(struct devlink_port *devlink_port, + unsigned int sb_index, u16 pool_index, + u32 threshold); + int (*sb_tc_pool_bind_get)(struct devlink_port *devlink_port, + unsigned int sb_index, + u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 *p_pool_index, u32 *p_threshold); + int (*sb_tc_pool_bind_set)(struct devlink_port *devlink_port, + unsigned int sb_index, + u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 pool_index, u32 threshold); }; static inline void *devlink_priv(struct devlink *devlink) @@ -82,6 +111,11 @@ void devlink_port_type_ib_set(struct devlink_port *devlink_port, void devlink_port_type_clear(struct devlink_port *devlink_port); void devlink_port_split_set(struct devlink_port *devlink_port, u32 split_group); +int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, + u16 egress_tc_count); +void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index); #else @@ -135,6 +169,19 @@ static inline void devlink_port_split_set(struct devlink_port *devlink_port, { } +static inline int devlink_sb_register(struct devlink *devlink, + unsigned int sb_index, u32 size, + u16 ingress_pools_count, + u16 egress_pools_count, u16 tc_count) +{ + return 0; +} + +static inline void devlink_sb_unregister(struct devlink *devlink, + unsigned int sb_index) +{ +} + #endif #endif /* _NET_DEVLINK_H_ */ diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index c9fee5781eb1..9c1aa5783090 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -33,6 +33,26 @@ enum devlink_command { DEVLINK_CMD_PORT_SPLIT, DEVLINK_CMD_PORT_UNSPLIT, + DEVLINK_CMD_SB_GET, /* can dump */ + DEVLINK_CMD_SB_SET, + DEVLINK_CMD_SB_NEW, + DEVLINK_CMD_SB_DEL, + + DEVLINK_CMD_SB_POOL_GET, /* can dump */ + DEVLINK_CMD_SB_POOL_SET, + DEVLINK_CMD_SB_POOL_NEW, + DEVLINK_CMD_SB_POOL_DEL, + + DEVLINK_CMD_SB_PORT_POOL_GET, /* can dump */ + DEVLINK_CMD_SB_PORT_POOL_SET, + DEVLINK_CMD_SB_PORT_POOL_NEW, + DEVLINK_CMD_SB_PORT_POOL_DEL, + + DEVLINK_CMD_SB_TC_POOL_BIND_GET, /* can dump */ + DEVLINK_CMD_SB_TC_POOL_BIND_SET, + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, + DEVLINK_CMD_SB_TC_POOL_BIND_DEL, + /* add new commands above here */ __DEVLINK_CMD_MAX, @@ -46,6 +66,31 @@ enum devlink_port_type { DEVLINK_PORT_TYPE_IB, }; +enum devlink_sb_pool_type { + DEVLINK_SB_POOL_TYPE_INGRESS, + DEVLINK_SB_POOL_TYPE_EGRESS, +}; + +/* static threshold - limiting the maximum number of bytes. + * dynamic threshold - limiting the maximum number of bytes + * based on the currently available free space in the shared buffer pool. + * In this mode, the maximum quota is calculated based + * on the following formula: + * max_quota = alpha / (1 + alpha) * Free_Buffer + * While Free_Buffer is the amount of none-occupied buffer associated to + * the relevant pool. + * The value range which can be passed is 0-20 and serves + * for computation of alpha by following formula: + * alpha = 2 ^ (passed_value - 10) + */ + +enum devlink_sb_threshold_type { + DEVLINK_SB_THRESHOLD_TYPE_STATIC, + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC, +}; + +#define DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX 20 + enum devlink_attr { /* don't change the order or add anything between, this is ABI! */ DEVLINK_ATTR_UNSPEC, @@ -62,6 +107,18 @@ enum devlink_attr { DEVLINK_ATTR_PORT_IBDEV_NAME, /* string */ DEVLINK_ATTR_PORT_SPLIT_COUNT, /* u32 */ DEVLINK_ATTR_PORT_SPLIT_GROUP, /* u32 */ + DEVLINK_ATTR_SB_INDEX, /* u32 */ + DEVLINK_ATTR_SB_SIZE, /* u32 */ + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, /* u16 */ + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, /* u16 */ + DEVLINK_ATTR_SB_INGRESS_TC_COUNT, /* u16 */ + DEVLINK_ATTR_SB_EGRESS_TC_COUNT, /* u16 */ + DEVLINK_ATTR_SB_POOL_INDEX, /* u16 */ + DEVLINK_ATTR_SB_POOL_TYPE, /* u8 */ + DEVLINK_ATTR_SB_POOL_SIZE, /* u32 */ + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, /* u8 */ + DEVLINK_ATTR_SB_THRESHOLD, /* u32 */ + DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ /* add new attributes above here, update the policy in devlink.c */ diff --git a/net/core/devlink.c b/net/core/devlink.c index b84cf0df4a0e..aa0b9e1542e7 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -119,8 +119,167 @@ static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, return devlink_port_get_from_attrs(devlink, info->attrs); } +struct devlink_sb { + struct list_head list; + unsigned int index; + u32 size; + u16 ingress_pools_count; + u16 egress_pools_count; + u16 ingress_tc_count; + u16 egress_tc_count; +}; + +static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) +{ + return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; +} + +static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, + unsigned int sb_index) +{ + struct devlink_sb *devlink_sb; + + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { + if (devlink_sb->index == sb_index) + return devlink_sb; + } + return NULL; +} + +static bool devlink_sb_index_exists(struct devlink *devlink, + unsigned int sb_index) +{ + return devlink_sb_get_by_index(devlink, sb_index); +} + +static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, + struct nlattr **attrs) +{ + if (attrs[DEVLINK_ATTR_SB_INDEX]) { + u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); + struct devlink_sb *devlink_sb; + + devlink_sb = devlink_sb_get_by_index(devlink, sb_index); + if (!devlink_sb) + return ERR_PTR(-ENODEV); + return devlink_sb; + } + return ERR_PTR(-EINVAL); +} + +static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, + struct genl_info *info) +{ + return devlink_sb_get_from_attrs(devlink, info->attrs); +} + +static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, + struct nlattr **attrs, + u16 *p_pool_index) +{ + u16 val; + + if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) + return -EINVAL; + + val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); + if (val >= devlink_sb_pool_count(devlink_sb)) + return -EINVAL; + *p_pool_index = val; + return 0; +} + +static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, + struct genl_info *info, + u16 *p_pool_index) +{ + return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, + p_pool_index); +} + +static int +devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, + enum devlink_sb_pool_type *p_pool_type) +{ + u8 val; + + if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) + return -EINVAL; + + val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); + if (val != DEVLINK_SB_POOL_TYPE_INGRESS && + val != DEVLINK_SB_POOL_TYPE_EGRESS) + return -EINVAL; + *p_pool_type = val; + return 0; +} + +static int +devlink_sb_pool_type_get_from_info(struct genl_info *info, + enum devlink_sb_pool_type *p_pool_type) +{ + return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); +} + +static int +devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, + enum devlink_sb_threshold_type *p_th_type) +{ + u8 val; + + if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) + return -EINVAL; + + val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); + if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && + val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) + return -EINVAL; + *p_th_type = val; + return 0; +} + +static int +devlink_sb_th_type_get_from_info(struct genl_info *info, + enum devlink_sb_threshold_type *p_th_type) +{ + return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); +} + +static int +devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, + struct nlattr **attrs, + enum devlink_sb_pool_type pool_type, + u16 *p_tc_index) +{ + u16 val; + + if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) + return -EINVAL; + + val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); + if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && + val >= devlink_sb->ingress_tc_count) + return -EINVAL; + if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && + val >= devlink_sb->egress_tc_count) + return -EINVAL; + *p_tc_index = val; + return 0; +} + +static int +devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, + struct genl_info *info, + enum devlink_sb_pool_type pool_type, + u16 *p_tc_index) +{ + return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, + pool_type, p_tc_index); +} + #define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) #define DEVLINK_NL_FLAG_NEED_PORT BIT(1) +#define DEVLINK_NL_FLAG_NEED_SB BIT(2) static int devlink_nl_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) @@ -147,6 +306,18 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, } info->user_ptr[0] = devlink_port; } + if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { + struct devlink_sb *devlink_sb; + + devlink_sb = devlink_sb_get_from_info(devlink, info); + if (IS_ERR(devlink_sb)) { + if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) + mutex_unlock(&devlink_port_mutex); + mutex_unlock(&devlink_mutex); + return PTR_ERR(devlink_sb); + } + info->user_ptr[1] = devlink_sb; + } return 0; } @@ -499,12 +670,675 @@ static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, return devlink_port_unsplit(devlink, port_index); } +static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, + struct devlink_sb *devlink_sb, + enum devlink_command cmd, u32 portid, + u32 seq, int flags) +{ + void *hdr; + + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + if (devlink_nl_put_handle(msg, devlink)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, + devlink_sb->ingress_pools_count)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, + devlink_sb->egress_pools_count)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, + devlink_sb->ingress_tc_count)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, + devlink_sb->egress_tc_count)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink *devlink = info->user_ptr[0]; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + struct sk_buff *msg; + int err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + err = devlink_nl_sb_fill(msg, devlink, devlink_sb, + DEVLINK_CMD_SB_NEW, + info->snd_portid, info->snd_seq, 0); + if (err) { + nlmsg_free(msg); + return err; + } + + return genlmsg_reply(msg, info); +} + +static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct devlink *devlink; + struct devlink_sb *devlink_sb; + int start = cb->args[0]; + int idx = 0; + int err; + + mutex_lock(&devlink_mutex); + list_for_each_entry(devlink, &devlink_list, list) { + if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) + continue; + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { + if (idx < start) { + idx++; + continue; + } + err = devlink_nl_sb_fill(msg, devlink, devlink_sb, + DEVLINK_CMD_SB_NEW, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + NLM_F_MULTI); + if (err) + goto out; + idx++; + } + } +out: + mutex_unlock(&devlink_mutex); + + cb->args[0] = idx; + return msg->len; +} + +static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, + struct devlink_sb *devlink_sb, + u16 pool_index, enum devlink_command cmd, + u32 portid, u32 seq, int flags) +{ + struct devlink_sb_pool_info pool_info; + void *hdr; + int err; + + err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, + pool_index, &pool_info); + if (err) + return err; + + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + if (devlink_nl_put_handle(msg, devlink)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) + goto nla_put_failure; + if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) + goto nla_put_failure; + if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, + pool_info.threshold_type)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink *devlink = info->user_ptr[0]; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + struct sk_buff *msg; + u16 pool_index; + int err; + + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, + &pool_index); + if (err) + return err; + + if (!devlink->ops || !devlink->ops->sb_pool_get) + return -EOPNOTSUPP; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, + DEVLINK_CMD_SB_POOL_NEW, + info->snd_portid, info->snd_seq, 0); + if (err) { + nlmsg_free(msg); + return err; + } + + return genlmsg_reply(msg, info); +} + +static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, + struct devlink *devlink, + struct devlink_sb *devlink_sb, + u32 portid, u32 seq) +{ + u16 pool_count = devlink_sb_pool_count(devlink_sb); + u16 pool_index; + int err; + + for (pool_index = 0; pool_index < pool_count; pool_index++) { + if (*p_idx < start) { + (*p_idx)++; + continue; + } + err = devlink_nl_sb_pool_fill(msg, devlink, + devlink_sb, + pool_index, + DEVLINK_CMD_SB_POOL_NEW, + portid, seq, NLM_F_MULTI); + if (err) + return err; + (*p_idx)++; + } + return 0; +} + +static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct devlink *devlink; + struct devlink_sb *devlink_sb; + int start = cb->args[0]; + int idx = 0; + int err; + + mutex_lock(&devlink_mutex); + list_for_each_entry(devlink, &devlink_list, list) { + if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || + !devlink->ops || !devlink->ops->sb_pool_get) + continue; + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { + err = __sb_pool_get_dumpit(msg, start, &idx, devlink, + devlink_sb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq); + if (err && err != -EOPNOTSUPP) + goto out; + } + } +out: + mutex_unlock(&devlink_mutex); + + cb->args[0] = idx; + return msg->len; +} + +static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, + u16 pool_index, u32 size, + enum devlink_sb_threshold_type threshold_type) + +{ + const struct devlink_ops *ops = devlink->ops; + + if (ops && ops->sb_pool_set) + return ops->sb_pool_set(devlink, sb_index, pool_index, + size, threshold_type); + return -EOPNOTSUPP; +} + +static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink *devlink = info->user_ptr[0]; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + enum devlink_sb_threshold_type threshold_type; + u16 pool_index; + u32 size; + int err; + + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, + &pool_index); + if (err) + return err; + + err = devlink_sb_th_type_get_from_info(info, &threshold_type); + if (err) + return err; + + if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]) + return -EINVAL; + + size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); + return devlink_sb_pool_set(devlink, devlink_sb->index, + pool_index, size, threshold_type); +} + +static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, + struct devlink *devlink, + struct devlink_port *devlink_port, + struct devlink_sb *devlink_sb, + u16 pool_index, + enum devlink_command cmd, + u32 portid, u32 seq, int flags) +{ + u32 threshold; + void *hdr; + int err; + + err = devlink->ops->sb_port_pool_get(devlink_port, devlink_sb->index, + pool_index, &threshold); + if (err) + return err; + + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + if (devlink_nl_put_handle(msg, devlink)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink_port *devlink_port = info->user_ptr[0]; + struct devlink *devlink = devlink_port->devlink; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + struct sk_buff *msg; + u16 pool_index; + int err; + + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, + &pool_index); + if (err) + return err; + + if (!devlink->ops || !devlink->ops->sb_port_pool_get) + return -EOPNOTSUPP; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, + devlink_sb, pool_index, + DEVLINK_CMD_SB_PORT_POOL_NEW, + info->snd_portid, info->snd_seq, 0); + if (err) { + nlmsg_free(msg); + return err; + } + + return genlmsg_reply(msg, info); +} + +static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, + struct devlink *devlink, + struct devlink_sb *devlink_sb, + u32 portid, u32 seq) +{ + struct devlink_port *devlink_port; + u16 pool_count = devlink_sb_pool_count(devlink_sb); + u16 pool_index; + int err; + + list_for_each_entry(devlink_port, &devlink->port_list, list) { + for (pool_index = 0; pool_index < pool_count; pool_index++) { + if (*p_idx < start) { + (*p_idx)++; + continue; + } + err = devlink_nl_sb_port_pool_fill(msg, devlink, + devlink_port, + devlink_sb, + pool_index, + DEVLINK_CMD_SB_PORT_POOL_NEW, + portid, seq, + NLM_F_MULTI); + if (err) + return err; + (*p_idx)++; + } + } + return 0; +} + +static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct devlink *devlink; + struct devlink_sb *devlink_sb; + int start = cb->args[0]; + int idx = 0; + int err; + + mutex_lock(&devlink_mutex); + mutex_lock(&devlink_port_mutex); + list_for_each_entry(devlink, &devlink_list, list) { + if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || + !devlink->ops || !devlink->ops->sb_port_pool_get) + continue; + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { + err = __sb_port_pool_get_dumpit(msg, start, &idx, + devlink, devlink_sb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq); + if (err && err != -EOPNOTSUPP) + goto out; + } + } +out: + mutex_unlock(&devlink_port_mutex); + mutex_unlock(&devlink_mutex); + + cb->args[0] = idx; + return msg->len; +} + +static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, + unsigned int sb_index, u16 pool_index, + u32 threshold) + +{ + const struct devlink_ops *ops = devlink_port->devlink->ops; + + if (ops && ops->sb_port_pool_set) + return ops->sb_port_pool_set(devlink_port, sb_index, + pool_index, threshold); + return -EOPNOTSUPP; +} + +static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink_port *devlink_port = info->user_ptr[0]; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + u16 pool_index; + u32 threshold; + int err; + + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, + &pool_index); + if (err) + return err; + + if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) + return -EINVAL; + + threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); + return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, + pool_index, threshold); +} + +static int +devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, + struct devlink_port *devlink_port, + struct devlink_sb *devlink_sb, u16 tc_index, + enum devlink_sb_pool_type pool_type, + enum devlink_command cmd, + u32 portid, u32 seq, int flags) +{ + u16 pool_index; + u32 threshold; + void *hdr; + int err; + + err = devlink->ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, + tc_index, pool_type, + &pool_index, &threshold); + if (err) + return err; + + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + if (devlink_nl_put_handle(msg, devlink)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) + goto nla_put_failure; + if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) + goto nla_put_failure; + if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink_port *devlink_port = info->user_ptr[0]; + struct devlink *devlink = devlink_port->devlink; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + struct sk_buff *msg; + enum devlink_sb_pool_type pool_type; + u16 tc_index; + int err; + + err = devlink_sb_pool_type_get_from_info(info, &pool_type); + if (err) + return err; + + err = devlink_sb_tc_index_get_from_info(devlink_sb, info, + pool_type, &tc_index); + if (err) + return err; + + if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get) + return -EOPNOTSUPP; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, + devlink_sb, tc_index, pool_type, + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, + info->snd_portid, + info->snd_seq, 0); + if (err) { + nlmsg_free(msg); + return err; + } + + return genlmsg_reply(msg, info); +} + +static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, + int start, int *p_idx, + struct devlink *devlink, + struct devlink_sb *devlink_sb, + u32 portid, u32 seq) +{ + struct devlink_port *devlink_port; + u16 tc_index; + int err; + + list_for_each_entry(devlink_port, &devlink->port_list, list) { + for (tc_index = 0; + tc_index < devlink_sb->ingress_tc_count; tc_index++) { + if (*p_idx < start) { + (*p_idx)++; + continue; + } + err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, + devlink_port, + devlink_sb, + tc_index, + DEVLINK_SB_POOL_TYPE_INGRESS, + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, + portid, seq, + NLM_F_MULTI); + if (err) + return err; + (*p_idx)++; + } + for (tc_index = 0; + tc_index < devlink_sb->egress_tc_count; tc_index++) { + if (*p_idx < start) { + (*p_idx)++; + continue; + } + err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, + devlink_port, + devlink_sb, + tc_index, + DEVLINK_SB_POOL_TYPE_EGRESS, + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, + portid, seq, + NLM_F_MULTI); + if (err) + return err; + (*p_idx)++; + } + } + return 0; +} + +static int +devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct devlink *devlink; + struct devlink_sb *devlink_sb; + int start = cb->args[0]; + int idx = 0; + int err; + + mutex_lock(&devlink_mutex); + mutex_lock(&devlink_port_mutex); + list_for_each_entry(devlink, &devlink_list, list) { + if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || + !devlink->ops || !devlink->ops->sb_tc_pool_bind_get) + continue; + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { + err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx, + devlink, + devlink_sb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq); + if (err && err != -EOPNOTSUPP) + goto out; + } + } +out: + mutex_unlock(&devlink_port_mutex); + mutex_unlock(&devlink_mutex); + + cb->args[0] = idx; + return msg->len; +} + +static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 pool_index, u32 threshold) + +{ + const struct devlink_ops *ops = devlink_port->devlink->ops; + + if (ops && ops->sb_tc_pool_bind_set) + return ops->sb_tc_pool_bind_set(devlink_port, sb_index, + tc_index, pool_type, + pool_index, threshold); + return -EOPNOTSUPP; +} + +static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink_port *devlink_port = info->user_ptr[0]; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + enum devlink_sb_pool_type pool_type; + u16 tc_index; + u16 pool_index; + u32 threshold; + int err; + + err = devlink_sb_pool_type_get_from_info(info, &pool_type); + if (err) + return err; + + err = devlink_sb_tc_index_get_from_info(devlink_sb, info, + pool_type, &tc_index); + if (err) + return err; + + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, + &pool_index); + if (err) + return err; + + if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) + return -EINVAL; + + threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); + return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, + tc_index, pool_type, + pool_index, threshold); +} + static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, + [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, + [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, + [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, + [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, + [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, + [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, + [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, }; static const struct genl_ops devlink_nl_ops[] = { @@ -545,6 +1379,66 @@ static const struct genl_ops devlink_nl_ops[] = { .flags = GENL_ADMIN_PERM, .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, }, + { + .cmd = DEVLINK_CMD_SB_GET, + .doit = devlink_nl_cmd_sb_get_doit, + .dumpit = devlink_nl_cmd_sb_get_dumpit, + .policy = devlink_nl_policy, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | + DEVLINK_NL_FLAG_NEED_SB, + /* can be retrieved by unprivileged users */ + }, + { + .cmd = DEVLINK_CMD_SB_POOL_GET, + .doit = devlink_nl_cmd_sb_pool_get_doit, + .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, + .policy = devlink_nl_policy, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | + DEVLINK_NL_FLAG_NEED_SB, + /* can be retrieved by unprivileged users */ + }, + { + .cmd = DEVLINK_CMD_SB_POOL_SET, + .doit = devlink_nl_cmd_sb_pool_set_doit, + .policy = devlink_nl_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | + DEVLINK_NL_FLAG_NEED_SB, + }, + { + .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, + .doit = devlink_nl_cmd_sb_port_pool_get_doit, + .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, + .policy = devlink_nl_policy, + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | + DEVLINK_NL_FLAG_NEED_SB, + /* can be retrieved by unprivileged users */ + }, + { + .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, + .doit = devlink_nl_cmd_sb_port_pool_set_doit, + .policy = devlink_nl_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | + DEVLINK_NL_FLAG_NEED_SB, + }, + { + .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, + .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, + .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, + .policy = devlink_nl_policy, + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | + DEVLINK_NL_FLAG_NEED_SB, + /* can be retrieved by unprivileged users */ + }, + { + .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, + .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, + .policy = devlink_nl_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | + DEVLINK_NL_FLAG_NEED_SB, + }, }; /** @@ -566,6 +1460,7 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) devlink->ops = ops; devlink_net_set(devlink, &init_net); INIT_LIST_HEAD(&devlink->port_list); + INIT_LIST_HEAD(&devlink->sb_list); return devlink; } EXPORT_SYMBOL_GPL(devlink_alloc); @@ -721,6 +1616,51 @@ void devlink_port_split_set(struct devlink_port *devlink_port, } EXPORT_SYMBOL_GPL(devlink_port_split_set); +int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, + u32 size, u16 ingress_pools_count, + u16 egress_pools_count, u16 ingress_tc_count, + u16 egress_tc_count) +{ + struct devlink_sb *devlink_sb; + int err = 0; + + mutex_lock(&devlink_mutex); + if (devlink_sb_index_exists(devlink, sb_index)) { + err = -EEXIST; + goto unlock; + } + + devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); + if (!devlink_sb) { + err = -ENOMEM; + goto unlock; + } + devlink_sb->index = sb_index; + devlink_sb->size = size; + devlink_sb->ingress_pools_count = ingress_pools_count; + devlink_sb->egress_pools_count = egress_pools_count; + devlink_sb->ingress_tc_count = ingress_tc_count; + devlink_sb->egress_tc_count = egress_tc_count; + list_add_tail(&devlink_sb->list, &devlink->sb_list); +unlock: + mutex_unlock(&devlink_mutex); + return err; +} +EXPORT_SYMBOL_GPL(devlink_sb_register); + +void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) +{ + struct devlink_sb *devlink_sb; + + mutex_lock(&devlink_mutex); + devlink_sb = devlink_sb_get_by_index(devlink, sb_index); + WARN_ON(!devlink_sb); + list_del(&devlink_sb->list); + mutex_unlock(&devlink_mutex); + kfree(devlink_sb); +} +EXPORT_SYMBOL_GPL(devlink_sb_unregister); + static int __init devlink_module_init(void) { return genl_register_family_with_ops_groups(&devlink_nl_family, -- GitLab From df38dafd255954ee7012785c62e615f595d5cb3c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:14 +0200 Subject: [PATCH 2811/9938] devlink: implement shared buffer occupancy monitoring interface User needs to monitor shared buffer occupancy. For that, he issues a snapshot command in order to instruct hardware to catch current and maximal occupancy values, and clear command in order to clear the historical maximal values. Also port-pool and tc-pool-bind command response messages are extended to carry occupancy values. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/devlink.h | 12 +++++ include/uapi/linux/devlink.h | 6 +++ net/core/devlink.c | 98 +++++++++++++++++++++++++++++++++--- 3 files changed, 110 insertions(+), 6 deletions(-) diff --git a/include/net/devlink.h b/include/net/devlink.h index e4c27473ee4f..be64218e0254 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -78,6 +78,18 @@ struct devlink_ops { u16 tc_index, enum devlink_sb_pool_type pool_type, u16 pool_index, u32 threshold); + int (*sb_occ_snapshot)(struct devlink *devlink, + unsigned int sb_index); + int (*sb_occ_max_clear)(struct devlink *devlink, + unsigned int sb_index); + int (*sb_occ_port_pool_get)(struct devlink_port *devlink_port, + unsigned int sb_index, u16 pool_index, + u32 *p_cur, u32 *p_max); + int (*sb_occ_tc_port_bind_get)(struct devlink_port *devlink_port, + unsigned int sb_index, + u16 tc_index, + enum devlink_sb_pool_type pool_type, + u32 *p_cur, u32 *p_max); }; static inline void *devlink_priv(struct devlink *devlink) diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 9c1aa5783090..ba0073b26fa6 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -53,6 +53,10 @@ enum devlink_command { DEVLINK_CMD_SB_TC_POOL_BIND_NEW, DEVLINK_CMD_SB_TC_POOL_BIND_DEL, + /* Shared buffer occupancy monitoring commands */ + DEVLINK_CMD_SB_OCC_SNAPSHOT, + DEVLINK_CMD_SB_OCC_MAX_CLEAR, + /* add new commands above here */ __DEVLINK_CMD_MAX, @@ -119,6 +123,8 @@ enum devlink_attr { DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, /* u8 */ DEVLINK_ATTR_SB_THRESHOLD, /* u32 */ DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ + DEVLINK_ATTR_SB_OCC_CUR, /* u32 */ + DEVLINK_ATTR_SB_OCC_MAX, /* u32 */ /* add new attributes above here, update the policy in devlink.c */ diff --git a/net/core/devlink.c b/net/core/devlink.c index aa0b9e1542e7..933e8d4d3968 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -280,6 +280,10 @@ devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, #define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) #define DEVLINK_NL_FLAG_NEED_PORT BIT(1) #define DEVLINK_NL_FLAG_NEED_SB BIT(2) +#define DEVLINK_NL_FLAG_LOCK_PORTS BIT(3) + /* port is not needed but we need to ensure they don't + * change in the middle of command + */ static int devlink_nl_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) @@ -306,6 +310,9 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, } info->user_ptr[0] = devlink_port; } + if (ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS) { + mutex_lock(&devlink_port_mutex); + } if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { struct devlink_sb *devlink_sb; @@ -324,7 +331,8 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, static void devlink_nl_post_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) { - if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) + if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT || + ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS) mutex_unlock(&devlink_port_mutex); mutex_unlock(&devlink_mutex); } @@ -942,12 +950,13 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, enum devlink_command cmd, u32 portid, u32 seq, int flags) { + const struct devlink_ops *ops = devlink->ops; u32 threshold; void *hdr; int err; - err = devlink->ops->sb_port_pool_get(devlink_port, devlink_sb->index, - pool_index, &threshold); + err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, + pool_index, &threshold); if (err) return err; @@ -966,6 +975,22 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) goto nla_put_failure; + if (ops->sb_occ_port_pool_get) { + u32 cur; + u32 max; + + err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, + pool_index, &cur, &max); + if (err && err != -EOPNOTSUPP) + return err; + if (!err) { + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) + goto nla_put_failure; + } + } + genlmsg_end(msg, hdr); return 0; @@ -1114,14 +1139,15 @@ devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, enum devlink_command cmd, u32 portid, u32 seq, int flags) { + const struct devlink_ops *ops = devlink->ops; u16 pool_index; u32 threshold; void *hdr; int err; - err = devlink->ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, - tc_index, pool_type, - &pool_index, &threshold); + err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, + tc_index, pool_type, + &pool_index, &threshold); if (err) return err; @@ -1144,6 +1170,24 @@ devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) goto nla_put_failure; + if (ops->sb_occ_tc_port_bind_get) { + u32 cur; + u32 max; + + err = ops->sb_occ_tc_port_bind_get(devlink_port, + devlink_sb->index, + tc_index, pool_type, + &cur, &max); + if (err && err != -EOPNOTSUPP) + return err; + if (!err) { + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) + goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) + goto nla_put_failure; + } + } + genlmsg_end(msg, hdr); return 0; @@ -1326,6 +1370,30 @@ static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, pool_index, threshold); } +static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink *devlink = info->user_ptr[0]; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + const struct devlink_ops *ops = devlink->ops; + + if (ops && ops->sb_occ_snapshot) + return ops->sb_occ_snapshot(devlink, devlink_sb->index); + return -EOPNOTSUPP; +} + +static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct devlink *devlink = info->user_ptr[0]; + struct devlink_sb *devlink_sb = info->user_ptr[1]; + const struct devlink_ops *ops = devlink->ops; + + if (ops && ops->sb_occ_max_clear) + return ops->sb_occ_max_clear(devlink, devlink_sb->index); + return -EOPNOTSUPP; +} + static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, @@ -1439,6 +1507,24 @@ static const struct genl_ops devlink_nl_ops[] = { .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | DEVLINK_NL_FLAG_NEED_SB, }, + { + .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, + .doit = devlink_nl_cmd_sb_occ_snapshot_doit, + .policy = devlink_nl_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | + DEVLINK_NL_FLAG_NEED_SB | + DEVLINK_NL_FLAG_LOCK_PORTS, + }, + { + .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, + .doit = devlink_nl_cmd_sb_occ_max_clear_doit, + .policy = devlink_nl_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | + DEVLINK_NL_FLAG_NEED_SB | + DEVLINK_NL_FLAG_LOCK_PORTS, + }, }; /** -- GitLab From a6179bf0d17a4d71075bad2a0b17a752fc973b64 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:15 +0200 Subject: [PATCH 2812/9938] mlxsw: core: Add devlink shared buffer callbacks Add middle layer in mlxsw core code to forward shared buffer calls into specific ASIC drivers. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 105 ++++++++++++++++++++- drivers/net/ethernet/mellanox/mlxsw/core.h | 20 ++++ 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 3958195526d1..1278260118a4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -816,9 +816,110 @@ static int mlxsw_devlink_port_unsplit(struct devlink *devlink, return mlxsw_core->driver->port_unsplit(mlxsw_core, port_index); } +static int +mlxsw_devlink_sb_pool_get(struct devlink *devlink, + unsigned int sb_index, u16 pool_index, + struct devlink_sb_pool_info *pool_info) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->sb_pool_get) + return -EOPNOTSUPP; + return mlxsw_driver->sb_pool_get(mlxsw_core, sb_index, + pool_index, pool_info); +} + +static int +mlxsw_devlink_sb_pool_set(struct devlink *devlink, + unsigned int sb_index, u16 pool_index, u32 size, + enum devlink_sb_threshold_type threshold_type) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->sb_pool_set) + return -EOPNOTSUPP; + return mlxsw_driver->sb_pool_set(mlxsw_core, sb_index, + pool_index, size, threshold_type); +} + +static void *__dl_port(struct devlink_port *devlink_port) +{ + return container_of(devlink_port, struct mlxsw_core_port, devlink_port); +} + +static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port, + unsigned int sb_index, u16 pool_index, + u32 *p_threshold) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); + + if (!mlxsw_driver->sb_port_pool_get) + return -EOPNOTSUPP; + return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index, + pool_index, p_threshold); +} + +static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port, + unsigned int sb_index, u16 pool_index, + u32 threshold) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); + + if (!mlxsw_driver->sb_port_pool_set) + return -EOPNOTSUPP; + return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index, + pool_index, threshold); +} + +static int +mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 *p_pool_index, u32 *p_threshold) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); + + if (!mlxsw_driver->sb_tc_pool_bind_get) + return -EOPNOTSUPP; + return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index, + tc_index, pool_type, + p_pool_index, p_threshold); +} + +static int +mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 pool_index, u32 threshold) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); + + if (!mlxsw_driver->sb_tc_pool_bind_set) + return -EOPNOTSUPP; + return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index, + tc_index, pool_type, + pool_index, threshold); +} + static const struct devlink_ops mlxsw_devlink_ops = { - .port_split = mlxsw_devlink_port_split, - .port_unsplit = mlxsw_devlink_port_unsplit, + .port_split = mlxsw_devlink_port_split, + .port_unsplit = mlxsw_devlink_port_unsplit, + .sb_pool_get = mlxsw_devlink_sb_pool_get, + .sb_pool_set = mlxsw_devlink_sb_pool_set, + .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get, + .sb_port_pool_set = mlxsw_devlink_sb_port_pool_set, + .sb_tc_pool_bind_get = mlxsw_devlink_sb_tc_pool_bind_get, + .sb_tc_pool_bind_set = mlxsw_devlink_sb_tc_pool_bind_set, }; int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index f3cebef9c31c..184e9853398b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -200,6 +200,26 @@ struct mlxsw_driver { int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port, unsigned int count); int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port); + int (*sb_pool_get)(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, + struct devlink_sb_pool_info *pool_info); + int (*sb_pool_set)(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, u32 size, + enum devlink_sb_threshold_type threshold_type); + int (*sb_port_pool_get)(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 *p_threshold); + int (*sb_port_pool_set)(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 threshold); + int (*sb_tc_pool_bind_get)(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 *p_pool_index, u32 *p_threshold); + int (*sb_tc_pool_bind_set)(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 pool_index, u32 threshold); void (*txhdr_construct)(struct sk_buff *skb, const struct mlxsw_tx_info *tx_info); u8 txhdr_len; -- GitLab From 94266e3278ef862bb422575a31ceb166dab1b406 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:16 +0200 Subject: [PATCH 2813/9938] mlxsw: spectrum_buffers: Push out shared buffer register writes Pushed them into helper functions. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../mellanox/mlxsw/spectrum_buffers.c | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index f58b1d3a619a..ae60838e0069 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -42,6 +42,37 @@ #include "port.h" #include "reg.h" +static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u8 pool, + enum mlxsw_reg_sbxx_dir dir, + enum mlxsw_reg_sbpr_mode mode, u32 size) +{ + char sbpr_pl[MLXSW_REG_SBPR_LEN]; + + mlxsw_reg_sbpr_pack(sbpr_pl, pool, dir, mode, size); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl); +} + +static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u8 pg_buff, enum mlxsw_reg_sbxx_dir dir, + u32 min_buff, u32 max_buff, u8 pool) +{ + char sbcm_pl[MLXSW_REG_SBCM_LEN]; + + mlxsw_reg_sbcm_pack(sbcm_pl, local_port, pg_buff, dir, + min_buff, max_buff, pool); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl); +} + +static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u8 pool, enum mlxsw_reg_sbxx_dir dir, + u32 min_buff, u32 max_buff) +{ + char sbpm_pl[MLXSW_REG_SBPM_LEN]; + + mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, min_buff, max_buff); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl); +} + struct mlxsw_sp_pb { u8 index; u16 size; @@ -151,7 +182,6 @@ static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = { static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp) { - char sbpr_pl[MLXSW_REG_SBPR_LEN]; int i; int err; @@ -159,9 +189,8 @@ static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp) const struct mlxsw_sp_sb_pool *pool; pool = &mlxsw_sp_sb_pools[i]; - mlxsw_reg_sbpr_pack(sbpr_pl, pool->pool, pool->dir, - pool->mode, pool->size); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl); + err = mlxsw_sp_sb_pr_write(mlxsw_sp, pool->pool, pool->dir, + pool->mode, pool->size); if (err) return err; } @@ -272,7 +301,6 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, const struct mlxsw_sp_sb_cm *cms, size_t cms_len) { - char sbcm_pl[MLXSW_REG_SBCM_LEN]; int i; int err; @@ -280,9 +308,9 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, const struct mlxsw_sp_sb_cm *cm; cm = &cms[i]; - mlxsw_reg_sbcm_pack(sbcm_pl, local_port, cm->u.pg, cm->dir, - cm->min_buff, cm->max_buff, cm->pool); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl); + err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, cm->u.pg, + cm->dir, cm->min_buff, + cm->max_buff, cm->pool); if (err) return err; } @@ -340,7 +368,6 @@ static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = { static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) { - char sbpm_pl[MLXSW_REG_SBPM_LEN]; int i; int err; @@ -348,11 +375,10 @@ static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) const struct mlxsw_sp_sb_pm *pm; pm = &mlxsw_sp_sb_pms[i]; - mlxsw_reg_sbpm_pack(sbpm_pl, mlxsw_sp_port->local_port, - pm->pool, pm->dir, - pm->min_buff, pm->max_buff); - err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, - MLXSW_REG(sbpm), sbpm_pl); + err = mlxsw_sp_sb_pm_write(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_port->local_port, + pm->pool, pm->dir, + pm->min_buff, pm->max_buff); if (err) return err; } -- GitLab From b11c3b4018e630dfcbdc2b9fe7aaffce5da8cfd7 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:17 +0200 Subject: [PATCH 2814/9938] mlxsw: spectrum_buffers: Push out indexes and direction out of SB structs Structs are in arrays so use array index as pool/tc/prio index. With that, there is need to maintain separate arrays for ingress and egress. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../mellanox/mlxsw/spectrum_buffers.c | 425 +++++++++--------- 1 file changed, 221 insertions(+), 204 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index ae60838e0069..c326e586bc1c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -73,27 +73,17 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl); } -struct mlxsw_sp_pb { - u8 index; - u16 size; -}; - -#define MLXSW_SP_PB(_index, _size) \ - { \ - .index = _index, \ - .size = _size, \ - } - -static const struct mlxsw_sp_pb mlxsw_sp_pbs[] = { - MLXSW_SP_PB(0, 2 * MLXSW_SP_BYTES_TO_CELLS(ETH_FRAME_LEN)), - MLXSW_SP_PB(1, 0), - MLXSW_SP_PB(2, 0), - MLXSW_SP_PB(3, 0), - MLXSW_SP_PB(4, 0), - MLXSW_SP_PB(5, 0), - MLXSW_SP_PB(6, 0), - MLXSW_SP_PB(7, 0), - MLXSW_SP_PB(9, 2 * MLXSW_SP_BYTES_TO_CELLS(MLXSW_PORT_MAX_MTU)), +static const u16 mlxsw_sp_pbs[] = { + 2 * MLXSW_SP_BYTES_TO_CELLS(ETH_FRAME_LEN), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* Unused */ + 2 * MLXSW_SP_BYTES_TO_CELLS(MLXSW_PORT_MAX_MTU), }; #define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs) @@ -106,10 +96,9 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0xffff, 0xffff / 2); for (i = 0; i < MLXSW_SP_PBS_LEN; i++) { - const struct mlxsw_sp_pb *pb; - - pb = &mlxsw_sp_pbs[i]; - mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pb->index, pb->size); + if (i == 8) + continue; + mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, mlxsw_sp_pbs[i]); } mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, MLXSW_REG_PBMC_PORT_SHARED_BUF_IDX, 0); @@ -140,8 +129,6 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) } struct mlxsw_sp_sb_pool { - u8 pool; - enum mlxsw_reg_sbxx_dir dir; enum mlxsw_reg_sbpr_mode mode; u32 size; }; @@ -151,45 +138,46 @@ struct mlxsw_sp_sb_pool { #define MLXSW_SP_SB_POOL_EGRESS_SIZE \ (14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) -#define MLXSW_SP_SB_POOL(_pool, _dir, _mode, _size) \ - { \ - .pool = _pool, \ - .dir = _dir, \ - .mode = _mode, \ - .size = _size, \ +#define MLXSW_SP_SB_POOL(_mode, _size) \ + { \ + .mode = _mode, \ + .size = _size, \ } -#define MLXSW_SP_SB_POOL_INGRESS(_pool, _size) \ - MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_INGRESS, \ - MLXSW_REG_SBPR_MODE_DYNAMIC, _size) - -#define MLXSW_SP_SB_POOL_EGRESS(_pool, _size) \ - MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_EGRESS, \ - MLXSW_REG_SBPR_MODE_DYNAMIC, _size) - -static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = { - MLXSW_SP_SB_POOL_INGRESS(0, MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_INGRESS_SIZE)), - MLXSW_SP_SB_POOL_INGRESS(1, 0), - MLXSW_SP_SB_POOL_INGRESS(2, 0), - MLXSW_SP_SB_POOL_INGRESS(3, 0), - MLXSW_SP_SB_POOL_EGRESS(0, MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), - MLXSW_SP_SB_POOL_EGRESS(1, 0), - MLXSW_SP_SB_POOL_EGRESS(2, 0), - MLXSW_SP_SB_POOL_EGRESS(2, MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), +static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_ingress[] = { + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_INGRESS_SIZE)), + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), }; -#define MLXSW_SP_SB_POOLS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools) +#define MLXSW_SP_SB_POOLS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_ingress) -static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp) +static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_egress[] = { + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), +}; + +#define MLXSW_SP_SB_POOLS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_egress) + +static int __mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp, + enum mlxsw_reg_sbxx_dir dir, + const struct mlxsw_sp_sb_pool *pools, + size_t pools_len) { int i; int err; - for (i = 0; i < MLXSW_SP_SB_POOLS_LEN; i++) { + for (i = 0; i < pools_len; i++) { const struct mlxsw_sp_sb_pool *pool; - pool = &mlxsw_sp_sb_pools[i]; - err = mlxsw_sp_sb_pr_write(mlxsw_sp, pool->pool, pool->dir, + pool = &pools[i]; + err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, dir, pool->mode, pool->size); if (err) return err; @@ -197,109 +185,114 @@ static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp) return 0; } +static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp) +{ + int err; + + err = __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_INGRESS, + mlxsw_sp_sb_pools_ingress, + MLXSW_SP_SB_POOLS_INGRESS_LEN); + if (err) + return err; + return __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_EGRESS, + mlxsw_sp_sb_pools_egress, + MLXSW_SP_SB_POOLS_EGRESS_LEN); +} + struct mlxsw_sp_sb_cm { - union { - u8 pg; - u8 tc; - } u; - enum mlxsw_reg_sbxx_dir dir; u32 min_buff; u32 max_buff; u8 pool; }; -#define MLXSW_SP_SB_CM(_pg_tc, _dir, _min_buff, _max_buff, _pool) \ - { \ - .u.pg = _pg_tc, \ - .dir = _dir, \ - .min_buff = _min_buff, \ - .max_buff = _max_buff, \ - .pool = _pool, \ +#define MLXSW_SP_SB_CM(_min_buff, _max_buff, _pool) \ + { \ + .min_buff = _min_buff, \ + .max_buff = _max_buff, \ + .pool = _pool, \ } -#define MLXSW_SP_SB_CM_INGRESS(_pg, _min_buff, _max_buff) \ - MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBXX_DIR_INGRESS, \ - _min_buff, _max_buff, 0) - -#define MLXSW_SP_SB_CM_EGRESS(_tc, _min_buff, _max_buff) \ - MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS, \ - _min_buff, _max_buff, 0) - -#define MLXSW_SP_CPU_PORT_SB_CM_EGRESS(_tc) \ - MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS, 104, 2, 3) - -static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = { - MLXSW_SP_SB_CM_INGRESS(0, MLXSW_SP_BYTES_TO_CELLS(10000), 8), - MLXSW_SP_SB_CM_INGRESS(1, 0, 0), - MLXSW_SP_SB_CM_INGRESS(2, 0, 0), - MLXSW_SP_SB_CM_INGRESS(3, 0, 0), - MLXSW_SP_SB_CM_INGRESS(4, 0, 0), - MLXSW_SP_SB_CM_INGRESS(5, 0, 0), - MLXSW_SP_SB_CM_INGRESS(6, 0, 0), - MLXSW_SP_SB_CM_INGRESS(7, 0, 0), - MLXSW_SP_SB_CM_INGRESS(9, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff), - MLXSW_SP_SB_CM_EGRESS(0, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(1, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(2, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(3, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(4, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(5, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(6, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(7, MLXSW_SP_BYTES_TO_CELLS(1500), 9), - MLXSW_SP_SB_CM_EGRESS(8, 0, 0), - MLXSW_SP_SB_CM_EGRESS(9, 0, 0), - MLXSW_SP_SB_CM_EGRESS(10, 0, 0), - MLXSW_SP_SB_CM_EGRESS(11, 0, 0), - MLXSW_SP_SB_CM_EGRESS(12, 0, 0), - MLXSW_SP_SB_CM_EGRESS(13, 0, 0), - MLXSW_SP_SB_CM_EGRESS(14, 0, 0), - MLXSW_SP_SB_CM_EGRESS(15, 0, 0), - MLXSW_SP_SB_CM_EGRESS(16, 1, 0xff), +static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = { + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(10000), 8, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), /* dummy, this PG does not exist */ + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), }; -#define MLXSW_SP_SB_CMS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms) +#define MLXSW_SP_SB_CMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_ingress) + +static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = { + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(1500), 9, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(1, 0xff, 0), +}; + +#define MLXSW_SP_SB_CMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_egress) + +#define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(104, 2, 3) static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = { - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(0), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(1), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(2), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(3), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(4), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(5), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(6), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(7), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(8), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(9), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(10), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(11), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(12), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(13), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(14), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(15), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(16), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(17), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(18), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(19), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(20), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(21), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(22), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(23), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(24), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(25), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(26), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(27), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(28), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(29), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(30), - MLXSW_SP_CPU_PORT_SB_CM_EGRESS(31), + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, + MLXSW_SP_CPU_PORT_SB_CM, }; #define MLXSW_SP_CPU_PORT_SB_MCS_LEN \ ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms) -static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, - const struct mlxsw_sp_sb_cm *cms, - size_t cms_len) +static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, + enum mlxsw_reg_sbxx_dir dir, + const struct mlxsw_sp_sb_cm *cms, + size_t cms_len) { int i; int err; @@ -307,10 +300,12 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, for (i = 0; i < cms_len; i++) { const struct mlxsw_sp_sb_cm *cm; + if (i == 8 && dir == MLXSW_REG_SBXX_DIR_INGRESS) + continue; /* PG number 8 does not exist, skip it */ cm = &cms[i]; - err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, cm->u.pg, - cm->dir, cm->min_buff, - cm->max_buff, cm->pool); + err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, i, dir, + cm->min_buff, cm->max_buff, + cm->pool); if (err) return err; } @@ -319,65 +314,71 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port) { - return mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp, - mlxsw_sp_port->local_port, mlxsw_sp_sb_cms, - MLXSW_SP_SB_CMS_LEN); + int err; + + err = __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_port->local_port, + MLXSW_REG_SBXX_DIR_INGRESS, + mlxsw_sp_sb_cms_ingress, + MLXSW_SP_SB_CMS_INGRESS_LEN); + if (err) + return err; + return __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_port->local_port, + MLXSW_REG_SBXX_DIR_EGRESS, + mlxsw_sp_sb_cms_egress, + MLXSW_SP_SB_CMS_EGRESS_LEN); } static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp) { - return mlxsw_sp_sb_cms_init(mlxsw_sp, 0, mlxsw_sp_cpu_port_sb_cms, - MLXSW_SP_CPU_PORT_SB_MCS_LEN); + return __mlxsw_sp_sb_cms_init(mlxsw_sp, 0, MLXSW_REG_SBXX_DIR_EGRESS, + mlxsw_sp_cpu_port_sb_cms, + MLXSW_SP_CPU_PORT_SB_MCS_LEN); } struct mlxsw_sp_sb_pm { - u8 pool; - enum mlxsw_reg_sbxx_dir dir; u32 min_buff; u32 max_buff; }; -#define MLXSW_SP_SB_PM(_pool, _dir, _min_buff, _max_buff) \ - { \ - .pool = _pool, \ - .dir = _dir, \ - .min_buff = _min_buff, \ - .max_buff = _max_buff, \ +#define MLXSW_SP_SB_PM(_min_buff, _max_buff) \ + { \ + .min_buff = _min_buff, \ + .max_buff = _max_buff, \ } -#define MLXSW_SP_SB_PM_INGRESS(_pool, _min_buff, _max_buff) \ - MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_INGRESS, \ - _min_buff, _max_buff) - -#define MLXSW_SP_SB_PM_EGRESS(_pool, _min_buff, _max_buff) \ - MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_EGRESS, \ - _min_buff, _max_buff) - -static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = { - MLXSW_SP_SB_PM_INGRESS(0, 0, 0xff), - MLXSW_SP_SB_PM_INGRESS(1, 0, 0), - MLXSW_SP_SB_PM_INGRESS(2, 0, 0), - MLXSW_SP_SB_PM_INGRESS(3, 0, 0), - MLXSW_SP_SB_PM_EGRESS(0, 0, 7), - MLXSW_SP_SB_PM_EGRESS(1, 0, 0), - MLXSW_SP_SB_PM_EGRESS(2, 0, 0), - MLXSW_SP_SB_PM_EGRESS(3, 0, 0), +static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_ingress[] = { + MLXSW_SP_SB_PM(0, 0xff), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0), }; -#define MLXSW_SP_SB_PMS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms) +#define MLXSW_SP_SB_PMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_ingress) -static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) +static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_egress[] = { + MLXSW_SP_SB_PM(0, 7), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0), +}; + +#define MLXSW_SP_SB_PMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_egress) + +static int __mlxsw_sp_port_sb_pms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, + enum mlxsw_reg_sbxx_dir dir, + const struct mlxsw_sp_sb_pm *pms, + size_t pms_len) { int i; int err; - for (i = 0; i < MLXSW_SP_SB_PMS_LEN; i++) { + for (i = 0; i < pms_len; i++) { const struct mlxsw_sp_sb_pm *pm; - pm = &mlxsw_sp_sb_pms[i]; - err = mlxsw_sp_sb_pm_write(mlxsw_sp_port->mlxsw_sp, - mlxsw_sp_port->local_port, - pm->pool, pm->dir, + pm = &pms[i]; + err = mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, i, dir, pm->min_buff, pm->max_buff); if (err) return err; @@ -385,37 +386,53 @@ static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) return 0; } +static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + int err; + + err = __mlxsw_sp_port_sb_pms_init(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_port->local_port, + MLXSW_REG_SBXX_DIR_INGRESS, + mlxsw_sp_sb_pms_ingress, + MLXSW_SP_SB_PMS_INGRESS_LEN); + if (err) + return err; + return __mlxsw_sp_port_sb_pms_init(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_port->local_port, + MLXSW_REG_SBXX_DIR_EGRESS, + mlxsw_sp_sb_pms_egress, + MLXSW_SP_SB_PMS_EGRESS_LEN); +} + struct mlxsw_sp_sb_mm { - u8 prio; u32 min_buff; u32 max_buff; u8 pool; }; -#define MLXSW_SP_SB_MM(_prio, _min_buff, _max_buff, _pool) \ - { \ - .prio = _prio, \ - .min_buff = _min_buff, \ - .max_buff = _max_buff, \ - .pool = _pool, \ +#define MLXSW_SP_SB_MM(_min_buff, _max_buff, _pool) \ + { \ + .min_buff = _min_buff, \ + .max_buff = _max_buff, \ + .pool = _pool, \ } static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = { - MLXSW_SP_SB_MM(0, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(1, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(2, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(3, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(4, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(5, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(6, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(7, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(8, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(9, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(10, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(11, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(12, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(13, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), - MLXSW_SP_SB_MM(14, MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_MM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), }; #define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms) @@ -430,7 +447,7 @@ static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) const struct mlxsw_sp_sb_mm *mc; mc = &mlxsw_sp_sb_mms[i]; - mlxsw_reg_sbmm_pack(sbmm_pl, mc->prio, mc->min_buff, + mlxsw_reg_sbmm_pack(sbmm_pl, i, mc->min_buff, mc->max_buff, mc->pool); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl); if (err) -- GitLab From aa99bc70bac1bb6815ad30248d0e34b14cdec575 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:18 +0200 Subject: [PATCH 2815/9938] mlxsw: spectrum_buffers: Rename "pool" to "pr" in initialization Be consintent with rest of the registers (pm, cm) and use "pr" here. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../mellanox/mlxsw/spectrum_buffers.c | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index c326e586bc1c..15bd5aa23a2c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -128,75 +128,75 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port); } -struct mlxsw_sp_sb_pool { +struct mlxsw_sp_sb_pr { enum mlxsw_reg_sbpr_mode mode; u32 size; }; -#define MLXSW_SP_SB_POOL_INGRESS_SIZE \ +#define MLXSW_SP_SB_PR_INGRESS_SIZE \ (15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) -#define MLXSW_SP_SB_POOL_EGRESS_SIZE \ +#define MLXSW_SP_SB_PR_EGRESS_SIZE \ (14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) -#define MLXSW_SP_SB_POOL(_mode, _size) \ +#define MLXSW_SP_SB_PR(_mode, _size) \ { \ .mode = _mode, \ .size = _size, \ } -static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_ingress[] = { - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, - MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_INGRESS_SIZE)), - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), +static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_ingress[] = { + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_PR_INGRESS_SIZE)), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), }; -#define MLXSW_SP_SB_POOLS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_ingress) +#define MLXSW_SP_SB_PRS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_ingress) -static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_egress[] = { - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, - MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), - MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, - MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_POOL_EGRESS_SIZE)), +static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_egress[] = { + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_PR_EGRESS_SIZE)), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_PR_EGRESS_SIZE)), }; -#define MLXSW_SP_SB_POOLS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_egress) +#define MLXSW_SP_SB_PRS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_egress) -static int __mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp, - enum mlxsw_reg_sbxx_dir dir, - const struct mlxsw_sp_sb_pool *pools, - size_t pools_len) +static int __mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp, + enum mlxsw_reg_sbxx_dir dir, + const struct mlxsw_sp_sb_pr *prs, + size_t prs_len) { int i; int err; - for (i = 0; i < pools_len; i++) { - const struct mlxsw_sp_sb_pool *pool; + for (i = 0; i < prs_len; i++) { + const struct mlxsw_sp_sb_pr *pr; - pool = &pools[i]; + pr = &prs[i]; err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, dir, - pool->mode, pool->size); + pr->mode, pr->size); if (err) return err; } return 0; } -static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp) +static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp) { int err; - err = __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_INGRESS, - mlxsw_sp_sb_pools_ingress, - MLXSW_SP_SB_POOLS_INGRESS_LEN); + err = __mlxsw_sp_sb_prs_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_INGRESS, + mlxsw_sp_sb_prs_ingress, + MLXSW_SP_SB_PRS_INGRESS_LEN); if (err) return err; - return __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_EGRESS, - mlxsw_sp_sb_pools_egress, - MLXSW_SP_SB_POOLS_EGRESS_LEN); + return __mlxsw_sp_sb_prs_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_EGRESS, + mlxsw_sp_sb_prs_egress, + MLXSW_SP_SB_PRS_EGRESS_LEN); } struct mlxsw_sp_sb_cm { @@ -460,7 +460,7 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) { int err; - err = mlxsw_sp_sb_pools_init(mlxsw_sp); + err = mlxsw_sp_sb_prs_init(mlxsw_sp); if (err) return err; err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp); -- GitLab From 078f9c7132cbbe12c2484a817ca5f477d1641b61 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:19 +0200 Subject: [PATCH 2816/9938] mlxsw: spectrum_buffers: Cache shared buffer configuration In order to achieve faster dumping of current setting and also in order to provide possibility to get pool mode without a need to query hardware, do cache the configuration in driver. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.h | 28 +++++++ .../mellanox/mlxsw/spectrum_buffers.c | 73 ++++++++++++++----- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 361b0c270b56..790c292b3230 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -117,6 +117,33 @@ static inline bool mlxsw_sp_fid_is_vfid(u16 fid) return fid >= MLXSW_SP_VFID_BASE; } +struct mlxsw_sp_sb_pr { + enum mlxsw_reg_sbpr_mode mode; + u32 size; +}; + +struct mlxsw_sp_sb_cm { + u32 min_buff; + u32 max_buff; + u8 pool; +}; + +struct mlxsw_sp_sb_pm { + u32 min_buff; + u32 max_buff; +}; + +#define MLXSW_SP_SB_POOL_COUNT 4 +#define MLXSW_SP_SB_TC_COUNT 8 + +struct mlxsw_sp_sb { + struct mlxsw_sp_sb_pr prs[2][MLXSW_SP_SB_POOL_COUNT]; + struct { + struct mlxsw_sp_sb_cm cms[2][MLXSW_SP_SB_TC_COUNT]; + struct mlxsw_sp_sb_pm pms[2][MLXSW_SP_SB_POOL_COUNT]; + } ports[MLXSW_PORT_MAX_PORTS]; +}; + struct mlxsw_sp { struct { struct list_head list; @@ -147,6 +174,7 @@ struct mlxsw_sp { struct mlxsw_sp_upper master_bridge; struct mlxsw_sp_upper lags[MLXSW_SP_LAG_MAX]; u8 port_to_module[MLXSW_PORT_MAX_PORTS]; + struct mlxsw_sp_sb sb; }; static inline struct mlxsw_sp_upper * diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 15bd5aa23a2c..b43f7d36ec64 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -42,14 +42,44 @@ #include "port.h" #include "reg.h" +static struct mlxsw_sp_sb_pr *mlxsw_sp_sb_pr_get(struct mlxsw_sp *mlxsw_sp, + u8 pool, + enum mlxsw_reg_sbxx_dir dir) +{ + return &mlxsw_sp->sb.prs[dir][pool]; +} + +static struct mlxsw_sp_sb_cm *mlxsw_sp_sb_cm_get(struct mlxsw_sp *mlxsw_sp, + u8 local_port, u8 pg_buff, + enum mlxsw_reg_sbxx_dir dir) +{ + return &mlxsw_sp->sb.ports[local_port].cms[dir][pg_buff]; +} + +static struct mlxsw_sp_sb_pm *mlxsw_sp_sb_pm_get(struct mlxsw_sp *mlxsw_sp, + u8 local_port, u8 pool, + enum mlxsw_reg_sbxx_dir dir) +{ + return &mlxsw_sp->sb.ports[local_port].pms[dir][pool]; +} + static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u8 pool, enum mlxsw_reg_sbxx_dir dir, enum mlxsw_reg_sbpr_mode mode, u32 size) { char sbpr_pl[MLXSW_REG_SBPR_LEN]; + struct mlxsw_sp_sb_pr *pr; + int err; mlxsw_reg_sbpr_pack(sbpr_pl, pool, dir, mode, size); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl); + if (err) + return err; + + pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir); + pr->mode = mode; + pr->size = size; + return 0; } static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, @@ -57,10 +87,22 @@ static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, u32 min_buff, u32 max_buff, u8 pool) { char sbcm_pl[MLXSW_REG_SBCM_LEN]; + int err; mlxsw_reg_sbcm_pack(sbcm_pl, local_port, pg_buff, dir, min_buff, max_buff, pool); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl); + if (err) + return err; + if (pg_buff < MLXSW_SP_SB_TC_COUNT) { + struct mlxsw_sp_sb_cm *cm; + + cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, pg_buff, dir); + cm->min_buff = min_buff; + cm->max_buff = max_buff; + cm->pool = pool; + } + return 0; } static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, @@ -68,9 +110,18 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, u32 min_buff, u32 max_buff) { char sbpm_pl[MLXSW_REG_SBPM_LEN]; + struct mlxsw_sp_sb_pm *pm; + int err; mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, min_buff, max_buff); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl); + if (err) + return err; + + pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool, dir); + pm->min_buff = min_buff; + pm->max_buff = max_buff; + return 0; } static const u16 mlxsw_sp_pbs[] = { @@ -128,11 +179,6 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port); } -struct mlxsw_sp_sb_pr { - enum mlxsw_reg_sbpr_mode mode; - u32 size; -}; - #define MLXSW_SP_SB_PR_INGRESS_SIZE \ (15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) #define MLXSW_SP_SB_PR_EGRESS_SIZE \ @@ -199,12 +245,6 @@ static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp) MLXSW_SP_SB_PRS_EGRESS_LEN); } -struct mlxsw_sp_sb_cm { - u32 min_buff; - u32 max_buff; - u8 pool; -}; - #define MLXSW_SP_SB_CM(_min_buff, _max_buff, _pool) \ { \ .min_buff = _min_buff, \ @@ -337,11 +377,6 @@ static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp) MLXSW_SP_CPU_PORT_SB_MCS_LEN); } -struct mlxsw_sp_sb_pm { - u32 min_buff; - u32 max_buff; -}; - #define MLXSW_SP_SB_PM(_min_buff, _max_buff) \ { \ .min_buff = _min_buff, \ -- GitLab From 5408f7cba341b26edf2fa5bcaaa37e52301830e2 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:20 +0200 Subject: [PATCH 2817/9938] mlxsw: spectrum_buffers: Remove eg pool 3 default init and CPU port TC binding to it Since there is no congestion control for CPU port traffic, we can change the CPU port TC binding to pool 0 with min_buff and max_buff zeroed. Remove initialization for pool egress pool 3 since it is no longer used by dafault. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index b43f7d36ec64..dc57d779ef9d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -205,8 +205,7 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_egress[] = { MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_PR_EGRESS_SIZE)), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), - MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, - MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_PR_EGRESS_SIZE)), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), }; #define MLXSW_SP_SB_PRS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_egress) @@ -289,7 +288,7 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = { #define MLXSW_SP_SB_CMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_egress) -#define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(104, 2, 3) +#define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(0, 0, 0) static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = { MLXSW_SP_CPU_PORT_SB_CM, -- GitLab From bc872506f58c21d1ee44b1303a5f5d00354e72c5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:21 +0200 Subject: [PATCH 2818/9938] mlxsw: spectrum_buffers: Change initialization of PG 9 As explained in commit ff6551ec0c27 ("mlxsw: spectrum: Correctly configure headroom size") control packets are directed to priority group buffer 9 (PG9) in the ports' headroom buffers. Since we don't want to drop control packets in case they can't be admitted to the switch's shared buffer we bind PG9 to a different ingress pool from the one used by all other PGs. Unlike other PGs, we currently don't expose the binding between PG9 to a pool and leave it fixed. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index dc57d779ef9d..7ee2315c11f5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -181,6 +181,7 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) #define MLXSW_SP_SB_PR_INGRESS_SIZE \ (15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) +#define MLXSW_SP_SB_PR_INGRESS_MNG_SIZE (200 * 1000) #define MLXSW_SP_SB_PR_EGRESS_SIZE \ (14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) @@ -195,7 +196,8 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_ingress[] = { MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_PR_INGRESS_SIZE)), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), - MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP_BYTES_TO_CELLS(MLXSW_SP_SB_PR_INGRESS_MNG_SIZE)), }; #define MLXSW_SP_SB_PRS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_ingress) @@ -261,7 +263,7 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = { MLXSW_SP_SB_CM(0, 0, 0), MLXSW_SP_SB_CM(0, 0, 0), MLXSW_SP_SB_CM(0, 0, 0), /* dummy, this PG does not exist */ - MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(20000), 0xff, 0), + MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(20000), 1, 3), }; #define MLXSW_SP_SB_CMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_ingress) @@ -386,7 +388,7 @@ static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_ingress[] = { MLXSW_SP_SB_PM(0, 0xff), MLXSW_SP_SB_PM(0, 0), MLXSW_SP_SB_PM(0, 0), - MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0xff), }; #define MLXSW_SP_SB_PMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_ingress) -- GitLab From c30a53c7de5e52249cd5381078f84082449ecc86 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:22 +0200 Subject: [PATCH 2819/9938] mlxsw: spectrum_buffers: Get max_buff defaults into limits exposed to user Although the device supports max_buff magic values 0 and 0xff, these are not exposed to the user via devlink. Therefore, adjust the default values to be within configurable range. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 4 +++ .../mellanox/mlxsw/spectrum_buffers.c | 28 +++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 57e4a6337ae3..fce5a962bf74 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3566,6 +3566,10 @@ MLXSW_ITEM32(reg, sbcm, dir, 0x00, 0, 2); */ MLXSW_ITEM32(reg, sbcm, min_buff, 0x18, 0, 24); +/* shared max_buff limits for dynamic threshold for SBCM, SBPM */ +#define MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN 1 +#define MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX 14 + /* reg_sbcm_max_buff * When the pool associated to the port-pg/tclass is configured to * static, Maximum buffer size for the limiter configured in cells. diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 7ee2315c11f5..fd6b08022e28 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -255,13 +255,13 @@ static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp) static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = { MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(10000), 8, 0), - MLXSW_SP_SB_CM(0, 0, 0), - MLXSW_SP_SB_CM(0, 0, 0), - MLXSW_SP_SB_CM(0, 0, 0), - MLXSW_SP_SB_CM(0, 0, 0), - MLXSW_SP_SB_CM(0, 0, 0), - MLXSW_SP_SB_CM(0, 0, 0), - MLXSW_SP_SB_CM(0, 0, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), MLXSW_SP_SB_CM(0, 0, 0), /* dummy, this PG does not exist */ MLXSW_SP_SB_CM(MLXSW_SP_BYTES_TO_CELLS(20000), 1, 3), }; @@ -385,19 +385,19 @@ static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp) } static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_ingress[] = { - MLXSW_SP_SB_PM(0, 0xff), - MLXSW_SP_SB_PM(0, 0), - MLXSW_SP_SB_PM(0, 0), - MLXSW_SP_SB_PM(0, 0xff), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX), }; #define MLXSW_SP_SB_PMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_ingress) static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_egress[] = { MLXSW_SP_SB_PM(0, 7), - MLXSW_SP_SB_PM(0, 0), - MLXSW_SP_SB_PM(0, 0), - MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN), }; #define MLXSW_SP_SB_PMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_egress) -- GitLab From 325f2f197d730bb7f6f1af2ce93fedfd728e3eed Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:23 +0200 Subject: [PATCH 2820/9938] mlxsw: core: Add mlxsw_core_port_driver_priv helper Needed in following patch. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 184e9853398b..d0c471f26748 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -137,6 +137,15 @@ struct mlxsw_core_port { struct devlink_port devlink_port; }; +static inline void * +mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) +{ + /* mlxsw_core_port is ensured to always be the first field in driver + * port structure. + */ + return mlxsw_core_port; +} + int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, struct mlxsw_core_port *mlxsw_core_port, u8 local_port, struct net_device *dev, bool split, u32 split_group); -- GitLab From 0f433fa0ecc59c1d0792937a26436bec8dd42b6d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:24 +0200 Subject: [PATCH 2821/9938] mlxsw: spectrum_buffers: Implement shared buffer configuration Implement previously introduced mlxsw core shared buffer API. For Spectrum, that is done utilizing registers SBPR, SBCM and SBPM. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 8 + .../net/ethernet/mellanox/mlxsw/spectrum.h | 22 +++ .../mellanox/mlxsw/spectrum_buffers.c | 187 +++++++++++++++++- 3 files changed, 216 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 19b3c144abc6..ecadb15c4907 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2434,6 +2434,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, err_switchdev_init: err_lag_init: + mlxsw_sp_buffers_fini(mlxsw_sp); err_buffers_init: err_flood_init: mlxsw_sp_traps_fini(mlxsw_sp); @@ -2448,6 +2449,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + mlxsw_sp_buffers_fini(mlxsw_sp); mlxsw_sp_switchdev_fini(mlxsw_sp); mlxsw_sp_traps_fini(mlxsw_sp); mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE); @@ -2498,6 +2500,12 @@ static struct mlxsw_driver mlxsw_sp_driver = { .fini = mlxsw_sp_fini, .port_split = mlxsw_sp_port_split, .port_unsplit = mlxsw_sp_port_unsplit, + .sb_pool_get = mlxsw_sp_sb_pool_get, + .sb_pool_set = mlxsw_sp_sb_pool_set, + .sb_port_pool_get = mlxsw_sp_sb_port_pool_get, + .sb_port_pool_set = mlxsw_sp_sb_port_pool_set, + .sb_tc_pool_bind_get = mlxsw_sp_sb_tc_pool_bind_get, + .sb_tc_pool_bind_set = mlxsw_sp_sb_tc_pool_bind_set, .txhdr_construct = mlxsw_sp_txhdr_construct, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sp_config_profile, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 790c292b3230..6458efa5607e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -65,6 +65,7 @@ #define MLXSW_SP_BYTES_PER_CELL 96 #define MLXSW_SP_BYTES_TO_CELLS(b) DIV_ROUND_UP(b, MLXSW_SP_BYTES_PER_CELL) +#define MLXSW_SP_CELLS_TO_BYTES(c) (c * MLXSW_SP_BYTES_PER_CELL) /* Maximum delay buffer needed in case of PAUSE frames, in cells. * Assumes 100m cable and maximum MTU. @@ -305,7 +306,28 @@ enum mlxsw_sp_flood_table { }; int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp); +void mlxsw_sp_buffers_fini(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port); +int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, + struct devlink_sb_pool_info *pool_info); +int mlxsw_sp_sb_pool_set(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, u32 size, + enum devlink_sb_threshold_type threshold_type); +int mlxsw_sp_sb_port_pool_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 *p_threshold); +int mlxsw_sp_sb_port_pool_set(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 threshold); +int mlxsw_sp_sb_tc_pool_bind_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 *p_pool_index, u32 *p_threshold); +int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 pool_index, u32 threshold); int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index fd6b08022e28..6042c1741f77 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -492,6 +492,8 @@ static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) return 0; } +#define MLXSW_SP_SB_SIZE (16 * 1024 * 1024) + int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) { int err; @@ -503,8 +505,19 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) if (err) return err; err = mlxsw_sp_sb_mms_init(mlxsw_sp); + if (err) + return err; + return devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0, + MLXSW_SP_SB_SIZE, + MLXSW_SP_SB_POOL_COUNT, + MLXSW_SP_SB_POOL_COUNT, + MLXSW_SP_SB_TC_COUNT, + MLXSW_SP_SB_TC_COUNT); +} - return err; +void mlxsw_sp_buffers_fini(struct mlxsw_sp *mlxsw_sp) +{ + devlink_sb_unregister(priv_to_devlink(mlxsw_sp->core), 0); } int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port) @@ -521,3 +534,175 @@ int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port) return err; } + +static u8 pool_get(u16 pool_index) +{ + return pool_index % MLXSW_SP_SB_POOL_COUNT; +} + +static u16 pool_index_get(u8 pool, enum mlxsw_reg_sbxx_dir dir) +{ + u16 pool_index; + + pool_index = pool; + if (dir == MLXSW_REG_SBXX_DIR_EGRESS) + pool_index += MLXSW_SP_SB_POOL_COUNT; + return pool_index; +} + +static enum mlxsw_reg_sbxx_dir dir_get(u16 pool_index) +{ + return pool_index < MLXSW_SP_SB_POOL_COUNT ? + MLXSW_REG_SBXX_DIR_INGRESS : MLXSW_REG_SBXX_DIR_EGRESS; +} + +int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, + struct devlink_sb_pool_info *pool_info) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + u8 pool = pool_get(pool_index); + enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index); + struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir); + + pool_info->pool_type = dir; + pool_info->size = MLXSW_SP_CELLS_TO_BYTES(pr->size); + pool_info->threshold_type = pr->mode; + return 0; +} + +int mlxsw_sp_sb_pool_set(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, u32 size, + enum devlink_sb_threshold_type threshold_type) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + u8 pool = pool_get(pool_index); + enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index); + enum mlxsw_reg_sbpr_mode mode = threshold_type; + u32 pool_size = MLXSW_SP_BYTES_TO_CELLS(size); + + return mlxsw_sp_sb_pr_write(mlxsw_sp, pool, dir, mode, pool_size); +} + +#define MLXSW_SP_SB_THRESHOLD_TO_ALPHA_OFFSET (-2) /* 3->1, 16->14 */ + +static u32 mlxsw_sp_sb_threshold_out(struct mlxsw_sp *mlxsw_sp, u8 pool, + enum mlxsw_reg_sbxx_dir dir, u32 max_buff) +{ + struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir); + + if (pr->mode == MLXSW_REG_SBPR_MODE_DYNAMIC) + return max_buff - MLXSW_SP_SB_THRESHOLD_TO_ALPHA_OFFSET; + return MLXSW_SP_CELLS_TO_BYTES(max_buff); +} + +static int mlxsw_sp_sb_threshold_in(struct mlxsw_sp *mlxsw_sp, u8 pool, + enum mlxsw_reg_sbxx_dir dir, u32 threshold, + u32 *p_max_buff) +{ + struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir); + + if (pr->mode == MLXSW_REG_SBPR_MODE_DYNAMIC) { + int val; + + val = threshold + MLXSW_SP_SB_THRESHOLD_TO_ALPHA_OFFSET; + if (val < MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN || + val > MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX) + return -EINVAL; + *p_max_buff = val; + } else { + *p_max_buff = MLXSW_SP_BYTES_TO_CELLS(threshold); + } + return 0; +} + +int mlxsw_sp_sb_port_pool_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 *p_threshold) +{ + struct mlxsw_sp_port *mlxsw_sp_port = + mlxsw_core_port_driver_priv(mlxsw_core_port); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 local_port = mlxsw_sp_port->local_port; + u8 pool = pool_get(pool_index); + enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index); + struct mlxsw_sp_sb_pm *pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, + pool, dir); + + *p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, pool, dir, + pm->max_buff); + return 0; +} + +int mlxsw_sp_sb_port_pool_set(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 threshold) +{ + struct mlxsw_sp_port *mlxsw_sp_port = + mlxsw_core_port_driver_priv(mlxsw_core_port); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 local_port = mlxsw_sp_port->local_port; + u8 pool = pool_get(pool_index); + enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index); + u32 max_buff; + int err; + + err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool, dir, + threshold, &max_buff); + if (err) + return err; + + return mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, pool, dir, + 0, max_buff); +} + +int mlxsw_sp_sb_tc_pool_bind_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 *p_pool_index, u32 *p_threshold) +{ + struct mlxsw_sp_port *mlxsw_sp_port = + mlxsw_core_port_driver_priv(mlxsw_core_port); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 local_port = mlxsw_sp_port->local_port; + u8 pg_buff = tc_index; + enum mlxsw_reg_sbxx_dir dir = pool_type; + struct mlxsw_sp_sb_cm *cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, + pg_buff, dir); + + *p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, cm->pool, dir, + cm->max_buff); + *p_pool_index = pool_index_get(cm->pool, pool_type); + return 0; +} + +int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u16 pool_index, u32 threshold) +{ + struct mlxsw_sp_port *mlxsw_sp_port = + mlxsw_core_port_driver_priv(mlxsw_core_port); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 local_port = mlxsw_sp_port->local_port; + u8 pg_buff = tc_index; + enum mlxsw_reg_sbxx_dir dir = pool_type; + u8 pool = pool_index; + u32 max_buff; + int err; + + err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool, dir, + threshold, &max_buff); + if (err) + return err; + + if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS) { + if (pool < MLXSW_SP_SB_POOL_COUNT) + return -EINVAL; + pool -= MLXSW_SP_SB_POOL_COUNT; + } else if (pool >= MLXSW_SP_SB_POOL_COUNT) { + return -EINVAL; + } + return mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, pg_buff, dir, + 0, max_buff, pool); +} -- GitLab From 1ceecc88d29bbbb0f8d0e49e3bf6d020dc582934 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:25 +0200 Subject: [PATCH 2822/9938] mlxsw: core: Add devlink shared buffer occupancy callbacks Add middle layer in mlxsw core code to forward shared buffer occupancy calls into specific ASIC drivers. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 74 +++++++++++++++++++--- drivers/net/ethernet/mellanox/mlxsw/core.h | 11 ++++ 2 files changed, 77 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 1278260118a4..63a977767c01 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -911,15 +911,73 @@ mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, pool_index, threshold); } +static int mlxsw_devlink_sb_occ_snapshot(struct devlink *devlink, + unsigned int sb_index) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->sb_occ_snapshot) + return -EOPNOTSUPP; + return mlxsw_driver->sb_occ_snapshot(mlxsw_core, sb_index); +} + +static int mlxsw_devlink_sb_occ_max_clear(struct devlink *devlink, + unsigned int sb_index) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + + if (!mlxsw_driver->sb_occ_max_clear) + return -EOPNOTSUPP; + return mlxsw_driver->sb_occ_max_clear(mlxsw_core, sb_index); +} + +static int +mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port, + unsigned int sb_index, u16 pool_index, + u32 *p_cur, u32 *p_max) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); + + if (!mlxsw_driver->sb_occ_port_pool_get) + return -EOPNOTSUPP; + return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index, + pool_index, p_cur, p_max); +} + +static int +mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u32 *p_cur, u32 *p_max) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); + struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; + struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); + + if (!mlxsw_driver->sb_occ_tc_port_bind_get) + return -EOPNOTSUPP; + return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port, + sb_index, tc_index, + pool_type, p_cur, p_max); +} + static const struct devlink_ops mlxsw_devlink_ops = { - .port_split = mlxsw_devlink_port_split, - .port_unsplit = mlxsw_devlink_port_unsplit, - .sb_pool_get = mlxsw_devlink_sb_pool_get, - .sb_pool_set = mlxsw_devlink_sb_pool_set, - .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get, - .sb_port_pool_set = mlxsw_devlink_sb_port_pool_set, - .sb_tc_pool_bind_get = mlxsw_devlink_sb_tc_pool_bind_get, - .sb_tc_pool_bind_set = mlxsw_devlink_sb_tc_pool_bind_set, + .port_split = mlxsw_devlink_port_split, + .port_unsplit = mlxsw_devlink_port_unsplit, + .sb_pool_get = mlxsw_devlink_sb_pool_get, + .sb_pool_set = mlxsw_devlink_sb_pool_set, + .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get, + .sb_port_pool_set = mlxsw_devlink_sb_port_pool_set, + .sb_tc_pool_bind_get = mlxsw_devlink_sb_tc_pool_bind_get, + .sb_tc_pool_bind_set = mlxsw_devlink_sb_tc_pool_bind_set, + .sb_occ_snapshot = mlxsw_devlink_sb_occ_snapshot, + .sb_occ_max_clear = mlxsw_devlink_sb_occ_max_clear, + .sb_occ_port_pool_get = mlxsw_devlink_sb_occ_port_pool_get, + .sb_occ_tc_port_bind_get = mlxsw_devlink_sb_occ_tc_port_bind_get, }; int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index d0c471f26748..377daccf0063 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -229,6 +229,17 @@ struct mlxsw_driver { unsigned int sb_index, u16 tc_index, enum devlink_sb_pool_type pool_type, u16 pool_index, u32 threshold); + int (*sb_occ_snapshot)(struct mlxsw_core *mlxsw_core, + unsigned int sb_index); + int (*sb_occ_max_clear)(struct mlxsw_core *mlxsw_core, + unsigned int sb_index); + int (*sb_occ_port_pool_get)(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 *p_cur, u32 *p_max); + int (*sb_occ_tc_port_bind_get)(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u32 *p_cur, u32 *p_max); void (*txhdr_construct)(struct sk_buff *skb, const struct mlxsw_tx_info *tx_info); u8 txhdr_len; -- GitLab From 26176def3c1e7933601d04de3d4980199c1c87d1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:26 +0200 Subject: [PATCH 2823/9938] mlxsw: reg: Add Shared Buffer Status register definition This register allows to query HW for current and maximal buffer usage. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 100 ++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index fce5a962bf74..656466a00386 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3722,6 +3722,104 @@ static inline void mlxsw_reg_sbmm_pack(char *payload, u8 prio, u32 min_buff, mlxsw_reg_sbmm_pool_set(payload, pool); } +/* SBSR - Shared Buffer Status Register + * ------------------------------------ + * The SBSR register retrieves the shared buffer occupancy according to + * Port-Pool. Note that this register enables reading a large amount of data. + * It is the user's responsibility to limit the amount of data to ensure the + * response can match the maximum transfer unit. In case the response exceeds + * the maximum transport unit, it will be truncated with no special notice. + */ +#define MLXSW_REG_SBSR_ID 0xB005 +#define MLXSW_REG_SBSR_BASE_LEN 0x5C /* base length, without records */ +#define MLXSW_REG_SBSR_REC_LEN 0x8 /* record length */ +#define MLXSW_REG_SBSR_REC_MAX_COUNT 120 +#define MLXSW_REG_SBSR_LEN (MLXSW_REG_SBSR_BASE_LEN + \ + MLXSW_REG_SBSR_REC_LEN * \ + MLXSW_REG_SBSR_REC_MAX_COUNT) + +static const struct mlxsw_reg_info mlxsw_reg_sbsr = { + .id = MLXSW_REG_SBSR_ID, + .len = MLXSW_REG_SBSR_LEN, +}; + +/* reg_sbsr_clr + * Clear Max Buffer Occupancy. When this bit is set, the max_buff_occupancy + * field is cleared (and a new max value is tracked from the time the clear + * was performed). + * Access: OP + */ +MLXSW_ITEM32(reg, sbsr, clr, 0x00, 31, 1); + +/* reg_sbsr_ingress_port_mask + * Bit vector for all ingress network ports. + * Indicates which of the ports (for which the relevant bit is set) + * are affected by the set operation. Configuration of any other port + * does not change. + * Access: Index + */ +MLXSW_ITEM_BIT_ARRAY(reg, sbsr, ingress_port_mask, 0x10, 0x20, 1); + +/* reg_sbsr_pg_buff_mask + * Bit vector for all switch priority groups. + * Indicates which of the priorities (for which the relevant bit is set) + * are affected by the set operation. Configuration of any other priority + * does not change. + * Range is 0..cap_max_pg_buffers - 1 + * Access: Index + */ +MLXSW_ITEM_BIT_ARRAY(reg, sbsr, pg_buff_mask, 0x30, 0x4, 1); + +/* reg_sbsr_egress_port_mask + * Bit vector for all egress network ports. + * Indicates which of the ports (for which the relevant bit is set) + * are affected by the set operation. Configuration of any other port + * does not change. + * Access: Index + */ +MLXSW_ITEM_BIT_ARRAY(reg, sbsr, egress_port_mask, 0x34, 0x20, 1); + +/* reg_sbsr_tclass_mask + * Bit vector for all traffic classes. + * Indicates which of the traffic classes (for which the relevant bit is + * set) are affected by the set operation. Configuration of any other + * traffic class does not change. + * Range is 0..cap_max_tclass - 1 + * Access: Index + */ +MLXSW_ITEM_BIT_ARRAY(reg, sbsr, tclass_mask, 0x54, 0x8, 1); + +static inline void mlxsw_reg_sbsr_pack(char *payload, bool clr) +{ + MLXSW_REG_ZERO(sbsr, payload); + mlxsw_reg_sbsr_clr_set(payload, clr); +} + +/* reg_sbsr_rec_buff_occupancy + * Current buffer occupancy in cells. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sbsr, rec_buff_occupancy, MLXSW_REG_SBSR_BASE_LEN, + 0, 24, MLXSW_REG_SBSR_REC_LEN, 0x00, false); + +/* reg_sbsr_rec_max_buff_occupancy + * Maximum value of buffer occupancy in cells monitored. Cleared by + * writing to the clr field. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sbsr, rec_max_buff_occupancy, MLXSW_REG_SBSR_BASE_LEN, + 0, 24, MLXSW_REG_SBSR_REC_LEN, 0x04, false); + +static inline void mlxsw_reg_sbsr_rec_unpack(char *payload, int rec_index, + u32 *p_buff_occupancy, + u32 *p_max_buff_occupancy) +{ + *p_buff_occupancy = + mlxsw_reg_sbsr_rec_buff_occupancy_get(payload, rec_index); + *p_max_buff_occupancy = + mlxsw_reg_sbsr_rec_max_buff_occupancy_get(payload, rec_index); +} + static inline const char *mlxsw_reg_id_str(u16 reg_id) { switch (reg_id) { @@ -3817,6 +3915,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SBPM"; case MLXSW_REG_SBMM_ID: return "SBMM"; + case MLXSW_REG_SBSR_ID: + return "SBSR"; default: return "*UNKNOWN*"; } -- GitLab From 42a7f1d7747904d89e9831fb85a678add00facf3 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:27 +0200 Subject: [PATCH 2824/9938] mlxsw: reg: Extend SBPM register for occupancy control Since it is not possible to get and clear Port-Pool occupancy data using SBSR register, there's a need to implement that using SBPM. Extend pack helper and add unpack helper to get occupancy values. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 31 ++++++++++++++++++- .../mellanox/mlxsw/spectrum_buffers.c | 3 +- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 656466a00386..1977e7a5c530 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3636,6 +3636,27 @@ MLXSW_ITEM32(reg, sbpm, pool, 0x00, 8, 4); */ MLXSW_ITEM32(reg, sbpm, dir, 0x00, 0, 2); +/* reg_sbpm_buff_occupancy + * Current buffer occupancy in cells. + * Access: RO + */ +MLXSW_ITEM32(reg, sbpm, buff_occupancy, 0x10, 0, 24); + +/* reg_sbpm_clr + * Clear Max Buffer Occupancy + * When this bit is set, max_buff_occupancy field is cleared (and a + * new max value is tracked from the time the clear was performed). + * Access: OP + */ +MLXSW_ITEM32(reg, sbpm, clr, 0x14, 31, 1); + +/* reg_sbpm_max_buff_occupancy + * Maximum value of buffer occupancy in cells monitored. Cleared by + * writing to the clr field. + * Access: RO + */ +MLXSW_ITEM32(reg, sbpm, max_buff_occupancy, 0x14, 0, 24); + /* reg_sbpm_min_buff * Minimum buffer size for the limiter, in cells. * Access: RW @@ -3656,17 +3677,25 @@ MLXSW_ITEM32(reg, sbpm, min_buff, 0x18, 0, 24); MLXSW_ITEM32(reg, sbpm, max_buff, 0x1C, 0, 24); static inline void mlxsw_reg_sbpm_pack(char *payload, u8 local_port, u8 pool, - enum mlxsw_reg_sbxx_dir dir, + enum mlxsw_reg_sbxx_dir dir, bool clr, u32 min_buff, u32 max_buff) { MLXSW_REG_ZERO(sbpm, payload); mlxsw_reg_sbpm_local_port_set(payload, local_port); mlxsw_reg_sbpm_pool_set(payload, pool); mlxsw_reg_sbpm_dir_set(payload, dir); + mlxsw_reg_sbpm_clr_set(payload, clr); mlxsw_reg_sbpm_min_buff_set(payload, min_buff); mlxsw_reg_sbpm_max_buff_set(payload, max_buff); } +static inline void mlxsw_reg_sbpm_unpack(char *payload, u32 *p_buff_occupancy, + u32 *p_max_buff_occupancy) +{ + *p_buff_occupancy = mlxsw_reg_sbpm_buff_occupancy_get(payload); + *p_max_buff_occupancy = mlxsw_reg_sbpm_max_buff_occupancy_get(payload); +} + /* SBMM - Shared Buffer Multicast Management Register * -------------------------------------------------- * The SBMM register configures and retrieves the shared buffer allocation diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 6042c1741f77..639ba5ae8bbd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -113,7 +113,8 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, struct mlxsw_sp_sb_pm *pm; int err; - mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, min_buff, max_buff); + mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, false, + min_buff, max_buff); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl); if (err) return err; -- GitLab From dd9bdb04d2d7c428b0203b5e4e435abc229fa656 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:28 +0200 Subject: [PATCH 2825/9938] mlxsw: core: Add mlxsw specific workqueue and use it for FDB notif. processing Follow-up patch is going to need to use delayed work as well and frequently. The FDB notification processing is already using that and also quite frequently. It makes sense to create separate workqueue just for mlxsw driver in this case and do not pollute system_wq. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 25 +++++++++++++++++-- drivers/net/ethernet/mellanox/mlxsw/core.h | 3 +++ .../mellanox/mlxsw/spectrum_switchdev.c | 4 +-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 63a977767c01..a14e422fae4d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,8 @@ static const char mlxsw_core_driver_name[] = "mlxsw_core"; static struct dentry *mlxsw_core_dbg_root; +static struct workqueue_struct *mlxsw_wq; + struct mlxsw_core_pcpu_stats { u64 trap_rx_packets[MLXSW_TRAP_ID_MAX]; u64 trap_rx_bytes[MLXSW_TRAP_ID_MAX]; @@ -1575,17 +1578,35 @@ int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, } EXPORT_SYMBOL(mlxsw_cmd_exec); +int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay) +{ + return queue_delayed_work(mlxsw_wq, dwork, delay); +} +EXPORT_SYMBOL(mlxsw_core_schedule_dw); + static int __init mlxsw_core_module_init(void) { - mlxsw_core_dbg_root = debugfs_create_dir(mlxsw_core_driver_name, NULL); - if (!mlxsw_core_dbg_root) + int err; + + mlxsw_wq = create_workqueue(mlxsw_core_driver_name); + if (!mlxsw_wq) return -ENOMEM; + mlxsw_core_dbg_root = debugfs_create_dir(mlxsw_core_driver_name, NULL); + if (!mlxsw_core_dbg_root) { + err = -ENOMEM; + goto err_debugfs_create_dir; + } return 0; + +err_debugfs_create_dir: + destroy_workqueue(mlxsw_wq); + return err; } static void __exit mlxsw_core_module_exit(void) { debugfs_remove_recursive(mlxsw_core_dbg_root); + destroy_workqueue(mlxsw_wq); } module_init(mlxsw_core_module_init); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 377daccf0063..b41ebf8cad72 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "trap.h" @@ -151,6 +152,8 @@ int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, struct net_device *dev, bool split, u32 split_group); void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port); +int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay); + #define MLXSW_CONFIG_PROFILE_SWID_COUNT 8 struct mlxsw_swid_config { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index e1c74efff51a..fb9efb84f13b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1430,8 +1430,8 @@ static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp) { - schedule_delayed_work(&mlxsw_sp->fdb_notify.dw, - msecs_to_jiffies(mlxsw_sp->fdb_notify.interval)); + mlxsw_core_schedule_dw(&mlxsw_sp->fdb_notify.dw, + msecs_to_jiffies(mlxsw_sp->fdb_notify.interval)); } static void mlxsw_sp_fdb_notify_work(struct work_struct *work) -- GitLab From caf7297e7ab5f8aa9d482200748a066adbfa5775 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:29 +0200 Subject: [PATCH 2826/9938] mlxsw: core: Introduce support for asynchronous EMAD register access So far it was possible to have one EMAD register access at a time, locked by mutex. This patch extends this interface to allow multiple EMAD register accesses to be in fly at once. That allows faster processing on firmware side avoiding unused time in between EMADs. Measured speedup is ~30% for shared occupancy snapshot operation. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 494 +++++++++++++-------- drivers/net/ethernet/mellanox/mlxsw/core.h | 13 + 2 files changed, 334 insertions(+), 173 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index a14e422fae4d..b0a0b01bb4ef 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include #include @@ -96,11 +96,9 @@ struct mlxsw_core { struct list_head rx_listener_list; struct list_head event_listener_list; struct { - struct sk_buff *resp_skb; - u64 tid; - wait_queue_head_t wait; - bool trans_active; - struct mutex lock; /* One EMAD transaction at a time. */ + atomic64_t tid; + struct list_head trans_list; + spinlock_t trans_list_lock; /* protects trans_list writes */ bool use_emad; } emad; struct mlxsw_core_pcpu_stats __percpu *pcpu_stats; @@ -293,7 +291,7 @@ static void mlxsw_emad_pack_reg_tlv(char *reg_tlv, static void mlxsw_emad_pack_op_tlv(char *op_tlv, const struct mlxsw_reg_info *reg, enum mlxsw_core_reg_access_type type, - struct mlxsw_core *mlxsw_core) + u64 tid) { mlxsw_emad_op_tlv_type_set(op_tlv, MLXSW_EMAD_TLV_TYPE_OP); mlxsw_emad_op_tlv_len_set(op_tlv, MLXSW_EMAD_OP_TLV_LEN); @@ -309,7 +307,7 @@ static void mlxsw_emad_pack_op_tlv(char *op_tlv, MLXSW_EMAD_OP_TLV_METHOD_WRITE); mlxsw_emad_op_tlv_class_set(op_tlv, MLXSW_EMAD_OP_TLV_CLASS_REG_ACCESS); - mlxsw_emad_op_tlv_tid_set(op_tlv, mlxsw_core->emad.tid); + mlxsw_emad_op_tlv_tid_set(op_tlv, tid); } static int mlxsw_emad_construct_eth_hdr(struct sk_buff *skb) @@ -331,7 +329,7 @@ static void mlxsw_emad_construct(struct sk_buff *skb, const struct mlxsw_reg_info *reg, char *payload, enum mlxsw_core_reg_access_type type, - struct mlxsw_core *mlxsw_core) + u64 tid) { char *buf; @@ -342,7 +340,7 @@ static void mlxsw_emad_construct(struct sk_buff *skb, mlxsw_emad_pack_reg_tlv(buf, reg, payload); buf = skb_push(skb, MLXSW_EMAD_OP_TLV_LEN * sizeof(u32)); - mlxsw_emad_pack_op_tlv(buf, reg, type, mlxsw_core); + mlxsw_emad_pack_op_tlv(buf, reg, type, tid); mlxsw_emad_construct_eth_hdr(skb); } @@ -379,58 +377,16 @@ static bool mlxsw_emad_is_resp(const struct sk_buff *skb) return (mlxsw_emad_op_tlv_r_get(op_tlv) == MLXSW_EMAD_OP_TLV_RESPONSE); } -#define MLXSW_EMAD_TIMEOUT_MS 200 - -static int __mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, - struct sk_buff *skb, - const struct mlxsw_tx_info *tx_info) -{ - int err; - int ret; - - mlxsw_core->emad.trans_active = true; - - err = mlxsw_core_skb_transmit(mlxsw_core, skb, tx_info); - if (err) { - dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n", - mlxsw_core->emad.tid); - dev_kfree_skb(skb); - goto trans_inactive_out; - } - - ret = wait_event_timeout(mlxsw_core->emad.wait, - !(mlxsw_core->emad.trans_active), - msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS)); - if (!ret) { - dev_warn(mlxsw_core->bus_info->dev, "EMAD timed-out (tid=%llx)\n", - mlxsw_core->emad.tid); - err = -EIO; - goto trans_inactive_out; - } - - return 0; - -trans_inactive_out: - mlxsw_core->emad.trans_active = false; - return err; -} - -static int mlxsw_emad_process_status(struct mlxsw_core *mlxsw_core, - char *op_tlv) +static int mlxsw_emad_process_status(char *op_tlv, + enum mlxsw_emad_op_tlv_status *p_status) { - enum mlxsw_emad_op_tlv_status status; - u64 tid; - - status = mlxsw_emad_op_tlv_status_get(op_tlv); - tid = mlxsw_emad_op_tlv_tid_get(op_tlv); + *p_status = mlxsw_emad_op_tlv_status_get(op_tlv); - switch (status) { + switch (*p_status) { case MLXSW_EMAD_OP_TLV_STATUS_SUCCESS: return 0; case MLXSW_EMAD_OP_TLV_STATUS_BUSY: case MLXSW_EMAD_OP_TLV_STATUS_MESSAGE_RECEIPT_ACK: - dev_warn(mlxsw_core->bus_info->dev, "Reg access status again (tid=%llx,status=%x(%s))\n", - tid, status, mlxsw_emad_op_tlv_status_str(status)); return -EAGAIN; case MLXSW_EMAD_OP_TLV_STATUS_VERSION_NOT_SUPPORTED: case MLXSW_EMAD_OP_TLV_STATUS_UNKNOWN_TLV: @@ -441,70 +397,150 @@ static int mlxsw_emad_process_status(struct mlxsw_core *mlxsw_core, case MLXSW_EMAD_OP_TLV_STATUS_RESOURCE_NOT_AVAILABLE: case MLXSW_EMAD_OP_TLV_STATUS_INTERNAL_ERROR: default: - dev_err(mlxsw_core->bus_info->dev, "Reg access status failed (tid=%llx,status=%x(%s))\n", - tid, status, mlxsw_emad_op_tlv_status_str(status)); return -EIO; } } -static int mlxsw_emad_process_status_skb(struct mlxsw_core *mlxsw_core, - struct sk_buff *skb) +static int +mlxsw_emad_process_status_skb(struct sk_buff *skb, + enum mlxsw_emad_op_tlv_status *p_status) { - return mlxsw_emad_process_status(mlxsw_core, mlxsw_emad_op_tlv(skb)); + return mlxsw_emad_process_status(mlxsw_emad_op_tlv(skb), p_status); +} + +struct mlxsw_reg_trans { + struct list_head list; + struct list_head bulk_list; + struct mlxsw_core *core; + struct sk_buff *tx_skb; + struct mlxsw_tx_info tx_info; + struct delayed_work timeout_dw; + unsigned int retries; + u64 tid; + struct completion completion; + atomic_t active; + mlxsw_reg_trans_cb_t *cb; + unsigned long cb_priv; + const struct mlxsw_reg_info *reg; + enum mlxsw_core_reg_access_type type; + int err; + enum mlxsw_emad_op_tlv_status emad_status; + struct rcu_head rcu; +}; + +#define MLXSW_EMAD_TIMEOUT_MS 200 + +static void mlxsw_emad_trans_timeout_schedule(struct mlxsw_reg_trans *trans) +{ + unsigned long timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS); + + mlxsw_core_schedule_dw(&trans->timeout_dw, timeout); } static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, - struct sk_buff *skb, - const struct mlxsw_tx_info *tx_info) + struct mlxsw_reg_trans *trans) { - struct sk_buff *trans_skb; - int n_retry; + struct sk_buff *skb; int err; - n_retry = 0; -retry: - /* We copy the EMAD to a new skb, since we might need - * to retransmit it in case of failure. - */ - trans_skb = skb_copy(skb, GFP_KERNEL); - if (!trans_skb) { - err = -ENOMEM; - goto out; + skb = skb_copy(trans->tx_skb, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + atomic_set(&trans->active, 1); + err = mlxsw_core_skb_transmit(mlxsw_core, skb, &trans->tx_info); + if (err) { + dev_kfree_skb(skb); + return err; } + mlxsw_emad_trans_timeout_schedule(trans); + return 0; +} - err = __mlxsw_emad_transmit(mlxsw_core, trans_skb, tx_info); - if (!err) { - struct sk_buff *resp_skb = mlxsw_core->emad.resp_skb; +static void mlxsw_emad_trans_finish(struct mlxsw_reg_trans *trans, int err) +{ + struct mlxsw_core *mlxsw_core = trans->core; + + dev_kfree_skb(trans->tx_skb); + spin_lock_bh(&mlxsw_core->emad.trans_list_lock); + list_del_rcu(&trans->list); + spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); + trans->err = err; + complete(&trans->completion); +} + +static void mlxsw_emad_transmit_retry(struct mlxsw_core *mlxsw_core, + struct mlxsw_reg_trans *trans) +{ + int err; - err = mlxsw_emad_process_status_skb(mlxsw_core, resp_skb); - if (err) - dev_kfree_skb(resp_skb); - if (!err || err != -EAGAIN) - goto out; + if (trans->retries < MLXSW_EMAD_MAX_RETRY) { + trans->retries++; + err = mlxsw_emad_transmit(trans->core, trans); + if (err == 0) + return; + } else { + err = -EIO; } - if (n_retry++ < MLXSW_EMAD_MAX_RETRY) - goto retry; + mlxsw_emad_trans_finish(trans, err); +} -out: - dev_kfree_skb(skb); - mlxsw_core->emad.tid++; - return err; +static void mlxsw_emad_trans_timeout_work(struct work_struct *work) +{ + struct mlxsw_reg_trans *trans = container_of(work, + struct mlxsw_reg_trans, + timeout_dw.work); + + if (!atomic_dec_and_test(&trans->active)) + return; + + mlxsw_emad_transmit_retry(trans->core, trans); } +static void mlxsw_emad_process_response(struct mlxsw_core *mlxsw_core, + struct mlxsw_reg_trans *trans, + struct sk_buff *skb) +{ + int err; + + if (!atomic_dec_and_test(&trans->active)) + return; + + err = mlxsw_emad_process_status_skb(skb, &trans->emad_status); + if (err == -EAGAIN) { + mlxsw_emad_transmit_retry(mlxsw_core, trans); + } else { + if (err == 0) { + char *op_tlv = mlxsw_emad_op_tlv(skb); + + if (trans->cb) + trans->cb(mlxsw_core, + mlxsw_emad_reg_payload(op_tlv), + trans->reg->len, trans->cb_priv); + } + mlxsw_emad_trans_finish(trans, err); + } +} + +/* called with rcu read lock held */ static void mlxsw_emad_rx_listener_func(struct sk_buff *skb, u8 local_port, void *priv) { struct mlxsw_core *mlxsw_core = priv; + struct mlxsw_reg_trans *trans; - if (mlxsw_emad_is_resp(skb) && - mlxsw_core->emad.trans_active && - mlxsw_emad_get_tid(skb) == mlxsw_core->emad.tid) { - mlxsw_core->emad.resp_skb = skb; - mlxsw_core->emad.trans_active = false; - wake_up(&mlxsw_core->emad.wait); - } else { - dev_kfree_skb(skb); + if (!mlxsw_emad_is_resp(skb)) + goto free_skb; + + list_for_each_entry_rcu(trans, &mlxsw_core->emad.trans_list, list) { + if (mlxsw_emad_get_tid(skb) == trans->tid) { + mlxsw_emad_process_response(mlxsw_core, trans, skb); + break; + } } + +free_skb: + dev_kfree_skb(skb); } static const struct mlxsw_rx_listener mlxsw_emad_rx_listener = { @@ -531,18 +567,19 @@ static int mlxsw_emad_traps_set(struct mlxsw_core *mlxsw_core) static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) { + u64 tid; int err; /* Set the upper 32 bits of the transaction ID field to a random * number. This allows us to discard EMADs addressed to other * devices. */ - get_random_bytes(&mlxsw_core->emad.tid, 4); - mlxsw_core->emad.tid = mlxsw_core->emad.tid << 32; + get_random_bytes(&tid, 4); + tid <<= 32; + atomic64_set(&mlxsw_core->emad.tid, tid); - init_waitqueue_head(&mlxsw_core->emad.wait); - mlxsw_core->emad.trans_active = false; - mutex_init(&mlxsw_core->emad.lock); + INIT_LIST_HEAD(&mlxsw_core->emad.trans_list); + spin_lock_init(&mlxsw_core->emad.trans_list_lock); err = mlxsw_core_rx_listener_register(mlxsw_core, &mlxsw_emad_rx_listener, @@ -600,6 +637,59 @@ static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core, return skb; } +static int mlxsw_emad_reg_access(struct mlxsw_core *mlxsw_core, + const struct mlxsw_reg_info *reg, + char *payload, + enum mlxsw_core_reg_access_type type, + struct mlxsw_reg_trans *trans, + struct list_head *bulk_list, + mlxsw_reg_trans_cb_t *cb, + unsigned long cb_priv, u64 tid) +{ + struct sk_buff *skb; + int err; + + dev_dbg(mlxsw_core->bus_info->dev, "EMAD reg access (tid=%llx,reg_id=%x(%s),type=%s)\n", + trans->tid, reg->id, mlxsw_reg_id_str(reg->id), + mlxsw_core_reg_access_type_str(type)); + + skb = mlxsw_emad_alloc(mlxsw_core, reg->len); + if (!skb) + return -ENOMEM; + + list_add_tail(&trans->bulk_list, bulk_list); + trans->core = mlxsw_core; + trans->tx_skb = skb; + trans->tx_info.local_port = MLXSW_PORT_CPU_PORT; + trans->tx_info.is_emad = true; + INIT_DELAYED_WORK(&trans->timeout_dw, mlxsw_emad_trans_timeout_work); + trans->tid = tid; + init_completion(&trans->completion); + trans->cb = cb; + trans->cb_priv = cb_priv; + trans->reg = reg; + trans->type = type; + + mlxsw_emad_construct(skb, reg, payload, type, trans->tid); + mlxsw_core->driver->txhdr_construct(skb, &trans->tx_info); + + spin_lock_bh(&mlxsw_core->emad.trans_list_lock); + list_add_tail_rcu(&trans->list, &mlxsw_core->emad.trans_list); + spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); + err = mlxsw_emad_transmit(mlxsw_core, trans); + if (err) + goto err_out; + return 0; + +err_out: + spin_lock_bh(&mlxsw_core->emad.trans_list_lock); + list_del_rcu(&trans->list); + spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); + list_del(&trans->bulk_list); + dev_kfree_skb(trans->tx_skb); + return err; +} + /***************** * Core functions *****************/ @@ -689,24 +779,6 @@ static const struct file_operations mlxsw_core_rx_stats_dbg_ops = { .llseek = seq_lseek }; -static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, - const char *buf, size_t size) -{ - __be32 *m = (__be32 *) buf; - int i; - int count = size / sizeof(__be32); - - for (i = count - 1; i >= 0; i--) - if (m[i]) - break; - i++; - count = i ? i : 1; - for (i = 0; i < count; i += 4) - dev_dbg(mlxsw_core->bus_info->dev, "%04x - %08x %08x %08x %08x\n", - i * 4, be32_to_cpu(m[i]), be32_to_cpu(m[i + 1]), - be32_to_cpu(m[i + 2]), be32_to_cpu(m[i + 3])); -} - int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver) { spin_lock(&mlxsw_core_driver_list_lock); @@ -1264,56 +1336,112 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_event_listener_unregister); +static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core) +{ + return atomic64_inc_return(&mlxsw_core->emad.tid); +} + static int mlxsw_core_reg_access_emad(struct mlxsw_core *mlxsw_core, const struct mlxsw_reg_info *reg, char *payload, - enum mlxsw_core_reg_access_type type) + enum mlxsw_core_reg_access_type type, + struct list_head *bulk_list, + mlxsw_reg_trans_cb_t *cb, + unsigned long cb_priv) { + u64 tid = mlxsw_core_tid_get(mlxsw_core); + struct mlxsw_reg_trans *trans; int err; - char *op_tlv; - struct sk_buff *skb; - struct mlxsw_tx_info tx_info = { - .local_port = MLXSW_PORT_CPU_PORT, - .is_emad = true, - }; - skb = mlxsw_emad_alloc(mlxsw_core, reg->len); - if (!skb) + trans = kzalloc(sizeof(*trans), GFP_KERNEL); + if (!trans) return -ENOMEM; - mlxsw_emad_construct(skb, reg, payload, type, mlxsw_core); - mlxsw_core->driver->txhdr_construct(skb, &tx_info); + err = mlxsw_emad_reg_access(mlxsw_core, reg, payload, type, trans, + bulk_list, cb, cb_priv, tid); + if (err) { + kfree(trans); + return err; + } + return 0; +} - dev_dbg(mlxsw_core->bus_info->dev, "EMAD send (tid=%llx)\n", - mlxsw_core->emad.tid); - mlxsw_core_buf_dump_dbg(mlxsw_core, skb->data, skb->len); +int mlxsw_reg_trans_query(struct mlxsw_core *mlxsw_core, + const struct mlxsw_reg_info *reg, char *payload, + struct list_head *bulk_list, + mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv) +{ + return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload, + MLXSW_CORE_REG_ACCESS_TYPE_QUERY, + bulk_list, cb, cb_priv); +} +EXPORT_SYMBOL(mlxsw_reg_trans_query); - err = mlxsw_emad_transmit(mlxsw_core, skb, &tx_info); - if (!err) { - op_tlv = mlxsw_emad_op_tlv(mlxsw_core->emad.resp_skb); - memcpy(payload, mlxsw_emad_reg_payload(op_tlv), - reg->len); +int mlxsw_reg_trans_write(struct mlxsw_core *mlxsw_core, + const struct mlxsw_reg_info *reg, char *payload, + struct list_head *bulk_list, + mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv) +{ + return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload, + MLXSW_CORE_REG_ACCESS_TYPE_WRITE, + bulk_list, cb, cb_priv); +} +EXPORT_SYMBOL(mlxsw_reg_trans_write); - dev_dbg(mlxsw_core->bus_info->dev, "EMAD recv (tid=%llx)\n", - mlxsw_core->emad.tid - 1); - mlxsw_core_buf_dump_dbg(mlxsw_core, - mlxsw_core->emad.resp_skb->data, - mlxsw_core->emad.resp_skb->len); +static int mlxsw_reg_trans_wait(struct mlxsw_reg_trans *trans) +{ + struct mlxsw_core *mlxsw_core = trans->core; + int err; - dev_kfree_skb(mlxsw_core->emad.resp_skb); - } + wait_for_completion(&trans->completion); + cancel_delayed_work_sync(&trans->timeout_dw); + err = trans->err; + if (trans->retries) + dev_warn(mlxsw_core->bus_info->dev, "EMAD retries (%d/%d) (tid=%llx)\n", + trans->retries, MLXSW_EMAD_MAX_RETRY, trans->tid); + if (err) + dev_err(mlxsw_core->bus_info->dev, "EMAD reg access failed (tid=%llx,reg_id=%x(%s),type=%s,status=%x(%s))\n", + trans->tid, trans->reg->id, + mlxsw_reg_id_str(trans->reg->id), + mlxsw_core_reg_access_type_str(trans->type), + trans->emad_status, + mlxsw_emad_op_tlv_status_str(trans->emad_status)); + + list_del(&trans->bulk_list); + kfree_rcu(trans, rcu); return err; } +int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list) +{ + struct mlxsw_reg_trans *trans; + struct mlxsw_reg_trans *tmp; + int sum_err = 0; + int err; + + list_for_each_entry_safe(trans, tmp, bulk_list, bulk_list) { + err = mlxsw_reg_trans_wait(trans); + if (err && sum_err == 0) + sum_err = err; /* first error to be returned */ + } + return sum_err; +} +EXPORT_SYMBOL(mlxsw_reg_trans_bulk_wait); + static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, const struct mlxsw_reg_info *reg, char *payload, enum mlxsw_core_reg_access_type type) { + enum mlxsw_emad_op_tlv_status status; int err, n_retry; char *in_mbox, *out_mbox, *tmp; + dev_dbg(mlxsw_core->bus_info->dev, "Reg cmd access (reg_id=%x(%s),type=%s)\n", + reg->id, mlxsw_reg_id_str(reg->id), + mlxsw_core_reg_access_type_str(type)); + in_mbox = mlxsw_cmd_mbox_alloc(); if (!in_mbox) return -ENOMEM; @@ -1324,7 +1452,8 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, goto free_in_mbox; } - mlxsw_emad_pack_op_tlv(in_mbox, reg, type, mlxsw_core); + mlxsw_emad_pack_op_tlv(in_mbox, reg, type, + mlxsw_core_tid_get(mlxsw_core)); tmp = in_mbox + MLXSW_EMAD_OP_TLV_LEN * sizeof(u32); mlxsw_emad_pack_reg_tlv(tmp, reg, payload); @@ -1332,60 +1461,61 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, retry: err = mlxsw_cmd_access_reg(mlxsw_core, in_mbox, out_mbox); if (!err) { - err = mlxsw_emad_process_status(mlxsw_core, out_mbox); - if (err == -EAGAIN && n_retry++ < MLXSW_EMAD_MAX_RETRY) - goto retry; + err = mlxsw_emad_process_status(out_mbox, &status); + if (err) { + if (err == -EAGAIN && n_retry++ < MLXSW_EMAD_MAX_RETRY) + goto retry; + dev_err(mlxsw_core->bus_info->dev, "Reg cmd access status failed (status=%x(%s))\n", + status, mlxsw_emad_op_tlv_status_str(status)); + } } if (!err) memcpy(payload, mlxsw_emad_reg_payload(out_mbox), reg->len); - mlxsw_core->emad.tid++; mlxsw_cmd_mbox_free(out_mbox); free_in_mbox: mlxsw_cmd_mbox_free(in_mbox); + if (err) + dev_err(mlxsw_core->bus_info->dev, "Reg cmd access failed (reg_id=%x(%s),type=%s)\n", + reg->id, mlxsw_reg_id_str(reg->id), + mlxsw_core_reg_access_type_str(type)); return err; } +static void mlxsw_core_reg_access_cb(struct mlxsw_core *mlxsw_core, + char *payload, size_t payload_len, + unsigned long cb_priv) +{ + char *orig_payload = (char *) cb_priv; + + memcpy(orig_payload, payload, payload_len); +} + static int mlxsw_core_reg_access(struct mlxsw_core *mlxsw_core, const struct mlxsw_reg_info *reg, char *payload, enum mlxsw_core_reg_access_type type) { - u64 cur_tid; + LIST_HEAD(bulk_list); int err; - if (mutex_lock_interruptible(&mlxsw_core->emad.lock)) { - dev_err(mlxsw_core->bus_info->dev, "Reg access interrupted (reg_id=%x(%s),type=%s)\n", - reg->id, mlxsw_reg_id_str(reg->id), - mlxsw_core_reg_access_type_str(type)); - return -EINTR; - } - - cur_tid = mlxsw_core->emad.tid; - dev_dbg(mlxsw_core->bus_info->dev, "Reg access (tid=%llx,reg_id=%x(%s),type=%s)\n", - cur_tid, reg->id, mlxsw_reg_id_str(reg->id), - mlxsw_core_reg_access_type_str(type)); - /* During initialization EMAD interface is not available to us, * so we default to command interface. We switch to EMAD interface * after setting the appropriate traps. */ if (!mlxsw_core->emad.use_emad) - err = mlxsw_core_reg_access_cmd(mlxsw_core, reg, - payload, type); - else - err = mlxsw_core_reg_access_emad(mlxsw_core, reg, + return mlxsw_core_reg_access_cmd(mlxsw_core, reg, payload, type); + err = mlxsw_core_reg_access_emad(mlxsw_core, reg, + payload, type, &bulk_list, + mlxsw_core_reg_access_cb, + (unsigned long) payload); if (err) - dev_err(mlxsw_core->bus_info->dev, "Reg access failed (tid=%llx,reg_id=%x(%s),type=%s)\n", - cur_tid, reg->id, mlxsw_reg_id_str(reg->id), - mlxsw_core_reg_access_type_str(type)); - - mutex_unlock(&mlxsw_core->emad.lock); - return err; + return err; + return mlxsw_reg_trans_bulk_wait(&bulk_list); } int mlxsw_reg_query(struct mlxsw_core *mlxsw_core, @@ -1536,6 +1666,24 @@ void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port) } EXPORT_SYMBOL(mlxsw_core_port_fini); +static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, + const char *buf, size_t size) +{ + __be32 *m = (__be32 *) buf; + int i; + int count = size / sizeof(__be32); + + for (i = count - 1; i >= 0; i--) + if (m[i]) + break; + i++; + count = i ? i : 1; + for (i = 0; i < count; i += 4) + dev_dbg(mlxsw_core->bus_info->dev, "%04x - %08x %08x %08x %08x\n", + i * 4, be32_to_cpu(m[i]), be32_to_cpu(m[i + 1]), + be32_to_cpu(m[i + 2]), be32_to_cpu(m[i + 3])); +} + int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, u32 in_mod, bool out_mbox_direct, char *in_mbox, size_t in_mbox_size, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index b41ebf8cad72..436bc49df6ab 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -109,6 +109,19 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core, const struct mlxsw_event_listener *el, void *priv); +typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload, + size_t payload_len, unsigned long cb_priv); + +int mlxsw_reg_trans_query(struct mlxsw_core *mlxsw_core, + const struct mlxsw_reg_info *reg, char *payload, + struct list_head *bulk_list, + mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv); +int mlxsw_reg_trans_write(struct mlxsw_core *mlxsw_core, + const struct mlxsw_reg_info *reg, char *payload, + struct list_head *bulk_list, + mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv); +int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list); + int mlxsw_reg_query(struct mlxsw_core *mlxsw_core, const struct mlxsw_reg_info *reg, char *payload); int mlxsw_reg_write(struct mlxsw_core *mlxsw_core, -- GitLab From 2d0ed39fbdee64835dc710b4ee3897f2bb9f8cf4 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 14 Apr 2016 18:19:30 +0200 Subject: [PATCH 2827/9938] mlxsw: spectrum_buffers: Implement occupancy monitoring Implement occupancy API introduced in devlink and mlxsw core. This is done by accessing SBPM register for Port-Pool and SBSR for Port-TC current and max occupancy values. Max clear is implemented using the same registers. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 36 +-- .../net/ethernet/mellanox/mlxsw/spectrum.h | 18 ++ .../mellanox/mlxsw/spectrum_buffers.c | 255 ++++++++++++++++++ 3 files changed, 293 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index ecadb15c4907..681afe1a3802 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2493,22 +2493,26 @@ static struct mlxsw_config_profile mlxsw_sp_config_profile = { }; static struct mlxsw_driver mlxsw_sp_driver = { - .kind = MLXSW_DEVICE_KIND_SPECTRUM, - .owner = THIS_MODULE, - .priv_size = sizeof(struct mlxsw_sp), - .init = mlxsw_sp_init, - .fini = mlxsw_sp_fini, - .port_split = mlxsw_sp_port_split, - .port_unsplit = mlxsw_sp_port_unsplit, - .sb_pool_get = mlxsw_sp_sb_pool_get, - .sb_pool_set = mlxsw_sp_sb_pool_set, - .sb_port_pool_get = mlxsw_sp_sb_port_pool_get, - .sb_port_pool_set = mlxsw_sp_sb_port_pool_set, - .sb_tc_pool_bind_get = mlxsw_sp_sb_tc_pool_bind_get, - .sb_tc_pool_bind_set = mlxsw_sp_sb_tc_pool_bind_set, - .txhdr_construct = mlxsw_sp_txhdr_construct, - .txhdr_len = MLXSW_TXHDR_LEN, - .profile = &mlxsw_sp_config_profile, + .kind = MLXSW_DEVICE_KIND_SPECTRUM, + .owner = THIS_MODULE, + .priv_size = sizeof(struct mlxsw_sp), + .init = mlxsw_sp_init, + .fini = mlxsw_sp_fini, + .port_split = mlxsw_sp_port_split, + .port_unsplit = mlxsw_sp_port_unsplit, + .sb_pool_get = mlxsw_sp_sb_pool_get, + .sb_pool_set = mlxsw_sp_sb_pool_set, + .sb_port_pool_get = mlxsw_sp_sb_port_pool_get, + .sb_port_pool_set = mlxsw_sp_sb_port_pool_set, + .sb_tc_pool_bind_get = mlxsw_sp_sb_tc_pool_bind_get, + .sb_tc_pool_bind_set = mlxsw_sp_sb_tc_pool_bind_set, + .sb_occ_snapshot = mlxsw_sp_sb_occ_snapshot, + .sb_occ_max_clear = mlxsw_sp_sb_occ_max_clear, + .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, + .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, + .txhdr_construct = mlxsw_sp_txhdr_construct, + .txhdr_len = MLXSW_TXHDR_LEN, + .profile = &mlxsw_sp_config_profile, }; static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 6458efa5607e..e2c022d3e2f3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -123,15 +123,22 @@ struct mlxsw_sp_sb_pr { u32 size; }; +struct mlxsw_cp_sb_occ { + u32 cur; + u32 max; +}; + struct mlxsw_sp_sb_cm { u32 min_buff; u32 max_buff; u8 pool; + struct mlxsw_cp_sb_occ occ; }; struct mlxsw_sp_sb_pm { u32 min_buff; u32 max_buff; + struct mlxsw_cp_sb_occ occ; }; #define MLXSW_SP_SB_POOL_COUNT 4 @@ -328,6 +335,17 @@ int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port, unsigned int sb_index, u16 tc_index, enum devlink_sb_pool_type pool_type, u16 pool_index, u32 threshold); +int mlxsw_sp_sb_occ_snapshot(struct mlxsw_core *mlxsw_core, + unsigned int sb_index); +int mlxsw_sp_sb_occ_max_clear(struct mlxsw_core *mlxsw_core, + unsigned int sb_index); +int mlxsw_sp_sb_occ_port_pool_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 *p_cur, u32 *p_max); +int mlxsw_sp_sb_occ_tc_port_bind_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u32 *p_cur, u32 *p_max); int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 639ba5ae8bbd..f2e073af5dd2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "spectrum.h" #include "core.h" @@ -125,6 +126,41 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, return 0; } +static int mlxsw_sp_sb_pm_occ_clear(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u8 pool, enum mlxsw_reg_sbxx_dir dir, + struct list_head *bulk_list) +{ + char sbpm_pl[MLXSW_REG_SBPM_LEN]; + + mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, true, 0, 0); + return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl, + bulk_list, NULL, 0); +} + +static void mlxsw_sp_sb_pm_occ_query_cb(struct mlxsw_core *mlxsw_core, + char *sbpm_pl, size_t sbpm_pl_len, + unsigned long cb_priv) +{ + struct mlxsw_sp_sb_pm *pm = (struct mlxsw_sp_sb_pm *) cb_priv; + + mlxsw_reg_sbpm_unpack(sbpm_pl, &pm->occ.cur, &pm->occ.max); +} + +static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u8 pool, enum mlxsw_reg_sbxx_dir dir, + struct list_head *bulk_list) +{ + char sbpm_pl[MLXSW_REG_SBPM_LEN]; + struct mlxsw_sp_sb_pm *pm; + + pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool, dir); + mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, false, 0, 0); + return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl, + bulk_list, + mlxsw_sp_sb_pm_occ_query_cb, + (unsigned long) pm); +} + static const u16 mlxsw_sp_pbs[] = { 2 * MLXSW_SP_BYTES_TO_CELLS(ETH_FRAME_LEN), 0, @@ -707,3 +743,222 @@ int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port, return mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, pg_buff, dir, 0, max_buff, pool); } + +#define MASKED_COUNT_MAX \ + (MLXSW_REG_SBSR_REC_MAX_COUNT / (MLXSW_SP_SB_TC_COUNT * 2)) + +struct mlxsw_sp_sb_sr_occ_query_cb_ctx { + u8 masked_count; + u8 local_port_1; +}; + +static void mlxsw_sp_sb_sr_occ_query_cb(struct mlxsw_core *mlxsw_core, + char *sbsr_pl, size_t sbsr_pl_len, + unsigned long cb_priv) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + struct mlxsw_sp_sb_sr_occ_query_cb_ctx cb_ctx; + u8 masked_count; + u8 local_port; + int rec_index = 0; + struct mlxsw_sp_sb_cm *cm; + int i; + + memcpy(&cb_ctx, &cb_priv, sizeof(cb_ctx)); + + masked_count = 0; + for (local_port = cb_ctx.local_port_1; + local_port < MLXSW_PORT_MAX_PORTS; local_port++) { + if (!mlxsw_sp->ports[local_port]) + continue; + for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) { + cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, i, + MLXSW_REG_SBXX_DIR_INGRESS); + mlxsw_reg_sbsr_rec_unpack(sbsr_pl, rec_index++, + &cm->occ.cur, &cm->occ.max); + } + if (++masked_count == cb_ctx.masked_count) + break; + } + masked_count = 0; + for (local_port = cb_ctx.local_port_1; + local_port < MLXSW_PORT_MAX_PORTS; local_port++) { + if (!mlxsw_sp->ports[local_port]) + continue; + for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) { + cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, i, + MLXSW_REG_SBXX_DIR_EGRESS); + mlxsw_reg_sbsr_rec_unpack(sbsr_pl, rec_index++, + &cm->occ.cur, &cm->occ.max); + } + if (++masked_count == cb_ctx.masked_count) + break; + } +} + +int mlxsw_sp_sb_occ_snapshot(struct mlxsw_core *mlxsw_core, + unsigned int sb_index) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + struct mlxsw_sp_sb_sr_occ_query_cb_ctx cb_ctx; + unsigned long cb_priv; + LIST_HEAD(bulk_list); + char *sbsr_pl; + u8 masked_count; + u8 local_port_1; + u8 local_port = 0; + int i; + int err; + int err2; + + sbsr_pl = kmalloc(MLXSW_REG_SBSR_LEN, GFP_KERNEL); + if (!sbsr_pl) + return -ENOMEM; + +next_batch: + local_port++; + local_port_1 = local_port; + masked_count = 0; + mlxsw_reg_sbsr_pack(sbsr_pl, false); + for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) { + mlxsw_reg_sbsr_pg_buff_mask_set(sbsr_pl, i, 1); + mlxsw_reg_sbsr_tclass_mask_set(sbsr_pl, i, 1); + } + for (; local_port < MLXSW_PORT_MAX_PORTS; local_port++) { + if (!mlxsw_sp->ports[local_port]) + continue; + mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1); + mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1); + for (i = 0; i < MLXSW_SP_SB_POOL_COUNT; i++) { + err = mlxsw_sp_sb_pm_occ_query(mlxsw_sp, local_port, i, + MLXSW_REG_SBXX_DIR_INGRESS, + &bulk_list); + if (err) + goto out; + err = mlxsw_sp_sb_pm_occ_query(mlxsw_sp, local_port, i, + MLXSW_REG_SBXX_DIR_EGRESS, + &bulk_list); + if (err) + goto out; + } + if (++masked_count == MASKED_COUNT_MAX) + goto do_query; + } + +do_query: + cb_ctx.masked_count = masked_count; + cb_ctx.local_port_1 = local_port_1; + memcpy(&cb_priv, &cb_ctx, sizeof(cb_ctx)); + err = mlxsw_reg_trans_query(mlxsw_core, MLXSW_REG(sbsr), sbsr_pl, + &bulk_list, mlxsw_sp_sb_sr_occ_query_cb, + cb_priv); + if (err) + goto out; + if (local_port < MLXSW_PORT_MAX_PORTS) + goto next_batch; + +out: + err2 = mlxsw_reg_trans_bulk_wait(&bulk_list); + if (!err) + err = err2; + kfree(sbsr_pl); + return err; +} + +int mlxsw_sp_sb_occ_max_clear(struct mlxsw_core *mlxsw_core, + unsigned int sb_index) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + LIST_HEAD(bulk_list); + char *sbsr_pl; + unsigned int masked_count; + u8 local_port = 0; + int i; + int err; + int err2; + + sbsr_pl = kmalloc(MLXSW_REG_SBSR_LEN, GFP_KERNEL); + if (!sbsr_pl) + return -ENOMEM; + +next_batch: + local_port++; + masked_count = 0; + mlxsw_reg_sbsr_pack(sbsr_pl, true); + for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) { + mlxsw_reg_sbsr_pg_buff_mask_set(sbsr_pl, i, 1); + mlxsw_reg_sbsr_tclass_mask_set(sbsr_pl, i, 1); + } + for (; local_port < MLXSW_PORT_MAX_PORTS; local_port++) { + if (!mlxsw_sp->ports[local_port]) + continue; + mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1); + mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1); + for (i = 0; i < MLXSW_SP_SB_POOL_COUNT; i++) { + err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i, + MLXSW_REG_SBXX_DIR_INGRESS, + &bulk_list); + if (err) + goto out; + err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i, + MLXSW_REG_SBXX_DIR_EGRESS, + &bulk_list); + if (err) + goto out; + } + if (++masked_count == MASKED_COUNT_MAX) + goto do_query; + } + +do_query: + err = mlxsw_reg_trans_query(mlxsw_core, MLXSW_REG(sbsr), sbsr_pl, + &bulk_list, NULL, 0); + if (err) + goto out; + if (local_port < MLXSW_PORT_MAX_PORTS) + goto next_batch; + +out: + err2 = mlxsw_reg_trans_bulk_wait(&bulk_list); + if (!err) + err = err2; + kfree(sbsr_pl); + return err; +} + +int mlxsw_sp_sb_occ_port_pool_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 pool_index, + u32 *p_cur, u32 *p_max) +{ + struct mlxsw_sp_port *mlxsw_sp_port = + mlxsw_core_port_driver_priv(mlxsw_core_port); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 local_port = mlxsw_sp_port->local_port; + u8 pool = pool_get(pool_index); + enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index); + struct mlxsw_sp_sb_pm *pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, + pool, dir); + + *p_cur = MLXSW_SP_CELLS_TO_BYTES(pm->occ.cur); + *p_max = MLXSW_SP_CELLS_TO_BYTES(pm->occ.max); + return 0; +} + +int mlxsw_sp_sb_occ_tc_port_bind_get(struct mlxsw_core_port *mlxsw_core_port, + unsigned int sb_index, u16 tc_index, + enum devlink_sb_pool_type pool_type, + u32 *p_cur, u32 *p_max) +{ + struct mlxsw_sp_port *mlxsw_sp_port = + mlxsw_core_port_driver_priv(mlxsw_core_port); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 local_port = mlxsw_sp_port->local_port; + u8 pg_buff = tc_index; + enum mlxsw_reg_sbxx_dir dir = pool_type; + struct mlxsw_sp_sb_cm *cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, + pg_buff, dir); + + *p_cur = MLXSW_SP_CELLS_TO_BYTES(cm->occ.cur); + *p_max = MLXSW_SP_CELLS_TO_BYTES(cm->occ.max); + return 0; +} -- GitLab From 518f213dddb3375e8cf0fcb791dda4c7d1ce4c74 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sun, 10 Apr 2016 21:44:44 -0400 Subject: [PATCH 2828/9938] ethtool: Add support for toggling any of the GSO offloads The strings were missing for several of the GSO offloads that are available. This patch provides the missing strings so that we can toggle or query any of them via the ethtool command. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/core/ethtool.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index f426c5ad6149..6a7f99661c2f 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -82,9 +82,11 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation", [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation", + [NETIF_F_GSO_GRE_CSUM_BIT] = "tx-gre-csum-segmentation", [NETIF_F_GSO_IPIP_BIT] = "tx-ipip-segmentation", [NETIF_F_GSO_SIT_BIT] = "tx-sit-segmentation", [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", + [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation", [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", [NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp", -- GitLab From cbc53e08a793b073e79f42ca33f1f3568703540d Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sun, 10 Apr 2016 21:44:51 -0400 Subject: [PATCH 2829/9938] GSO: Add GSO type for fixed IPv4 ID This patch adds support for TSO using IPv4 headers with a fixed IP ID field. This is meant to allow us to do a lossless GRO in the case of TCP flows that use a fixed IP ID such as those that convert IPv6 header to IPv4 headers. In addition I am adding a feature that for now I am referring to TSO with IP ID mangling. Basically when this flag is enabled the device has the option to either output the flow with incrementing IP IDs or with a fixed IP ID regardless of what the original IP ID ordering was. This is useful in cases where the DF bit is set and we do not care if the original IP ID value is maintained. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- include/linux/netdev_features.h | 3 +++ include/linux/netdevice.h | 1 + include/linux/skbuff.h | 20 ++++++++++--------- net/core/dev.c | 34 ++++++++++++++++++++++++++++----- net/core/ethtool.c | 1 + net/ipv4/af_inet.c | 19 ++++++++++-------- net/ipv4/gre_offload.c | 1 + net/ipv4/tcp_offload.c | 4 +++- net/ipv6/ip6_offload.c | 3 ++- net/mpls/mpls_gso.c | 1 + 10 files changed, 63 insertions(+), 24 deletions(-) diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index a734bf43d190..7cf272a4b5c8 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -39,6 +39,7 @@ enum { NETIF_F_UFO_BIT, /* ... UDPv4 fragmentation */ NETIF_F_GSO_ROBUST_BIT, /* ... ->SKB_GSO_DODGY */ NETIF_F_TSO_ECN_BIT, /* ... TCP ECN support */ + NETIF_F_TSO_MANGLEID_BIT, /* ... IPV4 ID mangling allowed */ NETIF_F_TSO6_BIT, /* ... TCPv6 segmentation */ NETIF_F_FSO_BIT, /* ... FCoE segmentation */ NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */ @@ -120,6 +121,7 @@ enum { #define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT) #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) #define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM) +#define NETIF_F_TSO_MANGLEID __NETIF_F(TSO_MANGLEID) #define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM) #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) #define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX) @@ -147,6 +149,7 @@ enum { /* List of features with software fallbacks. */ #define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ + NETIF_F_TSO_MANGLEID | \ NETIF_F_TSO6 | NETIF_F_UFO) /* List of IP checksum features. Note that NETIF_F_ HW_CSUM should not be diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9884fe9a6552..8e372d01b3c1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3992,6 +3992,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type) BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_UFO >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_DODGY != (NETIF_F_GSO_ROBUST >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT)); + BUILD_BUG_ON(SKB_GSO_TCP_FIXEDID != (NETIF_F_TSO_MANGLEID >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT)); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 007381270ff8..5fba16658f9d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -465,23 +465,25 @@ enum { /* This indicates the tcp segment has CWR set. */ SKB_GSO_TCP_ECN = 1 << 3, - SKB_GSO_TCPV6 = 1 << 4, + SKB_GSO_TCP_FIXEDID = 1 << 4, - SKB_GSO_FCOE = 1 << 5, + SKB_GSO_TCPV6 = 1 << 5, - SKB_GSO_GRE = 1 << 6, + SKB_GSO_FCOE = 1 << 6, - SKB_GSO_GRE_CSUM = 1 << 7, + SKB_GSO_GRE = 1 << 7, - SKB_GSO_IPIP = 1 << 8, + SKB_GSO_GRE_CSUM = 1 << 8, - SKB_GSO_SIT = 1 << 9, + SKB_GSO_IPIP = 1 << 9, - SKB_GSO_UDP_TUNNEL = 1 << 10, + SKB_GSO_SIT = 1 << 10, - SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11, + SKB_GSO_UDP_TUNNEL = 1 << 11, - SKB_GSO_TUNNEL_REMCSUM = 1 << 12, + SKB_GSO_UDP_TUNNEL_CSUM = 1 << 12, + + SKB_GSO_TUNNEL_REMCSUM = 1 << 13, }; #if BITS_PER_LONG > 32 diff --git a/net/core/dev.c b/net/core/dev.c index 09fb1ace9dc8..e896b1953ab6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2825,14 +2825,36 @@ static netdev_features_t dflt_features_check(const struct sk_buff *skb, return vlan_features_check(skb, features); } +static netdev_features_t gso_features_check(const struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + u16 gso_segs = skb_shinfo(skb)->gso_segs; + + if (gso_segs > dev->gso_max_segs) + return features & ~NETIF_F_GSO_MASK; + + /* Make sure to clear the IPv4 ID mangling feature if + * the IPv4 header has the potential to be fragmented. + */ + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { + struct iphdr *iph = skb->encapsulation ? + inner_ip_hdr(skb) : ip_hdr(skb); + + if (!(iph->frag_off & htons(IP_DF))) + features &= ~NETIF_F_TSO_MANGLEID; + } + + return features; +} + netdev_features_t netif_skb_features(struct sk_buff *skb) { struct net_device *dev = skb->dev; netdev_features_t features = dev->features; - u16 gso_segs = skb_shinfo(skb)->gso_segs; - if (gso_segs > dev->gso_max_segs) - features &= ~NETIF_F_GSO_MASK; + if (skb_is_gso(skb)) + features = gso_features_check(skb, dev, features); /* If encapsulation offload request, verify we are testing * hardware encapsulation features instead of standard @@ -6976,9 +6998,11 @@ int register_netdevice(struct net_device *dev) dev->features |= NETIF_F_SOFT_FEATURES; dev->wanted_features = dev->features & dev->hw_features; - if (!(dev->flags & IFF_LOOPBACK)) { + if (!(dev->flags & IFF_LOOPBACK)) dev->hw_features |= NETIF_F_NOCACHE_COPY; - } + + if (dev->hw_features & NETIF_F_TSO) + dev->hw_features |= NETIF_F_TSO_MANGLEID; /* Make NETIF_F_HIGHDMA inheritable to VLAN devices. */ diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 6a7f99661c2f..9494c41cc77c 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -79,6 +79,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] [NETIF_F_UFO_BIT] = "tx-udp-fragmentation", [NETIF_F_GSO_ROBUST_BIT] = "tx-gso-robust", [NETIF_F_TSO_ECN_BIT] = "tx-tcp-ecn-segmentation", + [NETIF_F_TSO_MANGLEID_BIT] = "tx-tcp-mangleid-segmentation", [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation", [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation", diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8217cd22f921..5bbea9a0ce96 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1195,10 +1195,10 @@ EXPORT_SYMBOL(inet_sk_rebuild_header); static struct sk_buff *inet_gso_segment(struct sk_buff *skb, netdev_features_t features) { + bool udpfrag = false, fixedid = false, encap; struct sk_buff *segs = ERR_PTR(-EINVAL); const struct net_offload *ops; unsigned int offset = 0; - bool udpfrag, encap; struct iphdr *iph; int proto; int nhoff; @@ -1217,6 +1217,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, SKB_GSO_TCPV6 | SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM | + SKB_GSO_TCP_FIXEDID | SKB_GSO_TUNNEL_REMCSUM | 0))) goto out; @@ -1248,11 +1249,14 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, segs = ERR_PTR(-EPROTONOSUPPORT); - if (skb->encapsulation && - skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) - udpfrag = proto == IPPROTO_UDP && encap; - else - udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; + if (!skb->encapsulation || encap) { + udpfrag = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP); + fixedid = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID); + + /* fixed ID is invalid if DF bit is not set */ + if (fixedid && !(iph->frag_off & htons(IP_DF))) + goto out; + } ops = rcu_dereference(inet_offloads[proto]); if (likely(ops && ops->callbacks.gso_segment)) @@ -1265,12 +1269,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, do { iph = (struct iphdr *)(skb_mac_header(skb) + nhoff); if (udpfrag) { - iph->id = htons(id); iph->frag_off = htons(offset >> 3); if (skb->next) iph->frag_off |= htons(IP_MF); offset += skb->len - nhoff - ihl; - } else { + } else if (!fixedid) { iph->id = htons(id++); } iph->tot_len = htons(skb->len - nhoff); diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 6a5bd4317866..6376b0cdf693 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -32,6 +32,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_TCP_ECN | + SKB_GSO_TCP_FIXEDID | SKB_GSO_GRE | SKB_GSO_GRE_CSUM | SKB_GSO_IPIP | diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 773083b7f1e9..08dd25d835af 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -89,6 +89,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, ~(SKB_GSO_TCPV4 | SKB_GSO_DODGY | SKB_GSO_TCP_ECN | + SKB_GSO_TCP_FIXEDID | SKB_GSO_TCPV6 | SKB_GSO_GRE | SKB_GSO_GRE_CSUM | @@ -98,7 +99,8 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, SKB_GSO_UDP_TUNNEL_CSUM | SKB_GSO_TUNNEL_REMCSUM | 0) || - !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) + !(type & (SKB_GSO_TCPV4 | + SKB_GSO_TCPV6)))) goto out; skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 204af2219471..b3a779393d71 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -73,6 +73,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_TCP_ECN | + SKB_GSO_TCP_FIXEDID | + SKB_GSO_TCPV6 | SKB_GSO_GRE | SKB_GSO_GRE_CSUM | SKB_GSO_IPIP | @@ -80,7 +82,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM | SKB_GSO_TUNNEL_REMCSUM | - SKB_GSO_TCPV6 | 0))) goto out; diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c index 0183b32da942..bbcf60465e5c 100644 --- a/net/mpls/mpls_gso.c +++ b/net/mpls/mpls_gso.c @@ -31,6 +31,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, SKB_GSO_TCPV6 | SKB_GSO_UDP | SKB_GSO_DODGY | + SKB_GSO_TCP_FIXEDID | SKB_GSO_TCP_ECN))) goto out; -- GitLab From 1530545ed64b42e87acb43c0c16401bd1ebae6bf Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sun, 10 Apr 2016 21:44:57 -0400 Subject: [PATCH 2830/9938] GRO: Add support for TCP with fixed IPv4 ID field, limit tunnel IP ID values This patch does two things. First it allows TCP to aggregate TCP frames with a fixed IPv4 ID field. As a result we should now be able to aggregate flows that were converted from IPv6 to IPv4. In addition this allows us more flexibility for future implementations of segmentation as we may be able to use a fixed IP ID when segmenting the flow. The second thing this does is that it places limitations on the outer IPv4 ID header in the case of tunneled frames. Specifically it forces the IP ID to be incrementing by 1 unless the DF bit is set in the outer IPv4 header. This way we can avoid creating overlapping series of IP IDs that could possibly be fragmented if the frame goes through GRO and is then resegmented via GSO. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- include/linux/netdevice.h | 5 ++++- net/core/dev.c | 1 + net/ipv4/af_inet.c | 35 ++++++++++++++++++++++++++++------- net/ipv4/tcp_offload.c | 16 +++++++++++++++- net/ipv6/ip6_offload.c | 8 ++++++-- 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8e372d01b3c1..2d70c521d516 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2121,7 +2121,10 @@ struct napi_gro_cb { /* Used in GRE, set in fou/gue_gro_receive */ u8 is_fou:1; - /* 6 bit hole */ + /* Used to determine if flush_id can be ignored */ + u8 is_atomic:1; + + /* 5 bit hole */ /* used to support CHECKSUM_COMPLETE for tunneling protocols */ __wsum csum; diff --git a/net/core/dev.c b/net/core/dev.c index e896b1953ab6..b78b586b1856 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4462,6 +4462,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff NAPI_GRO_CB(skb)->free = 0; NAPI_GRO_CB(skb)->encap_mark = 0; NAPI_GRO_CB(skb)->is_fou = 0; + NAPI_GRO_CB(skb)->is_atomic = 1; NAPI_GRO_CB(skb)->gro_remcsum_start = 0; /* Setup for GRO checksum validation */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 5bbea9a0ce96..8564cab96189 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1328,6 +1328,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, for (p = *head; p; p = p->next) { struct iphdr *iph2; + u16 flush_id; if (!NAPI_GRO_CB(p)->same_flow) continue; @@ -1351,16 +1352,36 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, (iph->tos ^ iph2->tos) | ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)); - /* Save the IP ID check to be included later when we get to - * the transport layer so only the inner most IP ID is checked. - * This is because some GSO/TSO implementations do not - * correctly increment the IP ID for the outer hdrs. - */ - NAPI_GRO_CB(p)->flush_id = - ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id); NAPI_GRO_CB(p)->flush |= flush; + + /* We need to store of the IP ID check to be included later + * when we can verify that this packet does in fact belong + * to a given flow. + */ + flush_id = (u16)(id - ntohs(iph2->id)); + + /* This bit of code makes it much easier for us to identify + * the cases where we are doing atomic vs non-atomic IP ID + * checks. Specifically an atomic check can return IP ID + * values 0 - 0xFFFF, while a non-atomic check can only + * return 0 or 0xFFFF. + */ + if (!NAPI_GRO_CB(p)->is_atomic || + !(iph->frag_off & htons(IP_DF))) { + flush_id ^= NAPI_GRO_CB(p)->count; + flush_id = flush_id ? 0xFFFF : 0; + } + + /* If the previous IP ID value was based on an atomic + * datagram we can overwrite the value and ignore it. + */ + if (NAPI_GRO_CB(skb)->is_atomic) + NAPI_GRO_CB(p)->flush_id = flush_id; + else + NAPI_GRO_CB(p)->flush_id |= flush_id; } + NAPI_GRO_CB(skb)->is_atomic = !!(iph->frag_off & htons(IP_DF)); NAPI_GRO_CB(skb)->flush |= flush; skb_set_network_header(skb, off); /* The above will be needed by the transport layer if there is one diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 08dd25d835af..d1ffd55289bd 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -239,7 +239,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) found: /* Include the IP ID check below from the inner most IP hdr */ - flush = NAPI_GRO_CB(p)->flush | NAPI_GRO_CB(p)->flush_id; + flush = NAPI_GRO_CB(p)->flush; flush |= (__force int)(flags & TCP_FLAG_CWR); flush |= (__force int)((flags ^ tcp_flag_word(th2)) & ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); @@ -248,6 +248,17 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) flush |= *(u32 *)((u8 *)th + i) ^ *(u32 *)((u8 *)th2 + i); + /* When we receive our second frame we can made a decision on if we + * continue this flow as an atomic flow with a fixed ID or if we use + * an incrementing ID. + */ + if (NAPI_GRO_CB(p)->flush_id != 1 || + NAPI_GRO_CB(p)->count != 1 || + !NAPI_GRO_CB(p)->is_atomic) + flush |= NAPI_GRO_CB(p)->flush_id; + else + NAPI_GRO_CB(p)->is_atomic = false; + mss = skb_shinfo(p)->gso_size; flush |= (len - 1) >= mss; @@ -316,6 +327,9 @@ static int tcp4_gro_complete(struct sk_buff *skb, int thoff) iph->daddr, 0); skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4; + if (NAPI_GRO_CB(skb)->is_atomic) + skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_FIXEDID; + return tcp_gro_complete(skb); } diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index b3a779393d71..061adcda65f3 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -240,10 +240,14 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000)); NAPI_GRO_CB(p)->flush |= flush; - /* Clear flush_id, there's really no concept of ID in IPv6. */ - NAPI_GRO_CB(p)->flush_id = 0; + /* If the previous IP ID value was based on an atomic + * datagram we can overwrite the value and ignore it. + */ + if (NAPI_GRO_CB(skb)->is_atomic) + NAPI_GRO_CB(p)->flush_id = 0; } + NAPI_GRO_CB(skb)->is_atomic = true; NAPI_GRO_CB(skb)->flush |= flush; skb_gro_postpull_rcsum(skb, iph, nlen); -- GitLab From 802ab55adc39a06940a1b384e9fd0387fc762d7e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sun, 10 Apr 2016 21:45:03 -0400 Subject: [PATCH 2831/9938] GSO: Support partial segmentation offload This patch adds support for something I am referring to as GSO partial. The basic idea is that we can support a broader range of devices for segmentation if we use fixed outer headers and have the hardware only really deal with segmenting the inner header. The idea behind the naming is due to the fact that everything before csum_start will be fixed headers, and everything after will be the region that is handled by hardware. With the current implementation it allows us to add support for the following GSO types with an inner TSO_MANGLEID or TSO6 offload: NETIF_F_GSO_GRE NETIF_F_GSO_GRE_CSUM NETIF_F_GSO_IPIP NETIF_F_GSO_SIT NETIF_F_UDP_TUNNEL NETIF_F_UDP_TUNNEL_CSUM In the case of hardware that already supports tunneling we may be able to extend this further to support TSO_TCPV4 without TSO_MANGLEID if the hardware can support updating inner IPv4 headers. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- include/linux/netdev_features.h | 5 +++++ include/linux/netdevice.h | 2 ++ include/linux/skbuff.h | 9 +++++++-- net/core/dev.c | 36 ++++++++++++++++++++++++++++++--- net/core/ethtool.c | 1 + net/core/skbuff.c | 29 +++++++++++++++++++++++++- net/ipv4/af_inet.c | 20 ++++++++++++++---- net/ipv4/gre_offload.c | 26 +++++++++++++++++++----- net/ipv4/tcp_offload.c | 10 +++++++-- net/ipv4/udp_offload.c | 27 +++++++++++++++++++------ net/ipv6/ip6_offload.c | 10 ++++++++- 11 files changed, 151 insertions(+), 24 deletions(-) diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 7cf272a4b5c8..9fc79df0e561 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -48,6 +48,10 @@ enum { NETIF_F_GSO_SIT_BIT, /* ... SIT tunnel with TSO */ NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */ NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */ + NETIF_F_GSO_PARTIAL_BIT, /* ... Only segment inner-most L4 + * in hardware and all other + * headers in software. + */ NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */ /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */ NETIF_F_GSO_TUNNEL_REMCSUM_BIT, @@ -122,6 +126,7 @@ enum { #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) #define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM) #define NETIF_F_TSO_MANGLEID __NETIF_F(TSO_MANGLEID) +#define NETIF_F_GSO_PARTIAL __NETIF_F(GSO_PARTIAL) #define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM) #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) #define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 2d70c521d516..a3bb534576a3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1654,6 +1654,7 @@ struct net_device { netdev_features_t vlan_features; netdev_features_t hw_enc_features; netdev_features_t mpls_features; + netdev_features_t gso_partial_features; int ifindex; int group; @@ -4004,6 +4005,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type) BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT)); + BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT)); return (features & feature) == feature; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 5fba16658f9d..da0ace389fec 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -483,7 +483,9 @@ enum { SKB_GSO_UDP_TUNNEL_CSUM = 1 << 12, - SKB_GSO_TUNNEL_REMCSUM = 1 << 13, + SKB_GSO_PARTIAL = 1 << 13, + + SKB_GSO_TUNNEL_REMCSUM = 1 << 14, }; #if BITS_PER_LONG > 32 @@ -3591,7 +3593,10 @@ static inline struct sec_path *skb_sec_path(struct sk_buff *skb) * Keeps track of level of encapsulation of network headers. */ struct skb_gso_cb { - int mac_offset; + union { + int mac_offset; + int data_offset; + }; int encap_level; __wsum csum; __u16 csum_start; diff --git a/net/core/dev.c b/net/core/dev.c index b78b586b1856..556dd09af3b8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2711,6 +2711,19 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, return ERR_PTR(err); } + /* Only report GSO partial support if it will enable us to + * support segmentation on this frame without needing additional + * work. + */ + if (features & NETIF_F_GSO_PARTIAL) { + netdev_features_t partial_features = NETIF_F_GSO_ROBUST; + struct net_device *dev = skb->dev; + + partial_features |= dev->features & dev->gso_partial_features; + if (!skb_gso_ok(skb, features | partial_features)) + features &= ~NETIF_F_GSO_PARTIAL; + } + BUILD_BUG_ON(SKB_SGO_CB_OFFSET + sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb)); @@ -2834,8 +2847,17 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, if (gso_segs > dev->gso_max_segs) return features & ~NETIF_F_GSO_MASK; - /* Make sure to clear the IPv4 ID mangling feature if - * the IPv4 header has the potential to be fragmented. + /* Support for GSO partial features requires software + * intervention before we can actually process the packets + * so we need to strip support for any partial features now + * and we can pull them back in after we have partially + * segmented the frame. + */ + if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL)) + features &= ~dev->gso_partial_features; + + /* Make sure to clear the IPv4 ID mangling feature if the + * IPv4 header has the potential to be fragmented. */ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { struct iphdr *iph = skb->encapsulation ? @@ -6729,6 +6751,14 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, } } + /* GSO partial features require GSO partial be set */ + if ((features & dev->gso_partial_features) && + !(features & NETIF_F_GSO_PARTIAL)) { + netdev_dbg(dev, + "Dropping partially supported GSO features since no GSO partial.\n"); + features &= ~dev->gso_partial_features; + } + #ifdef CONFIG_NET_RX_BUSY_POLL if (dev->netdev_ops->ndo_busy_poll) features |= NETIF_F_BUSY_POLL; @@ -7011,7 +7041,7 @@ int register_netdevice(struct net_device *dev) /* Make NETIF_F_SG inheritable to tunnel devices. */ - dev->hw_enc_features |= NETIF_F_SG; + dev->hw_enc_features |= NETIF_F_SG | NETIF_F_GSO_PARTIAL; /* Make NETIF_F_SG inheritable to MPLS. */ diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 9494c41cc77c..e0cf20a3b3dd 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -88,6 +88,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] [NETIF_F_GSO_SIT_BIT] = "tx-sit-segmentation", [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation", + [NETIF_F_GSO_PARTIAL_BIT] = "tx-gso-partial", [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", [NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp", diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d04c2d1c8c87..4cc594cdaada 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3076,8 +3076,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, struct sk_buff *frag_skb = head_skb; unsigned int offset = doffset; unsigned int tnl_hlen = skb_tnl_header_len(head_skb); + unsigned int partial_segs = 0; unsigned int headroom; - unsigned int len; + unsigned int len = head_skb->len; __be16 proto; bool csum; int sg = !!(features & NETIF_F_SG); @@ -3094,6 +3095,15 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, csum = !!can_checksum_protocol(features, proto); + /* GSO partial only requires that we trim off any excess that + * doesn't fit into an MSS sized block, so take care of that + * now. + */ + if (features & NETIF_F_GSO_PARTIAL) { + partial_segs = len / mss; + mss *= partial_segs; + } + headroom = skb_headroom(head_skb); pos = skb_headlen(head_skb); @@ -3281,6 +3291,23 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, */ segs->prev = tail; + /* Update GSO info on first skb in partial sequence. */ + if (partial_segs) { + int type = skb_shinfo(head_skb)->gso_type; + + /* Update type to add partial and then remove dodgy if set */ + type |= SKB_GSO_PARTIAL; + type &= ~SKB_GSO_DODGY; + + /* Update GSO info and prepare to start updating headers on + * our way back down the stack of protocols. + */ + skb_shinfo(segs)->gso_size = skb_shinfo(head_skb)->gso_size; + skb_shinfo(segs)->gso_segs = partial_segs; + skb_shinfo(segs)->gso_type = type; + SKB_GSO_CB(segs)->data_offset = skb_headroom(segs) + doffset; + } + /* Following permits correct backpressure, for protocols * using skb_set_owner_w(). * Idea is to tranfert ownership from head_skb to last segment. diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8564cab96189..2e6e65fc4d20 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1200,7 +1200,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, const struct net_offload *ops; unsigned int offset = 0; struct iphdr *iph; - int proto; + int proto, tot_len; int nhoff; int ihl; int id; @@ -1219,6 +1219,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, SKB_GSO_UDP_TUNNEL_CSUM | SKB_GSO_TCP_FIXEDID | SKB_GSO_TUNNEL_REMCSUM | + SKB_GSO_PARTIAL | 0))) goto out; @@ -1273,10 +1274,21 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, if (skb->next) iph->frag_off |= htons(IP_MF); offset += skb->len - nhoff - ihl; - } else if (!fixedid) { - iph->id = htons(id++); + tot_len = skb->len - nhoff; + } else if (skb_is_gso(skb)) { + if (!fixedid) { + iph->id = htons(id); + id += skb_shinfo(skb)->gso_segs; + } + tot_len = skb_shinfo(skb)->gso_size + + SKB_GSO_CB(skb)->data_offset + + skb->head - (unsigned char *)iph; + } else { + if (!fixedid) + iph->id = htons(id++); + tot_len = skb->len - nhoff; } - iph->tot_len = htons(skb->len - nhoff); + iph->tot_len = htons(tot_len); ip_send_check(iph); if (encap) skb_reset_inner_headers(skb); diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 6376b0cdf693..20557f211408 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -36,7 +36,8 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, SKB_GSO_GRE | SKB_GSO_GRE_CSUM | SKB_GSO_IPIP | - SKB_GSO_SIT))) + SKB_GSO_SIT | + SKB_GSO_PARTIAL))) goto out; if (!skb->encapsulation) @@ -87,7 +88,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, skb = segs; do { struct gre_base_hdr *greh; - __be32 *pcsum; + __sum16 *pcsum; /* Set up inner headers if we are offloading inner checksum */ if (skb->ip_summed == CHECKSUM_PARTIAL) { @@ -107,10 +108,25 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, continue; greh = (struct gre_base_hdr *)skb_transport_header(skb); - pcsum = (__be32 *)(greh + 1); + pcsum = (__sum16 *)(greh + 1); + + if (skb_is_gso(skb)) { + unsigned int partial_adj; + + /* Adjust checksum to account for the fact that + * the partial checksum is based on actual size + * whereas headers should be based on MSS size. + */ + partial_adj = skb->len + skb_headroom(skb) - + SKB_GSO_CB(skb)->data_offset - + skb_shinfo(skb)->gso_size; + *pcsum = ~csum_fold((__force __wsum)htonl(partial_adj)); + } else { + *pcsum = 0; + } - *pcsum = 0; - *(__sum16 *)pcsum = gso_make_checksum(skb, 0); + *(pcsum + 1) = 0; + *pcsum = gso_make_checksum(skb, 0); } while ((skb = skb->next)); out: return segs; diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index d1ffd55289bd..02737b607aa7 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -109,6 +109,12 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, goto out; } + /* GSO partial only requires splitting the frame into an MSS + * multiple and possibly a remainder. So update the mss now. + */ + if (features & NETIF_F_GSO_PARTIAL) + mss = skb->len - (skb->len % mss); + copy_destructor = gso_skb->destructor == tcp_wfree; ooo_okay = gso_skb->ooo_okay; /* All segments but the first should have ooo_okay cleared */ @@ -133,7 +139,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, newcheck = ~csum_fold((__force __wsum)((__force u32)th->check + (__force u32)delta)); - do { + while (skb->next) { th->fin = th->psh = 0; th->check = newcheck; @@ -153,7 +159,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, th->seq = htonl(seq); th->cwr = 0; - } while (skb->next); + } /* Following permits TCP Small Queues to work well with GSO : * The callback to TCP stack will be called at the time last frag diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 6230cf4b0d2d..097060def7f0 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -39,8 +39,11 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, * 16 bit length field due to the header being added outside of an * IP or IPv6 frame that was already limited to 64K - 1. */ - partial = csum_sub(csum_unfold(uh->check), - (__force __wsum)htonl(skb->len)); + if (skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) + partial = (__force __wsum)uh->len; + else + partial = (__force __wsum)htonl(skb->len); + partial = csum_sub(csum_unfold(uh->check), partial); /* setup inner skb. */ skb->encapsulation = 0; @@ -89,7 +92,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, udp_offset = outer_hlen - tnl_hlen; skb = segs; do { - __be16 len; + unsigned int len; if (remcsum) skb->ip_summed = CHECKSUM_NONE; @@ -107,14 +110,26 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, skb_reset_mac_header(skb); skb_set_network_header(skb, mac_len); skb_set_transport_header(skb, udp_offset); - len = htons(skb->len - udp_offset); + len = skb->len - udp_offset; uh = udp_hdr(skb); - uh->len = len; + + /* If we are only performing partial GSO the inner header + * will be using a length value equal to only one MSS sized + * segment instead of the entire frame. + */ + if (skb_is_gso(skb)) { + uh->len = htons(skb_shinfo(skb)->gso_size + + SKB_GSO_CB(skb)->data_offset + + skb->head - (unsigned char *)uh); + } else { + uh->len = htons(len); + } if (!need_csum) continue; - uh->check = ~csum_fold(csum_add(partial, (__force __wsum)len)); + uh->check = ~csum_fold(csum_add(partial, + (__force __wsum)htonl(len))); if (skb->encapsulation || !offload_csum) { uh->check = gso_make_checksum(skb, ~uh->check); diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 061adcda65f3..f5eb184e1093 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -63,6 +63,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int proto; struct frag_hdr *fptr; unsigned int unfrag_ip6hlen; + unsigned int payload_len; u8 *prevhdr; int offset = 0; bool encap, udpfrag; @@ -82,6 +83,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM | SKB_GSO_TUNNEL_REMCSUM | + SKB_GSO_PARTIAL | 0))) goto out; @@ -118,7 +120,13 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, for (skb = segs; skb; skb = skb->next) { ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); - ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); + if (skb_is_gso(skb)) + payload_len = skb_shinfo(skb)->gso_size + + SKB_GSO_CB(skb)->data_offset + + skb->head - (unsigned char *)(ipv6h + 1); + else + payload_len = skb->len - nhoff - sizeof(*ipv6h); + ipv6h->payload_len = htons(payload_len); skb->network_header = (u8 *)ipv6h - skb->head; if (udpfrag) { -- GitLab From f7a6272bf3cbd2576165dba020e0329c9ca67c1f Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sun, 10 Apr 2016 21:45:09 -0400 Subject: [PATCH 2832/9938] Documentation: Add documentation for TSO and GSO features This document is a starting point for defining the TSO and GSO features. The whole thing is starting to get a bit messy so I wanted to make sure we have notes somwhere to start describing what does and doesn't work. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- .../networking/segmentation-offloads.txt | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Documentation/networking/segmentation-offloads.txt diff --git a/Documentation/networking/segmentation-offloads.txt b/Documentation/networking/segmentation-offloads.txt new file mode 100644 index 000000000000..f200467ade38 --- /dev/null +++ b/Documentation/networking/segmentation-offloads.txt @@ -0,0 +1,130 @@ +Segmentation Offloads in the Linux Networking Stack + +Introduction +============ + +This document describes a set of techniques in the Linux networking stack +to take advantage of segmentation offload capabilities of various NICs. + +The following technologies are described: + * TCP Segmentation Offload - TSO + * UDP Fragmentation Offload - UFO + * IPIP, SIT, GRE, and UDP Tunnel Offloads + * Generic Segmentation Offload - GSO + * Generic Receive Offload - GRO + * Partial Generic Segmentation Offload - GSO_PARTIAL + +TCP Segmentation Offload +======================== + +TCP segmentation allows a device to segment a single frame into multiple +frames with a data payload size specified in skb_shinfo()->gso_size. +When TCP segmentation requested the bit for either SKB_GSO_TCP or +SKB_GSO_TCP6 should be set in skb_shinfo()->gso_type and +skb_shinfo()->gso_size should be set to a non-zero value. + +TCP segmentation is dependent on support for the use of partial checksum +offload. For this reason TSO is normally disabled if the Tx checksum +offload for a given device is disabled. + +In order to support TCP segmentation offload it is necessary to populate +the network and transport header offsets of the skbuff so that the device +drivers will be able determine the offsets of the IP or IPv6 header and the +TCP header. In addition as CHECKSUM_PARTIAL is required csum_start should +also point to the TCP header of the packet. + +For IPv4 segmentation we support one of two types in terms of the IP ID. +The default behavior is to increment the IP ID with every segment. If the +GSO type SKB_GSO_TCP_FIXEDID is specified then we will not increment the IP +ID and all segments will use the same IP ID. If a device has +NETIF_F_TSO_MANGLEID set then the IP ID can be ignored when performing TSO +and we will either increment the IP ID for all frames, or leave it at a +static value based on driver preference. + +UDP Fragmentation Offload +========================= + +UDP fragmentation offload allows a device to fragment an oversized UDP +datagram into multiple IPv4 fragments. Many of the requirements for UDP +fragmentation offload are the same as TSO. However the IPv4 ID for +fragments should not increment as a single IPv4 datagram is fragmented. + +IPIP, SIT, GRE, UDP Tunnel, and Remote Checksum Offloads +======================================================== + +In addition to the offloads described above it is possible for a frame to +contain additional headers such as an outer tunnel. In order to account +for such instances an additional set of segmentation offload types were +introduced including SKB_GSO_IPIP, SKB_GSO_SIT, SKB_GSO_GRE, and +SKB_GSO_UDP_TUNNEL. These extra segmentation types are used to identify +cases where there are more than just 1 set of headers. For example in the +case of IPIP and SIT we should have the network and transport headers moved +from the standard list of headers to "inner" header offsets. + +Currently only two levels of headers are supported. The convention is to +refer to the tunnel headers as the outer headers, while the encapsulated +data is normally referred to as the inner headers. Below is the list of +calls to access the given headers: + +IPIP/SIT Tunnel: + Outer Inner +MAC skb_mac_header +Network skb_network_header skb_inner_network_header +Transport skb_transport_header + +UDP/GRE Tunnel: + Outer Inner +MAC skb_mac_header skb_inner_mac_header +Network skb_network_header skb_inner_network_header +Transport skb_transport_header skb_inner_transport_header + +In addition to the above tunnel types there are also SKB_GSO_GRE_CSUM and +SKB_GSO_UDP_TUNNEL_CSUM. These two additional tunnel types reflect the +fact that the outer header also requests to have a non-zero checksum +included in the outer header. + +Finally there is SKB_GSO_REMCSUM which indicates that a given tunnel header +has requested a remote checksum offload. In this case the inner headers +will be left with a partial checksum and only the outer header checksum +will be computed. + +Generic Segmentation Offload +============================ + +Generic segmentation offload is a pure software offload that is meant to +deal with cases where device drivers cannot perform the offloads described +above. What occurs in GSO is that a given skbuff will have its data broken +out over multiple skbuffs that have been resized to match the MSS provided +via skb_shinfo()->gso_size. + +Before enabling any hardware segmentation offload a corresponding software +offload is required in GSO. Otherwise it becomes possible for a frame to +be re-routed between devices and end up being unable to be transmitted. + +Generic Receive Offload +======================= + +Generic receive offload is the complement to GSO. Ideally any frame +assembled by GRO should be segmented to create an identical sequence of +frames using GSO, and any sequence of frames segmented by GSO should be +able to be reassembled back to the original by GRO. The only exception to +this is IPv4 ID in the case that the DF bit is set for a given IP header. +If the value of the IPv4 ID is not sequentially incrementing it will be +altered so that it is when a frame assembled via GRO is segmented via GSO. + +Partial Generic Segmentation Offload +==================================== + +Partial generic segmentation offload is a hybrid between TSO and GSO. What +it effectively does is take advantage of certain traits of TCP and tunnels +so that instead of having to rewrite the packet headers for each segment +only the inner-most transport header and possibly the outer-most network +header need to be updated. This allows devices that do not support tunnel +offloads or tunnel offloads with checksum to still make use of segmentation. + +With the partial offload what occurs is that all headers excluding the +inner transport header are updated such that they will contain the correct +values for if the header was simply duplicated. The one exception to this +is the outer IPv4 ID field. It is up to the device drivers to guarantee +that the IPv4 ID field is incremented in the case that a given header does +not have the DF bit set. -- GitLab From 71815b1825d64c15ca25d4aa3cbad10b02d3981e Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Wed, 13 Apr 2016 10:44:15 +0200 Subject: [PATCH 2833/9938] ARM: dts: am335x-chili*: Move uart0 description from SOM to board uart0 configuration code has been in SOM. However, it is possible to use all (or none) of 6 uart's of AM335x processor present on ChiliSOM. This fix moves declaration of uart0 from ChiliSOM to ChiliBoard, because use of uart is strictly board-specific. Signed-off-by: Marcin Niestroj Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-chiliboard.dts | 14 ++++++++++++++ arch/arm/boot/dts/am335x-chilisom.dtsi | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/am335x-chiliboard.dts b/arch/arm/boot/dts/am335x-chiliboard.dts index 15d47ab28865..4aae702fae03 100644 --- a/arch/arm/boot/dts/am335x-chiliboard.dts +++ b/arch/arm/boot/dts/am335x-chiliboard.dts @@ -35,6 +35,13 @@ }; &am33xx_pinmux { + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + usb1_drvvbus: usb1_drvvbus { pinctrl-single,pins = < AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */ @@ -61,6 +68,13 @@ }; }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + &ldo4_reg { regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/am335x-chilisom.dtsi index e48c28236baa..de98bd4fd0d9 100644 --- a/arch/arm/boot/dts/am335x-chilisom.dtsi +++ b/arch/arm/boot/dts/am335x-chilisom.dtsi @@ -35,13 +35,6 @@ >; }; - uart0_pins: pinmux_uart0_pins { - pinctrl-single,pins = < - AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ - AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ - >; - }; - cpsw_default: cpsw_default { pinctrl-single,pins = < /* Slave 1 */ @@ -109,13 +102,6 @@ }; }; -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - - status = "okay"; -}; - &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins>; -- GitLab From ce07a9bd9c6ade102fc57ec562db8eed7c7db1ad Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Wed, 13 Apr 2016 10:44:16 +0200 Subject: [PATCH 2834/9938] ARM: dts: am335x-chili*: Move Ethernet MAC description from SOM to board ChiliSOM has 2 Ethernet subsystems with different types of possibly used PHY interfaces (i.e. MII, RMII, GMII, RGMII). Current code configured pinmux for RMII on 1st Ethernet subsystem and enabled Ethernet MAC with 1 slave for all boards which use ChiliSOM. This change moves pinmux configuration of 1st Ethernet subsystem to ChiliBoard description, as this is board-specific. Signed-off-by: Marcin Niestroj Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-chiliboard.dts | 61 ++++++++++++++++++++++++ arch/arm/boot/dts/am335x-chilisom.dtsi | 62 ------------------------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/arch/arm/boot/dts/am335x-chiliboard.dts b/arch/arm/boot/dts/am335x-chiliboard.dts index 4aae702fae03..2a624b3c9258 100644 --- a/arch/arm/boot/dts/am335x-chiliboard.dts +++ b/arch/arm/boot/dts/am335x-chiliboard.dts @@ -42,6 +42,52 @@ >; }; + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */ + AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */ + AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */ + AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii_ref_clk */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) + /* mdio_clk.mdio_clk */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + usb1_drvvbus: usb1_drvvbus { pinctrl-single,pins = < AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */ @@ -81,6 +127,21 @@ }; /* Ethernet */ +&mac { + slaves = <1>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + &cpsw_emac0 { phy_id = <&davinci_mdio>, <0>; phy-mode = "rmii"; diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/am335x-chilisom.dtsi index de98bd4fd0d9..5ae8434b7508 100644 --- a/arch/arm/boot/dts/am335x-chilisom.dtsi +++ b/arch/arm/boot/dts/am335x-chilisom.dtsi @@ -35,52 +35,6 @@ >; }; - cpsw_default: cpsw_default { - pinctrl-single,pins = < - /* Slave 1 */ - AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */ - AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */ - AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */ - AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ - AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ - AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ - AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ - AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii_ref_clk */ - >; - }; - - cpsw_sleep: cpsw_sleep { - pinctrl-single,pins = < - /* Slave 1 reset value */ - AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) - >; - }; - - davinci_mdio_default: davinci_mdio_default { - pinctrl-single,pins = < - /* mdio_data.mdio_data */ - AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) - /* mdio_clk.mdio_clk */ - AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) - >; - }; - - davinci_mdio_sleep: davinci_mdio_sleep { - pinctrl-single,pins = < - /* MDIO reset value */ - AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) - >; - }; - nandflash_pins: nandflash_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ @@ -168,22 +122,6 @@ }; }; -/* Ethernet MAC */ -&mac { - slaves = <1>; - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&cpsw_default>; - pinctrl-1 = <&cpsw_sleep>; - status = "okay"; -}; - -&davinci_mdio { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&davinci_mdio_default>; - pinctrl-1 = <&davinci_mdio_sleep>; - status = "okay"; -}; - /* NAND Flash */ &elm { status = "okay"; -- GitLab From 1ae5762dd67710626248097eb89d165535c8cdd5 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Wed, 13 Apr 2016 10:44:17 +0200 Subject: [PATCH 2835/9938] ARM: dts: am335x-chilisom: Enable poweroff PMIC sequence using RTC signal ChiliSOM has TPS65217's PWR_EN pin connected to AM335x PMIC_POWER_EN pin. Processor's PMIC_POWER_EN is controlled by it's internal RTC, hence RTC subsystem is responsible for proper board poweroff sequence. This change enables complete poweroff sequence for ChiliBoard, switching PMIC's state from ACTIVE to SLEEP. Signed-off-by: Marcin Niestroj Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-chilisom.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/am335x-chilisom.dtsi index 5ae8434b7508..1d647358f1c1 100644 --- a/arch/arm/boot/dts/am335x-chilisom.dtsi +++ b/arch/arm/boot/dts/am335x-chilisom.dtsi @@ -122,6 +122,10 @@ }; }; +&rtc { + system-power-controller; +}; + /* NAND Flash */ &elm { status = "okay"; -- GitLab From a4240d3af6771339c3557afe261a8a89573980a9 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 14 Apr 2016 12:45:58 -0500 Subject: [PATCH 2836/9938] ARM: dts: Add support for dra72-evm rev C (SR2.0) DRA72-EVM now has an upgrade to Rev C with SR2.0 silicon. As part of this change, a few updates were factored in that were software incompatible with previous board in few areas: - We now use DP83867 ethernet phy instead of older DP838865 which fails in certain use cases. - Two Ethernet ports now instead of the single one in rev B. - polarities changed for certain pcf gpios - Due to SoC phy current requirements, VDDA supplies are split between ldo3 and ldo2 (ldo2 was previously unused). NOTE: DSS (VDDA_VIDEO) is still supplied by ldo5, HDMI is now supplied by LDO2 instead of using LDO3. NOTE: It does not make much sense to spin off a new board compatible flag since there is no real benefit for the same. Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/dra72-evm-common.dtsi | 833 +++++++++++++++++++++++ arch/arm/boot/dts/dra72-evm-revc.dts | 73 +++ arch/arm/boot/dts/dra72-evm.dts | 838 +----------------------- 4 files changed, 921 insertions(+), 826 deletions(-) create mode 100644 arch/arm/boot/dts/dra72-evm-common.dtsi create mode 100644 arch/arm/boot/dts/dra72-evm-revc.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index a721c4cc3548..e32392228748 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -530,7 +530,8 @@ dtb-$(CONFIG_SOC_DRA7XX) += \ am57xx-sbc-am57x.dtb \ am572x-idk.dtb \ dra7-evm.dtb \ - dra72-evm.dtb + dra72-evm.dtb \ + dra72-evm-revc.dtb dtb-$(CONFIG_ARCH_ORION5X) += \ orion5x-lacie-d2-network.dtb \ orion5x-lacie-ethernet-disk-mini-v2.dtb \ diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi new file mode 100644 index 000000000000..2c880501ba2e --- /dev/null +++ b/arch/arm/boot/dts/dra72-evm-common.dtsi @@ -0,0 +1,833 @@ +/* + * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +/dts-v1/; + +#include "dra72x.dtsi" +#include +#include + +/ { + compatible = "ti,dra72-evm", "ti,dra722", "ti,dra72", "ti,dra7"; + + aliases { + display0 = &hdmi0; + }; + + evm_3v3: fixedregulator-evm_3v3 { + compatible = "regulator-fixed"; + regulator-name = "evm_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + aic_dvdd: fixedregulator-aic_dvdd { + /* TPS77018DBVT */ + compatible = "regulator-fixed"; + regulator-name = "aic_dvdd"; + vin-supply = <&evm_3v3>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + evm_3v3_sd: fixedregulator-sd { + compatible = "regulator-fixed"; + regulator-name = "evm_3v3_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pcf_gpio_21 5 GPIO_ACTIVE_HIGH>; + }; + + extcon_usb1: extcon_usb1 { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>; + }; + + extcon_usb2: extcon_usb2 { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>; + }; + + hdmi0: connector { + compatible = "hdmi-connector"; + label = "hdmi"; + + type = "a"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&tpd12s015_out>; + }; + }; + }; + + tpd12s015: encoder { + compatible = "ti,tpd12s015"; + + pinctrl-names = "default"; + pinctrl-0 = <&tpd12s015_pins>; + + gpios = <&pcf_hdmi 4 GPIO_ACTIVE_HIGH>, /* P4, CT CP HPD */ + <&pcf_hdmi 5 GPIO_ACTIVE_HIGH>, /* P5, LS OE */ + <&gpio7 12 GPIO_ACTIVE_HIGH>; /* gpio7_12/sp1_cs2, HPD */ + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpd12s015_in: endpoint { + remote-endpoint = <&hdmi_out>; + }; + }; + + port@1 { + reg = <1>; + + tpd12s015_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; + }; + }; + }; + + sound0: sound0 { + compatible = "simple-audio-card"; + simple-audio-card,name = "DRA7xx-EVM"; + simple-audio-card,widgets = + "Headphone", "Headphone Jack", + "Line", "Line Out", + "Microphone", "Mic Jack", + "Line", "Line In"; + simple-audio-card,routing = + "Headphone Jack", "HPLOUT", + "Headphone Jack", "HPROUT", + "Line Out", "LLOUT", + "Line Out", "RLOUT", + "MIC3L", "Mic Jack", + "MIC3R", "Mic Jack", + "Mic Jack", "Mic Bias", + "LINE1L", "Line In", + "LINE1R", "Line In"; + simple-audio-card,format = "dsp_b"; + simple-audio-card,bitclock-master = <&sound0_master>; + simple-audio-card,frame-master = <&sound0_master>; + simple-audio-card,bitclock-inversion; + + sound0_master: simple-audio-card,cpu { + sound-dai = <&mcasp3>; + system-clock-frequency = <5644800>; + }; + + simple-audio-card,codec { + sound-dai = <&tlv320aic3106>; + clocks = <&atl_clkin2_ck>; + }; + }; +}; + +&dra7_pmx_core { + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ + DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ + >; + }; + + i2c5_pins: pinmux_i2c5_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */ + DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */ + >; + }; + + i2c5_pins: pinmux_i2c5_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */ + DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */ + >; + }; + + nand_default: nand_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT | MUX_MODE0) /* gpmc_ad0 */ + DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT | MUX_MODE0) /* gpmc_ad1 */ + DRA7XX_CORE_IOPAD(0x3408, PIN_INPUT | MUX_MODE0) /* gpmc_ad2 */ + DRA7XX_CORE_IOPAD(0x340c, PIN_INPUT | MUX_MODE0) /* gpmc_ad3 */ + DRA7XX_CORE_IOPAD(0x3410, PIN_INPUT | MUX_MODE0) /* gpmc_ad4 */ + DRA7XX_CORE_IOPAD(0x3414, PIN_INPUT | MUX_MODE0) /* gpmc_ad5 */ + DRA7XX_CORE_IOPAD(0x3418, PIN_INPUT | MUX_MODE0) /* gpmc_ad6 */ + DRA7XX_CORE_IOPAD(0x341c, PIN_INPUT | MUX_MODE0) /* gpmc_ad7 */ + DRA7XX_CORE_IOPAD(0x3420, PIN_INPUT | MUX_MODE0) /* gpmc_ad8 */ + DRA7XX_CORE_IOPAD(0x3424, PIN_INPUT | MUX_MODE0) /* gpmc_ad9 */ + DRA7XX_CORE_IOPAD(0x3428, PIN_INPUT | MUX_MODE0) /* gpmc_ad10 */ + DRA7XX_CORE_IOPAD(0x342c, PIN_INPUT | MUX_MODE0) /* gpmc_ad11 */ + DRA7XX_CORE_IOPAD(0x3430, PIN_INPUT | MUX_MODE0) /* gpmc_ad12 */ + DRA7XX_CORE_IOPAD(0x3434, PIN_INPUT | MUX_MODE0) /* gpmc_ad13 */ + DRA7XX_CORE_IOPAD(0x3438, PIN_INPUT | MUX_MODE0) /* gpmc_ad14 */ + DRA7XX_CORE_IOPAD(0x343c, PIN_INPUT | MUX_MODE0) /* gpmc_ad15 */ + DRA7XX_CORE_IOPAD(0x34b4, PIN_OUTPUT | MUX_MODE0) /* gpmc_cs0 */ + DRA7XX_CORE_IOPAD(0x34c4, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale */ + DRA7XX_CORE_IOPAD(0x34cc, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen */ + DRA7XX_CORE_IOPAD(0x34c8, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren */ + DRA7XX_CORE_IOPAD(0x34d0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0 */ + DRA7XX_CORE_IOPAD(0x34d8, PIN_INPUT | MUX_MODE0) /* gpmc_wait0 */ + >; + }; + + usb1_pins: pinmux_usb1_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */ + >; + }; + + usb2_pins: pinmux_usb2_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3684, PIN_INPUT_SLEW | MUX_MODE0) /* usb2_drvvbus */ + >; + }; + + tps65917_pins_default: tps65917_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3824, PIN_INPUT_PULLUP | MUX_MODE1) /* wakeup3.sys_nirq1 */ + >; + }; + + mmc1_pins_default: mmc1_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14) /* mmc1sdcd.gpio219 */ + DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ + DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ + DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */ + DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */ + DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */ + DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */ + >; + }; + + mmc2_pins_default: mmc2_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ + DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ + DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */ + DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */ + DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */ + DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */ + DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */ + DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */ + DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */ + DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */ + >; + }; + + dcan1_pins_default: dcan1_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */ + DRA7XX_CORE_IOPAD(0x3818, PULL_UP | MUX_MODE1) /* wakeup0.dcan1_rx */ + >; + }; + + dcan1_pins_sleep: dcan1_pins_sleep { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP) /* dcan1_tx.off */ + DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP) /* wakeup0.off */ + >; + }; + + qspi1_pins: pinmux_qspi1_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3474, PIN_OUTPUT | MUX_MODE1) /* gpmc_a13.qspi1_rtclk */ + DRA7XX_CORE_IOPAD(0x3478, PIN_INPUT | MUX_MODE1) /* gpmc_a14.qspi1_d3 */ + DRA7XX_CORE_IOPAD(0x347c, PIN_INPUT | MUX_MODE1) /* gpmc_a15.qspi1_d2 */ + DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1) /* gpmc_a16.qspi1_d1 */ + DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1) /* gpmc_a17.qspi1_d0 */ + DRA7XX_CORE_IOPAD(0x3488, PIN_OUTPUT | MUX_MODE1) /* qpmc_a18.qspi1_sclk */ + DRA7XX_CORE_IOPAD(0x34b8, PIN_OUTPUT | MUX_MODE1) /* gpmc_cs2.qspi1_cs0 */ + >; + }; + + hdmi_pins: pinmux_hdmi_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */ + DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */ + >; + }; + + tpd12s015_pins: pinmux_tpd12s015_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpio7_12 HPD */ + >; + }; + + atl_pins: pinmux_atl_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3698, PIN_OUTPUT | MUX_MODE5) /* xref_clk1.atl_clk1 */ + DRA7XX_CORE_IOPAD(0x369c, PIN_OUTPUT | MUX_MODE5) /* xref_clk2.atl_clk2 */ + >; + }; + + mcasp3_pins: pinmux_mcasp3_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_aclkx */ + DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_fsx */ + DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr0 */ + DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr1 */ + >; + }; + + mcasp3_sleep_pins: pinmux_mcasp3_sleep_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x372c, PIN_INPUT_PULLDOWN | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE15) + >; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <400000>; + + tps65917: tps65917@58 { + compatible = "ti,tps65917"; + reg = <0x58>; + + pinctrl-names = "default"; + pinctrl-0 = <&tps65917_pins_default>; + + interrupts = ; /* IRQ_SYS_1N */ + interrupt-controller; + #interrupt-cells = <2>; + + ti,system-power-controller; + + tps65917_pmic { + compatible = "ti,tps65917-pmic"; + + tps65917_regulators: regulators { + smps1_reg: smps1 { + /* VDD_MPU */ + regulator-name = "smps1"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps2_reg: smps2 { + /* VDD_CORE */ + regulator-name = "smps2"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1060000>; + regulator-boot-on; + regulator-always-on; + }; + + smps3_reg: smps3 { + /* VDD_GPU IVA DSPEVE */ + regulator-name = "smps3"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-boot-on; + regulator-always-on; + }; + + smps4_reg: smps4 { + /* VDDS1V8 */ + regulator-name = "smps4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + smps5_reg: smps5 { + /* VDD_DDR */ + regulator-name = "smps5"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: ldo1 { + /* LDO1_OUT --> SDIO */ + regulator-name = "ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + regulator-allow-bypass; + }; + + ldo3_reg: ldo3 { + /* VDDA_1V8_PHY */ + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo5_reg: ldo5 { + /* VDDA_1V8_PLL */ + regulator-name = "ldo5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo4_reg: ldo4 { + /* VDDA_3V_USB: VDDA_USBHS33 */ + regulator-name = "ldo4"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + }; + }; + + tps65917_power_button { + compatible = "ti,palmas-pwrbutton"; + interrupt-parent = <&tps65917>; + interrupts = <1 IRQ_TYPE_NONE>; + wakeup-source; + ti,palmas-long-press-seconds = <6>; + }; + }; + + pcf_gpio_21: gpio@21 { + compatible = "nxp,pcf8575"; + reg = <0x21>; + lines-initial-states = <0x1408>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + tlv320aic3106: tlv320aic3106@19 { + #sound-dai-cells = <0>; + compatible = "ti,tlv320aic3106"; + reg = <0x19>; + adc-settle-ms = <40>; + ai3x-micbias-vg = <1>; /* 2.0V */ + status = "okay"; + + /* Regulators */ + AVDD-supply = <&evm_3v3>; + IOVDD-supply = <&evm_3v3>; + DRVDD-supply = <&evm_3v3>; + DVDD-supply = <&aic_dvdd>; + }; +}; + +&i2c5 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_pins>; + clock-frequency = <400000>; + + pcf_hdmi: pcf8575@26 { + compatible = "nxp,pcf8575"; + reg = <0x26>; + gpio-controller; + #gpio-cells = <2>; + /* + * initial state is used here to keep the mdio interface + * selected on RU89 through SEL_VIN4_MUX_S0, VIN2_S1 and + * VIN2_S0 driven high otherwise Ethernet stops working + * VIN6_SEL_S0 is low, thus selecting McASP3 over VIN6 + */ + lines-initial-states = <0x0f2b>; + + p1 { + /* vin6_sel_s0: high: VIN6, low: audio */ + gpio-hog; + gpios = <1 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "vin6_sel_s0"; + }; + }; +}; + +&uart1 { + status = "okay"; + interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, + <&dra7_pmx_core 0x3e0>; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&nand_default>; + ranges = <0 0 0x08000000 0x01000000>; /* minimum GPMC partition = 16MB */ + nand@0,0 { + /* To use NAND, DIP switch SW5 must be set like so: + * SW5.1 (NAND_SELn) = ON (LOW) + * SW5.9 (GPMC_WPN) = OFF (HIGH) + */ + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* device IO registers */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */ + ti,nand-ecc-opt = "bch8"; + ti,elm-id = <&elm>; + nand-bus-width = <16>; + gpmc,device-width = <2>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <80>; + gpmc,cs-wr-off-ns = <80>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <60>; + gpmc,adv-wr-off-ns = <60>; + gpmc,we-on-ns = <10>; + gpmc,we-off-ns = <50>; + gpmc,oe-on-ns = <4>; + gpmc,oe-off-ns = <40>; + gpmc,access-ns = <40>; + gpmc,wr-access-ns = <80>; + gpmc,rd-cycle-ns = <80>; + gpmc,wr-cycle-ns = <80>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wr-data-mux-bus-ns = <0>; + /* MTD partition table */ + /* All SPL-* partitions are sized to minimal length + * which can be independently programmable. For + * NAND flash this is equal to size of erase-block */ + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "NAND.SPL"; + reg = <0x00000000 0x000020000>; + }; + partition@1 { + label = "NAND.SPL.backup1"; + reg = <0x00020000 0x00020000>; + }; + partition@2 { + label = "NAND.SPL.backup2"; + reg = <0x00040000 0x00020000>; + }; + partition@3 { + label = "NAND.SPL.backup3"; + reg = <0x00060000 0x00020000>; + }; + partition@4 { + label = "NAND.u-boot-spl-os"; + reg = <0x00080000 0x00040000>; + }; + partition@5 { + label = "NAND.u-boot"; + reg = <0x000c0000 0x00100000>; + }; + partition@6 { + label = "NAND.u-boot-env"; + reg = <0x001c0000 0x00020000>; + }; + partition@7 { + label = "NAND.u-boot-env.backup1"; + reg = <0x001e0000 0x00020000>; + }; + partition@8 { + label = "NAND.kernel"; + reg = <0x00200000 0x00800000>; + }; + partition@9 { + label = "NAND.file-system"; + reg = <0x00a00000 0x0f600000>; + }; + }; +}; + +&usb2_phy1 { + phy-supply = <&ldo4_reg>; +}; + +&usb2_phy2 { + phy-supply = <&ldo4_reg>; +}; + +&omap_dwc3_1 { + extcon = <&extcon_usb1>; +}; + +&omap_dwc3_2 { + extcon = <&extcon_usb2>; +}; + +&usb1 { + dr_mode = "peripheral"; + pinctrl-names = "default"; + pinctrl-0 = <&usb1_pins>; +}; + +&usb2 { + dr_mode = "host"; + pinctrl-names = "default"; + pinctrl-0 = <&usb2_pins>; +}; + +&mmc1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_default>; + vmmc-supply = <&evm_3v3_sd>; + vmmc_aux-supply = <&ldo1_reg>; + bus-width = <4>; + /* + * SDCD signal is not being used here - using the fact that GPIO mode + * is a viable alternative + */ + cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; + max-frequency = <192000000>; +}; + +&mmc2 { + /* SW5-3 in ON position */ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins_default>; + + vmmc-supply = <&evm_3v3>; + bus-width = <8>; + ti,non-removable; + max-frequency = <192000000>; +}; + +&dra7_pmx_core { + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 2 */ + DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3) /* vin2a_d12.rgmii1_txc */ + DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3) /* vin2a_d13.rgmii1_tctl */ + DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3) /* vin2a_d14.rgmii1_td3 */ + DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3) /* vin2a_d15.rgmii1_td2 */ + DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3) /* vin2a_d16.rgmii1_td1 */ + DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3) /* vin2a_d17.rgmii1_td0 */ + DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE3) /* vin2a_d18.rgmii1_rclk */ + DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE3) /* vin2a_d19.rgmii1_rctl */ + DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE3) /* vin2a_d20.rgmii1_rd3 */ + DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE3) /* vin2a_d21.rgmii1_rd2 */ + DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE3) /* vin2a_d22.rgmii1_rd1 */ + DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE3) /* vin2a_d23.rgmii1_rd0 */ + >; + + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 2 */ + DRA7XX_CORE_IOPAD(0x3598, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x359c, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35a0, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35a4, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35a8, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35ac, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35b0, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35b4, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35b8, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35bc, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35c0, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35c4, MUX_MODE15) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + DRA7XX_CORE_IOPAD(0x363c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_d.mdio_d */ + DRA7XX_CORE_IOPAD(0x3640, PIN_INPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x363c, MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3640, MUX_MODE15) + >; + }; +}; + +&mac { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; +}; + +&dcan1 { + status = "ok"; + pinctrl-names = "default", "sleep", "active"; + pinctrl-0 = <&dcan1_pins_sleep>; + pinctrl-1 = <&dcan1_pins_sleep>; + pinctrl-2 = <&dcan1_pins_default>; +}; + +&qspi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&qspi1_pins>; + + spi-max-frequency = <48000000>; + m25p80@0 { + compatible = "s25fl256s1"; + spi-max-frequency = <48000000>; + reg = <0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + spi-cpol; + spi-cpha; + #address-cells = <1>; + #size-cells = <1>; + + /* MTD partition table. + * The ROM checks the first four physical blocks + * for a valid file to boot and the flash here is + * 64KiB block size. + */ + partition@0 { + label = "QSPI.SPL"; + reg = <0x00000000 0x000010000>; + }; + partition@1 { + label = "QSPI.SPL.backup1"; + reg = <0x00010000 0x00010000>; + }; + partition@2 { + label = "QSPI.SPL.backup2"; + reg = <0x00020000 0x00010000>; + }; + partition@3 { + label = "QSPI.SPL.backup3"; + reg = <0x00030000 0x00010000>; + }; + partition@4 { + label = "QSPI.u-boot"; + reg = <0x00040000 0x00100000>; + }; + partition@5 { + label = "QSPI.u-boot-spl-os"; + reg = <0x00140000 0x00080000>; + }; + partition@6 { + label = "QSPI.u-boot-env"; + reg = <0x001c0000 0x00010000>; + }; + partition@7 { + label = "QSPI.u-boot-env.backup1"; + reg = <0x001d0000 0x0010000>; + }; + partition@8 { + label = "QSPI.kernel"; + reg = <0x001e0000 0x0800000>; + }; + partition@9 { + label = "QSPI.file-system"; + reg = <0x009e0000 0x01620000>; + }; + }; +}; + +&dss { + status = "ok"; + + vdda_video-supply = <&ldo5_reg>; +}; + +&hdmi { + status = "ok"; + + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pins>; + + port { + hdmi_out: endpoint { + remote-endpoint = <&tpd12s015_in>; + }; + }; +}; + +&atl { + pinctrl-names = "default"; + pinctrl-0 = <&atl_pins>; + + assigned-clocks = <&abe_dpll_sys_clk_mux>, + <&atl_gfclk_mux>, + <&dpll_abe_ck>, + <&dpll_abe_m2x2_ck>, + <&atl_clkin2_ck>; + assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>; + assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, <5644800>; + + status = "okay"; + + atl2 { + bws = ; + aws = ; + }; +}; + +&mcasp3 { + #sound-dai-cells = <0>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mcasp3_pins>; + pinctrl-1 = <&mcasp3_sleep_pins>; + + assigned-clocks = <&mcasp3_ahclkx_mux>; + assigned-clock-parents = <&atl_clkin2_ck>; + + status = "okay"; + + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 4 serializer */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 1 2 0 0 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +&mailbox5 { + status = "okay"; + mbox_ipu1_ipc3x: mbox_ipu1_ipc3x { + status = "okay"; + }; + mbox_dsp1_ipc3x: mbox_dsp1_ipc3x { + status = "okay"; + }; +}; + +&mailbox6 { + status = "okay"; + mbox_ipu2_ipc3x: mbox_ipu2_ipc3x { + status = "okay"; + }; +}; diff --git a/arch/arm/boot/dts/dra72-evm-revc.dts b/arch/arm/boot/dts/dra72-evm-revc.dts new file mode 100644 index 000000000000..f9cfd3bb4dc2 --- /dev/null +++ b/arch/arm/boot/dts/dra72-evm-revc.dts @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "dra72-evm-common.dtsi" +#include + +/ { + model = "TI DRA722 Rev C EVM"; + + memory { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x80000000>; /* 2GB */ + }; +}; + +&tps65917_regulators { + ldo2_reg: ldo2 { + /* LDO2_OUT --> VDDA_1V8_PHY2 */ + regulator-name = "ldo2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&hdmi { + vdda-supply = <&ldo2_reg>; +}; + +&pcf_gpio_21 { + interrupt-parent = <&gpio3>; + interrupts = <30 IRQ_TYPE_EDGE_FALLING>; +}; + +&mac { + mode-gpios = <&pcf_gpio_21 4 GPIO_ACTIVE_LOW>, + <&pcf_hdmi 9 GPIO_ACTIVE_LOW>, /* P11 */ + <&pcf_hdmi 10 GPIO_ACTIVE_LOW>; /* P12 */ + dual_emac; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <2>; + phy-mode = "rgmii-id"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <3>; + phy-mode = "rgmii-id"; + dual_emac_res_vlan = <2>; +}; + +&davinci_mdio { + dp83867_0: ethernet-phy@2 { + reg = <2>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + ti,fifo-depth = ; + }; + + dp83867_1: ethernet-phy@3 { + reg = <3>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + ti,fifo-depth = ; + }; +}; diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index 3e63f660cd7c..cc1d32ca4a8a 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts @@ -1,695 +1,40 @@ /* - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -/dts-v1/; - -#include "dra72x.dtsi" -#include -#include - +#include "dra72-evm-common.dtsi" / { model = "TI DRA722"; - compatible = "ti,dra72-evm", "ti,dra722", "ti,dra72", "ti,dra7"; memory { device_type = "memory"; reg = <0x0 0x80000000 0x0 0x40000000>; /* 1024 MB */ }; +}; - aliases { - display0 = &hdmi0; - }; - - evm_3v3: fixedregulator-evm_3v3 { - compatible = "regulator-fixed"; - regulator-name = "evm_3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - aic_dvdd: fixedregulator-aic_dvdd { - /* TPS77018DBVT */ - compatible = "regulator-fixed"; - regulator-name = "aic_dvdd"; - vin-supply = <&evm_3v3>; +&tps65917_regulators { + ldo2_reg: ldo2 { + /* LDO2_OUT --> TP1017 (UNUSED) */ + regulator-name = "ldo2"; regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - evm_3v3_sd: fixedregulator-sd { - compatible = "regulator-fixed"; - regulator-name = "evm_3v3_sd"; - regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - enable-active-high; - gpio = <&pcf_gpio_21 5 GPIO_ACTIVE_HIGH>; - }; - - extcon_usb1: extcon_usb1 { - compatible = "linux,extcon-usb-gpio"; - id-gpio = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>; - }; - - extcon_usb2: extcon_usb2 { - compatible = "linux,extcon-usb-gpio"; - id-gpio = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>; - }; - - hdmi0: connector { - compatible = "hdmi-connector"; - label = "hdmi"; - - type = "a"; - - port { - hdmi_connector_in: endpoint { - remote-endpoint = <&tpd12s015_out>; - }; - }; - }; - - tpd12s015: encoder { - compatible = "ti,tpd12s015"; - - pinctrl-names = "default"; - pinctrl-0 = <&tpd12s015_pins>; - - gpios = <&pcf_hdmi 4 GPIO_ACTIVE_HIGH>, /* P4, CT CP HPD */ - <&pcf_hdmi 5 GPIO_ACTIVE_HIGH>, /* P5, LS OE */ - <&gpio7 12 GPIO_ACTIVE_HIGH>; /* gpio7_12/sp1_cs2, HPD */ - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - tpd12s015_in: endpoint { - remote-endpoint = <&hdmi_out>; - }; - }; - - port@1 { - reg = <1>; - - tpd12s015_out: endpoint { - remote-endpoint = <&hdmi_connector_in>; - }; - }; - }; - }; - - sound0: sound0 { - compatible = "simple-audio-card"; - simple-audio-card,name = "DRA7xx-EVM"; - simple-audio-card,widgets = - "Headphone", "Headphone Jack", - "Line", "Line Out", - "Microphone", "Mic Jack", - "Line", "Line In"; - simple-audio-card,routing = - "Headphone Jack", "HPLOUT", - "Headphone Jack", "HPROUT", - "Line Out", "LLOUT", - "Line Out", "RLOUT", - "MIC3L", "Mic Jack", - "MIC3R", "Mic Jack", - "Mic Jack", "Mic Bias", - "LINE1L", "Line In", - "LINE1R", "Line In"; - simple-audio-card,format = "dsp_b"; - simple-audio-card,bitclock-master = <&sound0_master>; - simple-audio-card,frame-master = <&sound0_master>; - simple-audio-card,bitclock-inversion; - - sound0_master: simple-audio-card,cpu { - sound-dai = <&mcasp3>; - system-clock-frequency = <5644800>; - }; - - simple-audio-card,codec { - sound-dai = <&tlv320aic3106>; - clocks = <&atl_clkin2_ck>; - }; - }; -}; - -&dra7_pmx_core { - i2c1_pins: pinmux_i2c1_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ - DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ - >; - }; - - i2c5_pins: pinmux_i2c5_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */ - DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */ - >; - }; - - i2c5_pins: pinmux_i2c5_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */ - DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */ - >; - }; - - nand_default: nand_default { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT | MUX_MODE0) /* gpmc_ad0 */ - DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT | MUX_MODE0) /* gpmc_ad1 */ - DRA7XX_CORE_IOPAD(0x3408, PIN_INPUT | MUX_MODE0) /* gpmc_ad2 */ - DRA7XX_CORE_IOPAD(0x340c, PIN_INPUT | MUX_MODE0) /* gpmc_ad3 */ - DRA7XX_CORE_IOPAD(0x3410, PIN_INPUT | MUX_MODE0) /* gpmc_ad4 */ - DRA7XX_CORE_IOPAD(0x3414, PIN_INPUT | MUX_MODE0) /* gpmc_ad5 */ - DRA7XX_CORE_IOPAD(0x3418, PIN_INPUT | MUX_MODE0) /* gpmc_ad6 */ - DRA7XX_CORE_IOPAD(0x341c, PIN_INPUT | MUX_MODE0) /* gpmc_ad7 */ - DRA7XX_CORE_IOPAD(0x3420, PIN_INPUT | MUX_MODE0) /* gpmc_ad8 */ - DRA7XX_CORE_IOPAD(0x3424, PIN_INPUT | MUX_MODE0) /* gpmc_ad9 */ - DRA7XX_CORE_IOPAD(0x3428, PIN_INPUT | MUX_MODE0) /* gpmc_ad10 */ - DRA7XX_CORE_IOPAD(0x342c, PIN_INPUT | MUX_MODE0) /* gpmc_ad11 */ - DRA7XX_CORE_IOPAD(0x3430, PIN_INPUT | MUX_MODE0) /* gpmc_ad12 */ - DRA7XX_CORE_IOPAD(0x3434, PIN_INPUT | MUX_MODE0) /* gpmc_ad13 */ - DRA7XX_CORE_IOPAD(0x3438, PIN_INPUT | MUX_MODE0) /* gpmc_ad14 */ - DRA7XX_CORE_IOPAD(0x343c, PIN_INPUT | MUX_MODE0) /* gpmc_ad15 */ - DRA7XX_CORE_IOPAD(0x34b4, PIN_OUTPUT | MUX_MODE0) /* gpmc_cs0 */ - DRA7XX_CORE_IOPAD(0x34c4, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale */ - DRA7XX_CORE_IOPAD(0x34cc, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen */ - DRA7XX_CORE_IOPAD(0x34c8, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren */ - DRA7XX_CORE_IOPAD(0x34d0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0 */ - DRA7XX_CORE_IOPAD(0x34d8, PIN_INPUT | MUX_MODE0) /* gpmc_wait0 */ - >; - }; - - usb1_pins: pinmux_usb1_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */ - >; - }; - - usb2_pins: pinmux_usb2_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3684, PIN_INPUT_SLEW | MUX_MODE0) /* usb2_drvvbus */ - >; - }; - - tps65917_pins_default: tps65917_pins_default { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3824, PIN_INPUT_PULLUP | MUX_MODE1) /* wakeup3.sys_nirq1 */ - >; - }; - - mmc1_pins_default: mmc1_pins_default { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14) /* mmc1sdcd.gpio219 */ - DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ - DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ - DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */ - DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */ - DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */ - DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */ - >; - }; - - mmc2_pins_default: mmc2_pins_default { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ - DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ - DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */ - DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */ - DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */ - DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */ - DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */ - DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */ - DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */ - DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */ - >; - }; - - dcan1_pins_default: dcan1_pins_default { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */ - DRA7XX_CORE_IOPAD(0x3818, PULL_UP | MUX_MODE1) /* wakeup0.dcan1_rx */ - >; - }; - - dcan1_pins_sleep: dcan1_pins_sleep { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP) /* dcan1_tx.off */ - DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP) /* wakeup0.off */ - >; - }; - - qspi1_pins: pinmux_qspi1_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3474, PIN_OUTPUT | MUX_MODE1) /* gpmc_a13.qspi1_rtclk */ - DRA7XX_CORE_IOPAD(0x3478, PIN_INPUT | MUX_MODE1) /* gpmc_a14.qspi1_d3 */ - DRA7XX_CORE_IOPAD(0x347c, PIN_INPUT | MUX_MODE1) /* gpmc_a15.qspi1_d2 */ - DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1) /* gpmc_a16.qspi1_d1 */ - DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1) /* gpmc_a17.qspi1_d0 */ - DRA7XX_CORE_IOPAD(0x3488, PIN_OUTPUT | MUX_MODE1) /* qpmc_a18.qspi1_sclk */ - DRA7XX_CORE_IOPAD(0x34b8, PIN_OUTPUT | MUX_MODE1) /* gpmc_cs2.qspi1_cs0 */ - >; - }; - - hdmi_pins: pinmux_hdmi_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */ - DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */ - >; - }; - - tpd12s015_pins: pinmux_tpd12s015_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpio7_12 HPD */ - >; - }; - - atl_pins: pinmux_atl_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3698, PIN_OUTPUT | MUX_MODE5) /* xref_clk1.atl_clk1 */ - DRA7XX_CORE_IOPAD(0x369c, PIN_OUTPUT | MUX_MODE5) /* xref_clk2.atl_clk2 */ - >; - }; - - mcasp3_pins: pinmux_mcasp3_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_aclkx */ - DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_fsx */ - DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr0 */ - DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr1 */ - >; - }; - - mcasp3_sleep_pins: pinmux_mcasp3_sleep_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE15) - DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE15) - DRA7XX_CORE_IOPAD(0x372c, PIN_INPUT_PULLDOWN | MUX_MODE15) - DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE15) - >; - }; -}; - -&i2c1 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; - clock-frequency = <400000>; - - tps65917: tps65917@58 { - compatible = "ti,tps65917"; - reg = <0x58>; - - pinctrl-names = "default"; - pinctrl-0 = <&tps65917_pins_default>; - - interrupts = ; /* IRQ_SYS_1N */ - interrupt-controller; - #interrupt-cells = <2>; - - ti,system-power-controller; - - tps65917_pmic { - compatible = "ti,tps65917-pmic"; - - regulators { - smps1_reg: smps1 { - /* VDD_MPU */ - regulator-name = "smps1"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1250000>; - regulator-always-on; - regulator-boot-on; - }; - - smps2_reg: smps2 { - /* VDD_CORE */ - regulator-name = "smps2"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1060000>; - regulator-boot-on; - regulator-always-on; - }; - - smps3_reg: smps3 { - /* VDD_GPU IVA DSPEVE */ - regulator-name = "smps3"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1250000>; - regulator-boot-on; - regulator-always-on; - }; - - smps4_reg: smps4 { - /* VDDS1V8 */ - regulator-name = "smps4"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - regulator-boot-on; - }; - - smps5_reg: smps5 { - /* VDD_DDR */ - regulator-name = "smps5"; - regulator-min-microvolt = <1350000>; - regulator-max-microvolt = <1350000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo1_reg: ldo1 { - /* LDO1_OUT --> SDIO */ - regulator-name = "ldo1"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - regulator-allow-bypass; - }; - - ldo2_reg: ldo2 { - /* LDO2_OUT --> TP1017 (UNUSED) */ - regulator-name = "ldo2"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-allow-bypass; - }; - - ldo3_reg: ldo3 { - /* VDDA_1V8_PHY */ - regulator-name = "ldo3"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo5_reg: ldo5 { - /* VDDA_1V8_PLL */ - regulator-name = "ldo5"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - regulator-boot-on; - }; - - ldo4_reg: ldo4 { - /* VDDA_3V_USB: VDDA_USBHS33 */ - regulator-name = "ldo4"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - }; - }; - }; - - tps65917_power_button { - compatible = "ti,palmas-pwrbutton"; - interrupt-parent = <&tps65917>; - interrupts = <1 IRQ_TYPE_NONE>; - wakeup-source; - ti,palmas-long-press-seconds = <6>; - }; - }; - - pcf_gpio_21: gpio@21 { - compatible = "nxp,pcf8575"; - reg = <0x21>; - lines-initial-states = <0x1408>; - gpio-controller; - #gpio-cells = <2>; - interrupt-parent = <&gpio6>; - interrupts = <11 IRQ_TYPE_EDGE_FALLING>; - interrupt-controller; - #interrupt-cells = <2>; - }; - - tlv320aic3106: tlv320aic3106@19 { - #sound-dai-cells = <0>; - compatible = "ti,tlv320aic3106"; - reg = <0x19>; - adc-settle-ms = <40>; - ai3x-micbias-vg = <1>; /* 2.0V */ - status = "okay"; - - /* Regulators */ - AVDD-supply = <&evm_3v3>; - IOVDD-supply = <&evm_3v3>; - DRVDD-supply = <&evm_3v3>; - DVDD-supply = <&aic_dvdd>; + regulator-allow-bypass; }; }; -&i2c5 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&i2c5_pins>; - clock-frequency = <400000>; - - pcf_hdmi: pcf8575@26 { - compatible = "nxp,pcf8575"; - reg = <0x26>; - gpio-controller; - #gpio-cells = <2>; - /* - * initial state is used here to keep the mdio interface - * selected on RU89 through SEL_VIN4_MUX_S0, VIN2_S1 and - * VIN2_S0 driven high otherwise Ethernet stops working - * VIN6_SEL_S0 is low, thus selecting McASP3 over VIN6 - */ - lines-initial-states = <0x0f2b>; - - p1 { - /* vin6_sel_s0: high: VIN6, low: audio */ - gpio-hog; - gpios = <1 GPIO_ACTIVE_HIGH>; - output-low; - line-name = "vin6_sel_s0"; - }; - }; -}; - -&uart1 { - status = "okay"; - interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, - <&dra7_pmx_core 0x3e0>; -}; - -&elm { - status = "okay"; -}; - -&gpmc { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&nand_default>; - ranges = <0 0 0x08000000 0x01000000>; /* minimum GPMC partition = 16MB */ - nand@0,0 { - /* To use NAND, DIP switch SW5 must be set like so: - * SW5.1 (NAND_SELn) = ON (LOW) - * SW5.9 (GPMC_WPN) = OFF (HIGH) - */ - compatible = "ti,omap2-nand"; - reg = <0 0 4>; /* device IO registers */ - interrupt-parent = <&gpmc>; - interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ - <1 IRQ_TYPE_NONE>; /* termcount */ - rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */ - ti,nand-ecc-opt = "bch8"; - ti,elm-id = <&elm>; - nand-bus-width = <16>; - gpmc,device-width = <2>; - gpmc,sync-clk-ps = <0>; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <80>; - gpmc,cs-wr-off-ns = <80>; - gpmc,adv-on-ns = <0>; - gpmc,adv-rd-off-ns = <60>; - gpmc,adv-wr-off-ns = <60>; - gpmc,we-on-ns = <10>; - gpmc,we-off-ns = <50>; - gpmc,oe-on-ns = <4>; - gpmc,oe-off-ns = <40>; - gpmc,access-ns = <40>; - gpmc,wr-access-ns = <80>; - gpmc,rd-cycle-ns = <80>; - gpmc,wr-cycle-ns = <80>; - gpmc,bus-turnaround-ns = <0>; - gpmc,cycle2cycle-delay-ns = <0>; - gpmc,clk-activation-ns = <0>; - gpmc,wr-data-mux-bus-ns = <0>; - /* MTD partition table */ - /* All SPL-* partitions are sized to minimal length - * which can be independently programmable. For - * NAND flash this is equal to size of erase-block */ - #address-cells = <1>; - #size-cells = <1>; - partition@0 { - label = "NAND.SPL"; - reg = <0x00000000 0x000020000>; - }; - partition@1 { - label = "NAND.SPL.backup1"; - reg = <0x00020000 0x00020000>; - }; - partition@2 { - label = "NAND.SPL.backup2"; - reg = <0x00040000 0x00020000>; - }; - partition@3 { - label = "NAND.SPL.backup3"; - reg = <0x00060000 0x00020000>; - }; - partition@4 { - label = "NAND.u-boot-spl-os"; - reg = <0x00080000 0x00040000>; - }; - partition@5 { - label = "NAND.u-boot"; - reg = <0x000c0000 0x00100000>; - }; - partition@6 { - label = "NAND.u-boot-env"; - reg = <0x001c0000 0x00020000>; - }; - partition@7 { - label = "NAND.u-boot-env.backup1"; - reg = <0x001e0000 0x00020000>; - }; - partition@8 { - label = "NAND.kernel"; - reg = <0x00200000 0x00800000>; - }; - partition@9 { - label = "NAND.file-system"; - reg = <0x00a00000 0x0f600000>; - }; - }; -}; - -&usb2_phy1 { - phy-supply = <&ldo4_reg>; -}; - -&usb2_phy2 { - phy-supply = <&ldo4_reg>; -}; - -&omap_dwc3_1 { - extcon = <&extcon_usb1>; -}; - -&omap_dwc3_2 { - extcon = <&extcon_usb2>; -}; - -&usb1 { - dr_mode = "peripheral"; - pinctrl-names = "default"; - pinctrl-0 = <&usb1_pins>; -}; - -&usb2 { - dr_mode = "host"; - pinctrl-names = "default"; - pinctrl-0 = <&usb2_pins>; -}; - -&mmc1 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&mmc1_pins_default>; - vmmc-supply = <&evm_3v3_sd>; - vmmc_aux-supply = <&ldo1_reg>; - bus-width = <4>; - /* - * SDCD signal is not being used here - using the fact that GPIO mode - * is a viable alternative - */ - cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; - max-frequency = <192000000>; -}; - -&mmc2 { - /* SW5-3 in ON position */ - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&mmc2_pins_default>; - - vmmc-supply = <&evm_3v3>; - bus-width = <8>; - ti,non-removable; - max-frequency = <192000000>; +&hdmi { + vdda-supply = <&ldo3_reg>; }; -&dra7_pmx_core { - cpsw_default: cpsw_default { - pinctrl-single,pins = < - /* Slave 2 */ - DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3) /* vin2a_d12.rgmii1_txc */ - DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3) /* vin2a_d13.rgmii1_tctl */ - DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3) /* vin2a_d14.rgmii1_td3 */ - DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3) /* vin2a_d15.rgmii1_td2 */ - DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3) /* vin2a_d16.rgmii1_td1 */ - DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3) /* vin2a_d17.rgmii1_td0 */ - DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE3) /* vin2a_d18.rgmii1_rclk */ - DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE3) /* vin2a_d19.rgmii1_rctl */ - DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE3) /* vin2a_d20.rgmii1_rd3 */ - DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE3) /* vin2a_d21.rgmii1_rd2 */ - DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE3) /* vin2a_d22.rgmii1_rd1 */ - DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE3) /* vin2a_d23.rgmii1_rd0 */ - >; - - }; - - cpsw_sleep: cpsw_sleep { - pinctrl-single,pins = < - /* Slave 2 */ - DRA7XX_CORE_IOPAD(0x3598, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x359c, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35a0, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35a4, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35a8, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35ac, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35b0, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35b4, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35b8, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35bc, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35c0, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x35c4, MUX_MODE15) - >; - }; - - davinci_mdio_default: davinci_mdio_default { - pinctrl-single,pins = < - /* MDIO */ - DRA7XX_CORE_IOPAD(0x363c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_d.mdio_d */ - DRA7XX_CORE_IOPAD(0x3640, PIN_INPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ - >; - }; - - davinci_mdio_sleep: davinci_mdio_sleep { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x363c, MUX_MODE15) - DRA7XX_CORE_IOPAD(0x3640, MUX_MODE15) - >; - }; +&pcf_gpio_21 { + interrupt-parent = <&gpio6>; + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; }; &mac { - status = "okay"; - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&cpsw_default>; - pinctrl-1 = <&cpsw_sleep>; slaves = <1>; mode-gpios = <&pcf_gpio_21 4 GPIO_ACTIVE_HIGH>; }; @@ -698,160 +43,3 @@ phy_id = <&davinci_mdio>, <3>; phy-mode = "rgmii"; }; - -&davinci_mdio { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&davinci_mdio_default>; - pinctrl-1 = <&davinci_mdio_sleep>; -}; - -&dcan1 { - status = "ok"; - pinctrl-names = "default", "sleep", "active"; - pinctrl-0 = <&dcan1_pins_sleep>; - pinctrl-1 = <&dcan1_pins_sleep>; - pinctrl-2 = <&dcan1_pins_default>; -}; - -&qspi { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&qspi1_pins>; - - spi-max-frequency = <48000000>; - m25p80@0 { - compatible = "s25fl256s1"; - spi-max-frequency = <48000000>; - reg = <0>; - spi-tx-bus-width = <1>; - spi-rx-bus-width = <4>; - spi-cpol; - spi-cpha; - #address-cells = <1>; - #size-cells = <1>; - - /* MTD partition table. - * The ROM checks the first four physical blocks - * for a valid file to boot and the flash here is - * 64KiB block size. - */ - partition@0 { - label = "QSPI.SPL"; - reg = <0x00000000 0x000010000>; - }; - partition@1 { - label = "QSPI.SPL.backup1"; - reg = <0x00010000 0x00010000>; - }; - partition@2 { - label = "QSPI.SPL.backup2"; - reg = <0x00020000 0x00010000>; - }; - partition@3 { - label = "QSPI.SPL.backup3"; - reg = <0x00030000 0x00010000>; - }; - partition@4 { - label = "QSPI.u-boot"; - reg = <0x00040000 0x00100000>; - }; - partition@5 { - label = "QSPI.u-boot-spl-os"; - reg = <0x00140000 0x00080000>; - }; - partition@6 { - label = "QSPI.u-boot-env"; - reg = <0x001c0000 0x00010000>; - }; - partition@7 { - label = "QSPI.u-boot-env.backup1"; - reg = <0x001d0000 0x0010000>; - }; - partition@8 { - label = "QSPI.kernel"; - reg = <0x001e0000 0x0800000>; - }; - partition@9 { - label = "QSPI.file-system"; - reg = <0x009e0000 0x01620000>; - }; - }; -}; - -&dss { - status = "ok"; - - vdda_video-supply = <&ldo5_reg>; -}; - -&hdmi { - status = "ok"; - vdda-supply = <&ldo3_reg>; - - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_pins>; - - port { - hdmi_out: endpoint { - remote-endpoint = <&tpd12s015_in>; - }; - }; -}; - -&atl { - pinctrl-names = "default"; - pinctrl-0 = <&atl_pins>; - - assigned-clocks = <&abe_dpll_sys_clk_mux>, - <&atl_gfclk_mux>, - <&dpll_abe_ck>, - <&dpll_abe_m2x2_ck>, - <&atl_clkin2_ck>; - assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>; - assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, <5644800>; - - status = "okay"; - - atl2 { - bws = ; - aws = ; - }; -}; - -&mcasp3 { - #sound-dai-cells = <0>; - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&mcasp3_pins>; - pinctrl-1 = <&mcasp3_sleep_pins>; - - assigned-clocks = <&mcasp3_ahclkx_mux>; - assigned-clock-parents = <&atl_clkin2_ck>; - - status = "okay"; - - op-mode = <0>; /* MCASP_IIS_MODE */ - tdm-slots = <2>; - /* 4 serializer */ - serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ - 1 2 0 0 - >; - tx-num-evt = <32>; - rx-num-evt = <32>; -}; - -&mailbox5 { - status = "okay"; - mbox_ipu1_ipc3x: mbox_ipu1_ipc3x { - status = "okay"; - }; - mbox_dsp1_ipc3x: mbox_dsp1_ipc3x { - status = "okay"; - }; -}; - -&mailbox6 { - status = "okay"; - mbox_ipu2_ipc3x: mbox_ipu2_ipc3x { - status = "okay"; - }; -}; -- GitLab From 333f796235a52727db7e0a13888045f3aa3d5335 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 12 Apr 2016 13:05:21 +0200 Subject: [PATCH 2837/9938] tipc: fix a race condition leading to subscriber refcnt bug Until now, the requests sent to topology server are queued to a workqueue by the generic server framework. These messages are processed by worker threads and trigger the registered callbacks. To reduce latency on uniprocessor systems, explicit rescheduling is performed using cond_resched() after MAX_RECV_MSG_COUNT(25) messages. This implementation on SMP systems leads to an subscriber refcnt error as described below: When a worker thread yields by calling cond_resched() in a SMP system, a new worker is created on another CPU to process the pending workitem. Sometimes the sleeping thread wakes up before the new thread finishes execution. This breaks the assumption on ordering and being single threaded. The fault is more frequent when MAX_RECV_MSG_COUNT is lowered. If the first thread was processing subscription create and the second thread processing close(), the close request will free the subscriber and the create request oops as follows: [31.224137] WARNING: CPU: 2 PID: 266 at include/linux/kref.h:46 tipc_subscrb_rcv_cb+0x317/0x380 [tipc] [31.228143] CPU: 2 PID: 266 Comm: kworker/u8:1 Not tainted 4.5.0+ #97 [31.228377] Workqueue: tipc_rcv tipc_recv_work [tipc] [...] [31.228377] Call Trace: [31.228377] [] dump_stack+0x4d/0x72 [31.228377] [] __warn+0xd1/0xf0 [31.228377] [] warn_slowpath_null+0x1d/0x20 [31.228377] [] tipc_subscrb_rcv_cb+0x317/0x380 [tipc] [31.228377] [] tipc_receive_from_sock+0xd4/0x130 [tipc] [31.228377] [] tipc_recv_work+0x2b/0x50 [tipc] [31.228377] [] process_one_work+0x145/0x3d0 [31.246554] ---[ end trace c3882c9baa05a4fd ]--- [31.248327] BUG: spinlock bad magic on CPU#2, kworker/u8:1/266 [31.249119] BUG: unable to handle kernel NULL pointer dereference at 0000000000000428 [31.249323] IP: [] spin_dump+0x5c/0xe0 [31.249323] PGD 0 [31.249323] Oops: 0000 [#1] SMP In this commit, we - rename tipc_conn_shutdown() to tipc_conn_release(). - move connection release callback execution from tipc_close_conn() to a new function tipc_sock_release(), which is executed before we free the connection. Thus we release the subscriber during connection release procedure rather than connection shutdown procedure. Signed-off-by: Parthasarathy Bhuvaragan Acked-by: Ying Xue Signed-off-by: David S. Miller --- net/tipc/server.c | 19 +++++++++++++------ net/tipc/server.h | 4 ++-- net/tipc/subscr.c | 4 ++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/net/tipc/server.c b/net/tipc/server.c index 2446bfbaa309..7a0af2dc0406 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -86,6 +86,7 @@ struct outqueue_entry { static void tipc_recv_work(struct work_struct *work); static void tipc_send_work(struct work_struct *work); static void tipc_clean_outqueues(struct tipc_conn *con); +static void tipc_sock_release(struct tipc_conn *con); static void tipc_conn_kref_release(struct kref *kref) { @@ -102,6 +103,7 @@ static void tipc_conn_kref_release(struct kref *kref) } saddr->scope = -TIPC_NODE_SCOPE; kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr)); + tipc_sock_release(con); sock_release(sock); con->sock = NULL; } @@ -184,26 +186,31 @@ static void tipc_unregister_callbacks(struct tipc_conn *con) write_unlock_bh(&sk->sk_callback_lock); } +static void tipc_sock_release(struct tipc_conn *con) +{ + struct tipc_server *s = con->server; + + if (con->conid) + s->tipc_conn_release(con->conid, con->usr_data); + + tipc_unregister_callbacks(con); +} + static void tipc_close_conn(struct tipc_conn *con) { struct tipc_server *s = con->server; if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { - if (con->conid) - s->tipc_conn_shutdown(con->conid, con->usr_data); spin_lock_bh(&s->idr_lock); idr_remove(&s->conn_idr, con->conid); s->idr_in_use--; spin_unlock_bh(&s->idr_lock); - tipc_unregister_callbacks(con); - /* We shouldn't flush pending works as we may be in the * thread. In fact the races with pending rx/tx work structs * are harmless for us here as we have already deleted this - * connection from server connection list and set - * sk->sk_user_data to 0 before releasing connection object. + * connection from server connection list. */ kernel_sock_shutdown(con->sock, SHUT_RDWR); diff --git a/net/tipc/server.h b/net/tipc/server.h index 9015faedb1b0..34f8055afa3b 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h @@ -53,7 +53,7 @@ * @send_wq: send workqueue * @max_rcvbuf_size: maximum permitted receive message length * @tipc_conn_new: callback will be called when new connection is incoming - * @tipc_conn_shutdown: callback will be called when connection is shut down + * @tipc_conn_release: callback will be called before releasing the connection * @tipc_conn_recvmsg: callback will be called when message arrives * @saddr: TIPC server address * @name: server name @@ -70,7 +70,7 @@ struct tipc_server { struct workqueue_struct *send_wq; int max_rcvbuf_size; void *(*tipc_conn_new)(int conid); - void (*tipc_conn_shutdown)(int conid, void *usr_data); + void (*tipc_conn_release)(int conid, void *usr_data); void (*tipc_conn_recvmsg)(struct net *net, int conid, struct sockaddr_tipc *addr, void *usr_data, void *buf, size_t len); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index e6cb386fbf34..79de588c7bd6 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -302,7 +302,7 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, } /* Handle one termination request for the subscriber */ -static void tipc_subscrb_shutdown_cb(int conid, void *usr_data) +static void tipc_subscrb_release_cb(int conid, void *usr_data) { tipc_subscrb_delete((struct tipc_subscriber *)usr_data); } @@ -365,7 +365,7 @@ int tipc_topsrv_start(struct net *net) topsrv->max_rcvbuf_size = sizeof(struct tipc_subscr); topsrv->tipc_conn_recvmsg = tipc_subscrb_rcv_cb; topsrv->tipc_conn_new = tipc_subscrb_connect_cb; - topsrv->tipc_conn_shutdown = tipc_subscrb_shutdown_cb; + topsrv->tipc_conn_release = tipc_subscrb_release_cb; strncpy(topsrv->name, name, strlen(name) + 1); tn->topsrv = topsrv; -- GitLab From da37845fdce24e174f44d020bc4085ddd1c8a6bd Mon Sep 17 00:00:00 2001 From: Weongyo Jeong Date: Thu, 14 Apr 2016 14:10:04 -0700 Subject: [PATCH 2838/9938] packet: uses kfree_skb() for errors. consume_skb() isn't for error cases that kfree_skb() is more proper one. At this patch, it fixed tpacket_rcv() and packet_rcv() to be consistent for error or non-error cases letting perf trace its event properly. Signed-off-by: Weongyo Jeong Signed-off-by: David S. Miller --- net/packet/af_packet.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 81a4c0574d73..4d5e699d0bfa 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2052,6 +2052,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, u8 *skb_head = skb->data; int skb_len = skb->len; unsigned int snaplen, res; + bool is_drop_n_account = false; if (skb->pkt_type == PACKET_LOOPBACK) goto drop; @@ -2140,6 +2141,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, return 0; drop_n_acct: + is_drop_n_account = true; spin_lock(&sk->sk_receive_queue.lock); po->stats.stats1.tp_drops++; atomic_inc(&sk->sk_drops); @@ -2151,7 +2153,10 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, skb->len = skb_len; } drop: - consume_skb(skb); + if (!is_drop_n_account) + consume_skb(skb); + else + kfree_skb(skb); return 0; } @@ -2170,6 +2175,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct sk_buff *copy_skb = NULL; struct timespec ts; __u32 ts_status; + bool is_drop_n_account = false; /* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT. * We may add members to them until current aligned size without forcing @@ -2377,10 +2383,14 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, skb->len = skb_len; } drop: - kfree_skb(skb); + if (!is_drop_n_account) + consume_skb(skb); + else + kfree_skb(skb); return 0; drop_n_account: + is_drop_n_account = true; po->stats.stats1.tp_drops++; spin_unlock(&sk->sk_receive_queue.lock); -- GitLab From bfbba189b681c86b9ae380358e5f50ce1e33d240 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 15:54:36 -0300 Subject: [PATCH 2839/9938] perf symbols: Move fprintf routines to separate object file To disentangle symbol printing from all the code related to symbol tables, resolution of addresses to symbols, etc. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-eik9g3hbtdc7ddv57f1d4v3p@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 1 + tools/perf/util/python-ext-sources | 1 + tools/perf/util/symbol.c | 71 ------------------------------ tools/perf/util/symbol.h | 5 +++ tools/perf/util/symbol_fprintf.c | 71 ++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 71 deletions(-) create mode 100644 tools/perf/util/symbol_fprintf.c diff --git a/tools/perf/util/Build b/tools/perf/util/Build index ea4ac03c1ec8..61021334e958 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -29,6 +29,7 @@ libperf-y += usage.o libperf-y += wrapper.o libperf-y += dso.o libperf-y += symbol.o +libperf-y += symbol_fprintf.o libperf-y += color.o libperf-y += header.o libperf-y += callchain.o diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 8162ba0e2e57..36c6862119e3 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -23,3 +23,4 @@ util/strlist.c util/trace-event.c ../lib/rbtree.c util/string.c +util/symbol_fprintf.c diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index bb162ee433c6..a36823c3b7c0 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -255,57 +255,6 @@ void symbol__delete(struct symbol *sym) free(((void *)sym) - symbol_conf.priv_size); } -size_t symbol__fprintf(struct symbol *sym, FILE *fp) -{ - return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", - sym->start, sym->end, - sym->binding == STB_GLOBAL ? 'g' : - sym->binding == STB_LOCAL ? 'l' : 'w', - sym->name); -} - -size_t __symbol__fprintf_symname_offs(const struct symbol *sym, - const struct addr_location *al, - bool unknown_as_addr, FILE *fp) -{ - unsigned long offset; - size_t length; - - if (sym && sym->name) { - length = fprintf(fp, "%s", sym->name); - if (al) { - if (al->addr < sym->end) - offset = al->addr - sym->start; - else - offset = al->addr - al->map->start - sym->start; - length += fprintf(fp, "+0x%lx", offset); - } - return length; - } else if (al && unknown_as_addr) - return fprintf(fp, "[%#" PRIx64 "]", al->addr); - else - return fprintf(fp, "[unknown]"); -} - -size_t symbol__fprintf_symname_offs(const struct symbol *sym, - const struct addr_location *al, - FILE *fp) -{ - return __symbol__fprintf_symname_offs(sym, al, false, fp); -} - -size_t __symbol__fprintf_symname(const struct symbol *sym, - const struct addr_location *al, - bool unknown_as_addr, FILE *fp) -{ - return __symbol__fprintf_symname_offs(sym, al, unknown_as_addr, fp); -} - -size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp) -{ - return __symbol__fprintf_symname_offs(sym, NULL, false, fp); -} - void symbols__delete(struct rb_root *symbols) { struct symbol *pos; @@ -381,11 +330,6 @@ static struct symbol *symbols__next(struct symbol *sym) return NULL; } -struct symbol_name_rb_node { - struct rb_node rb_node; - struct symbol sym; -}; - static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) { struct rb_node **p = &symbols->rb_node; @@ -514,21 +458,6 @@ void dso__sort_by_name(struct dso *dso, enum map_type type) &dso->symbols[type]); } -size_t dso__fprintf_symbols_by_name(struct dso *dso, - enum map_type type, FILE *fp) -{ - size_t ret = 0; - struct rb_node *nd; - struct symbol_name_rb_node *pos; - - for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) { - pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); - fprintf(fp, "%s\n", pos->sym.name); - } - - return ret; -} - int modules__parse(const char *filename, void *arg, int (*process_module)(void *arg, const char *name, u64 start)) diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index e2562568418d..1da7b101bc7f 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -140,6 +140,11 @@ struct symbol_conf { extern struct symbol_conf symbol_conf; +struct symbol_name_rb_node { + struct rb_node rb_node; + struct symbol sym; +}; + static inline int __symbol__join_symfs(char *bf, size_t size, const char *path) { return path__join(bf, size, symbol_conf.symfs, path); diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c new file mode 100644 index 000000000000..a680bdaa65dc --- /dev/null +++ b/tools/perf/util/symbol_fprintf.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include "symbol.h" + +size_t symbol__fprintf(struct symbol *sym, FILE *fp) +{ + return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", + sym->start, sym->end, + sym->binding == STB_GLOBAL ? 'g' : + sym->binding == STB_LOCAL ? 'l' : 'w', + sym->name); +} + +size_t __symbol__fprintf_symname_offs(const struct symbol *sym, + const struct addr_location *al, + bool unknown_as_addr, FILE *fp) +{ + unsigned long offset; + size_t length; + + if (sym && sym->name) { + length = fprintf(fp, "%s", sym->name); + if (al) { + if (al->addr < sym->end) + offset = al->addr - sym->start; + else + offset = al->addr - al->map->start - sym->start; + length += fprintf(fp, "+0x%lx", offset); + } + return length; + } else if (al && unknown_as_addr) + return fprintf(fp, "[%#" PRIx64 "]", al->addr); + else + return fprintf(fp, "[unknown]"); +} + +size_t symbol__fprintf_symname_offs(const struct symbol *sym, + const struct addr_location *al, + FILE *fp) +{ + return __symbol__fprintf_symname_offs(sym, al, false, fp); +} + +size_t __symbol__fprintf_symname(const struct symbol *sym, + const struct addr_location *al, + bool unknown_as_addr, FILE *fp) +{ + return __symbol__fprintf_symname_offs(sym, al, unknown_as_addr, fp); +} + +size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp) +{ + return __symbol__fprintf_symname_offs(sym, NULL, false, fp); +} + +size_t dso__fprintf_symbols_by_name(struct dso *dso, + enum map_type type, FILE *fp) +{ + size_t ret = 0; + struct rb_node *nd; + struct symbol_name_rb_node *pos; + + for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) { + pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); + fprintf(fp, "%s\n", pos->sym.name); + } + + return ret; +} -- GitLab From 6f736735e30f51805f6be31d20a4bf5b0ae91bae Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 17:45:51 -0300 Subject: [PATCH 2840/9938] perf evsel: Require that callchains be resolved before calling fprintf_{sym,callchain} This way the print routine merely does printing, not requiring access to the resolving machinery, which helps disentangling the object files and easing creating subsets with a limited functionality set. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-2ti2jbra8fypdfawwwm3aee3@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 36 +++++++++++++++++++--------------- tools/perf/builtin-trace.c | 8 +++++--- tools/perf/util/evsel.c | 39 +++++++++++++------------------------ tools/perf/util/evsel.h | 19 +++++++++--------- 4 files changed, 48 insertions(+), 54 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 717ba0215234..875d84e7ba5b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -569,19 +569,23 @@ static void print_sample_bts(struct perf_sample *sample, /* print branch_from information */ if (PRINT_FIELD(IP)) { unsigned int print_opts = output[attr->type].print_ip_opts; + struct callchain_cursor *cursor = NULL, cursor_callchain; - if (symbol_conf.use_callchain && sample->callchain) { - printf("\n"); - } else { - printf(" "); + if (symbol_conf.use_callchain && sample->callchain && + thread__resolve_callchain(al->thread, &cursor_callchain, evsel, + sample, NULL, NULL, scripting_max_stack) == 0) + cursor = &cursor_callchain; + + if (cursor == NULL) { + putchar(' '); if (print_opts & EVSEL__PRINT_SRCLINE) { print_srcline_last = true; print_opts &= ~EVSEL__PRINT_SRCLINE; } - } - perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts, - symbol_conf.use_callchain, - scripting_max_stack, stdout); + } else + putchar('\n'); + + sample__fprintf_sym(sample, al, 0, print_opts, cursor, stdout); } /* print branch_to information */ @@ -784,15 +788,15 @@ static void process_event(struct perf_script *script, printf("%16" PRIu64, sample->weight); if (PRINT_FIELD(IP)) { - if (!symbol_conf.use_callchain) - printf(" "); - else - printf("\n"); + struct callchain_cursor *cursor = NULL, cursor_callchain; + + if (symbol_conf.use_callchain && + thread__resolve_callchain(al->thread, &cursor_callchain, evsel, + sample, NULL, NULL, scripting_max_stack) == 0) + cursor = &cursor_callchain; - perf_evsel__fprintf_sym(evsel, sample, al, 0, - output[attr->type].print_ip_opts, - symbol_conf.use_callchain, - scripting_max_stack, stdout); + putchar(cursor ? '\n' : ' '); + sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout); } if (PRINT_FIELD(IREGS)) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e5f0cc16bb93..0e2a82bda22f 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1890,14 +1890,16 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evse if (sample->callchain == NULL) return 0; - if (machine__resolve(trace->host, &al, sample) < 0) { + if (machine__resolve(trace->host, &al, sample) < 0 || + thread__resolve_callchain(al.thread, &callchain_cursor, evsel, + sample, NULL, NULL, scripting_max_stack)) { pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); return 0; } - return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts, - scripting_max_stack, trace->output); + return sample__fprintf_callchain(sample, &al, 38, print_opts, + &callchain_cursor, trace->output); } static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 60bba67e6959..35c5a5282239 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2343,13 +2343,12 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, return ++printed; } -int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) +int sample__fprintf_callchain(struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, struct callchain_cursor *cursor, + FILE *fp) { int printed = 0; - struct callchain_cursor cursor; struct callchain_cursor_node *node; int print_ip = print_opts & EVSEL__PRINT_IP; int print_sym = print_opts & EVSEL__PRINT_SYM; @@ -2363,22 +2362,15 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * if (sample->callchain) { struct addr_location node_al; - if (thread__resolve_callchain(al->thread, &cursor, evsel, - sample, NULL, NULL, - stack_depth) != 0) { - if (verbose) - error("Failed to resolve callchain. Skipping\n"); - return printed; - } - callchain_cursor_commit(&cursor); + callchain_cursor_commit(cursor); if (print_symoffset) node_al = *al; - while (stack_depth) { + while (1) { u64 addr = 0; - node = callchain_cursor_current(&cursor); + node = callchain_cursor_current(cursor); if (!node) break; @@ -2418,20 +2410,17 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * if (!print_oneline) printed += fprintf(fp, "\n"); - - stack_depth--; next: - callchain_cursor_advance(&cursor); + callchain_cursor_advance(cursor); } } return printed; } -int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, bool print_callchain, - unsigned int stack_depth, FILE *fp) +int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, + int left_alignment, unsigned int print_opts, + struct callchain_cursor *cursor, FILE *fp) { int printed = 0; int print_ip = print_opts & EVSEL__PRINT_IP; @@ -2441,9 +2430,9 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; - if (print_callchain && sample->callchain) { - printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, - print_opts, stack_depth, fp); + if (cursor != NULL) { + printed += sample__fprintf_callchain(sample, al, left_alignment, + print_opts, cursor, fp); } else if (!(al->sym && al->sym->ignore)) { printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 013f3615730b..abadfea1dbaa 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -395,16 +395,15 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, #define EVSEL__PRINT_SRCLINE (1<<5) #define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6) -int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, - struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, - unsigned int stack_depth, FILE *fp); - -int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, bool print_callchain, - unsigned int stack_depth, FILE *fp); +struct callchain_cursor; + +int sample__fprintf_callchain(struct perf_sample *sample, struct addr_location *al, + int left_alignment, unsigned int print_opts, + struct callchain_cursor *cursor, FILE *fp); + +int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, + int left_alignment, unsigned int print_opts, + struct callchain_cursor *cursor, FILE *fp); bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); -- GitLab From d327e60cfae2201bcdee5aeb9b5a42e3988b184f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 17:53:49 -0300 Subject: [PATCH 2841/9938] perf tools: Remove addr_location argument to sample__fprintf_callchain Not used at all, nuke it. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-jf2w8ce8nl3wso3vuodg5jci@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 +-- tools/perf/util/evsel.c | 8 ++------ tools/perf/util/evsel.h | 4 ++-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0e2a82bda22f..5e5a95e34a53 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1898,8 +1898,7 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evse return 0; } - return sample__fprintf_callchain(sample, &al, 38, print_opts, - &callchain_cursor, trace->output); + return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output); } static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 35c5a5282239..060f619dea88 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2343,8 +2343,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, return ++printed; } -int sample__fprintf_callchain(struct perf_sample *sample, - struct addr_location *al, int left_alignment, +int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, unsigned int print_opts, struct callchain_cursor *cursor, FILE *fp) { @@ -2364,9 +2363,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, callchain_cursor_commit(cursor); - if (print_symoffset) - node_al = *al; - while (1) { u64 addr = 0; @@ -2431,7 +2427,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; if (cursor != NULL) { - printed += sample__fprintf_callchain(sample, al, left_alignment, + printed += sample__fprintf_callchain(sample, left_alignment, print_opts, cursor, fp); } else if (!(al->sym && al->sym->ignore)) { printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index abadfea1dbaa..b993218744d4 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -397,8 +397,8 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, struct callchain_cursor; -int sample__fprintf_callchain(struct perf_sample *sample, struct addr_location *al, - int left_alignment, unsigned int print_opts, +int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, + unsigned int print_opts, struct callchain_cursor *cursor, FILE *fp); int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, -- GitLab From 6125cc8dac432948a31df4d4ac20dd2d4f8c6c27 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 18:15:18 -0300 Subject: [PATCH 2842/9938] perf script: Add --max-stack knob Works just like with 'perf report'. In some cases we may want to have more than 127 entries, the default maximum. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-mqkz2p5ok2978gztb0vsnocc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script.txt | 10 ++++++++++ tools/perf/builtin-script.c | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 22ef3933342a..4fc44c75263f 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -259,6 +259,16 @@ include::itrace.txt[] --full-source-path:: Show the full path for source files for srcline output. +--max-stack:: + Set the stack depth limit when parsing the callchain, anything + beyond the specified depth will be ignored. This is a trade-off + between information loss and faster processing especially for + workloads that can have a very long callchain stack. + Note that when using the --itrace option the synthesized callchain size + will override this value if the synthesized callchain size is bigger. + + Default: 127 + --ns:: Use 9 decimal places when displaying time (i.e. show the nanoseconds) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 875d84e7ba5b..0e93282b405e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -22,6 +22,7 @@ #include "util/thread_map.h" #include "util/stat.h" #include +#include #include "asm/bug.h" #include "util/mem-events.h" @@ -2027,6 +2028,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "only consider symbols in these pids"), OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", "only consider symbols in these tids"), + OPT_UINTEGER(0, "max-stack", &scripting_max_stack, + "Set the maximum stack depth when parsing the callchain, " + "anything beyond the specified depth will be ignored. " + "Default: " __stringify(PERF_MAX_STACK_DEPTH)), OPT_BOOLEAN('I', "show-info", &show_full_info, "display extended information from perf.data file"), OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, -- GitLab From c6d4a494a207a336b45e52a44550150964daf1ce Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 18:29:08 -0300 Subject: [PATCH 2843/9938] perf trace: Add --max-stack knob Similar to the one in the other tools (report, script, top). Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-lh7kk5a5t3erwxw31ah0cgar@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 9 +++++++++ tools/perf/builtin-trace.c | 9 ++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 1bbcf305d233..2ee0c4fee18d 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -129,6 +129,15 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. --event:: Trace other events, see 'perf list' for a complete list. +--max-stack:: + Set the stack depth limit when parsing the callchain, anything + beyond the specified depth will be ignored. Note that at this point + this is just about the presentation part, i.e. the kernel is still + not limiting, the overhead of callchains needs to be set via the + knobs in --call-graph dwarf. + + Default: 127 + --proc-map-timeout:: When processing pre-existing threads /proc/XXX/mmap, it may take a long time, because the file may be huge. A time out is needed in such cases. diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 5e5a95e34a53..39a158923acf 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -46,6 +46,7 @@ #include #include #include +#include #ifndef O_CLOEXEC # define O_CLOEXEC 02000000 @@ -106,6 +107,7 @@ struct trace { u64 vfs_getname, proc_getname; } stats; + unsigned int max_stack; bool not_ev_qualifier; bool live; bool full_time; @@ -1892,7 +1894,7 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evse if (machine__resolve(trace->host, &al, sample) < 0 || thread__resolve_callchain(al.thread, &callchain_cursor, evsel, - sample, NULL, NULL, scripting_max_stack)) { + sample, NULL, NULL, trace->max_stack)) { pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); return 0; @@ -3029,6 +3031,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) .show_comm = true, .trace_syscalls = true, .kernel_syscallchains = false, + .max_stack = PERF_MAX_STACK_DEPTH, }; const char *output_name = NULL; const char *ev_qualifier_str = NULL; @@ -3079,6 +3082,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) &record_parse_callchain_opt), OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, "Show the kernel callchains on the syscall exit path"), + OPT_UINTEGER(0, "max-stack", &trace.max_stack, + "Set the maximum stack depth when parsing the callchain, " + "anything beyond the specified depth will be ignored. " + "Default: " __stringify(PERF_MAX_STACK_DEPTH)), OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, "per thread proc mmap processing timeout in ms"), OPT_END() -- GitLab From 25da4fab5f66e659da768cd61dbf8c3861104d7c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 14 Apr 2016 19:45:01 -0300 Subject: [PATCH 2844/9938] perf evsel: Move fprintf methods to separate source file They still use functions that would drag more stuff to the python binding, where these fprintf methods are not used, so separate it. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-xfp0mgq3hh3px61di6ixi1jk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 1 + tools/perf/util/evsel.c | 206 ------------------------------- tools/perf/util/evsel_fprintf.c | 212 ++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+), 206 deletions(-) create mode 100644 tools/perf/util/evsel_fprintf.c diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 61021334e958..85a9ab62e23f 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -8,6 +8,7 @@ libperf-y += env.o libperf-y += event.o libperf-y += evlist.o libperf-y += evsel.o +libperf-y += evsel_fprintf.o libperf-y += find_bit.o libperf-y += kallsyms.o libperf-y += levenshtein.o diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 060f619dea88..545bb3f0b2b0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2254,212 +2254,6 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, return 0; } -static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) -{ - va_list args; - int ret = 0; - - if (!*first) { - ret += fprintf(fp, ","); - } else { - ret += fprintf(fp, ":"); - *first = false; - } - - va_start(args, fmt); - ret += vfprintf(fp, fmt, args); - va_end(args); - return ret; -} - -static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv) -{ - return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val); -} - -int perf_evsel__fprintf(struct perf_evsel *evsel, - struct perf_attr_details *details, FILE *fp) -{ - bool first = true; - int printed = 0; - - if (details->event_group) { - struct perf_evsel *pos; - - if (!perf_evsel__is_group_leader(evsel)) - return 0; - - if (evsel->nr_members > 1) - printed += fprintf(fp, "%s{", evsel->group_name ?: ""); - - printed += fprintf(fp, "%s", perf_evsel__name(evsel)); - for_each_group_member(pos, evsel) - printed += fprintf(fp, ",%s", perf_evsel__name(pos)); - - if (evsel->nr_members > 1) - printed += fprintf(fp, "}"); - goto out; - } - - printed += fprintf(fp, "%s", perf_evsel__name(evsel)); - - if (details->verbose) { - printed += perf_event_attr__fprintf(fp, &evsel->attr, - __print_attr__fprintf, &first); - } else if (details->freq) { - const char *term = "sample_freq"; - - if (!evsel->attr.freq) - term = "sample_period"; - - printed += comma_fprintf(fp, &first, " %s=%" PRIu64, - term, (u64)evsel->attr.sample_freq); - } - - if (details->trace_fields) { - struct format_field *field; - - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { - printed += comma_fprintf(fp, &first, " (not a tracepoint)"); - goto out; - } - - field = evsel->tp_format->format.fields; - if (field == NULL) { - printed += comma_fprintf(fp, &first, " (no trace field)"); - goto out; - } - - printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name); - - field = field->next; - while (field) { - printed += comma_fprintf(fp, &first, "%s", field->name); - field = field->next; - } - } -out: - fputc('\n', fp); - return ++printed; -} - -int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, - unsigned int print_opts, struct callchain_cursor *cursor, - FILE *fp) -{ - int printed = 0; - struct callchain_cursor_node *node; - int print_ip = print_opts & EVSEL__PRINT_IP; - int print_sym = print_opts & EVSEL__PRINT_SYM; - int print_dso = print_opts & EVSEL__PRINT_DSO; - int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; - int print_oneline = print_opts & EVSEL__PRINT_ONELINE; - int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; - int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; - char s = print_oneline ? ' ' : '\t'; - - if (sample->callchain) { - struct addr_location node_al; - - callchain_cursor_commit(cursor); - - while (1) { - u64 addr = 0; - - node = callchain_cursor_current(cursor); - if (!node) - break; - - if (node->sym && node->sym->ignore) - goto next; - - printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); - - if (print_ip) - printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); - - if (node->map) - addr = node->map->map_ip(node->map, node->ip); - - if (print_sym) { - printed += fprintf(fp, " "); - node_al.addr = addr; - node_al.map = node->map; - - if (print_symoffset) { - printed += __symbol__fprintf_symname_offs(node->sym, &node_al, - print_unknown_as_addr, fp); - } else { - printed += __symbol__fprintf_symname(node->sym, &node_al, - print_unknown_as_addr, fp); - } - } - - if (print_dso) { - printed += fprintf(fp, " ("); - printed += map__fprintf_dsoname(node->map, fp); - printed += fprintf(fp, ")"); - } - - if (print_srcline) - printed += map__fprintf_srcline(node->map, addr, "\n ", fp); - - if (!print_oneline) - printed += fprintf(fp, "\n"); -next: - callchain_cursor_advance(cursor); - } - } - - return printed; -} - -int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, - int left_alignment, unsigned int print_opts, - struct callchain_cursor *cursor, FILE *fp) -{ - int printed = 0; - int print_ip = print_opts & EVSEL__PRINT_IP; - int print_sym = print_opts & EVSEL__PRINT_SYM; - int print_dso = print_opts & EVSEL__PRINT_DSO; - int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; - int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; - int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; - - if (cursor != NULL) { - printed += sample__fprintf_callchain(sample, left_alignment, - print_opts, cursor, fp); - } else if (!(al->sym && al->sym->ignore)) { - printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); - - if (print_ip) - printed += fprintf(fp, "%16" PRIx64, sample->ip); - - if (print_sym) { - printed += fprintf(fp, " "); - if (print_symoffset) { - printed += __symbol__fprintf_symname_offs(al->sym, al, - print_unknown_as_addr, fp); - } else { - printed += __symbol__fprintf_symname(al->sym, al, - print_unknown_as_addr, fp); - } - } - - if (print_dso) { - printed += fprintf(fp, " ("); - printed += map__fprintf_dsoname(al->map, fp); - printed += fprintf(fp, ")"); - } - - if (print_srcline) - printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); - } - - return printed; -} - - bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize) { diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c new file mode 100644 index 000000000000..3674e77ad640 --- /dev/null +++ b/tools/perf/util/evsel_fprintf.c @@ -0,0 +1,212 @@ +#include +#include +#include +#include "evsel.h" +#include "callchain.h" +#include "map.h" +#include "symbol.h" + +static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) +{ + va_list args; + int ret = 0; + + if (!*first) { + ret += fprintf(fp, ","); + } else { + ret += fprintf(fp, ":"); + *first = false; + } + + va_start(args, fmt); + ret += vfprintf(fp, fmt, args); + va_end(args); + return ret; +} + +static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv) +{ + return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val); +} + +int perf_evsel__fprintf(struct perf_evsel *evsel, + struct perf_attr_details *details, FILE *fp) +{ + bool first = true; + int printed = 0; + + if (details->event_group) { + struct perf_evsel *pos; + + if (!perf_evsel__is_group_leader(evsel)) + return 0; + + if (evsel->nr_members > 1) + printed += fprintf(fp, "%s{", evsel->group_name ?: ""); + + printed += fprintf(fp, "%s", perf_evsel__name(evsel)); + for_each_group_member(pos, evsel) + printed += fprintf(fp, ",%s", perf_evsel__name(pos)); + + if (evsel->nr_members > 1) + printed += fprintf(fp, "}"); + goto out; + } + + printed += fprintf(fp, "%s", perf_evsel__name(evsel)); + + if (details->verbose) { + printed += perf_event_attr__fprintf(fp, &evsel->attr, + __print_attr__fprintf, &first); + } else if (details->freq) { + const char *term = "sample_freq"; + + if (!evsel->attr.freq) + term = "sample_period"; + + printed += comma_fprintf(fp, &first, " %s=%" PRIu64, + term, (u64)evsel->attr.sample_freq); + } + + if (details->trace_fields) { + struct format_field *field; + + if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { + printed += comma_fprintf(fp, &first, " (not a tracepoint)"); + goto out; + } + + field = evsel->tp_format->format.fields; + if (field == NULL) { + printed += comma_fprintf(fp, &first, " (no trace field)"); + goto out; + } + + printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name); + + field = field->next; + while (field) { + printed += comma_fprintf(fp, &first, "%s", field->name); + field = field->next; + } + } +out: + fputc('\n', fp); + return ++printed; +} + +int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, + unsigned int print_opts, struct callchain_cursor *cursor, + FILE *fp) +{ + int printed = 0; + struct callchain_cursor_node *node; + int print_ip = print_opts & EVSEL__PRINT_IP; + int print_sym = print_opts & EVSEL__PRINT_SYM; + int print_dso = print_opts & EVSEL__PRINT_DSO; + int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; + int print_oneline = print_opts & EVSEL__PRINT_ONELINE; + int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; + int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; + char s = print_oneline ? ' ' : '\t'; + + if (sample->callchain) { + struct addr_location node_al; + + callchain_cursor_commit(cursor); + + while (1) { + u64 addr = 0; + + node = callchain_cursor_current(cursor); + if (!node) + break; + + if (node->sym && node->sym->ignore) + goto next; + + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + + if (print_ip) + printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); + + if (node->map) + addr = node->map->map_ip(node->map, node->ip); + + if (print_sym) { + printed += fprintf(fp, " "); + node_al.addr = addr; + node_al.map = node->map; + + if (print_symoffset) { + printed += __symbol__fprintf_symname_offs(node->sym, &node_al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(node->sym, &node_al, + print_unknown_as_addr, fp); + } + } + + if (print_dso) { + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(node->map, fp); + printed += fprintf(fp, ")"); + } + + if (print_srcline) + printed += map__fprintf_srcline(node->map, addr, "\n ", fp); + + if (!print_oneline) + printed += fprintf(fp, "\n"); +next: + callchain_cursor_advance(cursor); + } + } + + return printed; +} + +int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, + int left_alignment, unsigned int print_opts, + struct callchain_cursor *cursor, FILE *fp) +{ + int printed = 0; + int print_ip = print_opts & EVSEL__PRINT_IP; + int print_sym = print_opts & EVSEL__PRINT_SYM; + int print_dso = print_opts & EVSEL__PRINT_DSO; + int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; + int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; + int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; + + if (cursor != NULL) { + printed += sample__fprintf_callchain(sample, left_alignment, + print_opts, cursor, fp); + } else if (!(al->sym && al->sym->ignore)) { + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + + if (print_ip) + printed += fprintf(fp, "%16" PRIx64, sample->ip); + + if (print_sym) { + printed += fprintf(fp, " "); + if (print_symoffset) { + printed += __symbol__fprintf_symname_offs(al->sym, al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(al->sym, al, + print_unknown_as_addr, fp); + } + } + + if (print_dso) { + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(al->map, fp); + printed += fprintf(fp, ")"); + } + + if (print_srcline) + printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); + } + + return printed; +} -- GitLab From 01d1b6e543cfdc0f05027686b35d73de73caec10 Mon Sep 17 00:00:00 2001 From: Rameshwar Prasad Sahu Date: Tue, 29 Mar 2016 15:24:54 +0530 Subject: [PATCH 2845/9938] arm64: dts: apm: Fix compatible string for X-Gene 2 SATA controller DTS node Fix X-Gene SATA controller compatible string for Merlin board. Signed-off-by: Rameshwar Prasad Sahu Acked-by: Suman Tripathi --- arch/arm64/boot/dts/apm/apm-shadowcat.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi index a055a5d443b7..f7a36dbbcb15 100644 --- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi @@ -543,7 +543,7 @@ }; sata1: sata@1a000000 { - compatible = "apm,xgene-ahci"; + compatible = "apm,xgene-ahci-v2"; reg = <0x0 0x1a000000 0x0 0x1000>, <0x0 0x1f200000 0x0 0x1000>, <0x0 0x1f20d000 0x0 0x1000>, @@ -553,7 +553,7 @@ }; sata2: sata@1a200000 { - compatible = "apm,xgene-ahci"; + compatible = "apm,xgene-ahci-v2"; reg = <0x0 0x1a200000 0x0 0x1000>, <0x0 0x1f210000 0x0 0x1000>, <0x0 0x1f21d000 0x0 0x1000>, @@ -563,7 +563,7 @@ }; sata3: sata@1a400000 { - compatible = "apm,xgene-ahci"; + compatible = "apm,xgene-ahci-v2"; reg = <0x0 0x1a400000 0x0 0x1000>, <0x0 0x1f220000 0x0 0x1000>, <0x0 0x1f22d000 0x0 0x1000>, -- GitLab From a85fff3b01ac1d67d9ef15672a9b5b5a4a44204e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 16:44:17 +0200 Subject: [PATCH 2846/9938] PM / Domains: Add DT bindings for the R-Car System Controller The Renesas R-Car System Controller provides power management for the CPU cores and various coprocessors, following the generic PM domain bindings in Documentation/devicetree/bindings/power/power_domain.txt. This supports R-Car Gen1 (H1), Gen2, and Gen3. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Simon Horman --- .../bindings/power/renesas,rcar-sysc.txt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt new file mode 100644 index 000000000000..b74e4d4785ab --- /dev/null +++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt @@ -0,0 +1,48 @@ +DT bindings for the Renesas R-Car System Controller + +== System Controller Node == + +The R-Car System Controller provides power management for the CPU cores and +various coprocessors. + +Required properties: + - compatible: Must contain exactly one of the following: + - "renesas,r8a7779-sysc" (R-Car H1) + - "renesas,r8a7790-sysc" (R-Car H2) + - "renesas,r8a7791-sysc" (R-Car M2-W) + - "renesas,r8a7792-sysc" (R-Car V2H) + - "renesas,r8a7793-sysc" (R-Car M2-N) + - "renesas,r8a7794-sysc" (R-Car E2) + - "renesas,r8a7795-sysc" (R-Car H3) + - reg: Address start and address range for the device. + - #power-domain-cells: Must be 1. + + +Example: + + sysc: system-controller@e6180000 { + compatible = "renesas,r8a7791-sysc"; + reg = <0 0xe6180000 0 0x0200>; + #power-domain-cells = <1>; + }; + + +== PM Domain Consumers == + +Devices residing in a power area must refer to that power area, as documented +by the generic PM domain bindings in +Documentation/devicetree/bindings/power/power_domain.txt. + +Required properties: + - power-domains: A phandle and symbolic PM domain specifier, as defined in + . + + +Example: + + L2_CA15: cache-controller@0 { + compatible = "cache"; + power-domains = <&sysc R8A7791_PD_CA15_SCU>; + cache-unified; + cache-level = <2>; + }; -- GitLab From 79bca98cfb91d4b8dca6af1e865676f7677ca8f2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 16:44:18 +0200 Subject: [PATCH 2847/9938] soc: renesas: Add r8a7779 SYSC PM Domain Binding Definitions Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- include/dt-bindings/power/r8a7779-sysc.h | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 include/dt-bindings/power/r8a7779-sysc.h diff --git a/include/dt-bindings/power/r8a7779-sysc.h b/include/dt-bindings/power/r8a7779-sysc.h new file mode 100644 index 000000000000..183571da507e --- /dev/null +++ b/include/dt-bindings/power/r8a7779-sysc.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ +#ifndef __DT_BINDINGS_POWER_R8A7779_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A7779_SYSC_H__ + +/* + * These power domain indices match the numbers of the interrupt bits + * representing the power areas in the various Interrupt Registers + * (e.g. SYSCISR, Interrupt Status Register) + */ + +#define R8A7779_PD_ARM1 1 +#define R8A7779_PD_ARM2 2 +#define R8A7779_PD_ARM3 3 +#define R8A7779_PD_SGX 20 +#define R8A7779_PD_VDP 21 +#define R8A7779_PD_IMP 24 + +/* Always-on power area */ +#define R8A7779_PD_ALWAYS_ON 32 + +#endif /* __DT_BINDINGS_POWER_R8A7779_SYSC_H__ */ -- GitLab From 3dc4c00a33a82824b710892be4b059637c99cabf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 16:44:19 +0200 Subject: [PATCH 2848/9938] soc: renesas: Add r8a7790 SYSC PM Domain Binding Definitions Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- include/dt-bindings/power/r8a7790-sysc.h | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 include/dt-bindings/power/r8a7790-sysc.h diff --git a/include/dt-bindings/power/r8a7790-sysc.h b/include/dt-bindings/power/r8a7790-sysc.h new file mode 100644 index 000000000000..6af4e9929bd0 --- /dev/null +++ b/include/dt-bindings/power/r8a7790-sysc.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ +#ifndef __DT_BINDINGS_POWER_R8A7790_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A7790_SYSC_H__ + +/* + * These power domain indices match the numbers of the interrupt bits + * representing the power areas in the various Interrupt Registers + * (e.g. SYSCISR, Interrupt Status Register) + */ + +#define R8A7790_PD_CA15_CPU0 0 +#define R8A7790_PD_CA15_CPU1 1 +#define R8A7790_PD_CA15_CPU2 2 +#define R8A7790_PD_CA15_CPU3 3 +#define R8A7790_PD_CA7_CPU0 5 +#define R8A7790_PD_CA7_CPU1 6 +#define R8A7790_PD_CA7_CPU2 7 +#define R8A7790_PD_CA7_CPU3 8 +#define R8A7790_PD_CA15_SCU 12 +#define R8A7790_PD_SH_4A 16 +#define R8A7790_PD_RGX 20 +#define R8A7790_PD_CA7_SCU 21 +#define R8A7790_PD_IMP 24 + +/* Always-on power area */ +#define R8A7790_PD_ALWAYS_ON 32 + +#endif /* __DT_BINDINGS_POWER_R8A7790_SYSC_H__ */ -- GitLab From 434ac75a28d8b2aec08b6b8e080d793857c1b090 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 16:44:20 +0200 Subject: [PATCH 2849/9938] soc: renesas: Add r8a7791 SYSC PM Domain Binding Definitions Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- include/dt-bindings/power/r8a7791-sysc.h | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 include/dt-bindings/power/r8a7791-sysc.h diff --git a/include/dt-bindings/power/r8a7791-sysc.h b/include/dt-bindings/power/r8a7791-sysc.h new file mode 100644 index 000000000000..1403baa0514f --- /dev/null +++ b/include/dt-bindings/power/r8a7791-sysc.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ +#ifndef __DT_BINDINGS_POWER_R8A7791_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A7791_SYSC_H__ + +/* + * These power domain indices match the numbers of the interrupt bits + * representing the power areas in the various Interrupt Registers + * (e.g. SYSCISR, Interrupt Status Register) + */ + +#define R8A7791_PD_CA15_CPU0 0 +#define R8A7791_PD_CA15_CPU1 1 +#define R8A7791_PD_CA15_SCU 12 +#define R8A7791_PD_SH_4A 16 +#define R8A7791_PD_SGX 20 + +/* Always-on power area */ +#define R8A7791_PD_ALWAYS_ON 32 + +#endif /* __DT_BINDINGS_POWER_R8A7791_SYSC_H__ */ -- GitLab From a6171412725e4e7e510a2b91a1d79dbc2ef0e679 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 16:44:21 +0200 Subject: [PATCH 2850/9938] soc: renesas: Add r8a7793 SYSC PM Domain Binding Definitions R-Car M2-N is identical to R-Car M2-W w.r.t. power domains, so reuse the definitions from the latter. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- include/dt-bindings/power/r8a7793-sysc.h | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 include/dt-bindings/power/r8a7793-sysc.h diff --git a/include/dt-bindings/power/r8a7793-sysc.h b/include/dt-bindings/power/r8a7793-sysc.h new file mode 100644 index 000000000000..b5693df3d830 --- /dev/null +++ b/include/dt-bindings/power/r8a7793-sysc.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ +#ifndef __DT_BINDINGS_POWER_R8A7793_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A7793_SYSC_H__ + +/* + * These power domain indices match the numbers of the interrupt bits + * representing the power areas in the various Interrupt Registers + * (e.g. SYSCISR, Interrupt Status Register) + * + * Note that R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. + */ + +#define R8A7793_PD_CA15_CPU0 0 +#define R8A7793_PD_CA15_CPU1 1 +#define R8A7793_PD_CA15_SCU 12 +#define R8A7793_PD_SH_4A 16 +#define R8A7793_PD_SGX 20 + +/* Always-on power area */ +#define R8A7793_PD_ALWAYS_ON 32 + +#endif /* __DT_BINDINGS_POWER_R8A7793_SYSC_H__ */ -- GitLab From 353cf9961acf5e0db8a6cb6f24333ad76dacb8fc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 16:44:22 +0200 Subject: [PATCH 2851/9938] soc: renesas: Add r8a7794 SYSC PM Domain Binding Definitions Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- include/dt-bindings/power/r8a7794-sysc.h | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 include/dt-bindings/power/r8a7794-sysc.h diff --git a/include/dt-bindings/power/r8a7794-sysc.h b/include/dt-bindings/power/r8a7794-sysc.h new file mode 100644 index 000000000000..862241c2d27b --- /dev/null +++ b/include/dt-bindings/power/r8a7794-sysc.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ +#ifndef __DT_BINDINGS_POWER_R8A7794_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A7794_SYSC_H__ + +/* + * These power domain indices match the numbers of the interrupt bits + * representing the power areas in the various Interrupt Registers + * (e.g. SYSCISR, Interrupt Status Register) + */ + +#define R8A7794_PD_CA7_CPU0 5 +#define R8A7794_PD_CA7_CPU1 6 +#define R8A7794_PD_SH_4A 16 +#define R8A7794_PD_SGX 20 +#define R8A7794_PD_CA7_SCU 21 + +/* Always-on power area */ +#define R8A7794_PD_ALWAYS_ON 32 + +#endif /* __DT_BINDINGS_POWER_R8A7794_SYSC_H__ */ -- GitLab From 839a04d847f5871516f500091519c52dc40fe01d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 16:44:23 +0200 Subject: [PATCH 2852/9938] soc: renesas: Add r8a7795 SYSC PM Domain Binding Definitions Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- include/dt-bindings/power/r8a7795-sysc.h | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 include/dt-bindings/power/r8a7795-sysc.h diff --git a/include/dt-bindings/power/r8a7795-sysc.h b/include/dt-bindings/power/r8a7795-sysc.h new file mode 100644 index 000000000000..ee2e26ba605e --- /dev/null +++ b/include/dt-bindings/power/r8a7795-sysc.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ +#ifndef __DT_BINDINGS_POWER_R8A7795_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A7795_SYSC_H__ + +/* + * These power domain indices match the numbers of the interrupt bits + * representing the power areas in the various Interrupt Registers + * (e.g. SYSCISR, Interrupt Status Register) + */ + +#define R8A7795_PD_CA57_CPU0 0 +#define R8A7795_PD_CA57_CPU1 1 +#define R8A7795_PD_CA57_CPU2 2 +#define R8A7795_PD_CA57_CPU3 3 +#define R8A7795_PD_CA53_CPU0 5 +#define R8A7795_PD_CA53_CPU1 6 +#define R8A7795_PD_CA53_CPU2 7 +#define R8A7795_PD_CA53_CPU3 8 +#define R8A7795_PD_A3VP 9 +#define R8A7795_PD_CA57_SCU 12 +#define R8A7795_PD_CR7 13 +#define R8A7795_PD_A3VC 14 +#define R8A7795_PD_3DG_A 17 +#define R8A7795_PD_3DG_B 18 +#define R8A7795_PD_3DG_C 19 +#define R8A7795_PD_3DG_D 20 +#define R8A7795_PD_CA53_SCU 21 +#define R8A7795_PD_3DG_E 22 +#define R8A7795_PD_A3IR 24 +#define R8A7795_PD_A2VC0 25 +#define R8A7795_PD_A2VC1 26 + +/* Always-on power area */ +#define R8A7795_PD_ALWAYS_ON 32 + +#endif /* __DT_BINDINGS_POWER_R8A7795_SYSC_H__ */ -- GitLab From d21fd63ea3856208c3a1cb9b26d81898a2ccf71b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 Apr 2016 21:50:07 -0700 Subject: [PATCH 2853/9938] net: validate_xmit_skb() changes skbs given to validate_xmit_skb() should not have a next pointer anymore. Also if a packet is dropped, increment dev->tx_dropped __dev_queue_xmit() no longer has to change tx_dropped in this case. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 556dd09af3b8..52d446b2cb99 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2959,9 +2959,6 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device { netdev_features_t features; - if (skb->next) - return skb; - features = netif_skb_features(skb); skb = validate_xmit_vlan(skb, features); if (unlikely(!skb)) @@ -3004,6 +3001,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device out_kfree_skb: kfree_skb(skb); out_null: + atomic_long_inc(&dev->tx_dropped); return NULL; } @@ -3393,7 +3391,7 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) skb = validate_xmit_skb(skb, dev); if (!skb) - goto drop; + goto out; HARD_TX_LOCK(dev, txq, cpu); @@ -3420,7 +3418,6 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) } rc = -ENETDOWN; -drop: rcu_read_unlock_bh(); atomic_long_inc(&dev->tx_dropped); -- GitLab From 486bdee0134cf21c3714ded809d5933d2b8dfb81 Mon Sep 17 00:00:00 2001 From: Marcelo Ricardo Leitner Date: Tue, 12 Apr 2016 18:11:31 -0300 Subject: [PATCH 2854/9938] sctp: add support for RPS and RFS This patch adds what's missing to properly support RPS and RFS on SCTP, as some of it is already implemented in common calls. Having support for RPS and RFS allows better scaling specially because not all NICs support hashing SCTP headers. Save the hash right when we dequeue a skb from inqueue so we do it only once per skb instead of per chunk. New sockets will then inherit the hash through sctp_copy_sock(). Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller --- net/sctp/inqueue.c | 3 +++ net/sctp/socket.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index 7e8a16c77039..b335ffcef0b9 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -163,6 +163,9 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) chunk->singleton = 1; ch = (sctp_chunkhdr_t *) chunk->skb->data; chunk->data_accepted = 0; + + if (chunk->asoc) + sock_rps_save_rxhash(chunk->asoc->base.sk, chunk->skb); } chunk->chunk_hdr = ch; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 878d28eda1a6..36697f85ce48 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6430,6 +6430,8 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) poll_wait(file, sk_sleep(sk), wait); + sock_rps_record_flow(sk); + /* A TCP-style listening socket becomes readable when the accept queue * is not empty. */ @@ -7186,6 +7188,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, newsk->sk_lingertime = sk->sk_lingertime; newsk->sk_rcvtimeo = sk->sk_rcvtimeo; newsk->sk_sndtimeo = sk->sk_sndtimeo; + newsk->sk_rxhash = sk->sk_rxhash; newinet = inet_sk(newsk); -- GitLab From 33ff9823c569f3aceb071071914919177a6bed6a Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 13 Apr 2016 00:10:50 +0200 Subject: [PATCH 2855/9938] bpf, verifier: add bpf_call_arg_meta for passing meta data Currently, when the verifier checks calls in check_call() function, we call check_func_arg() for all 5 arguments e.g. to make sure expected types are correct. In some cases, we collect meta data (here: map pointer) to perform additional checks such as checking stack boundary on key/value sizes for subsequent arguments. As we're going to extend the meta data, add a generic struct bpf_call_arg_meta that we can use for passing into check_func_arg(). Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/bpf/verifier.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 6c5d7cd4cb0e..202f8f738542 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -205,6 +205,10 @@ struct verifier_env { #define BPF_COMPLEXITY_LIMIT_INSNS 65536 #define BPF_COMPLEXITY_LIMIT_STACK 1024 +struct bpf_call_arg_meta { + struct bpf_map *map_ptr; +}; + /* verbose verifier prints what it's seeing * bpf_check() is called under lock, so no race to access these global vars */ @@ -822,7 +826,8 @@ static int check_stack_boundary(struct verifier_env *env, int regno, } static int check_func_arg(struct verifier_env *env, u32 regno, - enum bpf_arg_type arg_type, struct bpf_map **mapp) + enum bpf_arg_type arg_type, + struct bpf_call_arg_meta *meta) { struct reg_state *reg = env->cur_state.regs + regno; enum bpf_reg_type expected_type; @@ -875,14 +880,13 @@ static int check_func_arg(struct verifier_env *env, u32 regno, if (arg_type == ARG_CONST_MAP_PTR) { /* bpf_map_xxx(map_ptr) call: remember that map_ptr */ - *mapp = reg->map_ptr; - + meta->map_ptr = reg->map_ptr; } else if (arg_type == ARG_PTR_TO_MAP_KEY) { /* bpf_map_xxx(..., map_ptr, ..., key) call: * check that [key, key + map->key_size) are within * stack limits and initialized */ - if (!*mapp) { + if (!meta->map_ptr) { /* in function declaration map_ptr must come before * map_key, so that it's verified and known before * we have to check map_key here. Otherwise it means @@ -891,19 +895,19 @@ static int check_func_arg(struct verifier_env *env, u32 regno, verbose("invalid map_ptr to access map->key\n"); return -EACCES; } - err = check_stack_boundary(env, regno, (*mapp)->key_size, + err = check_stack_boundary(env, regno, meta->map_ptr->key_size, false); } else if (arg_type == ARG_PTR_TO_MAP_VALUE) { /* bpf_map_xxx(..., map_ptr, ..., value) call: * check [value, value + map->value_size) validity */ - if (!*mapp) { + if (!meta->map_ptr) { /* kernel subsystem misconfigured verifier */ verbose("invalid map_ptr to access map->value\n"); return -EACCES; } - err = check_stack_boundary(env, regno, (*mapp)->value_size, - false); + err = check_stack_boundary(env, regno, + meta->map_ptr->value_size, false); } else if (arg_type == ARG_CONST_STACK_SIZE || arg_type == ARG_CONST_STACK_SIZE_OR_ZERO) { bool zero_size_allowed = (arg_type == ARG_CONST_STACK_SIZE_OR_ZERO); @@ -954,8 +958,8 @@ static int check_call(struct verifier_env *env, int func_id) struct verifier_state *state = &env->cur_state; const struct bpf_func_proto *fn = NULL; struct reg_state *regs = state->regs; - struct bpf_map *map = NULL; struct reg_state *reg; + struct bpf_call_arg_meta meta; int i, err; /* find function prototype */ @@ -978,20 +982,22 @@ static int check_call(struct verifier_env *env, int func_id) return -EINVAL; } + memset(&meta, 0, sizeof(meta)); + /* check args */ - err = check_func_arg(env, BPF_REG_1, fn->arg1_type, &map); + err = check_func_arg(env, BPF_REG_1, fn->arg1_type, &meta); if (err) return err; - err = check_func_arg(env, BPF_REG_2, fn->arg2_type, &map); + err = check_func_arg(env, BPF_REG_2, fn->arg2_type, &meta); if (err) return err; - err = check_func_arg(env, BPF_REG_3, fn->arg3_type, &map); + err = check_func_arg(env, BPF_REG_3, fn->arg3_type, &meta); if (err) return err; - err = check_func_arg(env, BPF_REG_4, fn->arg4_type, &map); + err = check_func_arg(env, BPF_REG_4, fn->arg4_type, &meta); if (err) return err; - err = check_func_arg(env, BPF_REG_5, fn->arg5_type, &map); + err = check_func_arg(env, BPF_REG_5, fn->arg5_type, &meta); if (err) return err; @@ -1013,18 +1019,18 @@ static int check_call(struct verifier_env *env, int func_id) * can check 'value_size' boundary of memory access * to map element returned from bpf_map_lookup_elem() */ - if (map == NULL) { + if (meta.map_ptr == NULL) { verbose("kernel subsystem misconfigured verifier\n"); return -EINVAL; } - regs[BPF_REG_0].map_ptr = map; + regs[BPF_REG_0].map_ptr = meta.map_ptr; } else { verbose("unknown return type %d of func %d\n", fn->ret_type, func_id); return -EINVAL; } - err = check_map_func_compatibility(map, func_id); + err = check_map_func_compatibility(meta.map_ptr, func_id); if (err) return err; -- GitLab From 435faee1aae9c1ac231f89e4faf0437bfe29f425 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 13 Apr 2016 00:10:51 +0200 Subject: [PATCH 2856/9938] bpf, verifier: add ARG_PTR_TO_RAW_STACK type When passing buffers from eBPF stack space into a helper function, we have ARG_PTR_TO_STACK argument type for helpers available. The verifier makes sure that such buffers are initialized, within boundaries, etc. However, the downside with this is that we have a couple of helper functions such as bpf_skb_load_bytes() that fill out the passed buffer in the expected success case anyway, so zero initializing them prior to the helper call is unneeded/wasted instructions in the eBPF program that can be avoided. Therefore, add a new helper function argument type called ARG_PTR_TO_RAW_STACK. The idea is to skip the STACK_MISC check in check_stack_boundary() and color the related stack slots as STACK_MISC after we checked all call arguments. Helper functions using ARG_PTR_TO_RAW_STACK must make sure that every path of the helper function will fill the provided buffer area, so that we cannot leak any uninitialized stack memory. This f.e. means that error paths need to memset() the buffers, but the expected fast-path doesn't have to do this anymore. Since there's no such helper needing more than at most one ARG_PTR_TO_RAW_STACK argument, we can keep it simple and don't need to check for multiple areas. Should in future such a use-case really appear, we have check_raw_mode() that will make sure we implement support for it first. Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/bpf.h | 5 ++++ kernel/bpf/verifier.c | 59 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index b2365a6eba3d..5fb3c610fa96 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -66,6 +66,11 @@ enum bpf_arg_type { * functions that access data on eBPF program stack */ ARG_PTR_TO_STACK, /* any pointer to eBPF program stack */ + ARG_PTR_TO_RAW_STACK, /* any pointer to eBPF program stack, area does not + * need to be initialized, helper function must fill + * all bytes or clear them in error case. + */ + ARG_CONST_STACK_SIZE, /* number of bytes accessed from stack */ ARG_CONST_STACK_SIZE_OR_ZERO, /* number of bytes accessed from stack or 0 */ diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 202f8f738542..9c843a5417da 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -207,6 +207,9 @@ struct verifier_env { struct bpf_call_arg_meta { struct bpf_map *map_ptr; + bool raw_mode; + int regno; + int access_size; }; /* verbose verifier prints what it's seeing @@ -789,7 +792,8 @@ static int check_xadd(struct verifier_env *env, struct bpf_insn *insn) * and all elements of stack are initialized */ static int check_stack_boundary(struct verifier_env *env, int regno, - int access_size, bool zero_size_allowed) + int access_size, bool zero_size_allowed, + struct bpf_call_arg_meta *meta) { struct verifier_state *state = &env->cur_state; struct reg_state *regs = state->regs; @@ -815,6 +819,12 @@ static int check_stack_boundary(struct verifier_env *env, int regno, return -EACCES; } + if (meta && meta->raw_mode) { + meta->access_size = access_size; + meta->regno = regno; + return 0; + } + for (i = 0; i < access_size; i++) { if (state->stack_slot_type[MAX_BPF_STACK + off + i] != STACK_MISC) { verbose("invalid indirect read from stack off %d+%d size %d\n", @@ -859,7 +869,8 @@ static int check_func_arg(struct verifier_env *env, u32 regno, expected_type = CONST_PTR_TO_MAP; } else if (arg_type == ARG_PTR_TO_CTX) { expected_type = PTR_TO_CTX; - } else if (arg_type == ARG_PTR_TO_STACK) { + } else if (arg_type == ARG_PTR_TO_STACK || + arg_type == ARG_PTR_TO_RAW_STACK) { expected_type = PTR_TO_STACK; /* One exception here. In case function allows for NULL to be * passed in as argument, it's a CONST_IMM type. Final test @@ -867,6 +878,7 @@ static int check_func_arg(struct verifier_env *env, u32 regno, */ if (reg->type == CONST_IMM && reg->imm == 0) expected_type = CONST_IMM; + meta->raw_mode = arg_type == ARG_PTR_TO_RAW_STACK; } else { verbose("unsupported arg_type %d\n", arg_type); return -EFAULT; @@ -896,7 +908,7 @@ static int check_func_arg(struct verifier_env *env, u32 regno, return -EACCES; } err = check_stack_boundary(env, regno, meta->map_ptr->key_size, - false); + false, NULL); } else if (arg_type == ARG_PTR_TO_MAP_VALUE) { /* bpf_map_xxx(..., map_ptr, ..., value) call: * check [value, value + map->value_size) validity @@ -907,7 +919,8 @@ static int check_func_arg(struct verifier_env *env, u32 regno, return -EACCES; } err = check_stack_boundary(env, regno, - meta->map_ptr->value_size, false); + meta->map_ptr->value_size, + false, NULL); } else if (arg_type == ARG_CONST_STACK_SIZE || arg_type == ARG_CONST_STACK_SIZE_OR_ZERO) { bool zero_size_allowed = (arg_type == ARG_CONST_STACK_SIZE_OR_ZERO); @@ -922,7 +935,7 @@ static int check_func_arg(struct verifier_env *env, u32 regno, return -EACCES; } err = check_stack_boundary(env, regno - 1, reg->imm, - zero_size_allowed); + zero_size_allowed, meta); } return err; @@ -953,6 +966,24 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id) return 0; } +static int check_raw_mode(const struct bpf_func_proto *fn) +{ + int count = 0; + + if (fn->arg1_type == ARG_PTR_TO_RAW_STACK) + count++; + if (fn->arg2_type == ARG_PTR_TO_RAW_STACK) + count++; + if (fn->arg3_type == ARG_PTR_TO_RAW_STACK) + count++; + if (fn->arg4_type == ARG_PTR_TO_RAW_STACK) + count++; + if (fn->arg5_type == ARG_PTR_TO_RAW_STACK) + count++; + + return count > 1 ? -EINVAL : 0; +} + static int check_call(struct verifier_env *env, int func_id) { struct verifier_state *state = &env->cur_state; @@ -984,6 +1015,15 @@ static int check_call(struct verifier_env *env, int func_id) memset(&meta, 0, sizeof(meta)); + /* We only support one arg being in raw mode at the moment, which + * is sufficient for the helper functions we have right now. + */ + err = check_raw_mode(fn); + if (err) { + verbose("kernel subsystem misconfigured func %d\n", func_id); + return err; + } + /* check args */ err = check_func_arg(env, BPF_REG_1, fn->arg1_type, &meta); if (err) @@ -1001,6 +1041,15 @@ static int check_call(struct verifier_env *env, int func_id) if (err) return err; + /* Mark slots with STACK_MISC in case of raw mode, stack offset + * is inferred from register state. + */ + for (i = 0; i < meta.access_size; i++) { + err = check_mem_access(env, meta.regno, i, BPF_B, BPF_WRITE, -1); + if (err) + return err; + } + /* reset caller saved regs */ for (i = 0; i < CALLER_SAVED_REGS; i++) { reg = regs + caller_saved[i]; -- GitLab From 074f528eed408b467516e142fa4c45e5b0d2ba16 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 13 Apr 2016 00:10:52 +0200 Subject: [PATCH 2857/9938] bpf: convert relevant helper args to ARG_PTR_TO_RAW_STACK This patch converts all helpers that can use ARG_PTR_TO_RAW_STACK as argument type. For tc programs this is bpf_skb_load_bytes(), bpf_skb_get_tunnel_key(), bpf_skb_get_tunnel_opt(). For tracing, this optimizes bpf_get_current_comm() and bpf_probe_read(). The check in bpf_skb_load_bytes() for MAX_BPF_STACK can also be removed since the verifier already makes sure we stay within bounds on stack buffers. Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/bpf/helpers.c | 17 +++++++++--- kernel/trace/bpf_trace.c | 10 ++++--- net/core/filter.c | 57 ++++++++++++++++++++++++++++------------ 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 50da680c479f..ad7a0573f71b 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -163,17 +163,26 @@ static u64 bpf_get_current_comm(u64 r1, u64 size, u64 r3, u64 r4, u64 r5) struct task_struct *task = current; char *buf = (char *) (long) r1; - if (!task) - return -EINVAL; + if (unlikely(!task)) + goto err_clear; - strlcpy(buf, task->comm, min_t(size_t, size, sizeof(task->comm))); + strncpy(buf, task->comm, size); + + /* Verifier guarantees that size > 0. For task->comm exceeding + * size, guarantee that buf is %NUL-terminated. Unconditionally + * done here to save the size test. + */ + buf[size - 1] = 0; return 0; +err_clear: + memset(buf, 0, size); + return -EINVAL; } const struct bpf_func_proto bpf_get_current_comm_proto = { .func = bpf_get_current_comm, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_STACK, + .arg1_type = ARG_PTR_TO_RAW_STACK, .arg2_type = ARG_CONST_STACK_SIZE, }; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 413ec5614180..685587885374 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -62,17 +62,21 @@ EXPORT_SYMBOL_GPL(trace_call_bpf); static u64 bpf_probe_read(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) { void *dst = (void *) (long) r1; - int size = (int) r2; + int ret, size = (int) r2; void *unsafe_ptr = (void *) (long) r3; - return probe_kernel_read(dst, unsafe_ptr, size); + ret = probe_kernel_read(dst, unsafe_ptr, size); + if (unlikely(ret < 0)) + memset(dst, 0, size); + + return ret; } static const struct bpf_func_proto bpf_probe_read_proto = { .func = bpf_probe_read, .gpl_only = true, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_STACK, + .arg1_type = ARG_PTR_TO_RAW_STACK, .arg2_type = ARG_CONST_STACK_SIZE, .arg3_type = ARG_ANYTHING, }; diff --git a/net/core/filter.c b/net/core/filter.c index e8486ba601ea..5d2ac2b9d1c4 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1409,16 +1409,19 @@ static u64 bpf_skb_load_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) unsigned int len = (unsigned int) r4; void *ptr; - if (unlikely((u32) offset > 0xffff || len > MAX_BPF_STACK)) - return -EFAULT; + if (unlikely((u32) offset > 0xffff)) + goto err_clear; ptr = skb_header_pointer(skb, offset, len, to); if (unlikely(!ptr)) - return -EFAULT; + goto err_clear; if (ptr != to) memcpy(to, ptr, len); return 0; +err_clear: + memset(to, 0, len); + return -EFAULT; } static const struct bpf_func_proto bpf_skb_load_bytes_proto = { @@ -1427,7 +1430,7 @@ static const struct bpf_func_proto bpf_skb_load_bytes_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_STACK, + .arg3_type = ARG_PTR_TO_RAW_STACK, .arg4_type = ARG_CONST_STACK_SIZE, }; @@ -1756,12 +1759,19 @@ static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) struct bpf_tunnel_key *to = (struct bpf_tunnel_key *) (long) r2; const struct ip_tunnel_info *info = skb_tunnel_info(skb); u8 compat[sizeof(struct bpf_tunnel_key)]; + void *to_orig = to; + int err; - if (unlikely(!info || (flags & ~(BPF_F_TUNINFO_IPV6)))) - return -EINVAL; - if (ip_tunnel_info_af(info) != bpf_tunnel_key_af(flags)) - return -EPROTO; + if (unlikely(!info || (flags & ~(BPF_F_TUNINFO_IPV6)))) { + err = -EINVAL; + goto err_clear; + } + if (ip_tunnel_info_af(info) != bpf_tunnel_key_af(flags)) { + err = -EPROTO; + goto err_clear; + } if (unlikely(size != sizeof(struct bpf_tunnel_key))) { + err = -EINVAL; switch (size) { case offsetof(struct bpf_tunnel_key, tunnel_label): case offsetof(struct bpf_tunnel_key, tunnel_ext): @@ -1771,12 +1781,12 @@ static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) * a common path later on. */ if (ip_tunnel_info_af(info) != AF_INET) - return -EINVAL; + goto err_clear; set_compat: to = (struct bpf_tunnel_key *)compat; break; default: - return -EINVAL; + goto err_clear; } } @@ -1793,9 +1803,12 @@ static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) } if (unlikely(size != sizeof(struct bpf_tunnel_key))) - memcpy((void *)(long) r2, to, size); + memcpy(to_orig, to, size); return 0; +err_clear: + memset(to_orig, 0, size); + return err; } static const struct bpf_func_proto bpf_skb_get_tunnel_key_proto = { @@ -1803,7 +1816,7 @@ static const struct bpf_func_proto bpf_skb_get_tunnel_key_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_STACK, + .arg2_type = ARG_PTR_TO_RAW_STACK, .arg3_type = ARG_CONST_STACK_SIZE, .arg4_type = ARG_ANYTHING, }; @@ -1813,16 +1826,26 @@ static u64 bpf_skb_get_tunnel_opt(u64 r1, u64 r2, u64 size, u64 r4, u64 r5) struct sk_buff *skb = (struct sk_buff *) (long) r1; u8 *to = (u8 *) (long) r2; const struct ip_tunnel_info *info = skb_tunnel_info(skb); + int err; if (unlikely(!info || - !(info->key.tun_flags & TUNNEL_OPTIONS_PRESENT))) - return -ENOENT; - if (unlikely(size < info->options_len)) - return -ENOMEM; + !(info->key.tun_flags & TUNNEL_OPTIONS_PRESENT))) { + err = -ENOENT; + goto err_clear; + } + if (unlikely(size < info->options_len)) { + err = -ENOMEM; + goto err_clear; + } ip_tunnel_info_opts_get(to, info); + if (size > info->options_len) + memset(to + info->options_len, 0, size - info->options_len); return info->options_len; +err_clear: + memset(to, 0, size); + return err; } static const struct bpf_func_proto bpf_skb_get_tunnel_opt_proto = { @@ -1830,7 +1853,7 @@ static const struct bpf_func_proto bpf_skb_get_tunnel_opt_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_STACK, + .arg2_type = ARG_PTR_TO_RAW_STACK, .arg3_type = ARG_CONST_STACK_SIZE, }; -- GitLab From 02413cabd6b67f1444f153ea85d44076deae2056 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 13 Apr 2016 00:10:53 +0200 Subject: [PATCH 2858/9938] bpf, samples: don't zero data when not needed Remove the zero initialization in the sample programs where appropriate. Note that this is an optimization which is now possible, old programs still doing the zero initialization are just fine as well. Also, make sure we don't have padding issues when we don't memset() the entire struct anymore. Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/offwaketime_kern.c | 10 ++++++---- samples/bpf/tracex1_kern.c | 4 +--- samples/bpf/tracex2_kern.c | 4 ++-- samples/bpf/tracex5_kern.c | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/samples/bpf/offwaketime_kern.c b/samples/bpf/offwaketime_kern.c index 983629a31c79..e7d9a0a3d45b 100644 --- a/samples/bpf/offwaketime_kern.c +++ b/samples/bpf/offwaketime_kern.c @@ -11,7 +11,7 @@ #include #include -#define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;}) +#define _(P) ({typeof(P) val; bpf_probe_read(&val, sizeof(val), &P); val;}) #define MINBLOCK_US 1 @@ -61,7 +61,7 @@ SEC("kprobe/try_to_wake_up") int waker(struct pt_regs *ctx) { struct task_struct *p = (void *) PT_REGS_PARM1(ctx); - struct wokeby_t woke = {}; + struct wokeby_t woke; u32 pid; pid = _(p->pid); @@ -75,17 +75,19 @@ int waker(struct pt_regs *ctx) static inline int update_counts(void *ctx, u32 pid, u64 delta) { - struct key_t key = {}; struct wokeby_t *woke; u64 zero = 0, *val; + struct key_t key; + __builtin_memset(&key.waker, 0, sizeof(key.waker)); bpf_get_current_comm(&key.target, sizeof(key.target)); key.tret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS); + key.wret = 0; woke = bpf_map_lookup_elem(&wokeby, &pid); if (woke) { key.wret = woke->ret; - __builtin_memcpy(&key.waker, woke->name, TASK_COMM_LEN); + __builtin_memcpy(&key.waker, woke->name, sizeof(key.waker)); bpf_map_delete_elem(&wokeby, &pid); } diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c index 3f450a8fa1f3..107da148820f 100644 --- a/samples/bpf/tracex1_kern.c +++ b/samples/bpf/tracex1_kern.c @@ -23,16 +23,14 @@ int bpf_prog1(struct pt_regs *ctx) /* attaches to kprobe netif_receive_skb, * looks for packets on loobpack device and prints them */ - char devname[IFNAMSIZ] = {}; + char devname[IFNAMSIZ]; struct net_device *dev; struct sk_buff *skb; int len; /* non-portable! works for the given kernel only */ skb = (struct sk_buff *) PT_REGS_PARM1(ctx); - dev = _(skb->dev); - len = _(skb->len); bpf_probe_read(devname, sizeof(devname), dev->name); diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c index 6d6eefd0d465..5e11c20ce5ec 100644 --- a/samples/bpf/tracex2_kern.c +++ b/samples/bpf/tracex2_kern.c @@ -66,7 +66,7 @@ struct hist_key { char comm[16]; u64 pid_tgid; u64 uid_gid; - u32 index; + u64 index; }; struct bpf_map_def SEC("maps") my_hist_map = { @@ -82,7 +82,7 @@ int bpf_prog3(struct pt_regs *ctx) long write_size = PT_REGS_PARM3(ctx); long init_val = 1; long *value; - struct hist_key key = {}; + struct hist_key key; key.index = log2l(write_size); key.pid_tgid = bpf_get_current_pid_tgid(); diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5_kern.c index b3f4295bf288..f95f232cbab9 100644 --- a/samples/bpf/tracex5_kern.c +++ b/samples/bpf/tracex5_kern.c @@ -22,7 +22,7 @@ struct bpf_map_def SEC("maps") progs = { SEC("kprobe/seccomp_phase1") int bpf_prog1(struct pt_regs *ctx) { - struct seccomp_data sd = {}; + struct seccomp_data sd; bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); @@ -40,7 +40,7 @@ int bpf_prog1(struct pt_regs *ctx) /* we jump here when syscall number == __NR_write */ PROG(__NR_write)(struct pt_regs *ctx) { - struct seccomp_data sd = {}; + struct seccomp_data sd; bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); if (sd.args[2] == 512) { @@ -53,7 +53,7 @@ PROG(__NR_write)(struct pt_regs *ctx) PROG(__NR_read)(struct pt_regs *ctx) { - struct seccomp_data sd = {}; + struct seccomp_data sd; bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); if (sd.args[2] > 128 && sd.args[2] <= 1024) { -- GitLab From 3f2050e20e6f3a762eb08397db651dcec9498998 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 13 Apr 2016 00:10:54 +0200 Subject: [PATCH 2859/9938] bpf, samples: add test cases for raw stack This adds test cases mostly around ARG_PTR_TO_RAW_STACK to check the verifier behaviour. [...] #84 raw_stack: no skb_load_bytes OK #85 raw_stack: skb_load_bytes, no init OK #86 raw_stack: skb_load_bytes, init OK #87 raw_stack: skb_load_bytes, spilled regs around bounds OK #88 raw_stack: skb_load_bytes, spilled regs corruption OK #89 raw_stack: skb_load_bytes, spilled regs corruption 2 OK #90 raw_stack: skb_load_bytes, spilled regs + data OK #91 raw_stack: skb_load_bytes, invalid access 1 OK #92 raw_stack: skb_load_bytes, invalid access 2 OK #93 raw_stack: skb_load_bytes, invalid access 3 OK #94 raw_stack: skb_load_bytes, invalid access 4 OK #95 raw_stack: skb_load_bytes, invalid access 5 OK #96 raw_stack: skb_load_bytes, invalid access 6 OK #97 raw_stack: skb_load_bytes, large access OK Summary: 98 PASSED, 0 FAILED Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/test_verifier.c | 268 ++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c index 4b51a9039c0d..9eba8d1d9dcc 100644 --- a/samples/bpf/test_verifier.c +++ b/samples/bpf/test_verifier.c @@ -308,6 +308,19 @@ static struct bpf_test tests[] = { .result = ACCEPT, .result_unpriv = REJECT, }, + { + "check valid spill/fill, skb mark", + .insns = { + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_1), + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -8), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, + offsetof(struct __sk_buff, mark)), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + .result_unpriv = ACCEPT, + }, { "check corrupted spill/fill", .insns = { @@ -1180,6 +1193,261 @@ static struct bpf_test tests[] = { .result_unpriv = REJECT, .result = ACCEPT, }, + { + "raw_stack: no skb_load_bytes", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + /* Call to skb_load_bytes() omitted. */ + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid read from stack off -8+0 size 8", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, no init", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, init", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8), + BPF_ST_MEM(BPF_DW, BPF_REG_6, 0, 0xcafe), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, spilled regs around bounds", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16), + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */ + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */ + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */ + BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, + offsetof(struct __sk_buff, mark)), + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2, + offsetof(struct __sk_buff, priority)), + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, spilled regs corruption", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8), + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */ + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), /* fill ctx into R0 */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, + offsetof(struct __sk_buff, mark)), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "R0 invalid mem access 'inv'", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, spilled regs corruption 2", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16), + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */ + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */ + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */ + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */ + BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */ + BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill ctx into R3 */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, + offsetof(struct __sk_buff, mark)), + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2, + offsetof(struct __sk_buff, priority)), + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_3, + offsetof(struct __sk_buff, pkt_type)), + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "R3 invalid mem access 'inv'", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, spilled regs + data", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16), + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */ + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */ + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */ + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */ + BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */ + BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill data into R3 */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, + offsetof(struct __sk_buff, mark)), + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2, + offsetof(struct __sk_buff, priority)), + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2), + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, invalid access 1", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -513), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid stack type R3 off=-513 access_size=8", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, invalid access 2", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid stack type R3 off=-1 access_size=8", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, invalid access 3", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 0xffffffff), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid stack type R3 off=-1 access_size=-1", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, invalid access 4", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid stack type R3 off=-1 access_size=2147483647", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, invalid access 5", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid stack type R3 off=-512 access_size=2147483647", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, invalid access 6", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid stack type R3 off=-512 access_size=0", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, + { + "raw_stack: skb_load_bytes, large access", + .insns = { + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), + BPF_MOV64_IMM(BPF_REG_4, 512), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + }, }; static int probe_filter_length(struct bpf_insn *fp) -- GitLab From 608b9977260f67d8b032ea170666a6174a48e2f1 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Wed, 13 Apr 2016 10:52:20 +0200 Subject: [PATCH 2860/9938] tun: use per cpu variables for stats accounting Currently the tun device accounting uses dev->stats without applying any kind of protection, regardless that accounting happens in preemptible process context. This patch move the tun stats to a per cpu data structure, and protect the updates with u64_stats_update_begin()/u64_stats_update_end() or this_cpu_inc according to the stat type. The per cpu stats are aggregated by the newly added ndo_get_stats64 ops. Signed-off-by: Paolo Abeni Signed-off-by: David S. Miller --- drivers/net/tun.c | 95 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a74661690a11..faf9297db2cf 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -131,6 +131,17 @@ struct tap_filter { #define TUN_FLOW_EXPIRE (3 * HZ) +struct tun_pcpu_stats { + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; + u32 rx_dropped; + u32 tx_dropped; + u32 rx_frame_errors; +}; + /* A tun_file connects an open character device to a tuntap netdevice. It * also contains all socket related structures (except sock_fprog and tap_filter) * to serve as one transmit queue for tuntap device. The sock_fprog and @@ -205,6 +216,7 @@ struct tun_struct { struct list_head disabled; void *security; u32 flow_count; + struct tun_pcpu_stats __percpu *pcpu_stats; }; #ifdef CONFIG_TUN_VNET_CROSS_LE @@ -886,7 +898,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; drop: - dev->stats.tx_dropped++; + this_cpu_inc(tun->pcpu_stats->tx_dropped); skb_tx_error(skb); kfree_skb(skb); rcu_read_unlock(); @@ -949,6 +961,43 @@ static void tun_set_headroom(struct net_device *dev, int new_hr) tun->align = new_hr; } +static struct rtnl_link_stats64 * +tun_net_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +{ + u32 rx_dropped = 0, tx_dropped = 0, rx_frame_errors = 0; + struct tun_struct *tun = netdev_priv(dev); + struct tun_pcpu_stats *p; + int i; + + for_each_possible_cpu(i) { + u64 rxpackets, rxbytes, txpackets, txbytes; + unsigned int start; + + p = per_cpu_ptr(tun->pcpu_stats, i); + do { + start = u64_stats_fetch_begin(&p->syncp); + rxpackets = p->rx_packets; + rxbytes = p->rx_bytes; + txpackets = p->tx_packets; + txbytes = p->tx_bytes; + } while (u64_stats_fetch_retry(&p->syncp, start)); + + stats->rx_packets += rxpackets; + stats->rx_bytes += rxbytes; + stats->tx_packets += txpackets; + stats->tx_bytes += txbytes; + + /* u32 counters */ + rx_dropped += p->rx_dropped; + rx_frame_errors += p->rx_frame_errors; + tx_dropped += p->tx_dropped; + } + stats->rx_dropped = rx_dropped; + stats->rx_frame_errors = rx_frame_errors; + stats->tx_dropped = tx_dropped; + return stats; +} + static const struct net_device_ops tun_netdev_ops = { .ndo_uninit = tun_net_uninit, .ndo_open = tun_net_open, @@ -961,6 +1010,7 @@ static const struct net_device_ops tun_netdev_ops = { .ndo_poll_controller = tun_poll_controller, #endif .ndo_set_rx_headroom = tun_set_headroom, + .ndo_get_stats64 = tun_net_get_stats64, }; static const struct net_device_ops tap_netdev_ops = { @@ -979,6 +1029,7 @@ static const struct net_device_ops tap_netdev_ops = { #endif .ndo_features_check = passthru_features_check, .ndo_set_rx_headroom = tun_set_headroom, + .ndo_get_stats64 = tun_net_get_stats64, }; static void tun_flow_init(struct tun_struct *tun) @@ -1103,6 +1154,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, size_t total_len = iov_iter_count(from); size_t len = total_len, align = tun->align, linear; struct virtio_net_hdr gso = { 0 }; + struct tun_pcpu_stats *stats; int good_linear; int copylen; bool zerocopy = false; @@ -1177,7 +1229,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); if (IS_ERR(skb)) { if (PTR_ERR(skb) != -EAGAIN) - tun->dev->stats.rx_dropped++; + this_cpu_inc(tun->pcpu_stats->rx_dropped); return PTR_ERR(skb); } @@ -1192,7 +1244,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, } if (err) { - tun->dev->stats.rx_dropped++; + this_cpu_inc(tun->pcpu_stats->rx_dropped); kfree_skb(skb); return -EFAULT; } @@ -1200,7 +1252,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { if (!skb_partial_csum_set(skb, tun16_to_cpu(tun, gso.csum_start), tun16_to_cpu(tun, gso.csum_offset))) { - tun->dev->stats.rx_frame_errors++; + this_cpu_inc(tun->pcpu_stats->rx_frame_errors); kfree_skb(skb); return -EINVAL; } @@ -1217,7 +1269,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, pi.proto = htons(ETH_P_IPV6); break; default: - tun->dev->stats.rx_dropped++; + this_cpu_inc(tun->pcpu_stats->rx_dropped); kfree_skb(skb); return -EINVAL; } @@ -1245,7 +1297,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, skb_shinfo(skb)->gso_type = SKB_GSO_UDP; break; default: - tun->dev->stats.rx_frame_errors++; + this_cpu_inc(tun->pcpu_stats->rx_frame_errors); kfree_skb(skb); return -EINVAL; } @@ -1255,7 +1307,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, skb_shinfo(skb)->gso_size = tun16_to_cpu(tun, gso.gso_size); if (skb_shinfo(skb)->gso_size == 0) { - tun->dev->stats.rx_frame_errors++; + this_cpu_inc(tun->pcpu_stats->rx_frame_errors); kfree_skb(skb); return -EINVAL; } @@ -1278,8 +1330,12 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, rxhash = skb_get_hash(skb); netif_rx_ni(skb); - tun->dev->stats.rx_packets++; - tun->dev->stats.rx_bytes += len; + stats = get_cpu_ptr(tun->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + stats->rx_packets++; + stats->rx_bytes += len; + u64_stats_update_end(&stats->syncp); + put_cpu_ptr(stats); tun_flow_update(tun, rxhash, tfile); return total_len; @@ -1308,6 +1364,7 @@ static ssize_t tun_put_user(struct tun_struct *tun, struct iov_iter *iter) { struct tun_pi pi = { 0, skb->protocol }; + struct tun_pcpu_stats *stats; ssize_t total; int vlan_offset = 0; int vlan_hlen = 0; @@ -1408,8 +1465,13 @@ static ssize_t tun_put_user(struct tun_struct *tun, skb_copy_datagram_iter(skb, vlan_offset, iter, skb->len - vlan_offset); done: - tun->dev->stats.tx_packets++; - tun->dev->stats.tx_bytes += skb->len + vlan_hlen; + /* caller is in process context, */ + stats = get_cpu_ptr(tun->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + stats->tx_packets++; + stats->tx_bytes += skb->len + vlan_hlen; + u64_stats_update_end(&stats->syncp); + put_cpu_ptr(tun->pcpu_stats); return total; } @@ -1467,6 +1529,7 @@ static void tun_free_netdev(struct net_device *dev) struct tun_struct *tun = netdev_priv(dev); BUG_ON(!(list_empty(&tun->disabled))); + free_percpu(tun->pcpu_stats); tun_flow_uninit(tun); security_tun_dev_free_security(tun->security); free_netdev(dev); @@ -1715,11 +1778,17 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun->filter_attached = false; tun->sndbuf = tfile->socket.sk->sk_sndbuf; + tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats); + if (!tun->pcpu_stats) { + err = -ENOMEM; + goto err_free_dev; + } + spin_lock_init(&tun->lock); err = security_tun_dev_alloc_security(&tun->security); if (err < 0) - goto err_free_dev; + goto err_free_stat; tun_net_init(dev); tun_flow_init(tun); @@ -1763,6 +1832,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) err_free_flow: tun_flow_uninit(tun); security_tun_dev_free_security(tun->security); +err_free_stat: + free_percpu(tun->pcpu_stats); err_free_dev: free_netdev(dev); return err; -- GitLab From 0fa5867e6a2c6119fac35b8b710bec87b4598940 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:24:55 -0700 Subject: [PATCH 2861/9938] dmaengine: bcm2835: set residue_granularity field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bcm2835-dma supports residue reporting at burst level but didn't report this via the residue_granularity field. See also: https://github.com/raspberrypi/linux/commit/b015555327afa402f70ddc86e3632f59df1cd9d7 for the downstream patch. Signed-off-by: Matthias Reichl Signed-off-by: Noralf Trønnes Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 996c4b00d323..2d72fe81243f 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -625,6 +625,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; od->ddev.dev = &pdev->dev; INIT_LIST_HEAD(&od->ddev.channels); spin_lock_init(&od->lock); -- GitLab From a1d71ba90c68a5dfd87dd4c1a6386cef017d9ecb Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:24:56 -0700 Subject: [PATCH 2862/9938] dmaengine: bcm2835: remove unnecessary masking of dma channels The original patch contained 3 dma channels that were masked out. These - as far as research and discussions show - are a artefacts remaining from the downstream legacy dma-api. Right now down-stream still includes a legacy api used only in a single (downstream only) driver (bcm2708_fb) that requires 2D DMA for speedup (DMA-channel 0). Formerly the sd-card support driver also was using this legacy api (DMA-channel 2), but since has been moved over to use dmaengine directly. The DMA-channel 3 is already masked out in the devicetree in the default property "brcm,dma-channel-mask = <0x7f35>;" So we can remove the whole masking of DMA channels. Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 2d72fe81243f..e4ca980049ba 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -123,9 +123,6 @@ struct bcm2835_desc { #define BCM2835_DMA_DATA_TYPE_S32 4 #define BCM2835_DMA_DATA_TYPE_S128 16 -#define BCM2835_DMA_BULK_MASK BIT(0) -#define BCM2835_DMA_FIQ_MASK (BIT(2) | BIT(3)) - /* Valid only for channels 0 - 14, 15 has its own base address */ #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) @@ -641,12 +638,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) goto err_no_dma; } - /* - * Do not use the FIQ and BULK channels, - * because they are used by the GPU. - */ - chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); - for (i = 0; i < pdev->num_resources; i++) { irq = platform_get_irq(pdev, i); if (irq < 0) -- GitLab From e42685d7a7d5afa6278561ffd85c475eae246be3 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:24:57 -0700 Subject: [PATCH 2863/9938] dmaengine: bcm2835: add additional defines for DMA-registers Add additional defines describing the DMA registers as well as adding some more documentation to those registers. Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 57 +++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index e4ca980049ba..a1d851aa5b18 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -97,26 +97,67 @@ struct bcm2835_desc { #define BCM2835_DMA_CS 0x00 #define BCM2835_DMA_ADDR 0x04 +#define BCM2835_DMA_TI 0x08 #define BCM2835_DMA_SOURCE_AD 0x0c #define BCM2835_DMA_DEST_AD 0x10 -#define BCM2835_DMA_NEXTCB 0x1C +#define BCM2835_DMA_LEN 0x14 +#define BCM2835_DMA_STRIDE 0x18 +#define BCM2835_DMA_NEXTCB 0x1c +#define BCM2835_DMA_DEBUG 0x20 /* DMA CS Control and Status bits */ -#define BCM2835_DMA_ACTIVE BIT(0) -#define BCM2835_DMA_INT BIT(2) +#define BCM2835_DMA_ACTIVE BIT(0) /* activate the DMA */ +#define BCM2835_DMA_END BIT(1) /* current CB has ended */ +#define BCM2835_DMA_INT BIT(2) /* interrupt status */ +#define BCM2835_DMA_DREQ BIT(3) /* DREQ state */ #define BCM2835_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ #define BCM2835_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ -#define BCM2835_DMA_ERR BIT(8) +#define BCM2835_DMA_WAITING_FOR_WRITES BIT(6) /* waiting for last + * AXI-write to ack + */ +#define BCM2835_DMA_ERR BIT(8) +#define BCM2835_DMA_PRIORITY(x) ((x & 15) << 16) /* AXI priority */ +#define BCM2835_DMA_PANIC_PRIORITY(x) ((x & 15) << 20) /* panic priority */ +/* current value of TI.BCM2835_DMA_WAIT_RESP */ +#define BCM2835_DMA_WAIT_FOR_WRITES BIT(28) +#define BCM2835_DMA_DIS_DEBUG BIT(29) /* disable debug pause signal */ #define BCM2835_DMA_ABORT BIT(30) /* Stop current CB, go to next, WO */ #define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ +/* Transfer information bits - also bcm2835_cb.info field */ #define BCM2835_DMA_INT_EN BIT(0) +#define BCM2835_DMA_TDMODE BIT(1) /* 2D-Mode */ +#define BCM2835_DMA_WAIT_RESP BIT(3) /* wait for AXI-write to be acked */ #define BCM2835_DMA_D_INC BIT(4) -#define BCM2835_DMA_D_DREQ BIT(6) +#define BCM2835_DMA_D_WIDTH BIT(5) /* 128bit writes if set */ +#define BCM2835_DMA_D_DREQ BIT(6) /* enable DREQ for destination */ +#define BCM2835_DMA_D_IGNORE BIT(7) /* ignore destination writes */ #define BCM2835_DMA_S_INC BIT(8) -#define BCM2835_DMA_S_DREQ BIT(10) - -#define BCM2835_DMA_PER_MAP(x) ((x) << 16) +#define BCM2835_DMA_S_WIDTH BIT(9) /* 128bit writes if set */ +#define BCM2835_DMA_S_DREQ BIT(10) /* enable SREQ for source */ +#define BCM2835_DMA_S_IGNORE BIT(11) /* ignore source reads - read 0 */ +#define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12) +#define BCM2835_DMA_PER_MAP(x) ((x & 31) << 16) /* REQ source */ +#define BCM2835_DMA_WAIT(x) ((x & 31) << 21) /* add DMA-wait cycles */ +#define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */ + +/* debug register bits */ +#define BCM2835_DMA_DEBUG_LAST_NOT_SET_ERR BIT(0) +#define BCM2835_DMA_DEBUG_FIFO_ERR BIT(1) +#define BCM2835_DMA_DEBUG_READ_ERR BIT(2) +#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_SHIFT 4 +#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_BITS 4 +#define BCM2835_DMA_DEBUG_ID_SHIFT 16 +#define BCM2835_DMA_DEBUG_ID_BITS 9 +#define BCM2835_DMA_DEBUG_STATE_SHIFT 16 +#define BCM2835_DMA_DEBUG_STATE_BITS 9 +#define BCM2835_DMA_DEBUG_VERSION_SHIFT 25 +#define BCM2835_DMA_DEBUG_VERSION_BITS 3 +#define BCM2835_DMA_DEBUG_LITE BIT(28) + +/* shared registers for all dma channels */ +#define BCM2835_DMA_INT_STATUS 0xfe0 +#define BCM2835_DMA_ENABLE 0xff0 #define BCM2835_DMA_DATA_TYPE_S8 1 #define BCM2835_DMA_DATA_TYPE_S16 2 -- GitLab From a4dcdd849ef8dbd0811ca8436aecf1c87e09686c Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:24:58 -0700 Subject: [PATCH 2864/9938] dmaengine: bcm2835: move cyclic member from bcm2835_chan into bcm2835_desc In preparation to consolidating code we move the cyclic member into the bcm_2835_desc structure. Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index a1d851aa5b18..b3bc382fd199 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -73,7 +73,6 @@ struct bcm2835_chan { struct list_head node; struct dma_slave_config cfg; - bool cyclic; unsigned int dreq; int ch; @@ -93,6 +92,8 @@ struct bcm2835_desc { unsigned int frames; size_t size; + + bool cyclic; }; #define BCM2835_DMA_CS 0x00 @@ -377,8 +378,6 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); unsigned long flags; - c->cyclic = true; /* Nothing else is implemented */ - spin_lock_irqsave(&c->vc.lock, flags); if (vchan_issue_pending(&c->vc) && !c->desc) bcm2835_dma_start_desc(c); @@ -432,6 +431,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( d->c = c; d->dir = direction; d->frames = buf_len / period_len; + d->cyclic = true; d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); if (!d->cb_list) { -- GitLab From 92153bb534fa4c2f0a1fdc3745cab25edaf10dca Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:24:59 -0700 Subject: [PATCH 2865/9938] dmaengine: bcm2835: move controlblock chain generation into separate method In preparation of adding slave_sg functionality this patch moves the generation/allocation of bcm2835_desc and the building of the corresponding DMA-control-block chain from bcm2835_dma_prep_dma_cyclic into the newly created method bcm2835_dma_create_cb_chain. Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 294 +++++++++++++++++++++++++------------- 1 file changed, 198 insertions(+), 96 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index b3bc382fd199..4db0e232fab8 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -88,12 +88,12 @@ struct bcm2835_desc { struct virt_dma_desc vd; enum dma_transfer_direction dir; - struct bcm2835_cb_entry *cb_list; - unsigned int frames; size_t size; bool cyclic; + + struct bcm2835_cb_entry cb_list[]; }; #define BCM2835_DMA_CS 0x00 @@ -169,6 +169,13 @@ struct bcm2835_desc { #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) +/* how many frames of max_len size do we need to transfer len bytes */ +static inline size_t bcm2835_dma_frames_for_length(size_t len, + size_t max_len) +{ + return DIV_ROUND_UP(len, max_len); +} + static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) { return container_of(d, struct bcm2835_dmadev, ddev); @@ -185,19 +192,161 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc( return container_of(t, struct bcm2835_desc, vd.tx); } -static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) +static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) { - struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd); - int i; + size_t i; for (i = 0; i < desc->frames; i++) dma_pool_free(desc->c->cb_pool, desc->cb_list[i].cb, desc->cb_list[i].paddr); - kfree(desc->cb_list); kfree(desc); } +static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) +{ + bcm2835_dma_free_cb_chain( + container_of(vd, struct bcm2835_desc, vd)); +} + +static void bcm2835_dma_create_cb_set_length( + struct bcm2835_chan *chan, + struct bcm2835_dma_cb *control_block, + size_t len, + size_t period_len, + size_t *total_len, + u32 finalextrainfo) +{ + /* set the length */ + control_block->length = len; + + /* finished if we have no period_length */ + if (!period_len) + return; + + /* + * period_len means: that we need to generate + * transfers that are terminating at every + * multiple of period_len - this is typically + * used to set the interrupt flag in info + * which is required during cyclic transfers + */ + + /* have we filled in period_length yet? */ + if (*total_len + control_block->length < period_len) + return; + + /* calculate the length that remains to reach period_length */ + control_block->length = period_len - *total_len; + + /* reset total_length for next period */ + *total_len = 0; + + /* add extrainfo bits in info */ + control_block->info |= finalextrainfo; +} + +/** + * bcm2835_dma_create_cb_chain - create a control block and fills data in + * + * @chan: the @dma_chan for which we run this + * @direction: the direction in which we transfer + * @cyclic: it is a cyclic transfer + * @info: the default info bits to apply per controlblock + * @frames: number of controlblocks to allocate + * @src: the src address to assign (if the S_INC bit is set + * in @info, then it gets incremented) + * @dst: the dst address to assign (if the D_INC bit is set + * in @info, then it gets incremented) + * @buf_len: the full buffer length (may also be 0) + * @period_len: the period length when to apply @finalextrainfo + * in addition to the last transfer + * this will also break some control-blocks early + * @finalextrainfo: additional bits in last controlblock + * (or when period_len is reached in case of cyclic) + * @gfp: the GFP flag to use for allocation + */ +static struct bcm2835_desc *bcm2835_dma_create_cb_chain( + struct dma_chan *chan, enum dma_transfer_direction direction, + bool cyclic, u32 info, u32 finalextrainfo, size_t frames, + dma_addr_t src, dma_addr_t dst, size_t buf_len, + size_t period_len, gfp_t gfp) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + size_t len = buf_len, total_len; + size_t frame; + struct bcm2835_desc *d; + struct bcm2835_cb_entry *cb_entry; + struct bcm2835_dma_cb *control_block; + + /* allocate and setup the descriptor. */ + d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), + gfp); + if (!d) + return NULL; + + d->c = c; + d->dir = direction; + d->cyclic = cyclic; + + /* + * Iterate over all frames, create a control block + * for each frame and link them together. + */ + for (frame = 0, total_len = 0; frame < frames; d->frames++, frame++) { + cb_entry = &d->cb_list[frame]; + cb_entry->cb = dma_pool_alloc(c->cb_pool, gfp, + &cb_entry->paddr); + if (!cb_entry->cb) + goto error_cb; + + /* fill in the control block */ + control_block = cb_entry->cb; + control_block->info = info; + control_block->src = src; + control_block->dst = dst; + control_block->stride = 0; + control_block->next = 0; + /* set up length in control_block if requested */ + if (buf_len) { + /* calculate length honoring period_length */ + bcm2835_dma_create_cb_set_length( + c, control_block, + len, period_len, &total_len, + cyclic ? finalextrainfo : 0); + + /* calculate new remaining length */ + len -= control_block->length; + } + + /* link this the last controlblock */ + if (frame) + d->cb_list[frame - 1].cb->next = cb_entry->paddr; + + /* update src and dst and length */ + if (src && (info & BCM2835_DMA_S_INC)) + src += control_block->length; + if (dst && (info & BCM2835_DMA_D_INC)) + dst += control_block->length; + + /* Length of total transfer */ + d->size += control_block->length; + } + + /* the last frame requires extra flags */ + d->cb_list[d->frames - 1].cb->info |= finalextrainfo; + + /* detect a size missmatch */ + if (buf_len && (d->size != buf_len)) + goto error_cb; + + return d; +error_cb: + bcm2835_dma_free_cb_chain(d); + + return NULL; +} + static int bcm2835_dma_abort(void __iomem *chan_base) { unsigned long cs; @@ -391,12 +540,11 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( unsigned long flags) { struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); - enum dma_slave_buswidth dev_width; struct bcm2835_desc *d; - dma_addr_t dev_addr; - unsigned int es, sync_type; - unsigned int frame; - int i; + dma_addr_t src, dst; + u32 info = BCM2835_DMA_WAIT_RESP; + u32 extra = BCM2835_DMA_INT_EN; + size_t frames; /* Grab configuration */ if (!is_slave_direction(direction)) { @@ -404,104 +552,58 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( return NULL; } - if (direction == DMA_DEV_TO_MEM) { - dev_addr = c->cfg.src_addr; - dev_width = c->cfg.src_addr_width; - sync_type = BCM2835_DMA_S_DREQ; - } else { - dev_addr = c->cfg.dst_addr; - dev_width = c->cfg.dst_addr_width; - sync_type = BCM2835_DMA_D_DREQ; - } - - /* Bus width translates to the element size (ES) */ - switch (dev_width) { - case DMA_SLAVE_BUSWIDTH_4_BYTES: - es = BCM2835_DMA_DATA_TYPE_S32; - break; - default: + if (!buf_len) { + dev_err(chan->device->dev, + "%s: bad buffer length (= 0)\n", __func__); return NULL; } - /* Now allocate and setup the descriptor. */ - d = kzalloc(sizeof(*d), GFP_NOWAIT); - if (!d) - return NULL; + /* + * warn if buf_len is not a multiple of period_len - this may leed + * to unexpected latencies for interrupts and thus audiable clicks + */ + if (buf_len % period_len) + dev_warn_once(chan->device->dev, + "%s: buffer_length (%zd) is not a multiple of period_len (%zd)\n", + __func__, buf_len, period_len); - d->c = c; - d->dir = direction; - d->frames = buf_len / period_len; - d->cyclic = true; + /* Setup DREQ channel */ + if (c->dreq != 0) + info |= BCM2835_DMA_PER_MAP(c->dreq); - d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); - if (!d->cb_list) { - kfree(d); - return NULL; + if (direction == DMA_DEV_TO_MEM) { + if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) + return NULL; + src = c->cfg.src_addr; + dst = buf_addr; + info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; + } else { + if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) + return NULL; + dst = c->cfg.dst_addr; + src = buf_addr; + info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; } - /* Allocate memory for control blocks */ - for (i = 0; i < d->frames; i++) { - struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; - cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC, - &cb_entry->paddr); - if (!cb_entry->cb) - goto error_cb; - } + /* calculate number of frames */ + frames = DIV_ROUND_UP(buf_len, period_len); /* - * Iterate over all frames, create a control block - * for each frame and link them together. + * allocate the CB chain + * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine + * implementation calls prep_dma_cyclic with interrupts disabled. */ - for (frame = 0; frame < d->frames; frame++) { - struct bcm2835_dma_cb *control_block = d->cb_list[frame].cb; - - /* Setup adresses */ - if (d->dir == DMA_DEV_TO_MEM) { - control_block->info = BCM2835_DMA_D_INC; - control_block->src = dev_addr; - control_block->dst = buf_addr + frame * period_len; - } else { - control_block->info = BCM2835_DMA_S_INC; - control_block->src = buf_addr + frame * period_len; - control_block->dst = dev_addr; - } - - /* Enable interrupt */ - control_block->info |= BCM2835_DMA_INT_EN; - - /* Setup synchronization */ - if (sync_type != 0) - control_block->info |= sync_type; - - /* Setup DREQ channel */ - if (c->dreq != 0) - control_block->info |= - BCM2835_DMA_PER_MAP(c->dreq); - - /* Length of a frame */ - control_block->length = period_len; - d->size += control_block->length; + d = bcm2835_dma_create_cb_chain(chan, direction, true, + info, extra, + frames, src, dst, buf_len, + period_len, GFP_NOWAIT); + if (!d) + return NULL; - /* - * Next block is the next frame. - * This DMA engine driver currently only supports cyclic DMA. - * Therefore, wrap around at number of frames. - */ - control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr; - } + /* wrap around into a loop */ + d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr; return vchan_tx_prep(&c->vc, &d->vd, flags); -error_cb: - i--; - for (; i >= 0; i--) { - struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; - - dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr); - } - - kfree(d->cb_list); - kfree(d); - return NULL; } static int bcm2835_dma_slave_config(struct dma_chan *chan, -- GitLab From 4087412258276be37c5660fc6caf5d4e08920193 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:25:00 -0700 Subject: [PATCH 2866/9938] dmaengine: bcm2835: limit max length based on channel type The bcm2835 dma system has 2 basic types of dma-channels: * "normal" channels * "light" channels Lite channels are limited in several aspects: * internal data-structure is 128 bit (not 256) * does not support BCM2835_DMA_TDMODE (2D) * DMA length register is limited to 16 bit. so 0-65535 (not 0-65536 as mentioned in the official datasheet) * BCM2835_DMA_S/D_IGNORE are not supported The detection of the type of mode is implemented by looking at the LITE bit in the DEBUG register for each channel. This allows automatic detection. Based on this the maximum block size is set to (64K - 4) or to 1G and this limit is honored during generation of control block chains. The effect is that when a LITE channel is used more control blocks are used to do the same transfer (compared to a normal channel). As there are several sources/target DREQS that are 32 bit wide we need to have the transfer to be a multiple of 4 as this would break the transfer otherwise. This is why the limit of (64K - 4) was chosen over the alternative of (64K - 4K). Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 4db0e232fab8..59c5ef36d970 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -81,6 +81,8 @@ struct bcm2835_chan { void __iomem *chan_base; int irq_number; + + bool is_lite_channel; }; struct bcm2835_desc { @@ -169,6 +171,16 @@ struct bcm2835_desc { #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) +/* the max dma length for different channels */ +#define MAX_DMA_LEN SZ_1G +#define MAX_LITE_DMA_LEN (SZ_64K - 4) + +static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c) +{ + /* lite and normal channels have different max frame length */ + return c->is_lite_channel ? MAX_LITE_DMA_LEN : MAX_DMA_LEN; +} + /* how many frames of max_len size do we need to transfer len bytes */ static inline size_t bcm2835_dma_frames_for_length(size_t len, size_t max_len) @@ -217,8 +229,10 @@ static void bcm2835_dma_create_cb_set_length( size_t *total_len, u32 finalextrainfo) { - /* set the length */ - control_block->length = len; + size_t max_len = bcm2835_dma_max_frame_length(chan); + + /* set the length taking lite-channel limitations into account */ + control_block->length = min_t(u32, len, max_len); /* finished if we have no period_length */ if (!period_len) @@ -544,6 +558,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( dma_addr_t src, dst; u32 info = BCM2835_DMA_WAIT_RESP; u32 extra = BCM2835_DMA_INT_EN; + size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; /* Grab configuration */ @@ -586,7 +601,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( } /* calculate number of frames */ - frames = DIV_ROUND_UP(buf_len, period_len); + frames = /* number of periods */ + DIV_ROUND_UP(buf_len, period_len) * + /* number of frames per period */ + bcm2835_dma_frames_for_length(period_len, max_len); /* * allocate the CB chain @@ -685,6 +703,11 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) c->ch = chan_id; c->irq_number = irq; + /* check in DEBUG register if this is a LITE channel */ + if (readl(c->chan_base + BCM2835_DMA_DEBUG) & + BCM2835_DMA_DEBUG_LITE) + c->is_lite_channel = true; + return 0; } -- GitLab From 388cc7a281c06e484afcc3c5125b3271316209ef Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:25:01 -0700 Subject: [PATCH 2867/9938] dmaengine: bcm2835: add slave_sg support to bcm2835-dma Add slave_sg support to bcm2835-dma using shared allocation code for bcm2835_desc and DMA-control blocks already used by dma_cyclic. Note that bcm2835_dma_callback had to get modified to support both modes of operation (cyclic and non-cyclic). Tested using: * Hifiberry I2S card (using cyclic DMA) * fb_st7735r SPI-framebuffer (using slave_sg DMA via spi-bcm2835) playing BigBuckBunny for audio and video. Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 113 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 5 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 59c5ef36d970..b46b12f66f38 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -260,6 +260,23 @@ static void bcm2835_dma_create_cb_set_length( control_block->info |= finalextrainfo; } +static inline size_t bcm2835_dma_count_frames_for_sg( + struct bcm2835_chan *c, + struct scatterlist *sgl, + unsigned int sg_len) +{ + size_t frames = 0; + struct scatterlist *sgent; + unsigned int i; + size_t plength = bcm2835_dma_max_frame_length(c); + + for_each_sg(sgl, sgent, sg_len, i) + frames += bcm2835_dma_frames_for_length( + sg_dma_len(sgent), plength); + + return frames; +} + /** * bcm2835_dma_create_cb_chain - create a control block and fills data in * @@ -361,6 +378,32 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( return NULL; } +static void bcm2835_dma_fill_cb_chain_with_sg( + struct dma_chan *chan, + enum dma_transfer_direction direction, + struct bcm2835_cb_entry *cb, + struct scatterlist *sgl, + unsigned int sg_len) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + size_t max_len = bcm2835_dma_max_frame_length(c); + unsigned int i, len; + dma_addr_t addr; + struct scatterlist *sgent; + + for_each_sg(sgl, sgent, sg_len, i) { + for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent); + len > 0; + addr += cb->cb->length, len -= cb->cb->length, cb++) { + if (direction == DMA_DEV_TO_MEM) + cb->cb->dst = addr; + else + cb->cb->src = addr; + cb->cb->length = min(len, max_len); + } + } +} + static int bcm2835_dma_abort(void __iomem *chan_base) { unsigned long cs; @@ -428,13 +471,19 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) d = c->desc; if (d) { - /* TODO Only works for cyclic DMA */ - vchan_cyclic_callback(&d->vd); + if (d->cyclic) { + /* call the cyclic callback */ + vchan_cyclic_callback(&d->vd); + + /* Keep the DMA engine running */ + writel(BCM2835_DMA_ACTIVE, + c->chan_base + BCM2835_DMA_CS); + } else { + vchan_cookie_complete(&c->desc->vd); + bcm2835_dma_start_desc(c); + } } - /* Keep the DMA engine running */ - writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); - spin_unlock_irqrestore(&c->vc.lock, flags); return IRQ_HANDLED; @@ -548,6 +597,58 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) spin_unlock_irqrestore(&c->vc.lock, flags); } +static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( + struct dma_chan *chan, + struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + struct bcm2835_desc *d; + dma_addr_t src = 0, dst = 0; + u32 info = BCM2835_DMA_WAIT_RESP; + u32 extra = BCM2835_DMA_INT_EN; + size_t frames; + + if (!is_slave_direction(direction)) { + dev_err(chan->device->dev, + "%s: bad direction?\n", __func__); + return NULL; + } + + if (c->dreq != 0) + info |= BCM2835_DMA_PER_MAP(c->dreq); + + if (direction == DMA_DEV_TO_MEM) { + if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) + return NULL; + src = c->cfg.src_addr; + info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; + } else { + if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) + return NULL; + dst = c->cfg.dst_addr; + info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; + } + + /* count frames in sg list */ + frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len); + + /* allocate the CB chain */ + d = bcm2835_dma_create_cb_chain(chan, direction, false, + info, extra, + frames, src, dst, 0, 0, + GFP_KERNEL); + if (!d) + return NULL; + + /* fill in frames with scatterlist pointers */ + bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list, + sgl, sg_len); + + return vchan_tx_prep(&c->vc, &d->vd, flags); +} + static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, @@ -778,11 +879,13 @@ static int bcm2835_dma_probe(struct platform_device *pdev) dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; od->ddev.device_tx_status = bcm2835_dma_tx_status; od->ddev.device_issue_pending = bcm2835_dma_issue_pending; od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; + od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; od->ddev.device_config = bcm2835_dma_slave_config; od->ddev.device_terminate_all = bcm2835_dma_terminate_all; od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -- GitLab From d9f094a02f30510ec5d394c44d01d2ec187d7e45 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 16 Mar 2016 12:25:02 -0700 Subject: [PATCH 2868/9938] dmaengine: bcm2835: add dma_memcopy support to bcm2835-dma Also added check for an error condition in bcm2835_dma_create_cb_chain that showed up during development of this patch. Tested using dmatest for all enabled channels. Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index b46b12f66f38..cc771cd35dd0 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -310,6 +310,9 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( struct bcm2835_cb_entry *cb_entry; struct bcm2835_dma_cb *control_block; + if (!frames) + return NULL; + /* allocate and setup the descriptor. */ d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), gfp); @@ -597,6 +600,34 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) spin_unlock_irqrestore(&c->vc.lock, flags); } +struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( + struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, + size_t len, unsigned long flags) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + struct bcm2835_desc *d; + u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; + u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; + size_t max_len = bcm2835_dma_max_frame_length(c); + size_t frames; + + /* if src, dst or len is not given return with an error */ + if (!src || !dst || !len) + return NULL; + + /* calculate number of frames */ + frames = bcm2835_dma_frames_for_length(len, max_len); + + /* allocate the CB chain - this also fills in the pointers */ + d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false, + info, extra, frames, + src, dst, len, 0, GFP_KERNEL); + if (!d) + return NULL; + + return vchan_tx_prep(&c->vc, &d->vd, flags); +} + static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, @@ -880,17 +911,20 @@ static int bcm2835_dma_probe(struct platform_device *pdev) dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); + dma_cap_set(DMA_MEMCPY, od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; od->ddev.device_tx_status = bcm2835_dma_tx_status; od->ddev.device_issue_pending = bcm2835_dma_issue_pending; od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; + od->ddev.device_prep_dma_memcpy = bcm2835_dma_prep_dma_memcpy; od->ddev.device_config = bcm2835_dma_slave_config; od->ddev.device_terminate_all = bcm2835_dma_terminate_all; od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | + BIT(DMA_MEM_TO_MEM); od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; od->ddev.dev = &pdev->dev; INIT_LIST_HEAD(&od->ddev.channels); -- GitLab From 4f62568c1fcf0f7da49e7c22bdd01645aa508e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Tue, 12 Apr 2016 22:06:34 +0930 Subject: [PATCH 2869/9938] fujitsu-laptop: Support radio LED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lifebook E734/E744/E754 has a LED which the manual calls "radio components indicator". It should be lit when any radio transmitter is enabled. Its state can be read and set using ACPI (FUNC interface, RFKILL method). Since the Lifebook E734/E744/E754 only has a button (as compared to a slider) for enabling/disabling radio transmitters, I believe the LED in question is meant to indicate whether all radio transmitters are currently on or off. However, pressing the radio toggle button does not automatically change the hardware state of the transmitters: it looks like this machine relies on soft rfkill. As for detecting whether the LED is present on a given machine, I had to resort to educated guesswork. I assumed this LED is present on all devices which have a radio toggle button instead of a slider. My Lifebook E744 holds 0x01010001 in BTNI. By comparing the bits and buttons with those of a Lifebook E8420 (BTNI=0x000F0101, has a slider), I put my money on bit 24 as the indicator of the radio toggle button being present. Furthermore, bit 24 is also clear on the S7020 which does not have the toggle button or an RF LED. Figuring out how the LED is controlled was more deterministic as all it took was decompiling the DSDT and taking a look at method S000 (the RFKILL method of the FUNC interface). The LED control method implemented here is unsuitable for use with "heavy" LED triggers, like phy0rx. Once blinking frequency achieves a certain level, the system hangs. Signed-off-by: Michał Kępień [jwoithe: Comment on bit 24 in BTNI, expanded commit msg] Signed-off-by: Jonathan Woithe [dvhart: Minor style and commit log adjustments] Signed-off-by: Darren Hart --- drivers/platform/x86/fujitsu-laptop.c | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index ffc84cc7b1c7..1cb39d00d014 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -107,6 +107,7 @@ #define KEYBOARD_LAMPS 0x100 #define LOGOLAMP_POWERON 0x2000 #define LOGOLAMP_ALWAYS 0x4000 +#define RADIO_LED_ON 0x20 #endif /* Hotkey details */ @@ -174,6 +175,7 @@ struct fujitsu_hotkey_t { int rfkill_state; int logolamp_registered; int kblamps_registered; + int radio_led_registered; }; static struct fujitsu_hotkey_t *fujitsu_hotkey; @@ -200,6 +202,16 @@ static struct led_classdev kblamps_led = { .brightness_get = kblamps_get, .brightness_set = kblamps_set }; + +static enum led_brightness radio_led_get(struct led_classdev *cdev); +static void radio_led_set(struct led_classdev *cdev, + enum led_brightness brightness); + +static struct led_classdev radio_led = { + .name = "fujitsu::radio_led", + .brightness_get = radio_led_get, + .brightness_set = radio_led_set +}; #endif #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG @@ -275,6 +287,15 @@ static void kblamps_set(struct led_classdev *cdev, call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF); } +static void radio_led_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + if (brightness >= LED_FULL) + call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, RADIO_LED_ON); + else + call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0); +} + static enum led_brightness logolamp_get(struct led_classdev *cdev) { enum led_brightness brightness = LED_OFF; @@ -299,6 +320,16 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev) return brightness; } + +static enum led_brightness radio_led_get(struct led_classdev *cdev) +{ + enum led_brightness brightness = LED_OFF; + + if (call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0) & RADIO_LED_ON) + brightness = LED_FULL; + + return brightness; +} #endif /* Hardware access for LCD brightness control */ @@ -895,6 +926,23 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) result); } } + + /* + * BTNI bit 24 seems to indicate the presence of a radio toggle + * button in place of a slide switch, and all such machines appear + * to also have an RF LED. Therefore use bit 24 as an indicator + * that an RF LED is present. + */ + if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) { + result = led_classdev_register(&fujitsu->pf_device->dev, + &radio_led); + if (result == 0) { + fujitsu_hotkey->radio_led_registered = 1; + } else { + pr_err("Could not register LED handler for radio LED, error %i\n", + result); + } + } #endif return result; @@ -921,6 +969,9 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device) if (fujitsu_hotkey->kblamps_registered) led_classdev_unregister(&kblamps_led); + + if (fujitsu_hotkey->radio_led_registered) + led_classdev_unregister(&radio_led); #endif input_unregister_device(input); -- GitLab From 35b3fc8876ef927885f68e481efc049285d07e53 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 10 Apr 2016 18:15:15 +0800 Subject: [PATCH 2870/9938] gpio: brcmstb: Return proper error if bank width is invalid Return proper error in brcmstb_gpio_probe if bank width is invalid. Signed-off-by: Axel Lin Acked-by: Gregory Fong Signed-off-by: Linus Walleij --- drivers/gpio/gpio-brcmstb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 42d51c59ed50..e6489143721a 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -461,6 +461,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) bank->id = num_banks; if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) { dev_err(dev, "Invalid bank width %d\n", bank_width); + err = -EINVAL; goto fail; } else { bank->width = bank_width; -- GitLab From f5f7e45537e4ff534436c00d5671c1df84b0c390 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Thu, 14 Apr 2016 16:39:19 +0100 Subject: [PATCH 2871/9938] arm64: dts: juno: Add external expansion bus to DT The Juno development platform has an external expansion bus which can be used for additional hardware (e.g. LogicTile Express daughterboards). Add this bus to the Juno base device-tree. Acked-by: Liviu Dudau Signed-off-by: Brian Starkey Signed-off-by: Sudeep Holla --- arch/arm64/boot/dts/arm/juno-base.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index 68ccc39a7a66..dee2386d3b9b 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -272,3 +272,13 @@ /include/ "juno-motherboard.dtsi" }; + + site2: tlx@60000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x60000000 0x10000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0>; + interrupt-map = <0 0 &gic 0 0 0 168 IRQ_TYPE_LEVEL_HIGH>; + }; -- GitLab From 58bc67fc32b1c67fb045f4828a67134dc8fee631 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 10 Jul 2015 15:23:28 +0300 Subject: [PATCH 2872/9938] ARM: OMAP2+: gpmc: Add platform data Add a platform data structure for GPMC. It contains all the necessary platform information that needs to be passed from platform init code to GPMC driver. Signed-off-by: Roger Quadros Acked-by: Tony Lindgren --- include/linux/omap-gpmc.h | 3 +-- include/linux/platform_data/gpmc-omap.h | 30 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 include/linux/platform_data/gpmc-omap.h diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h index d833eb4dd446..45d9075be1e5 100644 --- a/include/linux/omap-gpmc.h +++ b/include/linux/omap-gpmc.h @@ -7,8 +7,7 @@ * option) any later version. */ -/* Maximum Number of Chip Selects */ -#define GPMC_CS_NUM 8 +#include #define GPMC_CONFIG_WP 0x00000005 diff --git a/include/linux/platform_data/gpmc-omap.h b/include/linux/platform_data/gpmc-omap.h new file mode 100644 index 000000000000..6804a8b387d7 --- /dev/null +++ b/include/linux/platform_data/gpmc-omap.h @@ -0,0 +1,30 @@ +/* + * OMAP GPMC Platform data + * + * Copyright (C) 2014 Texas Instruments, Inc. - http://www.ti.com + * Roger Quadros + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef _GPMC_OMAP_H_ +#define _GPMC_OMAP_H_ + +/* Maximum Number of Chip Selects */ +#define GPMC_CS_NUM 8 + +/* Data for each chip select */ +struct gpmc_omap_cs_data { + bool valid; /* data is valid */ + bool is_nand; /* device within this CS is NAND */ + struct platform_device *pdev; /* device within this CS region */ + unsigned int pdata_size; +}; + +struct gpmc_omap_platform_data { + struct gpmc_omap_cs_data cs[GPMC_CS_NUM]; +}; + +#endif /* _GPMC_OMAP_H */ -- GitLab From fabe7d7756d17f5da4bd80fa2373c4bd93ed39e5 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 10 Jul 2015 15:23:29 +0300 Subject: [PATCH 2873/9938] ARM: OMAP2+: gpmc: Add gpmc timings and settings to platform data Add device_timings, gpmc_timings and gpmc_setting to gpmc platform data. Signed-off-by: Roger Quadros Acked-by: Tony Lindgren --- include/linux/omap-gpmc.h | 139 ----------------------- include/linux/platform_data/gpmc-omap.h | 142 ++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 139 deletions(-) diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h index 45d9075be1e5..2dcef1c8c8d4 100644 --- a/include/linux/omap-gpmc.h +++ b/include/linux/omap-gpmc.h @@ -14,145 +14,6 @@ #define GPMC_IRQ_FIFOEVENTENABLE 0x01 #define GPMC_IRQ_COUNT_EVENT 0x02 -#define GPMC_BURST_4 4 /* 4 word burst */ -#define GPMC_BURST_8 8 /* 8 word burst */ -#define GPMC_BURST_16 16 /* 16 word burst */ -#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ -#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ -#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ -#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ - -/* bool type time settings */ -struct gpmc_bool_timings { - bool cycle2cyclediffcsen; - bool cycle2cyclesamecsen; - bool we_extra_delay; - bool oe_extra_delay; - bool adv_extra_delay; - bool cs_extra_delay; - bool time_para_granularity; -}; - -/* - * Note that all values in this struct are in nanoseconds except sync_clk - * (which is in picoseconds), while the register values are in gpmc_fck cycles. - */ -struct gpmc_timings { - /* Minimum clock period for synchronous mode (in picoseconds) */ - u32 sync_clk; - - /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ - u32 cs_on; /* Assertion time */ - u32 cs_rd_off; /* Read deassertion time */ - u32 cs_wr_off; /* Write deassertion time */ - - /* ADV signal timings corresponding to GPMC_CONFIG3 */ - u32 adv_on; /* Assertion time */ - u32 adv_rd_off; /* Read deassertion time */ - u32 adv_wr_off; /* Write deassertion time */ - u32 adv_aad_mux_on; /* ADV assertion time for AAD */ - u32 adv_aad_mux_rd_off; /* ADV read deassertion time for AAD */ - u32 adv_aad_mux_wr_off; /* ADV write deassertion time for AAD */ - - /* WE signals timings corresponding to GPMC_CONFIG4 */ - u32 we_on; /* WE assertion time */ - u32 we_off; /* WE deassertion time */ - - /* OE signals timings corresponding to GPMC_CONFIG4 */ - u32 oe_on; /* OE assertion time */ - u32 oe_off; /* OE deassertion time */ - u32 oe_aad_mux_on; /* OE assertion time for AAD */ - u32 oe_aad_mux_off; /* OE deassertion time for AAD */ - - /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ - u32 page_burst_access; /* Multiple access word delay */ - u32 access; /* Start-cycle to first data valid delay */ - u32 rd_cycle; /* Total read cycle time */ - u32 wr_cycle; /* Total write cycle time */ - - u32 bus_turnaround; - u32 cycle2cycle_delay; - - u32 wait_monitoring; - u32 clk_activation; - - /* The following are only on OMAP3430 */ - u32 wr_access; /* WRACCESSTIME */ - u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ - - struct gpmc_bool_timings bool_timings; -}; - -/* Device timings in picoseconds */ -struct gpmc_device_timings { - u32 t_ceasu; /* address setup to CS valid */ - u32 t_avdasu; /* address setup to ADV valid */ - /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is - * of tusb using these timings even for sync whilst - * ideally for adv_rd/(wr)_off it should have considered - * t_avdh instead. This indirectly necessitates r/w - * variations of t_avdp as it is possible to have one - * sync & other async - */ - u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ - u32 t_avdp_w; - u32 t_aavdh; /* address hold time */ - u32 t_oeasu; /* address setup to OE valid */ - u32 t_aa; /* access time from ADV assertion */ - u32 t_iaa; /* initial access time */ - u32 t_oe; /* access time from OE assertion */ - u32 t_ce; /* access time from CS asertion */ - u32 t_rd_cycle; /* read cycle time */ - u32 t_cez_r; /* read CS deassertion to high Z */ - u32 t_cez_w; /* write CS deassertion to high Z */ - u32 t_oez; /* OE deassertion to high Z */ - u32 t_weasu; /* address setup to WE valid */ - u32 t_wpl; /* write assertion time */ - u32 t_wph; /* write deassertion time */ - u32 t_wr_cycle; /* write cycle time */ - - u32 clk; - u32 t_bacc; /* burst access valid clock to output delay */ - u32 t_ces; /* CS setup time to clk */ - u32 t_avds; /* ADV setup time to clk */ - u32 t_avdh; /* ADV hold time from clk */ - u32 t_ach; /* address hold time from clk */ - u32 t_rdyo; /* clk to ready valid */ - - u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ - u32 t_ce_avd; /* CS on to ADV on delay */ - - /* XXX: check the possibility of combining - * cyc_aavhd_oe & cyc_aavdh_we - */ - u8 cyc_aavdh_oe;/* read address hold time in cycles */ - u8 cyc_aavdh_we;/* write address hold time in cycles */ - u8 cyc_oe; /* access time from OE assertion in cycles */ - u8 cyc_wpl; /* write deassertion time in cycles */ - u32 cyc_iaa; /* initial access time in cycles */ - - /* extra delays */ - bool ce_xdelay; - bool avd_xdelay; - bool oe_xdelay; - bool we_xdelay; -}; - -struct gpmc_settings { - bool burst_wrap; /* enables wrap bursting */ - bool burst_read; /* enables read page/burst mode */ - bool burst_write; /* enables write page/burst mode */ - bool device_nand; /* device is NAND */ - bool sync_read; /* enables synchronous reads */ - bool sync_write; /* enables synchronous writes */ - bool wait_on_read; /* monitor wait on reads */ - bool wait_on_write; /* monitor wait on writes */ - u32 burst_len; /* page/burst length */ - u32 device_width; /* device bus width (8 or 16 bit) */ - u32 mux_add_data; /* multiplex address & data */ - u32 wait_pin; /* wait-pin to be used */ -}; - extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, struct gpmc_settings *gpmc_s, struct gpmc_device_timings *dev_t); diff --git a/include/linux/platform_data/gpmc-omap.h b/include/linux/platform_data/gpmc-omap.h index 6804a8b387d7..67ccdb0e1606 100644 --- a/include/linux/platform_data/gpmc-omap.h +++ b/include/linux/platform_data/gpmc-omap.h @@ -15,10 +15,152 @@ /* Maximum Number of Chip Selects */ #define GPMC_CS_NUM 8 +/* bool type time settings */ +struct gpmc_bool_timings { + bool cycle2cyclediffcsen; + bool cycle2cyclesamecsen; + bool we_extra_delay; + bool oe_extra_delay; + bool adv_extra_delay; + bool cs_extra_delay; + bool time_para_granularity; +}; + +/* + * Note that all values in this struct are in nanoseconds except sync_clk + * (which is in picoseconds), while the register values are in gpmc_fck cycles. + */ +struct gpmc_timings { + /* Minimum clock period for synchronous mode (in picoseconds) */ + u32 sync_clk; + + /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ + u32 cs_on; /* Assertion time */ + u32 cs_rd_off; /* Read deassertion time */ + u32 cs_wr_off; /* Write deassertion time */ + + /* ADV signal timings corresponding to GPMC_CONFIG3 */ + u32 adv_on; /* Assertion time */ + u32 adv_rd_off; /* Read deassertion time */ + u32 adv_wr_off; /* Write deassertion time */ + u32 adv_aad_mux_on; /* ADV assertion time for AAD */ + u32 adv_aad_mux_rd_off; /* ADV read deassertion time for AAD */ + u32 adv_aad_mux_wr_off; /* ADV write deassertion time for AAD */ + + /* WE signals timings corresponding to GPMC_CONFIG4 */ + u32 we_on; /* WE assertion time */ + u32 we_off; /* WE deassertion time */ + + /* OE signals timings corresponding to GPMC_CONFIG4 */ + u32 oe_on; /* OE assertion time */ + u32 oe_off; /* OE deassertion time */ + u32 oe_aad_mux_on; /* OE assertion time for AAD */ + u32 oe_aad_mux_off; /* OE deassertion time for AAD */ + + /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ + u32 page_burst_access; /* Multiple access word delay */ + u32 access; /* Start-cycle to first data valid delay */ + u32 rd_cycle; /* Total read cycle time */ + u32 wr_cycle; /* Total write cycle time */ + + u32 bus_turnaround; + u32 cycle2cycle_delay; + + u32 wait_monitoring; + u32 clk_activation; + + /* The following are only on OMAP3430 */ + u32 wr_access; /* WRACCESSTIME */ + u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ + + struct gpmc_bool_timings bool_timings; +}; + +/* Device timings in picoseconds */ +struct gpmc_device_timings { + u32 t_ceasu; /* address setup to CS valid */ + u32 t_avdasu; /* address setup to ADV valid */ + /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is + * of tusb using these timings even for sync whilst + * ideally for adv_rd/(wr)_off it should have considered + * t_avdh instead. This indirectly necessitates r/w + * variations of t_avdp as it is possible to have one + * sync & other async + */ + u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ + u32 t_avdp_w; + u32 t_aavdh; /* address hold time */ + u32 t_oeasu; /* address setup to OE valid */ + u32 t_aa; /* access time from ADV assertion */ + u32 t_iaa; /* initial access time */ + u32 t_oe; /* access time from OE assertion */ + u32 t_ce; /* access time from CS asertion */ + u32 t_rd_cycle; /* read cycle time */ + u32 t_cez_r; /* read CS deassertion to high Z */ + u32 t_cez_w; /* write CS deassertion to high Z */ + u32 t_oez; /* OE deassertion to high Z */ + u32 t_weasu; /* address setup to WE valid */ + u32 t_wpl; /* write assertion time */ + u32 t_wph; /* write deassertion time */ + u32 t_wr_cycle; /* write cycle time */ + + u32 clk; + u32 t_bacc; /* burst access valid clock to output delay */ + u32 t_ces; /* CS setup time to clk */ + u32 t_avds; /* ADV setup time to clk */ + u32 t_avdh; /* ADV hold time from clk */ + u32 t_ach; /* address hold time from clk */ + u32 t_rdyo; /* clk to ready valid */ + + u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ + u32 t_ce_avd; /* CS on to ADV on delay */ + + /* XXX: check the possibility of combining + * cyc_aavhd_oe & cyc_aavdh_we + */ + u8 cyc_aavdh_oe;/* read address hold time in cycles */ + u8 cyc_aavdh_we;/* write address hold time in cycles */ + u8 cyc_oe; /* access time from OE assertion in cycles */ + u8 cyc_wpl; /* write deassertion time in cycles */ + u32 cyc_iaa; /* initial access time in cycles */ + + /* extra delays */ + bool ce_xdelay; + bool avd_xdelay; + bool oe_xdelay; + bool we_xdelay; +}; + +#define GPMC_BURST_4 4 /* 4 word burst */ +#define GPMC_BURST_8 8 /* 8 word burst */ +#define GPMC_BURST_16 16 /* 16 word burst */ +#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ +#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ +#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ +#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ + +struct gpmc_settings { + bool burst_wrap; /* enables wrap bursting */ + bool burst_read; /* enables read page/burst mode */ + bool burst_write; /* enables write page/burst mode */ + bool device_nand; /* device is NAND */ + bool sync_read; /* enables synchronous reads */ + bool sync_write; /* enables synchronous writes */ + bool wait_on_read; /* monitor wait on reads */ + bool wait_on_write; /* monitor wait on writes */ + u32 burst_len; /* page/burst length */ + u32 device_width; /* device bus width (8 or 16 bit) */ + u32 mux_add_data; /* multiplex address & data */ + u32 wait_pin; /* wait-pin to be used */ +}; + /* Data for each chip select */ struct gpmc_omap_cs_data { bool valid; /* data is valid */ bool is_nand; /* device within this CS is NAND */ + struct gpmc_settings *settings; + struct gpmc_device_timings *device_timings; + struct gpmc_timings *gpmc_timings; struct platform_device *pdev; /* device within this CS region */ unsigned int pdata_size; }; -- GitLab From f47fcad63f6847ea677c6c7030f30fd6438e0052 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 5 Aug 2015 13:58:01 +0300 Subject: [PATCH 2874/9938] memory: omap-gpmc: Introduce GPMC to NAND interface The OMAP GPMC module has certain registers dedicated for NAND access and some NAND bits mixed with other GPMC functionality. For the NAND dedicated registers we have the struct gpmc_nand_regs. The NAND driver needs to access NAND specific bits from the following non-dedicated registers - EMPTYWRITEBUFFERSTATUS from GPMC_STATUS For accessing these bits we introduce the struct gpmc_nand_ops. Add gpmc_omap_get_nand_ops() that returns the gpmc_nand_ops along with updating the gpmc_nand_regs. This API will be called by the OMAP NAND driver to access the necessary bits in GPMC register space. Signed-off-by: Roger Quadros Acked-by: Tony Lindgren --- drivers/memory/omap-gpmc.c | 21 +++++++++++++++++++++ include/linux/omap-gpmc.h | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 21825ddce4a3..0b62afd86f7e 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -1118,6 +1118,27 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) } } +static struct gpmc_nand_ops nand_ops; + +/** + * gpmc_omap_get_nand_ops - Get the GPMC NAND interface + * @regs: the GPMC NAND register map exclusive for NAND use. + * @cs: GPMC chip select number on which the NAND sits. The + * register map returned will be specific to this chip select. + * + * Returns NULL on error e.g. invalid cs. + */ +struct gpmc_nand_ops *gpmc_omap_get_nand_ops(struct gpmc_nand_regs *reg, int cs) +{ + if (cs >= gpmc_cs_num) + return NULL; + + gpmc_update_nand_reg(reg, cs); + + return &nand_ops; +} +EXPORT_SYMBOL_GPL(gpmc_omap_get_nand_ops); + int gpmc_get_client_irq(unsigned irq_config) { int i; diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h index 2dcef1c8c8d4..dc2ada6fb9b4 100644 --- a/include/linux/omap-gpmc.h +++ b/include/linux/omap-gpmc.h @@ -14,14 +14,45 @@ #define GPMC_IRQ_FIFOEVENTENABLE 0x01 #define GPMC_IRQ_COUNT_EVENT 0x02 +/** + * gpmc_nand_ops - Interface between NAND and GPMC + * @nand_write_buffer_empty: get the NAND write buffer empty status. + */ +struct gpmc_nand_ops { + bool (*nand_writebuffer_empty)(void); +}; + +struct gpmc_nand_regs; + +#if IS_ENABLED(CONFIG_OMAP_GPMC) +struct gpmc_nand_ops *gpmc_omap_get_nand_ops(struct gpmc_nand_regs *regs, + int cs); +#else +static inline gpmc_nand_ops *gpmc_omap_get_nand_ops(struct gpmc_nand_regs *regs, + int cs) +{ + return NULL; +} +#endif /* CONFIG_OMAP_GPMC */ + +/*--------------------------------*/ + +/* deprecated APIs */ +#if IS_ENABLED(CONFIG_OMAP_GPMC) +void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); +#else +static inline void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) +{ +} +#endif /* CONFIG_OMAP_GPMC */ +/*--------------------------------*/ + extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, struct gpmc_settings *gpmc_s, struct gpmc_device_timings *dev_t); -struct gpmc_nand_regs; struct device_node; -extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); extern int gpmc_get_client_irq(unsigned irq_config); extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); -- GitLab From 512d73d1c64f15da9cdcdcdfba3cd8db0d4d94cc Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 5 Aug 2015 13:34:50 +0300 Subject: [PATCH 2875/9938] memory: omap-gpmc: Add GPMC-NAND ops to get writebufferempty status This is needed by OMAP NAND driver to poll the empty status of the writebuffer. Signed-off-by: Roger Quadros Acked-by: Tony Lindgren --- drivers/memory/omap-gpmc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 0b62afd86f7e..90dfba5a8f55 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -81,6 +81,8 @@ #define GPMC_CONFIG_LIMITEDADDRESS BIT(1) +#define GPMC_STATUS_EMPTYWRITEBUFFERSTATUS BIT(0) + #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) @@ -1118,7 +1120,17 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) } } -static struct gpmc_nand_ops nand_ops; +static bool gpmc_nand_writebuffer_empty(void) +{ + if (gpmc_read_reg(GPMC_STATUS) & GPMC_STATUS_EMPTYWRITEBUFFERSTATUS) + return true; + + return false; +} + +static struct gpmc_nand_ops nand_ops = { + .nand_writebuffer_empty = gpmc_nand_writebuffer_empty, +}; /** * gpmc_omap_get_nand_ops - Get the GPMC NAND interface -- GitLab From 384258f252727c67772bbd48dad3185a30ba50d3 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 30 Jul 2015 14:49:23 +0300 Subject: [PATCH 2876/9938] memory: omap-gpmc: Implement IRQ domain for NAND IRQs GPMC provides 2 interrupts for NAND use. i.e. fifoevent and termcount. Use IRQ domain for this. NAND device tree node can then get the necessary interrupts by using gpmc as the interrupt parent. Legacy boot uses gpmc_get_client_irq to get the NAND interrupts from the GPMC IRQ domain. Get rid of custom bitmasks and use IRQ domain for that as well. Signed-off-by: Roger Quadros Acked-by: Rob Herring Acked-by: Tony Lindgren --- .../devicetree/bindings/bus/ti-gpmc.txt | 8 + drivers/memory/omap-gpmc.c | 246 ++++++++++-------- include/linux/omap-gpmc.h | 5 +- 3 files changed, 144 insertions(+), 115 deletions(-) diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/bus/ti-gpmc.txt index 01683707060b..13f13786f992 100644 --- a/Documentation/devicetree/bindings/bus/ti-gpmc.txt +++ b/Documentation/devicetree/bindings/bus/ti-gpmc.txt @@ -32,6 +32,12 @@ Required properties: bootloader) are used for the physical address decoding. As this will change in the future, filling correct values here is a requirement. + - interrupt-controller: The GPMC driver implements and interrupt controller for + the NAND events "fifoevent" and "termcount". + The interrupt number mapping is as follows + 0 - NAND_fifoevent + 1 - NAND_termcount + - interrupt-cells: Must be set to 2 Timing properties for child nodes. All are optional and default to 0. @@ -130,6 +136,8 @@ Example for an AM33xx board: #address-cells = <2>; #size-cells = <1>; ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */ + interrupt-controller; + #interrupt-cells = <2>; /* child nodes go here */ }; diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 90dfba5a8f55..e28d6bc2500a 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -127,7 +128,6 @@ #define GPMC_CONFIG_RDY_BSY 0x00000001 #define GPMC_CONFIG_DEV_SIZE 0x00000002 #define GPMC_CONFIG_DEV_TYPE 0x00000003 -#define GPMC_SET_IRQ_STATUS 0x00000004 #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) @@ -176,8 +176,6 @@ #define GPMC_CONFIG_WRITEPROTECT 0x00000010 #define WR_RD_PIN_MONITORING 0x00600000 -#define GPMC_ENABLE_IRQ 0x0000000d - /* ECC commands */ #define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ #define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ @@ -201,11 +199,6 @@ struct gpmc_cs_data { struct resource mem; }; -struct gpmc_client_irq { - unsigned irq; - u32 bitmask; -}; - /* Structure to save gpmc cs context */ struct gpmc_cs_config { u32 config1; @@ -233,9 +226,13 @@ struct omap3_gpmc_regs { struct gpmc_cs_config cs_context[GPMC_CS_NUM]; }; -static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; -static struct irq_chip gpmc_irq_chip; -static int gpmc_irq_start; +struct gpmc_device { + struct device *dev; + int irq; + struct irq_chip irq_chip; +}; + +static struct irq_domain *gpmc_irq_domain; static struct resource gpmc_mem_root; static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM]; @@ -243,8 +240,6 @@ static DEFINE_SPINLOCK(gpmc_mem_lock); /* Define chip-selects as reserved by default until probe completes */ static unsigned int gpmc_cs_num = GPMC_CS_NUM; static unsigned int gpmc_nr_waitpins; -static struct device *gpmc_dev; -static int gpmc_irq; static resource_size_t phys_base, mem_size; static unsigned gpmc_capability; static void __iomem *gpmc_base; @@ -1056,14 +1051,6 @@ int gpmc_configure(int cmd, int wval) u32 regval; switch (cmd) { - case GPMC_ENABLE_IRQ: - gpmc_write_reg(GPMC_IRQENABLE, wval); - break; - - case GPMC_SET_IRQ_STATUS: - gpmc_write_reg(GPMC_IRQSTATUS, wval); - break; - case GPMC_CONFIG_WP: regval = gpmc_read_reg(GPMC_CONFIG); if (wval) @@ -1153,85 +1140,97 @@ EXPORT_SYMBOL_GPL(gpmc_omap_get_nand_ops); int gpmc_get_client_irq(unsigned irq_config) { - int i; - - if (hweight32(irq_config) > 1) + if (!gpmc_irq_domain) { + pr_warn("%s called before GPMC IRQ domain available\n", + __func__); return 0; + } - for (i = 0; i < GPMC_NR_IRQ; i++) - if (gpmc_client_irq[i].bitmask & irq_config) - return gpmc_client_irq[i].irq; + if (irq_config >= GPMC_NR_IRQ) + return 0; - return 0; + return irq_create_mapping(gpmc_irq_domain, irq_config); } -static int gpmc_irq_endis(unsigned irq, bool endis) +static int gpmc_irq_endis(unsigned long hwirq, bool endis) { - int i; u32 regval; - for (i = 0; i < GPMC_NR_IRQ; i++) - if (irq == gpmc_client_irq[i].irq) { - regval = gpmc_read_reg(GPMC_IRQENABLE); - if (endis) - regval |= gpmc_client_irq[i].bitmask; - else - regval &= ~gpmc_client_irq[i].bitmask; - gpmc_write_reg(GPMC_IRQENABLE, regval); - break; - } + regval = gpmc_read_reg(GPMC_IRQENABLE); + if (endis) + regval |= BIT(hwirq); + else + regval &= ~BIT(hwirq); + gpmc_write_reg(GPMC_IRQENABLE, regval); return 0; } static void gpmc_irq_disable(struct irq_data *p) { - gpmc_irq_endis(p->irq, false); + gpmc_irq_endis(p->hwirq, false); } static void gpmc_irq_enable(struct irq_data *p) { - gpmc_irq_endis(p->irq, true); + gpmc_irq_endis(p->hwirq, true); } static void gpmc_irq_noop(struct irq_data *data) { } static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } -static int gpmc_setup_irq(void) +static int gpmc_irq_map(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw) { - int i; + struct gpmc_device *gpmc = d->host_data; + + irq_set_chip_data(virq, gpmc); + irq_set_chip_and_handler(virq, &gpmc->irq_chip, handle_simple_irq); + irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOAUTOEN); + + return 0; +} + +static const struct irq_domain_ops gpmc_irq_domain_ops = { + .map = gpmc_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + +static irqreturn_t gpmc_handle_irq(int irq, void *data) +{ + int hwirq, virq; u32 regval; + struct gpmc_device *gpmc = data; - if (!gpmc_irq) - return -EINVAL; + regval = gpmc_read_reg(GPMC_IRQSTATUS); - gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0); - if (gpmc_irq_start < 0) { - pr_err("irq_alloc_descs failed\n"); - return gpmc_irq_start; - } + if (!regval) + return IRQ_NONE; - gpmc_irq_chip.name = "gpmc"; - gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret; - gpmc_irq_chip.irq_enable = gpmc_irq_enable; - gpmc_irq_chip.irq_disable = gpmc_irq_disable; - gpmc_irq_chip.irq_shutdown = gpmc_irq_noop; - gpmc_irq_chip.irq_ack = gpmc_irq_noop; - gpmc_irq_chip.irq_mask = gpmc_irq_noop; - gpmc_irq_chip.irq_unmask = gpmc_irq_noop; - - gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE; - gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT; - - for (i = 0; i < GPMC_NR_IRQ; i++) { - gpmc_client_irq[i].irq = gpmc_irq_start + i; - irq_set_chip_and_handler(gpmc_client_irq[i].irq, - &gpmc_irq_chip, handle_simple_irq); - irq_modify_status(gpmc_client_irq[i].irq, IRQ_NOREQUEST, - IRQ_NOAUTOEN); + for (hwirq = 0; hwirq < GPMC_NR_IRQ; hwirq++) { + if (regval & BIT(hwirq)) { + virq = irq_find_mapping(gpmc_irq_domain, hwirq); + if (!virq) { + dev_warn(gpmc->dev, + "spurious irq detected hwirq %d, virq %d\n", + hwirq, virq); + } + + generic_handle_irq(virq); + } } + gpmc_write_reg(GPMC_IRQSTATUS, regval); + + return IRQ_HANDLED; +} + +static int gpmc_setup_irq(struct gpmc_device *gpmc) +{ + u32 regval; + int rc; + /* Disable interrupts */ gpmc_write_reg(GPMC_IRQENABLE, 0); @@ -1239,22 +1238,46 @@ static int gpmc_setup_irq(void) regval = gpmc_read_reg(GPMC_IRQSTATUS); gpmc_write_reg(GPMC_IRQSTATUS, regval); - return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL); + gpmc->irq_chip.name = "gpmc"; + gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret; + gpmc->irq_chip.irq_enable = gpmc_irq_enable; + gpmc->irq_chip.irq_disable = gpmc_irq_disable; + gpmc->irq_chip.irq_shutdown = gpmc_irq_noop; + gpmc->irq_chip.irq_ack = gpmc_irq_noop; + gpmc->irq_chip.irq_mask = gpmc_irq_noop; + gpmc->irq_chip.irq_unmask = gpmc_irq_noop; + + gpmc_irq_domain = irq_domain_add_linear(gpmc->dev->of_node, + GPMC_NR_IRQ, + &gpmc_irq_domain_ops, + gpmc); + if (!gpmc_irq_domain) { + dev_err(gpmc->dev, "IRQ domain add failed\n"); + return -ENODEV; + } + + rc = request_irq(gpmc->irq, gpmc_handle_irq, 0, "gpmc", gpmc); + if (rc) { + dev_err(gpmc->dev, "failed to request irq %d: %d\n", + gpmc->irq, rc); + irq_domain_remove(gpmc_irq_domain); + gpmc_irq_domain = NULL; + } + + return rc; } -static int gpmc_free_irq(void) +static int gpmc_free_irq(struct gpmc_device *gpmc) { - int i; + int hwirq; - if (gpmc_irq) - free_irq(gpmc_irq, NULL); + free_irq(gpmc->irq, gpmc); - for (i = 0; i < GPMC_NR_IRQ; i++) { - irq_set_handler(gpmc_client_irq[i].irq, NULL); - irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip); - } + for (hwirq = 0; hwirq < GPMC_NR_IRQ; hwirq++) + irq_dispose_mapping(irq_find_mapping(gpmc_irq_domain, hwirq)); - irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ); + irq_domain_remove(gpmc_irq_domain); + gpmc_irq_domain = NULL; return 0; } @@ -2154,6 +2177,14 @@ static int gpmc_probe(struct platform_device *pdev) int rc; u32 l; struct resource *res; + struct gpmc_device *gpmc; + + gpmc = devm_kzalloc(&pdev->dev, sizeof(*gpmc), GFP_KERNEL); + if (!gpmc) + return -ENOMEM; + + gpmc->dev = &pdev->dev; + platform_set_drvdata(pdev, gpmc); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) @@ -2167,15 +2198,16 @@ static int gpmc_probe(struct platform_device *pdev) return PTR_ERR(gpmc_base); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) - dev_warn(&pdev->dev, "Failed to get resource: irq\n"); - else - gpmc_irq = res->start; + if (!res) { + dev_err(&pdev->dev, "Failed to get resource: irq\n"); + return -ENOENT; + } + + gpmc->irq = res->start; gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck"); if (IS_ERR(gpmc_l3_clk)) { dev_err(&pdev->dev, "Failed to get GPMC fck\n"); - gpmc_irq = 0; return PTR_ERR(gpmc_l3_clk); } @@ -2187,8 +2219,6 @@ static int gpmc_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - gpmc_dev = &pdev->dev; - l = gpmc_read_reg(GPMC_REVISION); /* @@ -2207,13 +2237,16 @@ static int gpmc_probe(struct platform_device *pdev) gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; if (GPMC_REVISION_MAJOR(l) > 0x5) gpmc_capability |= GPMC_HAS_MUX_AAD; - dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), + dev_info(gpmc->dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), GPMC_REVISION_MINOR(l)); gpmc_mem_init(); - if (gpmc_setup_irq() < 0) - dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); + rc = gpmc_setup_irq(gpmc); + if (rc) { + dev_err(gpmc->dev, "gpmc_setup_irq failed\n"); + goto fail; + } if (!pdev->dev.of_node) { gpmc_cs_num = GPMC_CS_NUM; @@ -2222,21 +2255,27 @@ static int gpmc_probe(struct platform_device *pdev) rc = gpmc_probe_dt(pdev); if (rc < 0) { - pm_runtime_put_sync(&pdev->dev); - dev_err(gpmc_dev, "failed to probe DT parameters\n"); - return rc; + dev_err(gpmc->dev, "failed to probe DT parameters\n"); + gpmc_free_irq(gpmc); + goto fail; } return 0; + +fail: + pm_runtime_put_sync(&pdev->dev); + return rc; } static int gpmc_remove(struct platform_device *pdev) { - gpmc_free_irq(); + struct gpmc_device *gpmc = platform_get_drvdata(pdev); + + gpmc_free_irq(gpmc); gpmc_mem_exit(); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - gpmc_dev = NULL; + return 0; } @@ -2282,25 +2321,6 @@ static __exit void gpmc_exit(void) postcore_initcall(gpmc_init); module_exit(gpmc_exit); -static irqreturn_t gpmc_handle_irq(int irq, void *dev) -{ - int i; - u32 regval; - - regval = gpmc_read_reg(GPMC_IRQSTATUS); - - if (!regval) - return IRQ_NONE; - - for (i = 0; i < GPMC_NR_IRQ; i++) - if (regval & gpmc_client_irq[i].bitmask) - generic_handle_irq(gpmc_client_irq[i].irq); - - gpmc_write_reg(GPMC_IRQSTATUS, regval); - - return IRQ_HANDLED; -} - static struct omap3_gpmc_regs gpmc_context; void omap3_gpmc_save_context(void) diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h index dc2ada6fb9b4..9e9d79e8efa5 100644 --- a/include/linux/omap-gpmc.h +++ b/include/linux/omap-gpmc.h @@ -11,8 +11,9 @@ #define GPMC_CONFIG_WP 0x00000005 -#define GPMC_IRQ_FIFOEVENTENABLE 0x01 -#define GPMC_IRQ_COUNT_EVENT 0x02 +/* IRQ numbers in GPMC IRQ domain for legacy boot use */ +#define GPMC_IRQ_FIFOEVENTENABLE 0 +#define GPMC_IRQ_COUNT_EVENT 1 /** * gpmc_nand_ops - Interface between NAND and GPMC -- GitLab From c509aefd75d026f4ef4aa306131d7a780c2eda7b Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 5 Aug 2015 14:01:50 +0300 Subject: [PATCH 2877/9938] mtd: nand: omap: Use gpmc_omap_get_nand_ops() to get NAND registers Deprecate nand register passing via platform data and use gpmc_omap_get_nand_ops() instead. Signed-off-by: Roger Quadros Acked-by: Brian Norris Acked-by: Tony Lindgren --- arch/arm/mach-omap2/gpmc-nand.c | 2 -- drivers/mtd/nand/omap2.c | 9 ++++++++- include/linux/platform_data/mtd-nand-omap2.h | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 72918c4973ea..04e6998c1529 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -121,8 +121,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, if (err < 0) goto out_free_cs; - gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); - if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) { pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n"); err = -EINVAL; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 0749ca1a1456..cba9bf0adba1 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -28,6 +28,7 @@ #include #include +#include #include #define DRIVER_NAME "omap2-nand" @@ -168,7 +169,9 @@ struct omap_nand_info { } iomode; u_char *buf; int buf_len; + /* Interface to GPMC */ struct gpmc_nand_regs reg; + struct gpmc_nand_ops *ops; /* generated at runtime depending on ECC algorithm and layout selected */ struct nand_ecclayout oobinfo; /* fields specific for BCHx_HW ECC scheme */ @@ -1665,9 +1668,13 @@ static int omap_nand_probe(struct platform_device *pdev) platform_set_drvdata(pdev, info); + info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs); + if (!info->ops) { + dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n"); + return -ENODEV; + } info->pdev = pdev; info->gpmc_cs = pdata->cs; - info->reg = pdata->reg; info->of_node = pdata->of_node; info->ecc_opt = pdata->ecc_opt; nand_chip = &info->nand; diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 090bbab0130a..a067f581e938 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -75,10 +75,12 @@ struct omap_nand_platform_data { enum nand_io xfer_type; int devsize; enum omap_ecc ecc_opt; - struct gpmc_nand_regs reg; /* for passing the partitions */ struct device_node *of_node; struct device_node *elm_of_node; + + /* deprecated */ + struct gpmc_nand_regs reg; }; #endif -- GitLab From d6e552168db59d627fd56074f2c588df1faf0c95 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 5 Aug 2015 13:36:43 +0300 Subject: [PATCH 2878/9938] mtd: nand: omap: Switch to using GPMC-NAND ops for writebuffer empty check Instead of accessing the gpmc_status register directly start using the gpmc_nand_ops->nand_writebuffer_empty() helper to check write buffer empty status. Signed-off-by: Roger Quadros Acked-by: Brian Norris Acked-by: Tony Lindgren --- drivers/mtd/nand/omap2.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index cba9bf0adba1..98023d5bfc35 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -291,14 +291,13 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) { struct omap_nand_info *info = mtd_to_omap(mtd); u_char *p = (u_char *)buf; - u32 status = 0; + bool status; while (len--) { iowrite8(*p++, info->nand.IO_ADDR_W); /* wait until buffer is available for write */ do { - status = readl(info->reg.gpmc_status) & - STATUS_BUFF_EMPTY; + status = info->ops->nand_writebuffer_empty(); } while (!status); } } @@ -326,7 +325,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) { struct omap_nand_info *info = mtd_to_omap(mtd); u16 *p = (u16 *) buf; - u32 status = 0; + bool status; /* FIXME try bursts of writesw() or DMA ... */ len >>= 1; @@ -334,8 +333,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) iowrite16(*p++, info->nand.IO_ADDR_W); /* wait until buffer is available for write */ do { - status = readl(info->reg.gpmc_status) & - STATUS_BUFF_EMPTY; + status = info->ops->nand_writebuffer_empty(); } while (!status); } } -- GitLab From 01b95fc6b299b99075b8980371fc19b980236c32 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 20 May 2014 22:29:28 +0300 Subject: [PATCH 2879/9938] mtd: nand: omap: Copy platform data parameters to omap_nand_info data Copy all the platform data parameters to the driver's local data structure 'omap_nand_info' and use it in the entire driver. This will make it easer for device tree migration. Signed-off-by: Roger Quadros Acked-by: Brian Norris Acked-by: Tony Lindgren --- drivers/mtd/nand/omap2.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 98023d5bfc35..7e4e263c7d9c 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -152,13 +152,17 @@ static struct nand_hw_control omap_gpmc_controller = { }; struct omap_nand_info { - struct omap_nand_platform_data *pdata; struct nand_chip nand; struct platform_device *pdev; int gpmc_cs; - unsigned long phys_base; + bool dev_ready; + enum nand_io xfer_type; + int devsize; enum omap_ecc ecc_opt; + struct device_node *elm_of_node; + + unsigned long phys_base; struct completion comp; struct dma_chan *dma; int gpmc_irq_fifo; @@ -1631,7 +1635,7 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info, "CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); return false; } - if (ecc_needs_elm && !is_elm_present(info, pdata->elm_of_node)) { + if (ecc_needs_elm && !is_elm_present(info, info->elm_of_node)) { dev_err(&info->pdev->dev, "ELM not available\n"); return false; } @@ -1675,6 +1679,11 @@ static int omap_nand_probe(struct platform_device *pdev) info->gpmc_cs = pdata->cs; info->of_node = pdata->of_node; info->ecc_opt = pdata->ecc_opt; + info->dev_ready = pdata->dev_ready; + info->xfer_type = pdata->xfer_type; + info->devsize = pdata->devsize; + info->elm_of_node = pdata->elm_of_node; + nand_chip = &info->nand; mtd = nand_to_mtd(nand_chip); mtd->dev.parent = &pdev->dev; @@ -1700,7 +1709,7 @@ static int omap_nand_probe(struct platform_device *pdev) * chip delay which is slightly more than tR (AC Timing) of the NAND * device and read status register until you get a failure or success */ - if (pdata->dev_ready) { + if (info->dev_ready) { nand_chip->dev_ready = omap_dev_ready; nand_chip->chip_delay = 0; } else { @@ -1714,15 +1723,16 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->options |= NAND_SKIP_BBTSCAN; /* scan NAND device connected to chip controller */ - nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16; + nand_chip->options |= info->devsize & NAND_BUSWIDTH_16; if (nand_scan_ident(mtd, 1, NULL)) { - dev_err(&info->pdev->dev, "scan failed, may be bus-width mismatch\n"); + dev_err(&info->pdev->dev, + "scan failed, may be bus-width mismatch\n"); err = -ENXIO; goto return_error; } /* re-populate low-level callbacks based on xfer modes */ - switch (pdata->xfer_type) { + switch (info->xfer_type) { case NAND_OMAP_PREFETCH_POLLED: nand_chip->read_buf = omap_read_buf_pref; nand_chip->write_buf = omap_write_buf_pref; @@ -1802,7 +1812,7 @@ static int omap_nand_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, - "xfer_type(%d) not supported!\n", pdata->xfer_type); + "xfer_type(%d) not supported!\n", info->xfer_type); err = -EINVAL; goto return_error; } -- GitLab From c9711ec5250b22fd94e9b34c17c095e001a90e66 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 21 May 2014 07:29:03 +0300 Subject: [PATCH 2880/9938] mtd: nand: omap: Clean up device tree support Move NAND specific device tree parsing to NAND driver. The NAND controller node must have a compatible id, register space resource and interrupt resource. Signed-off-by: Roger Quadros Acked-by: Brian Norris Acked-by: Tony Lindgren --- arch/arm/mach-omap2/gpmc-nand.c | 5 +- drivers/memory/omap-gpmc.c | 143 +++++-------------- drivers/mtd/nand/omap2.c | 134 ++++++++++++++--- include/linux/platform_data/mtd-nand-omap2.h | 3 +- 4 files changed, 153 insertions(+), 132 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 04e6998c1529..f6ac027f3c3b 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -97,10 +97,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); memset(&s, 0, sizeof(struct gpmc_settings)); - if (gpmc_nand_data->of_node) - gpmc_read_settings_dt(gpmc_nand_data->of_node, &s); - else - gpmc_set_legacy(gpmc_nand_data, &s); + gpmc_set_legacy(gpmc_nand_data, &s); s.device_nand = true; diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index e28d6bc2500a..8dc6e3b1c44a 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -1852,105 +1851,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, of_property_read_bool(np, "gpmc,time-para-granularity"); } -#if IS_ENABLED(CONFIG_MTD_NAND) - -static const char * const nand_xfer_types[] = { - [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", - [NAND_OMAP_POLLED] = "polled", - [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma", - [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq", -}; - -static int gpmc_probe_nand_child(struct platform_device *pdev, - struct device_node *child) -{ - u32 val; - const char *s; - struct gpmc_timings gpmc_t; - struct omap_nand_platform_data *gpmc_nand_data; - - if (of_property_read_u32(child, "reg", &val) < 0) { - dev_err(&pdev->dev, "%s has no 'reg' property\n", - child->full_name); - return -ENODEV; - } - - gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data), - GFP_KERNEL); - if (!gpmc_nand_data) - return -ENOMEM; - - gpmc_nand_data->cs = val; - gpmc_nand_data->of_node = child; - - /* Detect availability of ELM module */ - gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0); - if (gpmc_nand_data->elm_of_node == NULL) - gpmc_nand_data->elm_of_node = - of_parse_phandle(child, "elm_id", 0); - - /* select ecc-scheme for NAND */ - if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { - pr_err("%s: ti,nand-ecc-opt not found\n", __func__); - return -ENODEV; - } - - if (!strcmp(s, "sw")) - gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW; - else if (!strcmp(s, "ham1") || - !strcmp(s, "hw") || !strcmp(s, "hw-romcode")) - gpmc_nand_data->ecc_opt = - OMAP_ECC_HAM1_CODE_HW; - else if (!strcmp(s, "bch4")) - if (gpmc_nand_data->elm_of_node) - gpmc_nand_data->ecc_opt = - OMAP_ECC_BCH4_CODE_HW; - else - gpmc_nand_data->ecc_opt = - OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; - else if (!strcmp(s, "bch8")) - if (gpmc_nand_data->elm_of_node) - gpmc_nand_data->ecc_opt = - OMAP_ECC_BCH8_CODE_HW; - else - gpmc_nand_data->ecc_opt = - OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; - else if (!strcmp(s, "bch16")) - if (gpmc_nand_data->elm_of_node) - gpmc_nand_data->ecc_opt = - OMAP_ECC_BCH16_CODE_HW; - else - pr_err("%s: BCH16 requires ELM support\n", __func__); - else - pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__); - - /* select data transfer mode for NAND controller */ - if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) - for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) - if (!strcasecmp(s, nand_xfer_types[val])) { - gpmc_nand_data->xfer_type = val; - break; - } - - gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child); - - val = of_get_nand_bus_width(child); - if (val == 16) - gpmc_nand_data->devsize = NAND_BUSWIDTH_16; - - gpmc_read_timings_dt(child, &gpmc_t); - gpmc_nand_init(gpmc_nand_data, &gpmc_t); - - return 0; -} -#else -static int gpmc_probe_nand_child(struct platform_device *pdev, - struct device_node *child) -{ - return 0; -} -#endif - #if IS_ENABLED(CONFIG_MTD_ONENAND) static int gpmc_probe_onenand_child(struct platform_device *pdev, struct device_node *child) @@ -2069,9 +1969,42 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, goto err; } - ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width); - if (ret < 0) - goto err; + if (of_node_cmp(child->name, "nand") == 0) { + /* Warn about older DT blobs with no compatible property */ + if (!of_property_read_bool(child, "compatible")) { + dev_warn(&pdev->dev, + "Incompatible NAND node: missing compatible"); + ret = -EINVAL; + goto err; + } + } + + if (of_device_is_compatible(child, "ti,omap2-nand")) { + /* NAND specific setup */ + val = of_get_nand_bus_width(child); + switch (val) { + case 8: + gpmc_s.device_width = GPMC_DEVWIDTH_8BIT; + break; + case 16: + gpmc_s.device_width = GPMC_DEVWIDTH_16BIT; + break; + default: + dev_err(&pdev->dev, "%s: invalid 'nand-bus-width'\n", + child->name); + ret = -EINVAL; + goto err; + } + + /* disable write protect */ + gpmc_configure(GPMC_CONFIG_WP, 0); + gpmc_s.device_nand = true; + } else { + ret = of_property_read_u32(child, "bank-width", + &gpmc_s.device_width); + if (ret < 0) + goto err; + } gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings"); ret = gpmc_cs_program_settings(cs, &gpmc_s); @@ -2155,9 +2088,7 @@ static int gpmc_probe_dt(struct platform_device *pdev) if (!child->name) continue; - if (of_node_cmp(child->name, "nand") == 0) - ret = gpmc_probe_nand_child(pdev, child); - else if (of_node_cmp(child->name, "onenand") == 0) + if (of_node_cmp(child->name, "onenand") == 0) ret = gpmc_probe_onenand_child(pdev, child); else ret = gpmc_probe_generic_child(pdev, child); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 7e4e263c7d9c..35b8f3359c17 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -176,11 +177,11 @@ struct omap_nand_info { /* Interface to GPMC */ struct gpmc_nand_regs reg; struct gpmc_nand_ops *ops; + bool flash_bbt; /* generated at runtime depending on ECC algorithm and layout selected */ struct nand_ecclayout oobinfo; /* fields specific for BCHx_HW ECC scheme */ struct device *elm_dev; - struct device_node *of_node; }; static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) @@ -1643,10 +1644,86 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info, return true; } +static const char * const nand_xfer_types[] = { + [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", + [NAND_OMAP_POLLED] = "polled", + [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma", + [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq", +}; + +static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info) +{ + struct device_node *child = dev->of_node; + int i; + const char *s; + u32 cs; + + if (of_property_read_u32(child, "reg", &cs) < 0) { + dev_err(dev, "reg not found in DT\n"); + return -EINVAL; + } + + info->gpmc_cs = cs; + + /* detect availability of ELM module. Won't be present pre-OMAP4 */ + info->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0); + if (!info->elm_of_node) + dev_dbg(dev, "ti,elm-id not in DT\n"); + + /* select ecc-scheme for NAND */ + if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { + dev_err(dev, "ti,nand-ecc-opt not found\n"); + return -EINVAL; + } + + if (!strcmp(s, "sw")) { + info->ecc_opt = OMAP_ECC_HAM1_CODE_SW; + } else if (!strcmp(s, "ham1") || + !strcmp(s, "hw") || !strcmp(s, "hw-romcode")) { + info->ecc_opt = OMAP_ECC_HAM1_CODE_HW; + } else if (!strcmp(s, "bch4")) { + if (info->elm_of_node) + info->ecc_opt = OMAP_ECC_BCH4_CODE_HW; + else + info->ecc_opt = OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; + } else if (!strcmp(s, "bch8")) { + if (info->elm_of_node) + info->ecc_opt = OMAP_ECC_BCH8_CODE_HW; + else + info->ecc_opt = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; + } else if (!strcmp(s, "bch16")) { + info->ecc_opt = OMAP_ECC_BCH16_CODE_HW; + } else { + dev_err(dev, "unrecognized value for ti,nand-ecc-opt\n"); + return -EINVAL; + } + + /* select data transfer mode */ + if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) { + for (i = 0; i < ARRAY_SIZE(nand_xfer_types); i++) { + if (!strcasecmp(s, nand_xfer_types[i])) { + info->xfer_type = i; + goto next; + } + } + + dev_err(dev, "unrecognized value for ti,nand-xfer-type\n"); + return -EINVAL; + } + +next: + of_get_nand_on_flash_bbt(child); + + if (of_get_nand_bus_width(child) == 16) + info->devsize = NAND_BUSWIDTH_16; + + return 0; +} + static int omap_nand_probe(struct platform_device *pdev) { struct omap_nand_info *info; - struct omap_nand_platform_data *pdata; + struct omap_nand_platform_data *pdata = NULL; struct mtd_info *mtd; struct nand_chip *nand_chip; struct nand_ecclayout *ecclayout; @@ -1656,39 +1733,47 @@ static int omap_nand_probe(struct platform_device *pdev) unsigned sig; unsigned oob_index; struct resource *res; - - pdata = dev_get_platdata(&pdev->dev); - if (pdata == NULL) { - dev_err(&pdev->dev, "platform data missing\n"); - return -ENODEV; - } + struct device *dev = &pdev->dev; info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info), GFP_KERNEL); if (!info) return -ENOMEM; - platform_set_drvdata(pdev, info); + info->pdev = pdev; + if (dev->of_node) { + if (omap_get_dt_info(dev, info)) + return -EINVAL; + } else { + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + dev_err(&pdev->dev, "platform data missing\n"); + return -EINVAL; + } + + info->gpmc_cs = pdata->cs; + info->reg = pdata->reg; + info->ecc_opt = pdata->ecc_opt; + info->dev_ready = pdata->dev_ready; + info->xfer_type = pdata->xfer_type; + info->devsize = pdata->devsize; + info->elm_of_node = pdata->elm_of_node; + info->flash_bbt = pdata->flash_bbt; + } + + platform_set_drvdata(pdev, info); info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs); if (!info->ops) { dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n"); return -ENODEV; } - info->pdev = pdev; - info->gpmc_cs = pdata->cs; - info->of_node = pdata->of_node; - info->ecc_opt = pdata->ecc_opt; - info->dev_ready = pdata->dev_ready; - info->xfer_type = pdata->xfer_type; - info->devsize = pdata->devsize; - info->elm_of_node = pdata->elm_of_node; nand_chip = &info->nand; mtd = nand_to_mtd(nand_chip); mtd->dev.parent = &pdev->dev; nand_chip->ecc.priv = NULL; - nand_set_flash_node(nand_chip, pdata->of_node); + nand_set_flash_node(nand_chip, dev->of_node); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); @@ -1717,7 +1802,7 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->chip_delay = 50; } - if (pdata->flash_bbt) + if (info->flash_bbt) nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; else nand_chip->options |= NAND_SKIP_BBTSCAN; @@ -2035,7 +2120,10 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } - mtd_device_register(mtd, pdata->parts, pdata->nr_parts); + if (dev->of_node) + mtd_device_register(mtd, NULL, 0); + else + mtd_device_register(mtd, pdata->parts, pdata->nr_parts); platform_set_drvdata(pdev, mtd); @@ -2066,11 +2154,17 @@ static int omap_nand_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id omap_nand_ids[] = { + { .compatible = "ti,omap2-nand", }, + {}, +}; + static struct platform_driver omap_nand_driver = { .probe = omap_nand_probe, .remove = omap_nand_remove, .driver = { .name = DRIVER_NAME, + .of_match_table = of_match_ptr(omap_nand_ids), }, }; diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index a067f581e938..ff27e5a77e03 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -76,11 +76,10 @@ struct omap_nand_platform_data { int devsize; enum omap_ecc ecc_opt; - /* for passing the partitions */ - struct device_node *of_node; struct device_node *elm_of_node; /* deprecated */ struct gpmc_nand_regs reg; + struct device_node *of_node; }; #endif -- GitLab From 51735caad3db6237fa9d31a2ce8b54cbd42ff6f0 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 26 May 2014 11:54:45 +0300 Subject: [PATCH 2881/9938] mtd: nand: omap: Update DT binding documentation Add compatible id and interrupts. The NAND interrupts are provided by the GPMC controller node. Signed-off-by: Roger Quadros Acked-by: Rob Herring Acked-by: Brian Norris Acked-by: Tony Lindgren --- .../devicetree/bindings/mtd/gpmc-nand.txt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index fb733c4e1c11..ff3215d20343 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt @@ -13,7 +13,11 @@ Documentation/devicetree/bindings/mtd/nand.txt Required properties: - - reg: The CS line the peripheral is connected to + - compatible: "ti,omap2-nand" + - reg: range id (CS number), base offset and length of the + NAND I/O space + - interrupt-parent: must point to gpmc node + - interrupts: Two interrupt specifiers, one for fifoevent, one for termcount. Optional properties: @@ -55,17 +59,22 @@ Example for an AM33xx board: gpmc: gpmc@50000000 { compatible = "ti,am3352-gpmc"; ti,hwmods = "gpmc"; - reg = <0x50000000 0x1000000>; + reg = <0x50000000 0x36c>; interrupts = <100>; gpmc,num-cs = <8>; gpmc,num-waitpins = <2>; #address-cells = <2>; #size-cells = <1>; - ranges = <0 0 0x08000000 0x2000>; /* CS0: NAND */ + ranges = <0 0 0x08000000 0x1000000>; /* CS0 space, 16MB */ elm_id = <&elm>; + interrupt-controller; + #interrupt-cells = <2>; nand@0,0 { - reg = <0 0 0>; /* CS0, offset 0 */ + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, NAND I/O window 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, <1 IRQ_TYPE NONE>; nand-bus-width = <16>; ti,nand-ecc-opt = "bch8"; ti,nand-xfer-type = "polled"; -- GitLab From bdd7e033fe4cc3836b141b75119a4a975a64d9bc Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 9 Jul 2015 17:31:45 +0300 Subject: [PATCH 2882/9938] memory: omap-gpmc: Prevent mapping into 1st 16MB We have been preventing mapping GPMC children in the first 1MB but really it has to be the first 16MB as the minimum GPMC partition size is 16MB. Also print an error message if CS mapping fails due to DT requesting address outside the GPMC map. Signed-off-by: Roger Quadros Acked-by: Tony Lindgren --- drivers/memory/omap-gpmc.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 8dc6e3b1c44a..bfe4e8710973 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -94,6 +94,14 @@ #define GPMC_CS_SIZE 0x30 #define GPMC_BCH_SIZE 0x10 +/* + * The first 1MB of GPMC address space is typically mapped to + * the internal ROM. Never allocate the first page, to + * facilitate bug detection; even if we didn't boot from ROM. + * As GPMC minimum partition size is 16MB we can only start from + * there. + */ +#define GPMC_MEM_START 0x1000000 #define GPMC_MEM_END 0x3FFFFFFF #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ @@ -1297,12 +1305,7 @@ static void gpmc_mem_init(void) { int cs; - /* - * The first 1MB of GPMC address space is typically mapped to - * the internal ROM. Never allocate the first page, to - * facilitate bug detection; even if we didn't boot from ROM. - */ - gpmc_mem_root.start = SZ_1M; + gpmc_mem_root.start = GPMC_MEM_START; gpmc_mem_root.end = GPMC_MEM_END; /* Reserve all regions that has been set up by bootloader */ @@ -1966,6 +1969,15 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, if (ret < 0) { dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n", cs, &res.start); + if (res.start < GPMC_MEM_START) { + dev_info(&pdev->dev, + "GPMC CS %d start cannot be lesser than 0x%x\n", + cs, GPMC_MEM_START); + } else if (res.end > GPMC_MEM_END) { + dev_info(&pdev->dev, + "GPMC CS %d end cannot be greater than 0x%x\n", + cs, GPMC_MEM_END); + } goto err; } -- GitLab From 3c76f6119a64eb8ff6d088ceb6ca03891e29a7ce Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 5 Aug 2015 17:01:54 +0300 Subject: [PATCH 2883/9938] memory: omap-gpmc: Move device tree binding to correct location omap-gpmc.c is a memory controller so move the binding to the right place. Signed-off-by: Roger Quadros Acked-by: Rob Herring Acked-by: Tony Lindgren --- .../{bus/ti-gpmc.txt => memory-controllers/omap-gpmc.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/{bus/ti-gpmc.txt => memory-controllers/omap-gpmc.txt} (100%) diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt similarity index 100% rename from Documentation/devicetree/bindings/bus/ti-gpmc.txt rename to Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt -- GitLab From d2d00862dfbbd22d80ee67f816cb7eeaea71f03b Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 7 Mar 2016 12:18:43 +0200 Subject: [PATCH 2884/9938] memory: omap-gpmc: Support general purpose input for WAITPINs OMAPs can have 2 to 4 WAITPINs that can be used as general purpose input if not used for memory wait state insertion. The first user will be the OMAP NAND chip to get the NAND read/busy status using gpiolib. Signed-off-by: Roger Quadros Acked-by: Rob Herring Acked-by: Tony Lindgren --- .../bindings/memory-controllers/omap-gpmc.txt | 6 + drivers/memory/Kconfig | 1 + drivers/memory/omap-gpmc.c | 117 ++++++++++++++++-- 3 files changed, 112 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt index 13f13786f992..97e71924dbbb 100644 --- a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt +++ b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt @@ -38,6 +38,10 @@ Required properties: 0 - NAND_fifoevent 1 - NAND_termcount - interrupt-cells: Must be set to 2 + - gpio-controller: The GPMC driver implements a GPIO controller for the + GPMC WAIT pins that can be used as general purpose inputs. + 0 maps to GPMC_WAIT0 pin. + - gpio-cells: Must be set to 2 Timing properties for child nodes. All are optional and default to 0. @@ -138,6 +142,8 @@ Example for an AM33xx board: ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */ interrupt-controller; #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; /* child nodes go here */ }; diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 51d5cd20c26a..a9b1c1419bef 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -51,6 +51,7 @@ config TI_EMIF config OMAP_GPMC bool + select GPIOLIB help This driver is for the General Purpose Memory Controller (GPMC) present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index bfe4e8710973..4dd1c65ee70c 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -237,6 +238,7 @@ struct gpmc_device { struct device *dev; int irq; struct irq_chip irq_chip; + struct gpio_chip gpio_chip; }; static struct irq_domain *gpmc_irq_domain; @@ -2064,10 +2066,71 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, return ret; } +static int gpmc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + return 1; /* we're input only */ +} + +static int gpmc_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + return 0; /* we're input only */ +} + +static int gpmc_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + return -EINVAL; /* we're input only */ +} + +static void gpmc_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ +} + +static int gpmc_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + u32 reg; + + offset += 8; + + reg = gpmc_read_reg(GPMC_STATUS) & BIT(offset); + + return !!reg; +} + +static int gpmc_gpio_init(struct gpmc_device *gpmc) +{ + int ret; + + gpmc->gpio_chip.parent = gpmc->dev; + gpmc->gpio_chip.owner = THIS_MODULE; + gpmc->gpio_chip.label = DEVICE_NAME; + gpmc->gpio_chip.ngpio = gpmc_nr_waitpins; + gpmc->gpio_chip.get_direction = gpmc_gpio_get_direction; + gpmc->gpio_chip.direction_input = gpmc_gpio_direction_input; + gpmc->gpio_chip.direction_output = gpmc_gpio_direction_output; + gpmc->gpio_chip.set = gpmc_gpio_set; + gpmc->gpio_chip.get = gpmc_gpio_get; + gpmc->gpio_chip.base = -1; + + ret = gpiochip_add(&gpmc->gpio_chip); + if (ret < 0) { + dev_err(gpmc->dev, "could not register gpio chip: %d\n", ret); + return ret; + } + + return 0; +} + +static void gpmc_gpio_exit(struct gpmc_device *gpmc) +{ + gpiochip_remove(&gpmc->gpio_chip); +} + static int gpmc_probe_dt(struct platform_device *pdev) { int ret; - struct device_node *child; const struct of_device_id *of_id = of_match_device(gpmc_dt_ids, &pdev->dev); @@ -2095,6 +2158,14 @@ static int gpmc_probe_dt(struct platform_device *pdev) return ret; } + return 0; +} + +static int gpmc_probe_dt_children(struct platform_device *pdev) +{ + int ret; + struct device_node *child; + for_each_available_child_of_node(pdev->dev.of_node, child) { if (!child->name) @@ -2104,6 +2175,9 @@ static int gpmc_probe_dt(struct platform_device *pdev) ret = gpmc_probe_onenand_child(pdev, child); else ret = gpmc_probe_generic_child(pdev, child); + + if (ret) + return ret; } return 0; @@ -2113,6 +2187,11 @@ static int gpmc_probe_dt(struct platform_device *pdev) { return 0; } + +static int gpmc_probe_dt_children(struct platform_device *pdev) +{ + return 0; +} #endif static int gpmc_probe(struct platform_device *pdev) @@ -2159,6 +2238,15 @@ static int gpmc_probe(struct platform_device *pdev) return -EINVAL; } + if (pdev->dev.of_node) { + rc = gpmc_probe_dt(pdev); + if (rc) + return rc; + } else { + gpmc_cs_num = GPMC_CS_NUM; + gpmc_nr_waitpins = GPMC_NR_WAITPINS; + } + pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -2184,29 +2272,33 @@ static int gpmc_probe(struct platform_device *pdev) GPMC_REVISION_MINOR(l)); gpmc_mem_init(); + rc = gpmc_gpio_init(gpmc); + if (rc) + goto gpio_init_failed; rc = gpmc_setup_irq(gpmc); if (rc) { dev_err(gpmc->dev, "gpmc_setup_irq failed\n"); - goto fail; + goto setup_irq_failed; } - if (!pdev->dev.of_node) { - gpmc_cs_num = GPMC_CS_NUM; - gpmc_nr_waitpins = GPMC_NR_WAITPINS; - } - - rc = gpmc_probe_dt(pdev); + rc = gpmc_probe_dt_children(pdev); if (rc < 0) { - dev_err(gpmc->dev, "failed to probe DT parameters\n"); - gpmc_free_irq(gpmc); - goto fail; + dev_err(gpmc->dev, "failed to probe DT children\n"); + goto dt_children_failed; } return 0; -fail: +dt_children_failed: + gpmc_free_irq(gpmc); +setup_irq_failed: + gpmc_gpio_exit(gpmc); +gpio_init_failed: + gpmc_mem_exit(); pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + return rc; } @@ -2215,6 +2307,7 @@ static int gpmc_remove(struct platform_device *pdev) struct gpmc_device *gpmc = platform_get_drvdata(pdev); gpmc_free_irq(gpmc); + gpmc_gpio_exit(gpmc); gpmc_mem_exit(); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); -- GitLab From 210325f0f4eb531f83ffb0b0f95612e2a8063983 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 6 Aug 2015 13:21:40 +0300 Subject: [PATCH 2885/9938] memory: omap-gpmc: Reserve WAITPIN if needed for WAIT monitoring If the device attached to GPMC wants to use the WAIT pin for WAIT monitoring then we reserve it internally for exclusive use. Signed-off-by: Roger Quadros Acked-by: Tony Lindgren --- drivers/memory/omap-gpmc.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 4dd1c65ee70c..784a64f31a8b 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -1911,6 +1911,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, const char *name; int ret, cs; u32 val; + struct gpio_desc *waitpin_desc = NULL; + struct gpmc_device *gpmc = platform_get_drvdata(pdev); if (of_property_read_u32(child, "reg", &cs) < 0) { dev_err(&pdev->dev, "%s has no 'reg' property\n", @@ -2020,16 +2022,30 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, goto err; } + /* Reserve wait pin if it is required and valid */ + if (gpmc_s.wait_on_read || gpmc_s.wait_on_write) { + unsigned int wait_pin = gpmc_s.wait_pin; + + waitpin_desc = gpiochip_request_own_desc(&gpmc->gpio_chip, + wait_pin, "WAITPIN"); + if (IS_ERR(waitpin_desc)) { + dev_err(&pdev->dev, "invalid wait-pin: %d\n", wait_pin); + ret = PTR_ERR(waitpin_desc); + goto err; + } + } + gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings"); + ret = gpmc_cs_program_settings(cs, &gpmc_s); if (ret < 0) - goto err; + goto err_cs; ret = gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s); if (ret) { dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n", child->name); - goto err; + goto err_cs; } /* Clear limited address i.e. enable A26-A11 */ @@ -2060,6 +2076,10 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name); ret = -ENODEV; +err_cs: + if (waitpin_desc) + gpiochip_free_own_desc(waitpin_desc); + err: gpmc_cs_free(cs); -- GitLab From b2bac25a4d298309bb4b2649bb1107ddaa287c47 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 19 Feb 2016 11:01:02 +0200 Subject: [PATCH 2886/9938] memory: omap-gpmc: Support WAIT pin edge interrupts OMAPs can have 2 to 4 WAITPINs that can be used as edge triggered interrupts if not used for memory wait state insertion. Support these interrupts via the gpmc IRQ domain. The gpmc IRQ domain interrupt map is: 0 - NAND_fifoevent 1 - NAND_termcount 2 - GPMC_WAIT0 edge 3 - GPMC_WAIT1 edge, and so on Signed-off-by: Roger Quadros Acked-by: Rob Herring Acked-by: Tony Lindgren --- .../bindings/memory-controllers/omap-gpmc.txt | 5 +- drivers/memory/omap-gpmc.c | 106 +++++++++++++++--- 2 files changed, 92 insertions(+), 19 deletions(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt index 97e71924dbbb..21055e210234 100644 --- a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt +++ b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt @@ -33,10 +33,13 @@ Required properties: As this will change in the future, filling correct values here is a requirement. - interrupt-controller: The GPMC driver implements and interrupt controller for - the NAND events "fifoevent" and "termcount". + the NAND events "fifoevent" and "termcount" plus the + rising/falling edges on the GPMC_WAIT pins. The interrupt number mapping is as follows 0 - NAND_fifoevent 1 - NAND_termcount + 2 - GPMC_WAIT0 pin edge + 3 - GPMC_WAIT1 pin edge, and so on. - interrupt-cells: Must be set to 2 - gpio-controller: The GPMC driver implements a GPIO controller for the GPMC WAIT pins that can be used as general purpose inputs. diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 784a64f31a8b..ea9c89747950 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -189,9 +189,7 @@ #define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ #define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ -/* XXX: Only NAND irq has been considered,currently these are the only ones used - */ -#define GPMC_NR_IRQ 2 +#define GPMC_NR_NAND_IRQS 2 /* number of NAND specific IRQs */ enum gpmc_clk_domain { GPMC_CD_FCLK, @@ -239,6 +237,7 @@ struct gpmc_device { int irq; struct irq_chip irq_chip; struct gpio_chip gpio_chip; + int nirqs; }; static struct irq_domain *gpmc_irq_domain; @@ -1155,7 +1154,8 @@ int gpmc_get_client_irq(unsigned irq_config) return 0; } - if (irq_config >= GPMC_NR_IRQ) + /* we restrict this to NAND IRQs only */ + if (irq_config >= GPMC_NR_NAND_IRQS) return 0; return irq_create_mapping(gpmc_irq_domain, irq_config); @@ -1165,6 +1165,10 @@ static int gpmc_irq_endis(unsigned long hwirq, bool endis) { u32 regval; + /* bits GPMC_NR_NAND_IRQS to 8 are reserved */ + if (hwirq >= GPMC_NR_NAND_IRQS) + hwirq += 8 - GPMC_NR_NAND_IRQS; + regval = gpmc_read_reg(GPMC_IRQENABLE); if (endis) regval |= BIT(hwirq); @@ -1185,9 +1189,64 @@ static void gpmc_irq_enable(struct irq_data *p) gpmc_irq_endis(p->hwirq, true); } -static void gpmc_irq_noop(struct irq_data *data) { } +static void gpmc_irq_mask(struct irq_data *d) +{ + gpmc_irq_endis(d->hwirq, false); +} + +static void gpmc_irq_unmask(struct irq_data *d) +{ + gpmc_irq_endis(d->hwirq, true); +} + +static void gpmc_irq_edge_config(unsigned long hwirq, bool rising_edge) +{ + u32 regval; + + /* NAND IRQs polarity is not configurable */ + if (hwirq < GPMC_NR_NAND_IRQS) + return; + + /* WAITPIN starts at BIT 8 */ + hwirq += 8 - GPMC_NR_NAND_IRQS; + + regval = gpmc_read_reg(GPMC_CONFIG); + if (rising_edge) + regval &= ~BIT(hwirq); + else + regval |= BIT(hwirq); + + gpmc_write_reg(GPMC_CONFIG, regval); +} + +static void gpmc_irq_ack(struct irq_data *d) +{ + unsigned int hwirq = d->hwirq; + + /* skip reserved bits */ + if (hwirq >= GPMC_NR_NAND_IRQS) + hwirq += 8 - GPMC_NR_NAND_IRQS; + + /* Setting bit to 1 clears (or Acks) the interrupt */ + gpmc_write_reg(GPMC_IRQSTATUS, BIT(hwirq)); +} + +static int gpmc_irq_set_type(struct irq_data *d, unsigned int trigger) +{ + /* can't set type for NAND IRQs */ + if (d->hwirq < GPMC_NR_NAND_IRQS) + return -EINVAL; + + /* We can support either rising or falling edge at a time */ + if (trigger == IRQ_TYPE_EDGE_FALLING) + gpmc_irq_edge_config(d->hwirq, false); + else if (trigger == IRQ_TYPE_EDGE_RISING) + gpmc_irq_edge_config(d->hwirq, true); + else + return -EINVAL; -static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } + return 0; +} static int gpmc_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw) @@ -1195,8 +1254,14 @@ static int gpmc_irq_map(struct irq_domain *d, unsigned int virq, struct gpmc_device *gpmc = d->host_data; irq_set_chip_data(virq, gpmc); - irq_set_chip_and_handler(virq, &gpmc->irq_chip, handle_simple_irq); - irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOAUTOEN); + if (hw < GPMC_NR_NAND_IRQS) { + irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOAUTOEN); + irq_set_chip_and_handler(virq, &gpmc->irq_chip, + handle_simple_irq); + } else { + irq_set_chip_and_handler(virq, &gpmc->irq_chip, + handle_edge_irq); + } return 0; } @@ -1209,16 +1274,21 @@ static const struct irq_domain_ops gpmc_irq_domain_ops = { static irqreturn_t gpmc_handle_irq(int irq, void *data) { int hwirq, virq; - u32 regval; + u32 regval, regvalx; struct gpmc_device *gpmc = data; regval = gpmc_read_reg(GPMC_IRQSTATUS); + regvalx = regval; if (!regval) return IRQ_NONE; - for (hwirq = 0; hwirq < GPMC_NR_IRQ; hwirq++) { - if (regval & BIT(hwirq)) { + for (hwirq = 0; hwirq < gpmc->nirqs; hwirq++) { + /* skip reserved status bits */ + if (hwirq == GPMC_NR_NAND_IRQS) + regvalx >>= 8 - GPMC_NR_NAND_IRQS; + + if (regvalx & BIT(hwirq)) { virq = irq_find_mapping(gpmc_irq_domain, hwirq); if (!virq) { dev_warn(gpmc->dev, @@ -1248,16 +1318,15 @@ static int gpmc_setup_irq(struct gpmc_device *gpmc) gpmc_write_reg(GPMC_IRQSTATUS, regval); gpmc->irq_chip.name = "gpmc"; - gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret; gpmc->irq_chip.irq_enable = gpmc_irq_enable; gpmc->irq_chip.irq_disable = gpmc_irq_disable; - gpmc->irq_chip.irq_shutdown = gpmc_irq_noop; - gpmc->irq_chip.irq_ack = gpmc_irq_noop; - gpmc->irq_chip.irq_mask = gpmc_irq_noop; - gpmc->irq_chip.irq_unmask = gpmc_irq_noop; + gpmc->irq_chip.irq_ack = gpmc_irq_ack; + gpmc->irq_chip.irq_mask = gpmc_irq_mask; + gpmc->irq_chip.irq_unmask = gpmc_irq_unmask; + gpmc->irq_chip.irq_set_type = gpmc_irq_set_type; gpmc_irq_domain = irq_domain_add_linear(gpmc->dev->of_node, - GPMC_NR_IRQ, + gpmc->nirqs, &gpmc_irq_domain_ops, gpmc); if (!gpmc_irq_domain) { @@ -1282,7 +1351,7 @@ static int gpmc_free_irq(struct gpmc_device *gpmc) free_irq(gpmc->irq, gpmc); - for (hwirq = 0; hwirq < GPMC_NR_IRQ; hwirq++) + for (hwirq = 0; hwirq < gpmc->nirqs; hwirq++) irq_dispose_mapping(irq_find_mapping(gpmc_irq_domain, hwirq)); irq_domain_remove(gpmc_irq_domain); @@ -2296,6 +2365,7 @@ static int gpmc_probe(struct platform_device *pdev) if (rc) goto gpio_init_failed; + gpmc->nirqs = GPMC_NR_NAND_IRQS + gpmc_nr_waitpins; rc = gpmc_setup_irq(gpmc); if (rc) { dev_err(gpmc->dev, "gpmc_setup_irq failed\n"); -- GitLab From 9e6946215dbd9803e8b511928c9f61f3a49e2c58 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 7 Aug 2015 10:38:13 +0300 Subject: [PATCH 2887/9938] memory: omap-gpmc: Prevent GPMC_STATUS from being accessed via gpmc_regs GPMC_STATUS register is private to the GPMC module and must not be accessed directly by NAND driver through the gpmc_regs. They must use gpmc_omap_get_nand_ops() instead. Signed-off-by: Roger Quadros Acked-by: Tony Lindgren --- drivers/memory/omap-gpmc.c | 2 +- include/linux/platform_data/mtd-nand-omap2.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index ea9c89747950..33d69b1e4c31 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -1081,7 +1081,7 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) { int i; - reg->gpmc_status = gpmc_base + GPMC_STATUS; + reg->gpmc_status = NULL; /* deprecated */ reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET + GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET + diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index ff27e5a77e03..7f6de5377f80 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -45,7 +45,6 @@ enum omap_ecc { }; struct gpmc_nand_regs { - void __iomem *gpmc_status; void __iomem *gpmc_nand_command; void __iomem *gpmc_nand_address; void __iomem *gpmc_nand_data; @@ -64,6 +63,8 @@ struct gpmc_nand_regs { void __iomem *gpmc_bch_result4[GPMC_BCH_NUM_REMAINDER]; void __iomem *gpmc_bch_result5[GPMC_BCH_NUM_REMAINDER]; void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER]; + /* Deprecated. Do not use */ + void __iomem *gpmc_status; }; struct omap_nand_platform_data { -- GitLab From 10f22ee367c4aff7841da6a83c10445d7d6328d9 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 6 Aug 2015 17:39:35 +0300 Subject: [PATCH 2888/9938] mtd: nand: omap2: Implement NAND ready using gpiolib The GPMC WAIT pin status are now available over gpiolib. Update the omap_dev_ready() function to use gpio instead of directly accessing GPMC register space. Signed-off-by: Roger Quadros Acked-by: Brian Norris Acked-by: Boris Brezillon Acked-by: Tony Lindgren --- .../devicetree/bindings/mtd/gpmc-nand.txt | 2 ++ drivers/mtd/nand/omap2.c | 29 ++++++++++++------- include/linux/platform_data/mtd-nand-omap2.h | 2 +- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index ff3215d20343..3ee7e202657c 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt @@ -48,6 +48,7 @@ Optional properties: locating ECC errors for BCHx algorithms. SoC devices which have ELM hardware engines should specify this device node in .dtsi Using ELM for ECC error correction frees some CPU cycles. + - rb-gpios: GPIO specifier for the ready/busy# pin. For inline partition table parsing (optional): @@ -78,6 +79,7 @@ Example for an AM33xx board: nand-bus-width = <16>; ti,nand-ecc-opt = "bch8"; ti,nand-xfer-type = "polled"; + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ gpmc,sync-clk-ps = <0>; gpmc,cs-on-ns = <0>; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 35b8f3359c17..e0b2b2f0fbde 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -182,6 +183,8 @@ struct omap_nand_info { struct nand_ecclayout oobinfo; /* fields specific for BCHx_HW ECC scheme */ struct device *elm_dev; + /* NAND ready gpio */ + struct gpio_desc *ready_gpiod; }; static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) @@ -1023,21 +1026,16 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) } /** - * omap_dev_ready - calls the platform specific dev_ready function + * omap_dev_ready - checks the NAND Ready GPIO line * @mtd: MTD device structure + * + * Returns true if ready and false if busy. */ static int omap_dev_ready(struct mtd_info *mtd) { - unsigned int val = 0; struct omap_nand_info *info = mtd_to_omap(mtd); - val = readl(info->reg.gpmc_status); - - if ((val & 0x100) == 0x100) { - return 1; - } else { - return 0; - } + return gpiod_get_value(info->ready_gpiod); } /** @@ -1755,7 +1753,9 @@ static int omap_nand_probe(struct platform_device *pdev) info->gpmc_cs = pdata->cs; info->reg = pdata->reg; info->ecc_opt = pdata->ecc_opt; - info->dev_ready = pdata->dev_ready; + if (pdata->dev_ready) + dev_info(&pdev->dev, "pdata->dev_ready is deprecated\n"); + info->xfer_type = pdata->xfer_type; info->devsize = pdata->devsize; info->elm_of_node = pdata->elm_of_node; @@ -1787,6 +1787,13 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; nand_chip->cmd_ctrl = omap_hwcontrol; + info->ready_gpiod = devm_gpiod_get_optional(&pdev->dev, "rb", + GPIOD_IN); + if (IS_ERR(info->ready_gpiod)) { + dev_err(dev, "failed to get ready gpio\n"); + return PTR_ERR(info->ready_gpiod); + } + /* * If RDY/BSY line is connected to OMAP then use the omap ready * function and the generic nand_wait function which reads the status @@ -1794,7 +1801,7 @@ static int omap_nand_probe(struct platform_device *pdev) * chip delay which is slightly more than tR (AC Timing) of the NAND * device and read status register until you get a failure or success */ - if (info->dev_ready) { + if (info->ready_gpiod) { nand_chip->dev_ready = omap_dev_ready; nand_chip->chip_delay = 0; } else { diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 7f6de5377f80..17d57a18bac5 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -71,7 +71,6 @@ struct omap_nand_platform_data { int cs; struct mtd_partition *parts; int nr_parts; - bool dev_ready; bool flash_bbt; enum nand_io xfer_type; int devsize; @@ -82,5 +81,6 @@ struct omap_nand_platform_data { /* deprecated */ struct gpmc_nand_regs reg; struct device_node *of_node; + bool dev_ready; }; #endif -- GitLab From dec8e8f6e6504aa3496c0f7cc10c756bb0e10f44 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 14 Apr 2016 23:37:26 -0700 Subject: [PATCH 2889/9938] regmap: spmi: Fix regmap_spmi_ext_read in multi-byte case Specifically for the case of reads that use the Extended Register Read Long command, a multi-byte read operation is broken up into 8-byte chunks. However the call to spmi_ext_register_readl() is incorrectly passing 'val_size', which if greater than 8 will always fail. The argument should instead be 'len'. Fixes: c9afbb05a9ff ("regmap: spmi: support base and extended register spaces") Signed-off-by: Jack Pham Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/base/regmap/regmap-spmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c index 7e58f6560399..4a36e415e938 100644 --- a/drivers/base/regmap/regmap-spmi.c +++ b/drivers/base/regmap/regmap-spmi.c @@ -142,7 +142,7 @@ static int regmap_spmi_ext_read(void *context, while (val_size) { len = min_t(size_t, val_size, 8); - err = spmi_ext_register_readl(context, addr, val, val_size); + err = spmi_ext_register_readl(context, addr, val, len); if (err) goto err_out; -- GitLab From 2d8e1f039de842701d35a857a7c5d9d47bc1c639 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 11 Apr 2016 10:14:46 +0300 Subject: [PATCH 2890/9938] iommu/amd: Signedness bug in acpihid_device_group() "devid" needs to be signed for the error handling to work. Fixes: b097d11a0fa3f ('iommu/amd: Manage iommu_group for ACPI HID devices') Signed-off-by: Dan Carpenter Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index c430c10fb645..12f77798a0a4 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -283,7 +283,7 @@ static struct iommu_dev_data *get_dev_data(struct device *dev) static struct iommu_group *acpihid_device_group(struct device *dev) { struct acpihid_map_entry *p, *entry = NULL; - u16 devid; + int devid; devid = get_acpihid_device_id(dev, &entry); if (devid < 0) -- GitLab From 56ed4bb984acbba9cfe080e45ac4b50ca63dd188 Mon Sep 17 00:00:00 2001 From: Koji Matsuoka Date: Wed, 13 Apr 2016 21:01:47 +0300 Subject: [PATCH 2891/9938] pinctrl: sh-pfc: r8a7794: Add DU pin groups r8a7794 PFC DU support from the R-Car Gen2 v1.9.4 BSP [Magnus: added the description, added missing dot clock output signals, separated CDE and DISP signals, broke out the ODDF signal from the sync group.] [Sergei: resolved rejects, folded in Magnus' patches, killed empty lines, reordered pin/mux arrays and pin groups, fixed up some comments to the pin arrays, removed the "du" function splitting its groups between the "du0" and "du1" functions.] Signed-off-by: Koji Matsuoka Signed-off-by: Magnus Damm Signed-off-by: Sergei Shtylyov Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7794.c | 217 +++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c index 38912cff597b..8bc2cf0c594e 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c @@ -1682,6 +1682,179 @@ static const unsigned int avb_avtp_match_b_pins[] = { static const unsigned int avb_avtp_match_b_mux[] = { AVB_AVTP_MATCH_B_MARK, }; +/* - DU --------------------------------------------------------------------- */ +static const unsigned int du0_rgb666_pins[] = { + /* R[7:2], G[7:2], B[7:2] */ + RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 5), + RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 2), + RCAR_GP_PIN(2, 15), RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13), + RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), + RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 22), RCAR_GP_PIN(2, 21), + RCAR_GP_PIN(2, 20), RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 18), +}; +static const unsigned int du0_rgb666_mux[] = { + DU0_DR7_MARK, DU0_DR6_MARK, DU0_DR5_MARK, DU0_DR4_MARK, + DU0_DR3_MARK, DU0_DR2_MARK, + DU0_DG7_MARK, DU0_DG6_MARK, DU0_DG5_MARK, DU0_DG4_MARK, + DU0_DG3_MARK, DU0_DG2_MARK, + DU0_DB7_MARK, DU0_DB6_MARK, DU0_DB5_MARK, DU0_DB4_MARK, + DU0_DB3_MARK, DU0_DB2_MARK, +}; +static const unsigned int du0_rgb888_pins[] = { + /* R[7:0], G[7:0], B[7:0] */ + RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 5), + RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 2), + RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 0), + RCAR_GP_PIN(2, 15), RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13), + RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), + RCAR_GP_PIN(2, 9), RCAR_GP_PIN(2, 8), + RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 22), RCAR_GP_PIN(2, 21), + RCAR_GP_PIN(2, 20), RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 18), + RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 16), +}; +static const unsigned int du0_rgb888_mux[] = { + DU0_DR7_MARK, DU0_DR6_MARK, DU0_DR5_MARK, DU0_DR4_MARK, + DU0_DR3_MARK, DU0_DR2_MARK, DU0_DR1_MARK, DU0_DR0_MARK, + DU0_DG7_MARK, DU0_DG6_MARK, DU0_DG5_MARK, DU0_DG4_MARK, + DU0_DG3_MARK, DU0_DG2_MARK, DU0_DG1_MARK, DU0_DG0_MARK, + DU0_DB7_MARK, DU0_DB6_MARK, DU0_DB5_MARK, DU0_DB4_MARK, + DU0_DB3_MARK, DU0_DB2_MARK, DU0_DB1_MARK, DU0_DB0_MARK, +}; +static const unsigned int du0_clk0_out_pins[] = { + /* DOTCLKOUT0 */ + RCAR_GP_PIN(2, 25), +}; +static const unsigned int du0_clk0_out_mux[] = { + DU0_DOTCLKOUT0_MARK +}; +static const unsigned int du0_clk1_out_pins[] = { + /* DOTCLKOUT1 */ + RCAR_GP_PIN(2, 26), +}; +static const unsigned int du0_clk1_out_mux[] = { + DU0_DOTCLKOUT1_MARK +}; +static const unsigned int du0_clk_in_pins[] = { + /* CLKIN */ + RCAR_GP_PIN(2, 24), +}; +static const unsigned int du0_clk_in_mux[] = { + DU0_DOTCLKIN_MARK +}; +static const unsigned int du0_sync_pins[] = { + /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */ + RCAR_GP_PIN(2, 28), RCAR_GP_PIN(2, 27), +}; +static const unsigned int du0_sync_mux[] = { + DU0_EXVSYNC_DU0_VSYNC_MARK, DU0_EXHSYNC_DU0_HSYNC_MARK +}; +static const unsigned int du0_oddf_pins[] = { + /* EXODDF/ODDF/DISP/CDE */ + RCAR_GP_PIN(2, 29), +}; +static const unsigned int du0_oddf_mux[] = { + DU0_EXODDF_DU0_ODDF_DISP_CDE_MARK, +}; +static const unsigned int du0_cde_pins[] = { + /* CDE */ + RCAR_GP_PIN(2, 31), +}; +static const unsigned int du0_cde_mux[] = { + DU0_CDE_MARK, +}; +static const unsigned int du0_disp_pins[] = { + /* DISP */ + RCAR_GP_PIN(2, 30), +}; +static const unsigned int du0_disp_mux[] = { + DU0_DISP_MARK +}; +static const unsigned int du1_rgb666_pins[] = { + /* R[7:2], G[7:2], B[7:2] */ + RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 6), RCAR_GP_PIN(4, 5), + RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), + RCAR_GP_PIN(4, 15), RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 13), + RCAR_GP_PIN(4, 12), RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 10), + RCAR_GP_PIN(4, 23), RCAR_GP_PIN(4, 22), RCAR_GP_PIN(4, 21), + RCAR_GP_PIN(4, 20), RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 18), +}; +static const unsigned int du1_rgb666_mux[] = { + DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK, + DU1_DR3_MARK, DU1_DR2_MARK, + DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK, + DU1_DG3_MARK, DU1_DG2_MARK, + DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK, + DU1_DB3_MARK, DU1_DB2_MARK, +}; +static const unsigned int du1_rgb888_pins[] = { + /* R[7:0], G[7:0], B[7:0] */ + RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 6), RCAR_GP_PIN(4, 5), + RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), + RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0), + RCAR_GP_PIN(4, 15), RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 13), + RCAR_GP_PIN(4, 12), RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 10), + RCAR_GP_PIN(4, 9), RCAR_GP_PIN(4, 8), + RCAR_GP_PIN(4, 23), RCAR_GP_PIN(4, 22), RCAR_GP_PIN(4, 21), + RCAR_GP_PIN(4, 20), RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 18), + RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 16), +}; +static const unsigned int du1_rgb888_mux[] = { + DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK, + DU1_DR3_MARK, DU1_DR2_MARK, DU1_DR1_MARK, DU1_DR0_MARK, + DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK, + DU1_DG3_MARK, DU1_DG2_MARK, DU1_DG1_MARK, DU1_DG0_MARK, + DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK, + DU1_DB3_MARK, DU1_DB2_MARK, DU1_DB1_MARK, DU1_DB0_MARK, +}; +static const unsigned int du1_clk0_out_pins[] = { + /* DOTCLKOUT0 */ + RCAR_GP_PIN(4, 25), +}; +static const unsigned int du1_clk0_out_mux[] = { + DU1_DOTCLKOUT0_MARK +}; +static const unsigned int du1_clk1_out_pins[] = { + /* DOTCLKOUT1 */ + RCAR_GP_PIN(4, 26), +}; +static const unsigned int du1_clk1_out_mux[] = { + DU1_DOTCLKOUT1_MARK +}; +static const unsigned int du1_clk_in_pins[] = { + /* DOTCLKIN */ + RCAR_GP_PIN(4, 24), +}; +static const unsigned int du1_clk_in_mux[] = { + DU1_DOTCLKIN_MARK +}; +static const unsigned int du1_sync_pins[] = { + /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */ + RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 27), +}; +static const unsigned int du1_sync_mux[] = { + DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK +}; +static const unsigned int du1_oddf_pins[] = { + /* EXODDF/ODDF/DISP/CDE */ + RCAR_GP_PIN(4, 29), +}; +static const unsigned int du1_oddf_mux[] = { + DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK, +}; +static const unsigned int du1_cde_pins[] = { + /* CDE */ + RCAR_GP_PIN(4, 31), +}; +static const unsigned int du1_cde_mux[] = { + DU1_CDE_MARK +}; +static const unsigned int du1_disp_pins[] = { + /* DISP */ + RCAR_GP_PIN(4, 30), +}; +static const unsigned int du1_disp_mux[] = { + DU1_DISP_MARK +}; /* - ETH -------------------------------------------------------------------- */ static const unsigned int eth_link_pins[] = { /* LINK */ @@ -3364,6 +3537,24 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(avb_avtp_match), SH_PFC_PIN_GROUP(avb_avtp_capture_b), SH_PFC_PIN_GROUP(avb_avtp_match_b), + SH_PFC_PIN_GROUP(du0_rgb666), + SH_PFC_PIN_GROUP(du0_rgb888), + SH_PFC_PIN_GROUP(du0_clk0_out), + SH_PFC_PIN_GROUP(du0_clk1_out), + SH_PFC_PIN_GROUP(du0_clk_in), + SH_PFC_PIN_GROUP(du0_sync), + SH_PFC_PIN_GROUP(du0_oddf), + SH_PFC_PIN_GROUP(du0_cde), + SH_PFC_PIN_GROUP(du0_disp), + SH_PFC_PIN_GROUP(du1_rgb666), + SH_PFC_PIN_GROUP(du1_rgb888), + SH_PFC_PIN_GROUP(du1_clk0_out), + SH_PFC_PIN_GROUP(du1_clk1_out), + SH_PFC_PIN_GROUP(du1_clk_in), + SH_PFC_PIN_GROUP(du1_sync), + SH_PFC_PIN_GROUP(du1_oddf), + SH_PFC_PIN_GROUP(du1_cde), + SH_PFC_PIN_GROUP(du1_disp), SH_PFC_PIN_GROUP(eth_link), SH_PFC_PIN_GROUP(eth_magic), SH_PFC_PIN_GROUP(eth_mdio), @@ -3622,6 +3813,30 @@ static const char * const avb_groups[] = { "avb_avtp_match_b", }; +static const char * const du0_groups[] = { + "du0_rgb666", + "du0_rgb888", + "du0_clk0_out", + "du0_clk1_out", + "du0_clk_in", + "du0_sync", + "du0_oddf", + "du0_cde", + "du0_disp", +}; + +static const char * const du1_groups[] = { + "du1_rgb666", + "du1_rgb888", + "du1_clk0_out", + "du1_clk1_out", + "du1_clk_in", + "du1_sync", + "du1_oddf", + "du1_cde", + "du1_disp", +}; + static const char * const eth_groups[] = { "eth_link", "eth_magic", @@ -3969,6 +4184,8 @@ static const char * const vin1_groups[] = { static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(avb), + SH_PFC_FUNCTION(du0), + SH_PFC_FUNCTION(du1), SH_PFC_FUNCTION(eth), SH_PFC_FUNCTION(hscif0), SH_PFC_FUNCTION(hscif1), -- GitLab From a19c921fca0a865b657d59b2c9a05aa0a2905126 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Apr 2016 15:28:52 +0200 Subject: [PATCH 2892/9938] ALSA: lx646es: Fix possible uninitialized variable reference lx_pipe_state() checks the return value from lx_message_send_atomic() and breaks the loop only when it's a negative value. However, lx_message_send_atomic() may return a positive error code (as the return code from the hardware), and then lx_pipe_state() tries to compare the uninitialized current_state variable. Fix this behavior by checking the positive non-zero error code as well. Reported-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index f3d62020ef66..a80684bdc30d 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -644,7 +644,7 @@ static int lx_pipe_wait_for_state(struct lx6464es *chip, u32 pipe, if (err < 0) return err; - if (current_state == state) + if (!err && current_state == state) return 0; mdelay(1); -- GitLab From 8d53957c66e5cc0f1e8d33807800271d0f4fa009 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 14 Apr 2016 15:57:18 -0400 Subject: [PATCH 2893/9938] arm64: tegra: Enable cros-ec and charger on Smaug Add nodes for the ChromeOS Embedded Controller and for the gas gauge connected to the I2C bus that it controls. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra210-smaug.dts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts index 3d01af78cfb3..4d89f4e02d98 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts @@ -1300,6 +1300,33 @@ status = "okay"; }; + i2c@7000c400 { + status = "okay"; + clock-frequency = <1000000>; + + ec@1e { + compatible = "google,cros-ec-i2c"; + reg = <0x1e>; + interrupt-parent = <&gpio>; + interrupts = ; + wakeup-source; + + ec_i2c_0: i2c-tunnel { + compatible = "google,cros-ec-i2c-tunnel"; + #address-cells = <1>; + #size-cells = <0>; + + google,remote-bus = <0>; + + battery: bq27742@55 { + compatible = "ti,bq27742"; + reg = <0x55>; + battery-name = "battery"; + }; + }; + }; + }; + pmc@7000e400 { nvidia,invert-interrupt; nvidia,suspend-mode = <0>; -- GitLab From c686090f14e0673f9b1a3aec316098742f8e003c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 12 Apr 2016 18:00:53 +0200 Subject: [PATCH 2894/9938] gpio/reset: move gpio-{poweroff|restart} DT doc to proper place I did only find them after a fuzzy search, so let them be where one would expect them. Signed-off-by: Wolfram Sang Acked-By: Sebastian Reichel Signed-off-by: Linus Walleij --- .../devicetree/bindings/{gpio => power/reset}/gpio-poweroff.txt | 0 .../devicetree/bindings/{gpio => power/reset}/gpio-restart.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/{gpio => power/reset}/gpio-poweroff.txt (100%) rename Documentation/devicetree/bindings/{gpio => power/reset}/gpio-restart.txt (100%) diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt similarity index 100% rename from Documentation/devicetree/bindings/gpio/gpio-poweroff.txt rename to Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio-restart.txt b/Documentation/devicetree/bindings/power/reset/gpio-restart.txt similarity index 100% rename from Documentation/devicetree/bindings/gpio/gpio-restart.txt rename to Documentation/devicetree/bindings/power/reset/gpio-restart.txt -- GitLab From 6eae29e7e7144d01a6d6af111d232b36cdd30f51 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 2 Apr 2016 10:54:56 -0500 Subject: [PATCH 2895/9938] crypto: doc - document correct return value for request allocation Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- Documentation/DocBook/crypto-API.tmpl | 6 +++--- include/crypto/aead.h | 3 +-- include/crypto/hash.h | 3 +-- include/crypto/skcipher.h | 3 +-- include/linux/crypto.h | 3 +-- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Documentation/DocBook/crypto-API.tmpl b/Documentation/DocBook/crypto-API.tmpl index 348619fcafb8..d55dc5a39bad 100644 --- a/Documentation/DocBook/crypto-API.tmpl +++ b/Documentation/DocBook/crypto-API.tmpl @@ -1936,9 +1936,9 @@ static int test_skcipher(void) } req = skcipher_request_alloc(skcipher, GFP_KERNEL); - if (IS_ERR(req)) { - pr_info("could not allocate request queue\n"); - ret = PTR_ERR(req); + if (!req) { + pr_info("could not allocate skcipher request\n"); + ret = -ENOMEM; goto out; } diff --git a/include/crypto/aead.h b/include/crypto/aead.h index 957bb8763219..75174f80a106 100644 --- a/include/crypto/aead.h +++ b/include/crypto/aead.h @@ -405,8 +405,7 @@ static inline void aead_request_set_tfm(struct aead_request *req, * encrypt and decrypt API calls. During the allocation, the provided aead * handle is registered in the request data structure. * - * Return: allocated request handle in case of success; IS_ERR() is true in case - * of an error, PTR_ERR() returns the error code. + * Return: allocated request handle in case of success, or NULL if out of memory */ static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm, gfp_t gfp) diff --git a/include/crypto/hash.h b/include/crypto/hash.h index 1969f1416658..26605888a199 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -547,8 +547,7 @@ static inline void ahash_request_set_tfm(struct ahash_request *req, * the allocation, the provided ahash handle * is registered in the request data structure. * - * Return: allocated request handle in case of success; IS_ERR() is true in case - * of an error, PTR_ERR() returns the error code. + * Return: allocated request handle in case of success, or NULL if out of memory */ static inline struct ahash_request *ahash_request_alloc( struct crypto_ahash *tfm, gfp_t gfp) diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index 905490c1da89..0f987f50bb52 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -425,8 +425,7 @@ static inline struct skcipher_request *skcipher_request_cast( * encrypt and decrypt API calls. During the allocation, the provided skcipher * handle is registered in the request data structure. * - * Return: allocated request handle in case of success; IS_ERR() is true in case - * of an error, PTR_ERR() returns the error code. + * Return: allocated request handle in case of success, or NULL if out of memory */ static inline struct skcipher_request *skcipher_request_alloc( struct crypto_skcipher *tfm, gfp_t gfp) diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 99c94899ad0f..6e28c895c376 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -948,8 +948,7 @@ static inline struct ablkcipher_request *ablkcipher_request_cast( * encrypt and decrypt API calls. During the allocation, the provided ablkcipher * handle is registered in the request data structure. * - * Return: allocated request handle in case of success; IS_ERR() is true in case - * of an error, PTR_ERR() returns the error code. + * Return: allocated request handle in case of success, or NULL if out of memory */ static inline struct ablkcipher_request *ablkcipher_request_alloc( struct crypto_ablkcipher *tfm, gfp_t gfp) -- GitLab From 7587c407540006e4e8fd5ed33f66ffe6158e830a Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Tue, 5 Apr 2016 15:03:21 +0200 Subject: [PATCH 2896/9938] crypto: ccp - Fix RT breaking #include Direct include of rwlock_types.h breaks RT, use spinlock_types.h instead. Fixes: 553d2374db0b crypto: ccp - Support for multiple CCPs Signed-off-by: Mike Galbraith Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index 4dbc18727235..87b9f2bfa623 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include -- GitLab From d6064165ba4449ea085a389724d728258a3180ec Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Wed, 6 Apr 2016 11:01:54 -0700 Subject: [PATCH 2897/9938] crypto: qat - adf_dev_stop should not be called in atomic context VFs call adf_dev_stop() from a PF to VF interrupt bottom half. This causes an oops "scheduling while atomic", because it tries to acquire a mutex to un-register crypto algorithms. This patch fixes the issue by calling adf_dev_stop() asynchronously. Changes in v2: - change kthread to a work queue. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- .../crypto/qat/qat_common/adf_common_drv.h | 2 + drivers/crypto/qat/qat_common/adf_ctl_drv.c | 6 ++ drivers/crypto/qat/qat_common/adf_vf_isr.c | 59 ++++++++++++++++++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index c9e4d469e930..fd096eda880f 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -144,6 +144,8 @@ void adf_disable_aer(struct adf_accel_dev *accel_dev); void adf_dev_restore(struct adf_accel_dev *accel_dev); int adf_init_aer(void); void adf_exit_aer(void); +int adf_init_vf_wq(void); +void adf_exit_vf_wq(void); int adf_init_admin_comms(struct adf_accel_dev *accel_dev); void adf_exit_admin_comms(struct adf_accel_dev *accel_dev); int adf_send_admin_init(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c index 48a1248381b3..116ddda75e27 100644 --- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c @@ -471,12 +471,17 @@ static int __init adf_register_ctl_device_driver(void) if (adf_init_aer()) goto err_aer; + if (adf_init_vf_wq()) + goto err_vf_wq; + if (qat_crypto_register()) goto err_crypto_register; return 0; err_crypto_register: + adf_exit_vf_wq(); +err_vf_wq: adf_exit_aer(); err_aer: adf_chr_drv_destroy(); @@ -489,6 +494,7 @@ static void __exit adf_unregister_ctl_device_driver(void) { adf_chr_drv_destroy(); adf_exit_aer(); + adf_exit_vf_wq(); qat_crypto_unregister(); adf_clean_vf_map(false); mutex_destroy(&adf_ctl_lock); diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c index 09427b3d4d55..c3d501681466 100644 --- a/drivers/crypto/qat/qat_common/adf_vf_isr.c +++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "adf_accel_devices.h" #include "adf_common_drv.h" #include "adf_cfg.h" @@ -64,6 +65,13 @@ #define ADF_VINTSOU_BUN BIT(0) #define ADF_VINTSOU_PF2VF BIT(1) +static struct workqueue_struct *adf_vf_stop_wq; + +struct adf_vf_stop_data { + struct adf_accel_dev *accel_dev; + struct work_struct work; +}; + static int adf_enable_msi(struct adf_accel_dev *accel_dev) { struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev; @@ -90,6 +98,20 @@ static void adf_disable_msi(struct adf_accel_dev *accel_dev) pci_disable_msi(pdev); } +static void adf_dev_stop_async(struct work_struct *work) +{ + struct adf_vf_stop_data *stop_data = + container_of(work, struct adf_vf_stop_data, work); + struct adf_accel_dev *accel_dev = stop_data->accel_dev; + + adf_dev_stop(accel_dev); + adf_dev_shutdown(accel_dev); + + /* Re-enable PF2VF interrupts */ + adf_enable_pf2vf_interrupts(accel_dev); + kfree(stop_data); +} + static void adf_pf2vf_bh_handler(void *data) { struct adf_accel_dev *accel_dev = data; @@ -107,11 +129,27 @@ static void adf_pf2vf_bh_handler(void *data) goto err; switch ((msg & ADF_PF2VF_MSGTYPE_MASK) >> ADF_PF2VF_MSGTYPE_SHIFT) { - case ADF_PF2VF_MSGTYPE_RESTARTING: + case ADF_PF2VF_MSGTYPE_RESTARTING: { + struct adf_vf_stop_data *stop_data; + dev_dbg(&GET_DEV(accel_dev), "Restarting msg received from PF 0x%x\n", msg); - adf_dev_stop(accel_dev); - break; + + stop_data = kzalloc(sizeof(*stop_data), GFP_ATOMIC); + if (!stop_data) { + dev_err(&GET_DEV(accel_dev), + "Couldn't schedule stop for vf_%d\n", + accel_dev->accel_id); + return; + } + stop_data->accel_dev = accel_dev; + INIT_WORK(&stop_data->work, adf_dev_stop_async); + queue_work(adf_vf_stop_wq, &stop_data->work); + /* To ack, clear the PF2VFINT bit */ + msg &= ~BIT(0); + ADF_CSR_WR(pmisc_bar_addr, hw_data->get_pf2vf_offset(0), msg); + return; + } case ADF_PF2VF_MSGTYPE_VERSION_RESP: dev_dbg(&GET_DEV(accel_dev), "Version resp received from PF 0x%x\n", msg); @@ -278,3 +316,18 @@ int adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev) return -EFAULT; } EXPORT_SYMBOL_GPL(adf_vf_isr_resource_alloc); + +int __init adf_init_vf_wq(void) +{ + adf_vf_stop_wq = create_workqueue("adf_vf_stop_wq"); + + return !adf_vf_stop_wq ? -EFAULT : 0; +} + +void __exit adf_exit_vf_wq(void) +{ + if (adf_vf_stop_wq) + destroy_workqueue(adf_vf_stop_wq); + + adf_vf_stop_wq = NULL; +} -- GitLab From ff0078f0b047520405db14ef0deecde5898b50a4 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 12 Apr 2016 11:04:24 +0200 Subject: [PATCH 2898/9938] Documentation: devicetree: add Freescale SCC bindings Add documentation for the Freescale Security Controller (SCC) found on i.MX25 SoCs. Signed-off-by: Steffen Trumtrar Acked-by: Rob Herring Signed-off-by: Herbert Xu --- .../bindings/crypto/fsl-imx-scc.txt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt diff --git a/Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt b/Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt new file mode 100644 index 000000000000..7aad448e8a36 --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt @@ -0,0 +1,21 @@ +Freescale Security Controller (SCC) + +Required properties: +- compatible : Should be "fsl,imx25-scc". +- reg : Should contain register location and length. +- interrupts : Should contain interrupt numbers for SCM IRQ and SMN IRQ. +- interrupt-names : Should specify the names "scm" and "smn" for the + SCM IRQ and SMN IRQ. +- clocks: Should contain the clock driving the SCC core. +- clock-names: Should be set to "ipg". + +Example: + + scc: crypto@53fac000 { + compatible = "fsl,imx25-scc"; + reg = <0x53fac000 0x4000>; + clocks = <&clks 111>; + clock-names = "ipg"; + interrupts = <49>, <50>; + interrupt-names = "scm", "smn"; + }; -- GitLab From ba97eed2b62e97ab6a96d27ea6a049f3a815237c Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 12 Apr 2016 11:04:25 +0200 Subject: [PATCH 2899/9938] ARM: i.MX25: add scc module to dtsi Add the Security Controller (SCC) module to the dtsi. Signed-off-by: Steffen Trumtrar Signed-off-by: Herbert Xu --- arch/arm/boot/dts/imx25.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi index 6b1f4bbe6ec6..af6af8741fe5 100644 --- a/arch/arm/boot/dts/imx25.dtsi +++ b/arch/arm/boot/dts/imx25.dtsi @@ -420,6 +420,15 @@ interrupts = <41>; }; + scc: crypto@53fac000 { + compatible = "fsl,imx25-scc"; + reg = <0x53fac000 0x4000>; + clocks = <&clks 111>; + clock-names = "ipg"; + interrupts = <49>, <50>; + interrupt-names = "scm", "smn"; + }; + esdhc1: esdhc@53fb4000 { compatible = "fsl,imx25-esdhc"; reg = <0x53fb4000 0x4000>; -- GitLab From d293b640ebd532eb9d65bc42d48fb9d2c06e71c9 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 12 Apr 2016 11:04:26 +0200 Subject: [PATCH 2900/9938] crypto: mxc-scc - add basic driver for the MXC SCC According to the Freescale GPL driver code, there are two different Security Controller (SCC) versions: SCC and SCC2. The SCC is found on older i.MX SoCs, e.g. the i.MX25. This is the version implemented and tested here. As there is no publicly available documentation for this IP core, all information about this unit is gathered from the GPL'ed driver from Freescale. Signed-off-by: Steffen Trumtrar Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 9 + drivers/crypto/Makefile | 1 + drivers/crypto/mxc-scc.c | 762 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 772 insertions(+) create mode 100644 drivers/crypto/mxc-scc.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 8c141f01f29c..0a22ac7db360 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -340,6 +340,15 @@ config CRYPTO_DEV_SAHARA This option enables support for the SAHARA HW crypto accelerator found in some Freescale i.MX chips. +config CRYPTO_DEV_MXC_SCC + tristate "Support for Freescale Security Controller (SCC)" + depends on ARCH_MXC && OF + select CRYPTO_BLKCIPHER + select CRYPTO_DES + help + This option enables support for the Security Controller (SCC) + found in Freescale i.MX25 chips. + config CRYPTO_DEV_S5P tristate "Support for Samsung S5PV210/Exynos crypto accelerator" depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 713de9d11148..3c6432dd09d9 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o +obj-$(CONFIG_CRYPTO_DEV_MXC_SCC) += mxc-scc.o obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/ diff --git a/drivers/crypto/mxc-scc.c b/drivers/crypto/mxc-scc.c new file mode 100644 index 000000000000..38b01bf141d3 --- /dev/null +++ b/drivers/crypto/mxc-scc.c @@ -0,0 +1,762 @@ +/* + * Copyright (C) 2016 Pengutronix, Steffen Trumtrar + * + * The driver is based on information gathered from + * drivers/mxc/security/mxc_scc.c which can be found in + * the Freescale linux-2.6-imx.git in the imx_2.6.35_maintain branch. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Secure Memory (SCM) registers */ +#define SCC_SCM_RED_START 0x0000 +#define SCC_SCM_BLACK_START 0x0004 +#define SCC_SCM_LENGTH 0x0008 +#define SCC_SCM_CTRL 0x000C +#define SCC_SCM_STATUS 0x0010 +#define SCC_SCM_ERROR_STATUS 0x0014 +#define SCC_SCM_INTR_CTRL 0x0018 +#define SCC_SCM_CFG 0x001C +#define SCC_SCM_INIT_VECTOR_0 0x0020 +#define SCC_SCM_INIT_VECTOR_1 0x0024 +#define SCC_SCM_RED_MEMORY 0x0400 +#define SCC_SCM_BLACK_MEMORY 0x0800 + +/* Security Monitor (SMN) Registers */ +#define SCC_SMN_STATUS 0x1000 +#define SCC_SMN_COMMAND 0x1004 +#define SCC_SMN_SEQ_START 0x1008 +#define SCC_SMN_SEQ_END 0x100C +#define SCC_SMN_SEQ_CHECK 0x1010 +#define SCC_SMN_BIT_COUNT 0x1014 +#define SCC_SMN_BITBANK_INC_SIZE 0x1018 +#define SCC_SMN_BITBANK_DECREMENT 0x101C +#define SCC_SMN_COMPARE_SIZE 0x1020 +#define SCC_SMN_PLAINTEXT_CHECK 0x1024 +#define SCC_SMN_CIPHERTEXT_CHECK 0x1028 +#define SCC_SMN_TIMER_IV 0x102C +#define SCC_SMN_TIMER_CONTROL 0x1030 +#define SCC_SMN_DEBUG_DETECT_STAT 0x1034 +#define SCC_SMN_TIMER 0x1038 + +#define SCC_SCM_CTRL_START_CIPHER BIT(2) +#define SCC_SCM_CTRL_CBC_MODE BIT(1) +#define SCC_SCM_CTRL_DECRYPT_MODE BIT(0) + +#define SCC_SCM_STATUS_LEN_ERR BIT(12) +#define SCC_SCM_STATUS_SMN_UNBLOCKED BIT(11) +#define SCC_SCM_STATUS_CIPHERING_DONE BIT(10) +#define SCC_SCM_STATUS_ZEROIZING_DONE BIT(9) +#define SCC_SCM_STATUS_INTR_STATUS BIT(8) +#define SCC_SCM_STATUS_SEC_KEY BIT(7) +#define SCC_SCM_STATUS_INTERNAL_ERR BIT(6) +#define SCC_SCM_STATUS_BAD_SEC_KEY BIT(5) +#define SCC_SCM_STATUS_ZEROIZE_FAIL BIT(4) +#define SCC_SCM_STATUS_SMN_BLOCKED BIT(3) +#define SCC_SCM_STATUS_CIPHERING BIT(2) +#define SCC_SCM_STATUS_ZEROIZING BIT(1) +#define SCC_SCM_STATUS_BUSY BIT(0) + +#define SCC_SMN_STATUS_STATE_MASK 0x0000001F +#define SCC_SMN_STATE_START 0x0 +/* The SMN is zeroizing its RAM during reset */ +#define SCC_SMN_STATE_ZEROIZE_RAM 0x5 +/* SMN has passed internal checks */ +#define SCC_SMN_STATE_HEALTH_CHECK 0x6 +/* Fatal Security Violation. SMN is locked, SCM is inoperative. */ +#define SCC_SMN_STATE_FAIL 0x9 +/* SCC is in secure state. SCM is using secret key. */ +#define SCC_SMN_STATE_SECURE 0xA +/* SCC is not secure. SCM is using default key. */ +#define SCC_SMN_STATE_NON_SECURE 0xC + +#define SCC_SCM_INTR_CTRL_ZEROIZE_MEM BIT(2) +#define SCC_SCM_INTR_CTRL_CLR_INTR BIT(1) +#define SCC_SCM_INTR_CTRL_MASK_INTR BIT(0) + +/* Size, in blocks, of Red memory. */ +#define SCC_SCM_CFG_BLACK_SIZE_MASK 0x07fe0000 +#define SCC_SCM_CFG_BLACK_SIZE_SHIFT 17 +/* Size, in blocks, of Black memory. */ +#define SCC_SCM_CFG_RED_SIZE_MASK 0x0001ff80 +#define SCC_SCM_CFG_RED_SIZE_SHIFT 7 +/* Number of bytes per block. */ +#define SCC_SCM_CFG_BLOCK_SIZE_MASK 0x0000007f + +#define SCC_SMN_COMMAND_TAMPER_LOCK BIT(4) +#define SCC_SMN_COMMAND_CLR_INTR BIT(3) +#define SCC_SMN_COMMAND_CLR_BIT_BANK BIT(2) +#define SCC_SMN_COMMAND_EN_INTR BIT(1) +#define SCC_SMN_COMMAND_SET_SOFTWARE_ALARM BIT(0) + +#define SCC_KEY_SLOTS 20 +#define SCC_MAX_KEY_SIZE 32 +#define SCC_KEY_SLOT_SIZE 32 + +#define SCC_CRC_CCITT_START 0xFFFF + +/* + * Offset into each RAM of the base of the area which is not + * used for Stored Keys. + */ +#define SCC_NON_RESERVED_OFFSET (SCC_KEY_SLOTS * SCC_KEY_SLOT_SIZE) + +/* Fixed padding for appending to plaintext to fill out a block */ +static char scc_block_padding[8] = { 0x80, 0, 0, 0, 0, 0, 0, 0 }; + +enum mxc_scc_state { + SCC_STATE_OK, + SCC_STATE_UNIMPLEMENTED, + SCC_STATE_FAILED +}; + +struct mxc_scc { + struct device *dev; + void __iomem *base; + struct clk *clk; + bool hw_busy; + spinlock_t lock; + struct crypto_queue queue; + struct crypto_async_request *req; + int block_size_bytes; + int black_ram_size_blocks; + int memory_size_bytes; + int bytes_remaining; + + void __iomem *red_memory; + void __iomem *black_memory; +}; + +struct mxc_scc_ctx { + struct mxc_scc *scc; + struct scatterlist *sg_src; + size_t src_nents; + struct scatterlist *sg_dst; + size_t dst_nents; + unsigned int offset; + unsigned int size; + unsigned int ctrl; +}; + +struct mxc_scc_crypto_tmpl { + struct mxc_scc *scc; + struct crypto_alg alg; +}; + +static int mxc_scc_get_data(struct mxc_scc_ctx *ctx, + struct crypto_async_request *req) +{ + struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req); + struct mxc_scc *scc = ctx->scc; + size_t len; + void __iomem *from; + + if (ctx->ctrl & SCC_SCM_CTRL_DECRYPT_MODE) + from = scc->red_memory; + else + from = scc->black_memory; + + dev_dbg(scc->dev, "pcopy: from 0x%p %d bytes\n", from, + ctx->dst_nents * 8); + len = sg_pcopy_from_buffer(ablkreq->dst, ctx->dst_nents, + from, ctx->size, ctx->offset); + if (!len) { + dev_err(scc->dev, "pcopy err from 0x%p (len=%d)\n", from, len); + return -EINVAL; + } + +#ifdef DEBUG + print_hex_dump(KERN_ERR, + "red memory@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, + scc->red_memory, ctx->size, 1); + print_hex_dump(KERN_ERR, + "black memory@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, + scc->black_memory, ctx->size, 1); +#endif + + ctx->offset += len; + + if (ctx->offset < ablkreq->nbytes) + return -EINPROGRESS; + + return 0; +} + +static int mxc_scc_ablkcipher_req_init(struct ablkcipher_request *req, + struct mxc_scc_ctx *ctx) +{ + struct mxc_scc *scc = ctx->scc; + + ctx->src_nents = sg_nents_for_len(req->src, req->nbytes); + if (ctx->src_nents < 0) { + dev_err(scc->dev, "Invalid number of src SC"); + return ctx->src_nents; + } + + ctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes); + if (ctx->dst_nents < 0) { + dev_err(scc->dev, "Invalid number of dst SC"); + return ctx->dst_nents; + } + + ctx->size = 0; + ctx->offset = 0; + + return 0; +} + +static int mxc_scc_ablkcipher_req_complete(struct crypto_async_request *req, + struct mxc_scc_ctx *ctx, + int result) +{ + struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req); + struct mxc_scc *scc = ctx->scc; + + scc->req = NULL; + scc->bytes_remaining = scc->memory_size_bytes; + + if (ctx->ctrl & SCC_SCM_CTRL_CBC_MODE) + memcpy(ablkreq->info, scc->base + SCC_SCM_INIT_VECTOR_0, + scc->block_size_bytes); + + req->complete(req, result); + scc->hw_busy = false; + + return 0; +} + +static int mxc_scc_put_data(struct mxc_scc_ctx *ctx, + struct ablkcipher_request *req) +{ + u8 padding_buffer[sizeof(u16) + sizeof(scc_block_padding)]; + size_t len = min_t(size_t, req->nbytes - ctx->offset, + ctx->scc->bytes_remaining); + unsigned int padding_byte_count = 0; + struct mxc_scc *scc = ctx->scc; + void __iomem *to; + + if (ctx->ctrl & SCC_SCM_CTRL_DECRYPT_MODE) + to = scc->black_memory; + else + to = scc->red_memory; + + if (ctx->ctrl & SCC_SCM_CTRL_CBC_MODE && req->info) + memcpy(scc->base + SCC_SCM_INIT_VECTOR_0, req->info, + scc->block_size_bytes); + + len = sg_pcopy_to_buffer(req->src, ctx->src_nents, + to, len, ctx->offset); + if (!len) { + dev_err(scc->dev, "pcopy err to 0x%p (len=%d)\n", to, len); + return -EINVAL; + } + + ctx->size = len; + +#ifdef DEBUG + dev_dbg(scc->dev, "copied %d bytes to 0x%p\n", len, to); + print_hex_dump(KERN_ERR, + "init vector0@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, + scc->base + SCC_SCM_INIT_VECTOR_0, scc->block_size_bytes, + 1); + print_hex_dump(KERN_ERR, + "red memory@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, + scc->red_memory, ctx->size, 1); + print_hex_dump(KERN_ERR, + "black memory@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, + scc->black_memory, ctx->size, 1); +#endif + + scc->bytes_remaining -= len; + + padding_byte_count = len % scc->block_size_bytes; + + if (padding_byte_count) { + memcpy(padding_buffer, scc_block_padding, padding_byte_count); + memcpy(to + len, padding_buffer, padding_byte_count); + ctx->size += padding_byte_count; + } + +#ifdef DEBUG + print_hex_dump(KERN_ERR, + "data to encrypt@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, + to, ctx->size, 1); +#endif + + return 0; +} + +static void mxc_scc_ablkcipher_next(struct mxc_scc_ctx *ctx, + struct crypto_async_request *req) +{ + struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req); + struct mxc_scc *scc = ctx->scc; + int err; + + dev_dbg(scc->dev, "dispatch request (nbytes=%d, src=%p, dst=%p)\n", + ablkreq->nbytes, ablkreq->src, ablkreq->dst); + + writel(0, scc->base + SCC_SCM_ERROR_STATUS); + + err = mxc_scc_put_data(ctx, ablkreq); + if (err) { + mxc_scc_ablkcipher_req_complete(req, ctx, err); + return; + } + + dev_dbg(scc->dev, "Start encryption (0x%p/0x%p)\n", + (void *)readl(scc->base + SCC_SCM_RED_START), + (void *)readl(scc->base + SCC_SCM_BLACK_START)); + + /* clear interrupt control registers */ + writel(SCC_SCM_INTR_CTRL_CLR_INTR, + scc->base + SCC_SCM_INTR_CTRL); + + writel((ctx->size / ctx->scc->block_size_bytes) - 1, + scc->base + SCC_SCM_LENGTH); + + dev_dbg(scc->dev, "Process %d block(s) in 0x%p\n", + ctx->size / ctx->scc->block_size_bytes, + (ctx->ctrl & SCC_SCM_CTRL_DECRYPT_MODE) ? scc->black_memory : + scc->red_memory); + + writel(ctx->ctrl, scc->base + SCC_SCM_CTRL); +} + +static irqreturn_t mxc_scc_int(int irq, void *priv) +{ + struct crypto_async_request *req; + struct mxc_scc_ctx *ctx; + struct mxc_scc *scc = priv; + int status; + int ret; + + status = readl(scc->base + SCC_SCM_STATUS); + + /* clear interrupt control registers */ + writel(SCC_SCM_INTR_CTRL_CLR_INTR, scc->base + SCC_SCM_INTR_CTRL); + + if (status & SCC_SCM_STATUS_BUSY) + return IRQ_NONE; + + req = scc->req; + if (req) { + ctx = crypto_tfm_ctx(req->tfm); + ret = mxc_scc_get_data(ctx, req); + if (ret != -EINPROGRESS) + mxc_scc_ablkcipher_req_complete(req, ctx, ret); + else + mxc_scc_ablkcipher_next(ctx, req); + } + + return IRQ_HANDLED; +} + +static int mxc_scc_cra_init(struct crypto_tfm *tfm) +{ + struct mxc_scc_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_alg *alg = tfm->__crt_alg; + struct mxc_scc_crypto_tmpl *algt; + + algt = container_of(alg, struct mxc_scc_crypto_tmpl, alg); + + ctx->scc = algt->scc; + return 0; +} + +static void mxc_scc_dequeue_req_unlocked(struct mxc_scc_ctx *ctx) +{ + struct crypto_async_request *req, *backlog; + + if (ctx->scc->hw_busy) + return; + + spin_lock_bh(&ctx->scc->lock); + backlog = crypto_get_backlog(&ctx->scc->queue); + req = crypto_dequeue_request(&ctx->scc->queue); + ctx->scc->req = req; + ctx->scc->hw_busy = true; + spin_unlock_bh(&ctx->scc->lock); + + if (!req) + return; + + if (backlog) + backlog->complete(backlog, -EINPROGRESS); + + mxc_scc_ablkcipher_next(ctx, req); +} + +static int mxc_scc_queue_req(struct mxc_scc_ctx *ctx, + struct crypto_async_request *req) +{ + int ret; + + spin_lock_bh(&ctx->scc->lock); + ret = crypto_enqueue_request(&ctx->scc->queue, req); + spin_unlock_bh(&ctx->scc->lock); + + if (ret != -EINPROGRESS) + return ret; + + mxc_scc_dequeue_req_unlocked(ctx); + + return -EINPROGRESS; +} + +static int mxc_scc_des3_op(struct mxc_scc_ctx *ctx, + struct ablkcipher_request *req) +{ + int err; + + err = mxc_scc_ablkcipher_req_init(req, ctx); + if (err) + return err; + + return mxc_scc_queue_req(ctx, &req->base); +} + +static int mxc_scc_ecb_des_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); + struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher); + + ctx->ctrl = SCC_SCM_CTRL_START_CIPHER; + + return mxc_scc_des3_op(ctx, req); +} + +static int mxc_scc_ecb_des_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); + struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher); + + ctx->ctrl = SCC_SCM_CTRL_START_CIPHER; + ctx->ctrl |= SCC_SCM_CTRL_DECRYPT_MODE; + + return mxc_scc_des3_op(ctx, req); +} + +static int mxc_scc_cbc_des_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); + struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher); + + ctx->ctrl = SCC_SCM_CTRL_START_CIPHER; + ctx->ctrl |= SCC_SCM_CTRL_CBC_MODE; + + return mxc_scc_des3_op(ctx, req); +} + +static int mxc_scc_cbc_des_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req); + struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher); + + ctx->ctrl = SCC_SCM_CTRL_START_CIPHER; + ctx->ctrl |= SCC_SCM_CTRL_CBC_MODE; + ctx->ctrl |= SCC_SCM_CTRL_DECRYPT_MODE; + + return mxc_scc_des3_op(ctx, req); +} + +static void mxc_scc_hw_init(struct mxc_scc *scc) +{ + int offset; + + offset = SCC_NON_RESERVED_OFFSET / scc->block_size_bytes; + + /* Fill the RED_START register */ + writel(offset, scc->base + SCC_SCM_RED_START); + + /* Fill the BLACK_START register */ + writel(offset, scc->base + SCC_SCM_BLACK_START); + + scc->red_memory = scc->base + SCC_SCM_RED_MEMORY + + SCC_NON_RESERVED_OFFSET; + + scc->black_memory = scc->base + SCC_SCM_BLACK_MEMORY + + SCC_NON_RESERVED_OFFSET; + + scc->bytes_remaining = scc->memory_size_bytes; +} + +static int mxc_scc_get_config(struct mxc_scc *scc) +{ + int config; + + config = readl(scc->base + SCC_SCM_CFG); + + scc->block_size_bytes = config & SCC_SCM_CFG_BLOCK_SIZE_MASK; + + scc->black_ram_size_blocks = config & SCC_SCM_CFG_BLACK_SIZE_MASK; + + scc->memory_size_bytes = (scc->block_size_bytes * + scc->black_ram_size_blocks) - + SCC_NON_RESERVED_OFFSET; + + return 0; +} + +static enum mxc_scc_state mxc_scc_get_state(struct mxc_scc *scc) +{ + enum mxc_scc_state state; + int status; + + status = readl(scc->base + SCC_SMN_STATUS) & + SCC_SMN_STATUS_STATE_MASK; + + /* If in Health Check, try to bringup to secure state */ + if (status & SCC_SMN_STATE_HEALTH_CHECK) { + /* + * Write a simple algorithm to the Algorithm Sequence + * Checker (ASC) + */ + writel(0xaaaa, scc->base + SCC_SMN_SEQ_START); + writel(0x5555, scc->base + SCC_SMN_SEQ_END); + writel(0x5555, scc->base + SCC_SMN_SEQ_CHECK); + + status = readl(scc->base + SCC_SMN_STATUS) & + SCC_SMN_STATUS_STATE_MASK; + } + + switch (status) { + case SCC_SMN_STATE_NON_SECURE: + case SCC_SMN_STATE_SECURE: + state = SCC_STATE_OK; + break; + case SCC_SMN_STATE_FAIL: + state = SCC_STATE_FAILED; + break; + default: + state = SCC_STATE_UNIMPLEMENTED; + break; + } + + return state; +} + +static struct mxc_scc_crypto_tmpl scc_ecb_des = { + .alg = { + .cra_name = "ecb(des3_ede)", + .cra_driver_name = "ecb-des3-scc", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct mxc_scc_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = mxc_scc_cra_init, + .cra_u.ablkcipher = { + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .encrypt = mxc_scc_ecb_des_encrypt, + .decrypt = mxc_scc_ecb_des_decrypt, + } + } +}; + +static struct mxc_scc_crypto_tmpl scc_cbc_des = { + .alg = { + .cra_name = "cbc(des3_ede)", + .cra_driver_name = "cbc-des3-scc", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct mxc_scc_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = mxc_scc_cra_init, + .cra_u.ablkcipher = { + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .encrypt = mxc_scc_cbc_des_encrypt, + .decrypt = mxc_scc_cbc_des_decrypt, + } + } +}; + +static struct mxc_scc_crypto_tmpl *scc_crypto_algs[] = { + &scc_ecb_des, + &scc_cbc_des, +}; + +static int mxc_scc_crypto_register(struct mxc_scc *scc) +{ + unsigned int i; + int err = 0; + + for (i = 0; i < ARRAY_SIZE(scc_crypto_algs); i++) { + scc_crypto_algs[i]->scc = scc; + err = crypto_register_alg(&scc_crypto_algs[i]->alg); + if (err) + goto err_out; + } + + return 0; + +err_out: + for (; i > 0; i--) + crypto_unregister_alg(&scc_crypto_algs[i]->alg); + + return err; +} + +static void mxc_scc_crypto_unregister(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(scc_crypto_algs); i++) + crypto_unregister_alg(&scc_crypto_algs[i]->alg); +} + +static int mxc_scc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct mxc_scc *scc; + enum mxc_scc_state state; + int irq; + int ret; + int i; + + scc = devm_kzalloc(dev, sizeof(*scc), GFP_KERNEL); + if (!scc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + scc->base = devm_ioremap_resource(dev, res); + if (IS_ERR(scc->base)) + return PTR_ERR(scc->base); + + scc->clk = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(scc->clk)) { + dev_err(dev, "Could not get ipg clock\n"); + return PTR_ERR(scc->clk); + } + + clk_prepare_enable(scc->clk); + + /* clear error status register */ + writel(0x0, scc->base + SCC_SCM_ERROR_STATUS); + + /* clear interrupt control registers */ + writel(SCC_SCM_INTR_CTRL_CLR_INTR | + SCC_SCM_INTR_CTRL_MASK_INTR, + scc->base + SCC_SCM_INTR_CTRL); + + writel(SCC_SMN_COMMAND_CLR_INTR | + SCC_SMN_COMMAND_EN_INTR, + scc->base + SCC_SMN_COMMAND); + + scc->dev = dev; + platform_set_drvdata(pdev, scc); + + ret = mxc_scc_get_config(scc); + if (ret) + goto err_out; + + state = mxc_scc_get_state(scc); + + if (state != SCC_STATE_OK) { + dev_err(dev, "SCC in unusable state %d\n", state); + ret = -EINVAL; + goto err_out; + } + + mxc_scc_hw_init(scc); + + spin_lock_init(&scc->lock); + /* FIXME: calculate queue from RAM slots */ + crypto_init_queue(&scc->queue, 50); + + for (i = 0; i < 2; i++) { + irq = platform_get_irq(pdev, i); + if (irq < 0) { + dev_err(dev, "failed to get irq resource\n"); + ret = -EINVAL; + goto err_out; + } + + ret = devm_request_threaded_irq(dev, irq, NULL, mxc_scc_int, + IRQF_ONESHOT, dev_name(dev), scc); + if (ret) + goto err_out; + } + + ret = mxc_scc_crypto_register(scc); + if (ret) { + dev_err(dev, "could not register algorithms"); + goto err_out; + } + + dev_info(dev, "registered successfully.\n"); + + return 0; + +err_out: + clk_disable_unprepare(scc->clk); + + return ret; +} + +static int mxc_scc_remove(struct platform_device *pdev) +{ + struct mxc_scc *scc = platform_get_drvdata(pdev); + + mxc_scc_crypto_unregister(); + + clk_disable_unprepare(scc->clk); + + return 0; +} + +static const struct of_device_id mxc_scc_dt_ids[] = { + { .compatible = "fsl,imx25-scc", .data = NULL, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxc_scc_dt_ids); + +static struct platform_driver mxc_scc_driver = { + .probe = mxc_scc_probe, + .remove = mxc_scc_remove, + .driver = { + .name = "mxc-scc", + .of_match_table = mxc_scc_dt_ids, + }, +}; + +module_platform_driver(mxc_scc_driver); +MODULE_AUTHOR("Steffen Trumtrar "); +MODULE_DESCRIPTION("Freescale i.MX25 SCC Crypto driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From c7995ee7ff60c1973a3a63e35b41c2393f47f760 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Wed, 13 Apr 2016 18:11:27 +0800 Subject: [PATCH 2901/9938] dt/bindings: Add bindings for hisilicon random number generator Document the devicetree bindings for the random number generator found on Hisilicon Hip04 and Hip05 soc. Signed-off-by: Kefeng Wang Acked-by: Rob Herring Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/rng/hisi-rng.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Documentation/devicetree/bindings/rng/hisi-rng.txt diff --git a/Documentation/devicetree/bindings/rng/hisi-rng.txt b/Documentation/devicetree/bindings/rng/hisi-rng.txt new file mode 100644 index 000000000000..d04d55a6c2f5 --- /dev/null +++ b/Documentation/devicetree/bindings/rng/hisi-rng.txt @@ -0,0 +1,12 @@ +Hisilicon Random Number Generator + +Required properties: +- compatible : Should be "hisilicon,hip04-rng" or "hisilicon,hip05-rng" +- reg : Offset and length of the register set of this block + +Example: + +rng@d1010000 { + compatible = "hisilicon,hip05-rng"; + reg = <0xd1010000 0x100>; +}; -- GitLab From afc39d6e89b4f410f511f03dc6de8dc1d4952d42 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Wed, 13 Apr 2016 18:11:28 +0800 Subject: [PATCH 2902/9938] hwrng: hisi - Add support for Hisilicon SoC RNG This adds the Hisilicon Random Number Generator(RNG) support, which is found in Hip04 and Hip05 soc. Reviewed-by: Mathieu Poirier Signed-off-by: Kefeng Wang Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 13 +++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/hisi-rng.c | 126 ++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 drivers/char/hw_random/hisi-rng.c diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 3c5be60befce..c76a88da8d04 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -334,6 +334,19 @@ config HW_RANDOM_TPM If unsure, say Y. +config HW_RANDOM_HISI + tristate "Hisilicon Random Number Generator support" + depends on HW_RANDOM && ARCH_HISI + default HW_RANDOM + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on Hisilicon Hip04 and Hip05 SoC. + + To compile this driver as a module, choose M here: the + module will be called hisi-rng. + + If unsure, say Y. + config HW_RANDOM_MSM tristate "Qualcomm SoCs Random Number Generator support" depends on HW_RANDOM && ARCH_QCOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index f5a6fa7690e7..e09305bb89e1 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o +obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o diff --git a/drivers/char/hw_random/hisi-rng.c b/drivers/char/hw_random/hisi-rng.c new file mode 100644 index 000000000000..40d96572c591 --- /dev/null +++ b/drivers/char/hw_random/hisi-rng.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016 HiSilicon Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RNG_SEED 0x0 +#define RNG_CTRL 0x4 + #define RNG_SEED_SEL BIT(2) + #define RNG_RING_EN BIT(1) + #define RNG_EN BIT(0) +#define RNG_RAN_NUM 0x10 +#define RNG_PHY_SEED 0x14 + +#define to_hisi_rng(p) container_of(p, struct hisi_rng, rng) + +static int seed_sel; +module_param(seed_sel, int, S_IRUGO); +MODULE_PARM_DESC(seed_sel, "Auto reload seed. 0, use LFSR(default); 1, use ring oscillator."); + +struct hisi_rng { + void __iomem *base; + struct hwrng rng; +}; + +static int hisi_rng_init(struct hwrng *rng) +{ + struct hisi_rng *hrng = to_hisi_rng(rng); + int val = RNG_EN; + u32 seed; + + /* get a random number as initial seed */ + get_random_bytes(&seed, sizeof(seed)); + + writel_relaxed(seed, hrng->base + RNG_SEED); + + /** + * The seed is reload periodically, there are two choice + * of seeds, default seed using the value from LFSR, or + * will use seed generated by ring oscillator. + */ + if (seed_sel == 1) + val |= RNG_RING_EN | RNG_SEED_SEL; + + writel_relaxed(val, hrng->base + RNG_CTRL); + return 0; +} + +static void hisi_rng_cleanup(struct hwrng *rng) +{ + struct hisi_rng *hrng = to_hisi_rng(rng); + + writel_relaxed(0, hrng->base + RNG_CTRL); +} + +static int hisi_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) +{ + struct hisi_rng *hrng = to_hisi_rng(rng); + u32 *data = buf; + + *data = readl_relaxed(hrng->base + RNG_RAN_NUM); + return 4; +} + +static int hisi_rng_probe(struct platform_device *pdev) +{ + struct hisi_rng *rng; + struct resource *res; + int ret; + + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); + if (!rng) + return -ENOMEM; + + platform_set_drvdata(pdev, rng); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rng->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rng->base)) + return PTR_ERR(rng->base); + + rng->rng.name = pdev->name; + rng->rng.init = hisi_rng_init; + rng->rng.cleanup = hisi_rng_cleanup; + rng->rng.read = hisi_rng_read; + + ret = devm_hwrng_register(&pdev->dev, &rng->rng); + if (ret) { + dev_err(&pdev->dev, "failed to register hwrng\n"); + return ret; + } + + return 0; +} + +static const struct of_device_id hisi_rng_dt_ids[] = { + { .compatible = "hisilicon,hip04-rng" }, + { .compatible = "hisilicon,hip05-rng" }, + { } +}; +MODULE_DEVICE_TABLE(of, hisi_rng_dt_ids); + +static struct platform_driver hisi_rng_driver = { + .probe = hisi_rng_probe, + .driver = { + .name = "hisi-rng", + .of_match_table = of_match_ptr(hisi_rng_dt_ids), + }, +}; + +module_platform_driver(hisi_rng_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kefeng Wang "); +MODULE_DESCRIPTION("Hisilicon random number generator driver"); -- GitLab From 5f575efea79caae69b81f922d99b221302a2c003 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 14 Apr 2016 10:51:42 +0200 Subject: [PATCH 2903/9938] crypto: lzo - get rid of superfluous __GFP_REPEAT __GFP_REPEAT has a rather weak semantic but since it has been introduced around 2.6.12 it has been ignored for low order allocations. lzo_init uses __GFP_REPEAT to allocate LZO1X_MEM_COMPRESS 16K. This is order 3 allocation request and __GFP_REPEAT is ignored for this size as well as all <= PAGE_ALLOC_COSTLY requests. Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Michal Hocko Signed-off-by: Herbert Xu --- crypto/lzo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/lzo.c b/crypto/lzo.c index 4b3e92525dac..c3f3dd9a28c5 100644 --- a/crypto/lzo.c +++ b/crypto/lzo.c @@ -32,7 +32,7 @@ static int lzo_init(struct crypto_tfm *tfm) struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS, - GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); + GFP_KERNEL | __GFP_NOWARN); if (!ctx->lzo_comp_mem) ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS); if (!ctx->lzo_comp_mem) -- GitLab From 6da3aba6f056b861c9f54ef104425ceb5e9389ad Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 13 Apr 2016 07:55:37 +0800 Subject: [PATCH 2904/9938] arm64: dts: Reserve memory regions for hi6220 On Hi6220, below memory regions in DDR have specific purpose: 0x05e0,0000 - 0x05ef,ffff: For MCU firmware using at runtime; 0x06df,f000 - 0x06df,ffff: For mailbox message data; 0x0740,f000 - 0x0740,ffff: For MCU firmware's section; 0x3e00,0000 - 0x3fff,ffff: For OP-TEE. This patch reserves these memory regions in DT. Signed-off-by: Leo Yan Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 818525197508..17bd7932260f 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -7,9 +7,6 @@ /dts-v1/; -/*Reserved 1MB memory for MCU*/ -/memreserve/ 0x05e00000 0x00100000; - #include "hi6220.dtsi" / { @@ -27,9 +24,20 @@ stdout-path = "serial3:115200n8"; }; + /* + * Reserve below regions from memory node: + * + * 0x05e0,0000 - 0x05ef,ffff: MCU firmware runtime using + * 0x06df,f000 - 0x06df,ffff: Mailbox message data + * 0x0740,f000 - 0x0740,ffff: MCU firmware section + * 0x3e00,0000 - 0x3fff,ffff: OP-TEE + */ memory@0 { device_type = "memory"; - reg = <0x0 0x0 0x0 0x40000000>; + reg = <0x00000000 0x00000000 0x00000000 0x05e00000>, + <0x00000000 0x05f00000 0x00000000 0x00eff000>, + <0x00000000 0x06e00000 0x00000000 0x0060f000>, + <0x00000000 0x07410000 0x00000000 0x36bf0000>; }; }; -- GitLab From 9e92703165d982b3df35e551c4d15a93ab9fba3d Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 13 Apr 2016 07:55:38 +0800 Subject: [PATCH 2905/9938] arm64: dts: add sp804 timer node for Hi6220 Add sp804 timer for hi6220, so it can be used as broadcast timer. Signed-off-by: Leo Yan Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index ad1f1ebcb05c..b975286195ce 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -209,5 +209,16 @@ clock-names = "uartclk", "apb_pclk"; status = "disabled"; }; + + dual_timer0: timer@f8008000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x0 0xf8008000 0x0 0x1000>; + interrupts = , + ; + clocks = <&ao_ctrl HI6220_TIMER0_PCLK>, + <&ao_ctrl HI6220_TIMER0_PCLK>, + <&ao_ctrl HI6220_TIMER0_PCLK>; + clock-names = "timer1", "timer2", "apb_pclk"; + }; }; }; -- GitLab From 58fa29bfbe5e908e0f5d2627c5f15001696b1666 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 13 Apr 2016 07:55:39 +0800 Subject: [PATCH 2906/9938] arm64: dts: enable idle states for Hi6220 Add cpu and cluster level's low power state for Hi6220. Acked-by: Sudeep Holla Signed-off-by: Leo Yan Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index b975286195ce..dc7f21a1eed4 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -53,11 +53,35 @@ }; }; + idle-states { + entry-method = "psci"; + + CPU_SLEEP: cpu-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <700>; + exit-latency-us = <250>; + min-residency-us = <1000>; + }; + + CLUSTER_SLEEP: cluster-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <1000>; + exit-latency-us = <700>; + min-residency-us = <2700>; + wakeup-latency-us = <1500>; + }; + }; + cpu0: cpu@0 { compatible = "arm,cortex-a53", "arm,armv8"; device_type = "cpu"; reg = <0x0 0x0>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu1: cpu@1 { @@ -65,6 +89,7 @@ device_type = "cpu"; reg = <0x0 0x1>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu2: cpu@2 { @@ -72,6 +97,7 @@ device_type = "cpu"; reg = <0x0 0x2>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu3: cpu@3 { @@ -79,6 +105,7 @@ device_type = "cpu"; reg = <0x0 0x3>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu4: cpu@100 { @@ -86,6 +113,7 @@ device_type = "cpu"; reg = <0x0 0x100>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu5: cpu@101 { @@ -93,6 +121,7 @@ device_type = "cpu"; reg = <0x0 0x101>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu6: cpu@102 { @@ -100,6 +129,7 @@ device_type = "cpu"; reg = <0x0 0x102>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu7: cpu@103 { @@ -107,6 +137,7 @@ device_type = "cpu"; reg = <0x0 0x103>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; }; -- GitLab From 4d88d5a7bf92e31215543b955b8883dcf6f66c1f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 15 Apr 2016 17:51:06 +0300 Subject: [PATCH 2907/9938] PCI: acpiphp_ibm: Avoid uninitialized variable reference If ibm_get_table_from_acpi() fails then "table" isn't initialized. Check for failure so we don't reference "table" unless it's been initialized. Signed-off-by: Dan Carpenter Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/acpiphp_ibm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 2f6d3a1c1726..f6221d739f59 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -138,6 +138,8 @@ static union apci_descriptor *ibm_slot_from_id(int id) char *table; size = ibm_get_table_from_acpi(&table); + if (size < 0) + return NULL; des = (union apci_descriptor *)table; if (memcmp(des->header.sig, "aPCI", 4) != 0) goto ibm_slot_done; -- GitLab From f2bfacf9ddcff49103c08ee7e83bf3fffe6e37ba Mon Sep 17 00:00:00 2001 From: Zhong Kaihua Date: Wed, 13 Apr 2016 07:55:40 +0800 Subject: [PATCH 2908/9938] arm64: dts: Add Hi6220 gpio configuration nodes Add Hi6220 gpio configuration nodes Signed-off-by: Zhong Kaihua Signed-off-by: Kong Xinwei Signed-off-by: Guodong Xu Reviewed-by: Linus Walleij Acked-by: Rob Herring Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 239 ++++++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index dc7f21a1eed4..493bbb032ae0 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -251,5 +251,244 @@ <&ao_ctrl HI6220_TIMER0_PCLK>; clock-names = "timer1", "timer2", "apb_pclk"; }; + + gpio0: gpio@f8011000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf8011000 0x0 0x1000>; + interrupts = <0 52 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio1: gpio@f8012000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf8012000 0x0 0x1000>; + interrupts = <0 53 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio2: gpio@f8013000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf8013000 0x0 0x1000>; + interrupts = <0 54 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio3: gpio@f8014000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf8014000 0x0 0x1000>; + interrupts = <0 55 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio4: gpio@f7020000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7020000 0x0 0x1000>; + interrupts = <0 56 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio5: gpio@f7021000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7021000 0x0 0x1000>; + interrupts = <0 57 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio6: gpio@f7022000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7022000 0x0 0x1000>; + interrupts = <0 58 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio7: gpio@f7023000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7023000 0x0 0x1000>; + interrupts = <0 59 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio8: gpio@f7024000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7024000 0x0 0x1000>; + interrupts = <0 60 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio9: gpio@f7025000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7025000 0x0 0x1000>; + interrupts = <0 61 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio10: gpio@f7026000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7026000 0x0 0x1000>; + interrupts = <0 62 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio11: gpio@f7027000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7027000 0x0 0x1000>; + interrupts = <0 63 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio12: gpio@f7028000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7028000 0x0 0x1000>; + interrupts = <0 64 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio13: gpio@f7029000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf7029000 0x0 0x1000>; + interrupts = <0 65 0x4>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio14: gpio@f702a000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf702a000 0x0 0x1000>; + interrupts = <0 66 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio15: gpio@f702b000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf702b000 0x0 0x1000>; + interrupts = <0 67 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio16: gpio@f702c000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf702c000 0x0 0x1000>; + interrupts = <0 68 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio17: gpio@f702d000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf702d000 0x0 0x1000>; + interrupts = <0 69 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio18: gpio@f702e000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf702e000 0x0 0x1000>; + interrupts = <0 70 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; + + gpio19: gpio@f702f000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x0 0xf702f000 0x0 0x1000>; + interrupts = <0 71 0x4>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&ao_ctrl 2>; + clock-names = "apb_pclk"; + }; }; }; -- GitLab From 379e9bf52daaaa841ecc4eed3f2c5c86845c45a9 Mon Sep 17 00:00:00 2001 From: Zhong Kaihua Date: Wed, 13 Apr 2016 07:55:41 +0800 Subject: [PATCH 2909/9938] arm64: dts: add Hi6220 pinctrl configuration nodes Add Hi6220 pinctrl configuration nodes Signed-off-by: Zhong Kaihua Acked-by: Linus Walleij Acked-by: Haojian Zhuang Acked-by: Tony Lindgren Signed-off-by: Wei Xu --- .../arm64/boot/dts/hisilicon/hi6220-hikey.dts | 1 + arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 77 ++ .../boot/dts/hisilicon/hikey-pinctrl.dtsi | 684 ++++++++++++++++++ include/dt-bindings/pinctrl/hisi.h | 59 ++ 4 files changed, 821 insertions(+) create mode 100644 arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi create mode 100644 include/dt-bindings/pinctrl/hisi.h diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 17bd7932260f..3d9e8b2d2b18 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -8,6 +8,7 @@ /dts-v1/; #include "hi6220.dtsi" +#include "hikey-pinctrl.dtsi" / { model = "HiKey Development Board"; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 493bbb032ae0..df56571703b0 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -6,6 +6,7 @@ #include #include +#include / { compatible = "hisilicon,hi6220"; @@ -252,6 +253,60 @@ clock-names = "timer1", "timer2", "apb_pclk"; }; + pmx0: pinmux@f7010000 { + compatible = "pinctrl-single"; + reg = <0x0 0xf7010000 0x0 0x27c>; + #address-cells = <1>; + #size-cells = <1>; + #gpio-range-cells = <3>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <7>; + pinctrl-single,gpio-range = < + &range 80 8 MUX_M0 /* gpio 3: [0..7] */ + &range 88 8 MUX_M0 /* gpio 4: [0..7] */ + &range 96 8 MUX_M0 /* gpio 5: [0..7] */ + &range 104 8 MUX_M0 /* gpio 6: [0..7] */ + &range 112 8 MUX_M0 /* gpio 7: [0..7] */ + &range 120 2 MUX_M0 /* gpio 8: [0..1] */ + &range 2 6 MUX_M1 /* gpio 8: [2..7] */ + &range 8 8 MUX_M1 /* gpio 9: [0..7] */ + &range 0 1 MUX_M1 /* gpio 10: [0] */ + &range 16 7 MUX_M1 /* gpio 10: [1..7] */ + &range 23 3 MUX_M1 /* gpio 11: [0..2] */ + &range 28 5 MUX_M1 /* gpio 11: [3..7] */ + &range 33 3 MUX_M1 /* gpio 12: [0..2] */ + &range 43 5 MUX_M1 /* gpio 12: [3..7] */ + &range 48 8 MUX_M1 /* gpio 13: [0..7] */ + &range 56 8 MUX_M1 /* gpio 14: [0..7] */ + &range 74 6 MUX_M1 /* gpio 15: [0..5] */ + &range 122 1 MUX_M1 /* gpio 15: [6] */ + &range 126 1 MUX_M1 /* gpio 15: [7] */ + &range 127 8 MUX_M1 /* gpio 16: [0..7] */ + &range 135 8 MUX_M1 /* gpio 17: [0..7] */ + &range 143 8 MUX_M1 /* gpio 18: [0..7] */ + &range 151 8 MUX_M1 /* gpio 19: [0..7] */ + >; + range: gpio-range { + #pinctrl-single,gpio-range-cells = <3>; + }; + }; + + pmx1: pinmux@f7010800 { + compatible = "pinconf-single"; + reg = <0x0 0xf7010800 0x0 0x28c>; + #address-cells = <1>; + #size-cells = <1>; + pinctrl-single,register-width = <32>; + }; + + pmx2: pinmux@f8001800 { + compatible = "pinconf-single"; + reg = <0x0 0xf8001800 0x0 0x78>; + #address-cells = <1>; + #size-cells = <1>; + pinctrl-single,register-width = <32>; + }; + gpio0: gpio@f8011000 { compatible = "arm,pl061", "arm,primecell"; reg = <0x0 0xf8011000 0x0 0x1000>; @@ -294,6 +349,7 @@ interrupts = <0 55 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 80 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -306,6 +362,7 @@ interrupts = <0 56 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 88 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -318,6 +375,7 @@ interrupts = <0 57 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 96 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -330,6 +388,7 @@ interrupts = <0 58 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 104 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -342,6 +401,7 @@ interrupts = <0 59 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 112 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -354,6 +414,7 @@ interrupts = <0 60 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 120 2 &pmx0 2 2 6>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -366,6 +427,7 @@ interrupts = <0 61 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 8 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -378,6 +440,7 @@ interrupts = <0 62 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 0 1 &pmx0 1 16 7>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -390,6 +453,7 @@ interrupts = <0 63 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 23 3 &pmx0 3 28 5>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -402,6 +466,7 @@ interrupts = <0 64 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 33 3 &pmx0 3 43 5>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -413,6 +478,8 @@ reg = <0x0 0xf7029000 0x0 0x1000>; interrupts = <0 65 0x4>; gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 48 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -425,6 +492,7 @@ interrupts = <0 66 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 56 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -437,6 +505,11 @@ interrupts = <0 67 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = < + &pmx0 0 74 6 + &pmx0 6 122 1 + &pmx0 7 126 1 + >; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -449,6 +522,7 @@ interrupts = <0 68 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 127 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -461,6 +535,7 @@ interrupts = <0 69 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 135 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -473,6 +548,7 @@ interrupts = <0 70 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 143 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; @@ -485,6 +561,7 @@ interrupts = <0 71 0x4>; gpio-controller; #gpio-cells = <2>; + gpio-ranges = <&pmx0 0 151 8>; interrupt-controller; #interrupt-cells = <2>; clocks = <&ao_ctrl 2>; diff --git a/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi new file mode 100644 index 000000000000..28806df214d7 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi @@ -0,0 +1,684 @@ +/* + * pinctrl dts fils for Hislicon HiKey development board + * + */ +#include + +/ { + soc { + pmx0: pinmux@f7010000 { + pinctrl-names = "default"; + pinctrl-0 = < + &boot_sel_pmx_func + &hkadc_ssi_pmx_func + &codec_clk_pmx_func + &pwm_in_pmx_func + &bl_pwm_pmx_func + >; + + boot_sel_pmx_func: boot_sel_pmx_func { + pinctrl-single,pins = < + 0x0 MUX_M0 /* BOOT_SEL (IOMG000) */ + >; + }; + + emmc_pmx_func: emmc_pmx_func { + pinctrl-single,pins = < + 0x100 MUX_M0 /* EMMC_CLK (IOMG064) */ + 0x104 MUX_M0 /* EMMC_CMD (IOMG065) */ + 0x108 MUX_M0 /* EMMC_DATA0 (IOMG066) */ + 0x10c MUX_M0 /* EMMC_DATA1 (IOMG067) */ + 0x110 MUX_M0 /* EMMC_DATA2 (IOMG068) */ + 0x114 MUX_M0 /* EMMC_DATA3 (IOMG069) */ + 0x118 MUX_M0 /* EMMC_DATA4 (IOMG070) */ + 0x11c MUX_M0 /* EMMC_DATA5 (IOMG071) */ + 0x120 MUX_M0 /* EMMC_DATA6 (IOMG072) */ + 0x124 MUX_M0 /* EMMC_DATA7 (IOMG073) */ + >; + }; + + sd_pmx_func: sd_pmx_func { + pinctrl-single,pins = < + 0xc MUX_M0 /* SD_CLK (IOMG003) */ + 0x10 MUX_M0 /* SD_CMD (IOMG004) */ + 0x14 MUX_M0 /* SD_DATA0 (IOMG005) */ + 0x18 MUX_M0 /* SD_DATA1 (IOMG006) */ + 0x1c MUX_M0 /* SD_DATA2 (IOMG007) */ + 0x20 MUX_M0 /* SD_DATA3 (IOMG008) */ + >; + }; + sd_pmx_idle: sd_pmx_idle { + pinctrl-single,pins = < + 0xc MUX_M1 /* SD_CLK (IOMG003) */ + 0x10 MUX_M1 /* SD_CMD (IOMG004) */ + 0x14 MUX_M1 /* SD_DATA0 (IOMG005) */ + 0x18 MUX_M1 /* SD_DATA1 (IOMG006) */ + 0x1c MUX_M1 /* SD_DATA2 (IOMG007) */ + 0x20 MUX_M1 /* SD_DATA3 (IOMG008) */ + >; + }; + + sdio_pmx_func: sdio_pmx_func { + pinctrl-single,pins = < + 0x128 MUX_M0 /* SDIO_CLK (IOMG074) */ + 0x12c MUX_M0 /* SDIO_CMD (IOMG075) */ + 0x130 MUX_M0 /* SDIO_DATA0 (IOMG076) */ + 0x134 MUX_M0 /* SDIO_DATA1 (IOMG077) */ + 0x138 MUX_M0 /* SDIO_DATA2 (IOMG078) */ + 0x13c MUX_M0 /* SDIO_DATA3 (IOMG079) */ + >; + }; + sdio_pmx_idle: sdio_pmx_idle { + pinctrl-single,pins = < + 0x128 MUX_M1 /* SDIO_CLK (IOMG074) */ + 0x12c MUX_M1 /* SDIO_CMD (IOMG075) */ + 0x130 MUX_M1 /* SDIO_DATA0 (IOMG076) */ + 0x134 MUX_M1 /* SDIO_DATA1 (IOMG077) */ + 0x138 MUX_M1 /* SDIO_DATA2 (IOMG078) */ + 0x13c MUX_M1 /* SDIO_DATA3 (IOMG079) */ + >; + }; + + isp_pmx_func: isp_pmx_func { + pinctrl-single,pins = < + 0x24 MUX_M0 /* ISP_PWDN0 (IOMG009) */ + 0x28 MUX_M0 /* ISP_PWDN1 (IOMG010) */ + 0x2c MUX_M0 /* ISP_PWDN2 (IOMG011) */ + 0x30 MUX_M1 /* ISP_SHUTTER0 (IOMG012) */ + 0x34 MUX_M1 /* ISP_SHUTTER1 (IOMG013) */ + 0x38 MUX_M1 /* ISP_PWM (IOMG014) */ + 0x3c MUX_M0 /* ISP_CCLK0 (IOMG015) */ + 0x40 MUX_M0 /* ISP_CCLK1 (IOMG016) */ + 0x44 MUX_M0 /* ISP_RESETB0 (IOMG017) */ + 0x48 MUX_M0 /* ISP_RESETB1 (IOMG018) */ + 0x4c MUX_M1 /* ISP_STROBE0 (IOMG019) */ + 0x50 MUX_M1 /* ISP_STROBE1 (IOMG020) */ + 0x54 MUX_M0 /* ISP_SDA0 (IOMG021) */ + 0x58 MUX_M0 /* ISP_SCL0 (IOMG022) */ + 0x5c MUX_M0 /* ISP_SDA1 (IOMG023) */ + 0x60 MUX_M0 /* ISP_SCL1 (IOMG024) */ + >; + }; + + hkadc_ssi_pmx_func: hkadc_ssi_pmx_func { + pinctrl-single,pins = < + 0x68 MUX_M0 /* HKADC_SSI (IOMG026) */ + >; + }; + + codec_clk_pmx_func: codec_clk_pmx_func { + pinctrl-single,pins = < + 0x6c MUX_M0 /* CODEC_CLK (IOMG027) */ + >; + }; + + codec_pmx_func: codec_pmx_func { + pinctrl-single,pins = < + 0x70 MUX_M1 /* DMIC_CLK (IOMG028) */ + 0x74 MUX_M0 /* CODEC_SYNC (IOMG029) */ + 0x78 MUX_M0 /* CODEC_DI (IOMG030) */ + 0x7c MUX_M0 /* CODEC_DO (IOMG031) */ + >; + }; + + fm_pmx_func: fm_pmx_func { + pinctrl-single,pins = < + 0x80 MUX_M1 /* FM_XCLK (IOMG032) */ + 0x84 MUX_M1 /* FM_XFS (IOMG033) */ + 0x88 MUX_M1 /* FM_DI (IOMG034) */ + 0x8c MUX_M1 /* FM_DO (IOMG035) */ + >; + }; + + bt_pmx_func: bt_pmx_func { + pinctrl-single,pins = < + 0x90 MUX_M0 /* BT_XCLK (IOMG036) */ + 0x94 MUX_M0 /* BT_XFS (IOMG037) */ + 0x98 MUX_M0 /* BT_DI (IOMG038) */ + 0x9c MUX_M0 /* BT_DO (IOMG039) */ + >; + }; + + pwm_in_pmx_func: pwm_in_pmx_func { + pinctrl-single,pins = < + 0xb8 MUX_M1 /* PWM_IN (IOMG046) */ + >; + }; + + bl_pwm_pmx_func: bl_pwm_pmx_func { + pinctrl-single,pins = < + 0xbc MUX_M1 /* BL_PWM (IOMG047) */ + >; + }; + + uart0_pmx_func: uart0_pmx_func { + pinctrl-single,pins = < + 0xc0 MUX_M0 /* UART0_RXD (IOMG048) */ + 0xc4 MUX_M0 /* UART0_TXD (IOMG049) */ + >; + }; + + uart1_pmx_func: uart1_pmx_func { + pinctrl-single,pins = < + 0xc8 MUX_M0 /* UART1_CTS_N (IOMG050) */ + 0xcc MUX_M0 /* UART1_RTS_N (IOMG051) */ + 0xd0 MUX_M0 /* UART1_RXD (IOMG052) */ + 0xd4 MUX_M0 /* UART1_TXD (IOMG053) */ + >; + }; + + uart2_pmx_func: uart2_pmx_func { + pinctrl-single,pins = < + 0xd8 MUX_M0 /* UART2_CTS_N (IOMG054) */ + 0xdc MUX_M0 /* UART2_RTS_N (IOMG055) */ + 0xe0 MUX_M0 /* UART2_RXD (IOMG056) */ + 0xe4 MUX_M0 /* UART2_TXD (IOMG057) */ + >; + }; + + uart3_pmx_func: uart3_pmx_func { + pinctrl-single,pins = < + 0x180 MUX_M1 /* UART3_CTS_N (IOMG096) */ + 0x184 MUX_M1 /* UART3_RTS_N (IOMG097) */ + 0x188 MUX_M1 /* UART3_RXD (IOMG098) */ + 0x18c MUX_M1 /* UART3_TXD (IOMG099) */ + >; + }; + + uart4_pmx_func: uart4_pmx_func { + pinctrl-single,pins = < + 0x1d0 MUX_M1 /* UART4_CTS_N (IOMG116) */ + 0x1d4 MUX_M1 /* UART4_RTS_N (IOMG117) */ + 0x1d8 MUX_M1 /* UART4_RXD (IOMG118) */ + 0x1dc MUX_M1 /* UART4_TXD (IOMG119) */ + >; + }; + + uart5_pmx_func: uart5_pmx_func { + pinctrl-single,pins = < + 0x1c8 MUX_M1 /* UART5_RXD (IOMG114) */ + 0x1cc MUX_M1 /* UART5_TXD (IOMG115) */ + >; + }; + + i2c0_pmx_func: i2c0_pmx_func { + pinctrl-single,pins = < + 0xe8 MUX_M0 /* I2C0_SCL (IOMG058) */ + 0xec MUX_M0 /* I2C0_SDA (IOMG059) */ + >; + }; + + i2c1_pmx_func: i2c1_pmx_func { + pinctrl-single,pins = < + 0xf0 MUX_M0 /* I2C1_SCL (IOMG060) */ + 0xf4 MUX_M0 /* I2C1_SDA (IOMG061) */ + >; + }; + + i2c2_pmx_func: i2c2_pmx_func { + pinctrl-single,pins = < + 0xf8 MUX_M0 /* I2C2_SCL (IOMG062) */ + 0xfc MUX_M0 /* I2C2_SDA (IOMG063) */ + >; + }; + }; + + pmx1: pinmux@f7010800 { + + pinctrl-names = "default"; + pinctrl-0 = < + &boot_sel_cfg_func + &hkadc_ssi_cfg_func + &codec_clk_cfg_func + &pwm_in_cfg_func + &bl_pwm_cfg_func + >; + + boot_sel_cfg_func: boot_sel_cfg_func { + pinctrl-single,pins = < + 0x0 0x0 /* BOOT_SEL (IOCFG000) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + hkadc_ssi_cfg_func: hkadc_ssi_cfg_func { + pinctrl-single,pins = < + 0x6c 0x0 /* HKADC_SSI (IOCFG027) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + emmc_clk_cfg_func: emmc_clk_cfg_func { + pinctrl-single,pins = < + 0x104 0x0 /* EMMC_CLK (IOCFG065) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + emmc_cfg_func: emmc_cfg_func { + pinctrl-single,pins = < + 0x108 0x0 /* EMMC_CMD (IOCFG066) */ + 0x10c 0x0 /* EMMC_DATA0 (IOCFG067) */ + 0x110 0x0 /* EMMC_DATA1 (IOCFG068) */ + 0x114 0x0 /* EMMC_DATA2 (IOCFG069) */ + 0x118 0x0 /* EMMC_DATA3 (IOCFG070) */ + 0x11c 0x0 /* EMMC_DATA4 (IOCFG071) */ + 0x120 0x0 /* EMMC_DATA5 (IOCFG072) */ + 0x124 0x0 /* EMMC_DATA6 (IOCFG073) */ + 0x128 0x0 /* EMMC_DATA7 (IOCFG074) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + emmc_rst_cfg_func: emmc_rst_cfg_func { + pinctrl-single,pins = < + 0x12c 0x0 /* EMMC_RST_N (IOCFG075) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + sd_clk_cfg_func: sd_clk_cfg_func { + pinctrl-single,pins = < + 0xc 0x0 /* SD_CLK (IOCFG003) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + sd_clk_cfg_idle: sd_clk_cfg_idle { + pinctrl-single,pins = < + 0xc 0x0 /* SD_CLK (IOCFG003) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + sd_cfg_func: sd_cfg_func { + pinctrl-single,pins = < + 0x10 0x0 /* SD_CMD (IOCFG004) */ + 0x14 0x0 /* SD_DATA0 (IOCFG005) */ + 0x18 0x0 /* SD_DATA1 (IOCFG006) */ + 0x1c 0x0 /* SD_DATA2 (IOCFG007) */ + 0x20 0x0 /* SD_DATA3 (IOCFG008) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + sd_cfg_idle: sd_cfg_idle { + pinctrl-single,pins = < + 0x10 0x0 /* SD_CMD (IOCFG004) */ + 0x14 0x0 /* SD_DATA0 (IOCFG005) */ + 0x18 0x0 /* SD_DATA1 (IOCFG006) */ + 0x1c 0x0 /* SD_DATA2 (IOCFG007) */ + 0x20 0x0 /* SD_DATA3 (IOCFG008) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + sdio_clk_cfg_func: sdio_clk_cfg_func { + pinctrl-single,pins = < + 0x134 0x0 /* SDIO_CLK (IOCFG077) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + sdio_clk_cfg_idle: sdio_clk_cfg_idle { + pinctrl-single,pins = < + 0x134 0x0 /* SDIO_CLK (IOCFG077) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + sdio_cfg_func: sdio_cfg_func { + pinctrl-single,pins = < + 0x138 0x0 /* SDIO_CMD (IOCFG078) */ + 0x13c 0x0 /* SDIO_DATA0 (IOCFG079) */ + 0x140 0x0 /* SDIO_DATA1 (IOCFG080) */ + 0x144 0x0 /* SDIO_DATA2 (IOCFG081) */ + 0x148 0x0 /* SDIO_DATA3 (IOCFG082) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + sdio_cfg_idle: sdio_cfg_idle { + pinctrl-single,pins = < + 0x138 0x0 /* SDIO_CMD (IOCFG078) */ + 0x13c 0x0 /* SDIO_DATA0 (IOCFG079) */ + 0x140 0x0 /* SDIO_DATA1 (IOCFG080) */ + 0x144 0x0 /* SDIO_DATA2 (IOCFG081) */ + 0x148 0x0 /* SDIO_DATA3 (IOCFG082) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + isp_cfg_func1: isp_cfg_func1 { + pinctrl-single,pins = < + 0x28 0x0 /* ISP_PWDN0 (IOCFG010) */ + 0x2c 0x0 /* ISP_PWDN1 (IOCFG011) */ + 0x30 0x0 /* ISP_PWDN2 (IOCFG012) */ + 0x34 0x0 /* ISP_SHUTTER0 (IOCFG013) */ + 0x38 0x0 /* ISP_SHUTTER1 (IOCFG014) */ + 0x3c 0x0 /* ISP_PWM (IOCFG015) */ + 0x40 0x0 /* ISP_CCLK0 (IOCFG016) */ + 0x44 0x0 /* ISP_CCLK1 (IOCFG017) */ + 0x48 0x0 /* ISP_RESETB0 (IOCFG018) */ + 0x4c 0x0 /* ISP_RESETB1 (IOCFG019) */ + 0x50 0x0 /* ISP_STROBE0 (IOCFG020) */ + 0x58 0x0 /* ISP_SDA0 (IOCFG022) */ + 0x5c 0x0 /* ISP_SCL0 (IOCFG023) */ + 0x60 0x0 /* ISP_SDA1 (IOCFG024) */ + 0x64 0x0 /* ISP_SCL1 (IOCFG025) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + isp_cfg_idle1: isp_cfg_idle1 { + pinctrl-single,pins = < + 0x34 0x0 /* ISP_SHUTTER0 (IOCFG013) */ + 0x38 0x0 /* ISP_SHUTTER1 (IOCFG014) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + isp_cfg_func2: isp_cfg_func2 { + pinctrl-single,pins = < + 0x54 0x0 /* ISP_STROBE1 (IOCFG021) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + codec_clk_cfg_func: codec_clk_cfg_func { + pinctrl-single,pins = < + 0x70 0x0 /* CODEC_CLK (IOCFG028) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + codec_clk_cfg_idle: codec_clk_cfg_idle { + pinctrl-single,pins = < + 0x70 0x0 /* CODEC_CLK (IOCFG028) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + codec_cfg_func1: codec_cfg_func1 { + pinctrl-single,pins = < + 0x74 0x0 /* DMIC_CLK (IOCFG029) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + codec_cfg_func2: codec_cfg_func2 { + pinctrl-single,pins = < + 0x78 0x0 /* CODEC_SYNC (IOCFG030) */ + 0x7c 0x0 /* CODEC_DI (IOCFG031) */ + 0x80 0x0 /* CODEC_DO (IOCFG032) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + codec_cfg_idle2: codec_cfg_idle2 { + pinctrl-single,pins = < + 0x78 0x0 /* CODEC_SYNC (IOCFG030) */ + 0x7c 0x0 /* CODEC_DI (IOCFG031) */ + 0x80 0x0 /* CODEC_DO (IOCFG032) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + fm_cfg_func: fm_cfg_func { + pinctrl-single,pins = < + 0x84 0x0 /* FM_XCLK (IOCFG033) */ + 0x88 0x0 /* FM_XFS (IOCFG034) */ + 0x8c 0x0 /* FM_DI (IOCFG035) */ + 0x90 0x0 /* FM_DO (IOCFG036) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + bt_cfg_func: bt_cfg_func { + pinctrl-single,pins = < + 0x94 0x0 /* BT_XCLK (IOCFG037) */ + 0x98 0x0 /* BT_XFS (IOCFG038) */ + 0x9c 0x0 /* BT_DI (IOCFG039) */ + 0xa0 0x0 /* BT_DO (IOCFG040) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + bt_cfg_idle: bt_cfg_idle { + pinctrl-single,pins = < + 0x94 0x0 /* BT_XCLK (IOCFG037) */ + 0x98 0x0 /* BT_XFS (IOCFG038) */ + 0x9c 0x0 /* BT_DI (IOCFG039) */ + 0xa0 0x0 /* BT_DO (IOCFG040) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + pwm_in_cfg_func: pwm_in_cfg_func { + pinctrl-single,pins = < + 0xbc 0x0 /* PWM_IN (IOCFG047) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + bl_pwm_cfg_func: bl_pwm_cfg_func { + pinctrl-single,pins = < + 0xc0 0x0 /* BL_PWM (IOCFG048) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart0_cfg_func1: uart0_cfg_func1 { + pinctrl-single,pins = < + 0xc4 0x0 /* UART0_RXD (IOCFG049) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart0_cfg_func2: uart0_cfg_func2 { + pinctrl-single,pins = < + 0xc8 0x0 /* UART0_TXD (IOCFG050) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart1_cfg_func1: uart1_cfg_func1 { + pinctrl-single,pins = < + 0xcc 0x0 /* UART1_CTS_N (IOCFG051) */ + 0xd4 0x0 /* UART1_RXD (IOCFG053) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart1_cfg_func2: uart1_cfg_func2 { + pinctrl-single,pins = < + 0xd0 0x0 /* UART1_RTS_N (IOCFG052) */ + 0xd8 0x0 /* UART1_TXD (IOCFG054) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart2_cfg_func: uart2_cfg_func { + pinctrl-single,pins = < + 0xdc 0x0 /* UART2_CTS_N (IOCFG055) */ + 0xe0 0x0 /* UART2_RTS_N (IOCFG056) */ + 0xe4 0x0 /* UART2_RXD (IOCFG057) */ + 0xe8 0x0 /* UART2_TXD (IOCFG058) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart3_cfg_func: uart3_cfg_func { + pinctrl-single,pins = < + 0x190 0x0 /* UART3_CTS_N (IOCFG100) */ + 0x194 0x0 /* UART3_RTS_N (IOCFG101) */ + 0x198 0x0 /* UART3_RXD (IOCFG102) */ + 0x19c 0x0 /* UART3_TXD (IOCFG103) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart4_cfg_func: uart4_cfg_func { + pinctrl-single,pins = < + 0x1e0 0x0 /* UART4_CTS_N (IOCFG120) */ + 0x1e4 0x0 /* UART4_RTS_N (IOCFG121) */ + 0x1e8 0x0 /* UART4_RXD (IOCFG122) */ + 0x1ec 0x0 /* UART4_TXD (IOCFG123) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + uart5_cfg_func: uart5_cfg_func { + pinctrl-single,pins = < + 0x1d8 0x0 /* UART4_RXD (IOCFG118) */ + 0x1dc 0x0 /* UART4_TXD (IOCFG119) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + i2c0_cfg_func: i2c0_cfg_func { + pinctrl-single,pins = < + 0xec 0x0 /* I2C0_SCL (IOCFG059) */ + 0xf0 0x0 /* I2C0_SDA (IOCFG060) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + i2c1_cfg_func: i2c1_cfg_func { + pinctrl-single,pins = < + 0xf4 0x0 /* I2C1_SCL (IOCFG061) */ + 0xf8 0x0 /* I2C1_SDA (IOCFG062) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + i2c2_cfg_func: i2c2_cfg_func { + pinctrl-single,pins = < + 0xfc 0x0 /* I2C2_SCL (IOCFG063) */ + 0x100 0x0 /* I2C2_SDA (IOCFG064) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + }; + + pmx2: pinmux@f8001800 { + + pinctrl-names = "default"; + pinctrl-0 = < + &rstout_n_cfg_func + >; + + rstout_n_cfg_func: rstout_n_cfg_func { + pinctrl-single,pins = < + 0x0 0x0 /* RSTOUT_N (IOCFG000) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + pmu_peri_en_cfg_func: pmu_peri_en_cfg_func { + pinctrl-single,pins = < + 0x4 0x0 /* PMU_PERI_EN (IOCFG001) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + sysclk0_en_cfg_func: sysclk0_en_cfg_func { + pinctrl-single,pins = < + 0x8 0x0 /* SYSCLK0_EN (IOCFG002) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + jtag_tdo_cfg_func: jtag_tdo_cfg_func { + pinctrl-single,pins = < + 0xc 0x0 /* JTAG_TDO (IOCFG003) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + + rf_reset_cfg_func: rf_reset_cfg_func { + pinctrl-single,pins = < + 0x70 0x0 /* RF_RESET0 (IOCFG028) */ + 0x74 0x0 /* RF_RESET1 (IOCFG029) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; + }; + }; +}; diff --git a/include/dt-bindings/pinctrl/hisi.h b/include/dt-bindings/pinctrl/hisi.h new file mode 100644 index 000000000000..38f1ea879ea1 --- /dev/null +++ b/include/dt-bindings/pinctrl/hisi.h @@ -0,0 +1,59 @@ +/* + * This header provides constants for hisilicon pinctrl bindings. + * + * Copyright (c) 2015 Hisilicon Limited. + * Copyright (c) 2015 Linaro Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_PINCTRL_HISI_H +#define _DT_BINDINGS_PINCTRL_HISI_H + +/* iomg bit definition */ +#define MUX_M0 0 +#define MUX_M1 1 +#define MUX_M2 2 +#define MUX_M3 3 +#define MUX_M4 4 +#define MUX_M5 5 +#define MUX_M6 6 +#define MUX_M7 7 + +/* iocg bit definition */ +#define PULL_MASK (3) +#define PULL_DIS (0) +#define PULL_UP (1 << 0) +#define PULL_DOWN (1 << 1) + +/* drive strength definition */ +#define DRIVE_MASK (7 << 4) +#define DRIVE1_02MA (0 << 4) +#define DRIVE1_04MA (1 << 4) +#define DRIVE1_08MA (2 << 4) +#define DRIVE1_10MA (3 << 4) +#define DRIVE2_02MA (0 << 4) +#define DRIVE2_04MA (1 << 4) +#define DRIVE2_08MA (2 << 4) +#define DRIVE2_10MA (3 << 4) +#define DRIVE3_04MA (0 << 4) +#define DRIVE3_08MA (1 << 4) +#define DRIVE3_12MA (2 << 4) +#define DRIVE3_16MA (3 << 4) +#define DRIVE3_20MA (4 << 4) +#define DRIVE3_24MA (5 << 4) +#define DRIVE3_32MA (6 << 4) +#define DRIVE3_40MA (7 << 4) +#define DRIVE4_02MA (0 << 4) +#define DRIVE4_04MA (2 << 4) +#define DRIVE4_08MA (4 << 4) +#define DRIVE4_10MA (6 << 4) + +#endif -- GitLab From 60dac1b19b6af6ddc4df68d163e2d7508057c007 Mon Sep 17 00:00:00 2001 From: Zhong Kaihua Date: Wed, 13 Apr 2016 07:55:42 +0800 Subject: [PATCH 2910/9938] arm64: dts: add Hi6220 spi configuration nodes Add Hi6220 spi configuration nodes. Disable by default in hi6220.dtsi and enable it in board dts for usage of 96boards LS mezzanine board. Signed-off-by: Zhong Kaihua Signed-off-by: Guodong Xu Reviewed-by: Rob Herring Signed-off-by: Wei Xu --- .../arm64/boot/dts/hisilicon/hi6220-hikey.dts | 6 ++++++ arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 15 +++++++++++++ .../boot/dts/hisilicon/hikey-pinctrl.dtsi | 21 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 3d9e8b2d2b18..7545e363fbde 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -40,6 +40,12 @@ <0x00000000 0x06e00000 0x00000000 0x0060f000>, <0x00000000 0x07410000 0x00000000 0x36bf0000>; }; + + soc { + spi0: spi@f7106000 { + status = "ok"; + }; + }; }; &uart2 { diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index df56571703b0..7bcfffe5dfd9 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -567,5 +567,20 @@ clocks = <&ao_ctrl 2>; clock-names = "apb_pclk"; }; + + spi0: spi@f7106000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x0 0xf7106000 0x0 0x1000>; + interrupts = <0 50 4>; + bus-id = <0>; + enable-dma = <0>; + clocks = <&sys_ctrl HI6220_SPI_CLK>; + clock-names = "apb_pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pmx_func &spi0_cfg_func>; + num-cs = <1>; + cs-gpios = <&gpio6 2 0>; + status = "disabled"; + }; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi index 28806df214d7..0916e8459d6b 100644 --- a/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi @@ -221,6 +221,15 @@ 0xfc MUX_M0 /* I2C2_SDA (IOMG063) */ >; }; + + spi0_pmx_func: spi0_pmx_func { + pinctrl-single,pins = < + 0x1a0 MUX_M1 /* SPI0_DI (IOMG104) */ + 0x1a4 MUX_M1 /* SPI0_DO (IOMG105) */ + 0x1a8 MUX_M1 /* SPI0_CS_N (IOMG106) */ + 0x1ac MUX_M1 /* SPI0_CLK (IOMG107) */ + >; + }; }; pmx1: pinmux@f7010800 { @@ -625,6 +634,18 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; + + spi0_cfg_func: spi0_cfg_func { + pinctrl-single,pins = < + 0x1b0 0x0 /* SPI0_DI (IOCFG108) */ + 0x1b4 0x0 /* SPI0_DO (IOCFG109) */ + 0x1b8 0x0 /* SPI0_CS_N (IOCFG110) */ + 0x1bc 0x0 /* SPI0_CLK (IOCFG111) */ + >; + pinctrl-single,bias-pulldown = ; + pinctrl-single,bias-pullup = ; + pinctrl-single,drive-strength = ; + }; }; pmx2: pinmux@f8001800 { -- GitLab From 5ff3a4ddd142ac2ac4e6d4aa65cf0f7bf2d9679a Mon Sep 17 00:00:00 2001 From: Xinwei Kong Date: Wed, 13 Apr 2016 07:55:43 +0800 Subject: [PATCH 2911/9938] arm64: dts: add all hi6220 i2c nodes This patch adds all I2C nodes for the Hi6220 SoC. This hi6220 Soc use this I2C IP of Synopsys Designware for HiKey board. Signed-off-by: Xinwei Kong Signed-off-by: Chen Feng Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 7bcfffe5dfd9..4fc034724a9c 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -582,5 +582,38 @@ cs-gpios = <&gpio6 2 0>; status = "disabled"; }; + + i2c0: i2c@f7100000 { + compatible = "snps,designware-i2c"; + reg = <0x0 0xf7100000 0x0 0x1000>; + interrupts = <0 44 4>; + clocks = <&sys_ctrl HI6220_I2C0_CLK>; + i2c-sda-hold-time-ns = <300>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pmx_func &i2c0_cfg_func>; + status = "disabled"; + }; + + i2c1: i2c@f7101000 { + compatible = "snps,designware-i2c"; + reg = <0x0 0xf7101000 0x0 0x1000>; + clocks = <&sys_ctrl HI6220_I2C1_CLK>; + interrupts = <0 45 4>; + i2c-sda-hold-time-ns = <300>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pmx_func &i2c1_cfg_func>; + status = "disabled"; + }; + + i2c2: i2c@f7102000 { + compatible = "snps,designware-i2c"; + reg = <0x0 0xf7102000 0x0 0x1000>; + clocks = <&sys_ctrl HI6220_I2C2_CLK>; + interrupts = <0 46 4>; + i2c-sda-hold-time-ns = <300>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pmx_func &i2c2_cfg_func>; + status = "disabled"; + }; }; }; -- GitLab From 0c2317512d51f62401fdb7dd9d2ab5c932ac0ab9 Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Wed, 13 Apr 2016 07:55:44 +0800 Subject: [PATCH 2912/9938] arm64: dts: hikey: enable i2c0 and i2c1 for working with mezzanine boards In HiKey board dts file, enable i2c0 and i2c1 for working with 96boards' LS mezzanine. Signed-off-by: Guodong Xu Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 7545e363fbde..3dbf51b609a1 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -45,6 +45,14 @@ spi0: spi@f7106000 { status = "ok"; }; + + i2c0: i2c@f7100000 { + status = "ok"; + }; + + i2c1: i2c@f7101000 { + status = "ok"; + }; }; }; -- GitLab From b4b31a7cd797dcadba32a2f283923aec7583462e Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Wed, 13 Apr 2016 07:55:45 +0800 Subject: [PATCH 2913/9938] arm64: dts: Add hi6220 usb node Add USB nodes for Hi6220 Signed-off-by: Zhangfei Gao Acked-by: Rob Herring Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 4fc034724a9c..4d1d31f45d38 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -615,5 +615,37 @@ pinctrl-0 = <&i2c2_pmx_func &i2c2_cfg_func>; status = "disabled"; }; + + fixed_5v_hub: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "fixed_5v_hub"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + gpio = <&gpio0 7 0>; + regulator-always-on; + }; + + usb_phy: usbphy { + compatible = "hisilicon,hi6220-usb-phy"; + #phy-cells = <0>; + phy-supply = <&fixed_5v_hub>; + hisilicon,peripheral-syscon = <&sys_ctrl>; + }; + + usb: usb@f72c0000 { + compatible = "hisilicon,hi6220-usb"; + reg = <0x0 0xf72c0000 0x0 0x40000>; + phys = <&usb_phy>; + phy-names = "usb2-phy"; + clocks = <&sys_ctrl HI6220_USBOTG_HCLK>; + clock-names = "otg"; + dr_mode = "otg"; + g-use-dma; + g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <128>; + g-tx-fifo-size = <128 128 128 128 128 128>; + interrupts = <0 77 0x4>; + }; }; }; -- GitLab From 8607357016f6b643787727cf35ecdcfb49c3cf23 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 13 Apr 2016 07:55:46 +0800 Subject: [PATCH 2914/9938] arm64: dts: add mailbox node for Hi6220 This patch add device mailbox node for Hi6220 in DT. Signed-off-by: Leo Yan Acked-by: Jassi Brar Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 4d1d31f45d38..d71c51ff2f83 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -647,5 +647,13 @@ g-tx-fifo-size = <128 128 128 128 128 128>; interrupts = <0 77 0x4>; }; + + mailbox: mailbox@f7510000 { + compatible = "hisilicon,hi6220-mbox"; + reg = <0x0 0xf7510000 0x0 0x1000>, /* IPC_S */ + <0x0 0x06dff800 0x0 0x0800>; /* Mailbox buffer */ + interrupts = ; + #mbox-cells = <3>; + }; }; }; -- GitLab From 998605407249dd278aef28c1cc2ce00f90c09eaa Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Wed, 13 Apr 2016 07:55:47 +0800 Subject: [PATCH 2915/9938] arm64: dts: add Hi6220's stub clock node Enable SRAM node and stub clock node for Hi6220, which uses mailbox channel 1 for CPU's frequency change. Furthermore, add the CPU clock phandle in CPU's node and using operating-points-v2 to register operating points. So can be used by cpufreq-dt driver. Signed-off-by: Leo Yan Acked-by: Jassi Brar Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 56 +++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index d71c51ff2f83..3a665efd197b 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -82,6 +82,11 @@ device_type = "cpu"; reg = <0x0 0x0>; enable-method = "psci"; + clocks = <&stub_clock 0>; + operating-points-v2 = <&cpu_opp_table>; + cooling-min-level = <4>; + cooling-max-level = <0>; + #cooling-cells = <2>; /* min followed by max */ cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -90,6 +95,7 @@ device_type = "cpu"; reg = <0x0 0x1>; enable-method = "psci"; + operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -98,6 +104,7 @@ device_type = "cpu"; reg = <0x0 0x2>; enable-method = "psci"; + operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -106,6 +113,7 @@ device_type = "cpu"; reg = <0x0 0x3>; enable-method = "psci"; + operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -114,6 +122,7 @@ device_type = "cpu"; reg = <0x0 0x100>; enable-method = "psci"; + operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -122,6 +131,7 @@ device_type = "cpu"; reg = <0x0 0x101>; enable-method = "psci"; + operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -130,6 +140,7 @@ device_type = "cpu"; reg = <0x0 0x102>; enable-method = "psci"; + operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -138,10 +149,42 @@ device_type = "cpu"; reg = <0x0 0x103>; enable-method = "psci"; + operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; }; + cpu_opp_table: cpu_opp_table { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <208000000>; + opp-microvolt = <1040000>; + clock-latency-ns = <500000>; + }; + opp01 { + opp-hz = /bits/ 64 <432000000>; + opp-microvolt = <1040000>; + clock-latency-ns = <500000>; + }; + opp02 { + opp-hz = /bits/ 64 <729000000>; + opp-microvolt = <1090000>; + clock-latency-ns = <500000>; + }; + opp03 { + opp-hz = /bits/ 64 <960000000>; + opp-microvolt = <1180000>; + clock-latency-ns = <500000>; + }; + opp04 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1330000>; + clock-latency-ns = <500000>; + }; + }; + gic: interrupt-controller@f6801000 { compatible = "arm,gic-400"; reg = <0x0 0xf6801000 0 0x1000>, /* GICD */ @@ -169,6 +212,11 @@ #size-cells = <2>; ranges; + sram: sram@fff80000 { + compatible = "hisilicon,hi6220-sramctrl", "syscon"; + reg = <0x0 0xfff80000 0x0 0x12000>; + }; + ao_ctrl: ao_ctrl@f7800000 { compatible = "hisilicon,hi6220-aoctrl", "syscon"; reg = <0x0 0xf7800000 0x0 0x2000>; @@ -194,6 +242,14 @@ #clock-cells = <1>; }; + stub_clock: stub_clock { + compatible = "hisilicon,hi6220-stub-clk"; + hisilicon,hi6220-clk-sram = <&sram>; + #clock-cells = <1>; + mbox-names = "mbox-tx"; + mboxes = <&mailbox 1 0 11>; + }; + uart0: uart@f8015000 { /* console */ compatible = "arm,pl011", "arm,primecell"; reg = <0x0 0xf8015000 0x0 0x1000>; -- GitLab From c2aad93200fa2dbbc6c48632e619494080d64796 Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Wed, 13 Apr 2016 07:55:48 +0800 Subject: [PATCH 2916/9938] arm64: dts: hi6220: add pinctrl for uarts and enable them Add pinctrl for uart2 uart3 and uart4. Enable uart1 uart2 and uart3. Signed-off-by: Guodong Xu Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 12 ++++++++++++ arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 3dbf51b609a1..30c92bd0855f 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -53,6 +53,18 @@ i2c1: i2c@f7101000 { status = "ok"; }; + + uart1: uart@f7111000 { + status = "ok"; + }; + + uart2: uart@f7112000 { + status = "ok"; + }; + + uart3: uart@f7113000 { + status = "ok"; + }; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 3a665efd197b..e8bb81fe8479 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -266,6 +266,8 @@ clocks = <&sys_ctrl HI6220_UART1_PCLK>, <&sys_ctrl HI6220_UART1_PCLK>; clock-names = "uartclk", "apb_pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pmx_func &uart1_cfg_func1 &uart1_cfg_func2>; status = "disabled"; }; @@ -276,6 +278,8 @@ clocks = <&sys_ctrl HI6220_UART2_PCLK>, <&sys_ctrl HI6220_UART2_PCLK>; clock-names = "uartclk", "apb_pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pmx_func &uart2_cfg_func>; status = "disabled"; }; @@ -286,6 +290,9 @@ clocks = <&sys_ctrl HI6220_UART3_PCLK>, <&sys_ctrl HI6220_UART3_PCLK>; clock-names = "uartclk", "apb_pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pmx_func &uart3_cfg_func>; + status = "disabled"; }; uart4: uart@f7114000 { @@ -295,6 +302,8 @@ clocks = <&sys_ctrl HI6220_UART4_PCLK>, <&sys_ctrl HI6220_UART4_PCLK>; clock-names = "uartclk", "apb_pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pmx_func &uart4_cfg_func>; status = "disabled"; }; -- GitLab From ad05f38ba98ab01aebf52cc1d788df8272e6daa8 Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Wed, 13 Apr 2016 07:55:49 +0800 Subject: [PATCH 2917/9938] arm64: dts: add LED nodes for hi6220-hikey Add LED nodes for hi6220-hikey. There are total 6 LEDs on HiKey. Four general purposed, one for WiFi activity, and one for Bluetooth activity. Signed-off-by: Guodong Xu Signed-off-by: Wei Xu --- .../arm64/boot/dts/hisilicon/hi6220-hikey.dts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 30c92bd0855f..b7c41f83c61e 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -66,6 +66,47 @@ status = "ok"; }; }; + + leds { + compatible = "gpio-leds"; + user_led4 { + label = "user_led4"; + gpios = <&gpio4 0 0>; /* <&gpio_user_led_1>; */ + linux,default-trigger = "heartbeat"; + }; + + user_led3 { + label = "user_led3"; + gpios = <&gpio4 1 0>; /* <&gpio_user_led_2>; */ + linux,default-trigger = "mmc0"; + }; + + user_led2 { + label = "user_led2"; + gpios = <&gpio4 2 0>; /* <&gpio_user_led_3>; */ + linux,default-trigger = "mmc1"; + }; + + user_led1 { + label = "user_led1"; + gpios = <&gpio4 3 0>; /* <&gpio_user_led_4>; */ + linux,default-trigger = "cpu0"; + }; + + wlan_active_led { + label = "wifi_active"; + gpios = <&gpio3 5 0>; /* <&gpio_wlan_active_led>; */ + linux,default-trigger = "phy0tx"; + default-state = "off"; + }; + + bt_active_led { + label = "bt_active"; + gpios = <&gpio4 7 0>; /* <&gpio_bt_active_led>; */ + linux,default-trigger = "hci0rx"; + default-state = "off"; + }; + }; }; &uart2 { -- GitLab From a817137a6c3079c99954396afe94bb5a7cbfa251 Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Wed, 13 Apr 2016 07:55:50 +0800 Subject: [PATCH 2918/9938] arm64: dts: hikey: Add hi655x pmic dts node Add the mfd hi655x dts node and regulator support on hi6220 platform. Signed-off-by: Chen Feng Signed-off-by: Fei Wang Signed-off-by: Xinwei Kong Signed-off-by: Guodong Xu Reviewed-by: Haojian Zhuang Reviewed-by: Rob Herring Acked-by: Lee Jones Signed-off-by: Wei Xu --- .../arm64/boot/dts/hisilicon/hi6220-hikey.dts | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index b7c41f83c61e..cc1148d911ad 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -6,9 +6,9 @@ */ /dts-v1/; - #include "hi6220.dtsi" #include "hikey-pinctrl.dtsi" +#include / { model = "HiKey Development Board"; @@ -107,6 +107,91 @@ default-state = "off"; }; }; + + pmic: pmic@f8000000 { + compatible = "hisilicon,hi655x-pmic"; + reg = <0x0 0xf8000000 0x0 0x1000>; + interrupt-controller; + #interrupt-cells = <2>; + pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + + regulators { + ldo2: LDO2 { + regulator-name = "LDO2_2V8"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3200000>; + regulator-enable-ramp-delay = <120>; + }; + + ldo7: LDO7 { + regulator-name = "LDO7_SDIO"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <120>; + }; + + ldo10: LDO10 { + regulator-name = "LDO10_2V85"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <360>; + }; + + ldo13: LDO13 { + regulator-name = "LDO13_1V8"; + regulator-min-microvolt = <1600000>; + regulator-max-microvolt = <1950000>; + regulator-enable-ramp-delay = <120>; + }; + + ldo14: LDO14 { + regulator-name = "LDO14_2V8"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3200000>; + regulator-enable-ramp-delay = <120>; + }; + + ldo15: LDO15 { + regulator-name = "LDO15_1V8"; + regulator-min-microvolt = <1600000>; + regulator-max-microvolt = <1950000>; + regulator-boot-on; + regulator-always-on; + regulator-enable-ramp-delay = <120>; + }; + + ldo17: LDO17 { + regulator-name = "LDO17_2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3200000>; + regulator-enable-ramp-delay = <120>; + }; + + ldo19: LDO19 { + regulator-name = "LDO19_3V0"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <360>; + }; + + ldo21: LDO21 { + regulator-name = "LDO21_1V8"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2000000>; + regulator-always-on; + regulator-enable-ramp-delay = <120>; + }; + + ldo22: LDO22 { + regulator-name = "LDO22_1V2"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + regulator-always-on; + regulator-enable-ramp-delay = <120>; + }; + }; + }; }; &uart2 { -- GitLab From d6b259d4faa1670f372969141323c6fe4b3b7db9 Mon Sep 17 00:00:00 2001 From: Xinwei Kong Date: Wed, 13 Apr 2016 07:55:51 +0800 Subject: [PATCH 2919/9938] arm64: dts: add dwmmc nodes for hi6220 Add all three dwmmc nodes description for hi6220 Signed-off-by: Guodong Xu Signed-off-by: Xinwei Kong Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index e8bb81fe8479..7b7bbf66f004 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -720,5 +720,57 @@ interrupts = ; #mbox-cells = <3>; }; + + dwmmc_0: dwmmc0@f723d000 { + compatible = "hisilicon,hi6220-dw-mshc"; + num-slots = <0x1>; + cap-mmc-highspeed; + non-removable; + reg = <0x0 0xf723d000 0x0 0x1000>; + interrupts = <0x0 0x48 0x4>; + clocks = <&sys_ctrl 2>, <&sys_ctrl 1>; + clock-names = "ciu", "biu"; + bus-width = <0x8>; + vmmc-supply = <&ldo19>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_pmx_func &emmc_clk_cfg_func + &emmc_cfg_func &emmc_rst_cfg_func>; + }; + + dwmmc_1: dwmmc1@f723e000 { + compatible = "hisilicon,hi6220-dw-mshc"; + num-slots = <0x1>; + card-detect-delay = <200>; + hisilicon,peripheral-syscon = <&ao_ctrl>; + cap-sd-highspeed; + reg = <0x0 0xf723e000 0x0 0x1000>; + interrupts = <0x0 0x49 0x4>; + #address-cells = <0x1>; + #size-cells = <0x0>; + clocks = <&sys_ctrl 4>, <&sys_ctrl 3>; + clock-names = "ciu", "biu"; + vqmmc-supply = <&ldo7>; + vmmc-supply = <&ldo10>; + bus-width = <0x4>; + disable-wp; + cd-gpios = <&gpio1 0 1>; + pinctrl-names = "default", "idle"; + pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>; + pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>; + }; + + dwmmc_2: dwmmc2@f723f000 { + compatible = "hisilicon,hi6220-dw-mshc"; + num-slots = <0x1>; + reg = <0x0 0xf723f000 0x0 0x1000>; + interrupts = <0x0 0x4a 0x4>; + clocks = <&sys_ctrl HI6220_MMC2_CIUCLK>, <&sys_ctrl HI6220_MMC2_CLK>; + clock-names = "ciu", "biu"; + bus-width = <0x4>; + broken-cd; + pinctrl-names = "default", "idle"; + pinctrl-0 = <&sdio_pmx_func &sdio_clk_cfg_func &sdio_cfg_func>; + pinctrl-1 = <&sdio_pmx_idle &sdio_clk_cfg_idle &sdio_cfg_idle>; + }; }; }; -- GitLab From 841478d4ae2cb7205fc7940e7140ef0efb3fabf7 Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Wed, 13 Apr 2016 07:55:52 +0800 Subject: [PATCH 2920/9938] arm64: dts: add wifi nodes support for hi6220-hikey Add wifi nodes support for hi6220-hikey Signed-off-by: Guodong Xu Signed-off-by: Wei Xu --- .../arm64/boot/dts/hisilicon/hi6220-hikey.dts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index cc1148d911ad..e92a30c87a82 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -65,6 +65,35 @@ uart3: uart@f7113000 { status = "ok"; }; + + dwmmc_2: dwmmc2@f723f000 { + ti,non-removable; + non-removable; + /* WL_EN */ + vmmc-supply = <&wlan_en_reg>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + wlcore: wlcore@2 { + compatible = "ti,wl1835"; + reg = <2>; /* sdio func num */ + /* WL_IRQ, WL_HOST_WAKE_GPIO1_3 */ + interrupt-parent = <&gpio1>; + interrupts = <3 IRQ_TYPE_EDGE_RISING>; + }; + }; + + wlan_en_reg: regulator@1 { + compatible = "regulator-fixed"; + regulator-name = "wlan-en-regulator"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + /* WLAN_EN GPIO */ + gpio = <&gpio0 5 0>; + /* WLAN card specific delay */ + startup-delay-us = <70000>; + enable-active-high; + }; }; leds { -- GitLab From fc5cf80ac4e0b2727c7af1a70bca277b82771cf3 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 15 Apr 2016 08:45:32 -0700 Subject: [PATCH 2921/9938] of/platform: Allow secondary compatible match in of_dev_lookup We currently try to match of_dev_auxdata based on compatible, IO address, and device name. But in some cases we have multiple instances of drivers that can use the same auxdata. Let's add an additional secondary lookup for generic compatible match for auxdata if no device specific match is found. This does not change the existing matching, and still allows adding device specific auxdata. This simplifies things as specifying the IO address and device name is prone errors as it requires maintaining an in kernel database for each SoC. To specify a generic match, all that is needed is to add a OF_DEV_AUXDATA entry with no device instance specified: OF_DEV_AUXDATA("pinctrl-single", 0, NULL, &pcs_pdata), As the auxdata is already initialized only for the booted SoC, there's not much of a chance of getting things wrong. Let's also fix two checkpatch warnings while at it to add a space before parenthesis in the for loop, and remove a comparison to NULL by using !auxdata->compatible. Acked-by: Rob Herring Signed-off-by: Tony Lindgren --- drivers/of/platform.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 8d103e4968be..16e8daffac06 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -297,19 +297,37 @@ static struct amba_device *of_amba_device_create(struct device_node *node, static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup, struct device_node *np) { + const struct of_dev_auxdata *auxdata; struct resource res; + int compatible = 0; if (!lookup) return NULL; - for(; lookup->compatible != NULL; lookup++) { - if (!of_device_is_compatible(np, lookup->compatible)) + auxdata = lookup; + for (; auxdata->compatible; auxdata++) { + if (!of_device_is_compatible(np, auxdata->compatible)) continue; + compatible++; if (!of_address_to_resource(np, 0, &res)) - if (res.start != lookup->phys_addr) + if (res.start != auxdata->phys_addr) continue; - pr_debug("%s: devname=%s\n", np->full_name, lookup->name); - return lookup; + pr_debug("%s: devname=%s\n", np->full_name, auxdata->name); + return auxdata; + } + + if (!compatible) + return NULL; + + /* Try compatible match if no phys_addr and name are specified */ + auxdata = lookup; + for (; auxdata->compatible; auxdata++) { + if (!of_device_is_compatible(np, auxdata->compatible)) + continue; + if (!auxdata->phys_addr && !auxdata->name) { + pr_debug("%s: compatible match\n", np->full_name); + return auxdata; + } } return NULL; -- GitLab From d4f414e559caf36d811213e56b56e9b6957caab1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 15 Apr 2016 08:45:33 -0700 Subject: [PATCH 2922/9938] ARM: OMAP2+: Simplify auxdata by using the generic match We can now just use the compatible if there's no need to have device instance specific auxdata. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/pdata-quirks.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index a935d28443da..6ae132aadf6a 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -492,9 +492,6 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("tlv320aic3x", 0x18, "2-0018", &n810_aic33_data), #endif #ifdef CONFIG_ARCH_OMAP3 - OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002030, "48002030.pinmux", &pcs_pdata), - OF_DEV_AUXDATA("ti,omap3-padconf", 0x480025a0, "480025a0.pinmux", &pcs_pdata), - OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002a00, "48002a00.pinmux", &pcs_pdata), OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu", &omap3_iommu_pdata), /* Only on am3517 */ @@ -506,19 +503,7 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("ti,am3352-wkup-m3", 0x44d00000, "44d00000.wkup_m3", &wkup_m3_data), #endif -#ifdef CONFIG_ARCH_OMAP4 - OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a100040, "4a100040.pinmux", &pcs_pdata), - OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a31e040, "4a31e040.pinmux", &pcs_pdata), -#endif -#ifdef CONFIG_SOC_OMAP5 - OF_DEV_AUXDATA("ti,omap5-padconf", 0x4a002840, "4a002840.pinmux", &pcs_pdata), - OF_DEV_AUXDATA("ti,omap5-padconf", 0x4ae0c840, "4ae0c840.pinmux", &pcs_pdata), -#endif -#ifdef CONFIG_SOC_DRA7XX - OF_DEV_AUXDATA("ti,dra7-padconf", 0x4a003400, "4a003400.pinmux", &pcs_pdata), -#endif #ifdef CONFIG_SOC_AM43XX - OF_DEV_AUXDATA("ti,am437-padconf", 0x44e10800, "44e10800.pinmux", &pcs_pdata), OF_DEV_AUXDATA("ti,am4372-wkup-m3", 0x44d00000, "44d00000.wkup_m3", &wkup_m3_data), #endif @@ -531,6 +516,8 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("ti,omap4-iommu", 0x55082000, "55082000.mmu", &omap4_iommu_pdata), #endif + /* Common auxdata */ + OF_DEV_AUXDATA("pinctrl-single", 0, NULL, &pcs_pdata), { /* sentinel */ }, }; -- GitLab From f2353d7bd4221dfe0e230c5be49038d4a57d97e9 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 23 Mar 2016 10:42:01 -0700 Subject: [PATCH 2923/9938] f2fs: give RO message when recovering superblock When one of superblocks is missing, f2fs recovers it with the valid one. But, even if f2fs is mounted as RO, we'd better notify that too. Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 006f87d69921..ffe4616376ca 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1298,6 +1298,9 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) struct buffer_head *bh; int err; + if (f2fs_readonly(sbi->sb) || bdev_read_only(sbi->sb->s_bdev)) + return -EROFS; + /* write back-up superblock first */ bh = sb_getblk(sbi->sb, sbi->valid_super_block ? 0: 1); if (!bh) @@ -1565,7 +1568,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) kfree(options); /* recover broken superblock */ - if (recovery && !f2fs_readonly(sb) && !bdev_read_only(sb->s_bdev)) { + if (recovery) { err = f2fs_commit_super(sbi, true); f2fs_msg(sb, KERN_INFO, "Try to recover %dth superblock, ret: %ld", -- GitLab From df728b0f6954c38545f4bf12dedeeb9e07469a94 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 23 Mar 2016 17:05:27 -0700 Subject: [PATCH 2924/9938] f2fs: recover superblock at RW remounts This patch adds a sbi flag, SBI_NEED_SB_WRITE, which indicates it needs to recover superblock when (re)mounting as RW. This is set only when f2fs is mounted as RO. Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 1 + fs/f2fs/super.c | 36 +++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7a4558d17f36..7cb360e02109 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -672,6 +672,7 @@ enum { SBI_IS_CLOSE, /* specify unmounting */ SBI_NEED_FSCK, /* need fsck.f2fs to fix */ SBI_POR_DOING, /* recovery is doing or not */ + SBI_NEED_SB_WRITE, /* need to recover superblock */ }; enum { diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index ffe4616376ca..f5fbbfdb3d93 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -796,6 +796,15 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) set_sbi_flag(sbi, SBI_IS_DIRTY); } + /* recover superblocks we couldn't write due to previous RO mount */ + if (!(*flags & MS_RDONLY) && is_sbi_flag_set(sbi, SBI_NEED_SB_WRITE)) { + err = f2fs_commit_super(sbi, false); + f2fs_msg(sb, KERN_INFO, + "Try to recover all the superblocks, ret: %d", err); + if (!err) + clear_sbi_flag(sbi, SBI_NEED_SB_WRITE); + } + sync_filesystem(sb); sbi->mount_opt.opt = 0; @@ -852,8 +861,9 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) } skip: /* Update the POSIXACL Flag */ - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); + return 0; restore_gc: if (need_restart_gc) { @@ -998,11 +1008,12 @@ static int __f2fs_commit_super(struct buffer_head *bh, return __sync_dirty_buffer(bh, WRITE_FLUSH_FUA); } -static inline bool sanity_check_area_boundary(struct super_block *sb, +static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi, struct buffer_head *bh) { struct f2fs_super_block *raw_super = (struct f2fs_super_block *) (bh->b_data + F2FS_SUPER_OFFSET); + struct super_block *sb = sbi->sb; u32 segment0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr); u32 cp_blkaddr = le32_to_cpu(raw_super->cp_blkaddr); u32 sit_blkaddr = le32_to_cpu(raw_super->sit_blkaddr); @@ -1081,6 +1092,7 @@ static inline bool sanity_check_area_boundary(struct super_block *sb, segment0_blkaddr) >> log_blocks_per_seg); if (f2fs_readonly(sb) || bdev_read_only(sb->s_bdev)) { + set_sbi_flag(sbi, SBI_NEED_SB_WRITE); res = "internally"; } else { err = __f2fs_commit_super(bh, NULL); @@ -1098,11 +1110,12 @@ static inline bool sanity_check_area_boundary(struct super_block *sb, return false; } -static int sanity_check_raw_super(struct super_block *sb, +static int sanity_check_raw_super(struct f2fs_sb_info *sbi, struct buffer_head *bh) { struct f2fs_super_block *raw_super = (struct f2fs_super_block *) (bh->b_data + F2FS_SUPER_OFFSET); + struct super_block *sb = sbi->sb; unsigned int blocksize; if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { @@ -1169,7 +1182,7 @@ static int sanity_check_raw_super(struct super_block *sb, } /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ - if (sanity_check_area_boundary(sb, bh)) + if (sanity_check_area_boundary(sbi, bh)) return 1; return 0; @@ -1239,10 +1252,11 @@ static void init_sb_info(struct f2fs_sb_info *sbi) * to get the first valid one. If any one of them is broken, we pass * them recovery flag back to the caller. */ -static int read_raw_super_block(struct super_block *sb, +static int read_raw_super_block(struct f2fs_sb_info *sbi, struct f2fs_super_block **raw_super, int *valid_super_block, int *recovery) { + struct super_block *sb = sbi->sb; int block; struct buffer_head *bh; struct f2fs_super_block *super; @@ -1262,7 +1276,7 @@ static int read_raw_super_block(struct super_block *sb, } /* sanity checking of raw super */ - if (sanity_check_raw_super(sb, bh)) { + if (sanity_check_raw_super(sbi, bh)) { f2fs_msg(sb, KERN_ERR, "Can't find valid F2FS filesystem in %dth superblock", block + 1); @@ -1298,8 +1312,11 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) struct buffer_head *bh; int err; - if (f2fs_readonly(sbi->sb) || bdev_read_only(sbi->sb->s_bdev)) + if ((recover && f2fs_readonly(sbi->sb)) || + bdev_read_only(sbi->sb->s_bdev)) { + set_sbi_flag(sbi, SBI_NEED_SB_WRITE); return -EROFS; + } /* write back-up superblock first */ bh = sb_getblk(sbi->sb, sbi->valid_super_block ? 0: 1); @@ -1343,6 +1360,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) if (!sbi) return -ENOMEM; + sbi->sb = sb; + /* Load the checksum driver */ sbi->s_chksum_driver = crypto_alloc_shash("crc32", 0, 0); if (IS_ERR(sbi->s_chksum_driver)) { @@ -1358,7 +1377,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; } - err = read_raw_super_block(sb, &raw_super, &valid_super_block, + err = read_raw_super_block(sbi, &raw_super, &valid_super_block, &recovery); if (err) goto free_sbi; @@ -1393,7 +1412,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid)); /* init f2fs-specific super block info */ - sbi->sb = sb; sbi->raw_super = raw_super; sbi->valid_super_block = valid_super_block; mutex_init(&sbi->gc_mutex); -- GitLab From 6781eabba1bdb133eb9125c4acf6704ccbe4df02 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 23 Mar 2016 16:12:58 -0700 Subject: [PATCH 2925/9938] f2fs: give -EINVAL for norecovery and rw mount Once detecting something to recover, f2fs should stop mounting, given norecovery and rw mount options. Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 +- fs/f2fs/recovery.c | 11 +++++++---- fs/f2fs/super.c | 14 ++++++++++++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7cb360e02109..e1c07b60f301 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1907,7 +1907,7 @@ void build_gc_manager(struct f2fs_sb_info *); /* * recovery.c */ -int recover_fsync_data(struct f2fs_sb_info *); +int recover_fsync_data(struct f2fs_sb_info *, bool); bool space_for_roll_forward(struct f2fs_sb_info *); /* diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 011942f94d64..2c87c12b6f1c 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -551,12 +551,13 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *head) return err; } -int recover_fsync_data(struct f2fs_sb_info *sbi) +int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) { struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); struct list_head inode_list; block_t blkaddr; int err; + int ret = 0; bool need_writecp = false; fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", @@ -573,11 +574,13 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) /* step #1: find fsynced inode numbers */ err = find_fsync_dnodes(sbi, &inode_list); - if (err) + if (err || list_empty(&inode_list)) goto out; - if (list_empty(&inode_list)) + if (check_only) { + ret = 1; goto out; + } need_writecp = true; @@ -625,5 +628,5 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) } else { mutex_unlock(&sbi->cp_mutex); } - return err; + return ret ? ret: err; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index f5fbbfdb3d93..8f9648ffbbc3 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1562,14 +1562,24 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) if (need_fsck) set_sbi_flag(sbi, SBI_NEED_FSCK); - err = recover_fsync_data(sbi); - if (err) { + err = recover_fsync_data(sbi, false); + if (err < 0) { need_fsck = true; f2fs_msg(sb, KERN_ERR, "Cannot recover all fsync data errno=%ld", err); goto free_kobj; } + } else { + err = recover_fsync_data(sbi, true); + + if (!f2fs_readonly(sb) && err > 0) { + err = -EINVAL; + f2fs_msg(sb, KERN_ERR, + "Need to recover fsync data"); + goto free_kobj; + } } + /* recover_fsync_data() cleared this already */ clear_sbi_flag(sbi, SBI_POR_DOING); -- GitLab From faa0e55bba54b91c464850dc28376056d26fa310 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 24 Mar 2016 10:29:39 -0700 Subject: [PATCH 2926/9938] f2fs: treat as a normal umount when remounting ro When user remounts f2fs as read-only, we can mark the checkpoint as umount. Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8f9648ffbbc3..19a85cf83f40 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -791,11 +791,6 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) org_mount_opt = sbi->mount_opt; active_logs = sbi->active_logs; - if (*flags & MS_RDONLY) { - set_opt(sbi, FASTBOOT); - set_sbi_flag(sbi, SBI_IS_DIRTY); - } - /* recover superblocks we couldn't write due to previous RO mount */ if (!(*flags & MS_RDONLY) && is_sbi_flag_set(sbi, SBI_NEED_SB_WRITE)) { err = f2fs_commit_super(sbi, false); @@ -805,8 +800,6 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) clear_sbi_flag(sbi, SBI_NEED_SB_WRITE); } - sync_filesystem(sb); - sbi->mount_opt.opt = 0; default_options(sbi); @@ -838,7 +831,6 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) if ((*flags & MS_RDONLY) || !test_opt(sbi, BG_GC)) { if (sbi->gc_thread) { stop_gc_thread(sbi); - f2fs_sync_fs(sb, 1); need_restart_gc = true; } } else if (!sbi->gc_thread) { @@ -848,6 +840,16 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) need_stop_gc = true; } + if (*flags & MS_RDONLY) { + writeback_inodes_sb(sb, WB_REASON_SYNC); + sync_inodes_sb(sb); + + set_sbi_flag(sbi, SBI_IS_DIRTY); + set_sbi_flag(sbi, SBI_IS_CLOSE); + f2fs_sync_fs(sb, 1); + clear_sbi_flag(sbi, SBI_IS_CLOSE); + } + /* * We stop issue flush thread if FS is mounted as RO * or if flush_merge is not passed in mount option. -- GitLab From 8c11a53fc2557eb247e3eaa4d554d45c1b55fc98 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 18 Mar 2016 09:46:10 -0700 Subject: [PATCH 2927/9938] f2fs: show current mount status This patch remains the current mount status to f2fs status info. Signed-off-by: Jaegeuk Kim --- fs/f2fs/debug.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index f4a61a5ff79f..818064bacfda 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -216,8 +216,9 @@ static int stat_show(struct seq_file *s, void *v) list_for_each_entry(si, &f2fs_stat_list, stat_list) { update_general_status(si->sbi); - seq_printf(s, "\n=====[ partition info(%pg). #%d ]=====\n", - si->sbi->sb->s_bdev, i++); + seq_printf(s, "\n=====[ partition info(%pg). #%d, %s]=====\n", + si->sbi->sb->s_bdev, i++, + f2fs_readonly(si->sbi->sb) ? "RO": "RW"); seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", si->sit_area_segs, si->nat_area_segs); seq_printf(s, "[SSA: %d] [MAIN: %d", -- GitLab From 675f10bde6cc3874632a8f684df2a8a2a8ace76e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 22 Feb 2016 18:29:18 +0800 Subject: [PATCH 2928/9938] f2fs: fix to convert inline directory correctly With below serials, we will lose parts of dirents: 1) mount f2fs with inline_dentry option 2) echo 1 > /sys/fs/f2fs/sdX/dir_level 3) mkdir dir 4) touch 180 files named [1-180] in dir 5) touch 181 in dir 6) echo 3 > /proc/sys/vm/drop_caches 7) ll dir ls: cannot access 2: No such file or directory ls: cannot access 4: No such file or directory ls: cannot access 5: No such file or directory ls: cannot access 6: No such file or directory ls: cannot access 8: No such file or directory ls: cannot access 9: No such file or directory ... total 360 drwxr-xr-x 2 root root 4096 Feb 19 15:12 ./ drwxr-xr-x 3 root root 4096 Feb 19 15:11 ../ -rw-r--r-- 1 root root 0 Feb 19 15:12 1 -rw-r--r-- 1 root root 0 Feb 19 15:12 10 -rw-r--r-- 1 root root 0 Feb 19 15:12 100 -????????? ? ? ? ? ? 101 -????????? ? ? ? ? ? 102 -????????? ? ? ? ? ? 103 ... The reason is: when doing the inline dir conversion, we didn't consider that directory has hierarchical hash structure which can be configured through sysfs interface 'dir_level'. By default, dir_level of directory inode is 0, it means we have one bucket in hash table located in first level, all dirents will be hashed in this bucket, so it has no problem for us to do the duplication simply between inline dentry page and converted normal dentry page. However, if we configured dir_level with the value N (greater than 0), it will expand the bucket number of first level hash table by 2^N - 1, it hashs dirents into different buckets according their hash value, if we still move all dirents to first bucket, it makes incorrent locating for inline dirents, the result is, although we can iterate all dirents through ->readdir, we can't stat some of them in ->lookup which based on hash table searching. This patch fixes this issue by rehashing dirents into correct position when converting inline directory. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/dir.c | 87 ++++++++++++++++++++------------------ fs/f2fs/f2fs.h | 4 +- fs/f2fs/inline.c | 94 ++++++++++++++++++++++++++++++++++++++++- include/linux/f2fs_fs.h | 2 + 4 files changed, 144 insertions(+), 43 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index af819571bce7..e90380d82214 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -48,7 +48,6 @@ unsigned char f2fs_filetype_table[F2FS_FT_MAX] = { [F2FS_FT_SYMLINK] = DT_LNK, }; -#define S_SHIFT 12 static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = { [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE, [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR, @@ -64,6 +63,13 @@ void set_de_type(struct f2fs_dir_entry *de, umode_t mode) de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; } +unsigned char get_de_type(struct f2fs_dir_entry *de) +{ + if (de->file_type < F2FS_FT_MAX) + return f2fs_filetype_table[de->file_type]; + return DT_UNKNOWN; +} + static unsigned long dir_block_index(unsigned int level, int dir_level, unsigned int idx) { @@ -509,11 +515,7 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d, } } -/* - * Caller should grab and release a rwsem by calling f2fs_lock_op() and - * f2fs_unlock_op(). - */ -int __f2fs_add_link(struct inode *dir, const struct qstr *name, +int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, struct inode *inode, nid_t ino, umode_t mode) { unsigned int bit_pos; @@ -526,28 +528,11 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, struct f2fs_dentry_block *dentry_blk = NULL; struct f2fs_dentry_ptr d; struct page *page = NULL; - struct fscrypt_name fname; - struct qstr new_name; - int slots, err; - - err = fscrypt_setup_filename(dir, name, 0, &fname); - if (err) - return err; - - new_name.name = fname_name(&fname); - new_name.len = fname_len(&fname); - - if (f2fs_has_inline_dentry(dir)) { - err = f2fs_add_inline_entry(dir, &new_name, inode, ino, mode); - if (!err || err != -EAGAIN) - goto out; - else - err = 0; - } + int slots, err = 0; level = 0; - slots = GET_DENTRY_SLOTS(new_name.len); - dentry_hash = f2fs_dentry_hash(&new_name); + slots = GET_DENTRY_SLOTS(new_name->len); + dentry_hash = f2fs_dentry_hash(new_name); current_depth = F2FS_I(dir)->i_current_depth; if (F2FS_I(dir)->chash == dentry_hash) { @@ -556,10 +541,8 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, } start: - if (unlikely(current_depth == MAX_DIR_HASH_DEPTH)) { - err = -ENOSPC; - goto out; - } + if (unlikely(current_depth == MAX_DIR_HASH_DEPTH)) + return -ENOSPC; /* Increase the depth, if required */ if (level == current_depth) @@ -573,10 +556,8 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, for (block = bidx; block <= (bidx + nblock - 1); block++) { dentry_page = get_new_data_page(dir, NULL, block, true); - if (IS_ERR(dentry_page)) { - err = PTR_ERR(dentry_page); - goto out; - } + if (IS_ERR(dentry_page)) + return PTR_ERR(dentry_page); dentry_blk = kmap(dentry_page); bit_pos = room_for_filename(&dentry_blk->dentry_bitmap, @@ -596,7 +577,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, if (inode) { down_write(&F2FS_I(inode)->i_sem); - page = init_inode_metadata(inode, dir, &new_name, NULL); + page = init_inode_metadata(inode, dir, new_name, NULL); if (IS_ERR(page)) { err = PTR_ERR(page); goto fail; @@ -606,7 +587,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, } make_dentry_ptr(NULL, &d, (void *)dentry_blk, 1); - f2fs_update_dentry(ino, mode, &d, &new_name, dentry_hash, bit_pos); + f2fs_update_dentry(ino, mode, &d, new_name, dentry_hash, bit_pos); set_page_dirty(dentry_page); @@ -628,7 +609,34 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, } kunmap(dentry_page); f2fs_put_page(dentry_page, 1); -out: + + return err; +} + +/* + * Caller should grab and release a rwsem by calling f2fs_lock_op() and + * f2fs_unlock_op(). + */ +int __f2fs_add_link(struct inode *dir, const struct qstr *name, + struct inode *inode, nid_t ino, umode_t mode) +{ + struct fscrypt_name fname; + struct qstr new_name; + int err; + + err = fscrypt_setup_filename(dir, name, 0, &fname); + if (err) + return err; + + new_name.name = fname_name(&fname); + new_name.len = fname_len(&fname); + + err = -EAGAIN; + if (f2fs_has_inline_dentry(dir)) + err = f2fs_add_inline_entry(dir, &new_name, inode, ino, mode); + if (err == -EAGAIN) + err = f2fs_add_regular_entry(dir, &new_name, inode, ino, mode); + fscrypt_free_filename(&fname); f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); return err; @@ -792,10 +800,7 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, continue; } - if (de->file_type < F2FS_FT_MAX) - d_type = f2fs_filetype_table[de->file_type]; - else - d_type = DT_UNKNOWN; + d_type = get_de_type(de); de_name.name = d->filename[bit_pos]; de_name.len = le16_to_cpu(de->name_len); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e1c07b60f301..3f1551395244 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1711,7 +1711,7 @@ struct dentry *f2fs_get_parent(struct dentry *child); */ extern unsigned char f2fs_filetype_table[F2FS_FT_MAX]; void set_de_type(struct f2fs_dir_entry *, umode_t); - +unsigned char get_de_type(struct f2fs_dir_entry *); struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *, f2fs_hash_t, int *, struct f2fs_dentry_ptr *); bool f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *, @@ -1732,6 +1732,8 @@ void f2fs_set_link(struct inode *, struct f2fs_dir_entry *, int update_dent_inode(struct inode *, struct inode *, const struct qstr *); void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *, const struct qstr *, f2fs_hash_t , unsigned int); +int f2fs_add_regular_entry(struct inode *, const struct qstr *, + struct inode *, nid_t, umode_t); int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *, nid_t, umode_t); void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *, diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index a2fbe6f427d3..772056587eb9 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -355,7 +355,7 @@ int make_empty_inline_dir(struct inode *inode, struct inode *parent, * NOTE: ipage is grabbed by caller, but if any error occurs, we should * release ipage in this function. */ -static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, +static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, struct f2fs_inline_dentry *inline_dentry) { struct page *page; @@ -416,6 +416,98 @@ static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, return err; } +static int f2fs_add_inline_entries(struct inode *dir, + struct f2fs_inline_dentry *inline_dentry) +{ + struct f2fs_dentry_ptr d; + unsigned long bit_pos = 0; + int err = 0; + + make_dentry_ptr(NULL, &d, (void *)inline_dentry, 2); + + while (bit_pos < d.max) { + struct f2fs_dir_entry *de; + struct qstr new_name; + nid_t ino; + umode_t fake_mode; + + if (!test_bit_le(bit_pos, d.bitmap)) { + bit_pos++; + continue; + } + + de = &d.dentry[bit_pos]; + new_name.name = d.filename[bit_pos]; + new_name.len = de->name_len; + + ino = le32_to_cpu(de->ino); + fake_mode = get_de_type(de) << S_SHIFT; + + err = f2fs_add_regular_entry(dir, &new_name, NULL, + ino, fake_mode); + if (err) + goto punch_dentry_pages; + + if (unlikely(!de->name_len)) + d.max = -1; + + bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); + } + return 0; +punch_dentry_pages: + truncate_inode_pages(&dir->i_data, 0); + truncate_blocks(dir, 0, false); + remove_dirty_inode(dir); + return err; +} + +static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage, + struct f2fs_inline_dentry *inline_dentry) +{ + struct f2fs_inline_dentry *backup_dentry; + int err; + + backup_dentry = kmalloc(sizeof(struct f2fs_inline_dentry), + GFP_F2FS_ZERO); + if (!backup_dentry) + return -ENOMEM; + + memcpy(backup_dentry, inline_dentry, MAX_INLINE_DATA); + truncate_inline_inode(ipage, 0); + + unlock_page(ipage); + + err = f2fs_add_inline_entries(dir, backup_dentry); + if (err) + goto recover; + + lock_page(ipage); + + stat_dec_inline_dir(dir); + clear_inode_flag(F2FS_I(dir), FI_INLINE_DENTRY); + update_inode(dir, ipage); + kfree(backup_dentry); + return 0; +recover: + lock_page(ipage); + memcpy(inline_dentry, backup_dentry, MAX_INLINE_DATA); + i_size_write(dir, MAX_INLINE_DATA); + update_inode(dir, ipage); + f2fs_put_page(ipage, 1); + + kfree(backup_dentry); + return err; +} + +static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, + struct f2fs_inline_dentry *inline_dentry) +{ + if (!F2FS_I(dir)->i_dir_level) + return f2fs_move_inline_dirents(dir, ipage, inline_dentry); + else + return f2fs_move_rehashed_dirents(dir, ipage, inline_dentry); +} + int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name, struct inode *inode, nid_t ino, umode_t mode) { diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index b90e9bdbd1dd..4c02c6521fef 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -508,4 +508,6 @@ enum { F2FS_FT_MAX }; +#define S_SHIFT 12 + #endif /* _LINUX_F2FS_FS_H */ -- GitLab From 4a6de50d5408cdc699588119e2338e580adc2b73 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 30 Mar 2016 11:25:31 -0700 Subject: [PATCH 2929/9938] f2fs: use PGP_LOCK to check its truncation Previously, after trylock_page is succeeded, it doesn't check its mapping. In order to fix that, we can just give PGP_LOCK to pagecache_get_page. Signed-off-by: Jaegeuk Kim --- fs/f2fs/node.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 1a33de9d84b1..ade221c9756b 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1202,13 +1202,10 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) if (!inode) return; - page = pagecache_get_page(inode->i_mapping, 0, FGP_NOWAIT, 0); + page = pagecache_get_page(inode->i_mapping, 0, FGP_LOCK|FGP_NOWAIT, 0); if (!page) goto iput_out; - if (!trylock_page(page)) - goto release_out; - if (!PageUptodate(page)) goto page_out; @@ -1223,9 +1220,7 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) else set_page_dirty(page); page_out: - unlock_page(page); -release_out: - f2fs_put_page(page, 0); + f2fs_put_page(page, 1); iput_out: iput(inode); } -- GitLab From ff37355886ac2082cee594aa949c08e2cfb33aa0 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 29 Mar 2016 16:13:45 -0700 Subject: [PATCH 2930/9938] f2fs: add BUG_ON to avoid unnecessary flow This patch adds BUG_ON instead of retrying loop. In the case of node pages, we already got this inode page, but unlocked it. By the fact that we don't truncate any node pages in operations, the page's mapping should be unchangeable. Signed-off-by: Jaegeuk Kim --- fs/f2fs/node.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index ade221c9756b..095fc2c96e16 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -832,7 +832,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from) trace_f2fs_truncate_inode_blocks_enter(inode, from); level = get_node_path(inode, from, offset, noffset); -restart: + page = get_node_page(sbi, inode->i_ino); if (IS_ERR(page)) { trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); @@ -896,10 +896,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from) if (offset[1] == 0 && ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) { lock_page(page); - if (unlikely(page->mapping != NODE_MAPPING(sbi))) { - f2fs_put_page(page, 1); - goto restart; - } + BUG_ON(page->mapping != NODE_MAPPING(sbi)); f2fs_wait_on_page_writeback(page, NODE, true); ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; set_page_dirty(page); -- GitLab From de5307e46d28aa26ffd6f2048398b6303e134a67 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 11 Apr 2016 11:51:51 -0700 Subject: [PATCH 2931/9938] f2fs: fix dropping inmemory pages in a wrong time When one reader closes its file while the other writer is doing atomic writes, f2fs_release_file drops atomic data resulting in an empty commit. This patch fixes this wrong commit problem by checking openess of the file. Process0 Process1 open file start atomic write write data read data close file f2fs_release_file() clear atomic data commit atomic write Reported-by: Miao Xie Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 90d1157a09f9..e10eb61d9f62 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1254,6 +1254,14 @@ static long f2fs_fallocate(struct file *file, int mode, static int f2fs_release_file(struct inode *inode, struct file *filp) { + /* + * f2fs_relase_file is called at every close calls. So we should + * not drop any inmemory pages by close called by other process. + */ + if (!(filp->f_mode & FMODE_WRITE) || + atomic_read(&inode->i_writecount) != 1) + return 0; + /* some remained atomic pages should discarded */ if (f2fs_is_atomic_file(inode)) drop_inmem_pages(inode); -- GitLab From 26dc3d4424e9f4764d633bd8f9309a01e6f364dd Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 11 Apr 2016 13:15:10 -0700 Subject: [PATCH 2932/9938] f2fs: unset atomic/volatile flag in f2fs_release_file The atomic/volatile operation should be done in pair of start and commit ioctl. For example, if a killed process remains open-ended atomic operation, we should drop its flag as well as its atomic data. Otherwise, if sqlite initiates another operation which doesn't require atomic writes, it will lose every data, since f2fs still treats with them as atomic writes; nobody will trigger its commit. Reported-by: Miao Xie Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 5 ++--- fs/f2fs/segment.c | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index e10eb61d9f62..ed389f6a37b4 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1266,6 +1266,7 @@ static int f2fs_release_file(struct inode *inode, struct file *filp) if (f2fs_is_atomic_file(inode)) drop_inmem_pages(inode); if (f2fs_is_volatile_file(inode)) { + clear_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); set_inode_flag(F2FS_I(inode), FI_DROP_CACHE); filemap_fdatawrite(inode->i_mapping); clear_inode_flag(F2FS_I(inode), FI_DROP_CACHE); @@ -1449,10 +1450,8 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp) if (ret) return ret; - if (f2fs_is_atomic_file(inode)) { - clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); + if (f2fs_is_atomic_file(inode)) drop_inmem_pages(inode); - } if (f2fs_is_volatile_file(inode)) { clear_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); ret = f2fs_sync_file(filp, 0, LLONG_MAX, 0); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 540669d6978e..299c784f5b61 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -239,6 +239,8 @@ void drop_inmem_pages(struct inode *inode) { struct f2fs_inode_info *fi = F2FS_I(inode); + clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); + mutex_lock(&fi->inmem_lock); __revoke_inmem_pages(inode, &fi->inmem_pages, true, false); mutex_unlock(&fi->inmem_lock); -- GitLab From 4da7bf5a4345f3ce9699476a8022f66cfb4a8ce9 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 6 Apr 2016 11:27:03 -0700 Subject: [PATCH 2933/9938] f2fs: remove redundant condition check This patch resolves the redundant condition check reported by David. Reported-by: David Binderman Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/data.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 0955312e5ca0..b92782f40643 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -211,7 +211,7 @@ void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index) bool readahead = false; page = find_get_page(META_MAPPING(sbi), index); - if (!page || (page && !PageUptodate(page))) + if (!page || !PageUptodate(page)) readahead = true; f2fs_put_page(page, 0); diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 5dafb9cef12e..c29bcf4cfca1 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1496,7 +1496,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, } else { /* hole case */ err = get_dnode_of_data(&dn, index, LOOKUP_NODE); - if (err || (!err && dn.data_blkaddr == NULL_ADDR)) { + if (err || dn.data_blkaddr == NULL_ADDR) { f2fs_put_dnode(&dn); f2fs_lock_op(sbi); locked = true; -- GitLab From 58457f1c355545c468b8aed5c431d8a6bb71d35d Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 12 Apr 2016 11:52:30 -0700 Subject: [PATCH 2934/9938] f2fs: give -E2BIG for no space in xattr This patch returns -E2BIG if there is no space to add an xattr entry. This should fix generic/026 in xfstests as well. Signed-off-by: Jaegeuk Kim --- fs/f2fs/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 06a72dc0191a..152971243ad8 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -500,7 +500,7 @@ static int __f2fs_setxattr(struct inode *inode, int index, free = free + ENTRY_SIZE(here); if (unlikely(free < newsize)) { - error = -ENOSPC; + error = -E2BIG; goto exit; } } -- GitLab From 63c52d7878903a014fa4c9075afd051b1e77597b Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 12 Apr 2016 14:11:03 -0700 Subject: [PATCH 2935/9938] f2fs: don't invalidate atomic page if successful If we committed atomic write successfully, we don't need to invalidate pages. Signed-off-by: Jaegeuk Kim --- fs/f2fs/segment.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 299c784f5b61..770cdc95120f 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -223,9 +223,10 @@ static int __revoke_inmem_pages(struct inode *inode, f2fs_put_dnode(&dn); } next: - ClearPageUptodate(page); + /* we don't need to invalidate this in the sccessful status */ + if (drop || recover) + ClearPageUptodate(page); set_page_private(page, 0); - ClearPageUptodate(page); f2fs_put_page(page, 1); list_del(&cur->list); -- GitLab From c27753d675fccd3b15a78621a2a66616507693d4 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 12 Apr 2016 14:36:11 -0700 Subject: [PATCH 2936/9938] f2fs: flush dirty pages before starting atomic writes If somebody wrote some data before atomic writes, we should flush them in order to handle atomic data in a right period. Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index ed389f6a37b4..7de90e60abd1 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1369,7 +1369,16 @@ static int f2fs_ioc_start_atomic_write(struct file *filp) set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); - return 0; + if (!get_dirty_pages(inode)) + return 0; + + f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING, + "Unexpected flush for atomic writes: ino=%lu, npages=%u", + inode->i_ino, get_dirty_pages(inode)); + ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); + if (ret) + clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); + return ret; } static int f2fs_ioc_commit_atomic_write(struct file *filp) -- GitLab From 2158ab084b721da7b0e4963ac91fd96775b80916 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Tue, 29 Mar 2016 19:27:14 +0800 Subject: [PATCH 2937/9938] arm64: dts: register Hi6220's thermal sensor Bind thermal sensor driver for Hi6220. Signed-off-by: Leo Yan Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 7b7bbf66f004..fc61a164eceb 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -772,5 +772,14 @@ pinctrl-0 = <&sdio_pmx_func &sdio_clk_cfg_func &sdio_cfg_func>; pinctrl-1 = <&sdio_pmx_idle &sdio_clk_cfg_idle &sdio_cfg_idle>; }; + + tsensor: tsensor@0,f7030700 { + compatible = "hisilicon,tsensor"; + reg = <0x0 0xf7030700 0x0 0x1000>; + interrupts = ; + clocks = <&sys_ctrl 22>; + clock-names = "thermal_clk"; + #thermal-sensor-cells = <1>; + }; }; }; -- GitLab From cd0b69ec0eb5e489954d7125b934457ac7acf6f7 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Tue, 29 Mar 2016 19:27:15 +0800 Subject: [PATCH 2938/9938] arm64: dts: register Hi6220's thermal zone for power allocator With profiling Hi6220's power modeling so get dynamic coefficient and sustainable power. So pass these parameters from DT. Now enable power allocator with only one actor for CPU part, so directly use cluster0's thermal sensor for monitoring temperature. Reviewed-by: Javi Merino Signed-off-by: Leo Yan Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index fc61a164eceb..0c8df8a93dbe 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -7,6 +7,7 @@ #include #include #include +#include / { compatible = "hisilicon,hi6220"; @@ -88,6 +89,7 @@ cooling-max-level = <0>; #cooling-cells = <2>; /* min followed by max */ cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <311>; }; cpu1: cpu@1 { @@ -781,5 +783,38 @@ clock-names = "thermal_clk"; #thermal-sensor-cells = <1>; }; + + thermal-zones { + + cls0: cls0 { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3326>; + + /* sensor ID */ + thermal-sensors = <&tsensor 2>; + + trips { + threshold: trip-point@0 { + temperature = <65000>; + hysteresis = <0>; + type = "passive"; + }; + + target: trip-point@1 { + temperature = <75000>; + hysteresis = <0>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&target>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; }; }; -- GitLab From 6485160396fcec2fa8a0acfa7c8c090f020db694 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Fri, 26 Feb 2016 13:28:34 +0800 Subject: [PATCH 2939/9938] arm64: dts: Add L2 cache topology to Hi6220 This patch adds the L2 cache topology on Hi6220. Hi6220 has two clusters, every cluster has 512KiB L2 cache (32KiB x 16 ways). Signed-off-by: Leo Yan Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 0c8df8a93dbe..189d21541f9c 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -83,6 +83,7 @@ device_type = "cpu"; reg = <0x0 0x0>; enable-method = "psci"; + next-level-cache = <&CLUSTER0_L2>; clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cooling-min-level = <4>; @@ -97,6 +98,7 @@ device_type = "cpu"; reg = <0x0 0x1>; enable-method = "psci"; + next-level-cache = <&CLUSTER0_L2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -106,6 +108,7 @@ device_type = "cpu"; reg = <0x0 0x2>; enable-method = "psci"; + next-level-cache = <&CLUSTER0_L2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -115,6 +118,7 @@ device_type = "cpu"; reg = <0x0 0x3>; enable-method = "psci"; + next-level-cache = <&CLUSTER0_L2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -124,6 +128,7 @@ device_type = "cpu"; reg = <0x0 0x100>; enable-method = "psci"; + next-level-cache = <&CLUSTER1_L2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -133,6 +138,7 @@ device_type = "cpu"; reg = <0x0 0x101>; enable-method = "psci"; + next-level-cache = <&CLUSTER1_L2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -142,6 +148,7 @@ device_type = "cpu"; reg = <0x0 0x102>; enable-method = "psci"; + next-level-cache = <&CLUSTER1_L2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; @@ -151,9 +158,18 @@ device_type = "cpu"; reg = <0x0 0x103>; enable-method = "psci"; + next-level-cache = <&CLUSTER1_L2>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; + + CLUSTER0_L2: l2-cache0 { + compatible = "cache"; + }; + + CLUSTER1_L2: l2-cache1 { + compatible = "cache"; + }; }; cpu_opp_table: cpu_opp_table { -- GitLab From 72b67b3fcb5f500e73dfd42dce3a4749ba84e4bf Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 15 Apr 2016 15:32:52 +0900 Subject: [PATCH 2940/9938] dt-bindings: clock: Add the clock id for ACLK clock of Exynos542x SoC This patch adds the clock id for ACLK clock of Exynos542x SoC. ACLK clock means the source clock of AMBA AXI bus. This clock id should be used for Bus frequency scaling. Signed-off-by: Chanwoo Choi Tested-by: Markus Reichl Tested-by: Anand Moon Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos5420.h | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/exynos5420.h b/include/dt-bindings/clock/exynos5420.h index 7699ee9c16c0..17ab8394bec7 100644 --- a/include/dt-bindings/clock/exynos5420.h +++ b/include/dt-bindings/clock/exynos5420.h @@ -217,8 +217,30 @@ /* divider clocks */ #define CLK_DOUT_PIXEL 768 +#define CLK_DOUT_ACLK400_WCORE 769 +#define CLK_DOUT_ACLK400_ISP 770 +#define CLK_DOUT_ACLK400_MSCL 771 +#define CLK_DOUT_ACLK200 772 +#define CLK_DOUT_ACLK200_FSYS2 773 +#define CLK_DOUT_ACLK100_NOC 774 +#define CLK_DOUT_PCLK200_FSYS 775 +#define CLK_DOUT_ACLK200_FSYS 776 +#define CLK_DOUT_ACLK333_432_GSCL 777 +#define CLK_DOUT_ACLK333_432_ISP 778 +#define CLK_DOUT_ACLK66 779 +#define CLK_DOUT_ACLK333_432_ISP0 780 +#define CLK_DOUT_ACLK266 781 +#define CLK_DOUT_ACLK166 782 +#define CLK_DOUT_ACLK333 783 +#define CLK_DOUT_ACLK333_G2D 784 +#define CLK_DOUT_ACLK266_G2D 785 +#define CLK_DOUT_ACLK_G3D 786 +#define CLK_DOUT_ACLK300_JPEG 787 +#define CLK_DOUT_ACLK300_DISP1 788 +#define CLK_DOUT_ACLK300_GSCL 789 +#define CLK_DOUT_ACLK400_DISP1 790 /* must be greater than maximal clock id */ -#define CLK_NR_CLKS 769 +#define CLK_NR_CLKS 791 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5420_H */ -- GitLab From 81fed6e342c04a4ecb0650c914d24bd57c6c168f Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 15 Apr 2016 15:32:53 +0900 Subject: [PATCH 2941/9938] clk: samsung: exynos542x: Add the clock id for ACLK This patch adds the clock id for ACLK clock which is source clock of AMBA AXI bus. This clock should be handled in the bus frequency scaling driver. Signed-off-by: Chanwoo Choi Tested-by: Markus Reichl Tested-by: Anand Moon Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 77 +++++++++++++++++----------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index be03ed0fcb6b..92382cef9f90 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -554,8 +554,8 @@ static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = { }; static struct samsung_div_clock exynos5800_div_clks[] __initdata = { - DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3), - + DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore", + "mout_aclk400_wcore", DIV_TOP0, 16, 3), DIV(0, "dout_aclk550_cam", "mout_aclk550_cam", DIV_TOP8, 16, 3), DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam", @@ -607,8 +607,8 @@ static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { }; static struct samsung_div_clock exynos5420_div_clks[] __initdata = { - DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll", - DIV_TOP0, 16, 3), + DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore", + "mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3), }; static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { @@ -785,31 +785,47 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = { DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3), DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3), - DIV(0, "dout_aclk400_isp", "mout_aclk400_isp", DIV_TOP0, 0, 3), - DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3), - DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3), - DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3), - DIV(0, "dout_aclk100_noc", "mout_aclk100_noc", DIV_TOP0, 20, 3), - DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3), - DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3), - - DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl", - DIV_TOP1, 0, 3), - DIV(0, "dout_aclk333_432_isp", "mout_aclk333_432_isp", - DIV_TOP1, 4, 3), - DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6), - DIV(0, "dout_aclk333_432_isp0", "mout_aclk333_432_isp0", - DIV_TOP1, 16, 3), - DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3), - DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3), - DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3), - - DIV(0, "dout_aclk333_g2d", "mout_aclk333_g2d", DIV_TOP2, 8, 3), - DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3), - DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3), - DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3), - DIV(0, "dout_aclk300_disp1", "mout_aclk300_disp1", DIV_TOP2, 24, 3), - DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3), + DIV(CLK_DOUT_ACLK400_ISP, "dout_aclk400_isp", "mout_aclk400_isp", + DIV_TOP0, 0, 3), + DIV(CLK_DOUT_ACLK400_MSCL, "dout_aclk400_mscl", "mout_aclk400_mscl", + DIV_TOP0, 4, 3), + DIV(CLK_DOUT_ACLK200, "dout_aclk200", "mout_aclk200", + DIV_TOP0, 8, 3), + DIV(CLK_DOUT_ACLK200_FSYS2, "dout_aclk200_fsys2", "mout_aclk200_fsys2", + DIV_TOP0, 12, 3), + DIV(CLK_DOUT_ACLK100_NOC, "dout_aclk100_noc", "mout_aclk100_noc", + DIV_TOP0, 20, 3), + DIV(CLK_DOUT_PCLK200_FSYS, "dout_pclk200_fsys", "mout_pclk200_fsys", + DIV_TOP0, 24, 3), + DIV(CLK_DOUT_ACLK200_FSYS, "dout_aclk200_fsys", "mout_aclk200_fsys", + DIV_TOP0, 28, 3), + DIV(CLK_DOUT_ACLK333_432_GSCL, "dout_aclk333_432_gscl", + "mout_aclk333_432_gscl", DIV_TOP1, 0, 3), + DIV(CLK_DOUT_ACLK333_432_ISP, "dout_aclk333_432_isp", + "mout_aclk333_432_isp", DIV_TOP1, 4, 3), + DIV(CLK_DOUT_ACLK66, "dout_aclk66", "mout_aclk66", + DIV_TOP1, 8, 6), + DIV(CLK_DOUT_ACLK333_432_ISP0, "dout_aclk333_432_isp0", + "mout_aclk333_432_isp0", DIV_TOP1, 16, 3), + DIV(CLK_DOUT_ACLK266, "dout_aclk266", "mout_aclk266", + DIV_TOP1, 20, 3), + DIV(CLK_DOUT_ACLK166, "dout_aclk166", "mout_aclk166", + DIV_TOP1, 24, 3), + DIV(CLK_DOUT_ACLK333, "dout_aclk333", "mout_aclk333", + DIV_TOP1, 28, 3), + + DIV(CLK_DOUT_ACLK333_G2D, "dout_aclk333_g2d", "mout_aclk333_g2d", + DIV_TOP2, 8, 3), + DIV(CLK_DOUT_ACLK266_G2D, "dout_aclk266_g2d", "mout_aclk266_g2d", + DIV_TOP2, 12, 3), + DIV(CLK_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, + 16, 3), + DIV(CLK_DOUT_ACLK300_JPEG, "dout_aclk300_jpeg", "mout_aclk300_jpeg", + DIV_TOP2, 20, 3), + DIV(CLK_DOUT_ACLK300_DISP1, "dout_aclk300_disp1", + "mout_aclk300_disp1", DIV_TOP2, 24, 3), + DIV(CLK_DOUT_ACLK300_GSCL, "dout_aclk300_gscl", "mout_aclk300_gscl", + DIV_TOP2, 28, 3), /* DISP1 Block */ DIV(0, "dout_fimd1", "mout_fimd1_final", DIV_DISP10, 0, 4), @@ -817,7 +833,8 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = { DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2), - DIV(0, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3), + DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1", + "mout_aclk400_disp1", DIV_TOP2, 4, 3), /* Audio Block */ DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), -- GitLab From e519bd9a07fe5b13c47b506d0fbadb7498e60607 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 Apr 2016 10:20:10 -0300 Subject: [PATCH 2942/9938] perf trace: Do not print interrupted syscalls when using --duration With multiple threads, e.g. a system wide trace session, and one syscall is midway in a thread and another thread starts another syscall we must print the start of the interrupted syscall followed by ..., but that can't be done that way when we use the --duration filter, as we have to wait for the syscall exit to calculate the duration and decide if it should be filtered, so we have to disable the interrupted logic and only print at syscall exit, duh. Before: # trace --duration 100 9.248 (0.023 ms): gnome-shell/2287 poll(ufds: 0x7ffc5ea26580, nfds: 1, timeout_msecs: 4294967295) ... 9.296 (0.001 ms): gnome-shell/2287 recvmsg(fd: 11, msg: 0x7ffc5ea264a0 ) ... 9.311 (0.008 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) ... 9.859 (0.023 ms): gnome-shell/2287 poll(ufds: 0x7ffc5ea24250, nfds: 1, timeout_msecs: 4294967295) ... 9.942 (0.051 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) ... 10.467 (0.003 ms): gnome-shell/2287 poll(ufds: 0x55e623431220, nfds: 50, timeout_msecs: 4294967295) ... 11.136 (0.382 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) ... 11.223 (0.023 ms): SoftwareVsyncT/24369 futex(uaddr: 0x7f5ec5df8c14, op: WAIT_BITSET|PRIV, val: 1, utime: 0x7f5ec5df8b68, val3: 4294967295) ... 16.865 (5.501 ms): firefox/24321 poll(ufds: 0x7f5ec388b460, nfds: 6, timeout_msecs: 4294967295 ) ... 22.571 (0.006 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) ... 26.793 (4.063 ms): gnome-shell/2287 poll(ufds: 0x55e623431220, nfds: 50, timeout_msecs: 4294967295) ... 26.917 (0.080 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) ... 27.291 (0.355 ms): qemu-system-x8/10065 ppoll(ufds: 0x55c98b39e400, nfds: 72, tsp: 0x7fffe4e4fe60, sigsetsize: 8) ... 27.336 (0.012 ms): SoftwareVsyncT/24369 futex(uaddr: 0x7f5ec5df8c14, op: WAIT_BITSET|PRIV, val: 1, utime: 0x7f5ec5df8b68, val3: 4294967295) ... 33.370 (5.958 ms): firefox/24321 poll(ufds: 0x7f5ec388b460, nfds: 6, timeout_msecs: 4294967295) ... 33.866 (0.021 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) ... 35.762 (1.611 ms): gnome-shell/2287 poll(ufds: 0x55e623431220, nfds: 50, timeout_msecs: 8 ) ... 38.765 (2.910 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) ... After: # trace --duration 100 238.292 (153.226 ms): hexchat/2786 poll(ufds: 0x559ea372f370, nfds: 6, timeout_msecs: 153) = 0 Timeout 249.634 (199.433 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x7ffdcbb63610 ) = 1 385.583 (147.257 ms): hexchat/2786 poll(ufds: 0x559ea372f370, nfds: 6, timeout_msecs: 147) = 0 Timeout 397.166 (110.779 ms): gnome-shell/2287 poll(ufds: 0x55e623431220, nfds: 50, timeout_msecs: 4294967295) = 1 601.839 (132.066 ms): Xorg/2025 select(n: 512, inp: 0x83a8e0, tvp: 0x8316a0 ) = 1 602.445 (132.679 ms): gnome-shell/2287 poll(ufds: 0x55e623431220, nfds: 50, timeout_msecs: 4294967295) = 1 686.122 (300.418 ms): hexchat/2786 poll(ufds: 0x559ea372f370, nfds: 6, timeout_msecs: 300) = 0 Timeout 815.033 (184.641 ms): JS Helper/24352 futex(uaddr: 0x7f5ed98e584c, op: WAIT|PRIV, val: 1149859) = 0 825.868 (195.469 ms): JS Helper/24351 futex(uaddr: 0x7f5ed98e584c, op: WAIT|PRIV, val: 1149860) = 0 840.738 (210.335 ms): JS Helper/24350 futex(uaddr: 0x7f5ed98e584c, op: WAIT|PRIV, val: 1149861) = 0 914.898 (158.692 ms): Compositor/24363 futex(uaddr: 0x7f5ec8dfebf4, op: WAIT|PRIV, val: 1) = 0 915.199 (100.747 ms): Timer/24358 futex(uaddr: 0x7f5ed98e56cc, op: WAIT_BITSET|PRIV|CLKRT, val: 2545397, utime: 0x7f5ecdbfec30, val3: 4294967295) = 0 986.639 (247.325 ms): hexchat/2786 poll(ufds: 0x559ea372f370, nfds: 6, timeout_msecs: 247) = 0 Timeout 996.239 (500.591 ms): chrome/16237 poll(ufds: 0x3ecd739bd0, nfds: 5, timeout_msecs: 500) = 0 Timeout 1042.890 (120.076 ms): Timer/24358 futex(uaddr: 0x7f5ed98e56cc, op: WAIT_BITSET|PRIV|CLKRT, val: 2545403, utime: 0x7f5ecdbfec30, val3: 4294967295) = -1 ETIMEDOUT Connection timed out Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-d2nay6kjax5ro991c9kelvi5@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 39a158923acf..65f6abe75d71 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1849,7 +1849,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, goto out_put; } - if (!trace->summary_only) + if (!(trace->duration_filter || trace->summary_only)) trace__printf_interrupted_entry(trace, sample); ttrace->entry_time = sample->time; -- GitLab From 5cf9c84e21067ec7a44648aedbc38c197d707258 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 Apr 2016 11:10:31 -0300 Subject: [PATCH 2943/9938] perf trace: Introduce --min-stack filter Counterpart to --max-stack, to help focusing on deeply nested calls. Can be combined with --duration, etc. E.g.: System wide syscall tracing looking for call stacks longer than 66: # trace --mmap-pages 32768 --filter-pid 2711 --call-graph dwarf,16384 --min-stack 66 Or more compactly: # trace -m 32768 --filt 2711 --call dwarf,16384 --min-st 66 363.027 ( 0.002 ms): gnome-shell/2287 poll(ufds: 0x7ffc5ea24230, nfds: 1, timeout_msecs: 4294967295 ) = 1 [0xf6fdd] (/usr/lib64/libc-2.22.so) _xcb_conn_wait+0x92 (/usr/lib64/libxcb.so.1.1.0) _xcb_out_send+0x4d (/usr/lib64/libxcb.so.1.1.0) xcb_writev+0x45 (/usr/lib64/libxcb.so.1.1.0) _XSend+0x19e (/usr/lib64/libX11.so.6.3.0) _XReply+0x82 (/usr/lib64/libX11.so.6.3.0) XSync+0x4d (/usr/lib64/libX11.so.6.3.0) dri3_bind_tex_image+0x42 (/usr/lib64/libGL.so.1.2.0) _cogl_winsys_texture_pixmap_x11_update+0x117 (/usr/lib64/libcogl.so.20.4.1) _cogl_texture_pixmap_x11_update+0x67 (/usr/lib64/libcogl.so.20.4.1) _cogl_texture_pixmap_x11_pre_paint+0x13 (/usr/lib64/libcogl.so.20.4.1) _cogl_pipeline_layer_pre_paint+0x5e (/usr/lib64/libcogl.so.20.4.1) _cogl_rectangles_validate_layer_cb+0x1b (/usr/lib64/libcogl.so.20.4.1) cogl_pipeline_foreach_layer+0xbe (/usr/lib64/libcogl.so.20.4.1) _cogl_framebuffer_draw_multitextured_rectangles+0x77 (/usr/lib64/libcogl.so.20.4.1) cogl_framebuffer_draw_multitextured_rectangle+0x51 (/usr/lib64/libcogl.so.20.4.1) paint_clipped_rectangle+0xb6 (/usr/lib64/libmutter.so.0.0.0) meta_shaped_texture_paint+0x3e3 (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_window_actor_paint+0x14b (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_window_group_paint+0x19f (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) [0x3d970] (/usr/lib64/gnome-shell/libgnome-shell.so) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_stage_paint+0x3a (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_stage_paint+0x45 (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0x164 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) _clutter_stage_do_paint+0x17b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_stage_cogl_redraw+0x496 (/usr/lib64/libclutter-1.0.so.0.2400.2) _clutter_stage_do_update+0x117 (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_clock_dispatch+0x169 (/usr/lib64/libclutter-1.0.so.0.2400.2) g_main_context_dispatch+0x15a (/usr/lib64/libglib-2.0.so.0.4600.2) g_main_context_iterate.isra.29+0x1e0 (/usr/lib64/libglib-2.0.so.0.4600.2) g_main_loop_run+0xc2 (/usr/lib64/libglib-2.0.so.0.4600.2) meta_run+0x2c (/usr/lib64/libmutter.so.0.0.0) main+0x3f7 (/usr/bin/gnome-shell) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) [0x2909] (/usr/bin/gnome-shell) 363.038 ( 0.006 ms): gnome-shell/2287 writev(fd: 5, vec: 0x7ffc5ea243a0, vlen: 3 ) = 4 __GI___writev+0x2d (/usr/lib64/libc-2.22.so) _xcb_conn_wait+0x359 (/usr/lib64/libxcb.so.1.1.0) _xcb_out_send+0x4d (/usr/lib64/libxcb.so.1.1.0) xcb_writev+0x45 (/usr/lib64/libxcb.so.1.1.0) _XSend+0x19e (/usr/lib64/libX11.so.6.3.0) _XReply+0x82 (/usr/lib64/libX11.so.6.3.0) XSync+0x4d (/usr/lib64/libX11.so.6.3.0) dri3_bind_tex_image+0x42 (/usr/lib64/libGL.so.1.2.0) _cogl_winsys_texture_pixmap_x11_update+0x117 (/usr/lib64/libcogl.so.20.4.1) _cogl_texture_pixmap_x11_update+0x67 (/usr/lib64/libcogl.so.20.4.1) _cogl_texture_pixmap_x11_pre_paint+0x13 (/usr/lib64/libcogl.so.20.4.1) _cogl_pipeline_layer_pre_paint+0x5e (/usr/lib64/libcogl.so.20.4.1) _cogl_rectangles_validate_layer_cb+0x1b (/usr/lib64/libcogl.so.20.4.1) cogl_pipeline_foreach_layer+0xbe (/usr/lib64/libcogl.so.20.4.1) _cogl_framebuffer_draw_multitextured_rectangles+0x77 (/usr/lib64/libcogl.so.20.4.1) cogl_framebuffer_draw_multitextured_rectangle+0x51 (/usr/lib64/libcogl.so.20.4.1) paint_clipped_rectangle+0xb6 (/usr/lib64/libmutter.so.0.0.0) meta_shaped_texture_paint+0x3e3 (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_window_actor_paint+0x14b (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_window_group_paint+0x19f (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) [0x3d970] (/usr/lib64/gnome-shell/libgnome-shell.so) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_stage_paint+0x3a (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_stage_paint+0x45 (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0x164 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) _clutter_stage_do_paint+0x17b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_stage_cogl_redraw+0x496 (/usr/lib64/libclutter-1.0.so.0.2400.2) _clutter_stage_do_update+0x117 (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_clock_dispatch+0x169 (/usr/lib64/libclutter-1.0.so.0.2400.2) g_main_context_dispatch+0x15a (/usr/lib64/libglib-2.0.so.0.4600.2) g_main_context_iterate.isra.29+0x1e0 (/usr/lib64/libglib-2.0.so.0.4600.2) g_main_loop_run+0xc2 (/usr/lib64/libglib-2.0.so.0.4600.2) meta_run+0x2c (/usr/lib64/libmutter.so.0.0.0) main+0x3f7 (/usr/bin/gnome-shell) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) [0x2909] (/usr/bin/gnome-shell) 363.086 ( 0.042 ms): gnome-shell/2287 poll(ufds: 0x7ffc5ea24250, nfds: 1, timeout_msecs: 4294967295 ) = 1 [0xf6fdd] (/usr/lib64/libc-2.22.so) _xcb_conn_wait+0x92 (/usr/lib64/libxcb.so.1.1.0) wait_for_reply+0xb7 (/usr/lib64/libxcb.so.1.1.0) xcb_wait_for_reply+0x61 (/usr/lib64/libxcb.so.1.1.0) _XReply+0x127 (/usr/lib64/libX11.so.6.3.0) XSync+0x4d (/usr/lib64/libX11.so.6.3.0) dri3_bind_tex_image+0x42 (/usr/lib64/libGL.so.1.2.0) _cogl_winsys_texture_pixmap_x11_update+0x117 (/usr/lib64/libcogl.so.20.4.1) _cogl_texture_pixmap_x11_update+0x67 (/usr/lib64/libcogl.so.20.4.1) _cogl_texture_pixmap_x11_pre_paint+0x13 (/usr/lib64/libcogl.so.20.4.1) _cogl_pipeline_layer_pre_paint+0x5e (/usr/lib64/libcogl.so.20.4.1) _cogl_rectangles_validate_layer_cb+0x1b (/usr/lib64/libcogl.so.20.4.1) cogl_pipeline_foreach_layer+0xbe (/usr/lib64/libcogl.so.20.4.1) _cogl_framebuffer_draw_multitextured_rectangles+0x77 (/usr/lib64/libcogl.so.20.4.1) cogl_framebuffer_draw_multitextured_rectangle+0x51 (/usr/lib64/libcogl.so.20.4.1) paint_clipped_rectangle+0xb6 (/usr/lib64/libmutter.so.0.0.0) meta_shaped_texture_paint+0x3e3 (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_window_actor_paint+0x14b (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_real_paint+0x20 (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_window_group_paint+0x19f (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) [0x3d970] (/usr/lib64/gnome-shell/libgnome-shell.so) _g_closure_invoke_va+0xb2 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_stage_paint+0x3a (/usr/lib64/libclutter-1.0.so.0.2400.2) meta_stage_paint+0x45 (/usr/lib64/libmutter.so.0.0.0) _g_closure_invoke_va+0x164 (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit_valist+0xc0d (/usr/lib64/libgobject-2.0.so.0.4600.2) g_signal_emit+0x8f (/usr/lib64/libgobject-2.0.so.0.4600.2) clutter_actor_continue_paint+0x2bb (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_actor_paint.part.41+0x47b (/usr/lib64/libclutter-1.0.so.0.2400.2) _clutter_stage_do_paint+0x17b (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_stage_cogl_redraw+0x496 (/usr/lib64/libclutter-1.0.so.0.2400.2) _clutter_stage_do_update+0x117 (/usr/lib64/libclutter-1.0.so.0.2400.2) clutter_clock_dispatch+0x169 (/usr/lib64/libclutter-1.0.so.0.2400.2) g_main_context_dispatch+0x15a (/usr/lib64/libglib-2.0.so.0.4600.2) g_main_context_iterate.isra.29+0x1e0 (/usr/lib64/libglib-2.0.so.0.4600.2) g_main_loop_run+0xc2 (/usr/lib64/libglib-2.0.so.0.4600.2) meta_run+0x2c (/usr/lib64/libmutter.so.0.0.0) main+0x3f7 (/usr/bin/gnome-shell) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) [0x2909] (/usr/bin/gnome-shell) Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-jncuxju9fibq2rl6olhqwjw6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 4 ++ tools/perf/builtin-trace.c | 55 +++++++++++++++++-------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 2ee0c4fee18d..4e8baa75a32e 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -138,6 +138,10 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. Default: 127 +--min-stack:: + Set the stack depth limit when parsing the callchain, anything + below the specified depth will be ignored. Disabled by default. + --proc-map-timeout:: When processing pre-existing threads /proc/XXX/mmap, it may take a long time, because the file may be huge. A time out is needed in such cases. diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 65f6abe75d71..6a64cb1344c7 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -108,6 +108,7 @@ struct trace { proc_getname; } stats; unsigned int max_stack; + unsigned int min_stack; bool not_ev_qualifier; bool live; bool full_time; @@ -1849,7 +1850,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, goto out_put; } - if (!(trace->duration_filter || trace->summary_only)) + if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) trace__printf_interrupted_entry(trace, sample); ttrace->entry_time = sample->time; @@ -1860,7 +1861,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, args, trace, thread); if (sc->is_exit) { - if (!trace->duration_filter && !trace->summary_only) { + if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); fprintf(trace->output, "%-70s\n", ttrace->entry_str); } @@ -1880,26 +1881,26 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, return err; } -static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel, - struct perf_sample *sample) +static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel, + struct perf_sample *sample, + struct callchain_cursor *cursor) { struct addr_location al; + + if (machine__resolve(trace->host, &al, sample) < 0 || + thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack)) + return -1; + + return 0; +} + +static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample) +{ /* TODO: user-configurable print_opts */ const unsigned int print_opts = EVSEL__PRINT_SYM | EVSEL__PRINT_DSO | EVSEL__PRINT_UNKNOWN_AS_ADDR; - if (sample->callchain == NULL) - return 0; - - if (machine__resolve(trace->host, &al, sample) < 0 || - thread__resolve_callchain(al.thread, &callchain_cursor, evsel, - sample, NULL, NULL, trace->max_stack)) { - pr_err("Problem processing %s callchain, skipping...\n", - perf_evsel__name(evsel)); - return 0; - } - return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output); } @@ -1910,7 +1911,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, long ret; u64 duration = 0; struct thread *thread; - int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; + int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0; struct syscall *sc = trace__syscall_info(trace, evsel, id); struct thread_trace *ttrace; @@ -1942,6 +1943,15 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, } else if (trace->duration_filter) goto out; + if (sample->callchain) { + callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor); + if (callchain_ret == 0) { + if (callchain_cursor.nr < trace->min_stack) + goto out; + callchain_ret = 1; + } + } + if (trace->summary_only) goto out; @@ -1982,7 +1992,10 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, fputc('\n', trace->output); - trace__fprintf_callchain(trace, evsel, sample); + if (callchain_ret > 0) + trace__fprintf_callchain(trace, sample); + else if (callchain_ret < 0) + pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); out: ttrace->entry_pending = false; err = 0; @@ -2131,7 +2144,10 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, fprintf(trace->output, ")\n"); - trace__fprintf_callchain(trace, evsel, sample); + if (sample->callchain) { + if (trace__resolve_callchain(trace, evsel, sample, &callchain_cursor) == 0) + trace__fprintf_callchain(trace, sample); + } return 0; } @@ -3082,6 +3098,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) &record_parse_callchain_opt), OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, "Show the kernel callchains on the syscall exit path"), + OPT_UINTEGER(0, "min-stack", &trace.min_stack, + "Set the minimum stack depth when parsing the callchain, " + "anything below the specified depth will be ignored."), OPT_UINTEGER(0, "max-stack", &trace.max_stack, "Set the maximum stack depth when parsing the callchain, " "anything beyond the specified depth will be ignored. " -- GitLab From 5a3b7b112884f80ff19b18028fabeb4f9c035518 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Fri, 18 Mar 2016 09:42:13 +0100 Subject: [PATCH 2944/9938] s390/dasd: add query host access to volume support With this feature, applications can query if a DASD volume is online to another operating system instances by checking the online status of all attached hosts from the storage server. Reviewed-by: Sebastian Ott Reviewed-by: Heiko Carstens Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 56 +++++++++++ drivers/s390/block/dasd_devmap.c | 27 +++++ drivers/s390/block/dasd_eckd.c | 164 +++++++++++++++++++++++++++++++ drivers/s390/block/dasd_eckd.h | 33 ++++++- drivers/s390/block/dasd_int.h | 3 + 5 files changed, 282 insertions(+), 1 deletion(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index c78db05e75b1..4adb6d14d562 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -75,6 +75,8 @@ static void dasd_block_timeout(unsigned long); static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *); static void dasd_profile_init(struct dasd_profile *, struct dentry *); static void dasd_profile_exit(struct dasd_profile *); +static void dasd_hosts_init(struct dentry *, struct dasd_device *); +static void dasd_hosts_exit(struct dasd_device *); /* * SECTION: Operations on the device structure. @@ -267,6 +269,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device) dasd_debugfs_setup(dev_name(&device->cdev->dev), dasd_debugfs_root_entry); dasd_profile_init(&device->profile, device->debugfs_dentry); + dasd_hosts_init(device->debugfs_dentry, device); /* register 'device' debug area, used for all DBF_DEV_XXX calls */ device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1, @@ -304,6 +307,7 @@ static int dasd_state_basic_to_known(struct dasd_device *device) return rc; dasd_device_clear_timer(device); dasd_profile_exit(&device->profile); + dasd_hosts_exit(device); debugfs_remove(device->debugfs_dentry); DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); if (device->debug_area != NULL) { @@ -1150,6 +1154,58 @@ int dasd_profile_on(struct dasd_profile *profile) #endif /* CONFIG_DASD_PROFILE */ +static int dasd_hosts_show(struct seq_file *m, void *v) +{ + struct dasd_device *device; + int rc = -EOPNOTSUPP; + + device = m->private; + dasd_get_device(device); + + if (device->discipline->hosts_print) + rc = device->discipline->hosts_print(device, m); + + dasd_put_device(device); + return rc; +} + +static int dasd_hosts_open(struct inode *inode, struct file *file) +{ + struct dasd_device *device = inode->i_private; + + return single_open(file, dasd_hosts_show, device); +} + +static const struct file_operations dasd_hosts_fops = { + .owner = THIS_MODULE, + .open = dasd_hosts_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void dasd_hosts_exit(struct dasd_device *device) +{ + debugfs_remove(device->hosts_dentry); + device->hosts_dentry = NULL; +} + +static void dasd_hosts_init(struct dentry *base_dentry, + struct dasd_device *device) +{ + struct dentry *pde; + umode_t mode; + + if (!base_dentry) + return; + + mode = S_IRUSR | S_IFREG; + pde = debugfs_create_file("host_access_list", mode, base_dentry, + device, &dasd_hosts_fops); + if (pde && !IS_ERR(pde)) + device->hosts_dentry = pde; +} + /* * Allocate memory for a channel program with 'cplength' channel * command words and 'datasize' additional space. There are two diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 2f18f61092b5..3cdbce45e464 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -981,6 +981,32 @@ dasd_safe_offline_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(safe_offline, 0200, NULL, dasd_safe_offline_store); +static ssize_t +dasd_access_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ccw_device *cdev = to_ccwdev(dev); + struct dasd_device *device; + int count; + + device = dasd_device_from_cdev(cdev); + if (IS_ERR(device)) + return PTR_ERR(device); + + if (device->discipline->host_access_count) + count = device->discipline->host_access_count(device); + else + count = -EOPNOTSUPP; + + dasd_put_device(device); + if (count < 0) + return count; + + return sprintf(buf, "%d\n", count); +} + +static DEVICE_ATTR(host_access_count, 0444, dasd_access_show, NULL); + static ssize_t dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1471,6 +1497,7 @@ static struct attribute * dasd_attrs[] = { &dev_attr_reservation_policy.attr, &dev_attr_last_known_reservation_state.attr, &dev_attr_safe_offline.attr, + &dev_attr_host_access_count.attr, &dev_attr_path_masks.attr, NULL, }; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index c1b4ae55e129..3b70d378d1c1 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -4627,6 +4628,167 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device, return rc; } +static int dasd_eckd_query_host_access(struct dasd_device *device, + struct dasd_psf_query_host_access *data) +{ + struct dasd_eckd_private *private = device->private; + struct dasd_psf_query_host_access *host_access; + struct dasd_psf_prssd_data *prssdp; + struct dasd_ccw_req *cqr; + struct ccw1 *ccw; + int rc; + + /* not available for HYPER PAV alias devices */ + if (!device->block && private->lcu->pav == HYPER_PAV) + return -EOPNOTSUPP; + + cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, + sizeof(struct dasd_psf_prssd_data) + 1, + device); + if (IS_ERR(cqr)) { + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", + "Could not allocate read message buffer request"); + return PTR_ERR(cqr); + } + host_access = kzalloc(sizeof(*host_access), GFP_KERNEL | GFP_DMA); + if (!host_access) { + dasd_sfree_request(cqr, device); + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", + "Could not allocate host_access buffer"); + return -ENOMEM; + } + cqr->startdev = device; + cqr->memdev = device; + cqr->block = NULL; + cqr->retries = 256; + cqr->expires = 10 * HZ; + + /* Prepare for Read Subsystem Data */ + prssdp = (struct dasd_psf_prssd_data *) cqr->data; + memset(prssdp, 0, sizeof(struct dasd_psf_prssd_data)); + prssdp->order = PSF_ORDER_PRSSD; + prssdp->suborder = PSF_SUBORDER_QHA; /* query host access */ + /* LSS and Volume that will be queried */ + prssdp->lss = private->ned->ID; + prssdp->volume = private->ned->unit_addr; + /* all other bytes of prssdp must be zero */ + + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_PSF; + ccw->count = sizeof(struct dasd_psf_prssd_data); + ccw->flags |= CCW_FLAG_CC; + ccw->flags |= CCW_FLAG_SLI; + ccw->cda = (__u32)(addr_t) prssdp; + + /* Read Subsystem Data - query host access */ + ccw++; + ccw->cmd_code = DASD_ECKD_CCW_RSSD; + ccw->count = sizeof(struct dasd_psf_query_host_access); + ccw->flags |= CCW_FLAG_SLI; + ccw->cda = (__u32)(addr_t) host_access; + + cqr->buildclk = get_tod_clock(); + cqr->status = DASD_CQR_FILLED; + rc = dasd_sleep_on(cqr); + if (rc == 0) { + *data = *host_access; + } else { + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, + "Reading host access data failed with rc=%d\n", + rc); + rc = -EOPNOTSUPP; + } + + dasd_sfree_request(cqr, cqr->memdev); + kfree(host_access); + return rc; +} +/* + * return number of grouped devices + */ +static int dasd_eckd_host_access_count(struct dasd_device *device) +{ + struct dasd_psf_query_host_access *access; + struct dasd_ckd_path_group_entry *entry; + struct dasd_ckd_host_information *info; + int count = 0; + int rc, i; + + access = kzalloc(sizeof(*access), GFP_NOIO); + if (!access) { + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", + "Could not allocate access buffer"); + return -ENOMEM; + } + rc = dasd_eckd_query_host_access(device, access); + if (rc) { + kfree(access); + return rc; + } + + info = (struct dasd_ckd_host_information *) + access->host_access_information; + for (i = 0; i < info->entry_count; i++) { + entry = (struct dasd_ckd_path_group_entry *) + (info->entry + i * info->entry_size); + if (entry->status_flags & DASD_ECKD_PG_GROUPED) + count++; + } + + kfree(access); + return count; +} + +/* + * write host access information to a sequential file + */ +static int dasd_hosts_print(struct dasd_device *device, struct seq_file *m) +{ + struct dasd_psf_query_host_access *access; + struct dasd_ckd_path_group_entry *entry; + struct dasd_ckd_host_information *info; + char sysplex[9] = ""; + int rc, i, j; + + access = kzalloc(sizeof(*access), GFP_NOIO); + if (!access) { + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", + "Could not allocate access buffer"); + return -ENOMEM; + } + rc = dasd_eckd_query_host_access(device, access); + if (rc) { + kfree(access); + return rc; + } + + info = (struct dasd_ckd_host_information *) + access->host_access_information; + for (i = 0; i < info->entry_count; i++) { + entry = (struct dasd_ckd_path_group_entry *) + (info->entry + i * info->entry_size); + /* PGID */ + seq_puts(m, "pgid "); + for (j = 0; j < 11; j++) + seq_printf(m, "%02x", entry->pgid[j]); + seq_putc(m, '\n'); + /* FLAGS */ + seq_printf(m, "status_flags %02x\n", entry->status_flags); + /* SYSPLEX NAME */ + memcpy(&sysplex, &entry->sysplex_name, sizeof(sysplex) - 1); + EBCASC(sysplex, sizeof(sysplex)); + seq_printf(m, "sysplex_name %8s\n", sysplex); + /* SUPPORTED CYLINDER */ + seq_printf(m, "supported_cylinder %d\n", entry->cylinder); + /* TIMESTAMP */ + seq_printf(m, "timestamp %lu\n", (unsigned long) + entry->timestamp); + } + kfree(access); + + return 0; +} + /* * Perform Subsystem Function - CUIR response */ @@ -5099,6 +5261,8 @@ static struct dasd_discipline dasd_eckd_discipline = { .get_uid = dasd_eckd_get_uid, .kick_validate = dasd_eckd_kick_validate_server, .check_attention = dasd_eckd_check_attention, + .host_access_count = dasd_eckd_host_access_count, + .hosts_print = dasd_hosts_print, }; static int __init diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 6d9a6d3517cd..862ee4291abd 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -53,6 +53,7 @@ */ #define PSF_ORDER_PRSSD 0x18 #define PSF_ORDER_CUIR_RESPONSE 0x1A +#define PSF_SUBORDER_QHA 0x1C #define PSF_ORDER_SSC 0x1D /* @@ -81,6 +82,8 @@ #define ATTENTION_LENGTH_CUIR 0x0e #define ATTENTION_FORMAT_CUIR 0x01 +#define DASD_ECKD_PG_GROUPED 0x10 + /* * Size that is reportet for large volumes in the old 16-bit no_cyl field */ @@ -403,13 +406,41 @@ struct dasd_psf_cuir_response { __u8 ssid; } __packed; +struct dasd_ckd_path_group_entry { + __u8 status_flags; + __u8 pgid[11]; + __u8 sysplex_name[8]; + __u32 timestamp; + __u32 cylinder; + __u8 reserved[4]; +} __packed; + +struct dasd_ckd_host_information { + __u8 access_flags; + __u8 entry_size; + __u16 entry_count; + __u8 entry[16390]; +} __packed; + +struct dasd_psf_query_host_access { + __u8 access_flag; + __u8 version; + __u16 CKD_length; + __u16 SCSI_length; + __u8 unused[10]; + __u8 host_access_information[16394]; +} __packed; + /* * Perform Subsystem Function - Prepare for Read Subsystem Data */ struct dasd_psf_prssd_data { unsigned char order; unsigned char flags; - unsigned char reserved[4]; + unsigned char reserved1; + unsigned char reserved2; + unsigned char lss; + unsigned char volume; unsigned char suborder; unsigned char varies[5]; } __attribute__ ((packed)); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 0f0add932e7a..6132733bcd95 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -365,6 +365,8 @@ struct dasd_discipline { int (*get_uid) (struct dasd_device *, struct dasd_uid *); void (*kick_validate) (struct dasd_device *); int (*check_attention)(struct dasd_device *, __u8); + int (*host_access_count)(struct dasd_device *); + int (*hosts_print)(struct dasd_device *, struct seq_file *); }; extern struct dasd_discipline *dasd_diag_discipline_pointer; @@ -487,6 +489,7 @@ struct dasd_device { unsigned long blk_timeout; struct dentry *debugfs_dentry; + struct dentry *hosts_dentry; struct dasd_profile profile; }; -- GitLab From 0227f7c42d9e01b00ea8cbd635aaf92a09b54abc Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 22 Mar 2016 21:42:53 +0100 Subject: [PATCH 2945/9938] s390: Clarify pagefault interrupt While looking at set_task_state() users I stumbled over the s390 pfault interrupt code. Since Heiko provided a great explanation on how it worked, I figured we ought to preserve this. Also make a few little tweaks to the code to aid in readability and explicitly comment the unusual blocking scheme. Based-on-text-by: Heiko Carstens Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index cce577feab1e..7a3144017301 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -631,6 +631,29 @@ void pfault_fini(void) static DEFINE_SPINLOCK(pfault_lock); static LIST_HEAD(pfault_list); +#define PF_COMPLETE 0x0080 + +/* + * The mechanism of our pfault code: if Linux is running as guest, runs a user + * space process and the user space process accesses a page that the host has + * paged out we get a pfault interrupt. + * + * This allows us, within the guest, to schedule a different process. Without + * this mechanism the host would have to suspend the whole virtual cpu until + * the page has been paged in. + * + * So when we get such an interrupt then we set the state of the current task + * to uninterruptible and also set the need_resched flag. Both happens within + * interrupt context(!). If we later on want to return to user space we + * recognize the need_resched flag and then call schedule(). It's not very + * obvious how this works... + * + * Of course we have a lot of additional fun with the completion interrupt (-> + * host signals that a page of a process has been paged in and the process can + * continue to run). This interrupt can arrive on any cpu and, since we have + * virtual cpus, actually appear before the interrupt that signals that a page + * is missing. + */ static void pfault_interrupt(struct ext_code ext_code, unsigned int param32, unsigned long param64) { @@ -639,10 +662,9 @@ static void pfault_interrupt(struct ext_code ext_code, pid_t pid; /* - * Get the external interruption subcode & pfault - * initial/completion signal bit. VM stores this - * in the 'cpu address' field associated with the - * external interrupt. + * Get the external interruption subcode & pfault initial/completion + * signal bit. VM stores this in the 'cpu address' field associated + * with the external interrupt. */ subcode = ext_code.subcode; if ((subcode & 0xff00) != __SUBCODE_MASK) @@ -658,7 +680,7 @@ static void pfault_interrupt(struct ext_code ext_code, if (!tsk) return; spin_lock(&pfault_lock); - if (subcode & 0x0080) { + if (subcode & PF_COMPLETE) { /* signal bit is set -> a page has been swapped in by VM */ if (tsk->thread.pfault_wait == 1) { /* Initial interrupt was faster than the completion @@ -687,8 +709,7 @@ static void pfault_interrupt(struct ext_code ext_code, goto out; if (tsk->thread.pfault_wait == 1) { /* Already on the list with a reference: put to sleep */ - __set_task_state(tsk, TASK_UNINTERRUPTIBLE); - set_tsk_need_resched(tsk); + goto block; } else if (tsk->thread.pfault_wait == -1) { /* Completion interrupt was faster than the initial * interrupt (pfault_wait == -1). Set pfault_wait @@ -703,7 +724,11 @@ static void pfault_interrupt(struct ext_code ext_code, get_task_struct(tsk); tsk->thread.pfault_wait = 1; list_add(&tsk->thread.list, &pfault_list); - __set_task_state(tsk, TASK_UNINTERRUPTIBLE); +block: + /* Since this must be a userspace fault, there + * is no kernel task state to trample. Rely on the + * return to userspace schedule() to block. */ + __set_current_state(TASK_UNINTERRUPTIBLE); set_tsk_need_resched(tsk); } } -- GitLab From 52c48c51e60c473ccedb4c8f428050041ca7076a Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Tue, 5 Apr 2016 12:53:38 +0200 Subject: [PATCH 2946/9938] Documentation: document the nosmt and smt s390 kernel parameters Commit 6c2ff84e979a ("s390: add SMT support") added the nosmt and smt early kernel parameters for restricting the use of symmetric multithreading (SMT). They are quite useful for debugging and testing, so document them. Signed-off-by: Sascha Silbe Signed-off-by: Martin Schwidefsky --- Documentation/kernel-parameters.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ecc74fa4bfde..92435e7c5f55 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2538,6 +2538,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. nohugeiomap [KNL,x86] Disable kernel huge I/O mappings. + nosmt [KNL,S390] Disable symmetric multithreading (SMT). + Equivalent to smt=1. + noxsave [BUGS=X86] Disables x86 extended register state save and restore using xsave. The kernel will fallback to enabling legacy floating-point and sse state. @@ -3695,6 +3698,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. 1: Fast pin select (default) 2: ATC IRMode + smt [KNL,S390] Set the maximum number of threads (logical + CPUs) to use per physical CPU on systems capable of + symmetric multithreading (SMT). Will be capped to the + actual hardware limit. + Format: + Default: -1 (no limit) + softlockup_panic= [KNL] Should the soft-lockup detector generate panics. Format: -- GitLab From 68dd13d6d58c145bbf6d295b8c430b4d38c943d9 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 27 Nov 2015 11:15:36 +0100 Subject: [PATCH 2947/9938] s390/sclp: move pci related commands to separate file sclp commands only used by the PCI code shouldn't be build for !CONFIG_PCI. Instead of adding more ifdefs to sclp_cmd.c just move them to a new file. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/char/Makefile | 2 + drivers/s390/char/sclp_cmd.c | 61 ----------------------------- drivers/s390/char/sclp_pci.c | 76 ++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 61 deletions(-) create mode 100644 drivers/s390/char/sclp_pci.c diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index dd2f7c832e5e..41e28b23b26a 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -18,6 +18,8 @@ obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o obj-$(CONFIG_SCLP_ASYNC) += sclp_async.o +obj-$(CONFIG_PCI) += sclp_pci.o + obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o obj-$(CONFIG_VMCP) += vmcp.o diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index d3947ea3e351..e3fc7539116b 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -575,67 +575,6 @@ __initcall(sclp_detect_standby_memory); #endif /* CONFIG_MEMORY_HOTPLUG */ -/* - * PCI I/O adapter configuration related functions. - */ -#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001 -#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001 - -#define SCLP_RECONFIG_PCI_ATPYE 2 - -struct pci_cfg_sccb { - struct sccb_header header; - u8 atype; /* adapter type */ - u8 reserved1; - u16 reserved2; - u32 aid; /* adapter identifier */ -} __packed; - -static int do_pci_configure(sclp_cmdw_t cmd, u32 fid) -{ - struct pci_cfg_sccb *sccb; - int rc; - - if (!SCLP_HAS_PCI_RECONFIG) - return -EOPNOTSUPP; - - sccb = (struct pci_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!sccb) - return -ENOMEM; - - sccb->header.length = PAGE_SIZE; - sccb->atype = SCLP_RECONFIG_PCI_ATPYE; - sccb->aid = fid; - rc = sclp_sync_request(cmd, sccb); - if (rc) - goto out; - switch (sccb->header.response_code) { - case 0x0020: - case 0x0120: - break; - default: - pr_warn("configure PCI I/O adapter failed: cmd=0x%08x response=0x%04x\n", - cmd, sccb->header.response_code); - rc = -EIO; - break; - } -out: - free_page((unsigned long) sccb); - return rc; -} - -int sclp_pci_configure(u32 fid) -{ - return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI, fid); -} -EXPORT_SYMBOL(sclp_pci_configure); - -int sclp_pci_deconfigure(u32 fid) -{ - return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid); -} -EXPORT_SYMBOL(sclp_pci_deconfigure); - /* * Channel path configuration related functions. */ diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c new file mode 100644 index 000000000000..943e92539e65 --- /dev/null +++ b/drivers/s390/char/sclp_pci.c @@ -0,0 +1,76 @@ +/* + * PCI I/O adapter configuration related functions. + * + * Copyright IBM Corp. 2016 + */ +#define KMSG_COMPONENT "sclp_cmd" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include +#include +#include +#include +#include +#include + +#include + +#include "sclp.h" + +#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001 +#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001 + +#define SCLP_RECONFIG_PCI_ATPYE 2 + +struct pci_cfg_sccb { + struct sccb_header header; + u8 atype; /* adapter type */ + u8 reserved1; + u16 reserved2; + u32 aid; /* adapter identifier */ +} __packed; + +static int do_pci_configure(sclp_cmdw_t cmd, u32 fid) +{ + struct pci_cfg_sccb *sccb; + int rc; + + if (!SCLP_HAS_PCI_RECONFIG) + return -EOPNOTSUPP; + + sccb = (struct pci_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!sccb) + return -ENOMEM; + + sccb->header.length = PAGE_SIZE; + sccb->atype = SCLP_RECONFIG_PCI_ATPYE; + sccb->aid = fid; + rc = sclp_sync_request(cmd, sccb); + if (rc) + goto out; + switch (sccb->header.response_code) { + case 0x0020: + case 0x0120: + break; + default: + pr_warn("configure PCI I/O adapter failed: cmd=0x%08x response=0x%04x\n", + cmd, sccb->header.response_code); + rc = -EIO; + break; + } +out: + free_page((unsigned long) sccb); + return rc; +} + +int sclp_pci_configure(u32 fid) +{ + return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI, fid); +} +EXPORT_SYMBOL(sclp_pci_configure); + +int sclp_pci_deconfigure(u32 fid) +{ + return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid); +} +EXPORT_SYMBOL(sclp_pci_deconfigure); -- GitLab From 12283a4035691697977083a5ac1e00ad5cfa6a3d Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 27 Nov 2015 11:18:02 +0100 Subject: [PATCH 2948/9938] s390/sclp: add error notification command Add SCLP event 24 "Adapter-error notification". Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sclp.h | 13 ++++ drivers/s390/char/sclp.h | 2 + drivers/s390/char/sclp_pci.c | 120 ++++++++++++++++++++++++++++++++++- 3 files changed, 133 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index bab456be9a4f..bd7893d274fa 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -72,6 +72,18 @@ struct sclp_info { }; extern struct sclp_info sclp; +struct zpci_report_error_header { + u8 version; /* Interface version byte */ + u8 action; /* Action qualifier byte + * 1: Deconfigure and repair action requested + * (OpenCrypto Problem Call Home) + * 2: Informational Report + * (OpenCrypto Successful Diagnostics Execution) + */ + u16 length; /* Length of Subsequent Data (up to 4K – SCLP header */ + u8 data[0]; /* Subsequent Data passed verbatim to SCLP ET 24 */ +} __packed; + int sclp_get_core_info(struct sclp_core_info *info); int sclp_core_configure(u8 core); int sclp_core_deconfigure(u8 core); @@ -83,6 +95,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info); void sclp_get_ipl_info(struct sclp_ipl_info *info); int sclp_pci_configure(u32 fid); int sclp_pci_deconfigure(u32 fid); +int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid); int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count); int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count); void sclp_early_detect(void); diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 026e38990952..6079efa95eaa 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -22,6 +22,7 @@ #define EVTYP_DIAG_TEST 0x07 #define EVTYP_STATECHANGE 0x08 #define EVTYP_PMSGCMD 0x09 +#define EVTYP_ERRNOTIFY 0x18 #define EVTYP_CNTLPROGOPCMD 0x20 #define EVTYP_CNTLPROGIDENT 0x0B #define EVTYP_SIGQUIESCE 0x1D @@ -36,6 +37,7 @@ #define EVTYP_DIAG_TEST_MASK 0x02000000 #define EVTYP_STATECHANGE_MASK 0x01000000 #define EVTYP_PMSGCMD_MASK 0x00800000 +#define EVTYP_ERRNOTIFY_MASK 0x00000100 #define EVTYP_CTLPROGOPCMD_MASK 0x00000001 #define EVTYP_CTLPROGIDENT_MASK 0x00200000 #define EVTYP_SIGQUIESCE_MASK 0x00000008 diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c index 943e92539e65..0c8973c45b48 100644 --- a/drivers/s390/char/sclp_pci.c +++ b/drivers/s390/char/sclp_pci.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -20,7 +21,29 @@ #define SCLP_CMDW_CONFIGURE_PCI 0x001a0001 #define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001 -#define SCLP_RECONFIG_PCI_ATPYE 2 +#define SCLP_ATYPE_PCI 2 + +#define SCLP_ERRNOTIFY_AQ_REPAIR 1 +#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2 + +static DEFINE_MUTEX(sclp_pci_mutex); +static struct sclp_register sclp_pci_event = { + .send_mask = EVTYP_ERRNOTIFY_MASK, +}; + +struct err_notify_evbuf { + struct evbuf_header header; + u8 action; + u8 atype; + u32 fh; + u32 fid; + u8 data[0]; +} __packed; + +struct err_notify_sccb { + struct sccb_header header; + struct err_notify_evbuf evbuf; +} __packed; struct pci_cfg_sccb { struct sccb_header header; @@ -43,7 +66,7 @@ static int do_pci_configure(sclp_cmdw_t cmd, u32 fid) return -ENOMEM; sccb->header.length = PAGE_SIZE; - sccb->atype = SCLP_RECONFIG_PCI_ATPYE; + sccb->atype = SCLP_ATYPE_PCI; sccb->aid = fid; rc = sclp_sync_request(cmd, sccb); if (rc) @@ -74,3 +97,96 @@ int sclp_pci_deconfigure(u32 fid) return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid); } EXPORT_SYMBOL(sclp_pci_deconfigure); + +static void sclp_pci_callback(struct sclp_req *req, void *data) +{ + struct completion *completion = data; + + complete(completion); +} + +static int sclp_pci_check_report(struct zpci_report_error_header *report) +{ + if (report->version != 1) + return -EINVAL; + + if (report->action != SCLP_ERRNOTIFY_AQ_REPAIR && + report->action != SCLP_ERRNOTIFY_AQ_INFO_LOG) + return -EINVAL; + + if (report->length > (PAGE_SIZE - sizeof(struct err_notify_sccb))) + return -EINVAL; + + return 0; +} + +int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid) +{ + DECLARE_COMPLETION_ONSTACK(completion); + struct err_notify_sccb *sccb; + struct sclp_req req = {0}; + int ret; + + ret = sclp_pci_check_report(report); + if (ret) + return ret; + + mutex_lock(&sclp_pci_mutex); + ret = sclp_register(&sclp_pci_event); + if (ret) + goto out_unlock; + + if (!(sclp_pci_event.sclp_receive_mask & EVTYP_ERRNOTIFY_MASK)) { + ret = -EOPNOTSUPP; + goto out_unregister; + } + + sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!sccb) { + ret = -ENOMEM; + goto out_unregister; + } + + req.callback_data = &completion; + req.callback = sclp_pci_callback; + req.command = SCLP_CMDW_WRITE_EVENT_DATA; + req.status = SCLP_REQ_FILLED; + req.sccb = sccb; + + sccb->evbuf.header.length = sizeof(sccb->evbuf) + report->length; + sccb->evbuf.header.type = EVTYP_ERRNOTIFY; + sccb->header.length = sizeof(sccb->header) + sccb->evbuf.header.length; + + sccb->evbuf.action = report->action; + sccb->evbuf.atype = SCLP_ATYPE_PCI; + sccb->evbuf.fh = fh; + sccb->evbuf.fid = fid; + + memcpy(sccb->evbuf.data, report->data, report->length); + + ret = sclp_add_request(&req); + if (ret) + goto out_free_req; + + wait_for_completion(&completion); + if (req.status != SCLP_REQ_DONE) { + pr_warn("request failed (status=0x%02x)\n", + req.status); + ret = -EIO; + goto out_free_req; + } + + if (sccb->header.response_code != 0x0020) { + pr_warn("request failed with response code 0x%x\n", + sccb->header.response_code); + ret = -EIO; + } + +out_free_req: + free_page((unsigned long) sccb); +out_unregister: + sclp_unregister(&sclp_pci_event); +out_unlock: + mutex_unlock(&sclp_pci_mutex); + return ret; +} -- GitLab From 368704a65be8620df795ccbeb44e025dafbc3e1f Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 27 Nov 2015 11:22:57 +0100 Subject: [PATCH 2949/9938] s390/pci: add report_error attribute Provide an report_error attribute to send an adapter-error notification associated with a PCI function. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/pci/pci_sysfs.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c index f37a5808883d..ed484dc84d14 100644 --- a/arch/s390/pci/pci_sysfs.c +++ b/arch/s390/pci/pci_sysfs.c @@ -12,6 +12,8 @@ #include #include +#include + #define zpci_attr(name, fmt, member) \ static ssize_t name##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -77,8 +79,29 @@ static ssize_t util_string_read(struct file *filp, struct kobject *kobj, sizeof(zdev->util_str)); } static BIN_ATTR_RO(util_string, CLP_UTIL_STR_LEN); + +static ssize_t report_error_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct zpci_report_error_header *report = (void *) buf; + struct device *dev = kobj_to_dev(kobj); + struct pci_dev *pdev = to_pci_dev(dev); + struct zpci_dev *zdev = to_zpci(pdev); + int ret; + + if (off || (count < sizeof(*report))) + return -EINVAL; + + ret = sclp_pci_report(report, zdev->fh, zdev->fid); + + return ret ? ret : count; +} +static BIN_ATTR(report_error, S_IWUSR, NULL, report_error_write, PAGE_SIZE); + static struct bin_attribute *zpci_bin_attrs[] = { &bin_attr_util_string, + &bin_attr_report_error, NULL, }; -- GitLab From 3fa7ee8844c31cb9c78992bb82cfaeb13375345d Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 27 Nov 2015 12:33:18 +0100 Subject: [PATCH 2950/9938] s390/sclp: event type macro cleanup Sort the sclp event type defines and use a macro to create the corresponding event type masks. In addition to that one unused type/mask pair is removed and another previously unused define is used now (it was probably unused/unknown because it didn't follow the EVTYP_X EVTYP_X_MASK convention). Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp.h | 38 ++++++++++++++++---------------- drivers/s390/char/sclp_cpi_sys.c | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6079efa95eaa..7a10c56334bb 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -17,35 +17,35 @@ #define MAX_KMEM_PAGES (sizeof(unsigned long) << 3) #define SCLP_CONSOLE_PAGES 6 +#define SCLP_EVTYP_MASK(T) (1U << (32 - (T))) + #define EVTYP_OPCMD 0x01 #define EVTYP_MSG 0x02 +#define EVTYP_CONFMGMDATA 0x04 #define EVTYP_DIAG_TEST 0x07 #define EVTYP_STATECHANGE 0x08 #define EVTYP_PMSGCMD 0x09 +#define EVTYP_ASYNC 0x0A +#define EVTYP_CTLPROGIDENT 0x0B #define EVTYP_ERRNOTIFY 0x18 -#define EVTYP_CNTLPROGOPCMD 0x20 -#define EVTYP_CNTLPROGIDENT 0x0B -#define EVTYP_SIGQUIESCE 0x1D #define EVTYP_VT220MSG 0x1A -#define EVTYP_CONFMGMDATA 0x04 #define EVTYP_SDIAS 0x1C -#define EVTYP_ASYNC 0x0A +#define EVTYP_SIGQUIESCE 0x1D #define EVTYP_OCF 0x1E -#define EVTYP_OPCMD_MASK 0x80000000 -#define EVTYP_MSG_MASK 0x40000000 -#define EVTYP_DIAG_TEST_MASK 0x02000000 -#define EVTYP_STATECHANGE_MASK 0x01000000 -#define EVTYP_PMSGCMD_MASK 0x00800000 -#define EVTYP_ERRNOTIFY_MASK 0x00000100 -#define EVTYP_CTLPROGOPCMD_MASK 0x00000001 -#define EVTYP_CTLPROGIDENT_MASK 0x00200000 -#define EVTYP_SIGQUIESCE_MASK 0x00000008 -#define EVTYP_VT220MSG_MASK 0x00000040 -#define EVTYP_CONFMGMDATA_MASK 0x10000000 -#define EVTYP_SDIAS_MASK 0x00000010 -#define EVTYP_ASYNC_MASK 0x00400000 -#define EVTYP_OCF_MASK 0x00000004 +#define EVTYP_OPCMD_MASK SCLP_EVTYP_MASK(EVTYP_OPCMD) +#define EVTYP_MSG_MASK SCLP_EVTYP_MASK(EVTYP_MSG) +#define EVTYP_CONFMGMDATA_MASK SCLP_EVTYP_MASK(EVTYP_CONFMGMDATA) +#define EVTYP_DIAG_TEST_MASK SCLP_EVTYP_MASK(EVTYP_DIAG_TEST) +#define EVTYP_STATECHANGE_MASK SCLP_EVTYP_MASK(EVTYP_STATECHANGE) +#define EVTYP_PMSGCMD_MASK SCLP_EVTYP_MASK(EVTYP_PMSGCMD) +#define EVTYP_ASYNC_MASK SCLP_EVTYP_MASK(EVTYP_ASYNC) +#define EVTYP_CTLPROGIDENT_MASK SCLP_EVTYP_MASK(EVTYP_CTLPROGIDENT) +#define EVTYP_ERRNOTIFY_MASK SCLP_EVTYP_MASK(EVTYP_ERRNOTIFY) +#define EVTYP_VT220MSG_MASK SCLP_EVTYP_MASK(EVTYP_VT220MSG) +#define EVTYP_SDIAS_MASK SCLP_EVTYP_MASK(EVTYP_SDIAS) +#define EVTYP_SIGQUIESCE_MASK SCLP_EVTYP_MASK(EVTYP_SIGQUIESCE) +#define EVTYP_OCF_MASK SCLP_EVTYP_MASK(EVTYP_OCF) #define GNRLMSGFLGS_DOM 0x8000 #define GNRLMSGFLGS_SNDALRM 0x4000 diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c index f344e5bd2d9f..90d92fbe7b9b 100644 --- a/drivers/s390/char/sclp_cpi_sys.c +++ b/drivers/s390/char/sclp_cpi_sys.c @@ -93,7 +93,7 @@ static struct sclp_req *cpi_prepare_req(void) /* setup SCCB for Control-Program Identification */ sccb->header.length = sizeof(struct cpi_sccb); sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf); - sccb->cpi_evbuf.header.type = 0x0b; + sccb->cpi_evbuf.header.type = EVTYP_CTLPROGIDENT; evb = &sccb->cpi_evbuf; /* set system type */ -- GitLab From 8fd575200db5b53f6ea6818dd017f1b43190db12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B6ppner?= Date: Wed, 19 Aug 2015 13:41:20 +0200 Subject: [PATCH 2951/9938] s390/dasd: Add new ioctl BIODASDCHECKFMT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement new DASD IOCTL BIODASDCHECKFMT to check a range of tracks on a DASD volume for correct formatting. The following characteristics are checked: - Block size - ECKD key length - ECKD record ID - Number of records per track Signed-off-by: Jan Höppner Signed-off-by: Martin Schwidefsky --- arch/s390/include/uapi/asm/dasd.h | 32 ++ drivers/s390/block/dasd.c | 36 +- drivers/s390/block/dasd_3990_erp.c | 20 +- drivers/s390/block/dasd_eckd.c | 535 ++++++++++++++++++++++++++++- drivers/s390/block/dasd_eckd.h | 1 + drivers/s390/block/dasd_int.h | 14 +- drivers/s390/block/dasd_ioctl.c | 61 ++++ 7 files changed, 676 insertions(+), 23 deletions(-) diff --git a/arch/s390/include/uapi/asm/dasd.h b/arch/s390/include/uapi/asm/dasd.h index 5812a3b2df9e..1340311dab77 100644 --- a/arch/s390/include/uapi/asm/dasd.h +++ b/arch/s390/include/uapi/asm/dasd.h @@ -187,6 +187,36 @@ typedef struct format_data_t { #define DASD_FMT_INT_INVAL 4 /* invalidate tracks */ #define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */ +/* + * struct format_check_t + * represents all data necessary to evaluate the format of + * different tracks of a dasd + */ +typedef struct format_check_t { + /* Input */ + struct format_data_t expect; + + /* Output */ + unsigned int result; /* Error indication (DASD_FMT_ERR_*) */ + unsigned int unit; /* Track that is in error */ + unsigned int rec; /* Record that is in error */ + unsigned int num_records; /* Records in the track in error */ + unsigned int blksize; /* Blocksize of first record in error */ + unsigned int key_length; /* Key length of first record in error */ +} format_check_t; + +/* Values returned in format_check_t when a format error is detected: */ +/* Too few records were found on a single track */ +#define DASD_FMT_ERR_TOO_FEW_RECORDS 1 +/* Too many records were found on a single track */ +#define DASD_FMT_ERR_TOO_MANY_RECORDS 2 +/* Blocksize/data-length of a record was wrong */ +#define DASD_FMT_ERR_BLKSIZE 3 +/* A record ID is defined by cylinder, head, and record number (CHR). */ +/* On mismatch, this error is set */ +#define DASD_FMT_ERR_RECORD_ID 4 +/* If key-length was != 0 */ +#define DASD_FMT_ERR_KEY_LENGTH 5 /* * struct attrib_data_t @@ -288,6 +318,8 @@ struct dasd_snid_ioctl_data { /* Get Sense Path Group ID (SNID) data */ #define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data) +/* Check device format according to format_check_t */ +#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t) #define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4adb6d14d562..8973d34ce5ba 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1638,6 +1638,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, struct dasd_ccw_req *cqr, *next; struct dasd_device *device; unsigned long long now; + int nrf_suppressed = 0; + int fp_suppressed = 0; + u8 *sense = NULL; int expires; if (IS_ERR(irb)) { @@ -1673,7 +1676,23 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, dasd_put_device(device); return; } - device->discipline->dump_sense_dbf(device, irb, "int"); + + /* + * In some cases 'File Protected' or 'No Record Found' errors + * might be expected and debug log messages for the + * corresponding interrupts shouldn't be written then. + * Check if either of the according suppress bits is set. + */ + sense = dasd_get_sense(irb); + if (sense) { + fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) && + test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); + nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) && + test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); + } + if (!(fp_suppressed || nrf_suppressed)) + device->discipline->dump_sense_dbf(device, irb, "int"); + if (device->features & DASD_FEATURE_ERPLOG) device->discipline->dump_sense(device, cqr, irb); device->discipline->check_for_device_change(device, cqr, irb); @@ -2312,6 +2331,7 @@ static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible) { struct dasd_device *device; struct dasd_ccw_req *cqr, *n; + u8 *sense = NULL; int rc; retry: @@ -2357,6 +2377,20 @@ static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible) rc = 0; list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) { + /* + * In some cases the 'File Protected' or 'Incorrect Length' + * error might be expected and error recovery would be + * unnecessary in these cases. Check if the according suppress + * bit is set. + */ + sense = dasd_get_sense(&cqr->irb); + if (sense && sense[1] & SNS1_FILE_PROTECTED && + test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags)) + continue; + if (scsw_cstat(&cqr->irb.scsw) == 0x40 && + test_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags)) + continue; + /* * for alias devices simplify error recovery and * return to upper layer diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index d26134713682..8305ab688d57 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1367,8 +1367,14 @@ dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense) struct dasd_device *device = default_erp->startdev; - dev_err(&device->cdev->dev, - "The specified record was not found\n"); + /* + * In some cases the 'No Record Found' error might be expected and + * log messages shouldn't be written then. + * Check if the according suppress bit is set. + */ + if (!test_bit(DASD_CQR_SUPPRESS_NRF, &default_erp->flags)) + dev_err(&device->cdev->dev, + "The specified record was not found\n"); return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); @@ -1393,8 +1399,14 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) struct dasd_device *device = erp->startdev; - dev_err(&device->cdev->dev, "Accessing the DASD failed because of " - "a hardware error\n"); + /* + * In some cases the 'File Protected' error might be expected and + * log messages shouldn't be written then. + * Check if the according suppress bit is set. + */ + if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags)) + dev_err(&device->cdev->dev, + "Accessing the DASD failed because of a hardware error\n"); return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 3b70d378d1c1..42b34cd1f002 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -121,6 +121,11 @@ struct check_attention_work_data { __u8 lpum; }; +static int prepare_itcw(struct itcw *, unsigned int, unsigned int, int, + struct dasd_device *, struct dasd_device *, + unsigned int, int, unsigned int, unsigned int, + unsigned int, unsigned int); + /* initial attempt at a probe function. this can be simplified once * the other detection code is gone */ static int @@ -257,10 +262,13 @@ define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk, case DASD_ECKD_CCW_READ_CKD_MT: case DASD_ECKD_CCW_READ_KD: case DASD_ECKD_CCW_READ_KD_MT: - case DASD_ECKD_CCW_READ_COUNT: data->mask.perm = 0x1; data->attributes.operation = private->attrib.operation; break; + case DASD_ECKD_CCW_READ_COUNT: + data->mask.perm = 0x1; + data->attributes.operation = DASD_BYPASS_CACHE; + break; case DASD_ECKD_CCW_WRITE: case DASD_ECKD_CCW_WRITE_MT: case DASD_ECKD_CCW_WRITE_KD: @@ -529,10 +537,13 @@ static int prefix_LRE(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, case DASD_ECKD_CCW_READ_CKD_MT: case DASD_ECKD_CCW_READ_KD: case DASD_ECKD_CCW_READ_KD_MT: - case DASD_ECKD_CCW_READ_COUNT: dedata->mask.perm = 0x1; dedata->attributes.operation = basepriv->attrib.operation; break; + case DASD_ECKD_CCW_READ_COUNT: + dedata->mask.perm = 0x1; + dedata->attributes.operation = DASD_BYPASS_CACHE; + break; case DASD_ECKD_CCW_READ_TRACK: case DASD_ECKD_CCW_READ_TRACK_DATA: dedata->mask.perm = 0x1; @@ -2096,6 +2107,180 @@ dasd_eckd_fill_geometry(struct dasd_block *block, struct hd_geometry *geo) return 0; } +/* + * Build the TCW request for the format check + */ +static struct dasd_ccw_req * +dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata, + int enable_pav, struct eckd_count *fmt_buffer, + int rpt) +{ + struct dasd_eckd_private *start_priv; + struct dasd_device *startdev = NULL; + struct tidaw *last_tidaw = NULL; + struct dasd_ccw_req *cqr; + struct itcw *itcw; + int itcw_size; + int count; + int rc; + int i; + + if (enable_pav) + startdev = dasd_alias_get_start_dev(base); + + if (!startdev) + startdev = base; + + start_priv = startdev->private; + + count = rpt * (fdata->stop_unit - fdata->start_unit + 1); + + /* + * we're adding 'count' amount of tidaw to the itcw. + * calculate the corresponding itcw_size + */ + itcw_size = itcw_calc_size(0, count, 0); + + cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev); + if (IS_ERR(cqr)) + return cqr; + + start_priv->count++; + + itcw = itcw_init(cqr->data, itcw_size, ITCW_OP_READ, 0, count, 0); + if (IS_ERR(itcw)) { + rc = -EINVAL; + goto out_err; + } + + cqr->cpaddr = itcw_get_tcw(itcw); + rc = prepare_itcw(itcw, fdata->start_unit, fdata->stop_unit, + DASD_ECKD_CCW_READ_COUNT_MT, base, startdev, 0, count, + sizeof(struct eckd_count), + count * sizeof(struct eckd_count), 0, rpt); + if (rc) + goto out_err; + + for (i = 0; i < count; i++) { + last_tidaw = itcw_add_tidaw(itcw, 0, fmt_buffer++, + sizeof(struct eckd_count)); + if (IS_ERR(last_tidaw)) { + rc = -EINVAL; + goto out_err; + } + } + + last_tidaw->flags |= TIDAW_FLAGS_LAST; + itcw_finalize(itcw); + + cqr->cpmode = 1; + cqr->startdev = startdev; + cqr->memdev = startdev; + cqr->basedev = base; + cqr->retries = startdev->default_retries; + cqr->expires = startdev->default_expires * HZ; + cqr->buildclk = get_tod_clock(); + cqr->status = DASD_CQR_FILLED; + /* Set flags to suppress output for expected errors */ + set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); + set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags); + + return cqr; + +out_err: + dasd_sfree_request(cqr, startdev); + + return ERR_PTR(rc); +} + +/* + * Build the CCW request for the format check + */ +static struct dasd_ccw_req * +dasd_eckd_build_check(struct dasd_device *base, struct format_data_t *fdata, + int enable_pav, struct eckd_count *fmt_buffer, int rpt) +{ + struct dasd_eckd_private *start_priv; + struct dasd_eckd_private *base_priv; + struct dasd_device *startdev = NULL; + struct dasd_ccw_req *cqr; + struct ccw1 *ccw; + void *data; + int cplength, datasize; + int use_prefix; + int count; + int i; + + if (enable_pav) + startdev = dasd_alias_get_start_dev(base); + + if (!startdev) + startdev = base; + + start_priv = startdev->private; + base_priv = base->private; + + count = rpt * (fdata->stop_unit - fdata->start_unit + 1); + + use_prefix = base_priv->features.feature[8] & 0x01; + + if (use_prefix) { + cplength = 1; + datasize = sizeof(struct PFX_eckd_data); + } else { + cplength = 2; + datasize = sizeof(struct DE_eckd_data) + + sizeof(struct LO_eckd_data); + } + cplength += count; + + cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, + startdev); + if (IS_ERR(cqr)) + return cqr; + + start_priv->count++; + data = cqr->data; + ccw = cqr->cpaddr; + + if (use_prefix) { + prefix_LRE(ccw++, data, fdata->start_unit, fdata->stop_unit, + DASD_ECKD_CCW_READ_COUNT, base, startdev, 1, 0, + count, 0, 0); + } else { + define_extent(ccw++, data, fdata->start_unit, fdata->stop_unit, + DASD_ECKD_CCW_READ_COUNT, startdev); + + data += sizeof(struct DE_eckd_data); + ccw[-1].flags |= CCW_FLAG_CC; + + locate_record(ccw++, data, fdata->start_unit, 0, count, + DASD_ECKD_CCW_READ_COUNT, base, 0); + } + + for (i = 0; i < count; i++) { + ccw[-1].flags |= CCW_FLAG_CC; + ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; + ccw->flags = CCW_FLAG_SLI; + ccw->count = 8; + ccw->cda = (__u32)(addr_t) fmt_buffer; + ccw++; + fmt_buffer++; + } + + cqr->startdev = startdev; + cqr->memdev = startdev; + cqr->basedev = base; + cqr->retries = DASD_RETRIES; + cqr->expires = startdev->default_expires * HZ; + cqr->buildclk = get_tod_clock(); + cqr->status = DASD_CQR_FILLED; + /* Set flags to suppress output for expected errors */ + set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); + + return cqr; +} + static struct dasd_ccw_req * dasd_eckd_build_format(struct dasd_device *base, struct format_data_t *fdata, @@ -2363,9 +2548,24 @@ dasd_eckd_build_format(struct dasd_device *base, */ static struct dasd_ccw_req * dasd_eckd_format_build_ccw_req(struct dasd_device *base, - struct format_data_t *fdata, int enable_pav) + struct format_data_t *fdata, int enable_pav, + int tpm, struct eckd_count *fmt_buffer, int rpt) { - return dasd_eckd_build_format(base, fdata, enable_pav); + struct dasd_ccw_req *ccw_req; + + if (!fmt_buffer) { + ccw_req = dasd_eckd_build_format(base, fdata, enable_pav); + } else { + if (tpm) + ccw_req = dasd_eckd_build_check_tcw(base, fdata, + enable_pav, + fmt_buffer, rpt); + else + ccw_req = dasd_eckd_build_check(base, fdata, enable_pav, + fmt_buffer, rpt); + } + + return ccw_req; } /* @@ -2410,12 +2610,15 @@ static int dasd_eckd_format_sanity_checks(struct dasd_device *base, */ static int dasd_eckd_format_process_data(struct dasd_device *base, struct format_data_t *fdata, - int enable_pav) + int enable_pav, int tpm, + struct eckd_count *fmt_buffer, int rpt, + struct irb *irb) { struct dasd_eckd_private *private = base->private; struct dasd_ccw_req *cqr, *n; struct list_head format_queue; struct dasd_device *device; + char *sense = NULL; int old_start, old_stop, format_step; int step, retry; int rc; @@ -2429,8 +2632,18 @@ static int dasd_eckd_format_process_data(struct dasd_device *base, old_start = fdata->start_unit; old_stop = fdata->stop_unit; - format_step = DASD_CQR_MAX_CCW / recs_per_track(&private->rdc_data, 0, - fdata->blksize); + if (!tpm && fmt_buffer != NULL) { + /* Command Mode / Format Check */ + format_step = 1; + } else if (tpm && fmt_buffer != NULL) { + /* Transport Mode / Format Check */ + format_step = DASD_CQR_MAX_CCW / rpt; + } else { + /* Normal Formatting */ + format_step = DASD_CQR_MAX_CCW / + recs_per_track(&private->rdc_data, 0, fdata->blksize); + } + do { retry = 0; while (fdata->start_unit <= old_stop) { @@ -2441,7 +2654,8 @@ static int dasd_eckd_format_process_data(struct dasd_device *base, } cqr = dasd_eckd_format_build_ccw_req(base, fdata, - enable_pav); + enable_pav, tpm, + fmt_buffer, rpt); if (IS_ERR(cqr)) { rc = PTR_ERR(cqr); if (rc == -ENOMEM) { @@ -2459,6 +2673,10 @@ static int dasd_eckd_format_process_data(struct dasd_device *base, } list_add_tail(&cqr->blocklist, &format_queue); + if (fmt_buffer) { + step = fdata->stop_unit - fdata->start_unit + 1; + fmt_buffer += rpt * step; + } fdata->start_unit = fdata->stop_unit + 1; fdata->stop_unit = old_stop; } @@ -2469,15 +2687,41 @@ static int dasd_eckd_format_process_data(struct dasd_device *base, list_for_each_entry_safe(cqr, n, &format_queue, blocklist) { device = cqr->startdev; private = device->private; - if (cqr->status == DASD_CQR_FAILED) + + if (cqr->status == DASD_CQR_FAILED) { + /* + * Only get sense data if called by format + * check + */ + if (fmt_buffer && irb) { + sense = dasd_get_sense(&cqr->irb); + memcpy(irb, &cqr->irb, sizeof(*irb)); + } rc = -EIO; + } list_del_init(&cqr->blocklist); dasd_sfree_request(cqr, device); private->count--; } - if (rc) + if (rc && rc != -EIO) goto out; + if (rc == -EIO) { + /* + * In case fewer than the expected records are on the + * track, we will most likely get a 'No Record Found' + * error (in command mode) or a 'File Protected' error + * (in transport mode). Those particular cases shouldn't + * pass the -EIO to the IOCTL, therefore reset the rc + * and continue. + */ + if (sense && + (sense[1] & SNS1_NO_REC_FOUND || + sense[1] & SNS1_FILE_PROTECTED)) + retry = 1; + else + goto out; + } } while (retry); @@ -2491,7 +2735,225 @@ static int dasd_eckd_format_process_data(struct dasd_device *base, static int dasd_eckd_format_device(struct dasd_device *base, struct format_data_t *fdata, int enable_pav) { - return dasd_eckd_format_process_data(base, fdata, enable_pav); + return dasd_eckd_format_process_data(base, fdata, enable_pav, 0, NULL, + 0, NULL); +} + +/* + * Helper function to count consecutive records of a single track. + */ +static int dasd_eckd_count_records(struct eckd_count *fmt_buffer, int start, + int max) +{ + int head; + int i; + + head = fmt_buffer[start].head; + + /* + * There are 3 conditions where we stop counting: + * - if data reoccurs (same head and record may reoccur), which may + * happen due to the way DASD_ECKD_CCW_READ_COUNT works + * - when the head changes, because we're iterating over several tracks + * then (DASD_ECKD_CCW_READ_COUNT_MT) + * - when we've reached the end of sensible data in the buffer (the + * record will be 0 then) + */ + for (i = start; i < max; i++) { + if (i > start) { + if ((fmt_buffer[i].head == head && + fmt_buffer[i].record == 1) || + fmt_buffer[i].head != head || + fmt_buffer[i].record == 0) + break; + } + } + + return i - start; +} + +/* + * Evaluate a given range of tracks. Data like number of records, blocksize, + * record ids, and key length are compared with expected data. + * + * If a mismatch occurs, the corresponding error bit is set, as well as + * additional information, depending on the error. + */ +static void dasd_eckd_format_evaluate_tracks(struct eckd_count *fmt_buffer, + struct format_check_t *cdata, + int rpt_max, int rpt_exp, + int trk_per_cyl, int tpm) +{ + struct ch_t geo; + int max_entries; + int count = 0; + int trkcount; + int blksize; + int pos = 0; + int i, j; + int kl; + + trkcount = cdata->expect.stop_unit - cdata->expect.start_unit + 1; + max_entries = trkcount * rpt_max; + + for (i = cdata->expect.start_unit; i <= cdata->expect.stop_unit; i++) { + /* Calculate the correct next starting position in the buffer */ + if (tpm) { + while (fmt_buffer[pos].record == 0 && + fmt_buffer[pos].dl == 0) { + if (pos++ > max_entries) + break; + } + } else { + if (i != cdata->expect.start_unit) + pos += rpt_max - count; + } + + /* Calculate the expected geo values for the current track */ + set_ch_t(&geo, i / trk_per_cyl, i % trk_per_cyl); + + /* Count and check number of records */ + count = dasd_eckd_count_records(fmt_buffer, pos, pos + rpt_max); + + if (count < rpt_exp) { + cdata->result = DASD_FMT_ERR_TOO_FEW_RECORDS; + break; + } + if (count > rpt_exp) { + cdata->result = DASD_FMT_ERR_TOO_MANY_RECORDS; + break; + } + + for (j = 0; j < count; j++, pos++) { + blksize = cdata->expect.blksize; + kl = 0; + + /* + * Set special values when checking CDL formatted + * devices. + */ + if ((cdata->expect.intensity & 0x08) && + geo.cyl == 0 && geo.head == 0) { + if (j < 3) { + blksize = sizes_trk0[j] - 4; + kl = 4; + } + } + if ((cdata->expect.intensity & 0x08) && + geo.cyl == 0 && geo.head == 1) { + blksize = LABEL_SIZE - 44; + kl = 44; + } + + /* Check blocksize */ + if (fmt_buffer[pos].dl != blksize) { + cdata->result = DASD_FMT_ERR_BLKSIZE; + goto out; + } + /* Check if key length is 0 */ + if (fmt_buffer[pos].kl != kl) { + cdata->result = DASD_FMT_ERR_KEY_LENGTH; + goto out; + } + /* Check if record_id is correct */ + if (fmt_buffer[pos].cyl != geo.cyl || + fmt_buffer[pos].head != geo.head || + fmt_buffer[pos].record != (j + 1)) { + cdata->result = DASD_FMT_ERR_RECORD_ID; + goto out; + } + } + } + +out: + /* + * In case of no errors, we need to decrease by one + * to get the correct positions. + */ + if (!cdata->result) { + i--; + pos--; + } + + cdata->unit = i; + cdata->num_records = count; + cdata->rec = fmt_buffer[pos].record; + cdata->blksize = fmt_buffer[pos].dl; + cdata->key_length = fmt_buffer[pos].kl; +} + +/* + * Check the format of a range of tracks of a DASD. + */ +static int dasd_eckd_check_device_format(struct dasd_device *base, + struct format_check_t *cdata, + int enable_pav) +{ + struct dasd_eckd_private *private = base->private; + struct eckd_count *fmt_buffer; + struct irb irb; + int rpt_max, rpt_exp; + int fmt_buffer_size; + int trk_per_cyl; + int trkcount; + int tpm = 0; + int rc; + + trk_per_cyl = private->rdc_data.trk_per_cyl; + + /* Get maximum and expected amount of records per track */ + rpt_max = recs_per_track(&private->rdc_data, 0, 512) + 1; + rpt_exp = recs_per_track(&private->rdc_data, 0, cdata->expect.blksize); + + trkcount = cdata->expect.stop_unit - cdata->expect.start_unit + 1; + fmt_buffer_size = trkcount * rpt_max * sizeof(struct eckd_count); + + fmt_buffer = kzalloc(fmt_buffer_size, GFP_KERNEL | GFP_DMA); + if (!fmt_buffer) + return -ENOMEM; + + /* + * A certain FICON feature subset is needed to operate in transport + * mode. Additionally, the support for transport mode is implicitly + * checked by comparing the buffer size with fcx_max_data. As long as + * the buffer size is smaller we can operate in transport mode and + * process multiple tracks. If not, only one track at once is being + * processed using command mode. + */ + if ((private->features.feature[40] & 0x04) && + fmt_buffer_size <= private->fcx_max_data) + tpm = 1; + + rc = dasd_eckd_format_process_data(base, &cdata->expect, enable_pav, + tpm, fmt_buffer, rpt_max, &irb); + if (rc && rc != -EIO) + goto out; + if (rc == -EIO) { + /* + * If our first attempt with transport mode enabled comes back + * with an incorrect length error, we're going to retry the + * check with command mode. + */ + if (tpm && scsw_cstat(&irb.scsw) == 0x40) { + tpm = 0; + rc = dasd_eckd_format_process_data(base, &cdata->expect, + enable_pav, tpm, + fmt_buffer, rpt_max, + &irb); + if (rc) + goto out; + } else { + goto out; + } + } + + dasd_eckd_format_evaluate_tracks(fmt_buffer, cdata, rpt_max, rpt_exp, + trk_per_cyl, tpm); + +out: + kfree(fmt_buffer); + + return rc; } static void dasd_eckd_handle_terminated_request(struct dasd_ccw_req *cqr) @@ -3038,6 +3500,16 @@ static int prepare_itcw(struct itcw *itcw, lredata->auxiliary.check_bytes = 0x2; pfx_cmd = DASD_ECKD_CCW_PFX; break; + case DASD_ECKD_CCW_READ_COUNT_MT: + dedata->mask.perm = 0x1; + dedata->attributes.operation = DASD_BYPASS_CACHE; + dedata->ga_extended |= 0x42; + dedata->blk_size = blksize; + lredata->operation.orientation = 0x2; + lredata->operation.operation = 0x16; + lredata->auxiliary.check_bytes = 0x01; + pfx_cmd = DASD_ECKD_CCW_PFX_READ; + break; default: DBF_DEV_EVENT(DBF_ERR, basedev, "prepare itcw, unknown opcode 0x%x", cmd); @@ -3085,13 +3557,19 @@ static int prepare_itcw(struct itcw *itcw, } } - lredata->auxiliary.length_valid = 1; - lredata->auxiliary.length_scope = 1; + if (cmd == DASD_ECKD_CCW_READ_COUNT_MT) { + lredata->auxiliary.length_valid = 0; + lredata->auxiliary.length_scope = 0; + lredata->sector = 0xff; + } else { + lredata->auxiliary.length_valid = 1; + lredata->auxiliary.length_scope = 1; + lredata->sector = sector; + } lredata->auxiliary.imbedded_ccw_valid = 1; lredata->length = tlf; lredata->imbedded_ccw = cmd; lredata->count = count; - lredata->sector = sector; set_ch_t(&lredata->seek_addr, begcyl, beghead); lredata->search_arg.cyl = lredata->seek_addr.cyl; lredata->search_arg.head = lredata->seek_addr.head; @@ -4413,10 +4891,34 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, static void dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req *req, struct irb *irb) { - if (scsw_is_tm(&irb->scsw)) + u8 *sense = dasd_get_sense(irb); + + if (scsw_is_tm(&irb->scsw)) { + /* + * In some cases the 'File Protected' or 'Incorrect Length' + * error might be expected and log messages shouldn't be written + * then. Check if the according suppress bit is set. + */ + if (sense && (sense[1] & SNS1_FILE_PROTECTED) && + test_bit(DASD_CQR_SUPPRESS_FP, &req->flags)) + return; + if (scsw_cstat(&irb->scsw) == 0x40 && + test_bit(DASD_CQR_SUPPRESS_IL, &req->flags)) + return; + dasd_eckd_dump_sense_tcw(device, req, irb); - else + } else { + /* + * In some cases the 'No Record Found' error might be expected + * and log messages shouldn't be written then. Check if the + * according suppress bit is set. + */ + if (sense && sense[1] & SNS1_NO_REC_FOUND && + test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags)) + return; + dasd_eckd_dump_sense_ccw(device, req, irb); + } } static int dasd_eckd_pm_freeze(struct dasd_device *device) @@ -5246,6 +5748,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .term_IO = dasd_term_IO, .handle_terminated_request = dasd_eckd_handle_terminated_request, .format_device = dasd_eckd_format_device, + .check_device_format = dasd_eckd_check_device_format, .erp_action = dasd_eckd_erp_action, .erp_postaction = dasd_eckd_erp_postaction, .check_for_device_change = dasd_eckd_check_for_device_change, diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 862ee4291abd..59803626ea36 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -35,6 +35,7 @@ #define DASD_ECKD_CCW_READ_MT 0x86 #define DASD_ECKD_CCW_WRITE_KD_MT 0x8d #define DASD_ECKD_CCW_READ_KD_MT 0x8e +#define DASD_ECKD_CCW_READ_COUNT_MT 0x92 #define DASD_ECKD_CCW_RELEASE 0x94 #define DASD_ECKD_CCW_WRITE_FULL_TRACK 0x95 #define DASD_ECKD_CCW_READ_CKD_MT 0x9e diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 6132733bcd95..ac7027e6d52b 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -236,6 +236,13 @@ struct dasd_ccw_req { * stolen. Should not be combined with * DASD_CQR_FLAGS_USE_ERP */ +/* + * The following flags are used to suppress output of certain errors. + * These flags should only be used for format checks! + */ +#define DASD_CQR_SUPPRESS_NRF 4 /* Suppress 'No Record Found' error */ +#define DASD_CQR_SUPPRESS_FP 5 /* Suppress 'File Protected' error*/ +#define DASD_CQR_SUPPRESS_IL 6 /* Suppress 'Incorrect Length' error */ /* Signature for error recovery functions. */ typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); @@ -318,7 +325,8 @@ struct dasd_discipline { * Device operation functions. build_cp creates a ccw chain for * a block device request, start_io starts the request and * term_IO cancels it (e.g. in case of a timeout). format_device - * returns a ccw chain to be used to format the device. + * formats the device and check_device_format compares the format of + * a device with the expected format_data. * handle_terminated_request allows to examine a cqr and prepare * it for retry. */ @@ -329,7 +337,9 @@ struct dasd_discipline { int (*term_IO) (struct dasd_ccw_req *); void (*handle_terminated_request) (struct dasd_ccw_req *); int (*format_device) (struct dasd_device *, - struct format_data_t *, int enable_pav); + struct format_data_t *, int); + int (*check_device_format)(struct dasd_device *, + struct format_check_t *, int); int (*free_cp) (struct dasd_ccw_req *, struct request *); /* diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 90f30cc31561..9dfbd972f844 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -238,6 +238,23 @@ dasd_format(struct dasd_block *block, struct format_data_t *fdata) return rc; } +static int dasd_check_format(struct dasd_block *block, + struct format_check_t *cdata) +{ + struct dasd_device *base; + int rc; + + base = block->base; + if (!base->discipline->check_device_format) + return -ENOTTY; + + rc = base->discipline->check_device_format(base, cdata, 1); + if (rc == -EAGAIN) + rc = base->discipline->check_device_format(base, cdata, 0); + + return rc; +} + /* * Format device. */ @@ -272,6 +289,47 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) } rc = dasd_format(base->block, &fdata); dasd_put_device(base); + + return rc; +} + +/* + * Check device format + */ +static int dasd_ioctl_check_format(struct block_device *bdev, void __user *argp) +{ + struct format_check_t cdata; + struct dasd_device *base; + int rc = 0; + + if (!argp) + return -EINVAL; + + base = dasd_device_from_gendisk(bdev->bd_disk); + if (!base) + return -ENODEV; + if (bdev != bdev->bd_contains) { + pr_warn("%s: The specified DASD is a partition and cannot be checked\n", + dev_name(&base->cdev->dev)); + rc = -EINVAL; + goto out_err; + } + + if (copy_from_user(&cdata, argp, sizeof(cdata))) { + rc = -EFAULT; + goto out_err; + } + + rc = dasd_check_format(base->block, &cdata); + if (rc) + goto out_err; + + if (copy_to_user(argp, &cdata, sizeof(cdata))) + rc = -EFAULT; + +out_err: + dasd_put_device(base); + return rc; } @@ -519,6 +577,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, case BIODASDFMT: rc = dasd_ioctl_format(bdev, argp); break; + case BIODASDCHECKFMT: + rc = dasd_ioctl_check_format(bdev, argp); + break; case BIODASDINFO: rc = dasd_ioctl_information(block, cmd, argp); break; -- GitLab From f9dc447ec8f1f0a9f2ba4e4d5a61758f8df4acd8 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 29 Jun 2015 18:47:28 +0200 Subject: [PATCH 2952/9938] s390/pci: fmb enhancements Implement the function type specific function measurement block used in new machines. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/pci.h | 35 ++++++++++++++++----- arch/s390/pci/pci_debug.c | 61 ++++++++++++++++++++++++++++--------- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 535a46d46d28..0da91c4d30fd 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -31,20 +31,41 @@ int pci_proc_domain(struct pci_bus *); #define ZPCI_FC_BLOCKED 0x20 #define ZPCI_FC_DMA_ENABLED 0x10 +#define ZPCI_FMB_DMA_COUNTER_VALID (1 << 23) + +struct zpci_fmb_fmt0 { + u64 dma_rbytes; + u64 dma_wbytes; +}; + +struct zpci_fmb_fmt1 { + u64 rx_bytes; + u64 rx_packets; + u64 tx_bytes; + u64 tx_packets; +}; + +struct zpci_fmb_fmt2 { + u64 consumed_work_units; + u64 max_work_units; +}; + struct zpci_fmb { - u32 format : 8; - u32 dma_valid : 1; - u32 : 23; + u32 format : 8; + u32 fmt_ind : 24; u32 samples; u64 last_update; - /* hardware counters */ + /* common counters */ u64 ld_ops; u64 st_ops; u64 stb_ops; u64 rpcit_ops; - u64 dma_rbytes; - u64 dma_wbytes; - u64 pad[2]; + /* format specific counters */ + union { + struct zpci_fmb_fmt0 fmt0; + struct zpci_fmb_fmt1 fmt1; + struct zpci_fmb_fmt2 fmt2; + }; } __packed __aligned(128); enum zpci_state { diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c index c555de3d12d6..38993b156924 100644 --- a/arch/s390/pci/pci_debug.c +++ b/arch/s390/pci/pci_debug.c @@ -1,5 +1,5 @@ /* - * Copyright IBM Corp. 2012 + * Copyright IBM Corp. 2012,2015 * * Author(s): * Jan Glauber @@ -23,22 +23,45 @@ EXPORT_SYMBOL_GPL(pci_debug_msg_id); debug_info_t *pci_debug_err_id; EXPORT_SYMBOL_GPL(pci_debug_err_id); -static char *pci_perf_names[] = { - /* hardware counters */ +static char *pci_common_names[] = { "Load operations", "Store operations", "Store block operations", "Refresh operations", +}; + +static char *pci_fmt0_names[] = { "DMA read bytes", "DMA write bytes", }; +static char *pci_fmt1_names[] = { + "Received bytes", + "Received packets", + "Transmitted bytes", + "Transmitted packets", +}; + +static char *pci_fmt2_names[] = { + "Consumed work units", + "Maximum work units", +}; + static char *pci_sw_names[] = { "Allocated pages", "Mapped pages", "Unmapped pages", }; +static void pci_fmb_show(struct seq_file *m, char *name[], int length, + u64 *data) +{ + int i; + + for (i = 0; i < length; i++, data++) + seq_printf(m, "%26s:\t%llu\n", name[i], *data); +} + static void pci_sw_counter_show(struct seq_file *m) { struct zpci_dev *zdev = m->private; @@ -53,8 +76,6 @@ static void pci_sw_counter_show(struct seq_file *m) static int pci_perf_show(struct seq_file *m, void *v) { struct zpci_dev *zdev = m->private; - u64 *stat; - int i; if (!zdev) return 0; @@ -72,15 +93,27 @@ static int pci_perf_show(struct seq_file *m, void *v) seq_printf(m, "Samples: %u\n", zdev->fmb->samples); seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update); - /* hardware counters */ - stat = (u64 *) &zdev->fmb->ld_ops; - for (i = 0; i < 4; i++) - seq_printf(m, "%26s:\t%llu\n", - pci_perf_names[i], *(stat + i)); - if (zdev->fmb->dma_valid) - for (i = 4; i < 6; i++) - seq_printf(m, "%26s:\t%llu\n", - pci_perf_names[i], *(stat + i)); + pci_fmb_show(m, pci_common_names, ARRAY_SIZE(pci_common_names), + &zdev->fmb->ld_ops); + + switch (zdev->fmb->format) { + case 0: + if (!(zdev->fmb->fmt_ind & ZPCI_FMB_DMA_COUNTER_VALID)) + break; + pci_fmb_show(m, pci_fmt0_names, ARRAY_SIZE(pci_fmt0_names), + &zdev->fmb->fmt0.dma_rbytes); + break; + case 1: + pci_fmb_show(m, pci_fmt1_names, ARRAY_SIZE(pci_fmt1_names), + &zdev->fmb->fmt1.rx_bytes); + break; + case 2: + pci_fmb_show(m, pci_fmt2_names, ARRAY_SIZE(pci_fmt2_names), + &zdev->fmb->fmt2.consumed_work_units); + break; + default: + seq_puts(m, "Unknown format\n"); + } pci_sw_counter_show(m); mutex_unlock(&zdev->lock); -- GitLab From c7d4d259b7477866376435155eb0ccdaee880677 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 17 Mar 2016 15:22:12 +0100 Subject: [PATCH 2953/9938] s390/crypto: cleanup and move the header with the cpacf definitions The CPACF instructions are going be used in KVM as well, move the defines and the inline functions from arch/s390/crypt/crypt_s390.h to arch/s390/include/asm. Rename the header to cpacf.h and replace the crypt_s390_xxx names with cpacf_xxx. While we are at it, cleanup the header as well. The encoding for the CPACF operations is odd, there is an enum for each of the CPACF instructions with the hardware function code in the lower 8 bits of each entry and a software defined number for the CPACF instruction in the upper 8 bits. Remove the superfluous software number and replace the enums with simple defines. The crypt_s390_func_available() function tests for the presence of a specific CPACF operations. The new name of the function is cpacf_query and it works slightly different than before. It gets passed an opcode of an CPACF instruction and a function code for this instruction. The facility_mask parameter is gone, the opcode is used to find the correct MSA facility bit to check if the CPACF instruction itself is available. If it is the query function of the given instruction is used to test if the requested CPACF operation is present. Acked-by: David Hildenbrand Signed-off-by: Martin Schwidefsky --- arch/s390/crypto/aes_s390.c | 117 ++++---- arch/s390/crypto/crypt_s390.h | 493 --------------------------------- arch/s390/crypto/des_s390.c | 72 +++-- arch/s390/crypto/ghash_s390.c | 16 +- arch/s390/crypto/prng.c | 60 ++-- arch/s390/crypto/sha1_s390.c | 10 +- arch/s390/crypto/sha256_s390.c | 14 +- arch/s390/crypto/sha512_s390.c | 14 +- arch/s390/crypto/sha_common.c | 10 +- arch/s390/include/asm/cpacf.h | 410 +++++++++++++++++++++++++++ 10 files changed, 556 insertions(+), 660 deletions(-) delete mode 100644 arch/s390/crypto/crypt_s390.h create mode 100644 arch/s390/include/asm/cpacf.h diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 48e1a2d3e318..7554a8bb2adc 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -28,7 +28,7 @@ #include #include #include -#include "crypt_s390.h" +#include #define AES_KEYLEN_128 1 #define AES_KEYLEN_192 2 @@ -145,16 +145,16 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) switch (sctx->key_len) { case 16: - crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); + cpacf_km(CPACF_KM_AES_128_ENC, &sctx->key, out, in, + AES_BLOCK_SIZE); break; case 24: - crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); + cpacf_km(CPACF_KM_AES_192_ENC, &sctx->key, out, in, + AES_BLOCK_SIZE); break; case 32: - crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); + cpacf_km(CPACF_KM_AES_256_ENC, &sctx->key, out, in, + AES_BLOCK_SIZE); break; } } @@ -170,16 +170,16 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) switch (sctx->key_len) { case 16: - crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); + cpacf_km(CPACF_KM_AES_128_DEC, &sctx->key, out, in, + AES_BLOCK_SIZE); break; case 24: - crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); + cpacf_km(CPACF_KM_AES_192_DEC, &sctx->key, out, in, + AES_BLOCK_SIZE); break; case 32: - crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); + cpacf_km(CPACF_KM_AES_256_DEC, &sctx->key, out, in, + AES_BLOCK_SIZE); break; } } @@ -212,7 +212,7 @@ static void fallback_exit_cip(struct crypto_tfm *tfm) static struct crypto_alg aes_alg = { .cra_name = "aes", .cra_driver_name = "aes-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, @@ -298,16 +298,16 @@ static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, switch (key_len) { case 16: - sctx->enc = KM_AES_128_ENCRYPT; - sctx->dec = KM_AES_128_DECRYPT; + sctx->enc = CPACF_KM_AES_128_ENC; + sctx->dec = CPACF_KM_AES_128_DEC; break; case 24: - sctx->enc = KM_AES_192_ENCRYPT; - sctx->dec = KM_AES_192_DECRYPT; + sctx->enc = CPACF_KM_AES_192_ENC; + sctx->dec = CPACF_KM_AES_192_DEC; break; case 32: - sctx->enc = KM_AES_256_ENCRYPT; - sctx->dec = KM_AES_256_DECRYPT; + sctx->enc = CPACF_KM_AES_256_ENC; + sctx->dec = CPACF_KM_AES_256_DEC; break; } @@ -326,7 +326,7 @@ static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param, u8 *out = walk->dst.virt.addr; u8 *in = walk->src.virt.addr; - ret = crypt_s390_km(func, param, out, in, n); + ret = cpacf_km(func, param, out, in, n); if (ret < 0 || ret != n) return -EIO; @@ -393,7 +393,7 @@ static void fallback_exit_blk(struct crypto_tfm *tfm) static struct crypto_alg ecb_aes_alg = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: aes + ecb */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, @@ -427,16 +427,16 @@ static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, switch (key_len) { case 16: - sctx->enc = KMC_AES_128_ENCRYPT; - sctx->dec = KMC_AES_128_DECRYPT; + sctx->enc = CPACF_KMC_AES_128_ENC; + sctx->dec = CPACF_KMC_AES_128_DEC; break; case 24: - sctx->enc = KMC_AES_192_ENCRYPT; - sctx->dec = KMC_AES_192_DECRYPT; + sctx->enc = CPACF_KMC_AES_192_ENC; + sctx->dec = CPACF_KMC_AES_192_DEC; break; case 32: - sctx->enc = KMC_AES_256_ENCRYPT; - sctx->dec = KMC_AES_256_DECRYPT; + sctx->enc = CPACF_KMC_AES_256_ENC; + sctx->dec = CPACF_KMC_AES_256_DEC; break; } @@ -465,7 +465,7 @@ static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, u8 *out = walk->dst.virt.addr; u8 *in = walk->src.virt.addr; - ret = crypt_s390_kmc(func, ¶m, out, in, n); + ret = cpacf_kmc(func, ¶m, out, in, n); if (ret < 0 || ret != n) return -EIO; @@ -509,7 +509,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc, static struct crypto_alg cbc_aes_alg = { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: aes + cbc */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, @@ -596,8 +596,8 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, switch (key_len) { case 32: - xts_ctx->enc = KM_XTS_128_ENCRYPT; - xts_ctx->dec = KM_XTS_128_DECRYPT; + xts_ctx->enc = CPACF_KM_XTS_128_ENC; + xts_ctx->dec = CPACF_KM_XTS_128_DEC; memcpy(xts_ctx->key + 16, in_key, 16); memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16); break; @@ -607,8 +607,8 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, xts_fallback_setkey(tfm, in_key, key_len); break; case 64: - xts_ctx->enc = KM_XTS_256_ENCRYPT; - xts_ctx->dec = KM_XTS_256_DECRYPT; + xts_ctx->enc = CPACF_KM_XTS_256_ENC; + xts_ctx->dec = CPACF_KM_XTS_256_DEC; memcpy(xts_ctx->key, in_key, 32); memcpy(xts_ctx->pcc_key, in_key + 32, 32); break; @@ -643,7 +643,8 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func, memset(pcc_param.xts, 0, sizeof(pcc_param.xts)); memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak)); memcpy(pcc_param.key, xts_ctx->pcc_key, 32); - ret = crypt_s390_pcc(func, &pcc_param.key[offset]); + /* remove decipher modifier bit from 'func' and call PCC */ + ret = cpacf_pcc(func & 0x7f, &pcc_param.key[offset]); if (ret < 0) return -EIO; @@ -655,7 +656,7 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func, out = walk->dst.virt.addr; in = walk->src.virt.addr; - ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n); + ret = cpacf_km(func, &xts_param.key[offset], out, in, n); if (ret < 0 || ret != n) return -EIO; @@ -721,7 +722,7 @@ static void xts_fallback_exit(struct crypto_tfm *tfm) static struct crypto_alg xts_aes_alg = { .cra_name = "xts(aes)", .cra_driver_name = "xts-aes-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: aes + xts */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, @@ -751,16 +752,16 @@ static int ctr_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, switch (key_len) { case 16: - sctx->enc = KMCTR_AES_128_ENCRYPT; - sctx->dec = KMCTR_AES_128_DECRYPT; + sctx->enc = CPACF_KMCTR_AES_128_ENC; + sctx->dec = CPACF_KMCTR_AES_128_DEC; break; case 24: - sctx->enc = KMCTR_AES_192_ENCRYPT; - sctx->dec = KMCTR_AES_192_DECRYPT; + sctx->enc = CPACF_KMCTR_AES_192_ENC; + sctx->dec = CPACF_KMCTR_AES_192_DEC; break; case 32: - sctx->enc = KMCTR_AES_256_ENCRYPT; - sctx->dec = KMCTR_AES_256_DECRYPT; + sctx->enc = CPACF_KMCTR_AES_256_ENC; + sctx->dec = CPACF_KMCTR_AES_256_DEC; break; } @@ -804,8 +805,7 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func, n = __ctrblk_init(ctrptr, nbytes); else n = AES_BLOCK_SIZE; - ret = crypt_s390_kmctr(func, sctx->key, out, in, - n, ctrptr); + ret = cpacf_kmctr(func, sctx->key, out, in, n, ctrptr); if (ret < 0 || ret != n) { if (ctrptr == ctrblk) spin_unlock(&ctrblk_lock); @@ -837,8 +837,8 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func, if (nbytes) { out = walk->dst.virt.addr; in = walk->src.virt.addr; - ret = crypt_s390_kmctr(func, sctx->key, buf, in, - AES_BLOCK_SIZE, ctrbuf); + ret = cpacf_kmctr(func, sctx->key, buf, in, + AES_BLOCK_SIZE, ctrbuf); if (ret < 0 || ret != AES_BLOCK_SIZE) return -EIO; memcpy(out, buf, nbytes); @@ -875,7 +875,7 @@ static int ctr_aes_decrypt(struct blkcipher_desc *desc, static struct crypto_alg ctr_aes_alg = { .cra_name = "ctr(aes)", .cra_driver_name = "ctr-aes-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: aes + ctr */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, .cra_blocksize = 1, .cra_ctxsize = sizeof(struct s390_aes_ctx), @@ -899,11 +899,11 @@ static int __init aes_s390_init(void) { int ret; - if (crypt_s390_func_available(KM_AES_128_ENCRYPT, CRYPT_S390_MSA)) + if (cpacf_query(CPACF_KM, CPACF_KM_AES_128_ENC)) keylen_flag |= AES_KEYLEN_128; - if (crypt_s390_func_available(KM_AES_192_ENCRYPT, CRYPT_S390_MSA)) + if (cpacf_query(CPACF_KM, CPACF_KM_AES_192_ENC)) keylen_flag |= AES_KEYLEN_192; - if (crypt_s390_func_available(KM_AES_256_ENCRYPT, CRYPT_S390_MSA)) + if (cpacf_query(CPACF_KM, CPACF_KM_AES_256_ENC)) keylen_flag |= AES_KEYLEN_256; if (!keylen_flag) @@ -926,22 +926,17 @@ static int __init aes_s390_init(void) if (ret) goto cbc_aes_err; - if (crypt_s390_func_available(KM_XTS_128_ENCRYPT, - CRYPT_S390_MSA | CRYPT_S390_MSA4) && - crypt_s390_func_available(KM_XTS_256_ENCRYPT, - CRYPT_S390_MSA | CRYPT_S390_MSA4)) { + if (cpacf_query(CPACF_KM, CPACF_KM_XTS_128_ENC) && + cpacf_query(CPACF_KM, CPACF_KM_XTS_256_ENC)) { ret = crypto_register_alg(&xts_aes_alg); if (ret) goto xts_aes_err; xts_aes_alg_reg = 1; } - if (crypt_s390_func_available(KMCTR_AES_128_ENCRYPT, - CRYPT_S390_MSA | CRYPT_S390_MSA4) && - crypt_s390_func_available(KMCTR_AES_192_ENCRYPT, - CRYPT_S390_MSA | CRYPT_S390_MSA4) && - crypt_s390_func_available(KMCTR_AES_256_ENCRYPT, - CRYPT_S390_MSA | CRYPT_S390_MSA4)) { + if (cpacf_query(CPACF_KMCTR, CPACF_KMCTR_AES_128_ENC) && + cpacf_query(CPACF_KMCTR, CPACF_KMCTR_AES_192_ENC) && + cpacf_query(CPACF_KMCTR, CPACF_KMCTR_AES_256_ENC)) { ctrblk = (u8 *) __get_free_page(GFP_KERNEL); if (!ctrblk) { ret = -ENOMEM; diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h deleted file mode 100644 index d9c4c313fbc6..000000000000 --- a/arch/s390/crypto/crypt_s390.h +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Cryptographic API. - * - * Support for s390 cryptographic instructions. - * - * Copyright IBM Corp. 2003, 2015 - * Author(s): Thomas Spatzier - * Jan Glauber (jan.glauber@de.ibm.com) - * Harald Freudenberger (freude@de.ibm.com) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ -#ifndef _CRYPTO_ARCH_S390_CRYPT_S390_H -#define _CRYPTO_ARCH_S390_CRYPT_S390_H - -#include -#include - -#define CRYPT_S390_OP_MASK 0xFF00 -#define CRYPT_S390_FUNC_MASK 0x00FF - -#define CRYPT_S390_PRIORITY 300 -#define CRYPT_S390_COMPOSITE_PRIORITY 400 - -#define CRYPT_S390_MSA 0x1 -#define CRYPT_S390_MSA3 0x2 -#define CRYPT_S390_MSA4 0x4 -#define CRYPT_S390_MSA5 0x8 - -/* s390 cryptographic operations */ -enum crypt_s390_operations { - CRYPT_S390_KM = 0x0100, - CRYPT_S390_KMC = 0x0200, - CRYPT_S390_KIMD = 0x0300, - CRYPT_S390_KLMD = 0x0400, - CRYPT_S390_KMAC = 0x0500, - CRYPT_S390_KMCTR = 0x0600, - CRYPT_S390_PPNO = 0x0700 -}; - -/* - * function codes for KM (CIPHER MESSAGE) instruction - * 0x80 is the decipher modifier bit - */ -enum crypt_s390_km_func { - KM_QUERY = CRYPT_S390_KM | 0x0, - KM_DEA_ENCRYPT = CRYPT_S390_KM | 0x1, - KM_DEA_DECRYPT = CRYPT_S390_KM | 0x1 | 0x80, - KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2, - KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80, - KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3, - KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 0x3 | 0x80, - KM_AES_128_ENCRYPT = CRYPT_S390_KM | 0x12, - KM_AES_128_DECRYPT = CRYPT_S390_KM | 0x12 | 0x80, - KM_AES_192_ENCRYPT = CRYPT_S390_KM | 0x13, - KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80, - KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14, - KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80, - KM_XTS_128_ENCRYPT = CRYPT_S390_KM | 0x32, - KM_XTS_128_DECRYPT = CRYPT_S390_KM | 0x32 | 0x80, - KM_XTS_256_ENCRYPT = CRYPT_S390_KM | 0x34, - KM_XTS_256_DECRYPT = CRYPT_S390_KM | 0x34 | 0x80, -}; - -/* - * function codes for KMC (CIPHER MESSAGE WITH CHAINING) - * instruction - */ -enum crypt_s390_kmc_func { - KMC_QUERY = CRYPT_S390_KMC | 0x0, - KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 0x1, - KMC_DEA_DECRYPT = CRYPT_S390_KMC | 0x1 | 0x80, - KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2, - KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80, - KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3, - KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 0x3 | 0x80, - KMC_AES_128_ENCRYPT = CRYPT_S390_KMC | 0x12, - KMC_AES_128_DECRYPT = CRYPT_S390_KMC | 0x12 | 0x80, - KMC_AES_192_ENCRYPT = CRYPT_S390_KMC | 0x13, - KMC_AES_192_DECRYPT = CRYPT_S390_KMC | 0x13 | 0x80, - KMC_AES_256_ENCRYPT = CRYPT_S390_KMC | 0x14, - KMC_AES_256_DECRYPT = CRYPT_S390_KMC | 0x14 | 0x80, - KMC_PRNG = CRYPT_S390_KMC | 0x43, -}; - -/* - * function codes for KMCTR (CIPHER MESSAGE WITH COUNTER) - * instruction - */ -enum crypt_s390_kmctr_func { - KMCTR_QUERY = CRYPT_S390_KMCTR | 0x0, - KMCTR_DEA_ENCRYPT = CRYPT_S390_KMCTR | 0x1, - KMCTR_DEA_DECRYPT = CRYPT_S390_KMCTR | 0x1 | 0x80, - KMCTR_TDEA_128_ENCRYPT = CRYPT_S390_KMCTR | 0x2, - KMCTR_TDEA_128_DECRYPT = CRYPT_S390_KMCTR | 0x2 | 0x80, - KMCTR_TDEA_192_ENCRYPT = CRYPT_S390_KMCTR | 0x3, - KMCTR_TDEA_192_DECRYPT = CRYPT_S390_KMCTR | 0x3 | 0x80, - KMCTR_AES_128_ENCRYPT = CRYPT_S390_KMCTR | 0x12, - KMCTR_AES_128_DECRYPT = CRYPT_S390_KMCTR | 0x12 | 0x80, - KMCTR_AES_192_ENCRYPT = CRYPT_S390_KMCTR | 0x13, - KMCTR_AES_192_DECRYPT = CRYPT_S390_KMCTR | 0x13 | 0x80, - KMCTR_AES_256_ENCRYPT = CRYPT_S390_KMCTR | 0x14, - KMCTR_AES_256_DECRYPT = CRYPT_S390_KMCTR | 0x14 | 0x80, -}; - -/* - * function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) - * instruction - */ -enum crypt_s390_kimd_func { - KIMD_QUERY = CRYPT_S390_KIMD | 0, - KIMD_SHA_1 = CRYPT_S390_KIMD | 1, - KIMD_SHA_256 = CRYPT_S390_KIMD | 2, - KIMD_SHA_512 = CRYPT_S390_KIMD | 3, - KIMD_GHASH = CRYPT_S390_KIMD | 65, -}; - -/* - * function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) - * instruction - */ -enum crypt_s390_klmd_func { - KLMD_QUERY = CRYPT_S390_KLMD | 0, - KLMD_SHA_1 = CRYPT_S390_KLMD | 1, - KLMD_SHA_256 = CRYPT_S390_KLMD | 2, - KLMD_SHA_512 = CRYPT_S390_KLMD | 3, -}; - -/* - * function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) - * instruction - */ -enum crypt_s390_kmac_func { - KMAC_QUERY = CRYPT_S390_KMAC | 0, - KMAC_DEA = CRYPT_S390_KMAC | 1, - KMAC_TDEA_128 = CRYPT_S390_KMAC | 2, - KMAC_TDEA_192 = CRYPT_S390_KMAC | 3 -}; - -/* - * function codes for PPNO (PERFORM PSEUDORANDOM NUMBER - * OPERATION) instruction - */ -enum crypt_s390_ppno_func { - PPNO_QUERY = CRYPT_S390_PPNO | 0, - PPNO_SHA512_DRNG_GEN = CRYPT_S390_PPNO | 3, - PPNO_SHA512_DRNG_SEED = CRYPT_S390_PPNO | 0x83 -}; - -/** - * crypt_s390_km: - * @func: the function code passed to KM; see crypt_s390_km_func - * @param: address of parameter block; see POP for details on each func - * @dest: address of destination memory area - * @src: address of source memory area - * @src_len: length of src operand in bytes - * - * Executes the KM (CIPHER MESSAGE) operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for encryption/decryption funcs - */ -static inline int crypt_s390_km(long func, void *param, - u8 *dest, const u8 *src, long src_len) -{ - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; - register long __src_len asm("3") = src_len; - register u8 *__dest asm("4") = dest; - int ret; - - asm volatile( - "0: .insn rre,0xb92e0000,%3,%1\n" /* KM opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); - if (ret < 0) - return ret; - return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; -} - -/** - * crypt_s390_kmc: - * @func: the function code passed to KM; see crypt_s390_kmc_func - * @param: address of parameter block; see POP for details on each func - * @dest: address of destination memory area - * @src: address of source memory area - * @src_len: length of src operand in bytes - * - * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for encryption/decryption funcs - */ -static inline int crypt_s390_kmc(long func, void *param, - u8 *dest, const u8 *src, long src_len) -{ - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; - register long __src_len asm("3") = src_len; - register u8 *__dest asm("4") = dest; - int ret; - - asm volatile( - "0: .insn rre,0xb92f0000,%3,%1\n" /* KMC opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); - if (ret < 0) - return ret; - return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; -} - -/** - * crypt_s390_kimd: - * @func: the function code passed to KM; see crypt_s390_kimd_func - * @param: address of parameter block; see POP for details on each func - * @src: address of source memory area - * @src_len: length of src operand in bytes - * - * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation - * of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for digest funcs - */ -static inline int crypt_s390_kimd(long func, void *param, - const u8 *src, long src_len) -{ - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - asm volatile( - "0: .insn rre,0xb93e0000,%1,%1\n" /* KIMD opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "=d" (ret), "+a" (__src), "+d" (__src_len) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); - if (ret < 0) - return ret; - return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; -} - -/** - * crypt_s390_klmd: - * @func: the function code passed to KM; see crypt_s390_klmd_func - * @param: address of parameter block; see POP for details on each func - * @src: address of source memory area - * @src_len: length of src operand in bytes - * - * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for digest funcs - */ -static inline int crypt_s390_klmd(long func, void *param, - const u8 *src, long src_len) -{ - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - asm volatile( - "0: .insn rre,0xb93f0000,%1,%1\n" /* KLMD opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "=d" (ret), "+a" (__src), "+d" (__src_len) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); - if (ret < 0) - return ret; - return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; -} - -/** - * crypt_s390_kmac: - * @func: the function code passed to KM; see crypt_s390_klmd_func - * @param: address of parameter block; see POP for details on each func - * @src: address of source memory area - * @src_len: length of src operand in bytes - * - * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation - * of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for digest funcs - */ -static inline int crypt_s390_kmac(long func, void *param, - const u8 *src, long src_len) -{ - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - asm volatile( - "0: .insn rre,0xb91e0000,%1,%1\n" /* KLAC opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "=d" (ret), "+a" (__src), "+d" (__src_len) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); - if (ret < 0) - return ret; - return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; -} - -/** - * crypt_s390_kmctr: - * @func: the function code passed to KMCTR; see crypt_s390_kmctr_func - * @param: address of parameter block; see POP for details on each func - * @dest: address of destination memory area - * @src: address of source memory area - * @src_len: length of src operand in bytes - * @counter: address of counter value - * - * Executes the KMCTR (CIPHER MESSAGE WITH COUNTER) operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for encryption/decryption funcs - */ -static inline int crypt_s390_kmctr(long func, void *param, u8 *dest, - const u8 *src, long src_len, u8 *counter) -{ - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; - register long __src_len asm("3") = src_len; - register u8 *__dest asm("4") = dest; - register u8 *__ctr asm("6") = counter; - int ret = -1; - - asm volatile( - "0: .insn rrf,0xb92d0000,%3,%1,%4,0\n" /* KMCTR opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "+d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest), - "+a" (__ctr) - : "d" (__func), "a" (__param) : "cc", "memory"); - if (ret < 0) - return ret; - return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; -} - -/** - * crypt_s390_ppno: - * @func: the function code passed to PPNO; see crypt_s390_ppno_func - * @param: address of parameter block; see POP for details on each func - * @dest: address of destination memory area - * @dest_len: size of destination memory area in bytes - * @seed: address of seed data - * @seed_len: size of seed data in bytes - * - * Executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION) - * operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of random - * bytes stored in dest buffer for generate function - */ -static inline int crypt_s390_ppno(long func, void *param, - u8 *dest, long dest_len, - const u8 *seed, long seed_len) -{ - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; /* param block (240 bytes) */ - register u8 *__dest asm("2") = dest; /* buf for recv random bytes */ - register long __dest_len asm("3") = dest_len; /* requested random bytes */ - register const u8 *__seed asm("4") = seed; /* buf with seed data */ - register long __seed_len asm("5") = seed_len; /* bytes in seed buf */ - int ret = -1; - - asm volatile ( - "0: .insn rre,0xb93c0000,%1,%5\n" /* PPNO opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "+d" (ret), "+a"(__dest), "+d"(__dest_len) - : "d"(__func), "a"(__param), "a"(__seed), "d"(__seed_len) - : "cc", "memory"); - if (ret < 0) - return ret; - return (func & CRYPT_S390_FUNC_MASK) ? dest_len - __dest_len : 0; -} - -/** - * crypt_s390_func_available: - * @func: the function code of the specific function; 0 if op in general - * - * Tests if a specific crypto function is implemented on the machine. - * - * Returns 1 if func available; 0 if func or op in general not available - */ -static inline int crypt_s390_func_available(int func, - unsigned int facility_mask) -{ - unsigned char status[16]; - int ret; - - if (facility_mask & CRYPT_S390_MSA && !test_facility(17)) - return 0; - if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76)) - return 0; - if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77)) - return 0; - if (facility_mask & CRYPT_S390_MSA5 && !test_facility(57)) - return 0; - - switch (func & CRYPT_S390_OP_MASK) { - case CRYPT_S390_KM: - ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); - break; - case CRYPT_S390_KMC: - ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); - break; - case CRYPT_S390_KIMD: - ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); - break; - case CRYPT_S390_KLMD: - ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); - break; - case CRYPT_S390_KMAC: - ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); - break; - case CRYPT_S390_KMCTR: - ret = crypt_s390_kmctr(KMCTR_QUERY, &status, - NULL, NULL, 0, NULL); - break; - case CRYPT_S390_PPNO: - ret = crypt_s390_ppno(PPNO_QUERY, &status, - NULL, 0, NULL, 0); - break; - default: - return 0; - } - if (ret < 0) - return 0; - func &= CRYPT_S390_FUNC_MASK; - func &= 0x7f; /* mask modifier bit */ - return (status[func >> 3] & (0x80 >> (func & 7))) != 0; -} - -/** - * crypt_s390_pcc: - * @func: the function code passed to KM; see crypt_s390_km_func - * @param: address of parameter block; see POP for details on each func - * - * Executes the PCC (PERFORM CRYPTOGRAPHIC COMPUTATION) operation of the CPU. - * - * Returns -1 for failure, 0 for success. - */ -static inline int crypt_s390_pcc(long func, void *param) -{ - register long __func asm("0") = func & 0x7f; /* encrypt or decrypt */ - register void *__param asm("1") = param; - int ret = -1; - - asm volatile( - "0: .insn rre,0xb92c0000,0,0\n" /* PCC opcode */ - "1: brc 1,0b\n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "+d" (ret) - : "d" (__func), "a" (__param) : "cc", "memory"); - return ret; -} - -#endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */ diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index fba1c10a2dd0..697e71a75fc2 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c @@ -20,8 +20,7 @@ #include #include #include - -#include "crypt_s390.h" +#include #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) @@ -54,20 +53,20 @@ static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); - crypt_s390_km(KM_DEA_ENCRYPT, ctx->key, out, in, DES_BLOCK_SIZE); + cpacf_km(CPACF_KM_DEA_ENC, ctx->key, out, in, DES_BLOCK_SIZE); } static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); - crypt_s390_km(KM_DEA_DECRYPT, ctx->key, out, in, DES_BLOCK_SIZE); + cpacf_km(CPACF_KM_DEA_DEC, ctx->key, out, in, DES_BLOCK_SIZE); } static struct crypto_alg des_alg = { .cra_name = "des", .cra_driver_name = "des-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -95,7 +94,7 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, u8 *out = walk->dst.virt.addr; u8 *in = walk->src.virt.addr; - ret = crypt_s390_km(func, key, out, in, n); + ret = cpacf_km(func, key, out, in, n); if (ret < 0 || ret != n) return -EIO; @@ -128,7 +127,7 @@ static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, u8 *out = walk->dst.virt.addr; u8 *in = walk->src.virt.addr; - ret = crypt_s390_kmc(func, ¶m, out, in, n); + ret = cpacf_kmc(func, ¶m, out, in, n); if (ret < 0 || ret != n) return -EIO; @@ -149,7 +148,7 @@ static int ecb_des_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, ctx->key, &walk); + return ecb_desall_crypt(desc, CPACF_KM_DEA_ENC, ctx->key, &walk); } static int ecb_des_decrypt(struct blkcipher_desc *desc, @@ -160,13 +159,13 @@ static int ecb_des_decrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_DEA_DECRYPT, ctx->key, &walk); + return ecb_desall_crypt(desc, CPACF_KM_DEA_DEC, ctx->key, &walk); } static struct crypto_alg ecb_des_alg = { .cra_name = "ecb(des)", .cra_driver_name = "ecb-des-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: des + ecb */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -190,7 +189,7 @@ static int cbc_des_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &walk); + return cbc_desall_crypt(desc, CPACF_KMC_DEA_ENC, &walk); } static int cbc_des_decrypt(struct blkcipher_desc *desc, @@ -200,13 +199,13 @@ static int cbc_des_decrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, &walk); + return cbc_desall_crypt(desc, CPACF_KMC_DEA_DEC, &walk); } static struct crypto_alg cbc_des_alg = { .cra_name = "cbc(des)", .cra_driver_name = "cbc-des-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: des + cbc */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -258,20 +257,20 @@ static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); - crypt_s390_km(KM_TDEA_192_ENCRYPT, ctx->key, dst, src, DES_BLOCK_SIZE); + cpacf_km(CPACF_KM_TDEA_192_ENC, ctx->key, dst, src, DES_BLOCK_SIZE); } static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); - crypt_s390_km(KM_TDEA_192_DECRYPT, ctx->key, dst, src, DES_BLOCK_SIZE); + cpacf_km(CPACF_KM_TDEA_192_DEC, ctx->key, dst, src, DES_BLOCK_SIZE); } static struct crypto_alg des3_alg = { .cra_name = "des3_ede", .cra_driver_name = "des3_ede-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -295,7 +294,7 @@ static int ecb_des3_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, ctx->key, &walk); + return ecb_desall_crypt(desc, CPACF_KM_TDEA_192_ENC, ctx->key, &walk); } static int ecb_des3_decrypt(struct blkcipher_desc *desc, @@ -306,13 +305,13 @@ static int ecb_des3_decrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, ctx->key, &walk); + return ecb_desall_crypt(desc, CPACF_KM_TDEA_192_DEC, ctx->key, &walk); } static struct crypto_alg ecb_des3_alg = { .cra_name = "ecb(des3_ede)", .cra_driver_name = "ecb-des3_ede-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: des3 + ecb */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -336,7 +335,7 @@ static int cbc_des3_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk); + return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192_ENC, &walk); } static int cbc_des3_decrypt(struct blkcipher_desc *desc, @@ -346,13 +345,13 @@ static int cbc_des3_decrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk); + return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192_DEC, &walk); } static struct crypto_alg cbc_des3_alg = { .cra_name = "cbc(des3_ede)", .cra_driver_name = "cbc-des3_ede-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: des3 + cbc */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -407,8 +406,7 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, n = __ctrblk_init(ctrptr, nbytes); else n = DES_BLOCK_SIZE; - ret = crypt_s390_kmctr(func, ctx->key, out, in, - n, ctrptr); + ret = cpacf_kmctr(func, ctx->key, out, in, n, ctrptr); if (ret < 0 || ret != n) { if (ctrptr == ctrblk) spin_unlock(&ctrblk_lock); @@ -438,8 +436,8 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, if (nbytes) { out = walk->dst.virt.addr; in = walk->src.virt.addr; - ret = crypt_s390_kmctr(func, ctx->key, buf, in, - DES_BLOCK_SIZE, ctrbuf); + ret = cpacf_kmctr(func, ctx->key, buf, in, + DES_BLOCK_SIZE, ctrbuf); if (ret < 0 || ret != DES_BLOCK_SIZE) return -EIO; memcpy(out, buf, nbytes); @@ -458,7 +456,7 @@ static int ctr_des_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ctr_desall_crypt(desc, KMCTR_DEA_ENCRYPT, ctx, &walk); + return ctr_desall_crypt(desc, CPACF_KMCTR_DEA_ENC, ctx, &walk); } static int ctr_des_decrypt(struct blkcipher_desc *desc, @@ -469,13 +467,13 @@ static int ctr_des_decrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ctr_desall_crypt(desc, KMCTR_DEA_DECRYPT, ctx, &walk); + return ctr_desall_crypt(desc, CPACF_KMCTR_DEA_DEC, ctx, &walk); } static struct crypto_alg ctr_des_alg = { .cra_name = "ctr(des)", .cra_driver_name = "ctr-des-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: des + ctr */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, .cra_blocksize = 1, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -501,7 +499,7 @@ static int ctr_des3_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ctr_desall_crypt(desc, KMCTR_TDEA_192_ENCRYPT, ctx, &walk); + return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192_ENC, ctx, &walk); } static int ctr_des3_decrypt(struct blkcipher_desc *desc, @@ -512,13 +510,13 @@ static int ctr_des3_decrypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; blkcipher_walk_init(&walk, dst, src, nbytes); - return ctr_desall_crypt(desc, KMCTR_TDEA_192_DECRYPT, ctx, &walk); + return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192_DEC, ctx, &walk); } static struct crypto_alg ctr_des3_alg = { .cra_name = "ctr(des3_ede)", .cra_driver_name = "ctr-des3_ede-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, + .cra_priority = 400, /* combo: des3 + ede */ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, .cra_blocksize = 1, .cra_ctxsize = sizeof(struct s390_des_ctx), @@ -540,8 +538,8 @@ static int __init des_s390_init(void) { int ret; - if (!crypt_s390_func_available(KM_DEA_ENCRYPT, CRYPT_S390_MSA) || - !crypt_s390_func_available(KM_TDEA_192_ENCRYPT, CRYPT_S390_MSA)) + if (!cpacf_query(CPACF_KM, CPACF_KM_DEA_ENC) || + !cpacf_query(CPACF_KM, CPACF_KM_TDEA_192_ENC)) return -EOPNOTSUPP; ret = crypto_register_alg(&des_alg); @@ -563,10 +561,8 @@ static int __init des_s390_init(void) if (ret) goto cbc_des3_err; - if (crypt_s390_func_available(KMCTR_DEA_ENCRYPT, - CRYPT_S390_MSA | CRYPT_S390_MSA4) && - crypt_s390_func_available(KMCTR_TDEA_192_ENCRYPT, - CRYPT_S390_MSA | CRYPT_S390_MSA4)) { + if (cpacf_query(CPACF_KMCTR, CPACF_KMCTR_DEA_ENC) && + cpacf_query(CPACF_KMCTR, CPACF_KMCTR_TDEA_192_ENC)) { ret = crypto_register_alg(&ctr_des_alg); if (ret) goto ctr_des_err; diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c index 26e14efd30a7..ab68de72e795 100644 --- a/arch/s390/crypto/ghash_s390.c +++ b/arch/s390/crypto/ghash_s390.c @@ -10,8 +10,7 @@ #include #include #include - -#include "crypt_s390.h" +#include #define GHASH_BLOCK_SIZE 16 #define GHASH_DIGEST_SIZE 16 @@ -72,8 +71,8 @@ static int ghash_update(struct shash_desc *desc, src += n; if (!dctx->bytes) { - ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, - GHASH_BLOCK_SIZE); + ret = cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf, + GHASH_BLOCK_SIZE); if (ret != GHASH_BLOCK_SIZE) return -EIO; } @@ -81,7 +80,7 @@ static int ghash_update(struct shash_desc *desc, n = srclen & ~(GHASH_BLOCK_SIZE - 1); if (n) { - ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n); + ret = cpacf_kimd(CPACF_KIMD_GHASH, dctx, src, n); if (ret != n) return -EIO; src += n; @@ -106,7 +105,7 @@ static int ghash_flush(struct ghash_desc_ctx *dctx) memset(pos, 0, dctx->bytes); - ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE); + ret = cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE); if (ret != GHASH_BLOCK_SIZE) return -EIO; @@ -137,7 +136,7 @@ static struct shash_alg ghash_alg = { .base = { .cra_name = "ghash", .cra_driver_name = "ghash-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_SHASH, .cra_blocksize = GHASH_BLOCK_SIZE, .cra_ctxsize = sizeof(struct ghash_ctx), @@ -147,8 +146,7 @@ static struct shash_alg ghash_alg = { static int __init ghash_mod_init(void) { - if (!crypt_s390_func_available(KIMD_GHASH, - CRYPT_S390_MSA | CRYPT_S390_MSA4)) + if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_GHASH)) return -EOPNOTSUPP; return crypto_register_shash(&ghash_alg); diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index d750cc0dfe30..41527b113f5a 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c @@ -23,8 +23,7 @@ #include #include #include - -#include "crypt_s390.h" +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("IBM Corporation"); @@ -136,8 +135,8 @@ static int generate_entropy(u8 *ebuf, size_t nbytes) else h = ebuf; /* generate sha256 from this page */ - if (crypt_s390_kimd(KIMD_SHA_256, h, - pg, PAGE_SIZE) != PAGE_SIZE) { + if (cpacf_kimd(CPACF_KIMD_SHA_256, h, + pg, PAGE_SIZE) != PAGE_SIZE) { prng_errorflag = PRNG_GEN_ENTROPY_FAILED; ret = -EIO; goto out; @@ -164,9 +163,9 @@ static void prng_tdes_add_entropy(void) int ret; for (i = 0; i < 16; i++) { - ret = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block, - (char *)entropy, (char *)entropy, - sizeof(entropy)); + ret = cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block, + (char *)entropy, (char *)entropy, + sizeof(entropy)); BUG_ON(ret < 0 || ret != sizeof(entropy)); memcpy(prng_data->prngws.parm_block, entropy, sizeof(entropy)); } @@ -311,9 +310,8 @@ static int __init prng_sha512_selftest(void) memset(&ws, 0, sizeof(ws)); /* initial seed */ - ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED, - &ws, NULL, 0, - seed, sizeof(seed)); + ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED, &ws, NULL, 0, + seed, sizeof(seed)); if (ret < 0) { pr_err("The prng self test seed operation for the " "SHA-512 mode failed with rc=%d\n", ret); @@ -331,18 +329,16 @@ static int __init prng_sha512_selftest(void) } /* generate random bytes */ - ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN, - &ws, buf, sizeof(buf), - NULL, 0); + ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, + &ws, buf, sizeof(buf), NULL, 0); if (ret < 0) { pr_err("The prng self test generate operation for " "the SHA-512 mode failed with rc=%d\n", ret); prng_errorflag = PRNG_SELFTEST_FAILED; return -EIO; } - ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN, - &ws, buf, sizeof(buf), - NULL, 0); + ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, + &ws, buf, sizeof(buf), NULL, 0); if (ret < 0) { pr_err("The prng self test generate operation for " "the SHA-512 mode failed with rc=%d\n", ret); @@ -396,9 +392,8 @@ static int __init prng_sha512_instantiate(void) get_tod_clock_ext(seed + 48); /* initial seed of the ppno drng */ - ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED, - &prng_data->ppnows, NULL, 0, - seed, sizeof(seed)); + ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED, + &prng_data->ppnows, NULL, 0, seed, sizeof(seed)); if (ret < 0) { prng_errorflag = PRNG_SEED_FAILED; ret = -EIO; @@ -409,11 +404,9 @@ static int __init prng_sha512_instantiate(void) bytes for the FIPS 140-2 Conditional Self Test */ if (fips_enabled) { prng_data->prev = prng_data->buf + prng_chunk_size; - ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN, - &prng_data->ppnows, - prng_data->prev, - prng_chunk_size, - NULL, 0); + ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, + &prng_data->ppnows, + prng_data->prev, prng_chunk_size, NULL, 0); if (ret < 0 || ret != prng_chunk_size) { prng_errorflag = PRNG_GEN_FAILED; ret = -EIO; @@ -447,9 +440,8 @@ static int prng_sha512_reseed(void) return ret; /* do a reseed of the ppno drng with this bytestring */ - ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED, - &prng_data->ppnows, NULL, 0, - seed, sizeof(seed)); + ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED, + &prng_data->ppnows, NULL, 0, seed, sizeof(seed)); if (ret) { prng_errorflag = PRNG_RESEED_FAILED; return -EIO; @@ -471,9 +463,8 @@ static int prng_sha512_generate(u8 *buf, size_t nbytes) } /* PPNO generate */ - ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN, - &prng_data->ppnows, buf, nbytes, - NULL, 0); + ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN, + &prng_data->ppnows, buf, nbytes, NULL, 0); if (ret < 0 || ret != nbytes) { prng_errorflag = PRNG_GEN_FAILED; return -EIO; @@ -555,8 +546,8 @@ static ssize_t prng_tdes_read(struct file *file, char __user *ubuf, * Note: you can still get strict X9.17 conformity by setting * prng_chunk_size to 8 bytes. */ - tmp = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block, - prng_data->buf, prng_data->buf, n); + tmp = cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block, + prng_data->buf, prng_data->buf, n); if (tmp < 0 || tmp != n) { ret = -EIO; break; @@ -815,14 +806,13 @@ static int __init prng_init(void) int ret; /* check if the CPU has a PRNG */ - if (!crypt_s390_func_available(KMC_PRNG, CRYPT_S390_MSA)) + if (!cpacf_query(CPACF_KMC, CPACF_KMC_PRNG)) return -EOPNOTSUPP; /* choose prng mode */ if (prng_mode != PRNG_MODE_TDES) { /* check for MSA5 support for PPNO operations */ - if (!crypt_s390_func_available(PPNO_SHA512_DRNG_GEN, - CRYPT_S390_MSA5)) { + if (!cpacf_query(CPACF_PPNO, CPACF_PPNO_SHA512_DRNG_GEN)) { if (prng_mode == PRNG_MODE_SHA512) { pr_err("The prng module cannot " "start in SHA-512 mode\n"); diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c index 9208eadae9f0..5fbf91bbb478 100644 --- a/arch/s390/crypto/sha1_s390.c +++ b/arch/s390/crypto/sha1_s390.c @@ -28,8 +28,8 @@ #include #include #include +#include -#include "crypt_s390.h" #include "sha.h" static int sha1_init(struct shash_desc *desc) @@ -42,7 +42,7 @@ static int sha1_init(struct shash_desc *desc) sctx->state[3] = SHA1_H3; sctx->state[4] = SHA1_H4; sctx->count = 0; - sctx->func = KIMD_SHA_1; + sctx->func = CPACF_KIMD_SHA_1; return 0; } @@ -66,7 +66,7 @@ static int sha1_import(struct shash_desc *desc, const void *in) sctx->count = ictx->count; memcpy(sctx->state, ictx->state, sizeof(ictx->state)); memcpy(sctx->buf, ictx->buffer, sizeof(ictx->buffer)); - sctx->func = KIMD_SHA_1; + sctx->func = CPACF_KIMD_SHA_1; return 0; } @@ -82,7 +82,7 @@ static struct shash_alg alg = { .base = { .cra_name = "sha1", .cra_driver_name= "sha1-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_SHASH, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_module = THIS_MODULE, @@ -91,7 +91,7 @@ static struct shash_alg alg = { static int __init sha1_s390_init(void) { - if (!crypt_s390_func_available(KIMD_SHA_1, CRYPT_S390_MSA)) + if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_SHA_1)) return -EOPNOTSUPP; return crypto_register_shash(&alg); } diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c index 667888f5c964..10aac0b11988 100644 --- a/arch/s390/crypto/sha256_s390.c +++ b/arch/s390/crypto/sha256_s390.c @@ -18,8 +18,8 @@ #include #include #include +#include -#include "crypt_s390.h" #include "sha.h" static int sha256_init(struct shash_desc *desc) @@ -35,7 +35,7 @@ static int sha256_init(struct shash_desc *desc) sctx->state[6] = SHA256_H6; sctx->state[7] = SHA256_H7; sctx->count = 0; - sctx->func = KIMD_SHA_256; + sctx->func = CPACF_KIMD_SHA_256; return 0; } @@ -59,7 +59,7 @@ static int sha256_import(struct shash_desc *desc, const void *in) sctx->count = ictx->count; memcpy(sctx->state, ictx->state, sizeof(ictx->state)); memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); - sctx->func = KIMD_SHA_256; + sctx->func = CPACF_KIMD_SHA_256; return 0; } @@ -75,7 +75,7 @@ static struct shash_alg sha256_alg = { .base = { .cra_name = "sha256", .cra_driver_name= "sha256-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_SHASH, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_module = THIS_MODULE, @@ -95,7 +95,7 @@ static int sha224_init(struct shash_desc *desc) sctx->state[6] = SHA224_H6; sctx->state[7] = SHA224_H7; sctx->count = 0; - sctx->func = KIMD_SHA_256; + sctx->func = CPACF_KIMD_SHA_256; return 0; } @@ -112,7 +112,7 @@ static struct shash_alg sha224_alg = { .base = { .cra_name = "sha224", .cra_driver_name= "sha224-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_SHASH, .cra_blocksize = SHA224_BLOCK_SIZE, .cra_module = THIS_MODULE, @@ -123,7 +123,7 @@ static int __init sha256_s390_init(void) { int ret; - if (!crypt_s390_func_available(KIMD_SHA_256, CRYPT_S390_MSA)) + if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_SHA_256)) return -EOPNOTSUPP; ret = crypto_register_shash(&sha256_alg); if (ret < 0) diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c index 2ba66b1518f0..ea85757be407 100644 --- a/arch/s390/crypto/sha512_s390.c +++ b/arch/s390/crypto/sha512_s390.c @@ -19,9 +19,9 @@ #include #include #include +#include #include "sha.h" -#include "crypt_s390.h" static int sha512_init(struct shash_desc *desc) { @@ -36,7 +36,7 @@ static int sha512_init(struct shash_desc *desc) *(__u64 *)&ctx->state[12] = 0x1f83d9abfb41bd6bULL; *(__u64 *)&ctx->state[14] = 0x5be0cd19137e2179ULL; ctx->count = 0; - ctx->func = KIMD_SHA_512; + ctx->func = CPACF_KIMD_SHA_512; return 0; } @@ -64,7 +64,7 @@ static int sha512_import(struct shash_desc *desc, const void *in) memcpy(sctx->state, ictx->state, sizeof(ictx->state)); memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); - sctx->func = KIMD_SHA_512; + sctx->func = CPACF_KIMD_SHA_512; return 0; } @@ -80,7 +80,7 @@ static struct shash_alg sha512_alg = { .base = { .cra_name = "sha512", .cra_driver_name= "sha512-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_SHASH, .cra_blocksize = SHA512_BLOCK_SIZE, .cra_module = THIS_MODULE, @@ -102,7 +102,7 @@ static int sha384_init(struct shash_desc *desc) *(__u64 *)&ctx->state[12] = 0xdb0c2e0d64f98fa7ULL; *(__u64 *)&ctx->state[14] = 0x47b5481dbefa4fa4ULL; ctx->count = 0; - ctx->func = KIMD_SHA_512; + ctx->func = CPACF_KIMD_SHA_512; return 0; } @@ -119,7 +119,7 @@ static struct shash_alg sha384_alg = { .base = { .cra_name = "sha384", .cra_driver_name= "sha384-s390", - .cra_priority = CRYPT_S390_PRIORITY, + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_SHASH, .cra_blocksize = SHA384_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_sha_ctx), @@ -133,7 +133,7 @@ static int __init init(void) { int ret; - if (!crypt_s390_func_available(KIMD_SHA_512, CRYPT_S390_MSA)) + if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_SHA_512)) return -EOPNOTSUPP; if ((ret = crypto_register_shash(&sha512_alg)) < 0) goto out; diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c index 8620b0ec9c42..8e908166c3ee 100644 --- a/arch/s390/crypto/sha_common.c +++ b/arch/s390/crypto/sha_common.c @@ -15,8 +15,8 @@ #include #include +#include #include "sha.h" -#include "crypt_s390.h" int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) { @@ -35,7 +35,7 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) /* process one stored block */ if (index) { memcpy(ctx->buf + index, data, bsize - index); - ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, bsize); + ret = cpacf_kimd(ctx->func, ctx->state, ctx->buf, bsize); if (ret != bsize) return -EIO; data += bsize - index; @@ -45,8 +45,8 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) /* process as many blocks as possible */ if (len >= bsize) { - ret = crypt_s390_kimd(ctx->func, ctx->state, data, - len & ~(bsize - 1)); + ret = cpacf_kimd(ctx->func, ctx->state, data, + len & ~(bsize - 1)); if (ret != (len & ~(bsize - 1))) return -EIO; data += ret; @@ -89,7 +89,7 @@ int s390_sha_final(struct shash_desc *desc, u8 *out) bits = ctx->count * 8; memcpy(ctx->buf + end - 8, &bits, sizeof(bits)); - ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, end); + ret = cpacf_kimd(ctx->func, ctx->state, ctx->buf, end); if (ret != end) return -EIO; diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h new file mode 100644 index 000000000000..1a82cf26ee11 --- /dev/null +++ b/arch/s390/include/asm/cpacf.h @@ -0,0 +1,410 @@ +/* + * CP Assist for Cryptographic Functions (CPACF) + * + * Copyright IBM Corp. 2003, 2016 + * Author(s): Thomas Spatzier + * Jan Glauber + * Harald Freudenberger (freude@de.ibm.com) + * Martin Schwidefsky + */ +#ifndef _ASM_S390_CPACF_H +#define _ASM_S390_CPACF_H + +#include + +/* + * Instruction opcodes for the CPACF instructions + */ +#define CPACF_KMAC 0xb91e /* MSA */ +#define CPACF_KM 0xb92e /* MSA */ +#define CPACF_KMC 0xb92f /* MSA */ +#define CPACF_KIMD 0xb93e /* MSA */ +#define CPACF_KLMD 0xb93f /* MSA */ +#define CPACF_PCC 0xb92c /* MSA4 */ +#define CPACF_KMCTR 0xb92d /* MSA4 */ +#define CPACF_PPNO 0xb93c /* MSA5 */ + +/* + * Function codes for the KM (CIPHER MESSAGE) + * instruction (0x80 is the decipher modifier bit) + */ +#define CPACF_KM_QUERY 0x00 +#define CPACF_KM_DEA_ENC 0x01 +#define CPACF_KM_DEA_DEC 0x81 +#define CPACF_KM_TDEA_128_ENC 0x02 +#define CPACF_KM_TDEA_128_DEC 0x82 +#define CPACF_KM_TDEA_192_ENC 0x03 +#define CPACF_KM_TDEA_192_DEC 0x83 +#define CPACF_KM_AES_128_ENC 0x12 +#define CPACF_KM_AES_128_DEC 0x92 +#define CPACF_KM_AES_192_ENC 0x13 +#define CPACF_KM_AES_192_DEC 0x93 +#define CPACF_KM_AES_256_ENC 0x14 +#define CPACF_KM_AES_256_DEC 0x94 +#define CPACF_KM_XTS_128_ENC 0x32 +#define CPACF_KM_XTS_128_DEC 0xb2 +#define CPACF_KM_XTS_256_ENC 0x34 +#define CPACF_KM_XTS_256_DEC 0xb4 + +/* + * Function codes for the KMC (CIPHER MESSAGE WITH CHAINING) + * instruction (0x80 is the decipher modifier bit) + */ +#define CPACF_KMC_QUERY 0x00 +#define CPACF_KMC_DEA_ENC 0x01 +#define CPACF_KMC_DEA_DEC 0x81 +#define CPACF_KMC_TDEA_128_ENC 0x02 +#define CPACF_KMC_TDEA_128_DEC 0x82 +#define CPACF_KMC_TDEA_192_ENC 0x03 +#define CPACF_KMC_TDEA_192_DEC 0x83 +#define CPACF_KMC_AES_128_ENC 0x12 +#define CPACF_KMC_AES_128_DEC 0x92 +#define CPACF_KMC_AES_192_ENC 0x13 +#define CPACF_KMC_AES_192_DEC 0x93 +#define CPACF_KMC_AES_256_ENC 0x14 +#define CPACF_KMC_AES_256_DEC 0x94 +#define CPACF_KMC_PRNG 0x43 + +/* + * Function codes for the KMCTR (CIPHER MESSAGE WITH COUNTER) + * instruction (0x80 is the decipher modifier bit) + */ +#define CPACF_KMCTR_QUERY 0x00 +#define CPACF_KMCTR_DEA_ENC 0x01 +#define CPACF_KMCTR_DEA_DEC 0x81 +#define CPACF_KMCTR_TDEA_128_ENC 0x02 +#define CPACF_KMCTR_TDEA_128_DEC 0x82 +#define CPACF_KMCTR_TDEA_192_ENC 0x03 +#define CPACF_KMCTR_TDEA_192_DEC 0x83 +#define CPACF_KMCTR_AES_128_ENC 0x12 +#define CPACF_KMCTR_AES_128_DEC 0x92 +#define CPACF_KMCTR_AES_192_ENC 0x13 +#define CPACF_KMCTR_AES_192_DEC 0x93 +#define CPACF_KMCTR_AES_256_ENC 0x14 +#define CPACF_KMCTR_AES_256_DEC 0x94 + +/* + * Function codes for the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) + * instruction (0x80 is the decipher modifier bit) + */ +#define CPACF_KIMD_QUERY 0x00 +#define CPACF_KIMD_SHA_1 0x01 +#define CPACF_KIMD_SHA_256 0x02 +#define CPACF_KIMD_SHA_512 0x03 +#define CPACF_KIMD_GHASH 0x41 + +/* + * Function codes for the KLMD (COMPUTE LAST MESSAGE DIGEST) + * instruction (0x80 is the decipher modifier bit) + */ +#define CPACF_KLMD_QUERY 0x00 +#define CPACF_KLMD_SHA_1 0x01 +#define CPACF_KLMD_SHA_256 0x02 +#define CPACF_KLMD_SHA_512 0x03 + +/* + * function codes for the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) + * instruction (0x80 is the decipher modifier bit) + */ +#define CPACF_KMAC_QUERY 0x00 +#define CPACF_KMAC_DEA 0x01 +#define CPACF_KMAC_TDEA_128 0x02 +#define CPACF_KMAC_TDEA_192 0x03 + +/* + * Function codes for the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION) + * instruction (0x80 is the decipher modifier bit) + */ +#define CPACF_PPNO_QUERY 0x00 +#define CPACF_PPNO_SHA512_DRNG_GEN 0x03 +#define CPACF_PPNO_SHA512_DRNG_SEED 0x83 + +/** + * cpacf_query() - check if a specific CPACF function is available + * @opcode: the opcode of the crypto instruction + * @func: the function code to test for + * + * Executes the query function for the given crypto instruction @opcode + * and checks if @func is available + * + * Returns 1 if @func is available for @opcode, 0 otherwise + */ +static inline void __cpacf_query(unsigned int opcode, unsigned char *status) +{ + typedef struct { unsigned char _[16]; } status_type; + register unsigned long r0 asm("0") = 0; /* query function */ + register unsigned long r1 asm("1") = (unsigned long) status; + + asm volatile( + /* Parameter registers are ignored, but may not be 0 */ + "0: .insn rrf,%[opc] << 16,2,2,2,0\n" + " brc 1,0b\n" /* handle partial completion */ + : "=m" (*(status_type *) status) + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (opcode) + : "cc"); +} + +static inline int cpacf_query(unsigned int opcode, unsigned int func) +{ + unsigned char status[16]; + + switch (opcode) { + case CPACF_KMAC: + case CPACF_KM: + case CPACF_KMC: + case CPACF_KIMD: + case CPACF_KLMD: + if (!test_facility(17)) /* check for MSA */ + return 0; + break; + case CPACF_PCC: + case CPACF_KMCTR: + if (!test_facility(77)) /* check for MSA4 */ + return 0; + break; + case CPACF_PPNO: + if (!test_facility(57)) /* check for MSA5 */ + return 0; + break; + default: + BUG(); + } + __cpacf_query(opcode, status); + return (status[func >> 3] & (0x80 >> (func & 7))) != 0; +} + +/** + * cpacf_km() - executes the KM (CIPHER MESSAGE) instruction + * @func: the function code passed to KM; see CPACF_KM_xxx defines + * @param: address of parameter block; see POP for details on each func + * @dest: address of destination memory area + * @src: address of source memory area + * @src_len: length of src operand in bytes + * + * Returns 0 for the query func, number of processed bytes for + * encryption/decryption funcs + */ +static inline int cpacf_km(long func, void *param, + u8 *dest, const u8 *src, long src_len) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + register unsigned long r2 asm("2") = (unsigned long) src; + register unsigned long r3 asm("3") = (unsigned long) src_len; + register unsigned long r4 asm("4") = (unsigned long) dest; + + asm volatile( + "0: .insn rre,%[opc] << 16,%[dst],%[src]\n" + " brc 1,0b\n" /* handle partial completion */ + : [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4) + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KM) + : "cc", "memory"); + + return src_len - r3; +} + +/** + * cpacf_kmc() - executes the KMC (CIPHER MESSAGE WITH CHAINING) instruction + * @func: the function code passed to KM; see CPACF_KMC_xxx defines + * @param: address of parameter block; see POP for details on each func + * @dest: address of destination memory area + * @src: address of source memory area + * @src_len: length of src operand in bytes + * + * Returns 0 for the query func, number of processed bytes for + * encryption/decryption funcs + */ +static inline int cpacf_kmc(long func, void *param, + u8 *dest, const u8 *src, long src_len) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + register unsigned long r2 asm("2") = (unsigned long) src; + register unsigned long r3 asm("3") = (unsigned long) src_len; + register unsigned long r4 asm("4") = (unsigned long) dest; + + asm volatile( + "0: .insn rre,%[opc] << 16,%[dst],%[src]\n" + " brc 1,0b\n" /* handle partial completion */ + : [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4) + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMC) + : "cc", "memory"); + + return src_len - r3; +} + +/** + * cpacf_kimd() - executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) + * instruction + * @func: the function code passed to KM; see CPACF_KIMD_xxx defines + * @param: address of parameter block; see POP for details on each func + * @src: address of source memory area + * @src_len: length of src operand in bytes + * + * Returns 0 for the query func, number of processed bytes for digest funcs + */ +static inline int cpacf_kimd(long func, void *param, + const u8 *src, long src_len) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + register unsigned long r2 asm("2") = (unsigned long) src; + register unsigned long r3 asm("3") = (unsigned long) src_len; + + asm volatile( + "0: .insn rre,%[opc] << 16,0,%[src]\n" + " brc 1,0b\n" /* handle partial completion */ + : [src] "+a" (r2), [len] "+d" (r3) + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KIMD) + : "cc", "memory"); + + return src_len - r3; +} + +/** + * cpacf_klmd() - executes the KLMD (COMPUTE LAST MESSAGE DIGEST) instruction + * @func: the function code passed to KM; see CPACF_KLMD_xxx defines + * @param: address of parameter block; see POP for details on each func + * @src: address of source memory area + * @src_len: length of src operand in bytes + * + * Returns 0 for the query func, number of processed bytes for digest funcs + */ +static inline int cpacf_klmd(long func, void *param, + const u8 *src, long src_len) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + register unsigned long r2 asm("2") = (unsigned long) src; + register unsigned long r3 asm("3") = (unsigned long) src_len; + + asm volatile( + "0: .insn rre,%[opc] << 16,0,%[src]\n" + " brc 1,0b\n" /* handle partial completion */ + : [src] "+a" (r2), [len] "+d" (r3) + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KLMD) + : "cc", "memory"); + + return src_len - r3; +} + +/** + * cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) + * instruction + * @func: the function code passed to KM; see CPACF_KMAC_xxx defines + * @param: address of parameter block; see POP for details on each func + * @src: address of source memory area + * @src_len: length of src operand in bytes + * + * Returns 0 for the query func, number of processed bytes for digest funcs + */ +static inline int cpacf_kmac(long func, void *param, + const u8 *src, long src_len) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + register unsigned long r2 asm("2") = (unsigned long) src; + register unsigned long r3 asm("3") = (unsigned long) src_len; + + asm volatile( + "0: .insn rre,%[opc] << 16,0,%[src]\n" + " brc 1,0b\n" /* handle partial completion */ + : [src] "+a" (r2), [len] "+d" (r3) + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMAC) + : "cc", "memory"); + + return src_len - r3; +} + +/** + * cpacf_kmctr() - executes the KMCTR (CIPHER MESSAGE WITH COUNTER) instruction + * @func: the function code passed to KMCTR; see CPACF_KMCTR_xxx defines + * @param: address of parameter block; see POP for details on each func + * @dest: address of destination memory area + * @src: address of source memory area + * @src_len: length of src operand in bytes + * @counter: address of counter value + * + * Returns 0 for the query func, number of processed bytes for + * encryption/decryption funcs + */ +static inline int cpacf_kmctr(long func, void *param, u8 *dest, + const u8 *src, long src_len, u8 *counter) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + register unsigned long r2 asm("2") = (unsigned long) src; + register unsigned long r3 asm("3") = (unsigned long) src_len; + register unsigned long r4 asm("4") = (unsigned long) dest; + register unsigned long r6 asm("6") = (unsigned long) counter; + + asm volatile( + "0: .insn rrf,%[opc] << 16,%[dst],%[src],%[ctr],0\n" + " brc 1,0b\n" /* handle partial completion */ + : [src] "+a" (r2), [len] "+d" (r3), + [dst] "+a" (r4), [ctr] "+a" (r6) + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMCTR) + : "cc", "memory"); + + return src_len - r3; +} + +/** + * cpacf_ppno() - executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION) + * instruction + * @func: the function code passed to PPNO; see CPACF_PPNO_xxx defines + * @param: address of parameter block; see POP for details on each func + * @dest: address of destination memory area + * @dest_len: size of destination memory area in bytes + * @seed: address of seed data + * @seed_len: size of seed data in bytes + * + * Returns 0 for the query func, number of random bytes stored in + * dest buffer for generate function + */ +static inline int cpacf_ppno(long func, void *param, + u8 *dest, long dest_len, + const u8 *seed, long seed_len) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + register unsigned long r2 asm("2") = (unsigned long) dest; + register unsigned long r3 asm("3") = (unsigned long) dest_len; + register unsigned long r4 asm("4") = (unsigned long) seed; + register unsigned long r5 asm("5") = (unsigned long) seed_len; + + asm volatile ( + "0: .insn rre,%[opc] << 16,%[dst],%[seed]\n" + " brc 1,0b\n" /* handle partial completion */ + : [dst] "+a" (r2), [dlen] "+d" (r3) + : [fc] "d" (r0), [pba] "a" (r1), + [seed] "a" (r4), [slen] "d" (r5), [opc] "i" (CPACF_PPNO) + : "cc", "memory"); + + return dest_len - r3; +} + +/** + * cpacf_pcc() - executes the PCC (PERFORM CRYPTOGRAPHIC COMPUTATION) + * instruction + * @func: the function code passed to PCC; see CPACF_KM_xxx defines + * @param: address of parameter block; see POP for details on each func + * + * Returns 0. + */ +static inline int cpacf_pcc(long func, void *param) +{ + register unsigned long r0 asm("0") = (unsigned long) func; + register unsigned long r1 asm("1") = (unsigned long) param; + + asm volatile( + "0: .insn rre,%[opc] << 16,0,0\n" /* PCC opcode */ + " brc 1,0b\n" /* handle partial completion */ + : + : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_PCC) + : "cc", "memory"); + + return 0; +} + +#endif /* _ASM_S390_CPACF_H */ -- GitLab From de33efd0fb7f923cd41671b1f743c3a0d44dd953 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 15 Apr 2016 09:17:08 +0200 Subject: [PATCH 2954/9938] devlink: fix sb register stub in case devlink is disabled Reported-by: kbuild test robot Fixes: bf7974710a40 ("devlink: add shared buffer configuration") Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- include/net/devlink.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/net/devlink.h b/include/net/devlink.h index be64218e0254..1d45b61cb320 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -184,7 +184,9 @@ static inline void devlink_port_split_set(struct devlink_port *devlink_port, static inline int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, u32 size, u16 ingress_pools_count, - u16 egress_pools_count, u16 tc_count) + u16 egress_pools_count, + u16 ingress_tc_count, + u16 egress_tc_count) { return 0; } -- GitLab From ce78f020429c649b206e2fd7d44411fbc1ec920e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 15 Apr 2016 15:09:37 +0200 Subject: [PATCH 2955/9938] mlxsw: spectrum_buffers: Use designated initializers for mlxsw_sp_pbs Suggested-by: David Laight Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index f2e073af5dd2..64166dd67e6f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -162,16 +162,8 @@ static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port, } static const u16 mlxsw_sp_pbs[] = { - 2 * MLXSW_SP_BYTES_TO_CELLS(ETH_FRAME_LEN), - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* Unused */ - 2 * MLXSW_SP_BYTES_TO_CELLS(MLXSW_PORT_MAX_MTU), + [0] = 2 * MLXSW_SP_BYTES_TO_CELLS(ETH_FRAME_LEN), + [9] = 2 * MLXSW_SP_BYTES_TO_CELLS(MLXSW_PORT_MAX_MTU), }; #define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs) -- GitLab From b94cdabbf174a197020632748339392b494494e5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 15 Apr 2016 15:09:38 +0200 Subject: [PATCH 2956/9938] mlxsw: spectrum_buffers: Use MLXSW_SP_PB_UNUSED define for unused pb Suggested-by: David Laight Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 64166dd67e6f..a3720a0fad7d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -167,6 +167,7 @@ static const u16 mlxsw_sp_pbs[] = { }; #define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs) +#define MLXSW_SP_PB_UNUSED 8 static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) { @@ -176,7 +177,7 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0xffff, 0xffff / 2); for (i = 0; i < MLXSW_SP_PBS_LEN; i++) { - if (i == 8) + if (i == MLXSW_SP_PB_UNUSED) continue; mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, mlxsw_sp_pbs[i]); } -- GitLab From 83835fb07836eac1b35e98b919bf757ff7f77aad Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Fri, 15 Apr 2016 15:10:52 +0300 Subject: [PATCH 2957/9938] spi: dln2: Pass of_node to spi master This allows defining SPI devices connected to a DLN2 using devicetree. This already works for i2c because of a similar patch: 3b10db23: i2c: dln2: set the device tree node of the adapter Signed-off-by: Crestez Dan Leonard Acked-by: Laurentiu Palcu Signed-off-by: Mark Brown --- drivers/spi/spi-dln2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index 3b7d91d94fea..4e8a8629d514 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -683,6 +683,7 @@ static int dln2_spi_probe(struct platform_device *pdev) struct spi_master *master; struct dln2_spi *dln2; struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct device *dev = &pdev->dev; int ret; master = spi_alloc_master(&pdev->dev, sizeof(*dln2)); @@ -700,6 +701,8 @@ static int dln2_spi_probe(struct platform_device *pdev) } dln2->master = master; + dln2->master->dev.parent = dev; + dln2->master->dev.of_node = dev->of_node; dln2->pdev = pdev; dln2->port = pdata->port; /* cs/mode can never be 0xff, so the first transfer will set them */ -- GitLab From 17eebd1a435c8616c47b715e3447f4a9c15b741f Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 12 Apr 2016 15:46:00 +0100 Subject: [PATCH 2958/9938] arm64: Add cpu_panic_kernel helper During the activation of a secondary CPU, we could report serious configuration issues and hence request to crash the kernel. We do this for CPU ASID bit check now. We will need it also for handling mismatched exception levels for the CPUs with VHE. Hence, add a helper to do the same for reusability. Cc: Mark Rutland Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/include/asm/smp.h | 11 +++++++++++ arch/arm64/mm/context.c | 3 +-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index 817a067ba058..433e50405274 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -113,6 +113,17 @@ static inline void update_cpu_boot_status(int val) dsb(ishst); } +/* + * The calling secondary CPU has detected serious configuration mismatch, + * which calls for a kernel panic. Update the boot status and park the calling + * CPU. + */ +static inline void cpu_panic_kernel(void) +{ + update_cpu_boot_status(CPU_PANIC_KERNEL); + cpu_park_loop(); +} + #endif /* ifndef __ASSEMBLY__ */ #endif /* ifndef __ASM_SMP_H */ diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index c90c3c5f46af..b7b397802088 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -75,8 +75,7 @@ void verify_cpu_asid_bits(void) */ pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n", smp_processor_id(), asid, asid_bits); - update_cpu_boot_status(CPU_PANIC_KERNEL); - cpu_park_loop(); + cpu_panic_kernel(); } } -- GitLab From ac1ad20f9ed73a22b0a72eb83206302f5fbff55c Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 13 Apr 2016 14:41:33 +0100 Subject: [PATCH 2959/9938] arm64: vhe: Verify CPU Exception Levels With a VHE capable CPU, kernel can run at EL2 and is a decided at early boot. If some of the CPUs didn't start it EL2 or doesn't have VHE, we could have CPUs running at different exception levels, all in the same kernel! This patch adds an early check for the secondary CPUs to detect such situations. For each non-boot CPU add a sanity check to make sure we don't have different run levels w.r.t the boot CPU. We save the information on whether the boot CPU is running in hyp mode or not and ensure the remaining CPUs match it. Cc: Marc Zyngier Cc: Will Deacon Cc: Mark Rutland Cc: Catalin Marinas Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose [will: made boot_cpu_hyp_mode static] Signed-off-by: Will Deacon --- arch/arm64/include/asm/virt.h | 6 ++++++ arch/arm64/kernel/cpufeature.c | 1 + arch/arm64/kernel/smp.c | 38 ++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h index 9f22dd607958..a5c2b4852154 100644 --- a/arch/arm64/include/asm/virt.h +++ b/arch/arm64/include/asm/virt.h @@ -60,6 +60,12 @@ static inline bool is_kernel_in_hyp_mode(void) return el == CurrentEL_EL2; } +#ifdef CONFIG_ARM64_VHE +extern void verify_cpu_run_el(void); +#else +static inline void verify_cpu_run_el(void) {} +#endif + /* The section containing the hypervisor text */ extern char __hyp_text_start[]; extern char __hyp_text_end[]; diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 677f17cd05d1..f586343723fb 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -912,6 +912,7 @@ static u64 __raw_read_system_reg(u32 sys_id) */ static void check_early_cpu_features(void) { + verify_cpu_run_el(); verify_cpu_asid_bits(); } diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index b2d5f4ee9a1c..5fbab1c40424 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -75,6 +75,43 @@ enum ipi_msg_type { IPI_WAKEUP }; +#ifdef CONFIG_ARM64_VHE + +/* Whether the boot CPU is running in HYP mode or not*/ +static bool boot_cpu_hyp_mode; + +static inline void save_boot_cpu_run_el(void) +{ + boot_cpu_hyp_mode = is_kernel_in_hyp_mode(); +} + +static inline bool is_boot_cpu_in_hyp_mode(void) +{ + return boot_cpu_hyp_mode; +} + +/* + * Verify that a secondary CPU is running the kernel at the same + * EL as that of the boot CPU. + */ +void verify_cpu_run_el(void) +{ + bool in_el2 = is_kernel_in_hyp_mode(); + bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode(); + + if (in_el2 ^ boot_cpu_el2) { + pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n", + smp_processor_id(), + in_el2 ? 2 : 1, + boot_cpu_el2 ? 2 : 1); + cpu_panic_kernel(); + } +} + +#else +static inline void save_boot_cpu_run_el(void) {} +#endif + #ifdef CONFIG_HOTPLUG_CPU static int op_cpu_kill(unsigned int cpu); #else @@ -401,6 +438,7 @@ void __init smp_cpus_done(unsigned int max_cpus) void __init smp_prepare_boot_cpu(void) { cpuinfo_store_boot_cpu(); + save_boot_cpu_run_el(); set_my_cpu_offset(per_cpu_offset(smp_processor_id())); } -- GitLab From 500899c2cc3e3f06140373b587a69d30650f2d9d Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 8 Apr 2016 15:50:23 -0700 Subject: [PATCH 2960/9938] efi: ARM/arm64: ignore DT memory nodes instead of removing them There are two problems with the UEFI stub DT memory node removal routine: - it deletes nodes as it traverses the tree, which happens to work but is not supported, as deletion invalidates the node iterator; - deleting memory nodes entirely may discard annotations in the form of additional properties on the nodes. Since the discovery of DT memory nodes occurs strictly before the UEFI init sequence, we can simply clear the memblock memory table before parsing the UEFI memory map. This way, it is no longer necessary to remove the nodes, so we can remove that logic from the stub as well. Reviewed-by: Matt Fleming Acked-by: Steve Capper Signed-off-by: Ard Biesheuvel Signed-off-by: David Daney Signed-off-by: Will Deacon --- drivers/firmware/efi/arm-init.c | 8 ++++++++ drivers/firmware/efi/libstub/fdt.c | 24 +----------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index aa1f743152a2..5d6945b761dc 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -143,6 +143,14 @@ static __init void reserve_regions(void) if (efi_enabled(EFI_DBG)) pr_info("Processing EFI memory map:\n"); + /* + * Discard memblocks discovered so far: if there are any at this + * point, they originate from memory nodes in the DT, and UEFI + * uses its own memory map instead. + */ + memblock_dump_all(); + memblock_remove(0, ULLONG_MAX); + for_each_efi_memory_desc(&memmap, md) { paddr = md->phys_addr; npages = md->num_pages; diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 6dba78aef337..e58abfa953cc 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -24,7 +24,7 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, unsigned long map_size, unsigned long desc_size, u32 desc_ver) { - int node, prev, num_rsv; + int node, num_rsv; int status; u32 fdt_val32; u64 fdt_val64; @@ -53,28 +53,6 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, if (status != 0) goto fdt_set_fail; - /* - * Delete any memory nodes present. We must delete nodes which - * early_init_dt_scan_memory may try to use. - */ - prev = 0; - for (;;) { - const char *type; - int len; - - node = fdt_next_node(fdt, prev, NULL); - if (node < 0) - break; - - type = fdt_getprop(fdt, node, "device_type", &len); - if (type && strncmp(type, "memory", len) == 0) { - fdt_del_node(fdt, node); - continue; - } - - prev = node; - } - /* * Delete all memory reserve map entries. When booting via UEFI, * kernel will use the UEFI memory map to find reserved regions. -- GitLab From 2bc4da1d2b4d828cb4e3a5593967556b1bd78898 Mon Sep 17 00:00:00 2001 From: Ganapatrao Kulkarni Date: Fri, 8 Apr 2016 15:50:24 -0700 Subject: [PATCH 2961/9938] Documentation, dt, numa: dt bindings for NUMA. Add DT bindings for numa mapping of memory, CPUs and IOs. Reviewed-by: Robert Richter Signed-off-by: Ganapatrao Kulkarni Signed-off-by: David Daney Acked-by: Rob Herring Signed-off-by: Will Deacon --- Documentation/devicetree/bindings/numa.txt | 275 +++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 Documentation/devicetree/bindings/numa.txt diff --git a/Documentation/devicetree/bindings/numa.txt b/Documentation/devicetree/bindings/numa.txt new file mode 100644 index 000000000000..21b35053ca5a --- /dev/null +++ b/Documentation/devicetree/bindings/numa.txt @@ -0,0 +1,275 @@ +============================================================================== +NUMA binding description. +============================================================================== + +============================================================================== +1 - Introduction +============================================================================== + +Systems employing a Non Uniform Memory Access (NUMA) architecture contain +collections of hardware resources including processors, memory, and I/O buses, +that comprise what is commonly known as a NUMA node. +Processor accesses to memory within the local NUMA node is generally faster +than processor accesses to memory outside of the local NUMA node. +DT defines interfaces that allow the platform to convey NUMA node +topology information to OS. + +============================================================================== +2 - numa-node-id +============================================================================== + +For the purpose of identification, each NUMA node is associated with a unique +token known as a node id. For the purpose of this binding +a node id is a 32-bit integer. + +A device node is associated with a NUMA node by the presence of a +numa-node-id property which contains the node id of the device. + +Example: + /* numa node 0 */ + numa-node-id = <0>; + + /* numa node 1 */ + numa-node-id = <1>; + +============================================================================== +3 - distance-map +============================================================================== + +The optional device tree node distance-map describes the relative +distance (memory latency) between all numa nodes. + +- compatible : Should at least contain "numa-distance-map-v1". + +- distance-matrix + This property defines a matrix to describe the relative distances + between all numa nodes. + It is represented as a list of node pairs and their relative distance. + + Note: + 1. Each entry represents distance from first node to second node. + The distances are equal in either direction. + 2. The distance from a node to self (local distance) is represented + with value 10 and all internode distance should be represented with + a value greater than 10. + 3. distance-matrix should have entries in lexicographical ascending + order of nodes. + 4. There must be only one device node distance-map which must + reside in the root node. + 5. If the distance-map node is not present, a default + distance-matrix is used. + +Example: + 4 nodes connected in mesh/ring topology as below, + + 0_______20______1 + | | + | | + 20 20 + | | + | | + |_______________| + 3 20 2 + + if relative distance for each hop is 20, + then internode distance would be, + 0 -> 1 = 20 + 1 -> 2 = 20 + 2 -> 3 = 20 + 3 -> 0 = 20 + 0 -> 2 = 40 + 1 -> 3 = 40 + + and dt presentation for this distance matrix is, + + distance-map { + compatible = "numa-distance-map-v1"; + distance-matrix = <0 0 10>, + <0 1 20>, + <0 2 40>, + <0 3 20>, + <1 0 20>, + <1 1 10>, + <1 2 20>, + <1 3 40>, + <2 0 40>, + <2 1 20>, + <2 2 10>, + <2 3 20>, + <3 0 20>, + <3 1 40>, + <3 2 20>, + <3 3 10>; + }; + +============================================================================== +4 - Example dts +============================================================================== + +Dual socket system consists of 2 boards connected through ccn bus and +each board having one socket/soc of 8 cpus, memory and pci bus. + + memory@c00000 { + device_type = "memory"; + reg = <0x0 0xc00000 0x0 0x80000000>; + /* node 0 */ + numa-node-id = <0>; + }; + + memory@10000000000 { + device_type = "memory"; + reg = <0x100 0x0 0x0 0x80000000>; + /* node 1 */ + numa-node-id = <1>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + /* node 0 */ + numa-node-id = <0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu@4 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x4>; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu@5 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x5>; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu@6 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x6>; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu@7 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x7>; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu@8 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x8>; + enable-method = "psci"; + /* node 1 */ + numa-node-id = <1>; + }; + cpu@9 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x9>; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu@a { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0xa>; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu@b { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0xb>; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu@c { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0xc>; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu@d { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0xd>; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu@e { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0xe>; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu@f { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0xf>; + enable-method = "psci"; + numa-node-id = <1>; + }; + }; + + pcie0: pcie0@848000000000 { + compatible = "arm,armv8"; + device_type = "pci"; + bus-range = <0 255>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0x8480 0x00000000 0 0x10000000>; /* Configuration space */ + ranges = <0x03000000 0x8010 0x00000000 0x8010 0x00000000 0x70 0x00000000>; + /* node 0 */ + numa-node-id = <0>; + }; + + pcie1: pcie1@948000000000 { + compatible = "arm,armv8"; + device_type = "pci"; + bus-range = <0 255>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0x9480 0x00000000 0 0x10000000>; /* Configuration space */ + ranges = <0x03000000 0x9010 0x00000000 0x9010 0x00000000 0x70 0x00000000>; + /* node 1 */ + numa-node-id = <1>; + }; + + distance-map { + compatible = "numa-distance-map-v1"; + distance-matrix = <0 0 10>, + <0 1 20>, + <1 1 10>; + }; -- GitLab From 298535c00a2cbcd59e38f8f1c0c9ae7b9911e946 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 8 Apr 2016 15:50:25 -0700 Subject: [PATCH 2962/9938] of, numa: Add NUMA of binding implementation. Add device tree parsing for NUMA topology using device "numa-node-id" property in distance-map and cpu nodes. This is a complete rewrite of a previous patch by: Ganapatrao Kulkarni Signed-off-by: David Daney Acked-by: Rob Herring Signed-off-by: Will Deacon --- drivers/of/Kconfig | 3 + drivers/of/Makefile | 1 + drivers/of/of_numa.c | 211 +++++++++++++++++++++++++++++++++++++++++++ include/linux/of.h | 9 ++ 4 files changed, 224 insertions(+) create mode 100644 drivers/of/of_numa.c diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index e2a48415d969..b3bec3aaa45d 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -112,4 +112,7 @@ config OF_OVERLAY While this option is selected automatically when needed, you can enable it manually to improve device tree unit test coverage. +config OF_NUMA + bool + endif # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 156c072b3117..bee3fa96b981 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -14,5 +14,6 @@ obj-$(CONFIG_OF_MTD) += of_mtd.o obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o obj-$(CONFIG_OF_RESOLVE) += resolver.o obj-$(CONFIG_OF_OVERLAY) += overlay.o +obj-$(CONFIG_OF_NUMA) += of_numa.o obj-$(CONFIG_OF_UNITTEST) += unittest-data/ diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c new file mode 100644 index 000000000000..0f2784bc1874 --- /dev/null +++ b/drivers/of/of_numa.c @@ -0,0 +1,211 @@ +/* + * OF NUMA Parsing support. + * + * Copyright (C) 2015 - 2016 Cavium Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include + +/* define default numa node to 0 */ +#define DEFAULT_NODE 0 + +/* + * Even though we connect cpus to numa domains later in SMP + * init, we need to know the node ids now for all cpus. +*/ +static void __init of_numa_parse_cpu_nodes(void) +{ + u32 nid; + int r; + struct device_node *cpus; + struct device_node *np = NULL; + + cpus = of_find_node_by_path("/cpus"); + if (!cpus) + return; + + for_each_child_of_node(cpus, np) { + /* Skip things that are not CPUs */ + if (of_node_cmp(np->type, "cpu") != 0) + continue; + + r = of_property_read_u32(np, "numa-node-id", &nid); + if (r) + continue; + + pr_debug("NUMA: CPU on %u\n", nid); + if (nid >= MAX_NUMNODES) + pr_warn("NUMA: Node id %u exceeds maximum value\n", + nid); + else + node_set(nid, numa_nodes_parsed); + } +} + +static int __init of_numa_parse_memory_nodes(void) +{ + struct device_node *np = NULL; + struct resource rsrc; + u32 nid; + int r = 0; + + for (;;) { + np = of_find_node_by_type(np, "memory"); + if (!np) + break; + + r = of_property_read_u32(np, "numa-node-id", &nid); + if (r == -EINVAL) + /* + * property doesn't exist if -EINVAL, continue + * looking for more memory nodes with + * "numa-node-id" property + */ + continue; + else if (r) + /* some other error */ + break; + + r = of_address_to_resource(np, 0, &rsrc); + if (r) { + pr_err("NUMA: bad reg property in memory node\n"); + break; + } + + pr_debug("NUMA: base = %llx len = %llx, node = %u\n", + rsrc.start, rsrc.end - rsrc.start + 1, nid); + + r = numa_add_memblk(nid, rsrc.start, + rsrc.end - rsrc.start + 1); + if (r) + break; + } + of_node_put(np); + + return r; +} + +static int __init of_numa_parse_distance_map_v1(struct device_node *map) +{ + const __be32 *matrix; + int entry_count; + int i; + + pr_info("NUMA: parsing numa-distance-map-v1\n"); + + matrix = of_get_property(map, "distance-matrix", NULL); + if (!matrix) { + pr_err("NUMA: No distance-matrix property in distance-map\n"); + return -EINVAL; + } + + entry_count = of_property_count_u32_elems(map, "distance-matrix"); + if (entry_count <= 0) { + pr_err("NUMA: Invalid distance-matrix\n"); + return -EINVAL; + } + + for (i = 0; i + 2 < entry_count; i += 3) { + u32 nodea, nodeb, distance; + + nodea = of_read_number(matrix, 1); + matrix++; + nodeb = of_read_number(matrix, 1); + matrix++; + distance = of_read_number(matrix, 1); + matrix++; + + numa_set_distance(nodea, nodeb, distance); + pr_debug("NUMA: distance[node%d -> node%d] = %d\n", + nodea, nodeb, distance); + + /* Set default distance of node B->A same as A->B */ + if (nodeb > nodea) + numa_set_distance(nodeb, nodea, distance); + } + + return 0; +} + +static int __init of_numa_parse_distance_map(void) +{ + int ret = 0; + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, + "numa-distance-map-v1"); + if (np) + ret = of_numa_parse_distance_map_v1(np); + + of_node_put(np); + return ret; +} + +int of_node_to_nid(struct device_node *device) +{ + struct device_node *np; + u32 nid; + int r = -ENODATA; + + np = of_node_get(device); + + while (np) { + struct device_node *parent; + + r = of_property_read_u32(np, "numa-node-id", &nid); + /* + * -EINVAL indicates the property was not found, and + * we walk up the tree trying to find a parent with a + * "numa-node-id". Any other type of error indicates + * a bad device tree and we give up. + */ + if (r != -EINVAL) + break; + + parent = of_get_parent(np); + of_node_put(np); + np = parent; + } + if (np && r) + pr_warn("NUMA: Invalid \"numa-node-id\" property in node %s\n", + np->name); + of_node_put(np); + + if (!r) { + if (nid >= MAX_NUMNODES) + pr_warn("NUMA: Node id %u exceeds maximum value\n", + nid); + else + return nid; + } + + return NUMA_NO_NODE; +} +EXPORT_SYMBOL(of_node_to_nid); + +int __init of_numa_init(void) +{ + int r; + + of_numa_parse_cpu_nodes(); + r = of_numa_parse_memory_nodes(); + if (r) + return r; + return of_numa_parse_distance_map(); +} diff --git a/include/linux/of.h b/include/linux/of.h index 7fcb681baadf..76f07c84040f 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -685,6 +685,15 @@ static inline int of_node_to_nid(struct device_node *device) } #endif +#ifdef CONFIG_OF_NUMA +extern int of_numa_init(void); +#else +static inline int of_numa_init(void) +{ + return -ENOSYS; +} +#endif + static inline struct device_node *of_find_matching_node( struct device_node *from, const struct of_device_id *matches) -- GitLab From 3194ac6e66cc7a00c1fa9fecf33a7c376b489497 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 8 Apr 2016 15:50:26 -0700 Subject: [PATCH 2963/9938] arm64: Move unflatten_device_tree() call earlier. In order to extract NUMA information from the device tree, we need to have the tree in its unflattened form. Move the call to bootmem_init() in the tail of paging_init() into setup_arch, and adjust header files so that its declaration is visible. Move the unflatten_device_tree() call between the calls to paging_init() and bootmem_init(). Follow on patches add NUMA handling to bootmem_init(). Signed-off-by: David Daney Signed-off-by: Will Deacon --- arch/arm64/include/asm/mmu.h | 1 + arch/arm64/kernel/setup.c | 12 ++++++++---- arch/arm64/mm/mm.h | 1 - arch/arm64/mm/mmu.c | 2 -- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 990124a67eeb..97b1d8f26b9c 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -29,6 +29,7 @@ typedef struct { #define ASID(mm) ((mm)->context.id.counter & 0xffff) extern void paging_init(void); +extern void bootmem_init(void); extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void init_mem_pgprot(void); extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 7b85b1d6a6fb..432bc7f1dc45 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -265,18 +265,22 @@ void __init setup_arch(char **cmdline_p) paging_init(); + if (acpi_disabled) + unflatten_device_tree(); + + bootmem_init(); + kasan_init(); request_standard_resources(); early_ioremap_reset(); - if (acpi_disabled) { - unflatten_device_tree(); + if (acpi_disabled) psci_dt_init(); - } else { + else psci_acpi_init(); - } + xen_early_init(); cpu_read_bootcpu_ops(); diff --git a/arch/arm64/mm/mm.h b/arch/arm64/mm/mm.h index ef47d99b5cbc..71fe98985455 100644 --- a/arch/arm64/mm/mm.h +++ b/arch/arm64/mm/mm.h @@ -1,3 +1,2 @@ -extern void __init bootmem_init(void); void fixup_init(void); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index dbad533076d1..0f85a46c3e18 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -564,8 +564,6 @@ void __init paging_init(void) */ memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE, SWAPPER_DIR_SIZE - PAGE_SIZE); - - bootmem_init(); } /* -- GitLab From 1a2db300348b799479d2d22b84d51b27ad0458c7 Mon Sep 17 00:00:00 2001 From: Ganapatrao Kulkarni Date: Fri, 8 Apr 2016 15:50:27 -0700 Subject: [PATCH 2964/9938] arm64, numa: Add NUMA support for arm64 platforms. Attempt to get the memory and CPU NUMA node via of_numa. If that fails, default the dummy NUMA node and map all memory and CPUs to node 0. Tested-by: Shannon Zhao Reviewed-by: Robert Richter Signed-off-by: Ganapatrao Kulkarni Signed-off-by: David Daney Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 26 ++ arch/arm64/include/asm/mmzone.h | 12 + arch/arm64/include/asm/numa.h | 45 ++++ arch/arm64/include/asm/topology.h | 10 + arch/arm64/kernel/pci.c | 10 + arch/arm64/kernel/setup.c | 4 + arch/arm64/kernel/smp.c | 4 + arch/arm64/mm/Makefile | 1 + arch/arm64/mm/init.c | 35 ++- arch/arm64/mm/numa.c | 396 ++++++++++++++++++++++++++++++ 10 files changed, 538 insertions(+), 5 deletions(-) create mode 100644 arch/arm64/include/asm/mmzone.h create mode 100644 arch/arm64/include/asm/numa.h create mode 100644 arch/arm64/mm/numa.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 4f436220384f..99f9b5554bd1 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -76,6 +76,7 @@ config ARM64 select HAVE_HW_BREAKPOINT if PERF_EVENTS select HAVE_IRQ_TIME_ACCOUNTING select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP if NUMA select HAVE_PATA_PLATFORM select HAVE_PERF_EVENTS select HAVE_PERF_REGS @@ -98,6 +99,7 @@ config ARM64 select SYSCTL_EXCEPTION_TRACE select HAVE_CONTEXT_TRACKING select HAVE_ARM_SMCCC + select OF_NUMA if NUMA && OF help ARM 64-bit (AArch64) Linux support. @@ -546,6 +548,30 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. +# Common NUMA Features +config NUMA + bool "Numa Memory Allocation and Scheduler Support" + depends on SMP + help + Enable NUMA (Non Uniform Memory Access) support. + + The kernel will try to allocate memory used by a CPU on the + local memory of the CPU and add some more + NUMA awareness to the kernel. + +config NODES_SHIFT + int "Maximum NUMA Nodes (as a power of 2)" + range 1 10 + default "2" + depends on NEED_MULTIPLE_NODES + help + Specify the maximum number of NUMA Nodes available on the target + system. Increases memory reserved to accommodate various tables. + +config USE_PERCPU_NUMA_NODE_ID + def_bool y + depends on NUMA + source kernel/Kconfig.preempt source kernel/Kconfig.hz diff --git a/arch/arm64/include/asm/mmzone.h b/arch/arm64/include/asm/mmzone.h new file mode 100644 index 000000000000..a0de9e6ba73f --- /dev/null +++ b/arch/arm64/include/asm/mmzone.h @@ -0,0 +1,12 @@ +#ifndef __ASM_MMZONE_H +#define __ASM_MMZONE_H + +#ifdef CONFIG_NUMA + +#include + +extern struct pglist_data *node_data[]; +#define NODE_DATA(nid) (node_data[(nid)]) + +#endif /* CONFIG_NUMA */ +#endif /* __ASM_MMZONE_H */ diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h new file mode 100644 index 000000000000..e9b4f2942335 --- /dev/null +++ b/arch/arm64/include/asm/numa.h @@ -0,0 +1,45 @@ +#ifndef __ASM_NUMA_H +#define __ASM_NUMA_H + +#include + +#ifdef CONFIG_NUMA + +/* currently, arm64 implements flat NUMA topology */ +#define parent_node(node) (node) + +int __node_distance(int from, int to); +#define node_distance(a, b) __node_distance(a, b) + +extern nodemask_t numa_nodes_parsed __initdata; + +/* Mappings between node number and cpus on that node. */ +extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; +void numa_clear_node(unsigned int cpu); + +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +const struct cpumask *cpumask_of_node(int node); +#else +/* Returns a pointer to the cpumask of CPUs on Node 'node'. */ +static inline const struct cpumask *cpumask_of_node(int node) +{ + return node_to_cpumask_map[node]; +} +#endif + +void __init arm64_numa_init(void); +int __init numa_add_memblk(int nodeid, u64 start, u64 end); +void __init numa_set_distance(int from, int to, int distance); +void __init numa_free_distance(void); +void __init early_map_cpu_to_node(unsigned int cpu, int nid); +void numa_store_cpu_info(unsigned int cpu); + +#else /* CONFIG_NUMA */ + +static inline void numa_store_cpu_info(unsigned int cpu) { } +static inline void arm64_numa_init(void) { } +static inline void early_map_cpu_to_node(unsigned int cpu, int nid) { } + +#endif /* CONFIG_NUMA */ + +#endif /* __ASM_NUMA_H */ diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index a3e9d6fdbf21..8b57339823e9 100644 --- a/arch/arm64/include/asm/topology.h +++ b/arch/arm64/include/asm/topology.h @@ -22,6 +22,16 @@ void init_cpu_topology(void); void store_cpu_topology(unsigned int cpuid); const struct cpumask *cpu_coregroup_mask(int cpu); +#ifdef CONFIG_NUMA + +struct pci_bus; +int pcibus_to_node(struct pci_bus *bus); +#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \ + cpu_all_mask : \ + cpumask_of_node(pcibus_to_node(bus))) + +#endif /* CONFIG_NUMA */ + #include #endif /* _ASM_ARM_TOPOLOGY_H */ diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c index c72de668e1d4..3c4e308b40a0 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c @@ -74,6 +74,16 @@ int raw_pci_write(unsigned int domain, unsigned int bus, return -ENXIO; } +#ifdef CONFIG_NUMA + +int pcibus_to_node(struct pci_bus *bus) +{ + return dev_to_node(&bus->dev); +} +EXPORT_SYMBOL(pcibus_to_node); + +#endif + #ifdef CONFIG_ACPI /* Root bridge scanning */ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 432bc7f1dc45..65f515949baa 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -319,6 +320,9 @@ static int __init topology_init(void) { int i; + for_each_online_node(i) + register_one_node(i); + for_each_possible_cpu(i) { struct cpu *cpu = &per_cpu(cpu_data.cpu, i); cpu->hotpluggable = 1; diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 5fbab1c40424..622bd6cd86e4 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -203,6 +204,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) static void smp_store_cpu_info(unsigned int cpuid) { store_cpu_topology(cpuid); + numa_store_cpu_info(cpuid); } /* @@ -633,6 +635,8 @@ static void __init of_parse_and_init_cpus(void) pr_debug("cpu logical map 0x%llx\n", hwid); cpu_logical_map(cpu_count) = hwid; + + early_map_cpu_to_node(cpu_count, of_node_to_nid(dn)); next: cpu_count++; } diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index 57f57fde5722..54bb209cae8e 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile @@ -4,6 +4,7 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ context.o proc.o pageattr.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_ARM64_PTDUMP) += dump.o +obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_KASAN) += kasan_init.o KASAN_SANITIZE_kasan_init.o := n diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index d55d720dba79..f64dbd49eca3 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,21 @@ static phys_addr_t __init max_zone_dma_phys(void) return min(offset + (1ULL << 32), memblock_end_of_DRAM()); } +#ifdef CONFIG_NUMA + +static void __init zone_sizes_init(unsigned long min, unsigned long max) +{ + unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; + + if (IS_ENABLED(CONFIG_ZONE_DMA)) + max_zone_pfns[ZONE_DMA] = PFN_DOWN(max_zone_dma_phys()); + max_zone_pfns[ZONE_NORMAL] = max; + + free_area_init_nodes(max_zone_pfns); +} + +#else + static void __init zone_sizes_init(unsigned long min, unsigned long max) { struct memblock_region *reg; @@ -126,6 +142,8 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) free_area_init_node(0, zone_size, min, zhole_size); } +#endif /* CONFIG_NUMA */ + #ifdef CONFIG_HAVE_ARCH_PFN_VALID int pfn_valid(unsigned long pfn) { @@ -142,10 +160,15 @@ static void __init arm64_memory_present(void) static void __init arm64_memory_present(void) { struct memblock_region *reg; + int nid = 0; - for_each_memblock(memory, reg) - memory_present(0, memblock_region_memory_base_pfn(reg), - memblock_region_memory_end_pfn(reg)); + for_each_memblock(memory, reg) { +#ifdef CONFIG_NUMA + nid = reg->nid; +#endif + memory_present(nid, memblock_region_memory_base_pfn(reg), + memblock_region_memory_end_pfn(reg)); + } } #endif @@ -278,7 +301,6 @@ void __init arm64_memblock_init(void) dma_contiguous_reserve(arm64_dma_phys_limit); memblock_allow_resize(); - memblock_dump_all(); } void __init bootmem_init(void) @@ -290,6 +312,9 @@ void __init bootmem_init(void) early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT); + max_pfn = max_low_pfn = max; + + arm64_numa_init(); /* * Sparsemem tries to allocate bootmem in memory_present(), so must be * done after the fixed reservations. @@ -300,7 +325,7 @@ void __init bootmem_init(void) zone_sizes_init(min, max); high_memory = __va((max << PAGE_SHIFT) - 1) + 1; - max_pfn = max_low_pfn = max; + memblock_dump_all(); } #ifndef CONFIG_SPARSEMEM_VMEMMAP diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c new file mode 100644 index 000000000000..98dc1047f2a2 --- /dev/null +++ b/arch/arm64/mm/numa.c @@ -0,0 +1,396 @@ +/* + * NUMA support, based on the x86 implementation. + * + * Copyright (C) 2015 Cavium Inc. + * Author: Ganapatrao Kulkarni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; +EXPORT_SYMBOL(node_data); +nodemask_t numa_nodes_parsed __initdata; +static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE }; + +static int numa_distance_cnt; +static u8 *numa_distance; +static int numa_off; + +static __init int numa_parse_early_param(char *opt) +{ + if (!opt) + return -EINVAL; + if (!strncmp(opt, "off", 3)) { + pr_info("%s\n", "NUMA turned off"); + numa_off = 1; + } + return 0; +} +early_param("numa", numa_parse_early_param); + +cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; +EXPORT_SYMBOL(node_to_cpumask_map); + +#ifdef CONFIG_DEBUG_PER_CPU_MAPS + +/* + * Returns a pointer to the bitmask of CPUs on Node 'node'. + */ +const struct cpumask *cpumask_of_node(int node) +{ + if (WARN_ON(node >= nr_node_ids)) + return cpu_none_mask; + + if (WARN_ON(node_to_cpumask_map[node] == NULL)) + return cpu_online_mask; + + return node_to_cpumask_map[node]; +} +EXPORT_SYMBOL(cpumask_of_node); + +#endif + +static void map_cpu_to_node(unsigned int cpu, int nid) +{ + set_cpu_numa_node(cpu, nid); + if (nid >= 0) + cpumask_set_cpu(cpu, node_to_cpumask_map[nid]); +} + +void numa_clear_node(unsigned int cpu) +{ + int nid = cpu_to_node(cpu); + + if (nid >= 0) + cpumask_clear_cpu(cpu, node_to_cpumask_map[nid]); + set_cpu_numa_node(cpu, NUMA_NO_NODE); +} + +/* + * Allocate node_to_cpumask_map based on number of available nodes + * Requires node_possible_map to be valid. + * + * Note: cpumask_of_node() is not valid until after this is done. + * (Use CONFIG_DEBUG_PER_CPU_MAPS to check this.) + */ +static void __init setup_node_to_cpumask_map(void) +{ + unsigned int cpu; + int node; + + /* setup nr_node_ids if not done yet */ + if (nr_node_ids == MAX_NUMNODES) + setup_nr_node_ids(); + + /* allocate and clear the mapping */ + for (node = 0; node < nr_node_ids; node++) { + alloc_bootmem_cpumask_var(&node_to_cpumask_map[node]); + cpumask_clear(node_to_cpumask_map[node]); + } + + for_each_possible_cpu(cpu) + set_cpu_numa_node(cpu, NUMA_NO_NODE); + + /* cpumask_of_node() will now work */ + pr_debug("NUMA: Node to cpumask map for %d nodes\n", nr_node_ids); +} + +/* + * Set the cpu to node and mem mapping + */ +void numa_store_cpu_info(unsigned int cpu) +{ + map_cpu_to_node(cpu, numa_off ? 0 : cpu_to_node_map[cpu]); +} + +void __init early_map_cpu_to_node(unsigned int cpu, int nid) +{ + /* fallback to node 0 */ + if (nid < 0 || nid >= MAX_NUMNODES) + nid = 0; + + cpu_to_node_map[cpu] = nid; +} + +/** + * numa_add_memblk - Set node id to memblk + * @nid: NUMA node ID of the new memblk + * @start: Start address of the new memblk + * @size: Size of the new memblk + * + * RETURNS: + * 0 on success, -errno on failure. + */ +int __init numa_add_memblk(int nid, u64 start, u64 size) +{ + int ret; + + ret = memblock_set_node(start, size, &memblock.memory, nid); + if (ret < 0) { + pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n", + start, (start + size - 1), nid); + return ret; + } + + node_set(nid, numa_nodes_parsed); + pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n", + start, (start + size - 1), nid); + return ret; +} + +/** + * Initialize NODE_DATA for a node on the local memory + */ +static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) +{ + const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES); + u64 nd_pa; + void *nd; + int tnid; + + pr_info("NUMA: Initmem setup node %d [mem %#010Lx-%#010Lx]\n", + nid, start_pfn << PAGE_SHIFT, + (end_pfn << PAGE_SHIFT) - 1); + + nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); + nd = __va(nd_pa); + + /* report and initialize */ + pr_info("NUMA: NODE_DATA [mem %#010Lx-%#010Lx]\n", + nd_pa, nd_pa + nd_size - 1); + tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); + if (tnid != nid) + pr_info("NUMA: NODE_DATA(%d) on node %d\n", nid, tnid); + + node_data[nid] = nd; + memset(NODE_DATA(nid), 0, sizeof(pg_data_t)); + NODE_DATA(nid)->node_id = nid; + NODE_DATA(nid)->node_start_pfn = start_pfn; + NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; +} + +/** + * numa_free_distance + * + * The current table is freed. + */ +void __init numa_free_distance(void) +{ + size_t size; + + if (!numa_distance) + return; + + size = numa_distance_cnt * numa_distance_cnt * + sizeof(numa_distance[0]); + + memblock_free(__pa(numa_distance), size); + numa_distance_cnt = 0; + numa_distance = NULL; +} + +/** + * + * Create a new NUMA distance table. + * + */ +static int __init numa_alloc_distance(void) +{ + size_t size; + u64 phys; + int i, j; + + size = nr_node_ids * nr_node_ids * sizeof(numa_distance[0]); + phys = memblock_find_in_range(0, PFN_PHYS(max_pfn), + size, PAGE_SIZE); + if (WARN_ON(!phys)) + return -ENOMEM; + + memblock_reserve(phys, size); + + numa_distance = __va(phys); + numa_distance_cnt = nr_node_ids; + + /* fill with the default distances */ + for (i = 0; i < numa_distance_cnt; i++) + for (j = 0; j < numa_distance_cnt; j++) + numa_distance[i * numa_distance_cnt + j] = i == j ? + LOCAL_DISTANCE : REMOTE_DISTANCE; + + pr_debug("NUMA: Initialized distance table, cnt=%d\n", + numa_distance_cnt); + + return 0; +} + +/** + * numa_set_distance - Set inter node NUMA distance from node to node. + * @from: the 'from' node to set distance + * @to: the 'to' node to set distance + * @distance: NUMA distance + * + * Set the distance from node @from to @to to @distance. + * If distance table doesn't exist, a warning is printed. + * + * If @from or @to is higher than the highest known node or lower than zero + * or @distance doesn't make sense, the call is ignored. + * + */ +void __init numa_set_distance(int from, int to, int distance) +{ + if (!numa_distance) { + pr_warn_once("NUMA: Warning: distance table not allocated yet\n"); + return; + } + + if (from >= numa_distance_cnt || to >= numa_distance_cnt || + from < 0 || to < 0) { + pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n", + from, to, distance); + return; + } + + if ((u8)distance != distance || + (from == to && distance != LOCAL_DISTANCE)) { + pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n", + from, to, distance); + return; + } + + numa_distance[from * numa_distance_cnt + to] = distance; +} + +/** + * Return NUMA distance @from to @to + */ +int __node_distance(int from, int to) +{ + if (from >= numa_distance_cnt || to >= numa_distance_cnt) + return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE; + return numa_distance[from * numa_distance_cnt + to]; +} +EXPORT_SYMBOL(__node_distance); + +static int __init numa_register_nodes(void) +{ + int nid; + struct memblock_region *mblk; + + /* Check that valid nid is set to memblks */ + for_each_memblock(memory, mblk) + if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) { + pr_warn("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n", + mblk->nid, mblk->base, + mblk->base + mblk->size - 1); + return -EINVAL; + } + + /* Finally register nodes. */ + for_each_node_mask(nid, numa_nodes_parsed) { + unsigned long start_pfn, end_pfn; + + get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); + setup_node_data(nid, start_pfn, end_pfn); + node_set_online(nid); + } + + /* Setup online nodes to actual nodes*/ + node_possible_map = numa_nodes_parsed; + + return 0; +} + +static int __init numa_init(int (*init_func)(void)) +{ + int ret; + + nodes_clear(numa_nodes_parsed); + nodes_clear(node_possible_map); + nodes_clear(node_online_map); + numa_free_distance(); + + ret = numa_alloc_distance(); + if (ret < 0) + return ret; + + ret = init_func(); + if (ret < 0) + return ret; + + if (nodes_empty(numa_nodes_parsed)) + return -EINVAL; + + ret = numa_register_nodes(); + if (ret < 0) + return ret; + + setup_node_to_cpumask_map(); + + /* init boot processor */ + cpu_to_node_map[0] = 0; + map_cpu_to_node(0, 0); + + return 0; +} + +/** + * dummy_numa_init - Fallback dummy NUMA init + * + * Used if there's no underlying NUMA architecture, NUMA initialization + * fails, or NUMA is disabled on the command line. + * + * Must online at least one node (node 0) and add memory blocks that cover all + * allowed memory. It is unlikely that this function fails. + */ +static int __init dummy_numa_init(void) +{ + int ret; + struct memblock_region *mblk; + + pr_info("%s\n", "No NUMA configuration found"); + pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n", + 0LLU, PFN_PHYS(max_pfn) - 1); + + for_each_memblock(memory, mblk) { + ret = numa_add_memblk(0, mblk->base, mblk->size); + if (!ret) + continue; + + pr_err("NUMA init failed\n"); + return ret; + } + + numa_off = 1; + return 0; +} + +/** + * arm64_numa_init - Initialize NUMA + * + * Try each configured NUMA initialization method until one succeeds. The + * last fallback is dummy single node config encomapssing whole memory. + */ +void __init arm64_numa_init(void) +{ + if (!numa_off) { + if (!numa_init(of_numa_init)) + return; + } + + numa_init(dummy_numa_init); +} -- GitLab From 561662301eb6a40d569453b3555fc8cfce094b93 Mon Sep 17 00:00:00 2001 From: Ganapatrao Kulkarni Date: Fri, 8 Apr 2016 15:50:28 -0700 Subject: [PATCH 2965/9938] arm64, mm, numa: Add NUMA balancing support for arm64. Enable NUMA balancing for arm64 platforms. Add pte, pmd protnone helpers for use by automatic NUMA balancing. Reviewed-by: Steve Capper Reviewed-by: Robert Richter Signed-off-by: Ganapatrao Kulkarni Signed-off-by: David Daney Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/pgtable.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 99f9b5554bd1..a578080ae7a0 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -11,6 +11,7 @@ config ARM64 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_USE_CMPXCHG_LOCKREF select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_COMPAT_IPC_PARSE_VERSION select ARCH_WANT_FRAME_POINTERS diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 2abfa4d09e65..3c91b179089a 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -266,6 +266,21 @@ static inline pgprot_t mk_sect_prot(pgprot_t prot) return __pgprot(pgprot_val(prot) & ~PTE_TABLE_BIT); } +#ifdef CONFIG_NUMA_BALANCING +/* + * See the comment in include/asm-generic/pgtable.h + */ +static inline int pte_protnone(pte_t pte) +{ + return (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)) == PTE_PROT_NONE; +} + +static inline int pmd_protnone(pmd_t pmd) +{ + return pte_protnone(pmd_pte(pmd)); +} +#endif + /* * THP definitions. */ -- GitLab From 66dbd6e61a526ae7d11a208238ae2c17e5cacb6b Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 13 Apr 2016 16:01:22 +0100 Subject: [PATCH 2966/9938] arm64: Implement ptep_set_access_flags() for hardware AF/DBM When hardware updates of the access and dirty states are enabled, the default ptep_set_access_flags() implementation based on calling set_pte_at() directly is potentially racy. This triggers the "racy dirty state clearing" warning in set_pte_at() because an existing writable PTE is overridden with a clean entry. There are two main scenarios for this situation: 1. The CPU getting an access fault does not support hardware updates of the access/dirty flags. However, a different agent in the system (e.g. SMMU) can do this, therefore overriding a writable entry with a clean one could potentially lose the automatically updated dirty status 2. A more complex situation is possible when all CPUs support hardware AF/DBM: a) Initial state: shareable + writable vma and pte_none(pte) b) Read fault taken by two threads of the same process on different CPUs c) CPU0 takes the mmap_sem and proceeds to handling the fault. It eventually reaches do_set_pte() which sets a writable + clean pte. CPU0 releases the mmap_sem d) CPU1 acquires the mmap_sem and proceeds to handle_pte_fault(). The pte entry it reads is present, writable and clean and it continues to pte_mkyoung() e) CPU1 calls ptep_set_access_flags() If between (d) and (e) the hardware (another CPU) updates the dirty state (clears PTE_RDONLY), CPU1 will override the PTR_RDONLY bit marking the entry clean again. This patch implements an arm64-specific ptep_set_access_flags() function to perform an atomic update of the PTE flags. Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits") Signed-off-by: Catalin Marinas Reported-by: Ming Lei Tested-by: Julien Grall Cc: Will Deacon Cc: # 4.3+ [will: reworded comment] Signed-off-by: Will Deacon --- arch/arm64/include/asm/pgtable.h | 5 ++++ arch/arm64/mm/fault.c | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 3c91b179089a..3eefc181d00b 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -535,6 +535,11 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) } #ifdef CONFIG_ARM64_HW_AFDBM +#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +extern int ptep_set_access_flags(struct vm_area_struct *vma, + unsigned long address, pte_t *ptep, + pte_t entry, int dirty); + /* * Atomic pte/pmd modifications. */ diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index c12e96753de9..d24a5e05a3f2 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -81,6 +81,56 @@ void show_pte(struct mm_struct *mm, unsigned long addr) printk("\n"); } +#ifdef CONFIG_ARM64_HW_AFDBM +/* + * This function sets the access flags (dirty, accessed), as well as write + * permission, and only to a more permissive setting. + * + * It needs to cope with hardware update of the accessed/dirty state by other + * agents in the system and can safely skip the __sync_icache_dcache() call as, + * like set_pte_at(), the PTE is never changed from no-exec to exec here. + * + * Returns whether or not the PTE actually changed. + */ +int ptep_set_access_flags(struct vm_area_struct *vma, + unsigned long address, pte_t *ptep, + pte_t entry, int dirty) +{ + pteval_t old_pteval; + unsigned int tmp; + + if (pte_same(*ptep, entry)) + return 0; + + /* only preserve the access flags and write permission */ + pte_val(entry) &= PTE_AF | PTE_WRITE | PTE_DIRTY; + + /* + * PTE_RDONLY is cleared by default in the asm below, so set it in + * back if necessary (read-only or clean PTE). + */ + if (!pte_write(entry) || !dirty) + pte_val(entry) |= PTE_RDONLY; + + /* + * Setting the flags must be done atomically to avoid racing with the + * hardware update of the access/dirty state. + */ + asm volatile("// ptep_set_access_flags\n" + " prfm pstl1strm, %2\n" + "1: ldxr %0, %2\n" + " and %0, %0, %3 // clear PTE_RDONLY\n" + " orr %0, %0, %4 // set flags\n" + " stxr %w1, %0, %2\n" + " cbnz %w1, 1b\n" + : "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep)) + : "L" (~PTE_RDONLY), "r" (pte_val(entry))); + + flush_tlb_fix_spurious_fault(vma, address); + return 1; +} +#endif + /* * The kernel tried to access some page that wasn't present. */ -- GitLab From 522566376a3f8373fbd5ff75bb8a7a2da701c1a7 Mon Sep 17 00:00:00 2001 From: Aviya Erenfeld Date: Thu, 14 Apr 2016 11:59:31 +0200 Subject: [PATCH 2967/9938] devcoredump: add scatterlist support Add scatterlist support (dev_coredumpsg) to allow drivers to avoid vmalloc() like dev_coredumpm(), while also avoiding the module reference that the latter function requires. This internally uses dev_coredumpm() with function inside the devcoredump module, requiring removing the const (which touches the driver using it.) Signed-off-by: Aviya Erenfeld Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/base/devcoredump.c | 83 ++++++++++++++++-- .../net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 4 +- include/linux/devcoredump.h | 86 +++++++++++++++++-- 3 files changed, 154 insertions(+), 19 deletions(-) diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c index 1bd120a0b084..240374fd1838 100644 --- a/drivers/base/devcoredump.c +++ b/drivers/base/devcoredump.c @@ -4,6 +4,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -41,12 +42,12 @@ static bool devcd_disabled; struct devcd_entry { struct device devcd_dev; - const void *data; + void *data; size_t datalen; struct module *owner; ssize_t (*read)(char *buffer, loff_t offset, size_t count, - const void *data, size_t datalen); - void (*free)(const void *data); + void *data, size_t datalen); + void (*free)(void *data); struct delayed_work del_wk; struct device *failing_dev; }; @@ -174,7 +175,7 @@ static struct class devcd_class = { }; static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, - const void *data, size_t datalen) + void *data, size_t datalen) { if (offset > datalen) return -EINVAL; @@ -188,6 +189,11 @@ static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, return count; } +static void devcd_freev(void *data) +{ + vfree(data); +} + /** * dev_coredumpv - create device coredump with vmalloc data * @dev: the struct device for the crashed device @@ -198,10 +204,10 @@ static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, * This function takes ownership of the vmalloc'ed data and will free * it when it is no longer used. See dev_coredumpm() for more information. */ -void dev_coredumpv(struct device *dev, const void *data, size_t datalen, +void dev_coredumpv(struct device *dev, void *data, size_t datalen, gfp_t gfp) { - dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, vfree); + dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, devcd_freev); } EXPORT_SYMBOL_GPL(dev_coredumpv); @@ -212,6 +218,44 @@ static int devcd_match_failing(struct device *dev, const void *failing) return devcd->failing_dev == failing; } +/** + * devcd_free_sgtable - free all the memory of the given scatterlist table + * (i.e. both pages and scatterlist instances) + * NOTE: if two tables allocated with devcd_alloc_sgtable and then chained + * using the sg_chain function then that function should be called only once + * on the chained table + * @table: pointer to sg_table to free + */ +static void devcd_free_sgtable(void *data) +{ + _devcd_free_sgtable(data); +} + +/** + * devcd_read_from_table - copy data from sg_table to a given buffer + * and return the number of bytes read + * @buffer: the buffer to copy the data to it + * @buf_len: the length of the buffer + * @data: the scatterlist table to copy from + * @offset: start copy from @offset@ bytes from the head of the data + * in the given scatterlist + * @data_len: the length of the data in the sg_table + */ +static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset, + size_t buf_len, void *data, + size_t data_len) +{ + struct scatterlist *table = data; + + if (offset > data_len) + return -EINVAL; + + if (offset + buf_len > data_len) + buf_len = data_len - offset; + return sg_pcopy_to_buffer(table, sg_nents(table), buffer, buf_len, + offset); +} + /** * dev_coredumpm - create device coredump with read/free methods * @dev: the struct device for the crashed device @@ -228,10 +272,10 @@ static int devcd_match_failing(struct device *dev, const void *failing) * function will be called to free the data. */ void dev_coredumpm(struct device *dev, struct module *owner, - const void *data, size_t datalen, gfp_t gfp, + void *data, size_t datalen, gfp_t gfp, ssize_t (*read)(char *buffer, loff_t offset, size_t count, - const void *data, size_t datalen), - void (*free)(const void *data)) + void *data, size_t datalen), + void (*free)(void *data)) { static atomic_t devcd_count = ATOMIC_INIT(0); struct devcd_entry *devcd; @@ -291,6 +335,27 @@ void dev_coredumpm(struct device *dev, struct module *owner, } EXPORT_SYMBOL_GPL(dev_coredumpm); +/** + * dev_coredumpmsg - create device coredump that uses scatterlist as data + * parameter + * @dev: the struct device for the crashed device + * @table: the dump data + * @datalen: length of the data + * @gfp: allocation flags + * + * Creates a new device coredump for the given device. If a previous one hasn't + * been read yet, the new coredump is discarded. The data lifetime is determined + * by the device coredump framework and when it is no longer needed + * it will free the data. + */ +void dev_coredumpsg(struct device *dev, struct scatterlist *table, + size_t datalen, gfp_t gfp) +{ + dev_coredumpm(dev, NULL, table, datalen, gfp, devcd_read_from_sgtable, + devcd_free_sgtable); +} +EXPORT_SYMBOL_GPL(dev_coredumpsg); + static int __init devcoredump_init(void) { return class_register(&devcd_class); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 4856eac120f6..a4b0581d2275 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -71,7 +71,7 @@ #include "iwl-csr.h" static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, - const void *data, size_t datalen) + void *data, size_t datalen) { const struct iwl_mvm_dump_ptrs *dump_ptrs = data; ssize_t bytes_read; @@ -104,7 +104,7 @@ static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, return bytes_read + bytes_read_trans; } -static void iwl_mvm_free_coredump(const void *data) +static void iwl_mvm_free_coredump(void *data) { const struct iwl_mvm_dump_ptrs *fw_error_dump = data; diff --git a/include/linux/devcoredump.h b/include/linux/devcoredump.h index c0a360e99f64..269521f143ac 100644 --- a/include/linux/devcoredump.h +++ b/include/linux/devcoredump.h @@ -1,3 +1,22 @@ +/* + * This file is provided under the GPLv2 license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015 Intel Deutschland GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + */ #ifndef __DEVCOREDUMP_H #define __DEVCOREDUMP_H @@ -5,17 +24,62 @@ #include #include +#include +#include + +/* + * _devcd_free_sgtable - free all the memory of the given scatterlist table + * (i.e. both pages and scatterlist instances) + * NOTE: if two tables allocated and chained using the sg_chain function then + * this function should be called only once on the first table + * @table: pointer to sg_table to free + */ +static inline void _devcd_free_sgtable(struct scatterlist *table) +{ + int i; + struct page *page; + struct scatterlist *iter; + struct scatterlist *delete_iter; + + /* free pages */ + iter = table; + for_each_sg(table, iter, sg_nents(table), i) { + page = sg_page(iter); + if (page) + __free_page(page); + } + + /* then free all chained tables */ + iter = table; + delete_iter = table; /* always points on a head of a table */ + while (!sg_is_last(iter)) { + iter++; + if (sg_is_chain(iter)) { + iter = sg_chain_ptr(iter); + kfree(delete_iter); + delete_iter = iter; + } + } + + /* free the last table */ + kfree(delete_iter); +} + + #ifdef CONFIG_DEV_COREDUMP -void dev_coredumpv(struct device *dev, const void *data, size_t datalen, +void dev_coredumpv(struct device *dev, void *data, size_t datalen, gfp_t gfp); void dev_coredumpm(struct device *dev, struct module *owner, - const void *data, size_t datalen, gfp_t gfp, + void *data, size_t datalen, gfp_t gfp, ssize_t (*read)(char *buffer, loff_t offset, size_t count, - const void *data, size_t datalen), - void (*free)(const void *data)); + void *data, size_t datalen), + void (*free)(void *data)); + +void dev_coredumpsg(struct device *dev, struct scatterlist *table, + size_t datalen, gfp_t gfp); #else -static inline void dev_coredumpv(struct device *dev, const void *data, +static inline void dev_coredumpv(struct device *dev, void *data, size_t datalen, gfp_t gfp) { vfree(data); @@ -23,13 +87,19 @@ static inline void dev_coredumpv(struct device *dev, const void *data, static inline void dev_coredumpm(struct device *dev, struct module *owner, - const void *data, size_t datalen, gfp_t gfp, + void *data, size_t datalen, gfp_t gfp, ssize_t (*read)(char *buffer, loff_t offset, size_t count, - const void *data, size_t datalen), - void (*free)(const void *data)) + void *data, size_t datalen), + void (*free)(void *data)) { free(data); } + +static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table, + size_t datalen, gfp_t gfp) +{ + _devcd_free_sgtable(table); +} #endif /* CONFIG_DEV_COREDUMP */ #endif /* __DEVCOREDUMP_H */ -- GitLab From 0a233c98a8e933a65aec07663d3a2953c7642bbc Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:05 +0100 Subject: [PATCH 2968/9938] mwifiex: scan: simplify dereference of bss_desc fields given this structure: struct foo { struct bar { int baz; } } these accesses are equivalent: (*(foo->bar)).baz foo->bar->baz Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 98 ++++++++++----------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 624b0a95c64e..99026cef3179 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -121,8 +121,8 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). - ieee_hdr.element_id == WLAN_EID_RSN))) { + if (bss_desc->bcn_rsn_ie && + bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN) { iebody = (struct ie_body *) (((u8 *) bss_desc->bcn_rsn_ie->data) + RSN_GTK_OUI_OFFSET); @@ -148,9 +148,9 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (((bss_desc->bcn_wpa_ie) && - ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == - WLAN_EID_VENDOR_SPECIFIC))) { + if (bss_desc->bcn_wpa_ie && + bss_desc->bcn_wpa_ie->vend_hdr.element_id == + WLAN_EID_VENDOR_SPECIFIC) { iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; oui = &mwifiex_wpa_oui[cipher][0]; ret = mwifiex_search_oui_in_ie(iebody, oui); @@ -181,8 +181,8 @@ mwifiex_is_bss_wapi(struct mwifiex_private *priv, { if (priv->sec_info.wapi_enabled && (bss_desc->bcn_wapi_ie && - ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id == - WLAN_EID_BSS_AC_ACCESS_DELAY))) { + bss_desc->bcn_wapi_ie->ieee_hdr.element_id == + WLAN_EID_BSS_AC_ACCESS_DELAY)) { return true; } return false; @@ -197,12 +197,12 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != - WLAN_EID_RSN)) && + !priv->sec_info.wpa2_enabled && + (!bss_desc->bcn_wpa_ie || + bss_desc->bcn_wpa_ie->vend_hdr.element_id != + WLAN_EID_VENDOR_SPECIFIC) && + (!bss_desc->bcn_rsn_ie || + bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && !priv->sec_info.encryption_mode && !bss_desc->privacy) { return true; } @@ -233,9 +233,10 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) && - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)) + !priv->sec_info.wpa2_enabled && + (bss_desc->bcn_wpa_ie && + bss_desc->bcn_wpa_ie->vend_hdr.element_id == + WLAN_EID_VENDOR_SPECIFIC) /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -245,12 +246,10 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, "info: %s: WPA:\t" "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, (priv->sec_info.wep_enabled) ? "e" : "d", (priv->sec_info.wpa_enabled) ? "e" : "d", (priv->sec_info.wpa2_enabled) ? "e" : "d", @@ -269,11 +268,10 @@ static bool mwifiex_is_bss_wpa2(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { - if (!priv->sec_info.wep_enabled && - !priv->sec_info.wpa_enabled && + if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled && - ((bss_desc->bcn_rsn_ie) && - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) { + (bss_desc->bcn_rsn_ie && + bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN)) { /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -282,12 +280,10 @@ mwifiex_is_bss_wpa2(struct mwifiex_private *priv, "info: %s: WPA2:\t" "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, (priv->sec_info.wep_enabled) ? "e" : "d", (priv->sec_info.wpa_enabled) ? "e" : "d", (priv->sec_info.wpa2_enabled) ? "e" : "d", @@ -308,11 +304,11 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && + (!bss_desc->bcn_wpa_ie || + bss_desc->bcn_wpa_ie->vend_hdr.element_id != + WLAN_EID_VENDOR_SPECIFIC) && + (!bss_desc->bcn_rsn_ie || + bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && !priv->sec_info.encryption_mode && bss_desc->privacy) { return true; } @@ -329,23 +325,21 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && + (!bss_desc->bcn_wpa_ie || + bss_desc->bcn_wpa_ie->vend_hdr.element_id != + WLAN_EID_VENDOR_SPECIFIC) && + (!bss_desc->bcn_rsn_ie || + bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && priv->sec_info.encryption_mode && bss_desc->privacy) { mwifiex_dbg(priv->adapter, INFO, "info: %s: dynamic\t" "WEP: wpa_ie=%#x wpa2_ie=%#x\t" "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, priv->sec_info.encryption_mode, bss_desc->privacy); return true; @@ -464,10 +458,10 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t" "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie).vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie).ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, (priv->sec_info.wep_enabled) ? "e" : "d", (priv->sec_info.wpa_enabled) ? "e" : "d", (priv->sec_info.wpa2_enabled) ? "e" : "d", -- GitLab From 38329568c3f7075c7751984a65e16a9c7fc186bd Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:06 +0100 Subject: [PATCH 2969/9938] mwifiex: scan: factor out has_ieee_hdr/has_vendor_hdr Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 52 +++++++++------------ 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 99026cef3179..e926d3ab7286 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -76,6 +76,18 @@ static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ }; +static bool +has_ieee_hdr(struct ieee_types_generic *ie, u8 key) +{ + return (ie && ie->ieee_hdr.element_id == key); +} + +static bool +has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key) +{ + return (ie && ie->vend_hdr.element_id == key); +} + /* * This function parses a given IE for a given OUI. * @@ -121,8 +133,7 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (bss_desc->bcn_rsn_ie && - bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN) { + if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) { iebody = (struct ie_body *) (((u8 *) bss_desc->bcn_rsn_ie->data) + RSN_GTK_OUI_OFFSET); @@ -148,9 +159,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (bss_desc->bcn_wpa_ie && - bss_desc->bcn_wpa_ie->vend_hdr.element_id == - WLAN_EID_VENDOR_SPECIFIC) { + if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) { iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; oui = &mwifiex_wpa_oui[cipher][0]; ret = mwifiex_search_oui_in_ie(iebody, oui); @@ -180,11 +189,8 @@ mwifiex_is_bss_wapi(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { if (priv->sec_info.wapi_enabled && - (bss_desc->bcn_wapi_ie && - bss_desc->bcn_wapi_ie->ieee_hdr.element_id == - WLAN_EID_BSS_AC_ACCESS_DELAY)) { + has_ieee_hdr(bss_desc->bcn_wapi_ie, WLAN_EID_BSS_AC_ACCESS_DELAY)) return true; - } return false; } @@ -198,11 +204,8 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (!bss_desc->bcn_wpa_ie || - bss_desc->bcn_wpa_ie->vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC) && - (!bss_desc->bcn_rsn_ie || - bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && !priv->sec_info.encryption_mode && !bss_desc->privacy) { return true; } @@ -234,9 +237,7 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (bss_desc->bcn_wpa_ie && - bss_desc->bcn_wpa_ie->vend_hdr.element_id == - WLAN_EID_VENDOR_SPECIFIC) + has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -270,8 +271,7 @@ mwifiex_is_bss_wpa2(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled && - (bss_desc->bcn_rsn_ie && - bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN)) { + has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) { /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -304,11 +304,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (!bss_desc->bcn_wpa_ie || - bss_desc->bcn_wpa_ie->vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC) && - (!bss_desc->bcn_rsn_ie || - bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && !priv->sec_info.encryption_mode && bss_desc->privacy) { return true; } @@ -325,11 +322,8 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (!bss_desc->bcn_wpa_ie || - bss_desc->bcn_wpa_ie->vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC) && - (!bss_desc->bcn_rsn_ie || - bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && priv->sec_info.encryption_mode && bss_desc->privacy) { mwifiex_dbg(priv->adapter, INFO, "info: %s: dynamic\t" -- GitLab From 2ccf7cef0cf984241d0b6932ed1cfb1e0d6587d5 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:07 +0100 Subject: [PATCH 2970/9938] mwifiex: scan: simplify ternary operators using gnu extension "x ? x : y" can be simplified as "x ? : y" https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals Reviewed-by: Julian Calaby Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index e926d3ab7286..11f8a608b8af 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -900,14 +900,11 @@ mwifiex_config_scan(struct mwifiex_private *priv, /* Set the BSS type scan filter, use Adapter setting if unset */ scan_cfg_out->bss_mode = - (user_scan_in->bss_mode ? (u8) user_scan_in-> - bss_mode : (u8) adapter->scan_mode); + (u8)(user_scan_in->bss_mode ?: adapter->scan_mode); /* Set the number of probes to send, use Adapter setting if unset */ - num_probes = - (user_scan_in->num_probes ? user_scan_in-> - num_probes : adapter->scan_probes); + num_probes = user_scan_in->num_probes ?: adapter->scan_probes; /* * Set the BSSID filter to the incoming configuration, -- GitLab From 679b687bc96ddf2ef077ca4aa755924032bd18a8 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:08 +0100 Subject: [PATCH 2971/9938] mwifiex: scan: factor out dbg_security_flags merge copy/paste code Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 74 +++++++-------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 11f8a608b8af..11d57185a090 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -76,6 +76,27 @@ static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ }; +static void +_dbg_security_flags(int log_level, const char *func, const char *desc, + struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + _mwifiex_dbg(priv->adapter, log_level, + "info: %s: %s:\twpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\tEncMode=%#x privacy=%#x\n", + func, desc, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, + priv->sec_info.wep_enabled ? "e" : "d", + priv->sec_info.wpa_enabled ? "e" : "d", + priv->sec_info.wpa2_enabled ? "e" : "d", + priv->sec_info.encryption_mode, + bss_desc->privacy); +} +#define dbg_security_flags(mask, desc, priv, bss_desc) \ + _dbg_security_flags(MWIFIEX_DBG_##mask, desc, __func__, priv, bss_desc) + static bool has_ieee_hdr(struct ieee_types_generic *ie, u8 key) { @@ -243,19 +264,7 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, * LinkSys WRT54G && bss_desc->privacy */ ) { - mwifiex_dbg(priv->adapter, INFO, - "info: %s: WPA:\t" - "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" - "EncMode=%#x privacy=%#x\n", __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); + dbg_security_flags(INFO, "WPA", priv, bss_desc); return true; } return false; @@ -276,19 +285,7 @@ mwifiex_is_bss_wpa2(struct mwifiex_private *priv, * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy */ - mwifiex_dbg(priv->adapter, INFO, - "info: %s: WPA2:\t" - "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" - "EncMode=%#x privacy=%#x\n", __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); + dbg_security_flags(INFO, "WAP2", priv, bss_desc); return true; } return false; @@ -325,17 +322,7 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && priv->sec_info.encryption_mode && bss_desc->privacy) { - mwifiex_dbg(priv->adapter, INFO, - "info: %s: dynamic\t" - "WEP: wpa_ie=%#x wpa2_ie=%#x\t" - "EncMode=%#x privacy=%#x\n", - __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - priv->sec_info.encryption_mode, - bss_desc->privacy); + dbg_security_flags(INFO, "dynamic", priv, bss_desc); return true; } return false; @@ -448,18 +435,7 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, } /* Security doesn't match */ - mwifiex_dbg(adapter, ERROR, - "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t" - "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", - __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, bss_desc->privacy); + dbg_security_flags(ERROR, "failed", priv, bss_desc); return -1; } -- GitLab From 948ad6b34943a1247653392d59bcfc9896da8fe7 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:09 +0100 Subject: [PATCH 2972/9938] mwifiex: scan: replace pointer arithmetic with array access improves readability Reviewed-by: Julian Calaby Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 11d57185a090..753d92a731af 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1055,27 +1055,24 @@ mwifiex_config_scan(struct mwifiex_private *priv, chan_idx++) { channel = user_scan_in->chan_list[chan_idx].chan_number; - (scan_chan_list + chan_idx)->chan_number = channel; + scan_chan_list[chan_idx].chan_number = channel; radio_type = user_scan_in->chan_list[chan_idx].radio_type; - (scan_chan_list + chan_idx)->radio_type = radio_type; + scan_chan_list[chan_idx].radio_type = radio_type; scan_type = user_scan_in->chan_list[chan_idx].scan_type; if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap + scan_chan_list[chan_idx].chan_scan_mode_bitmap |= (MWIFIEX_PASSIVE_SCAN | MWIFIEX_HIDDEN_SSID_REPORT); else - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap + scan_chan_list[chan_idx].chan_scan_mode_bitmap &= ~MWIFIEX_PASSIVE_SCAN; if (*filtered_scan) - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap + scan_chan_list[chan_idx].chan_scan_mode_bitmap |= MWIFIEX_DISABLE_CHAN_FILT; if (user_scan_in->chan_list[chan_idx].scan_time) { @@ -1090,9 +1087,9 @@ mwifiex_config_scan(struct mwifiex_private *priv, scan_dur = adapter->active_scan_time; } - (scan_chan_list + chan_idx)->min_scan_time = + scan_chan_list[chan_idx].min_scan_time = cpu_to_le16(scan_dur); - (scan_chan_list + chan_idx)->max_scan_time = + scan_chan_list[chan_idx].max_scan_time = cpu_to_le16(scan_dur); } -- GitLab From c70ca8cb9a7c6722d5bb6d428b6571921998c48d Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:10 +0100 Subject: [PATCH 2973/9938] mwifiex: factor out mwifiex_cancel_pending_scan_cmd Releasing the scan_pending lock in mwifiex_check_next_scan_command introduces a short window where pending scan commands can be removed or added before removing them all in mwifiex_cancel_pending_scan_cmd. I think this is safe, since the worst thing to happen is that a pending scan cmd is removed by the command handler. Adding new scan commands is not possible while one is pending, see scan_processing flag. Since all commands are removed from the queue anyway, we don't care if some commands are removed by a different code path earlier, the final state remains the same. I assume, that the critical section needed for the check has been extended over clearing the pending scan queue out of convenience. The lock was already held and releasing it and grab it again was just more work. It doesn't seem to be necessary because of concurrency. Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 43 +++++++++---------- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/scan.c | 23 +++------- .../wireless/marvell/mwifiex/sta_cmdresp.c | 13 +----- 4 files changed, 27 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index 6f0470646483..f5af525485f6 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -991,6 +991,23 @@ mwifiex_cmd_timeout_func(unsigned long function_context) adapter->if_ops.card_reset(adapter); } +void +mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; + unsigned long flags; + + /* Cancel all pending scan command */ + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + list_del(&cmd_node->list); + cmd_node->wait_q_enabled = false; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + } + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); +} + /* * This function cancels all the pending commands. * @@ -1029,16 +1046,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + mwifiex_cancel_pending_scan_cmd(adapter); if (adapter->scan_processing) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); @@ -1070,9 +1078,8 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) { - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + struct cmd_ctrl_node *cmd_node = NULL; unsigned long cmd_flags; - unsigned long scan_pending_q_flags; struct mwifiex_private *priv; int i; @@ -1094,17 +1101,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) mwifiex_recycle_cmd_node(adapter, cmd_node); } - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - scan_pending_q_flags); + mwifiex_cancel_pending_scan_cmd(adapter); if (adapter->scan_processing) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index a159fbef20cd..6306654d2799 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1042,6 +1042,7 @@ int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter); int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter); void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); +void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter); void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_node); diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 753d92a731af..36cc9cca95fc 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -619,8 +619,6 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, int ret = 0; struct mwifiex_chan_scan_param_set *tmp_chan_list; struct mwifiex_chan_scan_param_set *start_chan; - struct cmd_ctrl_node *cmd_node, *tmp_node; - unsigned long flags; u32 tlv_idx, rates_size, cmd_no; u32 total_scan_time; u32 done_early; @@ -777,16 +775,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, sizeof(struct mwifiex_ie_types_header) + rates_size; if (ret) { - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, - list) { - list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); + mwifiex_cancel_pending_scan_cmd(adapter); break; } } @@ -1949,12 +1938,13 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv) static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node, *tmp_node; + struct cmd_ctrl_node *cmd_node; unsigned long flags; spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); if (list_empty(&adapter->scan_pending_q)) { spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); @@ -1976,13 +1966,10 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) } } else if ((priv->scan_aborting && !priv->scan_request) || priv->scan_block) { - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + mwifiex_cancel_pending_scan_cmd(adapter); + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 434b9776db45..d18c7979d723 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -44,7 +44,6 @@ static void mwifiex_process_cmdresp_error(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_802_11_ps_mode_enh *pm; unsigned long flags; @@ -71,17 +70,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, break; case HostCmd_CMD_802_11_SCAN: case HostCmd_CMD_802_11_SCAN_EXT: - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + mwifiex_cancel_pending_scan_cmd(adapter); spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = false; -- GitLab From 85abfb1239ecda32222c161670667c7b2f6832be Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:11 +0100 Subject: [PATCH 2974/9938] mwifiex: make mwifiex_insert_cmd_to_free_q local static after factoring out mwifiex_cancel_pending_scan_cmd the function is not called outside of cmdevt file moved function to head of file to avoid forward declaration, also moved mwifiex_recycle_cmd_node since they are very similar Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 82 +++++++++---------- drivers/net/wireless/marvell/mwifiex/main.h | 2 - 2 files changed, 41 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index f5af525485f6..6bc2011d8609 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -104,6 +104,47 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, } } +/* + * This function returns a command to the command free queue. + * + * The function also calls the completion callback if required, before + * cleaning the command node and re-inserting it into the free queue. + */ +static void +mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + unsigned long flags; + + if (!cmd_node) + return; + + if (cmd_node->wait_q_enabled) + mwifiex_complete_cmd(adapter, cmd_node); + /* Clean the node */ + mwifiex_clean_cmd_node(adapter, cmd_node); + + /* Insert node into cmd_free_q */ + spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); + list_add_tail(&cmd_node->list, &adapter->cmd_free_q); + spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); +} + +/* This function reuses a command node. */ +void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; + + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + + atomic_dec(&adapter->cmd_pending); + mwifiex_dbg(adapter, CMD, + "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", + le16_to_cpu(host_cmd->command), + atomic_read(&adapter->cmd_pending)); +} + /* * This function sends a host command to the firmware. * @@ -613,47 +654,6 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, return ret; } -/* - * This function returns a command to the command free queue. - * - * The function also calls the completion callback if required, before - * cleaning the command node and re-inserting it into the free queue. - */ -void -mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - unsigned long flags; - - if (!cmd_node) - return; - - if (cmd_node->wait_q_enabled) - mwifiex_complete_cmd(adapter, cmd_node); - /* Clean the node */ - mwifiex_clean_cmd_node(adapter, cmd_node); - - /* Insert node into cmd_free_q */ - spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); - list_add_tail(&cmd_node->list, &adapter->cmd_free_q); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); -} - -/* This function reuses a command node. */ -void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; - - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - - atomic_dec(&adapter->cmd_pending); - mwifiex_dbg(adapter, CMD, - "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", - le16_to_cpu(host_cmd->command), - atomic_read(&adapter->cmd_pending)); -} - /* * This function queues a command to the command pending queue. * diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 6306654d2799..63069dd8b8e8 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1044,8 +1044,6 @@ void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter); -void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node); void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_node); -- GitLab From c157863d99797f6fed60e6e56d53afeb0bc3b436 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:42 -0400 Subject: [PATCH 2975/9938] rtl8xxxu: Reorder parts of init code to match the 8192eu vendor code flow In order to debug 8192eu support, reorder some init code to match the flow of the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index e36fda8c1ad3..d67b88665194 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7592,6 +7592,26 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; + /* RFSW Control - clear bit 14 ?? */ + if (priv->rtl_chip != RTL8723B) + rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); + /* 0x07000760 */ + if (priv->rtl_chip == RTL8192E) { + val32 = 0; + } else { + val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | + FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << + FPGA0_RF_BD_CTRL_SHIFT); + } + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + /* 0x860[6:5]= 00 - why? - this sets antenna B */ + if (priv->rtl_chip != RTL8192E) + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); + + priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, + RF6052_REG_MODE_AG); + /* * Chip specific quirks */ @@ -7653,21 +7673,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; - /* RFSW Control - clear bit 14 ?? */ - if (priv->rtl_chip != RTL8723B) - rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); - /* 0x07000760 */ - val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | - FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | - ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << - FPGA0_RF_BD_CTRL_SHIFT); - rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); - /* 0x860[6:5]= 00 - why? - this sets antenna B */ - rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66F60210); - - priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, - RF6052_REG_MODE_AG); - /* * Set RX page boundary */ -- GitLab From 59b24dad20d41c00b51f5ca549a9e83a53671bc9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:43 -0400 Subject: [PATCH 2976/9938] rtl8xxxu: Reorg more code to match the flow of the 8192eu vendor driver This further reorganizes the init code flow to match that of the 8192eu vendor driver. This helps diffing the register write log against that of the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 109 +++++++++--------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index d67b88665194..c6c41ba2a511 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7468,34 +7468,39 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) goto exit; } - dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); if (!macpower) { - ret = priv->fops->llt_init(priv, TX_TOTAL_PAGE_NUM); - if (ret) { - dev_warn(dev, "%s: LLT table init failed\n", __func__); - goto exit; - } + if (priv->ep_tx_normal_queue) + val8 = TX_PAGE_NUM_NORM_PQ; + else + val8 = 0; - /* - * Presumably this is for 8188EU as well - * Enable TX report and TX report timer - */ - if (priv->rtl_chip == RTL8723B) { - val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL); - val8 |= TX_REPORT_CTRL_TIMER_ENABLE; - rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); - /* Set MAX RPT MACID */ - rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL + 1, 0x02); - /* TX report Timer. Unit: 32us */ - rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, 0xcdf0); + rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); - /* tmp ps ? */ - val8 = rtl8xxxu_read8(priv, 0xa3); - val8 &= 0xf8; - rtl8xxxu_write8(priv, 0xa3, val8); - } + val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; + + if (priv->ep_tx_high_queue) + val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); + if (priv->ep_tx_low_queue) + val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); } + ret = rtl8xxxu_init_queue_priority(priv); + dev_dbg(dev, "%s: init_queue_priority %i\n", __func__, ret); + if (ret) + goto exit; + + /* + * Set RX page boundary + */ + if (priv->rtl_chip == RTL8723B) + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); + else if (priv->rtl_chip == RTL8192E) + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); + else + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); + ret = rtl8xxxu_download_firmware(priv); dev_dbg(dev, "%s: download_fiwmare %i\n", __func__, ret); if (ret) @@ -7634,22 +7639,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) } if (!macpower) { - if (priv->ep_tx_normal_queue) - val8 = TX_PAGE_NUM_NORM_PQ; - else - val8 = 0; - - rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); - - val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; - - if (priv->ep_tx_high_queue) - val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); - if (priv->ep_tx_low_queue) - val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); - - rtl8xxxu_write32(priv, REG_RQPN, val32); - /* * Set TX buffer boundary */ @@ -7668,20 +7657,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, REG_TDECTRL + 1, val8); } - ret = rtl8xxxu_init_queue_priority(priv); - dev_dbg(dev, "%s: init_queue_priority %i\n", __func__, ret); - if (ret) - goto exit; - - /* - * Set RX page boundary - */ - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); - else if (priv->rtl_chip == RTL8192E) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); - else - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); /* * Transfer page size is always 128 */ @@ -7693,6 +7668,34 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); rtl8xxxu_write8(priv, REG_PBP, val8); + dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); + if (!macpower) { + ret = priv->fops->llt_init(priv, TX_TOTAL_PAGE_NUM); + if (ret) { + dev_warn(dev, "%s: LLT table init failed\n", __func__); + goto exit; + } + + /* + * Presumably this is for 8188EU as well + * Enable TX report and TX report timer + */ + if (priv->rtl_chip == RTL8723B) { + val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL); + val8 |= TX_REPORT_CTRL_TIMER_ENABLE; + rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); + /* Set MAX RPT MACID */ + rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL + 1, 0x02); + /* TX report Timer. Unit: 32us */ + rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, 0xcdf0); + + /* tmp ps ? */ + val8 = rtl8xxxu_read8(priv, 0xa3); + val8 &= 0xf8; + rtl8xxxu_write8(priv, 0xa3, val8); + } + } + /* * Unit in 8 bytes, not obvious what it is used for */ -- GitLab From 89c2a097df34362a5e8373749a2f81ca2503b598 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:44 -0400 Subject: [PATCH 2977/9938] rtl8xxxu: Implement generic init_queue_reserved_page() function Longer term we should switch all the chips over to use this function instead of the random chip specific ifdef hacks. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 75 +++++++++++++++---- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 9 +++ .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 2 +- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c6c41ba2a511..a9290d469759 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7439,6 +7439,60 @@ static void rtl8723bu_init_statistics(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_OFDM0_FA_RSTC, val32); } +static void rtl8xxxu_old_init_queue_reserved_page(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + + if (priv->ep_tx_normal_queue) + val8 = TX_PAGE_NUM_NORM_PQ; + else + val8 = 0; + + rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); + + val32 = (TX_PAGE_NUM_PUBQ << RQPN_PUB_PQ_SHIFT) | RQPN_LOAD; + + if (priv->ep_tx_high_queue) + val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); + if (priv->ep_tx_low_queue) + val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); +} + +static void rtl8xxxu_init_queue_reserved_page(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_fileops *fops = priv->fops; + u32 hq, lq, nq, eq, pubq; + u32 val32; + + hq = 0; + lq = 0; + nq = 0; + eq = 0; + pubq = 0; + + if (priv->ep_tx_high_queue) + hq = fops->page_num_hi; + if (priv->ep_tx_low_queue) + lq = fops->page_num_lo; + if (priv->ep_tx_normal_queue) + nq = fops->page_num_norm; + + val32 = (nq << RQPN_NPQ_SHIFT) | (eq << RQPN_EPQ_SHIFT); + rtl8xxxu_write32(priv, REG_RQPN_NPQ, val32); + + pubq = fops->total_page_num - hq - lq - nq; + + val32 = RQPN_LOAD; + val32 |= (hq << RQPN_HI_PQ_SHIFT); + val32 |= (lq << RQPN_LO_PQ_SHIFT); + val32 |= (pubq << RQPN_PUB_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); +} + static int rtl8xxxu_init_device(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; @@ -7469,21 +7523,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) } if (!macpower) { - if (priv->ep_tx_normal_queue) - val8 = TX_PAGE_NUM_NORM_PQ; + if (priv->fops->total_page_num) + rtl8xxxu_init_queue_reserved_page(priv); else - val8 = 0; - - rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); - - val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; - - if (priv->ep_tx_high_queue) - val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); - if (priv->ep_tx_low_queue) - val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); - - rtl8xxxu_write32(priv, REG_RQPN, val32); + rtl8xxxu_old_init_queue_reserved_page(priv); } ret = rtl8xxxu_init_queue_priority(priv); @@ -9751,6 +9794,10 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .adda_2t_path_on_a = 0x0fc01616, .adda_2t_path_on_b = 0x0fc01616, .mactable = rtl8192e_mac_init_table, + .total_page_num = TX_TOTAL_PAGE_NUM_8192E, + .page_num_hi = TX_PAGE_NUM_HI_PQ_8192E, + .page_num_lo = TX_PAGE_NUM_LO_PQ_8192E, + .page_num_norm = TX_PAGE_NUM_NORM_PQ_8192E, }; static struct usb_device_id dev_table[] = { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 48a80fa9eac2..4545e10bede1 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -49,6 +49,11 @@ #define TX_PAGE_NUM_LO_PQ 0x02 #define TX_PAGE_NUM_NORM_PQ 0x02 +#define TX_PAGE_NUM_PUBQ_8192E 0xe7 +#define TX_PAGE_NUM_HI_PQ_8192E 0x08 +#define TX_PAGE_NUM_LO_PQ_8192E 0x0c +#define TX_PAGE_NUM_NORM_PQ_8192E 0x00 + #define RTL_FW_PAGE_SIZE 4096 #define RTL8XXXU_FIRMWARE_POLL_MAX 1000 @@ -1304,4 +1309,8 @@ struct rtl8xxxu_fileops { u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; struct rtl8xxxu_reg8val *mactable; + u8 total_page_num; + u8 page_num_hi; + u8 page_num_lo; + u8 page_num_norm; }; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index bb08a3939e46..a2cff2273e72 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -387,7 +387,7 @@ #define REG_RQPN 0x0200 #define RQPN_HI_PQ_SHIFT 0 #define RQPN_LO_PQ_SHIFT 8 -#define RQPN_NORM_PQ_SHIFT 16 +#define RQPN_PUB_PQ_SHIFT 16 #define RQPN_LOAD BIT(31) #define REG_FIFOPAGE 0x0204 -- GitLab From 0486e80b2a447fc94687505ca106091b15e61651 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:45 -0400 Subject: [PATCH 2978/9938] rtl8xxxu: Reorder chip quirks to follow flow of 8192eu driver Another flow order change to match the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index a9290d469759..9e9d3e351e65 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7660,27 +7660,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); - /* - * Chip specific quirks - */ - if (priv->rtl_chip == RTL8723A) { - /* Fix USB interface interference issue */ - rtl8xxxu_write8(priv, 0xfe40, 0xe0); - rtl8xxxu_write8(priv, 0xfe41, 0x8d); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); - - /* Reduce 80M spur */ - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - } else { - val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); - val32 |= TXDMA_OFFSET_DROP_DATA_EN; - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); - } - if (!macpower) { /* * Set TX buffer boundary @@ -7719,6 +7698,27 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) goto exit; } + /* + * Chip specific quirks + */ + if (priv->rtl_chip == RTL8723A) { + /* Fix USB interface interference issue */ + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x8d); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + } else { + val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); + val32 |= TXDMA_OFFSET_DROP_DATA_EN; + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); + } + /* * Presumably this is for 8188EU as well * Enable TX report and TX report timer -- GitLab From 2e7c7b347d93e41a2c4adf9350da6a351f585810 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:46 -0400 Subject: [PATCH 2979/9938] rtl8xxxu: Do not set REG_PBP on 8192eu The vendor driver does not set REG_PBP on 8192eu. Whether this is due to the device not supporting it or simply an oversight in the vendor driver is not clear. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 9e9d3e351e65..36bd4fc1aee8 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7688,7 +7688,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) else val8 = (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_RX_SHIFT) | (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); - rtl8xxxu_write8(priv, REG_PBP, val8); + if (priv->rtl_chip != RTL8192E) + rtl8xxxu_write8(priv, REG_PBP, val8); dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); if (!macpower) { -- GitLab From b816901b3d20e9e2941b130139d440953c3b0ba8 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:47 -0400 Subject: [PATCH 2980/9938] rtl8xxxu: Do not init FPGA0_TX_INFO on 8192eu Like the 8723bu, the vendor driver does not set FPGA0_TX_INFO for 8192eu in the init sequence. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 36bd4fc1aee8..ed8c594dd10d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7641,7 +7641,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) goto exit; /* RFSW Control - clear bit 14 ?? */ - if (priv->rtl_chip != RTL8723B) + if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); /* 0x07000760 */ if (priv->rtl_chip == RTL8192E) { -- GitLab From 5bdb6b0859887bad5c83639ca9fb2d5fd0d5a8a0 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:48 -0400 Subject: [PATCH 2981/9938] rtl8xxxu: Do not try to set REG_LEDCFG2 on 8192eu Presumably 8192eu devices do not have leds, so do not enable them. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ed8c594dd10d..99cf4aa97c0b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7880,9 +7880,11 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) priv->fops->set_tx_power(priv, 1, false); /* Let the 8051 take control of antenna setting */ - val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); - val8 |= LEDCFG2_DPDT_SELECT; - rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + if (priv->rtl_chip != RTL8192E) { + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 |= LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + } rtl8xxxu_write8(priv, REG_HWSEQ_CTRL, 0xff); -- GitLab From 57e42a21a941decc15f1198db64fe3959b066096 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:49 -0400 Subject: [PATCH 2982/9938] rtl8xxxu: Implment rtl8192e_set_tx_power() 8192eu is a 2T part, so setting TX power for path A only, as done by rtl8723bu_set_tx_power() is not sufficient. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 78 ++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 99cf4aa97c0b..7ab009fc5ecc 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2555,6 +2555,82 @@ rtl8723b_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs); } +static void +rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +{ + u32 val32, ofdm, mcs; + u8 cck, ofdmbase, mcsbase; + int group, tx_idx; + + tx_idx = 0; + group = rtl8723b_channel_to_group(channel); + + cck = priv->cck_tx_power_index_A[group]; + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32); + val32 &= 0xffff00ff; + val32 |= (cck << 8); + rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xff; + val32 |= ((cck << 8) | (cck << 16) | (cck << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + ofdmbase = priv->ht40_1s_tx_power_index_A[group]; + ofdmbase += priv->ofdm_tx_power_diff[tx_idx].a; + ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm); + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_A[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[tx_idx++].a; + else + mcsbase += priv->ht20_tx_power_diff[tx_idx++].a; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs); + + if (priv->tx_paths > 1) { + cck = priv->cck_tx_power_index_B[group]; + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK1_55_MCS32); + val32 &= 0xff; + val32 |= ((cck << 8) | (cck << 16) | (cck << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK1_55_MCS32, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xffffff00; + val32 |= cck; + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + ofdmbase = priv->ht40_1s_tx_power_index_B[group]; + ofdmbase += priv->ofdm_tx_power_diff[tx_idx].b; + ofdm = ofdmbase | ofdmbase << 8 | + ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_B[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[tx_idx++].b; + else + mcsbase += priv->ht20_tx_power_diff[tx_idx++].b; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs); + } +} + static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, enum nl80211_iftype linktype) { @@ -9784,7 +9860,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .parse_rx_desc = rtl8723bu_parse_rx_desc, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, - .set_tx_power = rtl8723b_set_tx_power, + .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8723bu_update_rate_mask, .report_connect = rtl8723bu_report_connect, .writeN_block_size = 128, -- GitLab From 55c0b6ae1e7b1a402f23ca8fafa1874f854b4834 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:50 -0400 Subject: [PATCH 2983/9938] rtl8xxxu: Use has_s0s1 for REG_S0S1 issues only Instead use tx_desc_size() to distinguish between gen1 (8723a/8192c/8188c) and gen2 (8723b/8192e) parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7ab009fc5ecc..8b0b6c92793c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2758,7 +2758,8 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) } else if (val32 & SYS_CFG_TYPE_ID) { bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); bonding &= HPON_FSM_BONDING_MASK; - if (priv->fops->has_s0s1) { + if (priv->fops->tx_desc_size == + sizeof(struct rtl8xxxu_txdesc40)) { if (bonding == HPON_FSM_BONDING_1T2R) { sprintf(priv->chip_name, "8191EU"); priv->rf_paths = 2; @@ -7993,7 +7994,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * This should enable thermal meter */ - if (priv->fops->has_s0s1) + if (priv->fops->tx_desc_size == sizeof(struct rtl8xxxu_txdesc40)) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_T_METER_8723B, 0x37cf8); else @@ -9867,7 +9868,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), - .has_s0s1 = 1, + .has_s0s1 = 0, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, -- GitLab From 2cb79eb74f08f0217a6c4f21ddc42627016771ff Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:51 -0400 Subject: [PATCH 2984/9938] rtl8xxxu: byteswap the entire RX descriptor for 24 byte RX descriptors This shouldn't affect little endian system, but may have prevented the driver working on big endian systems for devices with the larger 24 byte RX descriptors. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 8b0b6c92793c..6545012a49ad 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8832,7 +8832,13 @@ static int rtl8723au_parse_rx_desc(struct rtl8xxxu_priv *priv, { struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; struct rtl8723au_phy_stats *phy_stats; + __le32 *_rx_desc_le = (__le32 *)skb->data; + u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; + int i; + + for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) + _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); skb_pull(skb, sizeof(struct rtl8xxxu_rx_desc)); @@ -8873,7 +8879,13 @@ static int rtl8723bu_parse_rx_desc(struct rtl8xxxu_priv *priv, struct rtl8723bu_rx_desc *rx_desc = (struct rtl8723bu_rx_desc *)skb->data; struct rtl8723au_phy_stats *phy_stats; + __le32 *_rx_desc_le = (__le32 *)skb->data; + u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; + int i; + + for (i = 0; i < (sizeof(struct rtl8723bu_rx_desc) / sizeof(u32)); i++) + _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); skb_pull(skb, sizeof(struct rtl8723bu_rx_desc)); @@ -8967,12 +8979,7 @@ static void rtl8xxxu_rx_complete(struct urb *urb) struct sk_buff *skb = (struct sk_buff *)urb->context; struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); struct device *dev = &priv->udev->dev; - __le32 *_rx_desc_le = (__le32 *)skb->data; - u32 *_rx_desc = (u32 *)skb->data; - int rx_type, i; - - for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) - _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); + int rx_type; skb_put(skb, urb->actual_length); -- GitLab From a49c7ce183cd78c9786348f8dea3d8027cee8177 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:52 -0400 Subject: [PATCH 2985/9938] rtl8xxxu: Name RX descriptor types rxdesc16/rxdesc24 This caught a bug where too little memory was allocated for RX urbs for parts using 24 byte RX descriptors Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 38 +++++++++++-------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 5 ++- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6545012a49ad..4b309a60f5a1 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8826,21 +8826,22 @@ static void rtl8xxxu_rx_urb_work(struct work_struct *work) } } -static int rtl8723au_parse_rx_desc(struct rtl8xxxu_priv *priv, +static int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { - struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; + struct rtl8xxxu_rxdesc16 *rx_desc = + (struct rtl8xxxu_rxdesc16 *)skb->data; struct rtl8723au_phy_stats *phy_stats; __le32 *_rx_desc_le = (__le32 *)skb->data; u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; int i; - for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) + for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc16) / sizeof(u32)); i++) _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); - skb_pull(skb, sizeof(struct rtl8xxxu_rx_desc)); + skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc16)); phy_stats = (struct rtl8723au_phy_stats *)skb->data; @@ -8872,22 +8873,22 @@ static int rtl8723au_parse_rx_desc(struct rtl8xxxu_priv *priv, return RX_TYPE_DATA_PKT; } -static int rtl8723bu_parse_rx_desc(struct rtl8xxxu_priv *priv, +static int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { - struct rtl8723bu_rx_desc *rx_desc = - (struct rtl8723bu_rx_desc *)skb->data; + struct rtl8xxxu_rxdesc24 *rx_desc = + (struct rtl8xxxu_rxdesc24 *)skb->data; struct rtl8723au_phy_stats *phy_stats; __le32 *_rx_desc_le = (__le32 *)skb->data; u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; int i; - for (i = 0; i < (sizeof(struct rtl8723bu_rx_desc) / sizeof(u32)); i++) + for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++) _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); - skb_pull(skb, sizeof(struct rtl8723bu_rx_desc)); + skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24)); phy_stats = (struct rtl8723au_phy_stats *)skb->data; @@ -9018,14 +9019,15 @@ static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, { struct sk_buff *skb; int skb_size; - int ret; + int ret, rx_desc_sz; - skb_size = sizeof(struct rtl8xxxu_rx_desc) + RTL_RX_BUFFER_SIZE; + rx_desc_sz = priv->fops->rx_desc_size; + skb_size = rx_desc_sz + RTL_RX_BUFFER_SIZE; skb = __netdev_alloc_skb(NULL, skb_size, GFP_KERNEL); if (!skb) return -ENOMEM; - memset(skb->data, 0, sizeof(struct rtl8xxxu_rx_desc)); + memset(skb->data, 0, rx_desc_sz); usb_fill_bulk_urb(&rx_urb->urb, priv->udev, priv->pipe_in, skb->data, skb_size, rtl8xxxu_rx_complete, skb); usb_anchor_urb(&rx_urb->urb, &priv->rx_anchor); @@ -9779,7 +9781,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .llt_init = rtl8xxxu_init_llt_table, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, - .parse_rx_desc = rtl8723au_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, .set_tx_power = rtl8723a_set_tx_power, @@ -9789,6 +9791,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16), .adda_1t_init = 0x0b1b25a0, .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, @@ -9806,7 +9809,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, - .parse_rx_desc = rtl8723bu_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .init_aggregation = rtl8723bu_init_aggregation, .init_statistics = rtl8723bu_init_statistics, .enable_rf = rtl8723b_enable_rf, @@ -9818,6 +9821,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), .has_s0s1 = 1, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, @@ -9837,7 +9841,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .llt_init = rtl8xxxu_init_llt_table, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, - .parse_rx_desc = rtl8723au_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, .set_tx_power = rtl8723a_set_tx_power, @@ -9847,6 +9851,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16), .adda_1t_init = 0x0b1b25a0, .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, @@ -9865,7 +9870,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .llt_init = rtl8xxxu_auto_llt_table, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, - .parse_rx_desc = rtl8723bu_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, .set_tx_power = rtl8192e_set_tx_power, @@ -9875,6 +9880,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), .has_s0s1 = 0, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 4545e10bede1..2f0709ee0cb3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -101,7 +101,7 @@ enum rtl8xxxu_rx_type { RX_TYPE_ERROR = -1 }; -struct rtl8xxxu_rx_desc { +struct rtl8xxxu_rxdesc16 { #ifdef __LITTLE_ENDIAN u32 pktlen:14; u32 crc32:1; @@ -237,7 +237,7 @@ struct rtl8xxxu_rx_desc { #endif }; -struct rtl8723bu_rx_desc { +struct rtl8xxxu_rxdesc24 { #ifdef __LITTLE_ENDIAN u32 pktlen:14; u32 crc32:1; @@ -1303,6 +1303,7 @@ struct rtl8xxxu_fileops { u16 mbox_ext_reg; char mbox_ext_width; char tx_desc_size; + char rx_desc_size; char has_s0s1; u32 adda_1t_init; u32 adda_1t_path_on; -- GitLab From fe62171fb5cac42d0ff665e61b2735965e9efd45 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:53 -0400 Subject: [PATCH 2986/9938] rtl8xxxu: Remove misleading warning from rtl8192eu_phy_iqcalibrate() No actual code flow change, but no need to warn about something that isn't a prioblem. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 4b309a60f5a1..71d375c5ffa3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -5897,8 +5897,6 @@ static void rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, dev_dbg(dev, "%s: Path A RX IQK failed!\n", __func__); if (priv->rf_paths > 1) { - dev_warn(dev, "%s: Path B ongoing\n", __func__); - /* Path A into standby */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x10000); -- GitLab From 15f9dc99237df4b29f000464c35925bb0a56ead7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:54 -0400 Subject: [PATCH 2987/9938] rtl8xxxu: Remove unused 8723bu path B IQ calibration code The 8723bu is a combo WiFi/BT dongle, and path B is not used for WiFi, so no point in calibrating it. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 76 +------------------ 1 file changed, 3 insertions(+), 73 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 71d375c5ffa3..c355d27a26d0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4988,50 +4988,6 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) return result; } -#ifdef RTL8723BU_PATH_B -static int rtl8723bu_iqk_path_b(struct rtl8xxxu_priv *priv) -{ - u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, path_sel; - int result = 0; - - path_sel = rtl8xxxu_read32(priv, REG_S0S1_PATH_SWITCH); - - val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK); - val32 &= 0x000000ff; - rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - - /* One shot, path B LOK & IQK */ - rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000002); - rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000000); - - mdelay(1); - - /* Check failed */ - reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); - reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); - reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); - reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); - reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); - - if (!(reg_eac & BIT(31)) && - ((reg_eb4 & 0x03ff0000) != 0x01420000) && - ((reg_ebc & 0x03ff0000) != 0x00420000)) - result |= 0x01; - else - goto out; - - if (!(reg_eac & BIT(30)) && - (((reg_ec4 & 0x03ff0000) >> 16) != 0x132) && - (((reg_ecc & 0x03ff0000) >> 16) != 0x36)) - result |= 0x02; - else - dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", - __func__); -out: - return result; -} -#endif - static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv) { u32 reg_eac, reg_e94, reg_e9c; @@ -5619,20 +5575,6 @@ static void rtl8723bu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000); -#ifdef RTL8723BU_PATH_B - /* Set RF mode to standby Path B */ - if (priv->tx_paths > 1) - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x10000); -#endif - -#if 0 - /* Page B init */ - rtl8xxxu_write32(priv, REG_CONFIG_ANT_A, 0x0f600000); - - if (priv->tx_paths > 1) - rtl8xxxu_write32(priv, REG_CONFIG_ANT_B, 0x0f600000); -#endif - /* * RX IQ calibration setting for 8723B D cut large current issue * when leaving IPS @@ -5662,12 +5604,6 @@ static void rtl8723bu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); -#if 0 /* Only needed in restore case, we may need this when going to suspend */ - priv->RFCalibrateInfo.TxLOK[RF_A] = - rtl8xxxu_read_rfreg(priv, RF_A, - RF6052_REG_TXM_IDAC); -#endif - val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); result[t][0] = (val32 >> 16) & 0x3ff; @@ -6209,15 +6145,9 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_ED, val32); rtl8xxxu_write_rfreg(priv, RF_A, 0x43, 0x300bd); - if (priv->rf_paths > 1) { - dev_dbg(dev, "%s: beware 2T not yet supported\n", __func__); -#ifdef RTL8723BU_PATH_B - if (RF_Path == 0x0) //S1 - ODM_SetIQCbyRFpath(pDM_Odm, 0); - else //S0 - ODM_SetIQCbyRFpath(pDM_Odm, 1); -#endif - } + if (priv->rf_paths > 1) + dev_dbg(dev, "%s: 8723BU 2T not supported\n", __func__); + rtl8xxxu_prepare_calibrate(priv, 0); } -- GitLab From 9068308ad185a3c2c5d7beb77146b6df7b96b9c6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:55 -0400 Subject: [PATCH 2988/9938] rtl8xxxu: Correctly mask what was read from REG_CCK0_AFE_SETTING The old code incorrectly wiped out bits 0-23 by mistake when setting the RX path for 1T parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c355d27a26d0..d0330a8f32fb 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3814,7 +3814,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val32); val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); - val32 &= 0xff000000; + val32 &= 0x00ffffff; val32 |= 0x45000000; rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); -- GitLab From bd8fe40cc4f30f3f0982345135d97a676d1d3652 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:56 -0400 Subject: [PATCH 2989/9938] rtl8xxxu: Use descriptive bits for setting RX paths for 1T2R parts This reduce the use of magic values a little. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 +++- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index d0330a8f32fb..3c45ad0bdbca 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3814,8 +3814,10 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val32); val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); + val32 &= ~CCK0_AFE_RX_MASK; val32 &= 0x00ffffff; - val32 |= 0x45000000; + val32 |= 0x40000000; + val32 |= CCK0_AFE_RX_ANT_B; rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index a2cff2273e72..e7709a5bcb3a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -882,6 +882,10 @@ #define CCK0_SIDEBAND BIT(4) #define REG_CCK0_AFE_SETTING 0x0a04 +#define CCK0_AFE_RX_MASK 0x0f000000 +#define CCK0_AFE_RX_ANT_AB BIT(24) +#define CCK0_AFE_RX_ANT_A 0 +#define CCK0_AFE_RX_ANT_B (BIT(24) | BIT(26)) #define REG_CONFIG_ANT_A 0x0b68 #define REG_CONFIG_ANT_B 0x0b6c -- GitLab From cb8772504a27d7ada67840efe5439f3df3621e13 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:57 -0400 Subject: [PATCH 2990/9938] rtl8xxxu: Split rtl8xxxu_init_phy_bb() into device specific functions This reduces the if () clutter. Longer term it probably makes sense to split this between gen1 (8723au/8188cu/8192cu) and gen2 (8192eu/8723bu) devices. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 134 ++++++++++-------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 77 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3c45ad0bdbca..43359a394503 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3717,76 +3717,36 @@ static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, return 0; } -/* - * Most of this is black magic retrieved from the old rtl8723au driver - */ -static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) +static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) { - u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u8 val8; u16 val16; u32 val32; - /* - * Todo: The vendor driver maintains a table of PHY register - * addresses, which is initialized here. Do we need this? - */ - - if (priv->rtl_chip == RTL8723B) { - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | - SYS_FUNC_DIO_RF; - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - - rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00); - } else if (priv->rtl_chip == RTL8192E) { - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | - SYS_FUNC_DIO_RF; - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - } else { - val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); - udelay(2); - val8 |= AFE_PLL_320_ENABLE; - rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); - udelay(2); + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + udelay(2); + val8 |= AFE_PLL_320_ENABLE; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + udelay(2); - rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, 0xff); - udelay(2); + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, 0xff); + udelay(2); - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB; - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - } + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) { - /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */ - val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); - val32 &= ~AFE_XTAL_RF_GATE; - if (priv->has_bluetooth) - val32 &= ~AFE_XTAL_BT_GATE; - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); - } + val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); + val32 &= ~AFE_XTAL_RF_GATE; + if (priv->has_bluetooth) + val32 &= ~AFE_XTAL_BT_GATE; + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); /* 6. 0x1f[7:0] = 0x07 */ val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); - if (priv->rtl_chip == RTL8723B) { - /* - * Why? - */ - rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); - rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); - rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); - } else if (priv->rtl_chip == RTL8192E) { - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= (SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_DIO_RF | - SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB); - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; - rtl8xxxu_write8(priv, REG_RF_CTRL, val8); - rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); - } else if (priv->hi_pa) + if (priv->hi_pa) rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); else if (priv->tx_paths == 2) rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); @@ -3796,6 +3756,60 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) if (priv->rtl_chip == RTL8188C && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); +} + +static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + + rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00); + + /* 6. 0x1f[7:0] = 0x07 */ + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + + /* Why? */ + rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); + rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); + rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); +} + +static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + + /* 6. 0x1f[7:0] = 0x07 */ + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= (SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_DIO_RF | + SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB); + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); +} + +/* + * Most of this is black magic retrieved from the old rtl8723au driver + */ +static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u32 val32; + + priv->fops->init_phy_bb(priv); if (priv->tx_paths == 1 && priv->rx_paths == 2) { /* @@ -9709,6 +9723,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, + .init_phy_bb = rtl8723au_init_phy_bb, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9736,6 +9751,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .power_off = rtl8723bu_power_off, .reset_8051 = rtl8723bu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, + .init_phy_bb = rtl8723bu_init_phy_bb, .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, @@ -9769,6 +9785,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, + .init_phy_bb = rtl8723au_init_phy_bb, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9798,6 +9815,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, + .init_phy_bb = rtl8192eu_init_phy_bb, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 2f0709ee0cb3..28874fae750e 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1284,6 +1284,7 @@ struct rtl8xxxu_fileops { void (*power_off) (struct rtl8xxxu_priv *priv); void (*reset_8051) (struct rtl8xxxu_priv *priv); int (*llt_init) (struct rtl8xxxu_priv *priv, u8 last_tx_page); + void (*init_phy_bb) (struct rtl8xxxu_priv *priv); void (*phy_init_antenna_selection) (struct rtl8xxxu_priv *priv); void (*phy_iq_calibrate) (struct rtl8xxxu_priv *priv); void (*config_channel) (struct ieee80211_hw *hw); -- GitLab From ade0dedde11923e1d1f17bd81395b627821ad49c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:58 -0400 Subject: [PATCH 2991/9938] rtl8xxxu: Load AGC table before patching for 1T2R parts This should get the order right and avoid patching something that is later overwritten. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 43359a394503..21275078b6e2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3811,6 +3811,20 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) priv->fops->init_phy_bb(priv); + if (priv->rtl_chip == RTL8723B) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); + else if (priv->rtl_chip == RTL8192E) { + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_std_table); + } else if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); + if (priv->tx_paths == 1 && priv->rx_paths == 2) { /* * For 1T2R boards, patch the registers. @@ -3871,20 +3885,6 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_TX_TO_TX, val32); } - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); - else if (priv->rtl_chip == RTL8192E) { - if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_std_table); - } else if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); - if (priv->has_xtalk) { val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL); -- GitLab From c82f8d113e354588fe3351b10e0c1ea154f5c600 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:59 -0400 Subject: [PATCH 2992/9938] rtl8xxxu: Move loading of AGC table to device specific function This moves the loading of the AGC table into init_phy_bb() and reduces the if() clutter. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 21275078b6e2..baa53a14a30d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3756,6 +3756,11 @@ static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) if (priv->rtl_chip == RTL8188C && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); } static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) @@ -3777,6 +3782,8 @@ static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); + + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); } static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) @@ -3799,6 +3806,11 @@ static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8192eu_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8192eu_std_table); } /* @@ -3811,20 +3823,6 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) priv->fops->init_phy_bb(priv); - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); - else if (priv->rtl_chip == RTL8192E) { - if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_std_table); - } else if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); - if (priv->tx_paths == 1 && priv->rx_paths == 2) { /* * For 1T2R boards, patch the registers. -- GitLab From b84cac16f0f42b9b3f6210984c939f712c471026 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:00 -0400 Subject: [PATCH 2993/9938] rtl8xxxu: REG_LDOA15_CTRL is only used on gen1 parts Move setting it to rtl8723au_init_phy_bb() Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index baa53a14a30d..4ef8a05d924f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3719,7 +3719,7 @@ static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) { - u8 val8; + u8 val8, ldoa15, ldov12d, lpldo, ldohci12; u16 val16; u32 val32; @@ -3761,6 +3761,13 @@ static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); else rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); + + ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; + ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); + ldohci12 = 0x57; + lpldo = 1; + val32 = (lpldo << 24) | (ldohci12 << 16) | (ldov12d << 8) | ldoa15; + rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); } static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) @@ -3818,7 +3825,7 @@ static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) */ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) { - u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u8 val8; u32 val32; priv->fops->init_phy_bb(priv); @@ -3893,17 +3900,6 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); } - if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) { - ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; - ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); - ldohci12 = 0x57; - lpldo = 1; - val32 = (lpldo << 24) | (ldohci12 << 16) | - (ldov12d << 8) | ldoa15; - - rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); - } - if (priv->rtl_chip == RTL8192E) rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x000f81fb); -- GitLab From 24e8e7ec331d04c329048d3b85034c54d23f4fab Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:01 -0400 Subject: [PATCH 2994/9938] rtl8xxxu: Store device specific TRXFF boundary in the fileops This removes another case of ugly if () clutter Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 11 +++++------ drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 4ef8a05d924f..ef93f6285aa2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7552,12 +7552,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Set RX page boundary */ - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); - else if (priv->rtl_chip == RTL8192E) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); - else - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, priv->fops->trxff_boundary); ret = rtl8xxxu_download_firmware(priv); dev_dbg(dev, "%s: download_fiwmare %i\n", __func__, ret); @@ -9735,6 +9730,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .trxff_boundary = 0x27ff, .mactable = rtl8723a_mac_init_table, }; @@ -9767,6 +9763,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, .adda_2t_path_on_b = 0x01c00014, + .trxff_boundary = 0x3f7f, .mactable = rtl8723b_mac_init_table, }; @@ -9797,6 +9794,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .trxff_boundary = 0x27ff, .mactable = rtl8723a_mac_init_table, }; @@ -9828,6 +9826,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, .adda_2t_path_on_b = 0x0fc01616, + .trxff_boundary = 0x3cff, .mactable = rtl8192e_mac_init_table, .total_page_num = TX_TOTAL_PAGE_NUM_8192E, .page_num_hi = TX_PAGE_NUM_HI_PQ_8192E, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 28874fae750e..f66e20d4449b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1310,6 +1310,7 @@ struct rtl8xxxu_fileops { u32 adda_1t_path_on; u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; + u16 trxff_boundary; struct rtl8xxxu_reg8val *mactable; u8 total_page_num; u8 page_num_hi; -- GitLab From a77372069119061313b4815d119b5fbde0676dbb Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:02 -0400 Subject: [PATCH 2995/9938] rtl8xxxu: Do not backup RF_MODE_AG when it's never being used This was expired by the vendor driver, but we never ended up using the backed up value. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 3 --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ef93f6285aa2..c12a4c8cb63a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7667,9 +7667,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); - priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, - RF6052_REG_MODE_AG); - if (!macpower) { /* * Set TX buffer boundary diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index f66e20d4449b..b87cd2bef53c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1228,7 +1228,6 @@ struct rtl8xxxu_priv { u8 rf_paths; u8 rx_paths; u8 tx_paths; - u32 rf_mode_ag[2]; u32 rege94; u32 rege9c; u32 regeb4; -- GitLab From 9b323ee97af6e0c982b57ba0a21db14728dd4476 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:03 -0400 Subject: [PATCH 2996/9938] rtl8xxxu: Make PBP tuning a fileops parameter Rather than scattering the code with #ifdefs, use the fileops structure to hold device specific PBP values. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 17 ++++++++++------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 ++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c12a4c8cb63a..3e3ca28d5709 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7687,14 +7687,11 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) } /* - * Transfer page size is always 128 + * The vendor drivers set PBP for all devices, except 8192e. + * There is no explanation for this in any of the sources. */ - if (priv->rtl_chip == RTL8723B) - val8 = (PBP_PAGE_SIZE_256 << PBP_PAGE_SIZE_RX_SHIFT) | - (PBP_PAGE_SIZE_256 << PBP_PAGE_SIZE_TX_SHIFT); - else - val8 = (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_RX_SHIFT) | - (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); + val8 = (priv->fops->pbp_rx << PBP_PAGE_SIZE_RX_SHIFT) | + (priv->fops->pbp_tx << PBP_PAGE_SIZE_TX_SHIFT); if (priv->rtl_chip != RTL8192E) rtl8xxxu_write8(priv, REG_PBP, val8); @@ -9728,6 +9725,8 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, .trxff_boundary = 0x27ff, + .pbp_rx = PBP_PAGE_SIZE_128, + .pbp_tx = PBP_PAGE_SIZE_128, .mactable = rtl8723a_mac_init_table, }; @@ -9761,6 +9760,8 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .adda_2t_path_on_a = 0x01c00014, .adda_2t_path_on_b = 0x01c00014, .trxff_boundary = 0x3f7f, + .pbp_rx = PBP_PAGE_SIZE_256, + .pbp_tx = PBP_PAGE_SIZE_256, .mactable = rtl8723b_mac_init_table, }; @@ -9792,6 +9793,8 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, .trxff_boundary = 0x27ff, + .pbp_rx = PBP_PAGE_SIZE_128, + .pbp_tx = PBP_PAGE_SIZE_128, .mactable = rtl8723a_mac_init_table, }; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index b87cd2bef53c..8064b264ad0b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1310,6 +1310,8 @@ struct rtl8xxxu_fileops { u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; u16 trxff_boundary; + u8 pbp_rx; + u8 pbp_tx; struct rtl8xxxu_reg8val *mactable; u8 total_page_num; u8 page_num_hi; -- GitLab From 747bf237592cd7237e52692772a3fe3abeca0872 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:04 -0400 Subject: [PATCH 2997/9938] rtl8xxxu: Split USB quirks into gen1 and gen2 quirks This removes a bunch of if () spaghetti and re-applies the USB bus quirks for 8188/8192 that had gotten lost. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 95 +++++++++++-------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3e3ca28d5709..821be8725256 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6899,6 +6899,50 @@ static int rtl8xxxu_flush_fifo(struct rtl8xxxu_priv *priv) return retval; } +static void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv) +{ + /* Fix USB interface interference issue */ + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x8d); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + /* + * This sets TXDMA_OFFSET_DROP_DATA_EN (bit 9) as well as bits + * 8 and 5, for which I have found no documentation. + */ + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); + + /* + * Solve too many protocol error on USB bus. + * Can't do this for 8188/8192 UMC A cut parts + */ + if (!(!priv->chip_cut && priv->vendor_umc)) { + rtl8xxxu_write8(priv, 0xfe40, 0xe6); + rtl8xxxu_write8(priv, 0xfe41, 0x94); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x19); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe5); + rtl8xxxu_write8(priv, 0xfe41, 0x91); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe2); + rtl8xxxu_write8(priv, 0xfe41, 0x81); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + } +} + +static void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv) +{ + u32 val32; + + val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); + val32 |= TXDMA_OFFSET_DROP_DATA_EN; + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); +} + static int rtl8723au_power_on(struct rtl8xxxu_priv *priv) { u8 val8; @@ -7563,29 +7607,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; - /* Solve too many protocol error on USB bus */ - /* Can't do this for 8188/8192 UMC A cut parts */ - if (priv->rtl_chip == RTL8723A || - ((priv->rtl_chip == RTL8192C || priv->rtl_chip == RTL8191C || - priv->rtl_chip == RTL8188C) && - (priv->chip_cut || !priv->vendor_umc))) { - rtl8xxxu_write8(priv, 0xfe40, 0xe6); - rtl8xxxu_write8(priv, 0xfe41, 0x94); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - - rtl8xxxu_write8(priv, 0xfe40, 0xe0); - rtl8xxxu_write8(priv, 0xfe41, 0x19); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - - rtl8xxxu_write8(priv, 0xfe40, 0xe5); - rtl8xxxu_write8(priv, 0xfe41, 0x91); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - - rtl8xxxu_write8(priv, 0xfe40, 0xe2); - rtl8xxxu_write8(priv, 0xfe41, 0x81); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - } - if (priv->fops->phy_init_antenna_selection) priv->fops->phy_init_antenna_selection(priv); @@ -7604,6 +7625,12 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) case RTL8723A: rftable = rtl8723au_radioa_1t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); break; case RTL8723B: rftable = rtl8723bu_radioa_1t_init_table; @@ -7706,23 +7733,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Chip specific quirks */ - if (priv->rtl_chip == RTL8723A) { - /* Fix USB interface interference issue */ - rtl8xxxu_write8(priv, 0xfe40, 0xe0); - rtl8xxxu_write8(priv, 0xfe41, 0x8d); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); - - /* Reduce 80M spur */ - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - } else { - val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); - val32 |= TXDMA_OFFSET_DROP_DATA_EN; - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); - } + priv->fops->usb_quirks(priv); /* * Presumably this is for 8188EU as well @@ -9712,6 +9723,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, + .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, .report_connect = rtl8723au_report_connect, @@ -9746,6 +9758,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .init_statistics = rtl8723bu_init_statistics, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, + .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, .update_rate_mask = rtl8723bu_update_rate_mask, .report_connect = rtl8723bu_report_connect, @@ -9780,6 +9793,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, + .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, .report_connect = rtl8723au_report_connect, @@ -9813,6 +9827,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, + .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8723bu_update_rate_mask, .report_connect = rtl8723bu_report_connect, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 8064b264ad0b..da86f3f528b4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1293,6 +1293,7 @@ struct rtl8xxxu_fileops { void (*init_statistics) (struct rtl8xxxu_priv *priv); void (*enable_rf) (struct rtl8xxxu_priv *priv); void (*disable_rf) (struct rtl8xxxu_priv *priv); + void (*usb_quirks) (struct rtl8xxxu_priv *priv); void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel, bool ht40); void (*update_rate_mask) (struct rtl8xxxu_priv *priv, -- GitLab From 31133da702e4229acbd813350660f3053daa57c6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:05 -0400 Subject: [PATCH 2998/9938] rtl8xxxu: Remove unneeded 8192eu hack This removes an unneeded hack for 8192eu, and allows for initializing REG_FPGA0_XAB_RF_SW_CTRL at the same point as it is done for all other parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 821be8725256..5c56a4fc088b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7680,15 +7680,12 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* RFSW Control - clear bit 14 ?? */ if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); - /* 0x07000760 */ - if (priv->rtl_chip == RTL8192E) { - val32 = 0; - } else { - val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | - FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | - ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << - FPGA0_RF_BD_CTRL_SHIFT); - } + + val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | + FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << + FPGA0_RF_BD_CTRL_SHIFT); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); /* 0x860[6:5]= 00 - why? - this sets antenna B */ if (priv->rtl_chip != RTL8192E) -- GitLab From 46b378318de9e8e9d3b479e6adb2cec55c01c2ef Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:06 -0400 Subject: [PATCH 2999/9938] rtl8xxxu: 8192eu Fix bug in LDPC RX hang fix Write the adjusted value back to the correct register Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 5c56a4fc088b..6febda5d0c75 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7967,7 +7967,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, REG_8192E_LDOV12_CTRL, 0x75); val32 &= 0xfff00fff; val32 |= 0x0007e000; - rtl8xxxu_write32(priv, REG_8192E_LDOV12_CTRL, val32); + rtl8xxxu_write32(priv, REG_AFE_MISC, val32); } exit: return ret; -- GitLab From a39b683966559902dab4ea7d24b3223102d6971f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:07 -0400 Subject: [PATCH 3000/9938] Re-enable 8192eu support Revert "rtl8xxxu: Temporarily disable 8192eu device init" This reverts commit ccfe1e85322090649d2fae599e55300c1512bf15. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6febda5d0c75..39a033c02871 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3137,10 +3137,6 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) raw[i + 6], raw[i + 7]); } } - /* - * Temporarily disable 8192eu support - */ - return -EINVAL; return 0; } -- GitLab From e1d70c9b04000ee122c450627ed0614c676339a5 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:06 -0400 Subject: [PATCH 3001/9938] rtl8xxxu: Mark 0x050d:0x1004 as tested This dongle was tested successfully by Andrea Merello Reported-by: Andrea Merello Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 39a033c02871..037b64f7bea4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -9560,6 +9560,10 @@ static int rtl8xxxu_probe(struct usb_interface *interface, if (id->idProduct == 0x7811) untested = 0; break; + case 0x050d: + if (id->idProduct == 0x1004) + untested = 0; + break; default: break; } @@ -9864,6 +9868,9 @@ static struct usb_device_id dev_table[] = { /* Tested by Larry Finger */ {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7811, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +/* Tested by Andrea Merello */ +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, /* Currently untested 8188 series devices */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, @@ -9948,8 +9955,6 @@ static struct usb_device_id dev_table[] = { /* Currently untested 8192 series devices */ {USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0950, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, -{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff), - .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2102, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2103, 0xff, 0xff, 0xff), -- GitLab From 37ba4b6265ea0aa6c3369e4cf736ecbac31c40c9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 14 Apr 2016 16:37:07 -0400 Subject: [PATCH 3002/9938] rtl8xxxu: fix uninitialized return value in ret several functions are not initializing a return status in ret resulting in garbage to be returned instead of 0 for success. Currently, the calls to these functions are not checking the return, however, it seems prudent to return the correct status in case they are to be checked at a later date. Signed-off-by: Colin Ian King Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 037b64f7bea4..b88cf1631489 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6370,7 +6370,7 @@ static void rtl8xxxu_set_ampdu_min_space(struct rtl8xxxu_priv *priv, u8 density) static int rtl8xxxu_active_to_emu(struct rtl8xxxu_priv *priv) { u8 val8; - int count, ret; + int count, ret = 0; /* Start of rtl8723AU_card_enable_flow */ /* Act to Cardemu sequence*/ @@ -6420,7 +6420,7 @@ static int rtl8723bu_active_to_emu(struct rtl8xxxu_priv *priv) u8 val8; u16 val16; u32 val32; - int count, ret; + int count, ret = 0; /* Turn off RF */ rtl8xxxu_write8(priv, REG_RF_CTRL, 0); @@ -6477,7 +6477,7 @@ static int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv) { u8 val8; u8 val32; - int count, ret; + int count, ret = 0; rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); -- GitLab From 4062b8ffec36df80d808d3bc3352e0f9c9abd3de Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:08 -0400 Subject: [PATCH 3003/9938] rtl8xxxu: Move PHY RF init into device specific functions Load the RF table in init_phy_rf(), which allows for applying device specific RF hacks in the same place. Getting rid of more ugly if () clutter. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 133 +++++++++++------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 80 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index b88cf1631489..50ca3eb875bd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4015,6 +4015,80 @@ static int rtl8xxxu_init_phy_rf(struct rtl8xxxu_priv *priv, return 0; } +static int rtl8723au_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8723au_radioa_1t_init_table, RF_A); + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + + return ret; +} + +static int rtl8723bu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8723bu_radioa_1t_init_table, RF_A); + /* + * PHY LCK + */ + rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdfbe0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, 0x8c01); + msleep(200); + rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdffe0); + + return ret; +} + +#ifdef CONFIG_RTL8XXXU_UNTESTED +static int rtl8192cu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_rfregval *rftable; + int ret; + + if (priv->rtl_chip == RTL8188C) { + if (priv->hi_pa) + rftable = rtl8188ru_radioa_1t_highpa_table; + else + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + } else if (priv->rf_paths == 1) { + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + } else { + rftable = rtl8192cu_radioa_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + if (ret) + goto exit; + rftable = rtl8192cu_radiob_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); + } + +exit: + return ret; +} +#endif + +static int rtl8192eu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8192eu_radioa_init_table, RF_A); + if (ret) + goto exit; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8192eu_radiob_init_table, RF_B); + +exit: + return ret; +} + static int rtl8xxxu_llt_write(struct rtl8xxxu_priv *priv, u8 address, u8 data) { int ret = -EBUSY; @@ -7552,7 +7626,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; - struct rtl8xxxu_rfregval *rftable; bool macpower; int ret; u8 val8; @@ -7617,59 +7690,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; - switch(priv->rtl_chip) { - case RTL8723A: - rftable = rtl8723au_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - - /* Reduce 80M spur */ - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - break; - case RTL8723B: - rftable = rtl8723bu_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - /* - * PHY LCK - */ - rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdfbe0); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, 0x8c01); - msleep(200); - rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdffe0); - break; - case RTL8188C: - if (priv->hi_pa) - rftable = rtl8188ru_radioa_1t_highpa_table; - else - rftable = rtl8192cu_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - break; - case RTL8191C: - rftable = rtl8192cu_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - break; - case RTL8192C: - rftable = rtl8192cu_radioa_2t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - if (ret) - break; - rftable = rtl8192cu_radiob_2t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); - break; - case RTL8192E: - rftable = rtl8192eu_radioa_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - if (ret) - break; - rftable = rtl8192eu_radiob_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); - break; - default: - ret = -EINVAL; - } - + ret = priv->fops->init_phy_rf(priv); if (ret) goto exit; @@ -9715,6 +9736,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_rf = rtl8723au_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9747,6 +9769,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .reset_8051 = rtl8723bu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, .init_phy_bb = rtl8723bu_init_phy_bb, + .init_phy_rf = rtl8723bu_init_phy_rf, .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, @@ -9785,6 +9808,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_rf = rtl8192cu_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9819,6 +9843,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, .init_phy_bb = rtl8192eu_init_phy_bb, + .init_phy_rf = rtl8192eu_init_phy_rf, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index da86f3f528b4..3efbb6042ca2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1284,6 +1284,7 @@ struct rtl8xxxu_fileops { void (*reset_8051) (struct rtl8xxxu_priv *priv); int (*llt_init) (struct rtl8xxxu_priv *priv, u8 last_tx_page); void (*init_phy_bb) (struct rtl8xxxu_priv *priv); + int (*init_phy_rf) (struct rtl8xxxu_priv *priv); void (*phy_init_antenna_selection) (struct rtl8xxxu_priv *priv); void (*phy_iq_calibrate) (struct rtl8xxxu_priv *priv); void (*config_channel) (struct ieee80211_hw *hw); -- GitLab From b591e982bc44baf79f6ebb963eb47fe5e223e8e7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:09 -0400 Subject: [PATCH 3004/9938] rtl8xxxu: For devices with external PA (8188RU), limit CCK TX power Per the vendor driver, devices with an external PA needs limiting it's TX power to 0x20. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 50ca3eb875bd..578d1bf2c821 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2421,6 +2421,13 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) cck[0] = priv->cck_tx_power_index_A[group]; cck[1] = priv->cck_tx_power_index_B[group]; + if (priv->hi_pa) { + if (cck[0] > 0x20) + cck[0] = 0x20; + if (cck[1] > 0x20) + cck[1] = 0x20; + } + ofdm[0] = priv->ht40_1s_tx_power_index_A[group]; ofdm[1] = priv->ht40_1s_tx_power_index_B[group]; -- GitLab From 78a8421959af5e13dd96493e3b74d8d7c7406609 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:10 -0400 Subject: [PATCH 3005/9938] rtl8xxxu: Apply 8188RU workaround for UMC B cut parts correctly This patch was being missed since rtl_chip will never match RTL8188C if hi_pa is true. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 578d1bf2c821..bebe484c1dd6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3756,7 +3756,7 @@ static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) else rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); - if (priv->rtl_chip == RTL8188C && priv->hi_pa && + if (priv->rtl_chip == RTL8188R && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); -- GitLab From 8d95c8084f5621240006f730986a3346b7794863 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:11 -0400 Subject: [PATCH 3006/9938] rtl8xxxu: Use rtl_chip == RTL8188R to identify high PA parts This is simpler than checking for RTL8188C && hi_pa. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index bebe484c1dd6..8bf9a74bec63 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3054,6 +3054,7 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) if (efuse->rf_regulatory & 0x20) { sprintf(priv->chip_name, "8188RU"); + priv->rtl_chip = RTL8188R; priv->hi_pa = 1; } @@ -4059,11 +4060,8 @@ static int rtl8192cu_init_phy_rf(struct rtl8xxxu_priv *priv) struct rtl8xxxu_rfregval *rftable; int ret; - if (priv->rtl_chip == RTL8188C) { - if (priv->hi_pa) - rftable = rtl8188ru_radioa_1t_highpa_table; - else - rftable = rtl8192cu_radioa_1t_init_table; + if (priv->rtl_chip == RTL8188R) { + rftable = rtl8188ru_radioa_1t_highpa_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); } else if (priv->rf_paths == 1) { rftable = rtl8192cu_radioa_1t_init_table; @@ -7219,7 +7217,7 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) /* * Workaround for 8188RU LNA power leakage problem. */ - if (priv->rtl_chip == RTL8188C && priv->hi_pa) { + if (priv->rtl_chip == RTL8188R) { val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); val32 &= ~BIT(1); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); @@ -7323,7 +7321,7 @@ static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) /* * Workaround for 8188RU LNA power leakage problem. */ - if (priv->rtl_chip == RTL8188C && priv->hi_pa) { + if (priv->rtl_chip == RTL8188R) { val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); val32 |= BIT(1); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); -- GitLab From 8e25496090431553ce2200f53bbe194b9e0a19d2 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:12 -0400 Subject: [PATCH 3007/9938] rtl8xxxu: Match 8723bu power down sequence to vendor driver In particular set APS_FSMCO_WLON_RESET in the right register, and do not overwrite too much of REG_CR. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 8bf9a74bec63..5685fd744fbc 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6510,9 +6510,9 @@ static int rtl8723bu_active_to_emu(struct rtl8xxxu_priv *priv) rtl8xxxu_write16(priv, REG_GPIO_INTM, val16); /* Release WLON reset 0x04[16]= 1*/ - val32 = rtl8xxxu_read32(priv, REG_GPIO_INTM); + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); val32 |= APS_FSMCO_WLON_RESET; - rtl8xxxu_write32(priv, REG_GPIO_INTM, val32); + rtl8xxxu_write32(priv, REG_APS_FSMCO, val32); /* 0x0005[1] = 1 turn off MAC by HW state machine*/ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); @@ -7376,7 +7376,7 @@ static void rtl8723bu_power_off(struct rtl8xxxu_priv *priv) val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE; rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); - rtl8xxxu_write16(priv, REG_CR, 0x0000); + rtl8xxxu_write8(priv, REG_CR, 0x0000); rtl8xxxu_active_to_lps(priv); @@ -7393,7 +7393,15 @@ static void rtl8723bu_power_off(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); rtl8723bu_active_to_emu(priv); - rtl8xxxu_emu_to_disabled(priv); + + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(3); /* APS_FSMCO_HW_SUSPEND */ + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */ + val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); } #ifdef NEED_PS_TDMA -- GitLab From 8cae2f1da87c82b2a0031f4d19c142e7bc22f1d7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:13 -0400 Subject: [PATCH 3008/9938] rtl8xxxu: Unregister from mac80211 before shutting down the device This fixes a long standing bug where mac80211 would send disconnect packets to the device, after we had shut down the device. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 5685fd744fbc..2b71a2baaf9b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8003,13 +8003,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) return ret; } -static void rtl8xxxu_disable_device(struct ieee80211_hw *hw) -{ - struct rtl8xxxu_priv *priv = hw->priv; - - priv->fops->power_off(priv); -} - static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv, struct ieee80211_key_conf *key, const u8 *mac) { @@ -9726,13 +9719,14 @@ static void rtl8xxxu_disconnect(struct usb_interface *interface) hw = usb_get_intfdata(interface); priv = hw->priv; - rtl8xxxu_disable_device(hw); + ieee80211_unregister_hw(hw); + + priv->fops->power_off(priv); + usb_set_intfdata(interface, NULL); dev_info(&priv->udev->dev, "disconnecting\n"); - ieee80211_unregister_hw(hw); - kfree(priv->fw_data); mutex_destroy(&priv->usb_buf_mutex); mutex_destroy(&priv->h2c_mutex); -- GitLab From eb18806261da3de958b5569fb6d93ed0d773028b Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:14 -0400 Subject: [PATCH 3009/9938] rtl8xxxu: Update copyright statement to include 2016 Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 +- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 2b71a2baaf9b..de62f0ba11d7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1,7 +1,7 @@ /* * RTL8XXXU mac80211 USB driver * - * Copyright (c) 2014 - 2015 Jes Sorensen + * Copyright (c) 2014 - 2016 Jes Sorensen * * Portions, notably calibration code: * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 3efbb6042ca2..a1b076cdab6f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 - 2015 Jes Sorensen + * Copyright (c) 2014 - 2016 Jes Sorensen * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index e7709a5bcb3a..b0e0c642302c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 - 2015 Jes Sorensen + * Copyright (c) 2014 - 2016 Jes Sorensen * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as -- GitLab From b9f9d6992f8338e919c977e4e18473f57dcb874d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:15 -0400 Subject: [PATCH 3010/9938] rtl8xxxu: Set register 0xfe10 on rtl8192cu based parts This register is undocumented in the vendor code, but it is set unconditionally for all 8192cu/8188cu/8188ru parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index de62f0ba11d7..6280d3d0cec7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7214,6 +7214,8 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE; rtl8xxxu_write16(priv, REG_CR, val16); + rtl8xxxu_write8(priv, 0xfe10, 0x19); + /* * Workaround for 8188RU LNA power leakage problem. */ -- GitLab From 2fc0b8e5a17dc415508d918eeeb1aa47443ae642 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:16 -0400 Subject: [PATCH 3011/9938] rtl8xxxu: Add TX power base values for gen1 parts Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 118 +++++++++++++++--- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 26 ++++ 2 files changed, 130 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6280d3d0cec7..422e7fa6756d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -214,6 +214,72 @@ static struct rtl8xxxu_reg8val rtl8192e_mac_init_table[] = { {0xffff, 0xff}, }; +static struct rtl8xxxu_power_base rtl8188r_power_base = { + .reg_0e00 = 0x06080808, + .reg_0e04 = 0x00040406, + .reg_0e08 = 0x00000000, + .reg_086c = 0x00000000, + + .reg_0e10 = 0x04060608, + .reg_0e14 = 0x00020204, + .reg_0e18 = 0x04060608, + .reg_0e1c = 0x00020204, + + .reg_0830 = 0x06080808, + .reg_0834 = 0x00040406, + .reg_0838 = 0x00000000, + .reg_086c_2 = 0x00000000, + + .reg_083c = 0x04060608, + .reg_0848 = 0x00020204, + .reg_084c = 0x04060608, + .reg_0868 = 0x00020204, +}; + +static struct rtl8xxxu_power_base rtl8192c_power_base = { + .reg_0e00 = 0x07090c0c, + .reg_0e04 = 0x01020405, + .reg_0e08 = 0x00000000, + .reg_086c = 0x00000000, + + .reg_0e10 = 0x0b0c0c0e, + .reg_0e14 = 0x01030506, + .reg_0e18 = 0x0b0c0d0e, + .reg_0e1c = 0x01030509, + + .reg_0830 = 0x07090c0c, + .reg_0834 = 0x01020405, + .reg_0838 = 0x00000000, + .reg_086c_2 = 0x00000000, + + .reg_083c = 0x0b0c0d0e, + .reg_0848 = 0x01030509, + .reg_084c = 0x0b0c0d0e, + .reg_0868 = 0x01030509, +}; + +static struct rtl8xxxu_power_base rtl8723a_power_base = { + .reg_0e00 = 0x0a0c0c0c, + .reg_0e04 = 0x02040608, + .reg_0e08 = 0x00000000, + .reg_086c = 0x00000000, + + .reg_0e10 = 0x0a0c0d0e, + .reg_0e14 = 0x02040608, + .reg_0e18 = 0x0a0c0d0e, + .reg_0e1c = 0x02040608, + + .reg_0830 = 0x0a0c0c0c, + .reg_0834 = 0x02040608, + .reg_0838 = 0x00000000, + .reg_086c_2 = 0x00000000, + + .reg_083c = 0x0a0c0d0e, + .reg_0848 = 0x02040608, + .reg_084c = 0x0a0c0d0e, + .reg_0868 = 0x02040608, +}; + static struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = { {0x800, 0x80040000}, {0x804, 0x00000003}, {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, @@ -2410,6 +2476,7 @@ static void rtl8723bu_config_channel(struct ieee80211_hw *hw) static void rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) { + struct rtl8xxxu_power_base *power_base = priv->power_base; u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS]; u8 ofdmbase[RTL8723A_MAX_RF_PATHS], mcsbase[RTL8723A_MAX_RF_PATHS]; u32 val32, ofdm_a, ofdm_b, mcs_a, mcs_b; @@ -2418,8 +2485,8 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) group = rtl8723a_channel_to_group(channel); - cck[0] = priv->cck_tx_power_index_A[group]; - cck[1] = priv->cck_tx_power_index_B[group]; + cck[0] = priv->cck_tx_power_index_A[group] - 1; + cck[1] = priv->cck_tx_power_index_B[group] - 1; if (priv->hi_pa) { if (cck[0] > 0x20) @@ -2430,6 +2497,10 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) ofdm[0] = priv->ht40_1s_tx_power_index_A[group]; ofdm[1] = priv->ht40_1s_tx_power_index_B[group]; + if (ofdm[0]) + ofdm[0] -= 1; + if (ofdm[1]) + ofdm[1] -= 1; ofdmbase[0] = ofdm[0] + priv->ofdm_tx_power_index_diff[group].a; ofdmbase[1] = ofdm[1] + priv->ofdm_tx_power_index_diff[group].b; @@ -2485,27 +2556,39 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) ofdmbase[0] << 16 | ofdmbase[0] << 24; ofdm_b = ofdmbase[1] | ofdmbase[1] << 8 | ofdmbase[1] << 16 | ofdmbase[1] << 24; - rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm_b); - rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, + ofdm_a + power_base->reg_0e00); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, + ofdm_b + power_base->reg_0830); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, + ofdm_a + power_base->reg_0e04); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, + ofdm_b + power_base->reg_0834); mcs_a = mcsbase[0] | mcsbase[0] << 8 | mcsbase[0] << 16 | mcsbase[0] << 24; mcs_b = mcsbase[1] | mcsbase[1] << 8 | mcsbase[1] << 16 | mcsbase[1] << 24; - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, + mcs_a + power_base->reg_0e10); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, + mcs_b + power_base->reg_083c); - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, + mcs_a + power_base->reg_0e14); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, + mcs_b + power_base->reg_0848); - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, + mcs_a + power_base->reg_0e18); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, + mcs_b + power_base->reg_084c); - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, + mcs_a + power_base->reg_0e1c); for (i = 0; i < 3; i++) { if (i != 2) val8 = (mcsbase[0] > 8) ? (mcsbase[0] - 8) : 0; @@ -2513,7 +2596,8 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) val8 = (mcsbase[0] > 6) ? (mcsbase[0] - 6) : 0; rtl8xxxu_write8(priv, REG_OFDM0_XC_TX_IQ_IMBALANCE + i, val8); } - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, + mcs_b + power_base->reg_0868); for (i = 0; i < 3; i++) { if (i != 2) val8 = (mcsbase[1] > 8) ? (mcsbase[1] - 8) : 0; @@ -2920,6 +3004,9 @@ static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv) priv->has_xtalk = 1; priv->xtalk = priv->efuse_wifi.efuse8723.xtal_k & 0x3f; } + + priv->power_base = &rtl8723a_power_base; + dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name); dev_info(&priv->udev->dev, "Product: %.41s\n", @@ -3052,10 +3139,13 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) dev_info(&priv->udev->dev, "Product: %.20s\n", efuse->device_name); + priv->power_base = &rtl8192c_power_base; + if (efuse->rf_regulatory & 0x20) { sprintf(priv->chip_name, "8188RU"); priv->rtl_chip = RTL8188R; priv->hi_pa = 1; + priv->power_base = &rtl8188r_power_base; } if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index a1b076cdab6f..ebd1a6e7b813 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -629,6 +629,31 @@ struct rtl8xxxu_firmware_header { u8 data[0]; }; +/* + * 8723au/8192cu/8188ru required base power index offset tables. + */ +struct rtl8xxxu_power_base { + u32 reg_0e00; + u32 reg_0e04; + u32 reg_0e08; + u32 reg_086c; + + u32 reg_0e10; + u32 reg_0e14; + u32 reg_0e18; + u32 reg_0e1c; + + u32 reg_0830; + u32 reg_0834; + u32 reg_0838; + u32 reg_086c_2; + + u32 reg_083c; + u32 reg_0848; + u32 reg_084c; + u32 reg_0868; +}; + /* * The 8723au has 3 channel groups: 1-3, 4-9, and 10-14 */ @@ -1201,6 +1226,7 @@ struct rtl8xxxu_priv { struct rtl8723au_idx ofdm_tx_power_diff[RTL8723B_TX_COUNT]; struct rtl8723au_idx ht20_tx_power_diff[RTL8723B_TX_COUNT]; struct rtl8723au_idx ht40_tx_power_diff[RTL8723B_TX_COUNT]; + struct rtl8xxxu_power_base *power_base; u32 chip_cut:4; u32 rom_rev:4; u32 is_multi_func:1; -- GitLab From cabb550e2b97b8ea42124a93d4665ca052f3e3ff Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:17 -0400 Subject: [PATCH 3012/9938] rtl8xxxu: Fix 8188RU support The 8188RU does not like PAPE to be enabled, while all the other gen1 parts seem to require it. This makes the RTL8188RU able to associate for me. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 21 ++++++++++++------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 422e7fa6756d..cf7832bfdde8 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3145,6 +3145,7 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) sprintf(priv->chip_name, "8188RU"); priv->rtl_chip = RTL8188R; priv->hi_pa = 1; + priv->no_pape = 1; priv->power_base = &rtl8188r_power_base; } @@ -5555,9 +5556,12 @@ static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000); - val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); - val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); - rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + if (!priv->no_pape) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); + val32 |= (FPGA0_RF_PAPE | + (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + } val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE); val32 &= ~BIT(10); @@ -7804,11 +7808,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | - FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | - ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << - FPGA0_RF_BD_CTRL_SHIFT); - + FPGA0_RF_ANTSWB | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB) << FPGA0_RF_BD_CTRL_SHIFT); + if (!priv->no_pape) { + val32 |= (FPGA0_RF_PAPE | + (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + } rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + /* 0x860[6:5]= 00 - why? - this sets antenna B */ if (priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index ebd1a6e7b813..3e2643c79b56 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1287,6 +1287,7 @@ struct rtl8xxxu_priv { u32 bb_recovery_backup[RTL8XXXU_BB_REGS]; enum rtl8xxxu_rtl_chip rtl_chip; u8 pi_enabled:1; + u8 no_pape:1; u8 int_buf[USB_INTR_CONTENT_LENGTH]; }; -- GitLab From 6a62f9d5273dbc8ec776717a73a8a223b9e5f38e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:18 -0400 Subject: [PATCH 3013/9938] rtl8xxxu: Fix OOPS if user tries to add device via /sys This driver relies on driver_info in struct usb_device_id, so allowing adding a device via /sys/bus/usb/drivers/rtl8xxxu/new_id will cause a NULL pointer dereference. Set .no_dynamic_id = 1 to disable hot add of USB IDs. Reported-by: Xose Vazquez Perez Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index cf7832bfdde8..2d92e643fcd6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -10141,6 +10141,7 @@ static struct usb_driver rtl8xxxu_driver = { .probe = rtl8xxxu_probe, .disconnect = rtl8xxxu_disconnect, .id_table = dev_table, + .no_dynamic_id = 1, .disable_hub_initiated_lpm = 1, }; -- GitLab From ae5c01fd2fd816486169787440bf900d1b703230 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:19 -0400 Subject: [PATCH 3014/9938] rtl8xxxu: Implement rtl8192e_enable_rf() This implements an 8192eu specific enable_rf() function. The 8192eu is not a combo device, so no need for doing the BT specific bits needed by the 8723bu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 2d92e643fcd6..a86b5c40efe4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7517,6 +7517,43 @@ static void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, } #endif +static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv) +{ + u32 val32; + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG); + val8 |= BIT(5); + rtl8xxxu_write8(priv, REG_GPIO_MUXCFG, val8); + + /* + * WLAN action by PTA + */ + rtl8xxxu_write8(priv, REG_WLAN_ACT_CONTROL_8723B, 0x04); + + val32 = rtl8xxxu_read32(priv, REG_PWR_DATA); + val32 |= PWR_DATA_EEPRPAD_RFE_CTRL_EN; + rtl8xxxu_write32(priv, REG_PWR_DATA, val32); + + val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER); + val32 |= (BIT(0) | BIT(1)); + rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32); + + rtl8xxxu_write8(priv, REG_RFE_CTRL_ANTA_SRC, 0x77); + + val32 = rtl8xxxu_read32(priv, REG_LEDCFG0); + val32 &= ~BIT(24); + val32 |= BIT(23); + rtl8xxxu_write32(priv, REG_LEDCFG0, val32); + + /* + * Fix external switch Main->S1, Aux->S0 + */ + val8 = rtl8xxxu_read8(priv, REG_PAD_CTRL1); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8); +} + static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv) { struct h2c_cmd h2c; @@ -9953,7 +9990,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, - .enable_rf = rtl8723b_enable_rf, + .enable_rf = rtl8192e_enable_rf, .disable_rf = rtl8723b_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, -- GitLab From 265697eb2f1b6c472c4b09ff7e008bc8ab145b4f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:20 -0400 Subject: [PATCH 3015/9938] rtl8xxxu: Pause TX before calling disable_rf() All the disable_rf() functions were setting REG_TXPAUSE to 0xff to stop transmission. Do it centrally before calling disable_rf() instead. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index a86b5c40efe4..928ca56f751c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2125,8 +2125,6 @@ static void rtl8723a_disable_rf(struct rtl8xxxu_priv *priv) u8 sps0; u32 val32; - rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); - sps0 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); /* RF RX code for preamble power saving */ @@ -7665,8 +7663,6 @@ static void rtl8723b_disable_rf(struct rtl8xxxu_priv *priv) { u32 val32; - rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); - val32 = rtl8xxxu_read32(priv, REG_RX_WAIT_CCA); val32 &= ~(BIT(22) | BIT(23)); rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val32); @@ -9591,6 +9587,8 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw) if (priv->usb_interrupts) usb_kill_anchored_urbs(&priv->int_anchor); + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + priv->fops->disable_rf(priv); /* -- GitLab From 171a900c4eb7b34667e64ffed316a50425b45581 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:21 -0400 Subject: [PATCH 3016/9938] rtl8xxxu: MAINTAINERS: Update to point to the active devel branch Update the MAINTAINERS info to reflect active development of the rtl8xxxu driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4851f02281d6..6ac970ba54b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9490,7 +9490,7 @@ F: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/ RTL8XXXU WIRELESS DRIVER (rtl8xxxu) M: Jes Sorensen L: linux-wireless@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8723au-mac80211 +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel S: Maintained F: drivers/net/wireless/realtek/rtl8xxxu/ -- GitLab From 0883e820a0ac18e04f036dbebc3580351d7fd6cf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 Apr 2016 16:37:17 -0300 Subject: [PATCH 3017/9938] perf record: Export record_opts based callchain parsing helper To be able to call it outside option parsing, like when setting a default --call-graph parameter in 'perf trace' when just --min-stack is used. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-xay69plylwibpb3l4isrpl1k@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 35 ++++++++++++++++++++--------------- tools/perf/util/callchain.h | 6 ++++++ 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 3239a6ec9d23..5b4758a08a49 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -930,45 +930,50 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) return status; } -static void callchain_debug(void) +static void callchain_debug(struct callchain_param *callchain) { static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; - pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); + pr_debug("callchain: type %s\n", str[callchain->record_mode]); - if (callchain_param.record_mode == CALLCHAIN_DWARF) + if (callchain->record_mode == CALLCHAIN_DWARF) pr_debug("callchain: stack dump size %d\n", - callchain_param.dump_size); + callchain->dump_size); } -int record_parse_callchain_opt(const struct option *opt, - const char *arg, - int unset) +int record_opts__parse_callchain(struct record_opts *record, + struct callchain_param *callchain, + const char *arg, bool unset) { int ret; - struct record_opts *record = (struct record_opts *)opt->value; - record->callgraph_set = true; - callchain_param.enabled = !unset; + callchain->enabled = !unset; /* --no-call-graph */ if (unset) { - callchain_param.record_mode = CALLCHAIN_NONE; + callchain->record_mode = CALLCHAIN_NONE; pr_debug("callchain: disabled\n"); return 0; } - ret = parse_callchain_record_opt(arg, &callchain_param); + ret = parse_callchain_record_opt(arg, callchain); if (!ret) { /* Enable data address sampling for DWARF unwind. */ - if (callchain_param.record_mode == CALLCHAIN_DWARF) + if (callchain->record_mode == CALLCHAIN_DWARF) record->sample_address = true; - callchain_debug(); + callchain_debug(callchain); } return ret; } +int record_parse_callchain_opt(const struct option *opt, + const char *arg, + int unset) +{ + return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); +} + int record_callchain_opt(const struct option *opt, const char *arg __maybe_unused, int unset __maybe_unused) @@ -981,7 +986,7 @@ int record_callchain_opt(const struct option *opt, if (callchain_param.record_mode == CALLCHAIN_NONE) callchain_param.record_mode = CALLCHAIN_FP; - callchain_debug(); + callchain_debug(&callchain_param); return 0; } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index cae5a7b1f5c8..65e2a4f7cb4e 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -212,6 +212,12 @@ struct hist_entry; int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); int record_callchain_opt(const struct option *opt, const char *arg, int unset); +struct record_opts; + +int record_opts__parse_callchain(struct record_opts *record, + struct callchain_param *callchain, + const char *arg, bool unset); + int sample__resolve_callchain(struct perf_sample *sample, struct callchain_cursor *cursor, struct symbol **parent, struct perf_evsel *evsel, struct addr_location *al, -- GitLab From 056149932602ef905f1e26fc4fe242ef0533a597 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 Apr 2016 16:41:19 -0300 Subject: [PATCH 3018/9938] perf trace: Make --(min,max}-stack imply "--call-graph dwarf" If one uses: # perf trace --min-stack 16 Then it implicitly means that callgraphs should be enabled, and the best option in terms of widespread availability is "dwarf". Further work needed to choose a better alternative, LBR, in capable systems. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-xtjmnpkyk42npekxz3kynzmx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 6 ++++++ tools/perf/builtin-trace.c | 13 ++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 4e8baa75a32e..146c6db21cbf 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -136,12 +136,18 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. not limiting, the overhead of callchains needs to be set via the knobs in --call-graph dwarf. + Implies '--call-graph dwarf' when --call-graph not present on the + command line, on systems where DWARF unwinding was built in. + Default: 127 --min-stack:: Set the stack depth limit when parsing the callchain, anything below the specified depth will be ignored. Disabled by default. + Implies '--call-graph dwarf' when --call-graph not present on the + command line, on systems where DWARF unwinding was built in. + --proc-map-timeout:: When processing pre-existing threads /proc/XXX/mmap, it may take a long time, because the file may be huge. A time out is needed in such cases. diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6a64cb1344c7..19f5100acc1d 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3047,7 +3047,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) .show_comm = true, .trace_syscalls = true, .kernel_syscallchains = false, - .max_stack = PERF_MAX_STACK_DEPTH, + .max_stack = UINT_MAX, }; const char *output_name = NULL; const char *ev_qualifier_str = NULL; @@ -3109,6 +3109,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) "per thread proc mmap processing timeout in ms"), OPT_END() }; + bool max_stack_user_set = true; const char * const trace_subcommands[] = { "record", NULL }; int err; char bf[BUFSIZ]; @@ -3142,6 +3143,16 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) trace.opts.sample_time = true; } + if (trace.max_stack == UINT_MAX) { + trace.max_stack = PERF_MAX_STACK_DEPTH; + max_stack_user_set = false; + } + +#ifdef HAVE_DWARF_UNWIND_SUPPORT + if ((trace.min_stack || max_stack_user_set) && !trace.opts.callgraph_set) + record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false); +#endif + if (trace.opts.callgraph_set) symbol_conf.use_callchain = true; -- GitLab From 634696b197411e7a95b346d6e5c21841f29fcedd Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Fri, 15 Apr 2016 13:33:03 -0400 Subject: [PATCH 3019/9938] tipc: guarantee peer bearer id exchange after reboot When a link endpoint is going down locally, e.g., because its interface is being stopped, it will spontaneously send out a RESET message to its peer, informing it about this fact. This saves the peer from detecting the failure via probing, and hence gives both speedier and less resource consuming failure detection on the peer side. According to the link FSM, a receiver of a RESET message, ignoring the reason for it, must now consider the sender ready to come back up, and starts periodically sending out ACTIVATE messages to the peer in order to re-establish the link. Also, according to the FSM, the receiver of an ACTIVATE message can now go directly to state ESTABLISHED and start sending regular traffic packets. This is a well-proven and robust FSM. However, in the case of a reboot, there is a small possibilty that link endpoint on the rebooted node may have been re-created with a new bearer identity between the moment it sent its (pre-boot) RESET and the moment it receives the ACTIVATE from the peer. The new bearer identity cannot be known by the peer according to this scenario, since traffic headers don't convey such information. This is a problem, because both endpoints need to know the correct value of the peer's bearer id at any moment in time in order to be able to produce correct link events for their users. The only way to guarantee this is to enforce a full setup message exchange (RESET + ACTIVATE) even after the reboot, since those messages carry the bearer idientity in their header. In this commit we do this by introducing and setting a "stopping" bit in the header of the spontaneously generated RESET messages, informing the peer that the sender will not be immediately ready to re-establish the link. A receiver seeing this bit must act as if this were a locally detected connectivity failure, and hence has to go through a full two- way setup message exchange before any link can be re-established. Although never reported, this problem seems to have always been around. This protocol addition is fully backwards compatible. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/link.c | 10 +++++++++- net/tipc/msg.h | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 7d2bb3e70baa..8b98fafc88a4 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1140,11 +1140,17 @@ int tipc_link_build_ack_msg(struct tipc_link *l, struct sk_buff_head *xmitq) void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq) { int mtyp = RESET_MSG; + struct sk_buff *skb; if (l->state == LINK_ESTABLISHING) mtyp = ACTIVATE_MSG; tipc_link_build_proto_msg(l, mtyp, 0, 0, 0, 0, xmitq); + + /* Inform peer that this endpoint is going down if applicable */ + skb = skb_peek_tail(xmitq); + if (skb && (l->state == LINK_RESET)) + msg_set_peer_stopping(buf_msg(skb), 1); } /* tipc_link_build_nack_msg: prepare link nack message for transmission @@ -1411,7 +1417,9 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, l->priority = peers_prio; /* ACTIVATE_MSG serves as PEER_RESET if link is already down */ - if ((mtyp == RESET_MSG) || !link_is_up(l)) + if (msg_peer_stopping(hdr)) + rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); + else if ((mtyp == RESET_MSG) || !link_is_up(l)) rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); /* ACTIVATE_MSG takes up link if it was already locally reset */ diff --git a/net/tipc/msg.h b/net/tipc/msg.h index f34f639df643..58bf51541813 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -715,6 +715,16 @@ static inline void msg_set_redundant_link(struct tipc_msg *m, u32 r) msg_set_bits(m, 5, 12, 0x1, r); } +static inline u32 msg_peer_stopping(struct tipc_msg *m) +{ + return msg_bits(m, 5, 13, 0x1); +} + +static inline void msg_set_peer_stopping(struct tipc_msg *m, u32 s) +{ + msg_set_bits(m, 5, 13, 0x1, s); +} + static inline char *msg_media_addr(struct tipc_msg *m) { return (char *)&m->hdr[TIPC_MEDIA_INFO_OFFSET]; -- GitLab From 88e8ac7000dc7ccf99975cc4070907e26a1027f9 Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Fri, 15 Apr 2016 13:33:04 -0400 Subject: [PATCH 3020/9938] tipc: reduce transmission rate of reset messages when link is down When a link is down, it will continuously try to re-establish contact with the peer by sending out a RESET or an ACTIVATE message at each timeout interval. The default value for this interval is currently 375 ms. This is wasteful, and may become a problem in very large clusters with dozens or hundreds of nodes being down simultaneously. We now introduce a simple backoff algorithm for these cases. The first five messages are sent at default rate; thereafter a message is sent only each 16th timer interval. This will cover the vast majority of link recycling cases, since the endpoint starting last will transmit at the higher speed, and the link should normally be established well be before the rate needs to be reduced. The only case where we will see a degradation of link re-establishment times is when the endpoints remain intact, and a glitch in the transmission media is causing the link reset. We will then experience a worst-case re-establishing time of 6 seconds, something we deem acceptable. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/link.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 8b98fafc88a4..238b12526b58 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -140,6 +140,7 @@ struct tipc_link { char if_name[TIPC_MAX_IF_NAME]; u32 priority; char net_plane; + u16 rst_cnt; /* Failover/synch */ u16 drop_point; @@ -699,8 +700,6 @@ static void link_profile_stats(struct tipc_link *l) l->stats.msg_length_profile[6]++; } -/* tipc_link_timeout - perform periodic task as instructed from node timeout - */ /* tipc_link_timeout - perform periodic task as instructed from node timeout */ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) @@ -730,7 +729,8 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) l->silent_intv_cnt++; break; case LINK_RESET: - xmit = true; + xmit = l->rst_cnt++ <= 4; + xmit |= !(l->rst_cnt % 16); mtyp = RESET_MSG; break; case LINK_ESTABLISHING: @@ -833,6 +833,7 @@ void tipc_link_reset(struct tipc_link *l) l->rcv_nxt = 1; l->acked = 0; l->silent_intv_cnt = 0; + l->rst_cnt = 0; l->stats.recv_info = 0; l->stale_count = 0; l->bc_peer_is_up = false; -- GitLab From 42b18f605feaf7aa1825b35656bb7d6fdc132b45 Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Fri, 15 Apr 2016 13:33:05 -0400 Subject: [PATCH 3021/9938] tipc: refactor function tipc_link_timeout() The function tipc_link_timeout() is unnecessary complex, and can easily be made more readable. We do that with this commit. The only functional change is that we remove a redundant test for whether the broadcast link is up or not. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/link.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 238b12526b58..774ad3cd1f1c 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -704,37 +704,33 @@ static void link_profile_stats(struct tipc_link *l) */ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) { - int rc = 0; - int mtyp = STATE_MSG; - bool xmit = false; - bool prb = false; + int mtyp, rc = 0; + bool state = false; + bool probe = false; + bool setup = false; u16 bc_snt = l->bc_sndlink->snd_nxt - 1; u16 bc_acked = l->bc_rcvlink->acked; - bool bc_up = link_is_up(l->bc_rcvlink); link_profile_stats(l); switch (l->state) { case LINK_ESTABLISHED: case LINK_SYNCHING: - if (!l->silent_intv_cnt) { - if (bc_up && (bc_acked != bc_snt)) - xmit = true; - } else if (l->silent_intv_cnt <= l->abort_limit) { - xmit = true; - prb = true; - } else { - rc |= tipc_link_fsm_evt(l, LINK_FAILURE_EVT); - } - l->silent_intv_cnt++; + if (l->silent_intv_cnt > l->abort_limit) + return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); + mtyp = STATE_MSG; + state = bc_acked != bc_snt; + probe = l->silent_intv_cnt; + if (probe) + l->silent_intv_cnt++; break; case LINK_RESET: - xmit = l->rst_cnt++ <= 4; - xmit |= !(l->rst_cnt % 16); + setup = l->rst_cnt++ <= 4; + setup |= !(l->rst_cnt % 16); mtyp = RESET_MSG; break; case LINK_ESTABLISHING: - xmit = true; + setup = true; mtyp = ACTIVATE_MSG; break; case LINK_PEER_RESET: @@ -745,8 +741,8 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) break; } - if (xmit) - tipc_link_build_proto_msg(l, mtyp, prb, 0, 0, 0, xmitq); + if (state || probe || setup) + tipc_link_build_proto_msg(l, mtyp, probe, 0, 0, 0, xmitq); return rc; } -- GitLab From de7e07f9ee14f47d05aa43046404c2904f0247dc Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Fri, 15 Apr 2016 13:33:06 -0400 Subject: [PATCH 3022/9938] tipc: ensure that first packets on link are sent in order In some link establishment scenarios we see that packet #2 may be sent out before packet #1, forcing the receiver to demand retransmission of the missing packet. This is harmless, but may cause confusion among people tracing the packet flow. Since this is extremely easy to fix, we do so by adding en extra send call to the bearer immediately after the link has come up. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/node.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/tipc/node.c b/net/tipc/node.c index ace178fd3850..b00e12cda66c 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -581,8 +581,12 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, static void tipc_node_link_up(struct tipc_node *n, int bearer_id, struct sk_buff_head *xmitq) { + struct tipc_media_addr *maddr; + tipc_node_write_lock(n); __tipc_node_link_up(n, bearer_id, xmitq); + maddr = &n->links[bearer_id].maddr; + tipc_bearer_xmit(n->net, bearer_id, xmitq, maddr); tipc_node_write_unlock(n); } -- GitLab From 34b9cd64c889d41eb990aec33fc185cab706c9b0 Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Fri, 15 Apr 2016 13:33:07 -0400 Subject: [PATCH 3023/9938] tipc: let first message on link be a state message According to the link FSM, a received traffic packet can take a link from state ESTABLISHING to ESTABLISHED, but the link can still not be fully set up in one atomic operation. This means that even if the the very first packet on the link is a traffic packet with sequence number 1 (one), it has to be dropped and retransmitted. This can be avoided if we let the mentioned packet be preceded by a LINK_PROTOCOL/STATE message, which takes up the endpoint before the arrival of the traffic. We add this small feature in this commit. This is a fully compatible change. Acked-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/link.c | 6 +++--- net/tipc/link.h | 2 +- net/tipc/node.c | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 774ad3cd1f1c..2e28a7d7e802 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1107,12 +1107,12 @@ static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked) return released; } -/* tipc_link_build_ack_msg: prepare link acknowledge message for transmission +/* tipc_link_build_state_msg: prepare link state message for transmission * * Note that sending of broadcast ack is coordinated among nodes, to reduce * risk of ack storms towards the sender */ -int tipc_link_build_ack_msg(struct tipc_link *l, struct sk_buff_head *xmitq) +int tipc_link_build_state_msg(struct tipc_link *l, struct sk_buff_head *xmitq) { if (!l) return 0; @@ -1222,7 +1222,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, if (!tipc_data_input(l, skb, l->inputq)) rc |= tipc_link_input(l, skb, l->inputq); if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN)) - rc |= tipc_link_build_ack_msg(l, xmitq); + rc |= tipc_link_build_state_msg(l, xmitq); if (unlikely(rc & ~TIPC_LINK_SND_BC_ACK)) break; } while ((skb = __skb_dequeue(defq))); diff --git a/net/tipc/link.h b/net/tipc/link.h index 6a94175ee20a..d7e9d42fcb2d 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -123,7 +123,7 @@ int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq); int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, struct sk_buff_head *xmitq); -int tipc_link_build_ack_msg(struct tipc_link *l, struct sk_buff_head *xmitq); +int tipc_link_build_state_msg(struct tipc_link *l, struct sk_buff_head *xmitq); void tipc_link_add_bc_peer(struct tipc_link *snd_l, struct tipc_link *uc_l, struct sk_buff_head *xmitq); diff --git a/net/tipc/node.c b/net/tipc/node.c index b00e12cda66c..68d9f7b8485c 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -545,6 +545,9 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, pr_debug("Established link <%s> on network plane %c\n", tipc_link_name(nl), tipc_link_plane(nl)); + /* Ensure that a STATE message goes first */ + tipc_link_build_state_msg(nl, xmitq); + /* First link? => give it both slots */ if (!ol) { *slot0 = bearer_id; @@ -1283,7 +1286,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id /* Broadcast ACKs are sent on a unicast link */ if (rc & TIPC_LINK_SND_BC_ACK) { tipc_node_read_lock(n); - tipc_link_build_ack_msg(le->link, &xmitq); + tipc_link_build_state_msg(le->link, &xmitq); tipc_node_read_unlock(n); } -- GitLab From ac18dd9e842294377dbaf1e8d169493567a81fa1 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 9 Apr 2016 17:27:45 +0530 Subject: [PATCH 3024/9938] qlge: Replace create_singlethread_workqueue with alloc_ordered_workqueue Replace deprecated create_singlethread_workqueue with alloc_ordered_workqueue. Work items include getting tx/rx frame sizes, resetting MPI processor, setting asic recovery bit so ordering seems necessary as only one work item should be in queue/executing at any given time, hence the use of alloc_ordered_workqueue. WQ_MEM_RECLAIM flag has been set since ethernet devices seem to sit in memory reclaim path, so to guarantee forward progress regardless of memory pressure. Signed-off-by: Amitoj Kaur Chawla Acked-by: Tejun Heo Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlge/qlge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index b28e73ea2c25..83d72106471c 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -4687,7 +4687,7 @@ static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev, /* * Set up the operating parameters. */ - qdev->workqueue = create_singlethread_workqueue(ndev->name); + qdev->workqueue = alloc_ordered_workqueue(ndev->name, WQ_MEM_RECLAIM); INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work); INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); -- GitLab From b3d051477cf94e9d71d6acadb8a90de15237b9c1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 13 Apr 2016 22:05:39 -0700 Subject: [PATCH 3025/9938] tcp: do not mess with listener sk_wmem_alloc When removing sk_refcnt manipulation on synflood, I missed that using skb_set_owner_w() was racy, if sk->sk_wmem_alloc had already transitioned to 0. We should hold sk_refcnt instead, but this is a big deal under attack. (Doing so increase performance from 3.2 Mpps to 3.8 Mpps only) In this patch, I chose to not attach a socket to syncookies skb. Performance is now 5 Mpps instead of 3.2 Mpps. Following patch will remove last known false sharing in tcp_rcv_state_process() Fixes: 3b24d854cb35 ("tcp/dccp: do not touch listener sk_refcnt under synflood") Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 9 +++++++-- net/ipv4/tcp_input.c | 7 ++++--- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/tcp_output.c | 16 ++++++++++++---- net/ipv6/tcp_ipv6.c | 4 ++-- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 74d3ed5eb219..fd40f8c64d5f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -452,10 +452,15 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb); int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); int tcp_connect(struct sock *sk); +enum tcp_synack_type { + TCP_SYNACK_NORMAL, + TCP_SYNACK_FASTOPEN, + TCP_SYNACK_COOKIE, +}; struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, struct request_sock *req, struct tcp_fastopen_cookie *foc, - bool attach_req); + enum tcp_synack_type synack_type); int tcp_disconnect(struct sock *sk, int flags); void tcp_finish_connect(struct sock *sk, struct sk_buff *skb); @@ -1728,7 +1733,7 @@ struct tcp_request_sock_ops { int (*send_synack)(const struct sock *sk, struct dst_entry *dst, struct flowi *fl, struct request_sock *req, struct tcp_fastopen_cookie *foc, - bool attach_req); + enum tcp_synack_type synack_type); }; #ifdef CONFIG_SYN_COOKIES diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 983f04c11177..7ea7034af83f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6327,7 +6327,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, } if (fastopen_sk) { af_ops->send_synack(fastopen_sk, dst, &fl, req, - &foc, false); + &foc, TCP_SYNACK_FASTOPEN); /* Add the child socket directly into the accept queue */ inet_csk_reqsk_queue_add(sk, req, fastopen_sk); sk->sk_data_ready(sk); @@ -6337,8 +6337,9 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, tcp_rsk(req)->tfo_listener = false; if (!want_cookie) inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); - af_ops->send_synack(sk, dst, &fl, req, - &foc, !want_cookie); + af_ops->send_synack(sk, dst, &fl, req, &foc, + !want_cookie ? TCP_SYNACK_NORMAL : + TCP_SYNACK_COOKIE); if (want_cookie) { reqsk_free(req); return 0; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f4f2a0a3849d..d2a5763e5abc 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -830,7 +830,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst, struct flowi *fl, struct request_sock *req, struct tcp_fastopen_cookie *foc, - bool attach_req) + enum tcp_synack_type synack_type) { const struct inet_request_sock *ireq = inet_rsk(req); struct flowi4 fl4; @@ -841,7 +841,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst, if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) return -1; - skb = tcp_make_synack(sk, dst, req, foc, attach_req); + skb = tcp_make_synack(sk, dst, req, foc, synack_type); if (skb) { __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7d2dc015cd19..6451b83d81e9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2944,7 +2944,7 @@ int tcp_send_synack(struct sock *sk) struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, struct request_sock *req, struct tcp_fastopen_cookie *foc, - bool attach_req) + enum tcp_synack_type synack_type) { struct inet_request_sock *ireq = inet_rsk(req); const struct tcp_sock *tp = tcp_sk(sk); @@ -2964,14 +2964,22 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, /* Reserve space for headers. */ skb_reserve(skb, MAX_TCP_HEADER); - if (attach_req) { + switch (synack_type) { + case TCP_SYNACK_NORMAL: skb_set_owner_w(skb, req_to_sk(req)); - } else { + break; + case TCP_SYNACK_COOKIE: + /* Under synflood, we do not attach skb to a socket, + * to avoid false sharing. + */ + break; + case TCP_SYNACK_FASTOPEN: /* sk is a const pointer, because we want to express multiple * cpu might call us concurrently. * sk->sk_wmem_alloc in an atomic, we can promote to rw. */ skb_set_owner_w(skb, (struct sock *)sk); + break; } skb_dst_set(skb, dst); @@ -3516,7 +3524,7 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req) int res; tcp_rsk(req)->txhash = net_tx_rndhash(); - res = af_ops->send_synack(sk, NULL, &fl, req, NULL, true); + res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL); if (!res) { TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0e621bc1ae11..800265c7fd3f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -439,7 +439,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst, struct flowi *fl, struct request_sock *req, struct tcp_fastopen_cookie *foc, - bool attach_req) + enum tcp_synack_type synack_type) { struct inet_request_sock *ireq = inet_rsk(req); struct ipv6_pinfo *np = inet6_sk(sk); @@ -452,7 +452,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst, IPPROTO_TCP)) == NULL) goto done; - skb = tcp_make_synack(sk, dst, req, foc, attach_req); + skb = tcp_make_synack(sk, dst, req, foc, synack_type); if (skb) { __tcp_v6_send_check(skb, &ireq->ir_v6_loc_addr, -- GitLab From 8804b2722dc5d6f9b7ba0a9e812eae9ee5ce95bc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 13 Apr 2016 22:05:40 -0700 Subject: [PATCH 3026/9938] tcp: remove false sharing in tcp_rcv_state_process() Last known hot point during SYNFLOOD attack is the clearing of rx_opt.saw_tstamp in tcp_rcv_state_process() It is not needed for a listener, so we move it where it matters. Performance while a SYNFLOOD hits a single listener socket went from 5 Mpps to 6 Mpps on my test server (24 cores, 8 NIC RX queues) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7ea7034af83f..90e0d9256b74 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5796,8 +5796,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) int queued = 0; bool acceptable; - tp->rx_opt.saw_tstamp = 0; - switch (sk->sk_state) { case TCP_CLOSE: goto discard; @@ -5838,6 +5836,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) goto discard; case TCP_SYN_SENT: + tp->rx_opt.saw_tstamp = 0; queued = tcp_rcv_synsent_state_process(sk, skb, th); if (queued >= 0) return queued; @@ -5849,6 +5848,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) return 0; } + tp->rx_opt.saw_tstamp = 0; req = tp->fastopen_rsk; if (req) { WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && -- GitLab From f5e7150cd9a7779a54b192d21afb9245384db8bc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 Apr 2016 17:46:31 -0300 Subject: [PATCH 3027/9938] perf evlist: Expose perf_event_mlock_kb_in_pages() helper When the user doesn't set --mmap-pages, perf_evlist__mmap() will do it by reading the maximum possible for a non-root user from the /proc/sys/kernel/perf_event_mlock_kb file. Expose that function so that 'perf trace' can, for root users, to bump mmap-pages to a higher value for root, based on the contents of this proc file. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-xay69plylwibpb3l4isrpl1k@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 42 ++++++++++++++++++++++++---------------- tools/perf/util/evlist.h | 2 ++ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4c9f510ae18d..6fb5725821de 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -986,26 +986,34 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, return -1; } -static size_t perf_evlist__mmap_size(unsigned long pages) +unsigned long perf_event_mlock_kb_in_pages(void) { - if (pages == UINT_MAX) { - int max; + unsigned long pages; + int max; - if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) { - /* - * Pick a once upon a time good value, i.e. things look - * strange since we can't read a sysctl value, but lets not - * die yet... - */ - max = 512; - } else { - max -= (page_size / 1024); - } + if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) { + /* + * Pick a once upon a time good value, i.e. things look + * strange since we can't read a sysctl value, but lets not + * die yet... + */ + max = 512; + } else { + max -= (page_size / 1024); + } + + pages = (max * 1024) / page_size; + if (!is_power_of_2(pages)) + pages = rounddown_pow_of_two(pages); - pages = (max * 1024) / page_size; - if (!is_power_of_2(pages)) - pages = rounddown_pow_of_two(pages); - } else if (!is_power_of_2(pages)) + return pages; +} + +static size_t perf_evlist__mmap_size(unsigned long pages) +{ + if (pages == UINT_MAX) + pages = perf_event_mlock_kb_in_pages(); + else if (!is_power_of_2(pages)) return 0; return (pages + 1) * page_size; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index da46423998e8..208897a646ca 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -158,6 +158,8 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, int unset); +unsigned long perf_event_mlock_kb_in_pages(void); + int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, bool overwrite, unsigned int auxtrace_pages, bool auxtrace_overwrite); -- GitLab From f05795d3d771f30a7bdc3a138bf714b06d42aa95 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Tue, 5 Apr 2016 11:50:44 +0200 Subject: [PATCH 3028/9938] scsi: Add intermediate STARGET_REMOVE state to scsi_target_state Add intermediate STARGET_REMOVE state to scsi_target_state to avoid running into the BUG_ON() in scsi_target_reap(). The STARGET_REMOVE state is only valid in the path from scsi_remove_target() to scsi_target_destroy() indicating this target is going to be removed. This re-fixes the problem introduced in commits bc3f02a795d3 ("[SCSI] scsi_remove_target: fix softlockup regression on hot remove") and 40998193560d ("scsi: restart list search after unlock in scsi_remove_target") in a more comprehensive way. [mkp: Included James' fix for scsi_target_destroy()] Signed-off-by: Johannes Thumshirn Fixes: 40998193560dab6c3ce8d25f4fa58a23e252ef38 Cc: stable@vger.kernel.org Reported-by: Sergey Senozhatsky Tested-by: Sergey Senozhatsky Reviewed-by: Ewan D. Milne Reviewed-by: Hannes Reinecke Reviewed-by: James Bottomley Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_scan.c | 1 + drivers/scsi/scsi_sysfs.c | 2 ++ include/scsi/scsi_device.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 6c8ad36560d1..e0a78f53d809 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -319,6 +319,7 @@ static void scsi_target_destroy(struct scsi_target *starget) struct Scsi_Host *shost = dev_to_shost(dev->parent); unsigned long flags; + BUG_ON(starget->state == STARGET_DEL); starget->state = STARGET_DEL; transport_destroy_device(dev); spin_lock_irqsave(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b36544162f2f..f7da8a9d40b6 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1374,11 +1374,13 @@ void scsi_remove_target(struct device *dev) spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL || + starget->state == STARGET_REMOVE || starget == last_target) continue; if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); last_target = starget; + starget->state = STARGET_REMOVE; spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); scsi_target_reap(starget); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 1d4a3297559e..7d85de855160 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -248,6 +248,7 @@ scmd_printk(const char *, const struct scsi_cmnd *, const char *, ...); enum scsi_target_state { STARGET_CREATED = 1, STARGET_RUNNING, + STARGET_REMOVE, STARGET_DEL, }; -- GitLab From f3e459d16a8493b617ccf2a940330279679e0291 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 15 Apr 2016 17:52:34 -0300 Subject: [PATCH 3029/9938] perf trace: Bump --mmap-pages when --call-graph is used by the root user To reduce the chances we'll overflow the mmap buffer, manual fine tuning trumps this. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-wxygbxmp1v9mng1ea28wet02@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 4 ++++ tools/perf/builtin-trace.c | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 146c6db21cbf..c075c002eaa4 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -123,6 +123,10 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. man pages for details. The ones that are most useful in 'perf trace' are 'dwarf' and 'lbr', where available, try: 'perf trace --call-graph dwarf'. + Using this will, for the root user, bump the value of --mmap-pages to 4 + times the maximum for non-root users, based on the kernel.perf_event_mlock_kb + sysctl. This is done only if the user doesn't specify a --mmap-pages value. + --kernel-syscall-graph:: Show the kernel callchains on the syscall exit path. diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 19f5100acc1d..026ec0c749b0 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3110,6 +3110,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) OPT_END() }; bool max_stack_user_set = true; + bool mmap_pages_user_set = true; const char * const trace_subcommands[] = { "record", NULL }; int err; char bf[BUFSIZ]; @@ -3143,6 +3144,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) trace.opts.sample_time = true; } + if (trace.opts.mmap_pages == UINT_MAX) + mmap_pages_user_set = false; + if (trace.max_stack == UINT_MAX) { trace.max_stack = PERF_MAX_STACK_DEPTH; max_stack_user_set = false; @@ -3153,8 +3157,12 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false); #endif - if (trace.opts.callgraph_set) + if (trace.opts.callgraph_set) { + if (!mmap_pages_user_set && geteuid() == 0) + trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4; + symbol_conf.use_callchain = true; + } if (trace.evlist->nr_entries > 0) evlist__set_evsel_handler(trace.evlist, trace__event_handler); -- GitLab From 305c2e71b3d733ec065cb716c76af7d554bd5571 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Tue, 5 Apr 2016 11:50:45 +0200 Subject: [PATCH 3030/9938] Revert "scsi: fix soft lockup in scsi_remove_target() on module removal" Now that we've done a more comprehensive fix with the intermediate target state we can remove the previous hack introduced with commit 90a88d6ef88e ("scsi: fix soft lockup in scsi_remove_target() on module removal"). Signed-off-by: Johannes Thumshirn Cc: stable@vger.kernel.org Reviewed-by: Ewan D. Milne Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_sysfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index f7da8a9d40b6..07349270535d 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1367,19 +1367,17 @@ static void __scsi_remove_target(struct scsi_target *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev->parent); - struct scsi_target *starget, *last_target = NULL; + struct scsi_target *starget; unsigned long flags; restart: spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL || - starget->state == STARGET_REMOVE || - starget == last_target) + starget->state == STARGET_REMOVE) continue; if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); - last_target = starget; starget->state = STARGET_REMOVE; spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); -- GitLab From e4c36ad756ec2de36b05c66bb50ed4ff47b0fdb0 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 1 Apr 2016 08:57:37 +0200 Subject: [PATCH 3031/9938] scsi: vpd pages are mandatory for SPC-2 VPD pages 0x0 and 0x83 are mandatory even for SPC-2, so we should be lowering the restriction to avoid having to whitelist every SPC-2 compliant device. Signed-off-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- include/scsi/scsi_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 7d85de855160..a6c346df290d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -542,9 +542,9 @@ static inline int scsi_device_supports_vpd(struct scsi_device *sdev) /* * Although VPD inquiries can go to SCSI-2 type devices, * some USB ones crash on receiving them, and the pages - * we currently ask for are for SPC-3 and beyond + * we currently ask for are mandatory for SPC-2 and beyond */ - if (sdev->scsi_level > SCSI_SPC_2 && !sdev->skip_vpd_pages) + if (sdev->scsi_level >= SCSI_SPC_2 && !sdev->skip_vpd_pages) return 1; return 0; } -- GitLab From 10755d3f47a9b28639f2e3d29a09ff2a0969657d Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Thu, 7 Apr 2016 09:07:56 -0400 Subject: [PATCH 3032/9938] bnx2fc: Add driver tunables. Per customer request, add the following driver tunables: o devloss_tmo o max_luns o queue_depth o tm_timeout tm_timeout is set per scsi_host in /sys/class/scsi_host/hostX/tm_timeout. Signed-off-by: Joe Carnuccio Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc.h | 1 + drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 79 ++++++++++++++++++++++++++++++- drivers/scsi/bnx2fc/bnx2fc_io.c | 2 +- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 499e369eabf0..106788f304d6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -261,6 +261,7 @@ struct bnx2fc_interface { u8 vlan_enabled; int vlan_id; bool enabled; + u8 tm_timeout; }; #define bnx2fc_from_ctlr(x) \ diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index d7029ea5d319..b0305b0fd21c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -107,6 +107,21 @@ MODULE_PARM_DESC(debug_logging, "\t\t0x10 - fcoe L2 fame related logs.\n" "\t\t0xff - LOG all messages."); +uint bnx2fc_devloss_tmo; +module_param_named(devloss_tmo, bnx2fc_devloss_tmo, uint, S_IRUGO); +MODULE_PARM_DESC(devloss_tmo, " Change devloss_tmo for the remote ports " + "attached via bnx2fc."); + +uint bnx2fc_max_luns = BNX2FC_MAX_LUN; +module_param_named(max_luns, bnx2fc_max_luns, uint, S_IRUGO); +MODULE_PARM_DESC(max_luns, " Change the default max_lun per SCSI host. Default " + "0xffff."); + +uint bnx2fc_queue_depth; +module_param_named(queue_depth, bnx2fc_queue_depth, uint, S_IRUGO); +MODULE_PARM_DESC(queue_depth, " Change the default queue depth of SCSI devices " + "attached via bnx2fc."); + static int bnx2fc_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu); /* notification function for CPU hotplug events */ @@ -692,7 +707,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev) int rc = 0; shost->max_cmd_len = BNX2FC_MAX_CMD_LEN; - shost->max_lun = BNX2FC_MAX_LUN; + shost->max_lun = bnx2fc_max_luns; shost->max_id = BNX2FC_MAX_FCP_TGT; shost->max_channel = 0; if (lport->vport) @@ -1102,6 +1117,9 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled) return -EIO; } + if (bnx2fc_devloss_tmo) + fc_host_dev_loss_tmo(vn_port->host) = bnx2fc_devloss_tmo; + if (disabled) { fc_vport_set_state(vport, FC_VPORT_DISABLED); } else { @@ -1495,6 +1513,9 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, } fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; + if (bnx2fc_devloss_tmo) + fc_host_dev_loss_tmo(shost) = bnx2fc_devloss_tmo; + /* Allocate exchange manager */ if (!npiv) rc = bnx2fc_em_config(lport, hba); @@ -2293,6 +2314,7 @@ static int _bnx2fc_create(struct net_device *netdev, ctlr = bnx2fc_to_ctlr(interface); cdev = fcoe_ctlr_to_ctlr_dev(ctlr); interface->vlan_id = vlan_id; + interface->tm_timeout = BNX2FC_TM_TIMEOUT; interface->timer_work_queue = create_singlethread_workqueue("bnx2fc_timer_wq"); @@ -2612,6 +2634,15 @@ static int bnx2fc_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } +static int bnx2fc_slave_configure(struct scsi_device *sdev) +{ + if (!bnx2fc_queue_depth) + return 0; + + scsi_change_queue_depth(sdev, bnx2fc_queue_depth); + return 0; +} + /** * bnx2fc_mod_init - module init entry point * @@ -2858,6 +2889,50 @@ static struct fc_function_template bnx2fc_vport_xport_function = { .bsg_request = fc_lport_bsg_request, }; +/* + * Additional scsi_host attributes. + */ +static ssize_t +bnx2fc_tm_timeout_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct fc_lport *lport = shost_priv(shost); + struct fcoe_port *port = lport_priv(lport); + struct bnx2fc_interface *interface = port->priv; + + sprintf(buf, "%u\n", interface->tm_timeout); + return strlen(buf); +} + +static ssize_t +bnx2fc_tm_timeout_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct fc_lport *lport = shost_priv(shost); + struct fcoe_port *port = lport_priv(lport); + struct bnx2fc_interface *interface = port->priv; + int rval, val; + + rval = kstrtouint(buf, 10, &val); + if (rval) + return rval; + if (val > 255) + return -ERANGE; + + interface->tm_timeout = (u8)val; + return strlen(buf); +} + +static DEVICE_ATTR(tm_timeout, S_IRUGO|S_IWUSR, bnx2fc_tm_timeout_show, + bnx2fc_tm_timeout_store); + +static struct device_attribute *bnx2fc_host_attrs[] = { + &dev_attr_tm_timeout, + NULL, +}; + /** * scsi_host_template structure used while registering with SCSI-ml */ @@ -2877,6 +2952,8 @@ static struct scsi_host_template bnx2fc_shost_template = { .sg_tablesize = BNX2FC_MAX_BDS_PER_CMD, .max_sectors = 1024, .track_queue_depth = 1, + .slave_configure = bnx2fc_slave_configure, + .shost_attrs = bnx2fc_host_attrs, }; static struct libfc_function_template bnx2fc_libfc_fcn_templ = { diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 2230dab67ca5..562175869d0f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -770,7 +770,7 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags) spin_unlock_bh(&tgt->tgt_lock); rc = wait_for_completion_timeout(&io_req->tm_done, - BNX2FC_TM_TIMEOUT * HZ); + interface->tm_timeout * HZ); spin_lock_bh(&tgt->tgt_lock); io_req->wait_for_comp = 0; -- GitLab From 3f12f76ee83b3388d2e6f97a9e8c4c642656e277 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:07:57 -0400 Subject: [PATCH 3033/9938] bnx2fc: Print when we send a fip keep alive. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index b0305b0fd21c..365101a1598f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -122,6 +122,11 @@ module_param_named(queue_depth, bnx2fc_queue_depth, uint, S_IRUGO); MODULE_PARM_DESC(queue_depth, " Change the default queue depth of SCSI devices " "attached via bnx2fc."); +uint bnx2fc_log_fka; +module_param_named(log_fka, bnx2fc_log_fka, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(log_fka, " Print message to kernel log when fcoe is " + "initiating a FIP keep alive when debug logging is enabled."); + static int bnx2fc_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu); /* notification function for CPU hotplug events */ @@ -1076,6 +1081,20 @@ static u8 *bnx2fc_get_src_mac(struct fc_lport *lport) */ static void bnx2fc_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) { + struct fip_header *fiph; + struct ethhdr *eth_hdr; + u16 op; + u8 sub; + + fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2); + eth_hdr = (struct ethhdr *)skb_mac_header(skb); + op = ntohs(fiph->fip_op); + sub = fiph->fip_subcode; + + if (op == FIP_OP_CTRL && sub == FIP_SC_SOL && bnx2fc_log_fka) + BNX2FC_MISC_DBG("Sending FKA from %pM to %pM.\n", + eth_hdr->h_source, eth_hdr->h_dest); + skb->dev = bnx2fc_from_ctlr(fip)->netdev; dev_queue_xmit(skb); } -- GitLab From f72464d128efd22301ce58b204f3f1808013a536 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:07:58 -0400 Subject: [PATCH 3034/9938] bnx2fc: Print netdev device name when FCoE is successfully initialized. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 365101a1598f..a1881993982c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2039,6 +2039,8 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev) return; } + pr_info(PFX "FCoE initialized for %s.\n", dev->netdev->name); + /* Add HBA to the adapter list */ mutex_lock(&bnx2fc_dev_lock); list_add_tail(&hba->list, &adapter_list); -- GitLab From d02327a863168647b9e6fde610c4730ff4837f9e Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:07:59 -0400 Subject: [PATCH 3035/9938] bnx2fc: Check sc_cmd device and host pointer before returning the command to the mid-layer. When we are in connection recovery and the internal command timer on a request pops, either the scsi_cmnd->device or scsi_cmnd->device->host back pointers may be NULL as the device that the command that the request was submitted on may have been subsequently reaped due to the connection recovery. This can cause one or both of the pointers above to be NULL and cause a system crash if we try to return the command to the midlayer. Instead, double check the pointers before the return to the midlayer so as to prevent the crash and let the upper layers finish the session recovery and rediscover the device. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_io.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 562175869d0f..026f394a3851 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -179,12 +179,24 @@ static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code) bnx2fc_unmap_sg_list(io_req); io_req->sc_cmd = NULL; + + /* Sanity checks before returning command to mid-layer */ if (!sc_cmd) { printk(KERN_ERR PFX "scsi_done - sc_cmd NULL. " "IO(0x%x) already cleaned up\n", io_req->xid); return; } + if (!sc_cmd->device) { + pr_err(PFX "0x%x: sc_cmd->device is NULL.\n", io_req->xid); + return; + } + if (!sc_cmd->device->host) { + pr_err(PFX "0x%x: sc_cmd->device->host is NULL.\n", + io_req->xid); + return; + } + sc_cmd->result = err_code << 16; BNX2FC_IO_DBG(io_req, "sc=%p, result=0x%x, retries=%d, allowed=%d\n", -- GitLab From 63f21677965ab5b888ca15be872fce294c6802d7 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Thu, 7 Apr 2016 09:08:00 -0400 Subject: [PATCH 3036/9938] bnx2fc: Update version number to 2.10.3. Signed-off-by: Chad Dupuis Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 106788f304d6..fdd4eb4e41b2 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -65,7 +65,7 @@ #include "bnx2fc_constants.h" #define BNX2FC_NAME "bnx2fc" -#define BNX2FC_VERSION "2.9.6" +#define BNX2FC_VERSION "2.10.3" #define PFX "bnx2fc: " -- GitLab From 7517b26c65eb4866ec9a02e9cc2b416c94326313 Mon Sep 17 00:00:00 2001 From: Leonid Moiseichuk Date: Thu, 7 Apr 2016 21:52:25 +0300 Subject: [PATCH 3037/9938] mvsas: Generalize Marvell 9485 in pci_device_id Claim Marvell 9485 controllers regardless of subdevice ID. Tested on ASUS P9A-I/C2550/SAS/4L which uses vendor-specific 1043:8635. [mkp: Tweaked commit message] Signed-off-by: Leonid Moiseichuk Reviewed-by: Andy Shevchenko Signed-off-by: Martin K. Petersen --- drivers/scsi/mvsas/mv_init.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index c7c250519c4b..8280046fd1f0 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -704,24 +704,7 @@ static struct pci_device_id mvs_pci_table[] = { .class_mask = 0, .driver_data = chip_9445, }, - { - .vendor = PCI_VENDOR_ID_MARVELL_EXT, - .device = 0x9485, - .subvendor = PCI_ANY_ID, - .subdevice = 0x9480, - .class = 0, - .class_mask = 0, - .driver_data = chip_9485, - }, - { - .vendor = PCI_VENDOR_ID_MARVELL_EXT, - .device = 0x9485, - .subvendor = PCI_ANY_ID, - .subdevice = 0x9485, - .class = 0, - .class_mask = 0, - .driver_data = chip_9485, - }, + { PCI_VDEVICE(MARVELL_EXT, 0x9485), chip_9485 }, /* Marvell 9480/9485 (any vendor/model) */ { PCI_VDEVICE(OCZ, 0x1021), chip_9485}, /* OCZ RevoDrive3 */ { PCI_VDEVICE(OCZ, 0x1022), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ { PCI_VDEVICE(OCZ, 0x1040), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ -- GitLab From 98be565f1c19747bfc463f668310ff89beb28696 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 8 Apr 2016 08:14:54 +0200 Subject: [PATCH 3038/9938] zfcp: Revert to original scanning behaviour zfcp has its own mechanism for selective scanning, so revert to the original scanning behaviour to not confuse users. Fixes: 4e91e876e9b8b6eb4255aa0d690778a89d3f1d28 Suggested-by: Benjamin Block Signed-off-by: Hannes Reinecke Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_unit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 08bba7ce7cef..9310a547b89f 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -27,7 +27,7 @@ void zfcp_unit_scsi_scan(struct zfcp_unit *unit) if (rport && rport->port_state == FC_PORTSTATE_ONLINE) scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, - SCSI_SCAN_RESCAN); + SCSI_SCAN_MANUAL); } static void zfcp_unit_scsi_scan_work(struct work_struct *work) -- GitLab From 91dbc08d64fba7c1426a32be4c57ebb63c4be124 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:07 -0700 Subject: [PATCH 3039/9938] scsi: replace "scsi_data_buffer" with "sg_table" in SG functions Replace parameter "struct scsi_data_buffer" with "struct sg_table" in SG alloc/free functions to make them generic. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8106515d1df8..4229c183648b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,14 +583,14 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool mq) { - if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); } -static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) { struct scatterlist *first_chunk = NULL; int ret; @@ -599,17 +599,17 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) if (mq) { if (nents <= SCSI_MAX_SG_SEGMENTS) { - sdb->table.nents = sdb->table.orig_nents = nents; - sg_init_table(sdb->table.sgl, nents); + table->nents = table->orig_nents = nents; + sg_init_table(table->sgl, nents); return 0; } - first_chunk = sdb->table.sgl; + first_chunk = table->sgl; } - ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, + ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(sdb, mq); + scsi_free_sgtable(table, mq); return ret; } @@ -625,12 +625,17 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) { + struct scsi_data_buffer *sdb; + if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, true); - if (cmd->request->next_rq && cmd->request->next_rq->special) - scsi_free_sgtable(cmd->request->next_rq->special, true); + scsi_free_sgtable(&cmd->sdb.table, true); + if (cmd->request->next_rq) { + sdb = cmd->request->next_rq->special; + if (sdb) + scsi_free_sgtable(&sdb->table, true); + } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, true); + scsi_free_sgtable(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -669,19 +674,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb, false); + scsi_free_sgtable(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb, false); + scsi_free_sgtable(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(bidi_sdb, false); + scsi_free_sgtable(&bidi_sdb->table, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } @@ -1085,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) /* * If sg table allocation fails, requeue request later. */ - if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments, + if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, req->mq_ctx != NULL))) return BLKPREP_DEFER; @@ -1158,7 +1163,7 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(prot_sdb, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { error = BLKPREP_DEFER; goto err_exit; } -- GitLab From 22cc3d4c6f4c529f4bf17445c60893b13e7611fb Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:08 -0700 Subject: [PATCH 3040/9938] scsi: replace "mq" with "first_chunk" in SG functions Parameter "bool mq" is block driver specific. Change it to "first_chunk" to make it more generic. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4229c183648b..9675353770e9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,33 +583,32 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool mq) +static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) { - if (mq && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, bool mq) +static int scsi_alloc_sgtable(struct sg_table *table, int nents, + struct scatterlist *first_chunk) { - struct scatterlist *first_chunk = NULL; int ret; BUG_ON(!nents); - if (mq) { + if (first_chunk) { if (nents <= SCSI_MAX_SG_SEGMENTS) { table->nents = table->orig_nents = nents; sg_init_table(table->sgl, nents); return 0; } - first_chunk = table->sgl; } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, first_chunk, GFP_ATOMIC, scsi_sg_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, mq); + scsi_free_sgtable(table, (bool)first_chunk); return ret; } @@ -1091,7 +1090,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) * If sg table allocation fails, requeue request later. */ if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, - req->mq_ctx != NULL))) + sdb->table.sgl))) return BLKPREP_DEFER; /* @@ -1163,7 +1162,8 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, is_mq)) { + if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, + prot_sdb->table.sgl)) { error = BLKPREP_DEFER; goto err_exit; } -- GitLab From 001d63be61c3b5a0413a46bacafbfc60c353951a Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:09 -0700 Subject: [PATCH 3041/9938] scsi: rename SG related struct and functions Rename SCSI specific struct and functions to more genenic names. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9675353770e9..08134f621450 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -40,10 +40,10 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) +#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) #define SG_MEMPOOL_SIZE 2 -struct scsi_host_sg_pool { +struct sg_pool { size_t size; char *name; struct kmem_cache *slab; @@ -54,7 +54,7 @@ struct scsi_host_sg_pool { #if (SCSI_MAX_SG_SEGMENTS < 32) #error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater) #endif -static struct scsi_host_sg_pool scsi_sg_pools[] = { +static struct sg_pool sg_pools[] = { SP(8), SP(16), #if (SCSI_MAX_SG_SEGMENTS > 32) @@ -553,7 +553,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int scsi_sgtable_index(unsigned short nents) +static inline unsigned int sg_pool_index(unsigned short nents) { unsigned int index; @@ -567,30 +567,30 @@ static inline unsigned int scsi_sgtable_index(unsigned short nents) return index; } -static void scsi_sg_free(struct scatterlist *sgl, unsigned int nents) +static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); mempool_free(sgl, sgp->pool); } -static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) +static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) { - struct scsi_host_sg_pool *sgp; + struct sg_pool *sgp; - sgp = scsi_sg_pools + scsi_sgtable_index(nents); + sgp = sg_pools + sg_pool_index(nents); return mempool_alloc(sgp->pool, gfp_mask); } -static void scsi_free_sgtable(struct sg_table *table, bool first_chunk) +static void sg_free_table_chained(struct sg_table *table, bool first_chunk) { if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, scsi_sg_free); + __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, sg_pool_free); } -static int scsi_alloc_sgtable(struct sg_table *table, int nents, +static int sg_alloc_table_chained(struct sg_table *table, int nents, struct scatterlist *first_chunk) { int ret; @@ -606,9 +606,9 @@ static int scsi_alloc_sgtable(struct sg_table *table, int nents, } ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, - first_chunk, GFP_ATOMIC, scsi_sg_alloc); + first_chunk, GFP_ATOMIC, sg_pool_alloc); if (unlikely(ret)) - scsi_free_sgtable(table, (bool)first_chunk); + sg_free_table_chained(table, (bool)first_chunk); return ret; } @@ -627,14 +627,14 @@ static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) struct scsi_data_buffer *sdb; if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, true); + sg_free_table_chained(&cmd->sdb.table, true); if (cmd->request->next_rq) { sdb = cmd->request->next_rq->special; if (sdb) - scsi_free_sgtable(&sdb->table, true); + sg_free_table_chained(&sdb->table, true); } if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, true); + sg_free_table_chained(&cmd->prot_sdb->table, true); } static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) @@ -673,19 +673,19 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb.table, false); + sg_free_table_chained(&cmd->sdb.table, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(&cmd->prot_sdb->table, false); + sg_free_table_chained(&cmd->prot_sdb->table, false); } static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(&bidi_sdb->table, false); + sg_free_table_chained(&bidi_sdb->table, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } @@ -1089,7 +1089,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb) /* * If sg table allocation fails, requeue request later. */ - if (unlikely(scsi_alloc_sgtable(&sdb->table, req->nr_phys_segments, + if (unlikely(sg_alloc_table_chained(&sdb->table, req->nr_phys_segments, sdb->table.sgl))) return BLKPREP_DEFER; @@ -1162,7 +1162,7 @@ int scsi_init_io(struct scsi_cmnd *cmd) ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(&prot_sdb->table, ivecs, + if (sg_alloc_table_chained(&prot_sdb->table, ivecs, prot_sdb->table.sgl)) { error = BLKPREP_DEFER; goto err_exit; @@ -2280,7 +2280,7 @@ int __init scsi_init_queue(void) } for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; + struct sg_pool *sgp = sg_pools + i; int size = sgp->size * sizeof(struct scatterlist); sgp->slab = kmem_cache_create(sgp->name, size, 0, @@ -2304,7 +2304,7 @@ int __init scsi_init_queue(void) cleanup_sdb: for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; + struct sg_pool *sgp = sg_pools + i; if (sgp->pool) mempool_destroy(sgp->pool); if (sgp->slab) @@ -2322,7 +2322,7 @@ void scsi_exit_queue(void) kmem_cache_destroy(scsi_sdb_cache); for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; + struct sg_pool *sgp = sg_pools + i; mempool_destroy(sgp->pool); kmem_cache_destroy(sgp->slab); } -- GitLab From 65e8617fba17732b4c68d3369a621725838b6f28 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:10 -0700 Subject: [PATCH 3042/9938] scsi: rename SCSI_MAX_{SG, SG_CHAIN}_SEGMENTS Rename SCSI_MAX_SG_SEGMENTS to SG_CHUNK_SIZE, which means the amount we fit into a single scatterlist chunk. Rename SCSI_MAX_SG_CHAIN_SEGMENTS to SG_MAX_SEGMENTS. Will move these 2 generic definitions to scatterlist.h later. Reviewed-by: Christoph Hellwig Acked-by: Bart Van Assche (for ib_srp changes) Signed-off-by: Ming Lin Acked-by: Tejun Heo Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/ata/pata_icside.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c | 2 +- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 4 ++-- drivers/scsi/hisi_sas/hisi_sas.h | 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 4 ++-- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_lib.c | 34 ++++++++++++++--------------- drivers/usb/storage/scsiglue.c | 2 +- include/scsi/scsi.h | 8 +++---- include/scsi/scsi_host.h | 2 +- 14 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index d7c732042a4f..188f2f2eb21f 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -294,7 +294,7 @@ static int icside_dma_init(struct pata_icside_info *info) static struct scsi_host_template pata_icside_sht = { ATA_BASE_SHT(DRV_NAME), - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, }; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index ff21597aa54d..369a75e1f44e 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(cmd_sg_entries, module_param(indirect_sg_entries, uint, 0444); MODULE_PARM_DESC(indirect_sg_entries, - "Default max number of gather/scatter entries (default is 12, max is " __stringify(SCSI_MAX_SG_CHAIN_SEGMENTS) ")"); + "Default max number of gather/scatter entries (default is 12, max is " __stringify(SG_MAX_SEGMENTS) ")"); module_param(allow_ext_sg, bool, 0444); MODULE_PARM_DESC(allow_ext_sg, @@ -3097,7 +3097,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) case SRP_OPT_SG_TABLESIZE: if (match_int(args, &token) || token < 1 || - token > SCSI_MAX_SG_CHAIN_SEGMENTS) { + token > SG_MAX_SEGMENTS) { pr_warn("bad max sg_tablesize parameter '%s'\n", p); goto out; diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index faa1bee07c8a..edce5f3cfdba 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -365,7 +365,7 @@ static struct scsi_host_template cumanascsi2_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "cumanascsi2", diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index a8ad6880dd91..e93e047f4316 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -484,7 +484,7 @@ static struct scsi_host_template eesox_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .use_clustering = DISABLE_CLUSTERING, .proc_name = "eesox", diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 5e1b73e1b743..79aa88911b7f 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -291,7 +291,7 @@ static struct scsi_host_template powertecscsi_template = { .can_queue = 8, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .dma_boundary = IOMD_DMA_BOUNDARY, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 33581ba4386e..2aca4d16f39e 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -246,7 +246,7 @@ static struct scsi_host_template driver_template = { .eh_target_reset_handler = esas2r_target_reset, .can_queue = 128, .this_id = -1, - .sg_tablesize = SCSI_MAX_SG_SEGMENTS, + .sg_tablesize = SG_CHUNK_SIZE, .cmd_per_lun = ESAS2R_DEFAULT_CMD_PER_LUN, .present = 0, @@ -271,7 +271,7 @@ module_param(num_sg_lists, int, 0); MODULE_PARM_DESC(num_sg_lists, "Number of scatter/gather lists. Default 1024."); -int sg_tablesize = SCSI_MAX_SG_SEGMENTS; +int sg_tablesize = SG_CHUNK_SIZE; module_param(sg_tablesize, int, 0); MODULE_PARM_DESC(sg_tablesize, "Maximum number of entries in a scatter/gather table."); diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 29e89f340b64..fa12eeac140c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -298,7 +298,7 @@ struct hisi_sas_command_table_stp { u8 atapi_cdb[ATAPI_CDB_LEN]; }; -#define HISI_SAS_SGE_PAGE_CNT SCSI_MAX_SG_SEGMENTS +#define HISI_SAS_SGE_PAGE_CNT SG_CHUNK_SIZE struct hisi_sas_sge_page { struct hisi_sas_sge sge[HISI_SAS_SGE_PAGE_CNT]; }; diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 8c44b9c424af..28d85314b3c6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -3207,10 +3207,10 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) sg_tablesize = MPT_MIN_PHYS_SEGMENTS; else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { sg_tablesize = min_t(unsigned short, sg_tablesize, - SCSI_MAX_SG_CHAIN_SEGMENTS); + SG_MAX_SEGMENTS); pr_warn(MPT3SAS_FMT "sg_tablesize(%u) is bigger than kernel" - " defined SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name, + " defined SG_CHUNK_SIZE(%u)\n", ioc->name, sg_tablesize, MPT_MAX_PHYS_SEGMENTS); } ioc->shost->sg_tablesize = sg_tablesize; diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 32580b514b18..6940c577053f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -90,7 +90,7 @@ /* * Set MPT3SAS_SG_DEPTH value based on user input. */ -#define MPT_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS +#define MPT_MAX_PHYS_SEGMENTS SG_CHUNK_SIZE #define MPT_MIN_PHYS_SEGMENTS 16 #ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index f3d69a98c725..06b151711cdd 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -5305,7 +5305,7 @@ static struct scsi_host_template sdebug_driver_template = { .eh_host_reset_handler = scsi_debug_host_reset, .can_queue = SCSI_DEBUG_CANQUEUE, .this_id = 7, - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, .cmd_per_lun = DEF_CMD_PER_LUN, .max_sectors = -1U, .use_clustering = DISABLE_CLUSTERING, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 08134f621450..8f776f1e95ce 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -51,25 +51,25 @@ struct sg_pool { }; #define SP(x) { .size = x, "sgpool-" __stringify(x) } -#if (SCSI_MAX_SG_SEGMENTS < 32) -#error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater) +#if (SG_CHUNK_SIZE < 32) +#error SG_CHUNK_SIZE is too small (must be 32 or greater) #endif static struct sg_pool sg_pools[] = { SP(8), SP(16), -#if (SCSI_MAX_SG_SEGMENTS > 32) +#if (SG_CHUNK_SIZE > 32) SP(32), -#if (SCSI_MAX_SG_SEGMENTS > 64) +#if (SG_CHUNK_SIZE > 64) SP(64), -#if (SCSI_MAX_SG_SEGMENTS > 128) +#if (SG_CHUNK_SIZE > 128) SP(128), -#if (SCSI_MAX_SG_SEGMENTS > 256) -#error SCSI_MAX_SG_SEGMENTS is too large (256 MAX) +#if (SG_CHUNK_SIZE > 256) +#error SG_CHUNK_SIZE is too large (256 MAX) #endif #endif #endif #endif - SP(SCSI_MAX_SG_SEGMENTS) + SP(SG_CHUNK_SIZE) }; #undef SP @@ -557,7 +557,7 @@ static inline unsigned int sg_pool_index(unsigned short nents) { unsigned int index; - BUG_ON(nents > SCSI_MAX_SG_SEGMENTS); + BUG_ON(nents > SG_CHUNK_SIZE); if (nents <= 8) index = 0; @@ -585,9 +585,9 @@ static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) static void sg_free_table_chained(struct sg_table *table, bool first_chunk) { - if (first_chunk && table->orig_nents <= SCSI_MAX_SG_SEGMENTS) + if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) return; - __sg_free_table(table, SCSI_MAX_SG_SEGMENTS, first_chunk, sg_pool_free); + __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); } static int sg_alloc_table_chained(struct sg_table *table, int nents, @@ -598,14 +598,14 @@ static int sg_alloc_table_chained(struct sg_table *table, int nents, BUG_ON(!nents); if (first_chunk) { - if (nents <= SCSI_MAX_SG_SEGMENTS) { + if (nents <= SG_CHUNK_SIZE) { table->nents = table->orig_nents = nents; sg_init_table(table->sgl, nents); return 0; } } - ret = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS, + ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, first_chunk, GFP_ATOMIC, sg_pool_alloc); if (unlikely(ret)) sg_free_table_chained(table, (bool)first_chunk); @@ -1937,7 +1937,7 @@ static int scsi_mq_prep_fn(struct request *req) if (scsi_host_get_prot(shost)) { cmd->prot_sdb = (void *)sg + min_t(unsigned int, - shost->sg_tablesize, SCSI_MAX_SG_SEGMENTS) * + shost->sg_tablesize, SG_CHUNK_SIZE) * sizeof(struct scatterlist); memset(cmd->prot_sdb, 0, sizeof(struct scsi_data_buffer)); @@ -2110,7 +2110,7 @@ static void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) * this limit is imposed by hardware restrictions */ blk_queue_max_segments(q, min_t(unsigned short, shost->sg_tablesize, - SCSI_MAX_SG_CHAIN_SEGMENTS)); + SG_MAX_SEGMENTS)); if (scsi_host_prot_dma(shost)) { shost->sg_prot_tablesize = @@ -2192,8 +2192,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost) unsigned int cmd_size, sgl_size, tbl_size; tbl_size = shost->sg_tablesize; - if (tbl_size > SCSI_MAX_SG_SEGMENTS) - tbl_size = SCSI_MAX_SG_SEGMENTS; + if (tbl_size > SG_CHUNK_SIZE) + tbl_size = SG_CHUNK_SIZE; sgl_size = tbl_size * sizeof(struct scatterlist); cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size; if (scsi_host_get_prot(shost)) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 90901861bfc0..ae85861051eb 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -563,7 +563,7 @@ static const struct scsi_host_template usb_stor_host_template = { .target_alloc = target_alloc, /* lots of sg segments can be handled */ - .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .sg_tablesize = SG_MAX_SEGMENTS, /* limit the total size of a transfer to 120 KB */ .max_sectors = 240, diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index e0a3398b1547..74dafa75bae7 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -24,16 +24,16 @@ enum scsi_timeouts { * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The * minimum value is 32 */ -#define SCSI_MAX_SG_SEGMENTS 128 +#define SG_CHUNK_SIZE 128 /* - * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit + * Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. */ #ifdef CONFIG_ARCH_HAS_SG_CHAIN -#define SCSI_MAX_SG_CHAIN_SEGMENTS 2048 +#define SG_MAX_SEGMENTS 2048 #else -#define SCSI_MAX_SG_CHAIN_SEGMENTS SCSI_MAX_SG_SEGMENTS +#define SG_MAX_SEGMENTS SG_CHUNK_SIZE #endif /* diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index fcfa3d7f5e7e..76e9d278c334 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -37,7 +37,7 @@ struct blk_queue_tags; * used in one scatter-gather request. */ #define SG_NONE 0 -#define SG_ALL SCSI_MAX_SG_SEGMENTS +#define SG_ALL SG_CHUNK_SIZE #define MODE_UNKNOWN 0x00 #define MODE_INITIATOR 0x01 -- GitLab From 9b1d6c8950021ab007608d455fc9c398ecd25476 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Mon, 4 Apr 2016 14:48:11 -0700 Subject: [PATCH 3043/9938] lib: scatterlist: move SG pool code from SCSI driver to lib/sg_pool.c Now it's ready to move the mempool based SG chained allocator code from SCSI driver to lib/sg_pool.c, which will be compiled only based on a Kconfig symbol CONFIG_SG_POOL. SCSI selects CONFIG_SG_POOL. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Reviewed-by: Sagi Grimberg Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 1 + drivers/scsi/scsi_lib.c | 137 ---------------------------- include/linux/scatterlist.h | 25 ++++++ include/scsi/scsi.h | 19 ---- lib/Kconfig | 7 ++ lib/Makefile | 1 + lib/sg_pool.c | 172 ++++++++++++++++++++++++++++++++++++ 7 files changed, 206 insertions(+), 156 deletions(-) create mode 100644 lib/sg_pool.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 0950567e6269..98e5d51a3346 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -17,6 +17,7 @@ config SCSI tristate "SCSI device support" depends on BLOCK select SCSI_DMA if HAS_DMA + select SG_POOL ---help--- If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or any other SCSI device under Linux, say Y and make sure that you know diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8f776f1e95ce..b920c5dabf60 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include #include @@ -40,39 +38,6 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) -#define SG_MEMPOOL_SIZE 2 - -struct sg_pool { - size_t size; - char *name; - struct kmem_cache *slab; - mempool_t *pool; -}; - -#define SP(x) { .size = x, "sgpool-" __stringify(x) } -#if (SG_CHUNK_SIZE < 32) -#error SG_CHUNK_SIZE is too small (must be 32 or greater) -#endif -static struct sg_pool sg_pools[] = { - SP(8), - SP(16), -#if (SG_CHUNK_SIZE > 32) - SP(32), -#if (SG_CHUNK_SIZE > 64) - SP(64), -#if (SG_CHUNK_SIZE > 128) - SP(128), -#if (SG_CHUNK_SIZE > 256) -#error SG_CHUNK_SIZE is too large (256 MAX) -#endif -#endif -#endif -#endif - SP(SG_CHUNK_SIZE) -}; -#undef SP - struct kmem_cache *scsi_sdb_cache; /* @@ -553,65 +518,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost) scsi_run_queue(sdev->request_queue); } -static inline unsigned int sg_pool_index(unsigned short nents) -{ - unsigned int index; - - BUG_ON(nents > SG_CHUNK_SIZE); - - if (nents <= 8) - index = 0; - else - index = get_count_order(nents) - 3; - - return index; -} - -static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - mempool_free(sgl, sgp->pool); -} - -static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) -{ - struct sg_pool *sgp; - - sgp = sg_pools + sg_pool_index(nents); - return mempool_alloc(sgp->pool, gfp_mask); -} - -static void sg_free_table_chained(struct sg_table *table, bool first_chunk) -{ - if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) - return; - __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); -} - -static int sg_alloc_table_chained(struct sg_table *table, int nents, - struct scatterlist *first_chunk) -{ - int ret; - - BUG_ON(!nents); - - if (first_chunk) { - if (nents <= SG_CHUNK_SIZE) { - table->nents = table->orig_nents = nents; - sg_init_table(table->sgl, nents); - return 0; - } - } - - ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, - first_chunk, GFP_ATOMIC, sg_pool_alloc); - if (unlikely(ret)) - sg_free_table_chained(table, (bool)first_chunk); - return ret; -} - static void scsi_uninit_cmd(struct scsi_cmnd *cmd) { if (cmd->request->cmd_type == REQ_TYPE_FS) { @@ -2269,8 +2175,6 @@ EXPORT_SYMBOL(scsi_unblock_requests); int __init scsi_init_queue(void) { - int i; - scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", sizeof(struct scsi_data_buffer), 0, 0, NULL); @@ -2279,53 +2183,12 @@ int __init scsi_init_queue(void) return -ENOMEM; } - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - int size = sgp->size * sizeof(struct scatterlist); - - sgp->slab = kmem_cache_create(sgp->name, size, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!sgp->slab) { - printk(KERN_ERR "SCSI: can't init sg slab %s\n", - sgp->name); - goto cleanup_sdb; - } - - sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE, - sgp->slab); - if (!sgp->pool) { - printk(KERN_ERR "SCSI: can't init sg mempool %s\n", - sgp->name); - goto cleanup_sdb; - } - } - return 0; - -cleanup_sdb: - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - if (sgp->pool) - mempool_destroy(sgp->pool); - if (sgp->slab) - kmem_cache_destroy(sgp->slab); - } - kmem_cache_destroy(scsi_sdb_cache); - - return -ENOMEM; } void scsi_exit_queue(void) { - int i; - kmem_cache_destroy(scsi_sdb_cache); - - for (i = 0; i < SG_MEMPOOL_NR; i++) { - struct sg_pool *sgp = sg_pools + i; - mempool_destroy(sgp->pool); - kmem_cache_destroy(sgp->slab); - } } /** diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 556ec1ea2574..cb3c8fe6acd7 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -285,6 +285,31 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, */ #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) +/* + * The maximum number of SG segments that we will put inside a + * scatterlist (unless chaining is used). Should ideally fit inside a + * single page, to avoid a higher order allocation. We could define this + * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The + * minimum value is 32 + */ +#define SG_CHUNK_SIZE 128 + +/* + * Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit + * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. + */ +#ifdef CONFIG_ARCH_HAS_SG_CHAIN +#define SG_MAX_SEGMENTS 2048 +#else +#define SG_MAX_SEGMENTS SG_CHUNK_SIZE +#endif + +#ifdef CONFIG_SG_POOL +void sg_free_table_chained(struct sg_table *table, bool first_chunk); +int sg_alloc_table_chained(struct sg_table *table, int nents, + struct scatterlist *first_chunk); +#endif + /* * sg page iterator * diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 74dafa75bae7..8ec7c30e35af 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -17,25 +17,6 @@ enum scsi_timeouts { SCSI_DEFAULT_EH_TIMEOUT = 10 * HZ, }; -/* - * The maximum number of SG segments that we will put inside a - * scatterlist (unless chaining is used). Should ideally fit inside a - * single page, to avoid a higher order allocation. We could define this - * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The - * minimum value is 32 - */ -#define SG_CHUNK_SIZE 128 - -/* - * Like SG_CHUNK_SIZE, but for archs that have sg chaining. This limit - * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. - */ -#ifdef CONFIG_ARCH_HAS_SG_CHAIN -#define SG_MAX_SEGMENTS 2048 -#else -#define SG_MAX_SEGMENTS SG_CHUNK_SIZE -#endif - /* * DIX-capable adapters effectively support infinite chaining for the * protection information scatterlist diff --git a/lib/Kconfig b/lib/Kconfig index 3cca1222578e..61d55bd0ed89 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -523,6 +523,13 @@ config SG_SPLIT a scatterlist. This should be selected by a driver or an API which whishes to split a scatterlist amongst multiple DMA channels. +config SG_POOL + def_bool n + help + Provides a helper to allocate chained scatterlists. This should be + selected by a driver or an API which whishes to allocate chained + scatterlist. + # # sg chaining option # diff --git a/lib/Makefile b/lib/Makefile index 7bd6fd436c97..bf01c2673423 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -178,6 +178,7 @@ obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_SG_SPLIT) += sg_split.o +obj-$(CONFIG_SG_POOL) += sg_pool.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o obj-$(CONFIG_IRQ_POLL) += irq_poll.o diff --git a/lib/sg_pool.c b/lib/sg_pool.c new file mode 100644 index 000000000000..6dd30615a201 --- /dev/null +++ b/lib/sg_pool.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include + +#define SG_MEMPOOL_NR ARRAY_SIZE(sg_pools) +#define SG_MEMPOOL_SIZE 2 + +struct sg_pool { + size_t size; + char *name; + struct kmem_cache *slab; + mempool_t *pool; +}; + +#define SP(x) { .size = x, "sgpool-" __stringify(x) } +#if (SG_CHUNK_SIZE < 32) +#error SG_CHUNK_SIZE is too small (must be 32 or greater) +#endif +static struct sg_pool sg_pools[] = { + SP(8), + SP(16), +#if (SG_CHUNK_SIZE > 32) + SP(32), +#if (SG_CHUNK_SIZE > 64) + SP(64), +#if (SG_CHUNK_SIZE > 128) + SP(128), +#if (SG_CHUNK_SIZE > 256) +#error SG_CHUNK_SIZE is too large (256 MAX) +#endif +#endif +#endif +#endif + SP(SG_CHUNK_SIZE) +}; +#undef SP + +static inline unsigned int sg_pool_index(unsigned short nents) +{ + unsigned int index; + + BUG_ON(nents > SG_CHUNK_SIZE); + + if (nents <= 8) + index = 0; + else + index = get_count_order(nents) - 3; + + return index; +} + +static void sg_pool_free(struct scatterlist *sgl, unsigned int nents) +{ + struct sg_pool *sgp; + + sgp = sg_pools + sg_pool_index(nents); + mempool_free(sgl, sgp->pool); +} + +static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask) +{ + struct sg_pool *sgp; + + sgp = sg_pools + sg_pool_index(nents); + return mempool_alloc(sgp->pool, gfp_mask); +} + +/** + * sg_free_table_chained - Free a previously mapped sg table + * @table: The sg table header to use + * @first_chunk: was first_chunk not NULL in sg_alloc_table_chained? + * + * Description: + * Free an sg table previously allocated and setup with + * sg_alloc_table_chained(). + * + **/ +void sg_free_table_chained(struct sg_table *table, bool first_chunk) +{ + if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) + return; + __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); +} +EXPORT_SYMBOL_GPL(sg_free_table_chained); + +/** + * sg_alloc_table_chained - Allocate and chain SGLs in an sg table + * @table: The sg table header to use + * @nents: Number of entries in sg list + * @first_chunk: first SGL + * + * Description: + * Allocate and chain SGLs in an sg table. If @nents@ is larger than + * SG_CHUNK_SIZE a chained sg table will be setup. + * + **/ +int sg_alloc_table_chained(struct sg_table *table, int nents, + struct scatterlist *first_chunk) +{ + int ret; + + BUG_ON(!nents); + + if (first_chunk) { + if (nents <= SG_CHUNK_SIZE) { + table->nents = table->orig_nents = nents; + sg_init_table(table->sgl, nents); + return 0; + } + } + + ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, + first_chunk, GFP_ATOMIC, sg_pool_alloc); + if (unlikely(ret)) + sg_free_table_chained(table, (bool)first_chunk); + return ret; +} +EXPORT_SYMBOL_GPL(sg_alloc_table_chained); + +static __init int sg_pool_init(void) +{ + int i; + + for (i = 0; i < SG_MEMPOOL_NR; i++) { + struct sg_pool *sgp = sg_pools + i; + int size = sgp->size * sizeof(struct scatterlist); + + sgp->slab = kmem_cache_create(sgp->name, size, 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!sgp->slab) { + printk(KERN_ERR "SG_POOL: can't init sg slab %s\n", + sgp->name); + goto cleanup_sdb; + } + + sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE, + sgp->slab); + if (!sgp->pool) { + printk(KERN_ERR "SG_POOL: can't init sg mempool %s\n", + sgp->name); + goto cleanup_sdb; + } + } + + return 0; + +cleanup_sdb: + for (i = 0; i < SG_MEMPOOL_NR; i++) { + struct sg_pool *sgp = sg_pools + i; + if (sgp->pool) + mempool_destroy(sgp->pool); + if (sgp->slab) + kmem_cache_destroy(sgp->slab); + } + + return -ENOMEM; +} + +static __exit void sg_pool_exit(void) +{ + int i; + + for (i = 0; i < SG_MEMPOOL_NR; i++) { + struct sg_pool *sgp = sg_pools + i; + mempool_destroy(sgp->pool); + kmem_cache_destroy(sgp->slab); + } +} + +module_init(sg_pool_init); +module_exit(sg_pool_exit); -- GitLab From 7524926826104b9e0665eaecd50f76889b89a72e Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:11 +0800 Subject: [PATCH 3044/9938] hisi_sas: use device linkrate in MCR for v2 hw Contrary to the field name, the MCR (max connection rate) in the ITCT should hold the device linkrate (linkrate of the connected phy), and not the max linkrate. This fixes an issue seen where some SATA drives connected through an expander which would not attach. Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index b7337476454b..f462fc4adc3a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -544,7 +544,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, } qw0 |= ((1 << ITCT_HDR_VALID_OFF) | - (device->max_linkrate << ITCT_HDR_MCR_OFF) | + (device->linkrate << ITCT_HDR_MCR_OFF) | (1 << ITCT_HDR_VLN_OFF) | (port->id << ITCT_HDR_PORT_ID_OFF)); itct->qw0 = cpu_to_le64(qw0); -- GitLab From 3a429d5ab60966cf75d9b99648700823c514b7ad Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:12 +0800 Subject: [PATCH 3045/9938] hisi_sas: fix v2 hw multiple SATA disk issue Intermittently it is found that when multiple SATA disks are directly connected to the host that some disks are not detected. The problem is that all set bitfields in ENT_INT_SRC1 are cleared for all phys in sata_int_v2_hw() - it should clear the set bit for the phy being serviced. Also unnecessary double-write to ENT_INT_SRC1 and ENT_INT_SRC_MSK1 is removed (remaining writes are done at end label). Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index f462fc4adc3a..5a7f7092018a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2003,12 +2003,10 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk | 1 << phy_no); ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1); - ent_tmp = ent_int; + ent_tmp = ent_int & (1 << (ENT_INT_SRC1_D2H_FIS_CH1_OFF * phy_no)); ent_int >>= ENT_INT_SRC1_D2H_FIS_CH1_OFF * (phy_no % 4); if ((ent_int & ENT_INT_SRC1_D2H_FIS_CH0_MSK) == 0) { dev_warn(dev, "sata int: phy%d did not receive FIS\n", phy_no); - hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk); res = IRQ_NONE; goto end; } -- GitLab From 11826e5dc7b7297164dd9dd6d735c6ff6acb4b86 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:13 +0800 Subject: [PATCH 3046/9938] hisi_sas: add v2 hw support for >4 SATA phys This patch adds support for directly attaching SATA disks to phy 4-8. The problem was that only registers concerned with phy 0-3 were being considered in sata_int_v2_hw(). The issue was not detected previously as the development board only exposed phy 0-3; the new board provides access to 8 phys. Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 5a7f7092018a..cc083b9b1041 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1993,17 +1993,20 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate; irqreturn_t res = IRQ_HANDLED; u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; - int phy_no; + int phy_no, offset; phy_no = sas_phy->id; initial_fis = &hisi_hba->initial_fis[phy_no]; fis = &initial_fis->fis; - ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK1); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk | 1 << phy_no); + offset = 4 * (phy_no / 4); + ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK1 + offset); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, + ent_msk | 1 << ((phy_no % 4) * 8)); - ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1); - ent_tmp = ent_int & (1 << (ENT_INT_SRC1_D2H_FIS_CH1_OFF * phy_no)); + ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1 + offset); + ent_tmp = ent_int & (1 << (ENT_INT_SRC1_D2H_FIS_CH1_OFF * + (phy_no % 4))); ent_int >>= ENT_INT_SRC1_D2H_FIS_CH1_OFF * (phy_no % 4); if ((ent_int & ENT_INT_SRC1_D2H_FIS_CH0_MSK) == 0) { dev_warn(dev, "sata int: phy%d did not receive FIS\n", phy_no); @@ -2054,8 +2057,8 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) queue_work(hisi_hba->wq, &phy->phyup_ws); end: - hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk); + hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, ent_msk); return res; } -- GitLab From f76a0b49402b39b2d314ced52aac2f02d6a6c45d Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:14 +0800 Subject: [PATCH 3047/9938] hisi_sas: for v2 hw only set ITCT qw2 for SAS device This patch fixes the ITCT table setup as it should be configured differently for SAS and SATA devices. For SATA disks there is no need to set qw2 (already zeroed). Also, link parameters for Bus inactive limit, max connection time limit, and reject to open limit timers parameters are changed to match global config register, MAX_CON_TIME_LIMIT_TIME, as recommended by hw team. Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index cc083b9b1041..4276594a14c8 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -554,10 +554,11 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, itct->sas_addr = __swab64(itct->sas_addr); /* qw2 */ - itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) | - (0xff00ULL << ITCT_HDR_BITLT_OFF) | - (0xff00ULL << ITCT_HDR_MCTLT_OFF) | - (0xff00ULL << ITCT_HDR_RTOLT_OFF)); + if (!dev_is_sata(device)) + itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) | + (0x1ULL << ITCT_HDR_BITLT_OFF) | + (0x32ULL << ITCT_HDR_MCTLT_OFF) | + (0x1ULL << ITCT_HDR_RTOLT_OFF)); } static void free_device_v2_hw(struct hisi_hba *hisi_hba, @@ -715,7 +716,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL, 0x7FF); hisi_sas_write32(hisi_hba, OPENA_WT_CONTI_TIME, 0x1); hisi_sas_write32(hisi_hba, I_T_NEXUS_LOSS_TIME, 0x1F4); - hisi_sas_write32(hisi_hba, MAX_CON_TIME_LIMIT_TIME, 0x4E20); + hisi_sas_write32(hisi_hba, MAX_CON_TIME_LIMIT_TIME, 0x32); hisi_sas_write32(hisi_hba, BUS_INACTIVE_LIMIT_TIME, 0x1); hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1); hisi_sas_write32(hisi_hba, HGC_ERR_STAT_EN, 0x1); -- GitLab From 33e56e48ea3b3f58358d12b28f36474040325f0c Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 8 Apr 2016 17:23:15 +0800 Subject: [PATCH 3048/9938] hisi_sas: update driver version to 1.4 Signed-off-by: John Garry Reviewed-by: Zhangfei Gao Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index fa12eeac140c..0978016482c1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -23,7 +23,7 @@ #include #include -#define DRV_VERSION "v1.3" +#define DRV_VERSION "v1.4" #define HISI_SAS_MAX_PHYS 9 #define HISI_SAS_MAX_QUEUES 32 -- GitLab From 5ea33eb573c9858cdebfb69626cc8621c7468f9e Mon Sep 17 00:00:00 2001 From: Tina Ruchandani Date: Mon, 25 Jan 2016 23:00:20 +0100 Subject: [PATCH 3049/9938] qla2xxx: Remove use of 'struct timeval' struct register_host_info stores a 64-bit UTC system time timestamp. This patch removes the use of 'struct timeval' to obtain that timestamp as its tv_sec value will overflow on 32-bit systems in year 2038 beyond. The patch uses ktime_get_real_seconds() which returns a 64-bit seconds value. Signed-off-by: Tina Ruchandani Reviewed-by: Johannes Thumshirn Acked-by: Himanshu Madhani Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index b5029e543b91..15dff7099955 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -6,6 +6,7 @@ */ #include "qla_def.h" #include +#include #include #include #include @@ -1812,7 +1813,6 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) struct host_system_info *phost_info; struct register_host_info *preg_hsi; struct new_utsname *p_sysid = NULL; - struct timeval tv; sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) @@ -1886,8 +1886,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) p_sysid->domainname, DOMNAME_LENGTH); strncpy(phost_info->hostdriver, QLA2XXX_VERSION, VERSION_LENGTH); - do_gettimeofday(&tv); - preg_hsi->utc = (uint64_t)tv.tv_sec; + preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); ql_dbg(ql_dbg_init, vha, 0x0149, "ISP%04X: Host registration with firmware\n", ha->pdev->device); -- GitLab From e83596b41cb9729837468a1c14de56a5529a2aa6 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 13 Apr 2016 14:26:56 -0700 Subject: [PATCH 3050/9938] pm80xx: Remove bogus address masking in pm8001_ioremap() It is unclear what the original intent of the masking was, but it is clearly incorrect to truncate a physical address before calling ioremap(). On systems where there are valid physical address bits above bit-31 (arm64 for example) the result is an eventual OOPs when initializing the driver. Remove the bogus code to fix it. Signed-off-by: David Daney Acked-by: Jack Wang Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 062ab34b86f8..6bd7bf4f4a81 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -418,8 +418,6 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha) if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { pm8001_ha->io_mem[logicalBar].membase = pci_resource_start(pdev, bar); - pm8001_ha->io_mem[logicalBar].membase &= - (u32)PCI_BASE_ADDRESS_MEM_MASK; pm8001_ha->io_mem[logicalBar].memsize = pci_resource_len(pdev, bar); pm8001_ha->io_mem[logicalBar].memvirtaddr = -- GitLab From 23409bd4a8b051e28d0106c7a83f362617452098 Mon Sep 17 00:00:00 2001 From: Tina Ruchandani Date: Wed, 13 Apr 2016 00:01:40 -0700 Subject: [PATCH 3051/9938] mpt3sas: Remove usage of 'struct timeval' 'struct timeval' will have its tv_sec value overflow on 32-bit systems in year 2038 and beyond. This patch replaces the use of struct timeval for computing mpi_request.TimeStamp, and instead uses ktime_t which provides 64-bit seconds value. The timestamp computed remains unaffected (milliseconds since Unix epoch). Signed-off-by: Tina Ruchandani Reviewed-by: Arnd Bergmann Reviewed-by: Johannes Thumshirn Acked-by: Sathya Prakash Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 28d85314b3c6..93d7c28f8162 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -4387,7 +4388,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) Mpi2IOCInitRequest_t mpi_request; Mpi2IOCInitReply_t mpi_reply; int i, r = 0; - struct timeval current_time; + ktime_t current_time; u16 ioc_status; u32 reply_post_free_array_sz = 0; Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL; @@ -4449,9 +4450,8 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) /* This time stamp specifies number of milliseconds * since epoch ~ midnight January 1, 1970. */ - do_gettimeofday(¤t_time); - mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 + - (current_time.tv_usec / 1000)); + current_time = ktime_get_real(); + mpi_request.TimeStamp = cpu_to_le64(ktime_to_ms(current_time)); if (ioc->logging_level & MPT_DEBUG_INIT) { __le32 *mfp; -- GitLab From 1f275f976fdc04bf1bfd06929d10852b1b05decc Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 14 Apr 2016 10:27:14 -0700 Subject: [PATCH 3052/9938] scsi_dh_alua: Declare local functions static This patch avoids that building with W=1 causes gcc to report the following type of warning: no previous prototype for ... [-Wmissing-prototypes] Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinicke Cc: Hannes Reinecke Cc: Christoph Hellwig Cc: Ewan Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 8eaed0522aa3..e034f12c1418 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -190,8 +190,8 @@ static int submit_stpg(struct scsi_device *sdev, int group_id, ALUA_FAILOVER_RETRIES, NULL, req_flags); } -struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, - int group_id) +static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, + int group_id) { struct alua_port_group *pg; @@ -219,8 +219,8 @@ struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size, * Allocate a new port_group structure for a given * device. */ -struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev, - int group_id, int tpgs) +static struct alua_port_group *alua_alloc_pg(struct scsi_device *sdev, + int group_id, int tpgs) { struct alua_port_group *pg, *tmp_pg; -- GitLab From c3e385a1b985a9202ba7fbd0bdbdcb909905d00c Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:30 -0700 Subject: [PATCH 3053/9938] megaraid_sas: reduce memory footprints in kdump mode This patch will reduce memory footprints of megaraid_sas driver when booted in kdump mode. Driver will not allocate memory for optional and perfromance oriented features. Below are key changes done in megaraid_sas driver to do this: 1. Limit Controller's queue depth to 100 in kdump mode. 2. Do not allocate memory for system info buffer and PD info buffer. 3. Disable performance oriented features e.g. Disable RDPQ mode, disable dual queue depth, restrict to single MSI-x vector. Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 2 + drivers/scsi/megaraid/megaraid_sas_base.c | 48 +++++++++++++-------- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 ++ 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index fce414a2cd76..1784b09523d3 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1344,6 +1344,8 @@ struct megasas_ctrl_info { #define SCAN_PD_CHANNEL 0x1 #define SCAN_VD_CHANNEL 0x2 +#define MEGASAS_KDUMP_QUEUE_DEPTH 100 + enum MR_SCSI_CMD_TYPE { READ_WRITE_LDIO = 0, NON_READ_WRITE_LDIO = 1, diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index e6ebc7ae2df1..858820255dcb 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5761,13 +5761,6 @@ static int megasas_probe_one(struct pci_dev *pdev, break; } - instance->system_info_buf = pci_zalloc_consistent(pdev, - sizeof(struct MR_DRV_SYSTEM_INFO), - &instance->system_info_h); - - if (!instance->system_info_buf) - dev_info(&instance->pdev->dev, "Can't allocate system info buffer\n"); - /* Crash dump feature related initialisation*/ instance->drv_buf_index = 0; instance->drv_buf_alloc = 0; @@ -5777,14 +5770,6 @@ static int megasas_probe_one(struct pci_dev *pdev, spin_lock_init(&instance->crashdump_lock); instance->crash_dump_buf = NULL; - if (!reset_devices) - instance->crash_dump_buf = pci_alloc_consistent(pdev, - CRASH_DMA_BUF_SIZE, - &instance->crash_dump_h); - if (!instance->crash_dump_buf) - dev_err(&pdev->dev, "Can't allocate Firmware " - "crash dump DMA buffer\n"); - megasas_poll_wait_aen = 0; instance->flag_ieee = 0; instance->ev = NULL; @@ -5803,11 +5788,26 @@ static int megasas_probe_one(struct pci_dev *pdev, goto fail_alloc_dma_buf; } - instance->pd_info = pci_alloc_consistent(pdev, - sizeof(struct MR_PD_INFO), &instance->pd_info_h); + if (!reset_devices) { + instance->system_info_buf = pci_zalloc_consistent(pdev, + sizeof(struct MR_DRV_SYSTEM_INFO), + &instance->system_info_h); + if (!instance->system_info_buf) + dev_info(&instance->pdev->dev, "Can't allocate system info buffer\n"); + + instance->pd_info = pci_alloc_consistent(pdev, + sizeof(struct MR_PD_INFO), &instance->pd_info_h); - if (!instance->pd_info) - dev_err(&instance->pdev->dev, "Failed to alloc mem for pd_info\n"); + if (!instance->pd_info) + dev_err(&instance->pdev->dev, "Failed to alloc mem for pd_info\n"); + + instance->crash_dump_buf = pci_alloc_consistent(pdev, + CRASH_DMA_BUF_SIZE, + &instance->crash_dump_h); + if (!instance->crash_dump_buf) + dev_err(&pdev->dev, "Can't allocate Firmware " + "crash dump DMA buffer\n"); + } /* * Initialize locks and queues @@ -7173,6 +7173,16 @@ static int __init megasas_init(void) { int rval; + /* + * Booted in kdump kernel, minimize memory footprints by + * disabling few features + */ + if (reset_devices) { + msix_vectors = 1; + rdpq_enable = 0; + dual_qdepth_disable = 1; + } + /* * Announce driver version and other information */ diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 98a848bdfdc2..320c1a0952d0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -257,6 +257,9 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c if (!instance->is_rdpq) instance->max_fw_cmds = min_t(u16, instance->max_fw_cmds, 1024); + if (reset_devices) + instance->max_fw_cmds = min(instance->max_fw_cmds, + (u16)MEGASAS_KDUMP_QUEUE_DEPTH); /* * Reduce the max supported cmds by 1. This is to ensure that the * reply_q_sz (1 more than the max cmd that driver may send) -- GitLab From 64d0b8e4a6f7e9a3c366c2df93ec1f003d180ca3 Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:31 -0700 Subject: [PATCH 3054/9938] megaraid_sas: call ISR function to clean up pending replies in OCR path In OCR path, before calling chip reset calls function megasas_wait_for_outstanding_fusion to check reason for OCR. In case of firmware FAULT initiated OCR and DCMD timeout initiated timeout, driver will clear any outstanding reply (yet to be processed by driver) in reply queues before going for chip reset. This code is added to handle a scenario when IO timeout initiated adapter reset and management application initiated adapter reset (by sending command to FAULT firmware) happens simultaneously since adapter reset function is safe-guarded by reset_mutex so only thread will be doing controller reset. Consider IO timeout thread gets mutex and proceeds with adapter reset process after disabling interrupts and by the time management application has fired command to firmware to do adapter reset and the same command is completed by firmware but since interrupts are disabled, driver will not get completion and the same command will be in outstanding/pending commands list of driver and refires same command from IO timeout thread after chip reset which will again FAULT firmware and eventually causes kill adapter. Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 320c1a0952d0..e2dc20566ab7 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -2762,6 +2762,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, dev_warn(&instance->pdev->dev, "Found FW in FAULT state," " will reset adapter scsi%d.\n", instance->host->host_no); + megasas_complete_cmd_dpc_fusion((unsigned long)instance); retval = 1; goto out; } @@ -2769,6 +2770,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, if (reason == MFI_IO_TIMEOUT_OCR) { dev_info(&instance->pdev->dev, "MFI IO is timed out, initiating OCR\n"); + megasas_complete_cmd_dpc_fusion((unsigned long)instance); retval = 1; goto out; } -- GitLab From bd23d4abe5edf09dfba086d44b7972cf73c14b0b Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:32 -0700 Subject: [PATCH 3055/9938] megaraid_sas: task management code optimizations This patch will do code optmization for task management functions. Below are key changes: 1. Remove reset_device hook as it was not being used and driver was setting this to NULL. 2. Create wrapper functions for task abort and target reset and inside these functions adapter specific calls be made. e.g. fusion adapters support task abort and target reset so task abort and target reset should be issued to fusion adapters only and for MFI adapters, print a message saying feature not supported. Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 67 ++++++++++++++++------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 858820255dcb..b84756c1d230 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2669,17 +2669,6 @@ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) return BLK_EH_RESET_TIMER; } -/** - * megasas_reset_device - Device reset handler entry point - */ -static int megasas_reset_device(struct scsi_cmnd *scmd) -{ - /* - * First wait for all commands to complete - */ - return megasas_generic_reset(scmd); -} - /** * megasas_reset_bus_host - Bus & host reset handler entry point */ @@ -2701,6 +2690,50 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) return ret; } +/** + * megasas_task_abort - Issues task abort request to firmware + * (supported only for fusion adapters) + * @scmd: SCSI command pointer + */ +static int megasas_task_abort(struct scsi_cmnd *scmd) +{ + int ret; + struct megasas_instance *instance; + + instance = (struct megasas_instance *)scmd->device->host->hostdata; + + if (instance->ctrl_context) + ret = megasas_task_abort_fusion(scmd); + else { + sdev_printk(KERN_NOTICE, scmd->device, "TASK ABORT not supported\n"); + ret = FAILED; + } + + return ret; +} + +/** + * megasas_reset_target: Issues target reset request to firmware + * (supported only for fusion adapters) + * @scmd: SCSI command pointer + */ +static int megasas_reset_target(struct scsi_cmnd *scmd) +{ + int ret; + struct megasas_instance *instance; + + instance = (struct megasas_instance *)scmd->device->host->hostdata; + + if (instance->ctrl_context) + ret = megasas_reset_target_fusion(scmd); + else { + sdev_printk(KERN_NOTICE, scmd->device, "TARGET RESET not supported\n"); + ret = FAILED; + } + + return ret; +} + /** * megasas_bios_param - Returns disk geometry for a disk * @sdev: device handle @@ -2969,8 +3002,8 @@ static struct scsi_host_template megasas_template = { .slave_alloc = megasas_slave_alloc, .slave_destroy = megasas_slave_destroy, .queuecommand = megasas_queue_command, - .eh_device_reset_handler = megasas_reset_device, - .eh_bus_reset_handler = megasas_reset_bus_host, + .eh_target_reset_handler = megasas_reset_target, + .eh_abort_handler = megasas_task_abort, .eh_host_reset_handler = megasas_reset_bus_host, .eh_timed_out = megasas_reset_timer, .shost_attrs = megaraid_host_attrs, @@ -5598,14 +5631,6 @@ static int megasas_io_attach(struct megasas_instance *instance) host->max_lun = MEGASAS_MAX_LUN; host->max_cmd_len = 16; - /* Fusion only supports host reset */ - if (instance->ctrl_context) { - host->hostt->eh_device_reset_handler = NULL; - host->hostt->eh_bus_reset_handler = NULL; - host->hostt->eh_target_reset_handler = megasas_reset_target_fusion; - host->hostt->eh_abort_handler = megasas_task_abort_fusion; - } - /* * Notify the mid-layer about the new controller */ -- GitLab From 54c4042852a85713a7bdd8436cc63762049fbb39 Mon Sep 17 00:00:00 2001 From: Sumit Saxena Date: Fri, 15 Apr 2016 00:23:33 -0700 Subject: [PATCH 3056/9938] megaraid_sas: driver version upgrade Signed-off-by: Sumit Saxena Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 1784b09523d3..ca86c885dfaa 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -35,8 +35,8 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "06.810.09.00-rc1" -#define MEGASAS_RELDATE "Jan. 28, 2016" +#define MEGASAS_VERSION "06.811.02.00-rc1" +#define MEGASAS_RELDATE "April 12, 2016" /* * Device IDs -- GitLab From 685b6d6e678705bf7ff5b7fdd9a904ec7ae9fbe3 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 15 Apr 2016 21:36:36 +0800 Subject: [PATCH 3057/9938] hisi_sas: add device and slot alloc hw methods Add methods to use HW specific versions of functions to allocate slot and device. HW specific methods are permitted to workaround device id vs IPTT collision issue in v2 hw. Signed-off-by: John Garry Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 3 +++ drivers/scsi/hisi_sas/hisi_sas_main.c | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 0978016482c1..d7cab724f203 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -133,6 +133,9 @@ struct hisi_sas_hw { int (*hw_init)(struct hisi_hba *hisi_hba); void (*setup_itct)(struct hisi_hba *hisi_hba, struct hisi_sas_device *device); + int (*slot_index_alloc)(struct hisi_hba *hisi_hba, int *slot_idx, + struct domain_device *device); + struct hisi_sas_device *(*alloc_dev)(struct domain_device *device); void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no); int (*get_free_slot)(struct hisi_hba *hisi_hba, int *q, int *s); void (*start_delivery)(struct hisi_hba *hisi_hba); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 097ab4f27a6b..18dd5ea2c721 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -227,7 +227,11 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, } else n_elem = task->num_scatter; - rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); + if (hisi_hba->hw->slot_index_alloc) + rc = hisi_hba->hw->slot_index_alloc(hisi_hba, &slot_idx, + device); + else + rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); if (rc) goto err_out; rc = hisi_hba->hw->get_free_slot(hisi_hba, &dlvry_queue, @@ -417,7 +421,10 @@ static int hisi_sas_dev_found(struct domain_device *device) struct hisi_sas_device *sas_dev; struct device *dev = &hisi_hba->pdev->dev; - sas_dev = hisi_sas_alloc_dev(device); + if (hisi_hba->hw->alloc_dev) + sas_dev = hisi_hba->hw->alloc_dev(device); + else + sas_dev = hisi_sas_alloc_dev(device); if (!sas_dev) { dev_err(dev, "fail alloc dev: max support %d devices\n", HISI_SAS_MAX_DEVICES); -- GitLab From 330fa7f3140481463eb4956c38b9a44dfeee52b9 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 15 Apr 2016 21:36:37 +0800 Subject: [PATCH 3058/9938] hisi_sas: add slot_index_alloc_quirk_v2_hw() Add v2 hw custom function slot_index_alloc_quirk_v2_hw(). SAS devices should have IPTT bit0 equal to 1. Signed-off-by: John Garry Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 4276594a14c8..f2966d8cde07 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -465,6 +465,33 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba, return readl(regs); } +/* This function needs to be protected from pre-emption. */ +static int +slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, + struct domain_device *device) +{ + unsigned int index = 0; + void *bitmap = hisi_hba->slot_index_tags; + int sata_dev = dev_is_sata(device); + + while (1) { + index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, + index); + if (index >= hisi_hba->slot_index_count) + return -SAS_QUEUE_FULL; + /* + * SAS IPTT bit0 should be 1 + */ + if (sata_dev || (index & 1)) + break; + index++; + } + + set_bit(index, bitmap); + *slot_idx = index; + return 0; +} + static void config_phy_opt_mode_v2_hw(struct hisi_hba *hisi_hba, int phy_no) { u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG); @@ -2167,6 +2194,7 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba) static const struct hisi_sas_hw hisi_sas_v2_hw = { .hw_init = hisi_sas_v2_init, .setup_itct = setup_itct_v2_hw, + .slot_index_alloc = slot_index_alloc_quirk_v2_hw, .sl_notify = sl_notify_v2_hw, .get_wideport_bitmap = get_wideport_bitmap_v2_hw, .free_device = free_device_v2_hw, -- GitLab From b2bdaf2bde16537cbdbd5376acecc555f428603f Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 15 Apr 2016 21:36:38 +0800 Subject: [PATCH 3059/9938] hisi_sas: add alloc_dev_quirk_v2_hw() Add custom version of function to allocate device, alloc_dev_quirk_v2_hw(). For sata devices the device id bit0 should be 0. Signed-off-by: John Garry Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index f2966d8cde07..bbe98ecea0bc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -492,6 +492,35 @@ slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba, int *slot_idx, return 0; } +static struct +hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device) +{ + struct hisi_hba *hisi_hba = device->port->ha->lldd_ha; + struct hisi_sas_device *sas_dev = NULL; + int i, sata_dev = dev_is_sata(device); + + spin_lock(&hisi_hba->lock); + for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) { + /* + * SATA device id bit0 should be 0 + */ + if (sata_dev && (i & 1)) + continue; + if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) { + hisi_hba->devices[i].device_id = i; + sas_dev = &hisi_hba->devices[i]; + sas_dev->dev_status = HISI_SAS_DEV_NORMAL; + sas_dev->dev_type = device->dev_type; + sas_dev->hisi_hba = hisi_hba; + sas_dev->sas_device = device; + break; + } + } + spin_unlock(&hisi_hba->lock); + + return sas_dev; +} + static void config_phy_opt_mode_v2_hw(struct hisi_hba *hisi_hba, int phy_no) { u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG); @@ -2195,6 +2224,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { .hw_init = hisi_sas_v2_init, .setup_itct = setup_itct_v2_hw, .slot_index_alloc = slot_index_alloc_quirk_v2_hw, + .alloc_dev = alloc_dev_quirk_v2_hw, .sl_notify = sl_notify_v2_hw, .get_wideport_bitmap = get_wideport_bitmap_v2_hw, .free_device = free_device_v2_hw, -- GitLab From ee1c27977284907d40f7f72c2d078d709f15811f Mon Sep 17 00:00:00 2001 From: Peter Heise Date: Wed, 13 Apr 2016 13:52:22 +0200 Subject: [PATCH 3060/9938] net/hsr: Added support for HSR v1 This patch adds support for the newer version 1 of the HSR networking standard. Version 0 is still default and the new version has to be selected via iproute2. Main changes are in the supervision frame handling and its ethertype field. Signed-off-by: Peter Heise Signed-off-by: David S. Miller --- include/uapi/linux/if_ether.h | 1 + include/uapi/linux/if_link.h | 1 + net/hsr/Kconfig | 5 ++- net/hsr/hsr_device.c | 80 ++++++++++++++++++++--------------- net/hsr/hsr_device.h | 2 +- net/hsr/hsr_forward.c | 43 ++++++++++++++----- net/hsr/hsr_framereg.c | 30 ++++++++----- net/hsr/hsr_main.h | 13 +++++- net/hsr/hsr_netlink.c | 10 ++++- net/hsr/hsr_slave.c | 4 +- 10 files changed, 126 insertions(+), 63 deletions(-) diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 4a93051c578c..cec849a239f6 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -92,6 +92,7 @@ #define ETH_P_TDLS 0x890D /* TDLS */ #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ #define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent Handover Protocol */ +#define ETH_P_HSR 0x892F /* IEC 62439-3 HSRv1 */ #define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */ #define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 9427f17d06d6..bb3a90b57199 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -773,6 +773,7 @@ enum { IFLA_HSR_SLAVE1, IFLA_HSR_SLAVE2, IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ + IFLA_HSR_VERSION, /* HSR version */ IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ IFLA_HSR_SEQ_NR, __IFLA_HSR_MAX, diff --git a/net/hsr/Kconfig b/net/hsr/Kconfig index 0d3d709052ca..4b683fd0abf1 100644 --- a/net/hsr/Kconfig +++ b/net/hsr/Kconfig @@ -18,8 +18,9 @@ config HSR earlier. This code is a "best effort" to comply with the HSR standard as - described in IEC 62439-3:2010 (HSRv0), but no compliancy tests have - been made. + described in IEC 62439-3:2010 (HSRv0) and IEC 62439-3:2012 (HSRv1), + but no compliancy tests have been made. Use iproute2 to select + the version you desire. You need to perform any and all necessary tests yourself before relying on this code in a safety critical system! diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index c7d1adca30d8..386cbce7bc51 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -90,7 +90,8 @@ static void hsr_check_announce(struct net_device *hsr_dev, hsr = netdev_priv(hsr_dev); - if ((hsr_dev->operstate == IF_OPER_UP) && (old_operstate != IF_OPER_UP)) { + if ((hsr_dev->operstate == IF_OPER_UP) + && (old_operstate != IF_OPER_UP)) { /* Went up */ hsr->announce_count = 0; hsr->announce_timer.expires = jiffies + @@ -250,31 +251,22 @@ static const struct header_ops hsr_header_ops = { .parse = eth_header_parse, }; - -/* HSR:2010 supervision frames should be padded so that the whole frame, - * including headers and FCS, is 64 bytes (without VLAN). - */ -static int hsr_pad(int size) -{ - const int min_size = ETH_ZLEN - HSR_HLEN - ETH_HLEN; - - if (size >= min_size) - return size; - return min_size; -} - -static void send_hsr_supervision_frame(struct hsr_port *master, u8 type) +static void send_hsr_supervision_frame(struct hsr_port *master, + u8 type, u8 hsrVer) { struct sk_buff *skb; int hlen, tlen; + struct hsr_tag *hsr_tag; struct hsr_sup_tag *hsr_stag; struct hsr_sup_payload *hsr_sp; unsigned long irqflags; hlen = LL_RESERVED_SPACE(master->dev); tlen = master->dev->needed_tailroom; - skb = alloc_skb(hsr_pad(sizeof(struct hsr_sup_payload)) + hlen + tlen, - GFP_ATOMIC); + skb = dev_alloc_skb( + sizeof(struct hsr_tag) + + sizeof(struct hsr_sup_tag) + + sizeof(struct hsr_sup_payload) + hlen + tlen); if (skb == NULL) return; @@ -282,32 +274,48 @@ static void send_hsr_supervision_frame(struct hsr_port *master, u8 type) skb_reserve(skb, hlen); skb->dev = master->dev; - skb->protocol = htons(ETH_P_PRP); + skb->protocol = htons(hsrVer ? ETH_P_HSR : ETH_P_PRP); skb->priority = TC_PRIO_CONTROL; - if (dev_hard_header(skb, skb->dev, ETH_P_PRP, + if (dev_hard_header(skb, skb->dev, (hsrVer ? ETH_P_HSR : ETH_P_PRP), master->hsr->sup_multicast_addr, skb->dev->dev_addr, skb->len) <= 0) goto out; skb_reset_mac_header(skb); - hsr_stag = (typeof(hsr_stag)) skb_put(skb, sizeof(*hsr_stag)); + if (hsrVer > 0) { + hsr_tag = (typeof(hsr_tag)) skb_put(skb, sizeof(struct hsr_tag)); + hsr_tag->encap_proto = htons(ETH_P_PRP); + set_hsr_tag_LSDU_size(hsr_tag, HSR_V1_SUP_LSDUSIZE); + } - set_hsr_stag_path(hsr_stag, 0xf); - set_hsr_stag_HSR_Ver(hsr_stag, 0); + hsr_stag = (typeof(hsr_stag)) skb_put(skb, sizeof(struct hsr_sup_tag)); + set_hsr_stag_path(hsr_stag, (hsrVer ? 0x0 : 0xf)); + set_hsr_stag_HSR_Ver(hsr_stag, hsrVer); + /* From HSRv1 on we have separate supervision sequence numbers. */ spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); - hsr_stag->sequence_nr = htons(master->hsr->sequence_nr); - master->hsr->sequence_nr++; + if (hsrVer > 0) { + hsr_stag->sequence_nr = htons(master->hsr->sup_sequence_nr); + hsr_tag->sequence_nr = htons(master->hsr->sequence_nr); + master->hsr->sup_sequence_nr++; + master->hsr->sequence_nr++; + } else { + hsr_stag->sequence_nr = htons(master->hsr->sequence_nr); + master->hsr->sequence_nr++; + } spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); hsr_stag->HSR_TLV_Type = type; - hsr_stag->HSR_TLV_Length = 12; + /* TODO: Why 12 in HSRv0? */ + hsr_stag->HSR_TLV_Length = hsrVer ? sizeof(struct hsr_sup_payload) : 12; /* Payload: MacAddressA */ - hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(*hsr_sp)); + hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(struct hsr_sup_payload)); ether_addr_copy(hsr_sp->MacAddressA, master->dev->dev_addr); + skb_put_padto(skb, ETH_ZLEN + HSR_HLEN); + hsr_forward_skb(skb, master); return; @@ -329,19 +337,20 @@ static void hsr_announce(unsigned long data) rcu_read_lock(); master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); - if (hsr->announce_count < 3) { - send_hsr_supervision_frame(master, HSR_TLV_ANNOUNCE); + if (hsr->announce_count < 3 && hsr->protVersion == 0) { + send_hsr_supervision_frame(master, HSR_TLV_ANNOUNCE, + hsr->protVersion); hsr->announce_count++; - } else { - send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK); - } - if (hsr->announce_count < 3) hsr->announce_timer.expires = jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL); - else + } else { + send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK, + hsr->protVersion); + hsr->announce_timer.expires = jiffies + msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); + } if (is_admin_up(master->dev)) add_timer(&hsr->announce_timer); @@ -428,7 +437,7 @@ static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = { }; int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], - unsigned char multicast_spec) + unsigned char multicast_spec, u8 protocol_version) { struct hsr_priv *hsr; struct hsr_port *port; @@ -450,6 +459,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], spin_lock_init(&hsr->seqnr_lock); /* Overflow soon to find bugs easier: */ hsr->sequence_nr = HSR_SEQNR_START; + hsr->sup_sequence_nr = HSR_SUP_SEQNR_START; init_timer(&hsr->announce_timer); hsr->announce_timer.function = hsr_announce; @@ -462,6 +472,8 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr); hsr->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; + hsr->protVersion = protocol_version; + /* FIXME: should I modify the value of these? * * - hsr_dev->flags - i.e. diff --git a/net/hsr/hsr_device.h b/net/hsr/hsr_device.h index 108a5d59d2a6..9975e31bbb82 100644 --- a/net/hsr/hsr_device.h +++ b/net/hsr/hsr_device.h @@ -17,7 +17,7 @@ void hsr_dev_setup(struct net_device *dev); int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], - unsigned char multicast_spec); + unsigned char multicast_spec, u8 protocol_version); void hsr_check_carrier_and_operstate(struct hsr_priv *hsr); bool is_hsr_master(struct net_device *dev); int hsr_get_max_mtu(struct hsr_priv *hsr); diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index 7871ed6d3825..5ee1d43f1310 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -50,21 +50,40 @@ struct hsr_frame_info { */ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb) { - struct hsr_ethhdr_sp *hdr; + struct ethhdr *ethHdr; + struct hsr_sup_tag *hsrSupTag; + struct hsrv1_ethhdr_sp *hsrV1Hdr; WARN_ON_ONCE(!skb_mac_header_was_set(skb)); - hdr = (struct hsr_ethhdr_sp *) skb_mac_header(skb); + ethHdr = (struct ethhdr *) skb_mac_header(skb); - if (!ether_addr_equal(hdr->ethhdr.h_dest, + /* Correct addr? */ + if (!ether_addr_equal(ethHdr->h_dest, hsr->sup_multicast_addr)) return false; - if (get_hsr_stag_path(&hdr->hsr_sup) != 0x0f) + /* Correct ether type?. */ + if (!(ethHdr->h_proto == htons(ETH_P_PRP) + || ethHdr->h_proto == htons(ETH_P_HSR))) return false; - if ((hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_ANNOUNCE) && - (hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_LIFE_CHECK)) + + /* Get the supervision header from correct location. */ + if (ethHdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */ + hsrV1Hdr = (struct hsrv1_ethhdr_sp *) skb_mac_header(skb); + if (hsrV1Hdr->hsr.encap_proto != htons(ETH_P_PRP)) + return false; + + hsrSupTag = &hsrV1Hdr->hsr_sup; + } else { + hsrSupTag = &((struct hsrv0_ethhdr_sp *) skb_mac_header(skb))->hsr_sup; + } + + if ((hsrSupTag->HSR_TLV_Type != HSR_TLV_ANNOUNCE) && + (hsrSupTag->HSR_TLV_Type != HSR_TLV_LIFE_CHECK)) return false; - if (hdr->hsr_sup.HSR_TLV_Length != 12) + if ((hsrSupTag->HSR_TLV_Length != 12) && + (hsrSupTag->HSR_TLV_Length != + sizeof(struct hsr_sup_payload))) return false; return true; @@ -110,7 +129,7 @@ static struct sk_buff *frame_get_stripped_skb(struct hsr_frame_info *frame, static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, - struct hsr_port *port) + struct hsr_port *port, u8 protoVersion) { struct hsr_ethhdr *hsr_ethhdr; int lane_id; @@ -131,7 +150,8 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr); hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; - hsr_ethhdr->ethhdr.h_proto = htons(ETH_P_PRP); + hsr_ethhdr->ethhdr.h_proto = htons(protoVersion ? + ETH_P_HSR : ETH_P_PRP); } static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, @@ -160,7 +180,7 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, memmove(dst, src, movelen); skb_reset_mac_header(skb); - hsr_fill_tag(skb, frame, port); + hsr_fill_tag(skb, frame, port, port->hsr->protVersion); return skb; } @@ -320,7 +340,8 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame, /* FIXME: */ WARN_ONCE(1, "HSR: VLAN not yet supported"); } - if (ethhdr->h_proto == htons(ETH_P_PRP)) { + if (ethhdr->h_proto == htons(ETH_P_PRP) + || ethhdr->h_proto == htons(ETH_P_HSR)) { frame->skb_std = NULL; frame->skb_hsr = skb; frame->sequence_nr = hsr_get_skb_sequence_nr(skb); diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index bace124d14ef..7ea925816f79 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -177,17 +177,17 @@ struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, return node; } - if (!is_sup) - return NULL; /* Only supervision frame may create node entry */ + /* Everyone may create a node entry, connected node to a HSR device. */ - if (ethhdr->h_proto == htons(ETH_P_PRP)) { + if (ethhdr->h_proto == htons(ETH_P_PRP) + || ethhdr->h_proto == htons(ETH_P_HSR)) { /* Use the existing sequence_nr from the tag as starting point * for filtering duplicate frames. */ seq_out = hsr_get_skb_sequence_nr(skb) - 1; } else { WARN_ONCE(1, "%s: Non-HSR frame\n", __func__); - seq_out = 0; + seq_out = HSR_SEQNR_START; } return hsr_add_node(node_db, ethhdr->h_source, seq_out); @@ -200,17 +200,25 @@ struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr, struct hsr_port *port_rcv) { + struct ethhdr *ethhdr; struct hsr_node *node_real; struct hsr_sup_payload *hsr_sp; struct list_head *node_db; int i; - skb_pull(skb, sizeof(struct hsr_ethhdr_sp)); - hsr_sp = (struct hsr_sup_payload *) skb->data; + ethhdr = (struct ethhdr *) skb_mac_header(skb); - if (ether_addr_equal(eth_hdr(skb)->h_source, hsr_sp->MacAddressA)) - /* Not sent from MacAddressB of a PICS_SUBS capable node */ - goto done; + /* Leave the ethernet header. */ + skb_pull(skb, sizeof(struct ethhdr)); + + /* And leave the HSR tag. */ + if (ethhdr->h_proto == htons(ETH_P_HSR)) + skb_pull(skb, sizeof(struct hsr_tag)); + + /* And leave the HSR sup tag. */ + skb_pull(skb, sizeof(struct hsr_sup_tag)); + + hsr_sp = (struct hsr_sup_payload *) skb->data; /* Merge node_curr (registered on MacAddressB) into node_real */ node_db = &port_rcv->hsr->node_db; @@ -225,7 +233,7 @@ void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr, /* Node has already been merged */ goto done; - ether_addr_copy(node_real->MacAddressB, eth_hdr(skb)->h_source); + ether_addr_copy(node_real->MacAddressB, ethhdr->h_source); for (i = 0; i < HSR_PT_PORTS; i++) { if (!node_curr->time_in_stale[i] && time_after(node_curr->time_in[i], node_real->time_in[i])) { @@ -241,7 +249,7 @@ void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr, kfree_rcu(node_curr, rcu_head); done: - skb_push(skb, sizeof(struct hsr_ethhdr_sp)); + skb_push(skb, sizeof(struct hsrv1_ethhdr_sp)); } diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h index 5a9c69962ded..9b9909e89e9e 100644 --- a/net/hsr/hsr_main.h +++ b/net/hsr/hsr_main.h @@ -30,6 +30,7 @@ */ #define MAX_SLAVE_DIFF 3000 /* ms */ #define HSR_SEQNR_START (USHRT_MAX - 1024) +#define HSR_SUP_SEQNR_START (HSR_SEQNR_START / 2) /* How often shall we check for broken ring and remove node entries older than @@ -58,6 +59,8 @@ struct hsr_tag { #define HSR_HLEN 6 +#define HSR_V1_SUP_LSDUSIZE 52 + /* The helper functions below assumes that 'path' occupies the 4 most * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or * equivalently, the 4 most significant bits of HSR tag byte 14). @@ -131,8 +134,14 @@ static inline void set_hsr_stag_HSR_Ver(struct hsr_sup_tag *hst, u16 HSR_Ver) set_hsr_tag_LSDU_size((struct hsr_tag *) hst, HSR_Ver); } -struct hsr_ethhdr_sp { +struct hsrv0_ethhdr_sp { + struct ethhdr ethhdr; + struct hsr_sup_tag hsr_sup; +} __packed; + +struct hsrv1_ethhdr_sp { struct ethhdr ethhdr; + struct hsr_tag hsr; struct hsr_sup_tag hsr_sup; } __packed; @@ -162,6 +171,8 @@ struct hsr_priv { struct timer_list prune_timer; int announce_count; u16 sequence_nr; + u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ + u8 protVersion; /* Indicate if HSRv0 or HSRv1. */ spinlock_t seqnr_lock; /* locking for sequence_nr */ unsigned char sup_multicast_addr[ETH_ALEN]; }; diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index a2c7e4c0ac1e..5425d87611fc 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -23,6 +23,7 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = { [IFLA_HSR_SLAVE1] = { .type = NLA_U32 }, [IFLA_HSR_SLAVE2] = { .type = NLA_U32 }, [IFLA_HSR_MULTICAST_SPEC] = { .type = NLA_U8 }, + [IFLA_HSR_VERSION] = { .type = NLA_U8 }, [IFLA_HSR_SUPERVISION_ADDR] = { .type = NLA_BINARY, .len = ETH_ALEN }, [IFLA_HSR_SEQ_NR] = { .type = NLA_U16 }, }; @@ -35,7 +36,7 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct net_device *link[2]; - unsigned char multicast_spec; + unsigned char multicast_spec, hsr_version; if (!data) { netdev_info(dev, "HSR: No slave devices specified\n"); @@ -62,7 +63,12 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, else multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]); - return hsr_dev_finalize(dev, link, multicast_spec); + if (!data[IFLA_HSR_VERSION]) + hsr_version = 0; + else + hsr_version = nla_get_u8(data[IFLA_HSR_VERSION]); + + return hsr_dev_finalize(dev, link, multicast_spec, hsr_version); } static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev) diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index 7d37366cc695..f5b60388d02f 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -22,6 +22,7 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) { struct sk_buff *skb = *pskb; struct hsr_port *port; + u16 protocol; if (!skb_mac_header_was_set(skb)) { WARN_ONCE(1, "%s: skb invalid", __func__); @@ -37,7 +38,8 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) goto finish_consume; } - if (eth_hdr(skb)->h_proto != htons(ETH_P_PRP)) + protocol = eth_hdr(skb)->h_proto; + if (protocol != htons(ETH_P_PRP) && protocol != htons(ETH_P_HSR)) goto finish_pass; skb_push(skb, ETH_HLEN); -- GitLab From 464f664501816ef5fbbc00b8de96f4ae5a1c9325 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 14 Apr 2016 01:38:29 -0400 Subject: [PATCH 3061/9938] qed: Add infrastructure support for tunneling This patch adds various structure/APIs needed to configure/enable different tunnel [VXLAN/GRE/GENEVE] parameters on the adapter. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 46 ++++ drivers/net/ethernet/qlogic/qed/qed_dev.c | 6 +- drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 2 + drivers/net/ethernet/qlogic/qed/qed_hsi.h | 51 +++- .../ethernet/qlogic/qed/qed_init_fw_funcs.c | 127 +++++++++ drivers/net/ethernet/qlogic/qed/qed_l2.c | 31 +++ drivers/net/ethernet/qlogic/qed/qed_main.c | 2 +- .../net/ethernet/qlogic/qed/qed_reg_addr.h | 31 +++ drivers/net/ethernet/qlogic/qed/qed_sp.h | 7 + .../net/ethernet/qlogic/qed/qed_sp_commands.c | 254 ++++++++++++++++++ include/linux/qed/qed_eth_if.h | 10 + 11 files changed, 563 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 0f0d2d1d77e5..33e2ed60c18f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -74,6 +74,51 @@ struct qed_rt_data { bool *b_valid; }; +enum qed_tunn_mode { + QED_MODE_L2GENEVE_TUNN, + QED_MODE_IPGENEVE_TUNN, + QED_MODE_L2GRE_TUNN, + QED_MODE_IPGRE_TUNN, + QED_MODE_VXLAN_TUNN, +}; + +enum qed_tunn_clss { + QED_TUNN_CLSS_MAC_VLAN, + QED_TUNN_CLSS_MAC_VNI, + QED_TUNN_CLSS_INNER_MAC_VLAN, + QED_TUNN_CLSS_INNER_MAC_VNI, + MAX_QED_TUNN_CLSS, +}; + +struct qed_tunn_start_params { + unsigned long tunn_mode; + u16 vxlan_udp_port; + u16 geneve_udp_port; + u8 update_vxlan_udp_port; + u8 update_geneve_udp_port; + u8 tunn_clss_vxlan; + u8 tunn_clss_l2geneve; + u8 tunn_clss_ipgeneve; + u8 tunn_clss_l2gre; + u8 tunn_clss_ipgre; +}; + +struct qed_tunn_update_params { + unsigned long tunn_mode_update_mask; + unsigned long tunn_mode; + u16 vxlan_udp_port; + u16 geneve_udp_port; + u8 update_rx_pf_clss; + u8 update_tx_pf_clss; + u8 update_vxlan_udp_port; + u8 update_geneve_udp_port; + u8 tunn_clss_vxlan; + u8 tunn_clss_l2geneve; + u8 tunn_clss_ipgeneve; + u8 tunn_clss_l2gre; + u8 tunn_clss_ipgre; +}; + /* The PCI personality is not quite synonymous to protocol ID: * 1. All personalities need CORE connections * 2. The Ethernet personality may support also the RoCE protocol @@ -430,6 +475,7 @@ struct qed_dev { u8 num_hwfns; struct qed_hwfn hwfns[MAX_HWFNS_PER_DEVICE]; + unsigned long tunn_mode; u32 drv_type; struct qed_eth_stats *reset_stats; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index b7d100f6bd6f..bdae5a55afa4 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -558,6 +558,7 @@ static int qed_hw_init_port(struct qed_hwfn *p_hwfn, static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_tunn_start_params *p_tunn, int hw_mode, bool b_hw_start, enum qed_int_mode int_mode, @@ -625,7 +626,7 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, qed_int_igu_enable(p_hwfn, p_ptt, int_mode); /* send function start command */ - rc = qed_sp_pf_start(p_hwfn, p_hwfn->cdev->mf_mode); + rc = qed_sp_pf_start(p_hwfn, p_tunn, p_hwfn->cdev->mf_mode); if (rc) DP_NOTICE(p_hwfn, "Function start ramrod failed\n"); } @@ -672,6 +673,7 @@ static void qed_reset_mb_shadow(struct qed_hwfn *p_hwfn, } int qed_hw_init(struct qed_dev *cdev, + struct qed_tunn_start_params *p_tunn, bool b_hw_start, enum qed_int_mode int_mode, bool allow_npar_tx_switch, @@ -724,7 +726,7 @@ int qed_hw_init(struct qed_dev *cdev, /* Fall into */ case FW_MSG_CODE_DRV_LOAD_FUNCTION: rc = qed_hw_init_pf(p_hwfn, p_hwfn->p_main_ptt, - p_hwfn->hw_info.hw_mode, + p_tunn, p_hwfn->hw_info.hw_mode, b_hw_start, int_mode, allow_npar_tx_switch); break; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h index d6c7ddf4f4d4..6aac3f855aa1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h @@ -62,6 +62,7 @@ void qed_resc_setup(struct qed_dev *cdev); * @brief qed_hw_init - * * @param cdev + * @param p_tunn * @param b_hw_start * @param int_mode - interrupt mode [msix, inta, etc.] to use. * @param allow_npar_tx_switch - npar tx switching to be used @@ -72,6 +73,7 @@ void qed_resc_setup(struct qed_dev *cdev); * @return int */ int qed_hw_init(struct qed_dev *cdev, + struct qed_tunn_start_params *p_tunn, bool b_hw_start, enum qed_int_mode int_mode, bool allow_npar_tx_switch, diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index a368f5e71d95..15e02ab9be5a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -46,7 +46,7 @@ enum common_ramrod_cmd_id { COMMON_RAMROD_PF_STOP /* PF Function Stop Ramrod */, COMMON_RAMROD_RESERVED, COMMON_RAMROD_RESERVED2, - COMMON_RAMROD_RESERVED3, + COMMON_RAMROD_PF_UPDATE, COMMON_RAMROD_EMPTY, MAX_COMMON_RAMROD_CMD_ID }; @@ -626,6 +626,42 @@ struct pf_start_ramrod_data { u8 reserved0[4]; }; +/* tunnel configuration */ +struct pf_update_tunnel_config { + u8 update_rx_pf_clss; + u8 update_tx_pf_clss; + u8 set_vxlan_udp_port_flg; + u8 set_geneve_udp_port_flg; + u8 tx_enable_vxlan; + u8 tx_enable_l2geneve; + u8 tx_enable_ipgeneve; + u8 tx_enable_l2gre; + u8 tx_enable_ipgre; + u8 tunnel_clss_vxlan; + u8 tunnel_clss_l2geneve; + u8 tunnel_clss_ipgeneve; + u8 tunnel_clss_l2gre; + u8 tunnel_clss_ipgre; + __le16 vxlan_udp_port; + __le16 geneve_udp_port; + __le16 reserved[3]; +}; + +struct pf_update_ramrod_data { + u32 reserved[2]; + u32 reserved_1[6]; + struct pf_update_tunnel_config tunnel_config; +}; + +/* Tunnel classification scheme */ +enum tunnel_clss { + TUNNEL_CLSS_MAC_VLAN = 0, + TUNNEL_CLSS_MAC_VNI, + TUNNEL_CLSS_INNER_MAC_VLAN, + TUNNEL_CLSS_INNER_MAC_VNI, + MAX_TUNNEL_CLSS +}; + enum ports_mode { ENGX2_PORTX1 /* 2 engines x 1 port */, ENGX2_PORTX2 /* 2 engines x 2 ports */, @@ -1603,6 +1639,19 @@ bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn, u16 start_pq, u16 num_pqs); +void qed_set_vxlan_dest_port(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, u16 dest_port); +void qed_set_vxlan_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, bool vxlan_enable); +void qed_set_gre_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, bool eth_gre_enable, + bool ip_gre_enable); +void qed_set_geneve_dest_port(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, u16 dest_port); +void qed_set_geneve_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, bool eth_geneve_enable, + bool ip_geneve_enable); + /* Ystorm flow control mode. Use enum fw_flow_ctrl_mode */ #define YSTORM_FLOW_CONTROL_MODE_OFFSET (IRO[0].base) #define YSTORM_FLOW_CONTROL_MODE_SIZE (IRO[0].size) diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c index f55ebdc3c832..1dd53248b984 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c +++ b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c @@ -788,3 +788,130 @@ bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn, return true; } + +static void +qed_set_tunnel_type_enable_bit(unsigned long *var, int bit, bool enable) +{ + if (enable) + set_bit(bit, var); + else + clear_bit(bit, var); +} + +#define PRS_ETH_TUNN_FIC_FORMAT -188897008 + +void qed_set_vxlan_dest_port(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 dest_port) +{ + qed_wr(p_hwfn, p_ptt, PRS_REG_VXLAN_PORT, dest_port); + qed_wr(p_hwfn, p_ptt, NIG_REG_VXLAN_PORT, dest_port); + qed_wr(p_hwfn, p_ptt, PBF_REG_VXLAN_PORT, dest_port); +} + +void qed_set_vxlan_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool vxlan_enable) +{ + unsigned long reg_val = 0; + u8 shift; + + reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN); + shift = PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, vxlan_enable); + + qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); + + if (reg_val) + qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0, + PRS_ETH_TUNN_FIC_FORMAT); + + reg_val = qed_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE); + shift = NIG_REG_ENC_TYPE_ENABLE_VXLAN_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, vxlan_enable); + + qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val); + + qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_VXLAN_EN, + vxlan_enable ? 1 : 0); +} + +void qed_set_gre_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + bool eth_gre_enable, bool ip_gre_enable) +{ + unsigned long reg_val = 0; + u8 shift; + + reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN); + shift = PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, eth_gre_enable); + + shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, ip_gre_enable); + qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); + if (reg_val) + qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0, + PRS_ETH_TUNN_FIC_FORMAT); + + reg_val = qed_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE); + shift = NIG_REG_ENC_TYPE_ENABLE_ETH_OVER_GRE_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, eth_gre_enable); + + shift = NIG_REG_ENC_TYPE_ENABLE_IP_OVER_GRE_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, ip_gre_enable); + qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val); + + qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_GRE_ETH_EN, + eth_gre_enable ? 1 : 0); + qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_GRE_IP_EN, + ip_gre_enable ? 1 : 0); +} + +void qed_set_geneve_dest_port(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 dest_port) +{ + qed_wr(p_hwfn, p_ptt, PRS_REG_NGE_PORT, dest_port); + qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_PORT, dest_port); + qed_wr(p_hwfn, p_ptt, PBF_REG_NGE_PORT, dest_port); +} + +void qed_set_geneve_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool eth_geneve_enable, + bool ip_geneve_enable) +{ + unsigned long reg_val = 0; + u8 shift; + + reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN); + shift = PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, eth_geneve_enable); + + shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_SHIFT; + qed_set_tunnel_type_enable_bit(®_val, shift, ip_geneve_enable); + + qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); + if (reg_val) + qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0, + PRS_ETH_TUNN_FIC_FORMAT); + + qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_ETH_ENABLE, + eth_geneve_enable ? 1 : 0); + qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_IP_ENABLE, ip_geneve_enable ? 1 : 0); + + /* comp ver */ + reg_val = (ip_geneve_enable || eth_geneve_enable) ? 1 : 0; + qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_COMP_VER, reg_val); + qed_wr(p_hwfn, p_ptt, PBF_REG_NGE_COMP_VER, reg_val); + qed_wr(p_hwfn, p_ptt, PRS_REG_NGE_COMP_VER, reg_val); + + /* EDPM with geneve tunnel not supported in BB_B0 */ + if (QED_IS_BB_B0(p_hwfn->cdev)) + return; + + qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_NGE_ETH_EN, + eth_geneve_enable ? 1 : 0); + qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_NGE_IP_EN, + ip_geneve_enable ? 1 : 0); +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 5005497ee23e..fb5f3b815340 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1884,6 +1884,36 @@ static int qed_stop_txq(struct qed_dev *cdev, return 0; } +static int qed_tunn_configure(struct qed_dev *cdev, + struct qed_tunn_params *tunn_params) +{ + struct qed_tunn_update_params tunn_info; + int i, rc; + + memset(&tunn_info, 0, sizeof(tunn_info)); + if (tunn_params->update_vxlan_port == 1) { + tunn_info.update_vxlan_udp_port = 1; + tunn_info.vxlan_udp_port = tunn_params->vxlan_port; + } + + if (tunn_params->update_geneve_port == 1) { + tunn_info.update_geneve_udp_port = 1; + tunn_info.geneve_udp_port = tunn_params->geneve_port; + } + + for_each_hwfn(cdev, i) { + struct qed_hwfn *hwfn = &cdev->hwfns[i]; + + rc = qed_sp_pf_update_tunn_cfg(hwfn, &tunn_info, + QED_SPQ_MODE_EBLOCK, NULL); + + if (rc) + return rc; + } + + return 0; +} + static int qed_configure_filter_rx_mode(struct qed_dev *cdev, enum qed_filter_rx_mode_type type) { @@ -2026,6 +2056,7 @@ static const struct qed_eth_ops qed_eth_ops_pass = { .fastpath_stop = &qed_fastpath_stop, .eth_cqe_completion = &qed_fp_cqe_completion, .get_vport_stats = &qed_get_vport_stats, + .tunn_config = &qed_tunn_configure, }; const struct qed_eth_ops *qed_get_eth_ops(void) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index c31d485f72d6..1916992ae8b1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -776,7 +776,7 @@ static int qed_slowpath_start(struct qed_dev *cdev, /* Start the slowpath */ data = cdev->firmware->data; - rc = qed_hw_init(cdev, true, cdev->int_params.out.int_mode, + rc = qed_hw_init(cdev, NULL, true, cdev->int_params.out.int_mode, true, data); if (rc) goto err2; diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index c15b1622e636..55451a4dc587 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -427,4 +427,35 @@ 0x2aae60UL #define PGLUE_B_REG_PF_BAR1_SIZE \ 0x2aae64UL +#define PRS_REG_ENCAPSULATION_TYPE_EN 0x1f0730UL +#define PRS_REG_GRE_PROTOCOL 0x1f0734UL +#define PRS_REG_VXLAN_PORT 0x1f0738UL +#define PRS_REG_OUTPUT_FORMAT_4_0 0x1f099cUL +#define NIG_REG_ENC_TYPE_ENABLE 0x501058UL + +#define NIG_REG_ENC_TYPE_ENABLE_ETH_OVER_GRE_ENABLE (0x1 << 0) +#define NIG_REG_ENC_TYPE_ENABLE_ETH_OVER_GRE_ENABLE_SHIFT 0 +#define NIG_REG_ENC_TYPE_ENABLE_IP_OVER_GRE_ENABLE (0x1 << 1) +#define NIG_REG_ENC_TYPE_ENABLE_IP_OVER_GRE_ENABLE_SHIFT 1 +#define NIG_REG_ENC_TYPE_ENABLE_VXLAN_ENABLE (0x1 << 2) +#define NIG_REG_ENC_TYPE_ENABLE_VXLAN_ENABLE_SHIFT 2 + +#define NIG_REG_VXLAN_PORT 0x50105cUL +#define PBF_REG_VXLAN_PORT 0xd80518UL +#define PBF_REG_NGE_PORT 0xd8051cUL +#define PRS_REG_NGE_PORT 0x1f086cUL +#define NIG_REG_NGE_PORT 0x508b38UL + +#define DORQ_REG_L2_EDPM_TUNNEL_GRE_ETH_EN 0x10090cUL +#define DORQ_REG_L2_EDPM_TUNNEL_GRE_IP_EN 0x100910UL +#define DORQ_REG_L2_EDPM_TUNNEL_VXLAN_EN 0x100914UL +#define DORQ_REG_L2_EDPM_TUNNEL_NGE_IP_EN 0x10092cUL +#define DORQ_REG_L2_EDPM_TUNNEL_NGE_ETH_EN 0x100930UL + +#define NIG_REG_NGE_IP_ENABLE 0x508b28UL +#define NIG_REG_NGE_ETH_ENABLE 0x508b2cUL +#define NIG_REG_NGE_COMP_VER 0x508b30UL +#define PBF_REG_NGE_COMP_VER 0xd80524UL +#define PRS_REG_NGE_COMP_VER 0x1f0878UL + #endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index d39f914b66ee..4b91cb32f317 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -52,6 +52,7 @@ int qed_eth_cqe_completion(struct qed_hwfn *p_hwfn, union ramrod_data { struct pf_start_ramrod_data pf_start; + struct pf_update_ramrod_data pf_update; struct rx_queue_start_ramrod_data rx_queue_start; struct rx_queue_update_ramrod_data rx_queue_update; struct rx_queue_stop_ramrod_data rx_queue_stop; @@ -338,12 +339,14 @@ int qed_sp_init_request(struct qed_hwfn *p_hwfn, * to the internal RAM of the UStorm by the Function Start Ramrod. * * @param p_hwfn + * @param p_tunn * @param mode * * @return int */ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, + struct qed_tunn_start_params *p_tunn, enum qed_mf_mode mode); /** @@ -362,4 +365,8 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, int qed_sp_pf_stop(struct qed_hwfn *p_hwfn); +int qed_sp_pf_update_tunn_cfg(struct qed_hwfn *p_hwfn, + struct qed_tunn_update_params *p_tunn, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data); #endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c index 1c06c37d4c3d..306da7000ddc 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c @@ -87,7 +87,217 @@ int qed_sp_init_request(struct qed_hwfn *p_hwfn, return 0; } +static enum tunnel_clss qed_tunn_get_clss_type(u8 type) +{ + switch (type) { + case QED_TUNN_CLSS_MAC_VLAN: + return TUNNEL_CLSS_MAC_VLAN; + case QED_TUNN_CLSS_MAC_VNI: + return TUNNEL_CLSS_MAC_VNI; + case QED_TUNN_CLSS_INNER_MAC_VLAN: + return TUNNEL_CLSS_INNER_MAC_VLAN; + case QED_TUNN_CLSS_INNER_MAC_VNI: + return TUNNEL_CLSS_INNER_MAC_VNI; + default: + return TUNNEL_CLSS_MAC_VLAN; + } +} + +static void +qed_tunn_set_pf_fix_tunn_mode(struct qed_hwfn *p_hwfn, + struct qed_tunn_update_params *p_src, + struct pf_update_tunnel_config *p_tunn_cfg) +{ + unsigned long cached_tunn_mode = p_hwfn->cdev->tunn_mode; + unsigned long update_mask = p_src->tunn_mode_update_mask; + unsigned long tunn_mode = p_src->tunn_mode; + unsigned long new_tunn_mode = 0; + + if (test_bit(QED_MODE_L2GRE_TUNN, &update_mask)) { + if (test_bit(QED_MODE_L2GRE_TUNN, &tunn_mode)) + __set_bit(QED_MODE_L2GRE_TUNN, &new_tunn_mode); + } else { + if (test_bit(QED_MODE_L2GRE_TUNN, &cached_tunn_mode)) + __set_bit(QED_MODE_L2GRE_TUNN, &new_tunn_mode); + } + + if (test_bit(QED_MODE_IPGRE_TUNN, &update_mask)) { + if (test_bit(QED_MODE_IPGRE_TUNN, &tunn_mode)) + __set_bit(QED_MODE_IPGRE_TUNN, &new_tunn_mode); + } else { + if (test_bit(QED_MODE_IPGRE_TUNN, &cached_tunn_mode)) + __set_bit(QED_MODE_IPGRE_TUNN, &new_tunn_mode); + } + + if (test_bit(QED_MODE_VXLAN_TUNN, &update_mask)) { + if (test_bit(QED_MODE_VXLAN_TUNN, &tunn_mode)) + __set_bit(QED_MODE_VXLAN_TUNN, &new_tunn_mode); + } else { + if (test_bit(QED_MODE_VXLAN_TUNN, &cached_tunn_mode)) + __set_bit(QED_MODE_VXLAN_TUNN, &new_tunn_mode); + } + + if (p_src->update_geneve_udp_port) { + p_tunn_cfg->set_geneve_udp_port_flg = 1; + p_tunn_cfg->geneve_udp_port = + cpu_to_le16(p_src->geneve_udp_port); + } + + if (test_bit(QED_MODE_L2GENEVE_TUNN, &update_mask)) { + if (test_bit(QED_MODE_L2GENEVE_TUNN, &tunn_mode)) + __set_bit(QED_MODE_L2GENEVE_TUNN, &new_tunn_mode); + } else { + if (test_bit(QED_MODE_L2GENEVE_TUNN, &cached_tunn_mode)) + __set_bit(QED_MODE_L2GENEVE_TUNN, &new_tunn_mode); + } + + if (test_bit(QED_MODE_IPGENEVE_TUNN, &update_mask)) { + if (test_bit(QED_MODE_IPGENEVE_TUNN, &tunn_mode)) + __set_bit(QED_MODE_IPGENEVE_TUNN, &new_tunn_mode); + } else { + if (test_bit(QED_MODE_IPGENEVE_TUNN, &cached_tunn_mode)) + __set_bit(QED_MODE_IPGENEVE_TUNN, &new_tunn_mode); + } + + p_src->tunn_mode = new_tunn_mode; +} + +static void +qed_tunn_set_pf_update_params(struct qed_hwfn *p_hwfn, + struct qed_tunn_update_params *p_src, + struct pf_update_tunnel_config *p_tunn_cfg) +{ + unsigned long tunn_mode = p_src->tunn_mode; + enum tunnel_clss type; + + qed_tunn_set_pf_fix_tunn_mode(p_hwfn, p_src, p_tunn_cfg); + p_tunn_cfg->update_rx_pf_clss = p_src->update_rx_pf_clss; + p_tunn_cfg->update_tx_pf_clss = p_src->update_tx_pf_clss; + + type = qed_tunn_get_clss_type(p_src->tunn_clss_vxlan); + p_tunn_cfg->tunnel_clss_vxlan = type; + + type = qed_tunn_get_clss_type(p_src->tunn_clss_l2gre); + p_tunn_cfg->tunnel_clss_l2gre = type; + + type = qed_tunn_get_clss_type(p_src->tunn_clss_ipgre); + p_tunn_cfg->tunnel_clss_ipgre = type; + + if (p_src->update_vxlan_udp_port) { + p_tunn_cfg->set_vxlan_udp_port_flg = 1; + p_tunn_cfg->vxlan_udp_port = cpu_to_le16(p_src->vxlan_udp_port); + } + + if (test_bit(QED_MODE_L2GRE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_l2gre = 1; + + if (test_bit(QED_MODE_IPGRE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_ipgre = 1; + + if (test_bit(QED_MODE_VXLAN_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_vxlan = 1; + + if (p_src->update_geneve_udp_port) { + p_tunn_cfg->set_geneve_udp_port_flg = 1; + p_tunn_cfg->geneve_udp_port = + cpu_to_le16(p_src->geneve_udp_port); + } + + if (test_bit(QED_MODE_L2GENEVE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_l2geneve = 1; + + if (test_bit(QED_MODE_IPGENEVE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_ipgeneve = 1; + + type = qed_tunn_get_clss_type(p_src->tunn_clss_l2geneve); + p_tunn_cfg->tunnel_clss_l2geneve = type; + + type = qed_tunn_get_clss_type(p_src->tunn_clss_ipgeneve); + p_tunn_cfg->tunnel_clss_ipgeneve = type; +} + +static void qed_set_hw_tunn_mode(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + unsigned long tunn_mode) +{ + u8 l2gre_enable = 0, ipgre_enable = 0, vxlan_enable = 0; + u8 l2geneve_enable = 0, ipgeneve_enable = 0; + + if (test_bit(QED_MODE_L2GRE_TUNN, &tunn_mode)) + l2gre_enable = 1; + + if (test_bit(QED_MODE_IPGRE_TUNN, &tunn_mode)) + ipgre_enable = 1; + + if (test_bit(QED_MODE_VXLAN_TUNN, &tunn_mode)) + vxlan_enable = 1; + + qed_set_gre_enable(p_hwfn, p_ptt, l2gre_enable, ipgre_enable); + qed_set_vxlan_enable(p_hwfn, p_ptt, vxlan_enable); + + if (test_bit(QED_MODE_L2GENEVE_TUNN, &tunn_mode)) + l2geneve_enable = 1; + + if (test_bit(QED_MODE_IPGENEVE_TUNN, &tunn_mode)) + ipgeneve_enable = 1; + + qed_set_geneve_enable(p_hwfn, p_ptt, l2geneve_enable, + ipgeneve_enable); +} + +static void +qed_tunn_set_pf_start_params(struct qed_hwfn *p_hwfn, + struct qed_tunn_start_params *p_src, + struct pf_start_tunnel_config *p_tunn_cfg) +{ + unsigned long tunn_mode; + enum tunnel_clss type; + + if (!p_src) + return; + + tunn_mode = p_src->tunn_mode; + type = qed_tunn_get_clss_type(p_src->tunn_clss_vxlan); + p_tunn_cfg->tunnel_clss_vxlan = type; + type = qed_tunn_get_clss_type(p_src->tunn_clss_l2gre); + p_tunn_cfg->tunnel_clss_l2gre = type; + type = qed_tunn_get_clss_type(p_src->tunn_clss_ipgre); + p_tunn_cfg->tunnel_clss_ipgre = type; + + if (p_src->update_vxlan_udp_port) { + p_tunn_cfg->set_vxlan_udp_port_flg = 1; + p_tunn_cfg->vxlan_udp_port = cpu_to_le16(p_src->vxlan_udp_port); + } + + if (test_bit(QED_MODE_L2GRE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_l2gre = 1; + + if (test_bit(QED_MODE_IPGRE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_ipgre = 1; + + if (test_bit(QED_MODE_VXLAN_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_vxlan = 1; + + if (p_src->update_geneve_udp_port) { + p_tunn_cfg->set_geneve_udp_port_flg = 1; + p_tunn_cfg->geneve_udp_port = + cpu_to_le16(p_src->geneve_udp_port); + } + + if (test_bit(QED_MODE_L2GENEVE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_l2geneve = 1; + + if (test_bit(QED_MODE_IPGENEVE_TUNN, &tunn_mode)) + p_tunn_cfg->tx_enable_ipgeneve = 1; + + type = qed_tunn_get_clss_type(p_src->tunn_clss_l2geneve); + p_tunn_cfg->tunnel_clss_l2geneve = type; + type = qed_tunn_get_clss_type(p_src->tunn_clss_ipgeneve); + p_tunn_cfg->tunnel_clss_ipgeneve = type; +} + int qed_sp_pf_start(struct qed_hwfn *p_hwfn, + struct qed_tunn_start_params *p_tunn, enum qed_mf_mode mode) { struct pf_start_ramrod_data *p_ramrod = NULL; @@ -143,6 +353,7 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, DMA_REGPAIR_LE(p_ramrod->consolid_q_pbl_addr, p_hwfn->p_consq->chain.pbl.p_phys_table); + qed_tunn_set_pf_start_params(p_hwfn, NULL, NULL); p_hwfn->hw_info.personality = PERSONALITY_ETH; DP_VERBOSE(p_hwfn, QED_MSG_SPQ, @@ -153,6 +364,49 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, return qed_spq_post(p_hwfn, p_ent, NULL); } +/* Set pf update ramrod command params */ +int qed_sp_pf_update_tunn_cfg(struct qed_hwfn *p_hwfn, + struct qed_tunn_update_params *p_tunn, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + struct qed_spq_entry *p_ent = NULL; + struct qed_sp_init_data init_data; + int rc = -EINVAL; + + /* Get SPQ entry */ + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = qed_spq_get_cid(p_hwfn); + init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; + init_data.comp_mode = comp_mode; + init_data.p_comp_data = p_comp_data; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + COMMON_RAMROD_PF_UPDATE, PROTOCOLID_COMMON, + &init_data); + if (rc) + return rc; + + qed_tunn_set_pf_update_params(p_hwfn, p_tunn, + &p_ent->ramrod.pf_update.tunnel_config); + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + if (rc) + return rc; + + if (p_tunn->update_vxlan_udp_port) + qed_set_vxlan_dest_port(p_hwfn, p_hwfn->p_main_ptt, + p_tunn->vxlan_udp_port); + if (p_tunn->update_geneve_udp_port) + qed_set_geneve_dest_port(p_hwfn, p_hwfn->p_main_ptt, + p_tunn->geneve_udp_port); + + qed_set_hw_tunn_mode(p_hwfn, p_hwfn->p_main_ptt, p_tunn->tunn_mode); + p_hwfn->cdev->tunn_mode = p_tunn->tunn_mode; + + return rc; +} + int qed_sp_pf_stop(struct qed_hwfn *p_hwfn) { struct qed_spq_entry *p_ent = NULL; diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index 795c9902e02f..3a4c806be156 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -112,6 +112,13 @@ struct qed_queue_start_common_params { u16 sb_idx; }; +struct qed_tunn_params { + u16 vxlan_port; + u8 update_vxlan_port; + u16 geneve_port; + u8 update_geneve_port; +}; + struct qed_eth_cb_ops { struct qed_common_cb_ops common; }; @@ -166,6 +173,9 @@ struct qed_eth_ops { void (*get_vport_stats)(struct qed_dev *cdev, struct qed_eth_stats *stats); + + int (*tunn_config)(struct qed_dev *cdev, + struct qed_tunn_params *params); }; const struct qed_eth_ops *qed_get_eth_ops(void); -- GitLab From b18e170cac62cb7c46d6778c50d7335e01ce566f Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 14 Apr 2016 01:38:30 -0400 Subject: [PATCH 3062/9938] qed/qede: Add VXLAN tunnel slowpath configuration support This patch enables VXLAN tunnel on the adapter and add support for driver hooks to configure UDP ports for VXLAN tunnel offload to be performed by the adapter. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/Kconfig | 11 ++++ drivers/net/ethernet/qlogic/qed/qed_main.c | 8 ++- .../net/ethernet/qlogic/qed/qed_sp_commands.c | 3 +- drivers/net/ethernet/qlogic/qede/qede.h | 4 +- drivers/net/ethernet/qlogic/qede/qede_main.c | 64 ++++++++++++++++++- 5 files changed, 86 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig index ddcfcab034c2..7a65522005ee 100644 --- a/drivers/net/ethernet/qlogic/Kconfig +++ b/drivers/net/ethernet/qlogic/Kconfig @@ -103,4 +103,15 @@ config QEDE depends on QED ---help--- This enables the support for ... + +config QEDE_VXLAN + bool "Virtual eXtensible Local Area Network support" + default n + depends on QEDE && VXLAN && !(QEDE=y && VXLAN=m) + ---help--- + This enables hardware offload support for VXLAN protocol over + qede module. Say Y here if you want to enable hardware offload + support for Virtual eXtensible Local Area Network (VXLAN) + in the driver. + endif # NET_VENDOR_QLOGIC diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 1916992ae8b1..0bb2c574df79 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -744,6 +744,7 @@ static void qed_update_pf_params(struct qed_dev *cdev, static int qed_slowpath_start(struct qed_dev *cdev, struct qed_slowpath_params *params) { + struct qed_tunn_start_params tunn_info; struct qed_mcp_drv_version drv_version; const u8 *data = NULL; struct qed_hwfn *hwfn; @@ -776,7 +777,12 @@ static int qed_slowpath_start(struct qed_dev *cdev, /* Start the slowpath */ data = cdev->firmware->data; - rc = qed_hw_init(cdev, NULL, true, cdev->int_params.out.int_mode, + memset(&tunn_info, 0, sizeof(tunn_info)); + tunn_info.tunn_mode |= 1 << QED_MODE_VXLAN_TUNN; + tunn_info.tunn_clss_vxlan = QED_TUNN_CLSS_MAC_VLAN; + + rc = qed_hw_init(cdev, &tunn_info, true, + cdev->int_params.out.int_mode, true, data); if (rc) goto err2; diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c index 306da7000ddc..7ccd96e5802b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c @@ -353,7 +353,8 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, DMA_REGPAIR_LE(p_ramrod->consolid_q_pbl_addr, p_hwfn->p_consq->chain.pbl.p_phys_table); - qed_tunn_set_pf_start_params(p_hwfn, NULL, NULL); + qed_tunn_set_pf_start_params(p_hwfn, p_tunn, + &p_ramrod->tunnel_config); p_hwfn->hw_info.personality = PERSONALITY_ETH; DP_VERBOSE(p_hwfn, QED_MSG_SPQ, diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 41c418909a5c..16a43444af21 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -169,6 +169,7 @@ struct qede_dev { bool accept_any_vlan; struct delayed_work sp_task; unsigned long sp_flags; + u16 vxlan_dst_port; }; enum QEDE_STATE { @@ -289,7 +290,8 @@ struct qede_fastpath { #define QEDE_CSUM_ERROR BIT(0) #define QEDE_CSUM_UNNECESSARY BIT(1) -#define QEDE_SP_RX_MODE 1 +#define QEDE_SP_RX_MODE 1 +#define QEDE_SP_VXLAN_PORT_CONFIG 2 union qede_reload_args { u16 mtu; diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 457caad2e752..895016d9f7e3 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -24,7 +24,9 @@ #include #include #include +#ifdef CONFIG_QEDE_VXLAN #include +#endif #include #include #include @@ -1821,6 +1823,42 @@ static void qede_vlan_mark_nonconfigured(struct qede_dev *edev) edev->accept_any_vlan = false; } +#ifdef CONFIG_QEDE_VXLAN +static void qede_add_vxlan_port(struct net_device *dev, + sa_family_t sa_family, __be16 port) +{ + struct qede_dev *edev = netdev_priv(dev); + u16 t_port = ntohs(port); + + if (edev->vxlan_dst_port) + return; + + edev->vxlan_dst_port = t_port; + + DP_VERBOSE(edev, QED_MSG_DEBUG, "Added vxlan port=%d", t_port); + + set_bit(QEDE_SP_VXLAN_PORT_CONFIG, &edev->sp_flags); + schedule_delayed_work(&edev->sp_task, 0); +} + +static void qede_del_vxlan_port(struct net_device *dev, + sa_family_t sa_family, __be16 port) +{ + struct qede_dev *edev = netdev_priv(dev); + u16 t_port = ntohs(port); + + if (t_port != edev->vxlan_dst_port) + return; + + edev->vxlan_dst_port = 0; + + DP_VERBOSE(edev, QED_MSG_DEBUG, "Deleted vxlan port=%d", t_port); + + set_bit(QEDE_SP_VXLAN_PORT_CONFIG, &edev->sp_flags); + schedule_delayed_work(&edev->sp_task, 0); +} +#endif + static const struct net_device_ops qede_netdev_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, @@ -1832,6 +1870,10 @@ static const struct net_device_ops qede_netdev_ops = { .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid, .ndo_get_stats64 = qede_get_stats64, +#ifdef CONFIG_QEDE_VXLAN + .ndo_add_vxlan_port = qede_add_vxlan_port, + .ndo_del_vxlan_port = qede_del_vxlan_port, +#endif }; /* ------------------------------------------------------------------------- @@ -2004,6 +2046,8 @@ static void qede_sp_task(struct work_struct *work) { struct qede_dev *edev = container_of(work, struct qede_dev, sp_task.work); + struct qed_dev *cdev = edev->cdev; + mutex_lock(&edev->qede_lock); if (edev->state == QEDE_STATE_OPEN) { @@ -2011,6 +2055,15 @@ static void qede_sp_task(struct work_struct *work) qede_config_rx_mode(edev->ndev); } + if (test_and_clear_bit(QEDE_SP_VXLAN_PORT_CONFIG, &edev->sp_flags)) { + struct qed_tunn_params tunn_params; + + memset(&tunn_params, 0, sizeof(tunn_params)); + tunn_params.update_vxlan_port = 1; + tunn_params.vxlan_port = edev->vxlan_dst_port; + qed_ops->tunn_config(cdev, &tunn_params); + } + mutex_unlock(&edev->qede_lock); } @@ -3149,12 +3202,21 @@ void qede_reload(struct qede_dev *edev, static int qede_open(struct net_device *ndev) { struct qede_dev *edev = netdev_priv(ndev); + int rc; netif_carrier_off(ndev); edev->ops->common->set_power_state(edev->cdev, PCI_D0); - return qede_load(edev, QEDE_LOAD_NORMAL); + rc = qede_load(edev, QEDE_LOAD_NORMAL); + + if (rc) + return rc; + +#ifdef CONFIG_QEDE_VXLAN + vxlan_get_rx_port(ndev); +#endif + return 0; } static int qede_close(struct net_device *ndev) -- GitLab From 9a109dd073582f69eba591888e64aa617340da6f Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 14 Apr 2016 01:38:31 -0400 Subject: [PATCH 3063/9938] qed/qede: Add GENEVE tunnel slowpath configuration support This patch enables GENEVE tunnel on the adapter and add support for driver hooks to configure UDP ports for GENEVE tunnel offload to be performed by the adapter. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/Kconfig | 10 ++++ drivers/net/ethernet/qlogic/qed/qed_main.c | 5 +- drivers/net/ethernet/qlogic/qede/qede.h | 2 + drivers/net/ethernet/qlogic/qede/qede_main.c | 53 ++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig index 7a65522005ee..c0a11b5158e7 100644 --- a/drivers/net/ethernet/qlogic/Kconfig +++ b/drivers/net/ethernet/qlogic/Kconfig @@ -114,4 +114,14 @@ config QEDE_VXLAN support for Virtual eXtensible Local Area Network (VXLAN) in the driver. +config QEDE_GENEVE + bool "Generic Network Virtualization Encapsulation (GENEVE) support" + depends on QEDE && GENEVE && !(QEDE=y && GENEVE=m) + ---help--- + This allows one to create GENEVE virtual interfaces that provide + Layer 2 Networks over Layer 3 Networks. GENEVE is often used + to tunnel virtual network infrastructure in virtualized environments. + Say Y here if you want to enable hardware offload support for + Generic Network Virtualization Encapsulation (GENEVE) in the driver. + endif # NET_VENDOR_QLOGIC diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 0bb2c574df79..c1533a64f41c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -778,7 +778,10 @@ static int qed_slowpath_start(struct qed_dev *cdev, data = cdev->firmware->data; memset(&tunn_info, 0, sizeof(tunn_info)); - tunn_info.tunn_mode |= 1 << QED_MODE_VXLAN_TUNN; + tunn_info.tunn_mode |= 1 << QED_MODE_VXLAN_TUNN | + 1 << QED_MODE_L2GENEVE_TUNN | + 1 << QED_MODE_IPGENEVE_TUNN; + tunn_info.tunn_clss_vxlan = QED_TUNN_CLSS_MAC_VLAN; rc = qed_hw_init(cdev, &tunn_info, true, diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 16a43444af21..8521feeda4de 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -170,6 +170,7 @@ struct qede_dev { struct delayed_work sp_task; unsigned long sp_flags; u16 vxlan_dst_port; + u16 geneve_dst_port; }; enum QEDE_STATE { @@ -292,6 +293,7 @@ struct qede_fastpath { #define QEDE_SP_RX_MODE 1 #define QEDE_SP_VXLAN_PORT_CONFIG 2 +#define QEDE_SP_GENEVE_PORT_CONFIG 3 union qede_reload_args { u16 mtu; diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 895016d9f7e3..6c40316f1e70 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -27,6 +27,9 @@ #ifdef CONFIG_QEDE_VXLAN #include #endif +#ifdef CONFIG_QEDE_GENEVE +#include +#endif #include #include #include @@ -1859,6 +1862,40 @@ static void qede_del_vxlan_port(struct net_device *dev, } #endif +#ifdef CONFIG_QEDE_GENEVE +static void qede_add_geneve_port(struct net_device *dev, + sa_family_t sa_family, __be16 port) +{ + struct qede_dev *edev = netdev_priv(dev); + u16 t_port = ntohs(port); + + if (edev->geneve_dst_port) + return; + + edev->geneve_dst_port = t_port; + + DP_VERBOSE(edev, QED_MSG_DEBUG, "Added geneve port=%d", t_port); + set_bit(QEDE_SP_GENEVE_PORT_CONFIG, &edev->sp_flags); + schedule_delayed_work(&edev->sp_task, 0); +} + +static void qede_del_geneve_port(struct net_device *dev, + sa_family_t sa_family, __be16 port) +{ + struct qede_dev *edev = netdev_priv(dev); + u16 t_port = ntohs(port); + + if (t_port != edev->geneve_dst_port) + return; + + edev->geneve_dst_port = 0; + + DP_VERBOSE(edev, QED_MSG_DEBUG, "Deleted geneve port=%d", t_port); + set_bit(QEDE_SP_GENEVE_PORT_CONFIG, &edev->sp_flags); + schedule_delayed_work(&edev->sp_task, 0); +} +#endif + static const struct net_device_ops qede_netdev_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, @@ -1874,6 +1911,10 @@ static const struct net_device_ops qede_netdev_ops = { .ndo_add_vxlan_port = qede_add_vxlan_port, .ndo_del_vxlan_port = qede_del_vxlan_port, #endif +#ifdef CONFIG_QEDE_GENEVE + .ndo_add_geneve_port = qede_add_geneve_port, + .ndo_del_geneve_port = qede_del_geneve_port, +#endif }; /* ------------------------------------------------------------------------- @@ -2064,6 +2105,15 @@ static void qede_sp_task(struct work_struct *work) qed_ops->tunn_config(cdev, &tunn_params); } + if (test_and_clear_bit(QEDE_SP_GENEVE_PORT_CONFIG, &edev->sp_flags)) { + struct qed_tunn_params tunn_params; + + memset(&tunn_params, 0, sizeof(tunn_params)); + tunn_params.update_geneve_port = 1; + tunn_params.geneve_port = edev->geneve_dst_port; + qed_ops->tunn_config(cdev, &tunn_params); + } + mutex_unlock(&edev->qede_lock); } @@ -3215,6 +3265,9 @@ static int qede_open(struct net_device *ndev) #ifdef CONFIG_QEDE_VXLAN vxlan_get_rx_port(ndev); +#endif +#ifdef CONFIG_QEDE_GENEVE + geneve_get_rx_port(ndev); #endif return 0; } -- GitLab From f7985869209b6d0c71c2cb1fd6fba0522d2c2b61 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 14 Apr 2016 01:38:32 -0400 Subject: [PATCH 3064/9938] qed: Enable GRE tunnel slowpath configuration Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index c1533a64f41c..1e9f321f1ac4 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -779,10 +779,14 @@ static int qed_slowpath_start(struct qed_dev *cdev, memset(&tunn_info, 0, sizeof(tunn_info)); tunn_info.tunn_mode |= 1 << QED_MODE_VXLAN_TUNN | + 1 << QED_MODE_L2GRE_TUNN | + 1 << QED_MODE_IPGRE_TUNN | 1 << QED_MODE_L2GENEVE_TUNN | 1 << QED_MODE_IPGENEVE_TUNN; tunn_info.tunn_clss_vxlan = QED_TUNN_CLSS_MAC_VLAN; + tunn_info.tunn_clss_l2gre = QED_TUNN_CLSS_MAC_VLAN; + tunn_info.tunn_clss_ipgre = QED_TUNN_CLSS_MAC_VLAN; rc = qed_hw_init(cdev, &tunn_info, true, cdev->int_params.out.int_mode, -- GitLab From 14db81defa1fb6dd2ff154fb9facb4243ad63b95 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 14 Apr 2016 01:38:33 -0400 Subject: [PATCH 3065/9938] qede: Add fastpath support for tunneling This patch enables netdev tunneling features and adds TX/RX fastpath support for tunneling in driver. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede.h | 1 + drivers/net/ethernet/qlogic/qede/qede_main.c | 101 +++++++++++++++++-- 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 8521feeda4de..16df1591388f 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -290,6 +290,7 @@ struct qede_fastpath { #define QEDE_CSUM_ERROR BIT(0) #define QEDE_CSUM_UNNECESSARY BIT(1) +#define QEDE_TUNN_CSUM_UNNECESSARY BIT(2) #define QEDE_SP_RX_MODE 1 #define QEDE_SP_VXLAN_PORT_CONFIG 2 diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 6c40316f1e70..e5dc35ae6313 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -315,6 +315,9 @@ static u32 qede_xmit_type(struct qede_dev *edev, (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6)) *ipv6_ext = 1; + if (skb->encapsulation) + rc |= XMIT_ENC; + if (skb_is_gso(skb)) rc |= XMIT_LSO; @@ -376,6 +379,16 @@ static int map_frag_to_bd(struct qede_dev *edev, return 0; } +static u16 qede_get_skb_hlen(struct sk_buff *skb, bool is_encap_pkt) +{ + if (is_encap_pkt) + return (skb_inner_transport_header(skb) + + inner_tcp_hdrlen(skb) - skb->data); + else + return (skb_transport_header(skb) + + tcp_hdrlen(skb) - skb->data); +} + /* +2 for 1st BD for headers and 2nd BD for headlen (if required) */ #if ((MAX_SKB_FRAGS + 2) > ETH_TX_MAX_BDS_PER_NON_LSO_PACKET) static bool qede_pkt_req_lin(struct qede_dev *edev, struct sk_buff *skb, @@ -386,8 +399,7 @@ static bool qede_pkt_req_lin(struct qede_dev *edev, struct sk_buff *skb, if (xmit_type & XMIT_LSO) { int hlen; - hlen = skb_transport_header(skb) + - tcp_hdrlen(skb) - skb->data; + hlen = qede_get_skb_hlen(skb, xmit_type & XMIT_ENC); /* linear payload would require its own BD */ if (skb_headlen(skb) > hlen) @@ -495,7 +507,18 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, first_bd->data.bd_flags.bitfields |= 1 << ETH_TX_1ST_BD_FLAGS_L4_CSUM_SHIFT; - first_bd->data.bitfields |= cpu_to_le16(temp); + if (xmit_type & XMIT_ENC) { + first_bd->data.bd_flags.bitfields |= + 1 << ETH_TX_1ST_BD_FLAGS_IP_CSUM_SHIFT; + } else { + /* In cases when OS doesn't indicate for inner offloads + * when packet is tunnelled, we need to override the HW + * tunnel configuration so that packets are treated as + * regular non tunnelled packets and no inner offloads + * are done by the hardware. + */ + first_bd->data.bitfields |= cpu_to_le16(temp); + } /* If the packet is IPv6 with extension header, indicate that * to FW and pass few params, since the device cracker doesn't @@ -511,10 +534,15 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, third_bd->data.lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - first_bd->data.bd_flags.bitfields |= - 1 << ETH_TX_1ST_BD_FLAGS_IP_CSUM_SHIFT; - hlen = skb_transport_header(skb) + - tcp_hdrlen(skb) - skb->data; + if (unlikely(xmit_type & XMIT_ENC)) { + first_bd->data.bd_flags.bitfields |= + 1 << ETH_TX_1ST_BD_FLAGS_TUNN_IP_CSUM_SHIFT; + hlen = qede_get_skb_hlen(skb, true); + } else { + first_bd->data.bd_flags.bitfields |= + 1 << ETH_TX_1ST_BD_FLAGS_IP_CSUM_SHIFT; + hlen = qede_get_skb_hlen(skb, false); + } /* @@@TBD - if will not be removed need to check */ third_bd->data.bitfields |= @@ -848,6 +876,9 @@ static void qede_set_skb_csum(struct sk_buff *skb, u8 csum_flag) if (csum_flag & QEDE_CSUM_UNNECESSARY) skb->ip_summed = CHECKSUM_UNNECESSARY; + + if (csum_flag & QEDE_TUNN_CSUM_UNNECESSARY) + skb->csum_level = 1; } static inline void qede_skb_receive(struct qede_dev *edev, @@ -1137,13 +1168,47 @@ static void qede_tpa_end(struct qede_dev *edev, tpa_info->skb = NULL; } -static u8 qede_check_csum(u16 flag) +static bool qede_tunn_exist(u16 flag) +{ + return !!(flag & (PARSING_AND_ERR_FLAGS_TUNNELEXIST_MASK << + PARSING_AND_ERR_FLAGS_TUNNELEXIST_SHIFT)); +} + +static u8 qede_check_tunn_csum(u16 flag) +{ + u16 csum_flag = 0; + u8 tcsum = 0; + + if (flag & (PARSING_AND_ERR_FLAGS_TUNNELL4CHKSMWASCALCULATED_MASK << + PARSING_AND_ERR_FLAGS_TUNNELL4CHKSMWASCALCULATED_SHIFT)) + csum_flag |= PARSING_AND_ERR_FLAGS_TUNNELL4CHKSMERROR_MASK << + PARSING_AND_ERR_FLAGS_TUNNELL4CHKSMERROR_SHIFT; + + if (flag & (PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_MASK << + PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_SHIFT)) { + csum_flag |= PARSING_AND_ERR_FLAGS_L4CHKSMERROR_MASK << + PARSING_AND_ERR_FLAGS_L4CHKSMERROR_SHIFT; + tcsum = QEDE_TUNN_CSUM_UNNECESSARY; + } + + csum_flag |= PARSING_AND_ERR_FLAGS_TUNNELIPHDRERROR_MASK << + PARSING_AND_ERR_FLAGS_TUNNELIPHDRERROR_SHIFT | + PARSING_AND_ERR_FLAGS_IPHDRERROR_MASK << + PARSING_AND_ERR_FLAGS_IPHDRERROR_SHIFT; + + if (csum_flag & flag) + return QEDE_CSUM_ERROR; + + return QEDE_CSUM_UNNECESSARY | tcsum; +} + +static u8 qede_check_notunn_csum(u16 flag) { u16 csum_flag = 0; u8 csum = 0; - if ((PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_MASK << - PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_SHIFT) & flag) { + if (flag & (PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_MASK << + PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_SHIFT)) { csum_flag |= PARSING_AND_ERR_FLAGS_L4CHKSMERROR_MASK << PARSING_AND_ERR_FLAGS_L4CHKSMERROR_SHIFT; csum = QEDE_CSUM_UNNECESSARY; @@ -1158,6 +1223,14 @@ static u8 qede_check_csum(u16 flag) return csum; } +static u8 qede_check_csum(u16 flag) +{ + if (!qede_tunn_exist(flag)) + return qede_check_notunn_csum(flag); + else + return qede_check_tunn_csum(flag); +} + static int qede_rx_int(struct qede_fastpath *fp, int budget) { struct qede_dev *edev = fp->edev; @@ -1987,6 +2060,14 @@ static void qede_init_ndev(struct qede_dev *edev) NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6; + /* Encap features*/ + hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_TSO_ECN; + ndev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO_ECN | + NETIF_F_TSO6 | NETIF_F_GSO_GRE | + NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM; + ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM | NETIF_F_HIGHDMA; ndev->features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM | -- GitLab From 6e38e6b26e590b21247c1dd5238be35e7b056ef9 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 5 Feb 2016 20:42:25 +0100 Subject: [PATCH 3066/9938] ARM: dts: rockchip: make rk3288-grf a simple-mfd Similar to the pmu, the general register files contain a lot of different setting bits grouped into general registers, but also some somewhat special entities like the controls for some phy-blocks or the io-voltage control. To be able to move these blocks under the grf node where they actually belong, make it a simple-mfd. Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 3071e94e86ed..180eb975ead5 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -754,7 +754,7 @@ }; grf: syscon@ff770000 { - compatible = "rockchip,rk3288-grf", "syscon"; + compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd"; reg = <0xff770000 0x1000>; }; -- GitLab From e1c9c62b9a3a761b56359a7437215ae2e9253821 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Mon, 11 Apr 2016 23:10:21 +0300 Subject: [PATCH 3067/9938] net/mlx5: Fix mlx5 ifc cmd_hca_cap bad offsets All reserved fields after early_vf_enable are off by 1, since early_vf_enable was not explicitly declared as array of size 1. Reserved field before cqe_zip had a wrong size, it should be 0x80 + 0x3f. Fixes: b0844444590e ("net/mlx5_core: Introduce access function to read internal timer ") Fixes: b4ff3a36d3e4 ("net/mlx5: Use offset based reserved field names in the IFC header file") Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: Matan Barak Signed-off-by: David S. Miller --- include/linux/mlx5/mlx5_ifc.h | 107 +++++++++++++++++----------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index c15b8a864937..c300e7491d80 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -750,21 +750,21 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 ets[0x1]; u8 nic_flow_table[0x1]; u8 eswitch_flow_table[0x1]; - u8 early_vf_enable; - u8 reserved_at_1a8[0x2]; + u8 early_vf_enable[0x1]; + u8 reserved_at_1a9[0x2]; u8 local_ca_ack_delay[0x5]; u8 reserved_at_1af[0x6]; u8 port_type[0x2]; u8 num_ports[0x8]; - u8 reserved_at_1bf[0x3]; + u8 reserved_at_1c0[0x3]; u8 log_max_msg[0x5]; - u8 reserved_at_1c7[0x4]; + u8 reserved_at_1c8[0x4]; u8 max_tc[0x4]; - u8 reserved_at_1cf[0x6]; + u8 reserved_at_1d0[0x6]; u8 rol_s[0x1]; u8 rol_g[0x1]; - u8 reserved_at_1d7[0x1]; + u8 reserved_at_1d8[0x1]; u8 wol_s[0x1]; u8 wol_g[0x1]; u8 wol_a[0x1]; @@ -774,47 +774,47 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 wol_p[0x1]; u8 stat_rate_support[0x10]; - u8 reserved_at_1ef[0xc]; + u8 reserved_at_1f0[0xc]; u8 cqe_version[0x4]; u8 compact_address_vector[0x1]; u8 reserved_at_200[0x3]; u8 ipoib_basic_offloads[0x1]; - u8 reserved_at_204[0xa]; + u8 reserved_at_205[0xa]; u8 drain_sigerr[0x1]; u8 cmdif_checksum[0x2]; u8 sigerr_cqe[0x1]; - u8 reserved_at_212[0x1]; + u8 reserved_at_213[0x1]; u8 wq_signature[0x1]; u8 sctr_data_cqe[0x1]; - u8 reserved_at_215[0x1]; + u8 reserved_at_216[0x1]; u8 sho[0x1]; u8 tph[0x1]; u8 rf[0x1]; u8 dct[0x1]; - u8 reserved_at_21a[0x1]; + u8 reserved_at_21b[0x1]; u8 eth_net_offloads[0x1]; u8 roce[0x1]; u8 atomic[0x1]; - u8 reserved_at_21e[0x1]; + u8 reserved_at_21f[0x1]; u8 cq_oi[0x1]; u8 cq_resize[0x1]; u8 cq_moderation[0x1]; - u8 reserved_at_222[0x3]; + u8 reserved_at_223[0x3]; u8 cq_eq_remap[0x1]; u8 pg[0x1]; u8 block_lb_mc[0x1]; - u8 reserved_at_228[0x1]; + u8 reserved_at_229[0x1]; u8 scqe_break_moderation[0x1]; u8 reserved_at_22a[0x1]; u8 cd[0x1]; - u8 reserved_at_22c[0x1]; + u8 reserved_at_22d[0x1]; u8 apm[0x1]; u8 vector_calc[0x1]; u8 reserved_at_22f[0x1]; u8 imaicl[0x1]; - u8 reserved_at_231[0x4]; + u8 reserved_at_232[0x4]; u8 qkv[0x1]; u8 pkv[0x1]; u8 set_deth_sqpn[0x1]; @@ -824,98 +824,101 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 uc[0x1]; u8 rc[0x1]; - u8 reserved_at_23f[0xa]; + u8 reserved_at_240[0xa]; u8 uar_sz[0x6]; - u8 reserved_at_24f[0x8]; + u8 reserved_at_250[0x8]; u8 log_pg_sz[0x8]; u8 bf[0x1]; - u8 reserved_at_260[0x1]; + u8 reserved_at_261[0x1]; u8 pad_tx_eth_packet[0x1]; - u8 reserved_at_262[0x8]; + u8 reserved_at_263[0x8]; u8 log_bf_reg_size[0x5]; - u8 reserved_at_26f[0x10]; + u8 reserved_at_270[0x10]; - u8 reserved_at_27f[0x10]; + u8 reserved_at_280[0x10]; u8 max_wqe_sz_sq[0x10]; - u8 reserved_at_29f[0x10]; + u8 reserved_at_2a0[0x10]; u8 max_wqe_sz_rq[0x10]; - u8 reserved_at_2bf[0x10]; + u8 reserved_at_2c0[0x10]; u8 max_wqe_sz_sq_dc[0x10]; - u8 reserved_at_2df[0x7]; + u8 reserved_at_2e0[0x7]; u8 max_qp_mcg[0x19]; - u8 reserved_at_2ff[0x18]; + u8 reserved_at_300[0x18]; u8 log_max_mcg[0x8]; - u8 reserved_at_31f[0x3]; + u8 reserved_at_320[0x3]; u8 log_max_transport_domain[0x5]; - u8 reserved_at_327[0x3]; + u8 reserved_at_328[0x3]; u8 log_max_pd[0x5]; - u8 reserved_at_32f[0xb]; + u8 reserved_at_330[0xb]; u8 log_max_xrcd[0x5]; - u8 reserved_at_33f[0x20]; + u8 reserved_at_340[0x20]; - u8 reserved_at_35f[0x3]; + u8 reserved_at_360[0x3]; u8 log_max_rq[0x5]; - u8 reserved_at_367[0x3]; + u8 reserved_at_368[0x3]; u8 log_max_sq[0x5]; - u8 reserved_at_36f[0x3]; + u8 reserved_at_370[0x3]; u8 log_max_tir[0x5]; - u8 reserved_at_377[0x3]; + u8 reserved_at_378[0x3]; u8 log_max_tis[0x5]; u8 basic_cyclic_rcv_wqe[0x1]; - u8 reserved_at_380[0x2]; + u8 reserved_at_381[0x2]; u8 log_max_rmp[0x5]; - u8 reserved_at_387[0x3]; + u8 reserved_at_388[0x3]; u8 log_max_rqt[0x5]; - u8 reserved_at_38f[0x3]; + u8 reserved_at_390[0x3]; u8 log_max_rqt_size[0x5]; - u8 reserved_at_397[0x3]; + u8 reserved_at_398[0x3]; u8 log_max_tis_per_sq[0x5]; - u8 reserved_at_39f[0x3]; + u8 reserved_at_3a0[0x3]; u8 log_max_stride_sz_rq[0x5]; - u8 reserved_at_3a7[0x3]; + u8 reserved_at_3a8[0x3]; u8 log_min_stride_sz_rq[0x5]; - u8 reserved_at_3af[0x3]; + u8 reserved_at_3b0[0x3]; u8 log_max_stride_sz_sq[0x5]; - u8 reserved_at_3b7[0x3]; + u8 reserved_at_3b8[0x3]; u8 log_min_stride_sz_sq[0x5]; - u8 reserved_at_3bf[0x1b]; + u8 reserved_at_3c0[0x1b]; u8 log_max_wq_sz[0x5]; u8 nic_vport_change_event[0x1]; - u8 reserved_at_3e0[0xa]; + u8 reserved_at_3e1[0xa]; u8 log_max_vlan_list[0x5]; - u8 reserved_at_3ef[0x3]; + u8 reserved_at_3f0[0x3]; u8 log_max_current_mc_list[0x5]; - u8 reserved_at_3f7[0x3]; + u8 reserved_at_3f8[0x3]; u8 log_max_current_uc_list[0x5]; - u8 reserved_at_3ff[0x80]; + u8 reserved_at_400[0x80]; - u8 reserved_at_47f[0x3]; + u8 reserved_at_480[0x3]; u8 log_max_l2_table[0x5]; - u8 reserved_at_487[0x8]; + u8 reserved_at_488[0x8]; u8 log_uar_page_sz[0x10]; - u8 reserved_at_49f[0x20]; + u8 reserved_at_4a0[0x20]; u8 device_frequency_mhz[0x20]; u8 device_frequency_khz[0x20]; - u8 reserved_at_4ff[0x5f]; + + u8 reserved_at_500[0x80]; + + u8 reserved_at_580[0x3f]; u8 cqe_zip[0x1]; u8 cqe_zip_timeout[0x10]; u8 cqe_zip_max_num[0x10]; - u8 reserved_at_57f[0x220]; + u8 reserved_at_5e0[0x220]; }; enum mlx5_flow_destination_type { -- GitLab From 7d5e14237a551a5de3d287f2e8db2d044ee81a1a Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Mon, 11 Apr 2016 23:10:22 +0300 Subject: [PATCH 3068/9938] net/mlx5: Update mlx5_ifc hardware features Adding the needed mlx5_ifc hardware bits and structs for the following feature: * Add vport to steering commands for SRIOV ACL support * Add mlcr, pcmr and mcia registers for dump module EEPROM * Add support for FCS, baeacon led and disable_link bits to hca caps * Add CQE period mode bit in CQ context for CQE based CQ moderation support * Add umr SQ bit for fragmented memory registration * Add needed bits and caps for Striding RQ support Signed-off-by: Saeed Mahameed Signed-off-by: Matan Barak Signed-off-by: David S. Miller --- include/linux/mlx5/mlx5_ifc.h | 146 +++++++++++++++++++++++++++++----- 1 file changed, 124 insertions(+), 22 deletions(-) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index c300e7491d80..4ce4ea422a10 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -513,7 +513,9 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits { u8 max_lso_cap[0x5]; u8 reserved_at_10[0x4]; u8 rss_ind_tbl_cap[0x4]; - u8 reserved_at_18[0x3]; + u8 reg_umr_sq[0x1]; + u8 scatter_fcs[0x1]; + u8 reserved_at_1a[0x1]; u8 tunnel_lso_const_out_ip_id[0x1]; u8 reserved_at_1c[0x2]; u8 tunnel_statless_gre[0x1]; @@ -648,7 +650,7 @@ struct mlx5_ifc_vector_calc_cap_bits { enum { MLX5_WQ_TYPE_LINKED_LIST = 0x0, MLX5_WQ_TYPE_CYCLIC = 0x1, - MLX5_WQ_TYPE_STRQ = 0x2, + MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ = 0x2, }; enum { @@ -753,7 +755,11 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 early_vf_enable[0x1]; u8 reserved_at_1a9[0x2]; u8 local_ca_ack_delay[0x5]; - u8 reserved_at_1af[0x6]; + u8 reserved_at_1af[0x2]; + u8 ports_check[0x1]; + u8 reserved_at_1b2[0x1]; + u8 disable_link_up[0x1]; + u8 beacon_led[0x1]; u8 port_type[0x2]; u8 num_ports[0x8]; @@ -778,7 +784,8 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 cqe_version[0x4]; u8 compact_address_vector[0x1]; - u8 reserved_at_200[0x3]; + u8 striding_rq[0x1]; + u8 reserved_at_201[0x2]; u8 ipoib_basic_offloads[0x1]; u8 reserved_at_205[0xa]; u8 drain_sigerr[0x1]; @@ -807,12 +814,12 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 block_lb_mc[0x1]; u8 reserved_at_229[0x1]; u8 scqe_break_moderation[0x1]; - u8 reserved_at_22a[0x1]; + u8 cq_period_start_from_cqe[0x1]; u8 cd[0x1]; u8 reserved_at_22d[0x1]; u8 apm[0x1]; u8 vector_calc[0x1]; - u8 reserved_at_22f[0x1]; + u8 umr_ptr_rlky[0x1]; u8 imaicl[0x1]; u8 reserved_at_232[0x4]; u8 qkv[0x1]; @@ -913,10 +920,10 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_500[0x80]; u8 reserved_at_580[0x3f]; - u8 cqe_zip[0x1]; + u8 cqe_compression[0x1]; - u8 cqe_zip_timeout[0x10]; - u8 cqe_zip_max_num[0x10]; + u8 cqe_compression_timeout[0x10]; + u8 cqe_compression_max_num[0x10]; u8 reserved_at_5e0[0x220]; }; @@ -1000,7 +1007,13 @@ struct mlx5_ifc_wq_bits { u8 reserved_at_118[0x3]; u8 log_wq_sz[0x5]; - u8 reserved_at_120[0x4e0]; + u8 reserved_at_120[0x15]; + u8 log_wqe_num_of_strides[0x3]; + u8 two_byte_shift_en[0x1]; + u8 reserved_at_139[0x4]; + u8 log_wqe_stride_size[0x3]; + + u8 reserved_at_140[0x4c0]; struct mlx5_ifc_cmd_pas_bits pas[0]; }; @@ -2199,7 +2212,8 @@ struct mlx5_ifc_sqc_bits { u8 flush_in_error_en[0x1]; u8 reserved_at_4[0x4]; u8 state[0x4]; - u8 reserved_at_c[0x14]; + u8 reg_umr[0x1]; + u8 reserved_at_d[0x13]; u8 reserved_at_20[0x8]; u8 user_index[0x18]; @@ -2247,7 +2261,8 @@ enum { struct mlx5_ifc_rqc_bits { u8 rlky[0x1]; - u8 reserved_at_1[0x2]; + u8 reserved_at_1[0x1]; + u8 scatter_fcs[0x1]; u8 vsd[0x1]; u8 mem_rq_type[0x4]; u8 state[0x4]; @@ -2604,6 +2619,11 @@ enum { MLX5_CQC_ST_FIRED = 0xa, }; +enum { + MLX5_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, + MLX5_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, +}; + struct mlx5_ifc_cqc_bits { u8 status[0x4]; u8 reserved_at_4[0x4]; @@ -2612,8 +2632,8 @@ struct mlx5_ifc_cqc_bits { u8 reserved_at_c[0x1]; u8 scqe_break_moderation_en[0x1]; u8 oi[0x1]; - u8 reserved_at_f[0x2]; - u8 cqe_zip_en[0x1]; + u8 cq_period_mode[0x2]; + u8 cqe_comp_en[0x1]; u8 mini_cqe_res_format[0x2]; u8 st[0x4]; u8 reserved_at_18[0x8]; @@ -2987,7 +3007,11 @@ struct mlx5_ifc_set_fte_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; + + u8 reserved_at_60[0x20]; u8 table_type[0x8]; u8 reserved_at_88[0x18]; @@ -5181,7 +5205,11 @@ struct mlx5_ifc_destroy_flow_table_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; + + u8 reserved_at_60[0x20]; u8 table_type[0x8]; u8 reserved_at_88[0x18]; @@ -5208,7 +5236,11 @@ struct mlx5_ifc_destroy_flow_group_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; + + u8 reserved_at_60[0x20]; u8 table_type[0x8]; u8 reserved_at_88[0x18]; @@ -5349,7 +5381,11 @@ struct mlx5_ifc_delete_fte_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; + + u8 reserved_at_60[0x20]; u8 table_type[0x8]; u8 reserved_at_88[0x18]; @@ -5795,7 +5831,11 @@ struct mlx5_ifc_create_flow_table_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; + + u8 reserved_at_60[0x20]; u8 table_type[0x8]; u8 reserved_at_88[0x18]; @@ -5839,7 +5879,11 @@ struct mlx5_ifc_create_flow_group_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; + + u8 reserved_at_60[0x20]; u8 table_type[0x8]; u8 reserved_at_88[0x18]; @@ -6372,6 +6416,17 @@ struct mlx5_ifc_ptys_reg_bits { u8 reserved_at_1a0[0x60]; }; +struct mlx5_ifc_mlcr_reg_bits { + u8 reserved_at_0[0x8]; + u8 local_port[0x8]; + u8 reserved_at_10[0x20]; + + u8 beacon_duration[0x10]; + u8 reserved_at_40[0x10]; + + u8 beacon_remain[0x10]; +}; + struct mlx5_ifc_ptas_reg_bits { u8 reserved_at_0[0x20]; @@ -6781,6 +6836,16 @@ struct mlx5_ifc_pamp_reg_bits { u8 index_data[18][0x10]; }; +struct mlx5_ifc_pcmr_reg_bits { + u8 reserved_at_0[0x8]; + u8 local_port[0x8]; + u8 reserved_at_10[0x2e]; + u8 fcs_cap[0x1]; + u8 reserved_at_3f[0x1f]; + u8 fcs_chk[0x1]; + u8 reserved_at_5f[0x1]; +}; + struct mlx5_ifc_lane_2_module_mapping_bits { u8 reserved_at_0[0x6]; u8 rx_lane[0x2]; @@ -7117,6 +7182,7 @@ union mlx5_ifc_ports_control_registers_document_bits { struct mlx5_ifc_pspa_reg_bits pspa_reg; struct mlx5_ifc_ptas_reg_bits ptas_reg; struct mlx5_ifc_ptys_reg_bits ptys_reg; + struct mlx5_ifc_mlcr_reg_bits mlcr_reg; struct mlx5_ifc_pude_reg_bits pude_reg; struct mlx5_ifc_pvlc_reg_bits pvlc_reg; struct mlx5_ifc_slrg_reg_bits slrg_reg; @@ -7150,7 +7216,11 @@ struct mlx5_ifc_set_flow_table_root_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; + + u8 reserved_at_60[0x20]; u8 table_type[0x8]; u8 reserved_at_88[0x18]; @@ -7181,7 +7251,9 @@ struct mlx5_ifc_modify_flow_table_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x20]; + u8 other_vport[0x1]; + u8 reserved_at_41[0xf]; + u8 vport_number[0x10]; u8 reserved_at_60[0x10]; u8 modify_field_select[0x10]; @@ -7247,4 +7319,34 @@ struct mlx5_ifc_qtct_reg_bits { u8 tclass[0x3]; }; +struct mlx5_ifc_mcia_reg_bits { + u8 l[0x1]; + u8 reserved_at_1[0x7]; + u8 module[0x8]; + u8 reserved_at_10[0x8]; + u8 status[0x8]; + + u8 i2c_device_address[0x8]; + u8 page_number[0x8]; + u8 device_address[0x10]; + + u8 reserved_at_40[0x10]; + u8 size[0x10]; + + u8 reserved_at_60[0x20]; + + u8 dword_0[0x20]; + u8 dword_1[0x20]; + u8 dword_2[0x20]; + u8 dword_3[0x20]; + u8 dword_4[0x20]; + u8 dword_5[0x20]; + u8 dword_6[0x20]; + u8 dword_7[0x20]; + u8 dword_8[0x20]; + u8 dword_9[0x20]; + u8 dword_10[0x20]; + u8 dword_11[0x20]; +}; + #endif /* MLX5_IFC_H */ -- GitLab From 311b21774f1389f9c34eac4da90c43c95fc2b62b Mon Sep 17 00:00:00 2001 From: Marcelo Ricardo Leitner Date: Wed, 13 Apr 2016 19:12:29 -0300 Subject: [PATCH 3069/9938] sctp: simplify sk_receive_queue locking SCTP already serializes access to rcvbuf through its sock lock: sctp_recvmsg takes it right in the start and release at the end, while rx path will also take the lock before doing any socket processing. On sctp_rcv() it will check if there is an user using the socket and, if there is, it will queue incoming packets to the backlog. The backlog processing will do the same. Even timers will do such check and re-schedule if an user is using the socket. Simplifying this will allow us to remove sctp_skb_list_tail and get ride of some expensive lockings. The lists that it is used on are also mangled with functions like __skb_queue_tail and __skb_unlink in the same context, like on sctp_ulpq_tail_event() and sctp_clear_pd(). sctp_close() will also purge those while using only the sock lock. Therefore the lockings performed by sctp_skb_list_tail() are not necessary. This patch removes this function and replaces its calls with just skb_queue_splice_tail_init() instead. The biggest gain is at sctp_ulpq_tail_event(), because the events always contain a list, even if it's queueing a single skb and this was triggering expensive calls to spin_lock_irqsave/_irqrestore for every data chunk received. As SCTP will deliver each data chunk on a corresponding recvmsg, the more effective the change will be. Before this patch, with chunks with 30 bytes: netperf -t SCTP_STREAM -H 192.168.1.2 -cC -l 60 -- -m 30 -S 400000 400000 -s 400000 400000 on a 10Gbit link with 1500 MTU: SCTP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.1.1 () port 0 AF_INET Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 425984 425984 30 60.00 137.45 7.34 7.36 52.504 52.608 With it: SCTP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.1.1 () port 0 AF_INET Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 425984 425984 30 60.00 179.10 7.97 6.70 43.740 36.788 Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 15 --------------- net/sctp/socket.c | 4 +--- net/sctp/ulpqueue.c | 5 +++-- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 03fb33efcae2..978d5f67d5a7 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -359,21 +359,6 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp); #define sctp_skb_for_each(pos, head, tmp) \ skb_queue_walk_safe(head, pos, tmp) -/* A helper to append an entire skb list (list) to another (head). */ -static inline void sctp_skb_list_tail(struct sk_buff_head *list, - struct sk_buff_head *head) -{ - unsigned long flags; - - spin_lock_irqsave(&head->lock, flags); - spin_lock(&list->lock); - - skb_queue_splice_tail_init(list, head); - - spin_unlock(&list->lock); - spin_unlock_irqrestore(&head->lock, flags); -} - /** * sctp_list_dequeue - remove from the head of the queue * @list: list to dequeue from diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 36697f85ce48..bf265a4bba6e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6766,13 +6766,11 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, * However, this function was correct in any case. 8) */ if (flags & MSG_PEEK) { - spin_lock_bh(&sk->sk_receive_queue.lock); skb = skb_peek(&sk->sk_receive_queue); if (skb) atomic_inc(&skb->users); - spin_unlock_bh(&sk->sk_receive_queue.lock); } else { - skb = skb_dequeue(&sk->sk_receive_queue); + skb = __skb_dequeue(&sk->sk_receive_queue); } if (skb) diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 72e5b3e41cdd..ec12a8920e5f 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -141,7 +141,8 @@ int sctp_clear_pd(struct sock *sk, struct sctp_association *asoc) */ if (!skb_queue_empty(&sp->pd_lobby)) { struct list_head *list; - sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue); + skb_queue_splice_tail_init(&sp->pd_lobby, + &sk->sk_receive_queue); list = (struct list_head *)&sctp_sk(sk)->pd_lobby; INIT_LIST_HEAD(list); return 1; @@ -252,7 +253,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) * collected on a list. */ if (skb_list) - sctp_skb_list_tail(skb_list, queue); + skb_queue_splice_tail_init(skb_list, queue); else __skb_queue_tail(queue, skb); -- GitLab From 4b91545072ad7ca1963d2a89c8b42fc2eb561484 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 15 Apr 2016 23:28:57 +0200 Subject: [PATCH 3070/9938] ARM: dts: rockchip: move rk3288 edp phy under the GRF The edp-phy control is a part of the General Register Files and with a recent patch in 4.6 the phy driver can now also handle this correctly, so move the dts node under the GRF as well. Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 180eb975ead5..906818955215 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -201,15 +201,6 @@ #clock-cells = <0>; }; - edp_phy: edp-phy { - compatible = "rockchip,rk3288-dp-phy"; - clocks = <&cru SCLK_EDP_24M>; - clock-names = "24m"; - rockchip,grf = <&grf>; - #phy-cells = <0>; - status = "disabled"; - }; - timer { compatible = "arm,armv7-timer"; arm,cpu-registers-not-fw-configured; @@ -756,6 +747,14 @@ grf: syscon@ff770000 { compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd"; reg = <0xff770000 0x1000>; + + edp_phy: edp-phy { + compatible = "rockchip,rk3288-dp-phy"; + clocks = <&cru SCLK_EDP_24M>; + clock-names = "24m"; + #phy-cells = <0>; + status = "disabled"; + }; }; wdt: watchdog@ff800000 { -- GitLab From 52c52a61a39fb319c14a582f8631619e5d5f55bf Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Apr 2016 15:35:30 +0800 Subject: [PATCH 3071/9938] sctp: add sctp_info dump api for sctp_diag sctp_diag will dump some important details of sctp's assoc or ep, we use sctp_info to describe them, sctp_get_sctp_info to get them, and export it to sctp_diag.ko. v2->v3: - we will not use list_for_each_safe in sctp_get_sctp_info, cause all the callers of it will use lock_sock. - fix the holes in struct sctp_info with __reserved* field. because sctp_diag is a new feature, and sctp_info is just for now, it may be changed in the future. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- include/linux/sctp.h | 67 ++++++++++++++++++++++++++++++++ include/net/sctp/sctp.h | 3 ++ net/sctp/socket.c | 86 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) diff --git a/include/linux/sctp.h b/include/linux/sctp.h index a9414fd49dc6..dacb5e711994 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -705,4 +705,71 @@ typedef struct sctp_auth_chunk { sctp_authhdr_t auth_hdr; } __packed sctp_auth_chunk_t; +struct sctp_info { + __u32 sctpi_tag; + __u32 sctpi_state; + __u32 sctpi_rwnd; + __u16 sctpi_unackdata; + __u16 sctpi_penddata; + __u16 sctpi_instrms; + __u16 sctpi_outstrms; + __u32 sctpi_fragmentation_point; + __u32 sctpi_inqueue; + __u32 sctpi_outqueue; + __u32 sctpi_overall_error; + __u32 sctpi_max_burst; + __u32 sctpi_maxseg; + __u32 sctpi_peer_rwnd; + __u32 sctpi_peer_tag; + __u8 sctpi_peer_capable; + __u8 sctpi_peer_sack; + __u16 __reserved1; + + /* assoc status info */ + __u64 sctpi_isacks; + __u64 sctpi_osacks; + __u64 sctpi_opackets; + __u64 sctpi_ipackets; + __u64 sctpi_rtxchunks; + __u64 sctpi_outofseqtsns; + __u64 sctpi_idupchunks; + __u64 sctpi_gapcnt; + __u64 sctpi_ouodchunks; + __u64 sctpi_iuodchunks; + __u64 sctpi_oodchunks; + __u64 sctpi_iodchunks; + __u64 sctpi_octrlchunks; + __u64 sctpi_ictrlchunks; + + /* primary transport info */ + struct sockaddr_storage sctpi_p_address; + __s32 sctpi_p_state; + __u32 sctpi_p_cwnd; + __u32 sctpi_p_srtt; + __u32 sctpi_p_rto; + __u32 sctpi_p_hbinterval; + __u32 sctpi_p_pathmaxrxt; + __u32 sctpi_p_sackdelay; + __u32 sctpi_p_sackfreq; + __u32 sctpi_p_ssthresh; + __u32 sctpi_p_partial_bytes_acked; + __u32 sctpi_p_flight_size; + __u16 sctpi_p_error; + __u16 __reserved2; + + /* sctp sock info */ + __u32 sctpi_s_autoclose; + __u32 sctpi_s_adaptation_ind; + __u32 sctpi_s_pd_point; + __u8 sctpi_s_nodelay; + __u8 sctpi_s_disable_fragments; + __u8 sctpi_s_v4mapped; + __u8 sctpi_s_frag_interleave; +}; + +struct sctp_infox { + struct sctp_info *sctpinfo; + struct sctp_association *asoc; +}; + #endif /* __LINUX_SCTP_H__ */ diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 978d5f67d5a7..268b10058ef5 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -116,6 +116,9 @@ extern struct percpu_counter sctp_sockets_allocated; int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); +int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc, + struct sctp_info *info); + /* * sctp/primitive.c */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index bf265a4bba6e..cd0fb3bb493c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4202,6 +4202,92 @@ static void sctp_shutdown(struct sock *sk, int how) } } +int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc, + struct sctp_info *info) +{ + struct sctp_transport *prim; + struct list_head *pos; + int mask; + + memset(info, 0, sizeof(*info)); + if (!asoc) { + struct sctp_sock *sp = sctp_sk(sk); + + info->sctpi_s_autoclose = sp->autoclose; + info->sctpi_s_adaptation_ind = sp->adaptation_ind; + info->sctpi_s_pd_point = sp->pd_point; + info->sctpi_s_nodelay = sp->nodelay; + info->sctpi_s_disable_fragments = sp->disable_fragments; + info->sctpi_s_v4mapped = sp->v4mapped; + info->sctpi_s_frag_interleave = sp->frag_interleave; + + return 0; + } + + info->sctpi_tag = asoc->c.my_vtag; + info->sctpi_state = asoc->state; + info->sctpi_rwnd = asoc->a_rwnd; + info->sctpi_unackdata = asoc->unack_data; + info->sctpi_penddata = sctp_tsnmap_pending(&asoc->peer.tsn_map); + info->sctpi_instrms = asoc->c.sinit_max_instreams; + info->sctpi_outstrms = asoc->c.sinit_num_ostreams; + list_for_each(pos, &asoc->base.inqueue.in_chunk_list) + info->sctpi_inqueue++; + list_for_each(pos, &asoc->outqueue.out_chunk_list) + info->sctpi_outqueue++; + info->sctpi_overall_error = asoc->overall_error_count; + info->sctpi_max_burst = asoc->max_burst; + info->sctpi_maxseg = asoc->frag_point; + info->sctpi_peer_rwnd = asoc->peer.rwnd; + info->sctpi_peer_tag = asoc->c.peer_vtag; + + mask = asoc->peer.ecn_capable << 1; + mask = (mask | asoc->peer.ipv4_address) << 1; + mask = (mask | asoc->peer.ipv6_address) << 1; + mask = (mask | asoc->peer.hostname_address) << 1; + mask = (mask | asoc->peer.asconf_capable) << 1; + mask = (mask | asoc->peer.prsctp_capable) << 1; + mask = (mask | asoc->peer.auth_capable); + info->sctpi_peer_capable = mask; + mask = asoc->peer.sack_needed << 1; + mask = (mask | asoc->peer.sack_generation) << 1; + mask = (mask | asoc->peer.zero_window_announced); + info->sctpi_peer_sack = mask; + + info->sctpi_isacks = asoc->stats.isacks; + info->sctpi_osacks = asoc->stats.osacks; + info->sctpi_opackets = asoc->stats.opackets; + info->sctpi_ipackets = asoc->stats.ipackets; + info->sctpi_rtxchunks = asoc->stats.rtxchunks; + info->sctpi_outofseqtsns = asoc->stats.outofseqtsns; + info->sctpi_idupchunks = asoc->stats.idupchunks; + info->sctpi_gapcnt = asoc->stats.gapcnt; + info->sctpi_ouodchunks = asoc->stats.ouodchunks; + info->sctpi_iuodchunks = asoc->stats.iuodchunks; + info->sctpi_oodchunks = asoc->stats.oodchunks; + info->sctpi_iodchunks = asoc->stats.iodchunks; + info->sctpi_octrlchunks = asoc->stats.octrlchunks; + info->sctpi_ictrlchunks = asoc->stats.ictrlchunks; + + prim = asoc->peer.primary_path; + memcpy(&info->sctpi_p_address, &prim->ipaddr, + sizeof(struct sockaddr_storage)); + info->sctpi_p_state = prim->state; + info->sctpi_p_cwnd = prim->cwnd; + info->sctpi_p_srtt = prim->srtt; + info->sctpi_p_rto = jiffies_to_msecs(prim->rto); + info->sctpi_p_hbinterval = prim->hbinterval; + info->sctpi_p_pathmaxrxt = prim->pathmaxrxt; + info->sctpi_p_sackdelay = jiffies_to_msecs(prim->sackdelay); + info->sctpi_p_ssthresh = prim->ssthresh; + info->sctpi_p_partial_bytes_acked = prim->partial_bytes_acked; + info->sctpi_p_flight_size = prim->flight_size; + info->sctpi_p_error = prim->error_count; + + return 0; +} +EXPORT_SYMBOL_GPL(sctp_get_sctp_info); + /* 7.2.1 Association Status (SCTP_STATUS) * Applications can retrieve current status information about an -- GitLab From 626d16f50f39bb9c44f98fd256cae2b864900a01 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Apr 2016 15:35:31 +0800 Subject: [PATCH 3072/9938] sctp: export some apis or variables for sctp_diag and reuse some for proc For some main variables in sctp.ko, we couldn't export it to other modules, so we have to define some api to access them. It will include sctp transport and endpoint's traversal. There are some transport traversal functions for sctp_diag, we can also use it for sctp_proc. cause they have the similar situation to traversal transport. v2->v3: - rhashtable_walk_init need the parameter gfp, because of recent upstrem update Signed-off-by: Xin Long Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 13 +++++ net/sctp/proc.c | 81 ++++++-------------------- net/sctp/socket.c | 125 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 63 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 268b10058ef5..3f1c0ff7d4b6 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -116,6 +116,19 @@ extern struct percpu_counter sctp_sockets_allocated; int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); +int sctp_transport_walk_start(struct rhashtable_iter *iter); +void sctp_transport_walk_stop(struct rhashtable_iter *iter); +struct sctp_transport *sctp_transport_get_next(struct net *net, + struct rhashtable_iter *iter); +struct sctp_transport *sctp_transport_get_idx(struct net *net, + struct rhashtable_iter *iter, int pos); +int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), + struct net *net, + const union sctp_addr *laddr, + const union sctp_addr *paddr, void *p); +int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), + struct net *net, int pos, void *p); +int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p); int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc, struct sctp_info *info); diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 6d45d53321e6..dd8492f0037d 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -282,81 +282,31 @@ struct sctp_ht_iter { struct rhashtable_iter hti; }; -static struct sctp_transport *sctp_transport_get_next(struct seq_file *seq) -{ - struct sctp_ht_iter *iter = seq->private; - struct sctp_transport *t; - - t = rhashtable_walk_next(&iter->hti); - for (; t; t = rhashtable_walk_next(&iter->hti)) { - if (IS_ERR(t)) { - if (PTR_ERR(t) == -EAGAIN) - continue; - break; - } - - if (net_eq(sock_net(t->asoc->base.sk), seq_file_net(seq)) && - t->asoc->peer.primary_path == t) - break; - } - - return t; -} - -static struct sctp_transport *sctp_transport_get_idx(struct seq_file *seq, - loff_t pos) -{ - void *obj = SEQ_START_TOKEN; - - while (pos && (obj = sctp_transport_get_next(seq)) && !IS_ERR(obj)) - pos--; - - return obj; -} - -static int sctp_transport_walk_start(struct seq_file *seq) -{ - struct sctp_ht_iter *iter = seq->private; - int err; - - err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti, - GFP_KERNEL); - if (err) - return err; - - err = rhashtable_walk_start(&iter->hti); - - return err == -EAGAIN ? 0 : err; -} - -static void sctp_transport_walk_stop(struct seq_file *seq) -{ - struct sctp_ht_iter *iter = seq->private; - - rhashtable_walk_stop(&iter->hti); - rhashtable_walk_exit(&iter->hti); -} - static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) { - int err = sctp_transport_walk_start(seq); + struct sctp_ht_iter *iter = seq->private; + int err = sctp_transport_walk_start(&iter->hti); if (err) return ERR_PTR(err); - return sctp_transport_get_idx(seq, *pos); + return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); } static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) { - sctp_transport_walk_stop(seq); + struct sctp_ht_iter *iter = seq->private; + + sctp_transport_walk_stop(&iter->hti); } static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos) { + struct sctp_ht_iter *iter = seq->private; + ++*pos; - return sctp_transport_get_next(seq); + return sctp_transport_get_next(seq_file_net(seq), &iter->hti); } /* Display sctp associations (/proc/net/sctp/assocs). */ @@ -458,24 +408,29 @@ void sctp_assocs_proc_exit(struct net *net) static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) { - int err = sctp_transport_walk_start(seq); + struct sctp_ht_iter *iter = seq->private; + int err = sctp_transport_walk_start(&iter->hti); if (err) return ERR_PTR(err); - return sctp_transport_get_idx(seq, *pos); + return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); } static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) { + struct sctp_ht_iter *iter = seq->private; + ++*pos; - return sctp_transport_get_next(seq); + return sctp_transport_get_next(seq_file_net(seq), &iter->hti); } static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) { - sctp_transport_walk_stop(seq); + struct sctp_ht_iter *iter = seq->private; + + sctp_transport_walk_stop(&iter->hti); } static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index cd0fb3bb493c..5e5bc08d2b25 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4288,6 +4288,131 @@ int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc, } EXPORT_SYMBOL_GPL(sctp_get_sctp_info); +/* use callback to avoid exporting the core structure */ +int sctp_transport_walk_start(struct rhashtable_iter *iter) +{ + int err; + + err = rhashtable_walk_init(&sctp_transport_hashtable, iter, + GFP_KERNEL); + if (err) + return err; + + err = rhashtable_walk_start(iter); + + return err == -EAGAIN ? 0 : err; +} + +void sctp_transport_walk_stop(struct rhashtable_iter *iter) +{ + rhashtable_walk_stop(iter); + rhashtable_walk_exit(iter); +} + +struct sctp_transport *sctp_transport_get_next(struct net *net, + struct rhashtable_iter *iter) +{ + struct sctp_transport *t; + + t = rhashtable_walk_next(iter); + for (; t; t = rhashtable_walk_next(iter)) { + if (IS_ERR(t)) { + if (PTR_ERR(t) == -EAGAIN) + continue; + break; + } + + if (net_eq(sock_net(t->asoc->base.sk), net) && + t->asoc->peer.primary_path == t) + break; + } + + return t; +} + +struct sctp_transport *sctp_transport_get_idx(struct net *net, + struct rhashtable_iter *iter, + int pos) +{ + void *obj = SEQ_START_TOKEN; + + while (pos && (obj = sctp_transport_get_next(net, iter)) && + !IS_ERR(obj)) + pos--; + + return obj; +} + +int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), + void *p) { + int err = 0; + int hash = 0; + struct sctp_ep_common *epb; + struct sctp_hashbucket *head; + + for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize; + hash++, head++) { + read_lock(&head->lock); + sctp_for_each_hentry(epb, &head->chain) { + err = cb(sctp_ep(epb), p); + if (err) + break; + } + read_unlock(&head->lock); + } + + return err; +} +EXPORT_SYMBOL_GPL(sctp_for_each_endpoint); + +int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), + struct net *net, + const union sctp_addr *laddr, + const union sctp_addr *paddr, void *p) +{ + struct sctp_transport *transport; + int err = 0; + + rcu_read_lock(); + transport = sctp_addrs_lookup_transport(net, laddr, paddr); + if (!transport || !sctp_transport_hold(transport)) + goto out; + err = cb(transport, p); + sctp_transport_put(transport); + +out: + rcu_read_unlock(); + return err; +} +EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); + +int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), + struct net *net, int pos, void *p) { + struct rhashtable_iter hti; + int err = 0; + void *obj; + + if (sctp_transport_walk_start(&hti)) + goto out; + + sctp_transport_get_idx(net, &hti, pos); + obj = sctp_transport_get_next(net, &hti); + for (; obj && !IS_ERR(obj); obj = sctp_transport_get_next(net, &hti)) { + struct sctp_transport *transport = obj; + + if (!sctp_transport_hold(transport)) + continue; + err = cb(transport, p); + sctp_transport_put(transport); + if (err) + break; + } +out: + sctp_transport_walk_stop(&hti); + return err; +} +EXPORT_SYMBOL_GPL(sctp_for_each_transport); + /* 7.2.1 Association Status (SCTP_STATUS) * Applications can retrieve current status information about an -- GitLab From cb2050a7b8131a9a9f3f97276df1feaae8987dc8 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Apr 2016 15:35:32 +0800 Subject: [PATCH 3073/9938] sctp: export some functions for sctp_diag in inet_diag inet_diag_msg_common_fill is used to fill the diag msg common info, we need to use it in sctp_diag as well, so export it. inet_diag_msg_attrs_fill is used to fill some common attrs info between sctp diag and tcp diag. v2->v3: - do not need to define and export inet_diag_get_handler any more. cause all the functions in it are in sctp_diag.ko, we just call them in sctp_diag.ko. - add inet_diag_msg_attrs_fill to make codes clear. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 67 +++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index bd591eb81ec9..70212bddf0f8 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -66,7 +66,7 @@ static void inet_diag_unlock_handler(const struct inet_diag_handler *handler) mutex_unlock(&inet_diag_table_mutex); } -static void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk) +void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk) { r->idiag_family = sk->sk_family; @@ -89,6 +89,7 @@ static void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk) r->id.idiag_dst[0] = sk->sk_daddr; } } +EXPORT_SYMBOL_GPL(inet_diag_msg_common_fill); static size_t inet_sk_attr_size(void) { @@ -104,13 +105,50 @@ static size_t inet_sk_attr_size(void) + 64; } +int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, + struct inet_diag_msg *r, int ext, + struct user_namespace *user_ns) +{ + const struct inet_sock *inet = inet_sk(sk); + + if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown)) + goto errout; + + /* IPv6 dual-stack sockets use inet->tos for IPv4 connections, + * hence this needs to be included regardless of socket family. + */ + if (ext & (1 << (INET_DIAG_TOS - 1))) + if (nla_put_u8(skb, INET_DIAG_TOS, inet->tos) < 0) + goto errout; + +#if IS_ENABLED(CONFIG_IPV6) + if (r->idiag_family == AF_INET6) { + if (ext & (1 << (INET_DIAG_TCLASS - 1))) + if (nla_put_u8(skb, INET_DIAG_TCLASS, + inet6_sk(sk)->tclass) < 0) + goto errout; + + if (((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && + nla_put_u8(skb, INET_DIAG_SKV6ONLY, ipv6_only_sock(sk))) + goto errout; + } +#endif + + r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); + r->idiag_inode = sock_i_ino(sk); + + return 0; +errout: + return 1; +} +EXPORT_SYMBOL_GPL(inet_diag_msg_attrs_fill); + int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, struct sk_buff *skb, const struct inet_diag_req_v2 *req, struct user_namespace *user_ns, u32 portid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { - const struct inet_sock *inet = inet_sk(sk); const struct tcp_congestion_ops *ca_ops; const struct inet_diag_handler *handler; int ext = req->idiag_ext; @@ -135,32 +173,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, r->idiag_timer = 0; r->idiag_retrans = 0; - if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown)) + if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns)) goto errout; - /* IPv6 dual-stack sockets use inet->tos for IPv4 connections, - * hence this needs to be included regardless of socket family. - */ - if (ext & (1 << (INET_DIAG_TOS - 1))) - if (nla_put_u8(skb, INET_DIAG_TOS, inet->tos) < 0) - goto errout; - -#if IS_ENABLED(CONFIG_IPV6) - if (r->idiag_family == AF_INET6) { - if (ext & (1 << (INET_DIAG_TCLASS - 1))) - if (nla_put_u8(skb, INET_DIAG_TCLASS, - inet6_sk(sk)->tclass) < 0) - goto errout; - - if (((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && - nla_put_u8(skb, INET_DIAG_SKV6ONLY, ipv6_only_sock(sk))) - goto errout; - } -#endif - - r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); - r->idiag_inode = sock_i_ino(sk); - if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { struct inet_diag_meminfo minfo = { .idiag_rmem = sk_rmem_alloc_get(sk), -- GitLab From 8f840e47f190cbe61a96945c13e9551048d42cef Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Apr 2016 15:35:33 +0800 Subject: [PATCH 3074/9938] sctp: add the sctp_diag.c file This one will implement all the interface of inet_diag, inet_diag_handler. which includes sctp_diag_dump, sctp_diag_dump_one and sctp_diag_get_info. It will work as a module, and register inet_diag_handler when loading. v2->v3: - fix the mistake in inet_assoc_attr_size(). - change inet_diag_msg_laddrs_fill() name to inet_diag_msg_sctpladdrs_fill. - change inet_diag_msg_paddrs_fill() name to inet_diag_msg_sctpaddrs_fill. - add inet_diag_msg_sctpinfo_fill() to make asoc/ep fill code clearer. - add inet_diag_msg_sctpasoc_fill() to make asoc fill code clearer. - merge inet_asoc_diag_fill() and inet_ep_diag_fill() to inet_sctp_diag_fill(). - call sctp_diag_get_info() directly, instead by handler, cause the caller is in the same file with it. - call lock_sock in sctp_tsp_dump_one() to make sure we call get sctp info safely. - after lock_sock(sk), we should check sk != assoc->base.sk. - change mem[SK_MEMINFO_WMEM_ALLOC] to asoc->sndbuf_used for asoc dump when asoc->ep->sndbuf_policy is set. don't use INET_DIAG_MEMINFO attr any more. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- include/uapi/linux/inet_diag.h | 2 + net/sctp/Kconfig | 4 + net/sctp/Makefile | 1 + net/sctp/sctp_diag.c | 497 +++++++++++++++++++++++++++++++++ 4 files changed, 504 insertions(+) create mode 100644 net/sctp/sctp_diag.c diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h index 68a1f71fde9f..f5f3629dd553 100644 --- a/include/uapi/linux/inet_diag.h +++ b/include/uapi/linux/inet_diag.h @@ -113,6 +113,8 @@ enum { INET_DIAG_DCTCPINFO, INET_DIAG_PROTOCOL, /* response attribute only */ INET_DIAG_SKV6ONLY, + INET_DIAG_LOCALS, + INET_DIAG_PEERS, }; #define INET_DIAG_MAX INET_DIAG_SKV6ONLY diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 71c1a598d9bc..d9c04dc1b3f3 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -99,5 +99,9 @@ config SCTP_COOKIE_HMAC_SHA1 select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1 select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1 +config INET_SCTP_DIAG + depends on INET_DIAG + def_tristate INET_DIAG + endif # IP_SCTP diff --git a/net/sctp/Makefile b/net/sctp/Makefile index 3b4ffb021cf1..0fca5824ad0e 100644 --- a/net/sctp/Makefile +++ b/net/sctp/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_IP_SCTP) += sctp.o obj-$(CONFIG_NET_SCTPPROBE) += sctp_probe.o +obj-$(CONFIG_INET_SCTP_DIAG) += sctp_diag.o sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ protocol.o endpointola.o associola.o \ diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c new file mode 100644 index 000000000000..98ecd16da0c9 --- /dev/null +++ b/net/sctp/sctp_diag.c @@ -0,0 +1,497 @@ +#include +#include +#include +#include + +extern void inet_diag_msg_common_fill(struct inet_diag_msg *r, + struct sock *sk); +extern int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, + struct inet_diag_msg *r, int ext, + struct user_namespace *user_ns); + +static void sctp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, + void *info); + +/* define some functions to make asoc/ep fill look clean */ +static void inet_diag_msg_sctpasoc_fill(struct inet_diag_msg *r, + struct sock *sk, + struct sctp_association *asoc) +{ + union sctp_addr laddr, paddr; + struct dst_entry *dst; + + laddr = list_entry(asoc->base.bind_addr.address_list.next, + struct sctp_sockaddr_entry, list)->a; + paddr = asoc->peer.primary_path->ipaddr; + dst = asoc->peer.primary_path->dst; + + r->idiag_family = sk->sk_family; + r->id.idiag_sport = htons(asoc->base.bind_addr.port); + r->id.idiag_dport = htons(asoc->peer.port); + r->id.idiag_if = dst ? dst->dev->ifindex : 0; + sock_diag_save_cookie(sk, r->id.idiag_cookie); + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) { + *(struct in6_addr *)r->id.idiag_src = laddr.v6.sin6_addr; + *(struct in6_addr *)r->id.idiag_dst = paddr.v6.sin6_addr; + } else +#endif + { + memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); + memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); + + r->id.idiag_src[0] = laddr.v4.sin_addr.s_addr; + r->id.idiag_dst[0] = paddr.v4.sin_addr.s_addr; + } + + r->idiag_state = asoc->state; + r->idiag_timer = SCTP_EVENT_TIMEOUT_T3_RTX; + r->idiag_retrans = asoc->rtx_data_chunks; +#define EXPIRES_IN_MS(tmo) DIV_ROUND_UP((tmo - jiffies) * 1000, HZ) + r->idiag_expires = + EXPIRES_IN_MS(asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX]); +#undef EXPIRES_IN_MS +} + +static int inet_diag_msg_sctpladdrs_fill(struct sk_buff *skb, + struct list_head *address_list) +{ + struct sctp_sockaddr_entry *laddr; + int addrlen = sizeof(struct sockaddr_storage); + int addrcnt = 0; + struct nlattr *attr; + void *info = NULL; + + list_for_each_entry_rcu(laddr, address_list, list) + addrcnt++; + + attr = nla_reserve(skb, INET_DIAG_LOCALS, addrlen * addrcnt); + if (!attr) + return -EMSGSIZE; + + info = nla_data(attr); + list_for_each_entry_rcu(laddr, address_list, list) { + memcpy(info, &laddr->a, addrlen); + info += addrlen; + } + + return 0; +} + +static int inet_diag_msg_sctpaddrs_fill(struct sk_buff *skb, + struct sctp_association *asoc) +{ + int addrlen = sizeof(struct sockaddr_storage); + struct sctp_transport *from; + struct nlattr *attr; + void *info = NULL; + + attr = nla_reserve(skb, INET_DIAG_PEERS, + addrlen * asoc->peer.transport_count); + if (!attr) + return -EMSGSIZE; + + info = nla_data(attr); + list_for_each_entry(from, &asoc->peer.transport_addr_list, + transports) { + memcpy(info, &from->ipaddr, addrlen); + info += addrlen; + } + + return 0; +} + +/* sctp asoc/ep fill*/ +static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc, + struct sk_buff *skb, + const struct inet_diag_req_v2 *req, + struct user_namespace *user_ns, + int portid, u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) +{ + struct sctp_endpoint *ep = sctp_sk(sk)->ep; + struct list_head *addr_list; + struct inet_diag_msg *r; + struct nlmsghdr *nlh; + int ext = req->idiag_ext; + struct sctp_infox infox; + void *info = NULL; + + nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r), + nlmsg_flags); + if (!nlh) + return -EMSGSIZE; + + r = nlmsg_data(nlh); + BUG_ON(!sk_fullsock(sk)); + + if (asoc) { + inet_diag_msg_sctpasoc_fill(r, sk, asoc); + } else { + inet_diag_msg_common_fill(r, sk); + r->idiag_state = sk->sk_state; + r->idiag_timer = 0; + r->idiag_retrans = 0; + } + + if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns)) + goto errout; + + if (ext & (1 << (INET_DIAG_SKMEMINFO - 1))) { + u32 mem[SK_MEMINFO_VARS]; + int amt; + + if (asoc && asoc->ep->sndbuf_policy) + amt = asoc->sndbuf_used; + else + amt = sk_wmem_alloc_get(sk); + mem[SK_MEMINFO_WMEM_ALLOC] = amt; + mem[SK_MEMINFO_RMEM_ALLOC] = sk_rmem_alloc_get(sk); + mem[SK_MEMINFO_RCVBUF] = sk->sk_rcvbuf; + mem[SK_MEMINFO_SNDBUF] = sk->sk_sndbuf; + mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc; + mem[SK_MEMINFO_WMEM_QUEUED] = sk->sk_wmem_queued; + mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc); + mem[SK_MEMINFO_BACKLOG] = sk->sk_backlog.len; + mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops); + + if (nla_put(skb, INET_DIAG_SKMEMINFO, sizeof(mem), &mem) < 0) + goto errout; + } + + if (ext & (1 << (INET_DIAG_INFO - 1))) { + struct nlattr *attr; + + attr = nla_reserve(skb, INET_DIAG_INFO, + sizeof(struct sctp_info)); + if (!attr) + goto errout; + + info = nla_data(attr); + } + infox.sctpinfo = (struct sctp_info *)info; + infox.asoc = asoc; + sctp_diag_get_info(sk, r, &infox); + + addr_list = asoc ? &asoc->base.bind_addr.address_list + : &ep->base.bind_addr.address_list; + if (inet_diag_msg_sctpladdrs_fill(skb, addr_list)) + goto errout; + + if (asoc && (ext & (1 << (INET_DIAG_CONG - 1)))) + if (nla_put_string(skb, INET_DIAG_CONG, "reno") < 0) + goto errout; + + if (asoc && inet_diag_msg_sctpaddrs_fill(skb, asoc)) + goto errout; + + nlmsg_end(skb, nlh); + return 0; + +errout: + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; +} + +/* callback and param */ +struct sctp_comm_param { + struct sk_buff *skb; + struct netlink_callback *cb; + const struct inet_diag_req_v2 *r; + const struct nlmsghdr *nlh; +}; + +static size_t inet_assoc_attr_size(struct sctp_association *asoc) +{ + int addrlen = sizeof(struct sockaddr_storage); + int addrcnt = 0; + struct sctp_sockaddr_entry *laddr; + + list_for_each_entry_rcu(laddr, &asoc->base.bind_addr.address_list, + list) + addrcnt++; + + return nla_total_size(sizeof(struct sctp_info)) + + nla_total_size(1) /* INET_DIAG_SHUTDOWN */ + + nla_total_size(1) /* INET_DIAG_TOS */ + + nla_total_size(1) /* INET_DIAG_TCLASS */ + + nla_total_size(addrlen * asoc->peer.transport_count) + + nla_total_size(addrlen * addrcnt) + + nla_total_size(sizeof(struct inet_diag_meminfo)) + + nla_total_size(sizeof(struct inet_diag_msg)) + + 64; +} + +static int sctp_tsp_dump_one(struct sctp_transport *tsp, void *p) +{ + struct sctp_association *assoc = tsp->asoc; + struct sock *sk = tsp->asoc->base.sk; + struct sctp_comm_param *commp = p; + struct sk_buff *in_skb = commp->skb; + const struct inet_diag_req_v2 *req = commp->r; + const struct nlmsghdr *nlh = commp->nlh; + struct net *net = sock_net(in_skb->sk); + struct sk_buff *rep; + int err; + + err = sock_diag_check_cookie(sk, req->id.idiag_cookie); + if (err) + goto out; + + err = -ENOMEM; + rep = nlmsg_new(inet_assoc_attr_size(assoc), GFP_KERNEL); + if (!rep) + goto out; + + lock_sock(sk); + if (sk != assoc->base.sk) { + release_sock(sk); + sk = assoc->base.sk; + lock_sock(sk); + } + err = inet_sctp_diag_fill(sk, assoc, rep, req, + sk_user_ns(NETLINK_CB(in_skb).sk), + NETLINK_CB(in_skb).portid, + nlh->nlmsg_seq, 0, nlh); + release_sock(sk); + if (err < 0) { + WARN_ON(err == -EMSGSIZE); + kfree_skb(rep); + goto out; + } + + err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, + MSG_DONTWAIT); + if (err > 0) + err = 0; +out: + return err; +} + +static int sctp_tsp_dump(struct sctp_transport *tsp, void *p) +{ + struct sctp_endpoint *ep = tsp->asoc->ep; + struct sctp_comm_param *commp = p; + struct sock *sk = ep->base.sk; + struct sk_buff *skb = commp->skb; + struct netlink_callback *cb = commp->cb; + const struct inet_diag_req_v2 *r = commp->r; + struct sctp_association *assoc = + list_entry(ep->asocs.next, struct sctp_association, asocs); + int err = 0; + + /* find the ep only once through the transports by this condition */ + if (tsp->asoc != assoc) + goto out; + + if (r->sdiag_family != AF_UNSPEC && sk->sk_family != r->sdiag_family) + goto out; + + lock_sock(sk); + if (sk != assoc->base.sk) + goto release; + list_for_each_entry(assoc, &ep->asocs, asocs) { + if (cb->args[4] < cb->args[1]) + goto next; + + if (r->id.idiag_sport != htons(assoc->base.bind_addr.port) && + r->id.idiag_sport) + goto next; + if (r->id.idiag_dport != htons(assoc->peer.port) && + r->id.idiag_dport) + goto next; + + if (!cb->args[3] && + inet_sctp_diag_fill(sk, NULL, skb, r, + sk_user_ns(NETLINK_CB(cb->skb).sk), + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + NLM_F_MULTI, cb->nlh) < 0) { + cb->args[3] = 1; + err = 2; + goto release; + } + cb->args[3] = 1; + + if (inet_sctp_diag_fill(sk, assoc, skb, r, + sk_user_ns(NETLINK_CB(cb->skb).sk), + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, 0, cb->nlh) < 0) { + err = 2; + goto release; + } +next: + cb->args[4]++; + } + cb->args[1] = 0; + cb->args[2]++; + cb->args[3] = 0; + cb->args[4] = 0; +release: + release_sock(sk); + return err; +out: + cb->args[2]++; + return err; +} + +static int sctp_ep_dump(struct sctp_endpoint *ep, void *p) +{ + struct sctp_comm_param *commp = p; + struct sock *sk = ep->base.sk; + struct sk_buff *skb = commp->skb; + struct netlink_callback *cb = commp->cb; + const struct inet_diag_req_v2 *r = commp->r; + struct net *net = sock_net(skb->sk); + struct inet_sock *inet = inet_sk(sk); + int err = 0; + + if (!net_eq(sock_net(sk), net)) + goto out; + + if (cb->args[4] < cb->args[1]) + goto next; + + if (r->sdiag_family != AF_UNSPEC && + sk->sk_family != r->sdiag_family) + goto next; + + if (r->id.idiag_sport != inet->inet_sport && + r->id.idiag_sport) + goto next; + + if (r->id.idiag_dport != inet->inet_dport && + r->id.idiag_dport) + goto next; + + if (inet_sctp_diag_fill(sk, NULL, skb, r, + sk_user_ns(NETLINK_CB(cb->skb).sk), + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, + cb->nlh) < 0) { + err = 2; + goto out; + } +next: + cb->args[4]++; +out: + return err; +} + +/* define the functions for sctp_diag_handler*/ +static void sctp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, + void *info) +{ + struct sctp_infox *infox = (struct sctp_infox *)info; + + if (infox->asoc) { + r->idiag_rqueue = atomic_read(&infox->asoc->rmem_alloc); + r->idiag_wqueue = infox->asoc->sndbuf_used; + } else { + r->idiag_rqueue = sk->sk_ack_backlog; + r->idiag_wqueue = sk->sk_max_ack_backlog; + } + if (infox->sctpinfo) + sctp_get_sctp_info(sk, infox->asoc, infox->sctpinfo); +} + +static int sctp_diag_dump_one(struct sk_buff *in_skb, + const struct nlmsghdr *nlh, + const struct inet_diag_req_v2 *req) +{ + struct net *net = sock_net(in_skb->sk); + union sctp_addr laddr, paddr; + struct sctp_comm_param commp = { + .skb = in_skb, + .r = req, + .nlh = nlh, + }; + + if (req->sdiag_family == AF_INET) { + laddr.v4.sin_port = req->id.idiag_sport; + laddr.v4.sin_addr.s_addr = req->id.idiag_src[0]; + laddr.v4.sin_family = AF_INET; + + paddr.v4.sin_port = req->id.idiag_dport; + paddr.v4.sin_addr.s_addr = req->id.idiag_dst[0]; + paddr.v4.sin_family = AF_INET; + } else { + laddr.v6.sin6_port = req->id.idiag_sport; + memcpy(&laddr.v6.sin6_addr, req->id.idiag_src, 64); + laddr.v6.sin6_family = AF_INET6; + + paddr.v6.sin6_port = req->id.idiag_dport; + memcpy(&paddr.v6.sin6_addr, req->id.idiag_dst, 64); + paddr.v6.sin6_family = AF_INET6; + } + + return sctp_transport_lookup_process(sctp_tsp_dump_one, + net, &laddr, &paddr, &commp); +} + +static void sctp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, + const struct inet_diag_req_v2 *r, struct nlattr *bc) +{ + u32 idiag_states = r->idiag_states; + struct net *net = sock_net(skb->sk); + struct sctp_comm_param commp = { + .skb = skb, + .cb = cb, + .r = r, + }; + + /* eps hashtable dumps + * args: + * 0 : if it will traversal listen sock + * 1 : to record the sock pos of this time's traversal + * 4 : to work as a temporary variable to traversal list + */ + if (cb->args[0] == 0) { + if (!(idiag_states & TCPF_LISTEN)) + goto skip; + if (sctp_for_each_endpoint(sctp_ep_dump, &commp)) + goto done; +skip: + cb->args[0] = 1; + cb->args[1] = 0; + cb->args[4] = 0; + } + + /* asocs by transport hashtable dump + * args: + * 1 : to record the assoc pos of this time's traversal + * 2 : to record the transport pos of this time's traversal + * 3 : to mark if we have dumped the ep info of the current asoc + * 4 : to work as a temporary variable to traversal list + */ + if (!(idiag_states & ~TCPF_LISTEN)) + goto done; + sctp_for_each_transport(sctp_tsp_dump, net, cb->args[2], &commp); +done: + cb->args[1] = cb->args[4]; + cb->args[4] = 0; +} + +static const struct inet_diag_handler sctp_diag_handler = { + .dump = sctp_diag_dump, + .dump_one = sctp_diag_dump_one, + .idiag_get_info = sctp_diag_get_info, + .idiag_type = IPPROTO_SCTP, + .idiag_info_size = sizeof(struct sctp_info), +}; + +static int __init sctp_diag_init(void) +{ + return inet_diag_register(&sctp_diag_handler); +} + +static void __exit sctp_diag_exit(void) +{ + inet_diag_unregister(&sctp_diag_handler); +} + +module_init(sctp_diag_init); +module_exit(sctp_diag_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-132); -- GitLab From b5e2f4e6998a2b999da8fa0290b692f0bd85c8b7 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Apr 2016 15:35:34 +0800 Subject: [PATCH 3075/9938] sctp: merge the seq_start/next/exits in remaddrs and assocs In sctp proc, these three functions in remaddrs and assocs are the same. we should merge them into one. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/proc.c | 45 +++++++++------------------------------------ 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/net/sctp/proc.c b/net/sctp/proc.c index dd8492f0037d..9fe139368ad7 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -282,7 +282,7 @@ struct sctp_ht_iter { struct rhashtable_iter hti; }; -static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) +static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) { struct sctp_ht_iter *iter = seq->private; int err = sctp_transport_walk_start(&iter->hti); @@ -293,14 +293,14 @@ static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); } -static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) +static void sctp_transport_seq_stop(struct seq_file *seq, void *v) { struct sctp_ht_iter *iter = seq->private; sctp_transport_walk_stop(&iter->hti); } -static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sctp_ht_iter *iter = seq->private; @@ -367,9 +367,9 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) } static const struct seq_operations sctp_assoc_ops = { - .start = sctp_assocs_seq_start, - .next = sctp_assocs_seq_next, - .stop = sctp_assocs_seq_stop, + .start = sctp_transport_seq_start, + .next = sctp_transport_seq_next, + .stop = sctp_transport_seq_stop, .show = sctp_assocs_seq_show, }; @@ -406,33 +406,6 @@ void sctp_assocs_proc_exit(struct net *net) remove_proc_entry("assocs", net->sctp.proc_net_sctp); } -static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) -{ - struct sctp_ht_iter *iter = seq->private; - int err = sctp_transport_walk_start(&iter->hti); - - if (err) - return ERR_PTR(err); - - return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); -} - -static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - struct sctp_ht_iter *iter = seq->private; - - ++*pos; - - return sctp_transport_get_next(seq_file_net(seq), &iter->hti); -} - -static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) -{ - struct sctp_ht_iter *iter = seq->private; - - sctp_transport_walk_stop(&iter->hti); -} - static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) { struct sctp_association *assoc; @@ -506,9 +479,9 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) } static const struct seq_operations sctp_remaddr_ops = { - .start = sctp_remaddr_seq_start, - .next = sctp_remaddr_seq_next, - .stop = sctp_remaddr_seq_stop, + .start = sctp_transport_seq_start, + .next = sctp_transport_seq_next, + .stop = sctp_transport_seq_stop, .show = sctp_remaddr_seq_show, }; -- GitLab From 53fa10369c45a51947f06e8b622d2fa2cc64fda1 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Apr 2016 15:35:35 +0800 Subject: [PATCH 3076/9938] sctp: fix some rhashtable functions using in sctp proc/diag When rhashtable_walk_init return err, no release function should be called, and when rhashtable_walk_start return err, we should only invoke rhashtable_walk_exit to release the source. But now when sctp_transport_walk_start return err, we just call rhashtable_walk_stop/exit, and never care about if rhashtable_walk_init or start return err, which is so bad. We will fix it by calling rhashtable_walk_exit if rhashtable_walk_start return err in sctp_transport_walk_start, and if sctp_transport_walk_start return err, we do not need to call sctp_transport_walk_stop any more. For sctp proc, we will use 'iter->start_fail' to decide if we will call rhashtable_walk_stop/exit. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/proc.c | 7 ++++++- net/sctp/socket.c | 15 ++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 9fe139368ad7..4cb5aedfe3ee 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -280,6 +280,7 @@ void sctp_eps_proc_exit(struct net *net) struct sctp_ht_iter { struct seq_net_private p; struct rhashtable_iter hti; + int start_fail; }; static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) @@ -287,8 +288,10 @@ static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos) struct sctp_ht_iter *iter = seq->private; int err = sctp_transport_walk_start(&iter->hti); - if (err) + if (err) { + iter->start_fail = 1; return ERR_PTR(err); + } return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos); } @@ -297,6 +300,8 @@ static void sctp_transport_seq_stop(struct seq_file *seq, void *v) { struct sctp_ht_iter *iter = seq->private; + if (iter->start_fail) + return; sctp_transport_walk_stop(&iter->hti); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5e5bc08d2b25..777d0324594a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4299,8 +4299,12 @@ int sctp_transport_walk_start(struct rhashtable_iter *iter) return err; err = rhashtable_walk_start(iter); + if (err && err != -EAGAIN) { + rhashtable_walk_exit(iter); + return err; + } - return err == -EAGAIN ? 0 : err; + return 0; } void sctp_transport_walk_stop(struct rhashtable_iter *iter) @@ -4389,11 +4393,12 @@ EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), struct net *net, int pos, void *p) { struct rhashtable_iter hti; - int err = 0; void *obj; + int err; - if (sctp_transport_walk_start(&hti)) - goto out; + err = sctp_transport_walk_start(&hti); + if (err) + return err; sctp_transport_get_idx(net, &hti, pos); obj = sctp_transport_get_next(net, &hti); @@ -4407,8 +4412,8 @@ int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), if (err) break; } -out: sctp_transport_walk_stop(&hti); + return err; } EXPORT_SYMBOL_GPL(sctp_for_each_transport); -- GitLab From 4f2651e1d838c4db656170bddfcabdf67a8d7f9b Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Thu, 31 Mar 2016 12:10:30 +0100 Subject: [PATCH 3077/9938] Documentation: update Michael K. Johnson's work The URL for "Writing Linux Device Drivers" hasn't been available in some time. Updating the entry to Michael K. Johnson's "Linux Kernel Hackers' Guide" Signed-off-by: Luis de Bethencourt Signed-off-by: Jonathan Corbet --- Documentation/kernel-docs.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt index 3aecbac1cb01..1dafc52167b0 100644 --- a/Documentation/kernel-docs.txt +++ b/Documentation/kernel-docs.txt @@ -194,15 +194,15 @@ simple---most of the complexity (other than talking to the hardware) involves managing network packets in memory". - * Title: "Writing Linux Device Drivers" + * Title: "Linux Kernel Hackers' Guide" Author: Michael K. Johnson. - URL: http://users.evitech.fi/~tk/rtos/writing_linux_device_d.html - Keywords: files, VFS, file operations, kernel interface, character - vs block devices, I/O access, hardware interrupts, DMA, access to - user memory, memory allocation, timers. - Description: Introductory 50-minutes (sic) tutorial on writing - device drivers. 12 pages written by the same author of the "Kernel - Hackers' Guide" which give a very good overview of the topic. + URL: http://www.tldp.org/LDP/khg/HyperNews/get/khg.html + Keywords: device drivers, files, VFS, kernel interface, character vs + block devices, hardware interrupts, scsi, DMA, access to user memory, + memory allocation, timers. + Description: A guide designed to help you get up to speed on the + concepts that are not intuitevly obvious, and to document the internal + structures of Linux. * Title: "The Venus kernel interface" Author: Peter J. Braam. -- GitLab From cfaf790f932beae903a5fc5b19039d7b3842a3b3 Mon Sep 17 00:00:00 2001 From: Diego Viola Date: Sun, 3 Apr 2016 04:34:48 -0300 Subject: [PATCH 3078/9938] README: remove trailing whitespace Signed-off-by: Diego Viola Signed-off-by: Jonathan Corbet --- README | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README b/README index afc4f0d81ee1..e8c8a6dc1c2b 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ These are the release notes for Linux version 4. Read them carefully, as they tell you what this is all about, explain how to install the -kernel, and what to do if something goes wrong. +kernel, and what to do if something goes wrong. WHAT IS LINUX? @@ -16,7 +16,7 @@ WHAT IS LINUX? and multistack networking including IPv4 and IPv6. It is distributed under the GNU General Public License - see the - accompanying COPYING file for more details. + accompanying COPYING file for more details. ON WHAT HARDWARE DOES IT RUN? @@ -44,7 +44,7 @@ DOCUMENTATION: system: there are much better sources available. - There are various README files in the Documentation/ subdirectory: - these typically contain kernel-specific installation notes for some + these typically contain kernel-specific installation notes for some drivers for example. See Documentation/00-INDEX for a list of what is contained in each file. Please read the Changes file, as it contains information about the problems, which may result by upgrading @@ -276,7 +276,7 @@ COMPILING the kernel: To have the build system also tell the reason for the rebuild of each target, use "V=2". The default is "V=0". - - Keep a backup kernel handy in case something goes wrong. This is + - Keep a backup kernel handy in case something goes wrong. This is especially true for the development releases, since each new release contains new code which has not been debugged. Make sure you keep a backup of the modules corresponding to that kernel, as well. If you @@ -290,7 +290,7 @@ COMPILING the kernel: - In order to boot your new kernel, you'll need to copy the kernel image (e.g. .../linux/arch/i386/boot/bzImage after compilation) - to the place where your regular bootable kernel is found. + to the place where your regular bootable kernel is found. - Booting a kernel directly from a floppy without the assistance of a bootloader such as LILO, is no longer supported. @@ -303,10 +303,10 @@ COMPILING the kernel: to update the loading map! If you don't, you won't be able to boot the new kernel image. - Reinstalling LILO is usually a matter of running /sbin/lilo. + Reinstalling LILO is usually a matter of running /sbin/lilo. You may wish to edit /etc/lilo.conf to specify an entry for your old kernel image (say, /vmlinux.old) in case the new one does not - work. See the LILO docs for more information. + work. See the LILO docs for more information. After reinstalling LILO, you should be all set. Shutdown the system, reboot, and enjoy! @@ -314,9 +314,9 @@ COMPILING the kernel: If you ever need to change the default root device, video mode, ramdisk size, etc. in the kernel image, use the 'rdev' program (or alternatively the LILO boot options when appropriate). No need to - recompile the kernel to change these parameters. + recompile the kernel to change these parameters. - - Reboot with the new kernel and enjoy. + - Reboot with the new kernel and enjoy. IF SOMETHING GOES WRONG: @@ -383,7 +383,7 @@ IF SOMETHING GOES WRONG: is followed by a function with a higher address you will find the one you want. In fact, it may be a good idea to include a bit of "context" in your problem report, giving a few lines around the - interesting one. + interesting one. If you for some reason cannot do the above (you have a pre-compiled kernel image or similar), telling me as much about your setup as -- GitLab From 2dd723fdbb61fbc4ee0125401f04f5431f61268d Mon Sep 17 00:00:00 2001 From: Diego Herranz Date: Tue, 12 Apr 2016 18:13:27 +0100 Subject: [PATCH 3079/9938] doc: usb: Fix typo in gadget_multi documentation It tries to "match" drivers for each interface (not "much"). Signed-off-by: Diego Herranz Signed-off-by: Jonathan Corbet --- Documentation/usb/gadget_multi.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/usb/gadget_multi.txt b/Documentation/usb/gadget_multi.txt index 7d66a8636cb5..5faf514047e9 100644 --- a/Documentation/usb/gadget_multi.txt +++ b/Documentation/usb/gadget_multi.txt @@ -43,7 +43,7 @@ For the gadget two work under Windows two conditions have to be met: First of all, Windows need to detect the gadget as an USB composite gadget which on its own have some conditions[4]. If they are met, Windows lets USB Generic Parent Driver[5] handle the device which then -tries to much drivers for each individual interface (sort of, don't +tries to match drivers for each individual interface (sort of, don't get into too many details). The good news is: you do not have to worry about most of the -- GitLab From 63f8e8d2a575ef62e5b705516b491a98a60517ff Mon Sep 17 00:00:00 2001 From: Doug Hoyte Date: Wed, 13 Apr 2016 11:09:21 -0400 Subject: [PATCH 3080/9938] Documentation typo: wrong page flag bit for KPF_HUGE The correct value 17 can be found later in this document and in the kernel-page-flags.h header (KPF_HUGE). I noticed this while implementing vmprobe's kpageflags support. Signed-off-by: Jonathan Corbet --- Documentation/vm/pagemap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/vm/pagemap.txt b/Documentation/vm/pagemap.txt index 0e1e55588b59..eafcefa15261 100644 --- a/Documentation/vm/pagemap.txt +++ b/Documentation/vm/pagemap.txt @@ -62,7 +62,7 @@ There are four components to pagemap: 14. SWAPBACKED 15. COMPOUND_HEAD 16. COMPOUND_TAIL - 16. HUGE + 17. HUGE 18. UNEVICTABLE 19. HWPOISON 20. NOPAGE -- GitLab From d124fd3bb36ceb40438f10c897ce642386b74b72 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 14 Apr 2016 11:08:08 +0200 Subject: [PATCH 3081/9938] serial: doc: Re-add paragraph documenting uart_console_write() Commit 834392a7d92677ff ("serial: doc: Un-document non-existing uart_write_console()") removed a paragraph about a helper function that seemed to never exist. Peter Hurley pointed out that the function does exist, but is called differently. Re-add the paragraph, with the function name corrected. Fixes: 834392a7d92677ff ("serial: doc: Un-document non-existing uart_write_console()") Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 65de49a4b39e..03369d076ca2 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -28,6 +28,11 @@ The serial core provides a few helper functions. This includes identifing the correct port structure (via uart_get_console) and decoding command line arguments (uart_parse_options). +There is also a helper function (uart_console_write) which performs a +character by character write, translating newlines to CRLF sequences. +Driver writers are recommended to use this function rather than implementing +their own version. + Locking ------- -- GitLab From a3bedc3bdc6e640141157636e253d63279860e23 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 14 Apr 2016 11:08:09 +0200 Subject: [PATCH 3082/9938] serial: doc: .(un)throttle() depends on hardware assisted flow control Document that .throttle() and .unthrottle() are relevant only if hardware assisted flow control is enabled. Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 03369d076ca2..03b703cf9318 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -135,6 +135,7 @@ hardware. Notify the serial driver that input buffers for the line discipline are close to full, and it should somehow signal that no more characters should be sent to the serial port. + This will be called only if hardware assisted flow control is enabled. Locking: none. @@ -142,6 +143,7 @@ hardware. Notify the serial driver that characters can now be sent to the serial port without fear of overrunning the input buffers of the line disciplines. + This will be called only if hardware assisted flow control is enabled. Locking: none. -- GitLab From 18717b06ee4897c2cc5e92783386c4b304b9fce9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 14 Apr 2016 11:08:10 +0200 Subject: [PATCH 3083/9938] serial: doc: .(un)throttle() are serialized by the tty layer Document that .(un)throttle() are serialized with each other, and with termios modification by the tty layer. Reported-by: Peter Hurley Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 03b703cf9318..7fb80682e394 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -137,7 +137,8 @@ hardware. should be sent to the serial port. This will be called only if hardware assisted flow control is enabled. - Locking: none. + Locking: serialized with .unthrottle() and termios modification by the + tty layer. unthrottle(port) Notify the serial driver that characters can now be sent to the serial @@ -145,7 +146,8 @@ hardware. disciplines. This will be called only if hardware assisted flow control is enabled. - Locking: none. + Locking: serialized with .throttle() and termios modification by the + tty layer. send_xchar(port,ch) Transmit a high priority character, even if the port is stopped. -- GitLab From 9e52cec04fd3b9b686f9256151b47fe61f7c28ef Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 12 Apr 2016 16:43:39 +0800 Subject: [PATCH 3084/9938] clk: Add clk_composite_set_rate_and_parent When changing the clock-rate, currently a new parent is set first and a divider adapted thereafter. This may result in the clock-rate overflowing its target rate for a short time if the new parent has a higher rate than the old parent. While this often doesn't produce negative effects, it can affect components in a voltage-scaling environment, like the GPU on the rk3399 socs, where the voltage than simply is to low for the temporarily to high clock rate. For general clock hirarchies this may need more extensive adaptions to the common clock-framework, but at least for composite clocks having both parent and rate settings it is easy to create a short-term solution to make sure the clock-rate does not overflow the target. Signed-off-by: Finley Xiao Reviewed-by: Heiko Stuebner Signed-off-by: Stephen Boyd --- drivers/clk/clk-composite.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 1f903e1f86a2..4d4b5aba397d 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -151,6 +151,33 @@ static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate, return rate_ops->set_rate(rate_hw, rate, parent_rate); } +static int clk_composite_set_rate_and_parent(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, + u8 index) +{ + struct clk_composite *composite = to_clk_composite(hw); + const struct clk_ops *rate_ops = composite->rate_ops; + const struct clk_ops *mux_ops = composite->mux_ops; + struct clk_hw *rate_hw = composite->rate_hw; + struct clk_hw *mux_hw = composite->mux_hw; + unsigned long temp_rate; + + __clk_hw_set_clk(rate_hw, hw); + __clk_hw_set_clk(mux_hw, hw); + + temp_rate = rate_ops->recalc_rate(rate_hw, parent_rate); + if (temp_rate > rate) { + rate_ops->set_rate(rate_hw, rate, parent_rate); + mux_ops->set_parent(mux_hw, index); + } else { + mux_ops->set_parent(mux_hw, index); + rate_ops->set_rate(rate_hw, rate, parent_rate); + } + + return 0; +} + static int clk_composite_is_enabled(struct clk_hw *hw) { struct clk_composite *composite = to_clk_composite(hw); @@ -250,6 +277,12 @@ struct clk *clk_register_composite(struct device *dev, const char *name, composite->rate_ops = rate_ops; } + if (mux_hw && mux_ops && rate_hw && rate_ops) { + if (mux_ops->set_parent && rate_ops->set_rate) + clk_composite_ops->set_rate_and_parent = + clk_composite_set_rate_and_parent; + } + if (gate_hw && gate_ops) { if (!gate_ops->is_enabled || !gate_ops->enable || !gate_ops->disable) { -- GitLab From c02b73c943d723511abecde7909d0818638d1bc2 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Tue, 5 Apr 2016 13:28:57 -0500 Subject: [PATCH 3085/9938] clk: ti: dflt: remove redundant unlikely Commit 7aba4f5201d1 ("clk: ti: dflt: fix enable_reg validity check") fixed a validation check by using an IS_ERR() macro within the existing unlikely expression, but IS_ERR() macro already has an unlikely inside it, so get rid of the redundant unlikely macro from the validation check. Reported-by: Stephen Boyd Signed-off-by: Suman Anna Signed-off-by: Stephen Boyd --- drivers/clk/ti/clkt_dflt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/ti/clkt_dflt.c b/drivers/clk/ti/clkt_dflt.c index 1ddc288fce4e..c6ae563801d7 100644 --- a/drivers/clk/ti/clkt_dflt.c +++ b/drivers/clk/ti/clkt_dflt.c @@ -222,7 +222,7 @@ int omap2_dflt_clk_enable(struct clk_hw *hw) } } - if (unlikely(IS_ERR(clk->enable_reg))) { + if (IS_ERR(clk->enable_reg)) { pr_err("%s: %s missing enable_reg\n", __func__, clk_hw_get_name(hw)); ret = -EINVAL; -- GitLab From 67bad3e5ce82b9eea2428118d909b2c8b80a71cf Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Mon, 4 Apr 2016 11:23:22 +0200 Subject: [PATCH 3086/9938] clk: add device tree binding for Artpec-6 clock controller Add device tree documentation for the main clock controller in the Artpec-6 SoC. Acked-by: Rob Herring Signed-off-by: Lars Persson [sboyd@codeaurora.org: Added unit address to binding example] Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/artpec6.txt | 41 +++++++++++++++++++ .../dt-bindings/clock/axis,artpec6-clkctrl.h | 38 +++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/artpec6.txt create mode 100644 include/dt-bindings/clock/axis,artpec6-clkctrl.h diff --git a/Documentation/devicetree/bindings/clock/artpec6.txt b/Documentation/devicetree/bindings/clock/artpec6.txt new file mode 100644 index 000000000000..dff9cdf0009c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/artpec6.txt @@ -0,0 +1,41 @@ +* Clock bindings for Axis ARTPEC-6 chip + +The bindings are based on the clock provider binding in +Documentation/devicetree/bindings/clock/clock-bindings.txt + +External clocks: +---------------- + +There are two external inputs to the main clock controller which should be +provided using the common clock bindings. +- "sys_refclk": External 50 Mhz oscillator (required) +- "i2s_refclk": Alternate audio reference clock (optional). + +Main clock controller +--------------------- + +Required properties: +- #clock-cells: Should be <1> + See dt-bindings/clock/axis,artpec6-clkctrl.h for the list of valid identifiers. +- compatible: Should be "axis,artpec6-clkctrl" +- reg: Must contain the base address and length of the system controller +- clocks: Must contain a phandle entry for each clock in clock-names +- clock-names: Must include the external oscillator ("sys_refclk"). Optional + ones are the audio reference clock ("i2s_refclk") and the audio fractional + dividers ("frac_clk0" and "frac_clk1"). + +Examples: + +ext_clk: ext_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; +}; + +clkctrl: clkctrl@f8000000 { + #clock-cells = <1>; + compatible = "axis,artpec6-clkctrl"; + reg = <0xf8000000 0x48>; + clocks = <&ext_clk>; + clock-names = "sys_refclk"; +}; diff --git a/include/dt-bindings/clock/axis,artpec6-clkctrl.h b/include/dt-bindings/clock/axis,artpec6-clkctrl.h new file mode 100644 index 000000000000..f9f04dccc996 --- /dev/null +++ b/include/dt-bindings/clock/axis,artpec6-clkctrl.h @@ -0,0 +1,38 @@ +/* + * ARTPEC-6 clock controller indexes + * + * Copyright 2016 Axis Comunications AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef DT_BINDINGS_CLK_ARTPEC6_CLKCTRL_H +#define DT_BINDINGS_CLK_ARTPEC6_CLKCTRL_H + +#define ARTPEC6_CLK_CPU 0 +#define ARTPEC6_CLK_CPU_PERIPH 1 +#define ARTPEC6_CLK_NAND_CLKA 2 +#define ARTPEC6_CLK_NAND_CLKB 3 +#define ARTPEC6_CLK_ETH_ACLK 4 +#define ARTPEC6_CLK_DMA_ACLK 5 +#define ARTPEC6_CLK_PTP_REF 6 +#define ARTPEC6_CLK_SD_PCLK 7 +#define ARTPEC6_CLK_SD_IMCLK 8 +#define ARTPEC6_CLK_I2S_HST 9 +#define ARTPEC6_CLK_I2S0_CLK 10 +#define ARTPEC6_CLK_I2S1_CLK 11 +#define ARTPEC6_CLK_UART_PCLK 12 +#define ARTPEC6_CLK_UART_REFCLK 13 +#define ARTPEC6_CLK_I2C 14 +#define ARTPEC6_CLK_SPI_PCLK 15 +#define ARTPEC6_CLK_SPI_SSPCLK 16 +#define ARTPEC6_CLK_SYS_TIMER 17 +#define ARTPEC6_CLK_FRACDIV_IN 18 +#define ARTPEC6_CLK_DBG_PCLK 19 + +/* This must be the highest clock index plus one. */ +#define ARTPEC6_CLK_NUMCLOCKS 20 + +#endif -- GitLab From 33b8ac917a8f7a22fa3d779f875646201d0097a0 Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Mon, 4 Apr 2016 11:23:23 +0200 Subject: [PATCH 3087/9938] clk: add artpec-6 clock controller Add a driver for the main clock controller of the Artpec-6 Soc. Signed-off-by: Lars Persson [sboyd@codeaurora.org: Reformatted driver structure and of match] Signed-off-by: Stephen Boyd --- MAINTAINERS | 2 +- drivers/clk/Makefile | 1 + drivers/clk/axis/Makefile | 1 + drivers/clk/axis/clk-artpec6.c | 242 +++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/axis/Makefile create mode 100644 drivers/clk/axis/clk-artpec6.c diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..05aeee0aab4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -973,7 +973,7 @@ S: Maintained L: linux-arm-kernel@axis.com F: arch/arm/mach-artpec F: arch/arm/boot/dts/artpec6* -F: drivers/clk/clk-artpec6.c +F: drivers/clk/axis ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT M: Nicolas Ferre diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 46869d696e4d..ca9aa7b1144c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o obj-$(CONFIG_COMMON_CLK_AT91) += at91/ +obj-$(CONFIG_ARCH_ARTPEC) += axis/ obj-y += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ diff --git a/drivers/clk/axis/Makefile b/drivers/clk/axis/Makefile new file mode 100644 index 000000000000..628c9d3b9a02 --- /dev/null +++ b/drivers/clk/axis/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MACH_ARTPEC6) += clk-artpec6.o diff --git a/drivers/clk/axis/clk-artpec6.c b/drivers/clk/axis/clk-artpec6.c new file mode 100644 index 000000000000..ffc988b098e4 --- /dev/null +++ b/drivers/clk/axis/clk-artpec6.c @@ -0,0 +1,242 @@ +/* + * ARTPEC-6 clock initialization + * + * Copyright 2015-2016 Axis Comunications AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_I2S_CLOCKS 2 + +struct artpec6_clkctrl_drvdata { + struct clk *clk_table[ARTPEC6_CLK_NUMCLOCKS]; + void __iomem *syscon_base; + struct clk_onecell_data clk_data; + spinlock_t i2scfg_lock; +}; + +static struct artpec6_clkctrl_drvdata *clkdata; + +static const char *const i2s_clk_names[NUM_I2S_CLOCKS] = { + "i2s0", + "i2s1", +}; + +static const int i2s_clk_indexes[NUM_I2S_CLOCKS] = { + ARTPEC6_CLK_I2S0_CLK, + ARTPEC6_CLK_I2S1_CLK, +}; + +static void of_artpec6_clkctrl_setup(struct device_node *np) +{ + int i; + const char *sys_refclk_name; + u32 pll_mode, pll_m, pll_n; + struct clk **clks; + + /* Mandatory parent clock. */ + i = of_property_match_string(np, "clock-names", "sys_refclk"); + if (i < 0) + return; + + sys_refclk_name = of_clk_get_parent_name(np, i); + + clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL); + if (!clkdata) + return; + + clks = clkdata->clk_table; + + for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) + clks[i] = ERR_PTR(-EPROBE_DEFER); + + clkdata->syscon_base = of_iomap(np, 0); + BUG_ON(clkdata->syscon_base == NULL); + + /* Read PLL1 factors configured by boot strap pins. */ + pll_mode = (readl(clkdata->syscon_base) >> 6) & 3; + switch (pll_mode) { + case 0: /* DDR3-2133 mode */ + pll_m = 4; + pll_n = 85; + break; + case 1: /* DDR3-1866 mode */ + pll_m = 6; + pll_n = 112; + break; + case 2: /* DDR3-1600 mode */ + pll_m = 4; + pll_n = 64; + break; + case 3: /* DDR3-1333 mode */ + pll_m = 8; + pll_n = 106; + break; + } + + clks[ARTPEC6_CLK_CPU] = + clk_register_fixed_factor(NULL, "cpu", sys_refclk_name, 0, pll_n, + pll_m); + clks[ARTPEC6_CLK_CPU_PERIPH] = + clk_register_fixed_factor(NULL, "cpu_periph", "cpu", 0, 1, 2); + + /* EPROBE_DEFER on the apb_clock is not handled in amba devices. */ + clks[ARTPEC6_CLK_UART_PCLK] = + clk_register_fixed_factor(NULL, "uart_pclk", "cpu", 0, 1, 8); + clks[ARTPEC6_CLK_UART_REFCLK] = + clk_register_fixed_rate(NULL, "uart_ref", sys_refclk_name, 0, + 50000000); + + clks[ARTPEC6_CLK_SPI_PCLK] = + clk_register_fixed_factor(NULL, "spi_pclk", "cpu", 0, 1, 8); + clks[ARTPEC6_CLK_SPI_SSPCLK] = + clk_register_fixed_rate(NULL, "spi_sspclk", sys_refclk_name, 0, + 50000000); + + clks[ARTPEC6_CLK_DBG_PCLK] = + clk_register_fixed_factor(NULL, "dbg_pclk", "cpu", 0, 1, 8); + + clkdata->clk_data.clks = clkdata->clk_table; + clkdata->clk_data.clk_num = ARTPEC6_CLK_NUMCLOCKS; + + of_clk_add_provider(np, of_clk_src_onecell_get, &clkdata->clk_data); +} + +CLK_OF_DECLARE(artpec6_clkctrl, "axis,artpec6-clkctrl", + of_artpec6_clkctrl_setup); + +static int artpec6_clkctrl_probe(struct platform_device *pdev) +{ + int propidx; + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct clk **clks = clkdata->clk_table; + const char *sys_refclk_name; + const char *i2s_refclk_name = NULL; + const char *frac_clk_name[2] = { NULL, NULL }; + const char *i2s_mux_parents[2]; + u32 muxreg; + int i; + int err = 0; + + /* Mandatory parent clock. */ + propidx = of_property_match_string(np, "clock-names", "sys_refclk"); + if (propidx < 0) + return -EINVAL; + + sys_refclk_name = of_clk_get_parent_name(np, propidx); + + /* Find clock names of optional parent clocks. */ + propidx = of_property_match_string(np, "clock-names", "i2s_refclk"); + if (propidx >= 0) + i2s_refclk_name = of_clk_get_parent_name(np, propidx); + + propidx = of_property_match_string(np, "clock-names", "frac_clk0"); + if (propidx >= 0) + frac_clk_name[0] = of_clk_get_parent_name(np, propidx); + propidx = of_property_match_string(np, "clock-names", "frac_clk1"); + if (propidx >= 0) + frac_clk_name[1] = of_clk_get_parent_name(np, propidx); + + spin_lock_init(&clkdata->i2scfg_lock); + + clks[ARTPEC6_CLK_NAND_CLKA] = + clk_register_fixed_factor(dev, "nand_clka", "cpu", 0, 1, 8); + clks[ARTPEC6_CLK_NAND_CLKB] = + clk_register_fixed_rate(dev, "nand_clkb", sys_refclk_name, 0, + 100000000); + clks[ARTPEC6_CLK_ETH_ACLK] = + clk_register_fixed_factor(dev, "eth_aclk", "cpu", 0, 1, 4); + clks[ARTPEC6_CLK_DMA_ACLK] = + clk_register_fixed_factor(dev, "dma_aclk", "cpu", 0, 1, 4); + clks[ARTPEC6_CLK_PTP_REF] = + clk_register_fixed_rate(dev, "ptp_ref", sys_refclk_name, 0, + 100000000); + clks[ARTPEC6_CLK_SD_PCLK] = + clk_register_fixed_rate(dev, "sd_pclk", sys_refclk_name, 0, + 100000000); + clks[ARTPEC6_CLK_SD_IMCLK] = + clk_register_fixed_rate(dev, "sd_imclk", sys_refclk_name, 0, + 100000000); + clks[ARTPEC6_CLK_I2S_HST] = + clk_register_fixed_factor(dev, "i2s_hst", "cpu", 0, 1, 8); + + for (i = 0; i < NUM_I2S_CLOCKS; ++i) { + if (i2s_refclk_name && frac_clk_name[i]) { + i2s_mux_parents[0] = frac_clk_name[i]; + i2s_mux_parents[1] = i2s_refclk_name; + + clks[i2s_clk_indexes[i]] = + clk_register_mux(dev, i2s_clk_names[i], + i2s_mux_parents, 2, + CLK_SET_RATE_NO_REPARENT | + CLK_SET_RATE_PARENT, + clkdata->syscon_base + 0x14, i, 1, + 0, &clkdata->i2scfg_lock); + } else if (frac_clk_name[i]) { + /* Lock the mux for internal clock reference. */ + muxreg = readl(clkdata->syscon_base + 0x14); + muxreg &= ~BIT(i); + writel(muxreg, clkdata->syscon_base + 0x14); + clks[i2s_clk_indexes[i]] = + clk_register_fixed_factor(dev, i2s_clk_names[i], + frac_clk_name[i], 0, 1, + 1); + } else if (i2s_refclk_name) { + /* Lock the mux for external clock reference. */ + muxreg = readl(clkdata->syscon_base + 0x14); + muxreg |= BIT(i); + writel(muxreg, clkdata->syscon_base + 0x14); + clks[i2s_clk_indexes[i]] = + clk_register_fixed_factor(dev, i2s_clk_names[i], + i2s_refclk_name, 0, 1, 1); + } + } + + clks[ARTPEC6_CLK_I2C] = + clk_register_fixed_rate(dev, "i2c", sys_refclk_name, 0, 100000000); + + clks[ARTPEC6_CLK_SYS_TIMER] = + clk_register_fixed_rate(dev, "timer", sys_refclk_name, 0, + 100000000); + clks[ARTPEC6_CLK_FRACDIV_IN] = + clk_register_fixed_rate(dev, "fracdiv_in", sys_refclk_name, 0, + 600000000); + + for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) { + if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER) { + dev_err(dev, + "Failed to register clock at index %d err=%ld\n", + i, PTR_ERR(clks[i])); + err = PTR_ERR(clks[i]); + } + } + + return err; +} + +static const struct of_device_id artpec_clkctrl_of_match[] = { + { .compatible = "axis,artpec6-clkctrl" }, + {} +}; + +static struct platform_driver artpec6_clkctrl_driver = { + .probe = artpec6_clkctrl_probe, + .driver = { + .name = "artpec6_clkctrl", + .of_match_table = artpec_clkctrl_of_match, + }, +}; + +builtin_platform_driver(artpec6_clkctrl_driver); -- GitLab From f2d32b623c774ee63151a308a6bd79b4e543a4ee Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 10:59:51 -0800 Subject: [PATCH 3088/9938] clk: meson: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Carlo Caione Signed-off-by: Stephen Boyd --- drivers/clk/meson/meson8b-clkc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 61f6d55c4ac7..4d057b3e21b2 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -141,11 +141,11 @@ static const struct composite_conf mali_conf __initconst = { }; static const struct clk_conf meson8b_xtal_conf __initconst = - FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal", - CLK_IS_ROOT, PARM(0x00, 4, 7)); + FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal", 0, + PARM(0x00, 4, 7)); static const struct clk_conf meson8b_clk_confs[] __initconst = { - FIXED_RATE(CLKID_ZERO, "zero", CLK_IS_ROOT, 0), + FIXED_RATE(CLKID_ZERO, "zero", 0, 0), PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll", p_xtal, 0, &pll_confs), PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll", -- GitLab From 536630ddbffb97e5a9de76a2d793ec118413e758 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 10:59:52 -0800 Subject: [PATCH 3089/9938] clk: mmp: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Chao Xie Signed-off-by: Stephen Boyd --- drivers/clk/mmp/clk-mmp2.c | 14 +++++--------- drivers/clk/mmp/clk-of-mmp2.c | 10 +++++----- drivers/clk/mmp/clk-of-pxa168.c | 8 ++++---- drivers/clk/mmp/clk-of-pxa1928.c | 12 ++++++------ drivers/clk/mmp/clk-of-pxa910.c | 8 ++++---- drivers/clk/mmp/clk-pxa168.c | 8 +++----- drivers/clk/mmp/clk-pxa910.c | 8 +++----- 7 files changed, 30 insertions(+), 38 deletions(-) diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c index 38931dbd1eff..383f6a4f64f0 100644 --- a/drivers/clk/mmp/clk-mmp2.c +++ b/drivers/clk/mmp/clk-mmp2.c @@ -99,23 +99,19 @@ void __init mmp2_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, return; } - clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); + clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200); clk_register_clkdev(clk, "clk32", NULL); - vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, - 26000000); + vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000); clk_register_clkdev(vctcxo, "vctcxo", NULL); - clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, - 800000000); + clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 800000000); clk_register_clkdev(clk, "pll1", NULL); - clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, CLK_IS_ROOT, - 480000000); + clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, 0, 480000000); clk_register_clkdev(clk, "usb_pll", NULL); - clk = clk_register_fixed_rate(NULL, "pll2", NULL, CLK_IS_ROOT, - 960000000); + clk = clk_register_fixed_rate(NULL, "pll2", NULL, 0, 960000000); clk_register_clkdev(clk, "pll2", NULL); clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c index 251533d87c65..3a51fff1b0e7 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c @@ -63,11 +63,11 @@ struct mmp2_clk_unit { }; static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { - {MMP2_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, - {MMP2_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, - {MMP2_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 800000000}, - {MMP2_CLK_PLL2, "pll2", NULL, CLK_IS_ROOT, 960000000}, - {MMP2_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, + {MMP2_CLK_CLK32, "clk32", NULL, 0, 32768}, + {MMP2_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000}, + {MMP2_CLK_PLL1, "pll1", NULL, 0, 800000000}, + {MMP2_CLK_PLL2, "pll2", NULL, 0, 960000000}, + {MMP2_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000}, }; static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c index 64eaf4141c69..87f2317b2a00 100644 --- a/drivers/clk/mmp/clk-of-pxa168.c +++ b/drivers/clk/mmp/clk-of-pxa168.c @@ -56,10 +56,10 @@ struct pxa168_clk_unit { }; static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { - {PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, - {PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, - {PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, - {PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, + {PXA168_CLK_CLK32, "clk32", NULL, 0, 32768}, + {PXA168_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000}, + {PXA168_CLK_PLL1, "pll1", NULL, 0, 624000000}, + {PXA168_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000}, }; static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c index 433a5ae1eae0..e478ff44e170 100644 --- a/drivers/clk/mmp/clk-of-pxa1928.c +++ b/drivers/clk/mmp/clk-of-pxa1928.c @@ -34,12 +34,12 @@ struct pxa1928_clk_unit { }; static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { - {0, "clk32", NULL, CLK_IS_ROOT, 32768}, - {0, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, - {0, "pll1_624", NULL, CLK_IS_ROOT, 624000000}, - {0, "pll5p", NULL, CLK_IS_ROOT, 832000000}, - {0, "pll5", NULL, CLK_IS_ROOT, 1248000000}, - {0, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, + {0, "clk32", NULL, 0, 32768}, + {0, "vctcxo", NULL, 0, 26000000}, + {0, "pll1_624", NULL, 0, 624000000}, + {0, "pll5p", NULL, 0, 832000000}, + {0, "pll5", NULL, 0, 1248000000}, + {0, "usb_pll", NULL, 0, 480000000}, }; static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c index 13d6173326a4..e22a67f76d93 100644 --- a/drivers/clk/mmp/clk-of-pxa910.c +++ b/drivers/clk/mmp/clk-of-pxa910.c @@ -56,10 +56,10 @@ struct pxa910_clk_unit { }; static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { - {PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, - {PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, - {PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, - {PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, + {PXA910_CLK_CLK32, "clk32", NULL, 0, 32768}, + {PXA910_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000}, + {PXA910_CLK_PLL1, "pll1", NULL, 0, 624000000}, + {PXA910_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000}, }; static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c index 0dd83fb950c9..a9ef9209532a 100644 --- a/drivers/clk/mmp/clk-pxa168.c +++ b/drivers/clk/mmp/clk-pxa168.c @@ -92,15 +92,13 @@ void __init pxa168_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, return; } - clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); + clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200); clk_register_clkdev(clk, "clk32", NULL); - clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, - 26000000); + clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000); clk_register_clkdev(clk, "vctcxo", NULL); - clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, - 624000000); + clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 624000000); clk_register_clkdev(clk, "pll1", NULL); clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c index e1d2ce22cdf1..a520cf7702a1 100644 --- a/drivers/clk/mmp/clk-pxa910.c +++ b/drivers/clk/mmp/clk-pxa910.c @@ -97,15 +97,13 @@ void __init pxa910_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, return; } - clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); + clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200); clk_register_clkdev(clk, "clk32", NULL); - clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, - 26000000); + clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000); clk_register_clkdev(clk, "vctcxo", NULL); - clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, - 624000000); + clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 624000000); clk_register_clkdev(clk, "pll1", NULL); clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", -- GitLab From 23ced2711bcdd26163f1188f693d6379ab0c6bf3 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 10:59:59 -0800 Subject: [PATCH 3090/9938] clk: sirf: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Guo Zeng Cc: Barry Song Signed-off-by: Stephen Boyd --- drivers/clk/sirf/clk-atlas6.c | 7 +++---- drivers/clk/sirf/clk-prima2.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/clk/sirf/clk-atlas6.c b/drivers/clk/sirf/clk-atlas6.c index c5eaa9d16247..665fa681b2e1 100644 --- a/drivers/clk/sirf/clk-atlas6.c +++ b/drivers/clk/sirf/clk-atlas6.c @@ -130,10 +130,9 @@ static void __init atlas6_clk_init(struct device_node *np) panic("unable to map clkc registers\n"); /* These are always available (RTC and 26MHz OSC)*/ - atlas6_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, - CLK_IS_ROOT, 32768); - atlas6_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, - CLK_IS_ROOT, 26000000); + atlas6_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768); + atlas6_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0, + 26000000); for (i = pll1; i < maxclk; i++) { atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]); diff --git a/drivers/clk/sirf/clk-prima2.c b/drivers/clk/sirf/clk-prima2.c index f92c40264342..aac1c8ec151a 100644 --- a/drivers/clk/sirf/clk-prima2.c +++ b/drivers/clk/sirf/clk-prima2.c @@ -129,10 +129,9 @@ static void __init prima2_clk_init(struct device_node *np) panic("unable to map clkc registers\n"); /* These are always available (RTC and 26MHz OSC)*/ - prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, - CLK_IS_ROOT, 32768); - prima2_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, - CLK_IS_ROOT, 26000000); + prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768); + prima2_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0, + 26000000); for (i = pll1; i < maxclk; i++) { prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); -- GitLab From 260c37f92a420958c25ab404e7f03a1cd3b04843 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:01 -0800 Subject: [PATCH 3091/9938] clk: sunxi: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Maxime Ripard Cc: Chen-Yu Tsai Signed-off-by: Stephen Boyd --- drivers/clk/sunxi/clk-a10-hosc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/sunxi/clk-a10-hosc.c b/drivers/clk/sunxi/clk-a10-hosc.c index 6b598c6a0213..dca532431394 100644 --- a/drivers/clk/sunxi/clk-a10-hosc.c +++ b/drivers/clk/sunxi/clk-a10-hosc.c @@ -54,8 +54,7 @@ static void __init sun4i_osc_clk_setup(struct device_node *node) NULL, 0, NULL, NULL, &fixed->hw, &clk_fixed_rate_ops, - &gate->hw, &clk_gate_ops, - CLK_IS_ROOT); + &gate->hw, &clk_gate_ops, 0); if (IS_ERR(clk)) goto err_free_gate; -- GitLab From c9bb8a4f3db60342ad97f7eb77965a6ae30851bb Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:08 -0800 Subject: [PATCH 3092/9938] clk: zte: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Jun Nie Signed-off-by: Stephen Boyd --- drivers/clk/zte/clk-zx296702.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/zte/clk-zx296702.c b/drivers/clk/zte/clk-zx296702.c index ebd20d852e73..76e967c19775 100644 --- a/drivers/clk/zte/clk-zx296702.c +++ b/drivers/clk/zte/clk-zx296702.c @@ -234,8 +234,7 @@ static void __init zx296702_top_clocks_init(struct device_node *np) WARN_ON(!topcrm_base); clk[ZX296702_OSC] = - clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT, - 30000000); + clk_register_fixed_rate(NULL, "osc", NULL, 0, 30000000); clk[ZX296702_PLL_A9] = clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base + 0x01c, pll_a9_config, -- GitLab From 26659ada14cece0d0705f4e020dab634db2f95cc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:10 -0800 Subject: [PATCH 3093/9938] clk: clps711x: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Alexander Shiyan Signed-off-by: Stephen Boyd --- drivers/clk/clk-clps711x.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/clk/clk-clps711x.c b/drivers/clk/clk-clps711x.c index ff4ef4f1df62..1f60b02416a7 100644 --- a/drivers/clk/clk-clps711x.c +++ b/drivers/clk/clk-clps711x.c @@ -107,16 +107,15 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base, writel(tmp, base + CLPS711X_SYSCON1); clps711x_clk->clks[CLPS711X_CLK_DUMMY] = - clk_register_fixed_rate(NULL, "dummy", NULL, CLK_IS_ROOT, 0); + clk_register_fixed_rate(NULL, "dummy", NULL, 0, 0); clps711x_clk->clks[CLPS711X_CLK_CPU] = - clk_register_fixed_rate(NULL, "cpu", NULL, CLK_IS_ROOT, f_cpu); + clk_register_fixed_rate(NULL, "cpu", NULL, 0, f_cpu); clps711x_clk->clks[CLPS711X_CLK_BUS] = - clk_register_fixed_rate(NULL, "bus", NULL, CLK_IS_ROOT, f_bus); + clk_register_fixed_rate(NULL, "bus", NULL, 0, f_bus); clps711x_clk->clks[CLPS711X_CLK_PLL] = - clk_register_fixed_rate(NULL, "pll", NULL, CLK_IS_ROOT, f_pll); + clk_register_fixed_rate(NULL, "pll", NULL, 0, f_pll); clps711x_clk->clks[CLPS711X_CLK_TIMERREF] = - clk_register_fixed_rate(NULL, "timer_ref", NULL, CLK_IS_ROOT, - f_tim); + clk_register_fixed_rate(NULL, "timer_ref", NULL, 0, f_tim); clps711x_clk->clks[CLPS711X_CLK_TIMER1] = clk_register_divider_table(NULL, "timer1", "timer_ref", 0, base + CLPS711X_SYSCON1, 5, 1, 0, @@ -126,10 +125,9 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base, base + CLPS711X_SYSCON1, 7, 1, 0, timer_div_table, &clps711x_clk->lock); clps711x_clk->clks[CLPS711X_CLK_PWM] = - clk_register_fixed_rate(NULL, "pwm", NULL, CLK_IS_ROOT, f_pwm); + clk_register_fixed_rate(NULL, "pwm", NULL, 0, f_pwm); clps711x_clk->clks[CLPS711X_CLK_SPIREF] = - clk_register_fixed_rate(NULL, "spi_ref", NULL, CLK_IS_ROOT, - f_spi); + clk_register_fixed_rate(NULL, "spi_ref", NULL, 0, f_spi); clps711x_clk->clks[CLPS711X_CLK_SPI] = clk_register_divider_table(NULL, "spi", "spi_ref", 0, base + CLPS711X_SYSCON1, 16, 2, 0, @@ -137,8 +135,7 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base, clps711x_clk->clks[CLPS711X_CLK_UART] = clk_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10); clps711x_clk->clks[CLPS711X_CLK_TICK] = - clk_register_fixed_rate(NULL, "tick", NULL, CLK_IS_ROOT, 64); - + clk_register_fixed_rate(NULL, "tick", NULL, 0, 64); for (i = 0; i < CLPS711X_CLK_MAX; i++) if (IS_ERR(clps711x_clk->clks[i])) pr_err("clk %i: register failed with %ld\n", -- GitLab From 3be32b79a1c3b99d5f0d266eaa2e727a672f62db Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:13 -0800 Subject: [PATCH 3094/9938] clk: ls1x: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Kelvin Cheung Signed-off-by: Stephen Boyd --- drivers/clk/clk-ls1x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c index d4c61985f448..5097831387ff 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/clk-ls1x.c @@ -88,8 +88,7 @@ void __init ls1x_clk_init(void) { struct clk *clk; - clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT, - OSC); + clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); clk_register_clkdev(clk, "osc_33m_clk", NULL); /* clock derived from 33 MHz OSC clk */ -- GitLab From 1efee90d275fe7b22ae0320adb6c9bb49937a9d8 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:16 -0800 Subject: [PATCH 3095/9938] clk: nspire: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Daniel Tang Signed-off-by: Stephen Boyd --- drivers/clk/clk-nspire.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/clk-nspire.c b/drivers/clk/clk-nspire.c index a378db7b2382..64f196a90816 100644 --- a/drivers/clk/clk-nspire.c +++ b/drivers/clk/clk-nspire.c @@ -125,8 +125,7 @@ static void __init nspire_clk_setup(struct device_node *node, of_property_read_string(node, "clock-output-names", &clk_name); - clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, - info.base_clock); + clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, info.base_clock); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); else -- GitLab From 1fb4742a268726293f022097f85f13fa3856ea49 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:17 -0800 Subject: [PATCH 3096/9938] clk: palmas: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Peter Ujfalusi Cc: Nishanth Menon Signed-off-by: Stephen Boyd --- drivers/clk/clk-palmas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c index 9c0b8e6b1ab3..8328863cb0e0 100644 --- a/drivers/clk/clk-palmas.c +++ b/drivers/clk/clk-palmas.c @@ -132,7 +132,7 @@ static const struct palmas_clks_of_match_data palmas_of_clk32kg = { .init = { .name = "clk32kg", .ops = &palmas_clks_ops, - .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, + .flags = CLK_IGNORE_UNUSED, }, .desc = { .clk_name = "clk32kg", @@ -148,7 +148,7 @@ static const struct palmas_clks_of_match_data palmas_of_clk32kgaudio = { .init = { .name = "clk32kgaudio", .ops = &palmas_clks_ops, - .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, + .flags = CLK_IGNORE_UNUSED, }, .desc = { .clk_name = "clk32kgaudio", -- GitLab From ec3f2fcb32060f3f31ffc778879553367e71ceaf Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:19 -0800 Subject: [PATCH 3097/9938] clk: qoriq: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Hou Zhiqiang Cc: Scott Wood Signed-off-by: Stephen Boyd --- drivers/clk/clk-qoriq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 7bc1c4527ae4..d247b75ddf6a 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -876,7 +876,7 @@ static struct clk *sysclk_from_fixed(struct device_node *node, const char *name) if (of_property_read_u32(node, "clock-frequency", &rate)) return ERR_PTR(-ENODEV); - return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); + return clk_register_fixed_rate(NULL, name, NULL, 0, rate); } static struct clk *sysclk_from_parent(const char *name) -- GitLab From 7ecf47c2c292e25947c2aa95293c52145997f67f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:20 -0800 Subject: [PATCH 3098/9938] clk: rk808: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Chris Zhong Signed-off-by: Stephen Boyd --- drivers/clk/clk-rk808.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c index 0fee2f4ca258..74383039761e 100644 --- a/drivers/clk/clk-rk808.c +++ b/drivers/clk/clk-rk808.c @@ -106,7 +106,6 @@ static int rk808_clkout_probe(struct platform_device *pdev) if (!clk_table) return -ENOMEM; - init.flags = CLK_IS_ROOT; init.parent_names = NULL; init.num_parents = 0; init.name = "rk808-clkout1"; -- GitLab From d4da52c38c38366689db437327fe8385957b970c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:24 -0800 Subject: [PATCH 3099/9938] clk: twl6040: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Peter Ujfalusi Signed-off-by: Stephen Boyd --- drivers/clk/clk-twl6040.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c index 8e5ed649a098..697c66757400 100644 --- a/drivers/clk/clk-twl6040.c +++ b/drivers/clk/clk-twl6040.c @@ -74,7 +74,6 @@ static const struct clk_ops twl6040_mcpdm_ops = { static struct clk_init_data wm831x_clkout_init = { .name = "mcpdm_fclk", .ops = &twl6040_mcpdm_ops, - .flags = CLK_IS_ROOT, }; static int twl6040_clk_probe(struct platform_device *pdev) -- GitLab From 4c211eaad6202ffae10f4dd476db2f6173f880c7 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:25 -0800 Subject: [PATCH 3100/9938] clk: wm831x: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Mark Brown Signed-off-by: Stephen Boyd --- drivers/clk/clk-wm831x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index 43f9d15255f4..88def4b2761c 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -58,7 +58,6 @@ static const struct clk_ops wm831x_xtal_ops = { static struct clk_init_data wm831x_xtal_init = { .name = "xtal", .ops = &wm831x_xtal_ops, - .flags = CLK_IS_ROOT, }; static const unsigned long wm831x_fll_auto_rates[] = { -- GitLab From d31d56ec17431d3883d5f4b60d407fa5e75add06 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 1 Mar 2016 11:00:26 -0800 Subject: [PATCH 3101/9938] clk: xgene: Remove CLK_IS_ROOT This flag is a no-op now. Remove usage of the flag. Cc: Loc Ho Signed-off-by: Stephen Boyd --- drivers/clk/clk-xgene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index d73450b60b28..343313250c58 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -198,7 +198,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty of_property_read_string(np, "clock-output-names", &clk_name); clk = xgene_register_clk_pll(NULL, clk_name, of_clk_get_parent_name(np, 0), - CLK_IS_ROOT, reg, 0, pll_type, &clk_lock, + 0, reg, 0, pll_type, &clk_lock, version); if (!IS_ERR(clk)) { of_clk_add_provider(np, of_clk_src_simple_get, clk); -- GitLab From cb0ceaf77d93964a0d00477c79f4499123f6159c Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 8 Mar 2016 01:41:29 +0200 Subject: [PATCH 3102/9938] clk: at91: fix check of clk_register() returned value The clk_register() function returns a valid pointer to struct clk or ERR_PTR() error code, this makes a check for returned NULL value useless and may lead to oops on error path. Signed-off-by: Vladimir Zapolskiy Acked-by: Alexandre Belloni Acked-by: Boris Brezillon Fixes: bcc5fd49a0fd ("clk: at91: add a driver for the h32mx clock") Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-h32mx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c index 819f5842fa66..8e20c8a76db7 100644 --- a/drivers/clk/at91/clk-h32mx.c +++ b/drivers/clk/at91/clk-h32mx.c @@ -114,7 +114,7 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) h32mxclk->regmap = regmap; clk = clk_register(NULL, &h32mxclk->hw); - if (!clk) { + if (IS_ERR(clk)) { kfree(h32mxclk); return; } -- GitLab From f48256efededaa87f475c0d6330d83f853cb064a Mon Sep 17 00:00:00 2001 From: wangweidong Date: Thu, 14 Apr 2016 15:43:52 +0800 Subject: [PATCH 3103/9938] phy: make some bits preserved while setup forced mode When tested the PHY SGMII Loopback: 1.set the LOOPBACK bit, 2.set the autoneg to AUTONEG_DISABLE, it calls the genphy_setup_forced which will clear the bit. The BMCR_LOOPBACK bit should be preserved. As Florian pointed out that other bits should be preserved too. So I make the BMCR_ISOLATE and BMCR_PDOWN as well. Signed-off-by: Weidong Wang Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e551f3a89cfd..10e39c2fbf81 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1123,8 +1123,9 @@ static int genphy_config_advert(struct phy_device *phydev) */ int genphy_setup_forced(struct phy_device *phydev) { - int ctl = 0; + int ctl = phy_read(phydev, MII_BMCR); + ctl &= BMCR_LOOPBACK | BMCR_ISOLATE | BMCR_PDOWN; phydev->pause = 0; phydev->asym_pause = 0; -- GitLab From fefe0535b74f7d577af9310cf3741b4960a6687f Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Mon, 4 Apr 2016 11:21:09 +0200 Subject: [PATCH 3104/9938] clk: tango4: improve clkgen driver Add support for USB and SDIO clocks. Report unsupported setups and panic. Signed-off-by: Marc Gonzalez Signed-off-by: Stephen Boyd --- drivers/clk/clk-tango4.c | 73 ++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/drivers/clk/clk-tango4.c b/drivers/clk/clk-tango4.c index 004ab7dfcfe3..eef75e305a59 100644 --- a/drivers/clk/clk-tango4.c +++ b/drivers/clk/clk-tango4.c @@ -4,17 +4,19 @@ #include #include -static struct clk *out[2]; -static struct clk_onecell_data clk_data = { out, 2 }; +#define CLK_COUNT 4 /* cpu_clk, sys_clk, usb_clk, sdio_clk */ +static struct clk *clks[CLK_COUNT]; +static struct clk_onecell_data clk_data = { clks, CLK_COUNT }; -#define SYSCLK_CTRL 0x20 -#define CPUCLK_CTRL 0x24 -#define LEGACY_DIV 0x3c +#define SYSCLK_DIV 0x20 +#define CPUCLK_DIV 0x24 +#define DIV_BYPASS BIT(23) -#define PLL_N(val) (((val) >> 0) & 0x7f) -#define PLL_K(val) (((val) >> 13) & 0x7) -#define PLL_M(val) (((val) >> 16) & 0x7) -#define DIV_INDEX(val) (((val) >> 8) & 0xf) +/*** CLKGEN_PLL ***/ +#define extract_pll_n(val) ((val >> 0) & ((1u << 7) - 1)) +#define extract_pll_k(val) ((val >> 13) & ((1u << 3) - 1)) +#define extract_pll_m(val) ((val >> 16) & ((1u << 3) - 1)) +#define extract_pll_isel(val) ((val >> 24) & ((1u << 3) - 1)) static void __init make_pll(int idx, const char *parent, void __iomem *base) { @@ -22,40 +24,61 @@ static void __init make_pll(int idx, const char *parent, void __iomem *base) u32 val, mul, div; sprintf(name, "pll%d", idx); - val = readl_relaxed(base + idx*8); - mul = PLL_N(val) + 1; - div = (PLL_M(val) + 1) << PLL_K(val); + val = readl(base + idx * 8); + mul = extract_pll_n(val) + 1; + div = (extract_pll_m(val) + 1) << extract_pll_k(val); clk_register_fixed_factor(NULL, name, parent, 0, mul, div); + if (extract_pll_isel(val) != 1) + panic("%s: input not set to XTAL_IN\n", name); } -static int __init get_div(void __iomem *base) +static void __init make_cd(int idx, void __iomem *base) { - u8 sysclk_tab[16] = { 2, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4 }; - int idx = DIV_INDEX(readl_relaxed(base + LEGACY_DIV)); + char name[8]; + u32 val, mul, div; - return sysclk_tab[idx]; + sprintf(name, "cd%d", idx); + val = readl(base + idx * 8); + mul = 1 << 27; + div = (2 << 27) + val; + clk_register_fixed_factor(NULL, name, "pll2", 0, mul, div); + if (val > 0xf0000000) + panic("%s: unsupported divider %x\n", name, val); } static void __init tango4_clkgen_setup(struct device_node *np) { - int div, ret; + struct clk **pp = clk_data.clks; void __iomem *base = of_iomap(np, 0); const char *parent = of_clk_get_parent_name(np, 0); if (!base) - panic("%s: invalid address\n", np->full_name); + panic("%s: invalid address\n", np->name); + + if (readl(base + CPUCLK_DIV) & DIV_BYPASS) + panic("%s: unsupported cpuclk setup\n", np->name); + + if (readl(base + SYSCLK_DIV) & DIV_BYPASS) + panic("%s: unsupported sysclk setup\n", np->name); + + writel(0x100, base + CPUCLK_DIV); /* disable frequency ramping */ make_pll(0, parent, base); make_pll(1, parent, base); + make_pll(2, parent, base); + make_cd(2, base + 0x80); + make_cd(6, base + 0x80); - out[0] = clk_register_divider(NULL, "cpuclk", "pll0", 0, - base + CPUCLK_CTRL, 8, 8, CLK_DIVIDER_ONE_BASED, NULL); + pp[0] = clk_register_divider(NULL, "cpu_clk", "pll0", 0, + base + CPUCLK_DIV, 8, 8, CLK_DIVIDER_ONE_BASED, NULL); + pp[1] = clk_register_fixed_factor(NULL, "sys_clk", "pll1", 0, 1, 4); + pp[2] = clk_register_fixed_factor(NULL, "usb_clk", "cd2", 0, 1, 2); + pp[3] = clk_register_fixed_factor(NULL, "sdio_clk", "cd6", 0, 1, 2); - div = readl_relaxed(base + SYSCLK_CTRL) & BIT(23) ? get_div(base) : 4; - out[1] = clk_register_fixed_factor(NULL, "sysclk", "pll1", 0, 1, div); + if (IS_ERR(pp[0]) || IS_ERR(pp[1]) || IS_ERR(pp[2]) || IS_ERR(pp[3])) + panic("%s: clk registration failed\n", np->name); - ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); - if (IS_ERR(out[0]) || IS_ERR(out[1]) || ret < 0) - panic("%s: clk registration failed\n", np->full_name); + if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) + panic("%s: clk provider registration failed\n", np->name); } CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup); -- GitLab From c5cc2a0bc930f1ae00b198aeb752acc3bdd4d5a7 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 16 Mar 2016 21:54:55 +0200 Subject: [PATCH 3105/9938] clk: ti: dpll: add support for specifying max rate for DPLLs DPLLs typically have a maximum rate they can support, and this varies from DPLL to DPLL. Add support of the maximum rate value to the DPLL data struct, and also add check for this in the DPLL round_rate function. Signed-off-by: Tero Kristo Reviewed-by: Nishanth Menon Cc: Tomi Valkeinen Cc: Lokesh Vutla Signed-off-by: Stephen Boyd --- drivers/clk/ti/clkt_dpll.c | 3 +++ include/linux/clk/ti.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c index 032c658a5f5e..b919fdfe8256 100644 --- a/drivers/clk/ti/clkt_dpll.c +++ b/drivers/clk/ti/clkt_dpll.c @@ -301,6 +301,9 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, dd = clk->dpll_data; + if (dd->max_rate && target_rate > dd->max_rate) + target_rate = dd->max_rate; + ref_rate = clk_hw_get_rate(dd->clk_ref); clk_name = clk_hw_get_name(hw); pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index dc5164a6df29..6110fe09ed18 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -37,6 +37,7 @@ * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() * @min_divider: minimum valid non-bypass divider value (actual) * @max_divider: maximum valid non-bypass divider value (actual) + * @max_rate: maximum clock rate for the DPLL * @modes: possible values of @enable_mask * @autoidle_reg: register containing the DPLL autoidle mode bitfield * @idlest_reg: register containing the DPLL idle status bitfield @@ -81,6 +82,7 @@ struct dpll_data { u8 last_rounded_n; u8 min_divider; u16 max_divider; + unsigned long max_rate; u8 modes; void __iomem *autoidle_reg; void __iomem *idlest_reg; -- GitLab From 3db5ca27c80c15d20d0f1152dc34a5bcfa432ae6 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 16 Mar 2016 21:54:56 +0200 Subject: [PATCH 3106/9938] clk: ti: amx3xx: limit the maximum frequency of DPLLs based on spec AM33xx/AM43xx devices use the same DPLL IP blocks, which only support maximum rate of 1GHz [1] for the default and 2GHz for the low-jitter type DPLLs [2]. Reflect this limitation in the DPLL init code by adding the max-rate parameter based on the DPLL types. [1] Functional, integration & test specification for GS70 ADPLLS, Rev 1.0-01 [2] Functional, integration & test specification for GS70 ADPLLLJ, Rev 0.8-02 Signed-off-by: Tero Kristo Cc: Nishanth Menon Cc: Tomi Valkeinen Cc: Lokesh Vutla Signed-off-by: Stephen Boyd --- drivers/clk/ti/dpll.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 3bc9959f71c3..9fc8754a6e61 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -655,6 +655,7 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node) .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, + .max_rate = 1000000000, .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), }; @@ -674,6 +675,7 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node) .max_divider = 256, .min_divider = 2, .flags = DPLL_J_TYPE, + .max_rate = 2000000000, .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), }; @@ -692,6 +694,7 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node) .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, + .max_rate = 2000000000, .flags = DPLL_J_TYPE, .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), }; @@ -712,6 +715,7 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node) .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, + .max_rate = 1000000000, .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), }; @@ -729,6 +733,7 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node) .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, + .max_rate = 1000000000, .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), }; -- GitLab From d5630b7a557aff4d107e5af2e73fb91ed707f442 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 10 Dec 2015 19:03:45 +0200 Subject: [PATCH 3107/9938] clk: ti: dra7: fix kernel boot with arg 'clocksource=gp_timer' The OMAP Platform code provides possibility to select GP Timer as default clocksource instead of counter_32K by using bootcmd parameter 'clocksource', but the system will crash during early boot when this option is used on dra7 or omap5 platforms, because it will hit BUG() statement: omap2_gptimer_clocksource_init ->BUG_ON(res); This happens because clk_dev alias "sys_clkin_ck" is not registered. Hence, fix it by adding missing "sys_clkin_ck" clk_dev aliases definitions for omap5 and dra7. Acked-by: Tero Kristo Cc: Tony Lindgren Signed-off-by: Grygorii Strashko Signed-off-by: Stephen Boyd --- drivers/clk/ti/clk-54xx.c | 1 + drivers/clk/ti/clk-7xx.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index 59ce2fa2c104..294bc03ec067 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c @@ -210,6 +210,7 @@ static struct ti_dt_clk omap54xx_clks[] = { DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), DT_CLK("omap_wdt", "ick", "dummy_ck"), DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), + DT_CLK(NULL, "sys_clkin_ck", "sys_clkin"), DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin"), DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin"), DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin"), diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index a911d7de3377..87a87b5089ea 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -289,6 +289,7 @@ static struct ti_dt_clk dra7xx_clks[] = { DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), DT_CLK("omap_wdt", "ick", "dummy_ck"), DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), + DT_CLK(NULL, "sys_clkin_ck", "timer_sys_clk_div"), DT_CLK("4ae18000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK("48032000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK("48034000.timer", "timer_sys_ck", "timer_sys_clk_div"), -- GitLab From 6111413be8708a7509fd9c09817a657f6bf8f749 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sat, 16 Apr 2016 02:54:52 +0200 Subject: [PATCH 3108/9938] clk: rockchip: fix checkpatch errors in rk3399 dt-binding header Some "please, no space before tabs" checkpatch warnings slipped through the recent addition of the rk3399 dt-binding header, so fix them. Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3399-cru.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h index 244746e7dc4c..f60fe6e4b16e 100644 --- a/include/dt-bindings/clock/rk3399-cru.h +++ b/include/dt-bindings/clock/rk3399-cru.h @@ -136,7 +136,7 @@ #define DCLK_VOP1_DIV 183 #define DCLK_M0_PERILP 184 -#define FCLK_CM0S 190 +#define FCLK_CM0S 190 /* aclk gates */ #define ACLK_PERIHP 192 @@ -207,11 +207,11 @@ #define ACLK_CORE_ADB400_CORE_B_2_CCI500 257 #define ACLK_ADB400M_PD_CORE_L 258 #define ACLK_ADB400M_PD_CORE_B 259 -#define ACLK_PERF_CORE_L 260 -#define ACLK_PERF_CORE_B 261 -#define ACLK_GIC_PRE 262 -#define ACLK_VOP0_PRE 263 -#define ACLK_VOP1_PRE 264 +#define ACLK_PERF_CORE_L 260 +#define ACLK_PERF_CORE_B 261 +#define ACLK_GIC_PRE 262 +#define ACLK_VOP0_PRE 263 +#define ACLK_VOP1_PRE 264 /* pclk gates */ #define PCLK_PERIHP 320 @@ -279,12 +279,12 @@ #define PCLK_EFUSE1024S 382 #define PCLK_PMU_INTR_ARB 383 #define PCLK_MAILBOX0 384 -#define PCLK_USBPHY_MUX_G 385 -#define PCLK_UPHY0_TCPHY_G 386 -#define PCLK_UPHY0_TCPD_G 387 -#define PCLK_UPHY1_TCPHY_G 388 -#define PCLK_UPHY1_TCPD_G 389 -#define PCLK_ALIVE 390 +#define PCLK_USBPHY_MUX_G 385 +#define PCLK_UPHY0_TCPHY_G 386 +#define PCLK_UPHY0_TCPD_G 387 +#define PCLK_UPHY1_TCPHY_G 388 +#define PCLK_UPHY1_TCPD_G 389 +#define PCLK_ALIVE 390 /* hclk gates */ #define HCLK_PERIHP 448 -- GitLab From a3819e3e71d5000c176918309284a1fa2f133fcf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 15 Apr 2016 19:00:26 +0200 Subject: [PATCH 3109/9938] x86: Fix non-static inlines Four instances of incorrect usage of non-static "inline" crept up in arch/x86, all trivial; cleaning them up: EVT_TO_HPET_DEV() - made static, it is only used in kernel/hpet.c Debug version of check_iommu_entries() is an __init function. Non-debug dummy empty version of it is declared "inline" instead - which doesn't help to eliminate it (the caller is in a different unit, inlining doesn't happen). Switch to non-inlined __init function, which does eliminate it (by discarding it as part of __init section). crypto/sha-mb/sha1_mb.c: looks like they just forgot to add "static" to their two internal inlines, which emitted two unused functions into vmlinux. text data bss dec hex filename 95903394 20860288 35991552 152755234 91adc22 vmlinux_before 95903266 20860288 35991552 152755106 91adba2 vmlinux Signed-off-by: Denys Vlasenko Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/1460739626-12179-1-git-send-email-dvlasenk@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/crypto/sha-mb/sha1_mb.c | 4 ++-- arch/x86/kernel/hpet.c | 2 +- arch/x86/kernel/pci-iommu_table.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/crypto/sha-mb/sha1_mb.c b/arch/x86/crypto/sha-mb/sha1_mb.c index a8a0224fa0f8..fb9c7a84700c 100644 --- a/arch/x86/crypto/sha-mb/sha1_mb.c +++ b/arch/x86/crypto/sha-mb/sha1_mb.c @@ -102,14 +102,14 @@ static asmlinkage struct job_sha1* (*sha1_job_mgr_submit)(struct sha1_mb_mgr *st static asmlinkage struct job_sha1* (*sha1_job_mgr_flush)(struct sha1_mb_mgr *state); static asmlinkage struct job_sha1* (*sha1_job_mgr_get_comp_job)(struct sha1_mb_mgr *state); -inline void sha1_init_digest(uint32_t *digest) +static inline void sha1_init_digest(uint32_t *digest) { static const uint32_t initial_digest[SHA1_DIGEST_LENGTH] = {SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 }; memcpy(digest, initial_digest, sizeof(initial_digest)); } -inline uint32_t sha1_pad(uint8_t padblock[SHA1_BLOCK_SIZE * 2], +static inline uint32_t sha1_pad(uint8_t padblock[SHA1_BLOCK_SIZE * 2], uint32_t total_len) { uint32_t i = total_len & (SHA1_BLOCK_SIZE - 1); diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index a1f0e4a5c47e..130f2b4b8ecb 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -54,7 +54,7 @@ struct hpet_dev { char name[10]; }; -inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev) +static inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev) { return container_of(evtdev, struct hpet_dev, evt); } diff --git a/arch/x86/kernel/pci-iommu_table.c b/arch/x86/kernel/pci-iommu_table.c index 35ccf75696eb..f712dfdf1357 100644 --- a/arch/x86/kernel/pci-iommu_table.c +++ b/arch/x86/kernel/pci-iommu_table.c @@ -72,7 +72,7 @@ void __init check_iommu_entries(struct iommu_table_entry *start, } } #else -inline void check_iommu_entries(struct iommu_table_entry *start, +void __init check_iommu_entries(struct iommu_table_entry *start, struct iommu_table_entry *finish) { } -- GitLab From 77c4ad2d6a9bb6c6744f8f3a25d1c62669d6b656 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 15 Apr 2016 18:06:56 +0300 Subject: [PATCH 3110/9938] iio: imu: Add initial support for Bosch BMI160 BMI160 is an Inertial Measurement Unit (IMU) which provides acceleration and angular rate measurement. It also offers a secondary I2C interface for connecting a magnetometer sensor (usually BMM160). Current driver offers support for accelerometer and gyroscope readings via sysfs or via buffer interface using an external trigger (e.g. hrtimer). Data is retrieved from IMU via I2C or SPI interface. Datasheet is at: http://www.mouser.com/ds/2/783/BST-BMI160-DS000-07-786474.pdf Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/Kconfig | 2 + drivers/iio/imu/Makefile | 1 + drivers/iio/imu/bmi160/Kconfig | 32 ++ drivers/iio/imu/bmi160/Makefile | 6 + drivers/iio/imu/bmi160/bmi160.h | 10 + drivers/iio/imu/bmi160/bmi160_core.c | 596 +++++++++++++++++++++++++++ drivers/iio/imu/bmi160/bmi160_i2c.c | 72 ++++ drivers/iio/imu/bmi160/bmi160_spi.c | 63 +++ 8 files changed, 782 insertions(+) create mode 100644 drivers/iio/imu/bmi160/Kconfig create mode 100644 drivers/iio/imu/bmi160/Makefile create mode 100644 drivers/iio/imu/bmi160/bmi160.h create mode 100644 drivers/iio/imu/bmi160/bmi160_core.c create mode 100644 drivers/iio/imu/bmi160/bmi160_i2c.c create mode 100644 drivers/iio/imu/bmi160/bmi160_spi.c diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 5e610f7de5aa..1f1ad41ef881 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -25,6 +25,8 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. +source "drivers/iio/imu/bmi160/Kconfig" + config KMX61 tristate "Kionix KMX61 6-axis accelerometer and magnetometer" depends on I2C diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index e1e6e3d70e26..c71bcd30dc38 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -13,6 +13,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o +obj-y += bmi160/ obj-y += inv_mpu6050/ obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/bmi160/Kconfig b/drivers/iio/imu/bmi160/Kconfig new file mode 100644 index 000000000000..005c17ccc2b0 --- /dev/null +++ b/drivers/iio/imu/bmi160/Kconfig @@ -0,0 +1,32 @@ +# +# BMI160 IMU driver +# + +config BMI160 + tristate + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + +config BMI160_I2C + tristate "Bosch BMI160 I2C driver" + depends on I2C + select BMI160 + select REGMAP_I2C + help + If you say yes here you get support for BMI160 IMU on I2C with + accelerometer, gyroscope and external BMG160 magnetometer. + + This driver can also be built as a module. If so, the module will be + called bmi160_i2c. + +config BMI160_SPI + tristate "Bosch BMI160 SPI driver" + depends on SPI + select BMI160 + select REGMAP_SPI + help + If you say yes here you get support for BMI160 IMU on SPI with + accelerometer, gyroscope and external BMG160 magnetometer. + + This driver can also be built as a module. If so, the module will be + called bmi160_spi. diff --git a/drivers/iio/imu/bmi160/Makefile b/drivers/iio/imu/bmi160/Makefile new file mode 100644 index 000000000000..10365e493ae2 --- /dev/null +++ b/drivers/iio/imu/bmi160/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for Bosch BMI160 IMU +# +obj-$(CONFIG_BMI160) += bmi160_core.o +obj-$(CONFIG_BMI160_I2C) += bmi160_i2c.o +obj-$(CONFIG_BMI160_SPI) += bmi160_spi.o diff --git a/drivers/iio/imu/bmi160/bmi160.h b/drivers/iio/imu/bmi160/bmi160.h new file mode 100644 index 000000000000..d2ae6ed70271 --- /dev/null +++ b/drivers/iio/imu/bmi160/bmi160.h @@ -0,0 +1,10 @@ +#ifndef BMI160_H_ +#define BMI160_H_ + +extern const struct regmap_config bmi160_regmap_config; + +int bmi160_core_probe(struct device *dev, struct regmap *regmap, + const char *name, bool use_spi); +void bmi160_core_remove(struct device *dev); + +#endif /* BMI160_H_ */ diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c new file mode 100644 index 000000000000..0bf92b06d7d8 --- /dev/null +++ b/drivers/iio/imu/bmi160/bmi160_core.c @@ -0,0 +1,596 @@ +/* + * BMI160 - Bosch IMU (accel, gyro plus external magnetometer) + * + * Copyright (c) 2016, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO core driver for BMI160, with support for I2C/SPI busses + * + * TODO: magnetometer, interrupts, hardware FIFO + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "bmi160.h" + +#define BMI160_REG_CHIP_ID 0x00 +#define BMI160_CHIP_ID_VAL 0xD1 + +#define BMI160_REG_PMU_STATUS 0x03 + +/* X axis data low byte address, the rest can be obtained using axis offset */ +#define BMI160_REG_DATA_MAGN_XOUT_L 0x04 +#define BMI160_REG_DATA_GYRO_XOUT_L 0x0C +#define BMI160_REG_DATA_ACCEL_XOUT_L 0x12 + +#define BMI160_REG_ACCEL_CONFIG 0x40 +#define BMI160_ACCEL_CONFIG_ODR_MASK GENMASK(3, 0) +#define BMI160_ACCEL_CONFIG_BWP_MASK GENMASK(6, 4) + +#define BMI160_REG_ACCEL_RANGE 0x41 +#define BMI160_ACCEL_RANGE_2G 0x03 +#define BMI160_ACCEL_RANGE_4G 0x05 +#define BMI160_ACCEL_RANGE_8G 0x08 +#define BMI160_ACCEL_RANGE_16G 0x0C + +#define BMI160_REG_GYRO_CONFIG 0x42 +#define BMI160_GYRO_CONFIG_ODR_MASK GENMASK(3, 0) +#define BMI160_GYRO_CONFIG_BWP_MASK GENMASK(5, 4) + +#define BMI160_REG_GYRO_RANGE 0x43 +#define BMI160_GYRO_RANGE_2000DPS 0x00 +#define BMI160_GYRO_RANGE_1000DPS 0x01 +#define BMI160_GYRO_RANGE_500DPS 0x02 +#define BMI160_GYRO_RANGE_250DPS 0x03 +#define BMI160_GYRO_RANGE_125DPS 0x04 + +#define BMI160_REG_CMD 0x7E +#define BMI160_CMD_ACCEL_PM_SUSPEND 0x10 +#define BMI160_CMD_ACCEL_PM_NORMAL 0x11 +#define BMI160_CMD_ACCEL_PM_LOW_POWER 0x12 +#define BMI160_CMD_GYRO_PM_SUSPEND 0x14 +#define BMI160_CMD_GYRO_PM_NORMAL 0x15 +#define BMI160_CMD_GYRO_PM_FAST_STARTUP 0x17 +#define BMI160_CMD_SOFTRESET 0xB6 + +#define BMI160_REG_DUMMY 0x7F + +#define BMI160_ACCEL_PMU_MIN_USLEEP 3200 +#define BMI160_ACCEL_PMU_MAX_USLEEP 3800 +#define BMI160_GYRO_PMU_MIN_USLEEP 55000 +#define BMI160_GYRO_PMU_MAX_USLEEP 80000 +#define BMI160_SOFTRESET_USLEEP 1000 + +#define BMI160_CHANNEL(_type, _axis, _index) { \ + .type = _type, \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + }, \ +} + +/* scan indexes follow DATA register order */ +enum bmi160_scan_axis { + BMI160_SCAN_EXT_MAGN_X = 0, + BMI160_SCAN_EXT_MAGN_Y, + BMI160_SCAN_EXT_MAGN_Z, + BMI160_SCAN_RHALL, + BMI160_SCAN_GYRO_X, + BMI160_SCAN_GYRO_Y, + BMI160_SCAN_GYRO_Z, + BMI160_SCAN_ACCEL_X, + BMI160_SCAN_ACCEL_Y, + BMI160_SCAN_ACCEL_Z, + BMI160_SCAN_TIMESTAMP, +}; + +enum bmi160_sensor_type { + BMI160_ACCEL = 0, + BMI160_GYRO, + BMI160_EXT_MAGN, + BMI160_NUM_SENSORS /* must be last */ +}; + +struct bmi160_data { + struct regmap *regmap; +}; + +const struct regmap_config bmi160_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; +EXPORT_SYMBOL(bmi160_regmap_config); + +struct bmi160_regs { + u8 data; /* LSB byte register for X-axis */ + u8 config; + u8 config_odr_mask; + u8 config_bwp_mask; + u8 range; + u8 pmu_cmd_normal; + u8 pmu_cmd_suspend; +}; + +static struct bmi160_regs bmi160_regs[] = { + [BMI160_ACCEL] = { + .data = BMI160_REG_DATA_ACCEL_XOUT_L, + .config = BMI160_REG_ACCEL_CONFIG, + .config_odr_mask = BMI160_ACCEL_CONFIG_ODR_MASK, + .config_bwp_mask = BMI160_ACCEL_CONFIG_BWP_MASK, + .range = BMI160_REG_ACCEL_RANGE, + .pmu_cmd_normal = BMI160_CMD_ACCEL_PM_NORMAL, + .pmu_cmd_suspend = BMI160_CMD_ACCEL_PM_SUSPEND, + }, + [BMI160_GYRO] = { + .data = BMI160_REG_DATA_GYRO_XOUT_L, + .config = BMI160_REG_GYRO_CONFIG, + .config_odr_mask = BMI160_GYRO_CONFIG_ODR_MASK, + .config_bwp_mask = BMI160_GYRO_CONFIG_BWP_MASK, + .range = BMI160_REG_GYRO_RANGE, + .pmu_cmd_normal = BMI160_CMD_GYRO_PM_NORMAL, + .pmu_cmd_suspend = BMI160_CMD_GYRO_PM_SUSPEND, + }, +}; + +struct bmi160_pmu_time { + unsigned long min; + unsigned long max; +}; + +static struct bmi160_pmu_time bmi160_pmu_time[] = { + [BMI160_ACCEL] = { + .min = BMI160_ACCEL_PMU_MIN_USLEEP, + .max = BMI160_ACCEL_PMU_MAX_USLEEP + }, + [BMI160_GYRO] = { + .min = BMI160_GYRO_PMU_MIN_USLEEP, + .max = BMI160_GYRO_PMU_MIN_USLEEP, + }, +}; + +struct bmi160_scale { + u8 bits; + int uscale; +}; + +struct bmi160_odr { + u8 bits; + int odr; + int uodr; +}; + +static const struct bmi160_scale bmi160_accel_scale[] = { + { BMI160_ACCEL_RANGE_2G, 598}, + { BMI160_ACCEL_RANGE_4G, 1197}, + { BMI160_ACCEL_RANGE_8G, 2394}, + { BMI160_ACCEL_RANGE_16G, 4788}, +}; + +static const struct bmi160_scale bmi160_gyro_scale[] = { + { BMI160_GYRO_RANGE_2000DPS, 1065}, + { BMI160_GYRO_RANGE_1000DPS, 532}, + { BMI160_GYRO_RANGE_500DPS, 266}, + { BMI160_GYRO_RANGE_250DPS, 133}, + { BMI160_GYRO_RANGE_125DPS, 66}, +}; + +struct bmi160_scale_item { + const struct bmi160_scale *tbl; + int num; +}; + +static const struct bmi160_scale_item bmi160_scale_table[] = { + [BMI160_ACCEL] = { + .tbl = bmi160_accel_scale, + .num = ARRAY_SIZE(bmi160_accel_scale), + }, + [BMI160_GYRO] = { + .tbl = bmi160_gyro_scale, + .num = ARRAY_SIZE(bmi160_gyro_scale), + }, +}; + +static const struct bmi160_odr bmi160_accel_odr[] = { + {0x01, 0, 78125}, + {0x02, 1, 5625}, + {0x03, 3, 125}, + {0x04, 6, 25}, + {0x05, 12, 5}, + {0x06, 25, 0}, + {0x07, 50, 0}, + {0x08, 100, 0}, + {0x09, 200, 0}, + {0x0A, 400, 0}, + {0x0B, 800, 0}, + {0x0C, 1600, 0}, +}; + +static const struct bmi160_odr bmi160_gyro_odr[] = { + {0x06, 25, 0}, + {0x07, 50, 0}, + {0x08, 100, 0}, + {0x09, 200, 0}, + {0x0A, 400, 0}, + {0x0B, 8000, 0}, + {0x0C, 1600, 0}, + {0x0D, 3200, 0}, +}; + +struct bmi160_odr_item { + const struct bmi160_odr *tbl; + int num; +}; + +static const struct bmi160_odr_item bmi160_odr_table[] = { + [BMI160_ACCEL] = { + .tbl = bmi160_accel_odr, + .num = ARRAY_SIZE(bmi160_accel_odr), + }, + [BMI160_GYRO] = { + .tbl = bmi160_gyro_odr, + .num = ARRAY_SIZE(bmi160_gyro_odr), + }, +}; + +static const struct iio_chan_spec bmi160_channels[] = { + BMI160_CHANNEL(IIO_ACCEL, X, BMI160_SCAN_ACCEL_X), + BMI160_CHANNEL(IIO_ACCEL, Y, BMI160_SCAN_ACCEL_Y), + BMI160_CHANNEL(IIO_ACCEL, Z, BMI160_SCAN_ACCEL_Z), + BMI160_CHANNEL(IIO_ANGL_VEL, X, BMI160_SCAN_GYRO_X), + BMI160_CHANNEL(IIO_ANGL_VEL, Y, BMI160_SCAN_GYRO_Y), + BMI160_CHANNEL(IIO_ANGL_VEL, Z, BMI160_SCAN_GYRO_Z), + IIO_CHAN_SOFT_TIMESTAMP(BMI160_SCAN_TIMESTAMP), +}; + +static enum bmi160_sensor_type bmi160_to_sensor(enum iio_chan_type iio_type) +{ + switch (iio_type) { + case IIO_ACCEL: + return BMI160_ACCEL; + case IIO_ANGL_VEL: + return BMI160_GYRO; + default: + return -EINVAL; + } +} + +static +int bmi160_set_mode(struct bmi160_data *data, enum bmi160_sensor_type t, + bool mode) +{ + int ret; + u8 cmd; + + if (mode) + cmd = bmi160_regs[t].pmu_cmd_normal; + else + cmd = bmi160_regs[t].pmu_cmd_suspend; + + ret = regmap_write(data->regmap, BMI160_REG_CMD, cmd); + if (ret < 0) + return ret; + + usleep_range(bmi160_pmu_time[t].min, bmi160_pmu_time[t].max); + + return 0; +} + +static +int bmi160_set_scale(struct bmi160_data *data, enum bmi160_sensor_type t, + int uscale) +{ + int i; + + for (i = 0; i < bmi160_scale_table[t].num; i++) + if (bmi160_scale_table[t].tbl[i].uscale == uscale) + break; + + if (i == bmi160_scale_table[t].num) + return -EINVAL; + + return regmap_write(data->regmap, bmi160_regs[t].range, + bmi160_scale_table[t].tbl[i].bits); +} + +static +int bmi160_get_scale(struct bmi160_data *data, enum bmi160_sensor_type t, + int *uscale) +{ + int i, ret, val; + + ret = regmap_read(data->regmap, bmi160_regs[t].range, &val); + if (ret < 0) + return ret; + + for (i = 0; i < bmi160_scale_table[t].num; i++) + if (bmi160_scale_table[t].tbl[i].bits == val) { + *uscale = bmi160_scale_table[t].tbl[i].uscale; + return 0; + } + + return -EINVAL; +} + +static int bmi160_get_data(struct bmi160_data *data, int chan_type, + int axis, int *val) +{ + u8 reg; + int ret; + __le16 sample; + enum bmi160_sensor_type t = bmi160_to_sensor(chan_type); + + reg = bmi160_regs[t].data + (axis - IIO_MOD_X) * sizeof(__le16); + + ret = regmap_bulk_read(data->regmap, reg, &sample, sizeof(__le16)); + if (ret < 0) + return ret; + + *val = sign_extend32(le16_to_cpu(sample), 15); + + return 0; +} + +static +int bmi160_set_odr(struct bmi160_data *data, enum bmi160_sensor_type t, + int odr, int uodr) +{ + int i; + + for (i = 0; i < bmi160_odr_table[t].num; i++) + if (bmi160_odr_table[t].tbl[i].odr == odr && + bmi160_odr_table[t].tbl[i].uodr == uodr) + break; + + if (i >= bmi160_odr_table[t].num) + return -EINVAL; + + return regmap_update_bits(data->regmap, + bmi160_regs[t].config, + bmi160_odr_table[t].tbl[i].bits, + bmi160_regs[t].config_odr_mask); +} + +static int bmi160_get_odr(struct bmi160_data *data, enum bmi160_sensor_type t, + int *odr, int *uodr) +{ + int i, val, ret; + + ret = regmap_read(data->regmap, bmi160_regs[t].config, &val); + if (ret < 0) + return ret; + + val &= bmi160_regs[t].config_odr_mask; + + for (i = 0; i < bmi160_odr_table[t].num; i++) + if (val == bmi160_odr_table[t].tbl[i].bits) + break; + + if (i >= bmi160_odr_table[t].num) + return -EINVAL; + + *odr = bmi160_odr_table[t].tbl[i].odr; + *uodr = bmi160_odr_table[t].tbl[i].uodr; + + return 0; +} + +static irqreturn_t bmi160_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct bmi160_data *data = iio_priv(indio_dev); + s16 buf[16]; /* 3 sens x 3 axis x s16 + 3 x s16 pad + 4 x s16 tstamp */ + int i, ret, j = 0, base = BMI160_REG_DATA_MAGN_XOUT_L; + __le16 sample; + + for_each_set_bit(i, indio_dev->active_scan_mask, + indio_dev->masklength) { + ret = regmap_bulk_read(data->regmap, base + i * sizeof(__le16), + &sample, sizeof(__le16)); + if (ret < 0) + goto done; + buf[j++] = sample; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int bmi160_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + struct bmi160_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = bmi160_get_data(data, chan->type, chan->channel2, val); + if (ret < 0) + return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + ret = bmi160_get_scale(data, + bmi160_to_sensor(chan->type), val2); + return ret < 0 ? ret : IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = bmi160_get_odr(data, bmi160_to_sensor(chan->type), + val, val2); + return ret < 0 ? ret : IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + + return 0; +} + +static int bmi160_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct bmi160_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return bmi160_set_scale(data, + bmi160_to_sensor(chan->type), val2); + break; + case IIO_CHAN_INFO_SAMP_FREQ: + return bmi160_set_odr(data, bmi160_to_sensor(chan->type), + val, val2); + default: + return -EINVAL; + } + + return 0; +} + +static const struct iio_info bmi160_info = { + .driver_module = THIS_MODULE, + .read_raw = bmi160_read_raw, + .write_raw = bmi160_write_raw, +}; + +static const char *bmi160_match_acpi_device(struct device *dev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + + return dev_name(dev); +} + +static int bmi160_chip_init(struct bmi160_data *data, bool use_spi) +{ + int ret; + unsigned int val; + struct device *dev = regmap_get_device(data->regmap); + + ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET); + if (ret < 0) + return ret; + + usleep_range(BMI160_SOFTRESET_USLEEP, BMI160_SOFTRESET_USLEEP + 1); + + /* + * CS rising edge is needed before starting SPI, so do a dummy read + * See Section 3.2.1, page 86 of the datasheet + */ + if (use_spi) { + ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val); + if (ret < 0) + return ret; + } + + ret = regmap_read(data->regmap, BMI160_REG_CHIP_ID, &val); + if (ret < 0) { + dev_err(dev, "Error reading chip id\n"); + return ret; + } + if (val != BMI160_CHIP_ID_VAL) { + dev_err(dev, "Wrong chip id, got %x expected %x\n", + val, BMI160_CHIP_ID_VAL); + return -ENODEV; + } + + ret = bmi160_set_mode(data, BMI160_ACCEL, true); + if (ret < 0) + return ret; + + ret = bmi160_set_mode(data, BMI160_GYRO, true); + if (ret < 0) + return ret; + + return 0; +} + +static void bmi160_chip_uninit(struct bmi160_data *data) +{ + bmi160_set_mode(data, BMI160_GYRO, false); + bmi160_set_mode(data, BMI160_ACCEL, false); +} + +int bmi160_core_probe(struct device *dev, struct regmap *regmap, + const char *name, bool use_spi) +{ + struct iio_dev *indio_dev; + struct bmi160_data *data; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); + data->regmap = regmap; + + ret = bmi160_chip_init(data, use_spi); + if (ret < 0) + return ret; + + if (!name && ACPI_HANDLE(dev)) + name = bmi160_match_acpi_device(dev); + + indio_dev->dev.parent = dev; + indio_dev->channels = bmi160_channels; + indio_dev->num_channels = ARRAY_SIZE(bmi160_channels); + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &bmi160_info; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + bmi160_trigger_handler, NULL); + if (ret < 0) + goto uninit; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto buffer_cleanup; + + return 0; +buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +uninit: + bmi160_chip_uninit(data); + return ret; +} +EXPORT_SYMBOL_GPL(bmi160_core_probe); + +void bmi160_core_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct bmi160_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + bmi160_chip_uninit(data); +} +EXPORT_SYMBOL_GPL(bmi160_core_remove); + +MODULE_AUTHOR("Daniel Baluta +#include +#include +#include + +#include "bmi160.h" + +static int bmi160_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + const char *name = NULL; + + regmap = devm_regmap_init_i2c(client, &bmi160_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to register i2c regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + if (id) + name = id->name; + + return bmi160_core_probe(&client->dev, regmap, name, false); +} + +static int bmi160_i2c_remove(struct i2c_client *client) +{ + bmi160_core_remove(&client->dev); + + return 0; +} + +static const struct i2c_device_id bmi160_i2c_id[] = { + {"bmi160", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id); + +static const struct acpi_device_id bmi160_acpi_match[] = { + {"BMI0160", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match); + +static struct i2c_driver bmi160_i2c_driver = { + .driver = { + .name = "bmi160_i2c", + .acpi_match_table = ACPI_PTR(bmi160_acpi_match), + }, + .probe = bmi160_i2c_probe, + .remove = bmi160_i2c_remove, + .id_table = bmi160_i2c_id, +}; +module_i2c_driver(bmi160_i2c_driver); + +MODULE_AUTHOR("Daniel Baluta "); +MODULE_DESCRIPTION("BMI160 I2C driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/imu/bmi160/bmi160_spi.c b/drivers/iio/imu/bmi160/bmi160_spi.c new file mode 100644 index 000000000000..1ec8b12bd984 --- /dev/null +++ b/drivers/iio/imu/bmi160/bmi160_spi.c @@ -0,0 +1,63 @@ +/* + * BMI160 - Bosch IMU, SPI bits + * + * Copyright (c) 2016, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ +#include +#include +#include +#include + +#include "bmi160.h" + +static int bmi160_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + const struct spi_device_id *id = spi_get_device_id(spi); + + regmap = devm_regmap_init_spi(spi, &bmi160_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Failed to register spi regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + return bmi160_core_probe(&spi->dev, regmap, id->name, true); +} + +static int bmi160_spi_remove(struct spi_device *spi) +{ + bmi160_core_remove(&spi->dev); + + return 0; +} + +static const struct spi_device_id bmi160_spi_id[] = { + {"bmi160", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, bmi160_spi_id); + +static const struct acpi_device_id bmi160_acpi_match[] = { + {"BMI0160", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match); + +static struct spi_driver bmi160_spi_driver = { + .probe = bmi160_spi_probe, + .remove = bmi160_spi_remove, + .id_table = bmi160_spi_id, + .driver = { + .acpi_match_table = ACPI_PTR(bmi160_acpi_match), + .name = "bmi160_spi", + }, +}; +module_spi_driver(bmi160_spi_driver); + +MODULE_AUTHOR("Daniel Baluta Date: Thu, 14 Apr 2016 21:36:33 +0200 Subject: [PATCH 3111/9938] iio: light apds9960: fix wrong use of brace This fixes the error reported by checkpatch.pl: ERROR: that open brace { should be on the previous line Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/light/apds9960.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index f6a07dc32ae4..47fcd5ad4ff2 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -321,8 +321,12 @@ static const struct iio_chan_spec apds9960_channels[] = { }; /* integration time in us */ -static const int apds9960_int_time[][2] = - { {28000, 246}, {100000, 219}, {200000, 182}, {700000, 0} }; +static const int apds9960_int_time[][2] = { + { 28000, 246}, + {100000, 219}, + {200000, 182}, + {700000, 0} +}; /* gain mapping */ static const int apds9960_pxs_gain_map[] = {1, 2, 4, 8}; -- GitLab From fc0b81704f0458c20793e82a3c094a215833dcfe Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:34 +0200 Subject: [PATCH 3112/9938] iio: inkern: add a missing space before if This fixes the error reported by checkpatch.pl: ERROR: space required before the open parenthesis '(' Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 734a0042de0c..2fc7928f401d 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -452,7 +452,7 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, if (val2 == NULL) val2 = &unused; - if(!iio_channel_has_info(chan->channel, info)) + if (!iio_channel_has_info(chan->channel, info)) return -EINVAL; if (chan->indio_dev->info->read_raw_multi) { -- GitLab From 37dd441e4fe2d4b38e88d067175f1fc7d6acdf16 Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:35 +0200 Subject: [PATCH 3113/9938] iio: adc: vf610_adc: fix case label indent This fixes the error reported by checkpatch.pl: ERROR: switch and case should be at the same indent Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/adc/vf610_adc.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index b10f629cc44b..653bf1379d2e 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -714,19 +714,19 @@ static int vf610_write_raw(struct iio_dev *indio_dev, int i; switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - for (i = 0; - i < ARRAY_SIZE(info->sample_freq_avail); - i++) - if (val == info->sample_freq_avail[i]) { - info->adc_feature.sample_rate = i; - vf610_adc_sample_set(info); - return 0; - } - break; + case IIO_CHAN_INFO_SAMP_FREQ: + for (i = 0; + i < ARRAY_SIZE(info->sample_freq_avail); + i++) + if (val == info->sample_freq_avail[i]) { + info->adc_feature.sample_rate = i; + vf610_adc_sample_set(info); + return 0; + } + break; - default: - break; + default: + break; } return -EINVAL; -- GitLab From 038a8b34d375b31a001198f5405f41cb48a153de Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:36 +0200 Subject: [PATCH 3114/9938] iio: adc: mcp3422: remove spaces before comma This fixes the error reported by checkpatch.pl: ERROR: space prohibited before that ',' (ctx:WxW) Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3422.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index d7b36efd2f3c..d1172dc1e8e2 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -61,9 +61,9 @@ static const int mcp3422_scales[4][4] = { { 1000000, 500000, 250000, 125000 }, - { 250000 , 125000, 62500 , 31250 }, - { 62500 , 31250 , 15625 , 7812 }, - { 15625 , 7812 , 3906 , 1953 } }; + { 250000, 125000, 62500, 31250 }, + { 62500, 31250, 15625, 7812 }, + { 15625, 7812, 3906, 1953 } }; /* Constant msleep times for data acquisitions */ static const int mcp3422_read_times[4] = { -- GitLab From 4c79dd006b6489a62516e6db636d91e71fd8bee1 Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:37 +0200 Subject: [PATCH 3115/9938] iio: adc: at91_adc: fix errors reported by checkpatch.pl This fixes the errors reported by checkpatch.pl: ERROR: space prohibited before that ',' (ctx:WxW) ERROR: code indent should use tabs where possible Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index f284cd6a93d6..52430ba171f3 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -797,8 +797,8 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) * Startup Time = / ADC Clock */ const int startup_lookup[] = { - 0 , 8 , 16 , 24 , - 64 , 80 , 96 , 112, + 0, 8, 16, 24, + 64, 80, 96, 112, 512, 576, 640, 704, 768, 832, 896, 960 }; @@ -924,14 +924,14 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, ret = -EINVAL; goto error_ret; } - trig->name = name; + trig->name = name; if (of_property_read_u32(trig_node, "trigger-value", &prop)) { dev_err(&idev->dev, "Missing trigger-value property in the DT.\n"); ret = -EINVAL; goto error_ret; } - trig->value = prop; + trig->value = prop; trig->is_external = of_property_read_bool(trig_node, "trigger-external"); i++; } -- GitLab From 102447adfa5a11df57ba1dfeefa250c96bf5e94f Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:38 +0200 Subject: [PATCH 3116/9938] iio: adc: ad799x: remove space before comma This fixes the error reported by checkpatch.pl: ERROR: space prohibited before that ',' (ctx:WxW) Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad799x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 01d71588d752..a3f5254f4e51 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -477,7 +477,7 @@ static int ad799x_read_event_value(struct iio_dev *indio_dev, if (ret < 0) return ret; *val = (ret >> chan->scan_type.shift) & - GENMASK(chan->scan_type.realbits - 1 , 0); + GENMASK(chan->scan_type.realbits - 1, 0); return IIO_VAL_INT; } -- GitLab From f6aa8eaf5d301b213f4660d1a37b44b5f1c2c458 Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:39 +0200 Subject: [PATCH 3117/9938] iio: common: ms_sensors: use tab for indention This fixes the error reported by checkpatch.pl: ERROR: code indent should use tabs where possible Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/common/ms_sensors/ms_sensors_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c index 669dc7c270f5..ecf7721ecaf4 100644 --- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c +++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c @@ -106,7 +106,7 @@ int ms_sensors_convert_and_read(void *cli, u8 conv, u8 rd, unsigned int delay, u32 *adc) { int ret; - __be32 buf = 0; + __be32 buf = 0; struct i2c_client *client = (struct i2c_client *)cli; /* Trigger conversion */ -- GitLab From d23057e0cadc465911968a4d3f8b0b556f545b6e Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:40 +0200 Subject: [PATCH 3118/9938] iio: common: hid-sensors: use tab for indention This fixes the error reported by checkpatch.pl: ERROR: code indent should use tabs where possible Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 595511022795..5b41f9d0d4f3 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -115,7 +115,7 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) return ret; } - return 0; + return 0; #else atomic_set(&st->user_requested_state, state); return _hid_sensor_power_state(st, state); -- GitLab From 26b89d7d2b22e3b7ae78dc8e5e17e0e4e9d448ca Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 21:36:41 +0200 Subject: [PATCH 3119/9938] iio: magnetometer: ak8975: put else and brace at the same line This fixes the error reported by checkpatch.pl: ERROR: else should follow close brace '}' Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 1e6898141f88..a2aac50a0149 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -882,8 +882,7 @@ static int ak8975_probe(struct i2c_client *client, name = ak8975_match_acpi_device(&client->dev, &chipset); if (!name) return -ENODEV; - } - else + } else return -ENOSYS; if (chipset >= AK_MAX_TYPE) { -- GitLab From 964d97bdab7d81bb65453d84ed3a51f4605a7e9c Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 16 Apr 2016 13:38:49 +0100 Subject: [PATCH 3120/9938] iio: pressure: ms5611: use tab for indention This fixes the errors reported by checkpatch.pl: ERROR: code indent should use tabs where possible Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611_core.c | 2 +- drivers/iio/pressure/ms5611_spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index c4e65868bc28..76578b07bb6e 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -429,7 +429,7 @@ static void ms5611_fini(const struct iio_dev *indio_dev) } int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, - const char *name, int type) + const char *name, int type) { int ret; struct ms5611_state *st = iio_priv(indio_dev); diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index 7600483e8cb4..932e05001e1a 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -108,7 +108,7 @@ static int ms5611_spi_probe(struct spi_device *spi) st->client = spi; return ms5611_probe(indio_dev, &spi->dev, spi_get_device_id(spi)->name, - spi_get_device_id(spi)->driver_data); + spi_get_device_id(spi)->driver_data); } static int ms5611_spi_remove(struct spi_device *spi) -- GitLab From af8a41271b56f6d79cb4d7c7f3ca688a2d97a801 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Apr 2016 16:59:38 +0200 Subject: [PATCH 3121/9938] iio:adis: Add support for manual self-test flag clear Some variants of the devices from the ADIS family don't auto-clear the self-test bit after the self-test has completed. Instead we have to manually clear. Add support for this to the ADIS library. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 7 ++++++- include/linux/iio/imu/adis.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 911255d41c1a..ad6f91d06185 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -324,7 +324,12 @@ static int adis_self_test(struct adis *adis) msleep(adis->data->startup_delay); - return adis_check_status(adis); + ret = adis_check_status(adis); + + if (adis->data->self_test_no_autoclear) + adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00); + + return ret; } /** diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index fa2d01ef8f55..360da7d18a3d 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -41,6 +41,7 @@ struct adis_data { unsigned int diag_stat_reg; unsigned int self_test_mask; + bool self_test_no_autoclear; unsigned int startup_delay; const char * const *status_error_msgs; -- GitLab From 24410492868ba816bfd4366b5406d4881b8aee94 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Apr 2016 16:59:39 +0200 Subject: [PATCH 3122/9938] staging:iio:adis16201: Set self_test_no_autoclear flag The ADIS16201 does not automatically clear the self test flag bit the self test has been, so clear it manually. Otherwise we'll see a offset caused by the self-test bias on the output values during normal operation. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 06c0b75ed26a..6f3f8ff2a066 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -167,6 +167,7 @@ static const struct adis_data adis16201_data = { .diag_stat_reg = ADIS16201_DIAG_STAT, .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, + .self_test_no_autoclear = true, .startup_delay = ADIS16201_STARTUP_DELAY, .status_error_msgs = adis16201_status_error_msgs, -- GitLab From 26d96e8ea9912d9fc7c48339ed6cf5642390ffff Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Apr 2016 16:59:40 +0200 Subject: [PATCH 3123/9938] staging:iio:adis16203: Set self_test_no_autoclear flag The ADIS16201 does not automatically clear the self test flag bit the self test has been, so clear it manually. Otherwise we'll see a offset caused by the self-test bias on the output values during normal operation. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16203_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index de5b84ac842b..c70671778bae 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -134,6 +134,7 @@ static const struct adis_data adis16203_data = { .diag_stat_reg = ADIS16203_DIAG_STAT, .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN, + .self_test_no_autoclear = true, .startup_delay = ADIS16203_STARTUP_DELAY, .status_error_msgs = adis16203_status_error_msgs, -- GitLab From 5d116edd71f688d0acc442ad8e66903e26d15d0b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Apr 2016 16:59:41 +0200 Subject: [PATCH 3124/9938] staging:iio:adis16209: Set self_test_no_autoclear flag The ADIS16201 does not automatically clear the self test flag bit the self test has been, so clear it manually. Otherwise we'll see a offset caused by the self-test bias on the output values during normal operation. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16209_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 8b42bf8c3f60..8dbad58628a1 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -168,6 +168,7 @@ static const struct adis_data adis16209_data = { .diag_stat_reg = ADIS16209_DIAG_STAT, .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, + .self_test_no_autoclear = true, .startup_delay = ADIS16209_STARTUP_DELAY, .status_error_msgs = adis16209_status_error_msgs, -- GitLab From 87a048ef959dc72148196141f0b8b6ff71991ac9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 15 Apr 2016 16:59:42 +0200 Subject: [PATCH 3125/9938] staging:iio:adis16240: Set self_test_no_autoclear flag The ADIS16201 does not automatically clear the self test flag bit the self test has been, so clear it manually. Otherwise we'll see a offset caused by the self-test bias on the output values during normal operation. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16240_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index a425e1894863..d5b99e610d08 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -222,6 +222,7 @@ static const struct adis_data adis16240_data = { .diag_stat_reg = ADIS16240_DIAG_STAT, .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN, + .self_test_no_autoclear = true, .startup_delay = ADIS16240_STARTUP_DELAY, .status_error_msgs = adis16240_status_error_msgs, -- GitLab From ccd62a896ffe3dbd60f3b7570a2b74e4fe030ed6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 16 Apr 2016 09:36:32 -0300 Subject: [PATCH 3126/9938] perf trace: Fix build when DWARF unwind isn't available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable is initialized and then conditionally set to a different value, but not used when DWARF unwinding is not available, bummer, write 1000 times: "Run make -C tools/perf build-test"... builtin-trace.c: In function ‘cmd_trace’: builtin-trace.c:3112:6: error: variable ‘max_stack_user_set’ set but not used [-Werror=unused-but-set-variable] bool max_stack_user_set = true; ^ cc1: all warnings being treated as err Fix it by marking it as __maybe_unused. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Fixes: 056149932602 ("perf trace: Make --(min,max}-stack imply "--call-graph dwarf"") Link: http://lkml.kernel.org/n/tip-85r40c5hhv6jnmph77l1hgsr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 026ec0c749b0..0e3c1cecef1b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3109,7 +3109,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) "per thread proc mmap processing timeout in ms"), OPT_END() }; - bool max_stack_user_set = true; + bool __maybe_unused max_stack_user_set = true; bool mmap_pages_user_set = true; const char * const trace_subcommands[] = { "record", NULL }; int err; -- GitLab From 101ca9ccdd30c46afc5c9a30e7acdcbeaa330fa1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 14 Apr 2016 11:08:11 +0200 Subject: [PATCH 3127/9938] serial: doc: .break_ctl() may sleep break_ctl() is not called from any sort of atomic context, so there is no problem with it sleeping. Reported-by: Peter Hurley Signed-off-by: Geert Uytterhoeven Signed-off-by: Jonathan Corbet --- Documentation/serial/driver | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/serial/driver b/Documentation/serial/driver index 7fb80682e394..39701515832b 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -187,7 +187,6 @@ hardware. ctl. Locking: caller holds port->mutex - This call must not sleep startup(port) Grab any interrupt resources and initialise any low level driver -- GitLab From ad0de1e3fe9aacbf110052bcc1765c877e69858f Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Sat, 16 Apr 2016 09:18:46 +0900 Subject: [PATCH 3128/9938] Documentatio: HOWTO: remove regression postings info from translations Obsolete info about regression postings were removed by commit 5645a717c6ee61e67d38aa9f15cb9db074e1e99d ("Documentation: HOWTO: remove obsolete info about regression postings") but not applied to translations. This commit applies the change to translations. Signed-off-by: SeongJae Park Signed-off-by: Jonathan Corbet --- Documentation/ja_JP/HOWTO | 6 ------ Documentation/ko_KR/HOWTO | 2 -- Documentation/zh_CN/HOWTO | 2 -- 3 files changed, 10 deletions(-) diff --git a/Documentation/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO index 52ef02b33da9..581c14bdd7be 100644 --- a/Documentation/ja_JP/HOWTO +++ b/Documentation/ja_JP/HOWTO @@ -290,12 +290,6 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン - このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま す。このプロセスはだいたい 6週間継続します。 - - 各リリースでの既知の後戻り問題(regression: このリリースの中で新規 - に作り込まれた問題を指す) はその都度 Linux-kernel メーリングリスト - に投稿されます。ゴールとしては、カーネルが 「準備ができた」と宣言 - する前にこのリストの長さをゼロに減らすことですが、現実には、数個の - 後戻り問題がリリース時にたびたび残ってしまいます。 - Andrew Morton が Linux-kernel メーリングリストにカーネルリリースについ て書いたことをここで言っておくことは価値があります- 「カーネルがいつリリースされるかは誰も知りません。なぜなら、これは現 diff --git a/Documentation/ko_KR/HOWTO b/Documentation/ko_KR/HOWTO index 5a81b394b3b5..46b22395748d 100644 --- a/Documentation/ko_KR/HOWTO +++ b/Documentation/ko_KR/HOWTO @@ -253,8 +253,6 @@ Documentation/DocBook/ 디렉토리 내에서 만들어지며 PDF, Postscript, H 것이다. - 이러한 프로세스는 커널이 "준비(ready)"되었다고 여겨질때까지 계속된다. 프로세스는 대체로 6주간 지속된다. - - 각 -rc 배포에 있는 알려진 회귀의 목록들은 다음 URI에 남겨진다. - http://kernelnewbies.org/known_regressions 커널 배포에 있어서 언급할만한 가치가 있는 리눅스 커널 메일링 리스트의 Andrew Morton의 글이 있다. diff --git a/Documentation/zh_CN/HOWTO b/Documentation/zh_CN/HOWTO index 54ea24ff63c7..56ca786e5842 100644 --- a/Documentation/zh_CN/HOWTO +++ b/Documentation/zh_CN/HOWTO @@ -218,8 +218,6 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循 时,一个新的-rc版本就会被发布。计划是每周都发布新的-rc版本。 - 这个过程一直持续下去直到内核被认为达到足够稳定的状态,持续时间大概是 6个星期。 - - 以下地址跟踪了在每个-rc发布中发现的退步列表: - http://kernelnewbies.org/known_regressions 关于内核发布,值得一提的是Andrew Morton在linux-kernel邮件列表中如是说: “没有人知道新内核何时会被发布,因为发布是根据已知bug的情况来决定 -- GitLab From 78f3873decadde42da6edf419635b5972ae61e00 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Sat, 16 Apr 2016 09:32:30 +0900 Subject: [PATCH 3129/9938] Documentation: HOWTO: update git home URL in translations Homepage url of git in HOWTO document was updated by commit e234ebf7881c013b654113f0a208977ac3ce1d01 ("Documentation/HOWTO: update git home URL") but not applied to several translations. This commit updates them. Signed-off-by: SeongJae Park Signed-off-by: Jonathan Corbet --- Documentation/ko_KR/HOWTO | 6 +++--- Documentation/zh_CN/HOWTO | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/ko_KR/HOWTO b/Documentation/ko_KR/HOWTO index 46b22395748d..9a3e65924d54 100644 --- a/Documentation/ko_KR/HOWTO +++ b/Documentation/ko_KR/HOWTO @@ -236,9 +236,9 @@ Documentation/DocBook/ 디렉토리 내에서 만들어지며 PDF, Postscript, H - 새로운 커널이 배포되자마자 2주의 시간이 주어진다. 이 기간동은 메인테이너들은 큰 diff들을 Linus에게 제출할 수 있다. 대개 이 패치들은 몇 주 동안 -next 커널내에 이미 있었던 것들이다. 큰 변경들을 제출하는 데 - 선호되는 방법은 git(커널의 소스 관리 툴, 더 많은 정보들은 http://git.or.cz/ - 에서 참조할 수 있다)를 사용하는 것이지만 순수한 패치파일의 형식으로 보내는 - 것도 무관하다. + 선호되는 방법은 git(커널의 소스 관리 툴, 더 많은 정보들은 + http://git-scm.com/ 에서 참조할 수 있다)를 사용하는 것이지만 순수한 + 패치파일의 형식으로 보내는 것도 무관하다. - 2주 후에 -rc1 커널이 배포되며 지금부터는 전체 커널의 안정성에 영향을 미칠수 있는 새로운 기능들을 포함하지 않는 패치들만이 추가될 수 있다. 완전히 새로운 드라이버(혹은 파일시스템)는 -rc1 이후에만 받아들여진다는 diff --git a/Documentation/zh_CN/HOWTO b/Documentation/zh_CN/HOWTO index 56ca786e5842..f0613b92e0be 100644 --- a/Documentation/zh_CN/HOWTO +++ b/Documentation/zh_CN/HOWTO @@ -207,7 +207,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循 - 每当一个新版本的内核被发布,为期两周的集成窗口将被打开。在这段时间里 维护者可以向Linus提交大段的修改,通常这些修改已经被放到-mm内核中几个 星期了。提交大量修改的首选方式是使用git工具(内核的代码版本管理工具 - ,更多的信息可以在http://git.or.cz/获取),不过使用普通补丁也是可以 + ,更多的信息可以在http://git-scm.com/获取),不过使用普通补丁也是可以 的。 - 两个星期以后-rc1版本内核发布。之后只有不包含可能影响整个内核稳定性的 新功能的补丁才可能被接受。请注意一个全新的驱动程序(或者文件系统)有 -- GitLab From aa0eb886be79eb785bf675bd8031ec1611d3295a Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 10 Apr 2016 21:20:56 +0200 Subject: [PATCH 3130/9938] iio: adc: Indent if statement Indent lines inside if statement. Signed-off-by: Ksenija Stanojevic Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mxs-lradc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c index 33051b87aac2..07287afa5bd3 100644 --- a/drivers/iio/adc/mxs-lradc.c +++ b/drivers/iio/adc/mxs-lradc.c @@ -1500,9 +1500,10 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, LRADC_CTRL0); - if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) - mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, - LRADC_CTRL0); + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) + mxs_lradc_reg_set(lradc, + LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); } /* Start internal temperature sensing. */ -- GitLab From 1f0477f18306c018a954e4f333690a9d0f7efc76 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 11 Apr 2016 14:12:04 +0200 Subject: [PATCH 3131/9938] iio: light: new driver for the ROHM BH1780 This is a reimplementation of the old misc device driver for the ROHM BH1780 ambient light sensor (drivers/misc/bh1780gli.c). Differences from the old driver: - Uses the IIO framework - Uses runtime PM to idle the hardware after 5 seconds - No weird custom power management from userspace - No homebrewn values in sysfs This uses the same (undocumented) device tree compatible-string as the old driver ("rohm,bh1780gli"). Cc: Arnd Bergmann Cc: Ulf Hansson Cc: Daniel Mack Cc: Peter Meerwald-Stadler Signed-off-by: Linus Walleij Reviewed-by: Ulf Hansson Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 11 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/bh1780.c | 297 +++++++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 drivers/iio/light/bh1780.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index cfd3df8416bb..5ee1d453b3d8 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -73,6 +73,17 @@ config BH1750 To compile this driver as a module, choose M here: the module will be called bh1750. +config BH1780 + tristate "ROHM BH1780 ambient light sensor" + depends on I2C + depends on !SENSORS_BH1780 + help + Say Y here to build support for the ROHM BH1780GLI ambient + light sensor. + + To compile this driver as a module, choose M here: the module will + be called bh1780. + config CM32181 depends on I2C tristate "CM32181 driver" diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index b2c31053db0c..4aeee2bd8f49 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AL3320A) += al3320a.o obj-$(CONFIG_APDS9300) += apds9300.o obj-$(CONFIG_APDS9960) += apds9960.o obj-$(CONFIG_BH1750) += bh1750.o +obj-$(CONFIG_BH1780) += bh1780.o obj-$(CONFIG_CM32181) += cm32181.o obj-$(CONFIG_CM3232) += cm3232.o obj-$(CONFIG_CM3323) += cm3323.o diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c new file mode 100644 index 000000000000..72b364e4aa72 --- /dev/null +++ b/drivers/iio/light/bh1780.c @@ -0,0 +1,297 @@ +/* + * ROHM 1780GLI Ambient Light Sensor Driver + * + * Copyright (C) 2016 Linaro Ltd. + * Author: Linus Walleij + * Loosely based on the previous BH1780 ALS misc driver + * Copyright (C) 2010 Texas Instruments + * Author: Hemanth V + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BH1780_CMD_BIT BIT(7) +#define BH1780_REG_CONTROL 0x00 +#define BH1780_REG_PARTID 0x0A +#define BH1780_REG_MANFID 0x0B +#define BH1780_REG_DLOW 0x0C +#define BH1780_REG_DHIGH 0x0D + +#define BH1780_REVMASK GENMASK(3,0) +#define BH1780_POWMASK GENMASK(1,0) +#define BH1780_POFF (0x0) +#define BH1780_PON (0x3) + +/* power on settling time in ms */ +#define BH1780_PON_DELAY 2 +/* max time before value available in ms */ +#define BH1780_INTERVAL 250 + +struct bh1780_data { + struct i2c_client *client; +}; + +static int bh1780_write(struct bh1780_data *bh1780, u8 reg, u8 val) +{ + int ret = i2c_smbus_write_byte_data(bh1780->client, + BH1780_CMD_BIT | reg, + val); + if (ret < 0) + dev_err(&bh1780->client->dev, + "i2c_smbus_write_byte_data failed error " + "%d, register %01x\n", + ret, reg); + return ret; +} + +static int bh1780_read(struct bh1780_data *bh1780, u8 reg) +{ + int ret = i2c_smbus_read_byte_data(bh1780->client, + BH1780_CMD_BIT | reg); + if (ret < 0) + dev_err(&bh1780->client->dev, + "i2c_smbus_read_byte_data failed error " + "%d, register %01x\n", + ret, reg); + return ret; +} + +static int bh1780_read_word(struct bh1780_data *bh1780, u8 reg) +{ + int ret = i2c_smbus_read_word_data(bh1780->client, + BH1780_CMD_BIT | reg); + if (ret < 0) + dev_err(&bh1780->client->dev, + "i2c_smbus_read_word_data failed error " + "%d, register %01x\n", + ret, reg); + return ret; +} + +static int bh1780_debugfs_reg_access(struct iio_dev *indio_dev, + unsigned int reg, unsigned int writeval, + unsigned int *readval) +{ + struct bh1780_data *bh1780 = iio_priv(indio_dev); + int ret; + + if (!readval) + bh1780_write(bh1780, (u8)reg, (u8)writeval); + + ret = bh1780_read(bh1780, (u8)reg); + if (ret < 0) + return ret; + + *readval = ret; + + return 0; +} + +static int bh1780_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct bh1780_data *bh1780 = iio_priv(indio_dev); + int value; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_LIGHT: + pm_runtime_get_sync(&bh1780->client->dev); + value = bh1780_read_word(bh1780, BH1780_REG_DLOW); + if (value < 0) + return value; + pm_runtime_mark_last_busy(&bh1780->client->dev); + pm_runtime_put_autosuspend(&bh1780->client->dev); + *val = value; + + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_INT_TIME: + *val = 0; + *val2 = BH1780_INTERVAL * 1000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static const struct iio_info bh1780_info = { + .driver_module = THIS_MODULE, + .read_raw = bh1780_read_raw, + .debugfs_reg_access = bh1780_debugfs_reg_access, +}; + +static const struct iio_chan_spec bh1780_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) + } +}; + +static int bh1780_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct bh1780_data *bh1780; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct iio_dev *indio_dev; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) + return -EIO; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1780)); + if (!indio_dev) + return -ENOMEM; + + bh1780 = iio_priv(indio_dev); + bh1780->client = client; + i2c_set_clientdata(client, indio_dev); + + /* Power up the device */ + ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON); + if (ret < 0) + return ret; + msleep(BH1780_PON_DELAY); + pm_runtime_get_noresume(&client->dev); + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + + ret = bh1780_read(bh1780, BH1780_REG_PARTID); + if (ret < 0) + goto out_disable_pm; + dev_info(&client->dev, + "Ambient Light Sensor, Rev : %lu\n", + (ret & BH1780_REVMASK)); + + /* + * As the device takes 250 ms to even come up with a fresh + * measurement after power-on, do not shut it down unnecessarily. + * Set autosuspend to a five seconds. + */ + pm_runtime_set_autosuspend_delay(&client->dev, 5000); + pm_runtime_use_autosuspend(&client->dev); + pm_runtime_put(&client->dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &bh1780_info; + indio_dev->name = id->name; + indio_dev->channels = bh1780_channels; + indio_dev->num_channels = ARRAY_SIZE(bh1780_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(indio_dev); + if (ret) + goto out_disable_pm; + return 0; + +out_disable_pm: + pm_runtime_put_noidle(&client->dev); + pm_runtime_disable(&client->dev); + return ret; +} + +static int bh1780_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct bh1780_data *bh1780 = iio_priv(indio_dev); + int ret; + + iio_device_unregister(indio_dev); + pm_runtime_get_sync(&client->dev); + pm_runtime_put_noidle(&client->dev); + pm_runtime_disable(&client->dev); + ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF); + if (ret < 0) { + dev_err(&client->dev, "failed to power off\n"); + return ret; + } + + return 0; +} + +#ifdef CONFIG_PM +static int bh1780_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct bh1780_data *bh1780 = i2c_get_clientdata(client); + int ret; + + ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF); + if (ret < 0) { + dev_err(dev, "failed to runtime suspend\n"); + return ret; + } + + return 0; +} + +static int bh1780_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct bh1780_data *bh1780 = i2c_get_clientdata(client); + int ret; + + ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON); + if (ret < 0) { + dev_err(dev, "failed to runtime resume\n"); + return ret; + } + + /* Wait for power on, then for a value to be available */ + msleep(BH1780_PON_DELAY + BH1780_INTERVAL); + + return 0; +} +#endif /* CONFIG_PM */ + +static const struct dev_pm_ops bh1780_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(bh1780_runtime_suspend, + bh1780_runtime_resume, NULL) +}; + +static const struct i2c_device_id bh1780_id[] = { + { "bh1780", 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, bh1780_id); + +#ifdef CONFIG_OF +static const struct of_device_id of_bh1780_match[] = { + { .compatible = "rohm,bh1780gli", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_bh1780_match); +#endif + +static struct i2c_driver bh1780_driver = { + .probe = bh1780_probe, + .remove = bh1780_remove, + .id_table = bh1780_id, + .driver = { + .name = "bh1780", + .pm = &bh1780_dev_pm_ops, + .of_match_table = of_match_ptr(of_bh1780_match), + }, +}; + +module_i2c_driver(bh1780_driver); + +MODULE_DESCRIPTION("ROHM BH1780GLI Ambient Light Sensor Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linus Walleij "); -- GitLab From 5057e8e07f2521649eb444492433f419f93de37a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 11 Apr 2016 11:57:17 -0700 Subject: [PATCH 3132/9938] eeprom: at24: remove a reduntant if The second check for I2C_FUNC_I2C is reduntant, so remove it. Signed-off-by: Bartosz Golaszewski [wsa: reworded commit message] Signed-off-by: Wolfram Sang --- drivers/misc/eeprom/at24.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 089d6943f68a..001a9af8e36c 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -544,10 +544,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) } else { return -EPFNOSUPPORT; } - } - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA; -- GitLab From 1d98d0ec0ef3594901c2356773c191304703f17e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 11 Apr 2016 11:57:21 -0700 Subject: [PATCH 3133/9938] eeprom: at24: replace msleep() with usleep_range() We cannot expect msleep(1) to actually sleep for a period shorter than 20 ms. Replace all calls to msleep() with usleep_range(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Wolfram Sang --- drivers/misc/eeprom/at24.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 001a9af8e36c..6cc17b7779a5 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -245,8 +245,7 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, if (status == count) return count; - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); + usleep_range(1000, 1500); } while (time_before(read_time, timeout)); return -ETIMEDOUT; @@ -365,8 +364,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, if (status == count) return count; - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); + usleep_range(1000, 1500); } while (time_before(write_time, timeout)); return -ETIMEDOUT; -- GitLab From 0412bd931f5f94d1054e958415c4a945d8ee62f4 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 8 Apr 2016 22:55:01 +0200 Subject: [PATCH 3134/9938] vxlan: synchronously and race-free destruction of vxlan sockets Due to the fact that the udp socket is destructed asynchronously in a work queue, we have some nondeterministic behavior during shutdown of vxlan tunnels and creating new ones. Fix this by keeping the destruction process synchronous in regards to the user space process so IFF_UP can be reliably set. udp_tunnel_sock_release destroys vs->sock->sk if reference counter indicates so. We expect to have the same lifetime of vxlan_sock and vxlan_sock->sock->sk even in fast paths with only rcu locks held. So only destruct the whole socket after we can be sure it cannot be found by searching vxlan_net->sock_list. Cc: Eric Dumazet Cc: Jiri Benc Cc: Marcelo Ricardo Leitner Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 20 +++----------------- include/net/vxlan.h | 2 -- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 7f697a3f00a4..19383371a27d 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -98,7 +98,6 @@ struct vxlan_fdb { /* salt for hash table */ static u32 vxlan_salt __read_mostly; -static struct workqueue_struct *vxlan_wq; static inline bool vxlan_collect_metadata(struct vxlan_sock *vs) { @@ -1053,7 +1052,9 @@ static void __vxlan_sock_release(struct vxlan_sock *vs) vxlan_notify_del_rx_port(vs); spin_unlock(&vn->sock_lock); - queue_work(vxlan_wq, &vs->del_work); + synchronize_net(); + udp_tunnel_sock_release(vs->sock); + kfree(vs); } static void vxlan_sock_release(struct vxlan_dev *vxlan) @@ -2674,13 +2675,6 @@ static const struct ethtool_ops vxlan_ethtool_ops = { .get_link = ethtool_op_get_link, }; -static void vxlan_del_work(struct work_struct *work) -{ - struct vxlan_sock *vs = container_of(work, struct vxlan_sock, del_work); - udp_tunnel_sock_release(vs->sock); - kfree_rcu(vs, rcu); -} - static struct socket *vxlan_create_sock(struct net *net, bool ipv6, __be16 port, u32 flags) { @@ -2726,8 +2720,6 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6, for (h = 0; h < VNI_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vs->vni_list[h]); - INIT_WORK(&vs->del_work, vxlan_del_work); - sock = vxlan_create_sock(net, ipv6, port, flags); if (IS_ERR(sock)) { pr_info("Cannot bind port %d, err=%ld\n", ntohs(port), @@ -3346,10 +3338,6 @@ static int __init vxlan_init_module(void) { int rc; - vxlan_wq = alloc_workqueue("vxlan", 0, 0); - if (!vxlan_wq) - return -ENOMEM; - get_random_bytes(&vxlan_salt, sizeof(vxlan_salt)); rc = register_pernet_subsys(&vxlan_net_ops); @@ -3370,7 +3358,6 @@ static int __init vxlan_init_module(void) out2: unregister_pernet_subsys(&vxlan_net_ops); out1: - destroy_workqueue(vxlan_wq); return rc; } late_initcall(vxlan_init_module); @@ -3379,7 +3366,6 @@ static void __exit vxlan_cleanup_module(void) { rtnl_link_unregister(&vxlan_link_ops); unregister_netdevice_notifier(&vxlan_notifier_block); - destroy_workqueue(vxlan_wq); unregister_pernet_subsys(&vxlan_net_ops); /* rcu_barrier() is called by netns */ } diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 2f168f0ea32c..d442eb3129cd 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -184,9 +184,7 @@ struct vxlan_metadata { /* per UDP socket information */ struct vxlan_sock { struct hlist_node hlist; - struct work_struct del_work; struct socket *sock; - struct rcu_head rcu; struct hlist_head vni_list[VNI_HASH_SIZE]; atomic_t refcnt; u32 flags; -- GitLab From 544a773a01828e3cc3b553721f68d880d0d27a97 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sat, 9 Apr 2016 12:46:23 +0200 Subject: [PATCH 3135/9938] vxlan: reduce usage of synchronize_net in ndo_stop We only need to do the synchronize_net dance once for both, ipv4 and ipv6 sockets, thus removing one synchronize_net in case both sockets get dismantled. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 19383371a27d..a7112b3bc9b4 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1037,14 +1037,14 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev) return false; } -static void __vxlan_sock_release(struct vxlan_sock *vs) +static bool __vxlan_sock_release_prep(struct vxlan_sock *vs) { struct vxlan_net *vn; if (!vs) - return; + return false; if (!atomic_dec_and_test(&vs->refcnt)) - return; + return false; vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id); spin_lock(&vn->sock_lock); @@ -1052,16 +1052,28 @@ static void __vxlan_sock_release(struct vxlan_sock *vs) vxlan_notify_del_rx_port(vs); spin_unlock(&vn->sock_lock); - synchronize_net(); - udp_tunnel_sock_release(vs->sock); - kfree(vs); + return true; } static void vxlan_sock_release(struct vxlan_dev *vxlan) { - __vxlan_sock_release(vxlan->vn4_sock); + bool ipv4 = __vxlan_sock_release_prep(vxlan->vn4_sock); #if IS_ENABLED(CONFIG_IPV6) - __vxlan_sock_release(vxlan->vn6_sock); + bool ipv6 = __vxlan_sock_release_prep(vxlan->vn6_sock); +#endif + + synchronize_net(); + + if (ipv4) { + udp_tunnel_sock_release(vxlan->vn4_sock->sock); + kfree(vxlan->vn4_sock); + } + +#if IS_ENABLED(CONFIG_IPV6) + if (ipv6) { + udp_tunnel_sock_release(vxlan->vn6_sock->sock); + kfree(vxlan->vn6_sock); + } #endif } -- GitLab From d6586d2ef4608f113df16ca8ca757563891389ce Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 15 Apr 2016 00:11:29 +0900 Subject: [PATCH 3136/9938] net: w5100: move mmiowb into register access callbacks Instead of sprinkle mmiowb over the driver code, move it into primary register write callbacks. (w5100_write, w5100_write16, w5100_writebuf) This is a preparation for supporting SPI interface which doesn't use MMIO for accessing w5100 registers. Signed-off-by: Akinobu Mita Cc: Mike Sinkovsky Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ethernet/wiznet/w5100.c | 44 ++++++++++------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index 8b282d0b169c..f4b7200bc0f5 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -122,10 +122,17 @@ static inline u8 w5100_read_direct(struct w5100_priv *priv, u16 addr) return ioread8(priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT)); } +static inline void __w5100_write_direct(struct w5100_priv *priv, u16 addr, + u8 data) +{ + iowrite8(data, priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT)); +} + static inline void w5100_write_direct(struct w5100_priv *priv, u16 addr, u8 data) { - iowrite8(data, priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT)); + __w5100_write_direct(priv, addr, data); + mmiowb(); } static u16 w5100_read16_direct(struct w5100_priv *priv, u16 addr) @@ -138,8 +145,9 @@ static u16 w5100_read16_direct(struct w5100_priv *priv, u16 addr) static void w5100_write16_direct(struct w5100_priv *priv, u16 addr, u16 data) { - w5100_write_direct(priv, addr, data >> 8); - w5100_write_direct(priv, addr + 1, data); + __w5100_write_direct(priv, addr, data >> 8); + __w5100_write_direct(priv, addr + 1, data); + mmiowb(); } static void w5100_readbuf_direct(struct w5100_priv *priv, @@ -164,8 +172,9 @@ static void w5100_writebuf_direct(struct w5100_priv *priv, for (i = 0; i < len; i++, addr++) { if (unlikely(addr > W5100_TX_MEM_END)) addr = W5100_TX_MEM_START; - w5100_write_direct(priv, addr, *buf++); + __w5100_write_direct(priv, addr, *buf++); } + mmiowb(); } /* @@ -186,7 +195,6 @@ static u8 w5100_read_indirect(struct w5100_priv *priv, u16 addr) spin_lock_irqsave(&priv->reg_lock, flags); w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); data = w5100_read_direct(priv, W5100_IDM_DR); spin_unlock_irqrestore(&priv->reg_lock, flags); @@ -199,9 +207,7 @@ static void w5100_write_indirect(struct w5100_priv *priv, u16 addr, u8 data) spin_lock_irqsave(&priv->reg_lock, flags); w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); w5100_write_direct(priv, W5100_IDM_DR, data); - mmiowb(); spin_unlock_irqrestore(&priv->reg_lock, flags); } @@ -212,7 +218,6 @@ static u16 w5100_read16_indirect(struct w5100_priv *priv, u16 addr) spin_lock_irqsave(&priv->reg_lock, flags); w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); data = w5100_read_direct(priv, W5100_IDM_DR) << 8; data |= w5100_read_direct(priv, W5100_IDM_DR); spin_unlock_irqrestore(&priv->reg_lock, flags); @@ -226,10 +231,8 @@ static void w5100_write16_indirect(struct w5100_priv *priv, u16 addr, u16 data) spin_lock_irqsave(&priv->reg_lock, flags); w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); - w5100_write_direct(priv, W5100_IDM_DR, data >> 8); + __w5100_write_direct(priv, W5100_IDM_DR, data >> 8); w5100_write_direct(priv, W5100_IDM_DR, data); - mmiowb(); spin_unlock_irqrestore(&priv->reg_lock, flags); } @@ -242,13 +245,11 @@ static void w5100_readbuf_indirect(struct w5100_priv *priv, spin_lock_irqsave(&priv->reg_lock, flags); w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); for (i = 0; i < len; i++, addr++) { if (unlikely(addr > W5100_RX_MEM_END)) { addr = W5100_RX_MEM_START; w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); } *buf++ = w5100_read_direct(priv, W5100_IDM_DR); } @@ -265,15 +266,13 @@ static void w5100_writebuf_indirect(struct w5100_priv *priv, spin_lock_irqsave(&priv->reg_lock, flags); w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); for (i = 0; i < len; i++, addr++) { if (unlikely(addr > W5100_TX_MEM_END)) { addr = W5100_TX_MEM_START; w5100_write16_direct(priv, W5100_IDM_AR, addr); - mmiowb(); } - w5100_write_direct(priv, W5100_IDM_DR, *buf++); + __w5100_write_direct(priv, W5100_IDM_DR, *buf++); } mmiowb(); spin_unlock_irqrestore(&priv->reg_lock, flags); @@ -309,7 +308,6 @@ static int w5100_command(struct w5100_priv *priv, u16 cmd) unsigned long timeout = jiffies + msecs_to_jiffies(100); w5100_write(priv, W5100_S0_CR, cmd); - mmiowb(); while (w5100_read(priv, W5100_S0_CR) != 0) { if (time_after(jiffies, timeout)) @@ -327,18 +325,15 @@ static void w5100_write_macaddr(struct w5100_priv *priv) for (i = 0; i < ETH_ALEN; i++) w5100_write(priv, W5100_SHAR + i, ndev->dev_addr[i]); - mmiowb(); } static void w5100_hw_reset(struct w5100_priv *priv) { w5100_write_direct(priv, W5100_MR, MR_RST); - mmiowb(); mdelay(5); w5100_write_direct(priv, W5100_MR, priv->indirect ? MR_PB | MR_AI | MR_IND : MR_PB); - mmiowb(); w5100_write(priv, W5100_IMR, 0); w5100_write_macaddr(priv); @@ -347,23 +342,19 @@ static void w5100_hw_reset(struct w5100_priv *priv) */ w5100_write(priv, W5100_RMSR, 0x03); w5100_write(priv, W5100_TMSR, 0x03); - mmiowb(); } static void w5100_hw_start(struct w5100_priv *priv) { w5100_write(priv, W5100_S0_MR, priv->promisc ? S0_MR_MACRAW : S0_MR_MACRAW_MF); - mmiowb(); w5100_command(priv, S0_CR_OPEN); w5100_write(priv, W5100_IMR, IR_S0); - mmiowb(); } static void w5100_hw_close(struct w5100_priv *priv) { w5100_write(priv, W5100_IMR, 0); - mmiowb(); w5100_command(priv, S0_CR_CLOSE); } @@ -447,7 +438,6 @@ static int w5100_start_tx(struct sk_buff *skb, struct net_device *ndev) offset = w5100_read16(priv, W5100_S0_TX_WR); w5100_writebuf(priv, offset, skb->data, skb->len); w5100_write16(priv, W5100_S0_TX_WR, offset + skb->len); - mmiowb(); ndev->stats.tx_bytes += skb->len; ndev->stats.tx_packets++; dev_kfree_skb(skb); @@ -488,7 +478,6 @@ static int w5100_napi_poll(struct napi_struct *napi, int budget) skb_put(skb, rx_len); w5100_readbuf(priv, offset + 2, skb->data, rx_len); w5100_write16(priv, W5100_S0_RX_RD, offset + 2 + rx_len); - mmiowb(); w5100_command(priv, S0_CR_RECV); skb->protocol = eth_type_trans(skb, ndev); @@ -500,7 +489,6 @@ static int w5100_napi_poll(struct napi_struct *napi, int budget) if (rx_count < budget) { napi_complete(napi); w5100_write(priv, W5100_IMR, IR_S0); - mmiowb(); } return rx_count; @@ -515,7 +503,6 @@ static irqreturn_t w5100_interrupt(int irq, void *ndev_instance) if (!ir) return IRQ_NONE; w5100_write(priv, W5100_S0_IR, ir); - mmiowb(); if (ir & S0_IR_SENDOK) { netif_dbg(priv, tx_done, ndev, "tx done\n"); @@ -525,7 +512,6 @@ static irqreturn_t w5100_interrupt(int irq, void *ndev_instance) if (ir & S0_IR_RECV) { if (napi_schedule_prep(&priv->napi)) { w5100_write(priv, W5100_IMR, 0); - mmiowb(); __napi_schedule(&priv->napi); } } -- GitLab From 850576cfede986f0683bed25e34bc15712ffb463 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 15 Apr 2016 00:11:30 +0900 Subject: [PATCH 3137/9938] net: w5100: add ability to support other bus interface The w5100 driver currently only supports direct and indirect bus interface mode which use MMIO space for accessing w5100 registers. In order to support SPI interface mode which is supported by W5100 chip, this makes the bus interface abstraction layer more generic so that separated w5100-spi driver can use w5100 driver as core module. Signed-off-by: Akinobu Mita Cc: Mike Sinkovsky Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ethernet/wiznet/w5100.c | 604 +++++++++++++++++++--------- drivers/net/ethernet/wiznet/w5100.h | 28 ++ 2 files changed, 431 insertions(+), 201 deletions(-) create mode 100644 drivers/net/ethernet/wiznet/w5100.h diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index f4b7200bc0f5..89cba6741e7f 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -27,6 +27,8 @@ #include #include +#include "w5100.h" + #define DRV_NAME "w5100" #define DRV_VERSION "2012-04-04" @@ -76,25 +78,16 @@ MODULE_LICENSE("GPL"); #define W5100_S0_REGS_LEN 0x0040 #define W5100_TX_MEM_START 0x4000 -#define W5100_TX_MEM_END 0x5fff -#define W5100_TX_MEM_MASK 0x1fff +#define W5100_TX_MEM_SIZE 0x2000 #define W5100_RX_MEM_START 0x6000 -#define W5100_RX_MEM_END 0x7fff -#define W5100_RX_MEM_MASK 0x1fff +#define W5100_RX_MEM_SIZE 0x2000 /* * Device driver private data structure */ + struct w5100_priv { - void __iomem *base; - spinlock_t reg_lock; - bool indirect; - u8 (*read)(struct w5100_priv *priv, u16 addr); - void (*write)(struct w5100_priv *priv, u16 addr, u8 data); - u16 (*read16)(struct w5100_priv *priv, u16 addr); - void (*write16)(struct w5100_priv *priv, u16 addr, u16 data); - void (*readbuf)(struct w5100_priv *priv, u16 addr, u8 *buf, int len); - void (*writebuf)(struct w5100_priv *priv, u16 addr, u8 *buf, int len); + const struct w5100_ops *ops; int irq; int link_irq; int link_gpio; @@ -111,72 +104,121 @@ struct w5100_priv { * ***********************************************************************/ +struct w5100_mmio_priv { + void __iomem *base; + /* Serialize access in indirect address mode */ + spinlock_t reg_lock; +}; + +static inline struct w5100_mmio_priv *w5100_mmio_priv(struct net_device *dev) +{ + return w5100_ops_priv(dev); +} + +static inline void __iomem *w5100_mmio(struct net_device *ndev) +{ + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); + + return mmio_priv->base; +} + /* * In direct address mode host system can directly access W5100 registers * after mapping to Memory-Mapped I/O space. * * 0x8000 bytes are required for memory space. */ -static inline u8 w5100_read_direct(struct w5100_priv *priv, u16 addr) +static inline int w5100_read_direct(struct net_device *ndev, u16 addr) { - return ioread8(priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT)); + return ioread8(w5100_mmio(ndev) + (addr << CONFIG_WIZNET_BUS_SHIFT)); } -static inline void __w5100_write_direct(struct w5100_priv *priv, u16 addr, - u8 data) +static inline int __w5100_write_direct(struct net_device *ndev, u16 addr, + u8 data) { - iowrite8(data, priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT)); + iowrite8(data, w5100_mmio(ndev) + (addr << CONFIG_WIZNET_BUS_SHIFT)); + + return 0; } -static inline void w5100_write_direct(struct w5100_priv *priv, - u16 addr, u8 data) +static inline int w5100_write_direct(struct net_device *ndev, u16 addr, u8 data) { - __w5100_write_direct(priv, addr, data); + __w5100_write_direct(ndev, addr, data); mmiowb(); + + return 0; } -static u16 w5100_read16_direct(struct w5100_priv *priv, u16 addr) +static int w5100_read16_direct(struct net_device *ndev, u16 addr) { u16 data; - data = w5100_read_direct(priv, addr) << 8; - data |= w5100_read_direct(priv, addr + 1); + data = w5100_read_direct(ndev, addr) << 8; + data |= w5100_read_direct(ndev, addr + 1); return data; } -static void w5100_write16_direct(struct w5100_priv *priv, u16 addr, u16 data) +static int w5100_write16_direct(struct net_device *ndev, u16 addr, u16 data) { - __w5100_write_direct(priv, addr, data >> 8); - __w5100_write_direct(priv, addr + 1, data); + __w5100_write_direct(ndev, addr, data >> 8); + __w5100_write_direct(ndev, addr + 1, data); mmiowb(); + + return 0; } -static void w5100_readbuf_direct(struct w5100_priv *priv, - u16 offset, u8 *buf, int len) +static int w5100_readbulk_direct(struct net_device *ndev, u16 addr, u8 *buf, + int len) { - u16 addr = W5100_RX_MEM_START + (offset & W5100_RX_MEM_MASK); int i; - for (i = 0; i < len; i++, addr++) { - if (unlikely(addr > W5100_RX_MEM_END)) - addr = W5100_RX_MEM_START; - *buf++ = w5100_read_direct(priv, addr); - } + for (i = 0; i < len; i++, addr++) + *buf++ = w5100_read_direct(ndev, addr); + + return 0; } -static void w5100_writebuf_direct(struct w5100_priv *priv, - u16 offset, u8 *buf, int len) +static int w5100_writebulk_direct(struct net_device *ndev, u16 addr, + const u8 *buf, int len) { - u16 addr = W5100_TX_MEM_START + (offset & W5100_TX_MEM_MASK); int i; - for (i = 0; i < len; i++, addr++) { - if (unlikely(addr > W5100_TX_MEM_END)) - addr = W5100_TX_MEM_START; - __w5100_write_direct(priv, addr, *buf++); - } + for (i = 0; i < len; i++, addr++) + __w5100_write_direct(ndev, addr, *buf++); + mmiowb(); + + return 0; +} + +static int w5100_mmio_init(struct net_device *ndev) +{ + struct platform_device *pdev = to_platform_device(ndev->dev.parent); + struct w5100_priv *priv = netdev_priv(ndev); + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); + struct resource *mem; + + spin_lock_init(&mmio_priv->reg_lock); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mmio_priv->base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(mmio_priv->base)) + return PTR_ERR(mmio_priv->base); + + netdev_info(ndev, "at 0x%llx irq %d\n", (u64)mem->start, priv->irq); + + return 0; } +static const struct w5100_ops w5100_mmio_direct_ops = { + .read = w5100_read_direct, + .write = w5100_write_direct, + .read16 = w5100_read16_direct, + .write16 = w5100_write16_direct, + .readbulk = w5100_readbulk_direct, + .writebulk = w5100_writebulk_direct, + .init = w5100_mmio_init, +}; + /* * In indirect address mode host system indirectly accesses registers by * using Indirect Mode Address Register (IDM_AR) and Indirect Mode Data @@ -188,121 +230,276 @@ static void w5100_writebuf_direct(struct w5100_priv *priv, #define W5100_IDM_AR 0x01 /* Indirect Mode Address Register */ #define W5100_IDM_DR 0x03 /* Indirect Mode Data Register */ -static u8 w5100_read_indirect(struct w5100_priv *priv, u16 addr) +static int w5100_read_indirect(struct net_device *ndev, u16 addr) { + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; u8 data; - spin_lock_irqsave(&priv->reg_lock, flags); - w5100_write16_direct(priv, W5100_IDM_AR, addr); - data = w5100_read_direct(priv, W5100_IDM_DR); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&mmio_priv->reg_lock, flags); + w5100_write16_direct(ndev, W5100_IDM_AR, addr); + data = w5100_read_direct(ndev, W5100_IDM_DR); + spin_unlock_irqrestore(&mmio_priv->reg_lock, flags); return data; } -static void w5100_write_indirect(struct w5100_priv *priv, u16 addr, u8 data) +static int w5100_write_indirect(struct net_device *ndev, u16 addr, u8 data) { + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - w5100_write16_direct(priv, W5100_IDM_AR, addr); - w5100_write_direct(priv, W5100_IDM_DR, data); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&mmio_priv->reg_lock, flags); + w5100_write16_direct(ndev, W5100_IDM_AR, addr); + w5100_write_direct(ndev, W5100_IDM_DR, data); + spin_unlock_irqrestore(&mmio_priv->reg_lock, flags); + + return 0; } -static u16 w5100_read16_indirect(struct w5100_priv *priv, u16 addr) +static int w5100_read16_indirect(struct net_device *ndev, u16 addr) { + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; u16 data; - spin_lock_irqsave(&priv->reg_lock, flags); - w5100_write16_direct(priv, W5100_IDM_AR, addr); - data = w5100_read_direct(priv, W5100_IDM_DR) << 8; - data |= w5100_read_direct(priv, W5100_IDM_DR); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&mmio_priv->reg_lock, flags); + w5100_write16_direct(ndev, W5100_IDM_AR, addr); + data = w5100_read_direct(ndev, W5100_IDM_DR) << 8; + data |= w5100_read_direct(ndev, W5100_IDM_DR); + spin_unlock_irqrestore(&mmio_priv->reg_lock, flags); return data; } -static void w5100_write16_indirect(struct w5100_priv *priv, u16 addr, u16 data) +static int w5100_write16_indirect(struct net_device *ndev, u16 addr, u16 data) { + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; - spin_lock_irqsave(&priv->reg_lock, flags); - w5100_write16_direct(priv, W5100_IDM_AR, addr); - __w5100_write_direct(priv, W5100_IDM_DR, data >> 8); - w5100_write_direct(priv, W5100_IDM_DR, data); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_lock_irqsave(&mmio_priv->reg_lock, flags); + w5100_write16_direct(ndev, W5100_IDM_AR, addr); + __w5100_write_direct(ndev, W5100_IDM_DR, data >> 8); + w5100_write_direct(ndev, W5100_IDM_DR, data); + spin_unlock_irqrestore(&mmio_priv->reg_lock, flags); + + return 0; } -static void w5100_readbuf_indirect(struct w5100_priv *priv, - u16 offset, u8 *buf, int len) +static int w5100_readbulk_indirect(struct net_device *ndev, u16 addr, u8 *buf, + int len) { - u16 addr = W5100_RX_MEM_START + (offset & W5100_RX_MEM_MASK); + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; int i; - spin_lock_irqsave(&priv->reg_lock, flags); - w5100_write16_direct(priv, W5100_IDM_AR, addr); + spin_lock_irqsave(&mmio_priv->reg_lock, flags); + w5100_write16_direct(ndev, W5100_IDM_AR, addr); + + for (i = 0; i < len; i++) + *buf++ = w5100_read_direct(ndev, W5100_IDM_DR); - for (i = 0; i < len; i++, addr++) { - if (unlikely(addr > W5100_RX_MEM_END)) { - addr = W5100_RX_MEM_START; - w5100_write16_direct(priv, W5100_IDM_AR, addr); - } - *buf++ = w5100_read_direct(priv, W5100_IDM_DR); - } mmiowb(); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_unlock_irqrestore(&mmio_priv->reg_lock, flags); + + return 0; } -static void w5100_writebuf_indirect(struct w5100_priv *priv, - u16 offset, u8 *buf, int len) +static int w5100_writebulk_indirect(struct net_device *ndev, u16 addr, + const u8 *buf, int len) { - u16 addr = W5100_TX_MEM_START + (offset & W5100_TX_MEM_MASK); + struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; int i; - spin_lock_irqsave(&priv->reg_lock, flags); - w5100_write16_direct(priv, W5100_IDM_AR, addr); + spin_lock_irqsave(&mmio_priv->reg_lock, flags); + w5100_write16_direct(ndev, W5100_IDM_AR, addr); + + for (i = 0; i < len; i++) + __w5100_write_direct(ndev, W5100_IDM_DR, *buf++); - for (i = 0; i < len; i++, addr++) { - if (unlikely(addr > W5100_TX_MEM_END)) { - addr = W5100_TX_MEM_START; - w5100_write16_direct(priv, W5100_IDM_AR, addr); - } - __w5100_write_direct(priv, W5100_IDM_DR, *buf++); - } mmiowb(); - spin_unlock_irqrestore(&priv->reg_lock, flags); + spin_unlock_irqrestore(&mmio_priv->reg_lock, flags); + + return 0; +} + +static int w5100_reset_indirect(struct net_device *ndev) +{ + w5100_write_direct(ndev, W5100_MR, MR_RST); + mdelay(5); + w5100_write_direct(ndev, W5100_MR, MR_PB | MR_AI | MR_IND); + + return 0; } +static const struct w5100_ops w5100_mmio_indirect_ops = { + .read = w5100_read_indirect, + .write = w5100_write_indirect, + .read16 = w5100_read16_indirect, + .write16 = w5100_write16_indirect, + .readbulk = w5100_readbulk_indirect, + .writebulk = w5100_writebulk_indirect, + .init = w5100_mmio_init, + .reset = w5100_reset_indirect, +}; + #if defined(CONFIG_WIZNET_BUS_DIRECT) -#define w5100_read w5100_read_direct -#define w5100_write w5100_write_direct -#define w5100_read16 w5100_read16_direct -#define w5100_write16 w5100_write16_direct -#define w5100_readbuf w5100_readbuf_direct -#define w5100_writebuf w5100_writebuf_direct + +static int w5100_read(struct w5100_priv *priv, u16 addr) +{ + return w5100_read_direct(priv->ndev, addr); +} + +static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data) +{ + return w5100_write_direct(priv->ndev, addr, data); +} + +static int w5100_read16(struct w5100_priv *priv, u16 addr) +{ + return w5100_read16_direct(priv->ndev, addr); +} + +static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data) +{ + return w5100_write16_direct(priv->ndev, addr, data); +} + +static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len) +{ + return w5100_readbulk_direct(priv->ndev, addr, buf, len); +} + +static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, + int len) +{ + return w5100_writebulk_direct(priv->ndev, addr, buf, len); +} #elif defined(CONFIG_WIZNET_BUS_INDIRECT) -#define w5100_read w5100_read_indirect -#define w5100_write w5100_write_indirect -#define w5100_read16 w5100_read16_indirect -#define w5100_write16 w5100_write16_indirect -#define w5100_readbuf w5100_readbuf_indirect -#define w5100_writebuf w5100_writebuf_indirect + +static int w5100_read(struct w5100_priv *priv, u16 addr) +{ + return w5100_read_indirect(priv->ndev, addr); +} + +static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data) +{ + return w5100_write_indirect(priv->ndev, addr, data); +} + +static int w5100_read16(struct w5100_priv *priv, u16 addr) +{ + return w5100_read16_indirect(priv->ndev, addr); +} + +static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data) +{ + return w5100_write16_indirect(priv->ndev, addr, data); +} + +static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len) +{ + return w5100_readbulk_indirect(priv->ndev, addr, buf, len); +} + +static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, + int len) +{ + return w5100_writebulk_indirect(priv->ndev, addr, buf, len); +} #else /* CONFIG_WIZNET_BUS_ANY */ -#define w5100_read priv->read -#define w5100_write priv->write -#define w5100_read16 priv->read16 -#define w5100_write16 priv->write16 -#define w5100_readbuf priv->readbuf -#define w5100_writebuf priv->writebuf + +static int w5100_read(struct w5100_priv *priv, u16 addr) +{ + return priv->ops->read(priv->ndev, addr); +} + +static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data) +{ + return priv->ops->write(priv->ndev, addr, data); +} + +static int w5100_read16(struct w5100_priv *priv, u16 addr) +{ + return priv->ops->read16(priv->ndev, addr); +} + +static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data) +{ + return priv->ops->write16(priv->ndev, addr, data); +} + +static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len) +{ + return priv->ops->readbulk(priv->ndev, addr, buf, len); +} + +static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, + int len) +{ + return priv->ops->writebulk(priv->ndev, addr, buf, len); +} + #endif +static int w5100_readbuf(struct w5100_priv *priv, u16 offset, u8 *buf, int len) +{ + u16 addr; + int remain = 0; + int ret; + + offset %= W5100_RX_MEM_SIZE; + addr = W5100_RX_MEM_START + offset; + + if (offset + len > W5100_RX_MEM_SIZE) { + remain = (offset + len) % W5100_RX_MEM_SIZE; + len = W5100_RX_MEM_SIZE - offset; + } + + ret = w5100_readbulk(priv, addr, buf, len); + if (ret || !remain) + return ret; + + return w5100_readbulk(priv, W5100_RX_MEM_START, buf + len, remain); +} + +static int w5100_writebuf(struct w5100_priv *priv, u16 offset, const u8 *buf, + int len) +{ + u16 addr; + int ret; + int remain = 0; + + offset %= W5100_TX_MEM_SIZE; + addr = W5100_TX_MEM_START + offset; + + if (offset + len > W5100_TX_MEM_SIZE) { + remain = (offset + len) % W5100_TX_MEM_SIZE; + len = W5100_TX_MEM_SIZE - offset; + } + + ret = w5100_writebulk(priv, addr, buf, len); + if (ret || !remain) + return ret; + + return w5100_writebulk(priv, W5100_TX_MEM_START, buf + len, remain); +} + +static int w5100_reset(struct w5100_priv *priv) +{ + if (priv->ops->reset) + return priv->ops->reset(priv->ndev); + + w5100_write(priv, W5100_MR, MR_RST); + mdelay(5); + w5100_write(priv, W5100_MR, MR_PB); + + return 0; +} + static int w5100_command(struct w5100_priv *priv, u16 cmd) { unsigned long timeout = jiffies + msecs_to_jiffies(100); @@ -321,19 +518,14 @@ static int w5100_command(struct w5100_priv *priv, u16 cmd) static void w5100_write_macaddr(struct w5100_priv *priv) { struct net_device *ndev = priv->ndev; - int i; - for (i = 0; i < ETH_ALEN; i++) - w5100_write(priv, W5100_SHAR + i, ndev->dev_addr[i]); + w5100_writebulk(priv, W5100_SHAR, ndev->dev_addr, ETH_ALEN); } static void w5100_hw_reset(struct w5100_priv *priv) { - w5100_write_direct(priv, W5100_MR, MR_RST); - mdelay(5); - w5100_write_direct(priv, W5100_MR, priv->indirect ? - MR_PB | MR_AI | MR_IND : - MR_PB); + w5100_reset(priv); + w5100_write(priv, W5100_IMR, 0); w5100_write_macaddr(priv); @@ -403,17 +595,14 @@ static int w5100_get_regs_len(struct net_device *ndev) } static void w5100_get_regs(struct net_device *ndev, - struct ethtool_regs *regs, void *_buf) + struct ethtool_regs *regs, void *buf) { struct w5100_priv *priv = netdev_priv(ndev); - u8 *buf = _buf; - u16 i; regs->version = 1; - for (i = 0; i < W5100_COMMON_REGS_LEN; i++) - *buf++ = w5100_read(priv, W5100_COMMON_REGS + i); - for (i = 0; i < W5100_S0_REGS_LEN; i++) - *buf++ = w5100_read(priv, W5100_S0_REGS + i); + w5100_readbulk(priv, W5100_COMMON_REGS, buf, W5100_COMMON_REGS_LEN); + buf += W5100_COMMON_REGS_LEN; + w5100_readbulk(priv, W5100_S0_REGS, buf, W5100_S0_REGS_LEN); } static void w5100_tx_timeout(struct net_device *ndev) @@ -606,91 +795,68 @@ static const struct net_device_ops w5100_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static int w5100_hw_probe(struct platform_device *pdev) +static int w5100_mmio_probe(struct platform_device *pdev) { struct wiznet_platform_data *data = dev_get_platdata(&pdev->dev); - struct net_device *ndev = platform_get_drvdata(pdev); - struct w5100_priv *priv = netdev_priv(ndev); - const char *name = netdev_name(ndev); + u8 *mac_addr = NULL; struct resource *mem; - int mem_size; + const struct w5100_ops *ops; int irq; - int ret; - if (data && is_valid_ether_addr(data->mac_addr)) { - memcpy(ndev->dev_addr, data->mac_addr, ETH_ALEN); - } else { - eth_hw_addr_random(ndev); - } + if (data && is_valid_ether_addr(data->mac_addr)) + mac_addr = data->mac_addr; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - - mem_size = resource_size(mem); - - spin_lock_init(&priv->reg_lock); - priv->indirect = mem_size < W5100_BUS_DIRECT_SIZE; - if (priv->indirect) { - priv->read = w5100_read_indirect; - priv->write = w5100_write_indirect; - priv->read16 = w5100_read16_indirect; - priv->write16 = w5100_write16_indirect; - priv->readbuf = w5100_readbuf_indirect; - priv->writebuf = w5100_writebuf_indirect; - } else { - priv->read = w5100_read_direct; - priv->write = w5100_write_direct; - priv->read16 = w5100_read16_direct; - priv->write16 = w5100_write16_direct; - priv->readbuf = w5100_readbuf_direct; - priv->writebuf = w5100_writebuf_direct; - } - - w5100_hw_reset(priv); - if (w5100_read16(priv, W5100_RTR) != RTR_DEFAULT) - return -ENODEV; + if (resource_size(mem) < W5100_BUS_DIRECT_SIZE) + ops = &w5100_mmio_indirect_ops; + else + ops = &w5100_mmio_direct_ops; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - ret = request_irq(irq, w5100_interrupt, - IRQ_TYPE_LEVEL_LOW, name, ndev); - if (ret < 0) - return ret; - priv->irq = irq; - priv->link_gpio = data ? data->link_gpio : -EINVAL; - if (gpio_is_valid(priv->link_gpio)) { - char *link_name = devm_kzalloc(&pdev->dev, 16, GFP_KERNEL); - if (!link_name) - return -ENOMEM; - snprintf(link_name, 16, "%s-link", name); - priv->link_irq = gpio_to_irq(priv->link_gpio); - if (request_any_context_irq(priv->link_irq, w5100_detect_link, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - link_name, priv->ndev) < 0) - priv->link_gpio = -EINVAL; - } + return w5100_probe(&pdev->dev, ops, sizeof(struct w5100_mmio_priv), + mac_addr, irq, data ? data->link_gpio : -EINVAL); +} - netdev_info(ndev, "at 0x%llx irq %d\n", (u64)mem->start, irq); - return 0; +static int w5100_mmio_remove(struct platform_device *pdev) +{ + return w5100_remove(&pdev->dev); } -static int w5100_probe(struct platform_device *pdev) +void *w5100_ops_priv(const struct net_device *ndev) +{ + return netdev_priv(ndev) + + ALIGN(sizeof(struct w5100_priv), NETDEV_ALIGN); +} +EXPORT_SYMBOL_GPL(w5100_ops_priv); + +int w5100_probe(struct device *dev, const struct w5100_ops *ops, + int sizeof_ops_priv, u8 *mac_addr, int irq, int link_gpio) { struct w5100_priv *priv; struct net_device *ndev; int err; + size_t alloc_size; + + alloc_size = sizeof(*priv); + if (sizeof_ops_priv) { + alloc_size = ALIGN(alloc_size, NETDEV_ALIGN); + alloc_size += sizeof_ops_priv; + } + alloc_size += NETDEV_ALIGN - 1; - ndev = alloc_etherdev(sizeof(*priv)); + ndev = alloc_etherdev(alloc_size); if (!ndev) return -ENOMEM; - SET_NETDEV_DEV(ndev, &pdev->dev); - platform_set_drvdata(pdev, ndev); + SET_NETDEV_DEV(ndev, dev); + dev_set_drvdata(dev, ndev); priv = netdev_priv(ndev); priv->ndev = ndev; + priv->ops = ops; + priv->irq = irq; + priv->link_gpio = link_gpio; ndev->netdev_ops = &w5100_netdev_ops; ndev->ethtool_ops = &w5100_ethtool_ops; @@ -706,22 +872,59 @@ static int w5100_probe(struct platform_device *pdev) if (err < 0) goto err_register; - err = w5100_hw_probe(pdev); - if (err < 0) - goto err_hw_probe; + if (mac_addr) + memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); + else + eth_hw_addr_random(ndev); + + if (priv->ops->init) { + err = priv->ops->init(priv->ndev); + if (err) + goto err_hw; + } + + w5100_hw_reset(priv); + if (w5100_read16(priv, W5100_RTR) != RTR_DEFAULT) { + err = -ENODEV; + goto err_hw; + } + + err = request_irq(priv->irq, w5100_interrupt, IRQF_TRIGGER_LOW, + netdev_name(ndev), ndev); + if (err) + goto err_hw; + + if (gpio_is_valid(priv->link_gpio)) { + char *link_name = devm_kzalloc(dev, 16, GFP_KERNEL); + + if (!link_name) { + err = -ENOMEM; + goto err_gpio; + } + snprintf(link_name, 16, "%s-link", netdev_name(ndev)); + priv->link_irq = gpio_to_irq(priv->link_gpio); + if (request_any_context_irq(priv->link_irq, w5100_detect_link, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + link_name, priv->ndev) < 0) + priv->link_gpio = -EINVAL; + } return 0; -err_hw_probe: +err_gpio: + free_irq(priv->irq, ndev); +err_hw: unregister_netdev(ndev); err_register: free_netdev(ndev); return err; } +EXPORT_SYMBOL_GPL(w5100_probe); -static int w5100_remove(struct platform_device *pdev) +int w5100_remove(struct device *dev) { - struct net_device *ndev = platform_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev); struct w5100_priv *priv = netdev_priv(ndev); w5100_hw_reset(priv); @@ -733,12 +936,12 @@ static int w5100_remove(struct platform_device *pdev) free_netdev(ndev); return 0; } +EXPORT_SYMBOL_GPL(w5100_remove); #ifdef CONFIG_PM_SLEEP static int w5100_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct net_device *ndev = platform_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev); struct w5100_priv *priv = netdev_priv(ndev); if (netif_running(ndev)) { @@ -752,8 +955,7 @@ static int w5100_suspend(struct device *dev) static int w5100_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct net_device *ndev = platform_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev); struct w5100_priv *priv = netdev_priv(ndev); if (netif_running(ndev)) { @@ -769,15 +971,15 @@ static int w5100_resume(struct device *dev) } #endif /* CONFIG_PM_SLEEP */ -static SIMPLE_DEV_PM_OPS(w5100_pm_ops, w5100_suspend, w5100_resume); +SIMPLE_DEV_PM_OPS(w5100_pm_ops, w5100_suspend, w5100_resume); +EXPORT_SYMBOL_GPL(w5100_pm_ops); -static struct platform_driver w5100_driver = { +static struct platform_driver w5100_mmio_driver = { .driver = { .name = DRV_NAME, .pm = &w5100_pm_ops, }, - .probe = w5100_probe, - .remove = w5100_remove, + .probe = w5100_mmio_probe, + .remove = w5100_mmio_remove, }; - -module_platform_driver(w5100_driver); +module_platform_driver(w5100_mmio_driver); diff --git a/drivers/net/ethernet/wiznet/w5100.h b/drivers/net/ethernet/wiznet/w5100.h new file mode 100644 index 000000000000..39d452d878e7 --- /dev/null +++ b/drivers/net/ethernet/wiznet/w5100.h @@ -0,0 +1,28 @@ +/* + * Ethernet driver for the WIZnet W5100 chip. + * + * Copyright (C) 2006-2008 WIZnet Co.,Ltd. + * Copyright (C) 2012 Mike Sinkovsky + * + * Licensed under the GPL-2 or later. + */ + +struct w5100_ops { + int (*read)(struct net_device *ndev, u16 addr); + int (*write)(struct net_device *ndev, u16 addr, u8 data); + int (*read16)(struct net_device *ndev, u16 addr); + int (*write16)(struct net_device *ndev, u16 addr, u16 data); + int (*readbulk)(struct net_device *ndev, u16 addr, u8 *buf, int len); + int (*writebulk)(struct net_device *ndev, u16 addr, const u8 *buf, + int len); + int (*reset)(struct net_device *ndev); + int (*init)(struct net_device *ndev); +}; + +void *w5100_ops_priv(const struct net_device *ndev); + +int w5100_probe(struct device *dev, const struct w5100_ops *ops, + int sizeof_ops_priv, u8 *mac_addr, int irq, int link_gpio); +int w5100_remove(struct device *dev); + +extern const struct dev_pm_ops w5100_pm_ops; -- GitLab From bf2c6b90b385c163ad9c48fe97f5dc6af0091de6 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 15 Apr 2016 00:11:31 +0900 Subject: [PATCH 3138/9938] net: w5100: enable to support sleepable register access interface SPI transfer routines are callable only from contexts that can sleep. This adds ability to tell the core driver that the interface mode cannot access w5100 register on atomic contexts. In this case, workqueue and threaded irq are required. This also corrects timeout period waiting for command register to be automatically cleared because the latency of the register access with SPI transfer can be interfered by other contexts. Signed-off-by: Akinobu Mita Cc: Mike Sinkovsky Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ethernet/wiznet/w5100.c | 190 ++++++++++++++++++++++------ drivers/net/ethernet/wiznet/w5100.h | 1 + 2 files changed, 153 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index 89cba6741e7f..42a9de4a48b1 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -96,6 +96,13 @@ struct w5100_priv { struct net_device *ndev; bool promisc; u32 msg_enable; + + struct workqueue_struct *xfer_wq; + struct work_struct rx_work; + struct sk_buff *tx_skb; + struct work_struct tx_work; + struct work_struct setrx_work; + struct work_struct restart_work; }; /************************************************************************ @@ -502,10 +509,12 @@ static int w5100_reset(struct w5100_priv *priv) static int w5100_command(struct w5100_priv *priv, u16 cmd) { - unsigned long timeout = jiffies + msecs_to_jiffies(100); + unsigned long timeout; w5100_write(priv, W5100_S0_CR, cmd); + timeout = jiffies + msecs_to_jiffies(100); + while (w5100_read(priv, W5100_S0_CR) != 0) { if (time_after(jiffies, timeout)) return -EIO; @@ -605,7 +614,7 @@ static void w5100_get_regs(struct net_device *ndev, w5100_readbulk(priv, W5100_S0_REGS, buf, W5100_S0_REGS_LEN); } -static void w5100_tx_timeout(struct net_device *ndev) +static void w5100_restart(struct net_device *ndev) { struct w5100_priv *priv = netdev_priv(ndev); @@ -617,12 +626,28 @@ static void w5100_tx_timeout(struct net_device *ndev) netif_wake_queue(ndev); } -static int w5100_start_tx(struct sk_buff *skb, struct net_device *ndev) +static void w5100_restart_work(struct work_struct *work) +{ + struct w5100_priv *priv = container_of(work, struct w5100_priv, + restart_work); + + w5100_restart(priv->ndev); +} + +static void w5100_tx_timeout(struct net_device *ndev) { struct w5100_priv *priv = netdev_priv(ndev); - u16 offset; - netif_stop_queue(ndev); + if (priv->ops->may_sleep) + schedule_work(&priv->restart_work); + else + w5100_restart(ndev); +} + +static void w5100_tx_skb(struct net_device *ndev, struct sk_buff *skb) +{ + struct w5100_priv *priv = netdev_priv(ndev); + u16 offset; offset = w5100_read16(priv, W5100_S0_TX_WR); w5100_writebuf(priv, offset, skb->data, skb->len); @@ -632,47 +657,98 @@ static int w5100_start_tx(struct sk_buff *skb, struct net_device *ndev) dev_kfree_skb(skb); w5100_command(priv, S0_CR_SEND); +} + +static void w5100_tx_work(struct work_struct *work) +{ + struct w5100_priv *priv = container_of(work, struct w5100_priv, + tx_work); + struct sk_buff *skb = priv->tx_skb; + + priv->tx_skb = NULL; + + if (WARN_ON(!skb)) + return; + w5100_tx_skb(priv->ndev, skb); +} + +static int w5100_start_tx(struct sk_buff *skb, struct net_device *ndev) +{ + struct w5100_priv *priv = netdev_priv(ndev); + + netif_stop_queue(ndev); + + if (priv->ops->may_sleep) { + WARN_ON(priv->tx_skb); + priv->tx_skb = skb; + queue_work(priv->xfer_wq, &priv->tx_work); + } else { + w5100_tx_skb(ndev, skb); + } return NETDEV_TX_OK; } -static int w5100_napi_poll(struct napi_struct *napi, int budget) +static struct sk_buff *w5100_rx_skb(struct net_device *ndev) { - struct w5100_priv *priv = container_of(napi, struct w5100_priv, napi); - struct net_device *ndev = priv->ndev; + struct w5100_priv *priv = netdev_priv(ndev); struct sk_buff *skb; - int rx_count; u16 rx_len; u16 offset; u8 header[2]; + u16 rx_buf_len = w5100_read16(priv, W5100_S0_RX_RSR); - for (rx_count = 0; rx_count < budget; rx_count++) { - u16 rx_buf_len = w5100_read16(priv, W5100_S0_RX_RSR); - if (rx_buf_len == 0) - break; + if (rx_buf_len == 0) + return NULL; - offset = w5100_read16(priv, W5100_S0_RX_RD); - w5100_readbuf(priv, offset, header, 2); - rx_len = get_unaligned_be16(header) - 2; - - skb = netdev_alloc_skb_ip_align(ndev, rx_len); - if (unlikely(!skb)) { - w5100_write16(priv, W5100_S0_RX_RD, - offset + rx_buf_len); - w5100_command(priv, S0_CR_RECV); - ndev->stats.rx_dropped++; - return -ENOMEM; - } + offset = w5100_read16(priv, W5100_S0_RX_RD); + w5100_readbuf(priv, offset, header, 2); + rx_len = get_unaligned_be16(header) - 2; - skb_put(skb, rx_len); - w5100_readbuf(priv, offset + 2, skb->data, rx_len); - w5100_write16(priv, W5100_S0_RX_RD, offset + 2 + rx_len); + skb = netdev_alloc_skb_ip_align(ndev, rx_len); + if (unlikely(!skb)) { + w5100_write16(priv, W5100_S0_RX_RD, offset + rx_buf_len); w5100_command(priv, S0_CR_RECV); - skb->protocol = eth_type_trans(skb, ndev); + ndev->stats.rx_dropped++; + return NULL; + } + + skb_put(skb, rx_len); + w5100_readbuf(priv, offset + 2, skb->data, rx_len); + w5100_write16(priv, W5100_S0_RX_RD, offset + 2 + rx_len); + w5100_command(priv, S0_CR_RECV); + skb->protocol = eth_type_trans(skb, ndev); + + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += rx_len; + + return skb; +} + +static void w5100_rx_work(struct work_struct *work) +{ + struct w5100_priv *priv = container_of(work, struct w5100_priv, + rx_work); + struct sk_buff *skb; + + while ((skb = w5100_rx_skb(priv->ndev))) + netif_rx_ni(skb); + + w5100_write(priv, W5100_IMR, IR_S0); +} + +static int w5100_napi_poll(struct napi_struct *napi, int budget) +{ + struct w5100_priv *priv = container_of(napi, struct w5100_priv, napi); + int rx_count; + + for (rx_count = 0; rx_count < budget; rx_count++) { + struct sk_buff *skb = w5100_rx_skb(priv->ndev); - netif_receive_skb(skb); - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += rx_len; + if (skb) + netif_receive_skb(skb); + else + break; } if (rx_count < budget) { @@ -699,10 +775,12 @@ static irqreturn_t w5100_interrupt(int irq, void *ndev_instance) } if (ir & S0_IR_RECV) { - if (napi_schedule_prep(&priv->napi)) { - w5100_write(priv, W5100_IMR, 0); + w5100_write(priv, W5100_IMR, 0); + + if (priv->ops->may_sleep) + queue_work(priv->xfer_wq, &priv->rx_work); + else if (napi_schedule_prep(&priv->napi)) __napi_schedule(&priv->napi); - } } return IRQ_HANDLED; @@ -726,6 +804,14 @@ static irqreturn_t w5100_detect_link(int irq, void *ndev_instance) return IRQ_HANDLED; } +static void w5100_setrx_work(struct work_struct *work) +{ + struct w5100_priv *priv = container_of(work, struct w5100_priv, + setrx_work); + + w5100_hw_start(priv); +} + static void w5100_set_rx_mode(struct net_device *ndev) { struct w5100_priv *priv = netdev_priv(ndev); @@ -733,7 +819,11 @@ static void w5100_set_rx_mode(struct net_device *ndev) if (priv->promisc != set_promisc) { priv->promisc = set_promisc; - w5100_hw_start(priv); + + if (priv->ops->may_sleep) + schedule_work(&priv->setrx_work); + else + w5100_hw_start(priv); } } @@ -872,6 +962,17 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops, if (err < 0) goto err_register; + priv->xfer_wq = create_workqueue(netdev_name(ndev)); + if (!priv->xfer_wq) { + err = -ENOMEM; + goto err_wq; + } + + INIT_WORK(&priv->rx_work, w5100_rx_work); + INIT_WORK(&priv->tx_work, w5100_tx_work); + INIT_WORK(&priv->setrx_work, w5100_setrx_work); + INIT_WORK(&priv->restart_work, w5100_restart_work); + if (mac_addr) memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); else @@ -889,8 +990,14 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops, goto err_hw; } - err = request_irq(priv->irq, w5100_interrupt, IRQF_TRIGGER_LOW, - netdev_name(ndev), ndev); + if (ops->may_sleep) { + err = request_threaded_irq(priv->irq, NULL, w5100_interrupt, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + netdev_name(ndev), ndev); + } else { + err = request_irq(priv->irq, w5100_interrupt, + IRQF_TRIGGER_LOW, netdev_name(ndev), ndev); + } if (err) goto err_hw; @@ -915,6 +1022,8 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops, err_gpio: free_irq(priv->irq, ndev); err_hw: + destroy_workqueue(priv->xfer_wq); +err_wq: unregister_netdev(ndev); err_register: free_netdev(ndev); @@ -932,6 +1041,11 @@ int w5100_remove(struct device *dev) if (gpio_is_valid(priv->link_gpio)) free_irq(priv->link_irq, ndev); + flush_work(&priv->setrx_work); + flush_work(&priv->restart_work); + flush_workqueue(priv->xfer_wq); + destroy_workqueue(priv->xfer_wq); + unregister_netdev(ndev); free_netdev(ndev); return 0; diff --git a/drivers/net/ethernet/wiznet/w5100.h b/drivers/net/ethernet/wiznet/w5100.h index 39d452d878e7..69045f0f9e10 100644 --- a/drivers/net/ethernet/wiznet/w5100.h +++ b/drivers/net/ethernet/wiznet/w5100.h @@ -8,6 +8,7 @@ */ struct w5100_ops { + bool may_sleep; int (*read)(struct net_device *ndev, u16 addr); int (*write)(struct net_device *ndev, u16 addr, u8 data); int (*read16)(struct net_device *ndev, u16 addr); -- GitLab From 630cf09751fe166ffc25d1ae35ce804bf58eb3c7 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 15 Apr 2016 00:11:32 +0900 Subject: [PATCH 3139/9938] net: w5100: support SPI interface mode This adds new w5100-spi driver which shares the bus interface independent code with existing w5100 driver. Signed-off-by: Akinobu Mita Cc: Mike Sinkovsky Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ethernet/wiznet/Kconfig | 14 +++ drivers/net/ethernet/wiznet/Makefile | 1 + drivers/net/ethernet/wiznet/w5100-spi.c | 136 ++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 drivers/net/ethernet/wiznet/w5100-spi.c diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig index f98b91d21f33..d1ab353790de 100644 --- a/drivers/net/ethernet/wiznet/Kconfig +++ b/drivers/net/ethernet/wiznet/Kconfig @@ -69,4 +69,18 @@ config WIZNET_BUS_ANY Performance may decrease compared to explicitly selected bus mode. endchoice +config WIZNET_W5100_SPI + tristate "WIZnet W5100 Ethernet support for SPI mode" + depends on WIZNET_BUS_ANY + depends on SPI + ---help--- + In SPI mode host system accesses registers using SPI protocol + (mode 0) on the SPI bus. + + Performance decreases compared to other bus interface mode. + In W5100 SPI mode, burst READ/WRITE processing are not provided. + + To compile this driver as a module, choose M here: the module + will be called w5100-spi. + endif # NET_VENDOR_WIZNET diff --git a/drivers/net/ethernet/wiznet/Makefile b/drivers/net/ethernet/wiznet/Makefile index c614535227e8..1e05e1a84208 100644 --- a/drivers/net/ethernet/wiznet/Makefile +++ b/drivers/net/ethernet/wiznet/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_WIZNET_W5100) += w5100.o +obj-$(CONFIG_WIZNET_W5100_SPI) += w5100-spi.o obj-$(CONFIG_WIZNET_W5300) += w5300.o diff --git a/drivers/net/ethernet/wiznet/w5100-spi.c b/drivers/net/ethernet/wiznet/w5100-spi.c new file mode 100644 index 000000000000..32f406cfce4b --- /dev/null +++ b/drivers/net/ethernet/wiznet/w5100-spi.c @@ -0,0 +1,136 @@ +/* + * Ethernet driver for the WIZnet W5100 chip. + * + * Copyright (C) 2016 Akinobu Mita + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include + +#include "w5100.h" + +#define W5100_SPI_WRITE_OPCODE 0xf0 +#define W5100_SPI_READ_OPCODE 0x0f + +static int w5100_spi_read(struct net_device *ndev, u16 addr) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[3] = { W5100_SPI_READ_OPCODE, addr >> 8, addr & 0xff }; + u8 data; + int ret; + + ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1); + + return ret ? ret : data; +} + +static int w5100_spi_write(struct net_device *ndev, u16 addr, u8 data) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[4] = { W5100_SPI_WRITE_OPCODE, addr >> 8, addr & 0xff, data}; + + return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); +} + +static int w5100_spi_read16(struct net_device *ndev, u16 addr) +{ + u16 data; + int ret; + + ret = w5100_spi_read(ndev, addr); + if (ret < 0) + return ret; + data = ret << 8; + ret = w5100_spi_read(ndev, addr + 1); + + return ret < 0 ? ret : data | ret; +} + +static int w5100_spi_write16(struct net_device *ndev, u16 addr, u16 data) +{ + int ret; + + ret = w5100_spi_write(ndev, addr, data >> 8); + if (ret) + return ret; + + return w5100_spi_write(ndev, addr + 1, data & 0xff); +} + +static int w5100_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf, + int len) +{ + int i; + + for (i = 0; i < len; i++) { + int ret = w5100_spi_read(ndev, addr + i); + + if (ret < 0) + return ret; + buf[i] = ret; + } + + return 0; +} + +static int w5100_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf, + int len) +{ + int i; + + for (i = 0; i < len; i++) { + int ret = w5100_spi_write(ndev, addr + i, buf[i]); + + if (ret) + return ret; + } + + return 0; +} + +static const struct w5100_ops w5100_spi_ops = { + .may_sleep = true, + .read = w5100_spi_read, + .write = w5100_spi_write, + .read16 = w5100_spi_read16, + .write16 = w5100_spi_write16, + .readbulk = w5100_spi_readbulk, + .writebulk = w5100_spi_writebulk, +}; + +static int w5100_spi_probe(struct spi_device *spi) +{ + return w5100_probe(&spi->dev, &w5100_spi_ops, 0, NULL, spi->irq, + -EINVAL); +} + +static int w5100_spi_remove(struct spi_device *spi) +{ + return w5100_remove(&spi->dev); +} + +static const struct spi_device_id w5100_spi_ids[] = { + { "w5100", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, w5100_spi_ids); + +static struct spi_driver w5100_spi_driver = { + .driver = { + .name = "w5100", + .pm = &w5100_pm_ops, + }, + .probe = w5100_spi_probe, + .remove = w5100_spi_remove, + .id_table = w5100_spi_ids, +}; +module_spi_driver(w5100_spi_driver); + +MODULE_DESCRIPTION("WIZnet W5100 Ethernet driver for SPI mode"); +MODULE_AUTHOR("Akinobu Mita "); +MODULE_LICENSE("GPL"); -- GitLab From 0c165ff2d8db575efa41f2586c2de193850dec48 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 15 Apr 2016 00:11:33 +0900 Subject: [PATCH 3140/9938] net: w5100: support W5200 This adds support for W5200 chip. W5100 and W5200 have similar memory map although some of their offsets are different. The register access sequences between them are different but w5100 driver has abstraction layer for difference bus interface modes so it is easy to add W5200 support to w5100 and w5100-spi drivers. Signed-off-by: Akinobu Mita Cc: Mike Sinkovsky Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ethernet/wiznet/Kconfig | 2 +- drivers/net/ethernet/wiznet/w5100-spi.c | 174 +++++++++++++++++++++++- drivers/net/ethernet/wiznet/w5100.c | 155 +++++++++++++++------ drivers/net/ethernet/wiznet/w5100.h | 6 + 4 files changed, 289 insertions(+), 48 deletions(-) diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig index d1ab353790de..1f15376e9856 100644 --- a/drivers/net/ethernet/wiznet/Kconfig +++ b/drivers/net/ethernet/wiznet/Kconfig @@ -70,7 +70,7 @@ config WIZNET_BUS_ANY endchoice config WIZNET_W5100_SPI - tristate "WIZnet W5100 Ethernet support for SPI mode" + tristate "WIZnet W5100/W5200 Ethernet support for SPI mode" depends on WIZNET_BUS_ANY depends on SPI ---help--- diff --git a/drivers/net/ethernet/wiznet/w5100-spi.c b/drivers/net/ethernet/wiznet/w5100-spi.c index 32f406cfce4b..598a7b00fdb9 100644 --- a/drivers/net/ethernet/wiznet/w5100-spi.c +++ b/drivers/net/ethernet/wiznet/w5100-spi.c @@ -1,9 +1,13 @@ /* - * Ethernet driver for the WIZnet W5100 chip. + * Ethernet driver for the WIZnet W5100/W5200 chip. * * Copyright (C) 2016 Akinobu Mita * * Licensed under the GPL-2 or later. + * + * Datasheet: + * http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Document/W5100_Datasheet_v1.2.6.pdf + * http://wiznethome.cafe24.com/wp-content/uploads/wiznethome/Chip/W5200/Documents/W5200_DS_V140E.pdf */ #include @@ -95,6 +99,7 @@ static int w5100_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf, static const struct w5100_ops w5100_spi_ops = { .may_sleep = true, + .chip_id = W5100, .read = w5100_spi_read, .write = w5100_spi_write, .read16 = w5100_spi_read16, @@ -103,10 +108,168 @@ static const struct w5100_ops w5100_spi_ops = { .writebulk = w5100_spi_writebulk, }; +#define W5200_SPI_WRITE_OPCODE 0x80 + +struct w5200_spi_priv { + /* Serialize access to cmd_buf */ + struct mutex cmd_lock; + + /* DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u8 cmd_buf[4] ____cacheline_aligned; +}; + +static struct w5200_spi_priv *w5200_spi_priv(struct net_device *ndev) +{ + return w5100_ops_priv(ndev); +} + +static int w5200_spi_init(struct net_device *ndev) +{ + struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev); + + mutex_init(&spi_priv->cmd_lock); + + return 0; +} + +static int w5200_spi_read(struct net_device *ndev, u16 addr) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 1 }; + u8 data; + int ret; + + ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1); + + return ret ? ret : data; +} + +static int w5200_spi_write(struct net_device *ndev, u16 addr, u8 data) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[5] = { addr >> 8, addr & 0xff, W5200_SPI_WRITE_OPCODE, 1, data }; + + return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); +} + +static int w5200_spi_read16(struct net_device *ndev, u16 addr) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 2 }; + __be16 data; + int ret; + + ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data)); + + return ret ? ret : be16_to_cpu(data); +} + +static int w5200_spi_write16(struct net_device *ndev, u16 addr, u16 data) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[6] = { + addr >> 8, addr & 0xff, + W5200_SPI_WRITE_OPCODE, 2, + data >> 8, data & 0xff + }; + + return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); +} + +static int w5200_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf, + int len) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev); + struct spi_transfer xfer[] = { + { + .tx_buf = spi_priv->cmd_buf, + .len = sizeof(spi_priv->cmd_buf), + }, + { + .rx_buf = buf, + .len = len, + }, + }; + int ret; + + mutex_lock(&spi_priv->cmd_lock); + + spi_priv->cmd_buf[0] = addr >> 8; + spi_priv->cmd_buf[1] = addr; + spi_priv->cmd_buf[2] = len >> 8; + spi_priv->cmd_buf[3] = len; + ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); + + mutex_unlock(&spi_priv->cmd_lock); + + return ret; +} + +static int w5200_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf, + int len) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev); + struct spi_transfer xfer[] = { + { + .tx_buf = spi_priv->cmd_buf, + .len = sizeof(spi_priv->cmd_buf), + }, + { + .tx_buf = buf, + .len = len, + }, + }; + int ret; + + mutex_lock(&spi_priv->cmd_lock); + + spi_priv->cmd_buf[0] = addr >> 8; + spi_priv->cmd_buf[1] = addr; + spi_priv->cmd_buf[2] = W5200_SPI_WRITE_OPCODE | (len >> 8); + spi_priv->cmd_buf[3] = len; + ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); + + mutex_unlock(&spi_priv->cmd_lock); + + return ret; +} + +static const struct w5100_ops w5200_ops = { + .may_sleep = true, + .chip_id = W5200, + .read = w5200_spi_read, + .write = w5200_spi_write, + .read16 = w5200_spi_read16, + .write16 = w5200_spi_write16, + .readbulk = w5200_spi_readbulk, + .writebulk = w5200_spi_writebulk, + .init = w5200_spi_init, +}; + static int w5100_spi_probe(struct spi_device *spi) { - return w5100_probe(&spi->dev, &w5100_spi_ops, 0, NULL, spi->irq, - -EINVAL); + const struct spi_device_id *id = spi_get_device_id(spi); + const struct w5100_ops *ops; + int priv_size; + + switch (id->driver_data) { + case W5100: + ops = &w5100_spi_ops; + priv_size = 0; + break; + case W5200: + ops = &w5200_ops; + priv_size = sizeof(struct w5200_spi_priv); + break; + default: + return -EINVAL; + } + + return w5100_probe(&spi->dev, ops, priv_size, NULL, spi->irq, -EINVAL); } static int w5100_spi_remove(struct spi_device *spi) @@ -115,7 +278,8 @@ static int w5100_spi_remove(struct spi_device *spi) } static const struct spi_device_id w5100_spi_ids[] = { - { "w5100", 0 }, + { "w5100", W5100 }, + { "w5200", W5200 }, {} }; MODULE_DEVICE_TABLE(spi, w5100_spi_ids); @@ -131,6 +295,6 @@ static struct spi_driver w5100_spi_driver = { }; module_spi_driver(w5100_spi_driver); -MODULE_DESCRIPTION("WIZnet W5100 Ethernet driver for SPI mode"); +MODULE_DESCRIPTION("WIZnet W5100/W5200 Ethernet driver for SPI mode"); MODULE_AUTHOR("Akinobu Mita "); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index 42a9de4a48b1..09149c9ebeff 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -38,7 +38,7 @@ MODULE_ALIAS("platform:"DRV_NAME); MODULE_LICENSE("GPL"); /* - * Registers + * W5100 and W5100 common registers */ #define W5100_COMMON_REGS 0x0000 #define W5100_MR 0x0000 /* Mode Register */ @@ -52,36 +52,68 @@ MODULE_LICENSE("GPL"); #define IR_S0 0x01 /* S0 interrupt */ #define W5100_RTR 0x0017 /* Retry Time-value Register */ #define RTR_DEFAULT 2000 /* =0x07d0 (2000) */ -#define W5100_RMSR 0x001a /* Receive Memory Size */ -#define W5100_TMSR 0x001b /* Transmit Memory Size */ #define W5100_COMMON_REGS_LEN 0x0040 -#define W5100_S0_REGS 0x0400 -#define W5100_S0_MR 0x0400 /* S0 Mode Register */ +#define W5100_Sn_MR 0x0000 /* Sn Mode Register */ +#define W5100_Sn_CR 0x0001 /* Sn Command Register */ +#define W5100_Sn_IR 0x0002 /* Sn Interrupt Register */ +#define W5100_Sn_SR 0x0003 /* Sn Status Register */ +#define W5100_Sn_TX_FSR 0x0020 /* Sn Transmit free memory size */ +#define W5100_Sn_TX_RD 0x0022 /* Sn Transmit memory read pointer */ +#define W5100_Sn_TX_WR 0x0024 /* Sn Transmit memory write pointer */ +#define W5100_Sn_RX_RSR 0x0026 /* Sn Receive free memory size */ +#define W5100_Sn_RX_RD 0x0028 /* Sn Receive memory read pointer */ + +#define S0_REGS(priv) (is_w5200(priv) ? W5200_S0_REGS : W5100_S0_REGS) + +#define W5100_S0_MR(priv) (S0_REGS(priv) + W5100_Sn_MR) #define S0_MR_MACRAW 0x04 /* MAC RAW mode (promiscuous) */ #define S0_MR_MACRAW_MF 0x44 /* MAC RAW mode (filtered) */ -#define W5100_S0_CR 0x0401 /* S0 Command Register */ +#define W5100_S0_CR(priv) (S0_REGS(priv) + W5100_Sn_CR) #define S0_CR_OPEN 0x01 /* OPEN command */ #define S0_CR_CLOSE 0x10 /* CLOSE command */ #define S0_CR_SEND 0x20 /* SEND command */ #define S0_CR_RECV 0x40 /* RECV command */ -#define W5100_S0_IR 0x0402 /* S0 Interrupt Register */ +#define W5100_S0_IR(priv) (S0_REGS(priv) + W5100_Sn_IR) #define S0_IR_SENDOK 0x10 /* complete sending */ #define S0_IR_RECV 0x04 /* receiving data */ -#define W5100_S0_SR 0x0403 /* S0 Status Register */ +#define W5100_S0_SR(priv) (S0_REGS(priv) + W5100_Sn_SR) #define S0_SR_MACRAW 0x42 /* mac raw mode */ -#define W5100_S0_TX_FSR 0x0420 /* S0 Transmit free memory size */ -#define W5100_S0_TX_RD 0x0422 /* S0 Transmit memory read pointer */ -#define W5100_S0_TX_WR 0x0424 /* S0 Transmit memory write pointer */ -#define W5100_S0_RX_RSR 0x0426 /* S0 Receive free memory size */ -#define W5100_S0_RX_RD 0x0428 /* S0 Receive memory read pointer */ +#define W5100_S0_TX_FSR(priv) (S0_REGS(priv) + W5100_Sn_TX_FSR) +#define W5100_S0_TX_RD(priv) (S0_REGS(priv) + W5100_Sn_TX_RD) +#define W5100_S0_TX_WR(priv) (S0_REGS(priv) + W5100_Sn_TX_WR) +#define W5100_S0_RX_RSR(priv) (S0_REGS(priv) + W5100_Sn_RX_RSR) +#define W5100_S0_RX_RD(priv) (S0_REGS(priv) + W5100_Sn_RX_RD) + #define W5100_S0_REGS_LEN 0x0040 +/* + * W5100 specific registers + */ +#define W5100_RMSR 0x001a /* Receive Memory Size */ +#define W5100_TMSR 0x001b /* Transmit Memory Size */ + +#define W5100_S0_REGS 0x0400 + #define W5100_TX_MEM_START 0x4000 #define W5100_TX_MEM_SIZE 0x2000 #define W5100_RX_MEM_START 0x6000 #define W5100_RX_MEM_SIZE 0x2000 +/* + * W5200 specific registers + */ +#define W5200_S0_REGS 0x4000 + +#define W5200_Sn_RXMEM_SIZE(n) (0x401e + (n) * 0x0100) /* Sn RX Memory Size */ +#define W5200_Sn_TXMEM_SIZE(n) (0x401f + (n) * 0x0100) /* Sn TX Memory Size */ +#define W5200_S0_IMR 0x402c /* S0 Interrupt Mask Register */ + +#define W5200_TX_MEM_START 0x8000 +#define W5200_TX_MEM_SIZE 0x4000 +#define W5200_RX_MEM_START 0xc000 +#define W5200_RX_MEM_SIZE 0x4000 + /* * Device driver private data structure */ @@ -105,6 +137,11 @@ struct w5100_priv { struct work_struct restart_work; }; +static inline bool is_w5200(struct w5100_priv *priv) +{ + return priv->ops->chip_id == W5200; +} + /************************************************************************ * * Lowlevel I/O functions @@ -217,6 +254,7 @@ static int w5100_mmio_init(struct net_device *ndev) } static const struct w5100_ops w5100_mmio_direct_ops = { + .chip_id = W5100, .read = w5100_read_direct, .write = w5100_write_direct, .read16 = w5100_read16_direct, @@ -341,6 +379,7 @@ static int w5100_reset_indirect(struct net_device *ndev) } static const struct w5100_ops w5100_mmio_indirect_ops = { + .chip_id = W5100, .read = w5100_read_indirect, .write = w5100_write_indirect, .read16 = w5100_read16_indirect, @@ -457,20 +496,24 @@ static int w5100_readbuf(struct w5100_priv *priv, u16 offset, u8 *buf, int len) u16 addr; int remain = 0; int ret; + const u16 mem_start = + is_w5200(priv) ? W5200_RX_MEM_START : W5100_RX_MEM_START; + const u16 mem_size = + is_w5200(priv) ? W5200_RX_MEM_SIZE : W5100_RX_MEM_SIZE; - offset %= W5100_RX_MEM_SIZE; - addr = W5100_RX_MEM_START + offset; + offset %= mem_size; + addr = mem_start + offset; - if (offset + len > W5100_RX_MEM_SIZE) { - remain = (offset + len) % W5100_RX_MEM_SIZE; - len = W5100_RX_MEM_SIZE - offset; + if (offset + len > mem_size) { + remain = (offset + len) % mem_size; + len = mem_size - offset; } ret = w5100_readbulk(priv, addr, buf, len); if (ret || !remain) return ret; - return w5100_readbulk(priv, W5100_RX_MEM_START, buf + len, remain); + return w5100_readbulk(priv, mem_start, buf + len, remain); } static int w5100_writebuf(struct w5100_priv *priv, u16 offset, const u8 *buf, @@ -479,20 +522,24 @@ static int w5100_writebuf(struct w5100_priv *priv, u16 offset, const u8 *buf, u16 addr; int ret; int remain = 0; + const u16 mem_start = + is_w5200(priv) ? W5200_TX_MEM_START : W5100_TX_MEM_START; + const u16 mem_size = + is_w5200(priv) ? W5200_TX_MEM_SIZE : W5100_TX_MEM_SIZE; - offset %= W5100_TX_MEM_SIZE; - addr = W5100_TX_MEM_START + offset; + offset %= mem_size; + addr = mem_start + offset; - if (offset + len > W5100_TX_MEM_SIZE) { - remain = (offset + len) % W5100_TX_MEM_SIZE; - len = W5100_TX_MEM_SIZE - offset; + if (offset + len > mem_size) { + remain = (offset + len) % mem_size; + len = mem_size - offset; } ret = w5100_writebulk(priv, addr, buf, len); if (ret || !remain) return ret; - return w5100_writebulk(priv, W5100_TX_MEM_START, buf + len, remain); + return w5100_writebulk(priv, mem_start, buf + len, remain); } static int w5100_reset(struct w5100_priv *priv) @@ -511,11 +558,11 @@ static int w5100_command(struct w5100_priv *priv, u16 cmd) { unsigned long timeout; - w5100_write(priv, W5100_S0_CR, cmd); + w5100_write(priv, W5100_S0_CR(priv), cmd); timeout = jiffies + msecs_to_jiffies(100); - while (w5100_read(priv, W5100_S0_CR) != 0) { + while (w5100_read(priv, W5100_S0_CR(priv)) != 0) { if (time_after(jiffies, timeout)) return -EIO; cpu_relax(); @@ -531,6 +578,31 @@ static void w5100_write_macaddr(struct w5100_priv *priv) w5100_writebulk(priv, W5100_SHAR, ndev->dev_addr, ETH_ALEN); } +static void w5100_memory_configure(struct w5100_priv *priv) +{ + /* Configure 16K of internal memory + * as 8K RX buffer and 8K TX buffer + */ + w5100_write(priv, W5100_RMSR, 0x03); + w5100_write(priv, W5100_TMSR, 0x03); +} + +static void w5200_memory_configure(struct w5100_priv *priv) +{ + int i; + + /* Configure internal RX memory as 16K RX buffer and + * internal TX memory as 16K TX buffer + */ + w5100_write(priv, W5200_Sn_RXMEM_SIZE(0), 0x10); + w5100_write(priv, W5200_Sn_TXMEM_SIZE(0), 0x10); + + for (i = 1; i < 8; i++) { + w5100_write(priv, W5200_Sn_RXMEM_SIZE(i), 0); + w5100_write(priv, W5200_Sn_TXMEM_SIZE(i), 0); + } +} + static void w5100_hw_reset(struct w5100_priv *priv) { w5100_reset(priv); @@ -538,16 +610,15 @@ static void w5100_hw_reset(struct w5100_priv *priv) w5100_write(priv, W5100_IMR, 0); w5100_write_macaddr(priv); - /* Configure 16K of internal memory - * as 8K RX buffer and 8K TX buffer - */ - w5100_write(priv, W5100_RMSR, 0x03); - w5100_write(priv, W5100_TMSR, 0x03); + if (is_w5200(priv)) + w5200_memory_configure(priv); + else + w5100_memory_configure(priv); } static void w5100_hw_start(struct w5100_priv *priv) { - w5100_write(priv, W5100_S0_MR, priv->promisc ? + w5100_write(priv, W5100_S0_MR(priv), priv->promisc ? S0_MR_MACRAW : S0_MR_MACRAW_MF); w5100_command(priv, S0_CR_OPEN); w5100_write(priv, W5100_IMR, IR_S0); @@ -611,7 +682,7 @@ static void w5100_get_regs(struct net_device *ndev, regs->version = 1; w5100_readbulk(priv, W5100_COMMON_REGS, buf, W5100_COMMON_REGS_LEN); buf += W5100_COMMON_REGS_LEN; - w5100_readbulk(priv, W5100_S0_REGS, buf, W5100_S0_REGS_LEN); + w5100_readbulk(priv, S0_REGS(priv), buf, W5100_S0_REGS_LEN); } static void w5100_restart(struct net_device *ndev) @@ -649,9 +720,9 @@ static void w5100_tx_skb(struct net_device *ndev, struct sk_buff *skb) struct w5100_priv *priv = netdev_priv(ndev); u16 offset; - offset = w5100_read16(priv, W5100_S0_TX_WR); + offset = w5100_read16(priv, W5100_S0_TX_WR(priv)); w5100_writebuf(priv, offset, skb->data, skb->len); - w5100_write16(priv, W5100_S0_TX_WR, offset + skb->len); + w5100_write16(priv, W5100_S0_TX_WR(priv), offset + skb->len); ndev->stats.tx_bytes += skb->len; ndev->stats.tx_packets++; dev_kfree_skb(skb); @@ -696,18 +767,18 @@ static struct sk_buff *w5100_rx_skb(struct net_device *ndev) u16 rx_len; u16 offset; u8 header[2]; - u16 rx_buf_len = w5100_read16(priv, W5100_S0_RX_RSR); + u16 rx_buf_len = w5100_read16(priv, W5100_S0_RX_RSR(priv)); if (rx_buf_len == 0) return NULL; - offset = w5100_read16(priv, W5100_S0_RX_RD); + offset = w5100_read16(priv, W5100_S0_RX_RD(priv)); w5100_readbuf(priv, offset, header, 2); rx_len = get_unaligned_be16(header) - 2; skb = netdev_alloc_skb_ip_align(ndev, rx_len); if (unlikely(!skb)) { - w5100_write16(priv, W5100_S0_RX_RD, offset + rx_buf_len); + w5100_write16(priv, W5100_S0_RX_RD(priv), offset + rx_buf_len); w5100_command(priv, S0_CR_RECV); ndev->stats.rx_dropped++; return NULL; @@ -715,7 +786,7 @@ static struct sk_buff *w5100_rx_skb(struct net_device *ndev) skb_put(skb, rx_len); w5100_readbuf(priv, offset + 2, skb->data, rx_len); - w5100_write16(priv, W5100_S0_RX_RD, offset + 2 + rx_len); + w5100_write16(priv, W5100_S0_RX_RD(priv), offset + 2 + rx_len); w5100_command(priv, S0_CR_RECV); skb->protocol = eth_type_trans(skb, ndev); @@ -764,10 +835,10 @@ static irqreturn_t w5100_interrupt(int irq, void *ndev_instance) struct net_device *ndev = ndev_instance; struct w5100_priv *priv = netdev_priv(ndev); - int ir = w5100_read(priv, W5100_S0_IR); + int ir = w5100_read(priv, W5100_S0_IR(priv)); if (!ir) return IRQ_NONE; - w5100_write(priv, W5100_S0_IR, ir); + w5100_write(priv, W5100_S0_IR(priv), ir); if (ir & S0_IR_SENDOK) { netif_dbg(priv, tx_done, ndev, "tx done\n"); diff --git a/drivers/net/ethernet/wiznet/w5100.h b/drivers/net/ethernet/wiznet/w5100.h index 69045f0f9e10..9b1fa23b46fe 100644 --- a/drivers/net/ethernet/wiznet/w5100.h +++ b/drivers/net/ethernet/wiznet/w5100.h @@ -7,8 +7,14 @@ * Licensed under the GPL-2 or later. */ +enum { + W5100, + W5200, +}; + struct w5100_ops { bool may_sleep; + int chip_id; int (*read)(struct net_device *ndev, u16 addr); int (*write)(struct net_device *ndev, u16 addr, u8 data); int (*read16)(struct net_device *ndev, u16 addr); -- GitLab From aed069df099cd1a27900acb56bb892ec24c66ac4 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 15:33:37 -0400 Subject: [PATCH 3141/9938] ip_tunnel_core: iptunnel_handle_offloads returns int and doesn't free skb This patch updates the IP tunnel core function iptunnel_handle_offloads so that we return an int and do not free the skb inside the function. This actually allows us to clean up several paths in several tunnels so that we can free the skb at one point in the path without having to have a secondary path if we are supporting tunnel offloads. In addition it should resolve some double-free issues I have found in the tunnels paths as I believe it is possible for us to end up triggering such an event in the case of fou or gue. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- drivers/net/geneve.c | 32 ++++++++++++-------------------- drivers/net/vxlan.c | 6 +++--- include/net/ip_tunnels.h | 2 +- include/net/udp_tunnel.h | 3 +-- net/ipv4/fou.c | 16 ++++++++-------- net/ipv4/ip_gre.c | 20 ++++++-------------- net/ipv4/ip_tunnel_core.c | 13 +++++-------- net/ipv4/ipip.c | 7 +++---- net/ipv6/sit.c | 14 ++++++-------- net/netfilter/ipvs/ip_vs_xmit.c | 6 ++---- 10 files changed, 47 insertions(+), 72 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index a9fbf17eb256..efbc7ceedc3a 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -696,16 +696,12 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr); err = skb_cow_head(skb, min_headroom); - if (unlikely(err)) { - kfree_skb(skb); + if (unlikely(err)) goto free_rt; - } - skb = udp_tunnel_handle_offloads(skb, udp_sum); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); + err = udp_tunnel_handle_offloads(skb, udp_sum); + if (err) goto free_rt; - } gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); geneve_build_header(gnvh, tun_flags, vni, opt_len, opt); @@ -733,16 +729,12 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb, min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len + GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr); err = skb_cow_head(skb, min_headroom); - if (unlikely(err)) { - kfree_skb(skb); + if (unlikely(err)) goto free_dst; - } - skb = udp_tunnel_handle_offloads(skb, udp_sum); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); + err = udp_tunnel_handle_offloads(skb, udp_sum); + if (IS_ERR(skb)) goto free_dst; - } gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); geneve_build_header(gnvh, tun_flags, vni, opt_len, opt); @@ -937,7 +929,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, err = geneve_build_skb(rt, skb, key->tun_flags, vni, info->options_len, opts, flags, xnet); if (unlikely(err)) - goto err; + goto tx_error; tos = ip_tunnel_ecn_encap(key->tos, iip, skb); ttl = key->ttl; @@ -946,7 +938,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, err = geneve_build_skb(rt, skb, 0, geneve->vni, 0, NULL, flags, xnet); if (unlikely(err)) - goto err; + goto tx_error; tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb); ttl = geneve->ttl; @@ -964,7 +956,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, tx_error: dev_kfree_skb(skb); -err: + if (err == -ELOOP) dev->stats.collisions++; else if (err == -ENETUNREACH) @@ -1026,7 +1018,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, info->options_len, opts, flags, xnet); if (unlikely(err)) - goto err; + goto tx_error; prio = ip_tunnel_ecn_encap(key->tos, iip, skb); ttl = key->ttl; @@ -1035,7 +1027,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, err = geneve6_build_skb(dst, skb, 0, geneve->vni, 0, NULL, flags, xnet); if (unlikely(err)) - goto err; + goto tx_error; prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel), iip, skb); @@ -1054,7 +1046,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, tx_error: dev_kfree_skb(skb); -err: + if (err == -ELOOP) dev->stats.collisions++; else if (err == -ENETUNREACH) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a7112b3bc9b4..c2e22c2532a1 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1797,9 +1797,9 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, if (WARN_ON(!skb)) return -ENOMEM; - skb = iptunnel_handle_offloads(skb, type); - if (IS_ERR(skb)) - return PTR_ERR(skb); + err = iptunnel_handle_offloads(skb, type); + if (err) + goto out_free; vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = VXLAN_HF_VNI; diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 9ae9fbbccd67..6d790910ebdf 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -309,7 +309,7 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md, gfp_t flags); -struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask); +int iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask); static inline int iptunnel_pull_offloads(struct sk_buff *skb) { diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index 2dcf1de948ac..4f543262dd81 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -105,8 +105,7 @@ struct metadata_dst *udp_tun_rx_dst(struct sk_buff *skb, unsigned short family, __be16 flags, __be64 tunnel_id, int md_size); -static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb, - bool udp_csum) +static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum) { int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index d039f8fff57f..7ac5ec87b004 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -802,11 +802,11 @@ int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; __be16 sport; + int err; - skb = iptunnel_handle_offloads(skb, type); - - if (IS_ERR(skb)) - return PTR_ERR(skb); + err = iptunnel_handle_offloads(skb, type); + if (err) + return err; sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev), skb, 0, 0, false); @@ -826,6 +826,7 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, __be16 sport; void *data; bool need_priv = false; + int err; if ((e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) && skb->ip_summed == CHECKSUM_PARTIAL) { @@ -836,10 +837,9 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, optlen += need_priv ? GUE_LEN_PRIV : 0; - skb = iptunnel_handle_offloads(skb, type); - - if (IS_ERR(skb)) - return PTR_ERR(skb); + err = iptunnel_handle_offloads(skb, type); + if (err) + return err; /* Get source port (based on flow hash) before skb_push */ sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev), diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index af5d1f38217f..eedd829a2f87 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -500,8 +500,7 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); } -static struct sk_buff *gre_handle_offloads(struct sk_buff *skb, - bool csum) +static int gre_handle_offloads(struct sk_buff *skb, bool csum) { return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); } @@ -568,11 +567,8 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) } /* Push Tunnel header. */ - skb = gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)); - if (IS_ERR(skb)) { - skb = NULL; + if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM))) goto err_free_rt; - } flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB), @@ -640,16 +636,14 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, tnl_params = &tunnel->parms.iph; } - skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); - if (IS_ERR(skb)) - goto out; + if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) + goto free_skb; __gre_xmit(skb, dev, tnl_params, skb->protocol); return NETDEV_TX_OK; free_skb: kfree_skb(skb); -out: dev->stats.tx_dropped++; return NETDEV_TX_OK; } @@ -664,9 +658,8 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } - skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); - if (IS_ERR(skb)) - goto out; + if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) + goto free_skb; if (skb_cow_head(skb, dev->needed_headroom)) goto free_skb; @@ -676,7 +669,6 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, free_skb: kfree_skb(skb); -out: dev->stats.tx_dropped++; return NETDEV_TX_OK; } diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 43445df61efd..f46c5c873831 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -146,8 +146,8 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md, } EXPORT_SYMBOL_GPL(iptunnel_metadata_reply); -struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, - int gso_type_mask) +int iptunnel_handle_offloads(struct sk_buff *skb, + int gso_type_mask) { int err; @@ -159,9 +159,9 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, if (skb_is_gso(skb)) { err = skb_unclone(skb, GFP_ATOMIC); if (unlikely(err)) - goto error; + return err; skb_shinfo(skb)->gso_type |= gso_type_mask; - return skb; + return 0; } if (skb->ip_summed != CHECKSUM_PARTIAL) { @@ -174,10 +174,7 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, skb->encapsulation = 0; } - return skb; -error: - kfree_skb(skb); - return ERR_PTR(err); + return 0; } EXPORT_SYMBOL_GPL(iptunnel_handle_offloads); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ec51d02166de..92827483ee3d 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -219,9 +219,8 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(skb->protocol != htons(ETH_P_IP))) goto tx_error; - skb = iptunnel_handle_offloads(skb, SKB_GSO_IPIP); - if (IS_ERR(skb)) - goto out; + if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP)) + goto tx_error; skb_set_inner_ipproto(skb, IPPROTO_IPIP); @@ -230,7 +229,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) tx_error: kfree_skb(skb); -out: + dev->stats.tx_errors++; return NETDEV_TX_OK; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 83384308d032..a13d8c114ccb 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -913,10 +913,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - skb = iptunnel_handle_offloads(skb, SKB_GSO_SIT); - if (IS_ERR(skb)) { + if (iptunnel_handle_offloads(skb, SKB_GSO_SIT)) { ip_rt_put(rt); - goto out; + goto tx_error; } if (df) { @@ -992,7 +991,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, dst_link_failure(skb); tx_error: kfree_skb(skb); -out: dev->stats.tx_errors++; return NETDEV_TX_OK; } @@ -1002,15 +1000,15 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); const struct iphdr *tiph = &tunnel->parms.iph; - skb = iptunnel_handle_offloads(skb, SKB_GSO_IPIP); - if (IS_ERR(skb)) - goto out; + if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP)) + goto tx_error; skb_set_inner_ipproto(skb, IPPROTO_IPIP); ip_tunnel_xmit(skb, dev, tiph, IPPROTO_IPIP); return NETDEV_TX_OK; -out: +tx_error: + kfree_skb(skb); dev->stats.tx_errors++; return NETDEV_TX_OK; } diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index dc196a0f501d..6d19d2eeaa60 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -1013,8 +1013,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, if (IS_ERR(skb)) goto tx_error; - skb = iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET, cp->af)); - if (IS_ERR(skb)) + if (iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET, cp->af))) goto tx_error; skb->transport_header = skb->network_header; @@ -1105,8 +1104,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, if (IS_ERR(skb)) goto tx_error; - skb = iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET6, cp->af)); - if (IS_ERR(skb)) + if (iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET6, cp->af))) goto tx_error; skb->transport_header = skb->network_header; -- GitLab From a9e242ca43b13e5a5d176f97dfd2481c339934b7 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 15:33:45 -0400 Subject: [PATCH 3142/9938] ip6gretap: Fix MTU to allow for Ethernet header When we were creating an ip6gretap interface the MTU was about 6 bytes short of what was needed. It turns out we were not taking the Ethernet header into account and as a result we were eating into the 8 bytes reserved for the encap limit. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/ipv6/ip6_gre.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 4e636e60a360..2be66e7b4a78 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -987,6 +987,8 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) dev->mtu = rt->dst.dev->mtu - addend; if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) dev->mtu -= 8; + if (dev->type == ARPHRD_ETHER) + dev->mtu -= ETH_HLEN; if (dev->mtu < IPV6_MIN_MTU) dev->mtu = IPV6_MIN_MTU; -- GitLab From ac4eb009e4776e9ef4c0484865c2f5a3786eecae Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 15:33:51 -0400 Subject: [PATCH 3143/9938] ip6gre: Add support for basic offloads offloads excluding GSO This patch adds support for the basic offloads we support on most devices. Specifically with this patch set we can support checksum offload, basic scatter-gather, and highdma. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/ipv6/ip6_gre.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 2be66e7b4a78..1a5ad143be40 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -598,6 +598,18 @@ static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) opt->ops.opt_nflen = 8; } +static __sum16 gre6_checksum(struct sk_buff *skb) +{ + __wsum csum; + + if (skb->ip_summed == CHECKSUM_PARTIAL) + csum = lco_csum(skb); + else + csum = skb_checksum(skb, sizeof(struct ipv6hdr), + skb->len - sizeof(struct ipv6hdr), 0); + return csum_fold(csum); +} + static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, @@ -750,8 +762,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, } if (tunnel->parms.o_flags&GRE_CSUM) { *ptr = 0; - *(__sum16 *)ptr = ip_compute_csum((void *)(ipv6h+1), - skb->len - sizeof(struct ipv6hdr)); + *(__sum16 *)ptr = gre6_checksum(skb); } } @@ -1507,6 +1518,11 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = { .ndo_get_iflink = ip6_tnl_get_iflink, }; +#define GRE6_FEATURES (NETIF_F_SG | \ + NETIF_F_FRAGLIST | \ + NETIF_F_HIGHDMA | \ + NETIF_F_HW_CSUM) + static void ip6gre_tap_setup(struct net_device *dev) { @@ -1540,6 +1556,9 @@ static int ip6gre_newlink(struct net *src_net, struct net_device *dev, nt->net = dev_net(dev); ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]); + dev->features |= GRE6_FEATURES; + dev->hw_features |= GRE6_FEATURES; + /* Can use a lockless transmit, unless we generate output sequences */ if (!(nt->parms.o_flags & GRE_SEQ)) dev->features |= NETIF_F_LLTX; -- GitLab From e0c20967c8a653d0213238621381e224d8f065fc Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 15:33:58 -0400 Subject: [PATCH 3144/9938] GRE: Add support for GRO/GSO of IPv6 GRE traffic Since GRE doesn't really care about L3 protocol we can support IPv4 and IPv6 using the same offloads. With that being the case we can add a call to register the offloads for IPv6 as a part of our GRE offload initialization. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/ipv4/gre_offload.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 20557f211408..e88190a8699a 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -292,6 +292,18 @@ static const struct net_offload gre_offload = { static int __init gre_offload_init(void) { - return inet_add_offload(&gre_offload, IPPROTO_GRE); + int err; + + err = inet_add_offload(&gre_offload, IPPROTO_GRE); +#if IS_ENABLED(CONFIG_IPV6) + if (err) + return err; + + err = inet6_add_offload(&gre_offload, IPPROTO_GRE); + if (err) + inet_del_offload(&gre_offload, IPPROTO_GRE); +#endif + + return err; } device_initcall(gre_offload_init); -- GitLab From 3a80e1facd3c825c5ac804bc2efe118872832e33 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 15:34:04 -0400 Subject: [PATCH 3145/9938] ip6gre: Add support for GSO This patch adds code borrowed from bits and pieces of other protocols to the IPv6 GRE path so that we can support GSO over IPv6 based GRE tunnels. By adding this support we are able to significantly improve the throughput for GRE tunnels as we are able to make use of GSO. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/ipv6/ip6_gre.c | 56 +++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 1a5ad143be40..ca5a2c5675c5 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -621,7 +621,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, struct net *net = tunnel->net; struct net_device *tdev; /* Device to other host */ struct ipv6hdr *ipv6h; /* Our new IP header */ - unsigned int max_headroom = 0; /* The extra header space needed */ + unsigned int min_headroom = 0; /* The extra header space needed */ int gre_hlen; struct ipv6_tel_txoption opt; int mtu; @@ -629,7 +629,6 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, struct net_device_stats *stats = &tunnel->dev->stats; int err = -1; u8 proto; - struct sk_buff *new_skb; __be16 protocol; if (dev->type == ARPHRD_ETHER) @@ -672,14 +671,14 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, mtu = dst_mtu(dst) - sizeof(*ipv6h); if (encap_limit >= 0) { - max_headroom += 8; + min_headroom += 8; mtu -= 8; } if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; if (skb_dst(skb)) skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); - if (skb->len > mtu) { + if (skb->len > mtu && !skb_is_gso(skb)) { *pmtu = mtu; err = -EMSGSIZE; goto tx_err_dst_release; @@ -697,20 +696,19 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); - max_headroom += LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len; + min_headroom += LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len; - if (skb_headroom(skb) < max_headroom || skb_shared(skb) || - (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { - new_skb = skb_realloc_headroom(skb, max_headroom); - if (max_headroom > dev->needed_headroom) - dev->needed_headroom = max_headroom; - if (!new_skb) - goto tx_err_dst_release; + if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { + int head_delta = SKB_DATA_ALIGN(min_headroom - + skb_headroom(skb) + + 16); - if (skb->sk) - skb_set_owner_w(new_skb, skb->sk); - consume_skb(skb); - skb = new_skb; + err = pskb_expand_head(skb, max_t(int, head_delta, 0), + 0, GFP_ATOMIC); + if (min_headroom > dev->needed_headroom) + dev->needed_headroom = min_headroom; + if (unlikely(err)) + goto tx_err_dst_release; } if (!fl6->flowi6_mark && ndst) @@ -723,10 +721,11 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); } - if (likely(!skb->encapsulation)) { - skb_reset_inner_headers(skb); - skb->encapsulation = 1; - } + err = iptunnel_handle_offloads(skb, + (tunnel->parms.o_flags & GRE_CSUM) ? + SKB_GSO_GRE_CSUM : SKB_GSO_GRE); + if (err) + goto tx_err_dst_release; skb_push(skb, gre_hlen); skb_reset_network_header(skb); @@ -760,7 +759,9 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, *ptr = tunnel->parms.o_key; ptr--; } - if (tunnel->parms.o_flags&GRE_CSUM) { + if ((tunnel->parms.o_flags & GRE_CSUM) && + !(skb_shinfo(skb)->gso_type & + (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) { *ptr = 0; *(__sum16 *)ptr = gre6_checksum(skb); } @@ -1559,9 +1560,18 @@ static int ip6gre_newlink(struct net *src_net, struct net_device *dev, dev->features |= GRE6_FEATURES; dev->hw_features |= GRE6_FEATURES; - /* Can use a lockless transmit, unless we generate output sequences */ - if (!(nt->parms.o_flags & GRE_SEQ)) + if (!(nt->parms.o_flags & GRE_SEQ)) { + /* TCP segmentation offload is not supported when we + * generate output sequences. + */ + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; + + /* Can use a lockless transmit, unless we generate + * output sequences + */ dev->features |= NETIF_F_LLTX; + } err = register_netdevice(dev); if (err) -- GitLab From 756ca874417695f77941948a77e9b8562635cc0a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 17:04:34 -0400 Subject: [PATCH 3146/9938] netdev_features: Add NETIF_F_TSO_MANGLEID to NETIF_F_ALL_TSO I realized that when I added NETIF_F_TSO_MANGLEID as a TSO type I forgot to add it to NETIF_F_ALL_TSO. This patch corrects that so the flag will be included correctly. The result should be minor as it was only used by a few drivers and in a few specific cases such as when NETIF_F_SG was not supported on a device so the TSO flags were cleared. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- include/linux/netdev_features.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 9fc79df0e561..15eb0b12fff9 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -164,7 +164,8 @@ enum { #define NETIF_F_CSUM_MASK (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ NETIF_F_HW_CSUM) -#define NETIF_F_ALL_TSO (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) +#define NETIF_F_ALL_TSO (NETIF_F_TSO | NETIF_F_TSO6 | \ + NETIF_F_TSO_ECN | NETIF_F_TSO_MANGLEID) #define NETIF_F_ALL_FCOE (NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU | \ NETIF_F_FSO) -- GitLab From 48ace4ef4c3f99ebf6f801c9a8326a4a39f31dbf Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Thu, 14 Apr 2016 23:47:12 +0200 Subject: [PATCH 3147/9938] dsa: mv88e6xxx: Kill the REG_READ and REG_WRITE macros These macros hide a ds variable and a return statement on error, which can lead to locking issues. Kill them off. Signed-off-by: Andrew Lunn Tested-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123.c | 13 +- drivers/net/dsa/mv88e6131.c | 41 +++--- drivers/net/dsa/mv88e6171.c | 16 ++- drivers/net/dsa/mv88e6352.c | 15 ++- drivers/net/dsa/mv88e6xxx.c | 241 ++++++++++++++++++++++++++---------- drivers/net/dsa/mv88e6xxx.h | 21 ---- 6 files changed, 224 insertions(+), 123 deletions(-) diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index c34283d929c4..140e44e50e8a 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -52,7 +52,9 @@ static int mv88e6123_setup_global(struct dsa_switch *ds) * external PHYs to poll), don't discard packets with * excessive collisions, and mask all interrupt sources. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, 0x0000); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, 0x0000); + if (ret) + return ret; /* Configure the upstream port, and configure the upstream * port as the port to which ingress and egress monitor frames @@ -61,14 +63,15 @@ static int mv88e6123_setup_global(struct dsa_switch *ds) reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT | upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT; - REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* Disable remote management for now, and set the switch's * DSA device number. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f); - - return 0; + return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2, + ds->index & 0x1f); } static int mv88e6123_setup(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index f5d75fce1e96..34d297b65040 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -49,11 +49,16 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) * to arbitrate between packet queues, set the maximum frame * size to 1632, and mask all interrupt sources. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_MAX_FRAME_1632); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, + GLOBAL_CONTROL_PPU_ENABLE | + GLOBAL_CONTROL_MAX_FRAME_1632); + if (ret) + return ret; /* Set the VLAN ethertype to 0x8100. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100); + if (ret) + return ret; /* Disable ARP mirroring, and configure the upstream port as * the port to which ingress and egress monitor frames are to @@ -62,31 +67,33 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT | GLOBAL_MONITOR_CONTROL_ARP_DISABLED; - REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* Disable cascade port functionality unless this device * is used in a cascade configuration, and set the switch's * DSA device number. */ if (ds->dst->pd->nr_chips > 1) - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, - GLOBAL_CONTROL_2_MULTIPLE_CASCADE | - (ds->index & 0x1f)); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2, + GLOBAL_CONTROL_2_MULTIPLE_CASCADE | + (ds->index & 0x1f)); else - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, - GLOBAL_CONTROL_2_NO_CASCADE | - (ds->index & 0x1f)); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2, + GLOBAL_CONTROL_2_NO_CASCADE | + (ds->index & 0x1f)); + if (ret) + return ret; /* Force the priority of IGMP/MLD snoop frames and ARP frames * to the highest setting. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE, - GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP | - 7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT | - GLOBAL2_PRIO_OVERRIDE_FORCE_ARP | - 7 << GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT); - - return 0; + return mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE, + GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP | + 7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT | + GLOBAL2_PRIO_OVERRIDE_FORCE_ARP | + 7 << GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT); } static int mv88e6131_setup(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index f5622506cdfa..b7af2b78f8ee 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -46,8 +46,11 @@ static int mv88e6171_setup_global(struct dsa_switch *ds) /* Discard packets with excessive collisions, mask all * interrupt sources, enable PPU. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, + GLOBAL_CONTROL_PPU_ENABLE | + GLOBAL_CONTROL_DISCARD_EXCESS); + if (ret) + return ret; /* Configure the upstream port, and configure the upstream * port as the port to which ingress and egress monitor frames @@ -57,14 +60,15 @@ static int mv88e6171_setup_global(struct dsa_switch *ds) upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT | upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT | upstream_port << GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT; - REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* Disable remote management for now, and set the switch's * DSA device number. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f); - - return 0; + return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL_2, + ds->index & 0x1f); } static int mv88e6171_setup(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index e54ee27db129..e8cb03fad21a 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -59,8 +59,11 @@ static int mv88e6352_setup_global(struct dsa_switch *ds) /* Discard packets with excessive collisions, * mask all interrupt sources, enable PPU (bit 14, undocumented). */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, + GLOBAL_CONTROL_PPU_ENABLE | + GLOBAL_CONTROL_DISCARD_EXCESS); + if (ret) + return ret; /* Configure the upstream port, and configure the upstream * port as the port to which ingress and egress monitor frames @@ -69,14 +72,14 @@ static int mv88e6352_setup_global(struct dsa_switch *ds) reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT | upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT; - REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* Disable remote management for now, and set the switch's * DSA device number. */ - REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); - - return 0; + return mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1c, ds->index & 0x1f); } static int mv88e6352_setup(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 9985a0cf31f1..b018f20829fb 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -180,28 +180,44 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr) { - REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 8) | addr[1]); - REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]); - REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]); + int err; - return 0; + err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_01, + (addr[0] << 8) | addr[1]); + if (err) + return err; + + err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_23, + (addr[2] << 8) | addr[3]); + if (err) + return err; + + return mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_MAC_45, + (addr[4] << 8) | addr[5]); } int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) { - int i; int ret; + int i; for (i = 0; i < 6; i++) { int j; /* Write the MAC address byte. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_SWITCH_MAC, - GLOBAL2_SWITCH_MAC_BUSY | (i << 8) | addr[i]); + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SWITCH_MAC, + GLOBAL2_SWITCH_MAC_BUSY | + (i << 8) | addr[i]); + if (ret) + return ret; /* Wait for the write to complete. */ for (j = 0; j < 16; j++) { - ret = REG_READ(REG_GLOBAL2, GLOBAL2_SWITCH_MAC); + ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, + GLOBAL2_SWITCH_MAC); + if (ret < 0) + return ret; + if ((ret & GLOBAL2_SWITCH_MAC_BUSY) == 0) break; } @@ -233,13 +249,21 @@ static int mv88e6xxx_ppu_disable(struct dsa_switch *ds) int ret; unsigned long timeout; - ret = REG_READ(REG_GLOBAL, GLOBAL_CONTROL); - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - ret & ~GLOBAL_CONTROL_PPU_ENABLE); + ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL); + if (ret < 0) + return ret; + + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, + ret & ~GLOBAL_CONTROL_PPU_ENABLE); + if (ret) + return ret; timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { - ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS); + ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATUS); + if (ret < 0) + return ret; + usleep_range(1000, 2000); if ((ret & GLOBAL_STATUS_PPU_MASK) != GLOBAL_STATUS_PPU_POLLING) @@ -251,15 +275,24 @@ static int mv88e6xxx_ppu_disable(struct dsa_switch *ds) static int mv88e6xxx_ppu_enable(struct dsa_switch *ds) { - int ret; + int ret, err; unsigned long timeout; - ret = REG_READ(REG_GLOBAL, GLOBAL_CONTROL); - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, ret | GLOBAL_CONTROL_PPU_ENABLE); + ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_CONTROL); + if (ret < 0) + return ret; + + err = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_CONTROL, + ret | GLOBAL_CONTROL_PPU_ENABLE); + if (err) + return err; timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { - ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS); + ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATUS); + if (ret < 0) + return ret; + usleep_range(1000, 2000); if ((ret & GLOBAL_STATUS_PPU_MASK) == GLOBAL_STATUS_PPU_POLLING) @@ -2667,7 +2700,9 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) ps->ds = ds; mutex_init(&ps->smi_mutex); - ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; + ps->id = mv88e6xxx_reg_read(ds, REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; + if (ps->id < 0) + return ps->id; INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); @@ -2677,42 +2712,67 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) int mv88e6xxx_setup_global(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int ret; + int err; int i; + mutex_lock(&ps->smi_mutex); /* Set the default address aging time to 5 minutes, and * enable address learn messages to be sent to all message * ports. */ - REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL, - 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL, + 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL); + if (err) + goto unlock; /* Configure the IP ToS mapping registers. */ - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000); - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000); - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555); - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555); - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa); - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa); - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff); - REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff); + if (err) + goto unlock; /* Configure the IEEE 802.1p priority mapping register. */ - REG_WRITE(REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41); + if (err) + goto unlock; /* Send all frames with destination addresses matching * 01:80:c2:00:00:0x to the CPU port. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff); + if (err) + goto unlock; /* Ignore removed tag data on doubly tagged packets, disable * flow control messages, force flow control priority to the * highest, and send all special multicast frames to the CPU * port at the highest priority. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_SWITCH_MGMT, - 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 | - GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT, + 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 | + GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI); + if (err) + goto unlock; /* Program the DSA routing table. */ for (i = 0; i < 32; i++) { @@ -2722,23 +2782,35 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) i != ds->index && i < ds->dst->pd->nr_chips) nexthop = ds->pd->rtable[i] & 0x1f; - REG_WRITE(REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING, - GLOBAL2_DEVICE_MAPPING_UPDATE | - (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | - nexthop); + err = _mv88e6xxx_reg_write( + ds, REG_GLOBAL2, + GLOBAL2_DEVICE_MAPPING, + GLOBAL2_DEVICE_MAPPING_UPDATE | + (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop); + if (err) + goto unlock; } /* Clear all trunk masks. */ - for (i = 0; i < 8; i++) - REG_WRITE(REG_GLOBAL2, GLOBAL2_TRUNK_MASK, - 0x8000 | (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) | - ((1 << ps->num_ports) - 1)); + for (i = 0; i < 8; i++) { + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK, + 0x8000 | + (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) | + ((1 << ps->num_ports) - 1)); + if (err) + goto unlock; + } /* Clear all trunk mappings. */ - for (i = 0; i < 16; i++) - REG_WRITE(REG_GLOBAL2, GLOBAL2_TRUNK_MAPPING, - GLOBAL2_TRUNK_MAPPING_UPDATE | - (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT)); + for (i = 0; i < 16; i++) { + err = _mv88e6xxx_reg_write( + ds, REG_GLOBAL2, + GLOBAL2_TRUNK_MAPPING, + GLOBAL2_TRUNK_MAPPING_UPDATE | + (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT)); + if (err) + goto unlock; + } if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || @@ -2746,17 +2818,27 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) /* Send all frames with destination addresses matching * 01:80:c2:00:00:2x to the CPU port. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_MGMT_EN_2X, 0xffff); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, + GLOBAL2_MGMT_EN_2X, 0xffff); + if (err) + goto unlock; /* Initialise cross-chip port VLAN table to reset * defaults. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_PVT_ADDR, 0x9000); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, + GLOBAL2_PVT_ADDR, 0x9000); + if (err) + goto unlock; /* Clear the priority override table. */ - for (i = 0; i < 16; i++) - REG_WRITE(REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE, - 0x8000 | (i << 8)); + for (i = 0; i < 16; i++) { + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, + GLOBAL2_PRIO_OVERRIDE, + 0x8000 | (i << 8)); + if (err) + goto unlock; + } } if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || @@ -2767,31 +2849,37 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) * ingress rate limit registers to their initial * state. */ - for (i = 0; i < ps->num_ports; i++) - REG_WRITE(REG_GLOBAL2, GLOBAL2_INGRESS_OP, - 0x9000 | (i << 8)); + for (i = 0; i < ps->num_ports; i++) { + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, + GLOBAL2_INGRESS_OP, + 0x9000 | (i << 8)); + if (err) + goto unlock; + } } /* Clear the statistics counters for all ports */ - REG_WRITE(REG_GLOBAL, GLOBAL_STATS_OP, GLOBAL_STATS_OP_FLUSH_ALL); + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP, + GLOBAL_STATS_OP_FLUSH_ALL); + if (err) + goto unlock; /* Wait for the flush to complete. */ - mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_stats_wait(ds); - if (ret < 0) + err = _mv88e6xxx_stats_wait(ds); + if (err < 0) goto unlock; /* Clear all ATU entries */ - ret = _mv88e6xxx_atu_flush(ds, 0, true); - if (ret < 0) + err = _mv88e6xxx_atu_flush(ds, 0, true); + if (err < 0) goto unlock; /* Clear all the VTU and STU entries */ - ret = _mv88e6xxx_vtu_stu_flush(ds); + err = _mv88e6xxx_vtu_stu_flush(ds); unlock: mutex_unlock(&ps->smi_mutex); - return ret; + return err; } int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) @@ -2803,10 +2891,18 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) int ret; int i; + mutex_lock(&ps->smi_mutex); + /* Set all ports to the disabled state. */ for (i = 0; i < ps->num_ports; i++) { - ret = REG_READ(REG_PORT(i), PORT_CONTROL); - REG_WRITE(REG_PORT(i), PORT_CONTROL, ret & 0xfffc); + ret = _mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL); + if (ret < 0) + goto unlock; + + ret = _mv88e6xxx_reg_write(ds, REG_PORT(i), PORT_CONTROL, + ret & 0xfffc); + if (ret) + goto unlock; } /* Wait for transmit queues to drain. */ @@ -2825,22 +2921,31 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) * through global registers 0x18 and 0x19. */ if (ppu_active) - REG_WRITE(REG_GLOBAL, 0x04, 0xc000); + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x04, 0xc000); else - REG_WRITE(REG_GLOBAL, 0x04, 0xc400); + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x04, 0xc400); + if (ret) + goto unlock; /* Wait up to one second for reset to complete. */ timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { - ret = REG_READ(REG_GLOBAL, 0x00); + ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x00); + if (ret < 0) + goto unlock; + if ((ret & is_reset) == is_reset) break; usleep_range(1000, 2000); } if (time_after(jiffies, timeout)) - return -ETIMEDOUT; + ret = -ETIMEDOUT; + else + ret = 0; +unlock: + mutex_unlock(&ps->smi_mutex); - return 0; + return ret; } int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 5d27decc85cb..0debb9f3cf0a 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -542,25 +542,4 @@ extern struct dsa_switch_driver mv88e6123_switch_driver; extern struct dsa_switch_driver mv88e6352_switch_driver; extern struct dsa_switch_driver mv88e6171_switch_driver; -#define REG_READ(addr, reg) \ - ({ \ - int __ret; \ - \ - __ret = mv88e6xxx_reg_read(ds, addr, reg); \ - if (__ret < 0) \ - return __ret; \ - __ret; \ - }) - -#define REG_WRITE(addr, reg, val) \ - ({ \ - int __ret; \ - \ - __ret = mv88e6xxx_reg_write(ds, addr, reg, val); \ - if (__ret < 0) \ - return __ret; \ - }) - - - #endif -- GitLab From f66bc94174e850a4de4adbe7a08fc37507051185 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 14 Apr 2016 20:42:29 -0500 Subject: [PATCH 3148/9938] stmmac: socfpga: remove extra call to socfpga_dwmac_setup In the socfpga_dwmac_probe function, we have a call to socfpga_dwmac_setup, which is already called from socfpga_dwmac_init later in the probe function. Remove this extra call to socfpga_dwmac_setup. Also we should not be calling socfpga_dwmac_setup() directly without wrapping it around the proper reset assert/deasserts. That is because the socfpga_dwmac_setup() is setting up PHY modes in the system manager, and it is requires the EMAC's to be in reset during the PHY setup. Reported-by: Matthew Gerlach Signed-off-by: Dinh Nguyen Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index f0d797ab74d8..41f4c58b22bd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -267,12 +267,6 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) return ret; } - ret = socfpga_dwmac_setup(dwmac); - if (ret) { - dev_err(dev, "couldn't setup SoC glue (%d)\n", ret); - return ret; - } - plat_dat->bsp_priv = dwmac; plat_dat->init = socfpga_dwmac_init; plat_dat->exit = socfpga_dwmac_exit; -- GitLab From da5a2383c9a2de88550841f6c100f991a6850230 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 15 Apr 2016 11:25:21 +0900 Subject: [PATCH 3149/9938] fjes: optimize timeout value This patch optimizes the following timeout value. - FJES_DEVICE_RESET_TIMEOUT - FJES_COMMAND_REQ_TIMEOUT - FJES_COMMAND_REQ_BUFF_TIMEOUT Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_hw.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h index 6d57b89a0ee8..baee7f59834b 100644 --- a/drivers/net/fjes/fjes_hw.h +++ b/drivers/net/fjes/fjes_hw.h @@ -33,9 +33,9 @@ struct fjes_hw; #define EP_BUFFER_SUPPORT_VLAN_MAX 4 #define EP_BUFFER_INFO_SIZE 4096 -#define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3) /* sec */ -#define FJES_COMMAND_REQ_TIMEOUT (5 + 1) /* sec */ -#define FJES_COMMAND_REQ_BUFF_TIMEOUT (8 * 3) /* sec */ +#define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3 * 8) /* sec */ +#define FJES_COMMAND_REQ_TIMEOUT ((5 + 1) * 3 * 8) /* sec */ +#define FJES_COMMAND_REQ_BUFF_TIMEOUT (60 * 3) /* sec */ #define FJES_COMMAND_EPSTOP_WAIT_TIMEOUT (1) /* sec */ #define FJES_CMD_REQ_ERR_INFO_PARAM (0x0001) -- GitLab From 3c3bd4a91ec12ad7c140bb3fd04b199e411760cb Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 15 Apr 2016 11:25:27 +0900 Subject: [PATCH 3150/9938] fjes: fix incorrect statistics information in fjes_xmit_frame() There are bugs of acounting statistics in fjes_xmit_frame(). Accounting self stats is wrong. accounting stats of other EPs to be transmitted is right. This patch fixes this bug. Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 061b4af4ee62..05bdd8bfee00 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -653,7 +653,7 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) &adapter->hw.ep_shm_info[dest_epid].rx, 0)) { /* version is NOT 0 */ adapter->stats64.tx_carrier_errors += 1; - hw->ep_shm_info[my_epid].net_stats + hw->ep_shm_info[dest_epid].net_stats .tx_carrier_errors += 1; ret = NETDEV_TX_OK; @@ -661,9 +661,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) &adapter->hw.ep_shm_info[dest_epid].rx, netdev->mtu)) { adapter->stats64.tx_dropped += 1; - hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1; + hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1; adapter->stats64.tx_errors += 1; - hw->ep_shm_info[my_epid].net_stats.tx_errors += 1; + hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1; ret = NETDEV_TX_OK; } else if (vlan && @@ -694,10 +694,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) (long)adapter->tx_start_jiffies) >= FJES_TX_RETRY_TIMEOUT) { adapter->stats64.tx_fifo_errors += 1; - hw->ep_shm_info[my_epid].net_stats + hw->ep_shm_info[dest_epid].net_stats .tx_fifo_errors += 1; adapter->stats64.tx_errors += 1; - hw->ep_shm_info[my_epid].net_stats + hw->ep_shm_info[dest_epid].net_stats .tx_errors += 1; ret = NETDEV_TX_OK; @@ -714,10 +714,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } else { if (!is_multi) { adapter->stats64.tx_packets += 1; - hw->ep_shm_info[my_epid].net_stats + hw->ep_shm_info[dest_epid].net_stats .tx_packets += 1; adapter->stats64.tx_bytes += len; - hw->ep_shm_info[my_epid].net_stats + hw->ep_shm_info[dest_epid].net_stats .tx_bytes += len; } -- GitLab From 19a0a7fd55af4658414de955f401cddaffc1f0ba Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 15 Apr 2016 11:25:34 +0900 Subject: [PATCH 3151/9938] fjes: fix bitwise check bug in fjes_raise_intr_rxdata_task In fjes_raise_intr_rxdata_task(), there's a bug of bitwise check because of missing "& FJES_RX_POLL_WORK". This patch fixes this bug. Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 05bdd8bfee00..e22a86976dcf 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -549,7 +549,8 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work) if ((hw->ep_shm_info[epid].tx_status_work == FJES_TX_DELAY_SEND_PENDING) && (pstatus == EP_PARTNER_SHARED) && - !(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) { + !(hw->ep_shm_info[epid].rx.info->v1i.rx_status & + FJES_RX_POLL_WORK)) { fjes_hw_raise_interrupt(hw, epid, REG_ICTL_MASK_RX_DATA); } -- GitLab From 16bbec3a50efec46b679c3408c8be09f09dbcb7e Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 15 Apr 2016 11:25:40 +0900 Subject: [PATCH 3152/9938] fjes: Enhance changing MTU related work This patch enhances the fjes_change_mtu() method by introducing new flag named FJES_RX_MTU_CHANGING_DONE in rx_status. At the same time, default MTU value is changed into 65510 bytes. Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_hw.c | 8 ++++- drivers/net/fjes/fjes_hw.h | 1 + drivers/net/fjes/fjes_main.c | 60 ++++++++++++++++++++++++++++++------ 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index b103adb8d62e..e9f494bd70ad 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -179,6 +179,8 @@ void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu) for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) info->v1i.vlan_id[i] = vlan_id[i]; + + info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE; } void @@ -810,7 +812,8 @@ bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu) { union ep_buffer_info *info = epbh->info; - return (info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)); + return ((info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)) && + info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE); } bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id) @@ -863,6 +866,9 @@ bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh) { union ep_buffer_info *info = epbh->info; + if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE)) + return true; + if (info->v1i.count_max == 0) return true; diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h index baee7f59834b..f40cf0792a39 100644 --- a/drivers/net/fjes/fjes_hw.h +++ b/drivers/net/fjes/fjes_hw.h @@ -57,6 +57,7 @@ struct fjes_hw; #define FJES_RX_STOP_REQ_DONE (0x1) #define FJES_RX_STOP_REQ_REQUEST (0x2) #define FJES_RX_POLL_WORK (0x4) +#define FJES_RX_MTU_CHANGING_DONE (0x8) #define EP_BUFFER_SIZE \ (((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \ diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index e22a86976dcf..3c0c1202f237 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -481,6 +481,9 @@ static void fjes_tx_stall_task(struct work_struct *work) info = adapter->hw.ep_shm_info[epid].tx.info; + if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE)) + return; + if (EP_RING_FULL(info->v1i.head, info->v1i.tail, info->v1i.count_max)) { all_queue_available = 0; @@ -760,9 +763,11 @@ fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) static int fjes_change_mtu(struct net_device *netdev, int new_mtu) { + struct fjes_adapter *adapter = netdev_priv(netdev); bool running = netif_running(netdev); - int ret = 0; - int idx; + struct fjes_hw *hw = &adapter->hw; + int ret = -EINVAL; + int idx, epidx; for (idx = 0; fjes_support_mtu[idx] != 0; idx++) { if (new_mtu <= fjes_support_mtu[idx]) { @@ -770,19 +775,54 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu) if (new_mtu == netdev->mtu) return 0; - if (running) - fjes_close(netdev); + ret = 0; + break; + } + } + + if (ret) + return ret; + + if (running) { + for (epidx = 0; epidx < hw->max_epid; epidx++) { + if (epidx == hw->my_epid) + continue; + hw->ep_shm_info[epidx].tx.info->v1i.rx_status &= + ~FJES_RX_MTU_CHANGING_DONE; + } + netif_tx_stop_all_queues(netdev); + netif_carrier_off(netdev); + cancel_work_sync(&adapter->tx_stall_task); + napi_disable(&adapter->napi); + + msleep(1000); - netdev->mtu = new_mtu; + netif_tx_stop_all_queues(netdev); + } - if (running) - ret = fjes_open(netdev); + netdev->mtu = new_mtu; - return ret; + if (running) { + for (epidx = 0; epidx < hw->max_epid; epidx++) { + if (epidx == hw->my_epid) + continue; + + local_irq_disable(); + fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, + netdev->dev_addr, + netdev->mtu); + local_irq_enable(); + + hw->ep_shm_info[epidx].tx.info->v1i.rx_status |= + FJES_RX_MTU_CHANGING_DONE; } + + netif_tx_wake_all_queues(netdev); + netif_carrier_on(netdev); + napi_enable(&adapter->napi); } - return -EINVAL; + return ret; } static int fjes_vlan_rx_add_vid(struct net_device *netdev, @@ -1204,7 +1244,7 @@ static void fjes_netdev_setup(struct net_device *netdev) netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL; netdev->netdev_ops = &fjes_netdev_ops; fjes_set_ethtool_ops(netdev); - netdev->mtu = fjes_support_mtu[0]; + netdev->mtu = fjes_support_mtu[3]; netdev->flags |= IFF_BROADCAST; netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; } -- GitLab From bd5a256991f9a9cc0b7f6385dd1d8cfc90559b12 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 15 Apr 2016 11:25:46 +0900 Subject: [PATCH 3153/9938] fjes: Introduce spinlock for rx_status This patch introduces spinlock of rx_status for proper excusive control. Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_hw.c | 22 +++++++++++++- drivers/net/fjes/fjes_hw.h | 2 ++ drivers/net/fjes/fjes_main.c | 57 +++++++++++++++++++++++++++++++----- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index e9f494bd70ad..0dbafedc0a34 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -216,6 +216,7 @@ static int fjes_hw_setup(struct fjes_hw *hw) u8 mac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; struct fjes_device_command_param param; struct ep_share_mem_info *buf_pair; + unsigned long flags; size_t mem_size; int result; int epidx; @@ -264,10 +265,12 @@ static int fjes_hw_setup(struct fjes_hw *hw) if (result) return result; + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&buf_pair->tx, mac, fjes_support_mtu[0]); fjes_hw_setup_epbuf(&buf_pair->rx, mac, fjes_support_mtu[0]); + spin_unlock_irqrestore(&hw->rx_status_lock, flags); } } @@ -329,6 +332,7 @@ int fjes_hw_init(struct fjes_hw *hw) INIT_WORK(&hw->epstop_task, fjes_hw_epstop_task); mutex_init(&hw->hw_info.lock); + spin_lock_init(&hw->rx_status_lock); hw->max_epid = fjes_hw_get_max_epid(hw); hw->my_epid = fjes_hw_get_my_epid(hw); @@ -736,6 +740,7 @@ fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid) void fjes_hw_raise_epstop(struct fjes_hw *hw) { enum ep_partner_status status; + unsigned long flags; int epidx; for (epidx = 0; epidx < hw->max_epid; epidx++) { @@ -755,8 +760,10 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw) set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); set_bit(epidx, &hw->txrx_stop_req_bit); + spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[epidx].tx.info->v1i.rx_status |= FJES_RX_STOP_REQ_REQUEST; + spin_unlock_irqrestore(&hw->rx_status_lock, flags); } } @@ -938,6 +945,7 @@ static void fjes_hw_update_zone_task(struct work_struct *work) struct fjes_adapter *adapter; struct net_device *netdev; + unsigned long flags; ulong unshare_bit = 0; ulong share_bit = 0; @@ -1030,8 +1038,10 @@ static void fjes_hw_update_zone_task(struct work_struct *work) continue; if (test_bit(epidx, &share_bit)) { + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); + spin_unlock_irqrestore(&hw->rx_status_lock, flags); mutex_lock(&hw->hw_info.lock); @@ -1075,10 +1085,14 @@ static void fjes_hw_update_zone_task(struct work_struct *work) mutex_unlock(&hw->hw_info.lock); - if (ret == 0) + if (ret == 0) { + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf( &hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); + spin_unlock_irqrestore(&hw->rx_status_lock, + flags); + } } if (test_bit(epidx, &irq_bit)) { @@ -1086,9 +1100,11 @@ static void fjes_hw_update_zone_task(struct work_struct *work) REG_ICTL_MASK_TXRX_STOP_REQ); set_bit(epidx, &hw->txrx_stop_req_bit); + spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[epidx].tx. info->v1i.rx_status |= FJES_RX_STOP_REQ_REQUEST; + spin_unlock_irqrestore(&hw->rx_status_lock, flags); set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); } } @@ -1104,6 +1120,7 @@ static void fjes_hw_epstop_task(struct work_struct *work) { struct fjes_hw *hw = container_of(work, struct fjes_hw, epstop_task); struct fjes_adapter *adapter = (struct fjes_adapter *)hw->back; + unsigned long flags; ulong remain_bit; int epid_bit; @@ -1111,9 +1128,12 @@ static void fjes_hw_epstop_task(struct work_struct *work) while ((remain_bit = hw->epstop_req_bit)) { for (epid_bit = 0; remain_bit; remain_bit >>= 1, epid_bit++) { if (remain_bit & 1) { + spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[epid_bit]. tx.info->v1i.rx_status |= FJES_RX_STOP_REQ_DONE; + spin_unlock_irqrestore(&hw->rx_status_lock, + flags); clear_bit(epid_bit, &hw->epstop_req_bit); set_bit(epid_bit, diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h index f40cf0792a39..1445ac99d6e3 100644 --- a/drivers/net/fjes/fjes_hw.h +++ b/drivers/net/fjes/fjes_hw.h @@ -300,6 +300,8 @@ struct fjes_hw { u8 *base; struct fjes_hw_info hw_info; + + spinlock_t rx_status_lock; /* spinlock for rx_status */ }; int fjes_hw_init(struct fjes_hw *); diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 3c0c1202f237..87b24748bfcd 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -290,6 +290,7 @@ static int fjes_close(struct net_device *netdev) { struct fjes_adapter *adapter = netdev_priv(netdev); struct fjes_hw *hw = &adapter->hw; + unsigned long flags; int epidx; netif_tx_stop_all_queues(netdev); @@ -299,13 +300,18 @@ static int fjes_close(struct net_device *netdev) napi_disable(&adapter->napi); + spin_lock_irqsave(&hw->rx_status_lock, flags); for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; - adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &= - ~FJES_RX_POLL_WORK; + if (fjes_hw_get_partner_ep_status(hw, epidx) == + EP_PARTNER_SHARED) + adapter->hw.ep_shm_info[epidx] + .tx.info->v1i.rx_status &= + ~FJES_RX_POLL_WORK; } + spin_unlock_irqrestore(&hw->rx_status_lock, flags); fjes_free_irq(adapter); @@ -330,6 +336,7 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) struct net_device *netdev = adapter->netdev; struct ep_share_mem_info *buf_pair; struct fjes_hw *hw = &adapter->hw; + unsigned long flags; int result; int epidx; @@ -371,8 +378,10 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) buf_pair = &hw->ep_shm_info[epidx]; + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr, netdev->mtu); + spin_unlock_irqrestore(&hw->rx_status_lock, flags); if (fjes_hw_epid_is_same_zone(hw, epidx)) { mutex_lock(&hw->hw_info.lock); @@ -402,6 +411,7 @@ static void fjes_free_resources(struct fjes_adapter *adapter) struct ep_share_mem_info *buf_pair; struct fjes_hw *hw = &adapter->hw; bool reset_flag = false; + unsigned long flags; int result; int epidx; @@ -418,8 +428,10 @@ static void fjes_free_resources(struct fjes_adapter *adapter) buf_pair = &hw->ep_shm_info[epidx]; + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr, netdev->mtu); + spin_unlock_irqrestore(&hw->rx_status_lock, flags); clear_bit(epidx, &hw->txrx_stop_req_bit); } @@ -766,6 +778,7 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu) struct fjes_adapter *adapter = netdev_priv(netdev); bool running = netif_running(netdev); struct fjes_hw *hw = &adapter->hw; + unsigned long flags; int ret = -EINVAL; int idx, epidx; @@ -784,12 +797,15 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu) return ret; if (running) { + spin_lock_irqsave(&hw->rx_status_lock, flags); for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; hw->ep_shm_info[epidx].tx.info->v1i.rx_status &= ~FJES_RX_MTU_CHANGING_DONE; } + spin_unlock_irqrestore(&hw->rx_status_lock, flags); + netif_tx_stop_all_queues(netdev); netif_carrier_off(netdev); cancel_work_sync(&adapter->tx_stall_task); @@ -803,23 +819,25 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu) netdev->mtu = new_mtu; if (running) { + spin_lock_irqsave(&hw->rx_status_lock, flags); for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; - local_irq_disable(); + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); - local_irq_enable(); hw->ep_shm_info[epidx].tx.info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE; + spin_unlock_irqrestore(&hw->rx_status_lock, flags); } netif_tx_wake_all_queues(netdev); netif_carrier_on(netdev); napi_enable(&adapter->napi); + napi_schedule(&adapter->napi); } return ret; @@ -866,6 +884,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter, { struct fjes_hw *hw = &adapter->hw; enum ep_partner_status status; + unsigned long flags; status = fjes_hw_get_partner_ep_status(hw, src_epid); switch (status) { @@ -875,8 +894,10 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter, break; case EP_PARTNER_WAITING: if (src_epid < hw->my_epid) { + spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |= FJES_RX_STOP_REQ_DONE; + spin_unlock_irqrestore(&hw->rx_status_lock, flags); clear_bit(src_epid, &hw->txrx_stop_req_bit); set_bit(src_epid, &adapter->unshare_watch_bitmask); @@ -902,14 +923,17 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid) { struct fjes_hw *hw = &adapter->hw; enum ep_partner_status status; + unsigned long flags; set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit); status = fjes_hw_get_partner_ep_status(hw, src_epid); switch (status) { case EP_PARTNER_WAITING: + spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |= FJES_RX_STOP_REQ_DONE; + spin_unlock_irqrestore(&hw->rx_status_lock, flags); clear_bit(src_epid, &hw->txrx_stop_req_bit); /* fall through */ case EP_PARTNER_UNSHARE: @@ -1042,13 +1066,17 @@ static int fjes_poll(struct napi_struct *napi, int budget) size_t frame_len; void *frame; + spin_lock(&hw->rx_status_lock); for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; - adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status |= - FJES_RX_POLL_WORK; + if (fjes_hw_get_partner_ep_status(hw, epidx) == + EP_PARTNER_SHARED) + adapter->hw.ep_shm_info[epidx] + .tx.info->v1i.rx_status |= FJES_RX_POLL_WORK; } + spin_unlock(&hw->rx_status_lock); while (work_done < budget) { prefetch(&adapter->hw); @@ -1106,13 +1134,17 @@ static int fjes_poll(struct napi_struct *napi, int budget) if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) { napi_reschedule(napi); } else { + spin_lock(&hw->rx_status_lock); for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; - adapter->hw.ep_shm_info[epidx] - .tx.info->v1i.rx_status &= + if (fjes_hw_get_partner_ep_status(hw, epidx) == + EP_PARTNER_SHARED) + adapter->hw.ep_shm_info[epidx].tx + .info->v1i.rx_status &= ~FJES_RX_POLL_WORK; } + spin_unlock(&hw->rx_status_lock); fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false); } @@ -1281,6 +1313,7 @@ static void fjes_watch_unshare_task(struct work_struct *work) int max_epid, my_epid, epidx; int stop_req, stop_req_done; ulong unshare_watch_bitmask; + unsigned long flags; int wait_time = 0; int is_shared; int ret; @@ -1333,8 +1366,10 @@ static void fjes_watch_unshare_task(struct work_struct *work) } mutex_unlock(&hw->hw_info.lock); + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); + spin_unlock_irqrestore(&hw->rx_status_lock, flags); clear_bit(epidx, &hw->txrx_stop_req_bit); clear_bit(epidx, &unshare_watch_bitmask); @@ -1372,9 +1407,12 @@ static void fjes_watch_unshare_task(struct work_struct *work) } mutex_unlock(&hw->hw_info.lock); + spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf( &hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); + spin_unlock_irqrestore(&hw->rx_status_lock, + flags); clear_bit(epidx, &hw->txrx_stop_req_bit); clear_bit(epidx, &unshare_watch_bitmask); @@ -1382,8 +1420,11 @@ static void fjes_watch_unshare_task(struct work_struct *work) } if (test_bit(epidx, &unshare_watch_bitmask)) { + spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[epidx].tx.info->v1i.rx_status &= ~FJES_RX_STOP_REQ_DONE; + spin_unlock_irqrestore(&hw->rx_status_lock, + flags); } } } -- GitLab From 8f180fadb521ce440af82b5fa12ed56845110f15 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Fri, 15 Apr 2016 11:25:52 +0900 Subject: [PATCH 3154/9938] fjes: Update fjes driver version : 1.1 Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 87b24748bfcd..bb7e90368f8f 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -29,7 +29,7 @@ #include "fjes.h" #define MAJ 1 -#define MIN 0 +#define MIN 1 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) #define DRV_NAME "fjes" char fjes_driver_name[] = DRV_NAME; -- GitLab From 9e7399173200934612edf2153b93a8f232b88e4b Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 15 Apr 2016 19:14:19 +0200 Subject: [PATCH 3155/9938] staging: rtl8188eu: Convert to using IFF_NO_QUEUE Cc: Jakub Sitnicki Signed-off-by: Phil Sutter Signed-off-by: David S. Miller --- drivers/staging/rtl8188eu/os_dep/mon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c index 63bb87593af0..d976e5e18d50 100644 --- a/drivers/staging/rtl8188eu/os_dep/mon.c +++ b/drivers/staging/rtl8188eu/os_dep/mon.c @@ -155,7 +155,7 @@ static void mon_setup(struct net_device *dev) dev->netdev_ops = &mon_netdev_ops; dev->destructor = free_netdev; ether_setup(dev); - dev->tx_queue_len = 0; + dev->priv_flags |= IFF_NO_QUEUE; dev->type = ARPHRD_IEEE80211; /* * Use a locally administered address (IEEE 802) -- GitLab From 4272cc51a6dcf2c086863372fd593809ffced7d5 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 15 Apr 2016 19:14:20 +0200 Subject: [PATCH 3156/9938] openvswitch: Convert to using IFF_NO_QUEUE Cc: Pravin Shelar Signed-off-by: Phil Sutter Signed-off-by: David S. Miller --- net/openvswitch/vport-internal_dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 7c8b90bf0e54..2ee48e447b72 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -165,11 +165,10 @@ static void do_setup(struct net_device *netdev) netdev->priv_flags &= ~IFF_TX_SKB_SHARING; netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH | - IFF_PHONY_HEADROOM; + IFF_PHONY_HEADROOM | IFF_NO_QUEUE; netdev->destructor = internal_dev_destructor; netdev->ethtool_ops = &internal_dev_ethtool_ops; netdev->rtnl_link_ops = &internal_dev_link_ops; - netdev->tx_queue_len = 0; netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | -- GitLab From 5b161096f0515b61b72156cd0c1e5c72e77cfed8 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 16 Apr 2016 11:25:49 +0100 Subject: [PATCH 3157/9938] nfp: check the right pointer for errors Correct checking error condition on wrong pointer - copy/paste mistake most likely. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c index f86a1f13d27b..d77ae4d0e4dc 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c @@ -200,7 +200,7 @@ void nfp_net_debugfs_adapter_add(struct nfp_net *nn) /* Create queue debugging sub-tree */ queues = debugfs_create_dir("queue", nn->debugfs_dir); - if (IS_ERR_OR_NULL(nn->debugfs_dir)) + if (IS_ERR_OR_NULL(queues)) return; rx = debugfs_create_dir("rx", queues); -- GitLab From c160692e8665880c844bebdee219ed9cdcb2346b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 16 Apr 2016 11:25:50 +0100 Subject: [PATCH 3158/9938] nfp: remove unnecessary static There is no reason for those local variables to be static. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c index d77ae4d0e4dc..f7c9a5bc4aa3 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c @@ -187,7 +187,7 @@ static const struct file_operations nfp_tx_q_fops = { void nfp_net_debugfs_adapter_add(struct nfp_net *nn) { - static struct dentry *queues, *tx, *rx; + struct dentry *queues, *tx, *rx; char int_name[16]; int i; -- GitLab From 6ffa622d8567de1daab2e0ca23b99520ad504215 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 16 Apr 2016 11:25:51 +0100 Subject: [PATCH 3159/9938] nfp: correct names of constants in comments Documentation in comments lacks CFG in some names. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h index 8692003aeed8..3ec950555892 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h @@ -152,9 +152,9 @@ * @NFP_NET_CFG_VERSION: Firmware version number * @NFP_NET_CFG_STS: Status * @NFP_NET_CFG_CAP: Capabilities (same bits as @NFP_NET_CFG_CTRL) - * @NFP_NET_MAX_TXRINGS: Maximum number of TX rings - * @NFP_NET_MAX_RXRINGS: Maximum number of RX rings - * @NFP_NET_MAX_MTU: Maximum support MTU + * @NFP_NET_CFG_MAX_TXRINGS: Maximum number of TX rings + * @NFP_NET_CFG_MAX_RXRINGS: Maximum number of RX rings + * @NFP_NET_CFG_MAX_MTU: Maximum support MTU * @NFP_NET_CFG_START_TXQ: Start Queue Control Queue to use for TX (PF only) * @NFP_NET_CFG_START_RXQ: Start Queue Control Queue to use for RX (PF only) * -- GitLab From 2db221cd444bf356243c57b653b6bf84c3491806 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 16 Apr 2016 11:25:52 +0100 Subject: [PATCH 3160/9938] nfp: remove unused suspicious mask defines NFP_NET_RXR_MASK sounds like a mask which could be used on NFP_NET_CFG_RXRS_ENABLE register but its value is quite strange. In fact there are no users of this define so let's just remove it. Same for TX rings. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h index 3ec950555892..ad6c4e31cedd 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h @@ -81,14 +81,10 @@ /** * @NFP_NET_TXR_MAX: Maximum number of TX rings - * @NFP_NET_TXR_MASK: Mask for TX rings * @NFP_NET_RXR_MAX: Maximum number of RX rings - * @NFP_NET_RXR_MASK: Mask for RX rings */ #define NFP_NET_TXR_MAX 64 -#define NFP_NET_TXR_MASK (NFP_NET_TXR_MAX - 1) #define NFP_NET_RXR_MAX 64 -#define NFP_NET_RXR_MASK (NFP_NET_RXR_MAX - 1) /** * Read/Write config words (0x0000 - 0x002c) -- GitLab From 180012dc05e565260a25696767c8f5b2df5fc50e Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 16 Apr 2016 11:25:53 +0100 Subject: [PATCH 3161/9938] nfp: remove buggy RX buffer length validation Meaning of data_len and meta_len RX WB descriptor fields is slightly confusing. Add a comment with a diagram clarifying the layout. Also remove the buffer length validation: (a) it's imprecise for static rx-offsets; (b) if firmware is buggy enough to DMA past the end of the buffer WARN_ON_ONCE() doesn't seem like a strong enough response. skb_put() will do the checking for us anyway. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/nfp_net_common.c | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 0bdff390c958..5235e86eb684 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1298,23 +1298,25 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) nfp_net_rx_give_one(rx_ring, new_skb, new_dma_addr); + /* < meta_len > + * <-- [rx_offset] --> + * --------------------------------------------------------- + * | [XX] | metadata | packet | XXXX | + * --------------------------------------------------------- + * <---------------- data_len ---------------> + * + * The rx_offset is fixed for all packets, the meta_len can vary + * on a packet by packet basis. If rx_offset is set to zero + * (_RX_OFFSET_DYNAMIC) metadata starts at the beginning of the + * buffer and is immediately followed by the packet (no [XX]). + */ meta_len = rxd->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK; data_len = le16_to_cpu(rxd->rxd.data_len); - if (WARN_ON_ONCE(data_len > nn->fl_bufsz)) { - dev_kfree_skb_any(skb); - continue; - } - - if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) { - /* The packet data starts after the metadata */ + if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) skb_reserve(skb, meta_len); - } else { - /* The packet data starts at a fixed offset */ + else skb_reserve(skb, nn->rx_offset); - } - - /* Adjust the SKB for the dynamic meta data pre-pended */ skb_put(skb, data_len - meta_len); nfp_net_set_hash(nn->netdev, skb, rxd); -- GitLab From 3d780b926a12dd798417446d733d457f1be1cc73 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 16 Apr 2016 11:25:54 +0100 Subject: [PATCH 3162/9938] nfp: add async reconfiguration mechanism Some callers of nfp_net_reconfig() are in atomic context so we used to busy wait for commands to complete. In worst case scenario that means locking up a core for up to 5 seconds when a command times out. Lets add a timer-based mechanism of asynchronously checking whether reconfiguration completed successfully for atomic callers to use. Non-atomic callers can now just sleep. The approach taken is quite simple because (1) synchronous reconfigurations always happen under RTNL (or before device is registered); (2) we can coalesce pending reconfigs. There is no need for request queues, timer which eventually takes a look at reconfiguration result to report errors is good enough. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_net.h | 12 +- .../ethernet/netronome/nfp/nfp_net_common.c | 172 +++++++++++++++--- 2 files changed, 157 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 3d53fcf323eb..e744acc18ef4 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -59,8 +59,8 @@ netdev_warn((nn)->netdev, fmt, ## args); \ } while (0) -/* Max time to wait for NFP to respond on updates (in ms) */ -#define NFP_NET_POLL_TIMEOUT 5000 +/* Max time to wait for NFP to respond on updates (in seconds) */ +#define NFP_NET_POLL_TIMEOUT 5 /* Bar allocation */ #define NFP_NET_CRTL_BAR 0 @@ -447,6 +447,10 @@ static inline bool nfp_net_fw_ver_eq(struct nfp_net_fw_version *fw_ver, * @shared_name: Name for shared interrupt * @me_freq_mhz: ME clock_freq (MHz) * @reconfig_lock: Protects HW reconfiguration request regs/machinery + * @reconfig_posted: Pending reconfig bits coming from async sources + * @reconfig_timer_active: Timer for reading reconfiguration results is pending + * @reconfig_sync_present: Some thread is performing synchronous reconfig + * @reconfig_timer: Timer for async reading of reconfig results * @link_up: Is the link up? * @link_status_lock: Protects @link_up and ensures atomicity with BAR reading * @rx_coalesce_usecs: RX interrupt moderation usecs delay parameter @@ -531,6 +535,10 @@ struct nfp_net { spinlock_t link_status_lock; spinlock_t reconfig_lock; + u32 reconfig_posted; + bool reconfig_timer_active; + bool reconfig_sync_present; + struct timer_list reconfig_timer; u32 rx_coalesce_usecs; u32 rx_coalesce_max_frames; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 5235e86eb684..fa47c14c743a 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -80,6 +80,116 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver, put_unaligned_le32(reg, fw_ver); } +/* Firmware reconfig + * + * Firmware reconfig may take a while so we have two versions of it - + * synchronous and asynchronous (posted). All synchronous callers are holding + * RTNL so we don't have to worry about serializing them. + */ +static void nfp_net_reconfig_start(struct nfp_net *nn, u32 update) +{ + nn_writel(nn, NFP_NET_CFG_UPDATE, update); + /* ensure update is written before pinging HW */ + nn_pci_flush(nn); + nfp_qcp_wr_ptr_add(nn->qcp_cfg, 1); +} + +/* Pass 0 as update to run posted reconfigs. */ +static void nfp_net_reconfig_start_async(struct nfp_net *nn, u32 update) +{ + update |= nn->reconfig_posted; + nn->reconfig_posted = 0; + + nfp_net_reconfig_start(nn, update); + + nn->reconfig_timer_active = true; + mod_timer(&nn->reconfig_timer, jiffies + NFP_NET_POLL_TIMEOUT * HZ); +} + +static bool nfp_net_reconfig_check_done(struct nfp_net *nn, bool last_check) +{ + u32 reg; + + reg = nn_readl(nn, NFP_NET_CFG_UPDATE); + if (reg == 0) + return true; + if (reg & NFP_NET_CFG_UPDATE_ERR) { + nn_err(nn, "Reconfig error: 0x%08x\n", reg); + return true; + } else if (last_check) { + nn_err(nn, "Reconfig timeout: 0x%08x\n", reg); + return true; + } + + return false; +} + +static int nfp_net_reconfig_wait(struct nfp_net *nn, unsigned long deadline) +{ + bool timed_out = false; + + /* Poll update field, waiting for NFP to ack the config */ + while (!nfp_net_reconfig_check_done(nn, timed_out)) { + msleep(1); + timed_out = time_is_before_eq_jiffies(deadline); + } + + if (nn_readl(nn, NFP_NET_CFG_UPDATE) & NFP_NET_CFG_UPDATE_ERR) + return -EIO; + + return timed_out ? -EIO : 0; +} + +static void nfp_net_reconfig_timer(unsigned long data) +{ + struct nfp_net *nn = (void *)data; + + spin_lock_bh(&nn->reconfig_lock); + + nn->reconfig_timer_active = false; + + /* If sync caller is present it will take over from us */ + if (nn->reconfig_sync_present) + goto done; + + /* Read reconfig status and report errors */ + nfp_net_reconfig_check_done(nn, true); + + if (nn->reconfig_posted) + nfp_net_reconfig_start_async(nn, 0); +done: + spin_unlock_bh(&nn->reconfig_lock); +} + +/** + * nfp_net_reconfig_post() - Post async reconfig request + * @nn: NFP Net device to reconfigure + * @update: The value for the update field in the BAR config + * + * Record FW reconfiguration request. Reconfiguration will be kicked off + * whenever reconfiguration machinery is idle. Multiple requests can be + * merged together! + */ +static void nfp_net_reconfig_post(struct nfp_net *nn, u32 update) +{ + spin_lock_bh(&nn->reconfig_lock); + + /* Sync caller will kick off async reconf when it's done, just post */ + if (nn->reconfig_sync_present) { + nn->reconfig_posted |= update; + goto done; + } + + /* Opportunistically check if the previous command is done */ + if (!nn->reconfig_timer_active || + nfp_net_reconfig_check_done(nn, false)) + nfp_net_reconfig_start_async(nn, update); + else + nn->reconfig_posted |= update; +done: + spin_unlock_bh(&nn->reconfig_lock); +} + /** * nfp_net_reconfig() - Reconfigure the firmware * @nn: NFP Net device to reconfigure @@ -93,35 +203,45 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver, */ int nfp_net_reconfig(struct nfp_net *nn, u32 update) { - int cnt, ret = 0; - u32 new; + bool cancelled_timer = false; + u32 pre_posted_requests; + int ret; spin_lock_bh(&nn->reconfig_lock); - nn_writel(nn, NFP_NET_CFG_UPDATE, update); - /* ensure update is written before pinging HW */ - nn_pci_flush(nn); - nfp_qcp_wr_ptr_add(nn->qcp_cfg, 1); + nn->reconfig_sync_present = true; - /* Poll update field, waiting for NFP to ack the config */ - for (cnt = 0; ; cnt++) { - new = nn_readl(nn, NFP_NET_CFG_UPDATE); - if (new == 0) - break; - if (new & NFP_NET_CFG_UPDATE_ERR) { - nn_err(nn, "Reconfig error: 0x%08x\n", new); - ret = -EIO; - break; - } else if (cnt >= NFP_NET_POLL_TIMEOUT) { - nn_err(nn, "Reconfig timeout for 0x%08x after %dms\n", - update, cnt); - ret = -EIO; - break; - } - mdelay(1); + if (nn->reconfig_timer_active) { + del_timer(&nn->reconfig_timer); + nn->reconfig_timer_active = false; + cancelled_timer = true; + } + pre_posted_requests = nn->reconfig_posted; + nn->reconfig_posted = 0; + + spin_unlock_bh(&nn->reconfig_lock); + + if (cancelled_timer) + nfp_net_reconfig_wait(nn, nn->reconfig_timer.expires); + + /* Run the posted reconfigs which were issued before we started */ + if (pre_posted_requests) { + nfp_net_reconfig_start(nn, pre_posted_requests); + nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT); } + nfp_net_reconfig_start(nn, update); + ret = nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT); + + spin_lock_bh(&nn->reconfig_lock); + + if (nn->reconfig_posted) + nfp_net_reconfig_start_async(nn, 0); + + nn->reconfig_sync_present = false; + spin_unlock_bh(&nn->reconfig_lock); + return ret; } @@ -2096,8 +2216,7 @@ static void nfp_net_set_rx_mode(struct net_device *netdev) return; nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); - if (nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN)) - return; + nfp_net_reconfig_post(nn, NFP_NET_CFG_UPDATE_GEN); nn->ctrl = new_ctrl; } @@ -2405,7 +2524,7 @@ static void nfp_net_set_vxlan_port(struct nfp_net *nn, int idx, __be16 port) be16_to_cpu(nn->vxlan_ports[i + 1]) << 16 | be16_to_cpu(nn->vxlan_ports[i])); - nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_VXLAN); + nfp_net_reconfig_post(nn, NFP_NET_CFG_UPDATE_VXLAN); } /** @@ -2551,6 +2670,9 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, spin_lock_init(&nn->reconfig_lock); spin_lock_init(&nn->link_status_lock); + setup_timer(&nn->reconfig_timer, + nfp_net_reconfig_timer, (unsigned long)nn); + return nn; } -- GitLab From 98a52530ed51394848079e7952c1145bd49fbe7d Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Thu, 14 Apr 2016 17:40:24 +0200 Subject: [PATCH 3163/9938] iio: frequency: ad9523: use unsigned int rather then bare unsigned This fix checkpatch warnings: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/ad9523.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 44a30f286de1..99eba524f6dd 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -284,7 +284,7 @@ struct ad9523_state { } data[2] ____cacheline_aligned; }; -static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) +static int ad9523_read(struct iio_dev *indio_dev, unsigned int addr) { struct ad9523_state *st = iio_priv(indio_dev); int ret; @@ -318,7 +318,8 @@ static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) return ret; }; -static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val) +static int ad9523_write(struct iio_dev *indio_dev, + unsigned int addr, unsigned int val) { struct ad9523_state *st = iio_priv(indio_dev); int ret; @@ -351,11 +352,11 @@ static int ad9523_io_update(struct iio_dev *indio_dev) } static int ad9523_vco_out_map(struct iio_dev *indio_dev, - unsigned ch, unsigned out) + unsigned int ch, unsigned int out) { struct ad9523_state *st = iio_priv(indio_dev); int ret; - unsigned mask; + unsigned int mask; switch (ch) { case 0 ... 3: @@ -405,7 +406,7 @@ static int ad9523_vco_out_map(struct iio_dev *indio_dev, } static int ad9523_set_clock_provider(struct iio_dev *indio_dev, - unsigned ch, unsigned long freq) + unsigned int ch, unsigned long freq) { struct ad9523_state *st = iio_priv(indio_dev); long tmp1, tmp2; @@ -619,7 +620,7 @@ static int ad9523_read_raw(struct iio_dev *indio_dev, long m) { struct ad9523_state *st = iio_priv(indio_dev); - unsigned code; + unsigned int code; int ret; mutex_lock(&indio_dev->mlock); @@ -655,7 +656,7 @@ static int ad9523_write_raw(struct iio_dev *indio_dev, long mask) { struct ad9523_state *st = iio_priv(indio_dev); - unsigned reg; + unsigned int reg; int ret, tmp, code; mutex_lock(&indio_dev->mlock); @@ -709,8 +710,8 @@ static int ad9523_write_raw(struct iio_dev *indio_dev, } static int ad9523_reg_access(struct iio_dev *indio_dev, - unsigned reg, unsigned writeval, - unsigned *readval) + unsigned int reg, unsigned int writeval, + unsigned int *readval) { int ret; -- GitLab From a6b5ec887b85df039055be316420b1520c23eb6b Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Mon, 11 Apr 2016 17:24:26 +0300 Subject: [PATCH 3164/9938] ti-adc081c: Add support for adc101c and adc121c These chips have an almost identical interface but support a different number of value bits. Datasheet links for comparison: * http://www.ti.com/lit/ds/symlink/adc081c021.pdf * http://www.ti.com/lit/ds/symlink/adc101c021.pdf * http://www.ti.com/lit/ds/symlink/adc121c021.pdf Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 6 ++--- drivers/iio/adc/ti-adc081c.c | 51 +++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 5937030f0444..25378c5882e2 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -385,11 +385,11 @@ config ROCKCHIP_SARADC module will be called rockchip_saradc. config TI_ADC081C - tristate "Texas Instruments ADC081C021/027" + tristate "Texas Instruments ADC081C/ADC101C/ADC121C family" depends on I2C help - If you say yes here you get support for Texas Instruments ADC081C021 - and ADC081C027 ADC chips. + If you say yes here you get support for Texas Instruments ADC081C, + ADC101C and ADC121C ADC chips. This driver can also be built as a module. If so, the module will be called ti-adc081c. diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index ecbc12138d58..b977340fbdb8 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -1,9 +1,21 @@ /* + * TI ADC081C/ADC101C/ADC121C 8/10/12-bit ADC driver + * * Copyright (C) 2012 Avionic Design GmbH + * Copyright (C) 2016 Intel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Datasheets: + * http://www.ti.com/lit/ds/symlink/adc081c021.pdf + * http://www.ti.com/lit/ds/symlink/adc101c021.pdf + * http://www.ti.com/lit/ds/symlink/adc121c021.pdf + * + * The devices have a very similar interface and differ mostly in the number of + * bits handled. For the 8-bit and 10-bit models the least-significant 4 or 2 + * bits of value registers are reserved. */ #include @@ -17,6 +29,9 @@ struct adc081c { struct i2c_client *i2c; struct regulator *ref; + + /* 8, 10 or 12 */ + int bits; }; #define REG_CONV_RES 0x00 @@ -34,7 +49,7 @@ static int adc081c_read_raw(struct iio_dev *iio, if (err < 0) return err; - *value = (err >> 4) & 0xff; + *value = (err & 0xFFF) >> (12 - adc->bits); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -43,7 +58,7 @@ static int adc081c_read_raw(struct iio_dev *iio, return err; *value = err / 1000; - *shift = 8; + *shift = adc->bits; return IIO_VAL_FRACTIONAL_LOG2; @@ -60,6 +75,28 @@ static const struct iio_chan_spec adc081c_channel = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), }; +struct adcxx1c_model { + int bits; +}; + +#define ADCxx1C_MODEL(_bits) \ + { \ + .bits = (_bits), \ + } + +/* Model ids are indexes in _models array */ +enum adcxx1c_model_id { + ADC081C = 0, + ADC101C = 1, + ADC121C = 2, +}; + +static struct adcxx1c_model adcxx1c_models[] = { + ADCxx1C_MODEL( 8), + ADCxx1C_MODEL(10), + ADCxx1C_MODEL(12), +}; + static const struct iio_info adc081c_info = { .read_raw = adc081c_read_raw, .driver_module = THIS_MODULE, @@ -70,6 +107,7 @@ static int adc081c_probe(struct i2c_client *client, { struct iio_dev *iio; struct adc081c *adc; + struct adcxx1c_model *model = &adcxx1c_models[id->driver_data]; int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) @@ -81,6 +119,7 @@ static int adc081c_probe(struct i2c_client *client, adc = iio_priv(iio); adc->i2c = client; + adc->bits = model->bits; adc->ref = devm_regulator_get(&client->dev, "vref"); if (IS_ERR(adc->ref)) @@ -124,7 +163,9 @@ static int adc081c_remove(struct i2c_client *client) } static const struct i2c_device_id adc081c_id[] = { - { "adc081c", 0 }, + { "adc081c", ADC081C }, + { "adc101c", ADC101C }, + { "adc121c", ADC121C }, { } }; MODULE_DEVICE_TABLE(i2c, adc081c_id); @@ -132,6 +173,8 @@ MODULE_DEVICE_TABLE(i2c, adc081c_id); #ifdef CONFIG_OF static const struct of_device_id adc081c_of_match[] = { { .compatible = "ti,adc081c" }, + { .compatible = "ti,adc101c" }, + { .compatible = "ti,adc121c" }, { } }; MODULE_DEVICE_TABLE(of, adc081c_of_match); @@ -149,5 +192,5 @@ static struct i2c_driver adc081c_driver = { module_i2c_driver(adc081c_driver); MODULE_AUTHOR("Thierry Reding "); -MODULE_DESCRIPTION("Texas Instruments ADC081C021/027 driver"); +MODULE_DESCRIPTION("Texas Instruments ADC081C/ADC101C/ADC121C driver"); MODULE_LICENSE("GPL v2"); -- GitLab From 08e05d1fce5c87e5eaf16655c45db6beb4d93701 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Mon, 11 Apr 2016 17:24:27 +0300 Subject: [PATCH 3165/9938] ti-adc081c: Initial triggered buffer support Using this requires software triggers like CONFIG_IIO_HRTIMER_TRIGGER. The device can be configured to do internal periodic sampling but does not offer some sort of interrupt on data ready. Interrupts can only trigger when values get out of a specific range. Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-adc081c.c | 77 ++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index b977340fbdb8..9fd032d9f402 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -24,6 +24,9 @@ #include #include +#include +#include +#include #include struct adc081c { @@ -69,21 +72,42 @@ static int adc081c_read_raw(struct iio_dev *iio, return -EINVAL; } -static const struct iio_chan_spec adc081c_channel = { - .type = IIO_VOLTAGE, - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), -}; +#define ADCxx1C_CHAN(_bits) { \ + .type = IIO_VOLTAGE, \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = (_bits), \ + .storagebits = 16, \ + .shift = 12 - (_bits), \ + .endianness = IIO_CPU, \ + }, \ +} + +#define DEFINE_ADCxx1C_CHANNELS(_name, _bits) \ + static const struct iio_chan_spec _name ## _channels[] = { \ + ADCxx1C_CHAN((_bits)), \ + IIO_CHAN_SOFT_TIMESTAMP(1), \ + }; \ + +#define ADC081C_NUM_CHANNELS 2 struct adcxx1c_model { + const struct iio_chan_spec* channels; int bits; }; -#define ADCxx1C_MODEL(_bits) \ +#define ADCxx1C_MODEL(_name, _bits) \ { \ + .channels = _name ## _channels, \ .bits = (_bits), \ } +DEFINE_ADCxx1C_CHANNELS(adc081c, 8); +DEFINE_ADCxx1C_CHANNELS(adc101c, 10); +DEFINE_ADCxx1C_CHANNELS(adc121c, 12); + /* Model ids are indexes in _models array */ enum adcxx1c_model_id { ADC081C = 0, @@ -92,9 +116,9 @@ enum adcxx1c_model_id { }; static struct adcxx1c_model adcxx1c_models[] = { - ADCxx1C_MODEL( 8), - ADCxx1C_MODEL(10), - ADCxx1C_MODEL(12), + ADCxx1C_MODEL(adc081c, 8), + ADCxx1C_MODEL(adc101c, 10), + ADCxx1C_MODEL(adc121c, 12), }; static const struct iio_info adc081c_info = { @@ -102,6 +126,24 @@ static const struct iio_info adc081c_info = { .driver_module = THIS_MODULE, }; +static irqreturn_t adc081c_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc081c *data = iio_priv(indio_dev); + u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */ + int ret; + + ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES); + if (ret < 0) + goto out; + buf[0] = ret; + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); +out: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + static int adc081c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -134,18 +176,26 @@ static int adc081c_probe(struct i2c_client *client, iio->modes = INDIO_DIRECT_MODE; iio->info = &adc081c_info; - iio->channels = &adc081c_channel; - iio->num_channels = 1; + iio->channels = model->channels; + iio->num_channels = ADC081C_NUM_CHANNELS; + + err = iio_triggered_buffer_setup(iio, NULL, adc081c_trigger_handler, NULL); + if (err < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + goto err_regulator_disable; + } err = iio_device_register(iio); if (err < 0) - goto regulator_disable; + goto err_buffer_cleanup; i2c_set_clientdata(client, iio); return 0; -regulator_disable: +err_buffer_cleanup: + iio_triggered_buffer_cleanup(iio); +err_regulator_disable: regulator_disable(adc->ref); return err; @@ -157,6 +207,7 @@ static int adc081c_remove(struct i2c_client *client) struct adc081c *adc = iio_priv(iio); iio_device_unregister(iio); + iio_triggered_buffer_cleanup(iio); regulator_disable(adc->ref); return 0; -- GitLab From 922b3aa6e74e4e1cac95cf4ab88ecc0fd5162c89 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 10 Apr 2016 21:22:32 +0200 Subject: [PATCH 3166/9938] iio: adc: set INPUT_PROP_DIRECT Set INPUT_PROP_DIRECT to indicate that it is a touchscreen on the device to help userspace classify it. Signed-off-by: Ksenija Stanojevic Acked-by: Dmitry Torokhov Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mxs-lradc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c index 07287afa5bd3..e4c4c5c8af83 100644 --- a/drivers/iio/adc/mxs-lradc.c +++ b/drivers/iio/adc/mxs-lradc.c @@ -1127,6 +1127,7 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) __set_bit(EV_ABS, input->evbit); __set_bit(EV_KEY, input->evbit); __set_bit(BTN_TOUCH, input->keybit); + __set_bit(INPUT_PROP_DIRECT, input->propbit); input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK, -- GitLab From 0209d144e3097fee1fe5d38532e6f0919c80d1ea Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:23:55 -0400 Subject: [PATCH 3167/9938] net: dsa: constify probed name Change the dsa_switch_driver.probe function to return a const char *. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 6 +++--- drivers/net/dsa/mv88e6060.c | 10 +++++----- drivers/net/dsa/mv88e6123.c | 6 +++--- drivers/net/dsa/mv88e6131.c | 6 +++--- drivers/net/dsa/mv88e6171.c | 6 +++--- drivers/net/dsa/mv88e6352.c | 6 +++--- drivers/net/dsa/mv88e6xxx.c | 17 +++++++++-------- drivers/net/dsa/mv88e6xxx.h | 8 ++++---- include/net/dsa.h | 5 +++-- net/dsa/dsa.c | 6 +++--- 10 files changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 7a5f0ef46bd6..448deb59b9a4 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -135,9 +135,9 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds) return BCM_SF2_STATS_SIZE; } -static char *bcm_sf2_sw_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **_priv) +static const char *bcm_sf2_sw_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **_priv) { struct bcm_sf2_priv *priv; diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 92cebab9383e..e36b40886bd8 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -51,7 +51,7 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) return __ret; \ }) -static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) +static const char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) { int ret; @@ -69,13 +69,13 @@ static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) return NULL; } -static char *mv88e6060_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **_priv) +static const char *mv88e6060_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **_priv) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); struct mv88e6060_priv *priv; - char *name; + const char *name; name = mv88e6060_get_name(bus, sw_addr); if (name) { diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 140e44e50e8a..9701c0f9a60a 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -29,9 +29,9 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = { { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, }; -static char *mv88e6123_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6123_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6123_table, diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 34d297b65040..fa3a35460453 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -25,9 +25,9 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = { { PORT_SWITCH_ID_6185, "Marvell 88E6185" }, }; -static char *mv88e6131_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6131_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6131_table, diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index b7af2b78f8ee..8d86c9ee1adf 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -24,9 +24,9 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = { { PORT_SWITCH_ID_6351, "Marvell 88E6351" }, }; -static char *mv88e6171_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6171_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6171_table, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index e8cb03fad21a..c7fa69c9a564 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -37,9 +37,9 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" }, }; -static char *mv88e6352_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6352_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6352_table, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index b018f20829fb..25d7fec98f8e 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -3173,9 +3173,10 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) } #endif /* CONFIG_NET_DSA_HWMON */ -static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr, - const struct mv88e6xxx_switch_id *table, - unsigned int num) +static const char * +mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr, + const struct mv88e6xxx_switch_id *table, + unsigned int num) { int i, ret; @@ -3205,14 +3206,14 @@ static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr, return NULL; } -char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv, - const struct mv88e6xxx_switch_id *table, - unsigned int num) +const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr, void **priv, + const struct mv88e6xxx_switch_id *table, + unsigned int num) { struct mv88e6xxx_priv_state *ps; struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); - char *name; + const char *name; if (!bus) return NULL; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 0debb9f3cf0a..5eb601398835 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -462,10 +462,10 @@ struct mv88e6xxx_hw_stat { }; int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); -char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv, - const struct mv88e6xxx_switch_id *table, - unsigned int num); +const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr, void **priv, + const struct mv88e6xxx_switch_id *table, + unsigned int num); int mv88e6xxx_setup_ports(struct dsa_switch *ds); int mv88e6xxx_setup_common(struct dsa_switch *ds); diff --git a/include/net/dsa.h b/include/net/dsa.h index 689ebd3542ba..c4bc42bd3538 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -217,8 +217,9 @@ struct dsa_switch_driver { /* * Probing and setup. */ - char *(*probe)(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv); + const char *(*probe)(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv); int (*setup)(struct dsa_switch *ds); int (*set_addr)(struct dsa_switch *ds, u8 *addr); u32 (*get_phy_flags)(struct dsa_switch *ds, int port); diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 60ea98481806..efa612f0ab9b 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -52,11 +52,11 @@ EXPORT_SYMBOL_GPL(unregister_switch_driver); static struct dsa_switch_driver * dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr, - char **_name, void **priv) + const char **_name, void **priv) { struct dsa_switch_driver *ret; struct list_head *list; - char *name; + const char *name; ret = NULL; name = NULL; @@ -383,7 +383,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, struct dsa_switch_driver *drv; struct dsa_switch *ds; int ret; - char *name; + const char *name; void *priv; /* -- GitLab From b346204737fafce585f62543ed7691fb4a72789d Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:23:56 -0400 Subject: [PATCH 3168/9938] net: dsa: mv88e6xxx: drop double ds assignment Every driver assigns ps->ds even though it gets assigned in the shared mv88e6xxx_setup_common function. Kill redundancy. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123.c | 2 -- drivers/net/dsa/mv88e6131.c | 2 -- drivers/net/dsa/mv88e6171.c | 2 -- drivers/net/dsa/mv88e6352.c | 2 -- 4 files changed, 8 deletions(-) diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 9701c0f9a60a..85537eb2806a 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -79,8 +79,6 @@ static int mv88e6123_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index fa3a35460453..4117c9b56571 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -101,8 +101,6 @@ static int mv88e6131_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 8d86c9ee1adf..ae328750eae8 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -76,8 +76,6 @@ static int mv88e6171_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index c7fa69c9a564..10c36abf4c64 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -87,8 +87,6 @@ static int mv88e6352_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; -- GitLab From 54c6f4bda7dabab7a7a9eeb8f1ced4b0b5fc4fd0 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:23:57 -0400 Subject: [PATCH 3169/9938] net: dsa: mv88e6xxx: drop revision probing There is no point in having a special case for the revision when probing a switch model. The code gets cluttered with unnecessary defines, and leads to errors when code such as mv88e6131_setup compares PORT_SWITCH_ID_6131_B2 to ps->id which masks the revision. Drop every revision definition, and lookup only the product number. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123.c | 6 ------ drivers/net/dsa/mv88e6131.c | 2 -- drivers/net/dsa/mv88e6352.c | 6 ------ drivers/net/dsa/mv88e6xxx.c | 14 +------------- drivers/net/dsa/mv88e6xxx.h | 15 --------------- 5 files changed, 1 insertion(+), 42 deletions(-) diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 85537eb2806a..d6921ba144b9 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -19,14 +19,8 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = { { PORT_SWITCH_ID_6123, "Marvell 88E6123" }, - { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" }, - { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" }, { PORT_SWITCH_ID_6161, "Marvell 88E6161" }, - { PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" }, - { PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" }, { PORT_SWITCH_ID_6165, "Marvell 88E6165" }, - { PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" }, - { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, }; static const char *mv88e6123_drv_probe(struct device *dsa_dev, diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 4117c9b56571..8dc136576fe4 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -21,7 +21,6 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = { { PORT_SWITCH_ID_6085, "Marvell 88E6085" }, { PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" }, { PORT_SWITCH_ID_6131, "Marvell 88E6131" }, - { PORT_SWITCH_ID_6131_B2, "Marvell 88E6131 (B2)" }, { PORT_SWITCH_ID_6185, "Marvell 88E6185" }, }; @@ -116,7 +115,6 @@ static int mv88e6131_setup(struct dsa_switch *ds) ps->num_ports = 11; break; case PORT_SWITCH_ID_6131: - case PORT_SWITCH_ID_6131_B2: ps->num_ports = 8; break; default: diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 10c36abf4c64..34f92b17146b 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -27,14 +27,8 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { { PORT_SWITCH_ID_6176, "Marvell 88E6176" }, { PORT_SWITCH_ID_6240, "Marvell 88E6240" }, { PORT_SWITCH_ID_6320, "Marvell 88E6320" }, - { PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" }, - { PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" }, { PORT_SWITCH_ID_6321, "Marvell 88E6321" }, - { PORT_SWITCH_ID_6321_A1, "Marvell 88E6321 (A1)" }, - { PORT_SWITCH_ID_6321_A2, "Marvell 88e6321 (A2)" }, { PORT_SWITCH_ID_6352, "Marvell 88E6352" }, - { PORT_SWITCH_ID_6352_A0, "Marvell 88E6352 (A0)" }, - { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" }, }; static const char *mv88e6352_drv_probe(struct device *dsa_dev, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 25d7fec98f8e..469d8a3476cb 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -3187,22 +3187,10 @@ mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr, if (ret < 0) return NULL; - /* Look up the exact switch ID */ for (i = 0; i < num; ++i) - if (table[i].id == ret) + if (table[i].id == (ret & 0xfff0)) return table[i].name; - /* Look up only the product number */ - for (i = 0; i < num; ++i) { - if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) { - dev_warn(&bus->dev, - "unknown revision %d, using base switch 0x%x\n", - ret & PORT_SWITCH_ID_REV_MASK, - ret & PORT_SWITCH_ID_PROD_NUM_MASK); - return table[i].name; - } - } - return NULL; } diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 5eb601398835..6513450d60bf 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -68,8 +68,6 @@ #define PORT_PCS_CTRL_UNFORCED 0x03 #define PORT_PAUSE_CTRL 0x02 #define PORT_SWITCH_ID 0x03 -#define PORT_SWITCH_ID_PROD_NUM_MASK 0xfff0 -#define PORT_SWITCH_ID_REV_MASK 0x000f #define PORT_SWITCH_ID_6031 0x0310 #define PORT_SWITCH_ID_6035 0x0350 #define PORT_SWITCH_ID_6046 0x0480 @@ -84,18 +82,11 @@ #define PORT_SWITCH_ID_6121 0x1040 #define PORT_SWITCH_ID_6122 0x1050 #define PORT_SWITCH_ID_6123 0x1210 -#define PORT_SWITCH_ID_6123_A1 0x1212 -#define PORT_SWITCH_ID_6123_A2 0x1213 #define PORT_SWITCH_ID_6131 0x1060 -#define PORT_SWITCH_ID_6131_B2 0x1066 #define PORT_SWITCH_ID_6152 0x1a40 #define PORT_SWITCH_ID_6155 0x1a50 #define PORT_SWITCH_ID_6161 0x1610 -#define PORT_SWITCH_ID_6161_A1 0x1612 -#define PORT_SWITCH_ID_6161_A2 0x1613 #define PORT_SWITCH_ID_6165 0x1650 -#define PORT_SWITCH_ID_6165_A1 0x1652 -#define PORT_SWITCH_ID_6165_A2 0x1653 #define PORT_SWITCH_ID_6171 0x1710 #define PORT_SWITCH_ID_6172 0x1720 #define PORT_SWITCH_ID_6175 0x1750 @@ -104,16 +95,10 @@ #define PORT_SWITCH_ID_6185 0x1a70 #define PORT_SWITCH_ID_6240 0x2400 #define PORT_SWITCH_ID_6320 0x1150 -#define PORT_SWITCH_ID_6320_A1 0x1151 -#define PORT_SWITCH_ID_6320_A2 0x1152 #define PORT_SWITCH_ID_6321 0x3100 -#define PORT_SWITCH_ID_6321_A1 0x3101 -#define PORT_SWITCH_ID_6321_A2 0x3102 #define PORT_SWITCH_ID_6350 0x3710 #define PORT_SWITCH_ID_6351 0x3750 #define PORT_SWITCH_ID_6352 0x3520 -#define PORT_SWITCH_ID_6352_A0 0x3521 -#define PORT_SWITCH_ID_6352_A1 0x3522 #define PORT_CONTROL 0x04 #define PORT_CONTROL_USE_CORE_TAG BIT(15) #define PORT_CONTROL_DROP_ON_LOCK BIT(14) -- GitLab From a439c0612d7bdbd5ce8ea868e6a1084f0d7300dc Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:23:58 -0400 Subject: [PATCH 3170/9938] net: dsa: mv88e6xxx: read switch ID in probe Read the switch ID only once, at probe time, to avoid multiple read accesses and MII bus checking. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 57 +++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 469d8a3476cb..49f085a8453d 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2700,10 +2700,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) ps->ds = ds; mutex_init(&ps->smi_mutex); - ps->id = mv88e6xxx_reg_read(ds, REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; - if (ps->id < 0) - return ps->id; - INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); return 0; @@ -3174,21 +3170,13 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) #endif /* CONFIG_NET_DSA_HWMON */ static const char * -mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr, - const struct mv88e6xxx_switch_id *table, +mv88e6xxx_lookup_name(unsigned int id, const struct mv88e6xxx_switch_id *table, unsigned int num) { - int i, ret; - - if (!bus) - return NULL; - - ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); - if (ret < 0) - return NULL; + int i; for (i = 0; i < num; ++i) - if (table[i].id == (ret & 0xfff0)) + if (table[i].id == (id & 0xfff0)) return table[i].name; return NULL; @@ -3200,23 +3188,38 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, unsigned int num) { struct mv88e6xxx_priv_state *ps; - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); + struct mii_bus *bus; const char *name; + int id, prod_num, rev; + bus = dsa_host_dev_to_mii_bus(host_dev); if (!bus) return NULL; - name = mv88e6xxx_lookup_name(bus, sw_addr, table, num); - if (name) { - ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); - if (!ps) - return NULL; - *priv = ps; - ps->bus = dsa_host_dev_to_mii_bus(host_dev); - if (!ps->bus) - return NULL; - ps->sw_addr = sw_addr; - } + id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); + if (id < 0) + return NULL; + + prod_num = (id & 0xfff0) >> 4; + rev = id & 0x000f; + + name = mv88e6xxx_lookup_name(id, table, num); + if (!name) + return NULL; + + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); + if (!ps) + return NULL; + + ps->bus = bus; + ps->sw_addr = sw_addr; + ps->id = id & 0xfff0; + + *priv = ps; + + dev_info(&ps->bus->dev, "switch 0x%x probed: %s, revision %u\n", + prod_num, name, rev); + return name; } -- GitLab From f6271e676b7f62a609f8ee5523a6a8ed47c0f333 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:23:59 -0400 Subject: [PATCH 3171/9938] net: dsa: mv88e6xxx: add switch info Add a new switch info structure which is meant to store switch models static information, such as product number, name, number of ports, number of databases, etc. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123.c | 15 +++++++++++---- drivers/net/dsa/mv88e6131.c | 19 ++++++++++++++----- drivers/net/dsa/mv88e6171.c | 19 ++++++++++++++----- drivers/net/dsa/mv88e6352.c | 27 ++++++++++++++++++++------- drivers/net/dsa/mv88e6xxx.c | 18 +++++++++++------- drivers/net/dsa/mv88e6xxx.h | 27 +++++++++++++++++++++++---- 6 files changed, 93 insertions(+), 32 deletions(-) diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index d6921ba144b9..62dffcf915a7 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -17,10 +17,17 @@ #include #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6123_table[] = { - { PORT_SWITCH_ID_6123, "Marvell 88E6123" }, - { PORT_SWITCH_ID_6161, "Marvell 88E6161" }, - { PORT_SWITCH_ID_6165, "Marvell 88E6165" }, +static const struct mv88e6xxx_info mv88e6123_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6123, + .name = "Marvell 88E6123", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6161, + .name = "Marvell 88E6161", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6165, + .name = "Marvell 88E6165", + } }; static const char *mv88e6123_drv_probe(struct device *dsa_dev, diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 8dc136576fe4..00567156f335 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -17,11 +17,20 @@ #include #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6131_table[] = { - { PORT_SWITCH_ID_6085, "Marvell 88E6085" }, - { PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" }, - { PORT_SWITCH_ID_6131, "Marvell 88E6131" }, - { PORT_SWITCH_ID_6185, "Marvell 88E6185" }, +static const struct mv88e6xxx_info mv88e6131_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6095, + .name = "Marvell 88E6095/88E6095F", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6085, + .name = "Marvell 88E6085", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6131, + .name = "Marvell 88E6131", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6185, + .name = "Marvell 88E6185", + } }; static const char *mv88e6131_drv_probe(struct device *dsa_dev, diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index ae328750eae8..ea14ab22d313 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -17,11 +17,20 @@ #include #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6171_table[] = { - { PORT_SWITCH_ID_6171, "Marvell 88E6171" }, - { PORT_SWITCH_ID_6175, "Marvell 88E6175" }, - { PORT_SWITCH_ID_6350, "Marvell 88E6350" }, - { PORT_SWITCH_ID_6351, "Marvell 88E6351" }, +static const struct mv88e6xxx_info mv88e6171_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6171, + .name = "Marvell 88E6171", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6175, + .name = "Marvell 88E6175", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6350, + .name = "Marvell 88E6350", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6351, + .name = "Marvell 88E6351", + } }; static const char *mv88e6171_drv_probe(struct device *dsa_dev, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 34f92b17146b..2f72606ecc9e 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -22,13 +22,26 @@ #include #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6352_table[] = { - { PORT_SWITCH_ID_6172, "Marvell 88E6172" }, - { PORT_SWITCH_ID_6176, "Marvell 88E6176" }, - { PORT_SWITCH_ID_6240, "Marvell 88E6240" }, - { PORT_SWITCH_ID_6320, "Marvell 88E6320" }, - { PORT_SWITCH_ID_6321, "Marvell 88E6321" }, - { PORT_SWITCH_ID_6352, "Marvell 88E6352" }, +static const struct mv88e6xxx_info mv88e6352_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6320, + .name = "Marvell 88E6320", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6321, + .name = "Marvell 88E6321", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6172, + .name = "Marvell 88E6172", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6176, + .name = "Marvell 88E6176", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6240, + .name = "Marvell 88E6240", + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6352, + .name = "Marvell 88E6352", + } }; static const char *mv88e6352_drv_probe(struct device *dsa_dev, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 49f085a8453d..5fb21e059f35 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -3169,24 +3169,25 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) } #endif /* CONFIG_NET_DSA_HWMON */ -static const char * -mv88e6xxx_lookup_name(unsigned int id, const struct mv88e6xxx_switch_id *table, +static const struct mv88e6xxx_info * +mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table, unsigned int num) { int i; for (i = 0; i < num; ++i) - if (table[i].id == (id & 0xfff0)) - return table[i].name; + if (table[i].prod_num == prod_num) + return &table[i]; return NULL; } const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, int sw_addr, void **priv, - const struct mv88e6xxx_switch_id *table, + const struct mv88e6xxx_info *table, unsigned int num) { + const struct mv88e6xxx_info *info; struct mv88e6xxx_priv_state *ps; struct mii_bus *bus; const char *name; @@ -3203,16 +3204,19 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, prod_num = (id & 0xfff0) >> 4; rev = id & 0x000f; - name = mv88e6xxx_lookup_name(id, table, num); - if (!name) + info = mv88e6xxx_lookup_info(prod_num, table, num); + if (!info) return NULL; + name = info->name; + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); if (!ps) return NULL; ps->bus = bus; ps->sw_addr = sw_addr; + ps->info = info; ps->id = id & 0xfff0; *priv = ps; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 6513450d60bf..b87f574a84de 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -68,6 +68,23 @@ #define PORT_PCS_CTRL_UNFORCED 0x03 #define PORT_PAUSE_CTRL 0x02 #define PORT_SWITCH_ID 0x03 +#define PORT_SWITCH_ID_PROD_NUM_6085 0x04a +#define PORT_SWITCH_ID_PROD_NUM_6095 0x095 +#define PORT_SWITCH_ID_PROD_NUM_6131 0x106 +#define PORT_SWITCH_ID_PROD_NUM_6320 0x115 +#define PORT_SWITCH_ID_PROD_NUM_6123 0x121 +#define PORT_SWITCH_ID_PROD_NUM_6161 0x161 +#define PORT_SWITCH_ID_PROD_NUM_6165 0x165 +#define PORT_SWITCH_ID_PROD_NUM_6171 0x171 +#define PORT_SWITCH_ID_PROD_NUM_6172 0x172 +#define PORT_SWITCH_ID_PROD_NUM_6175 0x175 +#define PORT_SWITCH_ID_PROD_NUM_6176 0x176 +#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7 +#define PORT_SWITCH_ID_PROD_NUM_6240 0x240 +#define PORT_SWITCH_ID_PROD_NUM_6321 0x310 +#define PORT_SWITCH_ID_PROD_NUM_6352 0x352 +#define PORT_SWITCH_ID_PROD_NUM_6350 0x371 +#define PORT_SWITCH_ID_PROD_NUM_6351 0x375 #define PORT_SWITCH_ID_6031 0x0310 #define PORT_SWITCH_ID_6035 0x0350 #define PORT_SWITCH_ID_6046 0x0480 @@ -352,9 +369,9 @@ #define MV88E6XXX_N_FID 4096 -struct mv88e6xxx_switch_id { - u16 id; - char *name; +struct mv88e6xxx_info { + u16 prod_num; + const char *name; }; struct mv88e6xxx_atu_entry { @@ -382,6 +399,8 @@ struct mv88e6xxx_priv_port { }; struct mv88e6xxx_priv_state { + const struct mv88e6xxx_info *info; + /* The dsa_switch this private structure is related to */ struct dsa_switch *ds; @@ -449,7 +468,7 @@ struct mv88e6xxx_hw_stat { int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, int sw_addr, void **priv, - const struct mv88e6xxx_switch_id *table, + const struct mv88e6xxx_info *table, unsigned int num); int mv88e6xxx_setup_ports(struct dsa_switch *ds); -- GitLab From 22356476a86fc569c34cbf209d3a247c01e0ef6d Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:24:00 -0400 Subject: [PATCH 3172/9938] net: dsa: mv88e6xxx: add family to info Add an mv88e6xxx_family enum to the info structure for better family indentification. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123.c | 3 ++ drivers/net/dsa/mv88e6131.c | 4 +++ drivers/net/dsa/mv88e6171.c | 4 +++ drivers/net/dsa/mv88e6352.c | 6 ++++ drivers/net/dsa/mv88e6xxx.c | 71 +++++-------------------------------- drivers/net/dsa/mv88e6xxx.h | 13 +++++++ 6 files changed, 38 insertions(+), 63 deletions(-) diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 62dffcf915a7..776e6ef3e29c 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -20,12 +20,15 @@ static const struct mv88e6xxx_info mv88e6123_table[] = { { .prod_num = PORT_SWITCH_ID_PROD_NUM_6123, + .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6123", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6161, + .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6161", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6165, + .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6165", } }; diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 00567156f335..1986651ac054 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -20,15 +20,19 @@ static const struct mv88e6xxx_info mv88e6131_table[] = { { .prod_num = PORT_SWITCH_ID_PROD_NUM_6095, + .family = MV88E6XXX_FAMILY_6095, .name = "Marvell 88E6095/88E6095F", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6085, + .family = MV88E6XXX_FAMILY_6097, .name = "Marvell 88E6085", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6131, + .family = MV88E6XXX_FAMILY_6185, .name = "Marvell 88E6131", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6185, + .family = MV88E6XXX_FAMILY_6185, .name = "Marvell 88E6185", } }; diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index ea14ab22d313..9a3b1e19b01a 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -20,15 +20,19 @@ static const struct mv88e6xxx_info mv88e6171_table[] = { { .prod_num = PORT_SWITCH_ID_PROD_NUM_6171, + .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6171", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6175, + .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6175", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6350, + .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6350", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6351, + .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6351", } }; diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 2f72606ecc9e..bae62eb9c3b5 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -25,21 +25,27 @@ static const struct mv88e6xxx_info mv88e6352_table[] = { { .prod_num = PORT_SWITCH_ID_PROD_NUM_6320, + .family = MV88E6XXX_FAMILY_6320, .name = "Marvell 88E6320", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6321, + .family = MV88E6XXX_FAMILY_6320, .name = "Marvell 88E6321", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6172, + .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6172", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6176, + .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6176", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6240, + .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6240", }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6352, + .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6352", } }; diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 5fb21e059f35..8f8a1cf59fda 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -402,111 +402,56 @@ static bool mv88e6xxx_6065_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6031: - case PORT_SWITCH_ID_6061: - case PORT_SWITCH_ID_6035: - case PORT_SWITCH_ID_6065: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6065; } static bool mv88e6xxx_6095_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6092: - case PORT_SWITCH_ID_6095: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6095; } static bool mv88e6xxx_6097_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6046: - case PORT_SWITCH_ID_6085: - case PORT_SWITCH_ID_6096: - case PORT_SWITCH_ID_6097: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6097; } static bool mv88e6xxx_6165_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6123: - case PORT_SWITCH_ID_6161: - case PORT_SWITCH_ID_6165: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6165; } static bool mv88e6xxx_6185_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6121: - case PORT_SWITCH_ID_6122: - case PORT_SWITCH_ID_6152: - case PORT_SWITCH_ID_6155: - case PORT_SWITCH_ID_6182: - case PORT_SWITCH_ID_6185: - case PORT_SWITCH_ID_6108: - case PORT_SWITCH_ID_6131: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6185; } static bool mv88e6xxx_6320_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6320: - case PORT_SWITCH_ID_6321: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6320; } static bool mv88e6xxx_6351_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6171: - case PORT_SWITCH_ID_6175: - case PORT_SWITCH_ID_6350: - case PORT_SWITCH_ID_6351: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6351; } static bool mv88e6xxx_6352_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6172: - case PORT_SWITCH_ID_6176: - case PORT_SWITCH_ID_6240: - case PORT_SWITCH_ID_6352: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6352; } static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index b87f574a84de..b4eec9a8c8ff 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -369,7 +369,20 @@ #define MV88E6XXX_N_FID 4096 +enum mv88e6xxx_family { + MV88E6XXX_FAMILY_NONE, + MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */ + MV88E6XXX_FAMILY_6095, /* 6092 6095 */ + MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ + MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ + MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ + MV88E6XXX_FAMILY_6320, /* 6320 6321 */ + MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ + MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ +}; + struct mv88e6xxx_info { + enum mv88e6xxx_family family; u16 prod_num; const char *name; }; -- GitLab From 009a2b9843bf0b1a85fbf79f76e1de4995de527c Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:24:01 -0400 Subject: [PATCH 3173/9938] net: dsa: mv88e6xxx: add number of ports to info Drop the ps->num_ports variable in favor of a new member of the info structure. This removes the need to assign it at setup time. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123.c | 16 +++------------- drivers/net/dsa/mv88e6131.c | 22 +++++---------------- drivers/net/dsa/mv88e6171.c | 7 ++++--- drivers/net/dsa/mv88e6352.c | 8 ++++++-- drivers/net/dsa/mv88e6xxx.c | 38 ++++++++++++++++++------------------- drivers/net/dsa/mv88e6xxx.h | 3 +-- 6 files changed, 38 insertions(+), 56 deletions(-) diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 776e6ef3e29c..0bf43bb17993 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -22,14 +22,17 @@ static const struct mv88e6xxx_info mv88e6123_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6123, .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6123", + .num_ports = 3, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6161, .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6161", + .num_ports = 6, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6165, .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6165", + .num_ports = 6, } }; @@ -80,25 +83,12 @@ static int mv88e6123_setup_global(struct dsa_switch *ds) static int mv88e6123_setup(struct dsa_switch *ds) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; - switch (ps->id) { - case PORT_SWITCH_ID_6123: - ps->num_ports = 3; - break; - case PORT_SWITCH_ID_6161: - case PORT_SWITCH_ID_6165: - ps->num_ports = 6; - break; - default: - return -ENODEV; - } - ret = mv88e6xxx_switch_reset(ds, false); if (ret < 0) return ret; diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 1986651ac054..c01bbb1e857e 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -22,18 +22,22 @@ static const struct mv88e6xxx_info mv88e6131_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6095, .family = MV88E6XXX_FAMILY_6095, .name = "Marvell 88E6095/88E6095F", + .num_ports = 11, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6085, .family = MV88E6XXX_FAMILY_6097, .name = "Marvell 88E6085", + .num_ports = 10, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6131, .family = MV88E6XXX_FAMILY_6185, .name = "Marvell 88E6131", + .num_ports = 8, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6185, .family = MV88E6XXX_FAMILY_6185, .name = "Marvell 88E6185", + .num_ports = 10, } }; @@ -110,7 +114,6 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) static int mv88e6131_setup(struct dsa_switch *ds) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; ret = mv88e6xxx_setup_common(ds); @@ -119,21 +122,6 @@ static int mv88e6131_setup(struct dsa_switch *ds) mv88e6xxx_ppu_state_init(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6085: - case PORT_SWITCH_ID_6185: - ps->num_ports = 10; - break; - case PORT_SWITCH_ID_6095: - ps->num_ports = 11; - break; - case PORT_SWITCH_ID_6131: - ps->num_ports = 8; - break; - default: - return -ENODEV; - } - ret = mv88e6xxx_switch_reset(ds, false); if (ret < 0) return ret; @@ -149,7 +137,7 @@ static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - if (port >= 0 && port < ps->num_ports) + if (port >= 0 && port < ps->info->num_ports) return port; return -EINVAL; diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 9a3b1e19b01a..172824fe1dc0 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -22,18 +22,22 @@ static const struct mv88e6xxx_info mv88e6171_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6171, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6171", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6175, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6175", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6350, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6350", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6351, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6351", + .num_ports = 7, } }; @@ -86,15 +90,12 @@ static int mv88e6171_setup_global(struct dsa_switch *ds) static int mv88e6171_setup(struct dsa_switch *ds) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; - ps->num_ports = 7; - ret = mv88e6xxx_switch_reset(ds, true); if (ret < 0) return ret; diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index bae62eb9c3b5..12b9a7b5cb31 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -27,26 +27,32 @@ static const struct mv88e6xxx_info mv88e6352_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6320, .family = MV88E6XXX_FAMILY_6320, .name = "Marvell 88E6320", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6321, .family = MV88E6XXX_FAMILY_6320, .name = "Marvell 88E6321", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6172, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6172", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6176, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6176", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6240, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6240", + .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6352, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6352", + .num_ports = 7, } }; @@ -104,8 +110,6 @@ static int mv88e6352_setup(struct dsa_switch *ds) if (ret < 0) return ret; - ps->num_ports = 7; - mutex_init(&ps->eeprom_mutex); ret = mv88e6xxx_switch_reset(ds, true); diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 8f8a1cf59fda..c952d91a5b88 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -551,7 +551,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, reg |= PORT_PCS_CTRL_DUPLEX_FULL; if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) && - (port >= ps->num_ports - 2)) { + (port >= ps->info->num_ports - 2)) { if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) @@ -1132,7 +1132,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct net_device *bridge = ps->ports[port].bridge_dev; - const u16 mask = (1 << ps->num_ports) - 1; + const u16 mask = (1 << ps->info->num_ports) - 1; u16 output_ports = 0; int reg; int i; @@ -1141,7 +1141,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { output_ports = mask; } else { - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { /* allow sending frames to every group member */ if (bridge && ps->ports[i].bridge_dev == bridge) output_ports |= BIT(i); @@ -1282,7 +1282,7 @@ static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds, regs[i] = ret; } - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { unsigned int shift = (i % 4) * 4 + nibble_offset; u16 reg = regs[i / 4]; @@ -1301,7 +1301,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds, int i; int ret; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { unsigned int shift = (i % 4) * 4 + nibble_offset; u8 data = entry->data[i]; @@ -1633,7 +1633,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid) bitmap_zero(fid_bitmap, MV88E6XXX_N_FID); /* Set every FID bit used by the (un)bridged ports */ - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { err = _mv88e6xxx_port_fid_get(ds, i, fid); if (err) return err; @@ -1683,7 +1683,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid, return err; /* exclude all ports except the CPU and DSA ports */ - for (i = 0; i < ps->num_ports; ++i) + for (i = 0; i < ps->info->num_ports; ++i) vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i) ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; @@ -1772,7 +1772,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, if (vlan.vid > vid_end) break; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i)) continue; @@ -1921,7 +1921,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) /* keep the VLAN unless all ports are excluded */ vlan.valid = false; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) continue; @@ -2230,11 +2230,11 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); /* Get or create the bridge FID and assign it to the port */ - for (i = 0; i < ps->num_ports; ++i) + for (i = 0; i < ps->info->num_ports; ++i) if (ps->ports[i].bridge_dev == bridge) break; - if (i < ps->num_ports) + if (i < ps->info->num_ports) err = _mv88e6xxx_port_fid_get(ds, i, &fid); else err = _mv88e6xxx_fid_new(ds, &fid); @@ -2248,7 +2248,7 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, /* Assign the bridge and remap each port's VLANTable */ ps->ports[port].bridge_dev = bridge; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { if (ps->ports[i].bridge_dev == bridge) { err = _mv88e6xxx_port_based_vlan_map(ds, i); if (err) @@ -2279,7 +2279,7 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port) /* Unassign the bridge and remap each port's VLANTable */ ps->ports[port].bridge_dev = NULL; - for (i = 0; i < ps->num_ports; ++i) + for (i = 0; i < ps->info->num_ports; ++i) if (i == port || ps->ports[i].bridge_dev == bridge) if (_mv88e6xxx_port_based_vlan_map(ds, i)) netdev_warn(ds->ports[i], "failed to remap\n"); @@ -2298,7 +2298,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) mutex_lock(&ps->smi_mutex); - for (port = 0; port < ps->num_ports; ++port) + for (port = 0; port < ps->info->num_ports; ++port) if (test_and_clear_bit(port, ps->port_state_update_mask) && _mv88e6xxx_port_state(ds, port, ps->ports[port].state)) netdev_warn(ds->ports[port], "failed to update state to %s\n", @@ -2630,7 +2630,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds) int ret; int i; - for (i = 0; i < ps->num_ports; i++) { + for (i = 0; i < ps->info->num_ports; i++) { ret = mv88e6xxx_setup_port(ds, i); if (ret < 0) return ret; @@ -2737,7 +2737,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK, 0x8000 | (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) | - ((1 << ps->num_ports) - 1)); + ((1 << ps->info->num_ports) - 1)); if (err) goto unlock; } @@ -2790,7 +2790,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) * ingress rate limit registers to their initial * state. */ - for (i = 0; i < ps->num_ports; i++) { + for (i = 0; i < ps->info->num_ports; i++) { err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_INGRESS_OP, 0x9000 | (i << 8)); @@ -2835,7 +2835,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) mutex_lock(&ps->smi_mutex); /* Set all ports to the disabled state. */ - for (i = 0; i < ps->num_ports; i++) { + for (i = 0; i < ps->info->num_ports; i++) { ret = _mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL); if (ret < 0) goto unlock; @@ -2918,7 +2918,7 @@ static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - if (port >= 0 && port < ps->num_ports) + if (port >= 0 && port < ps->info->num_ports) return port; return -EINVAL; } diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index b4eec9a8c8ff..801486aefe78 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -385,6 +385,7 @@ struct mv88e6xxx_info { enum mv88e6xxx_family family; u16 prod_num; const char *name; + unsigned int num_ports; }; struct mv88e6xxx_atu_entry { @@ -456,8 +457,6 @@ struct mv88e6xxx_priv_state { struct mutex eeprom_mutex; int id; /* switch product id */ - int num_ports; /* number of switch ports */ - struct mv88e6xxx_priv_port ports[DSA_MAX_PORTS]; DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS); -- GitLab From cd5a2c82bad9e59f2674befc07c12effa0aea49d Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:24:02 -0400 Subject: [PATCH 3174/9938] net: dsa: mv88e6xxx: add number of db to info Add the number of databases to the info structure. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123.c | 3 +++ drivers/net/dsa/mv88e6131.c | 4 ++++ drivers/net/dsa/mv88e6171.c | 4 ++++ drivers/net/dsa/mv88e6352.c | 6 ++++++ drivers/net/dsa/mv88e6xxx.c | 19 +------------------ drivers/net/dsa/mv88e6xxx.h | 1 + 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 0bf43bb17993..534ebc84de84 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -22,16 +22,19 @@ static const struct mv88e6xxx_info mv88e6123_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6123, .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6123", + .num_databases = 4096, .num_ports = 3, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6161, .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6161", + .num_databases = 4096, .num_ports = 6, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6165, .family = MV88E6XXX_FAMILY_6165, .name = "Marvell 88E6165", + .num_databases = 4096, .num_ports = 6, } }; diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index c01bbb1e857e..c3eb9a884cfd 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -22,21 +22,25 @@ static const struct mv88e6xxx_info mv88e6131_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6095, .family = MV88E6XXX_FAMILY_6095, .name = "Marvell 88E6095/88E6095F", + .num_databases = 256, .num_ports = 11, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6085, .family = MV88E6XXX_FAMILY_6097, .name = "Marvell 88E6085", + .num_databases = 4096, .num_ports = 10, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6131, .family = MV88E6XXX_FAMILY_6185, .name = "Marvell 88E6131", + .num_databases = 256, .num_ports = 8, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6185, .family = MV88E6XXX_FAMILY_6185, .name = "Marvell 88E6185", + .num_databases = 256, .num_ports = 10, } }; diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 172824fe1dc0..841ffe14ef75 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -22,21 +22,25 @@ static const struct mv88e6xxx_info mv88e6171_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6171, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6171", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6175, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6175", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6350, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6350", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6351, .family = MV88E6XXX_FAMILY_6351, .name = "Marvell 88E6351", + .num_databases = 4096, .num_ports = 7, } }; diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 12b9a7b5cb31..4afc24df56b8 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -27,31 +27,37 @@ static const struct mv88e6xxx_info mv88e6352_table[] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6320, .family = MV88E6XXX_FAMILY_6320, .name = "Marvell 88E6320", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6321, .family = MV88E6XXX_FAMILY_6320, .name = "Marvell 88E6321", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6172, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6172", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6176, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6176", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6240, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6240", + .num_databases = 4096, .num_ports = 7, }, { .prod_num = PORT_SWITCH_ID_PROD_NUM_6352, .family = MV88E6XXX_FAMILY_6352, .name = "Marvell 88E6352", + .num_databases = 4096, .num_ports = 7, } }; diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index c952d91a5b88..67b1dd1c22f7 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -458,24 +458,7 @@ static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - /* The following devices have 4-bit identifiers for 16 databases */ - if (ps->id == PORT_SWITCH_ID_6061) - return 16; - - /* The following devices have 6-bit identifiers for 64 databases */ - if (ps->id == PORT_SWITCH_ID_6065) - return 64; - - /* The following devices have 8-bit identifiers for 256 databases */ - if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) - return 256; - - /* The following devices have 12-bit identifiers for 4096 databases */ - if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) - return 4096; - - return 0; + return ps->info->num_databases; } static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 801486aefe78..8eeafff27a82 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -385,6 +385,7 @@ struct mv88e6xxx_info { enum mv88e6xxx_family family; u16 prod_num; const char *name; + unsigned int num_databases; unsigned int num_ports; }; -- GitLab From d967ecbc0b875081624857f27df4ed23c5eca106 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 17 Apr 2016 13:24:03 -0400 Subject: [PATCH 3175/9938] net: dsa: mv88e6xxx: remove switch ID from ps ps->id is not needed anymore, so remove it as well as the related defined values. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 1 - drivers/net/dsa/mv88e6xxx.h | 32 -------------------------------- 2 files changed, 33 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 67b1dd1c22f7..1dd525d8dc0a 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -3145,7 +3145,6 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, ps->bus = bus; ps->sw_addr = sw_addr; ps->info = info; - ps->id = id & 0xfff0; *priv = ps; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 8eeafff27a82..0dbe2d1779dd 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -85,37 +85,6 @@ #define PORT_SWITCH_ID_PROD_NUM_6352 0x352 #define PORT_SWITCH_ID_PROD_NUM_6350 0x371 #define PORT_SWITCH_ID_PROD_NUM_6351 0x375 -#define PORT_SWITCH_ID_6031 0x0310 -#define PORT_SWITCH_ID_6035 0x0350 -#define PORT_SWITCH_ID_6046 0x0480 -#define PORT_SWITCH_ID_6061 0x0610 -#define PORT_SWITCH_ID_6065 0x0650 -#define PORT_SWITCH_ID_6085 0x04a0 -#define PORT_SWITCH_ID_6092 0x0970 -#define PORT_SWITCH_ID_6095 0x0950 -#define PORT_SWITCH_ID_6096 0x0980 -#define PORT_SWITCH_ID_6097 0x0990 -#define PORT_SWITCH_ID_6108 0x1070 -#define PORT_SWITCH_ID_6121 0x1040 -#define PORT_SWITCH_ID_6122 0x1050 -#define PORT_SWITCH_ID_6123 0x1210 -#define PORT_SWITCH_ID_6131 0x1060 -#define PORT_SWITCH_ID_6152 0x1a40 -#define PORT_SWITCH_ID_6155 0x1a50 -#define PORT_SWITCH_ID_6161 0x1610 -#define PORT_SWITCH_ID_6165 0x1650 -#define PORT_SWITCH_ID_6171 0x1710 -#define PORT_SWITCH_ID_6172 0x1720 -#define PORT_SWITCH_ID_6175 0x1750 -#define PORT_SWITCH_ID_6176 0x1760 -#define PORT_SWITCH_ID_6182 0x1a60 -#define PORT_SWITCH_ID_6185 0x1a70 -#define PORT_SWITCH_ID_6240 0x2400 -#define PORT_SWITCH_ID_6320 0x1150 -#define PORT_SWITCH_ID_6321 0x3100 -#define PORT_SWITCH_ID_6350 0x3710 -#define PORT_SWITCH_ID_6351 0x3750 -#define PORT_SWITCH_ID_6352 0x3520 #define PORT_CONTROL 0x04 #define PORT_CONTROL_USE_CORE_TAG BIT(15) #define PORT_CONTROL_DROP_ON_LOCK BIT(14) @@ -457,7 +426,6 @@ struct mv88e6xxx_priv_state { */ struct mutex eeprom_mutex; - int id; /* switch product id */ struct mv88e6xxx_priv_port ports[DSA_MAX_PORTS]; DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS); -- GitLab From 60f9ae0d2b173245ba960b2fcd0fc44e81f92017 Mon Sep 17 00:00:00 2001 From: Yuan Yao Date: Wed, 13 Apr 2016 18:08:26 +0800 Subject: [PATCH 3176/9938] Documentation: fsl-quadspi: Add fsl,ls1043a-qspi compatible string new compatible string: "fsl,ls1043a-qspi". Signed-off-by: Yuan Yao Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/mtd/fsl-quadspi.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt index 0333ec87dc49..c34aa6f8a424 100644 --- a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt @@ -5,7 +5,8 @@ Required properties: "fsl,imx7d-qspi", "fsl,imx6ul-qspi", "fsl,ls1021a-qspi" or - "fsl,ls2080a-qspi" followed by "fsl,ls1021a-qspi" + "fsl,ls2080a-qspi" followed by "fsl,ls1021a-qspi", + "fsl,ls1043a-qspi" followed by "fsl,ls1021a-qspi" - reg : the first contains the register location and length, the second contains the memory mapping address and length - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory" -- GitLab From e26e054ba8a2f9d357cdc874168396ea4ef73c28 Mon Sep 17 00:00:00 2001 From: Yuan Yao Date: Wed, 13 Apr 2016 18:08:27 +0800 Subject: [PATCH 3177/9938] arm64: dts: ls1043a: add the DTS node for QSPI support Signed-off-by: Yuan Yao Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts | 13 +++++++++++++ arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 14 ++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts index 80688acb73a3..9d3e9fe1c87c 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts @@ -166,3 +166,16 @@ &lpuart0 { status = "okay"; }; + +&qspi { + bus-num = <0>; + status = "okay"; + + qflash0: s25fl128s@0 { + compatible = "spansion,m25p80"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <20000000>; + reg = <0>; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index bf70b276f09b..de0323b48b1e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -171,6 +171,20 @@ interrupts = <0 43 0x4>; }; + qspi: quadspi@1550000 { + compatible = "fsl,ls1043a-qspi", "fsl,ls1021a-qspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x1550000 0x0 0x10000>, + <0x0 0x40000000 0x0 0x4000000>; + reg-names = "QuadSPI", "QuadSPI-memory"; + interrupts = <0 99 0x4>; + clock-names = "qspi_en", "qspi"; + clocks = <&clockgen 4 0>, <&clockgen 4 0>; + big-endian; + status = "disabled"; + }; + esdhc: esdhc@1560000 { compatible = "fsl,ls1043a-esdhc", "fsl,esdhc"; reg = <0x0 0x1560000 0x0 0x10000>; -- GitLab From 3397c2c45b1b6f54834dfeae30a73046f33ca943 Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Thu, 14 Apr 2016 23:30:49 +0200 Subject: [PATCH 3178/9938] ARM: dts: imx35: restore existing used clock enumeration A new element got inserted into enum mx35_clks with commit 3713e3f5e927 ("clk: imx35: define two clocks for rtc"). This insertion shifted most nummerical clock assignments to a new nummerical value which in turn rendered most hardcoded nummeric values in imx35.dtsi incorrect. Restore the existing order by moving the newly introduced clock to the end of the enum. Update the dts documentation accordingly. Signed-off-by: Alexander Kurz Fixes: 3713e3f5e927 ("clk: imx35: define two clocks for rtc") Cc: Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/clock/imx35-clock.txt | 1 + drivers/clk/imx/clk-imx35.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/imx35-clock.txt b/Documentation/devicetree/bindings/clock/imx35-clock.txt index a70356452a82..f49783213c56 100644 --- a/Documentation/devicetree/bindings/clock/imx35-clock.txt +++ b/Documentation/devicetree/bindings/clock/imx35-clock.txt @@ -94,6 +94,7 @@ clocks and IDs. csi_sel 79 iim_gate 80 gpu2d_gate 81 + ckli_gate 82 Examples: diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c index a71d24cb4c06..b0978d3b83e2 100644 --- a/drivers/clk/imx/clk-imx35.c +++ b/drivers/clk/imx/clk-imx35.c @@ -66,7 +66,7 @@ static const char *std_sel[] = {"ppll", "arm"}; static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"}; enum mx35_clks { - ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg, + ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg, arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel, esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre, spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre, @@ -79,7 +79,7 @@ enum mx35_clks { rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate, ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate, wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate, - gpu2d_gate, clk_max + gpu2d_gate, ckil, clk_max }; static struct clk *clk[clk_max]; -- GitLab From c17e9377aa81664d94b4f2102559fcf2a01ec8e7 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 18 Apr 2016 07:12:00 +0300 Subject: [PATCH 3179/9938] ARM: dts: lpc32xx: set default clock rate of HCLK PLL Probably most of NXP LPC32xx boards have 13MHz main oscillator and therefore for HCLK PLL and ARM core clock rate default hardware setting is 16 * 13MHz = 208MHz, however a user may vary HCLK PLL/ARM core rate from 156MHz to about 266MHz for 13MHz clock source. The change explicitly defines HCLK PLL output rate to default 208MHz to overwrite any settings done by a bootloader, if needed it can be redefined in a board DTS file. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/lpc32xx.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index c58d8da9ea2a..d7b84cd209db 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -294,6 +294,9 @@ clocks = <&xtal_32k>, <&xtal>; clock-names = "xtal_32k", "xtal"; + + assigned-clocks = <&clk LPC32XX_CLK_HCLK_PLL>; + assigned-clock-rates = <208000000>; }; }; -- GitLab From d8c8c70c48d1bc9bca41369836f9a3c781a5cdea Mon Sep 17 00:00:00 2001 From: Alexander Kurz Date: Fri, 15 Apr 2016 09:54:20 +0200 Subject: [PATCH 3180/9938] ARM: dts: i.MX3x: add keypad port devicetree nodes Add the Keypad Port (KPP) devicetree nodes for IMX31 and IMX35 SOC. Signed-off-by: Alexander Kurz Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx31.dtsi | 8 ++++++++ arch/arm/boot/dts/imx35.dtsi | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi index 5fdb222636a7..1ce7ae94e7ad 100644 --- a/arch/arm/boot/dts/imx31.dtsi +++ b/arch/arm/boot/dts/imx31.dtsi @@ -69,6 +69,14 @@ status = "disabled"; }; + kpp: kpp@43fa8000 { + compatible = "fsl,imx31-kpp", "fsl,imx21-kpp"; + reg = <0x43fa8000 0x4000>; + interrupts = <24>; + clocks = <&clks 46>; + status = "disabled"; + }; + uart4: serial@43fb0000 { compatible = "fsl,imx31-uart", "fsl,imx21-uart"; reg = <0x43fb0000 0x4000>; diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi index 14e1320d9f84..490b7b44f1e7 100644 --- a/arch/arm/boot/dts/imx35.dtsi +++ b/arch/arm/boot/dts/imx35.dtsi @@ -137,6 +137,14 @@ status = "disabled"; }; + kpp: kpp@43fa8000 { + compatible = "fsl,imx35-kpp", "fsl,imx21-kpp"; + reg = <0x43fa8000 0x4000>; + interrupts = <24>; + clocks = <&clks 56>; + status = "disabled"; + }; + iomuxc: iomuxc@43fac000 { compatible = "fsl,imx35-iomuxc"; reg = <0x43fac000 0x4000>; -- GitLab From 880e1509db9732d5696d2a092e9bd61d80ad00be Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sat, 16 Apr 2016 00:27:23 +0200 Subject: [PATCH 3181/9938] ARM: dts: imx6qdl-udoo: add 7 inch LCD touchscreen panel support The official UDOO board kit has 7 and 15.6 inch touchscreen LCD panels as options. This patch adds support for 7 inch panel only, but the 15.6 inch one should be easy to add using the same regulator, backlight device and LVDS channel. Since this panel is an option for UDOO board it is disabled by default and can be enabled (for example) by the following U-Boot commands: fdt set backlight status okay fdt set panelchan status okay fdt set panel7 status okay fdt set touchscreenp7 status okay The LVDS channels is also disabled by default to avoid warning from its driver. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-udoo.dtsi | 96 +++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi index d3e54e40a017..0dd5aa1b45e0 100644 --- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi +++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi @@ -10,14 +10,49 @@ */ / { + aliases { + backlight = &backlight; + panelchan = &panelchan; + panel7 = &panel7; + touchscreenp7 = &touchscreenp7; + }; + chosen { stdout-path = &uart2; }; + backlight: backlight { + compatible = "gpio-backlight"; + gpios = <&gpio1 4 0>; + default-on; + status = "disabled"; + }; + memory { reg = <0x10000000 0x40000000>; }; + panel7: panel7 { + /* + * in reality it is a -20t (parallel) model, + * but with LVDS bridge chip attached, + * so it is equivalent to -19t model in drive + * characteristics + */ + compatible = "urt,umsh-8596md-19t"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_panel>; + power-supply = <®_panel>; + backlight = <&backlight>; + status = "disabled"; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; + regulators { compatible = "simple-bus"; #address-cells = <1>; @@ -33,6 +68,14 @@ startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */ gpio = <&gpio7 12 0>; }; + + reg_panel: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "lcd_panel"; + enable-active-high; + gpio = <&gpio1 2 0>; + }; }; sound { @@ -67,6 +110,24 @@ status = "okay"; }; +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; + + touchscreenp7: touchscreenp7@55 { + compatible = "sitronix,st1232"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_touchscreenp7>; + reg = <0x55>; + interrupt-parent = <&gpio1>; + interrupts = <13 8>; + gpios = <&gpio1 15 0>; + status = "disabled"; + }; +}; + &iomuxc { imx6q-udoo { pinctrl_enet: enetgrp { @@ -97,6 +158,27 @@ >; }; + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001f8b1 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001f8b1 + >; + }; + + pinctrl_panel: panelgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x70 + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x70 + >; + }; + + pinctrl_touchscreenp7: touchscreenp7grp { + fsl,pins = < + MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x70 + MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x1b0b0 + >; + }; + pinctrl_uart2: uart2grp { fsl,pins = < MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 @@ -154,6 +236,20 @@ }; }; +&ldb { + status = "okay"; + + panelchan: lvds-channel@0 { + port@4 { + reg = <4>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + &uart2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart2>; -- GitLab From a9eb221ab52480e86be60ab4cc3237fa4344b0cc Mon Sep 17 00:00:00 2001 From: Sina Hamedian Date: Sat, 30 Jan 2016 22:07:31 -0800 Subject: [PATCH 3182/9938] arch/ia64/lib: Fix broken URL in comments The URL to the book IA-64 and Elementary Functions in idiv32.S and idiv64.S just led to a 404 page, so I updated them with a known good link that others can reference. Signed-off-by: Sina Hamedian Signed-off-by: Jiri Kosina --- arch/ia64/lib/idiv32.S | 2 +- arch/ia64/lib/idiv64.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/lib/idiv32.S b/arch/ia64/lib/idiv32.S index 2ac28bf0a662..c91b5b0129ff 100644 --- a/arch/ia64/lib/idiv32.S +++ b/arch/ia64/lib/idiv32.S @@ -11,7 +11,7 @@ * * For more details on the theory behind these algorithms, see "IA-64 * and Elementary Functions" by Peter Markstein; HP Professional Books - * (http://www.hp.com/go/retailbooks/) + * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions) */ #include diff --git a/arch/ia64/lib/idiv64.S b/arch/ia64/lib/idiv64.S index f69bd2b0987a..627573c4ceb1 100644 --- a/arch/ia64/lib/idiv64.S +++ b/arch/ia64/lib/idiv64.S @@ -11,7 +11,7 @@ * * For more details on the theory behind these algorithms, see "IA-64 * and Elementary Functions" by Peter Markstein; HP Professional Books - * (http://www.hp.com/go/retailbooks/) + * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions) */ #include -- GitLab From bd7ced98812dbb906950d8b0ec786f14f631cede Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 2 Feb 2016 22:31:06 +0900 Subject: [PATCH 3183/9938] Doc: treewide : Fix typos in DocBook/filesystem.xml This patch fix spelling typos found in DocBook/filesystem.xml. It is because the file was generated from comments in code, I have to fix the comments in codes, instead of xml file. Signed-off-by: Masanari Iida Signed-off-by: Jiri Kosina --- fs/jbd2/recovery.c | 2 +- fs/jbd2/transaction.c | 6 +++--- fs/super.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 7f277e49fe88..76579c28edc7 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c @@ -304,7 +304,7 @@ int jbd2_journal_recover(journal_t *journal) * Locate any valid recovery information from the journal and set up the * journal structures in memory to ignore it (presumably because the * caller has evidence that it is out of date). - * This function does'nt appear to be exorted.. + * This function doesn't appear to be exported.. * * We perform one pass over the journal to allow us to tell the user how * much recovery information is being erased, and to let us initialise diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 6b8338ec2464..98d04c5fe3d2 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -543,7 +543,7 @@ EXPORT_SYMBOL(jbd2_journal_start_reserved); * * Some transactions, such as large extends and truncates, can be done * atomically all at once or in several stages. The operation requests - * a credit for a number of buffer modications in advance, but can + * a credit for a number of buffer modifications in advance, but can * extend its credit if it needs more. * * jbd2_journal_extend tries to give the running handle more buffer credits. @@ -627,7 +627,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) * If the jbd2_journal_extend() call above fails to grant new buffer credits * to a running handle, a call to jbd2_journal_restart will commit the * handle's transaction so far and reattach the handle to a new - * transaction capabable of guaranteeing the requested number of + * transaction capable of guaranteeing the requested number of * credits. We preserve reserved handle if there's any attached to the * passed in handle. */ @@ -1596,7 +1596,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) /** * int jbd2_journal_stop() - complete a transaction - * @handle: tranaction to complete. + * @handle: transaction to complete. * * All done for a particular handle. * diff --git a/fs/super.c b/fs/super.c index 7ea56de57d4b..6cd9f719cf61 100644 --- a/fs/super.c +++ b/fs/super.c @@ -285,7 +285,7 @@ static void put_super(struct super_block *sb) * deactivate_locked_super - drop an active reference to superblock * @s: superblock to deactivate * - * Drops an active reference to superblock, converting it into a temprory + * Drops an active reference to superblock, converting it into a temporary * one if there is no other active references left. In that case we * tell fs driver to shut it down and drop the temporary reference we * had just acquired. -- GitLab From c19ca6cb4c0891049009d48a0da79d9e8c475462 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 8 Feb 2016 20:53:12 +0900 Subject: [PATCH 3184/9938] treewide: Fix typos in printk This patch fix spelling typos found in printk within various part of the kernel sources. Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Jiri Kosina --- arch/x86/kernel/cpu/microcode/intel.c | 2 +- arch/x86/kvm/iommu.c | 2 +- block/partitions/efi.c | 4 ++-- drivers/edac/amd64_edac.c | 2 +- drivers/mtd/sm_ftl.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/sriov.c | 2 +- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 4 ++-- drivers/scsi/aic94xx/aic94xx_hwi.c | 2 +- drivers/scsi/aic94xx/aic94xx_seq.c | 2 +- drivers/scsi/isci/port.c | 2 +- fs/exofs/super.c | 2 +- net/tipc/socket.c | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index cbb3cf09b065..65cbbcd48fe4 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -422,7 +422,7 @@ static void show_saved_mc(void) data_size = get_datasize(mc_saved_header); date = mc_saved_header->date; - pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, toal size=0x%x, date = %04x-%02x-%02x\n", + pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, total size=0x%x, date = %04x-%02x-%02x\n", i, sig, pf, rev, total_size, date & 0xffff, date >> 24, diff --git a/arch/x86/kvm/iommu.c b/arch/x86/kvm/iommu.c index a22a488b4622..3069281904d3 100644 --- a/arch/x86/kvm/iommu.c +++ b/arch/x86/kvm/iommu.c @@ -254,7 +254,7 @@ int kvm_iommu_map_guest(struct kvm *kvm) !iommu_capable(&pci_bus_type, IOMMU_CAP_INTR_REMAP)) { printk(KERN_WARNING "%s: No interrupt remapping support," " disallowing device assignment." - " Re-enble with \"allow_unsafe_assigned_interrupts=1\"" + " Re-enable with \"allow_unsafe_assigned_interrupts=1\"" " module option.\n", __func__); iommu_domain_free(kvm->arch.iommu_domain); kvm->arch.iommu_domain = NULL; diff --git a/block/partitions/efi.c b/block/partitions/efi.c index 26cb624ace05..bcd86e5cd546 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c @@ -430,7 +430,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, } /* Check that sizeof_partition_entry has the correct value */ if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { - pr_debug("GUID Partitition Entry Size check failed.\n"); + pr_debug("GUID Partition Entry Size check failed.\n"); goto fail; } @@ -443,7 +443,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, le32_to_cpu((*gpt)->sizeof_partition_entry)); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { - pr_debug("GUID Partitition Entry Array CRC check failed.\n"); + pr_debug("GUID Partition Entry Array CRC check failed.\n"); goto fail_ptes; } diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index d87a47547ba5..930089e9e411 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -645,7 +645,7 @@ static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr) input_addr = dram_addr_to_input_addr(mci, sys_addr_to_dram_addr(mci, sys_addr)); - edac_dbg(2, "SysAdddr 0x%lx translates to InputAddr 0x%lx\n", + edac_dbg(2, "SysAddr 0x%lx translates to InputAddr 0x%lx\n", (unsigned long)sys_addr, (unsigned long)input_addr); return input_addr; diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index b096f8bb05ba..3692dd547879 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -386,7 +386,7 @@ static int sm_write_block(struct sm_ftl *ftl, uint8_t *buf, if (test_bit(boffset / SM_SECTOR_SIZE, &invalid_bitmap)) { sm_printk("sector %d of block at LBA %d of zone %d" - " coudn't be read, marking it as invalid", + " couldn't be read, marking it as invalid", boffset / SM_SECTOR_SIZE, lba, zone); oob.data_status = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c index 7b24386794f9..d6a3f412ba9f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c @@ -140,7 +140,7 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs) struct mlx5_core_sriov *sriov = &dev->priv.sriov; int err; - mlx5_core_dbg(dev, "requsted num_vfs %d\n", num_vfs); + mlx5_core_dbg(dev, "requested num_vfs %d\n", num_vfs); if (!mlx5_core_is_pf(dev)) return -EPERM; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index fe900badd468..71e4dd9965bb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -2315,14 +2315,14 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw) pci_read_config_byte(rtlpci->pdev, 0x34, &cap_pointer); RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PCI configration 0x34 = 0x%2x\n", cap_pointer); + "PCI configuration 0x34 = 0x%2x\n", cap_pointer); do { pci_read_config_word(rtlpci->pdev, cap_pointer, &cap_hdr); cap_id = cap_hdr & 0xFF; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "in pci configration, cap_pointer%x = %x\n", + "in pci configuration, cap_pointer%x = %x\n", cap_pointer, cap_id); if (cap_id == 0x01) { diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 9f636a34d595..0fdc98bc2338 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -477,7 +477,7 @@ static int asd_init_chip(struct asd_ha_struct *asd_ha) err = asd_start_seqs(asd_ha); if (err) { - asd_printk("coudln't start seqs for %s\n", + asd_printk("couldn't start seqs for %s\n", pci_name(asd_ha->pcidev)); goto out; } diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 5fdca93892ad..da1e0568510d 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -1352,7 +1352,7 @@ int asd_start_seqs(struct asd_ha_struct *asd_ha) for_each_sequencer(lseq_mask, lseq_mask, lseq) { err = asd_seq_start_lseq(asd_ha, lseq); if (err) { - asd_printk("coudln't start LSEQ %d for %s\n", lseq, + asd_printk("couldn't start LSEQ %d for %s\n", lseq, pci_name(asd_ha->pcidev)); return err; } diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 13098b09a824..a4dd5c91508c 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -794,7 +794,7 @@ static void port_timeout(unsigned long data) * case stay in the stopped state. */ dev_err(sciport_to_dev(iport), - "%s: SCIC Port 0x%p failed to stop before tiemout.\n", + "%s: SCIC Port 0x%p failed to stop before timeout.\n", __func__, iport); } else if (current_state == SCI_PORT_STOPPING) { diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 6658a50530a0..3ae161148dd5 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -122,7 +122,7 @@ static int parse_options(char *options, struct exofs_mountopt *opts) if (match_int(&args[0], &option)) return -EINVAL; if (option <= 0) { - EXOFS_ERR("Timout must be > 0"); + EXOFS_ERR("Timeout must be > 0"); return -EINVAL; } opts->timeout = option * HZ; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3eeb50a27b89..ea13717d12da 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -366,7 +366,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, sock->state = state; sock_init_data(sock, sk); if (tipc_sk_insert(tsk)) { - pr_warn("Socket create failed; port numbrer exhausted\n"); + pr_warn("Socket create failed; port number exhausted\n"); return -EINVAL; } msg_set_origport(msg, tsk->portid); -- GitLab From 148b1eb93c9b54e61d7937b5a5760030276240ab Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 16 Apr 2016 22:39:21 +0200 Subject: [PATCH 3185/9938] spi: cadence: mark pm functions __maybe_unused The newly added runtime PM support for the cadence spi driver causes harmless warnings when PM is disabled: drivers/spi/spi-cadence.c:681:12: warning: 'cnds_runtime_suspend' defined but not used drivers/spi/spi-cadence.c:652:12: warning: 'cnds_runtime_resume' defined but not used This adds __maybe_unused annotations to the respective functions to shut up the warnings, while leaving the code in place for compile testing and avoiding ugly #ifdefs. Fixes: d36ccd9f7ea4 ("spi: cadence: Runtime pm adaptation") Signed-off-by: Arnd Bergmann Acked-by: Shubhrajyoti Datta Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 8a0bd62a5088..1c57ce64abba 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -651,7 +651,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) * * Return: 0 on success and error value on error */ -static int cnds_runtime_resume(struct device *dev) +static int __maybe_unused cnds_runtime_resume(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct cdns_spi *xspi = spi_master_get_devdata(master); @@ -680,7 +680,7 @@ static int cnds_runtime_resume(struct device *dev) * * Return: Always 0 */ -static int cnds_runtime_suspend(struct device *dev) +static int __maybe_unused cnds_runtime_suspend(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct cdns_spi *xspi = spi_master_get_devdata(master); -- GitLab From 3ee15cac90e168fdea497a168a2e79acb1c4e612 Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Thu, 14 Apr 2016 15:29:35 +0200 Subject: [PATCH 3186/9938] ASoC: sti: select player for I2S/TDM TX bus By default, player#0 is connected to I2S/TDM TX bus. This patch connects player#1 to I2S/TDM TX bus. Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- sound/soc/sti/uniperif.h | 1 + sound/soc/sti/uniperif_player.c | 42 ++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index d0e24468478c..eb9933c62ad6 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1302,6 +1302,7 @@ struct uniperif { struct device *dev; int ver; /* IP version, used by register access macros */ struct regmap_field *clk_sel; + struct regmap_field *valid_sel; /* capabilities */ const struct snd_pcm_hardware *hw; diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index ff2d73597ce3..ee1c7c245bc7 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -21,7 +21,6 @@ /* sys config registers definitions */ #define SYS_CFG_AUDIO_GLUE 0xA4 -#define SYS_CFG_AUDI0_GLUE_PCM_CLKX 8 /* * Driver specific types. @@ -29,6 +28,7 @@ #define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999 #define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000 +#define UNIPERIF_PLAYER_I2S_OUT 1 /* player id connected to I2S/TDM TX bus */ /* * Note: snd_pcm_hardware is linked to DMA controller but is declared here to @@ -1013,27 +1013,30 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream, player->substream = NULL; } -static int uni_player_parse_dt_clk_glue(struct platform_device *pdev, - struct uniperif *player) +static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, + struct uniperif *player) { - int bit_offset; struct device_node *node = pdev->dev.of_node; struct regmap *regmap; - - bit_offset = SYS_CFG_AUDI0_GLUE_PCM_CLKX + player->info->id; + struct reg_field regfield[2] = { + /* PCM_CLK_SEL */ + REG_FIELD(SYS_CFG_AUDIO_GLUE, + 8 + player->info->id, + 8 + player->info->id), + /* PCMP_VALID_SEL */ + REG_FIELD(SYS_CFG_AUDIO_GLUE, 0, 1) + }; regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg"); - if (regmap) { - struct reg_field regfield = - REG_FIELD(SYS_CFG_AUDIO_GLUE, bit_offset, bit_offset); - - player->clk_sel = regmap_field_alloc(regmap, regfield); - } else { + if (!regmap) { dev_err(&pdev->dev, "sti-audio-clk-glue syscf not found\n"); return -EINVAL; } + player->clk_sel = regmap_field_alloc(regmap, regfield[0]); + player->valid_sel = regmap_field_alloc(regmap, regfield[1]); + return 0; } @@ -1084,8 +1087,8 @@ static int uni_player_parse_dt(struct platform_device *pdev, /* Save the info structure */ player->info = info; - /* Get the PCM_CLK_SEL bit from audio-glue-ctrl SoC register */ - if (uni_player_parse_dt_clk_glue(pdev, player)) + /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */ + if (uni_player_parse_dt_audio_glue(pdev, player)) return -EINVAL; return 0; @@ -1139,6 +1142,17 @@ int uni_player_init(struct platform_device *pdev, } } + /* connect to I2S/TDM TX bus */ + if (player->valid_sel && + (player->info->id == UNIPERIF_PLAYER_I2S_OUT)) { + ret = regmap_field_write(player->valid_sel, player->info->id); + if (ret) { + dev_err(player->dev, + "%s: unable to connect to tdm bus", __func__); + return ret; + } + } + ret = devm_request_irq(&pdev->dev, player->irq, uni_player_irq_handler, IRQF_SHARED, dev_name(&pdev->dev), player); -- GitLab From b1d21a24df458c897911af51cb637460c1ac5d95 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 15 Apr 2016 10:44:37 -0700 Subject: [PATCH 3187/9938] regulator: qcom_spmi: Always return a selector when asked I had a thinko in spmi_regulator_select_voltage_same_range() when converting it to return selectors via the function's return value instead of by modifying a pointer argument. I only tested multi-range regulators so this passed through testing. Fix it by returning the selector here. Fixes: 1b5b19689278 ("regulator: qcom_spmi: Only use selector based regulator ops") Reported-by: Rajendra Nayak Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index f502f2cc65d8..84cce21e98cd 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -692,7 +692,7 @@ static int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, if (selector >= vreg->set_points->n_voltages) goto different_range; - return 0; + return selector; different_range: return spmi_regulator_select_voltage(vreg, min_uV, max_uV); -- GitLab From 133895e9f42afee8ed837cef7e308c97bc708b5b Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Tue, 23 Feb 2016 15:27:23 -0800 Subject: [PATCH 3188/9938] avr32: Fix misspelling of 'definitions' in comment. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- arch/avr32/include/asm/addrspace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/include/asm/addrspace.h b/arch/avr32/include/asm/addrspace.h index 366794858ec7..5a47a7979648 100644 --- a/arch/avr32/include/asm/addrspace.h +++ b/arch/avr32/include/asm/addrspace.h @@ -1,5 +1,5 @@ /* - * Defitions for the address spaces of the AVR32 CPUs. Heavily based on + * Definitions for the address spaces of the AVR32 CPUs. Heavily based on * include/asm-sh/addrspace.h * * Copyright (C) 2004-2006 Atmel Corporation -- GitLab From e0b1c817d85d1611b4f44f9c5b3e6426886206e0 Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Tue, 23 Feb 2016 15:28:12 -0800 Subject: [PATCH 3189/9938] blackfin: Fix misspelling of 'register' in comment. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- arch/blackfin/mach-bf609/include/mach/defBF60x_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h b/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h index 35caa7bc192c..3933e912cacd 100644 --- a/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h +++ b/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h @@ -2689,7 +2689,7 @@ #define L2CTL0_STAT 0xFFCA3010 /* L2CTL0 L2 Status Register */ #define L2CTL0_RPCR 0xFFCA3014 /* L2CTL0 L2 Read Priority Count Register */ #define L2CTL0_WPCR 0xFFCA3018 /* L2CTL0 L2 Write Priority Count Register */ -#define L2CTL0_RFA 0xFFCA3024 /* L2CTL0 L2 Refresh Address Regsiter */ +#define L2CTL0_RFA 0xFFCA3024 /* L2CTL0 L2 Refresh Address Register */ #define L2CTL0_ERRADDR0 0xFFCA3040 /* L2CTL0 L2 Bank 0 ECC Error Address Register */ #define L2CTL0_ERRADDR1 0xFFCA3044 /* L2CTL0 L2 Bank 1 ECC Error Address Register */ #define L2CTL0_ERRADDR2 0xFFCA3048 /* L2CTL0 L2 Bank 2 ECC Error Address Register */ -- GitLab From 0398b95fe4b3c90fbabfb39b77e635ec863ac040 Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Tue, 23 Feb 2016 15:28:52 -0800 Subject: [PATCH 3190/9938] c6x: Fix misspellings in comments. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- arch/c6x/include/asm/clock.h | 2 +- arch/c6x/platforms/cache.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/c6x/include/asm/clock.h b/arch/c6x/include/asm/clock.h index bcf42b2b4b1e..e2f818a7a1d1 100644 --- a/arch/c6x/include/asm/clock.h +++ b/arch/c6x/include/asm/clock.h @@ -101,7 +101,7 @@ struct clk { #define CLK_PLL BIT(2) /* PLL-derived clock */ #define PRE_PLL BIT(3) /* source is before PLL mult/div */ #define FIXED_DIV_PLL BIT(4) /* fixed divisor from PLL */ -#define FIXED_RATE_PLL BIT(5) /* fixed ouput rate PLL */ +#define FIXED_RATE_PLL BIT(5) /* fixed output rate PLL */ #define MAX_PLL_SYSCLKS 16 diff --git a/arch/c6x/platforms/cache.c b/arch/c6x/platforms/cache.c index 46fd2d530271..ec3c887c79ec 100644 --- a/arch/c6x/platforms/cache.c +++ b/arch/c6x/platforms/cache.c @@ -145,7 +145,7 @@ static void cache_block_operation(unsigned int *start, spin_lock_irqsave(&cache_lock, flags); /* - * If another cache operation is occuring + * If another cache operation is occurring */ if (unlikely(imcr_get(wc_reg))) { spin_unlock_irqrestore(&cache_lock, flags); -- GitLab From 014b38ec694ce3fd11cfedbdee75d1fdcb031839 Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Tue, 23 Feb 2016 15:30:07 -0800 Subject: [PATCH 3191/9938] cris: Fix misspellings in comments. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- arch/cris/arch-v10/drivers/axisflashmap.c | 2 +- arch/cris/arch-v32/drivers/axisflashmap.c | 2 +- arch/cris/arch-v32/drivers/cryptocop.c | 2 +- arch/cris/arch-v32/mach-a3/dram_init.S | 2 +- arch/cris/arch-v32/mach-fs/dram_init.S | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c index a4bbdfd37bd8..60d57c590032 100644 --- a/arch/cris/arch-v10/drivers/axisflashmap.c +++ b/arch/cris/arch-v10/drivers/axisflashmap.c @@ -212,7 +212,7 @@ static struct mtd_info *probe_cs(struct map_info *map_cs) /* * Probe each chip select individually for flash chips. If there are chips on * both cse0 and cse1, the mtd_info structs will be concatenated to one struct - * so that MTD partitions can cross chip boundries. + * so that MTD partitions can cross chip boundaries. * * The only known restriction to how you can mount your chips is that each * chip select must hold similar flash chips. But you need external hardware diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c index c6309a182f46..bd10d3ba0949 100644 --- a/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/arch/cris/arch-v32/drivers/axisflashmap.c @@ -246,7 +246,7 @@ static struct mtd_info *probe_cs(struct map_info *map_cs) /* * Probe each chip select individually for flash chips. If there are chips on * both cse0 and cse1, the mtd_info structs will be concatenated to one struct - * so that MTD partitions can cross chip boundries. + * so that MTD partitions can cross chip boundaries. * * The only known restriction to how you can mount your chips is that each * chip select must hold similar flash chips. But you need external hardware diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index 617645d21b20..2081d8b45f06 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -525,7 +525,7 @@ static int setup_cipher_iv_desc(struct cryptocop_tfrm_ctx *tc, struct cryptocop_ return 0; } -/* Map the ouput length of the transform to operation output starting on the inject index. */ +/* Map the output length of the transform to operation output starting on the inject index. */ static int create_input_descriptors(struct cryptocop_operation *operation, struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag) { int err = 0; diff --git a/arch/cris/arch-v32/mach-a3/dram_init.S b/arch/cris/arch-v32/mach-a3/dram_init.S index ec8648be32d3..5c4f24dce94c 100644 --- a/arch/cris/arch-v32/mach-a3/dram_init.S +++ b/arch/cris/arch-v32/mach-a3/dram_init.S @@ -11,7 +11,7 @@ */ /* Just to be certain the config file is included, we include it here - * explicitely instead of depending on it being included in the file that + * explicitly instead of depending on it being included in the file that * uses this code. */ diff --git a/arch/cris/arch-v32/mach-fs/dram_init.S b/arch/cris/arch-v32/mach-fs/dram_init.S index 6fbad336527b..d3ce2eb04cb1 100644 --- a/arch/cris/arch-v32/mach-fs/dram_init.S +++ b/arch/cris/arch-v32/mach-fs/dram_init.S @@ -11,7 +11,7 @@ */ /* Just to be certain the config file is included, we include it here - * explicitely instead of depending on it being included in the file that + * explicitly instead of depending on it being included in the file that * uses this code. */ -- GitLab From bd1a0be5154788a052c6b851dbfa97bcd71f21d6 Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Wed, 24 Feb 2016 10:02:25 -0800 Subject: [PATCH 3192/9938] tools/perf: Fix misspellings in comments. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/util/evsel.c | 2 +- tools/perf/util/machine.c | 2 +- tools/perf/util/parse-events.c | 2 +- tools/perf/util/session.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 53c2273e8859..ad1cb63139a7 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -73,7 +73,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused) } /* - * Here we need to explicitely preallocate the counts, as if + * Here we need to explicitly preallocate the counts, as if * we use the auto allocation it will allocate just for 1 cpu, * as we start by cpu 0. */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 738ce226002b..846d633551b9 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -826,7 +826,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) perf_evsel__set_sample_bit(evsel, PERIOD); /* - * When the user explicitely disabled time don't force it here. + * When the user explicitly disabled time don't force it here. */ if (opts->sample_time && (!perf_missing_features.sample_id_all && diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 80b9b6a87990..2fa6d25b94bf 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -361,7 +361,7 @@ static void machine__update_thread_pid(struct machine *machine, } /* - * Caller must eventually drop thread->refcnt returned with a successfull + * Caller must eventually drop thread->refcnt returned with a successful * lookup/new thread inserted. */ static struct thread *____machine__findnew_thread(struct machine *machine, diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4c19d5e79d8c..696e8da4bcdf 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1649,7 +1649,7 @@ static void parse_events_print_error(struct parse_events_error *err, buf = _buf; - /* We're cutting from the beggining. */ + /* We're cutting from the beginning. */ if (err->idx > max_err_idx) cut = err->idx - max_err_idx; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 4abd85c6346d..9bd8d6c832b1 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -555,7 +555,7 @@ static u8 revbyte(u8 b) /* * XXX this is hack in attempt to carry flags bitfield - * throught endian village. ABI says: + * through endian village. ABI says: * * Bit-fields are allocated from right to left (least to most significant) * on little-endian implementations and from left to right (most to least -- GitLab From 238034e3fe3b0d75df0e4c7cbefb3df259ed628a Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Wed, 24 Feb 2016 10:49:53 -0800 Subject: [PATCH 3193/9938] hexagon: Fix misspellings in comments. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- arch/hexagon/include/asm/hexagon_vm.h | 2 +- arch/hexagon/include/asm/vm_mmu.h | 2 +- arch/hexagon/kernel/kgdb.c | 4 ++-- arch/hexagon/kernel/vm_ops.S | 2 +- arch/hexagon/lib/memcpy.S | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h index 1f6918b428de..e8990c9a6e99 100644 --- a/arch/hexagon/include/asm/hexagon_vm.h +++ b/arch/hexagon/include/asm/hexagon_vm.h @@ -237,7 +237,7 @@ static inline long __vmintop_clear(long i) /* * The initial program gets to find a system environment descriptor - * on its stack when it begins exection. The first word is a version + * on its stack when it begins execution. The first word is a version * code to indicate what is there. Zero means nothing more. */ diff --git a/arch/hexagon/include/asm/vm_mmu.h b/arch/hexagon/include/asm/vm_mmu.h index 096537d8f4c5..6fc29d9d570b 100644 --- a/arch/hexagon/include/asm/vm_mmu.h +++ b/arch/hexagon/include/asm/vm_mmu.h @@ -78,7 +78,7 @@ #define __HEXAGON_C_WB_L2 0x7 /* Write-back, with L2 */ /* - * This can be overriden, but we're defaulting to the most aggressive + * This can be overridden, but we're defaulting to the most aggressive * cache policy, the better to find bugs sooner. */ diff --git a/arch/hexagon/kernel/kgdb.c b/arch/hexagon/kernel/kgdb.c index 038580cc5abf..62dece3ad827 100644 --- a/arch/hexagon/kernel/kgdb.c +++ b/arch/hexagon/kernel/kgdb.c @@ -236,9 +236,9 @@ static struct notifier_block kgdb_notifier = { }; /** - * kgdb_arch_init - Perform any architecture specific initalization. + * kgdb_arch_init - Perform any architecture specific initialization. * - * This function will handle the initalization of any architecture + * This function will handle the initialization of any architecture * specific callbacks. */ int kgdb_arch_init(void) diff --git a/arch/hexagon/kernel/vm_ops.S b/arch/hexagon/kernel/vm_ops.S index 9fb77b3f6cf2..58f2b92a37ed 100644 --- a/arch/hexagon/kernel/vm_ops.S +++ b/arch/hexagon/kernel/vm_ops.S @@ -26,7 +26,7 @@ * could be, and perhaps some day will be, handled as in-line * macros, but for tracing/debugging it's handy to have * a single point of invocation for each of them. - * Conveniently, they take paramters and return values + * Conveniently, they take parameters and return values * consistent with the ABI calling convention. */ diff --git a/arch/hexagon/lib/memcpy.S b/arch/hexagon/lib/memcpy.S index 81c561c4b4d6..a46093a8800a 100644 --- a/arch/hexagon/lib/memcpy.S +++ b/arch/hexagon/lib/memcpy.S @@ -39,7 +39,7 @@ * DJH 10/14/09 Version 1.3 added special loop for aligned case, was * overreading bloated codesize back up to 892 * DJH 4/20/10 Version 1.4 fixed Ldword_loop_epilog loop to prevent loads - * occuring if only 1 left outstanding, fixes bug + * occurring if only 1 left outstanding, fixes bug * # 3888, corrected for all alignments. Peeled off * 1 32byte chunk from kernel loop and extended 8byte * loop at end to solve all combinations and prevent -- GitLab From 45b79a291fdd209cf40dfa40f91bf9e31f949b0d Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Wed, 24 Feb 2016 10:50:29 -0800 Subject: [PATCH 3194/9938] ia64: Fix misspellings in comments. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- arch/ia64/include/asm/sn/ioc3.h | 2 +- arch/ia64/include/asm/sn/shubio.h | 4 ++-- arch/ia64/kernel/efi.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/ia64/include/asm/sn/ioc3.h b/arch/ia64/include/asm/sn/ioc3.h index 95ed6cc83cf1..6eaa3cc1e919 100644 --- a/arch/ia64/include/asm/sn/ioc3.h +++ b/arch/ia64/include/asm/sn/ioc3.h @@ -131,7 +131,7 @@ struct ioc3 { #define SSCR_PAUSE_STATE 0x40000000 /* set when PAUSE takes effect*/ #define SSCR_RESET 0x80000000 /* reset DMA channels */ -/* all producer/comsumer pointers are the same bitfield */ +/* all producer/consumer pointers are the same bitfield */ #define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */ #define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */ #define PROD_CONS_PTR_OFF 3 diff --git a/arch/ia64/include/asm/sn/shubio.h b/arch/ia64/include/asm/sn/shubio.h index ecb8a49476b6..8a1ec139f977 100644 --- a/arch/ia64/include/asm/sn/shubio.h +++ b/arch/ia64/include/asm/sn/shubio.h @@ -1385,7 +1385,7 @@ typedef union ii_ibcr_u { * respones are captured until IXSS[VALID] is cleared by setting the * * appropriate bit in IECLR. Every time a spurious read response is * * detected, the SPUR_RD bit of the PRB corresponding to the incoming * - * message's SIDN field is set. This always happens, regarless of * + * message's SIDN field is set. This always happens, regardless of * * whether a header is captured. The programmer should check * * IXSM[SIDN] to determine which widget sent the spurious response, * * because there may be more than one SPUR_RD bit set in the PRB * @@ -2997,7 +2997,7 @@ typedef union ii_ippr_u { /* * Values for field imsgtype */ -#define IIO_ICRB_IMSGT_XTALK 0 /* Incoming Meessage from Xtalk */ +#define IIO_ICRB_IMSGT_XTALK 0 /* Incoming message from Xtalk */ #define IIO_ICRB_IMSGT_BTE 1 /* Incoming message from BTE */ #define IIO_ICRB_IMSGT_SN1NET 2 /* Incoming message from SN1 net */ #define IIO_ICRB_IMSGT_CRB 3 /* Incoming message from CRB ??? */ diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 300dac3702f1..a65740036824 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -966,7 +966,7 @@ efi_uart_console_only(void) /* * Look for the first granule aligned memory descriptor memory * that is big enough to hold EFI memory map. Make sure this - * descriptor is atleast granule sized so it does not get trimmed + * descriptor is at least granule sized so it does not get trimmed */ struct kern_memdesc * find_memmap_space (void) -- GitLab From cacd2c41c2349760e834f018951960da84332b56 Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Fri, 4 Mar 2016 11:20:54 -0800 Subject: [PATCH 3195/9938] metag: Fix misspellings in comments. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- arch/metag/include/asm/metag_regs.h | 2 +- arch/metag/include/asm/tbx.h | 6 +++--- arch/metag/tbx/tbipcx.S | 2 +- arch/metag/tbx/tbisoft.S | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/metag/include/asm/metag_regs.h b/arch/metag/include/asm/metag_regs.h index acf4b8e6e9d1..40c3f679c5b8 100644 --- a/arch/metag/include/asm/metag_regs.h +++ b/arch/metag/include/asm/metag_regs.h @@ -1165,7 +1165,7 @@ #define TXSTATUS_IPTOGGLE_BIT 0x80000000 /* Prev PToggle of TXPRIVEXT */ #define TXSTATUS_ISTATE_BIT 0x40000000 /* IState bit */ #define TXSTATUS_IWAIT_BIT 0x20000000 /* wait indefinitely in decision step*/ -#define TXSTATUS_IEXCEPT_BIT 0x10000000 /* Indicate an exception occured */ +#define TXSTATUS_IEXCEPT_BIT 0x10000000 /* Indicate an exception occurred */ #define TXSTATUS_IRPCOUNT_BITS 0x0E000000 /* Number of 'dirty' date entries*/ #define TXSTATUS_IRPCOUNT_S 25 #define TXSTATUS_IRQSTAT_BITS 0x0000F000 /* IRQEnc bits, trigger or interrupts */ diff --git a/arch/metag/include/asm/tbx.h b/arch/metag/include/asm/tbx.h index 703b9cb0ac5c..5cd2a6c86223 100644 --- a/arch/metag/include/asm/tbx.h +++ b/arch/metag/include/asm/tbx.h @@ -668,7 +668,7 @@ typedef union _tbires_tag_ { State.Sig.TrigMask will indicate the bits set within TXMASKI at the time of the handler call that have all been cleared to prevent - nested interrupt occuring immediately. + nested interrupt occurring immediately. State.Sig.SaveMask is a bit-mask which will be set to Zero when a trigger occurs at background level and TBICTX_CRIT_BIT and optionally @@ -1083,7 +1083,7 @@ TBIRES __TBINestInts( TBIRES State, void *pExt, int NoNestMask ); /* This routine causes the TBICTX structure specified in State.Sig.pCtx to be restored. This implies that execution will not return to the caller. The State.Sig.TrigMask field will be restored during the context switch - such that any immediately occuring interrupts occur in the context of the + such that any immediately occurring interrupts occur in the context of the newly specified task. The State.Sig.SaveMask parameter is ignored. */ void __TBIASyncResume( TBIRES State ); @@ -1305,7 +1305,7 @@ extern const char __TBISigNames[]; /* * Calculate linear PC value from real PC and Minim mode control, the LSB of - * the result returned indicates if address compression has occured. + * the result returned indicates if address compression has occurred. */ #ifndef __ASSEMBLY__ #define METAG_LINPC( PCVal ) (\ diff --git a/arch/metag/tbx/tbipcx.S b/arch/metag/tbx/tbipcx.S index de0626fdad25..163c79ac913b 100644 --- a/arch/metag/tbx/tbipcx.S +++ b/arch/metag/tbx/tbipcx.S @@ -15,7 +15,7 @@ #include /* BEGIN HACK */ -/* define these for now while doing inital conversion to GAS +/* define these for now while doing initial conversion to GAS will fix properly later */ /* Signal identifiers always have the TBID_SIGNAL_BIT set and contain the diff --git a/arch/metag/tbx/tbisoft.S b/arch/metag/tbx/tbisoft.S index 0346fe8a53b1..b04f50df8d91 100644 --- a/arch/metag/tbx/tbisoft.S +++ b/arch/metag/tbx/tbisoft.S @@ -56,7 +56,7 @@ ___TBIJumpX: /* * TBIRES __TBISwitch( TBIRES Switch, PTBICTX *rpSaveCtx ) * - * Software syncronous context switch between soft threads, save only the + * Software synchronous context switch between soft threads, save only the * registers which are actually valid on call entry. * * A0FrP, D0RtP, D0.5, D0.6, D0.7 - Saved on stack @@ -76,7 +76,7 @@ $LSwitchStart: SETL [A0StP+#8++],D0FrT,D1RtP /* * Save current frame state - we save all regs because we don't want - * uninitialised crap in the TBICTX structure that the asyncronous resumption + * uninitialised crap in the TBICTX structure that the asynchronous resumption * of a thread will restore. */ MOVT D1Re0,#HI($LSwitchExit) /* ASync resume point here */ @@ -117,7 +117,7 @@ $LSwitchExit: * This routine causes the TBICTX structure specified in State.Sig.pCtx to * be restored. This implies that execution will not return to the caller. * The State.Sig.TrigMask field will be ored into TXMASKI during the - * context switch such that any immediately occuring interrupts occur in + * context switch such that any immediately occurring interrupts occur in * the context of the newly specified task. The State.Sig.SaveMask parameter * is ignored. */ -- GitLab From 02dc8d634b4f175d92aa8b0b217eb0e4db1a0c3b Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Fri, 15 Apr 2016 10:37:58 -0700 Subject: [PATCH 3196/9938] crypto: qat - move vf2pf_init and vf2pf_exit to common The vf2pf_init and vf2pf_exit are exactly the same for all VFs so move them to common and reuse. Tested-by: Suman Bangalore Sathyanarayana Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- .../qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c | 23 ----- .../qat/qat_c62xvf/adf_c62xvf_hw_data.c | 23 ----- drivers/crypto/qat/qat_common/Makefile | 2 +- .../crypto/qat/qat_common/adf_common_drv.h | 12 +++ drivers/crypto/qat/qat_common/adf_vf2pf_msg.c | 90 +++++++++++++++++++ .../qat_dh895xccvf/adf_dh895xccvf_hw_data.c | 23 ----- 6 files changed, 103 insertions(+), 70 deletions(-) create mode 100644 drivers/crypto/qat/qat_common/adf_vf2pf_msg.c diff --git a/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c b/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c index 1af321c2ce1a..d2d0ae445fd8 100644 --- a/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c +++ b/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c @@ -109,29 +109,6 @@ static void adf_vf_void_noop(struct adf_accel_dev *accel_dev) { } -static int adf_vf2pf_init(struct adf_accel_dev *accel_dev) -{ - u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | - (ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT)); - - if (adf_iov_putmsg(accel_dev, msg, 0)) { - dev_err(&GET_DEV(accel_dev), - "Failed to send Init event to PF\n"); - return -EFAULT; - } - return 0; -} - -static void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev) -{ - u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | - (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT)); - - if (adf_iov_putmsg(accel_dev, msg, 0)) - dev_err(&GET_DEV(accel_dev), - "Failed to send Shutdown event to PF\n"); -} - void adf_init_hw_data_c3xxxiov(struct adf_hw_device_data *hw_data) { hw_data->dev_class = &c3xxxiov_class; diff --git a/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c b/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c index baf4b509c892..38e4bc04f407 100644 --- a/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c +++ b/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c @@ -109,29 +109,6 @@ static void adf_vf_void_noop(struct adf_accel_dev *accel_dev) { } -static int adf_vf2pf_init(struct adf_accel_dev *accel_dev) -{ - u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | - (ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT)); - - if (adf_iov_putmsg(accel_dev, msg, 0)) { - dev_err(&GET_DEV(accel_dev), - "Failed to send Init event to PF\n"); - return -EFAULT; - } - return 0; -} - -static void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev) -{ - u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | - (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT)); - - if (adf_iov_putmsg(accel_dev, msg, 0)) - dev_err(&GET_DEV(accel_dev), - "Failed to send Shutdown event to PF\n"); -} - void adf_init_hw_data_c62xiov(struct adf_hw_device_data *hw_data) { hw_data->dev_class = &c62xiov_class; diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile index 29c7c53d2845..5873d22fc6cd 100644 --- a/drivers/crypto/qat/qat_common/Makefile +++ b/drivers/crypto/qat/qat_common/Makefile @@ -27,4 +27,4 @@ intel_qat-objs := adf_cfg.o \ qat_hal.o intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o -intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_pf2vf_msg.o +intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_pf2vf_msg.o adf_vf2pf_msg.o diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index fd096eda880f..a8100a37ee0c 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -238,6 +238,9 @@ void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, uint32_t vf_mask); void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev); void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev); + +int adf_vf2pf_init(struct adf_accel_dev *accel_dev); +void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev); #else static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs) { @@ -255,5 +258,14 @@ static inline void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev) static inline void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev) { } + +static inline int adf_vf2pf_init(struct adf_accel_dev *accel_dev) +{ + return 0; +} + +static inline void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev) +{ +} #endif #endif diff --git a/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c b/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c new file mode 100644 index 000000000000..5f1d863ae802 --- /dev/null +++ b/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c @@ -0,0 +1,90 @@ +/* + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + Copyright(c) 2015 Intel Corporation. + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Contact Information: + qat-linux@intel.com + + BSD LICENSE + Copyright(c) 2015 Intel Corporation. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_pf2vf_msg.h" + +/** + * adf_vf2pf_init() - send init msg to PF + * @accel_dev: Pointer to acceleration VF device. + * + * Function sends an init messge from the VF to a PF + * + * Return: 0 on success, error code otherwise. + */ +int adf_vf2pf_init(struct adf_accel_dev *accel_dev) +{ + u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | + (ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT)); + + if (adf_iov_putmsg(accel_dev, msg, 0)) { + dev_err(&GET_DEV(accel_dev), + "Failed to send Init event to PF\n"); + return -EFAULT; + } + return 0; +} +EXPORT_SYMBOL_GPL(adf_vf2pf_init); + +/** + * adf_vf2pf_shutdown() - send shutdown msg to PF + * @accel_dev: Pointer to acceleration VF device. + * + * Function sends a shutdown messge from the VF to a PF + * + * Return: void + */ +void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev) +{ + u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | + (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT)); + + if (adf_iov_putmsg(accel_dev, msg, 0)) + dev_err(&GET_DEV(accel_dev), + "Failed to send Shutdown event to PF\n"); +} +EXPORT_SYMBOL_GPL(adf_vf2pf_shutdown); diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c b/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c index dc04ab68d24d..a3b4dd8099a7 100644 --- a/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c +++ b/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c @@ -109,29 +109,6 @@ static void adf_vf_void_noop(struct adf_accel_dev *accel_dev) { } -static int adf_vf2pf_init(struct adf_accel_dev *accel_dev) -{ - u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | - (ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT)); - - if (adf_iov_putmsg(accel_dev, msg, 0)) { - dev_err(&GET_DEV(accel_dev), - "Failed to send Init event to PF\n"); - return -EFAULT; - } - return 0; -} - -static void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev) -{ - u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | - (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT)); - - if (adf_iov_putmsg(accel_dev, msg, 0)) - dev_err(&GET_DEV(accel_dev), - "Failed to send Shutdown event to PF\n"); -} - void adf_init_hw_data_dh895xcciov(struct adf_hw_device_data *hw_data) { hw_data->dev_class = &dh895xcciov_class; -- GitLab From 25c6ffb249f612c56a48ce48a3887adf57b8f4bd Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Fri, 15 Apr 2016 10:37:59 -0700 Subject: [PATCH 3197/9938] crypto: qat - check if PF is running Before VF sends a signal to PF it should check if PF is still running. Tested-by: Suman Bangalore Sathyanarayana Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_c3xxxvf/adf_drv.c | 2 ++ drivers/crypto/qat/qat_c62xvf/adf_drv.c | 2 ++ drivers/crypto/qat/qat_common/adf_common_drv.h | 2 +- drivers/crypto/qat/qat_common/adf_vf2pf_msg.c | 8 +++++--- drivers/crypto/qat/qat_common/adf_vf_isr.c | 2 ++ drivers/crypto/qat/qat_dh895xccvf/adf_drv.c | 2 ++ 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c index a998981e9610..949d77b79fbe 100644 --- a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c +++ b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c @@ -238,6 +238,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_err_free_reg; + set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); + ret = adf_dev_init(accel_dev); if (ret) goto out_err_dev_shutdown; diff --git a/drivers/crypto/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/qat/qat_c62xvf/adf_drv.c index ccfb25e8a4a1..7540ce13b0d0 100644 --- a/drivers/crypto/qat/qat_c62xvf/adf_drv.c +++ b/drivers/crypto/qat/qat_c62xvf/adf_drv.c @@ -238,6 +238,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_err_free_reg; + set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); + ret = adf_dev_init(accel_dev); if (ret) goto out_err_dev_shutdown; diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index a8100a37ee0c..557ea361d385 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -67,7 +67,7 @@ #define ADF_STATUS_AE_INITIALISED 4 #define ADF_STATUS_AE_UCODE_LOADED 5 #define ADF_STATUS_AE_STARTED 6 -#define ADF_STATUS_ORPHAN_TH_RUNNING 7 +#define ADF_STATUS_PF_RUNNING 7 #define ADF_STATUS_IRQ_ALLOCATED 8 enum adf_dev_reset_mode { diff --git a/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c b/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c index 5f1d863ae802..cd5f37dffe8a 100644 --- a/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c +++ b/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c @@ -66,6 +66,7 @@ int adf_vf2pf_init(struct adf_accel_dev *accel_dev) "Failed to send Init event to PF\n"); return -EFAULT; } + set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); return 0; } EXPORT_SYMBOL_GPL(adf_vf2pf_init); @@ -83,8 +84,9 @@ void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev) u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT)); - if (adf_iov_putmsg(accel_dev, msg, 0)) - dev_err(&GET_DEV(accel_dev), - "Failed to send Shutdown event to PF\n"); + if (test_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status)) + if (adf_iov_putmsg(accel_dev, msg, 0)) + dev_err(&GET_DEV(accel_dev), + "Failed to send Shutdown event to PF\n"); } EXPORT_SYMBOL_GPL(adf_vf2pf_shutdown); diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c index c3d501681466..5d45796576ee 100644 --- a/drivers/crypto/qat/qat_common/adf_vf_isr.c +++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c @@ -135,6 +135,8 @@ static void adf_pf2vf_bh_handler(void *data) dev_dbg(&GET_DEV(accel_dev), "Restarting msg received from PF 0x%x\n", msg); + clear_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); + stop_data = kzalloc(sizeof(*stop_data), GFP_ATOMIC); if (!stop_data) { dev_err(&GET_DEV(accel_dev), diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c index 1bf753244230..60df98632fa2 100644 --- a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c +++ b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c @@ -238,6 +238,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_err_free_reg; + set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); + ret = adf_dev_init(accel_dev); if (ret) goto out_err_dev_shutdown; -- GitLab From 87ba569a398826733b14e77668c8d2630119b0ca Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Fri, 15 Apr 2016 10:38:00 -0700 Subject: [PATCH 3198/9938] crypto: qat - interrupts need to be enabled when VFs are disabled IRQs need to be enabled when VFs go down in case some VF to PF comms happens. Tested-by: Suman Bangalore Sathyanarayana Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/adf_init.c b/drivers/crypto/qat/qat_common/adf_init.c index a29470bc8539..888c6675e7e5 100644 --- a/drivers/crypto/qat/qat_common/adf_init.c +++ b/drivers/crypto/qat/qat_common/adf_init.c @@ -327,6 +327,8 @@ void adf_dev_shutdown(struct adf_accel_dev *accel_dev) clear_bit(accel_dev->accel_id, &service->init_status); } + hw_data->disable_iov(accel_dev); + if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) { hw_data->free_irq(accel_dev); clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status); @@ -342,7 +344,6 @@ void adf_dev_shutdown(struct adf_accel_dev *accel_dev) if (hw_data->exit_admin_comms) hw_data->exit_admin_comms(accel_dev); - hw_data->disable_iov(accel_dev); adf_cleanup_etr_data(accel_dev); adf_dev_restore(accel_dev); } -- GitLab From b3ab30a7cbdaf7ba20dddeac252cc0238312fff0 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Fri, 15 Apr 2016 10:54:07 -0700 Subject: [PATCH 3199/9938] crypto: qat - fix section mismatch warning Fix Section mismatch warinig in adf_exit_vf_wq() Reported-by: kbuild test robot Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_vf_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c index 5d45796576ee..aa689cabedb4 100644 --- a/drivers/crypto/qat/qat_common/adf_vf_isr.c +++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c @@ -326,7 +326,7 @@ int __init adf_init_vf_wq(void) return !adf_vf_stop_wq ? -EFAULT : 0; } -void __exit adf_exit_vf_wq(void) +void adf_exit_vf_wq(void) { if (adf_vf_stop_wq) destroy_workqueue(adf_vf_stop_wq); -- GitLab From bc2d52fe379b445b94cd7ce1de5a8ac4c13a9101 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:29:34 +0100 Subject: [PATCH 3200/9938] Blackfin: comment spelling s/divsor/divisor/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Jiri Kosina --- arch/blackfin/lib/udivsi3.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/lib/udivsi3.S b/arch/blackfin/lib/udivsi3.S index 748a6a2e8c17..90bfa809b392 100644 --- a/arch/blackfin/lib/udivsi3.S +++ b/arch/blackfin/lib/udivsi3.S @@ -154,7 +154,7 @@ ENTRY(___udivsi3) CC = R7 < 0; /* Check quotient(AQ) */ /* If AQ==0, we'll sub divisor */ IF CC R5 = R1; /* and if AQ==1, we'll add it. */ - R3 = R3 + R5; /* Add/sub divsor to partial remainder */ + R3 = R3 + R5; /* Add/sub divisor to partial remainder */ R7 = R3 ^ R1; /* Generate next quotient bit */ R5 = R7 >> 31; /* Get AQ */ -- GitLab From 0db71fec8560a7c58c04304fd2e10e9647a205d4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Mar 2016 16:31:37 +0100 Subject: [PATCH 3201/9938] w1: comment spelling s/minmum/minimum/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Jiri Kosina --- drivers/w1/w1_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 282092421cc9..f4bc8c100a01 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -352,7 +352,7 @@ int w1_reset_bus(struct w1_master *dev) w1_delay(70); result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1; - /* minmum 70 (above) + 430 = 500 us + /* minimum 70 (above) + 430 = 500 us * There aren't any timing requirements between a reset and * the following transactions. Sleeping is safe here. */ -- GitLab From 91540ccc9c4554c8bbb8b8a1be0b255a378b6475 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 17 Apr 2016 22:46:59 +0200 Subject: [PATCH 3202/9938] HID: thingm: factor out duplicated code to thingm_init_led Simplify thingm_init_rgb by factoring out duplicated code to thingm_init_led. Signed-off-by: Heiner Kallweit Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-thingm.c | 43 ++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c index 847a497cd472..a90463ecd75c 100644 --- a/drivers/hid/hid-thingm.c +++ b/drivers/hid/hid-thingm.c @@ -157,48 +157,35 @@ static int thingm_led_set(struct led_classdev *ldev, return ret; } +static int thingm_init_led(struct thingm_led *led, const char *color_name, + struct thingm_rgb *rgb, int minor) +{ + snprintf(led->name, sizeof(led->name), "thingm%d:%s:led%d", + minor, color_name, rgb->num); + led->ldev.name = led->name; + led->ldev.max_brightness = 255; + led->ldev.brightness_set_blocking = thingm_led_set; + led->rgb = rgb; + return devm_led_classdev_register(&rgb->tdev->hdev->dev, &led->ldev); +} + static int thingm_init_rgb(struct thingm_rgb *rgb) { const int minor = ((struct hidraw *) rgb->tdev->hdev->hidraw)->minor; int err; /* Register the red diode */ - snprintf(rgb->red.name, sizeof(rgb->red.name), - "thingm%d:red:led%d", minor, rgb->num); - rgb->red.ldev.name = rgb->red.name; - rgb->red.ldev.max_brightness = 255; - rgb->red.ldev.brightness_set_blocking = thingm_led_set; - rgb->red.rgb = rgb; - - err = devm_led_classdev_register(&rgb->tdev->hdev->dev, - &rgb->red.ldev); + err = thingm_init_led(&rgb->red, "red", rgb, minor); if (err) return err; /* Register the green diode */ - snprintf(rgb->green.name, sizeof(rgb->green.name), - "thingm%d:green:led%d", minor, rgb->num); - rgb->green.ldev.name = rgb->green.name; - rgb->green.ldev.max_brightness = 255; - rgb->green.ldev.brightness_set_blocking = thingm_led_set; - rgb->green.rgb = rgb; - - err = devm_led_classdev_register(&rgb->tdev->hdev->dev, - &rgb->green.ldev); + err = thingm_init_led(&rgb->green, "green", rgb, minor); if (err) return err; /* Register the blue diode */ - snprintf(rgb->blue.name, sizeof(rgb->blue.name), - "thingm%d:blue:led%d", minor, rgb->num); - rgb->blue.ldev.name = rgb->blue.name; - rgb->blue.ldev.max_brightness = 255; - rgb->blue.ldev.brightness_set_blocking = thingm_led_set; - rgb->blue.rgb = rgb; - - err = devm_led_classdev_register(&rgb->tdev->hdev->dev, - &rgb->blue.ldev); - return err; + return thingm_init_led(&rgb->blue, "blue", rgb, minor); } static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) -- GitLab From a4362fd6da7ab8b08028734004df486847ea593e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 17 Apr 2016 22:51:46 +0200 Subject: [PATCH 3203/9938] HID: thingm: set new flag LED_HW_PLUGGABLE Use recently introduced flag LED_HW_PLUGGABLE to avoid warnings when the device is unplugged. Signed-off-by: Heiner Kallweit Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-thingm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c index a90463ecd75c..2507bbe0eea7 100644 --- a/drivers/hid/hid-thingm.c +++ b/drivers/hid/hid-thingm.c @@ -165,6 +165,7 @@ static int thingm_init_led(struct thingm_led *led, const char *color_name, led->ldev.name = led->name; led->ldev.max_brightness = 255; led->ldev.brightness_set_blocking = thingm_led_set; + led->ldev.flags = LED_HW_PLUGGABLE; led->rgb = rgb; return devm_led_classdev_register(&rgb->tdev->hdev->dev, &led->ldev); } -- GitLab From 327819d1e52434de869aab2ee5183682357d8e6d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 18 Apr 2016 13:30:29 +0200 Subject: [PATCH 3204/9938] gpio: f7188x: fix edit mistake Fix a typo causing a build regression. Fixes: f90c6bdb690b ("gpio: f7188x: use the new open drain callback") Reported-by: Stephen Rothwell Signed-off-by: Linus Walleij --- drivers/gpio/gpio-f7188x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 58674ff75097..05aa538c3767 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -328,7 +328,7 @@ static int f7188x_gpio_set_single_ended(struct gpio_chip *chip, data &= ~BIT(offset); else data |= BIT(offset); - superio_outb(sio->addr, gpio_data_mode(bank->regbase), data); + superio_outb(sio->addr, gpio_out_mode(bank->regbase), data); superio_exit(sio->addr); return 0; -- GitLab From 4d7820b0465a78e6c85a74474b89fb4ab84768ba Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:28 +0530 Subject: [PATCH 3205/9938] ARM: dts: change SROM node compatible from generic to model specific This patch changes SROM nodes compatible from generic to model specific to match with binding documentation. Also updating property "samsung,srom-page-mode" as it is not defined as bool instead of int Signed-off-by: Pankaj Dubey Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4.dtsi | 4 ++-- arch/arm/boot/dts/exynos5.dtsi | 4 ++-- arch/arm/boot/dts/exynos5410-smdk5410.dts | 2 +- arch/arm/boot/dts/exynos5410.dtsi | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index c679b3cc3c48..d68f572fc7e6 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -77,8 +77,8 @@ reg = <0x10000000 0x100>; }; - sromc@12570000 { - compatible = "samsung,exynos-srom"; + memory-controller@12570000 { + compatible = "samsung,exynos4210-srom"; reg = <0x12570000 0x14>; }; diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi index 92313cac035e..d5c0f18a4223 100644 --- a/arch/arm/boot/dts/exynos5.dtsi +++ b/arch/arm/boot/dts/exynos5.dtsi @@ -31,8 +31,8 @@ reg = <0x10000000 0x100>; }; - sromc@12250000 { - compatible = "samsung,exynos-srom"; + memory-controller@12250000 { + compatible = "samsung,exynos4210-srom"; reg = <0x12250000 0x14>; }; diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts index a731fbe28ebc..0f6429e1b75c 100644 --- a/arch/arm/boot/dts/exynos5410-smdk5410.dts +++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts @@ -97,7 +97,7 @@ smsc,irq-push-pull; smsc,force-internal-phy; - samsung,srom-page-mode = <1>; + samsung,srom-page-mode; samsung,srom-timing = <9 12 1 9 1 1>; }; }; diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi index fa558674ac76..7a56aec2c5ba 100644 --- a/arch/arm/boot/dts/exynos5410.dtsi +++ b/arch/arm/boot/dts/exynos5410.dtsi @@ -102,8 +102,8 @@ reg = <0x10000000 0x100>; }; - sromc: sromc@12250000 { - compatible = "samsung,exynos-srom"; + sromc: memory-controller@12250000 { + compatible = "samsung,exynos4210-srom"; reg = <0x12250000 0x14>; #address-cells = <2>; #size-cells = <1>; -- GitLab From dea520a4a28307034b1842adbfde947e1ed385d2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 30 Mar 2016 09:39:34 +0300 Subject: [PATCH 3206/9938] usb: dwc3: gadget: pass ev_buff as cookie to irq handler we don't plan on using multiple event buffers, but if we find a good use case for it, this little trick will help us avoid a loop in hardirq handler looping for each and every event buffer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 96dfde011c76..93b96fffe0e4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1536,7 +1536,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, irq = platform_get_irq(to_platform_device(dwc->dev), 0); ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, - IRQF_SHARED, "dwc3", dwc); + IRQF_SHARED, "dwc3", dwc->ev_buf); if (ret) { dev_err(dwc->dev, "failed to request irq #%d --> %d\n", irq, ret); @@ -1636,7 +1636,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, err1: spin_unlock_irqrestore(&dwc->lock, flags); - free_irq(irq, dwc); + free_irq(irq, dwc->ev_buf); err0: return ret; @@ -1659,7 +1659,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g) spin_unlock_irqrestore(&dwc->lock, flags); irq = platform_get_irq(to_platform_device(dwc->dev), 0); - free_irq(irq, dwc); + free_irq(irq, dwc->ev_buf); return 0; } @@ -2602,14 +2602,13 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, } } -static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc) +static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt) { - struct dwc3_event_buffer *evt; + struct dwc3 *dwc = evt->dwc; irqreturn_t ret = IRQ_NONE; int left; u32 reg; - evt = dwc->ev_buf; left = evt->count; if (!(evt->flags & DWC3_EVENT_PENDING)) @@ -2649,27 +2648,26 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc) return ret; } -static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) +static irqreturn_t dwc3_thread_interrupt(int irq, void *_evt) { - struct dwc3 *dwc = _dwc; + struct dwc3_event_buffer *evt = _evt; + struct dwc3 *dwc = evt->dwc; unsigned long flags; irqreturn_t ret = IRQ_NONE; spin_lock_irqsave(&dwc->lock, flags); - ret = dwc3_process_event_buf(dwc); + ret = dwc3_process_event_buf(evt); spin_unlock_irqrestore(&dwc->lock, flags); return ret; } -static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) +static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) { - struct dwc3_event_buffer *evt; + struct dwc3 *dwc = evt->dwc; u32 count; u32 reg; - evt = dwc->ev_buf; - count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; if (!count) @@ -2686,11 +2684,11 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) return IRQ_WAKE_THREAD; } -static irqreturn_t dwc3_interrupt(int irq, void *_dwc) +static irqreturn_t dwc3_interrupt(int irq, void *_evt) { - struct dwc3 *dwc = _dwc; + struct dwc3_event_buffer *evt = _evt; - return dwc3_check_event_buf(dwc); + return dwc3_check_event_buf(evt); } /** -- GitLab From badf6d47f8a93098c6e05fdeb735b44b61877451 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 23 Mar 2016 17:45:08 +0100 Subject: [PATCH 3207/9938] usb: common: rework CONFIG_USB_COMMON logic The phy-am335x driver selects 'USB_COMMON', but all other drivers use 'depends on' for that symbol, and it depends on USB || USB_GADGET itself, which causes a Kconfig warning: warning: (AM335X_PHY_USB) selects USB_COMMON which has unmet direct dependencies (USB_SUPPORT && (USB || USB_GADGET)) As suggested by Felipe Balbi, this turns the logic around, and makes 'USB_COMMON' selected by everything else that needs it, so we can remove the dependencies. Fixes: 59f042f644c5 ("usb: phy: phy-am335x: bypass first VBUS sensing for host-only mode") Signed-off-by: Arnd Bergmann Acked-by: Felipe Balbi Reviewed-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/phy/Kconfig | 3 ++- drivers/usb/Kconfig | 3 +-- drivers/usb/gadget/Kconfig | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 26566db09de0..e92b97cd6056 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -250,7 +250,8 @@ config PHY_SUN9I_USB tristate "Allwinner sun9i SoC USB PHY driver" depends on ARCH_SUNXI && HAS_IOMEM && OF depends on RESET_CONTROLLER - depends on USB_COMMON + depends on USB_SUPPORT + select USB_COMMON select GENERIC_PHY help Enable this to support the transceiver that is part of Allwinner diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 8ed451dd651e..8689dcba5201 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -31,8 +31,6 @@ if USB_SUPPORT config USB_COMMON tristate - default y - depends on USB || USB_GADGET config USB_ARCH_HAS_HCD def_bool y @@ -41,6 +39,7 @@ config USB_ARCH_HAS_HCD config USB tristate "Support for Host-side USB" depends on USB_ARCH_HAS_HCD + select USB_COMMON select NLS # for UTF-8 strings ---help--- Universal Serial Bus (USB) is a specification for a serial bus diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index af5d922a8f5d..2057add439f0 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -15,6 +15,7 @@ menuconfig USB_GADGET tristate "USB Gadget Support" + select USB_COMMON select NLS help USB is a master/slave protocol, organized with one master -- GitLab From 5e3bd45f170b43cec3fb85f14ef94f176235c4af Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:55:34 +0200 Subject: [PATCH 3208/9938] usb: gadged: pch_udc: PCI core handles power state for us There is no need to repeat the work that is already done in the PCI driver core. The patch removes excerpts from suspend and resume callbacks. Note that there is no more calls performed to enable or disable a PCI device during suspend-resume cycle. Nowadays they seems to be superfluous. Someone can read more in [1]. While here, convert PM ops to use modern API. [1] https://www.kernel.org/doc/ols/2009/ols2009-pages-319-330.pdf Signed-off-by: Andy Shevchenko [felipe.balbi@linux.intel.com: fixed build break and checkpatch error ] Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 39 ++++++++++---------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 9571ef54b86b..58fc0adacd79 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -3096,44 +3096,28 @@ static void pch_udc_remove(struct pci_dev *pdev) kfree(dev); } -#ifdef CONFIG_PM -static int pch_udc_suspend(struct pci_dev *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int pch_udc_suspend(struct device *d) { + struct pci_dev *pdev = to_pci_dev(d); struct pch_udc_dev *dev = pci_get_drvdata(pdev); pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK); pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL); - pci_disable_device(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - - if (pci_save_state(pdev)) { - dev_err(&pdev->dev, - "%s: could not save PCI config state\n", __func__); - return -ENOMEM; - } - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } -static int pch_udc_resume(struct pci_dev *pdev) +static int pch_udc_resume(struct device *d) { - int ret; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__); - return ret; - } - pci_enable_wake(pdev, PCI_D3hot, 0); return 0; } + +static SIMPLE_DEV_PM_OPS(pch_udc_pm, pch_udc_suspend, pch_udc_resume); +#define PCH_UDC_PM_OPS (&pch_udc_pm) #else -#define pch_udc_suspend NULL -#define pch_udc_resume NULL -#endif /* CONFIG_PM */ +#define PCH_UDC_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ static int pch_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -3262,9 +3246,10 @@ static struct pci_driver pch_udc_driver = { .id_table = pch_udc_pcidev_id, .probe = pch_udc_probe, .remove = pch_udc_remove, - .suspend = pch_udc_suspend, - .resume = pch_udc_resume, .shutdown = pch_udc_shutdown, + .driver = { + .pm = PCH_UDC_PM_OPS, + }, }; module_pci_driver(pch_udc_driver); -- GitLab From 969733f3768528ce7fb435e90adcb5f7984316ec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:55:35 +0200 Subject: [PATCH 3209/9938] usb: gadget: pch_udc: convert to devres API devres API allows to make error paths cleaner and less error prone. Convert the driver to use it. Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 98 +++++++++----------------------- 1 file changed, 26 insertions(+), 72 deletions(-) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 58fc0adacd79..82e01f8995c5 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -325,11 +325,8 @@ struct pch_vbus_gpio_data { * @pdev: reference to the PCI device * @ep: array of endpoints * @lock: protects all state - * @active: enabled the PCI device * @stall: stall requested * @prot_stall: protcol stall requested - * @irq_registered: irq registered with system - * @mem_region: device memory mapped * @registered: driver registered with system * @suspended: driver in suspended state * @connected: gadget driver associated @@ -339,12 +336,8 @@ struct pch_vbus_gpio_data { * @data_requests: DMA pool for data requests * @stp_requests: DMA pool for setup requests * @dma_addr: DMA pool for received - * @ep0out_buf: Buffer for DMA * @setup_data: Received setup data - * @phys_addr: of device memory * @base_addr: for mapped device memory - * @bar: Indicates which PCI BAR for USB regs - * @irq: IRQ line for the device * @cfg_data: current cfg, intf, and alt in use * @vbus_gpio: GPIO informaton for detecting VBUS */ @@ -354,11 +347,9 @@ struct pch_udc_dev { struct pci_dev *pdev; struct pch_udc_ep ep[PCH_UDC_EP_NUM]; spinlock_t lock; /* protects all state */ - unsigned active:1, + unsigned stall:1, prot_stall:1, - irq_registered:1, - mem_region:1, suspended:1, connected:1, vbus_session:1, @@ -367,12 +358,8 @@ struct pch_udc_dev { struct pci_pool *data_requests; struct pci_pool *stp_requests; dma_addr_t dma_addr; - void *ep0out_buf; struct usb_ctrlrequest setup_data; - unsigned long phys_addr; void __iomem *base_addr; - unsigned bar; - unsigned irq; struct pch_udc_cfg_data cfg_data; struct pch_vbus_gpio_data vbus_gpio; }; @@ -2949,6 +2936,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) { struct pch_udc_stp_dma_desc *td_stp; struct pch_udc_data_dma_desc *td_data; + void *ep0out_buf; /* DMA setup */ dev->data_requests = pci_pool_create("data_requests", dev->pdev, @@ -2991,10 +2979,11 @@ static int init_dma_pools(struct pch_udc_dev *dev) dev->ep[UDC_EP0IN_IDX].td_data = NULL; dev->ep[UDC_EP0IN_IDX].td_data_phys = 0; - dev->ep0out_buf = kzalloc(UDC_EP0OUT_BUFF_SIZE * 4, GFP_KERNEL); - if (!dev->ep0out_buf) + ep0out_buf = devm_kzalloc(&dev->pdev->dev, UDC_EP0OUT_BUFF_SIZE * 4, + GFP_KERNEL); + if (!ep0out_buf) return -ENOMEM; - dev->dma_addr = dma_map_single(&dev->pdev->dev, dev->ep0out_buf, + dev->dma_addr = dma_map_single(&dev->pdev->dev, ep0out_buf, UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); return 0; @@ -3078,22 +3067,10 @@ static void pch_udc_remove(struct pci_dev *pdev) if (dev->dma_addr) dma_unmap_single(&dev->pdev->dev, dev->dma_addr, UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); - kfree(dev->ep0out_buf); pch_vbus_gpio_free(dev); pch_udc_exit(dev); - - if (dev->irq_registered) - free_irq(pdev->irq, dev); - if (dev->base_addr) - iounmap(dev->base_addr); - if (dev->mem_region) - release_mem_region(dev->phys_addr, - pci_resource_len(pdev, dev->bar)); - if (dev->active) - pci_disable_device(pdev); - kfree(dev); } #ifdef CONFIG_PM_SLEEP @@ -3122,69 +3099,46 @@ static SIMPLE_DEV_PM_OPS(pch_udc_pm, pch_udc_suspend, pch_udc_resume); static int pch_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - unsigned long resource; - unsigned long len; + int bar; int retval; struct pch_udc_dev *dev; /* init */ - dev = kzalloc(sizeof *dev, GFP_KERNEL); - if (!dev) { - pr_err("%s: no memory for device structure\n", __func__); + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) return -ENOMEM; - } + /* pci setup */ - if (pci_enable_device(pdev) < 0) { - kfree(dev); - pr_err("%s: pci_enable_device failed\n", __func__); - return -ENODEV; - } - dev->active = 1; + retval = pcim_enable_device(pdev); + if (retval) + return retval; + pci_set_drvdata(pdev, dev); /* Determine BAR based on PCI ID */ if (id->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC) - dev->bar = PCH_UDC_PCI_BAR_QUARK_X1000; + bar = PCH_UDC_PCI_BAR_QUARK_X1000; else - dev->bar = PCH_UDC_PCI_BAR; + bar = PCH_UDC_PCI_BAR; /* PCI resource allocation */ - resource = pci_resource_start(pdev, dev->bar); - len = pci_resource_len(pdev, dev->bar); + retval = pcim_iomap_regions(pdev, 1 << bar, pci_name(pdev)); + if (retval) + return retval; - if (!request_mem_region(resource, len, KBUILD_MODNAME)) { - dev_err(&pdev->dev, "%s: pci device used already\n", __func__); - retval = -EBUSY; - goto finished; - } - dev->phys_addr = resource; - dev->mem_region = 1; + dev->base_addr = pcim_iomap_table(pdev)[bar]; - dev->base_addr = ioremap_nocache(resource, len); - if (!dev->base_addr) { - pr_err("%s: device memory cannot be mapped\n", __func__); - retval = -ENOMEM; - goto finished; - } - if (!pdev->irq) { - dev_err(&pdev->dev, "%s: irq not set\n", __func__); - retval = -ENODEV; - goto finished; - } /* initialize the hardware */ - if (pch_udc_pcd_init(dev)) { - retval = -ENODEV; - goto finished; - } - if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME, - dev)) { + if (pch_udc_pcd_init(dev)) + return -ENODEV; + + retval = devm_request_irq(&pdev->dev, pdev->irq, pch_udc_isr, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (retval) { dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__, pdev->irq); - retval = -ENODEV; goto finished; } - dev->irq = pdev->irq; - dev->irq_registered = 1; pci_set_master(pdev); pci_try_set_mwi(pdev); -- GitLab From c7b640d2a21c2dd724cd8aa9f0b78d6a3d61d776 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:55:36 +0200 Subject: [PATCH 3210/9938] usb: gadget: pch_udc: enable MSI if hardware supports Try to enable MSI in case hardware supports it. At least Intel Quark is known SoC which indeed does. Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 82e01f8995c5..787f459e9e90 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -3132,6 +3132,8 @@ static int pch_udc_probe(struct pci_dev *pdev, if (pch_udc_pcd_init(dev)) return -ENODEV; + pci_enable_msi(pdev); + retval = devm_request_irq(&pdev->dev, pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME, dev); if (retval) { -- GitLab From 6b968737c3efe7cdaa5407afec972cd7c7d3ca35 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:55:37 +0200 Subject: [PATCH 3211/9938] usb: gadged: pch_udc: get rid of redundant assignments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems there are leftovers of some assignments which are not used anymore. Compiler even warns us about: drivers/usb/gadget/udc/pch_udc.c:2022:22: warning: variable ‘dev’ set \ but not used [-Wunused-but-set-variable] drivers/usb/gadget/udc/pch_udc.c:2639:9: warning: variable ‘ret’ set \ but not used [-Wunused-but-set-variable] Remove them and shut compiler about. Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 787f459e9e90..d6d1418bdd63 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -1719,14 +1719,12 @@ static int pch_udc_pcd_ep_enable(struct usb_ep *usbep, static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) { struct pch_udc_ep *ep; - struct pch_udc_dev *dev; unsigned long iflags; if (!usbep) return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); - dev = ep->dev; if ((usbep->name == ep0_string) || !ep->ep.desc) return -EINVAL; @@ -1757,12 +1755,10 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep, struct pch_udc_request *req; struct pch_udc_ep *ep; struct pch_udc_data_dma_desc *dma_desc; - struct pch_udc_dev *dev; if (!usbep) return NULL; ep = container_of(usbep, struct pch_udc_ep, ep); - dev = ep->dev; req = kzalloc(sizeof *req, gfp); if (!req) return NULL; @@ -1935,12 +1931,10 @@ static int pch_udc_pcd_dequeue(struct usb_ep *usbep, { struct pch_udc_ep *ep; struct pch_udc_request *req; - struct pch_udc_dev *dev; unsigned long flags; int ret = -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); - dev = ep->dev; if (!usbep || !usbreq || (!ep->ep.desc && ep->num)) return ret; req = container_of(usbreq, struct pch_udc_request, req); @@ -1972,14 +1966,12 @@ static int pch_udc_pcd_dequeue(struct usb_ep *usbep, static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt) { struct pch_udc_ep *ep; - struct pch_udc_dev *dev; unsigned long iflags; int ret; if (!usbep) return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); - dev = ep->dev; if (!ep->ep.desc && !ep->num) return -EINVAL; if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN)) @@ -2017,14 +2009,12 @@ static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt) static int pch_udc_pcd_set_wedge(struct usb_ep *usbep) { struct pch_udc_ep *ep; - struct pch_udc_dev *dev; unsigned long iflags; int ret; if (!usbep) return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); - dev = ep->dev; if (!ep->ep.desc && !ep->num) return -EINVAL; if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN)) @@ -2634,7 +2624,7 @@ static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev) static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) { u32 reg, dev_stat = 0; - int i, ret; + int i; dev_stat = pch_udc_read_device_status(dev); dev->cfg_data.cur_intf = (dev_stat & UDC_DEVSTS_INTF_MASK) >> @@ -2663,7 +2653,7 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) } dev->stall = 0; spin_lock(&dev->lock); - ret = dev->driver->setup(&dev->gadget, &dev->setup_data); + dev->driver->setup(&dev->gadget, &dev->setup_data); spin_unlock(&dev->lock); } @@ -2674,7 +2664,7 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) */ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) { - int i, ret; + int i; u32 reg, dev_stat = 0; dev_stat = pch_udc_read_device_status(dev); @@ -2700,7 +2690,7 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) /* call gadget zero with setup data received */ spin_lock(&dev->lock); - ret = dev->driver->setup(&dev->gadget, &dev->setup_data); + dev->driver->setup(&dev->gadget, &dev->setup_data); spin_unlock(&dev->lock); } -- GitLab From e4875bd4829c1a945bc4714ca806a823a169f3a1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Mar 2016 16:55:38 +0200 Subject: [PATCH 3212/9938] usb: gadget: pch_udc: sort IDs Sort IDs in groups to be easily found when needed. There is no functional change. Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index d6d1418bdd63..b2b70d4e2f5b 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -367,8 +367,10 @@ struct pch_udc_dev { #define PCH_UDC_PCI_BAR_QUARK_X1000 0 #define PCH_UDC_PCI_BAR 1 -#define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808 + #define PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC 0x0939 +#define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808 + #define PCI_VENDOR_ID_ROHM 0x10DB #define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D #define PCI_DEVICE_ID_ML7831_IOH_UDC 0x8808 -- GitLab From c0ca324d09a041ab56be1aaeb5a7cc64c47f877b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Apr 2016 09:11:51 +0300 Subject: [PATCH 3213/9938] usb: dwc3: gadget: combine return points into a single one dwc3_send_gadget_ep_cmd() had three return points. That becomes a pain to track when we need to debug something or if we need to add more code before returning. Let's combine all three return points into a single one just by introducing a local 'ret' variable. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 93b96fffe0e4..eb760b275004 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -227,6 +227,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, struct dwc3_ep *dep = dwc->eps[ep]; u32 timeout = 500; u32 reg; + int ret = -EINVAL; trace_dwc3_gadget_ep_cmd(dep, cmd, params); @@ -242,8 +243,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, "Command Complete --> %d", DWC3_DEPCMD_STATUS(reg)); if (DWC3_DEPCMD_STATUS(reg)) - return -EINVAL; - return 0; + break; + ret = 0; + break; } /* @@ -254,11 +256,14 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, if (!timeout) { dwc3_trace(trace_dwc3_gadget, "Command Timed Out"); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + break; } udelay(1); } while (1); + + return ret; } static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, -- GitLab From 2b0f11df84bb66c9ac71395382c018f33c3ff9a4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Apr 2016 09:19:17 +0300 Subject: [PATCH 3214/9938] usb: dwc3: gadget: clear SUSPHY bit before ep cmds Synopsys Databook 2.60a has a note that if we're sending an endpoint command we _must_ make sure that DWC3_GUSB2PHY(n).SUSPHY bit is cleared. This patch implements that particular detail. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index eb760b275004..79aad1061cdc 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -227,10 +227,27 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, struct dwc3_ep *dep = dwc->eps[ep]; u32 timeout = 500; u32 reg; + + int susphy = false; int ret = -EINVAL; trace_dwc3_gadget_ep_cmd(dep, cmd, params); + /* + * Synopsys Databook 2.60a states, on section 6.3.2.5.[1-8], that if + * we're issuing an endpoint command, we must check if + * GUSB2PHYCFG.SUSPHY bit is set. If it is, then we need to clear it. + * + * We will also set SUSPHY bit to what it was before returning as stated + * by the same section on Synopsys databook. + */ + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { + susphy = true; + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + } + dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0); dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1); dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2); @@ -263,6 +280,12 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, udelay(1); } while (1); + if (unlikely(susphy)) { + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg |= DWC3_GUSB2PHYCFG_SUSPHY; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + } + return ret; } -- GitLab From 218ef7b647e3367c9f81e18f63fbb0066f10b9a5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Apr 2016 11:24:04 +0300 Subject: [PATCH 3215/9938] usb: dwc3: gadget: extract unlocked dwc3_gadget_wakeup() we will need this from StartTransfer to make sure link is in U0 before starting a transfer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 79aad1061cdc..2cc2c1545f49 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1361,22 +1361,16 @@ static int dwc3_gadget_get_frame(struct usb_gadget *g) return DWC3_DSTS_SOFFN(reg); } -static int dwc3_gadget_wakeup(struct usb_gadget *g) +static int __dwc3_gadget_wakeup(struct dwc3 *dwc) { - struct dwc3 *dwc = gadget_to_dwc(g); - unsigned long timeout; - unsigned long flags; + int ret; u32 reg; - int ret = 0; - u8 link_state; u8 speed; - spin_lock_irqsave(&dwc->lock, flags); - /* * According to the Databook Remote wakeup request should * be issued only when the device is in early suspend state. @@ -1389,8 +1383,7 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) if ((speed == DWC3_DSTS_SUPERSPEED) || (speed == DWC3_DSTS_SUPERSPEED_PLUS)) { dwc3_trace(trace_dwc3_gadget, "no wakeup on SuperSpeed\n"); - ret = -EINVAL; - goto out; + return -EINVAL; } link_state = DWC3_DSTS_USBLNKST(reg); @@ -1403,14 +1396,13 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) dwc3_trace(trace_dwc3_gadget, "can't wakeup from '%s'\n", dwc3_gadget_link_string(link_state)); - ret = -EINVAL; - goto out; + return -EINVAL; } ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); if (ret < 0) { dev_err(dwc->dev, "failed to put link in Recovery\n"); - goto out; + return ret; } /* Recent versions do this automatically */ @@ -1434,10 +1426,20 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { dev_err(dwc->dev, "failed to send remote wakeup\n"); - ret = -EINVAL; + return -EINVAL; } -out: + return 0; +} + +static int dwc3_gadget_wakeup(struct usb_gadget *g) +{ + struct dwc3 *dwc = gadget_to_dwc(g); + unsigned long flags; + int ret; + + spin_lock_irqsave(&dwc->lock, flags); + ret = __dwc3_gadget_wakeup(dwc); spin_unlock_irqrestore(&dwc->lock, flags); return ret; -- GitLab From c36d8e947a56a6e6478fc48152c5f4626462db55 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Apr 2016 12:46:33 +0300 Subject: [PATCH 3216/9938] usb: dwc3: gadget: put link to U0 before Start Transfer Synopsys Databook says we should move link to U0 before issuing a Start Transfer command. We could require the gadget driver to call usb_gadget_wakeup() however I feel that changing all gadget drivers to keep track of Link State and conditionally call usb_gadget_wakeup() would be far too much work. For now we will handle this at the UDC level, but at some point composite.c should be one handling this. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2cc2c1545f49..0e271584e4cf 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -221,6 +221,8 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param) } while (1); } +static int __dwc3_gadget_wakeup(struct dwc3 *dwc); + int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, unsigned cmd, struct dwc3_gadget_ep_cmd_params *params) { @@ -248,6 +250,20 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); } + if (cmd == DWC3_DEPCMD_STARTTRANSFER) { + int needs_wakeup; + + needs_wakeup = (dwc->link_state == DWC3_LINK_STATE_U1 || + dwc->link_state == DWC3_LINK_STATE_U2 || + dwc->link_state == DWC3_LINK_STATE_U3); + + if (unlikely(needs_wakeup)) { + ret = __dwc3_gadget_wakeup(dwc); + dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n", + ret); + } + } + dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0); dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1); dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2); -- GitLab From 2c0b98ff29a7452edbbdc503857b74cfaa536808 Mon Sep 17 00:00:00 2001 From: Rajesh Bhagat Date: Mon, 14 Mar 2016 14:40:51 +0530 Subject: [PATCH 3217/9938] Documentation: dt: dwc3: Add snps,dis_rxdet_inp3_quirk property Add snps,dis_rxdet_inp3_quirk property which disables receiver detection in PHY P3 power state. Signed-off-by: Sriram Dash Signed-off-by: Rajesh Bhagat Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/dwc3.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 15695682a480..7d7ce089b003 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -37,6 +37,8 @@ Optional properties: - snps,dis_u2_susphy_quirk: when set core will disable USB2 suspend phy. - snps,dis_enblslpm_quirk: when set clears the enblslpm in GUSB2PHYCFG, disabling the suspend signal to the PHY. + - snps,dis_rxdet_inp3_quirk: when set core will disable receiver detection + in PHY P3 power state. - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal utmi_l1_suspend_n, false when asserts utmi_sleep_n - snps,hird-threshold: HIRD threshold -- GitLab From e58dd357741b93f5bc5487aabba968c76bb099ef Mon Sep 17 00:00:00 2001 From: Rajesh Bhagat Date: Mon, 14 Mar 2016 14:40:50 +0530 Subject: [PATCH 3218/9938] usb: dwc3: add disable receiver detection in P3 quirk Some freescale QorIQ platforms require to disable receiver detection in P3 for correct detection of USB devices. If GUSB3PIPECTL(DISRXDETINP3) is set, Core will change PHY power state to P2 and then perform receiver detection. After receiver detection, Core will change PHY power state to P3. Same quirk would be added in dts file in future patches. Signed-off-by: Sriram Dash Signed-off-by: Rajesh Bhagat Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 6 ++++++ drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/platform_data.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 05b7ec30266f..940489c1d1bd 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -412,6 +412,9 @@ static int dwc3_phy_setup(struct dwc3 *dwc) if (dwc->u2ss_inp3_quirk) reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; + if (dwc->dis_rxdet_inp3_quirk) + reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; + if (dwc->req_p1p2p3_quirk) reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; @@ -882,6 +885,8 @@ static int dwc3_probe(struct platform_device *pdev) "snps,dis_u2_susphy_quirk"); dwc->dis_enblslpm_quirk = device_property_read_bool(dev, "snps,dis_enblslpm_quirk"); + dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, + "snps,dis_rxdet_inp3_quirk"); dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, "snps,tx_de_emphasis_quirk"); @@ -915,6 +920,7 @@ static int dwc3_probe(struct platform_device *pdev) dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk; + dwc->dis_rxdet_inp3_quirk = pdata->dis_rxdet_inp3_quirk; dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; if (pdata->tx_de_emphasis) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index df72234a805b..f965e961b40e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -193,6 +193,7 @@ /* Global USB3 PIPE Control Register */ #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) #define DWC3_GUSB3PIPECTL_U2SSINP3OK (1 << 29) +#define DWC3_GUSB3PIPECTL_DISRXDETINP3 (1 << 28) #define DWC3_GUSB3PIPECTL_REQP1P2P3 (1 << 24) #define DWC3_GUSB3PIPECTL_DEP1P2P3(n) ((n) << 19) #define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK DWC3_GUSB3PIPECTL_DEP1P2P3(7) @@ -867,6 +868,7 @@ struct dwc3 { unsigned dis_u3_susphy_quirk:1; unsigned dis_u2_susphy_quirk:1; unsigned dis_enblslpm_quirk:1; + unsigned dis_rxdet_inp3_quirk:1; unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h index aaa6f00df755..8826cca5fc6f 100644 --- a/drivers/usb/dwc3/platform_data.h +++ b/drivers/usb/dwc3/platform_data.h @@ -42,6 +42,7 @@ struct dwc3_platform_data { unsigned dis_u3_susphy_quirk:1; unsigned dis_u2_susphy_quirk:1; unsigned dis_enblslpm_quirk:1; + unsigned dis_rxdet_inp3_quirk:1; unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; -- GitLab From 495dd5f78145c44274eeb8ec297195ac71a8fed0 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 5 Apr 2016 15:09:44 +0300 Subject: [PATCH 3219/9938] usb: dwc3: omap: drop dma_mask configuration The DWC3 OMAP driver supports DT-boot only, as result dma_mask will be always configured properly from DT - of_platform_device_create_pdata()->of_dma_configure(). More over, dwc3-omap.c can be built as module and in this case it's unsafe to assign local variable as dma_mask. Hence, remove dma_mask configuration code. Signed-off-by: Grygorii Strashko Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 22e9606d8e08..e92a992c2255 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -331,8 +331,6 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) dwc3_omap_write_irqmisc_clr(omap, reg); } -static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); - static int dwc3_omap_id_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -490,7 +488,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) omap->irq = irq; omap->base = base; omap->vbus_reg = vbus_reg; - dev->dma_mask = &dwc3_omap_dma_mask; pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); -- GitLab From 53fd88189e08c91cb9b43e2d51b4eb314a3d00d7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Apr 2016 15:33:41 +0300 Subject: [PATCH 3220/9938] usb: dwc3: gadget: rename busy/free_slot to trb_enqueue/dequeue This makes it clear that we're dealing with a queue of TRBs. No functional changes. While at that, also rename start_slot to first_trb_index for similar reasons. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 10 +++++----- drivers/usb/dwc3/ep0.c | 6 +++--- drivers/usb/dwc3/gadget.c | 30 +++++++++++++++--------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index f965e961b40e..a29d797bfcf4 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -449,8 +449,8 @@ struct dwc3_event_buffer { * @started_list: list of started requests on this endpoint * @trb_pool: array of transaction buffers * @trb_pool_dma: dma address of @trb_pool - * @free_slot: next slot which is going to be used - * @busy_slot: first slot which is owned by HW + * @trb_enqueue: enqueue 'pointer' into TRB array + * @trb_dequeue: dequeue 'pointer' into TRB array * @desc: usb_endpoint_descriptor pointer * @dwc: pointer to DWC controller * @saved_state: ep state saved during hibernation @@ -470,8 +470,8 @@ struct dwc3_ep { struct dwc3_trb *trb_pool; dma_addr_t trb_pool_dma; - u32 free_slot; - u32 busy_slot; + u32 trb_enqueue; + u32 trb_dequeue; const struct usb_ss_ep_comp_descriptor *comp_desc; struct dwc3 *dwc; @@ -628,7 +628,7 @@ struct dwc3_request { struct usb_request request; struct list_head list; struct dwc3_ep *dep; - u32 start_slot; + u32 first_trb_index; u8 epnum; struct dwc3_trb *trb; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 5e0a21b65053..143deb420481 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -70,10 +70,10 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, return 0; } - trb = &dwc->ep0_trb[dep->free_slot]; + trb = &dwc->ep0_trb[dep->trb_enqueue]; if (chain) - dep->free_slot++; + dep->trb_enqueue++; trb->bpl = lower_32_bits(buf_dma); trb->bph = upper_32_bits(buf_dma); @@ -845,7 +845,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, trb++; length = trb->size & DWC3_TRB_SIZE_MASK; - ep0->free_slot = 0; + ep0->trb_enqueue = 0; } transfer_size = roundup((ur->length - transfer_size), diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0e271584e4cf..bb29f4f08f5d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -154,16 +154,16 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->started) { i = 0; do { - dep->busy_slot++; + dep->trb_dequeue++; /* * Skip LINK TRB. We can't use req->trb and check for * DWC3_TRBCTL_LINK_TRB because it points the TRB we * just completed (not the LINK TRB). */ - if (((dep->busy_slot & DWC3_TRB_MASK) == + if (((dep->trb_dequeue & DWC3_TRB_MASK) == DWC3_TRB_NUM- 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) - dep->busy_slot++; + dep->trb_dequeue++; } while(++i < req->request.num_mapped_sgs); req->started = false; } @@ -741,20 +741,20 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, chain ? " chain" : ""); - trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; + trb = &dep->trb_pool[dep->trb_enqueue & DWC3_TRB_MASK]; if (!req->trb) { dwc3_gadget_move_started_request(req); req->trb = trb; req->trb_dma = dwc3_trb_dma_offset(dep, trb); - req->start_slot = dep->free_slot & DWC3_TRB_MASK; + req->first_trb_index = dep->trb_enqueue & DWC3_TRB_MASK; } - dep->free_slot++; + dep->trb_enqueue++; /* Skip the LINK-TRB on ISOC */ - if (((dep->free_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && + if (((dep->trb_enqueue & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) - dep->free_slot++; + dep->trb_enqueue++; trb->size = DWC3_TRB_SIZE_LENGTH(length); trb->bpl = lower_32_bits(dma); @@ -826,11 +826,11 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); /* the first request must not be queued */ - trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; + trbs_left = (dep->trb_dequeue - dep->trb_enqueue) & DWC3_TRB_MASK; /* Can't wrap around on a non-isoc EP since there's no link TRB */ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK); + max = DWC3_TRB_NUM - (dep->trb_enqueue & DWC3_TRB_MASK); if (trbs_left > max) trbs_left = max; } @@ -856,11 +856,11 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) * don't wrap around we have to start at the beginning. */ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - dep->busy_slot = 1; - dep->free_slot = 1; + dep->trb_dequeue = 1; + dep->trb_enqueue = 1; } else { - dep->busy_slot = 0; - dep->free_slot = 0; + dep->trb_dequeue = 0; + dep->trb_enqueue = 0; } } @@ -1931,7 +1931,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, i = 0; do { - slot = req->start_slot + i; + slot = req->first_trb_index + i; if ((slot == DWC3_TRB_NUM - 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) slot++; -- GitLab From 5ef68c56e169a9249b94645a9ea9ca8d14672d26 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Apr 2016 11:33:30 +0300 Subject: [PATCH 3221/9938] usb: dwc3: core: document struct dwc3_request No functional changes. Merely adding useful documentation for future readers. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index a29d797bfcf4..c0049c811cca 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -624,6 +624,19 @@ struct dwc3_hwparams { /* HWPARAMS7 */ #define DWC3_RAM1_DEPTH(n) ((n) & 0xffff) +/** + * struct dwc3_request - representation of a transfer request + * @request: struct usb_request to be transferred + * @list: a list_head used for request queueing + * @dep: struct dwc3_ep owning this request + * @first_trb_index: index to first trb used by this request + * @epnum: endpoint number to which this request refers + * @trb: pointer to struct dwc3_trb + * @trb_dma: DMA address of @trb + * @direction: IN or OUT direction flag + * @mapped: true when request has been dma-mapped + * @queued: true when request has been queued to HW + */ struct dwc3_request { struct usb_request request; struct list_head list; -- GitLab From c28f82595dde97dda0b769f78f0faea78acd993b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Apr 2016 12:42:15 +0300 Subject: [PATCH 3222/9938] usb: dwc3: switch trb enqueue/dequeue and first_trb_index to u8 We *know* that we have 1 PAGE (4096 bytes) for our TRB poll. We also know the size of each TRB and know that we can fit 256 of them in one PAGE. By using a u8 type we can make sure that: enqueue++ % 256; gets optimized to an increment only. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c0049c811cca..2f19573e08d9 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -470,8 +470,6 @@ struct dwc3_ep { struct dwc3_trb *trb_pool; dma_addr_t trb_pool_dma; - u32 trb_enqueue; - u32 trb_dequeue; const struct usb_ss_ep_comp_descriptor *comp_desc; struct dwc3 *dwc; @@ -487,6 +485,18 @@ struct dwc3_ep { /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN (1 << 31) + /* + * IMPORTANT: we *know* we have 256 TRBs in our @trb_pool, so we will + * use a u8 type here. If anybody decides to increase number of TRBs to + * anything larger than 256 - I can't see why people would want to do + * this though - then this type needs to be changed. + * + * By using u8 types we ensure that our % operator when incrementing + * enqueue and dequeue get optimized away by the compiler. + */ + u8 trb_enqueue; + u8 trb_dequeue; + u8 number; u8 type; u8 resource_index; @@ -641,8 +651,8 @@ struct dwc3_request { struct usb_request request; struct list_head list; struct dwc3_ep *dep; - u32 first_trb_index; + u8 first_trb_index; u8 epnum; struct dwc3_trb *trb; dma_addr_t trb_dma; -- GitLab From 92537d65d58ede86d752d1390cf3b51480ab0179 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:23 +0530 Subject: [PATCH 3223/9938] dt-bindings: EXYNOS: Add exynos-srom device tree binding This patch adds exynos-srom binding information for SROM Controller driver on Exynos SoCs. Documentation for new subnode properties, allowing bank configuration are added based on u-boot implementation, but heavily reworked. CC: Rob Herring CC: Mark Rutland CC: Ian Campbell Signed-off-by: Pankaj Dubey [p.fedin: Added SROMc configuration description and fixed SROMc mapping] Signed-off-by: Pavel Fedin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kukjin Kim Signed-off-by: Krzysztof Kozlowski --- .../memory-controllers/exynos-srom.txt | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt new file mode 100644 index 000000000000..f633b5d0f8ca --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt @@ -0,0 +1,79 @@ +SAMSUNG Exynos SoCs SROM Controller driver. + +Required properties: +- compatible : Should contain "samsung,exynos4210-srom". + +- reg: offset and length of the register set + +Optional properties: +The SROM controller can be used to attach external peripherals. In this case +extra properties, describing the bus behind it, should be specified as below: + +- #address-cells: Must be set to 2 to allow device address translation. + Address is specified as (bank#, offset). + +- #size-cells: Must be set to 1 to allow device size passing + +- ranges: Must be set up to reflect the memory layout with four integer values + per bank: + 0 + +Sub-nodes: +The actual device nodes should be added as subnodes to the SROMc node. These +subnodes, in addition to regular device specification, should contain the following +properties, describing configuration of the relevant SROM bank: + +Required properties: +- reg: bank number, base address (relative to start of the bank) and size of + the memory mapped for the device. Note that base address will be + typically 0 as this is the start of the bank. + +- samsung,srom-timing : array of 6 integers, specifying bank timings in the + following order: Tacp, Tcah, Tcoh, Tacc, Tcos, Tacs. + Each value is specified in cycles and has the following + meaning and valid range: + Tacp : Page mode access cycle at Page mode (0 - 15) + Tcah : Address holding time after CSn (0 - 15) + Tcoh : Chip selection hold on OEn (0 - 15) + Tacc : Access cycle (0 - 31, the actual time is N + 1) + Tcos : Chip selection set-up before OEn (0 - 15) + Tacs : Address set-up before CSn (0 - 15) + +Optional properties: +- reg-io-width : data width in bytes (1 or 2). If omitted, default of 1 is used. + +- samsung,srom-page-mode : if page mode is set, 4 data page mode will be configured, + else normal (1 data) page mode will be set. + +Example: basic definition, no banks are configured + memory-controller@12570000 { + compatible = "samsung,exynos4210-srom"; + reg = <0x12570000 0x14>; + }; + +Example: SROMc with SMSC911x ethernet chip on bank 3 + memory-controller@12570000 { + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x04000000 0x20000 // Bank0 + 1 0 0x05000000 0x20000 // Bank1 + 2 0 0x06000000 0x20000 // Bank2 + 3 0 0x07000000 0x20000>; // Bank3 + + compatible = "samsung,exynos4210-srom"; + reg = <0x12570000 0x14>; + + ethernet@3,0 { + compatible = "smsc,lan9115"; + reg = <3 0 0x10000>; // Bank 3, offset = 0 + phy-mode = "mii"; + interrupt-parent = <&gpx0>; + interrupts = <5 8>; + reg-io-width = <2>; + smsc,irq-push-pull; + smsc,force-internal-phy; + + samsung,srom-page-mode; + samsung,srom-timing = <9 12 1 9 1 1>; + }; + }; -- GitLab From a8aabb91dc5bef0875d93d6a86d01779947604e1 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:24 +0530 Subject: [PATCH 3224/9938] memory: Add support for Exynos SROM driver This patch adds Exynos SROM controller driver which will handle save restore of SROM registers during S2R. Signed-off-by: Pankaj Dubey Reviewed-by: Krzysztof Kozlowski [p.fedin@samsung.com: tested on SMDK5410] Tested-by: Pavel Fedin Signed-off-by: Kukjin Kim [k.kozlowski: Minor COMPILE_TEST adjustments in Kconfig entries] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 1 + drivers/memory/Makefile | 1 + drivers/memory/samsung/Kconfig | 13 ++ drivers/memory/samsung/Makefile | 1 + drivers/memory/samsung/exynos-srom.c | 175 +++++++++++++++++++++++++++ drivers/memory/samsung/exynos-srom.h | 51 ++++++++ 6 files changed, 242 insertions(+) create mode 100644 drivers/memory/samsung/Kconfig create mode 100644 drivers/memory/samsung/Makefile create mode 100644 drivers/memory/samsung/exynos-srom.c create mode 100644 drivers/memory/samsung/exynos-srom.h diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 51d5cd20c26a..c61a284133e0 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -122,6 +122,7 @@ config MTK_SMI mainly help enable/disable iommu and control the power domain and clocks for each local arbiter. +source "drivers/memory/samsung/Kconfig" source "drivers/memory/tegra/Kconfig" endif diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 890bdf402449..cb0b7a1df11a 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -17,4 +17,5 @@ obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o obj-$(CONFIG_MTK_SMI) += mtk-smi.o +obj-$(CONFIG_SAMSUNG_MC) += samsung/ obj-$(CONFIG_TEGRA_MC) += tegra/ diff --git a/drivers/memory/samsung/Kconfig b/drivers/memory/samsung/Kconfig new file mode 100644 index 000000000000..64ab5dd9f626 --- /dev/null +++ b/drivers/memory/samsung/Kconfig @@ -0,0 +1,13 @@ +config SAMSUNG_MC + bool "Samsung Exynos Memory Controller support" if COMPILE_TEST + help + Support for the Memory Controller (MC) devices found on + Samsung Exynos SoCs. + +if SAMSUNG_MC + +config EXYNOS_SROM + bool "Exynos SROM controller driver" if COMPILE_TEST + depends on (ARM && ARCH_EXYNOS && PM) || (COMPILE_TEST && HAS_IOMEM) + +endif diff --git a/drivers/memory/samsung/Makefile b/drivers/memory/samsung/Makefile new file mode 100644 index 000000000000..9c554d5522ad --- /dev/null +++ b/drivers/memory/samsung/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_EXYNOS_SROM) += exynos-srom.o diff --git a/drivers/memory/samsung/exynos-srom.c b/drivers/memory/samsung/exynos-srom.c new file mode 100644 index 000000000000..68e073c1651c --- /dev/null +++ b/drivers/memory/samsung/exynos-srom.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * EXYNOS - SROM Controller support + * Author: Pankaj Dubey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include "exynos-srom.h" + +static const unsigned long exynos_srom_offsets[] = { + /* SROM side */ + EXYNOS_SROM_BW, + EXYNOS_SROM_BC0, + EXYNOS_SROM_BC1, + EXYNOS_SROM_BC2, + EXYNOS_SROM_BC3, +}; + +/** + * struct exynos_srom_reg_dump: register dump of SROM Controller registers. + * @offset: srom register offset from the controller base address. + * @value: the value of register under the offset. + */ +struct exynos_srom_reg_dump { + u32 offset; + u32 value; +}; + +/** + * struct exynos_srom: platform data for exynos srom controller driver. + * @dev: platform device pointer + * @reg_base: srom base address + * @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value. + */ +struct exynos_srom { + struct device *dev; + void __iomem *reg_base; + struct exynos_srom_reg_dump *reg_offset; +}; + +static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump( + const unsigned long *rdump, + unsigned long nr_rdump) +{ + struct exynos_srom_reg_dump *rd; + unsigned int i; + + rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL); + if (!rd) + return NULL; + + for (i = 0; i < nr_rdump; ++i) + rd[i].offset = rdump[i]; + + return rd; +} + +static int exynos_srom_probe(struct platform_device *pdev) +{ + struct device_node *np; + struct exynos_srom *srom; + struct device *dev = &pdev->dev; + + np = dev->of_node; + if (!np) { + dev_err(&pdev->dev, "could not find device info\n"); + return -EINVAL; + } + + srom = devm_kzalloc(&pdev->dev, + sizeof(struct exynos_srom), GFP_KERNEL); + if (!srom) + return -ENOMEM; + + srom->dev = dev; + srom->reg_base = of_iomap(np, 0); + if (!srom->reg_base) { + dev_err(&pdev->dev, "iomap of exynos srom controller failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, srom); + + srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets, + sizeof(exynos_srom_offsets)); + if (!srom->reg_offset) { + iounmap(srom->reg_base); + return -ENOMEM; + } + + return 0; +} + +static int exynos_srom_remove(struct platform_device *pdev) +{ + struct exynos_srom *srom = platform_get_drvdata(pdev); + + kfree(srom->reg_offset); + iounmap(srom->reg_base); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static void exynos_srom_save(void __iomem *base, + struct exynos_srom_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + rd->value = readl(base + rd->offset); +} + +static void exynos_srom_restore(void __iomem *base, + const struct exynos_srom_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + writel(rd->value, base + rd->offset); +} + +static int exynos_srom_suspend(struct device *dev) +{ + struct exynos_srom *srom = dev_get_drvdata(dev); + + exynos_srom_save(srom->reg_base, srom->reg_offset, + ARRAY_SIZE(exynos_srom_offsets)); + return 0; +} + +static int exynos_srom_resume(struct device *dev) +{ + struct exynos_srom *srom = dev_get_drvdata(dev); + + exynos_srom_restore(srom->reg_base, srom->reg_offset, + ARRAY_SIZE(exynos_srom_offsets)); + return 0; +} +#endif + +static const struct of_device_id of_exynos_srom_ids[] = { + { + .compatible = "samsung,exynos4210-srom", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_exynos_srom_ids); + +static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume); + +static struct platform_driver exynos_srom_driver = { + .probe = exynos_srom_probe, + .remove = exynos_srom_remove, + .driver = { + .name = "exynos-srom", + .of_match_table = of_exynos_srom_ids, + .pm = &exynos_srom_pm_ops, + }, +}; +module_platform_driver(exynos_srom_driver); + +MODULE_AUTHOR("Pankaj Dubey "); +MODULE_DESCRIPTION("Exynos SROM Controller Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/memory/samsung/exynos-srom.h b/drivers/memory/samsung/exynos-srom.h new file mode 100644 index 000000000000..34660c6a57a9 --- /dev/null +++ b/drivers/memory/samsung/exynos-srom.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Exynos SROMC register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __EXYNOS_SROM_H +#define __EXYNOS_SROM_H __FILE__ + +#define EXYNOS_SROMREG(x) (x) + +#define EXYNOS_SROM_BW EXYNOS_SROMREG(0x0) +#define EXYNOS_SROM_BC0 EXYNOS_SROMREG(0x4) +#define EXYNOS_SROM_BC1 EXYNOS_SROMREG(0x8) +#define EXYNOS_SROM_BC2 EXYNOS_SROMREG(0xc) +#define EXYNOS_SROM_BC3 EXYNOS_SROMREG(0x10) +#define EXYNOS_SROM_BC4 EXYNOS_SROMREG(0x14) +#define EXYNOS_SROM_BC5 EXYNOS_SROMREG(0x18) + +/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */ + +#define EXYNOS_SROM_BW__DATAWIDTH__SHIFT 0 +#define EXYNOS_SROM_BW__ADDRMODE__SHIFT 1 +#define EXYNOS_SROM_BW__WAITENABLE__SHIFT 2 +#define EXYNOS_SROM_BW__BYTEENABLE__SHIFT 3 + +#define EXYNOS_SROM_BW__CS_MASK 0xf + +#define EXYNOS_SROM_BW__NCS0__SHIFT 0 +#define EXYNOS_SROM_BW__NCS1__SHIFT 4 +#define EXYNOS_SROM_BW__NCS2__SHIFT 8 +#define EXYNOS_SROM_BW__NCS3__SHIFT 12 +#define EXYNOS_SROM_BW__NCS4__SHIFT 16 +#define EXYNOS_SROM_BW__NCS5__SHIFT 20 + +/* applies to same to BCS0 - BCS3 */ + +#define EXYNOS_SROM_BCX__PMC__SHIFT 0 +#define EXYNOS_SROM_BCX__TACP__SHIFT 4 +#define EXYNOS_SROM_BCX__TCAH__SHIFT 8 +#define EXYNOS_SROM_BCX__TCOH__SHIFT 12 +#define EXYNOS_SROM_BCX__TACC__SHIFT 16 +#define EXYNOS_SROM_BCX__TCOS__SHIFT 24 +#define EXYNOS_SROM_BCX__TACS__SHIFT 28 + +#endif /* __EXYNOS_SROM_H */ -- GitLab From ffd51977beb3909c4626bab41cc5f405b308fcb2 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:25 +0530 Subject: [PATCH 3225/9938] MAINTAINERS: Add maintainers entry for drivers/memory/samsung Add maintainers entry for new driver folder drivers/memory/samsung. Signed-off-by: Pankaj Dubey Signed-off-by: Krzysztof Kozlowski --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..0d2a26437936 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1540,6 +1540,7 @@ F: arch/arm/mach-s5p*/ F: arch/arm/mach-exynos*/ F: drivers/*/*s3c2410* F: drivers/*/*/*s3c2410* +F: drivers/memory/samsung/* F: drivers/soc/samsung/* F: drivers/spi/spi-s3c* F: sound/soc/samsung/* -- GitLab From 5901f4c279f7ddbd32041ce1166387ffa05b902d Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:26 +0530 Subject: [PATCH 3226/9938] ARM: EXYNOS: Remove SROM related register settings from mach-exynos As now we have dedicated driver for SROM controller, it will take care of saving register banks during S2R so we can safely remove these settings from mach-exynos. Signed-off-by: Pankaj Dubey Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kukjin Kim [k.kozlowski: Need to select also SAMSUNG_MC] Signed-off-by: Krzysztof Kozlowski --- arch/arm/mach-exynos/Kconfig | 3 ++ arch/arm/mach-exynos/exynos.c | 17 ------- arch/arm/mach-exynos/include/mach/map.h | 3 -- arch/arm/mach-exynos/regs-srom.h | 53 -------------------- arch/arm/mach-exynos/suspend.c | 20 +------- arch/arm/plat-samsung/include/plat/map-s5p.h | 1 - 6 files changed, 5 insertions(+), 92 deletions(-) delete mode 100644 arch/arm/mach-exynos/regs-srom.h diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 207fa2c737a6..28f992886d67 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -18,6 +18,7 @@ menuconfig ARCH_EXYNOS select COMMON_CLK_SAMSUNG select EXYNOS_THERMAL select EXYNOS_PMU + select EXYNOS_SROM if PM select HAVE_ARM_SCU if SMP select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG @@ -26,11 +27,13 @@ menuconfig ARCH_EXYNOS select PINCTRL_EXYNOS select PM_GENERIC_DOMAINS if PM select S5P_DEV_MFC + select SAMSUNG_MC select SOC_SAMSUNG select SRAM select THERMAL select THERMAL_OF select MFD_SYSCON + select MEMORY select CLKSRC_EXYNOS_MCT select POWER_RESET select POWER_RESET_SYSCON diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index bbf51a46f772..f977eea1c496 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -31,11 +31,6 @@ static struct map_desc exynos4_iodesc[] __initdata = { { - .virtual = (unsigned long)S5P_VA_SROMC, - .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC), - .length = SZ_4K, - .type = MT_DEVICE, - }, { .virtual = (unsigned long)S5P_VA_CMU, .pfn = __phys_to_pfn(EXYNOS4_PA_CMU), .length = SZ_128K, @@ -58,15 +53,6 @@ static struct map_desc exynos4_iodesc[] __initdata = { }, }; -static struct map_desc exynos5_iodesc[] __initdata = { - { - .virtual = (unsigned long)S5P_VA_SROMC, - .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; - static struct platform_device exynos_cpuidle = { .name = "exynos_cpuidle", #ifdef CONFIG_ARM_EXYNOS_CPUIDLE @@ -138,9 +124,6 @@ static void __init exynos_map_io(void) { if (soc_is_exynos4()) iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); - - if (soc_is_exynos5()) - iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc)); } static void __init exynos_init_io(void) diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index c88325d56743..c48ba4fbdfd2 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -25,7 +25,4 @@ #define EXYNOS4_PA_COREPERI 0x10500000 -#define EXYNOS4_PA_SROMC 0x12570000 -#define EXYNOS5_PA_SROMC 0x12250000 - #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-exynos/regs-srom.h b/arch/arm/mach-exynos/regs-srom.h deleted file mode 100644 index 5c4d4427db7b..000000000000 --- a/arch/arm/mach-exynos/regs-srom.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * S5P SROMC register definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __PLAT_SAMSUNG_REGS_SROM_H -#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__ - -#include - -#define S5P_SROMREG(x) (S5P_VA_SROMC + (x)) - -#define S5P_SROM_BW S5P_SROMREG(0x0) -#define S5P_SROM_BC0 S5P_SROMREG(0x4) -#define S5P_SROM_BC1 S5P_SROMREG(0x8) -#define S5P_SROM_BC2 S5P_SROMREG(0xc) -#define S5P_SROM_BC3 S5P_SROMREG(0x10) -#define S5P_SROM_BC4 S5P_SROMREG(0x14) -#define S5P_SROM_BC5 S5P_SROMREG(0x18) - -/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */ - -#define S5P_SROM_BW__DATAWIDTH__SHIFT 0 -#define S5P_SROM_BW__ADDRMODE__SHIFT 1 -#define S5P_SROM_BW__WAITENABLE__SHIFT 2 -#define S5P_SROM_BW__BYTEENABLE__SHIFT 3 - -#define S5P_SROM_BW__CS_MASK 0xf - -#define S5P_SROM_BW__NCS0__SHIFT 0 -#define S5P_SROM_BW__NCS1__SHIFT 4 -#define S5P_SROM_BW__NCS2__SHIFT 8 -#define S5P_SROM_BW__NCS3__SHIFT 12 -#define S5P_SROM_BW__NCS4__SHIFT 16 -#define S5P_SROM_BW__NCS5__SHIFT 20 - -/* applies to same to BCS0 - BCS3 */ - -#define S5P_SROM_BCX__PMC__SHIFT 0 -#define S5P_SROM_BCX__TACP__SHIFT 4 -#define S5P_SROM_BCX__TCAH__SHIFT 8 -#define S5P_SROM_BCX__TCOH__SHIFT 12 -#define S5P_SROM_BCX__TACC__SHIFT 16 -#define S5P_SROM_BCX__TCOS__SHIFT 24 -#define S5P_SROM_BCX__TACS__SHIFT 28 - -#endif /* __PLAT_SAMSUNG_REGS_SROM_H */ diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index fee2b003e662..f21690937b7d 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -34,10 +34,11 @@ #include #include +#include + #include #include "common.h" -#include "regs-srom.h" #define REG_TABLE_END (-1U) @@ -53,15 +54,6 @@ struct exynos_wkup_irq { u32 mask; }; -static struct sleep_save exynos_core_save[] = { - /* SROM side */ - SAVE_ITEM(S5P_SROM_BW), - SAVE_ITEM(S5P_SROM_BC0), - SAVE_ITEM(S5P_SROM_BC1), - SAVE_ITEM(S5P_SROM_BC2), - SAVE_ITEM(S5P_SROM_BC3), -}; - struct exynos_pm_data { const struct exynos_wkup_irq *wkup_irq; unsigned int wake_disable_mask; @@ -343,8 +335,6 @@ static void exynos_pm_prepare(void) /* Set wake-up mask registers */ exynos_pm_set_wakeup_mask(); - s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - exynos_pm_enter_sleep_mode(); /* ensure at least INFORM0 has the resume address */ @@ -375,8 +365,6 @@ static void exynos5420_pm_prepare(void) /* Set wake-up mask registers */ exynos_pm_set_wakeup_mask(); - s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3); /* * The cpu state needs to be saved and restored so that the @@ -467,8 +455,6 @@ static void exynos_pm_resume(void) /* For release retention */ exynos_pm_release_retention(); - s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - if (cpuid == ARM_CPU_PART_CORTEX_A9) scu_enable(S5P_VA_SCU); @@ -535,8 +521,6 @@ static void exynos5420_pm_resume(void) pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3); - s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - early_wakeup: tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h index 4ec9a7050185..b63aeebb93f3 100644 --- a/arch/arm/plat-samsung/include/plat/map-s5p.h +++ b/arch/arm/plat-samsung/include/plat/map-s5p.h @@ -18,7 +18,6 @@ #define S5P_VA_DMC0 S3C_ADDR(0x02440000) #define S5P_VA_DMC1 S3C_ADDR(0x02480000) -#define S5P_VA_SROMC S3C_ADDR(0x024C0000) #define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000) #define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) -- GitLab From 8ac2266d88318d348fa5f1dad5b525e0d2c665ef Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Mon, 11 Apr 2016 13:12:27 +0530 Subject: [PATCH 3227/9938] memory: samsung: exynos-srom: Add support for bank configuration Implement handling properties in subnodes and adding child devices to the system. Child devices will not be added if configuration fails. Since the driver now does more than suspend-resume support, dependency on CONFIG_PM is removed. Signed-off-by: Pavel Fedin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Pankaj Dubey Signed-off-by: Krzysztof Kozlowski --- arch/arm/mach-exynos/Kconfig | 2 +- drivers/memory/samsung/Kconfig | 2 +- drivers/memory/samsung/exynos-srom.c | 60 +++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 28f992886d67..e65aa7d11b20 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -18,7 +18,7 @@ menuconfig ARCH_EXYNOS select COMMON_CLK_SAMSUNG select EXYNOS_THERMAL select EXYNOS_PMU - select EXYNOS_SROM if PM + select EXYNOS_SROM select HAVE_ARM_SCU if SMP select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG diff --git a/drivers/memory/samsung/Kconfig b/drivers/memory/samsung/Kconfig index 64ab5dd9f626..9de12222061c 100644 --- a/drivers/memory/samsung/Kconfig +++ b/drivers/memory/samsung/Kconfig @@ -8,6 +8,6 @@ if SAMSUNG_MC config EXYNOS_SROM bool "Exynos SROM controller driver" if COMPILE_TEST - depends on (ARM && ARCH_EXYNOS && PM) || (COMPILE_TEST && HAS_IOMEM) + depends on (ARM && ARCH_EXYNOS) || (COMPILE_TEST && HAS_IOMEM) endif diff --git a/drivers/memory/samsung/exynos-srom.c b/drivers/memory/samsung/exynos-srom.c index 68e073c1651c..96756fb4d6bd 100644 --- a/drivers/memory/samsung/exynos-srom.c +++ b/drivers/memory/samsung/exynos-srom.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -67,11 +68,50 @@ static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump( return rd; } +static int exynos_srom_configure_bank(struct exynos_srom *srom, + struct device_node *np) +{ + u32 bank, width, pmc = 0; + u32 timing[6]; + u32 cs, bw; + + if (of_property_read_u32(np, "reg", &bank)) + return -EINVAL; + if (of_property_read_u32(np, "reg-io-width", &width)) + width = 1; + if (of_property_read_bool(np, "samsung,srom-page-mode")) + pmc = 1 << EXYNOS_SROM_BCX__PMC__SHIFT; + if (of_property_read_u32_array(np, "samsung,srom-timing", timing, + ARRAY_SIZE(timing))) + return -EINVAL; + + bank *= 4; /* Convert bank into shift/offset */ + + cs = 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT; + if (width == 2) + cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT; + + bw = __raw_readl(srom->reg_base + EXYNOS_SROM_BW); + bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank); + __raw_writel(bw, srom->reg_base + EXYNOS_SROM_BW); + + __raw_writel(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) | + (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) | + (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) | + (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) | + (timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) | + (timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT), + srom->reg_base + EXYNOS_SROM_BC0 + bank); + + return 0; +} + static int exynos_srom_probe(struct platform_device *pdev) { - struct device_node *np; + struct device_node *np, *child; struct exynos_srom *srom; struct device *dev = &pdev->dev; + bool bad_bank_config = false; np = dev->of_node; if (!np) { @@ -100,7 +140,23 @@ static int exynos_srom_probe(struct platform_device *pdev) return -ENOMEM; } - return 0; + for_each_child_of_node(np, child) { + if (exynos_srom_configure_bank(srom, child)) { + dev_err(dev, + "Could not decode bank configuration for %s\n", + child->name); + bad_bank_config = true; + } + } + + /* + * If any bank failed to configure, we still provide suspend/resume, + * but do not probe child devices + */ + if (bad_bank_config) + return 0; + + return of_platform_populate(np, NULL, NULL, dev); } static int exynos_srom_remove(struct platform_device *pdev) -- GitLab From a7b221d8f0d75511c5f959584712a5dd35f88a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 18 Apr 2016 14:39:30 +0200 Subject: [PATCH 3228/9938] spi: bcm53xx: add spi_flash_read callback for MMIO-based reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements more efficient reads of SPI-attached flash content. Signed-off-by: Rafał Miłecki Signed-off-by: Mark Brown --- drivers/spi/spi-bcm53xx.c | 78 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c index cc3f938f0a6b..afb51699dbb5 100644 --- a/drivers/spi/spi-bcm53xx.c +++ b/drivers/spi/spi-bcm53xx.c @@ -10,6 +10,7 @@ #include "spi-bcm53xx.h" #define BCM53XXSPI_MAX_SPI_BAUD 13500000 /* 216 MHz? */ +#define BCM53XXSPI_FLASH_WINDOW SZ_32M /* The longest observed required wait was 19 ms */ #define BCM53XXSPI_SPE_TIMEOUT_MS 80 @@ -17,8 +18,10 @@ struct bcm53xxspi { struct bcma_device *core; struct spi_master *master; + void __iomem *mmio_base; size_t read_offset; + bool bspi; /* Boot SPI mode with memory mapping */ }; static inline u32 bcm53xxspi_read(struct bcm53xxspi *b53spi, u16 offset) @@ -32,6 +35,50 @@ static inline void bcm53xxspi_write(struct bcm53xxspi *b53spi, u16 offset, bcma_write32(b53spi->core, offset, value); } +static void bcm53xxspi_disable_bspi(struct bcm53xxspi *b53spi) +{ + struct device *dev = &b53spi->core->dev; + unsigned long deadline; + u32 tmp; + + if (!b53spi->bspi) + return; + + tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL); + if (tmp & 0x1) + return; + + deadline = jiffies + usecs_to_jiffies(200); + do { + tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_BUSY_STATUS); + if (!(tmp & 0x1)) { + bcm53xxspi_write(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL, + 0x1); + ndelay(200); + b53spi->bspi = false; + return; + } + udelay(1); + } while (!time_after_eq(jiffies, deadline)); + + dev_warn(dev, "Timeout disabling BSPI\n"); +} + +static void bcm53xxspi_enable_bspi(struct bcm53xxspi *b53spi) +{ + u32 tmp; + + if (b53spi->bspi) + return; + + tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL); + if (!(tmp & 0x1)) + return; + + bcm53xxspi_write(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL, 0x0); + b53spi->bspi = true; +} + static inline unsigned int bcm53xxspi_calc_timeout(size_t len) { /* Do some magic calculation based on length and buad. Add 10% and 1. */ @@ -176,6 +223,8 @@ static int bcm53xxspi_transfer_one(struct spi_master *master, u8 *buf; size_t left; + bcm53xxspi_disable_bspi(b53spi); + if (t->tx_buf) { buf = (u8 *)t->tx_buf; left = t->len; @@ -206,6 +255,22 @@ static int bcm53xxspi_transfer_one(struct spi_master *master, return 0; } +static int bcm53xxspi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg) +{ + struct bcm53xxspi *b53spi = spi_master_get_devdata(spi->master); + int ret = 0; + + if (msg->from + msg->len > BCM53XXSPI_FLASH_WINDOW) + return -EINVAL; + + bcm53xxspi_enable_bspi(b53spi); + memcpy_fromio(msg->buf, b53spi->mmio_base + msg->from, msg->len); + msg->retlen = msg->len; + + return ret; +} + /************************************************** * BCMA **************************************************/ @@ -222,6 +287,7 @@ MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl); static int bcm53xxspi_bcma_probe(struct bcma_device *core) { + struct device *dev = &core->dev; struct bcm53xxspi *b53spi; struct spi_master *master; int err; @@ -231,7 +297,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) return -ENOTSUPP; } - master = spi_alloc_master(&core->dev, sizeof(*b53spi)); + master = spi_alloc_master(dev, sizeof(*b53spi)); if (!master) return -ENOMEM; @@ -239,11 +305,19 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) b53spi->master = master; b53spi->core = core; + if (core->addr_s[0]) + b53spi->mmio_base = devm_ioremap(dev, core->addr_s[0], + BCM53XXSPI_FLASH_WINDOW); + b53spi->bspi = true; + bcm53xxspi_disable_bspi(b53spi); + master->transfer_one = bcm53xxspi_transfer_one; + if (b53spi->mmio_base) + master->spi_flash_read = bcm53xxspi_flash_read; bcma_set_drvdata(core, b53spi); - err = devm_spi_register_master(&core->dev, master); + err = devm_spi_register_master(dev, master); if (err) { spi_master_put(master); bcma_set_drvdata(core, NULL); -- GitLab From dc5a533f91305f91645513abde2da52026385a04 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 14 Apr 2016 12:01:32 +0200 Subject: [PATCH 3229/9938] serial: mctrl_gpio: Grammar s/lines GPIOs/line GPIOs/, /sets/set/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Jiri Kosina --- drivers/tty/serial/serial_mctrl_gpio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h index 9716db283290..bcfad5d1db61 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -62,7 +62,7 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, enum mctrl_gpio_idx gidx); /* - * Request and set direction of modem control lines GPIOs and sets up irq + * Request and set direction of modem control line GPIOs and set up irq * handling. * devm_* functions are used, so there's no need to call mctrl_gpio_free(). * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on @@ -71,7 +71,7 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx); /* - * Request and set direction of modem control lines GPIOs. + * Request and set direction of modem control line GPIOs. * devm_* functions are used, so there's no need to call mctrl_gpio_free(). * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on * allocation error. -- GitLab From acf2abbd0b7fcc6325e9690a8a32ee924c827f70 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Apr 2016 10:35:03 -0300 Subject: [PATCH 3230/9938] perf evsel: Add missign class prefix to has_branch_stack method Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-5i07ivw1yjsweb7gztr255jd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.h | 2 +- tools/perf/util/machine.c | 2 +- tools/perf/util/session.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index b993218744d4..8a644fef452c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -420,7 +420,7 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \ (_evsel) && (_evsel)->leader == (_leader); \ (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) -static inline bool has_branch_callstack(struct perf_evsel *evsel) +static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel) { return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 0c4dabc69932..52b51e004fe8 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1808,7 +1808,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, callchain_cursor_reset(cursor); - if (has_branch_callstack(evsel)) { + if (perf_evsel__has_branch_callstack(evsel)) { err = resolve_lbr_callchain_sample(thread, cursor, sample, parent, root_al, max_stack); if (err) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ca1827c4af4a..2335b2824d8a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -907,7 +907,7 @@ static void callchain__printf(struct perf_evsel *evsel, unsigned int i; struct ip_callchain *callchain = sample->callchain; - if (has_branch_callstack(evsel)) + if (perf_evsel__has_branch_callstack(evsel)) callchain__lbr_callstack_printf(sample); printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr); @@ -1081,7 +1081,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, if (sample_type & PERF_SAMPLE_CALLCHAIN) callchain__printf(evsel, sample); - if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel)) + if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel)) branch_stack__printf(sample); if (sample_type & PERF_SAMPLE_REGS_USER) -- GitLab From 922315210b8007a26374e30712813b714af71cac Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Apr 2016 11:31:46 -0300 Subject: [PATCH 3231/9938] perf script: Check sample->callchain before using it Found by code inspection, while looking at thread__resolve_callchain() callsites, one had it, the other didn't. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-6r8i2afd3523thuuaxl39yhk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 0e93282b405e..5099740aa50b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -791,7 +791,7 @@ static void process_event(struct perf_script *script, if (PRINT_FIELD(IP)) { struct callchain_cursor *cursor = NULL, cursor_callchain; - if (symbol_conf.use_callchain && + if (symbol_conf.use_callchain && sample->callchain && thread__resolve_callchain(al->thread, &cursor_callchain, evsel, sample, NULL, NULL, scripting_max_stack) == 0) cursor = &cursor_callchain; -- GitLab From 30234f0925c1deeb472b579b57a9f50791157c58 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Apr 2016 11:53:07 -0300 Subject: [PATCH 3232/9938] perf callchain: Set callchain_param.enabled when parsing --call-graph Trying to move in the direction of using callchain_param for all callchain parameters, eventually ditching them from symbol_conf. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-kixllia6r26mz45ng056zq7z@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/callchain.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 2b4ceaf058bb..aa248dcb4440 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -109,6 +109,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt) bool record_opt_set = false; bool try_stack_size = false; + callchain_param.enabled = true; symbol_conf.use_callchain = true; if (!arg) @@ -117,6 +118,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt) while ((tok = strtok((char *)arg, ",")) != NULL) { if (!strncmp(tok, "none", strlen(tok))) { callchain_param.mode = CHAIN_NONE; + callchain_param.enabled = false; symbol_conf.use_callchain = false; return 0; } -- GitLab From 1cc83815d5fdb40a7d06c3f9871134a10e5ffa79 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Apr 2016 11:54:31 -0300 Subject: [PATCH 3233/9938] perf report: Use callchain_param.enabled instead of tool specific knob We have callchain_param.enabled, so no need to have something just for 'perf report' to do the same thing. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-wbeisubpualwogwi5u8utnt1@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 160ea23b45aa..1d5be0bd426f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -47,7 +47,6 @@ struct report { struct perf_tool tool; struct perf_session *session; bool use_tui, use_gtk, use_stdio; - bool dont_use_callchains; bool show_full_info; bool show_threads; bool inverted_callchain; @@ -247,7 +246,7 @@ static int report__setup_sample_type(struct report *rep) "you call 'perf record' without -g?\n"); return -1; } - } else if (!rep->dont_use_callchains && + } else if (!callchain_param.enabled && callchain_param.mode != CHAIN_NONE && !symbol_conf.use_callchain) { symbol_conf.use_callchain = true; @@ -599,13 +598,15 @@ static int __cmd_report(struct report *rep) static int report_parse_callchain_opt(const struct option *opt, const char *arg, int unset) { - struct report *rep = (struct report *)opt->value; + struct callchain_param *callchain = opt->value; + callchain->enabled = !unset; /* * --no-call-graph */ if (unset) { - rep->dont_use_callchains = true; + symbol_conf.use_callchain = false; + callchain->mode = CHAIN_NONE; return 0; } @@ -734,7 +735,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, "Only display entries with parent-match"), - OPT_CALLBACK_DEFAULT('g', "call-graph", &report, + OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param, "print_type,threshold[,print_limit],order,sort_key[,branch],value", report_callchain_help, &report_parse_callchain_opt, callchain_default_opt), -- GitLab From 2ddd5c049e71dd8551c268e7386fefeb7495e988 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Apr 2016 12:09:08 -0300 Subject: [PATCH 3234/9938] perf tools: Ditch record_opts.callgraph_set We have callchain_param.enabled for that. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-silwqjc2t25ls42dsvg28pp5@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 14 ++++++-------- tools/perf/builtin-top.c | 13 ++++++------- tools/perf/builtin-trace.c | 8 ++++---- tools/perf/perf.h | 1 - 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 5b4758a08a49..bd9593346bb2 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -946,7 +946,6 @@ int record_opts__parse_callchain(struct record_opts *record, const char *arg, bool unset) { int ret; - record->callgraph_set = true; callchain->enabled = !unset; /* --no-call-graph */ @@ -978,15 +977,14 @@ int record_callchain_opt(const struct option *opt, const char *arg __maybe_unused, int unset __maybe_unused) { - struct record_opts *record = (struct record_opts *)opt->value; + struct callchain_param *callchain = opt->value; - record->callgraph_set = true; - callchain_param.enabled = true; + callchain->enabled = true; - if (callchain_param.record_mode == CALLCHAIN_NONE) - callchain_param.record_mode = CALLCHAIN_FP; + if (callchain->record_mode == CALLCHAIN_NONE) + callchain->record_mode = CALLCHAIN_FP; - callchain_debug(&callchain_param); + callchain_debug(callchain); return 0; } @@ -1224,7 +1222,7 @@ struct option __record_options[] = { record__parse_mmap_pages), OPT_BOOLEAN(0, "group", &record.opts.group, "put the counters into a counter group"), - OPT_CALLBACK_NOOPT('g', NULL, &record.opts, + OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, NULL, "enables call-graph recording" , &record_callchain_opt), OPT_CALLBACK(0, "call-graph", &record.opts, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8846df0ec0c3..f0cfdf394fac 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1045,18 +1045,17 @@ callchain_opt(const struct option *opt, const char *arg, int unset) static int parse_callchain_opt(const struct option *opt, const char *arg, int unset) { - struct record_opts *record = (struct record_opts *)opt->value; + struct callchain_param *callchain = opt->value; - record->callgraph_set = true; - callchain_param.enabled = !unset; - callchain_param.record_mode = CALLCHAIN_FP; + callchain->enabled = !unset; + callchain->record_mode = CALLCHAIN_FP; /* * --no-call-graph */ if (unset) { symbol_conf.use_callchain = false; - callchain_param.record_mode = CALLCHAIN_NONE; + callchain->record_mode = CALLCHAIN_NONE; return 0; } @@ -1162,10 +1161,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) "output field(s): overhead, period, sample plus all of sort keys"), OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, "Show a column with the number of samples"), - OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, + OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, NULL, "enables call-graph recording and display", &callchain_opt), - OPT_CALLBACK(0, "call-graph", &top.record_opts, + OPT_CALLBACK(0, "call-graph", &callchain_param, "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]", top_callchain_help, &parse_callchain_opt), OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0e3c1cecef1b..5e2614bbb48d 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2457,7 +2457,7 @@ static int trace__add_syscall_newtp(struct trace *trace) perf_evlist__add(evlist, sys_enter); perf_evlist__add(evlist, sys_exit); - if (trace->opts.callgraph_set && !trace->kernel_syscallchains) { + if (callchain_param.enabled && !trace->kernel_syscallchains) { /* * We're interested only in the user space callchain * leading to the syscall, allow overriding that for @@ -2546,7 +2546,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) perf_evlist__config(evlist, &trace->opts, NULL); - if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) { + if (callchain_param.enabled && trace->syscalls.events.sys_exit) { perf_evsel__config_callchain(trace->syscalls.events.sys_exit, &trace->opts, &callchain_param); /* @@ -3153,11 +3153,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) } #ifdef HAVE_DWARF_UNWIND_SUPPORT - if ((trace.min_stack || max_stack_user_set) && !trace.opts.callgraph_set) + if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled) record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false); #endif - if (trace.opts.callgraph_set) { + if (callchain_param.enabled) { if (!mmap_pages_user_set && geteuid() == 0) trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4; diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 5381a01c0610..cd8f1b150f9e 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -52,7 +52,6 @@ struct record_opts { bool sample_weight; bool sample_time; bool sample_time_set; - bool callgraph_set; bool period; bool running_time; bool full_auxtrace; -- GitLab From 1b6b678ecfb73724914a8b12d57909a4c514a9bd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Apr 2016 12:24:41 -0300 Subject: [PATCH 3235/9938] perf hists browser: Fold two consecutive symbol_conf.use_callchain ifs Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-u701i6qpecgm9jiat52i8l98@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index e70df2e54d66..6a4681932ba5 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1896,11 +1896,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, bool first = true; int ret; - if (symbol_conf.use_callchain) + if (symbol_conf.use_callchain) { folded_sign = hist_entry__folded(he); - - if (symbol_conf.use_callchain) printed += fprintf(fp, "%c ", folded_sign); + } hists__for_each_format(browser->hists, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) -- GitLab From e3815264a6c57147f8b5639536b1df3c98244642 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Apr 2016 12:30:16 -0300 Subject: [PATCH 3236/9938] perf top: Use callchain_param.enabled instead of symbol_conf.use_callchain One more step in the direction of using just callchain_param for callchain parameters. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-3b1o9kb2dc94zldz0klckti6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index f0cfdf394fac..c130a11d3a0d 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -917,15 +917,15 @@ static int perf_top__start_counters(struct perf_top *top) return -1; } -static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused) +static int callchain_param__setup_sample_type(struct callchain_param *callchain) { if (!sort__has_sym) { - if (symbol_conf.use_callchain) { + if (callchain->enabled) { ui__error("Selected -g but \"sym\" not present in --sort/-s."); return -EINVAL; } - } else if (callchain_param.mode != CHAIN_NONE) { - if (callchain_register_param(&callchain_param) < 0) { + } else if (callchain->mode != CHAIN_NONE) { + if (callchain_register_param(callchain) < 0) { ui__error("Can't register callchain params.\n"); return -EINVAL; } @@ -952,7 +952,7 @@ static int __cmd_top(struct perf_top *top) goto out_delete; } - ret = perf_top__setup_sample_type(top); + ret = callchain_param__setup_sample_type(&callchain_param); if (ret) goto out_delete; @@ -1311,7 +1311,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) top.sym_evsel = perf_evlist__first(top.evlist); - if (!symbol_conf.use_callchain) { + if (!callchain_param.enabled) { symbol_conf.cumulate_callchain = false; perf_hpp__cancel_cumulate(); } -- GitLab From 94be46b9e5e2954b6d5962750f8aae8b5f099baa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 18 Apr 2016 15:33:10 +0200 Subject: [PATCH 3237/9938] regulator: s2mps11: Set default ramp delay for S2MPS11 LDOs Driver did not provide default value for ramp delay for LDOs which lead to warning in dmesg, e.g. on Odroid XU4: [ 1.486076] vdd_ldo9: ramp_delay not set [ 1.506875] vddq_mmc2: ramp_delay not set [ 1.523766] vdd_ldo15: ramp_delay not set [ 1.544702] vdd_sd: ramp_delay not set The datasheet for all the S2MPS1x family is inconsistent here and does not specify unambiguously the value of ramp delay for LDO. It mentions 30 mV/us in one timing diagram but then omits it completely in LDO regulator characteristics table (it is specified for bucks). However the vendor kernels for Galaxy S5 and Odroid XU3 use values of 12 mV/us or 24 mV/us. Without the ramp delay value the consumers do not wait for voltage settle after changing it. Although the proper value of ramp delay for LDOs is unknown, it seems safer to use at least some value from reference kernel than to leave it unset. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 1 + include/linux/mfd/samsung/core.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 46e5a2922c4d..47c7de8f39e9 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -267,6 +267,7 @@ static struct regulator_ops s2mps11_buck_ops = { .ops = &s2mps11_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .ramp_delay = RAMP_DELAY_12_MVUS, \ .min_uV = MIN_800_MV, \ .uV_step = step, \ .n_voltages = S2MPS11_LDO_N_VOLTAGES, \ diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 6bc4bcd488ac..5a23dd4df432 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -30,6 +30,9 @@ #define MIN_600_MV 600000 #define MIN_500_MV 500000 +/* Ramp delay in uV/us */ +#define RAMP_DELAY_12_MVUS 12000 + /* Macros to represent steps for LDO/BUCK */ #define STEP_50_MV 50000 #define STEP_25_MV 25000 -- GitLab From 22225835e23f7a768e767967004d2f3751c64be5 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Mon, 18 Apr 2016 14:32:40 +0200 Subject: [PATCH 3238/9938] ASoC: davinci-mcbsp: add binding for McBSP Add devicetree binding for the TI DA850/OMAP-L138/AM18xx MultiChannel Buffered Serial Port (McBSP) The optional register range "dat" is not implemented at the moment. The current driver supports only DMA into RX/TX registers but no FIFO. Once the FIFO is implemented in the driver the "dat" range will be used. Signed-off-by: Petr Kulhavy Reviewed-by: Peter Ujfalusi Signed-off-by: Mark Brown --- .../bindings/sound/davinci-mcbsp.txt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/davinci-mcbsp.txt diff --git a/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt b/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt new file mode 100644 index 000000000000..55b53e1fd72c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt @@ -0,0 +1,51 @@ +Texas Instruments DaVinci McBSP module +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This binding describes the "Multi-channel Buffered Serial Port" (McBSP) +audio interface found in some TI DaVinci processors like the OMAP-L138 or AM180x. + + +Required properties: +~~~~~~~~~~~~~~~~~~~~ +- compatible : + "ti,da850-mcbsp" : for DA850, AM180x and OPAM-L138 platforms + +- reg : physical base address and length of the controller memory mapped + region(s). +- reg-names : Should contain: + * "mpu" for the main registers (required). + * "dat" for the data FIFO (optional). + +- dmas: three element list of DMA controller phandles, DMA request line and + TC channel ordered triplets. +- dma-names: identifier string for each DMA request line in the dmas property. + These strings correspond 1:1 with the ordered pairs in dmas. The dma + identifiers must be "rx" and "tx". + +Optional properties: +~~~~~~~~~~~~~~~~~~~~ +- interrupts : Interrupt numbers for McBSP +- interrupt-names : Known interrupt names are "rx" and "tx" + +- pinctrl-0: Should specify pin control group used for this controller. +- pinctrl-names: Should contain only one value - "default", for more details + please refer to pinctrl-bindings.txt + +Example (AM1808): +~~~~~~~~~~~~~~~~~ + +mcbsp0: mcbsp@1d10000 { + compatible = "ti,da850-mcbsp"; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp0_pins>; + + reg = <0x00110000 0x1000>, + <0x00310000 0x1000>; + reg-names = "mpu", "dat"; + interrupts = <97 98>; + interrupts-names = "rx", "tx"; + dmas = <&edma0 3 1 + &edma0 2 1>; + dma-names = "tx", "rx"; + status = "okay"; +}; -- GitLab From 5f9a50c3e55ee887b7a0ccb68045b92579972b55 Mon Sep 17 00:00:00 2001 From: Petr Kulhavy Date: Mon, 18 Apr 2016 14:32:41 +0200 Subject: [PATCH 3239/9938] ASoC: Davinci: McBSP: add device tree support for McBSP This adds DT support for the TI DA8xx/OMAP-L1x/AM17xx/AM18xx McBSP driver. Signed-off-by: Petr Kulhavy Reviewed-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/Kconfig | 6 ++- sound/soc/davinci/davinci-i2s.c | 80 ++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 50ca291cc225..6b732d8e5896 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig @@ -16,7 +16,11 @@ config SND_EDMA_SOC - DRA7xx family config SND_DAVINCI_SOC_I2S - tristate + tristate "DaVinci Multichannel Buffered Serial Port (McBSP) support" + depends on SND_EDMA_SOC + help + Say Y or M here if you want to have support for McBSP IP found in + Texas Instruments DaVinci DA850 SoCs. config SND_DAVINCI_SOC_MCASP tristate "Multichannel Audio Serial Port (McASP) support" diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index ec98548a5fc9..384961651904 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -4,9 +4,15 @@ * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., * + * DT support (c) 2016 Petr Kulhavy, Barix AG + * based on davinci-mcasp.c DT support + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * TODO: + * on DA850 implement HW FIFOs instead of DMA into DXR and DRR registers */ #include @@ -650,13 +656,24 @@ static const struct snd_soc_component_driver davinci_i2s_component = { static int davinci_i2s_probe(struct platform_device *pdev) { + struct snd_dmaengine_dai_dma_data *dma_data; struct davinci_mcbsp_dev *dev; struct resource *mem, *res; void __iomem *io_base; int *dma; int ret; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); + if (!mem) { + dev_warn(&pdev->dev, + "\"mpu\" mem resource not found, using index 0\n"); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&pdev->dev, "no mem resource?\n"); + return -ENODEV; + } + } + io_base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(io_base)) return PTR_ERR(io_base); @@ -666,39 +683,43 @@ static int davinci_i2s_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) - return -ENODEV; - clk_enable(dev->clk); - dev->base = io_base; - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = - (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); + /* setup DMA, first TX, then RX */ + dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; + dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); - dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = - (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); - - /* first TX, then RX */ res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_release_clk; + if (res) { + dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK]; + *dma = res->start; + dma_data->filter_data = dma; + } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { + dma_data->filter_data = "tx"; + } else { + dev_err(&pdev->dev, "Missing DMA tx resource\n"); + return -ENODEV; } - dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK]; - *dma = res->start; - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = dma; + + dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; + dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_release_clk; + if (res) { + dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE]; + *dma = res->start; + dma_data->filter_data = dma; + } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { + dma_data->filter_data = "rx"; + } else { + dev_err(&pdev->dev, "Missing DMA rx resource\n"); + return -ENODEV; } - dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE]; - *dma = res->start; - dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = dma; + + dev->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(dev->clk)) + return -ENODEV; + clk_enable(dev->clk); dev->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, dev); @@ -737,11 +758,18 @@ static int davinci_i2s_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id davinci_i2s_match[] = { + { .compatible = "ti,da850-mcbsp" }, + {}, +}; +MODULE_DEVICE_TABLE(of, davinci_i2s_match); + static struct platform_driver davinci_mcbsp_driver = { .probe = davinci_i2s_probe, .remove = davinci_i2s_remove, .driver = { .name = "davinci-mcbsp", + .of_match_table = of_match_ptr(davinci_i2s_match), }, }; -- GitLab From 550bce59baf3f3059cd4ae1e268f08f2d2cb1d5c Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Fri, 15 Apr 2016 20:36:25 -0700 Subject: [PATCH 3240/9938] rtnetlink: rtnl_fill_stats: avoid an unnecssary stats copy This patch passes netlink attr data ptr directly to dev_get_stats thus elimiating a stats copy. Suggested-by: David Miller Signed-off-by: Roopa Prabhu Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a75f7e94b445..a7a3d345134a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -808,11 +808,6 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, a->rx_nohandler = b->rx_nohandler; } -static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b) -{ - memcpy(v, b, sizeof(*b)); -} - /* All VF info */ static inline int rtnl_vfinfo_size(const struct net_device *dev, u32 ext_filter_mask) @@ -1054,25 +1049,23 @@ static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev) static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb, struct net_device *dev) { - const struct rtnl_link_stats64 *stats; - struct rtnl_link_stats64 temp; + struct rtnl_link_stats64 *sp; struct nlattr *attr; - stats = dev_get_stats(dev, &temp); - - attr = nla_reserve(skb, IFLA_STATS, - sizeof(struct rtnl_link_stats)); + attr = nla_reserve(skb, IFLA_STATS64, + sizeof(struct rtnl_link_stats64)); if (!attr) return -EMSGSIZE; - copy_rtnl_link_stats(nla_data(attr), stats); + sp = nla_data(attr); + dev_get_stats(dev, sp); - attr = nla_reserve(skb, IFLA_STATS64, - sizeof(struct rtnl_link_stats64)); + attr = nla_reserve(skb, IFLA_STATS, + sizeof(struct rtnl_link_stats)); if (!attr) return -EMSGSIZE; - copy_rtnl_link_stats64(nla_data(attr), stats); + copy_rtnl_link_stats(nla_data(attr), sp); return 0; } -- GitLab From 0a4afaae989c47fd93b73cc83d2c4a46b55aa1b7 Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 15 Apr 2016 16:57:18 +0530 Subject: [PATCH 3241/9938] spi: pic32-sqi: add binding document for PIC32 Quad-SPI driver. Document Device tree bindings for the quad SPI peripheral found on Microchip PIC32 class devices. Signed-off-by: Purna Chandra Mandal Acked-by: Rob Herring Cc: Kumar Gala Cc: Ian Campbell Cc: Rob Herring Cc: Pawel Moll Cc: Mark Rutland Cc: Mark Brown Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/sqi-pic32.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Documentation/devicetree/bindings/spi/sqi-pic32.txt diff --git a/Documentation/devicetree/bindings/spi/sqi-pic32.txt b/Documentation/devicetree/bindings/spi/sqi-pic32.txt new file mode 100644 index 000000000000..c82d021bce50 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/sqi-pic32.txt @@ -0,0 +1,18 @@ +Microchip PIC32 Quad SPI controller +----------------------------------- +Required properties: +- compatible: Should be "microchip,pic32mzda-sqi". +- reg: Address and length of SQI controller register space. +- interrupts: Should contain SQI interrupt. +- clocks: Should contain phandle of two clocks in sequence, one that drives + clock on SPI bus and other that drives SQI controller. +- clock-names: Should be "spi_ck" and "reg_ck" in order. + +Example: + sqi1: spi@1f8e2000 { + compatible = "microchip,pic32mzda-sqi"; + reg = <0x1f8e2000 0x200>; + clocks = <&rootclk REF2CLK>, <&rootclk PB5CLK>; + clock-names = "spi_ck", "reg_ck"; + interrupts = <169 IRQ_TYPE_LEVEL_HIGH>; + }; -- GitLab From 3270ac230f660843a7f7d631746ee2c8ee63f347 Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 15 Apr 2016 16:57:19 +0530 Subject: [PATCH 3242/9938] spi: pic32-sqi: add SPI driver for PIC32 SQI controller. This driver implements SPI master interface for Quad SPI controller, specifically for accessing quad SPI flash. It uses descriptor-based DMA transfer mode and supports half-duplex communication for single, dual and quad SPI transactions. Signed-off-by: Purna Chandra Mandal Cc: Mark Brown Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/spi-pic32-sqi.c | 768 ++++++++++++++++++++++++++++++++++++ 3 files changed, 775 insertions(+) create mode 100644 drivers/spi/spi-pic32-sqi.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8a8ff5051c64..281ed5da4832 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -442,6 +442,12 @@ config SPI_PIC32 help SPI driver for Microchip PIC32 SPI master controller. +config SPI_PIC32_SQI + tristate "Microchip PIC32 Quad SPI driver" + depends on MACH_PIC32 || COMPILE_TEST + help + SPI driver for PIC32 Quad SPI controller. + config SPI_PL022 tristate "ARM AMBA PL022 SSP controller" depends on ARM_AMBA diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 06019ed11fac..3c74d003535b 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o obj-$(CONFIG_SPI_ORION) += spi-orion.o obj-$(CONFIG_SPI_PIC32) += spi-pic32.o +obj-$(CONFIG_SPI_PIC32_SQI) += spi-pic32-sqi.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-dma.o diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c new file mode 100644 index 000000000000..b21534782ada --- /dev/null +++ b/drivers/spi/spi-pic32-sqi.c @@ -0,0 +1,768 @@ +/* + * PIC32 Quad SPI controller driver. + * + * Purna Chandra Mandal + * Copyright (c) 2016, Microchip Technology Inc. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SQI registers */ +#define PESQI_XIP_CONF1_REG 0x00 +#define PESQI_XIP_CONF2_REG 0x04 +#define PESQI_CONF_REG 0x08 +#define PESQI_CTRL_REG 0x0C +#define PESQI_CLK_CTRL_REG 0x10 +#define PESQI_CMD_THRES_REG 0x14 +#define PESQI_INT_THRES_REG 0x18 +#define PESQI_INT_ENABLE_REG 0x1C +#define PESQI_INT_STAT_REG 0x20 +#define PESQI_TX_DATA_REG 0x24 +#define PESQI_RX_DATA_REG 0x28 +#define PESQI_STAT1_REG 0x2C +#define PESQI_STAT2_REG 0x30 +#define PESQI_BD_CTRL_REG 0x34 +#define PESQI_BD_CUR_ADDR_REG 0x38 +#define PESQI_BD_BASE_ADDR_REG 0x40 +#define PESQI_BD_STAT_REG 0x44 +#define PESQI_BD_POLL_CTRL_REG 0x48 +#define PESQI_BD_TX_DMA_STAT_REG 0x4C +#define PESQI_BD_RX_DMA_STAT_REG 0x50 +#define PESQI_THRES_REG 0x54 +#define PESQI_INT_SIGEN_REG 0x58 + +/* PESQI_CONF_REG fields */ +#define PESQI_MODE 0x7 +#define PESQI_MODE_BOOT 0 +#define PESQI_MODE_PIO 1 +#define PESQI_MODE_DMA 2 +#define PESQI_MODE_XIP 3 +#define PESQI_MODE_SHIFT 0 +#define PESQI_CPHA BIT(3) +#define PESQI_CPOL BIT(4) +#define PESQI_LSBF BIT(5) +#define PESQI_RXLATCH BIT(7) +#define PESQI_SERMODE BIT(8) +#define PESQI_WP_EN BIT(9) +#define PESQI_HOLD_EN BIT(10) +#define PESQI_BURST_EN BIT(12) +#define PESQI_CS_CTRL_HW BIT(15) +#define PESQI_SOFT_RESET BIT(16) +#define PESQI_LANES_SHIFT 20 +#define PESQI_SINGLE_LANE 0 +#define PESQI_DUAL_LANE 1 +#define PESQI_QUAD_LANE 2 +#define PESQI_CSEN_SHIFT 24 +#define PESQI_EN BIT(23) + +/* PESQI_CLK_CTRL_REG fields */ +#define PESQI_CLK_EN BIT(0) +#define PESQI_CLK_STABLE BIT(1) +#define PESQI_CLKDIV_SHIFT 8 +#define PESQI_CLKDIV 0xff + +/* PESQI_INT_THR/CMD_THR_REG */ +#define PESQI_TXTHR_MASK 0x1f +#define PESQI_TXTHR_SHIFT 8 +#define PESQI_RXTHR_MASK 0x1f +#define PESQI_RXTHR_SHIFT 0 + +/* PESQI_INT_EN/INT_STAT/INT_SIG_EN_REG */ +#define PESQI_TXEMPTY BIT(0) +#define PESQI_TXFULL BIT(1) +#define PESQI_TXTHR BIT(2) +#define PESQI_RXEMPTY BIT(3) +#define PESQI_RXFULL BIT(4) +#define PESQI_RXTHR BIT(5) +#define PESQI_BDDONE BIT(9) /* BD processing complete */ +#define PESQI_PKTCOMP BIT(10) /* packet processing complete */ +#define PESQI_DMAERR BIT(11) /* error */ + +/* PESQI_BD_CTRL_REG */ +#define PESQI_DMA_EN BIT(0) /* enable DMA engine */ +#define PESQI_POLL_EN BIT(1) /* enable polling */ +#define PESQI_BDP_START BIT(2) /* start BD processor */ + +/* PESQI controller buffer descriptor */ +struct buf_desc { + u32 bd_ctrl; /* control */ + u32 bd_status; /* reserved */ + u32 bd_addr; /* DMA buffer addr */ + u32 bd_nextp; /* next item in chain */ +}; + +/* bd_ctrl */ +#define BD_BUFLEN 0x1ff +#define BD_CBD_INT_EN BIT(16) /* Current BD is processed */ +#define BD_PKT_INT_EN BIT(17) /* All BDs of PKT processed */ +#define BD_LIFM BIT(18) /* last data of pkt */ +#define BD_LAST BIT(19) /* end of list */ +#define BD_DATA_RECV BIT(20) /* receive data */ +#define BD_DDR BIT(21) /* DDR mode */ +#define BD_DUAL BIT(22) /* Dual SPI */ +#define BD_QUAD BIT(23) /* Quad SPI */ +#define BD_LSBF BIT(25) /* LSB First */ +#define BD_STAT_CHECK BIT(27) /* Status poll */ +#define BD_DEVSEL_SHIFT 28 /* CS */ +#define BD_CS_DEASSERT BIT(30) /* de-assert CS after current BD */ +#define BD_EN BIT(31) /* BD owned by H/W */ + +/** + * struct ring_desc - Representation of SQI ring descriptor + * @list: list element to add to free or used list. + * @bd: PESQI controller buffer descriptor + * @bd_dma: DMA address of PESQI controller buffer descriptor + * @xfer_len: transfer length + */ +struct ring_desc { + struct list_head list; + struct buf_desc *bd; + dma_addr_t bd_dma; + u32 xfer_len; +}; + +/* Global constants */ +#define PESQI_BD_BUF_LEN_MAX 256 +#define PESQI_BD_COUNT 256 /* max 64KB data per spi message */ + +struct pic32_sqi { + void __iomem *regs; + struct clk *sys_clk; + struct clk *base_clk; /* drives spi clock */ + struct spi_master *master; + int irq; + struct completion xfer_done; + struct ring_desc *ring; + void *bd; + dma_addr_t bd_dma; + struct list_head bd_list_free; /* free */ + struct list_head bd_list_used; /* allocated */ + struct spi_device *cur_spi; + u32 cur_speed; + u8 cur_mode; +}; + +static inline void pic32_setbits(void __iomem *reg, u32 set) +{ + writel(readl(reg) | set, reg); +} + +static inline void pic32_clrbits(void __iomem *reg, u32 clr) +{ + writel(readl(reg) & ~clr, reg); +} + +static int pic32_sqi_set_clk_rate(struct pic32_sqi *sqi, u32 sck) +{ + u32 val, div; + + /* div = base_clk / (2 * spi_clk) */ + div = clk_get_rate(sqi->base_clk) / (2 * sck); + div &= PESQI_CLKDIV; + + val = readl(sqi->regs + PESQI_CLK_CTRL_REG); + /* apply new divider */ + val &= ~(PESQI_CLK_STABLE | (PESQI_CLKDIV << PESQI_CLKDIV_SHIFT)); + val |= div << PESQI_CLKDIV_SHIFT; + writel(val, sqi->regs + PESQI_CLK_CTRL_REG); + + /* wait for stability */ + return readl_poll_timeout(sqi->regs + PESQI_CLK_CTRL_REG, val, + val & PESQI_CLK_STABLE, 1, 5000); +} + +static inline void pic32_sqi_enable_int(struct pic32_sqi *sqi) +{ + u32 mask = PESQI_DMAERR | PESQI_BDDONE | PESQI_PKTCOMP; + + writel(mask, sqi->regs + PESQI_INT_ENABLE_REG); + /* INT_SIGEN works as interrupt-gate to INTR line */ + writel(mask, sqi->regs + PESQI_INT_SIGEN_REG); +} + +static inline void pic32_sqi_disable_int(struct pic32_sqi *sqi) +{ + writel(0, sqi->regs + PESQI_INT_ENABLE_REG); + writel(0, sqi->regs + PESQI_INT_SIGEN_REG); +} + +static irqreturn_t pic32_sqi_isr(int irq, void *dev_id) +{ + struct pic32_sqi *sqi = dev_id; + u32 enable, status; + + enable = readl(sqi->regs + PESQI_INT_ENABLE_REG); + status = readl(sqi->regs + PESQI_INT_STAT_REG); + + /* check spurious interrupt */ + if (!status) + return IRQ_NONE; + + if (status & PESQI_DMAERR) { + enable = 0; + goto irq_done; + } + + if (status & PESQI_TXTHR) + enable &= ~(PESQI_TXTHR | PESQI_TXFULL | PESQI_TXEMPTY); + + if (status & PESQI_RXTHR) + enable &= ~(PESQI_RXTHR | PESQI_RXFULL | PESQI_RXEMPTY); + + if (status & PESQI_BDDONE) + enable &= ~PESQI_BDDONE; + + /* packet processing completed */ + if (status & PESQI_PKTCOMP) { + /* mask all interrupts */ + enable = 0; + /* complete trasaction */ + complete(&sqi->xfer_done); + } + +irq_done: + /* interrupts are sticky, so mask when handled */ + writel(enable, sqi->regs + PESQI_INT_ENABLE_REG); + + return IRQ_HANDLED; +} + +static struct ring_desc *ring_desc_get(struct pic32_sqi *sqi) +{ + struct ring_desc *rdesc; + + if (list_empty(&sqi->bd_list_free)) + return NULL; + + rdesc = list_first_entry(&sqi->bd_list_free, struct ring_desc, list); + list_del(&rdesc->list); + list_add_tail(&rdesc->list, &sqi->bd_list_used); + return rdesc; +} + +static void ring_desc_put(struct pic32_sqi *sqi, struct ring_desc *rdesc) +{ + list_del(&rdesc->list); + list_add(&rdesc->list, &sqi->bd_list_free); +} + +static int pic32_sqi_one_transfer(struct pic32_sqi *sqi, + struct spi_message *mesg, + struct spi_transfer *xfer) +{ + struct spi_device *spi = mesg->spi; + struct scatterlist *sg, *sgl; + struct ring_desc *rdesc; + struct buf_desc *bd; + int nents, i; + u32 bd_ctrl; + u32 nbits; + + /* Device selection */ + bd_ctrl = spi->chip_select << BD_DEVSEL_SHIFT; + + /* half-duplex: select transfer buffer, direction and lane */ + if (xfer->rx_buf) { + bd_ctrl |= BD_DATA_RECV; + nbits = xfer->rx_nbits; + sgl = xfer->rx_sg.sgl; + nents = xfer->rx_sg.nents; + } else { + nbits = xfer->tx_nbits; + sgl = xfer->tx_sg.sgl; + nents = xfer->tx_sg.nents; + } + + if (nbits & SPI_NBITS_QUAD) + bd_ctrl |= BD_QUAD; + else if (nbits & SPI_NBITS_DUAL) + bd_ctrl |= BD_DUAL; + + /* LSB first */ + if (spi->mode & SPI_LSB_FIRST) + bd_ctrl |= BD_LSBF; + + /* ownership to hardware */ + bd_ctrl |= BD_EN; + + for_each_sg(sgl, sg, nents, i) { + /* get ring descriptor */ + rdesc = ring_desc_get(sqi); + if (!rdesc) + break; + + bd = rdesc->bd; + + /* BD CTRL: length */ + rdesc->xfer_len = sg_dma_len(sg); + bd->bd_ctrl = bd_ctrl; + bd->bd_ctrl |= rdesc->xfer_len; + + /* BD STAT */ + bd->bd_status = 0; + + /* BD BUFFER ADDRESS */ + bd->bd_addr = sg->dma_address; + } + + return 0; +} + +static int pic32_sqi_prepare_hardware(struct spi_master *master) +{ + struct pic32_sqi *sqi = spi_master_get_devdata(master); + + /* enable spi interface */ + pic32_setbits(sqi->regs + PESQI_CONF_REG, PESQI_EN); + /* enable spi clk */ + pic32_setbits(sqi->regs + PESQI_CLK_CTRL_REG, PESQI_CLK_EN); + + return 0; +} + +static bool pic32_sqi_can_dma(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *x) +{ + /* Do DMA irrespective of transfer size */ + return true; +} + +static int pic32_sqi_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_device *spi = msg->spi; + struct ring_desc *rdesc, *next; + struct spi_transfer *xfer; + struct pic32_sqi *sqi; + int ret = 0, mode; + u32 val; + + sqi = spi_master_get_devdata(master); + + reinit_completion(&sqi->xfer_done); + msg->actual_length = 0; + + /* We can't handle spi_transfer specific "speed_hz", "bits_per_word" + * and "delay_usecs". But spi_device specific speed and mode change + * can be handled at best during spi chip-select switch. + */ + if (sqi->cur_spi != spi) { + /* set spi speed */ + if (sqi->cur_speed != spi->max_speed_hz) { + sqi->cur_speed = spi->max_speed_hz; + ret = pic32_sqi_set_clk_rate(sqi, spi->max_speed_hz); + if (ret) + dev_warn(&spi->dev, "set_clk, %d\n", ret); + } + + /* set spi mode */ + mode = spi->mode & (SPI_MODE_3 | SPI_LSB_FIRST); + if (sqi->cur_mode != mode) { + val = readl(sqi->regs + PESQI_CONF_REG); + val &= ~(PESQI_CPOL | PESQI_CPHA | PESQI_LSBF); + if (mode & SPI_CPOL) + val |= PESQI_CPOL; + if (mode & SPI_LSB_FIRST) + val |= PESQI_LSBF; + val |= PESQI_CPHA; + writel(val, sqi->regs + PESQI_CONF_REG); + + sqi->cur_mode = mode; + } + sqi->cur_spi = spi; + } + + /* prepare hardware desc-list(BD) for transfer(s) */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + ret = pic32_sqi_one_transfer(sqi, msg, xfer); + if (ret) { + dev_err(&spi->dev, "xfer %p err\n", xfer); + goto xfer_out; + } + } + + /* BDs are prepared and chained. Now mark LAST_BD, CS_DEASSERT at last + * element of the list. + */ + rdesc = list_last_entry(&sqi->bd_list_used, struct ring_desc, list); + rdesc->bd->bd_ctrl |= BD_LAST | BD_CS_DEASSERT | + BD_LIFM | BD_PKT_INT_EN; + + /* set base address BD list for DMA engine */ + rdesc = list_first_entry(&sqi->bd_list_used, struct ring_desc, list); + writel(rdesc->bd_dma, sqi->regs + PESQI_BD_BASE_ADDR_REG); + + /* enable interrupt */ + pic32_sqi_enable_int(sqi); + + /* enable DMA engine */ + val = PESQI_DMA_EN | PESQI_POLL_EN | PESQI_BDP_START; + writel(val, sqi->regs + PESQI_BD_CTRL_REG); + + /* wait for xfer completion */ + ret = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ); + if (ret <= 0) { + dev_err(&sqi->master->dev, "wait timedout/interrupted\n"); + ret = -EIO; + msg->status = ret; + } else { + /* success */ + msg->status = 0; + ret = 0; + } + + /* disable DMA */ + writel(0, sqi->regs + PESQI_BD_CTRL_REG); + + pic32_sqi_disable_int(sqi); + +xfer_out: + list_for_each_entry_safe_reverse(rdesc, next, + &sqi->bd_list_used, list) { + /* Update total byte transferred */ + msg->actual_length += rdesc->xfer_len; + /* release ring descr */ + ring_desc_put(sqi, rdesc); + } + spi_finalize_current_message(spi->master); + + return ret; +} + +static int pic32_sqi_unprepare_hardware(struct spi_master *master) +{ + struct pic32_sqi *sqi = spi_master_get_devdata(master); + + /* disable clk */ + pic32_clrbits(sqi->regs + PESQI_CLK_CTRL_REG, PESQI_CLK_EN); + /* disable spi */ + pic32_clrbits(sqi->regs + PESQI_CONF_REG, PESQI_EN); + + return 0; +} + +/* This may be called twice for each spi dev */ +static int pic32_sqi_setup(struct spi_device *spi) +{ + struct pic32_sqi *sqi; + + if (spi_get_ctldata(spi)) { + dev_err(&spi->dev, "is already associated\n"); + return -EBUSY; + } + + /* check word size */ + if (!spi->bits_per_word) { + dev_err(&spi->dev, "No bits_per_word defined\n"); + return -EINVAL; + } + + /* check maximum SPI clk rate */ + if (!spi->max_speed_hz) { + dev_err(&spi->dev, "No max speed HZ parameter\n"); + return -EINVAL; + } + + if (spi->master->max_speed_hz < spi->max_speed_hz) { + dev_err(&spi->dev, "max speed %u HZ is too high\n", + spi->max_speed_hz); + return -EINVAL; + } + + sqi = spi_master_get_devdata(spi->master); + spi_set_ctldata(spi, (void *)sqi); + + return 0; +} + +static void pic32_sqi_cleanup(struct spi_device *spi) +{ + spi_set_ctldata(spi, (void *)NULL); +} + +static int ring_desc_ring_alloc(struct pic32_sqi *sqi) +{ + struct ring_desc *rdesc; + struct buf_desc *bd; + int i; + + /* allocate coherent DMAable memory for hardware buffer descriptors. */ + sqi->bd = dma_zalloc_coherent(&sqi->master->dev, + sizeof(*bd) * PESQI_BD_COUNT, + &sqi->bd_dma, GFP_DMA32); + if (!sqi->bd) { + dev_err(&sqi->master->dev, "failed allocating dma buffer\n"); + return -ENOMEM; + } + + /* allocate software ring descriptors */ + sqi->ring = kcalloc(PESQI_BD_COUNT, sizeof(*rdesc), GFP_KERNEL); + if (!sqi->ring) { + dma_free_coherent(&sqi->master->dev, + sizeof(*bd) * PESQI_BD_COUNT, + sqi->bd, sqi->bd_dma); + return -ENOMEM; + } + + bd = (struct buf_desc *)sqi->bd; + + INIT_LIST_HEAD(&sqi->bd_list_free); + INIT_LIST_HEAD(&sqi->bd_list_used); + + /* initialize ring-desc */ + for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT; i++, rdesc++) { + INIT_LIST_HEAD(&rdesc->list); + rdesc->bd = &bd[i]; + rdesc->bd_dma = sqi->bd_dma + (void *)&bd[i] - (void *)bd; + list_add_tail(&rdesc->list, &sqi->bd_list_free); + } + + /* Prepare BD: chain to next BD(s) */ + for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT; i++) + bd[i].bd_nextp = rdesc[i + 1].bd_dma; + bd[PESQI_BD_COUNT - 1].bd_nextp = 0; + + return 0; +} + +static void ring_desc_ring_free(struct pic32_sqi *sqi) +{ + dma_free_coherent(&sqi->master->dev, + sizeof(struct buf_desc) * PESQI_BD_COUNT, + sqi->bd, sqi->bd_dma); + kfree(sqi->ring); +} + +static void pic32_sqi_hw_init(struct pic32_sqi *sqi) +{ + unsigned long flags; + u32 val; + + /* Soft-reset of PESQI controller triggers interrupt. + * We are not yet ready to handle them so disable CPU + * interrupt for the time being. + */ + local_irq_save(flags); + + /* assert soft-reset */ + writel(PESQI_SOFT_RESET, sqi->regs + PESQI_CONF_REG); + + /* wait until clear */ + readl_poll_timeout_atomic(sqi->regs + PESQI_CONF_REG, val, + !(val & PESQI_SOFT_RESET), 1, 5000); + + /* disable all interrupts */ + pic32_sqi_disable_int(sqi); + + /* Now it is safe to enable back CPU interrupt */ + local_irq_restore(flags); + + /* tx and rx fifo interrupt threshold */ + val = readl(sqi->regs + PESQI_CMD_THRES_REG); + val &= ~(PESQI_TXTHR_MASK << PESQI_TXTHR_SHIFT); + val &= ~(PESQI_RXTHR_MASK << PESQI_RXTHR_SHIFT); + val |= (1U << PESQI_TXTHR_SHIFT) | (1U << PESQI_RXTHR_SHIFT); + writel(val, sqi->regs + PESQI_CMD_THRES_REG); + + val = readl(sqi->regs + PESQI_INT_THRES_REG); + val &= ~(PESQI_TXTHR_MASK << PESQI_TXTHR_SHIFT); + val &= ~(PESQI_RXTHR_MASK << PESQI_RXTHR_SHIFT); + val |= (1U << PESQI_TXTHR_SHIFT) | (1U << PESQI_RXTHR_SHIFT); + writel(val, sqi->regs + PESQI_INT_THRES_REG); + + /* default configuration */ + val = readl(sqi->regs + PESQI_CONF_REG); + + /* set mode: DMA */ + val &= ~PESQI_MODE; + val |= PESQI_MODE_DMA << PESQI_MODE_SHIFT; + writel(val, sqi->regs + PESQI_CONF_REG); + + /* DATAEN - SQIID0-ID3 */ + val |= PESQI_QUAD_LANE << PESQI_LANES_SHIFT; + + /* burst/INCR4 enable */ + val |= PESQI_BURST_EN; + + /* CSEN - all CS */ + val |= 3U << PESQI_CSEN_SHIFT; + writel(val, sqi->regs + PESQI_CONF_REG); + + /* write poll count */ + writel(0, sqi->regs + PESQI_BD_POLL_CTRL_REG); + + sqi->cur_speed = 0; + sqi->cur_mode = -1; +} + +static int pic32_sqi_probe(struct platform_device *pdev) +{ + struct spi_master *master; + struct pic32_sqi *sqi; + struct resource *reg; + int ret; + + master = spi_alloc_master(&pdev->dev, sizeof(*sqi)); + if (!master) + return -ENOMEM; + + sqi = spi_master_get_devdata(master); + sqi->master = master; + + reg = platform_get_resource(pdev, IORESOURCE_MEM, 0); + sqi->regs = devm_ioremap_resource(&pdev->dev, reg); + if (IS_ERR(sqi->regs)) { + ret = PTR_ERR(sqi->regs); + goto err_free_master; + } + + /* irq */ + sqi->irq = platform_get_irq(pdev, 0); + if (sqi->irq < 0) { + dev_err(&pdev->dev, "no irq found\n"); + ret = sqi->irq; + goto err_free_master; + } + + /* clocks */ + sqi->sys_clk = devm_clk_get(&pdev->dev, "reg_ck"); + if (IS_ERR(sqi->sys_clk)) { + ret = PTR_ERR(sqi->sys_clk); + dev_err(&pdev->dev, "no sys_clk ?\n"); + goto err_free_master; + } + + sqi->base_clk = devm_clk_get(&pdev->dev, "spi_ck"); + if (IS_ERR(sqi->base_clk)) { + ret = PTR_ERR(sqi->base_clk); + dev_err(&pdev->dev, "no base clk ?\n"); + goto err_free_master; + } + + ret = clk_prepare_enable(sqi->sys_clk); + if (ret) { + dev_err(&pdev->dev, "sys clk enable failed\n"); + goto err_free_master; + } + + ret = clk_prepare_enable(sqi->base_clk); + if (ret) { + dev_err(&pdev->dev, "base clk enable failed\n"); + clk_disable_unprepare(sqi->sys_clk); + goto err_free_master; + } + + init_completion(&sqi->xfer_done); + + /* initialize hardware */ + pic32_sqi_hw_init(sqi); + + /* allocate buffers & descriptors */ + ret = ring_desc_ring_alloc(sqi); + if (ret) { + dev_err(&pdev->dev, "ring alloc failed\n"); + goto err_disable_clk; + } + + /* install irq handlers */ + ret = request_irq(sqi->irq, pic32_sqi_isr, 0, + dev_name(&pdev->dev), sqi); + if (ret < 0) { + dev_err(&pdev->dev, "request_irq(%d), failed\n", sqi->irq); + goto err_free_ring; + } + + /* register master */ + master->num_chipselect = 2; + master->max_speed_hz = clk_get_rate(sqi->base_clk); + master->dma_alignment = 32; + master->max_dma_len = PESQI_BD_BUF_LEN_MAX; + master->dev.of_node = of_node_get(pdev->dev.of_node); + master->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_TX_DUAL | + SPI_RX_DUAL | SPI_TX_QUAD | SPI_RX_QUAD; + master->flags = SPI_MASTER_HALF_DUPLEX; + master->setup = pic32_sqi_setup; + master->cleanup = pic32_sqi_cleanup; + master->can_dma = pic32_sqi_can_dma; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); + master->transfer_one_message = pic32_sqi_one_message; + master->prepare_transfer_hardware = pic32_sqi_prepare_hardware; + master->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware; + + ret = devm_spi_register_master(&pdev->dev, master); + if (ret) { + dev_err(&master->dev, "failed registering spi master\n"); + free_irq(sqi->irq, sqi); + goto err_free_ring; + } + + platform_set_drvdata(pdev, sqi); + + return 0; + +err_free_ring: + ring_desc_ring_free(sqi); + +err_disable_clk: + clk_disable_unprepare(sqi->base_clk); + clk_disable_unprepare(sqi->sys_clk); + +err_free_master: + spi_master_put(master); + return ret; +} + +static int pic32_sqi_remove(struct platform_device *pdev) +{ + struct pic32_sqi *sqi = platform_get_drvdata(pdev); + + /* release resources */ + free_irq(sqi->irq, sqi); + ring_desc_ring_free(sqi); + + /* disable clk */ + clk_disable_unprepare(sqi->base_clk); + clk_disable_unprepare(sqi->sys_clk); + + return 0; +} + +static const struct of_device_id pic32_sqi_of_ids[] = { + {.compatible = "microchip,pic32mzda-sqi",}, + {}, +}; +MODULE_DEVICE_TABLE(of, pic32_sqi_of_ids); + +static struct platform_driver pic32_sqi_driver = { + .driver = { + .name = "sqi-pic32", + .of_match_table = of_match_ptr(pic32_sqi_of_ids), + }, + .probe = pic32_sqi_probe, + .remove = pic32_sqi_remove, +}; + +module_platform_driver(pic32_sqi_driver); + +MODULE_AUTHOR("Purna Chandra Mandal "); +MODULE_DESCRIPTION("Microchip SPI driver for PIC32 SQI controller."); +MODULE_LICENSE("GPL v2"); -- GitLab From 99cf3af5e2d5c74e016ae9517a4dced3f1dbcf6a Mon Sep 17 00:00:00 2001 From: James Ban Date: Fri, 15 Apr 2016 13:34:22 +0900 Subject: [PATCH 3243/9938] regulator: pv88080: new regulator driver This is the driver for the Powerventure PV88080 BUCKs regulator. It communicates via an I2C bus to the device. Signed-off-by: James Ban Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/pv88080.txt | 49 ++ drivers/regulator/Kconfig | 7 + drivers/regulator/Makefile | 1 + drivers/regulator/pv88080-regulator.c | 419 ++++++++++++++++++ drivers/regulator/pv88080-regulator.h | 92 ++++ 5 files changed, 568 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/pv88080.txt create mode 100644 drivers/regulator/pv88080-regulator.c create mode 100644 drivers/regulator/pv88080-regulator.h diff --git a/Documentation/devicetree/bindings/regulator/pv88080.txt b/Documentation/devicetree/bindings/regulator/pv88080.txt new file mode 100644 index 000000000000..38a614210dcb --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/pv88080.txt @@ -0,0 +1,49 @@ +* Powerventure Semiconductor PV88080 Voltage Regulator + +Required properties: +- compatible: "pvs,pv88080". +- reg: I2C slave address, usually 0x49. +- interrupts: the interrupt outputs of the controller +- regulators: A node that houses a sub-node for each regulator within the + device. Each sub-node is identified using the node's name, with valid + values listed below. The content of each sub-node is defined by the + standard binding for regulators; see regulator.txt. + BUCK1, BUCK2, and BUCK3. + +Optional properties: +- Any optional property defined in regulator.txt + +Example + + pmic: pv88080@49 { + compatible = "pvs,pv88080"; + reg = <0x49>; + interrupt-parent = <&gpio>; + interrupts = <24 24>; + + regulators { + BUCK1 { + regulator-name = "buck1"; + regulator-min-microvolt = < 600000>; + regulator-max-microvolt = <1393750>; + regulator-min-microamp = < 220000>; + regulator-max-microamp = <7040000>; + }; + + BUCK2 { + regulator-name = "buck2"; + regulator-min-microvolt = < 600000>; + regulator-max-microvolt = <1393750>; + regulator-min-microamp = <1496000>; + regulator-max-microamp = <4189000>; + }; + + BUCK3 { + regulator-name = "buck3"; + regulator-min-microvolt = <1400000>; + regulator-max-microvolt = <2193750>; + regulator-min-microamp = <1496000>; + regulator-max-microamp = <4189000>; + }; + }; + }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c77dc08b1202..0b616e2192cc 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -548,6 +548,13 @@ config REGULATOR_PV88060 Say y here to support the voltage regulators and convertors PV88060 +config REGULATOR_PV88080 + tristate "Powerventure Semiconductor PV88080 regulator" + depends on I2C + select REGMAP_I2C + help + Say y here to support the buck convertors on PV88080 + config REGULATOR_PV88090 tristate "Powerventure Semiconductor PV88090 regulator" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 61bfbb9d4a0c..2f6f9f862aea 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o obj-$(CONFIG_REGULATOR_PV88060) += pv88060-regulator.o +obj-$(CONFIG_REGULATOR_PV88080) += pv88080-regulator.o obj-$(CONFIG_REGULATOR_PV88090) += pv88090-regulator.o obj-$(CONFIG_REGULATOR_PWM) += pwm-regulator.o obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c new file mode 100644 index 000000000000..d7107566c429 --- /dev/null +++ b/drivers/regulator/pv88080-regulator.c @@ -0,0 +1,419 @@ +/* + * pv88080-regulator.c - Regulator device driver for PV88080 + * Copyright (C) 2016 Powerventure Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pv88080-regulator.h" + +#define PV88080_MAX_REGULATORS 3 + +/* PV88080 REGULATOR IDs */ +enum { + /* BUCKs */ + PV88080_ID_BUCK1, + PV88080_ID_BUCK2, + PV88080_ID_BUCK3, +}; + +struct pv88080_regulator { + struct regulator_desc desc; + /* Current limiting */ + unsigned int n_current_limits; + const int *current_limits; + unsigned int limit_mask; + unsigned int conf; + unsigned int conf2; + unsigned int conf5; +}; + +struct pv88080 { + struct device *dev; + struct regmap *regmap; + struct regulator_dev *rdev[PV88080_MAX_REGULATORS]; +}; + +struct pv88080_buck_voltage { + int min_uV; + int max_uV; + int uV_step; +}; + +static const struct regmap_config pv88080_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +/* Current limits array (in uA) for BUCK1, BUCK2, BUCK3. + * Entry indexes corresponds to register values. + */ + +static const int pv88080_buck1_limits[] = { + 3230000, 5130000, 6960000, 8790000 +}; + +static const int pv88080_buck23_limits[] = { + 1496000, 2393000, 3291000, 4189000 +}; + +static const struct pv88080_buck_voltage pv88080_buck_vol[2] = { + { + .min_uV = 600000, + .max_uV = 1393750, + .uV_step = 6250, + }, + { + .min_uV = 1400000, + .max_uV = 2193750, + .uV_step = 6250, + }, +}; + +static unsigned int pv88080_buck_get_mode(struct regulator_dev *rdev) +{ + struct pv88080_regulator *info = rdev_get_drvdata(rdev); + unsigned int data; + int ret, mode = 0; + + ret = regmap_read(rdev->regmap, info->conf, &data); + if (ret < 0) + return ret; + + switch (data & PV88080_BUCK1_MODE_MASK) { + case PV88080_BUCK_MODE_SYNC: + mode = REGULATOR_MODE_FAST; + break; + case PV88080_BUCK_MODE_AUTO: + mode = REGULATOR_MODE_NORMAL; + break; + case PV88080_BUCK_MODE_SLEEP: + mode = REGULATOR_MODE_STANDBY; + break; + default: + return -EINVAL; + } + + return mode; +} + +static int pv88080_buck_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct pv88080_regulator *info = rdev_get_drvdata(rdev); + int val = 0; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = PV88080_BUCK_MODE_SYNC; + break; + case REGULATOR_MODE_NORMAL: + val = PV88080_BUCK_MODE_AUTO; + break; + case REGULATOR_MODE_STANDBY: + val = PV88080_BUCK_MODE_SLEEP; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, info->conf, + PV88080_BUCK1_MODE_MASK, val); +} + +static int pv88080_set_current_limit(struct regulator_dev *rdev, int min, + int max) +{ + struct pv88080_regulator *info = rdev_get_drvdata(rdev); + int i; + + /* search for closest to maximum */ + for (i = info->n_current_limits; i >= 0; i--) { + if (min <= info->current_limits[i] + && max >= info->current_limits[i]) { + return regmap_update_bits(rdev->regmap, + info->conf, + info->limit_mask, + i << PV88080_BUCK1_ILIM_SHIFT); + } + } + + return -EINVAL; +} + +static int pv88080_get_current_limit(struct regulator_dev *rdev) +{ + struct pv88080_regulator *info = rdev_get_drvdata(rdev); + unsigned int data; + int ret; + + ret = regmap_read(rdev->regmap, info->conf, &data); + if (ret < 0) + return ret; + + data = (data & info->limit_mask) >> PV88080_BUCK1_ILIM_SHIFT; + return info->current_limits[data]; +} + +static struct regulator_ops pv88080_buck_ops = { + .get_mode = pv88080_buck_get_mode, + .set_mode = pv88080_buck_set_mode, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear, + .set_current_limit = pv88080_set_current_limit, + .get_current_limit = pv88080_get_current_limit, +}; + +#define PV88080_BUCK(chip, regl_name, min, step, max, limits_array) \ +{\ + .desc = {\ + .id = chip##_ID_##regl_name,\ + .name = __stringify(chip##_##regl_name),\ + .of_match = of_match_ptr(#regl_name),\ + .regulators_node = of_match_ptr("regulators"),\ + .type = REGULATOR_VOLTAGE,\ + .owner = THIS_MODULE,\ + .ops = &pv88080_buck_ops,\ + .min_uV = min, \ + .uV_step = step, \ + .n_voltages = ((max) - (min))/(step) + 1, \ + .enable_reg = PV88080_REG_##regl_name##_CONF0, \ + .enable_mask = PV88080_##regl_name##_EN, \ + .vsel_reg = PV88080_REG_##regl_name##_CONF0, \ + .vsel_mask = PV88080_V##regl_name##_MASK, \ + },\ + .current_limits = limits_array, \ + .n_current_limits = ARRAY_SIZE(limits_array), \ + .limit_mask = PV88080_##regl_name##_ILIM_MASK, \ + .conf = PV88080_REG_##regl_name##_CONF1, \ + .conf2 = PV88080_REG_##regl_name##_CONF2, \ + .conf5 = PV88080_REG_##regl_name##_CONF5, \ +} + +static struct pv88080_regulator pv88080_regulator_info[] = { + PV88080_BUCK(PV88080, BUCK1, 600000, 6250, 1393750, + pv88080_buck1_limits), + PV88080_BUCK(PV88080, BUCK2, 600000, 6250, 1393750, + pv88080_buck23_limits), + PV88080_BUCK(PV88080, BUCK3, 600000, 6250, 1393750, + pv88080_buck23_limits), +}; + +static irqreturn_t pv88080_irq_handler(int irq, void *data) +{ + struct pv88080 *chip = data; + int i, reg_val, err, ret = IRQ_NONE; + + err = regmap_read(chip->regmap, PV88080_REG_EVENT_A, ®_val); + if (err < 0) + goto error_i2c; + + if (reg_val & PV88080_E_VDD_FLT) { + for (i = 0; i < PV88080_MAX_REGULATORS; i++) { + if (chip->rdev[i] != NULL) { + regulator_notifier_call_chain(chip->rdev[i], + REGULATOR_EVENT_UNDER_VOLTAGE, + NULL); + } + } + + err = regmap_write(chip->regmap, PV88080_REG_EVENT_A, + PV88080_E_VDD_FLT); + if (err < 0) + goto error_i2c; + + ret = IRQ_HANDLED; + } + + if (reg_val & PV88080_E_OVER_TEMP) { + for (i = 0; i < PV88080_MAX_REGULATORS; i++) { + if (chip->rdev[i] != NULL) { + regulator_notifier_call_chain(chip->rdev[i], + REGULATOR_EVENT_OVER_TEMP, + NULL); + } + } + + err = regmap_write(chip->regmap, PV88080_REG_EVENT_A, + PV88080_E_OVER_TEMP); + if (err < 0) + goto error_i2c; + + ret = IRQ_HANDLED; + } + + return ret; + +error_i2c: + dev_err(chip->dev, "I2C error : %d\n", err); + return IRQ_NONE; +} + +/* + * I2C driver interface functions + */ +static int pv88080_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); + struct pv88080 *chip; + struct regulator_config config = { }; + int i, error, ret; + unsigned int conf2, conf5; + + chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88080), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = &i2c->dev; + chip->regmap = devm_regmap_init_i2c(i2c, &pv88080_regmap_config); + if (IS_ERR(chip->regmap)) { + error = PTR_ERR(chip->regmap); + dev_err(chip->dev, "Failed to allocate register map: %d\n", + error); + return error; + } + + i2c_set_clientdata(i2c, chip); + + if (i2c->irq != 0) { + ret = regmap_write(chip->regmap, PV88080_REG_MASK_A, 0xFF); + if (ret < 0) { + dev_err(chip->dev, + "Failed to mask A reg: %d\n", ret); + return ret; + } + ret = regmap_write(chip->regmap, PV88080_REG_MASK_B, 0xFF); + if (ret < 0) { + dev_err(chip->dev, + "Failed to mask B reg: %d\n", ret); + return ret; + } + ret = regmap_write(chip->regmap, PV88080_REG_MASK_C, 0xFF); + if (ret < 0) { + dev_err(chip->dev, + "Failed to mask C reg: %d\n", ret); + return ret; + } + + ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, + pv88080_irq_handler, + IRQF_TRIGGER_LOW|IRQF_ONESHOT, + "pv88080", chip); + if (ret != 0) { + dev_err(chip->dev, "Failed to request IRQ: %d\n", + i2c->irq); + return ret; + } + + ret = regmap_update_bits(chip->regmap, PV88080_REG_MASK_A, + PV88080_M_VDD_FLT | PV88080_M_OVER_TEMP, 0); + if (ret < 0) { + dev_err(chip->dev, + "Failed to update mask reg: %d\n", ret); + return ret; + } + + } else { + dev_warn(chip->dev, "No IRQ configured\n"); + } + + config.dev = chip->dev; + config.regmap = chip->regmap; + + for (i = 0; i < PV88080_MAX_REGULATORS; i++) { + if (init_data) + config.init_data = &init_data[i]; + + ret = regmap_read(chip->regmap, + pv88080_regulator_info[i].conf2, &conf2); + if (ret < 0) + return ret; + + conf2 = ((conf2 >> PV88080_BUCK_VDAC_RANGE_SHIFT) & + PV88080_BUCK_VDAC_RANGE_MASK); + + ret = regmap_read(chip->regmap, + pv88080_regulator_info[i].conf5, &conf5); + if (ret < 0) + return ret; + + conf5 = ((conf5 >> PV88080_BUCK_VRANGE_GAIN_SHIFT) & + PV88080_BUCK_VRANGE_GAIN_MASK); + + pv88080_regulator_info[i].desc.min_uV = + pv88080_buck_vol[conf2].min_uV * (conf5+1); + pv88080_regulator_info[i].desc.uV_step = + pv88080_buck_vol[conf2].uV_step * (conf5+1); + pv88080_regulator_info[i].desc.n_voltages = + ((pv88080_buck_vol[conf2].max_uV * (conf5+1)) + - (pv88080_regulator_info[i].desc.min_uV)) + /(pv88080_regulator_info[i].desc.uV_step) + 1; + + config.driver_data = (void *)&pv88080_regulator_info[i]; + chip->rdev[i] = devm_regulator_register(chip->dev, + &pv88080_regulator_info[i].desc, &config); + if (IS_ERR(chip->rdev[i])) { + dev_err(chip->dev, + "Failed to register PV88080 regulator\n"); + return PTR_ERR(chip->rdev[i]); + } + } + + return 0; +} + +static const struct i2c_device_id pv88080_i2c_id[] = { + {"pv88080", 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id); + +#ifdef CONFIG_OF +static const struct of_device_id pv88080_dt_ids[] = { + { .compatible = "pvs,pv88080", .data = &pv88080_i2c_id[0] }, + {}, +}; +MODULE_DEVICE_TABLE(of, pv88080_dt_ids); +#endif + +static struct i2c_driver pv88080_regulator_driver = { + .driver = { + .name = "pv88080", + .of_match_table = of_match_ptr(pv88080_dt_ids), + }, + .probe = pv88080_i2c_probe, + .id_table = pv88080_i2c_id, +}; + +module_i2c_driver(pv88080_regulator_driver); + +MODULE_AUTHOR("James Ban "); +MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88080"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/pv88080-regulator.h b/drivers/regulator/pv88080-regulator.h new file mode 100644 index 000000000000..5e9afde606f4 --- /dev/null +++ b/drivers/regulator/pv88080-regulator.h @@ -0,0 +1,92 @@ +/* + * pv88080-regulator.h - Regulator definitions for PV88080 + * Copyright (C) 2016 Powerventure Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __PV88080_REGISTERS_H__ +#define __PV88080_REGISTERS_H__ + +/* System Control and Event Registers */ +#define PV88080_REG_EVENT_A 0x04 +#define PV88080_REG_MASK_A 0x09 +#define PV88080_REG_MASK_B 0x0a +#define PV88080_REG_MASK_C 0x0b + +/* Regulator Registers */ +#define PV88080_REG_BUCK1_CONF0 0x27 +#define PV88080_REG_BUCK1_CONF1 0x28 +#define PV88080_REG_BUCK1_CONF2 0x59 +#define PV88080_REG_BUCK1_CONF5 0x5c +#define PV88080_REG_BUCK2_CONF0 0x29 +#define PV88080_REG_BUCK2_CONF1 0x2a +#define PV88080_REG_BUCK2_CONF2 0x61 +#define PV88080_REG_BUCK2_CONF5 0x64 +#define PV88080_REG_BUCK3_CONF0 0x2b +#define PV88080_REG_BUCK3_CONF1 0x2c +#define PV88080_REG_BUCK3_CONF2 0x69 +#define PV88080_REG_BUCK3_CONF5 0x6c + +/* PV88080_REG_EVENT_A (addr=0x04) */ +#define PV88080_E_VDD_FLT 0x01 +#define PV88080_E_OVER_TEMP 0x02 + +/* PV88080_REG_MASK_A (addr=0x09) */ +#define PV88080_M_VDD_FLT 0x01 +#define PV88080_M_OVER_TEMP 0x02 + +/* PV88080_REG_BUCK1_CONF0 (addr=0x27) */ +#define PV88080_BUCK1_EN 0x80 +#define PV88080_VBUCK1_MASK 0x7F +/* PV88080_REG_BUCK2_CONF0 (addr=0x29) */ +#define PV88080_BUCK2_EN 0x80 +#define PV88080_VBUCK2_MASK 0x7F +/* PV88080_REG_BUCK3_CONF0 (addr=0x2b) */ +#define PV88080_BUCK3_EN 0x80 +#define PV88080_VBUCK3_MASK 0x7F + +/* PV88080_REG_BUCK1_CONF1 (addr=0x28) */ +#define PV88080_BUCK1_ILIM_SHIFT 2 +#define PV88080_BUCK1_ILIM_MASK 0x0C +#define PV88080_BUCK1_MODE_MASK 0x03 + +/* PV88080_REG_BUCK2_CONF1 (addr=0x2a) */ +#define PV88080_BUCK2_ILIM_SHIFT 2 +#define PV88080_BUCK2_ILIM_MASK 0x0C +#define PV88080_BUCK2_MODE_MASK 0x03 + +/* PV88080_REG_BUCK3_CONF1 (addr=0x2c) */ +#define PV88080_BUCK3_ILIM_SHIFT 2 +#define PV88080_BUCK3_ILIM_MASK 0x0C +#define PV88080_BUCK3_MODE_MASK 0x03 + +#define PV88080_BUCK_MODE_SLEEP 0x00 +#define PV88080_BUCK_MODE_AUTO 0x01 +#define PV88080_BUCK_MODE_SYNC 0x02 + +/* PV88080_REG_BUCK2_CONF2 (addr=0x61) */ +/* PV88080_REG_BUCK3_CONF2 (addr=0x69) */ +#define PV88080_BUCK_VDAC_RANGE_SHIFT 7 +#define PV88080_BUCK_VDAC_RANGE_MASK 0x01 + +#define PV88080_BUCK_VDAC_RANGE_1 0x00 +#define PV88080_BUCK_VDAC_RANGE_2 0x01 + +/* PV88080_REG_BUCK2_CONF5 (addr=0x64) */ +/* PV88080_REG_BUCK3_CONF5 (addr=0x6c) */ +#define PV88080_BUCK_VRANGE_GAIN_SHIFT 0 +#define PV88080_BUCK_VRANGE_GAIN_MASK 0x01 + +#define PV88080_BUCK_VRANGE_GAIN_1 0x00 +#define PV88080_BUCK_VRANGE_GAIN_2 0x01 + +#endif /* __PV88080_REGISTERS_H__ */ -- GitLab From 09184118a8abae030539469848d475adcc0e5839 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 31 Mar 2016 16:36:00 +0300 Subject: [PATCH 3244/9938] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders The hdmi-codec is a platform device driver to be registered from drivers of external HDMI encoders with I2S and/or spdif interface. The driver in turn registers an ASoC codec for the HDMI encoder's audio functionality. The structures and definitions in the API header are mostly redundant copies of similar structures in ASoC headers. This is on purpose to avoid direct dependencies to ASoC structures in video side driver. Signed-off-by: Jyri Sarha Acked-by: Arnaud Pouliquen Acked-by: PC Liao Signed-off-by: Mark Brown --- include/sound/hdmi-codec.h | 100 +++++++++ sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/hdmi-codec.c | 396 ++++++++++++++++++++++++++++++++++ 4 files changed, 504 insertions(+) create mode 100644 include/sound/hdmi-codec.h create mode 100644 sound/soc/codecs/hdmi-codec.c diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h new file mode 100644 index 000000000000..fc3a481ad91e --- /dev/null +++ b/include/sound/hdmi-codec.h @@ -0,0 +1,100 @@ +/* + * hdmi-codec.h - HDMI Codec driver API + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Jyri Sarha + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __HDMI_CODEC_H__ +#define __HDMI_CODEC_H__ + +#include +#include +#include +#include + +/* + * Protocol between ASoC cpu-dai and HDMI-encoder + */ +struct hdmi_codec_daifmt { + enum { + HDMI_I2S, + HDMI_RIGHT_J, + HDMI_LEFT_J, + HDMI_DSP_A, + HDMI_DSP_B, + HDMI_AC97, + HDMI_SPDIF, + } fmt; + int bit_clk_inv:1; + int frame_clk_inv:1; + int bit_clk_master:1; + int frame_clk_master:1; +}; + +/* + * HDMI audio parameters + */ +struct hdmi_codec_params { + struct hdmi_audio_infoframe cea; + struct snd_aes_iec958 iec; + int sample_rate; + int sample_width; + int channels; +}; + +struct hdmi_codec_ops { + /* + * Called when ASoC starts an audio stream setup. + * Optional + */ + int (*audio_startup)(struct device *dev); + + /* + * Configures HDMI-encoder for audio stream. + * Mandatory + */ + int (*hw_params)(struct device *dev, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms); + + /* + * Shuts down the audio stream. + * Mandatory + */ + void (*audio_shutdown)(struct device *dev); + + /* + * Mute/unmute HDMI audio stream. + * Optional + */ + int (*digital_mute)(struct device *dev, bool enable); + + /* + * Provides EDID-Like-Data from connected HDMI device. + * Optional + */ + int (*get_eld)(struct device *dev, uint8_t *buf, size_t len); +}; + +/* HDMI codec initalization data */ +struct hdmi_codec_pdata { + const struct hdmi_codec_ops *ops; + uint i2s:1; + uint spdif:1; + int max_i2s_channels; +}; + +#define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" + +#endif /* __HDMI_CODEC_H__ */ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 649e92a252ae..06d0e0593ec3 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -88,6 +88,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MC13783 if MFD_MC13XXX select SND_SOC_ML26124 if I2C select SND_SOC_NAU8825 if I2C + select SND_SOC_HDMI_CODEC select SND_SOC_PCM1681 if I2C select SND_SOC_PCM179X_I2C if I2C select SND_SOC_PCM179X_SPI if SPI_MASTER @@ -477,6 +478,11 @@ config SND_SOC_BT_SCO config SND_SOC_DMIC tristate +config SND_SOC_HDMI_CODEC + tristate + select SND_PCM_ELD + select SND_PCM_IEC958 + config SND_SOC_ES8328 tristate "Everest Semi ES8328 CODEC" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 185a712a7fe7..d7185dda58b8 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -81,6 +81,7 @@ snd-soc-max9850-objs := max9850.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o snd-soc-nau8825-objs := nau8825.o +snd-soc-hdmi-codec-objs := hdmi-codec.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o @@ -290,6 +291,7 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o +obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o obj-$(CONFIG_SND_SOC_PCM179X_I2C) += snd-soc-pcm179x-i2c.o diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c new file mode 100644 index 000000000000..b46b8edb9319 --- /dev/null +++ b/sound/soc/codecs/hdmi-codec.c @@ -0,0 +1,396 @@ +/* + * ALSA SoC codec for HDMI encoder drivers + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Jyri Sarha + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* This is only to get MAX_ELD_BYTES */ + +struct hdmi_codec_priv { + struct hdmi_codec_pdata hcd; + struct snd_soc_dai_driver *daidrv; + struct hdmi_codec_daifmt daifmt[2]; + struct mutex current_stream_lock; + struct snd_pcm_substream *current_stream; + struct snd_pcm_hw_constraint_list ratec; + uint8_t eld[MAX_ELD_BYTES]; +}; + +static const struct snd_soc_dapm_widget hdmi_widgets[] = { + SND_SOC_DAPM_OUTPUT("TX"), +}; + +static const struct snd_soc_dapm_route hdmi_routes[] = { + { "TX", NULL, "Playback" }, +}; + +enum { + DAI_ID_I2S = 0, + DAI_ID_SPDIF, +}; + +static int hdmi_codec_new_stream(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + int ret = 0; + + mutex_lock(&hcp->current_stream_lock); + if (!hcp->current_stream) { + hcp->current_stream = substream; + } else if (hcp->current_stream != substream) { + dev_err(dai->dev, "Only one simultaneous stream supported!\n"); + ret = -EINVAL; + } + mutex_unlock(&hcp->current_stream_lock); + + return ret; +} + +static int hdmi_codec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + int ret = 0; + + dev_dbg(dai->dev, "%s()\n", __func__); + + ret = hdmi_codec_new_stream(substream, dai); + if (ret) + return ret; + + if (hcp->hcd.ops->audio_startup) { + ret = hcp->hcd.ops->audio_startup(dai->dev->parent); + if (ret) { + mutex_lock(&hcp->current_stream_lock); + hcp->current_stream = NULL; + mutex_unlock(&hcp->current_stream_lock); + return ret; + } + } + + if (hcp->hcd.ops->get_eld) { + ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->eld, + sizeof(hcp->eld)); + + if (!ret) { + ret = snd_pcm_hw_constraint_eld(substream->runtime, + hcp->eld); + if (ret) + return ret; + } + } + return 0; +} + +static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + + dev_dbg(dai->dev, "%s()\n", __func__); + + WARN_ON(hcp->current_stream != substream); + + hcp->hcd.ops->audio_shutdown(dai->dev->parent); + + mutex_lock(&hcp->current_stream_lock); + hcp->current_stream = NULL; + mutex_unlock(&hcp->current_stream_lock); +} + +static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + struct hdmi_codec_params hp = { + .iec = { + .status = { 0 }, + .subcode = { 0 }, + .pad = 0, + .dig_subframe = { 0 }, + } + }; + int ret; + + dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, + params_width(params), params_rate(params), + params_channels(params)); + + if (params_width(params) > 24) + params->msbits = 24; + + ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status, + sizeof(hp.iec.status)); + if (ret < 0) { + dev_err(dai->dev, "Creating IEC958 channel status failed %d\n", + ret); + return ret; + } + + ret = hdmi_codec_new_stream(substream, dai); + if (ret) + return ret; + + hdmi_audio_infoframe_init(&hp.cea); + hp.cea.channels = params_channels(params); + hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; + hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; + hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; + + hp.sample_width = params_width(params); + hp.sample_rate = params_rate(params); + hp.channels = params_channels(params); + + return hcp->hcd.ops->hw_params(dai->dev->parent, &hcp->daifmt[dai->id], + &hp); +} + +static int hdmi_codec_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt) +{ + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + struct hdmi_codec_daifmt cf = { 0 }; + int ret = 0; + + dev_dbg(dai->dev, "%s()\n", __func__); + + if (dai->id == DAI_ID_SPDIF) { + cf.fmt = HDMI_SPDIF; + } else { + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + cf.bit_clk_master = 1; + cf.frame_clk_master = 1; + break; + case SND_SOC_DAIFMT_CBS_CFM: + cf.frame_clk_master = 1; + break; + case SND_SOC_DAIFMT_CBM_CFS: + cf.bit_clk_master = 1; + break; + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + cf.frame_clk_inv = 1; + break; + case SND_SOC_DAIFMT_IB_NF: + cf.bit_clk_inv = 1; + break; + case SND_SOC_DAIFMT_IB_IF: + cf.frame_clk_inv = 1; + cf.bit_clk_inv = 1; + break; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + cf.fmt = HDMI_I2S; + break; + case SND_SOC_DAIFMT_DSP_A: + cf.fmt = HDMI_DSP_A; + break; + case SND_SOC_DAIFMT_DSP_B: + cf.fmt = HDMI_DSP_B; + break; + case SND_SOC_DAIFMT_RIGHT_J: + cf.fmt = HDMI_RIGHT_J; + break; + case SND_SOC_DAIFMT_LEFT_J: + cf.fmt = HDMI_LEFT_J; + break; + case SND_SOC_DAIFMT_AC97: + cf.fmt = HDMI_AC97; + break; + default: + dev_err(dai->dev, "Invalid DAI interface format\n"); + return -EINVAL; + } + } + + hcp->daifmt[dai->id] = cf; + + return ret; +} + +static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); + + dev_dbg(dai->dev, "%s()\n", __func__); + + if (hcp->hcd.ops->digital_mute) + return hcp->hcd.ops->digital_mute(dai->dev->parent, mute); + + return 0; +} + +static const struct snd_soc_dai_ops hdmi_dai_ops = { + .startup = hdmi_codec_startup, + .shutdown = hdmi_codec_shutdown, + .hw_params = hdmi_codec_hw_params, + .set_fmt = hdmi_codec_set_fmt, + .digital_mute = hdmi_codec_digital_mute, +}; + + +#define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) + +/* + * This list is only for formats allowed on the I2S bus. So there is + * some formats listed that are not supported by HDMI interface. For + * instance allowing the 32-bit formats enables 24-precision with CPU + * DAIs that do not support 24-bit formats. If the extra formats cause + * problems, we should add the video side driver an option to disable + * them. + */ +#define I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) + +static struct snd_soc_dai_driver hdmi_i2s_dai = { + .name = "i2s-hifi", + .id = DAI_ID_I2S, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 8, + .rates = HDMI_RATES, + .formats = I2S_FORMATS, + .sig_bits = 24, + }, + .ops = &hdmi_dai_ops, +}; + +static const struct snd_soc_dai_driver hdmi_spdif_dai = { + .name = "spdif-hifi", + .id = DAI_ID_SPDIF, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = HDMI_RATES, + .formats = SPDIF_FORMATS, + }, + .ops = &hdmi_dai_ops, +}; + +static struct snd_soc_codec_driver hdmi_codec = { + .dapm_widgets = hdmi_widgets, + .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), + .dapm_routes = hdmi_routes, + .num_dapm_routes = ARRAY_SIZE(hdmi_routes), +}; + +static int hdmi_codec_probe(struct platform_device *pdev) +{ + struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct hdmi_codec_priv *hcp; + int dai_count, i = 0; + int ret; + + dev_dbg(dev, "%s()\n", __func__); + + if (!hcd) { + dev_err(dev, "%s: No plalform data\n", __func__); + return -EINVAL; + } + + dai_count = hcd->i2s + hcd->spdif; + if (dai_count < 1 || !hcd->ops || !hcd->ops->hw_params || + !hcd->ops->audio_shutdown) { + dev_err(dev, "%s: Invalid parameters\n", __func__); + return -EINVAL; + } + + hcp = devm_kzalloc(dev, sizeof(*hcp), GFP_KERNEL); + if (!hcp) + return -ENOMEM; + + hcp->hcd = *hcd; + mutex_init(&hcp->current_stream_lock); + + hcp->daidrv = devm_kzalloc(dev, dai_count * sizeof(*hcp->daidrv), + GFP_KERNEL); + if (!hcp->daidrv) + return -ENOMEM; + + if (hcd->i2s) { + hcp->daidrv[i] = hdmi_i2s_dai; + hcp->daidrv[i].playback.channels_max = + hcd->max_i2s_channels; + i++; + } + + if (hcd->spdif) + hcp->daidrv[i] = hdmi_spdif_dai; + + ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, + dai_count); + if (ret) { + dev_err(dev, "%s: snd_soc_register_codec() failed (%d)\n", + __func__, ret); + return ret; + } + + dev_set_drvdata(dev, hcp); + return 0; +} + +static int hdmi_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver hdmi_codec_driver = { + .driver = { + .name = HDMI_CODEC_DRV_NAME, + }, + .probe = hdmi_codec_probe, + .remove = hdmi_codec_remove, +}; + +module_platform_driver(hdmi_codec_driver); + +MODULE_AUTHOR("Jyri Sarha "); +MODULE_DESCRIPTION("HDMI Audio Codec Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" HDMI_CODEC_DRV_NAME); -- GitLab From 07c5c3ad98926dc15d31aa86de62fd4170f2a745 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 18 Apr 2016 14:49:53 +0300 Subject: [PATCH 3245/9938] regulator: core: remove lockdep assert from suspend_prepare suspend_prepare can be called during regulator init time also, where the mutex is not locked yet. This causes a false lockdep warning. To avoid the problem, remove the lockdep assertion from the function causing the issue. An alternative would be to lock the mutex during init, but this would cause other problems (some APIs used during init will attempt to lock the mutex also, causing deadlock.) Signed-off-by: Tero Kristo Reported-by: Tomi Valkeinen Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6dd63523bcfe..f28fca4b68e3 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -808,8 +808,6 @@ static int suspend_set_state(struct regulator_dev *rdev, /* locks held by caller */ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) { - lockdep_assert_held_once(&rdev->mutex); - if (!rdev->constraints) return -EINVAL; -- GitLab From 2c30322c4795bf26a74b6049bbea6267a19036a4 Mon Sep 17 00:00:00 2001 From: Askar Safin Date: Mon, 18 Apr 2016 20:30:56 +0300 Subject: [PATCH 3246/9938] documentation: trivial typo: adding-syscalls.txt: s/statat/fstatat/ Signed-off-by: Askar Safin Signed-off-by: Jonathan Corbet --- Documentation/adding-syscalls.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/adding-syscalls.txt b/Documentation/adding-syscalls.txt index cc2d4ac4f404..bbb31e091b28 100644 --- a/Documentation/adding-syscalls.txt +++ b/Documentation/adding-syscalls.txt @@ -136,7 +136,7 @@ an fxyzzy(3) operation for free: - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...) (For more details on the rationale of the *at() calls, see the openat(2) man -page; for an example of AT_EMPTY_PATH, see the statat(2) man page.) +page; for an example of AT_EMPTY_PATH, see the fstatat(2) man page.) If your new xyzzy(2) system call involves a parameter describing an offset within a file, make its type loff_t so that 64-bit offsets can be supported -- GitLab From 110361f41c17d1f565e2fd03a0af044c29e6513a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 18 Apr 2016 11:44:49 +0300 Subject: [PATCH 3247/9938] udp: fix if statement in SIOCINQ ioctl We deleted a line of code and accidentally made the "return put_user()" part of the if statement when it's supposed to be unconditional. Fixes: 9f9a45beaa96 ('udp: do not expect udp headers on ioctl SIOCINQ') Signed-off-by: Dan Carpenter Acked-by: Eric Dumazet Acked-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/ipv4/udp.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index f1863136d3e4..37e09c3dd046 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1276,12 +1276,6 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) { unsigned int amount = first_packet_length(sk); - if (amount) - /* - * We will only return the amount - * of this packet since that is all - * that will be read. - */ return put_user(amount, (int __user *)arg); } -- GitLab From 2a2bbf170054e2525f11e08bb36d4027d76b7bff Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 14 Apr 2016 18:39:39 +0200 Subject: [PATCH 3248/9938] tun: don't require serialization lock on tx The current tun_net_xmit() implementation don't need any external lock since it relies on rcu protection for the tun data structure and on socket queue lock for skb queuing. This patch set the NETIF_F_LLTX feature bit in the tun device, so that on xmit, in absence of qdisc, no serialization lock is acquired by the caller. The user space can remove the default tun qdisc with: tc qdisc replace dev root noqueue Signed-off-by: Paolo Abeni Acked-by: Hannes Frederic Sowa Acked-by: Eric Dumazet Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/tun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index faf9297db2cf..42992dcbdda8 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1796,7 +1796,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; - dev->features = dev->hw_features; + dev->features = dev->hw_features | NETIF_F_LLTX; dev->vlan_features = dev->features & ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX); -- GitLab From b4ef159927150bf1d63f36330bbb5239516ceb69 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 12 Apr 2016 18:14:23 +0200 Subject: [PATCH 3249/9938] netfilter: connlabels: move helpers to xt_connlabel Currently labels can only be set either by iptables connlabel match or via ctnetlink. Before adding nftables set support, clean up the clabel core and move helpers that nft will not need after all to the xtables module. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_labels.h | 1 - net/netfilter/nf_conntrack_labels.c | 19 +------------------ net/netfilter/xt_connlabel.c | 12 +++++++++++- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_labels.h b/include/net/netfilter/nf_conntrack_labels.h index 7e2b1d025f50..51678180e56c 100644 --- a/include/net/netfilter/nf_conntrack_labels.h +++ b/include/net/netfilter/nf_conntrack_labels.h @@ -45,7 +45,6 @@ static inline struct nf_conn_labels *nf_ct_labels_ext_add(struct nf_conn *ct) #endif } -bool nf_connlabel_match(const struct nf_conn *ct, u16 bit); int nf_connlabel_set(struct nf_conn *ct, u16 bit); int nf_connlabels_replace(struct nf_conn *ct, diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c index 3ce5c314ea4b..3a30900891c1 100644 --- a/net/netfilter/nf_conntrack_labels.c +++ b/net/netfilter/nf_conntrack_labels.c @@ -16,28 +16,11 @@ static spinlock_t nf_connlabels_lock; -static unsigned int label_bits(const struct nf_conn_labels *l) -{ - unsigned int longs = l->words; - return longs * BITS_PER_LONG; -} - -bool nf_connlabel_match(const struct nf_conn *ct, u16 bit) -{ - struct nf_conn_labels *labels = nf_ct_labels_find(ct); - - if (!labels) - return false; - - return bit < label_bits(labels) && test_bit(bit, labels->bits); -} -EXPORT_SYMBOL_GPL(nf_connlabel_match); - int nf_connlabel_set(struct nf_conn *ct, u16 bit) { struct nf_conn_labels *labels = nf_ct_labels_find(ct); - if (!labels || bit >= label_bits(labels)) + if (!labels || BIT_WORD(bit) >= labels->words) return -ENOSPC; if (test_bit(bit, labels->bits)) diff --git a/net/netfilter/xt_connlabel.c b/net/netfilter/xt_connlabel.c index bb9cbeb18868..d9b3e535d13a 100644 --- a/net/netfilter/xt_connlabel.c +++ b/net/netfilter/xt_connlabel.c @@ -18,6 +18,16 @@ MODULE_DESCRIPTION("Xtables: add/match connection trackling labels"); MODULE_ALIAS("ipt_connlabel"); MODULE_ALIAS("ip6t_connlabel"); +static bool connlabel_match(const struct nf_conn *ct, u16 bit) +{ + struct nf_conn_labels *labels = nf_ct_labels_find(ct); + + if (!labels) + return false; + + return BIT_WORD(bit) < labels->words && test_bit(bit, labels->bits); +} + static bool connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par) { @@ -33,7 +43,7 @@ connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par) if (info->options & XT_CONNLABEL_OP_SET) return (nf_connlabel_set(ct, info->bit) == 0) ^ invert; - return nf_connlabel_match(ct, info->bit) ^ invert; + return connlabel_match(ct, info->bit) ^ invert; } static int connlabel_mt_check(const struct xt_mtchk_param *par) -- GitLab From 5a8145f7b22269adaf9e98b160a20486d1ad5669 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 12 Apr 2016 18:14:24 +0200 Subject: [PATCH 3250/9938] netfilter: labels: don't emit ct event if labels were not changed make the replace function only send a ctnetlink event if the contents of the new set is different. Otherwise 'ct label set ct label | bar' will cause netlink event storm since we "replace" labels for each packet. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_labels.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c index 3a30900891c1..bd7f26b97ac6 100644 --- a/net/netfilter/nf_conntrack_labels.c +++ b/net/netfilter/nf_conntrack_labels.c @@ -33,14 +33,18 @@ int nf_connlabel_set(struct nf_conn *ct, u16 bit) } EXPORT_SYMBOL_GPL(nf_connlabel_set); -static void replace_u32(u32 *address, u32 mask, u32 new) +static int replace_u32(u32 *address, u32 mask, u32 new) { u32 old, tmp; do { old = *address; tmp = (old & mask) ^ new; + if (old == tmp) + return 0; } while (cmpxchg(address, old, tmp) != old); + + return 1; } int nf_connlabels_replace(struct nf_conn *ct, @@ -49,6 +53,7 @@ int nf_connlabels_replace(struct nf_conn *ct, { struct nf_conn_labels *labels; unsigned int size, i; + int changed = 0; u32 *dst; labels = nf_ct_labels_find(ct); @@ -60,16 +65,15 @@ int nf_connlabels_replace(struct nf_conn *ct, words32 = size / sizeof(u32); dst = (u32 *) labels->bits; - if (words32) { - for (i = 0; i < words32; i++) - replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]); - } + for (i = 0; i < words32; i++) + changed |= replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]); size /= sizeof(u32); for (i = words32; i < size; i++) /* pad */ replace_u32(&dst[i], 0, 0); - nf_conntrack_event_cache(IPCT_LABEL, ct); + if (changed) + nf_conntrack_event_cache(IPCT_LABEL, ct); return 0; } EXPORT_SYMBOL_GPL(nf_connlabels_replace); -- GitLab From adff6c65600000ec2bb71840c943ee12668080f5 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 12 Apr 2016 18:14:25 +0200 Subject: [PATCH 3251/9938] netfilter: connlabels: change nf_connlabels_get bit arg to 'highest used' nf_connlabel_set() takes the bit number that we would like to set. nf_connlabels_get() however took the number of bits that we want to support. So e.g. nf_connlabels_get(32) support bits 0 to 31, but not 32. This changes nf_connlabels_get() to take the highest bit that we want to set. Callers then don't have to cope with a potential integer wrap when using nf_connlabels_get(bit + 1) anymore. Current callers are fine, this change is only to make folloup nft ct label set support simpler. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_labels.h | 4 ++-- net/netfilter/nf_conntrack_labels.c | 9 +++++---- net/netfilter/nft_ct.c | 2 ++ net/netfilter/xt_connlabel.c | 2 +- net/openvswitch/conntrack.c | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_labels.h b/include/net/netfilter/nf_conntrack_labels.h index 51678180e56c..c5f8fc736b3d 100644 --- a/include/net/netfilter/nf_conntrack_labels.h +++ b/include/net/netfilter/nf_conntrack_labels.h @@ -53,11 +53,11 @@ int nf_connlabels_replace(struct nf_conn *ct, #ifdef CONFIG_NF_CONNTRACK_LABELS int nf_conntrack_labels_init(void); void nf_conntrack_labels_fini(void); -int nf_connlabels_get(struct net *net, unsigned int n_bits); +int nf_connlabels_get(struct net *net, unsigned int bit); void nf_connlabels_put(struct net *net); #else static inline int nf_conntrack_labels_init(void) { return 0; } static inline void nf_conntrack_labels_fini(void) {} -static inline int nf_connlabels_get(struct net *net, unsigned int n_bits) { return 0; } +static inline int nf_connlabels_get(struct net *net, unsigned int bit) { return 0; } static inline void nf_connlabels_put(struct net *net) {} #endif diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c index bd7f26b97ac6..252e6a7cd2f1 100644 --- a/net/netfilter/nf_conntrack_labels.c +++ b/net/netfilter/nf_conntrack_labels.c @@ -78,15 +78,14 @@ int nf_connlabels_replace(struct nf_conn *ct, } EXPORT_SYMBOL_GPL(nf_connlabels_replace); -int nf_connlabels_get(struct net *net, unsigned int n_bits) +int nf_connlabels_get(struct net *net, unsigned int bits) { size_t words; - if (n_bits > (NF_CT_LABELS_MAX_SIZE * BITS_PER_BYTE)) + words = BIT_WORD(bits) + 1; + if (words > NF_CT_LABELS_MAX_SIZE / sizeof(long)) return -ERANGE; - words = BITS_TO_LONGS(n_bits); - spin_lock(&nf_connlabels_lock); net->ct.labels_used++; if (words > net->ct.label_words) @@ -115,6 +114,8 @@ static struct nf_ct_ext_type labels_extend __read_mostly = { int nf_conntrack_labels_init(void) { + BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE / sizeof(long) >= U8_MAX); + spin_lock_init(&nf_connlabels_lock); return nf_ct_extend_register(&labels_extend); } diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index d4a4619fcebc..25998facefd0 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -484,6 +484,8 @@ static struct nft_expr_type nft_ct_type __read_mostly = { static int __init nft_ct_module_init(void) { + BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > NFT_REG_SIZE); + return nft_register_expr(&nft_ct_type); } diff --git a/net/netfilter/xt_connlabel.c b/net/netfilter/xt_connlabel.c index d9b3e535d13a..a79af255561a 100644 --- a/net/netfilter/xt_connlabel.c +++ b/net/netfilter/xt_connlabel.c @@ -65,7 +65,7 @@ static int connlabel_mt_check(const struct xt_mtchk_param *par) return ret; } - ret = nf_connlabels_get(par->net, info->bit + 1); + ret = nf_connlabels_get(par->net, info->bit); if (ret < 0) nf_ct_l3proto_module_put(par->family); return ret; diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 1b9d286756be..e5fe24a61f9f 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -1344,7 +1344,7 @@ void ovs_ct_init(struct net *net) unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE; struct ovs_net *ovs_net = net_generic(net, ovs_net_id); - if (nf_connlabels_get(net, n_bits)) { + if (nf_connlabels_get(net, n_bits - 1)) { ovs_net->xt_label = false; OVS_NLERR(true, "Failed to set connlabel length"); } else { -- GitLab From 6d62b4d5fac620ee0ca65dc6d99b0306d96bc541 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Fri, 15 Apr 2016 00:34:59 +0200 Subject: [PATCH 3252/9938] net: ethtool: export conversion function between u32 and link mode The function convert_legacy_u32_to_link_mode and convert_link_mode_to_legacy_u32 may be used outside of ethtool.c. We rename them to ethtool_convert_... and export them, so we could use them in others drivers and modules. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- include/linux/ethtool.h | 7 +++++++ net/core/ethtool.c | 21 ++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index e2b7bf27c03e..9ded8c6d8176 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -150,6 +150,13 @@ extern int __ethtool_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *link_ksettings); +void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, + u32 legacy_u32); + +/* return false if src had higher bits set. lower bits always updated. */ +bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, + const unsigned long *src); + /** * struct ethtool_ops - optional netdev operations * @get_settings: DEPRECATED, use %get_link_ksettings/%set_link_ksettings diff --git a/net/core/ethtool.c b/net/core/ethtool.c index e0cf20a3b3dd..bdb4013581b1 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -391,15 +391,17 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) return 0; } -static void convert_legacy_u32_to_link_mode(unsigned long *dst, u32 legacy_u32) +void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, + u32 legacy_u32) { bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); dst[0] = legacy_u32; } +EXPORT_SYMBOL(ethtool_convert_legacy_u32_to_link_mode); /* return false if src had higher bits set. lower bits always updated. */ -static bool convert_link_mode_to_legacy_u32(u32 *legacy_u32, - const unsigned long *src) +bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, + const unsigned long *src) { bool retval = true; @@ -419,6 +421,7 @@ static bool convert_link_mode_to_legacy_u32(u32 *legacy_u32, *legacy_u32 = src[0]; return retval; } +EXPORT_SYMBOL(ethtool_convert_link_mode_to_legacy_u32); /* return false if legacy contained non-0 deprecated fields * transceiver/maxtxpkt/maxrxpkt. rest of ksettings always updated @@ -441,13 +444,13 @@ convert_legacy_settings_to_link_ksettings( legacy_settings->maxrxpkt) retval = false; - convert_legacy_u32_to_link_mode( + ethtool_convert_legacy_u32_to_link_mode( link_ksettings->link_modes.supported, legacy_settings->supported); - convert_legacy_u32_to_link_mode( + ethtool_convert_legacy_u32_to_link_mode( link_ksettings->link_modes.advertising, legacy_settings->advertising); - convert_legacy_u32_to_link_mode( + ethtool_convert_legacy_u32_to_link_mode( link_ksettings->link_modes.lp_advertising, legacy_settings->lp_advertising); link_ksettings->base.speed @@ -486,13 +489,13 @@ convert_link_ksettings_to_legacy_settings( * __u32 maxrxpkt; */ - retval &= convert_link_mode_to_legacy_u32( + retval &= ethtool_convert_link_mode_to_legacy_u32( &legacy_settings->supported, link_ksettings->link_modes.supported); - retval &= convert_link_mode_to_legacy_u32( + retval &= ethtool_convert_link_mode_to_legacy_u32( &legacy_settings->advertising, link_ksettings->link_modes.advertising); - retval &= convert_link_mode_to_legacy_u32( + retval &= ethtool_convert_link_mode_to_legacy_u32( &legacy_settings->lp_advertising, link_ksettings->link_modes.lp_advertising); ethtool_cmd_speed_set(legacy_settings, link_ksettings->base.speed); -- GitLab From 2d55173e71b06c5a369489852d972304e14189fd Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Fri, 15 Apr 2016 00:35:00 +0200 Subject: [PATCH 3253/9938] phy: add generic function to support ksetting support The old ethtool api (get_setting and set_setting) has generic phy functions phy_ethtool_sset and phy_ethtool_gset. To supprt the new ethtool api (get_link_ksettings and set_link_ksettings), we add generic phy function phy_ethtool_ksettings_get and phy_ethtool_ksettings_set. Signed-off-by: Philippe Reynes Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 81 +++++++++++++++++++++++++++++++++++++++++++ include/linux/phy.h | 4 +++ 2 files changed, 85 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 5590b9c182c9..6f221c8c2a7f 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -362,6 +362,60 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd) } EXPORT_SYMBOL(phy_ethtool_sset); +int phy_ethtool_ksettings_set(struct phy_device *phydev, + const struct ethtool_link_ksettings *cmd) +{ + u8 autoneg = cmd->base.autoneg; + u8 duplex = cmd->base.duplex; + u32 speed = cmd->base.speed; + u32 advertising; + + if (cmd->base.phy_address != phydev->mdio.addr) + return -EINVAL; + + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + + /* We make sure that we don't pass unsupported values in to the PHY */ + advertising &= phydev->supported; + + /* Verify the settings we care about. */ + if (autoneg != AUTONEG_ENABLE && autoneg != AUTONEG_DISABLE) + return -EINVAL; + + if (autoneg == AUTONEG_ENABLE && advertising == 0) + return -EINVAL; + + if (autoneg == AUTONEG_DISABLE && + ((speed != SPEED_1000 && + speed != SPEED_100 && + speed != SPEED_10) || + (duplex != DUPLEX_HALF && + duplex != DUPLEX_FULL))) + return -EINVAL; + + phydev->autoneg = autoneg; + + phydev->speed = speed; + + phydev->advertising = advertising; + + if (autoneg == AUTONEG_ENABLE) + phydev->advertising |= ADVERTISED_Autoneg; + else + phydev->advertising &= ~ADVERTISED_Autoneg; + + phydev->duplex = duplex; + + phydev->mdix = cmd->base.eth_tp_mdix_ctrl; + + /* Restart the PHY */ + phy_start_aneg(phydev); + + return 0; +} +EXPORT_SYMBOL(phy_ethtool_ksettings_set); + int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) { cmd->supported = phydev->supported; @@ -385,6 +439,33 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) } EXPORT_SYMBOL(phy_ethtool_gset); +int phy_ethtool_ksettings_get(struct phy_device *phydev, + struct ethtool_link_ksettings *cmd) +{ + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + phydev->supported); + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + phydev->advertising); + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, + phydev->lp_advertising); + + cmd->base.speed = phydev->speed; + cmd->base.duplex = phydev->duplex; + if (phydev->interface == PHY_INTERFACE_MODE_MOCA) + cmd->base.port = PORT_BNC; + else + cmd->base.port = PORT_MII; + + cmd->base.phy_address = phydev->mdio.addr; + cmd->base.autoneg = phydev->autoneg; + cmd->base.eth_tp_mdix_ctrl = phydev->mdix; + + return 0; +} +EXPORT_SYMBOL(phy_ethtool_ksettings_get); + /** * phy_mii_ioctl - generic PHY MII ioctl interface * @phydev: the phy_device struct diff --git a/include/linux/phy.h b/include/linux/phy.h index 2abd7918f64f..be3f83bbdc0b 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -805,6 +805,10 @@ void phy_start_machine(struct phy_device *phydev); void phy_stop_machine(struct phy_device *phydev); int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd); int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd); +int phy_ethtool_ksettings_get(struct phy_device *phydev, + struct ethtool_link_ksettings *cmd); +int phy_ethtool_ksettings_set(struct phy_device *phydev, + const struct ethtool_link_ksettings *cmd); int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd); int phy_start_interrupts(struct phy_device *phydev); void phy_print_status(struct phy_device *phydev); -- GitLab From 54846f5838d871ad69ebe6eb1999cae3867dabc7 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Fri, 15 Apr 2016 00:35:01 +0200 Subject: [PATCH 3254/9938] fec: move to new ethtool api {get|set}_link_ksettings The ethtool api {get|set}_settings is deprecated. We move the fec driver to new api {get|set}_link_ksettings. Signed-off-by: Philippe Reynes Acked-by: Fugang Duan Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 08243c2ff4b4..bfa10c3da35f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2058,8 +2058,8 @@ static void fec_enet_mii_remove(struct fec_enet_private *fep) } } -static int fec_enet_get_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) +static int fec_enet_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) { struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = fep->phy_dev; @@ -2067,11 +2067,11 @@ static int fec_enet_get_settings(struct net_device *ndev, if (!phydev) return -ENODEV; - return phy_ethtool_gset(phydev, cmd); + return phy_ethtool_ksettings_get(phydev, cmd); } -static int fec_enet_set_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) +static int fec_enet_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) { struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = fep->phy_dev; @@ -2079,7 +2079,7 @@ static int fec_enet_set_settings(struct net_device *ndev, if (!phydev) return -ENODEV; - return phy_ethtool_sset(phydev, cmd); + return phy_ethtool_ksettings_set(phydev, cmd); } static void fec_enet_get_drvinfo(struct net_device *ndev, @@ -2562,8 +2562,6 @@ fec_enet_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) } static const struct ethtool_ops fec_enet_ethtool_ops = { - .get_settings = fec_enet_get_settings, - .set_settings = fec_enet_set_settings, .get_drvinfo = fec_enet_get_drvinfo, .get_regs_len = fec_enet_get_regs_len, .get_regs = fec_enet_get_regs, @@ -2583,6 +2581,8 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { .set_tunable = fec_enet_set_tunable, .get_wol = fec_enet_get_wol, .set_wol = fec_enet_set_wol, + .get_link_ksettings = fec_enet_get_link_ksettings, + .set_link_ksettings = fec_enet_set_link_ksettings, }; static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -- GitLab From 84bf9cefb162b197da20a0f4388929f4b5ba5db4 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Thu, 14 Apr 2016 16:31:54 -0700 Subject: [PATCH 3255/9938] hv_netvsc: Implement support for VF drivers on Hyper-V Support VF drivers on Hyper-V. On Hyper-V, each VF instance presented to the guest has an associated synthetic interface that shares the MAC address with the VF instance. Typically these are bonded together to support live migration. By default, the host delivers all the incoming packets on the synthetic interface. Once the VF is up, we need to explicitly switch the data path on the host to divert traffic onto the VF interface. Even after switching the data path, broadcast and multicast packets are always delivered on the synthetic interface and these will have to be injected back onto the VF interface (if VF is up). This patch implements the necessary support in netvsc to support Linux VF drivers. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 14 ++ drivers/net/hyperv/netvsc.c | 29 +++ drivers/net/hyperv/netvsc_drv.c | 312 +++++++++++++++++++++++++++--- drivers/net/hyperv/rndis_filter.c | 6 + 4 files changed, 335 insertions(+), 26 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 8b3bd8ecd1c4..6700a4dca7c8 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -202,6 +202,8 @@ int rndis_filter_receive(struct hv_device *dev, int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac); +void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf); + #define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) #define NVSP_PROTOCOL_VERSION_1 2 @@ -641,6 +643,12 @@ struct netvsc_reconfig { u32 event; }; +struct garp_wrk { + struct work_struct dwrk; + struct net_device *netdev; + struct netvsc_device *netvsc_dev; +}; + /* The context of the netvsc device */ struct net_device_context { /* point back to our device context */ @@ -656,6 +664,7 @@ struct net_device_context { struct work_struct work; u32 msg_enable; /* debug level */ + struct garp_wrk gwrk; struct netvsc_stats __percpu *tx_stats; struct netvsc_stats __percpu *rx_stats; @@ -730,6 +739,11 @@ struct netvsc_device { u32 vf_alloc; /* Serial number of the VF to team with */ u32 vf_serial; + atomic_t open_cnt; + /* State to manage the associated VF interface. */ + bool vf_inject; + struct net_device *vf_netdev; + atomic_t vf_use_cnt; }; /* NdisInitialize message */ diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index ec313fc08d82..eddce3cdafa8 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -33,6 +33,30 @@ #include "hyperv_net.h" +/* + * Switch the data path from the synthetic interface to the VF + * interface. + */ +void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf) +{ + struct nvsp_message *init_pkt = &nv_dev->channel_init_pkt; + struct hv_device *dev = nv_dev->dev; + + memset(init_pkt, 0, sizeof(struct nvsp_message)); + init_pkt->hdr.msg_type = NVSP_MSG4_TYPE_SWITCH_DATA_PATH; + if (vf) + init_pkt->msg.v4_msg.active_dp.active_datapath = + NVSP_DATAPATH_VF; + else + init_pkt->msg.v4_msg.active_dp.active_datapath = + NVSP_DATAPATH_SYNTHETIC; + + vmbus_sendpacket(dev->channel, init_pkt, + sizeof(struct nvsp_message), + (unsigned long)init_pkt, + VM_PKT_DATA_INBAND, 0); +} + static struct netvsc_device *alloc_net_device(struct hv_device *device) { @@ -52,11 +76,16 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) init_waitqueue_head(&net_device->wait_drain); net_device->start_remove = false; net_device->destroy = false; + atomic_set(&net_device->open_cnt, 0); + atomic_set(&net_device->vf_use_cnt, 0); net_device->dev = device; net_device->ndev = ndev; net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT; + net_device->vf_netdev = NULL; + net_device->vf_inject = false; + hv_set_drvdata(device, net_device); return net_device; } diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index b8121eba33ff..bfdb568ac6b8 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -610,42 +610,24 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, schedule_delayed_work(&ndev_ctx->dwork, 0); } -/* - * netvsc_recv_callback - Callback when we receive a packet from the - * "wire" on the specified device. - */ -int netvsc_recv_callback(struct hv_device *device_obj, + +static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net, struct hv_netvsc_packet *packet, - void **data, struct ndis_tcp_ip_checksum_info *csum_info, - struct vmbus_channel *channel, - u16 vlan_tci) + void *data, u16 vlan_tci) { - struct net_device *net; - struct net_device_context *net_device_ctx; struct sk_buff *skb; - struct netvsc_stats *rx_stats; - net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev; - if (!net || net->reg_state != NETREG_REGISTERED) { - return NVSP_STAT_FAIL; - } - net_device_ctx = netdev_priv(net); - rx_stats = this_cpu_ptr(net_device_ctx->rx_stats); - - /* Allocate a skb - TODO direct I/O to pages? */ skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); - if (unlikely(!skb)) { - ++net->stats.rx_dropped; - return NVSP_STAT_FAIL; - } + if (!skb) + return skb; /* * Copy to skb. This copy is needed here since the memory pointed by * hv_netvsc_packet cannot be deallocated */ - memcpy(skb_put(skb, packet->total_data_buflen), *data, - packet->total_data_buflen); + memcpy(skb_put(skb, packet->total_data_buflen), data, + packet->total_data_buflen); skb->protocol = eth_type_trans(skb, net); if (csum_info) { @@ -663,6 +645,75 @@ int netvsc_recv_callback(struct hv_device *device_obj, __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); + return skb; +} + +/* + * netvsc_recv_callback - Callback when we receive a packet from the + * "wire" on the specified device. + */ +int netvsc_recv_callback(struct hv_device *device_obj, + struct hv_netvsc_packet *packet, + void **data, + struct ndis_tcp_ip_checksum_info *csum_info, + struct vmbus_channel *channel, + u16 vlan_tci) +{ + struct net_device *net; + struct net_device_context *net_device_ctx; + struct sk_buff *skb; + struct sk_buff *vf_skb; + struct netvsc_stats *rx_stats; + struct netvsc_device *netvsc_dev = hv_get_drvdata(device_obj); + u32 bytes_recvd = packet->total_data_buflen; + int ret = 0; + + net = netvsc_dev->ndev; + if (!net || net->reg_state != NETREG_REGISTERED) + return NVSP_STAT_FAIL; + + if (READ_ONCE(netvsc_dev->vf_inject)) { + atomic_inc(&netvsc_dev->vf_use_cnt); + if (!READ_ONCE(netvsc_dev->vf_inject)) { + /* + * We raced; just move on. + */ + atomic_dec(&netvsc_dev->vf_use_cnt); + goto vf_injection_done; + } + + /* + * Inject this packet into the VF inerface. + * On Hyper-V, multicast and brodcast packets + * are only delivered on the synthetic interface + * (after subjecting these to policy filters on + * the host). Deliver these via the VF interface + * in the guest. + */ + vf_skb = netvsc_alloc_recv_skb(netvsc_dev->vf_netdev, packet, + csum_info, *data, vlan_tci); + if (vf_skb != NULL) { + ++netvsc_dev->vf_netdev->stats.rx_packets; + netvsc_dev->vf_netdev->stats.rx_bytes += bytes_recvd; + netif_receive_skb(vf_skb); + } else { + ++net->stats.rx_dropped; + ret = NVSP_STAT_FAIL; + } + atomic_dec(&netvsc_dev->vf_use_cnt); + return ret; + } + +vf_injection_done: + net_device_ctx = netdev_priv(net); + rx_stats = this_cpu_ptr(net_device_ctx->rx_stats); + + /* Allocate a skb - TODO direct I/O to pages? */ + skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci); + if (unlikely(!skb)) { + ++net->stats.rx_dropped; + return NVSP_STAT_FAIL; + } skb_record_rx_queue(skb, channel-> offermsg.offer.sub_channel_index); @@ -1102,6 +1153,175 @@ static void netvsc_free_netdev(struct net_device *netdev) free_netdev(netdev); } +static void netvsc_notify_peers(struct work_struct *wrk) +{ + struct garp_wrk *gwrk; + + gwrk = container_of(wrk, struct garp_wrk, dwrk); + + netdev_notify_peers(gwrk->netdev); + + atomic_dec(&gwrk->netvsc_dev->vf_use_cnt); +} + +static struct netvsc_device *get_netvsc_device(char *mac) +{ + struct net_device *dev; + struct net_device_context *netvsc_ctx = NULL; + int rtnl_locked; + + rtnl_locked = rtnl_trylock(); + + for_each_netdev(&init_net, dev) { + if (memcmp(dev->dev_addr, mac, ETH_ALEN) == 0) { + if (dev->netdev_ops != &device_ops) + continue; + netvsc_ctx = netdev_priv(dev); + break; + } + } + if (rtnl_locked) + rtnl_unlock(); + + if (netvsc_ctx == NULL) + return NULL; + + return hv_get_drvdata(netvsc_ctx->device_ctx); +} + +static int netvsc_register_vf(struct net_device *vf_netdev) +{ + struct netvsc_device *netvsc_dev; + const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops; + + if (eth_ops == NULL || eth_ops == ðtool_ops) + return NOTIFY_DONE; + + /* + * We will use the MAC address to locate the synthetic interface to + * associate with the VF interface. If we don't find a matching + * synthetic interface, move on. + */ + netvsc_dev = get_netvsc_device(vf_netdev->dev_addr); + if (netvsc_dev == NULL) + return NOTIFY_DONE; + + netdev_info(netvsc_dev->ndev, "VF registering: %s\n", vf_netdev->name); + /* + * Take a reference on the module. + */ + try_module_get(THIS_MODULE); + netvsc_dev->vf_netdev = vf_netdev; + return NOTIFY_OK; +} + + +static int netvsc_vf_up(struct net_device *vf_netdev) +{ + struct netvsc_device *netvsc_dev; + const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops; + struct net_device_context *net_device_ctx; + + if (eth_ops == ðtool_ops) + return NOTIFY_DONE; + + netvsc_dev = get_netvsc_device(vf_netdev->dev_addr); + + if ((netvsc_dev == NULL) || (netvsc_dev->vf_netdev == NULL)) + return NOTIFY_DONE; + + netdev_info(netvsc_dev->ndev, "VF up: %s\n", vf_netdev->name); + net_device_ctx = netdev_priv(netvsc_dev->ndev); + netvsc_dev->vf_inject = true; + + /* + * Open the device before switching data path. + */ + rndis_filter_open(net_device_ctx->device_ctx); + + /* + * notify the host to switch the data path. + */ + netvsc_switch_datapath(netvsc_dev, true); + netdev_info(netvsc_dev->ndev, "Data path switched to VF: %s\n", + vf_netdev->name); + + netif_carrier_off(netvsc_dev->ndev); + + /* + * Now notify peers. We are scheduling work to + * notify peers; take a reference to prevent + * the VF interface from vanishing. + */ + atomic_inc(&netvsc_dev->vf_use_cnt); + net_device_ctx->gwrk.netdev = vf_netdev; + net_device_ctx->gwrk.netvsc_dev = netvsc_dev; + schedule_work(&net_device_ctx->gwrk.dwrk); + + return NOTIFY_OK; +} + + +static int netvsc_vf_down(struct net_device *vf_netdev) +{ + struct netvsc_device *netvsc_dev; + struct net_device_context *net_device_ctx; + const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops; + + if (eth_ops == ðtool_ops) + return NOTIFY_DONE; + + netvsc_dev = get_netvsc_device(vf_netdev->dev_addr); + + if ((netvsc_dev == NULL) || (netvsc_dev->vf_netdev == NULL)) + return NOTIFY_DONE; + + netdev_info(netvsc_dev->ndev, "VF down: %s\n", vf_netdev->name); + net_device_ctx = netdev_priv(netvsc_dev->ndev); + netvsc_dev->vf_inject = false; + /* + * Wait for currently active users to + * drain out. + */ + + while (atomic_read(&netvsc_dev->vf_use_cnt) != 0) + udelay(50); + netvsc_switch_datapath(netvsc_dev, false); + netdev_info(netvsc_dev->ndev, "Data path switched from VF: %s\n", + vf_netdev->name); + rndis_filter_close(net_device_ctx->device_ctx); + netif_carrier_on(netvsc_dev->ndev); + /* + * Notify peers. + */ + atomic_inc(&netvsc_dev->vf_use_cnt); + net_device_ctx->gwrk.netdev = netvsc_dev->ndev; + net_device_ctx->gwrk.netvsc_dev = netvsc_dev; + schedule_work(&net_device_ctx->gwrk.dwrk); + + return NOTIFY_OK; +} + + +static int netvsc_unregister_vf(struct net_device *vf_netdev) +{ + struct netvsc_device *netvsc_dev; + const struct ethtool_ops *eth_ops = vf_netdev->ethtool_ops; + + if (eth_ops == ðtool_ops) + return NOTIFY_DONE; + + netvsc_dev = get_netvsc_device(vf_netdev->dev_addr); + if (netvsc_dev == NULL) + return NOTIFY_DONE; + netdev_info(netvsc_dev->ndev, "VF unregistering: %s\n", + vf_netdev->name); + + netvsc_dev->vf_netdev = NULL; + module_put(THIS_MODULE); + return NOTIFY_OK; +} + static int netvsc_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { @@ -1140,6 +1360,7 @@ static int netvsc_probe(struct hv_device *dev, hv_set_drvdata(dev, net); INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); INIT_WORK(&net_device_ctx->work, do_set_multicast); + INIT_WORK(&net_device_ctx->gwrk.dwrk, netvsc_notify_peers); spin_lock_init(&net_device_ctx->lock); INIT_LIST_HEAD(&net_device_ctx->reconfig_events); @@ -1235,19 +1456,58 @@ static struct hv_driver netvsc_drv = { .remove = netvsc_remove, }; + +/* + * On Hyper-V, every VF interface is matched with a corresponding + * synthetic interface. The synthetic interface is presented first + * to the guest. When the corresponding VF instance is registered, + * we will take care of switching the data path. + */ +static int netvsc_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); + + switch (event) { + case NETDEV_REGISTER: + return netvsc_register_vf(event_dev); + case NETDEV_UNREGISTER: + return netvsc_unregister_vf(event_dev); + case NETDEV_UP: + return netvsc_vf_up(event_dev); + case NETDEV_DOWN: + return netvsc_vf_down(event_dev); + default: + return NOTIFY_DONE; + } +} + +static struct notifier_block netvsc_netdev_notifier = { + .notifier_call = netvsc_netdev_event, +}; + static void __exit netvsc_drv_exit(void) { + unregister_netdevice_notifier(&netvsc_netdev_notifier); vmbus_driver_unregister(&netvsc_drv); } static int __init netvsc_drv_init(void) { + int ret; + if (ring_size < RING_SIZE_MIN) { ring_size = RING_SIZE_MIN; pr_info("Increased ring_size to %d (min allowed)\n", ring_size); } - return vmbus_driver_register(&netvsc_drv); + ret = vmbus_driver_register(&netvsc_drv); + + if (ret) + return ret; + + register_netdevice_notifier(&netvsc_netdev_notifier); + return 0; } MODULE_LICENSE("GPL"); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index c4e1e0408433..a59cdebc9b4b 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -1229,6 +1229,9 @@ int rndis_filter_open(struct hv_device *dev) if (!net_device) return -EINVAL; + if (atomic_inc_return(&net_device->open_cnt) != 1) + return 0; + return rndis_filter_open_device(net_device->extension); } @@ -1239,5 +1242,8 @@ int rndis_filter_close(struct hv_device *dev) if (!nvdev) return -EINVAL; + if (atomic_dec_return(&nvdev->open_cnt) != 0) + return 0; + return rndis_filter_close_device(nvdev->extension); } -- GitLab From e7600449bef0650ee7818be6de26955e81579d13 Mon Sep 17 00:00:00 2001 From: Govindarajulu Varadarajan <_govind@gmx.com> Date: Sat, 16 Apr 2016 00:40:43 +0530 Subject: [PATCH 3256/9938] enic: set netdev->vlan_features Driver sets vlan_feature to netdev->features as hardware supports all of them on vlan interface. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller --- drivers/net/ethernet/cisco/enic/enic_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index b2182d3ba3cc..f15560a06718 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2740,6 +2740,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->hw_features |= NETIF_F_RXCSUM; netdev->features |= netdev->hw_features; + netdev->vlan_features |= netdev->features; #ifdef CONFIG_RFS_ACCEL netdev->hw_features |= NETIF_F_NTUPLE; -- GitLab From e10f9a42e9e822a8439dd4aaaccfd22365ee3975 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 10 Mar 2016 16:09:08 +0100 Subject: [PATCH 3257/9938] USB: add descriptors from USB Power Delivery spec Adding the descriptors of chapter 9.2 of the Power Delivery spec. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/usb/ch9.h | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index d5ce71607972..df1beca31bec 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -913,6 +913,104 @@ struct usb_ssp_cap_descriptor { #define USB_SSP_SUBLINK_SPEED_LSM (0xff << 16) /* Lanespeed mantissa */ } __attribute__((packed)); +/* + * USB Power Delivery Capability Descriptor: + * Defines capabilities for PD + */ +/* Defines the various PD Capabilities of this device */ +#define USB_PD_POWER_DELIVERY_CAPABILITY 0x06 +/* Provides information on each battery supported by the device */ +#define USB_PD_BATTERY_INFO_CAPABILITY 0x07 +/* The Consumer characteristics of a Port on the device */ +#define USB_PD_PD_CONSUMER_PORT_CAPABILITY 0x08 +/* The provider characteristics of a Port on the device */ +#define USB_PD_PD_PROVIDER_PORT_CAPABILITY 0x09 + +struct usb_pd_cap_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; /* set to USB_PD_POWER_DELIVERY_CAPABILITY */ + __u8 bReserved; + __le32 bmAttributes; +#define USB_PD_CAP_BATTERY_CHARGING (1 << 1) /* supports Battery Charging specification */ +#define USB_PD_CAP_USB_PD (1 << 2) /* supports USB Power Delivery specification */ +#define USB_PD_CAP_PROVIDER (1 << 3) /* can provide power */ +#define USB_PD_CAP_CONSUMER (1 << 4) /* can consume power */ +#define USB_PD_CAP_CHARGING_POLICY (1 << 5) /* supports CHARGING_POLICY feature */ +#define USB_PD_CAP_TYPE_C_CURRENT (1 << 6) /* supports power capabilities defined in the USB Type-C Specification */ + +#define USB_PD_CAP_PWR_AC (1 << 8) +#define USB_PD_CAP_PWR_BAT (1 << 9) +#define USB_PD_CAP_PWR_USE_V_BUS (1 << 14) + + __le16 bmProviderPorts; /* Bit zero refers to the UFP of the device */ + __le16 bmConsumerPorts; + __le16 bcdBCVersion; + __le16 bcdPDVersion; + __le16 bcdUSBTypeCVersion; +} __attribute__((packed)); + +struct usb_pd_cap_battery_info_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + /* Index of string descriptor shall contain the user friendly name for this battery */ + __u8 iBattery; + /* Index of string descriptor shall contain the Serial Number String for this battery */ + __u8 iSerial; + __u8 iManufacturer; + __u8 bBatteryId; /* uniquely identifies this battery in status Messages */ + __u8 bReserved; + /* + * Shall contain the Battery Charge value above which this + * battery is considered to be fully charged but not necessarily + * “topped off.” + */ + __le32 dwChargedThreshold; /* in mWh */ + /* + * Shall contain the minimum charge level of this battery such + * that above this threshold, a device can be assured of being + * able to power up successfully (see Battery Charging 1.2). + */ + __le32 dwWeakThreshold; /* in mWh */ + __le32 dwBatteryDesignCapacity; /* in mWh */ + __le32 dwBatteryLastFullchargeCapacity; /* in mWh */ +} __attribute__((packed)); + +struct usb_pd_cap_consumer_port_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + __u8 bReserved; + __u8 bmCapabilities; +/* port will oerate under: */ +#define USB_PD_CAP_CONSUMER_BC (1 << 0) /* BC */ +#define USB_PD_CAP_CONSUMER_PD (1 << 1) /* PD */ +#define USB_PD_CAP_CONSUMER_TYPE_C (1 << 2) /* USB Type-C Current */ + __le16 wMinVoltage; /* in 50mV units */ + __le16 wMaxVoltage; /* in 50mV units */ + __u16 wReserved; + __le32 dwMaxOperatingPower; /* in 10 mW - operating at steady state */ + __le32 dwMaxPeakPower; /* in 10mW units - operating at peak power */ + __le32 dwMaxPeakPowerTime; /* in 100ms units - duration of peak */ +#define USB_PD_CAP_CONSUMER_UNKNOWN_PEAK_POWER_TIME 0xffff +} __attribute__((packed)); + +struct usb_pd_cap_provider_port_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + __u8 bReserved1; + __u8 bmCapabilities; +/* port will oerate under: */ +#define USB_PD_CAP_PROVIDER_BC (1 << 0) /* BC */ +#define USB_PD_CAP_PROVIDER_PD (1 << 1) /* PD */ +#define USB_PD_CAP_PROVIDER_TYPE_C (1 << 2) /* USB Type-C Current */ + __u8 bNumOfPDObjects; + __u8 bReserved2; + __le32 wPowerDataObject[]; +} __attribute__((packed)); + /* * Precision time measurement capability descriptor: advertised by devices and * hubs that support PTM -- GitLab From e1669f4a425c92c186e33a101e8fa84195fa2744 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 10 Mar 2016 16:09:09 +0100 Subject: [PATCH 3258/9938] USB: PD: define specific requests This takes the definitions of requests from chapter 9.3.1 of the USB Power Delivery spec. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/usb/ch9.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index df1beca31bec..535fce085459 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -105,6 +105,13 @@ #define USB_REQ_LOOPBACK_DATA_READ 0x16 #define USB_REQ_SET_INTERFACE_DS 0x17 +/* specific requests for USB Power Delivery */ +#define USB_REQ_GET_PARTNER_PDO 20 +#define USB_REQ_GET_BATTERY_STATUS 21 +#define USB_REQ_SET_PDO 22 +#define USB_REQ_GET_VDM 23 +#define USB_REQ_SEND_VDM 24 + /* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command, * used by hubs to put ports into a new L1 suspend state, except that it * forgot to define its number ... -- GitLab From 351e67ab5c0582e833c8d67dccb034348879cf25 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 10 Mar 2016 16:09:10 +0100 Subject: [PATCH 3259/9938] USB: PD: additional feature selectors This adds the feature selectors from Table 9-8 Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/usb/ch9.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 535fce085459..a8acc24765fe 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -172,6 +172,22 @@ #define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */ #define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */ +/* + * Feature selectors from Table 9-8 USB Power Delivery spec + */ +#define USB_DEVICE_BATTERY_WAKE_MASK 40 +#define USB_DEVICE_OS_IS_PD_AWARE 41 +#define USB_DEVICE_POLICY_MODE 42 +#define USB_PORT_PR_SWAP 43 +#define USB_PORT_GOTO_MIN 44 +#define USB_PORT_RETURN_POWER 45 +#define USB_PORT_ACCEPT_PD_REQUEST 46 +#define USB_PORT_REJECT_PD_REQUEST 47 +#define USB_PORT_PORT_PD_RESET 48 +#define USB_PORT_C_PORT_PD_CHANGE 49 +#define USB_PORT_CABLE_PD_RESET 50 +#define USB_DEVICE_CHARGING_POLICY 54 + /** * struct usb_ctrlrequest - SETUP data for a USB device control request * @bRequestType: matches the USB bmRequestType field -- GitLab From d4fc8bf59746b6ef9bdbec42a608b89d0221b7df Mon Sep 17 00:00:00 2001 From: Rajesh Bhagat Date: Fri, 11 Mar 2016 10:27:49 +0530 Subject: [PATCH 3260/9938] xhci: fix typo in babble endpoint handling comment The 0.95 xHCI spec says that non-control endpoints will be halted if a babble is detected on a transfer. The 0.96 xHCI spec says all types of endpoints will be halted when a babble is detected. Some hardware that claims to be 0.95 compliant halts the control endpoint anyway. Reference: http://www.spinics.net/lists/linux-usb/msg21755.html Signed-off-by: Rajesh Bhagat Reviewed-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 99b4ff42f7a0..251e29954711 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1768,7 +1768,7 @@ static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci, if (trb_comp_code == COMP_TX_ERR || trb_comp_code == COMP_BABBLE || trb_comp_code == COMP_SPLIT_ERR) - /* The 0.96 spec says a babbling control endpoint + /* The 0.95 spec says a babbling control endpoint * is not halted. The 0.96 spec says it is. Some HW * claims to be 0.95 compliant, but it halts the control * endpoint anyway. Check if a babble halted the -- GitLab From e352506e8a871890278ba66a2d77167193ffbfa9 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 26 Mar 2016 22:42:17 +0300 Subject: [PATCH 3261/9938] USB: whci-hcd: add more checks for dma mapping error Fixing checks for dma mapping error in qset_fill_page_list(), I have missed two similar problems in qset_add_urb_sg() and in qset_add_urb_sg_linearize(). v2: check validity of dma_addr with dma_mapping_error() in qset_free_std() as suggested by Vladimir Zapolskiy. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Reviewed-by: Vladimir Zapolskiy Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/whci/qset.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 1a8e960d073b..c0e6812426b3 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -314,7 +314,7 @@ void qset_free_std(struct whc *whc, struct whc_std *std) kfree(std->bounce_buf); } if (std->pl_virt) { - if (std->dma_addr) + if (!dma_mapping_error(whc->wusbhc.dev, std->dma_addr)) dma_unmap_single(whc->wusbhc.dev, std->dma_addr, std->num_pointers * sizeof(struct whc_page_list_entry), DMA_TO_DEVICE); @@ -535,9 +535,11 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u list_for_each_entry(std, &qset->stds, list_node) { if (std->ntds_remaining == -1) { pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); - std->ntds_remaining = ntds--; std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, pl_len, DMA_TO_DEVICE); + if (dma_mapping_error(whc->wusbhc.dev, std->dma_addr)) + return -EFAULT; + std->ntds_remaining = ntds--; } } return 0; @@ -618,6 +620,8 @@ static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset, std->dma_addr = dma_map_single(&whc->umc->dev, std->bounce_buf, std->len, is_out ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + if (dma_mapping_error(&whc->umc->dev, std->dma_addr)) + return -EFAULT; if (qset_fill_page_list(whc, std, mem_flags) < 0) return -ENOMEM; -- GitLab From bb7871ad99ea814565c3d6b551e039c71f24cbb3 Mon Sep 17 00:00:00 2001 From: Nobuo Iwata Date: Thu, 24 Mar 2016 10:50:59 +0900 Subject: [PATCH 3262/9938] usbip: event handler as one thread Dear all, 1. Overview In current USB/IP implementation, event kernel threads are created for each port. The functions of the threads are closing connection and error handling so they don't have not so many events to handle. There's no need to have thread for each port. BEFORE) vhci side - VHCI_NPORTS(8) threads are created. $ ps aux | grep usbip root 10059 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] root 10060 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] root 10061 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] root 10062 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] root 10063 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] root 10064 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] root 10065 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] root 10066 0.0 0.0 0 0 ? S 17:06 0:00 [usbip_eh] BEFORE) stub side - threads will be created every bind operation. $ ps aux | grep usbip root 8368 0.0 0.0 0 0 ? S 17:56 0:00 [usbip_eh] root 8399 0.0 0.0 0 0 ? S 17:56 0:00 [usbip_eh] This patch put event threads of stub and vhci driver as one workqueue. AFTER) only one event threads in each vhci and stub side. $ ps aux | grep usbip root 10457 0.0 0.0 0 0 ? S< 17:47 0:00 [usbip_event] 2. Modification to usbip_event.c BEFORE) kernel threads are created in usbip_start_eh(). AFTER) one workqueue is created in new usbip_init_eh(). Event handler which was main loop of kernel thread is modified to workqueue handler. Events themselves are stored in struct usbip_device - same as before. usbip_devices which have event are listed in event_list. The handler picks an element from the list and wakeup usbip_device. The wakeup method is same as before. usbip_in_eh() substitutes statement which checks whether functions are called from eh_ops or not. In this function, the worker context is used for the checking. The context will be set in a variable in the beginning of first event handling. usbip_in_eh() is used in event handler so it works well. 3. Modifications to programs using usbip_event.c Initialization and termination of workqueue are added to init and exit routine of usbip_core respectively. A. version info v2) # Merged 1/2 event handler itself and 2/2 user programs because of auto build fail at 1/2 casued unmodified user programs in 1/2. Signed-off-by: Nobuo Iwata Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/stub_dev.c | 3 +- drivers/usb/usbip/usbip_common.c | 7 ++ drivers/usb/usbip/usbip_common.h | 4 +- drivers/usb/usbip/usbip_event.c | 168 +++++++++++++++++++++++-------- 4 files changed, 137 insertions(+), 45 deletions(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index a3ec49bdc1e6..e286346041f6 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -388,7 +388,6 @@ static int stub_probe(struct usb_device *udev) err_port: dev_set_drvdata(&udev->dev, NULL); usb_put_dev(udev); - kthread_stop_put(sdev->ud.eh); busid_priv->sdev = NULL; stub_device_free(sdev); @@ -449,7 +448,7 @@ static void stub_disconnect(struct usb_device *udev) } /* If usb reset is called from event handler */ - if (busid_priv->sdev->ud.eh == current) + if (usbip_in_eh(current)) return; /* shutdown the current connection */ diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c index e40da7759a0e..2e5cf6392a8e 100644 --- a/drivers/usb/usbip/usbip_common.c +++ b/drivers/usb/usbip/usbip_common.c @@ -769,12 +769,19 @@ EXPORT_SYMBOL_GPL(usbip_recv_xbuff); static int __init usbip_core_init(void) { + int ret; + pr_info(DRIVER_DESC " v" USBIP_VERSION "\n"); + ret = usbip_init_eh(); + if (ret) + return ret; + return 0; } static void __exit usbip_core_exit(void) { + usbip_finish_eh(); return; } diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h index 86b08475c254..2fbbc643b888 100644 --- a/drivers/usb/usbip/usbip_common.h +++ b/drivers/usb/usbip/usbip_common.h @@ -267,7 +267,6 @@ struct usbip_device { struct task_struct *tcp_tx; unsigned long event; - struct task_struct *eh; wait_queue_head_t eh_waitq; struct eh_ops { @@ -313,10 +312,13 @@ void usbip_pad_iso(struct usbip_device *ud, struct urb *urb); int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); /* usbip_event.c */ +int usbip_init_eh(void); +void usbip_finish_eh(void); int usbip_start_eh(struct usbip_device *ud); void usbip_stop_eh(struct usbip_device *ud); void usbip_event_add(struct usbip_device *ud, unsigned long event); int usbip_event_happened(struct usbip_device *ud); +int usbip_in_eh(struct task_struct *task); static inline int interface_to_busnum(struct usb_interface *interface) { diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c index 2580a32bcdff..f1635662c299 100644 --- a/drivers/usb/usbip/usbip_event.c +++ b/drivers/usb/usbip/usbip_event.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003-2008 Takahiro Hirofuchi + * Copyright (C) 2015 Nobuo Iwata * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,17 +20,68 @@ #include #include +#include +#include #include "usbip_common.h" -static int event_handler(struct usbip_device *ud) +struct usbip_event { + struct list_head node; + struct usbip_device *ud; +}; + +static DEFINE_SPINLOCK(event_lock); +static LIST_HEAD(event_list); + +static void set_event(struct usbip_device *ud, unsigned long event) { - usbip_dbg_eh("enter\n"); + unsigned long flags; - /* - * Events are handled by only this thread. - */ - while (usbip_event_happened(ud)) { + spin_lock_irqsave(&ud->lock, flags); + ud->event |= event; + spin_unlock_irqrestore(&ud->lock, flags); +} + +static void unset_event(struct usbip_device *ud, unsigned long event) +{ + unsigned long flags; + + spin_lock_irqsave(&ud->lock, flags); + ud->event &= ~event; + spin_unlock_irqrestore(&ud->lock, flags); +} + +static struct usbip_device *get_event(void) +{ + struct usbip_event *ue = NULL; + struct usbip_device *ud = NULL; + unsigned long flags; + + spin_lock_irqsave(&event_lock, flags); + if (!list_empty(&event_list)) { + ue = list_first_entry(&event_list, struct usbip_event, node); + list_del(&ue->node); + } + spin_unlock_irqrestore(&event_lock, flags); + + if (ue) { + ud = ue->ud; + kfree(ue); + } + return ud; +} + +static struct task_struct *worker_context; + +static void event_handler(struct work_struct *work) +{ + struct usbip_device *ud; + + if (worker_context == NULL) { + worker_context = current; + } + + while ((ud = get_event()) != NULL) { usbip_dbg_eh("pending event %lx\n", ud->event); /* @@ -38,79 +90,102 @@ static int event_handler(struct usbip_device *ud) */ if (ud->event & USBIP_EH_SHUTDOWN) { ud->eh_ops.shutdown(ud); - ud->event &= ~USBIP_EH_SHUTDOWN; + unset_event(ud, USBIP_EH_SHUTDOWN); } /* Reset the device. */ if (ud->event & USBIP_EH_RESET) { ud->eh_ops.reset(ud); - ud->event &= ~USBIP_EH_RESET; + unset_event(ud, USBIP_EH_RESET); } /* Mark the device as unusable. */ if (ud->event & USBIP_EH_UNUSABLE) { ud->eh_ops.unusable(ud); - ud->event &= ~USBIP_EH_UNUSABLE; + unset_event(ud, USBIP_EH_UNUSABLE); } /* Stop the error handler. */ if (ud->event & USBIP_EH_BYE) - return -1; + usbip_dbg_eh("removed %p\n", ud); + + wake_up(&ud->eh_waitq); } +} +int usbip_start_eh(struct usbip_device *ud) +{ + init_waitqueue_head(&ud->eh_waitq); + ud->event = 0; return 0; } +EXPORT_SYMBOL_GPL(usbip_start_eh); -static int event_handler_loop(void *data) +void usbip_stop_eh(struct usbip_device *ud) { - struct usbip_device *ud = data; + unsigned long pending = ud->event & ~USBIP_EH_BYE; - while (!kthread_should_stop()) { - wait_event_interruptible(ud->eh_waitq, - usbip_event_happened(ud) || - kthread_should_stop()); - usbip_dbg_eh("wakeup\n"); + if (!(ud->event & USBIP_EH_BYE)) + usbip_dbg_eh("usbip_eh stopping but not removed\n"); - if (event_handler(ud) < 0) - break; - } + if (pending) + usbip_dbg_eh("usbip_eh waiting completion %lx\n", pending); - return 0; + wait_event_interruptible(ud->eh_waitq, !(ud->event & ~USBIP_EH_BYE)); + usbip_dbg_eh("usbip_eh has stopped\n"); } +EXPORT_SYMBOL_GPL(usbip_stop_eh); -int usbip_start_eh(struct usbip_device *ud) -{ - init_waitqueue_head(&ud->eh_waitq); - ud->event = 0; +#define WORK_QUEUE_NAME "usbip_event" - ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh"); - if (IS_ERR(ud->eh)) { - pr_warn("Unable to start control thread\n"); - return PTR_ERR(ud->eh); - } +static struct workqueue_struct *usbip_queue; +static DECLARE_WORK(usbip_work, event_handler); +int usbip_init_eh(void) +{ + usbip_queue = create_singlethread_workqueue(WORK_QUEUE_NAME); + if (usbip_queue == NULL) { + pr_err("failed to create usbip_event\n"); + return -ENOMEM; + } return 0; } -EXPORT_SYMBOL_GPL(usbip_start_eh); -void usbip_stop_eh(struct usbip_device *ud) +void usbip_finish_eh(void) { - if (ud->eh == current) - return; /* do not wait for myself */ - - kthread_stop(ud->eh); - usbip_dbg_eh("usbip_eh has finished\n"); + flush_workqueue(usbip_queue); + destroy_workqueue(usbip_queue); + usbip_queue = NULL; } -EXPORT_SYMBOL_GPL(usbip_stop_eh); void usbip_event_add(struct usbip_device *ud, unsigned long event) { + struct usbip_event *ue; unsigned long flags; - spin_lock_irqsave(&ud->lock, flags); - ud->event |= event; - wake_up(&ud->eh_waitq); - spin_unlock_irqrestore(&ud->lock, flags); + if (ud->event & USBIP_EH_BYE) + return; + + set_event(ud, event); + + spin_lock_irqsave(&event_lock, flags); + + list_for_each_entry_reverse(ue, &event_list, node) { + if (ue->ud == ud) + goto out; + } + + ue = kmalloc(sizeof(struct usbip_event), GFP_ATOMIC); + if (ue == NULL) + goto out; + + ue->ud = ud; + + list_add_tail(&ue->node, &event_list); + queue_work(usbip_queue, &usbip_work); + +out: + spin_unlock_irqrestore(&event_lock, flags); } EXPORT_SYMBOL_GPL(usbip_event_add); @@ -127,3 +202,12 @@ int usbip_event_happened(struct usbip_device *ud) return happened; } EXPORT_SYMBOL_GPL(usbip_event_happened); + +int usbip_in_eh(struct task_struct *task) +{ + if (task == worker_context) + return 1; + + return 0; +} +EXPORT_SYMBOL_GPL(usbip_in_eh); -- GitLab From 7ce04cff59d510c88bfa0745202281cf3c6417ae Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Thu, 7 Apr 2016 21:05:07 +0530 Subject: [PATCH 3263/9938] usb: wusbcore: remove unreachable code The call to wusb_dev_sysfs_rm() which is just after return will never be executed. On checking the code, wusb_dev_sysfs_add() is the last one to be executed so even if that fails we do not need wusb_dev_sysfs_rm() in the error path. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/devconnect.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 3f4f5fbded55..bf9551735938 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -893,7 +893,6 @@ static void wusb_dev_add_ncb(struct usb_device *usb_dev) error_nodev: return; - wusb_dev_sysfs_rm(wusb_dev); error_add_sysfs: wusb_dev_bos_rm(wusb_dev); error_bos_add: -- GitLab From 761b7910d4b4f0e7d283873b701ca83beacd70a5 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 15 Apr 2016 17:13:09 +0300 Subject: [PATCH 3264/9938] iio: magn: Split bmc150 driver in common/i2c parts This is useful for easily adding SPI support in later patches. Now bmc150_magn exports core functions to be used by I2C/SPI drivers instances. For the moment only I2C driver is supported. Signed-off-by: Daniel Baluta Acked-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/Kconfig | 17 ++- drivers/iio/magnetometer/Makefile | 2 + drivers/iio/magnetometer/bmc150_magn.c | 155 +++++++++------------ drivers/iio/magnetometer/bmc150_magn.h | 11 ++ drivers/iio/magnetometer/bmc150_magn_i2c.c | 77 ++++++++++ 5 files changed, 163 insertions(+), 99 deletions(-) create mode 100644 drivers/iio/magnetometer/bmc150_magn.h create mode 100644 drivers/iio/magnetometer/bmc150_magn_i2c.c diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index d9834ed023db..4972f9d17023 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -27,22 +27,25 @@ config AK09911 Deprecated: AK09911 is now supported by AK8975 driver. config BMC150_MAGN - tristate "Bosch BMC150 Magnetometer Driver" - depends on I2C - select REGMAP_I2C + tristate select IIO_BUFFER select IIO_TRIGGERED_BUFFER - help - Say yes here to build support for the BMC150 magnetometer. - Currently this only supports the device via an i2c interface. +config BMC150_MAGN_I2C + tristate "Bosch BMC150 I2C Magnetometer Driver" + depends on I2C + select BMC150_MAGN + select REGMAP_I2C + help + Say yes here to build support for the BMC150 magnetometer with + I2C interface. This is a combo module with both accelerometer and magnetometer. This driver is only implementing magnetometer part, which has its own address and register map. To compile this driver as a module, choose M here: the module will be - called bmc150_magn. + called bmc150_magn_i2c. config MAG3110 tristate "Freescale MAG3110 3-Axis Magnetometer" diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index dd03fe524481..56477737e083 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -5,6 +5,8 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o +obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o + obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o obj-$(CONFIG_MMC35240) += mmc35240.o diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index 0e9da189dc4c..d104fb8d9379 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -34,6 +34,8 @@ #include #include +#include "bmc150_magn.h" + #define BMC150_MAGN_DRV_NAME "bmc150_magn" #define BMC150_MAGN_IRQ_NAME "bmc150_magn_event" @@ -134,7 +136,7 @@ struct bmc150_magn_trim_regs { } __packed; struct bmc150_magn_data { - struct i2c_client *client; + struct device *dev; /* * 1. Protect this structure. * 2. Serialize sequences that power on/off the device and access HW. @@ -146,6 +148,7 @@ struct bmc150_magn_data { struct iio_trigger *dready_trig; bool dready_trigger_on; int max_odr; + int irq; }; static const struct { @@ -215,7 +218,7 @@ static bool bmc150_magn_is_volatile_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config bmc150_magn_regmap_config = { +const struct regmap_config bmc150_magn_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -225,6 +228,7 @@ static const struct regmap_config bmc150_magn_regmap_config = { .writeable_reg = bmc150_magn_is_writeable_reg, .volatile_reg = bmc150_magn_is_volatile_reg, }; +EXPORT_SYMBOL(bmc150_magn_regmap_config); static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data, enum bmc150_magn_power_modes mode, @@ -263,17 +267,17 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(&data->client->dev); + ret = pm_runtime_get_sync(data->dev); } else { - pm_runtime_mark_last_busy(&data->client->dev); - ret = pm_runtime_put_autosuspend(&data->client->dev); + pm_runtime_mark_last_busy(data->dev); + ret = pm_runtime_put_autosuspend(data->dev); } if (ret < 0) { - dev_err(&data->client->dev, + dev_err(data->dev, "failed to change power state to %d\n", on); if (on) - pm_runtime_put_noidle(&data->client->dev); + pm_runtime_put_noidle(data->dev); return ret; } @@ -350,7 +354,7 @@ static int bmc150_magn_set_max_odr(struct bmc150_magn_data *data, int rep_xy, /* the maximum selectable read-out frequency from datasheet */ max_odr = 1000000 / (145 * rep_xy + 500 * rep_z + 980); if (odr > max_odr) { - dev_err(&data->client->dev, + dev_err(data->dev, "Can't set oversampling with sampling freq %d\n", odr); return -EINVAL; @@ -684,27 +688,27 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, false); if (ret < 0) { - dev_err(&data->client->dev, + dev_err(data->dev, "Failed to bring up device from suspend mode\n"); return ret; } ret = regmap_read(data->regmap, BMC150_MAGN_REG_CHIP_ID, &chip_id); if (ret < 0) { - dev_err(&data->client->dev, "Failed reading chip id\n"); + dev_err(data->dev, "Failed reading chip id\n"); goto err_poweroff; } if (chip_id != BMC150_MAGN_CHIP_ID_VAL) { - dev_err(&data->client->dev, "Invalid chip id 0x%x\n", chip_id); + dev_err(data->dev, "Invalid chip id 0x%x\n", chip_id); ret = -ENODEV; goto err_poweroff; } - dev_dbg(&data->client->dev, "Chip id %x\n", chip_id); + dev_dbg(data->dev, "Chip id %x\n", chip_id); preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET]; ret = bmc150_magn_set_odr(data, preset.odr); if (ret < 0) { - dev_err(&data->client->dev, "Failed to set ODR to %d\n", + dev_err(data->dev, "Failed to set ODR to %d\n", preset.odr); goto err_poweroff; } @@ -712,7 +716,7 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) ret = regmap_write(data->regmap, BMC150_MAGN_REG_REP_XY, BMC150_MAGN_REPXY_TO_REGVAL(preset.rep_xy)); if (ret < 0) { - dev_err(&data->client->dev, "Failed to set REP XY to %d\n", + dev_err(data->dev, "Failed to set REP XY to %d\n", preset.rep_xy); goto err_poweroff; } @@ -720,7 +724,7 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) ret = regmap_write(data->regmap, BMC150_MAGN_REG_REP_Z, BMC150_MAGN_REPZ_TO_REGVAL(preset.rep_z)); if (ret < 0) { - dev_err(&data->client->dev, "Failed to set REP Z to %d\n", + dev_err(data->dev, "Failed to set REP Z to %d\n", preset.rep_z); goto err_poweroff; } @@ -733,7 +737,7 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL, true); if (ret < 0) { - dev_err(&data->client->dev, "Failed to power on device\n"); + dev_err(data->dev, "Failed to power on device\n"); goto err_poweroff; } @@ -842,41 +846,33 @@ static const char *bmc150_magn_match_acpi_device(struct device *dev) return dev_name(dev); } -static int bmc150_magn_probe(struct i2c_client *client, - const struct i2c_device_id *id) +int bmc150_magn_probe(struct device *dev, struct regmap *regmap, + int irq, const char *name) { struct bmc150_magn_data *data; struct iio_dev *indio_dev; - const char *name = NULL; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - data->client = client; + dev_set_drvdata(dev, indio_dev); + data->regmap = regmap; + data->irq = irq; + data->dev = dev; - if (id) - name = id->name; - else if (ACPI_HANDLE(&client->dev)) - name = bmc150_magn_match_acpi_device(&client->dev); - else - return -ENOSYS; + if (!name && ACPI_HANDLE(dev)) + name = bmc150_magn_match_acpi_device(dev); mutex_init(&data->mutex); - data->regmap = devm_regmap_init_i2c(client, &bmc150_magn_regmap_config); - if (IS_ERR(data->regmap)) { - dev_err(&client->dev, "Failed to allocate register map\n"); - return PTR_ERR(data->regmap); - } ret = bmc150_magn_init(data); if (ret < 0) return ret; - indio_dev->dev.parent = &client->dev; + indio_dev->dev.parent = dev; indio_dev->channels = bmc150_magn_channels; indio_dev->num_channels = ARRAY_SIZE(bmc150_magn_channels); indio_dev->available_scan_masks = bmc150_magn_scan_masks; @@ -884,35 +880,34 @@ static int bmc150_magn_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &bmc150_magn_info; - if (client->irq > 0) { - data->dready_trig = devm_iio_trigger_alloc(&client->dev, + if (irq > 0) { + data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); if (!data->dready_trig) { ret = -ENOMEM; - dev_err(&client->dev, "iio trigger alloc failed\n"); + dev_err(dev, "iio trigger alloc failed\n"); goto err_poweroff; } - data->dready_trig->dev.parent = &client->dev; + data->dready_trig->dev.parent = dev; data->dready_trig->ops = &bmc150_magn_trigger_ops; iio_trigger_set_drvdata(data->dready_trig, indio_dev); ret = iio_trigger_register(data->dready_trig); if (ret) { - dev_err(&client->dev, "iio trigger register failed\n"); + dev_err(dev, "iio trigger register failed\n"); goto err_poweroff; } - ret = request_threaded_irq(client->irq, + ret = request_threaded_irq(irq, iio_trigger_generic_data_rdy_poll, NULL, IRQF_TRIGGER_RISING | IRQF_ONESHOT, BMC150_MAGN_IRQ_NAME, data->dready_trig); if (ret < 0) { - dev_err(&client->dev, "request irq %d failed\n", - client->irq); + dev_err(dev, "request irq %d failed\n", irq); goto err_trigger_unregister; } } @@ -922,34 +917,33 @@ static int bmc150_magn_probe(struct i2c_client *client, bmc150_magn_trigger_handler, &bmc150_magn_buffer_setup_ops); if (ret < 0) { - dev_err(&client->dev, - "iio triggered buffer setup failed\n"); + dev_err(dev, "iio triggered buffer setup failed\n"); goto err_free_irq; } - ret = pm_runtime_set_active(&client->dev); + ret = pm_runtime_set_active(dev); if (ret) goto err_buffer_cleanup; - pm_runtime_enable(&client->dev); - pm_runtime_set_autosuspend_delay(&client->dev, + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, BMC150_MAGN_AUTO_SUSPEND_DELAY_MS); - pm_runtime_use_autosuspend(&client->dev); + pm_runtime_use_autosuspend(dev); ret = iio_device_register(indio_dev); if (ret < 0) { - dev_err(&client->dev, "unable to register iio device\n"); + dev_err(dev, "unable to register iio device\n"); goto err_buffer_cleanup; } - dev_dbg(&indio_dev->dev, "Registered device %s\n", name); + dev_dbg(dev, "Registered device %s\n", name); return 0; err_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); err_free_irq: - if (client->irq > 0) - free_irq(client->irq, data->dready_trig); + if (irq > 0) + free_irq(irq, data->dready_trig); err_trigger_unregister: if (data->dready_trig) iio_trigger_unregister(data->dready_trig); @@ -957,22 +951,23 @@ static int bmc150_magn_probe(struct i2c_client *client, bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); return ret; } +EXPORT_SYMBOL(bmc150_magn_probe); -static int bmc150_magn_remove(struct i2c_client *client) +int bmc150_magn_remove(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); iio_device_unregister(indio_dev); - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); iio_triggered_buffer_cleanup(indio_dev); - if (client->irq > 0) - free_irq(data->client->irq, data->dready_trig); + if (data->irq > 0) + free_irq(data->irq, data->dready_trig); if (data->dready_trig) iio_trigger_unregister(data->dready_trig); @@ -983,11 +978,12 @@ static int bmc150_magn_remove(struct i2c_client *client) return 0; } +EXPORT_SYMBOL(bmc150_magn_remove); #ifdef CONFIG_PM static int bmc150_magn_runtime_suspend(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); int ret; @@ -996,7 +992,7 @@ static int bmc150_magn_runtime_suspend(struct device *dev) true); mutex_unlock(&data->mutex); if (ret < 0) { - dev_err(&data->client->dev, "powering off device failed\n"); + dev_err(dev, "powering off device failed\n"); return ret; } return 0; @@ -1007,7 +1003,7 @@ static int bmc150_magn_runtime_suspend(struct device *dev) */ static int bmc150_magn_runtime_resume(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); return bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL, @@ -1018,7 +1014,7 @@ static int bmc150_magn_runtime_resume(struct device *dev) #ifdef CONFIG_PM_SLEEP static int bmc150_magn_suspend(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); int ret; @@ -1032,7 +1028,7 @@ static int bmc150_magn_suspend(struct device *dev) static int bmc150_magn_resume(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); int ret; @@ -1045,38 +1041,13 @@ static int bmc150_magn_resume(struct device *dev) } #endif -static const struct dev_pm_ops bmc150_magn_pm_ops = { +const struct dev_pm_ops bmc150_magn_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(bmc150_magn_suspend, bmc150_magn_resume) SET_RUNTIME_PM_OPS(bmc150_magn_runtime_suspend, bmc150_magn_runtime_resume, NULL) }; - -static const struct acpi_device_id bmc150_magn_acpi_match[] = { - {"BMC150B", 0}, - {"BMC156B", 0}, - {}, -}; -MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); - -static const struct i2c_device_id bmc150_magn_id[] = { - {"bmc150_magn", 0}, - {"bmc156_magn", 0}, - {}, -}; -MODULE_DEVICE_TABLE(i2c, bmc150_magn_id); - -static struct i2c_driver bmc150_magn_driver = { - .driver = { - .name = BMC150_MAGN_DRV_NAME, - .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match), - .pm = &bmc150_magn_pm_ops, - }, - .probe = bmc150_magn_probe, - .remove = bmc150_magn_remove, - .id_table = bmc150_magn_id, -}; -module_i2c_driver(bmc150_magn_driver); +EXPORT_SYMBOL(bmc150_magn_pm_ops); MODULE_AUTHOR("Irina Tirdea "); MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("BMC150 magnetometer driver"); +MODULE_DESCRIPTION("BMC150 magnetometer core driver"); diff --git a/drivers/iio/magnetometer/bmc150_magn.h b/drivers/iio/magnetometer/bmc150_magn.h new file mode 100644 index 000000000000..9a8e26812ca8 --- /dev/null +++ b/drivers/iio/magnetometer/bmc150_magn.h @@ -0,0 +1,11 @@ +#ifndef _BMC150_MAGN_H_ +#define _BMC150_MAGN_H_ + +extern const struct regmap_config bmc150_magn_regmap_config; +extern const struct dev_pm_ops bmc150_magn_pm_ops; + +int bmc150_magn_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name); +int bmc150_magn_remove(struct device *dev); + +#endif /* _BMC150_MAGN_H_ */ diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c new file mode 100644 index 000000000000..eddc7f0d0096 --- /dev/null +++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c @@ -0,0 +1,77 @@ +/* + * 3-axis magnetometer driver supporting following I2C Bosch-Sensortec chips: + * - BMC150 + * - BMC156 + * + * Copyright (c) 2016, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#include +#include +#include +#include +#include +#include + +#include "bmc150_magn.h" + +static int bmc150_magn_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + const char *name = NULL; + + regmap = devm_regmap_init_i2c(client, &bmc150_magn_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to initialize i2c regmap\n"); + return PTR_ERR(regmap); + } + + if (id) + name = id->name; + + return bmc150_magn_probe(&client->dev, regmap, client->irq, name); +} + +static int bmc150_magn_i2c_remove(struct i2c_client *client) +{ + return bmc150_magn_remove(&client->dev); +} + +static const struct acpi_device_id bmc150_magn_acpi_match[] = { + {"BMC150B", 0}, + {"BMC156B", 0}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); + +static const struct i2c_device_id bmc150_magn_i2c_id[] = { + {"bmc150_magn", 0}, + {"bmc156_magn", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); + +static struct i2c_driver bmc150_magn_driver = { + .driver = { + .name = "bmc150_magn_i2c", + .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match), + .pm = &bmc150_magn_pm_ops, + }, + .probe = bmc150_magn_i2c_probe, + .remove = bmc150_magn_i2c_remove, + .id_table = bmc150_magn_i2c_id, +}; +module_i2c_driver(bmc150_magn_driver); + +MODULE_AUTHOR("Daniel Baluta Date: Fri, 15 Apr 2016 17:13:10 +0300 Subject: [PATCH 3265/9938] iio: magn: bmc150: Introduce SPI support Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/Kconfig | 16 +++++ drivers/iio/magnetometer/Makefile | 1 + drivers/iio/magnetometer/bmc150_magn_spi.c | 68 ++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 drivers/iio/magnetometer/bmc150_magn_spi.c diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 4972f9d17023..84e6559ccc65 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -47,6 +47,22 @@ config BMC150_MAGN_I2C To compile this driver as a module, choose M here: the module will be called bmc150_magn_i2c. +config BMC150_MAGN_SPI + tristate "Bosch BMC150 SPI Magnetometer Driver" + depends on SPI + select BMC150_MAGN + select REGMAP_SPI + help + Say yes here to build support for the BMC150 magnetometer with + SPI interface. + + This is a combo module with both accelerometer and magnetometer. + This driver is only implementing magnetometer part, which has + its own address and register map. + + To compile this driver as a module, choose M here: the module will be + called bmc150_magn_spi. + config MAG3110 tristate "Freescale MAG3110 3-Axis Magnetometer" depends on I2C diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index 56477737e083..92a745c9a6e8 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o +obj-$(CONFIG_BMC150_MAGN_SPI) += bmc150_magn_spi.o obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c new file mode 100644 index 000000000000..c4c738a07695 --- /dev/null +++ b/drivers/iio/magnetometer/bmc150_magn_spi.c @@ -0,0 +1,68 @@ +/* + * 3-axis magnetometer driver support following SPI Bosch-Sensortec chips: + * - BMC150 + * - BMC156 + * + * Copyright (c) 2016, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ +#include +#include +#include +#include +#include + +#include "bmc150_magn.h" + +static int bmc150_magn_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + const struct spi_device_id *id = spi_get_device_id(spi); + + regmap = devm_regmap_init_spi(spi, &bmc150_magn_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Failed to register spi regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + return bmc150_magn_probe(&spi->dev, regmap, spi->irq, id->name); +} + +static int bmc150_magn_spi_remove(struct spi_device *spi) +{ + bmc150_magn_remove(&spi->dev); + + return 0; +} + +static const struct spi_device_id bmc150_magn_spi_id[] = { + {"bmc150_magn", 0}, + {"bmc156_magn", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id); + +static const struct acpi_device_id bmc150_magn_acpi_match[] = { + {"BMC150B", 0}, + {"BMC156B", 0}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); + +static struct spi_driver bmc150_magn_spi_driver = { + .probe = bmc150_magn_spi_probe, + .remove = bmc150_magn_spi_remove, + .id_table = bmc150_magn_spi_id, + .driver = { + .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match), + .name = "bmc150_magn_spi", + }, +}; +module_spi_driver(bmc150_magn_spi_driver); + +MODULE_AUTHOR("Daniel Baluta Date: Fri, 15 Apr 2016 12:24:57 +0200 Subject: [PATCH 3266/9938] netfilter: ctnetlink: restore inlining for netlink message size calculation Calm down gcc warnings: net/netfilter/nf_conntrack_netlink.c:529:15: warning: 'ctnetlink_proto_size' defined but not used [-Wunused-function] static size_t ctnetlink_proto_size(const struct nf_conn *ct) ^ net/netfilter/nf_conntrack_netlink.c:546:15: warning: 'ctnetlink_acct_size' defined but not used [-Wunused-function] static size_t ctnetlink_acct_size(const struct nf_conn *ct) ^ net/netfilter/nf_conntrack_netlink.c:556:12: warning: 'ctnetlink_secctx_size' defined but not used [-Wunused-function] static int ctnetlink_secctx_size(const struct nf_conn *ct) ^ net/netfilter/nf_conntrack_netlink.c:572:15: warning: 'ctnetlink_timestamp_size' defined but not used [-Wunused-function] static size_t ctnetlink_timestamp_size(const struct nf_conn *ct) ^ So gcc compiles them out when CONFIG_NF_CONNTRACK_EVENTS and CONFIG_NETFILTER_NETLINK_GLUE_CT are not set. Fixes: 4054ff45454a9a4 ("netfilter: ctnetlink: remove unnecessary inlining") Reported-by: Stephen Rothwell Signed-off-by: Pablo Neira Ayuso Acked-by: Arnd Bergmann --- net/netfilter/nf_conntrack_netlink.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index caa4efe5930b..6cca30ec8535 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -336,7 +336,7 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) #endif #ifdef CONFIG_NF_CONNTRACK_LABELS -static int ctnetlink_label_size(const struct nf_conn *ct) +static inline int ctnetlink_label_size(const struct nf_conn *ct) { struct nf_conn_labels *labels = nf_ct_labels_find(ct); @@ -526,7 +526,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, return -1; } -static size_t ctnetlink_proto_size(const struct nf_conn *ct) +static inline size_t ctnetlink_proto_size(const struct nf_conn *ct) { struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; @@ -543,7 +543,7 @@ static size_t ctnetlink_proto_size(const struct nf_conn *ct) return len; } -static size_t ctnetlink_acct_size(const struct nf_conn *ct) +static inline size_t ctnetlink_acct_size(const struct nf_conn *ct) { if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT)) return 0; @@ -553,7 +553,7 @@ static size_t ctnetlink_acct_size(const struct nf_conn *ct) ; } -static int ctnetlink_secctx_size(const struct nf_conn *ct) +static inline int ctnetlink_secctx_size(const struct nf_conn *ct) { #ifdef CONFIG_NF_CONNTRACK_SECMARK int len, ret; @@ -569,7 +569,7 @@ static int ctnetlink_secctx_size(const struct nf_conn *ct) #endif } -static size_t ctnetlink_timestamp_size(const struct nf_conn *ct) +static inline size_t ctnetlink_timestamp_size(const struct nf_conn *ct) { #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP)) -- GitLab From cef4bafcea2c33b0c296595cebd95f0cfd99f278 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 23 Mar 2016 11:56:50 -0700 Subject: [PATCH 3267/9938] soc: brcmstb: add SoC driver to brcmstb Value of soc_dev_attributes: * family = chip family id * soc_id = product id * revision = product revision Signed-off-by: Justin Chen Signed-off-by: Florian Fainelli --- arch/arm/mach-bcm/Kconfig | 1 + drivers/soc/brcmstb/common.c | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 7ef121472cdd..b95ea1135ef9 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -179,6 +179,7 @@ config ARCH_BRCMSTB select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_WANT_OPTIONAL_GPIOLIB select SOC_BRCMSTB + select SOC_BUS help Say Y if you intend to run the kernel on a Broadcom ARM-based STB chipset. diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c index c262c029b1b8..daf86acf9d01 100644 --- a/drivers/soc/brcmstb/common.c +++ b/drivers/soc/brcmstb/common.c @@ -12,10 +12,18 @@ * GNU General Public License for more details. */ +#include #include +#include +#include +#include +#include #include +static u32 family_id; +static u32 product_id; + static const struct of_device_id brcmstb_machine_match[] = { { .compatible = "brcm,brcmstb", }, { } @@ -31,3 +39,53 @@ bool soc_is_brcmstb(void) return of_match_node(brcmstb_machine_match, root) != NULL; } + +static const struct of_device_id sun_top_ctrl_match[] = { + { .compatible = "brcm,brcmstb-sun-top-ctrl", }, + { } +}; + +static int __init brcmstb_soc_device_init(void) +{ + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device_node *sun_top_ctrl; + void __iomem *sun_top_ctrl_base; + + sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); + if (!sun_top_ctrl) + return -ENODEV; + + sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0); + if (!sun_top_ctrl_base) + return -ENODEV; + + family_id = readl(sun_top_ctrl_base); + product_id = readl(sun_top_ctrl_base + 0x4); + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return -ENOMEM; + + soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x", + family_id >> 28 ? + family_id >> 16 : family_id >> 8); + soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x", + product_id >> 28 ? + product_id >> 16 : product_id >> 8); + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d", + ((product_id & 0xf0) >> 4) + 'A', + product_id & 0xf); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->family); + kfree(soc_dev_attr->soc_id); + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr); + return -ENODEV; + } + + return 0; +} +arch_initcall(brcmstb_soc_device_init); -- GitLab From b0ec633c28d42281c03b41dbc92a4448a481f2f3 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 16 Apr 2016 13:46:14 -0700 Subject: [PATCH 3268/9938] bus: brcmstb_gisb: Rework dependencies Do not have the machine Kconfig entry point need to select BRCMSTB_GISB_ARB, instead, just let it be default ARCH_BRCMSTB which is a better way to deal with this. While at it, also make it default BMIPS_GENERIC so the legacy MIPS-based STB platforms can benefit from the same thing. Signed-off-by: Florian Fainelli --- arch/arm/mach-bcm/Kconfig | 1 - drivers/bus/Kconfig | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index b95ea1135ef9..68ab6412392a 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -173,7 +173,6 @@ config ARCH_BRCMSTB select ARM_GIC select ARM_ERRATA_798181 if SMP select HAVE_ARM_ARCH_TIMER - select BRCMSTB_GISB_ARB select BRCMSTB_L2_IRQ select BCM7120_L2_IRQ select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index d4a3a3133da5..8807495e0efd 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -58,6 +58,7 @@ config ARM_CCN config BRCMSTB_GISB_ARB bool "Broadcom STB GISB bus arbiter" depends on ARM || MIPS + default ARCH_BRCMSTB || BMIPS_GENERIC help Driver for the Broadcom Set Top Box System-on-a-chip internal bus arbiter. This driver provides timeout and target abort error handling -- GitLab From 5ae74f2cc2f150c1a5cee54cabbd71dd0661285a Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 11 Apr 2016 10:13:18 +0800 Subject: [PATCH 3269/9938] ACPI / tables: Move table override mechanisms to tables.c This patch moves acpi_os_table_override() and acpi_os_physical_table_override() to tables.c. Along with the mechanisms, acpi_initrd_initialize_tables() is also moved to tables.c to form a static function. The following functions are renamed according to this change: 1. acpi_initrd_override() -> renamed to early_acpi_table_init(), which invokes acpi_table_initrd_init() 2. acpi_os_physical_table_override() -> which invokes acpi_table_initrd_override() 3. acpi_initialize_initrd_tables() -> renamed to acpi_table_initrd_scan() Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/setup.c | 2 +- drivers/acpi/internal.h | 1 - drivers/acpi/osl.c | 274 ------------------------------------- drivers/acpi/tables.c | 292 +++++++++++++++++++++++++++++++++++++++- include/linux/acpi.h | 10 +- 5 files changed, 294 insertions(+), 285 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 2367ae07eb76..902a6f7b1c04 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1139,7 +1139,7 @@ void __init setup_arch(char **cmdline_p) reserve_initrd(); #if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD) - acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start); + early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start); #endif vsmp_init(); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 7c188472d9c2..1b0e6fd6b280 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -20,7 +20,6 @@ #define PREFIX "ACPI: " -void acpi_initrd_initialize_tables(void); acpi_status acpi_os_initialize1(void); void init_acpi_device_notify(void); int acpi_scan_init(void); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 814d5f83b75e..0796ad96dc32 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -602,280 +602,6 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val, return AE_OK; } -static void acpi_table_taint(struct acpi_table_header *table) -{ - pr_warn(PREFIX - "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n", - table->signature, table->oem_table_id); - add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE); -} - -#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE -#include -#include - -static u64 acpi_tables_addr; -static int all_tables_size; - -/* Copied from acpica/tbutils.c:acpi_tb_checksum() */ -static u8 __init acpi_table_checksum(u8 *buffer, u32 length) -{ - u8 sum = 0; - u8 *end = buffer + length; - - while (buffer < end) - sum = (u8) (sum + *(buffer++)); - return sum; -} - -/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */ -static const char * const table_sigs[] = { - ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ, - ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT, - ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF, - ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET, - ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI, - ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA, - ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, - ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, - ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL }; - -#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) - -#define ACPI_OVERRIDE_TABLES 64 -static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES]; -static DECLARE_BITMAP(acpi_initrd_installed, ACPI_OVERRIDE_TABLES); - -#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) - -void __init acpi_initrd_override(void *data, size_t size) -{ - int sig, no, table_nr = 0, total_offset = 0; - long offset = 0; - struct acpi_table_header *table; - char cpio_path[32] = "kernel/firmware/acpi/"; - struct cpio_data file; - - if (data == NULL || size == 0) - return; - - for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) { - file = find_cpio_data(cpio_path, data, size, &offset); - if (!file.data) - break; - - data += offset; - size -= offset; - - if (file.size < sizeof(struct acpi_table_header)) { - pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n", - cpio_path, file.name); - continue; - } - - table = file.data; - - for (sig = 0; table_sigs[sig]; sig++) - if (!memcmp(table->signature, table_sigs[sig], 4)) - break; - - if (!table_sigs[sig]) { - pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n", - cpio_path, file.name); - continue; - } - if (file.size != table->length) { - pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n", - cpio_path, file.name); - continue; - } - if (acpi_table_checksum(file.data, table->length)) { - pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n", - cpio_path, file.name); - continue; - } - - pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n", - table->signature, cpio_path, file.name, table->length); - - all_tables_size += table->length; - acpi_initrd_files[table_nr].data = file.data; - acpi_initrd_files[table_nr].size = file.size; - table_nr++; - } - if (table_nr == 0) - return; - - acpi_tables_addr = - memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT, - all_tables_size, PAGE_SIZE); - if (!acpi_tables_addr) { - WARN_ON(1); - return; - } - /* - * Only calling e820_add_reserve does not work and the - * tables are invalid (memory got used) later. - * memblock_reserve works as expected and the tables won't get modified. - * But it's not enough on X86 because ioremap will - * complain later (used by acpi_os_map_memory) that the pages - * that should get mapped are not marked "reserved". - * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area) - * works fine. - */ - memblock_reserve(acpi_tables_addr, all_tables_size); - arch_reserve_mem_area(acpi_tables_addr, all_tables_size); - - /* - * early_ioremap only can remap 256k one time. If we map all - * tables one time, we will hit the limit. Need to map chunks - * one by one during copying the same as that in relocate_initrd(). - */ - for (no = 0; no < table_nr; no++) { - unsigned char *src_p = acpi_initrd_files[no].data; - phys_addr_t size = acpi_initrd_files[no].size; - phys_addr_t dest_addr = acpi_tables_addr + total_offset; - phys_addr_t slop, clen; - char *dest_p; - - total_offset += size; - - while (size) { - slop = dest_addr & ~PAGE_MASK; - clen = size; - if (clen > MAP_CHUNK_SIZE - slop) - clen = MAP_CHUNK_SIZE - slop; - dest_p = early_ioremap(dest_addr & PAGE_MASK, - clen + slop); - memcpy(dest_p + slop, src_p, clen); - early_iounmap(dest_p, clen + slop); - src_p += clen; - dest_addr += clen; - size -= clen; - } - } -} - -acpi_status -acpi_os_physical_table_override(struct acpi_table_header *existing_table, - acpi_physical_address *address, u32 *length) -{ - int table_offset = 0; - int table_index = 0; - struct acpi_table_header *table; - u32 table_length; - - *length = 0; - *address = 0; - if (!acpi_tables_addr) - return AE_OK; - - while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) { - table = acpi_os_map_memory(acpi_tables_addr + table_offset, - ACPI_HEADER_SIZE); - if (table_offset + table->length > all_tables_size) { - acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - WARN_ON(1); - return AE_OK; - } - - table_length = table->length; - - /* Only override tables matched */ - if (test_bit(table_index, acpi_initrd_installed) || - memcmp(existing_table->signature, table->signature, 4) || - memcmp(table->oem_table_id, existing_table->oem_table_id, - ACPI_OEM_TABLE_ID_SIZE)) { - acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - goto next_table; - } - - *length = table_length; - *address = acpi_tables_addr + table_offset; - acpi_table_taint(existing_table); - acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - set_bit(table_index, acpi_initrd_installed); - break; - -next_table: - table_offset += table_length; - table_index++; - } - return AE_OK; -} - -void __init acpi_initrd_initialize_tables(void) -{ - int table_offset = 0; - int table_index = 0; - u32 table_length; - struct acpi_table_header *table; - - if (!acpi_tables_addr) - return; - - while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) { - table = acpi_os_map_memory(acpi_tables_addr + table_offset, - ACPI_HEADER_SIZE); - if (table_offset + table->length > all_tables_size) { - acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - WARN_ON(1); - return; - } - - table_length = table->length; - - /* Skip RSDT/XSDT which should only be used for override */ - if (test_bit(table_index, acpi_initrd_installed) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) { - acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - goto next_table; - } - - acpi_table_taint(table); - acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - acpi_install_table(acpi_tables_addr + table_offset, TRUE); - set_bit(table_index, acpi_initrd_installed); -next_table: - table_offset += table_length; - table_index++; - } -} -#else -acpi_status -acpi_os_physical_table_override(struct acpi_table_header *existing_table, - acpi_physical_address *address, - u32 *table_length) -{ - *table_length = 0; - *address = 0; - return AE_OK; -} - -void __init acpi_initrd_initialize_tables(void) -{ -} -#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ - -acpi_status -acpi_os_table_override(struct acpi_table_header *existing_table, - struct acpi_table_header **new_table) -{ - if (!existing_table || !new_table) - return AE_BAD_PARAMETER; - - *new_table = NULL; - -#ifdef CONFIG_ACPI_CUSTOM_DSDT - if (strncmp(existing_table->signature, "DSDT", 4) == 0) - *new_table = (struct acpi_table_header *)AmlCode; -#endif - if (*new_table != NULL) - acpi_table_taint(existing_table); - return AE_OK; -} - static irqreturn_t acpi_irq(int irq, void *dev_id) { u32 handled; diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index f49c02442d65..2e74dbf45dd4 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "internal.h" #define ACPI_MAX_TABLES 128 @@ -433,6 +435,294 @@ static void __init check_multiple_madt(void) return; } +static void acpi_table_taint(struct acpi_table_header *table) +{ + pr_warn("Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n", + table->signature, table->oem_table_id); + add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE); +} + +#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE +static u64 acpi_tables_addr; +static int all_tables_size; + +/* Copied from acpica/tbutils.c:acpi_tb_checksum() */ +static u8 __init acpi_table_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) + sum = (u8) (sum + *(buffer++)); + return sum; +} + +/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */ +static const char * const table_sigs[] = { + ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ, + ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT, + ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF, + ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET, + ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI, + ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA, + ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, + ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, + ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL }; + +#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) + +#define ACPI_OVERRIDE_TABLES 64 +static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES]; +static DECLARE_BITMAP(acpi_initrd_installed, ACPI_OVERRIDE_TABLES); + +#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) + +static void __init acpi_table_initrd_init(void *data, size_t size) +{ + int sig, no, table_nr = 0, total_offset = 0; + long offset = 0; + struct acpi_table_header *table; + char cpio_path[32] = "kernel/firmware/acpi/"; + struct cpio_data file; + + if (data == NULL || size == 0) + return; + + for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) { + file = find_cpio_data(cpio_path, data, size, &offset); + if (!file.data) + break; + + data += offset; + size -= offset; + + if (file.size < sizeof(struct acpi_table_header)) { + pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n", + cpio_path, file.name); + continue; + } + + table = file.data; + + for (sig = 0; table_sigs[sig]; sig++) + if (!memcmp(table->signature, table_sigs[sig], 4)) + break; + + if (!table_sigs[sig]) { + pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n", + cpio_path, file.name); + continue; + } + if (file.size != table->length) { + pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n", + cpio_path, file.name); + continue; + } + if (acpi_table_checksum(file.data, table->length)) { + pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n", + cpio_path, file.name); + continue; + } + + pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n", + table->signature, cpio_path, file.name, table->length); + + all_tables_size += table->length; + acpi_initrd_files[table_nr].data = file.data; + acpi_initrd_files[table_nr].size = file.size; + table_nr++; + } + if (table_nr == 0) + return; + + acpi_tables_addr = + memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT, + all_tables_size, PAGE_SIZE); + if (!acpi_tables_addr) { + WARN_ON(1); + return; + } + /* + * Only calling e820_add_reserve does not work and the + * tables are invalid (memory got used) later. + * memblock_reserve works as expected and the tables won't get modified. + * But it's not enough on X86 because ioremap will + * complain later (used by acpi_os_map_memory) that the pages + * that should get mapped are not marked "reserved". + * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area) + * works fine. + */ + memblock_reserve(acpi_tables_addr, all_tables_size); + arch_reserve_mem_area(acpi_tables_addr, all_tables_size); + + /* + * early_ioremap only can remap 256k one time. If we map all + * tables one time, we will hit the limit. Need to map chunks + * one by one during copying the same as that in relocate_initrd(). + */ + for (no = 0; no < table_nr; no++) { + unsigned char *src_p = acpi_initrd_files[no].data; + phys_addr_t size = acpi_initrd_files[no].size; + phys_addr_t dest_addr = acpi_tables_addr + total_offset; + phys_addr_t slop, clen; + char *dest_p; + + total_offset += size; + + while (size) { + slop = dest_addr & ~PAGE_MASK; + clen = size; + if (clen > MAP_CHUNK_SIZE - slop) + clen = MAP_CHUNK_SIZE - slop; + dest_p = early_ioremap(dest_addr & PAGE_MASK, + clen + slop); + memcpy(dest_p + slop, src_p, clen); + early_iounmap(dest_p, clen + slop); + src_p += clen; + dest_addr += clen; + size -= clen; + } + } +} + +static acpi_status +acpi_table_initrd_override(struct acpi_table_header *existing_table, + acpi_physical_address *address, u32 *length) +{ + int table_offset = 0; + int table_index = 0; + struct acpi_table_header *table; + u32 table_length; + + *length = 0; + *address = 0; + if (!acpi_tables_addr) + return AE_OK; + + while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) { + table = acpi_os_map_memory(acpi_tables_addr + table_offset, + ACPI_HEADER_SIZE); + if (table_offset + table->length > all_tables_size) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + WARN_ON(1); + return AE_OK; + } + + table_length = table->length; + + /* Only override tables matched */ + if (test_bit(table_index, acpi_initrd_installed) || + memcmp(existing_table->signature, table->signature, 4) || + memcmp(table->oem_table_id, existing_table->oem_table_id, + ACPI_OEM_TABLE_ID_SIZE)) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + goto next_table; + } + + *length = table_length; + *address = acpi_tables_addr + table_offset; + acpi_table_taint(existing_table); + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + set_bit(table_index, acpi_initrd_installed); + break; + +next_table: + table_offset += table_length; + table_index++; + } + return AE_OK; +} + +static void __init acpi_table_initrd_scan(void) +{ + int table_offset = 0; + int table_index = 0; + u32 table_length; + struct acpi_table_header *table; + + if (!acpi_tables_addr) + return; + + while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) { + table = acpi_os_map_memory(acpi_tables_addr + table_offset, + ACPI_HEADER_SIZE); + if (table_offset + table->length > all_tables_size) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + WARN_ON(1); + return; + } + + table_length = table->length; + + /* Skip RSDT/XSDT which should only be used for override */ + if (test_bit(table_index, acpi_initrd_installed) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + goto next_table; + } + + acpi_table_taint(table); + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + acpi_install_table(acpi_tables_addr + table_offset, TRUE); + set_bit(table_index, acpi_initrd_installed); +next_table: + table_offset += table_length; + table_index++; + } +} +#else +static void __init acpi_table_initrd_init(void *data, size_t size) +{ +} + +static acpi_status +acpi_table_initrd_override(struct acpi_table_header *existing_table, + acpi_physical_address *address, + u32 *table_length) +{ + *table_length = 0; + *address = 0; + return AE_OK; +} + +static void __init acpi_table_initrd_scan(void) +{ +} +#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ + +acpi_status +acpi_os_physical_table_override(struct acpi_table_header *existing_table, + acpi_physical_address *address, + u32 *table_length) +{ + return acpi_table_initrd_override(existing_table, address, + table_length); +} + +acpi_status +acpi_os_table_override(struct acpi_table_header *existing_table, + struct acpi_table_header **new_table) +{ + if (!existing_table || !new_table) + return AE_BAD_PARAMETER; + + *new_table = NULL; + +#ifdef CONFIG_ACPI_CUSTOM_DSDT + if (strncmp(existing_table->signature, "DSDT", 4) == 0) + *new_table = (struct acpi_table_header *)AmlCode; +#endif + if (*new_table != NULL) + acpi_table_taint(existing_table); + return AE_OK; +} + +void __init early_acpi_table_init(void *data, size_t size) +{ + acpi_table_initrd_init(data, size); +} + /* * acpi_table_init() * @@ -457,7 +747,7 @@ int __init acpi_table_init(void) status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); if (ACPI_FAILURE(status)) return -EINVAL; - acpi_initrd_initialize_tables(); + acpi_table_initrd_scan(); check_multiple_madt(); return 0; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 06ed7e54033e..7718c04aa09f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -190,14 +190,6 @@ static inline int acpi_debugger_notify_command_complete(void) } #endif -#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE -void acpi_initrd_override(void *data, size_t size); -#else -static inline void acpi_initrd_override(void *data, size_t size) -{ -} -#endif - #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ ((struct acpi_subtable_header *)entry)->length < sizeof(*entry)) @@ -216,6 +208,7 @@ void acpi_boot_table_init (void); int acpi_mps_check (void); int acpi_numa_init (void); +void early_acpi_table_init(void *data, size_t size); int acpi_table_init (void); int acpi_table_parse(char *id, acpi_tbl_table_handler handler); int __init acpi_parse_entries(char *id, unsigned long table_size, @@ -596,6 +589,7 @@ static inline const char *acpi_dev_name(struct acpi_device *adev) return NULL; } +static inline void early_acpi_table_init(void *data, size_t size) { } static inline void acpi_early_init(void) { } static inline void acpi_subsystem_init(void) { } -- GitLab From af06f8b7a102417e93dc57ee7affb9fedcf5d83f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 11 Apr 2016 10:13:27 +0800 Subject: [PATCH 3270/9938] ACPI / x86: Cleanup initrd related code In arch/x86/kernel/setup.c, the #ifdef kept for CONFIG_ACPI actually is related to the accessibility of initrd_start/initrd_end, so the stub should be provided from this source file and should only be dependent on CONFIG_BLK_DEV_INITRD. Note that when ACPI=n and BLK_DEV_INITRD=y, early_initrd_acpi_init() is still a stub because of the stub prepared for early_acpi_table_init(). Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/setup.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 902a6f7b1c04..c4e7b3991b60 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -398,6 +398,11 @@ static void __init reserve_initrd(void) memblock_free(ramdisk_image, ramdisk_end - ramdisk_image); } + +static void __init early_initrd_acpi_init(void) +{ + early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start); +} #else static void __init early_reserve_initrd(void) { @@ -405,6 +410,9 @@ static void __init early_reserve_initrd(void) static void __init reserve_initrd(void) { } +static void __init early_initrd_acpi_init(void) +{ +} #endif /* CONFIG_BLK_DEV_INITRD */ static void __init parse_setup_data(void) @@ -1138,9 +1146,7 @@ void __init setup_arch(char **cmdline_p) reserve_initrd(); -#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD) - early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start); -#endif + early_initrd_acpi_init(); vsmp_init(); -- GitLab From 5d8813271f8a7c86027afb2ef554f2a5a9ba7c15 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 11 Apr 2016 10:13:33 +0800 Subject: [PATCH 3271/9938] ACPI / tables: Convert initrd table override to table upgrade mechanism This patch converts the initrd table override mechanism to the table upgrade mechanism by restricting its usage to the tables released with compatibility and more recent revision. This use case has been encouraged by the ACPI specification: 1. OEMID: An OEM-supplied string that identifies the OEM. 2. OEM Table ID: An OEM-supplied string that the OEM uses to identify the particular data table. This field is particularly useful when defining a definition block to distinguish definition block functions. OEM assigns each dissimilar table a new OEM Table Id. 3. OEM Revision: An OEM-supplied revision number. Larger numbers are assumed to be newer revisions. For OEMs, good practices will ensure consistency when assigning OEMID and OEM Table ID fields in any table. The intent of these fields is to allow for a binary control system that support services can use. Because many support function can be automated, it is useful when a tool can programatically determine which table release is a compatible and more recent revision of a prior table on the same OEMID and OEM Table ID. The facility can now be used by the vendors to upgrade wrong tables for bug fixing purpose, thus lockdep disabling taint is not suitable for it and it should be a default 'y' option to implement the spec encouraged use case. Note that, by implementing table upgrade inside of ACPICA itself, it is possible to remove acpi_table_initrd_override() and tables can be upgraded by acpi_install_table() automatically. Though current ACPICA impelentation hasn't implemented this, this patched changes the table flag setting timing to allow this to be implemented in ACPICA without changing the code here. Documentation of initrd override mechanism is upgraded accordingly. Original-by: Octavian Purdila Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- Documentation/acpi/initrd_table_override.txt | 65 ++++++++++++-------- drivers/acpi/Kconfig | 8 +-- drivers/acpi/tables.c | 48 ++++++++++----- 3 files changed, 77 insertions(+), 44 deletions(-) diff --git a/Documentation/acpi/initrd_table_override.txt b/Documentation/acpi/initrd_table_override.txt index 35c3f5415476..eb651a6aa285 100644 --- a/Documentation/acpi/initrd_table_override.txt +++ b/Documentation/acpi/initrd_table_override.txt @@ -1,5 +1,5 @@ -Overriding ACPI tables via initrd -================================= +Upgrading ACPI tables via initrd +================================ 1) Introduction (What is this about) 2) What is this for @@ -9,12 +9,14 @@ Overriding ACPI tables via initrd 1) What is this about --------------------- -If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to -override nearly any ACPI table provided by the BIOS with an instrumented, -modified one. +If the ACPI_TABLE_UPGRADE compile option is true, it is possible to +upgrade the ACPI execution environment that is defined by the ACPI tables +via upgrading the ACPI tables provided by the BIOS with an instrumented, +modified, more recent version one, or installing brand new ACPI tables. -For a full list of ACPI tables that can be overridden, take a look at -the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c +For a full list of ACPI tables that can be upgraded/installed, take a look +at the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in +drivers/acpi/tables.c. All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should be overridable, except: - ACPI_SIG_RSDP (has a signature of 6 bytes) @@ -25,17 +27,20 @@ Both could get implemented as well. 2) What is this for ------------------- -Please keep in mind that this is a debug option. -ACPI tables should not get overridden for productive use. -If BIOS ACPI tables are overridden the kernel will get tainted with the -TAINT_OVERRIDDEN_ACPI_TABLE flag. -Complain to your platform/BIOS vendor if you find a bug which is so sever -that a workaround is not accepted in the Linux kernel. +Complain to your platform/BIOS vendor if you find a bug which is so severe +that a workaround is not accepted in the Linux kernel. And this facility +allows you to upgrade the buggy tables before your platform/BIOS vendor +releases an upgraded BIOS binary. -Still, it can and should be enabled in any kernel, because: - - There is no functional change with not instrumented initrds - - It provides a powerful feature to easily debug and test ACPI BIOS table - compatibility with the Linux kernel. +This facility can be used by platform/BIOS vendors to provide a Linux +compatible environment without modifying the underlying platform firmware. + +This facility also provides a powerful feature to easily debug and test +ACPI BIOS table compatibility with the Linux kernel by modifying old +platform provided ACPI tables or inserting new ACPI tables. + +It can and should be enabled in any kernel because there is no functional +change with not instrumented initrds. 3) How does it work @@ -50,23 +55,31 @@ iasl -d *.dat # For example add this statement into a _PRT (PCI Routing Table) function # of the DSDT: Store("HELLO WORLD", debug) +# And increase the OEM Revision. For example, before modification: +DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000000) +# After modification: +DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000001) iasl -sa dsdt.dsl # Add the raw ACPI tables to an uncompressed cpio archive. -# They must be put into a /kernel/firmware/acpi directory inside the -# cpio archive. -# The uncompressed cpio archive must be the first. -# Other, typically compressed cpio archives, must be -# concatenated on top of the uncompressed one. +# They must be put into a /kernel/firmware/acpi directory inside the cpio +# archive. Note that if the table put here matches a platform table +# (similar Table Signature, and similar OEMID, and similar OEM Table ID) +# with a more recent OEM Revision, the platform table will be upgraded by +# this table. If the table put here doesn't match a platform table +# (dissimilar Table Signature, or dissimilar OEMID, or dissimilar OEM Table +# ID), this table will be appended. mkdir -p kernel/firmware/acpi cp dsdt.aml kernel/firmware/acpi -# A maximum of: #define ACPI_OVERRIDE_TABLES 10 -# tables are currently allowed (see osl.c): +# A maximum of "NR_ACPI_INITRD_TABLES (64)" tables are currently allowed +# (see osl.c): iasl -sa facp.dsl iasl -sa ssdt1.dsl cp facp.aml kernel/firmware/acpi cp ssdt1.aml kernel/firmware/acpi -# Create the uncompressed cpio archive and concatenate the original initrd -# on top: +# The uncompressed cpio archive must be the first. Other, typically +# compressed cpio archives, must be concatenated on top of the uncompressed +# one. Following command creates the uncompressed cpio archive and +# concatenates the original initrd on top: find kernel | cpio -H newc --create > /boot/instrumented_initrd cat /boot/initrd >>/boot/instrumented_initrd # reboot with increased acpi debug level, e.g. boot params: diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 82b96ee8624c..b225c4b9ba14 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -311,12 +311,12 @@ config ACPI_CUSTOM_DSDT bool default ACPI_CUSTOM_DSDT_FILE != "" -config ACPI_INITRD_TABLE_OVERRIDE - bool "ACPI tables override via initrd" +config ACPI_TABLE_UPGRADE + bool "Allow upgrading ACPI tables via initrd" depends on BLK_DEV_INITRD && X86 - default n + default y help - This option provides functionality to override arbitrary ACPI tables + This option provides functionality to upgrade arbitrary ACPI tables via initrd. No functional change if no ACPI tables are passed via initrd, therefore it's safe to say Y. See Documentation/acpi/initrd_table_override.txt for details diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 2e74dbf45dd4..08795fbde3fa 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -442,7 +442,7 @@ static void acpi_table_taint(struct acpi_table_header *table) add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE); } -#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE +#ifdef CONFIG_ACPI_TABLE_UPGRADE static u64 acpi_tables_addr; static int all_tables_size; @@ -471,9 +471,9 @@ static const char * const table_sigs[] = { #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) -#define ACPI_OVERRIDE_TABLES 64 -static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES]; -static DECLARE_BITMAP(acpi_initrd_installed, ACPI_OVERRIDE_TABLES); +#define NR_ACPI_INITRD_TABLES 64 +static struct cpio_data __initdata acpi_initrd_files[NR_ACPI_INITRD_TABLES]; +static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES); #define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) @@ -488,7 +488,7 @@ static void __init acpi_table_initrd_init(void *data, size_t size) if (data == NULL || size == 0) return; - for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) { + for (no = 0; no < NR_ACPI_INITRD_TABLES; no++) { file = find_cpio_data(cpio_path, data, size, &offset); if (!file.data) break; @@ -611,19 +611,30 @@ acpi_table_initrd_override(struct acpi_table_header *existing_table, table_length = table->length; /* Only override tables matched */ - if (test_bit(table_index, acpi_initrd_installed) || - memcmp(existing_table->signature, table->signature, 4) || + if (memcmp(existing_table->signature, table->signature, 4) || + memcmp(table->oem_id, existing_table->oem_id, + ACPI_OEM_ID_SIZE) || memcmp(table->oem_table_id, existing_table->oem_table_id, ACPI_OEM_TABLE_ID_SIZE)) { acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); goto next_table; } + /* + * Mark the table to avoid being used in + * acpi_table_initrd_scan() and check the revision. + */ + if (test_and_set_bit(table_index, acpi_initrd_installed) || + existing_table->oem_revision >= table->oem_revision) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + goto next_table; + } *length = table_length; *address = acpi_tables_addr + table_offset; - acpi_table_taint(existing_table); + pr_info("Table Upgrade: override [%4.4s-%6.6s-%8.8s]\n", + table->signature, table->oem_id, + table->oem_table_id); acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); - set_bit(table_index, acpi_initrd_installed); break; next_table: @@ -655,17 +666,26 @@ static void __init acpi_table_initrd_scan(void) table_length = table->length; /* Skip RSDT/XSDT which should only be used for override */ - if (test_bit(table_index, acpi_initrd_installed) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) || + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) || ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) { acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); goto next_table; } + /* + * Mark the table to avoid being used in + * acpi_table_initrd_override(). Though this is not possible + * because override is disabled in acpi_install_table(). + */ + if (test_and_set_bit(table_index, acpi_initrd_installed)) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + goto next_table; + } - acpi_table_taint(table); + pr_info("Table Upgrade: install [%4.4s-%6.6s-%8.8s]\n", + table->signature, table->oem_id, + table->oem_table_id); acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); acpi_install_table(acpi_tables_addr + table_offset, TRUE); - set_bit(table_index, acpi_initrd_installed); next_table: table_offset += table_length; table_index++; @@ -689,7 +709,7 @@ acpi_table_initrd_override(struct acpi_table_header *existing_table, static void __init acpi_table_initrd_scan(void) { } -#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ +#endif /* CONFIG_ACPI_TABLE_UPGRADE */ acpi_status acpi_os_physical_table_override(struct acpi_table_header *existing_table, -- GitLab From b520bd07595b117a08871ebc0a16452cc798d35b Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 17 Apr 2016 01:05:19 +0300 Subject: [PATCH 3272/9938] of_mdio: make of_mdiobus_register_{device|phy}() *void* The results of of_mdiobus_register_{device|phy}() are never checked, so we can make both these functions *void*... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 8453f08d2ef4..2c1e52e06102 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -41,8 +41,8 @@ static int of_get_phy_id(struct device_node *device, u32 *phy_id) return -EINVAL; } -static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *child, - u32 addr) +static void of_mdiobus_register_phy(struct mii_bus *mdio, + struct device_node *child, u32 addr) { struct phy_device *phy; bool is_c45; @@ -57,7 +57,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi else phy = get_phy_device(mdio, addr, is_c45); if (IS_ERR_OR_NULL(phy)) - return 1; + return; rc = irq_of_parse_and_map(child, 0); if (rc > 0) { @@ -81,25 +81,22 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi if (rc) { phy_device_free(phy); of_node_put(child); - return 1; + return; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); - - return 0; } -static int of_mdiobus_register_device(struct mii_bus *mdio, - struct device_node *child, - u32 addr) +static void of_mdiobus_register_device(struct mii_bus *mdio, + struct device_node *child, u32 addr) { struct mdio_device *mdiodev; int rc; mdiodev = mdio_device_create(mdio, addr); if (IS_ERR(mdiodev)) - return 1; + return; /* Associate the OF node with the device structure so it * can be looked up later. @@ -112,13 +109,11 @@ static int of_mdiobus_register_device(struct mii_bus *mdio, if (rc) { mdio_device_free(mdiodev); of_node_put(child); - return 1; + return; } dev_dbg(&mdio->dev, "registered mdio device %s at address %i\n", child->name, addr); - - return 0; } int of_mdio_parse_addr(struct device *dev, const struct device_node *np) -- GitLab From 266a0a790fb545fa1802a899ac44f61b1d6335a7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 16 Apr 2016 22:29:33 +0200 Subject: [PATCH 3273/9938] bpf: avoid warning for wrong pointer cast Two new functions in bpf contain a cast from a 'u64' to a pointer. This works on 64-bit architectures but causes a warning on all 32-bit architectures: kernel/trace/bpf_trace.c: In function 'bpf_perf_event_output_tp': kernel/trace/bpf_trace.c:350:13: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] u64 ctx = *(long *)r1; This changes the cast to first convert the u64 argument into a uintptr_t, which is guaranteed to be the same size as a pointer. Signed-off-by: Arnd Bergmann Fixes: 9940d67c93b5 ("bpf: support bpf_get_stackid() and bpf_perf_event_output() in tracepoint programs") Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/trace/bpf_trace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 685587885374..f389629dade7 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -351,7 +351,7 @@ static u64 bpf_perf_event_output_tp(u64 r1, u64 r2, u64 index, u64 r4, u64 size) * from bpf program and contain a pointer to 'struct pt_regs'. Fetch it * from there and call the same bpf_perf_event_output() helper */ - u64 ctx = *(long *)r1; + u64 ctx = *(long *)(uintptr_t)r1; return bpf_perf_event_output(ctx, r2, index, r4, size); } @@ -369,7 +369,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_tp = { static u64 bpf_get_stackid_tp(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) { - u64 ctx = *(long *)r1; + u64 ctx = *(long *)(uintptr_t)r1; return bpf_get_stackid(ctx, r2, r3, r4, r5); } -- GitLab From b67d1df5ad0c227adc89d2913e933ed4addc5dab Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Apr 2016 23:58:30 +0200 Subject: [PATCH 3274/9938] net: w5100: don't build spi driver without w5100 The w5100-spi driver front-end only makes sense when the w5100 core driver is enabled, not for a configuration that only has w5300: drivers/net/built-in.o: In function `w5100_spi_remove': drivers/net/ethernet/wiznet/w5100-spi.c:277: undefined reference to `w5100_remove' drivers/net/built-in.o: In function `w5100_spi_probe': drivers/net/ethernet/wiznet/w5100-spi.c:272: undefined reference to `w5100_probe' drivers/net/built-in.o: In function `w5200_spi_init': drivers/net/ethernet/wiznet/w5100-spi.c:125: undefined reference to `w5100_ops_priv' drivers/net/built-in.o: In function `w5200_spi_readbulk': drivers/net/ethernet/wiznet/w5100-spi.c:125: undefined reference to `w5100_ops_priv' drivers/net/built-in.o: In function `w5200_spi_writebulk': drivers/net/ethernet/wiznet/w5100-spi.c:125: undefined reference to `w5100_ops_priv' drivers/net/built-in.o:(.data+0x3ed1c): undefined reference to `w5100_pm_ops' This adds an appropriate Kconfig dependency. Signed-off-by: Arnd Bergmann Fixes: 630cf09751fe ("net: w5100: support SPI interface mode") Signed-off-by: David S. Miller --- drivers/net/ethernet/wiznet/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig index 1f15376e9856..f3385a1999a2 100644 --- a/drivers/net/ethernet/wiznet/Kconfig +++ b/drivers/net/ethernet/wiznet/Kconfig @@ -71,7 +71,7 @@ endchoice config WIZNET_W5100_SPI tristate "WIZnet W5100/W5200 Ethernet support for SPI mode" - depends on WIZNET_BUS_ANY + depends on WIZNET_BUS_ANY && WIZNET_W5100 depends on SPI ---help--- In SPI mode host system accesses registers using SPI protocol -- GitLab From c796c50b9c20b586cd8c3e3a57cea4f0762a60fc Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Tue, 5 Apr 2016 09:41:47 +0100 Subject: [PATCH 3275/9938] mfd: da9063: Remove unused struct da9063_irq_data and define EVENTS_BUF_LEN The structure da9063_irq_data and define EVENTS_BUF_LEN are not used, so remove the redundant entries. Signed-off-by: Steve Twiss Signed-off-by: Lee Jones --- drivers/mfd/da9063-irq.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index 0aa760e155ec..7e903fcb8813 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c @@ -25,12 +25,6 @@ #define DA9063_REG_EVENT_B_OFFSET 1 #define DA9063_REG_EVENT_C_OFFSET 2 #define DA9063_REG_EVENT_D_OFFSET 3 -#define EVENTS_BUF_LEN 4 - -struct da9063_irq_data { - u16 reg; - u8 mask; -}; static const struct regmap_irq da9063_irqs[] = { /* DA9063 event A register */ -- GitLab From 073d4aca342029fc62fefa500bb11a556c5f7223 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 4 Apr 2016 16:54:18 +0900 Subject: [PATCH 3276/9938] mfd: max77693: Allow building as a module The consumer of max77693 regulators on Trats2 board (samsung-usb2-phy driver) supports deferred probing so the max77693 main MFD driver can be built now as a module. This gives more flexibility and removes manual ordering of init calls. Suggested-by: Paul Gortmaker Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 4 ++-- drivers/mfd/max77693.c | 14 ++------------ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index eea61e349e26..aa1e7c3f82ee 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -543,8 +543,8 @@ config MFD_MAX77686 of the device. config MFD_MAX77693 - bool "Maxim Semiconductor MAX77693 PMIC Support" - depends on I2C=y + tristate "Maxim Semiconductor MAX77693 PMIC Support" + depends on I2C select MFD_CORE select REGMAP_I2C select REGMAP_IRQ diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index b83b7a7da1ae..78e501feb96c 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -368,6 +368,7 @@ static const struct of_device_id max77693_dt_match[] = { { .compatible = "maxim,max77693" }, {}, }; +MODULE_DEVICE_TABLE(of, max77693_dt_match); #endif static struct i2c_driver max77693_i2c_driver = { @@ -381,18 +382,7 @@ static struct i2c_driver max77693_i2c_driver = { .id_table = max77693_i2c_id, }; -static int __init max77693_i2c_init(void) -{ - return i2c_add_driver(&max77693_i2c_driver); -} -/* init early so consumer devices can complete system boot */ -subsys_initcall(max77693_i2c_init); - -static void __exit max77693_i2c_exit(void) -{ - i2c_del_driver(&max77693_i2c_driver); -} -module_exit(max77693_i2c_exit); +module_i2c_driver(max77693_i2c_driver); MODULE_DESCRIPTION("MAXIM 77693 multi-function core driver"); MODULE_AUTHOR("SangYoung, Son "); -- GitLab From dedf24a28da67f6bf814cb5d05a5d12bb39093dc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 25 Mar 2016 14:27:09 +0000 Subject: [PATCH 3277/9938] mfd: arizona: Fix lockdep recursion warning on set_irq_wake Avoid a false recursive locking warning from lockdep by adding a lock class for the arizona IRQ chip. Signed-off-by: Charles Keepax Acked-by: Thomas Gleixner Signed-off-by: Lee Jones --- drivers/mfd/arizona-irq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 5fef014920a3..edeb4951366a 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -168,12 +168,15 @@ static struct irq_chip arizona_irq_chip = { .irq_set_wake = arizona_irq_set_wake, }; +static struct lock_class_key arizona_irq_lock_class; + static int arizona_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { struct arizona *data = h->host_data; irq_set_chip_data(virq, data); + irq_set_lockdep_class(virq, &arizona_irq_lock_class); irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq); irq_set_nested_thread(virq, 1); irq_set_noprobe(virq); -- GitLab From 20147f0d4f50f6f0d1fbe1815fe3d4d0a6444a70 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 29 Mar 2016 17:22:26 +0800 Subject: [PATCH 3278/9938] mfd: axp20x: Add support for AXP809 PMIC The X-Powers AXP809 is a new PMIC that is paired with Allwinner's A80 SoC, along with a slave AXP806 PMIC. This PMIC is quite similar to the earlier AXP223, though the interrupts and regulator have changed a bit. This patch adds support for the interrupts and power button of the PMIC. Signed-off-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/axp20x-rsb.c | 1 + drivers/mfd/axp20x.c | 79 ++++++++++++++++++++++++++++++++++++++ include/linux/mfd/axp20x.h | 59 ++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c index 28c20247c112..a407527bcd09 100644 --- a/drivers/mfd/axp20x-rsb.c +++ b/drivers/mfd/axp20x-rsb.c @@ -61,6 +61,7 @@ static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev) static const struct of_device_id axp20x_rsb_of_match[] = { { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, + { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID }, { }, }; MODULE_DEVICE_TABLE(of, axp20x_rsb_of_match); diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index a57d6e940610..1ce923277cc8 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -37,6 +37,7 @@ static const char * const axp20x_model_names[] = { "AXP221", "AXP223", "AXP288", + "AXP809", }; static const struct regmap_range axp152_writeable_ranges[] = { @@ -85,6 +86,7 @@ static const struct regmap_access_table axp20x_volatile_table = { .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), }; +/* AXP22x ranges are shared with the AXP809, as they cover the same range */ static const struct regmap_range axp22x_writeable_ranges[] = { regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1), @@ -211,6 +213,20 @@ static struct resource axp288_fuel_gauge_resources[] = { }, }; +static struct resource axp809_pek_resources[] = { + { + .name = "PEK_DBR", + .start = AXP809_IRQ_PEK_RIS_EDGE, + .end = AXP809_IRQ_PEK_RIS_EDGE, + .flags = IORESOURCE_IRQ, + }, { + .name = "PEK_DBF", + .start = AXP809_IRQ_PEK_FAL_EDGE, + .end = AXP809_IRQ_PEK_FAL_EDGE, + .flags = IORESOURCE_IRQ, + }, +}; + static const struct regmap_config axp152_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -378,6 +394,41 @@ static const struct regmap_irq axp288_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), }; +static const struct regmap_irq axp809_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7), + INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6), + INIT_REGMAP_IRQ(AXP809, ACIN_REMOVAL, 0, 5), + INIT_REGMAP_IRQ(AXP809, VBUS_OVER_V, 0, 4), + INIT_REGMAP_IRQ(AXP809, VBUS_PLUGIN, 0, 3), + INIT_REGMAP_IRQ(AXP809, VBUS_REMOVAL, 0, 2), + INIT_REGMAP_IRQ(AXP809, VBUS_V_LOW, 0, 1), + INIT_REGMAP_IRQ(AXP809, BATT_PLUGIN, 1, 7), + INIT_REGMAP_IRQ(AXP809, BATT_REMOVAL, 1, 6), + INIT_REGMAP_IRQ(AXP809, BATT_ENT_ACT_MODE, 1, 5), + INIT_REGMAP_IRQ(AXP809, BATT_EXIT_ACT_MODE, 1, 4), + INIT_REGMAP_IRQ(AXP809, CHARG, 1, 3), + INIT_REGMAP_IRQ(AXP809, CHARG_DONE, 1, 2), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH, 2, 7), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH_END, 2, 6), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW, 2, 5), + INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW_END, 2, 4), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH, 2, 3), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH_END, 2, 2), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW, 2, 1), + INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW_END, 2, 0), + INIT_REGMAP_IRQ(AXP809, DIE_TEMP_HIGH, 3, 7), + INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL1, 3, 1), + INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL2, 3, 0), + INIT_REGMAP_IRQ(AXP809, TIMER, 4, 7), + INIT_REGMAP_IRQ(AXP809, PEK_RIS_EDGE, 4, 6), + INIT_REGMAP_IRQ(AXP809, PEK_FAL_EDGE, 4, 5), + INIT_REGMAP_IRQ(AXP809, PEK_SHORT, 4, 4), + INIT_REGMAP_IRQ(AXP809, PEK_LONG, 4, 3), + INIT_REGMAP_IRQ(AXP809, PEK_OVER_OFF, 4, 2), + INIT_REGMAP_IRQ(AXP809, GPIO1_INPUT, 4, 1), + INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), +}; + static const struct regmap_irq_chip axp152_regmap_irq_chip = { .name = "axp152_irq_chip", .status_base = AXP152_IRQ1_STATE, @@ -428,6 +479,18 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = { }; +static const struct regmap_irq_chip axp809_regmap_irq_chip = { + .name = "axp809", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, + .mask_base = AXP20X_IRQ1_EN, + .mask_invert = true, + .init_ack_masked = true, + .irqs = axp809_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp809_regmap_irqs), + .num_regs = 5, +}; + static struct mfd_cell axp20x_cells[] = { { .name = "axp20x-pek", @@ -572,6 +635,16 @@ static struct mfd_cell axp288_cells[] = { }, }; +static struct mfd_cell axp809_cells[] = { + { + .name = "axp20x-pek", + .num_resources = ARRAY_SIZE(axp809_pek_resources), + .resources = axp809_pek_resources, + }, { + .name = "axp20x-regulator", + }, +}; + static struct axp20x_dev *axp20x_pm_power_off; static void axp20x_power_off(void) { @@ -631,6 +704,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->regmap_cfg = &axp288_regmap_config; axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; break; + case AXP809_ID: + axp20x->nr_cells = ARRAY_SIZE(axp809_cells); + axp20x->cells = axp809_cells; + axp20x->regmap_cfg = &axp22x_regmap_config; + axp20x->regmap_irq_chip = &axp809_regmap_irq_chip; + break; default: dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); return -EINVAL; diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index d82e7d51372b..0be4982f08fe 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -20,6 +20,7 @@ enum { AXP221_ID, AXP223_ID, AXP288_ID, + AXP809_ID, NR_AXP20X_VARIANTS, }; @@ -264,6 +265,29 @@ enum { AXP22X_REG_ID_MAX, }; +enum { + AXP809_DCDC1 = 0, + AXP809_DCDC2, + AXP809_DCDC3, + AXP809_DCDC4, + AXP809_DCDC5, + AXP809_DC1SW, + AXP809_DC5LDO, + AXP809_ALDO1, + AXP809_ALDO2, + AXP809_ALDO3, + AXP809_ELDO1, + AXP809_ELDO2, + AXP809_ELDO3, + AXP809_DLDO1, + AXP809_DLDO2, + AXP809_RTC_LDO, + AXP809_LDO_IO0, + AXP809_LDO_IO1, + AXP809_SW, + AXP809_REG_ID_MAX, +}; + /* IRQs */ enum { AXP152_IRQ_LDO0IN_CONNECT = 1, @@ -390,6 +414,41 @@ enum axp288_irqs { AXP288_IRQ_BC_USB_CHNG, }; +enum axp809_irqs { + AXP809_IRQ_ACIN_OVER_V = 1, + AXP809_IRQ_ACIN_PLUGIN, + AXP809_IRQ_ACIN_REMOVAL, + AXP809_IRQ_VBUS_OVER_V, + AXP809_IRQ_VBUS_PLUGIN, + AXP809_IRQ_VBUS_REMOVAL, + AXP809_IRQ_VBUS_V_LOW, + AXP809_IRQ_BATT_PLUGIN, + AXP809_IRQ_BATT_REMOVAL, + AXP809_IRQ_BATT_ENT_ACT_MODE, + AXP809_IRQ_BATT_EXIT_ACT_MODE, + AXP809_IRQ_CHARG, + AXP809_IRQ_CHARG_DONE, + AXP809_IRQ_BATT_CHG_TEMP_HIGH, + AXP809_IRQ_BATT_CHG_TEMP_HIGH_END, + AXP809_IRQ_BATT_CHG_TEMP_LOW, + AXP809_IRQ_BATT_CHG_TEMP_LOW_END, + AXP809_IRQ_BATT_ACT_TEMP_HIGH, + AXP809_IRQ_BATT_ACT_TEMP_HIGH_END, + AXP809_IRQ_BATT_ACT_TEMP_LOW, + AXP809_IRQ_BATT_ACT_TEMP_LOW_END, + AXP809_IRQ_DIE_TEMP_HIGH, + AXP809_IRQ_LOW_PWR_LVL1, + AXP809_IRQ_LOW_PWR_LVL2, + AXP809_IRQ_TIMER, + AXP809_IRQ_PEK_RIS_EDGE, + AXP809_IRQ_PEK_FAL_EDGE, + AXP809_IRQ_PEK_SHORT, + AXP809_IRQ_PEK_LONG, + AXP809_IRQ_PEK_OVER_OFF, + AXP809_IRQ_GPIO1_INPUT, + AXP809_IRQ_GPIO0_INPUT, +}; + #define AXP288_TS_ADC_H 0x58 #define AXP288_TS_ADC_L 0x59 #define AXP288_GP_ADC_H 0x5a -- GitLab From bd425113a186f6dc104e07cd501916dc51f25e6a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 29 Mar 2016 17:22:25 +0800 Subject: [PATCH 3279/9938] mfd: axp20x: Add bindings for AXP809 PMIC This patch adds the basic and regulator bindings for the X-Powers AXP809 PMIC. Also update the DC-DC converter operating frequency for AXP22X/AXP80X. Signed-off-by: Chen-Yu Tsai Acked-by: Rob Herring Signed-off-by: Lee Jones --- .../devicetree/bindings/mfd/axp20x.txt | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt index fd39fa54571b..d20b1034e967 100644 --- a/Documentation/devicetree/bindings/mfd/axp20x.txt +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt @@ -6,10 +6,11 @@ axp202 (X-Powers) axp209 (X-Powers) axp221 (X-Powers) axp223 (X-Powers) +axp809 (X-Powers) Required properties: - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209", - "x-powers,axp221", "x-powers,axp223" + "x-powers,axp221", "x-powers,axp223", "x-powers,axp809" - reg: The I2C slave address or RSB hardware address for the AXP chip - interrupt-parent: The parent interrupt controller - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin @@ -18,7 +19,9 @@ Required properties: Optional properties: - x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz - (range: 750-1875). Default: 1.5MHz + AXP152/20X: range: 750-1875, Default: 1.5 MHz + AXP22X/80X: range: 1800-4050, Default: 3 MHz + - -supply: a phandle to the regulator supply node. May be omitted if inputs are unregulated, such as using the IPSOUT output from the PMIC. @@ -77,6 +80,30 @@ LDO_IO0 : LDO : ips-supply : GPIO 0 LDO_IO1 : LDO : ips-supply : GPIO 1 RTC_LDO : LDO : ips-supply : always on +AXP809 regulators, type, and corresponding input supply names: + +Regulator Type Supply Name Notes +--------- ---- ----------- ----- +DCDC1 : DC-DC buck : vin1-supply +DCDC2 : DC-DC buck : vin2-supply +DCDC3 : DC-DC buck : vin3-supply +DCDC4 : DC-DC buck : vin4-supply +DCDC5 : DC-DC buck : vin5-supply +DC1SW : On/Off Switch : : DCDC1 secondary output +DC5LDO : LDO : : input from DCDC5 +ALDO1 : LDO : aldoin-supply : shared supply +ALDO2 : LDO : aldoin-supply : shared supply +ALDO3 : LDO : aldoin-supply : shared supply +DLDO1 : LDO : dldoin-supply : shared supply +DLDO2 : LDO : dldoin-supply : shared supply +ELDO1 : LDO : eldoin-supply : shared supply +ELDO2 : LDO : eldoin-supply : shared supply +ELDO3 : LDO : eldoin-supply : shared supply +LDO_IO0 : LDO : ips-supply : GPIO 0 +LDO_IO1 : LDO : ips-supply : GPIO 1 +RTC_LDO : LDO : ips-supply : always on +SW : On/Off Switch : swin-supply + Example: axp209: pmic@34 { -- GitLab From a8f447be8056d9ce17bf7757d6de79426700bb8b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:55 +0530 Subject: [PATCH 3280/9938] mfd: Add resource managed APIs for mfd_add_devices Add resource managed API devm_mfd_add_devices() for the mfd_add_devices(). This helps in reducing code in error path as it is not required to call mfd_remove_devices() explicitly to remove all child-devices. In some cases, it also helps not to implement .remove() callback which get called during driver unbind. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/mfd/core.h | 4 ++++ 2 files changed, 42 insertions(+) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 409da01effcd..4b4c1d4f3280 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -334,6 +334,44 @@ void mfd_remove_devices(struct device *parent) } EXPORT_SYMBOL(mfd_remove_devices); +static void devm_mfd_dev_release(struct device *dev, void *res) +{ + mfd_remove_devices(dev); +} + +/** + * devm_mfd_add_devices - Resource managed version of mfd_add_devices() + * + * Returns 0 on success or an appropriate negative error number on failure. + * All child-devices of the MFD will automatically be removed when it gets + * unbinded. + */ +int devm_mfd_add_devices(struct device *dev, int id, + const struct mfd_cell *cells, int n_devs, + struct resource *mem_base, + int irq_base, struct irq_domain *domain) +{ + struct device **ptr; + int ret; + + ptr = devres_alloc(devm_mfd_dev_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = mfd_add_devices(dev, id, cells, n_devs, mem_base, + irq_base, domain); + if (ret < 0) { + devres_free(ptr); + return ret; + } + + *ptr = dev; + devres_add(dev, ptr); + + return ret; +} +EXPORT_SYMBOL(devm_mfd_add_devices); + int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) { struct mfd_cell cell_entry; diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index bc6f7e00fb3d..4a0268afe546 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -131,4 +131,8 @@ static inline int mfd_add_hotplug_devices(struct device *parent, extern void mfd_remove_devices(struct device *parent); +extern int devm_mfd_add_devices(struct device *dev, int id, + const struct mfd_cell *cells, int n_devs, + struct resource *mem_base, + int irq_base, struct irq_domain *irq_domain); #endif -- GitLab From 3698283b101388cb9d992ae4d34329f005aa35e8 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:56 +0530 Subject: [PATCH 3281/9938] mfd: Add devm_mfd_add_devices() in list of managed interfaces Add devm wrappers for the mfd_add_devices() in the list of managed interfaces. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- Documentation/driver-model/devres.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 73b98dfbcea4..7f8c416f3bcf 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -317,6 +317,9 @@ MEM devm_kvasprintf() devm_kzalloc() +MFD + devm_mfd_add_devices() + PCI pcim_enable_device() : after success, all PCI ops become managed pcim_pin_device() : keep PCI device enabled after release -- GitLab From f9932c6e66c17ca3d84a7c6424c844bea8003ffb Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:57 +0530 Subject: [PATCH 3282/9938] mfd: act8945a: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Wenyou Yang CC: Krzysztof Kozlowski Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/act8945a.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/act8945a.c b/drivers/mfd/act8945a.c index 525b546ba42f..10c6d2da8822 100644 --- a/drivers/mfd/act8945a.c +++ b/drivers/mfd/act8945a.c @@ -46,8 +46,9 @@ static int act8945a_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, regmap); - ret = mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, act8945a_devs, - ARRAY_SIZE(act8945a_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, + act8945a_devs, ARRAY_SIZE(act8945a_devs), + NULL, 0, NULL); if (ret) { dev_err(&i2c->dev, "Failed to add sub devices\n"); return ret; @@ -56,13 +57,6 @@ static int act8945a_i2c_probe(struct i2c_client *i2c, return 0; } -static int act8945a_i2c_remove(struct i2c_client *i2c) -{ - mfd_remove_devices(&i2c->dev); - - return 0; -} - static const struct i2c_device_id act8945a_i2c_id[] = { { "act8945a", 0 }, {} @@ -81,7 +75,6 @@ static struct i2c_driver act8945a_i2c_driver = { .of_match_table = of_match_ptr(act8945a_of_match), }, .probe = act8945a_i2c_probe, - .remove = act8945a_i2c_remove, .id_table = act8945a_i2c_id, }; -- GitLab From 9c9983267deab5c268676d8ac15686923b6e5e19 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:58 +0530 Subject: [PATCH 3283/9938] mfd: as3711: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Guennadi Liakhovetski Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/as3711.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c index 09e1483b99bc..67b12417585d 100644 --- a/drivers/mfd/as3711.c +++ b/drivers/mfd/as3711.c @@ -189,22 +189,14 @@ static int as3711_i2c_probe(struct i2c_client *client, as3711_subdevs[AS3711_BACKLIGHT].pdata_size = 0; } - ret = mfd_add_devices(as3711->dev, -1, as3711_subdevs, - ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL); + ret = devm_mfd_add_devices(as3711->dev, -1, as3711_subdevs, + ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL); if (ret < 0) dev_err(&client->dev, "add mfd devices failed: %d\n", ret); return ret; } -static int as3711_i2c_remove(struct i2c_client *client) -{ - struct as3711 *as3711 = i2c_get_clientdata(client); - - mfd_remove_devices(as3711->dev); - return 0; -} - static const struct i2c_device_id as3711_i2c_id[] = { {.name = "as3711", .driver_data = 0}, {} @@ -218,7 +210,6 @@ static struct i2c_driver as3711_i2c_driver = { .of_match_table = of_match_ptr(as3711_of_match), }, .probe = as3711_i2c_probe, - .remove = as3711_i2c_remove, .id_table = as3711_i2c_id, }; -- GitLab From f32fb9a593704a32ddc395686fa00075d10df173 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:12:59 +0530 Subject: [PATCH 3284/9938] mfd: atmel-hlcdc: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. Signed-off-by: Laxman Dewangan Acked-by: Boris Brezillon Signed-off-by: Lee Jones --- drivers/mfd/atmel-hlcdc.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index 06c205868573..eca7ea69b81c 100644 --- a/drivers/mfd/atmel-hlcdc.c +++ b/drivers/mfd/atmel-hlcdc.c @@ -128,16 +128,9 @@ static int atmel_hlcdc_probe(struct platform_device *pdev) dev_set_drvdata(dev, hlcdc); - return mfd_add_devices(dev, -1, atmel_hlcdc_cells, - ARRAY_SIZE(atmel_hlcdc_cells), - NULL, 0, NULL); -} - -static int atmel_hlcdc_remove(struct platform_device *pdev) -{ - mfd_remove_devices(&pdev->dev); - - return 0; + return devm_mfd_add_devices(dev, -1, atmel_hlcdc_cells, + ARRAY_SIZE(atmel_hlcdc_cells), + NULL, 0, NULL); } static const struct of_device_id atmel_hlcdc_match[] = { @@ -152,7 +145,6 @@ MODULE_DEVICE_TABLE(of, atmel_hlcdc_match); static struct platform_driver atmel_hlcdc_driver = { .probe = atmel_hlcdc_probe, - .remove = atmel_hlcdc_remove, .driver = { .name = "atmel-hlcdc", .of_match_table = atmel_hlcdc_match, -- GitLab From 9148f2c01827fe1c8c8d589ac54b0f459759d78b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:00 +0530 Subject: [PATCH 3285/9938] mfd: bcm590xx: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Matt Porter Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/bcm590xx.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c index 320aaefee718..0d76d690176b 100644 --- a/drivers/mfd/bcm590xx.c +++ b/drivers/mfd/bcm590xx.c @@ -82,8 +82,8 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri, goto err; } - ret = mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs, - ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs, + ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL); if (ret < 0) { dev_err(&i2c_pri->dev, "failed to add sub-devices: %d\n", ret); goto err; @@ -96,12 +96,6 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri, return ret; } -static int bcm590xx_i2c_remove(struct i2c_client *i2c) -{ - mfd_remove_devices(&i2c->dev); - return 0; -} - static const struct of_device_id bcm590xx_of_match[] = { { .compatible = "brcm,bcm59056" }, { } @@ -120,7 +114,6 @@ static struct i2c_driver bcm590xx_i2c_driver = { .of_match_table = of_match_ptr(bcm590xx_of_match), }, .probe = bcm590xx_i2c_probe, - .remove = bcm590xx_i2c_remove, .id_table = bcm590xx_i2c_id, }; module_i2c_driver(bcm590xx_i2c_driver); -- GitLab From 9c384b0268c69a36e6b5d9c6b336fb81a63d457e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:01 +0530 Subject: [PATCH 3286/9938] mfd: hi6421-pmic: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Guodong Xu Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/hi6421-pmic-core.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c index f9ded45a992d..3fd703fe3aba 100644 --- a/drivers/mfd/hi6421-pmic-core.c +++ b/drivers/mfd/hi6421-pmic-core.c @@ -76,8 +76,8 @@ static int hi6421_pmic_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmic); - ret = mfd_add_devices(&pdev->dev, 0, hi6421_devs, - ARRAY_SIZE(hi6421_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&pdev->dev, 0, hi6421_devs, + ARRAY_SIZE(hi6421_devs), NULL, 0, NULL); if (ret) { dev_err(&pdev->dev, "add mfd devices failed: %d\n", ret); return ret; @@ -86,13 +86,6 @@ static int hi6421_pmic_probe(struct platform_device *pdev) return 0; } -static int hi6421_pmic_remove(struct platform_device *pdev) -{ - mfd_remove_devices(&pdev->dev); - - return 0; -} - static const struct of_device_id of_hi6421_pmic_match_tbl[] = { { .compatible = "hisilicon,hi6421-pmic", }, { }, @@ -105,7 +98,6 @@ static struct platform_driver hi6421_pmic_driver = { .of_match_table = of_hi6421_pmic_match_tbl, }, .probe = hi6421_pmic_probe, - .remove = hi6421_pmic_remove, }; module_platform_driver(hi6421_pmic_driver); -- GitLab From c5f244549425c83835759f2d338967d0e798fda3 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:02 +0530 Subject: [PATCH 3287/9938] mfd: lp3943: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Milo Kim Signed-off-by: Laxman Dewangan Acked-by: Milo Kim Signed-off-by: Lee Jones --- drivers/mfd/lp3943.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c index eecbb13de1bd..65a2a8f14e74 100644 --- a/drivers/mfd/lp3943.c +++ b/drivers/mfd/lp3943.c @@ -123,16 +123,9 @@ static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id) lp3943->mux_cfg = lp3943_mux_cfg; i2c_set_clientdata(cl, lp3943); - return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs), - NULL, 0, NULL); -} - -static int lp3943_remove(struct i2c_client *cl) -{ - struct lp3943 *lp3943 = i2c_get_clientdata(cl); - - mfd_remove_devices(lp3943->dev); - return 0; + return devm_mfd_add_devices(dev, -1, lp3943_devs, + ARRAY_SIZE(lp3943_devs), + NULL, 0, NULL); } static const struct i2c_device_id lp3943_ids[] = { @@ -151,7 +144,6 @@ MODULE_DEVICE_TABLE(of, lp3943_of_match); static struct i2c_driver lp3943_driver = { .probe = lp3943_probe, - .remove = lp3943_remove, .driver = { .name = "lp3943", .of_match_table = of_match_ptr(lp3943_of_match), -- GitLab From 7990ad17a9debc2c91ffc1413d01450c982fcb8d Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:03 +0530 Subject: [PATCH 3288/9938] mfd: menf21bmc: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. Signed-off-by: Laxman Dewangan Reviewed-by: Andreas Werner Signed-off-by: Lee Jones --- drivers/mfd/menf21bmc.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/menf21bmc.c b/drivers/mfd/menf21bmc.c index 1c274345820c..3ad2def947d8 100644 --- a/drivers/mfd/menf21bmc.c +++ b/drivers/mfd/menf21bmc.c @@ -96,8 +96,8 @@ menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids) return ret; } - ret = mfd_add_devices(&client->dev, 0, menf21bmc_cell, - ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL); + ret = devm_mfd_add_devices(&client->dev, 0, menf21bmc_cell, + ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL); if (ret < 0) { dev_err(&client->dev, "failed to add BMC sub-devices\n"); return ret; @@ -106,12 +106,6 @@ menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids) return 0; } -static int menf21bmc_remove(struct i2c_client *client) -{ - mfd_remove_devices(&client->dev); - return 0; -} - static const struct i2c_device_id menf21bmc_id_table[] = { { "menf21bmc" }, { } @@ -122,7 +116,6 @@ static struct i2c_driver menf21bmc_driver = { .driver.name = "menf21bmc", .id_table = menf21bmc_id_table, .probe = menf21bmc_probe, - .remove = menf21bmc_remove, }; module_i2c_driver(menf21bmc_driver); -- GitLab From 08e380a53a92a445bdfd98e09680237bf0c269aa Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:04 +0530 Subject: [PATCH 3289/9938] mfd: mt6397: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: John Crispin Signed-off-by: Laxman Dewangan Reviewed-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/mt6397-core.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 8e8d93249c09..5a3ffa391942 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -276,8 +276,9 @@ static int mt6397_probe(struct platform_device *pdev) pmic->int_con[1] = MT6323_INT_CON1; pmic->int_status[0] = MT6323_INT_STATUS0; pmic->int_status[1] = MT6323_INT_STATUS1; - ret = mfd_add_devices(&pdev->dev, -1, mt6323_devs, - ARRAY_SIZE(mt6323_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, + ARRAY_SIZE(mt6323_devs), NULL, + 0, NULL); break; case MT6397_CID_CODE: @@ -286,8 +287,9 @@ static int mt6397_probe(struct platform_device *pdev) pmic->int_con[1] = MT6397_INT_CON1; pmic->int_status[0] = MT6397_INT_STATUS0; pmic->int_status[1] = MT6397_INT_STATUS1; - ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs, - ARRAY_SIZE(mt6397_devs), NULL, 0, NULL); + ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, + ARRAY_SIZE(mt6397_devs), NULL, + 0, NULL); break; default: @@ -312,13 +314,6 @@ static int mt6397_probe(struct platform_device *pdev) return ret; } -static int mt6397_remove(struct platform_device *pdev) -{ - mfd_remove_devices(&pdev->dev); - - return 0; -} - static const struct of_device_id mt6397_of_match[] = { { .compatible = "mediatek,mt6397" }, { .compatible = "mediatek,mt6323" }, @@ -334,7 +329,6 @@ MODULE_DEVICE_TABLE(platform, mt6397_id); static struct platform_driver mt6397_driver = { .probe = mt6397_probe, - .remove = mt6397_remove, .driver = { .name = "mt6397", .of_match_table = of_match_ptr(mt6397_of_match), -- GitLab From 7360544c2b91d5689b635b2117f5e85986cf529b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:05 +0530 Subject: [PATCH 3290/9938] mfd: rdc321x: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Florian Fainelli Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/rdc321x-southbridge.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 6575585f1d1f..2bd8c5b6d600 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c @@ -85,14 +85,10 @@ static int rdc321x_sb_probe(struct pci_dev *pdev, rdc321x_gpio_pdata.sb_pdev = pdev; rdc321x_wdt_pdata.sb_pdev = pdev; - return mfd_add_devices(&pdev->dev, -1, - rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), - NULL, 0, NULL); -} - -static void rdc321x_sb_remove(struct pci_dev *pdev) -{ - mfd_remove_devices(&pdev->dev); + return devm_mfd_add_devices(&pdev->dev, -1, + rdc321x_sb_cells, + ARRAY_SIZE(rdc321x_sb_cells), + NULL, 0, NULL); } static const struct pci_device_id rdc321x_sb_table[] = { @@ -105,7 +101,6 @@ static struct pci_driver rdc321x_sb_driver = { .name = "RDC321x Southbridge", .id_table = rdc321x_sb_table, .probe = rdc321x_sb_probe, - .remove = rdc321x_sb_remove, }; module_pci_driver(rdc321x_sb_driver); -- GitLab From d5623161accbc567452700add15d76fc092b07fe Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:06 +0530 Subject: [PATCH 3291/9938] mfd: rk808: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and remove the call of mfd_remove_devices() from .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Chris Zhong Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/rk808.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 4b1e4399754b..49d7f624fc94 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -213,9 +213,9 @@ static int rk808_probe(struct i2c_client *client, rk808->i2c = client; i2c_set_clientdata(client, rk808); - ret = mfd_add_devices(&client->dev, -1, - rk808s, ARRAY_SIZE(rk808s), - NULL, 0, regmap_irq_get_domain(rk808->irq_data)); + ret = devm_mfd_add_devices(&client->dev, -1, + rk808s, ARRAY_SIZE(rk808s), NULL, 0, + regmap_irq_get_domain(rk808->irq_data)); if (ret) { dev_err(&client->dev, "failed to add MFD devices %d\n", ret); goto err_irq; @@ -240,7 +240,6 @@ static int rk808_remove(struct i2c_client *client) struct rk808 *rk808 = i2c_get_clientdata(client); regmap_del_irq_chip(client->irq, rk808->irq_data); - mfd_remove_devices(&client->dev); pm_power_off = NULL; return 0; -- GitLab From f41206c9fd5c48becdb0f2f65328c5438f6ea34d Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:07 +0530 Subject: [PATCH 3292/9938] mfd: rn5t618: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and remove the call of mfd_remove_devices() from .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Beniamino Galvani Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/rn5t618.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index 666857192dbe..0ad51d792feb 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -78,8 +78,8 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c, return ret; } - ret = mfd_add_devices(&i2c->dev, -1, rn5t618_cells, - ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL); + ret = devm_mfd_add_devices(&i2c->dev, -1, rn5t618_cells, + ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL); if (ret) { dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret); return ret; @@ -102,7 +102,6 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c) pm_power_off = NULL; } - mfd_remove_devices(&i2c->dev); return 0; } -- GitLab From 6b719eba9f01cd65ede04e64f20f648f8dbe6359 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:08 +0530 Subject: [PATCH 3293/9938] mfd: rt5033: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Ingi Kim Signed-off-by: Laxman Dewangan Reviewed-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/rt5033.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index 2b95485f0057..9bd089c56375 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -97,9 +97,9 @@ static int rt5033_i2c_probe(struct i2c_client *i2c, return ret; } - ret = mfd_add_devices(rt5033->dev, -1, rt5033_devs, - ARRAY_SIZE(rt5033_devs), NULL, 0, - regmap_irq_get_domain(rt5033->irq_data)); + ret = devm_mfd_add_devices(rt5033->dev, -1, rt5033_devs, + ARRAY_SIZE(rt5033_devs), NULL, 0, + regmap_irq_get_domain(rt5033->irq_data)); if (ret < 0) { dev_err(&i2c->dev, "Failed to add RT5033 child devices.\n"); return ret; @@ -110,13 +110,6 @@ static int rt5033_i2c_probe(struct i2c_client *i2c, return 0; } -static int rt5033_i2c_remove(struct i2c_client *i2c) -{ - mfd_remove_devices(&i2c->dev); - - return 0; -} - static const struct i2c_device_id rt5033_i2c_id[] = { { "rt5033", }, { } @@ -135,7 +128,6 @@ static struct i2c_driver rt5033_driver = { .of_match_table = of_match_ptr(rt5033_dt_match), }, .probe = rt5033_i2c_probe, - .remove = rt5033_i2c_remove, .id_table = rt5033_i2c_id, }; module_i2c_driver(rt5033_driver); -- GitLab From 69633beaebf345cde6672a9ac7679c88fc0c3245 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:09 +0530 Subject: [PATCH 3294/9938] mfd: sky81452: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Gyungoh Yoo Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/sky81452.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c index b0c9b0415650..30a2a677100f 100644 --- a/drivers/mfd/sky81452.c +++ b/drivers/mfd/sky81452.c @@ -64,19 +64,14 @@ static int sky81452_probe(struct i2c_client *client, cells[1].platform_data = pdata->regulator_init_data; cells[1].pdata_size = sizeof(*pdata->regulator_init_data); - ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL); + ret = devm_mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), + NULL, 0, NULL); if (ret) dev_err(dev, "failed to add child devices. err=%d\n", ret); return ret; } -static int sky81452_remove(struct i2c_client *client) -{ - mfd_remove_devices(&client->dev); - return 0; -} - static const struct i2c_device_id sky81452_ids[] = { { "sky81452" }, { } @@ -97,7 +92,6 @@ static struct i2c_driver sky81452_driver = { .of_match_table = of_match_ptr(sky81452_of_match), }, .probe = sky81452_probe, - .remove = sky81452_remove, .id_table = sky81452_ids, }; -- GitLab From e253fb0472e7a892176c7a65cef61a6aa75f8d2e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:10 +0530 Subject: [PATCH 3295/9938] mfd: stw481x: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. Signed-off-by: Laxman Dewangan Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/stw481x.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c index ca613df36143..ab949eaca6ad 100644 --- a/drivers/mfd/stw481x.c +++ b/drivers/mfd/stw481x.c @@ -206,8 +206,8 @@ static int stw481x_probe(struct i2c_client *client, stw481x_cells[i].pdata_size = sizeof(*stw481x); } - ret = mfd_add_devices(&client->dev, 0, stw481x_cells, - ARRAY_SIZE(stw481x_cells), NULL, 0, NULL); + ret = devm_mfd_add_devices(&client->dev, 0, stw481x_cells, + ARRAY_SIZE(stw481x_cells), NULL, 0, NULL); if (ret) return ret; @@ -216,12 +216,6 @@ static int stw481x_probe(struct i2c_client *client, return ret; } -static int stw481x_remove(struct i2c_client *client) -{ - mfd_remove_devices(&client->dev); - return 0; -} - /* * This ID table is completely unused, as this is a pure * device-tree probed driver, but it has to be here due to @@ -246,7 +240,6 @@ static struct i2c_driver stw481x_driver = { .of_match_table = stw481x_match, }, .probe = stw481x_probe, - .remove = stw481x_remove, .id_table = stw481x_id, }; -- GitLab From 5635d994fe870a0de2614e83bbf2d70f506651eb Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:11 +0530 Subject: [PATCH 3296/9938] mfd: tps6507x: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Todd Fischer Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/tps6507x.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 1ab3dd6c8adf..40beb2f4350c 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -100,16 +100,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, tps6507x->read_dev = tps6507x_i2c_read_device; tps6507x->write_dev = tps6507x_i2c_write_device; - return mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, - ARRAY_SIZE(tps6507x_devs), NULL, 0, NULL); -} - -static int tps6507x_i2c_remove(struct i2c_client *i2c) -{ - struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c); - - mfd_remove_devices(tps6507x->dev); - return 0; + return devm_mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, + ARRAY_SIZE(tps6507x_devs), NULL, 0, NULL); } static const struct i2c_device_id tps6507x_i2c_id[] = { @@ -132,7 +124,6 @@ static struct i2c_driver tps6507x_i2c_driver = { .of_match_table = of_match_ptr(tps6507x_of_match), }, .probe = tps6507x_i2c_probe, - .remove = tps6507x_i2c_remove, .id_table = tps6507x_i2c_id, }; -- GitLab From b89b6b6bcd570a0beb1fc6fb8d0ecc20316413ab Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:12 +0530 Subject: [PATCH 3297/9938] mfd: tps65217: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Tony Lindgren Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/tps65217.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index d32b54426b70..049a6fcac651 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -205,8 +205,8 @@ static int tps65217_probe(struct i2c_client *client, return ret; } - ret = mfd_add_devices(tps->dev, -1, tps65217s, - ARRAY_SIZE(tps65217s), NULL, 0, NULL); + ret = devm_mfd_add_devices(tps->dev, -1, tps65217s, + ARRAY_SIZE(tps65217s), NULL, 0, NULL); if (ret < 0) { dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); return ret; @@ -235,15 +235,6 @@ static int tps65217_probe(struct i2c_client *client, return 0; } -static int tps65217_remove(struct i2c_client *client) -{ - struct tps65217 *tps = i2c_get_clientdata(client); - - mfd_remove_devices(tps->dev); - - return 0; -} - static const struct i2c_device_id tps65217_id_table[] = { {"tps65217", TPS65217}, { /* sentinel */ } @@ -257,7 +248,6 @@ static struct i2c_driver tps65217_driver = { }, .id_table = tps65217_id_table, .probe = tps65217_probe, - .remove = tps65217_remove, }; static int __init tps65217_init(void) -- GitLab From f3466e7764783ed4fae91ebe1653b0a08cca22bf Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:13 +0530 Subject: [PATCH 3298/9938] mfd: tps65910: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and remove the call of mfd_remove_devices() from .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Tony Lindgren Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/tps65910.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index f7ab115483a9..8086e5dae311 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -510,10 +510,10 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, pm_power_off = tps65910_power_off; } - ret = mfd_add_devices(tps65910->dev, -1, - tps65910s, ARRAY_SIZE(tps65910s), - NULL, 0, - regmap_irq_get_domain(tps65910->irq_data)); + ret = devm_mfd_add_devices(tps65910->dev, -1, + tps65910s, ARRAY_SIZE(tps65910s), + NULL, 0, + regmap_irq_get_domain(tps65910->irq_data)); if (ret < 0) { dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret); tps65910_irq_exit(tps65910); @@ -528,7 +528,6 @@ static int tps65910_i2c_remove(struct i2c_client *i2c) struct tps65910 *tps65910 = i2c_get_clientdata(i2c); tps65910_irq_exit(tps65910); - mfd_remove_devices(tps65910->dev); return 0; } -- GitLab From 7825dc05601b38f99808830098fd4f512c876b4e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 8 Apr 2016 00:13:14 +0530 Subject: [PATCH 3299/9938] mfd: wm8400: Use devm_mfd_add_devices() for mfd_device registration Use devm_mfd_add_devices() for MFD devices registration and get rid of .remove callback to remove MFD child-devices. This is done by managed device framework. CC: Mark Brown Signed-off-by: Laxman Dewangan Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm8400-core.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 3bd44a45c378..9fd823049f90 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) .pdata_size = sizeof(*wm8400), }; - return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); + return devm_mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); } /* @@ -111,7 +111,7 @@ static int wm8400_init(struct wm8400 *wm8400, ret = wm8400_register_codec(wm8400); if (ret != 0) { dev_err(wm8400->dev, "Failed to register codec\n"); - goto err_children; + return ret; } if (pdata && pdata->platform_init) { @@ -119,21 +119,12 @@ static int wm8400_init(struct wm8400 *wm8400, if (ret != 0) { dev_err(wm8400->dev, "Platform init failed: %d\n", ret); - goto err_children; + return ret; } } else dev_warn(wm8400->dev, "No platform initialisation supplied\n"); return 0; - -err_children: - mfd_remove_devices(wm8400->dev); - return ret; -} - -static void wm8400_release(struct wm8400 *wm8400) -{ - mfd_remove_devices(wm8400->dev); } static const struct regmap_config wm8400_regmap_config = { @@ -176,15 +167,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c, return wm8400_init(wm8400, dev_get_platdata(&i2c->dev)); } -static int wm8400_i2c_remove(struct i2c_client *i2c) -{ - struct wm8400 *wm8400 = i2c_get_clientdata(i2c); - - wm8400_release(wm8400); - - return 0; -} - static const struct i2c_device_id wm8400_i2c_id[] = { { "wm8400", 0 }, { } @@ -196,7 +178,6 @@ static struct i2c_driver wm8400_i2c_driver = { .name = "WM8400", }, .probe = wm8400_i2c_probe, - .remove = wm8400_i2c_remove, .id_table = wm8400_i2c_id, }; #endif -- GitLab From cf6fea8cda8ae3b5b7576fa6bd2b35905e155967 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Mon, 18 Apr 2016 16:09:55 +0200 Subject: [PATCH 3300/9938] leds: ledtrig-ide-disk: Move ide_blink_delay to ledtrig_ide_activity() Parameters delay_on and delay_off of led_trigger_blink_oneshot() are pointers, to enable blink interval adjustment by LED class drivers of the controllers that implement hardware blinking. Move ide_blink_delay variable to ledtrig_ide_activity() in order to prevent the situation when adjustment committed by one LED class driver influences blink interval of the software fallback blink feature, that is applied to the drivers that don't implement blink_set op. Reviewed-by: Boris Brezillon Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-ide-disk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/leds/trigger/ledtrig-ide-disk.c b/drivers/leds/trigger/ledtrig-ide-disk.c index c02a3ac3cd2b..15123d389240 100644 --- a/drivers/leds/trigger/ledtrig-ide-disk.c +++ b/drivers/leds/trigger/ledtrig-ide-disk.c @@ -18,10 +18,11 @@ #define BLINK_DELAY 30 DEFINE_LED_TRIGGER(ledtrig_ide); -static unsigned long ide_blink_delay = BLINK_DELAY; void ledtrig_ide_activity(void) { + unsigned long ide_blink_delay = BLINK_DELAY; + led_trigger_blink_oneshot(ledtrig_ide, &ide_blink_delay, &ide_blink_delay, 0); } -- GitLab From cbdd535d9481025a5a9020f9e9875b68ad86111c Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Sun, 14 Feb 2016 14:29:19 +0800 Subject: [PATCH 3301/9938] mfd: hi655x: Add document for hi665x PMIC DT bindings for hisilicon HI655x PMIC chip. Signed-off-by: Chen Feng Signed-off-by: Fei Wang Signed-off-by: Xinwei Kong Reviewed-by: Haojian Zhuang Signed-off-by: Lee Jones --- .../bindings/mfd/hisilicon,hi655x.txt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt diff --git a/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt b/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt new file mode 100644 index 000000000000..05485699d70e --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt @@ -0,0 +1,27 @@ +Hisilicon Hi655x Power Management Integrated Circuit (PMIC) + +The hardware layout for access PMIC Hi655x from AP SoC Hi6220. +Between PMIC Hi655x and Hi6220, the physical signal channel is SSI. +We can use memory-mapped I/O to communicate. + ++----------------+ +-------------+ +| | | | +| Hi6220 | SSI bus | Hi655x | +| |-------------| | +| |(REGMAP_MMIO)| | ++----------------+ +-------------+ + +Required properties: +- compatible: Should be "hisilicon,hi655x-pmic". +- reg: Base address of PMIC on Hi6220 SoC. +- interrupt-controller: Hi655x has internal IRQs (has own IRQ domain). +- pmic-gpios: The GPIO used by PMIC IRQ. + +Example: + pmic: pmic@f8000000 { + compatible = "hisilicon,hi655x-pmic"; + reg = <0x0 0xf8000000 0x0 0x1000>; + interrupt-controller; + #interrupt-cells = <2>; + pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + } -- GitLab From 082cc468385dbc7bbdc234bf6f2577e64fc00bbb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:01 +0200 Subject: [PATCH 3302/9938] mfd: asic3: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Paul Parsons Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/asic3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 4dca6bc61f5b..0413c8159551 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -446,7 +446,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip, unsigned long flags; struct asic3 *asic; - asic = container_of(chip, struct asic3, gpio); + asic = gpiochip_get_data(chip); gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_BASE) { @@ -492,7 +492,7 @@ static int asic3_gpio_get(struct gpio_chip *chip, u32 mask = ASIC3_GPIO_TO_MASK(offset); struct asic3 *asic; - asic = container_of(chip, struct asic3, gpio); + asic = gpiochip_get_data(chip); gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_BASE) { @@ -513,7 +513,7 @@ static void asic3_gpio_set(struct gpio_chip *chip, unsigned long flags; struct asic3 *asic; - asic = container_of(chip, struct asic3, gpio); + asic = gpiochip_get_data(chip); gpio_base = ASIC3_GPIO_TO_BASE(offset); if (gpio_base > ASIC3_GPIO_D_BASE) { @@ -540,7 +540,7 @@ static void asic3_gpio_set(struct gpio_chip *chip, static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - struct asic3 *asic = container_of(chip, struct asic3, gpio); + struct asic3 *asic = gpiochip_get_data(chip); return asic->irq_base + offset; } @@ -595,7 +595,7 @@ static __init int asic3_gpio_probe(struct platform_device *pdev, alt_reg[i]); } - return gpiochip_add(&asic->gpio); + return gpiochip_add_data(&asic->gpio, asic); } static int asic3_gpio_remove(struct platform_device *pdev) -- GitLab From 4363765c851313d460db86f2d41d2eebca0d9c17 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:02 +0200 Subject: [PATCH 3303/9938] mfd: dm355evm_msp: Switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/dm355evm_msp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index ec4438ed2faf..d7d59f8d9d06 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -260,7 +260,7 @@ static int add_children(struct i2c_client *client) /* GPIO-ish stuff */ dm355evm_msp_gpio.parent = &client->dev; - status = gpiochip_add(&dm355evm_msp_gpio); + status = gpiochip_add_data(&dm355evm_msp_gpio, NULL); if (status < 0) return status; -- GitLab From 8d5f095fc5f7e36f40a80e87317828be249ee454 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:03 +0200 Subject: [PATCH 3304/9938] mfd: htc-egpio: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Acked-by: Philipp Zabel Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/htc-egpio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index c636b5f83cfb..513cfc5c8fb6 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c @@ -155,7 +155,7 @@ static int egpio_get(struct gpio_chip *chip, unsigned offset) pr_debug("egpio_get_value(%d)\n", chip->base + offset); - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); ei = dev_get_drvdata(egpio->dev); bit = egpio_bit(ei, offset); reg = egpio->reg_start + egpio_pos(ei, offset); @@ -170,7 +170,7 @@ static int egpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct egpio_chip *egpio; - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); return test_bit(offset, &egpio->is_out) ? -EINVAL : 0; } @@ -192,7 +192,7 @@ static void egpio_set(struct gpio_chip *chip, unsigned offset, int value) pr_debug("egpio_set(%s, %d(%d), %d)\n", chip->label, offset, offset+chip->base, value); - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); ei = dev_get_drvdata(egpio->dev); bit = egpio_bit(ei, offset); pos = egpio_pos(ei, offset); @@ -216,7 +216,7 @@ static int egpio_direction_output(struct gpio_chip *chip, { struct egpio_chip *egpio; - egpio = container_of(chip, struct egpio_chip, chip); + egpio = gpiochip_get_data(chip); if (test_bit(offset, &egpio->is_out)) { egpio_set(chip, offset, value); return 0; @@ -330,7 +330,7 @@ static int __init egpio_probe(struct platform_device *pdev) chip->base = pdata->chip[i].gpio_base; chip->ngpio = pdata->chip[i].num_gpios; - gpiochip_add(chip); + gpiochip_add_data(chip, &ei->chip[i]); } /* Set initial pin values */ -- GitLab From ed1c9b3c18e33a69da0a911eadf4948ea7e5b5b9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:04 +0200 Subject: [PATCH 3305/9938] mfd: htc-i2cpld: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/htc-i2cpld.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index bd6b96d07ab8..3f9eee5f8fb9 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -227,8 +227,7 @@ static irqreturn_t htcpld_handler(int irq, void *dev) static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val) { struct i2c_client *client; - struct htcpld_chip *chip_data = - container_of(chip, struct htcpld_chip, chip_out); + struct htcpld_chip *chip_data = gpiochip_get_data(chip); unsigned long flags; client = chip_data->client; @@ -257,14 +256,12 @@ static void htcpld_chip_set_ni(struct work_struct *work) static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset) { - struct htcpld_chip *chip_data; + struct htcpld_chip *chip_data = gpiochip_get_data(chip); u8 cache; if (!strncmp(chip->label, "htcpld-out", 10)) { - chip_data = container_of(chip, struct htcpld_chip, chip_out); cache = chip_data->cache_out; } else if (!strncmp(chip->label, "htcpld-in", 9)) { - chip_data = container_of(chip, struct htcpld_chip, chip_in); cache = chip_data->cache_in; } else return -EINVAL; @@ -291,9 +288,7 @@ static int htcpld_direction_input(struct gpio_chip *chip, static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset) { - struct htcpld_chip *chip_data; - - chip_data = container_of(chip, struct htcpld_chip, chip_in); + struct htcpld_chip *chip_data = gpiochip_get_data(chip); if (offset < chip_data->nirqs) return chip_data->irq_start + offset; @@ -451,14 +446,14 @@ static int htcpld_register_chip_gpio( gpio_chip->ngpio = plat_chip_data->num_gpios; /* Add the GPIO chips */ - ret = gpiochip_add(&(chip->chip_out)); + ret = gpiochip_add_data(&(chip->chip_out), chip); if (ret) { dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n", plat_chip_data->addr, ret); return ret; } - ret = gpiochip_add(&(chip->chip_in)); + ret = gpiochip_add_data(&(chip->chip_in), chip); if (ret) { dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n", plat_chip_data->addr, ret); -- GitLab From 3a504105f0e4cf32464d596f3b30d23dbfd76520 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:05 +0200 Subject: [PATCH 3306/9938] mfd: sm501: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Ben Dooks Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/sm501.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index c646784c5a7d..65cd0d2a822a 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -879,11 +879,6 @@ static int sm501_register_display(struct sm501_devdata *sm, #ifdef CONFIG_MFD_SM501_GPIO -static inline struct sm501_gpio_chip *to_sm501_gpio(struct gpio_chip *gc) -{ - return container_of(gc, struct sm501_gpio_chip, gpio); -} - static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio) { return container_of(gpio, struct sm501_devdata, gpio); @@ -892,7 +887,7 @@ static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio) static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip); + struct sm501_gpio_chip *smgpio = gpiochip_get_data(chip); unsigned long result; result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW); @@ -923,7 +918,7 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip, static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; unsigned long bit = 1 << offset; void __iomem *regs = smchip->regbase; @@ -948,7 +943,7 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) { - struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; void __iomem *regs = smchip->regbase; unsigned long bit = 1 << offset; @@ -974,7 +969,7 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) static int sm501_gpio_output(struct gpio_chip *chip, unsigned offset, int value) { - struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); + struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; unsigned long bit = 1 << offset; void __iomem *regs = smchip->regbase; @@ -1039,7 +1034,7 @@ static int sm501_gpio_register_chip(struct sm501_devdata *sm, gchip->base = base; chip->ourgpio = gpio; - return gpiochip_add(gchip); + return gpiochip_add_data(gchip, chip); } static int sm501_register_gpio(struct sm501_devdata *sm) -- GitLab From 4e125f62b73dffde17f4c53155654623ab2a9855 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:06 +0200 Subject: [PATCH 3307/9938] mfd: tc6393xb: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Dmitry Baryshkov Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/tc6393xb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 1ecbfa40d1b3..d42d322ac7ca 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #define SCR_REVID 0x08 /* b Revision ID */ @@ -434,7 +434,7 @@ static struct mfd_cell tc6393xb_cells[] = { static int tc6393xb_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); /* XXX: does dsr also represent inputs? */ return !!(tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8)) @@ -444,7 +444,7 @@ static int tc6393xb_gpio_get(struct gpio_chip *chip, static void __tc6393xb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); u8 dsr; dsr = tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8)); @@ -459,7 +459,7 @@ static void __tc6393xb_gpio_set(struct gpio_chip *chip, static void tc6393xb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); unsigned long flags; spin_lock_irqsave(&tc6393xb->lock, flags); @@ -472,7 +472,7 @@ static void tc6393xb_gpio_set(struct gpio_chip *chip, static int tc6393xb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); unsigned long flags; u8 doecr; @@ -490,7 +490,7 @@ static int tc6393xb_gpio_direction_input(struct gpio_chip *chip, static int tc6393xb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio); + struct tc6393xb *tc6393xb = gpiochip_get_data(chip); unsigned long flags; u8 doecr; @@ -517,7 +517,7 @@ static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base) tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input; tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output; - return gpiochip_add(&tc6393xb->gpio); + return gpiochip_add_data(&tc6393xb->gpio, tc6393xb); } /*--------------------------------------------------------------------------*/ -- GitLab From 22e5e747e71f19ac3af60ce648f4c02c63ed3cc1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:07 +0200 Subject: [PATCH 3308/9938] mfd: tps65010: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/tps65010.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 495e4518fc29..d829a6131f09 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -34,7 +34,7 @@ #include -#include +#include /*-------------------------------------------------------------------------*/ @@ -477,7 +477,7 @@ tps65010_output(struct gpio_chip *chip, unsigned offset, int value) if (offset < 4) { struct tps65010 *tps; - tps = container_of(chip, struct tps65010, chip); + tps = gpiochip_get_data(chip); if (!(tps->outmask & (1 << offset))) return -EINVAL; tps65010_set_gpio_out_value(offset + 1, value); @@ -494,7 +494,7 @@ static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset) int value; struct tps65010 *tps; - tps = container_of(chip, struct tps65010, chip); + tps = gpiochip_get_data(chip); if (offset < 4) { value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO); @@ -651,7 +651,7 @@ static int tps65010_probe(struct i2c_client *client, tps->chip.ngpio = 7; tps->chip.can_sleep = 1; - status = gpiochip_add(&tps->chip); + status = gpiochip_add_data(&tps->chip, tps); if (status < 0) dev_err(&client->dev, "can't add gpiochip, err %d\n", status); -- GitLab From 7d94352eba4f943734c19d172a834d0b2affec09 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:08 +0200 Subject: [PATCH 3309/9938] mfd: ucb1x00: Use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ucb1x00-core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index bcafe1ecd71c..9ab9ec47ea75 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); @@ -109,7 +109,7 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned long flags; spin_lock_irqsave(&ucb->io_lock, flags); @@ -126,7 +126,7 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned val; ucb1x00_enable(ucb); @@ -138,7 +138,7 @@ static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned long flags; spin_lock_irqsave(&ucb->io_lock, flags); @@ -154,7 +154,7 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset , int value) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned long flags; unsigned old, mask = 1 << offset; @@ -181,7 +181,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset) { - struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); + struct ucb1x00 *ucb = gpiochip_get_data(chip); return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO; } @@ -579,7 +579,7 @@ static int ucb1x00_probe(struct mcp *mcp) ucb->gpio.direction_input = ucb1x00_gpio_direction_input; ucb->gpio.direction_output = ucb1x00_gpio_direction_output; ucb->gpio.to_irq = ucb1x00_to_irq; - ret = gpiochip_add(&ucb->gpio); + ret = gpiochip_add_data(&ucb->gpio, ucb); if (ret) goto err_gpio_add; } else -- GitLab From 7ad073695dff7b1fc2a6ef2e8112d96a76fc8dc4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Mar 2016 10:48:09 +0200 Subject: [PATCH 3310/9938] mfd: vexpress-sysreg: Switch to gpiochip_add_data() We're planning to remove the gpiochip_add() function to swith to gpiochip_add_data() with NULL for data argument. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/vexpress-sysreg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 855c0204f09a..201a3ea2a9d3 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -202,7 +202,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI, NULL, NULL, NULL, NULL, 0); mmc_gpio_chip->ngpio = 2; - gpiochip_add(mmc_gpio_chip); + gpiochip_add_data(mmc_gpio_chip, NULL); return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, vexpress_sysreg_cells, -- GitLab From 630fd98c0a7fcba67d4b33440793b0c9bd1fb440 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 Apr 2016 11:04:51 +0900 Subject: [PATCH 3311/9938] mfd: max77686/max77693: Fix misspelled Samsung address Correct smasung.com into samsung.com. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/max77686.c | 2 +- drivers/mfd/max77693.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index c1aff46e89d9..0aa33d4ee165 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -2,7 +2,7 @@ * max77686.c - mfd core driver for the Maxim 77686/802 * * Copyright (C) 2012 Samsung Electronics - * Chiwoong Byun + * Chiwoong Byun * Jonghwa Lee * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 78e501feb96c..662ae0d9e334 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -2,7 +2,7 @@ * max77693.c - mfd core driver for the MAX 77693 * * Copyright (C) 2012 Samsung Electronics - * SangYoung Son + * SangYoung Son * * This program is not provided / owned by Maxim Integrated Products. * -- GitLab From 8a0aee4a7c8500278495012d8f4b653033df83a3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 4 Apr 2016 18:46:02 -0400 Subject: [PATCH 3312/9938] mfd: max77686: Use module_i2c_driver() instead of subsys initcall The driver's init and exit function don't do anything besides adding and deleting the I2C driver so the module_i2c_driver() macro could be used. Currently is not being used because the driver is initialized at subsys initcall level, claiming that this is done to allow consumers devices to use the resources provided by this driver. But dependencies are in DT so manual ordering of init calls is not necessary any more. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Lee Jones --- drivers/mfd/max77686.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 0aa33d4ee165..7a0457e1771b 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -321,18 +321,7 @@ static struct i2c_driver max77686_i2c_driver = { .id_table = max77686_i2c_id, }; -static int __init max77686_i2c_init(void) -{ - return i2c_add_driver(&max77686_i2c_driver); -} -/* init early so consumer devices can complete system boot */ -subsys_initcall(max77686_i2c_init); - -static void __exit max77686_i2c_exit(void) -{ - i2c_del_driver(&max77686_i2c_driver); -} -module_exit(max77686_i2c_exit); +module_i2c_driver(max77686_i2c_driver); MODULE_DESCRIPTION("MAXIM 77686/802 multi-function core driver"); MODULE_AUTHOR("Chiwoong Byun "); -- GitLab From ba5776ab6f09800dd9ba8442185139661e065529 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 11 Apr 2016 10:27:32 -0700 Subject: [PATCH 3313/9938] mfd: cros_ec: Allow building for ARM64 There are platforms using the ChromeOS embeded controller on ARM64 now, so let's allow using this driver (without having to use COMPILE_TEST). Signed-off-by: Brian Norris Reviewed-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index aa1e7c3f82ee..cf7cbba61971 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -134,7 +134,7 @@ config MFD_CROS_EC select MFD_CORE select CHROME_PLATFORMS select CROS_EC_PROTO - depends on X86 || ARM || COMPILE_TEST + depends on X86 || ARM || ARM64 || COMPILE_TEST help If you say Y here you get support for the ChromeOS Embedded Controller (EC) providing keyboard, battery and power services. -- GitLab From fe15ee47e48d6d10f60c11ac7a15ecc0d147d9ea Mon Sep 17 00:00:00 2001 From: Martin Dummer Date: Sun, 17 Apr 2016 13:27:52 +0200 Subject: [PATCH 3314/9938] leds: ss4200: Add depend on x86 arch There is only one x86 hardware where the driver leds-ss4200 applies to. Add kconfig dependency to x86 architecture, fix help text whitespace. Signed-off-by: Martin Dummer Signed-off-by: Jacek Anaszewski --- drivers/leds/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 225147863e02..5ae28340a98b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -413,10 +413,11 @@ config LEDS_INTEL_SS4200 tristate "LED driver for Intel NAS SS4200 series" depends on LEDS_CLASS depends on PCI && DMI + depends on X86 help This option enables support for the Intel SS4200 series of - Network Attached Storage servers. You may control the hard - drive or power LEDs on the front panel. Using this driver + Network Attached Storage servers. You may control the hard + drive or power LEDs on the front panel. Using this driver can stop the front LED from blinking after startup. config LEDS_LT3593 -- GitLab From f15c65afddbe16a832cfe3f311588c7e34a4efbf Mon Sep 17 00:00:00 2001 From: Martin Dummer Date: Tue, 19 Apr 2016 07:51:48 +0200 Subject: [PATCH 3315/9938] leds: ss4200: add DMI data for FSC SCALEO Home Server The Intel NAS SS4200 was also sold by Fujitsu Siemens (FSC) under the name "SCALEO Home Server". The hardware is equivalent. This patch adds the DMI data of this rebranded device. Signed-off-by: Martin Dummer Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ss4200.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c index 046cb7008745..732eb86bc1a5 100644 --- a/drivers/leds/leds-ss4200.c +++ b/drivers/leds/leds-ss4200.c @@ -101,6 +101,19 @@ static struct dmi_system_id nas_led_whitelist[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00") } }, + { + /* + * FUJITSU SIEMENS SCALEO Home Server/SS4200-E + * BIOS V090L 12/19/2007 + */ + .callback = ss4200_led_dmi_callback, + .ident = "Fujitsu Siemens SCALEO Home Server", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "SCALEO Home Server"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00") + } + }, {} }; -- GitLab From 70fdb273db37196e9e5d292d5778a99fededb32f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Apr 2016 12:47:15 +0300 Subject: [PATCH 3316/9938] usb: dwc3: get rid of DWC3_TRB_MASK instead of using a bitwise and, let's rely on the % operator since that's a lot more clear. Also, GCC will optimize % 256 to nothing anyway. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 - drivers/usb/dwc3/gadget.c | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 2f19573e08d9..832da3f2e03a 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -440,7 +440,6 @@ struct dwc3_event_buffer { #define DWC3_EP_DIRECTION_RX false #define DWC3_TRB_NUM 256 -#define DWC3_TRB_MASK (DWC3_TRB_NUM - 1) /** * struct dwc3_ep - device side endpoint representation diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index bb29f4f08f5d..0e7cc20c2fd0 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -160,8 +160,8 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, * DWC3_TRBCTL_LINK_TRB because it points the TRB we * just completed (not the LINK TRB). */ - if (((dep->trb_dequeue & DWC3_TRB_MASK) == - DWC3_TRB_NUM- 1) && + if (((dep->trb_dequeue % DWC3_TRB_NUM) == + DWC3_TRB_NUM - 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) dep->trb_dequeue++; } while(++i < req->request.num_mapped_sgs); @@ -741,18 +741,18 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, chain ? " chain" : ""); - trb = &dep->trb_pool[dep->trb_enqueue & DWC3_TRB_MASK]; + trb = &dep->trb_pool[dep->trb_enqueue % DWC3_TRB_NUM]; if (!req->trb) { dwc3_gadget_move_started_request(req); req->trb = trb; req->trb_dma = dwc3_trb_dma_offset(dep, trb); - req->first_trb_index = dep->trb_enqueue & DWC3_TRB_MASK; + req->first_trb_index = dep->trb_enqueue % DWC3_TRB_NUM; } dep->trb_enqueue++; /* Skip the LINK-TRB on ISOC */ - if (((dep->trb_enqueue & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && + if (((dep->trb_enqueue % DWC3_TRB_NUM) == DWC3_TRB_NUM - 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) dep->trb_enqueue++; @@ -826,11 +826,11 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); /* the first request must not be queued */ - trbs_left = (dep->trb_dequeue - dep->trb_enqueue) & DWC3_TRB_MASK; + trbs_left = (dep->trb_dequeue - dep->trb_enqueue) % DWC3_TRB_NUM; /* Can't wrap around on a non-isoc EP since there's no link TRB */ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - max = DWC3_TRB_NUM - (dep->trb_enqueue & DWC3_TRB_MASK); + max = DWC3_TRB_NUM - (dep->trb_enqueue % DWC3_TRB_NUM); if (trbs_left > max) trbs_left = max; } -- GitLab From ef966b9d33533b0bf01fb8c4d586ac3b20a3bdb5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Apr 2016 13:09:51 +0300 Subject: [PATCH 3317/9938] usb: dwc3: gadget: add trb enqueue/dequeue helpers Add three little helpers which will aid in making the code slightly easier to read. One helper increments enqueue pointer, another increments dequeue pointer and the last one tests if we're dealing with the last TRB. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0e7cc20c2fd0..98d8a4549103 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -145,6 +145,21 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) return -ETIMEDOUT; } +static void dwc3_ep_inc_enq(struct dwc3_ep *dep) +{ + dep->trb_enqueue++; +} + +static void dwc3_ep_inc_deq(struct dwc3_ep *dep) +{ + dep->trb_dequeue++; +} + +static int dwc3_ep_is_last_trb(unsigned int index) +{ + return (index % DWC3_TRB_NUM) == (DWC3_TRB_NUM - 1); +} + void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status) { @@ -154,16 +169,15 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->started) { i = 0; do { - dep->trb_dequeue++; + dwc3_ep_inc_deq(dep); /* * Skip LINK TRB. We can't use req->trb and check for * DWC3_TRBCTL_LINK_TRB because it points the TRB we * just completed (not the LINK TRB). */ - if (((dep->trb_dequeue % DWC3_TRB_NUM) == - DWC3_TRB_NUM - 1) && + if (dwc3_ep_is_last_trb(dep->trb_dequeue) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) - dep->trb_dequeue++; + dwc3_ep_inc_deq(dep); } while(++i < req->request.num_mapped_sgs); req->started = false; } @@ -750,11 +764,11 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, req->first_trb_index = dep->trb_enqueue % DWC3_TRB_NUM; } - dep->trb_enqueue++; + dwc3_ep_inc_enq(dep); /* Skip the LINK-TRB on ISOC */ - if (((dep->trb_enqueue % DWC3_TRB_NUM) == DWC3_TRB_NUM - 1) && + if (dwc3_ep_is_last_trb(dep->trb_enqueue) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) - dep->trb_enqueue++; + dwc3_ep_inc_enq(dep); trb->size = DWC3_TRB_SIZE_LENGTH(length); trb->bpl = lower_32_bits(dma); -- GitLab From 4faf75504a7db790483aa419d8f61e58cec4934c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Apr 2016 13:14:31 +0300 Subject: [PATCH 3318/9938] usb: dwc3: gadget: move % operation to increment helpers By moving our % DWC3_NUM_TRB operation to the increment helpers, the rest of the driver can be simplified. It's also a good practice to make sure we will have a single place dealing with details about how to increment our enqueue and dequeue pointers. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 98d8a4549103..6c5eb0c59696 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -148,16 +148,18 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) static void dwc3_ep_inc_enq(struct dwc3_ep *dep) { dep->trb_enqueue++; + dep->trb_enqueue %= DWC3_TRB_NUM; } static void dwc3_ep_inc_deq(struct dwc3_ep *dep) { dep->trb_dequeue++; + dep->trb_dequeue %= DWC3_TRB_NUM; } static int dwc3_ep_is_last_trb(unsigned int index) { - return (index % DWC3_TRB_NUM) == (DWC3_TRB_NUM - 1); + return index == DWC3_TRB_NUM - 1; } void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, @@ -755,13 +757,13 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, chain ? " chain" : ""); - trb = &dep->trb_pool[dep->trb_enqueue % DWC3_TRB_NUM]; + trb = &dep->trb_pool[dep->trb_enqueue]; if (!req->trb) { dwc3_gadget_move_started_request(req); req->trb = trb; req->trb_dma = dwc3_trb_dma_offset(dep, trb); - req->first_trb_index = dep->trb_enqueue % DWC3_TRB_NUM; + req->first_trb_index = dep->trb_enqueue; } dwc3_ep_inc_enq(dep); @@ -840,11 +842,11 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); /* the first request must not be queued */ - trbs_left = (dep->trb_dequeue - dep->trb_enqueue) % DWC3_TRB_NUM; + trbs_left = dep->trb_dequeue - dep->trb_enqueue; /* Can't wrap around on a non-isoc EP since there's no link TRB */ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - max = DWC3_TRB_NUM - (dep->trb_enqueue % DWC3_TRB_NUM); + max = DWC3_TRB_NUM - dep->trb_enqueue; if (trbs_left > max) trbs_left = max; } -- GitLab From 36b68aae8e39ad456eec1ec2073eee388cbcc106 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Apr 2016 13:24:36 +0300 Subject: [PATCH 3319/9938] usb: dwc3: gadget: use link TRB for all endpoint types instead of limiting link TRB only to Isoc endpoints, let's use it for all endpoint types, this way we are more likely to transfer more data before a XferComplete event. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 49 ++++++++------------------------------- 1 file changed, 10 insertions(+), 39 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 6c5eb0c59696..5f95008aa730 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -177,8 +177,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, * DWC3_TRBCTL_LINK_TRB because it points the TRB we * just completed (not the LINK TRB). */ - if (dwc3_ep_is_last_trb(dep->trb_dequeue) && - usb_endpoint_xfer_isoc(dep->endpoint.desc)) + if (dwc3_ep_is_last_trb(dep->trb_dequeue)) dwc3_ep_inc_deq(dep); } while(++i < req->request.num_mapped_sgs); req->started = false; @@ -541,10 +540,10 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); - if (!usb_endpoint_xfer_isoc(desc)) + if (usb_endpoint_xfer_control(desc)) goto out; - /* Link TRB for ISOC. The HWO bit is never reset */ + /* Link TRB. The HWO bit is never reset */ trb_st_hw = &dep->trb_pool[0]; trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; @@ -767,9 +766,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, } dwc3_ep_inc_enq(dep); - /* Skip the LINK-TRB on ISOC */ - if (dwc3_ep_is_last_trb(dep->trb_enqueue) && - usb_endpoint_xfer_isoc(dep->endpoint.desc)) + /* Skip the LINK-TRB */ + if (dwc3_ep_is_last_trb(dep->trb_enqueue)) dwc3_ep_inc_enq(dep); trb->size = DWC3_TRB_SIZE_LENGTH(length); @@ -836,52 +834,26 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) { struct dwc3_request *req, *n; u32 trbs_left; - u32 max; unsigned int last_one = 0; BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); - /* the first request must not be queued */ trbs_left = dep->trb_dequeue - dep->trb_enqueue; - /* Can't wrap around on a non-isoc EP since there's no link TRB */ - if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - max = DWC3_TRB_NUM - dep->trb_enqueue; - if (trbs_left > max) - trbs_left = max; - } - /* - * If busy & slot are equal than it is either full or empty. If we are - * starting to process requests then we are empty. Otherwise we are + * If enqueue & dequeue are equal than it is either full or empty. If we + * are starting to process requests then we are empty. Otherwise we are * full and don't do anything */ if (!trbs_left) { if (!starting) return; + trbs_left = DWC3_TRB_NUM; - /* - * In case we start from scratch, we queue the ISOC requests - * starting from slot 1. This is done because we use ring - * buffer and have no LST bit to stop us. Instead, we place - * IOC bit every TRB_NUM/4. We try to avoid having an interrupt - * after the first request so we start at slot 1 and have - * 7 requests proceed before we hit the first IOC. - * Other transfer types don't use the ring buffer and are - * processed from the first TRB until the last one. Since we - * don't wrap around we have to start at the beginning. - */ - if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { - dep->trb_dequeue = 1; - dep->trb_enqueue = 1; - } else { - dep->trb_dequeue = 0; - dep->trb_enqueue = 0; - } } /* The last TRB is a link TRB, not used for xfer */ - if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) + if (trbs_left <= 1) return; list_for_each_entry_safe(req, n, &dep->pending_list, list) { @@ -1948,8 +1920,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, i = 0; do { slot = req->first_trb_index + i; - if ((slot == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->endpoint.desc)) + if (slot == DWC3_TRB_NUM - 1) slot++; slot %= DWC3_TRB_NUM; trb = &dep->trb_pool[slot]; -- GitLab From 052ba52efa1717651d303a9b88f2e8cbb91702c6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Apr 2016 15:05:05 +0300 Subject: [PATCH 3320/9938] usb: dwc3: gadget: remove newline from trace trace already adds a newline character for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5f95008aa730..c068a8f21f37 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1264,7 +1264,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) (!list_empty(&dep->started_list) || !list_empty(&dep->pending_list)))) { dwc3_trace(trace_dwc3_gadget, - "%s: pending request, cannot halt\n", + "%s: pending request, cannot halt", dep->name); return -EAGAIN; } -- GitLab From 8e7046b71daeb6dfbf8c6eaa164e55d4e1dcb5c8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Apr 2016 10:01:14 +0300 Subject: [PATCH 3321/9938] usb: dwc3: gadget: don't interrupt when chained It makes no sense to interrupt in the middle of chained transfer. This patch just makes sure we don't do that. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c068a8f21f37..88fd30bf0c46 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -804,7 +804,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, /* always enable Continue on Short Packet */ trb->ctrl |= DWC3_TRB_CTRL_CSP; - if (!req->request.no_interrupt) + if (!req->request.no_interrupt && !chain) trb->ctrl |= DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI; if (last) -- GitLab From af566a0be6e49b946708532a6a7a7ae29ab83aed Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 11 Apr 2016 17:18:25 +0300 Subject: [PATCH 3322/9938] usb: dwc3: omap: get rid of dma_status dma_status bit flag is set but never really used so get rid of it. Reported-by: Felipe Balbi Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index e92a992c2255..59ea35ffc043 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -126,8 +126,6 @@ struct dwc3_omap { u32 debug_offset; u32 irq0_offset; - u32 dma_status:1; - struct extcon_dev *edev; struct notifier_block vbus_nb; struct notifier_block id_nb; @@ -277,9 +275,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) reg = dwc3_omap_read_irqmisc_status(omap); - if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) - omap->dma_status = false; - dwc3_omap_write_irqmisc_status(omap, reg); reg = dwc3_omap_read_irq0_status(omap); @@ -501,7 +496,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) /* check the DMA Status */ reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); - omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0, "dwc3-omap", omap); -- GitLab From 4e9f311833a946e984c82086b21b128918f4a6a4 Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Tue, 12 Apr 2016 19:10:18 +0800 Subject: [PATCH 3323/9938] usb: dwc3: make dwc3_debugfs_init return value be void Debugfs init failure is not so important. We can continue our job on this failure. Also no break need for debugfs_create_file call failure. Signed-off-by: Du, Changbin [felipe.balbi@linux.intel.com : - remove out-of-memory message, we get that from OOM. - switch dev_err() to dev_dbg() ] Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 10 +------ drivers/usb/dwc3/debug.h | 6 ++--- drivers/usb/dwc3/debugfs.c | 55 +++++++++++++------------------------- 3 files changed, 23 insertions(+), 48 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 940489c1d1bd..6f57929f09b4 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1030,19 +1030,11 @@ static int dwc3_probe(struct platform_device *pdev) if (ret) goto err5; - ret = dwc3_debugfs_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize debugfs\n"); - goto err6; - } - + dwc3_debugfs_init(dwc); pm_runtime_allow(dev); return 0; -err6: - dwc3_core_exit_mode(dwc); - err5: dwc3_event_buffers_cleanup(dwc); diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index 07fbc2d94fd4..71e318025964 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -217,11 +217,11 @@ static inline const char *dwc3_gadget_event_type_string(u8 event) void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...); #ifdef CONFIG_DEBUG_FS -extern int dwc3_debugfs_init(struct dwc3 *); +extern void dwc3_debugfs_init(struct dwc3 *); extern void dwc3_debugfs_exit(struct dwc3 *); #else -static inline int dwc3_debugfs_init(struct dwc3 *d) -{ return 0; } +static inline void dwc3_debugfs_init(struct dwc3 *d) +{ } static inline void dwc3_debugfs_exit(struct dwc3 *d) { } #endif diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 9ac37fe1b6a7..81faddc60c8e 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -618,24 +618,23 @@ static const struct file_operations dwc3_link_state_fops = { .release = single_release, }; -int dwc3_debugfs_init(struct dwc3 *dwc) +void dwc3_debugfs_init(struct dwc3 *dwc) { struct dentry *root; - struct dentry *file; - int ret; + struct dentry *file; root = debugfs_create_dir(dev_name(dwc->dev), NULL); - if (!root) { - ret = -ENOMEM; - goto err0; + if (IS_ERR_OR_NULL(root)) { + if (!root) + dev_err(dwc->dev, "Can't create debugfs root\n"); + return; } - dwc->root = root; dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL); if (!dwc->regset) { - ret = -ENOMEM; - goto err1; + debugfs_remove_recursive(root); + return; } dwc->regset->regs = dwc3_regs; @@ -643,44 +642,28 @@ int dwc3_debugfs_init(struct dwc3 *dwc) dwc->regset->base = dwc->regs; file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); - if (!file) { - ret = -ENOMEM; - goto err1; - } + if (!file) + dev_dbg(dwc->dev, "Can't create debugfs regdump\n"); if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, dwc, &dwc3_mode_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } + if (!file) + dev_dbg(dwc->dev, "Can't create debugfs mode\n"); } if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, dwc, &dwc3_testmode_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - - file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, - dwc, &dwc3_link_state_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - } + if (!file) + dev_dbg(dwc->dev, "Can't create debugfs testmode\n"); - return 0; - -err1: - debugfs_remove_recursive(root); - -err0: - return ret; + file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, + root, dwc, &dwc3_link_state_fops); + if (!file) + dev_dbg(dwc->dev, "Can't create debugfs link_state\n"); + } } void dwc3_debugfs_exit(struct dwc3 *dwc) -- GitLab From 5096c4d3bfa75bdd23c78f799aabd08598afb48f Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 18 Apr 2016 16:53:38 +0900 Subject: [PATCH 3324/9938] usb: gadget: udc: core: Fix argument of dev_err() in usb_gadget_map_request() The argument of dev_err() in usb_gadget_map_request() should be dev instead of &gadget->dev. Fixes: 7ace8fc ("usb: gadget: udc: core: Fix argument of dma_map_single for IOMMU") Cc: # v4.3+ Signed-off-by: Yoshihiro Shimoda --- drivers/usb/gadget/udc/udc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index e4e70e11d0f6..c6e76465065a 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -75,7 +75,7 @@ int usb_gadget_map_request(struct usb_gadget *gadget, mapped = dma_map_sg(dev, req->sg, req->num_sgs, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (mapped == 0) { - dev_err(&gadget->dev, "failed to map SGs\n"); + dev_err(dev, "failed to map SGs\n"); return -EFAULT; } -- GitLab From 679ca39fc670a5a95c2b40d2cc8cf2cee2486f7a Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 18 Apr 2016 16:53:39 +0900 Subject: [PATCH 3325/9938] usb: gadget: udc: core: add usb_gadget_{un}map_request_by_dev() If the following environment, the first argument of DMA API should be set to a DMAC's device structure, not a udc controller's one. - A udc controller needs an external DMAC device (like a DMA Engine). - The external DMAC enables IOMMU. So, this patch add usb_gadget_{un}map_request_by_dev() API to set a DMAC's device structure by a udc controller driver. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/udc-core.c | 24 ++++++++++++++++++------ include/linux/usb/gadget.h | 4 ++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index c6e76465065a..6e8300d6a737 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -61,11 +61,9 @@ static int udc_bind_to_driver(struct usb_udc *udc, #ifdef CONFIG_HAS_DMA -int usb_gadget_map_request(struct usb_gadget *gadget, +int usb_gadget_map_request_by_dev(struct device *dev, struct usb_request *req, int is_in) { - struct device *dev = gadget->dev.parent; - if (req->length == 0) return 0; @@ -92,24 +90,38 @@ int usb_gadget_map_request(struct usb_gadget *gadget, return 0; } +EXPORT_SYMBOL_GPL(usb_gadget_map_request_by_dev); + +int usb_gadget_map_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) +{ + return usb_gadget_map_request_by_dev(gadget->dev.parent, req, is_in); +} EXPORT_SYMBOL_GPL(usb_gadget_map_request); -void usb_gadget_unmap_request(struct usb_gadget *gadget, +void usb_gadget_unmap_request_by_dev(struct device *dev, struct usb_request *req, int is_in) { if (req->length == 0) return; if (req->num_mapped_sgs) { - dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs, + dma_unmap_sg(dev, req->sg, req->num_mapped_sgs, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->num_mapped_sgs = 0; } else { - dma_unmap_single(gadget->dev.parent, req->dma, req->length, + dma_unmap_single(dev, req->dma, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } } +EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev); + +void usb_gadget_unmap_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) +{ + usb_gadget_unmap_request_by_dev(gadget->dev.parent, req, is_in); +} EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); #endif /* CONFIG_HAS_DMA */ diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 5d4e151c49bf..457651bf45b0 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -1223,9 +1223,13 @@ int usb_otg_descriptor_init(struct usb_gadget *gadget, /* utility to simplify map/unmap of usb_requests to/from DMA */ +extern int usb_gadget_map_request_by_dev(struct device *dev, + struct usb_request *req, int is_in); extern int usb_gadget_map_request(struct usb_gadget *gadget, struct usb_request *req, int is_in); +extern void usb_gadget_unmap_request_by_dev(struct device *dev, + struct usb_request *req, int is_in); extern void usb_gadget_unmap_request(struct usb_gadget *gadget, struct usb_request *req, int is_in); -- GitLab From e789ece1823596f24076aed1b9a2182a81b0a6b7 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 18 Apr 2016 16:53:40 +0900 Subject: [PATCH 3326/9938] usb: renesas_usbhs: change function call orfer in usbhsf_dma_prepare_push() Since usbhsf_dma_{un}map() will use the "fifo" data in the near future, this patch changes function call orfer in usbhsf_dma_prepare_push(). Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 000f9750149f..a805b239e805 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -881,12 +881,12 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) if (!fifo) goto usbhsf_pio_prepare_push; - if (usbhsf_dma_map(pkt) < 0) - goto usbhsf_pio_prepare_push; - ret = usbhsf_fifo_select(pipe, fifo, 0); if (ret < 0) - goto usbhsf_pio_prepare_push_unmap; + goto usbhsf_pio_prepare_push; + + if (usbhsf_dma_map(pkt) < 0) + goto usbhsf_pio_prepare_push_unselect; pkt->trans = len; @@ -896,8 +896,8 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) return 0; -usbhsf_pio_prepare_push_unmap: - usbhsf_dma_unmap(pkt); +usbhsf_pio_prepare_push_unselect: + usbhsf_fifo_unselect(pipe, fifo); usbhsf_pio_prepare_push: /* * change handler to PIO -- GitLab From c3cdcac786ae8ce9221a05609952d14aa57c27f7 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 18 Apr 2016 16:53:41 +0900 Subject: [PATCH 3327/9938] usb: renesas_usbhs: change arguments of dma_map_ctrl() Since usbhsg_dma_map_ctrl() needs DMA device structure in the near future, this patch changes arguments of dma_map_ctrl() to give such data. (This patch is only change the argument.) Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 4 +++- drivers/usb/renesas_usbhs/mod_gadget.c | 3 ++- drivers/usb/renesas_usbhs/mod_host.c | 3 ++- drivers/usb/renesas_usbhs/pipe.c | 3 ++- drivers/usb/renesas_usbhs/pipe.h | 6 ++++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index a805b239e805..7be4e7d57ace 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -799,8 +799,10 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); + struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); + struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); - return info->dma_map_ctrl(pkt, map); + return info->dma_map_ctrl(chan->device->dev, pkt, map); } static void usbhsf_dma_complete(void *arg); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 53d104b56ef1..d701ae643ace 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -191,7 +191,8 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, /* * dma map/unmap */ -static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map) +static int usbhsg_dma_map_ctrl(struct device *dma_dev, struct usbhs_pkt *pkt, + int map) { struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); struct usb_request *req = &ureq->req; diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 1a8e4c45c4c5..3bf0b72eb359 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -929,7 +929,8 @@ static int usbhsh_dcp_queue_push(struct usb_hcd *hcd, /* * dma map functions */ -static int usbhsh_dma_map_ctrl(struct usbhs_pkt *pkt, int map) +static int usbhsh_dma_map_ctrl(struct device *dma_dev, struct usbhs_pkt *pkt, + int map) { if (map) { struct usbhsh_request *ureq = usbhsh_pkt_to_ureq(pkt); diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 78e9dba701c4..77b615ce4a25 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -655,7 +655,8 @@ static void usbhsp_put_pipe(struct usbhs_pipe *pipe) } void usbhs_pipe_init(struct usbhs_priv *priv, - int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)) + int (*dma_map_ctrl)(struct device *dma_dev, + struct usbhs_pkt *pkt, int map)) { struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); struct usbhs_pipe *pipe; diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 7835747f9803..95185fdb29b1 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -47,7 +47,8 @@ struct usbhs_pipe_info { struct usbhs_pipe *pipe; int size; /* array size of "pipe" */ - int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map); + int (*dma_map_ctrl)(struct device *dma_dev, struct usbhs_pkt *pkt, + int map); }; /* @@ -84,7 +85,8 @@ int usbhs_pipe_is_running(struct usbhs_pipe *pipe); void usbhs_pipe_running(struct usbhs_pipe *pipe, int running); void usbhs_pipe_init(struct usbhs_priv *priv, - int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); + int (*dma_map_ctrl)(struct device *dma_dev, + struct usbhs_pkt *pkt, int map)); int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); void usbhs_pipe_clear(struct usbhs_pipe *pipe); int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe); -- GitLab From b41d8a6a014fba420a428244e04699b9c77a44f1 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 18 Apr 2016 16:53:42 +0900 Subject: [PATCH 3328/9938] usb: renesas_usbhs: use usb_gadget_{un}map_request_by_dev() for IPMMU The previous code could use the first USB-DMAC with IPMMU if iommus property was set into this device node. However, in this case, it could not control the second USB-DMAC with IPMMU because a parameter of IPMMU (micro-TLB id) is different with each USB-DMAC. So, this patch uses the usb_gadget_{un}map_request_by_dev() APIs for IPMMU. (Then, iommus property should be set into USB-DMAC node(s).) Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index d701ae643ace..30345c2d01be 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -197,8 +197,6 @@ static int usbhsg_dma_map_ctrl(struct device *dma_dev, struct usbhs_pkt *pkt, struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); struct usb_request *req = &ureq->req; struct usbhs_pipe *pipe = pkt->pipe; - struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); - struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); enum dma_data_direction dir; int ret = 0; @@ -208,13 +206,13 @@ static int usbhsg_dma_map_ctrl(struct device *dma_dev, struct usbhs_pkt *pkt, /* it can not use scatter/gather */ WARN_ON(req->num_sgs); - ret = usb_gadget_map_request(&gpriv->gadget, req, dir); + ret = usb_gadget_map_request_by_dev(dma_dev, req, dir); if (ret < 0) return ret; pkt->dma = req->dma; } else { - usb_gadget_unmap_request(&gpriv->gadget, req, dir); + usb_gadget_unmap_request_by_dev(dma_dev, req, dir); } return ret; -- GitLab From 9bc07890f891267285716c09bfee58e239137d36 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Apr 2016 15:05:12 +0200 Subject: [PATCH 3329/9938] usb: gadget: r8a66597-udc: Deinline pipe_change, save 2176 bytes This function compiles to 298 bytes of machine code, has ~10 callsites. This is a USB 2.0 device, USB 2.0 is limited to ~40 MB/s, so should be almost never CPU bound. No need to optimize for speed this agressively. Signed-off-by: Denys Vlasenko CC: Felipe Balbi CC: linux-usb@vger.kernel.org CC: linux-kernel@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/r8a66597-udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index baa0609a429d..8b300e6da7fc 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -296,7 +296,7 @@ static void r8a66597_change_curpipe(struct r8a66597 *r8a66597, u16 pipenum, } while ((tmp & mask) != loop); } -static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum) +static void pipe_change(struct r8a66597 *r8a66597, u16 pipenum) { struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum]; -- GitLab From 332a5b446b7916d272c2a659a3b20909ce34d2c1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 30 Mar 2016 13:49:14 +0200 Subject: [PATCH 3330/9938] usb: gadget: f_fs: Fix EFAULT generation for async read operations In the current implementation functionfs generates a EFAULT for async read operations if the read buffer size is larger than the URB data size. Since a application does not necessarily know how much data the host side is going to send it typically supplies a buffer larger than the actual data, which will then result in a EFAULT error. This behaviour was introduced while refactoring the code to use iov_iter interface in commit c993c39b8639 ("gadget/function/f_fs.c: use put iov_iter into io_data"). The original code took the minimum over the URB size and the user buffer size and then attempted to copy that many bytes using copy_to_user(). If copy_to_user() could not copy all data a EFAULT error was generated. Restore the original behaviour by only generating a EFAULT error when the number of bytes copied is not the size of the URB and the target buffer has not been fully filled. Commit 342f39a6c8d3 ("usb: gadget: f_fs: fix check in read operation") already fixed the same problem for the synchronous read path. Fixes: c993c39b8639 ("gadget/function/f_fs.c: use put iov_iter into io_data") Acked-by: Michal Nazarewicz Signed-off-by: Lars-Peter Clausen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index e21ca2bd6839..2c314c13f9a7 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -650,7 +650,7 @@ static void ffs_user_copy_worker(struct work_struct *work) if (io_data->read && ret > 0) { use_mm(io_data->mm); ret = copy_to_iter(io_data->buf, ret, &io_data->data); - if (iov_iter_count(&io_data->data)) + if (ret != io_data->req->actual && iov_iter_count(&io_data->data)) ret = -EFAULT; unuse_mm(io_data->mm); } -- GitLab From f78bbcae86e676fad9e6c6bb6cd9d9868ba23696 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 8 Apr 2016 10:24:11 +0200 Subject: [PATCH 3331/9938] usb: f_mass_storage: test whether thread is running before starting another MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When binding the function to usb_configuration, check whether the thread is running before starting another one. Without that, when function instance is added to multiple configurations, fsg_bing starts multiple threads with all but the latest one being forgotten by the driver. This leads to obvious thread leaks, possible lockups when trying to halt the machine and possible more issues. This fixes issues with legacy/multi¹ gadget as well as configfs gadgets when mass_storage function is added to multiple configurations. This change also simplifies API since the legacy gadgets no longer need to worry about starting the thread by themselves (which was where bug in legacy/multi was in the first place). N.B., this patch doesn’t address adding single mass_storage function instance to a single configuration twice. Thankfully, there’s no legitimate reason for such setup plus, if I’m not mistaken, configfs gadget doesn’t even allow it to be expressed. ¹ I have no example failure though. Conclusion that legacy/multi has a bug is based purely on me reading the code. Acked-by: Alan Stern Signed-off-by: Michal Nazarewicz Tested-by: Ivaylo Dimitrov Cc: Alan Stern Cc: Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 36 ++++++++------------ drivers/usb/gadget/function/f_mass_storage.h | 2 -- drivers/usb/gadget/legacy/acm_ms.c | 4 --- drivers/usb/gadget/legacy/mass_storage.c | 4 --- drivers/usb/gadget/legacy/multi.c | 12 ------- drivers/usb/gadget/legacy/nokia.c | 7 ---- 6 files changed, 15 insertions(+), 50 deletions(-) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index acf210f16328..5c6d4d7ca605 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2977,25 +2977,6 @@ void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn, } EXPORT_SYMBOL_GPL(fsg_common_set_inquiry_string); -int fsg_common_run_thread(struct fsg_common *common) -{ - common->state = FSG_STATE_IDLE; - /* Tell the thread to start working */ - common->thread_task = - kthread_create(fsg_main_thread, common, "file-storage"); - if (IS_ERR(common->thread_task)) { - common->state = FSG_STATE_TERMINATED; - return PTR_ERR(common->thread_task); - } - - DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task)); - - wake_up_process(common->thread_task); - - return 0; -} -EXPORT_SYMBOL_GPL(fsg_common_run_thread); - static void fsg_common_release(struct kref *ref) { struct fsg_common *common = container_of(ref, struct fsg_common, ref); @@ -3005,6 +2986,7 @@ static void fsg_common_release(struct kref *ref) if (common->state != FSG_STATE_TERMINATED) { raise_exception(common, FSG_STATE_EXIT); wait_for_completion(&common->thread_notifier); + common->thread_task = NULL; } for (i = 0; i < ARRAY_SIZE(common->luns); ++i) { @@ -3050,9 +3032,21 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) if (ret) return ret; fsg_common_set_inquiry_string(fsg->common, NULL, NULL); - ret = fsg_common_run_thread(fsg->common); - if (ret) + } + + if (!common->thread_task) { + common->state = FSG_STATE_IDLE; + common->thread_task = + kthread_create(fsg_main_thread, common, "file-storage"); + if (IS_ERR(common->thread_task)) { + int ret = PTR_ERR(common->thread_task); + common->thread_task = NULL; + common->state = FSG_STATE_TERMINATED; return ret; + } + DBG(common, "I/O thread pid: %d\n", + task_pid_nr(common->thread_task)); + wake_up_process(common->thread_task); } fsg->gadget = gadget; diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h index 445df6775609..b6a9918eaefb 100644 --- a/drivers/usb/gadget/function/f_mass_storage.h +++ b/drivers/usb/gadget/function/f_mass_storage.h @@ -153,8 +153,6 @@ int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg); void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn, const char *pn); -int fsg_common_run_thread(struct fsg_common *common); - void fsg_config_from_params(struct fsg_config *cfg, const struct fsg_module_parameters *params, unsigned int fsg_num_buffers); diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c index c16089efc322..c39de65a448b 100644 --- a/drivers/usb/gadget/legacy/acm_ms.c +++ b/drivers/usb/gadget/legacy/acm_ms.c @@ -133,10 +133,6 @@ static int acm_ms_do_config(struct usb_configuration *c) if (status < 0) goto put_msg; - status = fsg_common_run_thread(opts->common); - if (status) - goto remove_acm; - status = usb_add_function(c, f_msg); if (status) goto remove_acm; diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c index e61af53c7d2b..125974f32f50 100644 --- a/drivers/usb/gadget/legacy/mass_storage.c +++ b/drivers/usb/gadget/legacy/mass_storage.c @@ -132,10 +132,6 @@ static int msg_do_config(struct usb_configuration *c) if (IS_ERR(f_msg)) return PTR_ERR(f_msg); - ret = fsg_common_run_thread(opts->common); - if (ret) - goto put_func; - ret = usb_add_function(c, f_msg); if (ret) goto put_func; diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c index 229d704a620b..a70a406580ea 100644 --- a/drivers/usb/gadget/legacy/multi.c +++ b/drivers/usb/gadget/legacy/multi.c @@ -137,7 +137,6 @@ static struct usb_function *f_msg_rndis; static int rndis_do_config(struct usb_configuration *c) { - struct fsg_opts *fsg_opts; int ret; if (gadget_is_otg(c->cdev->gadget)) { @@ -169,11 +168,6 @@ static int rndis_do_config(struct usb_configuration *c) goto err_fsg; } - fsg_opts = fsg_opts_from_func_inst(fi_msg); - ret = fsg_common_run_thread(fsg_opts->common); - if (ret) - goto err_run; - ret = usb_add_function(c, f_msg_rndis); if (ret) goto err_run; @@ -225,7 +219,6 @@ static struct usb_function *f_msg_multi; static int cdc_do_config(struct usb_configuration *c) { - struct fsg_opts *fsg_opts; int ret; if (gadget_is_otg(c->cdev->gadget)) { @@ -258,11 +251,6 @@ static int cdc_do_config(struct usb_configuration *c) goto err_fsg; } - fsg_opts = fsg_opts_from_func_inst(fi_msg); - ret = fsg_common_run_thread(fsg_opts->common); - if (ret) - goto err_run; - ret = usb_add_function(c, f_msg_multi); if (ret) goto err_run; diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c index 09975046c694..b1e535f4022e 100644 --- a/drivers/usb/gadget/legacy/nokia.c +++ b/drivers/usb/gadget/legacy/nokia.c @@ -152,7 +152,6 @@ static int nokia_bind_config(struct usb_configuration *c) struct usb_function *f_ecm; struct usb_function *f_obex2 = NULL; struct usb_function *f_msg; - struct fsg_opts *fsg_opts; int status = 0; int obex1_stat = -1; int obex2_stat = -1; @@ -222,12 +221,6 @@ static int nokia_bind_config(struct usb_configuration *c) goto err_ecm; } - fsg_opts = fsg_opts_from_func_inst(fi_msg); - - status = fsg_common_run_thread(fsg_opts->common); - if (status) - goto err_msg; - status = usb_add_function(c, f_msg); if (status) goto err_msg; -- GitLab From 097aa1975e9a5b189d4c6fbc95c0f97e2c49c01e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 18 Apr 2016 12:57:15 +0300 Subject: [PATCH 3332/9938] usb: gadget: pch_udc: don't free devm allocated memory Coccinelle caught this instance of us kfree()ing devm-allocated memory. The solution is just to not do anything in our gadget_release. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index b2b70d4e2f5b..ebc51ec5790a 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -2834,17 +2834,6 @@ static void pch_udc_setup_ep0(struct pch_udc_dev *dev) UDC_DEVINT_SI | UDC_DEVINT_SC); } -/** - * gadget_release() - Free the gadget driver private data - * @pdev reference to struct pci_dev - */ -static void gadget_release(struct device *pdev) -{ - struct pch_udc_dev *dev = dev_get_drvdata(pdev); - - kfree(dev); -} - /** * pch_udc_pcd_reinit() - This API initializes the endpoint structures * @dev: Reference to the driver structure @@ -3151,8 +3140,7 @@ static int pch_udc_probe(struct pci_dev *pdev, /* Put the device in disconnected state till a driver is bound */ pch_udc_set_disconnect(dev); - retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, - gadget_release); + retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); if (retval) goto finished; return 0; -- GitLab From cf6d867d3b57d4eca229b3c506216d98d88be49c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Apr 2016 15:03:39 +0300 Subject: [PATCH 3333/9938] usb: dwc3: core: add fifo space helper this helper will be used, initially, to dump space of different queues and fifos in dwc3 to debugfs. Later, it'll be used to issue remote wakeup when we want to start a transfer and there's something in a TX FIFO. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 14 ++++++++++++++ drivers/usb/dwc3/core.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 6f57929f09b4..c050a88c16d4 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -60,6 +60,20 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) dwc3_writel(dwc->regs, DWC3_GCTL, reg); } +u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) +{ + struct dwc3 *dwc = dep->dwc; + u32 reg; + + dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, + DWC3_GDBGFIFOSPACE_NUM(dep->number) | + DWC3_GDBGFIFOSPACE_TYPE(type)); + + reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); + + return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); +} + /** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 832da3f2e03a..c3ea4270bf33 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -152,6 +152,19 @@ /* Bit fields */ +/* Global Debug Queue/FIFO Space Available Register */ +#define DWC3_GDBGFIFOSPACE_NUM(n) ((n) & 0x1f) +#define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0) +#define DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(n) (((n) >> 16) & 0xffff) + +#define DWC3_TXFIFOQ 1 +#define DWC3_RXFIFOQ 3 +#define DWC3_TXREQQ 5 +#define DWC3_RXREQQ 7 +#define DWC3_RXINFOQ 9 +#define DWC3_DESCFETCHQ 13 +#define DWC3_EVENTQ 15 + /* Global Configuration Register */ #define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) #define DWC3_GCTL_U2RSTECN (1 << 16) @@ -1043,6 +1056,7 @@ struct dwc3_gadget_ep_cmd_params { /* prototypes */ void dwc3_set_mode(struct dwc3 *dwc, u32 mode); +u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type); /* check whether we are on the DWC_usb31 core */ static inline bool dwc3_is_usb31(struct dwc3 *dwc) -- GitLab From b058f3e8a3991ba3ea3504fea1faf81974cf17fa Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Apr 2016 16:05:54 +0300 Subject: [PATCH 3334/9938] usb: dwc3: core: add helper to extract trb type This helper will be used later to convert trb type into a human-readable string for debugfs. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c3ea4270bf33..bbbd1789596e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -580,6 +580,7 @@ enum dwc3_link_state { #define DWC3_TRB_CTRL_IOC (1 << 11) #define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) +#define DWC3_TRBCTL_TYPE(n) ((n) & (0x3f << 4)) #define DWC3_TRBCTL_NORMAL DWC3_TRB_CTRL_TRBCTL(1) #define DWC3_TRBCTL_CONTROL_SETUP DWC3_TRB_CTRL_TRBCTL(2) #define DWC3_TRBCTL_CONTROL_STATUS2 DWC3_TRB_CTRL_TRBCTL(3) -- GitLab From 818ec3aba883f58225c9f5a2318cf373263869ed Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Apr 2016 14:53:44 +0300 Subject: [PATCH 3335/9938] usb: dwc3: debugfs: dump out endpoint details There's a bunch of information in the debug register set from dwc3 which is useful in some debugging scenarios. Let's dump them out in endpoint-specific directories and designated files. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 302 +++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 81faddc60c8e..6c14f653dc9b 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -618,6 +618,306 @@ static const struct file_operations dwc3_link_state_fops = { .release = single_release, }; +struct dwc3_ep_file_map { + char name[25]; + int (*show)(struct seq_file *s, void *unused); +}; + +static int dwc3_tx_fifo_queue_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&dwc->lock, flags); + val = dwc3_core_fifo_space(dep, DWC3_TXFIFOQ); + seq_printf(s, "%u\n", val); + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static int dwc3_rx_fifo_queue_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&dwc->lock, flags); + val = dwc3_core_fifo_space(dep, DWC3_RXFIFOQ); + seq_printf(s, "%u\n", val); + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static int dwc3_tx_request_queue_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&dwc->lock, flags); + val = dwc3_core_fifo_space(dep, DWC3_TXREQQ); + seq_printf(s, "%u\n", val); + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static int dwc3_rx_request_queue_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&dwc->lock, flags); + val = dwc3_core_fifo_space(dep, DWC3_RXREQQ); + seq_printf(s, "%u\n", val); + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static int dwc3_rx_info_queue_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&dwc->lock, flags); + val = dwc3_core_fifo_space(dep, DWC3_RXINFOQ); + seq_printf(s, "%u\n", val); + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static int dwc3_descriptor_fetch_queue_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&dwc->lock, flags); + val = dwc3_core_fifo_space(dep, DWC3_DESCFETCHQ); + seq_printf(s, "%u\n", val); + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static int dwc3_event_queue_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&dwc->lock, flags); + val = dwc3_core_fifo_space(dep, DWC3_EVENTQ); + seq_printf(s, "%u\n", val); + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static int dwc3_ep_transfer_type_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + + spin_lock_irqsave(&dwc->lock, flags); + if (!(dep->flags & DWC3_EP_ENABLED) || + !dep->endpoint.desc) { + seq_printf(s, "--\n"); + goto out; + } + + switch (usb_endpoint_type(dep->endpoint.desc)) { + case USB_ENDPOINT_XFER_CONTROL: + seq_printf(s, "control\n"); + break; + case USB_ENDPOINT_XFER_ISOC: + seq_printf(s, "isochronous\n"); + break; + case USB_ENDPOINT_XFER_BULK: + seq_printf(s, "bulk\n"); + break; + case USB_ENDPOINT_XFER_INT: + seq_printf(s, "interrupt\n"); + break; + default: + seq_printf(s, "--\n"); + } + +out: + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static inline const char *dwc3_trb_type_string(struct dwc3_trb *trb) +{ + switch (DWC3_TRBCTL_TYPE(trb->ctrl)) { + case DWC3_TRBCTL_NORMAL: + return "normal"; + case DWC3_TRBCTL_CONTROL_SETUP: + return "control-setup"; + case DWC3_TRBCTL_CONTROL_STATUS2: + return "control-status2"; + case DWC3_TRBCTL_CONTROL_STATUS3: + return "control-status3"; + case DWC3_TRBCTL_CONTROL_DATA: + return "control-data"; + case DWC3_TRBCTL_ISOCHRONOUS_FIRST: + return "isoc-first"; + case DWC3_TRBCTL_ISOCHRONOUS: + return "isoc"; + case DWC3_TRBCTL_LINK_TRB: + return "link"; + default: + return "UNKNOWN"; + } +} + +static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) +{ + struct dwc3_ep *dep = s->private; + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + int i; + + spin_lock_irqsave(&dwc->lock, flags); + if (dep->number <= 1) { + seq_printf(s, "--\n"); + goto out; + } + + seq_printf(s, "enqueue pointer %d\n", dep->trb_enqueue); + seq_printf(s, "dequeue pointer %d\n", dep->trb_dequeue); + seq_printf(s, "\n--------------------------------------------------\n\n"); + seq_printf(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n"); + + for (i = 0; i < DWC3_TRB_NUM; i++) { + struct dwc3_trb *trb = &dep->trb_pool[i]; + + seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n", + trb->bph, trb->bpl, trb->size, + dwc3_trb_type_string(trb), + !!(trb->ctrl & DWC3_TRB_CTRL_IOC), + !!(trb->ctrl & DWC3_TRB_CTRL_ISP_IMI), + !!(trb->ctrl & DWC3_TRB_CTRL_CSP), + !!(trb->ctrl & DWC3_TRB_CTRL_CHN), + !!(trb->ctrl & DWC3_TRB_CTRL_LST), + !!(trb->ctrl & DWC3_TRB_CTRL_HWO)); + } + +out: + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static struct dwc3_ep_file_map map[] = { + { "tx_fifo_queue", dwc3_tx_fifo_queue_show, }, + { "rx_fifo_queue", dwc3_rx_fifo_queue_show, }, + { "tx_request_queue", dwc3_tx_request_queue_show, }, + { "rx_request_queue", dwc3_rx_request_queue_show, }, + { "rx_info_queue", dwc3_rx_info_queue_show, }, + { "descriptor_fetch_queue", dwc3_descriptor_fetch_queue_show, }, + { "event_queue", dwc3_event_queue_show, }, + { "transfer_type", dwc3_ep_transfer_type_show, }, + { "trb_ring", dwc3_ep_trb_ring_show, }, +}; + +static int dwc3_endpoint_open(struct inode *inode, struct file *file) +{ + const char *file_name = file_dentry(file)->d_iname; + struct dwc3_ep_file_map *f_map; + int i; + + for (i = 0; i < ARRAY_SIZE(map); i++) { + f_map = &map[i]; + + if (strcmp(f_map->name, file_name) == 0) + break; + } + + return single_open(file, f_map->show, inode->i_private); +} + +static const struct file_operations dwc3_endpoint_fops = { + .open = dwc3_endpoint_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void dwc3_debugfs_create_endpoint_file(struct dwc3_ep *dep, + struct dentry *parent, int type) +{ + struct dentry *file; + struct dwc3_ep_file_map *ep_file = &map[type]; + + file = debugfs_create_file(ep_file->name, S_IRUGO, parent, dep, + &dwc3_endpoint_fops); +} + +static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep, + struct dentry *parent) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(map); i++) + dwc3_debugfs_create_endpoint_file(dep, parent, i); +} + +static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep, + struct dentry *parent) +{ + struct dentry *dir; + + dir = debugfs_create_dir(dep->name, parent); + if (IS_ERR_OR_NULL(dir)) + return; + + dwc3_debugfs_create_endpoint_files(dep, dir); +} + +static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc, + struct dentry *parent) +{ + int i; + + for (i = 0; i < dwc->num_in_eps; i++) { + u8 epnum = (i << 1) | 1; + struct dwc3_ep *dep = dwc->eps[epnum]; + + if (!dep) + continue; + + dwc3_debugfs_create_endpoint_dir(dep, parent); + } + + for (i = 0; i < dwc->num_out_eps; i++) { + u8 epnum = (i << 1); + struct dwc3_ep *dep = dwc->eps[epnum]; + + if (!dep) + continue; + + dwc3_debugfs_create_endpoint_dir(dep, parent); + } +} + void dwc3_debugfs_init(struct dwc3 *dwc) { struct dentry *root; @@ -663,6 +963,8 @@ void dwc3_debugfs_init(struct dwc3 *dwc) root, dwc, &dwc3_link_state_fops); if (!file) dev_dbg(dwc->dev, "Can't create debugfs link_state\n"); + + dwc3_debugfs_create_endpoint_dirs(dwc, root); } } -- GitLab From 9b238748cb6e9fadab0e761f6d30ba311b4ac470 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 18 Apr 2016 09:42:10 -0700 Subject: [PATCH 3336/9938] x86/KASLR: Rename aslr.c to kaslr.c In order to avoid confusion over what this file provides, rename it to kaslr.c since it is used exclusively for the kernel ASLR, not userspace ASLR. Suggested-by: Ingo Molnar Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1460997735-24785-2-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/Makefile | 2 +- arch/x86/boot/compressed/{aslr.c => kaslr.c} | 0 arch/x86/boot/compressed/misc.h | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename arch/x86/boot/compressed/{aslr.c => kaslr.c} (100%) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 8774cb23064f..542c92f5ca4f 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -62,7 +62,7 @@ vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/piggy.o $(obj)/cpuflags.o vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o -vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/aslr.o +vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/kaslr.c similarity index 100% rename from arch/x86/boot/compressed/aslr.c rename to arch/x86/boot/compressed/kaslr.c diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 3783dc3e10b3..a8c4e087e14d 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -66,7 +66,7 @@ int cmdline_find_option_bool(const char *option); #if CONFIG_RANDOMIZE_BASE -/* aslr.c */ +/* kaslr.c */ unsigned char *choose_kernel_location(struct boot_params *boot_params, unsigned char *input, unsigned long input_size, -- GitLab From 206f25a8319b312b9983953a308b0e38e1943c1c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 18 Apr 2016 09:42:11 -0700 Subject: [PATCH 3337/9938] x86/KASLR: Remove unneeded boot_params argument Since the boot_params can be found using the real_mode global variable, there is no need to pass around a pointer to it. This slightly simplifies the choose_kernel_location function and its callers. [kees: rewrote changelog, tracked file rename] Signed-off-by: Yinghai Lu Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1460997735-24785-3-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/kaslr.c | 5 ++--- arch/x86/boot/compressed/misc.c | 2 +- arch/x86/boot/compressed/misc.h | 6 ++---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 6a9b96b4624d..622aa881c6ab 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -295,8 +295,7 @@ static unsigned long find_random_addr(unsigned long minimum, return slots_fetch_random(); } -unsigned char *choose_kernel_location(struct boot_params *boot_params, - unsigned char *input, +unsigned char *choose_kernel_location(unsigned char *input, unsigned long input_size, unsigned char *output, unsigned long output_size) @@ -316,7 +315,7 @@ unsigned char *choose_kernel_location(struct boot_params *boot_params, } #endif - boot_params->hdr.loadflags |= KASLR_FLAG; + real_mode->hdr.loadflags |= KASLR_FLAG; /* Record the various known unsafe memory ranges. */ mem_avoid_init((unsigned long)input, input_size, diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 79dac1758e7c..f35ad9eb1bf1 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -428,7 +428,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, * the entire decompressed kernel plus relocation table, or the * entire decompressed kernel plus .bss and .brk sections. */ - output = choose_kernel_location(real_mode, input_data, input_len, output, + output = choose_kernel_location(input_data, input_len, output, output_len > run_size ? output_len : run_size); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index a8c4e087e14d..22346d5a2fa0 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -67,8 +67,7 @@ int cmdline_find_option_bool(const char *option); #if CONFIG_RANDOMIZE_BASE /* kaslr.c */ -unsigned char *choose_kernel_location(struct boot_params *boot_params, - unsigned char *input, +unsigned char *choose_kernel_location(unsigned char *input, unsigned long input_size, unsigned char *output, unsigned long output_size); @@ -76,8 +75,7 @@ unsigned char *choose_kernel_location(struct boot_params *boot_params, bool has_cpuflag(int flag); #else static inline -unsigned char *choose_kernel_location(struct boot_params *boot_params, - unsigned char *input, +unsigned char *choose_kernel_location(unsigned char *input, unsigned long input_size, unsigned char *output, unsigned long output_size) -- GitLab From 6655e0aaf768c39a62eea739c453b9db1e841cfb Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 18 Apr 2016 09:42:12 -0700 Subject: [PATCH 3338/9938] x86/boot: Rename "real_mode" to "boot_params" The non-compressed boot code uses the (much more obvious) name "boot_params" for the global pointer to the x86 boot parameters. The compressed kernel loader code, though, was using the legacy name "real_mode". There is no need to have a different name, and changing it improves readability. Suggested-by: Ingo Molnar Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1460997735-24785-4-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/cmdline.c | 4 ++-- arch/x86/boot/compressed/kaslr.c | 22 +++++++++++----------- arch/x86/boot/compressed/misc.c | 27 ++++++++++++++------------- arch/x86/boot/compressed/misc.h | 2 +- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c index b68e3033e6b9..73ccf63b0f48 100644 --- a/arch/x86/boot/compressed/cmdline.c +++ b/arch/x86/boot/compressed/cmdline.c @@ -15,9 +15,9 @@ static inline char rdfs8(addr_t addr) #include "../cmdline.c" static unsigned long get_cmd_line_ptr(void) { - unsigned long cmd_line_ptr = real_mode->hdr.cmd_line_ptr; + unsigned long cmd_line_ptr = boot_params->hdr.cmd_line_ptr; - cmd_line_ptr |= (u64)real_mode->ext_cmd_line_ptr << 32; + cmd_line_ptr |= (u64)boot_params->ext_cmd_line_ptr << 32; return cmd_line_ptr; } diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 622aa881c6ab..a51ec841c9b9 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -55,7 +55,7 @@ static unsigned long get_random_boot(void) unsigned long hash = 0; hash = rotate_xor(hash, build_str, sizeof(build_str)); - hash = rotate_xor(hash, real_mode, sizeof(*real_mode)); + hash = rotate_xor(hash, boot_params, sizeof(*boot_params)); return hash; } @@ -152,16 +152,16 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, mem_avoid[0].size = unsafe_len; /* Avoid initrd. */ - initrd_start = (u64)real_mode->ext_ramdisk_image << 32; - initrd_start |= real_mode->hdr.ramdisk_image; - initrd_size = (u64)real_mode->ext_ramdisk_size << 32; - initrd_size |= real_mode->hdr.ramdisk_size; + initrd_start = (u64)boot_params->ext_ramdisk_image << 32; + initrd_start |= boot_params->hdr.ramdisk_image; + initrd_size = (u64)boot_params->ext_ramdisk_size << 32; + initrd_size |= boot_params->hdr.ramdisk_size; mem_avoid[1].start = initrd_start; mem_avoid[1].size = initrd_size; /* Avoid kernel command line. */ - cmd_line = (u64)real_mode->ext_cmd_line_ptr << 32; - cmd_line |= real_mode->hdr.cmd_line_ptr; + cmd_line = (u64)boot_params->ext_cmd_line_ptr << 32; + cmd_line |= boot_params->hdr.cmd_line_ptr; /* Calculate size of cmd_line. */ ptr = (char *)(unsigned long)cmd_line; for (cmd_line_size = 0; ptr[cmd_line_size++]; ) @@ -190,7 +190,7 @@ static bool mem_avoid_overlap(struct mem_vector *img) } /* Avoid all entries in the setup_data linked list. */ - ptr = (struct setup_data *)(unsigned long)real_mode->hdr.setup_data; + ptr = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data; while (ptr) { struct mem_vector avoid; @@ -288,8 +288,8 @@ static unsigned long find_random_addr(unsigned long minimum, minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN); /* Verify potential e820 positions, appending to slots list. */ - for (i = 0; i < real_mode->e820_entries; i++) { - process_e820_entry(&real_mode->e820_map[i], minimum, size); + for (i = 0; i < boot_params->e820_entries; i++) { + process_e820_entry(&boot_params->e820_map[i], minimum, size); } return slots_fetch_random(); @@ -315,7 +315,7 @@ unsigned char *choose_kernel_location(unsigned char *input, } #endif - real_mode->hdr.loadflags |= KASLR_FLAG; + boot_params->hdr.loadflags |= KASLR_FLAG; /* Record the various known unsafe memory ranges. */ mem_avoid_init((unsigned long)input, input_size, diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index f35ad9eb1bf1..462dfbf7467b 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -114,7 +114,7 @@ static void error(char *m); /* * This is set up by the setup-routine at boot-time */ -struct boot_params *real_mode; /* Pointer to real-mode data */ +struct boot_params *boot_params; memptr free_mem_ptr; memptr free_mem_end_ptr; @@ -184,12 +184,12 @@ void __putstr(const char *s) } } - if (real_mode->screen_info.orig_video_mode == 0 && + if (boot_params->screen_info.orig_video_mode == 0 && lines == 0 && cols == 0) return; - x = real_mode->screen_info.orig_x; - y = real_mode->screen_info.orig_y; + x = boot_params->screen_info.orig_x; + y = boot_params->screen_info.orig_y; while ((c = *s++) != '\0') { if (c == '\n') { @@ -210,8 +210,8 @@ void __putstr(const char *s) } } - real_mode->screen_info.orig_x = x; - real_mode->screen_info.orig_y = y; + boot_params->screen_info.orig_x = x; + boot_params->screen_info.orig_y = y; pos = (x + cols * y) * 2; /* Update cursor position */ outb(14, vidport); @@ -392,14 +392,15 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, { unsigned char *output_orig = output; - real_mode = rmode; + /* Retain x86 boot parameters pointer passed from startup_32/64. */ + boot_params = rmode; - /* Clear it for solely in-kernel use */ - real_mode->hdr.loadflags &= ~KASLR_FLAG; + /* Clear flags intended for solely in-kernel use. */ + boot_params->hdr.loadflags &= ~KASLR_FLAG; - sanitize_boot_params(real_mode); + sanitize_boot_params(boot_params); - if (real_mode->screen_info.orig_video_mode == 7) { + if (boot_params->screen_info.orig_video_mode == 7) { vidmem = (char *) 0xb0000; vidport = 0x3b4; } else { @@ -407,8 +408,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, vidport = 0x3d4; } - lines = real_mode->screen_info.orig_video_lines; - cols = real_mode->screen_info.orig_video_cols; + lines = boot_params->screen_info.orig_video_lines; + cols = boot_params->screen_info.orig_video_cols; console_init(); debug_putstr("early console in decompress_kernel\n"); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 22346d5a2fa0..1f750a516580 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -32,7 +32,7 @@ /* misc.c */ extern memptr free_mem_ptr; extern memptr free_mem_end_ptr; -extern struct boot_params *real_mode; /* Pointer to real-mode data */ +extern struct boot_params *boot_params; void __putstr(const char *s); void __puthex(unsigned long value); #define error_putstr(__x) __putstr(__x) -- GitLab From c04028813221c2d39a4f368586795ac4466d311c Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 18 Apr 2016 09:42:13 -0700 Subject: [PATCH 3339/9938] x86/boot: Clarify purpose of functions in misc.c The function "decompress_kernel" now performs many more duties, so this patch renames it to "extract_kernel" and updates callers and comments. Additionally the file header comment for misc.c is improved to actually describe what is contained. Suggested-by: Ingo Molnar Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1460997735-24785-5-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/head_32.S | 8 ++++---- arch/x86/boot/compressed/head_64.S | 4 ++-- arch/x86/boot/compressed/misc.c | 10 ++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index 0256064da8da..26dd9df19a69 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -233,9 +233,9 @@ relocated: 2: /* - * Do the decompression, and jump to the new kernel.. + * Do the extraction, and jump to the new kernel.. */ - /* push arguments for decompress_kernel: */ + /* push arguments for extract_kernel: */ pushl $z_run_size /* size of kernel with .bss and .brk */ pushl $z_output_len /* decompressed length, end of relocs */ leal z_extract_offset_negative(%ebx), %ebp @@ -246,11 +246,11 @@ relocated: leal boot_heap(%ebx), %eax pushl %eax /* heap area */ pushl %esi /* real mode pointer */ - call decompress_kernel /* returns kernel location in %eax */ + call extract_kernel /* returns kernel location in %eax */ addl $28, %esp /* - * Jump to the decompressed kernel. + * Jump to the extracted kernel. */ xorl %ebx, %ebx jmp *%eax diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 86558a199139..d43c30ed89ed 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -408,7 +408,7 @@ relocated: 2: /* - * Do the decompression, and jump to the new kernel.. + * Do the extraction, and jump to the new kernel.. */ pushq %rsi /* Save the real mode argument */ movq $z_run_size, %r9 /* size of kernel with .bss and .brk */ @@ -419,7 +419,7 @@ relocated: movl $z_input_len, %ecx /* input_len */ movq %rbp, %r8 /* output target address */ movq $z_output_len, %r9 /* decompressed length, end of relocs */ - call decompress_kernel /* returns kernel location in %rax */ + call extract_kernel /* returns kernel location in %rax */ popq %r9 popq %rsi diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 462dfbf7467b..0d69e809673a 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -1,8 +1,10 @@ /* * misc.c * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. + * This is a collection of several routines used to extract the kernel + * which includes KASLR relocation, decompression, ELF parsing, and + * relocation processing. Additionally included are the screen and serial + * output functions and related debugging support functions. * * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 * puts by Nick Holloway 1993, better puts by Martin Mares 1995 @@ -383,7 +385,7 @@ static void parse_elf(void *output) free(phdrs); } -asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, +asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, unsigned char *input_data, unsigned long input_len, unsigned char *output, @@ -412,7 +414,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, cols = boot_params->screen_info.orig_video_cols; console_init(); - debug_putstr("early console in decompress_kernel\n"); + debug_putstr("early console in extract_kernel\n"); free_mem_ptr = heap; /* Heap */ free_mem_end_ptr = heap + BOOT_HEAP_SIZE; -- GitLab From 7de828dfe607013546ece7ce25aa9839e8f93a66 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 18 Apr 2016 09:42:14 -0700 Subject: [PATCH 3340/9938] x86/KASLR: Clarify purpose of kaslr.c The name "choose_kernel_location" isn't specific enough, and doesn't describe the primary thing it does: choosing a random location. This patch renames it to "choose_random_location", and clarifies the what routines are contained in the kaslr.c source file. Suggested-by: Ingo Molnar Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1460997735-24785-6-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/kaslr.c | 13 ++++++++++++- arch/x86/boot/compressed/misc.c | 2 +- arch/x86/boot/compressed/misc.h | 4 ++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index a51ec841c9b9..9e03190d00ad 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -1,3 +1,14 @@ +/* + * kaslr.c + * + * This contains the routines needed to generate a reasonable level of + * entropy to choose a randomized kernel base address offset in support + * of Kernel Address Space Layout Randomization (KASLR). Additionally + * handles walking the physical memory maps (and tracking memory regions + * to avoid) in order to select a physical memory location that can + * contain the entire properly aligned running kernel image. + * + */ #include "misc.h" #include @@ -295,7 +306,7 @@ static unsigned long find_random_addr(unsigned long minimum, return slots_fetch_random(); } -unsigned char *choose_kernel_location(unsigned char *input, +unsigned char *choose_random_location(unsigned char *input, unsigned long input_size, unsigned char *output, unsigned long output_size) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 0d69e809673a..ad8c01ac2885 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -431,7 +431,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, * the entire decompressed kernel plus relocation table, or the * entire decompressed kernel plus .bss and .brk sections. */ - output = choose_kernel_location(input_data, input_len, output, + output = choose_random_location(input_data, input_len, output, output_len > run_size ? output_len : run_size); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 1f750a516580..9887e0d4aaeb 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -67,7 +67,7 @@ int cmdline_find_option_bool(const char *option); #if CONFIG_RANDOMIZE_BASE /* kaslr.c */ -unsigned char *choose_kernel_location(unsigned char *input, +unsigned char *choose_random_location(unsigned char *input, unsigned long input_size, unsigned char *output, unsigned long output_size); @@ -75,7 +75,7 @@ unsigned char *choose_kernel_location(unsigned char *input, bool has_cpuflag(int flag); #else static inline -unsigned char *choose_kernel_location(unsigned char *input, +unsigned char *choose_random_location(unsigned char *input, unsigned long input_size, unsigned char *output, unsigned long output_size) -- GitLab From 9016875df408fc5db6a94a3c5f5f5503c916cf81 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 18 Apr 2016 09:42:15 -0700 Subject: [PATCH 3341/9938] x86/KASLR: Rename "random" to "random_addr" The variable "random" is also the name of a libc function. It's better coding style to avoid overloading such things, so rename it to the more accurate "random_addr". Suggested-by: Ingo Molnar Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1460997735-24785-7-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/kaslr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 9e03190d00ad..9c29e7885ef0 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -312,7 +312,7 @@ unsigned char *choose_random_location(unsigned char *input, unsigned long output_size) { unsigned long choice = (unsigned long)output; - unsigned long random; + unsigned long random_addr; #ifdef CONFIG_HIBERNATION if (!cmdline_find_option_bool("kaslr")) { @@ -333,17 +333,17 @@ unsigned char *choose_random_location(unsigned char *input, (unsigned long)output, output_size); /* Walk e820 and find a random address. */ - random = find_random_addr(choice, output_size); - if (!random) { + random_addr = find_random_addr(choice, output_size); + if (!random_addr) { debug_putstr("KASLR could not find suitable E820 region...\n"); goto out; } /* Always enforce the minimum. */ - if (random < choice) + if (random_addr < choice) goto out; - choice = random; + choice = random_addr; out: return (unsigned char *)choice; } -- GitLab From 7a09b225f31031f8cac9e7801b6004e79f8b0da1 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Tue, 19 Apr 2016 11:21:15 +0300 Subject: [PATCH 3342/9938] x86/build/defconfig/64: Enable CONFIG_E1000E=y Very common ethernet. Already enabled in i386_defconfig Signed-off-by: Konstantin Khlebnikov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/146105407523.18740.6392078851674393377.stgit@zurg Signed-off-by: Ingo Molnar --- arch/x86/configs/x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 4f404a64681b..0c8d7963483c 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -173,6 +173,7 @@ CONFIG_TIGON3=y CONFIG_NET_TULIP=y CONFIG_E100=y CONFIG_E1000=y +CONFIG_E1000E=y CONFIG_SKY2=y CONFIG_FORCEDETH=y CONFIG_8139TOO=y -- GitLab From abfb9498ee1327f534df92a7ecaea81a85913bae Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 18 Apr 2016 16:43:43 +0300 Subject: [PATCH 3343/9938] x86/entry: Rename is_{ia32,x32}_task() to in_{ia32,x32}_syscall() The is_ia32_task()/is_x32_task() function names are a big misnomer: they suggests that the compat-ness of a system call is a task property, which is not true, the compatness of a system call purely depends on how it was invoked through the system call layer. A task may call 32-bit and 64-bit and x32 system calls without changing any of its kernel visible state. This specific minomer is also actively dangerous, as it might cause kernel developers to use the wrong kind of security checks within system calls. So rename it to in_{ia32,x32}_syscall(). Suggested-by: Andy Lutomirski Suggested-by: Ingo Molnar Signed-off-by: Dmitry Safonov [ Expanded the changelog. ] Acked-by: Andy Lutomirski Cc: 0x7f454c46@gmail.com Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: akpm@linux-foundation.org Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1460987025-30360-1-git-send-email-dsafonov@virtuozzo.com Signed-off-by: Ingo Molnar --- arch/x86/entry/common.c | 2 +- arch/x86/include/asm/compat.h | 4 ++-- arch/x86/include/asm/thread_info.h | 2 +- arch/x86/kernel/process_64.c | 2 +- arch/x86/kernel/ptrace.c | 2 +- arch/x86/kernel/signal.c | 2 +- arch/x86/kernel/uprobes.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index e79d93d44ecd..ec138e538c44 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -191,7 +191,7 @@ long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch, long syscall_trace_enter(struct pt_regs *regs) { - u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; + u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch); if (phase1_result == 0) diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index ebb102e1bbc7..5a3b2c119ed0 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -307,7 +307,7 @@ static inline void __user *arch_compat_alloc_user_space(long len) return (void __user *)round_down(sp - len, 16); } -static inline bool is_x32_task(void) +static inline bool in_x32_syscall(void) { #ifdef CONFIG_X86_X32_ABI if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT) @@ -318,7 +318,7 @@ static inline bool is_x32_task(void) static inline bool in_compat_syscall(void) { - return is_ia32_task() || is_x32_task(); + return in_ia32_syscall() || in_x32_syscall(); } #define in_compat_syscall in_compat_syscall /* override the generic impl */ diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index ffae84df8a93..30c133ac05cd 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -255,7 +255,7 @@ static inline bool test_and_clear_restore_sigmask(void) return true; } -static inline bool is_ia32_task(void) +static inline bool in_ia32_syscall(void) { #ifdef CONFIG_X86_32 return true; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 50337eac1ca2..24d1b7fb4399 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -210,7 +210,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp, */ if (clone_flags & CLONE_SETTLS) { #ifdef CONFIG_IA32_EMULATION - if (is_ia32_task()) + if (in_ia32_syscall()) err = do_set_thread_area(p, -1, (struct user_desc __user *)tls, 0); else diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 32e9d9cbb884..0f4d2a5df2dc 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -1266,7 +1266,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, compat_ulong_t caddr, compat_ulong_t cdata) { #ifdef CONFIG_X86_X32_ABI - if (!is_ia32_task()) + if (!in_ia32_syscall()) return x32_arch_ptrace(child, request, caddr, cdata); #endif #ifdef CONFIG_IA32_EMULATION diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 6408c09bbcd4..2ebcc60f0e14 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -762,7 +762,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs) { #ifdef CONFIG_X86_64 - if (is_ia32_task()) + if (in_ia32_syscall()) return __NR_ia32_restart_syscall; #endif #ifdef CONFIG_X86_X32_ABI diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index bf4db6eaec8f..98b4dc87628b 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -516,7 +516,7 @@ struct uprobe_xol_ops { static inline int sizeof_long(void) { - return is_ia32_task() ? 4 : 8; + return in_ia32_syscall() ? 4 : 8; } static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs) -- GitLab From 3a72db703cc6965662ff6063befa7d7cf2b49a2e Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Mon, 18 Apr 2016 09:49:56 +0800 Subject: [PATCH 3344/9938] arm64: mm: remove the redundant code We already re-enable interrupts where necessary in the entry code, so there is no need to do it again in do_page fault. This patch removes the redundant code. Acked-by: Catalin Marinas Signed-off-by: Huang Shijie Signed-off-by: Will Deacon --- arch/arm64/mm/fault.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index d24a5e05a3f2..5954881a35ac 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -262,10 +262,6 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, tsk = current; mm = tsk->mm; - /* Enable interrupts if they were enabled in the parent context. */ - if (interrupts_enabled(regs)) - local_irq_enable(); - /* * If we're in an interrupt or have no user context, we must not take * the fault. -- GitLab From 82611c14c4e479715c071fb0f44ddd72dc632037 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 18 Apr 2016 09:43:33 +0200 Subject: [PATCH 3345/9938] arm64: Reduce verbosity on SMP CPU stop When CPUs are stopped during an abnormal operation like panic for each CPU a line is printed and the stack trace is dumped. This information is only interesting for the aborting CPU and on systems with many CPUs it only makes it harder to debug if after the aborting CPU the log is flooded with data about all other CPUs too. Therefore remove the stack dump and printk of other CPUs and only print a single line that the other CPUs are going to be stopped and, in case any CPUs remain online list them. Signed-off-by: Jan Glauber Signed-off-by: Will Deacon --- arch/arm64/kernel/smp.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 622bd6cd86e4..fef2e7337fc7 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -805,21 +805,11 @@ void arch_irq_work_raise(void) } #endif -static DEFINE_RAW_SPINLOCK(stop_lock); - /* * ipi_cpu_stop - handle IPI from smp_send_stop() */ static void ipi_cpu_stop(unsigned int cpu) { - if (system_state == SYSTEM_BOOTING || - system_state == SYSTEM_RUNNING) { - raw_spin_lock(&stop_lock); - pr_crit("CPU%u: stopping\n", cpu); - dump_stack(); - raw_spin_unlock(&stop_lock); - } - set_cpu_online(cpu, false); local_irq_disable(); @@ -914,6 +904,9 @@ void smp_send_stop(void) cpumask_copy(&mask, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), &mask); + if (system_state == SYSTEM_BOOTING || + system_state == SYSTEM_RUNNING) + pr_crit("SMP: stopping secondary CPUs\n"); smp_cross_call(&mask, IPI_CPU_STOP); } @@ -923,7 +916,8 @@ void smp_send_stop(void) udelay(1); if (num_online_cpus() > 1) - pr_warning("SMP: failed to stop secondary CPUs\n"); + pr_warning("SMP: failed to stop secondary CPUs %*pbl\n", + cpumask_pr_args(cpu_online_mask)); } /* -- GitLab From f454bfddf6ba557381d8bf5df50eff778602ff23 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Thu, 14 Apr 2016 14:59:49 +0300 Subject: [PATCH 3346/9938] perf/core, sched: Don't use clock function pointer to determine clock Now that local_clock() is explicitly inlined in sched.h, taking its pointer would uninline it in the compilation unit where it's done, making (among other things) comparing pointers to this function produce different results in different compilation units. Case in point, x86 perf core's user page updating function compares event's clock against &local_clock to see if it needs to set zero time offset related bits in the page. This patch fixes the latter by looking at the "use_clockid" event attribute instead, to determine whether local clock is used. Fixing the uninlined local_clock() in perf core is left as an exercise for the author of the prior work. Signed-off-by: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Borislav Petkov Cc: Daniel Lezcano Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: eranian@google.com Cc: vince@deater.net Fixes: http://lkml.kernel.org/r/1459541050-13654-1-git-send-email-daniel.lezcano@linaro.org Link: http://lkml.kernel.org/r/1460635189-2320-1-git-send-email-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 041e442a3e28..dd39fde66b54 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2177,7 +2177,7 @@ void arch_perf_update_userpage(struct perf_event *event, * cap_user_time_zero doesn't make sense when we're using a different * time base for the records. */ - if (event->clock == &local_clock) { + if (!event->attr.use_clockid) { userpg->cap_user_time_zero = 1; userpg->time_zero = data->cyc2ns_offset; } -- GitLab From ee4c879b53eb5d757661b9bc8fcdf1a3d2e5fdfb Mon Sep 17 00:00:00 2001 From: Moise Gergaud Date: Tue, 19 Apr 2016 11:24:45 +0200 Subject: [PATCH 3347/9938] ASoC: sti-asoc-card: update tdm mode - Add "TDM" in the st,mode property list - st,mode property is also mandatory for reader - add tdm playback dai-link example Signed-off-by: Moise Gergaud Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown --- .../bindings/sound/st,sti-asoc-card.txt | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt index f546dd914812..4d9a83d9a017 100644 --- a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt @@ -37,17 +37,18 @@ Required properties: - dai-name: DAI name that describes the IP. + - IP mode: IP working mode depending on associated codec. + "HDMI" connected to HDMI codec and support IEC HDMI formats (player only). + "SPDIF" connected to SPDIF codec and support SPDIF formats (player only). + "PCM" PCM standard mode for I2S or TDM bus. + "TDM" TDM mode for TDM bus. + Required properties ("st,sti-uni-player" compatibility only): - clocks: CPU_DAI IP clock source, listed in the same order than the CPU_DAI properties. - uniperiph-id: internal SOC IP instance ID. - - IP mode: IP working mode depending on associated codec. - "HDMI" connected to HDMI codec IP and IEC HDMI formats. - "SPDIF"connected to SPDIF codec and support SPDIF formats. - "PCM" PCM standard mode for I2S or TDM bus. - Optional properties: - pinctrl-0: defined for CPU_DAI@1 and CPU_DAI@4 to describe I2S PIOs for external codecs connection. @@ -56,6 +57,22 @@ Optional properties: Example: + sti_uni_player1: sti-uni-player@1 { + compatible = "st,sti-uni-player"; + status = "okay"; + #sound-dai-cells = <0>; + st,syscfg = <&syscfg_core>; + clocks = <&clk_s_d0_flexgen CLK_PCM_1>; + reg = <0x8D81000 0x158>; + interrupts = ; + dmas = <&fdma0 3 0 1>; + st,dai-name = "Uni Player #1 (I2S)"; + dma-names = "tx"; + st,uniperiph-id = <1>; + st,version = <5>; + st,mode = "TDM"; + }; + sti_uni_player2: sti-uni-player@2 { compatible = "st,sti-uni-player"; status = "okay"; @@ -99,6 +116,7 @@ Example: dma-names = "rx"; dai-name = "Uni Reader #1 (HDMI RX)"; version = <3>; + st,mode = "PCM"; }; 2) sti-sas-codec: internal audio codec IPs driver @@ -152,4 +170,20 @@ Example of audio card declaration: sound-dai = <&sti_sasg_codec 0>; }; }; + simple-audio-card,dai-link@2 { + /* TDM playback */ + format = "left_j"; + frame-inversion = <1>; + cpu { + sound-dai = <&sti_uni_player1>; + dai-tdm-slot-num = <16>; + dai-tdm-slot-width = <16>; + dai-tdm-slot-tx-mask = + <1 1 1 1 0 0 0 0 0 0 1 1 0 0 1 1>; + }; + + codec { + sound-dai = <&sti_sasg_codec 3>; + }; + }; }; -- GitLab From ec513886411e4fc47f98607a1bc79b72899710c4 Mon Sep 17 00:00:00 2001 From: Jeremy McDermond Date: Mon, 18 Apr 2016 17:24:04 -0700 Subject: [PATCH 3348/9938] ASoC: tlv320aic32x4: Change name of probe function The codec's probe function is named aic32x4_probe. This is going to conflict with later work to implement SPI support and separate out I2S into its own file. In line with other drivers in the tree, this function is renamed to aic32x4_codec_probe instead. Signed-off-by: Jeremy McDermond Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index f2d3191961e1..9d5b08b80d24 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -596,7 +596,7 @@ static struct snd_soc_dai_driver aic32x4_dai = { .symmetric_rates = 1, }; -static int aic32x4_probe(struct snd_soc_codec *codec) +static int aic32x4_codec_probe(struct snd_soc_codec *codec) { struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); u32 tmp_reg; @@ -655,7 +655,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { - .probe = aic32x4_probe, + .probe = aic32x4_codec_probe, .set_bias_level = aic32x4_set_bias_level, .suspend_bias_off = true, -- GitLab From 3bcfd222f6f0c8758f369ce0db23fa3287db59a6 Mon Sep 17 00:00:00 2001 From: Jeremy McDermond Date: Mon, 18 Apr 2016 17:24:05 -0700 Subject: [PATCH 3349/9938] ASoC: tlv320aic32x4: Break out I2C support into separate module To prepare for abstracting adding SPI support, the I2C pieces needs to be in its own moudle. This patch moves common probe code into aic32x4_probe and common removal code into aic32x4_remove. It also creates a static regmap config structure to be copied in the I2C specific driver. Signed-off-by: Jeremy McDermond Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 ++- sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tlv320aic32x4-i2c.c | 74 +++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic32x4.c | 76 +++++++++------------------- sound/soc/codecs/tlv320aic32x4.h | 7 +++ 5 files changed, 113 insertions(+), 53 deletions(-) create mode 100644 sound/soc/codecs/tlv320aic32x4-i2c.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 649e92a252ae..38d07c3f5a38 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -129,7 +129,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TLV320AIC23_SPI if SPI_MASTER select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4 if I2C + select SND_SOC_TLV320AIC32X4_I2C if I2C select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TPA6130A2 if I2C select SND_SOC_TLV320DAC33 if I2C @@ -769,6 +769,11 @@ config SND_SOC_TLV320AIC31XX config SND_SOC_TLV320AIC32X4 tristate +config SND_SOC_TLV320AIC32X4_I2C + tristate + depends on I2C + select SND_SOC_TLV320AIC32X4 + config SND_SOC_TLV320AIC3X tristate "Texas Instruments TLV320AIC3x CODECs" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 185a712a7fe7..7ce294ce3afd 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -136,6 +136,7 @@ snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o +snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-ts3a227e-objs := ts3a227e.o @@ -342,6 +343,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o +obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o diff --git a/sound/soc/codecs/tlv320aic32x4-i2c.c b/sound/soc/codecs/tlv320aic32x4-i2c.c new file mode 100644 index 000000000000..59606cf3008f --- /dev/null +++ b/sound/soc/codecs/tlv320aic32x4-i2c.c @@ -0,0 +1,74 @@ +/* + * linux/sound/soc/codecs/tlv320aic32x4-i2c.c + * + * Copyright 2011 NW Digital Radio + * + * Author: Jeremy McDermond + * + * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "tlv320aic32x4.h" + +static int aic32x4_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + struct regmap_config config; + + config = aic32x4_regmap_config; + config.reg_bits = 8; + config.val_bits = 8; + + regmap = devm_regmap_init_i2c(i2c, &config); + return aic32x4_probe(&i2c->dev, regmap); +} + +static int aic32x4_i2c_remove(struct i2c_client *i2c) +{ + return aic32x4_remove(&i2c->dev); +} + +static const struct i2c_device_id aic32x4_i2c_id[] = { + { "tlv320aic32x4", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); + +static const struct of_device_id aic32x4_of_id[] = { + { .compatible = "ti,tlv320aic32x4", }, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, aic32x4_of_id); + +static struct i2c_driver aic32x4_i2c_driver = { + .driver = { + .name = "tlv320aic32x4", + .of_match_table = aic32x4_of_id, + }, + .probe = aic32x4_i2c_probe, + .remove = aic32x4_i2c_remove, + .id_table = aic32x4_i2c_id, +}; + +module_i2c_driver(aic32x4_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C"); +MODULE_AUTHOR("Jeremy McDermond "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 9d5b08b80d24..c6b6d551f4fe 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -287,14 +286,12 @@ static const struct regmap_range_cfg aic32x4_regmap_pages[] = { }, }; -static const struct regmap_config aic32x4_regmap = { - .reg_bits = 8, - .val_bits = 8, - +const struct regmap_config aic32x4_regmap_config = { .max_register = AIC32X4_RMICPGAVOL, .ranges = aic32x4_regmap_pages, .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages), }; +EXPORT_SYMBOL(aic32x4_regmap_config); static inline int aic32x4_get_divs(int mclk, int rate) { @@ -777,24 +774,22 @@ static int aic32x4_setup_regulators(struct device *dev, return ret; } -static int aic32x4_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +int aic32x4_probe(struct device *dev, struct regmap *regmap) { - struct aic32x4_pdata *pdata = i2c->dev.platform_data; struct aic32x4_priv *aic32x4; - struct device_node *np = i2c->dev.of_node; + struct aic32x4_pdata *pdata = dev->platform_data; + struct device_node *np = dev->of_node; int ret; - aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv), GFP_KERNEL); if (aic32x4 == NULL) return -ENOMEM; - aic32x4->regmap = devm_regmap_init_i2c(i2c, &aic32x4_regmap); - if (IS_ERR(aic32x4->regmap)) - return PTR_ERR(aic32x4->regmap); - - i2c_set_clientdata(i2c, aic32x4); + dev_set_drvdata(dev, aic32x4); if (pdata) { aic32x4->power_cfg = pdata->power_cfg; @@ -804,7 +799,7 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, } else if (np) { ret = aic32x4_parse_dt(aic32x4, np); if (ret) { - dev_err(&i2c->dev, "Failed to parse DT node\n"); + dev_err(dev, "Failed to parse DT node\n"); return ret; } } else { @@ -814,71 +809,48 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } - aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); + aic32x4->mclk = devm_clk_get(dev, "mclk"); if (IS_ERR(aic32x4->mclk)) { - dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); + dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); return PTR_ERR(aic32x4->mclk); } if (gpio_is_valid(aic32x4->rstn_gpio)) { - ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, + ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); if (ret != 0) return ret; } - ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); + ret = aic32x4_setup_regulators(dev, aic32x4); if (ret) { - dev_err(&i2c->dev, "Failed to setup regulators\n"); + dev_err(dev, "Failed to setup regulators\n"); return ret; } - ret = snd_soc_register_codec(&i2c->dev, + ret = snd_soc_register_codec(dev, &soc_codec_dev_aic32x4, &aic32x4_dai, 1); if (ret) { - dev_err(&i2c->dev, "Failed to register codec\n"); + dev_err(dev, "Failed to register codec\n"); aic32x4_disable_regulators(aic32x4); return ret; } - i2c_set_clientdata(i2c, aic32x4); - return 0; } +EXPORT_SYMBOL(aic32x4_probe); -static int aic32x4_i2c_remove(struct i2c_client *client) +int aic32x4_remove(struct device *dev) { - struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); + struct aic32x4_priv *aic32x4 = dev_get_drvdata(dev); aic32x4_disable_regulators(aic32x4); - snd_soc_unregister_codec(&client->dev); + snd_soc_unregister_codec(dev); + return 0; } - -static const struct i2c_device_id aic32x4_i2c_id[] = { - { "tlv320aic32x4", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); - -static const struct of_device_id aic32x4_of_id[] = { - { .compatible = "ti,tlv320aic32x4", }, - { /* senitel */ } -}; -MODULE_DEVICE_TABLE(of, aic32x4_of_id); - -static struct i2c_driver aic32x4_i2c_driver = { - .driver = { - .name = "tlv320aic32x4", - .of_match_table = aic32x4_of_id, - }, - .probe = aic32x4_i2c_probe, - .remove = aic32x4_i2c_remove, - .id_table = aic32x4_i2c_id, -}; - -module_i2c_driver(aic32x4_i2c_driver); +EXPORT_SYMBOL(aic32x4_remove); MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); MODULE_AUTHOR("Javier Martin "); diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h index 995f033a855d..a197dd51addc 100644 --- a/sound/soc/codecs/tlv320aic32x4.h +++ b/sound/soc/codecs/tlv320aic32x4.h @@ -10,6 +10,13 @@ #ifndef _TLV320AIC32X4_H #define _TLV320AIC32X4_H +struct device; +struct regmap_config; + +extern const struct regmap_config aic32x4_regmap_config; +int aic32x4_probe(struct device *dev, struct regmap *regmap); +int aic32x4_remove(struct device *dev); + /* tlv320aic32x4 register space (in decimal to match datasheet) */ #define AIC32X4_PAGE1 128 -- GitLab From 125bc681bc5d8183594e30492f0345a61ab3cc94 Mon Sep 17 00:00:00 2001 From: Jeremy McDermond Date: Mon, 18 Apr 2016 17:24:06 -0700 Subject: [PATCH 3350/9938] ASoC: tlv320aic32x4: Add SPI support Add support for running the tlv32x4 control channel over SPI rather than I2C. Signed-off-by: Jeremy McDermond Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 +++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tlv320aic32x4-spi.c | 76 ++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 sound/soc/codecs/tlv320aic32x4-spi.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 38d07c3f5a38..3cc56e7d6e78 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -130,6 +130,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC31XX if I2C select SND_SOC_TLV320AIC32X4_I2C if I2C + select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TPA6130A2 if I2C select SND_SOC_TLV320DAC33 if I2C @@ -774,6 +775,11 @@ config SND_SOC_TLV320AIC32X4_I2C depends on I2C select SND_SOC_TLV320AIC32X4 +config SND_SOC_TLV320AIC32X4_SPI + tristate + depends on SPI_MASTER + select SND_SOC_TLV320AIC32X4 + config SND_SOC_TLV320AIC3X tristate "Texas Instruments TLV320AIC3x CODECs" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 7ce294ce3afd..6b59bdb20aa1 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -137,6 +137,7 @@ snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o +snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-ts3a227e-objs := ts3a227e.o @@ -344,6 +345,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o +obj-$(CONFIG_SND_SOC_TLV320AIC32X4_SPI) += snd-soc-tlv320aic32x4-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o diff --git a/sound/soc/codecs/tlv320aic32x4-spi.c b/sound/soc/codecs/tlv320aic32x4-spi.c new file mode 100644 index 000000000000..724fcdd491b2 --- /dev/null +++ b/sound/soc/codecs/tlv320aic32x4-spi.c @@ -0,0 +1,76 @@ +/* + * linux/sound/soc/codecs/tlv320aic32x4-spi.c + * + * Copyright 2011 NW Digital Radio + * + * Author: Jeremy McDermond + * + * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "tlv320aic32x4.h" + +static int aic32x4_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + struct regmap_config config; + + config = aic32x4_regmap_config; + config.reg_bits = 7; + config.pad_bits = 1; + config.val_bits = 8; + config.read_flag_mask = 0x01; + + regmap = devm_regmap_init_spi(spi, &config); + return aic32x4_probe(&spi->dev, regmap); +} + +static int aic32x4_spi_remove(struct spi_device *spi) +{ + return aic32x4_remove(&spi->dev); +} + +static const struct spi_device_id aic32x4_spi_id[] = { + { "tlv320aic32x4", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, aic32x4_spi_id); + +static const struct of_device_id aic32x4_of_id[] = { + { .compatible = "ti,tlv320aic32x4", }, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, aic32x4_of_id); + +static struct spi_driver aic32x4_spi_driver = { + .driver = { + .name = "tlv320aic32x4", + .owner = THIS_MODULE, + .of_match_table = aic32x4_of_id, + }, + .probe = aic32x4_spi_probe, + .remove = aic32x4_spi_remove, + .id_table = aic32x4_spi_id, +}; + +module_spi_driver(aic32x4_spi_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI"); +MODULE_AUTHOR("Jeremy McDermond "); +MODULE_LICENSE("GPL"); -- GitLab From 096559107bedf337c407be038a1d7926e85d8842 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Mar 2016 17:38:29 +0100 Subject: [PATCH 3351/9938] ARM: sun5i: dt: Add pll3 and pll7 clocks Enable the pll3 and pll7 clocks in the DT that are used to drive the display-related clocks. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 59a9426e3bd4..0840612b5ed6 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -88,6 +88,15 @@ clock-output-names = "osc24M"; }; + osc3M: osc3M_clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + clocks = <&osc24M>; + clock-output-names = "osc3M"; + }; + osc32k: clk@0 { #clock-cells = <0>; compatible = "fixed-clock"; @@ -112,6 +121,23 @@ "pll2-4x", "pll2-8x"; }; + pll3: clk@01c20010 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll3-clk"; + reg = <0x01c20010 0x4>; + clocks = <&osc3M>; + clock-output-names = "pll3"; + }; + + pll3x2: pll3x2_clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <1>; + clock-mult = <2>; + clocks = <&pll3>; + clock-output-names = "pll3-2x"; + }; + pll4: clk@01c20018 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-pll1-clk"; @@ -136,6 +162,23 @@ clock-output-names = "pll6_sata", "pll6_other", "pll6"; }; + pll7: clk@01c20030 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll3-clk"; + reg = <0x01c20030 0x4>; + clocks = <&osc3M>; + clock-output-names = "pll7"; + }; + + pll7x2: pll7x2_clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <1>; + clock-mult = <2>; + clocks = <&pll7>; + clock-output-names = "pll7-2x"; + }; + /* dummy is 200M */ cpu: cpu@01c20054 { #clock-cells = <0>; -- GitLab From 15bd920f9670f7fe13cec9148e5c05d160c2f30c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Mar 2016 17:38:32 +0100 Subject: [PATCH 3352/9938] ARM: sun5i: Add TV encoder gate to the DTSI It turns out that the A13 / R8 also have a tve encoder block, and a gate for it. Add it to the DT. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index d910d3a6c41c..7bbeec9fae92 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -110,8 +110,8 @@ <10>, <13>, <14>, <20>, <21>, <22>, - <28>, <32>, <36>, - <40>, <44>, + <28>, <32>, <34>, + <36>, <40>, <44>, <46>, <51>, <52>; clock-output-names = "ahb_usbotg", "ahb_ehci", @@ -120,8 +120,8 @@ "ahb_mmc2", "ahb_nand", "ahb_sdram", "ahb_spi0", "ahb_spi1", "ahb_spi2", - "ahb_stimer", "ahb_ve", "ahb_lcd", - "ahb_csi", "ahb_de_be", + "ahb_stimer", "ahb_ve", "ahb_tve", + "ahb_lcd", "ahb_csi", "ahb_de_be", "ahb_de_fe", "ahb_iep", "ahb_mali400"; }; -- GitLab From 541ac1554e1269c4462a2166992d87b752abda64 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Mar 2016 17:38:31 +0100 Subject: [PATCH 3353/9938] ARM: sun5i: Add DRAM gates The DRAM gates control whether the image / display devices on the SoC have access to the DRAM clock or not. Enable it. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13.dtsi | 23 ++++++++++++++++++++++- arch/arm/boot/dts/sun5i-r8.dtsi | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index 7bbeec9fae92..39f23b1ebc8f 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -61,7 +61,8 @@ compatible = "allwinner,simple-framebuffer", "simple-framebuffer"; allwinner,pipeline = "de_be0-lcd0"; - clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>; + clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>, + <&dram_gates 26>; status = "disabled"; }; }; @@ -149,6 +150,26 @@ "apb1_i2c2", "apb1_uart1", "apb1_uart3"; }; + + dram_gates: clk@01c20100 { + #clock-cells = <1>; + compatible = "allwinner,sun5i-a13-dram-gates-clk", + "allwinner,sun4i-a10-gates-clk"; + reg = <0x01c20100 0x4>; + clocks = <&pll5 0>; + clock-indices = <0>, + <1>, + <25>, + <26>, + <29>, + <31>; + clock-output-names = "dram_ve", + "dram_csi", + "dram_de_fe", + "dram_de_be", + "dram_ace", + "dram_iep"; + }; }; soc@01c00000 { diff --git a/arch/arm/boot/dts/sun5i-r8.dtsi b/arch/arm/boot/dts/sun5i-r8.dtsi index 0ef865601ac9..e346ba76db5d 100644 --- a/arch/arm/boot/dts/sun5i-r8.dtsi +++ b/arch/arm/boot/dts/sun5i-r8.dtsi @@ -52,7 +52,7 @@ "simple-framebuffer"; allwinner,pipeline = "de_be0-lcd0-tve0"; clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>, - <&ahb_gates 44>; + <&ahb_gates 44>, <&dram_gates 26>; status = "disabled"; }; }; -- GitLab From d23f0517357ef48d2845846e899d125b3c1a492e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 19 Apr 2016 15:28:39 +0200 Subject: [PATCH 3354/9938] ALSA: ens1371: Fix "Line In->Rear Out Switch" control The "Line In->Rear Out Switch" control on ens1371 driver returns a bogus value, always true, as its check is totally broken. Fix it to check the proper GPIO bit mask. Reported-by: David Binderman Signed-off-by: Takashi Iwai --- sound/pci/ens1370.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 0dc44ebb0032..626cd2167d29 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -1548,7 +1548,7 @@ static int snd_es1373_line_get(struct snd_kcontrol *kcontrol, int val = 0; spin_lock_irq(&ensoniq->reg_lock); - if ((ensoniq->ctrl & ES_1371_GPIO_OUTM) >= 4) + if (ensoniq->ctrl & ES_1371_GPIO_OUT(4)) val = 1; ucontrol->value.integer.value[0] = val; spin_unlock_irq(&ensoniq->reg_lock); -- GitLab From 7a18afe8097731b8ffb6cb5b2b3b418ded77c105 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Mon, 18 Apr 2016 15:47:53 -0400 Subject: [PATCH 3355/9938] hwmon: (ads7828) Enable internal reference On ads7828 the internal reference defaults to off upon power up. When using internal reference, it needs to be turned on and the voltage needs to settle before normal conversion cycle can be started. Hence perform a dummy read in the probe to enable the internal reference allowing the voltage to settle before performing a normal read. Without this fix, the first read from the ADC when using internal reference always returns incorrect data. Signed-off-by: Akshay Bhat Cc: stable@vger.kernel.org # v4.1+ Signed-off-by: Guenter Roeck --- drivers/hwmon/ads7828.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index 6c99ee7bafa3..ee396ff167d9 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -120,6 +120,7 @@ static int ads7828_probe(struct i2c_client *client, unsigned int vref_mv = ADS7828_INT_VREF_MV; bool diff_input = false; bool ext_vref = false; + unsigned int regval; data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL); if (!data) @@ -154,6 +155,15 @@ static int ads7828_probe(struct i2c_client *client, if (!diff_input) data->cmd_byte |= ADS7828_CMD_SD_SE; + /* + * Datasheet specifies internal reference voltage is disabled by + * default. The internal reference voltage needs to be enabled and + * voltage needs to settle before getting valid ADC data. So perform a + * dummy read to enable the internal reference voltage. + */ + if (!ext_vref) + regmap_read(data->regmap, data->cmd_byte, ®val); + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, ads7828_groups); -- GitLab From 04e1e70afec6bb2940aea0ac2e9cbaf7d643d5f4 Mon Sep 17 00:00:00 2001 From: Tiberiu Breana Date: Wed, 30 Mar 2016 19:16:24 +0300 Subject: [PATCH 3356/9938] hwmon: (max31722) Add support for MAX31722/MAX31723 temperature sensors Add basic support for the Maxim Integrated MAX31722/MAX31723 SPI temperature sensors / thermostats. Includes: - ACPI support; - raw temperature readings; - power management Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX31722-MAX31723.pdf Signed-off-by: Tiberiu Breana Signed-off-by: Guenter Roeck --- Documentation/hwmon/max31722 | 34 ++++++++ drivers/hwmon/Kconfig | 10 +++ drivers/hwmon/Makefile | 1 + drivers/hwmon/max31722.c | 165 +++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 Documentation/hwmon/max31722 create mode 100644 drivers/hwmon/max31722.c diff --git a/Documentation/hwmon/max31722 b/Documentation/hwmon/max31722 new file mode 100644 index 000000000000..090da84538c8 --- /dev/null +++ b/Documentation/hwmon/max31722 @@ -0,0 +1,34 @@ +Kernel driver max31722 +====================== + +Supported chips: + * Maxim Integrated MAX31722 + Prefix: 'max31722' + ACPI ID: MAX31722 + Addresses scanned: - + Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX31722-MAX31723.pdf + * Maxim Integrated MAX31723 + Prefix: 'max31723' + ACPI ID: MAX31723 + Addresses scanned: - + Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX31722-MAX31723.pdf + +Author: Tiberiu Breana + +Description +----------- + +This driver adds support for the Maxim Integrated MAX31722/MAX31723 thermometers +and thermostats running over an SPI interface. + +Usage Notes +----------- + +This driver uses ACPI to auto-detect devices. See ACPI IDs in the above section. + +Sysfs entries +------------- + +The following attribute is supported: + +temp1_input Measured temperature. Read-only. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5c2d13a687aa..bdfa39408996 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -821,6 +821,16 @@ config SENSORS_MAX197 This driver can also be built as a module. If so, the module will be called max197. +config SENSORS_MAX31722 +tristate "MAX31722 temperature sensor" + depends on SPI + help + Support for the Maxim Integrated MAX31722/MAX31723 digital + thermometers/thermostats operating over an SPI interface. + + This driver can also be built as a module. If so, the module + will be called max31722. + config SENSORS_MAX6639 tristate "Maxim MAX6639 sensor chip" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 58cc3acba7e7..2ef5b7c4c54f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -112,6 +112,7 @@ obj-$(CONFIG_SENSORS_MAX16065) += max16065.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_MAX1668) += max1668.o obj-$(CONFIG_SENSORS_MAX197) += max197.o +obj-$(CONFIG_SENSORS_MAX31722) += max31722.o obj-$(CONFIG_SENSORS_MAX6639) += max6639.o obj-$(CONFIG_SENSORS_MAX6642) += max6642.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c new file mode 100644 index 000000000000..30a100e70a0d --- /dev/null +++ b/drivers/hwmon/max31722.c @@ -0,0 +1,165 @@ +/* + * max31722 - hwmon driver for Maxim Integrated MAX31722/MAX31723 SPI + * digital thermometer and thermostats. + * + * Copyright (c) 2016, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ + +#include +#include +#include +#include +#include +#include + +#define MAX31722_REG_CFG 0x00 +#define MAX31722_REG_TEMP_LSB 0x01 + +#define MAX31722_MODE_CONTINUOUS 0x00 +#define MAX31722_MODE_STANDBY 0x01 +#define MAX31722_MODE_MASK 0xFE +#define MAX31722_RESOLUTION_12BIT 0x06 +#define MAX31722_WRITE_MASK 0x80 + +struct max31722_data { + struct device *hwmon_dev; + struct spi_device *spi_device; + u8 mode; +}; + +static int max31722_set_mode(struct max31722_data *data, u8 mode) +{ + int ret; + struct spi_device *spi = data->spi_device; + u8 buf[2] = { + MAX31722_REG_CFG | MAX31722_WRITE_MASK, + (data->mode & MAX31722_MODE_MASK) | mode + }; + + ret = spi_write(spi, &buf, sizeof(buf)); + if (ret < 0) { + dev_err(&spi->dev, "failed to set sensor mode.\n"); + return ret; + } + data->mode = (data->mode & MAX31722_MODE_MASK) | mode; + + return 0; +} + +static ssize_t max31722_show_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t ret; + struct max31722_data *data = dev_get_drvdata(dev); + + ret = spi_w8r16(data->spi_device, MAX31722_REG_TEMP_LSB); + if (ret < 0) + return ret; + /* Keep 12 bits and multiply by the scale of 62.5 millidegrees/bit. */ + return sprintf(buf, "%d\n", (s16)le16_to_cpu(ret) * 125 / 32); +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, + max31722_show_temp, NULL, 0); + +static struct attribute *max31722_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(max31722); + +static int max31722_probe(struct spi_device *spi) +{ + int ret; + struct max31722_data *data; + + data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spi_set_drvdata(spi, data); + data->spi_device = spi; + /* + * Set SD bit to 0 so we can have continuous measurements. + * Set resolution to 12 bits for maximum precision. + */ + data->mode = MAX31722_MODE_CONTINUOUS | MAX31722_RESOLUTION_12BIT; + ret = max31722_set_mode(data, MAX31722_MODE_CONTINUOUS); + if (ret < 0) + return ret; + + data->hwmon_dev = hwmon_device_register_with_groups(&spi->dev, + spi->modalias, + data, + max31722_groups); + if (IS_ERR(data->hwmon_dev)) { + max31722_set_mode(data, MAX31722_MODE_STANDBY); + return PTR_ERR(data->hwmon_dev); + } + + return 0; +} + +static int max31722_remove(struct spi_device *spi) +{ + struct max31722_data *data = spi_get_drvdata(spi); + + hwmon_device_unregister(data->hwmon_dev); + + return max31722_set_mode(data, MAX31722_MODE_STANDBY); +} + +static int __maybe_unused max31722_suspend(struct device *dev) +{ + struct spi_device *spi_device = to_spi_device(dev); + struct max31722_data *data = spi_get_drvdata(spi_device); + + return max31722_set_mode(data, MAX31722_MODE_STANDBY); +} + +static int __maybe_unused max31722_resume(struct device *dev) +{ + struct spi_device *spi_device = to_spi_device(dev); + struct max31722_data *data = spi_get_drvdata(spi_device); + + return max31722_set_mode(data, MAX31722_MODE_CONTINUOUS); +} + +static SIMPLE_DEV_PM_OPS(max31722_pm_ops, max31722_suspend, max31722_resume); + +static const struct spi_device_id max31722_spi_id[] = { + {"max31722", 0}, + {"max31723", 0}, + {} +}; + +static const struct acpi_device_id __maybe_unused max31722_acpi_id[] = { + {"MAX31722", 0}, + {"MAX31723", 0}, + {} +}; + +MODULE_DEVICE_TABLE(spi, max31722_spi_id); + +static struct spi_driver max31722_driver = { + .driver = { + .name = "max31722", + .pm = &max31722_pm_ops, + .acpi_match_table = ACPI_PTR(max31722_acpi_id), + }, + .probe = max31722_probe, + .remove = max31722_remove, + .id_table = max31722_spi_id, +}; + +module_spi_driver(max31722_driver); + +MODULE_AUTHOR("Tiberiu Breana "); +MODULE_DESCRIPTION("max31722 sensor driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 3ba4e3841530b1565f761778bd0e14e242a4ab9a Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 6 Apr 2016 15:44:10 +0800 Subject: [PATCH 3357/9938] hwmon: (fam15h_power) Add CPU_SUP_AMD as the dependence This patch adds CONFIG_CPU_SUP_AMD as the dependence of fam15h_power driver. Because the following patch will use the interface from x86/kernel/cpu/amd.c. Otherwise, the below error might be encountered: All errors (new ones prefixed by >>): drivers/built-in.o: In function `fam15h_power_probe': >> fam15h_power.c:(.text+0x26e3a3): undefined reference to >> `amd_get_cores_per_cu' fam15h_power.c:(.text+0x26e41e): undefined reference to `amd_get_cores_per_cu' Reported-by: build test robot Acked-by: Borislav Petkov Signed-off-by: Huang Rui Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index bdfa39408996..1b5b500ede07 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -288,7 +288,7 @@ config SENSORS_K10TEMP config SENSORS_FAM15H_POWER tristate "AMD Family 15h processor power" - depends on X86 && PCI + depends on X86 && PCI && CPU_SUP_AMD help If you say yes here you get support for processor power information of your AMD family 15h CPU. -- GitLab From fa7943449943124e40cabcd453b08c3f8221c454 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 6 Apr 2016 15:44:11 +0800 Subject: [PATCH 3358/9938] hwmon: (fam15h_power) Add compute unit accumulated power This patch adds a member in fam15h_power_data which specifies the compute unit accumulated power. It adds do_read_registers_on_cu to do all the read to all MSRs and run it on one of the online cores on each compute unit with smp_call_function_many(). This behavior can decrease IPI numbers. Suggested-by: Borislav Petkov Signed-off-by: Huang Rui Signed-off-by: Guenter Roeck --- drivers/hwmon/fam15h_power.c | 72 +++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 4f695d8fcafa..4edbaf083130 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -44,7 +46,9 @@ MODULE_LICENSE("GPL"); #define FAM15H_MIN_NUM_ATTRS 2 #define FAM15H_NUM_GROUPS 2 +#define MAX_CUS 8 +#define MSR_F15H_CU_PWR_ACCUMULATOR 0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR 0xc001007b #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4 @@ -59,6 +63,8 @@ struct fam15h_power_data { struct attribute_group group; /* maximum accumulated power of a compute unit */ u64 max_cu_acc_power; + /* accumulated power of the compute units */ + u64 cu_acc_power[MAX_CUS]; }; static ssize_t show_power(struct device *dev, @@ -125,6 +131,70 @@ static ssize_t show_power_crit(struct device *dev, } static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); +static void do_read_registers_on_cu(void *_data) +{ + struct fam15h_power_data *data = _data; + int cpu, cu; + + cpu = smp_processor_id(); + + /* + * With the new x86 topology modelling, cpu core id actually + * is compute unit id. + */ + cu = cpu_data(cpu).cpu_core_id; + + rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, &data->cu_acc_power[cu]); +} + +/* + * This function is only able to be called when CPUID + * Fn8000_0007:EDX[12] is set. + */ +static int read_registers(struct fam15h_power_data *data) +{ + int this_cpu, ret, cpu; + int core, this_core; + cpumask_var_t mask; + + ret = zalloc_cpumask_var(&mask, GFP_KERNEL); + if (!ret) + return -ENOMEM; + + get_online_cpus(); + this_cpu = smp_processor_id(); + + /* + * Choose the first online core of each compute unit, and then + * read their MSR value of power and ptsc in a single IPI, + * because the MSR value of CPU core represent the compute + * unit's. + */ + core = -1; + + for_each_online_cpu(cpu) { + this_core = topology_core_id(cpu); + + if (this_core == core) + continue; + + core = this_core; + + /* get any CPU on this compute unit */ + cpumask_set_cpu(cpumask_any(topology_sibling_cpumask(cpu)), mask); + } + + if (cpumask_test_cpu(this_cpu, mask)) + do_read_registers_on_cu(data); + + smp_call_function_many(mask, do_read_registers_on_cu, data, true); + put_online_cpus(); + + free_cpumask_var(mask); + + return 0; +} + static int fam15h_power_init_attrs(struct pci_dev *pdev, struct fam15h_power_data *data) { @@ -263,7 +333,7 @@ static int fam15h_power_init_data(struct pci_dev *f4, data->max_cu_acc_power = tmp; - return 0; + return read_registers(data); } static int fam15h_power_probe(struct pci_dev *pdev, -- GitLab From cdb9e110b10a08b7e1371356c2c03c73eb4f93d5 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 6 Apr 2016 15:44:12 +0800 Subject: [PATCH 3359/9938] hwmon: (fam15h_power) Add ptsc counter value for accumulated power PTSC is the performance timestamp counter value in a cpu core and the cores in one compute unit have the fixed frequency. So it picks up the performance timestamp counter value of the first core per compute unit to measure the interval for average power per compute unit. Signed-off-by: Huang Rui Cc: Borislav Petkov Signed-off-by: Guenter Roeck --- drivers/hwmon/fam15h_power.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 4edbaf083130..336d422fb863 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -50,6 +50,7 @@ MODULE_LICENSE("GPL"); #define MSR_F15H_CU_PWR_ACCUMULATOR 0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR 0xc001007b +#define MSR_F15H_PTSC 0xc0010280 #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4 @@ -65,6 +66,8 @@ struct fam15h_power_data { u64 max_cu_acc_power; /* accumulated power of the compute units */ u64 cu_acc_power[MAX_CUS]; + /* performance timestamp counter */ + u64 cpu_sw_pwr_ptsc[MAX_CUS]; }; static ssize_t show_power(struct device *dev, @@ -145,6 +148,7 @@ static void do_read_registers_on_cu(void *_data) cu = cpu_data(cpu).cpu_core_id; rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, &data->cu_acc_power[cu]); + rdmsrl_safe(MSR_F15H_PTSC, &data->cpu_sw_pwr_ptsc[cu]); } /* -- GitLab From 11bf0d78ccc4b2944aafd22ff05cd7e413ffea57 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 6 Apr 2016 15:44:13 +0800 Subject: [PATCH 3360/9938] hwmon: (fam15h_power) Introduce a cpu accumulated power reporting algorithm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces an algorithm that computes the average power by reading a delta value of “core power accumulator” register during measurement interval, and then dividing delta value by the length of the time interval. User is able to use power1_average entry to measure the processor power consumption and power1_average_interval entry to set the interval. A simple example: ray@hr-ub:~/tip$ sensors fam15h_power-pci-00c4 Adapter: PCI adapter power1: 19.58 mW (avg = 2.55 mW, interval = 0.01 s) (crit = 15.00 W) ... The result is current average processor power consumption in 10 millisecond. The unit of the result is uWatt. Suggested-by: Guenter Roeck Signed-off-by: Huang Rui Cc: Borislav Petkov Signed-off-by: Guenter Roeck --- drivers/hwmon/fam15h_power.c | 128 +++++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 336d422fb863..5abbfa89fb18 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,9 @@ MODULE_LICENSE("GPL"); #define FAM15H_NUM_GROUPS 2 #define MAX_CUS 8 +/* set maximum interval as 1 second */ +#define MAX_INTERVAL 1000 + #define MSR_F15H_CU_PWR_ACCUMULATOR 0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR 0xc001007b #define MSR_F15H_PTSC 0xc0010280 @@ -68,6 +73,9 @@ struct fam15h_power_data { u64 cu_acc_power[MAX_CUS]; /* performance timestamp counter */ u64 cpu_sw_pwr_ptsc[MAX_CUS]; + /* online/offline status of current compute unit */ + int cu_on[MAX_CUS]; + unsigned long power_period; }; static ssize_t show_power(struct device *dev, @@ -149,6 +157,8 @@ static void do_read_registers_on_cu(void *_data) rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, &data->cu_acc_power[cu]); rdmsrl_safe(MSR_F15H_PTSC, &data->cpu_sw_pwr_ptsc[cu]); + + data->cu_on[cu] = 1; } /* @@ -165,6 +175,8 @@ static int read_registers(struct fam15h_power_data *data) if (!ret) return -ENOMEM; + memset(data->cu_on, 0, sizeof(int) * MAX_CUS); + get_online_cpus(); this_cpu = smp_processor_id(); @@ -199,6 +211,98 @@ static int read_registers(struct fam15h_power_data *data) return 0; } +static ssize_t acc_show_power(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + u64 prev_cu_acc_power[MAX_CUS], prev_ptsc[MAX_CUS], + jdelta[MAX_CUS]; + u64 tdelta, avg_acc; + int cu, cu_num, ret; + signed long leftover; + + /* + * With the new x86 topology modelling, x86_max_cores is the + * compute unit number. + */ + cu_num = boot_cpu_data.x86_max_cores; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0; cu < cu_num; cu++) { + prev_cu_acc_power[cu] = data->cu_acc_power[cu]; + prev_ptsc[cu] = data->cpu_sw_pwr_ptsc[cu]; + } + + leftover = schedule_timeout_interruptible(msecs_to_jiffies(data->power_period)); + if (leftover) + return 0; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0, avg_acc = 0; cu < cu_num; cu++) { + /* check if current compute unit is online */ + if (data->cu_on[cu] == 0) + continue; + + if (data->cu_acc_power[cu] < prev_cu_acc_power[cu]) { + jdelta[cu] = data->max_cu_acc_power + data->cu_acc_power[cu]; + jdelta[cu] -= prev_cu_acc_power[cu]; + } else { + jdelta[cu] = data->cu_acc_power[cu] - prev_cu_acc_power[cu]; + } + tdelta = data->cpu_sw_pwr_ptsc[cu] - prev_ptsc[cu]; + jdelta[cu] *= data->cpu_pwr_sample_ratio * 1000; + do_div(jdelta[cu], tdelta); + + /* the unit is microWatt */ + avg_acc += jdelta[cu]; + } + + return sprintf(buf, "%llu\n", (unsigned long long)avg_acc); +} +static DEVICE_ATTR(power1_average, S_IRUGO, acc_show_power, NULL); + +static ssize_t acc_show_power_period(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%lu\n", data->power_period); +} + +static ssize_t acc_set_power_period(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + unsigned long temp; + int ret; + + ret = kstrtoul(buf, 10, &temp); + if (ret) + return ret; + + if (temp > MAX_INTERVAL) + return -EINVAL; + + /* the interval value should be greater than 0 */ + if (temp <= 0) + return -EINVAL; + + data->power_period = temp; + + return count; +} +static DEVICE_ATTR(power1_average_interval, S_IRUGO | S_IWUSR, + acc_show_power_period, acc_set_power_period); + static int fam15h_power_init_attrs(struct pci_dev *pdev, struct fam15h_power_data *data) { @@ -211,6 +315,10 @@ static int fam15h_power_init_attrs(struct pci_dev *pdev, (c->x86_model >= 0x60 && c->x86_model <= 0x7f))) n += 1; + /* check if processor supports accumulated power */ + if (boot_cpu_has(X86_FEATURE_ACC_POWER)) + n += 2; + fam15h_power_attrs = devm_kcalloc(&pdev->dev, n, sizeof(*fam15h_power_attrs), GFP_KERNEL); @@ -225,6 +333,11 @@ static int fam15h_power_init_attrs(struct pci_dev *pdev, (c->x86_model >= 0x60 && c->x86_model <= 0x7f))) fam15h_power_attrs[n++] = &dev_attr_power1_input.attr; + if (boot_cpu_has(X86_FEATURE_ACC_POWER)) { + fam15h_power_attrs[n++] = &dev_attr_power1_average.attr; + fam15h_power_attrs[n++] = &dev_attr_power1_average_interval.attr; + } + data->group.attrs = fam15h_power_attrs; return 0; @@ -290,7 +403,7 @@ static int fam15h_power_resume(struct pci_dev *pdev) static int fam15h_power_init_data(struct pci_dev *f4, struct fam15h_power_data *data) { - u32 val, eax, ebx, ecx, edx; + u32 val; u64 tmp; int ret; @@ -317,10 +430,9 @@ static int fam15h_power_init_data(struct pci_dev *f4, if (ret) return ret; - cpuid(0x80000007, &eax, &ebx, &ecx, &edx); /* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */ - if (!(edx & BIT(12))) + if (!boot_cpu_has(X86_FEATURE_ACC_POWER)) return 0; /* @@ -328,7 +440,7 @@ static int fam15h_power_init_data(struct pci_dev *f4, * sample period to the PTSC counter period by executing CPUID * Fn8000_0007:ECX */ - data->cpu_pwr_sample_ratio = ecx; + data->cpu_pwr_sample_ratio = cpuid_ecx(0x80000007); if (rdmsrl_safe(MSR_F15H_CU_MAX_PWR_ACCUMULATOR, &tmp)) { pr_err("Failed to read max compute unit power accumulator MSR\n"); @@ -337,6 +449,14 @@ static int fam15h_power_init_data(struct pci_dev *f4, data->max_cu_acc_power = tmp; + /* + * Milliseconds are a reasonable interval for the measurement. + * But it shouldn't set too long here, because several seconds + * would cause the read function to hang. So set default + * interval as 10 ms. + */ + data->power_period = 10; + return read_registers(data); } -- GitLab From a6e232f78698953e6fd9c2f4c95e16d5f5f9d0c3 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 6 Apr 2016 15:44:14 +0800 Subject: [PATCH 3361/9938] hwmon: (fam15h_power) Add documentation for TDP and accumulated power algorithm This patch adds the description to explain the TDP reporting mechanism and accumulated power algorithm. Signed-off-by: Huang Rui Cc: Borislav Petkov Signed-off-by: Guenter Roeck --- Documentation/hwmon/fam15h_power | 65 +++++++++++++++++++++++++++++++- drivers/hwmon/fam15h_power.c | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power index e2b1b69eebea..fb594c281c46 100644 --- a/Documentation/hwmon/fam15h_power +++ b/Documentation/hwmon/fam15h_power @@ -10,14 +10,22 @@ Supported chips: Datasheets: BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors BIOS and Kernel Developer's Guide (BKDG) For AMD Family 16h Processors + AMD64 Architecture Programmer's Manual Volume 2: System Programming Author: Andreas Herrmann Description ----------- +1) Processor TDP (Thermal design power) + +Given a fixed frequency and voltage, the power consumption of a +processor varies based on the workload being executed. Derated power +is the power consumed when running a specific application. Thermal +design power (TDP) is an example of derated power. + This driver permits reading of registers providing power information -of AMD Family 15h and 16h processors. +of AMD Family 15h and 16h processors via TDP algorithm. For AMD Family 15h and 16h processors the following power values can be calculated using different processor northbridge function @@ -37,3 +45,58 @@ This driver provides ProcessorPwrWatts and CurrPwrWatts: On multi-node processors the calculated value is for the entire package and not for a single node. Thus the driver creates sysfs attributes only for internal node0 of a multi-node processor. + +2) Accumulated Power Mechanism + +This driver also introduces an algorithm that should be used to +calculate the average power consumed by a processor during a +measurement interval Tm. The feature of accumulated power mechanism is +indicated by CPUID Fn8000_0007_EDX[12]. + +* Tsample: compute unit power accumulator sample period +* Tref: the PTSC counter period +* PTSC: performance timestamp counter +* N: the ratio of compute unit power accumulator sample period to the + PTSC period +* Jmax: max compute unit accumulated power which is indicated by + MaxCpuSwPwrAcc MSR C001007b +* Jx/Jy: compute unit accumulated power which is indicated by + CpuSwPwrAcc MSR C001007a +* Tx/Ty: the value of performance timestamp counter which is indicated + by CU_PTSC MSR C0010280 +* PwrCPUave: CPU average power + +i. Determine the ratio of Tsample to Tref by executing CPUID Fn8000_0007. + N = value of CPUID Fn8000_0007_ECX[CpuPwrSampleTimeRatio[15:0]]. + +ii. Read the full range of the cumulative energy value from the new +MSR MaxCpuSwPwrAcc. + Jmax = value returned. +iii. At time x, SW reads CpuSwPwrAcc MSR and samples the PTSC. + Jx = value read from CpuSwPwrAcc and Tx = value read from +PTSC. + +iv. At time y, SW reads CpuSwPwrAcc MSR and samples the PTSC. + Jy = value read from CpuSwPwrAcc and Ty = value read from +PTSC. + +v. Calculate the average power consumption for a compute unit over +time period (y-x). Unit of result is uWatt. + if (Jy < Jx) // Rollover has occurred + Jdelta = (Jy + Jmax) - Jx + else + Jdelta = Jy - Jx + PwrCPUave = N * Jdelta * 1000 / (Ty - Tx) + +This driver provides PwrCPUave and interval(default is 10 millisecond +and maximum is 1 second): +* power1_average (PwrCPUave) +* power1_average_interval (Interval) + +The power1_average_interval can be updated at /etc/sensors3.conf file +as below: + +chip "fam15h_power-*" + set power1_average_interval 0.01 + +Then save it with "sensors -s". diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 5abbfa89fb18..7d9d6976a575 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -1,7 +1,7 @@ /* * fam15h_power.c - AMD Family 15h processor power monitoring * - * Copyright (c) 2011 Advanced Micro Devices, Inc. + * Copyright (c) 2011-2016 Advanced Micro Devices, Inc. * Author: Andreas Herrmann * * -- GitLab From 1d28e01628aebab8fe403e7e9d0760f3787763d5 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 6 Apr 2016 15:44:15 +0800 Subject: [PATCH 3362/9938] hwmon: (fam15h_power) Add platform check function This patch adds a platform check function to make code more readable. Signed-off-by: Huang Rui Signed-off-by: Guenter Roeck --- drivers/hwmon/fam15h_power.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 7d9d6976a575..eb97a9241d17 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -78,6 +78,11 @@ struct fam15h_power_data { unsigned long power_period; }; +static bool is_carrizo_or_later(void) +{ + return boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60; +} + static ssize_t show_power(struct device *dev, struct device_attribute *attr, char *buf) { @@ -94,7 +99,7 @@ static ssize_t show_power(struct device *dev, * On Carrizo and later platforms, TdpRunAvgAccCap bit field * is extended to 4:31 from 4:25. */ - if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) { + if (is_carrizo_or_later()) { running_avg_capture = val >> 4; running_avg_capture = sign_extend32(running_avg_capture, 27); } else { @@ -111,7 +116,7 @@ static ssize_t show_power(struct device *dev, * On Carrizo and later platforms, ApmTdpLimit bit field * is extended to 16:31 from 16:28. */ - if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) + if (is_carrizo_or_later()) tdp_limit = val >> 16; else tdp_limit = (val >> 16) & 0x1fff; -- GitLab From 11b8360851c22cdc0f939be56e28ce348bc3056f Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 18 Jan 2016 00:34:53 -0800 Subject: [PATCH 3363/9938] hwmon: (ltc2978) Add missing devicetree binding for LTM4675 Signed-off-by: Guenter Roeck --- Documentation/devicetree/bindings/hwmon/ltc2978.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/hwmon/ltc2978.txt b/Documentation/devicetree/bindings/hwmon/ltc2978.txt index a7afbf60bb9c..bf2a47bbdc58 100644 --- a/Documentation/devicetree/bindings/hwmon/ltc2978.txt +++ b/Documentation/devicetree/bindings/hwmon/ltc2978.txt @@ -13,6 +13,7 @@ Required properties: * "lltc,ltc3886" * "lltc,ltc3887" * "lltc,ltm2987" + * "lltc,ltm4675" * "lltc,ltm4676" - reg: I2C slave address -- GitLab From 730554059bf26ab7a4f2cab8ed96e840a03d9b40 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 26 Mar 2015 09:16:32 -0700 Subject: [PATCH 3364/9938] hwmon: (it87) Add feature flag for AVCC3 support AVCC3 is supported on IT8620E, similar to IT8603E. Add feature flag to indicate AVCC3 support. Don't enable it for now on IT8620E since it is unclear if this chip supports it correctly. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1896e26df634..146f93584cde 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -233,6 +233,8 @@ static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 }; #define IT87_REG_VIN(nr) (0x20 + (nr)) #define IT87_REG_TEMP(nr) (0x29 + (nr)) +#define IT87_REG_AVCC3 0x2f + #define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2) #define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2) #define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2) @@ -269,6 +271,7 @@ struct it87_devices { #define FEAT_IN7_INTERNAL (1 << 10) /* Set if in7 is internal */ #define FEAT_SIX_FANS (1 << 11) /* Supports six fans */ #define FEAT_10_9MV_ADC (1 << 12) +#define FEAT_AVCC3 (1 << 13) /* Chip supports in9/AVCC3 */ static const struct it87_devices it87_devices[] = { [it87] = { @@ -389,7 +392,8 @@ static const struct it87_devices it87_devices[] = { .name = "it8603", .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS - | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL, + | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL + | FEAT_AVCC3, .peci_mask = 0x07, }, [it8620] = { @@ -419,6 +423,7 @@ static const struct it87_devices it87_devices[] = { #define has_vid(data) ((data)->features & FEAT_VID) #define has_in7_internal(data) ((data)->features & FEAT_IN7_INTERNAL) #define has_six_fans(data) ((data)->features & FEAT_SIX_FANS) +#define has_avcc3(data) ((data)->features & FEAT_AVCC3) struct it87_sio_data { enum chips type; @@ -1548,7 +1553,7 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr, static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2); -/* special AVCC3 IT8603E in9 */ +/* AVCC3 */ static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0); static ssize_t show_name(struct device *dev, struct device_attribute @@ -1944,8 +1949,10 @@ static int __init it87_find(unsigned short *address, /* in8 (Vbat) is always internal */ sio_data->internal |= (1 << 2); - /* Only the IT8603E has in9 */ - if (sio_data->type != it8603) + /* in9 (AVCC3), always internal if supported */ + if (has_avcc3(config)) + sio_data->internal |= (1 << 3); /* in9 is AVCC */ + else sio_data->skip_in |= (1 << 9); if (!has_vid(config)) @@ -2044,8 +2051,6 @@ static int __init it87_find(unsigned short *address, sio_data->skip_in |= (1 << 5); /* No VIN5 */ sio_data->skip_in |= (1 << 6); /* No VIN6 */ - sio_data->internal |= (1 << 3); /* in9 is AVCC */ - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; } else if (sio_data->type == it8620) { int reg; @@ -2689,8 +2694,8 @@ static struct it87_data *it87_update_device(struct device *dev) } /* in8 (battery) has no limit registers */ data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8)); - if (data->type == it8603) - data->in[9][0] = it87_read_value(data, 0x2f); + if (has_avcc3(data)) + data->in[9][0] = it87_read_value(data, IT87_REG_AVCC3); for (i = 0; i < 6; i++) { /* Skip disabled fans */ -- GitLab From 36c4d98a7883d4c51252d0f4ebf2c667fa7f879f Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 26 Mar 2015 18:18:19 -0700 Subject: [PATCH 3365/9938] hwmon: (it87) Add support for all pwm channels on IT8620E IT8620E supports up to 6 pwm channels. Add support for it. Also check if fan tachometers 4..6 are enabled before instantiating the respective sysfs attributes. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 114 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 20 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 146f93584cde..916d73630224 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -168,6 +168,7 @@ static inline void superio_exit(void) #define IT87_SIO_GPIO1_REG 0x25 #define IT87_SIO_GPIO2_REG 0x26 #define IT87_SIO_GPIO3_REG 0x27 +#define IT87_SIO_GPIO4_REG 0x28 #define IT87_SIO_GPIO5_REG 0x29 #define IT87_SIO_PINX1_REG 0x2a /* Pin selection */ #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ @@ -227,8 +228,8 @@ static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 }; #define IT87_REG_FAN_MAIN_CTRL 0x13 #define IT87_REG_FAN_CTL 0x14 -#define IT87_REG_PWM(nr) (0x15 + (nr)) -#define IT87_REG_PWM_DUTY(nr) (0x63 + (nr) * 8) +static const u8 IT87_REG_PWM[] = { 0x15, 0x16, 0x17, 0x7f, 0xa7, 0xaf }; +static const u8 IT87_REG_PWM_DUTY[] = { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab }; #define IT87_REG_VIN(nr) (0x20 + (nr)) #define IT87_REG_TEMP(nr) (0x29 + (nr)) @@ -272,6 +273,7 @@ struct it87_devices { #define FEAT_SIX_FANS (1 << 11) /* Supports six fans */ #define FEAT_10_9MV_ADC (1 << 12) #define FEAT_AVCC3 (1 << 13) /* Chip supports in9/AVCC3 */ +#define FEAT_SIX_PWM (1 << 14) /* Chip supports 6 pwm chn */ static const struct it87_devices it87_devices[] = { [it87] = { @@ -401,7 +403,7 @@ static const struct it87_devices it87_devices[] = { .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS - | FEAT_IN7_INTERNAL, + | FEAT_IN7_INTERNAL | FEAT_SIX_PWM, .peci_mask = 0x07, }, }; @@ -424,6 +426,7 @@ static const struct it87_devices it87_devices[] = { #define has_in7_internal(data) ((data)->features & FEAT_IN7_INTERNAL) #define has_six_fans(data) ((data)->features & FEAT_SIX_FANS) #define has_avcc3(data) ((data)->features & FEAT_AVCC3) +#define has_six_pwm(data) ((data)->features & FEAT_SIX_PWM) struct it87_sio_data { enum chips type; @@ -483,9 +486,9 @@ struct it87_data { * is no longer needed, but it is still done to keep the driver * simple. */ - u8 pwm_ctrl[3]; /* Register value */ - u8 pwm_duty[3]; /* Manual PWM value set by user */ - u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */ + u8 pwm_ctrl[6]; /* Register value */ + u8 pwm_duty[6]; /* Manual PWM value set by user */ + u8 pwm_temp_map[6]; /* PWM to temp. chan. mapping (bits 1-0) */ /* Automatic fan speed control registers */ u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */ @@ -1068,7 +1071,7 @@ static ssize_t set_pwm_enable(struct device *dev, data->pwm_duty[nr]; else /* Automatic mode */ data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; - it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); + it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]); if (data->type != it8603) { /* set SmartGuardian mode */ @@ -1104,7 +1107,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, return -EBUSY; } data->pwm_duty[nr] = pwm_to_reg(data, val); - it87_write_value(data, IT87_REG_PWM_DUTY(nr), + it87_write_value(data, IT87_REG_PWM_DUTY[nr], data->pwm_duty[nr]); } else { data->pwm_duty[nr] = pwm_to_reg(data, val); @@ -1114,7 +1117,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, */ if (!(data->pwm_ctrl[nr] & 0x80)) { data->pwm_ctrl[nr] = data->pwm_duty[nr]; - it87_write_value(data, IT87_REG_PWM(nr), + it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]); } } @@ -1207,7 +1210,7 @@ static ssize_t set_pwm_temp_map(struct device *dev, */ if (data->pwm_ctrl[nr] & 0x80) { data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; - it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); + it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]); } mutex_unlock(&data->update_lock); return count; @@ -1385,6 +1388,27 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR, static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, 2, 4); +static SENSOR_DEVICE_ATTR(pwm4_enable, S_IRUGO | S_IWUSR, + show_pwm_enable, set_pwm_enable, 3); +static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 3); +static DEVICE_ATTR(pwm4_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IRUGO | S_IWUSR, + show_pwm_temp_map, set_pwm_temp_map, 3); + +static SENSOR_DEVICE_ATTR(pwm5_enable, S_IRUGO | S_IWUSR, + show_pwm_enable, set_pwm_enable, 4); +static SENSOR_DEVICE_ATTR(pwm5, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 4); +static DEVICE_ATTR(pwm5_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm5_auto_channels_temp, S_IRUGO | S_IWUSR, + show_pwm_temp_map, set_pwm_temp_map, 4); + +static SENSOR_DEVICE_ATTR(pwm6_enable, S_IRUGO | S_IWUSR, + show_pwm_enable, set_pwm_enable, 5); +static SENSOR_DEVICE_ATTR(pwm6, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 5); +static DEVICE_ATTR(pwm6_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm6_auto_channels_temp, S_IRUGO | S_IWUSR, + show_pwm_temp_map, set_pwm_temp_map, 5); + /* Alarms */ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) @@ -1747,7 +1771,7 @@ static const struct attribute *it87_attributes_fan_div[] = { &sensor_dev_attr_fan3_div.dev_attr.attr, }; -static struct attribute *it87_attributes_pwm[3][4+1] = { { +static struct attribute *it87_attributes_pwm[6][4+1] = { { &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &dev_attr_pwm1_freq.attr, @@ -1765,12 +1789,33 @@ static struct attribute *it87_attributes_pwm[3][4+1] = { { &dev_attr_pwm3_freq.attr, &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, NULL +}, { + &sensor_dev_attr_pwm4_enable.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &dev_attr_pwm4_freq.attr, + &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, + NULL +}, { + &sensor_dev_attr_pwm5_enable.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + &dev_attr_pwm5_freq.attr, + &sensor_dev_attr_pwm5_auto_channels_temp.dev_attr.attr, + NULL +}, { + &sensor_dev_attr_pwm6_enable.dev_attr.attr, + &sensor_dev_attr_pwm6.dev_attr.attr, + &dev_attr_pwm6_freq.attr, + &sensor_dev_attr_pwm6_auto_channels_temp.dev_attr.attr, + NULL } }; -static const struct attribute_group it87_group_pwm[3] = { +static const struct attribute_group it87_group_pwm[6] = { { .attrs = it87_attributes_pwm[0] }, { .attrs = it87_attributes_pwm[1] }, { .attrs = it87_attributes_pwm[2] }, + { .attrs = it87_attributes_pwm[3] }, + { .attrs = it87_attributes_pwm[4] }, + { .attrs = it87_attributes_pwm[5] }, }; static struct attribute *it87_attributes_autopwm[3][9+1] = { { @@ -1955,6 +2000,9 @@ static int __init it87_find(unsigned short *address, else sio_data->skip_in |= (1 << 9); + if (!has_six_pwm(config)) + sio_data->skip_pwm |= (1 << 3) | (1 << 4) | (1 << 5); + if (!has_vid(config)) sio_data->skip_vid = 1; @@ -2057,6 +2105,11 @@ static int __init it87_find(unsigned short *address, superio_select(GPIO); + /* Check for pwm5 */ + reg = superio_inb(IT87_SIO_GPIO1_REG); + if (reg & (1 << 6)) + sio_data->skip_pwm |= (1 << 4); + /* Check for fan4, fan5 */ reg = superio_inb(IT87_SIO_GPIO2_REG); if (!(reg & (1 << 5))) @@ -2071,12 +2124,22 @@ static int __init it87_find(unsigned short *address, if (reg & (1 << 7)) sio_data->skip_fan |= (1 << 2); + /* Check for pwm4 */ + reg = superio_inb(IT87_SIO_GPIO4_REG); + if (!(reg & (1 << 2))) + sio_data->skip_pwm |= (1 << 3); + /* Check for pwm2, fan2 */ reg = superio_inb(IT87_SIO_GPIO5_REG); if (reg & (1 << 1)) sio_data->skip_pwm |= (1 << 1); if (reg & (1 << 2)) sio_data->skip_fan |= (1 << 1); + /* Check for pwm6, fan6 */ + if (!(reg & (1 << 7))) { + sio_data->skip_pwm |= (1 << 5); + sio_data->skip_fan |= (1 << 5); + } sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; } else { @@ -2219,7 +2282,7 @@ static void it87_remove_files(struct device *dev) sysfs_remove_file(&dev->kobj, it87_attributes_fan_div[i]); } - for (i = 0; i < 3; i++) { + for (i = 0; i < 6; i++) { if (sio_data->skip_pwm & (1 << i)) continue; sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]); @@ -2402,7 +2465,7 @@ static int it87_probe(struct platform_device *pdev) } if (enable_pwm_interface) { - for (i = 0; i < 3; i++) { + for (i = 0; i < 6; i++) { if (sio_data->skip_pwm & (1 << i)) continue; err = sysfs_create_group(&dev->kobj, @@ -2505,7 +2568,7 @@ static int it87_check_pwm(struct device *dev) for (i = 0; i < 3; i++) pwm[i] = it87_read_value(data, - IT87_REG_PWM(i)); + IT87_REG_PWM[i]); /* * If any fan is in automatic pwm mode, the polarity @@ -2520,7 +2583,7 @@ static int it87_check_pwm(struct device *dev) tmp | 0x87); for (i = 0; i < 3; i++) it87_write_value(data, - IT87_REG_PWM(i), + IT87_REG_PWM[i], 0x7f & ~pwm[i]); return 1; } @@ -2635,6 +2698,16 @@ static void it87_init_device(struct platform_device *pdev) /* Fan input pins may be used for alternative functions */ data->has_fan &= ~sio_data->skip_fan; + /* Check if pwm5, pwm6 are enabled */ + if (has_six_pwm(data)) { + /* The following code may be IT8620E specific */ + tmp = it87_read_value(data, IT87_REG_FAN_DIV); + if ((tmp & 0xc0) == 0xc0) + sio_data->skip_pwm |= (1 << 4); + if (!(tmp & (1 << 3))) + sio_data->skip_pwm |= (1 << 5); + } + /* Start monitoring */ it87_write_value(data, IT87_REG_CONFIG, (it87_read_value(data, IT87_REG_CONFIG) & 0x3e) @@ -2643,11 +2716,12 @@ static void it87_init_device(struct platform_device *pdev) static void it87_update_pwm_ctrl(struct it87_data *data, int nr) { - data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); + data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM[nr]); if (has_newer_autopwm(data)) { - data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; + data->pwm_temp_map[nr] = (data->pwm_ctrl[nr] & 0x03) + + nr < 3 ? 0 : 3; data->pwm_duty[nr] = it87_read_value(data, - IT87_REG_PWM_DUTY(nr)); + IT87_REG_PWM_DUTY[nr]); } else { if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; @@ -2746,7 +2820,7 @@ static struct it87_data *it87_update_device(struct device *dev) data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); - for (i = 0; i < 3; i++) + for (i = 0; i < 6; i++) it87_update_pwm_ctrl(data, i); data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); -- GitLab From 60878bcfd3dd2ea146dacf41313f8caa365df9a1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 26 Mar 2015 19:57:42 -0700 Subject: [PATCH 3366/9938] hwmon: (it87) Add support for second pwm frequency register Recent chips have a separate register to select the pwm2 frequency. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 100 +++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 916d73630224..68c8d98e711a 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -274,6 +274,7 @@ struct it87_devices { #define FEAT_10_9MV_ADC (1 << 12) #define FEAT_AVCC3 (1 << 13) /* Chip supports in9/AVCC3 */ #define FEAT_SIX_PWM (1 << 14) /* Chip supports 6 pwm chn */ +#define FEAT_PWM_FREQ2 (1 << 15) /* Separate pwm freq 2 */ static const struct it87_devices it87_devices[] = { [it87] = { @@ -291,20 +292,22 @@ static const struct it87_devices it87_devices[] = { .name = "it8716", .suffix = "F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID - | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS, + | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2, }, [it8718] = { .name = "it8718", .suffix = "F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS + | FEAT_PWM_FREQ2, .old_peci_mask = 0x4, }, [it8720] = { .name = "it8720", .suffix = "F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS + | FEAT_PWM_FREQ2, .old_peci_mask = 0x4, }, [it8721] = { @@ -312,7 +315,8 @@ static const struct it87_devices it87_devices[] = { .suffix = "F", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI - | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL, + | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL + | FEAT_PWM_FREQ2, .peci_mask = 0x05, .old_peci_mask = 0x02, /* Actually reports PCH */ }, @@ -321,7 +325,7 @@ static const struct it87_devices it87_devices[] = { .suffix = "F", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS - | FEAT_IN7_INTERNAL, + | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2, .peci_mask = 0x07, }, [it8732] = { @@ -337,7 +341,8 @@ static const struct it87_devices it87_devices[] = { .name = "it8771", .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS - | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL, + | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL + | FEAT_PWM_FREQ2, /* PECI: guesswork */ /* 12mV ADC (OHM) */ /* 16 bit fans (OHM) */ @@ -348,7 +353,8 @@ static const struct it87_devices it87_devices[] = { .name = "it8772", .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS - | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL, + | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL + | FEAT_PWM_FREQ2, /* PECI (coreboot) */ /* 12mV ADC (HWSensors4, OHM) */ /* 16 bit fans (HWSensors4, OHM) */ @@ -359,35 +365,37 @@ static const struct it87_devices it87_devices[] = { .name = "it8781", .suffix = "F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2, .old_peci_mask = 0x4, }, [it8782] = { .name = "it8782", .suffix = "F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2, .old_peci_mask = 0x4, }, [it8783] = { .name = "it8783", .suffix = "E/F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2, .old_peci_mask = 0x4, }, [it8786] = { .name = "it8786", .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS - | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL, + | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL + | FEAT_PWM_FREQ2, .peci_mask = 0x07, }, [it8790] = { .name = "it8790", .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS - | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL, + | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL + | FEAT_PWM_FREQ2, .peci_mask = 0x07, }, [it8603] = { @@ -395,7 +403,7 @@ static const struct it87_devices it87_devices[] = { .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL - | FEAT_AVCC3, + | FEAT_AVCC3 | FEAT_PWM_FREQ2, .peci_mask = 0x07, }, [it8620] = { @@ -403,7 +411,7 @@ static const struct it87_devices it87_devices[] = { .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS - | FEAT_IN7_INTERNAL | FEAT_SIX_PWM, + | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2, .peci_mask = 0x07, }, }; @@ -427,6 +435,7 @@ static const struct it87_devices it87_devices[] = { #define has_six_fans(data) ((data)->features & FEAT_SIX_FANS) #define has_avcc3(data) ((data)->features & FEAT_AVCC3) #define has_six_pwm(data) ((data)->features & FEAT_SIX_PWM) +#define has_pwm_freq2(data) ((data)->features & FEAT_PWM_FREQ2) struct it87_sio_data { enum chips type; @@ -906,9 +915,16 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf) { + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); struct it87_data *data = it87_update_device(dev); - int index = (data->fan_ctl >> 4) & 0x07; + int nr = sensor_attr->index; unsigned int freq; + int index; + + if (has_pwm_freq2(data) && nr == 1) + index = (data->extra >> 4) & 0x07; + else + index = (data->fan_ctl >> 4) & 0x07; freq = pwm_freq[index] / (has_newer_autopwm(data) ? 256 : 128); @@ -1127,7 +1143,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); struct it87_data *data = dev_get_drvdata(dev); + int nr = sensor_attr->index; unsigned long val; int i; @@ -1144,9 +1162,15 @@ static ssize_t set_pwm_freq(struct device *dev, } mutex_lock(&data->update_lock); - data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f; - data->fan_ctl |= i << 4; - it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl); + if (nr == 0) { + data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f; + data->fan_ctl |= i << 4; + it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl); + } else { + data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x8f; + data->extra |= i << 4; + it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra); + } mutex_unlock(&data->update_lock); return count; @@ -1316,7 +1340,8 @@ static SENSOR_DEVICE_ATTR_2(fan6_min, S_IRUGO | S_IWUSR, show_fan, set_fan, static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 0); static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); -static DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq, + set_pwm_freq, 0); static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, 0); static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, @@ -1341,7 +1366,7 @@ static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR, static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 1); static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); -static DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, NULL); +static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, set_pwm_freq, 1); static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, 1); static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, @@ -1366,7 +1391,7 @@ static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR, static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 2); static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 2); -static DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL); +static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL, 2); static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, 2); static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, @@ -1391,21 +1416,21 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR, static SENSOR_DEVICE_ATTR(pwm4_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 3); static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 3); -static DEVICE_ATTR(pwm4_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm4_freq, S_IRUGO, show_pwm_freq, NULL, 3); static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, 3); static SENSOR_DEVICE_ATTR(pwm5_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 4); static SENSOR_DEVICE_ATTR(pwm5, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 4); -static DEVICE_ATTR(pwm5_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm5_freq, S_IRUGO, show_pwm_freq, NULL, 4); static SENSOR_DEVICE_ATTR(pwm5_auto_channels_temp, S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, 4); static SENSOR_DEVICE_ATTR(pwm6_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 5); static SENSOR_DEVICE_ATTR(pwm6, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 5); -static DEVICE_ATTR(pwm6_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm6_freq, S_IRUGO, show_pwm_freq, NULL, 5); static SENSOR_DEVICE_ATTR(pwm6_auto_channels_temp, S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, 5); @@ -1774,44 +1799,57 @@ static const struct attribute *it87_attributes_fan_div[] = { static struct attribute *it87_attributes_pwm[6][4+1] = { { &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, - &dev_attr_pwm1_freq.attr, + &sensor_dev_attr_pwm1_freq.dev_attr.attr, &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, NULL }, { &sensor_dev_attr_pwm2_enable.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, - &dev_attr_pwm2_freq.attr, + &sensor_dev_attr_pwm2_freq.dev_attr.attr, &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, NULL }, { &sensor_dev_attr_pwm3_enable.dev_attr.attr, &sensor_dev_attr_pwm3.dev_attr.attr, - &dev_attr_pwm3_freq.attr, + &sensor_dev_attr_pwm3_freq.dev_attr.attr, &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, NULL }, { &sensor_dev_attr_pwm4_enable.dev_attr.attr, &sensor_dev_attr_pwm4.dev_attr.attr, - &dev_attr_pwm4_freq.attr, + &sensor_dev_attr_pwm4_freq.dev_attr.attr, &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, NULL }, { &sensor_dev_attr_pwm5_enable.dev_attr.attr, &sensor_dev_attr_pwm5.dev_attr.attr, - &dev_attr_pwm5_freq.attr, + &sensor_dev_attr_pwm5_freq.dev_attr.attr, &sensor_dev_attr_pwm5_auto_channels_temp.dev_attr.attr, NULL }, { &sensor_dev_attr_pwm6_enable.dev_attr.attr, &sensor_dev_attr_pwm6.dev_attr.attr, - &dev_attr_pwm6_freq.attr, + &sensor_dev_attr_pwm6_freq.dev_attr.attr, &sensor_dev_attr_pwm6_auto_channels_temp.dev_attr.attr, NULL } }; +static umode_t pwm_attribute_mode(struct kobject *kobj, struct attribute *attr, + int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct it87_data *data = dev_get_drvdata(dev); + + if (has_pwm_freq2(data) && index == 2) + return attr->mode | S_IWUSR; + + return attr->mode; +} + static const struct attribute_group it87_group_pwm[6] = { { .attrs = it87_attributes_pwm[0] }, - { .attrs = it87_attributes_pwm[1] }, + { .attrs = it87_attributes_pwm[1], + .is_visible = pwm_attribute_mode, }, { .attrs = it87_attributes_pwm[2] }, { .attrs = it87_attributes_pwm[3] }, { .attrs = it87_attributes_pwm[4] }, -- GitLab From 5cae84a58ee60eb54f636133f4f3ede9af93d476 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 28 Mar 2015 07:44:59 -0700 Subject: [PATCH 3367/9938] hwmon: (it87) Simplify error return in it87_device_add Return directly on errors if there is no cleanup necessary. Don't create an error message on memory allocation errors. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 68c8d98e711a..9b36987d7949 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -2898,14 +2898,11 @@ static int __init it87_device_add(unsigned short address, err = acpi_check_resource_conflict(&res); if (err) - goto exit; + return err; pdev = platform_device_alloc(DRVNAME, address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } + if (!pdev) + return -ENOMEM; err = platform_device_add_resources(pdev, &res, 1); if (err) { @@ -2930,7 +2927,6 @@ static int __init it87_device_add(unsigned short address, exit_device_put: platform_device_put(pdev); -exit: return err; } -- GitLab From 8e50e3c3f60c84b96956d37cbbf109b75569c6ba Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 28 Mar 2015 07:49:14 -0700 Subject: [PATCH 3368/9938] hwmon: (it87) Don't use pdev as static driver variable Using the same varible name for function names and as static variable invites misuse and prevents us from adding support for a second chip. Rename pdev to it87_pdev and limit its use to where it is needed. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 9b36987d7949..8f28f9b04150 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -78,7 +78,7 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -static struct platform_device *pdev; +static struct platform_device *it87_pdev; #define REG 0x2e /* The register to read/write */ #define DEV 0x07 /* Register: Logical device select */ @@ -2285,7 +2285,7 @@ static int __init it87_find(unsigned short *address, static void it87_remove_files(struct device *dev) { - struct it87_data *data = platform_get_drvdata(pdev); + struct it87_data *data = dev_get_drvdata(dev); struct it87_sio_data *sio_data = dev_get_platdata(dev); int i; @@ -2888,6 +2888,7 @@ static struct it87_data *it87_update_device(struct device *dev) static int __init it87_device_add(unsigned short address, const struct it87_sio_data *sio_data) { + struct platform_device *pdev; struct resource res = { .start = address + IT87_EC_OFFSET, .end = address + IT87_EC_OFFSET + IT87_EC_EXTENT - 1, @@ -2923,6 +2924,7 @@ static int __init it87_device_add(unsigned short address, goto exit_device_put; } + it87_pdev = pdev; return 0; exit_device_put: @@ -2955,7 +2957,7 @@ static int __init sm_it87_init(void) static void __exit sm_it87_exit(void) { - platform_device_unregister(pdev); + platform_device_unregister(it87_pdev); platform_driver_unregister(&it87_driver); } -- GitLab From 3c2e35126f2821be9b6f11dd5b772c68bcef4475 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 28 Mar 2015 08:03:10 -0700 Subject: [PATCH 3369/9938] hwmon: (it87) Pass SIO base address as parameter to superio functions This will let us support more than one chip on different SIO addresses with the same driver. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 137 +++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 65 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 8f28f9b04150..4840f2d8c7b1 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -80,9 +80,9 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); static struct platform_device *it87_pdev; -#define REG 0x2e /* The register to read/write */ +#define REG_2E 0x2e /* The register to read/write */ + #define DEV 0x07 /* Register: Logical device select */ -#define VAL 0x2f /* The value to read/write */ #define PME 0x04 /* The device with the fan registers in it */ /* The device with the IT8718F/IT8720F VID value in it */ @@ -91,54 +91,54 @@ static struct platform_device *it87_pdev; #define DEVID 0x20 /* Register: Device ID */ #define DEVREV 0x22 /* Register: Device Revision */ -static inline int superio_inb(int reg) +static inline int superio_inb(int ioreg, int reg) { - outb(reg, REG); - return inb(VAL); + outb(reg, ioreg); + return inb(ioreg + 1); } -static inline void superio_outb(int reg, int val) +static inline void superio_outb(int ioreg, int reg, int val) { - outb(reg, REG); - outb(val, VAL); + outb(reg, ioreg); + outb(val, ioreg + 1); } -static int superio_inw(int reg) +static int superio_inw(int ioreg, int reg) { int val; - outb(reg++, REG); - val = inb(VAL) << 8; - outb(reg, REG); - val |= inb(VAL); + outb(reg++, ioreg); + val = inb(ioreg + 1) << 8; + outb(reg, ioreg); + val |= inb(ioreg + 1); return val; } -static inline void superio_select(int ldn) +static inline void superio_select(int ioreg, int ldn) { - outb(DEV, REG); - outb(ldn, VAL); + outb(DEV, ioreg); + outb(ldn, ioreg + 1); } -static inline int superio_enter(void) +static inline int superio_enter(int ioreg) { /* - * Try to reserve REG and REG + 1 for exclusive access. + * Try to reserve ioreg and ioreg + 1 for exclusive access. */ - if (!request_muxed_region(REG, 2, DRVNAME)) + if (!request_muxed_region(ioreg, 2, DRVNAME)) return -EBUSY; - outb(0x87, REG); - outb(0x01, REG); - outb(0x55, REG); - outb(0x55, REG); + outb(0x87, ioreg); + outb(0x01, ioreg); + outb(0x55, ioreg); + outb(0x55, ioreg); return 0; } -static inline void superio_exit(void) +static inline void superio_exit(int ioreg) { - outb(0x02, REG); - outb(0x02, VAL); - release_region(REG, 2); + outb(0x02, ioreg); + outb(0x02, ioreg + 1); + release_region(ioreg, 2); } /* Logical device 4 registers */ @@ -1929,20 +1929,20 @@ static const struct attribute_group it87_group_label = { }; /* SuperIO detection - will change isa_address if a chip is found */ -static int __init it87_find(unsigned short *address, - struct it87_sio_data *sio_data) +static int __init it87_find(int sioaddr, unsigned short *address, + struct it87_sio_data *sio_data) { int err; u16 chip_type; const char *board_vendor, *board_name; const struct it87_devices *config; - err = superio_enter(); + err = superio_enter(sioaddr); if (err) return err; err = -ENODEV; - chip_type = force_id ? force_id : superio_inw(DEVID); + chip_type = force_id ? force_id : superio_inw(sioaddr, DEVID); switch (chip_type) { case IT8705F_DEVID: @@ -2005,20 +2005,20 @@ static int __init it87_find(unsigned short *address, goto exit; } - superio_select(PME); - if (!(superio_inb(IT87_ACT_REG) & 0x01)) { + superio_select(sioaddr, PME); + if (!(superio_inb(sioaddr, IT87_ACT_REG) & 0x01)) { pr_info("Device not activated, skipping\n"); goto exit; } - *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1); + *address = superio_inw(sioaddr, IT87_BASE_REG) & ~(IT87_EXTENT - 1); if (*address == 0) { pr_info("Base address not set, skipping\n"); goto exit; } err = 0; - sio_data->revision = superio_inb(DEVREV) & 0x0f; + sio_data->revision = superio_inb(sioaddr, DEVREV) & 0x0f; pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type, it87_devices[sio_data->type].suffix, *address, sio_data->revision); @@ -2047,18 +2047,19 @@ static int __init it87_find(unsigned short *address, /* Read GPIO config and VID value from LDN 7 (GPIO) */ if (sio_data->type == it87) { /* The IT8705F has a different LD number for GPIO */ - superio_select(5); - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; + superio_select(sioaddr, 5); + sio_data->beep_pin = superio_inb(sioaddr, + IT87_SIO_BEEP_PIN_REG) & 0x3f; } else if (sio_data->type == it8783) { int reg25, reg27, reg2a, reg2c, regef; - superio_select(GPIO); + superio_select(sioaddr, GPIO); - reg25 = superio_inb(IT87_SIO_GPIO1_REG); - reg27 = superio_inb(IT87_SIO_GPIO3_REG); - reg2a = superio_inb(IT87_SIO_PINX1_REG); - reg2c = superio_inb(IT87_SIO_PINX2_REG); - regef = superio_inb(IT87_SIO_SPI_REG); + reg25 = superio_inb(sioaddr, IT87_SIO_GPIO1_REG); + reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); + reg2a = superio_inb(sioaddr, IT87_SIO_PINX1_REG); + reg2c = superio_inb(sioaddr, IT87_SIO_PINX2_REG); + regef = superio_inb(sioaddr, IT87_SIO_SPI_REG); /* Check if fan3 is there or not */ if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2))) @@ -2101,7 +2102,8 @@ static int __init it87_find(unsigned short *address, */ if (!(reg2c & (1 << 1))) { reg2c |= (1 << 1); - superio_outb(IT87_SIO_PINX2_REG, reg2c); + superio_outb(sioaddr, IT87_SIO_PINX2_REG, + reg2c); pr_notice("Routing internal VCCH5V to in7.\n"); } pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n"); @@ -2113,13 +2115,14 @@ static int __init it87_find(unsigned short *address, if (reg2c & (1 << 1)) sio_data->internal |= (1 << 1); - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; + sio_data->beep_pin = superio_inb(sioaddr, + IT87_SIO_BEEP_PIN_REG) & 0x3f; } else if (sio_data->type == it8603) { int reg27, reg29; - superio_select(GPIO); + superio_select(sioaddr, GPIO); - reg27 = superio_inb(IT87_SIO_GPIO3_REG); + reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); /* Check if fan3 is there or not */ if (reg27 & (1 << 6)) @@ -2128,7 +2131,7 @@ static int __init it87_find(unsigned short *address, sio_data->skip_fan |= (1 << 2); /* Check if fan2 is there or not */ - reg29 = superio_inb(IT87_SIO_GPIO5_REG); + reg29 = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); if (reg29 & (1 << 1)) sio_data->skip_pwm |= (1 << 1); if (reg29 & (1 << 2)) @@ -2137,38 +2140,39 @@ static int __init it87_find(unsigned short *address, sio_data->skip_in |= (1 << 5); /* No VIN5 */ sio_data->skip_in |= (1 << 6); /* No VIN6 */ - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; + sio_data->beep_pin = superio_inb(sioaddr, + IT87_SIO_BEEP_PIN_REG) & 0x3f; } else if (sio_data->type == it8620) { int reg; - superio_select(GPIO); + superio_select(sioaddr, GPIO); /* Check for pwm5 */ - reg = superio_inb(IT87_SIO_GPIO1_REG); + reg = superio_inb(sioaddr, IT87_SIO_GPIO1_REG); if (reg & (1 << 6)) sio_data->skip_pwm |= (1 << 4); /* Check for fan4, fan5 */ - reg = superio_inb(IT87_SIO_GPIO2_REG); + reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG); if (!(reg & (1 << 5))) sio_data->skip_fan |= (1 << 3); if (!(reg & (1 << 4))) sio_data->skip_fan |= (1 << 4); /* Check for pwm3, fan3 */ - reg = superio_inb(IT87_SIO_GPIO3_REG); + reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); if (reg & (1 << 6)) sio_data->skip_pwm |= (1 << 2); if (reg & (1 << 7)) sio_data->skip_fan |= (1 << 2); /* Check for pwm4 */ - reg = superio_inb(IT87_SIO_GPIO4_REG); + reg = superio_inb(sioaddr, IT87_SIO_GPIO4_REG); if (!(reg & (1 << 2))) sio_data->skip_pwm |= (1 << 3); /* Check for pwm2, fan2 */ - reg = superio_inb(IT87_SIO_GPIO5_REG); + reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); if (reg & (1 << 1)) sio_data->skip_pwm |= (1 << 1); if (reg & (1 << 2)) @@ -2179,14 +2183,15 @@ static int __init it87_find(unsigned short *address, sio_data->skip_fan |= (1 << 5); } - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; + sio_data->beep_pin = superio_inb(sioaddr, + IT87_SIO_BEEP_PIN_REG) & 0x3f; } else { int reg; bool uart6; - superio_select(GPIO); + superio_select(sioaddr, GPIO); - reg = superio_inb(IT87_SIO_GPIO3_REG); + reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); if (!sio_data->skip_vid) { /* We need at least 4 VID pins */ if (reg & 0x0f) { @@ -2202,7 +2207,7 @@ static int __init it87_find(unsigned short *address, sio_data->skip_fan |= (1 << 2); /* Check if fan2 is there or not */ - reg = superio_inb(IT87_SIO_GPIO5_REG); + reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); if (reg & (1 << 1)) sio_data->skip_pwm |= (1 << 1); if (reg & (1 << 2)) @@ -2210,9 +2215,10 @@ static int __init it87_find(unsigned short *address, if ((sio_data->type == it8718 || sio_data->type == it8720) && !(sio_data->skip_vid)) - sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); + sio_data->vid_value = superio_inb(sioaddr, + IT87_SIO_VID_REG); - reg = superio_inb(IT87_SIO_PINX2_REG); + reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG); uart6 = sio_data->type == it8782 && (reg & (1 << 2)); @@ -2232,7 +2238,7 @@ static int __init it87_find(unsigned short *address, */ if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) { reg |= (1 << 1); - superio_outb(IT87_SIO_PINX2_REG, reg); + superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg); pr_notice("Routing internal VCCH to in7\n"); } if (reg & (1 << 0)) @@ -2254,7 +2260,8 @@ static int __init it87_find(unsigned short *address, sio_data->skip_temp |= (1 << 2); } - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; + sio_data->beep_pin = superio_inb(sioaddr, + IT87_SIO_BEEP_PIN_REG) & 0x3f; } if (sio_data->beep_pin) pr_info("Beeping is supported\n"); @@ -2279,7 +2286,7 @@ static int __init it87_find(unsigned short *address, } exit: - superio_exit(); + superio_exit(sioaddr); return err; } @@ -2939,7 +2946,7 @@ static int __init sm_it87_init(void) struct it87_sio_data sio_data; memset(&sio_data, 0, sizeof(struct it87_sio_data)); - err = it87_find(&isa_address, &sio_data); + err = it87_find(REG_2E, &isa_address, &sio_data); if (err) return err; err = platform_driver_register(&it87_driver); -- GitLab From e84bd9535e2bb59624091bc8c1eddae7cc82d260 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 28 Mar 2015 08:24:29 -0700 Subject: [PATCH 3370/9938] hwmon: (it87) Add support for second Super-IO chip The Super-IO chip can also reside at SIO address 0x4e, and there can be two Super-IO chips in the system. Add support for it. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 49 ++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 4840f2d8c7b1..f877cc98b2fd 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -78,9 +78,10 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -static struct platform_device *it87_pdev; +static struct platform_device *it87_pdev[2]; #define REG_2E 0x2e /* The register to read/write */ +#define REG_4E 0x4e /* Secondary register to read/write */ #define DEV 0x07 /* Register: Logical device select */ #define PME 0x04 /* The device with the fan registers in it */ @@ -130,7 +131,7 @@ static inline int superio_enter(int ioreg) outb(0x87, ioreg); outb(0x01, ioreg); outb(0x55, ioreg); - outb(0x55, ioreg); + outb(ioreg == REG_4E ? 0xaa : 0x55, ioreg); return 0; } @@ -2892,7 +2893,7 @@ static struct it87_data *it87_update_device(struct device *dev) return data; } -static int __init it87_device_add(unsigned short address, +static int __init it87_device_add(int index, unsigned short address, const struct it87_sio_data *sio_data) { struct platform_device *pdev; @@ -2931,7 +2932,7 @@ static int __init it87_device_add(unsigned short address, goto exit_device_put; } - it87_pdev = pdev; + it87_pdev[index] = pdev; return 0; exit_device_put: @@ -2941,30 +2942,48 @@ static int __init it87_device_add(unsigned short address, static int __init sm_it87_init(void) { - int err; - unsigned short isa_address = 0; + int sioaddr[2] = { REG_2E, REG_4E }; struct it87_sio_data sio_data; + unsigned short isa_address; + bool found = false; + int i, err; - memset(&sio_data, 0, sizeof(struct it87_sio_data)); - err = it87_find(REG_2E, &isa_address, &sio_data); - if (err) - return err; err = platform_driver_register(&it87_driver); if (err) return err; - err = it87_device_add(isa_address, &sio_data); - if (err) { - platform_driver_unregister(&it87_driver); - return err; + for (i = 0; i < ARRAY_SIZE(sioaddr); i++) { + memset(&sio_data, 0, sizeof(struct it87_sio_data)); + isa_address = 0; + err = it87_find(sioaddr[i], &isa_address, &sio_data); + if (err || isa_address == 0) + continue; + + err = it87_device_add(i, isa_address, &sio_data); + if (err) + goto exit_dev_unregister; + found = true; } + if (!found) { + err = -ENODEV; + goto exit_unregister; + } return 0; + +exit_dev_unregister: + /* NULL check handled by platform_device_unregister */ + platform_device_unregister(it87_pdev[0]); +exit_unregister: + platform_driver_unregister(&it87_driver); + return err; } static void __exit sm_it87_exit(void) { - platform_device_unregister(it87_pdev); + /* NULL check handled by platform_device_unregister */ + platform_device_unregister(it87_pdev[1]); + platform_device_unregister(it87_pdev[0]); platform_driver_unregister(&it87_driver); } -- GitLab From c1e7a4ca6d7c58e30185d40e9ba82c7976950f32 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 28 Mar 2015 09:27:27 -0700 Subject: [PATCH 3371/9938] hwmon: (it87) Rearrange code to avoid forward declarations Cleanup only, no functional change. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 761 +++++++++++++++++++++---------------------- 1 file changed, 376 insertions(+), 385 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index f877cc98b2fd..4b38ecb91959 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -603,23 +603,160 @@ static const unsigned int pwm_freq[8] = { 750000, }; -static int it87_probe(struct platform_device *pdev); -static int it87_remove(struct platform_device *pdev); +/* + * Must be called with data->update_lock held, except during initialization. + * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, + * would slow down the IT87 access and should not be necessary. + */ +static int it87_read_value(struct it87_data *data, u8 reg) +{ + outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); + return inb_p(data->addr + IT87_DATA_REG_OFFSET); +} + +/* + * Must be called with data->update_lock held, except during initialization. + * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, + * would slow down the IT87 access and should not be necessary. + */ +static void it87_write_value(struct it87_data *data, u8 reg, u8 value) +{ + outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); + outb_p(value, data->addr + IT87_DATA_REG_OFFSET); +} + +static void it87_update_pwm_ctrl(struct it87_data *data, int nr) +{ + data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM[nr]); + if (has_newer_autopwm(data)) { + data->pwm_temp_map[nr] = (data->pwm_ctrl[nr] & 0x03) + + nr < 3 ? 0 : 3; + data->pwm_duty[nr] = it87_read_value(data, + IT87_REG_PWM_DUTY[nr]); + } else { + if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ + data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; + else /* Manual mode */ + data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; + } -static int it87_read_value(struct it87_data *data, u8 reg); -static void it87_write_value(struct it87_data *data, u8 reg, u8 value); -static struct it87_data *it87_update_device(struct device *dev); -static int it87_check_pwm(struct device *dev); -static void it87_init_device(struct platform_device *pdev); + if (has_old_autopwm(data)) { + int i; + for (i = 0; i < 5 ; i++) + data->auto_temp[nr][i] = it87_read_value(data, + IT87_REG_AUTO_TEMP(nr, i)); + for (i = 0; i < 3 ; i++) + data->auto_pwm[nr][i] = it87_read_value(data, + IT87_REG_AUTO_PWM(nr, i)); + } +} -static struct platform_driver it87_driver = { - .driver = { - .name = DRVNAME, - }, - .probe = it87_probe, - .remove = it87_remove, -}; +static struct it87_data *it87_update_device(struct device *dev) +{ + struct it87_data *data = dev_get_drvdata(dev); + int i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + if (update_vbat) { + /* + * Cleared after each update, so reenable. Value + * returned by this read will be previous value + */ + it87_write_value(data, IT87_REG_CONFIG, + it87_read_value(data, IT87_REG_CONFIG) | 0x40); + } + for (i = 0; i <= 7; i++) { + data->in[i][0] = + it87_read_value(data, IT87_REG_VIN(i)); + data->in[i][1] = + it87_read_value(data, IT87_REG_VIN_MIN(i)); + data->in[i][2] = + it87_read_value(data, IT87_REG_VIN_MAX(i)); + } + /* in8 (battery) has no limit registers */ + data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8)); + if (has_avcc3(data)) + data->in[9][0] = it87_read_value(data, IT87_REG_AVCC3); + + for (i = 0; i < 6; i++) { + /* Skip disabled fans */ + if (!(data->has_fan & (1 << i))) + continue; + + data->fan[i][1] = + it87_read_value(data, IT87_REG_FAN_MIN[i]); + data->fan[i][0] = it87_read_value(data, + IT87_REG_FAN[i]); + /* Add high byte if in 16-bit mode */ + if (has_16bit_fans(data)) { + data->fan[i][0] |= it87_read_value(data, + IT87_REG_FANX[i]) << 8; + data->fan[i][1] |= it87_read_value(data, + IT87_REG_FANX_MIN[i]) << 8; + } + } + for (i = 0; i < 3; i++) { + if (!(data->has_temp & (1 << i))) + continue; + data->temp[i][0] = + it87_read_value(data, IT87_REG_TEMP(i)); + data->temp[i][1] = + it87_read_value(data, IT87_REG_TEMP_LOW(i)); + data->temp[i][2] = + it87_read_value(data, IT87_REG_TEMP_HIGH(i)); + if (has_temp_offset(data)) + data->temp[i][3] = + it87_read_value(data, + IT87_REG_TEMP_OFFSET[i]); + } + + /* Newer chips don't have clock dividers */ + if ((data->has_fan & 0x07) && !has_16bit_fans(data)) { + i = it87_read_value(data, IT87_REG_FAN_DIV); + data->fan_div[0] = i & 0x07; + data->fan_div[1] = (i >> 3) & 0x07; + data->fan_div[2] = (i & 0x40) ? 3 : 1; + } + + data->alarms = + it87_read_value(data, IT87_REG_ALARM1) | + (it87_read_value(data, IT87_REG_ALARM2) << 8) | + (it87_read_value(data, IT87_REG_ALARM3) << 16); + data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); + + data->fan_main_ctrl = it87_read_value(data, + IT87_REG_FAN_MAIN_CTRL); + data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); + for (i = 0; i < 6; i++) + it87_update_pwm_ctrl(data, i); + + data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); + data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); + /* + * The IT8705F does not have VID capability. + * The IT8718F and later don't use IT87_REG_VID for the + * same purpose. + */ + if (data->type == it8712 || data->type == it8716) { + data->vid = it87_read_value(data, IT87_REG_VID); + /* + * The older IT8712F revisions had only 5 VID pins, + * but we assume it is always safe to read 6 bits. + */ + data->vid &= 0x3f; + } + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} static ssize_t show_in(struct device *dev, struct device_attribute *attr, char *buf) @@ -2341,64 +2478,233 @@ static void it87_remove_files(struct device *dev) sysfs_remove_group(&dev->kobj, &it87_group_label); } -static int it87_probe(struct platform_device *pdev) +/* Called when we have found a new IT87. */ +static void it87_init_device(struct platform_device *pdev) { - struct it87_data *data; - struct resource *res; - struct device *dev = &pdev->dev; - struct it87_sio_data *sio_data = dev_get_platdata(dev); - int err = 0, i; - int enable_pwm_interface; - int fan_beep_need_rw; + struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev); + struct it87_data *data = platform_get_drvdata(pdev); + int tmp, i; + u8 mask; - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, - DRVNAME)) { - dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)res->start, - (unsigned long)(res->start + IT87_EC_EXTENT - 1)); - return -EBUSY; + /* + * For each PWM channel: + * - If it is in automatic mode, setting to manual mode should set + * the fan to full speed by default. + * - If it is in manual mode, we need a mapping to temperature + * channels to use when later setting to automatic mode later. + * Use a 1:1 mapping by default (we are clueless.) + * In both cases, the value can (and should) be changed by the user + * prior to switching to a different mode. + * Note that this is no longer needed for the IT8721F and later, as + * these have separate registers for the temperature mapping and the + * manual duty cycle. + */ + for (i = 0; i < 3; i++) { + data->pwm_temp_map[i] = i; + data->pwm_duty[i] = 0x7f; /* Full speed */ + data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */ } - data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->addr = res->start; - data->type = sio_data->type; - data->features = it87_devices[sio_data->type].features; - data->peci_mask = it87_devices[sio_data->type].peci_mask; - data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask; - data->name = it87_devices[sio_data->type].name; /* - * IT8705F Datasheet 0.4.1, 3h == Version G. - * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. - * These are the first revisions with 16-bit tachometer support. + * Some chips seem to have default value 0xff for all limit + * registers. For low voltage limits it makes no sense and triggers + * alarms, so change to 0 instead. For high temperature limits, it + * means -1 degree C, which surprisingly doesn't trigger an alarm, + * but is still confusing, so change to 127 degrees C. */ - switch (data->type) { - case it87: - if (sio_data->revision >= 0x03) { - data->features &= ~FEAT_OLD_AUTOPWM; - data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS; - } - break; - case it8712: - if (sio_data->revision >= 0x08) { - data->features &= ~FEAT_OLD_AUTOPWM; - data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS | - FEAT_FIVE_FANS; - } - break; - default: - break; + for (i = 0; i < 8; i++) { + tmp = it87_read_value(data, IT87_REG_VIN_MIN(i)); + if (tmp == 0xff) + it87_write_value(data, IT87_REG_VIN_MIN(i), 0); + } + for (i = 0; i < 3; i++) { + tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); + if (tmp == 0xff) + it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); } - /* Now, we do the remaining detection. */ - if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) - || it87_read_value(data, IT87_REG_CHIPID) != 0x90) - return -ENODEV; + /* + * Temperature channels are not forcibly enabled, as they can be + * set to two different sensor types and we can't guess which one + * is correct for a given system. These channels can be enabled at + * run-time through the temp{1-3}_type sysfs accessors if needed. + */ - platform_set_drvdata(pdev, data); + /* Check if voltage monitors are reset manually or by some reason */ + tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); + if ((tmp & 0xff) == 0) { + /* Enable all voltage monitors */ + it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff); + } + + /* Check if tachometers are reset manually or by some reason */ + mask = 0x70 & ~(sio_data->skip_fan << 4); + data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); + if ((data->fan_main_ctrl & mask) == 0) { + /* Enable all fan tachometers */ + data->fan_main_ctrl |= mask; + it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, + data->fan_main_ctrl); + } + data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; + + tmp = it87_read_value(data, IT87_REG_FAN_16BIT); + + /* Set tachometers to 16-bit mode if needed */ + if (has_fan16_config(data)) { + if (~tmp & 0x07 & data->has_fan) { + dev_dbg(&pdev->dev, + "Setting fan1-3 to 16-bit mode\n"); + it87_write_value(data, IT87_REG_FAN_16BIT, + tmp | 0x07); + } + } + + /* Check for additional fans */ + if (has_five_fans(data)) { + if (tmp & (1 << 4)) + data->has_fan |= (1 << 3); /* fan4 enabled */ + if (tmp & (1 << 5)) + data->has_fan |= (1 << 4); /* fan5 enabled */ + if (has_six_fans(data) && (tmp & (1 << 2))) + data->has_fan |= (1 << 5); /* fan6 enabled */ + } + + /* Fan input pins may be used for alternative functions */ + data->has_fan &= ~sio_data->skip_fan; + + /* Check if pwm5, pwm6 are enabled */ + if (has_six_pwm(data)) { + /* The following code may be IT8620E specific */ + tmp = it87_read_value(data, IT87_REG_FAN_DIV); + if ((tmp & 0xc0) == 0xc0) + sio_data->skip_pwm |= (1 << 4); + if (!(tmp & (1 << 3))) + sio_data->skip_pwm |= (1 << 5); + } + + /* Start monitoring */ + it87_write_value(data, IT87_REG_CONFIG, + (it87_read_value(data, IT87_REG_CONFIG) & 0x3e) + | (update_vbat ? 0x41 : 0x01)); +} + +/* Return 1 if and only if the PWM interface is safe to use */ +static int it87_check_pwm(struct device *dev) +{ + struct it87_data *data = dev_get_drvdata(dev); + /* + * Some BIOSes fail to correctly configure the IT87 fans. All fans off + * and polarity set to active low is sign that this is the case so we + * disable pwm control to protect the user. + */ + int tmp = it87_read_value(data, IT87_REG_FAN_CTL); + + if ((tmp & 0x87) == 0) { + if (fix_pwm_polarity) { + /* + * The user asks us to attempt a chip reconfiguration. + * This means switching to active high polarity and + * inverting all fan speed values. + */ + int i; + u8 pwm[3]; + + for (i = 0; i < 3; i++) + pwm[i] = it87_read_value(data, + IT87_REG_PWM[i]); + + /* + * If any fan is in automatic pwm mode, the polarity + * might be correct, as suspicious as it seems, so we + * better don't change anything (but still disable the + * PWM interface). + */ + if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) { + dev_info(dev, + "Reconfiguring PWM to active high polarity\n"); + it87_write_value(data, IT87_REG_FAN_CTL, + tmp | 0x87); + for (i = 0; i < 3; i++) + it87_write_value(data, + IT87_REG_PWM[i], + 0x7f & ~pwm[i]); + return 1; + } + + dev_info(dev, + "PWM configuration is too broken to be fixed\n"); + } + + dev_info(dev, + "Detected broken BIOS defaults, disabling PWM interface\n"); + return 0; + } else if (fix_pwm_polarity) { + dev_info(dev, + "PWM configuration looks sane, won't touch\n"); + } + + return 1; +} + +static int it87_probe(struct platform_device *pdev) +{ + struct it87_data *data; + struct resource *res; + struct device *dev = &pdev->dev; + struct it87_sio_data *sio_data = dev_get_platdata(dev); + int err = 0, i; + int enable_pwm_interface; + int fan_beep_need_rw; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, + DRVNAME)) { + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, + (unsigned long)(res->start + IT87_EC_EXTENT - 1)); + return -EBUSY; + } + + data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->addr = res->start; + data->type = sio_data->type; + data->features = it87_devices[sio_data->type].features; + data->peci_mask = it87_devices[sio_data->type].peci_mask; + data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask; + data->name = it87_devices[sio_data->type].name; + /* + * IT8705F Datasheet 0.4.1, 3h == Version G. + * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. + * These are the first revisions with 16-bit tachometer support. + */ + switch (data->type) { + case it87: + if (sio_data->revision >= 0x03) { + data->features &= ~FEAT_OLD_AUTOPWM; + data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS; + } + break; + case it8712: + if (sio_data->revision >= 0x08) { + data->features &= ~FEAT_OLD_AUTOPWM; + data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS | + FEAT_FIVE_FANS; + } + break; + default: + break; + } + + /* Now, we do the remaining detection. */ + if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) + || it87_read_value(data, IT87_REG_CHIPID) != 0x90) + return -ENODEV; + + platform_set_drvdata(pdev, data); mutex_init(&data->update_lock); @@ -2570,328 +2876,13 @@ static int it87_remove(struct platform_device *pdev) return 0; } -/* - * Must be called with data->update_lock held, except during initialization. - * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, - * would slow down the IT87 access and should not be necessary. - */ -static int it87_read_value(struct it87_data *data, u8 reg) -{ - outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); - return inb_p(data->addr + IT87_DATA_REG_OFFSET); -} - -/* - * Must be called with data->update_lock held, except during initialization. - * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, - * would slow down the IT87 access and should not be necessary. - */ -static void it87_write_value(struct it87_data *data, u8 reg, u8 value) -{ - outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); - outb_p(value, data->addr + IT87_DATA_REG_OFFSET); -} - -/* Return 1 if and only if the PWM interface is safe to use */ -static int it87_check_pwm(struct device *dev) -{ - struct it87_data *data = dev_get_drvdata(dev); - /* - * Some BIOSes fail to correctly configure the IT87 fans. All fans off - * and polarity set to active low is sign that this is the case so we - * disable pwm control to protect the user. - */ - int tmp = it87_read_value(data, IT87_REG_FAN_CTL); - if ((tmp & 0x87) == 0) { - if (fix_pwm_polarity) { - /* - * The user asks us to attempt a chip reconfiguration. - * This means switching to active high polarity and - * inverting all fan speed values. - */ - int i; - u8 pwm[3]; - - for (i = 0; i < 3; i++) - pwm[i] = it87_read_value(data, - IT87_REG_PWM[i]); - - /* - * If any fan is in automatic pwm mode, the polarity - * might be correct, as suspicious as it seems, so we - * better don't change anything (but still disable the - * PWM interface). - */ - if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) { - dev_info(dev, - "Reconfiguring PWM to active high polarity\n"); - it87_write_value(data, IT87_REG_FAN_CTL, - tmp | 0x87); - for (i = 0; i < 3; i++) - it87_write_value(data, - IT87_REG_PWM[i], - 0x7f & ~pwm[i]); - return 1; - } - - dev_info(dev, - "PWM configuration is too broken to be fixed\n"); - } - - dev_info(dev, - "Detected broken BIOS defaults, disabling PWM interface\n"); - return 0; - } else if (fix_pwm_polarity) { - dev_info(dev, - "PWM configuration looks sane, won't touch\n"); - } - - return 1; -} - -/* Called when we have found a new IT87. */ -static void it87_init_device(struct platform_device *pdev) -{ - struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev); - struct it87_data *data = platform_get_drvdata(pdev); - int tmp, i; - u8 mask; - - /* - * For each PWM channel: - * - If it is in automatic mode, setting to manual mode should set - * the fan to full speed by default. - * - If it is in manual mode, we need a mapping to temperature - * channels to use when later setting to automatic mode later. - * Use a 1:1 mapping by default (we are clueless.) - * In both cases, the value can (and should) be changed by the user - * prior to switching to a different mode. - * Note that this is no longer needed for the IT8721F and later, as - * these have separate registers for the temperature mapping and the - * manual duty cycle. - */ - for (i = 0; i < 3; i++) { - data->pwm_temp_map[i] = i; - data->pwm_duty[i] = 0x7f; /* Full speed */ - data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */ - } - - /* - * Some chips seem to have default value 0xff for all limit - * registers. For low voltage limits it makes no sense and triggers - * alarms, so change to 0 instead. For high temperature limits, it - * means -1 degree C, which surprisingly doesn't trigger an alarm, - * but is still confusing, so change to 127 degrees C. - */ - for (i = 0; i < 8; i++) { - tmp = it87_read_value(data, IT87_REG_VIN_MIN(i)); - if (tmp == 0xff) - it87_write_value(data, IT87_REG_VIN_MIN(i), 0); - } - for (i = 0; i < 3; i++) { - tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); - if (tmp == 0xff) - it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); - } - - /* - * Temperature channels are not forcibly enabled, as they can be - * set to two different sensor types and we can't guess which one - * is correct for a given system. These channels can be enabled at - * run-time through the temp{1-3}_type sysfs accessors if needed. - */ - - /* Check if voltage monitors are reset manually or by some reason */ - tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); - if ((tmp & 0xff) == 0) { - /* Enable all voltage monitors */ - it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff); - } - - /* Check if tachometers are reset manually or by some reason */ - mask = 0x70 & ~(sio_data->skip_fan << 4); - data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); - if ((data->fan_main_ctrl & mask) == 0) { - /* Enable all fan tachometers */ - data->fan_main_ctrl |= mask; - it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, - data->fan_main_ctrl); - } - data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; - - tmp = it87_read_value(data, IT87_REG_FAN_16BIT); - - /* Set tachometers to 16-bit mode if needed */ - if (has_fan16_config(data)) { - if (~tmp & 0x07 & data->has_fan) { - dev_dbg(&pdev->dev, - "Setting fan1-3 to 16-bit mode\n"); - it87_write_value(data, IT87_REG_FAN_16BIT, - tmp | 0x07); - } - } - - /* Check for additional fans */ - if (has_five_fans(data)) { - if (tmp & (1 << 4)) - data->has_fan |= (1 << 3); /* fan4 enabled */ - if (tmp & (1 << 5)) - data->has_fan |= (1 << 4); /* fan5 enabled */ - if (has_six_fans(data) && (tmp & (1 << 2))) - data->has_fan |= (1 << 5); /* fan6 enabled */ - } - - /* Fan input pins may be used for alternative functions */ - data->has_fan &= ~sio_data->skip_fan; - - /* Check if pwm5, pwm6 are enabled */ - if (has_six_pwm(data)) { - /* The following code may be IT8620E specific */ - tmp = it87_read_value(data, IT87_REG_FAN_DIV); - if ((tmp & 0xc0) == 0xc0) - sio_data->skip_pwm |= (1 << 4); - if (!(tmp & (1 << 3))) - sio_data->skip_pwm |= (1 << 5); - } - - /* Start monitoring */ - it87_write_value(data, IT87_REG_CONFIG, - (it87_read_value(data, IT87_REG_CONFIG) & 0x3e) - | (update_vbat ? 0x41 : 0x01)); -} - -static void it87_update_pwm_ctrl(struct it87_data *data, int nr) -{ - data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM[nr]); - if (has_newer_autopwm(data)) { - data->pwm_temp_map[nr] = (data->pwm_ctrl[nr] & 0x03) + - nr < 3 ? 0 : 3; - data->pwm_duty[nr] = it87_read_value(data, - IT87_REG_PWM_DUTY[nr]); - } else { - if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ - data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; - else /* Manual mode */ - data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; - } - - if (has_old_autopwm(data)) { - int i; - - for (i = 0; i < 5 ; i++) - data->auto_temp[nr][i] = it87_read_value(data, - IT87_REG_AUTO_TEMP(nr, i)); - for (i = 0; i < 3 ; i++) - data->auto_pwm[nr][i] = it87_read_value(data, - IT87_REG_AUTO_PWM(nr, i)); - } -} - -static struct it87_data *it87_update_device(struct device *dev) -{ - struct it87_data *data = dev_get_drvdata(dev); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - if (update_vbat) { - /* - * Cleared after each update, so reenable. Value - * returned by this read will be previous value - */ - it87_write_value(data, IT87_REG_CONFIG, - it87_read_value(data, IT87_REG_CONFIG) | 0x40); - } - for (i = 0; i <= 7; i++) { - data->in[i][0] = - it87_read_value(data, IT87_REG_VIN(i)); - data->in[i][1] = - it87_read_value(data, IT87_REG_VIN_MIN(i)); - data->in[i][2] = - it87_read_value(data, IT87_REG_VIN_MAX(i)); - } - /* in8 (battery) has no limit registers */ - data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8)); - if (has_avcc3(data)) - data->in[9][0] = it87_read_value(data, IT87_REG_AVCC3); - - for (i = 0; i < 6; i++) { - /* Skip disabled fans */ - if (!(data->has_fan & (1 << i))) - continue; - - data->fan[i][1] = - it87_read_value(data, IT87_REG_FAN_MIN[i]); - data->fan[i][0] = it87_read_value(data, - IT87_REG_FAN[i]); - /* Add high byte if in 16-bit mode */ - if (has_16bit_fans(data)) { - data->fan[i][0] |= it87_read_value(data, - IT87_REG_FANX[i]) << 8; - data->fan[i][1] |= it87_read_value(data, - IT87_REG_FANX_MIN[i]) << 8; - } - } - for (i = 0; i < 3; i++) { - if (!(data->has_temp & (1 << i))) - continue; - data->temp[i][0] = - it87_read_value(data, IT87_REG_TEMP(i)); - data->temp[i][1] = - it87_read_value(data, IT87_REG_TEMP_LOW(i)); - data->temp[i][2] = - it87_read_value(data, IT87_REG_TEMP_HIGH(i)); - if (has_temp_offset(data)) - data->temp[i][3] = - it87_read_value(data, - IT87_REG_TEMP_OFFSET[i]); - } - - /* Newer chips don't have clock dividers */ - if ((data->has_fan & 0x07) && !has_16bit_fans(data)) { - i = it87_read_value(data, IT87_REG_FAN_DIV); - data->fan_div[0] = i & 0x07; - data->fan_div[1] = (i >> 3) & 0x07; - data->fan_div[2] = (i & 0x40) ? 3 : 1; - } - - data->alarms = - it87_read_value(data, IT87_REG_ALARM1) | - (it87_read_value(data, IT87_REG_ALARM2) << 8) | - (it87_read_value(data, IT87_REG_ALARM3) << 16); - data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); - - data->fan_main_ctrl = it87_read_value(data, - IT87_REG_FAN_MAIN_CTRL); - data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); - for (i = 0; i < 6; i++) - it87_update_pwm_ctrl(data, i); - - data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); - data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); - /* - * The IT8705F does not have VID capability. - * The IT8718F and later don't use IT87_REG_VID for the - * same purpose. - */ - if (data->type == it8712 || data->type == it8716) { - data->vid = it87_read_value(data, IT87_REG_VID); - /* - * The older IT8712F revisions had only 5 VID pins, - * but we assume it is always safe to read 6 bits. - */ - data->vid &= 0x3f; - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} +static struct platform_driver it87_driver = { + .driver = { + .name = DRVNAME, + }, + .probe = it87_probe, + .remove = it87_remove, +}; static int __init it87_device_add(int index, unsigned short address, const struct it87_sio_data *sio_data) -- GitLab From 52929715634ad36782bd7018ab0bf59a6619c393 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 30 Mar 2013 14:00:08 -0700 Subject: [PATCH 3372/9938] hwmon: (it87) Use is_visible for voltage sensors Simplify code and reduce object size by more than 300 bytes on x86_64. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 124 +++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 68 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 4b38ecb91959..81c11d1d67e2 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -471,6 +471,7 @@ struct it87_data { unsigned long last_updated; /* In jiffies */ u16 in_scaled; /* Internal voltage sensors are scaled */ + u16 has_in; /* Bitfield, voltage sensors enabled */ u8 in[10][3]; /* [nr][0]=in, [1]=min, [2]=max */ u8 has_fan; /* Bitfield, fans enabled */ u16 fan[6][2]; /* Register values, [nr][0]=fan, [1]=min */ @@ -482,6 +483,7 @@ struct it87_data { u8 vid; /* Register encoding, combined */ u8 vrm; u32 alarms; /* Register encoding, combined */ + bool has_beep; /* true if beep supported */ u8 beeps; /* Register encoding */ u8 fan_main_ctrl; /* Register value */ u8 fan_ctl; /* Register value */ @@ -1751,74 +1753,85 @@ static ssize_t show_name(struct device *dev, struct device_attribute } static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static struct attribute *it87_attributes_in[10][5] = { +static umode_t it87_in_is_visible(struct kobject *kobj, + struct attribute *attr, int index) { + struct device *dev = container_of(kobj, struct device, kobj); + struct it87_data *data = dev_get_drvdata(dev); + int i = index / 5; /* voltage index */ + int a = index % 5; /* attribute index */ + + if (index >= 40) { /* in8, in9 only have input attributes */ + i = index - 40 + 8; + a = 0; + } + + if (!(data->has_in & (1 << i))) + return 0; + + if (a == 4 && !data->has_beep) + return 0; + + return attr->mode; +} + +static struct attribute *it87_attributes_in[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, &sensor_dev_attr_in0_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_in0_beep.dev_attr.attr, /* 4 */ + &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, &sensor_dev_attr_in1_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_in1_beep.dev_attr.attr, /* 9 */ + &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, &sensor_dev_attr_in2_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_in2_beep.dev_attr.attr, /* 14 */ + &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, &sensor_dev_attr_in3_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_in3_beep.dev_attr.attr, /* 19 */ + &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, &sensor_dev_attr_in4_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_in4_beep.dev_attr.attr, /* 24 */ + &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in5_min.dev_attr.attr, &sensor_dev_attr_in5_max.dev_attr.attr, &sensor_dev_attr_in5_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_in5_beep.dev_attr.attr, /* 29 */ + &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in6_min.dev_attr.attr, &sensor_dev_attr_in6_max.dev_attr.attr, &sensor_dev_attr_in6_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_in6_beep.dev_attr.attr, /* 34 */ + &sensor_dev_attr_in7_input.dev_attr.attr, &sensor_dev_attr_in7_min.dev_attr.attr, &sensor_dev_attr_in7_max.dev_attr.attr, &sensor_dev_attr_in7_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_in8_input.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_in9_input.dev_attr.attr, - NULL -} }; + &sensor_dev_attr_in7_beep.dev_attr.attr, /* 39 */ + + &sensor_dev_attr_in8_input.dev_attr.attr, /* 40 */ + + &sensor_dev_attr_in9_input.dev_attr.attr, /* 41 */ +}; -static const struct attribute_group it87_group_in[10] = { - { .attrs = it87_attributes_in[0] }, - { .attrs = it87_attributes_in[1] }, - { .attrs = it87_attributes_in[2] }, - { .attrs = it87_attributes_in[3] }, - { .attrs = it87_attributes_in[4] }, - { .attrs = it87_attributes_in[5] }, - { .attrs = it87_attributes_in[6] }, - { .attrs = it87_attributes_in[7] }, - { .attrs = it87_attributes_in[8] }, - { .attrs = it87_attributes_in[9] }, +static const struct attribute_group it87_group_in = { + .attrs = it87_attributes_in, + .is_visible = it87_in_is_visible, }; static struct attribute *it87_attributes_temp[3][6] = { @@ -1868,19 +1881,6 @@ static const struct attribute_group it87_group = { .attrs = it87_attributes, }; -static struct attribute *it87_attributes_in_beep[] = { - &sensor_dev_attr_in0_beep.dev_attr.attr, - &sensor_dev_attr_in1_beep.dev_attr.attr, - &sensor_dev_attr_in2_beep.dev_attr.attr, - &sensor_dev_attr_in3_beep.dev_attr.attr, - &sensor_dev_attr_in4_beep.dev_attr.attr, - &sensor_dev_attr_in5_beep.dev_attr.attr, - &sensor_dev_attr_in6_beep.dev_attr.attr, - &sensor_dev_attr_in7_beep.dev_attr.attr, - NULL, - NULL, -}; - static struct attribute *it87_attributes_temp_beep[] = { &sensor_dev_attr_temp1_beep.dev_attr.attr, &sensor_dev_attr_temp2_beep.dev_attr.attr, @@ -2435,14 +2435,8 @@ static void it87_remove_files(struct device *dev) int i; sysfs_remove_group(&dev->kobj, &it87_group); - for (i = 0; i < 10; i++) { - if (sio_data->skip_in & (1 << i)) - continue; - sysfs_remove_group(&dev->kobj, &it87_group_in[i]); - if (it87_attributes_in_beep[i]) - sysfs_remove_file(&dev->kobj, - it87_attributes_in_beep[i]); - } + sysfs_remove_group(&dev->kobj, &it87_group_in); + for (i = 0; i < 3; i++) { if (!(data->has_temp & (1 << i))) continue; @@ -2736,6 +2730,10 @@ static int it87_probe(struct platform_device *pdev) data->has_temp &= ~(1 << 2); } + data->has_in = 0x3ff & ~sio_data->skip_in; + + data->has_beep = !!sio_data->beep_pin; + /* Initialize the IT87 chip */ it87_init_device(pdev); @@ -2744,19 +2742,9 @@ static int it87_probe(struct platform_device *pdev) if (err) return err; - for (i = 0; i < 10; i++) { - if (sio_data->skip_in & (1 << i)) - continue; - err = sysfs_create_group(&dev->kobj, &it87_group_in[i]); - if (err) - goto error; - if (sio_data->beep_pin && it87_attributes_in_beep[i]) { - err = sysfs_create_file(&dev->kobj, - it87_attributes_in_beep[i]); - if (err) - goto error; - } - } + err = sysfs_create_group(&dev->kobj, &it87_group_in); + if (err) + goto error; for (i = 0; i < 3; i++) { if (!(data->has_temp & (1 << i))) -- GitLab From 87533770be36ecea55b86fa377ba4232d720df23 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 30 Mar 2013 14:23:20 -0700 Subject: [PATCH 3373/9938] hwmon: (it87) Use is_visible for temperature sensors Simplify code and reduce object size by more than 200 bytes on x86_64. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 87 ++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 81c11d1d67e2..c7feea9a6f80 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -1834,40 +1834,57 @@ static const struct attribute_group it87_group_in = { .is_visible = it87_in_is_visible, }; -static struct attribute *it87_attributes_temp[3][6] = { +static umode_t it87_temp_is_visible(struct kobject *kobj, + struct attribute *attr, int index) { + struct device *dev = container_of(kobj, struct device, kobj); + struct it87_data *data = dev_get_drvdata(dev); + int i = index / 7; /* temperature index */ + int a = index % 7; /* attribute index */ + + if (!(data->has_temp & (1 << i))) + return 0; + + if (a == 5 && !has_temp_offset(data)) + return 0; + + if (a == 6 && !data->has_beep) + return 0; + + return attr->mode; +} + +static struct attribute *it87_attributes_temp[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_type.dev_attr.attr, &sensor_dev_attr_temp1_alarm.dev_attr.attr, - NULL -} , { + &sensor_dev_attr_temp1_offset.dev_attr.attr, /* 5 */ + &sensor_dev_attr_temp1_beep.dev_attr.attr, /* 6 */ + &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_type.dev_attr.attr, &sensor_dev_attr_temp2_alarm.dev_attr.attr, - NULL -} , { + &sensor_dev_attr_temp2_offset.dev_attr.attr, + &sensor_dev_attr_temp2_beep.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp3_type.dev_attr.attr, &sensor_dev_attr_temp3_alarm.dev_attr.attr, - NULL -} }; + &sensor_dev_attr_temp3_offset.dev_attr.attr, + &sensor_dev_attr_temp3_beep.dev_attr.attr, -static const struct attribute_group it87_group_temp[3] = { - { .attrs = it87_attributes_temp[0] }, - { .attrs = it87_attributes_temp[1] }, - { .attrs = it87_attributes_temp[2] }, + NULL }; -static struct attribute *it87_attributes_temp_offset[] = { - &sensor_dev_attr_temp1_offset.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, +static const struct attribute_group it87_group_temp = { + .attrs = it87_attributes_temp, + .is_visible = it87_temp_is_visible, }; static struct attribute *it87_attributes[] = { @@ -1881,12 +1898,6 @@ static const struct attribute_group it87_group = { .attrs = it87_attributes, }; -static struct attribute *it87_attributes_temp_beep[] = { - &sensor_dev_attr_temp1_beep.dev_attr.attr, - &sensor_dev_attr_temp2_beep.dev_attr.attr, - &sensor_dev_attr_temp3_beep.dev_attr.attr, -}; - static struct attribute *it87_attributes_fan[6][3+1] = { { &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, @@ -2436,18 +2447,8 @@ static void it87_remove_files(struct device *dev) sysfs_remove_group(&dev->kobj, &it87_group); sysfs_remove_group(&dev->kobj, &it87_group_in); + sysfs_remove_group(&dev->kobj, &it87_group_temp); - for (i = 0; i < 3; i++) { - if (!(data->has_temp & (1 << i))) - continue; - sysfs_remove_group(&dev->kobj, &it87_group_temp[i]); - if (has_temp_offset(data)) - sysfs_remove_file(&dev->kobj, - it87_attributes_temp_offset[i]); - if (sio_data->beep_pin) - sysfs_remove_file(&dev->kobj, - it87_attributes_temp_beep[i]); - } for (i = 0; i < 6; i++) { if (!(data->has_fan & (1 << i))) continue; @@ -2746,25 +2747,9 @@ static int it87_probe(struct platform_device *pdev) if (err) goto error; - for (i = 0; i < 3; i++) { - if (!(data->has_temp & (1 << i))) - continue; - err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]); - if (err) - goto error; - if (has_temp_offset(data)) { - err = sysfs_create_file(&dev->kobj, - it87_attributes_temp_offset[i]); - if (err) - goto error; - } - if (sio_data->beep_pin) { - err = sysfs_create_file(&dev->kobj, - it87_attributes_temp_beep[i]); - if (err) - goto error; - } - } + err = sysfs_create_group(&dev->kobj, &it87_group_temp); + if (err) + goto error; /* Do not create fan files for disabled fans */ fan_beep_need_rw = 1; -- GitLab From 9a70ee814d7093a2806e94b99ce12b8d35c6102e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 30 Mar 2013 14:51:20 -0700 Subject: [PATCH 3374/9938] hwmon: (it87) Use is_visible for fan attributes Simplify code and reduce object size by almost 500 bytes on x86_64. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 140 +++++++++++++++++-------------------------- 1 file changed, 55 insertions(+), 85 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index c7feea9a6f80..e70d227c2bf8 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -1898,51 +1898,75 @@ static const struct attribute_group it87_group = { .attrs = it87_attributes, }; -static struct attribute *it87_attributes_fan[6][3+1] = { { +static umode_t it87_fan_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct it87_data *data = dev_get_drvdata(dev); + int i = index / 5; /* fan index */ + int a = index % 5; /* attribute index */ + + if (index >= 15) { /* fan 4..6 don't have divisor attributes */ + i = (index - 15) / 4 + 3; + a = (index - 15) % 4; + } + + if (!(data->has_fan & (1 << i))) + return 0; + + if (a == 3) { /* beep */ + if (!data->has_beep) + return 0; + /* first fan beep attribute is writable */ + if (i == __ffs(data->has_fan)) + return attr->mode | S_IWUSR; + } + + if (a == 4 && has_16bit_fans(data)) /* divisor */ + return 0; + + return attr->mode; +} + +static struct attribute *it87_attributes_fan[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_fan1_beep.dev_attr.attr, /* 3 */ + &sensor_dev_attr_fan1_div.dev_attr.attr, /* 4 */ + &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_alarm.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_fan2_beep.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, /* 9 */ + &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan3_min.dev_attr.attr, &sensor_dev_attr_fan3_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan3_beep.dev_attr.attr, + &sensor_dev_attr_fan3_div.dev_attr.attr, /* 14 */ + + &sensor_dev_attr_fan4_input.dev_attr.attr, /* 15 */ &sensor_dev_attr_fan4_min.dev_attr.attr, &sensor_dev_attr_fan4_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan4_beep.dev_attr.attr, + + &sensor_dev_attr_fan5_input.dev_attr.attr, /* 19 */ &sensor_dev_attr_fan5_min.dev_attr.attr, &sensor_dev_attr_fan5_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan5_beep.dev_attr.attr, + + &sensor_dev_attr_fan6_input.dev_attr.attr, /* 23 */ &sensor_dev_attr_fan6_min.dev_attr.attr, &sensor_dev_attr_fan6_alarm.dev_attr.attr, + &sensor_dev_attr_fan6_beep.dev_attr.attr, NULL -} }; - -static const struct attribute_group it87_group_fan[6] = { - { .attrs = it87_attributes_fan[0] }, - { .attrs = it87_attributes_fan[1] }, - { .attrs = it87_attributes_fan[2] }, - { .attrs = it87_attributes_fan[3] }, - { .attrs = it87_attributes_fan[4] }, - { .attrs = it87_attributes_fan[5] }, }; -static const struct attribute *it87_attributes_fan_div[] = { - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, +static const struct attribute_group it87_group_fan = { + .attrs = it87_attributes_fan, + .is_visible = it87_fan_is_visible, }; static struct attribute *it87_attributes_pwm[6][4+1] = { { @@ -2046,15 +2070,6 @@ static const struct attribute_group it87_group_autopwm[3] = { { .attrs = it87_attributes_autopwm[2] }, }; -static struct attribute *it87_attributes_fan_beep[] = { - &sensor_dev_attr_fan1_beep.dev_attr.attr, - &sensor_dev_attr_fan2_beep.dev_attr.attr, - &sensor_dev_attr_fan3_beep.dev_attr.attr, - &sensor_dev_attr_fan4_beep.dev_attr.attr, - &sensor_dev_attr_fan5_beep.dev_attr.attr, - &sensor_dev_attr_fan6_beep.dev_attr.attr, -}; - static struct attribute *it87_attributes_vid[] = { &dev_attr_vrm.attr, &dev_attr_cpu0_vid.attr, @@ -2448,18 +2463,8 @@ static void it87_remove_files(struct device *dev) sysfs_remove_group(&dev->kobj, &it87_group); sysfs_remove_group(&dev->kobj, &it87_group_in); sysfs_remove_group(&dev->kobj, &it87_group_temp); + sysfs_remove_group(&dev->kobj, &it87_group_fan); - for (i = 0; i < 6; i++) { - if (!(data->has_fan & (1 << i))) - continue; - sysfs_remove_group(&dev->kobj, &it87_group_fan[i]); - if (sio_data->beep_pin) - sysfs_remove_file(&dev->kobj, - it87_attributes_fan_beep[i]); - if (i < 3 && !has_16bit_fans(data)) - sysfs_remove_file(&dev->kobj, - it87_attributes_fan_div[i]); - } for (i = 0; i < 6; i++) { if (sio_data->skip_pwm & (1 << i)) continue; @@ -2650,7 +2655,6 @@ static int it87_probe(struct platform_device *pdev) struct it87_sio_data *sio_data = dev_get_platdata(dev); int err = 0, i; int enable_pwm_interface; - int fan_beep_need_rw; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, @@ -2751,43 +2755,9 @@ static int it87_probe(struct platform_device *pdev) if (err) goto error; - /* Do not create fan files for disabled fans */ - fan_beep_need_rw = 1; - for (i = 0; i < 6; i++) { - if (!(data->has_fan & (1 << i))) - continue; - err = sysfs_create_group(&dev->kobj, &it87_group_fan[i]); - if (err) - goto error; - - if (i < 3 && !has_16bit_fans(data)) { - err = sysfs_create_file(&dev->kobj, - it87_attributes_fan_div[i]); - if (err) - goto error; - } - - if (sio_data->beep_pin) { - err = sysfs_create_file(&dev->kobj, - it87_attributes_fan_beep[i]); - if (err) - goto error; - if (!fan_beep_need_rw) - continue; - - /* - * As we have a single beep enable bit for all fans, - * only the first enabled fan has a writable attribute - * for it. - */ - if (sysfs_chmod_file(&dev->kobj, - it87_attributes_fan_beep[i], - S_IRUGO | S_IWUSR)) - dev_dbg(dev, "chmod +w fan%d_beep failed\n", - i + 1); - fan_beep_need_rw = 0; - } - } + err = sysfs_create_group(&dev->kobj, &it87_group_fan); + if (err) + goto error; if (enable_pwm_interface) { for (i = 0; i < 6; i++) { -- GitLab From 5c3912616d37bcc292ae09a8be7f1a58d54f19f9 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 30 Mar 2013 15:02:12 -0700 Subject: [PATCH 3375/9938] hwmon: (it87) Use is_visible for pwm attributes Simplify code and reduce object size by about 250 bytes on x86_64. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 137 ++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 72 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index e70d227c2bf8..0c13d640bcc7 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -498,6 +498,7 @@ struct it87_data { * is no longer needed, but it is still done to keep the driver * simple. */ + u8 has_pwm; /* Bitfield, pwm control enabled */ u8 pwm_ctrl[6]; /* Register value */ u8 pwm_duty[6]; /* Manual PWM value set by user */ u8 pwm_temp_map[6]; /* PWM to temp. chan. mapping (bits 1-0) */ @@ -1340,15 +1341,6 @@ static ssize_t set_pwm_temp_map(struct device *dev, long val; u8 reg; - /* - * This check can go away if we ever support automatic fan speed - * control on newer chips. - */ - if (!has_old_autopwm(data)) { - dev_notice(dev, "Mapping change disabled for safety reasons\n"); - return -EINVAL; - } - if (kstrtol(buf, 10, &val) < 0) return -EINVAL; @@ -1482,7 +1474,7 @@ static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq, 0); -static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 0); static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, 0, 0); @@ -1507,7 +1499,7 @@ static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 1); static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, set_pwm_freq, 1); -static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 1); static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, 1, 0); @@ -1532,7 +1524,7 @@ static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 2); static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 2); static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL, 2); -static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 2); static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, 2, 0); @@ -1557,21 +1549,21 @@ static SENSOR_DEVICE_ATTR(pwm4_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 3); static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 3); static SENSOR_DEVICE_ATTR(pwm4_freq, S_IRUGO, show_pwm_freq, NULL, 3); -static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 3); static SENSOR_DEVICE_ATTR(pwm5_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 4); static SENSOR_DEVICE_ATTR(pwm5, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 4); static SENSOR_DEVICE_ATTR(pwm5_freq, S_IRUGO, show_pwm_freq, NULL, 4); -static SENSOR_DEVICE_ATTR(pwm5_auto_channels_temp, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm5_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 4); static SENSOR_DEVICE_ATTR(pwm6_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 5); static SENSOR_DEVICE_ATTR(pwm6, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 5); static SENSOR_DEVICE_ATTR(pwm6_freq, S_IRUGO, show_pwm_freq, NULL, 5); -static SENSOR_DEVICE_ATTR(pwm6_auto_channels_temp, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm6_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 5); /* Alarms */ @@ -1969,67 +1961,81 @@ static const struct attribute_group it87_group_fan = { .is_visible = it87_fan_is_visible, }; -static struct attribute *it87_attributes_pwm[6][4+1] = { { +static umode_t it87_pwm_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct it87_data *data = dev_get_drvdata(dev); + int i = index / 4; /* pwm index */ + int a = index % 4; /* attribute index */ + + if (!(data->has_pwm & (1 << i))) + return 0; + + /* pwmX_auto_channels_temp is only writable for old auto pwm */ + if (a == 3 && has_old_autopwm(data)) + return attr->mode | S_IWUSR; + + /* pwm2_freq is writable if there are two pwm frequency selects */ + if (has_pwm_freq2(data) && i == 1 && a == 2) + return attr->mode | S_IWUSR; + + return attr->mode; +} + +static struct attribute *it87_attributes_pwm[] = { &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm1_freq.dev_attr.attr, &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_pwm2_enable.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_pwm2_freq.dev_attr.attr, &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_pwm3_enable.dev_attr.attr, &sensor_dev_attr_pwm3.dev_attr.attr, &sensor_dev_attr_pwm3_freq.dev_attr.attr, &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_pwm4_enable.dev_attr.attr, &sensor_dev_attr_pwm4.dev_attr.attr, &sensor_dev_attr_pwm4_freq.dev_attr.attr, &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_pwm5_enable.dev_attr.attr, &sensor_dev_attr_pwm5.dev_attr.attr, &sensor_dev_attr_pwm5_freq.dev_attr.attr, &sensor_dev_attr_pwm5_auto_channels_temp.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_pwm6_enable.dev_attr.attr, &sensor_dev_attr_pwm6.dev_attr.attr, &sensor_dev_attr_pwm6_freq.dev_attr.attr, &sensor_dev_attr_pwm6_auto_channels_temp.dev_attr.attr, + NULL -} }; +}; -static umode_t pwm_attribute_mode(struct kobject *kobj, struct attribute *attr, - int index) +static const struct attribute_group it87_group_pwm = { + .attrs = it87_attributes_pwm, + .is_visible = it87_pwm_is_visible, +}; + +static umode_t it87_auto_pwm_is_visible(struct kobject *kobj, + struct attribute *attr, int index) { struct device *dev = container_of(kobj, struct device, kobj); struct it87_data *data = dev_get_drvdata(dev); + int i = index / 9; /* pwm index */ - if (has_pwm_freq2(data) && index == 2) - return attr->mode | S_IWUSR; + if (!(data->has_pwm & (1 << i))) + return 0; return attr->mode; } -static const struct attribute_group it87_group_pwm[6] = { - { .attrs = it87_attributes_pwm[0] }, - { .attrs = it87_attributes_pwm[1], - .is_visible = pwm_attribute_mode, }, - { .attrs = it87_attributes_pwm[2] }, - { .attrs = it87_attributes_pwm[3] }, - { .attrs = it87_attributes_pwm[4] }, - { .attrs = it87_attributes_pwm[5] }, -}; - -static struct attribute *it87_attributes_autopwm[3][9+1] = { { +static struct attribute *it87_attributes_auto_pwm[] = { &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, @@ -2039,8 +2045,7 @@ static struct attribute *it87_attributes_autopwm[3][9+1] = { { &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr, @@ -2050,8 +2055,7 @@ static struct attribute *it87_attributes_autopwm[3][9+1] = { { &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr, - NULL -}, { + &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr, @@ -2061,13 +2065,13 @@ static struct attribute *it87_attributes_autopwm[3][9+1] = { { &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr, - NULL -} }; -static const struct attribute_group it87_group_autopwm[3] = { - { .attrs = it87_attributes_autopwm[0] }, - { .attrs = it87_attributes_autopwm[1] }, - { .attrs = it87_attributes_autopwm[2] }, + NULL, +}; + +static const struct attribute_group it87_group_auto_pwm = { + .attrs = it87_attributes_auto_pwm, + .is_visible = it87_auto_pwm_is_visible, }; static struct attribute *it87_attributes_vid[] = { @@ -2456,23 +2460,15 @@ static int __init it87_find(int sioaddr, unsigned short *address, static void it87_remove_files(struct device *dev) { - struct it87_data *data = dev_get_drvdata(dev); struct it87_sio_data *sio_data = dev_get_platdata(dev); - int i; sysfs_remove_group(&dev->kobj, &it87_group); sysfs_remove_group(&dev->kobj, &it87_group_in); sysfs_remove_group(&dev->kobj, &it87_group_temp); sysfs_remove_group(&dev->kobj, &it87_group_fan); + sysfs_remove_group(&dev->kobj, &it87_group_pwm); + sysfs_remove_group(&dev->kobj, &it87_group_auto_pwm); - for (i = 0; i < 6; i++) { - if (sio_data->skip_pwm & (1 << i)) - continue; - sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]); - if (has_old_autopwm(data)) - sysfs_remove_group(&dev->kobj, - &it87_group_autopwm[i]); - } if (!sio_data->skip_vid) sysfs_remove_group(&dev->kobj, &it87_group_vid); sysfs_remove_group(&dev->kobj, &it87_group_label); @@ -2760,18 +2756,15 @@ static int it87_probe(struct platform_device *pdev) goto error; if (enable_pwm_interface) { - for (i = 0; i < 6; i++) { - if (sio_data->skip_pwm & (1 << i)) - continue; - err = sysfs_create_group(&dev->kobj, - &it87_group_pwm[i]); - if (err) - goto error; + data->has_pwm = (1 << ARRAY_SIZE(IT87_REG_PWM)) - 1; + data->has_pwm &= ~sio_data->skip_pwm; - if (!has_old_autopwm(data)) - continue; + err = sysfs_create_group(&dev->kobj, &it87_group_pwm); + if (err) + goto error; + if (has_old_autopwm(data)) { err = sysfs_create_group(&dev->kobj, - &it87_group_autopwm[i]); + &it87_group_auto_pwm); if (err) goto error; } -- GitLab From d376684880beb603a11fb6593489a21398d2a491 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 30 Mar 2013 15:47:21 -0700 Subject: [PATCH 3376/9938] hwmon: (it87) Use single group and is_visible for miscellaneous attributes Use is_visible to determine if attributes should be generated or not. This simplifies the code and reduces object size by about 120 bytes on x86_64. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 81 ++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0c13d640bcc7..e4fb466fd9c3 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -471,6 +471,7 @@ struct it87_data { unsigned long last_updated; /* In jiffies */ u16 in_scaled; /* Internal voltage sensors are scaled */ + u16 in_internal; /* Bitfield, internal sensors (for labels) */ u16 has_in; /* Bitfield, voltage sensors enabled */ u8 in[10][3]; /* [nr][0]=in, [1]=min, [2]=max */ u8 has_fan; /* Bitfield, fans enabled */ @@ -480,6 +481,7 @@ struct it87_data { u8 sensor; /* Register value (IT87_REG_TEMP_ENABLE) */ u8 extra; /* Register value (IT87_REG_TEMP_EXTRA) */ u8 fan_div[3]; /* Register encoding, shifted right */ + bool has_vid; /* True if VID supported */ u8 vid; /* Register encoding, combined */ u8 vrm; u32 alarms; /* Register encoding, combined */ @@ -1879,15 +1881,37 @@ static const struct attribute_group it87_group_temp = { .is_visible = it87_temp_is_visible, }; +static umode_t it87_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct it87_data *data = dev_get_drvdata(dev); + + if ((index == 3 || index == 4) && !data->has_vid) + return 0; + + if (index > 4 && !(data->in_internal & (1 << (index - 5)))) + return 0; + + return attr->mode; +} + static struct attribute *it87_attributes[] = { &dev_attr_alarms.attr, &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, &dev_attr_name.attr, + &dev_attr_vrm.attr, /* 3 */ + &dev_attr_cpu0_vid.attr, /* 4 */ + &sensor_dev_attr_in3_label.dev_attr.attr, /* 5 .. 8 */ + &sensor_dev_attr_in7_label.dev_attr.attr, + &sensor_dev_attr_in8_label.dev_attr.attr, + &sensor_dev_attr_in9_label.dev_attr.attr, NULL }; static const struct attribute_group it87_group = { .attrs = it87_attributes, + .is_visible = it87_is_visible, }; static umode_t it87_fan_is_visible(struct kobject *kobj, @@ -2074,28 +2098,6 @@ static const struct attribute_group it87_group_auto_pwm = { .is_visible = it87_auto_pwm_is_visible, }; -static struct attribute *it87_attributes_vid[] = { - &dev_attr_vrm.attr, - &dev_attr_cpu0_vid.attr, - NULL -}; - -static const struct attribute_group it87_group_vid = { - .attrs = it87_attributes_vid, -}; - -static struct attribute *it87_attributes_label[] = { - &sensor_dev_attr_in3_label.dev_attr.attr, - &sensor_dev_attr_in7_label.dev_attr.attr, - &sensor_dev_attr_in8_label.dev_attr.attr, - &sensor_dev_attr_in9_label.dev_attr.attr, - NULL -}; - -static const struct attribute_group it87_group_label = { - .attrs = it87_attributes_label, -}; - /* SuperIO detection - will change isa_address if a chip is found */ static int __init it87_find(int sioaddr, unsigned short *address, struct it87_sio_data *sio_data) @@ -2460,18 +2462,12 @@ static int __init it87_find(int sioaddr, unsigned short *address, static void it87_remove_files(struct device *dev) { - struct it87_sio_data *sio_data = dev_get_platdata(dev); - sysfs_remove_group(&dev->kobj, &it87_group); sysfs_remove_group(&dev->kobj, &it87_group_in); sysfs_remove_group(&dev->kobj, &it87_group_temp); sysfs_remove_group(&dev->kobj, &it87_group_fan); sysfs_remove_group(&dev->kobj, &it87_group_pwm); sysfs_remove_group(&dev->kobj, &it87_group_auto_pwm); - - if (!sio_data->skip_vid) - sysfs_remove_group(&dev->kobj, &it87_group_vid); - sysfs_remove_group(&dev->kobj, &it87_group_label); } /* Called when we have found a new IT87. */ @@ -2649,8 +2645,8 @@ static int it87_probe(struct platform_device *pdev) struct resource *res; struct device *dev = &pdev->dev; struct it87_sio_data *sio_data = dev_get_platdata(dev); - int err = 0, i; int enable_pwm_interface; + int err = 0; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, @@ -2731,6 +2727,7 @@ static int it87_probe(struct platform_device *pdev) data->has_temp &= ~(1 << 2); } + data->in_internal = sio_data->internal; data->has_in = 0x3ff & ~sio_data->skip_in; data->has_beep = !!sio_data->beep_pin; @@ -2738,6 +2735,13 @@ static int it87_probe(struct platform_device *pdev) /* Initialize the IT87 chip */ it87_init_device(pdev); + if (!sio_data->skip_vid) { + data->has_vid = true; + data->vrm = vid_which_vrm(); + /* VID reading from Super-I/O config space if available */ + data->vid = sio_data->vid_value; + } + /* Register sysfs hooks */ err = sysfs_create_group(&dev->kobj, &it87_group); if (err) @@ -2770,25 +2774,6 @@ static int it87_probe(struct platform_device *pdev) } } - if (!sio_data->skip_vid) { - data->vrm = vid_which_vrm(); - /* VID reading from Super-I/O config space if available */ - data->vid = sio_data->vid_value; - err = sysfs_create_group(&dev->kobj, &it87_group_vid); - if (err) - goto error; - } - - /* Export labels for internal sensors */ - for (i = 0; i < 4; i++) { - if (!(sio_data->internal & (1 << i))) - continue; - err = sysfs_create_file(&dev->kobj, - it87_attributes_label[i]); - if (err) - goto error; - } - data->hwmon_dev = hwmon_device_register(dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); -- GitLab From 8638d0afb4df0d3cebcd10c3056dcb4a52432941 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 30 Mar 2015 11:13:49 -0700 Subject: [PATCH 3377/9938] hwmon: (it87) Convert to use new hwmon API Convert to use devm_hwmon_device_register_with_groups to simplify code and reduce code size. This also attaches sysfs attributes to the hwmon device and no longer to the platform device. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 93 +++++++++----------------------------------- 1 file changed, 19 insertions(+), 74 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index e4fb466fd9c3..e02c972ef81e 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -458,7 +458,7 @@ struct it87_sio_data { * The structure is dynamically allocated. */ struct it87_data { - struct device *hwmon_dev; + const struct attribute_group *groups[7]; enum chips type; u16 features; u8 peci_mask; @@ -1739,14 +1739,6 @@ static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2); /* AVCC3 */ static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0); -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct it87_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - static umode_t it87_in_is_visible(struct kobject *kobj, struct attribute *attr, int index) { @@ -1887,10 +1879,10 @@ static umode_t it87_is_visible(struct kobject *kobj, struct device *dev = container_of(kobj, struct device, kobj); struct it87_data *data = dev_get_drvdata(dev); - if ((index == 3 || index == 4) && !data->has_vid) + if ((index == 2 || index == 3) && !data->has_vid) return 0; - if (index > 4 && !(data->in_internal & (1 << (index - 5)))) + if (index > 3 && !(data->in_internal & (1 << (index - 4)))) return 0; return attr->mode; @@ -1899,10 +1891,9 @@ static umode_t it87_is_visible(struct kobject *kobj, static struct attribute *it87_attributes[] = { &dev_attr_alarms.attr, &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, - &dev_attr_name.attr, - &dev_attr_vrm.attr, /* 3 */ - &dev_attr_cpu0_vid.attr, /* 4 */ - &sensor_dev_attr_in3_label.dev_attr.attr, /* 5 .. 8 */ + &dev_attr_vrm.attr, /* 2 */ + &dev_attr_cpu0_vid.attr, /* 3 */ + &sensor_dev_attr_in3_label.dev_attr.attr, /* 4 .. 7 */ &sensor_dev_attr_in7_label.dev_attr.attr, &sensor_dev_attr_in8_label.dev_attr.attr, &sensor_dev_attr_in9_label.dev_attr.attr, @@ -2460,16 +2451,6 @@ static int __init it87_find(int sioaddr, unsigned short *address, return err; } -static void it87_remove_files(struct device *dev) -{ - sysfs_remove_group(&dev->kobj, &it87_group); - sysfs_remove_group(&dev->kobj, &it87_group_in); - sysfs_remove_group(&dev->kobj, &it87_group_temp); - sysfs_remove_group(&dev->kobj, &it87_group_fan); - sysfs_remove_group(&dev->kobj, &it87_group_pwm); - sysfs_remove_group(&dev->kobj, &it87_group_auto_pwm); -} - /* Called when we have found a new IT87. */ static void it87_init_device(struct platform_device *pdev) { @@ -2646,7 +2627,7 @@ static int it87_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct it87_sio_data *sio_data = dev_get_platdata(dev); int enable_pwm_interface; - int err = 0; + struct device *hwmon_dev; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, @@ -2666,7 +2647,6 @@ static int it87_probe(struct platform_device *pdev) data->features = it87_devices[sio_data->type].features; data->peci_mask = it87_devices[sio_data->type].peci_mask; data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask; - data->name = it87_devices[sio_data->type].name; /* * IT8705F Datasheet 0.4.1, 3h == Version G. * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. @@ -2742,59 +2722,25 @@ static int it87_probe(struct platform_device *pdev) data->vid = sio_data->vid_value; } - /* Register sysfs hooks */ - err = sysfs_create_group(&dev->kobj, &it87_group); - if (err) - return err; - - err = sysfs_create_group(&dev->kobj, &it87_group_in); - if (err) - goto error; - - err = sysfs_create_group(&dev->kobj, &it87_group_temp); - if (err) - goto error; - - err = sysfs_create_group(&dev->kobj, &it87_group_fan); - if (err) - goto error; + /* Prepare for sysfs hooks */ + data->groups[0] = &it87_group; + data->groups[1] = &it87_group_in; + data->groups[2] = &it87_group_temp; + data->groups[3] = &it87_group_fan; if (enable_pwm_interface) { data->has_pwm = (1 << ARRAY_SIZE(IT87_REG_PWM)) - 1; data->has_pwm &= ~sio_data->skip_pwm; - err = sysfs_create_group(&dev->kobj, &it87_group_pwm); - if (err) - goto error; - if (has_old_autopwm(data)) { - err = sysfs_create_group(&dev->kobj, - &it87_group_auto_pwm); - if (err) - goto error; - } - } - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error; + data->groups[4] = &it87_group_pwm; + if (has_old_autopwm(data)) + data->groups[5] = &it87_group_auto_pwm; } - return 0; - -error: - it87_remove_files(dev); - return err; -} - -static int it87_remove(struct platform_device *pdev) -{ - struct it87_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - it87_remove_files(&pdev->dev); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, + it87_devices[sio_data->type].name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static struct platform_driver it87_driver = { @@ -2802,7 +2748,6 @@ static struct platform_driver it87_driver = { .name = DRVNAME, }, .probe = it87_probe, - .remove = it87_remove, }; static int __init it87_device_add(int index, unsigned short address, -- GitLab From cc18da79d9b7faf1ec617e2478d57d25d7b2f93a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 1 Apr 2015 10:03:01 -0700 Subject: [PATCH 3378/9938] hwmon: (it87) Support up to 6 temperature sensors on IT8620E Add support for the additional temperature sensors on IT8620E. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 48 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index e02c972ef81e..722d6de62d1c 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -219,7 +219,7 @@ static bool fix_pwm_polarity; #define IT87_REG_FAN_DIV 0x0b #define IT87_REG_FAN_16BIT 0x0c -/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */ +/* Monitors: 9 voltage (0 to 7, battery), 6 temp (1 to 6), 3 fan (1 to 3) */ static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82, 0x4c }; static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86, 0x4e }; @@ -252,10 +252,12 @@ static const u8 IT87_REG_PWM_DUTY[] = { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab }; #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) #define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) +#define IT87_REG_TEMP456_ENABLE 0x77 + struct it87_devices { const char *name; const char * const suffix; - u16 features; + u32 features; u8 peci_mask; u8 old_peci_mask; }; @@ -276,6 +278,7 @@ struct it87_devices { #define FEAT_AVCC3 (1 << 13) /* Chip supports in9/AVCC3 */ #define FEAT_SIX_PWM (1 << 14) /* Chip supports 6 pwm chn */ #define FEAT_PWM_FREQ2 (1 << 15) /* Separate pwm freq 2 */ +#define FEAT_SIX_TEMP (1 << 16) /* Up to 6 temp sensors */ static const struct it87_devices it87_devices[] = { [it87] = { @@ -412,7 +415,8 @@ static const struct it87_devices it87_devices[] = { .suffix = "E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS - | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2, + | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2 + | FEAT_SIX_TEMP, .peci_mask = 0x07, }, }; @@ -437,6 +441,7 @@ static const struct it87_devices it87_devices[] = { #define has_avcc3(data) ((data)->features & FEAT_AVCC3) #define has_six_pwm(data) ((data)->features & FEAT_SIX_PWM) #define has_pwm_freq2(data) ((data)->features & FEAT_PWM_FREQ2) +#define has_six_temp(data) ((data)->features & FEAT_SIX_TEMP) struct it87_sio_data { enum chips type; @@ -477,7 +482,7 @@ struct it87_data { u8 has_fan; /* Bitfield, fans enabled */ u16 fan[6][2]; /* Register values, [nr][0]=fan, [1]=min */ u8 has_temp; /* Bitfield, temp sensors enabled */ - s8 temp[3][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */ + s8 temp[6][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */ u8 sensor; /* Register value (IT87_REG_TEMP_ENABLE) */ u8 extra; /* Register value (IT87_REG_TEMP_EXTRA) */ u8 fan_div[3]; /* Register encoding, shifted right */ @@ -704,11 +709,16 @@ static struct it87_data *it87_update_device(struct device *dev) IT87_REG_FANX_MIN[i]) << 8; } } - for (i = 0; i < 3; i++) { + for (i = 0; i < 6; i++) { if (!(data->has_temp & (1 << i))) continue; data->temp[i][0] = it87_read_value(data, IT87_REG_TEMP(i)); + + /* No limits/offset for additional sensors */ + if (i >= 3) + continue; + data->temp[i][1] = it87_read_value(data, IT87_REG_TEMP_LOW(i)); data->temp[i][2] = @@ -848,7 +858,7 @@ static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in, static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0); static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0); -/* 3 temperatures */ +/* Up to 6 temperatures */ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) { @@ -921,6 +931,9 @@ static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, 2, 2); static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp, set_temp, 2, 3); +static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0); +static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0); +static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0); static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, char *buf) @@ -1828,6 +1841,11 @@ static umode_t it87_temp_is_visible(struct kobject *kobj, int i = index / 7; /* temperature index */ int a = index % 7; /* attribute index */ + if (index >= 21) { + i = index - 21 + 3; + a = 0; + } + if (!(data->has_temp & (1 << i))) return 0; @@ -1849,7 +1867,7 @@ static struct attribute *it87_attributes_temp[] = { &sensor_dev_attr_temp1_offset.dev_attr.attr, /* 5 */ &sensor_dev_attr_temp1_beep.dev_attr.attr, /* 6 */ - &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, /* 7 */ &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_type.dev_attr.attr, @@ -1857,7 +1875,7 @@ static struct attribute *it87_attributes_temp[] = { &sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp2_beep.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, /* 14 */ &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp3_type.dev_attr.attr, @@ -1865,6 +1883,9 @@ static struct attribute *it87_attributes_temp[] = { &sensor_dev_attr_temp3_offset.dev_attr.attr, &sensor_dev_attr_temp3_beep.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, /* 21 */ + &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, NULL }; @@ -2710,6 +2731,17 @@ static int it87_probe(struct platform_device *pdev) data->in_internal = sio_data->internal; data->has_in = 0x3ff & ~sio_data->skip_in; + if (has_six_temp(data)) { + u8 reg = it87_read_value(data, IT87_REG_TEMP456_ENABLE); + + if ((reg & 0x03) >= 0x02) + data->has_temp |= (1 << 3); + if (((reg >> 2) & 0x03) >= 0x02) + data->has_temp |= (1 << 4); + if (((reg >> 4) & 0x03) >= 0x02) + data->has_temp |= (1 << 5); + } + data->has_beep = !!sio_data->beep_pin; /* Initialize the IT87 chip */ -- GitLab From 559313c4e9b29f5d0ba246f69d1052ef2fd9b423 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 1 Apr 2015 10:15:38 -0700 Subject: [PATCH 3379/9938] hwmon: (it87) Simplify reading voltage registers Voltage registers are non-sequential. Use a register array instead of a macro to map sensor index to register to simplify the code and to make it easier to add additional voltage sensors. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 722d6de62d1c..aa3ec50527a3 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -232,10 +232,10 @@ static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 }; static const u8 IT87_REG_PWM[] = { 0x15, 0x16, 0x17, 0x7f, 0xa7, 0xaf }; static const u8 IT87_REG_PWM_DUTY[] = { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab }; -#define IT87_REG_VIN(nr) (0x20 + (nr)) -#define IT87_REG_TEMP(nr) (0x29 + (nr)) +static const u8 IT87_REG_VIN[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x2f }; -#define IT87_REG_AVCC3 0x2f +#define IT87_REG_TEMP(nr) (0x29 + (nr)) #define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2) #define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2) @@ -679,18 +679,22 @@ static struct it87_data *it87_update_device(struct device *dev) it87_write_value(data, IT87_REG_CONFIG, it87_read_value(data, IT87_REG_CONFIG) | 0x40); } - for (i = 0; i <= 7; i++) { + for (i = 0; i < ARRAY_SIZE(IT87_REG_VIN); i++) { + if (!(data->has_in & (1 << i))) + continue; + data->in[i][0] = - it87_read_value(data, IT87_REG_VIN(i)); + it87_read_value(data, IT87_REG_VIN[i]); + + /* VBAT and AVCC don't have limit registers */ + if (i >= 8) + continue; + data->in[i][1] = it87_read_value(data, IT87_REG_VIN_MIN(i)); data->in[i][2] = it87_read_value(data, IT87_REG_VIN_MAX(i)); } - /* in8 (battery) has no limit registers */ - data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8)); - if (has_avcc3(data)) - data->in[9][0] = it87_read_value(data, IT87_REG_AVCC3); for (i = 0; i < 6; i++) { /* Skip disabled fans */ -- GitLab From f838aa2611045fb1409c461fdd5102a6d8ae79f2 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 1 Apr 2015 20:09:36 -0700 Subject: [PATCH 3380/9938] hwmon: (it87) Add support for VIN7 to VIN10 on IT8620E IT8620E supports three additional voltage sensors. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index aa3ec50527a3..96876755376c 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -219,7 +219,12 @@ static bool fix_pwm_polarity; #define IT87_REG_FAN_DIV 0x0b #define IT87_REG_FAN_16BIT 0x0c -/* Monitors: 9 voltage (0 to 7, battery), 6 temp (1 to 6), 3 fan (1 to 3) */ +/* + * Monitors: + * - up to 13 voltage (0 to 7, battery, avcc, 10 to 12) + * - up to 6 temp (1 to 6) + * - up to 6 fan (1 to 6) + */ static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82, 0x4c }; static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86, 0x4e }; @@ -233,7 +238,7 @@ static const u8 IT87_REG_PWM[] = { 0x15, 0x16, 0x17, 0x7f, 0xa7, 0xaf }; static const u8 IT87_REG_PWM_DUTY[] = { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab }; static const u8 IT87_REG_VIN[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, - 0x27, 0x28, 0x2f }; + 0x27, 0x28, 0x2f, 0x2c, 0x2d, 0x2e }; #define IT87_REG_TEMP(nr) (0x29 + (nr)) @@ -478,7 +483,7 @@ struct it87_data { u16 in_scaled; /* Internal voltage sensors are scaled */ u16 in_internal; /* Bitfield, internal sensors (for labels) */ u16 has_in; /* Bitfield, voltage sensors enabled */ - u8 in[10][3]; /* [nr][0]=in, [1]=min, [2]=max */ + u8 in[13][3]; /* [nr][0]=in, [1]=min, [2]=max */ u8 has_fan; /* Bitfield, fans enabled */ u16 fan[6][2]; /* Register values, [nr][0]=fan, [1]=min */ u8 has_temp; /* Bitfield, temp sensors enabled */ @@ -861,6 +866,9 @@ static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in, static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0); static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0); +static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in, NULL, 10, 0); +static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in, NULL, 11, 0); +static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in, NULL, 12, 0); /* Up to 6 temperatures */ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, @@ -1764,7 +1772,7 @@ static umode_t it87_in_is_visible(struct kobject *kobj, int i = index / 5; /* voltage index */ int a = index % 5; /* attribute index */ - if (index >= 40) { /* in8, in9 only have input attributes */ + if (index >= 40) { /* in8 and higher only have input attributes */ i = index - 40 + 8; a = 0; } @@ -1828,8 +1836,10 @@ static struct attribute *it87_attributes_in[] = { &sensor_dev_attr_in7_beep.dev_attr.attr, /* 39 */ &sensor_dev_attr_in8_input.dev_attr.attr, /* 40 */ - &sensor_dev_attr_in9_input.dev_attr.attr, /* 41 */ + &sensor_dev_attr_in10_input.dev_attr.attr, /* 41 */ + &sensor_dev_attr_in11_input.dev_attr.attr, /* 41 */ + &sensor_dev_attr_in12_input.dev_attr.attr, /* 41 */ }; static const struct attribute_group it87_group_in = { @@ -2738,12 +2748,21 @@ static int it87_probe(struct platform_device *pdev) if (has_six_temp(data)) { u8 reg = it87_read_value(data, IT87_REG_TEMP456_ENABLE); + /* Check for additional temperature sensors */ if ((reg & 0x03) >= 0x02) data->has_temp |= (1 << 3); if (((reg >> 2) & 0x03) >= 0x02) data->has_temp |= (1 << 4); if (((reg >> 4) & 0x03) >= 0x02) data->has_temp |= (1 << 5); + + /* Check for additional voltage sensors */ + if ((reg & 0x03) == 0x01) + data->has_in |= (1 << 10); + if (((reg >> 2) & 0x03) == 0x01) + data->has_in |= (1 << 11); + if (((reg >> 4) & 0x03) == 0x01) + data->has_in |= (1 << 12); } data->has_beep = !!sio_data->beep_pin; -- GitLab From 48b2ae7fe9d0eba523a3633ff0f939aba9e962e2 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 2 Apr 2015 08:06:12 -0700 Subject: [PATCH 3381/9938] hwmon: (it87) Use BIT macro Using the BIT macro makes the code a little easier to read and has the added benefit of making checkpatch happy. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 290 ++++++++++++++++++++++--------------------- 1 file changed, 146 insertions(+), 144 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 96876755376c..0d6d106d53a2 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -52,6 +52,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -267,23 +268,23 @@ struct it87_devices { u8 old_peci_mask; }; -#define FEAT_12MV_ADC (1 << 0) -#define FEAT_NEWER_AUTOPWM (1 << 1) -#define FEAT_OLD_AUTOPWM (1 << 2) -#define FEAT_16BIT_FANS (1 << 3) -#define FEAT_TEMP_OFFSET (1 << 4) -#define FEAT_TEMP_PECI (1 << 5) -#define FEAT_TEMP_OLD_PECI (1 << 6) -#define FEAT_FAN16_CONFIG (1 << 7) /* Need to enable 16-bit fans */ -#define FEAT_FIVE_FANS (1 << 8) /* Supports five fans */ -#define FEAT_VID (1 << 9) /* Set if chip supports VID */ -#define FEAT_IN7_INTERNAL (1 << 10) /* Set if in7 is internal */ -#define FEAT_SIX_FANS (1 << 11) /* Supports six fans */ -#define FEAT_10_9MV_ADC (1 << 12) -#define FEAT_AVCC3 (1 << 13) /* Chip supports in9/AVCC3 */ -#define FEAT_SIX_PWM (1 << 14) /* Chip supports 6 pwm chn */ -#define FEAT_PWM_FREQ2 (1 << 15) /* Separate pwm freq 2 */ -#define FEAT_SIX_TEMP (1 << 16) /* Up to 6 temp sensors */ +#define FEAT_12MV_ADC BIT(0) +#define FEAT_NEWER_AUTOPWM BIT(1) +#define FEAT_OLD_AUTOPWM BIT(2) +#define FEAT_16BIT_FANS BIT(3) +#define FEAT_TEMP_OFFSET BIT(4) +#define FEAT_TEMP_PECI BIT(5) +#define FEAT_TEMP_OLD_PECI BIT(6) +#define FEAT_FAN16_CONFIG BIT(7) /* Need to enable 16-bit fans */ +#define FEAT_FIVE_FANS BIT(8) /* Supports five fans */ +#define FEAT_VID BIT(9) /* Set if chip supports VID */ +#define FEAT_IN7_INTERNAL BIT(10) /* Set if in7 is internal */ +#define FEAT_SIX_FANS BIT(11) /* Supports six fans */ +#define FEAT_10_9MV_ADC BIT(12) +#define FEAT_AVCC3 BIT(13) /* Chip supports in9/AVCC3 */ +#define FEAT_SIX_PWM BIT(14) /* Chip supports 6 pwm chn */ +#define FEAT_PWM_FREQ2 BIT(15) /* Separate pwm freq 2 */ +#define FEAT_SIX_TEMP BIT(16) /* Up to 6 temp sensors */ static const struct it87_devices it87_devices[] = { [it87] = { @@ -433,10 +434,10 @@ static const struct it87_devices it87_devices[] = { #define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM) #define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET) #define has_temp_peci(data, nr) (((data)->features & FEAT_TEMP_PECI) && \ - ((data)->peci_mask & (1 << nr))) + ((data)->peci_mask & BIT(nr))) #define has_temp_old_peci(data, nr) \ (((data)->features & FEAT_TEMP_OLD_PECI) && \ - ((data)->old_peci_mask & (1 << nr))) + ((data)->old_peci_mask & BIT(nr))) #define has_fan16_config(data) ((data)->features & FEAT_FAN16_CONFIG) #define has_five_fans(data) ((data)->features & (FEAT_FIVE_FANS | \ FEAT_SIX_FANS)) @@ -530,7 +531,7 @@ static int adc_lsb(const struct it87_data *data, int nr) lsb = 109; else lsb = 160; - if (data->in_scaled & (1 << nr)) + if (data->in_scaled & BIT(nr)) lsb <<= 1; return lsb; } @@ -595,7 +596,8 @@ static int DIV_TO_REG(int val) answer++; return answer; } -#define DIV_FROM_REG(val) (1 << (val)) + +#define DIV_FROM_REG(val) BIT(val) /* * PWM base frequencies. The frequency has to be divided by either 128 or 256, @@ -685,7 +687,7 @@ static struct it87_data *it87_update_device(struct device *dev) it87_read_value(data, IT87_REG_CONFIG) | 0x40); } for (i = 0; i < ARRAY_SIZE(IT87_REG_VIN); i++) { - if (!(data->has_in & (1 << i))) + if (!(data->has_in & BIT(i))) continue; data->in[i][0] = @@ -703,7 +705,7 @@ static struct it87_data *it87_update_device(struct device *dev) for (i = 0; i < 6; i++) { /* Skip disabled fans */ - if (!(data->has_fan & (1 << i))) + if (!(data->has_fan & BIT(i))) continue; data->fan[i][1] = @@ -719,7 +721,7 @@ static struct it87_data *it87_update_device(struct device *dev) } } for (i = 0; i < 6; i++) { - if (!(data->has_temp & (1 << i))) + if (!(data->has_temp & BIT(i))) continue; data->temp[i][0] = it87_read_value(data, IT87_REG_TEMP(i)); @@ -1026,7 +1028,7 @@ static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type, static int pwm_mode(const struct it87_data *data, int nr) { - int ctrl = data->fan_main_ctrl & (1 << nr); + int ctrl = data->fan_main_ctrl & BIT(nr); if (ctrl == 0 && data->type != it8603) /* Full speed */ return 0; @@ -1059,7 +1061,7 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index; struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); + return sprintf(buf, "%lu\n", DIV_FROM_REG(data->fan_div[nr])); } static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) @@ -1243,9 +1245,9 @@ static ssize_t set_pwm_enable(struct device *dev, int tmp; /* make sure the fan is on when in on/off mode */ tmp = it87_read_value(data, IT87_REG_FAN_CTL); - it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); + it87_write_value(data, IT87_REG_FAN_CTL, tmp | BIT(nr)); /* set on/off mode */ - data->fan_main_ctrl &= ~(1 << nr); + data->fan_main_ctrl &= ~BIT(nr); it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); } else { @@ -1259,7 +1261,7 @@ static ssize_t set_pwm_enable(struct device *dev, if (data->type != it8603) { /* set SmartGuardian mode */ - data->fan_main_ctrl |= (1 << nr); + data->fan_main_ctrl |= BIT(nr); it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); } @@ -1353,7 +1355,7 @@ static ssize_t show_pwm_temp_map(struct device *dev, int map; if (data->pwm_temp_map[nr] < 3) - map = 1 << data->pwm_temp_map[nr]; + map = BIT(data->pwm_temp_map[nr]); else map = 0; /* Should never happen */ return sprintf(buf, "%d\n", map); @@ -1372,13 +1374,13 @@ static ssize_t set_pwm_temp_map(struct device *dev, return -EINVAL; switch (val) { - case (1 << 0): + case BIT(0): reg = 0x00; break; - case (1 << 1): + case BIT(1): reg = 0x01; break; - case (1 << 2): + case BIT(2): reg = 0x02; break; default: @@ -1625,7 +1627,7 @@ static ssize_t clear_intrusion(struct device *dev, struct device_attribute if (config < 0) { count = config; } else { - config |= 1 << 5; + config |= BIT(5); it87_write_value(data, IT87_REG_CONFIG, config); /* Invalidate cache to force re-read */ data->valid = 0; @@ -1676,9 +1678,9 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); if (val) - data->beeps |= (1 << bitnr); + data->beeps |= BIT(bitnr); else - data->beeps &= ~(1 << bitnr); + data->beeps &= ~BIT(bitnr); it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps); mutex_unlock(&data->update_lock); return count; @@ -1777,7 +1779,7 @@ static umode_t it87_in_is_visible(struct kobject *kobj, a = 0; } - if (!(data->has_in & (1 << i))) + if (!(data->has_in & BIT(i))) return 0; if (a == 4 && !data->has_beep) @@ -1860,7 +1862,7 @@ static umode_t it87_temp_is_visible(struct kobject *kobj, a = 0; } - if (!(data->has_temp & (1 << i))) + if (!(data->has_temp & BIT(i))) return 0; if (a == 5 && !has_temp_offset(data)) @@ -1917,7 +1919,7 @@ static umode_t it87_is_visible(struct kobject *kobj, if ((index == 2 || index == 3) && !data->has_vid) return 0; - if (index > 3 && !(data->in_internal & (1 << (index - 4)))) + if (index > 3 && !(data->in_internal & BIT(index - 4))) return 0; return attr->mode; @@ -1953,7 +1955,7 @@ static umode_t it87_fan_is_visible(struct kobject *kobj, a = (index - 15) % 4; } - if (!(data->has_fan & (1 << i))) + if (!(data->has_fan & BIT(i))) return 0; if (a == 3) { /* beep */ @@ -2019,7 +2021,7 @@ static umode_t it87_pwm_is_visible(struct kobject *kobj, int i = index / 4; /* pwm index */ int a = index % 4; /* attribute index */ - if (!(data->has_pwm & (1 << i))) + if (!(data->has_pwm & BIT(i))) return 0; /* pwmX_auto_channels_temp is only writable for old auto pwm */ @@ -2079,7 +2081,7 @@ static umode_t it87_auto_pwm_is_visible(struct kobject *kobj, struct it87_data *data = dev_get_drvdata(dev); int i = index / 9; /* pwm index */ - if (!(data->has_pwm & (1 << i))) + if (!(data->has_pwm & BIT(i))) return 0; return attr->mode; @@ -2223,19 +2225,19 @@ static int __init it87_find(int sioaddr, unsigned short *address, /* in7 (VSB or VCCH5V) is always internal on some chips */ if (has_in7_internal(config)) - sio_data->internal |= (1 << 1); + sio_data->internal |= BIT(1); /* in8 (Vbat) is always internal */ - sio_data->internal |= (1 << 2); + sio_data->internal |= BIT(2); /* in9 (AVCC3), always internal if supported */ if (has_avcc3(config)) - sio_data->internal |= (1 << 3); /* in9 is AVCC */ + sio_data->internal |= BIT(3); /* in9 is AVCC */ else - sio_data->skip_in |= (1 << 9); + sio_data->skip_in |= BIT(9); if (!has_six_pwm(config)) - sio_data->skip_pwm |= (1 << 3) | (1 << 4) | (1 << 5); + sio_data->skip_pwm |= BIT(3) | BIT(4) | BIT(5); if (!has_vid(config)) sio_data->skip_vid = 1; @@ -2258,31 +2260,31 @@ static int __init it87_find(int sioaddr, unsigned short *address, regef = superio_inb(sioaddr, IT87_SIO_SPI_REG); /* Check if fan3 is there or not */ - if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2))) - sio_data->skip_fan |= (1 << 2); - if ((reg25 & (1 << 4)) - || (!(reg2a & (1 << 1)) && (regef & (1 << 0)))) - sio_data->skip_pwm |= (1 << 2); + if ((reg27 & BIT(0)) || !(reg2c & BIT(2))) + sio_data->skip_fan |= BIT(2); + if ((reg25 & BIT(4)) + || (!(reg2a & BIT(1)) && (regef & BIT(0)))) + sio_data->skip_pwm |= BIT(2); /* Check if fan2 is there or not */ - if (reg27 & (1 << 7)) - sio_data->skip_fan |= (1 << 1); - if (reg27 & (1 << 3)) - sio_data->skip_pwm |= (1 << 1); + if (reg27 & BIT(7)) + sio_data->skip_fan |= BIT(1); + if (reg27 & BIT(3)) + sio_data->skip_pwm |= BIT(1); /* VIN5 */ - if ((reg27 & (1 << 0)) || (reg2c & (1 << 2))) - sio_data->skip_in |= (1 << 5); /* No VIN5 */ + if ((reg27 & BIT(0)) || (reg2c & BIT(2))) + sio_data->skip_in |= BIT(5); /* No VIN5 */ /* VIN6 */ - if (reg27 & (1 << 1)) - sio_data->skip_in |= (1 << 6); /* No VIN6 */ + if (reg27 & BIT(1)) + sio_data->skip_in |= BIT(6); /* No VIN6 */ /* * VIN7 * Does not depend on bit 2 of Reg2C, contrary to datasheet. */ - if (reg27 & (1 << 2)) { + if (reg27 & BIT(2)) { /* * The data sheet is a bit unclear regarding the * internal voltage divider for VCCH5V. It says @@ -2296,8 +2298,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, * not the case, and ask the user to report if the * resulting voltage is sane. */ - if (!(reg2c & (1 << 1))) { - reg2c |= (1 << 1); + if (!(reg2c & BIT(1))) { + reg2c |= BIT(1); superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg2c); pr_notice("Routing internal VCCH5V to in7.\n"); @@ -2306,10 +2308,10 @@ static int __init it87_find(int sioaddr, unsigned short *address, pr_notice("Please report if it displays a reasonable voltage.\n"); } - if (reg2c & (1 << 0)) - sio_data->internal |= (1 << 0); - if (reg2c & (1 << 1)) - sio_data->internal |= (1 << 1); + if (reg2c & BIT(0)) + sio_data->internal |= BIT(0); + if (reg2c & BIT(1)) + sio_data->internal |= BIT(1); sio_data->beep_pin = superio_inb(sioaddr, IT87_SIO_BEEP_PIN_REG) & 0x3f; @@ -2321,20 +2323,20 @@ static int __init it87_find(int sioaddr, unsigned short *address, reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); /* Check if fan3 is there or not */ - if (reg27 & (1 << 6)) - sio_data->skip_pwm |= (1 << 2); - if (reg27 & (1 << 7)) - sio_data->skip_fan |= (1 << 2); + if (reg27 & BIT(6)) + sio_data->skip_pwm |= BIT(2); + if (reg27 & BIT(7)) + sio_data->skip_fan |= BIT(2); /* Check if fan2 is there or not */ reg29 = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); - if (reg29 & (1 << 1)) - sio_data->skip_pwm |= (1 << 1); - if (reg29 & (1 << 2)) - sio_data->skip_fan |= (1 << 1); + if (reg29 & BIT(1)) + sio_data->skip_pwm |= BIT(1); + if (reg29 & BIT(2)) + sio_data->skip_fan |= BIT(1); - sio_data->skip_in |= (1 << 5); /* No VIN5 */ - sio_data->skip_in |= (1 << 6); /* No VIN6 */ + sio_data->skip_in |= BIT(5); /* No VIN5 */ + sio_data->skip_in |= BIT(6); /* No VIN6 */ sio_data->beep_pin = superio_inb(sioaddr, IT87_SIO_BEEP_PIN_REG) & 0x3f; @@ -2345,38 +2347,38 @@ static int __init it87_find(int sioaddr, unsigned short *address, /* Check for pwm5 */ reg = superio_inb(sioaddr, IT87_SIO_GPIO1_REG); - if (reg & (1 << 6)) - sio_data->skip_pwm |= (1 << 4); + if (reg & BIT(6)) + sio_data->skip_pwm |= BIT(4); /* Check for fan4, fan5 */ reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG); - if (!(reg & (1 << 5))) - sio_data->skip_fan |= (1 << 3); - if (!(reg & (1 << 4))) - sio_data->skip_fan |= (1 << 4); + if (!(reg & BIT(5))) + sio_data->skip_fan |= BIT(3); + if (!(reg & BIT(4))) + sio_data->skip_fan |= BIT(4); /* Check for pwm3, fan3 */ reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); - if (reg & (1 << 6)) - sio_data->skip_pwm |= (1 << 2); - if (reg & (1 << 7)) - sio_data->skip_fan |= (1 << 2); + if (reg & BIT(6)) + sio_data->skip_pwm |= BIT(2); + if (reg & BIT(7)) + sio_data->skip_fan |= BIT(2); /* Check for pwm4 */ reg = superio_inb(sioaddr, IT87_SIO_GPIO4_REG); - if (!(reg & (1 << 2))) - sio_data->skip_pwm |= (1 << 3); + if (!(reg & BIT(2))) + sio_data->skip_pwm |= BIT(3); /* Check for pwm2, fan2 */ reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); - if (reg & (1 << 1)) - sio_data->skip_pwm |= (1 << 1); - if (reg & (1 << 2)) - sio_data->skip_fan |= (1 << 1); + if (reg & BIT(1)) + sio_data->skip_pwm |= BIT(1); + if (reg & BIT(2)) + sio_data->skip_fan |= BIT(1); /* Check for pwm6, fan6 */ - if (!(reg & (1 << 7))) { - sio_data->skip_pwm |= (1 << 5); - sio_data->skip_fan |= (1 << 5); + if (!(reg & BIT(7))) { + sio_data->skip_pwm |= BIT(5); + sio_data->skip_fan |= BIT(5); } sio_data->beep_pin = superio_inb(sioaddr, @@ -2397,17 +2399,17 @@ static int __init it87_find(int sioaddr, unsigned short *address, } /* Check if fan3 is there or not */ - if (reg & (1 << 6)) - sio_data->skip_pwm |= (1 << 2); - if (reg & (1 << 7)) - sio_data->skip_fan |= (1 << 2); + if (reg & BIT(6)) + sio_data->skip_pwm |= BIT(2); + if (reg & BIT(7)) + sio_data->skip_fan |= BIT(2); /* Check if fan2 is there or not */ reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); - if (reg & (1 << 1)) - sio_data->skip_pwm |= (1 << 1); - if (reg & (1 << 2)) - sio_data->skip_fan |= (1 << 1); + if (reg & BIT(1)) + sio_data->skip_pwm |= BIT(1); + if (reg & BIT(2)) + sio_data->skip_fan |= BIT(1); if ((sio_data->type == it8718 || sio_data->type == it8720) && !(sio_data->skip_vid)) @@ -2416,7 +2418,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG); - uart6 = sio_data->type == it8782 && (reg & (1 << 2)); + uart6 = sio_data->type == it8782 && (reg & BIT(2)); /* * The IT8720F has no VIN7 pin, so VCCH should always be @@ -2432,15 +2434,15 @@ static int __init it87_find(int sioaddr, unsigned short *address, * If UART6 is enabled, re-route VIN7 to the internal divider * if that is not already the case. */ - if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) { - reg |= (1 << 1); + if ((sio_data->type == it8720 || uart6) && !(reg & BIT(1))) { + reg |= BIT(1); superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg); pr_notice("Routing internal VCCH to in7\n"); } - if (reg & (1 << 0)) - sio_data->internal |= (1 << 0); - if (reg & (1 << 1)) - sio_data->internal |= (1 << 1); + if (reg & BIT(0)) + sio_data->internal |= BIT(0); + if (reg & BIT(1)) + sio_data->internal |= BIT(1); /* * On IT8782F, UART6 pins overlap with VIN5, VIN6, and VIN7. @@ -2452,8 +2454,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, * temperature source here, skip_temp is preliminary. */ if (uart6) { - sio_data->skip_in |= (1 << 5) | (1 << 6); - sio_data->skip_temp |= (1 << 2); + sio_data->skip_in |= BIT(5) | BIT(6); + sio_data->skip_temp |= BIT(2); } sio_data->beep_pin = superio_inb(sioaddr, @@ -2477,7 +2479,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, * the same board is ever used in other systems. */ pr_info("Disabling pwm2 due to hardware constraints\n"); - sio_data->skip_pwm = (1 << 1); + sio_data->skip_pwm = BIT(1); } } @@ -2570,12 +2572,12 @@ static void it87_init_device(struct platform_device *pdev) /* Check for additional fans */ if (has_five_fans(data)) { - if (tmp & (1 << 4)) - data->has_fan |= (1 << 3); /* fan4 enabled */ - if (tmp & (1 << 5)) - data->has_fan |= (1 << 4); /* fan5 enabled */ - if (has_six_fans(data) && (tmp & (1 << 2))) - data->has_fan |= (1 << 5); /* fan6 enabled */ + if (tmp & BIT(4)) + data->has_fan |= BIT(3); /* fan4 enabled */ + if (tmp & BIT(5)) + data->has_fan |= BIT(4); /* fan5 enabled */ + if (has_six_fans(data) && (tmp & BIT(2))) + data->has_fan |= BIT(5); /* fan6 enabled */ } /* Fan input pins may be used for alternative functions */ @@ -2586,9 +2588,9 @@ static void it87_init_device(struct platform_device *pdev) /* The following code may be IT8620E specific */ tmp = it87_read_value(data, IT87_REG_FAN_DIV); if ((tmp & 0xc0) == 0xc0) - sio_data->skip_pwm |= (1 << 4); - if (!(tmp & (1 << 3))) - sio_data->skip_pwm |= (1 << 5); + sio_data->skip_pwm |= BIT(4); + if (!(tmp & BIT(3))) + sio_data->skip_pwm |= BIT(5); } /* Start monitoring */ @@ -2719,27 +2721,27 @@ static int it87_probe(struct platform_device *pdev) /* Starting with IT8721F, we handle scaling of internal voltages */ if (has_12mv_adc(data)) { - if (sio_data->internal & (1 << 0)) - data->in_scaled |= (1 << 3); /* in3 is AVCC */ - if (sio_data->internal & (1 << 1)) - data->in_scaled |= (1 << 7); /* in7 is VSB */ - if (sio_data->internal & (1 << 2)) - data->in_scaled |= (1 << 8); /* in8 is Vbat */ - if (sio_data->internal & (1 << 3)) - data->in_scaled |= (1 << 9); /* in9 is AVCC */ + if (sio_data->internal & BIT(0)) + data->in_scaled |= BIT(3); /* in3 is AVCC */ + if (sio_data->internal & BIT(1)) + data->in_scaled |= BIT(7); /* in7 is VSB */ + if (sio_data->internal & BIT(2)) + data->in_scaled |= BIT(8); /* in8 is Vbat */ + if (sio_data->internal & BIT(3)) + data->in_scaled |= BIT(9); /* in9 is AVCC */ } else if (sio_data->type == it8781 || sio_data->type == it8782 || sio_data->type == it8783) { - if (sio_data->internal & (1 << 0)) - data->in_scaled |= (1 << 3); /* in3 is VCC5V */ - if (sio_data->internal & (1 << 1)) - data->in_scaled |= (1 << 7); /* in7 is VCCH5V */ + if (sio_data->internal & BIT(0)) + data->in_scaled |= BIT(3); /* in3 is VCC5V */ + if (sio_data->internal & BIT(1)) + data->in_scaled |= BIT(7); /* in7 is VCCH5V */ } data->has_temp = 0x07; - if (sio_data->skip_temp & (1 << 2)) { + if (sio_data->skip_temp & BIT(2)) { if (sio_data->type == it8782 && !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80)) - data->has_temp &= ~(1 << 2); + data->has_temp &= ~BIT(2); } data->in_internal = sio_data->internal; @@ -2750,19 +2752,19 @@ static int it87_probe(struct platform_device *pdev) /* Check for additional temperature sensors */ if ((reg & 0x03) >= 0x02) - data->has_temp |= (1 << 3); + data->has_temp |= BIT(3); if (((reg >> 2) & 0x03) >= 0x02) - data->has_temp |= (1 << 4); + data->has_temp |= BIT(4); if (((reg >> 4) & 0x03) >= 0x02) - data->has_temp |= (1 << 5); + data->has_temp |= BIT(5); /* Check for additional voltage sensors */ if ((reg & 0x03) == 0x01) - data->has_in |= (1 << 10); + data->has_in |= BIT(10); if (((reg >> 2) & 0x03) == 0x01) - data->has_in |= (1 << 11); + data->has_in |= BIT(11); if (((reg >> 4) & 0x03) == 0x01) - data->has_in |= (1 << 12); + data->has_in |= BIT(12); } data->has_beep = !!sio_data->beep_pin; @@ -2784,7 +2786,7 @@ static int it87_probe(struct platform_device *pdev) data->groups[3] = &it87_group_fan; if (enable_pwm_interface) { - data->has_pwm = (1 << ARRAY_SIZE(IT87_REG_PWM)) - 1; + data->has_pwm = BIT(ARRAY_SIZE(IT87_REG_PWM)) - 1; data->has_pwm &= ~sio_data->skip_pwm; data->groups[4] = &it87_group_pwm; -- GitLab From 2310048db70a58ae89b37fded0322b6a5ae6443f Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 2 Apr 2015 08:23:45 -0700 Subject: [PATCH 3382/9938] hwmon: (it87) Use defines for array sizes and sensor counts Using array size defines makes it much easier to find errors in index values and loop counts. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 58 ++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0d6d106d53a2..118d4c756e40 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -260,6 +260,16 @@ static const u8 IT87_REG_VIN[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, #define IT87_REG_TEMP456_ENABLE 0x77 +#define NUM_VIN ARRAY_SIZE(IT87_REG_VIN) +#define NUM_VIN_LIMIT 8 +#define NUM_TEMP 6 +#define NUM_TEMP_OFFSET ARRAY_SIZE(IT87_REG_TEMP_OFFSET) +#define NUM_TEMP_LIMIT 3 +#define NUM_FAN ARRAY_SIZE(IT87_REG_FAN) +#define NUM_FAN_DIV 3 +#define NUM_PWM ARRAY_SIZE(IT87_REG_PWM) +#define NUM_AUTO_PWM ARRAY_SIZE(IT87_REG_PWM) + struct it87_devices { const char *name; const char * const suffix; @@ -484,14 +494,14 @@ struct it87_data { u16 in_scaled; /* Internal voltage sensors are scaled */ u16 in_internal; /* Bitfield, internal sensors (for labels) */ u16 has_in; /* Bitfield, voltage sensors enabled */ - u8 in[13][3]; /* [nr][0]=in, [1]=min, [2]=max */ + u8 in[NUM_VIN][3]; /* [nr][0]=in, [1]=min, [2]=max */ u8 has_fan; /* Bitfield, fans enabled */ - u16 fan[6][2]; /* Register values, [nr][0]=fan, [1]=min */ + u16 fan[NUM_FAN][2]; /* Register values, [nr][0]=fan, [1]=min */ u8 has_temp; /* Bitfield, temp sensors enabled */ - s8 temp[6][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */ + s8 temp[NUM_TEMP][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */ u8 sensor; /* Register value (IT87_REG_TEMP_ENABLE) */ u8 extra; /* Register value (IT87_REG_TEMP_EXTRA) */ - u8 fan_div[3]; /* Register encoding, shifted right */ + u8 fan_div[NUM_FAN_DIV];/* Register encoding, shifted right */ bool has_vid; /* True if VID supported */ u8 vid; /* Register encoding, combined */ u8 vrm; @@ -512,13 +522,13 @@ struct it87_data { * simple. */ u8 has_pwm; /* Bitfield, pwm control enabled */ - u8 pwm_ctrl[6]; /* Register value */ - u8 pwm_duty[6]; /* Manual PWM value set by user */ - u8 pwm_temp_map[6]; /* PWM to temp. chan. mapping (bits 1-0) */ + u8 pwm_ctrl[NUM_PWM]; /* Register value */ + u8 pwm_duty[NUM_PWM]; /* Manual PWM value set by user */ + u8 pwm_temp_map[NUM_PWM];/* PWM to temp. chan. mapping (bits 1-0) */ /* Automatic fan speed control registers */ - u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */ - s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ + u8 auto_pwm[NUM_AUTO_PWM][4]; /* [nr][3] is hard-coded */ + s8 auto_temp[NUM_AUTO_PWM][5]; /* [nr][0] is point1_temp_hyst */ }; static int adc_lsb(const struct it87_data *data, int nr) @@ -686,7 +696,7 @@ static struct it87_data *it87_update_device(struct device *dev) it87_write_value(data, IT87_REG_CONFIG, it87_read_value(data, IT87_REG_CONFIG) | 0x40); } - for (i = 0; i < ARRAY_SIZE(IT87_REG_VIN); i++) { + for (i = 0; i < NUM_VIN; i++) { if (!(data->has_in & BIT(i))) continue; @@ -694,7 +704,7 @@ static struct it87_data *it87_update_device(struct device *dev) it87_read_value(data, IT87_REG_VIN[i]); /* VBAT and AVCC don't have limit registers */ - if (i >= 8) + if (i >= NUM_VIN_LIMIT) continue; data->in[i][1] = @@ -703,7 +713,7 @@ static struct it87_data *it87_update_device(struct device *dev) it87_read_value(data, IT87_REG_VIN_MAX(i)); } - for (i = 0; i < 6; i++) { + for (i = 0; i < NUM_FAN; i++) { /* Skip disabled fans */ if (!(data->has_fan & BIT(i))) continue; @@ -720,24 +730,24 @@ static struct it87_data *it87_update_device(struct device *dev) IT87_REG_FANX_MIN[i]) << 8; } } - for (i = 0; i < 6; i++) { + for (i = 0; i < NUM_TEMP; i++) { if (!(data->has_temp & BIT(i))) continue; data->temp[i][0] = it87_read_value(data, IT87_REG_TEMP(i)); - /* No limits/offset for additional sensors */ - if (i >= 3) + if (has_temp_offset(data) && i < NUM_TEMP_OFFSET) + data->temp[i][3] = + it87_read_value(data, + IT87_REG_TEMP_OFFSET[i]); + + if (i >= NUM_TEMP_LIMIT) continue; data->temp[i][1] = it87_read_value(data, IT87_REG_TEMP_LOW(i)); data->temp[i][2] = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); - if (has_temp_offset(data)) - data->temp[i][3] = - it87_read_value(data, - IT87_REG_TEMP_OFFSET[i]); } /* Newer chips don't have clock dividers */ @@ -757,7 +767,7 @@ static struct it87_data *it87_update_device(struct device *dev) data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); - for (i = 0; i < 6; i++) + for (i = 0; i < NUM_PWM; i++) it87_update_pwm_ctrl(data, i); data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); @@ -2509,7 +2519,7 @@ static void it87_init_device(struct platform_device *pdev) * these have separate registers for the temperature mapping and the * manual duty cycle. */ - for (i = 0; i < 3; i++) { + for (i = 0; i < NUM_AUTO_PWM; i++) { data->pwm_temp_map[i] = i; data->pwm_duty[i] = 0x7f; /* Full speed */ data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */ @@ -2522,12 +2532,12 @@ static void it87_init_device(struct platform_device *pdev) * means -1 degree C, which surprisingly doesn't trigger an alarm, * but is still confusing, so change to 127 degrees C. */ - for (i = 0; i < 8; i++) { + for (i = 0; i < NUM_VIN_LIMIT; i++) { tmp = it87_read_value(data, IT87_REG_VIN_MIN(i)); if (tmp == 0xff) it87_write_value(data, IT87_REG_VIN_MIN(i), 0); } - for (i = 0; i < 3; i++) { + for (i = 0; i < NUM_TEMP_LIMIT; i++) { tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); if (tmp == 0xff) it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); @@ -2620,7 +2630,7 @@ static int it87_check_pwm(struct device *dev) int i; u8 pwm[3]; - for (i = 0; i < 3; i++) + for (i = 0; i < ARRAY_SIZE(pwm); i++) pwm[i] = it87_read_value(data, IT87_REG_PWM[i]); -- GitLab From c962024e306ed598600853854a067b521bf5b530 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 4 Apr 2015 09:05:57 -0700 Subject: [PATCH 3383/9938] hwmon: (it87) Formatting cleanup Fix various checkpatch complaints to clean up the code and make it easier to read. CHECK: Do not include the paragraph about writing to the FSF CHECK: Alignment should match open parenthesis CHECK: Logical continuations should be on the previous line CHECK: No space is necessary after a cast CHECK: Please don't use multiple blank lines CHECK: Please use a blank line after function/struct/union/enum declarations CHECK: spaces preferred around that '+' (ctx:VxV) WARNING: Missing a blank line after declarations No functional change. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 155 ++++++++++++++++++++++--------------------- 1 file changed, 80 insertions(+), 75 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 118d4c756e40..515c5cd1890b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -44,10 +44,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -108,6 +104,7 @@ static inline void superio_outb(int ioreg, int reg, int val) static int superio_inw(int ioreg, int reg) { int val; + outb(reg++, ioreg); val = inb(ioreg + 1) << 8; outb(reg, ioreg); @@ -598,10 +595,10 @@ static int pwm_from_reg(const struct it87_data *data, u8 reg) return (reg & 0x7f) << 1; } - static int DIV_TO_REG(int val) { int answer = 0; + while (answer < 7 && (val >>= 1)) answer++; return answer; @@ -686,8 +683,8 @@ static struct it87_data *it87_update_device(struct device *dev) mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { if (update_vbat) { /* * Cleared after each update, so reenable. Value @@ -798,10 +795,10 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, char *buf) { struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int nr = sattr->nr; + struct it87_data *data = it87_update_device(dev); int index = sattr->index; + int nr = sattr->nr; - struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr][index])); } @@ -809,10 +806,9 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int nr = sattr->nr; - int index = sattr->index; - struct it87_data *data = dev_get_drvdata(dev); + int index = sattr->index; + int nr = sattr->nr; unsigned long val; if (kstrtoul(buf, 10, &val) < 0) @@ -968,8 +964,8 @@ static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, u8 reg = data->sensor; /* In case value is updated while used */ u8 extra = data->extra; - if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) - || (has_temp_old_peci(data, nr) && (extra & 0x80))) + if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) || + (has_temp_old_peci(data, nr) && (extra & 0x80))) return sprintf(buf, "6\n"); /* Intel PECI */ if (reg & (1 << nr)) return sprintf(buf, "3\n"); /* thermal diode */ @@ -1065,35 +1061,38 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, } static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct it87_data *data = it87_update_device(dev); int nr = sensor_attr->index; - struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%lu\n", DIV_FROM_REG(data->fan_div[nr])); } + static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct it87_data *data = it87_update_device(dev); int nr = sensor_attr->index; - struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%d\n", pwm_mode(data, nr)); } + static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct it87_data *data = it87_update_device(dev); int nr = sensor_attr->index; - struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%d\n", pwm_from_reg(data, data->pwm_duty[nr])); } + static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); struct it87_data *data = it87_update_device(dev); @@ -1157,12 +1156,11 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, } static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = dev_get_drvdata(dev); + int nr = sensor_attr->index; unsigned long val; int min; u8 old; @@ -1227,13 +1225,12 @@ static int check_trip_points(struct device *dev, int nr) return err; } -static ssize_t set_pwm_enable(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = dev_get_drvdata(dev); + int nr = sensor_attr->index; long val; if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 2) @@ -1280,13 +1277,13 @@ static ssize_t set_pwm_enable(struct device *dev, mutex_unlock(&data->update_lock); return count; } + static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = dev_get_drvdata(dev); + int nr = sensor_attr->index; long val; if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255) @@ -1320,8 +1317,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, mutex_unlock(&data->update_lock); return count; } -static ssize_t set_pwm_freq(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + +static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); struct it87_data *data = dev_get_drvdata(dev); @@ -1337,7 +1335,7 @@ static ssize_t set_pwm_freq(struct device *dev, /* Search for the nearest available frequency */ for (i = 0; i < 7; i++) { - if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) + if (val > (pwm_freq[i] + pwm_freq[i + 1]) / 2) break; } @@ -1355,13 +1353,13 @@ static ssize_t set_pwm_freq(struct device *dev, return count; } + static ssize_t show_pwm_temp_map(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = it87_update_device(dev); + int nr = sensor_attr->index; int map; if (data->pwm_temp_map[nr] < 3) @@ -1370,13 +1368,14 @@ static ssize_t show_pwm_temp_map(struct device *dev, map = 0; /* Should never happen */ return sprintf(buf, "%d\n", map); } + static ssize_t set_pwm_temp_map(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, const char *buf, + size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = dev_get_drvdata(dev); + int nr = sensor_attr->index; long val; u8 reg; @@ -1411,8 +1410,8 @@ static ssize_t set_pwm_temp_map(struct device *dev, return count; } -static ssize_t show_auto_pwm(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_auto_pwm(struct device *dev, struct device_attribute *attr, + char *buf) { struct it87_data *data = it87_update_device(dev); struct sensor_device_attribute_2 *sensor_attr = @@ -1424,8 +1423,8 @@ static ssize_t show_auto_pwm(struct device *dev, pwm_from_reg(data, data->auto_pwm[nr][point])); } -static ssize_t set_auto_pwm(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_auto_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct it87_data *data = dev_get_drvdata(dev); struct sensor_device_attribute_2 *sensor_attr = @@ -1445,8 +1444,8 @@ static ssize_t set_auto_pwm(struct device *dev, return count; } -static ssize_t show_auto_temp(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_auto_temp(struct device *dev, struct device_attribute *attr, + char *buf) { struct it87_data *data = it87_update_device(dev); struct sensor_device_attribute_2 *sensor_attr = @@ -1457,8 +1456,8 @@ static ssize_t show_auto_temp(struct device *dev, return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point])); } -static ssize_t set_auto_temp(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_auto_temp(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct it87_data *data = dev_get_drvdata(dev); struct sensor_device_attribute_2 *sensor_attr = @@ -1607,27 +1606,30 @@ static SENSOR_DEVICE_ATTR(pwm6_auto_channels_temp, S_IRUGO, /* Alarms */ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%u\n", data->alarms); } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { - int bitnr = to_sensor_dev_attr(attr)->index; struct it87_data *data = it87_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); } -static ssize_t clear_intrusion(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) +static ssize_t clear_intrusion(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct it87_data *data = dev_get_drvdata(dev); - long val; int config; + long val; if (kstrtol(buf, 10, &val) < 0 || val != 0) return -EINVAL; @@ -1668,21 +1670,22 @@ static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm, clear_intrusion, 4); static ssize_t show_beep(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { - int bitnr = to_sensor_dev_attr(attr)->index; struct it87_data *data = it87_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1); } + static ssize_t set_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { int bitnr = to_sensor_dev_attr(attr)->index; struct it87_data *data = dev_get_drvdata(dev); long val; - if (kstrtol(buf, 10, &val) < 0 - || (val != 0 && val != 1)) + if (kstrtol(buf, 10, &val) < 0 || (val != 0 && val != 1)) return -EINVAL; mutex_lock(&data->update_lock); @@ -1718,13 +1721,15 @@ static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2); static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct it87_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%u\n", data->vrm); } + static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct it87_data *data = dev_get_drvdata(dev); unsigned long val; @@ -1739,15 +1744,16 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); + + return sprintf(buf, "%ld\n", (long)vid_from_reg(data->vid, data->vrm)); } static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_label(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { static const char * const labels[] = { "+5V", @@ -2272,8 +2278,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, /* Check if fan3 is there or not */ if ((reg27 & BIT(0)) || !(reg2c & BIT(2))) sio_data->skip_fan |= BIT(2); - if ((reg25 & BIT(4)) - || (!(reg2a & BIT(1)) && (regef & BIT(0)))) + if ((reg25 & BIT(4)) || + (!(reg2a & BIT(1)) && (regef & BIT(0)))) sio_data->skip_pwm |= BIT(2); /* Check if fan2 is there or not */ @@ -2421,8 +2427,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, if (reg & BIT(2)) sio_data->skip_fan |= BIT(1); - if ((sio_data->type == it8718 || sio_data->type == it8720) - && !(sio_data->skip_vid)) + if ((sio_data->type == it8718 || sio_data->type == it8720) && + !(sio_data->skip_vid)) sio_data->vid_value = superio_inb(sioaddr, IT87_SIO_VID_REG); @@ -2478,8 +2484,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); board_name = dmi_get_system_info(DMI_BOARD_NAME); if (board_vendor && board_name) { - if (strcmp(board_vendor, "nVIDIA") == 0 - && strcmp(board_name, "FN68PT") == 0) { + if (strcmp(board_vendor, "nVIDIA") == 0 && + strcmp(board_name, "FN68PT") == 0) { /* * On the Shuttle SN68PT, FAN_CTL2 is apparently not * connected to a fan, but to something else. One user @@ -2718,8 +2724,8 @@ static int it87_probe(struct platform_device *pdev) } /* Now, we do the remaining detection. */ - if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) - || it87_read_value(data, IT87_REG_CHIPID) != 0x90) + if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) || + it87_read_value(data, IT87_REG_CHIPID) != 0x90) return -ENODEV; platform_set_drvdata(pdev, data); @@ -2749,8 +2755,8 @@ static int it87_probe(struct platform_device *pdev) data->has_temp = 0x07; if (sio_data->skip_temp & BIT(2)) { - if (sio_data->type == it8782 - && !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80)) + if (sio_data->type == it8782 && + !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80)) data->has_temp &= ~BIT(2); } @@ -2911,7 +2917,6 @@ static void __exit sm_it87_exit(void) platform_driver_unregister(&it87_driver); } - MODULE_AUTHOR("Chris Gauthron, Jean Delvare "); MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver"); module_param(update_vbat, bool, 0); -- GitLab From f1bbe618604a4aa833a4af0b1ecdfb47a25455c6 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 5 Apr 2015 13:16:54 -0700 Subject: [PATCH 3384/9938] hwmon: (it87) Support disabling fan control for all pwm control and chips On/Off mode is only supported for pwm controls 0-2, and not supported at all for IT8603E/IT8623E. For pwm controls 3-6 and for IT8603E/IT8623E, SmartGuardian mode is always enabled. Use it and set the pwm value to the maximum if fan control is disabled. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 52 ++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 515c5cd1890b..f40d81a0a9fc 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -1030,18 +1030,19 @@ static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type, static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type, set_temp_type, 2); -/* 3 Fans */ +/* 6 Fans */ static int pwm_mode(const struct it87_data *data, int nr) { - int ctrl = data->fan_main_ctrl & BIT(nr); + if (data->type != it8603 && nr < 3 && !(data->fan_main_ctrl & BIT(nr))) + return 0; /* Full speed */ + if (data->pwm_ctrl[nr] & 0x80) + return 2; /* Automatic mode */ + if ((data->type == it8603 || nr >= 3) && + data->pwm_duty[nr] == pwm_to_reg(data, 0xff)) + return 0; /* Full speed */ - if (ctrl == 0 && data->type != it8603) /* Full speed */ - return 0; - if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ - return 2; - else /* Manual mode */ - return 1; + return 1; /* Manual mode */ } static ssize_t show_fan(struct device *dev, struct device_attribute *attr, @@ -1242,21 +1243,30 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, return -EINVAL; } - /* IT8603E does not have on/off mode */ - if (val == 0 && data->type == it8603) - return -EINVAL; - mutex_lock(&data->update_lock); if (val == 0) { - int tmp; - /* make sure the fan is on when in on/off mode */ - tmp = it87_read_value(data, IT87_REG_FAN_CTL); - it87_write_value(data, IT87_REG_FAN_CTL, tmp | BIT(nr)); - /* set on/off mode */ - data->fan_main_ctrl &= ~BIT(nr); - it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, - data->fan_main_ctrl); + if (nr < 3 && data->type != it8603) { + int tmp; + /* make sure the fan is on when in on/off mode */ + tmp = it87_read_value(data, IT87_REG_FAN_CTL); + it87_write_value(data, IT87_REG_FAN_CTL, tmp | BIT(nr)); + /* set on/off mode */ + data->fan_main_ctrl &= ~BIT(nr); + it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, + data->fan_main_ctrl); + } else { + /* No on/off mode, set maximum pwm value */ + data->pwm_duty[nr] = pwm_to_reg(data, 0xff); + it87_write_value(data, IT87_REG_PWM_DUTY[nr], + data->pwm_duty[nr]); + /* and set manual mode */ + data->pwm_ctrl[nr] = has_newer_autopwm(data) ? + data->pwm_temp_map[nr] : + data->pwm_duty[nr]; + it87_write_value(data, IT87_REG_PWM[nr], + data->pwm_ctrl[nr]); + } } else { if (val == 1) /* Manual mode */ data->pwm_ctrl[nr] = has_newer_autopwm(data) ? @@ -1266,7 +1276,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]); - if (data->type != it8603) { + if (data->type != it8603 && nr < 3) { /* set SmartGuardian mode */ data->fan_main_ctrl |= BIT(nr); it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, -- GitLab From a0df926d33232f311d6a4d834391fec21b60db30 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 5 Apr 2015 16:51:36 -0700 Subject: [PATCH 3385/9938] hwmon: (it87) Enhance validation for fan4 and fan5 Several of the chips supported by this driver have a configuration register to enable fan4 and fan5. Use those registers to determine if fan4 and fan5 tachometers are supported. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index f40d81a0a9fc..5adb269918fb 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -2415,6 +2415,29 @@ static int __init it87_find(int sioaddr, unsigned short *address, superio_select(sioaddr, GPIO); + /* Check for fan4, fan5 */ + if (has_five_fans(config)) { + reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG); + switch (sio_data->type) { + case it8718: + if (reg & BIT(5)) + sio_data->skip_fan |= BIT(3); + if (reg & BIT(4)) + sio_data->skip_fan |= BIT(4); + break; + case it8720: + case it8721: + case it8728: + if (!(reg & BIT(5))) + sio_data->skip_fan |= BIT(3); + if (!(reg & BIT(4))) + sio_data->skip_fan |= BIT(4); + break; + default: + break; + } + } + reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); if (!sio_data->skip_vid) { /* We need at least 4 VID pins */ -- GitLab From 2cbb9c370fe32b5de5243f7338dc6ce8747d495b Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 5 Apr 2015 11:53:29 -0700 Subject: [PATCH 3386/9938] hwmon: (it87) Support automatic pwm control on newer chips Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 201 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 187 insertions(+), 14 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 5adb269918fb..e3fbcf49afdb 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -252,8 +252,10 @@ static const u8 IT87_REG_VIN[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, #define IT87_REG_CHIPID 0x58 -#define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) -#define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) +static const u8 IT87_REG_AUTO_BASE[] = { 0x60, 0x68, 0x70, 0x78, 0xa0, 0xa8 }; + +#define IT87_REG_AUTO_TEMP(nr, i) (IT87_REG_AUTO_BASE[nr] + (i)) +#define IT87_REG_AUTO_PWM(nr, i) (IT87_REG_AUTO_BASE[nr] + 5 + (i)) #define IT87_REG_TEMP456_ENABLE 0x77 @@ -673,6 +675,30 @@ static void it87_update_pwm_ctrl(struct it87_data *data, int nr) for (i = 0; i < 3 ; i++) data->auto_pwm[nr][i] = it87_read_value(data, IT87_REG_AUTO_PWM(nr, i)); + } else if (has_newer_autopwm(data)) { + int i; + + /* + * 0: temperature hysteresis (base + 5) + * 1: fan off temperature (base + 0) + * 2: fan start temperature (base + 1) + * 3: fan max temperature (base + 2) + */ + data->auto_temp[nr][0] = + it87_read_value(data, IT87_REG_AUTO_TEMP(nr, 5)); + + for (i = 0; i < 3 ; i++) + data->auto_temp[nr][i + 1] = + it87_read_value(data, + IT87_REG_AUTO_TEMP(nr, i)); + /* + * 0: start pwm value (base + 3) + * 1: pwm slope (base + 4, 1/8th pwm) + */ + data->auto_pwm[nr][0] = + it87_read_value(data, IT87_REG_AUTO_TEMP(nr, 3)); + data->auto_pwm[nr][1] = + it87_read_value(data, IT87_REG_AUTO_TEMP(nr, 4)); } } @@ -1216,6 +1242,11 @@ static int check_trip_points(struct device *dev, int nr) if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1]) err = -EINVAL; } + } else if (has_newer_autopwm(data)) { + for (i = 1; i < 3; i++) { + if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1]) + err = -EINVAL; + } } if (err) { @@ -1441,6 +1472,7 @@ static ssize_t set_auto_pwm(struct device *dev, struct device_attribute *attr, to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int point = sensor_attr->index; + int regaddr; long val; if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255) @@ -1448,8 +1480,41 @@ static ssize_t set_auto_pwm(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->auto_pwm[nr][point] = pwm_to_reg(data, val); - it87_write_value(data, IT87_REG_AUTO_PWM(nr, point), - data->auto_pwm[nr][point]); + if (has_newer_autopwm(data)) + regaddr = IT87_REG_AUTO_TEMP(nr, 3); + else + regaddr = IT87_REG_AUTO_PWM(nr, point); + it87_write_value(data, regaddr, data->auto_pwm[nr][point]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_auto_pwm_slope(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct it87_data *data = it87_update_device(dev); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + + return sprintf(buf, "%d\n", data->auto_pwm[nr][1] & 0x7f); +} + +static ssize_t set_auto_pwm_slope(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct it87_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + unsigned long val; + + if (kstrtoul(buf, 10, &val) < 0 || val > 127) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->auto_pwm[nr][1] = (data->auto_pwm[nr][1] & 0x80) | val; + it87_write_value(data, IT87_REG_AUTO_TEMP(nr, 4), + data->auto_pwm[nr][1]); mutex_unlock(&data->update_lock); return count; } @@ -1462,8 +1527,14 @@ static ssize_t show_auto_temp(struct device *dev, struct device_attribute *attr, to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int point = sensor_attr->index; + int reg; + + if (has_old_autopwm(data) || point) + reg = data->auto_temp[nr][point]; + else + reg = data->auto_temp[nr][1] - (data->auto_temp[nr][0] & 0x1f); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point])); + return sprintf(buf, "%d\n", TEMP_FROM_REG(reg)); } static ssize_t set_auto_temp(struct device *dev, struct device_attribute *attr, @@ -1475,14 +1546,24 @@ static ssize_t set_auto_temp(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->nr; int point = sensor_attr->index; long val; + int reg; if (kstrtol(buf, 10, &val) < 0 || val < -128000 || val > 127000) return -EINVAL; mutex_lock(&data->update_lock); - data->auto_temp[nr][point] = TEMP_TO_REG(val); - it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), - data->auto_temp[nr][point]); + if (has_newer_autopwm(data) && !point) { + reg = data->auto_temp[nr][1] - TEMP_TO_REG(val); + reg = clamp_val(reg, 0, 0x1f) | (data->auto_temp[nr][0] & 0xe0); + data->auto_temp[nr][0] = reg; + it87_write_value(data, IT87_REG_AUTO_TEMP(nr, 5), reg); + } else { + reg = TEMP_TO_REG(val); + data->auto_temp[nr][point] = reg; + if (has_newer_autopwm(data)) + point--; + it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), reg); + } mutex_unlock(&data->update_lock); return count; } @@ -1542,6 +1623,10 @@ static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, 0, 3); static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, 0, 4); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_start, S_IRUGO | S_IWUSR, + show_auto_pwm, set_auto_pwm, 0, 0); +static SENSOR_DEVICE_ATTR(pwm1_auto_slope, S_IRUGO | S_IWUSR, + show_auto_pwm_slope, set_auto_pwm_slope, 0); static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 1); @@ -1567,6 +1652,10 @@ static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, 1, 3); static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, 1, 4); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_start, S_IRUGO | S_IWUSR, + show_auto_pwm, set_auto_pwm, 1, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_slope, S_IRUGO | S_IWUSR, + show_auto_pwm_slope, set_auto_pwm_slope, 1); static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 2); @@ -1592,6 +1681,10 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, 2, 3); static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, 2, 4); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_start, S_IRUGO | S_IWUSR, + show_auto_pwm, set_auto_pwm, 2, 0); +static SENSOR_DEVICE_ATTR(pwm3_auto_slope, S_IRUGO | S_IWUSR, + show_auto_pwm_slope, set_auto_pwm_slope, 2); static SENSOR_DEVICE_ATTR(pwm4_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 3); @@ -1599,6 +1692,18 @@ static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 3); static SENSOR_DEVICE_ATTR(pwm4_freq, S_IRUGO, show_pwm_freq, NULL, 3); static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 3); +static SENSOR_DEVICE_ATTR_2(pwm4_auto_point1_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 1); +static SENSOR_DEVICE_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 0); +static SENSOR_DEVICE_ATTR_2(pwm4_auto_point2_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 2); +static SENSOR_DEVICE_ATTR_2(pwm4_auto_point3_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 3); +static SENSOR_DEVICE_ATTR_2(pwm4_auto_start, S_IRUGO | S_IWUSR, + show_auto_pwm, set_auto_pwm, 3, 0); +static SENSOR_DEVICE_ATTR(pwm4_auto_slope, S_IRUGO | S_IWUSR, + show_auto_pwm_slope, set_auto_pwm_slope, 3); static SENSOR_DEVICE_ATTR(pwm5_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 4); @@ -1606,6 +1711,18 @@ static SENSOR_DEVICE_ATTR(pwm5, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 4); static SENSOR_DEVICE_ATTR(pwm5_freq, S_IRUGO, show_pwm_freq, NULL, 4); static SENSOR_DEVICE_ATTR(pwm5_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 4); +static SENSOR_DEVICE_ATTR_2(pwm5_auto_point1_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 1); +static SENSOR_DEVICE_ATTR_2(pwm5_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 0); +static SENSOR_DEVICE_ATTR_2(pwm5_auto_point2_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 2); +static SENSOR_DEVICE_ATTR_2(pwm5_auto_point3_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 3); +static SENSOR_DEVICE_ATTR_2(pwm5_auto_start, S_IRUGO | S_IWUSR, + show_auto_pwm, set_auto_pwm, 4, 0); +static SENSOR_DEVICE_ATTR(pwm5_auto_slope, S_IRUGO | S_IWUSR, + show_auto_pwm_slope, set_auto_pwm_slope, 4); static SENSOR_DEVICE_ATTR(pwm6_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable, 5); @@ -1613,6 +1730,18 @@ static SENSOR_DEVICE_ATTR(pwm6, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 5); static SENSOR_DEVICE_ATTR(pwm6_freq, S_IRUGO, show_pwm_freq, NULL, 5); static SENSOR_DEVICE_ATTR(pwm6_auto_channels_temp, S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, 5); +static SENSOR_DEVICE_ATTR_2(pwm6_auto_point1_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 1); +static SENSOR_DEVICE_ATTR_2(pwm6_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 0); +static SENSOR_DEVICE_ATTR_2(pwm6_auto_point2_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 2); +static SENSOR_DEVICE_ATTR_2(pwm6_auto_point3_temp, S_IRUGO | S_IWUSR, + show_auto_temp, set_auto_temp, 2, 3); +static SENSOR_DEVICE_ATTR_2(pwm6_auto_start, S_IRUGO | S_IWUSR, + show_auto_pwm, set_auto_pwm, 5, 0); +static SENSOR_DEVICE_ATTR(pwm6_auto_slope, S_IRUGO | S_IWUSR, + show_auto_pwm_slope, set_auto_pwm_slope, 5); /* Alarms */ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, @@ -2050,8 +2179,8 @@ static umode_t it87_pwm_is_visible(struct kobject *kobj, if (!(data->has_pwm & BIT(i))) return 0; - /* pwmX_auto_channels_temp is only writable for old auto pwm */ - if (a == 3 && has_old_autopwm(data)) + /* pwmX_auto_channels_temp is only writable if auto pwm is supported */ + if (a == 3 && (has_old_autopwm(data) || has_newer_autopwm(data))) return attr->mode | S_IWUSR; /* pwm2_freq is writable if there are two pwm frequency selects */ @@ -2105,11 +2234,28 @@ static umode_t it87_auto_pwm_is_visible(struct kobject *kobj, { struct device *dev = container_of(kobj, struct device, kobj); struct it87_data *data = dev_get_drvdata(dev); - int i = index / 9; /* pwm index */ + int i = index / 11; /* pwm index */ + int a = index % 11; /* attribute index */ + + if (index >= 33) { /* pwm 4..6 */ + i = (index - 33) / 6 + 3; + a = (index - 33) % 6 + 4; + } if (!(data->has_pwm & BIT(i))) return 0; + if (has_newer_autopwm(data)) { + if (a < 4) /* no auto point pwm */ + return 0; + if (a == 8) /* no auto_point4 */ + return 0; + } + if (has_old_autopwm(data)) { + if (a >= 9) /* no pwm_auto_start, pwm_auto_slope */ + return 0; + } + return attr->mode; } @@ -2123,8 +2269,10 @@ static struct attribute *it87_attributes_auto_pwm[] = { &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_start.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_slope.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, /* 11 */ &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr, @@ -2133,8 +2281,10 @@ static struct attribute *it87_attributes_auto_pwm[] = { &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_start.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_slope.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, /* 22 */ &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr, @@ -2143,6 +2293,29 @@ static struct attribute *it87_attributes_auto_pwm[] = { &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_start.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_slope.dev_attr.attr, + + &sensor_dev_attr_pwm4_auto_point1_temp.dev_attr.attr, /* 33 */ + &sensor_dev_attr_pwm4_auto_point1_temp_hyst.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_start.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_slope.dev_attr.attr, + + &sensor_dev_attr_pwm5_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm5_auto_point1_temp_hyst.dev_attr.attr, + &sensor_dev_attr_pwm5_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm5_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_pwm5_auto_start.dev_attr.attr, + &sensor_dev_attr_pwm5_auto_slope.dev_attr.attr, + + &sensor_dev_attr_pwm6_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm6_auto_point1_temp_hyst.dev_attr.attr, + &sensor_dev_attr_pwm6_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm6_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_pwm6_auto_start.dev_attr.attr, + &sensor_dev_attr_pwm6_auto_slope.dev_attr.attr, NULL, }; @@ -2839,7 +3012,7 @@ static int it87_probe(struct platform_device *pdev) data->has_pwm &= ~sio_data->skip_pwm; data->groups[4] = &it87_group_pwm; - if (has_old_autopwm(data)) + if (has_old_autopwm(data) || has_newer_autopwm(data)) data->groups[5] = &it87_group_auto_pwm; } -- GitLab From 0624d861983c2cb1884ea3bafc1c534c7d2348b8 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 6 Apr 2015 21:04:18 -0700 Subject: [PATCH 3387/9938] hwmon: (it87) Fix pwm_temp_map for system with 6 pwm channels Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index e3fbcf49afdb..cde53c1109ea 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -655,8 +655,7 @@ static void it87_update_pwm_ctrl(struct it87_data *data, int nr) { data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM[nr]); if (has_newer_autopwm(data)) { - data->pwm_temp_map[nr] = (data->pwm_ctrl[nr] & 0x03) + - nr < 3 ? 0 : 3; + data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; data->pwm_duty[nr] = it87_read_value(data, IT87_REG_PWM_DUTY[nr]); } else { @@ -790,8 +789,11 @@ static struct it87_data *it87_update_device(struct device *dev) data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); - for (i = 0; i < NUM_PWM; i++) + for (i = 0; i < NUM_PWM; i++) { + if (!(data->has_pwm & BIT(i))) + continue; it87_update_pwm_ctrl(data, i); + } data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); @@ -1403,11 +1405,13 @@ static ssize_t show_pwm_temp_map(struct device *dev, int nr = sensor_attr->index; int map; - if (data->pwm_temp_map[nr] < 3) - map = BIT(data->pwm_temp_map[nr]); - else - map = 0; /* Should never happen */ - return sprintf(buf, "%d\n", map); + map = data->pwm_temp_map[nr]; + if (map >= 3) + map = 0; /* Should never happen */ + if (nr >= 3) /* pwm channels 3..6 map to temp4..6 */ + map += 3; + + return sprintf(buf, "%d\n", (int)BIT(map)); } static ssize_t set_pwm_temp_map(struct device *dev, @@ -1423,6 +1427,9 @@ static ssize_t set_pwm_temp_map(struct device *dev, if (kstrtol(buf, 10, &val) < 0) return -EINVAL; + if (nr >= 3) + val -= 3; + switch (val) { case BIT(0): reg = 0x00; -- GitLab From 71a9c23246fe68954f87787a4e6c1aa22565c326 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 18 Jan 2016 00:35:58 -0800 Subject: [PATCH 3388/9938] hwmon: (it87) Add support for IT8628E IT8628E is functionally identical to IT8620E. Tested-by: Martin Blumenstingl Signed-off-by: Guenter Roeck --- Documentation/hwmon/it87 | 15 +++++++++------ drivers/hwmon/Kconfig | 3 ++- drivers/hwmon/it87.c | 18 ++++++++++++++++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 index 733296d65449..fff6f6bf55bc 100644 --- a/Documentation/hwmon/it87 +++ b/Documentation/hwmon/it87 @@ -9,6 +9,9 @@ Supported chips: * IT8620E Prefix: 'it8620' Addresses scanned: from Super I/O config space (8 I/O ports) + * IT8628E + Prefix: 'it8628' + Addresses scanned: from Super I/O config space (8 I/O ports) Datasheet: Not publicly available * IT8705F Prefix: 'it87' @@ -114,8 +117,8 @@ motherboard models. Description ----------- -This driver implements support for the IT8603E, IT8620E, IT8623E, IT8705F, -IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F, +This driver implements support for the IT8603E, IT8620E, IT8623E, IT8628E, +IT8705F, IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F, IT8758E, IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and SiS950 chips. @@ -158,8 +161,8 @@ The IT8603E/IT8623E is a custom design, hardware monitoring part is similar to IT8728F. It only supports 3 fans, 16-bit fan mode, and the full speed mode of the fan is not supported (value 0 of pwmX_enable). -The IT8620E is another custom design, hardware monitoring part is similar to -IT8728F. It only supports 16-bit fan mode. +The IT8620E and IT8628E are custom designs, hardware monitoring part is similar +to IT8728F. It only supports 16-bit fan mode. Both chips support up to 6 fans. The IT8790E supports up to 3 fans. 16-bit fan mode is always enabled. @@ -187,8 +190,8 @@ of 0.016 volt. IT8603E, IT8721F/IT8758E and IT8728F can measure between 0 and 2.8 volts with a resolution of 0.0109 volt. The battery voltage in8 does not have limit registers. -On the IT8603E, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F, and IT8783E/F, some -voltage inputs are internal and scaled inside the chip: +On the IT8603E, IT8620E, IT8628E, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F, +and IT8783E/F, some voltage inputs are internal and scaled inside the chip: * in3 (optional) * in7 (optional for IT8781F, IT8782F, and IT8783E/F) * in8 (always) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 1b5b500ede07..ff940075bb90 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -621,7 +621,8 @@ config SENSORS_IT87 If you say yes here you get support for ITE IT8705F, IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F, IT8758E, IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, - IT8603E, IT8620E, and IT8623E sensor chips, and the SiS950 clone. + IT8603E, IT8620E, IT8623E, and IT8628E sensor chips, and the SiS950 + clone. This driver can also be built as a module. If so, the module will be called it87. diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index cde53c1109ea..730d84028260 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -13,6 +13,7 @@ * Supports: IT8603E Super I/O chip w/LPC interface * IT8620E Super I/O chip w/LPC interface * IT8623E Super I/O chip w/LPC interface + * IT8628E Super I/O chip w/LPC interface * IT8705F Super I/O chip w/LPC interface * IT8712F Super I/O chip w/LPC interface * IT8716F Super I/O chip w/LPC interface @@ -69,7 +70,7 @@ enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732, it8771, it8772, it8781, it8782, it8783, it8786, it8790, it8603, - it8620 }; + it8620, it8628 }; static unsigned short force_id; module_param(force_id, ushort, 0); @@ -160,6 +161,7 @@ static inline void superio_exit(int ioreg) #define IT8603E_DEVID 0x8603 #define IT8620E_DEVID 0x8620 #define IT8623E_DEVID 0x8623 +#define IT8628E_DEVID 0x8628 #define IT87_ACT_REG 0x30 #define IT87_BASE_REG 0x60 @@ -434,6 +436,15 @@ static const struct it87_devices it87_devices[] = { | FEAT_SIX_TEMP, .peci_mask = 0x07, }, + [it8628] = { + .name = "it8628", + .suffix = "E", + .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS + | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS + | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2 + | FEAT_SIX_TEMP, + .peci_mask = 0x07, + }, }; #define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS) @@ -2402,6 +2413,9 @@ static int __init it87_find(int sioaddr, unsigned short *address, case IT8620E_DEVID: sio_data->type = it8620; break; + case IT8628E_DEVID: + sio_data->type = it8628; + break; case 0xffff: /* No device at all */ goto exit; default: @@ -2546,7 +2560,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, sio_data->beep_pin = superio_inb(sioaddr, IT87_SIO_BEEP_PIN_REG) & 0x3f; - } else if (sio_data->type == it8620) { + } else if (sio_data->type == it8620 || sio_data->type == it8628) { int reg; superio_select(sioaddr, GPIO); -- GitLab From 7464b6e3a5fb213e7826d2fde4a2daf05abb6822 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Apr 2016 10:34:19 +0200 Subject: [PATCH 3389/9938] efi: ARM: avoid warning about phys_addr_t cast memblock_remove() takes a phys_addr_t, which may be narrower than 64 bits, causing a harmless warning: drivers/firmware/efi/arm-init.c: In function 'reserve_regions': include/linux/kernel.h:29:20: error: large integer implicitly truncated to unsigned type [-Werror=overflow] #define ULLONG_MAX (~0ULL) ^ drivers/firmware/efi/arm-init.c:152:21: note: in expansion of macro 'ULLONG_MAX' memblock_remove(0, ULLONG_MAX); This adds an explicit typecast to avoid the warning Fixes: 500899c2cc3e ("efi: ARM/arm64: ignore DT memory nodes instead of removing them") Acked-by Ard Biesheuvel Reviewed-by: Matt Fleming Signed-off-by: Arnd Bergmann Signed-off-by: Will Deacon --- drivers/firmware/efi/arm-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 5d6945b761dc..ca708fb18c1d 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -149,7 +149,7 @@ static __init void reserve_regions(void) * uses its own memory map instead. */ memblock_dump_all(); - memblock_remove(0, ULLONG_MAX); + memblock_remove(0, (phys_addr_t)ULLONG_MAX); for_each_efi_memory_desc(&memmap, md) { paddr = md->phys_addr; -- GitLab From 9ebc57cfaad21aacbc363eecead579269a46b493 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 12 Apr 2016 20:39:55 -0400 Subject: [PATCH 3390/9938] tracing: Rename check_ignore_pid() to ignore_this_task() The name "check_ignore_pid" is confusing in trying to figure out if the pid should be ignored or not. Rename it to "ignore_this_task" which is pretty straight forward, as a task (not a pid) is passed in, and should if true should be ignored. Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 05ddc0820771..598a18675a6b 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -484,7 +484,7 @@ static int cmp_pid(const void *key, const void *elt) } static bool -check_ignore_pid(struct trace_pid_list *filtered_pids, struct task_struct *task) +ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task) { pid_t search_pid; pid_t *pid; @@ -517,8 +517,8 @@ event_filter_pid_sched_switch_probe_pre(void *data, bool preempt, pid_list = rcu_dereference_sched(tr->filtered_pids); this_cpu_write(tr->trace_buffer.data->ignore_pid, - check_ignore_pid(pid_list, prev) && - check_ignore_pid(pid_list, next)); + ignore_this_task(pid_list, prev) && + ignore_this_task(pid_list, next)); } static void @@ -531,7 +531,7 @@ event_filter_pid_sched_switch_probe_post(void *data, bool preempt, pid_list = rcu_dereference_sched(tr->filtered_pids); this_cpu_write(tr->trace_buffer.data->ignore_pid, - check_ignore_pid(pid_list, next)); + ignore_this_task(pid_list, next)); } static void @@ -547,7 +547,7 @@ event_filter_pid_sched_wakeup_probe_pre(void *data, struct task_struct *task) pid_list = rcu_dereference_sched(tr->filtered_pids); this_cpu_write(tr->trace_buffer.data->ignore_pid, - check_ignore_pid(pid_list, task)); + ignore_this_task(pid_list, task)); } static void @@ -564,7 +564,7 @@ event_filter_pid_sched_wakeup_probe_post(void *data, struct task_struct *task) /* Set tracing if current is enabled */ this_cpu_write(tr->trace_buffer.data->ignore_pid, - check_ignore_pid(pid_list, current)); + ignore_this_task(pid_list, current)); } static void __ftrace_clear_event_pids(struct trace_array *tr) @@ -1561,7 +1561,7 @@ static void ignore_task_cpu(void *data) mutex_is_locked(&event_mutex)); this_cpu_write(tr->trace_buffer.data->ignore_pid, - check_ignore_pid(pid_list, current)); + ignore_this_task(pid_list, current)); } static ssize_t -- GitLab From f4d34a87e9c10f0ffd03d3548db6bfb200d06cdf Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 13 Apr 2016 16:27:49 -0400 Subject: [PATCH 3391/9938] tracing: Use pid bitmap instead of a pid array for set_event_pid In order to add the ability to let tasks that are filtered by the events have their children also be traced on fork (and then not traced on exit), convert the array into a pid bitmask. Most of the time the number of pids is only 32768 pids or a 4k bitmask, which is the same size as the default list currently is, and that list could grow if more pids are listed. This also greatly simplifies the code. Suggested-by: "H. Peter Anvin" Signed-off-by: Steven Rostedt --- kernel/trace/trace.h | 5 +- kernel/trace/trace_events.c | 221 ++++++++++++++++-------------------- 2 files changed, 102 insertions(+), 124 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 3fff4adfd431..68cbb8e10aea 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -177,9 +177,8 @@ struct trace_options { }; struct trace_pid_list { - unsigned int nr_pids; - int order; - pid_t *pids; + int pid_max; + unsigned long *pids; }; /* diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 598a18675a6b..45f7cc72bf25 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -471,23 +471,13 @@ static void ftrace_clear_events(struct trace_array *tr) mutex_unlock(&event_mutex); } -static int cmp_pid(const void *key, const void *elt) -{ - const pid_t *search_pid = key; - const pid_t *pid = elt; - - if (*search_pid == *pid) - return 0; - if (*search_pid < *pid) - return -1; - return 1; -} +/* Shouldn't this be in a header? */ +extern int pid_max; static bool ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task) { - pid_t search_pid; - pid_t *pid; + pid_t pid; /* * Return false, because if filtered_pids does not exist, @@ -496,15 +486,16 @@ ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task) if (!filtered_pids) return false; - search_pid = task->pid; + pid = task->pid; - pid = bsearch(&search_pid, filtered_pids->pids, - filtered_pids->nr_pids, sizeof(pid_t), - cmp_pid); - if (!pid) + /* + * If pid_max changed after filtered_pids was created, we + * by default ignore all pids greater than the previous pid_max. + */ + if (task->pid >= filtered_pids->pid_max) return true; - return false; + return !test_bit(task->pid, filtered_pids->pids); } static void @@ -602,7 +593,7 @@ static void __ftrace_clear_event_pids(struct trace_array *tr) /* Wait till all users are no longer using pid filtering */ synchronize_sched(); - free_pages((unsigned long)pid_list->pids, pid_list->order); + vfree(pid_list->pids); kfree(pid_list); } @@ -946,11 +937,32 @@ static void t_stop(struct seq_file *m, void *p) mutex_unlock(&event_mutex); } +static void * +p_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct trace_array *tr = m->private; + struct trace_pid_list *pid_list = rcu_dereference_sched(tr->filtered_pids); + unsigned long pid = (unsigned long)v; + + (*pos)++; + + /* pid already is +1 of the actual prevous bit */ + pid = find_next_bit(pid_list->pids, pid_list->pid_max, pid); + + /* Return pid + 1 to allow zero to be represented */ + if (pid < pid_list->pid_max) + return (void *)(pid + 1); + + return NULL; +} + static void *p_start(struct seq_file *m, loff_t *pos) __acquires(RCU) { struct trace_pid_list *pid_list; struct trace_array *tr = m->private; + unsigned long pid; + loff_t l = 0; /* * Grab the mutex, to keep calls to p_next() having the same @@ -963,10 +975,18 @@ static void *p_start(struct seq_file *m, loff_t *pos) pid_list = rcu_dereference_sched(tr->filtered_pids); - if (!pid_list || *pos >= pid_list->nr_pids) + if (!pid_list) + return NULL; + + pid = find_first_bit(pid_list->pids, pid_list->pid_max); + if (pid >= pid_list->pid_max) return NULL; - return (void *)&pid_list->pids[*pos]; + /* Return pid + 1 so that zero can be the exit value */ + for (pid++; pid && l < *pos; + pid = (unsigned long)p_next(m, (void *)pid, &l)) + ; + return (void *)pid; } static void p_stop(struct seq_file *m, void *p) @@ -976,25 +996,11 @@ static void p_stop(struct seq_file *m, void *p) mutex_unlock(&event_mutex); } -static void * -p_next(struct seq_file *m, void *v, loff_t *pos) -{ - struct trace_array *tr = m->private; - struct trace_pid_list *pid_list = rcu_dereference_sched(tr->filtered_pids); - - (*pos)++; - - if (*pos >= pid_list->nr_pids) - return NULL; - - return (void *)&pid_list->pids[*pos]; -} - static int p_show(struct seq_file *m, void *v) { - pid_t *pid = v; + unsigned long pid = (unsigned long)v - 1; - seq_printf(m, "%d\n", *pid); + seq_printf(m, "%lu\n", pid); return 0; } @@ -1543,11 +1549,6 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) return r; } -static int max_pids(struct trace_pid_list *pid_list) -{ - return (PAGE_SIZE << pid_list->order) / sizeof(pid_t); -} - static void ignore_task_cpu(void *data) { struct trace_array *tr = data; @@ -1571,7 +1572,7 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf, struct seq_file *m = filp->private_data; struct trace_array *tr = m->private; struct trace_pid_list *filtered_pids = NULL; - struct trace_pid_list *pid_list = NULL; + struct trace_pid_list *pid_list; struct trace_event_file *file; struct trace_parser parser; unsigned long val; @@ -1579,7 +1580,7 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf, ssize_t read = 0; ssize_t ret = 0; pid_t pid; - int i; + int nr_pids = 0; if (!cnt) return 0; @@ -1592,10 +1593,43 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf, return -ENOMEM; mutex_lock(&event_mutex); + filtered_pids = rcu_dereference_protected(tr->filtered_pids, + lockdep_is_held(&event_mutex)); + /* - * Load as many pids into the array before doing a - * swap from the tr->filtered_pids to the new list. + * Always recreate a new array. The write is an all or nothing + * operation. Always create a new array when adding new pids by + * the user. If the operation fails, then the current list is + * not modified. */ + pid_list = kmalloc(sizeof(*pid_list), GFP_KERNEL); + if (!pid_list) { + read = -ENOMEM; + goto out; + } + pid_list->pid_max = READ_ONCE(pid_max); + /* Only truncating will shrink pid_max */ + if (filtered_pids && filtered_pids->pid_max > pid_list->pid_max) + pid_list->pid_max = filtered_pids->pid_max; + pid_list->pids = vzalloc((pid_list->pid_max + 7) >> 3); + if (!pid_list->pids) { + kfree(pid_list); + read = -ENOMEM; + goto out; + } + if (filtered_pids) { + /* copy the current bits to the new max */ + pid = find_first_bit(filtered_pids->pids, + filtered_pids->pid_max); + while (pid < filtered_pids->pid_max) { + set_bit(pid, pid_list->pids); + pid = find_next_bit(filtered_pids->pids, + filtered_pids->pid_max, + pid + 1); + nr_pids++; + } + } + while (cnt > 0) { this_pos = 0; @@ -1613,92 +1647,35 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf, ret = -EINVAL; if (kstrtoul(parser.buffer, 0, &val)) break; - if (val > INT_MAX) + if (val >= pid_list->pid_max) break; pid = (pid_t)val; - ret = -ENOMEM; - if (!pid_list) { - pid_list = kmalloc(sizeof(*pid_list), GFP_KERNEL); - if (!pid_list) - break; - - filtered_pids = rcu_dereference_protected(tr->filtered_pids, - lockdep_is_held(&event_mutex)); - if (filtered_pids) - pid_list->order = filtered_pids->order; - else - pid_list->order = 0; - - pid_list->pids = (void *)__get_free_pages(GFP_KERNEL, - pid_list->order); - if (!pid_list->pids) - break; - - if (filtered_pids) { - pid_list->nr_pids = filtered_pids->nr_pids; - memcpy(pid_list->pids, filtered_pids->pids, - pid_list->nr_pids * sizeof(pid_t)); - } else - pid_list->nr_pids = 0; - } - - if (pid_list->nr_pids >= max_pids(pid_list)) { - pid_t *pid_page; - - pid_page = (void *)__get_free_pages(GFP_KERNEL, - pid_list->order + 1); - if (!pid_page) - break; - memcpy(pid_page, pid_list->pids, - pid_list->nr_pids * sizeof(pid_t)); - free_pages((unsigned long)pid_list->pids, pid_list->order); - - pid_list->order++; - pid_list->pids = pid_page; - } + set_bit(pid, pid_list->pids); + nr_pids++; - pid_list->pids[pid_list->nr_pids++] = pid; trace_parser_clear(&parser); ret = 0; } trace_parser_put(&parser); if (ret < 0) { - if (pid_list) - free_pages((unsigned long)pid_list->pids, pid_list->order); + vfree(pid_list->pids); kfree(pid_list); - mutex_unlock(&event_mutex); - return ret; - } - - if (!pid_list) { - mutex_unlock(&event_mutex); - return ret; + read = ret; + goto out; } - sort(pid_list->pids, pid_list->nr_pids, sizeof(pid_t), cmp_pid, NULL); - - /* Remove duplicates */ - for (i = 1; i < pid_list->nr_pids; i++) { - int start = i; - - while (i < pid_list->nr_pids && - pid_list->pids[i - 1] == pid_list->pids[i]) - i++; - - if (start != i) { - if (i < pid_list->nr_pids) { - memmove(&pid_list->pids[start], &pid_list->pids[i], - (pid_list->nr_pids - i) * sizeof(pid_t)); - pid_list->nr_pids -= i - start; - i = start; - } else - pid_list->nr_pids = start; - } + if (!nr_pids) { + /* Cleared the list of pids */ + vfree(pid_list->pids); + kfree(pid_list); + read = ret; + if (!filtered_pids) + goto out; + pid_list = NULL; } - rcu_assign_pointer(tr->filtered_pids, pid_list); list_for_each_entry(file, &tr->events, list) { @@ -1708,7 +1685,7 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf, if (filtered_pids) { synchronize_sched(); - free_pages((unsigned long)filtered_pids->pids, filtered_pids->order); + vfree(filtered_pids->pids); kfree(filtered_pids); } else { /* @@ -1745,10 +1722,12 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf, */ on_each_cpu(ignore_task_cpu, tr, 1); + out: mutex_unlock(&event_mutex); ret = read; - *ppos += read; + if (read > 0) + *ppos += read; return ret; } -- GitLab From c37775d57830a36382a9774bb84eca4ce3d019cc Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 13 Apr 2016 16:59:18 -0400 Subject: [PATCH 3392/9938] tracing: Add infrastructure to allow set_event_pid to follow children Add the infrastructure needed to have the PIDs in set_event_pid to automatically add PIDs of the children of the tasks that have their PIDs in set_event_pid. This will also remove PIDs from set_event_pid when a task exits This is implemented by adding hooks into the fork and exit tracepoints. On fork, the PIDs are added to the list, and on exit, they are removed. Add a new option called event_fork that when set, PIDs in set_event_pid will automatically get their children PIDs added when they fork, as well as any task that exits will have its PID removed from set_event_pid. This works for instances as well. Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 3 ++ kernel/trace/trace.h | 2 + kernel/trace/trace_events.c | 84 ++++++++++++++++++++++++++++++++----- 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index a2f0b9f33e9b..0d12dbde8399 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3571,6 +3571,9 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled) if (mask == TRACE_ITER_RECORD_CMD) trace_event_enable_cmd_record(enabled); + if (mask == TRACE_ITER_EVENT_FORK) + trace_event_follow_fork(tr, enabled); + if (mask == TRACE_ITER_OVERWRITE) { ring_buffer_change_overwrite(tr->trace_buffer.buffer, enabled); #ifdef CONFIG_TRACER_MAX_TRACE diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 68cbb8e10aea..2525042760e6 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -655,6 +655,7 @@ static inline void __trace_stack(struct trace_array *tr, unsigned long flags, extern cycle_t ftrace_now(int cpu); extern void trace_find_cmdline(int pid, char comm[]); +extern void trace_event_follow_fork(struct trace_array *tr, bool enable); #ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; @@ -966,6 +967,7 @@ extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf, C(STOP_ON_FREE, "disable_on_free"), \ C(IRQ_INFO, "irq-info"), \ C(MARKERS, "markers"), \ + C(EVENT_FORK, "event-fork"), \ FUNCTION_FLAGS \ FGRAPH_FLAGS \ STACK_FLAGS \ diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 45f7cc72bf25..add81dff7520 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -474,11 +474,23 @@ static void ftrace_clear_events(struct trace_array *tr) /* Shouldn't this be in a header? */ extern int pid_max; +/* Returns true if found in filter */ static bool -ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task) +find_filtered_pid(struct trace_pid_list *filtered_pids, pid_t search_pid) { - pid_t pid; + /* + * If pid_max changed after filtered_pids was created, we + * by default ignore all pids greater than the previous pid_max. + */ + if (search_pid >= filtered_pids->pid_max) + return false; + + return test_bit(search_pid, filtered_pids->pids); +} +static bool +ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task) +{ /* * Return false, because if filtered_pids does not exist, * all pids are good to trace. @@ -486,16 +498,68 @@ ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task) if (!filtered_pids) return false; - pid = task->pid; + return !find_filtered_pid(filtered_pids, task->pid); +} - /* - * If pid_max changed after filtered_pids was created, we - * by default ignore all pids greater than the previous pid_max. - */ - if (task->pid >= filtered_pids->pid_max) - return true; +static void filter_add_remove_task(struct trace_pid_list *pid_list, + struct task_struct *self, + struct task_struct *task) +{ + if (!pid_list) + return; + + /* For forks, we only add if the forking task is listed */ + if (self) { + if (!find_filtered_pid(pid_list, self->pid)) + return; + } + + /* Sorry, but we don't support pid_max changing after setting */ + if (task->pid >= pid_list->pid_max) + return; + + /* "self" is set for forks, and NULL for exits */ + if (self) + set_bit(task->pid, pid_list->pids); + else + clear_bit(task->pid, pid_list->pids); +} + +static void +event_filter_pid_sched_process_exit(void *data, struct task_struct *task) +{ + struct trace_pid_list *pid_list; + struct trace_array *tr = data; + + pid_list = rcu_dereference_sched(tr->filtered_pids); + filter_add_remove_task(pid_list, NULL, task); +} - return !test_bit(task->pid, filtered_pids->pids); +static void +event_filter_pid_sched_process_fork(void *data, + struct task_struct *self, + struct task_struct *task) +{ + struct trace_pid_list *pid_list; + struct trace_array *tr = data; + + pid_list = rcu_dereference_sched(tr->filtered_pids); + filter_add_remove_task(pid_list, self, task); +} + +void trace_event_follow_fork(struct trace_array *tr, bool enable) +{ + if (enable) { + register_trace_prio_sched_process_fork(event_filter_pid_sched_process_fork, + tr, INT_MIN); + register_trace_prio_sched_process_exit(event_filter_pid_sched_process_exit, + tr, INT_MAX); + } else { + unregister_trace_sched_process_fork(event_filter_pid_sched_process_fork, + tr); + unregister_trace_sched_process_exit(event_filter_pid_sched_process_exit, + tr); + } } static void -- GitLab From 540b589e6349779c0eeb8de82450b62a4569ffd9 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 19 Apr 2016 10:24:38 -0400 Subject: [PATCH 3393/9938] tracing: Update the documentation to describe "event-fork" option Add documentation to the ftrace.txt file in Documentation to describe the event-fork option. Also add the missing "display-graph" option now that it shows up in the trace_options file (from a previous commit). Signed-off-by: Steven Rostedt --- Documentation/trace/ftrace.txt | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt index f52f297cb406..fdf18485db2b 100644 --- a/Documentation/trace/ftrace.txt +++ b/Documentation/trace/ftrace.txt @@ -210,6 +210,11 @@ of ftrace. Here is a list of some of the key files: Note, sched_switch and sched_wake_up will also trace events listed in this file. + To have the PIDs of children of tasks with their PID in this file + added on fork, enable the "event-fork" option. That option will also + cause the PIDs of tasks to be removed from this file when the task + exits. + set_graph_function: Set a "trigger" function where tracing should start @@ -725,16 +730,14 @@ noraw nohex nobin noblock -nostacktrace trace_printk -noftrace_preempt nobranch annotate nouserstacktrace nosym-userobj noprintk-msg-only context-info -latency-format +nolatency-format sleep-time graph-time record-cmd @@ -742,7 +745,10 @@ overwrite nodisable_on_free irq-info markers +noevent-fork function-trace +nodisplay-graph +nostacktrace To disable one of the options, echo in the option prepended with "no". @@ -796,11 +802,6 @@ Here are the available options: block - When set, reading trace_pipe will not block when polled. - stacktrace - This is one of the options that changes the trace - itself. When a trace is recorded, so is the stack - of functions. This allows for back traces of - trace sites. - trace_printk - Can disable trace_printk() from writing into the buffer. branch - Enable branch tracing with the tracer. @@ -897,6 +898,10 @@ x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6] When disabled, the trace_marker will error with EINVAL on write. + event-fork - When set, tasks with PIDs listed in set_event_pid will have + the PIDs of their children added to set_event_pid when those + tasks fork. Also, when tasks with PIDs in set_event_pid exit, + their PIDs will be removed from the file. function-trace - The latency tracers will enable function tracing if this option is enabled (default it is). When @@ -904,8 +909,17 @@ x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6] functions. This keeps the overhead of the tracer down when performing latency tests. - Note: Some tracers have their own options. They only appear - when the tracer is active. + display-graph - When set, the latency tracers (irqsoff, wakeup, etc) will + use function graph tracing instead of function tracing. + + stacktrace - This is one of the options that changes the trace + itself. When a trace is recorded, so is the stack + of functions. This allows for back traces of + trace sites. + + Note: Some tracers have their own options. They only appear in this + file when the tracer is active. They always appear in the + options directory. -- GitLab From b5c46cef6c119aeeab0238dc4722ceea585edf33 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 30 Mar 2016 10:15:14 +0100 Subject: [PATCH 3394/9938] dt-bindings: Add power domain info for NVIDIA PMC Add power-domain binding documentation for the NVIDIA PMC driver in order to support generic power-domains. Signed-off-by: Jon Hunter Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt index 53aa5496c5cf..a74b37b07e5c 100644 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt @@ -1,5 +1,7 @@ NVIDIA Tegra Power Management Controller (PMC) +== Power Management Controller Node == + The PMC block interacts with an external Power Management Unit. The PMC mostly controls the entry and exit of the system from different sleep modes. It provides power-gating controllers for SoC and CPU power-islands. @@ -70,6 +72,11 @@ Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip' Defaults to 0. Valid values are described in section 12.5.2 "Pinmux Support" of the Tegra4 Technical Reference Manual. +Optional nodes: +- powergates : This node contains a hierarchy of power domain nodes, which + should match the powergates on the Tegra SoC. See "Powergate + Nodes" below. + Example: / SoC dts including file @@ -115,3 +122,76 @@ pmc@7000f400 { }; ... }; + + +== Powergate Nodes == + +Each of the powergate nodes represents a power-domain on the Tegra SoC +that can be power-gated by the Tegra PMC. The name of the powergate node +should be one of the below. Note that not every powergate is applicable +to all Tegra devices and the following list shows which powergates are +applicable to which devices. Please refer to the Tegra TRM for more +details on the various powergates. + + Name Description Devices Applicable + 3d 3D Graphics Tegra20/114/124/210 + 3d0 3D Graphics 0 Tegra30 + 3d1 3D Graphics 1 Tegra30 + aud Audio Tegra210 + dfd Debug Tegra210 + dis Display A Tegra114/124/210 + disb Display B Tegra114/124/210 + heg 2D Graphics Tegra30/114/124/210 + iram Internal RAM Tegra124/210 + mpe MPEG Encode All + nvdec NVIDIA Video Decode Engine Tegra210 + nvjpg NVIDIA JPEG Engine Tegra210 + pcie PCIE Tegra20/30/124/210 + sata SATA Tegra30/124/210 + sor Display interfaces Tegra124/210 + ve2 Video Encode Engine 2 Tegra210 + venc Video Encode Engine All + vdec Video Decode Engine Tegra20/30/114/124 + vic Video Imaging Compositor Tegra124/210 + xusba USB Partition A Tegra114/124/210 + xusbb USB Partition B Tegra114/124/210 + xusbc USB Partition C Tegra114/124/210 + +Required properties: + - clocks: Must contain an entry for each clock required by the PMC for + controlling a power-gate. See ../clocks/clock-bindings.txt for details. + - resets: Must contain an entry for each reset required by the PMC for + controlling a power-gate. See ../reset/reset.txt for details. + - #power-domain-cells: Must be 0. + +Example: + + pmc: pmc@7000e400 { + compatible = "nvidia,tegra210-pmc"; + reg = <0x0 0x7000e400 0x0 0x400>; + clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; + clock-names = "pclk", "clk32k_in"; + + powergates { + pd_audio: aud { + clocks = <&tegra_car TEGRA210_CLK_APE>, + <&tegra_car TEGRA210_CLK_APB2APE>; + resets = <&tegra_car 198>; + #power-domain-cells = <0>; + }; + }; + }; + + +== Powergate Clients == + +Hardware blocks belonging to a power domain should contain a "power-domains" +property that is a phandle pointing to the corresponding powergate node. + +Example: + + adma: adma@702e2000 { + ... + power-domains = <&pd_audio>; + ... + }; -- GitLab From 87be054a30de1d48a4c9850543080b8cc9854d2c Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 5 Apr 2016 20:58:26 +0530 Subject: [PATCH 3395/9938] ath10k: fix return value for btcoex and peer stats debugfs Return value is incorrect for btcoex and peer stats debugfs 'write' entries if the user provides a value that matches with the already available debugfs entry, this results in the debugfs entry getting stuck and the operation has to be terminated manually. Fix this by returning the appropriate return 'count' as we do it for other debugfs entries like pktlog etc. Fixes: cc61a1bbbc0e ("ath10k: enable debugfs provision to enable Peer Stats feature") Fixes: c28e6f06ff40 ("ath10k: fix sanity check on enabling btcoex via debugfs") Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 76bbe17b25b6..e7d441caa288 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -2122,7 +2122,7 @@ static ssize_t ath10k_write_btcoex(struct file *file, struct ath10k *ar = file->private_data; char buf[32]; size_t buf_size; - int ret = 0; + int ret; bool val; buf_size = min(count, (sizeof(buf) - 1)); @@ -2142,8 +2142,10 @@ static ssize_t ath10k_write_btcoex(struct file *file, goto exit; } - if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) + if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) { + ret = count; goto exit; + } if (val) set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags); @@ -2189,7 +2191,7 @@ static ssize_t ath10k_write_peer_stats(struct file *file, struct ath10k *ar = file->private_data; char buf[32]; size_t buf_size; - int ret = 0; + int ret; bool val; buf_size = min(count, (sizeof(buf) - 1)); @@ -2209,8 +2211,10 @@ static ssize_t ath10k_write_peer_stats(struct file *file, goto exit; } - if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) + if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) { + ret = count; goto exit; + } if (val) set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags); -- GitLab From 1ce8c1484e80010a6e4b9611c65668ff77556f45 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Apr 2016 12:11:54 +0530 Subject: [PATCH 3396/9938] ath10k: fix rx_channel during hw reconfigure Upon firmware assert, restart work will be triggered so that mac80211 will reconfigure the driver. An issue is reported that after restart work, survey dump data do not contain in-use (SURVEY_INFO_IN_USE) info for operating channel. During reconfigure, since mac80211 already has valid channel context for given radio, channel context iteration return num_chanctx > 0. Hence rx_channel is always NULL. Fix this by assigning channel context to rx_channel when driver restart is in progress. Cc: stable@vger.kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d9d98bf22b3e..32e9d5010b4e 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6893,7 +6893,13 @@ ath10k_mac_update_rx_channel(struct ath10k *ar, def = &vifs[0].new_ctx->def; ar->rx_channel = def->chan; - } else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) { + } else if ((ctx && ath10k_mac_num_chanctxs(ar) == 0) || + (ctx && (ar->state == ATH10K_STATE_RESTARTED))) { + /* During driver restart due to firmware assert, since mac80211 + * already has valid channel context for given radio, channel + * context iteration return num_chanctx > 0. So fix rx_channel + * when restart is in progress. + */ ar->rx_channel = ctx->def.chan; } else { ar->rx_channel = NULL; -- GitLab From de72a20dc3714918b208430dd426c9f6a23ffaec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 11 Apr 2016 11:15:20 +0300 Subject: [PATCH 3397/9938] ath10k: add some sanity checks to peer_map_event() functions Smatch complains that since "ev->peer_id" comes from skb->data that means we can't trust it and have to do a bounds check on it to prevent an array overflow. Fixes: 6942726f7f7b ('ath10k: add fast peer_map lookup') Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/txrx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 8c7086989a71..576e7c42ed65 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -190,6 +190,13 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct ath10k_peer *peer; + if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) { + ath10k_warn(ar, + "received htt peer map event with idx out of bounds: %hu\n", + ev->peer_id); + return; + } + spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr); if (!peer) { @@ -218,6 +225,13 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct ath10k_peer *peer; + if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) { + ath10k_warn(ar, + "received htt peer unmap event with idx out of bounds: %hu\n", + ev->peer_id); + return; + } + spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find_by_id(ar, ev->peer_id); if (!peer) { -- GitLab From 7e247a9e88dc811d0b7b6a70af1d741054772bc4 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Tue, 12 Apr 2016 20:15:53 +0530 Subject: [PATCH 3398/9938] ath10k: add dynamic tx mode switch config support for qca4019 push-pull mode needs certain amount the host driver involvement for managing queues in the host memory and packet delivery to firmware. qca4019 wifi firmware has an option to stay in push mode for less number of active traffic flow and then switch to push-pull mode when the active traffic flow goes beyond the certain limit. The advantage of staying in push mode for less active traffic is, the host cpu consumption is reduced. qca4019 firmware supports this flexibility of the mode switch. It takes the host driver interest (LOW_PERF/HIGH_PERF) via WMI_EXT_RESOURCE_CFG_CMDID, LOW_PERF - fw would stay in push mode and switch to push-pull based on demand. HIGH_PERF - fw would stay in push-pull mode from the boot. To make this configuration generic, new WMI services WMI_SERVICE_TX_MODE_PUSH_ONLY, WMI_SERVICE_TX_MODE_PUSH_PULL, WMI_SERVICE_TX_MODE_DYNAMIC are introduced to take dynamic tx mode switch support availability in firmware. Based on WMI_SERVICE_TX_MODE_DYNAMIC, LOW_PERF or HIGHT_PERF is configured to the firmware. Signed-off-by: Raja Mani Signed-off-by: Tamizh chelvam Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 3 +-- drivers/net/wireless/ath/ath10k/mac.c | 20 ++++++++++++++++++++ drivers/net/wireless/ath/ath10k/mac.h | 1 + drivers/net/wireless/ath/ath10k/wmi.h | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b2c7fe3d30a4..1c4106b84a35 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1787,8 +1787,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) if (ath10k_peer_stats_enabled(ar)) val = WMI_10_4_PEER_STATS; - status = ath10k_wmi_ext_resource_config(ar, - WMI_HOST_PLATFORM_HIGH_PERF, val); + status = ath10k_mac_ext_resource_config(ar, val); if (status) { ath10k_err(ar, "failed to send ext resource cfg command : %d\n", diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 32e9d5010b4e..fb393596f236 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -157,6 +157,26 @@ ath10k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) return 1; } +int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val) +{ + enum wmi_host_platform_type platform_type; + int ret; + + if (test_bit(WMI_SERVICE_TX_MODE_DYNAMIC, ar->wmi.svc_map)) + platform_type = WMI_HOST_PLATFORM_LOW_PERF; + else + platform_type = WMI_HOST_PLATFORM_HIGH_PERF; + + ret = ath10k_wmi_ext_resource_config(ar, platform_type, val); + + if (ret && ret != -EOPNOTSUPP) { + ath10k_warn(ar, "failed to configure ext resource: %d\n", ret); + return ret; + } + + return 0; +} + /**********/ /* Crypto */ /**********/ diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 2c3327beb445..1bd29ecfcdcc 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -81,6 +81,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, u16 peer_id, u8 tid); +int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 378f2998cd5a..db2553522d8b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -180,6 +180,9 @@ enum wmi_service { WMI_SERVICE_MESH_NON_11S, WMI_SERVICE_PEER_STATS, WMI_SERVICE_RESTRT_CHNL_SUPPORT, + WMI_SERVICE_TX_MODE_PUSH_ONLY, + WMI_SERVICE_TX_MODE_PUSH_PULL, + WMI_SERVICE_TX_MODE_DYNAMIC, /* keep last */ WMI_SERVICE_MAX, @@ -302,6 +305,9 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, WMI_10_4_SERVICE_PEER_STATS, WMI_10_4_SERVICE_MESH_11S, + WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY, + WMI_10_4_SERVICE_TX_MODE_PUSH_PULL, + WMI_10_4_SERVICE_TX_MODE_DYNAMIC, }; static inline char *wmi_service_name(int service_id) @@ -396,6 +402,9 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_MESH_NON_11S); SVCSTR(WMI_SERVICE_PEER_STATS); SVCSTR(WMI_SERVICE_RESTRT_CHNL_SUPPORT); + SVCSTR(WMI_SERVICE_TX_MODE_PUSH_ONLY); + SVCSTR(WMI_SERVICE_TX_MODE_PUSH_PULL); + SVCSTR(WMI_SERVICE_TX_MODE_DYNAMIC); default: return NULL; } @@ -643,6 +652,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_PEER_STATS, len); SVCMAP(WMI_10_4_SERVICE_MESH_11S, WMI_SERVICE_MESH_11S, len); + SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY, + WMI_SERVICE_TX_MODE_PUSH_ONLY, len); + SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_PULL, + WMI_SERVICE_TX_MODE_PUSH_PULL, len); + SVCMAP(WMI_10_4_SERVICE_TX_MODE_DYNAMIC, + WMI_SERVICE_TX_MODE_DYNAMIC, len); } #undef SVCMAP -- GitLab From f286dd899b4f1445279af6b5965c335ae6f998f7 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 1 Jan 2016 19:09:32 +0100 Subject: [PATCH 3399/9938] ath9k_htc: Replace a variable initialisation by an assignment in ath9k_htc_set_channel() Replace an explicit initialisation for one local variable at the beginning by a conditional assignment. Signed-off-by: Markus Elfring Reviewed-by: Oleksij Rempel Reviewed-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 639294a9e34d..6c5047cc837e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -246,7 +246,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, struct ieee80211_conf *conf = &common->hw->conf; bool fastcc; struct ieee80211_channel *channel = hw->conf.chandef.chan; - struct ath9k_hw_cal_data *caldata = NULL; + struct ath9k_hw_cal_data *caldata; enum htc_phymode mode; __be16 htc_mode; u8 cmd_rsp; @@ -274,10 +274,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, priv->ah->curchan->channel, channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), fastcc); - - if (!fastcc) - caldata = &priv->caldata; - + caldata = fastcc ? NULL : &priv->caldata; ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (ret) { ath_err(common, -- GitLab From 71f5137bf010c6faffab50c0ec15374c59c4a411 Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Fri, 1 Apr 2016 11:37:08 +0200 Subject: [PATCH 3400/9938] ath9k: interpret requested txpower in EIRP domain Tx power limitations at upper layers are interpreted in the EIRP domain. When the user requests a given maximum txpower, e.g. with: 'iw phy0 set txpower fixed 1500', he expects the EIRP to be at or below 15dBm. In ath9k_hw_apply_txpower(), the interpretation is different: the antenna-gain is capped against the current txpower limit in the regulatory, but not against the user set value. It ensures that the resulting EIRP is below the limit defined by the active countrycode, but not below the value the user requested. In a scenario like e.g. a) antenna_gain=6 b) countrycode limits to eirp=18 c) user set txpower=15 this will cause a setting for AR_PHY_POWER_TX_RATE regs resulting in an EIRP > 15. This patch ensures that antenna-gain is considered whenever the txpower limit is adjusted and with that the user set limits are kept. Signed-off-by: Zefir Kurtisi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 42009065e234..8b2895f9ac7a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2914,8 +2914,7 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan, { struct ath_regulatory *reg = ath9k_hw_regulatory(ah); struct ieee80211_channel *channel; - int chan_pwr, new_pwr, max_gain; - int ant_gain, ant_reduction = 0; + int chan_pwr, new_pwr; if (!chan) return; @@ -2923,15 +2922,10 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan, channel = chan->chan; chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER); new_pwr = min_t(int, chan_pwr, reg->power_limit); - max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2; - - ant_gain = get_antenna_gain(ah, chan); - if (ant_gain > max_gain) - ant_reduction = ant_gain - max_gain; ah->eep_ops->set_txpower(ah, chan, ath9k_regd_get_ctl(reg, chan), - ant_reduction, new_pwr, test); + get_antenna_gain(ah, chan), new_pwr, test); } void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) -- GitLab From 47f58b1ebe3739dad1ddeb5cd1f1e718648b4d24 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 10 Apr 2016 12:25:31 +0100 Subject: [PATCH 3401/9938] ath9k: remove duplicate assignment of variable ah ah is written twice with the same value, remove one of the redundant assignments to ah. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 77ace8d72d54..fb702c48a233 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -477,7 +477,7 @@ static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, static int ath9k_eeprom_request(struct ath_softc *sc, const char *name) { struct ath9k_eeprom_ctx ec; - struct ath_hw *ah = ah = sc->sc_ah; + struct ath_hw *ah = sc->sc_ah; int err; /* try to load the EEPROM content asynchronously */ -- GitLab From e7679db714c356f8e27df2dc3ff721c0d3775448 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 11 Apr 2016 13:29:07 +0000 Subject: [PATCH 3402/9938] dt/bindings: bcm2835: add interrupt-names property Added standard interrupt-names property so that platform_get_irq_byname() can get used to fetch the interrupt corresponding to each dma_channel instead of the current platform_get_irq() with an assumed ordering of the interrupts. Signed-off-by: Martin Sperl Acked-by: Rob Herring Acked-by: Eric Anholt Acked-by: Mark Rutland Signed-off-by: Vinod Koul --- .../bindings/dma/brcm,bcm2835-dma.txt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt index 1396078d15ac..baf9b34d20bf 100644 --- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt @@ -12,6 +12,10 @@ Required properties: - reg: Should contain DMA registers location and length. - interrupts: Should contain the DMA interrupts associated to the DMA channels in ascending order. +- interrupt-names: Should contain the names of the interrupt + in the form "dmaXX". + Use "dma-shared-all" for the common interrupt line + that is shared by all dma channels. - #dma-cells: Must be <1>, the cell in the dmas property of the client device represents the DREQ number. - brcm,dma-channel-mask: Bit mask representing the channels @@ -34,13 +38,35 @@ dma: dma@7e007000 { <1 24>, <1 25>, <1 26>, + /* dma channel 11-14 share one irq */ <1 27>, + <1 27>, + <1 27>, + <1 27>, + /* unused shared irq for all channels */ <1 28>; + interrupt-names = "dma0", + "dma1", + "dma2", + "dma3", + "dma4", + "dma5", + "dma6", + "dma7", + "dma8", + "dma9", + "dma10", + "dma11", + "dma12", + "dma13", + "dma14", + "dma-shared-all"; #dma-cells = <1>; brcm,dma-channel-mask = <0x7f35>; }; + DMA clients connected to the BCM2835 DMA controller must use the format described in the dma.txt file, using a two-cell specifier for each channel. -- GitLab From e2eca6389b031cdbbc4172eee89ce271c00cb672 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 11 Apr 2016 13:29:08 +0000 Subject: [PATCH 3403/9938] dmaengine: bcm2835: use platform_get_irq_byname Use platform_get_irq_byname to allow for correct mapping of interrupts to dma channels. The currently implemented device tree is unfortunately implemented with the wrong assumption, that each dma-channel has its own dma channel, but dma-irq 11 is handling dma-channel 11-14 and dma-irq 12 is actually a "catch all" interrupt. So here we use the byname variant and require that interrupts are explicitly named via the interrupts-name property in the device tree. The use of shared interrupts is also implemented. As a side-effect this means we can now use dma channels 12, 13 and 14 in a correct manner - also testing shows that onl using channels 11 to 14 for spi and i2s works perfectly (when playing some video) Signed-off-by: Martin Sperl Acked-by: Eric Anholt Acked-by: Mark Rutland Signed-off-by: Vinod Koul --- drivers/dma/bcm2835-dma.c | 77 ++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index cc771cd35dd0..974015193b93 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -46,6 +46,9 @@ #include "virt-dma.h" +#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 +#define BCM2835_DMA_CHAN_NAME_SIZE 8 + struct bcm2835_dmadev { struct dma_device ddev; spinlock_t lock; @@ -81,6 +84,7 @@ struct bcm2835_chan { void __iomem *chan_base; int irq_number; + unsigned int irq_flags; bool is_lite_channel; }; @@ -466,6 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) struct bcm2835_desc *d; unsigned long flags; + /* check the shared interrupt */ + if (c->irq_flags & IRQF_SHARED) { + /* check if the interrupt is enabled */ + flags = readl(c->chan_base + BCM2835_DMA_CS); + /* if not set then we are not the reason for the irq */ + if (!(flags & BCM2835_DMA_INT)) + return IRQ_NONE; + } + spin_lock_irqsave(&c->vc.lock, flags); /* Acknowledge interrupt */ @@ -506,8 +519,8 @@ static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan) return -ENOMEM; } - return request_irq(c->irq_number, - bcm2835_dma_callback, 0, "DMA IRQ", c); + return request_irq(c->irq_number, bcm2835_dma_callback, + c->irq_flags, "DMA IRQ", c); } static void bcm2835_dma_free_chan_resources(struct dma_chan *chan) @@ -819,7 +832,8 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) return 0; } -static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) +static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, + int irq, unsigned int irq_flags) { struct bcm2835_chan *c; @@ -834,6 +848,7 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id); c->ch = chan_id; c->irq_number = irq; + c->irq_flags = irq_flags; /* check in DEBUG register if this is a LITE channel */ if (readl(c->chan_base + BCM2835_DMA_DEBUG) & @@ -882,9 +897,11 @@ static int bcm2835_dma_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; int rc; - int i; - int irq; + int i, j; + int irq[BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1]; + int irq_flags; uint32_t chans_available; + char chan_name[BCM2835_DMA_CHAN_NAME_SIZE]; if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; @@ -941,16 +958,48 @@ static int bcm2835_dma_probe(struct platform_device *pdev) goto err_no_dma; } - for (i = 0; i < pdev->num_resources; i++) { - irq = platform_get_irq(pdev, i); - if (irq < 0) - break; - - if (chans_available & (1 << i)) { - rc = bcm2835_dma_chan_init(od, i, irq); - if (rc) - goto err_no_dma; + /* get irqs for each channel that we support */ + for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { + /* skip masked out channels */ + if (!(chans_available & (1 << i))) { + irq[i] = -1; + continue; } + + /* get the named irq */ + snprintf(chan_name, sizeof(chan_name), "dma%i", i); + irq[i] = platform_get_irq_byname(pdev, chan_name); + if (irq[i] >= 0) + continue; + + /* legacy device tree case handling */ + dev_warn_once(&pdev->dev, + "missing interrupts-names property in device tree - legacy interpretation is used"); + /* + * in case of channel >= 11 + * use the 11th interrupt and that is shared + */ + irq[i] = platform_get_irq(pdev, i < 11 ? i : 11); + } + + /* get irqs for each channel */ + for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { + /* skip channels without irq */ + if (irq[i] < 0) + continue; + + /* check if there are other channels that also use this irq */ + irq_flags = 0; + for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++) + if ((i != j) && (irq[j] == irq[i])) { + irq_flags = IRQF_SHARED; + break; + } + + /* initialize the channel */ + rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags); + if (rc) + goto err_no_dma; } dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i); -- GitLab From 9bc0fa53692837a6128d2ecc6943e451c7f7c332 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 11 Apr 2016 13:29:09 +0000 Subject: [PATCH 3404/9938] ARM: bcm2835: add interrupt-names and apply correct mapping Add interrupt-names properties to dt and apply the correct mapping between irq and dma channels. Signed-off-by: Martin Sperl Acked-by: Mark Rutland Acked-by: Eric Anholt Signed-off-by: Vinod Koul --- arch/arm/boot/dts/bcm283x.dtsi | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 8aaf193711bf..84dcf3e5c8d9 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -47,9 +47,29 @@ <1 24>, <1 25>, <1 26>, + /* dma channel 11-14 share one irq */ <1 27>, + <1 27>, + <1 27>, + <1 27>, + /* unused shared irq for all channels */ <1 28>; - + interrupt-names = "dma0", + "dma1", + "dma2", + "dma3", + "dma4", + "dma5", + "dma6", + "dma7", + "dma8", + "dma9", + "dma10", + "dma11", + "dma12", + "dma13", + "dma14", + "dma-shared-all"; #dma-cells = <1>; brcm,dma-channel-mask = <0x7f35>; }; -- GitLab From d6632dd59b66c89724ef28e2723586d1429382aa Mon Sep 17 00:00:00 2001 From: Chris Phlipot Date: Tue, 19 Apr 2016 01:56:02 -0700 Subject: [PATCH 3405/9938] perf script: Fix postgresql ubuntu install instructions The current instructions for setting up an Ubuntu system for using the export-to-postgresql.py script are incorrect. The instructions in the script have been updated to work on newer versions of ubuntu. -Add missing dependencies to apt-get command: python-pyside.qtsql, libqt4-sql-psql -Add '-s' option to createuser command to force the user to be a superuser since the command doesn't prompt as indicated in the current instructions. Tested on: Ubuntu 14.04, Ubuntu 16.04(beta) Signed-off-by: Chris Phlipot Cc: Adrian Hunter Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1461056164-14914-3-git-send-email-cphlipot0@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/export-to-postgresql.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py index 1b02cdc0cab6..6f0ca6873c17 100644 --- a/tools/perf/scripts/python/export-to-postgresql.py +++ b/tools/perf/scripts/python/export-to-postgresql.py @@ -34,10 +34,9 @@ import datetime # # ubuntu: # -# $ sudo apt-get install postgresql +# $ sudo apt-get install postgresql python-pyside.qtsql libqt4-sql-psql # $ sudo su - postgres -# $ createuser -# Shall the new role be a superuser? (y/n) y +# $ createuser -s # # An example of using this script with Intel PT: # -- GitLab From f56ebf20d0f535f5da7cfcf0000ab3e0af133f81 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 19 Apr 2016 00:07:18 +0100 Subject: [PATCH 3406/9938] perf jit: memset() variable 'st' using the correct size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code is memsetting the 'struct stat' variable 'st' with the size of 'stat' (which turns out to be 1 byte) rather than the size of variable 'sz'. Committer notes: sizeof(function) isn't valid, the result depends on the compiler used, with gcc, enabling pedantic warnings we get: $ cat sizeof_function.c #include #include #include #include int main(void) { printf("sizeof(stat)=%zd, stat=%p\n", sizeof(stat), stat); return 0; } $ readelf -sW sizeof_function | grep -w stat 49: 0000000000400630 16 FUNC WEAK HIDDEN 13 stat $ cc -pedantic sizeof_function.c -o sizeof_function sizeof_function.c: In function ‘main’: sizeof_function.c:8:46: warning: invalid application of ‘sizeof’ to a function type [-Wpointer-arith] printf("sizeof(stat)=%zd, stat=%p\n", sizeof(stat), stat); ^ $ ./sizeof_function sizeof(stat)=1, stat=0x400630 $ Standard C, section 6.5.3.4: "The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member." http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf Signed-off-by: Colin Ian King Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Peter Zijlstra Cc: Stephane Eranian Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Link: http://lkml.kernel.org/r/1461020838-9260-1-git-send-email-colin.king@canonical.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/jitdump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 52fcef3074fe..86afe9618bb0 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -412,7 +412,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) return -1; } if (stat(filename, &st)) - memset(&st, 0, sizeof(stat)); + memset(&st, 0, sizeof(st)); event->mmap2.header.type = PERF_RECORD_MMAP2; event->mmap2.header.misc = PERF_RECORD_MISC_USER; @@ -500,7 +500,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) size++; /* for \0 */ if (stat(filename, &st)) - memset(&st, 0, sizeof(stat)); + memset(&st, 0, sizeof(st)); size = PERF_ALIGN(size, sizeof(u64)); -- GitLab From 2cc4666927402ec748122cac15ceac35a5e298a3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 19 Apr 2016 12:01:51 -0300 Subject: [PATCH 3407/9938] perf build: Remove x86 references from arch-neutral Build It will already be dealt with generating the syscalltbl.c file in the x86 arch specific Build files, namely via 'archheaders'. This fixes the build on !x86 arches, as reported for powerpcle Reported-by: Stephen Rothwell Tested-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: "H. Peter Anvin" Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Wang Nan Fixes: 1b700c997500 ("perf tools: Build syscall table .c header from kernel's syscall_64.tbl") Link: http://lkml.kernel.org/r/20160415212831.GT9056@kernel.org [ Removed the syscalltbl.o altogether, as per Jiri's suggestion ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 85a9ab62e23f..90229a88f969 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -150,10 +150,6 @@ CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" CFLAGS_parse-events.o += -Wno-redundant-decls -$(OUTPUT)util/syscalltbl.o: util/syscalltbl.c arch/x86/entry/syscalls/syscall_64.tbl $(OUTPUT)arch/x86/include/generated/asm/syscalls_64.c FORCE - $(call rule_mkdir) - $(call if_changed_dep,cc_o_c) - $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) -- GitLab From e02092b9a922f17e951b2df5f12f4aafe7383a21 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 19 Apr 2016 12:12:49 -0300 Subject: [PATCH 3408/9938] perf symbols: Allow loading kallsyms without considering kcore files Before the support for using /proc/kcore was introduced, the kallsyms routines used /proc/modules and the first 'perf test' entry expected finding maps for each module in the system, which is not the case with the kcore code. Provide a way to ignore kcore files so that the test can have its expectations met. Improving the test to cover kcore files as well needs to be done. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-ek5urnu103dlhfk4l6pcw041@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 12 +++++++++--- tools/perf/util/machine.h | 2 ++ tools/perf/util/symbol.c | 12 +++++++++--- tools/perf/util/symbol.h | 2 ++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 52b51e004fe8..656c1d7ee7d4 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -908,11 +908,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid) return machine__create_kernel_maps(machine); } -int machine__load_kallsyms(struct machine *machine, const char *filename, - enum map_type type, symbol_filter_t filter) +int __machine__load_kallsyms(struct machine *machine, const char *filename, + enum map_type type, bool no_kcore, symbol_filter_t filter) { struct map *map = machine__kernel_map(machine); - int ret = dso__load_kallsyms(map->dso, filename, map, filter); + int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter); if (ret > 0) { dso__set_loaded(map->dso, type); @@ -927,6 +927,12 @@ int machine__load_kallsyms(struct machine *machine, const char *filename, return ret; } +int machine__load_kallsyms(struct machine *machine, const char *filename, + enum map_type type, symbol_filter_t filter) +{ + return __machine__load_kallsyms(machine, filename, type, false, filter); +} + int machine__load_vmlinux_path(struct machine *machine, enum map_type type, symbol_filter_t filter) { diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 382873bdc563..4822de5e4544 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -215,6 +215,8 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine, struct map *machine__findnew_module_map(struct machine *machine, u64 start, const char *filename); +int __machine__load_kallsyms(struct machine *machine, const char *filename, + enum map_type type, bool no_kcore, symbol_filter_t filter); int machine__load_kallsyms(struct machine *machine, const char *filename, enum map_type type, symbol_filter_t filter); int machine__load_vmlinux_path(struct machine *machine, enum map_type type, diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index a36823c3b7c0..415c4f6d98fd 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1208,8 +1208,8 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) return 0; } -int dso__load_kallsyms(struct dso *dso, const char *filename, - struct map *map, symbol_filter_t filter) +int __dso__load_kallsyms(struct dso *dso, const char *filename, + struct map *map, bool no_kcore, symbol_filter_t filter) { u64 delta = 0; @@ -1230,12 +1230,18 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, else dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; - if (!dso__load_kcore(dso, map, filename)) + if (!no_kcore && !dso__load_kcore(dso, map, filename)) return dso__split_kallsyms_for_kcore(dso, map, filter); else return dso__split_kallsyms(dso, map, delta, filter); } +int dso__load_kallsyms(struct dso *dso, const char *filename, + struct map *map, symbol_filter_t filter) +{ + return __dso__load_kallsyms(dso, filename, map, false, filter); +} + static int dso__load_perf_map(struct dso *dso, struct map *map, symbol_filter_t filter) { diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 1da7b101bc7f..c8e43979ed5c 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -240,6 +240,8 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, symbol_filter_t filter); int dso__load_vmlinux_path(struct dso *dso, struct map *map, symbol_filter_t filter); +int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, + bool no_kcore, symbol_filter_t filter); int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, symbol_filter_t filter); -- GitLab From 53d0fe68275dbdaf6a532bb4e87f00db5d36c140 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 19 Apr 2016 12:16:55 -0300 Subject: [PATCH 3409/9938] perf test: Ignore kcore files in the "vmlinux matches kallsyms" test Before: # perf test -v kallsyms Maps only in vmlinux: ffffffff81d5e000-ffffffff81ec3ac8 115e000 [kernel].init.text ffffffff81ec3ac8-ffffffffa0000000 12c3ac8 [kernel].exit.text ffffffffa0000000-ffffffffa000c000 0 [fjes] ffffffffa000c000-ffffffffa0017000 0 [video] ffffffffa0017000-ffffffffa001c000 0 [grace] ffffffffa0a7f000-ffffffffa0ba5000 0 [xfs] ffffffffa0ba5000-ffffffffffffffff 0 [veth] Maps in vmlinux with a different name in kallsyms: Maps only in kallsyms: ffff880000100000-ffff88001000b000 80000103000 [kernel.kallsyms] ffff88001000b000-ffff880100000000 8001000e000 [kernel.kallsyms] ffff880100000000-ffffc90000000000 80100003000 [kernel.kallsyms] ffffffffa0000000-ffffffffff600000 7fffa0003000 [kernel.kallsyms] ffffffffff600000-ffffffffffffffff 7fffff603000 [kernel.kallsyms] test child finished with -1 ---- end ---- vmlinux symtab matches kallsyms: FAILED! # After: # perf test -v 1 1: vmlinux symtab matches kallsyms : --- start --- test child forked, pid 7058 Looking at the vmlinux_path (8 entries long) Using /lib/modules/4.6.0-rc1+/build/vmlinux for symbols 0xffffffff81076870: diff end addr for aesni_gcm_dec v: 0xffffffff810791f2 k: 0xffffffff81076902 0xffffffff81079200: diff end addr for aesni_gcm_enc v: 0xffffffff8107bb03 k: 0xffffffff81079292 0xffffffff8107e8d0: diff end addr for aesni_gcm_enc_avx_gen2 v: 0xffffffff81083e76 k: 0xffffffff8107e943 0xffffffff81083e80: diff end addr for aesni_gcm_dec_avx_gen2 v: 0xffffffff81089611 k: 0xffffffff81083ef3 0xffffffff81089990: diff end addr for aesni_gcm_enc_avx_gen4 v: 0xffffffff8108e7c4 k: 0xffffffff81089a03 0xffffffff8108e7d0: diff end addr for aesni_gcm_dec_avx_gen4 v: 0xffffffff810937ef k: 0xffffffff8108e843 Maps only in vmlinux: ffffffff81d5e000-ffffffff81ec3ac8 115e000 [kernel].init.text ffffffff81ec3ac8-ffffffffa0000000 12c3ac8 [kernel].exit.text Maps in vmlinux with a different name in kallsyms: Maps only in kallsyms: test child finished with -1 ---- end ---- vmlinux symtab matches kallsyms: FAILED! # Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: 8e0cf965f95e ("perf symbols: Add support for reading from /proc/kcore") Link: http://lkml.kernel.org/n/tip-n6vrwt9t89w8k769y349govx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/vmlinux-kallsyms.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index 630b0b409b97..c05f1bdd9210 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -54,8 +54,14 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) * Step 3: * * Load and split /proc/kallsyms into multiple maps, one per module. + * Do not use kcore, as this test was designed before kcore support + * and has parts that only make sense if using the non-kcore code. + * XXX: extend it to stress the kcorre code as well, hint: the list + * of modules extracted from /proc/kcore, in its current form, can't + * be compacted against the list of modules found in the "vmlinux" + * code and with the one got from /proc/modules from the "kallsyms" code. */ - if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { + if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true, NULL) <= 0) { pr_debug("dso__load_kallsyms "); goto out; } -- GitLab From 6566feafb4dba4eef30a9c0b25e6f49f996178b6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 19 Apr 2016 12:22:25 -0300 Subject: [PATCH 3410/9938] perf test: Add missing verbose output explaining the reason for failure One of the branches leading to an error had no debug message emitted, fix it, the new lines are: # perf test -v kallsyms 0xffffffff81001000: diff name v: xen_hypercall_set_trap_table k: hypercall_page 0xffffffff810691f0: diff name v: try_to_free_pud_page k: try_to_free_pmd_page 0xffffffff8150bb20: diff name v: wakeup_expire_count_show.part.5 k: wakeup_active_count_show.part.7 0xffffffff816bc7f0: diff name v: phys_switch_id_show.part.11 k: phys_port_name_show.part.12 0xffffffff817bbb90: diff name v: __do_softirq k: __softirqentry_text_start This in turn exercises another bug, still under investigation, because those aliases _are_ in kallsyms, with the same name... Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Fixes: ab414dcda8fa ("perf test: Fixup aliases checking in the 'vmlinux matches kallsyms' test") Link: http://lkml.kernel.org/n/tip-5fhea7a54a54gsmagu9obpr4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/vmlinux-kallsyms.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index c05f1bdd9210..e63abab7d5a1 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -163,6 +163,9 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", mem_start, sym->name, pair->name); + } else { + pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", + mem_start, sym->name, first_pair->name); } } } else -- GitLab From f139f97878039f9a49db6cb555d95f6b6e9ba0f8 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Mon, 11 Apr 2016 11:38:38 +0300 Subject: [PATCH 3411/9938] dmaengine: qcom: bam_dma: fix dma free memory on remove Building the driver as a module and when removing the already inserted module gives below: [ 1389.392788] Unable to handle kernel paging request at virtual address ffffffbdc000001c [ 1389.421321] pgd = ffffffc02fa87000 [ 1389.447899] [ffffffbdc000001c] *pgd=0000000000000000, *pud=0000000000000000 [ 1389.460142] Internal error: Oops: 96000006 [#1] PREEMPT SMP [ 1389.466963] Modules linked in: qcom_bam_dma(-) [ 1389.486608] CPU: 2 PID: 2442 Comm: rmmod Not tainted 4.2.0+ #407 [ 1389.493885] Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) [ 1389.501196] task: ffffffc035bae2c0 ti: ffffffc0368a8000 task.ti: ffffffc0368a8000 [ 1389.508566] PC is at __free_pages+0xc/0x40 [ 1389.515893] LR is at free_pages.part.93+0x30/0x38 [ 1389.523141] pc : [] lr : [] pstate: 80000145 [ 1389.530602] sp : ffffffc0368abc20 [ 1389.537931] x29: ffffffc0368abc20 x28: ffffffc0368a8000 [ 1389.549153] x27: 0000000000000000 x26: 0000000000000000 [ 1389.560412] x25: ffffffc000cb2000 x24: 0000000000000170 [ 1389.571530] x23: 0000000000000004 x22: ffffffc036bc5010 [ 1389.582721] x21: ffffffc036bc5010 x20: 0000000000000000 [ 1389.593981] x19: 0000000000000002 x18: 0000007fcbc8e8b0 [ 1389.605301] x17: 0000007f9b8226ec x16: ffffffc0002089e8 [ 1389.616647] x15: 0000007f9b8a0588 x14: 0ffffffffffffffc [ 1389.628039] x13: 0000000000000030 x12: 0000000000000000 [ 1389.639436] x11: 0000000000000008 x10: ffffffc000ecc000 [ 1389.650872] x9 : ffffffc035bae2c0 x8 : ffffffc035bae9a8 [ 1389.662367] x7 : ffffffc035bae9a0 x6 : 0000000000000000 [ 1389.673906] x5 : ffffffbdc000001c x4 : 0000000080000000 [ 1389.685475] x3 : ffffffbdc0000000 x2 : 0000004080000000 [ 1389.697049] x1 : 0000000000000003 x0 : ffffffbdc0000000 The memory has been already freed by bam_free_chan() so fix this by skiping already freed memory. Signed-off-by: Stanimir Varbanov Reviewed-by: Andy Gross Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index d5e0a9c3ad5d..a486bc0f82e0 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -1234,6 +1234,9 @@ static int bam_dma_remove(struct platform_device *pdev) bam_dma_terminate_all(&bdev->channels[i].vc.chan); tasklet_kill(&bdev->channels[i].vc.task); + if (!bdev->channels[i].fifo_virt) + continue; + dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bdev->channels[i].fifo_virt, bdev->channels[i].fifo_phys); -- GitLab From f89117c0f54c235c149d31174d1dd855e04765b8 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Mon, 11 Apr 2016 11:38:39 +0300 Subject: [PATCH 3412/9938] dmaengine: qcom: bam_dma: clear BAM interrupt only if it is raised Currently we write BAM_IRQ_CLR register with zero even when no BAM_IRQ occured. This write has some bad side effects when the BAM instance is for the crypto engine. In case of crypto engine some of the BAM registers are xPU protected and they cannot be controlled by the driver. Signed-off-by: Stanimir Varbanov Reviewed-by: Andy Gross Tested-by: Pramod Gurav Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index a486bc0f82e0..789d5f836bf7 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -801,13 +801,17 @@ static irqreturn_t bam_dma_irq(int irq, void *data) if (srcs & P_IRQ) tasklet_schedule(&bdev->task); - if (srcs & BAM_IRQ) + if (srcs & BAM_IRQ) { clr_mask = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_STTS)); - /* don't allow reorder of the various accesses to the BAM registers */ - mb(); + /* + * don't allow reorder of the various accesses to the BAM + * registers + */ + mb(); - writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR)); + writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR)); + } return IRQ_HANDLED; } -- GitLab From c778ed46e6d245186522d2ebe2d39b52bbc4432b Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Mon, 11 Apr 2016 11:38:40 +0300 Subject: [PATCH 3413/9938] dmaengine: qcom: bam_dma: document controlled-remotely dt property Extend BAM dt bindings with controlled-remotely property. The property will be needed to handle cases where we need to skip register writes to initialise BAM hardware block. Signed-off-by: Stanimir Varbanov Reviewed-by: Andy Gross Acked-by: Rob Herring Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/qcom_bam_dma.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt index 1c9d48ea4914..9cbf5d9df8fd 100644 --- a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt +++ b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt @@ -13,6 +13,8 @@ Required properties: - clock-names: must contain "bam_clk" entry - qcom,ee : indicates the active Execution Environment identifier (0-7) used in the secure world. +- qcom,controlled-remotely : optional, indicates that the bam is controlled by + remote proccessor i.e. execution environment. Example: -- GitLab From 5172c9eb89d4ea41f86ff91b15b2b0dc75ded869 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Mon, 11 Apr 2016 11:38:41 +0300 Subject: [PATCH 3414/9938] dmaengine: qcom: bam_dma: add controlled-remotely dt property Some of the peripherals has bam which is controlled by remote processor, thus the bam dma driver must avoid register writes which initialise bam hw block. Those registers are protected from xPU block and any writes to them will lead to secure violation and system reboot. Adding the contolled_remotely flag in bam driver to avoid not permitted register writes in bam_init function. Signed-off-by: Stanimir Varbanov Reviewed-by: Andy Gross Tested-by: Pramod Gurav Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 789d5f836bf7..d0f878a78fae 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -387,6 +387,7 @@ struct bam_device { /* execution environment ID, from DT */ u32 ee; + bool controlled_remotely; const struct reg_offset_data *layout; @@ -1042,6 +1043,9 @@ static int bam_init(struct bam_device *bdev) val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); bdev->num_channels = val & BAM_NUM_PIPES_MASK; + if (bdev->controlled_remotely) + return 0; + /* s/w reset bam */ /* after reset all pipes are disabled and idle */ val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL)); @@ -1129,6 +1133,9 @@ static int bam_dma_probe(struct platform_device *pdev) return ret; } + bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node, + "qcom,controlled-remotely"); + bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); if (IS_ERR(bdev->bamclk)) return PTR_ERR(bdev->bamclk); -- GitLab From 2a663ed9fe88cb237d72ce869aeadbbf119ad8e4 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Mon, 11 Apr 2016 11:38:42 +0300 Subject: [PATCH 3415/9938] dmaengine: qcom: bam_dma: use correct pipe FIFO size The pipe fifo size register must instruct the bam hw how many hw descriptors can be pushed to fifo. Currently we instruct the hw with 32KBytes but wrap the tail in bam_start_dma in BAM_P_EVNT_REG on 4095 i.e. 32760. This leads to stalled transactions when the tail wraps. Fix this by use the correct fifo size in BAM_P_FIFO_SIZES register i.e. 32K - 8. Signed-off-by: Stanimir Varbanov Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index d0f878a78fae..7e5ad1c25e21 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -459,7 +459,7 @@ static void bam_chan_init_hw(struct bam_chan *bchan, */ writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)), bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR)); - writel_relaxed(BAM_DESC_FIFO_SIZE, + writel_relaxed(BAM_MAX_DATA_SIZE, bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES)); /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */ -- GitLab From 5ad3f29f6a712c3a37dbda4fba3b6969857d39d9 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Mon, 11 Apr 2016 11:38:43 +0300 Subject: [PATCH 3416/9938] dmaengine: qcom: bam_dma: rename BAM_MAX_DATA_SIZE define It seems that the define has not been with acurate name and makes confusion while reading the code. The more acurate name should be BAM_FIFO_SIZE. Signed-off-by: Stanimir Varbanov Reviewed-by: Andy Gross Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 7e5ad1c25e21..969b48176745 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -342,7 +342,7 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { #define BAM_DESC_FIFO_SIZE SZ_32K #define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1) -#define BAM_MAX_DATA_SIZE (SZ_32K - 8) +#define BAM_FIFO_SIZE (SZ_32K - 8) struct bam_chan { struct virt_dma_chan vc; @@ -459,7 +459,7 @@ static void bam_chan_init_hw(struct bam_chan *bchan, */ writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)), bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR)); - writel_relaxed(BAM_MAX_DATA_SIZE, + writel_relaxed(BAM_FIFO_SIZE, bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES)); /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */ @@ -605,7 +605,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, /* calculate number of required entries */ for_each_sg(sgl, sg, sg_len, i) - num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_MAX_DATA_SIZE); + num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_FIFO_SIZE); /* allocate enough room to accomodate the number of entries */ async_desc = kzalloc(sizeof(*async_desc) + @@ -636,10 +636,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, desc->addr = cpu_to_le32(sg_dma_address(sg) + curr_offset); - if (remainder > BAM_MAX_DATA_SIZE) { - desc->size = cpu_to_le16(BAM_MAX_DATA_SIZE); - remainder -= BAM_MAX_DATA_SIZE; - curr_offset += BAM_MAX_DATA_SIZE; + if (remainder > BAM_FIFO_SIZE) { + desc->size = cpu_to_le16(BAM_FIFO_SIZE); + remainder -= BAM_FIFO_SIZE; + curr_offset += BAM_FIFO_SIZE; } else { desc->size = cpu_to_le16(remainder); remainder = 0; @@ -1174,7 +1174,7 @@ static int bam_dma_probe(struct platform_device *pdev) /* set max dma segment size */ bdev->common.dev = bdev->dev; bdev->common.dev->dma_parms = &bdev->dma_parms; - ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE); + ret = dma_set_max_seg_size(bdev->common.dev, BAM_FIFO_SIZE); if (ret) { dev_err(bdev->dev, "cannot set maximum segment size\n"); goto err_bam_channel_exit; -- GitLab From ab703f818ac36b9e74f61b8890f14e5446b7c012 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 14 Apr 2016 18:11:01 +0200 Subject: [PATCH 3417/9938] dmaengine: dw: lazy allocation of dma descriptors This patch changes the driver to allocate DMA descriptors when needed. This stops memory resources to be wasted and letting them sit idle in the free_list structure when the device doesn't need it... This also solves the problem, that a driver has to guess the number of how many descriptors it needs to allocate in advance. Currently, the dma engine will just fail when put under load by sata_dwc_460ex. Signed-off-by: Christian Lamparter Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 166 ++++++++++++------------------------------ drivers/dma/dw/regs.h | 1 - 2 files changed, 48 insertions(+), 119 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index dd47d4b8aad6..78522dcf3a7d 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -58,13 +58,6 @@ | DWC_CTLL_SMS(_sms)); \ }) -/* - * Number of descriptors to allocate for each channel. This should be - * made configurable somehow; preferably, the clients (at least the - * ones using slave transfers) should be able to give us a hint. - */ -#define NR_DESCS_PER_CHANNEL 64 - /* The set of bus widths supported by the DMA controller */ #define DW_DMA_BUSWIDTHS \ BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \ @@ -84,51 +77,65 @@ static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc) return to_dw_desc(dwc->active_list.next); } -static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc) +static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) { - struct dw_desc *desc, *_desc; - struct dw_desc *ret = NULL; - unsigned int i = 0; - unsigned long flags; + struct dw_desc *desc = txd_to_dw_desc(tx); + struct dw_dma_chan *dwc = to_dw_dma_chan(tx->chan); + dma_cookie_t cookie; + unsigned long flags; spin_lock_irqsave(&dwc->lock, flags); - list_for_each_entry_safe(desc, _desc, &dwc->free_list, desc_node) { - i++; - if (async_tx_test_ack(&desc->txd)) { - list_del(&desc->desc_node); - ret = desc; - break; - } - dev_dbg(chan2dev(&dwc->chan), "desc %p not ACKed\n", desc); - } + cookie = dma_cookie_assign(tx); + + /* + * REVISIT: We should attempt to chain as many descriptors as + * possible, perhaps even appending to those already submitted + * for DMA. But this is hard to do in a race-free manner. + */ + + list_add_tail(&desc->desc_node, &dwc->queue); spin_unlock_irqrestore(&dwc->lock, flags); + dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", + __func__, desc->txd.cookie); - dev_vdbg(chan2dev(&dwc->chan), "scanned %u descriptors on freelist\n", i); + return cookie; +} - return ret; +static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc) +{ + struct dw_dma *dw = to_dw_dma(dwc->chan.device); + struct dw_desc *desc; + dma_addr_t phys; + + desc = dma_pool_zalloc(dw->desc_pool, GFP_ATOMIC, &phys); + if (!desc) + return NULL; + + dwc->descs_allocated++; + INIT_LIST_HEAD(&desc->tx_list); + dma_async_tx_descriptor_init(&desc->txd, &dwc->chan); + desc->txd.tx_submit = dwc_tx_submit; + desc->txd.flags = DMA_CTRL_ACK; + desc->txd.phys = phys; + return desc; } -/* - * Move a descriptor, including any children, to the free list. - * `desc' must not be on any lists. - */ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) { - unsigned long flags; + struct dw_dma *dw = to_dw_dma(dwc->chan.device); + struct dw_desc *child, *_next; - if (desc) { - struct dw_desc *child; + if (unlikely(!desc)) + return; - spin_lock_irqsave(&dwc->lock, flags); - list_for_each_entry(child, &desc->tx_list, desc_node) - dev_vdbg(chan2dev(&dwc->chan), - "moving child desc %p to freelist\n", - child); - list_splice_init(&desc->tx_list, &dwc->free_list); - dev_vdbg(chan2dev(&dwc->chan), "moving desc %p to freelist\n", desc); - list_add(&desc->desc_node, &dwc->free_list); - spin_unlock_irqrestore(&dwc->lock, flags); + list_for_each_entry_safe(child, _next, &desc->tx_list, desc_node) { + list_del(&child->desc_node); + dma_pool_free(dw->desc_pool, child, child->txd.phys); + dwc->descs_allocated--; } + + dma_pool_free(dw->desc_pool, desc, desc->txd.phys); + dwc->descs_allocated--; } static void dwc_initialize(struct dw_dma_chan *dwc) @@ -297,11 +304,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc, list_for_each_entry(child, &desc->tx_list, desc_node) async_tx_ack(&child->txd); async_tx_ack(&desc->txd); - - list_splice_init(&desc->tx_list, &dwc->free_list); - list_move(&desc->desc_node, &dwc->free_list); - - dma_descriptor_unmap(txd); + dwc_desc_put(dwc, desc); spin_unlock_irqrestore(&dwc->lock, flags); if (callback) @@ -663,30 +666,6 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id) /*----------------------------------------------------------------------*/ -static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) -{ - struct dw_desc *desc = txd_to_dw_desc(tx); - struct dw_dma_chan *dwc = to_dw_dma_chan(tx->chan); - dma_cookie_t cookie; - unsigned long flags; - - spin_lock_irqsave(&dwc->lock, flags); - cookie = dma_cookie_assign(tx); - - /* - * REVISIT: We should attempt to chain as many descriptors as - * possible, perhaps even appending to those already submitted - * for DMA. But this is hard to do in a race-free manner. - */ - - dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie); - list_add_tail(&desc->desc_node, &dwc->queue); - - spin_unlock_irqrestore(&dwc->lock, flags); - - return cookie; -} - static struct dma_async_tx_descriptor * dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, size_t len, unsigned long flags) @@ -1159,9 +1138,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); - struct dw_desc *desc; - int i; - unsigned long flags; dev_vdbg(chan2dev(chan), "%s\n", __func__); @@ -1192,48 +1168,13 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) dw_dma_on(dw); dw->in_use |= dwc->mask; - spin_lock_irqsave(&dwc->lock, flags); - i = dwc->descs_allocated; - while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) { - dma_addr_t phys; - - spin_unlock_irqrestore(&dwc->lock, flags); - - desc = dma_pool_alloc(dw->desc_pool, GFP_ATOMIC, &phys); - if (!desc) - goto err_desc_alloc; - - memset(desc, 0, sizeof(struct dw_desc)); - - INIT_LIST_HEAD(&desc->tx_list); - dma_async_tx_descriptor_init(&desc->txd, chan); - desc->txd.tx_submit = dwc_tx_submit; - desc->txd.flags = DMA_CTRL_ACK; - desc->txd.phys = phys; - - dwc_desc_put(dwc, desc); - - spin_lock_irqsave(&dwc->lock, flags); - i = ++dwc->descs_allocated; - } - - spin_unlock_irqrestore(&dwc->lock, flags); - - dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i); - - return i; - -err_desc_alloc: - dev_info(chan2dev(chan), "only allocated %d descriptors\n", i); - - return i; + return 0; } static void dwc_free_chan_resources(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); - struct dw_desc *desc, *_desc; unsigned long flags; LIST_HEAD(list); @@ -1246,8 +1187,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan) BUG_ON(dma_readl(to_dw_dma(chan->device), CH_EN) & dwc->mask); spin_lock_irqsave(&dwc->lock, flags); - list_splice_init(&dwc->free_list, &list); - dwc->descs_allocated = 0; /* Clear custom channel configuration */ dwc->src_id = 0; @@ -1270,11 +1209,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan) if (!dw->in_use) dw_dma_off(dw); - list_for_each_entry_safe(desc, _desc, &list, desc_node) { - dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc); - dma_pool_free(dw->desc_pool, desc, desc->txd.phys); - } - dev_vdbg(chan2dev(chan), "%s: done\n", __func__); } @@ -1406,9 +1340,6 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, retval = ERR_PTR(-ENOMEM); - if (periods > NR_DESCS_PER_CHANNEL) - goto out_err; - cdesc = kzalloc(sizeof(struct dw_cyclic_desc), GFP_KERNEL); if (!cdesc) goto out_err; @@ -1641,7 +1572,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) INIT_LIST_HEAD(&dwc->active_list); INIT_LIST_HEAD(&dwc->queue); - INIT_LIST_HEAD(&dwc->free_list); channel_clear_bit(dw, CH_EN, dwc->mask); diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 96f498188257..0ab02eb23bfc 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -236,7 +236,6 @@ struct dw_dma_chan { unsigned long flags; struct list_head active_list; struct list_head queue; - struct list_head free_list; struct dw_cyclic_desc *cdesc; unsigned int descs_allocated; -- GitLab From d32351c8242b7067b3f3e3a6caf7a387ff43f978 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Mon, 18 Apr 2016 11:09:46 +0800 Subject: [PATCH 3418/9938] arm64: mm: make pr_cont() per line in Virtual kernel memory layout Each line with single pr_cont() in Virtual kernel memory layout, or the dump of the kernel memory layout in dmesg is not aligned when PRINTK_TIME enabled, due to the missing time stamps. Tested-by: James Morse Signed-off-by: Kefeng Wang Signed-off-by: Will Deacon --- arch/arm64/mm/init.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index f64dbd49eca3..f6ff5b5df9f8 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -429,23 +429,22 @@ void __init mem_init(void) MLM(MODULES_VADDR, MODULES_END)); pr_cont(" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n", MLG(VMALLOC_START, VMALLOC_END)); - pr_cont(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n" - " .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n" - " .init : 0x%p" " - 0x%p" " (%6ld KB)\n" - " .data : 0x%p" " - 0x%p" " (%6ld KB)\n", - MLK_ROUNDUP(_text, __start_rodata), - MLK_ROUNDUP(__start_rodata, _etext), - MLK_ROUNDUP(__init_begin, __init_end), + pr_cont(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n", + MLK_ROUNDUP(_text, __start_rodata)); + pr_cont(" .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n", + MLK_ROUNDUP(__start_rodata, _etext)); + pr_cont(" .init : 0x%p" " - 0x%p" " (%6ld KB)\n", + MLK_ROUNDUP(__init_begin, __init_end)); + pr_cont(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(_sdata, _edata)); pr_cont(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", MLK(FIXADDR_START, FIXADDR_TOP)); pr_cont(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(PCI_IO_START, PCI_IO_END)); #ifdef CONFIG_SPARSEMEM_VMEMMAP - pr_cont(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n" - " 0x%16lx - 0x%16lx (%6ld MB actual)\n", - MLG(VMEMMAP_START, - VMEMMAP_START + VMEMMAP_SIZE), + pr_cont(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n", + MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE)); + pr_cont(" 0x%16lx - 0x%16lx (%6ld MB actual)\n", MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()), (unsigned long)virt_to_page(high_memory))); #endif -- GitLab From 9974723e31d1fa99e3c0efb2ae6cbbf089c0080c Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Mon, 18 Apr 2016 11:09:47 +0800 Subject: [PATCH 3419/9938] arm64: mm: Show bss segment in kernel memory layout Show the bss segment information as with text and data in Virtual memory kernel layout. Acked-by: James Morse Signed-off-by: Kefeng Wang Signed-off-by: Will Deacon --- arch/arm64/mm/init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index f6ff5b5df9f8..d45f8627012c 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -437,6 +437,8 @@ void __init mem_init(void) MLK_ROUNDUP(__init_begin, __init_end)); pr_cont(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(_sdata, _edata)); + pr_cont(" .bss : 0x%p" " - 0x%p" " (%6ld KB)\n", + MLK_ROUNDUP(__bss_start, __bss_stop)); pr_cont(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", MLK(FIXADDR_START, FIXADDR_TOP)); pr_cont(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", -- GitLab From 08d43a5fa063e03c860f2f391a30c388bcbc948e Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 10 Dec 2015 12:50:50 -0600 Subject: [PATCH 3420/9938] tracing: Add lock-free tracing_map Add tracing_map, a special-purpose lock-free map for tracing. tracing_map is designed to aggregate or 'sum' one or more values associated with a specific object of type tracing_map_elt, which is associated by the map to a given key. It provides various hooks allowing per-tracer customization and is separated out into a separate file in order to allow it to be shared between multiple tracers, but isn't meant to be generally used outside of that context. The tracing_map implementation was inspired by lock-free map algorithms originated by Dr. Cliff Click: http://www.azulsystems.com/blog/cliff/2007-03-26-non-blocking-hashtable http://www.azulsystems.com/events/javaone_2007/2007_LockFreeHash.pdf Link: http://lkml.kernel.org/r/b43d68d1add33582a396f553c8ef705a33a6a748.1449767187.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/Kconfig | 13 + kernel/trace/Makefile | 1 + kernel/trace/tracing_map.c | 1058 ++++++++++++++++++++++++++++++++++++ kernel/trace/tracing_map.h | 282 ++++++++++ 4 files changed, 1354 insertions(+) create mode 100644 kernel/trace/tracing_map.c create mode 100644 kernel/trace/tracing_map.h diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index e45db6b0d878..48b732943e0e 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -528,6 +528,19 @@ config MMIOTRACE See Documentation/trace/mmiotrace.txt. If you are not helping to develop drivers, say N. +config TRACING_MAP + bool + depends on ARCH_HAVE_NMI_SAFE_CMPXCHG + default n + help + tracing_map is a special-purpose lock-free map for tracing, + separated out as a stand-alone facility in order to allow it + to be shared between multiple tracers. It isn't meant to be + generally used outside of that context, and is normally + selected by tracers that use it. + + If in doubt, say N. + config MMIOTRACE_TEST tristate "Test module for mmiotrace" depends on MMIOTRACE && m diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 9b1044e936a6..4255c4057aaa 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_TRACING) += trace_output.o obj-$(CONFIG_TRACING) += trace_seq.o obj-$(CONFIG_TRACING) += trace_stat.o obj-$(CONFIG_TRACING) += trace_printk.o +obj-$(CONFIG_TRACING_MAP) += tracing_map.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c new file mode 100644 index 000000000000..dd6401dd145e --- /dev/null +++ b/kernel/trace/tracing_map.c @@ -0,0 +1,1058 @@ +/* + * tracing_map - lock-free map for tracing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2015 Tom Zanussi + * + * tracing_map implementation inspired by lock-free map algorithms + * originated by Dr. Cliff Click: + * + * http://www.azulsystems.com/blog/cliff/2007-03-26-non-blocking-hashtable + * http://www.azulsystems.com/events/javaone_2007/2007_LockFreeHash.pdf + */ + +#include +#include +#include +#include + +#include "tracing_map.h" +#include "trace.h" + +/* + * NOTE: For a detailed description of the data structures used by + * these functions (such as tracing_map_elt) please see the overview + * of tracing_map data structures at the beginning of tracing_map.h. + */ + +/** + * tracing_map_update_sum - Add a value to a tracing_map_elt's sum field + * @elt: The tracing_map_elt + * @i: The index of the given sum associated with the tracing_map_elt + * @n: The value to add to the sum + * + * Add n to sum i associated with the specified tracing_map_elt + * instance. The index i is the index returned by the call to + * tracing_map_add_sum_field() when the tracing map was set up. + */ +void tracing_map_update_sum(struct tracing_map_elt *elt, unsigned int i, u64 n) +{ + atomic64_add(n, &elt->fields[i].sum); +} + +/** + * tracing_map_read_sum - Return the value of a tracing_map_elt's sum field + * @elt: The tracing_map_elt + * @i: The index of the given sum associated with the tracing_map_elt + * + * Retrieve the value of the sum i associated with the specified + * tracing_map_elt instance. The index i is the index returned by the + * call to tracing_map_add_sum_field() when the tracing map was set + * up. + * + * Return: The sum associated with field i for elt. + */ +u64 tracing_map_read_sum(struct tracing_map_elt *elt, unsigned int i) +{ + return (u64)atomic64_read(&elt->fields[i].sum); +} + +int tracing_map_cmp_string(void *val_a, void *val_b) +{ + char *a = val_a; + char *b = val_b; + + return strcmp(a, b); +} + +int tracing_map_cmp_none(void *val_a, void *val_b) +{ + return 0; +} + +static int tracing_map_cmp_atomic64(void *val_a, void *val_b) +{ + u64 a = atomic64_read((atomic64_t *)val_a); + u64 b = atomic64_read((atomic64_t *)val_b); + + return (a > b) ? 1 : ((a < b) ? -1 : 0); +} + +#define DEFINE_TRACING_MAP_CMP_FN(type) \ +static int tracing_map_cmp_##type(void *val_a, void *val_b) \ +{ \ + type a = *(type *)val_a; \ + type b = *(type *)val_b; \ + \ + return (a > b) ? 1 : ((a < b) ? -1 : 0); \ +} + +DEFINE_TRACING_MAP_CMP_FN(s64); +DEFINE_TRACING_MAP_CMP_FN(u64); +DEFINE_TRACING_MAP_CMP_FN(s32); +DEFINE_TRACING_MAP_CMP_FN(u32); +DEFINE_TRACING_MAP_CMP_FN(s16); +DEFINE_TRACING_MAP_CMP_FN(u16); +DEFINE_TRACING_MAP_CMP_FN(s8); +DEFINE_TRACING_MAP_CMP_FN(u8); + +tracing_map_cmp_fn_t tracing_map_cmp_num(int field_size, + int field_is_signed) +{ + tracing_map_cmp_fn_t fn = tracing_map_cmp_none; + + switch (field_size) { + case 8: + if (field_is_signed) + fn = tracing_map_cmp_s64; + else + fn = tracing_map_cmp_u64; + break; + case 4: + if (field_is_signed) + fn = tracing_map_cmp_s32; + else + fn = tracing_map_cmp_u32; + break; + case 2: + if (field_is_signed) + fn = tracing_map_cmp_s16; + else + fn = tracing_map_cmp_u16; + break; + case 1: + if (field_is_signed) + fn = tracing_map_cmp_s8; + else + fn = tracing_map_cmp_u8; + break; + } + + return fn; +} + +static int tracing_map_add_field(struct tracing_map *map, + tracing_map_cmp_fn_t cmp_fn) +{ + int ret = -EINVAL; + + if (map->n_fields < TRACING_MAP_FIELDS_MAX) { + ret = map->n_fields; + map->fields[map->n_fields++].cmp_fn = cmp_fn; + } + + return ret; +} + +/** + * tracing_map_add_sum_field - Add a field describing a tracing_map sum + * @map: The tracing_map + * + * Add a sum field to the key and return the index identifying it in + * the map and associated tracing_map_elts. This is the index used + * for instance to update a sum for a particular tracing_map_elt using + * tracing_map_update_sum() or reading it via tracing_map_read_sum(). + * + * Return: The index identifying the field in the map and associated + * tracing_map_elts. + */ +int tracing_map_add_sum_field(struct tracing_map *map) +{ + return tracing_map_add_field(map, tracing_map_cmp_atomic64); +} + +/** + * tracing_map_add_key_field - Add a field describing a tracing_map key + * @map: The tracing_map + * @offset: The offset within the key + * @cmp_fn: The comparison function that will be used to sort on the key + * + * Let the map know there is a key and that if it's used as a sort key + * to use cmp_fn. + * + * A key can be a subset of a compound key; for that purpose, the + * offset param is used to describe where within the the compound key + * the key referenced by this key field resides. + * + * Return: The index identifying the field in the map and associated + * tracing_map_elts. + */ +int tracing_map_add_key_field(struct tracing_map *map, + unsigned int offset, + tracing_map_cmp_fn_t cmp_fn) + +{ + int idx = tracing_map_add_field(map, cmp_fn); + + if (idx < 0) + return idx; + + map->fields[idx].offset = offset; + + map->key_idx[map->n_keys++] = idx; + + return idx; +} + +void tracing_map_array_clear(struct tracing_map_array *a) +{ + unsigned int i; + + if (!a->pages) + return; + + for (i = 0; i < a->n_pages; i++) + memset(a->pages[i], 0, PAGE_SIZE); +} + +void tracing_map_array_free(struct tracing_map_array *a) +{ + unsigned int i; + + if (!a) + return; + + if (!a->pages) { + kfree(a); + return; + } + + for (i = 0; i < a->n_pages; i++) { + if (!a->pages[i]) + break; + free_page((unsigned long)a->pages[i]); + } +} + +struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts, + unsigned int entry_size) +{ + struct tracing_map_array *a; + unsigned int i; + + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return NULL; + + a->entry_size_shift = fls(roundup_pow_of_two(entry_size) - 1); + a->entries_per_page = PAGE_SIZE / (1 << a->entry_size_shift); + a->n_pages = n_elts / a->entries_per_page; + if (!a->n_pages) + a->n_pages = 1; + a->entry_shift = fls(a->entries_per_page) - 1; + a->entry_mask = (1 << a->entry_shift) - 1; + + a->pages = kcalloc(a->n_pages, sizeof(void *), GFP_KERNEL); + if (!a->pages) + goto free; + + for (i = 0; i < a->n_pages; i++) { + a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL); + if (!a->pages[i]) + goto free; + } + out: + return a; + free: + tracing_map_array_free(a); + a = NULL; + + goto out; +} + +static void tracing_map_elt_clear(struct tracing_map_elt *elt) +{ + unsigned i; + + for (i = 0; i < elt->map->n_fields; i++) + if (elt->fields[i].cmp_fn == tracing_map_cmp_atomic64) + atomic64_set(&elt->fields[i].sum, 0); + + if (elt->map->ops && elt->map->ops->elt_clear) + elt->map->ops->elt_clear(elt); +} + +static void tracing_map_elt_init_fields(struct tracing_map_elt *elt) +{ + unsigned int i; + + tracing_map_elt_clear(elt); + + for (i = 0; i < elt->map->n_fields; i++) { + elt->fields[i].cmp_fn = elt->map->fields[i].cmp_fn; + + if (elt->fields[i].cmp_fn != tracing_map_cmp_atomic64) + elt->fields[i].offset = elt->map->fields[i].offset; + } +} + +static void tracing_map_elt_free(struct tracing_map_elt *elt) +{ + if (!elt) + return; + + if (elt->map->ops && elt->map->ops->elt_free) + elt->map->ops->elt_free(elt); + kfree(elt->fields); + kfree(elt->key); + kfree(elt); +} + +static struct tracing_map_elt *tracing_map_elt_alloc(struct tracing_map *map) +{ + struct tracing_map_elt *elt; + int err = 0; + + elt = kzalloc(sizeof(*elt), GFP_KERNEL); + if (!elt) + return ERR_PTR(-ENOMEM); + + elt->map = map; + + elt->key = kzalloc(map->key_size, GFP_KERNEL); + if (!elt->key) { + err = -ENOMEM; + goto free; + } + + elt->fields = kcalloc(map->n_fields, sizeof(*elt->fields), GFP_KERNEL); + if (!elt->fields) { + err = -ENOMEM; + goto free; + } + + tracing_map_elt_init_fields(elt); + + if (map->ops && map->ops->elt_alloc) { + err = map->ops->elt_alloc(elt); + if (err) + goto free; + } + return elt; + free: + tracing_map_elt_free(elt); + + return ERR_PTR(err); +} + +static struct tracing_map_elt *get_free_elt(struct tracing_map *map) +{ + struct tracing_map_elt *elt = NULL; + int idx; + + idx = atomic_inc_return(&map->next_elt); + if (idx < map->max_elts) { + elt = *(TRACING_MAP_ELT(map->elts, idx)); + if (map->ops && map->ops->elt_init) + map->ops->elt_init(elt); + } + + return elt; +} + +static void tracing_map_free_elts(struct tracing_map *map) +{ + unsigned int i; + + if (!map->elts) + return; + + for (i = 0; i < map->max_elts; i++) + tracing_map_elt_free(*(TRACING_MAP_ELT(map->elts, i))); + + tracing_map_array_free(map->elts); +} + +static int tracing_map_alloc_elts(struct tracing_map *map) +{ + unsigned int i; + + map->elts = tracing_map_array_alloc(map->max_elts, + sizeof(struct tracing_map_elt *)); + if (!map->elts) + return -ENOMEM; + + for (i = 0; i < map->max_elts; i++) { + *(TRACING_MAP_ELT(map->elts, i)) = tracing_map_elt_alloc(map); + if (!(*(TRACING_MAP_ELT(map->elts, i)))) { + tracing_map_free_elts(map); + + return -ENOMEM; + } + } + + return 0; +} + +static inline bool keys_match(void *key, void *test_key, unsigned key_size) +{ + bool match = true; + + if (memcmp(key, test_key, key_size)) + match = false; + + return match; +} + +static inline struct tracing_map_elt * +__tracing_map_insert(struct tracing_map *map, void *key, bool lookup_only) +{ + u32 idx, key_hash, test_key; + struct tracing_map_entry *entry; + + key_hash = jhash(key, map->key_size, 0); + if (key_hash == 0) + key_hash = 1; + idx = key_hash >> (32 - (map->map_bits + 1)); + + while (1) { + idx &= (map->map_size - 1); + entry = TRACING_MAP_ENTRY(map->map, idx); + test_key = entry->key; + + if (test_key && test_key == key_hash && entry->val && + keys_match(key, entry->val->key, map->key_size)) { + atomic64_inc(&map->hits); + return entry->val; + } + + if (!test_key) { + if (lookup_only) + break; + + if (!cmpxchg(&entry->key, 0, key_hash)) { + struct tracing_map_elt *elt; + + elt = get_free_elt(map); + if (!elt) { + atomic64_inc(&map->drops); + entry->key = 0; + break; + } + + memcpy(elt->key, key, map->key_size); + entry->val = elt; + atomic64_inc(&map->hits); + + return entry->val; + } + } + + idx++; + } + + return NULL; +} + +/** + * tracing_map_insert - Insert key and/or retrieve val from a tracing_map + * @map: The tracing_map to insert into + * @key: The key to insert + * + * Inserts a key into a tracing_map and creates and returns a new + * tracing_map_elt for it, or if the key has already been inserted by + * a previous call, returns the tracing_map_elt already associated + * with it. When the map was created, the number of elements to be + * allocated for the map was specified (internally maintained as + * 'max_elts' in struct tracing_map), and that number of + * tracing_map_elts was created by tracing_map_init(). This is the + * pre-allocated pool of tracing_map_elts that tracing_map_insert() + * will allocate from when adding new keys. Once that pool is + * exhausted, tracing_map_insert() is useless and will return NULL to + * signal that state. There are two user-visible tracing_map + * variables, 'hits' and 'drops', which are updated by this function. + * Every time an element is either successfully inserted or retrieved, + * the 'hits' value is incrememented. Every time an element insertion + * fails, the 'drops' value is incremented. + * + * This is a lock-free tracing map insertion function implementing a + * modified form of Cliff Click's basic insertion algorithm. It + * requires the table size be a power of two. To prevent any + * possibility of an infinite loop we always make the internal table + * size double the size of the requested table size (max_elts * 2). + * Likewise, we never reuse a slot or resize or delete elements - when + * we've reached max_elts entries, we simply return NULL once we've + * run out of entries. Readers can at any point in time traverse the + * tracing map and safely access the key/val pairs. + * + * Return: the tracing_map_elt pointer val associated with the key. + * If this was a newly inserted key, the val will be a newly allocated + * and associated tracing_map_elt pointer val. If the key wasn't + * found and the pool of tracing_map_elts has been exhausted, NULL is + * returned and no further insertions will succeed. + */ +struct tracing_map_elt *tracing_map_insert(struct tracing_map *map, void *key) +{ + return __tracing_map_insert(map, key, false); +} + +/** + * tracing_map_lookup - Retrieve val from a tracing_map + * @map: The tracing_map to perform the lookup on + * @key: The key to look up + * + * Looks up key in tracing_map and if found returns the matching + * tracing_map_elt. This is a lock-free lookup; see + * tracing_map_insert() for details on tracing_map and how it works. + * Every time an element is retrieved, the 'hits' value is + * incrememented. There is one user-visible tracing_map variable, + * 'hits', which is updated by this function. Every time an element + * is successfully retrieved, the 'hits' value is incrememented. The + * 'drops' value is never updated by this function. + * + * Return: the tracing_map_elt pointer val associated with the key. + * If the key wasn't found, NULL is returned. + */ +struct tracing_map_elt *tracing_map_lookup(struct tracing_map *map, void *key) +{ + return __tracing_map_insert(map, key, true); +} + +/** + * tracing_map_destroy - Destroy a tracing_map + * @map: The tracing_map to destroy + * + * Frees a tracing_map along with its associated array of + * tracing_map_elts. + * + * Callers should make sure there are no readers or writers actively + * reading or inserting into the map before calling this. + */ +void tracing_map_destroy(struct tracing_map *map) +{ + if (!map) + return; + + tracing_map_free_elts(map); + + tracing_map_array_free(map->map); + kfree(map); +} + +/** + * tracing_map_clear - Clear a tracing_map + * @map: The tracing_map to clear + * + * Resets the tracing map to a cleared or initial state. The + * tracing_map_elts are all cleared, and the array of struct + * tracing_map_entry is reset to an initialized state. + * + * Callers should make sure there are no writers actively inserting + * into the map before calling this. + */ +void tracing_map_clear(struct tracing_map *map) +{ + unsigned int i; + + atomic_set(&map->next_elt, -1); + atomic64_set(&map->hits, 0); + atomic64_set(&map->drops, 0); + + tracing_map_array_clear(map->map); + + for (i = 0; i < map->max_elts; i++) + tracing_map_elt_clear(*(TRACING_MAP_ELT(map->elts, i))); +} + +static void set_sort_key(struct tracing_map *map, + struct tracing_map_sort_key *sort_key) +{ + map->sort_key = *sort_key; +} + +/** + * tracing_map_create - Create a lock-free map and element pool + * @map_bits: The size of the map (2 ** map_bits) + * @key_size: The size of the key for the map in bytes + * @ops: Optional client-defined tracing_map_ops instance + * @private_data: Client data associated with the map + * + * Creates and sets up a map to contain 2 ** map_bits number of + * elements (internally maintained as 'max_elts' in struct + * tracing_map). Before using, map fields should be added to the map + * with tracing_map_add_sum_field() and tracing_map_add_key_field(). + * tracing_map_init() should then be called to allocate the array of + * tracing_map_elts, in order to avoid allocating anything in the map + * insertion path. The user-specified map size reflects the maximum + * number of elements that can be contained in the table requested by + * the user - internally we double that in order to keep the table + * sparse and keep collisions manageable. + * + * A tracing_map is a special-purpose map designed to aggregate or + * 'sum' one or more values associated with a specific object of type + * tracing_map_elt, which is attached by the map to a given key. + * + * tracing_map_create() sets up the map itself, and provides + * operations for inserting tracing_map_elts, but doesn't allocate the + * tracing_map_elts themselves, or provide a means for describing the + * keys or sums associated with the tracing_map_elts. All + * tracing_map_elts for a given map have the same set of sums and + * keys, which are defined by the client using the functions + * tracing_map_add_key_field() and tracing_map_add_sum_field(). Once + * the fields are defined, the pool of elements allocated for the map + * can be created, which occurs when the client code calls + * tracing_map_init(). + * + * When tracing_map_init() returns, tracing_map_elt elements can be + * inserted into the map using tracing_map_insert(). When called, + * tracing_map_insert() grabs a free tracing_map_elt from the pool, or + * finds an existing match in the map and in either case returns it. + * The client can then use tracing_map_update_sum() and + * tracing_map_read_sum() to update or read a given sum field for the + * tracing_map_elt. + * + * The client can at any point retrieve and traverse the current set + * of inserted tracing_map_elts in a tracing_map, via + * tracing_map_sort_entries(). Sorting can be done on any field, + * including keys. + * + * See tracing_map.h for a description of tracing_map_ops. + * + * Return: the tracing_map pointer if successful, ERR_PTR if not. + */ +struct tracing_map *tracing_map_create(unsigned int map_bits, + unsigned int key_size, + const struct tracing_map_ops *ops, + void *private_data) +{ + struct tracing_map *map; + unsigned int i; + + if (map_bits < TRACING_MAP_BITS_MIN || + map_bits > TRACING_MAP_BITS_MAX) + return ERR_PTR(-EINVAL); + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (!map) + return ERR_PTR(-ENOMEM); + + map->map_bits = map_bits; + map->max_elts = (1 << map_bits); + atomic_set(&map->next_elt, -1); + + map->map_size = (1 << (map_bits + 1)); + map->ops = ops; + + map->private_data = private_data; + + map->map = tracing_map_array_alloc(map->map_size, + sizeof(struct tracing_map_entry)); + if (!map->map) + goto free; + + map->key_size = key_size; + for (i = 0; i < TRACING_MAP_KEYS_MAX; i++) + map->key_idx[i] = -1; + out: + return map; + free: + tracing_map_destroy(map); + map = ERR_PTR(-ENOMEM); + + goto out; +} + +/** + * tracing_map_init - Allocate and clear a map's tracing_map_elts + * @map: The tracing_map to initialize + * + * Allocates a clears a pool of tracing_map_elts equal to the + * user-specified size of 2 ** map_bits (internally maintained as + * 'max_elts' in struct tracing_map). Before using, the map fields + * should be added to the map with tracing_map_add_sum_field() and + * tracing_map_add_key_field(). tracing_map_init() should then be + * called to allocate the array of tracing_map_elts, in order to avoid + * allocating anything in the map insertion path. The user-specified + * map size reflects the max number of elements requested by the user + * - internally we double that in order to keep the table sparse and + * keep collisions manageable. + * + * See tracing_map.h for a description of tracing_map_ops. + * + * Return: the tracing_map pointer if successful, ERR_PTR if not. + */ +int tracing_map_init(struct tracing_map *map) +{ + int err; + + if (map->n_fields < 2) + return -EINVAL; /* need at least 1 key and 1 val */ + + err = tracing_map_alloc_elts(map); + if (err) + return err; + + tracing_map_clear(map); + + return err; +} + +static int cmp_entries_dup(const struct tracing_map_sort_entry **a, + const struct tracing_map_sort_entry **b) +{ + int ret = 0; + + if (memcmp((*a)->key, (*b)->key, (*a)->elt->map->key_size)) + ret = 1; + + return ret; +} + +static int cmp_entries_sum(const struct tracing_map_sort_entry **a, + const struct tracing_map_sort_entry **b) +{ + const struct tracing_map_elt *elt_a, *elt_b; + struct tracing_map_sort_key *sort_key; + struct tracing_map_field *field; + tracing_map_cmp_fn_t cmp_fn; + void *val_a, *val_b; + int ret = 0; + + elt_a = (*a)->elt; + elt_b = (*b)->elt; + + sort_key = &elt_a->map->sort_key; + + field = &elt_a->fields[sort_key->field_idx]; + cmp_fn = field->cmp_fn; + + val_a = &elt_a->fields[sort_key->field_idx].sum; + val_b = &elt_b->fields[sort_key->field_idx].sum; + + ret = cmp_fn(val_a, val_b); + if (sort_key->descending) + ret = -ret; + + return ret; +} + +static int cmp_entries_key(const struct tracing_map_sort_entry **a, + const struct tracing_map_sort_entry **b) +{ + const struct tracing_map_elt *elt_a, *elt_b; + struct tracing_map_sort_key *sort_key; + struct tracing_map_field *field; + tracing_map_cmp_fn_t cmp_fn; + void *val_a, *val_b; + int ret = 0; + + elt_a = (*a)->elt; + elt_b = (*b)->elt; + + sort_key = &elt_a->map->sort_key; + + field = &elt_a->fields[sort_key->field_idx]; + + cmp_fn = field->cmp_fn; + + val_a = elt_a->key + field->offset; + val_b = elt_b->key + field->offset; + + ret = cmp_fn(val_a, val_b); + if (sort_key->descending) + ret = -ret; + + return ret; +} + +static void destroy_sort_entry(struct tracing_map_sort_entry *entry) +{ + if (!entry) + return; + + if (entry->elt_copied) + tracing_map_elt_free(entry->elt); + + kfree(entry); +} + +/** + * tracing_map_destroy_sort_entries - Destroy an array of sort entries + * @entries: The entries to destroy + * @n_entries: The number of entries in the array + * + * Destroy the elements returned by a tracing_map_sort_entries() call. + */ +void tracing_map_destroy_sort_entries(struct tracing_map_sort_entry **entries, + unsigned int n_entries) +{ + unsigned int i; + + for (i = 0; i < n_entries; i++) + destroy_sort_entry(entries[i]); + + vfree(entries); +} + +static struct tracing_map_sort_entry * +create_sort_entry(void *key, struct tracing_map_elt *elt) +{ + struct tracing_map_sort_entry *sort_entry; + + sort_entry = kzalloc(sizeof(*sort_entry), GFP_KERNEL); + if (!sort_entry) + return NULL; + + sort_entry->key = key; + sort_entry->elt = elt; + + return sort_entry; +} + +static struct tracing_map_elt *copy_elt(struct tracing_map_elt *elt) +{ + struct tracing_map_elt *dup_elt; + unsigned int i; + + dup_elt = tracing_map_elt_alloc(elt->map); + if (!dup_elt) + return NULL; + + if (elt->map->ops && elt->map->ops->elt_copy) + elt->map->ops->elt_copy(dup_elt, elt); + + dup_elt->private_data = elt->private_data; + memcpy(dup_elt->key, elt->key, elt->map->key_size); + + for (i = 0; i < elt->map->n_fields; i++) { + atomic64_set(&dup_elt->fields[i].sum, + atomic64_read(&elt->fields[i].sum)); + dup_elt->fields[i].cmp_fn = elt->fields[i].cmp_fn; + } + + return dup_elt; +} + +static int merge_dup(struct tracing_map_sort_entry **sort_entries, + unsigned int target, unsigned int dup) +{ + struct tracing_map_elt *target_elt, *elt; + bool first_dup = (target - dup) == 1; + int i; + + if (first_dup) { + elt = sort_entries[target]->elt; + target_elt = copy_elt(elt); + if (!target_elt) + return -ENOMEM; + sort_entries[target]->elt = target_elt; + sort_entries[target]->elt_copied = true; + } else + target_elt = sort_entries[target]->elt; + + elt = sort_entries[dup]->elt; + + for (i = 0; i < elt->map->n_fields; i++) + atomic64_add(atomic64_read(&elt->fields[i].sum), + &target_elt->fields[i].sum); + + sort_entries[dup]->dup = true; + + return 0; +} + +static int merge_dups(struct tracing_map_sort_entry **sort_entries, + int n_entries, unsigned int key_size) +{ + unsigned int dups = 0, total_dups = 0; + int err, i, j; + void *key; + + if (n_entries < 2) + return total_dups; + + sort(sort_entries, n_entries, sizeof(struct tracing_map_sort_entry *), + (int (*)(const void *, const void *))cmp_entries_dup, NULL); + + key = sort_entries[0]->key; + for (i = 1; i < n_entries; i++) { + if (!memcmp(sort_entries[i]->key, key, key_size)) { + dups++; total_dups++; + err = merge_dup(sort_entries, i - dups, i); + if (err) + return err; + continue; + } + key = sort_entries[i]->key; + dups = 0; + } + + if (!total_dups) + return total_dups; + + for (i = 0, j = 0; i < n_entries; i++) { + if (!sort_entries[i]->dup) { + sort_entries[j] = sort_entries[i]; + if (j++ != i) + sort_entries[i] = NULL; + } else { + destroy_sort_entry(sort_entries[i]); + sort_entries[i] = NULL; + } + } + + return total_dups; +} + +static bool is_key(struct tracing_map *map, unsigned int field_idx) +{ + unsigned int i; + + for (i = 0; i < map->n_keys; i++) + if (map->key_idx[i] == field_idx) + return true; + return false; +} + +static void sort_secondary(struct tracing_map *map, + const struct tracing_map_sort_entry **entries, + unsigned int n_entries, + struct tracing_map_sort_key *primary_key, + struct tracing_map_sort_key *secondary_key) +{ + int (*primary_fn)(const struct tracing_map_sort_entry **, + const struct tracing_map_sort_entry **); + int (*secondary_fn)(const struct tracing_map_sort_entry **, + const struct tracing_map_sort_entry **); + unsigned i, start = 0, n_sub = 1; + + if (is_key(map, primary_key->field_idx)) + primary_fn = cmp_entries_key; + else + primary_fn = cmp_entries_sum; + + if (is_key(map, secondary_key->field_idx)) + secondary_fn = cmp_entries_key; + else + secondary_fn = cmp_entries_sum; + + for (i = 0; i < n_entries - 1; i++) { + const struct tracing_map_sort_entry **a = &entries[i]; + const struct tracing_map_sort_entry **b = &entries[i + 1]; + + if (primary_fn(a, b) == 0) { + n_sub++; + if (i < n_entries - 2) + continue; + } + + if (n_sub < 2) { + start = i + 1; + n_sub = 1; + continue; + } + + set_sort_key(map, secondary_key); + sort(&entries[start], n_sub, + sizeof(struct tracing_map_sort_entry *), + (int (*)(const void *, const void *))secondary_fn, NULL); + set_sort_key(map, primary_key); + + start = i + 1; + n_sub = 1; + } +} + +/** + * tracing_map_sort_entries - Sort the current set of tracing_map_elts in a map + * @map: The tracing_map + * @sort_key: The sort key to use for sorting + * @sort_entries: outval: pointer to allocated and sorted array of entries + * + * tracing_map_sort_entries() sorts the current set of entries in the + * map and returns the list of tracing_map_sort_entries containing + * them to the client in the sort_entries param. The client can + * access the struct tracing_map_elt element of interest directly as + * the 'elt' field of a returned struct tracing_map_sort_entry object. + * + * The sort_key has only two fields: idx and descending. 'idx' refers + * to the index of the field added via tracing_map_add_sum_field() or + * tracing_map_add_key_field() when the tracing_map was initialized. + * 'descending' is a flag that if set reverses the sort order, which + * by default is ascending. + * + * The client should not hold on to the returned array but should use + * it and call tracing_map_destroy_sort_entries() when done. + * + * Return: the number of sort_entries in the struct tracing_map_sort_entry + * array, negative on error + */ +int tracing_map_sort_entries(struct tracing_map *map, + struct tracing_map_sort_key *sort_keys, + unsigned int n_sort_keys, + struct tracing_map_sort_entry ***sort_entries) +{ + int (*cmp_entries_fn)(const struct tracing_map_sort_entry **, + const struct tracing_map_sort_entry **); + struct tracing_map_sort_entry *sort_entry, **entries; + int i, n_entries, ret; + + entries = vmalloc(map->max_elts * sizeof(sort_entry)); + if (!entries) + return -ENOMEM; + + for (i = 0, n_entries = 0; i < map->map_size; i++) { + struct tracing_map_entry *entry; + + entry = TRACING_MAP_ENTRY(map->map, i); + + if (!entry->key || !entry->val) + continue; + + entries[n_entries] = create_sort_entry(entry->val->key, + entry->val); + if (!entries[n_entries++]) { + ret = -ENOMEM; + goto free; + } + } + + if (n_entries == 0) { + ret = 0; + goto free; + } + + if (n_entries == 1) { + *sort_entries = entries; + return 1; + } + + ret = merge_dups(entries, n_entries, map->key_size); + if (ret < 0) + goto free; + n_entries -= ret; + + if (is_key(map, sort_keys[0].field_idx)) + cmp_entries_fn = cmp_entries_key; + else + cmp_entries_fn = cmp_entries_sum; + + set_sort_key(map, &sort_keys[0]); + + sort(entries, n_entries, sizeof(struct tracing_map_sort_entry *), + (int (*)(const void *, const void *))cmp_entries_fn, NULL); + + if (n_sort_keys > 1) + sort_secondary(map, + (const struct tracing_map_sort_entry **)entries, + n_entries, + &sort_keys[0], + &sort_keys[1]); + + *sort_entries = entries; + + return n_entries; + free: + tracing_map_destroy_sort_entries(entries, n_entries); + + return ret; +} diff --git a/kernel/trace/tracing_map.h b/kernel/trace/tracing_map.h new file mode 100644 index 000000000000..75718255a8ad --- /dev/null +++ b/kernel/trace/tracing_map.h @@ -0,0 +1,282 @@ +#ifndef __TRACING_MAP_H +#define __TRACING_MAP_H + +#define TRACING_MAP_BITS_DEFAULT 11 +#define TRACING_MAP_BITS_MAX 17 +#define TRACING_MAP_BITS_MIN 7 + +#define TRACING_MAP_FIELDS_MAX 4 +#define TRACING_MAP_KEYS_MAX 2 + +#define TRACING_MAP_SORT_KEYS_MAX 2 + +typedef int (*tracing_map_cmp_fn_t) (void *val_a, void *val_b); + +/* + * This is an overview of the tracing_map data structures and how they + * relate to the tracing_map API. The details of the algorithms + * aren't discussed here - this is just a general overview of the data + * structures and how they interact with the API. + * + * The central data structure of the tracing_map is an initially + * zeroed array of struct tracing_map_entry (stored in the map field + * of struct tracing_map). tracing_map_entry is a very simple data + * structure containing only two fields: a 32-bit unsigned 'key' + * variable and a pointer named 'val'. This array of struct + * tracing_map_entry is essentially a hash table which will be + * modified by a single function, tracing_map_insert(), but which can + * be traversed and read by a user at any time (though the user does + * this indirectly via an array of tracing_map_sort_entry - see the + * explanation of that data structure in the discussion of the + * sorting-related data structures below). + * + * The central function of the tracing_map API is + * tracing_map_insert(). tracing_map_insert() hashes the + * arbitrarily-sized key passed into it into a 32-bit unsigned key. + * It then uses this key, truncated to the array size, as an index + * into the array of tracing_map_entries. If the value of the 'key' + * field of the tracing_map_entry found at that location is 0, then + * that entry is considered to be free and can be claimed, by + * replacing the 0 in the 'key' field of the tracing_map_entry with + * the new 32-bit hashed key. Once claimed, that tracing_map_entry's + * 'val' field is then used to store a unique element which will be + * forever associated with that 32-bit hashed key in the + * tracing_map_entry. + * + * That unique element now in the tracing_map_entry's 'val' field is + * an instance of tracing_map_elt, where 'elt' in the latter part of + * that variable name is short for 'element'. The purpose of a + * tracing_map_elt is to hold values specific to the the particular + * 32-bit hashed key it's assocated with. Things such as the unique + * set of aggregated sums associated with the 32-bit hashed key, along + * with a copy of the full key associated with the entry, and which + * was used to produce the 32-bit hashed key. + * + * When tracing_map_create() is called to create the tracing map, the + * user specifies (indirectly via the map_bits param, the details are + * unimportant for this discussion) the maximum number of elements + * that the map can hold (stored in the max_elts field of struct + * tracing_map). This is the maximum possible number of + * tracing_map_entries in the tracing_map_entry array which can be + * 'claimed' as described in the above discussion, and therefore is + * also the maximum number of tracing_map_elts that can be associated + * with the tracing_map_entry array in the tracing_map. Because of + * the way the insertion algorithm works, the size of the allocated + * tracing_map_entry array is always twice the maximum number of + * elements (2 * max_elts). This value is stored in the map_size + * field of struct tracing_map. + * + * Because tracing_map_insert() needs to work from any context, + * including from within the memory allocation functions themselves, + * both the tracing_map_entry array and a pool of max_elts + * tracing_map_elts are pre-allocated before any call is made to + * tracing_map_insert(). + * + * The tracing_map_entry array is allocated as a single block by + * tracing_map_create(). + * + * Because the tracing_map_elts are much larger objects and can't + * generally be allocated together as a single large array without + * failure, they're allocated individually, by tracing_map_init(). + * + * The pool of tracing_map_elts are allocated by tracing_map_init() + * rather than by tracing_map_create() because at the time + * tracing_map_create() is called, there isn't enough information to + * create the tracing_map_elts. Specifically,the user first needs to + * tell the tracing_map implementation how many fields the + * tracing_map_elts contain, and which types of fields they are (key + * or sum). The user does this via the tracing_map_add_sum_field() + * and tracing_map_add_key_field() functions, following which the user + * calls tracing_map_init() to finish up the tracing map setup. The + * array holding the pointers which make up the pre-allocated pool of + * tracing_map_elts is allocated as a single block and is stored in + * the elts field of struct tracing_map. + * + * There is also a set of structures used for sorting that might + * benefit from some minimal explanation. + * + * struct tracing_map_sort_key is used to drive the sort at any given + * time. By 'any given time' we mean that a different + * tracing_map_sort_key will be used at different times depending on + * whether the sort currently being performed is a primary or a + * secondary sort. + * + * The sort key is very simple, consisting of the field index of the + * tracing_map_elt field to sort on (which the user saved when adding + * the field), and whether the sort should be done in an ascending or + * descending order. + * + * For the convenience of the sorting code, a tracing_map_sort_entry + * is created for each tracing_map_elt, again individually allocated + * to avoid failures that might be expected if allocated as a single + * large array of struct tracing_map_sort_entry. + * tracing_map_sort_entry instances are the objects expected by the + * various internal sorting functions, and are also what the user + * ultimately receives after calling tracing_map_sort_entries(). + * Because it doesn't make sense for users to access an unordered and + * sparsely populated tracing_map directly, the + * tracing_map_sort_entries() function is provided so that users can + * retrieve a sorted list of all existing elements. In addition to + * the associated tracing_map_elt 'elt' field contained within the + * tracing_map_sort_entry, which is the object of interest to the + * user, tracing_map_sort_entry objects contain a number of additional + * fields which are used for caching and internal purposes and can + * safely be ignored. +*/ + +struct tracing_map_field { + tracing_map_cmp_fn_t cmp_fn; + union { + atomic64_t sum; + unsigned int offset; + }; +}; + +struct tracing_map_elt { + struct tracing_map *map; + struct tracing_map_field *fields; + void *key; + void *private_data; +}; + +struct tracing_map_entry { + u32 key; + struct tracing_map_elt *val; +}; + +struct tracing_map_sort_key { + unsigned int field_idx; + bool descending; +}; + +struct tracing_map_sort_entry { + void *key; + struct tracing_map_elt *elt; + bool elt_copied; + bool dup; +}; + +struct tracing_map_array { + unsigned int entries_per_page; + unsigned int entry_size_shift; + unsigned int entry_shift; + unsigned int entry_mask; + unsigned int n_pages; + void **pages; +}; + +#define TRACING_MAP_ARRAY_ELT(array, idx) \ + (array->pages[idx >> array->entry_shift] + \ + ((idx & array->entry_mask) << array->entry_size_shift)) + +#define TRACING_MAP_ENTRY(array, idx) \ + ((struct tracing_map_entry *)TRACING_MAP_ARRAY_ELT(array, idx)) + +#define TRACING_MAP_ELT(array, idx) \ + ((struct tracing_map_elt **)TRACING_MAP_ARRAY_ELT(array, idx)) + +struct tracing_map { + unsigned int key_size; + unsigned int map_bits; + unsigned int map_size; + unsigned int max_elts; + atomic_t next_elt; + struct tracing_map_array *elts; + struct tracing_map_array *map; + const struct tracing_map_ops *ops; + void *private_data; + struct tracing_map_field fields[TRACING_MAP_FIELDS_MAX]; + unsigned int n_fields; + int key_idx[TRACING_MAP_KEYS_MAX]; + unsigned int n_keys; + struct tracing_map_sort_key sort_key; + atomic64_t hits; + atomic64_t drops; +}; + +/** + * struct tracing_map_ops - callbacks for tracing_map + * + * The methods in this structure define callback functions for various + * operations on a tracing_map or objects related to a tracing_map. + * + * For a detailed description of tracing_map_elt objects please see + * the overview of tracing_map data structures at the beginning of + * this file. + * + * All the methods below are optional. + * + * @elt_alloc: When a tracing_map_elt is allocated, this function, if + * defined, will be called and gives clients the opportunity to + * allocate additional data and attach it to the element + * (tracing_map_elt->private_data is meant for that purpose). + * Element allocation occurs before tracing begins, when the + * tracing_map_init() call is made by client code. + * + * @elt_copy: At certain points in the lifetime of an element, it may + * need to be copied. The copy should include a copy of the + * client-allocated data, which can be copied into the 'to' + * element from the 'from' element. + * + * @elt_free: When a tracing_map_elt is freed, this function is called + * and allows client-allocated per-element data to be freed. + * + * @elt_clear: This callback allows per-element client-defined data to + * be cleared, if applicable. + * + * @elt_init: This callback allows per-element client-defined data to + * be initialized when used i.e. when the element is actually + * claimed by tracing_map_insert() in the context of the map + * insertion. + */ +struct tracing_map_ops { + int (*elt_alloc)(struct tracing_map_elt *elt); + void (*elt_copy)(struct tracing_map_elt *to, + struct tracing_map_elt *from); + void (*elt_free)(struct tracing_map_elt *elt); + void (*elt_clear)(struct tracing_map_elt *elt); + void (*elt_init)(struct tracing_map_elt *elt); +}; + +extern struct tracing_map * +tracing_map_create(unsigned int map_bits, + unsigned int key_size, + const struct tracing_map_ops *ops, + void *private_data); +extern int tracing_map_init(struct tracing_map *map); + +extern int tracing_map_add_sum_field(struct tracing_map *map); +extern int tracing_map_add_key_field(struct tracing_map *map, + unsigned int offset, + tracing_map_cmp_fn_t cmp_fn); + +extern void tracing_map_destroy(struct tracing_map *map); +extern void tracing_map_clear(struct tracing_map *map); + +extern struct tracing_map_elt * +tracing_map_insert(struct tracing_map *map, void *key); +extern struct tracing_map_elt * +tracing_map_lookup(struct tracing_map *map, void *key); + +extern tracing_map_cmp_fn_t tracing_map_cmp_num(int field_size, + int field_is_signed); +extern int tracing_map_cmp_string(void *val_a, void *val_b); +extern int tracing_map_cmp_none(void *val_a, void *val_b); + +extern void tracing_map_update_sum(struct tracing_map_elt *elt, + unsigned int i, u64 n); +extern u64 tracing_map_read_sum(struct tracing_map_elt *elt, unsigned int i); +extern void tracing_map_set_field_descr(struct tracing_map *map, + unsigned int i, + unsigned int key_offset, + tracing_map_cmp_fn_t cmp_fn); +extern int +tracing_map_sort_entries(struct tracing_map *map, + struct tracing_map_sort_key *sort_keys, + unsigned int n_sort_keys, + struct tracing_map_sort_entry ***sort_entries); + +extern void +tracing_map_destroy_sort_entries(struct tracing_map_sort_entry **entries, + unsigned int n_entries); +#endif /* __TRACING_MAP_H */ -- GitLab From 8d44f2f34fb50f40185ef6404b0047223a27ba82 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 19 Feb 2016 14:47:00 -0500 Subject: [PATCH 3421/9938] tracing: Fix TRACING_MAP Kconfig The config option for TRACING_MAP has "default n", which is not needed because the default of configs is 'n'. Also, since the TRACING_MAP has no config prompt, there's no reason to include "If in doubt, say N" in the help text. Fixed a typo in the comments of tracing_map.h. Signed-off-by: Steven Rostedt --- kernel/trace/Kconfig | 3 --- kernel/trace/tracing_map.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 48b732943e0e..d39556fd863a 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -531,7 +531,6 @@ config MMIOTRACE config TRACING_MAP bool depends on ARCH_HAVE_NMI_SAFE_CMPXCHG - default n help tracing_map is a special-purpose lock-free map for tracing, separated out as a stand-alone facility in order to allow it @@ -539,8 +538,6 @@ config TRACING_MAP generally used outside of that context, and is normally selected by tracers that use it. - If in doubt, say N. - config MMIOTRACE_TEST tristate "Test module for mmiotrace" depends on MMIOTRACE && m diff --git a/kernel/trace/tracing_map.h b/kernel/trace/tracing_map.h index 75718255a8ad..1f7eda548787 100644 --- a/kernel/trace/tracing_map.h +++ b/kernel/trace/tracing_map.h @@ -46,7 +46,7 @@ typedef int (*tracing_map_cmp_fn_t) (void *val_a, void *val_b); * That unique element now in the tracing_map_entry's 'val' field is * an instance of tracing_map_elt, where 'elt' in the latter part of * that variable name is short for 'element'. The purpose of a - * tracing_map_elt is to hold values specific to the the particular + * tracing_map_elt is to hold values specific to the particular * 32-bit hashed key it's assocated with. Things such as the unique * set of aggregated sums associated with the 32-bit hashed key, along * with a copy of the full key associated with the entry, and which -- GitLab From 3b772b96b8338bca2532839b2cd7802800e66037 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:41 -0600 Subject: [PATCH 3422/9938] tracing: Update some tracing_map constants and comments Make it clear exactly how many keys and values are supported through better defines, and add 1 to the vals count, since normally clients want support for at least a hitcount and two other values. Also, note the error return value for tracing_map_add_key/val_field() in the comments. Link: http://lkml.kernel.org/r/6696fa02ebc716aa344c27a571a2afaa25e5b4d4.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt --- kernel/trace/tracing_map.c | 4 ++-- kernel/trace/tracing_map.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index dd6401dd145e..e0f172932eca 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -163,7 +163,7 @@ static int tracing_map_add_field(struct tracing_map *map, * tracing_map_update_sum() or reading it via tracing_map_read_sum(). * * Return: The index identifying the field in the map and associated - * tracing_map_elts. + * tracing_map_elts, or -EINVAL on error. */ int tracing_map_add_sum_field(struct tracing_map *map) { @@ -184,7 +184,7 @@ int tracing_map_add_sum_field(struct tracing_map *map) * the key referenced by this key field resides. * * Return: The index identifying the field in the map and associated - * tracing_map_elts. + * tracing_map_elts, or -EINVAL on error. */ int tracing_map_add_key_field(struct tracing_map *map, unsigned int offset, diff --git a/kernel/trace/tracing_map.h b/kernel/trace/tracing_map.h index 1f7eda548787..618838f5f30a 100644 --- a/kernel/trace/tracing_map.h +++ b/kernel/trace/tracing_map.h @@ -5,9 +5,10 @@ #define TRACING_MAP_BITS_MAX 17 #define TRACING_MAP_BITS_MIN 7 -#define TRACING_MAP_FIELDS_MAX 4 #define TRACING_MAP_KEYS_MAX 2 - +#define TRACING_MAP_VALS_MAX 3 +#define TRACING_MAP_FIELDS_MAX (TRACING_MAP_KEYS_MAX + \ + TRACING_MAP_VALS_MAX) #define TRACING_MAP_SORT_KEYS_MAX 2 typedef int (*tracing_map_cmp_fn_t) (void *val_a, void *val_b); -- GitLab From 7ef224d1d0e3a1ade02d02c01ce1dcffb736d2c3 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:42 -0600 Subject: [PATCH 3423/9938] tracing: Add 'hist' event trigger command 'hist' triggers allow users to continually aggregate trace events, which can then be viewed afterwards by simply reading a 'hist' file containing the aggregation in a human-readable format. The basic idea is very simple and boils down to a mechanism whereby trace events, rather than being exhaustively dumped in raw form and viewed directly, are automatically 'compressed' into meaningful tables completely defined by the user. This is done strictly via single-line command-line commands and without the aid of any kind of programming language or interpreter. A surprising number of typical use cases can be accomplished by users via this simple mechanism. In fact, a large number of the tasks that users typically do using the more complicated script-based tracing tools, at least during the initial stages of an investigation, can be accomplished by simply specifying a set of keys and values to be used in the creation of a hash table. The Linux kernel trace event subsystem happens to provide an extensive list of keys and values ready-made for such a purpose in the form of the event format files associated with each trace event. By simply consulting the format file for field names of interest and by plugging them into the hist trigger command, users can create an endless number of useful aggregations to help with investigating various properties of the system. See Documentation/trace/events.txt for examples. hist triggers are implemented on top of the existing event trigger infrastructure, and as such are consistent with the existing triggers from a user's perspective as well. The basic syntax follows the existing trigger syntax. Users start an aggregation by writing a 'hist' trigger to the event of interest's trigger file: # echo hist:keys=xxx [ if filter] > event/trigger Once a hist trigger has been set up, by default it continually aggregates every matching event into a hash table using the event key and a value field named 'hitcount'. To view the aggregation at any point in time, simply read the 'hist' file in the same directory as the 'trigger' file: # cat event/hist The detailed syntax provides additional options for user control, and is described exhaustively in Documentation/trace/events.txt and in the virtual tracing/README file in the tracing subsystem. Link: http://lkml.kernel.org/r/72d263b5e1853fe9c314953b65833c3aa75479f2.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- include/linux/trace_events.h | 1 + kernel/trace/Kconfig | 16 + kernel/trace/Makefile | 1 + kernel/trace/trace.c | 17 + kernel/trace/trace.h | 7 + kernel/trace/trace_events.c | 4 + kernel/trace/trace_events_hist.c | 849 ++++++++++++++++++++++++++++ kernel/trace/trace_events_trigger.c | 1 + 8 files changed, 896 insertions(+) create mode 100644 kernel/trace/trace_events_hist.c diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 0810f81b6db2..404603720650 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -407,6 +407,7 @@ enum event_trigger_type { ETT_SNAPSHOT = (1 << 1), ETT_STACKTRACE = (1 << 2), ETT_EVENT_ENABLE = (1 << 3), + ETT_EVENT_HIST = (1 << 4), }; extern int filter_match_preds(struct event_filter *filter, void *rec); diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index d39556fd863a..fafeaf803bd0 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -538,6 +538,22 @@ config TRACING_MAP generally used outside of that context, and is normally selected by tracers that use it. +config HIST_TRIGGERS + bool "Histogram triggers" + depends on ARCH_HAVE_NMI_SAFE_CMPXCHG + select TRACING_MAP + default n + help + Hist triggers allow one or more arbitrary trace event fields + to be aggregated into hash tables and dumped to stdout by + reading a debugfs/tracefs file. They're useful for + gathering quick and dirty (though precise) summaries of + event activity as an initial guide for further investigation + using more advanced tools. + + See Documentation/trace/events.txt. + If in doubt, say N. + config MMIOTRACE_TEST tristate "Test module for mmiotrace" depends on MMIOTRACE && m diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 4255c4057aaa..979e7bfbde7a 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o endif obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o obj-$(CONFIG_EVENT_TRACING) += trace_events_trigger.o +obj-$(CONFIG_HIST_TRIGGERS) += trace_events_hist.o obj-$(CONFIG_BPF_EVENTS) += bpf_trace.o obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o obj-$(CONFIG_TRACEPOINTS) += power-traces.o diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 0d12dbde8399..6cf8fd03b028 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3812,6 +3812,9 @@ static const char readme_msg[] = #endif #ifdef CONFIG_TRACER_SNAPSHOT "\t\t snapshot\n" +#endif +#ifdef CONFIG_HIST_TRIGGERS + "\t\t hist (see below)\n" #endif "\t example: echo traceoff > events/block/block_unplug/trigger\n" "\t echo traceoff:3 > events/block/block_unplug/trigger\n" @@ -3828,6 +3831,20 @@ static const char readme_msg[] = "\t To remove a trigger with a count:\n" "\t echo '!:0 > //trigger\n" "\t Filters can be ignored when removing a trigger.\n" +#ifdef CONFIG_HIST_TRIGGERS + " hist trigger\t- If set, event hits are aggregated into a hash table\n" + "\t Format: hist:keys=\n" + "\t [:size=#entries]\n" + "\t [if ]\n\n" + "\t When a matching event is hit, an entry is added to a hash\n" + "\t table using the key named, and the value of a sum called\n" + "\t 'hitcount' is incremented. Keys correspond to fields in the\n" + "\t event's format description. Keys can be any field. The\n" + "\t 'size' parameter can be used to specify more or fewer than\n" + "\t the default 2048 entries for the hashtable size.\n\n" + "\t Reading the 'hist' file for the event will dump the hash\n" + "\t table in its entirety to stdout." +#endif ; static ssize_t diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2525042760e6..505f8a45f426 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1162,6 +1162,13 @@ extern struct mutex event_mutex; extern struct list_head ftrace_events; extern const struct file_operations event_trigger_fops; +extern const struct file_operations event_hist_fops; + +#ifdef CONFIG_HIST_TRIGGERS +extern int register_trigger_hist_cmd(void); +#else +static inline int register_trigger_hist_cmd(void) { return 0; } +#endif extern int register_trigger_cmds(void); extern void clear_event_triggers(struct trace_array *tr); diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index add81dff7520..e7cb983ee93c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2141,6 +2141,10 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) trace_create_file("trigger", 0644, file->dir, file, &event_trigger_fops); +#ifdef CONFIG_HIST_TRIGGERS + trace_create_file("hist", 0444, file->dir, file, + &event_hist_fops); +#endif trace_create_file("format", 0444, file->dir, call, &ftrace_event_format_fops); diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c new file mode 100644 index 000000000000..23b45e462117 --- /dev/null +++ b/kernel/trace/trace_events_hist.c @@ -0,0 +1,849 @@ +/* + * trace_events_hist - trace event hist triggers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2015 Tom Zanussi + */ + +#include +#include +#include +#include +#include + +#include "tracing_map.h" +#include "trace.h" + +struct hist_field; + +typedef u64 (*hist_field_fn_t) (struct hist_field *field, void *event); + +struct hist_field { + struct ftrace_event_field *field; + unsigned long flags; + hist_field_fn_t fn; + unsigned int size; +}; + +static u64 hist_field_counter(struct hist_field *field, void *event) +{ + return 1; +} + +static u64 hist_field_string(struct hist_field *hist_field, void *event) +{ + char *addr = (char *)(event + hist_field->field->offset); + + return (u64)(unsigned long)addr; +} + +#define DEFINE_HIST_FIELD_FN(type) \ +static u64 hist_field_##type(struct hist_field *hist_field, void *event)\ +{ \ + type *addr = (type *)(event + hist_field->field->offset); \ + \ + return (u64)*addr; \ +} + +DEFINE_HIST_FIELD_FN(s64); +DEFINE_HIST_FIELD_FN(u64); +DEFINE_HIST_FIELD_FN(s32); +DEFINE_HIST_FIELD_FN(u32); +DEFINE_HIST_FIELD_FN(s16); +DEFINE_HIST_FIELD_FN(u16); +DEFINE_HIST_FIELD_FN(s8); +DEFINE_HIST_FIELD_FN(u8); + +#define for_each_hist_field(i, hist_data) \ + for ((i) = 0; (i) < (hist_data)->n_fields; (i)++) + +#define for_each_hist_val_field(i, hist_data) \ + for ((i) = 0; (i) < (hist_data)->n_vals; (i)++) + +#define for_each_hist_key_field(i, hist_data) \ + for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++) + +#define HITCOUNT_IDX 0 +#define HIST_KEY_MAX 1 +#define HIST_KEY_SIZE_MAX MAX_FILTER_STR_VAL + +enum hist_field_flags { + HIST_FIELD_FL_HITCOUNT = 1, + HIST_FIELD_FL_KEY = 2, + HIST_FIELD_FL_STRING = 4, +}; + +struct hist_trigger_attrs { + char *keys_str; + unsigned int map_bits; +}; + +struct hist_trigger_data { + struct hist_field *fields[TRACING_MAP_FIELDS_MAX]; + unsigned int n_vals; + unsigned int n_keys; + unsigned int n_fields; + unsigned int key_size; + struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX]; + unsigned int n_sort_keys; + struct trace_event_file *event_file; + struct hist_trigger_attrs *attrs; + struct tracing_map *map; +}; + +static hist_field_fn_t select_value_fn(int field_size, int field_is_signed) +{ + hist_field_fn_t fn = NULL; + + switch (field_size) { + case 8: + if (field_is_signed) + fn = hist_field_s64; + else + fn = hist_field_u64; + break; + case 4: + if (field_is_signed) + fn = hist_field_s32; + else + fn = hist_field_u32; + break; + case 2: + if (field_is_signed) + fn = hist_field_s16; + else + fn = hist_field_u16; + break; + case 1: + if (field_is_signed) + fn = hist_field_s8; + else + fn = hist_field_u8; + break; + } + + return fn; +} + +static int parse_map_size(char *str) +{ + unsigned long size, map_bits; + int ret; + + strsep(&str, "="); + if (!str) { + ret = -EINVAL; + goto out; + } + + ret = kstrtoul(str, 0, &size); + if (ret) + goto out; + + map_bits = ilog2(roundup_pow_of_two(size)); + if (map_bits < TRACING_MAP_BITS_MIN || + map_bits > TRACING_MAP_BITS_MAX) + ret = -EINVAL; + else + ret = map_bits; + out: + return ret; +} + +static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs) +{ + if (!attrs) + return; + + kfree(attrs->keys_str); + kfree(attrs); +} + +static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) +{ + struct hist_trigger_attrs *attrs; + int ret = 0; + + attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); + if (!attrs) + return ERR_PTR(-ENOMEM); + + while (trigger_str) { + char *str = strsep(&trigger_str, ":"); + + if ((strncmp(str, "key=", strlen("key=")) == 0) || + (strncmp(str, "keys=", strlen("keys=")) == 0)) + attrs->keys_str = kstrdup(str, GFP_KERNEL); + else if (strncmp(str, "size=", strlen("size=")) == 0) { + int map_bits = parse_map_size(str); + + if (map_bits < 0) { + ret = map_bits; + goto free; + } + attrs->map_bits = map_bits; + } else { + ret = -EINVAL; + goto free; + } + } + + if (!attrs->keys_str) { + ret = -EINVAL; + goto free; + } + + return attrs; + free: + destroy_hist_trigger_attrs(attrs); + + return ERR_PTR(ret); +} + +static void destroy_hist_field(struct hist_field *hist_field) +{ + kfree(hist_field); +} + +static struct hist_field *create_hist_field(struct ftrace_event_field *field, + unsigned long flags) +{ + struct hist_field *hist_field; + + if (field && is_function_field(field)) + return NULL; + + hist_field = kzalloc(sizeof(struct hist_field), GFP_KERNEL); + if (!hist_field) + return NULL; + + if (flags & HIST_FIELD_FL_HITCOUNT) { + hist_field->fn = hist_field_counter; + goto out; + } + + if (is_string_field(field)) { + flags |= HIST_FIELD_FL_STRING; + hist_field->fn = hist_field_string; + } else { + hist_field->fn = select_value_fn(field->size, + field->is_signed); + if (!hist_field->fn) { + destroy_hist_field(hist_field); + return NULL; + } + } + out: + hist_field->field = field; + hist_field->flags = flags; + + return hist_field; +} + +static void destroy_hist_fields(struct hist_trigger_data *hist_data) +{ + unsigned int i; + + for (i = 0; i < TRACING_MAP_FIELDS_MAX; i++) { + if (hist_data->fields[i]) { + destroy_hist_field(hist_data->fields[i]); + hist_data->fields[i] = NULL; + } + } +} + +static int create_hitcount_val(struct hist_trigger_data *hist_data) +{ + hist_data->fields[HITCOUNT_IDX] = + create_hist_field(NULL, HIST_FIELD_FL_HITCOUNT); + if (!hist_data->fields[HITCOUNT_IDX]) + return -ENOMEM; + + hist_data->n_vals++; + + if (WARN_ON(hist_data->n_vals > TRACING_MAP_VALS_MAX)) + return -EINVAL; + + return 0; +} + +static int create_val_fields(struct hist_trigger_data *hist_data, + struct trace_event_file *file) +{ + int ret; + + ret = create_hitcount_val(hist_data); + + return ret; +} + +static int create_key_field(struct hist_trigger_data *hist_data, + unsigned int key_idx, + struct trace_event_file *file, + char *field_str) +{ + struct ftrace_event_field *field = NULL; + unsigned long flags = 0; + unsigned int key_size; + int ret = 0; + + if (WARN_ON(key_idx >= TRACING_MAP_FIELDS_MAX)) + return -EINVAL; + + flags |= HIST_FIELD_FL_KEY; + + field = trace_find_event_field(file->event_call, field_str); + if (!field) { + ret = -EINVAL; + goto out; + } + + key_size = field->size; + + hist_data->fields[key_idx] = create_hist_field(field, flags); + if (!hist_data->fields[key_idx]) { + ret = -ENOMEM; + goto out; + } + + key_size = ALIGN(key_size, sizeof(u64)); + hist_data->fields[key_idx]->size = key_size; + hist_data->key_size = key_size; + if (hist_data->key_size > HIST_KEY_SIZE_MAX) { + ret = -EINVAL; + goto out; + } + + hist_data->n_keys++; + + if (WARN_ON(hist_data->n_keys > TRACING_MAP_KEYS_MAX)) + return -EINVAL; + + ret = key_size; + out: + return ret; +} + +static int create_key_fields(struct hist_trigger_data *hist_data, + struct trace_event_file *file) +{ + unsigned int i, n_vals = hist_data->n_vals; + char *fields_str, *field_str; + int ret = -EINVAL; + + fields_str = hist_data->attrs->keys_str; + if (!fields_str) + goto out; + + strsep(&fields_str, "="); + if (!fields_str) + goto out; + + for (i = n_vals; i < n_vals + HIST_KEY_MAX; i++) { + field_str = strsep(&fields_str, ","); + if (!field_str) + break; + ret = create_key_field(hist_data, i, file, field_str); + if (ret < 0) + goto out; + } + if (fields_str) { + ret = -EINVAL; + goto out; + } + ret = 0; + out: + return ret; +} + +static int create_hist_fields(struct hist_trigger_data *hist_data, + struct trace_event_file *file) +{ + int ret; + + ret = create_val_fields(hist_data, file); + if (ret) + goto out; + + ret = create_key_fields(hist_data, file); + if (ret) + goto out; + + hist_data->n_fields = hist_data->n_vals + hist_data->n_keys; + out: + return ret; +} + +static int create_sort_keys(struct hist_trigger_data *hist_data) +{ + int ret = 0; + + hist_data->n_sort_keys = 1; /* sort_keys[0] is always hitcount */ + + return ret; +} + +static void destroy_hist_data(struct hist_trigger_data *hist_data) +{ + destroy_hist_trigger_attrs(hist_data->attrs); + destroy_hist_fields(hist_data); + tracing_map_destroy(hist_data->map); + kfree(hist_data); +} + +static int create_tracing_map_fields(struct hist_trigger_data *hist_data) +{ + struct tracing_map *map = hist_data->map; + struct ftrace_event_field *field; + struct hist_field *hist_field; + unsigned int i, idx; + + for_each_hist_field(i, hist_data) { + hist_field = hist_data->fields[i]; + if (hist_field->flags & HIST_FIELD_FL_KEY) { + tracing_map_cmp_fn_t cmp_fn; + + field = hist_field->field; + + if (is_string_field(field)) + cmp_fn = tracing_map_cmp_string; + else + cmp_fn = tracing_map_cmp_num(field->size, + field->is_signed); + idx = tracing_map_add_key_field(map, 0, cmp_fn); + } else + idx = tracing_map_add_sum_field(map); + + if (idx < 0) + return idx; + } + + return 0; +} + +static struct hist_trigger_data * +create_hist_data(unsigned int map_bits, + struct hist_trigger_attrs *attrs, + struct trace_event_file *file) +{ + struct hist_trigger_data *hist_data; + int ret = 0; + + hist_data = kzalloc(sizeof(*hist_data), GFP_KERNEL); + if (!hist_data) + return ERR_PTR(-ENOMEM); + + hist_data->attrs = attrs; + + ret = create_hist_fields(hist_data, file); + if (ret) + goto free; + + ret = create_sort_keys(hist_data); + if (ret) + goto free; + + hist_data->map = tracing_map_create(map_bits, hist_data->key_size, + NULL, hist_data); + if (IS_ERR(hist_data->map)) { + ret = PTR_ERR(hist_data->map); + hist_data->map = NULL; + goto free; + } + + ret = create_tracing_map_fields(hist_data); + if (ret) + goto free; + + ret = tracing_map_init(hist_data->map); + if (ret) + goto free; + + hist_data->event_file = file; + out: + return hist_data; + free: + hist_data->attrs = NULL; + + destroy_hist_data(hist_data); + + hist_data = ERR_PTR(ret); + + goto out; +} + +static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, + struct tracing_map_elt *elt, + void *rec) +{ + struct hist_field *hist_field; + unsigned int i; + u64 hist_val; + + for_each_hist_val_field(i, hist_data) { + hist_field = hist_data->fields[i]; + hist_val = hist_field->fn(hist_field, rec); + tracing_map_update_sum(elt, i, hist_val); + } +} + +static void event_hist_trigger(struct event_trigger_data *data, void *rec) +{ + struct hist_trigger_data *hist_data = data->private_data; + struct hist_field *key_field; + struct tracing_map_elt *elt; + u64 field_contents; + void *key = NULL; + unsigned int i; + + for_each_hist_key_field(i, hist_data) { + key_field = hist_data->fields[i]; + + field_contents = key_field->fn(key_field, rec); + if (key_field->flags & HIST_FIELD_FL_STRING) + key = (void *)(unsigned long)field_contents; + else + key = (void *)&field_contents; + } + + elt = tracing_map_insert(hist_data->map, key); + if (elt) + hist_trigger_elt_update(hist_data, elt, rec); +} + +static void +hist_trigger_entry_print(struct seq_file *m, + struct hist_trigger_data *hist_data, void *key, + struct tracing_map_elt *elt) +{ + struct hist_field *key_field; + unsigned int i; + u64 uval; + + seq_puts(m, "{ "); + + for_each_hist_key_field(i, hist_data) { + key_field = hist_data->fields[i]; + + if (i > hist_data->n_vals) + seq_puts(m, ", "); + + if (key_field->flags & HIST_FIELD_FL_STRING) { + seq_printf(m, "%s: %-50s", key_field->field->name, + (char *)key); + } else { + uval = *(u64 *)key; + seq_printf(m, "%s: %10llu", + key_field->field->name, uval); + } + } + + seq_puts(m, " }"); + + seq_printf(m, " hitcount: %10llu", + tracing_map_read_sum(elt, HITCOUNT_IDX)); + + seq_puts(m, "\n"); +} + +static int print_entries(struct seq_file *m, + struct hist_trigger_data *hist_data) +{ + struct tracing_map_sort_entry **sort_entries = NULL; + struct tracing_map *map = hist_data->map; + unsigned int i, n_entries; + + n_entries = tracing_map_sort_entries(map, hist_data->sort_keys, + hist_data->n_sort_keys, + &sort_entries); + if (n_entries < 0) + return n_entries; + + for (i = 0; i < n_entries; i++) + hist_trigger_entry_print(m, hist_data, + sort_entries[i]->key, + sort_entries[i]->elt); + + tracing_map_destroy_sort_entries(sort_entries, n_entries); + + return n_entries; +} + +static int hist_show(struct seq_file *m, void *v) +{ + struct event_trigger_data *test, *data = NULL; + struct trace_event_file *event_file; + struct hist_trigger_data *hist_data; + int n_entries, ret = 0; + + mutex_lock(&event_mutex); + + event_file = event_file_data(m->private); + if (unlikely(!event_file)) { + ret = -ENODEV; + goto out_unlock; + } + + list_for_each_entry_rcu(test, &event_file->triggers, list) { + if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { + data = test; + break; + } + } + if (!data) + goto out_unlock; + + seq_puts(m, "# event histogram\n#\n# trigger info: "); + data->ops->print(m, data->ops, data); + seq_puts(m, "\n"); + + hist_data = data->private_data; + n_entries = print_entries(m, hist_data); + if (n_entries < 0) { + ret = n_entries; + n_entries = 0; + } + + seq_printf(m, "\nTotals:\n Hits: %llu\n Entries: %u\n Dropped: %llu\n", + (u64)atomic64_read(&hist_data->map->hits), + n_entries, (u64)atomic64_read(&hist_data->map->drops)); + out_unlock: + mutex_unlock(&event_mutex); + + return ret; +} + +static int event_hist_open(struct inode *inode, struct file *file) +{ + return single_open(file, hist_show, file); +} + +const struct file_operations event_hist_fops = { + .open = event_hist_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void hist_field_print(struct seq_file *m, struct hist_field *hist_field) +{ + seq_printf(m, "%s", hist_field->field->name); +} + +static int event_hist_trigger_print(struct seq_file *m, + struct event_trigger_ops *ops, + struct event_trigger_data *data) +{ + struct hist_trigger_data *hist_data = data->private_data; + struct hist_field *key_field; + unsigned int i; + + seq_puts(m, "hist:keys="); + + for_each_hist_key_field(i, hist_data) { + key_field = hist_data->fields[i]; + + if (i > hist_data->n_vals) + seq_puts(m, ","); + + hist_field_print(m, key_field); + } + + seq_puts(m, ":vals="); + seq_puts(m, "hitcount"); + + seq_puts(m, ":sort="); + seq_puts(m, "hitcount"); + + seq_printf(m, ":size=%u", (1 << hist_data->map->map_bits)); + + if (data->filter_str) + seq_printf(m, " if %s", data->filter_str); + + seq_puts(m, " [active]"); + + seq_putc(m, '\n'); + + return 0; +} + +static void event_hist_trigger_free(struct event_trigger_ops *ops, + struct event_trigger_data *data) +{ + struct hist_trigger_data *hist_data = data->private_data; + + if (WARN_ON_ONCE(data->ref <= 0)) + return; + + data->ref--; + if (!data->ref) { + trigger_data_free(data); + destroy_hist_data(hist_data); + } +} + +static struct event_trigger_ops event_hist_trigger_ops = { + .func = event_hist_trigger, + .print = event_hist_trigger_print, + .init = event_trigger_init, + .free = event_hist_trigger_free, +}; + +static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd, + char *param) +{ + return &event_hist_trigger_ops; +} + +static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, + struct event_trigger_data *data, + struct trace_event_file *file) +{ + struct event_trigger_data *test; + int ret = 0; + + list_for_each_entry_rcu(test, &file->triggers, list) { + if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { + ret = -EEXIST; + goto out; + } + } + + if (data->ops->init) { + ret = data->ops->init(data->ops, data); + if (ret < 0) + goto out; + } + + list_add_rcu(&data->list, &file->triggers); + ret++; + + update_cond_flag(file); + if (trace_event_trigger_enable_disable(file, 1) < 0) { + list_del_rcu(&data->list); + update_cond_flag(file); + ret--; + } + out: + return ret; +} + +static int event_hist_trigger_func(struct event_command *cmd_ops, + struct trace_event_file *file, + char *glob, char *cmd, char *param) +{ + unsigned int hist_trigger_bits = TRACING_MAP_BITS_DEFAULT; + struct event_trigger_data *trigger_data; + struct hist_trigger_attrs *attrs; + struct event_trigger_ops *trigger_ops; + struct hist_trigger_data *hist_data; + char *trigger; + int ret = 0; + + if (!param) + return -EINVAL; + + /* separate the trigger from the filter (k:v [if filter]) */ + trigger = strsep(¶m, " \t"); + if (!trigger) + return -EINVAL; + + attrs = parse_hist_trigger_attrs(trigger); + if (IS_ERR(attrs)) + return PTR_ERR(attrs); + + if (attrs->map_bits) + hist_trigger_bits = attrs->map_bits; + + hist_data = create_hist_data(hist_trigger_bits, attrs, file); + if (IS_ERR(hist_data)) { + destroy_hist_trigger_attrs(attrs); + return PTR_ERR(hist_data); + } + + trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger); + + ret = -ENOMEM; + trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL); + if (!trigger_data) + goto out_free; + + trigger_data->count = -1; + trigger_data->ops = trigger_ops; + trigger_data->cmd_ops = cmd_ops; + + INIT_LIST_HEAD(&trigger_data->list); + RCU_INIT_POINTER(trigger_data->filter, NULL); + + trigger_data->private_data = hist_data; + + if (glob[0] == '!') { + cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file); + ret = 0; + goto out_free; + } + + if (!param) /* if param is non-empty, it's supposed to be a filter */ + goto out_reg; + + if (!cmd_ops->set_filter) + goto out_reg; + + ret = cmd_ops->set_filter(param, trigger_data, file); + if (ret < 0) + goto out_free; + out_reg: + ret = cmd_ops->reg(glob, trigger_ops, trigger_data, file); + /* + * The above returns on success the # of triggers registered, + * but if it didn't register any it returns zero. Consider no + * triggers registered a failure too. + */ + if (!ret) { + ret = -ENOENT; + goto out_free; + } else if (ret < 0) + goto out_free; + /* Just return zero, not the number of registered triggers */ + ret = 0; + out: + return ret; + out_free: + if (cmd_ops->set_filter) + cmd_ops->set_filter(NULL, trigger_data, NULL); + + kfree(trigger_data); + + destroy_hist_data(hist_data); + goto out; +} + +static struct event_command trigger_hist_cmd = { + .name = "hist", + .trigger_type = ETT_EVENT_HIST, + .flags = EVENT_CMD_FL_NEEDS_REC, + .func = event_hist_trigger_func, + .reg = hist_register_trigger, + .unreg = unregister_trigger, + .get_trigger_ops = event_hist_get_trigger_ops, + .set_filter = set_trigger_filter, +}; + +__init int register_trigger_hist_cmd(void) +{ + int ret; + + ret = register_event_command(&trigger_hist_cmd); + WARN_ON(ret < 0); + + return ret; +} diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index d67992f3bb0e..d29092afe005 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -1447,6 +1447,7 @@ __init int register_trigger_cmds(void) register_trigger_snapshot_cmd(); register_trigger_stacktrace_cmd(); register_trigger_enable_disable_cmds(); + register_trigger_hist_cmd(); return 0; } -- GitLab From f2606835d70d2a2e6a134f01821da8149e124796 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:43 -0600 Subject: [PATCH 3424/9938] tracing: Add hist trigger support for multiple values ('vals=' param) Allow users to specify trace event fields to use in aggregated sums via a new 'vals=' keyword. Before this addition, the only aggregated sum supported was the implied value 'hitcount'. With this addition, 'hitcount' is also supported as an explicit value field, as is any numeric trace event field. This expands the hist trigger syntax from this: # echo hist:keys=xxx [ if filter] > event/trigger to this: # echo hist:keys=xxx:vals=yyy [ if filter] > event/trigger Link: http://lkml.kernel.org/r/2a5d1adb5ba6c65d7bb2148e379f2fed47f29a68.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 12 +++-- kernel/trace/trace_events_hist.c | 79 +++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 6cf8fd03b028..bb62f54c5480 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3834,14 +3834,16 @@ static const char readme_msg[] = #ifdef CONFIG_HIST_TRIGGERS " hist trigger\t- If set, event hits are aggregated into a hash table\n" "\t Format: hist:keys=\n" + "\t [:values=]\n" "\t [:size=#entries]\n" "\t [if ]\n\n" "\t When a matching event is hit, an entry is added to a hash\n" - "\t table using the key named, and the value of a sum called\n" - "\t 'hitcount' is incremented. Keys correspond to fields in the\n" - "\t event's format description. Keys can be any field. The\n" - "\t 'size' parameter can be used to specify more or fewer than\n" - "\t the default 2048 entries for the hashtable size.\n\n" + "\t table using the key(s) and value(s) named, and the value of a\n" + "\t sum called 'hitcount' is incremented. Keys and values\n" + "\t correspond to fields in the event's format description. Keys\n" + "\t can be any field. Values must correspond to numeric fields.\n" + "\t The 'size' parameter can be used to specify more or fewer\n" + "\t than the default 2048 entries for the hashtable size.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" "\t table in its entirety to stdout." #endif diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 23b45e462117..1b33590b9c8f 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -84,6 +84,7 @@ enum hist_field_flags { struct hist_trigger_attrs { char *keys_str; + char *vals_str; unsigned int map_bits; }; @@ -165,6 +166,7 @@ static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs) return; kfree(attrs->keys_str); + kfree(attrs->vals_str); kfree(attrs); } @@ -183,6 +185,10 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) if ((strncmp(str, "key=", strlen("key=")) == 0) || (strncmp(str, "keys=", strlen("keys=")) == 0)) attrs->keys_str = kstrdup(str, GFP_KERNEL); + else if ((strncmp(str, "val=", strlen("val=")) == 0) || + (strncmp(str, "vals=", strlen("vals=")) == 0) || + (strncmp(str, "values=", strlen("values=")) == 0)) + attrs->vals_str = kstrdup(str, GFP_KERNEL); else if (strncmp(str, "size=", strlen("size=")) == 0) { int map_bits = parse_map_size(str); @@ -276,13 +282,70 @@ static int create_hitcount_val(struct hist_trigger_data *hist_data) return 0; } +static int create_val_field(struct hist_trigger_data *hist_data, + unsigned int val_idx, + struct trace_event_file *file, + char *field_str) +{ + struct ftrace_event_field *field = NULL; + unsigned long flags = 0; + int ret = 0; + + if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX)) + return -EINVAL; + field = trace_find_event_field(file->event_call, field_str); + if (!field) { + ret = -EINVAL; + goto out; + } + + hist_data->fields[val_idx] = create_hist_field(field, flags); + if (!hist_data->fields[val_idx]) { + ret = -ENOMEM; + goto out; + } + + ++hist_data->n_vals; + + if (WARN_ON(hist_data->n_vals > TRACING_MAP_VALS_MAX)) + ret = -EINVAL; + out: + return ret; +} + static int create_val_fields(struct hist_trigger_data *hist_data, struct trace_event_file *file) { + char *fields_str, *field_str; + unsigned int i, j; int ret; ret = create_hitcount_val(hist_data); + if (ret) + goto out; + fields_str = hist_data->attrs->vals_str; + if (!fields_str) + goto out; + + strsep(&fields_str, "="); + if (!fields_str) + goto out; + + for (i = 0, j = 1; i < TRACING_MAP_VALS_MAX && + j < TRACING_MAP_VALS_MAX; i++) { + field_str = strsep(&fields_str, ","); + if (!field_str) + break; + if (strcmp(field_str, "hitcount") == 0) + continue; + ret = create_val_field(hist_data, j++, file, field_str); + if (ret) + goto out; + } + if (fields_str && (strcmp(fields_str, "hitcount") != 0)) + ret = -EINVAL; + out: return ret; } @@ -552,6 +615,12 @@ hist_trigger_entry_print(struct seq_file *m, seq_printf(m, " hitcount: %10llu", tracing_map_read_sum(elt, HITCOUNT_IDX)); + for (i = 1; i < hist_data->n_vals; i++) { + seq_printf(m, " %s: %10llu", + hist_data->fields[i]->field->name, + tracing_map_read_sum(elt, i)); + } + seq_puts(m, "\n"); } @@ -659,7 +728,15 @@ static int event_hist_trigger_print(struct seq_file *m, } seq_puts(m, ":vals="); - seq_puts(m, "hitcount"); + + for_each_hist_val_field(i, hist_data) { + if (i == HITCOUNT_IDX) + seq_puts(m, "hitcount"); + else { + seq_puts(m, ","); + hist_field_print(m, hist_data->fields[i]); + } + } seq_puts(m, ":sort="); seq_puts(m, "hitcount"); -- GitLab From 76a3b0c8ac344e1d0f436160cbb59b670b086947 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:44 -0600 Subject: [PATCH 3425/9938] tracing: Add hist trigger support for compound keys Allow users to specify multiple trace event fields to use in keys by allowing multiple fields in the 'keys=' keyword. With this addition, any unique combination of any of the fields named in the 'keys' keyword will result in a new entry being added to the hash table. Link: http://lkml.kernel.org/r/0cfa24e6ac3b0dcece7737d94aa1f322ae3afc4b.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 10 ++++---- kernel/trace/trace_events_hist.c | 41 +++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index bb62f54c5480..7a4c4dcf0bfe 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3833,7 +3833,7 @@ static const char readme_msg[] = "\t Filters can be ignored when removing a trigger.\n" #ifdef CONFIG_HIST_TRIGGERS " hist trigger\t- If set, event hits are aggregated into a hash table\n" - "\t Format: hist:keys=\n" + "\t Format: hist:keys=\n" "\t [:values=]\n" "\t [:size=#entries]\n" "\t [if ]\n\n" @@ -3841,9 +3841,11 @@ static const char readme_msg[] = "\t table using the key(s) and value(s) named, and the value of a\n" "\t sum called 'hitcount' is incremented. Keys and values\n" "\t correspond to fields in the event's format description. Keys\n" - "\t can be any field. Values must correspond to numeric fields.\n" - "\t The 'size' parameter can be used to specify more or fewer\n" - "\t than the default 2048 entries for the hashtable size.\n\n" + "\t can be any field. Compound keys consisting of up to two\n" + "\t fields can be specified by the 'keys' keyword. Values must\n" + "\t correspond to numeric fields. The 'size' parameter can be\n" + "\t used to specify more or fewer than the default 2048 entries\n" + "\t for the hashtable size.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" "\t table in its entirety to stdout." #endif diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 1b33590b9c8f..65fdfc6cb633 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -32,6 +32,7 @@ struct hist_field { unsigned long flags; hist_field_fn_t fn; unsigned int size; + unsigned int offset; }; static u64 hist_field_counter(struct hist_field *field, void *event) @@ -73,8 +74,7 @@ DEFINE_HIST_FIELD_FN(u8); for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++) #define HITCOUNT_IDX 0 -#define HIST_KEY_MAX 1 -#define HIST_KEY_SIZE_MAX MAX_FILTER_STR_VAL +#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + sizeof(u64)) enum hist_field_flags { HIST_FIELD_FL_HITCOUNT = 1, @@ -351,6 +351,7 @@ static int create_val_fields(struct hist_trigger_data *hist_data, static int create_key_field(struct hist_trigger_data *hist_data, unsigned int key_idx, + unsigned int key_offset, struct trace_event_file *file, char *field_str) { @@ -380,7 +381,8 @@ static int create_key_field(struct hist_trigger_data *hist_data, key_size = ALIGN(key_size, sizeof(u64)); hist_data->fields[key_idx]->size = key_size; - hist_data->key_size = key_size; + hist_data->fields[key_idx]->offset = key_offset; + hist_data->key_size += key_size; if (hist_data->key_size > HIST_KEY_SIZE_MAX) { ret = -EINVAL; goto out; @@ -399,7 +401,7 @@ static int create_key_field(struct hist_trigger_data *hist_data, static int create_key_fields(struct hist_trigger_data *hist_data, struct trace_event_file *file) { - unsigned int i, n_vals = hist_data->n_vals; + unsigned int i, key_offset = 0, n_vals = hist_data->n_vals; char *fields_str, *field_str; int ret = -EINVAL; @@ -411,13 +413,15 @@ static int create_key_fields(struct hist_trigger_data *hist_data, if (!fields_str) goto out; - for (i = n_vals; i < n_vals + HIST_KEY_MAX; i++) { + for (i = n_vals; i < n_vals + TRACING_MAP_KEYS_MAX; i++) { field_str = strsep(&fields_str, ","); if (!field_str) break; - ret = create_key_field(hist_data, i, file, field_str); + ret = create_key_field(hist_data, i, key_offset, + file, field_str); if (ret < 0) goto out; + key_offset += ret; } if (fields_str) { ret = -EINVAL; @@ -482,7 +486,10 @@ static int create_tracing_map_fields(struct hist_trigger_data *hist_data) else cmp_fn = tracing_map_cmp_num(field->size, field->is_signed); - idx = tracing_map_add_key_field(map, 0, cmp_fn); + idx = tracing_map_add_key_field(map, + hist_field->offset, + cmp_fn); + } else idx = tracing_map_add_sum_field(map); @@ -562,12 +569,16 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, static void event_hist_trigger(struct event_trigger_data *data, void *rec) { struct hist_trigger_data *hist_data = data->private_data; + char compound_key[HIST_KEY_SIZE_MAX]; struct hist_field *key_field; struct tracing_map_elt *elt; u64 field_contents; void *key = NULL; unsigned int i; + if (hist_data->n_keys > 1) + memset(compound_key, 0, hist_data->key_size); + for_each_hist_key_field(i, hist_data) { key_field = hist_data->fields[i]; @@ -576,8 +587,16 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) key = (void *)(unsigned long)field_contents; else key = (void *)&field_contents; + + if (hist_data->n_keys > 1) { + memcpy(compound_key + key_field->offset, key, + key_field->size); + } } + if (hist_data->n_keys > 1) + key = compound_key; + elt = tracing_map_insert(hist_data->map, key); if (elt) hist_trigger_elt_update(hist_data, elt, rec); @@ -602,11 +621,11 @@ hist_trigger_entry_print(struct seq_file *m, if (key_field->flags & HIST_FIELD_FL_STRING) { seq_printf(m, "%s: %-50s", key_field->field->name, - (char *)key); + (char *)(key + key_field->offset)); } else { - uval = *(u64 *)key; - seq_printf(m, "%s: %10llu", - key_field->field->name, uval); + uval = *(u64 *)(key + key_field->offset); + seq_printf(m, "%s: %10llu", key_field->field->name, + uval); } } -- GitLab From e62347d2453474fa514fbbbc4636313d34d3c850 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:45 -0600 Subject: [PATCH 3426/9938] tracing: Add hist trigger support for user-defined sorting ('sort=' param) Allow users to specify keys and/or values to sort on. With this addition, keys and values specified using the 'keys=' and 'vals=' keywords can be used to sort the hist trigger output via a new 'sort=' keyword. If multiple sort keys are specified, the output will be sorted using the second key as a secondary sort key, etc. The default sort order is ascending; if the user wants a different sort order, '.descending' can be appended to the specific sort key. Before this addition, output was always sorted by 'hitcount' in ascending order. This expands the hist trigger syntax from this: # echo hist:keys=xxx:vals=yyy \ [ if filter] > event/trigger to this: # echo hist:keys=xxx:vals=yyy:sort=zzz.descending \ [ if filter] > event/trigger Link: http://lkml.kernel.org/r/b30a41db66ba486979c4f987aff5fab500ea53b3.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 6 +- kernel/trace/trace_events_hist.c | 112 ++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7a4c4dcf0bfe..d16fa8e1cdbf 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3835,6 +3835,7 @@ static const char readme_msg[] = " hist trigger\t- If set, event hits are aggregated into a hash table\n" "\t Format: hist:keys=\n" "\t [:values=]\n" + "\t [:sort=]\n" "\t [:size=#entries]\n" "\t [if ]\n\n" "\t When a matching event is hit, an entry is added to a hash\n" @@ -3843,7 +3844,10 @@ static const char readme_msg[] = "\t correspond to fields in the event's format description. Keys\n" "\t can be any field. Compound keys consisting of up to two\n" "\t fields can be specified by the 'keys' keyword. Values must\n" - "\t correspond to numeric fields. The 'size' parameter can be\n" + "\t correspond to numeric fields. Sort keys consisting of up to\n" + "\t two fields can be specified using the 'sort' keyword. The\n" + "\t sort direction can be modified by appending '.descending' or\n" + "\t '.ascending' to a sort field. The 'size' parameter can be\n" "\t used to specify more or fewer than the default 2048 entries\n" "\t for the hashtable size.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 65fdfc6cb633..03ba4530c08c 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -85,6 +85,7 @@ enum hist_field_flags { struct hist_trigger_attrs { char *keys_str; char *vals_str; + char *sort_key_str; unsigned int map_bits; }; @@ -165,6 +166,7 @@ static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs) if (!attrs) return; + kfree(attrs->sort_key_str); kfree(attrs->keys_str); kfree(attrs->vals_str); kfree(attrs); @@ -189,6 +191,8 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) (strncmp(str, "vals=", strlen("vals=")) == 0) || (strncmp(str, "values=", strlen("values=")) == 0)) attrs->vals_str = kstrdup(str, GFP_KERNEL); + else if (strncmp(str, "sort=", strlen("sort=")) == 0) + attrs->sort_key_str = kstrdup(str, GFP_KERNEL); else if (strncmp(str, "size=", strlen("size=")) == 0) { int map_bits = parse_map_size(str); @@ -450,12 +454,92 @@ static int create_hist_fields(struct hist_trigger_data *hist_data, return ret; } +static int is_descending(const char *str) +{ + if (!str) + return 0; + + if (strcmp(str, "descending") == 0) + return 1; + + if (strcmp(str, "ascending") == 0) + return 0; + + return -EINVAL; +} + static int create_sort_keys(struct hist_trigger_data *hist_data) { - int ret = 0; + char *fields_str = hist_data->attrs->sort_key_str; + struct ftrace_event_field *field = NULL; + struct tracing_map_sort_key *sort_key; + int descending, ret = 0; + unsigned int i, j; + + hist_data->n_sort_keys = 1; /* we always have at least one, hitcount */ + + if (!fields_str) + goto out; + + strsep(&fields_str, "="); + if (!fields_str) { + ret = -EINVAL; + goto out; + } + + for (i = 0; i < TRACING_MAP_SORT_KEYS_MAX; i++) { + char *field_str, *field_name; + + sort_key = &hist_data->sort_keys[i]; + + field_str = strsep(&fields_str, ","); + if (!field_str) { + if (i == 0) + ret = -EINVAL; + break; + } + + if ((i == TRACING_MAP_SORT_KEYS_MAX - 1) && fields_str) { + ret = -EINVAL; + break; + } - hist_data->n_sort_keys = 1; /* sort_keys[0] is always hitcount */ + field_name = strsep(&field_str, "."); + if (!field_name) { + ret = -EINVAL; + break; + } + + if (strcmp(field_name, "hitcount") == 0) { + descending = is_descending(field_str); + if (descending < 0) { + ret = descending; + break; + } + sort_key->descending = descending; + continue; + } + for (j = 1; j < hist_data->n_fields; j++) { + field = hist_data->fields[j]->field; + if (field && (strcmp(field_name, field->name) == 0)) { + sort_key->field_idx = j; + descending = is_descending(field_str); + if (descending < 0) { + ret = descending; + goto out; + } + sort_key->descending = descending; + break; + } + } + if (j == hist_data->n_fields) { + ret = -EINVAL; + break; + } + } + hist_data->n_sort_keys = i; + out: return ret; } @@ -758,7 +842,29 @@ static int event_hist_trigger_print(struct seq_file *m, } seq_puts(m, ":sort="); - seq_puts(m, "hitcount"); + + for (i = 0; i < hist_data->n_sort_keys; i++) { + struct tracing_map_sort_key *sort_key; + + sort_key = &hist_data->sort_keys[i]; + + if (i > 0) + seq_puts(m, ","); + + if (sort_key->field_idx == HITCOUNT_IDX) + seq_puts(m, "hitcount"); + else { + unsigned int idx = sort_key->field_idx; + + if (WARN_ON(idx >= TRACING_MAP_FIELDS_MAX)) + return -EINVAL; + + hist_field_print(m, hist_data->fields[idx]); + } + + if (sort_key->descending) + seq_puts(m, ".descending"); + } seq_printf(m, ":size=%u", (1 << hist_data->map->map_bits)); -- GitLab From 83e99914c9e2677d8a80f2a23eca0d215d5bfb0f Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:46 -0600 Subject: [PATCH 3427/9938] tracing: Add hist trigger support for pausing and continuing a trace Allow users to append 'pause' or 'continue' to an existing trigger in order to have it paused or to have a paused trace continue. This expands the hist trigger syntax from this: # echo hist:keys=xxx:vals=yyy:sort=zzz.descending \ [ if filter] >> event/trigger to this: # echo hist:keys=xxx:vals=yyy:sort=zzz.descending:pause or cont \ [ if filter] >> event/trigger Link: http://lkml.kernel.org/r/b672a92c14702cb924cdf6fc27ea1809bed04907.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 7 ++++++- kernel/trace/trace_events_hist.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d16fa8e1cdbf..7d5c63dd410a 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3837,6 +3837,7 @@ static const char readme_msg[] = "\t [:values=]\n" "\t [:sort=]\n" "\t [:size=#entries]\n" + "\t [:pause][:continue]\n" "\t [if ]\n\n" "\t When a matching event is hit, an entry is added to a hash\n" "\t table using the key(s) and value(s) named, and the value of a\n" @@ -3851,7 +3852,11 @@ static const char readme_msg[] = "\t used to specify more or fewer than the default 2048 entries\n" "\t for the hashtable size.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" - "\t table in its entirety to stdout." + "\t table in its entirety to stdout.\n\n" + "\t The 'pause' parameter can be used to pause an existing hist\n" + "\t trigger or to start a hist trigger but not log any events\n" + "\t until told to do so. 'continue' can be used to start or\n" + "\t restart a paused hist trigger.\n\n" #endif ; diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 03ba4530c08c..e3fa9c89f125 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -86,6 +86,8 @@ struct hist_trigger_attrs { char *keys_str; char *vals_str; char *sort_key_str; + bool pause; + bool cont; unsigned int map_bits; }; @@ -193,6 +195,11 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) attrs->vals_str = kstrdup(str, GFP_KERNEL); else if (strncmp(str, "sort=", strlen("sort=")) == 0) attrs->sort_key_str = kstrdup(str, GFP_KERNEL); + else if (strcmp(str, "pause") == 0) + attrs->pause = true; + else if ((strcmp(str, "cont") == 0) || + (strcmp(str, "continue") == 0)) + attrs->cont = true; else if (strncmp(str, "size=", strlen("size=")) == 0) { int map_bits = parse_map_size(str); @@ -871,7 +878,10 @@ static int event_hist_trigger_print(struct seq_file *m, if (data->filter_str) seq_printf(m, " if %s", data->filter_str); - seq_puts(m, " [active]"); + if (data->paused) + seq_puts(m, " [paused]"); + else + seq_puts(m, " [active]"); seq_putc(m, '\n'); @@ -910,16 +920,30 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, struct event_trigger_data *data, struct trace_event_file *file) { + struct hist_trigger_data *hist_data = data->private_data; struct event_trigger_data *test; int ret = 0; list_for_each_entry_rcu(test, &file->triggers, list) { if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { - ret = -EEXIST; + if (hist_data->attrs->pause) + test->paused = true; + else if (hist_data->attrs->cont) + test->paused = false; + else + ret = -EEXIST; goto out; } } + if (hist_data->attrs->cont) { + ret = -ENOENT; + goto out; + } + + if (hist_data->attrs->pause) + data->paused = true; + if (data->ops->init) { ret = data->ops->init(data->ops, data); if (ret < 0) @@ -1011,7 +1035,8 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, * triggers registered a failure too. */ if (!ret) { - ret = -ENOENT; + if (!(attrs->pause || attrs->cont)) + ret = -ENOENT; goto out_free; } else if (ret < 0) goto out_free; -- GitLab From e86ae9baacfa9efe957df4fc037f079772636d76 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:47 -0600 Subject: [PATCH 3428/9938] tracing: Add hist trigger support for clearing a trace Allow users to append 'clear' to an existing trigger in order to have the hash table cleared. This expands the hist trigger syntax from this: # echo hist:keys=xxx:vals=yyy:sort=zzz.descending:pause/cont \ [ if filter] >> event/trigger to this: # echo hist:keys=xxx:vals=yyy:sort=zzz.descending:pause/cont/clear \ [ if filter] >> event/trigger Link: http://lkml.kernel.org/r/ae15dd0d9b2f7af07a37c1ff682063e2dbcdf160.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 5 ++++- kernel/trace/trace_events_hist.c | 24 ++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7d5c63dd410a..4097cd3763f7 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3837,7 +3837,7 @@ static const char readme_msg[] = "\t [:values=]\n" "\t [:sort=]\n" "\t [:size=#entries]\n" - "\t [:pause][:continue]\n" + "\t [:pause][:continue][:clear]\n" "\t [if ]\n\n" "\t When a matching event is hit, an entry is added to a hash\n" "\t table using the key(s) and value(s) named, and the value of a\n" @@ -3857,6 +3857,9 @@ static const char readme_msg[] = "\t trigger or to start a hist trigger but not log any events\n" "\t until told to do so. 'continue' can be used to start or\n" "\t restart a paused hist trigger.\n\n" + "\t The 'clear' parameter will clear the contents of a running\n" + "\t hist trigger and leave its current paused/active state\n" + "\t unchanged.\n\n" #endif ; diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index e3fa9c89f125..83cb25e067ad 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -88,6 +88,7 @@ struct hist_trigger_attrs { char *sort_key_str; bool pause; bool cont; + bool clear; unsigned int map_bits; }; @@ -200,6 +201,8 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) else if ((strcmp(str, "cont") == 0) || (strcmp(str, "continue") == 0)) attrs->cont = true; + else if (strcmp(str, "clear") == 0) + attrs->clear = true; else if (strncmp(str, "size=", strlen("size=")) == 0) { int map_bits = parse_map_size(str); @@ -916,6 +919,21 @@ static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd, return &event_hist_trigger_ops; } +static void hist_clear(struct event_trigger_data *data) +{ + struct hist_trigger_data *hist_data = data->private_data; + bool paused; + + paused = data->paused; + data->paused = true; + + synchronize_sched(); + + tracing_map_clear(hist_data->map); + + data->paused = paused; +} + static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, struct event_trigger_data *data, struct trace_event_file *file) @@ -930,13 +948,15 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, test->paused = true; else if (hist_data->attrs->cont) test->paused = false; + else if (hist_data->attrs->clear) + hist_clear(test); else ret = -EEXIST; goto out; } } - if (hist_data->attrs->cont) { + if (hist_data->attrs->cont || hist_data->attrs->clear) { ret = -ENOENT; goto out; } @@ -1035,7 +1055,7 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, * triggers registered a failure too. */ if (!ret) { - if (!(attrs->pause || attrs->cont)) + if (!(attrs->pause || attrs->cont || attrs->clear)) ret = -ENOENT; goto out_free; } else if (ret < 0) -- GitLab From 0c4a6b4666e8eb86dead3f09b40bb8ca4f614e4f Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:48 -0600 Subject: [PATCH 3429/9938] tracing: Add hist trigger 'hex' modifier for displaying numeric fields Allow users to have numeric fields displayed as hex values in the output by appending '.hex' to field names: # echo hist:keys=aaa,bbb.hex:vals=ccc.hex ... \ [ if filter] > event/trigger Link: http://lkml.kernel.org/r/67bd431edda2af5798d7694818f7e8d71b6b3463.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 5 ++- kernel/trace/trace_events_hist.c | 62 ++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 4097cd3763f7..2eb2eafbe7f5 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3852,7 +3852,10 @@ static const char readme_msg[] = "\t used to specify more or fewer than the default 2048 entries\n" "\t for the hashtable size.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" - "\t table in its entirety to stdout.\n\n" + "\t table in its entirety to stdout. The default format used to\n" + "\t display a given field can be modified by appending any of the\n" + "\t following modifiers to the field name, as applicable:\n\n" + "\t .hex display a number as a hex value\n\n" "\t The 'pause' parameter can be used to pause an existing hist\n" "\t trigger or to start a hist trigger but not log any events\n" "\t until told to do so. 'continue' can be used to start or\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 83cb25e067ad..8e49eeef8867 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -80,6 +80,7 @@ enum hist_field_flags { HIST_FIELD_FL_HITCOUNT = 1, HIST_FIELD_FL_KEY = 2, HIST_FIELD_FL_STRING = 4, + HIST_FIELD_FL_HEX = 8, }; struct hist_trigger_attrs { @@ -303,11 +304,23 @@ static int create_val_field(struct hist_trigger_data *hist_data, { struct ftrace_event_field *field = NULL; unsigned long flags = 0; + char *field_name; int ret = 0; if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX)) return -EINVAL; - field = trace_find_event_field(file->event_call, field_str); + + field_name = strsep(&field_str, "."); + if (field_str) { + if (strcmp(field_str, "hex") == 0) + flags |= HIST_FIELD_FL_HEX; + else { + ret = -EINVAL; + goto out; + } + } + + field = trace_find_event_field(file->event_call, field_name); if (!field) { ret = -EINVAL; goto out; @@ -372,6 +385,7 @@ static int create_key_field(struct hist_trigger_data *hist_data, struct ftrace_event_field *field = NULL; unsigned long flags = 0; unsigned int key_size; + char *field_name; int ret = 0; if (WARN_ON(key_idx >= TRACING_MAP_FIELDS_MAX)) @@ -379,7 +393,17 @@ static int create_key_field(struct hist_trigger_data *hist_data, flags |= HIST_FIELD_FL_KEY; - field = trace_find_event_field(file->event_call, field_str); + field_name = strsep(&field_str, "."); + if (field_str) { + if (strcmp(field_str, "hex") == 0) + flags |= HIST_FIELD_FL_HEX; + else { + ret = -EINVAL; + goto out; + } + } + + field = trace_find_event_field(file->event_call, field_name); if (!field) { ret = -EINVAL; goto out; @@ -713,7 +737,11 @@ hist_trigger_entry_print(struct seq_file *m, if (i > hist_data->n_vals) seq_puts(m, ", "); - if (key_field->flags & HIST_FIELD_FL_STRING) { + if (key_field->flags & HIST_FIELD_FL_HEX) { + uval = *(u64 *)(key + key_field->offset); + seq_printf(m, "%s: %llx", + key_field->field->name, uval); + } else if (key_field->flags & HIST_FIELD_FL_STRING) { seq_printf(m, "%s: %-50s", key_field->field->name, (char *)(key + key_field->offset)); } else { @@ -729,9 +757,15 @@ hist_trigger_entry_print(struct seq_file *m, tracing_map_read_sum(elt, HITCOUNT_IDX)); for (i = 1; i < hist_data->n_vals; i++) { - seq_printf(m, " %s: %10llu", - hist_data->fields[i]->field->name, - tracing_map_read_sum(elt, i)); + if (hist_data->fields[i]->flags & HIST_FIELD_FL_HEX) { + seq_printf(m, " %s: %10llx", + hist_data->fields[i]->field->name, + tracing_map_read_sum(elt, i)); + } else { + seq_printf(m, " %s: %10llu", + hist_data->fields[i]->field->name, + tracing_map_read_sum(elt, i)); + } } seq_puts(m, "\n"); @@ -816,9 +850,25 @@ const struct file_operations event_hist_fops = { .release = single_release, }; +static const char *get_hist_field_flags(struct hist_field *hist_field) +{ + const char *flags_str = NULL; + + if (hist_field->flags & HIST_FIELD_FL_HEX) + flags_str = "hex"; + + return flags_str; +} + static void hist_field_print(struct seq_file *m, struct hist_field *hist_field) { seq_printf(m, "%s", hist_field->field->name); + if (hist_field->flags) { + const char *flags_str = get_hist_field_flags(hist_field); + + if (flags_str) + seq_printf(m, ".%s", flags_str); + } } static int event_hist_trigger_print(struct seq_file *m, -- GitLab From c6afad49d127f6d7c9957319f55173a2198b1ba8 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:49 -0600 Subject: [PATCH 3430/9938] tracing: Add hist trigger 'sym' and 'sym-offset' modifiers Allow users to have address fields displayed as symbols in the output by appending '.sym' or 'sym-offset' to field names: # echo hist:keys=aaa.sym,bbb.sym-offset ... \ [ if filter] > event/trigger Link: http://lkml.kernel.org/r/87d4935821491c0275513f0fbfb9bab8d3d3f079.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 4 +++- kernel/trace/trace_events_hist.c | 29 +++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 2eb2eafbe7f5..34459eb0c844 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3855,7 +3855,9 @@ static const char readme_msg[] = "\t table in its entirety to stdout. The default format used to\n" "\t display a given field can be modified by appending any of the\n" "\t following modifiers to the field name, as applicable:\n\n" - "\t .hex display a number as a hex value\n\n" + "\t .hex display a number as a hex value\n" + "\t .sym display an address as a symbol\n" + "\t .sym-offset display an address as a symbol and offset\n\n" "\t The 'pause' parameter can be used to pause an existing hist\n" "\t trigger or to start a hist trigger but not log any events\n" "\t until told to do so. 'continue' can be used to start or\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 8e49eeef8867..808cc06cdb61 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -77,10 +77,12 @@ DEFINE_HIST_FIELD_FN(u8); #define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + sizeof(u64)) enum hist_field_flags { - HIST_FIELD_FL_HITCOUNT = 1, - HIST_FIELD_FL_KEY = 2, - HIST_FIELD_FL_STRING = 4, - HIST_FIELD_FL_HEX = 8, + HIST_FIELD_FL_HITCOUNT = 1, + HIST_FIELD_FL_KEY = 2, + HIST_FIELD_FL_STRING = 4, + HIST_FIELD_FL_HEX = 8, + HIST_FIELD_FL_SYM = 16, + HIST_FIELD_FL_SYM_OFFSET = 32, }; struct hist_trigger_attrs { @@ -397,6 +399,10 @@ static int create_key_field(struct hist_trigger_data *hist_data, if (field_str) { if (strcmp(field_str, "hex") == 0) flags |= HIST_FIELD_FL_HEX; + else if (strcmp(field_str, "sym") == 0) + flags |= HIST_FIELD_FL_SYM; + else if (strcmp(field_str, "sym-offset") == 0) + flags |= HIST_FIELD_FL_SYM_OFFSET; else { ret = -EINVAL; goto out; @@ -726,6 +732,7 @@ hist_trigger_entry_print(struct seq_file *m, struct tracing_map_elt *elt) { struct hist_field *key_field; + char str[KSYM_SYMBOL_LEN]; unsigned int i; u64 uval; @@ -741,6 +748,16 @@ hist_trigger_entry_print(struct seq_file *m, uval = *(u64 *)(key + key_field->offset); seq_printf(m, "%s: %llx", key_field->field->name, uval); + } else if (key_field->flags & HIST_FIELD_FL_SYM) { + uval = *(u64 *)(key + key_field->offset); + sprint_symbol_no_offset(str, uval); + seq_printf(m, "%s: [%llx] %-45s", + key_field->field->name, uval, str); + } else if (key_field->flags & HIST_FIELD_FL_SYM_OFFSET) { + uval = *(u64 *)(key + key_field->offset); + sprint_symbol(str, uval); + seq_printf(m, "%s: [%llx] %-55s", + key_field->field->name, uval, str); } else if (key_field->flags & HIST_FIELD_FL_STRING) { seq_printf(m, "%s: %-50s", key_field->field->name, (char *)(key + key_field->offset)); @@ -856,6 +873,10 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) if (hist_field->flags & HIST_FIELD_FL_HEX) flags_str = "hex"; + else if (hist_field->flags & HIST_FIELD_FL_SYM) + flags_str = "sym"; + else if (hist_field->flags & HIST_FIELD_FL_SYM_OFFSET) + flags_str = "sym-offset"; return flags_str; } -- GitLab From 6b4827ad028a1ab2fc4dcf1f5e6e077018d1b770 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:50 -0600 Subject: [PATCH 3431/9938] tracing: Add hist trigger 'execname' modifier Allow users to have common_pid field values displayed as program names in the output by appending '.execname' to a common_pid field name: # echo hist:keys=common_pid.execname ... \ [ if filter] > event/trigger Link: http://lkml.kernel.org/r/e172e81f10f5b8d1f08450e3763c850f39fbf698.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 3 +- kernel/trace/trace_events_hist.c | 100 ++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 34459eb0c844..58a8bee50c6e 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3857,7 +3857,8 @@ static const char readme_msg[] = "\t following modifiers to the field name, as applicable:\n\n" "\t .hex display a number as a hex value\n" "\t .sym display an address as a symbol\n" - "\t .sym-offset display an address as a symbol and offset\n\n" + "\t .sym-offset display an address as a symbol and offset\n" + "\t .execname display a common_pid as a program name\n\n" "\t The 'pause' parameter can be used to pause an existing hist\n" "\t trigger or to start a hist trigger but not log any events\n" "\t until told to do so. 'continue' can be used to start or\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 808cc06cdb61..227e6c21b1eb 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -83,6 +83,7 @@ enum hist_field_flags { HIST_FIELD_FL_HEX = 8, HIST_FIELD_FL_SYM = 16, HIST_FIELD_FL_SYM_OFFSET = 32, + HIST_FIELD_FL_EXECNAME = 64, }; struct hist_trigger_attrs { @@ -232,6 +233,73 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) return ERR_PTR(ret); } +static inline void save_comm(char *comm, struct task_struct *task) +{ + if (!task->pid) { + strcpy(comm, ""); + return; + } + + if (WARN_ON_ONCE(task->pid < 0)) { + strcpy(comm, ""); + return; + } + + memcpy(comm, task->comm, TASK_COMM_LEN); +} + +static void hist_trigger_elt_comm_free(struct tracing_map_elt *elt) +{ + kfree((char *)elt->private_data); +} + +static int hist_trigger_elt_comm_alloc(struct tracing_map_elt *elt) +{ + struct hist_trigger_data *hist_data = elt->map->private_data; + struct hist_field *key_field; + unsigned int i; + + for_each_hist_key_field(i, hist_data) { + key_field = hist_data->fields[i]; + + if (key_field->flags & HIST_FIELD_FL_EXECNAME) { + unsigned int size = TASK_COMM_LEN + 1; + + elt->private_data = kzalloc(size, GFP_KERNEL); + if (!elt->private_data) + return -ENOMEM; + break; + } + } + + return 0; +} + +static void hist_trigger_elt_comm_copy(struct tracing_map_elt *to, + struct tracing_map_elt *from) +{ + char *comm_from = from->private_data; + char *comm_to = to->private_data; + + if (comm_from) + memcpy(comm_to, comm_from, TASK_COMM_LEN + 1); +} + +static void hist_trigger_elt_comm_init(struct tracing_map_elt *elt) +{ + char *comm = elt->private_data; + + if (comm) + save_comm(comm, current); +} + +static const struct tracing_map_ops hist_trigger_elt_comm_ops = { + .elt_alloc = hist_trigger_elt_comm_alloc, + .elt_copy = hist_trigger_elt_comm_copy, + .elt_free = hist_trigger_elt_comm_free, + .elt_init = hist_trigger_elt_comm_init, +}; + static void destroy_hist_field(struct hist_field *hist_field) { kfree(hist_field); @@ -403,6 +471,9 @@ static int create_key_field(struct hist_trigger_data *hist_data, flags |= HIST_FIELD_FL_SYM; else if (strcmp(field_str, "sym-offset") == 0) flags |= HIST_FIELD_FL_SYM_OFFSET; + else if ((strcmp(field_str, "execname") == 0) && + (strcmp(field_name, "common_pid") == 0)) + flags |= HIST_FIELD_FL_EXECNAME; else { ret = -EINVAL; goto out; @@ -624,11 +695,27 @@ static int create_tracing_map_fields(struct hist_trigger_data *hist_data) return 0; } +static bool need_tracing_map_ops(struct hist_trigger_data *hist_data) +{ + struct hist_field *key_field; + unsigned int i; + + for_each_hist_key_field(i, hist_data) { + key_field = hist_data->fields[i]; + + if (key_field->flags & HIST_FIELD_FL_EXECNAME) + return true; + } + + return false; +} + static struct hist_trigger_data * create_hist_data(unsigned int map_bits, struct hist_trigger_attrs *attrs, struct trace_event_file *file) { + const struct tracing_map_ops *map_ops = NULL; struct hist_trigger_data *hist_data; int ret = 0; @@ -646,8 +733,11 @@ create_hist_data(unsigned int map_bits, if (ret) goto free; + if (need_tracing_map_ops(hist_data)) + map_ops = &hist_trigger_elt_comm_ops; + hist_data->map = tracing_map_create(map_bits, hist_data->key_size, - NULL, hist_data); + map_ops, hist_data); if (IS_ERR(hist_data->map)) { ret = PTR_ERR(hist_data->map); hist_data->map = NULL; @@ -758,6 +848,12 @@ hist_trigger_entry_print(struct seq_file *m, sprint_symbol(str, uval); seq_printf(m, "%s: [%llx] %-55s", key_field->field->name, uval, str); + } else if (key_field->flags & HIST_FIELD_FL_EXECNAME) { + char *comm = elt->private_data; + + uval = *(u64 *)(key + key_field->offset); + seq_printf(m, "%s: %-16s[%10llu]", + key_field->field->name, comm, uval); } else if (key_field->flags & HIST_FIELD_FL_STRING) { seq_printf(m, "%s: %-50s", key_field->field->name, (char *)(key + key_field->offset)); @@ -877,6 +973,8 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) flags_str = "sym"; else if (hist_field->flags & HIST_FIELD_FL_SYM_OFFSET) flags_str = "sym-offset"; + else if (hist_field->flags & HIST_FIELD_FL_EXECNAME) + flags_str = "execname"; return flags_str; } -- GitLab From 316961988b5ec71bbf4b2ad447662770349aec13 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:51 -0600 Subject: [PATCH 3432/9938] tracing: Add hist trigger 'syscall' modifier Allow users to have syscall id fields displayed as syscall names in the output by appending '.syscall' to field names: # echo hist:keys=aaa.syscall ... \ [ if filter] > event/trigger Link: http://lkml.kernel.org/r/2bab1e59933d76a14b545bd2e02f80b8b08ac4d3.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 3 ++- kernel/trace/trace_events_hist.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 58a8bee50c6e..0dd23c5b1c34 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3858,7 +3858,8 @@ static const char readme_msg[] = "\t .hex display a number as a hex value\n" "\t .sym display an address as a symbol\n" "\t .sym-offset display an address as a symbol and offset\n" - "\t .execname display a common_pid as a program name\n\n" + "\t .execname display a common_pid as a program name\n" + "\t .syscall display a syscall id as a syscall name\n\n" "\t The 'pause' parameter can be used to pause an existing hist\n" "\t trigger or to start a hist trigger but not log any events\n" "\t until told to do so. 'continue' can be used to start or\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 227e6c21b1eb..f9e7ecb33847 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -84,6 +84,7 @@ enum hist_field_flags { HIST_FIELD_FL_SYM = 16, HIST_FIELD_FL_SYM_OFFSET = 32, HIST_FIELD_FL_EXECNAME = 64, + HIST_FIELD_FL_SYSCALL = 128, }; struct hist_trigger_attrs { @@ -474,6 +475,8 @@ static int create_key_field(struct hist_trigger_data *hist_data, else if ((strcmp(field_str, "execname") == 0) && (strcmp(field_name, "common_pid") == 0)) flags |= HIST_FIELD_FL_EXECNAME; + else if (strcmp(field_str, "syscall") == 0) + flags |= HIST_FIELD_FL_SYSCALL; else { ret = -EINVAL; goto out; @@ -854,6 +857,16 @@ hist_trigger_entry_print(struct seq_file *m, uval = *(u64 *)(key + key_field->offset); seq_printf(m, "%s: %-16s[%10llu]", key_field->field->name, comm, uval); + } else if (key_field->flags & HIST_FIELD_FL_SYSCALL) { + const char *syscall_name; + + uval = *(u64 *)(key + key_field->offset); + syscall_name = get_syscall_name(uval); + if (!syscall_name) + syscall_name = "unknown_syscall"; + + seq_printf(m, "%s: %-30s[%3llu]", + key_field->field->name, syscall_name, uval); } else if (key_field->flags & HIST_FIELD_FL_STRING) { seq_printf(m, "%s: %-50s", key_field->field->name, (char *)(key + key_field->offset)); @@ -975,6 +988,8 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) flags_str = "sym-offset"; else if (hist_field->flags & HIST_FIELD_FL_EXECNAME) flags_str = "execname"; + else if (hist_field->flags & HIST_FIELD_FL_SYSCALL) + flags_str = "syscall"; return flags_str; } -- GitLab From 69a0200c2e25d61c50091549d00cfeb426c258f5 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:52 -0600 Subject: [PATCH 3433/9938] tracing: Add hist trigger support for stacktraces as keys It's often useful to be able to use a stacktrace as a hash key, for keeping a count of the number of times a particular call path resulted in a trace event, for instance. Add a special key named 'stacktrace' which can be used as key in a 'keys=' param for this purpose: # echo hist:keys=stacktrace ... \ [ if filter] > event/trigger Link: http://lkml.kernel.org/r/87515e90b3785232a874a12156174635a348edb1.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 16 ++-- kernel/trace/trace_events_hist.c | 135 +++++++++++++++++++++++-------- 2 files changed, 109 insertions(+), 42 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 0dd23c5b1c34..2238bfde799b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3843,14 +3843,14 @@ static const char readme_msg[] = "\t table using the key(s) and value(s) named, and the value of a\n" "\t sum called 'hitcount' is incremented. Keys and values\n" "\t correspond to fields in the event's format description. Keys\n" - "\t can be any field. Compound keys consisting of up to two\n" - "\t fields can be specified by the 'keys' keyword. Values must\n" - "\t correspond to numeric fields. Sort keys consisting of up to\n" - "\t two fields can be specified using the 'sort' keyword. The\n" - "\t sort direction can be modified by appending '.descending' or\n" - "\t '.ascending' to a sort field. The 'size' parameter can be\n" - "\t used to specify more or fewer than the default 2048 entries\n" - "\t for the hashtable size.\n\n" + "\t can be any field, or the special string 'stacktrace'.\n" + "\t Compound keys consisting of up to two fields can be specified\n" + "\t by the 'keys' keyword. Values must correspond to numeric\n" + "\t fields. Sort keys consisting of up to two fields can be\n" + "\t specified using the 'sort' keyword. The sort direction can\n" + "\t be modified by appending '.descending' or '.ascending' to a\n" + "\t sort field. The 'size' parameter can be used to specify more\n" + "\t or fewer than the default 2048 entries for the hashtable size.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" "\t table in its entirety to stdout. The default format used to\n" "\t display a given field can be modified by appending any of the\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index f9e7ecb33847..21cae42b54da 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -35,6 +35,11 @@ struct hist_field { unsigned int offset; }; +static u64 hist_field_none(struct hist_field *field, void *event) +{ + return 0; +} + static u64 hist_field_counter(struct hist_field *field, void *event) { return 1; @@ -73,8 +78,12 @@ DEFINE_HIST_FIELD_FN(u8); #define for_each_hist_key_field(i, hist_data) \ for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++) +#define HIST_STACKTRACE_DEPTH 16 +#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) +#define HIST_STACKTRACE_SKIP 5 + #define HITCOUNT_IDX 0 -#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + sizeof(u64)) +#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE) enum hist_field_flags { HIST_FIELD_FL_HITCOUNT = 1, @@ -85,6 +94,7 @@ enum hist_field_flags { HIST_FIELD_FL_SYM_OFFSET = 32, HIST_FIELD_FL_EXECNAME = 64, HIST_FIELD_FL_SYSCALL = 128, + HIST_FIELD_FL_STACKTRACE = 256, }; struct hist_trigger_attrs { @@ -323,6 +333,11 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field, goto out; } + if (flags & HIST_FIELD_FL_STACKTRACE) { + hist_field->fn = hist_field_none; + goto out; + } + if (is_string_field(field)) { flags |= HIST_FIELD_FL_STRING; hist_field->fn = hist_field_string; @@ -456,7 +471,6 @@ static int create_key_field(struct hist_trigger_data *hist_data, struct ftrace_event_field *field = NULL; unsigned long flags = 0; unsigned int key_size; - char *field_name; int ret = 0; if (WARN_ON(key_idx >= TRACING_MAP_FIELDS_MAX)) @@ -464,33 +478,39 @@ static int create_key_field(struct hist_trigger_data *hist_data, flags |= HIST_FIELD_FL_KEY; - field_name = strsep(&field_str, "."); - if (field_str) { - if (strcmp(field_str, "hex") == 0) - flags |= HIST_FIELD_FL_HEX; - else if (strcmp(field_str, "sym") == 0) - flags |= HIST_FIELD_FL_SYM; - else if (strcmp(field_str, "sym-offset") == 0) - flags |= HIST_FIELD_FL_SYM_OFFSET; - else if ((strcmp(field_str, "execname") == 0) && - (strcmp(field_name, "common_pid") == 0)) - flags |= HIST_FIELD_FL_EXECNAME; - else if (strcmp(field_str, "syscall") == 0) - flags |= HIST_FIELD_FL_SYSCALL; - else { + if (strcmp(field_str, "stacktrace") == 0) { + flags |= HIST_FIELD_FL_STACKTRACE; + key_size = sizeof(unsigned long) * HIST_STACKTRACE_DEPTH; + } else { + char *field_name = strsep(&field_str, "."); + + if (field_str) { + if (strcmp(field_str, "hex") == 0) + flags |= HIST_FIELD_FL_HEX; + else if (strcmp(field_str, "sym") == 0) + flags |= HIST_FIELD_FL_SYM; + else if (strcmp(field_str, "sym-offset") == 0) + flags |= HIST_FIELD_FL_SYM_OFFSET; + else if ((strcmp(field_str, "execname") == 0) && + (strcmp(field_name, "common_pid") == 0)) + flags |= HIST_FIELD_FL_EXECNAME; + else if (strcmp(field_str, "syscall") == 0) + flags |= HIST_FIELD_FL_SYSCALL; + else { + ret = -EINVAL; + goto out; + } + } + + field = trace_find_event_field(file->event_call, field_name); + if (!field) { ret = -EINVAL; goto out; } - } - field = trace_find_event_field(file->event_call, field_name); - if (!field) { - ret = -EINVAL; - goto out; + key_size = field->size; } - key_size = field->size; - hist_data->fields[key_idx] = create_hist_field(field, flags); if (!hist_data->fields[key_idx]) { ret = -ENOMEM; @@ -679,7 +699,9 @@ static int create_tracing_map_fields(struct hist_trigger_data *hist_data) field = hist_field->field; - if (is_string_field(field)) + if (hist_field->flags & HIST_FIELD_FL_STACKTRACE) + cmp_fn = tracing_map_cmp_none; + else if (is_string_field(field)) cmp_fn = tracing_map_cmp_string; else cmp_fn = tracing_map_cmp_num(field->size, @@ -786,7 +808,9 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, static void event_hist_trigger(struct event_trigger_data *data, void *rec) { struct hist_trigger_data *hist_data = data->private_data; + unsigned long entries[HIST_STACKTRACE_DEPTH]; char compound_key[HIST_KEY_SIZE_MAX]; + struct stack_trace stacktrace; struct hist_field *key_field; struct tracing_map_elt *elt; u64 field_contents; @@ -799,15 +823,27 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) for_each_hist_key_field(i, hist_data) { key_field = hist_data->fields[i]; - field_contents = key_field->fn(key_field, rec); - if (key_field->flags & HIST_FIELD_FL_STRING) - key = (void *)(unsigned long)field_contents; - else - key = (void *)&field_contents; + if (key_field->flags & HIST_FIELD_FL_STACKTRACE) { + stacktrace.max_entries = HIST_STACKTRACE_DEPTH; + stacktrace.entries = entries; + stacktrace.nr_entries = 0; + stacktrace.skip = HIST_STACKTRACE_SKIP; - if (hist_data->n_keys > 1) { - memcpy(compound_key + key_field->offset, key, - key_field->size); + memset(stacktrace.entries, 0, HIST_STACKTRACE_SIZE); + save_stack_trace(&stacktrace); + + key = entries; + } else { + field_contents = key_field->fn(key_field, rec); + if (key_field->flags & HIST_FIELD_FL_STRING) + key = (void *)(unsigned long)field_contents; + else + key = (void *)&field_contents; + + if (hist_data->n_keys > 1) { + memcpy(compound_key + key_field->offset, key, + key_field->size); + } } } @@ -819,6 +855,24 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) hist_trigger_elt_update(hist_data, elt, rec); } +static void hist_trigger_stacktrace_print(struct seq_file *m, + unsigned long *stacktrace_entries, + unsigned int max_entries) +{ + char str[KSYM_SYMBOL_LEN]; + unsigned int spaces = 8; + unsigned int i; + + for (i = 0; i < max_entries; i++) { + if (stacktrace_entries[i] == ULONG_MAX) + return; + + seq_printf(m, "%*c", 1 + spaces, ' '); + sprint_symbol(str, stacktrace_entries[i]); + seq_printf(m, "%s\n", str); + } +} + static void hist_trigger_entry_print(struct seq_file *m, struct hist_trigger_data *hist_data, void *key, @@ -826,6 +880,7 @@ hist_trigger_entry_print(struct seq_file *m, { struct hist_field *key_field; char str[KSYM_SYMBOL_LEN]; + bool multiline = false; unsigned int i; u64 uval; @@ -867,6 +922,12 @@ hist_trigger_entry_print(struct seq_file *m, seq_printf(m, "%s: %-30s[%3llu]", key_field->field->name, syscall_name, uval); + } else if (key_field->flags & HIST_FIELD_FL_STACKTRACE) { + seq_puts(m, "stacktrace:\n"); + hist_trigger_stacktrace_print(m, + key + key_field->offset, + HIST_STACKTRACE_DEPTH); + multiline = true; } else if (key_field->flags & HIST_FIELD_FL_STRING) { seq_printf(m, "%s: %-50s", key_field->field->name, (char *)(key + key_field->offset)); @@ -877,7 +938,10 @@ hist_trigger_entry_print(struct seq_file *m, } } - seq_puts(m, " }"); + if (!multiline) + seq_puts(m, " "); + + seq_puts(m, "}"); seq_printf(m, " hitcount: %10llu", tracing_map_read_sum(elt, HITCOUNT_IDX)); @@ -1021,7 +1085,10 @@ static int event_hist_trigger_print(struct seq_file *m, if (i > hist_data->n_vals) seq_puts(m, ","); - hist_field_print(m, key_field); + if (key_field->flags & HIST_FIELD_FL_STACKTRACE) + seq_puts(m, "stacktrace"); + else + hist_field_print(m, key_field); } seq_puts(m, ":vals="); -- GitLab From 63a450aa4d08ccf4f53e9fa59144e746e2288319 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Tue, 19 Apr 2016 15:19:02 +0100 Subject: [PATCH 3434/9938] ASoC: da7219: Update PLL ranges and dividers to improve locking The expected MCLK frequency ranges and the associated dividers are updated to improve PLL locking in a corner scenario, with low MCLK frequency near an input divider change boundary. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- sound/soc/codecs/da7219.c | 28 ++++++++++++++-------------- sound/soc/codecs/da7219.h | 20 ++++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 81c0708b85c1..3b1d65badbda 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1079,21 +1079,21 @@ static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, dev_err(codec->dev, "PLL input clock %d below valid range\n", da7219->mclk_rate); return -EINVAL; - } else if (da7219->mclk_rate <= 5000000) { - indiv_bits = DA7219_PLL_INDIV_2_5_MHZ; - indiv = DA7219_PLL_INDIV_2_5_MHZ_VAL; - } else if (da7219->mclk_rate <= 10000000) { - indiv_bits = DA7219_PLL_INDIV_5_10_MHZ; - indiv = DA7219_PLL_INDIV_5_10_MHZ_VAL; - } else if (da7219->mclk_rate <= 20000000) { - indiv_bits = DA7219_PLL_INDIV_10_20_MHZ; - indiv = DA7219_PLL_INDIV_10_20_MHZ_VAL; - } else if (da7219->mclk_rate <= 40000000) { - indiv_bits = DA7219_PLL_INDIV_20_40_MHZ; - indiv = DA7219_PLL_INDIV_20_40_MHZ_VAL; + } else if (da7219->mclk_rate <= 4500000) { + indiv_bits = DA7219_PLL_INDIV_2_TO_4_5_MHZ; + indiv = DA7219_PLL_INDIV_2_TO_4_5_MHZ_VAL; + } else if (da7219->mclk_rate <= 9000000) { + indiv_bits = DA7219_PLL_INDIV_4_5_TO_9_MHZ; + indiv = DA7219_PLL_INDIV_4_5_TO_9_MHZ_VAL; + } else if (da7219->mclk_rate <= 18000000) { + indiv_bits = DA7219_PLL_INDIV_9_TO_18_MHZ; + indiv = DA7219_PLL_INDIV_9_TO_18_MHZ_VAL; + } else if (da7219->mclk_rate <= 36000000) { + indiv_bits = DA7219_PLL_INDIV_18_TO_36_MHZ; + indiv = DA7219_PLL_INDIV_18_TO_36_MHZ_VAL; } else if (da7219->mclk_rate <= 54000000) { - indiv_bits = DA7219_PLL_INDIV_40_54_MHZ; - indiv = DA7219_PLL_INDIV_40_54_MHZ_VAL; + indiv_bits = DA7219_PLL_INDIV_36_TO_54_MHZ; + indiv = DA7219_PLL_INDIV_36_TO_54_MHZ_VAL; } else { dev_err(codec->dev, "PLL input clock %d above valid range\n", da7219->mclk_rate); diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 5a787e738084..ff2a2f02ce40 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -194,11 +194,11 @@ /* DA7219_PLL_CTRL = 0x20 */ #define DA7219_PLL_INDIV_SHIFT 2 #define DA7219_PLL_INDIV_MASK (0x7 << 2) -#define DA7219_PLL_INDIV_2_5_MHZ (0x0 << 2) -#define DA7219_PLL_INDIV_5_10_MHZ (0x1 << 2) -#define DA7219_PLL_INDIV_10_20_MHZ (0x2 << 2) -#define DA7219_PLL_INDIV_20_40_MHZ (0x3 << 2) -#define DA7219_PLL_INDIV_40_54_MHZ (0x4 << 2) +#define DA7219_PLL_INDIV_2_TO_4_5_MHZ (0x0 << 2) +#define DA7219_PLL_INDIV_4_5_TO_9_MHZ (0x1 << 2) +#define DA7219_PLL_INDIV_9_TO_18_MHZ (0x2 << 2) +#define DA7219_PLL_INDIV_18_TO_36_MHZ (0x3 << 2) +#define DA7219_PLL_INDIV_36_TO_54_MHZ (0x4 << 2) #define DA7219_PLL_MCLK_SQR_EN_SHIFT 5 #define DA7219_PLL_MCLK_SQR_EN_MASK (0x1 << 5) #define DA7219_PLL_MODE_SHIFT 6 @@ -761,11 +761,11 @@ #define DA7219_PLL_FREQ_OUT_98304 98304000 /* PLL Frequency Dividers */ -#define DA7219_PLL_INDIV_2_5_MHZ_VAL 1 -#define DA7219_PLL_INDIV_5_10_MHZ_VAL 2 -#define DA7219_PLL_INDIV_10_20_MHZ_VAL 4 -#define DA7219_PLL_INDIV_20_40_MHZ_VAL 8 -#define DA7219_PLL_INDIV_40_54_MHZ_VAL 16 +#define DA7219_PLL_INDIV_2_TO_4_5_MHZ_VAL 1 +#define DA7219_PLL_INDIV_4_5_TO_9_MHZ_VAL 2 +#define DA7219_PLL_INDIV_9_TO_18_MHZ_VAL 4 +#define DA7219_PLL_INDIV_18_TO_36_MHZ_VAL 8 +#define DA7219_PLL_INDIV_36_TO_54_MHZ_VAL 16 /* SRM */ #define DA7219_SRM_CHECK_RETRIES 8 -- GitLab From fb137ba64a6415ddf231495f6d1a82de1cd69ed0 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Tue, 19 Apr 2016 15:19:03 +0100 Subject: [PATCH 3435/9938] ASoC: da7219: Disallow unsupported 32KHz clock setting in set_dai_sysclk() The PLL function was updated to disallow 32KHz in commit 501f72e9c520 ("ASoC: da7219: Remove support for 32KHz PLL mode"), but set_dai_sysclk() was missed and still permits it. This patch resolves that discrepancy. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- sound/soc/codecs/da7219.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 3b1d65badbda..caea2ee19d9a 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1025,7 +1025,7 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) return 0; - if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) { + if ((freq < 2000000) || (freq > 54000000)) { dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; -- GitLab From f5cc17720b61af382a053d49a4a14c3d14857a5b Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 19 Apr 2016 18:00:20 +0200 Subject: [PATCH 3436/9938] ASoC: tlv320aix31xx: Add ACPI match for Lenovo 100S The Lenovo 100S netbook has a codec controller for which there is a driver, but doesn't know how to access the device. This adds the necessary ACPI table for the driver to find the device. Device (TTLV) { Name (_ADR, Zero) // _ADR: Address Name (_HID, "10TI3100") // _HID: Hardware ID Name (_CID, "10TI3100") // _CID: Compatible ID Name (_DDN, "TI TLV320AIC3100 Codec Controller ") // _DDN: DOS Device Name Name (_UID, One) // _UID: Unique ID Signed-off-by: Bastien Nocera Tested-by: Jan Schmidt Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index ee4def4f819f..3c5e1df01c19 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1280,10 +1281,19 @@ static const struct i2c_device_id aic31xx_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); +#ifdef CONFIG_ACPI +static const struct acpi_device_id aic31xx_acpi_match[] = { + { "10TI3100", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match); +#endif + static struct i2c_driver aic31xx_i2c_driver = { .driver = { .name = "tlv320aic31xx-codec", .of_match_table = of_match_ptr(tlv320aic31xx_of_match), + .acpi_match_table = ACPI_PTR(aic31xx_acpi_match), }, .probe = aic31xx_i2c_probe, .remove = aic31xx_i2c_remove, -- GitLab From 041f9d336f28d3a45b31799bb8b5b2e1fa322321 Mon Sep 17 00:00:00 2001 From: Jeremy McDermond Date: Tue, 19 Apr 2016 09:59:04 -0700 Subject: [PATCH 3437/9938] ASoC: tlv320aic32x4: Add 96k sample rate The TLV320AIC32x4 series supports 96ksps rates in hardware. This patch adds the necessary PLL divider values and clock settings to the table to make 96ksps work. Signed-off-by: Jeremy McDermond Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index c6b6d551f4fe..2f8480c93b3c 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -159,7 +159,10 @@ static const struct aic32x4_rate_divs aic32x4_divs[] = { /* 48k rate */ {AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4}, {AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4}, - {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4} + {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4}, + + /* 96k rate */ + {AIC32X4_FREQ_25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1}, }; static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { @@ -564,7 +567,7 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, return 0; } -#define AIC32X4_RATES SNDRV_PCM_RATE_8000_48000 +#define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000 #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) -- GitLab From a163f2cb393d9d71cad57bfe6a8c7f452a478fb4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Apr 2016 21:14:29 +0200 Subject: [PATCH 3438/9938] netfilter: conntrack: don't acquire lock during seq_printf read access doesn't need any lock here. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_proto_sctp.c | 8 +------- net/netfilter/nf_conntrack_proto_tcp.c | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 9578a7c371ef..1d7ab960a9e6 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -191,13 +191,7 @@ static void sctp_print_tuple(struct seq_file *s, /* Print out the private part of the conntrack. */ static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct) { - enum sctp_conntrack state; - - spin_lock_bh(&ct->lock); - state = ct->proto.sctp.state; - spin_unlock_bh(&ct->lock); - - seq_printf(s, "%s ", sctp_conntrack_names[state]); + seq_printf(s, "%s ", sctp_conntrack_names[ct->proto.sctp.state]); } #define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) \ diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 278f3b9356ef..e0cb0ce38746 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -313,13 +313,7 @@ static void tcp_print_tuple(struct seq_file *s, /* Print out the private part of the conntrack. */ static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct) { - enum tcp_conntrack state; - - spin_lock_bh(&ct->lock); - state = ct->proto.tcp.state; - spin_unlock_bh(&ct->lock); - - seq_printf(s, "%s ", tcp_conntrack_names[state]); + seq_printf(s, "%s ", tcp_conntrack_names[ct->proto.tcp.state]); } static unsigned int get_conntrack_index(const struct tcphdr *tcph) -- GitLab From 18402843bf88c2e9674e1a3a05c73b7d9b09ee05 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 19 Apr 2016 14:30:10 -0400 Subject: [PATCH 3439/9938] net: Align IFLA_STATS64 attributes properly on architectures that need it. Since the nlattr header is 4 bytes in size, it can cause the netlink attribute payload to not be 8-byte aligned. This is particularly troublesome for IFLA_STATS64 which contains 64-bit statistic values. Solve this by creating a dummy IFLA_PAD attribute which has a payload which is zero bytes in size. When HAVE_EFFICIENT_UNALIGNED_ACCESS is false, we insert an IFLA_PAD attribute into the netlink response when necessary such that the IFLA_STATS64 payload will be properly aligned. With help and suggestions from Eric Dumazet. Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 1 + net/core/rtnetlink.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index bb3a90b57199..5ffdcb34e35b 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -155,6 +155,7 @@ enum { IFLA_PROTO_DOWN, IFLA_GSO_MAX_SEGS, IFLA_GSO_MAX_SIZE, + IFLA_PAD, __IFLA_MAX }; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a7a3d345134a..198ca2c99510 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -878,6 +878,9 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ + nla_total_size(sizeof(struct rtnl_link_ifmap)) + nla_total_size(sizeof(struct rtnl_link_stats)) +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS + + nla_total_size(0) /* IFLA_PAD */ +#endif + nla_total_size(sizeof(struct rtnl_link_stats64)) + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ @@ -1052,6 +1055,22 @@ static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb, struct rtnl_link_stats64 *sp; struct nlattr *attr; +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS + /* IF necessary, add a zero length NOP attribute so that the + * nla_data() of the IFLA_STATS64 will be 64-bit aligned. + * + * The nlattr header is 4 bytes in size, that's why we test + * if the skb->data _is_ aligned. This NOP attribute, plus + * nlattr header for IFLA_STATS64, will make nla_data() 8-byte + * aligned. + */ + if (IS_ALIGNED((unsigned long)skb->data, 8)) { + attr = nla_reserve(skb, IFLA_PAD, 0); + if (!attr) + return -EMSGSIZE; + } +#endif + attr = nla_reserve(skb, IFLA_STATS64, sizeof(struct rtnl_link_stats64)); if (!attr) -- GitLab From 6e8ac724bf45d116195d57fbe3a949f570c35635 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 19 Apr 2016 06:05:09 +0100 Subject: [PATCH 3440/9938] ARM: 8562/1: suppress "include/generated/mach-types.h is up to date." For incremental build, "include/generated/mach-types.h is up to date" is every time displayed like follows: $ make ARCH=arm CHK include/config/kernel.release CHK include/generated/uapi/linux/version.h CHK include/generated/utsrelease.h make[1]: `include/generated/mach-types.h' is up to date. CHK include/generated/bounds.h CHK include/generated/timeconst.h CHK include/generated/asm-offsets.h This commit avoids such a clumsy log and introduces Kbuild standard log style: GEN include/generated/mach-types.h Signed-off-by: Masahiro Yamada Signed-off-by: Russell King --- arch/arm/tools/Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile index 32d05c8219dc..6e4cd1867a9f 100644 --- a/arch/arm/tools/Makefile +++ b/arch/arm/tools/Makefile @@ -4,7 +4,10 @@ # Copyright (C) 2001 Russell King # -include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types - @$(kecho) ' Generating $@' - @mkdir -p $(dir $@) - $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; } +quiet_cmd_gen_mach = GEN $@ + cmd_gen_mach = mkdir -p $(dir $@) && \ + $(AWK) -f $(filter-out $(PHONY),$^) > $@ || \ + { rm -f $@; /bin/false; } + +include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types FORCE + $(call if_changed,gen_mach) -- GitLab From bc5ce155d9d769f86a63a1301fb295ea3fcf22b2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2016 03:08:26 +0100 Subject: [PATCH 3441/9938] ARM: 8557/1: specify install, zinstall, and uinstall as PHONY targets Obviously, these are PHONY targets. Signed-off-by: Masahiro Yamada Signed-off-by: Russell King --- arch/arm/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 48fab15cfc02..446705a4325a 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -88,7 +88,7 @@ $(obj)/bootpImage: $(obj)/bootp/bootp FORCE $(call if_changed,objcopy) @$(kecho) ' Kernel: $@ is ready' -PHONY += initrd +PHONY += initrd install zinstall uinstall initrd: @test "$(INITRD_PHYS)" != "" || \ (echo This machine does not support INITRD; exit -1) -- GitLab From 9cf6fcc15aa90bf742fc3d9325992867c130e6ce Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Thu, 14 Apr 2016 15:48:26 +0000 Subject: [PATCH 3442/9938] iio: mxs-lradc: move TS config into suitable function This patch moves the touchscreen type configuration into a more suitable function. Btw this simplifies PM ops later. Signed-off-by: Stefan Wahren Reviewed-by: Marek Vasut Tested-by: Marek Vasut Acked-by: Dmitry Torokhov Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mxs-lradc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c index e4c4c5c8af83..f8a6c8e19503 100644 --- a/drivers/iio/adc/mxs-lradc.c +++ b/drivers/iio/adc/mxs-lradc.c @@ -686,6 +686,17 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) { + /* Configure the touchscreen type */ + if (lradc->soc == IMX28_LRADC) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); + + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) + mxs_lradc_reg_set(lradc, + LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); + } + mxs_lradc_setup_touch_detection(lradc); lradc->cur_plate = LRADC_TOUCH; @@ -1496,17 +1507,6 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); - /* Configure the touchscreen type */ - if (lradc->soc == IMX28_LRADC) { - mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, - LRADC_CTRL0); - - if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) - mxs_lradc_reg_set(lradc, - LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, - LRADC_CTRL0); - } - /* Start internal temperature sensing. */ mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); -- GitLab From 850c25c857647e4095c4290e32eb62395f9c8117 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Thu, 14 Apr 2016 15:48:27 +0000 Subject: [PATCH 3443/9938] iio: mxs-lradc: move STMP reset out of ADC init This patch moves the STMP reset out of ADC init function so as to remove the possiblity of an error return which will be necessary for PM ops support patches to follow. Signed-off-by: Stefan Wahren Tested-by: Marek Vasut Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mxs-lradc.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c index f8a6c8e19503..ad26da1edbee 100644 --- a/drivers/iio/adc/mxs-lradc.c +++ b/drivers/iio/adc/mxs-lradc.c @@ -1487,18 +1487,13 @@ static const struct iio_chan_spec mx28_lradc_chan_spec[] = { MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"), }; -static int mxs_lradc_hw_init(struct mxs_lradc *lradc) +static void mxs_lradc_hw_init(struct mxs_lradc *lradc) { /* The ADC always uses DELAY CHANNEL 0. */ const u32 adc_cfg = (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) | (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); - int ret = stmp_reset_block(lradc->base); - - if (ret) - return ret; - /* Configure DELAY CHANNEL 0 for generic ADC sampling. */ mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0)); @@ -1509,8 +1504,6 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) /* Start internal temperature sensing. */ mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); - - return 0; } static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) @@ -1710,11 +1703,13 @@ static int mxs_lradc_probe(struct platform_device *pdev) } } - /* Configure the hardware. */ - ret = mxs_lradc_hw_init(lradc); + ret = stmp_reset_block(lradc->base); if (ret) goto err_dev; + /* Configure the hardware. */ + mxs_lradc_hw_init(lradc); + /* Register the touchscreen input device. */ if (touch_ret == 0) { ret = mxs_lradc_ts_register(lradc); -- GitLab From 6436db37b4a5da1ae1f381e4791e17e2236fd276 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Mar 2016 14:18:04 +0100 Subject: [PATCH 3444/9938] iio: st_sensors: read each channel individually The current buffer read code tries to optimize reads from the sensor data registers by issuing a single read operation across all the indata registers. This doesn't work: when the LIS331DL accelerometer sensor is configured to open drain, active low interrupt mode, this will just clear the XDA (X-axis data available) bit in the STATUS_REG register (0x27), while YDA, ZDA and even ZYXDA remain set to 1, and the internal logic of the sensor holds the DRDY (INT1) line asserted (the value of the status register is 0xee). If we instead issue one read operation per enabled channel (X, Y, Z) things start working and we can use open drain and active low interrupts. Note that a backported patch fixing this issue will be heading via the fixes branch but changes in this file already in staging-next will make that patch 'look' rather different. The code in here is the correct one when that clash hits. Cc: Giuseppe Barba Cc: Denis Ciocca Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- .../iio/common/st_sensors/st_sensors_buffer.c | 63 ++++--------------- 1 file changed, 13 insertions(+), 50 deletions(-) diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index 73764961feac..2ce0d2a3f855 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -24,67 +24,30 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { - u8 addr[3]; /* no ST sensor has more than 3 channels */ - int i, n = 0, len; + int i, len; + int total = 0; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned int num_data_channels = sdata->num_data_channels; - unsigned int byte_for_channel = - indio_dev->channels[0].scan_type.storagebits >> 3; for (i = 0; i < num_data_channels; i++) { + unsigned int bytes_to_read; + if (test_bit(i, indio_dev->active_scan_mask)) { - addr[n] = indio_dev->channels[i].address; - n++; - } - } - switch (n) { - case 1: - len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - addr[0], byte_for_channel, buf, sdata->multiread_bit); - break; - case 2: - if ((addr[1] - addr[0]) == byte_for_channel) { + bytes_to_read = indio_dev->channels[i].scan_type.storagebits >> 3; len = sdata->tf->read_multiple_byte(&sdata->tb, - sdata->dev, addr[0], byte_for_channel * n, - buf, sdata->multiread_bit); - } else { - u8 *rx_array; - rx_array = kmalloc(byte_for_channel * num_data_channels, - GFP_KERNEL); - if (!rx_array) - return -ENOMEM; + sdata->dev, indio_dev->channels[i].address, + bytes_to_read, + buf + total, sdata->multiread_bit); - len = sdata->tf->read_multiple_byte(&sdata->tb, - sdata->dev, addr[0], - byte_for_channel * num_data_channels, - rx_array, sdata->multiread_bit); - if (len < 0) { - kfree(rx_array); - return len; - } + if (len < bytes_to_read) + return -EIO; - for (i = 0; i < n * byte_for_channel; i++) { - if (i < n) - buf[i] = rx_array[i]; - else - buf[i] = rx_array[n + i]; - } - kfree(rx_array); - len = byte_for_channel * n; + /* Advance the buffer pointer */ + total += len; } - break; - case 3: - len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - addr[0], byte_for_channel * num_data_channels, - buf, sdata->multiread_bit); - break; - default: - return -EINVAL; } - if (len != byte_for_channel * n) - return -EIO; - return len; + return total; } EXPORT_SYMBOL(st_sensors_get_buffer_element); -- GitLab From 97865fe41322d83dac4373fe0a0de5b1a1b318c5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 24 Mar 2016 14:18:05 +0100 Subject: [PATCH 3445/9938] iio: st_sensors: verify interrupt event to status This makes all ST sensor drivers check that they actually have new data available for the requested channel(s) before claiming an IRQ, by reading the status register (which is conveniently the same for all ST sensors) and check that the channel has new data before proceeding to read it and fill the buffer. This way sensors can share an interrupt line: it can be flaged as shared and then the sensor that did not fire will return NO_IRQ, and the sensor that fired will handle the IRQ and return IRQ_HANDLED. Cc: Giuseppe Barba Cc: Denis Ciocca Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 5 +++++ .../iio/common/st_sensors/st_sensors_buffer.c | 18 ++++++++++++++++++ drivers/iio/gyro/st_gyro_core.c | 3 +++ drivers/iio/magnetometer/st_magn_core.c | 1 + drivers/iio/pressure/st_pressure_core.c | 2 ++ include/linux/iio/common/st_sensors.h | 3 +++ 6 files changed, 32 insertions(+) diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index fee32e3d7a05..9fb6d35fce5b 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -332,6 +332,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR, .mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT, .bootime = 2, @@ -397,6 +398,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR, .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, .bootime = 2, @@ -474,6 +476,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR, .mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, .ig1 = { .en_addr = ST_ACCEL_3_IG1_EN_ADDR, .en_mask = ST_ACCEL_3_IG1_EN_MASK, @@ -532,6 +535,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .drdy_irq = { .addr = ST_ACCEL_4_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT, .bootime = 2, /* guess */ @@ -583,6 +587,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR, .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, .bootime = 2, /* guess */ diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index 2ce0d2a3f855..c55898543a47 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -58,6 +58,24 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct st_sensor_data *sdata = iio_priv(indio_dev); + /* If we have a status register, check if this IRQ came from us */ + if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) { + u8 status; + + len = sdata->tf->read_byte(&sdata->tb, sdata->dev, + sdata->sensor_settings->drdy_irq.addr_stat_drdy, + &status); + if (len < 0) + dev_err(sdata->dev, "could not read channel status\n"); + + /* + * If this was not caused by any channels on this sensor, + * return IRQ_NONE + */ + if (!(status & (u8)indio_dev->active_scan_mask[0])) + return IRQ_NONE; + } + len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data); if (len < 0) goto st_sensors_get_buffer_element_error; diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 110f95b6e52f..be9057e89dc3 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -190,6 +190,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { * drain settings, but only for INT1 and not * for the DRDY line on INT2. */ + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT, .bootime = 2, @@ -258,6 +259,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { * drain settings, but only for INT1 and not * for the DRDY line on INT2. */ + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT, .bootime = 2, @@ -322,6 +324,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { * drain settings, but only for INT1 and not * for the DRDY line on INT2. */ + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_GYRO_3_MULTIREAD_BIT, .bootime = 2, diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 501f858df413..62036d2a9956 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -484,6 +484,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { .mask_int1 = ST_MAGN_3_DRDY_INT_MASK, .addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR, .mask_ihl = ST_MAGN_3_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_MAGN_3_MULTIREAD_BIT, .bootime = 2, diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 172393ad34af..1cd37eaa4a57 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -226,6 +226,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR, .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT, .bootime = 2, @@ -312,6 +313,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR, .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK, + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, .bootime = 2, diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 6670c3d25c58..d8da075bfda0 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -37,6 +37,7 @@ #define ST_SENSORS_DEFAULT_AXIS_ADDR 0x20 #define ST_SENSORS_DEFAULT_AXIS_MASK 0x07 #define ST_SENSORS_DEFAULT_AXIS_N_BIT 3 +#define ST_SENSORS_DEFAULT_STAT_ADDR 0x27 #define ST_SENSORS_MAX_NAME 17 #define ST_SENSORS_MAX_4WAI 7 @@ -121,6 +122,7 @@ struct st_sensor_bdu { * @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. + * @addr_stat_drdy: address to read status of DRDY (data ready) interrupt * 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. @@ -131,6 +133,7 @@ struct st_sensor_data_ready_irq { u8 mask_int2; u8 addr_ihl; u8 mask_ihl; + u8 addr_stat_drdy; struct { u8 en_addr; u8 en_mask; -- GitLab From 0e6f6871a1591f4bb0971809c45bc91a991f1967 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 14 Apr 2016 10:45:21 +0200 Subject: [PATCH 3446/9938] iio: st_sensors: support open drain mode Some types of ST Sensors can be connected to the same IRQ line as other peripherals using open drain. Add a device tree binding and a sensor data property to flip the right bit in the interrupt control register to enable open drain mode on the INT line. If the line is set to be open drain, also tag on IRQF_SHARED to the IRQ flags when requesting the interrupt, as the whole point of using open drain interrupt lines is to share them with more than one peripheral (wire-or). Cc: devicetree@vger.kernel.org Cc: Giuseppe Barba Cc: Denis Ciocca Acked-by: Rob Herring Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/st-sensors.txt | 4 ++++ drivers/iio/accel/st_accel_core.c | 8 ++++++++ .../iio/common/st_sensors/st_sensors_core.c | 20 +++++++++++++++++++ .../common/st_sensors/st_sensors_trigger.c | 13 ++++++++++++ drivers/iio/pressure/st_pressure_core.c | 8 ++++++++ include/linux/iio/common/st_sensors.h | 6 ++++++ .../linux/platform_data/st_sensors_pdata.h | 2 ++ 7 files changed, 61 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt index 71b7bdff21cd..637e283f4a8b 100644 --- a/Documentation/devicetree/bindings/iio/st-sensors.txt +++ b/Documentation/devicetree/bindings/iio/st-sensors.txt @@ -16,6 +16,10 @@ Optional properties: - st,drdy-int-pin: the pin on the package that will be used to signal "data ready" (valid values: 1 or 2). This property is not configurable on all sensors. +- drive-open-drain: the interrupt/data ready line will be configured + as open drain, which is useful if several sensors share the same + interrupt line. (This binding is taken from pinctrl/pinctrl-bindings.txt) + This is a boolean property. Sensors may also have applicable pin control settings, those use the standard bindings from pinctrl/pinctrl-bindings.txt. diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 9fb6d35fce5b..dc73f2d85e6d 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -99,6 +99,8 @@ #define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10 #define ST_ACCEL_2_IHL_IRQ_ADDR 0x22 #define ST_ACCEL_2_IHL_IRQ_MASK 0x80 +#define ST_ACCEL_2_OD_IRQ_ADDR 0x22 +#define ST_ACCEL_2_OD_IRQ_MASK 0x40 #define ST_ACCEL_2_MULTIREAD_BIT true /* CUSTOM VALUES FOR SENSOR 3 */ @@ -180,6 +182,8 @@ #define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20 #define ST_ACCEL_5_IHL_IRQ_ADDR 0x22 #define ST_ACCEL_5_IHL_IRQ_MASK 0x80 +#define ST_ACCEL_5_OD_IRQ_ADDR 0x22 +#define ST_ACCEL_5_OD_IRQ_MASK 0x40 #define ST_ACCEL_5_IG1_EN_ADDR 0x21 #define ST_ACCEL_5_IG1_EN_MASK 0x08 #define ST_ACCEL_5_MULTIREAD_BIT false @@ -398,6 +402,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR, .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK, + .addr_od = ST_ACCEL_2_OD_IRQ_ADDR, + .mask_od = ST_ACCEL_2_OD_IRQ_MASK, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, @@ -587,6 +593,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR, .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK, + .addr_od = ST_ACCEL_5_OD_IRQ_ADDR, + .mask_od = ST_ACCEL_5_OD_IRQ_MASK, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index f5a2d445d0c0..dffe00692169 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -301,6 +301,14 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, return -EINVAL; } + if (pdata->open_drain) { + if (!sdata->sensor_settings->drdy_irq.addr_od) + dev_err(&indio_dev->dev, + "open drain requested but unsupported.\n"); + else + sdata->int_pin_open_drain = true; + } + return 0; } @@ -321,6 +329,8 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, else pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; + pdata->open_drain = of_property_read_bool(np, "drive-open-drain"); + return pdata; } #else @@ -374,6 +384,16 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, return err; } + if (sdata->int_pin_open_drain) { + dev_info(&indio_dev->dev, + "set interrupt line to open drain mode\n"); + err = st_sensors_write_data_with_mask(indio_dev, + sdata->sensor_settings->drdy_irq.addr_od, + sdata->sensor_settings->drdy_irq.mask_od, 1); + if (err < 0) + return err; + } + err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); return err; diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 6a8c98327945..da72279fcf99 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -64,6 +64,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, "rising edge\n", irq_trig); irq_trig = IRQF_TRIGGER_RISING; } + + /* + * If the interrupt pin is Open Drain, by definition this + * means that the interrupt line may be shared with other + * peripherals. But to do this we also need to have a status + * register and mask to figure out if this sensor was firing + * the IRQ or not, so we can tell the interrupt handle that + * it was "our" interrupt. + */ + if (sdata->int_pin_open_drain && + sdata->sensor_settings->drdy_irq.addr_stat_drdy) + irq_trig |= IRQF_SHARED; + err = request_threaded_irq(irq, iio_trigger_generic_data_rdy_poll, NULL, diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 1cd37eaa4a57..9e9b72a8f18f 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -64,6 +64,8 @@ #define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20 #define ST_PRESS_LPS331AP_IHL_IRQ_ADDR 0x22 #define ST_PRESS_LPS331AP_IHL_IRQ_MASK 0x80 +#define ST_PRESS_LPS331AP_OD_IRQ_ADDR 0x22 +#define ST_PRESS_LPS331AP_OD_IRQ_MASK 0x40 #define ST_PRESS_LPS331AP_MULTIREAD_BIT true #define ST_PRESS_LPS331AP_TEMP_OFFSET 42500 @@ -104,6 +106,8 @@ #define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10 #define ST_PRESS_LPS25H_IHL_IRQ_ADDR 0x22 #define ST_PRESS_LPS25H_IHL_IRQ_MASK 0x80 +#define ST_PRESS_LPS25H_OD_IRQ_ADDR 0x22 +#define ST_PRESS_LPS25H_OD_IRQ_MASK 0x40 #define ST_PRESS_LPS25H_MULTIREAD_BIT true #define ST_PRESS_LPS25H_TEMP_OFFSET 42500 #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 @@ -226,6 +230,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR, .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK, + .addr_od = ST_PRESS_LPS331AP_OD_IRQ_ADDR, + .mask_od = ST_PRESS_LPS331AP_OD_IRQ_MASK, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT, @@ -313,6 +319,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK, .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR, .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK, + .addr_od = ST_PRESS_LPS25H_OD_IRQ_ADDR, + .mask_od = ST_PRESS_LPS25H_OD_IRQ_MASK, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index d8da075bfda0..d029ffac0d69 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -122,6 +122,8 @@ struct st_sensor_bdu { * @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. + * @addr_od: address to enable/disable Open Drain on the INT lines. + * @mask_od: mask to enable/disable Open Drain on the INT lines. * @addr_stat_drdy: address to read status of DRDY (data ready) interrupt * struct ig1 - represents the Interrupt Generator 1 of sensors. * @en_addr: address of the enable ig1 register. @@ -133,6 +135,8 @@ struct st_sensor_data_ready_irq { u8 mask_int2; u8 addr_ihl; u8 mask_ihl; + u8 addr_od; + u8 mask_od; u8 addr_stat_drdy; struct { u8 en_addr; @@ -215,6 +219,7 @@ struct st_sensor_settings { * @odr: Output data rate of the sensor [Hz]. * num_data_channels: Number of data channels used in buffer. * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). + * @int_pin_open_drain: Set the interrupt/DRDY to open drain. * @get_irq_data_ready: Function to get the IRQ used for data ready signal. * @tf: Transfer function structure used by I/O operations. * @tb: Transfer buffers and mutex used by I/O operations. @@ -236,6 +241,7 @@ struct st_sensor_data { unsigned int num_data_channels; u8 drdy_int_pin; + bool int_pin_open_drain; unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev); diff --git a/include/linux/platform_data/st_sensors_pdata.h b/include/linux/platform_data/st_sensors_pdata.h index 753839187ba0..79b0e4cdb814 100644 --- a/include/linux/platform_data/st_sensors_pdata.h +++ b/include/linux/platform_data/st_sensors_pdata.h @@ -16,9 +16,11 @@ * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). * Available only for accelerometer and pressure sensors. * Accelerometer DRDY on LSM330 available only on pin 1 (see datasheet). + * @open_drain: set the interrupt line to be open drain if possible. */ struct st_sensors_platform_data { u8 drdy_int_pin; + bool open_drain; }; #endif /* ST_SENSORS_PDATA_H */ -- GitLab From 5f991a921a08279f573fa5ecf84261a3a6fac0cc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 14 Apr 2016 10:26:47 +0200 Subject: [PATCH 3447/9938] iio: tools: generic_buffer: auto-enable channels If no channels are enabled when we run generic_buffer on a device, add a command-line option to just enable all of them, run the sampling and disable them all again afterwards. This is extremely useful when I'm low-level testing my sensors with interrupts and triggers, sample session: root@Ux500:/ lsiio Device 000: lsm303dlh_accel Device 001: lis331dl_accel Device 002: l3g4200d Device 003: lsm303dlh_magn Device 004: lps001wp Trigger 000: lsm303dlh_accel-trigger Trigger 001: lis331dl_accel-trigger Trigger 002: l3g4200d-trigger root@Ux500:/ generic_buffer -a -c 10 -n l3g4200d iio device number being used is 2 iio trigger number being used is 2 No channels are enabled, enabling all channels Enabling: in_anglvel_x_en Enabling: in_anglvel_y_en Enabling: in_anglvel_z_en Enabling: in_timestamp_en /sys/bus/iio/devices/iio:device2 l3g4200d-trigger -3.593664 -0.713133 4.870143 946684863662292480 3.225546 0.867357 -4.945878 946684863671875000 -0.676413 0.127296 0.106641 946684863681488037 -0.661113 0.110160 0.128826 946684863690673828 -0.664173 0.113067 0.123471 946684863700683593 -0.664938 0.109395 0.124848 946684863710144042 -0.664173 0.110619 0.130203 946684863719512939 -0.666162 0.111231 0.132651 946684863729125976 -0.668610 0.111690 0.130662 946684863738739013 -0.660501 0.110466 0.131733 946684863748565673 Disabling: in_anglvel_x_en Disabling: in_anglvel_y_en Disabling: in_anglvel_z_en Disabling: in_timestamp_en Pure awesomeness. If some channels have been enabled through scripts or manual interaction, nothing happens. Cc: Peter Meerwald-Stadler Acked-by: Daniel Baluta Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- tools/iio/generic_buffer.c | 102 +++++++++++++++++++++++++++++++++++-- tools/iio/iio_utils.h | 7 +++ 2 files changed, 105 insertions(+), 4 deletions(-) diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c index c42b7f836b48..2429c78de940 100644 --- a/tools/iio/generic_buffer.c +++ b/tools/iio/generic_buffer.c @@ -34,6 +34,15 @@ #include #include "iio_utils.h" +/** + * enum autochan - state for the automatic channel enabling mechanism + */ +enum autochan { + AUTOCHANNELS_DISABLED, + AUTOCHANNELS_ENABLED, + AUTOCHANNELS_ACTIVE, +}; + /** * size_from_channelarray() - calculate the storage size of a scan * @channels: the channel info array @@ -191,10 +200,51 @@ void process_scan(char *data, printf("\n"); } +static int enable_disable_all_channels(char *dev_dir_name, int enable) +{ + const struct dirent *ent; + char scanelemdir[256]; + DIR *dp; + int ret; + + snprintf(scanelemdir, sizeof(scanelemdir), + FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name); + scanelemdir[sizeof(scanelemdir)-1] = '\0'; + + dp = opendir(scanelemdir); + if (!dp) { + fprintf(stderr, "Enabling/disabling channels: can't open %s\n", + scanelemdir); + return -EIO; + } + + ret = -ENOENT; + while (ent = readdir(dp), ent) { + if (iioutils_check_suffix(ent->d_name, "_en")) { + printf("%sabling: %s\n", + enable ? "En" : "Dis", + ent->d_name); + ret = write_sysfs_int(ent->d_name, scanelemdir, + enable); + if (ret < 0) + fprintf(stderr, "Failed to enable/disable %s\n", + ent->d_name); + } + } + + if (closedir(dp) == -1) { + perror("Enabling/disabling channels: " + "Failed to close directory"); + return -errno; + } + return 0; +} + void print_usage(void) { fprintf(stderr, "Usage: generic_buffer [options]...\n" "Capture, convert and output data from IIO device buffer\n" + " -a Auto-activate all available channels\n" " -c Do n conversions\n" " -e Disable wait for event (new data)\n" " -g Use trigger-less mode\n" @@ -225,12 +275,16 @@ int main(int argc, char **argv) int scan_size; int noevents = 0; int notrigger = 0; + enum autochan autochannels = AUTOCHANNELS_DISABLED; char *dummy; struct iio_channel_info *channels; - while ((c = getopt(argc, argv, "c:egl:n:t:w:")) != -1) { + while ((c = getopt(argc, argv, "ac:egl:n:t:w:")) != -1) { switch (c) { + case 'a': + autochannels = AUTOCHANNELS_ENABLED; + break; case 'c': errno = 0; num_loops = strtoul(optarg, &dummy, 10); @@ -340,12 +394,47 @@ int main(int argc, char **argv) "diag %s\n", dev_dir_name); goto error_free_triggername; } - if (!num_channels) { + if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { + fprintf(stderr, "Auto-channels selected but some channels " + "are already activated in sysfs\n"); + fprintf(stderr, "Proceeding without activating any channels\n"); + } + + if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) { + fprintf(stderr, + "No channels are enabled, enabling all channels\n"); + + ret = enable_disable_all_channels(dev_dir_name, 1); + if (ret) { + fprintf(stderr, "Failed to enable all channels\n"); + goto error_free_triggername; + } + + /* This flags that we need to disable the channels again */ + autochannels = AUTOCHANNELS_ACTIVE; + + ret = build_channel_array(dev_dir_name, &channels, + &num_channels); + if (ret) { + fprintf(stderr, "Problem reading scan element " + "information\n" + "diag %s\n", dev_dir_name); + goto error_disable_channels; + } + if (!num_channels) { + fprintf(stderr, "Still no channels after " + "auto-enabling, giving up\n"); + goto error_disable_channels; + } + } + + if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) { fprintf(stderr, "No channels are enabled, we have nothing to scan.\n"); fprintf(stderr, "Enable channels manually in " FORMAT_SCAN_ELEMENTS_DIR - "/*_en and try again.\n", dev_dir_name); + "/*_en or pass -a to autoenable channels and " + "try again.\n", dev_dir_name); ret = -ENOENT; goto error_free_triggername; } @@ -479,7 +568,12 @@ int main(int argc, char **argv) error_free_triggername: if (datardytrigger) free(trigger_name); - +error_disable_channels: + if (autochannels == AUTOCHANNELS_ACTIVE) { + ret = enable_disable_all_channels(dev_dir_name, 0); + if (ret) + fprintf(stderr, "Failed to disable all channels\n"); + } error_free_dev_dir_name: free(dev_dir_name); diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h index e3503bfe538b..780f2014f8fa 100644 --- a/tools/iio/iio_utils.h +++ b/tools/iio/iio_utils.h @@ -52,6 +52,13 @@ struct iio_channel_info { unsigned location; }; +static inline int iioutils_check_suffix(const char *str, const char *suffix) +{ + return strlen(str) >= strlen(suffix) && + strncmp(str+strlen(str)-strlen(suffix), + suffix, strlen(suffix)) == 0; +} + int iioutils_break_up_name(const char *full_name, char **generic_name); int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, unsigned *shift, uint64_t *mask, unsigned *be, -- GitLab From 8bf872d8d261feefcdf67027522e3f717cad2bfe Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 6 Apr 2016 16:01:06 +0530 Subject: [PATCH 3448/9938] iio: core: Add devm_ APIs for iio_channel_{get,release} Some of kernel driver uses the IIO framework to get the sensor value via ADC or IIO HW driver. The client driver get iio channel by iio_channel_get() and release it by calling iio_channel_release(). Add resource managed version (devm_*) of these APIs so that if client calls the devm_iio_channel_get() then it need not to release it explicitly, it can be done by managed device framework when driver get un-binded. This reduces the code in error path and also need of .remove callback in some cases. Signed-off-by: Laxman Dewangan Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 48 ++++++++++++++++++++++++++++++++++++ include/linux/iio/consumer.h | 27 ++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 2fc7928f401d..9fd8934c1887 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -356,6 +356,54 @@ void iio_channel_release(struct iio_channel *channel) } EXPORT_SYMBOL_GPL(iio_channel_release); +static void devm_iio_channel_free(struct device *dev, void *res) +{ + struct iio_channel *channel = *(struct iio_channel **)res; + + iio_channel_release(channel); +} + +static int devm_iio_channel_match(struct device *dev, void *res, void *data) +{ + struct iio_channel **r = res; + + if (!r || !*r) { + WARN_ON(!r || !*r); + return 0; + } + + return *r == data; +} + +struct iio_channel *devm_iio_channel_get(struct device *dev, + const char *channel_name) +{ + struct iio_channel **ptr, *channel; + + ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + channel = iio_channel_get(dev, channel_name); + if (IS_ERR(channel)) { + devres_free(ptr); + return channel; + } + + *ptr = channel; + devres_add(dev, ptr); + + return channel; +} +EXPORT_SYMBOL_GPL(devm_iio_channel_get); + +void devm_iio_channel_release(struct device *dev, struct iio_channel *channel) +{ + WARN_ON(devres_release(dev, devm_iio_channel_free, + devm_iio_channel_match, channel)); +} +EXPORT_SYMBOL_GPL(devm_iio_channel_release); + struct iio_channel *iio_channel_get_all(struct device *dev) { const char *name; diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index fad58671c49e..e1e033d6a81f 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -48,6 +48,33 @@ struct iio_channel *iio_channel_get(struct device *dev, */ void iio_channel_release(struct iio_channel *chan); +/** + * devm_iio_channel_get() - Resource managed version of iio_channel_get(). + * @dev: Pointer to consumer device. Device name must match + * the name of the device as provided in the iio_map + * with which the desired provider to consumer mapping + * was registered. + * @consumer_channel: Unique name to identify the channel on the consumer + * side. This typically describes the channels use within + * the consumer. E.g. 'battery_voltage' + * + * Returns a pointer to negative errno if it is not able to get the iio channel + * otherwise returns valid pointer for iio channel. + * + * The allocated iio channel is automatically released when the device is + * unbound. + */ +struct iio_channel *devm_iio_channel_get(struct device *dev, + const char *consumer_channel); +/** + * devm_iio_channel_release() - Resource managed version of + * iio_channel_release(). + * @dev: Pointer to consumer device for which resource + * is allocared. + * @chan: The channel to be released. + */ +void devm_iio_channel_release(struct device *dev, struct iio_channel *chan); + /** * iio_channel_get_all() - get all channels associated with a client * @dev: Pointer to consumer device. -- GitLab From efc2c0133f198bc65593a67015af358919b0c48f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 6 Apr 2016 16:01:07 +0530 Subject: [PATCH 3449/9938] iio: core: Add devm_ APIs for iio_channel_{get,release}_all Some of kernel driver uses the IIO framework to get the sensor value via ADC or IIO HW driver. The client driver get iio channel by iio_channel_get_all() and release it by calling iio_channel_release_all(). Add resource managed version (devm_*) of these APIs so that if client calls the devm_iio_channel_get_all() then it need not to release it explicitly, it can be done by managed device framework when driver get un-binded. This reduces the code in error path and also need of .remove callback in some cases. Signed-off-by: Laxman Dewangan Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/iio/consumer.h | 26 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 9fd8934c1887..c4757e6367e7 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -489,6 +489,42 @@ void iio_channel_release_all(struct iio_channel *channels) } EXPORT_SYMBOL_GPL(iio_channel_release_all); +static void devm_iio_channel_free_all(struct device *dev, void *res) +{ + struct iio_channel *channels = *(struct iio_channel **)res; + + iio_channel_release_all(channels); +} + +struct iio_channel *devm_iio_channel_get_all(struct device *dev) +{ + struct iio_channel **ptr, *channels; + + ptr = devres_alloc(devm_iio_channel_free_all, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + channels = iio_channel_get_all(dev); + if (IS_ERR(channels)) { + devres_free(ptr); + return channels; + } + + *ptr = channels; + devres_add(dev, ptr); + + return channels; +} +EXPORT_SYMBOL_GPL(devm_iio_channel_get_all); + +void devm_iio_channel_release_all(struct device *dev, + struct iio_channel *channels) +{ + WARN_ON(devres_release(dev, devm_iio_channel_free_all, + devm_iio_channel_match, channels)); +} +EXPORT_SYMBOL_GPL(devm_iio_channel_release_all); + static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, enum iio_chan_info_enum info) { diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index e1e033d6a81f..3d672f72e7ec 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -92,6 +92,32 @@ struct iio_channel *iio_channel_get_all(struct device *dev); */ void iio_channel_release_all(struct iio_channel *chan); +/** + * devm_iio_channel_get_all() - Resource managed version of + * iio_channel_get_all(). + * @dev: Pointer to consumer device. + * + * Returns a pointer to negative errno if it is not able to get the iio channel + * otherwise returns an array of iio_channel structures terminated with one with + * null iio_dev pointer. + * + * This function is used by fairly generic consumers to get all the + * channels registered as having this consumer. + * + * The allocated iio channels are automatically released when the device is + * unbounded. + */ +struct iio_channel *devm_iio_channel_get_all(struct device *dev); + +/** + * devm_iio_channel_release_all() - Resource managed version of + * iio_channel_release_all(). + * @dev: Pointer to consumer device for which resource + * is allocared. + * @chan: Array channel to be released. + */ +void devm_iio_channel_release_all(struct device *dev, struct iio_channel *chan); + struct iio_cb_buffer; /** * iio_channel_get_all_cb() - register callback for triggered capture -- GitLab From e21a294d1e35e890c1b5f0a29df15f75c8934a73 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 6 Apr 2016 16:01:08 +0530 Subject: [PATCH 3450/9938] iio: Add resource managed APIs devm_iio_channel_{get,release) in devres Add following APIs in the list of managed resources of IIO: devm_iio_channel_get() devm_iio_channel_get_all() devm_iio_channel_release() devm_iio_channel_release_all() Signed-off-by: Laxman Dewangan Signed-off-by: Jonathan Cameron --- Documentation/driver-model/devres.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 73b98dfbcea4..bdc2dfbe6795 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -267,6 +267,10 @@ IIO devm_iio_kfifo_free() devm_iio_trigger_alloc() devm_iio_trigger_free() + devm_iio_channel_get() + devm_iio_channel_release() + devm_iio_channel_get_all() + devm_iio_channel_release_all() IO region devm_release_mem_region() -- GitLab From dfd2ab8dda719b98203f5b3e940961019d373541 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler Date: Sun, 20 Mar 2016 16:20:24 +0100 Subject: [PATCH 3451/9938] iio: Add Vishay VEML6070 UV A light sensor driver ultraviolet (UV) light sensor with I2C interface with a peak sensitivity at 355 nm strangely, chip uses two addresses 0x38 and 0x39 for LSB and MSB data, resp. datasheet: http://www.vishay.com/docs/84277/veml6070.pdf Signed-off-by: Peter Meerwald-Stadler Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 10 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/veml6070.c | 218 +++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 drivers/iio/light/veml6070.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 5ee1d453b3d8..cbd723236e38 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -331,4 +331,14 @@ config VCNL4000 To compile this driver as a module, choose M here: the module will be called vcnl4000. +config VEML6070 + tristate "VEML6070 UV A light sensor" + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VEML6070 UV A + light sensor. + + To compile this driver as a module, choose M here: the + module will be called veml6070. + endmenu diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 4aeee2bd8f49..8b246a604a92 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_TCS3472) += tcs3472.o obj-$(CONFIG_TSL4531) += tsl4531.o obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_VCNL4000) += vcnl4000.o +obj-$(CONFIG_VEML6070) += veml6070.o diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c new file mode 100644 index 000000000000..bc1c4cb782cd --- /dev/null +++ b/drivers/iio/light/veml6070.c @@ -0,0 +1,218 @@ +/* + * veml6070.c - Support for Vishay VEML6070 UV A light sensor + * + * Copyright 2016 Peter Meerwald-Stadler + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39) + * + * TODO: integration time, ACK signal + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define VEML6070_DRV_NAME "veml6070" + +#define VEML6070_ADDR_CONFIG_DATA_MSB 0x38 /* read: MSB data, write: config */ +#define VEML6070_ADDR_DATA_LSB 0x39 /* LSB data */ + +#define VEML6070_COMMAND_ACK BIT(5) /* raise interrupt when over threshold */ +#define VEML6070_COMMAND_IT GENMASK(3, 2) /* bit mask integration time */ +#define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */ +#define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */ + +#define VEML6070_IT_10 0x04 /* integration time 1x */ + +struct veml6070_data { + struct i2c_client *client1; + struct i2c_client *client2; + u8 config; + struct mutex lock; +}; + +static int veml6070_read(struct veml6070_data *data) +{ + int ret; + u8 msb, lsb; + + mutex_lock(&data->lock); + + /* disable shutdown */ + ret = i2c_smbus_write_byte(data->client1, + data->config & ~VEML6070_COMMAND_SD); + if (ret < 0) + goto out; + + msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */ + + ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */ + if (ret < 0) + goto out; + msb = ret; + + ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */ + if (ret < 0) + goto out; + lsb = ret; + + /* shutdown again */ + ret = i2c_smbus_write_byte(data->client1, data->config); + if (ret < 0) + goto out; + + ret = (msb << 8) | lsb; + +out: + mutex_unlock(&data->lock); + return ret; +} + +static const struct iio_chan_spec veml6070_channels[] = { + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_UV, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, + { + .type = IIO_UVINDEX, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + } +}; + +static int veml6070_to_uv_index(unsigned val) +{ + /* + * conversion of raw UV intensity values to UV index depends on + * integration time (IT) and value of the resistor connected to + * the RSET pin (default: 270 KOhm) + */ + unsigned uvi[11] = { + 187, 373, 560, /* low */ + 746, 933, 1120, /* moderate */ + 1308, 1494, /* high */ + 1681, 1868, 2054}; /* very high */ + int i; + + for (i = 0; i < ARRAY_SIZE(uvi); i++) + if (val <= uvi[i]) + return i; + + return 11; /* extreme */ +} + +static int veml6070_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct veml6070_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + ret = veml6070_read(data); + if (ret < 0) + return ret; + if (mask == IIO_CHAN_INFO_PROCESSED) + *val = veml6070_to_uv_index(ret); + else + *val = ret; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_info veml6070_info = { + .read_raw = veml6070_read_raw, + .driver_module = THIS_MODULE, +}; + +static int veml6070_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct veml6070_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client1 = client; + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &veml6070_info; + indio_dev->channels = veml6070_channels; + indio_dev->num_channels = ARRAY_SIZE(veml6070_channels); + indio_dev->name = VEML6070_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); + if (!data->client2) { + dev_err(&client->dev, "i2c device for second chip address failed\n"); + return -ENODEV; + } + + data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | + VEML6070_COMMAND_SD; + ret = i2c_smbus_write_byte(data->client1, data->config); + if (ret < 0) + goto fail; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto fail; + + return ret; + +fail: + i2c_unregister_device(data->client2); + return ret; +} + +static int veml6070_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct veml6070_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + i2c_unregister_device(data->client2); + + return 0; +} + +static const struct i2c_device_id veml6070_id[] = { + { "veml6070", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, veml6070_id); + +static struct i2c_driver veml6070_driver = { + .driver = { + .name = VEML6070_DRV_NAME, + }, + .probe = veml6070_probe, + .remove = veml6070_remove, + .id_table = veml6070_id, +}; + +module_i2c_driver(veml6070_driver); + +MODULE_AUTHOR("Peter Meerwald-Stadler "); +MODULE_DESCRIPTION("Vishay VEML6070 UV A light sensor driver"); +MODULE_LICENSE("GPL"); -- GitLab From 0ef4c311abdc821d10e092ae623e022dd4b6a6d4 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sun, 10 Apr 2016 12:05:13 -0700 Subject: [PATCH 3452/9938] iio: accel: bmc150: use regmap to retrieve struct device Driver includes struct regmap and struct device in its global data. Remove the struct device and use regmap API to retrieve device info. Patch created using Coccinelle plus manual edits. Signed-off-by: Alison Schofield Reviewed-by: Irina Tirdea Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel-core.c | 99 +++++++++++++++------------ 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index e631ee9a6a77..91a52c275d0e 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -188,7 +188,6 @@ enum bmc150_accel_trigger_id { struct bmc150_accel_data { struct regmap *regmap; - struct device *dev; int irq; struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; atomic_t active_intr; @@ -257,6 +256,7 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data, enum bmc150_power_modes mode, int dur_us) { + struct device *dev = regmap_get_device(data->regmap); int i; int ret; u8 lpw_bits; @@ -280,11 +280,11 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data, lpw_bits = mode << BMC150_ACCEL_PMU_MODE_SHIFT; lpw_bits |= (dur_val << BMC150_ACCEL_PMU_BIT_SLEEP_DUR_SHIFT); - dev_dbg(data->dev, "Set Mode bits %x\n", lpw_bits); + dev_dbg(dev, "Set Mode bits %x\n", lpw_bits); ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits); if (ret < 0) { - dev_err(data->dev, "Error writing reg_pmu_lpw\n"); + dev_err(dev, "Error writing reg_pmu_lpw\n"); return ret; } @@ -317,23 +317,24 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val, static int bmc150_accel_update_slope(struct bmc150_accel_data *data) { + struct device *dev = regmap_get_device(data->regmap); int ret; ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6, data->slope_thres); if (ret < 0) { - dev_err(data->dev, "Error writing reg_int_6\n"); + dev_err(dev, "Error writing reg_int_6\n"); return ret; } ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5, BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur); if (ret < 0) { - dev_err(data->dev, "Error updating reg_int_5\n"); + dev_err(dev, "Error updating reg_int_5\n"); return ret; } - dev_dbg(data->dev, "%s: %x %x\n", __func__, data->slope_thres, + dev_dbg(dev, "%s: %x %x\n", __func__, data->slope_thres, data->slope_dur); return ret; @@ -379,20 +380,21 @@ static int bmc150_accel_get_startup_times(struct bmc150_accel_data *data) static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) { + struct device *dev = regmap_get_device(data->regmap); int ret; if (on) { - ret = pm_runtime_get_sync(data->dev); + ret = pm_runtime_get_sync(dev); } else { - pm_runtime_mark_last_busy(data->dev); - ret = pm_runtime_put_autosuspend(data->dev); + pm_runtime_mark_last_busy(dev); + ret = pm_runtime_put_autosuspend(dev); } if (ret < 0) { - dev_err(data->dev, + dev_err(dev, "Failed: bmc150_accel_set_power_state for %d\n", on); if (on) - pm_runtime_put_noidle(data->dev); + pm_runtime_put_noidle(dev); return ret; } @@ -446,6 +448,7 @@ static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev, static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i, bool state) { + struct device *dev = regmap_get_device(data->regmap); struct bmc150_accel_interrupt *intr = &data->interrupts[i]; const struct bmc150_accel_interrupt_info *info = intr->info; int ret; @@ -475,7 +478,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i, ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask, (state ? info->map_bitmask : 0)); if (ret < 0) { - dev_err(data->dev, "Error updating reg_int_map\n"); + dev_err(dev, "Error updating reg_int_map\n"); goto out_fix_power_state; } @@ -483,7 +486,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i, ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask, (state ? info->en_bitmask : 0)); if (ret < 0) { - dev_err(data->dev, "Error updating reg_int_en\n"); + dev_err(dev, "Error updating reg_int_en\n"); goto out_fix_power_state; } @@ -501,6 +504,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i, static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val) { + struct device *dev = regmap_get_device(data->regmap); int ret, i; for (i = 0; i < ARRAY_SIZE(data->chip_info->scale_table); ++i) { @@ -509,8 +513,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val) BMC150_ACCEL_REG_PMU_RANGE, data->chip_info->scale_table[i].reg_range); if (ret < 0) { - dev_err(data->dev, - "Error writing pmu_range\n"); + dev_err(dev, "Error writing pmu_range\n"); return ret; } @@ -524,6 +527,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val) static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val) { + struct device *dev = regmap_get_device(data->regmap); int ret; unsigned int value; @@ -531,7 +535,7 @@ static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val) ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value); if (ret < 0) { - dev_err(data->dev, "Error reading reg_temp\n"); + dev_err(dev, "Error reading reg_temp\n"); mutex_unlock(&data->mutex); return ret; } @@ -546,6 +550,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data, struct iio_chan_spec const *chan, int *val) { + struct device *dev = regmap_get_device(data->regmap); int ret; int axis = chan->scan_index; unsigned int raw_val; @@ -560,7 +565,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data, ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis), &raw_val, 2); if (ret < 0) { - dev_err(data->dev, "Error reading axis %d\n", axis); + dev_err(dev, "Error reading axis %d\n", axis); bmc150_accel_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; @@ -832,6 +837,7 @@ static int bmc150_accel_set_watermark(struct iio_dev *indio_dev, unsigned val) static int bmc150_accel_fifo_transfer(struct bmc150_accel_data *data, char *buffer, int samples) { + struct device *dev = regmap_get_device(data->regmap); int sample_length = 3 * 2; int ret; int total_length = samples * sample_length; @@ -855,7 +861,8 @@ static int bmc150_accel_fifo_transfer(struct bmc150_accel_data *data, } if (ret) - dev_err(data->dev, "Error transferring data from fifo in single steps of %zu\n", + dev_err(dev, + "Error transferring data from fifo in single steps of %zu\n", step); return ret; @@ -865,6 +872,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev, unsigned samples, bool irq) { struct bmc150_accel_data *data = iio_priv(indio_dev); + struct device *dev = regmap_get_device(data->regmap); int ret, i; u8 count; u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3]; @@ -874,7 +882,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev, ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val); if (ret < 0) { - dev_err(data->dev, "Error reading reg_fifo_status\n"); + dev_err(dev, "Error reading reg_fifo_status\n"); return ret; } @@ -1136,6 +1144,7 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig) { struct bmc150_accel_trigger *t = iio_trigger_get_drvdata(trig); struct bmc150_accel_data *data = t->data; + struct device *dev = regmap_get_device(data->regmap); int ret; /* new data interrupts don't need ack */ @@ -1149,8 +1158,7 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig) BMC150_ACCEL_INT_MODE_LATCH_RESET); mutex_unlock(&data->mutex); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_int_rst_latch\n"); + dev_err(dev, "Error writing reg_int_rst_latch\n"); return ret; } @@ -1201,13 +1209,14 @@ static const struct iio_trigger_ops bmc150_accel_trigger_ops = { static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev) { struct bmc150_accel_data *data = iio_priv(indio_dev); + struct device *dev = regmap_get_device(data->regmap); int dir; int ret; unsigned int val; ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val); if (ret < 0) { - dev_err(data->dev, "Error reading reg_int_status_2\n"); + dev_err(dev, "Error reading reg_int_status_2\n"); return ret; } @@ -1250,6 +1259,7 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private) { struct iio_dev *indio_dev = private; struct bmc150_accel_data *data = iio_priv(indio_dev); + struct device *dev = regmap_get_device(data->regmap); bool ack = false; int ret; @@ -1273,7 +1283,7 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private) BMC150_ACCEL_INT_MODE_LATCH_INT | BMC150_ACCEL_INT_MODE_LATCH_RESET); if (ret) - dev_err(data->dev, "Error writing reg_int_rst_latch\n"); + dev_err(dev, "Error writing reg_int_rst_latch\n"); ret = IRQ_HANDLED; } else { @@ -1344,13 +1354,14 @@ static void bmc150_accel_unregister_triggers(struct bmc150_accel_data *data, static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev, struct bmc150_accel_data *data) { + struct device *dev = regmap_get_device(data->regmap); int i, ret; for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) { struct bmc150_accel_trigger *t = &data->triggers[i]; - t->indio_trig = devm_iio_trigger_alloc(data->dev, - bmc150_accel_triggers[i].name, + t->indio_trig = devm_iio_trigger_alloc(dev, + bmc150_accel_triggers[i].name, indio_dev->name, indio_dev->id); if (!t->indio_trig) { @@ -1358,7 +1369,7 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev, break; } - t->indio_trig->dev.parent = data->dev; + t->indio_trig->dev.parent = dev; t->indio_trig->ops = &bmc150_accel_trigger_ops; t->intr = bmc150_accel_triggers[i].intr; t->data = data; @@ -1382,12 +1393,13 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev, static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data) { + struct device *dev = regmap_get_device(data->regmap); u8 reg = BMC150_ACCEL_REG_FIFO_CONFIG1; int ret; ret = regmap_write(data->regmap, reg, data->fifo_mode); if (ret < 0) { - dev_err(data->dev, "Error writing reg_fifo_config1\n"); + dev_err(dev, "Error writing reg_fifo_config1\n"); return ret; } @@ -1397,7 +1409,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data) ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0, data->watermark); if (ret < 0) - dev_err(data->dev, "Error writing reg_fifo_config0\n"); + dev_err(dev, "Error writing reg_fifo_config0\n"); return ret; } @@ -1481,17 +1493,17 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = { static int bmc150_accel_chip_init(struct bmc150_accel_data *data) { + struct device *dev = regmap_get_device(data->regmap); int ret, i; unsigned int val; ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val); if (ret < 0) { - dev_err(data->dev, - "Error: Reading chip id\n"); + dev_err(dev, "Error: Reading chip id\n"); return ret; } - dev_dbg(data->dev, "Chip Id %x\n", val); + dev_dbg(dev, "Chip Id %x\n", val); for (i = 0; i < ARRAY_SIZE(bmc150_accel_chip_info_tbl); i++) { if (bmc150_accel_chip_info_tbl[i].chip_id == val) { data->chip_info = &bmc150_accel_chip_info_tbl[i]; @@ -1500,7 +1512,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data) } if (!data->chip_info) { - dev_err(data->dev, "Invalid chip %x\n", val); + dev_err(dev, "Invalid chip %x\n", val); return -ENODEV; } @@ -1517,8 +1529,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data) ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE, BMC150_ACCEL_DEF_RANGE_4G); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_pmu_range\n"); + dev_err(dev, "Error writing reg_pmu_range\n"); return ret; } @@ -1536,8 +1547,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data) BMC150_ACCEL_INT_MODE_LATCH_INT | BMC150_ACCEL_INT_MODE_LATCH_RESET); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_int_rst_latch\n"); + dev_err(dev, "Error writing reg_int_rst_latch\n"); return ret; } @@ -1557,7 +1567,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, data = iio_priv(indio_dev); dev_set_drvdata(dev, indio_dev); - data->dev = dev; data->irq = irq; data->regmap = regmap; @@ -1581,13 +1590,13 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, bmc150_accel_trigger_handler, &bmc150_accel_buffer_ops); if (ret < 0) { - dev_err(data->dev, "Failed: iio triggered buffer setup\n"); + dev_err(dev, "Failed: iio triggered buffer setup\n"); return ret; } if (data->irq > 0) { ret = devm_request_threaded_irq( - data->dev, data->irq, + dev, data->irq, bmc150_accel_irq_handler, bmc150_accel_irq_thread_handler, IRQF_TRIGGER_RISING, @@ -1605,7 +1614,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH, BMC150_ACCEL_INT_MODE_LATCH_RESET); if (ret < 0) { - dev_err(data->dev, "Error writing reg_int_rst_latch\n"); + dev_err(dev, "Error writing reg_int_rst_latch\n"); goto err_buffer_cleanup; } @@ -1654,9 +1663,9 @@ int bmc150_accel_core_remove(struct device *dev) iio_device_unregister(indio_dev); - pm_runtime_disable(data->dev); - pm_runtime_set_suspended(data->dev); - pm_runtime_put_noidle(data->dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); @@ -1705,7 +1714,7 @@ static int bmc150_accel_runtime_suspend(struct device *dev) struct bmc150_accel_data *data = iio_priv(indio_dev); int ret; - dev_dbg(data->dev, __func__); + dev_dbg(dev, __func__); ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0); if (ret < 0) return -EAGAIN; @@ -1720,7 +1729,7 @@ static int bmc150_accel_runtime_resume(struct device *dev) int ret; int sleep_val; - dev_dbg(data->dev, __func__); + dev_dbg(dev, __func__); ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); if (ret < 0) -- GitLab From dc2c57153ec5119eae7770042197eff627184d74 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Sun, 10 Apr 2016 12:08:14 -0700 Subject: [PATCH 3453/9938] iio: gyro: bmg160: use regmap to retrieve struct device Driver includes struct regmap and struct device in its global data. Remove the struct device and use regmap API to retrieve device info. Patch created using Coccinelle plus manual edits. Signed-off-by: Alison Schofield Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/bmg160_core.c | 86 +++++++++++++++++----------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index 2493bb17a03d..b2b1071c1892 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -95,7 +95,6 @@ #define BMG160_AUTO_SUSPEND_DELAY_MS 2000 struct bmg160_data { - struct device *dev; struct regmap *regmap; struct iio_trigger *dready_trig; struct iio_trigger *motion_trig; @@ -137,11 +136,12 @@ static const struct { static int bmg160_set_mode(struct bmg160_data *data, u8 mode) { + struct device *dev = regmap_get_device(data->regmap); int ret; ret = regmap_write(data->regmap, BMG160_REG_PMU_LPW, mode); if (ret < 0) { - dev_err(data->dev, "Error writing reg_pmu_lpw\n"); + dev_err(dev, "Error writing reg_pmu_lpw\n"); return ret; } @@ -162,6 +162,7 @@ static int bmg160_convert_freq_to_bit(int val) static int bmg160_set_bw(struct bmg160_data *data, int val) { + struct device *dev = regmap_get_device(data->regmap); int ret; int bw_bits; @@ -171,7 +172,7 @@ static int bmg160_set_bw(struct bmg160_data *data, int val) ret = regmap_write(data->regmap, BMG160_REG_PMU_BW, bw_bits); if (ret < 0) { - dev_err(data->dev, "Error writing reg_pmu_bw\n"); + dev_err(dev, "Error writing reg_pmu_bw\n"); return ret; } @@ -182,18 +183,19 @@ static int bmg160_set_bw(struct bmg160_data *data, int val) static int bmg160_chip_init(struct bmg160_data *data) { + struct device *dev = regmap_get_device(data->regmap); int ret; unsigned int val; ret = regmap_read(data->regmap, BMG160_REG_CHIP_ID, &val); if (ret < 0) { - dev_err(data->dev, "Error reading reg_chip_id\n"); + dev_err(dev, "Error reading reg_chip_id\n"); return ret; } - dev_dbg(data->dev, "Chip Id %x\n", val); + dev_dbg(dev, "Chip Id %x\n", val); if (val != BMG160_CHIP_ID_VAL) { - dev_err(data->dev, "invalid chip %x\n", val); + dev_err(dev, "invalid chip %x\n", val); return -ENODEV; } @@ -212,14 +214,14 @@ static int bmg160_chip_init(struct bmg160_data *data) /* Set Default Range */ ret = regmap_write(data->regmap, BMG160_REG_RANGE, BMG160_RANGE_500DPS); if (ret < 0) { - dev_err(data->dev, "Error writing reg_range\n"); + dev_err(dev, "Error writing reg_range\n"); return ret; } data->dps_range = BMG160_RANGE_500DPS; ret = regmap_read(data->regmap, BMG160_REG_SLOPE_THRES, &val); if (ret < 0) { - dev_err(data->dev, "Error reading reg_slope_thres\n"); + dev_err(dev, "Error reading reg_slope_thres\n"); return ret; } data->slope_thres = val; @@ -228,7 +230,7 @@ static int bmg160_chip_init(struct bmg160_data *data) ret = regmap_update_bits(data->regmap, BMG160_REG_INT_EN_1, BMG160_INT1_BIT_OD, 0); if (ret < 0) { - dev_err(data->dev, "Error updating bits in reg_int_en_1\n"); + dev_err(dev, "Error updating bits in reg_int_en_1\n"); return ret; } @@ -236,7 +238,7 @@ static int bmg160_chip_init(struct bmg160_data *data) BMG160_INT_MODE_LATCH_INT | BMG160_INT_MODE_LATCH_RESET); if (ret < 0) { - dev_err(data->dev, + dev_err(dev, "Error writing reg_motion_intr\n"); return ret; } @@ -247,20 +249,21 @@ static int bmg160_chip_init(struct bmg160_data *data) static int bmg160_set_power_state(struct bmg160_data *data, bool on) { #ifdef CONFIG_PM + struct device *dev = regmap_get_device(data->regmap); int ret; if (on) - ret = pm_runtime_get_sync(data->dev); + ret = pm_runtime_get_sync(dev); else { - pm_runtime_mark_last_busy(data->dev); - ret = pm_runtime_put_autosuspend(data->dev); + pm_runtime_mark_last_busy(dev); + ret = pm_runtime_put_autosuspend(dev); } if (ret < 0) { - dev_err(data->dev, - "Failed: bmg160_set_power_state for %d\n", on); + dev_err(dev, "Failed: bmg160_set_power_state for %d\n", on); + if (on) - pm_runtime_put_noidle(data->dev); + pm_runtime_put_noidle(dev); return ret; } @@ -272,6 +275,7 @@ static int bmg160_set_power_state(struct bmg160_data *data, bool on) static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, bool status) { + struct device *dev = regmap_get_device(data->regmap); int ret; /* Enable/Disable INT_MAP0 mapping */ @@ -279,7 +283,7 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, BMG160_INT_MAP_0_BIT_ANY, (status ? BMG160_INT_MAP_0_BIT_ANY : 0)); if (ret < 0) { - dev_err(data->dev, "Error updating bits reg_int_map0\n"); + dev_err(dev, "Error updating bits reg_int_map0\n"); return ret; } @@ -289,8 +293,7 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, ret = regmap_write(data->regmap, BMG160_REG_SLOPE_THRES, data->slope_thres); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_slope_thres\n"); + dev_err(dev, "Error writing reg_slope_thres\n"); return ret; } @@ -298,8 +301,7 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, BMG160_INT_MOTION_X | BMG160_INT_MOTION_Y | BMG160_INT_MOTION_Z); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_motion_intr\n"); + dev_err(dev, "Error writing reg_motion_intr\n"); return ret; } @@ -314,8 +316,7 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, BMG160_INT_MODE_LATCH_INT | BMG160_INT_MODE_LATCH_RESET); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_rst_latch\n"); + dev_err(dev, "Error writing reg_rst_latch\n"); return ret; } } @@ -328,7 +329,7 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, } if (ret < 0) { - dev_err(data->dev, "Error writing reg_int_en0\n"); + dev_err(dev, "Error writing reg_int_en0\n"); return ret; } @@ -338,6 +339,7 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, static int bmg160_setup_new_data_interrupt(struct bmg160_data *data, bool status) { + struct device *dev = regmap_get_device(data->regmap); int ret; /* Enable/Disable INT_MAP1 mapping */ @@ -345,7 +347,7 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data, BMG160_INT_MAP_1_BIT_NEW_DATA, (status ? BMG160_INT_MAP_1_BIT_NEW_DATA : 0)); if (ret < 0) { - dev_err(data->dev, "Error updating bits in reg_int_map1\n"); + dev_err(dev, "Error updating bits in reg_int_map1\n"); return ret; } @@ -354,9 +356,8 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data, BMG160_INT_MODE_NON_LATCH_INT | BMG160_INT_MODE_LATCH_RESET); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_rst_latch\n"); - return ret; + dev_err(dev, "Error writing reg_rst_latch\n"); + return ret; } ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, @@ -368,16 +369,15 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data, BMG160_INT_MODE_LATCH_INT | BMG160_INT_MODE_LATCH_RESET); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_rst_latch\n"); - return ret; + dev_err(dev, "Error writing reg_rst_latch\n"); + return ret; } ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0); } if (ret < 0) { - dev_err(data->dev, "Error writing reg_int_en0\n"); + dev_err(dev, "Error writing reg_int_en0\n"); return ret; } @@ -400,6 +400,7 @@ static int bmg160_get_bw(struct bmg160_data *data, int *val) static int bmg160_set_scale(struct bmg160_data *data, int val) { + struct device *dev = regmap_get_device(data->regmap); int ret, i; for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) { @@ -407,8 +408,7 @@ static int bmg160_set_scale(struct bmg160_data *data, int val) ret = regmap_write(data->regmap, BMG160_REG_RANGE, bmg160_scale_table[i].dps_range); if (ret < 0) { - dev_err(data->dev, - "Error writing reg_range\n"); + dev_err(dev, "Error writing reg_range\n"); return ret; } data->dps_range = bmg160_scale_table[i].dps_range; @@ -421,6 +421,7 @@ static int bmg160_set_scale(struct bmg160_data *data, int val) static int bmg160_get_temp(struct bmg160_data *data, int *val) { + struct device *dev = regmap_get_device(data->regmap); int ret; unsigned int raw_val; @@ -433,7 +434,7 @@ static int bmg160_get_temp(struct bmg160_data *data, int *val) ret = regmap_read(data->regmap, BMG160_REG_TEMP, &raw_val); if (ret < 0) { - dev_err(data->dev, "Error reading reg_temp\n"); + dev_err(dev, "Error reading reg_temp\n"); bmg160_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; @@ -450,6 +451,7 @@ static int bmg160_get_temp(struct bmg160_data *data, int *val) static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val) { + struct device *dev = regmap_get_device(data->regmap); int ret; unsigned int raw_val; @@ -463,7 +465,7 @@ static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val) ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(axis), &raw_val, 2); if (ret < 0) { - dev_err(data->dev, "Error reading axis %d\n", axis); + dev_err(dev, "Error reading axis %d\n", axis); bmg160_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; @@ -793,6 +795,7 @@ static int bmg160_trig_try_reen(struct iio_trigger *trig) { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct bmg160_data *data = iio_priv(indio_dev); + struct device *dev = regmap_get_device(data->regmap); int ret; /* new data interrupts don't need ack */ @@ -804,7 +807,7 @@ static int bmg160_trig_try_reen(struct iio_trigger *trig) BMG160_INT_MODE_LATCH_INT | BMG160_INT_MODE_LATCH_RESET); if (ret < 0) { - dev_err(data->dev, "Error writing reg_rst_latch\n"); + dev_err(dev, "Error writing reg_rst_latch\n"); return ret; } @@ -864,13 +867,14 @@ static irqreturn_t bmg160_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; struct bmg160_data *data = iio_priv(indio_dev); + struct device *dev = regmap_get_device(data->regmap); int ret; int dir; unsigned int val; ret = regmap_read(data->regmap, BMG160_REG_INT_STATUS_2, &val); if (ret < 0) { - dev_err(data->dev, "Error reading reg_int_status2\n"); + dev_err(dev, "Error reading reg_int_status2\n"); goto ack_intr_status; } @@ -907,8 +911,7 @@ static irqreturn_t bmg160_event_handler(int irq, void *private) BMG160_INT_MODE_LATCH_INT | BMG160_INT_MODE_LATCH_RESET); if (ret < 0) - dev_err(data->dev, - "Error writing reg_rst_latch\n"); + dev_err(dev, "Error writing reg_rst_latch\n"); } return IRQ_HANDLED; @@ -976,7 +979,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, data = iio_priv(indio_dev); dev_set_drvdata(dev, indio_dev); - data->dev = dev; data->irq = irq; data->regmap = regmap; @@ -1139,7 +1141,7 @@ static int bmg160_runtime_suspend(struct device *dev) ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND); if (ret < 0) { - dev_err(data->dev, "set mode failed\n"); + dev_err(dev, "set mode failed\n"); return -EAGAIN; } -- GitLab From 995d3fdeb2f2d362b1b6bf26656c417452939a1a Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 19 Apr 2016 21:07:01 +0200 Subject: [PATCH 3454/9938] clk: rockchip: reign in some overly long lines in the rk3399 controller We allow overlong lines in the array portitions describing the clock trees to ease readability by having each element always at the same position. But the rest of the code should honor the 80 char limit. Fix the newly added rk3399 clock code to respect that. Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 139 +++++++++++++++++------------- 1 file changed, 81 insertions(+), 58 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 356e13256242..e8f040be3fea 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -117,73 +117,96 @@ PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src", "gpll_aclk_cci_src", "npll_aclk_cci_src", "vpll_aclk_cci_src" }; -PNAME(mux_cci_trace_p) = { "cpll_cci_trace", "gpll_cci_trace" }; -PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", "npll_cs"}; -PNAME(mux_aclk_perihp_p) = { "cpll_aclk_perihp_src", "gpll_aclk_perihp_src" }; +PNAME(mux_cci_trace_p) = { "cpll_cci_trace", + "gpll_cci_trace" }; +PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", + "npll_cs"}; +PNAME(mux_aclk_perihp_p) = { "cpll_aclk_perihp_src", + "gpll_aclk_perihp_src" }; PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" }; PNAME(mux_pll_src_cpll_gpll_ppll_p) = { "cpll", "gpll", "ppll" }; PNAME(mux_pll_src_cpll_gpll_upll_p) = { "cpll", "gpll", "upll" }; PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" }; -PNAME(mux_pll_src_cpll_gpll_npll_ppll_p) = { "cpll", "gpll", "npll", "ppll" }; -PNAME(mux_pll_src_cpll_gpll_npll_24m_p) = { "cpll", "gpll", "npll", "xin24m" }; -PNAME(mux_pll_src_cpll_gpll_npll_usbphy480m_p) = { "cpll", "gpll", "npll", "clk_usbphy_480m" }; -PNAME(mux_pll_src_ppll_cpll_gpll_npll_p) = { "ppll", "cpll", "gpll", "npll", "upll" }; -PNAME(mux_pll_src_cpll_gpll_npll_upll_24m_p) = { "cpll", "gpll", "npll", "upll", "xin24m" }; -PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", "ppll", "upll", "xin24m" }; +PNAME(mux_pll_src_cpll_gpll_npll_ppll_p) = { "cpll", "gpll", "npll", + "ppll" }; +PNAME(mux_pll_src_cpll_gpll_npll_24m_p) = { "cpll", "gpll", "npll", + "xin24m" }; +PNAME(mux_pll_src_cpll_gpll_npll_usbphy480m_p) = { "cpll", "gpll", "npll", + "clk_usbphy_480m" }; +PNAME(mux_pll_src_ppll_cpll_gpll_npll_p) = { "ppll", "cpll", "gpll", + "npll", "upll" }; +PNAME(mux_pll_src_cpll_gpll_npll_upll_24m_p) = { "cpll", "gpll", "npll", + "upll", "xin24m" }; +PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", + "ppll", "upll", "xin24m" }; PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" }; -PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", "npll" }; -PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", "xin24m" }; - -PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", "dclk_vop0_frac" }; -PNAME(mux_dclk_vop1_p) = { "dclk_vop1_div", "dclk_vop1_frac" }; - -PNAME(mux_clk_cif_p) = { "clk_cifout_div", "xin24m" }; - -PNAME(mux_pll_src_24m_usbphy480m_p) = { "xin24m", "clk_usbphy_480m" }; -PNAME(mux_pll_src_24m_pciephy_p) = { "xin24m", "clk_pciephy_ref100m" }; -PNAME(mux_pll_src_24m_32k_cpll_gpll_p) = { "xin24m", "xin32k", "cpll", "gpll" }; -PNAME(mux_pciecore_cru_phy_p) = { "clk_pcie_core_cru", "clk_pcie_core_phy" }; - -PNAME(mux_aclk_emmc_p) = { "cpll_aclk_emmc_src", "gpll_aclk_emmc_src" }; - -PNAME(mux_aclk_perilp0_p) = { "cpll_aclk_perilp0_src", "gpll_aclk_perilp0_src" }; - -PNAME(mux_fclk_cm0s_p) = { "cpll_fclk_cm0s_src", "gpll_fclk_cm0s_src" }; - -PNAME(mux_hclk_perilp1_p) = { "cpll_hclk_perilp1_src", "gpll_hclk_perilp1_src" }; - -PNAME(mux_clk_testout1_p) = { "clk_testout1_pll_src", "xin24m" }; -PNAME(mux_clk_testout2_p) = { "clk_testout2_pll_src", "xin24m" }; - -PNAME(mux_usbphy_480m_p) = { "clk_usbphy0_480m_src", "clk_usbphy1_480m_src" }; -PNAME(mux_aclk_gmac_p) = { "cpll_aclk_gmac_src", "gpll_aclk_gmac_src" }; -PNAME(mux_rmii_p) = { "clk_gmac", "clkin_gmac" }; -PNAME(mux_spdif_p) = { "clk_spdif_div", "clk_spdif_frac", - "clkin_i2s", "xin12m" }; -PNAME(mux_i2s0_p) = { "clk_i2s0_div", "clk_i2s0_frac", - "clkin_i2s", "xin12m" }; -PNAME(mux_i2s1_p) = { "clk_i2s1_div", "clk_i2s1_frac", - "clkin_i2s", "xin12m" }; -PNAME(mux_i2s2_p) = { "clk_i2s2_div", "clk_i2s2_frac", - "clkin_i2s", "xin12m" }; -PNAME(mux_i2sch_p) = { "clk_i2s0", "clk_i2s1", "clk_i2s2" }; -PNAME(mux_i2sout_p) = { "clk_i2sout_src", "xin12m" }; - -PNAME(mux_uart0_p) = { "clk_uart0_div", "clk_uart0_frac", "xin24m" }; -PNAME(mux_uart1_p) = { "clk_uart1_div", "clk_uart1_frac", "xin24m" }; -PNAME(mux_uart2_p) = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; -PNAME(mux_uart3_p) = { "clk_uart3_div", "clk_uart3_frac", "xin24m" }; +PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", + "npll" }; +PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", + "xin24m" }; + +PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", + "dclk_vop0_frac" }; +PNAME(mux_dclk_vop1_p) = { "dclk_vop1_div", + "dclk_vop1_frac" }; + +PNAME(mux_clk_cif_p) = { "clk_cifout_div", "xin24m" }; + +PNAME(mux_pll_src_24m_usbphy480m_p) = { "xin24m", "clk_usbphy_480m" }; +PNAME(mux_pll_src_24m_pciephy_p) = { "xin24m", "clk_pciephy_ref100m" }; +PNAME(mux_pll_src_24m_32k_cpll_gpll_p) = { "xin24m", "xin32k", + "cpll", "gpll" }; +PNAME(mux_pciecore_cru_phy_p) = { "clk_pcie_core_cru", + "clk_pcie_core_phy" }; + +PNAME(mux_aclk_emmc_p) = { "cpll_aclk_emmc_src", + "gpll_aclk_emmc_src" }; + +PNAME(mux_aclk_perilp0_p) = { "cpll_aclk_perilp0_src", + "gpll_aclk_perilp0_src" }; + +PNAME(mux_fclk_cm0s_p) = { "cpll_fclk_cm0s_src", + "gpll_fclk_cm0s_src" }; + +PNAME(mux_hclk_perilp1_p) = { "cpll_hclk_perilp1_src", + "gpll_hclk_perilp1_src" }; + +PNAME(mux_clk_testout1_p) = { "clk_testout1_pll_src", "xin24m" }; +PNAME(mux_clk_testout2_p) = { "clk_testout2_pll_src", "xin24m" }; + +PNAME(mux_usbphy_480m_p) = { "clk_usbphy0_480m_src", + "clk_usbphy1_480m_src" }; +PNAME(mux_aclk_gmac_p) = { "cpll_aclk_gmac_src", + "gpll_aclk_gmac_src" }; +PNAME(mux_rmii_p) = { "clk_gmac", "clkin_gmac" }; +PNAME(mux_spdif_p) = { "clk_spdif_div", "clk_spdif_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2s0_p) = { "clk_i2s0_div", "clk_i2s0_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2s1_p) = { "clk_i2s1_div", "clk_i2s1_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2s2_p) = { "clk_i2s2_div", "clk_i2s2_frac", + "clkin_i2s", "xin12m" }; +PNAME(mux_i2sch_p) = { "clk_i2s0", "clk_i2s1", + "clk_i2s2" }; +PNAME(mux_i2sout_p) = { "clk_i2sout_src", "xin12m" }; + +PNAME(mux_uart0_p) = { "clk_uart0_div", "clk_uart0_frac", "xin24m" }; +PNAME(mux_uart1_p) = { "clk_uart1_div", "clk_uart1_frac", "xin24m" }; +PNAME(mux_uart2_p) = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; +PNAME(mux_uart3_p) = { "clk_uart3_div", "clk_uart3_frac", "xin24m" }; /* PMU CRU parents */ -PNAME(mux_ppll_24m_p) = { "ppll", "xin24m" }; -PNAME(mux_24m_ppll_p) = { "xin24m", "ppll" }; -PNAME(mux_fclk_cm0s_pmu_ppll_p) = { "fclk_cm0s_pmu_ppll_src", "xin24m" }; -PNAME(mux_wifi_pmu_p) = { "clk_wifi_div", "clk_wifi_frac" }; -PNAME(mux_uart4_pmu_p) = { "clk_uart4_div", "clk_uart4_frac", "xin24m" }; -PNAME(mux_clk_testout2_2io_p) = { "clk_testout2", "clk_32k_suspend_pmu" }; +PNAME(mux_ppll_24m_p) = { "ppll", "xin24m" }; +PNAME(mux_24m_ppll_p) = { "xin24m", "ppll" }; +PNAME(mux_fclk_cm0s_pmu_ppll_p) = { "fclk_cm0s_pmu_ppll_src", "xin24m" }; +PNAME(mux_wifi_pmu_p) = { "clk_wifi_div", "clk_wifi_frac" }; +PNAME(mux_uart4_pmu_p) = { "clk_uart4_div", "clk_uart4_frac", + "xin24m" }; +PNAME(mux_clk_testout2_2io_p) = { "clk_testout2", "clk_32k_suspend_pmu" }; static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = { [lpll] = PLL(pll_rk3399, PLL_APLLL, "lpll", mux_pll_p, 0, RK3399_PLL_CON(0), @@ -1530,7 +1553,7 @@ static void __init rk3399_pmu_clk_init(struct device_node *np) ARRAY_SIZE(rk3399_clk_pmu_branches)); rockchip_clk_protect_critical(rk3399_pmucru_critical_clocks, - ARRAY_SIZE(rk3399_pmucru_critical_clocks)); + ARRAY_SIZE(rk3399_pmucru_critical_clocks)); rockchip_register_softrst(np, 2, reg_base + RK3399_PMU_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); -- GitLab From 2b4e6286484c3eeae2c80063c510166c63d7cb85 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 19 Apr 2016 21:17:55 +0200 Subject: [PATCH 3455/9938] clk: rockchip: drop unnecessary header comment The internal clk header did contain a comment indicating that some of the defined registers were shared over multiple clock controller variants. In recent times, it was simply extended all the time and stopped providing any meaningful information, so drop it and it's overlong line. Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 880349f6d3d7..4a355bf1d69a 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -34,7 +34,6 @@ struct clk; #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) -/* register positions shared by RK2928, RK3036, RK3066, RK3188, RK3228, RK3399 */ #define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) -- GitLab From aaa3ca82286d53c5409d2c22204426c9ca419d8c Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 8 Apr 2016 18:26:52 +0300 Subject: [PATCH 3456/9938] intel_th: pci: Add Broxton-M SOC support This adds Intel(R) Trace Hub PCI ID for Broxton-M SOC. Signed-off-by: Alexander Shishkin Reviewed-by: Laurent Fert --- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index bca7a2ac00d6..5e25c7eb31d3 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -75,6 +75,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80), .driver_data = (kernel_ulong_t)0, }, + { + /* Broxton B-step */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e), + .driver_data = (kernel_ulong_t)0, + }, { 0 }, }; -- GitLab From b0fcd8ab7b3c89b5da7fff5224d06ed73e7a33cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 23 Mar 2016 11:19:00 +0100 Subject: [PATCH 3457/9938] mtd: nand: add new enum for storing ECC algorithm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our nand_ecc_modes_t is already a bit abused by value NAND_ECC_SOFT_BCH. This enum should store ECC mode only and putting algorithm details there is a bad idea. It would result in too many values impossible to support in a sane way. To solve this problem let's add a new enum. We'll have to modify all drivers to set it properly but once it's done it'll be possible to drop NAND_ECC_SOFT_BCH. That will result in a cleaner design and more possibilities like setting ECC algorithm for hardware ECC mode. Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- include/linux/mtd/nand.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 56574ba36555..1b673e19667c 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -119,6 +119,12 @@ typedef enum { NAND_ECC_SOFT_BCH, } nand_ecc_modes_t; +enum nand_ecc_algo { + NAND_ECC_UNKNOWN, + NAND_ECC_HAMMING, + NAND_ECC_BCH, +}; + /* * Constants for Hardware ECC */ @@ -458,6 +464,7 @@ struct nand_hw_control { /** * struct nand_ecc_ctrl - Control structure for ECC * @mode: ECC mode + * @algo: ECC algorithm * @steps: number of ECC steps per page * @size: data bytes per ECC step * @bytes: ECC bytes per step @@ -508,6 +515,7 @@ struct nand_hw_control { */ struct nand_ecc_ctrl { nand_ecc_modes_t mode; + enum nand_ecc_algo algo; int steps; int size; int bytes; -- GitLab From dd2dcc004230b9d8fa809102cd326e3ee4bbdb2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 23 Mar 2016 11:19:01 +0100 Subject: [PATCH 3458/9938] of: mtd: prepare helper reading NAND ECC algo from DT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NAND subsystem is being slightly reworked to store ECC details in separated fields. In future we'll want to add support for more DT properties as specifying every possible setup with a single "nand-ecc-mode" is a pretty bad idea. To allow this let's add a helper that will support something like "nand-ecc-algo" in future. Right now we use it for keeping backward compatibility. Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/of/of_mtd.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/of_mtd.h | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c index b7361ed70537..15d056e181d2 100644 --- a/drivers/of/of_mtd.c +++ b/drivers/of/of_mtd.c @@ -49,6 +49,42 @@ int of_get_nand_ecc_mode(struct device_node *np) } EXPORT_SYMBOL_GPL(of_get_nand_ecc_mode); +/** + * of_get_nand_ecc_algo - Get nand ecc algorithm for given device_node + * @np: Pointer to the given device_node + * + * The function gets ecc algorithm and returns its enum value, or errno in error + * case. + */ +int of_get_nand_ecc_algo(struct device_node *np) +{ + const char *pm; + int err; + + /* + * TODO: Read ECC algo OF property and map it to enum nand_ecc_algo. + * It's not implemented yet as currently NAND subsystem ignores + * algorithm explicitly set this way. Once it's handled we should + * document & support new property. + */ + + /* + * For backward compatibility we also read "nand-ecc-mode" checking + * for some obsoleted values that were specifying ECC algorithm. + */ + err = of_property_read_string(np, "nand-ecc-mode", &pm); + if (err < 0) + return err; + + if (!strcasecmp(pm, "soft")) + return NAND_ECC_HAMMING; + else if (!strcasecmp(pm, "soft_bch")) + return NAND_ECC_BCH; + + return -ENODEV; +} +EXPORT_SYMBOL_GPL(of_get_nand_ecc_algo); + /** * of_get_nand_ecc_step_size - Get ECC step size associated to * the required ECC strength (see below). diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h index e266caa36402..0f6aca5c6f2f 100644 --- a/include/linux/of_mtd.h +++ b/include/linux/of_mtd.h @@ -13,6 +13,7 @@ #include int of_get_nand_ecc_mode(struct device_node *np); +int of_get_nand_ecc_algo(struct device_node *np); int of_get_nand_ecc_step_size(struct device_node *np); int of_get_nand_ecc_strength(struct device_node *np); int of_get_nand_bus_width(struct device_node *np); @@ -25,6 +26,11 @@ static inline int of_get_nand_ecc_mode(struct device_node *np) return -ENOSYS; } +static inline int of_get_nand_ecc_algo(struct device_node *np) +{ + return -ENOSYS; +} + static inline int of_get_nand_ecc_step_size(struct device_node *np) { return -ENOSYS; -- GitLab From 79082457d71af879922e15f9dedf85384e84c29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 23 Mar 2016 11:19:02 +0100 Subject: [PATCH 3459/9938] mtd: nand: set ECC algorithm in nand_dt_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use recently added of_get_nand_ecc_algo for that. Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 8d6287ef3926..728543b97dd8 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3954,7 +3954,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, static int nand_dt_init(struct nand_chip *chip) { struct device_node *dn = nand_get_flash_node(chip); - int ecc_mode, ecc_strength, ecc_step; + int ecc_mode, ecc_algo, ecc_strength, ecc_step; if (!dn) return 0; @@ -3966,6 +3966,7 @@ static int nand_dt_init(struct nand_chip *chip) chip->bbt_options |= NAND_BBT_USE_FLASH; ecc_mode = of_get_nand_ecc_mode(dn); + ecc_algo = of_get_nand_ecc_algo(dn); ecc_strength = of_get_nand_ecc_strength(dn); ecc_step = of_get_nand_ecc_step_size(dn); @@ -3978,6 +3979,9 @@ static int nand_dt_init(struct nand_chip *chip) if (ecc_mode >= 0) chip->ecc.mode = ecc_mode; + if (ecc_algo >= 0) + chip->ecc.algo = ecc_algo; + if (ecc_strength >= 0) chip->ecc.strength = ecc_strength; -- GitLab From 8ae6bcd1dcea249591b4165bd7f795c4868bc531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 23 Mar 2016 11:19:03 +0100 Subject: [PATCH 3460/9938] mtd: nand: nandsim: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This follows recent work on switching to enum nand_ecc_algo and deprecating NAND_ECC_SOFT_BCH. Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nandsim.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 1fd519503bb1..6ff1d8d31ac2 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -2261,6 +2261,7 @@ static int __init ns_init_module(void) chip->read_buf = ns_nand_read_buf; chip->read_word = ns_nand_read_word; chip->ecc.mode = NAND_ECC_SOFT; + chip->ecc.algo = NAND_ECC_HAMMING; /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ /* and 'badblocks' parameters to work */ chip->options |= NAND_SKIP_BBTSCAN; @@ -2339,6 +2340,7 @@ static int __init ns_init_module(void) goto error; } chip->ecc.mode = NAND_ECC_SOFT_BCH; + chip->ecc.algo = NAND_ECC_BCH; chip->ecc.size = 512; chip->ecc.strength = bch; chip->ecc.bytes = eccbytes; -- GitLab From ff6ee101584c17c4f30ca48d75e2910c49d0b0ff Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 1 Mar 2016 14:11:52 +0100 Subject: [PATCH 3461/9938] mtd: nand: atmel: correct bitflips in erased pages for pre-sama5d4 SoCs New atmel SoCs are able to fix bitflips in erased pages, but old ones are still impacted by this problem. Use nand_check_erased_ecc_chunk() to handle this case. Signed-off-by: Boris Brezillon Reported-by: Herve Codina Reviewed-by: Herve Codina Tested-by: Herve Codina --- drivers/mtd/nand/atmel_nand.c | 37 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 20cbaabb2959..0b5da7271440 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -863,17 +863,6 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, uint8_t *buf_pos; int max_bitflips = 0; - /* If can correct bitfilps from erased page, do the normal check */ - if (host->caps->pmecc_correct_erase_page) - goto normal_check; - - for (i = 0; i < nand_chip->ecc.total; i++) - if (ecc[i] != 0xff) - goto normal_check; - /* Erased page, return OK */ - return 0; - -normal_check: for (i = 0; i < nand_chip->ecc.steps; i++) { err_nbr = 0; if (pmecc_stat & 0x1) { @@ -884,16 +873,30 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, pmecc_get_sigma(mtd); err_nbr = pmecc_err_location(mtd); - if (err_nbr == -1) { + if (err_nbr >= 0) { + pmecc_correct_data(mtd, buf_pos, ecc, i, + nand_chip->ecc.bytes, + err_nbr); + } else if (!host->caps->pmecc_correct_erase_page) { + u8 *ecc_pos = ecc + (i * nand_chip->ecc.bytes); + + /* Try to detect erased pages */ + err_nbr = nand_check_erased_ecc_chunk(buf_pos, + host->pmecc_sector_size, + ecc_pos, + nand_chip->ecc.bytes, + NULL, 0, + nand_chip->ecc.strength); + } + + if (err_nbr < 0) { dev_err(host->dev, "PMECC: Too many errors\n"); mtd->ecc_stats.failed++; return -EIO; - } else { - pmecc_correct_data(mtd, buf_pos, ecc, i, - nand_chip->ecc.bytes, err_nbr); - mtd->ecc_stats.corrected += err_nbr; - max_bitflips = max_t(int, max_bitflips, err_nbr); } + + mtd->ecc_stats.corrected += err_nbr; + max_bitflips = max_t(int, max_bitflips, err_nbr); } pmecc_stat >>= 1; } -- GitLab From ce8716e97149d15379603890c4c7a2acfcf4a7ee Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Wed, 23 Mar 2016 21:53:27 -0400 Subject: [PATCH 3462/9938] mtd: nand: jz4780: fixup, device structure assigned at probe bch->dev is already assigned to &pdev->dev in the probe function. Remove the duplicate assignment done in jz4780_bch_get(). Signed-off-by: Jorge Ramirez-Ortiz Signed-off-by: Boris Brezillon Acked-by: Acked-by: Harvey Hunt --- drivers/mtd/nand/jz4780_bch.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/jz4780_bch.c b/drivers/mtd/nand/jz4780_bch.c index 755499c6650e..d74f4ba4a6f4 100644 --- a/drivers/mtd/nand/jz4780_bch.c +++ b/drivers/mtd/nand/jz4780_bch.c @@ -287,7 +287,6 @@ static struct jz4780_bch *jz4780_bch_get(struct device_node *np) bch = platform_get_drvdata(pdev); clk_prepare_enable(bch->clk); - bch->dev = &pdev->dev; return bch; } -- GitLab From 2d472aba15ff169a30dc3661f837d8535af9b9ee Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 1 Apr 2016 14:26:35 +0200 Subject: [PATCH 3463/9938] mtd: nand: document the NAND controller/NAND chip DT representation Standardize the NAND controller/NAND chip DT representation. Now, all new NAND controller drivers should comply with this representation, even if they are only supporting a single NAND chip. Existing drivers can keep support for the old representation (where only the NAND chip was described), but are encouraged to also support the new one. Signed-off-by: Boris Brezillon Acked-by: Brian Norris Acked-by: Rob Herring --- .../devicetree/bindings/mtd/nand.txt | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/nand.txt b/Documentation/devicetree/bindings/mtd/nand.txt index b53f92e252d4..a17662b1dfcb 100644 --- a/Documentation/devicetree/bindings/mtd/nand.txt +++ b/Documentation/devicetree/bindings/mtd/nand.txt @@ -1,4 +1,23 @@ -* MTD generic binding +* NAND chip and NAND controller generic binding + +NAND controller/NAND chip representation: + +The NAND controller should be represented with its own DT node, and all +NAND chips attached to this controller should be defined as children nodes +of the NAND controller. This representation should be enforced even for +simple controllers supporting only one chip. + +Mandatory NAND controller properties: +- #address-cells: depends on your controller. Should at least be 1 to + encode the CS line id. +- #size-cells: depends on your controller. Put zero unless you need a + mapping between CS lines and dedicated memory regions + +Optional NAND controller properties +- ranges: only needed if you need to define a mapping between CS lines and + memory regions + +Optional NAND chip properties: - nand-ecc-mode : String, operation mode of the NAND ecc mode. Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", @@ -19,3 +38,19 @@ errors per {size} bytes". The interpretation of these parameters is implementation-defined, so not all implementations must support all possible combinations. However, implementations are encouraged to further specify the value(s) they support. + +Example: + + nand-controller { + #address-cells = <1>; + #size-cells = <0>; + + /* controller specific properties */ + + nand@0 { + reg = <0>; + nand-ecc-mode = "soft_bch"; + + /* controller specific properties */ + }; + }; -- GitLab From 269ecf03a5b32b0d1de1f60a4b86b75c0521053f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 10 Mar 2016 15:34:16 -0800 Subject: [PATCH 3464/9938] mtd: brcmnand: Add support for v6.2 controllers Document and match the brcm,brcmnand-v6.2 compatible string, the controller has a register layout identical to the v6.0 version and supports prefetch. Update the command shift logic to account for v6.2 controller which are the first ones to use a shift of 0 (6.1 used a shift of 24). Signed-off-by: Kamal Dasu Signed-off-by: Florian Fainelli Acked-by: Rob Herring Acked-by: Brian Norris Signed-off-by: Boris Brezillon --- Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt | 1 + drivers/mtd/nand/brcmnand/brcmnand.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt index c2546ced9c02..deb24cbdda82 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt @@ -24,6 +24,7 @@ Required properties: brcm,brcmnand-v5.0 brcm,brcmnand-v6.0 brcm,brcmnand-v6.1 + brcm,brcmnand-v6.2 brcm,brcmnand-v7.0 brcm,brcmnand-v7.1 brcm,brcmnand diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index e0528397306a..0b7a698cc233 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -601,7 +601,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl) { - if (ctrl->nand_version < 0x0700) + if (ctrl->nand_version < 0x0602) return 24; return 0; } @@ -2115,6 +2115,7 @@ static const struct of_device_id brcmnand_of_match[] = { { .compatible = "brcm,brcmnand-v5.0" }, { .compatible = "brcm,brcmnand-v6.0" }, { .compatible = "brcm,brcmnand-v6.1" }, + { .compatible = "brcm,brcmnand-v6.2" }, { .compatible = "brcm,brcmnand-v7.0" }, { .compatible = "brcm,brcmnand-v7.1" }, {}, -- GitLab From 2cd395d13a104cd96ddae5c5612871dc18553cca Mon Sep 17 00:00:00 2001 From: Han Xu Date: Mon, 4 Apr 2016 15:41:29 -0500 Subject: [PATCH 3465/9938] mtd: gpmi: fix raw_buffer pointer double free issue fix the raw_buffer pointer double free issue found by coverify. CID 18344 (#2 of 2): Double free (USE_AFTER_FREE) 3. double_free: Calling gpmi_alloc_dma_buffer frees pointer this->raw_buffer which has already been freed Signed-off-by: Han Xu Reviewed-by: Richard Weinberger Signed-off-by: Boris Brezillon --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 8122c699ccf2..dcb60b0fe5eb 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -797,6 +797,7 @@ static void gpmi_free_dma_buffer(struct gpmi_nand_data *this) this->cmd_buffer = NULL; this->data_buffer_dma = NULL; + this->raw_buffer = NULL; this->page_buffer_virt = NULL; this->page_buffer_size = 0; } -- GitLab From 11eaf6df1cce3c5e9f51b422aaedc42dc4aa1d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Fri, 1 Apr 2016 18:29:24 -0300 Subject: [PATCH 3466/9938] mtd: nand: Remove BUG() abuse in nand_scan_tail There's no reason to BUG() when parameters are being validated. Drivers can get things wrong, and it's much nicer to just throw a noisy warn and fail gracefully, than calling BUG() and throwing the whole system down the drain. Signed-off-by: Ezequiel Garcia Reviewed-by: Richard Weinberger Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 52 +++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 728543b97dd8..0f0c5b190316 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4107,10 +4107,12 @@ int nand_scan_tail(struct mtd_info *mtd) struct nand_chip *chip = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_buffers *nbuf; + int ret; /* New bad blocks should be marked in OOB, flash-based BBT, or both */ - BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && - !(chip->bbt_options & NAND_BBT_USE_FLASH)); + if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && + !(chip->bbt_options & NAND_BBT_USE_FLASH))) + return -EINVAL; if (!(chip->options & NAND_OWN_BUFFERS)) { nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize @@ -4148,9 +4150,10 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->layout = &nand_oob_128; break; default: - pr_warn("No oob scheme defined for oobsize %d\n", - mtd->oobsize); - BUG(); + WARN(1, "No oob scheme defined for oobsize %d\n", + mtd->oobsize); + ret = -EINVAL; + goto err_free; } } @@ -4166,8 +4169,9 @@ int nand_scan_tail(struct mtd_info *mtd) case NAND_ECC_HW_OOB_FIRST: /* Similar to NAND_ECC_HW, but a separate read_page handle */ if (!ecc->calculate || !ecc->correct || !ecc->hwctl) { - pr_warn("No ECC functions supplied; hardware ECC not possible\n"); - BUG(); + WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); + ret = -EINVAL; + goto err_free; } if (!ecc->read_page) ecc->read_page = nand_read_page_hwecc_oob_first; @@ -4197,8 +4201,9 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->read_page == nand_read_page_hwecc || !ecc->write_page || ecc->write_page == nand_write_page_hwecc)) { - pr_warn("No ECC functions supplied; hardware ECC not possible\n"); - BUG(); + WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); + ret = -EINVAL; + goto err_free; } /* Use standard syndrome read/write page function? */ if (!ecc->read_page) @@ -4216,8 +4221,9 @@ int nand_scan_tail(struct mtd_info *mtd) if (mtd->writesize >= ecc->size) { if (!ecc->strength) { - pr_warn("Driver must set ecc.strength when using hardware ECC\n"); - BUG(); + WARN(1, "Driver must set ecc.strength when using hardware ECC\n"); + ret = -EINVAL; + goto err_free; } break; } @@ -4243,8 +4249,9 @@ int nand_scan_tail(struct mtd_info *mtd) case NAND_ECC_SOFT_BCH: if (!mtd_nand_has_bch()) { - pr_warn("CONFIG_MTD_NAND_ECC_BCH not enabled\n"); - BUG(); + WARN(1, "CONFIG_MTD_NAND_ECC_BCH not enabled\n"); + ret = -EINVAL; + goto err_free; } ecc->calculate = nand_bch_calculate_ecc; ecc->correct = nand_bch_correct_data; @@ -4269,8 +4276,9 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->bytes = 0; ecc->priv = nand_bch_init(mtd); if (!ecc->priv) { - pr_warn("BCH ECC initialization failed!\n"); - BUG(); + WARN(1, "BCH ECC initialization failed!\n"); + ret = -EINVAL; + goto err_free; } break; @@ -4288,8 +4296,9 @@ int nand_scan_tail(struct mtd_info *mtd) break; default: - pr_warn("Invalid NAND_ECC_MODE %d\n", ecc->mode); - BUG(); + WARN(1, "Invalid NAND_ECC_MODE %d\n", ecc->mode); + ret = -EINVAL; + goto err_free; } /* For many systems, the standard OOB write also works for raw */ @@ -4319,8 +4328,9 @@ int nand_scan_tail(struct mtd_info *mtd) */ ecc->steps = mtd->writesize / ecc->size; if (ecc->steps * ecc->size != mtd->writesize) { - pr_warn("Invalid ECC parameters\n"); - BUG(); + WARN(1, "Invalid ECC parameters\n"); + ret = -EINVAL; + goto err_free; } ecc->total = ecc->steps * ecc->bytes; @@ -4398,6 +4408,10 @@ int nand_scan_tail(struct mtd_info *mtd) /* Build bad block table */ return chip->scan_bbt(mtd); +err_free: + if (!(chip->options & NAND_OWN_BUFFERS)) + kfree(chip->buffers); + return ret; } EXPORT_SYMBOL(nand_scan_tail); -- GitLab From 7a654172161c8c9c7d59cbd0054d9e63c7411219 Mon Sep 17 00:00:00 2001 From: Raghav Dogra Date: Wed, 17 Feb 2016 16:54:18 +0530 Subject: [PATCH 3467/9938] mtd/ifc: Add support for IFC controller version 2.0 The new IFC controller version 2.0 has a different memory map page. Upto IFC 1.4 PAGE size is 4 KB and from IFC2.0 PAGE size is 64KB. This patch segregates the IFC global and runtime registers to appropriate PAGE sizes. Signed-off-by: Jaiprakash Singh Signed-off-by: Raghav Dogra Acked-by: Li Yang Signed-off-by: Raghav Dogra Acked-by: Scott Wood Acked-by: Brian Norris Signed-off-by: Boris Brezillon --- drivers/memory/fsl_ifc.c | 36 ++++++++--------- drivers/mtd/nand/fsl_ifc_nand.c | 72 ++++++++++++++++++--------------- include/linux/fsl_ifc.h | 45 ++++++++++++++------- 3 files changed, 87 insertions(+), 66 deletions(-) diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c index 2a691da8c1c7..904b4af5f142 100644 --- a/drivers/memory/fsl_ifc.c +++ b/drivers/memory/fsl_ifc.c @@ -59,11 +59,11 @@ int fsl_ifc_find(phys_addr_t addr_base) { int i = 0; - if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) + if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->gregs) return -ENODEV; for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) { - u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); + u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->gregs->cspr_cs[i].cspr); if (cspr & CSPR_V && (cspr & CSPR_BA) == convert_ifc_address(addr_base)) return i; @@ -75,7 +75,7 @@ EXPORT_SYMBOL(fsl_ifc_find); static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl) { - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_global __iomem *ifc = ctrl->gregs; /* * Clear all the common status and event registers @@ -104,7 +104,7 @@ static int fsl_ifc_ctrl_remove(struct platform_device *dev) irq_dispose_mapping(ctrl->nand_irq); irq_dispose_mapping(ctrl->irq); - iounmap(ctrl->regs); + iounmap(ctrl->gregs); dev_set_drvdata(&dev->dev, NULL); kfree(ctrl); @@ -122,7 +122,7 @@ static DEFINE_SPINLOCK(nand_irq_lock); static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl) { - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; unsigned long flags; u32 stat; @@ -157,7 +157,7 @@ static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data) static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data) { struct fsl_ifc_ctrl *ctrl = data; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_global __iomem *ifc = ctrl->gregs; u32 err_axiid, err_srcid, status, cs_err, err_addr; irqreturn_t ret = IRQ_NONE; @@ -215,6 +215,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) { int ret = 0; int version, banks; + void __iomem *addr; dev_info(&dev->dev, "Freescale Integrated Flash Controller\n"); @@ -225,22 +226,13 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev); /* IOMAP the entire IFC region */ - fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0); - if (!fsl_ifc_ctrl_dev->regs) { + fsl_ifc_ctrl_dev->gregs = of_iomap(dev->dev.of_node, 0); + if (!fsl_ifc_ctrl_dev->gregs) { dev_err(&dev->dev, "failed to get memory region\n"); ret = -ENODEV; goto err; } - version = ifc_in32(&fsl_ifc_ctrl_dev->regs->ifc_rev) & - FSL_IFC_VERSION_MASK; - banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; - dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", - version >> 24, (version >> 16) & 0xf, banks); - - fsl_ifc_ctrl_dev->version = version; - fsl_ifc_ctrl_dev->banks = banks; - if (of_property_read_bool(dev->dev.of_node, "little-endian")) { fsl_ifc_ctrl_dev->little_endian = true; dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n"); @@ -249,8 +241,9 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n"); } - version = ioread32be(&fsl_ifc_ctrl_dev->regs->ifc_rev) & + version = ifc_in32(&fsl_ifc_ctrl_dev->gregs->ifc_rev) & FSL_IFC_VERSION_MASK; + banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", version >> 24, (version >> 16) & 0xf, banks); @@ -258,6 +251,13 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) fsl_ifc_ctrl_dev->version = version; fsl_ifc_ctrl_dev->banks = banks; + addr = fsl_ifc_ctrl_dev->gregs; + if (version >= FSL_IFC_VERSION_2_0_0) + addr += PGOFFSET_64K; + else + addr += PGOFFSET_4K; + fsl_ifc_ctrl_dev->rregs = addr; + /* get the Controller level irq */ fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); if (fsl_ifc_ctrl_dev->irq == 0) { diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 43f5a3a4873f..f8a016f038cd 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -232,7 +232,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; int buf_num; ifc_nand_ctrl->page = page_addr; @@ -295,7 +295,7 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; u32 eccstat[4]; int i; @@ -371,7 +371,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip, { struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ if (mtd->writesize > 512) { @@ -411,7 +411,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; /* clear the read buffer */ ifc_nand_ctrl->read_bytes = 0; @@ -723,7 +723,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) { struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; u32 nand_fsr; /* Use READ_STATUS command, but wait for the device to be ready */ @@ -825,39 +825,42 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) { struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs; + struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs; uint32_t csor = 0, csor_8k = 0, csor_ext = 0; uint32_t cs = priv->bank; /* Save CSOR and CSOR_ext */ - csor = ifc_in32(&ifc->csor_cs[cs].csor); - csor_ext = ifc_in32(&ifc->csor_cs[cs].csor_ext); + csor = ifc_in32(&ifc_global->csor_cs[cs].csor); + csor_ext = ifc_in32(&ifc_global->csor_cs[cs].csor_ext); /* chage PageSize 8K and SpareSize 1K*/ csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000; - ifc_out32(csor_8k, &ifc->csor_cs[cs].csor); - ifc_out32(0x0000400, &ifc->csor_cs[cs].csor_ext); + ifc_out32(csor_8k, &ifc_global->csor_cs[cs].csor); + ifc_out32(0x0000400, &ifc_global->csor_cs[cs].csor_ext); /* READID */ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), - &ifc->ifc_nand.nand_fir0); + (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), + &ifc_runtime->ifc_nand.nand_fir0); ifc_out32(NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT, - &ifc->ifc_nand.nand_fcr0); - ifc_out32(0x0, &ifc->ifc_nand.row3); + &ifc_runtime->ifc_nand.nand_fcr0); + ifc_out32(0x0, &ifc_runtime->ifc_nand.row3); - ifc_out32(0x0, &ifc->ifc_nand.nand_fbcr); + ifc_out32(0x0, &ifc_runtime->ifc_nand.nand_fbcr); /* Program ROW0/COL0 */ - ifc_out32(0x0, &ifc->ifc_nand.row0); - ifc_out32(0x0, &ifc->ifc_nand.col0); + ifc_out32(0x0, &ifc_runtime->ifc_nand.row0); + ifc_out32(0x0, &ifc_runtime->ifc_nand.col0); /* set the chip select for NAND Transaction */ - ifc_out32(cs << IFC_NAND_CSEL_SHIFT, &ifc->ifc_nand.nand_csel); + ifc_out32(cs << IFC_NAND_CSEL_SHIFT, + &ifc_runtime->ifc_nand.nand_csel); /* start read seq */ - ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, &ifc->ifc_nand.nandseq_strt); + ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, + &ifc_runtime->ifc_nand.nandseq_strt); /* wait for command complete flag or timeout */ wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, @@ -867,14 +870,15 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n"); /* Restore CSOR and CSOR_ext */ - ifc_out32(csor, &ifc->csor_cs[cs].csor); - ifc_out32(csor_ext, &ifc->csor_cs[cs].csor_ext); + ifc_out32(csor, &ifc_global->csor_cs[cs].csor); + ifc_out32(csor_ext, &ifc_global->csor_cs[cs].csor_ext); } static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) { struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_regs __iomem *ifc = ctrl->regs; + struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs; + struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs; struct nand_chip *chip = &priv->chip; struct mtd_info *mtd = nand_to_mtd(&priv->chip); struct nand_ecclayout *layout; @@ -886,7 +890,8 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) /* fill in nand_chip structure */ /* set up function call table */ - if ((ifc_in32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16) + if ((ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr)) + & CSPR_PORT_SIZE_16) chip->read_byte = fsl_ifc_read_byte16; else chip->read_byte = fsl_ifc_read_byte; @@ -900,13 +905,14 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) chip->bbt_td = &bbt_main_descr; chip->bbt_md = &bbt_mirror_descr; - ifc_out32(0x0, &ifc->ifc_nand.ncfgr); + ifc_out32(0x0, &ifc_runtime->ifc_nand.ncfgr); /* set up nand options */ chip->bbt_options = NAND_BBT_USE_FLASH; chip->options = NAND_NO_SUBPAGE_WRITE; - if (ifc_in32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { + if (ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr) + & CSPR_PORT_SIZE_16) { chip->read_byte = fsl_ifc_read_byte16; chip->options |= NAND_BUSWIDTH_16; } else { @@ -919,7 +925,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) chip->ecc.read_page = fsl_ifc_read_page; chip->ecc.write_page = fsl_ifc_write_page; - csor = ifc_in32(&ifc->csor_cs[priv->bank].csor); + csor = ifc_in32(&ifc_global->csor_cs[priv->bank].csor); /* Hardware generates ECC per 512 Bytes */ chip->ecc.size = 512; @@ -1007,10 +1013,10 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) return 0; } -static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank, +static int match_bank(struct fsl_ifc_global __iomem *ifc_global, int bank, phys_addr_t addr) { - u32 cspr = ifc_in32(&ifc->cspr_cs[bank].cspr); + u32 cspr = ifc_in32(&ifc_global->cspr_cs[bank].cspr); if (!(cspr & CSPR_V)) return 0; @@ -1024,7 +1030,7 @@ static DEFINE_MUTEX(fsl_ifc_nand_mutex); static int fsl_ifc_nand_probe(struct platform_device *dev) { - struct fsl_ifc_regs __iomem *ifc; + struct fsl_ifc_runtime __iomem *ifc; struct fsl_ifc_mtd *priv; struct resource res; static const char *part_probe_types[] @@ -1034,9 +1040,9 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) struct device_node *node = dev->dev.of_node; struct mtd_info *mtd; - if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) + if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->rregs) return -ENODEV; - ifc = fsl_ifc_ctrl_dev->regs; + ifc = fsl_ifc_ctrl_dev->rregs; /* get, allocate and map the memory resource */ ret = of_address_to_resource(node, 0, &res); @@ -1047,7 +1053,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) /* find which chip select it is connected to */ for (bank = 0; bank < fsl_ifc_ctrl_dev->banks; bank++) { - if (match_bank(ifc, bank, res.start)) + if (match_bank(fsl_ifc_ctrl_dev->gregs, bank, res.start)) break; } diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h index 0023088b253b..3f9778cbc79d 100644 --- a/include/linux/fsl_ifc.h +++ b/include/linux/fsl_ifc.h @@ -39,6 +39,10 @@ #define FSL_IFC_VERSION_MASK 0x0F0F0000 #define FSL_IFC_VERSION_1_0_0 0x01000000 #define FSL_IFC_VERSION_1_1_0 0x01010000 +#define FSL_IFC_VERSION_2_0_0 0x02000000 + +#define PGOFFSET_64K (64*1024) +#define PGOFFSET_4K (4*1024) /* * CSPR - Chip Select Property Register @@ -723,20 +727,26 @@ struct fsl_ifc_nand { __be32 nand_evter_en; u32 res17[0x2]; __be32 nand_evter_intr_en; - u32 res18[0x2]; + __be32 nand_vol_addr_stat; + u32 res18; __be32 nand_erattr0; __be32 nand_erattr1; u32 res19[0x10]; __be32 nand_fsr; - u32 res20; - __be32 nand_eccstat[4]; - u32 res21[0x20]; + u32 res20[0x3]; + __be32 nand_eccstat[6]; + u32 res21[0x1c]; __be32 nanndcr; u32 res22[0x2]; __be32 nand_autoboot_trgr; u32 res23; __be32 nand_mdr; - u32 res24[0x5C]; + u32 res24[0x1C]; + __be32 nand_dll_lowcfg0; + __be32 nand_dll_lowcfg1; + u32 res25; + __be32 nand_dll_lowstat; + u32 res26[0x3c]; }; /* @@ -771,13 +781,12 @@ struct fsl_ifc_gpcm { __be32 gpcm_erattr1; __be32 gpcm_erattr2; __be32 gpcm_stat; - u32 res4[0x1F3]; }; /* * IFC Controller Registers */ -struct fsl_ifc_regs { +struct fsl_ifc_global { __be32 ifc_rev; u32 res1[0x2]; struct { @@ -803,21 +812,26 @@ struct fsl_ifc_regs { } ftim_cs[FSL_IFC_BANK_COUNT]; u32 res9[0x30]; __be32 rb_stat; - u32 res10[0x2]; + __be32 rb_map; + __be32 wb_map; __be32 ifc_gcr; - u32 res11[0x2]; + u32 res10[0x2]; __be32 cm_evter_stat; - u32 res12[0x2]; + u32 res11[0x2]; __be32 cm_evter_en; - u32 res13[0x2]; + u32 res12[0x2]; __be32 cm_evter_intr_en; - u32 res14[0x2]; + u32 res13[0x2]; __be32 cm_erattr0; __be32 cm_erattr1; - u32 res15[0x2]; + u32 res14[0x2]; __be32 ifc_ccr; __be32 ifc_csr; - u32 res16[0x2EB]; + __be32 ddr_ccr_low; +}; + + +struct fsl_ifc_runtime { struct fsl_ifc_nand ifc_nand; struct fsl_ifc_nor ifc_nor; struct fsl_ifc_gpcm ifc_gpcm; @@ -831,7 +845,8 @@ extern int fsl_ifc_find(phys_addr_t addr_base); struct fsl_ifc_ctrl { /* device info */ struct device *dev; - struct fsl_ifc_regs __iomem *regs; + struct fsl_ifc_global __iomem *gregs; + struct fsl_ifc_runtime __iomem *rregs; int irq; int nand_irq; spinlock_t lock; -- GitLab From 03a97550941d17c7d5b621afde5945bbc0da6546 Mon Sep 17 00:00:00 2001 From: Zhaoxiu Zeng Date: Tue, 12 Apr 2016 15:30:35 +0800 Subject: [PATCH 3468/9938] mtd: nand: s3c2410: fix bug in s3c2410_nand_correct_data() If there is only one bit difference in the ECC, the function should return 1. The result of "diff0 & ~(1< Signed-off-by: Boris Brezillon --- drivers/mtd/nand/s3c2410.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 9c9397b54b2c..86ffb73e1085 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -542,7 +542,8 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, diff0 |= (diff1 << 8); diff0 |= (diff2 << 16); - if ((diff0 & ~(1< Date: Fri, 1 Apr 2016 14:54:21 +0200 Subject: [PATCH 3469/9938] mtd: nand: remove unneeded of_mtd.h inclusions Some drivers are including linux/of_mtd.h even if they don't use any of the of_get_nand_xxx() helpers. Signed-off-by: Boris Brezillon Acked-by: Harvey Hunt --- drivers/mtd/nand/jz4780_nand.c | 1 - drivers/mtd/nand/lpc32xx_mlc.c | 1 - drivers/mtd/nand/qcom_nandc.c | 1 - drivers/mtd/nand/sunxi_nand.c | 1 - drivers/mtd/nand/vf610_nfc.c | 1 - 5 files changed, 5 deletions(-) diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/jz4780_nand.c index e1c016c9d32d..23a1999ae839 100644 --- a/drivers/mtd/nand/jz4780_nand.c +++ b/drivers/mtd/nand/jz4780_nand.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index d8c3e7afcc0b..8e439787b04e 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index f550a57e6eea..f3de983475db 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -21,7 +21,6 @@ #include #include #include -#include #include /* NANDc reg offsets */ diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 1c03eee44f3d..3a97093662ea 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 293feb19b0b1..a7f2756c49ee 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include -- GitLab From f679888f29fe5c4a4c44459f2c1fc62b72188773 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 19 Apr 2016 20:29:58 +0200 Subject: [PATCH 3470/9938] mtd: nand: omap2: rely on generic DT parsing done in nand_scan_ident() The core now takes care of parsing generic DT properties in nand_scan_ident() when nand_set_flash_node() has been called. Rely on this initialization instead of calling of_get_nand_xxx() manually. Signed-off-by: Boris Brezillon Acked-by: Roger Quadros Tested-by: Franklin S Cooper Jr. --- drivers/memory/omap-gpmc.c | 4 ++-- drivers/mtd/nand/omap2.c | 18 +++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 33d69b1e4c31..af4884ba6b7c 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -2066,7 +2065,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, if (of_device_is_compatible(child, "ti,omap2-nand")) { /* NAND specific setup */ - val = of_get_nand_bus_width(child); + val = 8; + of_property_read_u32(child, "nand-bus-width", &val); switch (val) { case 8: gpmc_s.device_width = GPMC_DEVWIDTH_8BIT; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index e0b2b2f0fbde..c59bc85009d7 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -1701,7 +1700,7 @@ static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info) for (i = 0; i < ARRAY_SIZE(nand_xfer_types); i++) { if (!strcasecmp(s, nand_xfer_types[i])) { info->xfer_type = i; - goto next; + return 0; } } @@ -1709,12 +1708,6 @@ static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info) return -EINVAL; } -next: - of_get_nand_on_flash_bbt(child); - - if (of_get_nand_bus_width(child) == 16) - info->devsize = NAND_BUSWIDTH_16; - return 0; } @@ -1810,9 +1803,7 @@ static int omap_nand_probe(struct platform_device *pdev) } if (info->flash_bbt) - nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; - else - nand_chip->options |= NAND_SKIP_BBTSCAN; + nand_chip->bbt_options |= NAND_BBT_USE_FLASH; /* scan NAND device connected to chip controller */ nand_chip->options |= info->devsize & NAND_BUSWIDTH_16; @@ -1823,6 +1814,11 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } + if (nand_chip->bbt_options & NAND_BBT_USE_FLASH) + nand_chip->bbt_options |= NAND_BBT_NO_OOB; + else + nand_chip->options |= NAND_SKIP_BBTSCAN; + /* re-populate low-level callbacks based on xfer modes */ switch (info->xfer_type) { case NAND_OMAP_PREFETCH_POLLED: -- GitLab From 541e3c8912fe4257ba0b71908ea8fbf79143f510 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 1 Apr 2016 14:54:24 +0200 Subject: [PATCH 3471/9938] mtd: nand: brcm: rely on generic DT parsing done in nand_scan_ident() The core now takes care of parsing generic DT properties in nand_scan_ident() when nand_set_flash_node() has been called. Rely on this initialization instead of calling of_get_nand_xxx() manually. Signed-off-by: Boris Brezillon Acked-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 0b7a698cc233..e5f281f148dc 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -2001,8 +2000,8 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) */ chip->options |= NAND_USE_BOUNCE_BUFFER; - if (of_get_nand_on_flash_bbt(dn)) - chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; + if (chip->bbt_options & NAND_BBT_USE_FLASH) + chip->bbt_options |= NAND_BBT_NO_OOB; if (brcmnand_setup_dev(host)) return -ENXIO; -- GitLab From e58dd3c33d3046c3ad3c849cb95365b45b9ecb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:44 +0200 Subject: [PATCH 3472/9938] mtd: nand: ams-delta: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/ams-delta.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 68b58c85789c..78e12cc8bac2 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -224,6 +224,7 @@ static int ams_delta_init(struct platform_device *pdev) /* 25 us command delay time */ this->chip_delay = 30; this->ecc.mode = NAND_ECC_SOFT; + this->ecc.algo = NAND_ECC_HAMMING; platform_set_drvdata(pdev, io_base); -- GitLab From 050658c8f9bd8d7b2addf40f6a5b340d5d4ec21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:45 +0200 Subject: [PATCH 3473/9938] mtd: nand: gpio: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/gpio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index ded658fc7d73..6317f6836022 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -273,6 +273,7 @@ static int gpio_nand_probe(struct platform_device *pdev) nand_set_flash_node(chip, pdev->dev.of_node); chip->IO_ADDR_W = chip->IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; + chip->ecc.algo = NAND_ECC_HAMMING; chip->options = gpiomtd->plat.options; chip->chip_delay = gpiomtd->plat.chip_delay; chip->cmd_ctrl = gpio_nand_cmd_ctrl; -- GitLab From c1c7040e072caac6445a1e298bd1fc5e8da0a5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:46 +0200 Subject: [PATCH 3474/9938] mtd: nand: mxc: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/mxc_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 854c832597aa..57b1b74c8fa0 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1585,6 +1585,7 @@ static int mxcnd_probe(struct platform_device *pdev) this->ecc.mode = NAND_ECC_HW; } else { this->ecc.mode = NAND_ECC_SOFT; + this->ecc.algo = NAND_ECC_HAMMING; } /* NAND bus width determines access functions used by upper layer */ -- GitLab From 37afb2034f17c5f17423bfe5a4fc100d6803b554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:47 +0200 Subject: [PATCH 3475/9938] mtd: nand: nuc900: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nuc900_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index dbc5b571c2bb..8f64011d32ef 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -261,6 +261,7 @@ static int nuc900_nand_probe(struct platform_device *pdev) chip->chip_delay = 50; chip->options = 0; chip->ecc.mode = NAND_ECC_SOFT; + chip->ecc.algo = NAND_ECC_HAMMING; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nuc900_nand->reg = devm_ioremap_resource(&pdev->dev, res); -- GitLab From ac7efcbe0e3d64565f5b086d231589e3637e9b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:48 +0200 Subject: [PATCH 3476/9938] mtd: nand: orion: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/orion_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index d4614bfbfed6..40a7c4a2cf0d 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -130,6 +130,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) nc->cmd_ctrl = orion_nand_cmd_ctrl; nc->read_buf = orion_nand_read_buf; nc->ecc.mode = NAND_ECC_SOFT; + nc->ecc.algo = NAND_ECC_HAMMING; if (board->chip_delay) nc->chip_delay = board->chip_delay; -- GitLab From a9670a9c7ff9488d66d6fd7593415bb978017509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:49 +0200 Subject: [PATCH 3477/9938] mtd: nand: pasemi: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/pasemi_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 3ab53ca53cca..63fcb8c63877 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -151,6 +151,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) chip->write_buf = pasemi_write_buf; chip->chip_delay = 0; chip->ecc.mode = NAND_ECC_SOFT; + chip->ecc.algo = NAND_ECC_HAMMING; /* Enable the following for a flash based bad block table */ chip->bbt_options = NAND_BBT_USE_FLASH; -- GitLab From 41ccb49e9123e268e8f84d019893cacd6a312c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:50 +0200 Subject: [PATCH 3478/9938] mtd: nand: plat: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/plat_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index e4e50da30444..415a53a0deeb 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -74,6 +74,7 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; data->chip.ecc.mode = NAND_ECC_SOFT; + data->chip.ecc.algo = NAND_ECC_HAMMING; platform_set_drvdata(pdev, data); -- GitLab From ce111afd01bce7c137c92e9ed0dbe294a0f2373a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 8 Apr 2016 12:23:51 +0200 Subject: [PATCH 3479/9938] mtd: nand: socrates: set ECC algorithm explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of process deprecating NAND_ECC_SOFT_BCH (and switching to enum nand_ecc_algo). Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/socrates_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index e3305f9dd6fb..888fd314c62a 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -180,6 +180,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) nand_chip->dev_ready = socrates_nand_device_ready; nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ + nand_chip->ecc.algo = NAND_ECC_HAMMING; /* TODO: I have no idea what real delay is. */ nand_chip->chip_delay = 20; /* 20us command delay time */ -- GitLab From ff05fdb187cc25bff3e7ee9f79d94077c8d16a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 13 Apr 2016 11:48:05 +0200 Subject: [PATCH 3480/9938] mtd: nand: pasemi: switch to dev_* printing functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It also contains some minor related changes: 1) Don't warn if kzalloc fails as it dumps stack on its own 2) Use %pR format for displaying whole resource to avoid invalid format warning Signed-off-by: Rafał Miłecki Signed-off-by: Boris Brezillon --- drivers/mtd/nand/pasemi_nand.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 63fcb8c63877..5de7591b0510 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -92,8 +92,9 @@ int pasemi_device_ready(struct mtd_info *mtd) static int pasemi_nand_probe(struct platform_device *ofdev) { + struct device *dev = &ofdev->dev; struct pci_dev *pdev; - struct device_node *np = ofdev->dev.of_node; + struct device_node *np = dev->of_node; struct resource res; struct nand_chip *chip; int err = 0; @@ -107,13 +108,11 @@ static int pasemi_nand_probe(struct platform_device *ofdev) if (pasemi_nand_mtd) return -ENODEV; - pr_debug("pasemi_nand at %pR\n", &res); + dev_dbg(dev, "pasemi_nand at %pR\n", &res); /* Allocate memory for MTD device structure and private data */ chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); if (!chip) { - printk(KERN_WARNING - "Unable to allocate PASEMI NAND MTD device structure\n"); err = -ENOMEM; goto out; } @@ -121,7 +120,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) pasemi_nand_mtd = nand_to_mtd(chip); /* Link the private data with the MTD structure */ - pasemi_nand_mtd->dev.parent = &ofdev->dev; + pasemi_nand_mtd->dev.parent = dev; chip->IO_ADDR_R = of_iomap(np, 0); chip->IO_ADDR_W = chip->IO_ADDR_R; @@ -163,13 +162,13 @@ static int pasemi_nand_probe(struct platform_device *ofdev) } if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) { - printk(KERN_ERR "pasemi_nand: Unable to register MTD device\n"); + dev_err(dev, "Unable to register MTD device\n"); err = -ENODEV; goto out_lpc; } - printk(KERN_INFO "PA Semi NAND flash at %08llx, control at I/O %x\n", - res.start, lpcctl); + dev_info(dev, "PA Semi NAND flash at %pR, control at I/O %x\n", &res, + lpcctl); return 0; -- GitLab From 4f3cab9b4457108a8241ec7a66e03fe0b2cb3646 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 1 Apr 2016 14:54:22 +0200 Subject: [PATCH 3481/9938] mtd: nand: atmel: rely on generic DT parsing done in nand_scan_ident() The core now takes care of parsing generic DT properties in nand_scan_ident() when nand_set_flash_node() has been called. Rely on this initialization instead of calling of_get_nand_xxx() manually. Signed-off-by: Boris Brezillon Tested-by: Boris Brezillon Reviewed-by: Nicolas Ferre --- drivers/mtd/nand/atmel_nand.c | 133 +++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 60 deletions(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 0b5da7271440..5e716f2a8739 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -434,14 +433,13 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_get_controller_data(chip); if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) return; - if (host->board.bus_width_16) + if (chip->options & NAND_BUSWIDTH_16) atmel_read_buf16(mtd, buf, len); else atmel_read_buf8(mtd, buf, len); @@ -450,14 +448,13 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_get_controller_data(chip); if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) return; - if (host->board.bus_width_16) + if (chip->options & NAND_BUSWIDTH_16) atmel_write_buf16(mtd, buf, len); else atmel_write_buf8(mtd, buf, len); @@ -1507,58 +1504,17 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) ecc_writel(host->ecc, CR, ATMEL_ECC_RST); } -static int atmel_of_init_port(struct atmel_nand_host *host, - struct device_node *np) +static int atmel_of_init_ecc(struct atmel_nand_host *host, + struct device_node *np) { - u32 val; u32 offset[2]; - int ecc_mode; - struct atmel_nand_data *board = &host->board; - enum of_gpio_flags flags = 0; - - host->caps = (struct atmel_nand_caps *) - of_device_get_match_data(host->dev); - - if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { - if (val >= 32) { - dev_err(host->dev, "invalid addr-offset %u\n", val); - return -EINVAL; - } - board->ale = val; - } - - if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { - if (val >= 32) { - dev_err(host->dev, "invalid cmd-offset %u\n", val); - return -EINVAL; - } - board->cle = val; - } - - ecc_mode = of_get_nand_ecc_mode(np); - - board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode; - - board->on_flash_bbt = of_get_nand_on_flash_bbt(np); - - board->has_dma = of_property_read_bool(np, "atmel,nand-has-dma"); - - if (of_get_nand_bus_width(np) == 16) - board->bus_width_16 = 1; - - board->rdy_pin = of_get_gpio_flags(np, 0, &flags); - board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); - - board->enable_pin = of_get_gpio(np, 1); - board->det_pin = of_get_gpio(np, 2); + u32 val; host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); - /* load the nfc driver if there is */ - of_platform_populate(np, NULL, NULL, host->dev); - - if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc) - return 0; /* Not using PMECC */ + /* Not using PMECC */ + if (!(host->nand_chip.ecc.mode == NAND_ECC_HW) || !host->has_pmecc) + return 0; /* use PMECC, get correction capability, sector size and lookup * table offset. @@ -1599,16 +1555,64 @@ static int atmel_of_init_port(struct atmel_nand_host *host, /* Will build a lookup table and initialize the offset later */ return 0; } + if (!offset[0] && !offset[1]) { dev_err(host->dev, "Invalid PMECC lookup table offset\n"); return -EINVAL; } + host->pmecc_lookup_table_offset_512 = offset[0]; host->pmecc_lookup_table_offset_1024 = offset[1]; return 0; } +static int atmel_of_init_port(struct atmel_nand_host *host, + struct device_node *np) +{ + u32 val; + struct atmel_nand_data *board = &host->board; + enum of_gpio_flags flags = 0; + + host->caps = (struct atmel_nand_caps *) + of_device_get_match_data(host->dev); + + if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { + if (val >= 32) { + dev_err(host->dev, "invalid addr-offset %u\n", val); + return -EINVAL; + } + board->ale = val; + } + + if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { + if (val >= 32) { + dev_err(host->dev, "invalid cmd-offset %u\n", val); + return -EINVAL; + } + board->cle = val; + } + + board->has_dma = of_property_read_bool(np, "atmel,nand-has-dma"); + + board->rdy_pin = of_get_gpio_flags(np, 0, &flags); + board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); + + board->enable_pin = of_get_gpio(np, 1); + board->det_pin = of_get_gpio(np, 2); + + /* load the nfc driver if there is */ + of_platform_populate(np, NULL, NULL, host->dev); + + /* + * Initialize ECC mode to NAND_ECC_SOFT so that we have a correct value + * even if the nand-ecc-mode property is not defined. + */ + host->nand_chip.ecc.mode = NAND_ECC_SOFT; + + return 0; +} + static int atmel_hw_nand_init_params(struct platform_device *pdev, struct atmel_nand_host *host) { @@ -2150,6 +2154,11 @@ static int atmel_nand_probe(struct platform_device *pdev) } else { memcpy(&host->board, dev_get_platdata(&pdev->dev), sizeof(struct atmel_nand_data)); + nand_chip->ecc.mode = host->board.ecc_mode; + + /* 16-bit bus width */ + if (host->board.bus_width_16) + nand_chip->options |= NAND_BUSWIDTH_16; } /* link the private data structures */ @@ -2191,11 +2200,8 @@ static int atmel_nand_probe(struct platform_device *pdev) nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; } - nand_chip->ecc.mode = host->board.ecc_mode; nand_chip->chip_delay = 40; /* 40us command delay time */ - if (host->board.bus_width_16) /* 16-bit bus width */ - nand_chip->options |= NAND_BUSWIDTH_16; nand_chip->read_buf = atmel_read_buf; nand_chip->write_buf = atmel_write_buf; @@ -2228,11 +2234,6 @@ static int atmel_nand_probe(struct platform_device *pdev) } } - if (host->board.on_flash_bbt || on_flash_bbt) { - dev_info(&pdev->dev, "Use On Flash BBT\n"); - nand_chip->bbt_options |= NAND_BBT_USE_FLASH; - } - if (!host->board.has_dma) use_dma = 0; @@ -2259,6 +2260,18 @@ static int atmel_nand_probe(struct platform_device *pdev) goto err_scan_ident; } + if (host->board.on_flash_bbt || on_flash_bbt) + nand_chip->bbt_options |= NAND_BBT_USE_FLASH; + + if (nand_chip->bbt_options & NAND_BBT_USE_FLASH) + dev_info(&pdev->dev, "Use On Flash BBT\n"); + + if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { + res = atmel_of_init_ecc(host, pdev->dev.of_node); + if (res) + goto err_hw_ecc; + } + if (nand_chip->ecc.mode == NAND_ECC_HW) { if (host->has_pmecc) res = atmel_pmecc_nand_init_params(pdev, host); -- GitLab From 44ccb64fa56ad6d6d2d33a8625d9464f54c63eba Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 1 Apr 2016 14:54:30 +0200 Subject: [PATCH 3482/9938] mtd: nand: pxa3xx: rely on generic DT parsing done in nand_scan_ident() The core now takes care of parsing generic DT properties in nand_scan_ident() when nand_set_flash_node() has been called. Rely on this initialization instead of calling of_get_nand_xxx() manually. Signed-off-by: Boris Brezillon Acked-by: Ezequiel Garcia --- drivers/mtd/nand/pxa3xx_nand.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index d6508856da99..38d26ab1f0f7 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200) @@ -1651,6 +1650,12 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) nand_writel(info, NDECCCTRL, 0x0); + if (pdata->flash_bbt) + chip->bbt_options |= NAND_BBT_USE_FLASH; + + chip->ecc.strength = pdata->ecc_strength; + chip->ecc.size = pdata->ecc_step_size; + if (nand_scan_ident(mtd, 1, NULL)) return -ENODEV; @@ -1663,13 +1668,12 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) } } - if (pdata->flash_bbt) { + if (chip->bbt_options & NAND_BBT_USE_FLASH) { /* * We'll use a bad block table stored in-flash and don't * allow writing the bad block marker to the flash. */ - chip->bbt_options |= NAND_BBT_USE_FLASH | - NAND_BBT_NO_OOB_BBM; + chip->bbt_options |= NAND_BBT_NO_OOB_BBM; chip->bbt_td = &bbt_main_descr; chip->bbt_md = &bbt_mirror_descr; } @@ -1689,10 +1693,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) } } - if (pdata->ecc_strength && pdata->ecc_step_size) { - ecc_strength = pdata->ecc_strength; - ecc_step = pdata->ecc_step_size; - } else { + ecc_strength = chip->ecc.strength; + ecc_step = chip->ecc.size; + if (!ecc_strength || !ecc_step) { ecc_strength = chip->ecc_strength_ds; ecc_step = chip->ecc_step_ds; } @@ -1903,15 +1906,6 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev) if (of_get_property(np, "marvell,nand-keep-config", NULL)) pdata->keep_config = 1; of_property_read_u32(np, "num-cs", &pdata->num_cs); - pdata->flash_bbt = of_get_nand_on_flash_bbt(np); - - pdata->ecc_strength = of_get_nand_ecc_strength(np); - if (pdata->ecc_strength < 0) - pdata->ecc_strength = 0; - - pdata->ecc_step_size = of_get_nand_ecc_step_size(np); - if (pdata->ecc_step_size < 0) - pdata->ecc_step_size = 0; pdev->dev.platform_data = pdata; -- GitLab From 9edb47004e2afb5884d0c900cbd1ece8b2d6f403 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 2 Dec 2015 16:00:57 +0100 Subject: [PATCH 3483/9938] mtd: nand: sunxi: fix call order in sunxi_nand_chip_init() sunxi_nand_chip_set_timings() is extracting a pointer to the nfc from the nand->controller field, but this field is initialized after sunxi_nand_chip_set_timings() call. Reorder the calls to avoid any problem. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 3a97093662ea..546a9cae9bd1 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1535,21 +1535,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, } } - timings = onfi_async_timing_mode_to_sdr_timings(0); - if (IS_ERR(timings)) { - ret = PTR_ERR(timings); - dev_err(dev, - "could not retrieve timings for ONFI mode 0: %d\n", - ret); - return ret; - } - - ret = sunxi_nand_chip_set_timings(chip, timings); - if (ret) { - dev_err(dev, "could not configure chip timings: %d\n", ret); - return ret; - } - nand = &chip->nand; /* Default tR value specified in the ONFI spec (chapter 4.15.1) */ nand->chip_delay = 200; @@ -1569,6 +1554,21 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, mtd = nand_to_mtd(nand); mtd->dev.parent = dev; + timings = onfi_async_timing_mode_to_sdr_timings(0); + if (IS_ERR(timings)) { + ret = PTR_ERR(timings); + dev_err(dev, + "could not retrieve timings for ONFI mode 0: %d\n", + ret); + return ret; + } + + ret = sunxi_nand_chip_set_timings(chip, timings); + if (ret) { + dev_err(dev, "could not configure chip timings: %d\n", ret); + return ret; + } + ret = nand_scan_ident(mtd, nsels, NULL); if (ret) return ret; -- GitLab From 2f9992e080b8892a10d189cbc846c06e6594ad0b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 2 Dec 2015 15:10:40 +0100 Subject: [PATCH 3484/9938] mtd: nand: sunxi: fix clk rate calculation Unlike what is specified in the Allwinner datasheets, the NAND clock rate is not equal to 2/T but 1/T. Fix the clock rate selection accordingly. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 546a9cae9bd1..05b33035f651 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1208,12 +1208,12 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); /* - * Convert min_clk_period into a clk frequency, then get the - * appropriate rate for the NAND controller IP given this formula - * (specified in the datasheet): - * nand clk_rate = 2 * min_clk_rate + * Unlike what is stated in Allwinner datasheet, the clk_rate should + * be set to (1 / min_clk_period), and not (2 / min_clk_period). + * This new formula was verified with a scope and validated by + * Allwinner engineers. */ - chip->clk_rate = (2 * NSEC_PER_SEC) / min_clk_period; + chip->clk_rate = NSEC_PER_SEC / min_clk_period; return 0; } -- GitLab From 2d43457f79e48ee427666fdbfe9a53f35d3a1672 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 2 Dec 2015 15:57:20 +0100 Subject: [PATCH 3485/9938] mtd: nand: sunxi: fix EDO mode selection The ONFI spec says that EDO should be enabled if the host drives tRC less than 30ns, but the code just tests for the tRC_min value extracted from the timings exposed by the NAND chip not the timings actually configured in the NAND controller. Fix that by first rounding down the requested clk_rate with clk_round_rate() and then checking if tRC is actually smaller than 30ns. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 05b33035f651..b906fc5a22fe 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1100,6 +1100,7 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller); u32 min_clk_period = 0; s32 tWB, tADL, tWHR, tRHW, tCAD; + long real_clk_rate; /* T1 <=> tCLS */ if (timings->tCLS_min > min_clk_period) @@ -1197,13 +1198,6 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */ chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); - /* - * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data - * output cycle timings shall be used if the host drives tRC less than - * 30 ns. - */ - chip->timing_ctl = (timings->tRC_min < 30000) ? NFC_TIMING_CTL_EDO : 0; - /* Convert min_clk_period from picoseconds to nanoseconds */ min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); @@ -1214,6 +1208,16 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, * Allwinner engineers. */ chip->clk_rate = NSEC_PER_SEC / min_clk_period; + real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate); + + /* + * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data + * output cycle timings shall be used if the host drives tRC less than + * 30 ns. + */ + min_clk_period = NSEC_PER_SEC / real_clk_rate; + chip->timing_ctl = ((min_clk_period * 2) < 30) ? + NFC_TIMING_CTL_EDO : 0; return 0; } -- GitLab From 5abcd95d8c69008c72d54d7763e0ee2b5df84ac4 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 11 Nov 2015 22:30:30 +0100 Subject: [PATCH 3486/9938] mtd: nand: sunxi: adapt clk_rate to tWB, tADL, tWHR and tRHW timings Adapt the NAND controller clk rate to the tWB, tADL, tWHR and tRHW timings instead of returning an error when the maximum clk divisor is not big enough to provide an appropriate timing. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index b906fc5a22fe..e30276d9a9e3 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1163,6 +1163,18 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2); /* T16 - T19 + tCAD */ + if (timings->tWB_max > (min_clk_period * 20)) + min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20); + + if (timings->tADL_min > (min_clk_period * 32)) + min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32); + + if (timings->tWHR_min > (min_clk_period * 32)) + min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32); + + if (timings->tRHW_min > (min_clk_period * 20)) + min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20); + tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max, min_clk_period); if (tWB < 0) { -- GitLab From 9d02fc2a5129449581c3108c260e96377cf35f7e Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 26 Aug 2015 16:08:12 +0200 Subject: [PATCH 3487/9938] mtd: nand: export default read/write oob functions Export the default read/write oob functions (for the standard and syndrome scheme), so that drivers can use them for their raw implementation and implement their own functions for the normal oob operation. This is required if your ECC engine is capable of fixing some of the OOB data. In this case you have to overload the ->read_oob() and ->write_oob(), but if you don't specify the ->read/write_oob_raw() functions they are assigned to the ->read/write_oob() implementation, which is not what you want. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 18 ++++++++++-------- include/linux/mtd/nand.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0f0c5b190316..13fcddc8a10e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1893,13 +1893,13 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, * @chip: nand chip info structure * @page: page number to read */ -static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, - int page) +int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) { chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); return 0; } +EXPORT_SYMBOL(nand_read_oob_std); /** * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC @@ -1908,8 +1908,8 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, * @chip: nand chip info structure * @page: page number to read */ -static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page) +int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + int page) { int length = mtd->oobsize; int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; @@ -1937,6 +1937,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, return 0; } +EXPORT_SYMBOL(nand_read_oob_syndrome); /** * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function @@ -1944,8 +1945,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, * @chip: nand chip info structure * @page: page number to write */ -static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, - int page) +int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) { int status = 0; const uint8_t *buf = chip->oob_poi; @@ -1960,6 +1960,7 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, return status & NAND_STATUS_FAIL ? -EIO : 0; } +EXPORT_SYMBOL(nand_write_oob_std); /** * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC @@ -1968,8 +1969,8 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, * @chip: nand chip info structure * @page: page number to write */ -static int nand_write_oob_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, int page) +int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + int page) { int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; int eccsize = chip->ecc.size, length = mtd->oobsize; @@ -2019,6 +2020,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, return status & NAND_STATUS_FAIL ? -EIO : 0; } +EXPORT_SYMBOL(nand_write_oob_syndrome); /** * nand_do_read_oob - [INTERN] NAND read out-of-band diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 1b673e19667c..7e06afb8552c 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -1078,4 +1078,18 @@ int nand_check_erased_ecc_chunk(void *data, int datalen, void *ecc, int ecclen, void *extraoob, int extraooblen, int threshold); + +/* Default write_oob implementation */ +int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page); + +/* Default write_oob syndrome implementation */ +int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + int page); + +/* Default read_oob implementation */ +int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page); + +/* Default read_oob syndrome implementation */ +int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + int page); #endif /* __LINUX_MTD_NAND_H */ -- GitLab From 1c1bdd6f866e08b2a34318ce089b678200e8de85 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 2 Sep 2015 15:05:52 +0200 Subject: [PATCH 3488/9938] mtd: nand: sunxi: implement ->read_oob()/->write_oob() Allwinner's ECC engine is capable of protecting a few bytes of the OOB area. Implement specific OOB functions to benefit from this capability. Also, when in raw mode, the randomizer is disabled, which means you'll only be able to retrieve randomized data, which is not really useful for most applications. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index e30276d9a9e3..d8ad50fbadb7 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1073,6 +1073,40 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd, return 0; } +static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd, + struct nand_chip *chip, + int page) +{ + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + + chip->pagebuf = -1; + + return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page); +} + +static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd, + struct nand_chip *chip, + int page) +{ + int ret, status; + + chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page); + + chip->pagebuf = -1; + + memset(chip->buffers->databuf, 0xff, mtd->writesize); + ret = chip->ecc.write_page(mtd, chip, chip->buffers->databuf, 1, page); + if (ret) + return ret; + + /* Send command to program the OOB data */ + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + + status = chip->waitfunc(mtd, chip); + + return status & NAND_STATUS_FAIL ? -EIO : 0; +} + static const s32 tWB_lut[] = {6, 12, 16, 20}; static const s32 tRHW_lut[] = {4, 8, 12, 20}; @@ -1320,6 +1354,8 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, layout->eccbytes = (ecc->bytes * nsectors); + ecc->read_oob = sunxi_nfc_hw_common_ecc_read_oob; + ecc->write_oob = sunxi_nfc_hw_common_ecc_write_oob; ecc->layout = layout; ecc->priv = data; @@ -1351,6 +1387,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, ecc->read_page = sunxi_nfc_hw_ecc_read_page; ecc->write_page = sunxi_nfc_hw_ecc_write_page; + ecc->read_oob_raw = nand_read_oob_std; + ecc->write_oob_raw = nand_write_oob_std; layout = ecc->layout; nsectors = mtd->writesize / ecc->size; @@ -1405,6 +1443,8 @@ static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd, ecc->prepad = 4; ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page; ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page; + ecc->read_oob_raw = nand_read_oob_syndrome; + ecc->write_oob_raw = nand_write_oob_syndrome; layout = ecc->layout; nsectors = mtd->writesize / ecc->size; -- GitLab From fe82ccefc992b255c35e0e56d6aded2ce090e9af Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 16 Sep 2015 09:01:45 +0200 Subject: [PATCH 3489/9938] mtd: nand: sunxi: implement ->read_subpage() Being able to read subpages can greatly improve read performances if the MTD user is only interested in a small section of a NAND page. This is particularly true with large pages (>= 8k). Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index d8ad50fbadb7..e4d487cf2ebd 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -973,6 +973,39 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, return max_bitflips; } +static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd, + struct nand_chip *chip, + u32 data_offs, u32 readlen, + u8 *bufpoi, int page) +{ + struct nand_ecc_ctrl *ecc = &chip->ecc; + int ret, i, cur_off = 0; + unsigned int max_bitflips = 0; + + sunxi_nfc_hw_ecc_enable(mtd); + + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + for (i = data_offs / ecc->size; + i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { + int data_off = i * ecc->size; + int oob_off = i * (ecc->bytes + 4); + u8 *data = bufpoi + data_off; + u8 *oob = chip->oob_poi + oob_off; + + ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, + oob, + oob_off + mtd->writesize, + &cur_off, &max_bitflips, + !i, page); + if (ret < 0) + return ret; + } + + sunxi_nfc_hw_ecc_disable(mtd); + + return max_bitflips; +} + static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, @@ -1389,6 +1422,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, ecc->write_page = sunxi_nfc_hw_ecc_write_page; ecc->read_oob_raw = nand_read_oob_std; ecc->write_oob_raw = nand_write_oob_std; + ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage; layout = ecc->layout; nsectors = mtd->writesize / ecc->size; @@ -1635,6 +1669,8 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, if (nand->options & NAND_NEED_SCRAMBLING) nand->options |= NAND_NO_SUBPAGE_WRITE; + nand->options |= NAND_SUBPAGE_READ; + ret = sunxi_nand_chip_init_timings(chip, np); if (ret) { dev_err(dev, "could not configure chip timings: %d\n", ret); -- GitLab From e9aa671f69acb87db4835e4f0b41f5fa16d16562 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 16 Sep 2015 09:05:31 +0200 Subject: [PATCH 3490/9938] mtd: nand: sunxi: improve ->cmd_ctrl() function Try to pack address and command cycles into a single NAND controller command to avoid polling the status register for each single change on the NAND bus. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 52 +++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index e4d487cf2ebd..ab572dd5ad3c 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -238,6 +238,10 @@ struct sunxi_nand_chip { u32 timing_cfg; u32 timing_ctl; int selected; + int addr_cycles; + u32 addr[2]; + int cmd_cycles; + u8 cmd[2]; int nsels; struct sunxi_nand_chip_sel sels[0]; }; @@ -525,17 +529,49 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, writel(tmp, nfc->regs + NFC_REG_CTL); } - if (dat == NAND_CMD_NONE) - return; + if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) && + !(ctrl & (NAND_CLE | NAND_ALE))) { + u32 cmd = 0; - if (ctrl & NAND_CLE) { - writel(NFC_SEND_CMD1 | dat, nfc->regs + NFC_REG_CMD); - } else { - writel(dat, nfc->regs + NFC_REG_ADDR_LOW); - writel(NFC_SEND_ADR, nfc->regs + NFC_REG_CMD); + if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles) + return; + + if (sunxi_nand->cmd_cycles--) + cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0]; + + if (sunxi_nand->cmd_cycles--) { + cmd |= NFC_SEND_CMD2; + writel(sunxi_nand->cmd[1], + nfc->regs + NFC_REG_RCMD_SET); + } + + sunxi_nand->cmd_cycles = 0; + + if (sunxi_nand->addr_cycles) { + cmd |= NFC_SEND_ADR | + NFC_ADR_NUM(sunxi_nand->addr_cycles); + writel(sunxi_nand->addr[0], + nfc->regs + NFC_REG_ADDR_LOW); + } + + if (sunxi_nand->addr_cycles > 4) + writel(sunxi_nand->addr[1], + nfc->regs + NFC_REG_ADDR_HIGH); + + writel(cmd, nfc->regs + NFC_REG_CMD); + sunxi_nand->addr[0] = 0; + sunxi_nand->addr[1] = 0; + sunxi_nand->addr_cycles = 0; + sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); } - sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + if (ctrl & NAND_CLE) { + sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat; + } else if (ctrl & NAND_ALE) { + sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |= + dat << ((sunxi_nand->addr_cycles % 4) * 8); + sunxi_nand->addr_cycles++; + } } /* These seed values have been extracted from Allwinner's BSP */ -- GitLab From ece03cfd5260e0349442dea1d1065f44fbed1ea8 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 17:21:35 +0100 Subject: [PATCH 3491/9938] mtd: nand: sunxi: let the NAND controller control the CE line We don't need to manually toggle the CE line since the controller handles it for us. Moreover, keeping the CE line low when interacting with a DDR NAND can be problematic (data loss in some corner cases). Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index ab572dd5ad3c..4dcc0e42e0ef 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -514,21 +514,11 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); int ret; - u32 tmp; ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) return; - if (ctrl & NAND_CTRL_CHANGE) { - tmp = readl(nfc->regs + NFC_REG_CTL); - if (ctrl & NAND_NCE) - tmp |= NFC_CE_CTL; - else - tmp &= ~NFC_CE_CTL; - writel(tmp, nfc->regs + NFC_REG_CTL); - } - if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) && !(ctrl & (NAND_CLE | NAND_ALE))) { u32 cmd = 0; -- GitLab From f8b04746a4ba389d609b5ddcfbf95835c7dfcb31 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 17:25:08 +0100 Subject: [PATCH 3492/9938] mtd: nand: sunxi: fix the NFC_ECC_ERR_CNT() macro NFC_ECC_ERR_CNT() is not taking into account the case when the NAND chip contains more than 4 ECC blocks (NANDs with 4kB+ pages). Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 4dcc0e42e0ef..4cb5c6f866ff 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -154,7 +154,7 @@ /* define bit use in NFC_ECC_ST */ #define NFC_ECC_ERR(x) BIT(x) #define NFC_ECC_PAT_FOUND(x) BIT(x + 16) -#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff) +#define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff) #define NFC_DEFAULT_TIMEOUT_MS 1000 -- GitLab From 68ffbf7f9fb11323238cb31c956b4f381e6b05cc Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 17:29:20 +0100 Subject: [PATCH 3493/9938] mtd: nand: sunxi: fix NFC_CTL setting NFC_PAGE_SHIFT() already takes the real page_shift value and subtract 10 to it. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 4cb5c6f866ff..f8b3a7281af0 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -410,7 +410,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) sel = &sunxi_nand->sels[chip]; ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | - NFC_PAGE_SHIFT(nand->page_shift - 10); + NFC_PAGE_SHIFT(nand->page_shift); if (sel->rb.type == RB_NONE) { nand->dev_ready = NULL; } else { -- GitLab From dd26a4584c37687b8bbe89233bcc23279ca361b1 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 18:26:40 +0100 Subject: [PATCH 3494/9938] mtd: nand: sunxi: disable clks on device removal mod and ahb clocks are not disabled when the NAND controller device is removed. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index f8b3a7281af0..cad20fb058a1 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1845,6 +1845,8 @@ static int sunxi_nfc_remove(struct platform_device *pdev) struct sunxi_nfc *nfc = platform_get_drvdata(pdev); sunxi_nand_chips_cleanup(nfc); + clk_disable_unprepare(nfc->mod_clk); + clk_disable_unprepare(nfc->ahb_clk); return 0; } -- GitLab From 336de7b1e07e6c666dbed522120547b852b3fba7 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 17:33:10 +0100 Subject: [PATCH 3495/9938] mtd: nand: enable ECC pipelining When the NAND controller operates in DMA mode it can pipeline ECC operations which improves the throughput. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index cad20fb058a1..fe3730a6ba54 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -742,7 +742,8 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE_MSK); - ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION; + ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION | + NFC_ECC_PIPELINE; writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); } -- GitLab From a9a416f0c723e10ecccfe7ea30e93dfee0dbf10d Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 7 Mar 2016 15:10:28 +0100 Subject: [PATCH 3496/9938] mtd: nand: sunxi: fix ->dev_ready() implementation ->dev_ready() is not supposed to wait for busy to ready solution (this is the role of ->waitfunc()). Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index fe3730a6ba54..fff28512cd71 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -357,7 +357,6 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd) struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct sunxi_nand_rb *rb; - unsigned long timeo = (sunxi_nand->nand.state == FL_ERASING ? 400 : 20); int ret; if (sunxi_nand->selected < 0) @@ -367,12 +366,6 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd) switch (rb->type) { case RB_NATIVE: - ret = !!(readl(nfc->regs + NFC_REG_ST) & - NFC_RB_STATE(rb->info.nativeid)); - if (ret) - break; - - sunxi_nfc_wait_int(nfc, NFC_RB_B2R, timeo); ret = !!(readl(nfc->regs + NFC_REG_ST) & NFC_RB_STATE(rb->info.nativeid)); break; -- GitLab From 166f08c7b6ab2f98eebbb6fc1fdb0be1efe0a566 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 7 Mar 2016 15:25:17 +0100 Subject: [PATCH 3497/9938] mtd: nand: sunxi: make use of readl_poll_timeout() Replace open coded polling loops by readl_poll_timeout() calls. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index fff28512cd71..d4d79b2f1d43 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #define NFC_REG_CTL 0x0000 #define NFC_REG_ST 0x0004 @@ -322,33 +322,33 @@ static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags, static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc) { - unsigned long timeout = jiffies + - msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS); + u32 status; + int ret; - do { - if (!(readl(nfc->regs + NFC_REG_ST) & NFC_CMD_FIFO_STATUS)) - return 0; - } while (time_before(jiffies, timeout)); + ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, + !(status & NFC_CMD_FIFO_STATUS), 1, + NFC_DEFAULT_TIMEOUT_MS * 1000); + if (ret) + dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n"); - dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n"); - return -ETIMEDOUT; + return ret; } static int sunxi_nfc_rst(struct sunxi_nfc *nfc) { - unsigned long timeout = jiffies + - msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS); + u32 ctl; + int ret; writel(0, nfc->regs + NFC_REG_ECC_CTL); writel(NFC_RESET, nfc->regs + NFC_REG_CTL); - do { - if (!(readl(nfc->regs + NFC_REG_CTL) & NFC_RESET)) - return 0; - } while (time_before(jiffies, timeout)); + ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl, + !(ctl & NFC_RESET), 1, + NFC_DEFAULT_TIMEOUT_MS * 1000); + if (ret) + dev_err(nfc->dev, "wait for NAND controller reset timedout\n"); - dev_err(nfc->dev, "wait for NAND controller reset timedout\n"); - return -ETIMEDOUT; + return ret; } static int sunxi_nfc_dev_ready(struct mtd_info *mtd) -- GitLab From c0c9dfa8adf09dbbb7dc32c20d9ccb33e19250c0 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 7 Mar 2016 15:34:39 +0100 Subject: [PATCH 3498/9938] mtd: nand: sunxi: poll for events instead of using interrupts Some NAND operations are so fast that it doesn't make any sense to use interrupt based waits (the scheduling overhead is not worth it). Rename sunxi_nfc_wait_int() into sunxi_nfc_wait_events() and add a parameter to specify whether polling should be used or not. Note that all sunxi_nfc_wait_int() are moved to the polling approach now, but this should change as soon as we have more information about the approximate time we are about to wait (can be extracted from the NAND timings, and the type of operation). Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 45 ++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index d4d79b2f1d43..8be3dba07ff7 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -301,23 +301,40 @@ static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags, - unsigned int timeout_ms) +static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, + bool use_polling, unsigned int timeout_ms) { - init_completion(&nfc->complete); + int ret; - writel(flags, nfc->regs + NFC_REG_INT); + if (events & ~NFC_INT_MASK) + return -EINVAL; if (!timeout_ms) timeout_ms = NFC_DEFAULT_TIMEOUT_MS; - if (!wait_for_completion_timeout(&nfc->complete, - msecs_to_jiffies(timeout_ms))) { - dev_err(nfc->dev, "wait interrupt timedout\n"); - return -ETIMEDOUT; + if (!use_polling) { + init_completion(&nfc->complete); + + writel(events, nfc->regs + NFC_REG_INT); + + ret = wait_for_completion_timeout(&nfc->complete, + msecs_to_jiffies(timeout_ms)); + + writel(0, nfc->regs + NFC_REG_INT); + } else { + u32 status; + + ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status, + (status & events) == events, 1, + timeout_ms * 1000); } - return 0; + writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); + + if (ret) + dev_err(nfc->dev, "wait interrupt timedout\n"); + + return ret; } static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc) @@ -448,7 +465,7 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; writel(tmp, nfc->regs + NFC_REG_CMD); - ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); if (ret) break; @@ -483,7 +500,7 @@ static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, NFC_ACCESS_DIR; writel(tmp, nfc->regs + NFC_REG_CMD); - ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); if (ret) break; @@ -545,7 +562,7 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, sunxi_nand->addr[0] = 0; sunxi_nand->addr[1] = 0; sunxi_nand->addr_cycles = 0; - sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); } if (ctrl & NAND_CLE) { @@ -788,7 +805,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); - ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); sunxi_nfc_randomizer_disable(mtd); if (ret) return ret; @@ -926,7 +943,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, NFC_ACCESS_DIR | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); - ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0); sunxi_nfc_randomizer_disable(mtd); if (ret) return ret; -- GitLab From cc6822fb756b5080ca127fef1a89f35558bd2610 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 17:56:47 +0100 Subject: [PATCH 3499/9938] mtd: nand: sunxi: move some ECC related operations to their own functions In order to support DMA operations in a clean way we need to extract some of the logic coded in sunxi_nfc_hw_ecc_read/write_page() into their own function. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 163 ++++++++++++++++++++++------------ 1 file changed, 108 insertions(+), 55 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 8be3dba07ff7..c20bf59141b0 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -775,6 +775,94 @@ static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf) buf[3] = user_data >> 24; } +static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) +{ + return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); +} + +static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob, + int step, bool bbm, int page) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)), + oob); + + /* De-randomize the Bad Block Marker. */ + if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) + sunxi_nfc_randomize_bbm(mtd, page, oob); +} + +static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd, + const u8 *oob, int step, + bool bbm, int page) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u8 user_data[4]; + + /* Randomize the Bad Block Marker. */ + if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { + memcpy(user_data, oob, sizeof(user_data)); + sunxi_nfc_randomize_bbm(mtd, page, user_data); + oob = user_data; + } + + writel(sunxi_nfc_buf_to_user_data(oob), + nfc->regs + NFC_REG_USER_DATA(step)); +} + +static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd, + unsigned int *max_bitflips, int ret) +{ + if (ret < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += ret; + *max_bitflips = max_t(unsigned int, *max_bitflips, ret); + } +} + +static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob, + int step, bool *erased) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + u32 status, tmp; + + *erased = false; + + status = readl(nfc->regs + NFC_REG_ECC_ST); + + if (status & NFC_ECC_ERR(step)) + return -EBADMSG; + + if (status & NFC_ECC_PAT_FOUND(step)) { + u8 pattern; + + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) { + pattern = 0x0; + } else { + pattern = 0xff; + *erased = true; + } + + if (data) + memset(data, pattern, ecc->size); + + if (oob) + memset(oob, pattern, ecc->bytes + 4); + + return 0; + } + + tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step)); + + return NFC_ECC_ERR_CNT(step, tmp); +} + static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, u8 *data, int data_off, u8 *oob, int oob_off, @@ -786,7 +874,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; int raw_mode = 0; - u32 status; + bool erased; int ret; if (*cur_off != data_off) @@ -812,27 +900,11 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, *cur_off = oob_off + ecc->bytes + 4; - status = readl(nfc->regs + NFC_REG_ECC_ST); - if (status & NFC_ECC_PAT_FOUND(0)) { - u8 pattern = 0xff; - - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) - pattern = 0x0; - - memset(data, pattern, ecc->size); - memset(oob, pattern, ecc->bytes + 4); - + ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob, 0, &erased); + if (erased) return 1; - } - - ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0))); - - memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); - nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); - sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page); - - if (status & NFC_ECC_ERR(0)) { + if (ret < 0) { /* * Re-read the data with the randomizer disabled to identify * bitflips in erased pages. @@ -840,35 +912,32 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (nand->options & NAND_NEED_SCRAMBLING) { nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); nand->read_buf(mtd, data, ecc->size); - nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); - nand->read_buf(mtd, oob, ecc->bytes + 4); + } else { + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, + ecc->size); } + nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); + nand->read_buf(mtd, oob, ecc->bytes + 4); + ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, ecc->bytes + 4, NULL, 0, ecc->strength); if (ret >= 0) raw_mode = 1; } else { - /* - * The engine protects 4 bytes of OOB data per chunk. - * Retrieve the corrected OOB bytes. - */ - sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(0)), - oob); + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); - /* De-randomize the Bad Block Marker. */ - if (bbm && nand->options & NAND_NEED_SCRAMBLING) - sunxi_nfc_randomize_bbm(mtd, page, oob); - } + nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); + sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, + true, page); - if (ret < 0) { - mtd->ecc_stats.failed++; - } else { - mtd->ecc_stats.corrected += ret; - *max_bitflips = max_t(unsigned int, *max_bitflips, ret); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0, + bbm, page); } + sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret); + return raw_mode; } @@ -897,11 +966,6 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, *cur_off = mtd->oobsize + mtd->writesize; } -static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) -{ - return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); -} - static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, const u8 *data, int data_off, const u8 *oob, int oob_off, @@ -918,19 +982,6 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page); - /* Fill OOB data in */ - if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) { - u8 user_data[4]; - - memcpy(user_data, oob, 4); - sunxi_nfc_randomize_bbm(mtd, page, user_data); - writel(sunxi_nfc_buf_to_user_data(user_data), - nfc->regs + NFC_REG_USER_DATA(0)); - } else { - writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(0)); - } - if (data_off + ecc->size != oob_off) nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1); @@ -939,6 +990,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, return ret; sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page); + writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); -- GitLab From 828dec153044805506cc2b8e39cb3f62d5f76a12 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 18:09:21 +0100 Subject: [PATCH 3500/9938] mtd: nand: sunxi: make OOB retrieval optional sunxi_nfc_hw_ecc_read_chunk() always retrieves the ECC and protected free bytes, no matter if the user really asked for it or not. This can take a non negligible amount of time, especially on NAND chips exposing large OOB areas (> 1KB). Make it optional. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index c20bf59141b0..b71053252a02 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -868,7 +868,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, - bool bbm, int page) + bool bbm, bool oob_required, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); @@ -900,7 +900,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, *cur_off = oob_off + ecc->bytes + 4; - ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob, 0, &erased); + ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0, + &erased); if (erased) return 1; @@ -928,12 +929,14 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, } else { memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); - nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); - sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, - true, page); + if (oob_required) { + nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); + sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, + true, page); - sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0, - bbm, page); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0, + bbm, page); + } } sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret); @@ -1047,7 +1050,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, - !i, page); + !i, oob_required, page); if (ret < 0) return ret; else if (ret) @@ -1085,8 +1088,8 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, &max_bitflips, - !i, page); + &cur_off, &max_bitflips, !i, + false, page); if (ret < 0) return ret; } @@ -1148,7 +1151,9 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off, &cur_off, - &max_bitflips, !i, page); + &max_bitflips, !i, + oob_required, + page); if (ret < 0) return ret; else if (ret) -- GitLab From c4f3ef2c6c219c3e58e0f5a9589a67685a75d787 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 4 Mar 2016 18:13:10 +0100 Subject: [PATCH 3501/9938] mtd: nand: sunxi: make cur_off parameter optional in extra oob helpers Allow for NULL cur_offs values when the caller does not know where the NAND page register pointer points to. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index b71053252a02..b12ed83ebd56 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -956,7 +956,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, if (len <= 0) return; - if (*cur_off != offset) + if (!cur_off || *cur_off != offset) nand->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1); @@ -966,7 +966,8 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len, false, page); - *cur_off = mtd->oobsize + mtd->writesize; + if (cur_off) + *cur_off = mtd->oobsize + mtd->writesize; } static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, @@ -1021,13 +1022,14 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, if (len <= 0) return; - if (*cur_off != offset) + if (!cur_off || *cur_off != offset) nand->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1); sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page); - *cur_off = mtd->oobsize + mtd->writesize; + if (cur_off) + *cur_off = mtd->oobsize + mtd->writesize; } static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, -- GitLab From 75eb2cec251fda33c9bb716ecc372819abb9278a Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 4 Feb 2016 09:52:30 +0100 Subject: [PATCH 3502/9938] mtd: add mtd_ooblayout_xxx() helper functions In order to make the ecclayout definition completely dynamic we need to rework the way the OOB layout are defined and iterated. Create a few mtd_ooblayout_xxx() helpers to ease OOB bytes manipulation and hide ecclayout internals to their users. Signed-off-by: Boris Brezillon --- drivers/mtd/mtdcore.c | 400 ++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/mtd.h | 33 ++++ 2 files changed, 433 insertions(+) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index bee180bd11e7..0290c41e44fc 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1016,6 +1016,406 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to, } EXPORT_SYMBOL_GPL(mtd_write_oob); +/** + * mtd_ooblayout_ecc - Get the OOB region definition of a specific ECC section + * @mtd: MTD device structure + * @section: ECC section. Depending on the layout you may have all the ECC + * bytes stored in a single contiguous section, or one section + * per ECC chunk (and sometime several sections for a single ECC + * ECC chunk) + * @oobecc: OOB region struct filled with the appropriate ECC position + * information + * + * This functions return ECC section information in the OOB area. I you want + * to get all the ECC bytes information, then you should call + * mtd_ooblayout_ecc(mtd, section++, oobecc) until it returns -ERANGE. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobecc) +{ + int eccbyte = 0, cursection = 0, length = 0, eccpos = 0; + + memset(oobecc, 0, sizeof(*oobecc)); + + if (!mtd || section < 0) + return -EINVAL; + + if (!mtd->ecclayout) + return -ENOTSUPP; + + /* + * This logic allows us to reuse the ->ecclayout information and + * expose them as ECC regions (as done for the OOB free regions). + * + * TODO: this should be dropped as soon as we get rid of the + * ->ecclayout field. + */ + for (eccbyte = 0; eccbyte < mtd->ecclayout->eccbytes; eccbyte++) { + eccpos = mtd->ecclayout->eccpos[eccbyte]; + + if (eccbyte < mtd->ecclayout->eccbytes - 1) { + int neccpos = mtd->ecclayout->eccpos[eccbyte + 1]; + + if (eccpos + 1 == neccpos) { + length++; + continue; + } + } + + if (section == cursection) + break; + + length = 0; + cursection++; + } + + if (cursection != section || eccbyte >= mtd->ecclayout->eccbytes) + return -ERANGE; + + oobecc->length = length + 1; + oobecc->offset = eccpos - length; + + return 0; +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_ecc); + +/** + * mtd_ooblayout_free - Get the OOB region definition of a specific free + * section + * @mtd: MTD device structure + * @section: Free section you are interested in. Depending on the layout + * you may have all the free bytes stored in a single contiguous + * section, or one section per ECC chunk plus an extra section + * for the remaining bytes (or other funky layout). + * @oobfree: OOB region struct filled with the appropriate free position + * information + * + * This functions return free bytes position in the OOB area. I you want + * to get all the free bytes information, then you should call + * mtd_ooblayout_free(mtd, section++, oobfree) until it returns -ERANGE. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobfree) +{ + memset(oobfree, 0, sizeof(*oobfree)); + + if (!mtd || section < 0) + return -EINVAL; + + if (!mtd->ecclayout) + return -ENOTSUPP; + + if (section >= MTD_MAX_OOBFREE_ENTRIES_LARGE) + return -ERANGE; + + oobfree->offset = mtd->ecclayout->oobfree[section].offset; + oobfree->length = mtd->ecclayout->oobfree[section].length; + + return 0; +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_free); + +/** + * mtd_ooblayout_find_region - Find the region attached to a specific byte + * @mtd: mtd info structure + * @byte: the byte we are searching for + * @sectionp: pointer where the section id will be stored + * @oobregion: used to retrieve the ECC position + * @iter: iterator function. Should be either mtd_ooblayout_free or + * mtd_ooblayout_ecc depending on the region type you're searching for + * + * This functions returns the section id and oobregion information of a + * specific byte. For example, say you want to know where the 4th ECC byte is + * stored, you'll use: + * + * mtd_ooblayout_find_region(mtd, 3, §ion, &oobregion, mtd_ooblayout_ecc); + * + * Returns zero on success, a negative error code otherwise. + */ +static int mtd_ooblayout_find_region(struct mtd_info *mtd, int byte, + int *sectionp, struct mtd_oob_region *oobregion, + int (*iter)(struct mtd_info *, + int section, + struct mtd_oob_region *oobregion)) +{ + int pos = 0, ret, section = 0; + + memset(oobregion, 0, sizeof(*oobregion)); + + while (1) { + ret = iter(mtd, section, oobregion); + if (ret) + return ret; + + if (pos + oobregion->length > byte) + break; + + pos += oobregion->length; + section++; + } + + /* + * Adjust region info to make it start at the beginning at the + * 'start' ECC byte. + */ + oobregion->offset += byte - pos; + oobregion->length -= byte - pos; + *sectionp = section; + + return 0; +} + +/** + * mtd_ooblayout_find_eccregion - Find the ECC region attached to a specific + * ECC byte + * @mtd: mtd info structure + * @eccbyte: the byte we are searching for + * @sectionp: pointer where the section id will be stored + * @oobregion: OOB region information + * + * Works like mtd_ooblayout_find_region() except it searches for a specific ECC + * byte. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, + int *section, + struct mtd_oob_region *oobregion) +{ + return mtd_ooblayout_find_region(mtd, eccbyte, section, oobregion, + mtd_ooblayout_ecc); +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_find_eccregion); + +/** + * mtd_ooblayout_get_bytes - Extract OOB bytes from the oob buffer + * @mtd: mtd info structure + * @buf: destination buffer to store OOB bytes + * @oobbuf: OOB buffer + * @start: first byte to retrieve + * @nbytes: number of bytes to retrieve + * @iter: section iterator + * + * Extract bytes attached to a specific category (ECC or free) + * from the OOB buffer and copy them into buf. + * + * Returns zero on success, a negative error code otherwise. + */ +static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf, + const u8 *oobbuf, int start, int nbytes, + int (*iter)(struct mtd_info *, + int section, + struct mtd_oob_region *oobregion)) +{ + struct mtd_oob_region oobregion = { }; + int section = 0, ret; + + ret = mtd_ooblayout_find_region(mtd, start, §ion, + &oobregion, iter); + + while (!ret) { + int cnt; + + cnt = oobregion.length > nbytes ? nbytes : oobregion.length; + memcpy(buf, oobbuf + oobregion.offset, cnt); + buf += cnt; + nbytes -= cnt; + + if (!nbytes) + break; + + ret = iter(mtd, ++section, &oobregion); + } + + return ret; +} + +/** + * mtd_ooblayout_set_bytes - put OOB bytes into the oob buffer + * @mtd: mtd info structure + * @buf: source buffer to get OOB bytes from + * @oobbuf: OOB buffer + * @start: first OOB byte to set + * @nbytes: number of OOB bytes to set + * @iter: section iterator + * + * Fill the OOB buffer with data provided in buf. The category (ECC or free) + * is selected by passing the appropriate iterator. + * + * Returns zero on success, a negative error code otherwise. + */ +static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf, + u8 *oobbuf, int start, int nbytes, + int (*iter)(struct mtd_info *, + int section, + struct mtd_oob_region *oobregion)) +{ + struct mtd_oob_region oobregion = { }; + int section = 0, ret; + + ret = mtd_ooblayout_find_region(mtd, start, §ion, + &oobregion, iter); + + while (!ret) { + int cnt; + + cnt = oobregion.length > nbytes ? nbytes : oobregion.length; + memcpy(oobbuf + oobregion.offset, buf, cnt); + buf += cnt; + nbytes -= cnt; + + if (!nbytes) + break; + + ret = iter(mtd, ++section, &oobregion); + } + + return ret; +} + +/** + * mtd_ooblayout_count_bytes - count the number of bytes in a OOB category + * @mtd: mtd info structure + * @iter: category iterator + * + * Count the number of bytes in a given category. + * + * Returns a positive value on success, a negative error code otherwise. + */ +static int mtd_ooblayout_count_bytes(struct mtd_info *mtd, + int (*iter)(struct mtd_info *, + int section, + struct mtd_oob_region *oobregion)) +{ + struct mtd_oob_region oobregion = { }; + int section = 0, ret, nbytes = 0; + + while (1) { + ret = iter(mtd, section++, &oobregion); + if (ret) { + if (ret == -ERANGE) + ret = nbytes; + break; + } + + nbytes += oobregion.length; + } + + return ret; +} + +/** + * mtd_ooblayout_get_eccbytes - extract ECC bytes from the oob buffer + * @mtd: mtd info structure + * @eccbuf: destination buffer to store ECC bytes + * @oobbuf: OOB buffer + * @start: first ECC byte to retrieve + * @nbytes: number of ECC bytes to retrieve + * + * Works like mtd_ooblayout_get_bytes(), except it acts on ECC bytes. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, + const u8 *oobbuf, int start, int nbytes) +{ + return mtd_ooblayout_get_bytes(mtd, eccbuf, oobbuf, start, nbytes, + mtd_ooblayout_ecc); +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_get_eccbytes); + +/** + * mtd_ooblayout_set_eccbytes - set ECC bytes into the oob buffer + * @mtd: mtd info structure + * @eccbuf: source buffer to get ECC bytes from + * @oobbuf: OOB buffer + * @start: first ECC byte to set + * @nbytes: number of ECC bytes to set + * + * Works like mtd_ooblayout_set_bytes(), except it acts on ECC bytes. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, + u8 *oobbuf, int start, int nbytes) +{ + return mtd_ooblayout_set_bytes(mtd, eccbuf, oobbuf, start, nbytes, + mtd_ooblayout_ecc); +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_set_eccbytes); + +/** + * mtd_ooblayout_get_databytes - extract data bytes from the oob buffer + * @mtd: mtd info structure + * @databuf: destination buffer to store ECC bytes + * @oobbuf: OOB buffer + * @start: first ECC byte to retrieve + * @nbytes: number of ECC bytes to retrieve + * + * Works like mtd_ooblayout_get_bytes(), except it acts on free bytes. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, + const u8 *oobbuf, int start, int nbytes) +{ + return mtd_ooblayout_get_bytes(mtd, databuf, oobbuf, start, nbytes, + mtd_ooblayout_free); +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes); + +/** + * mtd_ooblayout_get_eccbytes - set data bytes into the oob buffer + * @mtd: mtd info structure + * @eccbuf: source buffer to get data bytes from + * @oobbuf: OOB buffer + * @start: first ECC byte to set + * @nbytes: number of ECC bytes to set + * + * Works like mtd_ooblayout_get_bytes(), except it acts on free bytes. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, + u8 *oobbuf, int start, int nbytes) +{ + return mtd_ooblayout_set_bytes(mtd, databuf, oobbuf, start, nbytes, + mtd_ooblayout_free); +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_set_databytes); + +/** + * mtd_ooblayout_count_freebytes - count the number of free bytes in OOB + * @mtd: mtd info structure + * + * Works like mtd_ooblayout_count_bytes(), except it count free bytes. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_count_freebytes(struct mtd_info *mtd) +{ + return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_free); +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_count_freebytes); + +/** + * mtd_ooblayout_count_freebytes - count the number of ECC bytes in OOB + * @mtd: mtd info structure + * + * Works like mtd_ooblayout_count_bytes(), except it count ECC bytes. + * + * Returns zero on success, a negative error code otherwise. + */ +int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd) +{ + return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_ecc); +} +EXPORT_SYMBOL_GPL(mtd_ooblayout_count_eccbytes); + /* * Method to access the protection register area, present in some flash * devices. The user data is one time programmable but the factory data is read diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index ef9fea4fc400..117ca1ff581d 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -108,6 +108,21 @@ struct nand_ecclayout { struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; }; +/** + * struct mtd_oob_region - oob region definition + * @offset: region offset + * @length: region length + * + * This structure describes a region of the OOB area, and is used + * to retrieve ECC or free bytes sections. + * Each section is defined by an offset within the OOB area and a + * length. + */ +struct mtd_oob_region { + u32 offset; + u32 length; +}; + struct module; /* only needed for owner field in mtd_info */ struct mtd_info { @@ -253,6 +268,24 @@ struct mtd_info { int usecount; }; +int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobecc); +int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, + int *section, + struct mtd_oob_region *oobregion); +int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, + const u8 *oobbuf, int start, int nbytes); +int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, + u8 *oobbuf, int start, int nbytes); +int mtd_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobfree); +int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, + const u8 *oobbuf, int start, int nbytes); +int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, + u8 *oobbuf, int start, int nbytes); +int mtd_ooblayout_count_freebytes(struct mtd_info *mtd); +int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd); + static inline void mtd_set_of_node(struct mtd_info *mtd, struct device_node *np) { -- GitLab From c2b78452a9db438d592bf72af7bb2ae3062cb922 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:10:30 +0100 Subject: [PATCH 3503/9938] mtd: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon --- drivers/mtd/mtdchar.c | 107 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 6d19835b80a9..cd64ab76dd7b 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -472,28 +472,101 @@ static int mtdchar_readoob(struct file *file, struct mtd_info *mtd, * nand_ecclayout flexibly (i.e. the struct may change size in new * releases without requiring major rewrites). */ -static int shrink_ecclayout(const struct nand_ecclayout *from, - struct nand_ecclayout_user *to) +static int shrink_ecclayout(struct mtd_info *mtd, + struct nand_ecclayout_user *to) { - int i; + struct mtd_oob_region oobregion; + int i, section = 0, ret; - if (!from || !to) + if (!mtd || !to) return -EINVAL; memset(to, 0, sizeof(*to)); - to->eccbytes = min((int)from->eccbytes, MTD_MAX_ECCPOS_ENTRIES); - for (i = 0; i < to->eccbytes; i++) - to->eccpos[i] = from->eccpos[i]; + to->eccbytes = 0; + for (i = 0; i < MTD_MAX_ECCPOS_ENTRIES;) { + u32 eccpos; + + ret = mtd_ooblayout_ecc(mtd, section, &oobregion); + if (ret < 0) { + if (ret != -ERANGE) + return ret; + + break; + } + + eccpos = oobregion.offset; + for (; i < MTD_MAX_ECCPOS_ENTRIES && + eccpos < oobregion.offset + oobregion.length; i++) { + to->eccpos[i] = eccpos++; + to->eccbytes++; + } + } for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { - if (from->oobfree[i].length == 0 && - from->oobfree[i].offset == 0) + ret = mtd_ooblayout_free(mtd, i, &oobregion); + if (ret < 0) { + if (ret != -ERANGE) + return ret; + + break; + } + + to->oobfree[i].offset = oobregion.offset; + to->oobfree[i].length = oobregion.length; + to->oobavail += to->oobfree[i].length; + } + + return 0; +} + +static int get_oobinfo(struct mtd_info *mtd, struct nand_oobinfo *to) +{ + struct mtd_oob_region oobregion; + int i, section = 0, ret; + + if (!mtd || !to) + return -EINVAL; + + memset(to, 0, sizeof(*to)); + + to->eccbytes = 0; + for (i = 0; i < ARRAY_SIZE(to->eccpos);) { + u32 eccpos; + + ret = mtd_ooblayout_ecc(mtd, section, &oobregion); + if (ret < 0) { + if (ret != -ERANGE) + return ret; + break; - to->oobavail += from->oobfree[i].length; - to->oobfree[i] = from->oobfree[i]; + } + + if (oobregion.length + i > ARRAY_SIZE(to->eccpos)) + return -EINVAL; + + eccpos = oobregion.offset; + for (; eccpos < oobregion.offset + oobregion.length; i++) { + to->eccpos[i] = eccpos++; + to->eccbytes++; + } } + for (i = 0; i < 8; i++) { + ret = mtd_ooblayout_free(mtd, i, &oobregion); + if (ret < 0) { + if (ret != -ERANGE) + return ret; + + break; + } + + to->oobfree[i][0] = oobregion.offset; + to->oobfree[i][1] = oobregion.length; + } + + to->useecc = MTD_NANDECC_AUTOPLACE; + return 0; } @@ -817,14 +890,10 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) if (!mtd->ecclayout) return -EOPNOTSUPP; - if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos)) - return -EINVAL; - oi.useecc = MTD_NANDECC_AUTOPLACE; - memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); - memcpy(&oi.oobfree, mtd->ecclayout->oobfree, - sizeof(oi.oobfree)); - oi.eccbytes = mtd->ecclayout->eccbytes; + ret = get_oobinfo(mtd, &oi); + if (ret) + return ret; if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) return -EFAULT; @@ -920,7 +989,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) if (!usrlay) return -ENOMEM; - shrink_ecclayout(mtd->ecclayout, usrlay); + shrink_ecclayout(mtd, usrlay); if (copy_to_user(argp, usrlay, sizeof(*usrlay))) ret = -EFAULT; -- GitLab From 846031d3e1837b71e350bd8098f00995069859a8 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:11:00 +0100 Subject: [PATCH 3504/9938] mtd: nand: core: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 200 +++++++++++++++-------------------- drivers/mtd/nand/nand_bch.c | 13 ++- 2 files changed, 100 insertions(+), 113 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 13fcddc8a10e..24ed4450df57 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1279,13 +1279,12 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - int i, eccsize = chip->ecc.size; + int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; - uint32_t *eccpos = chip->ecc.layout->eccpos; unsigned int max_bitflips = 0; chip->ecc.read_page_raw(mtd, chip, buf, 1, page); @@ -1293,8 +1292,10 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(mtd, p, &ecc_calc[i]); - for (i = 0; i < chip->ecc.total; i++) - ecc_code[i] = chip->oob_poi[eccpos[i]]; + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; eccsteps = chip->ecc.steps; p = buf; @@ -1326,14 +1327,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, int page) { - int start_step, end_step, num_steps; - uint32_t *eccpos = chip->ecc.layout->eccpos; + int start_step, end_step, num_steps, ret; uint8_t *p; int data_col_addr, i, gaps = 0; int datafrag_len, eccfrag_len, aligned_len, aligned_pos; int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; - int index; + int index, section = 0; unsigned int max_bitflips = 0; + struct mtd_oob_region oobregion = { }; /* Column address within the page aligned to ECC size (256bytes) */ start_step = data_offs / chip->ecc.size; @@ -1361,12 +1362,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * The performance is faster if we position offsets according to * ecc.pos. Let's make sure that there are no gaps in ECC positions. */ - for (i = 0; i < eccfrag_len - 1; i++) { - if (eccpos[i + index] + 1 != eccpos[i + index + 1]) { - gaps = 1; - break; - } - } + ret = mtd_ooblayout_find_eccregion(mtd, index, §ion, &oobregion); + if (ret) + return ret; + + if (oobregion.length < eccfrag_len) + gaps = 1; + if (gaps) { chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -1375,20 +1377,23 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * Send the command to read the particular ECC bytes take care * about buswidth alignment in read_buf. */ - aligned_pos = eccpos[index] & ~(busw - 1); + aligned_pos = oobregion.offset & ~(busw - 1); aligned_len = eccfrag_len; - if (eccpos[index] & (busw - 1)) + if (oobregion.offset & (busw - 1)) aligned_len++; - if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) + if ((oobregion.offset + (num_steps * chip->ecc.bytes)) & + (busw - 1)) aligned_len++; chip->cmdfunc(mtd, NAND_CMD_RNDOUT, - mtd->writesize + aligned_pos, -1); + mtd->writesize + aligned_pos, -1); chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); } - for (i = 0; i < eccfrag_len; i++) - chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; + ret = mtd_ooblayout_get_eccbytes(mtd, chip->buffers->ecccode, + chip->oob_poi, index, eccfrag_len); + if (ret) + return ret; p = bufpoi + data_col_addr; for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { @@ -1429,13 +1434,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - int i, eccsize = chip->ecc.size; + int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; - uint32_t *eccpos = chip->ecc.layout->eccpos; unsigned int max_bitflips = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { @@ -1445,8 +1449,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, } chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - for (i = 0; i < chip->ecc.total; i++) - ecc_code[i] = chip->oob_poi[eccpos[i]]; + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; eccsteps = chip->ecc.steps; p = buf; @@ -1491,12 +1497,11 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - int i, eccsize = chip->ecc.size; + int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *ecc_code = chip->buffers->ecccode; - uint32_t *eccpos = chip->ecc.layout->eccpos; uint8_t *ecc_calc = chip->buffers->ecccalc; unsigned int max_bitflips = 0; @@ -1505,8 +1510,10 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); - for (i = 0; i < chip->ecc.total; i++) - ecc_code[i] = chip->oob_poi[eccpos[i]]; + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; @@ -1607,14 +1614,17 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, /** * nand_transfer_oob - [INTERN] Transfer oob to client buffer - * @chip: nand chip structure + * @mtd: mtd info structure * @oob: oob destination address * @ops: oob ops structure * @len: size of oob to transfer */ -static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, +static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob, struct mtd_oob_ops *ops, size_t len) { + struct nand_chip *chip = mtd_to_nand(mtd); + int ret; + switch (ops->mode) { case MTD_OPS_PLACE_OOB: @@ -1622,31 +1632,12 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, memcpy(oob, chip->oob_poi + ops->ooboffs, len); return oob + len; - case MTD_OPS_AUTO_OOB: { - struct nand_oobfree *free = chip->ecc.layout->oobfree; - uint32_t boffs = 0, roffs = ops->ooboffs; - size_t bytes = 0; - - for (; free->length && len; free++, len -= bytes) { - /* Read request not from offset 0? */ - if (unlikely(roffs)) { - if (roffs >= free->length) { - roffs -= free->length; - continue; - } - boffs = free->offset + roffs; - bytes = min_t(size_t, len, - (free->length - roffs)); - roffs = 0; - } else { - bytes = min_t(size_t, len, free->length); - boffs = free->offset; - } - memcpy(oob, chip->oob_poi + boffs, bytes); - oob += bytes; - } - return oob; - } + case MTD_OPS_AUTO_OOB: + ret = mtd_ooblayout_get_databytes(mtd, oob, chip->oob_poi, + ops->ooboffs, len); + BUG_ON(ret); + return oob + len; + default: BUG(); } @@ -1780,7 +1771,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, int toread = min(oobreadlen, max_oobsize); if (toread) { - oob = nand_transfer_oob(chip, + oob = nand_transfer_oob(mtd, oob, ops, toread); oobreadlen -= toread; } @@ -2080,7 +2071,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, break; len = min(len, readlen); - buf = nand_transfer_oob(chip, buf, ops, len); + buf = nand_transfer_oob(mtd, buf, ops, len); if (chip->options & NAND_NEED_READRDY) { /* Apply delay or wait for ready/busy pin */ @@ -2239,19 +2230,20 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - int i, eccsize = chip->ecc.size; + int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *ecc_calc = chip->buffers->ecccalc; const uint8_t *p = buf; - uint32_t *eccpos = chip->ecc.layout->eccpos; /* Software ECC calculation */ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(mtd, p, &ecc_calc[i]); - for (i = 0; i < chip->ecc.total; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; + ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; return chip->ecc.write_page_raw(mtd, chip, buf, 1, page); } @@ -2268,12 +2260,11 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - int i, eccsize = chip->ecc.size; + int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *ecc_calc = chip->buffers->ecccalc; const uint8_t *p = buf; - uint32_t *eccpos = chip->ecc.layout->eccpos; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_WRITE); @@ -2281,8 +2272,10 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, chip->ecc.calculate(mtd, p, &ecc_calc[i]); } - for (i = 0; i < chip->ecc.total; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; + ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -2310,11 +2303,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, int ecc_size = chip->ecc.size; int ecc_bytes = chip->ecc.bytes; int ecc_steps = chip->ecc.steps; - uint32_t *eccpos = chip->ecc.layout->eccpos; uint32_t start_step = offset / ecc_size; uint32_t end_step = (offset + data_len - 1) / ecc_size; int oob_bytes = mtd->oobsize / ecc_steps; - int step, i; + int step, ret; for (step = 0; step < ecc_steps; step++) { /* configure controller for WRITE access */ @@ -2342,8 +2334,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, /* copy calculated ECC for whole page to chip->buffer->oob */ /* this include masked-value(0xFF) for unwritten subpages */ ecc_calc = chip->buffers->ecccalc; - for (i = 0; i < chip->ecc.total; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; + ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; /* write OOB buffer to NAND device */ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -2480,6 +2474,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, struct mtd_oob_ops *ops) { struct nand_chip *chip = mtd_to_nand(mtd); + int ret; /* * Initialise to all 0xFF, to avoid the possibility of left over OOB @@ -2494,31 +2489,12 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, memcpy(chip->oob_poi + ops->ooboffs, oob, len); return oob + len; - case MTD_OPS_AUTO_OOB: { - struct nand_oobfree *free = chip->ecc.layout->oobfree; - uint32_t boffs = 0, woffs = ops->ooboffs; - size_t bytes = 0; - - for (; free->length && len; free++, len -= bytes) { - /* Write request not from offset 0? */ - if (unlikely(woffs)) { - if (woffs >= free->length) { - woffs -= free->length; - continue; - } - boffs = free->offset + woffs; - bytes = min_t(size_t, len, - (free->length - woffs)); - woffs = 0; - } else { - bytes = min_t(size_t, len, free->length); - boffs = free->offset; - } - memcpy(chip->oob_poi + boffs, oob, bytes); - oob += bytes; - } - return oob; - } + case MTD_OPS_AUTO_OOB: + ret = mtd_ooblayout_set_databytes(mtd, oob, chip->oob_poi, + ops->ooboffs, len); + BUG_ON(ret); + return oob + len; + default: BUG(); } @@ -4105,7 +4081,6 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd) */ int nand_scan_tail(struct mtd_info *mtd) { - int i; struct nand_chip *chip = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_buffers *nbuf; @@ -4309,20 +4284,10 @@ int nand_scan_tail(struct mtd_info *mtd) if (!ecc->write_oob_raw) ecc->write_oob_raw = ecc->write_oob; - /* - * The number of bytes available for a client to place data into - * the out of band area. - */ - mtd->oobavail = 0; - if (ecc->layout) { - for (i = 0; ecc->layout->oobfree[i].length; i++) - mtd->oobavail += ecc->layout->oobfree[i].length; - } - - /* ECC sanity check: warn if it's too weak */ - if (!nand_ecc_strength_good(mtd)) - pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", - mtd->name); + /* propagate ecc info to mtd_info */ + mtd->ecclayout = ecc->layout; + mtd->ecc_strength = ecc->strength; + mtd->ecc_step_size = ecc->size; /* * Set the number of read / write steps for one page depending on ECC @@ -4336,6 +4301,21 @@ int nand_scan_tail(struct mtd_info *mtd) } ecc->total = ecc->steps * ecc->bytes; + /* + * The number of bytes available for a client to place data into + * the out of band area. + */ + ret = mtd_ooblayout_count_freebytes(mtd); + if (ret < 0) + ret = 0; + + mtd->oobavail = ret; + + /* ECC sanity check: warn if it's too weak */ + if (!nand_ecc_strength_good(mtd)) + pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", + mtd->name); + /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { switch (ecc->steps) { @@ -4392,10 +4372,6 @@ int nand_scan_tail(struct mtd_info *mtd) mtd->_block_markbad = nand_block_markbad; mtd->writebufsize = mtd->writesize; - /* propagate ecc info to mtd_info */ - mtd->ecclayout = ecc->layout; - mtd->ecc_strength = ecc->strength; - mtd->ecc_step_size = ecc->size; /* * Initialize bitflip_threshold to its default prior scan_bbt() call. * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index b585bae37929..d8c03ebb62dc 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -196,7 +196,18 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) printk(KERN_WARNING "eccsize %u is too large\n", eccsize); goto fail; } - if (layout->eccbytes != (eccsteps*eccbytes)) { + + /* + * ecc->steps and ecc->total might be used by mtd->ooblayout->ecc(), + * which is called by mtd_ooblayout_count_eccbytes(). + * Make sure they are properly initialized before calling + * mtd_ooblayout_count_eccbytes(). + * FIXME: we should probaly rework the sequencing in nand_scan_tail() + * to avoid setting those fields twice. + */ + nand->ecc.steps = eccsteps; + nand->ecc.total = eccsteps * eccbytes; + if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) { printk(KERN_WARNING "invalid ecc layout\n"); goto fail; } -- GitLab From 78d28e8ec4fbd4d1e0c375d7a28f4f23e9e7b15e Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:11:14 +0100 Subject: [PATCH 3505/9938] mtd: nand: atmel: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon Reviewed-by: Nicolas Ferre --- drivers/mtd/nand/atmel_nand.c | 50 ++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 5e716f2a8739..b132c8fd3701 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -833,13 +833,16 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", pos, bit_pos, err_byte, *(buf + byte_pos)); } else { + struct mtd_oob_region oobregion; + /* Bit flip in OOB area */ tmp = sector_num * nand_chip->ecc.bytes + (byte_pos - sector_size); err_byte = ecc[tmp]; ecc[tmp] ^= (1 << bit_pos); - pos = tmp + nand_chip->ecc.layout->eccpos[0]; + mtd_ooblayout_ecc(mtd, 0, &oobregion); + pos = tmp + oobregion.offset; dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", pos, bit_pos, err_byte, ecc[tmp]); } @@ -931,7 +934,6 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, struct atmel_nand_host *host = nand_get_controller_data(chip); int eccsize = chip->ecc.size * chip->ecc.steps; uint8_t *oob = chip->oob_poi; - uint32_t *eccpos = chip->ecc.layout->eccpos; uint32_t stat; unsigned long end_time; int bitflips = 0; @@ -953,7 +955,11 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, stat = pmecc_readl_relaxed(host->ecc, ISR); if (stat != 0) { - bitflips = pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]); + struct mtd_oob_region oobregion; + + mtd_ooblayout_ecc(mtd, 0, &oobregion); + bitflips = pmecc_correction(mtd, stat, buf, + &oob[oobregion.offset]); if (bitflips < 0) /* uncorrectable errors */ return 0; @@ -967,8 +973,8 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, int page) { struct atmel_nand_host *host = nand_get_controller_data(chip); - uint32_t *eccpos = chip->ecc.layout->eccpos; - int i, j; + struct mtd_oob_region oobregion = { }; + int i, j, section = 0; unsigned long end_time; if (!host->nfc || !host->nfc->write_by_sram) { @@ -987,11 +993,14 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, for (i = 0; i < chip->ecc.steps; i++) { for (j = 0; j < chip->ecc.bytes; j++) { - int pos; + if (!oobregion.length) + mtd_ooblayout_ecc(mtd, section, &oobregion); - pos = i * chip->ecc.bytes + j; - chip->oob_poi[eccpos[pos]] = + chip->oob_poi[oobregion.offset] = pmecc_readb_ecc_relaxed(host->ecc, i, j); + oobregion.length--; + oobregion.offset++; + section++; } } chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -1005,6 +1014,7 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) struct atmel_nand_host *host = nand_get_controller_data(nand_chip); uint32_t val = 0; struct nand_ecclayout *ecc_layout; + struct mtd_oob_region oobregion; pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); @@ -1056,9 +1066,10 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) ecc_layout = nand_chip->ecc.layout; pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1); - pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]); + mtd_ooblayout_ecc(mtd, 0, &oobregion); + pmecc_writel(host->ecc, SADDR, oobregion.offset); pmecc_writel(host->ecc, EADDR, - ecc_layout->eccpos[ecc_layout->eccbytes - 1]); + oobregion.offset + ecc_layout->eccbytes - 1); /* See datasheet about PMECC Clock Control Register */ pmecc_writel(host->ecc, CLK, 2); pmecc_writel(host->ecc, IDR, 0xff); @@ -1359,12 +1370,12 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; - uint32_t *eccpos = chip->ecc.layout->eccpos; uint8_t *p = buf; uint8_t *oob = chip->oob_poi; uint8_t *ecc_pos; int stat; unsigned int max_bitflips = 0; + struct mtd_oob_region oobregion = {}; /* * Errata: ALE is incorrectly wired up to the ECC controller @@ -1382,19 +1393,20 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, p, eccsize); /* move to ECC position if needed */ - if (eccpos[0] != 0) { - /* This only works on large pages - * because the ECC controller waits for - * NAND_CMD_RNDOUTSTART after the - * NAND_CMD_RNDOUT. - * anyway, for small pages, the eccpos[0] == 0 + mtd_ooblayout_ecc(mtd, 0, &oobregion); + if (oobregion.offset != 0) { + /* + * This only works on large pages because the ECC controller + * waits for NAND_CMD_RNDOUTSTART after the NAND_CMD_RNDOUT. + * Anyway, for small pages, the first ECC byte is at offset + * 0 in the OOB area. */ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, - mtd->writesize + eccpos[0], -1); + mtd->writesize + oobregion.offset, -1); } /* the ECC controller needs to read the ECC just after the data */ - ecc_pos = oob + eccpos[0]; + ecc_pos = oob + oobregion.offset; chip->read_buf(mtd, ecc_pos, eccbytes); /* check if there's an error */ -- GitLab From 9ed92dd29015de67041cf45f364a46f1fa84bf79 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:11:32 +0100 Subject: [PATCH 3506/9938] mtd: nand: fsl_ifc: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/fsl_ifc_nand.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index f8a016f038cd..1d922a0f7436 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -257,18 +257,22 @@ static int is_blank(struct mtd_info *mtd, unsigned int bufnum) u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2); u32 __iomem *mainarea = (u32 __iomem *)addr; u8 __iomem *oob = addr + mtd->writesize; - int i; + struct mtd_oob_region oobregion = { }; + int i, section = 0; for (i = 0; i < mtd->writesize / 4; i++) { if (__raw_readl(&mainarea[i]) != 0xffffffff) return 0; } - for (i = 0; i < chip->ecc.layout->eccbytes; i++) { - int pos = chip->ecc.layout->eccpos[i]; + mtd_ooblayout_ecc(mtd, section++, &oobregion); + while (oobregion.length) { + for (i = 0; i < oobregion.length; i++) { + if (__raw_readb(&oob[oobregion.offset + i]) != 0xff) + return 0; + } - if (__raw_readb(&oob[pos]) != 0xff) - return 0; + mtd_ooblayout_ecc(mtd, section++, &oobregion); } return 1; -- GitLab From 191a82946a99fe110814860873cdfe64170c660b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:11:44 +0100 Subject: [PATCH 3507/9938] mtd: nand: gpmi: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index dcb60b0fe5eb..4721008e0289 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1328,18 +1328,19 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, static int gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct nand_oobfree *of = mtd->ecclayout->oobfree; + struct mtd_oob_region of = { }; int status = 0; /* Do we have available oob area? */ - if (!of->length) + mtd_ooblayout_free(mtd, 0, &of); + if (!of.length) return -EPERM; if (!nand_is_slc(chip)) return -EPERM; - chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of->offset, page); - chip->write_buf(mtd, chip->oob_poi + of->offset, of->length); + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of.offset, page); + chip->write_buf(mtd, chip->oob_poi + of.offset, of.length); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); status = chip->waitfunc(mtd, chip); -- GitLab From b9c0f65feab8a6dd4f37fdd8150cf5fe716304f5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:12:04 +0100 Subject: [PATCH 3508/9938] mtd: nand: lpc32xx: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/lpc32xx_slc.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 3b8f3735f3e8..10cf8e6223bc 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -604,7 +604,8 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, int oob_required, int page) { struct lpc32xx_nand_host *host = nand_get_controller_data(chip); - int stat, i, status; + struct mtd_oob_region oobregion = { }; + int stat, i, status, error; uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE]; /* Issue read command */ @@ -620,7 +621,11 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, lpc32xx_slc_ecc_copy(tmpecc, (uint32_t *) host->ecc_buf, chip->ecc.steps); /* Pointer to ECC data retrieved from NAND spare area */ - oobecc = chip->oob_poi + chip->ecc.layout->eccpos[0]; + error = mtd_ooblayout_ecc(mtd, 0, &oobregion); + if (error) + return error; + + oobecc = chip->oob_poi + oobregion.offset; for (i = 0; i < chip->ecc.steps; i++) { stat = chip->ecc.correct(mtd, buf, oobecc, @@ -666,7 +671,8 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd, int oob_required, int page) { struct lpc32xx_nand_host *host = nand_get_controller_data(chip); - uint8_t *pb = chip->oob_poi + chip->ecc.layout->eccpos[0]; + struct mtd_oob_region oobregion = { }; + uint8_t *pb; int error; /* Write data, calculate ECC on outbound data */ @@ -678,6 +684,11 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd, * The calculated ECC needs some manual work done to it before * committing it to NAND. Process the calculated ECC and place * the resultant values directly into the OOB buffer. */ + error = mtd_ooblayout_ecc(mtd, 0, &oobregion); + if (error) + return error; + + pb = chip->oob_poi + oobregion.offset; lpc32xx_slc_ecc_copy(pb, (uint32_t *)host->ecc_buf, chip->ecc.steps); /* Write ECC data to device */ -- GitLab From 8cfc1e8b68f3e0b144f17a94709c757c6db05b82 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:12:19 +0100 Subject: [PATCH 3509/9938] mtd: nand: omap2: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/omap2.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c59bc85009d7..38fe6b8a0b14 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1498,9 +1498,8 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - int i; + int ret; uint8_t *ecc_calc = chip->buffers->ecccalc; - uint32_t *eccpos = chip->ecc.layout->eccpos; /* Enable GPMC ecc engine */ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); @@ -1511,8 +1510,10 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, /* Update ecc vector from GPMC result registers */ chip->ecc.calculate(mtd, buf, &ecc_calc[0]); - for (i = 0; i < chip->ecc.total; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; + ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; /* Write ecc vector to OOB area */ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -1539,10 +1540,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, { uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; - uint32_t *eccpos = chip->ecc.layout->eccpos; - uint8_t *oob = &chip->oob_poi[eccpos[0]]; - uint32_t oob_pos = mtd->writesize + chip->ecc.layout->eccpos[0]; - int stat; + int stat, ret; unsigned int max_bitflips = 0; /* Enable GPMC ecc engine */ @@ -1552,13 +1550,18 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, buf, mtd->writesize); /* Read oob bytes */ - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1); - chip->read_buf(mtd, oob, chip->ecc.total); + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, + mtd->writesize + BADBLOCK_MARKER_LENGTH, -1); + chip->read_buf(mtd, chip->oob_poi + BADBLOCK_MARKER_LENGTH, + chip->ecc.total); /* Calculate ecc bytes */ chip->ecc.calculate(mtd, buf, ecc_calc); - memcpy(ecc_code, &chip->oob_poi[eccpos[0]], chip->ecc.total); + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc); -- GitLab From aa02fcf555c8d42836584783288b33a2a0d40481 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 18 Mar 2016 17:53:31 +0100 Subject: [PATCH 3510/9938] mtd: nand: qcom: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to ecclayout fields, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon Tested-by: Archit Taneja --- drivers/mtd/nand/qcom_nandc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index f3de983475db..4ea2cb771191 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -1436,7 +1436,6 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; u8 *oob = chip->oob_poi; - int free_boff; int data_size, oob_size; int ret, status = 0; @@ -1450,12 +1449,11 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, /* calculate the data and oob size for the last codeword/step */ data_size = ecc->size - ((ecc->steps - 1) << 2); - oob_size = ecc->steps << 2; - - free_boff = ecc->layout->oobfree[0].offset; + oob_size = mtd->oobavail; /* override new oob content to last codeword */ - memcpy(nandc->data_buffer + data_size, oob + free_boff, oob_size); + mtd_ooblayout_get_databytes(mtd, nandc->data_buffer + data_size, oob, + 0, mtd->oobavail); set_address(host, host->cw_size * (ecc->steps - 1), page); update_rw_regs(host, 1, false); -- GitLab From d30aae6d5630c27fa461f9da9ba2f40ae59e3287 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:12:31 +0100 Subject: [PATCH 3511/9938] mtd: onenand: use mtd_ooblayout_xxx() helpers where appropriate The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon --- drivers/mtd/onenand/onenand_base.c | 75 ++++++------------------------ 1 file changed, 15 insertions(+), 60 deletions(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index af28bb3ae7cf..20fdf8cceae9 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1024,34 +1024,15 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col int thislen) { struct onenand_chip *this = mtd->priv; - struct nand_oobfree *free; - int readcol = column; - int readend = column + thislen; - int lastgap = 0; - unsigned int i; - uint8_t *oob_buf = this->oob_buf; - - free = this->ecclayout->oobfree; - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { - if (readcol >= lastgap) - readcol += free->offset - lastgap; - if (readend >= lastgap) - readend += free->offset - lastgap; - lastgap = free->offset + free->length; - } - this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); - free = this->ecclayout->oobfree; - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { - int free_end = free->offset + free->length; - if (free->offset < readend && free_end > readcol) { - int st = max_t(int,free->offset,readcol); - int ed = min_t(int,free_end,readend); - int n = ed - st; - memcpy(buf, oob_buf + st, n); - buf += n; - } else if (column == 0) - break; - } + int ret; + + this->read_bufferram(mtd, ONENAND_SPARERAM, this->oob_buf, 0, + mtd->oobsize); + ret = mtd_ooblayout_get_databytes(mtd, buf, this->oob_buf, + column, thislen); + if (ret) + return ret; + return 0; } @@ -1808,34 +1789,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len, static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf, const u_char *buf, int column, int thislen) { - struct onenand_chip *this = mtd->priv; - struct nand_oobfree *free; - int writecol = column; - int writeend = column + thislen; - int lastgap = 0; - unsigned int i; - - free = this->ecclayout->oobfree; - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { - if (writecol >= lastgap) - writecol += free->offset - lastgap; - if (writeend >= lastgap) - writeend += free->offset - lastgap; - lastgap = free->offset + free->length; - } - free = this->ecclayout->oobfree; - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { - int free_end = free->offset + free->length; - if (free->offset < writeend && free_end > writecol) { - int st = max_t(int,free->offset,writecol); - int ed = min_t(int,free_end,writeend); - int n = ed - st; - memcpy(oob_buf + st, buf, n); - buf += n; - } else if (column == 0) - break; - } - return 0; + return mtd_ooblayout_set_databytes(mtd, buf, oob_buf, column, thislen); } /** @@ -4037,10 +3991,11 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) * The number of bytes available for a client to place data into * the out of band area */ - mtd->oobavail = 0; - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && - this->ecclayout->oobfree[i].length; i++) - mtd->oobavail += this->ecclayout->oobfree[i].length; + ret = mtd_ooblayout_count_freebytes(mtd); + if (ret < 0) + ret = 0; + + mtd->oobavail = ret; mtd->ecclayout = this->ecclayout; mtd->ecc_strength = 1; -- GitLab From 036d6543f85319ffe96afad6de73d3a220917a63 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 18:53:44 +0100 Subject: [PATCH 3512/9938] mtd: add mtd_set_ecclayout() helper function Add an mtd_set_ecclayout() helper function to avoid direct accesses to the mtd->ecclayout field. This will ease future reworks of ECC layout definition. Signed-off-by: Boris Brezillon --- include/linux/mtd/mtd.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 117ca1ff581d..e62da8462493 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -286,6 +286,12 @@ int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, int mtd_ooblayout_count_freebytes(struct mtd_info *mtd); int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd); +static inline void mtd_set_ecclayout(struct mtd_info *mtd, + struct nand_ecclayout *ecclayout) +{ + mtd->ecclayout = ecclayout; +} + static inline void mtd_set_of_node(struct mtd_info *mtd, struct device_node *np) { -- GitLab From f6a6da179308356cac0f1dde979b67094437ef16 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:13:26 +0100 Subject: [PATCH 3513/9938] mtd: use mtd_set_ecclayout() where appropriate Use the mtd_set_ecclayout() helper instead of directly assigning the mtd->ecclayout field. Signed-off-by: Boris Brezillon --- drivers/mtd/mtdconcat.c | 2 +- drivers/mtd/mtdpart.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 239a8c806b67..481565e5fbaa 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -777,7 +777,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c } - concat->mtd.ecclayout = subdev[0]->ecclayout; + mtd_set_ecclayout(&concat->mtd, subdev[0]->ecclayout); concat->num_subdev = num_devs; concat->mtd.name = name; diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 08de4b2cf0f5..f53d9d72b23a 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -533,7 +533,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, part->name); } - slave->mtd.ecclayout = master->ecclayout; + mtd_set_ecclayout(&slave->mtd, master->ecclayout); slave->mtd.ecc_step_size = master->ecc_step_size; slave->mtd.ecc_strength = master->ecc_strength; slave->mtd.bitflip_threshold = master->bitflip_threshold; -- GitLab From 70d105e4eec233d8f8758d604bfe6c411b6ded5f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:13:50 +0100 Subject: [PATCH 3514/9938] mtd: nand: use mtd_set_ecclayout() where appropriate Use the mtd_set_ecclayout() helper instead of directly assigning the mtd->ecclayout field. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 24ed4450df57..feb1448e9dd6 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4285,7 +4285,7 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->write_oob_raw = ecc->write_oob; /* propagate ecc info to mtd_info */ - mtd->ecclayout = ecc->layout; + mtd_set_ecclayout(mtd, ecc->layout); mtd->ecc_strength = ecc->strength; mtd->ecc_step_size = ecc->size; -- GitLab From eb8c2be581e0f6c98830bc9eee09905f9fefed32 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:14:03 +0100 Subject: [PATCH 3515/9938] mtd: onenand: use mtd_set_ecclayout() where appropriate Use the mtd_set_ecclayout() helper instead of directly assigning the mtd->ecclayout field. Signed-off-by: Boris Brezillon --- drivers/mtd/onenand/onenand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 20fdf8cceae9..d0fa505d40bd 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -3997,7 +3997,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) mtd->oobavail = ret; - mtd->ecclayout = this->ecclayout; + mtd_set_ecclayout(mtd, this->ecclayout); mtd->ecc_strength = 1; /* Fill in remaining MTD driver data */ -- GitLab From 06af3b023c016bf97e39fbe22087b1d974f9e474 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 20:14:14 +0100 Subject: [PATCH 3516/9938] mtd: docg3: use mtd_set_ecclayout() where appropriate Use the mtd_set_ecclayout() helper instead of directly assigning the mtd->ecclayout field. Signed-off-by: Boris Brezillon Acked-by: Robert Jarzmik --- drivers/mtd/devices/docg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index e7b2e439696c..6b516e14264b 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -1857,7 +1857,7 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) mtd->_read_oob = doc_read_oob; mtd->_write_oob = doc_write_oob; mtd->_block_isbad = doc_block_isbad; - mtd->ecclayout = &docg3_oobinfo; + mtd_set_ecclayout(mtd, &docg3_oobinfo); mtd->oobavail = 8; mtd->ecc_strength = DOC_ECC_BCH_T; -- GitLab From adbbc3bc827eb1f43a932d783f09ba55c8ec8379 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 19:01:31 +0100 Subject: [PATCH 3517/9938] mtd: create an mtd_ooblayout_ops struct to ease ECC layout definition ECC layout definitions are currently exposed using the nand_ecclayout struct which embeds oobfree and eccpos arrays with predefined size. This approach was acceptable when NAND chips were providing relatively small OOB regions, but MLC and TLC now provide OOB regions of several hundreds of bytes, which implies a non negligible overhead for everybody even those who only need to support legacy NANDs. Create an mtd_ooblayout_ops interface providing the same functionality (expose the ECC and oobfree layout) without the need for this huge structure. The mtd->ecclayout is now deprecated and should be replaced by the equivalent mtd_ooblayout_ops. In the meantime we provide a wrapper around the ->ecclayout field to ease migration to this new model. Signed-off-by: Boris Brezillon --- drivers/mtd/mtdchar.c | 4 +- drivers/mtd/mtdconcat.c | 2 +- drivers/mtd/mtdcore.c | 165 +++++++++++++++++++++++++++++----------- drivers/mtd/mtdpart.c | 23 +++++- include/linux/mtd/mtd.h | 32 +++++++- 5 files changed, 174 insertions(+), 52 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index cd64ab76dd7b..3fad2c7425b0 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -888,7 +888,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) { struct nand_oobinfo oi; - if (!mtd->ecclayout) + if (!mtd->ooblayout) return -EOPNOTSUPP; ret = get_oobinfo(mtd, &oi); @@ -982,7 +982,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) { struct nand_ecclayout_user *usrlay; - if (!mtd->ecclayout) + if (!mtd->ooblayout) return -EOPNOTSUPP; usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL); diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 481565e5fbaa..d573606b91c2 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -777,7 +777,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c } - mtd_set_ecclayout(&concat->mtd, subdev[0]->ecclayout); + mtd_set_ooblayout(&concat->mtd, subdev[0]->ooblayout); concat->num_subdev = num_devs; concat->mtd.name = name; diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 0290c41e44fc..134ed2f7b919 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1035,49 +1035,15 @@ EXPORT_SYMBOL_GPL(mtd_write_oob); int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobecc) { - int eccbyte = 0, cursection = 0, length = 0, eccpos = 0; - memset(oobecc, 0, sizeof(*oobecc)); if (!mtd || section < 0) return -EINVAL; - if (!mtd->ecclayout) + if (!mtd->ooblayout || !mtd->ooblayout->ecc) return -ENOTSUPP; - /* - * This logic allows us to reuse the ->ecclayout information and - * expose them as ECC regions (as done for the OOB free regions). - * - * TODO: this should be dropped as soon as we get rid of the - * ->ecclayout field. - */ - for (eccbyte = 0; eccbyte < mtd->ecclayout->eccbytes; eccbyte++) { - eccpos = mtd->ecclayout->eccpos[eccbyte]; - - if (eccbyte < mtd->ecclayout->eccbytes - 1) { - int neccpos = mtd->ecclayout->eccpos[eccbyte + 1]; - - if (eccpos + 1 == neccpos) { - length++; - continue; - } - } - - if (section == cursection) - break; - - length = 0; - cursection++; - } - - if (cursection != section || eccbyte >= mtd->ecclayout->eccbytes) - return -ERANGE; - - oobecc->length = length + 1; - oobecc->offset = eccpos - length; - - return 0; + return mtd->ooblayout->ecc(mtd, section, oobecc); } EXPORT_SYMBOL_GPL(mtd_ooblayout_ecc); @@ -1106,16 +1072,10 @@ int mtd_ooblayout_free(struct mtd_info *mtd, int section, if (!mtd || section < 0) return -EINVAL; - if (!mtd->ecclayout) + if (!mtd->ooblayout || !mtd->ooblayout->free) return -ENOTSUPP; - if (section >= MTD_MAX_OOBFREE_ENTRIES_LARGE) - return -ERANGE; - - oobfree->offset = mtd->ecclayout->oobfree[section].offset; - oobfree->length = mtd->ecclayout->oobfree[section].length; - - return 0; + return mtd->ooblayout->free(mtd, section, oobfree); } EXPORT_SYMBOL_GPL(mtd_ooblayout_free); @@ -1416,6 +1376,123 @@ int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(mtd_ooblayout_count_eccbytes); +/** + * mtd_ecclayout_ecc - Default ooblayout_ecc iterator implementation + * @mtd: MTD device structure + * @section: ECC section. Depending on the layout you may have all the ECC + * bytes stored in a single contiguous section, or one section + * per ECC chunk (and sometime several sections for a single ECC + * ECC chunk) + * @oobecc: OOB region struct filled with the appropriate ECC position + * information + * + * This function is just a wrapper around the mtd->ecclayout field and is + * here to ease the transition to the mtd_ooblayout_ops approach. + * All it does is convert the layout->eccpos information into proper oob + * region definitions. + * + * Returns zero on success, a negative error code otherwise. + */ +static int mtd_ecclayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobecc) +{ + int eccbyte = 0, cursection = 0, length = 0, eccpos = 0; + + if (!mtd->ecclayout) + return -ENOTSUPP; + + /* + * This logic allows us to reuse the ->ecclayout information and + * expose them as ECC regions (as done for the OOB free regions). + * + * TODO: this should be dropped as soon as we get rid of the + * ->ecclayout field. + */ + for (eccbyte = 0; eccbyte < mtd->ecclayout->eccbytes; eccbyte++) { + eccpos = mtd->ecclayout->eccpos[eccbyte]; + + if (eccbyte < mtd->ecclayout->eccbytes - 1) { + int neccpos = mtd->ecclayout->eccpos[eccbyte + 1]; + + if (eccpos + 1 == neccpos) { + length++; + continue; + } + } + + if (section == cursection) + break; + + length = 0; + cursection++; + } + + if (cursection != section || eccbyte >= mtd->ecclayout->eccbytes) + return -ERANGE; + + oobecc->length = length + 1; + oobecc->offset = eccpos - length; + + return 0; +} + +/** + * mtd_ecclayout_ecc - Default ooblayout_free iterator implementation + * @mtd: MTD device structure + * @section: Free section. Depending on the layout you may have all the free + * bytes stored in a single contiguous section, or one section + * per ECC chunk (and sometime several sections for a single ECC + * ECC chunk) + * @oobfree: OOB region struct filled with the appropriate free position + * information + * + * This function is just a wrapper around the mtd->ecclayout field and is + * here to ease the transition to the mtd_ooblayout_ops approach. + * All it does is convert the layout->oobfree information into proper oob + * region definitions. + * + * Returns zero on success, a negative error code otherwise. + */ +static int mtd_ecclayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobfree) +{ + struct nand_ecclayout *layout = mtd->ecclayout; + + if (!layout) + return -ENOTSUPP; + + if (section >= MTD_MAX_OOBFREE_ENTRIES_LARGE || + !layout->oobfree[section].length) + return -ERANGE; + + oobfree->offset = layout->oobfree[section].offset; + oobfree->length = layout->oobfree[section].length; + + return 0; +} + +static const struct mtd_ooblayout_ops mtd_ecclayout_wrapper_ops = { + .ecc = mtd_ecclayout_ecc, + .free = mtd_ecclayout_free, +}; + +/** + * mtd_set_ecclayout - Attach an ecclayout to an MTD device + * @mtd: MTD device structure + * @ecclayout: The ecclayout to attach to the device + * + * Returns zero on success, a negative error code otherwise. + */ +void mtd_set_ecclayout(struct mtd_info *mtd, struct nand_ecclayout *ecclayout) +{ + if (!mtd || !ecclayout) + return; + + mtd->ecclayout = ecclayout; + mtd_set_ooblayout(mtd, &mtd_ecclayout_wrapper_ops); +} +EXPORT_SYMBOL_GPL(mtd_set_ecclayout); + /* * Method to access the protection register area, present in some flash * devices. The user data is one time programmable but the factory data is read diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index f53d9d72b23a..1f13e32556f8 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -317,6 +317,27 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) return res; } +static int part_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct mtd_part *part = mtd_to_part(mtd); + + return mtd_ooblayout_ecc(part->master, section, oobregion); +} + +static int part_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct mtd_part *part = mtd_to_part(mtd); + + return mtd_ooblayout_free(part->master, section, oobregion); +} + +static const struct mtd_ooblayout_ops part_ooblayout_ops = { + .ecc = part_ooblayout_ecc, + .free = part_ooblayout_free, +}; + static inline void free_partition(struct mtd_part *p) { kfree(p->mtd.name); @@ -533,7 +554,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, part->name); } - mtd_set_ecclayout(&slave->mtd, master->ecclayout); + mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops); slave->mtd.ecc_step_size = master->ecc_step_size; slave->mtd.ecc_strength = master->ecc_strength; slave->mtd.bitflip_threshold = master->bitflip_threshold; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index e62da8462493..177bf314ad70 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -101,6 +101,9 @@ struct mtd_oob_ops { * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained * for export to user-space via the ECCGETLAYOUT ioctl. * nand_ecclayout should be expandable in the future simply by the above macros. + * + * This structure is now deprecated, you should use struct nand_ecclayout_ops + * to describe your OOB layout. */ struct nand_ecclayout { __u32 eccbytes; @@ -123,6 +126,22 @@ struct mtd_oob_region { u32 length; }; +/* + * struct mtd_ooblayout_ops - NAND OOB layout operations + * @ecc: function returning an ECC region in the OOB area. + * Should return -ERANGE if %section exceeds the total number of + * ECC sections. + * @free: function returning a free region in the OOB area. + * Should return -ERANGE if %section exceeds the total number of + * free sections. + */ +struct mtd_ooblayout_ops { + int (*ecc)(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobecc); + int (*free)(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobfree); +}; + struct module; /* only needed for owner field in mtd_info */ struct mtd_info { @@ -181,9 +200,12 @@ struct mtd_info { const char *name; int index; - /* ECC layout structure pointer - read only! */ + /* [Deprecated] ECC layout structure pointer - read only! */ struct nand_ecclayout *ecclayout; + /* OOB layout description */ + const struct mtd_ooblayout_ops *ooblayout; + /* the ecc step size. */ unsigned int ecc_step_size; @@ -286,10 +308,12 @@ int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, int mtd_ooblayout_count_freebytes(struct mtd_info *mtd); int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd); -static inline void mtd_set_ecclayout(struct mtd_info *mtd, - struct nand_ecclayout *ecclayout) +void mtd_set_ecclayout(struct mtd_info *mtd, struct nand_ecclayout *ecclayout); + +static inline void mtd_set_ooblayout(struct mtd_info *mtd, + const struct mtd_ooblayout_ops *ooblayout) { - mtd->ecclayout = ecclayout; + mtd->ooblayout = ooblayout; } static inline void mtd_set_of_node(struct mtd_info *mtd, -- GitLab From 1bd0b24737710697e0a850fb1983dcdce1d01196 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 19:05:04 +0100 Subject: [PATCH 3518/9938] mtd: docg3: switch to mtd_ooblayout_ops Replace the nand_ecclayout definition by the equivalent mtd_ooblayout_ops definition. Signed-off-by: Boris Brezillon Acked-by: Robert Jarzmik --- drivers/mtd/devices/docg3.c | 46 ++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 6b516e14264b..b833e6cc684c 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -67,16 +67,40 @@ module_param(reliable_mode, uint, 0); MODULE_PARM_DESC(reliable_mode, "Set the docg3 mode (0=normal MLC, 1=fast, " "2=reliable) : MLC normal operations are in normal mode"); -/** - * struct docg3_oobinfo - DiskOnChip G3 OOB layout - * @eccbytes: 8 bytes are used (1 for Hamming ECC, 7 for BCH ECC) - * @eccpos: ecc positions (byte 7 is Hamming ECC, byte 8-14 are BCH ECC) - * @oobfree: free pageinfo bytes (byte 0 until byte 6, byte 15 - */ -static struct nand_ecclayout docg3_oobinfo = { - .eccbytes = 8, - .eccpos = {7, 8, 9, 10, 11, 12, 13, 14}, - .oobfree = {{0, 7}, {15, 1} }, +static int docg3_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + if (section) + return -ERANGE; + + /* byte 7 is Hamming ECC, byte 8-14 are BCH ECC */ + oobregion->offset = 7; + oobregion->length = 8; + + return 0; +} + +static int docg3_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + if (section > 1) + return -ERANGE; + + /* free bytes: byte 0 until byte 6, byte 15 */ + if (!section) { + oobregion->offset = 0; + oobregion->length = 7; + } else { + oobregion->offset = 15; + oobregion->length = 1; + } + + return 0; +} + +static const struct mtd_ooblayout_ops nand_ooblayout_docg3_ops = { + .ecc = docg3_ooblayout_ecc, + .free = docg3_ooblayout_free, }; static inline u8 doc_readb(struct docg3 *docg3, u16 reg) @@ -1857,7 +1881,7 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) mtd->_read_oob = doc_read_oob; mtd->_write_oob = doc_write_oob; mtd->_block_isbad = doc_block_isbad; - mtd_set_ecclayout(mtd, &docg3_oobinfo); + mtd_set_ooblayout(mtd, &nand_ooblayout_docg3_ops); mtd->oobavail = 8; mtd->ecc_strength = DOC_ECC_BCH_T; -- GitLab From 41b207a70d3a86b9e2eede155e87838234c7cbd5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Feb 2016 19:06:15 +0100 Subject: [PATCH 3519/9938] mtd: nand: implement the default mtd_ooblayout_ops Replace the default nand_ecclayout definitions for large and small page devices with the equivalent mtd_ooblayout_ops. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 142 +++++++++++++++++++++++------------ include/linux/mtd/nand.h | 3 + 2 files changed, 96 insertions(+), 49 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index feb1448e9dd6..e8332ea45739 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -47,54 +47,96 @@ #include #include +static int nand_get_device(struct mtd_info *mtd, int new_state); + +static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); + /* Define default oob placement schemes for large and small page devices */ -static struct nand_ecclayout nand_oob_8 = { - .eccbytes = 3, - .eccpos = {0, 1, 2}, - .oobfree = { - {.offset = 3, - .length = 2}, - {.offset = 6, - .length = 2} } -}; +static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; -static struct nand_ecclayout nand_oob_16 = { - .eccbytes = 6, - .eccpos = {0, 1, 2, 3, 6, 7}, - .oobfree = { - {.offset = 8, - . length = 8} } -}; + if (section > 1) + return -ERANGE; -static struct nand_ecclayout nand_oob_64 = { - .eccbytes = 24, - .eccpos = { - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63}, - .oobfree = { - {.offset = 2, - .length = 38} } -}; + if (!section) { + oobregion->offset = 0; + oobregion->length = 4; + } else { + oobregion->offset = 6; + oobregion->length = ecc->total - 4; + } -static struct nand_ecclayout nand_oob_128 = { - .eccbytes = 48, - .eccpos = { - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127}, - .oobfree = { - {.offset = 2, - .length = 78} } + return 0; +} + +static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + if (section > 1) + return -ERANGE; + + if (mtd->oobsize == 16) { + if (section) + return -ERANGE; + + oobregion->length = 8; + oobregion->offset = 8; + } else { + oobregion->length = 2; + if (!section) + oobregion->offset = 3; + else + oobregion->offset = 6; + } + + return 0; +} + +const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = { + .ecc = nand_ooblayout_ecc_sp, + .free = nand_ooblayout_free_sp, }; +EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops); -static int nand_get_device(struct mtd_info *mtd, int new_state); +static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; -static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops); + if (section) + return -ERANGE; + + oobregion->length = ecc->total; + oobregion->offset = mtd->oobsize - oobregion->length; + + return 0; +} + +static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + + if (section) + return -ERANGE; + + oobregion->length = mtd->oobsize - ecc->total - 2; + oobregion->offset = 2; + + return 0; +} + +const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = { + .ecc = nand_ooblayout_ecc_lp, + .free = nand_ooblayout_free_lp, +}; +EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) @@ -4109,22 +4151,25 @@ int nand_scan_tail(struct mtd_info *mtd) /* Set the internal oob buffer location, just after the page data */ chip->oob_poi = chip->buffers->databuf + mtd->writesize; + /* + * Set the provided ECC layout. If ecc->layout is NULL, the MTD core + * will just leave mtd->ooblayout to NULL, if it's not NULL, it will + * set ->ooblayout to the default ecclayout wrapper. + */ + mtd_set_ecclayout(mtd, ecc->layout); + /* * If no default placement scheme is given, select an appropriate one. */ - if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) { + if (!mtd->ooblayout && (ecc->mode != NAND_ECC_SOFT_BCH)) { switch (mtd->oobsize) { case 8: - ecc->layout = &nand_oob_8; - break; case 16: - ecc->layout = &nand_oob_16; + mtd_set_ooblayout(mtd, &nand_ooblayout_sp_ops); break; case 64: - ecc->layout = &nand_oob_64; - break; case 128: - ecc->layout = &nand_oob_128; + mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); break; default: WARN(1, "No oob scheme defined for oobsize %d\n", @@ -4285,7 +4330,6 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->write_oob_raw = ecc->write_oob; /* propagate ecc info to mtd_info */ - mtd_set_ecclayout(mtd, ecc->layout); mtd->ecc_strength = ecc->strength; mtd->ecc_step_size = ecc->size; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 7e06afb8552c..f2ded7b1b3b8 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -748,6 +748,9 @@ struct nand_chip { void *priv; }; +extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops; +extern const struct mtd_ooblayout_ops nand_ooblayout_lp_ops; + static inline void nand_set_flash_node(struct nand_chip *chip, struct device_node *np) { -- GitLab From 2c97165befb487c0dc8b25d39f457d0d91d22a6f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 19 Apr 2016 16:36:28 -0400 Subject: [PATCH 3520/9938] selinux: don't revalidate an inode's label when explicitly setting it There is no point in attempting to revalidate an inode's security label when we are in the process of setting it. Reported-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/hooks.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fce7dc81f2d9..f8ecc0a3c0fa 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -297,6 +297,13 @@ static struct inode_security_struct *inode_security(struct inode *inode) return inode->i_security; } +static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry) +{ + struct inode *inode = d_backing_inode(dentry); + + return inode->i_security; +} + /* * Get the security label of a dentry's backing inode. */ @@ -686,7 +693,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, struct superblock_security_struct *sbsec = sb->s_security; const char *name = sb->s_type->name; struct dentry *root = sbsec->sb->s_root; - struct inode_security_struct *root_isec = backing_inode_security(root); + struct inode_security_struct *root_isec; u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; u32 defcontext_sid = 0; char **mount_options = opts->mnt_opts; @@ -729,6 +736,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, && (num_opts == 0)) goto out; + root_isec = backing_inode_security_novalidate(root); + /* * parse the mount options, check if they are valid sids. * also check if someone is trying to mount the same sb more @@ -3222,7 +3231,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void static int selinux_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - struct inode_security_struct *isec = inode_security(inode); + struct inode_security_struct *isec = inode_security_novalidate(inode); u32 newsid; int rc; -- GitLab From 20cdef8d57591ec8674f65ccfe555aca5fd10b64 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 4 Apr 2016 14:14:42 -0400 Subject: [PATCH 3521/9938] selinux: delay inode label lookup as long as possible Since looking up an inode's label can result in revalidation, delay the lookup as long as possible to limit the performance impact. Signed-off-by: Paul Moore --- security/selinux/hooks.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f8ecc0a3c0fa..b09aad7ad423 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1790,7 +1790,6 @@ static int selinux_determine_inode_label(struct inode *dir, u32 *_new_isid) { const struct superblock_security_struct *sbsec = dir->i_sb->s_security; - const struct inode_security_struct *dsec = inode_security(dir); const struct task_security_struct *tsec = current_security(); if ((sbsec->flags & SE_SBINITIALIZED) && @@ -1800,6 +1799,7 @@ static int selinux_determine_inode_label(struct inode *dir, tsec->create_sid) { *_new_isid = tsec->create_sid; } else { + const struct inode_security_struct *dsec = inode_security(dir); return security_transition_sid(tsec->sid, dsec->sid, tclass, name, _new_isid); } @@ -2084,7 +2084,7 @@ static int selinux_binder_transfer_file(struct task_struct *from, u32 sid = task_sid(to); struct file_security_struct *fsec = file->f_security; struct dentry *dentry = file->f_path.dentry; - struct inode_security_struct *isec = backing_inode_security(dentry); + struct inode_security_struct *isec; struct common_audit_data ad; int rc; @@ -2103,6 +2103,7 @@ static int selinux_binder_transfer_file(struct task_struct *from, if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; + isec = backing_inode_security(dentry); return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), &ad); } @@ -3057,7 +3058,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct inode *inode = d_backing_inode(dentry); - struct inode_security_struct *isec = backing_inode_security(dentry); + struct inode_security_struct *isec; struct superblock_security_struct *sbsec; struct common_audit_data ad; u32 newsid, sid = current_sid(); @@ -3076,6 +3077,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = dentry; + isec = backing_inode_security(dentry); rc = avc_has_perm(sid, isec->sid, isec->sclass, FILE__RELABELFROM, &ad); if (rc) @@ -3134,7 +3136,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, int flags) { struct inode *inode = d_backing_inode(dentry); - struct inode_security_struct *isec = backing_inode_security(dentry); + struct inode_security_struct *isec; u32 newsid; int rc; @@ -3151,6 +3153,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, return; } + isec = backing_inode_security(dentry); isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sid = newsid; isec->initialized = LABEL_INITIALIZED; @@ -3192,7 +3195,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void u32 size; int error; char *context = NULL; - struct inode_security_struct *isec = inode_security(inode); + struct inode_security_struct *isec; if (strcmp(name, XATTR_SELINUX_SUFFIX)) return -EOPNOTSUPP; @@ -3211,6 +3214,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void if (!error) error = cred_has_capability(current_cred(), CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT); + isec = inode_security(inode); if (!error) error = security_sid_to_context_force(isec->sid, &context, &size); @@ -3320,7 +3324,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, struct common_audit_data ad; struct file_security_struct *fsec = file->f_security; struct inode *inode = file_inode(file); - struct inode_security_struct *isec = inode_security(inode); + struct inode_security_struct *isec; struct lsm_ioctlop_audit ioctl; u32 ssid = cred_sid(cred); int rc; @@ -3344,6 +3348,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, if (unlikely(IS_PRIVATE(inode))) return 0; + isec = inode_security(inode); rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, requested, driver, xperm, &ad); out: @@ -3745,18 +3750,18 @@ static int selinux_kernel_module_from_file(struct file *file) SYSTEM__MODULE_LOAD, NULL); /* finit_module */ + ad.type = LSM_AUDIT_DATA_PATH; ad.u.path = file->f_path; - isec = inode_security(file_inode(file)); fsec = file->f_security; - if (sid != fsec->sid) { rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); if (rc) return rc; } + isec = inode_security(file_inode(file)); return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, SYSTEM__MODULE_LOAD, &ad); } -- GitLab From 1ac42476263eec99fb2d3c31ee946cb44e80ddd5 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 18 Apr 2016 16:41:38 -0400 Subject: [PATCH 3522/9938] selinux: check ss_initialized before revalidating an inode label There is no point in trying to revalidate an inode's security label if the security server is not yet initialized. Signed-off-by: Paul Moore --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b09aad7ad423..474011c46bbd 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -259,7 +259,7 @@ static int __inode_security_revalidate(struct inode *inode, might_sleep_if(may_sleep); - if (isec->initialized != LABEL_INITIALIZED) { + if (ss_initialized && isec->initialized != LABEL_INITIALIZED) { if (!may_sleep) return -ECHILD; -- GitLab From 8bcf4525c5d43306c5fd07e132bc8650e3491aec Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 24 Mar 2016 13:03:49 -0600 Subject: [PATCH 3523/9938] PCI: Mark Intel i40e NIC INTx masking as broken All of the i40e (XL710/X710) 10/20/40GbE NICs lack support for indicating INTx is asserted via the interrupt bit in the PCI status register. The DisINTx bit in the command register is functional, causing these devices to be incorrectly detected as supporting INTx masking. Quirk them to properly indicate no INTx masking support. Device IDs copied from i40e_devids.h. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas CC: John Ronciak CC: Jesse Brandeburg --- drivers/pci/quirks.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8e678027b900..e248c2aad000 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3150,6 +3150,39 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, PCI_ANY_ID, quirk_broken_intx_masking); +/* + * Intel i40e (XL710/X710) 10/20/40GbE NICs all have broken INTx masking, + * DisINTx can be set but the interrupt status bit is non-functional. + */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1572, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1574, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1580, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1581, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1583, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1584, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1585, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1586, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1587, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1588, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1589, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x37d0, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x37d1, + quirk_broken_intx_masking); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x37d2, + quirk_broken_intx_masking); + static void quirk_no_bus_reset(struct pci_dev *dev) { dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET; -- GitLab From 5c1458478c49b905652fc002708d09369763f58f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 28 Jan 2016 16:49:24 -0800 Subject: [PATCH 3524/9938] documentation: Add documentation for RCU's major data structures This commit adds documentation for RCU's major data structures, including rcu_state, rcu_node, rcu_data, rcu_dynticks, and rcu_head. Signed-off-by: Paul E. McKenney --- .../Data-Structures/BigTreeClassicRCU.svg | 474 ++++++ .../Data-Structures/BigTreeClassicRCUBH.svg | 499 ++++++ .../BigTreeClassicRCUBHdyntick.svg | 695 +++++++++ .../BigTreePreemptRCUBHdyntick.svg | 741 +++++++++ .../BigTreePreemptRCUBHdyntickCB.svg | 858 +++++++++++ .../Data-Structures/Data-Structures.html | 1333 +++++++++++++++++ .../Data-Structures/HugeTreeClassicRCU.svg | 939 ++++++++++++ .../RCU/Design/Data-Structures/TreeLevel.svg | 828 ++++++++++ .../Design/Data-Structures/TreeMapping.svg | 305 ++++ .../Data-Structures/TreeMappingLevel.svg | 380 +++++ .../RCU/Design/Data-Structures/blkd_task.svg | 843 +++++++++++ .../RCU/Design/Data-Structures/nxtlist.svg | 396 +++++ 12 files changed, 8291 insertions(+) create mode 100644 Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg create mode 100644 Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg create mode 100644 Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg create mode 100644 Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg create mode 100644 Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg create mode 100644 Documentation/RCU/Design/Data-Structures/Data-Structures.html create mode 100644 Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg create mode 100644 Documentation/RCU/Design/Data-Structures/TreeLevel.svg create mode 100644 Documentation/RCU/Design/Data-Structures/TreeMapping.svg create mode 100644 Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg create mode 100644 Documentation/RCU/Design/Data-Structures/blkd_task.svg create mode 100644 Documentation/RCU/Design/Data-Structures/nxtlist.svg diff --git a/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg b/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg new file mode 100644 index 000000000000..727e270b11e4 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg @@ -0,0 +1,474 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + struct + + rcu_data + + CPU 0 + + struct + + rcu_data + + CPU 15 + + struct + + rcu_data + + CPU 1007 + + struct + + rcu_data + + CPU 1023 + + struct rcu_state + + struct + + rcu_node + + rcu_node + + struct + + struct + + rcu_node + + + + + + + + diff --git a/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg b/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg new file mode 100644 index 000000000000..9bbb1944f962 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg @@ -0,0 +1,499 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rcu_bh + + struct + + rcu_node + + struct + + rcu_node + + rcu_node + + struct + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct rcu_state + + rcu_sched + + + + + + + + + + + diff --git a/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg b/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg new file mode 100644 index 000000000000..21ba7823479d --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg @@ -0,0 +1,695 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rcu_bh + + struct + + rcu_node + + struct + + rcu_node + + rcu_node + + struct + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct rcu_state + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + rcu_sched + + + + + diff --git a/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg b/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg new file mode 100644 index 000000000000..15adcac036c7 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg @@ -0,0 +1,741 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rcu_bh + + struct + + rcu_node + + struct + + rcu_node + + rcu_node + + struct + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct rcu_state + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + rcu_preempt + + rcu_sched + + + + + diff --git a/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg b/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg new file mode 100644 index 000000000000..bbc3801470d0 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg @@ -0,0 +1,858 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + struct + + rcu_head + + struct + + rcu_head + + struct + + rcu_head + + rcu_sched + + rcu_bh + + struct + + rcu_node + + struct + + rcu_node + + rcu_node + + struct + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct rcu_state + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + rcu_preempt + + + + + diff --git a/Documentation/RCU/Design/Data-Structures/Data-Structures.html b/Documentation/RCU/Design/Data-Structures/Data-Structures.html new file mode 100644 index 000000000000..7eb47ac25ad7 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/Data-Structures.html @@ -0,0 +1,1333 @@ + + + A Tour Through TREE_RCU's Data Structures [LWN.net] + + +

    January 27, 2016

    +

    This article was contributed by Paul E. McKenney

    + +

    Introduction

    + +This document describes RCU's major data structures and their relationship +to each other. + +
      +
    1. + Data-Structure Relationships +
    2. + The rcu_state Structure +
    3. + The rcu_node Structure +
    4. + The rcu_data Structure +
    5. + The rcu_dynticks Structure +
    6. + The rcu_head Structure +
    7. + RCU-Specific Fields in the task_struct Structure +
    8. + Accessor Functions +
    + +At the end we have the +answers to the quick quizzes. + +

    Data-Structure Relationships

    + +

    RCU is for all intents and purposes a large state machine, and its +data structures maintain the state in such a way as to allow RCU readers +to execute extremely quickly, while also processing the RCU grace periods +requested by updaters in an efficient and extremely scalable fashion. +The efficiency and scalability of RCU updaters is provided primarily +by a combining tree, as shown below: + +

    BigTreeClassicRCU.svg + +

    This diagram shows an enclosing rcu_state structure +containing a tree of rcu_node structures. +Each leaf node of the rcu_node tree has up to 16 +rcu_data structures associated with it, so that there +are NR_CPUS number of rcu_data structures, +one for each possible CPU. +This structure is adjusted at boot time, if needed, to handle the +common case where nr_cpu_ids is much less than +NR_CPUs. +For example, a number of Linux distributions set NR_CPUs=4096, +which results in a three-level rcu_node tree. +If the actual hardware has only 16 CPUs, RCU will adjust itself +at boot time, resulting in an rcu_node tree with only a single node. + +

    The purpose of this combining tree is to allow per-CPU events +such as quiescent states, dyntick-idle transitions, +and CPU hotplug operations to be processed efficiently +and scalably. +Quiescent states are recorded by the per-CPU rcu_data structures, +and other events are recorded by the leaf-level rcu_node +structures. +All of these events are combined at each level of the tree until finally +grace periods are completed at the tree's root rcu_node +structure. +A grace period can be completed at the root once every CPU +(or, in the case of CONFIG_PREEMPT_RCU, task) +has passed through a quiescent state. +Once a grace period has completed, record of that fact is propagated +back down the tree. + +

    As can be seen from the diagram, on a 64-bit system +a two-level tree with 64 leaves can accommodate 1,024 CPUs, with a fanout +of 64 at the root and a fanout of 16 at the leaves. + + + + + + + + +
     
    Quick Quiz:
    + Why isn't the fanout at the leaves also 64? +
    Answer:
    + Because there are more types of events that affect the leaf-level + rcu_node structures than further up the tree. + Therefore, if the leaf rcu_node structures have fanout of + 64, the contention on these structures' ->structures + becomes excessive. + Experimentation on a wide variety of systems has shown that a fanout + of 16 works well for the leaves of the rcu_node tree. + + +

    Of course, further experience with + systems having hundreds or thousands of CPUs may demonstrate + that the fanout for the non-leaf rcu_node structures + must also be reduced. + Such reduction can be easily carried out when and if it proves + necessary. + In the meantime, if you are using such a system and running into + contention problems on the non-leaf rcu_node structures, + you may use the CONFIG_RCU_FANOUT kernel configuration + parameter to reduce the non-leaf fanout as needed. + + +

    Kernels built for systems with + strong NUMA characteristics might also need to adjust + CONFIG_RCU_FANOUT so that the domains of the + rcu_node structures align with hardware boundaries. + However, there has thus far been no need for this. +

     
    + +

    If your system has more than 1,024 CPUs (or more than 512 CPUs on +a 32-bit system), then RCU will automatically add more levels to the +tree. +For example, if you are crazy enough to build a 64-bit system with 65,536 +CPUs, RCU would configure the rcu_node tree as follows: + +

    HugeTreeClassicRCU.svg + +

    RCU currently permits up to a four-level tree, which on a 64-bit system +accommodates up to 4,194,304 CPUs, though only a mere 524,288 CPUs for +32-bit systems. +On the other hand, you can set CONFIG_RCU_FANOUT to be +as small as 2 if you wish, which would permit only 16 CPUs, which +is useful for testing. + +

    This multi-level combining tree allows us to get most of the +performance and scalability +benefits of partitioning, even though RCU grace-period detection is +inherently a global operation. +The trick here is that only the last CPU to report a quiescent state +into a given rcu_node structure need advance to the rcu_node +structure at the next level up the tree. +This means that at the leaf-level rcu_node structure, only +one access out of sixteen will progress up the tree. +For the internal rcu_node structures, the situation is even +more extreme: Only one access out of sixty-four will progress up +the tree. +Because the vast majority of the CPUs do not progress up the tree, +the lock contention remains roughly constant up the tree. +No matter how many CPUs there are in the system, at most 64 quiescent-state +reports per grace period will progress all the way to the root +rcu_node structure, thus ensuring that the lock contention +on that root rcu_node structure remains acceptably low. + +

    In effect, the combining tree acts like a big shock absorber, +keeping lock contention under control at all tree levels regardless +of the level of loading on the system. + +

    The Linux kernel actually supports multiple flavors of RCU +running concurrently, so RCU builds separate data structures for each +flavor. +For example, for CONFIG_TREE_RCU=y kernels, RCU provides +rcu_sched and rcu_bh, as shown below: + +

    BigTreeClassicRCUBH.svg + +

    Energy efficiency is increasingly important, and for that +reason the Linux kernel provides CONFIG_NO_HZ_IDLE, which +turns off the scheduling-clock interrupts on idle CPUs, which in +turn allows those CPUs to attain deeper sleep states and to consume +less energy. +CPUs whose scheduling-clock interrupts have been turned off are +said to be in dyntick-idle mode. +RCU must handle dyntick-idle CPUs specially +because RCU would otherwise wake up each CPU on every grace period, +which would defeat the whole purpose of CONFIG_NO_HZ_IDLE. +RCU uses the rcu_dynticks structure to track +which CPUs are in dyntick idle mode, as shown below: + +

    BigTreeClassicRCUBHdyntick.svg + +

    However, if a CPU is in dyntick-idle mode, it is in that mode +for all flavors of RCU. +Therefore, a single rcu_dynticks structure is allocated per +CPU, and all of a given CPU's rcu_data structures share +that rcu_dynticks, as shown in the figure. + +

    Kernels built with CONFIG_PREEMPT_RCU support +rcu_preempt in addition to rcu_sched and rcu_bh, as shown below: + +

    BigTreePreemptRCUBHdyntick.svg + +

    RCU updaters wait for normal grace periods by registering +RCU callbacks, either directly via call_rcu() and +friends (namely call_rcu_bh() and call_rcu_sched()), +there being a separate interface per flavor of RCU) +or indirectly via synchronize_rcu() and friends. +RCU callbacks are represented by rcu_head structures, +which are queued on rcu_data structures while they are +waiting for a grace period to elapse, as shown in the following figure: + +

    BigTreePreemptRCUBHdyntickCB.svg + +

    This figure shows how TREE_RCU's and +PREEMPT_RCU's major data structures are related. +Lesser data structures will be introduced with the algorithms that +make use of them. + +

    Note that each of the data structures in the above figure has +its own synchronization: + +

      +
    1. Each rcu_state structures has a lock and a mutex, + and some fields are protected by the corresponding root + rcu_node structure's lock. +
    2. Each rcu_node structure has a spinlock. +
    3. The fields in rcu_data are private to the corresponding + CPU, although a few can be read and written by other CPUs. +
    4. Similarly, the fields in rcu_dynticks are private + to the corresponding CPU, although a few can be read by + other CPUs. +
    + +

    It is important to note that different data structures can have +very different ideas about the state of RCU at any given time. +For but one example, awareness of the start or end of a given RCU +grace period propagates slowly through the data structures. +This slow propagation is absolutely necessary for RCU to have good +read-side performance. +If this balkanized implementation seems foreign to you, one useful +trick is to consider each instance of these data structures to be +a different person, each having the usual slightly different +view of reality. + +

    The general role of each of these data structures is as +follows: + +

      +
    1. rcu_state: + This structure forms the interconnection between the + rcu_node and rcu_data structures, + tracks grace periods, serves as short-term repository + for callbacks orphaned by CPU-hotplug events, + maintains rcu_barrier() state, + tracks expedited grace-period state, + and maintains state used to force quiescent states when + grace periods extend too long, +
    2. rcu_node: This structure forms the combining + tree that propagates quiescent-state + information from the leaves to the root, and also propagates + grace-period information from the root to the leaves. + It provides local copies of the grace-period state in order + to allow this information to be accessed in a synchronized + manner without suffering the scalability limitations that + would otherwise be imposed by global locking. + In CONFIG_PREEMPT_RCU kernels, it manages the lists + of tasks that have blocked while in their current + RCU read-side critical section. + In CONFIG_PREEMPT_RCU with + CONFIG_RCU_BOOST, it manages the + per-rcu_node priority-boosting + kernel threads (kthreads) and state. + Finally, it records CPU-hotplug state in order to determine + which CPUs should be ignored during a given grace period. +
    3. rcu_data: This per-CPU structure is the + focus of quiescent-state detection and RCU callback queuing. + It also tracks its relationship to the corresponding leaf + rcu_node structure to allow more-efficient + propagation of quiescent states up the rcu_node + combining tree. + Like the rcu_node structure, it provides a local + copy of the grace-period information to allow for-free + synchronized + access to this information from the corresponding CPU. + Finally, this structure records past dyntick-idle state + for the corresponding CPU and also tracks statistics. +
    4. rcu_dynticks: + This per-CPU structure tracks the current dyntick-idle + state for the corresponding CPU. + Unlike the other three structures, the rcu_dynticks + structure is not replicated per RCU flavor. +
    5. rcu_head: + This structure represents RCU callbacks, and is the + only structure allocated and managed by RCU users. + The rcu_head structure is normally embedded + within the RCU-protected data structure. +
    + +

    If all you wanted from this article was a general notion of how +RCU's data structures are related, you are done. +Otherwise, each of the following sections give more details on +the rcu_state, rcu_node, rcu_data, +and rcu_dynticks data structures. + +

    +The rcu_state Structure

    + +

    The rcu_state structure is the base structure that +represents a flavor of RCU. +This structure forms the interconnection between the +rcu_node and rcu_data structures, +tracks grace periods, contains the lock used to +synchronize with CPU-hotplug events, +and maintains state used to force quiescent states when +grace periods extend too long, + +

    A few of the rcu_state structure's fields are discussed, +singly and in groups, in the following sections. +The more specialized fields are covered in the discussion of their +use. + +

    Relationship to rcu_node and rcu_data Structures
    + +This portion of the rcu_state structure is declared +as follows: + +
    +  1   struct rcu_node node[NUM_RCU_NODES];
    +  2   struct rcu_node *level[NUM_RCU_LVLS + 1];
    +  3   struct rcu_data __percpu *rda;
    +
    + + + + + + + + +
     
    Quick Quiz:
    + Wait a minute! + You said that the rcu_node structures formed a tree, + but they are declared as a flat array! + What gives? +
    Answer:
    + The tree is laid out in the array. + The first node In the array is the head, the next set of nodes in the + array are children of the head node, and so on until the last set of + nodes in the array are the leaves. + + +

    See the following diagrams to see how + this works. +

     
    + +

    The rcu_node tree is embedded into the +->node[] array as shown in the following figure: + +

    TreeMapping.svg + +

    One interesting consequence of this mapping is that a +breadth-first traversal of the tree is implemented as a simple +linear scan of the array, which is in fact what the +rcu_for_each_node_breadth_first() macro does. +This macro is used at the beginning and ends of grace periods. + +

    Each entry of the ->level array references +the first rcu_node structure on the corresponding level +of the tree, for example, as shown below: + +

    TreeMappingLevel.svg + +

    The zeroth element of the array references the root +rcu_node structure, the first element references the +first child of the root rcu_node, and finally the second +element references the first leaf rcu_node structure. + +

    For whatever it is worth, if you draw the tree to be tree-shaped +rather than array-shaped, it is easy to draw a planar representation: + +

    TreeLevel.svg + +

    Finally, the ->rda field references a per-CPU +pointer to the corresponding CPU's rcu_data structure. + +

    All of these fields are constant once initialization is complete, +and therefore need no protection. + +

    Grace-Period Tracking
    + +

    This portion of the rcu_state structure is declared +as follows: + +

    +  1   unsigned long gpnum;
    +  2   unsigned long completed;
    +
    + +

    RCU grace periods are numbered, and +the ->gpnum field contains the number of the grace +period that started most recently. +The ->completed field contains the number of the +grace period that completed most recently. +If the two fields are equal, the RCU grace period that most recently +started has already completed, and therefore the corresponding +flavor of RCU is idle. +If ->gpnum is one greater than ->completed, +then ->gpnum gives the number of the current RCU +grace period, which has not yet completed. +Any other combination of values indicates that something is broken. +These two fields are protected by the root rcu_node's +->lock field. + +

    There are ->gpnum and ->completed fields +in the rcu_node and rcu_data structures +as well. +The fields in the rcu_state structure represent the +most current values, and those of the other structures are compared +in order to detect the start of a new grace period in a distributed +fashion. +The values flow from rcu_state to rcu_node +(down the tree from the root to the leaves) to rcu_data. + +

    Miscellaneous
    + +

    This portion of the rcu_state structure is declared +as follows: + +

    +  1   unsigned long gp_max;
    +  2   char abbr;
    +  3   char *name;
    +
    + +

    The ->gp_max field tracks the duration of the longest +grace period in jiffies. +It is protected by the root rcu_node's ->lock. + +

    The ->name field points to the name of the RCU flavor +(for example, “rcu_sched”), and is constant. +The ->abbr field contains a one-character abbreviation, +for example, “s” for RCU-sched. + +

    +The rcu_node Structure

    + +

    The rcu_node structures form the combining +tree that propagates quiescent-state +information from the leaves to the root and also that propagates +grace-period information from the root down to the leaves. +They provides local copies of the grace-period state in order +to allow this information to be accessed in a synchronized +manner without suffering the scalability limitations that +would otherwise be imposed by global locking. +In CONFIG_PREEMPT_RCU kernels, they manage the lists +of tasks that have blocked while in their current +RCU read-side critical section. +In CONFIG_PREEMPT_RCU with +CONFIG_RCU_BOOST, they manage the +per-rcu_node priority-boosting +kernel threads (kthreads) and state. +Finally, they record CPU-hotplug state in order to determine +which CPUs should be ignored during a given grace period. + +

    The rcu_node structure's fields are discussed, +singly and in groups, in the following sections. + +

    Connection to Combining Tree
    + +

    This portion of the rcu_node structure is declared +as follows: + +

    +  1   struct rcu_node *parent;
    +  2   u8 level;
    +  3   u8 grpnum;
    +  4   unsigned long grpmask;
    +  5   int grplo;
    +  6   int grphi;
    +
    + +

    The ->parent pointer references the rcu_node +one level up in the tree, and is NULL for the root +rcu_node. +The RCU implementation makes heavy use of this field to push quiescent +states up the tree. +The ->level field gives the level in the tree, with +the root being at level zero, its children at level one, and so on. +The ->grpnum field gives this node's position within +the children of its parent, so this number can range between 0 and 31 +on 32-bit systems and between 0 and 63 on 64-bit systems. +The ->level and ->grpnum fields are +used only during initialization and for tracing. +The ->grpmask field is the bitmask counterpart of +->grpnum, and therefore always has exactly one bit set. +This mask is used to clear the bit corresponding to this rcu_node +structure in its parent's bitmasks, which are described later. +Finally, the ->grplo and ->grphi fields +contain the lowest and highest numbered CPU served by this +rcu_node structure, respectively. + +

    All of these fields are constant, and thus do not require any +synchronization. + +

    Synchronization
    + +

    This field of the rcu_node structure is declared +as follows: + +

    +  1   raw_spinlock_t lock;
    +
    + +

    This field is used to protect the remaining fields in this structure, +unless otherwise stated. +That said, all of the fields in this structure can be accessed without +locking for tracing purposes. +Yes, this can result in confusing traces, but better some tracing confusion +than to be heisenbugged out of existence. + +

    Grace-Period Tracking
    + +

    This portion of the rcu_node structure is declared +as follows: + +

    +  1   unsigned long gpnum;
    +  2   unsigned long completed;
    +
    + +

    These fields are the counterparts of the fields of the same name in +the rcu_state structure. +They each may lag up to one behind their rcu_state +counterparts. +If a given rcu_node structure's ->gpnum and +->complete fields are equal, then this rcu_node +structure believes that RCU is idle. +Otherwise, as with the rcu_state structure, +the ->gpnum field will be one greater than the +->complete fields, with ->gpnum +indicating which grace period this rcu_node believes +is still being waited for. + +

    The >gpnum field of each rcu_node +structure is updated at the beginning +of each grace period, and the ->completed fields are +updated at the end of each grace period. + +

    Quiescent-State Tracking
    + +

    These fields manage the propagation of quiescent states up the +combining tree. + +

    This portion of the rcu_node structure has fields +as follows: + +

    +  1   unsigned long qsmask;
    +  2   unsigned long expmask;
    +  3   unsigned long qsmaskinit;
    +  4   unsigned long expmaskinit;
    +
    + +

    The ->qsmask field tracks which of this +rcu_node structure's children still need to report +quiescent states for the current normal grace period. +Such children will have a value of 1 in their corresponding bit. +Note that the leaf rcu_node structures should be +thought of as having rcu_data structures as their +children. +Similarly, the ->expmask field tracks which +of this rcu_node structure's children still need to report +quiescent states for the current expedited grace period. +An expedited grace period has +the same conceptual properties as a normal grace period, but the +expedited implementation accepts extreme CPU overhead to obtain +much lower grace-period latency, for example, consuming a few +tens of microseconds worth of CPU time to reduce grace-period +duration from milliseconds to tens of microseconds. +The ->qsmaskinit field tracks which of this +rcu_node structure's children cover for at least +one online CPU. +This mask is used to initialize ->qsmask, +and ->expmaskinit is used to initialize +->expmask and the beginning of the +normal and expedited grace periods, respectively. + + + + + + + + +
     
    Quick Quiz:
    + Why are these bitmasks protected by locking? + Come on, haven't you heard of atomic instructions??? +
    Answer:
    + Lockless grace-period computation! Such a tantalizing possibility! + + +

    But consider the following sequence of events: + + +

      +
    1. CPU 0 has been in dyntick-idle + mode for quite some time. + When it wakes up, it notices that the current RCU + grace period needs it to report in, so it sets a + flag where the scheduling clock interrupt will find it. +

      +

    2. Meanwhile, CPU 1 is running + force_quiescent_state(), + and notices that CPU 0 has been in dyntick idle mode, + which qualifies as an extended quiescent state. +

      +

    3. CPU 0's scheduling clock + interrupt fires in the + middle of an RCU read-side critical section, and notices + that the RCU core needs something, so commences RCU softirq + processing. + +

      +

    4. CPU 0's softirq handler + executes and is just about ready + to report its quiescent state up the rcu_node + tree. +

      +

    5. But CPU 1 beats it to the punch, + completing the current + grace period and starting a new one. +

      +

    6. CPU 0 now reports its quiescent + state for the wrong + grace period. + That grace period might now end before the RCU read-side + critical section. + If that happens, disaster will ensue. + +
    + +

    So the locking is absolutely required in + order to coordinate + clearing of the bits with the grace-period numbers in + ->gpnum and ->completed. +

     
    + +

    Blocked-Task Management
    + +

    PREEMPT_RCU allows tasks to be preempted in the +midst of their RCU read-side critical sections, and these tasks +must be tracked explicitly. +The details of exactly why and how they are tracked will be covered +in a separate article on RCU read-side processing. +For now, it is enough to know that the rcu_node +structure tracks them. + +

    +  1   struct list_head blkd_tasks;
    +  2   struct list_head *gp_tasks;
    +  3   struct list_head *exp_tasks;
    +  4   bool wait_blkd_tasks;
    +
    + +

    The ->blkd_tasks field is a list header for +the list of blocked and preempted tasks. +As tasks undergo context switches within RCU read-side critical +sections, their task_struct structures are enqueued +(via the task_struct's ->rcu_node_entry +field) onto the head of the ->blkd_tasks list for the +leaf rcu_node structure corresponding to the CPU +on which the outgoing context switch executed. +As these tasks later exit their RCU read-side critical sections, +they remove themselves from the list. +This list is therefore in reverse time order, so that if one of the tasks +is blocking the current grace period, all subsequent tasks must +also be blocking that same grace period. +Therefore, a single pointer into this list suffices to track +all tasks blocking a given grace period. +That pointer is stored in ->gp_tasks for normal +grace periods and in ->exp_tasks for expedited +grace periods. +These last two fields are NULL if either there is +no grace period in flight or if there are no blocked tasks +preventing that grace period from completing. +If either of these two pointers is referencing a task that +removes itself from the ->blkd_tasks list, +then that task must advance the pointer to the next task on +the list, or set the pointer to NULL if there +are no subsequent tasks on the list. + +

    For example, suppose that tasks T1, T2, and T3 are +all hard-affinitied to the largest-numbered CPU in the system. +Then if task T1 blocked in an RCU read-side +critical section, then an expedited grace period started, +then task T2 blocked in an RCU read-side critical section, +then a normal grace period started, and finally task 3 blocked +in an RCU read-side critical section, then the state of the +last leaf rcu_node structure's blocked-task list +would be as shown below: + +

    blkd_task.svg + +

    Task T1 is blocking both grace periods, task T2 is +blocking only the normal grace period, and task T3 is blocking +neither grace period. +Note that these tasks will not remove themselves from this list +immediately upon resuming execution. +They will instead remain on the list until they execute the outermost +rcu_read_unlock() that ends their RCU read-side critical +section. + +

    +The ->wait_blkd_tasks field indicates whether or not +the current grace period is waiting on a blocked task. + +

    Sizing the rcu_node Array
    + +

    The rcu_node array is sized via a series of +C-preprocessor expressions as follows: + +

    + 1 #ifdef CONFIG_RCU_FANOUT
    + 2 #define RCU_FANOUT CONFIG_RCU_FANOUT
    + 3 #else
    + 4 # ifdef CONFIG_64BIT
    + 5 # define RCU_FANOUT 64
    + 6 # else
    + 7 # define RCU_FANOUT 32
    + 8 # endif
    + 9 #endif
    +10
    +11 #ifdef CONFIG_RCU_FANOUT_LEAF
    +12 #define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF
    +13 #else
    +14 # ifdef CONFIG_64BIT
    +15 # define RCU_FANOUT_LEAF 64
    +16 # else
    +17 # define RCU_FANOUT_LEAF 32
    +18 # endif
    +19 #endif
    +20
    +21 #define RCU_FANOUT_1        (RCU_FANOUT_LEAF)
    +22 #define RCU_FANOUT_2        (RCU_FANOUT_1 * RCU_FANOUT)
    +23 #define RCU_FANOUT_3        (RCU_FANOUT_2 * RCU_FANOUT)
    +24 #define RCU_FANOUT_4        (RCU_FANOUT_3 * RCU_FANOUT)
    +25
    +26 #if NR_CPUS <= RCU_FANOUT_1
    +27 #  define RCU_NUM_LVLS        1
    +28 #  define NUM_RCU_LVL_0        1
    +29 #  define NUM_RCU_NODES        NUM_RCU_LVL_0
    +30 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }
    +31 #  define RCU_NODE_NAME_INIT  { "rcu_node_0" }
    +32 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0" }
    +33 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0" }
    +34 #elif NR_CPUS <= RCU_FANOUT_2
    +35 #  define RCU_NUM_LVLS        2
    +36 #  define NUM_RCU_LVL_0        1
    +37 #  define NUM_RCU_LVL_1        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
    +38 #  define NUM_RCU_NODES        (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)
    +39 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
    +40 #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1" }
    +41 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1" }
    +42 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0", "rcu_node_exp_1" }
    +43 #elif NR_CPUS <= RCU_FANOUT_3
    +44 #  define RCU_NUM_LVLS        3
    +45 #  define NUM_RCU_LVL_0        1
    +46 #  define NUM_RCU_LVL_1        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
    +47 #  define NUM_RCU_LVL_2        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
    +48 #  define NUM_RCU_NODES        (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)
    +49 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
    +50 #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
    +51 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
    +52 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2" }
    +53 #elif NR_CPUS <= RCU_FANOUT_4
    +54 #  define RCU_NUM_LVLS        4
    +55 #  define NUM_RCU_LVL_0        1
    +56 #  define NUM_RCU_LVL_1        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
    +57 #  define NUM_RCU_LVL_2        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
    +58 #  define NUM_RCU_LVL_3        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
    +59 #  define NUM_RCU_NODES        (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)
    +60 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
    +61 #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
    +62 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
    +63 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2", "rcu_node_exp_3" }
    +64 #else
    +65 # error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
    +66 #endif
    +
    + +

    The maximum number of levels in the rcu_node structure +is currently limited to four, as specified by lines 21-24 +and the structure of the subsequent “if” statement. +For 32-bit systems, this allows 16*32*32*32=524,288 CPUs, which +should be sufficient for the next few years at least. +For 64-bit systems, 16*64*64*64=4,194,304 CPUs is allowed, which +should see us through the next decade or so. +This four-level tree also allows kernels built with +CONFIG_RCU_FANOUT=8 to support up to 4096 CPUs, +which might be useful in very large systems having eight CPUs per +socket (but please note that no one has yet shown any measurable +performance degradation due to misaligned socket and rcu_node +boundaries). +In addition, building kernels with a full four levels of rcu_node +tree permits better testing of RCU's combining-tree code. + +

    The RCU_FANOUT symbol controls how many children +are permitted at each non-leaf level of the rcu_node tree. +If the CONFIG_RCU_FANOUT Kconfig option is not specified, +it is set based on the word size of the system, which is also +the Kconfig default. + +

    The RCU_FANOUT_LEAF symbol controls how many CPUs are +handled by each leaf rcu_node structure. +Experience has shown that allowing a given leaf rcu_node +structure to handle 64 CPUs, as permitted by the number of bits in +the ->qsmask field on a 64-bit system, results in +excessive contention for the leaf rcu_node structures' +->lock fields. +The number of CPUs per leaf rcu_node structure is therefore +limited to 16 given the default value of CONFIG_RCU_FANOUT_LEAF. +If CONFIG_RCU_FANOUT_LEAF is unspecified, the value +selected is based on the word size of the system, just as for +CONFIG_RCU_FANOUT. +Lines 11-19 perform this computation. + +

    Lines 21-24 compute the maximum number of CPUs supported by +a single-level (which contains a single rcu_node structure), +two-level, three-level, and four-level rcu_node tree, +respectively, given the fanout specified by RCU_FANOUT +and RCU_FANOUT_LEAF. +These numbers of CPUs are retained in the +RCU_FANOUT_1, +RCU_FANOUT_2, +RCU_FANOUT_3, and +RCU_FANOUT_4 +C-preprocessor variables, respectively. + +

    These variables are used to control the C-preprocessor #if +statement spanning lines 26-66 that computes the number of +rcu_node structures required for each level of the tree, +as well as the number of levels required. +The number of levels is placed in the NUM_RCU_LVLS +C-preprocessor variable by lines 27, 35, 44, and 54. +The number of rcu_node structures for the topmost level +of the tree is always exactly one, and this value is unconditionally +placed into NUM_RCU_LVL_0 by lines 28, 36, 45, and 55. +The rest of the levels (if any) of the rcu_node tree +are computed by dividing the maximum number of CPUs by the +fanout supported by the number of levels from the current level down, +rounding up. This computation is performed by lines 37, +46-47, and 56-58. +Lines 31-33, 40-42, 50-52, and 62-63 create initializers +for lockdep lock-class names. +Finally, lines 64-66 produce an error if the maximum number of +CPUs is too large for the specified fanout. + +

    +The rcu_data Structure

    + +

    The rcu_data maintains the per-CPU state for the +corresponding flavor of RCU. +The fields in this structure may be accessed only from the corresponding +CPU (and from tracing) unless otherwise stated. +This structure is the +focus of quiescent-state detection and RCU callback queuing. +It also tracks its relationship to the corresponding leaf +rcu_node structure to allow more-efficient +propagation of quiescent states up the rcu_node +combining tree. +Like the rcu_node structure, it provides a local +copy of the grace-period information to allow for-free +synchronized +access to this information from the corresponding CPU. +Finally, this structure records past dyntick-idle state +for the corresponding CPU and also tracks statistics. + +

    The rcu_data structure's fields are discussed, +singly and in groups, in the following sections. + +

    Connection to Other Data Structures
    + +

    This portion of the rcu_data structure is declared +as follows: + +

    +  1   int cpu;
    +  2   struct rcu_state *rsp;
    +  3   struct rcu_node *mynode;
    +  4   struct rcu_dynticks *dynticks;
    +  5   unsigned long grpmask;
    +  6   bool beenonline;
    +
    + +

    The ->cpu field contains the number of the +corresponding CPU, the ->rsp pointer references +the corresponding rcu_state structure (and is most frequently +used to locate the name of the corresponding flavor of RCU for tracing), +and the ->mynode field references the corresponding +rcu_node structure. +The ->mynode is used to propagate quiescent states +up the combining tree. +

    The ->dynticks pointer references the +rcu_dynticks structure corresponding to this +CPU. +Recall that a single per-CPU instance of the rcu_dynticks +structure is shared among all flavors of RCU. +These first four fields are constant and therefore require not +synchronization. + +

    The ->grpmask field indicates the bit in +the ->mynode->qsmask corresponding to this +rcu_data structure, and is also used when propagating +quiescent states. +The ->beenonline flag is set whenever the corresponding +CPU comes online, which means that the debugfs tracing need not dump +out any rcu_data structure for which this flag is not set. + +

    Quiescent-State and Grace-Period Tracking
    + +

    This portion of the rcu_data structure is declared +as follows: + +

    +  1   unsigned long completed;
    +  2   unsigned long gpnum;
    +  3   bool cpu_no_qs;
    +  4   bool core_needs_qs;
    +  5   bool gpwrap;
    +  6   unsigned long rcu_qs_ctr_snap;
    +
    + +

    The completed and gpnum +fields are the counterparts of the fields of the same name +in the rcu_state and rcu_node structures. +They may each lag up to one behind their rcu_node +counterparts, but in CONFIG_NO_HZ_IDLE and +CONFIG_NO_HZ_FULL kernels can lag +arbitrarily far behind for CPUs in dyntick-idle mode (but these counters +will catch up upon exit from dyntick-idle mode). +If a given rcu_data structure's ->gpnum and +->complete fields are equal, then this rcu_data +structure believes that RCU is idle. +Otherwise, as with the rcu_state and rcu_node +structure, +the ->gpnum field will be one greater than the +->complete fields, with ->gpnum +indicating which grace period this rcu_data believes +is still being waited for. + + + + + + + + +
     
    Quick Quiz:
    + All this replication of the grace period numbers can only cause + massive confusion. + Why not just keep a global pair of counters and be done with it??? +
    Answer:
    + Because if there was only a single global pair of grace-period + numbers, there would need to be a single global lock to allow + safely accessing and updating them. + And if we are not going to have a single global lock, we need + to carefully manage the numbers on a per-node basis. + Recall from the answer to a previous Quick Quiz that the consequences + of applying a previously sampled quiescent state to the wrong + grace period are quite severe. +
     
    + +

    The ->cpu_no_qs flag indicates that the +CPU has not yet passed through a quiescent state, +while the ->core_needs_qs flag indicates that the +RCU core needs a quiescent state from the corresponding CPU. +The ->gpwrap field indicates that the corresponding +CPU has remained idle for so long that the completed +and gpnum counters are in danger of overflow, which +will cause the CPU to disregard the values of its counters on +its next exit from idle. +Finally, the rcu_qs_ctr_snap field is used to detect +cases where a given operation has resulted in a quiescent state +for all flavors of RCU, for example, cond_resched_rcu_qs(). + +

    RCU Callback Handling
    + +

    In the absence of CPU-hotplug events, RCU callbacks are invoked by +the same CPU that registered them. +This is strictly a cache-locality optimization: callbacks can and +do get invoked on CPUs other than the one that registered them. +After all, if the CPU that registered a given callback has gone +offline before the callback can be invoked, there really is no other +choice. + +

    This portion of the rcu_data structure is declared +as follows: + +

    + 1 struct rcu_head *nxtlist;
    + 2 struct rcu_head **nxttail[RCU_NEXT_SIZE];
    + 3 unsigned long nxtcompleted[RCU_NEXT_SIZE];
    + 4 long qlen_lazy;
    + 5 long qlen;
    + 6 long qlen_last_fqs_check;
    + 7 unsigned long n_force_qs_snap;
    + 8 unsigned long n_cbs_invoked;
    + 9 unsigned long n_cbs_orphaned;
    +10 unsigned long n_cbs_adopted;
    +11 long blimit;
    +
    + +

    The ->nxtlist pointer and the +->nxttail[] array form a four-segment list with +older callbacks near the head and newer ones near the tail. +Each segment contains callbacks with the corresponding relationship +to the current grace period. +The pointer out of the end of each of the four segments is referenced +by the element of the ->nxttail[] array indexed by +RCU_DONE_TAIL (for callbacks handled by a prior grace period), +RCU_WAIT_TAIL (for callbacks waiting on the current grace period), +RCU_NEXT_READY_TAIL (for callbacks that will wait on the next +grace period), and +RCU_NEXT_TAIL (for callbacks that are not yet associated +with a specific grace period) +respectively, as shown in the following figure. + +

    nxtlist.svg + +

    In this figure, the ->nxtlist pointer references the +first +RCU callback in the list. +The ->nxttail[RCU_DONE_TAIL] array element references +the ->nxtlist pointer itself, indicating that none +of the callbacks is ready to invoke. +The ->nxttail[RCU_WAIT_TAIL] array element references callback +CB 2's ->next pointer, which indicates that +CB 1 and CB 2 are both waiting on the current grace period. +The ->nxttail[RCU_NEXT_READY_TAIL] array element +references the same RCU callback that ->nxttail[RCU_WAIT_TAIL] +does, which indicates that there are no callbacks waiting on the next +RCU grace period. +The ->nxttail[RCU_NEXT_TAIL] array element references +CB 4's ->next pointer, indicating that all the +remaining RCU callbacks have not yet been assigned to an RCU grace +period. +Note that the ->nxttail[RCU_NEXT_TAIL] array element +always references the last RCU callback's ->next pointer +unless the callback list is empty, in which case it references +the ->nxtlist pointer. + +

    CPUs advance their callbacks from the +RCU_NEXT_TAIL to the RCU_NEXT_READY_TAIL to the +RCU_WAIT_TAIL to the RCU_DONE_TAIL list segments +as grace periods advance. +The CPU advances the callbacks in its rcu_data structure +whenever it notices that another RCU grace period has completed. +The CPU detects the completion of an RCU grace period by noticing +that the value of its rcu_data structure's +->completed field differs from that of its leaf +rcu_node structure. +Recall that each rcu_node structure's +->completed field is updated at the end of each +grace period. + +

    The ->nxtcompleted[] array records grace-period +numbers corresponding to the list segments. +This allows CPUs that go idle for extended periods to determine +which of their callbacks are ready to be invoked after reawakening. + +

    The ->qlen counter contains the number of +callbacks in ->nxtlist, and the +->qlen_lazy contains the number of those callbacks that +are known to only free memory, and whose invocation can therefore +be safely deferred. +The ->qlen_last_fqs_check and +->n_force_qs_snap coordinate the forcing of quiescent +states from call_rcu() and friends when callback +lists grow excessively long. + +

    The ->n_cbs_invoked, +->n_cbs_orphaned, and ->n_cbs_adopted +fields count the number of callbacks invoked, +sent to other CPUs when this CPU goes offline, +and received from other CPUs when those other CPUs go offline. +Finally, the ->blimit counter is the maximum number of +RCU callbacks that may be invoked at a given time. + +

    Dyntick-Idle Handling
    + +

    This portion of the rcu_data structure is declared +as follows: + +

    +  1   int dynticks_snap;
    +  2   unsigned long dynticks_fqs;
    +
    + +The ->dynticks_snap field is used to take a snapshot +of the corresponding CPU's dyntick-idle state when forcing +quiescent states, and is therefore accessed from other CPUs. +Finally, the ->dynticks_fqs field is used to +count the number of times this CPU is determined to be in +dyntick-idle state, and is used for tracing and debugging purposes. + +

    +The rcu_dynticks Structure

    + +

    The rcu_dynticks maintains the per-CPU dyntick-idle state +for the corresponding CPU. +Unlike the other structures, rcu_dynticks is not +replicated over the different flavors of RCU. +The fields in this structure may be accessed only from the corresponding +CPU (and from tracing) unless otherwise stated. +Its fields are as follows: + +

    +  1   int dynticks_nesting;
    +  2   int dynticks_nmi_nesting;
    +  3   atomic_t dynticks;
    +
    + +

    The ->dynticks_nesting field counts the +nesting depth of normal interrupts. +In addition, this counter is incremented when exiting dyntick-idle +mode and decremented when entering it. +This counter can therefore be thought of as counting the number +of reasons why this CPU cannot be permitted to enter dyntick-idle +mode, aside from non-maskable interrupts (NMIs). +NMIs are counted by the ->dynticks_nmi_nesting +field, except that NMIs that interrupt non-dyntick-idle execution +are not counted. + +

    Finally, the ->dynticks field counts the corresponding +CPU's transitions to and from dyntick-idle mode, so that this counter +has an even value when the CPU is in dyntick-idle mode and an odd +value otherwise. + + + + + + + + +
     
    Quick Quiz:
    + Why not just count all NMIs? + Wouldn't that be simpler and less error prone? +
    Answer:
    + It seems simpler only until you think hard about how to go about + updating the rcu_dynticks structure's + ->dynticks field. +
     
    + +

    Additional fields are present for some special-purpose +builds, and are discussed separately. + +

    +The rcu_head Structure

    + +

    Each rcu_head structure represents an RCU callback. +These structures are normally embedded within RCU-protected data +structures whose algorithms use asynchronous grace periods. +In contrast, when using algorithms that block waiting for RCU grace periods, +RCU users need not provide rcu_head structures. + +

    The rcu_head structure has fields as follows: + +

    +  1   struct rcu_head *next;
    +  2   void (*func)(struct rcu_head *head);
    +
    + +

    The ->next field is used +to link the rcu_head structures together in the +lists within the rcu_data structures. +The ->func field is a pointer to the function +to be called when the callback is ready to be invoked, and +this function is passed a pointer to the rcu_head +structure. +However, kfree_rcu() uses the ->func +field to record the offset of the rcu_head +structure within the enclosing RCU-protected data structure. + +

    Both of these fields are used internally by RCU. +From the viewpoint of RCU users, this structure is an +opaque “cookie”. + + + + + + + + +
     
    Quick Quiz:
    + Given that the callback function ->func + is passed a pointer to the rcu_head structure, + how is that function supposed to find the beginning of the + enclosing RCU-protected data structure? +
    Answer:
    + In actual practice, there is a separate callback function per + type of RCU-protected data structure. + The callback function can therefore use the container_of() + macro in the Linux kernel (or other pointer-manipulation facilities + in other software environments) to find the beginning of the + enclosing structure. +
     
    + +

    +RCU-Specific Fields in the task_struct Structure

    + +

    The CONFIG_PREEMPT_RCU implementation uses some +additional fields in the task_struct structure: + +

    + 1 #ifdef CONFIG_PREEMPT_RCU
    + 2   int rcu_read_lock_nesting;
    + 3   union rcu_special rcu_read_unlock_special;
    + 4   struct list_head rcu_node_entry;
    + 5   struct rcu_node *rcu_blocked_node;
    + 6 #endif /* #ifdef CONFIG_PREEMPT_RCU */
    + 7 #ifdef CONFIG_TASKS_RCU
    + 8   unsigned long rcu_tasks_nvcsw;
    + 9   bool rcu_tasks_holdout;
    +10   struct list_head rcu_tasks_holdout_list;
    +11   int rcu_tasks_idle_cpu;
    +12 #endif /* #ifdef CONFIG_TASKS_RCU */
    +
    + +

    The ->rcu_read_lock_nesting field records the +nesting level for RCU read-side critical sections, and +the ->rcu_read_unlock_special field is a bitmask +that records special conditions that require rcu_read_unlock() +to do additional work. +The ->rcu_node_entry field is used to form lists of +tasks that have blocked within preemptible-RCU read-side critical +sections and the ->rcu_blocked_node field references +the rcu_node structure whose list this task is a member of, +or NULL if it is not blocked within a preemptible-RCU +read-side critical section. + +

    The ->rcu_tasks_nvcsw field tracks the number of +voluntary context switches that this task had undergone at the +beginning of the current tasks-RCU grace period, +->rcu_tasks_holdout is set if the current tasks-RCU +grace period is waiting on this task, ->rcu_tasks_holdout_list +is a list element enqueuing this task on the holdout list, +and ->rcu_tasks_idle_cpu tracks which CPU this +idle task is running, but only if the task is currently running, +that is, if the CPU is currently idle. + +

    +Accessor Functions

    + +

    The following listing shows the +rcu_get_root(), rcu_for_each_node_breadth_first, +rcu_for_each_nonleaf_node_breadth_first(), and +rcu_for_each_leaf_node() function and macros: + +

    +  1 static struct rcu_node *rcu_get_root(struct rcu_state *rsp)
    +  2 {
    +  3   return &rsp->node[0];
    +  4 }
    +  5
    +  6 #define rcu_for_each_node_breadth_first(rsp, rnp) \
    +  7   for ((rnp) = &(rsp)->node[0]; \
    +  8        (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
    +  9
    + 10 #define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \
    + 11   for ((rnp) = &(rsp)->node[0]; \
    + 12        (rnp) < (rsp)->level[NUM_RCU_LVLS - 1]; (rnp)++)
    + 13
    + 14 #define rcu_for_each_leaf_node(rsp, rnp) \
    + 15   for ((rnp) = (rsp)->level[NUM_RCU_LVLS - 1]; \
    + 16        (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
    +
    + +

    The rcu_get_root() simply returns a pointer to the +first element of the specified rcu_state structure's +->node[] array, which is the root rcu_node +structure. + +

    As noted earlier, the rcu_for_each_node_breadth_first() +macro takes advantage of the layout of the rcu_node +structures in the rcu_state structure's +->node[] array, performing a breadth-first traversal by +simply traversing the array in order. +The rcu_for_each_nonleaf_node_breadth_first() macro operates +similarly, but traverses only the first part of the array, thus excluding +the leaf rcu_node structures. +Finally, the rcu_for_each_leaf_node() macro traverses only +the last part of the array, thus traversing only the leaf +rcu_node structures. + + + + + + + + +
     
    Quick Quiz:
    + What do rcu_for_each_nonleaf_node_breadth_first() and + rcu_for_each_leaf_node() do if the rcu_node tree + contains only a single node? +
    Answer:
    + In the single-node case, + rcu_for_each_nonleaf_node_breadth_first() is a no-op + and rcu_for_each_leaf_node() traverses the single node. +
     
    + +

    +Summary

    + +So each flavor of RCU is represented by an rcu_state structure, +which contains a combining tree of rcu_node and +rcu_data structures. +Finally, in CONFIG_NO_HZ_IDLE kernels, each CPU's dyntick-idle +state is tracked by an rcu_dynticks structure. + +If you made it this far, you are well prepared to read the code +walkthroughs in the other articles in this series. + +

    +Acknowledgments

    + +I owe thanks to Cyrill Gorcunov, Mathieu Desnoyers, Dhaval Giani, Paul +Turner, Abhishek Srivastava, Matt Kowalczyk, and Serge Hallyn +for helping me get this document into a more human-readable state. + +

    +Legal Statement

    + +

    This work represents the view of the author and does not necessarily +represent the view of IBM. + +

    Linux is a registered trademark of Linus Torvalds. + +

    Other company, product, and service names may be trademarks or +service marks of others. + + diff --git a/Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg b/Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg new file mode 100644 index 000000000000..2bf12b468206 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg @@ -0,0 +1,939 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rcu_node + + struct + + struct + + rcu_node + + struct + + rcu_node + + rcu_node + + struct + + rcu_node + + struct + + struct + + rcu_node + + CPU 0 + + struct + + rcu_data + + CPU 15 + + struct + + rcu_data + + struct + + rcu_data + + CPU 21823 + + CPU 21839 + + rcu_data + + struct + + struct + + rcu_data + + CPU 43679 + + CPU 43695 + + rcu_data + + struct + + struct + + rcu_data + + CPU 65519 + + CPU 65535 + + rcu_data + + struct + + struct rcu_state + + struct + + rcu_node + + diff --git a/Documentation/RCU/Design/Data-Structures/TreeLevel.svg b/Documentation/RCU/Design/Data-Structures/TreeLevel.svg new file mode 100644 index 000000000000..7a7eb3bac95c --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/TreeLevel.svg @@ -0,0 +1,828 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rcu_node + + struct + + struct + + rcu_node + + struct + + rcu_node + + rcu_node + + struct + + rcu_node + + struct + + struct + + rcu_node + + ->level[0] + + ->level[1] + + ->level[2] + + struct + + rcu_node + + CPU 15 + + CPU 0 + + CPU 65535 + + CPU 65519 + + CPU 43695 + + CPU 43679 + + CPU 21839 + + CPU 21823 + + struct rcu_state + + diff --git a/Documentation/RCU/Design/Data-Structures/TreeMapping.svg b/Documentation/RCU/Design/Data-Structures/TreeMapping.svg new file mode 100644 index 000000000000..729cfa9e6cdb --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/TreeMapping.svg @@ -0,0 +1,305 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0:7 + + 4:7 + + 0:1 + + 2:3 + + 4:5 + + 6:7 + + 0:3 + + struct rcu_state + + diff --git a/Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg b/Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg new file mode 100644 index 000000000000..5b416a4b8453 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg @@ -0,0 +1,380 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ->level[0] + + ->level[1] + + ->level[2] + + 0:7 + + 4:7 + + 0:1 + + 2:3 + + 4:5 + + 6:7 + + 0:3 + + struct rcu_state + + + + + + + + + diff --git a/Documentation/RCU/Design/Data-Structures/blkd_task.svg b/Documentation/RCU/Design/Data-Structures/blkd_task.svg new file mode 100644 index 000000000000..00e810bb8419 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/blkd_task.svg @@ -0,0 +1,843 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rcu_bh + + struct + + rcu_node + + struct + + rcu_node + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct + + rcu_data + + struct rcu_state + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + struct + + rcu_dynticks + + rcu_sched + + T3 + + T2 + + T1 + + + + + + + + + + + + + rcu_node + + struct + + blkd_tasks + + gp_tasks + + exp_tasks + + diff --git a/Documentation/RCU/Design/Data-Structures/nxtlist.svg b/Documentation/RCU/Design/Data-Structures/nxtlist.svg new file mode 100644 index 000000000000..abc4cc73a097 --- /dev/null +++ b/Documentation/RCU/Design/Data-Structures/nxtlist.svg @@ -0,0 +1,396 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nxtlist + + nxttail[RCU_DONE_TAIL] + + nxttail[RCU_WAIT_TAIL] + + nxttail[RCU_NEXT_READY_TAIL] + + nxttail[RCU_NEXT_TAIL] + + CB 1 + + next + + CB 3 + + next + + CB 4 + + next + + CB 2 + + next + + -- GitLab From 34b82026a507ec0092398d9fc7893c00dd11b7da Mon Sep 17 00:00:00 2001 From: Max Uvarov Date: Wed, 13 Apr 2016 12:52:16 +0300 Subject: [PATCH 3525/9938] fdt: fix extend of cmd line On arm CONFIG_CMDLINE_EXTEND does not append build-in cmdline in kernel to U-boot parameters. Fix it here. Theoretically this patch should repair kdump work where it adds elfcorehdr= and memmap additional parameters to second kernel. Signed-off-by: Max Uvarov Signed-off-by: Rob Herring --- drivers/of/fdt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 3349d2aa6634..5e897bfe6628 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -969,10 +969,16 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, * is set in which case we override whatever was found earlier. */ #ifdef CONFIG_CMDLINE -#ifndef CONFIG_CMDLINE_FORCE +#if defined(CONFIG_CMDLINE_EXTEND) + strlcat(data, " ", COMMAND_LINE_SIZE); + strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#elif defined(CONFIG_CMDLINE_FORCE) + strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#else + /* No arguments from boot loader, use kernel's cmdl*/ if (!((char *)data)[0]) -#endif strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif #endif /* CONFIG_CMDLINE */ pr_debug("Command line is: %s\n", (char*)data); -- GitLab From 74e1fbb1375a3ede3e17da22911761ce9bc8f53f Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 4 Apr 2016 17:49:17 +0200 Subject: [PATCH 3526/9938] of: Introduce struct of_phandle_iterator This struct carrys all necessary information to iterate over a list of phandles and extract the arguments. Add an init-function for the iterator and make use of it in __of_parse_phandle_with_args(). Signed-off-by: Joerg Roedel Signed-off-by: Rob Herring --- drivers/of/base.c | 99 ++++++++++++++++++++++++++++------------------ include/linux/of.h | 33 ++++++++++++++++ 2 files changed, 93 insertions(+), 39 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index b299de2b3afa..1c6f43b5737d 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1440,35 +1440,56 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk("\n"); } +int of_phandle_iterator_init(struct of_phandle_iterator *it, + const struct device_node *np, + const char *list_name, + const char *cells_name, + int cell_count) +{ + const __be32 *list; + int size; + + memset(it, 0, sizeof(*it)); + + list = of_get_property(np, list_name, &size); + if (!list) + return -ENOENT; + + it->cells_name = cells_name; + it->cell_count = cell_count; + it->parent = np; + it->list_end = list + size / sizeof(*list); + it->phandle_end = list; + it->cur = list; + + return 0; +} + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int cell_count, int index, struct of_phandle_args *out_args) { - const __be32 *list, *list_end; - int rc = 0, size, cur_index = 0; - uint32_t count = 0; - struct device_node *node = NULL; - phandle phandle; + struct of_phandle_iterator it; + int rc, cur_index = 0; - /* Retrieve the phandle list property */ - list = of_get_property(np, list_name, &size); - if (!list) - return -ENOENT; - list_end = list + size / sizeof(*list); + rc = of_phandle_iterator_init(&it, np, list_name, + cells_name, cell_count); + if (rc) + return rc; /* Loop over the phandles until all the requested entry is found */ - while (list < list_end) { + while (it.cur < it.list_end) { rc = -EINVAL; - count = 0; + it.cur_count = 0; /* * If phandle is 0, then it is an empty entry with no * arguments. Skip forward to the next entry. */ - phandle = be32_to_cpup(list++); - if (phandle) { + it.phandle = be32_to_cpup(it.cur++); + if (it.phandle) { /* * Find the provider node and parse the #*-cells * property to determine the argument length. @@ -1478,34 +1499,34 @@ static int __of_parse_phandle_with_args(const struct device_node *np, * except when we're going to return the found node * below. */ - if (cells_name || cur_index == index) { - node = of_find_node_by_phandle(phandle); - if (!node) { + if (it.cells_name || cur_index == index) { + it.node = of_find_node_by_phandle(it.phandle); + if (!it.node) { pr_err("%s: could not find phandle\n", - np->full_name); + it.parent->full_name); goto err; } } - if (cells_name) { - if (of_property_read_u32(node, cells_name, - &count)) { + if (it.cells_name) { + if (of_property_read_u32(it.node, it.cells_name, + &it.cur_count)) { pr_err("%s: could not get %s for %s\n", - np->full_name, cells_name, - node->full_name); + it.parent->full_name, it.cells_name, + it.node->full_name); goto err; } } else { - count = cell_count; + it.cur_count = it.cell_count; } /* * Make sure that the arguments actually fit in the * remaining property data length */ - if (list + count > list_end) { + if (it.cur + it.cur_count > it.list_end) { pr_err("%s: arguments longer than property\n", - np->full_name); + it.parent->full_name); goto err; } } @@ -1518,28 +1539,28 @@ static int __of_parse_phandle_with_args(const struct device_node *np, */ rc = -ENOENT; if (cur_index == index) { - if (!phandle) + if (!it.phandle) goto err; if (out_args) { int i; - if (WARN_ON(count > MAX_PHANDLE_ARGS)) - count = MAX_PHANDLE_ARGS; - out_args->np = node; - out_args->args_count = count; - for (i = 0; i < count; i++) - out_args->args[i] = be32_to_cpup(list++); + if (WARN_ON(it.cur_count > MAX_PHANDLE_ARGS)) + it.cur_count = MAX_PHANDLE_ARGS; + out_args->np = it.node; + out_args->args_count = it.cur_count; + for (i = 0; i < it.cur_count; i++) + out_args->args[i] = be32_to_cpup(it.cur++); } else { - of_node_put(node); + of_node_put(it.node); } /* Found it! return success */ return 0; } - of_node_put(node); - node = NULL; - list += count; + of_node_put(it.node); + it.node = NULL; + it.cur += it.cur_count; cur_index++; } @@ -1551,8 +1572,8 @@ static int __of_parse_phandle_with_args(const struct device_node *np, */ rc = index < 0 ? cur_index : -ENOENT; err: - if (node) - of_node_put(node); + if (it.node) + of_node_put(it.node); return rc; } diff --git a/include/linux/of.h b/include/linux/of.h index 7fcb681baadf..0f187dbb890b 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -75,6 +75,23 @@ struct of_phandle_args { uint32_t args[MAX_PHANDLE_ARGS]; }; +struct of_phandle_iterator { + /* Common iterator information */ + const char *cells_name; + int cell_count; + const struct device_node *parent; + + /* List size information */ + const __be32 *list_end; + const __be32 *phandle_end; + + /* Current position state */ + const __be32 *cur; + uint32_t cur_count; + phandle phandle; + struct device_node *node; +}; + struct of_reconfig_data { struct device_node *dn; struct property *prop; @@ -334,6 +351,13 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name); +/* phandle iterator functions */ +extern int of_phandle_iterator_init(struct of_phandle_iterator *it, + const struct device_node *np, + const char *list_name, + const char *cells_name, + int cell_count); + extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of_alias_get_id(struct device_node *np, const char *stem); extern int of_alias_get_highest_id(const char *stem); @@ -608,6 +632,15 @@ static inline int of_count_phandle_with_args(struct device_node *np, return -ENOSYS; } +static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, + const struct device_node *np, + const char *list_name, + const char *cells_name, + int cell_count) +{ + return -ENOSYS; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; -- GitLab From cd209b412c8a5d632b51af1e45576f0d00b8105f Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 4 Apr 2016 17:49:18 +0200 Subject: [PATCH 3527/9938] of: Move phandle walking to of_phandle_iterator_next() Move the code to walk over the phandles out of the loop in __of_parse_phandle_with_args() to a separate function that just works with the iterator handle: of_phandle_iterator_next(). Signed-off-by: Joerg Roedel Signed-off-by: Rob Herring --- drivers/of/base.c | 130 ++++++++++++++++++++++++++------------------- include/linux/of.h | 7 +++ 2 files changed, 81 insertions(+), 56 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 1c6f43b5737d..69286ec206f7 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1465,6 +1465,75 @@ int of_phandle_iterator_init(struct of_phandle_iterator *it, return 0; } +int of_phandle_iterator_next(struct of_phandle_iterator *it) +{ + uint32_t count = 0; + + if (it->node) { + of_node_put(it->node); + it->node = NULL; + } + + if (!it->cur || it->phandle_end >= it->list_end) + return -ENOENT; + + it->cur = it->phandle_end; + + /* If phandle is 0, then it is an empty entry with no arguments. */ + it->phandle = be32_to_cpup(it->cur++); + + if (it->phandle) { + + /* + * Find the provider node and parse the #*-cells property to + * determine the argument length. + */ + it->node = of_find_node_by_phandle(it->phandle); + + if (it->cells_name) { + if (!it->node) { + pr_err("%s: could not find phandle\n", + it->parent->full_name); + goto err; + } + + if (of_property_read_u32(it->node, it->cells_name, + &count)) { + pr_err("%s: could not get %s for %s\n", + it->parent->full_name, + it->cells_name, + it->node->full_name); + goto err; + } + } else { + count = it->cell_count; + } + + /* + * Make sure that the arguments actually fit in the remaining + * property data length + */ + if (it->cur + count > it->list_end) { + pr_err("%s: arguments longer than property\n", + it->parent->full_name); + goto err; + } + } + + it->phandle_end = it->cur + count; + it->cur_count = count; + + return 0; + +err: + if (it->node) { + of_node_put(it->node); + it->node = NULL; + } + + return -EINVAL; +} + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, @@ -1480,59 +1549,9 @@ static int __of_parse_phandle_with_args(const struct device_node *np, return rc; /* Loop over the phandles until all the requested entry is found */ - while (it.cur < it.list_end) { - rc = -EINVAL; - it.cur_count = 0; - - /* - * If phandle is 0, then it is an empty entry with no - * arguments. Skip forward to the next entry. - */ - it.phandle = be32_to_cpup(it.cur++); - if (it.phandle) { - /* - * Find the provider node and parse the #*-cells - * property to determine the argument length. - * - * This is not needed if the cell count is hard-coded - * (i.e. cells_name not set, but cell_count is set), - * except when we're going to return the found node - * below. - */ - if (it.cells_name || cur_index == index) { - it.node = of_find_node_by_phandle(it.phandle); - if (!it.node) { - pr_err("%s: could not find phandle\n", - it.parent->full_name); - goto err; - } - } - - if (it.cells_name) { - if (of_property_read_u32(it.node, it.cells_name, - &it.cur_count)) { - pr_err("%s: could not get %s for %s\n", - it.parent->full_name, it.cells_name, - it.node->full_name); - goto err; - } - } else { - it.cur_count = it.cell_count; - } - - /* - * Make sure that the arguments actually fit in the - * remaining property data length - */ - if (it.cur + it.cur_count > it.list_end) { - pr_err("%s: arguments longer than property\n", - it.parent->full_name); - goto err; - } - } - + while ((rc = of_phandle_iterator_next(&it)) == 0) { /* - * All of the error cases above bail out of the loop, so at + * All of the error cases bail out of the loop, so at * this point, the parsing is successful. If the requested * index matches, then fill the out_args structure and return, * or return -ENOENT for an empty entry. @@ -1558,9 +1577,6 @@ static int __of_parse_phandle_with_args(const struct device_node *np, return 0; } - of_node_put(it.node); - it.node = NULL; - it.cur += it.cur_count; cur_index++; } @@ -1570,7 +1586,9 @@ static int __of_parse_phandle_with_args(const struct device_node *np, * -EINVAL : parsing error on data * [1..n] : Number of phandle (count mode; when index = -1) */ - rc = index < 0 ? cur_index : -ENOENT; + if (rc == -ENOENT && index < 0) + rc = cur_index; + err: if (it.node) of_node_put(it.node); diff --git a/include/linux/of.h b/include/linux/of.h index 0f187dbb890b..1f5e108f6716 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -358,6 +358,8 @@ extern int of_phandle_iterator_init(struct of_phandle_iterator *it, const char *cells_name, int cell_count); +extern int of_phandle_iterator_next(struct of_phandle_iterator *it); + extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of_alias_get_id(struct device_node *np, const char *stem); extern int of_alias_get_highest_id(const char *stem); @@ -641,6 +643,11 @@ static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, return -ENOSYS; } +static inline int of_phandle_iterator_next(struct of_phandle_iterator *it) +{ + return -ENOSYS; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; -- GitLab From 2021bd01ffccf2728a591070008d7de5bc41306a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 4 Apr 2016 17:49:19 +0200 Subject: [PATCH 3528/9938] of: Remove counting special case from __of_parse_phandle_with_args() The index = -1 case in __of_parse_phandle_with_args() is used to just return the number of phandles. That special case needs extra handling, so move it to the place where it is needed: of_count_phandle_with_args(). This allows to further simplify __of_parse_phandle_with_args() later on. Signed-off-by: Joerg Roedel Signed-off-by: Rob Herring --- drivers/of/base.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 69286ec206f7..fcff2b62ec10 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1584,10 +1584,7 @@ static int __of_parse_phandle_with_args(const struct device_node *np, * Unlock node before returning result; will be one of: * -ENOENT : index is for empty phandle * -EINVAL : parsing error on data - * [1..n] : Number of phandle (count mode; when index = -1) */ - if (rc == -ENOENT && index < 0) - rc = cur_index; err: if (it.node) @@ -1723,8 +1720,20 @@ EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name) { - return __of_parse_phandle_with_args(np, list_name, cells_name, 0, -1, - NULL); + struct of_phandle_iterator it; + int rc, cur_index = 0; + + rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0); + if (rc) + return rc; + + while ((rc = of_phandle_iterator_next(&it)) == 0) + cur_index += 1; + + if (rc != -ENOENT) + return rc; + + return cur_index; } EXPORT_SYMBOL(of_count_phandle_with_args); -- GitLab From f623ce95a51baee6a6638f0b025efc0229a9ac0d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 4 Apr 2016 17:49:20 +0200 Subject: [PATCH 3529/9938] of: Introduce of_for_each_phandle() helper macro With this macro any user can easily iterate over a list of phandles. The patch also converts __of_parse_phandle_with_args() to make use of the macro. The of_count_phandle_with_args() function is not converted, because the macro hides the return value of of_phandle_iterator_init(), which is needed in there. Signed-off-by: Joerg Roedel Signed-off-by: Rob Herring --- drivers/of/base.c | 7 +------ include/linux/of.h | 6 ++++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index fcff2b62ec10..ea5a13d3c5a5 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1543,13 +1543,8 @@ static int __of_parse_phandle_with_args(const struct device_node *np, struct of_phandle_iterator it; int rc, cur_index = 0; - rc = of_phandle_iterator_init(&it, np, list_name, - cells_name, cell_count); - if (rc) - return rc; - /* Loop over the phandles until all the requested entry is found */ - while ((rc = of_phandle_iterator_next(&it)) == 0) { + of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) { /* * All of the error cases bail out of the loop, so at * this point, the parsing is successful. If the requested diff --git a/include/linux/of.h b/include/linux/of.h index 1f5e108f6716..b0b80716fbfb 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -908,6 +908,12 @@ static inline int of_property_read_s32(const struct device_node *np, return of_property_read_u32(np, propname, (u32*) out_value); } +#define of_for_each_phandle(it, err, np, ln, cn, cc) \ + for (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)), \ + err = of_phandle_iterator_next(it); \ + err == 0; \ + err = of_phandle_iterator_next(it)) + #define of_property_for_each_u32(np, propname, prop, p, u) \ for (prop = of_find_property(np, propname, NULL), \ p = of_prop_next_u32(prop, NULL, &u); \ -- GitLab From abdaa77b18480361f3565d958a2acffad268c39c Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 4 Apr 2016 17:49:21 +0200 Subject: [PATCH 3530/9938] of: Introduce of_phandle_iterator_args() This helper function can be used to copy the arguments of a phandle to an array. Signed-off-by: Joerg Roedel Signed-off-by: Rob Herring --- drivers/of/base.c | 29 +++++++++++++++++++++++------ include/linux/of.h | 10 ++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ea5a13d3c5a5..e87e21df19d8 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1534,6 +1534,23 @@ int of_phandle_iterator_next(struct of_phandle_iterator *it) return -EINVAL; } +int of_phandle_iterator_args(struct of_phandle_iterator *it, + uint32_t *args, + int size) +{ + int i, count; + + count = it->cur_count; + + if (WARN_ON(size < count)) + count = size; + + for (i = 0; i < count; i++) + args[i] = be32_to_cpup(it->cur++); + + return count; +} + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, @@ -1557,13 +1574,13 @@ static int __of_parse_phandle_with_args(const struct device_node *np, goto err; if (out_args) { - int i; - if (WARN_ON(it.cur_count > MAX_PHANDLE_ARGS)) - it.cur_count = MAX_PHANDLE_ARGS; + int c; + + c = of_phandle_iterator_args(&it, + out_args->args, + MAX_PHANDLE_ARGS); out_args->np = it.node; - out_args->args_count = it.cur_count; - for (i = 0; i < it.cur_count; i++) - out_args->args[i] = be32_to_cpup(it.cur++); + out_args->args_count = c; } else { of_node_put(it.node); } diff --git a/include/linux/of.h b/include/linux/of.h index b0b80716fbfb..71e1c35a5960 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -359,6 +359,9 @@ extern int of_phandle_iterator_init(struct of_phandle_iterator *it, int cell_count); extern int of_phandle_iterator_next(struct of_phandle_iterator *it); +extern int of_phandle_iterator_args(struct of_phandle_iterator *it, + uint32_t *args, + int size); extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of_alias_get_id(struct device_node *np, const char *stem); @@ -648,6 +651,13 @@ static inline int of_phandle_iterator_next(struct of_phandle_iterator *it) return -ENOSYS; } +static inline int of_phandle_iterator_args(struct of_phandle_iterator *it, + uint32_t *args, + int size) +{ + return 0; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; -- GitLab From cb6c27bb09122ceb0effda0b15885123870a6af7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 4 Apr 2016 17:49:22 +0200 Subject: [PATCH 3531/9938] iommu/arm-smmu: Make use of phandle iterators in device-tree parsing Remove the usage of of_parse_phandle_with_args() and replace it by the phandle-iterator implementation so that we can parse out all of the potentially present 128 stream-ids. Signed-off-by: Joerg Roedel Acked-by: Will Deacon Signed-off-by: Rob Herring --- drivers/iommu/arm-smmu.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 2409e3bd3df2..a1c965cdcfad 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -49,7 +49,7 @@ #include "io-pgtable.h" /* Maximum number of stream IDs assigned to a single device */ -#define MAX_MASTER_STREAMIDS MAX_PHANDLE_ARGS +#define MAX_MASTER_STREAMIDS 128 /* Maximum number of context banks per SMMU */ #define ARM_SMMU_MAX_CBS 128 @@ -357,6 +357,12 @@ struct arm_smmu_domain { struct iommu_domain domain; }; +struct arm_smmu_phandle_args { + struct device_node *np; + int args_count; + uint32_t args[MAX_MASTER_STREAMIDS]; +}; + static struct iommu_ops arm_smmu_ops; static DEFINE_SPINLOCK(arm_smmu_devices_lock); @@ -466,7 +472,7 @@ static int insert_smmu_master(struct arm_smmu_device *smmu, static int register_smmu_master(struct arm_smmu_device *smmu, struct device *dev, - struct of_phandle_args *masterspec) + struct arm_smmu_phandle_args *masterspec) { int i; struct arm_smmu_master *master; @@ -1737,7 +1743,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) struct arm_smmu_device *smmu; struct device *dev = &pdev->dev; struct rb_node *node; - struct of_phandle_args masterspec; + struct of_phandle_iterator it; + struct arm_smmu_phandle_args *masterspec; int num_irqs, i, err; smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); @@ -1798,20 +1805,35 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) i = 0; smmu->masters = RB_ROOT; - while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters", - "#stream-id-cells", i, - &masterspec)) { - err = register_smmu_master(smmu, dev, &masterspec); + + err = -ENOMEM; + /* No need to zero the memory for masterspec */ + masterspec = kmalloc(sizeof(*masterspec), GFP_KERNEL); + if (!masterspec) + goto out_put_masters; + + of_for_each_phandle(&it, err, dev->of_node, + "mmu-masters", "#stream-id-cells", 0) { + int count = of_phandle_iterator_args(&it, masterspec->args, + MAX_MASTER_STREAMIDS); + masterspec->np = of_node_get(it.node); + masterspec->args_count = count; + + err = register_smmu_master(smmu, dev, masterspec); if (err) { dev_err(dev, "failed to add master %s\n", - masterspec.np->name); + masterspec->np->name); + kfree(masterspec); goto out_put_masters; } i++; } + dev_notice(dev, "registered %d master devices\n", i); + kfree(masterspec); + parse_driver_options(smmu); if (smmu->version > ARM_SMMU_V1 && -- GitLab From f2953a461042721e9a2aca58d2b1cfc67c70d371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 16 Mar 2016 12:53:29 +0100 Subject: [PATCH 3532/9938] Documentation: devicetree: Clean up gpio-keys example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop #address-cells and #size-cells, which are not required by the gpio-keys binding documentation, as button sub-nodes are not devices. Rename sub-nodes to avoid new dtc unit address warnings when copied. While at it, adopt the dashes convention for the node name. Reported-by: Julien Chauveau Cc: Julien Chauveau Cc: Javier Martinez Canillas Cc: Geert Uytterhoeven Signed-off-by: Andreas Färber Reviewed-by: Javier Martinez Canillas Reviewed-by: Julien Chauveau Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/input/gpio-keys.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt b/Documentation/devicetree/bindings/input/gpio-keys.txt index 21641236c095..a94940481e55 100644 --- a/Documentation/devicetree/bindings/input/gpio-keys.txt +++ b/Documentation/devicetree/bindings/input/gpio-keys.txt @@ -32,17 +32,17 @@ Optional subnode-properties: Example nodes: - gpio_keys { + gpio-keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; autorepeat; - button@21 { + + up { label = "GPIO Key UP"; linux,code = <103>; gpios = <&gpio1 0 1>; }; - button@22 { + + down { label = "GPIO Key DOWN"; linux,code = <108>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; -- GitLab From ba1800930d79c287dcef043dfc30486d168e05b8 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 17 Mar 2016 14:47:57 +0000 Subject: [PATCH 3533/9938] dt-bindings: Correct path for ARM GIC documentation Commit eb3fcf007fff ("dt-bindings: consolidate interrupt controller bindings") moved the binding documentation for the ARM GIC from arm/gic.txt to interrupt-controller/arm,gic.txt. However, there are still some binding documents referring to the old path. Update these binding documents to use the correct location. Fixes: eb3fcf007fff ("dt-bindings: consolidate interrupt controller bindings") Signed-off-by: Jon Hunter Acked-by: Linus Walleij Acked-by: Matthias Brugger Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/arm/omap/crossbar.txt | 3 ++- Documentation/devicetree/bindings/arm/ux500/boards.txt | 2 +- .../bindings/interrupt-controller/mediatek,sysirq.txt | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt index a9b28d74d902..bb5727ae004a 100644 --- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt +++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt @@ -42,7 +42,8 @@ Examples: Consumer: ======== See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and -Documentation/devicetree/bindings/arm/gic.txt for further details. +Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt for +further details. An interrupt consumer on an SoC using crossbar will use: interrupts = diff --git a/Documentation/devicetree/bindings/arm/ux500/boards.txt b/Documentation/devicetree/bindings/arm/ux500/boards.txt index b8737a8de718..7334c24625fc 100644 --- a/Documentation/devicetree/bindings/arm/ux500/boards.txt +++ b/Documentation/devicetree/bindings/arm/ux500/boards.txt @@ -23,7 +23,7 @@ scu: see binding for arm/scu.txt interrupt-controller: - see binding for arm/gic.txt + see binding for interrupt-controller/arm,gic.txt timer: see binding for arm/twd.txt diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt index b8e1674c7837..8cf564d083d2 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt @@ -16,8 +16,7 @@ Required properties: "mediatek,mt6577-sysirq" "mediatek,mt2701-sysirq" - interrupt-controller : Identifies the node as an interrupt controller -- #interrupt-cells : Use the same format as specified by GIC in - Documentation/devicetree/bindings/arm/gic.txt +- #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt. - interrupt-parent: phandle of irq parent for sysirq. The parent must use the same interrupt-cells format as GIC. - reg: Physical base address of the intpol registers and length of memory -- GitLab From ade50c2dd3f6523f727ed4163a00a5721a602743 Mon Sep 17 00:00:00 2001 From: Schuyler Patton Date: Tue, 29 Mar 2016 18:12:43 +0530 Subject: [PATCH 3534/9938] Documentation: devicetree: bindings: regulator: palmas-pmic.txt Adding support for the tps659038 pmic so it doesn't generate a warning when running the patch check script to Documentation/devicetree/bindings/regulator/palmas-pmic.txt Adding a note that the tps659037 device is a OTP spin of the tps659038 pmic and device compatible. Signed-off-by: Schuyler Patton Signed-off-by: Keerthy Acked-by: Rob Herring Signed-off-by: Rob Herring --- .../devicetree/bindings/regulator/palmas-pmic.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt index 725393c8a7f2..99872819604f 100644 --- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt +++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt @@ -1,5 +1,12 @@ * palmas regulator IP block devicetree bindings +The tps659038 for the AM57x class have OTP spins that +have different part numbers but the same functionality. There +is not a need to add the OTP spins to the palmas driver. The +spin devices should use the tps659038 as it's compatible value. +This is the list of those devices: +tps659037 + Required properties: - compatible : Should be from the list ti,twl6035-pmic @@ -8,6 +15,7 @@ Required properties: ti,tps65913-pmic ti,tps65914-pmic ti,tps65917-pmic + ti,tps659038-pmic and also the generic series names ti,palmas-pmic - interrupt-parent : The parent interrupt controller which is palmas. -- GitLab From 0f18d9245fe8b5613980baa8f03ba2e72d9c071b Mon Sep 17 00:00:00 2001 From: Sergio Prado Date: Sat, 9 Apr 2016 15:14:25 -0300 Subject: [PATCH 3535/9938] of: Add vendor prefix for Shenzhen Embest Technology Signed-off-by: Sergio Prado Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 86740d4a270d..ae99b90e8a7c 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -75,6 +75,7 @@ ebv EBV Elektronik edt Emerging Display Technologies eeti eGalax_eMPIA Technology Inc elan Elan Microelectronic Corp. +embest Shenzhen Embest Technology Co., Ltd. emmicro EM Microelectronic energymicro Silicon Laboratories (formerly Energy Micro AS) epcos EPCOS AG -- GitLab From af6858c3827d6d6aad3ebf2d4762ff1e59d0ed56 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:29:56 +0100 Subject: [PATCH 3536/9938] of: Add Arrow Electronics to vendor prefix list This patch adds Arrow Electronics to vendor perfix list, as this vendor makes some of the Qualcomm SOC based 96boards like DB600c and DB410c. Signed-off-by: Srinivas Kandagatla Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index ae99b90e8a7c..8c42f3343ea7 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -27,6 +27,7 @@ aptina Aptina Imaging arasan Arasan Chip Systems arm ARM Ltd. armadeus ARMadeus Systems SARL +arrow Arrow Electronics artesyn Artesyn Embedded Technologies Inc. asahi-kasei Asahi Kasei Corp. atlas Atlas Scientific LLC -- GitLab From 7aa5d38cfb77d69a349ed47ce26a9d83bd6388d2 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:29:57 +0100 Subject: [PATCH 3537/9938] of: Add Inforce Computing to vendor prefix list This patch adds Inforce Computing to vendor prefix list. This vendor makes boards like IFC6410, IFC6540 based on Qualcomm SOCs. Signed-off-by: Srinivas Kandagatla Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 8c42f3343ea7..bbf51f73e5d1 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -120,6 +120,7 @@ idt Integrated Device Technologies, Inc. ifi Ingenieurburo Fur Ic-Technologie (I/F/I) iom Iomega Corporation img Imagination Technologies Ltd. +inforce Inforce Computing ingenic Ingenic Semiconductor innolux Innolux Corporation intel Intel Corporation -- GitLab From f43521e9521133c169fe4b9255fb0917baf5ec84 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 12 Apr 2016 17:07:35 +0200 Subject: [PATCH 3538/9938] dt-bindings: tegra: Remove 0, prefix from unit-addresses When Tegra124 support was first merged the unit-addresses of all devices were listed with a "0," prefix to encode the reg property's second cell. It turns out that this notation is not correct, and the "," separator is only used to separate fields in the unit address (such as the device and function number in PCI devices), not individual cells for addresses with more than one cell. Acked-by: Stephen Warren Signed-off-by: Thierry Reding Signed-off-by: Rob Herring --- .../devicetree/bindings/clock/nvidia,tegra124-dfll.txt | 2 +- Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt | 2 +- .../bindings/memory-controllers/nvidia,tegra-mc.txt | 6 +++--- .../devicetree/bindings/memory-controllers/tegra-emc.txt | 4 ++-- .../bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt | 6 +++--- .../devicetree/bindings/sound/nvidia,tegra30-hda.txt | 2 +- .../devicetree/bindings/thermal/tegra-soctherm.txt | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt index ee7e5fd4a50b..63f9d8277d48 100644 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt @@ -50,7 +50,7 @@ Required properties for I2C mode: Example: -clock@0,70110000 { +clock@70110000 { compatible = "nvidia,tegra124-dfll"; reg = <0 0x70110000 0 0x100>, /* DFLL control */ <0 0x70110000 0 0x100>, /* I2C output control */ diff --git a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt index 23bfe8e1f7cc..9d47a2c25e2d 100644 --- a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt +++ b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt @@ -26,7 +26,7 @@ Required properties: Example: - gpu@0,57000000 { + gpu@57000000 { compatible = "nvidia,gk20a"; reg = <0x0 0x57000000 0x0 0x01000000>, <0x0 0x58000000 0x0 0x01000000>; diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt index 3338a2834ad7..8dbe47013c2b 100644 --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt @@ -61,7 +61,7 @@ specified, according to the board documentation: Example SoC include file: / { - mc: memory-controller@0,70019000 { + mc: memory-controller@70019000 { compatible = "nvidia,tegra124-mc"; reg = <0x0 0x70019000 0x0 0x1000>; clocks = <&tegra_car TEGRA124_CLK_MC>; @@ -72,7 +72,7 @@ Example SoC include file: #iommu-cells = <1>; }; - sdhci@0,700b0000 { + sdhci@700b0000 { compatible = "nvidia,tegra124-sdhci"; ... iommus = <&mc TEGRA_SWGROUP_SDMMC1A>; @@ -82,7 +82,7 @@ Example SoC include file: Example board file: / { - memory-controller@0,70019000 { + memory-controller@70019000 { emc-timings-3 { nvidia,ram-code = <3>; diff --git a/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt b/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt index b59c625d6336..ba0bc3f12419 100644 --- a/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt +++ b/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt @@ -190,7 +190,7 @@ be specified, according to the board documentation: Example SoC include file: / { - emc@0,7001b000 { + emc@7001b000 { compatible = "nvidia,tegra124-emc"; reg = <0x0 0x7001b000 0x0 0x1000>; @@ -201,7 +201,7 @@ Example SoC include file: Example board file: / { - emc@0,7001b000 { + emc@7001b000 { emc-timings-3 { nvidia,ram-code = <3>; diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt index 30676ded85bb..9c8ddd547a99 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt @@ -79,7 +79,7 @@ Example: SoC file extract: ----------------- - padctl@0,7009f000 { + padctl@7009f000 { compatible = "nvidia,tegra124-xusb-padctl"; reg = <0x0 0x7009f000 0x0 0x1000>; resets = <&tegra_car 142>; @@ -91,7 +91,7 @@ SoC file extract: Board file extract: ------------------- - pcie-controller@0,01003000 { + pcie-controller@01003000 { ... phys = <&padctl 0>; @@ -102,7 +102,7 @@ Board file extract: ... - padctl: padctl@0,7009f000 { + padctl: padctl@7009f000 { pinctrl-0 = <&padctl_default>; pinctrl-names = "default"; diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt index 275c6ea356f6..44d27456e8a4 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt @@ -15,7 +15,7 @@ Required properties: Example: -hda@0,70030000 { +hda@70030000 { compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda"; reg = <0x0 0x70030000 0x0 0x10000>; interrupts = ; diff --git a/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt b/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt index 6b68cd150405..6908d3aca598 100644 --- a/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt +++ b/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt @@ -29,7 +29,7 @@ Required properties : Example : - soctherm@0,700e2000 { + soctherm@700e2000 { compatible = "nvidia,tegra124-soctherm"; reg = <0x0 0x700e2000 0x0 0x1000>; interrupts = ; -- GitLab From a8ca1b28acf543143bb96f62eb1423164accaa53 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 12 Apr 2016 17:07:36 +0200 Subject: [PATCH 3539/9938] dt-bindings: tegra: Rename some bindings for consistency Device tree binding for NVIDIA Tegra have traditionally carried the "nvidia," vendor prefix in the filename. A couple of odd ones don't, so fix them up for consistency. Also rename existing bindings to reflect the first compatible value that they document. This wasn't done consistently either. Acked-by: Stephen Warren Signed-off-by: Thierry Reding Signed-off-by: Rob Herring --- .../bindings/ata/{tegra-sata.txt => nvidia,tegra124-ahci.txt} | 0 .../cpufreq/{tegra124-cpufreq.txt => nvidia,tegra124-cpufreq.txt} | 0 .../dma/{tegra20-apbdma.txt => nvidia,tegra20-apbdma.txt} | 0 .../{nvidia,tegra-ictlr.txt => nvidia,tegra20-ictlr.txt} | 0 .../memory-controllers/{tegra-emc.txt => nvidia,tegra124-emc.txt} | 0 .../{nvidia,tegra-mc.txt => nvidia,tegra30-mc.txt} | 0 .../thermal/{tegra-soctherm.txt => nvidia,tegra124-soctherm.txt} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/ata/{tegra-sata.txt => nvidia,tegra124-ahci.txt} (100%) rename Documentation/devicetree/bindings/cpufreq/{tegra124-cpufreq.txt => nvidia,tegra124-cpufreq.txt} (100%) rename Documentation/devicetree/bindings/dma/{tegra20-apbdma.txt => nvidia,tegra20-apbdma.txt} (100%) rename Documentation/devicetree/bindings/interrupt-controller/{nvidia,tegra-ictlr.txt => nvidia,tegra20-ictlr.txt} (100%) rename Documentation/devicetree/bindings/memory-controllers/{tegra-emc.txt => nvidia,tegra124-emc.txt} (100%) rename Documentation/devicetree/bindings/memory-controllers/{nvidia,tegra-mc.txt => nvidia,tegra30-mc.txt} (100%) rename Documentation/devicetree/bindings/thermal/{tegra-soctherm.txt => nvidia,tegra124-soctherm.txt} (100%) diff --git a/Documentation/devicetree/bindings/ata/tegra-sata.txt b/Documentation/devicetree/bindings/ata/nvidia,tegra124-ahci.txt similarity index 100% rename from Documentation/devicetree/bindings/ata/tegra-sata.txt rename to Documentation/devicetree/bindings/ata/nvidia,tegra124-ahci.txt diff --git a/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra124-cpufreq.txt similarity index 100% rename from Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt rename to Documentation/devicetree/bindings/cpufreq/nvidia,tegra124-cpufreq.txt diff --git a/Documentation/devicetree/bindings/dma/tegra20-apbdma.txt b/Documentation/devicetree/bindings/dma/nvidia,tegra20-apbdma.txt similarity index 100% rename from Documentation/devicetree/bindings/dma/tegra20-apbdma.txt rename to Documentation/devicetree/bindings/dma/nvidia,tegra20-apbdma.txt diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.txt similarity index 100% rename from Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt rename to Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt similarity index 100% rename from Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt rename to Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt similarity index 100% rename from Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt rename to Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt diff --git a/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt similarity index 100% rename from Documentation/devicetree/bindings/thermal/tegra-soctherm.txt rename to Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt -- GitLab From ea9b269fa561c6a4a452e85bc1af7e0288418b53 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 12 Apr 2016 13:01:34 -0700 Subject: [PATCH 3540/9938] devicetree: bindings: designware-pcie: Fix unit address Remove the 0x in the unit address because it shouldn't be there. Cc: Joao Pinto Signed-off-by: Stephen Boyd Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/pci/designware-pcie.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt index 64f2fff12128..6c5322c55411 100644 --- a/Documentation/devicetree/bindings/pci/designware-pcie.txt +++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt @@ -31,7 +31,7 @@ Optional properties: Example configuration: - pcie: pcie@0xdffff000 { + pcie: pcie@dffff000 { compatible = "snps,dw-pcie"; reg = <0xdffff000 0x1000>, /* Controller registers */ <0xd0000000 0x2000>; /* PCI config space */ -- GitLab From 79e577cbce4c4c2bf0d64ec315adb04eda40736b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 3 Mar 2016 12:54:53 -0600 Subject: [PATCH 3541/9938] tracing: Support string type key properly The string in a trace event is usually recorded as dynamic array which is variable length. But current hist code only support fixed length array so it cannot support most strings. This patch fixes it by checking filter_type of the field and get proper pointer with it. With this, it can get a histogram of exec() based on filenames like below: # cd /sys/kernel/tracing/events/sched/sched_process_exec # cat 'hist:key=filename' > trigger # ps PID TTY TIME CMD 1 ? 00:00:00 init 29 ? 00:00:00 sh 38 ? 00:00:00 ps # ls enable filter format hist id trigger # cat hist # trigger info: hist:keys=filename:vals=hitcount:sort=hitcount:size=2048 [active] { filename: /usr/bin/ps } hitcount: 1 { filename: /usr/bin/ls } hitcount: 1 { filename: /usr/bin/cat } hitcount: 1 Totals: Hits: 3 Entries: 3 Dropped: 0 Link: http://lkml.kernel.org/r/610180d6df0cfdf11ee205452f3b241dea657233.1457029949.git.tom.zanussi@linux.intel.com Cc: Tom Zanussi Cc: Masami Hiramatsu Signed-off-by: Namhyung Kim Tested-by: Masami Hiramatsu [ Added (unsigned long) typecast to fix compile warning ] Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 49 +++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 21cae42b54da..418ff27cbbaf 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -52,12 +52,28 @@ static u64 hist_field_string(struct hist_field *hist_field, void *event) return (u64)(unsigned long)addr; } +static u64 hist_field_dynstring(struct hist_field *hist_field, void *event) +{ + u32 str_item = *(u32 *)(event + hist_field->field->offset); + int str_loc = str_item & 0xffff; + char *addr = (char *)(event + str_loc); + + return (u64)(unsigned long)addr; +} + +static u64 hist_field_pstring(struct hist_field *hist_field, void *event) +{ + char **addr = (char **)(event + hist_field->field->offset); + + return (u64)(unsigned long)*addr; +} + #define DEFINE_HIST_FIELD_FN(type) \ static u64 hist_field_##type(struct hist_field *hist_field, void *event)\ { \ type *addr = (type *)(event + hist_field->field->offset); \ \ - return (u64)*addr; \ + return (u64)(unsigned long)*addr; \ } DEFINE_HIST_FIELD_FN(s64); @@ -340,7 +356,13 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field, if (is_string_field(field)) { flags |= HIST_FIELD_FL_STRING; - hist_field->fn = hist_field_string; + + if (field->filter_type == FILTER_STATIC_STRING) + hist_field->fn = hist_field_string; + else if (field->filter_type == FILTER_DYN_STRING) + hist_field->fn = hist_field_dynstring; + else + hist_field->fn = hist_field_pstring; } else { hist_field->fn = select_value_fn(field->size, field->is_signed); @@ -508,7 +530,10 @@ static int create_key_field(struct hist_trigger_data *hist_data, goto out; } - key_size = field->size; + if (is_string_field(field)) /* should be last key field */ + key_size = HIST_KEY_SIZE_MAX - key_offset; + else + key_size = field->size; } hist_data->fields[key_idx] = create_hist_field(field, flags); @@ -841,8 +866,24 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) key = (void *)&field_contents; if (hist_data->n_keys > 1) { + /* ensure NULL-termination */ + size_t size = key_field->size - 1; + + if (key_field->flags & HIST_FIELD_FL_STRING) { + struct ftrace_event_field *field; + + field = key_field->field; + if (field->filter_type == FILTER_DYN_STRING) + size = *(u32 *)(rec + field->offset) >> 16; + else if (field->filter_type == FILTER_PTR_STRING) + size = strlen(key); + + if (size > key_field->size - 1) + size = key_field->size - 1; + } + memcpy(compound_key + key_field->offset, key, - key_field->size); + size); } } } -- GitLab From a4b8c18c40704c28be62af4606cc6758c9ff3dba Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 14 Apr 2016 10:33:16 +0200 Subject: [PATCH 3542/9938] ARM: shmobile: timer: Drop support for Cortex A8 Commit edf4100906044225 ("ARM: shmobile: sh7372 dtsi: Remove Legacy file") removed the DTS for the last shmobile SoC with a Cortex A8 CPU core (sh7372 aka SH-Mobile AP4), hence drop support for it in the loops-per-jiffy preset code. As "div" is always 1 for supported contemporary ARM processors, we can simplify the code: - Absorb shmobile_setup_delay_hz(), which was always called with mult = div = 1, - Return earlier if the Cortex A7/A15 arch timer exists and support is enabled. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/timer.c | 52 +++++++++++++--------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index 67d79f9c6bad..6196a6380385 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c @@ -20,28 +20,9 @@ #include "common.h" -static void __init shmobile_setup_delay_hz(unsigned int max_cpu_core_hz, - unsigned int mult, unsigned int div) -{ - /* calculate a worst-case loops-per-jiffy value - * based on maximum cpu core hz setting and the - * __delay() implementation in arch/arm/lib/delay.S - * - * this will result in a longer delay than expected - * when the cpu core runs on lower frequencies. - */ - - unsigned int value = HZ * div / mult; - - if (!preset_lpj) - preset_lpj = max_cpu_core_hz / value; -} - void __init shmobile_init_delay(void) { struct device_node *np, *cpus; - unsigned int div = 0; - bool has_arch_timer = false; u32 max_freq = 0; cpus = of_find_node_by_path("/cpus"); @@ -51,25 +32,32 @@ void __init shmobile_init_delay(void) for_each_child_of_node(cpus, np) { u32 freq; + if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER) && + (of_device_is_compatible(np, "arm,cortex-a7") || + of_device_is_compatible(np, "arm,cortex-a15"))) { + of_node_put(np); + of_node_put(cpus); + return; + } + if (!of_property_read_u32(np, "clock-frequency", &freq)) max_freq = max(max_freq, freq); - - if (of_device_is_compatible(np, "arm,cortex-a8")) { - div = 2; - } else if (of_device_is_compatible(np, "arm,cortex-a9")) { - div = 1; - } else if (of_device_is_compatible(np, "arm,cortex-a7") || - of_device_is_compatible(np, "arm,cortex-a15")) { - div = 1; - has_arch_timer = true; - } } of_node_put(cpus); - if (!max_freq || !div) + if (!max_freq) return; - if (!has_arch_timer || !IS_ENABLED(CONFIG_ARM_ARCH_TIMER)) - shmobile_setup_delay_hz(max_freq, 1, div); + /* + * Calculate a worst-case loops-per-jiffy value + * based on maximum cpu core hz setting and the + * __delay() implementation in arch/arm/lib/delay.S. + * + * This will result in a longer delay than expected + * when the cpu core runs on lower frequencies. + */ + + if (!preset_lpj) + preset_lpj = max_freq / HZ; } -- GitLab From 6a475cb17fe161dbde62eca7e4c2cf59edff182f Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:54 -0600 Subject: [PATCH 3543/9938] tracing: Remove restriction on string position in hist trigger keys If we assume the maximum size for a string field, we don't have to worry about its position. Since we only allow two keys in a compound key and having more than one string key in a given compound key doesn't make much sense anyway, trading a bit of extra space instead of introducing an arbitrary restriction makes more sense. We also need to use the event field size for static strings when copying the contents, otherwise we get random garbage in the key. Also, cast string return values to avoid warnings on 32-bit compiles. Finally, rearrange the code without changing any functionality by moving the compound key updating code into a separate function. Link: http://lkml.kernel.org/r/8976e1ab04b66bc2700ad1ed0768a2de85ac1983.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 63 ++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 418ff27cbbaf..4f4041d76926 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -530,8 +530,8 @@ static int create_key_field(struct hist_trigger_data *hist_data, goto out; } - if (is_string_field(field)) /* should be last key field */ - key_size = HIST_KEY_SIZE_MAX - key_offset; + if (is_string_field(field)) + key_size = MAX_FILTER_STR_VAL; else key_size = field->size; } @@ -830,9 +830,34 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, } } +static inline void add_to_key(char *compound_key, void *key, + struct hist_field *key_field, void *rec) +{ + size_t size = key_field->size; + + if (key_field->flags & HIST_FIELD_FL_STRING) { + struct ftrace_event_field *field; + + field = key_field->field; + if (field->filter_type == FILTER_DYN_STRING) + size = *(u32 *)(rec + field->offset) >> 16; + else if (field->filter_type == FILTER_PTR_STRING) + size = strlen(key); + else if (field->filter_type == FILTER_STATIC_STRING) + size = field->size; + + /* ensure NULL-termination */ + if (size > key_field->size - 1) + size = key_field->size - 1; + } + + memcpy(compound_key + key_field->offset, key, size); +} + static void event_hist_trigger(struct event_trigger_data *data, void *rec) { struct hist_trigger_data *hist_data = data->private_data; + bool use_compound_key = (hist_data->n_keys > 1); unsigned long entries[HIST_STACKTRACE_DEPTH]; char compound_key[HIST_KEY_SIZE_MAX]; struct stack_trace stacktrace; @@ -842,8 +867,7 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) void *key = NULL; unsigned int i; - if (hist_data->n_keys > 1) - memset(compound_key, 0, hist_data->key_size); + memset(compound_key, 0, hist_data->key_size); for_each_hist_key_field(i, hist_data) { key_field = hist_data->fields[i]; @@ -860,35 +884,18 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) key = entries; } else { field_contents = key_field->fn(key_field, rec); - if (key_field->flags & HIST_FIELD_FL_STRING) + if (key_field->flags & HIST_FIELD_FL_STRING) { key = (void *)(unsigned long)field_contents; - else + use_compound_key = true; + } else key = (void *)&field_contents; - - if (hist_data->n_keys > 1) { - /* ensure NULL-termination */ - size_t size = key_field->size - 1; - - if (key_field->flags & HIST_FIELD_FL_STRING) { - struct ftrace_event_field *field; - - field = key_field->field; - if (field->filter_type == FILTER_DYN_STRING) - size = *(u32 *)(rec + field->offset) >> 16; - else if (field->filter_type == FILTER_PTR_STRING) - size = strlen(key); - - if (size > key_field->size - 1) - size = key_field->size - 1; - } - - memcpy(compound_key + key_field->offset, key, - size); - } } + + if (use_compound_key) + add_to_key(compound_key, key, key_field, rec); } - if (hist_data->n_keys > 1) + if (use_compound_key) key = compound_key; elt = tracing_map_insert(hist_data->map, key); -- GitLab From d0bad49bb0a094a1beb06640785f95cb256b7272 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:55 -0600 Subject: [PATCH 3544/9938] tracing: Add enable_hist/disable_hist triggers Similar to enable_event/disable_event triggers, these triggers enable and disable the aggregation of events into maps rather than enabling and disabling their writing into the trace buffer. They can be used to automatically start and stop hist triggers based on a matching filter condition. If there's a paused hist trigger on system:event, the following would start it when the filter condition was hit: # echo enable_hist:system:event [ if filter] > event/trigger And the following would disable a running system:event hist trigger: # echo disable_hist:system:event [ if filter] > event/trigger See Documentation/trace/events.txt for real examples. Link: http://lkml.kernel.org/r/f812f086e52c8b7c8ad5443487375e03c96a601f.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- include/linux/trace_events.h | 1 + kernel/trace/trace.c | 8 ++ kernel/trace/trace.h | 32 ++++++++ kernel/trace/trace_events_hist.c | 115 ++++++++++++++++++++++++++++ kernel/trace/trace_events_trigger.c | 71 +++++++++-------- 5 files changed, 196 insertions(+), 31 deletions(-) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 404603720650..5f89a5b0c7e6 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -408,6 +408,7 @@ enum event_trigger_type { ETT_STACKTRACE = (1 << 2), ETT_EVENT_ENABLE = (1 << 3), ETT_EVENT_HIST = (1 << 4), + ETT_HIST_ENABLE = (1 << 5), }; extern int filter_match_preds(struct event_filter *filter, void *rec); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 2238bfde799b..8430145bea12 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3807,6 +3807,10 @@ static const char readme_msg[] = "\t trigger: traceon, traceoff\n" "\t enable_event::\n" "\t disable_event::\n" +#ifdef CONFIG_HIST_TRIGGERS + "\t enable_hist::\n" + "\t disable_hist::\n" +#endif #ifdef CONFIG_STACKTRACE "\t\t stacktrace\n" #endif @@ -3867,6 +3871,10 @@ static const char readme_msg[] = "\t The 'clear' parameter will clear the contents of a running\n" "\t hist trigger and leave its current paused/active state\n" "\t unchanged.\n\n" + "\t The enable_hist and disable_hist triggers can be used to\n" + "\t have one event conditionally start and stop another event's\n" + "\t already-attached hist trigger. The syntax is analagous to\n" + "\t the enable_event and disable_event triggers.\n" #endif ; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 505f8a45f426..cab1f4bfe85b 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1166,8 +1166,10 @@ extern const struct file_operations event_hist_fops; #ifdef CONFIG_HIST_TRIGGERS extern int register_trigger_hist_cmd(void); +extern int register_trigger_hist_enable_disable_cmds(void); #else static inline int register_trigger_hist_cmd(void) { return 0; } +static inline int register_trigger_hist_enable_disable_cmds(void) { return 0; } #endif extern int register_trigger_cmds(void); @@ -1185,6 +1187,34 @@ struct event_trigger_data { struct list_head list; }; +/* Avoid typos */ +#define ENABLE_EVENT_STR "enable_event" +#define DISABLE_EVENT_STR "disable_event" +#define ENABLE_HIST_STR "enable_hist" +#define DISABLE_HIST_STR "disable_hist" + +struct enable_trigger_data { + struct trace_event_file *file; + bool enable; + bool hist; +}; + +extern int event_enable_trigger_print(struct seq_file *m, + struct event_trigger_ops *ops, + struct event_trigger_data *data); +extern void event_enable_trigger_free(struct event_trigger_ops *ops, + struct event_trigger_data *data); +extern int event_enable_trigger_func(struct event_command *cmd_ops, + struct trace_event_file *file, + char *glob, char *cmd, char *param); +extern int event_enable_register_trigger(char *glob, + struct event_trigger_ops *ops, + struct event_trigger_data *data, + struct trace_event_file *file); +extern void event_enable_unregister_trigger(char *glob, + struct event_trigger_ops *ops, + struct event_trigger_data *test, + struct trace_event_file *file); extern void trigger_data_free(struct event_trigger_data *data); extern int event_trigger_init(struct event_trigger_ops *ops, struct event_trigger_data *data); @@ -1198,6 +1228,8 @@ extern int set_trigger_filter(char *filter_str, struct event_trigger_data *trigger_data, struct trace_event_file *file); extern int register_event_command(struct event_command *cmd); +extern int unregister_event_command(struct event_command *cmd); +extern int register_trigger_hist_enable_disable_cmds(void); /** * struct event_trigger_ops - callbacks for trace event triggers diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 4f4041d76926..5d4f02792440 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1393,3 +1393,118 @@ __init int register_trigger_hist_cmd(void) return ret; } + +static void +hist_enable_trigger(struct event_trigger_data *data, void *rec) +{ + struct enable_trigger_data *enable_data = data->private_data; + struct event_trigger_data *test; + + list_for_each_entry_rcu(test, &enable_data->file->triggers, list) { + if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { + if (enable_data->enable) + test->paused = false; + else + test->paused = true; + break; + } + } +} + +static void +hist_enable_count_trigger(struct event_trigger_data *data, void *rec) +{ + if (!data->count) + return; + + if (data->count != -1) + (data->count)--; + + hist_enable_trigger(data, rec); +} + +static struct event_trigger_ops hist_enable_trigger_ops = { + .func = hist_enable_trigger, + .print = event_enable_trigger_print, + .init = event_trigger_init, + .free = event_enable_trigger_free, +}; + +static struct event_trigger_ops hist_enable_count_trigger_ops = { + .func = hist_enable_count_trigger, + .print = event_enable_trigger_print, + .init = event_trigger_init, + .free = event_enable_trigger_free, +}; + +static struct event_trigger_ops hist_disable_trigger_ops = { + .func = hist_enable_trigger, + .print = event_enable_trigger_print, + .init = event_trigger_init, + .free = event_enable_trigger_free, +}; + +static struct event_trigger_ops hist_disable_count_trigger_ops = { + .func = hist_enable_count_trigger, + .print = event_enable_trigger_print, + .init = event_trigger_init, + .free = event_enable_trigger_free, +}; + +static struct event_trigger_ops * +hist_enable_get_trigger_ops(char *cmd, char *param) +{ + struct event_trigger_ops *ops; + bool enable; + + enable = (strcmp(cmd, ENABLE_HIST_STR) == 0); + + if (enable) + ops = param ? &hist_enable_count_trigger_ops : + &hist_enable_trigger_ops; + else + ops = param ? &hist_disable_count_trigger_ops : + &hist_disable_trigger_ops; + + return ops; +} + +static struct event_command trigger_hist_enable_cmd = { + .name = ENABLE_HIST_STR, + .trigger_type = ETT_HIST_ENABLE, + .func = event_enable_trigger_func, + .reg = event_enable_register_trigger, + .unreg = event_enable_unregister_trigger, + .get_trigger_ops = hist_enable_get_trigger_ops, + .set_filter = set_trigger_filter, +}; + +static struct event_command trigger_hist_disable_cmd = { + .name = DISABLE_HIST_STR, + .trigger_type = ETT_HIST_ENABLE, + .func = event_enable_trigger_func, + .reg = event_enable_register_trigger, + .unreg = event_enable_unregister_trigger, + .get_trigger_ops = hist_enable_get_trigger_ops, + .set_filter = set_trigger_filter, +}; + +static __init void unregister_trigger_hist_enable_disable_cmds(void) +{ + unregister_event_command(&trigger_hist_enable_cmd); + unregister_event_command(&trigger_hist_disable_cmd); +} + +__init int register_trigger_hist_enable_disable_cmds(void) +{ + int ret; + + ret = register_event_command(&trigger_hist_enable_cmd); + if (WARN_ON(ret < 0)) + return ret; + ret = register_event_command(&trigger_hist_disable_cmd); + if (WARN_ON(ret < 0)) + unregister_trigger_hist_enable_disable_cmds(); + + return ret; +} diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index d29092afe005..d133f2094566 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -347,7 +347,7 @@ __init int register_event_command(struct event_command *cmd) * Currently we only unregister event commands from __init, so mark * this __init too. */ -static __init int unregister_event_command(struct event_command *cmd) +__init int unregister_event_command(struct event_command *cmd) { struct event_command *p, *n; int ret = -ENODEV; @@ -1062,15 +1062,6 @@ static __init void unregister_trigger_traceon_traceoff_cmds(void) unregister_event_command(&trigger_traceoff_cmd); } -/* Avoid typos */ -#define ENABLE_EVENT_STR "enable_event" -#define DISABLE_EVENT_STR "disable_event" - -struct enable_trigger_data { - struct trace_event_file *file; - bool enable; -}; - static void event_enable_trigger(struct event_trigger_data *data, void *rec) { @@ -1100,14 +1091,16 @@ event_enable_count_trigger(struct event_trigger_data *data, void *rec) event_enable_trigger(data, rec); } -static int -event_enable_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, - struct event_trigger_data *data) +int event_enable_trigger_print(struct seq_file *m, + struct event_trigger_ops *ops, + struct event_trigger_data *data) { struct enable_trigger_data *enable_data = data->private_data; seq_printf(m, "%s:%s:%s", - enable_data->enable ? ENABLE_EVENT_STR : DISABLE_EVENT_STR, + enable_data->hist ? + (enable_data->enable ? ENABLE_HIST_STR : DISABLE_HIST_STR) : + (enable_data->enable ? ENABLE_EVENT_STR : DISABLE_EVENT_STR), enable_data->file->event_call->class->system, trace_event_name(enable_data->file->event_call)); @@ -1124,9 +1117,8 @@ event_enable_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, return 0; } -static void -event_enable_trigger_free(struct event_trigger_ops *ops, - struct event_trigger_data *data) +void event_enable_trigger_free(struct event_trigger_ops *ops, + struct event_trigger_data *data) { struct enable_trigger_data *enable_data = data->private_data; @@ -1171,10 +1163,9 @@ static struct event_trigger_ops event_disable_count_trigger_ops = { .free = event_enable_trigger_free, }; -static int -event_enable_trigger_func(struct event_command *cmd_ops, - struct trace_event_file *file, - char *glob, char *cmd, char *param) +int event_enable_trigger_func(struct event_command *cmd_ops, + struct trace_event_file *file, + char *glob, char *cmd, char *param) { struct trace_event_file *event_enable_file; struct enable_trigger_data *enable_data; @@ -1183,6 +1174,7 @@ event_enable_trigger_func(struct event_command *cmd_ops, struct trace_array *tr = file->tr; const char *system; const char *event; + bool hist = false; char *trigger; char *number; bool enable; @@ -1207,8 +1199,15 @@ event_enable_trigger_func(struct event_command *cmd_ops, if (!event_enable_file) goto out; - enable = strcmp(cmd, ENABLE_EVENT_STR) == 0; +#ifdef CONFIG_HIST_TRIGGERS + hist = ((strcmp(cmd, ENABLE_HIST_STR) == 0) || + (strcmp(cmd, DISABLE_HIST_STR) == 0)); + enable = ((strcmp(cmd, ENABLE_EVENT_STR) == 0) || + (strcmp(cmd, ENABLE_HIST_STR) == 0)); +#else + enable = strcmp(cmd, ENABLE_EVENT_STR) == 0; +#endif trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger); ret = -ENOMEM; @@ -1228,6 +1227,7 @@ event_enable_trigger_func(struct event_command *cmd_ops, INIT_LIST_HEAD(&trigger_data->list); RCU_INIT_POINTER(trigger_data->filter, NULL); + enable_data->hist = hist; enable_data->enable = enable; enable_data->file = event_enable_file; trigger_data->private_data = enable_data; @@ -1305,10 +1305,10 @@ event_enable_trigger_func(struct event_command *cmd_ops, goto out; } -static int event_enable_register_trigger(char *glob, - struct event_trigger_ops *ops, - struct event_trigger_data *data, - struct trace_event_file *file) +int event_enable_register_trigger(char *glob, + struct event_trigger_ops *ops, + struct event_trigger_data *data, + struct trace_event_file *file) { struct enable_trigger_data *enable_data = data->private_data; struct enable_trigger_data *test_enable_data; @@ -1318,6 +1318,8 @@ static int event_enable_register_trigger(char *glob, list_for_each_entry_rcu(test, &file->triggers, list) { test_enable_data = test->private_data; if (test_enable_data && + (test->cmd_ops->trigger_type == + data->cmd_ops->trigger_type) && (test_enable_data->file == enable_data->file)) { ret = -EEXIST; goto out; @@ -1343,10 +1345,10 @@ static int event_enable_register_trigger(char *glob, return ret; } -static void event_enable_unregister_trigger(char *glob, - struct event_trigger_ops *ops, - struct event_trigger_data *test, - struct trace_event_file *file) +void event_enable_unregister_trigger(char *glob, + struct event_trigger_ops *ops, + struct event_trigger_data *test, + struct trace_event_file *file) { struct enable_trigger_data *test_enable_data = test->private_data; struct enable_trigger_data *enable_data; @@ -1356,6 +1358,8 @@ static void event_enable_unregister_trigger(char *glob, list_for_each_entry_rcu(data, &file->triggers, list) { enable_data = data->private_data; if (enable_data && + (data->cmd_ops->trigger_type == + test->cmd_ops->trigger_type) && (enable_data->file == test_enable_data->file)) { unregistered = true; list_del_rcu(&data->list); @@ -1375,8 +1379,12 @@ event_enable_get_trigger_ops(char *cmd, char *param) struct event_trigger_ops *ops; bool enable; +#ifdef CONFIG_HIST_TRIGGERS + enable = ((strcmp(cmd, ENABLE_EVENT_STR) == 0) || + (strcmp(cmd, ENABLE_HIST_STR) == 0)); +#else enable = strcmp(cmd, ENABLE_EVENT_STR) == 0; - +#endif if (enable) ops = param ? &event_enable_count_trigger_ops : &event_enable_trigger_ops; @@ -1447,6 +1455,7 @@ __init int register_trigger_cmds(void) register_trigger_snapshot_cmd(); register_trigger_stacktrace_cmd(); register_trigger_enable_disable_cmds(); + register_trigger_hist_enable_disable_cmds(); register_trigger_hist_cmd(); return 0; -- GitLab From 0fc3813ce1036b57598ee5cdcf891f8a19581654 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:56 -0600 Subject: [PATCH 3545/9938] tracing: Add 'hist' trigger Documentation Add documentation and usage examples for 'hist' triggers. Link: http://lkml.kernel.org/r/2e13f35f47fea6d647f0efefccfc9673ea84b29f.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- Documentation/trace/events.txt | 1155 ++++++++++++++++++++++++++++++++ 1 file changed, 1155 insertions(+) diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt index c010be8c85d7..db223e85bd2f 100644 --- a/Documentation/trace/events.txt +++ b/Documentation/trace/events.txt @@ -512,3 +512,1158 @@ The following commands are supported: Note that there can be only one traceon or traceoff trigger per triggering event. + +- hist + + This command aggregates event hits into a hash table keyed on one or + more trace event format fields (or stacktrace) and a set of running + totals derived from one or more trace event format fields and/or + event counts (hitcount). + + The format of a hist trigger is as follows: + + hist:keys=[:values=] + [:sort=][:size=#entries][:pause][:continue] + [:clear] [if ] + + When a matching event is hit, an entry is added to a hash table + using the key(s) and value(s) named. Keys and values correspond to + fields in the event's format description. Values must correspond to + numeric fields - on an event hit, the value(s) will be added to a + sum kept for that field. The special string 'hitcount' can be used + in place of an explicit value field - this is simply a count of + event hits. If 'values' isn't specified, an implicit 'hitcount' + value will be automatically created and used as the only value. + Keys can be any field, or the special string 'stacktrace', which + will use the event's kernel stacktrace as the key. The keywords + 'keys' or 'key' can be used to specify keys, and the keywords + 'values', 'vals', or 'val' can be used to specify values. Compound + keys consisting of up to two fields can be specified by the 'keys' + keyword. Hashing a compound key produces a unique entry in the + table for each unique combination of component keys, and can be + useful for providing more fine-grained summaries of event data. + Additionally, sort keys consisting of up to two fields can be + specified by the 'sort' keyword. If more than one field is + specified, the result will be a 'sort within a sort': the first key + is taken to be the primary sort key and the second the secondary + key. + + 'hist' triggers add a 'hist' file to each event's subdirectory. + Reading the 'hist' file for the event will dump the hash table in + its entirety to stdout. Each printed hash table entry is a simple + list of the keys and values comprising the entry; keys are printed + first and are delineated by curly braces, and are followed by the + set of value fields for the entry. By default, numeric fields are + displayed as base-10 integers. This can be modified by appending + any of the following modifiers to the field name: + + .hex display a number as a hex value + .sym display an address as a symbol + .sym-offset display an address as a symbol and offset + .syscall display a syscall id as a system call name + .execname display a common_pid as a program name + + Note that in general the semantics of a given field aren't + interpreted when applying a modifier to it, but there are some + restrictions to be aware of in this regard: + + - only the 'hex' modifier can be used for values (because values + are essentially sums, and the other modifiers don't make sense + in that context). + - the 'execname' modifier can only be used on a 'common_pid'. The + reason for this is that the execname is simply the 'comm' value + saved for the 'current' process when an event was triggered, + which is the same as the common_pid value saved by the event + tracing code. Trying to apply that comm value to other pid + values wouldn't be correct, and typically events that care save + pid-specific comm fields in the event itself. + + A typical usage scenario would be the following to enable a hist + trigger, read its current contents, and then turn it off: + + # echo 'hist:keys=skbaddr.hex:vals=len' > \ + /sys/kernel/debug/tracing/events/net/netif_rx/trigger + + # cat /sys/kernel/debug/tracing/events/net/netif_rx/hist + + # echo '!hist:keys=skbaddr.hex:vals=len' > \ + /sys/kernel/debug/tracing/events/net/netif_rx/trigger + + The trigger file itself can be read to show the details of the + currently attached hist trigger. This information is also displayed + at the top of the 'hist' file when read. + + By default, the size of the hash table is 2048 entries. The 'size' + parameter can be used to specify more or fewer than that. The units + are in terms of hashtable entries - if a run uses more entries than + specified, the results will show the number of 'drops', the number + of hits that were ignored. The size should be a power of 2 between + 128 and 131072 (any non- power-of-2 number specified will be rounded + up). + + The 'sort' parameter can be used to specify a value field to sort + on. The default if unspecified is 'hitcount' and the default sort + order is 'ascending'. To sort in the opposite direction, append + .descending' to the sort key. + + The 'pause' parameter can be used to pause an existing hist trigger + or to start a hist trigger but not log any events until told to do + so. 'continue' or 'cont' can be used to start or restart a paused + hist trigger. + + The 'clear' parameter will clear the contents of a running hist + trigger and leave its current paused/active state. + + Note that the 'pause', 'cont', and 'clear' parameters should be + applied using 'append' shell operator ('>>') if applied to an + existing trigger, rather than via the '>' operator, which will cause + the trigger to be removed through truncation. + +- enable_hist/disable_hist + + The enable_hist and disable_hist triggers can be used to have one + event conditionally start and stop another event's already-attached + hist trigger. Any number of enable_hist and disable_hist triggers + can be attached to a given event, allowing that event to kick off + and stop aggregations on a host of other events. + + The format is very similar to the enable/disable_event triggers: + + enable_hist::[:count] + disable_hist::[:count] + + Instead of enabling or disabling the tracing of the target event + into the trace buffer as the enable/disable_event triggers do, the + enable/disable_hist triggers enable or disable the aggregation of + the target event into a hash table. + + A typical usage scenario for the enable_hist/disable_hist triggers + would be to first set up a paused hist trigger on some event, + followed by an enable_hist/disable_hist pair that turns the hist + aggregation on and off when conditions of interest are hit: + + # echo 'hist:keys=skbaddr.hex:vals=len:pause' > \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + + # echo 'enable_hist:net:netif_receive_skb if filename==/usr/bin/wget' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger + + # echo 'disable_hist:net:netif_receive_skb if comm==wget' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger + + The above sets up an initially paused hist trigger which is unpaused + and starts aggregating events when a given program is executed, and + which stops aggregating when the process exits and the hist trigger + is paused again. + + The examples below provide a more concrete illustration of the + concepts and typical usage patterns discussed above. + + +6.2 'hist' trigger examples +--------------------------- + + The first set of examples creates aggregations using the kmalloc + event. The fields that can be used for the hist trigger are listed + in the kmalloc event's format file: + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/format + name: kmalloc + ID: 374 + format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:unsigned long call_site; offset:8; size:8; signed:0; + field:const void * ptr; offset:16; size:8; signed:0; + field:size_t bytes_req; offset:24; size:8; signed:0; + field:size_t bytes_alloc; offset:32; size:8; signed:0; + field:gfp_t gfp_flags; offset:40; size:4; signed:0; + + We'll start by creating a hist trigger that generates a simple table + that lists the total number of bytes requested for each function in + the kernel that made one or more calls to kmalloc: + + # echo 'hist:key=call_site:val=bytes_req' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + This tells the tracing system to create a 'hist' trigger using the + call_site field of the kmalloc event as the key for the table, which + just means that each unique call_site address will have an entry + created for it in the table. The 'val=bytes_req' parameter tells + the hist trigger that for each unique entry (call_site) in the + table, it should keep a running total of the number of bytes + requested by that call_site. + + We'll let it run for awhile and then dump the contents of the 'hist' + file in the kmalloc event's subdirectory (for readability, a number + of entries have been omitted): + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist + # trigger info: hist:keys=call_site:vals=bytes_req:sort=hitcount:size=2048 [active] + + { call_site: 18446744072106379007 } hitcount: 1 bytes_req: 176 + { call_site: 18446744071579557049 } hitcount: 1 bytes_req: 1024 + { call_site: 18446744071580608289 } hitcount: 1 bytes_req: 16384 + { call_site: 18446744071581827654 } hitcount: 1 bytes_req: 24 + { call_site: 18446744071580700980 } hitcount: 1 bytes_req: 8 + { call_site: 18446744071579359876 } hitcount: 1 bytes_req: 152 + { call_site: 18446744071580795365 } hitcount: 3 bytes_req: 144 + { call_site: 18446744071581303129 } hitcount: 3 bytes_req: 144 + { call_site: 18446744071580713234 } hitcount: 4 bytes_req: 2560 + { call_site: 18446744071580933750 } hitcount: 4 bytes_req: 736 + . + . + . + { call_site: 18446744072106047046 } hitcount: 69 bytes_req: 5576 + { call_site: 18446744071582116407 } hitcount: 73 bytes_req: 2336 + { call_site: 18446744072106054684 } hitcount: 136 bytes_req: 140504 + { call_site: 18446744072106224230 } hitcount: 136 bytes_req: 19584 + { call_site: 18446744072106078074 } hitcount: 153 bytes_req: 2448 + { call_site: 18446744072106062406 } hitcount: 153 bytes_req: 36720 + { call_site: 18446744071582507929 } hitcount: 153 bytes_req: 37088 + { call_site: 18446744072102520590 } hitcount: 273 bytes_req: 10920 + { call_site: 18446744071582143559 } hitcount: 358 bytes_req: 716 + { call_site: 18446744072106465852 } hitcount: 417 bytes_req: 56712 + { call_site: 18446744072102523378 } hitcount: 485 bytes_req: 27160 + { call_site: 18446744072099568646 } hitcount: 1676 bytes_req: 33520 + + Totals: + Hits: 4610 + Entries: 45 + Dropped: 0 + + The output displays a line for each entry, beginning with the key + specified in the trigger, followed by the value(s) also specified in + the trigger. At the beginning of the output is a line that displays + the trigger info, which can also be displayed by reading the + 'trigger' file: + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + hist:keys=call_site:vals=bytes_req:sort=hitcount:size=2048 [active] + + At the end of the output are a few lines that display the overall + totals for the run. The 'Hits' field shows the total number of + times the event trigger was hit, the 'Entries' field shows the total + number of used entries in the hash table, and the 'Dropped' field + shows the number of hits that were dropped because the number of + used entries for the run exceeded the maximum number of entries + allowed for the table (normally 0, but if not a hint that you may + want to increase the size of the table using the 'size' parameter). + + Notice in the above output that there's an extra field, 'hitcount', + which wasn't specified in the trigger. Also notice that in the + trigger info output, there's a parameter, 'sort=hitcount', which + wasn't specified in the trigger either. The reason for that is that + every trigger implicitly keeps a count of the total number of hits + attributed to a given entry, called the 'hitcount'. That hitcount + information is explicitly displayed in the output, and in the + absence of a user-specified sort parameter, is used as the default + sort field. + + The value 'hitcount' can be used in place of an explicit value in + the 'values' parameter if you don't really need to have any + particular field summed and are mainly interested in hit + frequencies. + + To turn the hist trigger off, simply call up the trigger in the + command history and re-execute it with a '!' prepended: + + # echo '!hist:key=call_site:val=bytes_req' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + Finally, notice that the call_site as displayed in the output above + isn't really very useful. It's an address, but normally addresses + are displayed in hex. To have a numeric field displayed as a hex + value, simply append '.hex' to the field name in the trigger: + + # echo 'hist:key=call_site.hex:val=bytes_req' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist + # trigger info: hist:keys=call_site.hex:vals=bytes_req:sort=hitcount:size=2048 [active] + + { call_site: ffffffffa026b291 } hitcount: 1 bytes_req: 433 + { call_site: ffffffffa07186ff } hitcount: 1 bytes_req: 176 + { call_site: ffffffff811ae721 } hitcount: 1 bytes_req: 16384 + { call_site: ffffffff811c5134 } hitcount: 1 bytes_req: 8 + { call_site: ffffffffa04a9ebb } hitcount: 1 bytes_req: 511 + { call_site: ffffffff8122e0a6 } hitcount: 1 bytes_req: 12 + { call_site: ffffffff8107da84 } hitcount: 1 bytes_req: 152 + { call_site: ffffffff812d8246 } hitcount: 1 bytes_req: 24 + { call_site: ffffffff811dc1e5 } hitcount: 3 bytes_req: 144 + { call_site: ffffffffa02515e8 } hitcount: 3 bytes_req: 648 + { call_site: ffffffff81258159 } hitcount: 3 bytes_req: 144 + { call_site: ffffffff811c80f4 } hitcount: 4 bytes_req: 544 + . + . + . + { call_site: ffffffffa06c7646 } hitcount: 106 bytes_req: 8024 + { call_site: ffffffffa06cb246 } hitcount: 132 bytes_req: 31680 + { call_site: ffffffffa06cef7a } hitcount: 132 bytes_req: 2112 + { call_site: ffffffff8137e399 } hitcount: 132 bytes_req: 23232 + { call_site: ffffffffa06c941c } hitcount: 185 bytes_req: 171360 + { call_site: ffffffffa06f2a66 } hitcount: 185 bytes_req: 26640 + { call_site: ffffffffa036a70e } hitcount: 265 bytes_req: 10600 + { call_site: ffffffff81325447 } hitcount: 292 bytes_req: 584 + { call_site: ffffffffa072da3c } hitcount: 446 bytes_req: 60656 + { call_site: ffffffffa036b1f2 } hitcount: 526 bytes_req: 29456 + { call_site: ffffffffa0099c06 } hitcount: 1780 bytes_req: 35600 + + Totals: + Hits: 4775 + Entries: 46 + Dropped: 0 + + Even that's only marginally more useful - while hex values do look + more like addresses, what users are typically more interested in + when looking at text addresses are the corresponding symbols + instead. To have an address displayed as symbolic value instead, + simply append '.sym' or '.sym-offset' to the field name in the + trigger: + + # echo 'hist:key=call_site.sym:val=bytes_req' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist + # trigger info: hist:keys=call_site.sym:vals=bytes_req:sort=hitcount:size=2048 [active] + + { call_site: [ffffffff810adcb9] syslog_print_all } hitcount: 1 bytes_req: 1024 + { call_site: [ffffffff8154bc62] usb_control_msg } hitcount: 1 bytes_req: 8 + { call_site: [ffffffffa00bf6fe] hidraw_send_report [hid] } hitcount: 1 bytes_req: 7 + { call_site: [ffffffff8154acbe] usb_alloc_urb } hitcount: 1 bytes_req: 192 + { call_site: [ffffffffa00bf1ca] hidraw_report_event [hid] } hitcount: 1 bytes_req: 7 + { call_site: [ffffffff811e3a25] __seq_open_private } hitcount: 1 bytes_req: 40 + { call_site: [ffffffff8109524a] alloc_fair_sched_group } hitcount: 2 bytes_req: 128 + { call_site: [ffffffff811febd5] fsnotify_alloc_group } hitcount: 2 bytes_req: 528 + { call_site: [ffffffff81440f58] __tty_buffer_request_room } hitcount: 2 bytes_req: 2624 + { call_site: [ffffffff81200ba6] inotify_new_group } hitcount: 2 bytes_req: 96 + { call_site: [ffffffffa05e19af] ieee80211_start_tx_ba_session [mac80211] } hitcount: 2 bytes_req: 464 + { call_site: [ffffffff81672406] tcp_get_metrics } hitcount: 2 bytes_req: 304 + { call_site: [ffffffff81097ec2] alloc_rt_sched_group } hitcount: 2 bytes_req: 128 + { call_site: [ffffffff81089b05] sched_create_group } hitcount: 2 bytes_req: 1424 + . + . + . + { call_site: [ffffffffa04a580c] intel_crtc_page_flip [i915] } hitcount: 1185 bytes_req: 123240 + { call_site: [ffffffffa0287592] drm_mode_page_flip_ioctl [drm] } hitcount: 1185 bytes_req: 104280 + { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state [i915] } hitcount: 1402 bytes_req: 190672 + { call_site: [ffffffff812891ca] ext4_find_extent } hitcount: 1518 bytes_req: 146208 + { call_site: [ffffffffa029070e] drm_vma_node_allow [drm] } hitcount: 1746 bytes_req: 69840 + { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23 [i915] } hitcount: 2021 bytes_req: 792312 + { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc [drm] } hitcount: 2592 bytes_req: 145152 + { call_site: [ffffffffa0489a66] intel_ring_begin [i915] } hitcount: 2629 bytes_req: 378576 + { call_site: [ffffffffa046041c] i915_gem_execbuffer2 [i915] } hitcount: 2629 bytes_req: 3783248 + { call_site: [ffffffff81325607] apparmor_file_alloc_security } hitcount: 5192 bytes_req: 10384 + { call_site: [ffffffffa00b7c06] hid_report_raw_event [hid] } hitcount: 5529 bytes_req: 110584 + { call_site: [ffffffff8131ebf7] aa_alloc_task_context } hitcount: 21943 bytes_req: 702176 + { call_site: [ffffffff8125847d] ext4_htree_store_dirent } hitcount: 55759 bytes_req: 5074265 + + Totals: + Hits: 109928 + Entries: 71 + Dropped: 0 + + Because the default sort key above is 'hitcount', the above shows a + the list of call_sites by increasing hitcount, so that at the bottom + we see the functions that made the most kmalloc calls during the + run. If instead we we wanted to see the top kmalloc callers in + terms of the number of bytes requested rather than the number of + calls, and we wanted the top caller to appear at the top, we can use + the 'sort' parameter, along with the 'descending' modifier: + + # echo 'hist:key=call_site.sym:val=bytes_req:sort=bytes_req.descending' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist + # trigger info: hist:keys=call_site.sym:vals=bytes_req:sort=bytes_req.descending:size=2048 [active] + + { call_site: [ffffffffa046041c] i915_gem_execbuffer2 [i915] } hitcount: 2186 bytes_req: 3397464 + { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23 [i915] } hitcount: 1790 bytes_req: 712176 + { call_site: [ffffffff8125847d] ext4_htree_store_dirent } hitcount: 8132 bytes_req: 513135 + { call_site: [ffffffff811e2a1b] seq_buf_alloc } hitcount: 106 bytes_req: 440128 + { call_site: [ffffffffa0489a66] intel_ring_begin [i915] } hitcount: 2186 bytes_req: 314784 + { call_site: [ffffffff812891ca] ext4_find_extent } hitcount: 2174 bytes_req: 208992 + { call_site: [ffffffff811ae8e1] __kmalloc } hitcount: 8 bytes_req: 131072 + { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state [i915] } hitcount: 859 bytes_req: 116824 + { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc [drm] } hitcount: 1834 bytes_req: 102704 + { call_site: [ffffffffa04a580c] intel_crtc_page_flip [i915] } hitcount: 972 bytes_req: 101088 + { call_site: [ffffffffa0287592] drm_mode_page_flip_ioctl [drm] } hitcount: 972 bytes_req: 85536 + { call_site: [ffffffffa00b7c06] hid_report_raw_event [hid] } hitcount: 3333 bytes_req: 66664 + { call_site: [ffffffff8137e559] sg_kmalloc } hitcount: 209 bytes_req: 61632 + . + . + . + { call_site: [ffffffff81095225] alloc_fair_sched_group } hitcount: 2 bytes_req: 128 + { call_site: [ffffffff81097ec2] alloc_rt_sched_group } hitcount: 2 bytes_req: 128 + { call_site: [ffffffff812d8406] copy_semundo } hitcount: 2 bytes_req: 48 + { call_site: [ffffffff81200ba6] inotify_new_group } hitcount: 1 bytes_req: 48 + { call_site: [ffffffffa027121a] drm_getmagic [drm] } hitcount: 1 bytes_req: 48 + { call_site: [ffffffff811e3a25] __seq_open_private } hitcount: 1 bytes_req: 40 + { call_site: [ffffffff811c52f4] bprm_change_interp } hitcount: 2 bytes_req: 16 + { call_site: [ffffffff8154bc62] usb_control_msg } hitcount: 1 bytes_req: 8 + { call_site: [ffffffffa00bf1ca] hidraw_report_event [hid] } hitcount: 1 bytes_req: 7 + { call_site: [ffffffffa00bf6fe] hidraw_send_report [hid] } hitcount: 1 bytes_req: 7 + + Totals: + Hits: 32133 + Entries: 81 + Dropped: 0 + + To display the offset and size information in addition to the symbol + name, just use 'sym-offset' instead: + + # echo 'hist:key=call_site.sym-offset:val=bytes_req:sort=bytes_req.descending' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist + # trigger info: hist:keys=call_site.sym-offset:vals=bytes_req:sort=bytes_req.descending:size=2048 [active] + + { call_site: [ffffffffa046041c] i915_gem_execbuffer2+0x6c/0x2c0 [i915] } hitcount: 4569 bytes_req: 3163720 + { call_site: [ffffffffa0489a66] intel_ring_begin+0xc6/0x1f0 [i915] } hitcount: 4569 bytes_req: 657936 + { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23+0x694/0x1020 [i915] } hitcount: 1519 bytes_req: 472936 + { call_site: [ffffffffa045e646] i915_gem_do_execbuffer.isra.23+0x516/0x1020 [i915] } hitcount: 3050 bytes_req: 211832 + { call_site: [ffffffff811e2a1b] seq_buf_alloc+0x1b/0x50 } hitcount: 34 bytes_req: 148384 + { call_site: [ffffffffa04a580c] intel_crtc_page_flip+0xbc/0x870 [i915] } hitcount: 1385 bytes_req: 144040 + { call_site: [ffffffff811ae8e1] __kmalloc+0x191/0x1b0 } hitcount: 8 bytes_req: 131072 + { call_site: [ffffffffa0287592] drm_mode_page_flip_ioctl+0x282/0x360 [drm] } hitcount: 1385 bytes_req: 121880 + { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc+0x32/0x100 [drm] } hitcount: 1848 bytes_req: 103488 + { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state+0x2c/0xa0 [i915] } hitcount: 461 bytes_req: 62696 + { call_site: [ffffffffa029070e] drm_vma_node_allow+0x2e/0xd0 [drm] } hitcount: 1541 bytes_req: 61640 + { call_site: [ffffffff815f8d7b] sk_prot_alloc+0xcb/0x1b0 } hitcount: 57 bytes_req: 57456 + . + . + . + { call_site: [ffffffff8109524a] alloc_fair_sched_group+0x5a/0x1a0 } hitcount: 2 bytes_req: 128 + { call_site: [ffffffffa027b921] drm_vm_open_locked+0x31/0xa0 [drm] } hitcount: 3 bytes_req: 96 + { call_site: [ffffffff8122e266] proc_self_follow_link+0x76/0xb0 } hitcount: 8 bytes_req: 96 + { call_site: [ffffffff81213e80] load_elf_binary+0x240/0x1650 } hitcount: 3 bytes_req: 84 + { call_site: [ffffffff8154bc62] usb_control_msg+0x42/0x110 } hitcount: 1 bytes_req: 8 + { call_site: [ffffffffa00bf6fe] hidraw_send_report+0x7e/0x1a0 [hid] } hitcount: 1 bytes_req: 7 + { call_site: [ffffffffa00bf1ca] hidraw_report_event+0x8a/0x120 [hid] } hitcount: 1 bytes_req: 7 + + Totals: + Hits: 26098 + Entries: 64 + Dropped: 0 + + We can also add multiple fields to the 'values' parameter. For + example, we might want to see the total number of bytes allocated + alongside bytes requested, and display the result sorted by bytes + allocated in a descending order: + + # echo 'hist:keys=call_site.sym:values=bytes_req,bytes_alloc:sort=bytes_alloc.descending' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist + # trigger info: hist:keys=call_site.sym:vals=bytes_req,bytes_alloc:sort=bytes_alloc.descending:size=2048 [active] + + { call_site: [ffffffffa046041c] i915_gem_execbuffer2 [i915] } hitcount: 7403 bytes_req: 4084360 bytes_alloc: 5958016 + { call_site: [ffffffff811e2a1b] seq_buf_alloc } hitcount: 541 bytes_req: 2213968 bytes_alloc: 2228224 + { call_site: [ffffffffa0489a66] intel_ring_begin [i915] } hitcount: 7404 bytes_req: 1066176 bytes_alloc: 1421568 + { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23 [i915] } hitcount: 1565 bytes_req: 557368 bytes_alloc: 1037760 + { call_site: [ffffffff8125847d] ext4_htree_store_dirent } hitcount: 9557 bytes_req: 595778 bytes_alloc: 695744 + { call_site: [ffffffffa045e646] i915_gem_do_execbuffer.isra.23 [i915] } hitcount: 5839 bytes_req: 430680 bytes_alloc: 470400 + { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state [i915] } hitcount: 2388 bytes_req: 324768 bytes_alloc: 458496 + { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc [drm] } hitcount: 3911 bytes_req: 219016 bytes_alloc: 250304 + { call_site: [ffffffff815f8d7b] sk_prot_alloc } hitcount: 235 bytes_req: 236880 bytes_alloc: 240640 + { call_site: [ffffffff8137e559] sg_kmalloc } hitcount: 557 bytes_req: 169024 bytes_alloc: 221760 + { call_site: [ffffffffa00b7c06] hid_report_raw_event [hid] } hitcount: 9378 bytes_req: 187548 bytes_alloc: 206312 + { call_site: [ffffffffa04a580c] intel_crtc_page_flip [i915] } hitcount: 1519 bytes_req: 157976 bytes_alloc: 194432 + . + . + . + { call_site: [ffffffff8109bd3b] sched_autogroup_create_attach } hitcount: 2 bytes_req: 144 bytes_alloc: 192 + { call_site: [ffffffff81097ee8] alloc_rt_sched_group } hitcount: 2 bytes_req: 128 bytes_alloc: 128 + { call_site: [ffffffff8109524a] alloc_fair_sched_group } hitcount: 2 bytes_req: 128 bytes_alloc: 128 + { call_site: [ffffffff81095225] alloc_fair_sched_group } hitcount: 2 bytes_req: 128 bytes_alloc: 128 + { call_site: [ffffffff81097ec2] alloc_rt_sched_group } hitcount: 2 bytes_req: 128 bytes_alloc: 128 + { call_site: [ffffffff81213e80] load_elf_binary } hitcount: 3 bytes_req: 84 bytes_alloc: 96 + { call_site: [ffffffff81079a2e] kthread_create_on_node } hitcount: 1 bytes_req: 56 bytes_alloc: 64 + { call_site: [ffffffffa00bf6fe] hidraw_send_report [hid] } hitcount: 1 bytes_req: 7 bytes_alloc: 8 + { call_site: [ffffffff8154bc62] usb_control_msg } hitcount: 1 bytes_req: 8 bytes_alloc: 8 + { call_site: [ffffffffa00bf1ca] hidraw_report_event [hid] } hitcount: 1 bytes_req: 7 bytes_alloc: 8 + + Totals: + Hits: 66598 + Entries: 65 + Dropped: 0 + + Finally, to finish off our kmalloc example, instead of simply having + the hist trigger display symbolic call_sites, we can have the hist + trigger additionally display the complete set of kernel stack traces + that led to each call_site. To do that, we simply use the special + value 'stacktrace' for the key parameter: + + # echo 'hist:keys=stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \ + /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger + + The above trigger will use the kernel stack trace in effect when an + event is triggered as the key for the hash table. This allows the + enumeration of every kernel callpath that led up to a particular + event, along with a running total of any of the event fields for + that event. Here we tally bytes requested and bytes allocated for + every callpath in the system that led up to a kmalloc (in this case + every callpath to a kmalloc for a kernel compile): + + # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist + # trigger info: hist:keys=stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active] + + { stacktrace: + __kmalloc_track_caller+0x10b/0x1a0 + kmemdup+0x20/0x50 + hidraw_report_event+0x8a/0x120 [hid] + hid_report_raw_event+0x3ea/0x440 [hid] + hid_input_report+0x112/0x190 [hid] + hid_irq_in+0xc2/0x260 [usbhid] + __usb_hcd_giveback_urb+0x72/0x120 + usb_giveback_urb_bh+0x9e/0xe0 + tasklet_hi_action+0xf8/0x100 + __do_softirq+0x114/0x2c0 + irq_exit+0xa5/0xb0 + do_IRQ+0x5a/0xf0 + ret_from_intr+0x0/0x30 + cpuidle_enter+0x17/0x20 + cpu_startup_entry+0x315/0x3e0 + rest_init+0x7c/0x80 + } hitcount: 3 bytes_req: 21 bytes_alloc: 24 + { stacktrace: + __kmalloc_track_caller+0x10b/0x1a0 + kmemdup+0x20/0x50 + hidraw_report_event+0x8a/0x120 [hid] + hid_report_raw_event+0x3ea/0x440 [hid] + hid_input_report+0x112/0x190 [hid] + hid_irq_in+0xc2/0x260 [usbhid] + __usb_hcd_giveback_urb+0x72/0x120 + usb_giveback_urb_bh+0x9e/0xe0 + tasklet_hi_action+0xf8/0x100 + __do_softirq+0x114/0x2c0 + irq_exit+0xa5/0xb0 + do_IRQ+0x5a/0xf0 + ret_from_intr+0x0/0x30 + } hitcount: 3 bytes_req: 21 bytes_alloc: 24 + { stacktrace: + kmem_cache_alloc_trace+0xeb/0x150 + aa_alloc_task_context+0x27/0x40 + apparmor_cred_prepare+0x1f/0x50 + security_prepare_creds+0x16/0x20 + prepare_creds+0xdf/0x1a0 + SyS_capset+0xb5/0x200 + system_call_fastpath+0x12/0x6a + } hitcount: 1 bytes_req: 32 bytes_alloc: 32 + . + . + . + { stacktrace: + __kmalloc+0x11b/0x1b0 + i915_gem_execbuffer2+0x6c/0x2c0 [i915] + drm_ioctl+0x349/0x670 [drm] + do_vfs_ioctl+0x2f0/0x4f0 + SyS_ioctl+0x81/0xa0 + system_call_fastpath+0x12/0x6a + } hitcount: 17726 bytes_req: 13944120 bytes_alloc: 19593808 + { stacktrace: + __kmalloc+0x11b/0x1b0 + load_elf_phdrs+0x76/0xa0 + load_elf_binary+0x102/0x1650 + search_binary_handler+0x97/0x1d0 + do_execveat_common.isra.34+0x551/0x6e0 + SyS_execve+0x3a/0x50 + return_from_execve+0x0/0x23 + } hitcount: 33348 bytes_req: 17152128 bytes_alloc: 20226048 + { stacktrace: + kmem_cache_alloc_trace+0xeb/0x150 + apparmor_file_alloc_security+0x27/0x40 + security_file_alloc+0x16/0x20 + get_empty_filp+0x93/0x1c0 + path_openat+0x31/0x5f0 + do_filp_open+0x3a/0x90 + do_sys_open+0x128/0x220 + SyS_open+0x1e/0x20 + system_call_fastpath+0x12/0x6a + } hitcount: 4766422 bytes_req: 9532844 bytes_alloc: 38131376 + { stacktrace: + __kmalloc+0x11b/0x1b0 + seq_buf_alloc+0x1b/0x50 + seq_read+0x2cc/0x370 + proc_reg_read+0x3d/0x80 + __vfs_read+0x28/0xe0 + vfs_read+0x86/0x140 + SyS_read+0x46/0xb0 + system_call_fastpath+0x12/0x6a + } hitcount: 19133 bytes_req: 78368768 bytes_alloc: 78368768 + + Totals: + Hits: 6085872 + Entries: 253 + Dropped: 0 + + If you key a hist trigger on common_pid, in order for example to + gather and display sorted totals for each process, you can use the + special .execname modifier to display the executable names for the + processes in the table rather than raw pids. The example below + keeps a per-process sum of total bytes read: + + # echo 'hist:key=common_pid.execname:val=count:sort=count.descending' > \ + /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger + + # cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/hist + # trigger info: hist:keys=common_pid.execname:vals=count:sort=count.descending:size=2048 [active] + + { common_pid: gnome-terminal [ 3196] } hitcount: 280 count: 1093512 + { common_pid: Xorg [ 1309] } hitcount: 525 count: 256640 + { common_pid: compiz [ 2889] } hitcount: 59 count: 254400 + { common_pid: bash [ 8710] } hitcount: 3 count: 66369 + { common_pid: dbus-daemon-lau [ 8703] } hitcount: 49 count: 47739 + { common_pid: irqbalance [ 1252] } hitcount: 27 count: 27648 + { common_pid: 01ifupdown [ 8705] } hitcount: 3 count: 17216 + { common_pid: dbus-daemon [ 772] } hitcount: 10 count: 12396 + { common_pid: Socket Thread [ 8342] } hitcount: 11 count: 11264 + { common_pid: nm-dhcp-client. [ 8701] } hitcount: 6 count: 7424 + { common_pid: gmain [ 1315] } hitcount: 18 count: 6336 + . + . + . + { common_pid: postgres [ 1892] } hitcount: 2 count: 32 + { common_pid: postgres [ 1891] } hitcount: 2 count: 32 + { common_pid: gmain [ 8704] } hitcount: 2 count: 32 + { common_pid: upstart-dbus-br [ 2740] } hitcount: 21 count: 21 + { common_pid: nm-dispatcher.a [ 8696] } hitcount: 1 count: 16 + { common_pid: indicator-datet [ 2904] } hitcount: 1 count: 16 + { common_pid: gdbus [ 2998] } hitcount: 1 count: 16 + { common_pid: rtkit-daemon [ 2052] } hitcount: 1 count: 8 + { common_pid: init [ 1] } hitcount: 2 count: 2 + + Totals: + Hits: 2116 + Entries: 51 + Dropped: 0 + + Similarly, if you key a hist trigger on syscall id, for example to + gather and display a list of systemwide syscall hits, you can use + the special .syscall modifier to display the syscall names rather + than raw ids. The example below keeps a running total of syscall + counts for the system during the run: + + # echo 'hist:key=id.syscall:val=hitcount' > \ + /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger + + # cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/hist + # trigger info: hist:keys=id.syscall:vals=hitcount:sort=hitcount:size=2048 [active] + + { id: sys_fsync [ 74] } hitcount: 1 + { id: sys_newuname [ 63] } hitcount: 1 + { id: sys_prctl [157] } hitcount: 1 + { id: sys_statfs [137] } hitcount: 1 + { id: sys_symlink [ 88] } hitcount: 1 + { id: sys_sendmmsg [307] } hitcount: 1 + { id: sys_semctl [ 66] } hitcount: 1 + { id: sys_readlink [ 89] } hitcount: 3 + { id: sys_bind [ 49] } hitcount: 3 + { id: sys_getsockname [ 51] } hitcount: 3 + { id: sys_unlink [ 87] } hitcount: 3 + { id: sys_rename [ 82] } hitcount: 4 + { id: unknown_syscall [ 58] } hitcount: 4 + { id: sys_connect [ 42] } hitcount: 4 + { id: sys_getpid [ 39] } hitcount: 4 + . + . + . + { id: sys_rt_sigprocmask [ 14] } hitcount: 952 + { id: sys_futex [202] } hitcount: 1534 + { id: sys_write [ 1] } hitcount: 2689 + { id: sys_setitimer [ 38] } hitcount: 2797 + { id: sys_read [ 0] } hitcount: 3202 + { id: sys_select [ 23] } hitcount: 3773 + { id: sys_writev [ 20] } hitcount: 4531 + { id: sys_poll [ 7] } hitcount: 8314 + { id: sys_recvmsg [ 47] } hitcount: 13738 + { id: sys_ioctl [ 16] } hitcount: 21843 + + Totals: + Hits: 67612 + Entries: 72 + Dropped: 0 + + The syscall counts above provide a rough overall picture of system + call activity on the system; we can see for example that the most + popular system call on this system was the 'sys_ioctl' system call. + + We can use 'compound' keys to refine that number and provide some + further insight as to which processes exactly contribute to the + overall ioctl count. + + The command below keeps a hitcount for every unique combination of + system call id and pid - the end result is essentially a table + that keeps a per-pid sum of system call hits. The results are + sorted using the system call id as the primary key, and the + hitcount sum as the secondary key: + + # echo 'hist:key=id.syscall,common_pid.execname:val=hitcount:sort=id,hitcount' > \ + /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger + + # cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/hist + # trigger info: hist:keys=id.syscall,common_pid.execname:vals=hitcount:sort=id.syscall,hitcount:size=2048 [active] + + { id: sys_read [ 0], common_pid: rtkit-daemon [ 1877] } hitcount: 1 + { id: sys_read [ 0], common_pid: gdbus [ 2976] } hitcount: 1 + { id: sys_read [ 0], common_pid: console-kit-dae [ 3400] } hitcount: 1 + { id: sys_read [ 0], common_pid: postgres [ 1865] } hitcount: 1 + { id: sys_read [ 0], common_pid: deja-dup-monito [ 3543] } hitcount: 2 + { id: sys_read [ 0], common_pid: NetworkManager [ 890] } hitcount: 2 + { id: sys_read [ 0], common_pid: evolution-calen [ 3048] } hitcount: 2 + { id: sys_read [ 0], common_pid: postgres [ 1864] } hitcount: 2 + { id: sys_read [ 0], common_pid: nm-applet [ 3022] } hitcount: 2 + { id: sys_read [ 0], common_pid: whoopsie [ 1212] } hitcount: 2 + . + . + . + { id: sys_ioctl [ 16], common_pid: bash [ 8479] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: bash [ 3472] } hitcount: 12 + { id: sys_ioctl [ 16], common_pid: gnome-terminal [ 3199] } hitcount: 16 + { id: sys_ioctl [ 16], common_pid: Xorg [ 1267] } hitcount: 1808 + { id: sys_ioctl [ 16], common_pid: compiz [ 2994] } hitcount: 5580 + . + . + . + { id: sys_waitid [247], common_pid: upstart-dbus-br [ 2690] } hitcount: 3 + { id: sys_waitid [247], common_pid: upstart-dbus-br [ 2688] } hitcount: 16 + { id: sys_inotify_add_watch [254], common_pid: gmain [ 975] } hitcount: 2 + { id: sys_inotify_add_watch [254], common_pid: gmain [ 3204] } hitcount: 4 + { id: sys_inotify_add_watch [254], common_pid: gmain [ 2888] } hitcount: 4 + { id: sys_inotify_add_watch [254], common_pid: gmain [ 3003] } hitcount: 4 + { id: sys_inotify_add_watch [254], common_pid: gmain [ 2873] } hitcount: 4 + { id: sys_inotify_add_watch [254], common_pid: gmain [ 3196] } hitcount: 6 + { id: sys_openat [257], common_pid: java [ 2623] } hitcount: 2 + { id: sys_eventfd2 [290], common_pid: ibus-ui-gtk3 [ 2760] } hitcount: 4 + { id: sys_eventfd2 [290], common_pid: compiz [ 2994] } hitcount: 6 + + Totals: + Hits: 31536 + Entries: 323 + Dropped: 0 + + The above list does give us a breakdown of the ioctl syscall by + pid, but it also gives us quite a bit more than that, which we + don't really care about at the moment. Since we know the syscall + id for sys_ioctl (16, displayed next to the sys_ioctl name), we + can use that to filter out all the other syscalls: + + # echo 'hist:key=id.syscall,common_pid.execname:val=hitcount:sort=id,hitcount if id == 16' > \ + /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger + + # cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/hist + # trigger info: hist:keys=id.syscall,common_pid.execname:vals=hitcount:sort=id.syscall,hitcount:size=2048 if id == 16 [active] + + { id: sys_ioctl [ 16], common_pid: gmain [ 2769] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: evolution-addre [ 8571] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: gmain [ 3003] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: gmain [ 2781] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: gmain [ 2829] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: bash [ 8726] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: bash [ 8508] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: gmain [ 2970] } hitcount: 1 + { id: sys_ioctl [ 16], common_pid: gmain [ 2768] } hitcount: 1 + . + . + . + { id: sys_ioctl [ 16], common_pid: pool [ 8559] } hitcount: 45 + { id: sys_ioctl [ 16], common_pid: pool [ 8555] } hitcount: 48 + { id: sys_ioctl [ 16], common_pid: pool [ 8551] } hitcount: 48 + { id: sys_ioctl [ 16], common_pid: avahi-daemon [ 896] } hitcount: 66 + { id: sys_ioctl [ 16], common_pid: Xorg [ 1267] } hitcount: 26674 + { id: sys_ioctl [ 16], common_pid: compiz [ 2994] } hitcount: 73443 + + Totals: + Hits: 101162 + Entries: 103 + Dropped: 0 + + The above output shows that 'compiz' and 'Xorg' are far and away + the heaviest ioctl callers (which might lead to questions about + whether they really need to be making all those calls and to + possible avenues for further investigation.) + + The compound key examples used a key and a sum value (hitcount) to + sort the output, but we can just as easily use two keys instead. + Here's an example where we use a compound key composed of the the + common_pid and size event fields. Sorting with pid as the primary + key and 'size' as the secondary key allows us to display an + ordered summary of the recvfrom sizes, with counts, received by + each process: + + # echo 'hist:key=common_pid.execname,size:val=hitcount:sort=common_pid,size' > \ + /sys/kernel/debug/tracing/events/syscalls/sys_enter_recvfrom/trigger + + # cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_recvfrom/hist + # trigger info: hist:keys=common_pid.execname,size:vals=hitcount:sort=common_pid.execname,size:size=2048 [active] + + { common_pid: smbd [ 784], size: 4 } hitcount: 1 + { common_pid: dnsmasq [ 1412], size: 4096 } hitcount: 672 + { common_pid: postgres [ 1796], size: 1000 } hitcount: 6 + { common_pid: postgres [ 1867], size: 1000 } hitcount: 10 + { common_pid: bamfdaemon [ 2787], size: 28 } hitcount: 2 + { common_pid: bamfdaemon [ 2787], size: 14360 } hitcount: 1 + { common_pid: compiz [ 2994], size: 8 } hitcount: 1 + { common_pid: compiz [ 2994], size: 20 } hitcount: 11 + { common_pid: gnome-terminal [ 3199], size: 4 } hitcount: 2 + { common_pid: firefox [ 8817], size: 4 } hitcount: 1 + { common_pid: firefox [ 8817], size: 8 } hitcount: 5 + { common_pid: firefox [ 8817], size: 588 } hitcount: 2 + { common_pid: firefox [ 8817], size: 628 } hitcount: 1 + { common_pid: firefox [ 8817], size: 6944 } hitcount: 1 + { common_pid: firefox [ 8817], size: 408880 } hitcount: 2 + { common_pid: firefox [ 8822], size: 8 } hitcount: 2 + { common_pid: firefox [ 8822], size: 160 } hitcount: 2 + { common_pid: firefox [ 8822], size: 320 } hitcount: 2 + { common_pid: firefox [ 8822], size: 352 } hitcount: 1 + . + . + . + { common_pid: pool [ 8923], size: 1960 } hitcount: 10 + { common_pid: pool [ 8923], size: 2048 } hitcount: 10 + { common_pid: pool [ 8924], size: 1960 } hitcount: 10 + { common_pid: pool [ 8924], size: 2048 } hitcount: 10 + { common_pid: pool [ 8928], size: 1964 } hitcount: 4 + { common_pid: pool [ 8928], size: 1965 } hitcount: 2 + { common_pid: pool [ 8928], size: 2048 } hitcount: 6 + { common_pid: pool [ 8929], size: 1982 } hitcount: 1 + { common_pid: pool [ 8929], size: 2048 } hitcount: 1 + + Totals: + Hits: 2016 + Entries: 224 + Dropped: 0 + + The above example also illustrates the fact that although a compound + key is treated as a single entity for hashing purposes, the sub-keys + it's composed of can be accessed independently. + + The next example uses a string field as the hash key and + demonstrates how you can manually pause and continue a hist trigger. + In this example, we'll aggregate fork counts and don't expect a + large number of entries in the hash table, so we'll drop it to a + much smaller number, say 256: + + # echo 'hist:key=child_comm:val=hitcount:size=256' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger + + # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist + # trigger info: hist:keys=child_comm:vals=hitcount:sort=hitcount:size=256 [active] + + { child_comm: dconf worker } hitcount: 1 + { child_comm: ibus-daemon } hitcount: 1 + { child_comm: whoopsie } hitcount: 1 + { child_comm: smbd } hitcount: 1 + { child_comm: gdbus } hitcount: 1 + { child_comm: kthreadd } hitcount: 1 + { child_comm: dconf worker } hitcount: 1 + { child_comm: evolution-alarm } hitcount: 2 + { child_comm: Socket Thread } hitcount: 2 + { child_comm: postgres } hitcount: 2 + { child_comm: bash } hitcount: 3 + { child_comm: compiz } hitcount: 3 + { child_comm: evolution-sourc } hitcount: 4 + { child_comm: dhclient } hitcount: 4 + { child_comm: pool } hitcount: 5 + { child_comm: nm-dispatcher.a } hitcount: 8 + { child_comm: firefox } hitcount: 8 + { child_comm: dbus-daemon } hitcount: 8 + { child_comm: glib-pacrunner } hitcount: 10 + { child_comm: evolution } hitcount: 23 + + Totals: + Hits: 89 + Entries: 20 + Dropped: 0 + + If we want to pause the hist trigger, we can simply append :pause to + the command that started the trigger. Notice that the trigger info + displays as [paused]: + + # echo 'hist:key=child_comm:val=hitcount:size=256:pause' >> \ + /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger + + # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist + # trigger info: hist:keys=child_comm:vals=hitcount:sort=hitcount:size=256 [paused] + + { child_comm: dconf worker } hitcount: 1 + { child_comm: kthreadd } hitcount: 1 + { child_comm: dconf worker } hitcount: 1 + { child_comm: gdbus } hitcount: 1 + { child_comm: ibus-daemon } hitcount: 1 + { child_comm: Socket Thread } hitcount: 2 + { child_comm: evolution-alarm } hitcount: 2 + { child_comm: smbd } hitcount: 2 + { child_comm: bash } hitcount: 3 + { child_comm: whoopsie } hitcount: 3 + { child_comm: compiz } hitcount: 3 + { child_comm: evolution-sourc } hitcount: 4 + { child_comm: pool } hitcount: 5 + { child_comm: postgres } hitcount: 6 + { child_comm: firefox } hitcount: 8 + { child_comm: dhclient } hitcount: 10 + { child_comm: emacs } hitcount: 12 + { child_comm: dbus-daemon } hitcount: 20 + { child_comm: nm-dispatcher.a } hitcount: 20 + { child_comm: evolution } hitcount: 35 + { child_comm: glib-pacrunner } hitcount: 59 + + Totals: + Hits: 199 + Entries: 21 + Dropped: 0 + + To manually continue having the trigger aggregate events, append + :cont instead. Notice that the trigger info displays as [active] + again, and the data has changed: + + # echo 'hist:key=child_comm:val=hitcount:size=256:cont' >> \ + /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger + + # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist + # trigger info: hist:keys=child_comm:vals=hitcount:sort=hitcount:size=256 [active] + + { child_comm: dconf worker } hitcount: 1 + { child_comm: dconf worker } hitcount: 1 + { child_comm: kthreadd } hitcount: 1 + { child_comm: gdbus } hitcount: 1 + { child_comm: ibus-daemon } hitcount: 1 + { child_comm: Socket Thread } hitcount: 2 + { child_comm: evolution-alarm } hitcount: 2 + { child_comm: smbd } hitcount: 2 + { child_comm: whoopsie } hitcount: 3 + { child_comm: compiz } hitcount: 3 + { child_comm: evolution-sourc } hitcount: 4 + { child_comm: bash } hitcount: 5 + { child_comm: pool } hitcount: 5 + { child_comm: postgres } hitcount: 6 + { child_comm: firefox } hitcount: 8 + { child_comm: dhclient } hitcount: 11 + { child_comm: emacs } hitcount: 12 + { child_comm: dbus-daemon } hitcount: 22 + { child_comm: nm-dispatcher.a } hitcount: 22 + { child_comm: evolution } hitcount: 35 + { child_comm: glib-pacrunner } hitcount: 59 + + Totals: + Hits: 206 + Entries: 21 + Dropped: 0 + + The previous example showed how to start and stop a hist trigger by + appending 'pause' and 'continue' to the hist trigger command. A + hist trigger can also be started in a paused state by initially + starting the trigger with ':pause' appended. This allows you to + start the trigger only when you're ready to start collecting data + and not before. For example, you could start the trigger in a + paused state, then unpause it and do something you want to measure, + then pause the trigger again when done. + + Of course, doing this manually can be difficult and error-prone, but + it is possible to automatically start and stop a hist trigger based + on some condition, via the enable_hist and disable_hist triggers. + + For example, suppose we wanted to take a look at the relative + weights in terms of skb length for each callpath that leads to a + netif_receieve_skb event when downloading a decent-sized file using + wget. + + First we set up an initially paused stacktrace trigger on the + netif_receive_skb event: + + # echo 'hist:key=stacktrace:vals=len:pause' > \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + + Next, we set up an 'enable_hist' trigger on the sched_process_exec + event, with an 'if filename==/usr/bin/wget' filter. The effect of + this new trigger is that it will 'unpause' the hist trigger we just + set up on netif_receive_skb if and only if it sees a + sched_process_exec event with a filename of '/usr/bin/wget'. When + that happens, all netif_receive_skb events are aggregated into a + hash table keyed on stacktrace: + + # echo 'enable_hist:net:netif_receive_skb if filename==/usr/bin/wget' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger + + The aggregation continues until the netif_receive_skb is paused + again, which is what the following disable_hist event does by + creating a similar setup on the sched_process_exit event, using the + filter 'comm==wget': + + # echo 'disable_hist:net:netif_receive_skb if comm==wget' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger + + Whenever a process exits and the comm field of the disable_hist + trigger filter matches 'comm==wget', the netif_receive_skb hist + trigger is disabled. + + The overall effect is that netif_receive_skb events are aggregated + into the hash table for only the duration of the wget. Executing a + wget command and then listing the 'hist' file will display the + output generated by the wget command: + + $ wget https://www.kernel.org/pub/linux/kernel/v3.x/patch-3.19.xz + + # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist + # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused] + + { stacktrace: + __netif_receive_skb_core+0x46d/0x990 + __netif_receive_skb+0x18/0x60 + netif_receive_skb_internal+0x23/0x90 + napi_gro_receive+0xc8/0x100 + ieee80211_deliver_skb+0xd6/0x270 [mac80211] + ieee80211_rx_handlers+0xccf/0x22f0 [mac80211] + ieee80211_prepare_and_rx_handle+0x4e7/0xc40 [mac80211] + ieee80211_rx+0x31d/0x900 [mac80211] + iwlagn_rx_reply_rx+0x3db/0x6f0 [iwldvm] + iwl_rx_dispatch+0x8e/0xf0 [iwldvm] + iwl_pcie_irq_handler+0xe3c/0x12f0 [iwlwifi] + irq_thread_fn+0x20/0x50 + irq_thread+0x11f/0x150 + kthread+0xd2/0xf0 + ret_from_fork+0x42/0x70 + } hitcount: 85 len: 28884 + { stacktrace: + __netif_receive_skb_core+0x46d/0x990 + __netif_receive_skb+0x18/0x60 + netif_receive_skb_internal+0x23/0x90 + napi_gro_complete+0xa4/0xe0 + dev_gro_receive+0x23a/0x360 + napi_gro_receive+0x30/0x100 + ieee80211_deliver_skb+0xd6/0x270 [mac80211] + ieee80211_rx_handlers+0xccf/0x22f0 [mac80211] + ieee80211_prepare_and_rx_handle+0x4e7/0xc40 [mac80211] + ieee80211_rx+0x31d/0x900 [mac80211] + iwlagn_rx_reply_rx+0x3db/0x6f0 [iwldvm] + iwl_rx_dispatch+0x8e/0xf0 [iwldvm] + iwl_pcie_irq_handler+0xe3c/0x12f0 [iwlwifi] + irq_thread_fn+0x20/0x50 + irq_thread+0x11f/0x150 + kthread+0xd2/0xf0 + } hitcount: 98 len: 664329 + { stacktrace: + __netif_receive_skb_core+0x46d/0x990 + __netif_receive_skb+0x18/0x60 + process_backlog+0xa8/0x150 + net_rx_action+0x15d/0x340 + __do_softirq+0x114/0x2c0 + do_softirq_own_stack+0x1c/0x30 + do_softirq+0x65/0x70 + __local_bh_enable_ip+0xb5/0xc0 + ip_finish_output+0x1f4/0x840 + ip_output+0x6b/0xc0 + ip_local_out_sk+0x31/0x40 + ip_send_skb+0x1a/0x50 + udp_send_skb+0x173/0x2a0 + udp_sendmsg+0x2bf/0x9f0 + inet_sendmsg+0x64/0xa0 + sock_sendmsg+0x3d/0x50 + } hitcount: 115 len: 13030 + { stacktrace: + __netif_receive_skb_core+0x46d/0x990 + __netif_receive_skb+0x18/0x60 + netif_receive_skb_internal+0x23/0x90 + napi_gro_complete+0xa4/0xe0 + napi_gro_flush+0x6d/0x90 + iwl_pcie_irq_handler+0x92a/0x12f0 [iwlwifi] + irq_thread_fn+0x20/0x50 + irq_thread+0x11f/0x150 + kthread+0xd2/0xf0 + ret_from_fork+0x42/0x70 + } hitcount: 934 len: 5512212 + + Totals: + Hits: 1232 + Entries: 4 + Dropped: 0 + + The above shows all the netif_receive_skb callpaths and their total + lengths for the duration of the wget command. + + The 'clear' hist trigger param can be used to clear the hash table. + Suppose we wanted to try another run of the previous example but + this time also wanted to see the complete list of events that went + into the histogram. In order to avoid having to set everything up + again, we can just clear the histogram first: + + # echo 'hist:key=stacktrace:vals=len:clear' >> \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + + Just to verify that it is in fact cleared, here's what we now see in + the hist file: + + # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist + # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused] + + Totals: + Hits: 0 + Entries: 0 + Dropped: 0 + + Since we want to see the detailed list of every netif_receive_skb + event occurring during the new run, which are in fact the same + events being aggregated into the hash table, we add some additional + 'enable_event' events to the triggering sched_process_exec and + sched_process_exit events as such: + + # echo 'enable_event:net:netif_receive_skb if filename==/usr/bin/wget' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger + + # echo 'disable_event:net:netif_receive_skb if comm==wget' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger + + If you read the trigger files for the sched_process_exec and + sched_process_exit triggers, you should see two triggers for each: + one enabling/disabling the hist aggregation and the other + enabling/disabling the logging of events: + + # cat /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger + enable_event:net:netif_receive_skb:unlimited if filename==/usr/bin/wget + enable_hist:net:netif_receive_skb:unlimited if filename==/usr/bin/wget + + # cat /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger + enable_event:net:netif_receive_skb:unlimited if comm==wget + disable_hist:net:netif_receive_skb:unlimited if comm==wget + + In other words, whenever either of the sched_process_exec or + sched_process_exit events is hit and matches 'wget', it enables or + disables both the histogram and the event log, and what you end up + with is a hash table and set of events just covering the specified + duration. Run the wget command again: + + $ wget https://www.kernel.org/pub/linux/kernel/v3.x/patch-3.19.xz + + Displaying the 'hist' file should show something similar to what you + saw in the last run, but this time you should also see the + individual events in the trace file: + + # cat /sys/kernel/debug/tracing/trace + + # tracer: nop + # + # entries-in-buffer/entries-written: 183/1426 #P:4 + # + # _-----=> irqs-off + # / _----=> need-resched + # | / _---=> hardirq/softirq + # || / _--=> preempt-depth + # ||| / delay + # TASK-PID CPU# |||| TIMESTAMP FUNCTION + # | | | |||| | | + wget-15108 [000] ..s1 31769.606929: netif_receive_skb: dev=lo skbaddr=ffff88009c353100 len=60 + wget-15108 [000] ..s1 31769.606999: netif_receive_skb: dev=lo skbaddr=ffff88009c353200 len=60 + dnsmasq-1382 [000] ..s1 31769.677652: netif_receive_skb: dev=lo skbaddr=ffff88009c352b00 len=130 + dnsmasq-1382 [000] ..s1 31769.685917: netif_receive_skb: dev=lo skbaddr=ffff88009c352200 len=138 + ##### CPU 2 buffer started #### + irq/29-iwlwifi-559 [002] ..s. 31772.031529: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d433d00 len=2948 + irq/29-iwlwifi-559 [002] ..s. 31772.031572: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d432200 len=1500 + irq/29-iwlwifi-559 [002] ..s. 31772.032196: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d433100 len=2948 + irq/29-iwlwifi-559 [002] ..s. 31772.032761: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d433000 len=2948 + irq/29-iwlwifi-559 [002] ..s. 31772.033220: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d432e00 len=1500 + . + . + . -- GitLab From 52a7f16dedff8f23d03df3ea556dec95b92a5801 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:57 -0600 Subject: [PATCH 3546/9938] tracing: Add support for multiple hist triggers per event Allow users to define any number of hist triggers per trace event. Any number of hist triggers may be added for a given event, which may differ by key, value, or filter. Reading the event's 'hist' file will display the output of all the hist triggers defined on an event concatenated in the order they were defined. Link: http://lkml.kernel.org/r/48a0c8dd34c344571de880fb35e211c6d9a28961.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- Documentation/trace/events.txt | 154 +++++++++++++++++++++++++-- kernel/trace/trace.c | 8 +- kernel/trace/trace_events_hist.c | 172 +++++++++++++++++++++++++------ 3 files changed, 293 insertions(+), 41 deletions(-) diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt index db223e85bd2f..cc0216760b78 100644 --- a/Documentation/trace/events.txt +++ b/Documentation/trace/events.txt @@ -550,12 +550,14 @@ The following commands are supported: 'hist' triggers add a 'hist' file to each event's subdirectory. Reading the 'hist' file for the event will dump the hash table in - its entirety to stdout. Each printed hash table entry is a simple - list of the keys and values comprising the entry; keys are printed - first and are delineated by curly braces, and are followed by the - set of value fields for the entry. By default, numeric fields are - displayed as base-10 integers. This can be modified by appending - any of the following modifiers to the field name: + its entirety to stdout. If there are multiple hist triggers + attached to an event, there will be a table for each trigger in the + output. Each printed hash table entry is a simple list of the keys + and values comprising the entry; keys are printed first and are + delineated by curly braces, and are followed by the set of value + fields for the entry. By default, numeric fields are displayed as + base-10 integers. This can be modified by appending any of the + following modifiers to the field name: .hex display a number as a hex value .sym display an address as a symbol @@ -1667,3 +1669,143 @@ The following commands are supported: . . . + + The following example demonstrates how multiple hist triggers can be + attached to a given event. This capability can be useful for + creating a set of different summaries derived from the same set of + events, or for comparing the effects of different filters, among + other things. + + # echo 'hist:keys=skbaddr.hex:vals=len if len < 0' >> \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + # echo 'hist:keys=skbaddr.hex:vals=len if len > 4096' >> \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + # echo 'hist:keys=skbaddr.hex:vals=len if len == 256' >> \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + # echo 'hist:keys=skbaddr.hex:vals=len' >> \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + # echo 'hist:keys=len:vals=common_preempt_count' >> \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + + The above set of commands create four triggers differing only in + their filters, along with a completely different though fairly + nonsensical trigger. Note that in order to append multiple hist + triggers to the same file, you should use the '>>' operator to + append them ('>' will also add the new hist trigger, but will remove + any existing hist triggers beforehand). + + Displaying the contents of the 'hist' file for the event shows the + contents of all five histograms: + + # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist + + # event histogram + # + # trigger info: hist:keys=len:vals=hitcount,common_preempt_count:sort=hitcount:size=2048 [active] + # + + { len: 176 } hitcount: 1 common_preempt_count: 0 + { len: 223 } hitcount: 1 common_preempt_count: 0 + { len: 4854 } hitcount: 1 common_preempt_count: 0 + { len: 395 } hitcount: 1 common_preempt_count: 0 + { len: 177 } hitcount: 1 common_preempt_count: 0 + { len: 446 } hitcount: 1 common_preempt_count: 0 + { len: 1601 } hitcount: 1 common_preempt_count: 0 + . + . + . + { len: 1280 } hitcount: 66 common_preempt_count: 0 + { len: 116 } hitcount: 81 common_preempt_count: 40 + { len: 708 } hitcount: 112 common_preempt_count: 0 + { len: 46 } hitcount: 221 common_preempt_count: 0 + { len: 1264 } hitcount: 458 common_preempt_count: 0 + + Totals: + Hits: 1428 + Entries: 147 + Dropped: 0 + + + # event histogram + # + # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active] + # + + { skbaddr: ffff8800baee5e00 } hitcount: 1 len: 130 + { skbaddr: ffff88005f3d5600 } hitcount: 1 len: 1280 + { skbaddr: ffff88005f3d4900 } hitcount: 1 len: 1280 + { skbaddr: ffff88009fed6300 } hitcount: 1 len: 115 + { skbaddr: ffff88009fe0ad00 } hitcount: 1 len: 115 + { skbaddr: ffff88008cdb1900 } hitcount: 1 len: 46 + { skbaddr: ffff880064b5ef00 } hitcount: 1 len: 118 + { skbaddr: ffff880044e3c700 } hitcount: 1 len: 60 + { skbaddr: ffff880100065900 } hitcount: 1 len: 46 + { skbaddr: ffff8800d46bd500 } hitcount: 1 len: 116 + { skbaddr: ffff88005f3d5f00 } hitcount: 1 len: 1280 + { skbaddr: ffff880100064700 } hitcount: 1 len: 365 + { skbaddr: ffff8800badb6f00 } hitcount: 1 len: 60 + . + . + . + { skbaddr: ffff88009fe0be00 } hitcount: 27 len: 24677 + { skbaddr: ffff88009fe0a400 } hitcount: 27 len: 23052 + { skbaddr: ffff88009fe0b700 } hitcount: 31 len: 25589 + { skbaddr: ffff88009fe0b600 } hitcount: 32 len: 27326 + { skbaddr: ffff88006a462800 } hitcount: 68 len: 71678 + { skbaddr: ffff88006a463700 } hitcount: 70 len: 72678 + { skbaddr: ffff88006a462b00 } hitcount: 71 len: 77589 + { skbaddr: ffff88006a463600 } hitcount: 73 len: 71307 + { skbaddr: ffff88006a462200 } hitcount: 81 len: 81032 + + Totals: + Hits: 1451 + Entries: 318 + Dropped: 0 + + + # event histogram + # + # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 if len == 256 [active] + # + + + Totals: + Hits: 0 + Entries: 0 + Dropped: 0 + + + # event histogram + # + # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 if len > 4096 [active] + # + + { skbaddr: ffff88009fd2c300 } hitcount: 1 len: 7212 + { skbaddr: ffff8800d2bcce00 } hitcount: 1 len: 7212 + { skbaddr: ffff8800d2bcd700 } hitcount: 1 len: 7212 + { skbaddr: ffff8800d2bcda00 } hitcount: 1 len: 21492 + { skbaddr: ffff8800ae2e2d00 } hitcount: 1 len: 7212 + { skbaddr: ffff8800d2bcdb00 } hitcount: 1 len: 7212 + { skbaddr: ffff88006a4df500 } hitcount: 1 len: 4854 + { skbaddr: ffff88008ce47b00 } hitcount: 1 len: 18636 + { skbaddr: ffff8800ae2e2200 } hitcount: 1 len: 12924 + { skbaddr: ffff88005f3e1000 } hitcount: 1 len: 4356 + { skbaddr: ffff8800d2bcdc00 } hitcount: 2 len: 24420 + { skbaddr: ffff8800d2bcc200 } hitcount: 2 len: 12996 + + Totals: + Hits: 14 + Entries: 12 + Dropped: 0 + + + # event histogram + # + # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 if len < 0 [active] + # + + + Totals: + Hits: 0 + Entries: 0 + Dropped: 0 diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8430145bea12..e89b2ed76d2d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3856,9 +3856,11 @@ static const char readme_msg[] = "\t sort field. The 'size' parameter can be used to specify more\n" "\t or fewer than the default 2048 entries for the hashtable size.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" - "\t table in its entirety to stdout. The default format used to\n" - "\t display a given field can be modified by appending any of the\n" - "\t following modifiers to the field name, as applicable:\n\n" + "\t table in its entirety to stdout. If there are multiple hist\n" + "\t triggers attached to an event, there will be a table for each\n" + "\t trigger in the output. The default format used to display a\n" + "\t given field can be modified by appending any of the following\n" + "\t modifiers to the field name, as applicable:\n\n" "\t .hex display a number as a hex value\n" "\t .sym display an address as a symbol\n" "\t .sym-offset display an address as a symbol and offset\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 5d4f02792440..4b02f8ab4dd3 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1032,33 +1032,18 @@ static int print_entries(struct seq_file *m, return n_entries; } -static int hist_show(struct seq_file *m, void *v) +static void hist_trigger_show(struct seq_file *m, + struct event_trigger_data *data, int n) { - struct event_trigger_data *test, *data = NULL; - struct trace_event_file *event_file; struct hist_trigger_data *hist_data; int n_entries, ret = 0; - mutex_lock(&event_mutex); - - event_file = event_file_data(m->private); - if (unlikely(!event_file)) { - ret = -ENODEV; - goto out_unlock; - } - - list_for_each_entry_rcu(test, &event_file->triggers, list) { - if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { - data = test; - break; - } - } - if (!data) - goto out_unlock; + if (n > 0) + seq_puts(m, "\n\n"); seq_puts(m, "# event histogram\n#\n# trigger info: "); data->ops->print(m, data->ops, data); - seq_puts(m, "\n"); + seq_puts(m, "#\n\n"); hist_data = data->private_data; n_entries = print_entries(m, hist_data); @@ -1070,6 +1055,27 @@ static int hist_show(struct seq_file *m, void *v) seq_printf(m, "\nTotals:\n Hits: %llu\n Entries: %u\n Dropped: %llu\n", (u64)atomic64_read(&hist_data->map->hits), n_entries, (u64)atomic64_read(&hist_data->map->drops)); +} + +static int hist_show(struct seq_file *m, void *v) +{ + struct event_trigger_data *data; + struct trace_event_file *event_file; + int n = 0, ret = 0; + + mutex_lock(&event_mutex); + + event_file = event_file_data(m->private); + if (unlikely(!event_file)) { + ret = -ENODEV; + goto out_unlock; + } + + list_for_each_entry_rcu(data, &event_file->triggers, list) { + if (data->cmd_ops->trigger_type == ETT_EVENT_HIST) + hist_trigger_show(m, data, n++); + } + out_unlock: mutex_unlock(&event_mutex); @@ -1233,6 +1239,54 @@ static void hist_clear(struct event_trigger_data *data) data->paused = paused; } +static bool hist_trigger_match(struct event_trigger_data *data, + struct event_trigger_data *data_test) +{ + struct tracing_map_sort_key *sort_key, *sort_key_test; + struct hist_trigger_data *hist_data, *hist_data_test; + struct hist_field *key_field, *key_field_test; + unsigned int i; + + hist_data = data->private_data; + hist_data_test = data_test->private_data; + + if (hist_data->n_vals != hist_data_test->n_vals || + hist_data->n_fields != hist_data_test->n_fields || + hist_data->n_sort_keys != hist_data_test->n_sort_keys) + return false; + + if ((data->filter_str && !data_test->filter_str) || + (!data->filter_str && data_test->filter_str)) + return false; + + for_each_hist_field(i, hist_data) { + key_field = hist_data->fields[i]; + key_field_test = hist_data_test->fields[i]; + + if (key_field->flags != key_field_test->flags) + return false; + if (key_field->field != key_field_test->field) + return false; + if (key_field->offset != key_field_test->offset) + return false; + } + + for (i = 0; i < hist_data->n_sort_keys; i++) { + sort_key = &hist_data->sort_keys[i]; + sort_key_test = &hist_data_test->sort_keys[i]; + + if (sort_key->field_idx != sort_key_test->field_idx || + sort_key->descending != sort_key_test->descending) + return false; + } + + if (data->filter_str && + (strcmp(data->filter_str, data_test->filter_str) != 0)) + return false; + + return true; +} + static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, struct event_trigger_data *data, struct trace_event_file *file) @@ -1243,6 +1297,8 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, list_for_each_entry_rcu(test, &file->triggers, list) { if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { + if (!hist_trigger_match(data, test)) + continue; if (hist_data->attrs->pause) test->paused = true; else if (hist_data->attrs->cont) @@ -1282,6 +1338,44 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, return ret; } +static void hist_unregister_trigger(char *glob, struct event_trigger_ops *ops, + struct event_trigger_data *data, + struct trace_event_file *file) +{ + struct event_trigger_data *test; + bool unregistered = false; + + list_for_each_entry_rcu(test, &file->triggers, list) { + if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { + if (!hist_trigger_match(data, test)) + continue; + unregistered = true; + list_del_rcu(&test->list); + trace_event_trigger_enable_disable(file, 0); + update_cond_flag(file); + break; + } + } + + if (unregistered && test->ops->free) + test->ops->free(test->ops, test); +} + +static void hist_unreg_all(struct trace_event_file *file) +{ + struct event_trigger_data *test; + + list_for_each_entry_rcu(test, &file->triggers, list) { + if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { + list_del_rcu(&test->list); + trace_event_trigger_enable_disable(file, 0); + update_cond_flag(file); + if (test->ops->free) + test->ops->free(test->ops, test); + } + } +} + static int event_hist_trigger_func(struct event_command *cmd_ops, struct trace_event_file *file, char *glob, char *cmd, char *param) @@ -1331,22 +1425,19 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, trigger_data->private_data = hist_data; + /* if param is non-empty, it's supposed to be a filter */ + if (param && cmd_ops->set_filter) { + ret = cmd_ops->set_filter(param, trigger_data, file); + if (ret < 0) + goto out_free; + } + if (glob[0] == '!') { cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file); ret = 0; goto out_free; } - if (!param) /* if param is non-empty, it's supposed to be a filter */ - goto out_reg; - - if (!cmd_ops->set_filter) - goto out_reg; - - ret = cmd_ops->set_filter(param, trigger_data, file); - if (ret < 0) - goto out_free; - out_reg: ret = cmd_ops->reg(glob, trigger_ops, trigger_data, file); /* * The above returns on success the # of triggers registered, @@ -1379,7 +1470,8 @@ static struct event_command trigger_hist_cmd = { .flags = EVENT_CMD_FL_NEEDS_REC, .func = event_hist_trigger_func, .reg = hist_register_trigger, - .unreg = unregister_trigger, + .unreg = hist_unregister_trigger, + .unreg_all = hist_unreg_all, .get_trigger_ops = event_hist_get_trigger_ops, .set_filter = set_trigger_filter, }; @@ -1406,7 +1498,6 @@ hist_enable_trigger(struct event_trigger_data *data, void *rec) test->paused = false; else test->paused = true; - break; } } } @@ -1469,12 +1560,28 @@ hist_enable_get_trigger_ops(char *cmd, char *param) return ops; } +static void hist_enable_unreg_all(struct trace_event_file *file) +{ + struct event_trigger_data *test; + + list_for_each_entry_rcu(test, &file->triggers, list) { + if (test->cmd_ops->trigger_type == ETT_HIST_ENABLE) { + list_del_rcu(&test->list); + update_cond_flag(file); + trace_event_trigger_enable_disable(file, 0); + if (test->ops->free) + test->ops->free(test->ops, test); + } + } +} + static struct event_command trigger_hist_enable_cmd = { .name = ENABLE_HIST_STR, .trigger_type = ETT_HIST_ENABLE, .func = event_enable_trigger_func, .reg = event_enable_register_trigger, .unreg = event_enable_unregister_trigger, + .unreg_all = hist_enable_unreg_all, .get_trigger_ops = hist_enable_get_trigger_ops, .set_filter = set_trigger_filter, }; @@ -1485,6 +1592,7 @@ static struct event_command trigger_hist_disable_cmd = { .func = event_enable_trigger_func, .reg = event_enable_register_trigger, .unreg = event_enable_unregister_trigger, + .unreg_all = hist_enable_unreg_all, .get_trigger_ops = hist_enable_get_trigger_ops, .set_filter = set_trigger_filter, }; -- GitLab From db1388b4ffa9e31e9ff0abacc3bdb121bec8c688 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:58 -0600 Subject: [PATCH 3547/9938] tracing: Add support for named triggers Named triggers are sets of triggers that share a common set of trigger data. An example of functionality that could benefit from this type of capability would be a set of inlined probes that would each contribute event counts, for example, to a shared counter data structure. The first named trigger registered with a given name owns the common trigger data that the others subsequently registered with the same name will reference. The functions defined here allow users to add, delete, and find named triggers. It also adds functions to pause and unpause named triggers; since named triggers act upon common data, they should also be paused and unpaused as a group. Link: http://lkml.kernel.org/r/c09ff648360f65b10a3e321eddafe18060b4a04f.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace.h | 13 +++ kernel/trace/trace_events_trigger.c | 143 ++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index cab1f4bfe85b..727a3d28bce5 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1184,7 +1184,11 @@ struct event_trigger_data { char *filter_str; void *private_data; bool paused; + bool paused_tmp; struct list_head list; + char *name; + struct list_head named_list; + struct event_trigger_data *named_data; }; /* Avoid typos */ @@ -1227,6 +1231,15 @@ extern void unregister_trigger(char *glob, struct event_trigger_ops *ops, extern int set_trigger_filter(char *filter_str, struct event_trigger_data *trigger_data, struct trace_event_file *file); +extern struct event_trigger_data *find_named_trigger(const char *name); +extern bool is_named_trigger(struct event_trigger_data *test); +extern int save_named_trigger(const char *name, + struct event_trigger_data *data); +extern void del_named_trigger(struct event_trigger_data *data); +extern void pause_named_trigger(struct event_trigger_data *data); +extern void unpause_named_trigger(struct event_trigger_data *data); +extern void set_named_trigger_data(struct event_trigger_data *data, + struct event_trigger_data *named_data); extern int register_event_command(struct event_command *cmd); extern int unregister_event_command(struct event_command *cmd); extern int register_trigger_hist_enable_disable_cmds(void); diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index d133f2094566..a975571cde24 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -641,6 +641,7 @@ event_trigger_callback(struct event_command *cmd_ops, trigger_data->ops = trigger_ops; trigger_data->cmd_ops = cmd_ops; INIT_LIST_HEAD(&trigger_data->list); + INIT_LIST_HEAD(&trigger_data->named_list); if (glob[0] == '!') { cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file); @@ -764,6 +765,148 @@ int set_trigger_filter(char *filter_str, return ret; } +static LIST_HEAD(named_triggers); + +/** + * find_named_trigger - Find the common named trigger associated with @name + * @name: The name of the set of named triggers to find the common data for + * + * Named triggers are sets of triggers that share a common set of + * trigger data. The first named trigger registered with a given name + * owns the common trigger data that the others subsequently + * registered with the same name will reference. This function + * returns the common trigger data associated with that first + * registered instance. + * + * Return: the common trigger data for the given named trigger on + * success, NULL otherwise. + */ +struct event_trigger_data *find_named_trigger(const char *name) +{ + struct event_trigger_data *data; + + if (!name) + return NULL; + + list_for_each_entry(data, &named_triggers, named_list) { + if (data->named_data) + continue; + if (strcmp(data->name, name) == 0) + return data; + } + + return NULL; +} + +/** + * is_named_trigger - determine if a given trigger is a named trigger + * @test: The trigger data to test + * + * Return: true if 'test' is a named trigger, false otherwise. + */ +bool is_named_trigger(struct event_trigger_data *test) +{ + struct event_trigger_data *data; + + list_for_each_entry(data, &named_triggers, named_list) { + if (test == data) + return true; + } + + return false; +} + +/** + * save_named_trigger - save the trigger in the named trigger list + * @name: The name of the named trigger set + * @data: The trigger data to save + * + * Return: 0 if successful, negative error otherwise. + */ +int save_named_trigger(const char *name, struct event_trigger_data *data) +{ + data->name = kstrdup(name, GFP_KERNEL); + if (!data->name) + return -ENOMEM; + + list_add(&data->named_list, &named_triggers); + + return 0; +} + +/** + * del_named_trigger - delete a trigger from the named trigger list + * @data: The trigger data to delete + */ +void del_named_trigger(struct event_trigger_data *data) +{ + kfree(data->name); + data->name = NULL; + + list_del(&data->named_list); +} + +static void __pause_named_trigger(struct event_trigger_data *data, bool pause) +{ + struct event_trigger_data *test; + + list_for_each_entry(test, &named_triggers, named_list) { + if (strcmp(test->name, data->name) == 0) { + if (pause) { + test->paused_tmp = test->paused; + test->paused = true; + } else { + test->paused = test->paused_tmp; + } + } + } +} + +/** + * pause_named_trigger - Pause all named triggers with the same name + * @data: The trigger data of a named trigger to pause + * + * Pauses a named trigger along with all other triggers having the + * same name. Because named triggers share a common set of data, + * pausing only one is meaningless, so pausing one named trigger needs + * to pause all triggers with the same name. + */ +void pause_named_trigger(struct event_trigger_data *data) +{ + __pause_named_trigger(data, true); +} + +/** + * unpause_named_trigger - Un-pause all named triggers with the same name + * @data: The trigger data of a named trigger to unpause + * + * Un-pauses a named trigger along with all other triggers having the + * same name. Because named triggers share a common set of data, + * unpausing only one is meaningless, so unpausing one named trigger + * needs to unpause all triggers with the same name. + */ +void unpause_named_trigger(struct event_trigger_data *data) +{ + __pause_named_trigger(data, false); +} + +/** + * set_named_trigger_data - Associate common named trigger data + * @data: The trigger data of a named trigger to unpause + * + * Named triggers are sets of triggers that share a common set of + * trigger data. The first named trigger registered with a given name + * owns the common trigger data that the others subsequently + * registered with the same name will reference. This function + * associates the common trigger data from the first trigger with the + * given trigger. + */ +void set_named_trigger_data(struct event_trigger_data *data, + struct event_trigger_data *named_data) +{ + data->named_data = named_data; +} + static void traceon_trigger(struct event_trigger_data *data, void *rec) { -- GitLab From 5463bfda327b1f7310556ef3136533e27c774f13 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 3 Mar 2016 12:54:59 -0600 Subject: [PATCH 3548/9938] tracing: Add support for named hist triggers Allow users to define 'named' hist triggers. All triggers created with the same 'name=xxx' option will update the same shared histogram data. This expands the hist trigger syntax from this: # echo hist:keys=xxx ... [ if filter] > event/trigger to this: # echo hist:name=xxx:keys=xxx ... [ if filter] > event/trigger Named histograms must use a 'compatible' set of keys and values, which means each event added to a set of named triggers must have the same names and types. Reading the 'hist' file of any of the participating events will produce the same output as any other participating event, which is to be expected since they share the same data. Link: http://lkml.kernel.org/r/1dbc84ee3322a75daaf5b3ef1d0cc0a2fb682fc7.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Tested-by: Masami Hiramatsu Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- Documentation/trace/events.txt | 274 ++++++++++++++++++++++++++++++- kernel/trace/trace.c | 14 +- kernel/trace/trace_events_hist.c | 148 +++++++++++++++-- 3 files changed, 407 insertions(+), 29 deletions(-) diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt index cc0216760b78..08d74d75150d 100644 --- a/Documentation/trace/events.txt +++ b/Documentation/trace/events.txt @@ -524,7 +524,7 @@ The following commands are supported: hist:keys=[:values=] [:sort=][:size=#entries][:pause][:continue] - [:clear] [if ] + [:clear][:name=histname1] [if ] When a matching event is hit, an entry is added to a hash table using the key(s) and value(s) named. Keys and values correspond to @@ -546,18 +546,28 @@ The following commands are supported: specified by the 'sort' keyword. If more than one field is specified, the result will be a 'sort within a sort': the first key is taken to be the primary sort key and the second the secondary - key. + key. If a hist trigger is given a name using the 'name' parameter, + its histogram data will be shared with other triggers of the same + name, and trigger hits will update this common data. Only triggers + with 'compatible' fields can be combined in this way; triggers are + 'compatible' if the fields named in the trigger share the same + number and type of fields and those fields also have the same names. + Note that any two events always share the compatible 'hitcount' and + 'stacktrace' fields and can therefore be combined using those + fields, however pointless that may be. 'hist' triggers add a 'hist' file to each event's subdirectory. Reading the 'hist' file for the event will dump the hash table in its entirety to stdout. If there are multiple hist triggers attached to an event, there will be a table for each trigger in the - output. Each printed hash table entry is a simple list of the keys - and values comprising the entry; keys are printed first and are - delineated by curly braces, and are followed by the set of value - fields for the entry. By default, numeric fields are displayed as - base-10 integers. This can be modified by appending any of the - following modifiers to the field name: + output. The table displayed for a named trigger will be the same as + any other instance having the same name. Each printed hash table + entry is a simple list of the keys and values comprising the entry; + keys are printed first and are delineated by curly braces, and are + followed by the set of value fields for the entry. By default, + numeric fields are displayed as base-10 integers. This can be + modified by appending any of the following modifiers to the field + name: .hex display a number as a hex value .sym display an address as a symbol @@ -1809,3 +1819,251 @@ The following commands are supported: Hits: 0 Entries: 0 Dropped: 0 + + Named triggers can be used to have triggers share a common set of + histogram data. This capability is mostly useful for combining the + output of events generated by tracepoints contained inside inline + functions, but names can be used in a hist trigger on any event. + For example, these two triggers when hit will update the same 'len' + field in the shared 'foo' histogram data: + + # echo 'hist:name=foo:keys=skbaddr.hex:vals=len' > \ + /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger + # echo 'hist:name=foo:keys=skbaddr.hex:vals=len' > \ + /sys/kernel/debug/tracing/events/net/netif_rx/trigger + + You can see that they're updating common histogram data by reading + each event's hist files at the same time: + + # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist; + cat /sys/kernel/debug/tracing/events/net/netif_rx/hist + + # event histogram + # + # trigger info: hist:name=foo:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active] + # + + { skbaddr: ffff88000ad53500 } hitcount: 1 len: 46 + { skbaddr: ffff8800af5a1500 } hitcount: 1 len: 76 + { skbaddr: ffff8800d62a1900 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bccb00 } hitcount: 1 len: 468 + { skbaddr: ffff8800d3c69900 } hitcount: 1 len: 46 + { skbaddr: ffff88009ff09100 } hitcount: 1 len: 52 + { skbaddr: ffff88010f13ab00 } hitcount: 1 len: 168 + { skbaddr: ffff88006a54f400 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bcc500 } hitcount: 1 len: 260 + { skbaddr: ffff880064505000 } hitcount: 1 len: 46 + { skbaddr: ffff8800baf24e00 } hitcount: 1 len: 32 + { skbaddr: ffff88009fe0ad00 } hitcount: 1 len: 46 + { skbaddr: ffff8800d3edff00 } hitcount: 1 len: 44 + { skbaddr: ffff88009fe0b400 } hitcount: 1 len: 168 + { skbaddr: ffff8800a1c55a00 } hitcount: 1 len: 40 + { skbaddr: ffff8800d2bcd100 } hitcount: 1 len: 40 + { skbaddr: ffff880064505f00 } hitcount: 1 len: 174 + { skbaddr: ffff8800a8bff200 } hitcount: 1 len: 160 + { skbaddr: ffff880044e3cc00 } hitcount: 1 len: 76 + { skbaddr: ffff8800a8bfe700 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bcdc00 } hitcount: 1 len: 32 + { skbaddr: ffff8800a1f64800 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bcde00 } hitcount: 1 len: 988 + { skbaddr: ffff88006a5dea00 } hitcount: 1 len: 46 + { skbaddr: ffff88002e37a200 } hitcount: 1 len: 44 + { skbaddr: ffff8800a1f32c00 } hitcount: 2 len: 676 + { skbaddr: ffff88000ad52600 } hitcount: 2 len: 107 + { skbaddr: ffff8800a1f91e00 } hitcount: 2 len: 92 + { skbaddr: ffff8800af5a0200 } hitcount: 2 len: 142 + { skbaddr: ffff8800d2bcc600 } hitcount: 2 len: 220 + { skbaddr: ffff8800ba36f500 } hitcount: 2 len: 92 + { skbaddr: ffff8800d021f800 } hitcount: 2 len: 92 + { skbaddr: ffff8800a1f33600 } hitcount: 2 len: 675 + { skbaddr: ffff8800a8bfff00 } hitcount: 3 len: 138 + { skbaddr: ffff8800d62a1300 } hitcount: 3 len: 138 + { skbaddr: ffff88002e37a100 } hitcount: 4 len: 184 + { skbaddr: ffff880064504400 } hitcount: 4 len: 184 + { skbaddr: ffff8800a8bfec00 } hitcount: 4 len: 184 + { skbaddr: ffff88000ad53700 } hitcount: 5 len: 230 + { skbaddr: ffff8800d2bcdb00 } hitcount: 5 len: 196 + { skbaddr: ffff8800a1f90000 } hitcount: 6 len: 276 + { skbaddr: ffff88006a54f900 } hitcount: 6 len: 276 + + Totals: + Hits: 81 + Entries: 42 + Dropped: 0 + # event histogram + # + # trigger info: hist:name=foo:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active] + # + + { skbaddr: ffff88000ad53500 } hitcount: 1 len: 46 + { skbaddr: ffff8800af5a1500 } hitcount: 1 len: 76 + { skbaddr: ffff8800d62a1900 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bccb00 } hitcount: 1 len: 468 + { skbaddr: ffff8800d3c69900 } hitcount: 1 len: 46 + { skbaddr: ffff88009ff09100 } hitcount: 1 len: 52 + { skbaddr: ffff88010f13ab00 } hitcount: 1 len: 168 + { skbaddr: ffff88006a54f400 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bcc500 } hitcount: 1 len: 260 + { skbaddr: ffff880064505000 } hitcount: 1 len: 46 + { skbaddr: ffff8800baf24e00 } hitcount: 1 len: 32 + { skbaddr: ffff88009fe0ad00 } hitcount: 1 len: 46 + { skbaddr: ffff8800d3edff00 } hitcount: 1 len: 44 + { skbaddr: ffff88009fe0b400 } hitcount: 1 len: 168 + { skbaddr: ffff8800a1c55a00 } hitcount: 1 len: 40 + { skbaddr: ffff8800d2bcd100 } hitcount: 1 len: 40 + { skbaddr: ffff880064505f00 } hitcount: 1 len: 174 + { skbaddr: ffff8800a8bff200 } hitcount: 1 len: 160 + { skbaddr: ffff880044e3cc00 } hitcount: 1 len: 76 + { skbaddr: ffff8800a8bfe700 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bcdc00 } hitcount: 1 len: 32 + { skbaddr: ffff8800a1f64800 } hitcount: 1 len: 46 + { skbaddr: ffff8800d2bcde00 } hitcount: 1 len: 988 + { skbaddr: ffff88006a5dea00 } hitcount: 1 len: 46 + { skbaddr: ffff88002e37a200 } hitcount: 1 len: 44 + { skbaddr: ffff8800a1f32c00 } hitcount: 2 len: 676 + { skbaddr: ffff88000ad52600 } hitcount: 2 len: 107 + { skbaddr: ffff8800a1f91e00 } hitcount: 2 len: 92 + { skbaddr: ffff8800af5a0200 } hitcount: 2 len: 142 + { skbaddr: ffff8800d2bcc600 } hitcount: 2 len: 220 + { skbaddr: ffff8800ba36f500 } hitcount: 2 len: 92 + { skbaddr: ffff8800d021f800 } hitcount: 2 len: 92 + { skbaddr: ffff8800a1f33600 } hitcount: 2 len: 675 + { skbaddr: ffff8800a8bfff00 } hitcount: 3 len: 138 + { skbaddr: ffff8800d62a1300 } hitcount: 3 len: 138 + { skbaddr: ffff88002e37a100 } hitcount: 4 len: 184 + { skbaddr: ffff880064504400 } hitcount: 4 len: 184 + { skbaddr: ffff8800a8bfec00 } hitcount: 4 len: 184 + { skbaddr: ffff88000ad53700 } hitcount: 5 len: 230 + { skbaddr: ffff8800d2bcdb00 } hitcount: 5 len: 196 + { skbaddr: ffff8800a1f90000 } hitcount: 6 len: 276 + { skbaddr: ffff88006a54f900 } hitcount: 6 len: 276 + + Totals: + Hits: 81 + Entries: 42 + Dropped: 0 + + And here's an example that shows how to combine histogram data from + any two events even if they don't share any 'compatible' fields + other than 'hitcount' and 'stacktrace'. These commands create a + couple of triggers named 'bar' using those fields: + + # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \ + /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger + # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \ + /sys/kernel/debug/tracing/events/net/netif_rx/trigger + + And displaying the output of either shows some interesting if + somewhat confusing output: + + # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist + # cat /sys/kernel/debug/tracing/events/net/netif_rx/hist + + # event histogram + # + # trigger info: hist:name=bar:keys=stacktrace:vals=hitcount:sort=hitcount:size=2048 [active] + # + + { stacktrace: + _do_fork+0x18e/0x330 + kernel_thread+0x29/0x30 + kthreadd+0x154/0x1b0 + ret_from_fork+0x3f/0x70 + } hitcount: 1 + { stacktrace: + netif_rx_internal+0xb2/0xd0 + netif_rx_ni+0x20/0x70 + dev_loopback_xmit+0xaa/0xd0 + ip_mc_output+0x126/0x240 + ip_local_out_sk+0x31/0x40 + igmp_send_report+0x1e9/0x230 + igmp_timer_expire+0xe9/0x120 + call_timer_fn+0x39/0xf0 + run_timer_softirq+0x1e1/0x290 + __do_softirq+0xfd/0x290 + irq_exit+0x98/0xb0 + smp_apic_timer_interrupt+0x4a/0x60 + apic_timer_interrupt+0x6d/0x80 + cpuidle_enter+0x17/0x20 + call_cpuidle+0x3b/0x60 + cpu_startup_entry+0x22d/0x310 + } hitcount: 1 + { stacktrace: + netif_rx_internal+0xb2/0xd0 + netif_rx_ni+0x20/0x70 + dev_loopback_xmit+0xaa/0xd0 + ip_mc_output+0x17f/0x240 + ip_local_out_sk+0x31/0x40 + ip_send_skb+0x1a/0x50 + udp_send_skb+0x13e/0x270 + udp_sendmsg+0x2bf/0x980 + inet_sendmsg+0x67/0xa0 + sock_sendmsg+0x38/0x50 + SYSC_sendto+0xef/0x170 + SyS_sendto+0xe/0x10 + entry_SYSCALL_64_fastpath+0x12/0x6a + } hitcount: 2 + { stacktrace: + netif_rx_internal+0xb2/0xd0 + netif_rx+0x1c/0x60 + loopback_xmit+0x6c/0xb0 + dev_hard_start_xmit+0x219/0x3a0 + __dev_queue_xmit+0x415/0x4f0 + dev_queue_xmit_sk+0x13/0x20 + ip_finish_output2+0x237/0x340 + ip_finish_output+0x113/0x1d0 + ip_output+0x66/0xc0 + ip_local_out_sk+0x31/0x40 + ip_send_skb+0x1a/0x50 + udp_send_skb+0x16d/0x270 + udp_sendmsg+0x2bf/0x980 + inet_sendmsg+0x67/0xa0 + sock_sendmsg+0x38/0x50 + ___sys_sendmsg+0x14e/0x270 + } hitcount: 76 + { stacktrace: + netif_rx_internal+0xb2/0xd0 + netif_rx+0x1c/0x60 + loopback_xmit+0x6c/0xb0 + dev_hard_start_xmit+0x219/0x3a0 + __dev_queue_xmit+0x415/0x4f0 + dev_queue_xmit_sk+0x13/0x20 + ip_finish_output2+0x237/0x340 + ip_finish_output+0x113/0x1d0 + ip_output+0x66/0xc0 + ip_local_out_sk+0x31/0x40 + ip_send_skb+0x1a/0x50 + udp_send_skb+0x16d/0x270 + udp_sendmsg+0x2bf/0x980 + inet_sendmsg+0x67/0xa0 + sock_sendmsg+0x38/0x50 + ___sys_sendmsg+0x269/0x270 + } hitcount: 77 + { stacktrace: + netif_rx_internal+0xb2/0xd0 + netif_rx+0x1c/0x60 + loopback_xmit+0x6c/0xb0 + dev_hard_start_xmit+0x219/0x3a0 + __dev_queue_xmit+0x415/0x4f0 + dev_queue_xmit_sk+0x13/0x20 + ip_finish_output2+0x237/0x340 + ip_finish_output+0x113/0x1d0 + ip_output+0x66/0xc0 + ip_local_out_sk+0x31/0x40 + ip_send_skb+0x1a/0x50 + udp_send_skb+0x16d/0x270 + udp_sendmsg+0x2bf/0x980 + inet_sendmsg+0x67/0xa0 + sock_sendmsg+0x38/0x50 + SYSC_sendto+0xef/0x170 + } hitcount: 88 + { stacktrace: + _do_fork+0x18e/0x330 + SyS_clone+0x19/0x20 + entry_SYSCALL_64_fastpath+0x12/0x6a + } hitcount: 244 + + Totals: + Hits: 489 + Entries: 7 + Dropped: 0 diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e89b2ed76d2d..4e342d354c12 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3842,6 +3842,7 @@ static const char readme_msg[] = "\t [:sort=]\n" "\t [:size=#entries]\n" "\t [:pause][:continue][:clear]\n" + "\t [:name=histname1]\n" "\t [if ]\n\n" "\t When a matching event is hit, an entry is added to a hash\n" "\t table using the key(s) and value(s) named, and the value of a\n" @@ -3854,13 +3855,18 @@ static const char readme_msg[] = "\t specified using the 'sort' keyword. The sort direction can\n" "\t be modified by appending '.descending' or '.ascending' to a\n" "\t sort field. The 'size' parameter can be used to specify more\n" - "\t or fewer than the default 2048 entries for the hashtable size.\n\n" + "\t or fewer than the default 2048 entries for the hashtable size.\n" + "\t If a hist trigger is given a name using the 'name' parameter,\n" + "\t its histogram data will be shared with other triggers of the\n" + "\t same name, and trigger hits will update this common data.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" "\t table in its entirety to stdout. If there are multiple hist\n" "\t triggers attached to an event, there will be a table for each\n" - "\t trigger in the output. The default format used to display a\n" - "\t given field can be modified by appending any of the following\n" - "\t modifiers to the field name, as applicable:\n\n" + "\t trigger in the output. The table displayed for a named\n" + "\t trigger will be the same as any other instance having the\n" + "\t same name. The default format used to display a given field\n" + "\t can be modified by appending any of the following modifiers\n" + "\t to the field name, as applicable:\n\n" "\t .hex display a number as a hex value\n" "\t .sym display an address as a symbol\n" "\t .sym-offset display an address as a symbol and offset\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 4b02f8ab4dd3..bdea5603cbde 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -117,6 +117,7 @@ struct hist_trigger_attrs { char *keys_str; char *vals_str; char *sort_key_str; + char *name; bool pause; bool cont; bool clear; @@ -200,6 +201,7 @@ static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs) if (!attrs) return; + kfree(attrs->name); kfree(attrs->sort_key_str); kfree(attrs->keys_str); kfree(attrs->vals_str); @@ -227,6 +229,8 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str) attrs->vals_str = kstrdup(str, GFP_KERNEL); else if (strncmp(str, "sort=", strlen("sort=")) == 0) attrs->sort_key_str = kstrdup(str, GFP_KERNEL); + else if (strncmp(str, "name=", strlen("name=")) == 0) + attrs->name = kstrdup(str, GFP_KERNEL); else if (strcmp(str, "pause") == 0) attrs->pause = true; else if ((strcmp(str, "cont") == 0) || @@ -1131,7 +1135,12 @@ static int event_hist_trigger_print(struct seq_file *m, struct hist_field *key_field; unsigned int i; - seq_puts(m, "hist:keys="); + seq_puts(m, "hist:"); + + if (data->name) + seq_printf(m, "%s:", data->name); + + seq_puts(m, "keys="); for_each_hist_key_field(i, hist_data) { key_field = hist_data->fields[i]; @@ -1196,6 +1205,19 @@ static int event_hist_trigger_print(struct seq_file *m, return 0; } +static int event_hist_trigger_init(struct event_trigger_ops *ops, + struct event_trigger_data *data) +{ + struct hist_trigger_data *hist_data = data->private_data; + + if (!data->ref && hist_data->attrs->name) + save_named_trigger(hist_data->attrs->name, data); + + data->ref++; + + return 0; +} + static void event_hist_trigger_free(struct event_trigger_ops *ops, struct event_trigger_data *data) { @@ -1206,6 +1228,8 @@ static void event_hist_trigger_free(struct event_trigger_ops *ops, data->ref--; if (!data->ref) { + if (data->name) + del_named_trigger(data); trigger_data_free(data); destroy_hist_data(hist_data); } @@ -1214,10 +1238,44 @@ static void event_hist_trigger_free(struct event_trigger_ops *ops, static struct event_trigger_ops event_hist_trigger_ops = { .func = event_hist_trigger, .print = event_hist_trigger_print, - .init = event_trigger_init, + .init = event_hist_trigger_init, .free = event_hist_trigger_free, }; +static int event_hist_trigger_named_init(struct event_trigger_ops *ops, + struct event_trigger_data *data) +{ + data->ref++; + + save_named_trigger(data->named_data->name, data); + + event_hist_trigger_init(ops, data->named_data); + + return 0; +} + +static void event_hist_trigger_named_free(struct event_trigger_ops *ops, + struct event_trigger_data *data) +{ + if (WARN_ON_ONCE(data->ref <= 0)) + return; + + event_hist_trigger_free(ops, data->named_data); + + data->ref--; + if (!data->ref) { + del_named_trigger(data); + trigger_data_free(data); + } +} + +static struct event_trigger_ops event_hist_trigger_named_ops = { + .func = event_hist_trigger, + .print = event_hist_trigger_print, + .init = event_hist_trigger_named_init, + .free = event_hist_trigger_named_free, +}; + static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd, char *param) { @@ -1227,26 +1285,54 @@ static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd, static void hist_clear(struct event_trigger_data *data) { struct hist_trigger_data *hist_data = data->private_data; - bool paused; - paused = data->paused; - data->paused = true; + if (data->name) + pause_named_trigger(data); synchronize_sched(); tracing_map_clear(hist_data->map); - data->paused = paused; + if (data->name) + unpause_named_trigger(data); +} + +static bool compatible_field(struct ftrace_event_field *field, + struct ftrace_event_field *test_field) +{ + if (field == test_field) + return true; + if (field == NULL || test_field == NULL) + return false; + if (strcmp(field->name, test_field->name) != 0) + return false; + if (strcmp(field->type, test_field->type) != 0) + return false; + if (field->size != test_field->size) + return false; + if (field->is_signed != test_field->is_signed) + return false; + + return true; } static bool hist_trigger_match(struct event_trigger_data *data, - struct event_trigger_data *data_test) + struct event_trigger_data *data_test, + struct event_trigger_data *named_data, + bool ignore_filter) { struct tracing_map_sort_key *sort_key, *sort_key_test; struct hist_trigger_data *hist_data, *hist_data_test; struct hist_field *key_field, *key_field_test; unsigned int i; + if (named_data && (named_data != data_test) && + (named_data != data_test->named_data)) + return false; + + if (!named_data && is_named_trigger(data_test)) + return false; + hist_data = data->private_data; hist_data_test = data_test->private_data; @@ -1255,9 +1341,11 @@ static bool hist_trigger_match(struct event_trigger_data *data, hist_data->n_sort_keys != hist_data_test->n_sort_keys) return false; - if ((data->filter_str && !data_test->filter_str) || - (!data->filter_str && data_test->filter_str)) - return false; + if (!ignore_filter) { + if ((data->filter_str && !data_test->filter_str) || + (!data->filter_str && data_test->filter_str)) + return false; + } for_each_hist_field(i, hist_data) { key_field = hist_data->fields[i]; @@ -1265,7 +1353,7 @@ static bool hist_trigger_match(struct event_trigger_data *data, if (key_field->flags != key_field_test->flags) return false; - if (key_field->field != key_field_test->field) + if (!compatible_field(key_field->field, key_field_test->field)) return false; if (key_field->offset != key_field_test->offset) return false; @@ -1280,7 +1368,7 @@ static bool hist_trigger_match(struct event_trigger_data *data, return false; } - if (data->filter_str && + if (!ignore_filter && data->filter_str && (strcmp(data->filter_str, data_test->filter_str) != 0)) return false; @@ -1292,12 +1380,26 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, struct trace_event_file *file) { struct hist_trigger_data *hist_data = data->private_data; - struct event_trigger_data *test; + struct event_trigger_data *test, *named_data = NULL; int ret = 0; + if (hist_data->attrs->name) { + named_data = find_named_trigger(hist_data->attrs->name); + if (named_data) { + if (!hist_trigger_match(data, named_data, named_data, + true)) { + ret = -EINVAL; + goto out; + } + } + } + + if (hist_data->attrs->name && !named_data) + goto new; + list_for_each_entry_rcu(test, &file->triggers, list) { if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { - if (!hist_trigger_match(data, test)) + if (!hist_trigger_match(data, test, named_data, false)) continue; if (hist_data->attrs->pause) test->paused = true; @@ -1310,12 +1412,19 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, goto out; } } - + new: if (hist_data->attrs->cont || hist_data->attrs->clear) { ret = -ENOENT; goto out; } + if (named_data) { + destroy_hist_data(data->private_data); + data->private_data = named_data->private_data; + set_named_trigger_data(data, named_data); + data->ops = &event_hist_trigger_named_ops; + } + if (hist_data->attrs->pause) data->paused = true; @@ -1329,6 +1438,7 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops, ret++; update_cond_flag(file); + if (trace_event_trigger_enable_disable(file, 1) < 0) { list_del_rcu(&data->list); update_cond_flag(file); @@ -1342,12 +1452,16 @@ static void hist_unregister_trigger(char *glob, struct event_trigger_ops *ops, struct event_trigger_data *data, struct trace_event_file *file) { - struct event_trigger_data *test; + struct hist_trigger_data *hist_data = data->private_data; + struct event_trigger_data *test, *named_data = NULL; bool unregistered = false; + if (hist_data->attrs->name) + named_data = find_named_trigger(hist_data->attrs->name); + list_for_each_entry_rcu(test, &file->triggers, list) { if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { - if (!hist_trigger_match(data, test)) + if (!hist_trigger_match(data, test, named_data, false)) continue; unregistered = true; list_del_rcu(&test->list); -- GitLab From cfa0963dc474fd098d6a7a722dcecfc143a4b377 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 3 Mar 2016 12:55:00 -0600 Subject: [PATCH 3549/9938] kselftests/ftrace : Add event trigger testcases This adds simple event trigger testcases for ftracetest, which covers following triggers. - traceon-traceoff trigger - enable/disable_event trigger - snapshot trigger - stacktrace trigger - trigger filters Here is the test result. ---- # ./ftracetest test.d/trigger/ === Ftrace unit tests === [1] event trigger - test event enable/disable trigger [PASS] [2] event trigger - test trigger filter [PASS] [3] event trigger - test snapshot-trigger [PASS] [4] event trigger - test stacktrace-trigger [PASS] [5] event trigger - test traceon/off trigger [PASS] # of passed: 5 # of failed: 0 # of unresolved: 0 # of untested: 0 # of unsupported: 0 # of xfailed: 0 # of undefined(test bug): 0 ---- Link: http://lkml.kernel.org/r/12b9c2b289a0dc1e4386e7b77674611a83abca85.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Masami Hiramatsu Cc: Ingo Molnar Cc: Shuah Khan Cc: Namhyung Kim Cc: Tom Zanussi Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- .../testing/selftests/ftrace/test.d/functions | 9 +++ .../test.d/trigger/trigger-eventonoff.tc | 64 +++++++++++++++++++ .../ftrace/test.d/trigger/trigger-filter.tc | 59 +++++++++++++++++ .../ftrace/test.d/trigger/trigger-snapshot.tc | 56 ++++++++++++++++ .../test.d/trigger/trigger-stacktrace.tc | 53 +++++++++++++++ .../test.d/trigger/trigger-traceonoff.tc | 58 +++++++++++++++++ 6 files changed, 299 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions index 5d8cd06d920f..c37262f6c269 100644 --- a/tools/testing/selftests/ftrace/test.d/functions +++ b/tools/testing/selftests/ftrace/test.d/functions @@ -14,3 +14,12 @@ enable_tracing() { # start trace recording reset_tracer() { # reset the current tracer echo nop > current_tracer } + +reset_trigger() { # reset all current setting triggers + grep -v ^# events/*/*/trigger | + while read line; do + cmd=`echo $line | cut -f2- -d: | cut -f1 -d" "` + echo "!$cmd" > `echo $line | cut -f1 -d:` + done +} + diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc new file mode 100644 index 000000000000..1a9445021bf1 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc @@ -0,0 +1,64 @@ +#!/bin/sh +# description: event trigger - test event enable/disable trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep enable_event events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "event enable/disable trigger is not supported" + exit_unsupported +fi + +echo "Test enable_event trigger" +echo 0 > events/sched/sched_switch/enable +echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat events/sched/sched_switch/enable` != '1*' ]; then + fail "enable_event trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test disable_event trigger" +echo 1 > events/sched/sched_switch/enable +echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat events/sched/sched_switch/enable` != '0*' ]; then + fail "disable_event trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test semantic error for event enable/disable trigger" +! echo 'enable_event:nogroup:noevent' > events/sched/sched_process_fork/trigger +! echo 'disable_event+1' > events/sched/sched_process_fork/trigger +echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +! echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +! echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc new file mode 100644 index 000000000000..514e466e198b --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc @@ -0,0 +1,59 @@ +#!/bin/sh +# description: event trigger - test trigger filter + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test trigger filter" +echo 1 > tracing_on +echo 'traceoff if child_pid == 0' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat tracing_on` -ne 1 ]; then + fail "traceoff trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test semantic error for trigger filter" +! echo 'traceoff if a' > events/sched/sched_process_fork/trigger +! echo 'traceoff if common_pid=0' > events/sched/sched_process_fork/trigger +! echo 'traceoff if common_pid==b' > events/sched/sched_process_fork/trigger +echo 'traceoff if common_pid == 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +! echo 'traceoff if common_pid == child_pid' > events/sched/sched_process_fork/trigger +echo 'traceoff if common_pid <= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +echo 'traceoff if common_pid >= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +echo 'traceoff if parent_pid >= 0 && child_pid >= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +echo 'traceoff if parent_pid >= 0 || child_pid >= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger + + + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc new file mode 100644 index 000000000000..f84b80d551a2 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc @@ -0,0 +1,56 @@ +#!/bin/sh +# description: event trigger - test snapshot-trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep snapshot events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "snapshot trigger is not supported" + exit_unsupported +fi + +echo "Test snapshot tigger" +echo 0 > snapshot +echo 1 > events/sched/sched_process_fork/enable +( echo "forked") +echo 'snapshot:1' > events/sched/sched_process_fork/trigger +( echo "forked") +grep sched_process_fork snapshot > /dev/null || \ + fail "snapshot trigger on sched_process_fork did not work" + +reset_trigger +echo 0 > snapshot +echo 0 > events/sched/sched_process_fork/enable + +echo "Test snapshot semantic errors" + +! echo "snapshot+1" > events/sched/sched_process_fork/trigger +echo "snapshot" > events/sched/sched_process_fork/trigger +! echo "snapshot" > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc new file mode 100644 index 000000000000..9fa23b085def --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc @@ -0,0 +1,53 @@ +#!/bin/sh +# description: event trigger - test stacktrace-trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep stacktrace events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "stacktrace trigger is not supported" + exit_unsupported +fi + +echo "Test stacktrace tigger" +echo 0 > trace +echo 0 > options/stacktrace +echo 'stacktrace' > events/sched/sched_process_fork/trigger +( echo "forked") +grep "" trace > /dev/null || \ + fail "stacktrace trigger on sched_process_fork did not work" + +reset_trigger + +echo "Test stacktrace semantic errors" + +! echo "stacktrace:foo" > events/sched/sched_process_fork/trigger +echo "stacktrace" > events/sched/sched_process_fork/trigger +! echo "stacktrace" > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc new file mode 100644 index 000000000000..87648e5f987c --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc @@ -0,0 +1,58 @@ +#!/bin/sh +# description: event trigger - test traceon/off trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test traceoff trigger" +echo 1 > tracing_on +echo 'traceoff' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat tracing_on` -ne 0 ]; then + fail "traceoff trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test traceon trigger" +echo 0 > tracing_on +echo 'traceon' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat tracing_on` -ne 1 ]; then + fail "traceoff trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test semantic error for traceoff/on trigger" +! echo 'traceoff:badparam' > events/sched/sched_process_fork/trigger +! echo 'traceoff+0' > events/sched/sched_process_fork/trigger +echo 'traceon' > events/sched/sched_process_fork/trigger +! echo 'traceon' > events/sched/sched_process_fork/trigger +! echo 'traceoff' > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 -- GitLab From 76929ab51f0ee398bcf72286c4b377051f07a31b Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 3 Mar 2016 12:55:01 -0600 Subject: [PATCH 3550/9938] kselftests/ftrace: Add hist trigger testcases Add the hist trigger testcases for ftracetest. This checks the basic histogram trigger behaviors like as; - Histogram trigger itself - Histogram with string key - Histogram with compound keys - Histogram with sort key - Histogram trigger modifiers (execname, hex, syscall) - Multiple histograms on an event - Named histogram - Named histogram on multi events Here is the test result. ---- # ./ftracetest test.d/trigger/*hist*.tc === Ftrace unit tests === [1] event trigger - test histogram modifiers [PASS] [2] event trigger - test histogram trigger [PASS] [3] event trigger - test multiple histogram triggers [PASS] # of passed: 3 # of failed: 0 # of unresolved: 0 # of untested: 0 # of unsupported: 0 # of xfailed: 0 # of undefined(test bug): 0 ---- Link: http://lkml.kernel.org/r/17cb3a3d9eeadc3282645147905455a298e7fbeb.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Masami Hiramatsu Cc: Ingo Molnar Cc: Shuah Khan Cc: Namhyung Kim Cc: Tom Zanussi Signed-off-by: Tom Zanussi [Tom Zanussi: Change multihist test from truncate ('>') to append ('>>')] Reviewed-by: Namhyung Kim Signed-off-by: Steven Rostedt --- .../ftrace/test.d/trigger/trigger-hist-mod.tc | 65 +++++++++++++++ .../ftrace/test.d/trigger/trigger-hist.tc | 83 +++++++++++++++++++ .../test.d/trigger/trigger-multihist.tc | 73 ++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc new file mode 100644 index 000000000000..57e350a0bcca --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc @@ -0,0 +1,65 @@ +#!/bin/sh +# description: event trigger - test histogram modifiers + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep hist events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +echo "Test histogram with execname modifier" + +echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +COMM=`cat /proc/$$/comm` +grep "common_pid: $COMM" events/sched/sched_process_fork/hist > /dev/null || \ + fail "execname modifier on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with hex modifier" + +echo 'hist:keys=parent_pid.hex' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +# Note that $$ is the parent pid. $PID is current PID. +HEX=`printf %x $PID` +grep "parent_pid: $HEX" events/sched/sched_process_fork/hist > /dev/null || \ + fail "hex modifier on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with syscall modifier" + +echo 'hist:keys=id.syscall' > events/raw_syscalls/sys_exit/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep "id: sys_" events/raw_syscalls/sys_exit/hist > /dev/null || \ + fail "syscall modifier on raw_syscalls/sys_exit did not work" + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc new file mode 100644 index 000000000000..b2902d42a537 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc @@ -0,0 +1,83 @@ +#!/bin/sh +# description: event trigger - test histogram trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep hist events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +echo "Test histogram basic tigger" + +echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" +grep child events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with compound keys" + +echo 'hist:keys=parent_pid,child_pid' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep '^{ parent_pid:.*, child_pid:.*}' events/sched/sched_process_fork/hist > /dev/null || \ + fail "compound keys on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with string key" + +echo 'hist:keys=parent_comm' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +COMM=`cat /proc/$$/comm` +grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \ + fail "string key on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with sort key" + +echo 'hist:keys=parent_pid,child_pid:sort=child_pid.ascending' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done + +check_inc() { + while [ $# -gt 1 ]; do + [ $1 -gt $2 ] && return 1 + shift 1 + done + return 0 +} +check_inc `grep -o "child_pid:[[:space:]]*[[:digit:]]*" \ + events/sched/sched_process_fork/hist | cut -d: -f2 ` || + fail "sort param on sched_process_fork did not work" + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc new file mode 100644 index 000000000000..03c4a46561fc --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc @@ -0,0 +1,73 @@ +#!/bin/sh +# description: event trigger - test multiple histogram triggers + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit $FAIL +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep hist events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +reset_trigger + +echo "Test histogram multiple tiggers" + +echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger +echo 'hist:keys=parent_comm:vals=child_pid' >> events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" +grep child events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" +COMM=`cat /proc/$$/comm` +grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \ + fail "string key on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with its name" + +echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep test_hist events/sched/sched_process_fork/hist > /dev/null || \ + fail "named event on sched_process_fork did not work" + +echo "Test same named histogram on different events" + +echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_exit/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep test_hist events/sched/sched_process_exit/hist > /dev/null || \ + fail "named event on sched_process_fork did not work" + +diffs=`diff events/sched/sched_process_exit/hist events/sched/sched_process_fork/hist | wc -l` +test $diffs -eq 0 || fail "Same name histograms are not same" + +reset_trigger + +do_reset + +exit 0 -- GitLab From 4b94f5b7b4a5ffd885609bd033af2ecca0c9cc54 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 3 Mar 2016 12:55:02 -0600 Subject: [PATCH 3551/9938] tracing: Add hist trigger 'log2' modifier Allow users to have numeric fields displayed as log2 values in case value range is very wide by appending '.log2' to field names. For example, # echo 'hist:key=bytes_req' > kmalloc/trigger # cat kmalloc/hist { bytes_req: 504 } hitcount: 1 { bytes_req: 11 } hitcount: 1 { bytes_req: 104 } hitcount: 1 { bytes_req: 48 } hitcount: 1 { bytes_req: 2048 } hitcount: 1 { bytes_req: 4096 } hitcount: 1 { bytes_req: 240 } hitcount: 1 { bytes_req: 392 } hitcount: 1 { bytes_req: 13 } hitcount: 1 { bytes_req: 28 } hitcount: 1 { bytes_req: 12 } hitcount: 1 { bytes_req: 64 } hitcount: 2 { bytes_req: 128 } hitcount: 2 { bytes_req: 32 } hitcount: 2 { bytes_req: 8 } hitcount: 11 { bytes_req: 10 } hitcount: 13 { bytes_req: 24 } hitcount: 25 { bytes_req: 160 } hitcount: 29 { bytes_req: 16 } hitcount: 33 { bytes_req: 80 } hitcount: 36 When using '.log2' modifier, the output looks like: # echo 'hist:key=bytes_req.log2' > kmalloc/trigger # cat kmalloc/hist { bytes_req: ~ 2^12 } hitcount: 1 { bytes_req: ~ 2^11 } hitcount: 1 { bytes_req: ~ 2^9 } hitcount: 2 { bytes_req: ~ 2^6 } hitcount: 3 { bytes_req: ~ 2^3 } hitcount: 13 { bytes_req: ~ 2^5 } hitcount: 19 { bytes_req: ~ 2^8 } hitcount: 49 { bytes_req: ~ 2^7 } hitcount: 57 { bytes_req: ~ 2^4 } hitcount: 74 Link: http://lkml.kernel.org/r/7ff396b246c6a881f46b979735fddf05a0d6c71a.1457029949.git.tom.zanussi@linux.intel.com Cc: Tom Zanussi Cc: Masami Hiramatsu Signed-off-by: Namhyung Kim Reviewed-by: Masami Hiramatsu Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 1 + kernel/trace/trace_events_hist.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 4e342d354c12..988a35263fdd 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3872,6 +3872,7 @@ static const char readme_msg[] = "\t .sym-offset display an address as a symbol and offset\n" "\t .execname display a common_pid as a program name\n" "\t .syscall display a syscall id as a syscall name\n\n" + "\t .log2 display log2 value rather than raw number\n\n" "\t The 'pause' parameter can be used to pause an existing hist\n" "\t trigger or to start a hist trigger but not log any events\n" "\t until told to do so. 'continue' can be used to start or\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index bdea5603cbde..23df38aab503 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -68,6 +68,13 @@ static u64 hist_field_pstring(struct hist_field *hist_field, void *event) return (u64)(unsigned long)*addr; } +static u64 hist_field_log2(struct hist_field *hist_field, void *event) +{ + u64 val = *(u64 *)(event + hist_field->field->offset); + + return (u64) ilog2(roundup_pow_of_two(val)); +} + #define DEFINE_HIST_FIELD_FN(type) \ static u64 hist_field_##type(struct hist_field *hist_field, void *event)\ { \ @@ -111,6 +118,7 @@ enum hist_field_flags { HIST_FIELD_FL_EXECNAME = 64, HIST_FIELD_FL_SYSCALL = 128, HIST_FIELD_FL_STACKTRACE = 256, + HIST_FIELD_FL_LOG2 = 512, }; struct hist_trigger_attrs { @@ -358,6 +366,11 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field, goto out; } + if (flags & HIST_FIELD_FL_LOG2) { + hist_field->fn = hist_field_log2; + goto out; + } + if (is_string_field(field)) { flags |= HIST_FIELD_FL_STRING; @@ -522,6 +535,8 @@ static int create_key_field(struct hist_trigger_data *hist_data, flags |= HIST_FIELD_FL_EXECNAME; else if (strcmp(field_str, "syscall") == 0) flags |= HIST_FIELD_FL_SYSCALL; + else if (strcmp(field_str, "log2") == 0) + flags |= HIST_FIELD_FL_LOG2; else { ret = -EINVAL; goto out; @@ -980,6 +995,9 @@ hist_trigger_entry_print(struct seq_file *m, key + key_field->offset, HIST_STACKTRACE_DEPTH); multiline = true; + } else if (key_field->flags & HIST_FIELD_FL_LOG2) { + seq_printf(m, "%s: ~ 2^%-2llu", key_field->field->name, + *(u64 *)(key + key_field->offset)); } else if (key_field->flags & HIST_FIELD_FL_STRING) { seq_printf(m, "%s: %-50s", key_field->field->name, (char *)(key + key_field->offset)); @@ -1112,6 +1130,8 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) flags_str = "execname"; else if (hist_field->flags & HIST_FIELD_FL_SYSCALL) flags_str = "syscall"; + else if (hist_field->flags & HIST_FIELD_FL_LOG2) + flags_str = "log2"; return flags_str; } -- GitLab From 93c5f671f25cb7a73492b7a96b426c4fb1efa715 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 3 Mar 2016 12:55:03 -0600 Subject: [PATCH 3552/9938] kselftests/ftrace: Add a test for log2 modifier of hist trigger Add a test for log2 modifier of hist trigger in hist_mod.tc. Here is the test result. ---- # ./ftracetest test.d/trigger/trigger-hist-mod.tc === Ftrace unit tests === [1] event trigger - test histogram modifiers [PASS] # of passed: 1 # of failed: 0 # of unresolved: 0 # of untested: 0 # of unsupported: 0 # of xfailed: 0 # of undefined(test bug): 0 ---- Link: http://lkml.kernel.org/r/3f1ab735c06a50b1b40d3e96b8b6a3e5ea62fd86.1457029949.git.tom.zanussi@linux.intel.com Signed-off-by: Masami Hiramatsu Cc: Ingo Molnar Cc: Shuah Khan Cc: Namhyung Kim Cc: Tom Zanussi Tested-by: Tom Zanussi Signed-off-by: Steven Rostedt --- .../ftrace/test.d/trigger/trigger-hist-mod.tc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc index 57e350a0bcca..c2b61c4fda11 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc @@ -60,6 +60,16 @@ for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done grep "id: sys_" events/raw_syscalls/sys_exit/hist > /dev/null || \ fail "syscall modifier on raw_syscalls/sys_exit did not work" + +reset_trigger + +echo "Test histgram with log2 modifier" + +echo 'hist:keys=bytes_req.log2' > events/kmem/kmalloc/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep 'bytes_req: ~ 2^[0-9]*' events/kmem/kmalloc/hist > /dev/null || \ + fail "log2 modifier on kmem/kmalloc did not work" + do_reset exit 0 -- GitLab From d50c744ecde7ee3ba4d7ffb0e1c55e7a2f6bbc8e Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 8 Mar 2016 17:17:15 -0500 Subject: [PATCH 3553/9938] tracing: Fix unsigned comparison to zero in hist trigger code Fengguang Wu's bot found two comparisons of unsigned integers to zero. These were real bugs, as it would miss error conditions returned to zero. trace_events_hist.c:426:6-9: WARNING: Unsigned expression compared with zero: idx < 0 trace_events_hist.c:568:5-14: WARNING: Unsigned expression compared with zero: n_entries < 0 Reported-by: kbuild test robot Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 23df38aab503..f98b6b3a2804 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -734,7 +734,7 @@ static int create_tracing_map_fields(struct hist_trigger_data *hist_data) struct tracing_map *map = hist_data->map; struct ftrace_event_field *field; struct hist_field *hist_field; - unsigned int i, idx; + int i, idx; for_each_hist_field(i, hist_data) { hist_field = hist_data->fields[i]; @@ -1036,7 +1036,7 @@ static int print_entries(struct seq_file *m, { struct tracing_map_sort_entry **sort_entries = NULL; struct tracing_map *map = hist_data->map; - unsigned int i, n_entries; + int i, n_entries; n_entries = tracing_map_sort_entries(map, hist_data->sort_keys, hist_data->n_sort_keys, -- GitLab From 1c4b68fdd52e05730591682bc62042cead6f5af3 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 24 Feb 2016 11:29:05 +0900 Subject: [PATCH 3554/9938] ARM: dts: r8a7790: use fallback jpu compatibility string Use recently added fallback compatibility string in r8a7790 device trees. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 283698fc0fea..60db8e4f5790 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -990,7 +990,7 @@ }; jpu: jpeg-codec@fe980000 { - compatible = "renesas,jpu-r8a7790"; + compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu"; reg = <0 0xfe980000 0 0x10300>; interrupts = ; clocks = <&mstp1_clks R8A7790_CLK_JPU>; -- GitLab From 803f7e0b23d3a7cb3f038df786df4faf2e0c752a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 24 Feb 2016 11:29:06 +0900 Subject: [PATCH 3555/9938] ARM: dts: r8a7791: use fallback jpu compatibility string Use recently added fallback compatibility string in r8a7791 device tree. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 8010d935300f..d4de6db1143b 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1035,7 +1035,7 @@ }; jpu: jpeg-codec@fe980000 { - compatible = "renesas,jpu-r8a7791"; + compatible = "renesas,jpu-r8a7791", "renesas,rcar-gen2-jpu"; reg = <0 0xfe980000 0 0x10300>; interrupts = ; clocks = <&mstp1_clks R8A7791_CLK_JPU>; -- GitLab From 38805823377d762ec46f2430f29ef0cb8b3937d4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 3 Mar 2016 10:32:40 +0100 Subject: [PATCH 3556/9938] ARM: dts: r8a7790: Add SCIF2 clock Based on Rev. 2.00 of the R-Car Gen2 datasheet. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 6 +++--- include/dt-bindings/clock/r8a7790-clock.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 60db8e4f5790..6f4fdfccdcfd 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1302,19 +1302,19 @@ mstp3_clks: mstp3_clks@e615013c { compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; - clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, + clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&p_clk>, <&sd3_clk>, <&sd2_clk>, <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < - R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3 + R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SCIF2 R8A7790_CLK_SDHI3 R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0 R8A7790_CLK_IIC0 R8A7790_CLK_PCIEC R8A7790_CLK_IIC1 R8A7790_CLK_SSUSB R8A7790_CLK_CMT1 R8A7790_CLK_USBDMAC0 R8A7790_CLK_USBDMAC1 >; clock-output-names = - "iic2", "tpu0", "mmcif1", "sdhi3", + "iic2", "tpu0", "mmcif1", "scif2", "sdhi3", "sdhi2", "sdhi1", "sdhi0", "mmcif0", "iic0", "pciec", "iic1", "ssusb", "cmt1", "usbdmac0", "usbdmac1"; diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h index 7b1ad8922eec..fa5e8da809f2 100644 --- a/include/dt-bindings/clock/r8a7790-clock.h +++ b/include/dt-bindings/clock/r8a7790-clock.h @@ -66,6 +66,7 @@ #define R8A7790_CLK_IIC2 0 #define R8A7790_CLK_TPU0 4 #define R8A7790_CLK_MMCIF1 5 +#define R8A7790_CLK_SCIF2 10 #define R8A7790_CLK_SDHI3 11 #define R8A7790_CLK_SDHI2 12 #define R8A7790_CLK_SDHI1 13 -- GitLab From 022869a2c4e15c3b615dd278d59e0fa82e5a8449 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 3 Mar 2016 10:32:41 +0100 Subject: [PATCH 3557/9938] ARM: dts: r8a7790: Add SCIF2 device node Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 6f4fdfccdcfd..e96f8a4cb66f 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -732,6 +732,20 @@ status = "disabled"; }; + scif2: serial@e6e56000 { + compatible = "renesas,scif-r8a7790", "renesas,rcar-gen2-scif", + "renesas,scif"; + reg = <0 0xe6e56000 0 64>; + interrupts = ; + clocks = <&mstp3_clks R8A7790_CLK_SCIF2>, <&zs_clk>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x2b>, <&dmac0 0x2c>; + dma-names = "tx", "rx"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + hscif0: serial@e62c0000 { compatible = "renesas,hscif-r8a7790", "renesas,rcar-gen2-hscif", "renesas,hscif"; -- GitLab From 73ae9cfecd069060e7bf182250e16ff8c598f997 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 14 Mar 2016 11:13:58 +0900 Subject: [PATCH 3558/9938] ARM: dts: r8a7791: use fallback can compatibility string Use recently added fallback compatibility string in r8a7791 device tree. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index d4de6db1143b..6122a7919c9f 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1013,7 +1013,7 @@ }; can0: can@e6e80000 { - compatible = "renesas,can-r8a7791"; + compatible = "renesas,can-r8a7791", "renesas,rcar-gen2-can"; reg = <0 0xe6e80000 0 0x1000>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_RCAN0>, @@ -1024,7 +1024,7 @@ }; can1: can@e6e88000 { - compatible = "renesas,can-r8a7791"; + compatible = "renesas,can-r8a7791", "renesas,rcar-gen2-can"; reg = <0 0xe6e88000 0 0x1000>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_RCAN1>, -- GitLab From 28e941de3dc7105ab3c0c261814d4d53a6b8ddf4 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 14 Mar 2016 11:13:59 +0900 Subject: [PATCH 3559/9938] ARM: dts: r8a7790: use fallback can compatibility string Use recently added fallback compatibility string in r8a7790 device tree. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index e96f8a4cb66f..7cf52e6da956 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -982,7 +982,7 @@ }; can0: can@e6e80000 { - compatible = "renesas,can-r8a7790"; + compatible = "renesas,can-r8a7790", "renesas,rcar-gen2-can"; reg = <0 0xe6e80000 0 0x1000>; interrupts = ; clocks = <&mstp9_clks R8A7790_CLK_RCAN0>, @@ -993,7 +993,7 @@ }; can1: can@e6e88000 { - compatible = "renesas,can-r8a7790"; + compatible = "renesas,can-r8a7790", "renesas,rcar-gen2-can"; reg = <0 0xe6e88000 0 0x1000>; interrupts = ; clocks = <&mstp9_clks R8A7790_CLK_RCAN1>, -- GitLab From e980f9418f45a3c0d53e54bc17bd48406060c2bb Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 15 Mar 2016 09:26:33 +0900 Subject: [PATCH 3560/9938] ARM: dts: r8a7794: add CAN clocks to device tree Add CAN nodes to r8a7794 device tree. Based on work by Sergei Shtylyov for the r8a7791 SoC. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Acked-by: Ramesh Shanmugasundaram --- arch/arm/boot/dts/r8a7794.dtsi | 33 ++++++++++++++++++----- include/dt-bindings/clock/r8a7794-clock.h | 3 +++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 7d7d18766540..2d8835bdf3f6 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -843,6 +843,22 @@ clock-frequency = <0>; }; + /* External USB clock - can be overridden by the board */ + usb_extal_clk: usb_extal { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + }; + + /* External CAN clock */ + can_clk: can { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board. */ + clock-frequency = <0>; + status = "disabled"; + }; + /* External SCIF clock */ scif_clk: scif { compatible = "fixed-clock"; @@ -857,10 +873,11 @@ compatible = "renesas,r8a7794-cpg-clocks", "renesas,rcar-gen2-cpg-clocks"; reg = <0 0xe6150000 0 0x1000>; - clocks = <&extal_clk>; + clocks = <&extal_clk &usb_extal_clk>; #clock-cells = <1>; clock-output-names = "main", "pll0", "pll1", "pll3", - "lb", "qspi", "sdh", "sd0", "z"; + "lb", "qspi", "sdh", "sd0", "z", + "rcan"; #power-domain-cells = <0>; }; /* Variable factor clocks */ @@ -1115,20 +1132,22 @@ compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; clocks = <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>, - <&cp_clk>, <&cp_clk>, <&cp_clk>, - <&cpg_clocks R8A7794_CLK_QSPI>, <&hp_clk>, <&hp_clk>, - <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; + <&cp_clk>, <&cp_clk>, <&cp_clk>, <&p_clk>, + <&p_clk>, <&cpg_clocks R8A7794_CLK_QSPI>, + <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, + <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = ; clock-output-names = "gpio6", "gpio5", "gpio4", "gpio3", "gpio2", - "gpio1", "gpio0", "qspi_mod", + "gpio1", "gpio0", "rcan1", "rcan0", "qspi_mod", "i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0"; }; mstp11_clks: mstp11_clks@e615099c { diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index f843de6bf377..9703fbdb81c8 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -21,6 +21,7 @@ #define R8A7794_CLK_SDH 6 #define R8A7794_CLK_SD0 7 #define R8A7794_CLK_Z 8 +#define R8A7794_CLK_RCAN 9 /* MSTP0 */ #define R8A7794_CLK_MSIOF0 0 @@ -95,6 +96,8 @@ #define R8A7794_CLK_GPIO2 10 #define R8A7794_CLK_GPIO1 11 #define R8A7794_CLK_GPIO0 12 +#define R8A7794_CLK_RCAN1 15 +#define R8A7794_CLK_RCAN0 16 #define R8A7794_CLK_QSPI_MOD 17 #define R8A7794_CLK_I2C5 25 #define R8A7794_CLK_I2C4 27 -- GitLab From 9f1c1a2c784d28d45d0cd18a44e45ddd15d7458f Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 15 Mar 2016 09:26:34 +0900 Subject: [PATCH 3561/9938] ARM: dts: r8a7794: add CAN nodes to device tree Add CAN nodes to r8a7794 device tree. Based on work by Sergei Shtylyov for the r8a7791 SoC. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Acked-by: Ramesh Shanmugasundaram --- arch/arm/boot/dts/r8a7794.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 2d8835bdf3f6..a1ee2a82c3c0 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -830,6 +830,28 @@ }; }; + can0: can@e6e80000 { + compatible = "renesas,can-r8a7794", "renesas,rcar-gen2-can"; + reg = <0 0xe6e80000 0 0x1000>; + interrupts = ; + clocks = <&mstp9_clks R8A7794_CLK_RCAN0>, + <&cpg_clocks R8A7794_CLK_RCAN>, <&can_clk>; + clock-names = "clkp1", "clkp2", "can_clk"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + + can1: can@e6e88000 { + compatible = "renesas,can-r8a7794", "renesas,rcar-gen2-can"; + reg = <0 0xe6e88000 0 0x1000>; + interrupts = ; + clocks = <&mstp9_clks R8A7794_CLK_RCAN1>, + <&cpg_clocks R8A7794_CLK_RCAN>, <&can_clk>; + clock-names = "clkp1", "clkp2", "can_clk"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + clocks { #address-cells = <2>; #size-cells = <2>; -- GitLab From 7892e6c1be78a7b008722badd99e5abd0ad6007b Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 16 Mar 2016 10:52:55 +0900 Subject: [PATCH 3562/9938] ARM: dts: r8a7793: add CAN clocks to device tree The R-Car CAN controllers can derive the CAN bus clock not only from their peripheral clock input (clkp1) but also from the other internal clock (clkp2) and external clock fed on CAN_CLK pin. Describe those clocks in the device tree along with the USB_EXTAL clock from which clkp2 is derived. Based on work by Sergei Shtylyov for the r8a7791 SoC. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7793.dtsi | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index 95bbed95b0c1..0e609bdafaa9 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -839,6 +839,22 @@ clock-frequency = <0>; }; + /* External USB clock - can be overridden by the board */ + usb_extal_clk: usb_extal { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + }; + + /* External CAN clock */ + can_clk: can { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board. */ + clock-frequency = <0>; + status = "disabled"; + }; + /* External SCIF clock */ scif_clk: scif { compatible = "fixed-clock"; @@ -853,7 +869,7 @@ compatible = "renesas,r8a7793-cpg-clocks", "renesas,rcar-gen2-cpg-clocks"; reg = <0 0xe6150000 0 0x1000>; - clocks = <&extal_clk>; + clocks = <&extal_clk &usb_extal_clk>; #clock-cells = <1>; clock-output-names = "main", "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "z", @@ -1081,6 +1097,7 @@ reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; clocks = <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>, + <&p_clk>, <&p_clk>, <&cpg_clocks R8A7793_CLK_QSPI>, <&hp_clk>, <&cp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; @@ -1090,7 +1107,8 @@ R8A7793_CLK_GPIO5 R8A7793_CLK_GPIO4 R8A7793_CLK_GPIO3 R8A7793_CLK_GPIO2 R8A7793_CLK_GPIO1 R8A7793_CLK_GPIO0 - R8A7793_CLK_QSPI_MOD R8A7793_CLK_I2C5 + R8A7793_CLK_QSPI_MOD R8A7793_CLK_RCAN1 + R8A7793_CLK_RCAN0 R8A7793_CLK_I2C5 R8A7793_CLK_IICDVFS R8A7793_CLK_I2C4 R8A7793_CLK_I2C3 R8A7793_CLK_I2C2 R8A7793_CLK_I2C1 R8A7793_CLK_I2C0 @@ -1098,8 +1116,9 @@ clock-output-names = "gpio7", "gpio6", "gpio5", "gpio4", "gpio3", "gpio2", "gpio1", "gpio0", - "qspi_mod", "i2c5", "i2c6", "i2c4", - "i2c3", "i2c2", "i2c1", "i2c0"; + "rcan1", "rcan0", "qspi_mod", "i2c5", + "i2c6", "i2c4", "i2c3", "i2c2", "i2c1", + "i2c0"; }; mstp10_clks: mstp10_clks@e6150998 { compatible = "renesas,r8a7793-mstp-clocks", "renesas,cpg-mstp-clocks"; -- GitLab From a0e300ceb5259e8584ff67971981ac22580ef550 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 16 Mar 2016 10:52:56 +0900 Subject: [PATCH 3563/9938] ARM: dts: r8a7793: add CAN nodes to device tree Add CAN nodes to r8a7793 device tree. Based on work by Sergei Shtylyov for the r8a7791 SoC. Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7793.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index 0e609bdafaa9..bddc31283bd9 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -806,6 +806,28 @@ }; }; + can0: can@e6e80000 { + compatible = "renesas,can-r8a7793", "renesas,rcar-gen2-can"; + reg = <0 0xe6e80000 0 0x1000>; + interrupts = ; + clocks = <&mstp9_clks R8A7793_CLK_RCAN0>, + <&cpg_clocks R8A7793_CLK_RCAN>, <&can_clk>; + clock-names = "clkp1", "clkp2", "can_clk"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + + can1: can@e6e88000 { + compatible = "renesas,can-r8a7793", "renesas,rcar-gen2-can"; + reg = <0 0xe6e88000 0 0x1000>; + interrupts = ; + clocks = <&mstp9_clks R8A7793_CLK_RCAN1>, + <&cpg_clocks R8A7793_CLK_RCAN>, <&can_clk>; + clock-names = "clkp1", "clkp2", "can_clk"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + clocks { #address-cells = <2>; #size-cells = <2>; -- GitLab From a856b195d129059c71981b6d069085d611ad8d38 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 17 Mar 2016 16:33:10 +0900 Subject: [PATCH 3564/9938] ARM: dts: r8a7794: add IIC clocks Add IIC clocks to r8a7794 device tree. Based on similar work for the r8a7790 by Wolfram Sang. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 9 ++++++--- include/dt-bindings/clock/r8a7794-clock.h | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index a1ee2a82c3c0..8b2060c87a76 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -1099,16 +1099,19 @@ compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; clocks = <&sd3_clk>, <&sd2_clk>, <&cpg_clocks R8A7794_CLK_SD0>, - <&mmc0_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; + <&mmc0_clk>, <&hp_clk>, <&hp_clk>, <&rclk_clk>, + <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < R8A7794_CLK_SDHI2 R8A7794_CLK_SDHI1 R8A7794_CLK_SDHI0 - R8A7794_CLK_MMCIF0 R8A7794_CLK_CMT1 + R8A7794_CLK_MMCIF0 R8A7794_CLK_IIC0 + R8A7794_CLK_IIC1 R8A7794_CLK_CMT1 R8A7794_CLK_USBDMAC0 R8A7794_CLK_USBDMAC1 >; clock-output-names = "sdhi2", "sdhi1", "sdhi0", - "mmcif0", "cmt1", "usbdmac0", "usbdmac1"; + "mmcif0", "i2c6", "i2c7", + "cmt1", "usbdmac0", "usbdmac1"; }; mstp4_clks: mstp4_clks@e6150140 { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index 9703fbdb81c8..4d3ecd626c1f 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -57,6 +57,8 @@ #define R8A7794_CLK_SDHI1 12 #define R8A7794_CLK_SDHI0 14 #define R8A7794_CLK_MMCIF0 15 +#define R8A7794_CLK_IIC0 18 +#define R8A7794_CLK_IIC1 23 #define R8A7794_CLK_CMT1 29 #define R8A7794_CLK_USBDMAC0 30 #define R8A7794_CLK_USBDMAC1 31 -- GitLab From aa9b992ea2d3c2cc48712c21d1e680318d4156e2 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 17 Mar 2016 16:35:17 +0900 Subject: [PATCH 3565/9938] ARM: dts: r8a7794: Add IIC nodes Add IIC nodes to r8a7794 device tree. Based on similar work for the r8a7793 by Laurent Pinchart. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 8b2060c87a76..b0bce43779f1 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -26,6 +26,8 @@ i2c3 = &i2c3; i2c4 = &i2c4; i2c5 = &i2c5; + i2c6 = &i2c6; + i2c7 = &i2c7; spi0 = &qspi; vin0 = &vin0; vin1 = &vin1; @@ -629,6 +631,32 @@ status = "disabled"; }; + i2c6: i2c@e6500000 { + compatible = "renesas,iic-r8a7794", "renesas,rmobile-iic"; + reg = <0 0xe6500000 0 0x425>; + interrupts = ; + clocks = <&mstp3_clks R8A7794_CLK_IIC0>; + dmas = <&dmac0 0x61>, <&dmac0 0x62>; + dma-names = "tx", "rx"; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c7: i2c@e6510000 { + compatible = "renesas,iic-r8a7794", "renesas,rmobile-iic"; + reg = <0 0xe6510000 0 0x425>; + interrupts = ; + clocks = <&mstp3_clks R8A7794_CLK_IIC1>; + dmas = <&dmac0 0x65>, <&dmac0 0x66>; + dma-names = "tx", "rx"; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + mmcif0: mmc@ee200000 { compatible = "renesas,mmcif-r8a7794", "renesas,sh-mmcif"; reg = <0 0xee200000 0 0x80>; -- GitLab From a4a72b473e2897265a0fecbd5f6b5a92ea62585f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 18 Mar 2016 11:19:20 +0100 Subject: [PATCH 3566/9938] ARM: dts: sh73a0: Correct interrupt type for ARM TWD The ARM TWD interrupt is a private peripheral interrupt (PPI), and per the ARM GIC documentation, whether the type for PPIs can be set is IMPLEMENTATION DEFINED. For SH-Mobile AG5 devices the PPI type cannot be set, and so when we attempt to set the type for the ARM TWD interrupt it fails. This has gone unnoticed because it fails silently, and because we cannot re-configure the type it has had no impact. Nevertheless fix the type for the TWD interrupt so that it matches the hardware configuration. Based on patches by Jon Hunter for Tegra20/30 and OMAP4. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index 639ea2d76970..c4f434cdec60 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -43,7 +43,7 @@ timer@f0000600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0xf0000600 0x20>; - interrupts = ; + interrupts = ; clocks = <&twd_clk>; }; -- GitLab From e6c2488251b1c7e62f3e43907ca3f6fd016b1353 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 18 Mar 2016 11:19:21 +0100 Subject: [PATCH 3567/9938] ARM: dts: r8a7779: Correct interrupt type for ARM TWD The ARM TWD interrupt is a private peripheral interrupt (PPI), and per the ARM GIC documentation, whether the type for PPIs can be set is IMPLEMENTATION DEFINED. For R-Car H1 devices the PPI type cannot be set, and so when we attempt to set the type for the ARM TWD interrupt it fails. This has gone unnoticed because it fails silently, and because we cannot re-configure the type it has had no impact. Nevertheless fix the type for the TWD interrupt so that it matches the hardware configuration. Based on patches by Jon Hunter for Tegra20/30 and OMAP4. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index 60bc1e66bba9..5c1d48d712a1 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -67,7 +67,7 @@ compatible = "arm,cortex-a9-twd-timer"; reg = <0xf0000600 0x20>; interrupts = ; + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>; clocks = <&cpg_clocks R8A7779_CLK_ZS>; }; -- GitLab From 92cc7798edf105b0684a4a154fc7bac9955a4766 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 24 Mar 2016 11:01:07 +0900 Subject: [PATCH 3568/9938] ARM: dts: r8a7790: Use USB3.0 fallback compatibility string Use recently added fallback compatibility string in r8a7790 device tree. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 7cf52e6da956..7486fcf985c4 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1513,7 +1513,7 @@ }; xhci: usb@ee000000 { - compatible = "renesas,xhci-r8a7790"; + compatible = "renesas,xhci-r8a7790", "renesas,rcar-gen2-xhci"; reg = <0 0xee000000 0 0xc00>; interrupts = ; clocks = <&mstp3_clks R8A7790_CLK_SSUSB>; -- GitLab From 26dba29689aef1135378ab8783157debe1314bce Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 24 Mar 2016 11:01:08 +0900 Subject: [PATCH 3569/9938] ARM: dts: r8a7791: Use USB3.0 fallback compatibility string Use recently added fallback compatibility string in r8a7791 device tree. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 6122a7919c9f..6d4a0b6e4df9 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1520,7 +1520,7 @@ }; xhci: usb@ee000000 { - compatible = "renesas,xhci-r8a7791"; + compatible = "renesas,xhci-r8a7791", "renesas,rcar-gen2-xhci"; reg = <0 0xee000000 0 0xc00>; interrupts = ; clocks = <&mstp3_clks R8A7791_CLK_SSUSB>; -- GitLab From c1d61c9bb163e696bf06850bcabbd26386554489 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 31 Mar 2016 16:34:32 -0600 Subject: [PATCH 3570/9938] PCI: Reverse standard ACS vs device-specific ACS enabling The original thought was that if a device implemented ACS, then surely we want to use that... well, it turns out that devices can make an ACS capability so broken that we still need to fall back to quirks. Reverse the order of ACS enabling to give quirks first shot at it. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 10 ++++------ drivers/pci/quirks.c | 6 ++++-- include/linux/pci.h | 7 +++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 25e0327d4429..c98c4e2aed3c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2547,7 +2547,7 @@ void pci_request_acs(void) * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites * @dev: the PCI device */ -static int pci_std_enable_acs(struct pci_dev *dev) +static void pci_std_enable_acs(struct pci_dev *dev) { int pos; u16 cap; @@ -2555,7 +2555,7 @@ static int pci_std_enable_acs(struct pci_dev *dev) pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); if (!pos) - return -ENODEV; + return; pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); @@ -2573,8 +2573,6 @@ static int pci_std_enable_acs(struct pci_dev *dev) ctrl |= (cap & PCI_ACS_UF); pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); - - return 0; } /** @@ -2586,10 +2584,10 @@ void pci_enable_acs(struct pci_dev *dev) if (!pci_acs_enable) return; - if (!pci_std_enable_acs(dev)) + if (!pci_dev_specific_enable_acs(dev)) return; - pci_dev_specific_enable_acs(dev); + pci_std_enable_acs(dev); } static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e248c2aad000..1f5c7898a246 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4201,7 +4201,7 @@ static const struct pci_dev_enable_acs { { 0 } }; -void pci_dev_specific_enable_acs(struct pci_dev *dev) +int pci_dev_specific_enable_acs(struct pci_dev *dev) { const struct pci_dev_enable_acs *i; int ret; @@ -4213,9 +4213,11 @@ void pci_dev_specific_enable_acs(struct pci_dev *dev) i->device == (u16)PCI_ANY_ID)) { ret = i->enable_acs(dev); if (ret >= 0) - return; + return ret; } } + + return -ENOTTY; } /* diff --git a/include/linux/pci.h b/include/linux/pci.h index 004b8133417d..aaec79aee805 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1663,7 +1663,7 @@ enum pci_fixup_pass { #ifdef CONFIG_PCI_QUIRKS void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); -void pci_dev_specific_enable_acs(struct pci_dev *dev); +int pci_dev_specific_enable_acs(struct pci_dev *dev); #else static inline void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { } @@ -1672,7 +1672,10 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, { return -ENOTTY; } -static inline void pci_dev_specific_enable_acs(struct pci_dev *dev) { } +static inline int pci_dev_specific_enable_acs(struct pci_dev *dev) +{ + return -ENOTTY; +} #endif void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); -- GitLab From 35c5845957c7982dac1f525ff3412f8acf0a0385 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 19 Apr 2016 19:49:29 -0400 Subject: [PATCH 3571/9938] net: Add helpers for 64-bit aligning netlink attributes. Suggested-by: Eric Dumazet Suggested-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/netlink.h | 37 +++++++++++++++++++++++++++++++++++++ net/core/rtnetlink.c | 24 +++++------------------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 0e3172751755..e644b3489acf 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -1230,6 +1230,43 @@ static inline int nla_validate_nested(const struct nlattr *start, int maxtype, return nla_validate(nla_data(start), nla_len(start), maxtype, policy); } +/** + * nla_align_64bit - 64-bit align the nla_data() of next attribute + * @skb: socket buffer the message is stored in + * @padattr: attribute type for the padding + * + * Conditionally emit a padding netlink attribute in order to make + * the next attribute we emit have a 64-bit aligned nla_data() area. + * This will only be done in architectures which do not have + * HAVE_EFFICIENT_UNALIGNED_ACCESS defined. + * + * Returns zero on success or a negative error code. + */ +static inline int nla_align_64bit(struct sk_buff *skb, int padattr) +{ +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS + if (IS_ALIGNED((unsigned long)skb->data, 8)) { + struct nlattr *attr = nla_reserve(skb, padattr, 0); + if (!attr) + return -EMSGSIZE; + } +#endif + return 0; +} + +/** + * nla_total_size_64bit - total length of attribute including padding + * @payload: length of payload + */ +static inline int nla_total_size_64bit(int payload) +{ + return NLA_ALIGN(nla_attr_size(payload)) +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS + + NLA_ALIGN(nla_attr_size(0)) +#endif + ; +} + /** * nla_for_each_attr - iterate over a stream of attributes * @pos: loop counter, set to current attribute diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 198ca2c99510..d3694a13c85a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -878,10 +878,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ + nla_total_size(sizeof(struct rtnl_link_ifmap)) + nla_total_size(sizeof(struct rtnl_link_stats)) -#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS - + nla_total_size(0) /* IFLA_PAD */ -#endif - + nla_total_size(sizeof(struct rtnl_link_stats64)) + + nla_total_size_64bit(sizeof(struct rtnl_link_stats64)) + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ + nla_total_size(4) /* IFLA_TXQLEN */ @@ -1054,22 +1051,11 @@ static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb, { struct rtnl_link_stats64 *sp; struct nlattr *attr; + int err; -#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS - /* IF necessary, add a zero length NOP attribute so that the - * nla_data() of the IFLA_STATS64 will be 64-bit aligned. - * - * The nlattr header is 4 bytes in size, that's why we test - * if the skb->data _is_ aligned. This NOP attribute, plus - * nlattr header for IFLA_STATS64, will make nla_data() 8-byte - * aligned. - */ - if (IS_ALIGNED((unsigned long)skb->data, 8)) { - attr = nla_reserve(skb, IFLA_PAD, 0); - if (!attr) - return -EMSGSIZE; - } -#endif + err = nla_align_64bit(skb, IFLA_PAD); + if (err) + return err; attr = nla_reserve(skb, IFLA_STATS64, sizeof(struct rtnl_link_stats64)); -- GitLab From a14b9e0512404ed7d4415b888dc9f1f9785a4fa3 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 5 Feb 2016 16:40:47 -0800 Subject: [PATCH 3572/9938] clkdev: Remove clk_register_clkdevs() Now that we've converted the only caller over to another clkdev API, remove this one. Reviewed-by: Andy Shevchenko Cc: Russell King Signed-off-by: Stephen Boyd --- drivers/clk/clkdev.c | 27 --------------------------- include/linux/clkdev.h | 1 - 2 files changed, 28 deletions(-) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index eb20b941154b..ae8e40a82d34 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -402,30 +402,3 @@ int clk_register_clkdev(struct clk *clk, const char *con_id, return cl ? 0 : -ENOMEM; } EXPORT_SYMBOL(clk_register_clkdev); - -/** - * clk_register_clkdevs - register a set of clk_lookup for a struct clk - * @clk: struct clk to associate with all clk_lookups - * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized - * @num: number of clk_lookup structures to register - * - * To make things easier for mass registration, we detect error clks - * from a previous clk_register() call, and return the error code for - * those. This is to permit this function to be called immediately - * after clk_register(). - */ -int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num) -{ - unsigned i; - - if (IS_ERR(clk)) - return PTR_ERR(clk); - - for (i = 0; i < num; i++, cl++) { - cl->clk_hw = __clk_get_hw(clk); - __clkdev_add(cl); - } - - return 0; -} -EXPORT_SYMBOL(clk_register_clkdevs); diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h index c2c04f7cbe8a..e6f8eb1d585f 100644 --- a/include/linux/clkdev.h +++ b/include/linux/clkdev.h @@ -45,7 +45,6 @@ void clkdev_add_table(struct clk_lookup *, size_t); int clk_add_alias(const char *, const char *, const char *, struct device *); int clk_register_clkdev(struct clk *, const char *, const char *); -int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t); #ifdef CONFIG_COMMON_CLK int __clk_get(struct clk *clk); -- GitLab From 4143804c4fdef40358c654d1fb2271a1a0f1fedf Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 5 Feb 2016 17:02:52 -0800 Subject: [PATCH 3573/9938] clk: Add {devm_}clk_hw_{register,unregister}() APIs We've largely split the clk consumer and provider APIs along struct clk and struct clk_hw, but clk_register() still returns a struct clk pointer for each struct clk_hw that's registered. Eventually we'd like to only allocate struct clks when there's a user, because struct clk is per-user now, so clk_register() needs to change. Let's add new APIs to register struct clk_hws, but this time we'll hide the struct clk from the caller by returning an int error code. Also add an unregistration API that takes the clk_hw structure that was passed to the registration API. This way provider drivers never have to deal with a struct clk pointer unless they're using the clk consumer APIs. Signed-off-by: Stephen Boyd --- Documentation/driver-model/devres.txt | 1 + drivers/clk/clk.c | 86 +++++++++++++++++++++++++++ include/linux/clk-provider.h | 6 ++ 3 files changed, 93 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 73b98dfbcea4..108d45553e1b 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer). CLOCK devm_clk_get() devm_clk_put() + devm_clk_hw_register() DMA dmam_alloc_coherent() diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb74dc1f7520..0ef919666827 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2536,6 +2536,22 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(clk_register); +/** + * clk_hw_register - register a clk_hw and return an error code + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * clk_hw_register is the primary interface for populating the clock tree with + * new clock nodes. It returns an integer equal to zero indicating success or + * less than zero indicating failure. Drivers must test for an error code after + * calling clk_hw_register(). + */ +int clk_hw_register(struct device *dev, struct clk_hw *hw) +{ + return PTR_ERR_OR_ZERO(clk_register(dev, hw)); +} +EXPORT_SYMBOL_GPL(clk_hw_register); + /* Free memory allocated for a clock. */ static void __clk_release(struct kref *ref) { @@ -2637,11 +2653,26 @@ void clk_unregister(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_unregister); +/** + * clk_hw_unregister - unregister a currently registered clk_hw + * @hw: hardware-specific clock data to unregister + */ +void clk_hw_unregister(struct clk_hw *hw) +{ + clk_unregister(hw->clk); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister); + static void devm_clk_release(struct device *dev, void *res) { clk_unregister(*(struct clk **)res); } +static void devm_clk_hw_release(struct device *dev, void *res) +{ + clk_hw_unregister(*(struct clk_hw **)res); +} + /** * devm_clk_register - resource managed clk_register() * @dev: device that is registering this clock @@ -2672,6 +2703,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(devm_clk_register); +/** + * devm_clk_hw_register - resource managed clk_hw_register() + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * Managed clk_hw_register(). Clocks returned from this function are + * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register() + * for more information. + */ +int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) +{ + struct clk_hw **hwp; + int ret; + + hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL); + if (!hwp) + return -ENOMEM; + + ret = clk_hw_register(dev, hw); + if (!ret) { + *hwp = hw; + devres_add(dev, hwp); + } else { + devres_free(hwp); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_clk_hw_register); + static int devm_clk_match(struct device *dev, void *res, void *data) { struct clk *c = res; @@ -2680,6 +2741,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data) return c == data; } +static int devm_clk_hw_match(struct device *dev, void *res, void *data) +{ + struct clk_hw *hw = res; + + if (WARN_ON(!hw)) + return 0; + return hw == data; +} + /** * devm_clk_unregister - resource managed clk_unregister() * @clk: clock to unregister @@ -2694,6 +2764,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk) } EXPORT_SYMBOL_GPL(devm_clk_unregister); +/** + * devm_clk_hw_unregister - resource managed clk_hw_unregister() + * @dev: device that is unregistering the hardware-specific clock data + * @hw: link to hardware-specific clock data + * + * Unregister a clk_hw registered with devm_clk_hw_register(). Normally + * this function will not need to be called and the resource management + * code will ensure that the resource is freed. + */ +void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) +{ + WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match, + hw)); +} +EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); + /* * clkdev helpers */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index da95258127aa..bc6c8de1fac1 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -655,9 +655,15 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name, struct clk *clk_register(struct device *dev, struct clk_hw *hw); struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw); +int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw); +int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw); + void clk_unregister(struct clk *clk); void devm_clk_unregister(struct device *dev, struct clk *clk); +void clk_hw_unregister(struct clk_hw *hw); +void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw); + /* helper functions */ const char *__clk_get_name(const struct clk *clk); const char *clk_hw_get_name(const struct clk_hw *hw); -- GitLab From 0861e5b8cf80038e91942f1005c8dfce79d18c38 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 5 Feb 2016 17:38:26 -0800 Subject: [PATCH 3574/9938] clk: Add clk_hw OF clk providers Now that we have a clk registration API that doesn't return struct clks, we need to have some way to hand out struct clks via the clk_get() APIs that doesn't involve associating struct clk pointers with an OF node. Currently we ask the OF provider to give us a struct clk pointer for some clkspec, turn that struct clk into a struct clk_hw and then allocate a new struct clk to return to the caller. Let's add a clk_hw based OF provider hook that returns a struct clk_hw directly, so that we skip the intermediate step of converting from struct clk to struct clk_hw. Eventually when we've converted all OF clk providers to struct clk_hw based APIs we can remove the struct clk based ones. It should also be noted that we change the onecell provider to have a flex array instead of a pointer for the array of clk_hw pointers. This allows providers to allocate one structure of the correct length in one step instead of two. Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 85 ++++++++++++++++++++++++++++++++++-- include/linux/clk-provider.h | 30 +++++++++++++ 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0ef919666827..e813b2aabc87 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2941,6 +2941,7 @@ struct of_clk_provider { struct device_node *node; struct clk *(*get)(struct of_phandle_args *clkspec, void *data); + struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data); void *data; }; @@ -2957,6 +2958,12 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, } EXPORT_SYMBOL_GPL(of_clk_src_simple_get); +struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data) +{ + return data; +} +EXPORT_SYMBOL_GPL(of_clk_hw_simple_get); + struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) { struct clk_onecell_data *clk_data = data; @@ -2971,6 +2978,21 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) } EXPORT_SYMBOL_GPL(of_clk_src_onecell_get); +struct clk_hw * +of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data) +{ + struct clk_hw_onecell_data *hw_data = data; + unsigned int idx = clkspec->args[0]; + + if (idx >= hw_data->num) { + pr_err("%s: invalid index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } + + return hw_data->hws[idx]; +} +EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get); + /** * of_clk_add_provider() - Register a clock provider for a node * @np: Device node pointer associated with clock provider @@ -3006,6 +3028,41 @@ int of_clk_add_provider(struct device_node *np, } EXPORT_SYMBOL_GPL(of_clk_add_provider); +/** + * of_clk_add_hw_provider() - Register a clock provider for a node + * @np: Device node pointer associated with clock provider + * @get: callback for decoding clk_hw + * @data: context pointer for @get callback. + */ +int of_clk_add_hw_provider(struct device_node *np, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + struct of_clk_provider *cp; + int ret; + + cp = kzalloc(sizeof(*cp), GFP_KERNEL); + if (!cp) + return -ENOMEM; + + cp->node = of_node_get(np); + cp->data = data; + cp->get_hw = get; + + mutex_lock(&of_clk_mutex); + list_add(&cp->link, &of_clk_providers); + mutex_unlock(&of_clk_mutex); + pr_debug("Added clk_hw provider from %s\n", np->full_name); + + ret = of_clk_set_defaults(np, true); + if (ret < 0) + of_clk_del_provider(np); + + return ret; +} +EXPORT_SYMBOL_GPL(of_clk_add_hw_provider); + /** * of_clk_del_provider() - Remove a previously registered clock provider * @np: Device node pointer associated with clock provider @@ -3027,11 +3084,32 @@ void of_clk_del_provider(struct device_node *np) } EXPORT_SYMBOL_GPL(of_clk_del_provider); +static struct clk_hw * +__of_clk_get_hw_from_provider(struct of_clk_provider *provider, + struct of_phandle_args *clkspec) +{ + struct clk *clk; + struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); + + if (provider->get_hw) { + hw = provider->get_hw(clkspec, provider->data); + } else if (provider->get) { + clk = provider->get(clkspec, provider->data); + if (!IS_ERR(clk)) + hw = __clk_get_hw(clk); + else + hw = ERR_CAST(clk); + } + + return hw; +} + struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, const char *dev_id, const char *con_id) { struct of_clk_provider *provider; struct clk *clk = ERR_PTR(-EPROBE_DEFER); + struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); if (!clkspec) return ERR_PTR(-EINVAL); @@ -3040,10 +3118,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, mutex_lock(&of_clk_mutex); list_for_each_entry(provider, &of_clk_providers, link) { if (provider->node == clkspec->np) - clk = provider->get(clkspec, provider->data); - if (!IS_ERR(clk)) { - clk = __clk_create_clk(__clk_get_hw(clk), dev_id, - con_id); + hw = __of_clk_get_hw_from_provider(provider, clkspec); + if (!IS_ERR(hw)) { + clk = __clk_create_clk(hw, dev_id, con_id); if (!IS_ERR(clk) && !__clk_get(clk)) { __clk_free_clk(clk); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index bc6c8de1fac1..bf8c8bb8c2cb 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -709,6 +709,11 @@ struct clk_onecell_data { unsigned int clk_num; }; +struct clk_hw_onecell_data { + size_t num; + struct clk_hw *hws[]; +}; + extern struct of_device_id __clk_of_table; #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn) @@ -718,10 +723,18 @@ int of_clk_add_provider(struct device_node *np, struct clk *(*clk_src_get)(struct of_phandle_args *args, void *data), void *data); +int of_clk_add_hw_provider(struct device_node *np, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data); void of_clk_del_provider(struct device_node *np); struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data); +struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, + void *data); struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); +struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec, + void *data); unsigned int of_clk_get_parent_count(struct device_node *np); int of_clk_parent_fill(struct device_node *np, const char **parents, unsigned int size); @@ -738,17 +751,34 @@ static inline int of_clk_add_provider(struct device_node *np, { return 0; } +static inline int of_clk_add_hw_provider(struct device_node *np, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + return 0; +} static inline void of_clk_del_provider(struct device_node *np) {} static inline struct clk *of_clk_src_simple_get( struct of_phandle_args *clkspec, void *data) { return ERR_PTR(-ENOENT); } +static inline struct clk_hw * +of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data) +{ + return ERR_PTR(-ENOENT); +} static inline struct clk *of_clk_src_onecell_get( struct of_phandle_args *clkspec, void *data) { return ERR_PTR(-ENOENT); } +static inline struct clk_hw * +of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data) +{ + return ERR_PTR(-ENOENT); +} static inline int of_clk_get_parent_count(struct device_node *np) { return 0; -- GitLab From 1bf2bf229b64540f91ac6fa3af37c81249037a0b Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 31 Mar 2016 16:34:37 -0600 Subject: [PATCH 3575/9938] PCI: Work around Intel Sunrise Point PCH incorrect ACS capability Intel Sunrise Point root ports implement ACS but use dwords for the capability and control registers, putting the control register at the wrong offset. Use quirks to enable and test ACS for these devices, which match the standard functions modulo the broken control register offset. Note that lspci assumes devices implement ACS per spec, so it shows invalid ACS data for these devices. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 78 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1f5c7898a246..ac47d6bc9946 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3969,6 +3969,55 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags) return acs_flags & ~flags ? 0 : 1; } +/* + * Sunrise Point PCH root ports implement ACS, but unfortunately as shown in + * the datasheet (Intel 100 Series Chipset Family PCH Datasheet, Vol. 2, + * 12.1.46, 12.1.47)[1] this chipset uses dwords for the ACS capability and + * control registers whereas the PCIe spec packs them into words (Rev 3.0, + * 7.16 ACS Extended Capability). The bit definitions are correct, but the + * control register is at offset 8 instead of 6 and we should probably use + * dword accesses to them. This applies to the following PCI Device IDs, as + * found in volume 1 of the datasheet[2]: + * + * 0xa110-0xa11f Sunrise Point-H PCI Express Root Port #{0-16} + * 0xa167-0xa16a Sunrise Point-H PCI Express Root Port #{17-20} + * + * N.B. This doesn't fix what lspci shows. + * + * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html + * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html + */ +static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) +{ + return pci_is_pcie(dev) && + pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT && + ((dev->device & ~0xf) == 0xa110 || + (dev->device >= 0xa167 && dev->device <= 0xa16a)); +} + +#define INTEL_SPT_ACS_CTRL (PCI_ACS_CAP + 4) + +static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u16 acs_flags) +{ + int pos; + u32 cap, ctrl; + + if (!pci_quirk_intel_spt_pch_acs_match(dev)) + return -ENOTTY; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return -ENOTTY; + + /* see pci_acs_flags_enabled() */ + pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap); + acs_flags &= (cap | PCI_ACS_EC); + + pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl); + + return acs_flags & ~ctrl ? 0 : 1; +} + static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags) { /* @@ -4057,6 +4106,7 @@ static const struct pci_dev_acs_enabled { { PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs }, /* Intel PCH root ports */ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs }, + { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_spt_pch_acs }, { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */ { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */ /* Cavium ThunderX */ @@ -4192,12 +4242,40 @@ static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev) return 0; } +static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev) +{ + int pos; + u32 cap, ctrl; + + if (!pci_quirk_intel_spt_pch_acs_match(dev)) + return -ENOTTY; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return -ENOTTY; + + pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap); + pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl); + + ctrl |= (cap & PCI_ACS_SV); + ctrl |= (cap & PCI_ACS_RR); + ctrl |= (cap & PCI_ACS_CR); + ctrl |= (cap & PCI_ACS_UF); + + pci_write_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, ctrl); + + dev_info(&dev->dev, "Intel SPT PCH root port ACS workaround enabled\n"); + + return 0; +} + static const struct pci_dev_enable_acs { u16 vendor; u16 device; int (*enable_acs)(struct pci_dev *dev); } pci_dev_enable_acs[] = { { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs }, + { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_spt_pch_acs }, { 0 } }; -- GitLab From e4f1b49bda6d6aa2e13730ff7eeccbe65a6271f1 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 8 Feb 2016 14:59:49 -0800 Subject: [PATCH 3576/9938] clkdev: Add clk_hw based registration APIs Now that we have a clk registration API that doesn't return struct clks, we need to have some way to hand out struct clks via the clk_get() APIs that doesn't involve associating struct clk pointers with a struct clk_lookup. Luckily, clkdev already operates on struct clk_hw pointers, except for the registration facing APIs where it converts struct clk pointers into struct clk_hw pointers almost immediately. Let's add clk_hw based registration APIs so that we can skip the conversion step and provide a way for clk provider drivers to operate exclusively on clk_hw structs. This way we clearly split the API between consumers and providers. Cc: Russell King Signed-off-by: Stephen Boyd --- drivers/clk/clkdev.c | 64 ++++++++++++++++++++++++++++++++++++++++++ include/linux/clkdev.h | 6 ++++ 2 files changed, 70 insertions(+) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index ae8e40a82d34..89cc700fbc37 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -301,6 +301,20 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) } EXPORT_SYMBOL(clkdev_alloc); +struct clk_lookup * +clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, ...) +{ + struct clk_lookup *cl; + va_list ap; + + va_start(ap, dev_fmt); + cl = vclkdev_alloc(hw, con_id, dev_fmt, ap); + va_end(ap); + + return cl; +} +EXPORT_SYMBOL(clkdev_hw_alloc); + /** * clkdev_create - allocate and add a clkdev lookup structure * @clk: struct clk to associate with all clk_lookups @@ -324,6 +338,29 @@ struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id, } EXPORT_SYMBOL_GPL(clkdev_create); +/** + * clkdev_hw_create - allocate and add a clkdev lookup structure + * @hw: struct clk_hw to associate with all clk_lookups + * @con_id: connection ID string on device + * @dev_fmt: format string describing device name + * + * Returns a clk_lookup structure, which can be later unregistered and + * freed. + */ +struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id, + const char *dev_fmt, ...) +{ + struct clk_lookup *cl; + va_list ap; + + va_start(ap, dev_fmt); + cl = vclkdev_create(hw, con_id, dev_fmt, ap); + va_end(ap); + + return cl; +} +EXPORT_SYMBOL_GPL(clkdev_hw_create); + int clk_add_alias(const char *alias, const char *alias_dev_name, const char *con_id, struct device *dev) { @@ -402,3 +439,30 @@ int clk_register_clkdev(struct clk *clk, const char *con_id, return cl ? 0 : -ENOMEM; } EXPORT_SYMBOL(clk_register_clkdev); + +/** + * clk_hw_register_clkdev - register one clock lookup for a struct clk_hw + * @hw: struct clk_hw to associate with all clk_lookups + * @con_id: connection ID string on device + * @dev_id: format string describing device name + * + * con_id or dev_id may be NULL as a wildcard, just as in the rest of + * clkdev. + */ +int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id, + const char *dev_id) +{ + struct clk_lookup *cl; + + /* + * Since dev_id can be NULL, and NULL is handled specially, we must + * pass it as either a NULL format string, or with "%s". + */ + if (dev_id) + cl = __clk_register_clkdev(hw, con_id, "%s", dev_id); + else + cl = __clk_register_clkdev(hw, con_id, NULL); + + return cl ? 0 : -ENOMEM; +} +EXPORT_SYMBOL(clk_hw_register_clkdev); diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h index e6f8eb1d585f..2eabc862abdb 100644 --- a/include/linux/clkdev.h +++ b/include/linux/clkdev.h @@ -15,6 +15,7 @@ #include struct clk; +struct clk_hw; struct device; struct clk_lookup { @@ -34,17 +35,22 @@ struct clk_lookup { struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) __printf(3, 4); +struct clk_lookup *clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, + const char *dev_fmt, ...) __printf(3, 4); void clkdev_add(struct clk_lookup *cl); void clkdev_drop(struct clk_lookup *cl); struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id, const char *dev_fmt, ...) __printf(3, 4); +struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id, + const char *dev_fmt, ...) __printf(3, 4); void clkdev_add_table(struct clk_lookup *, size_t); int clk_add_alias(const char *, const char *, const char *, struct device *); int clk_register_clkdev(struct clk *, const char *, const char *); +int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *); #ifdef CONFIG_COMMON_CLK int __clk_get(struct clk *clk); -- GitLab From eb7d264f3bf9ca7c093efb77bdde557c6c6e826f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 6 Feb 2016 23:26:37 -0800 Subject: [PATCH 3577/9938] clk: divider: Add hw based registration APIs Add registration APIs in the clk divider code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-divider.c | 91 ++++++++++++++++++++++++++++++++---- include/linux/clk-provider.h | 10 ++++ 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 00e035b51c69..a0f55bc1ad3d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -426,15 +426,16 @@ const struct clk_ops clk_divider_ro_ops = { }; EXPORT_SYMBOL_GPL(clk_divider_ro_ops); -static struct clk *_register_divider(struct device *dev, const char *name, +static struct clk_hw *_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { struct clk_divider *div; - struct clk *clk; + struct clk_hw *hw; struct clk_init_data init; + int ret; if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { if (width + shift > 16) { @@ -467,12 +468,14 @@ static struct clk *_register_divider(struct device *dev, const char *name, div->table = table; /* register the clock */ - clk = clk_register(dev, &div->hw); - - if (IS_ERR(clk)) + hw = &div->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(div); + hw = ERR_PTR(ret); + } - return clk; + return hw; } /** @@ -492,11 +495,38 @@ struct clk *clk_register_divider(struct device *dev, const char *name, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, spinlock_t *lock) { - return _register_divider(dev, name, parent_name, flags, reg, shift, + struct clk_hw *hw; + + hw = _register_divider(dev, name, parent_name, flags, reg, shift, width, clk_divider_flags, NULL, lock); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } EXPORT_SYMBOL_GPL(clk_register_divider); +/** + * clk_hw_register_divider - register a divider clock with the clock framework + * @dev: device registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @reg: register address to adjust divider + * @shift: number of bits to shift the bitfield + * @width: width of the bitfield + * @clk_divider_flags: divider-specific flags for this clock + * @lock: shared register lock for this clock + */ +struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, spinlock_t *lock) +{ + return _register_divider(dev, name, parent_name, flags, reg, shift, + width, clk_divider_flags, NULL, lock); +} +EXPORT_SYMBOL_GPL(clk_hw_register_divider); + /** * clk_register_divider_table - register a table based divider clock with * the clock framework @@ -517,11 +547,41 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, u8 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { - return _register_divider(dev, name, parent_name, flags, reg, shift, + struct clk_hw *hw; + + hw = _register_divider(dev, name, parent_name, flags, reg, shift, width, clk_divider_flags, table, lock); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } EXPORT_SYMBOL_GPL(clk_register_divider_table); +/** + * clk_hw_register_divider_table - register a table based divider clock with + * the clock framework + * @dev: device registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @reg: register address to adjust divider + * @shift: number of bits to shift the bitfield + * @width: width of the bitfield + * @clk_divider_flags: divider-specific flags for this clock + * @table: array of divider/value pairs ending with a div set to 0 + * @lock: shared register lock for this clock + */ +struct clk_hw *clk_hw_register_divider_table(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock) +{ + return _register_divider(dev, name, parent_name, flags, reg, shift, + width, clk_divider_flags, table, lock); +} +EXPORT_SYMBOL_GPL(clk_hw_register_divider_table); + void clk_unregister_divider(struct clk *clk) { struct clk_divider *div; @@ -537,3 +597,18 @@ void clk_unregister_divider(struct clk *clk) kfree(div); } EXPORT_SYMBOL_GPL(clk_unregister_divider); + +/** + * clk_hw_unregister_divider - unregister a clk divider + * @hw: hardware-specific clock data to unregister + */ +void clk_hw_unregister_divider(struct clk_hw *hw) +{ + struct clk_divider *div; + + div = to_clk_divider(hw); + + clk_hw_unregister(hw); + kfree(div); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister_divider); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index bf8c8bb8c2cb..8885d0350596 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -407,12 +407,22 @@ struct clk *clk_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, spinlock_t *lock); +struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, spinlock_t *lock); struct clk *clk_register_divider_table(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock); +struct clk_hw *clk_hw_register_divider_table(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock); void clk_unregister_divider(struct clk *clk); +void clk_hw_unregister_divider(struct clk_hw *hw); /** * struct clk_mux - multiplexer clock -- GitLab From e270d8cb13763f58107198e879cf396511ba2867 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 6 Feb 2016 23:54:45 -0800 Subject: [PATCH 3578/9938] clk: gate: Add hw based registration APIs Add registration APIs in the clk gate code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-gate.c | 43 ++++++++++++++++++++++++++++++------ include/linux/clk-provider.h | 5 +++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index d0d8ec8e1f1b..4e691e35483a 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -110,7 +110,7 @@ const struct clk_ops clk_gate_ops = { EXPORT_SYMBOL_GPL(clk_gate_ops); /** - * clk_register_gate - register a gate clock with the clock framework + * clk_hw_register_gate - register a gate clock with the clock framework * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of this clock's parent @@ -120,14 +120,15 @@ EXPORT_SYMBOL_GPL(clk_gate_ops); * @clk_gate_flags: gate-specific flags for this clock * @lock: shared register lock for this clock */ -struct clk *clk_register_gate(struct device *dev, const char *name, +struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock) { struct clk_gate *gate; - struct clk *clk; + struct clk_hw *hw; struct clk_init_data init; + int ret; if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { if (bit_idx > 15) { @@ -154,12 +155,29 @@ struct clk *clk_register_gate(struct device *dev, const char *name, gate->lock = lock; gate->hw.init = &init; - clk = clk_register(dev, &gate->hw); - - if (IS_ERR(clk)) + hw = &gate->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(gate); + hw = ERR_PTR(ret); + } - return clk; + return hw; +} +EXPORT_SYMBOL_GPL(clk_hw_register_gate); + +struct clk *clk_register_gate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock) +{ + struct clk_hw *hw; + + hw = clk_hw_register_gate(dev, name, parent_name, flags, reg, + bit_idx, clk_gate_flags, lock); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } EXPORT_SYMBOL_GPL(clk_register_gate); @@ -178,3 +196,14 @@ void clk_unregister_gate(struct clk *clk) kfree(gate); } EXPORT_SYMBOL_GPL(clk_unregister_gate); + +void clk_hw_unregister_gate(struct clk_hw *hw) +{ + struct clk_gate *gate; + + gate = to_clk_gate(hw); + + clk_hw_unregister(hw); + kfree(gate); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister_gate); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 8885d0350596..bf12050aadd5 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -326,7 +326,12 @@ struct clk *clk_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock); +struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock); void clk_unregister_gate(struct clk *clk); +void clk_hw_unregister_gate(struct clk_hw *hw); struct clk_div_table { unsigned int val; -- GitLab From 264b31719735eb1fcbed47cecdb20f517e804856 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 7 Feb 2016 00:05:48 -0800 Subject: [PATCH 3579/9938] clk: mux: Add hw based registration APIs Add registration APIs in the clk mux code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-mux.c | 57 ++++++++++++++++++++++++++++++++---- include/linux/clk-provider.h | 11 +++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 252188fd8bcd..16a3d5717f4e 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -113,16 +113,17 @@ const struct clk_ops clk_mux_ro_ops = { }; EXPORT_SYMBOL_GPL(clk_mux_ro_ops); -struct clk *clk_register_mux_table(struct device *dev, const char *name, +struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, u8 clk_mux_flags, u32 *table, spinlock_t *lock) { struct clk_mux *mux; - struct clk *clk; + struct clk_hw *hw; struct clk_init_data init; u8 width = 0; + int ret; if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { width = fls(mask) - ffs(mask) + 1; @@ -157,12 +158,31 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, mux->table = table; mux->hw.init = &init; - clk = clk_register(dev, &mux->hw); - - if (IS_ERR(clk)) + hw = &mux->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(mux); + hw = ERR_PTR(ret); + } - return clk; + return hw; +} +EXPORT_SYMBOL_GPL(clk_hw_register_mux_table); + +struct clk *clk_register_mux_table(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, + void __iomem *reg, u8 shift, u32 mask, + u8 clk_mux_flags, u32 *table, spinlock_t *lock) +{ + struct clk_hw *hw; + + hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents, + flags, reg, shift, mask, clk_mux_flags, + table, lock); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } EXPORT_SYMBOL_GPL(clk_register_mux_table); @@ -180,6 +200,20 @@ struct clk *clk_register_mux(struct device *dev, const char *name, } EXPORT_SYMBOL_GPL(clk_register_mux); +struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_mux_flags, spinlock_t *lock) +{ + u32 mask = BIT(width) - 1; + + return clk_hw_register_mux_table(dev, name, parent_names, num_parents, + flags, reg, shift, mask, clk_mux_flags, + NULL, lock); +} +EXPORT_SYMBOL_GPL(clk_hw_register_mux); + void clk_unregister_mux(struct clk *clk) { struct clk_mux *mux; @@ -195,3 +229,14 @@ void clk_unregister_mux(struct clk *clk) kfree(mux); } EXPORT_SYMBOL_GPL(clk_unregister_mux); + +void clk_hw_unregister_mux(struct clk_hw *hw) +{ + struct clk_mux *mux; + + mux = to_clk_mux(hw); + + clk_hw_unregister(hw); + kfree(mux); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister_mux); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index bf12050aadd5..d690d99b9c1c 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -478,14 +478,25 @@ struct clk *clk_register_mux(struct device *dev, const char *name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_mux_flags, spinlock_t *lock); +struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_mux_flags, spinlock_t *lock); struct clk *clk_register_mux_table(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, u8 clk_mux_flags, u32 *table, spinlock_t *lock); +struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, + void __iomem *reg, u8 shift, u32 mask, + u8 clk_mux_flags, u32 *table, spinlock_t *lock); void clk_unregister_mux(struct clk *clk); +void clk_hw_unregister_mux(struct clk_hw *hw); void of_fixed_factor_clk_setup(struct device_node *node); -- GitLab From 0759ac8a73dc2c8cc8ac697fbe5dbd8d67348d37 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 7 Feb 2016 00:11:06 -0800 Subject: [PATCH 3580/9938] clk: fixed-factor: Add hw based registration APIs Add registration APIs in the clk fixed-factor code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-factor.c | 42 ++++++++++++++++++++++++++++------ include/linux/clk-provider.h | 4 ++++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 053448e2453d..75cd6c792cb8 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -68,13 +68,14 @@ const struct clk_ops clk_fixed_factor_ops = { }; EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); -struct clk *clk_register_fixed_factor(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, +struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div) { struct clk_fixed_factor *fix; struct clk_init_data init; - struct clk *clk; + struct clk_hw *hw; + int ret; fix = kmalloc(sizeof(*fix), GFP_KERNEL); if (!fix) @@ -91,12 +92,28 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, init.parent_names = &parent_name; init.num_parents = 1; - clk = clk_register(dev, &fix->hw); - - if (IS_ERR(clk)) + hw = &fix->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(fix); + hw = ERR_PTR(ret); + } + + return hw; +} +EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor); + +struct clk *clk_register_fixed_factor(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned int mult, unsigned int div) +{ + struct clk_hw *hw; - return clk; + hw = clk_hw_register_fixed_factor(dev, name, parent_name, flags, mult, + div); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } EXPORT_SYMBOL_GPL(clk_register_fixed_factor); @@ -113,6 +130,17 @@ void clk_unregister_fixed_factor(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor); +void clk_hw_unregister_fixed_factor(struct clk_hw *hw) +{ + struct clk_fixed_factor *fix; + + fix = to_clk_fixed_factor(hw); + + clk_hw_unregister(hw); + kfree(fix); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor); + #ifdef CONFIG_OF /** * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index d690d99b9c1c..79ad1a8a6831 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -525,6 +525,10 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div); void clk_unregister_fixed_factor(struct clk *clk); +struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + unsigned int mult, unsigned int div); +void clk_hw_unregister_fixed_factor(struct clk_hw *hw); /** * struct clk_fractional_divider - adjustable fractional divider clock -- GitLab From 39b44cff4ad4af6d7abd9dd2acb288b005c26503 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 7 Feb 2016 00:15:09 -0800 Subject: [PATCH 3581/9938] clk: fractional-divider: Add hw based registration APIs Add registration APIs in the clk fractional divider code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-fractional-divider.c | 40 ++++++++++++++++++++++++---- include/linux/clk-provider.h | 5 ++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index 1abcd76b4993..aab904618eb6 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c @@ -116,14 +116,15 @@ const struct clk_ops clk_fractional_divider_ops = { }; EXPORT_SYMBOL_GPL(clk_fractional_divider_ops); -struct clk *clk_register_fractional_divider(struct device *dev, +struct clk_hw *clk_hw_register_fractional_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, u8 clk_divider_flags, spinlock_t *lock) { struct clk_fractional_divider *fd; struct clk_init_data init; - struct clk *clk; + struct clk_hw *hw; + int ret; fd = kzalloc(sizeof(*fd), GFP_KERNEL); if (!fd) @@ -146,10 +147,39 @@ struct clk *clk_register_fractional_divider(struct device *dev, fd->lock = lock; fd->hw.init = &init; - clk = clk_register(dev, &fd->hw); - if (IS_ERR(clk)) + hw = &fd->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(fd); + hw = ERR_PTR(ret); + } + + return hw; +} +EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider); - return clk; +struct clk *clk_register_fractional_divider(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, + u8 clk_divider_flags, spinlock_t *lock) +{ + struct clk_hw *hw; + + hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags, + reg, mshift, mwidth, nshift, nwidth, clk_divider_flags, + lock); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } EXPORT_SYMBOL_GPL(clk_register_fractional_divider); + +void clk_hw_unregister_fractional_divider(struct clk_hw *hw) +{ + struct clk_fractional_divider *fd; + + fd = to_clk_fd(hw); + + clk_hw_unregister(hw); + kfree(fd); +} diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 79ad1a8a6831..bcbaf6c95d52 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -563,6 +563,11 @@ struct clk *clk_register_fractional_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, u8 clk_divider_flags, spinlock_t *lock); +struct clk_hw *clk_hw_register_fractional_divider(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, + u8 clk_divider_flags, spinlock_t *lock); +void clk_hw_unregister_fractional_divider(struct clk_hw *hw); /** * struct clk_multiplier - adjustable multiplier clock -- GitLab From 49cb392d36397a296dcd51ec57cf83585a89a94a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 7 Feb 2016 00:20:31 -0800 Subject: [PATCH 3582/9938] clk: composite: Add hw based registration APIs Add registration APIs in the clk composite code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-composite.c | 45 ++++++++++++++++++++++++++---------- include/linux/clk-provider.h | 7 ++++++ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 1f903e1f86a2..463fadd5a68f 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -184,17 +184,18 @@ static void clk_composite_disable(struct clk_hw *hw) gate_ops->disable(gate_hw); } -struct clk *clk_register_composite(struct device *dev, const char *name, +struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name, const char * const *parent_names, int num_parents, struct clk_hw *mux_hw, const struct clk_ops *mux_ops, struct clk_hw *rate_hw, const struct clk_ops *rate_ops, struct clk_hw *gate_hw, const struct clk_ops *gate_ops, unsigned long flags) { - struct clk *clk; + struct clk_hw *hw; struct clk_init_data init; struct clk_composite *composite; struct clk_ops *clk_composite_ops; + int ret; composite = kzalloc(sizeof(*composite), GFP_KERNEL); if (!composite) @@ -204,12 +205,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name, init.flags = flags | CLK_IS_BASIC; init.parent_names = parent_names; init.num_parents = num_parents; + hw = &composite->hw; clk_composite_ops = &composite->ops; if (mux_hw && mux_ops) { if (!mux_ops->get_parent) { - clk = ERR_PTR(-EINVAL); + hw = ERR_PTR(-EINVAL); goto err; } @@ -224,7 +226,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, if (rate_hw && rate_ops) { if (!rate_ops->recalc_rate) { - clk = ERR_PTR(-EINVAL); + hw = ERR_PTR(-EINVAL); goto err; } clk_composite_ops->recalc_rate = clk_composite_recalc_rate; @@ -253,7 +255,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, if (gate_hw && gate_ops) { if (!gate_ops->is_enabled || !gate_ops->enable || !gate_ops->disable) { - clk = ERR_PTR(-EINVAL); + hw = ERR_PTR(-EINVAL); goto err; } @@ -267,22 +269,41 @@ struct clk *clk_register_composite(struct device *dev, const char *name, init.ops = clk_composite_ops; composite->hw.init = &init; - clk = clk_register(dev, &composite->hw); - if (IS_ERR(clk)) + ret = clk_hw_register(dev, hw); + if (ret) { + hw = ERR_PTR(ret); goto err; + } if (composite->mux_hw) - composite->mux_hw->clk = clk; + composite->mux_hw->clk = hw->clk; if (composite->rate_hw) - composite->rate_hw->clk = clk; + composite->rate_hw->clk = hw->clk; if (composite->gate_hw) - composite->gate_hw->clk = clk; + composite->gate_hw->clk = hw->clk; - return clk; + return hw; err: kfree(composite); - return clk; + return hw; +} + +struct clk *clk_register_composite(struct device *dev, const char *name, + const char * const *parent_names, int num_parents, + struct clk_hw *mux_hw, const struct clk_ops *mux_ops, + struct clk_hw *rate_hw, const struct clk_ops *rate_ops, + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, + unsigned long flags) +{ + struct clk_hw *hw; + + hw = clk_hw_register_composite(dev, name, parent_names, num_parents, + mux_hw, mux_ops, rate_hw, rate_ops, gate_hw, gate_ops, + flags); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index bcbaf6c95d52..456c3ced1ac9 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -638,6 +638,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name, struct clk_hw *rate_hw, const struct clk_ops *rate_ops, struct clk_hw *gate_hw, const struct clk_ops *gate_ops, unsigned long flags); +struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name, + const char * const *parent_names, int num_parents, + struct clk_hw *mux_hw, const struct clk_ops *mux_ops, + struct clk_hw *rate_hw, const struct clk_ops *rate_ops, + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, + unsigned long flags); +void clk_hw_unregister_composite(struct clk_hw *hw); /*** * struct clk_gpio_gate - gpio gated clock -- GitLab From b120743a64a3ec68b8c5310a6009094329b4a33b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 7 Feb 2016 00:27:55 -0800 Subject: [PATCH 3583/9938] clk: gpio: Add hw based registration APIs Add registration APIs in the clk gpio code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-gpio.c | 52 ++++++++++++++++++++++++++++-------- include/linux/clk-provider.h | 8 ++++++ 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 08f65acc5d57..86b245746a6b 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -94,13 +94,13 @@ const struct clk_ops clk_gpio_mux_ops = { }; EXPORT_SYMBOL_GPL(clk_gpio_mux_ops); -static struct clk *clk_register_gpio(struct device *dev, const char *name, +static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned gpio, bool active_low, unsigned long flags, const struct clk_ops *clk_gpio_ops) { struct clk_gpio *clk_gpio; - struct clk *clk; + struct clk_hw *hw; struct clk_init_data init = {}; unsigned long gpio_flags; int err; @@ -141,24 +141,26 @@ static struct clk *clk_register_gpio(struct device *dev, const char *name, clk_gpio->gpiod = gpio_to_desc(gpio); clk_gpio->hw.init = &init; + hw = &clk_gpio->hw; if (dev) - clk = devm_clk_register(dev, &clk_gpio->hw); + err = devm_clk_hw_register(dev, hw); else - clk = clk_register(NULL, &clk_gpio->hw); + err = clk_hw_register(NULL, hw); - if (!IS_ERR(clk)) - return clk; + if (!err) + return hw; if (!dev) { gpiod_put(clk_gpio->gpiod); kfree(clk_gpio); } - return clk; + return ERR_PTR(err); } /** - * clk_register_gpio_gate - register a gpio clock gate with the clock framework + * clk_hw_register_gpio_gate - register a gpio clock gate with the clock + * framework * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of this clock's parent @@ -166,7 +168,7 @@ static struct clk *clk_register_gpio(struct device *dev, const char *name, * @active_low: true if gpio should be set to 0 to enable clock * @flags: clock flags */ -struct clk *clk_register_gpio_gate(struct device *dev, const char *name, +struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, const char *parent_name, unsigned gpio, bool active_low, unsigned long flags) { @@ -175,10 +177,24 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name, (parent_name ? 1 : 0), gpio, active_low, flags, &clk_gpio_gate_ops); } +EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate); + +struct clk *clk_register_gpio_gate(struct device *dev, const char *name, + const char *parent_name, unsigned gpio, bool active_low, + unsigned long flags) +{ + struct clk_hw *hw; + + hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low, + flags); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; +} EXPORT_SYMBOL_GPL(clk_register_gpio_gate); /** - * clk_register_gpio_mux - register a gpio clock mux with the clock framework + * clk_hw_register_gpio_mux - register a gpio clock mux with the clock framework * @dev: device that is registering this clock * @name: name of this clock * @parent_names: names of this clock's parents @@ -187,7 +203,7 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate); * @active_low: true if gpio should be set to 0 to enable clock * @flags: clock flags */ -struct clk *clk_register_gpio_mux(struct device *dev, const char *name, +struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned gpio, bool active_low, unsigned long flags) { @@ -199,6 +215,20 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name, return clk_register_gpio(dev, name, parent_names, num_parents, gpio, active_low, flags, &clk_gpio_mux_ops); } +EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux); + +struct clk *clk_register_gpio_mux(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, unsigned gpio, + bool active_low, unsigned long flags) +{ + struct clk_hw *hw; + + hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents, + gpio, active_low, flags); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; +} EXPORT_SYMBOL_GPL(clk_register_gpio_mux); static int gpio_clk_driver_probe(struct platform_device *pdev) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 456c3ced1ac9..6c36c5e8ccbe 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -667,6 +667,10 @@ extern const struct clk_ops clk_gpio_gate_ops; struct clk *clk_register_gpio_gate(struct device *dev, const char *name, const char *parent_name, unsigned gpio, bool active_low, unsigned long flags); +struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, + const char *parent_name, unsigned gpio, bool active_low, + unsigned long flags); +void clk_hw_unregister_gpio_gate(struct clk_hw *hw); /** * struct clk_gpio_mux - gpio controlled clock multiplexer @@ -682,6 +686,10 @@ extern const struct clk_ops clk_gpio_mux_ops; struct clk *clk_register_gpio_mux(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned gpio, bool active_low, unsigned long flags); +struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, unsigned gpio, + bool active_low, unsigned long flags); +void clk_hw_unregister_gpio_mux(struct clk_hw *hw); /** * clk_register - allocate a new clock, register it and return an opaque cookie -- GitLab From 26ef56be9e0944a9b136169eb47140f309ce745b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 7 Feb 2016 00:34:13 -0800 Subject: [PATCH 3584/9938] clk: fixed-rate: Add hw based registration APIs Add registration APIs in the clk fixed-rate code to return struct clk_hw pointers instead of struct clk pointers. This way we hide the struct clk pointer from providers unless they need to use consumer facing APIs. Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-rate.c | 44 +++++++++++++++++++++++++++++------- include/linux/clk-provider.h | 7 ++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index cd9dc925b3f8..8e4453eb54e8 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -45,8 +45,8 @@ const struct clk_ops clk_fixed_rate_ops = { EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); /** - * clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the - * clock framework + * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with + * the clock framework * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of clock's parent @@ -54,13 +54,14 @@ EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); * @fixed_rate: non-adjustable clock rate * @fixed_accuracy: non-adjustable clock rate */ -struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, +struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate, unsigned long fixed_accuracy) { struct clk_fixed_rate *fixed; - struct clk *clk; + struct clk_hw *hw; struct clk_init_data init; + int ret; /* allocate fixed-rate clock */ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); @@ -79,22 +80,49 @@ struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, fixed->hw.init = &init; /* register the clock */ - clk = clk_register(dev, &fixed->hw); - if (IS_ERR(clk)) + hw = &fixed->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(fixed); + hw = ERR_PTR(ret); + } - return clk; + return hw; +} +EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate_with_accuracy); + +struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + unsigned long fixed_rate, unsigned long fixed_accuracy) +{ + struct clk_hw *hw; + + hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, + flags, fixed_rate, fixed_accuracy); + if (IS_ERR(hw)) + return ERR_CAST(hw); + return hw->clk; } EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy); /** - * clk_register_fixed_rate - register fixed-rate clock with the clock framework + * clk_hw_register_fixed_rate - register fixed-rate clock with the clock + * framework * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of clock's parent * @flags: framework-specific flags * @fixed_rate: non-adjustable clock rate */ +struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned long fixed_rate) +{ + return clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, + flags, fixed_rate, 0); +} +EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate); + struct clk *clk_register_fixed_rate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 6c36c5e8ccbe..c3fc042d517c 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -282,10 +282,17 @@ extern const struct clk_ops clk_fixed_rate_ops; struct clk *clk_register_fixed_rate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate); +struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned long fixed_rate); struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate, unsigned long fixed_accuracy); void clk_unregister_fixed_rate(struct clk *clk); +struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, + const char *name, const char *parent_name, unsigned long flags, + unsigned long fixed_rate, unsigned long fixed_accuracy); + void of_fixed_clk_setup(struct device_node *np); /** -- GitLab From 9c7fe83530a351845719acf1dda0587e8c743588 Mon Sep 17 00:00:00 2001 From: Daniel DeFreez Date: Tue, 19 Apr 2016 19:57:45 -0400 Subject: [PATCH 3585/9938] GFS2: Add calls to gfs2_holder_uninit in two error handlers This patch fixes two locations that do not call gfs2_holder_uninit if gfs2_glock_nq returns an error. Signed-off-by: Daniel DeFreez Signed-off-by: Bob Peterson --- fs/gfs2/aops.c | 3 ++- fs/gfs2/file.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index aa016e4b8bec..58dd0061134b 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -1063,7 +1063,7 @@ static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter, gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh); rv = gfs2_glock_nq(&gh); if (rv) - return rv; + goto out_uninit; rv = gfs2_ok_for_dio(ip, offset); if (rv != 1) goto out; /* dio not valid, fall back to buffered i/o */ @@ -1102,6 +1102,7 @@ static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter, offset, gfs2_get_block_direct, NULL, NULL, 0); out: gfs2_glock_dq(&gh); +out_uninit: gfs2_holder_uninit(&gh); return rv; } diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index fd9a10e4518d..f33fd92e5f49 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -160,7 +160,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); error = gfs2_glock_nq(&gh); if (error) - return error; + goto out_uninit; fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_diskflags); if (!S_ISDIR(inode->i_mode) && ip->i_diskflags & GFS2_DIF_JDATA) @@ -169,6 +169,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) error = -EFAULT; gfs2_glock_dq(&gh); +out_uninit: gfs2_holder_uninit(&gh); return error; } -- GitLab From 607ea7cda6315be0ad8be2f98bc9de6f2d656ae6 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Mon, 18 Apr 2016 14:41:10 +0300 Subject: [PATCH 3586/9938] net/ipv6/addrconf: simplify sysctl registration Struct ctl_table_header holds pointer to sysctl table which could be used for freeing it after unregistration. IPv4 sysctls already use that. Remove redundant NULL assignment: ndev allocated using kzalloc. This also saves some bytes: sysctl table could be shorter than DEVCONF_MAX+1 if some options are disable in config. Signed-off-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- include/linux/ipv6.h | 3 ++- net/ipv6/addrconf.c | 43 +++++++++++++++++-------------------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 7edc14fb66b6..58d6e158755f 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -63,7 +63,8 @@ struct ipv6_devconf { } stable_secret; __s32 use_oif_addrs_only; __s32 keep_addr_on_down; - void *sysctl; + + struct ctl_table_header *sysctl_header; }; struct ipv6_params { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a6c99275bd8c..5a42c0fe0449 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -359,7 +359,6 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64; ndev->cnf.mtu6 = dev->mtu; - ndev->cnf.sysctl = NULL; ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); if (!ndev->nd_parms) { kfree(ndev); @@ -5620,13 +5619,7 @@ int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl, return ret; } -static struct addrconf_sysctl_table -{ - struct ctl_table_header *sysctl_header; - struct ctl_table addrconf_vars[DEVCONF_MAX+1]; -} addrconf_sysctl __read_mostly = { - .sysctl_header = NULL, - .addrconf_vars = { +static const struct ctl_table addrconf_sysctl[] = { { .procname = "forwarding", .data = &ipv6_devconf.forwarding, @@ -5944,52 +5937,50 @@ static struct addrconf_sysctl_table { /* sentinel */ } - }, }; static int __addrconf_sysctl_register(struct net *net, char *dev_name, struct inet6_dev *idev, struct ipv6_devconf *p) { int i; - struct addrconf_sysctl_table *t; + struct ctl_table *table; char path[sizeof("net/ipv6/conf/") + IFNAMSIZ]; - t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL); - if (!t) + table = kmemdup(addrconf_sysctl, sizeof(addrconf_sysctl), GFP_KERNEL); + if (!table) goto out; - for (i = 0; t->addrconf_vars[i].data; i++) { - t->addrconf_vars[i].data += (char *)p - (char *)&ipv6_devconf; - t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ - t->addrconf_vars[i].extra2 = net; + for (i = 0; table[i].data; i++) { + table[i].data += (char *)p - (char *)&ipv6_devconf; + table[i].extra1 = idev; /* embedded; no ref */ + table[i].extra2 = net; } snprintf(path, sizeof(path), "net/ipv6/conf/%s", dev_name); - t->sysctl_header = register_net_sysctl(net, path, t->addrconf_vars); - if (!t->sysctl_header) + p->sysctl_header = register_net_sysctl(net, path, table); + if (!p->sysctl_header) goto free; - p->sysctl = t; return 0; free: - kfree(t); + kfree(table); out: return -ENOBUFS; } static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) { - struct addrconf_sysctl_table *t; + struct ctl_table *table; - if (!p->sysctl) + if (!p->sysctl_header) return; - t = p->sysctl; - p->sysctl = NULL; - unregister_net_sysctl_table(t->sysctl_header); - kfree(t); + table = p->sysctl_header->ctl_table_arg; + unregister_net_sysctl_table(p->sysctl_header); + p->sysctl_header = NULL; + kfree(table); } static int addrconf_sysctl_register(struct inet6_dev *idev) -- GitLab From 5df1f77f65e11f2d7454de70998a68c42293397a Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Mon, 18 Apr 2016 14:41:17 +0300 Subject: [PATCH 3587/9938] net/ipv6/addrconf: fix sysctl table indentation Separated from previous patch for readability. Signed-off-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 616 ++++++++++++++++++++++---------------------- 1 file changed, 307 insertions(+), 309 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5a42c0fe0449..19258d97494c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -5620,323 +5620,321 @@ int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl, } static const struct ctl_table addrconf_sysctl[] = { - { - .procname = "forwarding", - .data = &ipv6_devconf.forwarding, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = addrconf_sysctl_forward, - }, - { - .procname = "hop_limit", - .data = &ipv6_devconf.hop_limit, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = addrconf_sysctl_hop_limit, - }, - { - .procname = "mtu", - .data = &ipv6_devconf.mtu6, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = addrconf_sysctl_mtu, - }, - { - .procname = "accept_ra", - .data = &ipv6_devconf.accept_ra, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "accept_redirects", - .data = &ipv6_devconf.accept_redirects, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "autoconf", - .data = &ipv6_devconf.autoconf, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "dad_transmits", - .data = &ipv6_devconf.dad_transmits, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "router_solicitations", - .data = &ipv6_devconf.rtr_solicits, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "router_solicitation_interval", - .data = &ipv6_devconf.rtr_solicit_interval, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_jiffies, - }, - { - .procname = "router_solicitation_delay", - .data = &ipv6_devconf.rtr_solicit_delay, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_jiffies, - }, - { - .procname = "force_mld_version", - .data = &ipv6_devconf.force_mld_version, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "mldv1_unsolicited_report_interval", - .data = - &ipv6_devconf.mldv1_unsolicited_report_interval, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_ms_jiffies, - }, - { - .procname = "mldv2_unsolicited_report_interval", - .data = - &ipv6_devconf.mldv2_unsolicited_report_interval, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_ms_jiffies, - }, - { - .procname = "use_tempaddr", - .data = &ipv6_devconf.use_tempaddr, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "temp_valid_lft", - .data = &ipv6_devconf.temp_valid_lft, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "temp_prefered_lft", - .data = &ipv6_devconf.temp_prefered_lft, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "regen_max_retry", - .data = &ipv6_devconf.regen_max_retry, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "max_desync_factor", - .data = &ipv6_devconf.max_desync_factor, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "max_addresses", - .data = &ipv6_devconf.max_addresses, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "accept_ra_defrtr", - .data = &ipv6_devconf.accept_ra_defrtr, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "accept_ra_min_hop_limit", - .data = &ipv6_devconf.accept_ra_min_hop_limit, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "accept_ra_pinfo", - .data = &ipv6_devconf.accept_ra_pinfo, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, + { + .procname = "forwarding", + .data = &ipv6_devconf.forwarding, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = addrconf_sysctl_forward, + }, + { + .procname = "hop_limit", + .data = &ipv6_devconf.hop_limit, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = addrconf_sysctl_hop_limit, + }, + { + .procname = "mtu", + .data = &ipv6_devconf.mtu6, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = addrconf_sysctl_mtu, + }, + { + .procname = "accept_ra", + .data = &ipv6_devconf.accept_ra, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "accept_redirects", + .data = &ipv6_devconf.accept_redirects, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "autoconf", + .data = &ipv6_devconf.autoconf, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "dad_transmits", + .data = &ipv6_devconf.dad_transmits, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "router_solicitations", + .data = &ipv6_devconf.rtr_solicits, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "router_solicitation_interval", + .data = &ipv6_devconf.rtr_solicit_interval, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "router_solicitation_delay", + .data = &ipv6_devconf.rtr_solicit_delay, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "force_mld_version", + .data = &ipv6_devconf.force_mld_version, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "mldv1_unsolicited_report_interval", + .data = + &ipv6_devconf.mldv1_unsolicited_report_interval, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_ms_jiffies, + }, + { + .procname = "mldv2_unsolicited_report_interval", + .data = + &ipv6_devconf.mldv2_unsolicited_report_interval, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_ms_jiffies, + }, + { + .procname = "use_tempaddr", + .data = &ipv6_devconf.use_tempaddr, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "temp_valid_lft", + .data = &ipv6_devconf.temp_valid_lft, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "temp_prefered_lft", + .data = &ipv6_devconf.temp_prefered_lft, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "regen_max_retry", + .data = &ipv6_devconf.regen_max_retry, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "max_desync_factor", + .data = &ipv6_devconf.max_desync_factor, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "max_addresses", + .data = &ipv6_devconf.max_addresses, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "accept_ra_defrtr", + .data = &ipv6_devconf.accept_ra_defrtr, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "accept_ra_min_hop_limit", + .data = &ipv6_devconf.accept_ra_min_hop_limit, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "accept_ra_pinfo", + .data = &ipv6_devconf.accept_ra_pinfo, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #ifdef CONFIG_IPV6_ROUTER_PREF - { - .procname = "accept_ra_rtr_pref", - .data = &ipv6_devconf.accept_ra_rtr_pref, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "router_probe_interval", - .data = &ipv6_devconf.rtr_probe_interval, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_jiffies, - }, + { + .procname = "accept_ra_rtr_pref", + .data = &ipv6_devconf.accept_ra_rtr_pref, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "router_probe_interval", + .data = &ipv6_devconf.rtr_probe_interval, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, #ifdef CONFIG_IPV6_ROUTE_INFO - { - .procname = "accept_ra_rt_info_max_plen", - .data = &ipv6_devconf.accept_ra_rt_info_max_plen, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, + { + .procname = "accept_ra_rt_info_max_plen", + .data = &ipv6_devconf.accept_ra_rt_info_max_plen, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #endif #endif - { - .procname = "proxy_ndp", - .data = &ipv6_devconf.proxy_ndp, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = addrconf_sysctl_proxy_ndp, - }, - { - .procname = "accept_source_route", - .data = &ipv6_devconf.accept_source_route, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, + { + .procname = "proxy_ndp", + .data = &ipv6_devconf.proxy_ndp, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = addrconf_sysctl_proxy_ndp, + }, + { + .procname = "accept_source_route", + .data = &ipv6_devconf.accept_source_route, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #ifdef CONFIG_IPV6_OPTIMISTIC_DAD - { - .procname = "optimistic_dad", - .data = &ipv6_devconf.optimistic_dad, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - - }, - { - .procname = "use_optimistic", - .data = &ipv6_devconf.use_optimistic, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - - }, + { + .procname = "optimistic_dad", + .data = &ipv6_devconf.optimistic_dad, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "use_optimistic", + .data = &ipv6_devconf.use_optimistic, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #endif #ifdef CONFIG_IPV6_MROUTE - { - .procname = "mc_forwarding", - .data = &ipv6_devconf.mc_forwarding, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = proc_dointvec, - }, + { + .procname = "mc_forwarding", + .data = &ipv6_devconf.mc_forwarding, + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = proc_dointvec, + }, #endif - { - .procname = "disable_ipv6", - .data = &ipv6_devconf.disable_ipv6, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = addrconf_sysctl_disable, - }, - { - .procname = "accept_dad", - .data = &ipv6_devconf.accept_dad, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "force_tllao", - .data = &ipv6_devconf.force_tllao, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .procname = "ndisc_notify", - .data = &ipv6_devconf.ndisc_notify, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .procname = "suppress_frag_ndisc", - .data = &ipv6_devconf.suppress_frag_ndisc, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .procname = "accept_ra_from_local", - .data = &ipv6_devconf.accept_ra_from_local, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "accept_ra_mtu", - .data = &ipv6_devconf.accept_ra_mtu, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "stable_secret", - .data = &ipv6_devconf.stable_secret, - .maxlen = IPV6_MAX_STRLEN, - .mode = 0600, - .proc_handler = addrconf_sysctl_stable_secret, - }, - { - .procname = "use_oif_addrs_only", - .data = &ipv6_devconf.use_oif_addrs_only, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "ignore_routes_with_linkdown", - .data = &ipv6_devconf.ignore_routes_with_linkdown, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = addrconf_sysctl_ignore_routes_with_linkdown, - }, - { - .procname = "drop_unicast_in_l2_multicast", - .data = &ipv6_devconf.drop_unicast_in_l2_multicast, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "drop_unsolicited_na", - .data = &ipv6_devconf.drop_unsolicited_na, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { - .procname = "keep_addr_on_down", - .data = &ipv6_devconf.keep_addr_on_down, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - - }, - { - /* sentinel */ - } + { + .procname = "disable_ipv6", + .data = &ipv6_devconf.disable_ipv6, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = addrconf_sysctl_disable, + }, + { + .procname = "accept_dad", + .data = &ipv6_devconf.accept_dad, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "force_tllao", + .data = &ipv6_devconf.force_tllao, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .procname = "ndisc_notify", + .data = &ipv6_devconf.ndisc_notify, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .procname = "suppress_frag_ndisc", + .data = &ipv6_devconf.suppress_frag_ndisc, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .procname = "accept_ra_from_local", + .data = &ipv6_devconf.accept_ra_from_local, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "accept_ra_mtu", + .data = &ipv6_devconf.accept_ra_mtu, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "stable_secret", + .data = &ipv6_devconf.stable_secret, + .maxlen = IPV6_MAX_STRLEN, + .mode = 0600, + .proc_handler = addrconf_sysctl_stable_secret, + }, + { + .procname = "use_oif_addrs_only", + .data = &ipv6_devconf.use_oif_addrs_only, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "ignore_routes_with_linkdown", + .data = &ipv6_devconf.ignore_routes_with_linkdown, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = addrconf_sysctl_ignore_routes_with_linkdown, + }, + { + .procname = "drop_unicast_in_l2_multicast", + .data = &ipv6_devconf.drop_unicast_in_l2_multicast, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "drop_unsolicited_na", + .data = &ipv6_devconf.drop_unsolicited_na, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "keep_addr_on_down", + .data = &ipv6_devconf.keep_addr_on_down, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + + }, + { + /* sentinel */ + } }; static int __addrconf_sysctl_register(struct net *net, char *dev_name, -- GitLab From 553bc087caf052458dc9f92bc42710027740caa9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 18 Apr 2016 16:55:35 +0200 Subject: [PATCH 3588/9938] arcnet: com90xx: add __init attribute Add __init attribute on a function that is only called from other __init functions and that is not inlined, at least with gcc version 4.8.4 on an x86 machine with allyesconfig. Currently, the function is put in the .text.unlikely segment. Declaring it as __init will cause it to be put in the .init.text and to disappear after initialization. The result of objdump -x on the function before the change is as follows: 0000000000000000 l F .text.unlikely 00000000000000bf check_mirror And after the change it is as follows: 0000000000000000 l F .init.text 00000000000000ba check_mirror Done with the help of Coccinelle. The semantic patch checks for local static non-init functions that are called from an __init function and are not called from any other function. Signed-off-by: Julia Lawall Acked-by: Michael Grzeschik Signed-off-by: David S. Miller --- drivers/net/arcnet/com90xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 0d9b45ff1bb2..81f90c4703ae 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -433,7 +433,7 @@ static void __init com90xx_probe(void) kfree(iomem); } -static int check_mirror(unsigned long addr, size_t size) +static int __init check_mirror(unsigned long addr, size_t size) { void __iomem *p; int res = -1; -- GitLab From 1e33759c788c78f31d4d6f65bac647b23624734c Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 18 Apr 2016 21:01:23 +0200 Subject: [PATCH 3589/9938] bpf, trace: add BPF_F_CURRENT_CPU flag for bpf_perf_event_output Add a BPF_F_CURRENT_CPU flag to optimize the use-case where user space has per-CPU ring buffers and the eBPF program pushes the data into the current CPU's ring buffer which saves us an extra helper function call in eBPF. Also, make sure to properly reserve the remaining flags which are not used. Signed-off-by: Daniel Borkmann Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/uapi/linux/bpf.h | 4 ++++ kernel/trace/bpf_trace.c | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 70eda5aeb304..b7b0fb1292e7 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -347,6 +347,10 @@ enum bpf_func_id { #define BPF_F_ZERO_CSUM_TX (1ULL << 1) #define BPF_F_DONT_FRAGMENT (1ULL << 2) +/* BPF_FUNC_perf_event_output flags. */ +#define BPF_F_INDEX_MASK 0xffffffffULL +#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK + /* user accessible mirror of in-kernel sk_buff. * new fields can only be added to the end of this structure */ diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index f389629dade7..b3cc24cb4321 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -225,11 +225,12 @@ static const struct bpf_func_proto bpf_perf_event_read_proto = { .arg2_type = ARG_ANYTHING, }; -static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 index, u64 r4, u64 size) +static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 flags, u64 r4, u64 size) { struct pt_regs *regs = (struct pt_regs *) (long) r1; struct bpf_map *map = (struct bpf_map *) (long) r2; struct bpf_array *array = container_of(map, struct bpf_array, map); + u64 index = flags & BPF_F_INDEX_MASK; void *data = (void *) (long) r4; struct perf_sample_data sample_data; struct perf_event *event; @@ -239,6 +240,10 @@ static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 index, u64 r4, u64 size) .data = data, }; + if (unlikely(flags & ~(BPF_F_INDEX_MASK))) + return -EINVAL; + if (index == BPF_F_CURRENT_CPU) + index = raw_smp_processor_id(); if (unlikely(index >= array->map.max_entries)) return -E2BIG; -- GitLab From bd570ff970a54df653b48ed0cfb373f2ebed083d Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 18 Apr 2016 21:01:24 +0200 Subject: [PATCH 3590/9938] bpf: add event output helper for notifications/sampling/logging This patch adds a new helper for cls/act programs that can push events to user space applications. For networking, this can be f.e. for sampling, debugging, logging purposes or pushing of arbitrary wake-up events. The idea is similar to a43eec304259 ("bpf: introduce bpf_perf_event_output() helper") and 39111695b1b8 ("samples: bpf: add bpf_perf_event_output example"). The eBPF program utilizes a perf event array map that user space populates with fds from perf_event_open(), the eBPF program calls into the helper f.e. as skb_event_output(skb, &my_map, BPF_F_CURRENT_CPU, raw, sizeof(raw)) so that the raw data is pushed into the fd f.e. at the map index of the current CPU. User space can poll/mmap/etc on this and has a data channel for receiving events that can be post-processed. The nice thing is that since the eBPF program and user space application making use of it are tightly coupled, they can define their own arbitrary raw data format and what/when they want to push. While f.e. packet headers could be one part of the meta data that is being pushed, this is not a substitute for things like packet sockets as whole packet is not being pushed and push is only done in a single direction. Intention is more of a generically usable, efficient event pipe to applications. Workflow is that tc can pin the map and applications can attach themselves e.g. after cls/act setup to one or multiple map slots, demuxing is done by the eBPF program. Adding this facility is with minimal effort, it reuses the helper introduced in a43eec304259 ("bpf: introduce bpf_perf_event_output() helper") and we get its functionality for free by overloading its BPF_FUNC_ identifier for cls/act programs, ctx is currently unused, but will be made use of in future. Example will be added to iproute2's BPF example files. Signed-off-by: Daniel Borkmann Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/bpf.h | 2 ++ kernel/bpf/core.c | 7 +++++++ kernel/trace/bpf_trace.c | 27 +++++++++++++++++++++++++++ net/core/filter.c | 2 ++ 4 files changed, 38 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 5fb3c610fa96..f63afdc43bec 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -169,7 +169,9 @@ u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5); u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); void bpf_fd_array_map_clear(struct bpf_map *map); bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp); + const struct bpf_func_proto *bpf_get_trace_printk_proto(void); +const struct bpf_func_proto *bpf_get_event_output_proto(void); #ifdef CONFIG_BPF_SYSCALL DECLARE_PER_CPU(int, bpf_prog_active); diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index be0abf669ced..e4248fe79513 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -764,14 +764,21 @@ const struct bpf_func_proto bpf_map_delete_elem_proto __weak; const struct bpf_func_proto bpf_get_prandom_u32_proto __weak; const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak; const struct bpf_func_proto bpf_ktime_get_ns_proto __weak; + const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak; const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak; const struct bpf_func_proto bpf_get_current_comm_proto __weak; + const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void) { return NULL; } +const struct bpf_func_proto * __weak bpf_get_event_output_proto(void) +{ + return NULL; +} + /* Always built-in helper functions. */ const struct bpf_func_proto bpf_tail_call_proto = { .func = NULL, diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index b3cc24cb4321..780bcbe1d4de 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -277,6 +277,33 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = { .arg5_type = ARG_CONST_STACK_SIZE, }; +static DEFINE_PER_CPU(struct pt_regs, bpf_pt_regs); + +static u64 bpf_event_output(u64 r1, u64 r2, u64 flags, u64 r4, u64 size) +{ + struct pt_regs *regs = this_cpu_ptr(&bpf_pt_regs); + + perf_fetch_caller_regs(regs); + + return bpf_perf_event_output((long)regs, r2, flags, r4, size); +} + +static const struct bpf_func_proto bpf_event_output_proto = { + .func = bpf_event_output, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_CONST_MAP_PTR, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_PTR_TO_STACK, + .arg5_type = ARG_CONST_STACK_SIZE, +}; + +const struct bpf_func_proto *bpf_get_event_output_proto(void) +{ + return &bpf_event_output_proto; +} + static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id) { switch (func_id) { diff --git a/net/core/filter.c b/net/core/filter.c index 5d2ac2b9d1c4..218e5de8c402 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2039,6 +2039,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id) return &bpf_redirect_proto; case BPF_FUNC_get_route_realm: return &bpf_get_route_realm_proto; + case BPF_FUNC_perf_event_output: + return bpf_get_event_output_proto(); default: return sk_filter_func_proto(func_id); } -- GitLab From 46e7b8d8d53bcde075dca6da3a3816a663073499 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Mon, 18 Apr 2016 16:10:24 -0400 Subject: [PATCH 3591/9938] net: dsa: kill circular reference with slave priv The dsa_slave_priv structure does not need a pointer to its net_device. Kill it. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- net/dsa/dsa_priv.h | 5 ----- net/dsa/slave.c | 9 ++++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 1d1a54687e4a..dfa33779d49c 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -22,11 +22,6 @@ struct dsa_device_ops { }; struct dsa_slave_priv { - /* - * The linux network interface corresponding to this - * switch port. - */ - struct net_device *dev; struct sk_buff * (*xmit)(struct sk_buff *skb, struct net_device *dev); diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 2dae0d064359..3b6750f5e68b 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -673,10 +673,10 @@ static void dsa_slave_get_ethtool_stats(struct net_device *dev, struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; - data[0] = p->dev->stats.tx_packets; - data[1] = p->dev->stats.tx_bytes; - data[2] = p->dev->stats.rx_packets; - data[3] = p->dev->stats.rx_bytes; + data[0] = dev->stats.tx_packets; + data[1] = dev->stats.tx_bytes; + data[2] = dev->stats.rx_packets; + data[3] = dev->stats.rx_bytes; if (ds->drv->get_ethtool_stats != NULL) ds->drv->get_ethtool_stats(ds, p->port, data + 4); } @@ -1063,7 +1063,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, slave_dev->vlan_features = master->vlan_features; p = netdev_priv(slave_dev); - p->dev = slave_dev; p->parent = ds; p->port = port; -- GitLab From b3a15f6d55fb584dd4d8baac5d1b6a398720620c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 19 Apr 2016 13:24:14 -0700 Subject: [PATCH 3592/9938] drm/vc4: Kick out the simplefb framebuffer before we set up KMS. If we don't, then simplefb stays loaded on /dev/fb0 even though scanout isn't happening from simplefb's memory area any more, and you end up with no console. Signed-off-by: Eric Anholt Acked-by: Dave Airlie --- drivers/gpu/drm/vc4/vc4_drv.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index b7d2ff0e6e1f..109b10651959 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -153,6 +153,24 @@ static void vc4_match_add_drivers(struct device *dev, } } +static void vc4_kick_out_firmware_fb(void) +{ + struct apertures_struct *ap; + + ap = alloc_apertures(1); + if (!ap) + return; + + /* Since VC4 is a UMA device, the simplefb node may have been + * located anywhere in memory. + */ + ap->ranges[0].base = 0; + ap->ranges[0].size = ~0; + + remove_conflicting_framebuffers(ap, "vc4drmfb", false); + kfree(ap); +} + static int vc4_drm_bind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -186,6 +204,8 @@ static int vc4_drm_bind(struct device *dev) if (ret) goto gem_destroy; + vc4_kick_out_firmware_fb(); + ret = drm_dev_register(drm, 0); if (ret < 0) goto unbind_all; -- GitLab From 49ac67e0c39cd268371e63ce0662ecb59a164a20 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Mar 2015 14:36:16 -0800 Subject: [PATCH 3593/9938] ARM: bcm2835: Add VC4 to the device tree. VC4 is the GPU (display and 3D) present on the 283x. Signed-off-by: Eric Anholt Acked-by: Stephen Warren --- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 4 ++ arch/arm/boot/dts/bcm2835-rpi-a.dts | 4 ++ arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 4 ++ arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 4 ++ arch/arm/boot/dts/bcm2835-rpi-b.dts | 4 ++ arch/arm/boot/dts/bcm2835-rpi.dtsi | 9 +++++ arch/arm/boot/dts/bcm2836-rpi-2-b.dts | 4 ++ arch/arm/boot/dts/bcm283x.dtsi | 47 ++++++++++++++++++++++++ 8 files changed, 80 insertions(+) diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts index 228614ffff44..35ff4e7a4aac 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts @@ -29,3 +29,7 @@ brcm,function = ; }; }; + +&hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts index ddbbbbd42dda..306a84ee9898 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-a.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts @@ -22,3 +22,7 @@ brcm,function = ; }; }; + +&hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts index ef5405025223..57d313b6afaf 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts @@ -29,3 +29,7 @@ brcm,function = ; }; }; + +&hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts index 86f1f2f598a7..cf2774ec0834 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts @@ -22,3 +22,7 @@ brcm,function = ; }; }; + +&hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts index 4859e9d81b23..8b15f9c35643 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts @@ -16,3 +16,7 @@ &gpio { pinctrl-0 = <&gpioout &alt0 &alt3>; }; + +&hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 76bdbcafab18..caf2707680c1 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -74,3 +74,12 @@ &usb { power-domains = <&power RPI_POWER_DOMAIN_USB>; }; + +&v3d { + power-domains = <&power RPI_POWER_DOMAIN_V3D>; +}; + +&hdmi { + power-domains = <&power RPI_POWER_DOMAIN_HDMI>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts index ff946661bd13..c4743f42237b 100644 --- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts +++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts @@ -33,3 +33,7 @@ brcm,function = ; }; }; + +&hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 8aaf193711bf..31cc2f2ef040 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -1,6 +1,7 @@ #include #include #include +#include #include "skeleton.dtsi" /* This include file covers the common peripherals and configuration between @@ -153,6 +154,18 @@ status = "disabled"; }; + pixelvalve@7e206000 { + compatible = "brcm,bcm2835-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <2 13>; /* pwa0 */ + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <2 14>; /* pwa1 */ + }; + aux: aux@0x7e215000 { compatible = "brcm,bcm2835-aux"; #clock-cells = <1>; @@ -206,6 +219,12 @@ status = "disabled"; }; + hvs@7e400000 { + compatible = "brcm,bcm2835-hvs"; + reg = <0x7e400000 0x6000>; + interrupts = <2 1>; + }; + i2c1: i2c@7e804000 { compatible = "brcm,bcm2835-i2c"; reg = <0x7e804000 0x1000>; @@ -226,11 +245,39 @@ status = "disabled"; }; + pixelvalve@7e807000 { + compatible = "brcm,bcm2835-pixelvalve2"; + reg = <0x7e807000 0x100>; + interrupts = <2 10>; /* pixelvalve */ + }; + + hdmi: hdmi@7e902000 { + compatible = "brcm,bcm2835-hdmi"; + reg = <0x7e902000 0x600>, + <0x7e808000 0x100>; + interrupts = <2 8>, <2 9>; + ddc = <&i2c2>; + clocks = <&clocks BCM2835_PLLH_PIX>, + <&clocks BCM2835_CLOCK_HSM>; + clock-names = "pixel", "hdmi"; + status = "disabled"; + }; + usb: usb@7e980000 { compatible = "brcm,bcm2835-usb"; reg = <0x7e980000 0x10000>; interrupts = <1 9>; }; + + v3d: v3d@7ec00000 { + compatible = "brcm,bcm2835-v3d"; + reg = <0x7ec00000 0x1000>; + interrupts = <1 10>; + }; + + vc4: gpu { + compatible = "brcm,bcm2835-vc4"; + }; }; clocks { -- GitLab From 1b2f8973c3bda7a100a8f3e1b4bc1c8ea9bf92d8 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Thu, 31 Mar 2016 17:25:17 +0000 Subject: [PATCH 3594/9938] ARM: bcm2835: add CPU node for ARM core This patch adds the CPU node of the BCM2835 into the DT. Signed-off-by: Stefan Wahren Acked-by: Mark Rutland Acked-by: Stephen Warren Reviewed-by: Eric Anholt --- arch/arm/boot/dts/bcm2835.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index b83b32639358..a78759e73710 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -3,6 +3,17 @@ / { compatible = "brcm,bcm2835"; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,arm1176jzf-s"; + reg = <0x0>; + }; + }; + soc { ranges = <0x7e000000 0x20000000 0x02000000>; dma-ranges = <0x40000000 0x00000000 0x20000000>; -- GitLab From 896ad420db8d5ec4cc4727b786d15e28eb59b366 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sat, 5 Mar 2016 18:02:49 +0000 Subject: [PATCH 3595/9938] dt/bindings: bcm2835: correct description for DMA-int Interrupt DMA11 is the shared interrupt for DMA channels 11 to 14 Interrupt DMA12 is the shared interrupt triggering for any DMA channel (this also includes DMA channel 15) Signed-off-by: Martin Sperl Reviewed-by: Eric Anholt Acked-by: Rob Herring --- .../bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt index 2d6c8bb4d827..6428a6ba9f4a 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt @@ -71,8 +71,8 @@ Bank 1: 24: DMA8 25: DMA9 26: DMA10 -27: DMA11 -28: DMA12 +27: DMA11-14 - shared interrupt for DMA 11 to 14 +28: DMAALL - triggers on all dma interrupts (including chanel 15) 29: AUX 30: ARM 31: VPUDMA -- GitLab From 4d1821e729b5d2060ef8c9825af1dacc2182da38 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Mar 2016 00:30:55 +0100 Subject: [PATCH 3596/9938] PCI: imx6: Factor out ref clock enable Factor out ref clock enable to make it cleaner to add imx6sx support. No functional change intended. Signed-off-by: Bjorn Helgaas Tested-by: Christoph Fritz --- drivers/pci/host/pci-imx6.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 2f817fa4c661..4357f4d90d0c 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -269,6 +269,23 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp) return 0; } +static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) +{ + /* power up core phy and enable ref clock */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, + IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18); + /* + * the async reset input need ref clock to sync internally, + * when the ref clock comes after reset, internal synced + * reset time is too short, cannot meet the requirement. + * add one ~10us delay here. + */ + udelay(10); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, + IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); + return 0; +} + static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) { struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); @@ -292,18 +309,11 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) goto err_pcie; } - /* power up core phy and enable ref clock */ - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18); - /* - * the async reset input need ref clock to sync internally, - * when the ref clock comes after reset, internal synced - * reset time is too short, cannot meet the requirement. - * add one ~10us delay here. - */ - udelay(10); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); + ret = imx6_pcie_enable_ref_clk(imx6_pcie); + if (ret) { + dev_err(pp->dev, "unable to enable pcie ref clock\n"); + goto err_ref_clk; + } /* allow the clocks to stabilize */ usleep_range(200, 500); @@ -316,6 +326,8 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) } return 0; +err_ref_clk: + clk_disable_unprepare(imx6_pcie->pcie); err_pcie: clk_disable_unprepare(imx6_pcie->pcie_bus); err_pcie_bus: -- GitLab From e3c06cd063d69df741295a50a691d4a2cad3852a Mon Sep 17 00:00:00 2001 From: Christoph Fritz Date: Tue, 5 Apr 2016 16:53:27 -0500 Subject: [PATCH 3597/9938] PCI: imx6: Add initial imx6sx support Add initial PCIe support for the imx6 SoC derivate imx6sx. PCI MSI support is untested as the necessary suspend/resume quirk is not included in this patch. This patch is heavily based on patches by Richard Zhu. [bhelgaas: factor out refclk enable, fix adjacent typos in imx6q-pcie.txt] Signed-off-by: Christoph Fritz Acked-by: Richard Zhu Acked-by: Lucas Stach --- .../bindings/pci/fsl,imx6q-pcie.txt | 8 ++- drivers/pci/host/pci-imx6.c | 53 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt index 3be80c68941a..0561e88f3b37 100644 --- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt +++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt @@ -4,8 +4,8 @@ This PCIe host controller is based on the Synopsis Designware PCIe IP and thus inherits all the common properties defined in designware-pcie.txt. Required properties: -- compatible: "fsl,imx6q-pcie" -- reg: base addresse and length of the pcie controller +- compatible: "fsl,imx6q-pcie", "fsl,imx6sx-pcie" +- reg: base address and length of the PCIe controller - interrupts: A list of interrupt outputs of the controller. Must contain an entry for each entry in the interrupt-names property. - interrupt-names: Must include the following entries: @@ -20,6 +20,10 @@ Optional properties: - fsl,tx-swing-full: Gen2 TX SWING FULL value. Default: 127 - fsl,tx-swing-low: TX launch amplitude swing_low value. Default: 127 +Additional required properties for imx6sx-pcie: +- clock names: Must include the following additional entries: + - "pcie_inbound_axi" + Example: pcie@0x01000000 { diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 4357f4d90d0c..7cfe00e34f58 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -35,9 +35,11 @@ struct imx6_pcie { int reset_gpio; struct clk *pcie_bus; struct clk *pcie_phy; + struct clk *pcie_inbound_axi; struct clk *pcie; struct pcie_port pp; struct regmap *iomuxc_gpr; + bool is_imx6sx; void __iomem *mem_base; u32 tx_deemph_gen1; u32 tx_deemph_gen2_3p5db; @@ -236,6 +238,17 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp) struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); u32 val, gpr1, gpr12; + if (imx6_pcie->is_imx6sx) { + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6SX_GPR12_PCIE_TEST_POWERDOWN, + IMX6SX_GPR12_PCIE_TEST_POWERDOWN); + /* Force PCIe PHY reset */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5, + IMX6SX_GPR5_PCIE_BTNRST_RESET, + IMX6SX_GPR5_PCIE_BTNRST_RESET); + return 0; + } + /* * If the bootloader already enabled the link we need some special * handling to get the core back into a state where it is safe to @@ -271,6 +284,21 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp) static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) { + struct pcie_port *pp = &imx6_pcie->pp; + int ret; + + if (imx6_pcie->is_imx6sx) { + ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi); + if (ret) { + dev_err(pp->dev, "unable to enable pcie_axi clock\n"); + return ret; + } + + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0); + return ret; + } + /* power up core phy and enable ref clock */ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18); @@ -324,6 +352,11 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) msleep(100); gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1); } + + if (imx6_pcie->is_imx6sx) + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5, + IMX6SX_GPR5_PCIE_BTNRST_RESET, 0); + return 0; err_ref_clk: @@ -341,6 +374,12 @@ static void imx6_pcie_init_phy(struct pcie_port *pp) { struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); + if (imx6_pcie->is_imx6sx) { + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6SX_GPR12_PCIE_RX_EQ_MASK, + IMX6SX_GPR12_PCIE_RX_EQ_2); + } + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); @@ -547,6 +586,9 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) pp = &imx6_pcie->pp; pp->dev = &pdev->dev; + imx6_pcie->is_imx6sx = of_device_is_compatible(pp->dev->of_node, + "fsl,imx6sx-pcie"); + /* Added for PCI abort handling */ hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, "imprecise external abort"); @@ -589,6 +631,16 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) return PTR_ERR(imx6_pcie->pcie); } + if (imx6_pcie->is_imx6sx) { + imx6_pcie->pcie_inbound_axi = devm_clk_get(&pdev->dev, + "pcie_inbound_axi"); + if (IS_ERR(imx6_pcie->pcie_inbound_axi)) { + dev_err(&pdev->dev, + "pcie_incbound_axi clock missing or invalid\n"); + return PTR_ERR(imx6_pcie->pcie_inbound_axi); + } + } + /* Grab GPR config register range */ imx6_pcie->iomuxc_gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); @@ -636,6 +688,7 @@ static void imx6_pcie_shutdown(struct platform_device *pdev) static const struct of_device_id imx6_pcie_of_match[] = { { .compatible = "fsl,imx6q-pcie", }, + { .compatible = "fsl,imx6sx-pcie", }, {}, }; MODULE_DEVICE_TABLE(of, imx6_pcie_of_match); -- GitLab From 4f6926e9fdf94208dc37da0cd17835328fa4dbba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Fri, 1 Apr 2016 14:41:47 +0200 Subject: [PATCH 3598/9938] ARM: dts: imx6: Fix PCIe reset GPIO polarity on Toradex Apalis Ixora MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding reset-gpio-active-high boolean DT binding property, which we need to make PCIe working on Apalis SoMs and not break old DTBs. While at it, I've fixed comment and GPIO polarity. On Apalis SoMs the GPIO1_IO28 used to PCIe reset is not connected directly to PERST# PCIe signal, but it's ORed with RESETBMCU coming off the PMIC, and thus is inverted, active-high. Signed-off-by: Petr Štetiar Signed-off-by: Bjorn Helgaas --- arch/arm/boot/dts/imx6q-apalis-ixora.dts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts b/arch/arm/boot/dts/imx6q-apalis-ixora.dts index 2cba82d0d859..4b533cb5c82e 100644 --- a/arch/arm/boot/dts/imx6q-apalis-ixora.dts +++ b/arch/arm/boot/dts/imx6q-apalis-ixora.dts @@ -174,8 +174,9 @@ }; &pcie { - /* active-low meaning opposite of regular PERST# active-low polarity */ - reset-gpio = <&gpio1 28 GPIO_ACTIVE_LOW>; + /* active-high meaning opposite of regular PERST# active-low polarity */ + reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>; + reset-gpio-active-high; status = "okay"; }; -- GitLab From 3ea8529acc30467331b7b1f5da6cf668fac091c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Tue, 19 Apr 2016 19:42:07 -0500 Subject: [PATCH 3599/9938] PCI: imx6: Add reset-gpio-active-high boolean property to DT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the reset-gpio DT property which controls the PCI bus device reset signal defaults to active-low reset sequence (L=reset state, H=operation state) plus the code in reset function isn't GPIO polarity aware - it doesn't matter if the defined reset-gpio is active-low or active-high, it will always result into active-low reset sequence. I've tried to fix it properly and change the reset-gpio reset sequence to be polarity-aware, but this patch has been accepted and then reverted as it has introduced few backward incompatible issues: 1. Some DTBs, for example, imx6qdl-sabresd, don't define reset-gpio polarity correctly: reset-gpio = <&gpio7 12 0>; which means that it's defined as active-high, but in reality it's active-low; thus it wouldn't work without a DTS fix. 2. The logic in the reset function is inverted: gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0) msleep(100); gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1); so even if some of the i.MX6 boards had reset-gpio polarity defined correctly in their DTSes, they would stop working. As we can't break old DTBs, we can't fix them, so we need to introduce this new DT reset-gpio-active-high boolean property so we can support boards with active-high reset sequence. This active-high reset sequence is for example needed on Apalis SoMs, where GPIO1_IO28, used to PCIe reset is not connected directly to PERST# PCIe signal, but it's ORed with RESETBMCU coming off the PMIC, and thus is inverted, active-high. Tested-by: Tim Harvey # Gateworks Ventana boards (which have active-low PERST#) Signed-off-by: Petr Štetiar Signed-off-by: Bjorn Helgaas Reviewed-by: Lucas Stach Acked-by: Rob Herring --- .../devicetree/bindings/pci/fsl,imx6q-pcie.txt | 6 ++++++ drivers/pci/host/pci-imx6.c | 14 +++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt index 0561e88f3b37..636707df0952 100644 --- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt +++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt @@ -19,6 +19,12 @@ Optional properties: - fsl,tx-deemph-gen2-6db: Gen2 (6db) De-emphasis value. Default: 20 - fsl,tx-swing-full: Gen2 TX SWING FULL value. Default: 127 - fsl,tx-swing-low: TX launch amplitude swing_low value. Default: 127 +- reset-gpio: Should specify the GPIO for controlling the PCI bus device reset + signal. It's not polarity aware and defaults to active-low reset sequence + (L=reset state, H=operation state). +- reset-gpio-active-high: If present then the reset sequence using the GPIO + specified in the "reset-gpio" property is reversed (H=reset state, + L=operation state). Additional required properties for imx6sx-pcie: - clock names: Must include the following additional entries: diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 7cfe00e34f58..0b8793d908de 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -33,6 +33,7 @@ struct imx6_pcie { int reset_gpio; + bool gpio_active_high; struct clk *pcie_bus; struct clk *pcie_phy; struct clk *pcie_inbound_axi; @@ -348,9 +349,11 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) /* Some boards don't have PCIe reset GPIO. */ if (gpio_is_valid(imx6_pcie->reset_gpio)) { - gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0); + gpio_set_value_cansleep(imx6_pcie->reset_gpio, + imx6_pcie->gpio_active_high); msleep(100); - gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1); + gpio_set_value_cansleep(imx6_pcie->reset_gpio, + !imx6_pcie->gpio_active_high); } if (imx6_pcie->is_imx6sx) @@ -600,9 +603,14 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) /* Fetch GPIOs */ imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); + imx6_pcie->gpio_active_high = of_property_read_bool(np, + "reset-gpio-active-high"); if (gpio_is_valid(imx6_pcie->reset_gpio)) { ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio, - GPIOF_OUT_INIT_LOW, "PCIe reset"); + imx6_pcie->gpio_active_high ? + GPIOF_OUT_INIT_HIGH : + GPIOF_OUT_INIT_LOW, + "PCIe reset"); if (ret) { dev_err(&pdev->dev, "unable to get reset gpio\n"); return ret; -- GitLab From a5fcec480f25eb5444c0b71ecdf9b18b09236b95 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Tue, 19 Apr 2016 19:52:44 -0500 Subject: [PATCH 3600/9938] PCI: imx6: Add DT property for link gen, default to Gen1 Freescale has stated [1] that the LVDS clock source of the IMX6 does not pass the PCI Gen2 clock jitter test, therefore unless an external Gen2 compliant external clock source is present and supplied back to the IMX6 PCIe core via LVDS CLK1/CLK2 you can not claim Gen2 compliance. Add a DT property to specify Gen1 vs Gen2 and check this before allowing a Gen2 link. We default to Gen1 if the property is not present because at this time there are no IMX6 boards in mainline that 'input' a clock on LVDS CLK1/CLK2. In order to be Gen2 compliant on IMX6 you need to: - Have a Gen2 compliant external clock generator and route that clock back to either LVDS CLK1 or LVDS CLK2 as an input (see IMX6SX-SabreSD reference design). - Specify this clock in the PCIe node in the DT (i.e., IMX6QDL_CLK_LVDS1_IN or IMX6QDL_CLK_LVDS2_IN instead of IMX6QDL_CLK_LVDS1_GATE which configures it as a CLK output). [1] https://community.freescale.com/message/453209 Signed-off-by: Tim Harvey Signed-off-by: Bjorn Helgaas Reviewed-by: Lucas Stach CC: Fabio Estevam CC: Zhu Richard CC: Akshay Bhat CC: Rob Herring CC: Shawn Guo --- .../bindings/pci/fsl,imx6q-pcie.txt | 4 ++++ drivers/pci/host/pci-imx6.c | 24 +++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt index 636707df0952..d742f917505a 100644 --- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt +++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt @@ -19,6 +19,10 @@ Optional properties: - fsl,tx-deemph-gen2-6db: Gen2 (6db) De-emphasis value. Default: 20 - fsl,tx-swing-full: Gen2 TX SWING FULL value. Default: 127 - fsl,tx-swing-low: TX launch amplitude swing_low value. Default: 127 +- fsl,max-link-speed: Specify PCI gen for link capability. Must be '2' for + gen2, otherwise will default to gen1. Note that the IMX6 LVDS clock outputs + do not meet gen2 jitter requirements and thus for gen2 capability a gen2 + compliant clock generator should be used and configured. - reset-gpio: Should specify the GPIO for controlling the PCI bus device reset signal. It's not polarity aware and defaults to active-low reset sequence (L=reset state, H=operation state). diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 0b8793d908de..837d5e0447ac 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -47,6 +47,7 @@ struct imx6_pcie { u32 tx_deemph_gen2_6db; u32 tx_swing_full; u32 tx_swing_low; + int link_gen; }; /* PCIe Root Complex registers (memory-mapped) */ @@ -471,11 +472,15 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) goto err_reset_phy; } - /* Allow Gen2 mode after the link is up. */ - tmp = readl(pp->dbi_base + PCIE_RC_LCR); - tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; - tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; - writel(tmp, pp->dbi_base + PCIE_RC_LCR); + if (imx6_pcie->link_gen == 2) { + /* Allow Gen2 mode after the link is up. */ + tmp = readl(pp->dbi_base + PCIE_RC_LCR); + tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; + tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; + writel(tmp, pp->dbi_base + PCIE_RC_LCR); + } else { + dev_info(pp->dev, "Link: Gen2 disabled\n"); + } /* * Start Directed Speed Change so the best possible speed both link @@ -499,8 +504,7 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) } tmp = readl(pp->dbi_base + PCIE_RC_LCSR); - dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); - + dev_info(pp->dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf); return 0; err_reset_phy: @@ -678,6 +682,12 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) &imx6_pcie->tx_swing_low)) imx6_pcie->tx_swing_low = 127; + /* Limit link speed */ + ret = of_property_read_u32(pp->dev->of_node, "fsl,max-link-speed", + &imx6_pcie->link_gen); + if (ret) + imx6_pcie->link_gen = 1; + ret = imx6_add_pcie_port(pp, pdev); if (ret < 0) return ret; -- GitLab From 660e1551939931657808d47838a3f443c0e83fd0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Mar 2016 16:13:32 +0200 Subject: [PATCH 3601/9938] clk: ti: dra7-atl-clock: Fix of_node reference counting of_find_node_by_name() will call of_node_put() on the node so we need to get it first to avoid warnings. The cfg_node needs to be put after we have finished processing the properties. Signed-off-by: Peter Ujfalusi Tested-by: Nishanth Menon Signed-off-by: Stephen Boyd --- drivers/clk/ti/clk-dra7-atl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index 2e14dfb588f4..c77333230bdf 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -265,6 +265,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) /* Get configuration for the ATL instances */ snprintf(prop, sizeof(prop), "atl%u", i); + of_node_get(node); cfg_node = of_find_node_by_name(node, prop); if (cfg_node) { ret = of_property_read_u32(cfg_node, "bws", @@ -278,6 +279,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i), cdesc->aws); } + of_node_put(cfg_node); } cdesc->probed = true; -- GitLab From 3432a2e39742ebbd8b01890a742bd45b219d5d8f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 18 Apr 2016 16:55:34 +0200 Subject: [PATCH 3602/9938] clk: qoriq: add __init attribute Add __init attribute on a function that is only called from other __init functions and that is not inlined, at least with gcc version 4.8.4 on an x86 machine with allyesconfig. Currently, the function is put in the .text.unlikely segment. Declaring it as __init will cause it to be put in the .init.text and to disappear after initialization. The result of objdump -x on the function before the change is as follows: 0000000000000000 l F .text.unlikely 0000000000000071 sysclk_from_fixed.constprop.5 And after the change it is as follows: 0000000000000480 l F .init.text 000000000000006c sysclk_from_fixed.constprop.5 Done with the help of Coccinelle. The semantic patch checks for local static non-init functions that are called from an __init function and are not called from any other function. Signed-off-by: Julia Lawall Signed-off-by: Stephen Boyd --- drivers/clk/clk-qoriq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index d247b75ddf6a..58566a17944a 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -869,7 +869,8 @@ static void __init core_mux_init(struct device_node *np) } } -static struct clk *sysclk_from_fixed(struct device_node *node, const char *name) +static struct clk __init +*sysclk_from_fixed(struct device_node *node, const char *name) { u32 rate; -- GitLab From 286259ef4b30bff092b223c530c7fa4dc5fd792d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 13 Apr 2016 13:05:02 -0700 Subject: [PATCH 3603/9938] clk: bcm2835: Fix compiler warnings on 64-bit builds Signed-off-by: Eric Anholt Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2835.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 4c0f1b504e2f..87616ded5bbe 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -400,17 +400,17 @@ struct bcm2835_pll_ana_bits { static const struct bcm2835_pll_ana_bits bcm2835_ana_default = { .mask0 = 0, .set0 = 0, - .mask1 = ~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK), + .mask1 = (u32)~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK), .set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT), - .mask3 = ~A2W_PLL_KA_MASK, + .mask3 = (u32)~A2W_PLL_KA_MASK, .set3 = (2 << A2W_PLL_KA_SHIFT), .fb_prediv_mask = BIT(14), }; static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = { - .mask0 = ~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK), + .mask0 = (u32)~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK), .set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT), - .mask1 = ~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK), + .mask1 = (u32)~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK), .set1 = (6 << A2W_PLLH_KP_SHIFT), .mask3 = 0, .set3 = 0, -- GitLab From e708b383f4b94feca2e0d5d06e1cfc13cdfea100 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 13 Apr 2016 13:05:03 -0700 Subject: [PATCH 3604/9938] clk: bcm2835: Fix PLL poweron In poweroff, we set the reset bit and the power down bit, but only managed to unset the reset bit for poweron. This meant that if HDMI did -EPROBE_DEFER after it had grabbed its clocks, we'd power down the PLLH (that had been on at boot time) and never recover. Signed-off-by: Eric Anholt Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") Cc: stable@vger.kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2835.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 87616ded5bbe..7a7970865c2d 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -554,6 +554,10 @@ static int bcm2835_pll_on(struct clk_hw *hw) const struct bcm2835_pll_data *data = pll->data; ktime_t timeout; + cprman_write(cprman, data->a2w_ctrl_reg, + cprman_read(cprman, data->a2w_ctrl_reg) & + ~A2W_PLL_CTRL_PWRDN); + /* Take the PLL out of reset. */ cprman_write(cprman, data->cm_ctrl_reg, cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST); -- GitLab From 39b9722315364121c6e2524515a6e95d52287549 Mon Sep 17 00:00:00 2001 From: Marco Angaroni Date: Tue, 5 Apr 2016 18:26:29 +0200 Subject: [PATCH 3605/9938] ipvs: handle connections started by real-servers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using LVS-NAT and SIP persistence-egine over UDP, the following limitations are present with current implementation: 1) To actually have load-balancing based on Call-ID header, you need to use one-packet-scheduling mode. But with one-packet-scheduling the connection is deleted just after packet is forwarded, so SIP responses coming from real-servers do not match any connection and SNAT is not applied. 2) If you do not use "-o" option, IPVS behaves as normal UDP load balancer, so different SIP calls (each one identified by a different Call-ID) coming from the same ip-address/port go to the same real-server. So basically you don’t have load-balancing based on Call-ID as intended. 3) Call-ID is not learned when a new SIP call is started by a real-server (inside-to-outside direction), but only in the outside-to-inside direction. This would be a general problem for all SIP servers acting as Back2BackUserAgent. This patch aims to solve problems 1) and 3) while keeping OPS mode mandatory for SIP-UDP, so that 2) is not a problem anymore. The basic mechanism implemented is to make packets, that do not match any existent connection but come from real-servers, create new connections instead of let them pass without any effect. When such packets pass through ip_vs_out(), if their source ip address and source port match a configured real-server, a new connection is automatically created in the same way as it would have happened if the packet had come from outside-to-inside direction. A new connection template is created too if the virtual-service is persistent and there is no matching connection template found. The new connection automatically created, if the service had "-o" option, is an OPS connection that lasts only the time to forward the packet, just like it happens on the ingress side. The main part of this mechanism is implemented inside a persistent-engine specific callback (at the moment only SIP persistent engine exists) and is triggered only for UDP packets, since connection oriented protocols, by using different set of ports (typically ephemeral ports) to open new outgoing connections, should not need this feature. The following requisites are needed for automatic connection creation; if any is missing the packet simply goes the same way as before. a) virtual-service is not fwmark based (this is because fwmark services do not store address and port of the virtual-service, required to build the connection data). b) virtual-service and real-servers must not have been configured with omitted port (this is again to have all data to create the connection). Signed-off-by: Marco Angaroni Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 17 ++++ net/netfilter/ipvs/ip_vs_core.c | 154 ++++++++++++++++++++++++++++++ net/netfilter/ipvs/ip_vs_ctl.c | 46 ++++++++- net/netfilter/ipvs/ip_vs_pe_sip.c | 15 +++ 4 files changed, 231 insertions(+), 1 deletion(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index a6cc576fd467..af4c10ebb241 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -731,6 +731,12 @@ struct ip_vs_pe { u32 (*hashkey_raw)(const struct ip_vs_conn_param *p, u32 initval, bool inverse); int (*show_pe_data)(const struct ip_vs_conn *cp, char *buf); + /* create connections for real-server outgoing packets */ + struct ip_vs_conn* (*conn_out)(struct ip_vs_service *svc, + struct ip_vs_dest *dest, + struct sk_buff *skb, + const struct ip_vs_iphdr *iph, + __be16 dport, __be16 cport); }; /* The application module object (a.k.a. app incarnation) */ @@ -874,6 +880,7 @@ struct netns_ipvs { /* Service counters */ atomic_t ftpsvc_counter; atomic_t nullsvc_counter; + atomic_t conn_out_counter; #ifdef CONFIG_SYSCTL /* 1/rate drop and drop-entry variables */ @@ -1147,6 +1154,12 @@ static inline int sysctl_cache_bypass(struct netns_ipvs *ipvs) */ const char *ip_vs_proto_name(unsigned int proto); void ip_vs_init_hash_table(struct list_head *table, int rows); +struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc, + struct ip_vs_dest *dest, + struct sk_buff *skb, + const struct ip_vs_iphdr *iph, + __be16 dport, + __be16 cport); #define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table((t), ARRAY_SIZE((t))) #define IP_VS_APP_TYPE_FTP 1 @@ -1378,6 +1391,10 @@ ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol bool ip_vs_has_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol, const union nf_inet_addr *daddr, __be16 dport); +struct ip_vs_dest * +ip_vs_find_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol, + const union nf_inet_addr *daddr, __be16 dport); + int ip_vs_use_count_inc(void); void ip_vs_use_count_dec(void); int ip_vs_register_nl_ioctl(void); diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index b9a4082afa3a..f3bac2e9a25a 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -68,6 +68,7 @@ EXPORT_SYMBOL(ip_vs_conn_put); #ifdef CONFIG_IP_VS_DEBUG EXPORT_SYMBOL(ip_vs_get_debug_level); #endif +EXPORT_SYMBOL(ip_vs_new_conn_out); static int ip_vs_net_id __read_mostly; /* netns cnt used for uniqueness */ @@ -1100,6 +1101,143 @@ static inline bool is_new_conn_expected(const struct ip_vs_conn *cp, } } +/* Generic function to create new connections for outgoing RS packets + * + * Pre-requisites for successful connection creation: + * 1) Virtual Service is NOT fwmark based: + * In fwmark-VS actual vaddr and vport are unknown to IPVS + * 2) Real Server and Virtual Service were NOT configured without port: + * This is to allow match of different VS to the same RS ip-addr + */ +struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc, + struct ip_vs_dest *dest, + struct sk_buff *skb, + const struct ip_vs_iphdr *iph, + __be16 dport, + __be16 cport) +{ + struct ip_vs_conn_param param; + struct ip_vs_conn *ct = NULL, *cp = NULL; + const union nf_inet_addr *vaddr, *daddr, *caddr; + union nf_inet_addr snet; + __be16 vport; + unsigned int flags; + + EnterFunction(12); + vaddr = &svc->addr; + vport = svc->port; + daddr = &iph->saddr; + caddr = &iph->daddr; + + /* check pre-requisites are satisfied */ + if (svc->fwmark) + return NULL; + if (!vport || !dport) + return NULL; + + /* for persistent service first create connection template */ + if (svc->flags & IP_VS_SVC_F_PERSISTENT) { + /* apply netmask the same way ingress-side does */ +#ifdef CONFIG_IP_VS_IPV6 + if (svc->af == AF_INET6) + ipv6_addr_prefix(&snet.in6, &caddr->in6, + (__force __u32)svc->netmask); + else +#endif + snet.ip = caddr->ip & svc->netmask; + /* fill params and create template if not existent */ + if (ip_vs_conn_fill_param_persist(svc, skb, iph->protocol, + &snet, 0, vaddr, + vport, ¶m) < 0) + return NULL; + ct = ip_vs_ct_in_get(¶m); + if (!ct) { + ct = ip_vs_conn_new(¶m, dest->af, daddr, dport, + IP_VS_CONN_F_TEMPLATE, dest, 0); + if (!ct) { + kfree(param.pe_data); + return NULL; + } + ct->timeout = svc->timeout; + } else { + kfree(param.pe_data); + } + } + + /* connection flags */ + flags = ((svc->flags & IP_VS_SVC_F_ONEPACKET) && + iph->protocol == IPPROTO_UDP) ? IP_VS_CONN_F_ONE_PACKET : 0; + /* create connection */ + ip_vs_conn_fill_param(svc->ipvs, svc->af, iph->protocol, + caddr, cport, vaddr, vport, ¶m); + cp = ip_vs_conn_new(¶m, dest->af, daddr, dport, flags, dest, 0); + if (!cp) { + if (ct) + ip_vs_conn_put(ct); + return NULL; + } + if (ct) { + ip_vs_control_add(cp, ct); + ip_vs_conn_put(ct); + } + ip_vs_conn_stats(cp, svc); + + /* return connection (will be used to handle outgoing packet) */ + IP_VS_DBG_BUF(6, "New connection RS-initiated:%c c:%s:%u v:%s:%u " + "d:%s:%u conn->flags:%X conn->refcnt:%d\n", + ip_vs_fwd_tag(cp), + IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport), + IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport), + IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport), + cp->flags, atomic_read(&cp->refcnt)); + LeaveFunction(12); + return cp; +} + +/* Handle outgoing packets which are considered requests initiated by + * real servers, so that subsequent responses from external client can be + * routed to the right real server. + * Used also for outgoing responses in OPS mode. + * + * Connection management is handled by persistent-engine specific callback. + */ +static struct ip_vs_conn *__ip_vs_rs_conn_out(unsigned int hooknum, + struct netns_ipvs *ipvs, + int af, struct sk_buff *skb, + const struct ip_vs_iphdr *iph) +{ + struct ip_vs_dest *dest; + struct ip_vs_conn *cp = NULL; + __be16 _ports[2], *pptr; + + if (hooknum == NF_INET_LOCAL_IN) + return NULL; + + pptr = frag_safe_skb_hp(skb, iph->len, + sizeof(_ports), _ports, iph); + if (!pptr) + return NULL; + + rcu_read_lock(); + dest = ip_vs_find_real_service(ipvs, af, iph->protocol, + &iph->saddr, pptr[0]); + if (dest) { + struct ip_vs_service *svc; + struct ip_vs_pe *pe; + + svc = rcu_dereference(dest->svc); + if (svc) { + pe = rcu_dereference(svc->pe); + if (pe && pe->conn_out) + cp = pe->conn_out(svc, dest, skb, iph, + pptr[0], pptr[1]); + } + } + rcu_read_unlock(); + + return cp; +} + /* Handle response packets: rewrite addresses and send away... */ static unsigned int @@ -1245,6 +1383,22 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in if (likely(cp)) return handle_response(af, skb, pd, cp, &iph, hooknum); + + /* Check for real-server-started requests */ + if (atomic_read(&ipvs->conn_out_counter)) { + /* Currently only for UDP: + * connection oriented protocols typically use + * ephemeral ports for outgoing connections, so + * related incoming responses would not match any VS + */ + if (pp->protocol == IPPROTO_UDP) { + cp = __ip_vs_rs_conn_out(hooknum, ipvs, af, skb, &iph); + if (likely(cp)) + return handle_response(af, skb, pd, cp, &iph, + hooknum); + } + } + if (sysctl_nat_icmp_send(ipvs) && (pp->protocol == IPPROTO_TCP || pp->protocol == IPPROTO_UDP || diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 404b2a4f4b5b..6794391c5a32 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -567,6 +567,36 @@ bool ip_vs_has_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol, return false; } +/* Find real service record by . + * In case of multiple records with the same , only + * the first found record is returned. + * + * To be called under RCU lock. + */ +struct ip_vs_dest *ip_vs_find_real_service(struct netns_ipvs *ipvs, int af, + __u16 protocol, + const union nf_inet_addr *daddr, + __be16 dport) +{ + unsigned int hash; + struct ip_vs_dest *dest; + + /* Check for "full" addressed entries */ + hash = ip_vs_rs_hashkey(af, daddr, dport); + + hlist_for_each_entry_rcu(dest, &ipvs->rs_table[hash], d_list) { + if (dest->port == dport && + dest->af == af && + ip_vs_addr_equal(af, &dest->addr, daddr) && + (dest->protocol == protocol || dest->vfwmark)) { + /* HIT */ + return dest; + } + } + + return NULL; +} + /* Lookup destination by {addr,port} in the given service * Called under RCU lock. */ @@ -1253,6 +1283,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, atomic_inc(&ipvs->ftpsvc_counter); else if (svc->port == 0) atomic_inc(&ipvs->nullsvc_counter); + if (svc->pe && svc->pe->conn_out) + atomic_inc(&ipvs->conn_out_counter); ip_vs_start_estimator(ipvs, &svc->stats); @@ -1293,6 +1325,7 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) struct ip_vs_scheduler *sched = NULL, *old_sched; struct ip_vs_pe *pe = NULL, *old_pe = NULL; int ret = 0; + bool new_pe_conn_out, old_pe_conn_out; /* * Lookup the scheduler, by 'u->sched_name' @@ -1355,8 +1388,16 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) svc->netmask = u->netmask; old_pe = rcu_dereference_protected(svc->pe, 1); - if (pe != old_pe) + if (pe != old_pe) { rcu_assign_pointer(svc->pe, pe); + /* check for optional methods in new pe */ + new_pe_conn_out = (pe && pe->conn_out) ? true : false; + old_pe_conn_out = (old_pe && old_pe->conn_out) ? true : false; + if (new_pe_conn_out && !old_pe_conn_out) + atomic_inc(&svc->ipvs->conn_out_counter); + if (old_pe_conn_out && !new_pe_conn_out) + atomic_dec(&svc->ipvs->conn_out_counter); + } out: ip_vs_scheduler_put(old_sched); @@ -1389,6 +1430,8 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup) /* Unbind persistence engine, keep svc->pe */ old_pe = rcu_dereference_protected(svc->pe, 1); + if (old_pe && old_pe->conn_out) + atomic_dec(&ipvs->conn_out_counter); ip_vs_pe_put(old_pe); /* @@ -3957,6 +4000,7 @@ int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs) (unsigned long) ipvs); atomic_set(&ipvs->ftpsvc_counter, 0); atomic_set(&ipvs->nullsvc_counter, 0); + atomic_set(&ipvs->conn_out_counter, 0); /* procfs stats */ ipvs->tot_stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c index 0a6eb5c0d9e9..d07ef9e31c12 100644 --- a/net/netfilter/ipvs/ip_vs_pe_sip.c +++ b/net/netfilter/ipvs/ip_vs_pe_sip.c @@ -143,6 +143,20 @@ static int ip_vs_sip_show_pe_data(const struct ip_vs_conn *cp, char *buf) return cp->pe_data_len; } +static struct ip_vs_conn * +ip_vs_sip_conn_out(struct ip_vs_service *svc, + struct ip_vs_dest *dest, + struct sk_buff *skb, + const struct ip_vs_iphdr *iph, + __be16 dport, + __be16 cport) +{ + if (likely(iph->protocol == IPPROTO_UDP)) + return ip_vs_new_conn_out(svc, dest, skb, iph, dport, cport); + /* currently no need to handle other than UDP */ + return NULL; +} + static struct ip_vs_pe ip_vs_sip_pe = { .name = "sip", @@ -153,6 +167,7 @@ static struct ip_vs_pe ip_vs_sip_pe = .ct_match = ip_vs_sip_ct_match, .hashkey_raw = ip_vs_sip_hashkey_raw, .show_pe_data = ip_vs_sip_show_pe_data, + .conn_out = ip_vs_sip_conn_out, }; static int __init ip_vs_sip_init(void) -- GitLab From 013b042465d3fefef84b4b87947747eda08277e2 Mon Sep 17 00:00:00 2001 From: Marco Angaroni Date: Tue, 5 Apr 2016 18:26:52 +0200 Subject: [PATCH 3606/9938] ipvs: optimize release of connections in OPS mode One-packet-scheduling is the most expensive mode in IPVS from performance point of view: for each packet to be processed a new connection data structure is created and, after packet is sent, deleted by starting a new timer set to expire immediately. SIP persistent-engine needs OPS mode to have Call-ID based load balancing, so OPS mode performance has negative impact in SIP protocol load balancing. This patch aims to improve performance of OPS mode by means of the following changes in the release mechanism of OPS connections: a) call expire callback ip_vs_conn_expire() directly instead of starting a timer programmed to fire immediately. b) avoid call_rcu() overhead inside expire callback, since OPS connection are not inserted in the hash-table and last just the time to process the packet, hence there is no concurrent access to such data structures. Signed-off-by: Marco Angaroni Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_conn.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 85ca189bdc3d..dd75d4120099 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -104,6 +104,7 @@ static inline void ct_write_unlock_bh(unsigned int key) spin_unlock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l); } +static void ip_vs_conn_expire(unsigned long data); /* * Returns hash value for IPVS connection entry @@ -453,10 +454,16 @@ ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af, } EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto); +static void __ip_vs_conn_put_notimer(struct ip_vs_conn *cp) +{ + __ip_vs_conn_put(cp); + ip_vs_conn_expire((unsigned long)cp); +} + /* * Put back the conn and restart its timer with its timeout */ -void ip_vs_conn_put(struct ip_vs_conn *cp) +static void __ip_vs_conn_put_timer(struct ip_vs_conn *cp) { unsigned long t = (cp->flags & IP_VS_CONN_F_ONE_PACKET) ? 0 : cp->timeout; @@ -465,6 +472,16 @@ void ip_vs_conn_put(struct ip_vs_conn *cp) __ip_vs_conn_put(cp); } +void ip_vs_conn_put(struct ip_vs_conn *cp) +{ + if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) && + (atomic_read(&cp->refcnt) == 1) && + !timer_pending(&cp->timer)) + /* expire connection immediately */ + __ip_vs_conn_put_notimer(cp); + else + __ip_vs_conn_put_timer(cp); +} /* * Fill a no_client_port connection with a client port number @@ -834,7 +851,10 @@ static void ip_vs_conn_expire(unsigned long data) ip_vs_unbind_dest(cp); if (cp->flags & IP_VS_CONN_F_NO_CPORT) atomic_dec(&ip_vs_conn_no_cport_cnt); - call_rcu(&cp->rcu_head, ip_vs_conn_rcu_free); + if (cp->flags & IP_VS_CONN_F_ONE_PACKET) + ip_vs_conn_rcu_free(&cp->rcu_head); + else + call_rcu(&cp->rcu_head, ip_vs_conn_rcu_free); atomic_dec(&ipvs->conn_count); return; } @@ -850,7 +870,7 @@ static void ip_vs_conn_expire(unsigned long data) if (ipvs->sync_state & IP_VS_STATE_MASTER) ip_vs_sync_conn(ipvs, cp, sysctl_sync_threshold(ipvs)); - ip_vs_conn_put(cp); + __ip_vs_conn_put_timer(cp); } /* Modify timer, so that it expires as soon as possible. -- GitLab From 8fb04d9fc70a67ccabf71dbabf92d7f6fca64a16 Mon Sep 17 00:00:00 2001 From: Marco Angaroni Date: Sat, 9 Apr 2016 14:14:23 +0200 Subject: [PATCH 3607/9938] ipvs: don't alter conntrack in OPS mode When using OPS mode in conjunction with SIP persistent-engine, packets originating from the same ip-address/port could be balanced to different real servers, and (to properly handle SIP responses) OPS connections are created in the in-out direction too, where ip_vs_update_conntrack() is called to modify the reply tuple. As a result, there can be collision of conntrack tuples, causing random packet drops, as explained below: conntrack1: orig=CIP->VIP, reply=RIP1->CIP conntrack2: orig=RIP2->CIP, reply=CIP->VIP Tuple CIP->VIP is both in orig of conntrack1 and reply of conntrack2. The collision triggers packet drop inside nf_conntrack processing. In addition, the current implementation deletes the conntrack object at every expire of an OPS connection (once every forwarded packet), to have it recreated from scratch at next packet traversing IPVS. Since in OPS mode, by definition, we don't expect any associated response, the choices implemented in this patch are: a) don't call nf_conntrack_alter_reply() for OPS connections inside ip_vs_update_conntrack(). b) don't delete the conntrack object at OPS connection expire. The result is that created conntrack objects for each tuple CIP->VIP, RIP-N->CIP, etc. are left in UNREPLIED state and not modified by IPVS OPS connection management. This eliminates packet drops and leaves a single conntrack object for each tuple packets are sent from. Signed-off-by: Marco Angaroni Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_conn.c | 3 ++- net/netfilter/ipvs/ip_vs_nfct.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index dd75d4120099..292365ffa4f0 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -836,7 +836,8 @@ static void ip_vs_conn_expire(unsigned long data) if (cp->control) ip_vs_control_del(cp); - if (cp->flags & IP_VS_CONN_F_NFCT) { + if ((cp->flags & IP_VS_CONN_F_NFCT) && + !(cp->flags & IP_VS_CONN_F_ONE_PACKET)) { /* Do not access conntracks during subsys cleanup * because nf_conntrack_find_get can not be used after * conntrack cleanup for the net. diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c index 30434fb133df..f04fd8df210b 100644 --- a/net/netfilter/ipvs/ip_vs_nfct.c +++ b/net/netfilter/ipvs/ip_vs_nfct.c @@ -93,6 +93,10 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin) if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) return; + /* Never alter conntrack for OPS conns (no reply is expected) */ + if (cp->flags & IP_VS_CONN_F_ONE_PACKET) + return; + /* Alter reply only in original direction */ if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) return; -- GitLab From bec6ba4cdf2ac918364836c54f7d6deaf280bcb8 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Thu, 19 Nov 2015 17:19:31 -0600 Subject: [PATCH 3608/9938] qcom: ipq4019: Add basic board/dts support for IPQ4019 SoC Add initial dts files and SoC support for IPQ4019 Signed-off-by: Varadarajan Narayanan Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 115 ++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 arch/arm/boot/dts/qcom-ipq4019.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi new file mode 100644 index 000000000000..fc738228c59a --- /dev/null +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "skeleton.dtsi" +#include + +/ { + model = "Qualcomm Technologies, Inc. IPQ4019"; + compatible = "qcom,ipq4019"; + interrupt-parent = <&intc>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x0>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x1>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x2>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x3>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + }; + }; + + clocks { + sleep_clk: sleep_clk { + compatible = "fixed-clock"; + clock-frequency = <32768>; + #clock-cells = <0>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "simple-bus"; + + intc: interrupt-controller@b000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x0b000000 0x1000>, + <0x0b002000 0x1000>; + }; + + gcc: clock-controller@1800000 { + compatible = "qcom,gcc-ipq4019"; + #clock-cells = <1>; + #reset-cells = <1>; + reg = <0x1800000 0x60000>; + }; + + tlmm: pinctrl@0x01000000 { + compatible = "qcom,ipq4019-pinctrl"; + reg = <0x01000000 0x300000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <0 208 0>; + }; + + serial@78af000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x78af000 0x200>; + interrupts = <0 107 0>; + status = "disabled"; + clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + }; + + serial@78b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x78b0000 0x200>; + interrupts = <0 108 0>; + status = "disabled"; + clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + }; + }; +}; -- GitLab From dbe9e6f6451929b5beb7e8ec6a8d4193e698636a Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Thu, 19 Nov 2015 17:19:32 -0600 Subject: [PATCH 3609/9938] dts: ipq4019: Add support for IPQ4019 DK01 board Initial board support dts files for DK01 board. Signed-off-by: Senthilkumar N L Signed-off-by: Varadarajan Narayanan Signed-off-by: Andy Gross --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts | 22 +++++++ arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 59 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts create mode 100644 arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..15ed1221b4d4 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -546,6 +546,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-apq8074-dragonboard.dtb \ qcom-apq8084-ifc6540.dtb \ qcom-apq8084-mtp.dtb \ + qcom-ipq4019-ap.dk01.1-c1.dtb \ qcom-ipq8064-ap148.dtb \ qcom-msm8660-surf.dtb \ qcom-msm8960-cdp.dtb \ diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts new file mode 100644 index 000000000000..0d92f1bc3a13 --- /dev/null +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019-ap.dk01.1.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1"; + +}; diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi new file mode 100644 index 000000000000..fe78f3f2c919 --- /dev/null +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi @@ -0,0 +1,59 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1"; + compatible = "qcom,ipq4019"; + + clocks { + xo: xo { + compatible = "fixed-clock"; + clock-frequency = <48000000>; + #clock-cells = <0>; + }; + }; + + soc { + + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 2 0xf08>, + <1 3 0xf08>, + <1 4 0xf08>, + <1 1 0xf08>; + clock-frequency = <48000000>; + }; + + pinctrl@0x01000000 { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + }; +}; -- GitLab From 595b30c716d57cd4b61054de338bf834fc7a351e Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Thu, 19 Nov 2015 18:29:48 -0600 Subject: [PATCH 3610/9938] qcom: ipq4019: add acc and saw nodes to bring up secondary cores This adds the required device tree nodes to bring up the secondary cores on the ipq4019 SoC. Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index fc738228c59a..e44f5b6a1c76 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -27,29 +27,45 @@ cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a7"; + enable-method = "qcom,kpss-acc-v1"; + qcom,acc = <&acc0>; + qcom,saw = <&saw0>; reg = <0x0>; clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a7"; + enable-method = "qcom,kpss-acc-v1"; + qcom,acc = <&acc1>; + qcom,saw = <&saw1>; reg = <0x1>; clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; }; cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a7"; + enable-method = "qcom,kpss-acc-v1"; + qcom,acc = <&acc2>; + qcom,saw = <&saw2>; reg = <0x2>; clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; }; cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a7"; + enable-method = "qcom,kpss-acc-v1"; + qcom,acc = <&acc3>; + qcom,saw = <&saw3>; reg = <0x3>; clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; }; }; @@ -92,6 +108,50 @@ interrupts = <0 208 0>; }; + acc0: clock-controller@b088000 { + compatible = "qcom,kpss-acc-v1"; + reg = <0x0b088000 0x1000>, <0xb008000 0x1000>; + }; + + acc1: clock-controller@b098000 { + compatible = "qcom,kpss-acc-v1"; + reg = <0x0b098000 0x1000>, <0xb008000 0x1000>; + }; + + acc2: clock-controller@b0a8000 { + compatible = "qcom,kpss-acc-v1"; + reg = <0x0b0a8000 0x1000>, <0xb008000 0x1000>; + }; + + acc3: clock-controller@b0b8000 { + compatible = "qcom,kpss-acc-v1"; + reg = <0x0b0b8000 0x1000>, <0xb008000 0x1000>; + }; + + saw0: regulator@b089000 { + compatible = "qcom,saw2"; + reg = <0x02089000 0x1000>, <0x0b009000 0x1000>; + regulator; + }; + + saw1: regulator@b099000 { + compatible = "qcom,saw2"; + reg = <0x0b099000 0x1000>, <0x0b009000 0x1000>; + regulator; + }; + + saw2: regulator@b0a9000 { + compatible = "qcom,saw2"; + reg = <0x0b0a9000 0x1000>, <0x0b009000 0x1000>; + regulator; + }; + + saw3: regulator@b0b9000 { + compatible = "qcom,saw2"; + reg = <0x0b0b9000 0x1000>, <0x0b009000 0x1000>; + regulator; + }; + serial@78af000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x78af000 0x200>; -- GitLab From 40057afdc2a02e488a3556dedd8383f86751d006 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:05 -0500 Subject: [PATCH 3611/9938] qcom: ipq4019: add watchdog node to ipq4019 SoC and DK01 device tree This will allow boards to enable watchdog support Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 4 ++++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi index fe78f3f2c919..223da1afd89a 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi @@ -55,5 +55,9 @@ pinctrl-names = "default"; status = "ok"; }; + + watchdog@b017000 { + status = "ok"; + }; }; }; diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index e44f5b6a1c76..00a5e9ef95ea 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -171,5 +171,13 @@ <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; }; + + watchdog@b017000 { + compatible = "qcom,kpss-standalone"; + reg = <0xb017000 0x40>; + clocks = <&sleep_clk>; + timeout-sec = <10>; + status = "disabled"; + }; }; }; -- GitLab From 8196dd5e5c4c3b623a23e25060588a7129f0574e Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:06 -0500 Subject: [PATCH 3612/9938] qcom: ipq4019: add support for reset via qcom,ps-hold This will allow these types of boards to be rebooted. Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index 00a5e9ef95ea..acb851d55a19 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -179,5 +179,10 @@ timeout-sec = <10>; status = "disabled"; }; + + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x4ab000 0x4>; + }; }; }; -- GitLab From 13ad4fd36a815f1f4fb96c7308ea104bafc6bdb9 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:07 -0500 Subject: [PATCH 3613/9938] qcom: ipq4019: add spi node to ipq4019 SoC and DK01 device tree This will allow boards to enable the SPI bus Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 37 +++++++++++++++++++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 18 +++++++++ 2 files changed, 55 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi index 223da1afd89a..21032a8c86f6 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi @@ -48,6 +48,43 @@ bias-disable; }; }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio54"; + }; + pinconf { + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + }; + + spi_0: spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; + + mx25l25635e@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "mx25l25635e"; + spi-max-frequency = <24000000>; + }; }; serial@78af000 { diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index acb851d55a19..99e64f4881bc 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -15,12 +15,18 @@ #include "skeleton.dtsi" #include +#include +#include / { model = "Qualcomm Technologies, Inc. IPQ4019"; compatible = "qcom,ipq4019"; interrupt-parent = <&intc>; + aliases { + spi0 = &spi_0; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -108,6 +114,18 @@ interrupts = <0 208 0>; }; + spi_0: spi@78b5000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x78b5000 0x600>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + acc0: clock-controller@b088000 { compatible = "qcom,kpss-acc-v1"; reg = <0x0b088000 0x1000>, <0xb008000 0x1000>; -- GitLab From e76b4284b520ba3b83d2f3df1451c0cbb897b85d Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:08 -0500 Subject: [PATCH 3614/9938] qcom: ipq4019: add i2c node to ipq4019 SoC and DK01 device tree This will allow boards to enable the I2C bus CC: Sricharan R Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index 99e64f4881bc..1937edfdcd75 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -25,6 +25,7 @@ aliases { spi0 = &spi_0; + i2c0 = &i2c_0; }; cpus { @@ -126,6 +127,18 @@ status = "disabled"; }; + i2c_0: i2c@78b7000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x78b7000 0x6000>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>, + <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; + clock-names = "iface", "core"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + acc0: clock-controller@b088000 { compatible = "qcom,kpss-acc-v1"; reg = <0x0b088000 0x1000>, <0xb008000 0x1000>; -- GitLab From 15689ec209b2bc9ef0a02a82fdafd6da87dc1021 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:10 -0500 Subject: [PATCH 3615/9938] qcom: ipq4019: add cpu operating points for cpufreq support This adds some operating points for cpu frequeny scaling Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index 1937edfdcd75..db48fd348370 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -40,6 +40,14 @@ reg = <0x0>; clocks = <&gcc GCC_APPS_CLK_SRC>; clock-frequency = <0>; + operating-points = < + /* kHz uV (fixed) */ + 48000 1100000 + 200000 1100000 + 500000 1100000 + 666000 1100000 + >; + clock-latency = <256000>; }; cpu@1 { -- GitLab From fd6fd38692171e12aff2ef3ae854de24b1c3a3df Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:11 -0500 Subject: [PATCH 3616/9938] qcom: ipq4019: add crypto nodes to ipq4019 SoC and DK01 device tree This adds the crypto nodes to the ipq4019 device tree, it also adds the BAM node used by crypto as well which the driver currently requires to operate properly The crypto driver itself depends on some other patches to qcom_bam_dma to function properly: https://lkml.org/lkml/2015/12/1/113 CC: Stanimir Varbanov Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 8 ++++++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 25 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi index 21032a8c86f6..2c347ad8faab 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi @@ -93,6 +93,14 @@ status = "ok"; }; + cryptobam: dma@8e04000 { + status = "ok"; + }; + + crypto@8e3a000 { + status = "ok"; + }; + watchdog@b017000 { status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index db48fd348370..3cd42c04421b 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -147,6 +147,31 @@ status = "disabled"; }; + + cryptobam: dma@8e04000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x08e04000 0x20000>; + interrupts = ; + clocks = <&gcc GCC_CRYPTO_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <1>; + qcom,controlled-remotely; + status = "disabled"; + }; + + crypto@8e3a000 { + compatible = "qcom,crypto-v5.1"; + reg = <0x08e3a000 0x6000>; + clocks = <&gcc GCC_CRYPTO_AHB_CLK>, + <&gcc GCC_CRYPTO_AXI_CLK>, + <&gcc GCC_CRYPTO_CLK>; + clock-names = "iface", "bus", "core"; + dmas = <&cryptobam 2>, <&cryptobam 3>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + acc0: clock-controller@b088000 { compatible = "qcom,kpss-acc-v1"; reg = <0x0b088000 0x1000>, <0xb008000 0x1000>; -- GitLab From 9ca595f08e021972e6113dacf06b247a71e09530 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:12 -0500 Subject: [PATCH 3617/9938] qcom: ipq4019: add DMA nodes to ipq4019 SoC and DK01 device tree This adds the blsp_dma node to the device tree and the required properties for using DMA with serial Signed-off-by: Matthew McClintock Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 4 ++++ arch/arm/boot/dts/qcom-ipq4019.dtsi | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi index 2c347ad8faab..b9457dd21a69 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi @@ -72,6 +72,10 @@ }; }; + blsp_dma: dma@7884000 { + status = "ok"; + }; + spi_0: spi@78b5000 { pinctrl-0 = <&spi_0_pins>; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index 3cd42c04421b..5c08d19066c2 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -123,6 +123,17 @@ interrupts = <0 208 0>; }; + blsp_dma: dma@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x23000>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + status = "disabled"; + }; + spi_0: spi@78b5000 { compatible = "qcom,spi-qup-v2.2.1"; reg = <0x78b5000 0x600>; @@ -224,6 +235,8 @@ clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; + dmas = <&blsp_dma 1>, <&blsp_dma 0>; + dma-names = "rx", "tx"; }; serial@78b0000 { @@ -234,6 +247,8 @@ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; + dmas = <&blsp_dma 3>, <&blsp_dma 2>; + dma-names = "rx", "tx"; }; watchdog@b017000 { -- GitLab From 973111981b2de97c22891f83b76981dc27b42202 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 18:32:37 -0700 Subject: [PATCH 3618/9938] ARM: dts: msm8974: Split efs in rfsa and rmtfs One part of the efs memory region is used specifically for sharing file system buffers between the apps and modem cpus (aka rmtfs), so better reflect this split. Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-msm8974.dtsi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index ef5330578431..8780246bd3c1 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -49,8 +49,13 @@ no-map; }; - efs@0fd600000 { - reg = <0x0fd60000 0x1a0000>; + rfsa@0fd60000 { + reg = <0x0fd60000 0x20000>; + no-map; + }; + + rmtfs@0fd80000 { + reg = <0x0fd80000 0x180000>; no-map; }; -- GitLab From 89af1c2d63b0e9785e11e17c1435825c56705052 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 18:32:38 -0700 Subject: [PATCH 3619/9938] ARM: dts: msm8974: Add node for second i2c from blsp1 Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-msm8974.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index 8780246bd3c1..d8078d350ede 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -445,6 +445,17 @@ interrupts = <0 208 0>; }; + i2c@f9924000 { + status = "disabled"; + compatible = "qcom,i2c-qup-v2.1.1"; + reg = <0xf9924000 0x1000>; + interrupts = <0 96 IRQ_TYPE_NONE>; + clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + #address-cells = <1>; + #size-cells = <0>; + }; + blsp_i2c8: i2c@f9964000 { status = "disabled"; compatible = "qcom,i2c-qup-v2.1.1"; -- GitLab From 5d3178c82739ae052d442b2fc8c332ce6fb4c7c9 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 18:32:39 -0700 Subject: [PATCH 3620/9938] ARM: dts: msm8974: Add modem smp2p and smd nodes Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-msm8974.dtsi | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index d8078d350ede..e98b3738ee42 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -168,6 +168,31 @@ hwlocks = <&tcsr_mutex 3>; }; + smp2p-modem { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupt-parent = <&intc>; + interrupts = <0 27 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&apcs 8 14>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + modem_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,state-cells = <1>; + }; + + modem_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + smp2p-wcnss { compatible = "qcom,smp2p"; qcom,smem = <451>, <431>; @@ -510,6 +535,13 @@ smd { compatible = "qcom,smd"; + modem { + interrupts = <0 25 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&apcs 8 12>; + qcom,smd-edge = <0>; + }; + rpm { interrupts = <0 168 1>; qcom,ipc = <&apcs 8 0>; -- GitLab From afd356dfb3a4127b61a3519802a4db9046703724 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 21:35:23 -0700 Subject: [PATCH 3621/9938] soc: qcom: smem: Use write-combine remap for SMEM Mapping the SMEM region as write combine makes the contiguous writes in SMD perform better and also allows us to do unaligned read and writes on ARM64. Signed-off-by: Bjorn Andersson Reviewed-by: Andy Gross Signed-off-by: Andy Gross --- drivers/soc/qcom/smem.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 19019aa092e8..2e1aa9f130f4 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -684,8 +684,7 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev, smem->regions[i].aux_base = (u32)r.start; smem->regions[i].size = resource_size(&r); - smem->regions[i].virt_base = devm_ioremap_nocache(dev, r.start, - resource_size(&r)); + smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, resource_size(&r)); if (!smem->regions[i].virt_base) return -ENOMEM; -- GitLab From b853cb9628bfbcc4017da46d5f5b46e3eba9d8c6 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 21:35:22 -0700 Subject: [PATCH 3622/9938] soc: qcom: smd: Make callback pass channel reference By passing the smd channel reference to the callback, rather than the smd device, we can open additional smd channels from sub-devices of smd devices. Also updates the two smd clients today found in mainline. Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd-rpm.c | 9 ++++++--- drivers/soc/qcom/smd.c | 22 ++++++++++++++++++---- drivers/soc/qcom/wcnss_ctrl.c | 8 ++++---- include/linux/soc/qcom/smd.h | 7 +++++-- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c index 731fa066f712..6609d7e0edb0 100644 --- a/drivers/soc/qcom/smd-rpm.c +++ b/drivers/soc/qcom/smd-rpm.c @@ -33,6 +33,7 @@ */ struct qcom_smd_rpm { struct qcom_smd_channel *rpm_channel; + struct device *dev; struct completion ack; struct mutex lock; @@ -149,14 +150,14 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm, } EXPORT_SYMBOL(qcom_rpm_smd_write); -static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev, +static int qcom_smd_rpm_callback(struct qcom_smd_channel *channel, const void *data, size_t count) { const struct qcom_rpm_header *hdr = data; size_t hdr_length = le32_to_cpu(hdr->length); const struct qcom_rpm_message *msg; - struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev); + struct qcom_smd_rpm *rpm = qcom_smd_get_drvdata(channel); const u8 *buf = data + sizeof(struct qcom_rpm_header); const u8 *end = buf + hdr_length; char msgbuf[32]; @@ -165,7 +166,7 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev, if (le32_to_cpu(hdr->service_type) != RPM_SERVICE_TYPE_REQUEST || hdr_length < sizeof(struct qcom_rpm_message)) { - dev_err(&qsdev->dev, "invalid request\n"); + dev_err(rpm->dev, "invalid request\n"); return 0; } @@ -206,7 +207,9 @@ static int qcom_smd_rpm_probe(struct qcom_smd_device *sdev) mutex_init(&rpm->lock); init_completion(&rpm->ack); + rpm->dev = &sdev->dev; rpm->rpm_channel = sdev->channel; + qcom_smd_set_drvdata(sdev->channel, rpm); dev_set_drvdata(&sdev->dev, rpm); diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index b6434c4be86a..ac1957dfdf24 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -194,6 +194,8 @@ struct qcom_smd_channel { int pkt_size; + void *drvdata; + struct list_head list; struct list_head dev_list; }; @@ -513,7 +515,6 @@ static void qcom_smd_channel_advance(struct qcom_smd_channel *channel, */ static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel) { - struct qcom_smd_device *qsdev = channel->qsdev; unsigned tail; size_t len; void *ptr; @@ -533,7 +534,7 @@ static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel) len = channel->pkt_size; } - ret = channel->cb(qsdev, ptr, len); + ret = channel->cb(channel, ptr, len); if (ret < 0) return ret; @@ -1034,6 +1035,18 @@ int qcom_smd_driver_register(struct qcom_smd_driver *qsdrv) } EXPORT_SYMBOL(qcom_smd_driver_register); +void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel) +{ + return channel->drvdata; +} +EXPORT_SYMBOL(qcom_smd_get_drvdata); + +void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data) +{ + channel->drvdata = data; +} +EXPORT_SYMBOL(qcom_smd_set_drvdata); + /** * qcom_smd_driver_unregister - unregister a smd driver * @qsdrv: qcom_smd_driver struct @@ -1079,12 +1092,13 @@ qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name) * Returns a channel handle on success, or -EPROBE_DEFER if the channel isn't * ready. */ -struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_device *sdev, +struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *parent, const char *name, qcom_smd_cb_t cb) { struct qcom_smd_channel *channel; - struct qcom_smd_edge *edge = sdev->channel->edge; + struct qcom_smd_device *sdev = parent->qsdev; + struct qcom_smd_edge *edge = parent->edge; int ret; /* Wait up to HZ for the channel to appear */ diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c index 7a986f881d5c..c544f3d2c6ee 100644 --- a/drivers/soc/qcom/wcnss_ctrl.c +++ b/drivers/soc/qcom/wcnss_ctrl.c @@ -100,17 +100,17 @@ struct wcnss_download_nv_resp { /** * wcnss_ctrl_smd_callback() - handler from SMD responses - * @qsdev: smd device handle + * @channel: smd channel handle * @data: pointer to the incoming data packet * @count: size of the incoming data packet * * Handles any incoming packets from the remote WCNSS_CTRL service. */ -static int wcnss_ctrl_smd_callback(struct qcom_smd_device *qsdev, +static int wcnss_ctrl_smd_callback(struct qcom_smd_channel *channel, const void *data, size_t count) { - struct wcnss_ctrl *wcnss = dev_get_drvdata(&qsdev->dev); + struct wcnss_ctrl *wcnss = qcom_smd_get_drvdata(channel); const struct wcnss_download_nv_resp *nvresp; const struct wcnss_version_resp *version; const struct wcnss_msg_hdr *hdr = data; @@ -246,7 +246,7 @@ static int wcnss_ctrl_probe(struct qcom_smd_device *sdev) init_completion(&wcnss->ack); INIT_WORK(&wcnss->download_nv_work, wcnss_download_nv); - dev_set_drvdata(&sdev->dev, wcnss); + qcom_smd_set_drvdata(sdev->channel, wcnss); return wcnss_request_version(wcnss); } diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h index bd51c8a9d807..cb2f81559bc0 100644 --- a/include/linux/soc/qcom/smd.h +++ b/include/linux/soc/qcom/smd.h @@ -26,7 +26,7 @@ struct qcom_smd_device { struct qcom_smd_channel *channel; }; -typedef int (*qcom_smd_cb_t)(struct qcom_smd_device *, const void *, size_t); +typedef int (*qcom_smd_cb_t)(struct qcom_smd_channel *, const void *, size_t); /** * struct qcom_smd_driver - smd driver struct @@ -50,13 +50,16 @@ struct qcom_smd_driver { int qcom_smd_driver_register(struct qcom_smd_driver *drv); void qcom_smd_driver_unregister(struct qcom_smd_driver *drv); +void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel); +void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data); + #define module_qcom_smd_driver(__smd_driver) \ module_driver(__smd_driver, qcom_smd_driver_register, \ qcom_smd_driver_unregister) int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len); -struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_device *sdev, +struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *channel, const char *name, qcom_smd_cb_t cb); -- GitLab From 33475a8784f4b8f0bff4419569e0dc348b318c99 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 22 Mar 2016 22:42:40 +0800 Subject: [PATCH 3623/9938] ARM: cpuidle: add const qualifier to cpuidle_ops member in structures The core code does not modify smp_operations structures. To clarify it, this patch adds 'const' qualifier to the 'ops' member of struct of_cpuidle_method. This change allows each arm cpuidle code to add 'const' qualifier to its cpuidle_ops structure. Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- arch/arm/include/asm/cpuidle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h index 3848259bebf8..baefe1d51517 100644 --- a/arch/arm/include/asm/cpuidle.h +++ b/arch/arm/include/asm/cpuidle.h @@ -36,7 +36,7 @@ struct cpuidle_ops { struct of_cpuidle_method { const char *method; - struct cpuidle_ops *ops; + const struct cpuidle_ops *ops; }; #define CPUIDLE_METHOD_OF_DECLARE(name, _method, _ops) \ -- GitLab From 4cfd55202cee115a3686d5ad6a0f60d604aca802 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 22 Mar 2016 22:42:41 +0800 Subject: [PATCH 3624/9938] ARM: cpuidle: constify return value of arm_cpuidle_get_ops() arm_cpuidle_read_ops() just copies '*ops' to cpuidle_ops[cpu], so the structure '*ops' is not modified at all. The comment is also updated accordingly. Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- arch/arm/kernel/cpuidle.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c index 703926e7007b..a44b268e12e1 100644 --- a/arch/arm/kernel/cpuidle.c +++ b/arch/arm/kernel/cpuidle.c @@ -70,7 +70,7 @@ int arm_cpuidle_suspend(int index) * * Returns a struct cpuidle_ops pointer, NULL if not found. */ -static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method) +static const struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method) { struct of_cpuidle_method *m = __cpuidle_method_of_table; @@ -88,7 +88,7 @@ static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method) * * Get the method name defined in the 'enable-method' property, retrieve the * associated cpuidle_ops and do a struct copy. This copy is needed because all - * cpuidle_ops are tagged __initdata and will be unloaded after the init + * cpuidle_ops are tagged __initconst and will be unloaded after the init * process. * * Return 0 on sucess, -ENOENT if no 'enable-method' is defined, -EOPNOTSUPP if @@ -97,7 +97,7 @@ static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method) static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu) { const char *enable_method; - struct cpuidle_ops *ops; + const struct cpuidle_ops *ops; enable_method = of_get_property(dn, "enable-method", NULL); if (!enable_method) -- GitLab From 1e712d9be873a44d7f5bc2a11d0ad6573029a67e Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 22 Mar 2016 22:42:42 +0800 Subject: [PATCH 3625/9938] soc: qcom: spm: Use const and __initconst for qcom_cpuidle_ops The qcom_cpuidle_ops structures is not over-written, so add "const" qualifier and replace __initdata with __initconst. Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano Acked-by: Andy Gross --- drivers/soc/qcom/spm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index 5548a31e1a39..1fcbb22a4a1c 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -274,7 +274,7 @@ static int __init qcom_cpuidle_init(struct device_node *cpu_node, int cpu) return per_cpu(cpu_spm_drv, cpu) ? 0 : -ENXIO; } -static struct cpuidle_ops qcom_cpuidle_ops __initdata = { +static const struct cpuidle_ops qcom_cpuidle_ops __initconst = { .suspend = qcom_idle_enter, .init = qcom_cpuidle_init, }; -- GitLab From a5bd7f7a726c97698dacb062e4635da13e5ea8c4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 11:08:42 +0200 Subject: [PATCH 3626/9938] clk: renesas: Provide Kconfig symbols for CPG/MSSR and CPG/MSTP support Currently the decision whether to build the renesas-cpg-mssr and clk-mstp drivers is handled by Makefile logic. However, the rcar-sysc driver will need to know whether CPG/MSSR and/or CPG/MSTP support are available or not. To avoid having to duplicate this logic, move it to Kconfig. Provide non-visible CLK_RENESAS_CPG_MSSR and CLK_RENESAS_CPG_MSTP Kconfig symbols, which can be used by both Makefiles and C code. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart --- drivers/clk/Kconfig | 1 + drivers/clk/renesas/Kconfig | 16 ++++++++++++++++ drivers/clk/renesas/Makefile | 26 ++++++++++++++------------ 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 drivers/clk/renesas/Kconfig diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 16f7d33421d8..c45554957499 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -201,6 +201,7 @@ source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" +source "drivers/clk/renesas/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig new file mode 100644 index 000000000000..2115ce410cfb --- /dev/null +++ b/drivers/clk/renesas/Kconfig @@ -0,0 +1,16 @@ +config CLK_RENESAS_CPG_MSSR + bool + default y if ARCH_R8A7795 + +config CLK_RENESAS_CPG_MSTP + bool + default y if ARCH_R7S72100 + default y if ARCH_R8A73A4 + default y if ARCH_R8A7740 + default y if ARCH_R8A7778 + default y if ARCH_R8A7779 + default y if ARCH_R8A7790 + default y if ARCH_R8A7791 + default y if ARCH_R8A7793 + default y if ARCH_R8A7794 + default y if ARCH_SH73A0 diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 7e2579b30326..ead8bb843524 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -1,13 +1,15 @@ obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o -obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o clk-mstp.o -obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o clk-mstp.o -obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o clk-mstp.o -obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7795) += renesas-cpg-mssr.o \ - r8a7795-cpg-mssr.o clk-div6.o -obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-mstp.o clk-div6.o +obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o +obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o +obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o +obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o +obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o + +obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o +obj-$(CONFIG_CLK_RENESAS_CPG_MSTP) += clk-mstp.o -- GitLab From 12524e348bcb2189a8cf43829e90256f7e7d4f3d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2016 11:18:06 +0200 Subject: [PATCH 3627/9938] clk: renesas: mstp: Provide dummy attach/detach_dev callbacks Provide dummy cpg_mstp_{at,de}tach_dev() PM Domain callbacks if CPG/MSTP support is not included, so the rcar-sysc driver won't have to care about this. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart --- include/linux/clk/renesas.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 095b1681daf4..ab57a298a374 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -25,7 +25,12 @@ void r8a7779_clocks_init(u32 mode); void rcar_gen2_clocks_init(u32 mode); void cpg_mstp_add_clk_domain(struct device_node *np); +#ifdef CONFIG_CLK_RENESAS_CPG_MSTP int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev); void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev); +#else +#define cpg_mstp_attach_dev NULL +#define cpg_mstp_detach_dev NULL +#endif #endif -- GitLab From 2066390ad47b374f3d35075a32325b47d15bf735 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 4 Mar 2016 17:03:46 +0100 Subject: [PATCH 3628/9938] clk: renesas: cpg-mssr: Export cpg_mssr_{at,de}tach_dev() The R-Car SYSC PM Domain driver has to power manage devices in power areas using clocks. To reuse code and to share knowledge of clocks suitable for power management, this is ideally done through the existing cpg_mssr_attach_dev() and cpg_mssr_detach_dev() callbacks. Hence these callbacks can no longer rely on their "domain" parameter pointing to the CPG/MSSR Clock Domain. To handle this, keep a pointer to the clock domain in a static variable. cpg_mssr_attach_dev() has to support probe deferral, as the R-Car SYSC PM Domain may be initialized, and devices may be added to it, before the CPG/MSSR Clock Domain is initialized. Dummy callbacks are provided for the case where CPG/MSTP support is not included, so the rcar-sysc driver won't have to care about this. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart --- drivers/clk/renesas/renesas-cpg-mssr.c | 18 ++++++++++++------ include/linux/clk/renesas.h | 7 +++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 703bdb157528..1f2dc3629f0e 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -388,6 +389,8 @@ struct cpg_mssr_clk_domain { unsigned int core_pm_clks[0]; }; +static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain; + static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec, struct cpg_mssr_clk_domain *pd) { @@ -411,17 +414,20 @@ static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec, } } -static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd, - struct device *dev) +int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev) { - struct cpg_mssr_clk_domain *pd = - container_of(genpd, struct cpg_mssr_clk_domain, genpd); + struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain; struct device_node *np = dev->of_node; struct of_phandle_args clkspec; struct clk *clk; int i = 0; int error; + if (!pd) { + dev_dbg(dev, "CPG/MSSR clock domain not yet available\n"); + return -EPROBE_DEFER; + } + while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec)) { if (cpg_mssr_is_pm_clk(&clkspec, pd)) @@ -461,8 +467,7 @@ static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd, return error; } -static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd, - struct device *dev) +void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev) { if (!list_empty(&dev->power.subsys_data->clock_list)) pm_clk_destroy(dev); @@ -491,6 +496,7 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, pm_genpd_init(genpd, &simple_qos_governor, false); genpd->attach_dev = cpg_mssr_attach_dev; genpd->detach_dev = cpg_mssr_detach_dev; + cpg_mssr_clk_domain = pd; of_genpd_add_provider_simple(np, genpd); return 0; diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index ab57a298a374..ba6fa4148515 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -33,4 +33,11 @@ void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev); #define cpg_mstp_detach_dev NULL #endif +#ifdef CONFIG_CLK_RENESAS_CPG_MSSR +int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev); +void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev); +#else +#define cpg_mssr_attach_dev NULL +#define cpg_mssr_detach_dev NULL +#endif #endif -- GitLab From 4deaaa4deb0f9c42452711aa0a4b9c27016ca2f0 Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Tue, 12 Apr 2016 23:54:59 +0300 Subject: [PATCH 3629/9938] scripts: genksyms: fix resource leak This commit fixed resource leak at func main Signed-off-by: Maxim Zhukov Signed-off-by: Michal Marek --- scripts/genksyms/genksyms.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index dafaf96e0a34..06121ce524a7 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -873,5 +873,8 @@ int main(int argc, char **argv) (double)nsyms / (double)HASH_BUCKETS); } + if (dumpfile) + fclose(dumpfile); + return errors != 0; } -- GitLab From 531f50388f1b05a297c6eab7a0c1e8e6d997678b Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Sun, 20 Mar 2016 10:57:32 +0530 Subject: [PATCH 3630/9938] Coccinelle: setup_timer: Add space in front of parentheses Add space in front of the offending parentheses to silent the parse error for older Coccinelle versions. This makes the rule usable with all Coccinelle versions. Reported-by: Nishanth Menon Signed-off-by: Vaishali Thakkar Acked-by: Julia Lawall Fixes: c5eda8fd10c6 ("Coccinelle: Add api/setup_timer.cocci") Signed-off-by: Michal Marek --- scripts/coccinelle/api/setup_timer.cocci | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/coccinelle/api/setup_timer.cocci b/scripts/coccinelle/api/setup_timer.cocci index 8ee0ac30e547..eb6bd9e4ab1a 100644 --- a/scripts/coccinelle/api/setup_timer.cocci +++ b/scripts/coccinelle/api/setup_timer.cocci @@ -106,7 +106,7 @@ position j0, j1, j2; @match_function_and_data_after_init_timer_context depends on !patch && !match_immediate_function_data_after_init_timer_context && -(context || org || report)@ + (context || org || report)@ expression a, b, e1, e2, e3, e4, e5; position j0, j1, j2; @@ @@ -127,7 +127,7 @@ position j0, j1, j2; @r3_context depends on !patch && !match_immediate_function_data_after_init_timer_context && !match_function_and_data_after_init_timer_context && -(context || org || report)@ + (context || org || report)@ expression c, e6, e7; position r1.p; position j0, j1; -- GitLab From f931362b38191016b7a6dc31d90a515b37658e02 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 19 Mar 2016 18:37:51 +0100 Subject: [PATCH 3631/9938] scripts: coccinelle: remove check to move constants to right The header mentions this check depends on personal taste. I agree. Running coccicheck on patches before I apply them, this SmPL produced enough false positives for me that I'd rather see it removed. Signed-off-by: Wolfram Sang Acked-by: Julia Lawall Signed-off-by: Michal Marek --- .../coccinelle/misc/compare_const_fl.cocci | 171 ------------------ 1 file changed, 171 deletions(-) delete mode 100644 scripts/coccinelle/misc/compare_const_fl.cocci diff --git a/scripts/coccinelle/misc/compare_const_fl.cocci b/scripts/coccinelle/misc/compare_const_fl.cocci deleted file mode 100644 index b5d4bab60263..000000000000 --- a/scripts/coccinelle/misc/compare_const_fl.cocci +++ /dev/null @@ -1,171 +0,0 @@ -/// Move constants to the right of binary operators. -//# Depends on personal taste in some cases. -/// -// Confidence: Moderate -// Copyright: (C) 2015 Copyright: (C) 2015 Julia Lawall, Inria. GPLv2. -// URL: http://coccinelle.lip6.fr/ -// Options: --no-includes --include-headers - -virtual patch -virtual context -virtual org -virtual report - -@r1 depends on patch && !context && !org && !report - disable bitor_comm, neg_if_exp@ -constant c,c1; -local idexpression i; -expression e,e1,e2; -binary operator b = {==,!=,&,|}; -type t; -@@ - -( -c b (c1) -| -sizeof(t) b e1 -| -sizeof e b e1 -| -i b e1 -| -c | e1 | e2 | ... -| -c | (e ? e1 : e2) -| -- c -+ e -b -- e -+ c -) - -@r2 depends on patch && !context && !org && !report - disable gtr_lss, gtr_lss_eq, not_int2@ -constant c,c1; -expression e,e1,e2; -binary operator b; -binary operator b1 = {<,<=},b2 = {<,<=}; -binary operator b3 = {>,>=},b4 = {>,>=}; -local idexpression i; -type t; -@@ - -( -c b c1 -| -sizeof(t) b e1 -| -sizeof e b e1 -| - (e1 b1 e) && (e b2 e2) -| - (e1 b3 e) && (e b4 e2) -| -i b e -| -- c < e -+ e > c -| -- c <= e -+ e >= c -| -- c > e -+ e < c -| -- c >= e -+ e <= c -) - -// ---------------------------------------------------------------------------- - -@r1_context depends on !patch && (context || org || report) - disable bitor_comm, neg_if_exp exists@ -type t; -binary operator b = {==,!=,&,|}; -constant c, c1; -expression e, e1, e2; -local idexpression i; -position j0; -@@ - -( -c b (c1) -| -sizeof(t) b e1 -| -sizeof e b e1 -| -i b e1 -| -c | e1 | e2 | ... -| -c | (e ? e1 : e2) -| -* c@j0 b e -) - -@r2_context depends on !patch && (context || org || report) - disable gtr_lss, gtr_lss_eq, not_int2 exists@ -type t; -binary operator b, b1 = {<,<=}, b2 = {<,<=}, b3 = {>,>=}, b4 = {>,>=}; -constant c, c1; -expression e, e1, e2; -local idexpression i; -position j0; -@@ - -( -c b c1 -| -sizeof(t) b e1 -| -sizeof e b e1 -| - (e1 b1 e) && (e b2 e2) -| - (e1 b3 e) && (e b4 e2) -| -i b e -| -* c@j0 < e -| -* c@j0 <= e -| -* c@j0 > e -| -* c@j0 >= e -) - -// ---------------------------------------------------------------------------- - -@script:python r1_org depends on org@ -j0 << r1_context.j0; -@@ - -msg = "Move constant to right." -coccilib.org.print_todo(j0[0], msg) - -@script:python r2_org depends on org@ -j0 << r2_context.j0; -@@ - -msg = "Move constant to right." -coccilib.org.print_todo(j0[0], msg) - -// ---------------------------------------------------------------------------- - -@script:python r1_report depends on report@ -j0 << r1_context.j0; -@@ - -msg = "Move constant to right." -coccilib.report.print_report(j0[0], msg) - -@script:python r2_report depends on report@ -j0 << r2_context.j0; -@@ - -msg = "Move constant to right." -coccilib.report.print_report(j0[0], msg) - -- GitLab From 03ae1747869437a8e4d0d4e79d4c88c25c6df39c Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 19 Apr 2016 21:29:27 +0200 Subject: [PATCH 3632/9938] clk: rockchip: fix checkpatch warning in core code We seem to have accumulated a bunch of checkpatch warnings, with mainly overlong lines and two unnecessary allocation error messages. Most were introduced with the recent multi-controller-support but some were quite a bit older. Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-mmc-phase.c | 3 +- drivers/clk/rockchip/clk.c | 44 +++++++++++++++------------- drivers/clk/rockchip/clk.h | 2 +- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c index e0dc7e83403a..bc856f21f6b2 100644 --- a/drivers/clk/rockchip/clk-mmc-phase.c +++ b/drivers/clk/rockchip/clk-mmc-phase.c @@ -123,7 +123,8 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees) raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; raw_value |= nineties; - writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg); + writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), + mmc_clock->reg); pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n", clk_hw_get_name(hw), degrees, delay_num, diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 277f9270bf72..f0a8be1553b0 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -42,7 +42,8 @@ * sometimes without one of those components. */ static struct clk *rockchip_clk_register_branch(const char *name, - const char *const *parent_names, u8 num_parents, void __iomem *base, + const char *const *parent_names, u8 num_parents, + void __iomem *base, int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, u8 div_shift, u8 div_width, u8 div_flags, struct clk_div_table *div_table, int gate_offset, @@ -139,9 +140,11 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n", __func__, event, ndata->old_rate, ndata->new_rate); if (event == PRE_RATE_CHANGE) { - frac->rate_change_idx = frac->mux_ops->get_parent(&frac_mux->hw); + frac->rate_change_idx = + frac->mux_ops->get_parent(&frac_mux->hw); if (frac->rate_change_idx != frac->mux_frac_idx) { - frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx); + frac->mux_ops->set_parent(&frac_mux->hw, + frac->mux_frac_idx); frac->rate_change_remuxed = 1; } } else if (event == POST_RATE_CHANGE) { @@ -152,7 +155,8 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, * reaches the mux itself. */ if (frac->rate_change_remuxed) { - frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx); + frac->mux_ops->set_parent(&frac_mux->hw, + frac->rate_change_idx); frac->rate_change_remuxed = 0; } } @@ -326,18 +330,12 @@ struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, int i; ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL); - if (!ctx) { - pr_err("%s: Could not allocate clock provider context\n", - __func__); + if (!ctx) return ERR_PTR(-ENOMEM); - } clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); - if (!clk_table) { - pr_err("%s: Could not allocate clock lookup table\n", - __func__); + if (!clk_table) goto err_free; - } for (i = 0; i < nr_clks; ++i) clk_table[i] = ERR_PTR(-ENOENT); @@ -367,7 +365,8 @@ void __init rockchip_clk_of_add_provider(struct device_node *np, struct regmap *rockchip_clk_get_grf(struct rockchip_clk_provider *ctx) { if (IS_ERR(ctx->grf)) - ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, "rockchip,grf"); + ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, + "rockchip,grf"); return ctx->grf; } @@ -427,7 +426,8 @@ void __init rockchip_clk_register_branches( if (list->div_table) clk = clk_register_divider_table(NULL, list->name, list->parent_names[0], - flags, ctx->reg_base + list->muxdiv_offset, + flags, + ctx->reg_base + list->muxdiv_offset, list->div_shift, list->div_width, list->div_flags, list->div_table, &ctx->lock); @@ -441,7 +441,8 @@ void __init rockchip_clk_register_branches( case branch_fraction_divider: clk = rockchip_clk_register_frac_branch(ctx, list->name, list->parent_names, list->num_parents, - ctx->reg_base, list->muxdiv_offset, list->div_flags, + ctx->reg_base, list->muxdiv_offset, + list->div_flags, list->gate_offset, list->gate_shift, list->gate_flags, flags, list->child, &ctx->lock); @@ -457,7 +458,8 @@ void __init rockchip_clk_register_branches( case branch_composite: clk = rockchip_clk_register_branch(list->name, list->parent_names, list->num_parents, - ctx->reg_base, list->muxdiv_offset, list->mux_shift, + ctx->reg_base, list->muxdiv_offset, + list->mux_shift, list->mux_width, list->mux_flags, list->div_shift, list->div_width, list->div_flags, list->div_table, @@ -517,8 +519,8 @@ void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, struct clk *clk; clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, - reg_data, rates, nrates, ctx->reg_base, - &ctx->lock); + reg_data, rates, nrates, + ctx->reg_base, &ctx->lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s: %ld\n", __func__, name, PTR_ERR(clk)); @@ -560,8 +562,10 @@ static struct notifier_block rockchip_restart_handler = { .priority = 128, }; -void __init rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, - unsigned int reg, void (*cb)(void)) +void __init +rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, + unsigned int reg, + void (*cb)(void)) { int ret; diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 4a355bf1d69a..1abb7d05d1c7 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -252,7 +252,7 @@ struct rockchip_cpuclk_rate_table { }; /** - * struct rockchip_cpuclk_reg_data - describes register offsets and masks of the cpuclock + * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock * @core_reg: register offset of the core settings register * @div_core_shift: core divider offset used to divide the pll value * @div_core_mask: core divider mask -- GitLab From 27c3bffd230abd0a598586aed0fe0ba7b61e0e2e Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 7 Apr 2016 15:00:54 +0200 Subject: [PATCH 3633/9938] kbuild/mkspec: support 'update-bootloader'-based systems When uninstalling kernel RPM, we're unconditionally calling "new-kernel-pkg --remove". This is useless on systems which are based on 'update-bootloader' script instead. Support update-bootloader removal method as well in case the script is present; contrary to new-kernel-pkg, this needs to be done in %postun, otherwise update-bootloader will refuse to remove entry for kernel for which the binary still exists. Signed-off-by: Jiri Kosina Signed-off-by: Michal Marek --- scripts/package/mkspec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/package/mkspec b/scripts/package/mkspec index b6de63cb3f23..57673bae5597 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -143,6 +143,11 @@ echo "if [ -x /sbin/new-kernel-pkg ]; then" echo "new-kernel-pkg --remove $KERNELRELEASE --rminitrd --initrdfile=/boot/initramfs-$KERNELRELEASE.img" echo "fi" echo "" +echo "%postun" +echo "if [ -x /sbin/update-bootloader ]; then" +echo "/sbin/update-bootloader --remove $KERNELRELEASE" +echo "fi" +echo "" echo "%files" echo '%defattr (-, root, root)' echo "/lib/modules/$KERNELRELEASE" -- GitLab From 2e8d696b79e9c68d3005a9b09a8c72625d141ea6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 13 Mar 2016 09:13:55 +0900 Subject: [PATCH 3634/9938] kbuild: drop FORCE from PHONY targets These targets are marked as PHONY. No need to add FORCE to their dependency. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- Makefile | 8 ++++---- arch/arm/vdso/Makefile | 2 +- arch/ia64/Makefile | 4 ++-- arch/x86/entry/vdso/Makefile | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index cec9539d3082..f1e5e3bcc217 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ PHONY += $(MAKECMDGOALS) sub-make $(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make @: -sub-make: FORCE +sub-make: $(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \ -f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS)) @@ -1018,7 +1018,7 @@ prepare1: prepare2 $(version_h) include/generated/utsrelease.h \ archprepare: archheaders archscripts prepare1 scripts_basic -prepare0: archprepare FORCE +prepare0: archprepare $(Q)$(MAKE) $(build)=. # All the preparing.. @@ -1077,7 +1077,7 @@ INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware export INSTALL_FW_PATH PHONY += firmware_install -firmware_install: FORCE +firmware_install: @mkdir -p $(objtree)/firmware $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install @@ -1097,7 +1097,7 @@ PHONY += archscripts archscripts: PHONY += __headers -__headers: $(version_h) scripts_basic asm-generic archheaders archscripts FORCE +__headers: $(version_h) scripts_basic asm-generic archheaders archscripts $(Q)$(MAKE) $(build)=scripts build_unifdef PHONY += headers_install_all diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile index 1160434eece0..59a8fa7b8a3b 100644 --- a/arch/arm/vdso/Makefile +++ b/arch/arm/vdso/Makefile @@ -74,5 +74,5 @@ $(MODLIB)/vdso: FORCE @mkdir -p $(MODLIB)/vdso PHONY += vdso_install -vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso FORCE +vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso $(call cmd,vdso_install) diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 970d0bd99621..648f1cef33fa 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -95,8 +95,8 @@ define archhelp echo '* unwcheck - Check vmlinux for invalid unwind info' endef -archprepare: make_nr_irqs_h FORCE +archprepare: make_nr_irqs_h PHONY += make_nr_irqs_h FORCE -make_nr_irqs_h: FORCE +make_nr_irqs_h: $(Q)$(MAKE) $(build)=arch/ia64/kernel include/generated/nr-irqs.h diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index 6874da5f67fc..253b72eaade6 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile @@ -193,10 +193,10 @@ vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%) $(MODLIB)/vdso: FORCE @mkdir -p $(MODLIB)/vdso -$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE +$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso $(call cmd,vdso_install) PHONY += vdso_install $(vdso_img_insttargets) -vdso_install: $(vdso_img_insttargets) FORCE +vdso_install: $(vdso_img_insttargets) clean-files := vdso32.so vdso32.so.dbg vdso64* vdso-image-*.c vdsox32.so* -- GitLab From 612e47cec4ad6c5e49fe0a248b0c70849c86b0ee Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 13 Mar 2016 09:39:22 +0900 Subject: [PATCH 3635/9938] kbuild: specify modules(_install) as PHONY rather than FORCE As in other places, PHONY is a better fit for "modules" and "modules_install". Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f1e5e3bcc217..ec3dde3f6bb8 100644 --- a/Makefile +++ b/Makefile @@ -1208,7 +1208,8 @@ else # CONFIG_MODULES # Modules not configured # --------------------------------------------------------------------------- -modules modules_install: FORCE +PHONY += modules modules_install +modules modules_install: @echo >&2 @echo >&2 "The present kernel configuration has modules disabled." @echo >&2 "Type 'make config' and enable loadable module support." -- GitLab From fe69b420d39d307cfe2cba875dc1dbf668877198 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 13 Mar 2016 09:39:55 +0900 Subject: [PATCH 3636/9938] kbuild: mark help target as PHONY Obviously, the "help" should be a PHONY target. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index ec3dde3f6bb8..e3af48068c65 100644 --- a/Makefile +++ b/Makefile @@ -1300,6 +1300,7 @@ boards := $(sort $(notdir $(boards))) board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig)) board-dirs := $(sort $(notdir $(board-dirs:/=))) +PHONY += help help: @echo 'Cleaning targets:' @echo ' clean - Remove most generated files but keep the config and' @@ -1470,6 +1471,7 @@ $(clean-dirs): clean: rm-dirs := $(MODVERDIR) clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers +PHONY += help help: @echo ' Building external modules.' @echo ' Syntax: make -C path/to/kernel/src M=$$PWD target' -- GitLab From be1fb0e8eb0821234a9df2e2938332c1884f7f0f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 31 Mar 2016 20:14:16 +0900 Subject: [PATCH 3637/9938] kbuild: delete unnecessary "@:" Since commit 2aedcd098a94 ('kbuild: suppress annoying "... is up to date." message'), $(call if_changed,...) is evaluated to "@:" when there is nothing to do. We no longer need to add "@:" after $(call if_changed,...) to suppress "... is up to date." message. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- arch/arm/boot/Makefile | 1 - arch/arm/boot/bootp/Makefile | 1 - arch/h8300/boot/compressed/Makefile | 1 - arch/m32r/boot/compressed/Makefile | 1 - arch/mn10300/boot/compressed/Makefile | 1 - arch/nios2/boot/compressed/Makefile | 1 - arch/s390/boot/compressed/Makefile | 1 - arch/sh/boot/compressed/Makefile | 1 - arch/sh/boot/romimage/Makefile | 1 - arch/unicore32/boot/compressed/Makefile | 1 - arch/x86/boot/compressed/Makefile | 1 - arch/x86/purgatory/Makefile | 2 -- arch/x86/realmode/rm/Makefile | 1 - 13 files changed, 14 deletions(-) diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 48fab15cfc02..535a424d9eb0 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -82,7 +82,6 @@ $(obj)/uImage: $(obj)/zImage FORCE $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE $(Q)$(MAKE) $(build)=$(obj)/bootp $@ - @: $(obj)/bootpImage: $(obj)/bootp/bootp FORCE $(call if_changed,objcopy) diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile index 5761f0039133..52a543b17ee3 100644 --- a/arch/arm/boot/bootp/Makefile +++ b/arch/arm/boot/bootp/Makefile @@ -17,7 +17,6 @@ targets := bootp init.o kernel.o initrd.o # Note that bootp.lds picks up kernel.o and initrd.o $(obj)/bootp: $(src)/bootp.lds $(addprefix $(obj)/,init.o kernel.o initrd.o) FORCE $(call if_changed,ld) - @: # kernel.o and initrd.o includes a binary image using # .incbin, a dependency which is not tracked automatically diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile index 7643633f1330..613bfe6f5272 100644 --- a/arch/h8300/boot/compressed/Makefile +++ b/arch/h8300/boot/compressed/Makefile @@ -23,7 +23,6 @@ LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup -T $(obj)/vmlinux.lds \ $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE $(call if_changed,ld) - @: $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) diff --git a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile index 01729c2979ba..0606a727aab2 100644 --- a/arch/m32r/boot/compressed/Makefile +++ b/arch/m32r/boot/compressed/Makefile @@ -19,7 +19,6 @@ LDFLAGS_vmlinux := -T $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE $(call if_changed,ld) - @: $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) diff --git a/arch/mn10300/boot/compressed/Makefile b/arch/mn10300/boot/compressed/Makefile index 08a95e171685..5f56f9de1061 100644 --- a/arch/mn10300/boot/compressed/Makefile +++ b/arch/mn10300/boot/compressed/Makefile @@ -8,7 +8,6 @@ LDFLAGS_vmlinux := -Ttext $(CONFIG_KERNEL_ZIMAGE_BASE_ADDRESS) -e startup_32 $(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE $(call if_changed,ld) - @: $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) diff --git a/arch/nios2/boot/compressed/Makefile b/arch/nios2/boot/compressed/Makefile index 5b0fb346d888..d5921c9a9726 100644 --- a/arch/nios2/boot/compressed/Makefile +++ b/arch/nios2/boot/compressed/Makefile @@ -11,7 +11,6 @@ LDFLAGS_vmlinux := -T $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE $(call if_changed,ld) - @: LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile index fac6ac9790fa..1dd210347e12 100644 --- a/arch/s390/boot/compressed/Makefile +++ b/arch/s390/boot/compressed/Makefile @@ -22,7 +22,6 @@ OBJECTS += $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o LDFLAGS_vmlinux := --oformat $(LD_BFD) -e startup -T $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(call if_changed,ld) - @: sed-sizes := -e 's/^\([0-9a-fA-F]*\) . \(__bss_start\|_end\)$$/\#define SZ\2 0x\1/p' diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 6df826ee7316..c4c47ea9fa94 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -55,7 +55,6 @@ $(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(lib1funcs-obj) FORCE $(call if_changed,ld) - @: $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) diff --git a/arch/sh/boot/romimage/Makefile b/arch/sh/boot/romimage/Makefile index 2216ee57f251..43c41191de5d 100644 --- a/arch/sh/boot/romimage/Makefile +++ b/arch/sh/boot/romimage/Makefile @@ -17,7 +17,6 @@ LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(load-y) -e romstart \ $(obj)/vmlinux: $(obj)/head.o $(obj-y) $(obj)/piggy.o FORCE $(call if_changed,ld) - @: OBJCOPYFLAGS += -j .empty_zero_page diff --git a/arch/unicore32/boot/compressed/Makefile b/arch/unicore32/boot/compressed/Makefile index 96494fb646f7..9aecdd3ddc48 100644 --- a/arch/unicore32/boot/compressed/Makefile +++ b/arch/unicore32/boot/compressed/Makefile @@ -54,7 +54,6 @@ LDFLAGS_vmlinux += -T $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \ $(obj)/misc.o FORCE $(call if_changed,ld) - @: # We now have a PIC decompressor implementation. Decompressors running # from RAM should not define ZTEXTADDR. Decompressors running directly diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 6915ff2bd996..0fb857ebe3d9 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -60,7 +60,6 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o $(obj)/vmlinux: $(vmlinux-objs-y) FORCE $(call if_changed,ld) - @: OBJCOPYFLAGS_vmlinux.bin := -R .comment -S $(obj)/vmlinux.bin: vmlinux FORCE diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index 92e3e1d84c1d..12734a96df47 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile @@ -26,7 +26,5 @@ quiet_cmd_bin2c = BIN2C $@ $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE $(call if_changed,bin2c) - @: - obj-$(CONFIG_KEXEC_FILE) += kexec-purgatory.o diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index b95964610ea7..c556c5ae8de5 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile @@ -59,7 +59,6 @@ OBJCOPYFLAGS_realmode.bin := -O binary targets += realmode.bin $(obj)/realmode.bin: $(obj)/realmode.elf $(obj)/realmode.relocs FORCE $(call if_changed,objcopy) - @: quiet_cmd_relocs = RELOCS $@ cmd_relocs = arch/x86/tools/relocs --realmode $< > $@ -- GitLab From 1c44b28dfe527d70a6451ffb7ee091221be82168 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 8 Apr 2016 11:16:10 +0900 Subject: [PATCH 3638/9938] kbuild: drop redundant "PHONY += FORCE" "PHONY += FORCE" is already cared by scripts/Makefile.build, which these files are included from. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- arch/arm/boot/bootp/Makefile | 2 +- arch/ia64/Makefile | 2 +- arch/unicore32/boot/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile index 52a543b17ee3..5e4acd253b30 100644 --- a/arch/arm/boot/bootp/Makefile +++ b/arch/arm/boot/bootp/Makefile @@ -25,4 +25,4 @@ $(obj)/kernel.o: arch/arm/boot/zImage FORCE $(obj)/initrd.o: $(INITRD) FORCE -PHONY += $(INITRD) FORCE +PHONY += $(INITRD) diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 648f1cef33fa..c100d780f1eb 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -96,7 +96,7 @@ define archhelp endef archprepare: make_nr_irqs_h -PHONY += make_nr_irqs_h FORCE +PHONY += make_nr_irqs_h make_nr_irqs_h: $(Q)$(MAKE) $(build)=arch/ia64/kernel include/generated/nr-irqs.h diff --git a/arch/unicore32/boot/Makefile b/arch/unicore32/boot/Makefile index ec7fb70b412b..828855007b29 100644 --- a/arch/unicore32/boot/Makefile +++ b/arch/unicore32/boot/Makefile @@ -31,7 +31,7 @@ $(obj)/uImage: $(obj)/zImage FORCE $(call if_changed,uimage) @echo ' Image $@ is ready' -PHONY += initrd FORCE +PHONY += initrd initrd: @test "$(INITRD)" != "" || \ (echo You must specify INITRD; exit -1) -- GitLab From 5e7c17df795e462c70a43f1b3b670e08efefe8fd Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 22 Mar 2016 22:42:43 +0800 Subject: [PATCH 3639/9938] drivers: firmware: psci: use const and __initconst for psci_cpuidle_ops The psci_cpuidle_ops structures is not over-written, so add "const" qualifier and replace __initdata with __initconst. Acked-by: Lorenzo Pieralisi Signed-off-by: Jisheng Zhang Signed-off-by: Daniel Lezcano --- drivers/firmware/psci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index 11bfee8b79a9..eb8134a148c0 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -355,7 +355,7 @@ int psci_cpu_suspend_enter(unsigned long index) /* ARM specific CPU idle operations */ #ifdef CONFIG_ARM -static struct cpuidle_ops psci_cpuidle_ops __initdata = { +static const struct cpuidle_ops psci_cpuidle_ops __initconst = { .suspend = psci_cpu_suspend_enter, .init = psci_dt_cpu_init_idle, }; -- GitLab From 23d43848708afd7aa9a2c8516a3f269a3e71be4f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 8 Apr 2016 11:24:47 +0900 Subject: [PATCH 3640/9938] kbuild: rename cmd_cc_i_c to cmd_cpp_i_c This command just preprocesses .c files into .i files, so cmd_cpp_i_c seems more suitable. Signed-off-by: Masahiro Yamada Acked-by: Arnaldo Carvalho de Melo Signed-off-by: Michal Marek --- scripts/Makefile.build | 6 +++--- tools/build/Makefile.build | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 12821d9eae85..13f606ba2a3b 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -152,11 +152,11 @@ cmd_cc_s_c = $(CC) $(c_flags) $(DISABLE_LTO) -fverbose-asm -S -o $@ $< $(obj)/%.s: $(src)/%.c FORCE $(call if_changed_dep,cc_s_c) -quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@ -cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $< +quiet_cmd_cpp_i_c = CPP $(quiet_modtag) $@ +cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $< $(obj)/%.i: $(src)/%.c FORCE - $(call if_changed_dep,cc_i_c) + $(call if_changed_dep,cpp_i_c) cmd_gensymtypes = \ $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build index ee566e8bd1cf..27f3583193e6 100644 --- a/tools/build/Makefile.build +++ b/tools/build/Makefile.build @@ -58,8 +58,8 @@ quiet_cmd_mkdir = MKDIR $(dir $@) quiet_cmd_cc_o_c = CC $@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< -quiet_cmd_cc_i_c = CPP $@ - cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $< +quiet_cmd_cpp_i_c = CPP $@ + cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $< quiet_cmd_cc_s_c = AS $@ cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< @@ -83,11 +83,11 @@ $(OUTPUT)%.o: %.S FORCE $(OUTPUT)%.i: %.c FORCE $(call rule_mkdir) - $(call if_changed_dep,cc_i_c) + $(call if_changed_dep,cpp_i_c) $(OUTPUT)%.s: %.S FORCE $(call rule_mkdir) - $(call if_changed_dep,cc_i_c) + $(call if_changed_dep,cpp_i_c) $(OUTPUT)%.s: %.c FORCE $(call rule_mkdir) -- GitLab From e0f41e52ddf5dc676577f974c9f0af77732f251a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 8 Apr 2016 11:24:48 +0900 Subject: [PATCH 3641/9938] kbuild: rename cmd_as_s_S to cmd_cpp_s_S This command just preprocesses .S files into .s files, so cmd_cpp_s_S seems more suitable. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- scripts/Makefile.build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 13f606ba2a3b..0d1ca5bf42fb 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -313,11 +313,11 @@ modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL) $(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) $(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) -quiet_cmd_as_s_S = CPP $(quiet_modtag) $@ -cmd_as_s_S = $(CPP) $(a_flags) -o $@ $< +quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@ +cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $< $(obj)/%.s: $(src)/%.S FORCE - $(call if_changed_dep,as_s_S) + $(call if_changed_dep,cpp_s_S) quiet_cmd_as_o_S = AS $(quiet_modtag) $@ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< -- GitLab From b42841b7bb6286da56b4fa79835c27166b7e228b Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 17 Mar 2016 16:32:14 +0100 Subject: [PATCH 3642/9938] kbuild: Get rid of KBUILD_STR The compiler can accept -DKBUILD_MODNAME="foo", it's just a matter of quoting. That way, we reduce the gcc command line a bit. Signed-off-by: Michal Marek --- scripts/Makefile.lib | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index ddf83d0181e7..e64ad0dbff5b 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -96,10 +96,10 @@ obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) # Note: Files that end up in two or more modules are compiled without the # KBUILD_MODNAME definition. The reason is that any made-up name would # differ in different configs. -name-fix = $(subst $(comma),_,$(subst -,_,$1)) -basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +name-fix = $(squote)$(quote)$(subst $(comma),_,$(subst -,_,$1))$(quote)$(squote) +basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget)) modname_flags = $(if $(filter 1,$(words $(modname))),\ - -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + -DKBUILD_MODNAME=$(call name-fix,$(modname))) orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ $(ccflags-y) $(CFLAGS_$(basetarget).o) @@ -162,7 +162,7 @@ endif c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ $(__c_flags) $(modkern_cflags) \ - -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + $(basename_flags) $(modname_flags) a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ $(__a_flags) $(modkern_aflags) -- GitLab From b6bf3289bc3c1d8df9f37c2f4f8450cc677fb286 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:05:04 -0700 Subject: [PATCH 3643/9938] ASoC: ak4642: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Signed-off-by: Stephen Boyd Acked-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak4642.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index cda27c22812a..1ee8506c06c7 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -608,9 +608,7 @@ static struct clk *ak4642_of_parse_mcko(struct device *dev) of_property_read_string(np, "clock-output-names", &clk_name); - clk = clk_register_fixed_rate(dev, clk_name, parent_clk_name, - (parent_clk_name) ? 0 : CLK_IS_ROOT, - rate); + clk = clk_register_fixed_rate(dev, clk_name, parent_clk_name, 0, rate); if (!IS_ERR(clk)) of_clk_add_provider(np, of_clk_src_simple_get, clk); -- GitLab From 2ebdf684082fa9ad924df1b2f80653920c7ca097 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:08:00 -0700 Subject: [PATCH 3644/9938] ASoC: rsnd: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Signed-off-by: Stephen Boyd Acked-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 606399de684d..49354d17ea55 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -492,9 +492,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, */ if (!count) { clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT], - parent_clk_name, - (parent_clk_name) ? - 0 : CLK_IS_ROOT, req_rate); + parent_clk_name, 0, req_rate); if (!IS_ERR(clk)) { adg->clkout[CLKOUT] = clk; of_clk_add_provider(np, of_clk_src_simple_get, clk); @@ -506,9 +504,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, else { for (i = 0; i < CLKOUTMAX; i++) { clk = clk_register_fixed_rate(dev, clkout_name[i], - parent_clk_name, - (parent_clk_name) ? - 0 : CLK_IS_ROOT, + parent_clk_name, 0, req_rate); if (!IS_ERR(clk)) { adg->onecell.clks = adg->clkout; -- GitLab From 280af2b8eb3674628223b8d143b5f71cd2a96159 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:10:07 -0700 Subject: [PATCH 3645/9938] spi: spi-pxa2xx: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Cc: Daniel Mack Cc: Haojian Zhuang Cc: Robert Jarzmik Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 520ed1dd5780..83706aeb39b2 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -173,8 +173,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ssp->type = c->type; snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); - ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL, - CLK_IS_ROOT, c->max_clk_rate); + ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL, 0, + c->max_clk_rate); if (IS_ERR(ssp->clk)) return PTR_ERR(ssp->clk); -- GitLab From e81f3340bba2bdcdf021aff511830e718e6e2112 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 16 Apr 2016 15:01:09 +0800 Subject: [PATCH 3646/9938] eCryptfs: Do not allocate hash tfm in NORECLAIM context You cannot allocate crypto tfm objects in NORECLAIM or NOFS contexts. The ecryptfs code currently does exactly that for the MD5 tfm. This patch fixes it by preallocating the MD5 tfm in a safe context. The MD5 tfm is also reentrant so this patch removes the superfluous cs_hash_tfm_mutex. Reported-by: Nicolas Boichat Signed-off-by: Herbert Xu --- fs/ecryptfs/crypto.c | 32 ++++++++++++++++---------------- fs/ecryptfs/ecryptfs_kernel.h | 3 +-- fs/ecryptfs/inode.c | 7 +++++-- fs/ecryptfs/super.c | 5 ++++- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 64026e53722a..56004965d351 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -105,19 +105,7 @@ static int ecryptfs_calculate_md5(char *dst, struct crypto_shash *tfm; int rc = 0; - mutex_lock(&crypt_stat->cs_hash_tfm_mutex); tfm = crypt_stat->hash_tfm; - if (!tfm) { - tfm = crypto_alloc_shash(ECRYPTFS_DEFAULT_HASH, 0, 0); - if (IS_ERR(tfm)) { - rc = PTR_ERR(tfm); - ecryptfs_printk(KERN_ERR, "Error attempting to " - "allocate crypto context; rc = [%d]\n", - rc); - goto out; - } - crypt_stat->hash_tfm = tfm; - } rc = ecryptfs_hash_digest(tfm, src, len, dst); if (rc) { printk(KERN_ERR @@ -126,7 +114,6 @@ static int ecryptfs_calculate_md5(char *dst, goto out; } out: - mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); return rc; } @@ -207,16 +194,29 @@ int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, * * Initialize the crypt_stat structure. */ -void -ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) +int ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) { + struct crypto_shash *tfm; + int rc; + + tfm = crypto_alloc_shash(ECRYPTFS_DEFAULT_HASH, 0, 0); + if (IS_ERR(tfm)) { + rc = PTR_ERR(tfm); + ecryptfs_printk(KERN_ERR, "Error attempting to " + "allocate crypto context; rc = [%d]\n", + rc); + return rc; + } + memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); INIT_LIST_HEAD(&crypt_stat->keysig_list); mutex_init(&crypt_stat->keysig_list_mutex); mutex_init(&crypt_stat->cs_mutex); mutex_init(&crypt_stat->cs_tfm_mutex); - mutex_init(&crypt_stat->cs_hash_tfm_mutex); + crypt_stat->hash_tfm = tfm; crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED; + + return 0; } /** diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index d123fbaa28e0..c7761a91cc2c 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -242,7 +242,6 @@ struct ecryptfs_crypt_stat { struct list_head keysig_list; struct mutex keysig_list_mutex; struct mutex cs_tfm_mutex; - struct mutex cs_hash_tfm_mutex; struct mutex cs_mutex; }; @@ -577,7 +576,7 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, int sg_size); int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat); void ecryptfs_rotate_iv(unsigned char *iv); -void ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); +int ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); void ecryptfs_destroy_mount_crypt_stat( struct ecryptfs_mount_crypt_stat *mount_crypt_stat); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 121114e9a464..0caec70a8f17 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -898,8 +898,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) struct ecryptfs_crypt_stat *crypt_stat; crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat; - if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) - ecryptfs_init_crypt_stat(crypt_stat); + if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) { + rc = ecryptfs_init_crypt_stat(crypt_stat); + if (rc) + return rc; + } inode = d_inode(dentry); lower_inode = ecryptfs_inode_to_lower(inode); lower_dentry = ecryptfs_dentry_to_lower(dentry); diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 77a486d3a51b..85411ceb0508 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -55,7 +55,10 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb) inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL); if (unlikely(!inode_info)) goto out; - ecryptfs_init_crypt_stat(&inode_info->crypt_stat); + if (ecryptfs_init_crypt_stat(&inode_info->crypt_stat)) { + kmem_cache_free(ecryptfs_inode_info_cache, inode_info); + goto out; + } mutex_init(&inode_info->lower_file_mutex); atomic_set(&inode_info->lower_file_count, 0); inode_info->lower_file = NULL; -- GitLab From 5343e674f32fb82b7a80a24b5a84eee62d3fe624 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 18 Apr 2016 12:57:41 +0200 Subject: [PATCH 3647/9938] crypto4xx: integrate ppc4xx-rng into crypto4xx This patch integrates the ppc4xx-rng driver into the existing crypto4xx. This is because the true random number generator is controlled and part of the security core. Signed-off-by: Christian Lamparter Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 13 --- drivers/char/hw_random/Makefile | 1 - drivers/char/hw_random/ppc4xx-rng.c | 147 ------------------------ drivers/crypto/Kconfig | 8 ++ drivers/crypto/amcc/Makefile | 1 + drivers/crypto/amcc/crypto4xx_core.c | 7 +- drivers/crypto/amcc/crypto4xx_core.h | 4 + drivers/crypto/amcc/crypto4xx_reg_def.h | 1 + drivers/crypto/amcc/crypto4xx_trng.c | 131 +++++++++++++++++++++ drivers/crypto/amcc/crypto4xx_trng.h | 34 ++++++ 10 files changed, 184 insertions(+), 163 deletions(-) delete mode 100644 drivers/char/hw_random/ppc4xx-rng.c create mode 100644 drivers/crypto/amcc/crypto4xx_trng.c create mode 100644 drivers/crypto/amcc/crypto4xx_trng.h diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index c76a88da8d04..ac51149e9777 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -268,19 +268,6 @@ config HW_RANDOM_NOMADIK If unsure, say Y. -config HW_RANDOM_PPC4XX - tristate "PowerPC 4xx generic true random number generator support" - depends on PPC && 4xx - default HW_RANDOM - ---help--- - This driver provides the kernel-side support for the TRNG hardware - found in the security function of some PowerPC 4xx SoCs. - - To compile this driver as a module, choose M here: the - module will be called ppc4xx-rng. - - If unsure, say N. - config HW_RANDOM_PSERIES tristate "pSeries HW Random Number Generator support" depends on PPC64 && IBMVIO diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index e09305bb89e1..63022b49f160 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o -obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c deleted file mode 100644 index c0db4387d2e2..000000000000 --- a/drivers/char/hw_random/ppc4xx-rng.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Generic PowerPC 44x RNG driver - * - * Copyright 2011 IBM Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2 of the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define PPC4XX_TRNG_DEV_CTRL 0x60080 - -#define PPC4XX_TRNGE 0x00020000 -#define PPC4XX_TRNG_CTRL 0x0008 -#define PPC4XX_TRNG_CTRL_DALM 0x20 -#define PPC4XX_TRNG_STAT 0x0004 -#define PPC4XX_TRNG_STAT_B 0x1 -#define PPC4XX_TRNG_DATA 0x0000 - -#define MODULE_NAME "ppc4xx_rng" - -static int ppc4xx_rng_data_present(struct hwrng *rng, int wait) -{ - void __iomem *rng_regs = (void __iomem *) rng->priv; - int busy, i, present = 0; - - for (i = 0; i < 20; i++) { - busy = (in_le32(rng_regs + PPC4XX_TRNG_STAT) & PPC4XX_TRNG_STAT_B); - if (!busy || !wait) { - present = 1; - break; - } - udelay(10); - } - return present; -} - -static int ppc4xx_rng_data_read(struct hwrng *rng, u32 *data) -{ - void __iomem *rng_regs = (void __iomem *) rng->priv; - *data = in_le32(rng_regs + PPC4XX_TRNG_DATA); - return 4; -} - -static int ppc4xx_rng_enable(int enable) -{ - struct device_node *ctrl; - void __iomem *ctrl_reg; - int err = 0; - u32 val; - - /* Find the main crypto device node and map it to turn the TRNG on */ - ctrl = of_find_compatible_node(NULL, NULL, "amcc,ppc4xx-crypto"); - if (!ctrl) - return -ENODEV; - - ctrl_reg = of_iomap(ctrl, 0); - if (!ctrl_reg) { - err = -ENODEV; - goto out; - } - - val = in_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL); - - if (enable) - val |= PPC4XX_TRNGE; - else - val = val & ~PPC4XX_TRNGE; - - out_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL, val); - iounmap(ctrl_reg); - -out: - of_node_put(ctrl); - - return err; -} - -static struct hwrng ppc4xx_rng = { - .name = MODULE_NAME, - .data_present = ppc4xx_rng_data_present, - .data_read = ppc4xx_rng_data_read, -}; - -static int ppc4xx_rng_probe(struct platform_device *dev) -{ - void __iomem *rng_regs; - int err = 0; - - rng_regs = of_iomap(dev->dev.of_node, 0); - if (!rng_regs) - return -ENODEV; - - err = ppc4xx_rng_enable(1); - if (err) - return err; - - out_le32(rng_regs + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM); - ppc4xx_rng.priv = (unsigned long) rng_regs; - - err = hwrng_register(&ppc4xx_rng); - - return err; -} - -static int ppc4xx_rng_remove(struct platform_device *dev) -{ - void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv; - - hwrng_unregister(&ppc4xx_rng); - ppc4xx_rng_enable(0); - iounmap(rng_regs); - - return 0; -} - -static const struct of_device_id ppc4xx_rng_match[] = { - { .compatible = "ppc4xx-rng", }, - { .compatible = "amcc,ppc460ex-rng", }, - { .compatible = "amcc,ppc440epx-rng", }, - {}, -}; -MODULE_DEVICE_TABLE(of, ppc4xx_rng_match); - -static struct platform_driver ppc4xx_rng_driver = { - .driver = { - .name = MODULE_NAME, - .of_match_table = ppc4xx_rng_match, - }, - .probe = ppc4xx_rng_probe, - .remove = ppc4xx_rng_remove, -}; - -module_platform_driver(ppc4xx_rng_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Josh Boyer "); -MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors"); diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 0a22ac7db360..12fd49950f47 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -279,6 +279,14 @@ config CRYPTO_DEV_PPC4XX help This option allows you to have support for AMCC crypto acceleration. +config HW_RANDOM_PPC4XX + bool "PowerPC 4xx generic true random number generator support" + depends on CRYPTO_DEV_PPC4XX && HW_RANDOM + default y + ---help--- + This option provides the kernel-side support for the TRNG hardware + found in the security function of some PowerPC 4xx SoCs. + config CRYPTO_DEV_OMAP_SHAM tristate "Support for OMAP MD5/SHA1/SHA2 hw accelerator" depends on ARCH_OMAP2PLUS diff --git a/drivers/crypto/amcc/Makefile b/drivers/crypto/amcc/Makefile index 5c0c62b65d69..b95539928fdf 100644 --- a/drivers/crypto/amcc/Makefile +++ b/drivers/crypto/amcc/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o crypto4xx-y := crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o +crypto4xx-$(CONFIG_HW_RANDOM_PPC4XX) += crypto4xx_trng.o diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 62134c8a2260..dae1e39139e9 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -40,6 +40,7 @@ #include "crypto4xx_reg_def.h" #include "crypto4xx_core.h" #include "crypto4xx_sa.h" +#include "crypto4xx_trng.h" #define PPC4XX_SEC_VERSION_STR "0.5" @@ -1225,6 +1226,7 @@ static int crypto4xx_probe(struct platform_device *ofdev) if (rc) goto err_start_dev; + ppc4xx_trng_probe(core_dev); return 0; err_start_dev: @@ -1252,6 +1254,8 @@ static int crypto4xx_remove(struct platform_device *ofdev) struct device *dev = &ofdev->dev; struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); + ppc4xx_trng_remove(core_dev); + free_irq(core_dev->irq, dev); irq_dispose_mapping(core_dev->irq); @@ -1272,7 +1276,7 @@ MODULE_DEVICE_TABLE(of, crypto4xx_match); static struct platform_driver crypto4xx_driver = { .driver = { - .name = "crypto4xx", + .name = MODULE_NAME, .of_match_table = crypto4xx_match, }, .probe = crypto4xx_probe, @@ -1284,4 +1288,3 @@ module_platform_driver(crypto4xx_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("James Hsiao "); MODULE_DESCRIPTION("Driver for AMCC PPC4xx crypto accelerator"); - diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h index bac0bdeb4b5f..ecfdcfe3698d 100644 --- a/drivers/crypto/amcc/crypto4xx_core.h +++ b/drivers/crypto/amcc/crypto4xx_core.h @@ -24,6 +24,8 @@ #include +#define MODULE_NAME "crypto4xx" + #define PPC460SX_SDR0_SRST 0x201 #define PPC405EX_SDR0_SRST 0x200 #define PPC460EX_SDR0_SRST 0x201 @@ -72,6 +74,7 @@ struct crypto4xx_device { char *name; u64 ce_phy_address; void __iomem *ce_base; + void __iomem *trng_base; void *pdr; /* base address of packet descriptor ring */ @@ -106,6 +109,7 @@ struct crypto4xx_core_device { struct device *device; struct platform_device *ofdev; struct crypto4xx_device *dev; + struct hwrng *trng; u32 int_status; u32 irq; struct tasklet_struct tasklet; diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h index 5f5fbc0716ff..46fe57c8f6eb 100644 --- a/drivers/crypto/amcc/crypto4xx_reg_def.h +++ b/drivers/crypto/amcc/crypto4xx_reg_def.h @@ -125,6 +125,7 @@ #define PPC4XX_INTERRUPT_CLR 0x3ffff #define PPC4XX_PRNG_CTRL_AUTO_EN 0x3 #define PPC4XX_DC_3DES_EN 1 +#define PPC4XX_TRNG_EN 0x00020000 #define PPC4XX_INT_DESCR_CNT 4 #define PPC4XX_INT_TIMEOUT_CNT 0 #define PPC4XX_INT_CFG 1 diff --git a/drivers/crypto/amcc/crypto4xx_trng.c b/drivers/crypto/amcc/crypto4xx_trng.c new file mode 100644 index 000000000000..677ca17fd223 --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_trng.c @@ -0,0 +1,131 @@ +/* + * Generic PowerPC 44x RNG driver + * + * Copyright 2011 IBM Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crypto4xx_core.h" +#include "crypto4xx_trng.h" +#include "crypto4xx_reg_def.h" + +#define PPC4XX_TRNG_CTRL 0x0008 +#define PPC4XX_TRNG_CTRL_DALM 0x20 +#define PPC4XX_TRNG_STAT 0x0004 +#define PPC4XX_TRNG_STAT_B 0x1 +#define PPC4XX_TRNG_DATA 0x0000 + +static int ppc4xx_trng_data_present(struct hwrng *rng, int wait) +{ + struct crypto4xx_device *dev = (void *)rng->priv; + int busy, i, present = 0; + + for (i = 0; i < 20; i++) { + busy = (in_le32(dev->trng_base + PPC4XX_TRNG_STAT) & + PPC4XX_TRNG_STAT_B); + if (!busy || !wait) { + present = 1; + break; + } + udelay(10); + } + return present; +} + +static int ppc4xx_trng_data_read(struct hwrng *rng, u32 *data) +{ + struct crypto4xx_device *dev = (void *)rng->priv; + *data = in_le32(dev->trng_base + PPC4XX_TRNG_DATA); + return 4; +} + +static void ppc4xx_trng_enable(struct crypto4xx_device *dev, bool enable) +{ + u32 device_ctrl; + + device_ctrl = readl(dev->ce_base + CRYPTO4XX_DEVICE_CTRL); + if (enable) + device_ctrl |= PPC4XX_TRNG_EN; + else + device_ctrl &= ~PPC4XX_TRNG_EN; + writel(device_ctrl, dev->ce_base + CRYPTO4XX_DEVICE_CTRL); +} + +static const struct of_device_id ppc4xx_trng_match[] = { + { .compatible = "ppc4xx-rng", }, + { .compatible = "amcc,ppc460ex-rng", }, + { .compatible = "amcc,ppc440epx-rng", }, + {}, +}; + +void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev) +{ + struct crypto4xx_device *dev = core_dev->dev; + struct device_node *trng = NULL; + struct hwrng *rng = NULL; + int err; + + /* Find the TRNG device node and map it */ + trng = of_find_matching_node(NULL, ppc4xx_trng_match); + if (!trng || !of_device_is_available(trng)) + return; + + dev->trng_base = of_iomap(trng, 0); + of_node_put(trng); + if (!dev->trng_base) + goto err_out; + + rng = kzalloc(sizeof(*rng), GFP_KERNEL); + if (!rng) + goto err_out; + + rng->name = MODULE_NAME; + rng->data_present = ppc4xx_trng_data_present; + rng->data_read = ppc4xx_trng_data_read; + rng->priv = (unsigned long) dev; + core_dev->trng = rng; + ppc4xx_trng_enable(dev, true); + out_le32(dev->trng_base + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM); + err = devm_hwrng_register(core_dev->device, core_dev->trng); + if (err) { + ppc4xx_trng_enable(dev, false); + dev_err(core_dev->device, "failed to register hwrng (%d).\n", + err); + goto err_out; + } + return; + +err_out: + of_node_put(trng); + iounmap(dev->trng_base); + kfree(rng); + dev->trng_base = NULL; + core_dev->trng = NULL; +} + +void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev) +{ + if (core_dev && core_dev->trng) { + struct crypto4xx_device *dev = core_dev->dev; + + devm_hwrng_unregister(core_dev->device, core_dev->trng); + ppc4xx_trng_enable(dev, false); + iounmap(dev->trng_base); + kfree(core_dev->trng); + } +} + +MODULE_ALIAS("ppc4xx_rng"); diff --git a/drivers/crypto/amcc/crypto4xx_trng.h b/drivers/crypto/amcc/crypto4xx_trng.h new file mode 100644 index 000000000000..931d22531f51 --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_trng.h @@ -0,0 +1,34 @@ +/** + * AMCC SoC PPC4xx Crypto Driver + * + * Copyright (c) 2008 Applied Micro Circuits Corporation. + * All rights reserved. James Hsiao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file defines the security context + * associate format. + */ + +#ifndef __CRYPTO4XX_TRNG_H__ +#define __CRYPTO4XX_TRNG_H__ + +#ifdef CONFIG_HW_RANDOM_PPC4XX +void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev); +void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev); +#else +static inline void ppc4xx_trng_probe( + struct crypto4xx_device *dev __maybe_unused) { } +static inline void ppc4xx_trng_remove( + struct crypto4xx_device *dev __maybe_unused) { } +#endif + +#endif -- GitLab From 58ea8abf490415c390e0cc671e875510c9b66318 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Mon, 18 Apr 2016 09:21:44 -0500 Subject: [PATCH 3648/9938] crypto: ccp - Register the CCP as a DMA resource The CCP has the ability to provide DMA services to the kernel using pass-through mode of the device. Register these services as general purpose DMA channels. Changes since v2: - Add a Signed-off-by Changes since v1: - Allocate memory for a string in ccp_dmaengine_register - Ensure register/unregister calls are properly ordered - Verified all changed files are listed in the diffstat - Undo some superfluous changes - Added a cc: Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/Kconfig | 1 + drivers/crypto/ccp/Makefile | 6 +- drivers/crypto/ccp/ccp-dev-v3.c | 11 + drivers/crypto/ccp/ccp-dev.h | 47 ++ drivers/crypto/ccp/ccp-dmaengine.c | 727 +++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-ops.c | 69 ++- include/linux/ccp.h | 36 +- 7 files changed, 893 insertions(+), 4 deletions(-) create mode 100644 drivers/crypto/ccp/ccp-dmaengine.c diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig index 6e37845abf8f..79cabfba2a2a 100644 --- a/drivers/crypto/ccp/Kconfig +++ b/drivers/crypto/ccp/Kconfig @@ -3,6 +3,7 @@ config CRYPTO_DEV_CCP_DD depends on CRYPTO_DEV_CCP default m select HW_RANDOM + select DMA_ENGINE select CRYPTO_SHA1 select CRYPTO_SHA256 help diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile index b750592cc936..ee4d2741b3ab 100644 --- a/drivers/crypto/ccp/Makefile +++ b/drivers/crypto/ccp/Makefile @@ -1,5 +1,9 @@ obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o -ccp-objs := ccp-dev.o ccp-ops.o ccp-dev-v3.o ccp-platform.o +ccp-objs := ccp-dev.o \ + ccp-ops.o \ + ccp-dev-v3.o \ + ccp-platform.o \ + ccp-dmaengine.o ccp-$(CONFIG_PCI) += ccp-pci.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c index 7d5eab49179e..597fc50bdaa6 100644 --- a/drivers/crypto/ccp/ccp-dev-v3.c +++ b/drivers/crypto/ccp/ccp-dev-v3.c @@ -406,6 +406,11 @@ static int ccp_init(struct ccp_device *ccp) goto e_kthread; } + /* Register the DMA engine support */ + ret = ccp_dmaengine_register(ccp); + if (ret) + goto e_hwrng; + ccp_add_device(ccp); /* Enable interrupts */ @@ -413,6 +418,9 @@ static int ccp_init(struct ccp_device *ccp) return 0; +e_hwrng: + hwrng_unregister(&ccp->hwrng); + e_kthread: for (i = 0; i < ccp->cmd_q_count; i++) if (ccp->cmd_q[i].kthread) @@ -436,6 +444,9 @@ static void ccp_destroy(struct ccp_device *ccp) /* Remove this device from the list of available units first */ ccp_del_device(ccp); + /* Unregister the DMA engine */ + ccp_dmaengine_unregister(ccp); + /* Unregister the RNG */ hwrng_unregister(&ccp->hwrng); diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index 7745d0be491d..5d986c9d72eb 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #define MAX_CCP_NAME_LEN 16 #define MAX_DMAPOOL_NAME_LEN 32 @@ -167,6 +170,39 @@ extern struct ccp_vdata ccpv3; struct ccp_device; struct ccp_cmd; +struct ccp_dma_cmd { + struct list_head entry; + + struct ccp_cmd ccp_cmd; +}; + +struct ccp_dma_desc { + struct list_head entry; + + struct ccp_device *ccp; + + struct list_head pending; + struct list_head active; + + enum dma_status status; + struct dma_async_tx_descriptor tx_desc; + size_t len; +}; + +struct ccp_dma_chan { + struct ccp_device *ccp; + + spinlock_t lock; + struct list_head pending; + struct list_head active; + struct list_head complete; + + struct tasklet_struct cleanup_tasklet; + + enum dma_status status; + struct dma_chan dma_chan; +}; + struct ccp_cmd_queue { struct ccp_device *ccp; @@ -260,6 +296,14 @@ struct ccp_device { struct hwrng hwrng; unsigned int hwrng_retries; + /* + * Support for the CCP DMA capabilities + */ + struct dma_device dma_dev; + struct ccp_dma_chan *ccp_dma_chan; + struct kmem_cache *dma_cmd_cache; + struct kmem_cache *dma_desc_cache; + /* * A counter used to generate job-ids for cmds submitted to the CCP */ @@ -418,4 +462,7 @@ int ccp_cmd_queue_thread(void *data); int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd); +int ccp_dmaengine_register(struct ccp_device *ccp); +void ccp_dmaengine_unregister(struct ccp_device *ccp); + #endif diff --git a/drivers/crypto/ccp/ccp-dmaengine.c b/drivers/crypto/ccp/ccp-dmaengine.c new file mode 100644 index 000000000000..94f77b0f9ae7 --- /dev/null +++ b/drivers/crypto/ccp/ccp-dmaengine.c @@ -0,0 +1,727 @@ +/* + * AMD Cryptographic Coprocessor (CCP) driver + * + * Copyright (C) 2016 Advanced Micro Devices, Inc. + * + * Author: Gary R Hook + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include "ccp-dev.h" +#include "../../dma/dmaengine.h" + +#define CCP_DMA_WIDTH(_mask) \ +({ \ + u64 mask = _mask + 1; \ + (mask == 0) ? 64 : fls64(mask); \ +}) + +static void ccp_free_cmd_resources(struct ccp_device *ccp, + struct list_head *list) +{ + struct ccp_dma_cmd *cmd, *ctmp; + + list_for_each_entry_safe(cmd, ctmp, list, entry) { + list_del(&cmd->entry); + kmem_cache_free(ccp->dma_cmd_cache, cmd); + } +} + +static void ccp_free_desc_resources(struct ccp_device *ccp, + struct list_head *list) +{ + struct ccp_dma_desc *desc, *dtmp; + + list_for_each_entry_safe(desc, dtmp, list, entry) { + ccp_free_cmd_resources(ccp, &desc->active); + ccp_free_cmd_resources(ccp, &desc->pending); + + list_del(&desc->entry); + kmem_cache_free(ccp->dma_desc_cache, desc); + } +} + +static void ccp_free_chan_resources(struct dma_chan *dma_chan) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + unsigned long flags; + + dev_dbg(chan->ccp->dev, "%s - chan=%p\n", __func__, chan); + + spin_lock_irqsave(&chan->lock, flags); + + ccp_free_desc_resources(chan->ccp, &chan->complete); + ccp_free_desc_resources(chan->ccp, &chan->active); + ccp_free_desc_resources(chan->ccp, &chan->pending); + + spin_unlock_irqrestore(&chan->lock, flags); +} + +static void ccp_cleanup_desc_resources(struct ccp_device *ccp, + struct list_head *list) +{ + struct ccp_dma_desc *desc, *dtmp; + + list_for_each_entry_safe_reverse(desc, dtmp, list, entry) { + if (!async_tx_test_ack(&desc->tx_desc)) + continue; + + dev_dbg(ccp->dev, "%s - desc=%p\n", __func__, desc); + + ccp_free_cmd_resources(ccp, &desc->active); + ccp_free_cmd_resources(ccp, &desc->pending); + + list_del(&desc->entry); + kmem_cache_free(ccp->dma_desc_cache, desc); + } +} + +static void ccp_do_cleanup(unsigned long data) +{ + struct ccp_dma_chan *chan = (struct ccp_dma_chan *)data; + unsigned long flags; + + dev_dbg(chan->ccp->dev, "%s - chan=%s\n", __func__, + dma_chan_name(&chan->dma_chan)); + + spin_lock_irqsave(&chan->lock, flags); + + ccp_cleanup_desc_resources(chan->ccp, &chan->complete); + + spin_unlock_irqrestore(&chan->lock, flags); +} + +static int ccp_issue_next_cmd(struct ccp_dma_desc *desc) +{ + struct ccp_dma_cmd *cmd; + int ret; + + cmd = list_first_entry(&desc->pending, struct ccp_dma_cmd, entry); + list_move(&cmd->entry, &desc->active); + + dev_dbg(desc->ccp->dev, "%s - tx %d, cmd=%p\n", __func__, + desc->tx_desc.cookie, cmd); + + ret = ccp_enqueue_cmd(&cmd->ccp_cmd); + if (!ret || (ret == -EINPROGRESS) || (ret == -EBUSY)) + return 0; + + dev_dbg(desc->ccp->dev, "%s - error: ret=%d, tx %d, cmd=%p\n", __func__, + ret, desc->tx_desc.cookie, cmd); + + return ret; +} + +static void ccp_free_active_cmd(struct ccp_dma_desc *desc) +{ + struct ccp_dma_cmd *cmd; + + cmd = list_first_entry_or_null(&desc->active, struct ccp_dma_cmd, + entry); + if (!cmd) + return; + + dev_dbg(desc->ccp->dev, "%s - freeing tx %d cmd=%p\n", + __func__, desc->tx_desc.cookie, cmd); + + list_del(&cmd->entry); + kmem_cache_free(desc->ccp->dma_cmd_cache, cmd); +} + +static struct ccp_dma_desc *__ccp_next_dma_desc(struct ccp_dma_chan *chan, + struct ccp_dma_desc *desc) +{ + /* Move current DMA descriptor to the complete list */ + if (desc) + list_move(&desc->entry, &chan->complete); + + /* Get the next DMA descriptor on the active list */ + desc = list_first_entry_or_null(&chan->active, struct ccp_dma_desc, + entry); + + return desc; +} + +static struct ccp_dma_desc *ccp_handle_active_desc(struct ccp_dma_chan *chan, + struct ccp_dma_desc *desc) +{ + struct dma_async_tx_descriptor *tx_desc; + unsigned long flags; + + /* Loop over descriptors until one is found with commands */ + do { + if (desc) { + /* Remove the DMA command from the list and free it */ + ccp_free_active_cmd(desc); + + if (!list_empty(&desc->pending)) { + /* No errors, keep going */ + if (desc->status != DMA_ERROR) + return desc; + + /* Error, free remaining commands and move on */ + ccp_free_cmd_resources(desc->ccp, + &desc->pending); + } + + tx_desc = &desc->tx_desc; + } else { + tx_desc = NULL; + } + + spin_lock_irqsave(&chan->lock, flags); + + if (desc) { + if (desc->status != DMA_ERROR) + desc->status = DMA_COMPLETE; + + dev_dbg(desc->ccp->dev, + "%s - tx %d complete, status=%u\n", __func__, + desc->tx_desc.cookie, desc->status); + + dma_cookie_complete(tx_desc); + } + + desc = __ccp_next_dma_desc(chan, desc); + + spin_unlock_irqrestore(&chan->lock, flags); + + if (tx_desc) { + if (tx_desc->callback && + (tx_desc->flags & DMA_PREP_INTERRUPT)) + tx_desc->callback(tx_desc->callback_param); + + dma_run_dependencies(tx_desc); + } + } while (desc); + + return NULL; +} + +static struct ccp_dma_desc *__ccp_pending_to_active(struct ccp_dma_chan *chan) +{ + struct ccp_dma_desc *desc; + + if (list_empty(&chan->pending)) + return NULL; + + desc = list_empty(&chan->active) + ? list_first_entry(&chan->pending, struct ccp_dma_desc, entry) + : NULL; + + list_splice_tail_init(&chan->pending, &chan->active); + + return desc; +} + +static void ccp_cmd_callback(void *data, int err) +{ + struct ccp_dma_desc *desc = data; + struct ccp_dma_chan *chan; + int ret; + + if (err == -EINPROGRESS) + return; + + chan = container_of(desc->tx_desc.chan, struct ccp_dma_chan, + dma_chan); + + dev_dbg(chan->ccp->dev, "%s - tx %d callback, err=%d\n", + __func__, desc->tx_desc.cookie, err); + + if (err) + desc->status = DMA_ERROR; + + while (true) { + /* Check for DMA descriptor completion */ + desc = ccp_handle_active_desc(chan, desc); + + /* Don't submit cmd if no descriptor or DMA is paused */ + if (!desc || (chan->status == DMA_PAUSED)) + break; + + ret = ccp_issue_next_cmd(desc); + if (!ret) + break; + + desc->status = DMA_ERROR; + } + + tasklet_schedule(&chan->cleanup_tasklet); +} + +static dma_cookie_t ccp_tx_submit(struct dma_async_tx_descriptor *tx_desc) +{ + struct ccp_dma_desc *desc = container_of(tx_desc, struct ccp_dma_desc, + tx_desc); + struct ccp_dma_chan *chan; + dma_cookie_t cookie; + unsigned long flags; + + chan = container_of(tx_desc->chan, struct ccp_dma_chan, dma_chan); + + spin_lock_irqsave(&chan->lock, flags); + + cookie = dma_cookie_assign(tx_desc); + list_add_tail(&desc->entry, &chan->pending); + + spin_unlock_irqrestore(&chan->lock, flags); + + dev_dbg(chan->ccp->dev, "%s - added tx descriptor %d to pending list\n", + __func__, cookie); + + return cookie; +} + +static struct ccp_dma_cmd *ccp_alloc_dma_cmd(struct ccp_dma_chan *chan) +{ + struct ccp_dma_cmd *cmd; + + cmd = kmem_cache_alloc(chan->ccp->dma_cmd_cache, GFP_NOWAIT); + if (cmd) + memset(cmd, 0, sizeof(*cmd)); + + return cmd; +} + +static struct ccp_dma_desc *ccp_alloc_dma_desc(struct ccp_dma_chan *chan, + unsigned long flags) +{ + struct ccp_dma_desc *desc; + + desc = kmem_cache_alloc(chan->ccp->dma_desc_cache, GFP_NOWAIT); + if (!desc) + return NULL; + + memset(desc, 0, sizeof(*desc)); + + dma_async_tx_descriptor_init(&desc->tx_desc, &chan->dma_chan); + desc->tx_desc.flags = flags; + desc->tx_desc.tx_submit = ccp_tx_submit; + desc->ccp = chan->ccp; + INIT_LIST_HEAD(&desc->pending); + INIT_LIST_HEAD(&desc->active); + desc->status = DMA_IN_PROGRESS; + + return desc; +} + +static struct ccp_dma_desc *ccp_create_desc(struct dma_chan *dma_chan, + struct scatterlist *dst_sg, + unsigned int dst_nents, + struct scatterlist *src_sg, + unsigned int src_nents, + unsigned long flags) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + struct ccp_device *ccp = chan->ccp; + struct ccp_dma_desc *desc; + struct ccp_dma_cmd *cmd; + struct ccp_cmd *ccp_cmd; + struct ccp_passthru_nomap_engine *ccp_pt; + unsigned int src_offset, src_len; + unsigned int dst_offset, dst_len; + unsigned int len; + unsigned long sflags; + size_t total_len; + + if (!dst_sg || !src_sg) + return NULL; + + if (!dst_nents || !src_nents) + return NULL; + + desc = ccp_alloc_dma_desc(chan, flags); + if (!desc) + return NULL; + + total_len = 0; + + src_len = sg_dma_len(src_sg); + src_offset = 0; + + dst_len = sg_dma_len(dst_sg); + dst_offset = 0; + + while (true) { + if (!src_len) { + src_nents--; + if (!src_nents) + break; + + src_sg = sg_next(src_sg); + if (!src_sg) + break; + + src_len = sg_dma_len(src_sg); + src_offset = 0; + continue; + } + + if (!dst_len) { + dst_nents--; + if (!dst_nents) + break; + + dst_sg = sg_next(dst_sg); + if (!dst_sg) + break; + + dst_len = sg_dma_len(dst_sg); + dst_offset = 0; + continue; + } + + len = min(dst_len, src_len); + + cmd = ccp_alloc_dma_cmd(chan); + if (!cmd) + goto err; + + ccp_cmd = &cmd->ccp_cmd; + ccp_pt = &ccp_cmd->u.passthru_nomap; + ccp_cmd->flags = CCP_CMD_MAY_BACKLOG; + ccp_cmd->flags |= CCP_CMD_PASSTHRU_NO_DMA_MAP; + ccp_cmd->engine = CCP_ENGINE_PASSTHRU; + ccp_pt->bit_mod = CCP_PASSTHRU_BITWISE_NOOP; + ccp_pt->byte_swap = CCP_PASSTHRU_BYTESWAP_NOOP; + ccp_pt->src_dma = sg_dma_address(src_sg) + src_offset; + ccp_pt->dst_dma = sg_dma_address(dst_sg) + dst_offset; + ccp_pt->src_len = len; + ccp_pt->final = 1; + ccp_cmd->callback = ccp_cmd_callback; + ccp_cmd->data = desc; + + list_add_tail(&cmd->entry, &desc->pending); + + dev_dbg(ccp->dev, + "%s - cmd=%p, src=%pad, dst=%pad, len=%llu\n", __func__, + cmd, &ccp_pt->src_dma, + &ccp_pt->dst_dma, ccp_pt->src_len); + + total_len += len; + + src_len -= len; + src_offset += len; + + dst_len -= len; + dst_offset += len; + } + + desc->len = total_len; + + if (list_empty(&desc->pending)) + goto err; + + dev_dbg(ccp->dev, "%s - desc=%p\n", __func__, desc); + + spin_lock_irqsave(&chan->lock, sflags); + + list_add_tail(&desc->entry, &chan->pending); + + spin_unlock_irqrestore(&chan->lock, sflags); + + return desc; + +err: + ccp_free_cmd_resources(ccp, &desc->pending); + kmem_cache_free(ccp->dma_desc_cache, desc); + + return NULL; +} + +static struct dma_async_tx_descriptor *ccp_prep_dma_memcpy( + struct dma_chan *dma_chan, dma_addr_t dst, dma_addr_t src, size_t len, + unsigned long flags) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + struct ccp_dma_desc *desc; + struct scatterlist dst_sg, src_sg; + + dev_dbg(chan->ccp->dev, + "%s - src=%pad, dst=%pad, len=%zu, flags=%#lx\n", + __func__, &src, &dst, len, flags); + + sg_init_table(&dst_sg, 1); + sg_dma_address(&dst_sg) = dst; + sg_dma_len(&dst_sg) = len; + + sg_init_table(&src_sg, 1); + sg_dma_address(&src_sg) = src; + sg_dma_len(&src_sg) = len; + + desc = ccp_create_desc(dma_chan, &dst_sg, 1, &src_sg, 1, flags); + if (!desc) + return NULL; + + return &desc->tx_desc; +} + +static struct dma_async_tx_descriptor *ccp_prep_dma_sg( + struct dma_chan *dma_chan, struct scatterlist *dst_sg, + unsigned int dst_nents, struct scatterlist *src_sg, + unsigned int src_nents, unsigned long flags) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + struct ccp_dma_desc *desc; + + dev_dbg(chan->ccp->dev, + "%s - src=%p, src_nents=%u dst=%p, dst_nents=%u, flags=%#lx\n", + __func__, src_sg, src_nents, dst_sg, dst_nents, flags); + + desc = ccp_create_desc(dma_chan, dst_sg, dst_nents, src_sg, src_nents, + flags); + if (!desc) + return NULL; + + return &desc->tx_desc; +} + +static struct dma_async_tx_descriptor *ccp_prep_dma_interrupt( + struct dma_chan *dma_chan, unsigned long flags) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + struct ccp_dma_desc *desc; + + desc = ccp_alloc_dma_desc(chan, flags); + if (!desc) + return NULL; + + return &desc->tx_desc; +} + +static void ccp_issue_pending(struct dma_chan *dma_chan) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + struct ccp_dma_desc *desc; + unsigned long flags; + + dev_dbg(chan->ccp->dev, "%s\n", __func__); + + spin_lock_irqsave(&chan->lock, flags); + + desc = __ccp_pending_to_active(chan); + + spin_unlock_irqrestore(&chan->lock, flags); + + /* If there was nothing active, start processing */ + if (desc) + ccp_cmd_callback(desc, 0); +} + +static enum dma_status ccp_tx_status(struct dma_chan *dma_chan, + dma_cookie_t cookie, + struct dma_tx_state *state) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + struct ccp_dma_desc *desc; + enum dma_status ret; + unsigned long flags; + + if (chan->status == DMA_PAUSED) { + ret = DMA_PAUSED; + goto out; + } + + ret = dma_cookie_status(dma_chan, cookie, state); + if (ret == DMA_COMPLETE) { + spin_lock_irqsave(&chan->lock, flags); + + /* Get status from complete chain, if still there */ + list_for_each_entry(desc, &chan->complete, entry) { + if (desc->tx_desc.cookie != cookie) + continue; + + ret = desc->status; + break; + } + + spin_unlock_irqrestore(&chan->lock, flags); + } + +out: + dev_dbg(chan->ccp->dev, "%s - %u\n", __func__, ret); + + return ret; +} + +static int ccp_pause(struct dma_chan *dma_chan) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + + chan->status = DMA_PAUSED; + + /*TODO: Wait for active DMA to complete before returning? */ + + return 0; +} + +static int ccp_resume(struct dma_chan *dma_chan) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + struct ccp_dma_desc *desc; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + + desc = list_first_entry_or_null(&chan->active, struct ccp_dma_desc, + entry); + + spin_unlock_irqrestore(&chan->lock, flags); + + /* Indicate the channel is running again */ + chan->status = DMA_IN_PROGRESS; + + /* If there was something active, re-start */ + if (desc) + ccp_cmd_callback(desc, 0); + + return 0; +} + +static int ccp_terminate_all(struct dma_chan *dma_chan) +{ + struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan, + dma_chan); + unsigned long flags; + + dev_dbg(chan->ccp->dev, "%s\n", __func__); + + /*TODO: Wait for active DMA to complete before continuing */ + + spin_lock_irqsave(&chan->lock, flags); + + /*TODO: Purge the complete list? */ + ccp_free_desc_resources(chan->ccp, &chan->active); + ccp_free_desc_resources(chan->ccp, &chan->pending); + + spin_unlock_irqrestore(&chan->lock, flags); + + return 0; +} + +int ccp_dmaengine_register(struct ccp_device *ccp) +{ + struct ccp_dma_chan *chan; + struct dma_device *dma_dev = &ccp->dma_dev; + struct dma_chan *dma_chan; + char *dma_cmd_cache_name; + char *dma_desc_cache_name; + unsigned int i; + int ret; + + ccp->ccp_dma_chan = devm_kcalloc(ccp->dev, ccp->cmd_q_count, + sizeof(*(ccp->ccp_dma_chan)), + GFP_KERNEL); + if (!ccp->ccp_dma_chan) + return -ENOMEM; + + dma_cmd_cache_name = devm_kasprintf(ccp->dev, GFP_KERNEL, + "%s-dmaengine-cmd-cache", + ccp->name); + if (!dma_cmd_cache_name) + return -ENOMEM; + + ccp->dma_cmd_cache = kmem_cache_create(dma_cmd_cache_name, + sizeof(struct ccp_dma_cmd), + sizeof(void *), + SLAB_HWCACHE_ALIGN, NULL); + if (!ccp->dma_cmd_cache) + return -ENOMEM; + + dma_desc_cache_name = devm_kasprintf(ccp->dev, GFP_KERNEL, + "%s-dmaengine-desc-cache", + ccp->name); + if (!dma_cmd_cache_name) + return -ENOMEM; + ccp->dma_desc_cache = kmem_cache_create(dma_desc_cache_name, + sizeof(struct ccp_dma_desc), + sizeof(void *), + SLAB_HWCACHE_ALIGN, NULL); + if (!ccp->dma_desc_cache) { + ret = -ENOMEM; + goto err_cache; + } + + dma_dev->dev = ccp->dev; + dma_dev->src_addr_widths = CCP_DMA_WIDTH(dma_get_mask(ccp->dev)); + dma_dev->dst_addr_widths = CCP_DMA_WIDTH(dma_get_mask(ccp->dev)); + dma_dev->directions = DMA_MEM_TO_MEM; + dma_dev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR; + dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask); + dma_cap_set(DMA_SG, dma_dev->cap_mask); + dma_cap_set(DMA_INTERRUPT, dma_dev->cap_mask); + + INIT_LIST_HEAD(&dma_dev->channels); + for (i = 0; i < ccp->cmd_q_count; i++) { + chan = ccp->ccp_dma_chan + i; + dma_chan = &chan->dma_chan; + + chan->ccp = ccp; + + spin_lock_init(&chan->lock); + INIT_LIST_HEAD(&chan->pending); + INIT_LIST_HEAD(&chan->active); + INIT_LIST_HEAD(&chan->complete); + + tasklet_init(&chan->cleanup_tasklet, ccp_do_cleanup, + (unsigned long)chan); + + dma_chan->device = dma_dev; + dma_cookie_init(dma_chan); + + list_add_tail(&dma_chan->device_node, &dma_dev->channels); + } + + dma_dev->device_free_chan_resources = ccp_free_chan_resources; + dma_dev->device_prep_dma_memcpy = ccp_prep_dma_memcpy; + dma_dev->device_prep_dma_sg = ccp_prep_dma_sg; + dma_dev->device_prep_dma_interrupt = ccp_prep_dma_interrupt; + dma_dev->device_issue_pending = ccp_issue_pending; + dma_dev->device_tx_status = ccp_tx_status; + dma_dev->device_pause = ccp_pause; + dma_dev->device_resume = ccp_resume; + dma_dev->device_terminate_all = ccp_terminate_all; + + ret = dma_async_device_register(dma_dev); + if (ret) + goto err_reg; + + return 0; + +err_reg: + kmem_cache_destroy(ccp->dma_desc_cache); + +err_cache: + kmem_cache_destroy(ccp->dma_cmd_cache); + + return ret; +} + +void ccp_dmaengine_unregister(struct ccp_device *ccp) +{ + struct dma_device *dma_dev = &ccp->dma_dev; + + dma_async_device_unregister(dma_dev); + + kmem_cache_destroy(ccp->dma_desc_cache); + kmem_cache_destroy(ccp->dma_cmd_cache); +} diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index eefdf595f758..ffa2891035ac 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -1427,6 +1427,70 @@ static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, return ret; } +static int ccp_run_passthru_nomap_cmd(struct ccp_cmd_queue *cmd_q, + struct ccp_cmd *cmd) +{ + struct ccp_passthru_nomap_engine *pt = &cmd->u.passthru_nomap; + struct ccp_dm_workarea mask; + struct ccp_op op; + int ret; + + if (!pt->final && (pt->src_len & (CCP_PASSTHRU_BLOCKSIZE - 1))) + return -EINVAL; + + if (!pt->src_dma || !pt->dst_dma) + return -EINVAL; + + if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) { + if (pt->mask_len != CCP_PASSTHRU_MASKSIZE) + return -EINVAL; + if (!pt->mask) + return -EINVAL; + } + + BUILD_BUG_ON(CCP_PASSTHRU_KSB_COUNT != 1); + + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + + if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) { + /* Load the mask */ + op.ksb_key = cmd_q->ksb_key; + + mask.length = pt->mask_len; + mask.dma.address = pt->mask; + mask.dma.length = pt->mask_len; + + ret = ccp_copy_to_ksb(cmd_q, &mask, op.jobid, op.ksb_key, + CCP_PASSTHRU_BYTESWAP_NOOP); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + return ret; + } + } + + /* Send data to the CCP Passthru engine */ + op.eom = 1; + op.soc = 1; + + op.src.type = CCP_MEMTYPE_SYSTEM; + op.src.u.dma.address = pt->src_dma; + op.src.u.dma.offset = 0; + op.src.u.dma.length = pt->src_len; + + op.dst.type = CCP_MEMTYPE_SYSTEM; + op.dst.u.dma.address = pt->dst_dma; + op.dst.u.dma.offset = 0; + op.dst.u.dma.length = pt->src_len; + + ret = cmd_q->ccp->vdata->perform->perform_passthru(&op); + if (ret) + cmd->engine_error = cmd_q->cmd_error; + + return ret; +} + static int ccp_run_ecc_mm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_ecc_engine *ecc = &cmd->u.ecc; @@ -1762,7 +1826,10 @@ int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) ret = ccp_run_rsa_cmd(cmd_q, cmd); break; case CCP_ENGINE_PASSTHRU: - ret = ccp_run_passthru_cmd(cmd_q, cmd); + if (cmd->flags & CCP_CMD_PASSTHRU_NO_DMA_MAP) + ret = ccp_run_passthru_nomap_cmd(cmd_q, cmd); + else + ret = ccp_run_passthru_cmd(cmd_q, cmd); break; case CCP_ENGINE_ECC: ret = ccp_run_ecc_cmd(cmd_q, cmd); diff --git a/include/linux/ccp.h b/include/linux/ccp.h index 915af3095b39..7c2bb27c067c 100644 --- a/include/linux/ccp.h +++ b/include/linux/ccp.h @@ -1,9 +1,10 @@ /* * AMD Cryptographic Coprocessor (CCP) driver * - * Copyright (C) 2013 Advanced Micro Devices, Inc. + * Copyright (C) 2013,2016 Advanced Micro Devices, Inc. * * Author: Tom Lendacky + * Author: Gary R Hook * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -381,6 +382,35 @@ struct ccp_passthru_engine { u32 final; }; +/** + * struct ccp_passthru_nomap_engine - CCP pass-through operation + * without performing DMA mapping + * @bit_mod: bitwise operation to perform + * @byte_swap: byteswap operation to perform + * @mask: mask to be applied to data + * @mask_len: length in bytes of mask + * @src: data to be used for this operation + * @dst: data produced by this operation + * @src_len: length in bytes of data used for this operation + * @final: indicate final pass-through operation + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - bit_mod, byte_swap, src, dst, src_len + * - mask, mask_len if bit_mod is not CCP_PASSTHRU_BITWISE_NOOP + */ +struct ccp_passthru_nomap_engine { + enum ccp_passthru_bitwise bit_mod; + enum ccp_passthru_byteswap byte_swap; + + dma_addr_t mask; + u32 mask_len; /* In bytes */ + + dma_addr_t src_dma, dst_dma; + u64 src_len; /* In bytes */ + + u32 final; +}; + /***** ECC engine *****/ #define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */ #define CCP_ECC_MAX_OPERANDS 6 @@ -522,7 +552,8 @@ enum ccp_engine { }; /* Flag values for flags member of ccp_cmd */ -#define CCP_CMD_MAY_BACKLOG 0x00000001 +#define CCP_CMD_MAY_BACKLOG 0x00000001 +#define CCP_CMD_PASSTHRU_NO_DMA_MAP 0x00000002 /** * struct ccp_cmd - CPP operation request @@ -562,6 +593,7 @@ struct ccp_cmd { struct ccp_sha_engine sha; struct ccp_rsa_engine rsa; struct ccp_passthru_engine passthru; + struct ccp_passthru_nomap_engine passthru_nomap; struct ccp_ecc_engine ecc; } u; -- GitLab From 07c8fccbf7fd6adf896db380c5a32c66a5b32aca Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 19 Apr 2016 15:44:11 +0200 Subject: [PATCH 3649/9938] crypto: s5p-sss - Fix use after free of copied input buffer in error path The driver makes copies of memory (input or output scatterlists) if they are not aligned. In s5p_aes_crypt_start() error path (on unsuccessful initialization of output scatterlist), if input scatterlist was not aligned, the driver first freed copied input memory and then unmapped it from the device, instead of doing otherwise (unmap and then free). This was wrong in two ways: 1. Freed pages were still mapped to the device. 2. The dma_unmap_sg() iterated over freed scatterlist structure. The call to s5p_free_sg_cpy() in this error path is not needed because the copied scatterlists will be freed by s5p_aes_complete(). Fixes: 9e4a1100a445 ("crypto: s5p-sss - Handle unaligned buffers") Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 4f6d5b3ec418..b0484d4d68d9 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -577,7 +577,6 @@ static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) return; outdata_error: - s5p_free_sg_cpy(dev, &dev->sg_src_cpy); s5p_unset_indata(dev); indata_error: -- GitLab From 5512442553bbe8d4fcdba3e17b30f187706384a7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 19 Apr 2016 15:44:12 +0200 Subject: [PATCH 3650/9938] crypto: s5p-sss - Remove useless hash interrupt handler Beside regular feed control interrupt, the driver requires also hash interrupt for older SoCs (samsung,s5pv210-secss). However after requesting it, the interrupt handler isn't doing anything with it, not even clearing the hash interrupt bit. Driver does not provide hash functions so it is safe to remove the hash interrupt related code and to not require the interrupt in Device Tree. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- .../bindings/crypto/samsung-sss.txt | 6 ++-- drivers/crypto/s5p-sss.c | 34 ++++--------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/Documentation/devicetree/bindings/crypto/samsung-sss.txt b/Documentation/devicetree/bindings/crypto/samsung-sss.txt index a6dafa83c6df..7a5ca56683cc 100644 --- a/Documentation/devicetree/bindings/crypto/samsung-sss.txt +++ b/Documentation/devicetree/bindings/crypto/samsung-sss.txt @@ -23,10 +23,8 @@ Required properties: - "samsung,exynos4210-secss" for Exynos4210, Exynos4212, Exynos4412, Exynos5250, Exynos5260 and Exynos5420 SoCs. - reg : Offset and length of the register set for the module -- interrupts : interrupt specifiers of SSS module interrupts, should contain - following entries: - - first : feed control interrupt (required for all variants), - - second : hash interrupt (required only for samsung,s5pv210-secss). +- interrupts : interrupt specifiers of SSS module interrupts (one feed + control interrupt). - clocks : list of clock phandle and specifier pairs for all clocks listed in clock-names property. diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index b0484d4d68d9..71ca6a5d636d 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -149,7 +149,6 @@ /** * struct samsung_aes_variant - platform specific SSS driver data - * @has_hash_irq: true if SSS module uses hash interrupt, false otherwise * @aes_offset: AES register offset from SSS module's base. * * Specifies platform specific configuration of SSS module. @@ -157,7 +156,6 @@ * expansion of its usage. */ struct samsung_aes_variant { - bool has_hash_irq; unsigned int aes_offset; }; @@ -178,7 +176,6 @@ struct s5p_aes_dev { struct clk *clk; void __iomem *ioaddr; void __iomem *aes_ioaddr; - int irq_hash; int irq_fc; struct ablkcipher_request *req; @@ -201,12 +198,10 @@ struct s5p_aes_dev { static struct s5p_aes_dev *s5p_dev; static const struct samsung_aes_variant s5p_aes_data = { - .has_hash_irq = true, .aes_offset = 0x4000, }; static const struct samsung_aes_variant exynos_aes_data = { - .has_hash_irq = false, .aes_offset = 0x200, }; @@ -421,15 +416,13 @@ static irqreturn_t s5p_aes_interrupt(int irq, void *dev_id) spin_lock_irqsave(&dev->lock, flags); - if (irq == dev->irq_fc) { - status = SSS_READ(dev, FCINTSTAT); - if (status & SSS_FCINTSTAT_BRDMAINT) - s5p_aes_rx(dev); - if (status & SSS_FCINTSTAT_BTDMAINT) - s5p_aes_tx(dev); + status = SSS_READ(dev, FCINTSTAT); + if (status & SSS_FCINTSTAT_BRDMAINT) + s5p_aes_rx(dev); + if (status & SSS_FCINTSTAT_BTDMAINT) + s5p_aes_tx(dev); - SSS_WRITE(dev, FCINTPEND, status); - } + SSS_WRITE(dev, FCINTPEND, status); spin_unlock_irqrestore(&dev->lock, flags); @@ -795,21 +788,6 @@ static int s5p_aes_probe(struct platform_device *pdev) goto err_irq; } - if (variant->has_hash_irq) { - pdata->irq_hash = platform_get_irq(pdev, 1); - if (pdata->irq_hash < 0) { - err = pdata->irq_hash; - dev_warn(dev, "hash interrupt is not available.\n"); - goto err_irq; - } - err = devm_request_irq(dev, pdata->irq_hash, s5p_aes_interrupt, - IRQF_SHARED, pdev->name, pdev); - if (err < 0) { - dev_warn(dev, "hash interrupt is not available.\n"); - goto err_irq; - } - } - pdata->busy = false; pdata->variant = variant; pdata->dev = dev; -- GitLab From 21ec757d2dd8650f978d27ad53cb1fcca8bb5e2b Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Tue, 19 Apr 2016 17:09:20 +0200 Subject: [PATCH 3651/9938] crypto: marvell/cesa - Improving code readability When looking for available engines, the variable "engine" is assigned to "&cesa->engines[i]" at the beginning of the for loop. Replacing next occurences of "&cesa->engines[i]" by "engine" and in order to improve readability. Signed-off-by: Romain Perier Acked-by: Boris Brezillon Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c index 80239ae69527..e8ef9fd24a16 100644 --- a/drivers/crypto/marvell/cesa.c +++ b/drivers/crypto/marvell/cesa.c @@ -475,18 +475,18 @@ static int mv_cesa_probe(struct platform_device *pdev) engine->regs = cesa->regs + CESA_ENGINE_OFF(i); if (dram && cesa->caps->has_tdma) - mv_cesa_conf_mbus_windows(&cesa->engines[i], dram); + mv_cesa_conf_mbus_windows(engine, dram); - writel(0, cesa->engines[i].regs + CESA_SA_INT_STATUS); + writel(0, engine->regs + CESA_SA_INT_STATUS); writel(CESA_SA_CFG_STOP_DIG_ERR, - cesa->engines[i].regs + CESA_SA_CFG); + engine->regs + CESA_SA_CFG); writel(engine->sram_dma & CESA_SA_SRAM_MSK, - cesa->engines[i].regs + CESA_SA_DESC_P0); + engine->regs + CESA_SA_DESC_P0); ret = devm_request_threaded_irq(dev, irq, NULL, mv_cesa_int, IRQF_ONESHOT, dev_name(&pdev->dev), - &cesa->engines[i]); + engine); if (ret) goto err_cleanup; } -- GitLab From 5e39cf49729b910795daa0b86052463d23c0a18d Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Wed, 20 Apr 2016 10:01:07 +0200 Subject: [PATCH 3652/9938] regulator: fan53555: Add support for FAN53555BUC18X type FAN53555BUC18X has the DIE_ID 8, starts at 600mV and increments in 10mV steps. Signed-off-by: Wadim Egorov Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 2cb5cc311610..d4bfa9312724 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -65,6 +65,7 @@ enum { FAN53555_CHIP_ID_03, FAN53555_CHIP_ID_04, FAN53555_CHIP_ID_05, + FAN53555_CHIP_ID_08 = 8, }; enum { @@ -220,6 +221,7 @@ static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) case FAN53555_CHIP_ID_01: case FAN53555_CHIP_ID_03: case FAN53555_CHIP_ID_05: + case FAN53555_CHIP_ID_08: di->vsel_min = 600000; di->vsel_step = 10000; break; -- GitLab From e57cbb70b7b3773f78fc6b8b70ab1eb3367e5350 Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Wed, 20 Apr 2016 10:01:08 +0200 Subject: [PATCH 3653/9938] regulator: fan53555: Add support for FAN53555UC13X type IC type options 00, 13 and 23 are sharing the same DIE_ID 0. Let's differentiate between these revisions. FAN53555UC13X has the ID 0 and REV 0xf, starts at 800mV and increments in 10mV steps. Signed-off-by: Wadim Egorov Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index d4bfa9312724..d7da81a875cf 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -68,6 +68,12 @@ enum { FAN53555_CHIP_ID_08 = 8, }; +/* IC mask revision */ +enum { + FAN53555_CHIP_REV_00 = 0x3, + FAN53555_CHIP_REV_13 = 0xf, +}; + enum { SILERGY_SYR82X = 8, }; @@ -218,6 +224,22 @@ static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) /* Init voltage range and step */ switch (di->chip_id) { case FAN53555_CHIP_ID_00: + switch (di->chip_rev) { + case FAN53555_CHIP_REV_00: + di->vsel_min = 600000; + di->vsel_step = 10000; + break; + case FAN53555_CHIP_REV_13: + di->vsel_min = 800000; + di->vsel_step = 10000; + break; + default: + dev_err(di->dev, + "Chip ID %d with rev %d not supported!\n", + di->chip_id, di->chip_rev); + return -EINVAL; + } + break; case FAN53555_CHIP_ID_01: case FAN53555_CHIP_ID_03: case FAN53555_CHIP_ID_05: -- GitLab From e16cb8c23b51faf23a120feac149e10423b2e37d Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:05 +0100 Subject: [PATCH 3654/9938] dt-bindings: ARM: Mediatek: add MT2701/7623 string to the PMIC wrapper doc Signed-off-by: John Crispin Acked-by: Rob Herring Cc: devicetree@vger.kernel.org Signed-off-by: Matthias Brugger --- Documentation/devicetree/bindings/soc/mediatek/pwrap.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt index ddeb5b6a53c1..107700d00df4 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt +++ b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt @@ -18,6 +18,7 @@ IP Pairing Required properties in pwrap device node. - compatible: + "mediatek,mt2701-pwrap" for MT2701/7623 SoCs "mediatek,mt8135-pwrap" for MT8135 SoCs "mediatek,mt8173-pwrap" for MT8173 SoCs - interrupts: IRQ for pwrap in SOC -- GitLab From 9bebedb054f98b70c798423cba6d9ba903b27d63 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:06 +0100 Subject: [PATCH 3655/9938] soc: mediatek: PMIC wrap: don't duplicate the wrapper data As we add support for more devices struct pmic_wrapper_type will grow and we do not really want to start duplicating all the elements in struct pmic_wrapper. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 0d9b19a78d27..340c4b520da1 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -376,9 +376,7 @@ struct pmic_wrapper { struct device *dev; void __iomem *base; struct regmap *regmap; - int *regs; - enum pwrap_type type; - u32 arb_en_all; + const struct pmic_wrapper_type *master; struct clk *clk_spi; struct clk *clk_wrap; struct reset_control *rstc; @@ -389,22 +387,22 @@ struct pmic_wrapper { static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp) { - return wrp->type == PWRAP_MT8135; + return wrp->master->type == PWRAP_MT8135; } static inline int pwrap_is_mt8173(struct pmic_wrapper *wrp) { - return wrp->type == PWRAP_MT8173; + return wrp->master->type == PWRAP_MT8173; } static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg) { - return readl(wrp->base + wrp->regs[reg]); + return readl(wrp->base + wrp->master->regs[reg]); } static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg) { - writel(val, wrp->base + wrp->regs[reg]); + writel(val, wrp->base + wrp->master->regs[reg]); } static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp) @@ -697,7 +695,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_WRAP_EN); - pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN); + pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); pwrap_writel(wrp, 1, PWRAP_WACS2_EN); @@ -742,7 +740,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR); - pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN); + pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); if (pwrap_is_mt8135(wrp)) pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN); @@ -836,7 +834,6 @@ static int pwrap_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_id = of_match_device(of_pwrap_match_tbl, &pdev->dev); - const struct pmic_wrapper_type *type; struct resource *res; wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL); @@ -845,10 +842,7 @@ static int pwrap_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wrp); - type = of_id->data; - wrp->regs = type->regs; - wrp->type = type->type; - wrp->arb_en_all = type->arb_en_all; + wrp->master = of_id->data; wrp->dev = &pdev->dev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap"); -- GitLab From a397845338af260658f55b2ba73834940244cf6d Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:07 +0100 Subject: [PATCH 3656/9938] soc: mediatek: PMIC wrap: add wrapper callbacks for init_reg_clock Split init_reg_clock up into SoC specific callbacks. The patch also reorders the code to avoid the need for callback function prototypes. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 70 +++++++++++++++------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 340c4b520da1..b22b664b155b 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -354,24 +354,6 @@ enum pwrap_type { PWRAP_MT8173, }; -struct pmic_wrapper_type { - int *regs; - enum pwrap_type type; - u32 arb_en_all; -}; - -static struct pmic_wrapper_type pwrap_mt8135 = { - .regs = mt8135_regs, - .type = PWRAP_MT8135, - .arb_en_all = 0x1ff, -}; - -static struct pmic_wrapper_type pwrap_mt8173 = { - .regs = mt8173_regs, - .type = PWRAP_MT8173, - .arb_en_all = 0x3f, -}; - struct pmic_wrapper { struct device *dev; void __iomem *base; @@ -385,6 +367,13 @@ struct pmic_wrapper { void __iomem *bridge_base; }; +struct pmic_wrapper_type { + int *regs; + enum pwrap_type type; + u32 arb_en_all; + int (*init_reg_clock)(struct pmic_wrapper *wrp); +}; + static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp) { return wrp->master->type == PWRAP_MT8135; @@ -578,20 +567,23 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp) return 0; } -static int pwrap_init_reg_clock(struct pmic_wrapper *wrp) +static int pwrap_mt8135_init_reg_clock(struct pmic_wrapper *wrp) { - if (pwrap_is_mt8135(wrp)) { - pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); - pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); - pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); - pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START); - pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END); - } else { - pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); - pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); - pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); - pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); - } + pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); + pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); + pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); + pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START); + pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END); + + return 0; +} + +static int pwrap_mt8173_init_reg_clock(struct pmic_wrapper *wrp) +{ + pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); + pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); return 0; } @@ -699,7 +691,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_WACS2_EN); - ret = pwrap_init_reg_clock(wrp); + ret = wrp->master->init_reg_clock(wrp); if (ret) return ret; @@ -814,6 +806,20 @@ static const struct regmap_config pwrap_regmap_config = { .max_register = 0xffff, }; +static struct pmic_wrapper_type pwrap_mt8135 = { + .regs = mt8135_regs, + .type = PWRAP_MT8135, + .arb_en_all = 0x1ff, + .init_reg_clock = pwrap_mt8135_init_reg_clock, +}; + +static struct pmic_wrapper_type pwrap_mt8173 = { + .regs = mt8173_regs, + .type = PWRAP_MT8173, + .arb_en_all = 0x3f, + .init_reg_clock = pwrap_mt8173_init_reg_clock, +}; + static struct of_device_id of_pwrap_match_tbl[] = { { .compatible = "mediatek,mt8135-pwrap", -- GitLab From 41c11f32d86ac1b64c78b827f977432df4934147 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:08 +0100 Subject: [PATCH 3657/9938] soc: mediatek: PMIC wrap: split SoC specific init into callback This patch moves the SoC specific wrapper init code into separate callback to avoid pwrap_init() getting too large. This is done by adding a new element called init_special to pmic_wrapper_type. Each currently supported SoC gets its own version of the callback and we copy the code that was previously inside pwrap_init() to these new callbacks. Finally we point the 2 instances of pmic_wrapper_type at the 2 new functions. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 67 +++++++++++++++++----------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index b22b664b155b..22c89e96a731 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -372,6 +372,7 @@ struct pmic_wrapper_type { enum pwrap_type type; u32 arb_en_all; int (*init_reg_clock)(struct pmic_wrapper *wrp); + int (*init_soc_specific)(struct pmic_wrapper *wrp); }; static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp) @@ -665,6 +666,41 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) return 0; } +static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp) +{ + /* enable pwrap events and pwrap bridge in AP side */ + pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN); + pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN); + writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN); + writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN); + writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN); + writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT); + writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN); + writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN); + writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN); + + /* enable PMIC event out and sources */ + if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || + pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { + dev_err(wrp->dev, "enable dewrap fail\n"); + return -EFAULT; + } + + return 0; +} + +static int pwrap_mt8173_init_soc_specific(struct pmic_wrapper *wrp) +{ + /* PMIC_DEWRAP enables */ + if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || + pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { + dev_err(wrp->dev, "enable dewrap fail\n"); + return -EFAULT; + } + + return 0; +} + static int pwrap_init(struct pmic_wrapper *wrp) { int ret; @@ -743,31 +779,10 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD); pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN); - if (pwrap_is_mt8135(wrp)) { - /* enable pwrap events and pwrap bridge in AP side */ - pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN); - pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN); - writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT); - writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN); - writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN); - - /* enable PMIC event out and sources */ - if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || - pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { - dev_err(wrp->dev, "enable dewrap fail\n"); - return -EFAULT; - } - } else { - /* PMIC_DEWRAP enables */ - if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || - pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { - dev_err(wrp->dev, "enable dewrap fail\n"); - return -EFAULT; - } + if (wrp->master->init_soc_specific) { + ret = wrp->master->init_soc_specific(wrp); + if (ret) + return ret; } /* Setup the init done registers */ @@ -811,6 +826,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = { .type = PWRAP_MT8135, .arb_en_all = 0x1ff, .init_reg_clock = pwrap_mt8135_init_reg_clock, + .init_soc_specific = pwrap_mt8135_init_soc_specific, }; static struct pmic_wrapper_type pwrap_mt8173 = { @@ -818,6 +834,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = { .type = PWRAP_MT8173, .arb_en_all = 0x3f, .init_reg_clock = pwrap_mt8173_init_reg_clock, + .init_soc_specific = pwrap_mt8173_init_soc_specific, }; static struct of_device_id of_pwrap_match_tbl[] = { -- GitLab From e5eef49bc34b2adda3d3d0549d92a7f252130e79 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:09 +0100 Subject: [PATCH 3658/9938] soc: mediatek: PMIC wrap: WRAP_INT_EN needs a different bitmask for MT2701/7623 MT2701 and MT7623 use a different bitmask for PWRAP_INT_EN. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 22c89e96a731..9df113546160 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -371,6 +371,7 @@ struct pmic_wrapper_type { int *regs; enum pwrap_type type; u32 arb_en_all; + u32 int_en_all; int (*init_reg_clock)(struct pmic_wrapper *wrp); int (*init_soc_specific)(struct pmic_wrapper *wrp); }; @@ -825,6 +826,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = { .regs = mt8135_regs, .type = PWRAP_MT8135, .arb_en_all = 0x1ff, + .int_en_all = ~(BIT(31) | BIT(1)), .init_reg_clock = pwrap_mt8135_init_reg_clock, .init_soc_specific = pwrap_mt8135_init_soc_specific, }; @@ -833,6 +835,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = { .regs = mt8173_regs, .type = PWRAP_MT8173, .arb_en_all = 0x3f, + .int_en_all = ~(BIT(31) | BIT(1)), .init_reg_clock = pwrap_mt8173_init_reg_clock, .init_soc_specific = pwrap_mt8173_init_soc_specific, }; @@ -946,7 +949,7 @@ static int pwrap_probe(struct platform_device *pdev) PWRAP_WDT_SRC_MASK_NO_STAUPD : PWRAP_WDT_SRC_MASK_ALL; pwrap_writel(wrp, wdt_src, PWRAP_WDT_SRC_EN); pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); - pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN); + pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); irq = platform_get_irq(pdev, 0); ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH, -- GitLab From 174f7b4ce15f9edd77caac67a82c686c54788485 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:10 +0100 Subject: [PATCH 3659/9938] soc: mediatek: PMIC wrap: SPI_WRITE needs a different bitmask for MT2701/7623 Different SoCs will use different bitmask for the SPI_WRITE command. This patch defines the bitmask in the pmic_wrapper_type struct. This allows us to support new SoCs with a different bitmask to the one currently used. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 9df113546160..8ce1bad3b605 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -372,6 +372,7 @@ struct pmic_wrapper_type { enum pwrap_type type; u32 arb_en_all; u32 int_en_all; + u32 spi_w; int (*init_reg_clock)(struct pmic_wrapper *wrp); int (*init_soc_specific)(struct pmic_wrapper *wrp); }; @@ -511,15 +512,15 @@ static int pwrap_reset_spislave(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_MAN_EN); pwrap_writel(wrp, 0, PWRAP_DIO_EN); - pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSL, + pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSL, PWRAP_MAN_CMD); - pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS, + pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS, PWRAP_MAN_CMD); - pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSH, + pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSH, PWRAP_MAN_CMD); for (i = 0; i < 4; i++) - pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS, + pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS, PWRAP_MAN_CMD); ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle); @@ -827,6 +828,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = { .type = PWRAP_MT8135, .arb_en_all = 0x1ff, .int_en_all = ~(BIT(31) | BIT(1)), + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .init_reg_clock = pwrap_mt8135_init_reg_clock, .init_soc_specific = pwrap_mt8135_init_soc_specific, }; @@ -836,6 +838,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = { .type = PWRAP_MT8173, .arb_en_all = 0x3f, .int_en_all = ~(BIT(31) | BIT(1)), + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .init_reg_clock = pwrap_mt8173_init_reg_clock, .init_soc_specific = pwrap_mt8173_init_soc_specific, }; -- GitLab From 95b25c589158d97fbc6d5504b434aef263798fa7 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:11 +0100 Subject: [PATCH 3660/9938] soc: mediatek: PMIC wrap: move wdt_src into the pmic_wrapper_type struct Different SoCs will use different bitmask for the wdt_src. This patch defines the bitmask in the pmic_wrapper_type struct. This allows us to support new SoCs with a different bitmask to the one currently used. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 8ce1bad3b605..aa54df304449 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -373,6 +373,7 @@ struct pmic_wrapper_type { u32 arb_en_all; u32 int_en_all; u32 spi_w; + u32 wdt_src; int (*init_reg_clock)(struct pmic_wrapper *wrp); int (*init_soc_specific)(struct pmic_wrapper *wrp); }; @@ -829,6 +830,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = { .arb_en_all = 0x1ff, .int_en_all = ~(BIT(31) | BIT(1)), .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, .init_reg_clock = pwrap_mt8135_init_reg_clock, .init_soc_specific = pwrap_mt8135_init_soc_specific, }; @@ -839,6 +841,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = { .arb_en_all = 0x3f, .int_en_all = ~(BIT(31) | BIT(1)), .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, .init_reg_clock = pwrap_mt8173_init_reg_clock, .init_soc_specific = pwrap_mt8173_init_soc_specific, }; @@ -858,7 +861,7 @@ MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); static int pwrap_probe(struct platform_device *pdev) { - int ret, irq, wdt_src; + int ret, irq; struct pmic_wrapper *wrp; struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_id = @@ -948,9 +951,7 @@ static int pwrap_probe(struct platform_device *pdev) * Since STAUPD was not used on mt8173 platform, * so STAUPD of WDT_SRC which should be turned off */ - wdt_src = pwrap_is_mt8173(wrp) ? - PWRAP_WDT_SRC_MASK_NO_STAUPD : PWRAP_WDT_SRC_MASK_ALL; - pwrap_writel(wrp, wdt_src, PWRAP_WDT_SRC_EN); + pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN); pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); -- GitLab From 25269cefb691d324a3fe2be4d2a7b81f6a733996 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:12 +0100 Subject: [PATCH 3661/9938] soc: mediatek: PMIC wrap: remove pwrap_is_mt8135() and pwrap_is_mt8173() With more SoCs being added the list of helper functions like these would grow. To mitigate this problem we remove the existing helpers and change the code to test against the pmic type stored inside the pmic specific datastructure that our context structure points at. There is one usage of pwrap_is_mt8135() that is ambiguous as the test should not be dependent on mt8135, but rather on the existence of a bridge. Add a new element to pmic_wrapper_type to indicate if a bridge is present and use this where appropriate. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index aa54df304449..a2bacda5a65d 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -374,20 +374,11 @@ struct pmic_wrapper_type { u32 int_en_all; u32 spi_w; u32 wdt_src; + int has_bridge:1; int (*init_reg_clock)(struct pmic_wrapper *wrp); int (*init_soc_specific)(struct pmic_wrapper *wrp); }; -static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp) -{ - return wrp->master->type == PWRAP_MT8135; -} - -static inline int pwrap_is_mt8173(struct pmic_wrapper *wrp) -{ - return wrp->master->type == PWRAP_MT8173; -} - static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg) { return readl(wrp->base + wrp->master->regs[reg]); @@ -619,11 +610,14 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL); pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL); - if (pwrap_is_mt8135(wrp)) { + switch (wrp->master->type) { + case PWRAP_MT8135: pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD); pwrap_writel(wrp, 1, PWRAP_CIPHER_START); - } else { + break; + case PWRAP_MT8173: pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); + break; } /* Config cipher mode @PMIC */ @@ -713,7 +707,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) if (wrp->rstc_bridge) reset_control_reset(wrp->rstc_bridge); - if (pwrap_is_mt8173(wrp)) { + if (wrp->master->type == PWRAP_MT8173) { /* Enable DCM */ pwrap_writel(wrp, 3, PWRAP_DCM_EN); pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); @@ -773,7 +767,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR); pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); - if (pwrap_is_mt8135(wrp)) + if (wrp->master->type == PWRAP_MT8135) pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN); pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN); @@ -793,7 +787,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_INIT_DONE0); pwrap_writel(wrp, 1, PWRAP_INIT_DONE1); - if (pwrap_is_mt8135(wrp)) { + if (wrp->master->has_bridge) { writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3); writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4); } @@ -831,6 +825,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = { .int_en_all = ~(BIT(31) | BIT(1)), .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .has_bridge = 1, .init_reg_clock = pwrap_mt8135_init_reg_clock, .init_soc_specific = pwrap_mt8135_init_soc_specific, }; @@ -842,6 +837,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = { .int_en_all = ~(BIT(31) | BIT(1)), .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, + .has_bridge = 0, .init_reg_clock = pwrap_mt8173_init_reg_clock, .init_soc_specific = pwrap_mt8173_init_soc_specific, }; @@ -889,7 +885,7 @@ static int pwrap_probe(struct platform_device *pdev) return ret; } - if (pwrap_is_mt8135(wrp)) { + if (wrp->master->has_bridge) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap-bridge"); wrp->bridge_base = devm_ioremap_resource(wrp->dev, res); -- GitLab From b28d78cd1812e4c65063ff6db9c7f4ab213e75d8 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:13 +0100 Subject: [PATCH 3662/9938] soc: mediatek: PMIC wrap: add a slave specific struct This patch adds a new struct pwrap_slv_type that we use to store the slave specific data. The patch adds 2 new helper functions to access the dew registers. The slave type is looked up via the wrappers child node. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 159 +++++++++++++++++++-------- 1 file changed, 112 insertions(+), 47 deletions(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index a2bacda5a65d..bcc841ebbdc3 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -69,33 +69,54 @@ PWRAP_WDT_SRC_EN_HARB_STAUPD_DLE | \ PWRAP_WDT_SRC_EN_HARB_STAUPD_ALE) -/* macro for slave device wrapper registers */ -#define PWRAP_DEW_BASE 0xbc00 -#define PWRAP_DEW_EVENT_OUT_EN (PWRAP_DEW_BASE + 0x0) -#define PWRAP_DEW_DIO_EN (PWRAP_DEW_BASE + 0x2) -#define PWRAP_DEW_EVENT_SRC_EN (PWRAP_DEW_BASE + 0x4) -#define PWRAP_DEW_EVENT_SRC (PWRAP_DEW_BASE + 0x6) -#define PWRAP_DEW_EVENT_FLAG (PWRAP_DEW_BASE + 0x8) -#define PWRAP_DEW_READ_TEST (PWRAP_DEW_BASE + 0xa) -#define PWRAP_DEW_WRITE_TEST (PWRAP_DEW_BASE + 0xc) -#define PWRAP_DEW_CRC_EN (PWRAP_DEW_BASE + 0xe) -#define PWRAP_DEW_CRC_VAL (PWRAP_DEW_BASE + 0x10) -#define PWRAP_DEW_MON_GRP_SEL (PWRAP_DEW_BASE + 0x12) -#define PWRAP_DEW_MON_FLAG_SEL (PWRAP_DEW_BASE + 0x14) -#define PWRAP_DEW_EVENT_TEST (PWRAP_DEW_BASE + 0x16) -#define PWRAP_DEW_CIPHER_KEY_SEL (PWRAP_DEW_BASE + 0x18) -#define PWRAP_DEW_CIPHER_IV_SEL (PWRAP_DEW_BASE + 0x1a) -#define PWRAP_DEW_CIPHER_LOAD (PWRAP_DEW_BASE + 0x1c) -#define PWRAP_DEW_CIPHER_START (PWRAP_DEW_BASE + 0x1e) -#define PWRAP_DEW_CIPHER_RDY (PWRAP_DEW_BASE + 0x20) -#define PWRAP_DEW_CIPHER_MODE (PWRAP_DEW_BASE + 0x22) -#define PWRAP_DEW_CIPHER_SWRST (PWRAP_DEW_BASE + 0x24) -#define PWRAP_MT8173_DEW_CIPHER_IV0 (PWRAP_DEW_BASE + 0x26) -#define PWRAP_MT8173_DEW_CIPHER_IV1 (PWRAP_DEW_BASE + 0x28) -#define PWRAP_MT8173_DEW_CIPHER_IV2 (PWRAP_DEW_BASE + 0x2a) -#define PWRAP_MT8173_DEW_CIPHER_IV3 (PWRAP_DEW_BASE + 0x2c) -#define PWRAP_MT8173_DEW_CIPHER_IV4 (PWRAP_DEW_BASE + 0x2e) -#define PWRAP_MT8173_DEW_CIPHER_IV5 (PWRAP_DEW_BASE + 0x30) +/* defines for slave device wrapper registers */ +enum dew_regs { + PWRAP_DEW_BASE, + PWRAP_DEW_DIO_EN, + PWRAP_DEW_READ_TEST, + PWRAP_DEW_WRITE_TEST, + PWRAP_DEW_CRC_EN, + PWRAP_DEW_CRC_VAL, + PWRAP_DEW_MON_GRP_SEL, + PWRAP_DEW_CIPHER_KEY_SEL, + PWRAP_DEW_CIPHER_IV_SEL, + PWRAP_DEW_CIPHER_RDY, + PWRAP_DEW_CIPHER_MODE, + PWRAP_DEW_CIPHER_SWRST, + + /* MT6397 only regs */ + PWRAP_DEW_EVENT_OUT_EN, + PWRAP_DEW_EVENT_SRC_EN, + PWRAP_DEW_EVENT_SRC, + PWRAP_DEW_EVENT_FLAG, + PWRAP_DEW_MON_FLAG_SEL, + PWRAP_DEW_EVENT_TEST, + PWRAP_DEW_CIPHER_LOAD, + PWRAP_DEW_CIPHER_START, +}; + +static const u32 mt6397_regs[] = { + [PWRAP_DEW_BASE] = 0xbc00, + [PWRAP_DEW_EVENT_OUT_EN] = 0xbc00, + [PWRAP_DEW_DIO_EN] = 0xbc02, + [PWRAP_DEW_EVENT_SRC_EN] = 0xbc04, + [PWRAP_DEW_EVENT_SRC] = 0xbc06, + [PWRAP_DEW_EVENT_FLAG] = 0xbc08, + [PWRAP_DEW_READ_TEST] = 0xbc0a, + [PWRAP_DEW_WRITE_TEST] = 0xbc0c, + [PWRAP_DEW_CRC_EN] = 0xbc0e, + [PWRAP_DEW_CRC_VAL] = 0xbc10, + [PWRAP_DEW_MON_GRP_SEL] = 0xbc12, + [PWRAP_DEW_MON_FLAG_SEL] = 0xbc14, + [PWRAP_DEW_EVENT_TEST] = 0xbc16, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0xbc18, + [PWRAP_DEW_CIPHER_IV_SEL] = 0xbc1a, + [PWRAP_DEW_CIPHER_LOAD] = 0xbc1c, + [PWRAP_DEW_CIPHER_START] = 0xbc1e, + [PWRAP_DEW_CIPHER_RDY] = 0xbc20, + [PWRAP_DEW_CIPHER_MODE] = 0xbc22, + [PWRAP_DEW_CIPHER_SWRST] = 0xbc24, +}; enum pwrap_regs { PWRAP_MUX_SEL, @@ -349,16 +370,26 @@ static int mt8135_regs[] = { [PWRAP_DCM_DBC_PRD] = 0x160, }; +enum pmic_type { + PMIC_MT6397, +}; + enum pwrap_type { PWRAP_MT8135, PWRAP_MT8173, }; +struct pwrap_slv_type { + const u32 *dew_regs; + enum pmic_type type; +}; + struct pmic_wrapper { struct device *dev; void __iomem *base; struct regmap *regmap; const struct pmic_wrapper_type *master; + const struct pwrap_slv_type *slave; struct clk *clk_spi; struct clk *clk_wrap; struct reset_control *rstc; @@ -544,7 +575,8 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp) for (i = 0; i < 4; i++) { pwrap_writel(wrp, i, PWRAP_SIDLY); - pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata); + pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], + &rdata); if (rdata == PWRAP_DEW_READ_TEST_VAL) { dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i); pass |= 1 << i; @@ -593,7 +625,8 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) u32 rdata; int ret; - ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata); + ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY], + &rdata); if (ret) return 0; @@ -621,12 +654,12 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) } /* Config cipher mode @PMIC */ - pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1); - pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0); - pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1); - pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2); - pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1); - pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1); /* wait for cipher data ready@AP */ ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready); @@ -643,7 +676,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) } /* wait for cipher mode idle */ - pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_MODE], 0x1); ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); if (ret) { dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret); @@ -653,9 +686,11 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE); /* Write Test */ - if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) || - pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) || - (rdata != PWRAP_DEW_WRITE_TEST_VAL)) { + if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST], + PWRAP_DEW_WRITE_TEST_VAL) || + pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_WRITE_TEST], + &rdata) || + (rdata != PWRAP_DEW_WRITE_TEST_VAL)) { dev_err(wrp->dev, "rdata=0x%04X\n", rdata); return -EFAULT; } @@ -677,8 +712,10 @@ static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp) writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN); /* enable PMIC event out and sources */ - if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || - pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { + if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN], + 0x1) || + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN], + 0xffff)) { dev_err(wrp->dev, "enable dewrap fail\n"); return -EFAULT; } @@ -689,8 +726,10 @@ static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp) static int pwrap_mt8173_init_soc_specific(struct pmic_wrapper *wrp) { /* PMIC_DEWRAP enables */ - if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) || - pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) { + if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN], + 0x1) || + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_SRC_EN], + 0xffff)) { dev_err(wrp->dev, "enable dewrap fail\n"); return -EFAULT; } @@ -734,7 +773,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) return ret; /* Enable dual IO mode */ - pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); /* Check IDLE & INIT_DONE in advance */ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); @@ -746,7 +785,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_DIO_EN); /* Read Test */ - pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata); + pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata); if (rdata != PWRAP_DEW_READ_TEST_VAL) { dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n", PWRAP_DEW_READ_TEST_VAL, rdata); @@ -759,12 +798,13 @@ static int pwrap_init(struct pmic_wrapper *wrp) return ret; /* Signature checking - using CRC */ - if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1)) + if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1)) return -EFAULT; pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); - pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR); + pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL], + PWRAP_SIG_ADR); pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); if (wrp->master->type == PWRAP_MT8135) @@ -818,6 +858,21 @@ static const struct regmap_config pwrap_regmap_config = { .max_register = 0xffff, }; +static const struct pwrap_slv_type pmic_mt6397 = { + .dew_regs = mt6397_regs, + .type = PMIC_MT6397, +}; + +static const struct of_device_id of_slave_match_tbl[] = { + { + .compatible = "mediatek,mt6397", + .data = &pmic_mt6397, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, of_slave_match_tbl); + static struct pmic_wrapper_type pwrap_mt8135 = { .regs = mt8135_regs, .type = PWRAP_MT8135, @@ -862,8 +917,17 @@ static int pwrap_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_id = of_match_device(of_pwrap_match_tbl, &pdev->dev); + const struct of_device_id *of_slave_id = NULL; struct resource *res; + if (pdev->dev.of_node->child) + of_slave_id = of_match_node(of_slave_match_tbl, + pdev->dev.of_node->child); + if (!of_slave_id) { + dev_dbg(&pdev->dev, "slave pmic should be defined in dts\n"); + return -EINVAL; + } + wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL); if (!wrp) return -ENOMEM; @@ -871,6 +935,7 @@ static int pwrap_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wrp); wrp->master = of_id->data; + wrp->slave = of_slave_id->data; wrp->dev = &pdev->dev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap"); -- GitLab From 5ae48040aa479e9bb4f2e4630867725edca1a1c3 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:14 +0100 Subject: [PATCH 3663/9938] soc: mediatek: PMIC wrap: add mt6323 slave support Add support for MT6323 slaves. This PMIC can be found on MT2701 and MT7623 EVB. The only function that we need to touch is pwrap_init_cipher(). Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index bcc841ebbdc3..0e4ebb84ee7f 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -93,6 +93,27 @@ enum dew_regs { PWRAP_DEW_EVENT_TEST, PWRAP_DEW_CIPHER_LOAD, PWRAP_DEW_CIPHER_START, + + /* MT6323 only regs */ + PWRAP_DEW_CIPHER_EN, + PWRAP_DEW_RDDMY_NO, +}; + +static const u32 mt6323_regs[] = { + [PWRAP_DEW_BASE] = 0x0000, + [PWRAP_DEW_DIO_EN] = 0x018a, + [PWRAP_DEW_READ_TEST] = 0x018c, + [PWRAP_DEW_WRITE_TEST] = 0x018e, + [PWRAP_DEW_CRC_EN] = 0x0192, + [PWRAP_DEW_CRC_VAL] = 0x0194, + [PWRAP_DEW_MON_GRP_SEL] = 0x0196, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0198, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x019a, + [PWRAP_DEW_CIPHER_EN] = 0x019c, + [PWRAP_DEW_CIPHER_RDY] = 0x019e, + [PWRAP_DEW_CIPHER_MODE] = 0x01a0, + [PWRAP_DEW_CIPHER_SWRST] = 0x01a2, + [PWRAP_DEW_RDDMY_NO] = 0x01a4, }; static const u32 mt6397_regs[] = { @@ -371,6 +392,7 @@ static int mt8135_regs[] = { }; enum pmic_type { + PMIC_MT6323, PMIC_MT6397, }; @@ -661,6 +683,19 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1); pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1); + switch (wrp->slave->type) { + case PMIC_MT6397: + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], + 0x1); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], + 0x1); + break; + case PMIC_MT6323: + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN], + 0x1); + break; + } + /* wait for cipher data ready@AP */ ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready); if (ret) { @@ -858,6 +893,11 @@ static const struct regmap_config pwrap_regmap_config = { .max_register = 0xffff, }; +static const struct pwrap_slv_type pmic_mt6323 = { + .dew_regs = mt6323_regs, + .type = PMIC_MT6323, +}; + static const struct pwrap_slv_type pmic_mt6397 = { .dew_regs = mt6397_regs, .type = PMIC_MT6397, @@ -865,6 +905,9 @@ static const struct pwrap_slv_type pmic_mt6397 = { static const struct of_device_id of_slave_match_tbl[] = { { + .compatible = "mediatek,mt6323", + .data = &pmic_mt6323, + }, { .compatible = "mediatek,mt6397", .data = &pmic_mt6397, }, { -- GitLab From 060a1d6461ebed23463262365fe41556e8a5cfc7 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 19 Feb 2016 09:44:15 +0100 Subject: [PATCH 3664/9938] soc: mediatek: PMIC wrap: add MT2701/7623 support Add the registers, callbacks and data structures required to make the wrapper work on MT2701 and MT7623. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 154 +++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 0e4ebb84ee7f..3c3e56df526e 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -52,6 +52,7 @@ #define PWRAP_DEW_WRITE_TEST_VAL 0xa55a /* macro for manual command */ +#define PWRAP_MAN_CMD_SPI_WRITE_NEW (1 << 14) #define PWRAP_MAN_CMD_SPI_WRITE (1 << 13) #define PWRAP_MAN_CMD_OP_CSH (0x0 << 8) #define PWRAP_MAN_CMD_OP_CSL (0x1 << 8) @@ -200,6 +201,13 @@ enum pwrap_regs { PWRAP_DCM_EN, PWRAP_DCM_DBC_PRD, + /* MT2701 only regs */ + PWRAP_ADC_CMD_ADDR, + PWRAP_PWRAP_ADC_CMD, + PWRAP_ADC_RDY_ADDR, + PWRAP_ADC_RDATA_ADDR1, + PWRAP_ADC_RDATA_ADDR2, + /* MT8135 only regs */ PWRAP_CSHEXT, PWRAP_EVENT_IN_EN, @@ -236,6 +244,92 @@ enum pwrap_regs { PWRAP_CIPHER_EN, }; +static int mt2701_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_SIDLY] = 0xc, + [PWRAP_RDDMY] = 0x18, + [PWRAP_SI_CK_CON] = 0x1c, + [PWRAP_CSHEXT_WRITE] = 0x20, + [PWRAP_CSHEXT_READ] = 0x24, + [PWRAP_CSLEXT_START] = 0x28, + [PWRAP_CSLEXT_END] = 0x2c, + [PWRAP_STAUPD_PRD] = 0x30, + [PWRAP_STAUPD_GRPEN] = 0x34, + [PWRAP_STAUPD_MAN_TRIG] = 0x38, + [PWRAP_STAUPD_STA] = 0x3c, + [PWRAP_WRAP_STA] = 0x44, + [PWRAP_HARB_INIT] = 0x48, + [PWRAP_HARB_HPRIO] = 0x4c, + [PWRAP_HIPRIO_ARB_EN] = 0x50, + [PWRAP_HARB_STA0] = 0x54, + [PWRAP_HARB_STA1] = 0x58, + [PWRAP_MAN_EN] = 0x5c, + [PWRAP_MAN_CMD] = 0x60, + [PWRAP_MAN_RDATA] = 0x64, + [PWRAP_MAN_VLDCLR] = 0x68, + [PWRAP_WACS0_EN] = 0x6c, + [PWRAP_INIT_DONE0] = 0x70, + [PWRAP_WACS0_CMD] = 0x74, + [PWRAP_WACS0_RDATA] = 0x78, + [PWRAP_WACS0_VLDCLR] = 0x7c, + [PWRAP_WACS1_EN] = 0x80, + [PWRAP_INIT_DONE1] = 0x84, + [PWRAP_WACS1_CMD] = 0x88, + [PWRAP_WACS1_RDATA] = 0x8c, + [PWRAP_WACS1_VLDCLR] = 0x90, + [PWRAP_WACS2_EN] = 0x94, + [PWRAP_INIT_DONE2] = 0x98, + [PWRAP_WACS2_CMD] = 0x9c, + [PWRAP_WACS2_RDATA] = 0xa0, + [PWRAP_WACS2_VLDCLR] = 0xa4, + [PWRAP_INT_EN] = 0xa8, + [PWRAP_INT_FLG_RAW] = 0xac, + [PWRAP_INT_FLG] = 0xb0, + [PWRAP_INT_CLR] = 0xb4, + [PWRAP_SIG_ADR] = 0xb8, + [PWRAP_SIG_MODE] = 0xbc, + [PWRAP_SIG_VALUE] = 0xc0, + [PWRAP_SIG_ERRVAL] = 0xc4, + [PWRAP_CRC_EN] = 0xc8, + [PWRAP_TIMER_EN] = 0xcc, + [PWRAP_TIMER_STA] = 0xd0, + [PWRAP_WDT_UNIT] = 0xd4, + [PWRAP_WDT_SRC_EN] = 0xd8, + [PWRAP_WDT_FLG] = 0xdc, + [PWRAP_DEBUG_INT_SEL] = 0xe0, + [PWRAP_DVFS_ADR0] = 0xe4, + [PWRAP_DVFS_WDATA0] = 0xe8, + [PWRAP_DVFS_ADR1] = 0xec, + [PWRAP_DVFS_WDATA1] = 0xf0, + [PWRAP_DVFS_ADR2] = 0xf4, + [PWRAP_DVFS_WDATA2] = 0xf8, + [PWRAP_DVFS_ADR3] = 0xfc, + [PWRAP_DVFS_WDATA3] = 0x100, + [PWRAP_DVFS_ADR4] = 0x104, + [PWRAP_DVFS_WDATA4] = 0x108, + [PWRAP_DVFS_ADR5] = 0x10c, + [PWRAP_DVFS_WDATA5] = 0x110, + [PWRAP_DVFS_ADR6] = 0x114, + [PWRAP_DVFS_WDATA6] = 0x118, + [PWRAP_DVFS_ADR7] = 0x11c, + [PWRAP_DVFS_WDATA7] = 0x120, + [PWRAP_CIPHER_KEY_SEL] = 0x124, + [PWRAP_CIPHER_IV_SEL] = 0x128, + [PWRAP_CIPHER_EN] = 0x12c, + [PWRAP_CIPHER_RDY] = 0x130, + [PWRAP_CIPHER_MODE] = 0x134, + [PWRAP_CIPHER_SWRST] = 0x138, + [PWRAP_DCM_EN] = 0x13c, + [PWRAP_DCM_DBC_PRD] = 0x140, + [PWRAP_ADC_CMD_ADDR] = 0x144, + [PWRAP_PWRAP_ADC_CMD] = 0x148, + [PWRAP_ADC_RDY_ADDR] = 0x14c, + [PWRAP_ADC_RDATA_ADDR1] = 0x150, + [PWRAP_ADC_RDATA_ADDR2] = 0x154, +}; + static int mt8173_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -397,6 +491,7 @@ enum pmic_type { }; enum pwrap_type { + PWRAP_MT2701, PWRAP_MT8135, PWRAP_MT8173, }; @@ -637,6 +732,31 @@ static int pwrap_mt8173_init_reg_clock(struct pmic_wrapper *wrp) return 0; } +static int pwrap_mt2701_init_reg_clock(struct pmic_wrapper *wrp) +{ + switch (wrp->slave->type) { + case PMIC_MT6397: + pwrap_writel(wrp, 0xc, PWRAP_RDDMY); + pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE); + pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ); + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); + break; + + case PMIC_MT6323: + pwrap_writel(wrp, 0x8, PWRAP_RDDMY); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_RDDMY_NO], + 0x8); + pwrap_writel(wrp, 0x5, PWRAP_CSHEXT_WRITE); + pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ); + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); + break; + } + + return 0; +} + static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp) { return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1; @@ -670,6 +790,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD); pwrap_writel(wrp, 1, PWRAP_CIPHER_START); break; + case PWRAP_MT2701: case PWRAP_MT8173: pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); break; @@ -772,6 +893,24 @@ static int pwrap_mt8173_init_soc_specific(struct pmic_wrapper *wrp) return 0; } +static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp) +{ + /* GPS_INTF initialization */ + switch (wrp->slave->type) { + case PMIC_MT6323: + pwrap_writel(wrp, 0x076c, PWRAP_ADC_CMD_ADDR); + pwrap_writel(wrp, 0x8000, PWRAP_PWRAP_ADC_CMD); + pwrap_writel(wrp, 0x072c, PWRAP_ADC_RDY_ADDR); + pwrap_writel(wrp, 0x072e, PWRAP_ADC_RDATA_ADDR1); + pwrap_writel(wrp, 0x0730, PWRAP_ADC_RDATA_ADDR2); + break; + default: + break; + } + + return 0; +} + static int pwrap_init(struct pmic_wrapper *wrp) { int ret; @@ -916,6 +1055,18 @@ static const struct of_device_id of_slave_match_tbl[] = { }; MODULE_DEVICE_TABLE(of, of_slave_match_tbl); +static const struct pmic_wrapper_type pwrap_mt2701 = { + .regs = mt2701_regs, + .type = PWRAP_MT2701, + .arb_en_all = 0x3f, + .int_en_all = ~(BIT(31) | BIT(2)), + .spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .has_bridge = 0, + .init_reg_clock = pwrap_mt2701_init_reg_clock, + .init_soc_specific = pwrap_mt2701_init_soc_specific, +}; + static struct pmic_wrapper_type pwrap_mt8135 = { .regs = mt8135_regs, .type = PWRAP_MT8135, @@ -942,6 +1093,9 @@ static struct pmic_wrapper_type pwrap_mt8173 = { static struct of_device_id of_pwrap_match_tbl[] = { { + .compatible = "mediatek,mt2701-pwrap", + .data = &pwrap_mt2701, + }, { .compatible = "mediatek,mt8135-pwrap", .data = &pwrap_mt8135, }, { -- GitLab From 8ee708792e1ccda683ec9cce9fab3b25ece0eb60 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Mon, 18 Apr 2016 11:16:14 -0700 Subject: [PATCH 3665/9938] arm64: Kconfig: remove redundant HAVE_ARCH_TRANSPARENT_HUGEPAGE definition HAVE_ARCH_TRANSPARENT_HUGEPAGE has been defined in arch/Kconfig already, the ARM64 version is identical with it and the default value is Y. So remove the redundant definition and just select it under CONFIG_ARM64. Signed-off-by: Yang Shi [will: sort into alphabetical order whilst I'm resolving conflicts] Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a578080ae7a0..c8762f4613f0 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -59,11 +59,14 @@ config ARM64 select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK + select HAVE_ARCH_TRANSPARENT_HUGEPAGE + select HAVE_ARM_SMCCC select HAVE_BPF_JIT select HAVE_C_RECORDMCOUNT select HAVE_CC_STACKPROTECTOR select HAVE_CMPXCHG_DOUBLE select HAVE_CMPXCHG_LOCAL + select HAVE_CONTEXT_TRACKING select HAVE_DEBUG_BUGVERBOSE select HAVE_DEBUG_KMEMLEAK select HAVE_DMA_API_DEBUG @@ -91,6 +94,7 @@ config ARM64 select NO_BOOTMEM select OF select OF_EARLY_FLATTREE + select OF_NUMA if NUMA && OF select OF_RESERVED_MEM select PERF_USE_VMALLOC select POWER_RESET @@ -98,9 +102,6 @@ config ARM64 select RTC_LIB select SPARSE_IRQ select SYSCTL_EXCEPTION_TRACE - select HAVE_CONTEXT_TRACKING - select HAVE_ARM_SMCCC - select OF_NUMA if NUMA && OF help ARM 64-bit (AArch64) Linux support. @@ -605,9 +606,6 @@ config SYS_SUPPORTS_HUGETLBFS config ARCH_WANT_HUGE_PMD_SHARE def_bool y if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36) -config HAVE_ARCH_TRANSPARENT_HUGEPAGE - def_bool y - config ARCH_HAS_CACHE_LINE_SIZE def_bool y -- GitLab From 2ff4936c1d68060b080aac49ec622b047f9e6c45 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 19 Apr 2016 10:31:19 +0100 Subject: [PATCH 3666/9938] arm64: asm: remove unused push/pop macros We haven't used the push/pop macros for a while now, as it's typically better to use immediate offsets for batches of accesses to the stack, as we now do in the entry assembly for the kernel and hyp code. Remove the unused macros. Signed-off-by: Mark Rutland Acked-by: Catalin Marinas Cc: James Morse Cc: Marc Zyngier Cc: Will Deacon Signed-off-by: Will Deacon --- arch/arm64/include/asm/assembler.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 70f7b9e04598..972fb55af9f1 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -26,18 +26,6 @@ #include #include -/* - * Stack pushing/popping (register pairs only). Equivalent to store decrement - * before, load increment after. - */ - .macro push, xreg1, xreg2 - stp \xreg1, \xreg2, [sp, #-16]! - .endm - - .macro pop, xreg1, xreg2 - ldp \xreg1, \xreg2, [sp], #16 - .endm - /* * Enable and disable interrupts. */ -- GitLab From f3efb67590e8f68918a7a63ab0d2debee04fba9e Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 18 Apr 2016 10:28:32 +0100 Subject: [PATCH 3667/9938] arm64: hwcaps: Cleanup naming We use hwcaps for referring to ELF hwcaps capability information. However this can be confusing with 'cpu_hwcaps' which stands for the CPU capability bit field. This patch cleans up the names to make it a bit more readable. Tested-by: Yury Norov Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/kernel/cpufeature.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index f586343723fb..e3576d9b45c7 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -744,7 +744,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .hwcap = cap, \ } -static const struct arm64_cpu_capabilities arm64_hwcaps[] = { +static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_PMULL), HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_AES), HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA1), @@ -765,7 +765,7 @@ static const struct arm64_cpu_capabilities arm64_hwcaps[] = { {}, }; -static void __init cap_set_hwcap(const struct arm64_cpu_capabilities *cap) +static void __init cap_set_elf_hwcap(const struct arm64_cpu_capabilities *cap) { switch (cap->hwcap_type) { case CAP_HWCAP: @@ -786,7 +786,7 @@ static void __init cap_set_hwcap(const struct arm64_cpu_capabilities *cap) } /* Check if we have a particular HWCAP enabled */ -static bool __maybe_unused cpus_have_hwcap(const struct arm64_cpu_capabilities *cap) +static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap) { bool rc; @@ -810,14 +810,14 @@ static bool __maybe_unused cpus_have_hwcap(const struct arm64_cpu_capabilities * return rc; } -static void __init setup_cpu_hwcaps(void) +static void __init setup_elf_hwcaps(void) { int i; - const struct arm64_cpu_capabilities *hwcaps = arm64_hwcaps; + const struct arm64_cpu_capabilities *hwcaps = arm64_elf_hwcaps; for (i = 0; hwcaps[i].matches; i++) if (hwcaps[i].matches(&hwcaps[i])) - cap_set_hwcap(&hwcaps[i]); + cap_set_elf_hwcap(&hwcaps[i]); } void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, @@ -955,8 +955,8 @@ void verify_local_cpu_capabilities(void) caps[i].enable(NULL); } - for (i = 0, caps = arm64_hwcaps; caps[i].matches; i++) { - if (!cpus_have_hwcap(&caps[i])) + for (i = 0, caps = arm64_elf_hwcaps; caps[i].matches; i++) { + if (!cpus_have_elf_hwcap(&caps[i])) continue; if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) { pr_crit("CPU%d: missing HWCAP: %s\n", @@ -979,7 +979,7 @@ void __init setup_cpu_features(void) /* Set the CPU feature capabilies */ setup_feature_capabilities(); - setup_cpu_hwcaps(); + setup_elf_hwcaps(); /* Advertise that we have computed the system capabilities */ set_sys_caps_initialised(); -- GitLab From 752835019c15f720a51433e6bc1c5c515c01d1a2 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 18 Apr 2016 10:28:33 +0100 Subject: [PATCH 3668/9938] arm64: HWCAP: Split COMPAT HWCAP table entries In order to handle systems which do not support 32bit at EL0, split the COMPAT HWCAP entries into a separate table which can be processed, only if the support is available. Tested-by: Yury Norov Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/kernel/cpufeature.c | 104 ++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index e3576d9b45c7..cac7c414b458 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -755,6 +755,10 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP), HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD), HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_ASIMDHP), + {}, +}; + +static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = { #ifdef CONFIG_COMPAT HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL), HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES), @@ -810,28 +814,23 @@ static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap) return rc; } -static void __init setup_elf_hwcaps(void) +static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps) { - int i; - const struct arm64_cpu_capabilities *hwcaps = arm64_elf_hwcaps; - - for (i = 0; hwcaps[i].matches; i++) - if (hwcaps[i].matches(&hwcaps[i])) - cap_set_elf_hwcap(&hwcaps[i]); + for (; hwcaps->matches; hwcaps++) + if (hwcaps->matches(hwcaps)) + cap_set_elf_hwcap(hwcaps); } void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, const char *info) { - int i; - - for (i = 0; caps[i].matches; i++) { - if (!caps[i].matches(&caps[i])) + for (; caps->matches; caps++) { + if (!caps->matches(caps)) continue; - if (!cpus_have_cap(caps[i].capability) && caps[i].desc) - pr_info("%s %s\n", info, caps[i].desc); - cpus_set_cap(caps[i].capability); + if (!cpus_have_cap(caps->capability) && caps->desc) + pr_info("%s %s\n", info, caps->desc); + cpus_set_cap(caps->capability); } } @@ -842,11 +841,9 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, static void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) { - int i; - - for (i = 0; caps[i].matches; i++) - if (caps[i].enable && cpus_have_cap(caps[i].capability)) - on_each_cpu(caps[i].enable, NULL, true); + for (; caps->matches; caps++) + if (caps->enable && cpus_have_cap(caps->capability)) + on_each_cpu(caps->enable, NULL, true); } /* @@ -916,6 +913,41 @@ static void check_early_cpu_features(void) verify_cpu_asid_bits(); } +static void +verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps) +{ + + for (; caps->matches; caps++) { + if (!cpus_have_elf_hwcap(caps)) + continue; + if (!feature_matches(__raw_read_system_reg(caps->sys_reg), caps)) { + pr_crit("CPU%d: missing HWCAP: %s\n", + smp_processor_id(), caps->desc); + cpu_die_early(); + } + } +} + +static void +verify_local_cpu_features(const struct arm64_cpu_capabilities *caps) +{ + for (; caps->matches; caps++) { + if (!cpus_have_cap(caps->capability) || !caps->sys_reg) + continue; + /* + * If the new CPU misses an advertised feature, we cannot proceed + * further, park the cpu. + */ + if (!feature_matches(__raw_read_system_reg(caps->sys_reg), caps)) { + pr_crit("CPU%d: missing feature: %s\n", + smp_processor_id(), caps->desc); + cpu_die_early(); + } + if (caps->enable) + caps->enable(NULL); + } +} + /* * Run through the enabled system capabilities and enable() it on this CPU. * The capabilities were decided based on the available CPUs at the boot time. @@ -926,8 +958,6 @@ static void check_early_cpu_features(void) */ void verify_local_cpu_capabilities(void) { - int i; - const struct arm64_cpu_capabilities *caps; check_early_cpu_features(); @@ -938,32 +968,9 @@ void verify_local_cpu_capabilities(void) if (!sys_caps_initialised) return; - caps = arm64_features; - for (i = 0; caps[i].matches; i++) { - if (!cpus_have_cap(caps[i].capability) || !caps[i].sys_reg) - continue; - /* - * If the new CPU misses an advertised feature, we cannot proceed - * further, park the cpu. - */ - if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) { - pr_crit("CPU%d: missing feature: %s\n", - smp_processor_id(), caps[i].desc); - cpu_die_early(); - } - if (caps[i].enable) - caps[i].enable(NULL); - } - - for (i = 0, caps = arm64_elf_hwcaps; caps[i].matches; i++) { - if (!cpus_have_elf_hwcap(&caps[i])) - continue; - if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) { - pr_crit("CPU%d: missing HWCAP: %s\n", - smp_processor_id(), caps[i].desc); - cpu_die_early(); - } - } + verify_local_cpu_features(arm64_features); + verify_local_elf_hwcaps(arm64_elf_hwcaps); + verify_local_elf_hwcaps(compat_elf_hwcaps); } static void __init setup_feature_capabilities(void) @@ -979,7 +986,8 @@ void __init setup_cpu_features(void) /* Set the CPU feature capabilies */ setup_feature_capabilities(); - setup_elf_hwcaps(); + setup_elf_hwcaps(arm64_elf_hwcaps); + setup_elf_hwcaps(compat_elf_hwcaps); /* Advertise that we have computed the system capabilities */ set_sys_caps_initialised(); -- GitLab From c80aba803a9aa131f997f62a71ab453e456d08a8 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 18 Apr 2016 10:28:34 +0100 Subject: [PATCH 3669/9938] arm64: Add helpers for detecting AArch32 support at EL0 Adds a helper to extract the support for AArch32 at EL0 Tested-by: Yury Norov Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/include/asm/cpufeature.h | 7 +++++++ arch/arm64/include/asm/sysreg.h | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index b9b649422fca..7f64285e4ef7 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -170,6 +170,13 @@ static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0) cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_BIGENDEL0_SHIFT) == 0x1; } +static inline bool id_aa64pfr0_32bit_el0(u64 pfr0) +{ + u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL0_SHIFT); + + return val == ID_AA64PFR0_EL0_32BIT_64BIT; +} + void __init setup_cpu_features(void); void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 19182ef18f8f..d39d4343318a 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -115,6 +115,7 @@ #define ID_AA64PFR0_ASIMD_SUPPORTED 0x0 #define ID_AA64PFR0_EL1_64BIT_ONLY 0x1 #define ID_AA64PFR0_EL0_64BIT_ONLY 0x1 +#define ID_AA64PFR0_EL0_32BIT_64BIT 0x2 /* id_aa64mmfr0 */ #define ID_AA64MMFR0_TGRAN4_SHIFT 28 -- GitLab From a6dc3cd718ec2a19b8ca812087666899852af78f Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 18 Apr 2016 10:28:35 +0100 Subject: [PATCH 3670/9938] arm64: cpufeature: Check availability of AArch32 On ARMv8 support for AArch32 state is optional. Hence it is not safe to check the AArch32 ID registers for sanity, which could lead to false warnings. This patch makes sure that the AArch32 state is implemented before we keep track of the 32bit ID registers. As per ARM ARM (D.1.21.2 - Support for Exception Levels and Execution States, DDI0487A.h), checking the support for AArch32 at EL0 is good enough to check the support for AArch32 (i.e, AArch32 at EL1 => AArch32 at EL0, but not vice versa). Tested-by: Yury Norov Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/kernel/cpufeature.c | 86 +++++++++++++++++++--------------- arch/arm64/kernel/cpuinfo.c | 37 ++++++++------- 2 files changed, 67 insertions(+), 56 deletions(-) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index cac7c414b458..9097ce9244e3 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -439,22 +439,26 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info) init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2); init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0); init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1); - init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0); - init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0); - init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1); - init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2); - init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3); - init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4); - init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5); - init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0); - init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1); - init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2); - init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3); - init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0); - init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1); - init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0); - init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1); - init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2); + + if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) { + init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0); + init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0); + init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1); + init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2); + init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3); + init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4); + init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5); + init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0); + init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1); + init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2); + init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3); + init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0); + init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1); + init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0); + init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1); + init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2); + } + } static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new) @@ -559,47 +563,51 @@ void update_cpu_features(int cpu, info->reg_id_aa64pfr1, boot->reg_id_aa64pfr1); /* - * If we have AArch32, we care about 32-bit features for compat. These - * registers should be RES0 otherwise. + * If we have AArch32, we care about 32-bit features for compat. + * If the system doesn't support AArch32, don't update them. */ - taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu, + if (id_aa64pfr0_32bit_el0(read_system_reg(SYS_ID_AA64PFR0_EL1)) && + id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) { + + taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu, info->reg_id_dfr0, boot->reg_id_dfr0); - taint |= check_update_ftr_reg(SYS_ID_ISAR0_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_ISAR0_EL1, cpu, info->reg_id_isar0, boot->reg_id_isar0); - taint |= check_update_ftr_reg(SYS_ID_ISAR1_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_ISAR1_EL1, cpu, info->reg_id_isar1, boot->reg_id_isar1); - taint |= check_update_ftr_reg(SYS_ID_ISAR2_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_ISAR2_EL1, cpu, info->reg_id_isar2, boot->reg_id_isar2); - taint |= check_update_ftr_reg(SYS_ID_ISAR3_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_ISAR3_EL1, cpu, info->reg_id_isar3, boot->reg_id_isar3); - taint |= check_update_ftr_reg(SYS_ID_ISAR4_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_ISAR4_EL1, cpu, info->reg_id_isar4, boot->reg_id_isar4); - taint |= check_update_ftr_reg(SYS_ID_ISAR5_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_ISAR5_EL1, cpu, info->reg_id_isar5, boot->reg_id_isar5); - /* - * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and - * ACTLR formats could differ across CPUs and therefore would have to - * be trapped for virtualization anyway. - */ - taint |= check_update_ftr_reg(SYS_ID_MMFR0_EL1, cpu, + /* + * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and + * ACTLR formats could differ across CPUs and therefore would have to + * be trapped for virtualization anyway. + */ + taint |= check_update_ftr_reg(SYS_ID_MMFR0_EL1, cpu, info->reg_id_mmfr0, boot->reg_id_mmfr0); - taint |= check_update_ftr_reg(SYS_ID_MMFR1_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_MMFR1_EL1, cpu, info->reg_id_mmfr1, boot->reg_id_mmfr1); - taint |= check_update_ftr_reg(SYS_ID_MMFR2_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_MMFR2_EL1, cpu, info->reg_id_mmfr2, boot->reg_id_mmfr2); - taint |= check_update_ftr_reg(SYS_ID_MMFR3_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_MMFR3_EL1, cpu, info->reg_id_mmfr3, boot->reg_id_mmfr3); - taint |= check_update_ftr_reg(SYS_ID_PFR0_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_PFR0_EL1, cpu, info->reg_id_pfr0, boot->reg_id_pfr0); - taint |= check_update_ftr_reg(SYS_ID_PFR1_EL1, cpu, + taint |= check_update_ftr_reg(SYS_ID_PFR1_EL1, cpu, info->reg_id_pfr1, boot->reg_id_pfr1); - taint |= check_update_ftr_reg(SYS_MVFR0_EL1, cpu, + taint |= check_update_ftr_reg(SYS_MVFR0_EL1, cpu, info->reg_mvfr0, boot->reg_mvfr0); - taint |= check_update_ftr_reg(SYS_MVFR1_EL1, cpu, + taint |= check_update_ftr_reg(SYS_MVFR1_EL1, cpu, info->reg_mvfr1, boot->reg_mvfr1); - taint |= check_update_ftr_reg(SYS_MVFR2_EL1, cpu, + taint |= check_update_ftr_reg(SYS_MVFR2_EL1, cpu, info->reg_mvfr2, boot->reg_mvfr2); + } /* * Mismatched CPU features are a recipe for disaster. Don't even diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index 84c8684431c7..92189e2875f2 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -216,23 +216,26 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1); info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1); - info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1); - info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1); - info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1); - info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1); - info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1); - info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1); - info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1); - info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1); - info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1); - info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1); - info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1); - info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1); - info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1); - - info->reg_mvfr0 = read_cpuid(MVFR0_EL1); - info->reg_mvfr1 = read_cpuid(MVFR1_EL1); - info->reg_mvfr2 = read_cpuid(MVFR2_EL1); + /* Update the 32bit ID registers only if AArch32 is implemented */ + if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) { + info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1); + info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1); + info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1); + info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1); + info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1); + info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1); + info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1); + info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1); + info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1); + info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1); + info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1); + info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1); + info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1); + + info->reg_mvfr0 = read_cpuid(MVFR0_EL1); + info->reg_mvfr1 = read_cpuid(MVFR1_EL1); + info->reg_mvfr2 = read_cpuid(MVFR2_EL1); + } cpuinfo_detect_icache_policy(info); -- GitLab From 042446a31e3803d81c7e618dd80928dc3dce70c5 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 18 Apr 2016 10:28:36 +0100 Subject: [PATCH 3671/9938] arm64: cpufeature: Track 32bit EL0 support Add cpu_hwcap bit for keeping track of the support for 32bit EL0. Tested-by: Yury Norov Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/include/asm/cpufeature.h | 8 +++++++- arch/arm64/kernel/cpufeature.c | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 7f64285e4ef7..ca8fb4bcfb1a 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -35,8 +35,9 @@ #define ARM64_ALT_PAN_NOT_UAO 10 #define ARM64_HAS_VIRT_HOST_EXTN 11 #define ARM64_WORKAROUND_CAVIUM_27456 12 +#define ARM64_HAS_32BIT_EL0 13 -#define ARM64_NCAPS 13 +#define ARM64_NCAPS 14 #ifndef __ASSEMBLY__ @@ -192,6 +193,11 @@ static inline bool cpu_supports_mixed_endian_el0(void) return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1)); } +static inline bool system_supports_32bit_el0(void) +{ + return cpus_have_cap(ARM64_HAS_32BIT_EL0); +} + static inline bool system_supports_mixed_endian_el0(void) { return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1)); diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9097ce9244e3..40a23f24559d 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -737,6 +737,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .capability = ARM64_HAS_VIRT_HOST_EXTN, .matches = runs_at_el2, }, + { + .desc = "32-bit EL0 Support", + .capability = ARM64_HAS_32BIT_EL0, + .matches = has_cpuid_feature, + .sys_reg = SYS_ID_AA64PFR0_EL1, + .sign = FTR_UNSIGNED, + .field_pos = ID_AA64PFR0_EL0_SHIFT, + .min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT, + }, {}, }; -- GitLab From 643d703d2d2dbf8e2f16efa0a6a32b1eca101d02 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 18 Apr 2016 10:28:37 +0100 Subject: [PATCH 3672/9938] arm64: compat: Check for AArch32 state Make sure we have AArch32 state available for running COMPAT binaries and also for switching the personality to PER_LINUX32. Signed-off-by: Yury Norov [ Added cap bit, checks for HWCAP, personality ] Signed-off-by: Suzuki K Poulose Tested-by: Yury Norov Signed-off-by: Will Deacon --- arch/arm64/include/asm/elf.h | 3 ++- arch/arm64/kernel/cpufeature.c | 7 +++++-- arch/arm64/kernel/sys.c | 10 ++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 24ed037f09fd..7a09c48c0475 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -177,7 +177,8 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; /* AArch32 EABI. */ #define EF_ARM_EABI_MASK 0xff000000 -#define compat_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \ +#define compat_elf_check_arch(x) (system_supports_32bit_el0() && \ + ((x)->e_machine == EM_ARM) && \ ((x)->e_flags & EF_ARM_EABI_MASK)) #define compat_start_thread compat_start_thread diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 40a23f24559d..8e62d61f6c42 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -987,7 +987,8 @@ void verify_local_cpu_capabilities(void) verify_local_cpu_features(arm64_features); verify_local_elf_hwcaps(arm64_elf_hwcaps); - verify_local_elf_hwcaps(compat_elf_hwcaps); + if (system_supports_32bit_el0()) + verify_local_elf_hwcaps(compat_elf_hwcaps); } static void __init setup_feature_capabilities(void) @@ -1004,7 +1005,9 @@ void __init setup_cpu_features(void) /* Set the CPU feature capabilies */ setup_feature_capabilities(); setup_elf_hwcaps(arm64_elf_hwcaps); - setup_elf_hwcaps(compat_elf_hwcaps); + + if (system_supports_32bit_el0()) + setup_elf_hwcaps(compat_elf_hwcaps); /* Advertise that we have computed the system capabilities */ set_sys_caps_initialised(); diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c index 75151aaf1a52..26fe8ea93ea2 100644 --- a/arch/arm64/kernel/sys.c +++ b/arch/arm64/kernel/sys.c @@ -25,6 +25,7 @@ #include #include #include +#include asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, @@ -36,11 +37,20 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); } +SYSCALL_DEFINE1(arm64_personality, unsigned int, personality) +{ + if (personality(personality) == PER_LINUX32 && + !system_supports_32bit_el0()) + return -EINVAL; + return sys_personality(personality); +} + /* * Wrappers to pass the pt_regs argument. */ asmlinkage long sys_rt_sigreturn_wrapper(void); #define sys_rt_sigreturn sys_rt_sigreturn_wrapper +#define sys_personality sys_arm64_personality #undef __SYSCALL #define __SYSCALL(nr, sym) [nr] = sym, -- GitLab From 748c7d4de46a18818b2736dce55becad9ca6c691 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 30 Nov 2015 12:42:33 +0100 Subject: [PATCH 3673/9938] ARM64: dts: mt8173: Add thermal/auxadc device nodes This adds the thermal controller and auxadc nodes to the Mediatek MT8173 dtsi file. Signed-off-by: Sascha Hauer Reviewed-by: Daniel Kurtz Acked-by: Eduardo Valentin Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index eab7efc2302d..3bebe29ab192 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -313,6 +313,11 @@ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; }; + auxadc: auxadc@11001000 { + compatible = "mediatek,mt8173-auxadc"; + reg = <0 0x11001000 0 0x1000>; + }; + uart0: serial@11002000 { compatible = "mediatek,mt8173-uart", "mediatek,mt6577-uart"; @@ -414,6 +419,18 @@ status = "disabled"; }; + thermal: thermal@1100b000 { + #thermal-sensor-cells = <0>; + compatible = "mediatek,mt8173-thermal"; + reg = <0 0x1100b000 0 0x1000>; + interrupts = <0 70 IRQ_TYPE_LEVEL_LOW>; + clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>; + clock-names = "therm", "auxadc"; + resets = <&pericfg MT8173_PERI_THERM_SW_RST>; + mediatek,auxadc = <&auxadc>; + mediatek,apmixedsys = <&apmixedsys>; + }; + nor_flash: spi@1100d000 { compatible = "mediatek,mt8173-nor"; reg = <0 0x1100d000 0 0xe0>; -- GitLab From 610175b7972afc78f0e4a622a17a32b1fccad4bf Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 19 Feb 2016 08:18:46 +0100 Subject: [PATCH 3674/9938] dt-bindings: MediaTek: Add binding document for the AUXADC Signed-off-by: Sascha Hauer Acked-by: Rob Herring Signed-off-by: Matthias Brugger --- .../bindings/soc/mediatek/auxadc.txt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/mediatek/auxadc.txt diff --git a/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt b/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt new file mode 100644 index 000000000000..bdb782918a72 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt @@ -0,0 +1,21 @@ +MediaTek AUXADC +=============== + +The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found +in some Mediatek SoCs which among other things measures the temperatures +in the SoC. It can be used directly with register accesses, but it is also +used by thermal controller which reads the temperatures from the AUXADC +directly via its own bus interface. See +Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +for the Thermal Controller which holds a phandle to the AUXADC. + +Required properties: +- compatible: Must be "mediatek,mt8173-auxadc" +- reg: Address range of the AUXADC unit + +Example: + +auxadc: auxadc@11001000 { + compatible = "mediatek,mt8173-auxadc"; + reg = <0 0x11001000 0 0x1000>; +}; -- GitLab From 601bac7638fa693204dc70035d2651474704967c Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 7 Apr 2016 20:18:35 +0200 Subject: [PATCH 3675/9938] ARM: mediatek: enable gpt6 on boot up to make arch timer work on mt7623 GPT6 needs to be enabled on MT7623 for the arch timer to work. Signed-off-by: John Crispin Signed-off-by: Matthias Brugger --- arch/arm/mach-mediatek/mediatek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c index 9c2e38d30f47..a6e3c98b95ed 100644 --- a/arch/arm/mach-mediatek/mediatek.c +++ b/arch/arm/mach-mediatek/mediatek.c @@ -29,6 +29,7 @@ static void __init mediatek_timer_init(void) void __iomem *gpt_base; if (of_machine_is_compatible("mediatek,mt6589") || + of_machine_is_compatible("mediatek,mt7623") || of_machine_is_compatible("mediatek,mt8135") || of_machine_is_compatible("mediatek,mt8127")) { /* turn on GPT6 which ungates arch timer clocks */ -- GitLab From 9f10b79dad6030b71e1f3cb0d7edbe6f4d943d1a Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Tue, 15 Mar 2016 14:30:23 +0100 Subject: [PATCH 3676/9938] KVM: s390/perf: provide additional sigp events perf kvm stat can decode sigp events, let's make the list complete by adding the missing ones. Signed-off-by: Christian Borntraeger Acked-by: Cornelia Huck Acked-by: Alexander Yarygin Signed-off-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- arch/s390/include/uapi/asm/sie.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/uapi/asm/sie.h b/arch/s390/include/uapi/asm/sie.h index 5dbaa72baa64..8fb5d4a6dd25 100644 --- a/arch/s390/include/uapi/asm/sie.h +++ b/arch/s390/include/uapi/asm/sie.h @@ -16,14 +16,19 @@ { 0x01, "SIGP sense" }, \ { 0x02, "SIGP external call" }, \ { 0x03, "SIGP emergency signal" }, \ + { 0x04, "SIGP start" }, \ { 0x05, "SIGP stop" }, \ { 0x06, "SIGP restart" }, \ { 0x09, "SIGP stop and store status" }, \ { 0x0b, "SIGP initial cpu reset" }, \ + { 0x0c, "SIGP cpu reset" }, \ { 0x0d, "SIGP set prefix" }, \ { 0x0e, "SIGP store status at address" }, \ { 0x12, "SIGP set architecture" }, \ - { 0x15, "SIGP sense running" } + { 0x13, "SIGP conditional emergency signal" }, \ + { 0x15, "SIGP sense running" }, \ + { 0x16, "SIGP set multithreading"}, \ + { 0x17, "SIGP store additional status ait address"} #define icpt_prog_codes \ { 0x0001, "Prog Operation" }, \ -- GitLab From 4f1298584eb60fc7172851f75e10f7d6c33a2628 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 25 Feb 2016 12:44:17 +0100 Subject: [PATCH 3677/9938] KVM: s390: implement has_attr for FLIC HAS_ATTR is useful for determining the supported attributes; let's implement it. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Reviewed-by: Christian Borntraeger Signed-off-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- arch/s390/kvm/interrupt.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 84efc2ba6a90..4c2cdb2dcfc8 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -2074,6 +2074,22 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) return r; } +static int flic_has_attr(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + switch (attr->group) { + case KVM_DEV_FLIC_GET_ALL_IRQS: + case KVM_DEV_FLIC_ENQUEUE: + case KVM_DEV_FLIC_CLEAR_IRQS: + case KVM_DEV_FLIC_APF_ENABLE: + case KVM_DEV_FLIC_APF_DISABLE_WAIT: + case KVM_DEV_FLIC_ADAPTER_REGISTER: + case KVM_DEV_FLIC_ADAPTER_MODIFY: + return 0; + } + return -ENXIO; +} + static int flic_create(struct kvm_device *dev, u32 type) { if (!dev) @@ -2095,6 +2111,7 @@ struct kvm_device_ops kvm_flic_ops = { .name = "kvm-flic", .get_attr = flic_get_attr, .set_attr = flic_set_attr, + .has_attr = flic_has_attr, .create = flic_create, .destroy = flic_destroy, }; -- GitLab From dad7eefbd048a2f44c990303751159671e988d13 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 25 Feb 2016 13:26:32 +0100 Subject: [PATCH 3678/9938] KVM: s390: document FLIC behavior on unsupported FLIC behavior deviates from the API documentation in reporting EINVAL instead of ENXIO for KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR when the group or attribute is unknown/unsupported. Unfortunately this can not be fixed for historical reasons. Let us at least have it documented. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Reviewed-by: Christian Borntraeger Signed-off-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- Documentation/virtual/kvm/devices/s390_flic.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt index e3e314cb83e8..646f47470f98 100644 --- a/Documentation/virtual/kvm/devices/s390_flic.txt +++ b/Documentation/virtual/kvm/devices/s390_flic.txt @@ -94,3 +94,9 @@ struct kvm_s390_io_adapter_req { KVM_S390_IO_ADAPTER_UNMAP release a userspace page for the translated address specified in addr from the list of mappings + +Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on +FLIC with an unknown group or attribute gives the error code EINVAL (instead of +ENXIO, as specified in the API documentation). It is not possible to conclude +that a FLIC operation is unavailable based on the error code resulting from a +usage attempt. -- GitLab From 6d28f789bf81540d4069342b1a28bfd41dab38a3 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Mon, 25 Jan 2016 19:10:40 +0100 Subject: [PATCH 3679/9938] KVM: s390: add clear I/O irq operation for FLIC Introduce a FLIC operation for clearing I/O interrupts for a subchannel. Rationale: According to the platform specification, pending I/O interruption requests have to be revoked in certain situations. For instance, according to the Principles of Operation (page 17-27), a subchannel put into the installed parameters initialized state is in the same state as after an I/O system reset (just parameters possibly changed). This implies that any I/O interrupts for that subchannel are no longer pending (as I/O system resets clear I/O interrupts). Therefore, we need an interface to clear pending I/O interrupts. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Reviewed-by: Christian Borntraeger Signed-off-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- .../virtual/kvm/devices/s390_flic.txt | 6 +++++ arch/s390/include/uapi/asm/kvm.h | 1 + arch/s390/kvm/interrupt.c | 25 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt index 646f47470f98..8478de1c0192 100644 --- a/Documentation/virtual/kvm/devices/s390_flic.txt +++ b/Documentation/virtual/kvm/devices/s390_flic.txt @@ -11,6 +11,7 @@ FLIC provides support to - add interrupts (KVM_DEV_FLIC_ENQUEUE) - inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS) - purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS) +- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ) - enable/disable for the guest transparent async page faults - register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*) @@ -40,6 +41,11 @@ Groups: Simply deletes all elements from the list of currently pending floating interrupts. No interrupts are injected into the guest. + KVM_DEV_FLIC_CLEAR_IO_IRQ + Deletes one (if any) I/O interrupt for a subchannel identified by the + subsystem identification word passed via the buffer specified by + attr->addr (address) and attr->attr (length). + KVM_DEV_FLIC_APF_ENABLE Enables async page faults for the guest. So in case of a major page fault the host is allowed to handle this async and continues the guest. diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h index 347fe5afa419..3b8e99ef9d58 100644 --- a/arch/s390/include/uapi/asm/kvm.h +++ b/arch/s390/include/uapi/asm/kvm.h @@ -25,6 +25,7 @@ #define KVM_DEV_FLIC_APF_DISABLE_WAIT 5 #define KVM_DEV_FLIC_ADAPTER_REGISTER 6 #define KVM_DEV_FLIC_ADAPTER_MODIFY 7 +#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 /* * We can have up to 4*64k pending subchannels + 8 adapter interrupts, * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 4c2cdb2dcfc8..e55040467eb5 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -2034,6 +2034,27 @@ static int modify_io_adapter(struct kvm_device *dev, return ret; } +static int clear_io_irq(struct kvm *kvm, struct kvm_device_attr *attr) + +{ + const u64 isc_mask = 0xffUL << 24; /* all iscs set */ + u32 schid; + + if (attr->flags) + return -EINVAL; + if (attr->attr != sizeof(schid)) + return -EINVAL; + if (copy_from_user(&schid, (void __user *) attr->addr, sizeof(schid))) + return -EFAULT; + kfree(kvm_s390_get_io_int(kvm, isc_mask, schid)); + /* + * If userspace is conforming to the architecture, we can have at most + * one pending I/O interrupt per subchannel, so this is effectively a + * clear all. + */ + return 0; +} + static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { int r = 0; @@ -2067,6 +2088,9 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) case KVM_DEV_FLIC_ADAPTER_MODIFY: r = modify_io_adapter(dev, attr); break; + case KVM_DEV_FLIC_CLEAR_IO_IRQ: + r = clear_io_irq(dev->kvm, attr); + break; default: r = -EINVAL; } @@ -2085,6 +2109,7 @@ static int flic_has_attr(struct kvm_device *dev, case KVM_DEV_FLIC_APF_DISABLE_WAIT: case KVM_DEV_FLIC_ADAPTER_REGISTER: case KVM_DEV_FLIC_ADAPTER_MODIFY: + case KVM_DEV_FLIC_CLEAR_IO_IRQ: return 0; } return -ENXIO; -- GitLab From 71daabca344b503f98c59e4bdd53a818cd01f2af Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 14 Apr 2016 14:20:19 +0800 Subject: [PATCH 3680/9938] dt-bindings: modify document of Rockchip power domains Rockchip Socs contain quality of service (qos) blocks managing priority, bandwidth, etc of the connection of each domain to the interconnect. These blocks loose state when their domain gets disabled and therefore need to be saved when disabling and restored when enabling a power-domain. These qos blocks also are similar over all currently available Rockchip SoCs. Signed-off-by: Elaine Zhang Signed-off-by: Heiko Stuebner --- .../devicetree/bindings/soc/rockchip/power_domain.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt index 98085c888d65..f909ce06afc4 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt +++ b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt @@ -20,6 +20,15 @@ Required properties for power domain sub nodes: "include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain. - clocks (optional): phandles to clocks which need to be enabled while power domain switches state. +- pm_qos (optional): phandles to qos blocks which need to be saved and restored + while power domain switches state. + +Qos Example: + + qos_gpu: qos_gpu@ffaf0000 { + compatible ="syscon"; + reg = <0x0 0xffaf0000 0x0 0x20>; + }; Example: @@ -32,6 +41,7 @@ Example: pd_gpu { reg = ; clocks = <&cru ACLK_GPU>; + pm_qos = <&qos_gpu>; }; }; -- GitLab From c54cdf141c40a5115774e91fc947c34e91df0259 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Wed, 16 Mar 2016 19:33:16 +0800 Subject: [PATCH 3681/9938] KVM: x86: optimize steal time calculation Since accumulate_steal_time is now only called in record_steal_time, it doesn't quite make sense to put the delta calculation in a separate function. The function could be called thousands of times before guest enables the steal time MSR (though the compiler may optimize out this function call). And after it's enabled, the MSR enable bit is tested twice every time. Removing the accumulate_steal_time function also avoids the necessity of having the accum_steal field. Signed-off-by: Liang Chen Signed-off-by: Gavin Guo Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 1 - arch/x86/kvm/x86.c | 19 +++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index b7e394485a5f..c66e26280707 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -562,7 +562,6 @@ struct kvm_vcpu_arch { struct { u64 msr_val; u64 last_steal; - u64 accum_steal; struct gfn_to_hva_cache stime; struct kvm_steal_time steal; } st; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9b7798c7b210..96e81d284deb 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2002,22 +2002,8 @@ static void kvmclock_reset(struct kvm_vcpu *vcpu) vcpu->arch.pv_time_enabled = false; } -static void accumulate_steal_time(struct kvm_vcpu *vcpu) -{ - u64 delta; - - if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) - return; - - delta = current->sched_info.run_delay - vcpu->arch.st.last_steal; - vcpu->arch.st.last_steal = current->sched_info.run_delay; - vcpu->arch.st.accum_steal = delta; -} - static void record_steal_time(struct kvm_vcpu *vcpu) { - accumulate_steal_time(vcpu); - if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) return; @@ -2025,9 +2011,10 @@ static void record_steal_time(struct kvm_vcpu *vcpu) &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)))) return; - vcpu->arch.st.steal.steal += vcpu->arch.st.accum_steal; + vcpu->arch.st.steal.steal += current->sched_info.run_delay - + vcpu->arch.st.last_steal; + vcpu->arch.st.last_steal = current->sched_info.run_delay; vcpu->arch.st.steal.version += 2; - vcpu->arch.st.accum_steal = 0; kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime, &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); -- GitLab From 46971a2f59f135341f8912f516540fef6890d4df Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Fri, 25 Mar 2016 21:19:38 +0800 Subject: [PATCH 3682/9938] KVM: MMU: skip obsolete sp in for_each_gfn_*() The obsolete sp should not be used on current vCPUs and should not hurt vCPU's running, so skip it from for_each_gfn_sp() and for_each_gfn_indirect_valid_sp() The side effort is we will double check role.invalid in kvm_mmu_get_page() but i think it is okay as role is well cached Signed-off-by: Xiao Guangrong Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 1ff4dbb73fb7..850335a71d9f 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1909,18 +1909,17 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm, * since it has been deleted from active_mmu_pages but still can be found * at hast list. * - * for_each_gfn_indirect_valid_sp has skipped that kind of page and - * kvm_mmu_get_page(), the only user of for_each_gfn_sp(), has skipped - * all the obsolete pages. + * for_each_gfn_valid_sp() has skipped that kind of pages. */ -#define for_each_gfn_sp(_kvm, _sp, _gfn) \ +#define for_each_gfn_valid_sp(_kvm, _sp, _gfn) \ hlist_for_each_entry(_sp, \ &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)], hash_link) \ - if ((_sp)->gfn != (_gfn)) {} else + if ((_sp)->gfn != (_gfn) || is_obsolete_sp((_kvm), (_sp)) \ + || (_sp)->role.invalid) {} else #define for_each_gfn_indirect_valid_sp(_kvm, _sp, _gfn) \ - for_each_gfn_sp(_kvm, _sp, _gfn) \ - if ((_sp)->role.direct || (_sp)->role.invalid) {} else + for_each_gfn_valid_sp(_kvm, _sp, _gfn) \ + if ((_sp)->role.direct) {} else /* @sp->gfn should be write-protected at the call site */ static bool __kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, @@ -1961,6 +1960,11 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, int point) { } static void mmu_audit_disable(void) { } #endif +static bool is_obsolete_sp(struct kvm *kvm, struct kvm_mmu_page *sp) +{ + return unlikely(sp->mmu_valid_gen != kvm->arch.mmu_valid_gen); +} + static bool kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, struct list_head *invalid_list) { @@ -2105,11 +2109,6 @@ static void clear_sp_write_flooding_count(u64 *spte) __clear_sp_write_flooding_count(sp); } -static bool is_obsolete_sp(struct kvm *kvm, struct kvm_mmu_page *sp) -{ - return unlikely(sp->mmu_valid_gen != kvm->arch.mmu_valid_gen); -} - static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gaddr, @@ -2136,10 +2135,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1; role.quadrant = quadrant; } - for_each_gfn_sp(vcpu->kvm, sp, gfn) { - if (is_obsolete_sp(vcpu->kvm, sp)) - continue; - + for_each_gfn_valid_sp(vcpu->kvm, sp, gfn) { if (!need_sync && sp->unsync) need_sync = true; -- GitLab From 2e4682ba2ed79d8082b78d292b3b80f54d970b7a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 10 Mar 2016 16:30:22 +0100 Subject: [PATCH 3683/9938] KVM: add missing memory barrier in kvm_{make,check}_request kvm_make_request and kvm_check_request imply a producer-consumer relationship; add implicit memory barriers to them. There was indeed already a place that was adding an explicit smp_mb() to order between kvm_check_request and the processing of the request. That memory barrier can be removed (as an added benefit, kvm_check_request can use smp_mb__after_atomic which is free on x86). Signed-off-by: Paolo Bonzini --- arch/x86/kvm/irq_comm.c | 3 --- include/linux/kvm_host.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c index 54ead79e444b..dfb4c6476877 100644 --- a/arch/x86/kvm/irq_comm.c +++ b/arch/x86/kvm/irq_comm.c @@ -382,9 +382,6 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu, u32 i, nr_ioapic_pins; int idx; - /* kvm->irq_routing must be read after clearing - * KVM_SCAN_IOAPIC. */ - smp_mb(); idx = srcu_read_lock(&kvm->irq_srcu); table = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); nr_ioapic_pins = min_t(u32, table->nr_rt_entries, diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 5276fe0916fc..ad40d44784c7 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1091,6 +1091,11 @@ static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; } static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu) { + /* + * Ensure the rest of the request is published to kvm_check_request's + * caller. Paired with the smp_mb__after_atomic in kvm_check_request. + */ + smp_wmb(); set_bit(req, &vcpu->requests); } @@ -1098,6 +1103,12 @@ static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu) { if (test_bit(req, &vcpu->requests)) { clear_bit(req, &vcpu->requests); + + /* + * Ensure the rest of the request is visible to kvm_check_request's + * caller. Paired with the smp_wmb in kvm_make_request. + */ + smp_mb__after_atomic(); return true; } else { return false; -- GitLab From 60f5f5d3a106dc5385b39348d13b20b15ac9cbf9 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Tue, 19 Apr 2016 15:34:22 +0200 Subject: [PATCH 3684/9938] at86rf230: increase sleep to off timings I expierenced when setting channel while sleep mode it didn't changed the channel inside the hardware registers. Then I got another report of an user which has similar issues. I increased the sleep to off state change timing, which is according at86rf233 at maximum 1000 us. After this change I got no similar effects again. I tried another option to wait on AWAKE_END irq, which can be used to wait until the transceiver is awaked. I tested it and the IRQ took 4 seconds after starting state change. I don't believe it takes 4 seconds to go into the TRX_OFF state from SLEEP state. The alternative is to increase the timings which seems to work. Cc: Oleg Hahm Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index cb9e9fe6d77a..9f10da60e02d 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1340,7 +1340,7 @@ static struct at86rf2xx_chip_data at86rf233_data = { .t_off_to_aack = 80, .t_off_to_tx_on = 80, .t_off_to_sleep = 35, - .t_sleep_to_off = 210, + .t_sleep_to_off = 1000, .t_frame = 4096, .t_p_ack = 545, .rssi_base_val = -91, @@ -1355,7 +1355,7 @@ static struct at86rf2xx_chip_data at86rf231_data = { .t_off_to_aack = 110, .t_off_to_tx_on = 110, .t_off_to_sleep = 35, - .t_sleep_to_off = 380, + .t_sleep_to_off = 1000, .t_frame = 4096, .t_p_ack = 545, .rssi_base_val = -91, @@ -1370,7 +1370,7 @@ static struct at86rf2xx_chip_data at86rf212_data = { .t_off_to_aack = 200, .t_off_to_tx_on = 200, .t_off_to_sleep = 35, - .t_sleep_to_off = 380, + .t_sleep_to_off = 1000, .t_frame = 4096, .t_p_ack = 545, .rssi_base_val = -100, -- GitLab From c7c999cb18da88a881e10e07f0724ad0bfaff770 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Apr 2016 17:32:19 +0200 Subject: [PATCH 3685/9938] Bluetooth: vhci: Fix race at creating hci device hci_vhci driver creates a hci device object dynamically upon each HCI_VENDOR_PKT write. Although it checks the already created object and returns an error, it's still racy and may build multiple hci_dev objects concurrently when parallel writes are performed, as the device tracks only a single hci_dev object. This patch introduces a mutex to protect against the concurrent device creations. Cc: Signed-off-by: Takashi Iwai Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_vhci.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index f67ea1c090cb..aba31210c802 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -50,6 +50,7 @@ struct vhci_data { wait_queue_head_t read_wait; struct sk_buff_head readq; + struct mutex open_mutex; struct delayed_work open_timeout; }; @@ -87,12 +88,15 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return 0; } -static int vhci_create_device(struct vhci_data *data, __u8 opcode) +static int __vhci_create_device(struct vhci_data *data, __u8 opcode) { struct hci_dev *hdev; struct sk_buff *skb; __u8 dev_type; + if (data->hdev) + return -EBADFD; + /* bits 0-1 are dev_type (BR/EDR or AMP) */ dev_type = opcode & 0x03; @@ -151,6 +155,17 @@ static int vhci_create_device(struct vhci_data *data, __u8 opcode) return 0; } +static int vhci_create_device(struct vhci_data *data, __u8 opcode) +{ + int err; + + mutex_lock(&data->open_mutex); + err = __vhci_create_device(data, opcode); + mutex_unlock(&data->open_mutex); + + return err; +} + static inline ssize_t vhci_get_user(struct vhci_data *data, struct iov_iter *from) { @@ -191,11 +206,6 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, case HCI_VENDOR_PKT: cancel_delayed_work_sync(&data->open_timeout); - if (data->hdev) { - kfree_skb(skb); - return -EBADFD; - } - opcode = *((__u8 *) skb->data); skb_pull(skb, 1); @@ -320,6 +330,7 @@ static int vhci_open(struct inode *inode, struct file *file) skb_queue_head_init(&data->readq); init_waitqueue_head(&data->read_wait); + mutex_init(&data->open_mutex); INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout); file->private_data = data; -- GitLab From b84e93077fe926bc65e23d887b54fc46be60b76e Mon Sep 17 00:00:00 2001 From: Peter Heise Date: Wed, 20 Apr 2016 09:08:29 +0200 Subject: [PATCH 3686/9938] net/hsr: Fixed version field in ENUM New field (IFLA_HSR_VERSION) was added in the middle of an existing ENUM and would break kernel ABI, therefore moved to the end. Reported by Stephen Hemminger. Signed-off-by: Peter Heise Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 5ffdcb34e35b..af8fd58b4006 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -774,9 +774,9 @@ enum { IFLA_HSR_SLAVE1, IFLA_HSR_SLAVE2, IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ - IFLA_HSR_VERSION, /* HSR version */ IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ IFLA_HSR_SEQ_NR, + IFLA_HSR_VERSION, /* HSR version */ __IFLA_HSR_MAX, }; -- GitLab From cca1d81574d266d4a3aa33f3947297564525e127 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 20 Apr 2016 07:31:31 -0700 Subject: [PATCH 3687/9938] net: fix HAVE_EFFICIENT_UNALIGNED_ACCESS typos HAVE_EFFICIENT_UNALIGNED_ACCESS needs CONFIG_ prefix. Also add a comment in nla_align_64bit() explaining we have to add a padding if current skb->data is aligned, as it certainly can be confusing. Fixes: 35c5845957c7 ("net: Add helpers for 64-bit aligning netlink attributes.") Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/netlink.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index e644b3489acf..cf95df1fa14b 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -1238,18 +1238,21 @@ static inline int nla_validate_nested(const struct nlattr *start, int maxtype, * Conditionally emit a padding netlink attribute in order to make * the next attribute we emit have a 64-bit aligned nla_data() area. * This will only be done in architectures which do not have - * HAVE_EFFICIENT_UNALIGNED_ACCESS defined. + * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS defined. * * Returns zero on success or a negative error code. */ static inline int nla_align_64bit(struct sk_buff *skb, int padattr) { -#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS - if (IS_ALIGNED((unsigned long)skb->data, 8)) { - struct nlattr *attr = nla_reserve(skb, padattr, 0); - if (!attr) - return -EMSGSIZE; - } +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* The nlattr header is 4 bytes in size, that's why we test + * if the skb->data _is_ aligned. This NOP attribute, plus + * nlattr header for next attribute, will make nla_data() + * 8-byte aligned. + */ + if (IS_ALIGNED((unsigned long)skb->data, 8) && + !nla_reserve(skb, padattr, 0)) + return -EMSGSIZE; #endif return 0; } @@ -1261,7 +1264,7 @@ static inline int nla_align_64bit(struct sk_buff *skb, int padattr) static inline int nla_total_size_64bit(int payload) { return NLA_ALIGN(nla_attr_size(payload)) -#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + NLA_ALIGN(nla_attr_size(0)) #endif ; -- GitLab From 1a4d5a3e2caacd104e82ebd3c4964e681de1aa8a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 17:32:19 +0200 Subject: [PATCH 3688/9938] regulator: ti-abb: DT spelling s/#{address,size}-cell/#{address,size}-cells/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/ti-abb-regulator.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt b/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt index c58db75f959e..c3f6546ebac7 100644 --- a/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt @@ -14,8 +14,8 @@ Required Properties: - "setup-address" - contains setup register address of ABB module (ti,abb-v3) - "int-address" - contains address of interrupt register for ABB module (also see Optional properties) -- #address-cell: should be 0 -- #size-cell: should be 0 +- #address-cells: should be 0 +- #size-cells: should be 0 - clocks: should point to the clock node used by ABB module - ti,settling-time: Settling time in uSecs from SoC documentation for ABB module to settle down(target time for SR2_WTCNT_VALUE). @@ -69,7 +69,7 @@ Example #1: Simplest configuration (no efuse data, hard coded ABB table): abb_x: regulator-abb-x { compatible = "ti,abb-v1"; regulator-name = "abb_x"; - #address-cell = <0>; + #address-cells = <0>; #size-cells = <0>; reg = <0x483072f0 0x8>, <0x48306818 0x4>; reg-names = "base-address", "int-address"; @@ -89,7 +89,7 @@ Example #2: Efuse bits contain ABB mode setting (no LDO override capability) abb_y: regulator-abb-y { compatible = "ti,abb-v2"; regulator-name = "abb_y"; - #address-cell = <0>; + #address-cells = <0>; #size-cells = <0>; reg = <0x4a307bd0 0x8>, <0x4a306014 0x4>, <0x4A002268 0x8>; reg-names = "base-address", "int-address", "efuse-address"; @@ -110,7 +110,7 @@ Example #3: Efuse bits contain ABB mode setting and LDO override capability abb_z: regulator-abb-z { compatible = "ti,abb-v2"; regulator-name = "abb_z"; - #address-cell = <0>; + #address-cells = <0>; #size-cells = <0>; reg = <0x4ae07ce4 0x8>, <0x4ae06010 0x4>, <0x4a002194 0x8>, <0x4ae0C314 0x4>; -- GitLab From e2c91d4d78ee3a69ad634bc7ef90688704baab9d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 6 Apr 2016 10:55:24 -0300 Subject: [PATCH 3689/9938] [media] media-device: get rid of the spinlock Right now, the lock schema for media_device struct is messy, since sometimes, it is protected via a spin lock, while, for media graph traversal, it is protected by a mutex. Solve this conflict by always using a mutex. As a side effect, this prevents a bug when the media notifiers is called at atomic context, while running the notifier callback: BUG: sleeping function called from invalid context at mm/slub.c:1289 in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe 4 locks held by modprobe/3479: #0: (&dev->mutex){......}, at: [] __driver_attach+0xa3/0x160 #1: (&dev->mutex){......}, at: [] __driver_attach+0xb1/0x160 #2: (register_mutex#5){+.+.+.}, at: [] usb_audio_probe+0x257/0x1c90 [snd_usb_audio] #3: (&(&mdev->lock)->rlock){+.+.+.}, at: [] media_device_register_entity+0x1cb/0x700 [media] CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49 Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000 ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000 ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5 Call Trace: [] dump_stack+0x85/0xc4 [] ___might_sleep+0x245/0x3a0 [] __might_sleep+0x95/0x1a0 [] kmem_cache_alloc_trace+0x20e/0x300 [] ? media_add_link+0x4d/0x140 [media] [] media_add_link+0x4d/0x140 [media] [] media_create_pad_link+0xa1/0x600 [media] [] au0828_media_graph_notify+0x173/0x360 [au0828] [] ? media_gobj_create+0x1ba/0x480 [media] [] media_device_register_entity+0x3ab/0x700 [media] Reviewed-by: Javier Martinez Canillas Acked-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 39 ++++++++++++------------------------ drivers/media/media-entity.c | 16 +++++++-------- include/media/media-device.h | 6 +----- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 6e43c95629ea..898a3cf814ba 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -90,18 +90,13 @@ static struct media_entity *find_entity(struct media_device *mdev, u32 id) id &= ~MEDIA_ENT_ID_FLAG_NEXT; - spin_lock(&mdev->lock); - media_device_for_each_entity(entity, mdev) { if (((media_entity_id(entity) == id) && !next) || ((media_entity_id(entity) > id) && next)) { - spin_unlock(&mdev->lock); return entity; } } - spin_unlock(&mdev->lock); - return NULL; } @@ -431,6 +426,7 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, struct media_device *dev = to_media_device(devnode); long ret; + mutex_lock(&dev->graph_mutex); switch (cmd) { case MEDIA_IOC_DEVICE_INFO: ret = media_device_get_info(dev, @@ -443,29 +439,24 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, break; case MEDIA_IOC_ENUM_LINKS: - mutex_lock(&dev->graph_mutex); ret = media_device_enum_links(dev, (struct media_links_enum __user *)arg); - mutex_unlock(&dev->graph_mutex); break; case MEDIA_IOC_SETUP_LINK: - mutex_lock(&dev->graph_mutex); ret = media_device_setup_link(dev, (struct media_link_desc __user *)arg); - mutex_unlock(&dev->graph_mutex); break; case MEDIA_IOC_G_TOPOLOGY: - mutex_lock(&dev->graph_mutex); ret = media_device_get_topology(dev, (struct media_v2_topology __user *)arg); - mutex_unlock(&dev->graph_mutex); break; default: ret = -ENOIOCTLCMD; } + mutex_unlock(&dev->graph_mutex); return ret; } @@ -590,12 +581,12 @@ int __must_check media_device_register_entity(struct media_device *mdev, if (!ida_pre_get(&mdev->entity_internal_idx, GFP_KERNEL)) return -ENOMEM; - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); ret = ida_get_new_above(&mdev->entity_internal_idx, 1, &entity->internal_idx); if (ret < 0) { - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); return ret; } @@ -615,9 +606,6 @@ int __must_check media_device_register_entity(struct media_device *mdev, (notify)->notify(entity, notify->notify_data); } - spin_unlock(&mdev->lock); - - mutex_lock(&mdev->graph_mutex); if (mdev->entity_internal_idx_max >= mdev->pm_count_walk.ent_enum.idx_max) { struct media_entity_graph new = { .top = 0 }; @@ -680,9 +668,9 @@ void media_device_unregister_entity(struct media_entity *entity) if (mdev == NULL) return; - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); __media_device_unregister_entity(entity); - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); } EXPORT_SYMBOL_GPL(media_device_unregister_entity); @@ -703,7 +691,6 @@ void media_device_init(struct media_device *mdev) INIT_LIST_HEAD(&mdev->pads); INIT_LIST_HEAD(&mdev->links); INIT_LIST_HEAD(&mdev->entity_notify); - spin_lock_init(&mdev->lock); mutex_init(&mdev->graph_mutex); ida_init(&mdev->entity_internal_idx); @@ -752,9 +739,9 @@ EXPORT_SYMBOL_GPL(__media_device_register); int __must_check media_device_register_entity_notify(struct media_device *mdev, struct media_entity_notify *nptr) { - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); list_add_tail(&nptr->list, &mdev->entity_notify); - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); return 0; } EXPORT_SYMBOL_GPL(media_device_register_entity_notify); @@ -771,9 +758,9 @@ static void __media_device_unregister_entity_notify(struct media_device *mdev, void media_device_unregister_entity_notify(struct media_device *mdev, struct media_entity_notify *nptr) { - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); __media_device_unregister_entity_notify(mdev, nptr); - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); } EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify); @@ -787,11 +774,11 @@ void media_device_unregister(struct media_device *mdev) if (mdev == NULL) return; - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); /* Check if mdev was ever registered at all */ if (!media_devnode_is_registered(&mdev->devnode)) { - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); return; } @@ -811,7 +798,7 @@ void media_device_unregister(struct media_device *mdev) kfree(intf); } - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); device_remove_file(&mdev->devnode.dev, &dev_attr_model); media_devnode_unregister(&mdev->devnode); diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index e95070b3a3d4..c53c1d5589a0 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -219,7 +219,7 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, entity->pads = pads; if (mdev) - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); for (i = 0; i < num_pads; i++) { pads[i].entity = entity; @@ -230,7 +230,7 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, } if (mdev) - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); return 0; } @@ -747,9 +747,9 @@ void media_entity_remove_links(struct media_entity *entity) if (mdev == NULL) return; - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); __media_entity_remove_links(entity); - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); } EXPORT_SYMBOL_GPL(media_entity_remove_links); @@ -951,9 +951,9 @@ void media_remove_intf_link(struct media_link *link) if (mdev == NULL) return; - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); __media_remove_intf_link(link); - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); } EXPORT_SYMBOL_GPL(media_remove_intf_link); @@ -975,8 +975,8 @@ void media_remove_intf_links(struct media_interface *intf) if (mdev == NULL) return; - spin_lock(&mdev->lock); + mutex_lock(&mdev->graph_mutex); __media_remove_intf_links(intf); - spin_unlock(&mdev->lock); + mutex_unlock(&mdev->graph_mutex); } EXPORT_SYMBOL_GPL(media_remove_intf_links); diff --git a/include/media/media-device.h b/include/media/media-device.h index 07809f698464..b21ef244ad3e 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -304,8 +303,7 @@ struct media_entity_notify { * @pads: List of registered pads * @links: List of registered links * @entity_notify: List of registered entity_notify callbacks - * @lock: Entities list lock - * @graph_mutex: Entities graph operation lock + * @graph_mutex: Protects access to struct media_device data * @pm_count_walk: Graph walk for power state walk. Access serialised using * graph_mutex. * @@ -371,8 +369,6 @@ struct media_device { /* notify callback list invoked when a new entity is registered */ struct list_head entity_notify; - /* Protects the graph objects creation/removal */ - spinlock_t lock; /* Serializes graph operations. */ struct mutex graph_mutex; struct media_entity_graph pm_count_walk; -- GitLab From 2f0ad49104cbb19db24442af736614659363d2ab Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 19 Apr 2016 13:12:35 +0800 Subject: [PATCH 3690/9938] ASoC: Change DAI link's be_id to a generic id The generic ID can be used by topology: - Toplogy can create FE links and set their ID, machine drivers will be notified and check this ID for machine-specific init. - Toplogy can use the ID to find existing BE & CC links and further configure them. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- include/sound/soc.h | 2 +- sound/soc/intel/boards/broadwell.c | 2 +- sound/soc/intel/boards/bytcr_rt5640.c | 2 +- sound/soc/intel/boards/bytcr_rt5651.c | 2 +- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 2 +- sound/soc/intel/boards/cht_bsw_rt5645.c | 2 +- sound/soc/intel/boards/cht_bsw_rt5672.c | 2 +- sound/soc/intel/boards/haswell.c | 2 +- sound/soc/intel/boards/skl_nau88l25_max98357a.c | 12 ++++++------ sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 12 ++++++------ sound/soc/intel/boards/skl_rt286.c | 10 +++++----- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 02b4a215fd75..ef25e86d51ee 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1002,7 +1002,7 @@ struct snd_soc_dai_link { */ const char *platform_name; struct device_node *platform_of_node; - int be_id; /* optional ID for machine driver BE identification */ + int id; /* optional ID for machine driver link identification */ const struct snd_soc_pcm_stream *params; unsigned int num_params; diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 3f8a1e10bed0..7486a0022fde 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -201,7 +201,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { { /* SSP0 - Codec */ .name = "Codec", - .be_id = 0, + .id = 0, .cpu_dai_name = "snd-soc-dummy-dai", .platform_name = "snd-soc-dummy", .no_pcm = 1, diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 032a2e753f0b..88efb62439ba 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -304,7 +304,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { /* back ends */ { .name = "SSP2-Codec", - .be_id = 1, + .id = 1, .cpu_dai_name = "ssp2-port", .platform_name = "sst-mfld-platform", .no_pcm = 1, diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 1c95ccc886c4..35f591eab3c9 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -267,7 +267,7 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { /* back ends */ { .name = "SSP2-Codec", - .be_id = 1, + .id = 1, .cpu_dai_name = "ssp2-port", .platform_name = "sst-mfld-platform", .no_pcm = 1, diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index e609f089593a..6260df6bd49c 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -255,7 +255,7 @@ static struct snd_soc_dai_link cht_dailink[] = { /* back ends */ { .name = "SSP2-Codec", - .be_id = 1, + .id = 1, .cpu_dai_name = "ssp2-port", .platform_name = "sst-mfld-platform", .no_pcm = 1, diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 2a6f80843bc9..0618a7f1025b 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -295,7 +295,7 @@ static struct snd_soc_dai_link cht_dailink[] = { /* back ends */ { .name = "SSP2-Codec", - .be_id = 1, + .id = 1, .cpu_dai_name = "ssp2-port", .platform_name = "sst-mfld-platform", .no_pcm = 1, diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 2e5347f8f96c..df9d254baa18 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -273,7 +273,7 @@ static struct snd_soc_dai_link cht_dailink[] = { { /* SSP2 - Codec */ .name = "SSP2-Codec", - .be_id = 1, + .id = 1, .cpu_dai_name = "ssp2-port", .platform_name = "sst-mfld-platform", .no_pcm = 1, diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 22558572cb9c..863f1d5e2a2c 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -156,7 +156,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { { /* SSP0 - Codec */ .name = "Codec", - .be_id = 0, + .id = 0, .cpu_dai_name = "snd-soc-dummy-dai", .platform_name = "snd-soc-dummy", .no_pcm = 1, diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 72176b79a18d..9cc9240ed717 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -456,7 +456,7 @@ static struct snd_soc_dai_link skylake_dais[] = { { /* SSP0 - Codec */ .name = "SSP0-Codec", - .be_id = 0, + .id = 0, .cpu_dai_name = "SSP0 Pin", .platform_name = "0000:00:1f.3", .no_pcm = 1, @@ -472,7 +472,7 @@ static struct snd_soc_dai_link skylake_dais[] = { { /* SSP1 - Codec */ .name = "SSP1-Codec", - .be_id = 1, + .id = 1, .cpu_dai_name = "SSP1 Pin", .platform_name = "0000:00:1f.3", .no_pcm = 1, @@ -489,7 +489,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "dmic01", - .be_id = 2, + .id = 2, .cpu_dai_name = "DMIC01 Pin", .codec_name = "dmic-codec", .codec_dai_name = "dmic-hifi", @@ -501,7 +501,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "iDisp1", - .be_id = 3, + .id = 3, .cpu_dai_name = "iDisp1 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi1", @@ -512,7 +512,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "iDisp2", - .be_id = 4, + .id = 4, .cpu_dai_name = "iDisp2 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi2", @@ -523,7 +523,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "iDisp3", - .be_id = 5, + .id = 5, .cpu_dai_name = "iDisp3 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi3", diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index 5f1ca99ae9b0..53380b2cb1a8 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -505,7 +505,7 @@ static struct snd_soc_dai_link skylake_dais[] = { { /* SSP0 - Codec */ .name = "SSP0-Codec", - .be_id = 0, + .id = 0, .cpu_dai_name = "SSP0 Pin", .platform_name = "0000:00:1f.3", .no_pcm = 1, @@ -523,7 +523,7 @@ static struct snd_soc_dai_link skylake_dais[] = { { /* SSP1 - Codec */ .name = "SSP1-Codec", - .be_id = 1, + .id = 1, .cpu_dai_name = "SSP1 Pin", .platform_name = "0000:00:1f.3", .no_pcm = 1, @@ -540,7 +540,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "dmic01", - .be_id = 2, + .id = 2, .cpu_dai_name = "DMIC01 Pin", .codec_name = "dmic-codec", .codec_dai_name = "dmic-hifi", @@ -552,7 +552,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "iDisp1", - .be_id = 3, + .id = 3, .cpu_dai_name = "iDisp1 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi1", @@ -563,7 +563,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "iDisp2", - .be_id = 4, + .id = 4, .cpu_dai_name = "iDisp2 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi2", @@ -574,7 +574,7 @@ static struct snd_soc_dai_link skylake_dais[] = { }, { .name = "iDisp3", - .be_id = 5, + .id = 5, .cpu_dai_name = "iDisp3 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi3", diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 2016397a8e75..9e39fc1b89d3 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -375,7 +375,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { { /* SSP0 - Codec */ .name = "SSP0-Codec", - .be_id = 0, + .id = 0, .cpu_dai_name = "SSP0 Pin", .platform_name = "0000:00:1f.3", .no_pcm = 1, @@ -393,7 +393,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { }, { .name = "dmic01", - .be_id = 1, + .id = 1, .cpu_dai_name = "DMIC01 Pin", .codec_name = "dmic-codec", .codec_dai_name = "dmic-hifi", @@ -405,7 +405,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { }, { .name = "iDisp1", - .be_id = 2, + .id = 2, .cpu_dai_name = "iDisp1 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi1", @@ -416,7 +416,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { }, { .name = "iDisp2", - .be_id = 3, + .id = 3, .cpu_dai_name = "iDisp2 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi2", @@ -427,7 +427,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { }, { .name = "iDisp3", - .be_id = 4, + .id = 4, .cpu_dai_name = "iDisp3 Pin", .codec_name = "ehdaudio0D2", .codec_dai_name = "intel-hdmi-hifi3", -- GitLab From 5ed470feb9a121582dbd455c72b133dc1a856a0a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 6 Apr 2016 10:55:25 -0300 Subject: [PATCH 3691/9938] [media] media: Improve documentation for link_setup/link_modify Those callbacks are called with the media_device.graph_mutex held. Add a note about that, as the code called by those notifiers should not be touching in the mutex. Acked-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/media-device.h | 3 ++- include/media/media-entity.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/media/media-device.h b/include/media/media-device.h index b21ef244ad3e..a9b33c47310d 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -311,7 +311,8 @@ struct media_entity_notify { * @enable_source: Enable Source Handler function pointer * @disable_source: Disable Source Handler function pointer * - * @link_notify: Link state change notification callback + * @link_notify: Link state change notification callback. This callback is + * called with the graph_mutex held. * * This structure represents an abstract high-level media device. It allows easy * access to entities and provides basic media device-level support. The diff --git a/include/media/media-entity.h b/include/media/media-entity.h index e0295eefd702..cbb266f7f2b5 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -179,6 +179,9 @@ struct media_pad { * @link_validate: Return whether a link is valid from the entity point of * view. The media_entity_pipeline_start() function * validates all links by calling this operation. Optional. + * + * Note: Those these callbacks are called with struct media_device.@graph_mutex + * mutex held. */ struct media_entity_operations { int (*link_setup)(struct media_entity *entity, -- GitLab From b84fff5afb16627a8973256992f3951ac3e90d84 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 19 Apr 2016 13:12:43 +0800 Subject: [PATCH 3692/9938] ASoC: topology: Set the link ID when creating a FE DAI link Topology will set the link's generic id when creating a FE link. Device drivers can check the id for link specific initialization. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- include/uapi/sound/asoc.h | 2 +- sound/soc/soc-topology.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index db86b447b515..e4701a3c6331 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -423,7 +423,7 @@ struct snd_soc_tplg_pcm { __le32 size; /* in bytes of this structure */ char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - __le32 pcm_id; /* unique ID - used to match */ + __le32 pcm_id; /* unique ID - used to match with DAI link */ __le32 dai_id; /* unique ID - used to match */ __le32 playback; /* supports playback mode */ __le32 capture; /* supports capture mode */ diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 1cf94d7fb9f4..bdbfcef4c319 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1598,6 +1598,7 @@ static int soc_tplg_link_create(struct soc_tplg *tplg, link->name = pcm->pcm_name; link->stream_name = pcm->pcm_name; + link->id = pcm->pcm_id; /* pass control to component driver for optional further init */ ret = soc_tplg_dai_link_load(tplg, link); -- GitLab From 305e9020f09d28560373c0112682e6fd11e909f6 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 19 Apr 2016 13:12:25 +0800 Subject: [PATCH 3693/9938] ASoC: Export snd_soc_find_dai() This API can be used by topology to find an existing BE dai by name and further configure it. Topology will also check DAI ID to avoid wrong match. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- include/sound/soc.h | 3 +++ sound/soc/soc-core.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 02b4a215fd75..7687e2d4b0e4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1683,6 +1683,9 @@ void snd_soc_remove_dai_link(struct snd_soc_card *card, int snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv); +struct snd_soc_dai *snd_soc_find_dai( + const struct snd_soc_dai_link_component *dlc); + #include #ifdef CONFIG_DEBUG_FS diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d2e62b159610..07663def2db6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -930,7 +930,7 @@ static struct snd_soc_component *soc_find_component( return NULL; } -static struct snd_soc_dai *snd_soc_find_dai( +struct snd_soc_dai *snd_soc_find_dai( const struct snd_soc_dai_link_component *dlc) { struct snd_soc_component *component; @@ -959,6 +959,7 @@ static struct snd_soc_dai *snd_soc_find_dai( return NULL; } +EXPORT_SYMBOL_GPL(snd_soc_find_dai); static bool soc_is_dai_link_bound(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) -- GitLab From 67d1c21e37301ca3cea3705951950ce21f2723e1 Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Tue, 19 Apr 2016 13:12:50 +0800 Subject: [PATCH 3694/9938] ASoC: topology: Set CPU DAI name and enable DPCM by default for FE link When creating a FE link, the cpu_dai_name will come from topology and dpcm will be enabled by default. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index bdbfcef4c319..ca5f82885031 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1586,6 +1586,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, return snd_soc_register_dai(tplg->comp, dai_drv); } +/* create the FE DAI link */ static int soc_tplg_link_create(struct soc_tplg *tplg, struct snd_soc_tplg_pcm *pcm) { @@ -1600,6 +1601,15 @@ static int soc_tplg_link_create(struct soc_tplg *tplg, link->stream_name = pcm->pcm_name; link->id = pcm->pcm_id; + link->cpu_dai_name = pcm->dai_name; + link->codec_name = "snd-soc-dummy"; + link->codec_dai_name = "snd-soc-dummy-dai"; + + /* enable DPCM */ + link->dynamic = 1; + link->dpcm_playback = pcm->playback; + link->dpcm_capture = pcm->capture; + /* pass control to component driver for optional further init */ ret = soc_tplg_dai_link_load(tplg, link); if (ret < 0) { -- GitLab From 0ff59f3190ba7b380ca4387dab5eb69d2b8f4d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Fri, 11 Mar 2016 09:23:16 -0300 Subject: [PATCH 3695/9938] [media] TW686x frame grabber driver A driver for Intersil/Techwell TW686x-based PCIe frame grabbers. [hans.verkuil@cisco.com: renamed staging tw686x to tw686x-kh to prevent naming conflicts] [hans.verkuil@cisco.com: don't build tw686x-kh if tw686x is already selected to prevent conflicts] [mchehab@osg.samsung.com: use "unsigned int" instead of just "unsigned" and add some whitespaces to make checkpatch happier] Signed-off-by: Krzysztof Halasa Signed-off-by: Hans Verkuil Tested-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/Kconfig | 2 + drivers/staging/media/Makefile | 1 + drivers/staging/media/tw686x-kh/Kconfig | 17 + drivers/staging/media/tw686x-kh/Makefile | 3 + drivers/staging/media/tw686x-kh/TODO | 3 + .../staging/media/tw686x-kh/tw686x-kh-core.c | 140 +++ .../staging/media/tw686x-kh/tw686x-kh-regs.h | 103 +++ .../staging/media/tw686x-kh/tw686x-kh-video.c | 820 ++++++++++++++++++ drivers/staging/media/tw686x-kh/tw686x-kh.h | 118 +++ 9 files changed, 1207 insertions(+) create mode 100644 drivers/staging/media/tw686x-kh/Kconfig create mode 100644 drivers/staging/media/tw686x-kh/Makefile create mode 100644 drivers/staging/media/tw686x-kh/TODO create mode 100644 drivers/staging/media/tw686x-kh/tw686x-kh-core.c create mode 100644 drivers/staging/media/tw686x-kh/tw686x-kh-regs.h create mode 100644 drivers/staging/media/tw686x-kh/tw686x-kh-video.c create mode 100644 drivers/staging/media/tw686x-kh/tw686x-kh.h diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 0078b6a92f0b..de7e9f52e7eb 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -37,6 +37,8 @@ source "drivers/staging/media/omap4iss/Kconfig" source "drivers/staging/media/timb/Kconfig" +source "drivers/staging/media/tw686x-kh/Kconfig" + # Keep LIRC at the end, as it has sub-menus source "drivers/staging/media/lirc/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 91495882a36c..60a35b3a47e7 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ obj-$(CONFIG_VIDEO_TIMBERDALE) += timb/ +obj-$(CONFIG_VIDEO_TW686X_KH) += tw686x-kh/ diff --git a/drivers/staging/media/tw686x-kh/Kconfig b/drivers/staging/media/tw686x-kh/Kconfig new file mode 100644 index 000000000000..6264d30edf5a --- /dev/null +++ b/drivers/staging/media/tw686x-kh/Kconfig @@ -0,0 +1,17 @@ +config VIDEO_TW686X_KH + tristate "Intersil/Techwell TW686x Video For Linux" + depends on VIDEO_DEV && PCI && VIDEO_V4L2 + depends on !(VIDEO_TW686X=y || VIDEO_TW686X=m) || COMPILE_TEST + select VIDEOBUF2_DMA_SG + help + Support for Intersil/Techwell TW686x-based frame grabber cards. + + Currently supported chips: + - TW6864 (4 video channels), + - TW6865 (4 video channels, not tested, second generation chip), + - TW6868 (8 video channels but only 4 first channels using + built-in video decoder are supported, not tested), + - TW6869 (8 video channels, second generation chip). + + To compile this driver as a module, choose M here: the module + will be named tw686x-kh. diff --git a/drivers/staging/media/tw686x-kh/Makefile b/drivers/staging/media/tw686x-kh/Makefile new file mode 100644 index 000000000000..2a36a38cf30e --- /dev/null +++ b/drivers/staging/media/tw686x-kh/Makefile @@ -0,0 +1,3 @@ +tw686x-kh-objs := tw686x-kh-core.o tw686x-kh-video.o + +obj-$(CONFIG_VIDEO_TW686X_KH) += tw686x-kh.o diff --git a/drivers/staging/media/tw686x-kh/TODO b/drivers/staging/media/tw686x-kh/TODO new file mode 100644 index 000000000000..f226e808390e --- /dev/null +++ b/drivers/staging/media/tw686x-kh/TODO @@ -0,0 +1,3 @@ +TODO: implement V4L2_FIELD_INTERLACED* mode(s). + +Please Cc: patches to Krzysztof Halasa . diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-core.c b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c new file mode 100644 index 000000000000..c3c5c2602541 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * Written by Krzysztof Ha?asa. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include "tw686x-kh.h" +#include "tw686x-kh-regs.h" + +static irqreturn_t tw686x_irq(int irq, void *dev_id) +{ + struct tw686x_dev *dev = (struct tw686x_dev *)dev_id; + u32 int_status = reg_read(dev, INT_STATUS); /* cleared on read */ + unsigned long flags; + unsigned int handled = 0; + + if (int_status) { + spin_lock_irqsave(&dev->irq_lock, flags); + dev->dma_requests |= int_status; + spin_unlock_irqrestore(&dev->irq_lock, flags); + + if (int_status & 0xFF0000FF) + handled = tw686x_video_irq(dev); + } + + return IRQ_RETVAL(handled); +} + +static int tw686x_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) +{ + struct tw686x_dev *dev; + int err; + + dev = devm_kzalloc(&pci_dev->dev, sizeof(*dev) + + (pci_id->driver_data & TYPE_MAX_CHANNELS) * + sizeof(dev->video_channels[0]), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + sprintf(dev->name, "TW%04X", pci_dev->device); + dev->type = pci_id->driver_data; + + pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name, + pci_name(pci_dev), pci_dev->irq, + (unsigned long)pci_resource_start(pci_dev, 0)); + + dev->pci_dev = pci_dev; + if (pcim_enable_device(pci_dev)) + return -EIO; + + pci_set_master(pci_dev); + + if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { + pr_err("%s: 32-bit PCI DMA not supported\n", dev->name); + return -EIO; + } + + err = pci_request_regions(pci_dev, dev->name); + if (err < 0) { + pr_err("%s: Unable to get MMIO region\n", dev->name); + return err; + } + + dev->mmio = pci_ioremap_bar(pci_dev, 0); + if (!dev->mmio) { + pr_err("%s: Unable to remap MMIO region\n", dev->name); + return -EIO; + } + + reg_write(dev, SYS_SOFT_RST, 0x0F); /* Reset all subsystems */ + mdelay(1); + + reg_write(dev, SRST[0], 0x3F); + if (max_channels(dev) > 4) + reg_write(dev, SRST[1], 0x3F); + reg_write(dev, DMA_CMD, 0); + reg_write(dev, DMA_CHANNEL_ENABLE, 0); + reg_write(dev, DMA_CHANNEL_TIMEOUT, 0x3EFF0FF0); + reg_write(dev, DMA_TIMER_INTERVAL, 0x38000); + reg_write(dev, DMA_CONFIG, 0xFFFFFF04); + + spin_lock_init(&dev->irq_lock); + + err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw686x_irq, + IRQF_SHARED, dev->name, dev); + if (err < 0) { + pr_err("%s: Unable to get IRQ\n", dev->name); + return err; + } + + err = tw686x_video_init(dev); + if (err) + return err; + + pci_set_drvdata(pci_dev, dev); + return 0; +} + +static void tw686x_remove(struct pci_dev *pci_dev) +{ + struct tw686x_dev *dev = pci_get_drvdata(pci_dev); + + tw686x_video_free(dev); +} + +/* driver_data is number of A/V channels */ +static const struct pci_device_id tw686x_pci_tbl[] = { + {PCI_DEVICE(0x1797, 0x6864), .driver_data = 4}, + /* not tested */ + {PCI_DEVICE(0x1797, 0x6865), .driver_data = 4 | TYPE_SECOND_GEN}, + /* TW6868 supports 8 A/V channels with an external TW2865 chip - + not supported by the driver */ + {PCI_DEVICE(0x1797, 0x6868), .driver_data = 4}, /* not tested */ + {PCI_DEVICE(0x1797, 0x6869), .driver_data = 8 | TYPE_SECOND_GEN}, + {} +}; + +static struct pci_driver tw686x_pci_driver = { + .name = "tw686x-kh", + .id_table = tw686x_pci_tbl, + .probe = tw686x_probe, + .remove = tw686x_remove, +}; + +MODULE_DESCRIPTION("Driver for video frame grabber cards based on Intersil/Techwell TW686[4589]"); +MODULE_AUTHOR("Krzysztof Halasa"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl); +module_pci_driver(tw686x_pci_driver); diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h b/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h new file mode 100644 index 000000000000..53e1889babd0 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h @@ -0,0 +1,103 @@ +/* DMA controller registers */ +#define REG8_1(a0) ((const u16[8]) {a0, a0 + 1, a0 + 2, a0 + 3, \ + a0 + 4, a0 + 5, a0 + 6, a0 + 7}) +#define REG8_2(a0) ((const u16[8]) {a0, a0 + 2, a0 + 4, a0 + 6, \ + a0 + 8, a0 + 0xA, a0 + 0xC, a0 + 0xE}) +#define REG8_8(a0) ((const u16[8]) {a0, a0 + 8, a0 + 0x10, a0 + 0x18, \ + a0 + 0x20, a0 + 0x28, a0 + 0x30, a0 + 0x38}) +#define INT_STATUS 0x00 +#define PB_STATUS 0x01 +#define DMA_CMD 0x02 +#define VIDEO_FIFO_STATUS 0x03 +#define VIDEO_CHANNEL_ID 0x04 +#define VIDEO_PARSER_STATUS 0x05 +#define SYS_SOFT_RST 0x06 +#define DMA_PAGE_TABLE0_ADDR ((const u16[8]) {0x08, 0xD0, 0xD2, 0xD4, \ + 0xD6, 0xD8, 0xDA, 0xDC}) +#define DMA_PAGE_TABLE1_ADDR ((const u16[8]) {0x09, 0xD1, 0xD3, 0xD5, \ + 0xD7, 0xD9, 0xDB, 0xDD}) +#define DMA_CHANNEL_ENABLE 0x0A +#define DMA_CONFIG 0x0B +#define DMA_TIMER_INTERVAL 0x0C +#define DMA_CHANNEL_TIMEOUT 0x0D +#define VDMA_CHANNEL_CONFIG REG8_1(0x10) +#define ADMA_P_ADDR REG8_2(0x18) +#define ADMA_B_ADDR REG8_2(0x19) +#define DMA10_P_ADDR 0x28 /* ??? */ +#define DMA10_B_ADDR 0x29 +#define VIDEO_CONTROL1 0x2A +#define VIDEO_CONTROL2 0x2B +#define AUDIO_CONTROL1 0x2C +#define AUDIO_CONTROL2 0x2D +#define PHASE_REF 0x2E +#define GPIO_REG 0x2F +#define INTL_HBAR_CTRL REG8_1(0x30) +#define AUDIO_CONTROL3 0x38 +#define VIDEO_FIELD_CTRL REG8_1(0x39) +#define HSCALER_CTRL REG8_1(0x42) +#define VIDEO_SIZE REG8_1(0x4A) +#define VIDEO_SIZE_F2 REG8_1(0x52) +#define MD_CONF REG8_1(0x60) +#define MD_INIT REG8_1(0x68) +#define MD_MAP0 REG8_1(0x70) +#define VDMA_P_ADDR REG8_8(0x80) /* not used in DMA SG mode */ +#define VDMA_WHP REG8_8(0x81) +#define VDMA_B_ADDR REG8_8(0x82) +#define VDMA_F2_P_ADDR REG8_8(0x84) +#define VDMA_F2_WHP REG8_8(0x85) +#define VDMA_F2_B_ADDR REG8_8(0x86) +#define EP_REG_ADDR 0xFE +#define EP_REG_DATA 0xFF + +/* Video decoder registers */ +#define VDREG8(a0) ((const u16[8]) { \ + a0 + 0x000, a0 + 0x010, a0 + 0x020, a0 + 0x030, \ + a0 + 0x100, a0 + 0x110, a0 + 0x120, a0 + 0x130}) +#define VIDSTAT VDREG8(0x100) +#define BRIGHT VDREG8(0x101) +#define CONTRAST VDREG8(0x102) +#define SHARPNESS VDREG8(0x103) +#define SAT_U VDREG8(0x104) +#define SAT_V VDREG8(0x105) +#define HUE VDREG8(0x106) +#define CROP_HI VDREG8(0x107) +#define VDELAY_LO VDREG8(0x108) +#define VACTIVE_LO VDREG8(0x109) +#define HDELAY_LO VDREG8(0x10A) +#define HACTIVE_LO VDREG8(0x10B) +#define MVSN VDREG8(0x10C) +#define STATUS2 VDREG8(0x10C) +#define SDT VDREG8(0x10E) +#define SDT_EN VDREG8(0x10F) + +#define VSCALE_LO VDREG8(0x144) +#define SCALE_HI VDREG8(0x145) +#define HSCALE_LO VDREG8(0x146) +#define F2CROP_HI VDREG8(0x147) +#define F2VDELAY_LO VDREG8(0x148) +#define F2VACTIVE_LO VDREG8(0x149) +#define F2HDELAY_LO VDREG8(0x14A) +#define F2HACTIVE_LO VDREG8(0x14B) +#define F2VSCALE_LO VDREG8(0x14C) +#define F2SCALE_HI VDREG8(0x14D) +#define F2HSCALE_LO VDREG8(0x14E) +#define F2CNT VDREG8(0x14F) + +#define VDREG2(a0) ((const u16[2]) {a0, a0 + 0x100}) +#define SRST VDREG2(0x180) +#define ACNTL VDREG2(0x181) +#define ACNTL2 VDREG2(0x182) +#define CNTRL1 VDREG2(0x183) +#define CKHY VDREG2(0x184) +#define SHCOR VDREG2(0x185) +#define CORING VDREG2(0x186) +#define CLMPG VDREG2(0x187) +#define IAGC VDREG2(0x188) +#define VCTRL1 VDREG2(0x18F) +#define MISC1 VDREG2(0x194) +#define LOOP VDREG2(0x195) +#define MISC2 VDREG2(0x196) + +#define CLMD VDREG2(0x197) +#define AIGAIN ((const u16[8]) {0x1D0, 0x1D1, 0x1D2, 0x1D3, \ + 0x2D0, 0x2D1, 0x2D2, 0x2D3}) diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c new file mode 100644 index 000000000000..2fbc3cbd9eb0 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c @@ -0,0 +1,820 @@ +/* + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * Written by Krzysztof Ha?asa. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "tw686x-kh.h" +#include "tw686x-kh-regs.h" + +#define MAX_SG_ENTRY_SIZE (/* 8192 - 128 */ 4096) +#define MAX_SG_DESC_COUNT 256 /* PAL 704x576 needs up to 198 4-KB pages */ + +static const struct tw686x_format formats[] = { + { + .name = "4:2:2 packed, UYVY", /* aka Y422 */ + .fourcc = V4L2_PIX_FMT_UYVY, + .mode = 0, + .depth = 16, + }, { +#if 0 + .name = "4:2:0 packed, YUV", + .mode = 1, /* non-standard */ + .depth = 12, + }, { + .name = "4:1:1 packed, YUV", + .mode = 2, /* non-standard */ + .depth = 12, + }, { +#endif + .name = "4:1:1 packed, YUV", + .fourcc = V4L2_PIX_FMT_Y41P, + .mode = 3, + .depth = 12, + }, { + .name = "15 bpp RGB", + .fourcc = V4L2_PIX_FMT_RGB555, + .mode = 4, + .depth = 16, + }, { + .name = "16 bpp RGB", + .fourcc = V4L2_PIX_FMT_RGB565, + .mode = 5, + .depth = 16, + }, { + .name = "4:2:2 packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .mode = 6, + .depth = 16, + } + /* mode 7 is "reserved" */ +}; + +static const v4l2_std_id video_standards[7] = { + V4L2_STD_NTSC, + V4L2_STD_PAL, + V4L2_STD_SECAM, + V4L2_STD_NTSC_443, + V4L2_STD_PAL_M, + V4L2_STD_PAL_N, + V4L2_STD_PAL_60, +}; + +static const struct tw686x_format *format_by_fourcc(unsigned int fourcc) +{ + unsigned int cnt; + + for (cnt = 0; cnt < ARRAY_SIZE(formats); cnt++) + if (formats[cnt].fourcc == fourcc) + return &formats[cnt]; + return NULL; +} + +static void tw686x_get_format(struct tw686x_video_channel *vc, + struct v4l2_format *f) +{ + const struct tw686x_format *format; + unsigned int width, height, height_div = 1; + + format = format_by_fourcc(f->fmt.pix.pixelformat); + if (!format) { + format = &formats[0]; + f->fmt.pix.pixelformat = format->fourcc; + } + + width = 704; + if (f->fmt.pix.width < width * 3 / 4 /* halfway */) + width /= 2; + + height = (vc->video_standard & V4L2_STD_625_50) ? 576 : 480; + if (f->fmt.pix.height < height * 3 / 4 /* halfway */) + height_div = 2; + + switch (f->fmt.pix.field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + height_div = 2; + break; + case V4L2_FIELD_SEQ_BT: + if (height_div > 1) + f->fmt.pix.field = V4L2_FIELD_BOTTOM; + break; + default: + if (height_div > 1) + f->fmt.pix.field = V4L2_FIELD_TOP; + else + f->fmt.pix.field = V4L2_FIELD_SEQ_TB; + } + height /= height_div; + + f->fmt.pix.width = width; + f->fmt.pix.height = height; + f->fmt.pix.bytesperline = f->fmt.pix.width * format->depth / 8; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; +} + +/* video queue operations */ + +static int tw686x_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, + unsigned int *nplanes, unsigned int sizes[], + void *alloc_ctxs[]) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + unsigned int size = vc->width * vc->height * vc->format->depth / 8; + + alloc_ctxs[0] = vc->alloc_ctx; + if (*nbuffers < 2) + *nbuffers = 2; + + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; + + sizes[0] = size; + *nplanes = 1; /* packed formats only */ + return 0; +} + +static void tw686x_buf_queue(struct vb2_buffer *vb) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct tw686x_vb2_buf *buf; + + buf = container_of(vbuf, struct tw686x_vb2_buf, vb); + + spin_lock(&vc->qlock); + list_add_tail(&buf->list, &vc->vidq_queued); + spin_unlock(&vc->qlock); +} + +static void setup_descs(struct tw686x_video_channel *vc, unsigned int n) +{ +loop: + while (!list_empty(&vc->vidq_queued)) { + struct vdma_desc *descs = vc->sg_descs[n]; + struct tw686x_vb2_buf *buf; + struct sg_table *vbuf; + struct scatterlist *sg; + unsigned int buf_len, count = 0; + int i; + + buf = list_first_entry(&vc->vidq_queued, struct tw686x_vb2_buf, + list); + list_del(&buf->list); + + buf_len = vc->width * vc->height * vc->format->depth / 8; + if (vb2_plane_size(&buf->vb.vb2_buf, 0) < buf_len) { + pr_err("Video buffer size too small\n"); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + goto loop; /* try another */ + } + + vbuf = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0); + for_each_sg(vbuf->sgl, sg, vbuf->nents, i) { + dma_addr_t phys = sg_dma_address(sg); + unsigned int len = sg_dma_len(sg); + + while (len && buf_len) { + unsigned int entry_len = min_t(unsigned int, len, + MAX_SG_ENTRY_SIZE); + entry_len = min(entry_len, buf_len); + if (count == MAX_SG_DESC_COUNT) { + pr_err("Video buffer size too fragmented\n"); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + goto loop; + } + descs[count].phys = cpu_to_le32(phys); + descs[count++].flags_length = + cpu_to_le32(0x40000000 /* available */ | + entry_len); + phys += entry_len; + len -= entry_len; + buf_len -= entry_len; + } + if (!buf_len) + break; + } + + /* clear the remaining entries */ + while (count < MAX_SG_DESC_COUNT) { + descs[count].phys = 0; + descs[count++].flags_length = 0; /* unavailable */ + } + + buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; + vc->curr_bufs[n] = buf; + return; + } + vc->curr_bufs[n] = NULL; +} + +/* On TW6864 and TW6868, all channels share the pair of video DMA SG tables, + with 10-bit start_idx and end_idx determining start and end of frame buffer + for particular channel. + TW6868 with all its 8 channels would be problematic (only 127 SG entries per + channel) but we support only 4 channels on this chip anyway (the first + 4 channels are driven with internal video decoder, the other 4 would require + an external TW286x part). + + On TW6865 and TW6869, each channel has its own DMA SG table, with indexes + starting with 0. Both chips have complete sets of internal video decoders + (respectively 4 or 8-channel). + + All chips have separate SG tables for two video frames. */ + +static void setup_dma_cfg(struct tw686x_video_channel *vc) +{ + unsigned int field_width = 704; + unsigned int field_height = (vc->video_standard & V4L2_STD_625_50) ? + 288 : 240; + unsigned int start_idx = is_second_gen(vc->dev) ? 0 : + vc->ch * MAX_SG_DESC_COUNT; + unsigned int end_idx = start_idx + MAX_SG_DESC_COUNT - 1; + u32 dma_cfg = (0 << 30) /* input selection */ | + (1 << 29) /* field2 dropped (if any) */ | + ((vc->height < 300) << 28) /* field dropping */ | + (1 << 27) /* master */ | + (0 << 25) /* master channel (for slave only) */ | + (0 << 24) /* (no) vertical (line) decimation */ | + ((vc->width < 400) << 23) /* horizontal decimation */ | + (vc->format->mode << 20) /* output video format */ | + (end_idx << 10) /* DMA end index */ | + start_idx /* DMA start index */; + u32 reg; + + reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], dma_cfg); + reg_write(vc->dev, VIDEO_SIZE[vc->ch], (1 << 31) | (field_height << 16) + | field_width); + reg = reg_read(vc->dev, VIDEO_CONTROL1); + if (vc->video_standard & V4L2_STD_625_50) + reg |= 1 << (vc->ch + 13); + else + reg &= ~(1 << (vc->ch + 13)); + reg_write(vc->dev, VIDEO_CONTROL1, reg); +} + +static int tw686x_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + struct tw686x_dev *dev = vc->dev; + u32 dma_ch_mask; + unsigned int n; + + setup_dma_cfg(vc); + + /* queue video buffers if available */ + spin_lock(&vc->qlock); + for (n = 0; n < 2; n++) + setup_descs(vc, n); + spin_unlock(&vc->qlock); + + dev->video_active |= 1 << vc->ch; + vc->seq = 0; + dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE) | (1 << vc->ch); + reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask); + reg_write(dev, DMA_CMD, (1 << 31) | dma_ch_mask); + return 0; +} + +static void tw686x_stop_streaming(struct vb2_queue *vq) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + struct tw686x_dev *dev = vc->dev; + u32 dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE); + u32 dma_cmd = reg_read(dev, DMA_CMD); + unsigned int n; + + dma_ch_mask &= ~(1 << vc->ch); + reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask); + + dev->video_active &= ~(1 << vc->ch); + + dma_cmd &= ~(1 << vc->ch); + reg_write(dev, DMA_CMD, dma_cmd); + + if (!dev->video_active) { + reg_write(dev, DMA_CMD, 0); + reg_write(dev, DMA_CHANNEL_ENABLE, 0); + } + + spin_lock(&vc->qlock); + while (!list_empty(&vc->vidq_queued)) { + struct tw686x_vb2_buf *buf; + + buf = list_entry(vc->vidq_queued.next, struct tw686x_vb2_buf, + list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + + for (n = 0; n < 2; n++) + if (vc->curr_bufs[n]) + vb2_buffer_done(&vc->curr_bufs[n]->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + + spin_unlock(&vc->qlock); +} + +static struct vb2_ops tw686x_video_qops = { + .queue_setup = tw686x_queue_setup, + .buf_queue = tw686x_buf_queue, + .start_streaming = tw686x_start_streaming, + .stop_streaming = tw686x_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static int tw686x_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct tw686x_video_channel *vc; + struct tw686x_dev *dev; + unsigned int ch; + + vc = container_of(ctrl->handler, struct tw686x_video_channel, + ctrl_handler); + dev = vc->dev; + ch = vc->ch; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + reg_write(dev, BRIGHT[ch], ctrl->val & 0xFF); + return 0; + + case V4L2_CID_CONTRAST: + reg_write(dev, CONTRAST[ch], ctrl->val); + return 0; + + case V4L2_CID_SATURATION: + reg_write(dev, SAT_U[ch], ctrl->val); + reg_write(dev, SAT_V[ch], ctrl->val); + return 0; + + case V4L2_CID_HUE: + reg_write(dev, HUE[ch], ctrl->val & 0xFF); + return 0; + } + + return -EINVAL; +} + +static const struct v4l2_ctrl_ops ctrl_ops = { + .s_ctrl = tw686x_s_ctrl, +}; + +static int tw686x_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + f->fmt.pix.width = vc->width; + f->fmt.pix.height = vc->height; + f->fmt.pix.field = vc->field; + f->fmt.pix.pixelformat = vc->format->fourcc; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.bytesperline = f->fmt.pix.width * vc->format->depth / 8; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + return 0; +} + +static int tw686x_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + tw686x_get_format(video_drvdata(file), f); + return 0; +} + +static int tw686x_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + tw686x_get_format(vc, f); + vc->format = format_by_fourcc(f->fmt.pix.pixelformat); + vc->field = f->fmt.pix.field; + vc->width = f->fmt.pix.width; + vc->height = f->fmt.pix.height; + return 0; +} + +static int tw686x_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + struct tw686x_dev *dev = vc->dev; + + strcpy(cap->driver, "tw686x-kh"); + strcpy(cap->card, dev->name); + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci_dev)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + unsigned int cnt; + u32 sdt = 0; /* default */ + + for (cnt = 0; cnt < ARRAY_SIZE(video_standards); cnt++) + if (id & video_standards[cnt]) { + sdt = cnt; + break; + } + + reg_write(vc->dev, SDT[vc->ch], sdt); + vc->video_standard = video_standards[sdt]; + return 0; +} + +static int tw686x_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + *id = vc->video_standard; + return 0; +} + +static int tw686x_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + f->pixelformat = formats[f->index].fourcc; + return 0; +} + +static int tw686x_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *sp) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + memset(&sp->parm.capture, 0, sizeof(sp->parm.capture)); + sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + v4l2_video_std_frame_period(vc->video_standard, + &sp->parm.capture.timeperframe); + + return 0; +} + +static int tw686x_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + /* the chip has internal multiplexer, support can be added + if the actual hw uses it */ + if (inp->index) + return -EINVAL; + + snprintf(inp->name, sizeof(inp->name), "Composite"); + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_ALL; + inp->capabilities = V4L2_IN_CAP_STD; + return 0; +} + +static int tw686x_g_input(struct file *file, void *priv, unsigned int *v) +{ + *v = 0; + return 0; +} + +static int tw686x_s_input(struct file *file, void *priv, unsigned int v) +{ + if (v) + return -EINVAL; + return 0; +} + +const struct v4l2_file_operations tw686x_video_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .unlocked_ioctl = video_ioctl2, + .release = vb2_fop_release, + .poll = vb2_fop_poll, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, +}; + +const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = { + .vidioc_querycap = tw686x_querycap, + .vidioc_enum_fmt_vid_cap = tw686x_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = tw686x_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = tw686x_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = tw686x_try_fmt_vid_cap, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_g_std = tw686x_g_std, + .vidioc_s_std = tw686x_s_std, + .vidioc_g_parm = tw686x_g_parm, + .vidioc_enum_input = tw686x_enum_input, + .vidioc_g_input = tw686x_g_input, + .vidioc_s_input = tw686x_s_input, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static int video_thread(void *arg) +{ + struct tw686x_dev *dev = arg; + DECLARE_WAITQUEUE(wait, current); + + set_freezable(); + add_wait_queue(&dev->video_thread_wait, &wait); + + while (1) { + long timeout = schedule_timeout_interruptible(HZ); + unsigned int ch; + + if (timeout == -ERESTARTSYS || kthread_should_stop()) + break; + + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc; + unsigned long flags; + u32 request, n, stat = VB2_BUF_STATE_DONE; + + vc = &dev->video_channels[ch]; + if (!(dev->video_active & (1 << ch))) + continue; + + spin_lock_irq(&dev->irq_lock); + request = dev->dma_requests & (0x01000001 << ch); + if (request) + dev->dma_requests &= ~request; + spin_unlock_irq(&dev->irq_lock); + + if (!request) + continue; + + request >>= ch; + + /* handle channel events */ + if ((request & 0x01000000) | + (reg_read(dev, VIDEO_FIFO_STATUS) & (0x01010001 << ch)) | + (reg_read(dev, VIDEO_PARSER_STATUS) & (0x00000101 << ch))) { + /* DMA Errors - reset channel */ + u32 reg; + + spin_lock_irqsave(&dev->irq_lock, flags); + reg = reg_read(dev, DMA_CMD); + /* Reset DMA channel */ + reg_write(dev, DMA_CMD, reg & ~(1 << ch)); + reg_write(dev, DMA_CMD, reg); + spin_unlock_irqrestore(&dev->irq_lock, flags); + stat = VB2_BUF_STATE_ERROR; + } + + /* handle video stream */ + mutex_lock(&vc->vb_mutex); + spin_lock(&vc->qlock); + n = !!(reg_read(dev, PB_STATUS) & (1 << ch)); + if (vc->curr_bufs[n]) { + struct vb2_v4l2_buffer *vb; + + vb = &vc->curr_bufs[n]->vb; + vb->vb2_buf.timestamp = ktime_get_ns(); + vb->field = vc->field; + if (V4L2_FIELD_HAS_BOTH(vc->field)) + vb->sequence = vc->seq++; + else + vb->sequence = (vc->seq++) / 2; + vb2_set_plane_payload(&vb->vb2_buf, 0, + vc->width * vc->height * vc->format->depth / 8); + vb2_buffer_done(&vb->vb2_buf, stat); + } + setup_descs(vc, n); + spin_unlock(&vc->qlock); + mutex_unlock(&vc->vb_mutex); + } + try_to_freeze(); + } + + remove_wait_queue(&dev->video_thread_wait, &wait); + return 0; +} + +int tw686x_video_irq(struct tw686x_dev *dev) +{ + unsigned long flags, handled = 0; + u32 requests; + + spin_lock_irqsave(&dev->irq_lock, flags); + requests = dev->dma_requests; + spin_unlock_irqrestore(&dev->irq_lock, flags); + + if (dev->dma_requests & dev->video_active) { + wake_up_interruptible_all(&dev->video_thread_wait); + handled = 1; + } + return handled; +} + +void tw686x_video_free(struct tw686x_dev *dev) +{ + unsigned int ch, n; + + if (dev->video_thread) + kthread_stop(dev->video_thread); + + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + + v4l2_ctrl_handler_free(&vc->ctrl_handler); + if (vc->device) + video_unregister_device(vc->device); + vb2_dma_sg_cleanup_ctx(vc->alloc_ctx); + for (n = 0; n < 2; n++) { + struct dma_desc *descs = &vc->sg_tables[n]; + + if (descs->virt) + pci_free_consistent(dev->pci_dev, descs->size, + descs->virt, descs->phys); + } + } + + v4l2_device_unregister(&dev->v4l2_dev); +} + +#define SG_TABLE_SIZE (MAX_SG_DESC_COUNT * sizeof(struct vdma_desc)) + +int tw686x_video_init(struct tw686x_dev *dev) +{ + unsigned int ch, n; + int err; + + init_waitqueue_head(&dev->video_thread_wait); + + err = v4l2_device_register(&dev->pci_dev->dev, &dev->v4l2_dev); + if (err) + return err; + + reg_write(dev, VIDEO_CONTROL1, 0); /* NTSC, disable scaler */ + reg_write(dev, PHASE_REF, 0x00001518); /* Scatter-gather DMA mode */ + + /* setup required SG table sizes */ + for (n = 0; n < 2; n++) + if (is_second_gen(dev)) { + /* TW 6865, TW6869 - each channel needs a pair of + descriptor tables */ + for (ch = 0; ch < max_channels(dev); ch++) + dev->video_channels[ch].sg_tables[n].size = + SG_TABLE_SIZE; + + } else + /* TW 6864, TW6868 - we need to allocate a pair of + descriptor tables, common for all channels. + Each table will be bigger than 4 KB. */ + dev->video_channels[0].sg_tables[n].size = + max_channels(dev) * SG_TABLE_SIZE; + + /* allocate SG tables and initialize video channels */ + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + struct video_device *vdev; + + mutex_init(&vc->vb_mutex); + spin_lock_init(&vc->qlock); + INIT_LIST_HEAD(&vc->vidq_queued); + + vc->dev = dev; + vc->ch = ch; + + /* default settings: NTSC */ + vc->format = &formats[0]; + vc->video_standard = V4L2_STD_NTSC; + reg_write(vc->dev, SDT[vc->ch], 0); + vc->field = V4L2_FIELD_SEQ_BT; + vc->width = 704; + vc->height = 480; + + for (n = 0; n < 2; n++) { + void *cpu; + + if (vc->sg_tables[n].size) { + unsigned int reg = n ? DMA_PAGE_TABLE1_ADDR[ch] : + DMA_PAGE_TABLE0_ADDR[ch]; + + cpu = pci_alloc_consistent(dev->pci_dev, + vc->sg_tables[n].size, + &vc->sg_tables[n].phys); + if (!cpu) { + pr_err("Error allocating video DMA scatter-gather tables\n"); + err = -ENOMEM; + goto error; + } + vc->sg_tables[n].virt = cpu; + reg_write(dev, reg, vc->sg_tables[n].phys); + } else + cpu = dev->video_channels[0].sg_tables[n].virt + + ch * SG_TABLE_SIZE; + + vc->sg_descs[n] = cpu; + } + + reg_write(dev, VCTRL1[0], 0x24); + reg_write(dev, LOOP[0], 0xA5); + if (max_channels(dev) > 4) { + reg_write(dev, VCTRL1[1], 0x24); + reg_write(dev, LOOP[1], 0xA5); + } + reg_write(dev, VIDEO_FIELD_CTRL[ch], 0); + reg_write(dev, VDELAY_LO[ch], 0x14); + + vdev = video_device_alloc(); + if (!vdev) { + pr_warn("Unable to allocate video device\n"); + err = -ENOMEM; + goto error; + } + + vc->alloc_ctx = vb2_dma_sg_init_ctx(&dev->pci_dev->dev); + if (IS_ERR(vc->alloc_ctx)) { + pr_warn("Unable to initialize DMA scatter-gather context\n"); + err = PTR_ERR(vc->alloc_ctx); + goto error; + } + + vc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + vc->vidq.drv_priv = vc; + vc->vidq.buf_struct_size = sizeof(struct tw686x_vb2_buf); + vc->vidq.ops = &tw686x_video_qops; + vc->vidq.mem_ops = &vb2_dma_sg_memops; + vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + vc->vidq.min_buffers_needed = 2; + vc->vidq.lock = &vc->vb_mutex; + + err = vb2_queue_init(&vc->vidq); + if (err) + goto error; + + strcpy(vdev->name, "TW686x-video"); + snprintf(vdev->name, sizeof(vdev->name), "%s video", dev->name); + vdev->fops = &tw686x_video_fops; + vdev->ioctl_ops = &tw686x_video_ioctl_ops; + vdev->release = video_device_release; + vdev->v4l2_dev = &dev->v4l2_dev; + vdev->queue = &vc->vidq; + vdev->tvnorms = V4L2_STD_ALL; + vdev->minor = -1; + vdev->lock = &vc->vb_mutex; + + dev->video_channels[ch].device = vdev; + video_set_drvdata(vdev, vc); + err = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (err < 0) + goto error; + + v4l2_ctrl_handler_init(&vc->ctrl_handler, + 4 /* number of controls */); + vdev->ctrl_handler = &vc->ctrl_handler; + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 64); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 128); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, V4L2_CID_HUE, + -124, 127, 1, 0); + err = vc->ctrl_handler.error; + if (err) + goto error; + + v4l2_ctrl_handler_setup(&vc->ctrl_handler); + } + + dev->video_thread = kthread_run(video_thread, dev, "tw686x_video"); + if (IS_ERR(dev->video_thread)) { + err = PTR_ERR(dev->video_thread); + goto error; + } + + return 0; + +error: + tw686x_video_free(dev); + return err; +} diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh.h b/drivers/staging/media/tw686x-kh/tw686x-kh.h new file mode 100644 index 000000000000..46c4ebd7f00c --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * Written by Krzysztof Ha?asa. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TYPE_MAX_CHANNELS 0x0F +#define TYPE_SECOND_GEN 0x10 + +struct tw686x_format { + char *name; + unsigned int fourcc; + unsigned int depth; + unsigned int mode; +}; + +struct dma_desc { + dma_addr_t phys; + void *virt; + unsigned int size; +}; + +struct vdma_desc { + __le32 flags_length; /* 3 MSBits for flags, 13 LSBits for length */ + __le32 phys; +}; + +struct tw686x_vb2_buf { + struct vb2_v4l2_buffer vb; + struct list_head list; +}; + +struct tw686x_video_channel { + struct tw686x_dev *dev; + + struct vb2_queue vidq; + struct list_head vidq_queued; + struct video_device *device; + struct dma_desc sg_tables[2]; + struct tw686x_vb2_buf *curr_bufs[2]; + void *alloc_ctx; + struct vdma_desc *sg_descs[2]; + + struct v4l2_ctrl_handler ctrl_handler; + const struct tw686x_format *format; + struct mutex vb_mutex; + spinlock_t qlock; + v4l2_std_id video_standard; + unsigned int width, height; + enum v4l2_field field; /* supported TOP, BOTTOM, SEQ_TB and SEQ_BT */ + unsigned int seq; /* video field or frame counter */ + unsigned int ch; +}; + +/* global device status */ +struct tw686x_dev { + spinlock_t irq_lock; + + struct v4l2_device v4l2_dev; + struct snd_card *card; /* sound card */ + + unsigned int video_active; /* active video channel mask */ + + char name[32]; + unsigned int type; + struct pci_dev *pci_dev; + __u32 __iomem *mmio; + + struct task_struct *video_thread; + wait_queue_head_t video_thread_wait; + u32 dma_requests; + + struct tw686x_video_channel video_channels[0]; +}; + +static inline uint32_t reg_read(struct tw686x_dev *dev, unsigned int reg) +{ + return readl(dev->mmio + reg); +} + +static inline void reg_write(struct tw686x_dev *dev, unsigned int reg, + uint32_t value) +{ + writel(value, dev->mmio + reg); +} + +static inline unsigned int max_channels(struct tw686x_dev *dev) +{ + return dev->type & TYPE_MAX_CHANNELS; /* 4 or 8 channels */ +} + +static inline unsigned int is_second_gen(struct tw686x_dev *dev) +{ + /* each channel has its own DMA SG table */ + return dev->type & TYPE_SECOND_GEN; +} + +int tw686x_video_irq(struct tw686x_dev *dev); +int tw686x_video_init(struct tw686x_dev *dev); +void tw686x_video_free(struct tw686x_dev *dev); -- GitLab From 704a84ccdbf19fdce9adfda0b936dfdcac52fa49 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 2 Mar 2016 11:30:16 -0300 Subject: [PATCH 3696/9938] [media] media: Support Intersil/Techwell TW686x-based video capture cards This commit introduces the support for the Techwell TW686x video capture IC. This hardware supports a few DMA modes, including scatter-gather and frame (contiguous). This commit makes little use of the DMA engine and instead has a memcpy based implementation. DMA frame and scatter-gather modes support may be added in the future. Currently supported chips: - TW6864 (4 video channels), - TW6865 (4 video channels, not tested, second generation chip), - TW6868 (8 video channels but only 4 first channels using built-in video decoder are supported, not tested), - TW6869 (8 video channels, second generation chip). [mchehab@osg.samsung.com: make checkpatch happy by using "unsigned int" instead of just "unsigned"] Cc: Krzysztof Halasa Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Tested-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 8 + drivers/media/pci/Kconfig | 1 + drivers/media/pci/Makefile | 1 + drivers/media/pci/tw686x/Kconfig | 18 + drivers/media/pci/tw686x/Makefile | 3 + drivers/media/pci/tw686x/tw686x-audio.c | 386 ++++++++++ drivers/media/pci/tw686x/tw686x-core.c | 415 +++++++++++ drivers/media/pci/tw686x/tw686x-regs.h | 122 ++++ drivers/media/pci/tw686x/tw686x-video.c | 927 ++++++++++++++++++++++++ drivers/media/pci/tw686x/tw686x.h | 158 ++++ 10 files changed, 2039 insertions(+) create mode 100644 drivers/media/pci/tw686x/Kconfig create mode 100644 drivers/media/pci/tw686x/Makefile create mode 100644 drivers/media/pci/tw686x/tw686x-audio.c create mode 100644 drivers/media/pci/tw686x/tw686x-core.c create mode 100644 drivers/media/pci/tw686x/tw686x-regs.h create mode 100644 drivers/media/pci/tw686x/tw686x-video.c create mode 100644 drivers/media/pci/tw686x/tw686x.h diff --git a/MAINTAINERS b/MAINTAINERS index 2ec50793c3ba..bfcb7ea42e20 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11258,6 +11258,14 @@ W: https://linuxtv.org S: Odd Fixes F: drivers/media/pci/tw68/ +TW686X VIDEO4LINUX DRIVER +M: Ezequiel Garcia +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +W: http://linuxtv.org +S: Maintained +F: drivers/media/pci/tw686x/ + TPM DEVICE DRIVER M: Peter Huewe M: Marcel Selhorst diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig index 48a611bc3e18..4f6467fbaeb4 100644 --- a/drivers/media/pci/Kconfig +++ b/drivers/media/pci/Kconfig @@ -14,6 +14,7 @@ source "drivers/media/pci/meye/Kconfig" source "drivers/media/pci/solo6x10/Kconfig" source "drivers/media/pci/sta2x11/Kconfig" source "drivers/media/pci/tw68/Kconfig" +source "drivers/media/pci/tw686x/Kconfig" source "drivers/media/pci/zoran/Kconfig" endif diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile index 5f8aacb8b9b8..2e54c36441f7 100644 --- a/drivers/media/pci/Makefile +++ b/drivers/media/pci/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_VIDEO_BT848) += bt8xx/ obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ obj-$(CONFIG_VIDEO_TW68) += tw68/ +obj-$(CONFIG_VIDEO_TW686X) += tw686x/ obj-$(CONFIG_VIDEO_DT3155) += dt3155/ obj-$(CONFIG_VIDEO_MEYE) += meye/ obj-$(CONFIG_STA2X11_VIP) += sta2x11/ diff --git a/drivers/media/pci/tw686x/Kconfig b/drivers/media/pci/tw686x/Kconfig new file mode 100644 index 000000000000..fb8536974052 --- /dev/null +++ b/drivers/media/pci/tw686x/Kconfig @@ -0,0 +1,18 @@ +config VIDEO_TW686X + tristate "Intersil/Techwell TW686x video capture cards" + depends on PCI && VIDEO_DEV && VIDEO_V4L2 && SND + depends on HAS_DMA + select VIDEOBUF2_VMALLOC + select SND_PCM + help + Support for Intersil/Techwell TW686x-based frame grabber cards. + + Currently supported chips: + - TW6864 (4 video channels), + - TW6865 (4 video channels, not tested, second generation chip), + - TW6868 (8 video channels but only 4 first channels using + built-in video decoder are supported, not tested), + - TW6869 (8 video channels, second generation chip). + + To compile this driver as a module, choose M here: the module + will be named tw686x. diff --git a/drivers/media/pci/tw686x/Makefile b/drivers/media/pci/tw686x/Makefile new file mode 100644 index 000000000000..99819542b733 --- /dev/null +++ b/drivers/media/pci/tw686x/Makefile @@ -0,0 +1,3 @@ +tw686x-objs := tw686x-core.o tw686x-video.o tw686x-audio.o + +obj-$(CONFIG_VIDEO_TW686X) += tw686x.o diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c new file mode 100644 index 000000000000..91459ab715b2 --- /dev/null +++ b/drivers/media/pci/tw686x/tw686x-audio.c @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar + * + * Based on the audio support from the tw6869 driver: + * Copyright 2015 www.starterkit.ru + * + * Based on: + * Driver for Intersil|Techwell TW6869 based DVR cards + * (c) 2011-12 liran [Intersil|Techwell China] + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "tw686x.h" +#include "tw686x-regs.h" + +#define AUDIO_CHANNEL_OFFSET 8 + +void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests, + unsigned int pb_status) +{ + unsigned long flags; + unsigned int ch, pb; + + for_each_set_bit(ch, &requests, max_channels(dev)) { + struct tw686x_audio_channel *ac = &dev->audio_channels[ch]; + struct tw686x_audio_buf *done = NULL; + struct tw686x_audio_buf *next = NULL; + struct tw686x_dma_desc *desc; + + pb = !!(pb_status & BIT(AUDIO_CHANNEL_OFFSET + ch)); + + spin_lock_irqsave(&ac->lock, flags); + + /* Sanity check */ + if (!ac->ss || !ac->curr_bufs[0] || !ac->curr_bufs[1]) { + spin_unlock_irqrestore(&ac->lock, flags); + continue; + } + + if (!list_empty(&ac->buf_list)) { + next = list_first_entry(&ac->buf_list, + struct tw686x_audio_buf, list); + list_move_tail(&next->list, &ac->buf_list); + done = ac->curr_bufs[!pb]; + ac->curr_bufs[pb] = next; + } + spin_unlock_irqrestore(&ac->lock, flags); + + desc = &ac->dma_descs[pb]; + if (done && next && desc->virt) { + memcpy(done->virt, desc->virt, desc->size); + ac->ptr = done->dma - ac->buf[0].dma; + snd_pcm_period_elapsed(ac->ss); + } + } +} + +static int tw686x_pcm_hw_params(struct snd_pcm_substream *ss, + struct snd_pcm_hw_params *hw_params) +{ + return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params)); +} + +static int tw686x_pcm_hw_free(struct snd_pcm_substream *ss) +{ + return snd_pcm_lib_free_pages(ss); +} + +/* + * The audio device rate is global and shared among all + * capture channels. The driver makes no effort to prevent + * rate modifications. User is free change the rate, but it + * means changing the rate for all capture sub-devices. + */ +static const struct snd_pcm_hardware tw686x_capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 1, + .buffer_bytes_max = TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ, + .period_bytes_min = TW686X_AUDIO_PAGE_SZ, + .period_bytes_max = TW686X_AUDIO_PAGE_SZ, + .periods_min = TW686X_AUDIO_PERIODS_MIN, + .periods_max = TW686X_AUDIO_PERIODS_MAX, +}; + +static int tw686x_pcm_open(struct snd_pcm_substream *ss) +{ + struct tw686x_dev *dev = snd_pcm_substream_chip(ss); + struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number]; + struct snd_pcm_runtime *rt = ss->runtime; + int err; + + ac->ss = ss; + rt->hw = tw686x_capture_hw; + + err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) + return err; + + return 0; +} + +static int tw686x_pcm_close(struct snd_pcm_substream *ss) +{ + struct tw686x_dev *dev = snd_pcm_substream_chip(ss); + struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number]; + + ac->ss = NULL; + return 0; +} + +static int tw686x_pcm_prepare(struct snd_pcm_substream *ss) +{ + struct tw686x_dev *dev = snd_pcm_substream_chip(ss); + struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number]; + struct snd_pcm_runtime *rt = ss->runtime; + unsigned int period_size = snd_pcm_lib_period_bytes(ss); + struct tw686x_audio_buf *p_buf, *b_buf; + unsigned long flags; + int i; + + spin_lock_irqsave(&dev->lock, flags); + tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch); + spin_unlock_irqrestore(&dev->lock, flags); + + if (dev->audio_rate != rt->rate) { + u32 reg; + + dev->audio_rate = rt->rate; + reg = ((125000000 / rt->rate) << 16) + + ((125000000 % rt->rate) << 16) / rt->rate; + + reg_write(dev, AUDIO_CONTROL2, reg); + } + + if (period_size != TW686X_AUDIO_PAGE_SZ || + rt->periods < TW686X_AUDIO_PERIODS_MIN || + rt->periods > TW686X_AUDIO_PERIODS_MAX) { + return -EINVAL; + } + + spin_lock_irqsave(&ac->lock, flags); + INIT_LIST_HEAD(&ac->buf_list); + + for (i = 0; i < rt->periods; i++) { + ac->buf[i].dma = rt->dma_addr + period_size * i; + ac->buf[i].virt = rt->dma_area + period_size * i; + INIT_LIST_HEAD(&ac->buf[i].list); + list_add_tail(&ac->buf[i].list, &ac->buf_list); + } + + p_buf = list_first_entry(&ac->buf_list, struct tw686x_audio_buf, list); + list_move_tail(&p_buf->list, &ac->buf_list); + + b_buf = list_first_entry(&ac->buf_list, struct tw686x_audio_buf, list); + list_move_tail(&b_buf->list, &ac->buf_list); + + ac->curr_bufs[0] = p_buf; + ac->curr_bufs[1] = b_buf; + ac->ptr = 0; + spin_unlock_irqrestore(&ac->lock, flags); + + return 0; +} + +static int tw686x_pcm_trigger(struct snd_pcm_substream *ss, int cmd) +{ + struct tw686x_dev *dev = snd_pcm_substream_chip(ss); + struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number]; + unsigned long flags; + int err = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (ac->curr_bufs[0] && ac->curr_bufs[1]) { + spin_lock_irqsave(&dev->lock, flags); + tw686x_enable_channel(dev, + AUDIO_CHANNEL_OFFSET + ac->ch); + spin_unlock_irqrestore(&dev->lock, flags); + + mod_timer(&dev->dma_delay_timer, + jiffies + msecs_to_jiffies(100)); + } else { + err = -EIO; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + spin_lock_irqsave(&dev->lock, flags); + tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch); + spin_unlock_irqrestore(&dev->lock, flags); + + spin_lock_irqsave(&ac->lock, flags); + ac->curr_bufs[0] = NULL; + ac->curr_bufs[1] = NULL; + spin_unlock_irqrestore(&ac->lock, flags); + break; + default: + err = -EINVAL; + } + return err; +} + +static snd_pcm_uframes_t tw686x_pcm_pointer(struct snd_pcm_substream *ss) +{ + struct tw686x_dev *dev = snd_pcm_substream_chip(ss); + struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number]; + + return bytes_to_frames(ss->runtime, ac->ptr); +} + +static struct snd_pcm_ops tw686x_pcm_ops = { + .open = tw686x_pcm_open, + .close = tw686x_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = tw686x_pcm_hw_params, + .hw_free = tw686x_pcm_hw_free, + .prepare = tw686x_pcm_prepare, + .trigger = tw686x_pcm_trigger, + .pointer = tw686x_pcm_pointer, +}; + +static int tw686x_snd_pcm_init(struct tw686x_dev *dev) +{ + struct snd_card *card = dev->snd_card; + struct snd_pcm *pcm; + struct snd_pcm_substream *ss; + unsigned int i; + int err; + + err = snd_pcm_new(card, card->driver, 0, 0, max_channels(dev), &pcm); + if (err < 0) + return err; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tw686x_pcm_ops); + snd_pcm_chip(pcm) = dev; + pcm->info_flags = 0; + strlcpy(pcm->name, "tw686x PCM", sizeof(pcm->name)); + + for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; + ss; ss = ss->next, i++) + snprintf(ss->name, sizeof(ss->name), "vch%u audio", i); + + return snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(dev->pci_dev), + TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ, + TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ); +} + +static void tw686x_audio_dma_free(struct tw686x_dev *dev, + struct tw686x_audio_channel *ac) +{ + int pb; + + for (pb = 0; pb < 2; pb++) { + if (!ac->dma_descs[pb].virt) + continue; + pci_free_consistent(dev->pci_dev, ac->dma_descs[pb].size, + ac->dma_descs[pb].virt, + ac->dma_descs[pb].phys); + ac->dma_descs[pb].virt = NULL; + } +} + +static int tw686x_audio_dma_alloc(struct tw686x_dev *dev, + struct tw686x_audio_channel *ac) +{ + int pb; + + for (pb = 0; pb < 2; pb++) { + u32 reg = pb ? ADMA_B_ADDR[ac->ch] : ADMA_P_ADDR[ac->ch]; + void *virt; + + virt = pci_alloc_consistent(dev->pci_dev, TW686X_AUDIO_PAGE_SZ, + &ac->dma_descs[pb].phys); + if (!virt) { + dev_err(&dev->pci_dev->dev, + "dma%d: unable to allocate audio DMA %s-buffer\n", + ac->ch, pb ? "B" : "P"); + return -ENOMEM; + } + ac->dma_descs[pb].virt = virt; + ac->dma_descs[pb].size = TW686X_AUDIO_PAGE_SZ; + reg_write(dev, reg, ac->dma_descs[pb].phys); + } + return 0; +} + +void tw686x_audio_free(struct tw686x_dev *dev) +{ + unsigned long flags; + u32 dma_ch_mask; + u32 dma_cmd; + + spin_lock_irqsave(&dev->lock, flags); + dma_cmd = reg_read(dev, DMA_CMD); + dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE); + reg_write(dev, DMA_CMD, dma_cmd & ~0xff00); + reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask & ~0xff00); + spin_unlock_irqrestore(&dev->lock, flags); + + if (!dev->snd_card) + return; + snd_card_free(dev->snd_card); + dev->snd_card = NULL; +} + +int tw686x_audio_init(struct tw686x_dev *dev) +{ + struct pci_dev *pci_dev = dev->pci_dev; + struct snd_card *card; + int err, ch; + + /* + * AUDIO_CONTROL1 + * DMA byte length [31:19] = 4096 (i.e. ALSA period) + * External audio enable [0] = enabled + */ + reg_write(dev, AUDIO_CONTROL1, 0x80000001); + + err = snd_card_new(&pci_dev->dev, SNDRV_DEFAULT_IDX1, + SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); + if (err < 0) + return err; + + dev->snd_card = card; + strlcpy(card->driver, "tw686x", sizeof(card->driver)); + strlcpy(card->shortname, "tw686x", sizeof(card->shortname)); + strlcpy(card->longname, pci_name(pci_dev), sizeof(card->longname)); + snd_card_set_dev(card, &pci_dev->dev); + + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_audio_channel *ac; + + ac = &dev->audio_channels[ch]; + spin_lock_init(&ac->lock); + ac->dev = dev; + ac->ch = ch; + + err = tw686x_audio_dma_alloc(dev, ac); + if (err < 0) + goto err_cleanup; + } + + err = tw686x_snd_pcm_init(dev); + if (err < 0) + goto err_cleanup; + + err = snd_card_register(card); + if (!err) + return 0; + +err_cleanup: + for (ch = 0; ch < max_channels(dev); ch++) { + if (!dev->audio_channels[ch].dev) + continue; + tw686x_audio_dma_free(dev, &dev->audio_channels[ch]); + } + snd_card_free(card); + dev->snd_card = NULL; + return err; +} diff --git a/drivers/media/pci/tw686x/tw686x-core.c b/drivers/media/pci/tw686x/tw686x-core.c new file mode 100644 index 000000000000..cf53b0e97be2 --- /dev/null +++ b/drivers/media/pci/tw686x/tw686x-core.c @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar + * + * Based on original driver by Krzysztof Ha?asa: + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * Notes + * ----- + * + * 1. Under stress-testing, it has been observed that the PCIe link + * goes down, without reason. Therefore, the driver takes special care + * to allow device hot-unplugging. + * + * 2. TW686X devices are capable of setting a few different DMA modes, + * including: scatter-gather, field and frame modes. However, + * under stress testings it has been found that the machine can + * freeze completely if DMA registers are programmed while streaming + * is active. + * This driver tries to access hardware registers as infrequently + * as possible by: + * i. allocating fixed DMA buffers and memcpy'ing into + * vmalloc'ed buffers + * ii. using a timer to mitigate the rate of DMA reset operations, + * on DMA channels error. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tw686x.h" +#include "tw686x-regs.h" + +/* + * This module parameter allows to control the DMA_TIMER_INTERVAL value. + * The DMA_TIMER_INTERVAL register controls the minimum DMA interrupt + * time span (iow, the maximum DMA interrupt rate) thus allowing for + * IRQ coalescing. + * + * The chip datasheet does not mention a time unit for this value, so + * users wanting fine-grain control over the interrupt rate should + * determine the desired value through testing. + */ +static u32 dma_interval = 0x00098968; +module_param(dma_interval, int, 0444); +MODULE_PARM_DESC(dma_interval, "Minimum time span for DMA interrupting host"); + +void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel) +{ + u32 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE); + u32 dma_cmd = reg_read(dev, DMA_CMD); + + dma_en &= ~BIT(channel); + dma_cmd &= ~BIT(channel); + + /* Must remove it from pending too */ + dev->pending_dma_en &= ~BIT(channel); + dev->pending_dma_cmd &= ~BIT(channel); + + /* Stop DMA if no channels are enabled */ + if (!dma_en) + dma_cmd = 0; + reg_write(dev, DMA_CHANNEL_ENABLE, dma_en); + reg_write(dev, DMA_CMD, dma_cmd); +} + +void tw686x_enable_channel(struct tw686x_dev *dev, unsigned int channel) +{ + u32 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE); + u32 dma_cmd = reg_read(dev, DMA_CMD); + + dev->pending_dma_en |= dma_en | BIT(channel); + dev->pending_dma_cmd |= dma_cmd | DMA_CMD_ENABLE | BIT(channel); +} + +/* + * The purpose of this awful hack is to avoid enabling the DMA + * channels "too fast" which makes some TW686x devices very + * angry and freeze the CPU (see note 1). + */ +static void tw686x_dma_delay(unsigned long data) +{ + struct tw686x_dev *dev = (struct tw686x_dev *)data; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + + reg_write(dev, DMA_CHANNEL_ENABLE, dev->pending_dma_en); + reg_write(dev, DMA_CMD, dev->pending_dma_cmd); + dev->pending_dma_en = 0; + dev->pending_dma_cmd = 0; + + spin_unlock_irqrestore(&dev->lock, flags); +} + +static void tw686x_reset_channels(struct tw686x_dev *dev, unsigned int ch_mask) +{ + u32 dma_en, dma_cmd; + + dma_en = reg_read(dev, DMA_CHANNEL_ENABLE); + dma_cmd = reg_read(dev, DMA_CMD); + + /* + * Save pending register status, the timer will + * restore them. + */ + dev->pending_dma_en |= dma_en; + dev->pending_dma_cmd |= dma_cmd; + + /* Disable the reset channels */ + reg_write(dev, DMA_CHANNEL_ENABLE, dma_en & ~ch_mask); + + if ((dma_en & ~ch_mask) == 0) { + dev_dbg(&dev->pci_dev->dev, "reset: stopping DMA\n"); + dma_cmd &= ~DMA_CMD_ENABLE; + } + reg_write(dev, DMA_CMD, dma_cmd & ~ch_mask); +} + +static irqreturn_t tw686x_irq(int irq, void *dev_id) +{ + struct tw686x_dev *dev = (struct tw686x_dev *)dev_id; + unsigned int video_requests, audio_requests, reset_ch; + u32 fifo_status, fifo_signal, fifo_ov, fifo_bad, fifo_errors; + u32 int_status, dma_en, video_en, pb_status; + unsigned long flags; + + int_status = reg_read(dev, INT_STATUS); /* cleared on read */ + fifo_status = reg_read(dev, VIDEO_FIFO_STATUS); + + /* INT_STATUS does not include FIFO_STATUS errors! */ + if (!int_status && !TW686X_FIFO_ERROR(fifo_status)) + return IRQ_NONE; + + if (int_status & INT_STATUS_DMA_TOUT) { + dev_dbg(&dev->pci_dev->dev, + "DMA timeout. Resetting DMA for all channels\n"); + reset_ch = ~0; + goto reset_channels; + } + + spin_lock_irqsave(&dev->lock, flags); + dma_en = reg_read(dev, DMA_CHANNEL_ENABLE); + spin_unlock_irqrestore(&dev->lock, flags); + + video_en = dma_en & 0xff; + fifo_signal = ~(fifo_status & 0xff) & video_en; + fifo_ov = fifo_status >> 24; + fifo_bad = fifo_status >> 16; + + /* Mask of channels with signal and FIFO errors */ + fifo_errors = fifo_signal & (fifo_ov | fifo_bad); + + reset_ch = 0; + pb_status = reg_read(dev, PB_STATUS); + + /* Coalesce video frame/error events */ + video_requests = (int_status & video_en) | fifo_errors; + audio_requests = (int_status & dma_en) >> 8; + + if (video_requests) + tw686x_video_irq(dev, video_requests, pb_status, + fifo_status, &reset_ch); + if (audio_requests) + tw686x_audio_irq(dev, audio_requests, pb_status); + +reset_channels: + if (reset_ch) { + spin_lock_irqsave(&dev->lock, flags); + tw686x_reset_channels(dev, reset_ch); + spin_unlock_irqrestore(&dev->lock, flags); + mod_timer(&dev->dma_delay_timer, + jiffies + msecs_to_jiffies(100)); + } + + return IRQ_HANDLED; +} + +static void tw686x_dev_release(struct v4l2_device *v4l2_dev) +{ + struct tw686x_dev *dev = container_of(v4l2_dev, struct tw686x_dev, + v4l2_dev); + unsigned int ch; + + for (ch = 0; ch < max_channels(dev); ch++) + v4l2_ctrl_handler_free(&dev->video_channels[ch].ctrl_handler); + + v4l2_device_unregister(&dev->v4l2_dev); + + kfree(dev->audio_channels); + kfree(dev->video_channels); + kfree(dev); +} + +static int tw686x_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) +{ + struct tw686x_dev *dev; + int err; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + dev->type = pci_id->driver_data; + sprintf(dev->name, "tw%04X", pci_dev->device); + + dev->video_channels = kcalloc(max_channels(dev), + sizeof(*dev->video_channels), GFP_KERNEL); + if (!dev->video_channels) { + err = -ENOMEM; + goto free_dev; + } + + dev->audio_channels = kcalloc(max_channels(dev), + sizeof(*dev->audio_channels), GFP_KERNEL); + if (!dev->audio_channels) { + err = -ENOMEM; + goto free_video; + } + + pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name, + pci_name(pci_dev), pci_dev->irq, + (unsigned long)pci_resource_start(pci_dev, 0)); + + dev->pci_dev = pci_dev; + if (pci_enable_device(pci_dev)) { + err = -EIO; + goto free_audio; + } + + pci_set_master(pci_dev); + err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pci_dev->dev, "32-bit PCI DMA not supported\n"); + err = -EIO; + goto disable_pci; + } + + err = pci_request_regions(pci_dev, dev->name); + if (err) { + dev_err(&pci_dev->dev, "unable to request PCI region\n"); + goto disable_pci; + } + + dev->mmio = pci_ioremap_bar(pci_dev, 0); + if (!dev->mmio) { + dev_err(&pci_dev->dev, "unable to remap PCI region\n"); + err = -ENOMEM; + goto free_region; + } + + /* Reset all subsystems */ + reg_write(dev, SYS_SOFT_RST, 0x0f); + mdelay(1); + + reg_write(dev, SRST[0], 0x3f); + if (max_channels(dev) > 4) + reg_write(dev, SRST[1], 0x3f); + + /* Disable the DMA engine */ + reg_write(dev, DMA_CMD, 0); + reg_write(dev, DMA_CHANNEL_ENABLE, 0); + + /* Enable DMA FIFO overflow and pointer check */ + reg_write(dev, DMA_CONFIG, 0xffffff04); + reg_write(dev, DMA_CHANNEL_TIMEOUT, 0x140c8584); + reg_write(dev, DMA_TIMER_INTERVAL, dma_interval); + + spin_lock_init(&dev->lock); + + err = request_irq(pci_dev->irq, tw686x_irq, IRQF_SHARED, + dev->name, dev); + if (err < 0) { + dev_err(&pci_dev->dev, "unable to request interrupt\n"); + goto iounmap; + } + + setup_timer(&dev->dma_delay_timer, + tw686x_dma_delay, (unsigned long) dev); + + /* + * This must be set right before initializing v4l2_dev. + * It's used to release resources after the last handle + * held is released. + */ + dev->v4l2_dev.release = tw686x_dev_release; + err = tw686x_video_init(dev); + if (err) { + dev_err(&pci_dev->dev, "can't register video\n"); + goto free_irq; + } + + err = tw686x_audio_init(dev); + if (err) + dev_warn(&pci_dev->dev, "can't register audio\n"); + + pci_set_drvdata(pci_dev, dev); + return 0; + +free_irq: + free_irq(pci_dev->irq, dev); +iounmap: + pci_iounmap(pci_dev, dev->mmio); +free_region: + pci_release_regions(pci_dev); +disable_pci: + pci_disable_device(pci_dev); +free_audio: + kfree(dev->audio_channels); +free_video: + kfree(dev->video_channels); +free_dev: + kfree(dev); + return err; +} + +static void tw686x_remove(struct pci_dev *pci_dev) +{ + struct tw686x_dev *dev = pci_get_drvdata(pci_dev); + unsigned long flags; + + /* This guarantees the IRQ handler is no longer running, + * which means we can kiss good-bye some resources. + */ + free_irq(pci_dev->irq, dev); + + tw686x_video_free(dev); + tw686x_audio_free(dev); + del_timer_sync(&dev->dma_delay_timer); + + pci_iounmap(pci_dev, dev->mmio); + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); + + /* + * Setting pci_dev to NULL allows to detect hardware is no longer + * available and will be used by vb2_ops. This is required because + * the device sometimes hot-unplugs itself as the result of a PCIe + * link down. + * The lock is really important here. + */ + spin_lock_irqsave(&dev->lock, flags); + dev->pci_dev = NULL; + spin_unlock_irqrestore(&dev->lock, flags); + + /* + * This calls tw686x_dev_release if it's the last reference. + * Otherwise, release is postponed until there are no users left. + */ + v4l2_device_put(&dev->v4l2_dev); +} + +/* + * On TW6864 and TW6868, all channels share the pair of video DMA SG tables, + * with 10-bit start_idx and end_idx determining start and end of frame buffer + * for particular channel. + * TW6868 with all its 8 channels would be problematic (only 127 SG entries per + * channel) but we support only 4 channels on this chip anyway (the first + * 4 channels are driven with internal video decoder, the other 4 would require + * an external TW286x part). + * + * On TW6865 and TW6869, each channel has its own DMA SG table, with indexes + * starting with 0. Both chips have complete sets of internal video decoders + * (respectively 4 or 8-channel). + * + * All chips have separate SG tables for two video frames. + */ + +/* driver_data is number of A/V channels */ +static const struct pci_device_id tw686x_pci_tbl[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6864), + .driver_data = 4 + }, + { + PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6865), /* not tested */ + .driver_data = 4 | TYPE_SECOND_GEN + }, + /* + * TW6868 supports 8 A/V channels with an external TW2865 chip; + * not supported by the driver. + */ + { + PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6868), /* not tested */ + .driver_data = 4 + }, + { + PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6869), + .driver_data = 8 | TYPE_SECOND_GEN}, + {} +}; +MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl); + +static struct pci_driver tw686x_pci_driver = { + .name = "tw686x", + .id_table = tw686x_pci_tbl, + .probe = tw686x_probe, + .remove = tw686x_remove, +}; +module_pci_driver(tw686x_pci_driver); + +MODULE_DESCRIPTION("Driver for video frame grabber cards based on Intersil/Techwell TW686[4589]"); +MODULE_AUTHOR("Ezequiel Garcia "); +MODULE_AUTHOR("Krzysztof Ha?asa "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/pci/tw686x/tw686x-regs.h b/drivers/media/pci/tw686x/tw686x-regs.h new file mode 100644 index 000000000000..fcef586a4c8c --- /dev/null +++ b/drivers/media/pci/tw686x/tw686x-regs.h @@ -0,0 +1,122 @@ +/* DMA controller registers */ +#define REG8_1(a0) ((const u16[8]) { a0, a0 + 1, a0 + 2, a0 + 3, \ + a0 + 4, a0 + 5, a0 + 6, a0 + 7}) +#define REG8_2(a0) ((const u16[8]) { a0, a0 + 2, a0 + 4, a0 + 6, \ + a0 + 8, a0 + 0xa, a0 + 0xc, a0 + 0xe}) +#define REG8_8(a0) ((const u16[8]) { a0, a0 + 8, a0 + 0x10, a0 + 0x18, \ + a0 + 0x20, a0 + 0x28, a0 + 0x30, \ + a0 + 0x38}) +#define INT_STATUS 0x00 +#define PB_STATUS 0x01 +#define DMA_CMD 0x02 +#define VIDEO_FIFO_STATUS 0x03 +#define VIDEO_CHANNEL_ID 0x04 +#define VIDEO_PARSER_STATUS 0x05 +#define SYS_SOFT_RST 0x06 +#define DMA_PAGE_TABLE0_ADDR ((const u16[8]) { 0x08, 0xd0, 0xd2, 0xd4, \ + 0xd6, 0xd8, 0xda, 0xdc }) +#define DMA_PAGE_TABLE1_ADDR ((const u16[8]) { 0x09, 0xd1, 0xd3, 0xd5, \ + 0xd7, 0xd9, 0xdb, 0xdd }) +#define DMA_CHANNEL_ENABLE 0x0a +#define DMA_CONFIG 0x0b +#define DMA_TIMER_INTERVAL 0x0c +#define DMA_CHANNEL_TIMEOUT 0x0d +#define VDMA_CHANNEL_CONFIG REG8_1(0x10) +#define ADMA_P_ADDR REG8_2(0x18) +#define ADMA_B_ADDR REG8_2(0x19) +#define DMA10_P_ADDR 0x28 +#define DMA10_B_ADDR 0x29 +#define VIDEO_CONTROL1 0x2a +#define VIDEO_CONTROL2 0x2b +#define AUDIO_CONTROL1 0x2c +#define AUDIO_CONTROL2 0x2d +#define PHASE_REF 0x2e +#define GPIO_REG 0x2f +#define INTL_HBAR_CTRL REG8_1(0x30) +#define AUDIO_CONTROL3 0x38 +#define VIDEO_FIELD_CTRL REG8_1(0x39) +#define HSCALER_CTRL REG8_1(0x42) +#define VIDEO_SIZE REG8_1(0x4A) +#define VIDEO_SIZE_F2 REG8_1(0x52) +#define MD_CONF REG8_1(0x60) +#define MD_INIT REG8_1(0x68) +#define MD_MAP0 REG8_1(0x70) +#define VDMA_P_ADDR REG8_8(0x80) /* not used in DMA SG mode */ +#define VDMA_WHP REG8_8(0x81) +#define VDMA_B_ADDR REG8_8(0x82) +#define VDMA_F2_P_ADDR REG8_8(0x84) +#define VDMA_F2_WHP REG8_8(0x85) +#define VDMA_F2_B_ADDR REG8_8(0x86) +#define EP_REG_ADDR 0xfe +#define EP_REG_DATA 0xff + +/* Video decoder registers */ +#define VDREG8(a0) ((const u16[8]) { \ + a0 + 0x000, a0 + 0x010, a0 + 0x020, a0 + 0x030, \ + a0 + 0x100, a0 + 0x110, a0 + 0x120, a0 + 0x130}) +#define VIDSTAT VDREG8(0x100) +#define BRIGHT VDREG8(0x101) +#define CONTRAST VDREG8(0x102) +#define SHARPNESS VDREG8(0x103) +#define SAT_U VDREG8(0x104) +#define SAT_V VDREG8(0x105) +#define HUE VDREG8(0x106) +#define CROP_HI VDREG8(0x107) +#define VDELAY_LO VDREG8(0x108) +#define VACTIVE_LO VDREG8(0x109) +#define HDELAY_LO VDREG8(0x10a) +#define HACTIVE_LO VDREG8(0x10b) +#define MVSN VDREG8(0x10c) +#define STATUS2 VDREG8(0x10d) +#define SDT VDREG8(0x10e) +#define SDT_EN VDREG8(0x10f) + +#define VSCALE_LO VDREG8(0x144) +#define SCALE_HI VDREG8(0x145) +#define HSCALE_LO VDREG8(0x146) +#define F2CROP_HI VDREG8(0x147) +#define F2VDELAY_LO VDREG8(0x148) +#define F2VACTIVE_LO VDREG8(0x149) +#define F2HDELAY_LO VDREG8(0x14a) +#define F2HACTIVE_LO VDREG8(0x14b) +#define F2VSCALE_LO VDREG8(0x14c) +#define F2SCALE_HI VDREG8(0x14d) +#define F2HSCALE_LO VDREG8(0x14e) +#define F2CNT VDREG8(0x14f) + +#define VDREG2(a0) ((const u16[2]) { a0, a0 + 0x100 }) +#define SRST VDREG2(0x180) +#define ACNTL VDREG2(0x181) +#define ACNTL2 VDREG2(0x182) +#define CNTRL1 VDREG2(0x183) +#define CKHY VDREG2(0x184) +#define SHCOR VDREG2(0x185) +#define CORING VDREG2(0x186) +#define CLMPG VDREG2(0x187) +#define IAGC VDREG2(0x188) +#define VCTRL1 VDREG2(0x18f) +#define MISC1 VDREG2(0x194) +#define LOOP VDREG2(0x195) +#define MISC2 VDREG2(0x196) + +#define CLMD VDREG2(0x197) +#define ANPWRDOWN VDREG2(0x1ce) +#define AIGAIN ((const u16[8]) { 0x1d0, 0x1d1, 0x1d2, 0x1d3, \ + 0x2d0, 0x2d1, 0x2d2, 0x2d3 }) + +#define SYS_MODE_DMA_SHIFT 13 + +#define DMA_CMD_ENABLE BIT(31) +#define INT_STATUS_DMA_TOUT BIT(17) +#define TW686X_VIDSTAT_HLOCK BIT(6) +#define TW686X_VIDSTAT_VDLOSS BIT(7) + +#define TW686X_STD_NTSC_M 0 +#define TW686X_STD_PAL 1 +#define TW686X_STD_SECAM 2 +#define TW686X_STD_NTSC_443 3 +#define TW686X_STD_PAL_M 4 +#define TW686X_STD_PAL_CN 5 +#define TW686X_STD_PAL_60 6 + +#define TW686X_FIFO_ERROR(x) (x & ~(0xff)) diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c new file mode 100644 index 000000000000..35ad8e650717 --- /dev/null +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -0,0 +1,927 @@ +/* + * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar + * + * Based on original driver by Krzysztof Ha?asa: + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tw686x.h" +#include "tw686x-regs.h" + +#define TW686X_INPUTS_PER_CH 4 +#define TW686X_VIDEO_WIDTH 720 +#define TW686X_VIDEO_HEIGHT(id) ((id & V4L2_STD_625_50) ? 576 : 480) + +static const struct tw686x_format formats[] = { + { + .fourcc = V4L2_PIX_FMT_UYVY, + .mode = 0, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, + .mode = 5, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .mode = 6, + .depth = 16, + } +}; + +static unsigned int tw686x_fields_map(v4l2_std_id std, unsigned int fps) +{ + static const unsigned int map[15] = { + 0x00000000, 0x00000001, 0x00004001, 0x00104001, 0x00404041, + 0x01041041, 0x01104411, 0x01111111, 0x04444445, 0x04511445, + 0x05145145, 0x05151515, 0x05515455, 0x05551555, 0x05555555 + }; + + static const unsigned int std_625_50[26] = { + 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, + 8, 8, 9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 0 + }; + + static const unsigned int std_525_60[31] = { + 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 0, 0 + }; + + unsigned int i = + (std & V4L2_STD_625_50) ? std_625_50[fps] : std_525_60[fps]; + + return map[i]; +} + +static void tw686x_set_framerate(struct tw686x_video_channel *vc, + unsigned int fps) +{ + unsigned int map; + + if (vc->fps == fps) + return; + + map = tw686x_fields_map(vc->video_standard, fps) << 1; + map |= map << 1; + if (map > 0) + map |= BIT(31); + reg_write(vc->dev, VIDEO_FIELD_CTRL[vc->ch], map); + vc->fps = fps; +} + +static const struct tw686x_format *format_by_fourcc(unsigned int fourcc) +{ + unsigned int cnt; + + for (cnt = 0; cnt < ARRAY_SIZE(formats); cnt++) + if (formats[cnt].fourcc == fourcc) + return &formats[cnt]; + return NULL; +} + +static int tw686x_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + unsigned int szimage = + (vc->width * vc->height * vc->format->depth) >> 3; + + /* + * Let's request at least three buffers: two for the + * DMA engine and one for userspace. + */ + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; + + if (*nplanes) { + if (*nplanes != 1 || sizes[0] < szimage) + return -EINVAL; + return 0; + } + + sizes[0] = szimage; + *nplanes = 1; + return 0; +} + +static void tw686x_buf_queue(struct vb2_buffer *vb) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vb->vb2_queue); + struct tw686x_dev *dev = vc->dev; + struct pci_dev *pci_dev; + unsigned long flags; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct tw686x_v4l2_buf *buf = + container_of(vbuf, struct tw686x_v4l2_buf, vb); + + /* Check device presence */ + spin_lock_irqsave(&dev->lock, flags); + pci_dev = dev->pci_dev; + spin_unlock_irqrestore(&dev->lock, flags); + if (!pci_dev) { + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + return; + } + + spin_lock_irqsave(&vc->qlock, flags); + list_add_tail(&buf->list, &vc->vidq_queued); + spin_unlock_irqrestore(&vc->qlock, flags); +} + +/* + * We can call this even when alloc_dma failed for the given channel + */ +static void tw686x_free_dma(struct tw686x_video_channel *vc, unsigned int pb) +{ + struct tw686x_dma_desc *desc = &vc->dma_descs[pb]; + struct tw686x_dev *dev = vc->dev; + struct pci_dev *pci_dev; + unsigned long flags; + + /* Check device presence. Shouldn't really happen! */ + spin_lock_irqsave(&dev->lock, flags); + pci_dev = dev->pci_dev; + spin_unlock_irqrestore(&dev->lock, flags); + if (!pci_dev) { + WARN(1, "trying to deallocate on missing device\n"); + return; + } + + if (desc->virt) { + pci_free_consistent(dev->pci_dev, desc->size, + desc->virt, desc->phys); + desc->virt = NULL; + } +} + +static int tw686x_alloc_dma(struct tw686x_video_channel *vc, unsigned int pb) +{ + struct tw686x_dev *dev = vc->dev; + u32 reg = pb ? VDMA_B_ADDR[vc->ch] : VDMA_P_ADDR[vc->ch]; + unsigned int len; + void *virt; + + WARN(vc->dma_descs[pb].virt, + "Allocating buffer but previous still here\n"); + + len = (vc->width * vc->height * vc->format->depth) >> 3; + virt = pci_alloc_consistent(dev->pci_dev, len, + &vc->dma_descs[pb].phys); + if (!virt) { + v4l2_err(&dev->v4l2_dev, + "dma%d: unable to allocate %s-buffer\n", + vc->ch, pb ? "B" : "P"); + return -ENOMEM; + } + vc->dma_descs[pb].size = len; + vc->dma_descs[pb].virt = virt; + reg_write(dev, reg, vc->dma_descs[pb].phys); + + return 0; +} + +static void tw686x_buffer_refill(struct tw686x_video_channel *vc, + unsigned int pb) +{ + struct tw686x_v4l2_buf *buf; + + while (!list_empty(&vc->vidq_queued)) { + + buf = list_first_entry(&vc->vidq_queued, + struct tw686x_v4l2_buf, list); + list_del(&buf->list); + + vc->curr_bufs[pb] = buf; + return; + } + vc->curr_bufs[pb] = NULL; +} + +static void tw686x_clear_queue(struct tw686x_video_channel *vc, + enum vb2_buffer_state state) +{ + unsigned int pb; + + while (!list_empty(&vc->vidq_queued)) { + struct tw686x_v4l2_buf *buf; + + buf = list_first_entry(&vc->vidq_queued, + struct tw686x_v4l2_buf, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } + + for (pb = 0; pb < 2; pb++) { + if (vc->curr_bufs[pb]) + vb2_buffer_done(&vc->curr_bufs[pb]->vb.vb2_buf, state); + vc->curr_bufs[pb] = NULL; + } +} + +static int tw686x_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + struct tw686x_dev *dev = vc->dev; + struct pci_dev *pci_dev; + unsigned long flags; + int pb, err; + + /* Check device presence */ + spin_lock_irqsave(&dev->lock, flags); + pci_dev = dev->pci_dev; + spin_unlock_irqrestore(&dev->lock, flags); + if (!pci_dev) { + err = -ENODEV; + goto err_clear_queue; + } + + spin_lock_irqsave(&vc->qlock, flags); + + /* Sanity check */ + if (!vc->dma_descs[0].virt || !vc->dma_descs[1].virt) { + spin_unlock_irqrestore(&vc->qlock, flags); + v4l2_err(&dev->v4l2_dev, + "video%d: refusing to start without DMA buffers\n", + vc->num); + err = -ENOMEM; + goto err_clear_queue; + } + + for (pb = 0; pb < 2; pb++) + tw686x_buffer_refill(vc, pb); + spin_unlock_irqrestore(&vc->qlock, flags); + + vc->sequence = 0; + vc->pb = 0; + + spin_lock_irqsave(&dev->lock, flags); + tw686x_enable_channel(dev, vc->ch); + spin_unlock_irqrestore(&dev->lock, flags); + + mod_timer(&dev->dma_delay_timer, jiffies + msecs_to_jiffies(100)); + + return 0; + +err_clear_queue: + spin_lock_irqsave(&vc->qlock, flags); + tw686x_clear_queue(vc, VB2_BUF_STATE_QUEUED); + spin_unlock_irqrestore(&vc->qlock, flags); + return err; +} + +static void tw686x_stop_streaming(struct vb2_queue *vq) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + struct tw686x_dev *dev = vc->dev; + struct pci_dev *pci_dev; + unsigned long flags; + + /* Check device presence */ + spin_lock_irqsave(&dev->lock, flags); + pci_dev = dev->pci_dev; + spin_unlock_irqrestore(&dev->lock, flags); + if (pci_dev) + tw686x_disable_channel(dev, vc->ch); + + spin_lock_irqsave(&vc->qlock, flags); + tw686x_clear_queue(vc, VB2_BUF_STATE_ERROR); + spin_unlock_irqrestore(&vc->qlock, flags); +} + +static int tw686x_buf_prepare(struct vb2_buffer *vb) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vb->vb2_queue); + unsigned int size = + (vc->width * vc->height * vc->format->depth) >> 3; + + if (vb2_plane_size(vb, 0) < size) + return -EINVAL; + vb2_set_plane_payload(vb, 0, size); + return 0; +} + +static struct vb2_ops tw686x_video_qops = { + .queue_setup = tw686x_queue_setup, + .buf_queue = tw686x_buf_queue, + .buf_prepare = tw686x_buf_prepare, + .start_streaming = tw686x_start_streaming, + .stop_streaming = tw686x_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static int tw686x_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct tw686x_video_channel *vc; + struct tw686x_dev *dev; + unsigned int ch; + + vc = container_of(ctrl->handler, struct tw686x_video_channel, + ctrl_handler); + dev = vc->dev; + ch = vc->ch; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + reg_write(dev, BRIGHT[ch], ctrl->val & 0xff); + return 0; + + case V4L2_CID_CONTRAST: + reg_write(dev, CONTRAST[ch], ctrl->val); + return 0; + + case V4L2_CID_SATURATION: + reg_write(dev, SAT_U[ch], ctrl->val); + reg_write(dev, SAT_V[ch], ctrl->val); + return 0; + + case V4L2_CID_HUE: + reg_write(dev, HUE[ch], ctrl->val & 0xff); + return 0; + } + + return -EINVAL; +} + +static const struct v4l2_ctrl_ops ctrl_ops = { + .s_ctrl = tw686x_s_ctrl, +}; + +static int tw686x_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + f->fmt.pix.width = vc->width; + f->fmt.pix.height = vc->height; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.pixelformat = vc->format->fourcc; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.bytesperline = (f->fmt.pix.width * vc->format->depth) / 8; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + return 0; +} + +static int tw686x_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + unsigned int video_height = TW686X_VIDEO_HEIGHT(vc->video_standard); + const struct tw686x_format *format; + + format = format_by_fourcc(f->fmt.pix.pixelformat); + if (!format) { + format = &formats[0]; + f->fmt.pix.pixelformat = format->fourcc; + } + + if (f->fmt.pix.width <= TW686X_VIDEO_WIDTH / 2) + f->fmt.pix.width = TW686X_VIDEO_WIDTH / 2; + else + f->fmt.pix.width = TW686X_VIDEO_WIDTH; + + if (f->fmt.pix.height <= video_height / 2) + f->fmt.pix.height = video_height / 2; + else + f->fmt.pix.height = video_height; + + f->fmt.pix.bytesperline = (f->fmt.pix.width * format->depth) / 8; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + + return 0; +} + +static int tw686x_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + u32 val, width, line_width, height; + unsigned long bitsperframe; + int err, pb; + + if (vb2_is_busy(&vc->vidq)) + return -EBUSY; + + bitsperframe = vc->width * vc->height * vc->format->depth; + err = tw686x_try_fmt_vid_cap(file, priv, f); + if (err) + return err; + + vc->format = format_by_fourcc(f->fmt.pix.pixelformat); + vc->width = f->fmt.pix.width; + vc->height = f->fmt.pix.height; + + /* We need new DMA buffers if the framesize has changed */ + if (bitsperframe != vc->width * vc->height * vc->format->depth) { + for (pb = 0; pb < 2; pb++) + tw686x_free_dma(vc, pb); + + for (pb = 0; pb < 2; pb++) { + err = tw686x_alloc_dma(vc, pb); + if (err) { + if (pb > 0) + tw686x_free_dma(vc, 0); + return err; + } + } + } + + val = reg_read(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch]); + + if (vc->width <= TW686X_VIDEO_WIDTH / 2) + val |= BIT(23); + else + val &= ~BIT(23); + + if (vc->height <= TW686X_VIDEO_HEIGHT(vc->video_standard) / 2) + val |= BIT(24); + else + val &= ~BIT(24); + + val &= ~(0x7 << 20); + val |= vc->format->mode << 20; + reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val); + + /* Program the DMA frame size */ + width = (vc->width * 2) & 0x7ff; + height = vc->height / 2; + line_width = (vc->width * 2) & 0x7ff; + val = (height << 22) | (line_width << 11) | width; + reg_write(vc->dev, VDMA_WHP[vc->ch], val); + return 0; +} + +static int tw686x_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + struct tw686x_dev *dev = vc->dev; + + strlcpy(cap->driver, "tw686x", sizeof(cap->driver)); + strlcpy(cap->card, dev->name, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "PCI:%s", pci_name(dev->pci_dev)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + struct v4l2_format f; + u32 val, ret; + + if (vc->video_standard == id) + return 0; + + if (vb2_is_busy(&vc->vidq)) + return -EBUSY; + + if (id & V4L2_STD_NTSC) + val = 0; + else if (id & V4L2_STD_PAL) + val = 1; + else if (id & V4L2_STD_SECAM) + val = 2; + else if (id & V4L2_STD_NTSC_443) + val = 3; + else if (id & V4L2_STD_PAL_M) + val = 4; + else if (id & V4L2_STD_PAL_Nc) + val = 5; + else if (id & V4L2_STD_PAL_60) + val = 6; + else + return -EINVAL; + + vc->video_standard = id; + reg_write(vc->dev, SDT[vc->ch], val); + + val = reg_read(vc->dev, VIDEO_CONTROL1); + if (id & V4L2_STD_625_50) + val |= (1 << (SYS_MODE_DMA_SHIFT + vc->ch)); + else + val &= ~(1 << (SYS_MODE_DMA_SHIFT + vc->ch)); + reg_write(vc->dev, VIDEO_CONTROL1, val); + + /* + * Adjust format after V4L2_STD_525_60/V4L2_STD_625_50 change, + * calling g_fmt and s_fmt will sanitize the height + * according to the standard. + */ + ret = tw686x_g_fmt_vid_cap(file, priv, &f); + if (!ret) + tw686x_s_fmt_vid_cap(file, priv, &f); + return 0; +} + +static int tw686x_querystd(struct file *file, void *priv, v4l2_std_id *std) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + struct tw686x_dev *dev = vc->dev; + unsigned int old_std, detected_std = 0; + unsigned long end; + + if (vb2_is_streaming(&vc->vidq)) + return -EBUSY; + + /* Enable and start standard detection */ + old_std = reg_read(dev, SDT[vc->ch]); + reg_write(dev, SDT[vc->ch], 0x7); + reg_write(dev, SDT_EN[vc->ch], 0xff); + + end = jiffies + msecs_to_jiffies(500); + while (time_is_after_jiffies(end)) { + + detected_std = reg_read(dev, SDT[vc->ch]); + if (!(detected_std & BIT(7))) + break; + msleep(100); + } + reg_write(dev, SDT[vc->ch], old_std); + + /* Exit if still busy */ + if (detected_std & BIT(7)) + return 0; + + detected_std = (detected_std >> 4) & 0x7; + switch (detected_std) { + case TW686X_STD_NTSC_M: + *std &= V4L2_STD_NTSC; + break; + case TW686X_STD_NTSC_443: + *std &= V4L2_STD_NTSC_443; + break; + case TW686X_STD_PAL_M: + *std &= V4L2_STD_PAL_M; + break; + case TW686X_STD_PAL_60: + *std &= V4L2_STD_PAL_60; + break; + case TW686X_STD_PAL: + *std &= V4L2_STD_PAL; + break; + case TW686X_STD_PAL_CN: + *std &= V4L2_STD_PAL_Nc; + break; + case TW686X_STD_SECAM: + *std &= V4L2_STD_SECAM; + break; + default: + *std = 0; + } + return 0; +} + +static int tw686x_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + *id = vc->video_standard; + return 0; +} + +static int tw686x_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + f->pixelformat = formats[f->index].fourcc; + return 0; +} + +static int tw686x_s_input(struct file *file, void *priv, unsigned int i) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + u32 val; + + if (i >= TW686X_INPUTS_PER_CH) + return -EINVAL; + if (i == vc->input) + return 0; + /* + * Not sure we are able to support on the fly input change + */ + if (vb2_is_busy(&vc->vidq)) + return -EBUSY; + + vc->input = i; + + val = reg_read(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch]); + val &= ~(0x3 << 30); + val |= i << 30; + reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val); + return 0; +} + +static int tw686x_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + *i = vc->input; + return 0; +} + +static int tw686x_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + unsigned int vidstat; + + if (i->index >= TW686X_INPUTS_PER_CH) + return -EINVAL; + + snprintf(i->name, sizeof(i->name), "Composite%d", i->index); + i->type = V4L2_INPUT_TYPE_CAMERA; + i->std = vc->device->tvnorms; + i->capabilities = V4L2_IN_CAP_STD; + + vidstat = reg_read(vc->dev, VIDSTAT[vc->ch]); + i->status = 0; + if (vidstat & TW686X_VIDSTAT_VDLOSS) + i->status |= V4L2_IN_ST_NO_SIGNAL; + if (!(vidstat & TW686X_VIDSTAT_HLOCK)) + i->status |= V4L2_IN_ST_NO_H_LOCK; + + return 0; +} + +const struct v4l2_file_operations tw686x_video_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .unlocked_ioctl = video_ioctl2, + .release = vb2_fop_release, + .poll = vb2_fop_poll, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, +}; + +const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = { + .vidioc_querycap = tw686x_querycap, + .vidioc_g_fmt_vid_cap = tw686x_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = tw686x_s_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = tw686x_enum_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = tw686x_try_fmt_vid_cap, + + .vidioc_querystd = tw686x_querystd, + .vidioc_g_std = tw686x_g_std, + .vidioc_s_std = tw686x_s_std, + + .vidioc_enum_input = tw686x_enum_input, + .vidioc_g_input = tw686x_g_input, + .vidioc_s_input = tw686x_s_input, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static void tw686x_buffer_copy(struct tw686x_video_channel *vc, + unsigned int pb, struct vb2_v4l2_buffer *vb) +{ + struct tw686x_dma_desc *desc = &vc->dma_descs[pb]; + struct vb2_buffer *vb2_buf = &vb->vb2_buf; + + vb->field = V4L2_FIELD_INTERLACED; + vb->sequence = vc->sequence++; + + memcpy(vb2_plane_vaddr(vb2_buf, 0), desc->virt, desc->size); + vb2_buf->timestamp = ktime_get_ns(); + vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); +} + +void tw686x_video_irq(struct tw686x_dev *dev, unsigned long requests, + unsigned int pb_status, unsigned int fifo_status, + unsigned int *reset_ch) +{ + struct tw686x_video_channel *vc; + struct vb2_v4l2_buffer *vb; + unsigned long flags; + unsigned int ch, pb; + + for_each_set_bit(ch, &requests, max_channels(dev)) { + vc = &dev->video_channels[ch]; + + /* + * This can either be a blue frame (with signal-lost bit set) + * or a good frame (with signal-lost bit clear). If we have just + * got signal, then this channel needs resetting. + */ + if (vc->no_signal && !(fifo_status & BIT(ch))) { + v4l2_printk(KERN_DEBUG, &dev->v4l2_dev, + "video%d: signal recovered\n", vc->num); + vc->no_signal = false; + *reset_ch |= BIT(ch); + vc->pb = 0; + continue; + } + vc->no_signal = !!(fifo_status & BIT(ch)); + + /* Check FIFO errors only if there's signal */ + if (!vc->no_signal) { + u32 fifo_ov, fifo_bad; + + fifo_ov = (fifo_status >> 24) & BIT(ch); + fifo_bad = (fifo_status >> 16) & BIT(ch); + if (fifo_ov || fifo_bad) { + /* Mark this channel for reset */ + v4l2_printk(KERN_DEBUG, &dev->v4l2_dev, + "video%d: FIFO error\n", vc->num); + *reset_ch |= BIT(ch); + vc->pb = 0; + continue; + } + } + + pb = !!(pb_status & BIT(ch)); + if (vc->pb != pb) { + /* Mark this channel for reset */ + v4l2_printk(KERN_DEBUG, &dev->v4l2_dev, + "video%d: unexpected p-b buffer!\n", + vc->num); + *reset_ch |= BIT(ch); + vc->pb = 0; + continue; + } + + /* handle video stream */ + spin_lock_irqsave(&vc->qlock, flags); + if (vc->curr_bufs[pb]) { + vb = &vc->curr_bufs[pb]->vb; + tw686x_buffer_copy(vc, pb, vb); + } + vc->pb = !pb; + tw686x_buffer_refill(vc, pb); + spin_unlock_irqrestore(&vc->qlock, flags); + } +} + +void tw686x_video_free(struct tw686x_dev *dev) +{ + unsigned int ch, pb; + + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + + if (vc->device) + video_unregister_device(vc->device); + + for (pb = 0; pb < 2; pb++) + tw686x_free_dma(vc, pb); + } +} + +int tw686x_video_init(struct tw686x_dev *dev) +{ + unsigned int ch, val, pb; + int err; + + err = v4l2_device_register(&dev->pci_dev->dev, &dev->v4l2_dev); + if (err) + return err; + + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + struct video_device *vdev; + + mutex_init(&vc->vb_mutex); + spin_lock_init(&vc->qlock); + INIT_LIST_HEAD(&vc->vidq_queued); + + vc->dev = dev; + vc->ch = ch; + + /* default settings */ + vc->format = &formats[0]; + vc->video_standard = V4L2_STD_NTSC; + vc->width = TW686X_VIDEO_WIDTH; + vc->height = TW686X_VIDEO_HEIGHT(vc->video_standard); + vc->input = 0; + + reg_write(vc->dev, SDT[ch], 0); + tw686x_set_framerate(vc, 30); + + reg_write(dev, VDELAY_LO[ch], 0x14); + reg_write(dev, HACTIVE_LO[ch], 0xd0); + reg_write(dev, VIDEO_SIZE[ch], 0); + + for (pb = 0; pb < 2; pb++) { + err = tw686x_alloc_dma(vc, pb); + if (err) + goto error; + } + + vc->vidq.io_modes = VB2_READ | VB2_MMAP | VB2_DMABUF; + vc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vc->vidq.drv_priv = vc; + vc->vidq.buf_struct_size = sizeof(struct tw686x_v4l2_buf); + vc->vidq.ops = &tw686x_video_qops; + vc->vidq.mem_ops = &vb2_vmalloc_memops; + vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + vc->vidq.min_buffers_needed = 2; + vc->vidq.lock = &vc->vb_mutex; + + err = vb2_queue_init(&vc->vidq); + if (err) { + v4l2_err(&dev->v4l2_dev, + "dma%d: cannot init vb2 queue\n", ch); + goto error; + } + + err = v4l2_ctrl_handler_init(&vc->ctrl_handler, 4); + if (err) { + v4l2_err(&dev->v4l2_dev, + "dma%d: cannot init ctrl handler\n", ch); + goto error; + } + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 100); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 128); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_HUE, -128, 127, 1, 0); + err = vc->ctrl_handler.error; + if (err) + goto error; + + err = v4l2_ctrl_handler_setup(&vc->ctrl_handler); + if (err) + goto error; + + vdev = video_device_alloc(); + if (!vdev) { + v4l2_err(&dev->v4l2_dev, + "dma%d: unable to allocate device\n", ch); + err = -ENOMEM; + goto error; + } + + snprintf(vdev->name, sizeof(vdev->name), "%s video", dev->name); + vdev->fops = &tw686x_video_fops; + vdev->ioctl_ops = &tw686x_video_ioctl_ops; + vdev->release = video_device_release; + vdev->v4l2_dev = &dev->v4l2_dev; + vdev->queue = &vc->vidq; + vdev->tvnorms = V4L2_STD_525_60 | V4L2_STD_625_50; + vdev->minor = -1; + vdev->lock = &vc->vb_mutex; + vdev->ctrl_handler = &vc->ctrl_handler; + vc->device = vdev; + video_set_drvdata(vdev, vc); + + err = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (err < 0) + goto error; + vc->num = vdev->num; + } + + /* Set DMA frame mode on all channels. Only supported mode for now. */ + val = TW686X_DEF_PHASE_REF; + for (ch = 0; ch < max_channels(dev); ch++) + val |= TW686X_FRAME_MODE << (16 + ch * 2); + reg_write(dev, PHASE_REF, val); + + reg_write(dev, MISC2[0], 0xe7); + reg_write(dev, VCTRL1[0], 0xcc); + reg_write(dev, LOOP[0], 0xa5); + if (max_channels(dev) > 4) { + reg_write(dev, VCTRL1[1], 0xcc); + reg_write(dev, LOOP[1], 0xa5); + reg_write(dev, MISC2[1], 0xe7); + } + return 0; + +error: + tw686x_video_free(dev); + return err; +} diff --git a/drivers/media/pci/tw686x/tw686x.h b/drivers/media/pci/tw686x/tw686x.h new file mode 100644 index 000000000000..44b5755acf02 --- /dev/null +++ b/drivers/media/pci/tw686x/tw686x.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar + * + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * Written by Krzysztof Ha?asa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tw686x-regs.h" + +#define TYPE_MAX_CHANNELS 0x0f +#define TYPE_SECOND_GEN 0x10 +#define TW686X_DEF_PHASE_REF 0x1518 + +#define TW686X_FIELD_MODE 0x3 +#define TW686X_FRAME_MODE 0x2 +/* 0x1 is reserved */ +#define TW686X_SG_MODE 0x0 + +#define TW686X_AUDIO_PAGE_SZ 4096 +#define TW686X_AUDIO_PAGE_MAX 16 +#define TW686X_AUDIO_PERIODS_MIN 2 +#define TW686X_AUDIO_PERIODS_MAX TW686X_AUDIO_PAGE_MAX + +struct tw686x_format { + char *name; + unsigned int fourcc; + unsigned int depth; + unsigned int mode; +}; + +struct tw686x_dma_desc { + dma_addr_t phys; + void *virt; + unsigned int size; +}; + +struct tw686x_audio_buf { + dma_addr_t dma; + void *virt; + struct list_head list; +}; + +struct tw686x_v4l2_buf { + struct vb2_v4l2_buffer vb; + struct list_head list; +}; + +struct tw686x_audio_channel { + struct tw686x_dev *dev; + struct snd_pcm_substream *ss; + unsigned int ch; + struct tw686x_audio_buf *curr_bufs[2]; + struct tw686x_dma_desc dma_descs[2]; + dma_addr_t ptr; + + struct tw686x_audio_buf buf[TW686X_AUDIO_PAGE_MAX]; + struct list_head buf_list; + spinlock_t lock; +}; + +struct tw686x_video_channel { + struct tw686x_dev *dev; + + struct vb2_queue vidq; + struct list_head vidq_queued; + struct video_device *device; + struct tw686x_v4l2_buf *curr_bufs[2]; + struct tw686x_dma_desc dma_descs[2]; + + struct v4l2_ctrl_handler ctrl_handler; + const struct tw686x_format *format; + struct mutex vb_mutex; + spinlock_t qlock; + v4l2_std_id video_standard; + unsigned int width, height; + unsigned int h_halve, v_halve; + unsigned int ch; + unsigned int num; + unsigned int fps; + unsigned int input; + unsigned int sequence; + unsigned int pb; + bool no_signal; +}; + +/** + * struct tw686x_dev - global device status + * @lock: spinlock controlling access to the + * shared device registers (DMA enable/disable). + */ +struct tw686x_dev { + spinlock_t lock; + + struct v4l2_device v4l2_dev; + struct snd_card *snd_card; + + char name[32]; + unsigned int type; + struct pci_dev *pci_dev; + __u32 __iomem *mmio; + + void *alloc_ctx; + + struct tw686x_video_channel *video_channels; + struct tw686x_audio_channel *audio_channels; + + int audio_rate; /* per-device value */ + + struct timer_list dma_delay_timer; + u32 pending_dma_en; /* must be protected by lock */ + u32 pending_dma_cmd; /* must be protected by lock */ +}; + +static inline uint32_t reg_read(struct tw686x_dev *dev, unsigned int reg) +{ + return readl(dev->mmio + reg); +} + +static inline void reg_write(struct tw686x_dev *dev, unsigned int reg, + uint32_t value) +{ + writel(value, dev->mmio + reg); +} + +static inline unsigned int max_channels(struct tw686x_dev *dev) +{ + return dev->type & TYPE_MAX_CHANNELS; /* 4 or 8 channels */ +} + +void tw686x_enable_channel(struct tw686x_dev *dev, unsigned int channel); +void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel); + +int tw686x_video_init(struct tw686x_dev *dev); +void tw686x_video_free(struct tw686x_dev *dev); +void tw686x_video_irq(struct tw686x_dev *dev, unsigned long requests, + unsigned int pb_status, unsigned int fifo_status, + unsigned int *reset_ch); + +int tw686x_audio_init(struct tw686x_dev *dev); +void tw686x_audio_free(struct tw686x_dev *dev); +void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests, + unsigned int pb_status); -- GitLab From ae714c3b8e50a64d967188f3bc585bcd6a79539d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 19 Apr 2016 18:19:08 +0100 Subject: [PATCH 3697/9938] regulator: tps6524x: Fix broken use of spi_dev_get() The tps6524x driver uses spi_dev_get() to take a copy of the SPI device it uses but has no obvious reason to do so and never calls spi_dev_put() to release the reference. Fix this to just a straight copy. Signed-off-by: Mark Brown --- drivers/regulator/tps6524x-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 9d6ea3a4dccd..67cac2682f50 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -600,7 +600,7 @@ static int pmic_probe(struct spi_device *spi) memset(hw, 0, sizeof(struct tps6524x)); hw->dev = dev; - hw->spi = spi_dev_get(spi); + hw->spi = spi; mutex_init(&hw->lock); for (i = 0; i < N_REGULATORS; i++, info++, init_data++) { -- GitLab From de4a54c4dfaed0604565c1b27488dce56997acc0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 21 Jan 2016 20:19:41 +0000 Subject: [PATCH 3698/9938] regulator: core: Use a bitfield for continuous_voltage_range Using a bitfield enables the compiler to lay out the structure more efficiently when we have other boolean flags since multiple values can be included in a single byte. Signed-off-by: Mark Brown --- include/linux/regulator/driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index cd271e89a7e6..9ac3f9879576 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -292,7 +292,7 @@ struct regulator_desc { const struct regulator_desc *, struct regulator_config *); int id; - bool continuous_voltage_range; + unsigned int continuous_voltage_range:1; unsigned n_voltages; const struct regulator_ops *ops; int irq; -- GitLab From 13431509a41889a70cc76b31180f63fd10d0a5b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 20 Apr 2016 13:39:20 -0300 Subject: [PATCH 3699/9938] [media] tw686x-kh: use the cached value the dma_requests field is cached, but cache is not used: drivers/staging/media/tw686x-kh/tw686x-kh-video.c: In function 'tw686x_video_irq': drivers/staging/media/tw686x-kh/tw686x-kh-video.c:622:6: warning: variable 'requests' set but not used [-Wunused-but-set-variable] u32 requests; ^ Use the cache instead, as it seems reading it needs to be done with spin lock taken. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tw686x-kh/tw686x-kh-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c index 2fbc3cbd9eb0..0650c29f78eb 100644 --- a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c @@ -625,7 +625,7 @@ int tw686x_video_irq(struct tw686x_dev *dev) requests = dev->dma_requests; spin_unlock_irqrestore(&dev->irq_lock, flags); - if (dev->dma_requests & dev->video_active) { + if (requests & dev->video_active) { wake_up_interruptible_all(&dev->video_thread_wait); handled = 1; } -- GitLab From 304d2a7fc8acc1bb337596e0fc301092ea079b4d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 21 Mar 2016 08:07:44 -0300 Subject: [PATCH 3700/9938] [media] tw686x-kh: specify that the DMA is 32 bits Set vb2_queue.gfp_flags to GFP_DMA32. Otherwise it will start to create bounce buffers which is something you want to avoid since those are in limited supply. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tw686x-kh/tw686x-kh-video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c index 0650c29f78eb..2065c6c906bc 100644 --- a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c @@ -766,6 +766,7 @@ int tw686x_video_init(struct tw686x_dev *dev) vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; vc->vidq.min_buffers_needed = 2; vc->vidq.lock = &vc->vb_mutex; + vc->vidq.gfp_flags = GFP_DMA32; err = vb2_queue_init(&vc->vidq); if (err) -- GitLab From e4c32b495fd06831e3f1553a6ebac5c68431b2a8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 21 Mar 2016 08:17:14 -0300 Subject: [PATCH 3701/9938] [media] tw686x-kh: add audio support to the TODO list The mainline tw686x driver also supports audio, that's missing here as well. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tw686x-kh/TODO | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/tw686x-kh/TODO b/drivers/staging/media/tw686x-kh/TODO index f226e808390e..480a495b11fb 100644 --- a/drivers/staging/media/tw686x-kh/TODO +++ b/drivers/staging/media/tw686x-kh/TODO @@ -1,3 +1,6 @@ -TODO: implement V4L2_FIELD_INTERLACED* mode(s). +TODO: + +- implement V4L2_FIELD_INTERLACED* mode(s). +- add audio support Please Cc: patches to Krzysztof Halasa . -- GitLab From 2e2dedb96ddd9e4f8d8a0330bc31ac56670a36b4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 21 Mar 2016 12:09:59 -0300 Subject: [PATCH 3702/9938] [media] tw686x: add missing statics Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw686x/tw686x-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index 35ad8e650717..2356fa2e951d 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -665,7 +665,7 @@ static int tw686x_enum_input(struct file *file, void *priv, return 0; } -const struct v4l2_file_operations tw686x_video_fops = { +static const struct v4l2_file_operations tw686x_video_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, .unlocked_ioctl = video_ioctl2, @@ -675,7 +675,7 @@ const struct v4l2_file_operations tw686x_video_fops = { .mmap = vb2_fop_mmap, }; -const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = { +static const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = { .vidioc_querycap = tw686x_querycap, .vidioc_g_fmt_vid_cap = tw686x_g_fmt_vid_cap, .vidioc_s_fmt_vid_cap = tw686x_s_fmt_vid_cap, -- GitLab From e3a900a8fae22949523e0b6c3f0626ce5f3f48c3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 21 Mar 2016 12:10:12 -0300 Subject: [PATCH 3703/9938] [media] tw686x-kh: rename three functions to prevent clash with tw686x driver Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tw686x-kh/tw686x-kh-core.c | 6 +++--- drivers/staging/media/tw686x-kh/tw686x-kh-video.c | 12 ++++++------ drivers/staging/media/tw686x-kh/tw686x-kh.h | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-core.c b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c index c3c5c2602541..03b3b62c59c4 100644 --- a/drivers/staging/media/tw686x-kh/tw686x-kh-core.c +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c @@ -30,7 +30,7 @@ static irqreturn_t tw686x_irq(int irq, void *dev_id) spin_unlock_irqrestore(&dev->irq_lock, flags); if (int_status & 0xFF0000FF) - handled = tw686x_video_irq(dev); + handled = tw686x_kh_video_irq(dev); } return IRQ_RETVAL(handled); @@ -99,7 +99,7 @@ static int tw686x_probe(struct pci_dev *pci_dev, return err; } - err = tw686x_video_init(dev); + err = tw686x_kh_video_init(dev); if (err) return err; @@ -111,7 +111,7 @@ static void tw686x_remove(struct pci_dev *pci_dev) { struct tw686x_dev *dev = pci_get_drvdata(pci_dev); - tw686x_video_free(dev); + tw686x_kh_video_free(dev); } /* driver_data is number of A/V channels */ diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c index 2065c6c906bc..6ecb504a79f9 100644 --- a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c @@ -503,7 +503,7 @@ static int tw686x_s_input(struct file *file, void *priv, unsigned int v) return 0; } -const struct v4l2_file_operations tw686x_video_fops = { +static const struct v4l2_file_operations tw686x_video_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, .unlocked_ioctl = video_ioctl2, @@ -513,7 +513,7 @@ const struct v4l2_file_operations tw686x_video_fops = { .mmap = vb2_fop_mmap, }; -const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = { +static const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = { .vidioc_querycap = tw686x_querycap, .vidioc_enum_fmt_vid_cap = tw686x_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = tw686x_g_fmt_vid_cap, @@ -616,7 +616,7 @@ static int video_thread(void *arg) return 0; } -int tw686x_video_irq(struct tw686x_dev *dev) +int tw686x_kh_video_irq(struct tw686x_dev *dev) { unsigned long flags, handled = 0; u32 requests; @@ -632,7 +632,7 @@ int tw686x_video_irq(struct tw686x_dev *dev) return handled; } -void tw686x_video_free(struct tw686x_dev *dev) +void tw686x_kh_video_free(struct tw686x_dev *dev) { unsigned int ch, n; @@ -660,7 +660,7 @@ void tw686x_video_free(struct tw686x_dev *dev) #define SG_TABLE_SIZE (MAX_SG_DESC_COUNT * sizeof(struct vdma_desc)) -int tw686x_video_init(struct tw686x_dev *dev) +int tw686x_kh_video_init(struct tw686x_dev *dev) { unsigned int ch, n; int err; @@ -816,6 +816,6 @@ int tw686x_video_init(struct tw686x_dev *dev) return 0; error: - tw686x_video_free(dev); + tw686x_kh_video_free(dev); return err; } diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh.h b/drivers/staging/media/tw686x-kh/tw686x-kh.h index 46c4ebd7f00c..dc257967dbc7 100644 --- a/drivers/staging/media/tw686x-kh/tw686x-kh.h +++ b/drivers/staging/media/tw686x-kh/tw686x-kh.h @@ -113,6 +113,6 @@ static inline unsigned int is_second_gen(struct tw686x_dev *dev) return dev->type & TYPE_SECOND_GEN; } -int tw686x_video_irq(struct tw686x_dev *dev); -int tw686x_video_init(struct tw686x_dev *dev); -void tw686x_video_free(struct tw686x_dev *dev); +int tw686x_kh_video_irq(struct tw686x_dev *dev); +int tw686x_kh_video_init(struct tw686x_dev *dev); +void tw686x_kh_video_free(struct tw686x_dev *dev); -- GitLab From 1c9f47195ef83ffd59ff665f2006789c0610cff0 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 1 Apr 2016 19:38:21 -0300 Subject: [PATCH 3704/9938] [media] tw686x: Specify that the DMA is 32 bits Set vb2_queue.gfp_flags to GFP_DMA32. Otherwise it will start to create bounce buffers which is something you want to avoid since those are in limited supply. Without this patch, DMA scatter-gather may not work because machines can ran out of buffers easily. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw686x/tw686x-video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index 2356fa2e951d..118e9fac9f28 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -848,6 +848,7 @@ int tw686x_video_init(struct tw686x_dev *dev) vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; vc->vidq.min_buffers_needed = 2; vc->vidq.lock = &vc->vb_mutex; + vc->vidq.gfp_flags = GFP_DMA32; err = vb2_queue_init(&vc->vidq); if (err) { -- GitLab From 3fb55c79d092d085bddd4fc94f250acfc1275f3d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:44:36 +0300 Subject: [PATCH 3705/9938] ath10k: remove deprecated firmware API 1 support This has ben deprecated years ago, I haven't heard anyone using it since and most likely it won't even work anymore. So just remove all of it. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 73 -------------------------- drivers/net/wireless/ath/ath10k/core.h | 3 -- drivers/net/wireless/ath/ath10k/hw.h | 12 ----- drivers/net/wireless/ath/ath10k/pci.c | 1 - drivers/net/wireless/ath/ath10k/wmi.c | 4 -- 5 files changed, 93 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 1c4106b84a35..48389e0b87f6 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -63,8 +63,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 2116, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, - .fw = QCA988X_HW_2_0_FW_FILE, - .otp = QCA988X_HW_2_0_OTP_FILE, .board = QCA988X_HW_2_0_BOARD_DATA_FILE, .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, @@ -82,8 +80,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, - .fw = QCA6174_HW_2_1_FW_FILE, - .otp = QCA6174_HW_2_1_OTP_FILE, .board = QCA6174_HW_2_1_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -102,8 +98,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, - .fw = QCA6174_HW_2_1_FW_FILE, - .otp = QCA6174_HW_2_1_OTP_FILE, .board = QCA6174_HW_2_1_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -122,8 +116,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, - .fw = QCA6174_HW_3_0_FW_FILE, - .otp = QCA6174_HW_3_0_OTP_FILE, .board = QCA6174_HW_3_0_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -143,8 +135,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, - .fw = QCA6174_HW_3_0_FW_FILE, - .otp = QCA6174_HW_3_0_OTP_FILE, .board = QCA6174_HW_3_0_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -167,8 +157,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 12064, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, - .fw = QCA99X0_HW_2_0_FW_FILE, - .otp = QCA99X0_HW_2_0_OTP_FILE, .board = QCA99X0_HW_2_0_BOARD_DATA_FILE, .board_size = QCA99X0_BOARD_DATA_SZ, .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, @@ -186,8 +174,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA9377_HW_1_0_FW_DIR, - .fw = QCA9377_HW_1_0_FW_FILE, - .otp = QCA9377_HW_1_0_OTP_FILE, .board = QCA9377_HW_1_0_BOARD_DATA_FILE, .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, @@ -205,8 +191,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA9377_HW_1_0_FW_DIR, - .fw = QCA9377_HW_1_0_FW_FILE, - .otp = QCA9377_HW_1_0_OTP_FILE, .board = QCA9377_HW_1_0_BOARD_DATA_FILE, .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, @@ -229,8 +213,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 12064, .fw = { .dir = QCA4019_HW_1_0_FW_DIR, - .fw = QCA4019_HW_1_0_FW_FILE, - .otp = QCA4019_HW_1_0_OTP_FILE, .board = QCA4019_HW_1_0_BOARD_DATA_FILE, .board_size = QCA4019_BOARD_DATA_SZ, .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ, @@ -703,9 +685,6 @@ static void ath10k_core_free_board_files(struct ath10k *ar) static void ath10k_core_free_firmware_files(struct ath10k *ar) { - if (!IS_ERR(ar->otp)) - release_firmware(ar->otp); - if (!IS_ERR(ar->firmware)) release_firmware(ar->firmware); @@ -714,7 +693,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ath10k_swap_code_seg_release(ar); - ar->otp = NULL; ar->otp_data = NULL; ar->otp_len = 0; @@ -1000,50 +978,6 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) -{ - int ret = 0; - - if (ar->hw_params.fw.fw == NULL) { - ath10k_err(ar, "firmware file not defined\n"); - return -EINVAL; - } - - ar->firmware = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.fw); - if (IS_ERR(ar->firmware)) { - ret = PTR_ERR(ar->firmware); - ath10k_err(ar, "could not fetch firmware (%d)\n", ret); - goto err; - } - - ar->firmware_data = ar->firmware->data; - ar->firmware_len = ar->firmware->size; - - /* OTP may be undefined. If so, don't fetch it at all */ - if (ar->hw_params.fw.otp == NULL) - return 0; - - ar->otp = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.otp); - if (IS_ERR(ar->otp)) { - ret = PTR_ERR(ar->otp); - ath10k_err(ar, "could not fetch otp (%d)\n", ret); - goto err; - } - - ar->otp_data = ar->otp->data; - ar->otp_len = ar->otp->size; - - return 0; - -err: - ath10k_core_free_firmware_files(ar); - return ret; -} - static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) { size_t magic_len, len, ie_len; @@ -1253,13 +1187,6 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE); - if (ret == 0) - goto success; - - ar->fw_api = 1; - ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - - ret = ath10k_core_fetch_firmware_api_1(ar); if (ret) return ret; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index e6f889df1e0d..2d0cc92f3c5b 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -708,8 +708,6 @@ struct ath10k { struct ath10k_hw_params_fw { const char *dir; - const char *fw; - const char *otp; const char *board; size_t board_size; size_t board_ext_size; @@ -720,7 +718,6 @@ struct ath10k { const void *board_data; size_t board_len; - const struct firmware *otp; const void *otp_data; size_t otp_len; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index c0179bc4af29..aedd8987040b 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -35,8 +35,6 @@ #define QCA988X_HW_2_0_VERSION 0x4100016c #define QCA988X_HW_2_0_CHIP_ID_REV 0x2 #define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0" -#define QCA988X_HW_2_0_FW_FILE "firmware.bin" -#define QCA988X_HW_2_0_OTP_FILE "otp.bin" #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 @@ -76,14 +74,10 @@ enum qca9377_chip_id_rev { }; #define QCA6174_HW_2_1_FW_DIR "ath10k/QCA6174/hw2.1" -#define QCA6174_HW_2_1_FW_FILE "firmware.bin" -#define QCA6174_HW_2_1_OTP_FILE "otp.bin" #define QCA6174_HW_2_1_BOARD_DATA_FILE "board.bin" #define QCA6174_HW_2_1_PATCH_LOAD_ADDR 0x1234 #define QCA6174_HW_3_0_FW_DIR "ath10k/QCA6174/hw3.0" -#define QCA6174_HW_3_0_FW_FILE "firmware.bin" -#define QCA6174_HW_3_0_OTP_FILE "otp.bin" #define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin" #define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234 @@ -94,23 +88,17 @@ enum qca9377_chip_id_rev { #define QCA99X0_HW_2_0_DEV_VERSION 0x01000000 #define QCA99X0_HW_2_0_CHIP_ID_REV 0x1 #define QCA99X0_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA99X0/hw2.0" -#define QCA99X0_HW_2_0_FW_FILE "firmware.bin" -#define QCA99X0_HW_2_0_OTP_FILE "otp.bin" #define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234 /* QCA9377 1.0 definitions */ #define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0" -#define QCA9377_HW_1_0_FW_FILE "firmware.bin" -#define QCA9377_HW_1_0_OTP_FILE "otp.bin" #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" #define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 /* QCA4019 1.0 definitions */ #define QCA4019_HW_1_0_DEV_VERSION 0x01000000 #define QCA4019_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA4019/hw1.0" -#define QCA4019_HW_1_0_FW_FILE "firmware.bin" -#define QCA4019_HW_1_0_OTP_FILE "otp.bin" #define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin" #define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234 diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index cdd8a307c55b..8133d7b5b956 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3173,7 +3173,6 @@ MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); MODULE_LICENSE("Dual BSD/GPL"); /* QCA988x 2.0 firmware files */ -MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 7eb40f54fdb5..254844b37d92 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4604,10 +4604,6 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", arg.service_map, arg.service_map_len); - /* only manually set fw features when not using FW IE format */ - if (ar->fw_api == 1 && ar->fw_version_build > 636) - set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features); - if (ar->num_rf_chains > ar->max_spatial_stream) { ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n", ar->num_rf_chains, ar->max_spatial_stream); -- GitLab From 7ebf721d0d47150f6e327a6ae2692779495a2c2a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:44:51 +0300 Subject: [PATCH 3706/9938] ath10k: refactor firmware images to struct ath10k_fw_components To make it easier to share ath10k_core_fetch_board_data_api_n() with testmode.c refactor all firmware components to struct ath10k_fw_components. This structure will hold firmware related files, for example firmware-N.bin and board-N.bin. For firmware-N.bin create a new struct ath10k_fw_file which contains the actual firmware image as well as the parsed data from the image. Modify ath10k_core_start() to take struct ath10k_fw_components() as an argument which makes it possible in following patches to drop some ugly hacks from testmode.c. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 176 +++++++++++---------- drivers/net/wireless/ath/ath10k/core.h | 46 ++++-- drivers/net/wireless/ath/ath10k/debug.c | 28 ++-- drivers/net/wireless/ath/ath10k/mac.c | 3 +- drivers/net/wireless/ath/ath10k/swap.c | 22 ++- drivers/net/wireless/ath/ath10k/testmode.c | 61 ++++--- 6 files changed, 199 insertions(+), 137 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 48389e0b87f6..b2efece5b32d 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -538,7 +538,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) address = ar->hw_params.patch_load_addr; - if (!ar->otp_data || !ar->otp_len) { + if (!ar->normal_mode_fw.fw_file.otp_data || + !ar->normal_mode_fw.fw_file.otp_len) { ath10k_warn(ar, "failed to retrieve board id because of invalid otp\n"); return -ENODATA; @@ -546,9 +547,11 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd for board id\n", - address, ar->otp_len); + address, ar->normal_mode_fw.fw_file.otp_len); - ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); + ret = ath10k_bmi_fast_download(ar, address, + ar->normal_mode_fw.fw_file.otp_data, + ar->normal_mode_fw.fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp for board id check: %d\n", ret); @@ -586,7 +589,9 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; int ret; - ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len); + ret = ath10k_download_board_data(ar, + ar->running_fw->board_data, + ar->running_fw->board_len); if (ret) { ath10k_err(ar, "failed to download board data: %d\n", ret); return ret; @@ -594,16 +599,20 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) /* OTP is optional */ - if (!ar->otp_data || !ar->otp_len) { + if (!ar->running_fw->fw_file.otp_data || + !ar->running_fw->fw_file.otp_len) { ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n", - ar->otp_data, ar->otp_len); + ar->running_fw->fw_file.otp_data, + ar->running_fw->fw_file.otp_len); return 0; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", - address, ar->otp_len); + address, ar->running_fw->fw_file.otp_len); - ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); + ret = ath10k_bmi_fast_download(ar, address, + ar->running_fw->fw_file.otp_data, + ar->running_fw->fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp (%d)\n", ret); return ret; @@ -627,46 +636,33 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) return 0; } -static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) +static int ath10k_download_fw(struct ath10k *ar) { u32 address, data_len; - const char *mode_name; const void *data; int ret; address = ar->hw_params.patch_load_addr; - switch (mode) { - case ATH10K_FIRMWARE_MODE_NORMAL: - data = ar->firmware_data; - data_len = ar->firmware_len; - mode_name = "normal"; - ret = ath10k_swap_code_seg_configure(ar, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); - if (ret) { - ath10k_err(ar, "failed to configure fw code swap: %d\n", - ret); - return ret; - } - break; - case ATH10K_FIRMWARE_MODE_UTF: - data = ar->testmode.utf_firmware_data; - data_len = ar->testmode.utf_firmware_len; - mode_name = "utf"; - break; - default: - ath10k_err(ar, "unknown firmware mode: %d\n", mode); - return -EINVAL; + data = ar->running_fw->fw_file.firmware_data; + data_len = ar->running_fw->fw_file.firmware_len; + + ret = ath10k_swap_code_seg_configure(ar, + ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + if (ret) { + ath10k_err(ar, "failed to configure fw code swap: %d\n", + ret); + return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, - "boot uploading firmware image %p len %d mode %s\n", - data, data_len, mode_name); + "boot uploading firmware image %p len %d\n", + data, data_len); ret = ath10k_bmi_fast_download(ar, address, data, data_len); if (ret) { - ath10k_err(ar, "failed to download %s firmware: %d\n", - mode_name, ret); + ath10k_err(ar, "failed to download firmware: %d\n", + ret); return ret; } @@ -675,30 +671,30 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) static void ath10k_core_free_board_files(struct ath10k *ar) { - if (!IS_ERR(ar->board)) - release_firmware(ar->board); + if (!IS_ERR(ar->normal_mode_fw.board)) + release_firmware(ar->normal_mode_fw.board); - ar->board = NULL; - ar->board_data = NULL; - ar->board_len = 0; + ar->normal_mode_fw.board = NULL; + ar->normal_mode_fw.board_data = NULL; + ar->normal_mode_fw.board_len = 0; } static void ath10k_core_free_firmware_files(struct ath10k *ar) { - if (!IS_ERR(ar->firmware)) - release_firmware(ar->firmware); + if (!IS_ERR(ar->normal_mode_fw.fw_file.firmware)) + release_firmware(ar->normal_mode_fw.fw_file.firmware); if (!IS_ERR(ar->cal_file)) release_firmware(ar->cal_file); ath10k_swap_code_seg_release(ar); - ar->otp_data = NULL; - ar->otp_len = 0; + ar->normal_mode_fw.fw_file.otp_data = NULL; + ar->normal_mode_fw.fw_file.otp_len = 0; - ar->firmware = NULL; - ar->firmware_data = NULL; - ar->firmware_len = 0; + ar->normal_mode_fw.fw_file.firmware = NULL; + ar->normal_mode_fw.fw_file.firmware_data = NULL; + ar->normal_mode_fw.fw_file.firmware_len = 0; ar->cal_file = NULL; } @@ -737,14 +733,14 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar) return -EINVAL; } - ar->board = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.board); - if (IS_ERR(ar->board)) - return PTR_ERR(ar->board); + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + ar->hw_params.fw.board); + if (IS_ERR(ar->normal_mode_fw.board)) + return PTR_ERR(ar->normal_mode_fw.board); - ar->board_data = ar->board->data; - ar->board_len = ar->board->size; + ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data; + ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size; return 0; } @@ -804,8 +800,8 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, "boot found board data for '%s'", boardname); - ar->board_data = board_ie_data; - ar->board_len = board_ie_len; + ar->normal_mode_fw.board_data = board_ie_data; + ar->normal_mode_fw.board_len = board_ie_len; ret = 0; goto out; @@ -838,12 +834,14 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, const u8 *data; int ret, ie_id; - ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename); - if (IS_ERR(ar->board)) - return PTR_ERR(ar->board); + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + filename); + if (IS_ERR(ar->normal_mode_fw.board)) + return PTR_ERR(ar->normal_mode_fw.board); - data = ar->board->data; - len = ar->board->size; + data = ar->normal_mode_fw.board->data; + len = ar->normal_mode_fw.board->size; /* magic has extra null byte padded */ magic_len = strlen(ATH10K_BOARD_MAGIC) + 1; @@ -910,7 +908,7 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, } out: - if (!ar->board_data || !ar->board_len) { + if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) { ath10k_err(ar, "failed to fetch board data for %s from %s/%s\n", boardname, ar->hw_params.fw.dir, filename); @@ -978,7 +976,8 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) +static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, + struct ath10k_fw_file *fw_file) { size_t magic_len, len, ie_len; int ie_id, i, index, bit, ret; @@ -987,15 +986,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) __le32 *timestamp, *version; /* first fetch the firmware file (firmware-*.bin) */ - ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name); - if (IS_ERR(ar->firmware)) { + fw_file->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, + name); + if (IS_ERR(fw_file->firmware)) { ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n", - ar->hw_params.fw.dir, name, PTR_ERR(ar->firmware)); - return PTR_ERR(ar->firmware); + ar->hw_params.fw.dir, name, + PTR_ERR(fw_file->firmware)); + return PTR_ERR(fw_file->firmware); } - data = ar->firmware->data; - len = ar->firmware->size; + data = fw_file->firmware->data; + len = fw_file->firmware->size; /* magic also includes the null byte, check that as well */ magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; @@ -1086,8 +1087,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) "found fw image ie (%zd B)\n", ie_len); - ar->firmware_data = data; - ar->firmware_len = ie_len; + fw_file->firmware_data = data; + fw_file->firmware_len = ie_len; break; case ATH10K_FW_IE_OTP_IMAGE: @@ -1095,8 +1096,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) "found otp image ie (%zd B)\n", ie_len); - ar->otp_data = data; - ar->otp_len = ie_len; + fw_file->otp_data = data; + fw_file->otp_len = ie_len; break; case ATH10K_FW_IE_WMI_OP_VERSION: @@ -1125,8 +1126,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw code swap image ie (%zd B)\n", ie_len); - ar->swap.firmware_codeswap_data = data; - ar->swap.firmware_codeswap_len = ie_len; + fw_file->codeswap_data = data; + fw_file->codeswap_len = ie_len; break; default: ath10k_warn(ar, "Unknown FW IE: %u\n", @@ -1141,7 +1142,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) data += ie_len; } - if (!ar->firmware_data || !ar->firmware_len) { + if (!fw_file->firmware_data || + !fw_file->firmware_len) { ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n", ar->hw_params.fw.dir, name); ret = -ENOMEDIUM; @@ -1165,28 +1167,32 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ar->fw_api = 5; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE, + &ar->normal_mode_fw.fw_file); if (ret == 0) goto success; ar->fw_api = 4; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE, + &ar->normal_mode_fw.fw_file); if (ret == 0) goto success; ar->fw_api = 3; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE, + &ar->normal_mode_fw.fw_file); if (ret == 0) goto success; ar->fw_api = 2; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE, + &ar->normal_mode_fw.fw_file); if (ret) return ret; @@ -1585,7 +1591,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) return 0; } -int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) +int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, + const struct ath10k_fw_components *fw) { int status; u32 val; @@ -1594,6 +1601,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); + ar->running_fw = fw; + ath10k_bmi_start(ar); if (ath10k_init_configure_target(ar)) { @@ -1621,7 +1630,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) } } - status = ath10k_download_fw(ar, mode); + status = ath10k_download_fw(ar); if (status) goto err; @@ -1899,7 +1908,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar) mutex_lock(&ar->conf_mutex); - ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL); + ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL, + &ar->normal_mode_fw); if (ret) { ath10k_err(ar, "could not init core (%d)\n", ret); goto err_unlock; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 2d0cc92f3c5b..b377fd42c0a3 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -627,6 +627,27 @@ enum ath10k_tx_pause_reason { ATH10K_TX_PAUSE_MAX, }; +struct ath10k_fw_file { + const struct firmware *firmware; + + const void *firmware_data; + size_t firmware_len; + + const void *otp_data; + size_t otp_len; + + const void *codeswap_data; + size_t codeswap_len; +}; + +struct ath10k_fw_components { + const struct firmware *board; + const void *board_data; + size_t board_len; + + struct ath10k_fw_file fw_file; +}; + struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; @@ -714,23 +735,18 @@ struct ath10k { } fw; } hw_params; - const struct firmware *board; - const void *board_data; - size_t board_len; + /* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */ + struct ath10k_fw_components normal_mode_fw; - const void *otp_data; - size_t otp_len; - - const struct firmware *firmware; - const void *firmware_data; - size_t firmware_len; + /* READ-ONLY images of the running firmware, which can be either + * normal or UTF. Do not modify, release etc! + */ + const struct ath10k_fw_components *running_fw; const struct firmware *pre_cal_file; const struct firmware *cal_file; struct { - const void *firmware_codeswap_data; - size_t firmware_codeswap_len; struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info; } swap; @@ -876,13 +892,12 @@ struct ath10k { struct { /* protected by conf_mutex */ - const struct firmware *utf; + struct ath10k_fw_components utf_mode_fw; char utf_version[32]; - const void *utf_firmware_data; - size_t utf_firmware_len; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; enum ath10k_fw_wmi_op_version op_version; + /* protected by data_lock */ bool utf_monitor; } testmode; @@ -919,7 +934,8 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar, char *buf, size_t max_len); -int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode); +int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, + const struct ath10k_fw_components *fw_components); int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt); void ath10k_core_stop(struct ath10k *ar); int ath10k_core_register(struct ath10k *ar, u32 chip_id); diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index e7d441caa288..27787d23b2bd 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -126,6 +126,7 @@ EXPORT_SYMBOL(ath10k_info); void ath10k_debug_print_hwfw_info(struct ath10k *ar) { + const struct firmware *firmware; char fw_features[128] = {}; u32 crc = 0; @@ -144,8 +145,9 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar) config_enabled(CONFIG_ATH10K_DFS_CERTIFIED), config_enabled(CONFIG_NL80211_TESTMODE)); - if (ar->firmware) - crc = crc32_le(0, ar->firmware->data, ar->firmware->size); + firmware = ar->normal_mode_fw.fw_file.firmware; + if (firmware) + crc = crc32_le(0, firmware->data, firmware->size); ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n", ar->hw->wiphy->fw_version, @@ -167,7 +169,8 @@ void ath10k_debug_print_board_info(struct ath10k *ar) ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x", ar->bd_api, boardinfo, - crc32_le(0, ar->board->data, ar->board->size)); + crc32_le(0, ar->normal_mode_fw.board->data, + ar->normal_mode_fw.board->size)); } void ath10k_debug_print_boot_info(struct ath10k *ar) @@ -2270,23 +2273,28 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file, len += scnprintf(buf + len, buf_len - len, "firmware-N.bin\t\t%08x\n", - crc32_le(0, ar->firmware->data, ar->firmware->size)); + crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data, + ar->normal_mode_fw.fw_file.firmware->size)); len += scnprintf(buf + len, buf_len - len, "athwlan\t\t\t%08x\n", - crc32_le(0, ar->firmware_data, ar->firmware_len)); + crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data, + ar->normal_mode_fw.fw_file.firmware_len)); len += scnprintf(buf + len, buf_len - len, "otp\t\t\t%08x\n", - crc32_le(0, ar->otp_data, ar->otp_len)); + crc32_le(0, ar->normal_mode_fw.fw_file.otp_data, + ar->normal_mode_fw.fw_file.otp_len)); len += scnprintf(buf + len, buf_len - len, "codeswap\t\t%08x\n", - crc32_le(0, ar->swap.firmware_codeswap_data, - ar->swap.firmware_codeswap_len)); + crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data, + ar->normal_mode_fw.fw_file.codeswap_len)); len += scnprintf(buf + len, buf_len - len, "board-N.bin\t\t%08x\n", - crc32_le(0, ar->board->data, ar->board->size)); + crc32_le(0, ar->normal_mode_fw.board->data, + ar->normal_mode_fw.board->size)); len += scnprintf(buf + len, buf_len - len, "board\t\t\t%08x\n", - crc32_le(0, ar->board_data, ar->board_len)); + crc32_le(0, ar->normal_mode_fw.board_data, + ar->normal_mode_fw.board_len)); ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index fb393596f236..56abbf2f2a59 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4376,7 +4376,8 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err_off; } - ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL); + ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL, + &ar->normal_mode_fw); if (ret) { ath10k_err(ar, "Could not init core: %d\n", ret); goto err_power_down; diff --git a/drivers/net/wireless/ath/ath10k/swap.c b/drivers/net/wireless/ath/ath10k/swap.c index 3ca3fae408a7..47d449bac86d 100644 --- a/drivers/net/wireless/ath/ath10k/swap.c +++ b/drivers/net/wireless/ath/ath10k/swap.c @@ -171,8 +171,13 @@ int ath10k_swap_code_seg_configure(struct ath10k *ar, void ath10k_swap_code_seg_release(struct ath10k *ar) { ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info); - ar->swap.firmware_codeswap_data = NULL; - ar->swap.firmware_codeswap_len = 0; + + /* FIXME: these two assignments look to bein wrong place! Shouldn't + * they be in ath10k_core_free_firmware_files() like the rest? + */ + ar->normal_mode_fw.fw_file.codeswap_data = NULL; + ar->normal_mode_fw.fw_file.codeswap_len = 0; + ar->swap.firmware_swap_code_seg_info = NULL; } @@ -180,20 +185,23 @@ int ath10k_swap_code_seg_init(struct ath10k *ar) { int ret; struct ath10k_swap_code_seg_info *seg_info; + const void *codeswap_data; + size_t codeswap_len; + + codeswap_data = ar->normal_mode_fw.fw_file.codeswap_data; + codeswap_len = ar->normal_mode_fw.fw_file.codeswap_len; - if (!ar->swap.firmware_codeswap_len || !ar->swap.firmware_codeswap_data) + if (!codeswap_len || !codeswap_data) return 0; - seg_info = ath10k_swap_code_seg_alloc(ar, - ar->swap.firmware_codeswap_len); + seg_info = ath10k_swap_code_seg_alloc(ar, codeswap_len); if (!seg_info) { ath10k_err(ar, "failed to allocate fw code swap segment\n"); return -ENOMEM; } ret = ath10k_swap_code_seg_fill(ar, seg_info, - ar->swap.firmware_codeswap_data, - ar->swap.firmware_codeswap_len); + codeswap_data, codeswap_len); if (ret) { ath10k_warn(ar, "failed to initialize fw code swap segment: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 1d5a2fdcbf56..480fad301fad 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -139,7 +139,8 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) return cfg80211_testmode_reply(skb); } -static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) +static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, + struct ath10k_fw_file *fw_file) { size_t len, magic_len, ie_len; struct ath10k_fw_ie *hdr; @@ -152,15 +153,15 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); /* load utf firmware image */ - ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + ret = request_firmware(&fw_file->firmware, filename, ar->dev); if (ret) { ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", filename, ret); return ret; } - data = ar->testmode.utf->data; - len = ar->testmode.utf->size; + data = fw_file->firmware->data; + len = fw_file->firmware->size; /* FIXME: call release_firmware() in error cases */ @@ -222,8 +223,8 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) "testmode found fw image ie (%zd B)\n", ie_len); - ar->testmode.utf_firmware_data = data; - ar->testmode.utf_firmware_len = ie_len; + fw_file->firmware_data = data; + fw_file->firmware_len = ie_len; break; case ATH10K_FW_IE_WMI_OP_VERSION: if (ie_len != sizeof(u32)) @@ -245,7 +246,7 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) data += ie_len; } - if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { + if (!fw_file->firmware_data || !fw_file->firmware_len) { ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); ret = -EINVAL; goto err; @@ -254,12 +255,13 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) return 0; err: - release_firmware(ar->testmode.utf); + release_firmware(fw_file->firmware); return ret; } -static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) +static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, + struct ath10k_fw_file *fw_file) { char filename[100]; int ret; @@ -268,7 +270,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); /* load utf firmware image */ - ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + ret = request_firmware(&fw_file->firmware, filename, ar->dev); if (ret) { ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", filename, ret); @@ -282,23 +284,24 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) */ ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; - ar->testmode.utf_firmware_data = ar->testmode.utf->data; - ar->testmode.utf_firmware_len = ar->testmode.utf->size; + fw_file->firmware_data = fw_file->firmware->data; + fw_file->firmware_len = fw_file->firmware->size; return 0; } static int ath10k_tm_fetch_firmware(struct ath10k *ar) { + struct ath10k_fw_components *utf_mode_fw; int ret; - ret = ath10k_tm_fetch_utf_firmware_api_2(ar); + ret = ath10k_tm_fetch_utf_firmware_api_2(ar, &ar->testmode.utf_mode_fw.fw_file); if (ret == 0) { ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); - return 0; + goto out; } - ret = ath10k_tm_fetch_utf_firmware_api_1(ar); + ret = ath10k_tm_fetch_utf_firmware_api_1(ar, &ar->testmode.utf_mode_fw.fw_file); if (ret) { ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret); return ret; @@ -306,6 +309,21 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1"); +out: + utf_mode_fw = &ar->testmode.utf_mode_fw; + + /* Use the same board data file as the normal firmware uses (but + * it's still "owned" by normal_mode_fw so we shouldn't free it. + */ + utf_mode_fw->board_data = ar->normal_mode_fw.board_data; + utf_mode_fw->board_len = ar->normal_mode_fw.board_len; + + if (!utf_mode_fw->fw_file.otp_data) { + ath10k_info(ar, "utf.bin didn't contain otp binary, taking it from the normal mode firmware"); + utf_mode_fw->fw_file.otp_data = ar->normal_mode_fw.fw_file.otp_data; + utf_mode_fw->fw_file.otp_len = ar->normal_mode_fw.fw_file.otp_len; + } + return 0; } @@ -329,7 +347,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) goto err; } - if (WARN_ON(ar->testmode.utf != NULL)) { + if (WARN_ON(ar->testmode.utf_mode_fw.fw_file.firmware != NULL)) { /* utf image is already downloaded, it shouldn't be */ ret = -EEXIST; goto err; @@ -364,7 +382,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) goto err_fw_features; } - ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF); + ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF, + &ar->testmode.utf_mode_fw); if (ret) { ath10k_err(ar, "failed to start core (testmode): %d\n", ret); ar->state = ATH10K_STATE_OFF; @@ -393,8 +412,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) sizeof(ar->fw_features)); ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - release_firmware(ar->testmode.utf); - ar->testmode.utf = NULL; + release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); + ar->testmode.utf_mode_fw.fw_file.firmware = NULL; err: mutex_unlock(&ar->conf_mutex); @@ -420,8 +439,8 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar) sizeof(ar->fw_features)); ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - release_firmware(ar->testmode.utf); - ar->testmode.utf = NULL; + release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); + ar->testmode.utf_mode_fw.fw_file.firmware = NULL; ar->state = ATH10K_STATE_OFF; } -- GitLab From 453173550256542c20b24a8d85b806941b77ac76 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:05 +0300 Subject: [PATCH 3707/9938] ath10k: move fw_version inside struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 13 +++++++++---- drivers/net/wireless/ath/ath10k/core.h | 3 ++- drivers/net/wireless/ath/ath10k/testmode.c | 12 ++++++------ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b2efece5b32d..015241aec608 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1039,15 +1039,15 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, switch (ie_id) { case ATH10K_FW_IE_FW_VERSION: - if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1) + if (ie_len > sizeof(fw_file->fw_version) - 1) break; - memcpy(ar->hw->wiphy->fw_version, data, ie_len); - ar->hw->wiphy->fw_version[ie_len] = '\0'; + memcpy(fw_file->fw_version, data, ie_len); + fw_file->fw_version[ie_len] = '\0'; ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw version %s\n", - ar->hw->wiphy->fw_version); + fw_file->fw_version); break; case ATH10K_FW_IE_TIMESTAMP: if (ie_len != sizeof(u32)) @@ -1866,6 +1866,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_power_down; } + BUILD_BUG_ON(sizeof(ar->hw->wiphy->fw_version) != + sizeof(ar->normal_mode_fw.fw_file.fw_version)); + memcpy(ar->hw->wiphy->fw_version, ar->normal_mode_fw.fw_file.fw_version, + sizeof(ar->hw->wiphy->fw_version)); + ath10k_debug_print_hwfw_info(ar); ret = ath10k_core_pre_cal_download(ar); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index b377fd42c0a3..432b1590f6e6 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -630,6 +630,8 @@ enum ath10k_tx_pause_reason { struct ath10k_fw_file { const struct firmware *firmware; + char fw_version[ETHTOOL_FWVERS_LEN]; + const void *firmware_data; size_t firmware_len; @@ -893,7 +895,6 @@ struct ath10k { struct { /* protected by conf_mutex */ struct ath10k_fw_components utf_mode_fw; - char utf_version[32]; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; enum ath10k_fw_wmi_op_version op_version; diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 480fad301fad..2c4a5d31cf0c 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -205,15 +205,15 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, switch (ie_id) { case ATH10K_FW_IE_FW_VERSION: - if (ie_len > sizeof(ar->testmode.utf_version) - 1) + if (ie_len > sizeof(fw_file->fw_version) - 1) break; - memcpy(ar->testmode.utf_version, data, ie_len); - ar->testmode.utf_version[ie_len] = '\0'; + memcpy(fw_file->fw_version, data, ie_len); + fw_file->fw_version[ie_len] = '\0'; ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw utf version %s\n", - ar->testmode.utf_version); + fw_file->fw_version); break; case ATH10K_FW_IE_TIMESTAMP: /* ignore timestamp, but don't warn about it either */ @@ -392,8 +392,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ar->state = ATH10K_STATE_UTF; - if (strlen(ar->testmode.utf_version) > 0) - ver = ar->testmode.utf_version; + if (strlen(ar->testmode.utf_mode_fw.fw_file.fw_version) > 0) + ver = ar->testmode.utf_mode_fw.fw_file.fw_version; else ver = "API 1"; -- GitLab From c4cdf753ed4287467248126a4fac072fbba53b31 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:18 +0300 Subject: [PATCH 3708/9938] ath10k: move fw_features to struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 28 ++++++++++++---------- drivers/net/wireless/ath/ath10k/core.h | 5 ++-- drivers/net/wireless/ath/ath10k/htt_rx.c | 2 +- drivers/net/wireless/ath/ath10k/htt_tx.c | 9 ++++--- drivers/net/wireless/ath/ath10k/mac.c | 14 ++++++----- drivers/net/wireless/ath/ath10k/testmode.c | 14 ----------- drivers/net/wireless/ath/ath10k/wmi.c | 5 ++-- drivers/net/wireless/ath/ath10k/wow.c | 7 +++--- 8 files changed, 39 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 015241aec608..71b8ca71d1da 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -261,7 +261,7 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar, int i; for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) { - if (test_bit(i, ar->fw_features)) { + if (test_bit(i, ar->normal_mode_fw.fw_file.fw_features)) { if (len > 0) len += scnprintf(buf + len, buf_len - len, ","); @@ -627,7 +627,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, - ar->fw_features)) && + ar->running_fw->fw_file.fw_features)) && result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; @@ -1074,13 +1074,13 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, ath10k_dbg(ar, ATH10K_DBG_BOOT, "Enabling feature bit: %i\n", i); - __set_bit(i, ar->fw_features); + __set_bit(i, fw_file->fw_features); } } ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "features", "", - ar->fw_features, - sizeof(ar->fw_features)); + ar->running_fw->fw_file.fw_features, + sizeof(fw_file->fw_features)); break; case ATH10K_FW_IE_FW_IMAGE: ath10k_dbg(ar, ATH10K_DBG_BOOT, @@ -1430,8 +1430,10 @@ static void ath10k_core_restart(struct work_struct *work) static int ath10k_core_init_firmware_features(struct ath10k *ar) { - if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) && - !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file; + + if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) && + !test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well"); return -EINVAL; } @@ -1450,7 +1452,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) break; case ATH10K_CRYPT_MODE_SW: if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT, - ar->fw_features)) { + fw_file->fw_features)) { ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware"); return -EINVAL; } @@ -1469,7 +1471,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) if (rawmode) { if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT, - ar->fw_features)) { + fw_file->fw_features)) { ath10k_err(ar, "rawmode = 1 requires support from firmware"); return -EINVAL; } @@ -1495,9 +1497,9 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) * ATH10K_FW_IE_WMI_OP_VERSION. */ if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) { - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, - ar->fw_features)) + fw_file->fw_features)) ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2; else ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; @@ -1553,7 +1555,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->max_spatial_stream = ar->hw_params.max_spatial_stream; if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, - ar->fw_features)) + fw_file->fw_features)) ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC; else ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC; @@ -1621,7 +1623,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, * to set the clock source once the target is initialized. */ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT, - ar->fw_features)) { + ar->running_fw->fw_file.fw_features)) { status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1); if (status) { ath10k_err(ar, "could not write to skip_clock_init: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 432b1590f6e6..18e21b4fe034 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -632,6 +632,8 @@ struct ath10k_fw_file { char fw_version[ETHTOOL_FWVERS_LEN]; + DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); + const void *firmware_data; size_t firmware_len; @@ -675,8 +677,6 @@ struct ath10k { /* protected by conf_mutex */ bool ani_enabled; - DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); - bool p2p; struct { @@ -895,7 +895,6 @@ struct ath10k { struct { /* protected by conf_mutex */ struct ath10k_fw_components utf_mode_fw; - DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; enum ath10k_fw_wmi_op_version op_version; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 9390897a00c6..5b777c24d2ba 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -966,7 +966,7 @@ static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar, int len = ieee80211_hdrlen(hdr->frame_control); if (!test_bit(ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING, - ar->fw_features)) + ar->running_fw->fw_file.fw_features)) len = round_up(len, 4); return len; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 9baa2e677f8a..6269c610b0a3 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -267,7 +267,8 @@ static void ath10k_htt_tx_free_txq(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; size_t size; - if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->running_fw->fw_file.fw_features)) return; size = sizeof(*htt->tx_q_state.vaddr); @@ -282,7 +283,8 @@ static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt) size_t size; int ret; - if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->running_fw->fw_file.fw_features)) return 0; htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS; @@ -513,7 +515,8 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) info |= SM(htt->tx_q_state.type, HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE); - if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->running_fw->fw_file.fw_features)) info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID; cfg = &cmd->frag_desc_bank_cfg; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 56abbf2f2a59..0fd0fc111c40 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1772,7 +1772,7 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) if (enable_ps && ath10k_mac_num_vifs_started(ar) > 1 && !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT, - ar->fw_features)) { + ar->running_fw->fw_file.fw_features)) { ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n", arvif->vdev_id); enable_ps = false; @@ -2060,7 +2060,8 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, } if (sta->mfp && - test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, ar->fw_features)) { + test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, + ar->running_fw->fw_file.fw_features)) { arg->peer_flags |= ar->wmi.peer_flags->pmf; } } @@ -3207,7 +3208,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar, */ if (ar->htt.target_version_major < 3 && (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) && - !test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, ar->fw_features)) + !test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, + ar->running_fw->fw_file.fw_features)) return ATH10K_HW_TXRX_MGMT; /* Workaround: @@ -3394,7 +3396,7 @@ ath10k_mac_tx_h_get_txpath(struct ath10k *ar, return ATH10K_MAC_TX_HTT; case ATH10K_HW_TXRX_MGMT: if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, - ar->fw_features)) + ar->running_fw->fw_file.fw_features)) return ATH10K_MAC_TX_WMI_MGMT; else if (ar->htt.target_version_major >= 3) return ATH10K_MAC_TX_HTT; @@ -4435,7 +4437,7 @@ static int ath10k_start(struct ieee80211_hw *hw) } if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA, - ar->fw_features)) { + ar->running_fw->fw_file.fw_features)) { ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1, WMI_CCA_DETECT_LEVEL_AUTO, WMI_CCA_DETECT_MARGIN_AUTO); @@ -7694,7 +7696,7 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask; ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask; - if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->normal_mode_fw.fw_file.fw_features)) ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE) | BIT(NL80211_IFTYPE_P2P_CLIENT) | diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 2c4a5d31cf0c..102539409f54 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -362,14 +362,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) spin_lock_bh(&ar->data_lock); ar->testmode.utf_monitor = true; spin_unlock_bh(&ar->data_lock); - BUILD_BUG_ON(sizeof(ar->fw_features) != - sizeof(ar->testmode.orig_fw_features)); - memcpy(ar->testmode.orig_fw_features, ar->fw_features, - sizeof(ar->fw_features)); ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - memset(ar->fw_features, 0, sizeof(ar->fw_features)); - ar->wmi.op_version = ar->testmode.op_version; ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", @@ -407,9 +401,6 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ath10k_hif_power_down(ar); err_fw_features: - /* return the original firmware features */ - memcpy(ar->fw_features, ar->testmode.orig_fw_features, - sizeof(ar->fw_features)); ar->wmi.op_version = ar->testmode.orig_wmi_op_version; release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); @@ -434,11 +425,6 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar) spin_unlock_bh(&ar->data_lock); - /* return the original firmware features */ - memcpy(ar->fw_features, ar->testmode.orig_fw_features, - sizeof(ar->fw_features)); - ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); ar->testmode.utf_mode_fw.fw_file.firmware = NULL; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 254844b37d92..d5279ce32974 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2149,7 +2149,8 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb, u32 msdu_len; u32 len; - if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) { + if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, + ar->running_fw->fw_file.fw_features)) { ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data; ev_hdr = &ev_v2->hdr.v1; pull_len = sizeof(*ev_v2); @@ -4634,7 +4635,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, - ar->fw_features)) + ar->running_fw->fw_file.fw_features)) ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC + ar->max_num_vdevs; else diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c index 8e02b381990f..77100d42f401 100644 --- a/drivers/net/wireless/ath/ath10k/wow.c +++ b/drivers/net/wireless/ath/ath10k/wow.c @@ -233,7 +233,7 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, - ar->fw_features))) { + ar->running_fw->fw_file.fw_features))) { ret = 1; goto exit; } @@ -285,7 +285,7 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw) mutex_lock(&ar->conf_mutex); if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, - ar->fw_features))) { + ar->running_fw->fw_file.fw_features))) { ret = 1; goto exit; } @@ -325,7 +325,8 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw) int ath10k_wow_init(struct ath10k *ar) { - if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, + ar->running_fw->fw_file.fw_features)) return 0; if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map))) -- GitLab From bf3c13ab49965f0517b579dc490d612d074d535a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:33 +0300 Subject: [PATCH 3709/9938] ath10k: move wmi_op_version to struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 20 ++++++++++---------- drivers/net/wireless/ath/ath10k/core.h | 5 ++--- drivers/net/wireless/ath/ath10k/debug.c | 2 +- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/testmode.c | 17 ++++++----------- drivers/net/wireless/ath/ath10k/wmi.c | 4 ++-- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 71b8ca71d1da..a7c99355a7c2 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1106,10 +1106,10 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, version = (__le32 *)data; - ar->wmi.op_version = le32_to_cpup(version); + fw_file->wmi_op_version = le32_to_cpup(version); ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n", - ar->wmi.op_version); + fw_file->wmi_op_version); break; case ATH10K_FW_IE_HTT_OP_VERSION: if (ie_len != sizeof(u32)) @@ -1438,9 +1438,9 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) return -EINVAL; } - if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) { + if (fw_file->wmi_op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) { ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n", - ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version); + ATH10K_FW_WMI_OP_VERSION_MAX, fw_file->wmi_op_version); return -EINVAL; } @@ -1496,19 +1496,19 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) /* Backwards compatibility for firmwares without * ATH10K_FW_IE_WMI_OP_VERSION. */ - if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) { + if (fw_file->wmi_op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) { if (test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features)) - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_2; else - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1; } else { - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_MAIN; } } - switch (ar->wmi.op_version) { + switch (fw_file->wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->max_num_peers = TARGET_NUM_PEERS; ar->max_num_stations = TARGET_NUM_STATIONS; @@ -1570,7 +1570,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) * ATH10K_FW_IE_HTT_OP_VERSION. */ if (ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) { - switch (ar->wmi.op_version) { + switch (fw_file->wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_MAIN; break; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 18e21b4fe034..7d709f848fac 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -139,7 +139,6 @@ struct ath10k_mem_chunk { }; struct ath10k_wmi { - enum ath10k_fw_wmi_op_version op_version; enum ath10k_htc_ep_id eid; struct completion service_ready; struct completion unified_ready; @@ -634,6 +633,8 @@ struct ath10k_fw_file { DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); + enum ath10k_fw_wmi_op_version wmi_op_version; + const void *firmware_data; size_t firmware_len; @@ -895,8 +896,6 @@ struct ath10k { struct { /* protected by conf_mutex */ struct ath10k_fw_components utf_mode_fw; - enum ath10k_fw_wmi_op_version orig_wmi_op_version; - enum ath10k_fw_wmi_op_version op_version; /* protected by data_lock */ bool utf_monitor; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 27787d23b2bd..8a63ce5c6e09 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -178,7 +178,7 @@ void ath10k_debug_print_boot_info(struct ath10k *ar) ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n", ar->htt.target_version_major, ar->htt.target_version_minor, - ar->wmi.op_version, + ar->normal_mode_fw.fw_file.wmi_op_version, ar->htt.op_version, ath10k_cal_mode_str(ar->cal_mode), ar->max_num_stations, diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0fd0fc111c40..5fb912acc0a8 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7786,7 +7786,7 @@ int ath10k_mac_register(struct ath10k *ar) */ ar->hw->offchannel_tx_hw_queue = IEEE80211_MAX_QUEUES - 1; - switch (ar->wmi.op_version) { + switch (ar->running_fw->fw_file.wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->hw->wiphy->iface_combinations = ath10k_if_comb; ar->hw->wiphy->n_iface_combinations = diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 102539409f54..3d4418969697 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -230,9 +230,9 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, if (ie_len != sizeof(u32)) break; version = (__le32 *)data; - ar->testmode.op_version = le32_to_cpup(version); + fw_file->wmi_op_version = le32_to_cpup(version); ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", - ar->testmode.op_version); + fw_file->wmi_op_version); break; default: ath10k_warn(ar, "Unknown testmode FW IE: %u\n", @@ -283,7 +283,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, * correct WMI interface. */ - ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1; fw_file->firmware_data = fw_file->firmware->data; fw_file->firmware_len = fw_file->firmware->size; @@ -363,17 +363,14 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ar->testmode.utf_monitor = true; spin_unlock_bh(&ar->data_lock); - ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - ar->wmi.op_version = ar->testmode.op_version; - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", - ar->wmi.op_version); + ar->testmode.utf_mode_fw.fw_file.wmi_op_version); ret = ath10k_hif_power_up(ar); if (ret) { ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret); ar->state = ATH10K_STATE_OFF; - goto err_fw_features; + goto err_release_utf_mode_fw; } ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF, @@ -400,9 +397,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) err_power_down: ath10k_hif_power_down(ar); -err_fw_features: - ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - +err_release_utf_mode_fw: release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); ar->testmode.utf_mode_fw.fw_file.firmware = NULL; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index d5279ce32974..a1afb2e2b05a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -7865,7 +7865,7 @@ static const struct wmi_ops wmi_10_4_ops = { int ath10k_wmi_attach(struct ath10k *ar) { - switch (ar->wmi.op_version) { + switch (ar->running_fw->fw_file.wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_10_4: ar->wmi.ops = &wmi_10_4_ops; ar->wmi.cmd = &wmi_10_4_cmd_map; @@ -7907,7 +7907,7 @@ int ath10k_wmi_attach(struct ath10k *ar) case ATH10K_FW_WMI_OP_VERSION_UNSET: case ATH10K_FW_WMI_OP_VERSION_MAX: ath10k_err(ar, "unsupported WMI op version: %d\n", - ar->wmi.op_version); + ar->running_fw->fw_file.wmi_op_version); return -EINVAL; } -- GitLab From 77561f9394f8553cce487b12b15b4879ecbaf6d7 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:47 +0300 Subject: [PATCH 3710/9938] ath10k: move htt_op_version to struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 12 ++++++------ drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/debug.c | 2 +- drivers/net/wireless/ath/ath10k/htt.c | 2 +- drivers/net/wireless/ath/ath10k/htt.h | 1 - drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/testmode.c | 1 + 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index a7c99355a7c2..4af01afdaf6c 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1117,10 +1117,10 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, version = (__le32 *)data; - ar->htt.op_version = le32_to_cpup(version); + fw_file->htt_op_version = le32_to_cpup(version); ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie htt op version %d\n", - ar->htt.op_version); + fw_file->htt_op_version); break; case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE: ath10k_dbg(ar, ATH10K_DBG_BOOT, @@ -1569,18 +1569,18 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) /* Backwards compatibility for firmwares without * ATH10K_FW_IE_HTT_OP_VERSION. */ - if (ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) { + if (fw_file->htt_op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) { switch (fw_file->wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: - ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_MAIN; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_MAIN; break; case ATH10K_FW_WMI_OP_VERSION_10_1: case ATH10K_FW_WMI_OP_VERSION_10_2: case ATH10K_FW_WMI_OP_VERSION_10_2_4: - ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_10_1; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1; break; case ATH10K_FW_WMI_OP_VERSION_TLV: - ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_TLV; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV; break; case ATH10K_FW_WMI_OP_VERSION_10_4: case ATH10K_FW_WMI_OP_VERSION_UNSET: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7d709f848fac..55a28c08e898 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -634,6 +634,7 @@ struct ath10k_fw_file { DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version wmi_op_version; + enum ath10k_fw_htt_op_version htt_op_version; const void *firmware_data; size_t firmware_len; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 8a63ce5c6e09..e2511550fbb8 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -179,7 +179,7 @@ void ath10k_debug_print_boot_info(struct ath10k *ar) ar->htt.target_version_major, ar->htt.target_version_minor, ar->normal_mode_fw.fw_file.wmi_op_version, - ar->htt.op_version, + ar->normal_mode_fw.fw_file.htt_op_version, ath10k_cal_mode_str(ar->cal_mode), ar->max_num_stations, test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags), diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index ee79512b1fcc..130cd9502021 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -183,7 +183,7 @@ int ath10k_htt_init(struct ath10k *ar) 8 + /* llc snap */ 2; /* ip4 dscp or ip6 priority */ - switch (ar->htt.op_version) { + switch (ar->running_fw->fw_file.htt_op_version) { case ATH10K_FW_HTT_OP_VERSION_10_4: ar->htt.t2h_msg_types = htt_10_4_t2h_msg_types; ar->htt.t2h_msg_types_max = HTT_10_4_T2H_NUM_MSGS; diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index ee7c8f8f8073..911c535d0863 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1562,7 +1562,6 @@ struct ath10k_htt { u8 target_version_major; u8 target_version_minor; struct completion target_version_received; - enum ath10k_fw_htt_op_version op_version; u8 max_num_amsdu; u8 max_num_ampdu; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 5fb912acc0a8..67cf004b685a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3359,7 +3359,7 @@ bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) */ return (ar->htt.target_version_major >= 3 && ar->htt.target_version_minor >= 4 && - ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV); + ar->running_fw->fw_file.htt_op_version == ATH10K_FW_HTT_OP_VERSION_TLV); } static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 3d4418969697..daf04d74c6d0 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -284,6 +284,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, */ fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1; fw_file->firmware_data = fw_file->firmware->data; fw_file->firmware_len = fw_file->firmware->size; -- GitLab From 9dfe240b4d684f17efa861e92e45dc949b0049ed Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:46:01 +0300 Subject: [PATCH 3711/9938] ath10k: switch testmode to use ath10k_core_fetch_firmware_api_n() Now that all firmware-N.bin related are within struct ath10k_fw_file we can switch to use ath10k_core_fetch_firmware_api_n() and delete almost identical ath10k_tm_fetch_utf_firmware_api_2(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 +- drivers/net/wireless/ath/ath10k/core.h | 2 + drivers/net/wireless/ath/ath10k/testmode.c | 124 +-------------------- 3 files changed, 6 insertions(+), 124 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 4af01afdaf6c..db9437a72ba4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -976,8 +976,8 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, - struct ath10k_fw_file *fw_file) +int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, + struct ath10k_fw_file *fw_file) { size_t magic_len, len, ie_len; int ie_id, i, index, bit, ret; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 55a28c08e898..f3553dc11c5d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -933,6 +933,8 @@ void ath10k_core_destroy(struct ath10k *ar); void ath10k_core_get_fw_features_str(struct ath10k *ar, char *buf, size_t max_len); +int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, + struct ath10k_fw_file *fw_file); int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, const struct ath10k_fw_components *fw_components); diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index daf04d74c6d0..120f4234d3b0 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -139,127 +139,6 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) return cfg80211_testmode_reply(skb); } -static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, - struct ath10k_fw_file *fw_file) -{ - size_t len, magic_len, ie_len; - struct ath10k_fw_ie *hdr; - char filename[100]; - __le32 *version; - const u8 *data; - int ie_id, ret; - - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); - - /* load utf firmware image */ - ret = request_firmware(&fw_file->firmware, filename, ar->dev); - if (ret) { - ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", - filename, ret); - return ret; - } - - data = fw_file->firmware->data; - len = fw_file->firmware->size; - - /* FIXME: call release_firmware() in error cases */ - - /* magic also includes the null byte, check that as well */ - magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; - - if (len < magic_len) { - ath10k_err(ar, "utf firmware file is too small to contain magic\n"); - ret = -EINVAL; - goto err; - } - - if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { - ath10k_err(ar, "invalid firmware magic\n"); - ret = -EINVAL; - goto err; - } - - /* jump over the padding */ - magic_len = ALIGN(magic_len, 4); - - len -= magic_len; - data += magic_len; - - /* loop elements */ - while (len > sizeof(struct ath10k_fw_ie)) { - hdr = (struct ath10k_fw_ie *)data; - - ie_id = le32_to_cpu(hdr->id); - ie_len = le32_to_cpu(hdr->len); - - len -= sizeof(*hdr); - data += sizeof(*hdr); - - if (len < ie_len) { - ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", - ie_id, len, ie_len); - ret = -EINVAL; - goto err; - } - - switch (ie_id) { - case ATH10K_FW_IE_FW_VERSION: - if (ie_len > sizeof(fw_file->fw_version) - 1) - break; - - memcpy(fw_file->fw_version, data, ie_len); - fw_file->fw_version[ie_len] = '\0'; - - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, - "testmode found fw utf version %s\n", - fw_file->fw_version); - break; - case ATH10K_FW_IE_TIMESTAMP: - /* ignore timestamp, but don't warn about it either */ - break; - case ATH10K_FW_IE_FW_IMAGE: - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, - "testmode found fw image ie (%zd B)\n", - ie_len); - - fw_file->firmware_data = data; - fw_file->firmware_len = ie_len; - break; - case ATH10K_FW_IE_WMI_OP_VERSION: - if (ie_len != sizeof(u32)) - break; - version = (__le32 *)data; - fw_file->wmi_op_version = le32_to_cpup(version); - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", - fw_file->wmi_op_version); - break; - default: - ath10k_warn(ar, "Unknown testmode FW IE: %u\n", - le32_to_cpu(hdr->id)); - break; - } - /* jump over the padding */ - ie_len = ALIGN(ie_len, 4); - - len -= ie_len; - data += ie_len; - } - - if (!fw_file->firmware_data || !fw_file->firmware_len) { - ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); - ret = -EINVAL; - goto err; - } - - return 0; - -err: - release_firmware(fw_file->firmware); - - return ret; -} - static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, struct ath10k_fw_file *fw_file) { @@ -296,7 +175,8 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar) struct ath10k_fw_components *utf_mode_fw; int ret; - ret = ath10k_tm_fetch_utf_firmware_api_2(ar, &ar->testmode.utf_mode_fw.fw_file); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_UTF_API2_FILE, + &ar->testmode.utf_mode_fw.fw_file); if (ret == 0) { ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); goto out; -- GitLab From 1fe63c9ca8913eb7af6c428cf81abad29e0bc9d6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:46:16 +0300 Subject: [PATCH 3712/9938] ath10k: remove enum ath10k_swap_code_seg_bin_type It's not needed for anything so just get rid of it. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 3 +-- drivers/net/wireless/ath/ath10k/swap.c | 22 ++++++---------------- drivers/net/wireless/ath/ath10k/swap.h | 9 +-------- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index db9437a72ba4..e94cb87380d2 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -647,8 +647,7 @@ static int ath10k_download_fw(struct ath10k *ar) data = ar->running_fw->fw_file.firmware_data; data_len = ar->running_fw->fw_file.firmware_len; - ret = ath10k_swap_code_seg_configure(ar, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + ret = ath10k_swap_code_seg_configure(ar); if (ret) { ath10k_err(ar, "failed to configure fw code swap: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/swap.c b/drivers/net/wireless/ath/ath10k/swap.c index 47d449bac86d..0c5f5863dac8 100644 --- a/drivers/net/wireless/ath/ath10k/swap.c +++ b/drivers/net/wireless/ath/ath10k/swap.c @@ -134,27 +134,17 @@ ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len) return seg_info; } -int ath10k_swap_code_seg_configure(struct ath10k *ar, - enum ath10k_swap_code_seg_bin_type type) +int ath10k_swap_code_seg_configure(struct ath10k *ar) { int ret; struct ath10k_swap_code_seg_info *seg_info = NULL; - switch (type) { - case ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW: - if (!ar->swap.firmware_swap_code_seg_info) - return 0; - - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n"); - seg_info = ar->swap.firmware_swap_code_seg_info; - break; - default: - case ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP: - case ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF: - ath10k_warn(ar, "ignoring unknown code swap binary type %d\n", - type); + if (!ar->swap.firmware_swap_code_seg_info) return 0; - } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n"); + + seg_info = ar->swap.firmware_swap_code_seg_info; ret = ath10k_bmi_write_memory(ar, seg_info->target_addr, &seg_info->seg_hw_info, diff --git a/drivers/net/wireless/ath/ath10k/swap.h b/drivers/net/wireless/ath/ath10k/swap.h index 5c89952dd20f..36991c7b07a0 100644 --- a/drivers/net/wireless/ath/ath10k/swap.h +++ b/drivers/net/wireless/ath/ath10k/swap.h @@ -39,12 +39,6 @@ union ath10k_swap_code_seg_item { struct ath10k_swap_code_seg_tail tail; } __packed; -enum ath10k_swap_code_seg_bin_type { - ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF, -}; - struct ath10k_swap_code_seg_hw_info { /* Swap binary image size */ __le32 swap_size; @@ -64,8 +58,7 @@ struct ath10k_swap_code_seg_info { dma_addr_t paddr[ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED]; }; -int ath10k_swap_code_seg_configure(struct ath10k *ar, - enum ath10k_swap_code_seg_bin_type type); +int ath10k_swap_code_seg_configure(struct ath10k *ar); void ath10k_swap_code_seg_release(struct ath10k *ar); int ath10k_swap_code_seg_init(struct ath10k *ar); -- GitLab From 86b2749ba79e78130dd9f678aa52d57992fbdf1c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 15 Apr 2016 12:35:31 -0300 Subject: [PATCH 3713/9938] [media] vivid: fix smatch errors The smatch utility got really confused about the grp % 22 code. Rewrote it so it now understands that there really isn't a buffer overwrite. vivid-rds-gen.c:82 vivid_rds_generate() error: buffer overflow 'rds->psname' 9 <= 43 vivid-rds-gen.c:83 vivid_rds_generate() error: buffer overflow 'rds->psname' 9 <= 42 vivid-rds-gen.c:89 vivid_rds_generate() error: buffer overflow 'rds->radiotext' 65 <= 84 vivid-rds-gen.c:90 vivid_rds_generate() error: buffer overflow 'rds->radiotext' 65 <= 85 vivid-rds-gen.c:92 vivid_rds_generate() error: buffer overflow 'rds->radiotext' 65 <= 86 vivid-rds-gen.c:93 vivid_rds_generate() error: buffer overflow 'rds->radiotext' 65 <= 87 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-rds-gen.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-rds-gen.c b/drivers/media/platform/vivid/vivid-rds-gen.c index c382343fdb66..53c7777dc001 100644 --- a/drivers/media/platform/vivid/vivid-rds-gen.c +++ b/drivers/media/platform/vivid/vivid-rds-gen.c @@ -55,6 +55,7 @@ void vivid_rds_generate(struct vivid_rds_gen *rds) { struct v4l2_rds_data *data = rds->data; unsigned grp; + unsigned idx; struct tm tm; unsigned date; unsigned time; @@ -73,24 +74,26 @@ void vivid_rds_generate(struct vivid_rds_gen *rds) case 0 ... 3: case 22 ... 25: case 44 ... 47: /* Group 0B */ + idx = (grp % 22) % 4; data[1].lsb |= (rds->ta << 4) | (rds->ms << 3); - data[1].lsb |= vivid_get_di(rds, grp % 22); + data[1].lsb |= vivid_get_di(rds, idx); data[1].msb |= 1 << 3; data[2].lsb = rds->picode & 0xff; data[2].msb = rds->picode >> 8; data[2].block = V4L2_RDS_BLOCK_C_ALT | (V4L2_RDS_BLOCK_C_ALT << 3); - data[3].lsb = rds->psname[2 * (grp % 22) + 1]; - data[3].msb = rds->psname[2 * (grp % 22)]; + data[3].lsb = rds->psname[2 * idx + 1]; + data[3].msb = rds->psname[2 * idx]; break; case 4 ... 19: case 26 ... 41: /* Group 2A */ - data[1].lsb |= (grp - 4) % 22; + idx = ((grp - 4) % 22) % 16; + data[1].lsb |= idx; data[1].msb |= 4 << 3; - data[2].msb = rds->radiotext[4 * ((grp - 4) % 22)]; - data[2].lsb = rds->radiotext[4 * ((grp - 4) % 22) + 1]; + data[2].msb = rds->radiotext[4 * idx]; + data[2].lsb = rds->radiotext[4 * idx + 1]; data[2].block = V4L2_RDS_BLOCK_C | (V4L2_RDS_BLOCK_C << 3); - data[3].msb = rds->radiotext[4 * ((grp - 4) % 22) + 2]; - data[3].lsb = rds->radiotext[4 * ((grp - 4) % 22) + 3]; + data[3].msb = rds->radiotext[4 * idx + 2]; + data[3].lsb = rds->radiotext[4 * idx + 3]; break; case 56: /* -- GitLab From 622202938952e43471c31835906c8a4f4e16f050 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 15 Apr 2016 12:35:32 -0300 Subject: [PATCH 3714/9938] [media] pvrusb2: fix smatch errors These are false positives, but still easy to fix. pvrusb2-hdw.c:3676 pvr2_send_request_ex() error: we previously assumed 'write_data' could be null (see line 3648) pvrusb2-hdw.c:3829 pvr2_send_request_ex() error: we previously assumed 'read_data' could be null (see line 3649) Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 1a093e5953fd..83e9a3eb3859 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -3672,11 +3672,10 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, hdw->cmd_debug_state = 1; - if (write_len) { + if (write_len && write_data) hdw->cmd_debug_code = ((unsigned char *)write_data)[0]; - } else { + else hdw->cmd_debug_code = 0; - } hdw->cmd_debug_write_len = write_len; hdw->cmd_debug_read_len = read_len; @@ -3688,7 +3687,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, setup_timer(&timer, pvr2_ctl_timeout, (unsigned long)hdw); timer.expires = jiffies + timeout; - if (write_len) { + if (write_len && write_data) { hdw->cmd_debug_state = 2; /* Transfer write data to internal buffer */ for (idx = 0; idx < write_len; idx++) { @@ -3795,7 +3794,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, goto done; } } - if (read_len) { + if (read_len && read_data) { /* Validate results of read request */ if ((hdw->ctl_read_urb->status != 0) && (hdw->ctl_read_urb->status != -ENOENT) && -- GitLab From 5848adbe43034c8a1a378f9fed9afe501d9a4988 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 15 Apr 2016 12:35:33 -0300 Subject: [PATCH 3715/9938] [media] dib0090: fix smatch error Fix this smatch error: dib0090.c:1124 dib0090_pwm_gain_reset() error: we previously assumed 'state->rf_ramp' could be null (see line 1086) Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/dib0090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c index dc2d41e144fd..d879dc0607f4 100644 --- a/drivers/media/dvb-frontends/dib0090.c +++ b/drivers/media/dvb-frontends/dib0090.c @@ -1121,7 +1121,7 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe) (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", state->identity.version & 0x1f); - if (rf_ramp && ((state->rf_ramp[0] == 0) || + if (rf_ramp && ((state->rf_ramp && state->rf_ramp[0] == 0) || (state->current_band == BAND_CBAND && (state->identity.version & 0x1f) <= P1D_E_F))) { dprintk("DE-Engage mux for direct gain reg control"); -- GitLab From 72777724881f90c6efa027cc0dde9466371d740c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2016 06:59:02 -0300 Subject: [PATCH 3716/9938] [media] tc358743: zero the reserved array v4l2-compliance complained about this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 972e0d47259d..73e0cef0ea61 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1551,6 +1551,8 @@ static int tc358743_g_edid(struct v4l2_subdev *sd, { struct tc358743_state *state = to_state(sd); + memset(edid->reserved, 0, sizeof(edid->reserved)); + if (edid->pad != 0) return -EINVAL; @@ -1585,6 +1587,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", __func__, edid->pad, edid->start_block, edid->blocks); + memset(edid->reserved, 0, sizeof(edid->reserved)); + if (edid->pad != 0) return -EINVAL; -- GitLab From 0be67c40d4e8c5b3d96581680fa797f28a3025ec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2016 07:30:27 -0300 Subject: [PATCH 3717/9938] [media] vidioc-g-edid.xml: be explicit about zeroing the reserved array The G/S_EDID documentation did not explicitly state that the reserved array should be zeroed by the application. Also add the missing VIDIOC_SUBDEV_G/S_EDID ioctl names to the header. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-g-edid.xml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml index 2702536bbc7c..b7602d30f596 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml @@ -1,6 +1,6 @@ - ioctl VIDIOC_G_EDID, VIDIOC_S_EDID + ioctl VIDIOC_G_EDID, VIDIOC_S_EDID, VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID &manvol; @@ -71,7 +71,8 @@ To get the EDID data the application has to fill in the pad, start_block, blocks and edid - fields and call VIDIOC_G_EDID. The current EDID from block + fields, zero the reserved array and call + VIDIOC_G_EDID. The current EDID from block start_block and of size blocks will be placed in the memory edid points to. The edid pointer must point to memory at least blocks * 128 bytes @@ -92,8 +93,9 @@ the driver will set blocks to 0 and it returns 0. To set the EDID blocks of a receiver the application has to fill in the pad, - blocks and edid fields and set - start_block to 0. It is not possible to set part of an EDID, + blocks and edid fields, set + start_block to 0 and zero the reserved array. + It is not possible to set part of an EDID, it is always all or nothing. Setting the EDID data is only valid for receivers as it makes no sense for a transmitter. -- GitLab From 0c53fee973a9adfa4ad21433d397adae12b2120b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2016 07:30:28 -0300 Subject: [PATCH 3718/9938] [media] vidioc-enum-dv-timings.xml: explicitly state that pad and reserved should be zeroed The ENUM_DV_TIMINGS documentation did not clearly state that the pad and reserved fields should be zeroed (pad only when used with a video device node). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml index 6e3cadd4e1f9..70ca76d1e6d2 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml @@ -61,8 +61,9 @@ of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also sup standards or even custom timings that are not in this list. To query the available timings, applications initialize the -index field and zero the reserved array of &v4l2-enum-dv-timings; -and call the VIDIOC_ENUM_DV_TIMINGS ioctl on a video node with a +index field, set the pad field to 0, +zero the reserved array of &v4l2-enum-dv-timings; and call the +VIDIOC_ENUM_DV_TIMINGS ioctl on a video node with a pointer to this structure. Drivers fill the rest of the structure or return an &EINVAL; when the index is out of bounds. To enumerate all supported DV timings, applications shall begin at index zero, incrementing by one until the -- GitLab From c5c631416789004e7205a56ab1aaab2b3a011b1b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2016 07:30:29 -0300 Subject: [PATCH 3719/9938] [media] vidioc-dv-timings-cap.xml: explicitly state that pad and reserved should be zeroed The DV_TIMINGS_CAP documentation didn't state clearly that the pad and reserved fields should be zeroed by the application. For subdev pad can be other values as well. It also mistakenly said that only drivers would have to zero the reserved field, that's not correct. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-dv-timings-cap.xml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml index a2017bfcaed2..b6f47a6b14d5 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml @@ -55,8 +55,9 @@ interface and may change in the future. - To query the capabilities of the DV receiver/transmitter applications -can call the VIDIOC_DV_TIMINGS_CAP ioctl on a video node + To query the capabilities of the DV receiver/transmitter applications initialize the +pad field to 0, zero the reserved array of &v4l2-dv-timings-cap; +and call the VIDIOC_DV_TIMINGS_CAP ioctl on a video node and the driver will fill in the structure. Note that drivers may return different values after switching the video input or output. @@ -65,8 +66,8 @@ queried by calling the VIDIOC_SUBDEV_DV_TIMINGS_CAP ioctl directly on a subdevice node. The capabilities are specific to inputs (for DV receivers) or outputs (for DV transmitters), applications must specify the desired pad number in the &v4l2-dv-timings-cap; pad -field. Attempts to query capabilities on a pad that doesn't support them will -return an &EINVAL;. +field and zero the reserved array. Attempts to query +capabilities on a pad that doesn't support them will return an &EINVAL;. struct <structname>v4l2_bt_timings_cap</structname> @@ -145,7 +146,8 @@ return an &EINVAL;. __u32 reserved[2] - Reserved for future extensions. Drivers must set the array to zero. + Reserved for future extensions. Drivers and applications must + set the array to zero. union -- GitLab From 314f1dc140844a73034e285ddac92b9e1ffecb5b Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 11:32:45 +0300 Subject: [PATCH 3720/9938] iommu/vt-d: refactoring of deferred flush entries Currently, deferred flushes' info is striped between several lists in the flush tables. Instead, move all information about a specific flush to a single entry in this table. This patch does not introduce any functional change. Signed-off-by: Omer Peleg [mad@cs.technion.ac.il: rebased and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 48 ++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index e1852e845d21..ec562078247f 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -458,15 +458,19 @@ static void flush_unmaps_timeout(unsigned long data); static DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0); +struct deferred_flush_entry { + struct iova *iova; + struct dmar_domain *domain; + struct page *freelist; +}; + #define HIGH_WATER_MARK 250 -struct deferred_flush_tables { +struct deferred_flush_table { int next; - struct iova *iova[HIGH_WATER_MARK]; - struct dmar_domain *domain[HIGH_WATER_MARK]; - struct page *freelist[HIGH_WATER_MARK]; + struct deferred_flush_entry entries[HIGH_WATER_MARK]; }; -static struct deferred_flush_tables *deferred_flush; +static struct deferred_flush_table *deferred_flush; /* bitmap for indexing intel_iommus */ static int g_num_of_iommus; @@ -3111,7 +3115,7 @@ static int __init init_dmars(void) } deferred_flush = kzalloc(g_num_of_iommus * - sizeof(struct deferred_flush_tables), GFP_KERNEL); + sizeof(struct deferred_flush_table), GFP_KERNEL); if (!deferred_flush) { ret = -ENOMEM; goto free_g_iommus; @@ -3518,22 +3522,25 @@ static void flush_unmaps(void) DMA_TLB_GLOBAL_FLUSH); for (j = 0; j < deferred_flush[i].next; j++) { unsigned long mask; - struct iova *iova = deferred_flush[i].iova[j]; - struct dmar_domain *domain = deferred_flush[i].domain[j]; + struct deferred_flush_entry *entry = + &deferred_flush->entries[j]; + struct iova *iova = entry->iova; + struct dmar_domain *domain = entry->domain; + struct page *freelist = entry->freelist; /* On real hardware multiple invalidations are expensive */ if (cap_caching_mode(iommu->cap)) iommu_flush_iotlb_psi(iommu, domain, iova->pfn_lo, iova_size(iova), - !deferred_flush[i].freelist[j], 0); + !freelist, 0); else { mask = ilog2(mm_to_dma_pfn(iova_size(iova))); - iommu_flush_dev_iotlb(deferred_flush[i].domain[j], + iommu_flush_dev_iotlb(domain, (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); } - __free_iova(&deferred_flush[i].domain[j]->iovad, iova); - if (deferred_flush[i].freelist[j]) - dma_free_pagelist(deferred_flush[i].freelist[j]); + __free_iova(&domain->iovad, iova); + if (freelist) + dma_free_pagelist(freelist); } deferred_flush[i].next = 0; } @@ -3553,8 +3560,9 @@ static void flush_unmaps_timeout(unsigned long data) static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist) { unsigned long flags; - int next, iommu_id; + int entry_id, iommu_id; struct intel_iommu *iommu; + struct deferred_flush_entry *entry; spin_lock_irqsave(&async_umap_flush_lock, flags); if (list_size == HIGH_WATER_MARK) @@ -3563,11 +3571,13 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *f iommu = domain_get_iommu(dom); iommu_id = iommu->seq_id; - next = deferred_flush[iommu_id].next; - deferred_flush[iommu_id].domain[next] = dom; - deferred_flush[iommu_id].iova[next] = iova; - deferred_flush[iommu_id].freelist[next] = freelist; - deferred_flush[iommu_id].next++; + entry_id = deferred_flush[iommu_id].next; + ++(deferred_flush[iommu_id].next); + + entry = &deferred_flush[iommu_id].entries[entry_id]; + entry->domain = dom; + entry->iova = iova; + entry->freelist = freelist; if (!timer_on) { mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10)); -- GitLab From aa4732406e1290dd18a8d2078977996c152a4be7 Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 11:33:02 +0300 Subject: [PATCH 3721/9938] iommu/vt-d: per-cpu deferred invalidation queues The IOMMU's IOTLB invalidation is a costly process. When iommu mode is not set to "strict", it is done asynchronously. Current code amortizes the cost of invalidating IOTLB entries by batching all the invalidations in the system and performing a single global invalidation instead. The code queues pending invalidations in a global queue that is accessed under the global "async_umap_flush_lock" spinlock, which can result is significant spinlock contention. This patch splits this deferred queue into multiple per-cpu deferred queues, and thus gets rid of the "async_umap_flush_lock" and its contention. To keep existing deferred invalidation behavior, it still invalidates the pending invalidations of all CPUs whenever a CPU reaches its watermark or a timeout occurs. Signed-off-by: Omer Peleg [mad@cs.technion.ac.il: rebased, cleaned up and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 133 +++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 41 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index ec562078247f..a64b6f3b9a66 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -456,8 +457,6 @@ static LIST_HEAD(dmar_rmrr_units); static void flush_unmaps_timeout(unsigned long data); -static DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0); - struct deferred_flush_entry { struct iova *iova; struct dmar_domain *domain; @@ -470,17 +469,19 @@ struct deferred_flush_table { struct deferred_flush_entry entries[HIGH_WATER_MARK]; }; -static struct deferred_flush_table *deferred_flush; +struct deferred_flush_data { + spinlock_t lock; + int timer_on; + struct timer_list timer; + long size; + struct deferred_flush_table *tables; +}; + +DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush); /* bitmap for indexing intel_iommus */ static int g_num_of_iommus; -static DEFINE_SPINLOCK(async_umap_flush_lock); -static LIST_HEAD(unmaps_to_do); - -static int timer_on; -static long list_size; - static void domain_exit(struct dmar_domain *domain); static void domain_remove_dev_info(struct dmar_domain *domain); static void dmar_remove_one_dev_info(struct dmar_domain *domain, @@ -1922,8 +1923,12 @@ static void domain_exit(struct dmar_domain *domain) return; /* Flush any lazy unmaps that may reference this domain */ - if (!intel_iommu_strict) - flush_unmaps_timeout(0); + if (!intel_iommu_strict) { + int cpu; + + for_each_possible_cpu(cpu) + flush_unmaps_timeout(cpu); + } /* Remove associated devices and clear attached or cached domains */ rcu_read_lock(); @@ -3081,7 +3086,7 @@ static int __init init_dmars(void) bool copied_tables = false; struct device *dev; struct intel_iommu *iommu; - int i, ret; + int i, ret, cpu; /* * for each drhd @@ -3114,11 +3119,20 @@ static int __init init_dmars(void) goto error; } - deferred_flush = kzalloc(g_num_of_iommus * - sizeof(struct deferred_flush_table), GFP_KERNEL); - if (!deferred_flush) { - ret = -ENOMEM; - goto free_g_iommus; + for_each_possible_cpu(cpu) { + struct deferred_flush_data *dfd = per_cpu_ptr(&deferred_flush, + cpu); + + dfd->tables = kzalloc(g_num_of_iommus * + sizeof(struct deferred_flush_table), + GFP_KERNEL); + if (!dfd->tables) { + ret = -ENOMEM; + goto free_g_iommus; + } + + spin_lock_init(&dfd->lock); + setup_timer(&dfd->timer, flush_unmaps_timeout, cpu); } for_each_active_iommu(iommu, drhd) { @@ -3295,8 +3309,9 @@ static int __init init_dmars(void) disable_dmar_iommu(iommu); free_dmar_iommu(iommu); } - kfree(deferred_flush); free_g_iommus: + for_each_possible_cpu(cpu) + kfree(per_cpu_ptr(&deferred_flush, cpu)->tables); kfree(g_iommus); error: return ret; @@ -3501,29 +3516,31 @@ static dma_addr_t intel_map_page(struct device *dev, struct page *page, dir, *dev->dma_mask); } -static void flush_unmaps(void) +static void flush_unmaps(struct deferred_flush_data *flush_data) { int i, j; - timer_on = 0; + flush_data->timer_on = 0; /* just flush them all */ for (i = 0; i < g_num_of_iommus; i++) { struct intel_iommu *iommu = g_iommus[i]; + struct deferred_flush_table *flush_table = + &flush_data->tables[i]; if (!iommu) continue; - if (!deferred_flush[i].next) + if (!flush_table->next) continue; /* In caching mode, global flushes turn emulation expensive */ if (!cap_caching_mode(iommu->cap)) iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH); - for (j = 0; j < deferred_flush[i].next; j++) { + for (j = 0; j < flush_table->next; j++) { unsigned long mask; struct deferred_flush_entry *entry = - &deferred_flush->entries[j]; + &flush_table->entries[j]; struct iova *iova = entry->iova; struct dmar_domain *domain = entry->domain; struct page *freelist = entry->freelist; @@ -3542,19 +3559,20 @@ static void flush_unmaps(void) if (freelist) dma_free_pagelist(freelist); } - deferred_flush[i].next = 0; + flush_table->next = 0; } - list_size = 0; + flush_data->size = 0; } -static void flush_unmaps_timeout(unsigned long data) +static void flush_unmaps_timeout(unsigned long cpuid) { + struct deferred_flush_data *flush_data = per_cpu_ptr(&deferred_flush, cpuid); unsigned long flags; - spin_lock_irqsave(&async_umap_flush_lock, flags); - flush_unmaps(); - spin_unlock_irqrestore(&async_umap_flush_lock, flags); + spin_lock_irqsave(&flush_data->lock, flags); + flush_unmaps(flush_data); + spin_unlock_irqrestore(&flush_data->lock, flags); } static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist) @@ -3563,28 +3581,44 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *f int entry_id, iommu_id; struct intel_iommu *iommu; struct deferred_flush_entry *entry; + struct deferred_flush_data *flush_data; + unsigned int cpuid; - spin_lock_irqsave(&async_umap_flush_lock, flags); - if (list_size == HIGH_WATER_MARK) - flush_unmaps(); + cpuid = get_cpu(); + flush_data = per_cpu_ptr(&deferred_flush, cpuid); + + /* Flush all CPUs' entries to avoid deferring too much. If + * this becomes a bottleneck, can just flush us, and rely on + * flush timer for the rest. + */ + if (flush_data->size == HIGH_WATER_MARK) { + int cpu; + + for_each_online_cpu(cpu) + flush_unmaps_timeout(cpu); + } + + spin_lock_irqsave(&flush_data->lock, flags); iommu = domain_get_iommu(dom); iommu_id = iommu->seq_id; - entry_id = deferred_flush[iommu_id].next; - ++(deferred_flush[iommu_id].next); + entry_id = flush_data->tables[iommu_id].next; + ++(flush_data->tables[iommu_id].next); - entry = &deferred_flush[iommu_id].entries[entry_id]; + entry = &flush_data->tables[iommu_id].entries[entry_id]; entry->domain = dom; entry->iova = iova; entry->freelist = freelist; - if (!timer_on) { - mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10)); - timer_on = 1; + if (!flush_data->timer_on) { + mod_timer(&flush_data->timer, jiffies + msecs_to_jiffies(10)); + flush_data->timer_on = 1; } - list_size++; - spin_unlock_irqrestore(&async_umap_flush_lock, flags); + flush_data->size++; + spin_unlock_irqrestore(&flush_data->lock, flags); + + put_cpu(); } static void intel_unmap(struct device *dev, dma_addr_t dev_addr) @@ -4508,6 +4542,23 @@ static struct notifier_block intel_iommu_memory_nb = { .priority = 0 }; +static int intel_iommu_cpu_notifier(struct notifier_block *nfb, + unsigned long action, void *v) +{ + unsigned int cpu = (unsigned long)v; + + switch (action) { + case CPU_DEAD: + case CPU_DEAD_FROZEN: + flush_unmaps_timeout(cpu); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block intel_iommu_cpu_nb = { + .notifier_call = intel_iommu_cpu_notifier, +}; static ssize_t intel_iommu_show_version(struct device *dev, struct device_attribute *attr, @@ -4641,7 +4692,6 @@ int __init intel_iommu_init(void) up_write(&dmar_global_lock); pr_info("Intel(R) Virtualization Technology for Directed I/O\n"); - init_timer(&unmap_timer); #ifdef CONFIG_SWIOTLB swiotlb = 0; #endif @@ -4658,6 +4708,7 @@ int __init intel_iommu_init(void) bus_register_notifier(&pci_bus_type, &device_nb); if (si_domain && !hw_pass_through) register_memory_notifier(&intel_iommu_memory_nb); + register_hotcpu_notifier(&intel_iommu_cpu_nb); intel_iommu_enabled = 1; -- GitLab From b05a4fa66a8d4589ba9f027db11d383250a4b774 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Sun, 27 Mar 2016 18:15:14 -0300 Subject: [PATCH 3722/9938] [media] Staging: media: bcm2048: defined region_configs[] array as const array This patch defines region_configs[] array as const array since it is not changed anywhere in code. Signed-off-by: Claudiu Beznea Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/bcm2048/radio-bcm2048.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index abf330f92c0b..8dade197f053 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -308,7 +308,7 @@ module_param(radio_nr, int, 0); MODULE_PARM_DESC(radio_nr, "Minor number for radio device (-1 ==> auto assign)"); -static struct region_info region_configs[] = { +static const struct region_info region_configs[] = { /* USA */ { .channel_spacing = 20, -- GitLab From f5c0c08b1e0976cb493d503108f1b897ce58bc5d Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 11:33:11 +0300 Subject: [PATCH 3723/9938] iommu/vt-d: correct flush_unmaps pfn usage Change flush_unmaps() to correctly pass iommu_flush_iotlb_psi() dma addresses. (x86_64 mm and dma have the same size for pages at the moment, but this usage improves consistency.) Signed-off-by: Omer Peleg [mad@cs.technion.ac.il: rebased and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a64b6f3b9a66..6aacfa4eee2a 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3548,7 +3548,8 @@ static void flush_unmaps(struct deferred_flush_data *flush_data) /* On real hardware multiple invalidations are expensive */ if (cap_caching_mode(iommu->cap)) iommu_flush_iotlb_psi(iommu, domain, - iova->pfn_lo, iova_size(iova), + mm_to_dma_pfn(iova->pfn_lo), + mm_to_dma_pfn(iova_size(iova)), !freelist, 0); else { mask = ilog2(mm_to_dma_pfn(iova_size(iova))); -- GitLab From 769530e4ba4898748a293592f0920275b40cbb93 Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 11:33:25 +0300 Subject: [PATCH 3724/9938] iommu/vt-d: only unmap mapped entries Current unmap implementation unmaps the entire area covered by the IOVA range, which is a power-of-2 aligned region. The corresponding map, however, only maps those pages originally mapped by the user. This discrepancy can lead to unmapping of already unmapped entries, which is unneeded work. With this patch, only mapped pages are unmapped. This is also a baseline for a map/unmap implementation based on IOVAs and not iova structures, which will allow caching. Signed-off-by: Omer Peleg [mad@cs.technion.ac.il: rebased and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 6aacfa4eee2a..63b8c026ef9c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -459,6 +459,7 @@ static void flush_unmaps_timeout(unsigned long data); struct deferred_flush_entry { struct iova *iova; + unsigned long nrpages; struct dmar_domain *domain; struct page *freelist; }; @@ -3542,6 +3543,7 @@ static void flush_unmaps(struct deferred_flush_data *flush_data) struct deferred_flush_entry *entry = &flush_table->entries[j]; struct iova *iova = entry->iova; + unsigned long nrpages = entry->nrpages; struct dmar_domain *domain = entry->domain; struct page *freelist = entry->freelist; @@ -3549,10 +3551,9 @@ static void flush_unmaps(struct deferred_flush_data *flush_data) if (cap_caching_mode(iommu->cap)) iommu_flush_iotlb_psi(iommu, domain, mm_to_dma_pfn(iova->pfn_lo), - mm_to_dma_pfn(iova_size(iova)), - !freelist, 0); + nrpages, !freelist, 0); else { - mask = ilog2(mm_to_dma_pfn(iova_size(iova))); + mask = ilog2(nrpages); iommu_flush_dev_iotlb(domain, (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); } @@ -3576,7 +3577,8 @@ static void flush_unmaps_timeout(unsigned long cpuid) spin_unlock_irqrestore(&flush_data->lock, flags); } -static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *freelist) +static void add_unmap(struct dmar_domain *dom, struct iova *iova, + unsigned long nrpages, struct page *freelist) { unsigned long flags; int entry_id, iommu_id; @@ -3610,6 +3612,7 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *f entry = &flush_data->tables[iommu_id].entries[entry_id]; entry->domain = dom; entry->iova = iova; + entry->nrpages = nrpages; entry->freelist = freelist; if (!flush_data->timer_on) { @@ -3622,10 +3625,11 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *f put_cpu(); } -static void intel_unmap(struct device *dev, dma_addr_t dev_addr) +static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) { struct dmar_domain *domain; unsigned long start_pfn, last_pfn; + unsigned long nrpages; struct iova *iova; struct intel_iommu *iommu; struct page *freelist; @@ -3643,8 +3647,9 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr) (unsigned long long)dev_addr)) return; + nrpages = aligned_nrpages(dev_addr, size); start_pfn = mm_to_dma_pfn(iova->pfn_lo); - last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; + last_pfn = start_pfn + nrpages - 1; pr_debug("Device %s unmapping: pfn %lx-%lx\n", dev_name(dev), start_pfn, last_pfn); @@ -3653,12 +3658,12 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr) if (intel_iommu_strict) { iommu_flush_iotlb_psi(iommu, domain, start_pfn, - last_pfn - start_pfn + 1, !freelist, 0); + nrpages, !freelist, 0); /* free iova */ __free_iova(&domain->iovad, iova); dma_free_pagelist(freelist); } else { - add_unmap(domain, iova, freelist); + add_unmap(domain, iova, nrpages, freelist); /* * queue up the release of the unmap to save the 1/6th of the * cpu used up by the iotlb flush operation... @@ -3670,7 +3675,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - intel_unmap(dev, dev_addr); + intel_unmap(dev, dev_addr, size); } static void *intel_alloc_coherent(struct device *dev, size_t size, @@ -3729,7 +3734,7 @@ static void intel_free_coherent(struct device *dev, size_t size, void *vaddr, size = PAGE_ALIGN(size); order = get_order(size); - intel_unmap(dev, dma_handle); + intel_unmap(dev, dma_handle, size); if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) __free_pages(page, order); } @@ -3738,7 +3743,16 @@ static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction dir, struct dma_attrs *attrs) { - intel_unmap(dev, sglist[0].dma_address); + dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK; + unsigned long nrpages = 0; + struct scatterlist *sg; + int i; + + for_each_sg(sglist, sg, nelems, i) { + nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg)); + } + + intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT); } static int intel_nontranslate_map_sg(struct device *hddev, -- GitLab From d0fadc869349e0469abc80109d4251be432736bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sat, 2 Apr 2016 14:42:18 -0300 Subject: [PATCH 3725/9938] [media] adv7180: Add g_std operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support to get the standard to the adv7180 driver. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index ff57c1dcb8af..d680d7656e2f 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -434,6 +434,15 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) return ret; } +static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) +{ + struct adv7180_state *state = to_state(sd); + + *norm = state->curr_norm; + + return 0; +} + static int adv7180_set_power(struct adv7180_state *state, bool on) { u8 val; @@ -719,6 +728,7 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops adv7180_video_ops = { .s_std = adv7180_s_std, + .g_std = adv7180_g_std, .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, .s_routing = adv7180_s_routing, -- GitLab From 0824c5920b16fe11034f3b5d2d48456d282d83f9 Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 19:03:35 +0300 Subject: [PATCH 3726/9938] iommu/vt-d: avoid dev iotlb logic for domains with no dev iotlbs This patch avoids taking the device_domain_lock in iommu_flush_dev_iotlb() for domains with no dev iotlb devices. Signed-off-by: Omer Peleg [gvdl@google.com: fixed locking issues] Signed-off-by: Godfrey van der Linden [mad@cs.technion.ac.il: rebased and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 63b8c026ef9c..d100583e15e3 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -391,6 +391,7 @@ struct dmar_domain { * domain ids are 16 bit wide according * to VT-d spec, section 9.3 */ + bool has_iotlb_device; struct list_head devices; /* all devices' list */ struct iova_domain iovad; /* iova's that belong to this domain */ @@ -1464,10 +1465,35 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu, return NULL; } +static void domain_update_iotlb(struct dmar_domain *domain) +{ + struct device_domain_info *info; + bool has_iotlb_device = false; + + assert_spin_locked(&device_domain_lock); + + list_for_each_entry(info, &domain->devices, link) { + struct pci_dev *pdev; + + if (!info->dev || !dev_is_pci(info->dev)) + continue; + + pdev = to_pci_dev(info->dev); + if (pdev->ats_enabled) { + has_iotlb_device = true; + break; + } + } + + domain->has_iotlb_device = has_iotlb_device; +} + static void iommu_enable_dev_iotlb(struct device_domain_info *info) { struct pci_dev *pdev; + assert_spin_locked(&device_domain_lock); + if (!info || !dev_is_pci(info->dev)) return; @@ -1487,6 +1513,7 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info) #endif if (info->ats_supported && !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) { info->ats_enabled = 1; + domain_update_iotlb(info->domain); info->ats_qdep = pci_ats_queue_depth(pdev); } } @@ -1495,6 +1522,8 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info) { struct pci_dev *pdev; + assert_spin_locked(&device_domain_lock); + if (!dev_is_pci(info->dev)) return; @@ -1503,6 +1532,7 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info) if (info->ats_enabled) { pci_disable_ats(pdev); info->ats_enabled = 0; + domain_update_iotlb(info->domain); } #ifdef CONFIG_INTEL_IOMMU_SVM if (info->pri_enabled) { @@ -1523,6 +1553,9 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, unsigned long flags; struct device_domain_info *info; + if (!domain->has_iotlb_device) + return; + spin_lock_irqsave(&device_domain_lock, flags); list_for_each_entry(info, &domain->devices, link) { if (!info->ats_enabled) @@ -1740,6 +1773,7 @@ static struct dmar_domain *alloc_domain(int flags) memset(domain, 0, sizeof(*domain)); domain->nid = -1; domain->flags = flags; + domain->has_iotlb_device = false; INIT_LIST_HEAD(&domain->devices); return domain; -- GitLab From 64b3df9223aa4d0e809bbf5a8b006fcc884b7c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sat, 2 Apr 2016 14:42:19 -0300 Subject: [PATCH 3727/9938] [media] adv7180: Add cropcap operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support to get the pixel aspect ratio depending on the current standard (50 vs 60 Hz). Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index d680d7656e2f..80ded7007e55 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -726,6 +726,21 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd, return 0; } +static int adv7180_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cropcap) +{ + struct adv7180_state *state = to_state(sd); + + if (state->curr_norm & V4L2_STD_525_60) { + cropcap->pixelaspect.numerator = 11; + cropcap->pixelaspect.denominator = 10; + } else { + cropcap->pixelaspect.numerator = 54; + cropcap->pixelaspect.denominator = 59; + } + + return 0; +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .s_std = adv7180_s_std, .g_std = adv7180_g_std, @@ -733,6 +748,7 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { .g_input_status = adv7180_g_input_status, .s_routing = adv7180_s_routing, .g_mbus_config = adv7180_g_mbus_config, + .cropcap = adv7180_cropcap, }; -- GitLab From 2aac630429d986a43ac59525a4cff47a624dc58e Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 11:33:57 +0300 Subject: [PATCH 3728/9938] iommu/vt-d: change intel-iommu to use IOVA frame numbers Make intel-iommu map/unmap/invalidate work with IOVA pfns instead of pointers to "struct iova". This avoids using the iova struct from the IOVA red-black tree and the resulting explicit find_iova() on unmap. This patch will allow us to cache IOVAs in the next patch, in order to avoid rbtree operations for the majority of map/unmap operations. Note: In eliminating the find_iova() operation, we have also eliminated the sanity check previously done in the unmap flow. Arguably, this was overhead that is better avoided in production code, but it could be brought back as a debug option for driver development. Signed-off-by: Omer Peleg [mad@cs.technion.ac.il: rebased, fixed to not break iova api, and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 61 ++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d100583e15e3..a8babc43e6d4 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -459,7 +459,7 @@ static LIST_HEAD(dmar_rmrr_units); static void flush_unmaps_timeout(unsigned long data); struct deferred_flush_entry { - struct iova *iova; + unsigned long iova_pfn; unsigned long nrpages; struct dmar_domain *domain; struct page *freelist; @@ -3353,7 +3353,7 @@ static int __init init_dmars(void) } /* This takes a number of _MM_ pages, not VTD pages */ -static struct iova *intel_alloc_iova(struct device *dev, +static unsigned long intel_alloc_iova(struct device *dev, struct dmar_domain *domain, unsigned long nrpages, uint64_t dma_mask) { @@ -3373,16 +3373,16 @@ static struct iova *intel_alloc_iova(struct device *dev, iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(DMA_BIT_MASK(32)), 1); if (iova) - return iova; + return iova->pfn_lo; } iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); if (unlikely(!iova)) { pr_err("Allocating %ld-page iova for %s failed", nrpages, dev_name(dev)); - return NULL; + return 0; } - return iova; + return iova->pfn_lo; } static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev) @@ -3480,7 +3480,7 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, { struct dmar_domain *domain; phys_addr_t start_paddr; - struct iova *iova; + unsigned long iova_pfn; int prot = 0; int ret; struct intel_iommu *iommu; @@ -3498,8 +3498,8 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, iommu = domain_get_iommu(domain); size = aligned_nrpages(paddr, size); - iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask); - if (!iova) + iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask); + if (!iova_pfn) goto error; /* @@ -3517,7 +3517,7 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, * might have two guest_addr mapping to the same host paddr, but this * is not a big problem */ - ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo), + ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn), mm_to_dma_pfn(paddr_pfn), size, prot); if (ret) goto error; @@ -3525,18 +3525,18 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, /* it's a non-present to present mapping. Only flush if caching mode */ if (cap_caching_mode(iommu->cap)) iommu_flush_iotlb_psi(iommu, domain, - mm_to_dma_pfn(iova->pfn_lo), + mm_to_dma_pfn(iova_pfn), size, 0, 1); else iommu_flush_write_buffer(iommu); - start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; + start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT; start_paddr += paddr & ~PAGE_MASK; return start_paddr; error: - if (iova) - __free_iova(&domain->iovad, iova); + if (iova_pfn) + free_iova(&domain->iovad, iova_pfn); pr_err("Device %s request: %zx@%llx dir %d --- failed\n", dev_name(dev), size, (unsigned long long)paddr, dir); return 0; @@ -3576,7 +3576,7 @@ static void flush_unmaps(struct deferred_flush_data *flush_data) unsigned long mask; struct deferred_flush_entry *entry = &flush_table->entries[j]; - struct iova *iova = entry->iova; + unsigned long iova_pfn = entry->iova_pfn; unsigned long nrpages = entry->nrpages; struct dmar_domain *domain = entry->domain; struct page *freelist = entry->freelist; @@ -3584,14 +3584,14 @@ static void flush_unmaps(struct deferred_flush_data *flush_data) /* On real hardware multiple invalidations are expensive */ if (cap_caching_mode(iommu->cap)) iommu_flush_iotlb_psi(iommu, domain, - mm_to_dma_pfn(iova->pfn_lo), + mm_to_dma_pfn(iova_pfn), nrpages, !freelist, 0); else { mask = ilog2(nrpages); iommu_flush_dev_iotlb(domain, - (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); + (uint64_t)iova_pfn << PAGE_SHIFT, mask); } - __free_iova(&domain->iovad, iova); + free_iova(&domain->iovad, iova_pfn); if (freelist) dma_free_pagelist(freelist); } @@ -3611,7 +3611,7 @@ static void flush_unmaps_timeout(unsigned long cpuid) spin_unlock_irqrestore(&flush_data->lock, flags); } -static void add_unmap(struct dmar_domain *dom, struct iova *iova, +static void add_unmap(struct dmar_domain *dom, unsigned long iova_pfn, unsigned long nrpages, struct page *freelist) { unsigned long flags; @@ -3645,7 +3645,7 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova, entry = &flush_data->tables[iommu_id].entries[entry_id]; entry->domain = dom; - entry->iova = iova; + entry->iova_pfn = iova_pfn; entry->nrpages = nrpages; entry->freelist = freelist; @@ -3664,7 +3664,7 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) struct dmar_domain *domain; unsigned long start_pfn, last_pfn; unsigned long nrpages; - struct iova *iova; + unsigned long iova_pfn; struct intel_iommu *iommu; struct page *freelist; @@ -3676,13 +3676,10 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) iommu = domain_get_iommu(domain); - iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); - if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n", - (unsigned long long)dev_addr)) - return; + iova_pfn = IOVA_PFN(dev_addr); nrpages = aligned_nrpages(dev_addr, size); - start_pfn = mm_to_dma_pfn(iova->pfn_lo); + start_pfn = mm_to_dma_pfn(iova_pfn); last_pfn = start_pfn + nrpages - 1; pr_debug("Device %s unmapping: pfn %lx-%lx\n", @@ -3694,10 +3691,10 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) iommu_flush_iotlb_psi(iommu, domain, start_pfn, nrpages, !freelist, 0); /* free iova */ - __free_iova(&domain->iovad, iova); + free_iova(&domain->iovad, iova_pfn); dma_free_pagelist(freelist); } else { - add_unmap(domain, iova, nrpages, freelist); + add_unmap(domain, iova_pfn, nrpages, freelist); /* * queue up the release of the unmap to save the 1/6th of the * cpu used up by the iotlb flush operation... @@ -3810,7 +3807,7 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele struct dmar_domain *domain; size_t size = 0; int prot = 0; - struct iova *iova = NULL; + unsigned long iova_pfn; int ret; struct scatterlist *sg; unsigned long start_vpfn; @@ -3829,9 +3826,9 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele for_each_sg(sglist, sg, nelems, i) size += aligned_nrpages(sg->offset, sg->length); - iova = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), + iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), *dev->dma_mask); - if (!iova) { + if (!iova_pfn) { sglist->dma_length = 0; return 0; } @@ -3846,13 +3843,13 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) prot |= DMA_PTE_WRITE; - start_vpfn = mm_to_dma_pfn(iova->pfn_lo); + start_vpfn = mm_to_dma_pfn(iova_pfn); ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot); if (unlikely(ret)) { dma_pte_free_pagetable(domain, start_vpfn, start_vpfn + size - 1); - __free_iova(&domain->iovad, iova); + free_iova(&domain->iovad, iova_pfn); return 0; } -- GitLab From bae4c757a5255a149249294dab3a6ab16e5d598b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sat, 2 Apr 2016 14:42:20 -0300 Subject: [PATCH 3729/9938] [media] adv7180: Add g_tvnorms operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ADV7180 supports NTSC, PAL and SECAM. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 80ded7007e55..51a92b3b20cc 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -741,6 +741,12 @@ static int adv7180_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cropcap) return 0; } +static int adv7180_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm) +{ + *norm = V4L2_STD_ALL; + return 0; +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .s_std = adv7180_s_std, .g_std = adv7180_g_std, @@ -749,9 +755,9 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { .s_routing = adv7180_s_routing, .g_mbus_config = adv7180_g_mbus_config, .cropcap = adv7180_cropcap, + .g_tvnorms = adv7180_g_tvnorms, }; - static const struct v4l2_subdev_core_ops adv7180_core_ops = { .s_power = adv7180_s_power, }; -- GitLab From 96655553e5f9af6a8d908386685b7c865a138283 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Apr 2016 17:44:16 -0300 Subject: [PATCH 3730/9938] [media] v4l2-device.h: add v4l2_device_mask_ variants The v4l2_device_call_* defines filter subdevs based on the grp_id value. But some drivers use a bitmask, so instead of filtering by grp_id == value, you want to filter by grp_id & value. Make variants of these defines to do this. The 'has_op' define has been extended to have a grp_id argument as well, and a mask variant has been added. This extra argument required a change to go7007. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/go7007/go7007-v4l2.c | 2 +- include/media/v4l2-device.h | 55 +++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index 358c1c186d03..ea01ee5df60a 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -1125,7 +1125,7 @@ int go7007_v4l2_init(struct go7007 *go) vdev->queue = &go->vidq; video_set_drvdata(vdev, go); vdev->v4l2_dev = &go->v4l2_dev; - if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd)) + if (!v4l2_device_has_op(&go->v4l2_dev, 0, video, querystd)) v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD); if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) { v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY); diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 9c581578783f..d5d45a8d3998 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -196,11 +196,64 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev *sd, ##args); \ }) -#define v4l2_device_has_op(v4l2_dev, o, f) \ +/* + * Call the specified callback for all subdevs where grp_id & grpmsk != 0 + * (if grpmsk == `0, then match them all). Ignore any errors. Note that you + * cannot add or delete a subdev while walking the subdevs list. + */ +#define v4l2_device_mask_call_all(v4l2_dev, grpmsk, o, f, args...) \ + do { \ + struct v4l2_subdev *__sd; \ + \ + __v4l2_device_call_subdevs_p(v4l2_dev, __sd, \ + !(grpmsk) || (__sd->grp_id & (grpmsk)), o, f , \ + ##args); \ + } while (0) + +/* + * Call the specified callback for all subdevs where grp_id & grpmsk != 0 + * (if grpmsk == `0, then match them all). If the callback returns an error + * other than 0 or -ENOIOCTLCMD, then return with that error code. Note that + * you cannot add or delete a subdev while walking the subdevs list. + */ +#define v4l2_device_mask_call_until_err(v4l2_dev, grpmsk, o, f, args...) \ +({ \ + struct v4l2_subdev *__sd; \ + __v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, \ + !(grpmsk) || (__sd->grp_id & (grpmsk)), o, f , \ + ##args); \ +}) + +/* + * Does any subdev with matching grpid (or all if grpid == 0) has the given + * op? + */ +#define v4l2_device_has_op(v4l2_dev, grpid, o, f) \ +({ \ + struct v4l2_subdev *__sd; \ + bool __result = false; \ + list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) { \ + if ((grpid) && __sd->grp_id != (grpid)) \ + continue; \ + if (v4l2_subdev_has_op(__sd, o, f)) { \ + __result = true; \ + break; \ + } \ + } \ + __result; \ +}) + +/* + * Does any subdev with matching grpmsk (or all if grpmsk == 0) has the given + * op? + */ +#define v4l2_device_mask_has_op(v4l2_dev, grpmsk, o, f) \ ({ \ struct v4l2_subdev *__sd; \ bool __result = false; \ list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) { \ + if ((grpmsk) && !(__sd->grp_id & (grpmsk))) \ + continue; \ if (v4l2_subdev_has_op(__sd, o, f)) { \ __result = true; \ break; \ -- GitLab From fe29301122902a902c5c323ee14078b1ab3f1ad1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Apr 2016 17:44:17 -0300 Subject: [PATCH 3731/9938] [media] ivtv/cx18: use the new mask variants of the v4l2_device_call_* defines Instead of rolling our own define, just use the new mask defines. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx18/cx18-driver.h | 13 ++----------- drivers/media/pci/ivtv/ivtv-driver.h | 13 ++----------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index 7e31f2a2e085..47ce80fa73b9 100644 --- a/drivers/media/pci/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h @@ -707,11 +707,7 @@ static inline int cx18_raw_vbi(const struct cx18 *cx) /* Call the specified callback for all subdevs with a grp_id bit matching the * mask in hw (if 0, then match them all). Ignore any errors. */ #define cx18_call_hw(cx, hw, o, f, args...) \ - do { \ - struct v4l2_subdev *__sd; \ - __v4l2_device_call_subdevs_p(&(cx)->v4l2_dev, __sd, \ - !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \ - } while (0) + v4l2_device_mask_call_all(&(cx)->v4l2_dev, hw, o, f, ##args) #define cx18_call_all(cx, o, f, args...) cx18_call_hw(cx, 0, o, f , ##args) @@ -719,12 +715,7 @@ static inline int cx18_raw_vbi(const struct cx18 *cx) * mask in hw (if 0, then match them all). If the callback returns an error * other than 0 or -ENOIOCTLCMD, then return with that error code. */ #define cx18_call_hw_err(cx, hw, o, f, args...) \ -({ \ - struct v4l2_subdev *__sd; \ - __v4l2_device_call_subdevs_until_err_p(&(cx)->v4l2_dev, \ - __sd, !(hw) || (__sd->grp_id & (hw)), o, f, \ - ##args); \ -}) + v4l2_device_mask_call_until_err(&(cx)->v4l2_dev, hw, o, f, ##args) #define cx18_call_all_err(cx, o, f, args...) \ cx18_call_hw_err(cx, 0, o, f , ##args) diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h index 6c08dae67a73..10cba305dbd2 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.h +++ b/drivers/media/pci/ivtv/ivtv-driver.h @@ -827,12 +827,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) /* Call the specified callback for all subdevs matching hw (if 0, then match them all). Ignore any errors. */ #define ivtv_call_hw(itv, hw, o, f, args...) \ - do { \ - struct v4l2_subdev *__sd; \ - __v4l2_device_call_subdevs_p(&(itv)->v4l2_dev, __sd, \ - !(hw) ? true : (__sd->grp_id & (hw)), \ - o, f, ##args); \ - } while (0) + v4l2_device_mask_call_all(&(itv)->v4l2_dev, hw, o, f, ##args) #define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args) @@ -840,11 +835,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) match them all). If the callback returns an error other than 0 or -ENOIOCTLCMD, then return with that error code. */ #define ivtv_call_hw_err(itv, hw, o, f, args...) \ -({ \ - struct v4l2_subdev *__sd; \ - __v4l2_device_call_subdevs_until_err_p(&(itv)->v4l2_dev, __sd, \ - !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \ -}) + v4l2_device_mask_call_until_err(&(itv)->v4l2_dev, hw, o, f, ##args) #define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args) -- GitLab From ac49de8c49d770b5ded5c717c1eaf339d7649da1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Apr 2016 16:42:42 -0300 Subject: [PATCH 3732/9938] [media] v4l2-rect.h: new header with struct v4l2_rect helper functions This makes it easier to share this code with any driver that needs to manipulate the v4l2_rect datastructure. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/device-drivers.tmpl | 1 + include/media/v4l2-rect.h | 173 ++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 include/media/v4l2-rect.h diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 184f3c7b5145..893b2cabf7e4 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -233,6 +233,7 @@ X!Isound/sound_firmware.c !Iinclude/media/v4l2-mediabus.h !Iinclude/media/v4l2-mem2mem.h !Iinclude/media/v4l2-of.h +!Iinclude/media/v4l2-rect.h !Iinclude/media/v4l2-subdev.h !Iinclude/media/videobuf2-core.h !Iinclude/media/videobuf2-v4l2.h diff --git a/include/media/v4l2-rect.h b/include/media/v4l2-rect.h new file mode 100644 index 000000000000..d2125f0cc7cd --- /dev/null +++ b/include/media/v4l2-rect.h @@ -0,0 +1,173 @@ +/* + * v4l2-rect.h - v4l2_rect helper functions + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _V4L2_RECT_H_ +#define _V4L2_RECT_H_ + +#include + +/** + * v4l2_rect_set_size_to() - copy the width/height values. + * @r: rect whose width and height fields will be set + * @size: rect containing the width and height fields you need. + */ +static inline void v4l2_rect_set_size_to(struct v4l2_rect *r, + const struct v4l2_rect *size) +{ + r->width = size->width; + r->height = size->height; +} + +/** + * v4l2_rect_set_min_size() - width and height of r should be >= min_size. + * @r: rect whose width and height will be modified + * @min_size: rect containing the minimal width and height + */ +static inline void v4l2_rect_set_min_size(struct v4l2_rect *r, + const struct v4l2_rect *min_size) +{ + if (r->width < min_size->width) + r->width = min_size->width; + if (r->height < min_size->height) + r->height = min_size->height; +} + +/** + * v4l2_rect_set_max_size() - width and height of r should be <= max_size + * @r: rect whose width and height will be modified + * @max_size: rect containing the maximum width and height + */ +static inline void v4l2_rect_set_max_size(struct v4l2_rect *r, + const struct v4l2_rect *max_size) +{ + if (r->width > max_size->width) + r->width = max_size->width; + if (r->height > max_size->height) + r->height = max_size->height; +} + +/** + * v4l2_rect_map_inside()- r should be inside boundary. + * @r: rect that will be modified + * @boundary: rect containing the boundary for @r + */ +static inline void v4l2_rect_map_inside(struct v4l2_rect *r, + const struct v4l2_rect *boundary) +{ + v4l2_rect_set_max_size(r, boundary); + if (r->left < boundary->left) + r->left = boundary->left; + if (r->top < boundary->top) + r->top = boundary->top; + if (r->left + r->width > boundary->width) + r->left = boundary->width - r->width; + if (r->top + r->height > boundary->height) + r->top = boundary->height - r->height; +} + +/** + * v4l2_rect_same_size() - return true if r1 has the same size as r2 + * @r1: rectangle. + * @r2: rectangle. + * + * Return true if both rectangles have the same size. + */ +static inline bool v4l2_rect_same_size(const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + return r1->width == r2->width && r1->height == r2->height; +} + +/** + * v4l2_rect_intersect() - calculate the intersection of two rects. + * @r: intersection of @r1 and @r2. + * @r1: rectangle. + * @r2: rectangle. + */ +static inline void v4l2_rect_intersect(struct v4l2_rect *r, + const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + int right, bottom; + + r->top = max(r1->top, r2->top); + r->left = max(r1->left, r2->left); + bottom = min(r1->top + r1->height, r2->top + r2->height); + right = min(r1->left + r1->width, r2->left + r2->width); + r->height = max(0, bottom - r->top); + r->width = max(0, right - r->left); +} + +/** + * v4l2_rect_scale() - scale rect r by to/from + * @r: rect to be scaled. + * @from: from rectangle. + * @to: to rectangle. + * + * This scales rectangle @r horizontally by @to->width / @from->width and + * vertically by @to->height / @from->height. + * + * Typically @r is a rectangle inside @from and you want the rectangle as + * it would appear after scaling @from to @to. So the resulting @r will + * be the scaled rectangle inside @to. + */ +static inline void v4l2_rect_scale(struct v4l2_rect *r, + const struct v4l2_rect *from, + const struct v4l2_rect *to) +{ + if (from->width == 0 || from->height == 0) { + r->left = r->top = r->width = r->height = 0; + return; + } + r->left = (((r->left - from->left) * to->width) / from->width) & ~1; + r->width = ((r->width * to->width) / from->width) & ~1; + r->top = ((r->top - from->top) * to->height) / from->height; + r->height = (r->height * to->height) / from->height; +} + +/** + * v4l2_rect_overlap() - do r1 and r2 overlap? + * @r1: rectangle. + * @r2: rectangle. + * + * Returns true if @r1 and @r2 overlap. + */ +static inline bool v4l2_rect_overlap(const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + /* + * IF the left side of r1 is to the right of the right side of r2 OR + * the left side of r2 is to the right of the right side of r1 THEN + * they do not overlap. + */ + if (r1->left >= r2->left + r2->width || + r2->left >= r1->left + r1->width) + return false; + /* + * IF the top side of r1 is below the bottom of r2 OR + * the top side of r2 is below the bottom of r1 THEN + * they do not overlap. + */ + if (r1->top >= r2->top + r2->height || + r2->top >= r1->top + r1->height) + return false; + return true; +} + +#endif -- GitLab From d1e5d8bd49d9a830b6b5f4da906f868b2ceb83a4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Apr 2016 16:42:43 -0300 Subject: [PATCH 3733/9938] [media] vivid: use new v4l2-rect.h header The v4l2_rect helper functions have been moved to include/media/v4l2-rect.h. Use this new header, dropping the functions from vivid. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/vivid/vivid-kthread-cap.c | 13 ++- drivers/media/platform/vivid/vivid-vid-cap.c | 101 ++++++++--------- .../media/platform/vivid/vivid-vid-common.c | 97 ----------------- .../media/platform/vivid/vivid-vid-common.h | 9 -- drivers/media/platform/vivid/vivid-vid-out.c | 103 +++++++++--------- 5 files changed, 110 insertions(+), 213 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c index 9034281944a4..3b8c10108dfa 100644 --- a/drivers/media/platform/vivid/vivid-kthread-cap.c +++ b/drivers/media/platform/vivid/vivid-kthread-cap.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "vivid-core.h" #include "vivid-vid-common.h" @@ -184,15 +185,15 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev) dev->compose_out.width, dev->compose_out.height }; - dev->loop_vid_copy = rect_intersect(&dev->crop_cap, &dev->compose_out); + v4l2_rect_intersect(&dev->loop_vid_copy, &dev->crop_cap, &dev->compose_out); dev->loop_vid_out = dev->loop_vid_copy; - rect_scale(&dev->loop_vid_out, &dev->compose_out, &dev->crop_out); + v4l2_rect_scale(&dev->loop_vid_out, &dev->compose_out, &dev->crop_out); dev->loop_vid_out.left += dev->crop_out.left; dev->loop_vid_out.top += dev->crop_out.top; dev->loop_vid_cap = dev->loop_vid_copy; - rect_scale(&dev->loop_vid_cap, &dev->crop_cap, &dev->compose_cap); + v4l2_rect_scale(&dev->loop_vid_cap, &dev->crop_cap, &dev->compose_cap); dprintk(dev, 1, "loop_vid_copy: %dx%d@%dx%d loop_vid_out: %dx%d@%dx%d loop_vid_cap: %dx%d@%dx%d\n", @@ -203,13 +204,13 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev) dev->loop_vid_cap.width, dev->loop_vid_cap.height, dev->loop_vid_cap.left, dev->loop_vid_cap.top); - r_overlay = rect_intersect(&r_fb, &r_overlay); + v4l2_rect_intersect(&r_overlay, &r_fb, &r_overlay); /* shift r_overlay to the same origin as compose_out */ r_overlay.left += dev->compose_out.left - dev->overlay_out_left; r_overlay.top += dev->compose_out.top - dev->overlay_out_top; - dev->loop_vid_overlay = rect_intersect(&r_overlay, &dev->loop_vid_copy); + v4l2_rect_intersect(&dev->loop_vid_overlay, &r_overlay, &dev->loop_vid_copy); dev->loop_fb_copy = dev->loop_vid_overlay; /* shift dev->loop_fb_copy back again to the fb origin */ @@ -217,7 +218,7 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev) dev->loop_fb_copy.top -= dev->compose_out.top - dev->overlay_out_top; dev->loop_vid_overlay_cap = dev->loop_vid_overlay; - rect_scale(&dev->loop_vid_overlay_cap, &dev->crop_cap, &dev->compose_cap); + v4l2_rect_scale(&dev->loop_vid_overlay_cap, &dev->crop_cap, &dev->compose_cap); dprintk(dev, 1, "loop_fb_copy: %dx%d@%dx%d loop_vid_overlay: %dx%d@%dx%d loop_vid_overlay_cap: %dx%d@%dx%d\n", diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c index b84f081c1b92..4f730f355a17 100644 --- a/drivers/media/platform/vivid/vivid-vid-cap.c +++ b/drivers/media/platform/vivid/vivid-vid-cap.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "vivid-core.h" #include "vivid-vid-common.h" @@ -590,16 +591,16 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv, } else { struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor }; - rect_set_min_size(&r, &vivid_min_rect); - rect_set_max_size(&r, &vivid_max_rect); + v4l2_rect_set_min_size(&r, &vivid_min_rect); + v4l2_rect_set_max_size(&r, &vivid_max_rect); if (dev->has_scaler_cap && !dev->has_compose_cap) { struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h }; - rect_set_max_size(&r, &max_r); + v4l2_rect_set_max_size(&r, &max_r); } else if (!dev->has_scaler_cap && dev->has_crop_cap && !dev->has_compose_cap) { - rect_set_max_size(&r, &dev->src_rect); + v4l2_rect_set_max_size(&r, &dev->src_rect); } else if (!dev->has_scaler_cap && !dev->has_crop_cap) { - rect_set_min_size(&r, &dev->src_rect); + v4l2_rect_set_min_size(&r, &dev->src_rect); } mp->width = r.width; mp->height = r.height / factor; @@ -668,7 +669,7 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, if (dev->has_scaler_cap) { if (dev->has_compose_cap) - rect_map_inside(compose, &r); + v4l2_rect_map_inside(compose, &r); else *compose = r; if (dev->has_crop_cap && !dev->has_compose_cap) { @@ -683,9 +684,9 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, factor * r.height * MAX_ZOOM }; - rect_set_min_size(crop, &min_r); - rect_set_max_size(crop, &max_r); - rect_map_inside(crop, &dev->crop_bounds_cap); + v4l2_rect_set_min_size(crop, &min_r); + v4l2_rect_set_max_size(crop, &max_r); + v4l2_rect_map_inside(crop, &dev->crop_bounds_cap); } else if (dev->has_crop_cap) { struct v4l2_rect min_r = { 0, 0, @@ -698,27 +699,27 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, factor * compose->height * MAX_ZOOM }; - rect_set_min_size(crop, &min_r); - rect_set_max_size(crop, &max_r); - rect_map_inside(crop, &dev->crop_bounds_cap); + v4l2_rect_set_min_size(crop, &min_r); + v4l2_rect_set_max_size(crop, &max_r); + v4l2_rect_map_inside(crop, &dev->crop_bounds_cap); } } else if (dev->has_crop_cap && !dev->has_compose_cap) { r.height *= factor; - rect_set_size_to(crop, &r); - rect_map_inside(crop, &dev->crop_bounds_cap); + v4l2_rect_set_size_to(crop, &r); + v4l2_rect_map_inside(crop, &dev->crop_bounds_cap); r = *crop; r.height /= factor; - rect_set_size_to(compose, &r); + v4l2_rect_set_size_to(compose, &r); } else if (!dev->has_crop_cap) { - rect_map_inside(compose, &r); + v4l2_rect_map_inside(compose, &r); } else { r.height *= factor; - rect_set_max_size(crop, &r); - rect_map_inside(crop, &dev->crop_bounds_cap); + v4l2_rect_set_max_size(crop, &r); + v4l2_rect_map_inside(crop, &dev->crop_bounds_cap); compose->top *= factor; compose->height *= factor; - rect_set_size_to(compose, crop); - rect_map_inside(compose, &r); + v4l2_rect_set_size_to(compose, crop); + v4l2_rect_map_inside(compose, &r); compose->top /= factor; compose->height /= factor; } @@ -735,9 +736,9 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, } else { struct v4l2_rect r = { 0, 0, mp->width, mp->height }; - rect_set_size_to(compose, &r); + v4l2_rect_set_size_to(compose, &r); r.height *= factor; - rect_set_size_to(crop, &r); + v4l2_rect_set_size_to(crop, &r); } dev->fmt_cap_rect.width = mp->width; @@ -886,9 +887,9 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection ret = vivid_vid_adjust_sel(s->flags, &s->r); if (ret) return ret; - rect_set_min_size(&s->r, &vivid_min_rect); - rect_set_max_size(&s->r, &dev->src_rect); - rect_map_inside(&s->r, &dev->crop_bounds_cap); + v4l2_rect_set_min_size(&s->r, &vivid_min_rect); + v4l2_rect_set_max_size(&s->r, &dev->src_rect); + v4l2_rect_map_inside(&s->r, &dev->crop_bounds_cap); s->r.top /= factor; s->r.height /= factor; if (dev->has_scaler_cap) { @@ -904,36 +905,36 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection s->r.height / MAX_ZOOM }; - rect_set_min_size(&fmt, &min_rect); + v4l2_rect_set_min_size(&fmt, &min_rect); if (!dev->has_compose_cap) - rect_set_max_size(&fmt, &max_rect); - if (!rect_same_size(&dev->fmt_cap_rect, &fmt) && + v4l2_rect_set_max_size(&fmt, &max_rect); + if (!v4l2_rect_same_size(&dev->fmt_cap_rect, &fmt) && vb2_is_busy(&dev->vb_vid_cap_q)) return -EBUSY; if (dev->has_compose_cap) { - rect_set_min_size(compose, &min_rect); - rect_set_max_size(compose, &max_rect); + v4l2_rect_set_min_size(compose, &min_rect); + v4l2_rect_set_max_size(compose, &max_rect); } dev->fmt_cap_rect = fmt; tpg_s_buf_height(&dev->tpg, fmt.height); } else if (dev->has_compose_cap) { struct v4l2_rect fmt = dev->fmt_cap_rect; - rect_set_min_size(&fmt, &s->r); - if (!rect_same_size(&dev->fmt_cap_rect, &fmt) && + v4l2_rect_set_min_size(&fmt, &s->r); + if (!v4l2_rect_same_size(&dev->fmt_cap_rect, &fmt) && vb2_is_busy(&dev->vb_vid_cap_q)) return -EBUSY; dev->fmt_cap_rect = fmt; tpg_s_buf_height(&dev->tpg, fmt.height); - rect_set_size_to(compose, &s->r); - rect_map_inside(compose, &dev->fmt_cap_rect); + v4l2_rect_set_size_to(compose, &s->r); + v4l2_rect_map_inside(compose, &dev->fmt_cap_rect); } else { - if (!rect_same_size(&s->r, &dev->fmt_cap_rect) && + if (!v4l2_rect_same_size(&s->r, &dev->fmt_cap_rect) && vb2_is_busy(&dev->vb_vid_cap_q)) return -EBUSY; - rect_set_size_to(&dev->fmt_cap_rect, &s->r); - rect_set_size_to(compose, &s->r); - rect_map_inside(compose, &dev->fmt_cap_rect); + v4l2_rect_set_size_to(&dev->fmt_cap_rect, &s->r); + v4l2_rect_set_size_to(compose, &s->r); + v4l2_rect_map_inside(compose, &dev->fmt_cap_rect); tpg_s_buf_height(&dev->tpg, dev->fmt_cap_rect.height); } s->r.top *= factor; @@ -946,8 +947,8 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection ret = vivid_vid_adjust_sel(s->flags, &s->r); if (ret) return ret; - rect_set_min_size(&s->r, &vivid_min_rect); - rect_set_max_size(&s->r, &dev->fmt_cap_rect); + v4l2_rect_set_min_size(&s->r, &vivid_min_rect); + v4l2_rect_set_max_size(&s->r, &dev->fmt_cap_rect); if (dev->has_scaler_cap) { struct v4l2_rect max_rect = { 0, 0, @@ -955,7 +956,7 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection (dev->src_rect.height / factor) * MAX_ZOOM }; - rect_set_max_size(&s->r, &max_rect); + v4l2_rect_set_max_size(&s->r, &max_rect); if (dev->has_crop_cap) { struct v4l2_rect min_rect = { 0, 0, @@ -968,23 +969,23 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection (s->r.height * factor) * MAX_ZOOM }; - rect_set_min_size(crop, &min_rect); - rect_set_max_size(crop, &max_rect); - rect_map_inside(crop, &dev->crop_bounds_cap); + v4l2_rect_set_min_size(crop, &min_rect); + v4l2_rect_set_max_size(crop, &max_rect); + v4l2_rect_map_inside(crop, &dev->crop_bounds_cap); } } else if (dev->has_crop_cap) { s->r.top *= factor; s->r.height *= factor; - rect_set_max_size(&s->r, &dev->src_rect); - rect_set_size_to(crop, &s->r); - rect_map_inside(crop, &dev->crop_bounds_cap); + v4l2_rect_set_max_size(&s->r, &dev->src_rect); + v4l2_rect_set_size_to(crop, &s->r); + v4l2_rect_map_inside(crop, &dev->crop_bounds_cap); s->r.top /= factor; s->r.height /= factor; } else { - rect_set_size_to(&s->r, &dev->src_rect); + v4l2_rect_set_size_to(&s->r, &dev->src_rect); s->r.height /= factor; } - rect_map_inside(&s->r, &dev->fmt_cap_rect); + v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect); if (dev->bitmap_cap && (compose->width != s->r.width || compose->height != s->r.height)) { kfree(dev->bitmap_cap); @@ -1124,7 +1125,7 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, for (j = i + 1; j < win->clipcount; j++) { struct v4l2_rect *r2 = &dev->try_clips_cap[j].c; - if (rect_overlap(r1, r2)) + if (v4l2_rect_overlap(r1, r2)) return -EINVAL; } } diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c index b0d4e3a0acf0..39ea2284789c 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.c +++ b/drivers/media/platform/vivid/vivid-vid-common.c @@ -653,103 +653,6 @@ int fmt_sp2mp_func(struct file *file, void *priv, return ret; } -/* v4l2_rect helper function: copy the width/height values */ -void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size) -{ - r->width = size->width; - r->height = size->height; -} - -/* v4l2_rect helper function: width and height of r should be >= min_size */ -void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size) -{ - if (r->width < min_size->width) - r->width = min_size->width; - if (r->height < min_size->height) - r->height = min_size->height; -} - -/* v4l2_rect helper function: width and height of r should be <= max_size */ -void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size) -{ - if (r->width > max_size->width) - r->width = max_size->width; - if (r->height > max_size->height) - r->height = max_size->height; -} - -/* v4l2_rect helper function: r should be inside boundary */ -void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary) -{ - rect_set_max_size(r, boundary); - if (r->left < boundary->left) - r->left = boundary->left; - if (r->top < boundary->top) - r->top = boundary->top; - if (r->left + r->width > boundary->width) - r->left = boundary->width - r->width; - if (r->top + r->height > boundary->height) - r->top = boundary->height - r->height; -} - -/* v4l2_rect helper function: return true if r1 has the same size as r2 */ -bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2) -{ - return r1->width == r2->width && r1->height == r2->height; -} - -/* v4l2_rect helper function: calculate the intersection of two rects */ -struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b) -{ - struct v4l2_rect r; - int right, bottom; - - r.top = max(a->top, b->top); - r.left = max(a->left, b->left); - bottom = min(a->top + a->height, b->top + b->height); - right = min(a->left + a->width, b->left + b->width); - r.height = max(0, bottom - r.top); - r.width = max(0, right - r.left); - return r; -} - -/* - * v4l2_rect helper function: scale rect r by to->width / from->width and - * to->height / from->height. - */ -void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from, - const struct v4l2_rect *to) -{ - if (from->width == 0 || from->height == 0) { - r->left = r->top = r->width = r->height = 0; - return; - } - r->left = (((r->left - from->left) * to->width) / from->width) & ~1; - r->width = ((r->width * to->width) / from->width) & ~1; - r->top = ((r->top - from->top) * to->height) / from->height; - r->height = (r->height * to->height) / from->height; -} - -bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2) -{ - /* - * IF the left side of r1 is to the right of the right side of r2 OR - * the left side of r2 is to the right of the right side of r1 THEN - * they do not overlap. - */ - if (r1->left >= r2->left + r2->width || - r2->left >= r1->left + r1->width) - return false; - /* - * IF the top side of r1 is below the bottom of r2 OR - * the top side of r2 is below the bottom of r1 THEN - * they do not overlap. - */ - if (r1->top >= r2->top + r2->height || - r2->top >= r1->top + r1->height) - return false; - return true; -} int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r) { unsigned w = r->width; diff --git a/drivers/media/platform/vivid/vivid-vid-common.h b/drivers/media/platform/vivid/vivid-vid-common.h index 3ec4fa85c9b9..4b6175eab8a2 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.h +++ b/drivers/media/platform/vivid/vivid-vid-common.h @@ -37,15 +37,6 @@ const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat) bool vivid_vid_can_loop(struct vivid_dev *dev); void vivid_send_source_change(struct vivid_dev *dev, unsigned type); -bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2); -void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size); -void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size); -void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size); -void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary); -bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2); -struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b); -void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from, - const struct v4l2_rect *to); int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r); int vivid_enum_fmt_vid(struct file *file, void *priv, struct v4l2_fmtdesc *f); diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c index 64e4d66482c1..f92f4496d527 100644 --- a/drivers/media/platform/vivid/vivid-vid-out.c +++ b/drivers/media/platform/vivid/vivid-vid-out.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "vivid-core.h" #include "vivid-vid-common.h" @@ -376,16 +377,16 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv, } else { struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor }; - rect_set_min_size(&r, &vivid_min_rect); - rect_set_max_size(&r, &vivid_max_rect); + v4l2_rect_set_min_size(&r, &vivid_min_rect); + v4l2_rect_set_max_size(&r, &vivid_max_rect); if (dev->has_scaler_out && !dev->has_crop_out) { struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h }; - rect_set_max_size(&r, &max_r); + v4l2_rect_set_max_size(&r, &max_r); } else if (!dev->has_scaler_out && dev->has_compose_out && !dev->has_crop_out) { - rect_set_max_size(&r, &dev->sink_rect); + v4l2_rect_set_max_size(&r, &dev->sink_rect); } else if (!dev->has_scaler_out && !dev->has_compose_out) { - rect_set_min_size(&r, &dev->sink_rect); + v4l2_rect_set_min_size(&r, &dev->sink_rect); } mp->width = r.width; mp->height = r.height / factor; @@ -473,7 +474,7 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv, if (dev->has_scaler_out) { if (dev->has_crop_out) - rect_map_inside(crop, &r); + v4l2_rect_map_inside(crop, &r); else *crop = r; if (dev->has_compose_out && !dev->has_crop_out) { @@ -488,9 +489,9 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv, factor * r.height * MAX_ZOOM }; - rect_set_min_size(compose, &min_r); - rect_set_max_size(compose, &max_r); - rect_map_inside(compose, &dev->compose_bounds_out); + v4l2_rect_set_min_size(compose, &min_r); + v4l2_rect_set_max_size(compose, &max_r); + v4l2_rect_map_inside(compose, &dev->compose_bounds_out); } else if (dev->has_compose_out) { struct v4l2_rect min_r = { 0, 0, @@ -503,36 +504,36 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv, factor * crop->height * MAX_ZOOM }; - rect_set_min_size(compose, &min_r); - rect_set_max_size(compose, &max_r); - rect_map_inside(compose, &dev->compose_bounds_out); + v4l2_rect_set_min_size(compose, &min_r); + v4l2_rect_set_max_size(compose, &max_r); + v4l2_rect_map_inside(compose, &dev->compose_bounds_out); } } else if (dev->has_compose_out && !dev->has_crop_out) { - rect_set_size_to(crop, &r); + v4l2_rect_set_size_to(crop, &r); r.height *= factor; - rect_set_size_to(compose, &r); - rect_map_inside(compose, &dev->compose_bounds_out); + v4l2_rect_set_size_to(compose, &r); + v4l2_rect_map_inside(compose, &dev->compose_bounds_out); } else if (!dev->has_compose_out) { - rect_map_inside(crop, &r); + v4l2_rect_map_inside(crop, &r); r.height /= factor; - rect_set_size_to(compose, &r); + v4l2_rect_set_size_to(compose, &r); } else { r.height *= factor; - rect_set_max_size(compose, &r); - rect_map_inside(compose, &dev->compose_bounds_out); + v4l2_rect_set_max_size(compose, &r); + v4l2_rect_map_inside(compose, &dev->compose_bounds_out); crop->top *= factor; crop->height *= factor; - rect_set_size_to(crop, compose); - rect_map_inside(crop, &r); + v4l2_rect_set_size_to(crop, compose); + v4l2_rect_map_inside(crop, &r); crop->top /= factor; crop->height /= factor; } } else { struct v4l2_rect r = { 0, 0, mp->width, mp->height }; - rect_set_size_to(crop, &r); + v4l2_rect_set_size_to(crop, &r); r.height /= factor; - rect_set_size_to(compose, &r); + v4l2_rect_set_size_to(compose, &r); } dev->fmt_out_rect.width = mp->width; @@ -683,8 +684,8 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection ret = vivid_vid_adjust_sel(s->flags, &s->r); if (ret) return ret; - rect_set_min_size(&s->r, &vivid_min_rect); - rect_set_max_size(&s->r, &dev->fmt_out_rect); + v4l2_rect_set_min_size(&s->r, &vivid_min_rect); + v4l2_rect_set_max_size(&s->r, &dev->fmt_out_rect); if (dev->has_scaler_out) { struct v4l2_rect max_rect = { 0, 0, @@ -692,7 +693,7 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection (dev->sink_rect.height / factor) * MAX_ZOOM }; - rect_set_max_size(&s->r, &max_rect); + v4l2_rect_set_max_size(&s->r, &max_rect); if (dev->has_compose_out) { struct v4l2_rect min_rect = { 0, 0, @@ -705,23 +706,23 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection (s->r.height * factor) * MAX_ZOOM }; - rect_set_min_size(compose, &min_rect); - rect_set_max_size(compose, &max_rect); - rect_map_inside(compose, &dev->compose_bounds_out); + v4l2_rect_set_min_size(compose, &min_rect); + v4l2_rect_set_max_size(compose, &max_rect); + v4l2_rect_map_inside(compose, &dev->compose_bounds_out); } } else if (dev->has_compose_out) { s->r.top *= factor; s->r.height *= factor; - rect_set_max_size(&s->r, &dev->sink_rect); - rect_set_size_to(compose, &s->r); - rect_map_inside(compose, &dev->compose_bounds_out); + v4l2_rect_set_max_size(&s->r, &dev->sink_rect); + v4l2_rect_set_size_to(compose, &s->r); + v4l2_rect_map_inside(compose, &dev->compose_bounds_out); s->r.top /= factor; s->r.height /= factor; } else { - rect_set_size_to(&s->r, &dev->sink_rect); + v4l2_rect_set_size_to(&s->r, &dev->sink_rect); s->r.height /= factor; } - rect_map_inside(&s->r, &dev->fmt_out_rect); + v4l2_rect_map_inside(&s->r, &dev->fmt_out_rect); *crop = s->r; break; case V4L2_SEL_TGT_COMPOSE: @@ -730,9 +731,9 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection ret = vivid_vid_adjust_sel(s->flags, &s->r); if (ret) return ret; - rect_set_min_size(&s->r, &vivid_min_rect); - rect_set_max_size(&s->r, &dev->sink_rect); - rect_map_inside(&s->r, &dev->compose_bounds_out); + v4l2_rect_set_min_size(&s->r, &vivid_min_rect); + v4l2_rect_set_max_size(&s->r, &dev->sink_rect); + v4l2_rect_map_inside(&s->r, &dev->compose_bounds_out); s->r.top /= factor; s->r.height /= factor; if (dev->has_scaler_out) { @@ -748,35 +749,35 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection s->r.height / MAX_ZOOM }; - rect_set_min_size(&fmt, &min_rect); + v4l2_rect_set_min_size(&fmt, &min_rect); if (!dev->has_crop_out) - rect_set_max_size(&fmt, &max_rect); - if (!rect_same_size(&dev->fmt_out_rect, &fmt) && + v4l2_rect_set_max_size(&fmt, &max_rect); + if (!v4l2_rect_same_size(&dev->fmt_out_rect, &fmt) && vb2_is_busy(&dev->vb_vid_out_q)) return -EBUSY; if (dev->has_crop_out) { - rect_set_min_size(crop, &min_rect); - rect_set_max_size(crop, &max_rect); + v4l2_rect_set_min_size(crop, &min_rect); + v4l2_rect_set_max_size(crop, &max_rect); } dev->fmt_out_rect = fmt; } else if (dev->has_crop_out) { struct v4l2_rect fmt = dev->fmt_out_rect; - rect_set_min_size(&fmt, &s->r); - if (!rect_same_size(&dev->fmt_out_rect, &fmt) && + v4l2_rect_set_min_size(&fmt, &s->r); + if (!v4l2_rect_same_size(&dev->fmt_out_rect, &fmt) && vb2_is_busy(&dev->vb_vid_out_q)) return -EBUSY; dev->fmt_out_rect = fmt; - rect_set_size_to(crop, &s->r); - rect_map_inside(crop, &dev->fmt_out_rect); + v4l2_rect_set_size_to(crop, &s->r); + v4l2_rect_map_inside(crop, &dev->fmt_out_rect); } else { - if (!rect_same_size(&s->r, &dev->fmt_out_rect) && + if (!v4l2_rect_same_size(&s->r, &dev->fmt_out_rect) && vb2_is_busy(&dev->vb_vid_out_q)) return -EBUSY; - rect_set_size_to(&dev->fmt_out_rect, &s->r); - rect_set_size_to(crop, &s->r); + v4l2_rect_set_size_to(&dev->fmt_out_rect, &s->r); + v4l2_rect_set_size_to(crop, &s->r); crop->height /= factor; - rect_map_inside(crop, &dev->fmt_out_rect); + v4l2_rect_map_inside(crop, &dev->fmt_out_rect); } s->r.top *= factor; s->r.height *= factor; @@ -901,7 +902,7 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv, for (j = i + 1; j < win->clipcount; j++) { struct v4l2_rect *r2 = &dev->try_clips_out[j].c; - if (rect_overlap(r1, r2)) + if (v4l2_rect_overlap(r1, r2)) return -EINVAL; } } -- GitLab From e07d46e7e0da86c146f199dae76f879096bc436a Mon Sep 17 00:00:00 2001 From: Helen Mae Koike Fornazier Date: Fri, 8 Apr 2016 17:28:58 -0300 Subject: [PATCH 3734/9938] [media] tpg: Export the tpg code from vivid as a module The test pattern generator will be used by other drivers as the virtual media controller (vimc) Signed-off-by: Helen Mae Koike Fornazier Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/Kconfig | 1 + drivers/media/common/Makefile | 2 +- drivers/media/common/v4l2-tpg/Kconfig | 2 ++ drivers/media/common/v4l2-tpg/Makefile | 3 +++ .../v4l2-tpg/v4l2-tpg-colors.c} | 7 +++--- .../v4l2-tpg/v4l2-tpg-core.c} | 25 +++++++++++++++++-- drivers/media/platform/vivid/Kconfig | 1 + drivers/media/platform/vivid/Makefile | 2 +- drivers/media/platform/vivid/vivid-core.h | 2 +- .../media/v4l2-tpg-colors.h | 6 ++--- .../vivid-tpg.h => include/media/v4l2-tpg.h | 9 +++---- 11 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 drivers/media/common/v4l2-tpg/Kconfig create mode 100644 drivers/media/common/v4l2-tpg/Makefile rename drivers/media/{platform/vivid/vivid-tpg-colors.c => common/v4l2-tpg/v4l2-tpg-colors.c} (99%) rename drivers/media/{platform/vivid/vivid-tpg.c => common/v4l2-tpg/v4l2-tpg-core.c} (98%) rename drivers/media/platform/vivid/vivid-tpg-colors.h => include/media/v4l2-tpg-colors.h (93%) rename drivers/media/platform/vivid/vivid-tpg.h => include/media/v4l2-tpg.h (99%) diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 21154dd87b0b..326df0ad75c0 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -19,3 +19,4 @@ config CYPRESS_FIRMWARE source "drivers/media/common/b2c2/Kconfig" source "drivers/media/common/saa7146/Kconfig" source "drivers/media/common/siano/Kconfig" +source "drivers/media/common/v4l2-tpg/Kconfig" diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index 89b795df2cdd..2d1b0a025084 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,4 +1,4 @@ -obj-y += b2c2/ saa7146/ siano/ +obj-y += b2c2/ saa7146/ siano/ v4l2-tpg/ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o diff --git a/drivers/media/common/v4l2-tpg/Kconfig b/drivers/media/common/v4l2-tpg/Kconfig new file mode 100644 index 000000000000..7456fc1c41ed --- /dev/null +++ b/drivers/media/common/v4l2-tpg/Kconfig @@ -0,0 +1,2 @@ +config VIDEO_V4L2_TPG + tristate diff --git a/drivers/media/common/v4l2-tpg/Makefile b/drivers/media/common/v4l2-tpg/Makefile new file mode 100644 index 000000000000..f588df466ae3 --- /dev/null +++ b/drivers/media/common/v4l2-tpg/Makefile @@ -0,0 +1,3 @@ +v4l2-tpg-objs := v4l2-tpg-core.o v4l2-tpg-colors.o + +obj-$(CONFIG_VIDEO_V4L2_TPG) += v4l2-tpg.o diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c similarity index 99% rename from drivers/media/platform/vivid/vivid-tpg-colors.c rename to drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c index 2299f0ce47c8..9bcbd318489b 100644 --- a/drivers/media/platform/vivid/vivid-tpg-colors.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c @@ -1,5 +1,5 @@ /* - * vivid-color.c - A table that converts colors to various colorspaces + * v4l2-tpg-colors.c - A table that converts colors to various colorspaces * * The test pattern generator uses the tpg_colors for its test patterns. * For testing colorspaces the first 8 colors of that table need to be @@ -12,7 +12,7 @@ * This source also contains the code used to generate the tpg_csc_colors * table. Run the following command to compile it: * - * gcc vivid-tpg-colors.c -DCOMPILE_APP -o gen-colors -lm + * gcc v4l2-tpg-colors.c -DCOMPILE_APP -o gen-colors -lm * * and run the utility. * @@ -36,8 +36,7 @@ */ #include - -#include "vivid-tpg-colors.h" +#include /* sRGB colors with range [0-255] */ const struct color tpg_colors[TPG_COLOR_MAX] = { diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c similarity index 98% rename from drivers/media/platform/vivid/vivid-tpg.c rename to drivers/media/common/v4l2-tpg/v4l2-tpg-core.c index da862bb2e5f8..cf1dadd0be9e 100644 --- a/drivers/media/platform/vivid/vivid-tpg.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c @@ -1,5 +1,5 @@ /* - * vivid-tpg.c - Test Pattern Generator + * v4l2-tpg-core.c - Test Pattern Generator * * Note: gen_twopix and tpg_gen_text are based on code from vivi.c. See the * vivi.c source for the copyright information of those functions. @@ -20,7 +20,8 @@ * SOFTWARE. */ -#include "vivid-tpg.h" +#include +#include /* Must remain in sync with enum tpg_pattern */ const char * const tpg_pattern_strings[] = { @@ -48,6 +49,7 @@ const char * const tpg_pattern_strings[] = { "Noise", NULL }; +EXPORT_SYMBOL_GPL(tpg_pattern_strings); /* Must remain in sync with enum tpg_aspect */ const char * const tpg_aspect_strings[] = { @@ -58,6 +60,7 @@ const char * const tpg_aspect_strings[] = { "16x9 Anamorphic", NULL }; +EXPORT_SYMBOL_GPL(tpg_aspect_strings); /* * Sine table: sin[0] = 127 * sin(-180 degrees) @@ -93,6 +96,7 @@ void tpg_set_font(const u8 *f) { font8x16 = f; } +EXPORT_SYMBOL_GPL(tpg_set_font); void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h) { @@ -114,6 +118,7 @@ void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h) tpg->colorspace = V4L2_COLORSPACE_SRGB; tpg->perc_fill = 100; } +EXPORT_SYMBOL_GPL(tpg_init); int tpg_alloc(struct tpg_data *tpg, unsigned max_w) { @@ -150,6 +155,7 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w) } return 0; } +EXPORT_SYMBOL_GPL(tpg_alloc); void tpg_free(struct tpg_data *tpg) { @@ -174,6 +180,7 @@ void tpg_free(struct tpg_data *tpg) tpg->random_line[plane] = NULL; } } +EXPORT_SYMBOL_GPL(tpg_free); bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) { @@ -403,6 +410,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) } return true; } +EXPORT_SYMBOL_GPL(tpg_s_fourcc); void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop, const struct v4l2_rect *compose) @@ -418,6 +426,7 @@ void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop, tpg->scaled_width = 2; tpg->recalc_lines = true; } +EXPORT_SYMBOL_GPL(tpg_s_crop_compose); void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, u32 field) @@ -442,6 +451,7 @@ void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, (2 * tpg->hdownsampling[p]); tpg->recalc_square_border = true; } +EXPORT_SYMBOL_GPL(tpg_reset_source); static enum tpg_color tpg_get_textbg_color(struct tpg_data *tpg) { @@ -1250,6 +1260,7 @@ unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line) return 0; } } +EXPORT_SYMBOL_GPL(tpg_g_interleaved_plane); /* Return how many pattern lines are used by the current pattern. */ static unsigned tpg_get_pat_lines(const struct tpg_data *tpg) @@ -1725,6 +1736,7 @@ void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2], } } } +EXPORT_SYMBOL_GPL(tpg_gen_text); void tpg_update_mv_step(struct tpg_data *tpg) { @@ -1773,6 +1785,7 @@ void tpg_update_mv_step(struct tpg_data *tpg) if (factor < 0) tpg->mv_vert_step = tpg->src_height - tpg->mv_vert_step; } +EXPORT_SYMBOL_GPL(tpg_update_mv_step); /* Map the line number relative to the crop rectangle to a frame line number */ static unsigned tpg_calc_frameline(const struct tpg_data *tpg, unsigned src_y, @@ -1862,6 +1875,7 @@ void tpg_calc_text_basep(struct tpg_data *tpg, if (p == 0 && tpg->interleaved) tpg_calc_text_basep(tpg, basep, 1, vbuf); } +EXPORT_SYMBOL_GPL(tpg_calc_text_basep); static int tpg_pattern_avg(const struct tpg_data *tpg, unsigned pat1, unsigned pat2) @@ -1891,6 +1905,7 @@ void tpg_log_status(struct tpg_data *tpg) pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization); pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range); } +EXPORT_SYMBOL_GPL(tpg_log_status); /* * This struct contains common parameters used by both the drawing of the @@ -2296,6 +2311,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, vbuf + buf_line * params.stride); } } +EXPORT_SYMBOL_GPL(tpg_fill_plane_buffer); void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf) { @@ -2312,3 +2328,8 @@ void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf) offset += tpg_calc_plane_size(tpg, i); } } +EXPORT_SYMBOL_GPL(tpg_fillbuffer); + +MODULE_DESCRIPTION("V4L2 Test Pattern Generator"); +MODULE_AUTHOR("Hans Verkuil"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig index 0885e93ad436..f535f576913d 100644 --- a/drivers/media/platform/vivid/Kconfig +++ b/drivers/media/platform/vivid/Kconfig @@ -7,6 +7,7 @@ config VIDEO_VIVID select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select VIDEOBUF2_VMALLOC + select VIDEO_V4L2_TPG default n ---help--- Enables a virtual video driver. This driver emulates a webcam, diff --git a/drivers/media/platform/vivid/Makefile b/drivers/media/platform/vivid/Makefile index 756fc12851df..633c8a1b2c27 100644 --- a/drivers/media/platform/vivid/Makefile +++ b/drivers/media/platform/vivid/Makefile @@ -2,5 +2,5 @@ vivid-objs := vivid-core.o vivid-ctrls.o vivid-vid-common.o vivid-vbi-gen.o \ vivid-vid-cap.o vivid-vid-out.o vivid-kthread-cap.o vivid-kthread-out.o \ vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \ vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \ - vivid-osd.o vivid-tpg.o vivid-tpg-colors.o + vivid-osd.o obj-$(CONFIG_VIDEO_VIVID) += vivid.o diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h index 751c1ba391e9..776783bec227 100644 --- a/drivers/media/platform/vivid/vivid-core.h +++ b/drivers/media/platform/vivid/vivid-core.h @@ -25,7 +25,7 @@ #include #include #include -#include "vivid-tpg.h" +#include #include "vivid-rds-gen.h" #include "vivid-vbi-gen.h" diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.h b/include/media/v4l2-tpg-colors.h similarity index 93% rename from drivers/media/platform/vivid/vivid-tpg-colors.h rename to include/media/v4l2-tpg-colors.h index 4e5a76a1e25b..2a88d1fae0cd 100644 --- a/drivers/media/platform/vivid/vivid-tpg-colors.h +++ b/include/media/v4l2-tpg-colors.h @@ -1,5 +1,5 @@ /* - * vivid-color.h - Color definitions for the test pattern generator + * v4l2-tpg-colors.h - Color definitions for the test pattern generator * * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. * @@ -17,8 +17,8 @@ * SOFTWARE. */ -#ifndef _VIVID_COLORS_H_ -#define _VIVID_COLORS_H_ +#ifndef _V4L2_TPG_COLORS_H_ +#define _V4L2_TPG_COLORS_H_ struct color { unsigned char r, g, b; diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/include/media/v4l2-tpg.h similarity index 99% rename from drivers/media/platform/vivid/vivid-tpg.h rename to include/media/v4l2-tpg.h index 93fbaee69675..329bebfa930c 100644 --- a/drivers/media/platform/vivid/vivid-tpg.h +++ b/include/media/v4l2-tpg.h @@ -1,5 +1,5 @@ /* - * vivid-tpg.h - Test Pattern Generator + * v4l2-tpg.h - Test Pattern Generator * * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. * @@ -17,8 +17,8 @@ * SOFTWARE. */ -#ifndef _VIVID_TPG_H_ -#define _VIVID_TPG_H_ +#ifndef _V4L2_TPG_H_ +#define _V4L2_TPG_H_ #include #include @@ -26,8 +26,7 @@ #include #include #include - -#include "vivid-tpg-colors.h" +#include enum tpg_pattern { TPG_PAT_75_COLORBAR, -- GitLab From e6f268ef3687862b0e9f01f7b3706b54f75b82ab Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 20 Apr 2016 15:32:54 -0400 Subject: [PATCH 3735/9938] net: nla_align_64bit() needs to test the right pointer. Netlink messages are appended, one object at a time, to the end of the SKB. Therefore we need to test skb_tail_pointer() not skb->data for alignment. Fixes: 35c5845957c7 ("net: Add helpers for 64-bit aligning netlink attributes.") Signed-off-by: David S. Miller --- include/net/netlink.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index cf95df1fa14b..3c1fd92a52c8 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -1250,7 +1250,7 @@ static inline int nla_align_64bit(struct sk_buff *skb, int padattr) * nlattr header for next attribute, will make nla_data() * 8-byte aligned. */ - if (IS_ALIGNED((unsigned long)skb->data, 8) && + if (IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8) && !nla_reserve(skb, padattr, 0)) return -EMSGSIZE; #endif -- GitLab From 9257b4a206fc0229dd5f84b78e4d1ebf3f91d270 Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 11:34:11 +0300 Subject: [PATCH 3736/9938] iommu/iova: introduce per-cpu caching to iova allocation IOVA allocation has two problems that impede high-throughput I/O. First, it can do a linear search over the allocated IOVA ranges. Second, the rbtree spinlock that serializes IOVA allocations becomes contended. Address these problems by creating an API for caching allocated IOVA ranges, so that the IOVA allocator isn't accessed frequently. This patch adds a per-CPU cache, from which CPUs can alloc/free IOVAs without taking the rbtree spinlock. The per-CPU caches are backed by a global cache, to avoid invoking the (linear-time) IOVA allocator without needing to make the per-CPU cache size excessive. This design is based on magazines, as described in "Magazines and Vmem: Extending the Slab Allocator to Many CPUs and Arbitrary Resources" (currently available at https://www.usenix.org/legacy/event/usenix01/bonwick.html) Adding caching on top of the existing rbtree allocator maintains the property that IOVAs are densely packed in the IO virtual address space, which is important for keeping IOMMU page table usage low. To keep the cache size reasonable, we bound the IOVA space a CPU can cache by 32 MiB (we cache a bounded number of IOVA ranges, and only ranges of size <= 128 KiB). The shared global cache is bounded at 4 MiB of IOVA space. Signed-off-by: Omer Peleg [mad@cs.technion.ac.il: rebased, cleaned up and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin [dwmw2: split out VT-d part into a separate patch] Signed-off-by: David Woodhouse --- drivers/iommu/iova.c | 417 ++++++++++++++++++++++++++++++++++++++++--- include/linux/iova.h | 23 ++- 2 files changed, 414 insertions(+), 26 deletions(-) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index fa0adef32bd6..ba764a0835d3 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -20,6 +20,17 @@ #include #include #include +#include +#include + +static bool iova_rcache_insert(struct iova_domain *iovad, + unsigned long pfn, + unsigned long size); +static unsigned long iova_rcache_get(struct iova_domain *iovad, + unsigned long size, + unsigned long limit_pfn); +static void init_iova_rcaches(struct iova_domain *iovad); +static void free_iova_rcaches(struct iova_domain *iovad); void init_iova_domain(struct iova_domain *iovad, unsigned long granule, @@ -38,6 +49,7 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule, iovad->granule = granule; iovad->start_pfn = start_pfn; iovad->dma_32bit_pfn = pfn_32bit; + init_iova_rcaches(iovad); } EXPORT_SYMBOL_GPL(init_iova_domain); @@ -291,33 +303,18 @@ alloc_iova(struct iova_domain *iovad, unsigned long size, } EXPORT_SYMBOL_GPL(alloc_iova); -/** - * find_iova - find's an iova for a given pfn - * @iovad: - iova domain in question. - * @pfn: - page frame number - * This function finds and returns an iova belonging to the - * given doamin which matches the given pfn. - */ -struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn) +static struct iova * +private_find_iova(struct iova_domain *iovad, unsigned long pfn) { - unsigned long flags; - struct rb_node *node; + struct rb_node *node = iovad->rbroot.rb_node; + + assert_spin_locked(&iovad->iova_rbtree_lock); - /* Take the lock so that no other thread is manipulating the rbtree */ - spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); - node = iovad->rbroot.rb_node; while (node) { struct iova *iova = container_of(node, struct iova, node); /* If pfn falls within iova's range, return iova */ if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) { - spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); - /* We are not holding the lock while this iova - * is referenced by the caller as the same thread - * which called this function also calls __free_iova() - * and it is by design that only one thread can possibly - * reference a particular iova and hence no conflict. - */ return iova; } @@ -327,9 +324,35 @@ struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn) node = node->rb_right; } - spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); return NULL; } + +static void private_free_iova(struct iova_domain *iovad, struct iova *iova) +{ + assert_spin_locked(&iovad->iova_rbtree_lock); + __cached_rbnode_delete_update(iovad, iova); + rb_erase(&iova->node, &iovad->rbroot); + free_iova_mem(iova); +} + +/** + * find_iova - finds an iova for a given pfn + * @iovad: - iova domain in question. + * @pfn: - page frame number + * This function finds and returns an iova belonging to the + * given doamin which matches the given pfn. + */ +struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn) +{ + unsigned long flags; + struct iova *iova; + + /* Take the lock so that no other thread is manipulating the rbtree */ + spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + iova = private_find_iova(iovad, pfn); + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + return iova; +} EXPORT_SYMBOL_GPL(find_iova); /** @@ -344,10 +367,8 @@ __free_iova(struct iova_domain *iovad, struct iova *iova) unsigned long flags; spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); - __cached_rbnode_delete_update(iovad, iova); - rb_erase(&iova->node, &iovad->rbroot); + private_free_iova(iovad, iova); spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); - free_iova_mem(iova); } EXPORT_SYMBOL_GPL(__free_iova); @@ -369,6 +390,63 @@ free_iova(struct iova_domain *iovad, unsigned long pfn) } EXPORT_SYMBOL_GPL(free_iova); +/** + * alloc_iova_fast - allocates an iova from rcache + * @iovad: - iova domain in question + * @size: - size of page frames to allocate + * @limit_pfn: - max limit address + * This function tries to satisfy an iova allocation from the rcache, + * and falls back to regular allocation on failure. +*/ +unsigned long +alloc_iova_fast(struct iova_domain *iovad, unsigned long size, + unsigned long limit_pfn) +{ + bool flushed_rcache = false; + unsigned long iova_pfn; + struct iova *new_iova; + + iova_pfn = iova_rcache_get(iovad, size, limit_pfn); + if (iova_pfn) + return iova_pfn; + +retry: + new_iova = alloc_iova(iovad, size, limit_pfn, true); + if (!new_iova) { + unsigned int cpu; + + if (flushed_rcache) + return 0; + + /* Try replenishing IOVAs by flushing rcache. */ + flushed_rcache = true; + for_each_online_cpu(cpu) + free_cpu_cached_iovas(cpu, iovad); + goto retry; + } + + return new_iova->pfn_lo; +} +EXPORT_SYMBOL_GPL(alloc_iova_fast); + +/** + * free_iova_fast - free iova pfn range into rcache + * @iovad: - iova domain in question. + * @pfn: - pfn that is allocated previously + * @size: - # of pages in range + * This functions frees an iova range by trying to put it into the rcache, + * falling back to regular iova deallocation via free_iova() if this fails. + */ +void +free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size) +{ + if (iova_rcache_insert(iovad, pfn, size)) + return; + + free_iova(iovad, pfn); +} +EXPORT_SYMBOL_GPL(free_iova_fast); + /** * put_iova_domain - destroys the iova doamin * @iovad: - iova domain in question. @@ -379,6 +457,7 @@ void put_iova_domain(struct iova_domain *iovad) struct rb_node *node; unsigned long flags; + free_iova_rcaches(iovad); spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); node = rb_first(&iovad->rbroot); while (node) { @@ -550,5 +629,295 @@ split_and_remove_iova(struct iova_domain *iovad, struct iova *iova, return NULL; } +/* + * Magazine caches for IOVA ranges. For an introduction to magazines, + * see the USENIX 2001 paper "Magazines and Vmem: Extending the Slab + * Allocator to Many CPUs and Arbitrary Resources" by Bonwick and Adams. + * For simplicity, we use a static magazine size and don't implement the + * dynamic size tuning described in the paper. + */ + +#define IOVA_MAG_SIZE 128 + +struct iova_magazine { + unsigned long size; + unsigned long pfns[IOVA_MAG_SIZE]; +}; + +struct iova_cpu_rcache { + spinlock_t lock; + struct iova_magazine *loaded; + struct iova_magazine *prev; +}; + +static struct iova_magazine *iova_magazine_alloc(gfp_t flags) +{ + return kzalloc(sizeof(struct iova_magazine), flags); +} + +static void iova_magazine_free(struct iova_magazine *mag) +{ + kfree(mag); +} + +static void +iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad) +{ + unsigned long flags; + int i; + + if (!mag) + return; + + spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + + for (i = 0 ; i < mag->size; ++i) { + struct iova *iova = private_find_iova(iovad, mag->pfns[i]); + + BUG_ON(!iova); + private_free_iova(iovad, iova); + } + + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + + mag->size = 0; +} + +static bool iova_magazine_full(struct iova_magazine *mag) +{ + return (mag && mag->size == IOVA_MAG_SIZE); +} + +static bool iova_magazine_empty(struct iova_magazine *mag) +{ + return (!mag || mag->size == 0); +} + +static unsigned long iova_magazine_pop(struct iova_magazine *mag, + unsigned long limit_pfn) +{ + BUG_ON(iova_magazine_empty(mag)); + + if (mag->pfns[mag->size - 1] >= limit_pfn) + return 0; + + return mag->pfns[--mag->size]; +} + +static void iova_magazine_push(struct iova_magazine *mag, unsigned long pfn) +{ + BUG_ON(iova_magazine_full(mag)); + + mag->pfns[mag->size++] = pfn; +} + +static void init_iova_rcaches(struct iova_domain *iovad) +{ + struct iova_cpu_rcache *cpu_rcache; + struct iova_rcache *rcache; + unsigned int cpu; + int i; + + for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) { + rcache = &iovad->rcaches[i]; + spin_lock_init(&rcache->lock); + rcache->depot_size = 0; + rcache->cpu_rcaches = __alloc_percpu(sizeof(*cpu_rcache), cache_line_size()); + if (WARN_ON(!rcache->cpu_rcaches)) + continue; + for_each_possible_cpu(cpu) { + cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu); + spin_lock_init(&cpu_rcache->lock); + cpu_rcache->loaded = iova_magazine_alloc(GFP_KERNEL); + cpu_rcache->prev = iova_magazine_alloc(GFP_KERNEL); + } + } +} + +/* + * Try inserting IOVA range starting with 'iova_pfn' into 'rcache', and + * return true on success. Can fail if rcache is full and we can't free + * space, and free_iova() (our only caller) will then return the IOVA + * range to the rbtree instead. + */ +static bool __iova_rcache_insert(struct iova_domain *iovad, + struct iova_rcache *rcache, + unsigned long iova_pfn) +{ + struct iova_magazine *mag_to_free = NULL; + struct iova_cpu_rcache *cpu_rcache; + bool can_insert = false; + unsigned long flags; + + cpu_rcache = this_cpu_ptr(rcache->cpu_rcaches); + spin_lock_irqsave(&cpu_rcache->lock, flags); + + if (!iova_magazine_full(cpu_rcache->loaded)) { + can_insert = true; + } else if (!iova_magazine_full(cpu_rcache->prev)) { + swap(cpu_rcache->prev, cpu_rcache->loaded); + can_insert = true; + } else { + struct iova_magazine *new_mag = iova_magazine_alloc(GFP_ATOMIC); + + if (new_mag) { + spin_lock(&rcache->lock); + if (rcache->depot_size < MAX_GLOBAL_MAGS) { + rcache->depot[rcache->depot_size++] = + cpu_rcache->loaded; + } else { + mag_to_free = cpu_rcache->loaded; + } + spin_unlock(&rcache->lock); + + cpu_rcache->loaded = new_mag; + can_insert = true; + } + } + + if (can_insert) + iova_magazine_push(cpu_rcache->loaded, iova_pfn); + + spin_unlock_irqrestore(&cpu_rcache->lock, flags); + + if (mag_to_free) { + iova_magazine_free_pfns(mag_to_free, iovad); + iova_magazine_free(mag_to_free); + } + + return can_insert; +} + +static bool iova_rcache_insert(struct iova_domain *iovad, unsigned long pfn, + unsigned long size) +{ + unsigned int log_size = order_base_2(size); + + if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE) + return false; + + return __iova_rcache_insert(iovad, &iovad->rcaches[log_size], pfn); +} + +/* + * Caller wants to allocate a new IOVA range from 'rcache'. If we can + * satisfy the request, return a matching non-NULL range and remove + * it from the 'rcache'. + */ +static unsigned long __iova_rcache_get(struct iova_rcache *rcache, + unsigned long limit_pfn) +{ + struct iova_cpu_rcache *cpu_rcache; + unsigned long iova_pfn = 0; + bool has_pfn = false; + unsigned long flags; + + cpu_rcache = this_cpu_ptr(rcache->cpu_rcaches); + spin_lock_irqsave(&cpu_rcache->lock, flags); + + if (!iova_magazine_empty(cpu_rcache->loaded)) { + has_pfn = true; + } else if (!iova_magazine_empty(cpu_rcache->prev)) { + swap(cpu_rcache->prev, cpu_rcache->loaded); + has_pfn = true; + } else { + spin_lock(&rcache->lock); + if (rcache->depot_size > 0) { + iova_magazine_free(cpu_rcache->loaded); + cpu_rcache->loaded = rcache->depot[--rcache->depot_size]; + has_pfn = true; + } + spin_unlock(&rcache->lock); + } + + if (has_pfn) + iova_pfn = iova_magazine_pop(cpu_rcache->loaded, limit_pfn); + + spin_unlock_irqrestore(&cpu_rcache->lock, flags); + + return iova_pfn; +} + +/* + * Try to satisfy IOVA allocation range from rcache. Fail if requested + * size is too big or the DMA limit we are given isn't satisfied by the + * top element in the magazine. + */ +static unsigned long iova_rcache_get(struct iova_domain *iovad, + unsigned long size, + unsigned long limit_pfn) +{ + unsigned int log_size = order_base_2(size); + + if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE) + return 0; + + return __iova_rcache_get(&iovad->rcaches[log_size], limit_pfn); +} + +/* + * Free a cpu's rcache. + */ +static void free_cpu_iova_rcache(unsigned int cpu, struct iova_domain *iovad, + struct iova_rcache *rcache) +{ + struct iova_cpu_rcache *cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu); + unsigned long flags; + + spin_lock_irqsave(&cpu_rcache->lock, flags); + + iova_magazine_free_pfns(cpu_rcache->loaded, iovad); + iova_magazine_free(cpu_rcache->loaded); + + iova_magazine_free_pfns(cpu_rcache->prev, iovad); + iova_magazine_free(cpu_rcache->prev); + + spin_unlock_irqrestore(&cpu_rcache->lock, flags); +} + +/* + * free rcache data structures. + */ +static void free_iova_rcaches(struct iova_domain *iovad) +{ + struct iova_rcache *rcache; + unsigned long flags; + unsigned int cpu; + int i, j; + + for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) { + rcache = &iovad->rcaches[i]; + for_each_possible_cpu(cpu) + free_cpu_iova_rcache(cpu, iovad, rcache); + spin_lock_irqsave(&rcache->lock, flags); + free_percpu(rcache->cpu_rcaches); + for (j = 0; j < rcache->depot_size; ++j) { + iova_magazine_free_pfns(rcache->depot[j], iovad); + iova_magazine_free(rcache->depot[j]); + } + spin_unlock_irqrestore(&rcache->lock, flags); + } +} + +/* + * free all the IOVA ranges cached by a cpu (used when cpu is unplugged) + */ +void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad) +{ + struct iova_cpu_rcache *cpu_rcache; + struct iova_rcache *rcache; + unsigned long flags; + int i; + + for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) { + rcache = &iovad->rcaches[i]; + cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu); + spin_lock_irqsave(&cpu_rcache->lock, flags); + iova_magazine_free_pfns(cpu_rcache->loaded, iovad); + iova_magazine_free_pfns(cpu_rcache->prev, iovad); + spin_unlock_irqrestore(&cpu_rcache->lock, flags); + } +} + MODULE_AUTHOR("Anil S Keshavamurthy "); MODULE_LICENSE("GPL"); diff --git a/include/linux/iova.h b/include/linux/iova.h index 92f7177db2ce..f27bb2c62fca 100644 --- a/include/linux/iova.h +++ b/include/linux/iova.h @@ -19,8 +19,21 @@ /* iova structure */ struct iova { struct rb_node node; - unsigned long pfn_hi; /* IOMMU dish out addr hi */ - unsigned long pfn_lo; /* IOMMU dish out addr lo */ + unsigned long pfn_hi; /* Highest allocated pfn */ + unsigned long pfn_lo; /* Lowest allocated pfn */ +}; + +struct iova_magazine; +struct iova_cpu_rcache; + +#define IOVA_RANGE_CACHE_MAX_SIZE 6 /* log of max cached IOVA range size (in pages) */ +#define MAX_GLOBAL_MAGS 32 /* magazines per bin */ + +struct iova_rcache { + spinlock_t lock; + unsigned long depot_size; + struct iova_magazine *depot[MAX_GLOBAL_MAGS]; + struct iova_cpu_rcache __percpu *cpu_rcaches; }; /* holds all the iova translations for a domain */ @@ -31,6 +44,7 @@ struct iova_domain { unsigned long granule; /* pfn granularity for this domain */ unsigned long start_pfn; /* Lower limit for this domain */ unsigned long dma_32bit_pfn; + struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE]; /* IOVA range caches */ }; static inline unsigned long iova_size(struct iova *iova) @@ -78,6 +92,10 @@ void __free_iova(struct iova_domain *iovad, struct iova *iova); struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size, unsigned long limit_pfn, bool size_aligned); +void free_iova_fast(struct iova_domain *iovad, unsigned long pfn, + unsigned long size); +unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size, + unsigned long limit_pfn); struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo, unsigned long pfn_hi); void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to); @@ -87,5 +105,6 @@ struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn); void put_iova_domain(struct iova_domain *iovad); struct iova *split_and_remove_iova(struct iova_domain *iovad, struct iova *iova, unsigned long pfn_lo, unsigned long pfn_hi); +void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad); #endif -- GitLab From 10c9ead9f3c6bb24bddc9a96681f7d58e6623966 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Wed, 20 Apr 2016 08:43:43 -0700 Subject: [PATCH 3737/9938] rtnetlink: add new RTM_GETSTATS message to dump link stats This patch adds a new RTM_GETSTATS message to query link stats via netlink from the kernel. RTM_NEWLINK also dumps stats today, but RTM_NEWLINK returns a lot more than just stats and is expensive in some cases when frequent polling for stats from userspace is a common operation. RTM_GETSTATS is an attempt to provide a light weight netlink message to explicity query only link stats from the kernel on an interface. The idea is to also keep it extensible so that new kinds of stats can be added to it in the future. This patch adds the following attribute for NETDEV stats: struct nla_policy ifla_stats_policy[IFLA_STATS_MAX + 1] = { [IFLA_STATS_LINK_64] = { .len = sizeof(struct rtnl_link_stats64) }, }; Like any other rtnetlink message, RTM_GETSTATS can be used to get stats of a single interface or all interfaces with NLM_F_DUMP. Future possible new types of stat attributes: link af stats: - IFLA_STATS_LINK_IPV6 (nested. for ipv6 stats) - IFLA_STATS_LINK_MPLS (nested. for mpls/mdev stats) extended stats: - IFLA_STATS_LINK_EXTENDED (nested. extended software netdev stats like bridge, vlan, vxlan etc) - IFLA_STATS_LINK_HW_EXTENDED (nested. extended hardware stats which are available via ethtool today) This patch also declares a filter mask for all stat attributes. User has to provide a mask of stats attributes to query. filter mask can be specified in the new hdr 'struct if_stats_msg' for stats messages. Other important field in the header is the ifindex. This api can also include attributes for global stats (eg tcp) in the future. When global stats are included in a stats msg, the ifindex in the header must be zero. A single stats message cannot contain both global and netdev specific stats. To easily distinguish them, netdev specific stat attributes name are prefixed with IFLA_STATS_LINK_ Without any attributes in the filter_mask, no stats will be returned. This patch has been tested with mofified iproute2 ifstat. Suggested-by: Jamal Hadi Salim Signed-off-by: Roopa Prabhu Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 23 +++++ include/uapi/linux/rtnetlink.h | 5 ++ net/core/rtnetlink.c | 158 +++++++++++++++++++++++++++++++++ security/selinux/nlmsgtab.c | 4 +- 4 files changed, 189 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index af8fd58b4006..ba69d4447249 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -782,4 +782,27 @@ enum { #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1) +/* STATS section */ + +struct if_stats_msg { + __u8 family; + __u8 pad1; + __u16 pad2; + __u32 ifindex; + __u32 filter_mask; +}; + +/* A stats attribute can be netdev specific or a global stat. + * For netdev stats, lets use the prefix IFLA_STATS_LINK_* + */ +enum { + IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */ + IFLA_STATS_LINK_64, + __IFLA_STATS_MAX, +}; + +#define IFLA_STATS_MAX (__IFLA_STATS_MAX - 1) + +#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1)) + #endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index ca764b5da86d..cc885c4e9065 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -139,6 +139,11 @@ enum { RTM_GETNSID = 90, #define RTM_GETNSID RTM_GETNSID + RTM_NEWSTATS = 92, +#define RTM_NEWSTATS RTM_NEWSTATS + RTM_GETSTATS = 94, +#define RTM_GETSTATS RTM_GETSTATS + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d3694a13c85a..4a47a9aceb1d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3449,6 +3449,161 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) return err; } +static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev, + int type, u32 pid, u32 seq, u32 change, + unsigned int flags, unsigned int filter_mask) +{ + struct if_stats_msg *ifsm; + struct nlmsghdr *nlh; + struct nlattr *attr; + + ASSERT_RTNL(); + + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifsm), flags); + if (!nlh) + return -EMSGSIZE; + + ifsm = nlmsg_data(nlh); + ifsm->ifindex = dev->ifindex; + ifsm->filter_mask = filter_mask; + + if (filter_mask & IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_64)) { + struct rtnl_link_stats64 *sp; + int err; + + /* if necessary, add a zero length NOP attribute so that + * IFLA_STATS_LINK_64 will be 64-bit aligned + */ + err = nla_align_64bit(skb, IFLA_STATS_UNSPEC); + if (err) + goto nla_put_failure; + + attr = nla_reserve(skb, IFLA_STATS_LINK_64, + sizeof(struct rtnl_link_stats64)); + if (!attr) + goto nla_put_failure; + + sp = nla_data(attr); + dev_get_stats(dev, sp); + } + + nlmsg_end(skb, nlh); + + return 0; + +nla_put_failure: + nlmsg_cancel(skb, nlh); + + return -EMSGSIZE; +} + +static const struct nla_policy ifla_stats_policy[IFLA_STATS_MAX + 1] = { + [IFLA_STATS_LINK_64] = { .len = sizeof(struct rtnl_link_stats64) }, +}; + +static size_t if_nlmsg_stats_size(const struct net_device *dev, + u32 filter_mask) +{ + size_t size = 0; + + if (filter_mask & IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_64)) + size += nla_total_size_64bit(sizeof(struct rtnl_link_stats64)); + + return size; +} + +static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh) +{ + struct net *net = sock_net(skb->sk); + struct if_stats_msg *ifsm; + struct net_device *dev = NULL; + struct sk_buff *nskb; + u32 filter_mask; + int err; + + ifsm = nlmsg_data(nlh); + if (ifsm->ifindex > 0) + dev = __dev_get_by_index(net, ifsm->ifindex); + else + return -EINVAL; + + if (!dev) + return -ENODEV; + + filter_mask = ifsm->filter_mask; + if (!filter_mask) + return -EINVAL; + + nskb = nlmsg_new(if_nlmsg_stats_size(dev, filter_mask), GFP_KERNEL); + if (!nskb) + return -ENOBUFS; + + err = rtnl_fill_statsinfo(nskb, dev, RTM_NEWSTATS, + NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, + 0, filter_mask); + if (err < 0) { + /* -EMSGSIZE implies BUG in if_nlmsg_stats_size */ + WARN_ON(err == -EMSGSIZE); + kfree_skb(nskb); + } else { + err = rtnl_unicast(nskb, net, NETLINK_CB(skb).portid); + } + + return err; +} + +static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct net *net = sock_net(skb->sk); + struct if_stats_msg *ifsm; + int h, s_h; + int idx = 0, s_idx; + struct net_device *dev; + struct hlist_head *head; + unsigned int flags = NLM_F_MULTI; + u32 filter_mask = 0; + int err; + + s_h = cb->args[0]; + s_idx = cb->args[1]; + + cb->seq = net->dev_base_seq; + + ifsm = nlmsg_data(cb->nlh); + filter_mask = ifsm->filter_mask; + if (!filter_mask) + return -EINVAL; + + for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { + idx = 0; + head = &net->dev_index_head[h]; + hlist_for_each_entry(dev, head, index_hlist) { + if (idx < s_idx) + goto cont; + err = rtnl_fill_statsinfo(skb, dev, RTM_NEWSTATS, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, 0, + flags, filter_mask); + /* If we ran out of room on the first message, + * we're in trouble + */ + WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); + + if (err < 0) + goto out; + + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +cont: + idx++; + } + } +out: + cb->args[1] = idx; + cb->args[0] = h; + + return skb->len; +} + /* Process one rtnetlink message. */ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) @@ -3598,4 +3753,7 @@ void __init rtnetlink_init(void) rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL); rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, NULL); rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL); + + rtnl_register(PF_UNSPEC, RTM_GETSTATS, rtnl_stats_get, rtnl_stats_dump, + NULL); } diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 8495b9368190..2ca9cde939d4 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -76,6 +76,8 @@ static struct nlmsg_perm nlmsg_route_perms[] = { RTM_NEWNSID, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_DELNSID, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_GETNSID, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWSTATS, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_GETSTATS, NETLINK_ROUTE_SOCKET__NLMSG_READ }, }; static struct nlmsg_perm nlmsg_tcpdiag_perms[] = @@ -155,7 +157,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) switch (sclass) { case SECCLASS_NETLINK_ROUTE_SOCKET: /* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */ - BUILD_BUG_ON(RTM_MAX != (RTM_NEWNSID + 3)); + BUILD_BUG_ON(RTM_MAX != (RTM_NEWSTATS + 3)); err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms, sizeof(nlmsg_route_perms)); break; -- GitLab From 22e2f9fa63b092923873fc8a52955151f4d83274 Mon Sep 17 00:00:00 2001 From: Omer Peleg Date: Wed, 20 Apr 2016 11:34:11 +0300 Subject: [PATCH 3738/9938] iommu/vt-d: Use per-cpu IOVA caching Commit 9257b4a2 ('iommu/iova: introduce per-cpu caching to iova allocation') introduced per-CPU IOVA caches to massively improve scalability. Use them. Signed-off-by: Omer Peleg [mad@cs.technion.ac.il: rebased, cleaned up and reworded the commit message] Signed-off-by: Adam Morrison Reviewed-by: Shaohua Li Reviewed-by: Ben Serebrin [dwmw2: split out VT-d part into a separate patch] Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 47 +++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a8babc43e6d4..76e833278db0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3357,7 +3357,7 @@ static unsigned long intel_alloc_iova(struct device *dev, struct dmar_domain *domain, unsigned long nrpages, uint64_t dma_mask) { - struct iova *iova = NULL; + unsigned long iova_pfn = 0; /* Restrict dma_mask to the width that the iommu can handle */ dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); @@ -3370,19 +3370,19 @@ static unsigned long intel_alloc_iova(struct device *dev, * DMA_BIT_MASK(32) and if that fails then try allocating * from higher range */ - iova = alloc_iova(&domain->iovad, nrpages, - IOVA_PFN(DMA_BIT_MASK(32)), 1); - if (iova) - return iova->pfn_lo; + iova_pfn = alloc_iova_fast(&domain->iovad, nrpages, + IOVA_PFN(DMA_BIT_MASK(32))); + if (iova_pfn) + return iova_pfn; } - iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); - if (unlikely(!iova)) { + iova_pfn = alloc_iova_fast(&domain->iovad, nrpages, IOVA_PFN(dma_mask)); + if (unlikely(!iova_pfn)) { pr_err("Allocating %ld-page iova for %s failed", nrpages, dev_name(dev)); return 0; } - return iova->pfn_lo; + return iova_pfn; } static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev) @@ -3536,7 +3536,7 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, error: if (iova_pfn) - free_iova(&domain->iovad, iova_pfn); + free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size)); pr_err("Device %s request: %zx@%llx dir %d --- failed\n", dev_name(dev), size, (unsigned long long)paddr, dir); return 0; @@ -3591,7 +3591,7 @@ static void flush_unmaps(struct deferred_flush_data *flush_data) iommu_flush_dev_iotlb(domain, (uint64_t)iova_pfn << PAGE_SHIFT, mask); } - free_iova(&domain->iovad, iova_pfn); + free_iova_fast(&domain->iovad, iova_pfn, nrpages); if (freelist) dma_free_pagelist(freelist); } @@ -3691,7 +3691,7 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) iommu_flush_iotlb_psi(iommu, domain, start_pfn, nrpages, !freelist, 0); /* free iova */ - free_iova(&domain->iovad, iova_pfn); + free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages)); dma_free_pagelist(freelist); } else { add_unmap(domain, iova_pfn, nrpages, freelist); @@ -3849,7 +3849,7 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele if (unlikely(ret)) { dma_pte_free_pagetable(domain, start_vpfn, start_vpfn + size - 1); - free_iova(&domain->iovad, iova_pfn); + free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size)); return 0; } @@ -4588,6 +4588,28 @@ static struct notifier_block intel_iommu_memory_nb = { .priority = 0 }; +static void free_all_cpu_cached_iovas(unsigned int cpu) +{ + int i; + + for (i = 0; i < g_num_of_iommus; i++) { + struct intel_iommu *iommu = g_iommus[i]; + struct dmar_domain *domain; + u16 did; + + if (!iommu) + continue; + + for (did = 0; did < 0xffff; did++) { + domain = get_iommu_domain(iommu, did); + + if (!domain) + continue; + free_cpu_cached_iovas(cpu, &domain->iovad); + } + } +} + static int intel_iommu_cpu_notifier(struct notifier_block *nfb, unsigned long action, void *v) { @@ -4596,6 +4618,7 @@ static int intel_iommu_cpu_notifier(struct notifier_block *nfb, switch (action) { case CPU_DEAD: case CPU_DEAD_FROZEN: + free_all_cpu_cached_iovas(cpu); flush_unmaps_timeout(cpu); break; } -- GitLab From b9e4c5e6ee26a906fa8514467b5abb9655c3ffdc Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 20:37:02 -0700 Subject: [PATCH 3739/9938] ARM: dts: qcom: apq8064: Add syscon for sic-non-secure Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 65d0e8d98259..4dc7e2c740af 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -212,6 +212,11 @@ regulator; }; + sps_sic_non_secure: sps-sic-non-secure@12100000 { + compatible = "syscon"; + reg = <0x12100000 0x10000>; + }; + gsbi1: gsbi@12440000 { status = "disabled"; compatible = "qcom,gsbi-v1.0.0"; -- GitLab From b4d4582fa6959ee494b2146522f1edd72ba6218d Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 20:37:03 -0700 Subject: [PATCH 3740/9938] ARM: dts: qcom: apq8064: Add complete smsm node Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064.dtsi | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 4dc7e2c740af..24c3c3581917 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -124,6 +124,55 @@ hwlocks = <&sfpb_mutex 3>; }; + smsm { + compatible = "qcom,smsm"; + + #address-cells = <1>; + #size-cells = <0>; + + qcom,ipc-1 = <&l2cc 8 4>; + qcom,ipc-2 = <&l2cc 8 14>; + qcom,ipc-3 = <&l2cc 8 23>; + qcom,ipc-4 = <&sps_sic_non_secure 0x4094 0>; + + apps_smsm: apps@0 { + reg = <0>; + #qcom,state-cells = <1>; + }; + + modem_smsm: modem@1 { + reg = <1>; + interrupts = <0 38 IRQ_TYPE_EDGE_RISING>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + q6_smsm: q6@2 { + reg = <2>; + interrupts = <0 89 IRQ_TYPE_EDGE_RISING>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + wcnss_smsm: wcnss@3 { + reg = <3>; + interrupts = <0 204 IRQ_TYPE_EDGE_RISING>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + dsps_smsm: dsps@4 { + reg = <4>; + interrupts = <0 137 IRQ_TYPE_EDGE_RISING>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc { #address-cells = <1>; #size-cells = <1>; -- GitLab From 2afc5287c50e013c46e07413c066920dc7f55a91 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 28 Mar 2016 20:37:04 -0700 Subject: [PATCH 3741/9938] ARM: dts: qcom: apq8064: Add smd node and all edges Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064.dtsi | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 24c3c3581917..042a8903bdb1 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -124,6 +124,46 @@ hwlocks = <&sfpb_mutex 3>; }; + smd { + compatible = "qcom,smd"; + + modem@0 { + interrupts = <0 37 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&l2cc 8 3>; + qcom,smd-edge = <0>; + + status = "disabled"; + }; + + q6@1 { + interrupts = <0 90 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&l2cc 8 15>; + qcom,smd-edge = <1>; + + status = "disabled"; + }; + + dsps@3 { + interrupts = <0 138 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&sps_sic_non_secure 0x4080 0>; + qcom,smd-edge = <3>; + + status = "disabled"; + }; + + riva@6 { + interrupts = <0 198 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&l2cc 8 25>; + qcom,smd-edge = <6>; + + status = "disabled"; + }; + }; + smsm { compatible = "qcom,smsm"; -- GitLab From 67b5ad57df3537aa479010af1581e8c4edf580e4 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:50 +0100 Subject: [PATCH 3742/9938] ARM: dts: apq8064: fix the pinctrls for i2c and spi This patch fixes pinctrls for spi and i2c nodes whose default and sleep states are together, which is incorrect. Without this patch i2c/spi would not be functional. Signed-off-by: Srinivas Kandagatla Acked-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064.dtsi | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 042a8903bdb1..18637c06566c 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -321,7 +321,8 @@ gsbi1_i2c: i2c@12460000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c1_pins &i2c1_pins_sleep>; + pinctrl-0 = <&i2c1_pins>; + pinctrl-1 = <&i2c1_pins_sleep>; pinctrl-names = "default", "sleep"; reg = <0x12460000 0x1000>; interrupts = <0 194 IRQ_TYPE_NONE>; @@ -349,7 +350,8 @@ gsbi2_i2c: i2c@124a0000 { compatible = "qcom,i2c-qup-v1.1.1"; reg = <0x124a0000 0x1000>; - pinctrl-0 = <&i2c2_pins &i2c2_pins_sleep>; + pinctrl-0 = <&i2c2_pins>; + pinctrl-1 = <&i2c2_pins_sleep>; pinctrl-names = "default", "sleep"; interrupts = <0 196 IRQ_TYPE_NONE>; clocks = <&gcc GSBI2_QUP_CLK>, <&gcc GSBI2_H_CLK>; @@ -371,7 +373,8 @@ ranges; gsbi3_i2c: i2c@16280000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c3_pins &i2c3_pins_sleep>; + pinctrl-0 = <&i2c3_pins>; + pinctrl-1 = <&i2c3_pins_sleep>; pinctrl-names = "default", "sleep"; reg = <0x16280000 0x1000>; interrupts = ; @@ -396,7 +399,8 @@ gsbi4_i2c: i2c@16380000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c4_pins &i2c4_pins_sleep>; + pinctrl-0 = <&i2c4_pins>; + pinctrl-1 = <&i2c4_pins_sleep>; pinctrl-names = "default", "sleep"; reg = <0x16380000 0x1000>; interrupts = ; @@ -431,7 +435,8 @@ compatible = "qcom,spi-qup-v1.1.1"; reg = <0x1a280000 0x1000>; interrupts = <0 155 0>; - pinctrl-0 = <&spi5_default &spi5_sleep>; + pinctrl-0 = <&spi5_default>; + pinctrl-1 = <&spi5_sleep>; pinctrl-names = "default", "sleep"; clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>; clock-names = "core", "iface"; @@ -464,7 +469,8 @@ gsbi6_i2c: i2c@16580000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c6_pins &i2c6_pins_sleep>; + pinctrl-0 = <&i2c6_pins>; + pinctrl-1 = <&i2c6_pins_sleep>; pinctrl-names = "default", "sleep"; reg = <0x16580000 0x1000>; interrupts = ; -- GitLab From 12861674c99100b77dc78ed5037e4e1a5b95b0d5 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:51 +0100 Subject: [PATCH 3743/9938] ARM: dts: apq8064: add support to gsbi1 uart This patch adds support to gsbi1 uart and its pinctrls nodes. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064-pins.dtsi | 14 ++++++++++++++ arch/arm/boot/dts/qcom-apq8064.dtsi | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-pins.dtsi b/arch/arm/boot/dts/qcom-apq8064-pins.dtsi index b57c59d5bc00..8bb5e5f3d07a 100644 --- a/arch/arm/boot/dts/qcom-apq8064-pins.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064-pins.dtsi @@ -39,6 +39,20 @@ }; }; + gsbi1_uart_2pins: gsbi1_uart_2pins { + mux { + pins = "gpio18", "gpio19"; + function = "gsbi1"; + }; + }; + + gsbi1_uart_4pins: gsbi1_uart_4pins { + mux { + pins = "gpio18", "gpio19", "gpio20", "gpio21"; + function = "gsbi1"; + }; + }; + i2c2_pins: i2c2 { mux { pins = "gpio24", "gpio25"; diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 18637c06566c..407a072dea69 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -319,6 +319,16 @@ syscon-tcsr = <&tcsr>; + gsbi1_serial: serial@12450000 { + compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; + reg = <0x12450000 0x100>, + <0x12400000 0x03>; + interrupts = <0 193 0x0>; + clocks = <&gcc GSBI1_UART_CLK>, <&gcc GSBI1_H_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + gsbi1_i2c: i2c@12460000 { compatible = "qcom,i2c-qup-v1.1.1"; pinctrl-0 = <&i2c1_pins>; -- GitLab From e4b01fda5dca99c227494bd9dc3a9d7628a17c2f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:52 +0100 Subject: [PATCH 3744/9938] ARM: dts: apq8064: add gsbi7 i2c support This patch adds support to gsbi7 i2c which is used in some of the new boards. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064-pins.dtsi | 25 ++++++++++++++++++++++++ arch/arm/boot/dts/qcom-apq8064.dtsi | 13 ++++++++++++ 2 files changed, 38 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-pins.dtsi b/arch/arm/boot/dts/qcom-apq8064-pins.dtsi index 8bb5e5f3d07a..4102a98f475b 100644 --- a/arch/arm/boot/dts/qcom-apq8064-pins.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064-pins.dtsi @@ -219,4 +219,29 @@ function = "gsbi7"; }; }; + + i2c7_pins: i2c7 { + mux { + pins = "gpio84", "gpio85"; + function = "gsbi7"; + }; + + pinconf { + pins = "gpio84", "gpio85"; + drive-strength = <16>; + bias-disable; + }; + }; + + i2c7_pins_sleep: i2c7_pins_sleep { + mux { + pins = "gpio84", "gpio85"; + function = "gpio"; + }; + pinconf { + pins = "gpio84", "gpio85"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 407a072dea69..b176c094cd6f 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -511,6 +511,19 @@ clock-names = "core", "iface"; status = "disabled"; }; + + gsbi7_i2c: i2c@16680000 { + compatible = "qcom,i2c-qup-v1.1.1"; + pinctrl-0 = <&i2c7_pins>; + pinctrl-1 = <&i2c7_pins_sleep>; + pinctrl-names = "default", "sleep"; + reg = <0x16680000 0x1000>; + interrupts = ; + clocks = <&gcc GSBI7_QUP_CLK>, + <&gcc GSBI7_H_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; }; rng@1a500000 { -- GitLab From 973747fb473474db4ad69900e7af7d4f91e78895 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:53 +0100 Subject: [PATCH 3745/9938] ARM: dts: db600c: add board support with serial This patch adds support to DB600c with basic serial ports. DB600c is based on APQ8064. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/qcom-apq8064-arrow-db600c.dts | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 15ed1221b4d4..8904a0a1cdf6 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -539,6 +539,7 @@ dtb-$(CONFIG_ARCH_ORION5X) += \ dtb-$(CONFIG_ARCH_PRIMA2) += \ prima2-evb.dtb dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-apq8064-arrow-db600c.dtb \ qcom-apq8064-cm-qs600.dtb \ qcom-apq8064-ifc6410.dtb \ qcom-apq8064-sony-xperia-yuga.dtb \ diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts new file mode 100644 index 000000000000..57d45001cc27 --- /dev/null +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -0,0 +1,36 @@ +#include "qcom-apq8064-v2.0.dtsi" + +/ { + model = "Arrow Electronics, APQ8064 DB600c"; + compatible = "arrow,db600c", "qcom,apq8064"; + + aliases { + serial0 = &gsbi7_serial; + serial1 = &gsbi1_serial; + }; + + soc { + gsbi@12440000 { + status = "okay"; + qcom,mode = ; + serial@12450000 { + label = "LS-UART1"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&gsbi1_uart_4pins>; + }; + }; + + /* DEBUG UART */ + gsbi@16600000 { + status = "okay"; + qcom,mode = ; + serial@16640000 { + label = "LS-UART0"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&gsbi7_uart_2pins>; + }; + }; + }; +}; -- GitLab From 696a8a16f92b83c14c58b7a4d28526aaeeabafe8 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:54 +0100 Subject: [PATCH 3746/9938] ARM: dts: db600c: add pmic regulator supplies This patch adds pmic regulator supplies connected on the board. Rest of the invidual regulators would be added as and when required by the devices. Signed-off-by: Srinivas Kandagatla Acked-by: Bjorn Andersson Signed-off-by: Andy Gross --- .../boot/dts/qcom-apq8064-arrow-db600c.dts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 57d45001cc27..6695b007a34f 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -9,7 +9,69 @@ serial1 = &gsbi1_serial; }; + regulators { + compatible = "simple-bus"; + vph: regulator-fixed@1 { + compatible = "regulator-fixed"; + regulator-min-microvolt = <4500000>; + regulator-max-microvolt = <4500000>; + regulator-name = "VPH"; + regulator-type = "voltage"; + regulator-boot-on; + }; + }; + soc { + rpm@108000 { + regulators { + vdd_s1-supply = <&vph>; + vdd_s2-supply = <&vph>; + vdd_s3-supply = <&vph>; + vdd_s4-supply = <&vph>; + vdd_s5-supply = <&vph>; + vdd_s6-supply = <&vph>; + vdd_s7-supply = <&vph>; + vdd_l1_l2_l12_l18-supply = <&pm8921_s4>; + vdd_l3_l15_l17-supply = <&vph>; + vdd_l4_l14-supply = <&vph>; + vdd_l5_l8_l16-supply = <&vph>; + vdd_l6_l7-supply = <&vph>; + vdd_l9_l11-supply = <&vph>; + vdd_l10_l22-supply = <&vph>; + vdd_l21_l23_l29-supply = <&vph>; + vdd_l24-supply = <&pm8921_s1>; + vdd_l25-supply = <&pm8921_s1>; + vdd_l26-supply = <&pm8921_s7>; + vdd_l27-supply = <&pm8921_s7>; + vdd_l28-supply = <&pm8921_s7>; + vin_lvs1_3_6-supply = <&pm8921_s4>; + vin_lvs2-supply = <&pm8921_s1>; + vin_lvs4_5_7-supply = <&pm8921_s4>; + + s1 { + regulator-always-on; + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + qcom,switch-mode-frequency = <3200000>; + bias-pull-down; + }; + + s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + qcom,switch-mode-frequency = <3200000>; + bias-pull-down; + regulator-always-on; + }; + + s7 { + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + qcom,switch-mode-frequency = <3200000>; + }; + }; + }; + gsbi@12440000 { status = "okay"; qcom,mode = ; -- GitLab From 226355fb9e486ae472df10e34eb5ac636f196657 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:55 +0100 Subject: [PATCH 3747/9938] ARM: dts: db600c: Add eMMC and SD card support This patch adds eMMC and SD card support with card detect and adding required regulators. Signed-off-by: Srinivas Kandagatla Acked-by: Bjorn Andersson Signed-off-by: Andy Gross --- .../dts/qcom-apq8064-arrow-db600c-pins.dtsi | 9 +++++ .../boot/dts/qcom-apq8064-arrow-db600c.dts | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi new file mode 100644 index 000000000000..7339919783d2 --- /dev/null +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi @@ -0,0 +1,9 @@ +&tlmm_pinmux { + card_detect: card-detect { + mux { + pins = "gpio26"; + function = "gpio"; + bias-disable; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 6695b007a34f..d92142409c43 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -1,4 +1,6 @@ #include "qcom-apq8064-v2.0.dtsi" +#include "qcom-apq8064-arrow-db600c-pins.dtsi" +#include / { model = "Arrow Electronics, APQ8064 DB600c"; @@ -69,6 +71,20 @@ regulator-max-microvolt = <1300000>; qcom,switch-mode-frequency = <3200000>; }; + + l5 { + regulator-min-microvolt = <2750000>; + regulator-max-microvolt = <3000000>; + bias-pull-down; + regulator-boot-on; + regulator-always-on; + }; + + l6 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + bias-pull-down; + }; }; }; @@ -94,5 +110,23 @@ pinctrl-0 = <&gsbi7_uart_2pins>; }; }; + + amba { + /* eMMC */ + sdcc@12400000 { + status = "okay"; + vmmc-supply = <&pm8921_l5>; + vqmmc-supply = <&pm8921_s4>; + }; + + /* External micro SD card */ + sdcc@12180000 { + status = "okay"; + vmmc-supply = <&pm8921_l6>; + pinctrl-names = "default"; + pinctrl-0 = <&card_detect>; + cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_HIGH>; + }; + }; }; }; -- GitLab From f43a92715d5b71b3524a96bdf3b5ed6c4ce1d6b2 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:56 +0100 Subject: [PATCH 3748/9938] ARM: dts: db600c: add usb support This patch adds usb host and otg support on board with required regulators. Signed-off-by: Srinivas Kandagatla Acked-by: Bjorn Andersson Signed-off-by: Andy Gross --- .../boot/dts/qcom-apq8064-arrow-db600c.dts | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index d92142409c43..2c563df3c832 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -58,6 +58,12 @@ bias-pull-down; }; + s3 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + qcom,switch-mode-frequency = <4800000>; + }; + s4 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -72,6 +78,18 @@ qcom,switch-mode-frequency = <3200000>; }; + l3 { + regulator-min-microvolt = <3050000>; + regulator-max-microvolt = <3300000>; + bias-pull-down; + }; + + l4 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1800000>; + bias-pull-down; + }; + l5 { regulator-min-microvolt = <2750000>; regulator-max-microvolt = <3000000>; @@ -85,6 +103,12 @@ regulator-max-microvolt = <2950000>; bias-pull-down; }; + + l23 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1900000>; + bias-pull-down; + }; }; }; @@ -111,6 +135,46 @@ }; }; + /* OTG */ + phy@12500000 { + status = "okay"; + dr_mode = "peripheral"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l4>; + }; + + phy@12520000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l23>; + }; + + phy@12530000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l23>; + }; + + gadget@12500000 { + status = "okay"; + }; + + /* OTG */ + usb@12500000 { + status = "okay"; + }; + + usb@12520000 { + status = "okay"; + }; + + usb@12530000 { + status = "okay"; + }; + amba { /* eMMC */ sdcc@12400000 { -- GitLab From c22847863a58c42035660ffa7fadbef6459e67bd Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:57 +0100 Subject: [PATCH 3749/9938] ARM: dts: db600c: add pcie support This patch adds pcie and regulators required to get on board ATL1C ethernet working. Signed-off-by: Srinivas Kandagatla Acked-by: Bjorn Andersson Signed-off-by: Andy Gross --- .../dts/qcom-apq8064-arrow-db600c-pins.dtsi | 12 ++++++++++ .../boot/dts/qcom-apq8064-arrow-db600c.dts | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi index 7339919783d2..0610f0027b38 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi @@ -6,4 +6,16 @@ bias-disable; }; }; + + pcie_pins: pcie-pinmux { + mux { + pins = "gpio27"; + function = "gpio"; + }; + conf { + pins = "gpio27"; + drive-strength = <12>; + bias-disable; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 2c563df3c832..4f2218c4622e 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -21,6 +21,16 @@ regulator-type = "voltage"; regulator-boot-on; }; + + /* on board fixed 3.3v supply */ + vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; soc { @@ -109,6 +119,10 @@ regulator-max-microvolt = <1900000>; bias-pull-down; }; + + lvs6 { + bias-pull-down; + }; }; }; @@ -135,6 +149,16 @@ }; }; + pci@1b500000 { + status = "okay"; + vdda-supply = <&pm8921_s3>; + vdda_phy-supply = <&pm8921_lvs6>; + vdda_refclk-supply = <&vcc3v3>; + pinctrl-0 = <&pcie_pins>; + pinctrl-names = "default"; + perst-gpio = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>; + }; + /* OTG */ phy@12500000 { status = "okay"; -- GitLab From 2ce36229a8cab110d50f227dda64850072e74b2d Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:58 +0100 Subject: [PATCH 3750/9938] ARM: dts: db600c: add on board sata support. This patch enables sata and regulators required to get on board sata working. Signed-off-by: Srinivas Kandagatla Acked-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 4f2218c4622e..6f97ddc340e6 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -123,6 +123,10 @@ lvs6 { bias-pull-down; }; + + lvs7 { + bias-pull-down; + }; }; }; @@ -159,6 +163,15 @@ perst-gpio = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>; }; + phy@1b400000 { + status = "okay"; + }; + + sata@29000000 { + status = "okay"; + target-supply = <&pm8921_lvs7>; + }; + /* OTG */ phy@12500000 { status = "okay"; -- GitLab From 2f29160fce634cb0e8e1bc493d0e509407ac1e0e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:33:59 +0100 Subject: [PATCH 3751/9938] ARM: dts: db600c: Add on board leds support This patch adds support to 4 user leds, wlan and bt led on board. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- .../dts/qcom-apq8064-arrow-db600c-pins.dtsi | 23 +++++++++ .../boot/dts/qcom-apq8064-arrow-db600c.dts | 47 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi index 0610f0027b38..3b55bb97c696 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi @@ -18,4 +18,27 @@ bias-disable; }; }; + + user_leds: user-leds { + mux { + pins = "gpio3", "gpio7", "gpio10", "gpio11"; + function = "gpio"; + }; + + conf { + pins = "gpio3", "gpio7", "gpio10", "gpio11"; + function = "gpio"; + output-low; + }; + }; +}; + +&pm8921_mpps { + mpp_leds: mpp-leds { + pinconf { + pins = "mpp7", "mpp8"; + function = "digital"; + output-low; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 6f97ddc340e6..8c18a4bad088 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -153,6 +153,53 @@ }; }; + leds { + pinctrl-names = "default"; + pinctrl-0 = <&user_leds>, <&mpp_leds>; + + compatible = "gpio-leds"; + + user-led0 { + label = "user0-led"; + gpios = <&tlmm_pinmux 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + user-led1 { + label = "user1-led"; + gpios = <&tlmm_pinmux 7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + user-led2 { + label = "user2-led"; + gpios = <&tlmm_pinmux 10 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc1"; + default-state = "off"; + }; + + user-led3 { + label = "user3-led"; + gpios = <&tlmm_pinmux 11 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + default-state = "off"; + }; + + wifi-led { + label = "WiFi-led"; + gpios = <&pm8921_mpps 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + bt-led { + label = "BT-led"; + gpios = <&pm8921_mpps 8 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + pci@1b500000 { status = "okay"; vdda-supply = <&pm8921_s3>; -- GitLab From d8aef8720c605600e21f57c412876f60e1721582 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:34:00 +0100 Subject: [PATCH 3752/9938] ARM: dts: db600c: add i2c support This patch adds nodes required to enable 4 i2c buses on the board which are connected to various sensors and eeprom. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- .../boot/dts/qcom-apq8064-arrow-db600c.dts | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 8c18a4bad088..2f0dfff75572 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -9,6 +9,10 @@ aliases { serial0 = &gsbi7_serial; serial1 = &gsbi1_serial; + i2c0 = &gsbi2_i2c; + i2c1 = &gsbi3_i2c; + i2c2 = &gsbi4_i2c; + i2c3 = &gsbi7_i2c; }; regulators { @@ -141,6 +145,42 @@ }; }; + gsbi@12480000 { + status = "okay"; + qcom,mode = ; + i2c@124a0000 { + /* On Low speed expansion and Sensors */ + label = "LS-I2C0"; + status = "okay"; + }; + }; + + gsbi@16200000 { + status = "okay"; + qcom,mode = ; + i2c@16280000 { + /* On Low speed expansion */ + status = "okay"; + label = "LS-I2C1"; + clock-frequency = <200000>; + eeprom@52 { + compatible = "atmel,24c128"; + reg = <0x52>; + pagesize = <64>; + }; + }; + }; + + gsbi@16300000 { + status = "okay"; + qcom,mode = ; + i2c@16380000 { + /* On High speed expansion */ + label = "HS-CAM-I2C3"; + status = "okay"; + }; + }; + /* DEBUG UART */ gsbi@16600000 { status = "okay"; @@ -151,6 +191,12 @@ pinctrl-names = "default"; pinctrl-0 = <&gsbi7_uart_2pins>; }; + + i2c@16680000 { + /* On High speed expansion */ + status = "okay"; + label = "HS-CAM-I2C2"; + }; }; leds { -- GitLab From e0da214a8892d0e36f8575e1c996e78c66e2674c Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:34:01 +0100 Subject: [PATCH 3753/9938] ARM: dts: db600c: add spi support This patch adds spi nodes required to provide spi bus support on LS expansion. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 2f0dfff75572..34bb4157872e 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -13,6 +13,7 @@ i2c1 = &gsbi3_i2c; i2c2 = &gsbi4_i2c; i2c3 = &gsbi7_i2c; + spi0 = &gsbi5_spi; }; regulators { @@ -181,6 +182,15 @@ }; }; + gsbi@1a200000 { + status = "okay"; + spi@1a280000 { + /* On Low speed expansion */ + label = "LS-SPI0"; + status = "okay"; + }; + }; + /* DEBUG UART */ gsbi@16600000 { status = "okay"; -- GitLab From 2b9d49d8c749ce3c8f5cb28f54875a6f33fa1f72 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 12 Apr 2016 10:34:02 +0100 Subject: [PATCH 3754/9938] ARM: dts: db600c: add support to magnetometer This patch adds support to on board LIS3MDLTR magnetometer. Signed-off-by: Srinivas Kandagatla Signed-off-by: Andy Gross --- .../boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi | 8 ++++++++ arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi index 3b55bb97c696..a3efb9704fcd 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi @@ -31,6 +31,14 @@ output-low; }; }; + + magneto_pins: magneto-pins { + mux { + pins = "gpio31", "gpio48"; + function = "gpio"; + bias-disable; + }; + }; }; &pm8921_mpps { diff --git a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts index 34bb4157872e..e01b27ea7fba 100644 --- a/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts +++ b/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts @@ -153,6 +153,19 @@ /* On Low speed expansion and Sensors */ label = "LS-I2C0"; status = "okay"; + lis3mdl_mag@1e { + compatible = "st,lis3mdl-magn"; + reg = <0x1e>; + vdd-supply = <&vcc3v3>; + vddio-supply = <&pm8921_s4>; + pinctrl-names = "default"; + pinctrl-0 = <&magneto_pins>; + interrupt-parent = <&tlmm_pinmux>; + + st,drdy-int-pin = <2>; + interrupts = <48 IRQ_TYPE_EDGE_RISING>, /* DRDY line */ + <31 IRQ_TYPE_EDGE_RISING>; /* INT */ + }; }; }; -- GitLab From 3db63602505fa30f9d8faa1512fc71dae0cbf71b Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 14 Apr 2016 14:07:11 -0700 Subject: [PATCH 3755/9938] device-tree: nexus7: Add bq27541 battery interface to dts Add support for battery level reading on the Nexus7 by enabling the bq27541 driver in the nexus7 dts Cc: Rob Herring Cc: Arnd Bergmann Cc: Pawel Moll Cc: Mark Rutland Cc: Ian Campbell Cc: Kumar Gala Cc: Andy Gross Cc: Vinay Simha BN Cc: Bjorn Andersson Cc: Stephen Boyd Cc: linux-arm-msm@vger.kernel.org Cc: devicetree@vger.kernel.org Signed-off-by: John Stultz Acked-by: Rob Herring Acked-by: Bjorn Andersson Signed-off-by: Andy Gross --- arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts b/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts index c535b3f0e5cf..32fedfa149d0 100644 --- a/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts +++ b/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts @@ -224,6 +224,12 @@ reg = <0x52>; pagesize = <32>; }; + + bq27541@55 { + compatible = "ti,bq27541"; + reg = <0x55>; + }; + }; }; -- GitLab From 2d077d9f4e984a5364bf62e719396375b2922d26 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 10:41:10 -0700 Subject: [PATCH 3756/9938] Input: bcm_iproc_tsc - DT spelling s/clock-name/clock-names/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/brcm,iproc-touchscreen.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt b/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt index 25541f30e387..ac5dff412e25 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt @@ -7,7 +7,7 @@ Required properties: If this property is selected please make sure MFD_SYSCON config is enabled in the defconfig file. - clocks: The clock provided by the SOC to driver the tsc -- clock-name: name for the clock +- clock-names: name for the clock - interrupts: The touchscreen controller's interrupt - address-cells: Specify the number of u32 entries needed in child nodes. Should set to 1. -- GitLab From 80e0f8d94d3090f0f7bf3faf3e6180e920ee0d22 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:12:59 +0530 Subject: [PATCH 3757/9938] pinctrl: Add devm_ apis for pinctrl_{register, unregister} Add device managed APIs devm_pinctrl_register() and devm_pinctrl_unregister() for the APIs pinctrl_register() and pinctrl_unregister(). This helps in reducing code in error path and sometimes removal of .remove callback for driver unbind. Signed-off-by: Laxman Dewangan Reviewed-by: Philipp Zabel Acked-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 63 +++++++++++++++++++++++++++++++++ include/linux/pinctrl/pinctrl.h | 6 ++++ 2 files changed, 69 insertions(+) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index f67a8b7a4e18..21df52e8192a 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1872,6 +1872,69 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) } EXPORT_SYMBOL_GPL(pinctrl_unregister); +static void devm_pinctrl_dev_release(struct device *dev, void *res) +{ + struct pinctrl_dev *pctldev = *(struct pinctrl_dev **)res; + + pinctrl_unregister(pctldev); +} + +static int devm_pinctrl_dev_match(struct device *dev, void *res, void *data) +{ + struct pctldev **r = res; + + if (WARN_ON(!r || !*r) + return 0; + + return *r == data; +} + +/** + * devm_pinctrl_register() - Resource managed version of pinctrl_register(). + * @dev: parent device for this pin controller + * @pctldesc: descriptor for this pin controller + * @driver_data: private pin controller data for this pin controller + * + * Returns an error pointer if pincontrol register failed. Otherwise + * it returns valid pinctrl handle. + * + * The pinctrl device will be automatically released when the device is unbound. + */ +struct pinctrl_dev *devm_pinctrl_register(struct device *dev, + struct pinctrl_desc *pctldesc, + void *driver_data) +{ + struct pinctrl_dev **ptr, *pctldev; + + ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + pctldev = pinctrl_register(pctldesc, dev, driver_data); + if (IS_ERR(pctldev)) { + devres_free(ptr); + return pctldev; + } + + *ptr = pctldev; + devres_add(dev, ptr); + + return pctldev; +} +EXPORT_SYMBOL_GPL(devm_pinctrl_register); + +/** + * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister(). + * @dev: device for which which resource was allocated + * @pctldev: the pinctrl device to unregister. + */ +void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev) +{ + WARN_ON(devres_release(dev, devm_pinctrl_dev_release, + devm_pinctrl_dev_match, pctldev)); +} +EXPORT_SYMBOL_GPL(devm_pinctrl_unregister); + static int __init pinctrl_init(void) { pr_info("initialized pinctrl subsystem\n"); diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 9ba59fcba549..a42e57da270d 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -144,6 +144,12 @@ struct pinctrl_desc { extern struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, struct device *dev, void *driver_data); extern void pinctrl_unregister(struct pinctrl_dev *pctldev); +extern struct pinctrl_dev *devm_pinctrl_register(struct device *dev, + struct pinctrl_desc *pctldesc, + void *driver_data); +extern void devm_pinctrl_unregister(struct device *dev, + struct pinctrl_dev *pctldev); + extern bool pin_is_valid(struct pinctrl_dev *pctldev, int pin); extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range); -- GitLab From 1f8dd72fc3f0d371684685a2f9f8c4220ecd3517 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:14:35 +0530 Subject: [PATCH 3758/9938] pinctrl: Add resource management devm_pinctrl_{register, unregister} Add new member of devm wrappers for the pinctrl_register and pinctrl_unregister in list of managed interfaces. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- Documentation/driver-model/devres.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 73b98dfbcea4..e89f7b51f243 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -328,6 +328,8 @@ PHY PINCTRL devm_pinctrl_get() devm_pinctrl_put() + devm_pinctrl_register() + devm_pinctrl_unregister() PWM devm_pwm_get() -- GitLab From 7f5567aa879bac8eec961fa8c82cbacf7f97f288 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3759/9938] pinctrl: bcm281xx: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Ray Jui Cc: linux-rpi-kernel@lists.infradead.org Cc: linux-arm-kernel@lists.infradead.org Cc: bcm-kernel-feedback-list@broadcom.com Acked-by: Ray Jui Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c index f043b83b18f0..582f6df446e8 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c @@ -1422,9 +1422,7 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev) bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins; bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins; - pctl = pinctrl_register(&bcm281xx_pinctrl_desc, - &pdev->dev, - pdata); + pctl = devm_pinctrl_register(&pdev->dev, &bcm281xx_pinctrl_desc, pdata); if (IS_ERR(pctl)) { dev_err(&pdev->dev, "Failed to register pinctrl\n"); return PTR_ERR(pctl); -- GitLab From 5f276f679f5a80294c5689b8d900ba3881f2de8f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3760/9938] pinctrl: bcm2835: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Ray Jui Cc: linux-rpi-kernel@lists.infradead.org Cc: linux-arm-kernel@lists.infradead.org Cc: bcm-kernel-feedback-list@broadcom.com Acked-by: Ray Jui Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 57e7d21d526b..fa77165fab2c 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -1040,7 +1040,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) return err; } - pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc); + pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); if (IS_ERR(pc->pctl_dev)) { gpiochip_remove(&pc->gpio_chip); return PTR_ERR(pc->pctl_dev); @@ -1058,7 +1058,6 @@ static int bcm2835_pinctrl_remove(struct platform_device *pdev) { struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev); - pinctrl_unregister(pc->pctl_dev); gpiochip_remove(&pc->gpio_chip); return 0; -- GitLab From ead044eeec3e822f17cdce2a690970b96e289682 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3761/9938] pinctrl: cygnus-mux: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Ray Jui Cc: Scott Branden Cc: Jon Mason Acked-by: Ray Jui Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-cygnus-mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c index f0184dc16730..d31c95701a92 100644 --- a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c @@ -987,7 +987,7 @@ static int cygnus_pinmux_probe(struct platform_device *pdev) cygnus_pinctrl_desc.pins = pins; cygnus_pinctrl_desc.npins = num_pins; - pinctrl->pctl = pinctrl_register(&cygnus_pinctrl_desc, &pdev->dev, + pinctrl->pctl = devm_pinctrl_register(&pdev->dev, &cygnus_pinctrl_desc, pinctrl); if (IS_ERR(pinctrl->pctl)) { dev_err(&pdev->dev, "unable to register Cygnus IOMUX pinctrl\n"); -- GitLab From ee17e04102e2483ad61e7f0e704e6d6dc94922d7 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3762/9938] pinctrl: iproc-gpio: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Ray Jui Cc: Scott Branden Cc: Jon Mason Acked-by: Ray Jui Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-iproc-gpio.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index 9ed98813c7d0..3670f5ea7a12 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -623,7 +623,7 @@ static int iproc_gpio_register_pinconf(struct iproc_gpio *chip) pctldesc->npins = gc->ngpio; pctldesc->confops = &iproc_pconf_ops; - chip->pctl = pinctrl_register(pctldesc, chip->dev, chip); + chip->pctl = devm_pinctrl_register(chip->dev, pctldesc, chip); if (IS_ERR(chip->pctl)) { dev_err(chip->dev, "unable to register pinctrl device\n"); return PTR_ERR(chip->pctl); @@ -632,11 +632,6 @@ static int iproc_gpio_register_pinconf(struct iproc_gpio *chip) return 0; } -static void iproc_gpio_unregister_pinconf(struct iproc_gpio *chip) -{ - pinctrl_unregister(chip->pctl); -} - static const struct of_device_id iproc_gpio_of_match[] = { { .compatible = "brcm,cygnus-ccm-gpio" }, { .compatible = "brcm,cygnus-asiu-gpio" }, @@ -720,7 +715,7 @@ static int iproc_gpio_probe(struct platform_device *pdev) handle_simple_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "no GPIO irqchip\n"); - goto err_unregister_pinconf; + goto err_rm_gpiochip; } gpiochip_set_chained_irqchip(gc, &iproc_gpio_irq_chip, irq, @@ -729,9 +724,6 @@ static int iproc_gpio_probe(struct platform_device *pdev) return 0; -err_unregister_pinconf: - iproc_gpio_unregister_pinconf(chip); - err_rm_gpiochip: gpiochip_remove(gc); -- GitLab From 315d118f1ac5b6132b604f69e1281cf7fa83594f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3763/9938] pinctrl: nsp-gpio: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Ray Jui Cc: Scott Branden Cc: Jon Mason Acked-by: Ray Jui Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-nsp-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c index 6c7d5f500f35..a8b37a9a8230 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c @@ -609,7 +609,7 @@ static int nsp_gpio_register_pinconf(struct nsp_gpio *chip) pctldesc->npins = gc->ngpio; pctldesc->confops = &nsp_pconf_ops; - chip->pctl = pinctrl_register(pctldesc, chip->dev, chip); + chip->pctl = devm_pinctrl_register(chip->dev, pctldesc, chip); if (IS_ERR(chip->pctl)) { dev_err(chip->dev, "unable to register pinctrl device\n"); return PTR_ERR(chip->pctl); -- GitLab From 7e73f819054c5da0203a4faf446c9776a4ca0f75 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3764/9938] pinctrl: berlin: Use devm_pinctrl_register() for pinctrl registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Antoine Ténart Acked-by: Antoine Tenart Signed-off-by: Linus Walleij --- drivers/pinctrl/berlin/berlin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c index 87b17b77df02..8f0dc02f7624 100644 --- a/drivers/pinctrl/berlin/berlin.c +++ b/drivers/pinctrl/berlin/berlin.c @@ -316,7 +316,8 @@ int berlin_pinctrl_probe_regmap(struct platform_device *pdev, return ret; } - pctrl->pctrl_dev = pinctrl_register(&berlin_pctrl_desc, dev, pctrl); + pctrl->pctrl_dev = devm_pinctrl_register(dev, &berlin_pctrl_desc, + pctrl); if (IS_ERR(pctrl->pctrl_dev)) { dev_err(dev, "failed to register pinctrl driver\n"); return PTR_ERR(pctrl->pctrl_dev); -- GitLab From a4b0f4571c7438cbc11f088d57d6a5ef3e60e3cb Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3765/9938] pinctrl: imx: Use devm_pinctrl_register() for pinctrl registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use devm_pinctrl_register() for pin control registration and remove need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Shawn Guo Cc: Stefan Agner Cc: Adrian Alonso Cc: Uwe Kleine-König Reviewed-by: Philipp Zabel Signed-off-by: Linus Walleij --- drivers/pinctrl/freescale/pinctrl-imx.c | 11 +---------- drivers/pinctrl/freescale/pinctrl-imx.h | 1 - drivers/pinctrl/freescale/pinctrl-imx25.c | 1 - drivers/pinctrl/freescale/pinctrl-imx35.c | 1 - drivers/pinctrl/freescale/pinctrl-imx50.c | 1 - drivers/pinctrl/freescale/pinctrl-imx51.c | 1 - drivers/pinctrl/freescale/pinctrl-imx53.c | 1 - drivers/pinctrl/freescale/pinctrl-imx6dl.c | 1 - drivers/pinctrl/freescale/pinctrl-imx6q.c | 1 - drivers/pinctrl/freescale/pinctrl-imx6sl.c | 1 - drivers/pinctrl/freescale/pinctrl-imx6sx.c | 1 - drivers/pinctrl/freescale/pinctrl-imx6ul.c | 1 - drivers/pinctrl/freescale/pinctrl-imx7d.c | 1 - drivers/pinctrl/freescale/pinctrl-vf610.c | 1 - 14 files changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index 46210512d8ec..74d603501eec 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -790,7 +790,7 @@ int imx_pinctrl_probe(struct platform_device *pdev, ipctl->info = info; ipctl->dev = info->dev; platform_set_drvdata(pdev, ipctl); - ipctl->pctl = pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl); + ipctl->pctl = devm_pinctrl_register(&pdev->dev, &imx_pinctrl_desc, ipctl); if (IS_ERR(ipctl->pctl)) { dev_err(&pdev->dev, "could not register IMX pinctrl driver\n"); return PTR_ERR(ipctl->pctl); @@ -800,12 +800,3 @@ int imx_pinctrl_probe(struct platform_device *pdev, return 0; } - -int imx_pinctrl_remove(struct platform_device *pdev) -{ - struct imx_pinctrl *ipctl = platform_get_drvdata(pdev); - - pinctrl_unregister(ipctl->pctl); - - return 0; -} diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h b/drivers/pinctrl/freescale/pinctrl-imx.h index 3b8bd81a39a4..8af8aa2897ab 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.h +++ b/drivers/pinctrl/freescale/pinctrl-imx.h @@ -99,5 +99,4 @@ struct imx_pinctrl_soc_info { int imx_pinctrl_probe(struct platform_device *pdev, struct imx_pinctrl_soc_info *info); -int imx_pinctrl_remove(struct platform_device *pdev); #endif /* __DRIVERS_PINCTRL_IMX_H */ diff --git a/drivers/pinctrl/freescale/pinctrl-imx25.c b/drivers/pinctrl/freescale/pinctrl-imx25.c index 293ed4381cc0..81ad546d74bb 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx25.c +++ b/drivers/pinctrl/freescale/pinctrl-imx25.c @@ -331,7 +331,6 @@ static struct platform_driver imx25_pinctrl_driver = { .of_match_table = of_match_ptr(imx25_pinctrl_of_match), }, .probe = imx25_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx25_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx35.c b/drivers/pinctrl/freescale/pinctrl-imx35.c index 9109c10c5dab..13eb224a29a9 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx35.c +++ b/drivers/pinctrl/freescale/pinctrl-imx35.c @@ -1021,7 +1021,6 @@ static struct platform_driver imx35_pinctrl_driver = { .of_match_table = imx35_pinctrl_of_match, }, .probe = imx35_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx35_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx50.c b/drivers/pinctrl/freescale/pinctrl-imx50.c index 8acc4d960cfa..95a36c88b66a 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx50.c +++ b/drivers/pinctrl/freescale/pinctrl-imx50.c @@ -408,7 +408,6 @@ static struct platform_driver imx50_pinctrl_driver = { .of_match_table = of_match_ptr(imx50_pinctrl_of_match), }, .probe = imx50_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx50_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx51.c b/drivers/pinctrl/freescale/pinctrl-imx51.c index 8dec494aa2c6..0863e5279896 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx51.c +++ b/drivers/pinctrl/freescale/pinctrl-imx51.c @@ -784,7 +784,6 @@ static struct platform_driver imx51_pinctrl_driver = { .of_match_table = imx51_pinctrl_of_match, }, .probe = imx51_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx51_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx53.c b/drivers/pinctrl/freescale/pinctrl-imx53.c index d39dfd6a3a44..64c9cbe2a5df 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx53.c +++ b/drivers/pinctrl/freescale/pinctrl-imx53.c @@ -471,7 +471,6 @@ static struct platform_driver imx53_pinctrl_driver = { .of_match_table = imx53_pinctrl_of_match, }, .probe = imx53_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx53_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx6dl.c b/drivers/pinctrl/freescale/pinctrl-imx6dl.c index 5a2cdb0549ce..de17bac8ad89 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx6dl.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6dl.c @@ -477,7 +477,6 @@ static struct platform_driver imx6dl_pinctrl_driver = { .of_match_table = imx6dl_pinctrl_of_match, }, .probe = imx6dl_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx6dl_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx6q.c b/drivers/pinctrl/freescale/pinctrl-imx6q.c index 7d50a36b1086..55cd8a0e367d 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx6q.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6q.c @@ -483,7 +483,6 @@ static struct platform_driver imx6q_pinctrl_driver = { .of_match_table = imx6q_pinctrl_of_match, }, .probe = imx6q_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx6q_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx6sl.c b/drivers/pinctrl/freescale/pinctrl-imx6sl.c index e27d17fdc69d..bf455b8e73fc 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx6sl.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6sl.c @@ -384,7 +384,6 @@ static struct platform_driver imx6sl_pinctrl_driver = { .of_match_table = imx6sl_pinctrl_of_match, }, .probe = imx6sl_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx6sl_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx6sx.c b/drivers/pinctrl/freescale/pinctrl-imx6sx.c index 117180c26c50..84118c388cc5 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx6sx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6sx.c @@ -387,7 +387,6 @@ static struct platform_driver imx6sx_pinctrl_driver = { .of_match_table = of_match_ptr(imx6sx_pinctrl_of_match), }, .probe = imx6sx_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx6sx_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx6ul.c b/drivers/pinctrl/freescale/pinctrl-imx6ul.c index 78627c70c6ba..c707fdd933ec 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx6ul.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6ul.c @@ -303,7 +303,6 @@ static struct platform_driver imx6ul_pinctrl_driver = { .of_match_table = of_match_ptr(imx6ul_pinctrl_of_match), }, .probe = imx6ul_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx6ul_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-imx7d.c b/drivers/pinctrl/freescale/pinctrl-imx7d.c index 1c89613eb4b7..d30d91f80dfd 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx7d.c +++ b/drivers/pinctrl/freescale/pinctrl-imx7d.c @@ -395,7 +395,6 @@ static struct platform_driver imx7d_pinctrl_driver = { .of_match_table = of_match_ptr(imx7d_pinctrl_of_match), }, .probe = imx7d_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init imx7d_pinctrl_init(void) diff --git a/drivers/pinctrl/freescale/pinctrl-vf610.c b/drivers/pinctrl/freescale/pinctrl-vf610.c index 587d1ff6210e..6d81be096bc0 100644 --- a/drivers/pinctrl/freescale/pinctrl-vf610.c +++ b/drivers/pinctrl/freescale/pinctrl-vf610.c @@ -318,7 +318,6 @@ static struct platform_driver vf610_pinctrl_driver = { .of_match_table = vf610_pinctrl_of_match, }, .probe = vf610_pinctrl_probe, - .remove = imx_pinctrl_remove, }; static int __init vf610_pinctrl_init(void) -- GitLab From e55e025d16871018ec2fd168e2deaa2a9a0333b5 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3766/9938] pinctrl: imxl: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Hongzhou Yang Cc: Antoine Tenart Cc: Heiko Stuebner Signed-off-by: Linus Walleij --- drivers/pinctrl/freescale/pinctrl-imx1-core.c | 11 +---------- drivers/pinctrl/freescale/pinctrl-imx1.c | 1 - drivers/pinctrl/freescale/pinctrl-imx1.h | 1 - drivers/pinctrl/freescale/pinctrl-imx21.c | 1 - drivers/pinctrl/freescale/pinctrl-imx27.c | 1 - 5 files changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index acaf84cadca3..b4400cb19b61 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -635,7 +635,7 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev, ipctl->info = info; ipctl->dev = info->dev; platform_set_drvdata(pdev, ipctl); - ipctl->pctl = pinctrl_register(pctl_desc, &pdev->dev, ipctl); + ipctl->pctl = devm_pinctrl_register(&pdev->dev, pctl_desc, ipctl); if (IS_ERR(ipctl->pctl)) { dev_err(&pdev->dev, "could not register IMX pinctrl driver\n"); return PTR_ERR(ipctl->pctl); @@ -652,12 +652,3 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev, return 0; } - -int imx1_pinctrl_core_remove(struct platform_device *pdev) -{ - struct imx1_pinctrl *ipctl = platform_get_drvdata(pdev); - - pinctrl_unregister(ipctl->pctl); - - return 0; -} diff --git a/drivers/pinctrl/freescale/pinctrl-imx1.c b/drivers/pinctrl/freescale/pinctrl-imx1.c index d3bacb7d6d37..04723455db58 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1.c @@ -269,7 +269,6 @@ static struct platform_driver imx1_pinctrl_driver = { .name = "imx1-pinctrl", .of_match_table = imx1_pinctrl_of_match, }, - .remove = imx1_pinctrl_core_remove, }; module_platform_driver_probe(imx1_pinctrl_driver, imx1_pinctrl_probe); diff --git a/drivers/pinctrl/freescale/pinctrl-imx1.h b/drivers/pinctrl/freescale/pinctrl-imx1.h index 692a54c15cda..174074308d6c 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1.h +++ b/drivers/pinctrl/freescale/pinctrl-imx1.h @@ -69,5 +69,4 @@ struct imx1_pinctrl_soc_info { int imx1_pinctrl_core_probe(struct platform_device *pdev, struct imx1_pinctrl_soc_info *info); -int imx1_pinctrl_core_remove(struct platform_device *pdev); #endif /* __DRIVERS_PINCTRL_IMX1_H */ diff --git a/drivers/pinctrl/freescale/pinctrl-imx21.c b/drivers/pinctrl/freescale/pinctrl-imx21.c index 9d9aca3dbd7e..aa1221f4dbb7 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx21.c +++ b/drivers/pinctrl/freescale/pinctrl-imx21.c @@ -332,7 +332,6 @@ static struct platform_driver imx21_pinctrl_driver = { .name = "imx21-pinctrl", .of_match_table = imx21_pinctrl_of_match, }, - .remove = imx1_pinctrl_core_remove, }; module_platform_driver_probe(imx21_pinctrl_driver, imx21_pinctrl_probe); diff --git a/drivers/pinctrl/freescale/pinctrl-imx27.c b/drivers/pinctrl/freescale/pinctrl-imx27.c index a461d5881f37..f828fbbba4b9 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx27.c +++ b/drivers/pinctrl/freescale/pinctrl-imx27.c @@ -405,7 +405,6 @@ static struct platform_driver imx27_pinctrl_driver = { .of_match_table = of_match_ptr(imx27_pinctrl_of_match), }, .probe = imx27_pinctrl_probe, - .remove = imx1_pinctrl_core_remove, }; static int __init imx27_pinctrl_init(void) -- GitLab From 7cf061fadd66511074631acbb95e6f00e4fcc047 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3767/9938] pinctrl: cherryview: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean error path. Signed-off-by: Laxman Dewangan Cc: Mika Westerberg Cc: Heikki Krogerus Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-cherryview.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 4251e0747a3a..ac4f564f1c3e 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1526,17 +1526,16 @@ static int chv_pinctrl_probe(struct platform_device *pdev) pctrl->pctldesc.pins = pctrl->community->pins; pctrl->pctldesc.npins = pctrl->community->npins; - pctrl->pctldev = pinctrl_register(&pctrl->pctldesc, &pdev->dev, pctrl); + pctrl->pctldev = devm_pinctrl_register(&pdev->dev, &pctrl->pctldesc, + pctrl); if (IS_ERR(pctrl->pctldev)) { dev_err(&pdev->dev, "failed to register pinctrl driver\n"); return PTR_ERR(pctrl->pctldev); } ret = chv_gpio_probe(pctrl, irq); - if (ret) { - pinctrl_unregister(pctrl->pctldev); + if (ret) return ret; - } platform_set_drvdata(pdev, pctrl); @@ -1548,7 +1547,6 @@ static int chv_pinctrl_remove(struct platform_device *pdev) struct chv_pinctrl *pctrl = platform_get_drvdata(pdev); gpiochip_remove(&pctrl->chip); - pinctrl_unregister(pctrl->pctldev); return 0; } -- GitLab From 54d46cd7d236540f881767af366eca9734b7e980 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 28 Feb 2016 14:42:47 +0530 Subject: [PATCH 3768/9938] pinctrl: intel: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean error path. Signed-off-by: Laxman Dewangan Cc: Mika Westerberg Cc: Heikki Krogerus Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-intel.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 85536b467c25..457e740e941e 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1014,17 +1014,16 @@ int intel_pinctrl_probe(struct platform_device *pdev, pctrl->pctldesc.pins = pctrl->soc->pins; pctrl->pctldesc.npins = pctrl->soc->npins; - pctrl->pctldev = pinctrl_register(&pctrl->pctldesc, &pdev->dev, pctrl); + pctrl->pctldev = devm_pinctrl_register(&pdev->dev, &pctrl->pctldesc, + pctrl); if (IS_ERR(pctrl->pctldev)) { dev_err(&pdev->dev, "failed to register pinctrl driver\n"); return PTR_ERR(pctrl->pctldev); } ret = intel_gpio_probe(pctrl, irq); - if (ret) { - pinctrl_unregister(pctrl->pctldev); + if (ret) return ret; - } platform_set_drvdata(pdev, pctrl); @@ -1037,7 +1036,6 @@ int intel_pinctrl_remove(struct platform_device *pdev) struct intel_pinctrl *pctrl = platform_get_drvdata(pdev); gpiochip_remove(&pctrl->chip); - pinctrl_unregister(pctrl->pctldev); return 0; } -- GitLab From 03a3a5587e62079a6e8dc0a269ab5ba2262c0a87 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 28 Feb 2016 14:43:15 +0530 Subject: [PATCH 3769/9938] pinctrl: mtk-common: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Matthias Brugger Cc: Hongzhou Yang Cc: Yingjoe Chen Reviewed-by: Matthias Brugger Acked-by: Hongzhou Yang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 8ca82c134260..4091f9d9c4d4 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -1395,17 +1395,16 @@ int mtk_pctrl_init(struct platform_device *pdev, pctl->pctl_desc.pmxops = &mtk_pmx_ops; pctl->dev = &pdev->dev; - pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl); + pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc, + pctl); if (IS_ERR(pctl->pctl_dev)) { dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); return PTR_ERR(pctl->pctl_dev); } pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL); - if (!pctl->chip) { - ret = -ENOMEM; - goto pctrl_error; - } + if (!pctl->chip) + return -ENOMEM; *pctl->chip = mtk_gpio_chip; pctl->chip->ngpio = pctl->devdata->npins; @@ -1414,10 +1413,8 @@ int mtk_pctrl_init(struct platform_device *pdev, pctl->chip->base = -1; ret = gpiochip_add_data(pctl->chip, pctl); - if (ret) { - ret = -EINVAL; - goto pctrl_error; - } + if (ret) + return -EINVAL; /* Register the GPIO to pin mappings. */ ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev), @@ -1495,8 +1492,6 @@ int mtk_pctrl_init(struct platform_device *pdev, chip_error: gpiochip_remove(pctl->chip); -pctrl_error: - pinctrl_unregister(pctl->pctl_dev); return ret; } -- GitLab From e649f7ec8c5f776dd7e9fbeb18ca5f4e8ce85922 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3770/9938] pinctrl: meson: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Carlo Caione Cc: Beniamino Galvani Cc: Lee Jones Acked-by: Robert Jarzmik Signed-off-by: Linus Walleij --- drivers/pinctrl/meson/pinctrl-meson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index 5bcbd3ee758c..e61011284f29 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -713,7 +713,7 @@ static int meson_pinctrl_probe(struct platform_device *pdev) pc->desc.pins = pc->data->pins; pc->desc.npins = pc->data->num_pins; - pc->pcdev = pinctrl_register(&pc->desc, pc->dev, pc); + pc->pcdev = devm_pinctrl_register(pc->dev, &pc->desc, pc); if (IS_ERR(pc->pcdev)) { dev_err(pc->dev, "can't register pinctrl device"); return PTR_ERR(pc->pcdev); -- GitLab From 699097a9b8aeb7ae819dd8fefb7863799cbde98e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3771/9938] pinctrl: mvebu: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Thomas Petazzoni Cc: Hongzhou Yang Cc: Fabian Frederick Cc: Andrew Andrianov Reviewed-by: Thomas Petazzoni Signed-off-by: Linus Walleij --- drivers/pinctrl/mvebu/pinctrl-armada-370.c | 6 ------ drivers/pinctrl/mvebu/pinctrl-armada-375.c | 6 ------ drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 6 ------ drivers/pinctrl/mvebu/pinctrl-armada-39x.c | 6 ------ drivers/pinctrl/mvebu/pinctrl-armada-xp.c | 6 ------ drivers/pinctrl/mvebu/pinctrl-dove.c | 5 +---- drivers/pinctrl/mvebu/pinctrl-kirkwood.c | 6 ------ drivers/pinctrl/mvebu/pinctrl-mvebu.c | 9 +-------- drivers/pinctrl/mvebu/pinctrl-mvebu.h | 1 - drivers/pinctrl/mvebu/pinctrl-orion.c | 6 ------ 10 files changed, 2 insertions(+), 55 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c index 73dc1bc5f32c..9cc1cc3f5c34 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c @@ -417,18 +417,12 @@ static int armada_370_pinctrl_probe(struct platform_device *pdev) return mvebu_pinctrl_probe(pdev); } -static int armada_370_pinctrl_remove(struct platform_device *pdev) -{ - return mvebu_pinctrl_remove(pdev); -} - static struct platform_driver armada_370_pinctrl_driver = { .driver = { .name = "armada-370-pinctrl", .of_match_table = armada_370_pinctrl_of_match, }, .probe = armada_370_pinctrl_probe, - .remove = armada_370_pinctrl_remove, }; module_platform_driver(armada_370_pinctrl_driver); diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-375.c b/drivers/pinctrl/mvebu/pinctrl-armada-375.c index 54e9fbd0121f..070651431ca4 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-375.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-375.c @@ -435,18 +435,12 @@ static int armada_375_pinctrl_probe(struct platform_device *pdev) return mvebu_pinctrl_probe(pdev); } -static int armada_375_pinctrl_remove(struct platform_device *pdev) -{ - return mvebu_pinctrl_remove(pdev); -} - static struct platform_driver armada_375_pinctrl_driver = { .driver = { .name = "armada-375-pinctrl", .of_match_table = of_match_ptr(armada_375_pinctrl_of_match), }, .probe = armada_375_pinctrl_probe, - .remove = armada_375_pinctrl_remove, }; module_platform_driver(armada_375_pinctrl_driver); diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c index 6ec82c62dff7..4e84c8e4938c 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c @@ -446,18 +446,12 @@ static int armada_38x_pinctrl_probe(struct platform_device *pdev) return mvebu_pinctrl_probe(pdev); } -static int armada_38x_pinctrl_remove(struct platform_device *pdev) -{ - return mvebu_pinctrl_remove(pdev); -} - static struct platform_driver armada_38x_pinctrl_driver = { .driver = { .name = "armada-38x-pinctrl", .of_match_table = of_match_ptr(armada_38x_pinctrl_of_match), }, .probe = armada_38x_pinctrl_probe, - .remove = armada_38x_pinctrl_remove, }; module_platform_driver(armada_38x_pinctrl_driver); diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c index fcfe9b478a2e..e288f8ba0bf1 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c @@ -428,18 +428,12 @@ static int armada_39x_pinctrl_probe(struct platform_device *pdev) return mvebu_pinctrl_probe(pdev); } -static int armada_39x_pinctrl_remove(struct platform_device *pdev) -{ - return mvebu_pinctrl_remove(pdev); -} - static struct platform_driver armada_39x_pinctrl_driver = { .driver = { .name = "armada-39x-pinctrl", .of_match_table = of_match_ptr(armada_39x_pinctrl_of_match), }, .probe = armada_39x_pinctrl_probe, - .remove = armada_39x_pinctrl_remove, }; module_platform_driver(armada_39x_pinctrl_driver); diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c index bf70e0953576..e4ea71a9d985 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c @@ -502,18 +502,12 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev) return mvebu_pinctrl_probe(pdev); } -static int armada_xp_pinctrl_remove(struct platform_device *pdev) -{ - return mvebu_pinctrl_remove(pdev); -} - static struct platform_driver armada_xp_pinctrl_driver = { .driver = { .name = "armada-xp-pinctrl", .of_match_table = armada_xp_pinctrl_of_match, }, .probe = armada_xp_pinctrl_probe, - .remove = armada_xp_pinctrl_remove, .suspend = armada_xp_pinctrl_suspend, .resume = armada_xp_pinctrl_resume, }; diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c index 95bfd0653e8f..f93ae0dcef9c 100644 --- a/drivers/pinctrl/mvebu/pinctrl-dove.c +++ b/drivers/pinctrl/mvebu/pinctrl-dove.c @@ -840,12 +840,9 @@ static int dove_pinctrl_probe(struct platform_device *pdev) static int dove_pinctrl_remove(struct platform_device *pdev) { - int ret; - - ret = mvebu_pinctrl_remove(pdev); if (!IS_ERR(clk)) clk_disable_unprepare(clk); - return ret; + return 0; } static struct platform_driver dove_pinctrl_driver = { diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c index 0f07dc554a1d..a78e9a4997ba 100644 --- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c +++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c @@ -481,18 +481,12 @@ static int kirkwood_pinctrl_probe(struct platform_device *pdev) return mvebu_pinctrl_probe(pdev); } -static int kirkwood_pinctrl_remove(struct platform_device *pdev) -{ - return mvebu_pinctrl_remove(pdev); -} - static struct platform_driver kirkwood_pinctrl_driver = { .driver = { .name = "kirkwood-pinctrl", .of_match_table = kirkwood_pinctrl_of_match, }, .probe = kirkwood_pinctrl_probe, - .remove = kirkwood_pinctrl_remove, }; module_platform_driver(kirkwood_pinctrl_driver); diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 3ef798fac81b..b6ec6db78351 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -711,7 +711,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) return ret; } - pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl); + pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pctl->desc, pctl); if (IS_ERR(pctl->pctldev)) { dev_err(&pdev->dev, "unable to register pinctrl driver\n"); return PTR_ERR(pctl->pctldev); @@ -725,10 +725,3 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) return 0; } - -int mvebu_pinctrl_remove(struct platform_device *pdev) -{ - struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev); - pinctrl_unregister(pctl->pctldev); - return 0; -} diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h index 65a98e6f7265..b75a5f4adf3b 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h @@ -202,6 +202,5 @@ static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid, } int mvebu_pinctrl_probe(struct platform_device *pdev); -int mvebu_pinctrl_remove(struct platform_device *pdev); #endif diff --git a/drivers/pinctrl/mvebu/pinctrl-orion.c b/drivers/pinctrl/mvebu/pinctrl-orion.c index 3b7122d826e4..345c3df669a0 100644 --- a/drivers/pinctrl/mvebu/pinctrl-orion.c +++ b/drivers/pinctrl/mvebu/pinctrl-orion.c @@ -239,18 +239,12 @@ static int orion_pinctrl_probe(struct platform_device *pdev) return mvebu_pinctrl_probe(pdev); } -static int orion_pinctrl_remove(struct platform_device *pdev) -{ - return mvebu_pinctrl_remove(pdev); -} - static struct platform_driver orion_pinctrl_driver = { .driver = { .name = "orion-pinctrl", .of_match_table = of_match_ptr(orion_pinctrl_of_match), }, .probe = orion_pinctrl_probe, - .remove = orion_pinctrl_remove, }; module_platform_driver(orion_pinctrl_driver); -- GitLab From 0ee60110ca567b951c4855c12c472dd8f9193589 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3772/9938] pinctrl: nomadic: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Alessandro Rubini Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Linus Walleij --- drivers/pinctrl/nomadik/pinctrl-abx500.c | 3 ++- drivers/pinctrl/nomadik/pinctrl-nomadik.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 532356823eea..7d343c22c90c 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -1212,7 +1212,8 @@ static int abx500_gpio_probe(struct platform_device *pdev) abx500_pinctrl_desc.pins = pct->soc->pins; abx500_pinctrl_desc.npins = pct->soc->npins; - pct->pctldev = pinctrl_register(&abx500_pinctrl_desc, &pdev->dev, pct); + pct->pctldev = devm_pinctrl_register(&pdev->dev, &abx500_pinctrl_desc, + pct); if (IS_ERR(pct->pctldev)) { dev_err(&pdev->dev, "could not register abx500 pinctrl driver\n"); diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index c9c8c17678d7..7a7b9846ff57 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -2044,7 +2044,7 @@ static int nmk_pinctrl_probe(struct platform_device *pdev) nmk_pinctrl_desc.npins = npct->soc->npins; npct->dev = &pdev->dev; - npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct); + npct->pctl = devm_pinctrl_register(&pdev->dev, &nmk_pinctrl_desc, npct); if (IS_ERR(npct->pctl)) { dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n"); return PTR_ERR(npct->pctl); -- GitLab From b46ddfe60ba0a37f7bdfc871ff3802465c92e6d9 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3773/9938] pinctrl: spmi-gpio: Use devm_pinctrl_register() for pinctrl registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: "Björn Andersson" Cc: "Ivan T. Ivanov" Cc: Lee Jones Cc: Stephen Boyd Cc: Jonas Gorski Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 857ccfa67986..686accb89f52 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -764,14 +764,14 @@ static int pmic_gpio_probe(struct platform_device *pdev) state->chip.of_gpio_n_cells = 2; state->chip.can_sleep = false; - state->ctrl = pinctrl_register(pctrldesc, dev, state); + state->ctrl = devm_pinctrl_register(dev, pctrldesc, state); if (IS_ERR(state->ctrl)) return PTR_ERR(state->ctrl); ret = gpiochip_add_data(&state->chip, state); if (ret) { dev_err(state->dev, "can't add gpio chip\n"); - goto err_chip; + return ret; } ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins); @@ -784,8 +784,6 @@ static int pmic_gpio_probe(struct platform_device *pdev) err_range: gpiochip_remove(&state->chip); -err_chip: - pinctrl_unregister(state->ctrl); return ret; } @@ -794,7 +792,6 @@ static int pmic_gpio_remove(struct platform_device *pdev) struct pmic_gpio_state *state = platform_get_drvdata(pdev); gpiochip_remove(&state->chip); - pinctrl_unregister(state->ctrl); return 0; } -- GitLab From ce18e595b7f9feee947eb4d3ecb1dfdd704f46a4 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3774/9938] pinctrl: spmi: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Bjorn Andersson Cc: Ivan T. Ivanov Cc: Lee Jones Cc: Stephen Boyd Cc: Jonas Gorski Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-spmi-mpp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c index 469660055809..1735ffef9d5c 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c @@ -877,14 +877,14 @@ static int pmic_mpp_probe(struct platform_device *pdev) state->chip.of_gpio_n_cells = 2; state->chip.can_sleep = false; - state->ctrl = pinctrl_register(pctrldesc, dev, state); + state->ctrl = devm_pinctrl_register(dev, pctrldesc, state); if (IS_ERR(state->ctrl)) return PTR_ERR(state->ctrl); ret = gpiochip_add_data(&state->chip, state); if (ret) { dev_err(state->dev, "can't add gpio chip\n"); - goto err_chip; + return ret; } ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins); @@ -897,8 +897,6 @@ static int pmic_mpp_probe(struct platform_device *pdev) err_range: gpiochip_remove(&state->chip); -err_chip: - pinctrl_unregister(state->ctrl); return ret; } @@ -907,7 +905,6 @@ static int pmic_mpp_remove(struct platform_device *pdev) struct pmic_mpp_state *state = platform_get_drvdata(pdev); gpiochip_remove(&state->chip); - pinctrl_unregister(state->ctrl); return 0; } -- GitLab From 16f3b9c3a5bb5f1d4c73356c93dc0f25a0e97b8f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3775/9938] pinctrl: ssbi-gpi: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Bjorn Andersson Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c index ecd784b6c743..d3f5501d17ee 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c @@ -729,7 +729,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) pctrl->desc.custom_conf_items = pm8xxx_conf_items; #endif - pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl); + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); if (IS_ERR(pctrl->pctrl)) { dev_err(&pdev->dev, "couldn't register pm8xxx gpio driver\n"); return PTR_ERR(pctrl->pctrl); @@ -745,7 +745,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { dev_err(&pdev->dev, "failed register gpiochip\n"); - goto unregister_pinctrl; + return ret; } ret = gpiochip_add_pin_range(&pctrl->chip, @@ -765,9 +765,6 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) unregister_gpiochip: gpiochip_remove(&pctrl->chip); -unregister_pinctrl: - pinctrl_unregister(pctrl->pctrl); - return ret; } @@ -777,8 +774,6 @@ static int pm8xxx_gpio_remove(struct platform_device *pdev) gpiochip_remove(&pctrl->chip); - pinctrl_unregister(pctrl->pctrl); - return 0; } -- GitLab From 5f5e111af617c2371552af3e516841adb2e25f58 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3776/9938] pinctrl: ssbi-mpp: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Bjorn Andersson Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c index ac79021eb261..9191727aff5e 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c @@ -820,7 +820,7 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev) pctrl->desc.custom_conf_items = pm8xxx_conf_items; #endif - pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl); + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); if (IS_ERR(pctrl->pctrl)) { dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n"); return PTR_ERR(pctrl->pctrl); @@ -836,7 +836,7 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev) ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { dev_err(&pdev->dev, "failed register gpiochip\n"); - goto unregister_pinctrl; + return ret; } ret = gpiochip_add_pin_range(&pctrl->chip, @@ -856,9 +856,6 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev) unregister_gpiochip: gpiochip_remove(&pctrl->chip); -unregister_pinctrl: - pinctrl_unregister(pctrl->pctrl); - return ret; } @@ -868,8 +865,6 @@ static int pm8xxx_mpp_remove(struct platform_device *pdev) gpiochip_remove(&pctrl->chip); - pinctrl_unregister(pctrl->pctrl); - return 0; } -- GitLab From fe0267f47a9f32f6e73ce1d3cb97eafc63d9be5c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3777/9938] pinctrl: msm: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Bjorn Andersson Cc: Thomas Gleixner Cc: Lee Jones Cc: Stephen Boyd Reviewed-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-msm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index f9322d4c2294..1a44e1d03390 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -898,17 +898,16 @@ int msm_pinctrl_probe(struct platform_device *pdev, msm_pinctrl_desc.name = dev_name(&pdev->dev); msm_pinctrl_desc.pins = pctrl->soc->pins; msm_pinctrl_desc.npins = pctrl->soc->npins; - pctrl->pctrl = pinctrl_register(&msm_pinctrl_desc, &pdev->dev, pctrl); + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &msm_pinctrl_desc, + pctrl); if (IS_ERR(pctrl->pctrl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(pctrl->pctrl); } ret = msm_gpio_init(pctrl); - if (ret) { - pinctrl_unregister(pctrl->pctrl); + if (ret) return ret; - } platform_set_drvdata(pdev, pctrl); @@ -923,7 +922,6 @@ int msm_pinctrl_remove(struct platform_device *pdev) struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); gpiochip_remove(&pctrl->chip); - pinctrl_unregister(pctrl->pctrl); unregister_restart_handler(&pctrl->restart_nb); -- GitLab From 6d33ee7a05341f9ddcaa9374d3d6800919e2f150 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3778/9938] pinctrl: pxa: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Daniel Mack Cc: Haojian Zhuang Cc: Robert Jarzmik Cc: linux-arm-kernel@lists.infradead.org Acked-by: Robert Jarzmik Signed-off-by: Linus Walleij --- drivers/pinctrl/pxa/pinctrl-pxa2xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c index 6098685f0116..866aa3ce1ac9 100644 --- a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c @@ -416,7 +416,7 @@ int pxa2xx_pinctrl_init(struct platform_device *pdev, if (ret) return ret; - pctl->pctl_dev = pinctrl_register(&pctl->desc, &pdev->dev, pctl); + pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->desc, pctl); if (IS_ERR(pctl->pctl_dev)) { dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); return PTR_ERR(pctl->pctl_dev); -- GitLab From 40011bfe15c4c5907391d9d0efa3801a3f28ddc6 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3779/9938] pinctrl: exynos5440: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Tomasz Figa Cc: Kukjin Kim Cc: Krzysztof Kozlowski Signed-off-by: Linus Walleij --- drivers/pinctrl/samsung/pinctrl-exynos5440.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c index 00ab63abf1d9..71f9f13e826d 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c @@ -788,7 +788,7 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev, if (ret) return ret; - pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, priv); + pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, priv); if (IS_ERR(pctl_dev)) { dev_err(&pdev->dev, "could not register pinctrl driver\n"); return PTR_ERR(pctl_dev); -- GitLab From 9ed19e06ca4dcc12d621b02ed6150b5ffcf2a249 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 28 Feb 2016 14:36:42 +0530 Subject: [PATCH 3780/9938] pinctrl: samsung: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Tomasz Figa Cc: Kukjin Kim Cc: Krzysztof Kozlowski Signed-off-by: Linus Walleij --- drivers/pinctrl/samsung/pinctrl-samsung.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 5cc97f85db02..ed0b70881e19 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -884,7 +884,8 @@ static int samsung_pinctrl_register(struct platform_device *pdev, if (ret) return ret; - drvdata->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, drvdata); + drvdata->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, + drvdata); if (IS_ERR(drvdata->pctl_dev)) { dev_err(&pdev->dev, "could not register pinctrl driver\n"); return PTR_ERR(drvdata->pctl_dev); -- GitLab From 67ec8d7b484639040b7a75b289a2a1d1763e3430 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 28 Feb 2016 14:37:47 +0530 Subject: [PATCH 3781/9938] pinctrl: ish-pfc: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Laurent Pinchart Cc: Geert Uytterhoeven Cc: linux-renesas-soc@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/core.c | 1 - drivers/pinctrl/sh-pfc/core.h | 2 -- drivers/pinctrl/sh-pfc/pinctrl.c | 13 +------------ 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 0497bbb8a8e7..9a085cbb9d18 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -603,7 +603,6 @@ static int sh_pfc_remove(struct platform_device *pdev) #ifdef CONFIG_PINCTRL_SH_PFC_GPIO sh_pfc_unregister_gpiochip(pfc); #endif - sh_pfc_unregister_pinctrl(pfc); return 0; } diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index fc05d0c516f3..dc1b2adb24c5 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h @@ -50,14 +50,12 @@ struct sh_pfc { struct sh_pfc_chip *func; #endif - struct sh_pfc_pinctrl *pinctrl; }; int sh_pfc_register_gpiochip(struct sh_pfc *pfc); int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc); int sh_pfc_register_pinctrl(struct sh_pfc *pfc); -int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc); u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width); void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width, diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index 8efaa0631be6..fdb445d68b9a 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -789,7 +789,6 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc) return -ENOMEM; pmx->pfc = pfc; - pfc->pinctrl = pmx; ret = sh_pfc_map_pins(pfc, pmx); if (ret < 0) @@ -803,19 +802,9 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc) pmx->pctl_desc.pins = pmx->pins; pmx->pctl_desc.npins = pfc->info->nr_pins; - pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx); + pmx->pctl = devm_pinctrl_register(pfc->dev, &pmx->pctl_desc, pmx); if (IS_ERR(pmx->pctl)) return PTR_ERR(pmx->pctl); return 0; } - -int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc) -{ - struct sh_pfc_pinctrl *pmx = pfc->pinctrl; - - pinctrl_unregister(pmx->pctl); - - pfc->pinctrl = NULL; - return 0; -} -- GitLab From d39de3139180ff90d43a5f4093ada4b31af40e9d Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3782/9938] pinctrl: spear: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Viresh Kumar Cc: spear-devel@list.st.com Cc: linux-arm-kernel@lists.infradead.org Acked-by: Viresh Kumar Signed-off-by: Linus Walleij --- drivers/pinctrl/spear/pinctrl-spear.c | 11 +---------- drivers/pinctrl/spear/pinctrl-spear.h | 1 - drivers/pinctrl/spear/pinctrl-spear1310.c | 6 ------ drivers/pinctrl/spear/pinctrl-spear1340.c | 6 ------ drivers/pinctrl/spear/pinctrl-spear300.c | 6 ------ drivers/pinctrl/spear/pinctrl-spear310.c | 6 ------ drivers/pinctrl/spear/pinctrl-spear320.c | 6 ------ 7 files changed, 1 insertion(+), 41 deletions(-) diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 0afaf79a4e51..4db52ba38d8d 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -395,7 +395,7 @@ int spear_pinctrl_probe(struct platform_device *pdev, spear_pinctrl_desc.pins = machdata->pins; spear_pinctrl_desc.npins = machdata->npins; - pmx->pctl = pinctrl_register(&spear_pinctrl_desc, &pdev->dev, pmx); + pmx->pctl = devm_pinctrl_register(&pdev->dev, &spear_pinctrl_desc, pmx); if (IS_ERR(pmx->pctl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(pmx->pctl); @@ -403,12 +403,3 @@ int spear_pinctrl_probe(struct platform_device *pdev, return 0; } - -int spear_pinctrl_remove(struct platform_device *pdev) -{ - struct spear_pmx *pmx = platform_get_drvdata(pdev); - - pinctrl_unregister(pmx->pctl); - - return 0; -} diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h index 27c2cc8d83ad..aa5cf7032231 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.h +++ b/drivers/pinctrl/spear/pinctrl-spear.h @@ -197,7 +197,6 @@ void pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup, unsigned count, u16 reg); int spear_pinctrl_probe(struct platform_device *pdev, struct spear_pinctrl_machdata *machdata); -int spear_pinctrl_remove(struct platform_device *pdev); #define SPEAR_PIN_0_TO_101 \ PINCTRL_PIN(0, "PLGPIO0"), \ diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index 92611bb757ac..18210681c737 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -2704,18 +2704,12 @@ static int spear1310_pinctrl_probe(struct platform_device *pdev) return spear_pinctrl_probe(pdev, &spear1310_machdata); } -static int spear1310_pinctrl_remove(struct platform_device *pdev) -{ - return spear_pinctrl_remove(pdev); -} - static struct platform_driver spear1310_pinctrl_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = spear1310_pinctrl_of_match, }, .probe = spear1310_pinctrl_probe, - .remove = spear1310_pinctrl_remove, }; static int __init spear1310_pinctrl_init(void) diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index f842e9dc40d0..c01fb23ee636 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -2020,18 +2020,12 @@ static int spear1340_pinctrl_probe(struct platform_device *pdev) return spear_pinctrl_probe(pdev, &spear1340_machdata); } -static int spear1340_pinctrl_remove(struct platform_device *pdev) -{ - return spear_pinctrl_remove(pdev); -} - static struct platform_driver spear1340_pinctrl_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = spear1340_pinctrl_of_match, }, .probe = spear1340_pinctrl_probe, - .remove = spear1340_pinctrl_remove, }; static int __init spear1340_pinctrl_init(void) diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c index d998a2ccff48..111148daa3f1 100644 --- a/drivers/pinctrl/spear/pinctrl-spear300.c +++ b/drivers/pinctrl/spear/pinctrl-spear300.c @@ -677,18 +677,12 @@ static int spear300_pinctrl_probe(struct platform_device *pdev) return 0; } -static int spear300_pinctrl_remove(struct platform_device *pdev) -{ - return spear_pinctrl_remove(pdev); -} - static struct platform_driver spear300_pinctrl_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = spear300_pinctrl_of_match, }, .probe = spear300_pinctrl_probe, - .remove = spear300_pinctrl_remove, }; static int __init spear300_pinctrl_init(void) diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c index 609b18aceb16..a7b000062985 100644 --- a/drivers/pinctrl/spear/pinctrl-spear310.c +++ b/drivers/pinctrl/spear/pinctrl-spear310.c @@ -400,18 +400,12 @@ static int spear310_pinctrl_probe(struct platform_device *pdev) return 0; } -static int spear310_pinctrl_remove(struct platform_device *pdev) -{ - return spear_pinctrl_remove(pdev); -} - static struct platform_driver spear310_pinctrl_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = spear310_pinctrl_of_match, }, .probe = spear310_pinctrl_probe, - .remove = spear310_pinctrl_remove, }; static int __init spear310_pinctrl_init(void) diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index c07114431bd4..e2b3817701dc 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -3441,18 +3441,12 @@ static int spear320_pinctrl_probe(struct platform_device *pdev) return 0; } -static int spear320_pinctrl_remove(struct platform_device *pdev) -{ - return spear_pinctrl_remove(pdev); -} - static struct platform_driver spear320_pinctrl_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = spear320_pinctrl_of_match, }, .probe = spear320_pinctrl_probe, - .remove = spear320_pinctrl_remove, }; static int __init spear320_pinctrl_init(void) -- GitLab From 88edad04d9bc0f87e44d5a44f438a399c31432ba Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3783/9938] pinctrl: stm32: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Maxime Coquelin Cc: Patrice Chotard Acked-by: Maxime Coquelin Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index b97b7c01f942..72b790450118 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -813,10 +813,11 @@ int stm32_pctl_probe(struct platform_device *pdev) pctl->pctl_desc.pmxops = &stm32_pmx_ops; pctl->dev = &pdev->dev; - pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl); - if (!pctl->pctl_dev) { + pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc, + pctl); + if (IS_ERR(pctl->pctl_dev)) { dev_err(&pdev->dev, "Failed pinctrl registration\n"); - return -EINVAL; + return PTR_ERR(pctl->pctl_dev); } for (i = 0; i < pctl->nbanks; i++) -- GitLab From 45078ea03f169ddb1bf13aceba748c4bfca524ac Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3784/9938] pinctrl: ssbi-mpp: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Maxime Ripard Cc: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 12a1dfabb1af..4a3166193562 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -932,18 +932,15 @@ int sunxi_pinctrl_init(struct platform_device *pdev, pctrl_desc->pctlops = &sunxi_pctrl_ops; pctrl_desc->pmxops = &sunxi_pmx_ops; - pctl->pctl_dev = pinctrl_register(pctrl_desc, - &pdev->dev, pctl); + pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, pctrl_desc, pctl); if (IS_ERR(pctl->pctl_dev)) { dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); return PTR_ERR(pctl->pctl_dev); } pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL); - if (!pctl->chip) { - ret = -ENOMEM; - goto pinctrl_error; - } + if (!pctl->chip) + return -ENOMEM; last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number; pctl->chip->owner = THIS_MODULE; @@ -965,7 +962,7 @@ int sunxi_pinctrl_init(struct platform_device *pdev, ret = gpiochip_add_data(pctl->chip, pctl); if (ret) - goto pinctrl_error; + return ret; for (i = 0; i < pctl->desc->npins; i++) { const struct sunxi_desc_pin *pin = pctl->desc->pins + i; @@ -1041,7 +1038,5 @@ int sunxi_pinctrl_init(struct platform_device *pdev, clk_disable_unprepare(clk); gpiochip_error: gpiochip_remove(pctl->chip); -pinctrl_error: - pinctrl_unregister(pctl->pctl_dev); return ret; } -- GitLab From f1daa8a1a96812372f3afda90c6dc29d62f7f9b3 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3785/9938] pinctrl: tegra: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Stephen Warren Cc: Thierry Reding Cc: Alexandre Courbot Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/tegra/pinctrl-tegra.c | 12 +----------- drivers/pinctrl/tegra/pinctrl-tegra.h | 2 -- drivers/pinctrl/tegra/pinctrl-tegra114.c | 1 - drivers/pinctrl/tegra/pinctrl-tegra124.c | 1 - drivers/pinctrl/tegra/pinctrl-tegra20.c | 1 - drivers/pinctrl/tegra/pinctrl-tegra210.c | 1 - drivers/pinctrl/tegra/pinctrl-tegra30.c | 1 - 7 files changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index 053d62016e5a..861baf29ef70 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -735,7 +735,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev, return PTR_ERR(pmx->regs[i]); } - pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx); + pmx->pctl = devm_pinctrl_register(&pdev->dev, &tegra_pinctrl_desc, pmx); if (IS_ERR(pmx->pctl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(pmx->pctl); @@ -753,13 +753,3 @@ int tegra_pinctrl_probe(struct platform_device *pdev, return 0; } EXPORT_SYMBOL_GPL(tegra_pinctrl_probe); - -int tegra_pinctrl_remove(struct platform_device *pdev) -{ - struct tegra_pmx *pmx = platform_get_drvdata(pdev); - - pinctrl_unregister(pmx->pctl); - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_pinctrl_remove); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h index 20b893443d0b..d2ced17382b5 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.h +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h @@ -195,6 +195,4 @@ struct tegra_pinctrl_soc_data { int tegra_pinctrl_probe(struct platform_device *pdev, const struct tegra_pinctrl_soc_data *soc_data); -int tegra_pinctrl_remove(struct platform_device *pdev); - #endif diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c index b831dcfa5359..4851d169f4c7 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra114.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c @@ -1865,7 +1865,6 @@ static struct platform_driver tegra114_pinctrl_driver = { .of_match_table = tegra114_pinctrl_of_match, }, .probe = tegra114_pinctrl_probe, - .remove = tegra_pinctrl_remove, }; module_platform_driver(tegra114_pinctrl_driver); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c index 199d301f7c3e..a0ce723a9482 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra124.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c @@ -2077,7 +2077,6 @@ static struct platform_driver tegra124_pinctrl_driver = { .of_match_table = tegra124_pinctrl_of_match, }, .probe = tegra124_pinctrl_probe, - .remove = tegra_pinctrl_remove, }; module_platform_driver(tegra124_pinctrl_driver); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c index a2d0b98d72b3..09bad6980ad1 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra20.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -2245,7 +2245,6 @@ static struct platform_driver tegra20_pinctrl_driver = { .of_match_table = tegra20_pinctrl_of_match, }, .probe = tegra20_pinctrl_probe, - .remove = tegra_pinctrl_remove, }; module_platform_driver(tegra20_pinctrl_driver); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c index 825bf62d939a..2d856af389ef 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra210.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c @@ -1583,7 +1583,6 @@ static struct platform_driver tegra210_pinctrl_driver = { .of_match_table = tegra210_pinctrl_of_match, }, .probe = tegra210_pinctrl_probe, - .remove = tegra_pinctrl_remove, }; module_platform_driver(tegra210_pinctrl_driver); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c index 4dc9642c914a..fb7817fea2d9 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra30.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c @@ -2500,7 +2500,6 @@ static struct platform_driver tegra30_pinctrl_driver = { .of_match_table = tegra30_pinctrl_of_match, }, .probe = tegra30_pinctrl_probe, - .remove = tegra_pinctrl_remove, }; module_platform_driver(tegra30_pinctrl_driver); -- GitLab From e46e3ef3d7472f8bdf8f26801847f375300a666b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3786/9938] pinctrl: tegra-xusb: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Stephen Warren Cc: Thierry Reding Cc: Alexandre Courbot Cc: Jon Hunter Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/tegra/pinctrl-tegra-xusb.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c index e58b5f344b34..5ce174ad4fb3 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c @@ -914,7 +914,8 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops; padctl->desc.owner = THIS_MODULE; - padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl); + padctl->pinctrl = devm_pinctrl_register(&pdev->dev, &padctl->desc, + padctl); if (IS_ERR(padctl->pinctrl)) { dev_err(&pdev->dev, "failed to register pincontrol\n"); err = PTR_ERR(padctl->pinctrl); @@ -924,7 +925,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops); if (IS_ERR(phy)) { err = PTR_ERR(phy); - goto unregister; + goto reset; } padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy; @@ -933,7 +934,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops); if (IS_ERR(phy)) { err = PTR_ERR(phy); - goto unregister; + goto reset; } padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy; @@ -944,13 +945,11 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) if (IS_ERR(padctl->provider)) { err = PTR_ERR(padctl->provider); dev_err(&pdev->dev, "failed to register PHYs: %d\n", err); - goto unregister; + goto reset; } return 0; -unregister: - pinctrl_unregister(padctl->pinctrl); reset: reset_control_assert(padctl->rst); return err; @@ -961,8 +960,6 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev) struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); int err; - pinctrl_unregister(padctl->pinctrl); - err = reset_control_assert(padctl->rst); if (err < 0) dev_err(&pdev->dev, "failed to assert reset: %d\n", err); -- GitLab From 1ac471edd909184a94893aac075db8408539178e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3787/9938] pinctrl: uniphier: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Masahiro Yamada Acked-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 12 +----------- drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c | 1 - drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 1 - drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 1 - drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 1 - drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 1 - drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 1 - drivers/pinctrl/uniphier/pinctrl-uniphier.h | 2 -- 8 files changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index c9e4a852afa5..967400971d45 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -665,7 +665,7 @@ int uniphier_pinctrl_probe(struct platform_device *pdev, desc->pmxops = &uniphier_pmxops; desc->confops = &uniphier_confops; - priv->pctldev = pinctrl_register(desc, dev, priv); + priv->pctldev = devm_pinctrl_register(dev, desc, priv); if (IS_ERR(priv->pctldev)) { dev_err(dev, "failed to register UniPhier pinctrl driver\n"); return PTR_ERR(priv->pctldev); @@ -676,13 +676,3 @@ int uniphier_pinctrl_probe(struct platform_device *pdev, return 0; } EXPORT_SYMBOL_GPL(uniphier_pinctrl_probe); - -int uniphier_pinctrl_remove(struct platform_device *pdev) -{ - struct uniphier_pinctrl_priv *priv = platform_get_drvdata(pdev); - - pinctrl_unregister(priv->pctldev); - - return 0; -} -EXPORT_SYMBOL_GPL(uniphier_pinctrl_remove); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c index a7056dccfa53..4a0439c80aa0 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c @@ -878,7 +878,6 @@ MODULE_DEVICE_TABLE(of, ph1_ld4_pinctrl_match); static struct platform_driver ph1_ld4_pinctrl_driver = { .probe = ph1_ld4_pinctrl_probe, - .remove = uniphier_pinctrl_remove, .driver = { .name = DRIVER_NAME, .of_match_table = ph1_ld4_pinctrl_match, diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c index 1824831bb4da..150d33928df2 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c @@ -1266,7 +1266,6 @@ MODULE_DEVICE_TABLE(of, ph1_ld6b_pinctrl_match); static struct platform_driver ph1_ld6b_pinctrl_driver = { .probe = ph1_ld6b_pinctrl_probe, - .remove = uniphier_pinctrl_remove, .driver = { .name = DRIVER_NAME, .of_match_table = ph1_ld6b_pinctrl_match, diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c index ec8e92dfaf8c..b1f09e68f90e 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c @@ -1552,7 +1552,6 @@ MODULE_DEVICE_TABLE(of, ph1_pro4_pinctrl_match); static struct platform_driver ph1_pro4_pinctrl_driver = { .probe = ph1_pro4_pinctrl_probe, - .remove = uniphier_pinctrl_remove, .driver = { .name = DRIVER_NAME, .of_match_table = ph1_pro4_pinctrl_match, diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c index e3d648eae85a..3087f76752a6 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c @@ -1343,7 +1343,6 @@ MODULE_DEVICE_TABLE(of, ph1_pro5_pinctrl_match); static struct platform_driver ph1_pro5_pinctrl_driver = { .probe = ph1_pro5_pinctrl_probe, - .remove = uniphier_pinctrl_remove, .driver = { .name = DRIVER_NAME, .of_match_table = ph1_pro5_pinctrl_match, diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c index bc00d7591c59..e868030ff31c 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c @@ -1261,7 +1261,6 @@ MODULE_DEVICE_TABLE(of, proxstream2_pinctrl_match); static struct platform_driver proxstream2_pinctrl_driver = { .probe = proxstream2_pinctrl_probe, - .remove = uniphier_pinctrl_remove, .driver = { .name = DRIVER_NAME, .of_match_table = proxstream2_pinctrl_match, diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c index c3700a33a5da..ceb7a9899bde 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c @@ -786,7 +786,6 @@ MODULE_DEVICE_TABLE(of, ph1_sld8_pinctrl_match); static struct platform_driver ph1_sld8_pinctrl_driver = { .probe = ph1_sld8_pinctrl_probe, - .remove = uniphier_pinctrl_remove, .driver = { .name = DRIVER_NAME, .of_match_table = ph1_sld8_pinctrl_match, diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h index e1e98b868be5..a21154f4b453 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h @@ -212,6 +212,4 @@ int uniphier_pinctrl_probe(struct platform_device *pdev, struct pinctrl_desc *desc, struct uniphier_pinctrl_socdata *socdata); -int uniphier_pinctrl_remove(struct platform_device *pdev); - #endif /* __PINCTRL_UNIPHIER_H__ */ -- GitLab From fb7c579ab01f010a353d117e484edb05e6f3745c Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 19 Apr 2016 16:28:52 +0200 Subject: [PATCH 3788/9938] ieee802154: atusb: implement .set_csma_params ops callback Catching up with the stack here and implement CSMA parameter setting. Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index b1cd865ade2e..2d8de9f40ec4 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -472,6 +472,23 @@ atusb_set_txpower(struct ieee802154_hw *hw, s32 mbm) return -EINVAL; } +static int +atusb_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries) +{ + struct atusb *atusb = hw->priv; + int ret; + + ret = atusb_write_subreg(atusb, SR_MIN_BE, min_be); + if (ret) + return ret; + + ret = atusb_write_subreg(atusb, SR_MAX_BE, max_be); + if (ret) + return ret; + + return atusb_write_subreg(atusb, SR_MAX_CSMA_RETRIES, retries); +} + static int atusb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on) { @@ -508,6 +525,7 @@ static struct ieee802154_ops atusb_ops = { .stop = atusb_stop, .set_hw_addr_filt = atusb_set_hw_addr_filt, .set_txpower = atusb_set_txpower, + .set_csma_params = atusb_set_csma_params, .set_promiscuous_mode = atusb_set_promiscuous_mode, }; @@ -636,7 +654,7 @@ static int atusb_probe(struct usb_interface *interface, hw->parent = &usb_dev->dev; hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | - IEEE802154_HW_PROMISCUOUS; + IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS; hw->phy->flags = WPAN_PHY_FLAG_TXPOWER; -- GitLab From 0f4715c87031fb6a128103f8e640c4ce4dfdea9a Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 19 Apr 2016 16:28:53 +0200 Subject: [PATCH 3789/9938] ieee802154: atusb: implement .set_cca_ed_level ops callback Catching up with the stack here and implement CCA ED level setting. Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 2d8de9f40ec4..94f84574f9ee 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -472,6 +472,26 @@ atusb_set_txpower(struct ieee802154_hw *hw, s32 mbm) return -EINVAL; } +#define ATUSB_MAX_ED_LEVELS 0xF +static const s32 atusb_ed_levels[ATUSB_MAX_ED_LEVELS + 1] = { + -9100, -8900, -8700, -8500, -8300, -8100, -7900, -7700, -7500, -7300, + -7100, -6900, -6700, -6500, -6300, -6100, +}; + +static int +atusb_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm) +{ + struct atusb *atusb = hw->priv; + u32 i; + + for (i = 0; i < hw->phy->supported.cca_ed_levels_size; i++) { + if (hw->phy->supported.cca_ed_levels[i] == mbm) + return atusb_write_subreg(atusb, SR_CCA_ED_THRES, i); + } + + return -EINVAL; +} + static int atusb_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries) { @@ -525,6 +545,7 @@ static struct ieee802154_ops atusb_ops = { .stop = atusb_stop, .set_hw_addr_filt = atusb_set_hw_addr_filt, .set_txpower = atusb_set_txpower, + .set_cca_ed_level = atusb_set_cca_ed_level, .set_csma_params = atusb_set_csma_params, .set_promiscuous_mode = atusb_set_promiscuous_mode, }; @@ -656,7 +677,10 @@ static int atusb_probe(struct usb_interface *interface, hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS; - hw->phy->flags = WPAN_PHY_FLAG_TXPOWER; + hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL; + + hw->phy->supported.cca_ed_levels = atusb_ed_levels; + hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(atusb_ed_levels); hw->phy->current_page = 0; hw->phy->current_channel = 11; /* reset default */ @@ -665,6 +689,7 @@ static int atusb_probe(struct usb_interface *interface, hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->transmit_power = hw->phy->supported.tx_powers[0]; ieee802154_random_extended_addr(&hw->phy->perm_extended_addr); + hw->phy->cca_ed_level = hw->phy->supported.cca_ed_levels[7]; atusb_command(atusb, ATUSB_RF_RESET, 0); atusb_get_and_show_chip(atusb); -- GitLab From 308dbb7afde27f9ba359624e6cc1dcba9c93f49a Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 19 Apr 2016 16:28:54 +0200 Subject: [PATCH 3790/9938] ieee802154: atusb: implement .set_cca_mode ops callback Catching up with the stack here and implement CCA mode setting. Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 44 +++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 94f84574f9ee..72128b3aaec4 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -478,6 +478,39 @@ static const s32 atusb_ed_levels[ATUSB_MAX_ED_LEVELS + 1] = { -7100, -6900, -6700, -6500, -6300, -6100, }; +static int +atusb_set_cca_mode(struct ieee802154_hw *hw, const struct wpan_phy_cca *cca) +{ + struct atusb *atusb = hw->priv; + u8 val; + + /* mapping 802.15.4 to driver spec */ + switch (cca->mode) { + case NL802154_CCA_ENERGY: + val = 1; + break; + case NL802154_CCA_CARRIER: + val = 2; + break; + case NL802154_CCA_ENERGY_CARRIER: + switch (cca->opt) { + case NL802154_CCA_OPT_ENERGY_CARRIER_AND: + val = 3; + break; + case NL802154_CCA_OPT_ENERGY_CARRIER_OR: + val = 0; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return atusb_write_subreg(atusb, SR_CCA_MODE, val); +} + static int atusb_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm) { @@ -545,6 +578,7 @@ static struct ieee802154_ops atusb_ops = { .stop = atusb_stop, .set_hw_addr_filt = atusb_set_hw_addr_filt, .set_txpower = atusb_set_txpower, + .set_cca_mode = atusb_set_cca_mode, .set_cca_ed_level = atusb_set_cca_ed_level, .set_csma_params = atusb_set_csma_params, .set_promiscuous_mode = atusb_set_promiscuous_mode, @@ -677,11 +711,19 @@ static int atusb_probe(struct usb_interface *interface, hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS; - hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL; + hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL | + WPAN_PHY_FLAG_CCA_MODE; + + hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) | + BIT(NL802154_CCA_CARRIER) | BIT(NL802154_CCA_ENERGY_CARRIER); + hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND) | + BIT(NL802154_CCA_OPT_ENERGY_CARRIER_OR); hw->phy->supported.cca_ed_levels = atusb_ed_levels; hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(atusb_ed_levels); + hw->phy->cca.mode = NL802154_CCA_ENERGY; + hw->phy->current_page = 0; hw->phy->current_channel = 11; /* reset default */ hw->phy->supported.channels[0] = 0x7FFF800; -- GitLab From 151c37bc29bcbc4b34450c76a8125a5b155520e7 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 19 Apr 2016 16:28:55 +0200 Subject: [PATCH 3791/9938] ieee802154: atusb: update my copyright years for this driver Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 72128b3aaec4..52c9051f3b95 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -3,6 +3,8 @@ * * Written 2013 by Werner Almesberger * + * Copyright (c) 2015 - 2016 Stefan Schmidt + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2 -- GitLab From b53f27e4fa0d0e72d897830cc4f3f83d2a25d952 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 15:46:23 -0700 Subject: [PATCH 3792/9938] string_helpers: add kstrdup_quotable Handle allocating and escaping a string safe for logging. Signed-off-by: Kees Cook Signed-off-by: James Morris --- include/linux/string_helpers.h | 2 ++ lib/string_helpers.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index dabe643eb5fa..9de228af00c1 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h @@ -68,4 +68,6 @@ static inline int string_escape_str_any_np(const char *src, char *dst, return string_escape_str(src, dst, sz, ESCAPE_ANY_NP, only); } +char *kstrdup_quotable(const char *src, gfp_t gfp); + #endif diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 5c88204b6f1f..aa00c9f989ee 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -534,3 +535,30 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, return p - dst; } EXPORT_SYMBOL(string_escape_mem); + +/* + * Return an allocated string that has been escaped of special characters + * and double quotes, making it safe to log in quotes. + */ +char *kstrdup_quotable(const char *src, gfp_t gfp) +{ + size_t slen, dlen; + char *dst; + const int flags = ESCAPE_HEX; + const char esc[] = "\f\n\r\t\v\a\e\\\""; + + if (!src) + return NULL; + slen = strlen(src); + + dlen = string_escape_mem(src, slen, NULL, 0, flags, esc); + dst = kmalloc(dlen + 1, gfp); + if (!dst) + return NULL; + + WARN_ON(string_escape_mem(src, slen, dst, dlen, flags, esc) != dlen); + dst[dlen] = '\0'; + + return dst; +} +EXPORT_SYMBOL_GPL(kstrdup_quotable); -- GitLab From 0d0443288f2244d7054796086e481ddef6abdbba Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 15:46:24 -0700 Subject: [PATCH 3793/9938] string_helpers: add kstrdup_quotable_cmdline Provide an escaped (but readable: no inter-argument NULLs) commandline safe for logging. Signed-off-by: Kees Cook Signed-off-by: James Morris --- include/linux/string_helpers.h | 1 + lib/string_helpers.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index 9de228af00c1..684d2695fc36 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h @@ -69,5 +69,6 @@ static inline int string_escape_str_any_np(const char *src, char *dst, } char *kstrdup_quotable(const char *src, gfp_t gfp); +char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp); #endif diff --git a/lib/string_helpers.c b/lib/string_helpers.c index aa00c9f989ee..b16ee85aaf87 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -562,3 +563,36 @@ char *kstrdup_quotable(const char *src, gfp_t gfp) return dst; } EXPORT_SYMBOL_GPL(kstrdup_quotable); + +/* + * Returns allocated NULL-terminated string containing process + * command line, with inter-argument NULLs replaced with spaces, + * and other special characters escaped. + */ +char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp) +{ + char *buffer, *quoted; + int i, res; + + buffer = kmalloc(PAGE_SIZE, GFP_TEMPORARY); + if (!buffer) + return NULL; + + res = get_cmdline(task, buffer, PAGE_SIZE - 1); + buffer[res] = '\0'; + + /* Collapse trailing NULLs, leave res pointing to last non-NULL. */ + while (--res >= 0 && buffer[res] == '\0') + ; + + /* Replace inter-argument NULLs. */ + for (i = 0; i <= res; i++) + if (buffer[i] == '\0') + buffer[i] = ' '; + + /* Make sure result is printable. */ + quoted = kstrdup_quotable(buffer, gfp); + kfree(buffer); + return quoted; +} +EXPORT_SYMBOL_GPL(kstrdup_quotable_cmdline); -- GitLab From 21985319add60b55fc27230d9421a3e5af7e998a Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 15:46:25 -0700 Subject: [PATCH 3794/9938] string_helpers: add kstrdup_quotable_file Allocate a NULL-terminated file path with special characters escaped, safe for logging. Signed-off-by: Kees Cook Signed-off-by: James Morris --- include/linux/string_helpers.h | 3 +++ lib/string_helpers.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index 684d2695fc36..5ce9538f290e 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h @@ -3,6 +3,8 @@ #include +struct file; + /* Descriptions of the types of units to * print in */ enum string_size_units { @@ -70,5 +72,6 @@ static inline int string_escape_str_any_np(const char *src, char *dst, char *kstrdup_quotable(const char *src, gfp_t gfp); char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp); +char *kstrdup_quotable_file(struct file *file, gfp_t gfp); #endif diff --git a/lib/string_helpers.c b/lib/string_helpers.c index b16ee85aaf87..ecaac2c0526f 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -596,3 +598,31 @@ char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp) return quoted; } EXPORT_SYMBOL_GPL(kstrdup_quotable_cmdline); + +/* + * Returns allocated NULL-terminated string containing pathname, + * with special characters escaped, able to be safely logged. If + * there is an error, the leading character will be "<". + */ +char *kstrdup_quotable_file(struct file *file, gfp_t gfp) +{ + char *temp, *pathname; + + if (!file) + return kstrdup("", gfp); + + /* We add 11 spaces for ' (deleted)' to be appended */ + temp = kmalloc(PATH_MAX + 11, GFP_TEMPORARY); + if (!temp) + return kstrdup("", gfp); + + pathname = file_path(file, temp, PATH_MAX + 11); + if (IS_ERR(pathname)) + pathname = kstrdup("", gfp); + else + pathname = kstrdup_quotable(pathname, gfp); + + kfree(temp); + return pathname; +} +EXPORT_SYMBOL_GPL(kstrdup_quotable_file); -- GitLab From 8a56038c2aef97a9d4b9dd608b912b9d9a4a2d68 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 15:46:26 -0700 Subject: [PATCH 3795/9938] Yama: consolidate error reporting Use a common error reporting function for Yama violation reports, and give more detail into the process command lines. Signed-off-by: Kees Cook Signed-off-by: James Morris --- security/yama/yama_lsm.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index cb6ed10816d4..c19f6e5df9a3 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -18,6 +18,7 @@ #include #include #include +#include #define YAMA_SCOPE_DISABLED 0 #define YAMA_SCOPE_RELATIONAL 1 @@ -41,6 +42,22 @@ static DEFINE_SPINLOCK(ptracer_relations_lock); static void yama_relation_cleanup(struct work_struct *work); static DECLARE_WORK(yama_relation_work, yama_relation_cleanup); +static void report_access(const char *access, struct task_struct *target, + struct task_struct *agent) +{ + char *target_cmd, *agent_cmd; + + target_cmd = kstrdup_quotable_cmdline(target, GFP_KERNEL); + agent_cmd = kstrdup_quotable_cmdline(agent, GFP_KERNEL); + + pr_notice_ratelimited( + "ptrace %s of \"%s\"[%d] was attempted by \"%s\"[%d]\n", + access, target_cmd, target->pid, agent_cmd, agent->pid); + + kfree(agent_cmd); + kfree(target_cmd); +} + /** * yama_relation_cleanup - remove invalid entries from the relation list * @@ -307,11 +324,8 @@ static int yama_ptrace_access_check(struct task_struct *child, } } - if (rc && (mode & PTRACE_MODE_NOAUDIT) == 0) { - printk_ratelimited(KERN_NOTICE - "ptrace of pid %d was attempted by: %s (pid %d)\n", - child->pid, current->comm, current->pid); - } + if (rc && (mode & PTRACE_MODE_NOAUDIT) == 0) + report_access("attach", child, current); return rc; } @@ -337,11 +351,8 @@ int yama_ptrace_traceme(struct task_struct *parent) break; } - if (rc) { - printk_ratelimited(KERN_NOTICE - "ptraceme of pid %d was attempted by: %s (pid %d)\n", - current->pid, parent->comm, parent->pid); - } + if (rc) + report_access("traceme", current, parent); return rc; } -- GitLab From 1284ab5b2dcb927d38e4f3fbc2e307f3d1af9262 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 20 Apr 2016 15:46:27 -0700 Subject: [PATCH 3796/9938] fs: define a string representation of the kernel_read_file_id enumeration A string representation of the kernel_read_file_id enumeration is needed for displaying messages (eg. pr_info, auditing) that can be used by multiple LSMs and the integrity subsystem. To simplify keeping the list of strings up to date with the enumeration, this patch defines two new preprocessing macros named __fid_enumify and __fid_stringify to create the enumeration and an array of strings. kernel_read_file_id_str() returns a string based on the enumeration. Signed-off-by: Mimi Zohar [kees: removed removal of my old version, constified pointer values] Signed-off-by: Kees Cook Signed-off-by: James Morris --- include/linux/fs.h | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 14a97194b34b..90477550b935 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2580,15 +2580,34 @@ static inline void i_readcount_inc(struct inode *inode) #endif extern int do_pipe_flags(int *, int); +#define __kernel_read_file_id(id) \ + id(UNKNOWN, unknown) \ + id(FIRMWARE, firmware) \ + id(MODULE, kernel-module) \ + id(KEXEC_IMAGE, kexec-image) \ + id(KEXEC_INITRAMFS, kexec-initramfs) \ + id(POLICY, security-policy) \ + id(MAX_ID, ) + +#define __fid_enumify(ENUM, dummy) READING_ ## ENUM, +#define __fid_stringify(dummy, str) #str, + enum kernel_read_file_id { - READING_FIRMWARE = 1, - READING_MODULE, - READING_KEXEC_IMAGE, - READING_KEXEC_INITRAMFS, - READING_POLICY, - READING_MAX_ID + __kernel_read_file_id(__fid_enumify) +}; + +static const char * const kernel_read_file_str[] = { + __kernel_read_file_id(__fid_stringify) }; +static inline const char * const kernel_read_file_id_str(enum kernel_read_file_id id) +{ + if (id < 0 || id >= READING_MAX_ID) + return kernel_read_file_str[READING_UNKNOWN]; + + return kernel_read_file_str[id]; +} + extern int kernel_read(struct file *, loff_t, char *, unsigned long); extern int kernel_read_file(struct file *, void **, loff_t *, loff_t, enum kernel_read_file_id); -- GitLab From 9b091556a073a9f5f93e2ad23d118f45c4796a84 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 15:46:28 -0700 Subject: [PATCH 3797/9938] LSM: LoadPin for kernel file loading restrictions This LSM enforces that kernel-loaded files (modules, firmware, etc) must all come from the same filesystem, with the expectation that such a filesystem is backed by a read-only device such as dm-verity or CDROM. This allows systems that have a verified and/or unchangeable filesystem to enforce module and firmware loading restrictions without needing to sign the files individually. Signed-off-by: Kees Cook Acked-by: Serge Hallyn Signed-off-by: James Morris --- Documentation/security/LoadPin.txt | 17 +++ MAINTAINERS | 6 + include/linux/lsm_hooks.h | 5 + security/Kconfig | 1 + security/Makefile | 2 + security/loadpin/Kconfig | 10 ++ security/loadpin/Makefile | 1 + security/loadpin/loadpin.c | 190 +++++++++++++++++++++++++++++ security/security.c | 1 + 9 files changed, 233 insertions(+) create mode 100644 Documentation/security/LoadPin.txt create mode 100644 security/loadpin/Kconfig create mode 100644 security/loadpin/Makefile create mode 100644 security/loadpin/loadpin.c diff --git a/Documentation/security/LoadPin.txt b/Documentation/security/LoadPin.txt new file mode 100644 index 000000000000..e11877f5d3d4 --- /dev/null +++ b/Documentation/security/LoadPin.txt @@ -0,0 +1,17 @@ +LoadPin is a Linux Security Module that ensures all kernel-loaded files +(modules, firmware, etc) all originate from the same filesystem, with +the expectation that such a filesystem is backed by a read-only device +such as dm-verity or CDROM. This allows systems that have a verified +and/or unchangeable filesystem to enforce module and firmware loading +restrictions without needing to sign the files individually. + +The LSM is selectable at build-time with CONFIG_SECURITY_LOADPIN, and +can be controlled at boot-time with the kernel command line option +"loadpin.enabled". By default, it is enabled, but can be disabled at +boot ("loadpin.enabled=0"). + +LoadPin starts pinning when it sees the first file loaded. If the +block device backing the filesystem is not read-only, a sysctl is +created to toggle pinning: /proc/sys/kernel/loadpin/enabled. (Having +a mutable filesystem means pinning is mutable too, but having the +sysctl allows for easy testing on systems with a mutable filesystem.) diff --git a/MAINTAINERS b/MAINTAINERS index 1c32f8a3d6c4..b4b1e8179018 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9962,6 +9962,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git S: Supported F: security/apparmor/ +LOADPIN SECURITY MODULE +M: Kees Cook +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git lsm/loadpin +S: Supported +F: security/loadpin/ + YAMA SECURITY MODULE M: Kees Cook T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git yama/tip diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index ae2537886177..6e466fc0666c 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1892,5 +1892,10 @@ extern void __init yama_add_hooks(void); #else static inline void __init yama_add_hooks(void) { } #endif +#ifdef CONFIG_SECURITY_LOADPIN +void __init loadpin_add_hooks(void); +#else +static inline void loadpin_add_hooks(void) { }; +#endif #endif /* ! __LINUX_LSM_HOOKS_H */ diff --git a/security/Kconfig b/security/Kconfig index e45237897b43..176758cdfa57 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -122,6 +122,7 @@ source security/selinux/Kconfig source security/smack/Kconfig source security/tomoyo/Kconfig source security/apparmor/Kconfig +source security/loadpin/Kconfig source security/yama/Kconfig source security/integrity/Kconfig diff --git a/security/Makefile b/security/Makefile index c9bfbc84ff50..f2d71cdb8e19 100644 --- a/security/Makefile +++ b/security/Makefile @@ -8,6 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor subdir-$(CONFIG_SECURITY_YAMA) += yama +subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin # always enable default capabilities obj-y += commoncap.o @@ -22,6 +23,7 @@ obj-$(CONFIG_AUDIT) += lsm_audit.o obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ obj-$(CONFIG_SECURITY_YAMA) += yama/ +obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o # Object integrity file lists diff --git a/security/loadpin/Kconfig b/security/loadpin/Kconfig new file mode 100644 index 000000000000..c668ac4eda65 --- /dev/null +++ b/security/loadpin/Kconfig @@ -0,0 +1,10 @@ +config SECURITY_LOADPIN + bool "Pin load of kernel files (modules, fw, etc) to one filesystem" + depends on SECURITY && BLOCK + help + Any files read through the kernel file reading interface + (kernel modules, firmware, kexec images, security policy) will + be pinned to the first filesystem used for loading. Any files + that come from other filesystems will be rejected. This is best + used on systems without an initrd that have a root filesystem + backed by a read-only device such as dm-verity or a CDROM. diff --git a/security/loadpin/Makefile b/security/loadpin/Makefile new file mode 100644 index 000000000000..c2d77f83037b --- /dev/null +++ b/security/loadpin/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SECURITY_LOADPIN) += loadpin.o diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c new file mode 100644 index 000000000000..e4debae3c4d6 --- /dev/null +++ b/security/loadpin/loadpin.c @@ -0,0 +1,190 @@ +/* + * Module and Firmware Pinning Security Module + * + * Copyright 2011-2016 Google Inc. + * + * Author: Kees Cook + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "LoadPin: " fmt + +#include +#include +#include +#include +#include +#include +#include /* current */ +#include + +static void report_load(const char *origin, struct file *file, char *operation) +{ + char *cmdline, *pathname; + + pathname = kstrdup_quotable_file(file, GFP_KERNEL); + cmdline = kstrdup_quotable_cmdline(current, GFP_KERNEL); + + pr_notice("%s %s obj=%s%s%s pid=%d cmdline=%s%s%s\n", + origin, operation, + (pathname && pathname[0] != '<') ? "\"" : "", + pathname, + (pathname && pathname[0] != '<') ? "\"" : "", + task_pid_nr(current), + cmdline ? "\"" : "", cmdline, cmdline ? "\"" : ""); + + kfree(cmdline); + kfree(pathname); +} + +static int enabled = 1; +static struct super_block *pinned_root; +static DEFINE_SPINLOCK(pinned_root_spinlock); + +#ifdef CONFIG_SYSCTL +static int zero; +static int one = 1; + +static struct ctl_path loadpin_sysctl_path[] = { + { .procname = "kernel", }, + { .procname = "loadpin", }, + { } +}; + +static struct ctl_table loadpin_sysctl_table[] = { + { + .procname = "enabled", + .data = &enabled, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { } +}; + +/* + * This must be called after early kernel init, since then the rootdev + * is available. + */ +static void check_pinning_enforcement(struct super_block *mnt_sb) +{ + bool ro = false; + + /* + * If load pinning is not enforced via a read-only block + * device, allow sysctl to change modes for testing. + */ + if (mnt_sb->s_bdev) { + ro = bdev_read_only(mnt_sb->s_bdev); + pr_info("dev(%u,%u): %s\n", + MAJOR(mnt_sb->s_bdev->bd_dev), + MINOR(mnt_sb->s_bdev->bd_dev), + ro ? "read-only" : "writable"); + } else + pr_info("mnt_sb lacks block device, treating as: writable\n"); + + if (!ro) { + if (!register_sysctl_paths(loadpin_sysctl_path, + loadpin_sysctl_table)) + pr_notice("sysctl registration failed!\n"); + else + pr_info("load pinning can be disabled.\n"); + } else + pr_info("load pinning engaged.\n"); +} +#else +static void check_pinning_enforcement(struct super_block *mnt_sb) +{ + pr_info("load pinning engaged.\n"); +} +#endif + +static void loadpin_sb_free_security(struct super_block *mnt_sb) +{ + /* + * When unmounting the filesystem we were using for load + * pinning, we acknowledge the superblock release, but make sure + * no other modules or firmware can be loaded. + */ + if (!IS_ERR_OR_NULL(pinned_root) && mnt_sb == pinned_root) { + pinned_root = ERR_PTR(-EIO); + pr_info("umount pinned fs: refusing further loads\n"); + } +} + +static int loadpin_read_file(struct file *file, enum kernel_read_file_id id) +{ + struct super_block *load_root; + const char *origin = kernel_read_file_id_str(id); + + /* This handles the older init_module API that has a NULL file. */ + if (!file) { + if (!enabled) { + report_load(origin, NULL, "old-api-pinning-ignored"); + return 0; + } + + report_load(origin, NULL, "old-api-denied"); + return -EPERM; + } + + load_root = file->f_path.mnt->mnt_sb; + + /* First loaded module/firmware defines the root for all others. */ + spin_lock(&pinned_root_spinlock); + /* + * pinned_root is only NULL at startup. Otherwise, it is either + * a valid reference, or an ERR_PTR. + */ + if (!pinned_root) { + pinned_root = load_root; + /* + * Unlock now since it's only pinned_root we care about. + * In the worst case, we will (correctly) report pinning + * failures before we have announced that pinning is + * enabled. This would be purely cosmetic. + */ + spin_unlock(&pinned_root_spinlock); + check_pinning_enforcement(pinned_root); + report_load(origin, file, "pinned"); + } else { + spin_unlock(&pinned_root_spinlock); + } + + if (IS_ERR_OR_NULL(pinned_root) || load_root != pinned_root) { + if (unlikely(!enabled)) { + report_load(origin, file, "pinning-ignored"); + return 0; + } + + report_load(origin, file, "denied"); + return -EPERM; + } + + return 0; +} + +static struct security_hook_list loadpin_hooks[] = { + LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), + LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), +}; + +void __init loadpin_add_hooks(void) +{ + pr_info("ready to pin (currently %sabled)", enabled ? "en" : "dis"); + security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks)); +} + +/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ +module_param(enabled, int, 0); +MODULE_PARM_DESC(enabled, "Pin module/firmware loading (default: true)"); diff --git a/security/security.c b/security/security.c index 554c3fb7d4a5..e42860899f23 100644 --- a/security/security.c +++ b/security/security.c @@ -60,6 +60,7 @@ int __init security_init(void) */ capability_add_hooks(); yama_add_hooks(); + loadpin_add_hooks(); /* * Load all the remaining security modules. -- GitLab From 22f708b057dbe3ab4aa53c76b5f3051743784777 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 1 Apr 2016 17:44:38 +0200 Subject: [PATCH 3798/9938] ARM: dts: r8a7790: Set maximum frequencies for SDHI clocks Taken from the datasheet. Signed-off-by: Ben Hutchings Signed-off-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 7486fcf985c4..b920facb0c3b 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -589,6 +589,7 @@ clocks = <&mstp3_clks R8A7790_CLK_SDHI0>; dmas = <&dmac1 0xcd>, <&dmac1 0xce>; dma-names = "tx", "rx"; + max-frequency = <156000000>; power-domains = <&cpg_clocks>; status = "disabled"; }; @@ -600,6 +601,7 @@ clocks = <&mstp3_clks R8A7790_CLK_SDHI1>; dmas = <&dmac1 0xc9>, <&dmac1 0xca>; dma-names = "tx", "rx"; + max-frequency = <156000000>; power-domains = <&cpg_clocks>; status = "disabled"; }; @@ -611,6 +613,7 @@ clocks = <&mstp3_clks R8A7790_CLK_SDHI2>; dmas = <&dmac1 0xc1>, <&dmac1 0xc2>; dma-names = "tx", "rx"; + max-frequency = <97500000>; power-domains = <&cpg_clocks>; status = "disabled"; }; @@ -622,6 +625,7 @@ clocks = <&mstp3_clks R8A7790_CLK_SDHI3>; dmas = <&dmac1 0xd3>, <&dmac1 0xd4>; dma-names = "tx", "rx"; + max-frequency = <97500000>; power-domains = <&cpg_clocks>; status = "disabled"; }; -- GitLab From 09401ae25191039f4aa45c13718595f550745c68 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 11:15:09 -0700 Subject: [PATCH 3799/9938] fm10k: add helper functions to set strings and data for ethtool stats Reduce duplicate code and the amount of indentation by adding fm10k_add_stat_strings and fm10k_add_ethtool_stats functions which help add fm10k_stat structures to the ethtool stats callbacks. This helps increase ease of use for future stat additions, and increases code readability. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/fm10k/fm10k_ethtool.c | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index a23748777b1b..f331966ac9df 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -121,13 +121,22 @@ static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = { FM10K_MBX_STAT("mbx_rx_mbmem_pushed", rx_mbmem_pushed), }; +#define FM10K_QUEUE_STAT(_name, _stat) { \ + .stat_string = _name, \ + .sizeof_stat = FIELD_SIZEOF(struct fm10k_ring, _stat), \ + .stat_offset = offsetof(struct fm10k_ring, _stat) \ +} + +static const struct fm10k_stats fm10k_gstrings_queue_stats[] = { + FM10K_QUEUE_STAT("packets", stats.packets), + FM10K_QUEUE_STAT("bytes", stats.bytes), +}; + #define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats) #define FM10K_DEBUG_STATS_LEN ARRAY_SIZE(fm10k_gstrings_debug_stats) #define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats) #define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats) - -#define FM10K_QUEUE_STATS_LEN(_n) \ - ((_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64))) +#define FM10K_QUEUE_STATS_LEN ARRAY_SIZE(fm10k_gstrings_queue_stats) #define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \ FM10K_NETDEV_STATS_LEN + \ @@ -202,14 +211,17 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) } for (i = 0; i < interface->hw.mac.max_queues; i++) { - snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; - snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; + char prefix[ETH_GSTRING_LEN]; + + snprintf(prefix, ETH_GSTRING_LEN, "tx_queue_%u_", i); + fm10k_add_stat_strings(&p, prefix, + fm10k_gstrings_queue_stats, + FM10K_QUEUE_STATS_LEN); + + snprintf(prefix, ETH_GSTRING_LEN, "rx_queue_%u_", i); + fm10k_add_stat_strings(&p, prefix, + fm10k_gstrings_queue_stats, + FM10K_QUEUE_STATS_LEN); } } @@ -244,7 +256,7 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset) case ETH_SS_TEST: return FM10K_TEST_LEN; case ETH_SS_STATS: - stats_len += FM10K_QUEUE_STATS_LEN(hw->mac.max_queues); + stats_len += hw->mac.max_queues * 2 * FM10K_QUEUE_STATS_LEN; if (hw->mac.type != fm10k_mac_vf) stats_len += FM10K_PF_STATS_LEN; @@ -272,9 +284,10 @@ static void fm10k_add_ethtool_stats(u64 **data, void *pointer, unsigned int i; char *p; - /* simply skip forward if we were not given a valid pointer */ if (!pointer) { - *data += size; + /* memory is not zero allocated so we have to clear it */ + for (i = 0; i < size; i++) + *((*data)++) = 0; return; } @@ -304,11 +317,10 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats __always_unused *stats, u64 *data) { - const int stat_count = sizeof(struct fm10k_queue_stats) / sizeof(u64); struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_iov_data *iov_data = interface->iov_data; struct net_device_stats *net_stats = &netdev->stats; - int i, j; + int i; fm10k_update_stats(interface); @@ -347,19 +359,16 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, for (i = 0; i < interface->hw.mac.max_queues; i++) { struct fm10k_ring *ring; - u64 *queue_stat; ring = interface->tx_ring[i]; - if (ring) - queue_stat = (u64 *)&ring->stats; - for (j = 0; j < stat_count; j++) - *(data++) = ring ? queue_stat[j] : 0; + fm10k_add_ethtool_stats(&data, ring, + fm10k_gstrings_queue_stats, + FM10K_QUEUE_STATS_LEN); ring = interface->rx_ring[i]; - if (ring) - queue_stat = (u64 *)&ring->stats; - for (j = 0; j < stat_count; j++) - *(data++) = ring ? queue_stat[j] : 0; + fm10k_add_ethtool_stats(&data, ring, + fm10k_gstrings_queue_stats, + FM10K_QUEUE_STATS_LEN); } } -- GitLab From 3ef2f563267892230681b1b8890d8f759d39e64d Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 4 Mar 2016 15:37:48 -0800 Subject: [PATCH 3800/9938] fm10k: remove debug-statistics support This change fixes an (ab)use of the ethtool stats API, which could result in corrupt memory or misleading stat output. The ethtool stats API is not robust enough to handle varying number of statistics due to how it requests the size and allocates memory. Remove the poorly conceived support originally added for extra debug statistics. In the future, a new stats API may open up the ability to display these statistics. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/fm10k/fm10k_ethtool.c | 72 +------------------ 1 file changed, 1 insertion(+), 71 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index f331966ac9df..6ab9df52f301 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -81,17 +81,6 @@ static const struct fm10k_stats fm10k_gstrings_global_stats[] = { FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), }; -static const struct fm10k_stats fm10k_gstrings_debug_stats[] = { - FM10K_STAT("hw_sm_mbx_full", hw_sm_mbx_full), - FM10K_STAT("hw_csum_tx_good", hw_csum_tx_good), - FM10K_STAT("hw_csum_rx_good", hw_csum_rx_good), - FM10K_STAT("rx_switch_errors", rx_switch_errors), - FM10K_STAT("rx_drops", rx_drops), - FM10K_STAT("rx_pp_errors", rx_pp_errors), - FM10K_STAT("rx_link_errors", rx_link_errors), - FM10K_STAT("rx_length_errors", rx_length_errors), -}; - static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { FM10K_STAT("timeout", stats.timeout.count), FM10K_STAT("ur", stats.ur.count), @@ -133,7 +122,6 @@ static const struct fm10k_stats fm10k_gstrings_queue_stats[] = { }; #define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats) -#define FM10K_DEBUG_STATS_LEN ARRAY_SIZE(fm10k_gstrings_debug_stats) #define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats) #define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats) #define FM10K_QUEUE_STATS_LEN ARRAY_SIZE(fm10k_gstrings_queue_stats) @@ -154,12 +142,10 @@ enum fm10k_self_test_types { }; enum { - FM10K_PRV_FLAG_DEBUG_STATS, FM10K_PRV_FLAG_LEN, }; static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = { - "debug-statistics", }; static void fm10k_add_stat_strings(char **p, const char *prefix, @@ -178,7 +164,6 @@ static void fm10k_add_stat_strings(char **p, const char *prefix, static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) { struct fm10k_intfc *interface = netdev_priv(dev); - struct fm10k_iov_data *iov_data = interface->iov_data; char *p = (char *)data; unsigned int i; @@ -188,10 +173,6 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) fm10k_add_stat_strings(&p, "", fm10k_gstrings_global_stats, FM10K_GLOBAL_STATS_LEN); - if (interface->flags & FM10K_FLAG_DEBUG_STATS) - fm10k_add_stat_strings(&p, "", fm10k_gstrings_debug_stats, - FM10K_DEBUG_STATS_LEN); - fm10k_add_stat_strings(&p, "", fm10k_gstrings_mbx_stats, FM10K_MBX_STATS_LEN); @@ -199,17 +180,6 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) fm10k_add_stat_strings(&p, "", fm10k_gstrings_pf_stats, FM10K_PF_STATS_LEN); - if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { - for (i = 0; i < iov_data->num_vfs; i++) { - char prefix[ETH_GSTRING_LEN]; - - snprintf(prefix, ETH_GSTRING_LEN, "vf_%u_", i); - fm10k_add_stat_strings(&p, prefix, - fm10k_gstrings_mbx_stats, - FM10K_MBX_STATS_LEN); - } - } - for (i = 0; i < interface->hw.mac.max_queues; i++) { char prefix[ETH_GSTRING_LEN]; @@ -248,7 +218,6 @@ static void fm10k_get_strings(struct net_device *dev, static int fm10k_get_sset_count(struct net_device *dev, int sset) { struct fm10k_intfc *interface = netdev_priv(dev); - struct fm10k_iov_data *iov_data = interface->iov_data; struct fm10k_hw *hw = &interface->hw; int stats_len = FM10K_STATIC_STATS_LEN; @@ -261,14 +230,6 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset) if (hw->mac.type != fm10k_mac_vf) stats_len += FM10K_PF_STATS_LEN; - if (interface->flags & FM10K_FLAG_DEBUG_STATS) { - stats_len += FM10K_DEBUG_STATS_LEN; - - if (iov_data) - stats_len += FM10K_MBX_STATS_LEN * - iov_data->num_vfs; - } - return stats_len; case ETH_SS_PRIV_FLAGS: return FM10K_PRV_FLAG_LEN; @@ -318,7 +279,6 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, u64 *data) { struct fm10k_intfc *interface = netdev_priv(netdev); - struct fm10k_iov_data *iov_data = interface->iov_data; struct net_device_stats *net_stats = &netdev->stats; int i; @@ -330,11 +290,6 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, fm10k_add_ethtool_stats(&data, interface, fm10k_gstrings_global_stats, FM10K_GLOBAL_STATS_LEN); - if (interface->flags & FM10K_FLAG_DEBUG_STATS) - fm10k_add_ethtool_stats(&data, interface, - fm10k_gstrings_debug_stats, - FM10K_DEBUG_STATS_LEN); - fm10k_add_ethtool_stats(&data, &interface->hw.mbx, fm10k_gstrings_mbx_stats, FM10K_MBX_STATS_LEN); @@ -345,18 +300,6 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, FM10K_PF_STATS_LEN); } - if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { - for (i = 0; i < iov_data->num_vfs; i++) { - struct fm10k_vf_info *vf_info; - - vf_info = &iov_data->vf_info[i]; - - fm10k_add_ethtool_stats(&data, &vf_info->mbx, - fm10k_gstrings_mbx_stats, - FM10K_MBX_STATS_LEN); - } - } - for (i = 0; i < interface->hw.mac.max_queues; i++) { struct fm10k_ring *ring; @@ -1012,27 +955,14 @@ static void fm10k_self_test(struct net_device *dev, static u32 fm10k_get_priv_flags(struct net_device *netdev) { - struct fm10k_intfc *interface = netdev_priv(netdev); - u32 priv_flags = 0; - - if (interface->flags & FM10K_FLAG_DEBUG_STATS) - priv_flags |= BIT(FM10K_PRV_FLAG_DEBUG_STATS); - - return priv_flags; + return 0; } static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags) { - struct fm10k_intfc *interface = netdev_priv(netdev); - if (priv_flags >= BIT(FM10K_PRV_FLAG_LEN)) return -EINVAL; - if (priv_flags & BIT(FM10K_PRV_FLAG_DEBUG_STATS)) - interface->flags |= FM10K_FLAG_DEBUG_STATS; - else - interface->flags &= ~FM10K_FLAG_DEBUG_STATS; - return 0; } -- GitLab From 144d8305585a00467aaedc86d039a4ab036a9bcc Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 7 Mar 2016 09:30:15 -0800 Subject: [PATCH 3801/9938] fm10k: Add support for bulk Tx cleanup & cleanup boolean logic This patch enables bulk free in Tx cleanup for fm10k and cleans up the boolean logic in the polling routines for fm10k in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 0b465394f88a..97650802a4cc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1198,9 +1198,10 @@ void fm10k_tx_timeout_reset(struct fm10k_intfc *interface) * fm10k_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: structure containing interrupt and ring information * @tx_ring: tx ring to clean + * @napi_budget: Used to determine if we are in netpoll **/ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, - struct fm10k_ring *tx_ring) + struct fm10k_ring *tx_ring, int napi_budget) { struct fm10k_intfc *interface = q_vector->interface; struct fm10k_tx_buffer *tx_buffer; @@ -1238,7 +1239,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, total_packets += tx_buffer->gso_segs; /* free the skb */ - dev_consume_skb_any(tx_buffer->skb); + napi_consume_skb(tx_buffer->skb, napi_budget); /* unmap skb header data */ dma_unmap_single(tx_ring->dev, @@ -1449,8 +1450,10 @@ static int fm10k_poll(struct napi_struct *napi, int budget) int per_ring_budget, work_done = 0; bool clean_complete = true; - fm10k_for_each_ring(ring, q_vector->tx) - clean_complete &= fm10k_clean_tx_irq(q_vector, ring); + fm10k_for_each_ring(ring, q_vector->tx) { + if (!fm10k_clean_tx_irq(q_vector, ring, budget)) + clean_complete = false; + } /* Handle case where we are called by netpoll with a budget of 0 */ if (budget <= 0) @@ -1468,7 +1471,8 @@ static int fm10k_poll(struct napi_struct *napi, int budget) int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget); work_done += work; - clean_complete &= !!(work < per_ring_budget); + if (work >= per_ring_budget) + clean_complete = false; } /* If all work not completed, return budget and keep polling */ -- GitLab From 2d0f76bedbddaacc465c7a3ebdc9f8c13f68d931 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 9 Mar 2016 16:36:08 -0800 Subject: [PATCH 3802/9938] fm10k: use DRV_SUMMARY to reduce code duplication Use DRV_SUMMARY, similar to DRV_VERSION so that we don't have to duplicate the driver summary in multiple places. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 97650802a4cc..ca5b9d7eeb22 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -29,15 +29,15 @@ #include "fm10k.h" #define DRV_VERSION "0.19.3-k" +#define DRV_SUMMARY "Intel(R) Ethernet Switch Host Interface Driver" const char fm10k_driver_version[] = DRV_VERSION; char fm10k_driver_name[] = "fm10k"; -static const char fm10k_driver_string[] = - "Intel(R) Ethernet Switch Host Interface Driver"; +static const char fm10k_driver_string[] = DRV_SUMMARY; static const char fm10k_copyright[] = "Copyright (c) 2013 Intel Corporation."; MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) Ethernet Switch Host Interface Driver"); +MODULE_DESCRIPTION(DRV_SUMMARY); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -- GitLab From 1e4c32f3ede19bdb738aec2cc3cf69439d7b9310 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 11 Mar 2016 09:52:32 -0800 Subject: [PATCH 3803/9938] fm10k: prevent RCU issues during AER events During an AER action response, we were calling fm10k_close without holding the rtnl_lock() which could lead to possible RCU warnings being produced due to 64bit stat updates among other causes. Similarly, we need rtnl_lock() around fm10k_open during fm10k_io_resume. Follow the same pattern elsewhere in the driver and protect the entire open/close sequence. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index f0992950e228..a604513d0451 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -2271,6 +2271,8 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, if (state == pci_channel_io_perm_failure) return PCI_ERS_RESULT_DISCONNECT; + rtnl_lock(); + if (netif_running(netdev)) fm10k_close(netdev); @@ -2279,6 +2281,8 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, /* free interrupts */ fm10k_clear_queueing_scheme(interface); + rtnl_unlock(); + pci_disable_device(pdev); /* Request a slot reset. */ @@ -2349,11 +2353,13 @@ static void fm10k_io_resume(struct pci_dev *pdev) /* reset statistics starting values */ hw->mac.ops.rebind_hw_stats(hw, &interface->stats); + rtnl_lock(); + err = fm10k_init_queueing_scheme(interface); if (err) { dev_err(&interface->pdev->dev, "init_queueing_scheme failed: %d\n", err); - return; + goto unlock; } /* reassociate interrupts */ @@ -2370,6 +2376,9 @@ static void fm10k_io_resume(struct pci_dev *pdev) if (!err) netif_device_attach(netdev); + +unlock: + rtnl_unlock(); } static const struct pci_error_handlers fm10k_err_handler = { -- GitLab From 9de6a1a6b8ed889ecd3ae13bb0a2459485d90a24 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 16:17:31 -0700 Subject: [PATCH 3804/9938] fm10k: drop 1588 support The 1588 support within fm10k does not work correctly with the current version of the switch management software, and likely never worked correctly to begin with. Remove support for PTP/1588. Update copyright year for all these files while we're touching them. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/Makefile | 3 +- drivers/net/ethernet/intel/fm10k/fm10k.h | 34 +- .../net/ethernet/intel/fm10k/fm10k_ethtool.c | 30 +- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 22 +- .../net/ethernet/intel/fm10k/fm10k_netdev.c | 22 +- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 110 +---- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 101 +--- drivers/net/ethernet/intel/fm10k/fm10k_pf.h | 17 +- drivers/net/ethernet/intel/fm10k/fm10k_ptp.c | 462 ------------------ drivers/net/ethernet/intel/fm10k/fm10k_type.h | 17 +- drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 57 +-- drivers/net/ethernet/intel/fm10k/fm10k_vf.h | 12 +- 12 files changed, 11 insertions(+), 876 deletions(-) delete mode 100644 drivers/net/ethernet/intel/fm10k/fm10k_ptp.c diff --git a/drivers/net/ethernet/intel/fm10k/Makefile b/drivers/net/ethernet/intel/fm10k/Makefile index b006ff66d028..2aeaa39d9a25 100644 --- a/drivers/net/ethernet/intel/fm10k/Makefile +++ b/drivers/net/ethernet/intel/fm10k/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel Ethernet Switch Host Interface Driver -# Copyright(c) 2013 - 2015 Intel Corporation. +# Copyright(c) 2013 - 2016 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, @@ -30,7 +30,6 @@ obj-$(CONFIG_FM10K) += fm10k.o fm10k-y := fm10k_main.o \ fm10k_common.o \ fm10k_pci.o \ - fm10k_ptp.o \ fm10k_netdev.o \ fm10k_ethtool.o \ fm10k_pf.o \ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index 9c7fafef7cf6..c21fa8699fc4 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -27,9 +27,6 @@ #include #include #include -#include -#include -#include #include "fm10k_pf.h" #include "fm10k_vf.h" @@ -342,22 +339,8 @@ struct fm10k_intfc { #ifdef CONFIG_DEBUG_FS struct dentry *dbg_intfc; - #endif /* CONFIG_DEBUG_FS */ - struct ptp_clock_info ptp_caps; - struct ptp_clock *ptp_clock; - - struct sk_buff_head ts_tx_skb_queue; - u32 tx_hwtstamp_timeouts; - struct hwtstamp_config ts_config; - /* We are unable to actually adjust the clock beyond the frequency - * value. Once the clock is started there is no resetting it. As - * such we maintain a separate offset from the actual hardware clock - * to allow for offset adjustment. - */ - s64 ptp_adjust; - rwlock_t systime_lock; #ifdef CONFIG_DCB u8 pfc_en; #endif @@ -546,21 +529,6 @@ static inline void fm10k_dbg_init(void) {} static inline void fm10k_dbg_exit(void) {} #endif /* CONFIG_DEBUG_FS */ -/* Time Stamping */ -void fm10k_systime_to_hwtstamp(struct fm10k_intfc *interface, - struct skb_shared_hwtstamps *hwtstamp, - u64 systime); -void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb); -void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort, - u64 systime); -void fm10k_ts_reset(struct fm10k_intfc *interface); -void fm10k_ts_init(struct fm10k_intfc *interface); -void fm10k_ts_tx_subtask(struct fm10k_intfc *interface); -void fm10k_ptp_register(struct fm10k_intfc *interface); -void fm10k_ptp_unregister(struct fm10k_intfc *interface); -int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr); -int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr); - /* DCB */ #ifdef CONFIG_DCB void fm10k_dcbnl_set_ops(struct net_device *dev); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 6ab9df52f301..ca276c0a4b8d 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -77,8 +77,6 @@ static const struct fm10k_stats fm10k_gstrings_global_stats[] = { FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail), FM10K_STAT("tx_hang_count", tx_timeout_count), - - FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), }; static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { @@ -1140,31 +1138,6 @@ static int fm10k_set_channels(struct net_device *dev, return fm10k_setup_tc(dev, netdev_get_num_tc(dev)); } -static int fm10k_get_ts_info(struct net_device *dev, - struct ethtool_ts_info *info) -{ - struct fm10k_intfc *interface = netdev_priv(dev); - - info->so_timestamping = - SOF_TIMESTAMPING_TX_SOFTWARE | - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE | - SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE; - - if (interface->ptp_clock) - info->phc_index = ptp_clock_index(interface->ptp_clock); - else - info->phc_index = -1; - - info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); - - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); - - return 0; -} - static const struct ethtool_ops fm10k_ethtool_ops = { .get_strings = fm10k_get_strings, .get_sset_count = fm10k_get_sset_count, @@ -1192,7 +1165,6 @@ static const struct ethtool_ops fm10k_ethtool_ops = { .set_rxfh = fm10k_set_rssh, .get_channels = fm10k_get_channels, .set_channels = fm10k_set_channels, - .get_ts_info = fm10k_get_ts_info, }; void fm10k_set_ethtool_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index ca5b9d7eeb22..58092e523bbe 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2014 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -424,19 +424,6 @@ static inline void fm10k_rx_hash(struct fm10k_ring *ring, PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); } -static void fm10k_rx_hwtstamp(struct fm10k_ring *rx_ring, - union fm10k_rx_desc *rx_desc, - struct sk_buff *skb) -{ - struct fm10k_intfc *interface = rx_ring->q_vector->interface; - - FM10K_CB(skb)->tstamp = rx_desc->q.timestamp; - - if (unlikely(interface->flags & FM10K_FLAG_RX_TS_ENABLED)) - fm10k_systime_to_hwtstamp(interface, skb_hwtstamps(skb), - le64_to_cpu(rx_desc->q.timestamp)); -} - static void fm10k_type_trans(struct fm10k_ring *rx_ring, union fm10k_rx_desc __maybe_unused *rx_desc, struct sk_buff *skb) @@ -486,8 +473,6 @@ static unsigned int fm10k_process_skb_fields(struct fm10k_ring *rx_ring, fm10k_rx_checksum(rx_ring, rx_desc, skb); - fm10k_rx_hwtstamp(rx_ring, rx_desc, skb); - FM10K_CB(skb)->fi.w.vlan = rx_desc->w.vlan; skb_record_rx_queue(skb, rx_ring->queue_index); @@ -912,11 +897,6 @@ static u8 fm10k_tx_desc_flags(struct sk_buff *skb, u32 tx_flags) /* set type for advanced descriptor with frame checksum insertion */ u32 desc_flags = 0; - /* set timestamping bits */ - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && - likely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) - desc_flags |= FM10K_TXD_FLAG_TIME; - /* set checksum offload bits */ desc_flags |= FM10K_SET_FLAG(tx_flags, FM10K_TX_FLAGS_CSUM, FM10K_TXD_FLAG_CSUM); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 1d0f0583222c..32778dda8c12 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -243,9 +243,6 @@ void fm10k_clean_all_tx_rings(struct fm10k_intfc *interface) for (i = 0; i < interface->num_tx_queues; i++) fm10k_clean_tx_ring(interface->tx_ring[i]); - - /* remove any stale timestamp buffers and free them */ - skb_queue_purge(&interface->ts_tx_skb_queue); } /** @@ -660,10 +657,6 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev) __skb_put(skb, pad_len); } - /* prepare packet for hardware time stamping */ - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) - fm10k_ts_tx_enqueue(interface, skb); - if (r_idx >= interface->num_tx_queues) r_idx %= interface->num_tx_queues; @@ -1213,18 +1206,6 @@ static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto, return fm10k_setup_tc(dev, tc->tc); } -static int fm10k_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGHWTSTAMP: - return fm10k_get_ts_config(netdev, ifr); - case SIOCSHWTSTAMP: - return fm10k_set_ts_config(netdev, ifr); - default: - return -EOPNOTSUPP; - } -} - static void fm10k_assign_l2_accel(struct fm10k_intfc *interface, struct fm10k_l2_accel *l2_accel) { @@ -1402,7 +1383,6 @@ static const struct net_device_ops fm10k_netdev_ops = { .ndo_get_vf_config = fm10k_ndo_get_vf_config, .ndo_add_vxlan_port = fm10k_add_vxlan_port, .ndo_del_vxlan_port = fm10k_del_vxlan_port, - .ndo_do_ioctl = fm10k_ioctl, .ndo_dfwd_add_station = fm10k_dfwd_add_station, .ndo_dfwd_del_station = fm10k_dfwd_del_station, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index a604513d0451..29e9402c4352 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -209,9 +209,6 @@ static void fm10k_reinit(struct fm10k_intfc *interface) netdev->features |= NETIF_F_HW_VLAN_CTAG_RX; } - /* reset clock */ - fm10k_ts_reset(interface); - err = netif_running(netdev) ? fm10k_open(netdev) : 0; if (err) goto err_open; @@ -559,7 +556,6 @@ static void fm10k_service_task(struct work_struct *work) /* tasks only run when interface is up */ fm10k_watchdog_subtask(interface); fm10k_check_hang_subtask(interface); - fm10k_ts_tx_subtask(interface); /* release lock on service events to allow scheduling next event */ fm10k_service_event_complete(interface); @@ -1204,25 +1200,6 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results, return 0; } -static s32 fm10k_1588_msg_vf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info __always_unused *mbx) -{ - struct fm10k_intfc *interface; - u64 timestamp; - s32 err; - - err = fm10k_tlv_attr_get_u64(results[FM10K_1588_MSG_TIMESTAMP], - ×tamp); - if (err) - return err; - - interface = container_of(hw, struct fm10k_intfc, hw); - - fm10k_ts_tx_hwtstamp(interface, 0, timestamp); - - return 0; -} - /* generic error handler for mailbox issues */ static s32 fm10k_mbx_error(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info __always_unused *mbx) @@ -1243,7 +1220,6 @@ static const struct fm10k_msg_data vf_mbx_data[] = { FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_mbx_mac_addr), FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf), - FM10K_VF_MSG_1588_HANDLER(fm10k_1588_msg_vf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error), }; @@ -1341,68 +1317,6 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results, return 0; } -static s32 fm10k_1588_msg_pf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info __always_unused *mbx) -{ - struct fm10k_swapi_1588_timestamp timestamp; - struct fm10k_iov_data *iov_data; - struct fm10k_intfc *interface; - u16 sglort, vf_idx; - s32 err; - - err = fm10k_tlv_attr_get_le_struct( - results[FM10K_PF_ATTR_ID_1588_TIMESTAMP], - ×tamp, sizeof(timestamp)); - if (err) - return err; - - interface = container_of(hw, struct fm10k_intfc, hw); - - if (timestamp.dglort) { - fm10k_ts_tx_hwtstamp(interface, timestamp.dglort, - le64_to_cpu(timestamp.egress)); - return 0; - } - - /* either dglort or sglort must be set */ - if (!timestamp.sglort) - return FM10K_ERR_PARAM; - - /* verify GLORT is at least one of the ones we own */ - sglort = le16_to_cpu(timestamp.sglort); - if (!fm10k_glort_valid_pf(hw, sglort)) - return FM10K_ERR_PARAM; - - if (sglort == interface->glort) { - fm10k_ts_tx_hwtstamp(interface, 0, - le64_to_cpu(timestamp.ingress)); - return 0; - } - - /* if there is no iov_data then there is no mailbox to process */ - if (!ACCESS_ONCE(interface->iov_data)) - return FM10K_ERR_PARAM; - - rcu_read_lock(); - - /* notify VF if this timestamp belongs to it */ - iov_data = interface->iov_data; - vf_idx = (hw->mac.dglort_map & FM10K_DGLORTMAP_NONE) - sglort; - - if (!iov_data || vf_idx >= iov_data->num_vfs) { - err = FM10K_ERR_PARAM; - goto err_unlock; - } - - err = hw->iov.ops.report_timestamp(hw, &iov_data->vf_info[vf_idx], - le64_to_cpu(timestamp.ingress)); - -err_unlock: - rcu_read_unlock(); - - return err; -} - static const struct fm10k_msg_data pf_mbx_data[] = { FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), @@ -1410,7 +1324,6 @@ static const struct fm10k_msg_data pf_mbx_data[] = { FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf), FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_update_pvid), - FM10K_PF_MSG_1588_TIMESTAMP_HANDLER(fm10k_1588_msg_pf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error), }; @@ -1789,18 +1702,9 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, return -EIO; } - /* assign BAR 4 resources for use with PTP */ - if (fm10k_read_reg(hw, FM10K_CTRL) & FM10K_CTRL_BAR4_ALLOWED) - interface->sw_addr = ioremap(pci_resource_start(pdev, 4), - pci_resource_len(pdev, 4)); - hw->sw_addr = interface->sw_addr; - /* initialize DCBNL interface */ fm10k_dcbnl_set_ops(netdev); - /* Intitialize timestamp data */ - fm10k_ts_init(interface); - /* set default ring sizes */ interface->tx_ring_count = FM10K_DEFAULT_TXD; interface->rx_ring_count = FM10K_DEFAULT_RXD; @@ -2018,9 +1922,6 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* kick off service timer now, even when interface is down */ mod_timer(&interface->service_timer, (HZ * 2) + jiffies); - /* Register PTP interface */ - fm10k_ptp_register(interface); - /* print warning for non-optimal configurations */ fm10k_slot_warn(interface); @@ -2077,9 +1978,6 @@ static void fm10k_remove(struct pci_dev *pdev) if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); - /* cleanup timestamp handling */ - fm10k_ptp_unregister(interface); - /* release VFs */ fm10k_iov_disable(pdev); @@ -2152,9 +2050,6 @@ static int fm10k_resume(struct pci_dev *pdev) /* reset statistics starting values */ hw->mac.ops.rebind_hw_stats(hw, &interface->stats); - /* reset clock */ - fm10k_ts_reset(interface); - rtnl_lock(); err = fm10k_init_queueing_scheme(interface); @@ -2365,9 +2260,6 @@ static void fm10k_io_resume(struct pci_dev *pdev) /* reassociate interrupts */ fm10k_mbx_request_irq(interface); - /* reset clock */ - fm10k_ts_reset(interface); - if (netif_running(netdev)) err = fm10k_open(netdev); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index ecc99f9d2cce..c8e8ce5a8327 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -1140,19 +1140,6 @@ static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw, fm10k_update_hw_stats_q(hw, q, idx, qpp); } -static s32 fm10k_iov_report_timestamp_pf(struct fm10k_hw *hw, - struct fm10k_vf_info *vf_info, - u64 timestamp) -{ - u32 msg[4]; - - /* generate port state response to notify VF it is not ready */ - fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_1588); - fm10k_tlv_attr_put_u64(msg, FM10K_1588_MSG_TIMESTAMP, timestamp); - - return vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); -} - /** * fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF * @hw: Pointer to hardware structure @@ -1773,89 +1760,6 @@ s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results, return 0; } -const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[] = { - FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_1588_TIMESTAMP, - sizeof(struct fm10k_swapi_1588_timestamp)), - FM10K_TLV_ATTR_LAST -}; - -/* currently there is no shared 1588 timestamp handler */ - -/** - * fm10k_adjust_systime_pf - Adjust systime frequency - * @hw: pointer to hardware structure - * @ppb: adjustment rate in parts per billion - * - * This function will adjust the SYSTIME_CFG register contained in BAR 4 - * if this function is supported for BAR 4 access. The adjustment amount - * is based on the parts per billion value provided and adjusted to a - * value based on parts per 2^48 clock cycles. - * - * If adjustment is not supported or the requested value is too large - * we will return an error. - **/ -static s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb) -{ - u64 systime_adjust; - - /* if sw_addr is not set we don't have switch register access */ - if (!hw->sw_addr) - return ppb ? FM10K_ERR_PARAM : 0; - - /* we must convert the value from parts per billion to parts per - * 2^48 cycles. In addition I have opted to only use the 30 most - * significant bits of the adjustment value as the 8 least - * significant bits are located in another register and represent - * a value significantly less than a part per billion, the result - * of dropping the 8 least significant bits is that the adjustment - * value is effectively multiplied by 2^8 when we write it. - * - * As a result of all this the math for this breaks down as follows: - * ppb / 10^9 == adjust * 2^8 / 2^48 - * If we solve this for adjust, and simplify it comes out as: - * ppb * 2^31 / 5^9 == adjust - */ - systime_adjust = (ppb < 0) ? -ppb : ppb; - systime_adjust <<= 31; - do_div(systime_adjust, 1953125); - - /* verify the requested adjustment value is in range */ - if (systime_adjust > FM10K_SW_SYSTIME_ADJUST_MASK) - return FM10K_ERR_PARAM; - - if (ppb > 0) - systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_POSITIVE; - - fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_ADJUST, (u32)systime_adjust); - - return 0; -} - -/** - * fm10k_read_systime_pf - Reads value of systime registers - * @hw: pointer to the hardware structure - * - * Function reads the content of 2 registers, combined to represent a 64 bit - * value measured in nanosecods. In order to guarantee the value is accurate - * we check the 32 most significant bits both before and after reading the - * 32 least significant bits to verify they didn't change as we were reading - * the registers. - **/ -static u64 fm10k_read_systime_pf(struct fm10k_hw *hw) -{ - u32 systime_l, systime_h, systime_tmp; - - systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1); - - do { - systime_tmp = systime_h; - systime_l = fm10k_read_reg(hw, FM10K_SYSTIME); - systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1); - } while (systime_tmp != systime_h); - - return ((u64)systime_h << 32) | systime_l; -} - static const struct fm10k_msg_data fm10k_msg_data_pf[] = { FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), @@ -1885,8 +1789,6 @@ static const struct fm10k_mac_ops mac_ops_pf = { .set_dma_mask = fm10k_set_dma_mask_pf, .get_fault = fm10k_get_fault_pf, .get_host_state = fm10k_get_host_state_pf, - .adjust_systime = fm10k_adjust_systime_pf, - .read_systime = fm10k_read_systime_pf, }; static const struct fm10k_iov_ops iov_ops_pf = { @@ -1898,7 +1800,6 @@ static const struct fm10k_iov_ops iov_ops_pf = { .set_lport = fm10k_iov_set_lport_pf, .reset_lport = fm10k_iov_reset_lport_pf, .update_stats = fm10k_iov_update_stats_pf, - .report_timestamp = fm10k_iov_report_timestamp_pf, }; static s32 fm10k_get_invariants_pf(struct fm10k_hw *hw) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h index b2d96b45ca3c..b78210d06213 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -42,8 +42,6 @@ enum fm10k_pf_tlv_msg_id_v1 { FM10K_PF_MSG_ID_UPDATE_FLOW = 0x503, FM10K_PF_MSG_ID_DELETE_FLOW = 0x504, FM10K_PF_MSG_ID_SET_FLOW_STATE = 0x505, - FM10K_PF_MSG_ID_GET_1588_INFO = 0x506, - FM10K_PF_MSG_ID_1588_TIMESTAMP = 0x701, }; enum fm10k_pf_tlv_attr_id_v1 { @@ -61,7 +59,6 @@ enum fm10k_pf_tlv_attr_id_v1 { FM10K_PF_ATTR_ID_DELETE_FLOW = 0x0B, FM10K_PF_ATTR_ID_PORT = 0x0C, FM10K_PF_ATTR_ID_UPDATE_PVID = 0x0D, - FM10K_PF_ATTR_ID_1588_TIMESTAMP = 0x10, }; #define FM10K_MSG_LPORT_MAP_GLORT_SHIFT 0 @@ -100,13 +97,6 @@ struct fm10k_swapi_error { struct fm10k_global_table_data ffu; } __aligned(4) __packed; -struct fm10k_swapi_1588_timestamp { - __le64 egress; - __le64 ingress; - __le16 dglort; - __le16 sglort; -} __aligned(4) __packed; - s32 fm10k_msg_lport_map_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[]; #define FM10K_PF_MSG_LPORT_MAP_HANDLER(func) \ @@ -122,11 +112,6 @@ extern const struct fm10k_tlv_attr fm10k_err_msg_attr[]; #define FM10K_PF_MSG_ERR_HANDLER(msg, func) \ FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_##msg, fm10k_err_msg_attr, func) -extern const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[]; -#define FM10K_PF_MSG_1588_TIMESTAMP_HANDLER(func) \ - FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_1588_TIMESTAMP, \ - fm10k_1588_timestamp_msg_attr, func) - s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c b/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c deleted file mode 100644 index 1c1ccade6538..000000000000 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ptp.c +++ /dev/null @@ -1,462 +0,0 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include -#include - -#include "fm10k.h" - -#define FM10K_TS_TX_TIMEOUT (HZ * 15) - -void fm10k_systime_to_hwtstamp(struct fm10k_intfc *interface, - struct skb_shared_hwtstamps *hwtstamp, - u64 systime) -{ - unsigned long flags; - - read_lock_irqsave(&interface->systime_lock, flags); - systime += interface->ptp_adjust; - read_unlock_irqrestore(&interface->systime_lock, flags); - - hwtstamp->hwtstamp = ns_to_ktime(systime); -} - -static struct sk_buff *fm10k_ts_tx_skb(struct fm10k_intfc *interface, - __le16 dglort) -{ - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *skb; - - skb_queue_walk(list, skb) { - if (FM10K_CB(skb)->fi.w.dglort == dglort) - return skb; - } - - return NULL; -} - -void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb) -{ - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *clone; - unsigned long flags; - - /* create clone for us to return on the Tx path */ - clone = skb_clone_sk(skb); - if (!clone) - return; - - FM10K_CB(clone)->ts_tx_timeout = jiffies + FM10K_TS_TX_TIMEOUT; - spin_lock_irqsave(&list->lock, flags); - - /* attempt to locate any buffers with the same dglort, - * if none are present then insert skb in tail of list - */ - skb = fm10k_ts_tx_skb(interface, FM10K_CB(clone)->fi.w.dglort); - if (!skb) { - skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; - __skb_queue_tail(list, clone); - } - - spin_unlock_irqrestore(&list->lock, flags); - - /* if list is already has one then we just free the clone */ - if (skb) - dev_kfree_skb(clone); -} - -void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort, - u64 systime) -{ - struct skb_shared_hwtstamps shhwtstamps; - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *skb; - unsigned long flags; - - spin_lock_irqsave(&list->lock, flags); - - /* attempt to locate and pull the sk_buff out of the list */ - skb = fm10k_ts_tx_skb(interface, dglort); - if (skb) - __skb_unlink(skb, list); - - spin_unlock_irqrestore(&list->lock, flags); - - /* if not found do nothing */ - if (!skb) - return; - - /* timestamp the sk_buff and free out copy */ - fm10k_systime_to_hwtstamp(interface, &shhwtstamps, systime); - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); -} - -void fm10k_ts_tx_subtask(struct fm10k_intfc *interface) -{ - struct sk_buff_head *list = &interface->ts_tx_skb_queue; - struct sk_buff *skb, *tmp; - unsigned long flags; - - /* If we're down or resetting, just bail */ - if (test_bit(__FM10K_DOWN, &interface->state) || - test_bit(__FM10K_RESETTING, &interface->state)) - return; - - spin_lock_irqsave(&list->lock, flags); - - /* walk though the list and flush any expired timestamp packets */ - skb_queue_walk_safe(list, skb, tmp) { - if (!time_is_after_jiffies(FM10K_CB(skb)->ts_tx_timeout)) - continue; - __skb_unlink(skb, list); - kfree_skb(skb); - interface->tx_hwtstamp_timeouts++; - } - - spin_unlock_irqrestore(&list->lock, flags); -} - -static u64 fm10k_systime_read(struct fm10k_intfc *interface) -{ - struct fm10k_hw *hw = &interface->hw; - - return hw->mac.ops.read_systime(hw); -} - -void fm10k_ts_reset(struct fm10k_intfc *interface) -{ - s64 ns = ktime_to_ns(ktime_get_real()); - unsigned long flags; - - /* reinitialize the clock */ - write_lock_irqsave(&interface->systime_lock, flags); - interface->ptp_adjust = fm10k_systime_read(interface) - ns; - write_unlock_irqrestore(&interface->systime_lock, flags); -} - -void fm10k_ts_init(struct fm10k_intfc *interface) -{ - /* Initialize lock protecting systime access */ - rwlock_init(&interface->systime_lock); - - /* Initialize skb queue for pending timestamp requests */ - skb_queue_head_init(&interface->ts_tx_skb_queue); - - /* reset the clock to current kernel time */ - fm10k_ts_reset(interface); -} - -/** - * fm10k_get_ts_config - get current hardware timestamping configuration - * @netdev: network interface device structure - * @ifreq: ioctl data - * - * This function returns the current timestamping settings. Rather than - * attempt to deconstruct registers to fill in the values, simply keep a copy - * of the old settings around, and return a copy when requested. - */ -int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr) -{ - struct fm10k_intfc *interface = netdev_priv(netdev); - struct hwtstamp_config *config = &interface->ts_config; - - return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? - -EFAULT : 0; -} - -/** - * fm10k_set_ts_config - control hardware time stamping - * @netdev: network interface device structure - * @ifreq: ioctl data - * - * Outgoing time stamping can be enabled and disabled. Play nice and - * disable it when requested, although it shouldn't cause any overhead - * when no packet needs it. At most one packet in the queue may be - * marked for time stamping, otherwise it would be impossible to tell - * for sure to which packet the hardware time stamp belongs. - * - * Incoming time stamping has to be configured via the hardware - * filters. Not all combinations are supported, in particular event - * type has to be specified. Matching the kind of event packet is - * not supported, with the exception of "all V2 events regardless of - * level 2 or 4". - * - * Since hardware always timestamps Path delay packets when timestamping V2 - * packets, regardless of the type specified in the register, only use V2 - * Event mode. This more accurately tells the user what the hardware is going - * to do anyways. - */ -int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr) -{ - struct fm10k_intfc *interface = netdev_priv(netdev); - struct hwtstamp_config ts_config; - - if (copy_from_user(&ts_config, ifr->ifr_data, sizeof(ts_config))) - return -EFAULT; - - /* reserved for future extensions */ - if (ts_config.flags) - return -EINVAL; - - switch (ts_config.tx_type) { - case HWTSTAMP_TX_OFF: - break; - case HWTSTAMP_TX_ON: - /* we likely need some check here to see if this is supported */ - break; - default: - return -ERANGE; - } - - switch (ts_config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - interface->flags &= ~FM10K_FLAG_RX_TS_ENABLED; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_ALL: - interface->flags |= FM10K_FLAG_RX_TS_ENABLED; - ts_config.rx_filter = HWTSTAMP_FILTER_ALL; - break; - default: - return -ERANGE; - } - - /* save these settings for future reference */ - interface->ts_config = ts_config; - - return copy_to_user(ifr->ifr_data, &ts_config, sizeof(ts_config)) ? - -EFAULT : 0; -} - -static int fm10k_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - struct fm10k_intfc *interface; - struct fm10k_hw *hw; - int err; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - hw = &interface->hw; - - err = hw->mac.ops.adjust_systime(hw, ppb); - - /* the only error we should see is if the value is out of range */ - return (err == FM10K_ERR_PARAM) ? -ERANGE : err; -} - -static int fm10k_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - struct fm10k_intfc *interface; - unsigned long flags; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - - write_lock_irqsave(&interface->systime_lock, flags); - interface->ptp_adjust += delta; - write_unlock_irqrestore(&interface->systime_lock, flags); - - return 0; -} - -static int fm10k_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) -{ - struct fm10k_intfc *interface; - unsigned long flags; - u64 now; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - - read_lock_irqsave(&interface->systime_lock, flags); - now = fm10k_systime_read(interface) + interface->ptp_adjust; - read_unlock_irqrestore(&interface->systime_lock, flags); - - *ts = ns_to_timespec64(now); - - return 0; -} - -static int fm10k_ptp_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts) -{ - struct fm10k_intfc *interface; - unsigned long flags; - u64 ns = timespec64_to_ns(ts); - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - - write_lock_irqsave(&interface->systime_lock, flags); - interface->ptp_adjust = fm10k_systime_read(interface) - ns; - write_unlock_irqrestore(&interface->systime_lock, flags); - - return 0; -} - -static int fm10k_ptp_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, - int __always_unused on) -{ - struct ptp_clock_time *t = &rq->perout.period; - struct fm10k_intfc *interface; - struct fm10k_hw *hw; - u64 period; - u32 step; - - /* we can only support periodic output */ - if (rq->type != PTP_CLK_REQ_PEROUT) - return -EINVAL; - - /* verify the requested channel is there */ - if (rq->perout.index >= ptp->n_per_out) - return -EINVAL; - - /* we cannot enforce start time as there is no - * mechanism for that in the hardware, we can only control - * the period. - */ - - /* we cannot support periods greater than 4 seconds due to reg limit */ - if (t->sec > 4 || t->sec < 0) - return -ERANGE; - - interface = container_of(ptp, struct fm10k_intfc, ptp_caps); - hw = &interface->hw; - - /* we simply cannot support the operation if we don't have BAR4 */ - if (!hw->sw_addr) - return -ENOTSUPP; - - /* convert to unsigned 64b ns, verify we can put it in a 32b register */ - period = t->sec * 1000000000LL + t->nsec; - - /* determine the minimum size for period */ - step = 2 * (fm10k_read_reg(hw, FM10K_SYSTIME_CFG) & - FM10K_SYSTIME_CFG_STEP_MASK); - - /* verify the value is in range supported by hardware */ - if ((period && (period < step)) || (period > U32_MAX)) - return -ERANGE; - - /* notify hardware of request to being sending pulses */ - fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_PULSE(rq->perout.index), - (u32)period); - - return 0; -} - -static struct ptp_pin_desc fm10k_ptp_pd[2] = { - { - .name = "IEEE1588_PULSE0", - .index = 0, - .func = PTP_PF_PEROUT, - .chan = 0 - }, - { - .name = "IEEE1588_PULSE1", - .index = 1, - .func = PTP_PF_PEROUT, - .chan = 1 - } -}; - -static int fm10k_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin, - enum ptp_pin_function func, unsigned int chan) -{ - /* verify the requested pin is there */ - if (pin >= ptp->n_pins || !ptp->pin_config) - return -EINVAL; - - /* enforce locked channels, no changing them */ - if (chan != ptp->pin_config[pin].chan) - return -EINVAL; - - /* we want to keep the functions locked as well */ - if (func != ptp->pin_config[pin].func) - return -EINVAL; - - return 0; -} - -void fm10k_ptp_register(struct fm10k_intfc *interface) -{ - struct ptp_clock_info *ptp_caps = &interface->ptp_caps; - struct device *dev = &interface->pdev->dev; - struct ptp_clock *ptp_clock; - - snprintf(ptp_caps->name, sizeof(ptp_caps->name), - "%s", interface->netdev->name); - ptp_caps->owner = THIS_MODULE; - /* This math is simply the inverse of the math in - * fm10k_adjust_systime_pf applied to an adjustment value - * of 2^30 - 1 which is the maximum value of the register: - * max_ppb == ((2^30 - 1) * 5^9) / 2^31 - */ - ptp_caps->max_adj = 976562; - ptp_caps->adjfreq = fm10k_ptp_adjfreq; - ptp_caps->adjtime = fm10k_ptp_adjtime; - ptp_caps->gettime64 = fm10k_ptp_gettime; - ptp_caps->settime64 = fm10k_ptp_settime; - - /* provide pins if BAR4 is accessible */ - if (interface->sw_addr) { - /* enable periodic outputs */ - ptp_caps->n_per_out = 2; - ptp_caps->enable = fm10k_ptp_enable; - - /* enable clock pins */ - ptp_caps->verify = fm10k_ptp_verify; - ptp_caps->n_pins = 2; - ptp_caps->pin_config = fm10k_ptp_pd; - } - - ptp_clock = ptp_clock_register(ptp_caps, dev); - if (IS_ERR(ptp_clock)) { - ptp_clock = NULL; - dev_err(dev, "ptp_clock_register failed\n"); - } else { - dev_info(dev, "registered PHC device %s\n", ptp_caps->name); - } - - interface->ptp_clock = ptp_clock; -} - -void fm10k_ptp_unregister(struct fm10k_intfc *interface) -{ - struct ptp_clock *ptp_clock = interface->ptp_clock; - struct device *dev = &interface->pdev->dev; - - if (!ptp_clock) - return; - - interface->ptp_clock = NULL; - - ptp_clock_unregister(ptp_clock); - dev_info(dev, "removed PHC %s\n", interface->ptp_caps.name); -} diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index 5c0533054c5f..995dceefec25 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -225,11 +225,6 @@ struct fm10k_hw; #define FM10K_STATS_LOOPBACK_DROP 0x3806 #define FM10K_STATS_NODESC_DROP 0x3807 -/* Timesync registers */ -#define FM10K_SYSTIME 0x3814 -#define FM10K_SYSTIME_CFG 0x3818 -#define FM10K_SYSTIME_CFG_STEP_MASK 0x0000000F - /* PCIe state registers */ #define FM10K_PHYADDR 0x381C @@ -381,12 +376,6 @@ struct fm10k_hw; #define FM10K_VFSYSTIME 0x00040 #define FM10K_VFITR(_n) ((_n) + 0x00060) -/* Registers contained in BAR 4 for Switch management */ -#define FM10K_SW_SYSTIME_ADJUST 0x0224D -#define FM10K_SW_SYSTIME_ADJUST_MASK 0x3FFFFFFF -#define FM10K_SW_SYSTIME_ADJUST_DIR_POSITIVE 0x80000000 -#define FM10K_SW_SYSTIME_PULSE(_n) ((_n) + 0x02252) - enum fm10k_int_source { fm10k_int_mailbox = 0, fm10k_int_pcie_fault = 1, @@ -550,8 +539,6 @@ struct fm10k_mac_ops { struct fm10k_dglort_cfg *); void (*set_dma_mask)(struct fm10k_hw *, u64); s32 (*get_fault)(struct fm10k_hw *, int, struct fm10k_fault *); - s32 (*adjust_systime)(struct fm10k_hw *, s32 ppb); - u64 (*read_systime)(struct fm10k_hw *); }; enum fm10k_mac_type { @@ -643,7 +630,6 @@ struct fm10k_iov_ops { s32 (*set_lport)(struct fm10k_hw *, struct fm10k_vf_info *, u16, u8); void (*reset_lport)(struct fm10k_hw *, struct fm10k_vf_info *); void (*update_stats)(struct fm10k_hw *, struct fm10k_hw_stats_q *, u16); - s32 (*report_timestamp)(struct fm10k_hw *, struct fm10k_vf_info *, u64); }; struct fm10k_iov_info { @@ -667,7 +653,6 @@ struct fm10k_info { struct fm10k_hw { u32 __iomem *hw_addr; - u32 __iomem *sw_addr; void *back; struct fm10k_mac_info mac; struct fm10k_bus_info bus; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index 91f8d7311f3b..86c358c37d3f 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -451,13 +451,6 @@ static s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, u16 glort, u8 mode) return mbx->ops.enqueue_tx(hw, mbx, msg); } -const struct fm10k_tlv_attr fm10k_1588_msg_attr[] = { - FM10K_TLV_ATTR_U64(FM10K_1588_MSG_TIMESTAMP), - FM10K_TLV_ATTR_LAST -}; - -/* currently there is no shared 1588 timestamp handler */ - /** * fm10k_update_hw_stats_vf - Updates hardware related statistics of VF * @hw: pointer to hardware structure @@ -509,52 +502,6 @@ static s32 fm10k_configure_dglort_map_vf(struct fm10k_hw *hw, return 0; } -/** - * fm10k_adjust_systime_vf - Adjust systime frequency - * @hw: pointer to hardware structure - * @ppb: adjustment rate in parts per billion - * - * This function takes an adjustment rate in parts per billion and will - * verify that this value is 0 as the VF cannot support adjusting the - * systime clock. - * - * If the ppb value is non-zero the return is ERR_PARAM else success - **/ -static s32 fm10k_adjust_systime_vf(struct fm10k_hw *hw, s32 ppb) -{ - /* The VF cannot adjust the clock frequency, however it should - * already have a syntonic clock with whichever host interface is - * running as the master for the host interface clock domain so - * there should be not frequency adjustment necessary. - */ - return ppb ? FM10K_ERR_PARAM : 0; -} - -/** - * fm10k_read_systime_vf - Reads value of systime registers - * @hw: pointer to the hardware structure - * - * Function reads the content of 2 registers, combined to represent a 64 bit - * value measured in nanoseconds. In order to guarantee the value is accurate - * we check the 32 most significant bits both before and after reading the - * 32 least significant bits to verify they didn't change as we were reading - * the registers. - **/ -static u64 fm10k_read_systime_vf(struct fm10k_hw *hw) -{ - u32 systime_l, systime_h, systime_tmp; - - systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1); - - do { - systime_tmp = systime_h; - systime_l = fm10k_read_reg(hw, FM10K_VFSYSTIME); - systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1); - } while (systime_tmp != systime_h); - - return ((u64)systime_h << 32) | systime_l; -} - static const struct fm10k_msg_data fm10k_msg_data_vf[] = { FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf), @@ -579,8 +526,6 @@ static const struct fm10k_mac_ops mac_ops_vf = { .rebind_hw_stats = fm10k_rebind_hw_stats_vf, .configure_dglort_map = fm10k_configure_dglort_map_vf, .get_host_state = fm10k_get_host_state_generic, - .adjust_systime = fm10k_adjust_systime_vf, - .read_systime = fm10k_read_systime_vf, }; static s32 fm10k_get_invariants_vf(struct fm10k_hw *hw) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.h b/drivers/net/ethernet/intel/fm10k/fm10k_vf.h index c4439f1313a0..f0932f944793 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.h @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2014 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -29,7 +29,6 @@ enum fm10k_vf_tlv_msg_id { FM10K_VF_MSG_ID_MSIX, FM10K_VF_MSG_ID_MAC_VLAN, FM10K_VF_MSG_ID_LPORT_STATE, - FM10K_VF_MSG_ID_1588, FM10K_VF_MSG_ID_MAX, }; @@ -49,11 +48,6 @@ enum fm10k_tlv_lport_state_attr_id { FM10K_LPORT_STATE_MSG_MAX }; -enum fm10k_tlv_1588_attr_id { - FM10K_1588_MSG_TIMESTAMP, - FM10K_1588_MSG_MAX -}; - #define FM10K_VF_MSG_MSIX_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_MSIX, NULL, func) @@ -70,9 +64,5 @@ extern const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[]; FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_LPORT_STATE, \ fm10k_lport_state_msg_attr, func) -extern const struct fm10k_tlv_attr fm10k_1588_msg_attr[]; -#define FM10K_VF_MSG_1588_HANDLER(func) \ - FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_1588, fm10k_1588_msg_attr, func) - extern const struct fm10k_info fm10k_vf_info; #endif /* _FM10K_VF_H */ -- GitLab From 8998763a7b57583ef2e07f68ea6a7d05bcfc1cfa Mon Sep 17 00:00:00 2001 From: Ngai-Mint Kwan Date: Fri, 1 Apr 2016 16:17:32 -0700 Subject: [PATCH 3805/9938] fm10k: Fix multicast mode sync issues Multicast mode checking is no longer a requirement to perform unicast and multicast address syncs. Specifically, a device operating in promiscuous and/or all multicast mode is not excluded. The issue occurs when the netdev is pre-configured to either multicast mode and is enabled for the first time. The multicast-group table in the Switch Manager will be missing obvious multicast entries associated to this netdev. Changes were also made to disallow unicast and multicast syncs with VLAN 0. The Switch Manager considers VLAN 0 to be an invalid entry. Requests with VLAN 0 by the netdev are only generated when the driver is freshly installed and the default VID is not set. Signed-off-by: Ngai-Mint Kwan Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/fm10k/fm10k_netdev.c | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 32778dda8c12..bf229d54c20c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -877,7 +877,7 @@ static int __fm10k_uc_sync(struct net_device *dev, return -EADDRNOTAVAIL; /* update table with current entries */ - for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 0; + for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1; vid < VLAN_N_VID; vid = fm10k_find_next_vlan(interface, vid)) { err = hw->mac.ops.update_uc_addr(hw, glort, addr, @@ -940,7 +940,7 @@ static int __fm10k_mc_sync(struct net_device *dev, u16 vid, glort = interface->glort; /* update table with current entries */ - for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 0; + for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1; vid < VLAN_N_VID; vid = fm10k_find_next_vlan(interface, vid)) { hw->mac.ops.update_mc_addr(hw, glort, addr, vid, sync); @@ -995,11 +995,8 @@ static void fm10k_set_rx_mode(struct net_device *dev) } /* synchronize all of the addresses */ - if (xcast_mode != FM10K_XCAST_MODE_PROMISC) { - __dev_uc_sync(dev, fm10k_uc_sync, fm10k_uc_unsync); - if (xcast_mode != FM10K_XCAST_MODE_ALLMULTI) - __dev_mc_sync(dev, fm10k_mc_sync, fm10k_mc_unsync); - } + __dev_uc_sync(dev, fm10k_uc_sync, fm10k_uc_unsync); + __dev_mc_sync(dev, fm10k_mc_sync, fm10k_mc_unsync); fm10k_mbx_unlock(interface); } @@ -1037,7 +1034,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) hw->mac.ops.update_vlan(hw, 0, 0, true); /* update table with current entries */ - for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 0; + for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1; vid < VLAN_N_VID; vid = fm10k_find_next_vlan(interface, vid)) { hw->mac.ops.update_vlan(hw, vid, 0, true); @@ -1049,11 +1046,8 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode); /* synchronize all of the addresses */ - if (xcast_mode != FM10K_XCAST_MODE_PROMISC) { - __dev_uc_sync(netdev, fm10k_uc_sync, fm10k_uc_unsync); - if (xcast_mode != FM10K_XCAST_MODE_ALLMULTI) - __dev_mc_sync(netdev, fm10k_mc_sync, fm10k_mc_unsync); - } + __dev_uc_sync(netdev, fm10k_uc_sync, fm10k_uc_unsync); + __dev_mc_sync(netdev, fm10k_mc_sync, fm10k_mc_unsync); fm10k_mbx_unlock(interface); -- GitLab From a7a7783adabc3cc7599f7dbf97fcc3b0d44087b7 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 16:17:33 -0700 Subject: [PATCH 3806/9938] fm10k: correctly handle LPORT_MAP error Currently, any error responses from the switch manager after an LPORT_MAP request are silently ignored. At most the mailbox message will be reported as an error. This can result in unexpected behavior when the switch manager has configured a port with zero bandwidth. Add support for reading the fm10k_swapi_error structure from LPORT_MAP responses. If the message contains the necessary TLV and has a non-zero error code, report link down, clear the dglort_map, and delay the next get_host_state call by a reasonable delay. Also log an error message indicating that the LPORT_MAP request failed. The delay ensures preventing an interrupt storm on the switch manager, and reduces the number of mailbox messages we send in this scenario drastically. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k.h | 1 + drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 31 +++++++++++++++++++- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 2 ++ drivers/net/ethernet/intel/fm10k/fm10k_pf.h | 2 ++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index c21fa8699fc4..5efae40698cc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -330,6 +330,7 @@ struct fm10k_intfc { unsigned long last_reset; unsigned long link_down_event; bool host_ready; + bool lport_map_failed; u32 reta[FM10K_RETA_SIZE]; u32 rssrk[FM10K_RSSRK_SIZE]; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 29e9402c4352..9055681cf34d 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1263,11 +1263,40 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results, u32 dglort_map = hw->mac.dglort_map; s32 err; + interface = container_of(hw, struct fm10k_intfc, hw); + + err = fm10k_msg_err_pf(hw, results, mbx); + if (!err && hw->swapi.status) { + /* force link down for a reasonable delay */ + interface->link_down_event = jiffies + (2 * HZ); + set_bit(__FM10K_LINK_DOWN, &interface->state); + + /* reset dglort_map back to no config */ + hw->mac.dglort_map = FM10K_DGLORTMAP_NONE; + + fm10k_service_event_schedule(interface); + + /* prevent overloading kernel message buffer */ + if (interface->lport_map_failed) + return 0; + + interface->lport_map_failed = true; + + if (hw->swapi.status == FM10K_MSG_ERR_PEP_NOT_SCHEDULED) + dev_warn(&interface->pdev->dev, + "cannot obtain link because the host interface is configured for a PCIe host interface bandwidth of zero\n"); + dev_warn(&interface->pdev->dev, + "request logical port map failed: %d\n", + hw->swapi.status); + + return 0; + } + err = fm10k_msg_lport_map_pf(hw, results, mbx); if (err) return err; - interface = container_of(hw, struct fm10k_intfc, hw); + interface->lport_map_failed = false; /* we need to reset if port count was just updated */ if (dglort_map != hw->mac.dglort_map) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index c8e8ce5a8327..865f5c2da9d0 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1620,6 +1620,8 @@ static s32 fm10k_get_host_state_pf(struct fm10k_hw *hw, bool *switch_ready) /* This structure defines the attibutes to be parsed below */ const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = { + FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR, + sizeof(struct fm10k_swapi_error)), FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_LPORT_MAP), FM10K_TLV_ATTR_LAST }; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h index b78210d06213..d4a34657b861 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h @@ -71,6 +71,8 @@ enum fm10k_pf_tlv_attr_id_v1 { #define FM10K_MSG_UPDATE_PVID_PVID_SHIFT 16 #define FM10K_MSG_UPDATE_PVID_PVID_SIZE 16 +#define FM10K_MSG_ERR_PEP_NOT_SCHEDULED 280 + /* The following data structures are overlayed directly onto TLV mailbox * messages, and must not break 4 byte alignment. Ensure the structures line * up correctly as per their TLV definition. -- GitLab From 3417415c3a86d6bae8bfee495ce634f4d24e16b8 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 16:17:34 -0700 Subject: [PATCH 3807/9938] fm10k: do not disable PCI device in fm10k_io_error_detected fm10k_io_error_detected() does not need to call pci_disable_device(). In the cases where the reset needs to occur, the stack flow will result in calling fm10k_remove() which already disables the PCI device. If we leave the pci_disable_device(), we result in a warning about disabling an already disabled device. Many PCI drivers do call pci_disable_device() in their .error_detected() routines, but it does not appear to be required. In addition, these drivers have a check "is_pci_enabled()" call in their remove routines, which is how they chose to handle the duplicate device disable. This seems incorrect, since the PCI device structure is reference counted. It is very possible that the reference count for the PCI device could be greater than 1. In this case, you would remove the PCI device within the error_detected routine, reducing count to 1, then remove it again in the remove function, reducing it to zero. This would result in yet another disable somewhere else failing. Thus, we shouldn't be using is_pci_enabled() to check for this issue. Instead, just remove the extraneous pci_device_disable() found within the error_detected routine. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 9055681cf34d..1d833782d917 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -2207,8 +2207,6 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, rtnl_unlock(); - pci_disable_device(pdev); - /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; } -- GitLab From 4e160f2a59cec8f705583edfaa11ce5f3b3ef4a6 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 16:17:35 -0700 Subject: [PATCH 3808/9938] fm10k: fix documentation of fm10k_tlv_parse_attr fm10k_tlv_parse_attr is supposed to return FM10K_NOT_IMPLEMENTED for any TLV who's attribute id lies outside the range of results. It does not do this today. In addition, the documentation does not indicate that other attributes which are not implemented for a given TLV will be silently ignored. Fix this. Clean up the logic so that we don't rely on the fact that FM10K_NOT_IMPLEMENTED is greater than zero, as this can easily cause confusion. A future extension could look into some way of reporting unknown TLVs in order to make issues more easily discoverable. We can't just return FM10K_NOT_IMPLEMENTED here because we don't want to drop the entire message if it has an unknown TLV. While here, update the copyright year. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_tlv.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c index b999897e50d8..6b500a6378e0 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c @@ -1,5 +1,5 @@ /* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -481,7 +481,8 @@ static s32 fm10k_tlv_attr_validate(u32 *attr, * up into an array of pointers stored in results. The function will * return FM10K_ERR_PARAM on any input or message error, * FM10K_NOT_IMPLEMENTED for any attribute that is outside of the array - * and 0 on success. + * and 0 on success. Any attributes not found in tlv_attr will be silently + * ignored. **/ static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results, const struct fm10k_tlv_attr *tlv_attr) @@ -518,14 +519,15 @@ static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results, while (offset < len) { attr_id = *attr & FM10K_TLV_ID_MASK; - if (attr_id < FM10K_TLV_RESULTS_MAX) - err = fm10k_tlv_attr_validate(attr, tlv_attr); - else - err = FM10K_NOT_IMPLEMENTED; + if (attr_id >= FM10K_TLV_RESULTS_MAX) + return FM10K_NOT_IMPLEMENTED; - if (err < 0) + err = fm10k_tlv_attr_validate(attr, tlv_attr); + if (err == FM10K_NOT_IMPLEMENTED) + ; /* silently ignore non-implemented attributes */ + else if (err) return err; - if (!err) + else results[attr_id] = attr; /* update offset */ -- GitLab From d057d9a9446636293b4884d1a0da6ad5a7ef4e13 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 16:17:36 -0700 Subject: [PATCH 3809/9938] fm10k: use 8bit notation instead of 10bit notation for diagram The diagram represents bit layout of the multi-bit VLAN update message format. Typically these diagrams are drawn using some power of 2 as the base, to more easily grasp where fields split. Although the numbers above can make it somewhat easy to understand which bit you're looking at, it makes the break points not line up. Re-draw the numbers using base 8, and mark the bit values every 8 bits at the top. This should make it more easy to grasp the table quickly. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 865f5c2da9d0..ffe98056755b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -219,8 +219,8 @@ static s32 fm10k_update_vlan_pf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) /* VLAN multi-bit write: * The multi-bit write has several parts to it. - * 3 2 1 0 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * 24 16 8 0 + * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | RSVD0 | Length |C|RSVD0| VLAN ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -- GitLab From 5c69df8a33408c82ac633c521be0acf71a690d43 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 16:17:37 -0700 Subject: [PATCH 3810/9938] fm10k: use different name than FM10K_VLAN_CLEAR for override bit Use a new #define FM10K_VLAN_OVERRIDE even though we're using the exact same bit. The reason for this is clarity in the code, otherwise you can read FM10K_VLAN_CLEAR and think it should be removed. Also add a comment explaining why the FM10K_VLAN_OVERRIDE bit is set. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 8 ++++++-- drivers/net/ethernet/intel/fm10k/fm10k_type.h | 1 + drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index ffe98056755b..88d5acf484d0 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -864,9 +864,13 @@ static s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw, fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), 0); fm10k_write_reg(hw, FM10K_TXDCTL(vf_q_idx), 0); - /* determine correct default VLAN ID */ + /* Determine correct default VLAN ID. The FM10K_VLAN_OVERRIDE bit is + * used here to indicate to the VF that it will not have privilege to + * write VLAN_TABLE. All policy is enforced on the PF but this allows + * the VF to correctly report errors to userspace rqeuests. + */ if (vf_info->pf_vid) - vf_vid = vf_info->pf_vid | FM10K_VLAN_CLEAR; + vf_vid = vf_info->pf_vid | FM10K_VLAN_OVERRIDE; else vf_vid = vf_info->sw_vid; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index 995dceefec25..f3f37a49806e 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -350,6 +350,7 @@ struct fm10k_hw; #define FM10K_VLAN_TABLE_VSI_MAX 64 #define FM10K_VLAN_LENGTH_SHIFT 16 #define FM10K_VLAN_CLEAR BIT(15) +#define FM10K_VLAN_OVERRIDE FM10K_VLAN_CLEAR #define FM10K_VLAN_ALL \ ((FM10K_VLAN_TABLE_VID_MAX - 1) << FM10K_VLAN_LENGTH_SHIFT) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index 86c358c37d3f..801238dec624 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -228,7 +228,7 @@ s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *hw, u32 **results, ether_addr_copy(hw->mac.perm_addr, perm_addr); hw->mac.default_vid = vid & (FM10K_VLAN_TABLE_VID_MAX - 1); - hw->mac.vlan_override = !!(vid & FM10K_VLAN_CLEAR); + hw->mac.vlan_override = !!(vid & FM10K_VLAN_OVERRIDE); return 0; } -- GitLab From fb6515c8f03bbfdc99cff156becd5e14df1dd601 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 1 Apr 2016 16:17:38 -0700 Subject: [PATCH 3811/9938] fm10k: update comment regarding reserved bits check The original comment may be read incorrectly as referring to checking the *entire* length is zero. However, it merely checks only the reserved bits of both length and reserved in a small amount of code. Update the comment to indicate this is a clever trick and clearly spell out that it only checks the reserve bits. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index 801238dec624..0440706eeb82 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -188,7 +188,7 @@ static s32 fm10k_update_vlan_vf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) if (vsi) return FM10K_ERR_PARAM; - /* verify upper 4 bits of vid and length are 0 */ + /* clever trick to verify reserved bits in both vid and length */ if ((vid << 16 | vid) >> 28) return FM10K_ERR_PARAM; -- GitLab From 11ec36a974f59c99e8a4ff7040026569a43ab567 Mon Sep 17 00:00:00 2001 From: Ngai-Mint Kwan Date: Fri, 1 Apr 2016 16:17:39 -0700 Subject: [PATCH 3812/9938] fm10k: Reset multicast mode when deleting lport Deleting lport when multicast mode is configured to FM10K_XCAST_MODE_ALLMULTI or FM10K_XCAST_MODE_PROMISC will result in generating orphaned multicast-group entries in the switch manager. Before deleting the lport, reset multicast mode to FM10K_XCAST_MODE_NONE to flush out these multicast-group entries. Signed-off-by: Ngai-Mint Kwan Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 88d5acf484d0..2105cb8d31cc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -488,6 +488,10 @@ static s32 fm10k_update_lport_state_pf(struct fm10k_hw *hw, u16 glort, if (!fm10k_glort_valid_pf(hw, glort)) return FM10K_ERR_PARAM; + /* reset multicast mode if deleting lport */ + if (!enable) + fm10k_update_xcast_mode_pf(hw, glort, FM10K_XCAST_MODE_NONE); + /* construct the lport message from the 2 pieces of data we have */ lport_msg = ((u32)count << 16) | glort; -- GitLab From 540a5d859010a239a99aba02a9fed7b255c0033e Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 7 Apr 2016 08:21:20 -0700 Subject: [PATCH 3813/9938] fm10k: fix possible null pointer deref after kcalloc When writing a new default redirection table, we needed to populate a new RSS table using ethtool_rxfh_indir_default. We populated this table into a region of memory allocated using kcalloc, but never checked this for NULL. Fix this by moving the default table generation into fm10k_write_reta. If this function is passed a table, use it. Otherwise, generate the default table using ethtool_rxfh_indir_default, 4 at at time. Fixes: 0ea7fae44094 ("fm10k: use ethtool_rxfh_indir_default for default redirection table") Signed-off-by: Jacob Keller Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/fm10k/fm10k_ethtool.c | 26 ++++++++++++++----- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 14 ++-------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index ca276c0a4b8d..e79e91500a0c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -971,15 +971,29 @@ u32 fm10k_get_reta_size(struct net_device __always_unused *netdev) void fm10k_write_reta(struct fm10k_intfc *interface, const u32 *indir) { + u16 rss_i = interface->ring_feature[RING_F_RSS].indices; struct fm10k_hw *hw = &interface->hw; - int i; + u32 table[4]; + int i, j; /* record entries to reta table */ - for (i = 0; i < FM10K_RETA_SIZE; i++, indir += 4) { - u32 reta = indir[0] | - (indir[1] << 8) | - (indir[2] << 16) | - (indir[3] << 24); + for (i = 0; i < FM10K_RETA_SIZE; i++) { + u32 reta, n; + + /* generate a new table if we weren't given one */ + for (j = 0; j < 4; j++) { + if (indir) + n = indir[i + j]; + else + n = ethtool_rxfh_indir_default(i + j, rss_i); + + table[j] = n; + } + + reta = table[0] | + (table[1] << 8) | + (table[2] << 16) | + (table[3] << 24); if (interface->reta[i] == reta) continue; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 58092e523bbe..aca3e4762da7 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1927,8 +1927,7 @@ static void fm10k_assign_rings(struct fm10k_intfc *interface) static void fm10k_init_reta(struct fm10k_intfc *interface) { u16 i, rss_i = interface->ring_feature[RING_F_RSS].indices; - struct net_device *netdev = interface->netdev; - u32 reta, *indir; + u32 reta; /* If the Rx flow indirection table has been configured manually, we * need to maintain it when possible. @@ -1953,16 +1952,7 @@ static void fm10k_init_reta(struct fm10k_intfc *interface) } repopulate_reta: - indir = kcalloc(fm10k_get_reta_size(netdev), - sizeof(indir[0]), GFP_KERNEL); - - /* generate redirection table using the default kernel policy */ - for (i = 0; i < fm10k_get_reta_size(netdev); i++) - indir[i] = ethtool_rxfh_indir_default(i, rss_i); - - fm10k_write_reta(interface, indir); - - kfree(indir); + fm10k_write_reta(interface, NULL); } /** -- GitLab From 86641094678a90af278d1f44c0e47f817c9ba46e Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 7 Apr 2016 08:21:21 -0700 Subject: [PATCH 3814/9938] fm10k: consistently use Intel(R) for driver names Update every header file and other locations to consistently use Intel(R) instead of just Intel. Also update copyright year of files which we modified. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/Makefile | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k.h | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_common.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_common.h | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_mbx.h | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_pf.h | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_tlv.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_tlv.h | 4 ++-- drivers/net/ethernet/intel/fm10k/fm10k_type.h | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_vf.h | 2 +- 20 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/Makefile b/drivers/net/ethernet/intel/fm10k/Makefile index 2aeaa39d9a25..cac645329cea 100644 --- a/drivers/net/ethernet/intel/fm10k/Makefile +++ b/drivers/net/ethernet/intel/fm10k/Makefile @@ -1,6 +1,6 @@ ################################################################################ # -# Intel Ethernet Switch Host Interface Driver +# Intel(R) Ethernet Switch Host Interface Driver # Copyright(c) 2013 - 2016 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ ################################################################################ # -# Makefile for the Intel(R) FM10000 Ethernet Switch Host Interface driver +# Makefile for the Intel(R) Ethernet Switch Host Interface Driver # obj-$(CONFIG_FM10K) += fm10k.o diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index 5efae40698cc..fcf106e545c5 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_common.c b/drivers/net/ethernet/intel/fm10k/fm10k_common.c index 6cfae6ac04ea..5bbf19cfe29b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_common.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_common.c @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2014 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_common.h b/drivers/net/ethernet/intel/fm10k/fm10k_common.h index 45e4e5b1f20a..50f71e997448 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_common.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_common.h @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2014 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c b/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c index 2be4361839db..db4bd8bf9722 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c index 5d6137faf7d1..5116fd043630 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index e79e91500a0c..9c0d87503977 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index bbf7c4bac303..47f0743ec03b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index aca3e4762da7..b875f4243667 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ const char fm10k_driver_version[] = DRV_VERSION; char fm10k_driver_name[] = "fm10k"; static const char fm10k_driver_string[] = DRV_SUMMARY; static const char fm10k_copyright[] = - "Copyright (c) 2013 Intel Corporation."; + "Copyright (c) 2013 - 2016 Intel Corporation."; MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION(DRV_SUMMARY); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index 98202c3d591c..c9dfa6564fcf 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h index 245a0a3dc32e..b7dbc8a84c05 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.h @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index bf229d54c20c..2a08d3f5b6df 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 1d833782d917..404f47ae14b6 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 2105cb8d31cc..5b0ceec361e6 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h index d4a34657b861..3336d3c10760 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c index 6b500a6378e0..f8e87bf086b9 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.c @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.h b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.h index e1845e0a17d8..a1f1027fe184 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_tlv.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_tlv.h @@ -1,5 +1,5 @@ -/* Intel Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2015 Intel Corporation. +/* Intel(R) Ethernet Switch Host Interface Driver + * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index f3f37a49806e..b8bc06183720 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index 0440706eeb82..3b06685ea63b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.h b/drivers/net/ethernet/intel/fm10k/fm10k_vf.h index f0932f944793..2662f33c0c71 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.h @@ -1,4 +1,4 @@ -/* Intel Ethernet Switch Host Interface Driver +/* Intel(R) Ethernet Switch Host Interface Driver * Copyright(c) 2013 - 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it -- GitLab From dc1b4c2b88b976a7882922e55666b20e28477c57 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 7 Apr 2016 08:52:53 -0700 Subject: [PATCH 3815/9938] fm10k: fix incorrect IPv6 extended header checksum Check for and handle IPv6 extended headers so that Tx checksum offload can be done. Also use skb_checksum_help for unexpected cases. This was originally discovered in ixgbe. Reported-by: Mark Rustad Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index b875f4243667..0e166e9c90c8 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -820,6 +820,8 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, struct ipv6hdr *ipv6; u8 *raw; } network_hdr; + u8 *transport_hdr; + __be16 frag_off; __be16 protocol; u8 l4_hdr = 0; @@ -837,9 +839,11 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, goto no_csum; } network_hdr.raw = skb_inner_network_header(skb); + transport_hdr = skb_inner_transport_header(skb); } else { protocol = vlan_get_protocol(skb); network_hdr.raw = skb_network_header(skb); + transport_hdr = skb_transport_header(skb); } switch (protocol) { @@ -848,15 +852,17 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, break; case htons(ETH_P_IPV6): l4_hdr = network_hdr.ipv6->nexthdr; + if (likely((transport_hdr - network_hdr.raw) == + sizeof(struct ipv6hdr))) + break; + ipv6_skip_exthdr(skb, network_hdr.raw - skb->data + + sizeof(struct ipv6hdr), + &l4_hdr, &frag_off); + if (unlikely(frag_off)) + l4_hdr = NEXTHDR_FRAGMENT; break; default: - if (unlikely(net_ratelimit())) { - dev_warn(tx_ring->dev, - "partial checksum but ip version=%x!\n", - protocol); - } - tx_ring->tx_stats.csum_err++; - goto no_csum; + break; } switch (l4_hdr) { @@ -869,9 +875,10 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, default: if (unlikely(net_ratelimit())) { dev_warn(tx_ring->dev, - "partial checksum but l4 proto=%x!\n", - l4_hdr); + "partial checksum, version=%d l4 proto=%x\n", + protocol, l4_hdr); } + skb_checksum_help(skb); tx_ring->tx_stats.csum_err++; goto no_csum; } -- GitLab From f3abcb66b55ff30b976f7fd48c84fd3922d95d55 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3816/9938] pinctrl: vt8500: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean the error path. Signed-off-by: Laxman Dewangan Cc: Lee Jones Cc: Heiko Stuebner Cc: Mika Westerberg Cc: Hongzhou Yang Signed-off-by: Linus Walleij --- drivers/pinctrl/vt8500/pinctrl-wmt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index 5c261bf5542f..cbc638631678 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -583,7 +583,7 @@ int wmt_pinctrl_probe(struct platform_device *pdev, data->dev = &pdev->dev; - data->pctl_dev = pinctrl_register(&wmt_desc, &pdev->dev, data); + data->pctl_dev = devm_pinctrl_register(&pdev->dev, &wmt_desc, data); if (IS_ERR(data->pctl_dev)) { dev_err(&pdev->dev, "Failed to register pinctrl\n"); return PTR_ERR(data->pctl_dev); @@ -592,7 +592,7 @@ int wmt_pinctrl_probe(struct platform_device *pdev, err = gpiochip_add_data(&data->gpio_chip, data); if (err) { dev_err(&pdev->dev, "could not add GPIO chip\n"); - goto fail_gpio; + return err; } err = gpiochip_add_pin_range(&data->gpio_chip, dev_name(data->dev), @@ -606,8 +606,6 @@ int wmt_pinctrl_probe(struct platform_device *pdev, fail_range: gpiochip_remove(&data->gpio_chip); -fail_gpio: - pinctrl_unregister(data->pctl_dev); return err; } @@ -616,7 +614,6 @@ int wmt_pinctrl_remove(struct platform_device *pdev) struct wmt_pinctrl_data *data = platform_get_drvdata(pdev); gpiochip_remove(&data->gpio_chip); - pinctrl_unregister(data->pctl_dev); return 0; } -- GitLab From 12ba40821ad0fd3c202efdb31b0be9b5872cef1c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3817/9938] pinctrl: adi2: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove the need of .remove callback. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-adi2.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c index ecb57635a37e..54569a7eac59 100644 --- a/drivers/pinctrl/pinctrl-adi2.c +++ b/drivers/pinctrl/pinctrl-adi2.c @@ -1058,7 +1058,8 @@ static int adi_pinctrl_probe(struct platform_device *pdev) adi_pinmux_desc.npins = pinctrl->soc->npins; /* Now register the pin controller and all pins it handles */ - pinctrl->pctl = pinctrl_register(&adi_pinmux_desc, &pdev->dev, pinctrl); + pinctrl->pctl = devm_pinctrl_register(&pdev->dev, &adi_pinmux_desc, + pinctrl); if (IS_ERR(pinctrl->pctl)) { dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n"); return PTR_ERR(pinctrl->pctl); @@ -1069,18 +1070,8 @@ static int adi_pinctrl_probe(struct platform_device *pdev) return 0; } -static int adi_pinctrl_remove(struct platform_device *pdev) -{ - struct adi_pinctrl *pinctrl = platform_get_drvdata(pdev); - - pinctrl_unregister(pinctrl->pctl); - - return 0; -} - static struct platform_driver adi_pinctrl_driver = { .probe = adi_pinctrl_probe, - .remove = adi_pinctrl_remove, .driver = { .name = DRIVER_NAME, }, -- GitLab From 251e22abde21833b3d29577e4d8c7aaccd650eee Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3818/9938] pinctrl: amd: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean error path. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-amd.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index b0e2ec0daed3..634b4d30eefb 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -783,8 +783,8 @@ static int amd_gpio_probe(struct platform_device *pdev) gpio_dev->ngroups = ARRAY_SIZE(kerncz_groups); amd_pinctrl_desc.name = dev_name(&pdev->dev); - gpio_dev->pctrl = pinctrl_register(&amd_pinctrl_desc, - &pdev->dev, gpio_dev); + gpio_dev->pctrl = devm_pinctrl_register(&pdev->dev, &amd_pinctrl_desc, + gpio_dev); if (IS_ERR(gpio_dev->pctrl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(gpio_dev->pctrl); @@ -792,7 +792,7 @@ static int amd_gpio_probe(struct platform_device *pdev) ret = gpiochip_add_data(&gpio_dev->gc, gpio_dev); if (ret) - goto out1; + return ret; ret = gpiochip_add_pin_range(&gpio_dev->gc, dev_name(&pdev->dev), 0, 0, TOTAL_NUMBER_OF_PINS); @@ -825,8 +825,6 @@ static int amd_gpio_probe(struct platform_device *pdev) out2: gpiochip_remove(&gpio_dev->gc); -out1: - pinctrl_unregister(gpio_dev->pctrl); return ret; } @@ -837,7 +835,6 @@ static int amd_gpio_remove(struct platform_device *pdev) gpio_dev = platform_get_drvdata(pdev); gpiochip_remove(&gpio_dev->gc); - pinctrl_unregister(gpio_dev->pctrl); return 0; } -- GitLab From 4d106c2282804e7247e97314d97f8ec5d2d66dab Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3819/9938] pinctrl: as3722: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean error path. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-as3722.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c index 1070bb9fa99d..4e9fe7854e8a 100644 --- a/drivers/pinctrl/pinctrl-as3722.c +++ b/drivers/pinctrl/pinctrl-as3722.c @@ -569,8 +569,8 @@ static int as3722_pinctrl_probe(struct platform_device *pdev) as3722_pinctrl_desc.name = dev_name(&pdev->dev); as3722_pinctrl_desc.pins = as3722_pins_desc; as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc); - as_pci->pctl = pinctrl_register(&as3722_pinctrl_desc, - &pdev->dev, as_pci); + as_pci->pctl = devm_pinctrl_register(&pdev->dev, &as3722_pinctrl_desc, + as_pci); if (IS_ERR(as_pci->pctl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(as_pci->pctl); @@ -582,7 +582,7 @@ static int as3722_pinctrl_probe(struct platform_device *pdev) ret = gpiochip_add_data(&as_pci->gpio_chip, as_pci); if (ret < 0) { dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret); - goto fail_chip_add; + return ret; } ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev), @@ -596,8 +596,6 @@ static int as3722_pinctrl_probe(struct platform_device *pdev) fail_range_add: gpiochip_remove(&as_pci->gpio_chip); -fail_chip_add: - pinctrl_unregister(as_pci->pctl); return ret; } @@ -606,7 +604,6 @@ static int as3722_pinctrl_remove(struct platform_device *pdev) struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev); gpiochip_remove(&as_pci->gpio_chip); - pinctrl_unregister(as_pci->pctl); return 0; } -- GitLab From 5d3fc884b2616d0b0b5db4dbd83e9f3bae5d6d3f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3820/9938] pinctrl: at91-pio4: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean error path. Signed-off-by: Laxman Dewangan Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-at91-pio4.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 629b6fefa8e0..6f77756ed9d9 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -1034,18 +1034,19 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) goto clk_prepare_enable_error; } - atmel_pioctrl->pinctrl_dev = pinctrl_register(&atmel_pinctrl_desc, - &pdev->dev, - atmel_pioctrl); - if (!atmel_pioctrl->pinctrl_dev) { + atmel_pioctrl->pinctrl_dev = devm_pinctrl_register(&pdev->dev, + &atmel_pinctrl_desc, + atmel_pioctrl); + if (IS_ERR(atmel_pioctrl->pinctrl_dev)) { + ret = PTR_ERR(atmel_pioctrl->pinctrl_dev); dev_err(dev, "pinctrl registration failed\n"); - goto pinctrl_register_error; + goto clk_unprep; } ret = gpiochip_add_data(atmel_pioctrl->gpio_chip, atmel_pioctrl); if (ret) { dev_err(dev, "failed to add gpiochip\n"); - goto gpiochip_add_error; + goto clk_unprep; } ret = gpiochip_add_pin_range(atmel_pioctrl->gpio_chip, dev_name(dev), @@ -1059,15 +1060,15 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) return 0; -clk_prepare_enable_error: - irq_domain_remove(atmel_pioctrl->irq_domain); -pinctrl_register_error: - clk_disable_unprepare(atmel_pioctrl->clk); -gpiochip_add_error: - pinctrl_unregister(atmel_pioctrl->pinctrl_dev); gpiochip_add_pin_range_error: gpiochip_remove(atmel_pioctrl->gpio_chip); +clk_unprep: + clk_disable_unprepare(atmel_pioctrl->clk); + +clk_prepare_enable_error: + irq_domain_remove(atmel_pioctrl->irq_domain); + return ret; } @@ -1077,7 +1078,6 @@ int atmel_pinctrl_remove(struct platform_device *pdev) irq_domain_remove(atmel_pioctrl->irq_domain); clk_disable_unprepare(atmel_pioctrl->clk); - pinctrl_unregister(atmel_pioctrl->pinctrl_dev); gpiochip_remove(atmel_pioctrl->gpio_chip); return 0; -- GitLab From 5c67425a46738b6193af28371af6d2ba42e8550c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 28 Feb 2016 14:32:19 +0530 Subject: [PATCH 3821/9938] pinctrl: at91: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove the need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Jean-Christophe Plagniol-Villard Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-at91.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 523b6b794d1f..f265ebe7b0a3 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1252,7 +1252,8 @@ static int at91_pinctrl_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, info); - info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info); + info->pctl = devm_pinctrl_register(&pdev->dev, &at91_pinctrl_desc, + info); if (IS_ERR(info->pctl)) { dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n"); @@ -1269,15 +1270,6 @@ static int at91_pinctrl_probe(struct platform_device *pdev) return 0; } -static int at91_pinctrl_remove(struct platform_device *pdev) -{ - struct at91_pinctrl *info = platform_get_drvdata(pdev); - - pinctrl_unregister(info->pctl); - - return 0; -} - static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct at91_gpio_chip *at91_gpio = gpiochip_get_data(chip); @@ -1821,7 +1813,6 @@ static struct platform_driver at91_pinctrl_driver = { .of_match_table = at91_pinctrl_of_match, }, .probe = at91_pinctrl_probe, - .remove = at91_pinctrl_remove, }; static struct platform_driver * const drivers[] = { -- GitLab From 8f91ed4780d4870c7e442ae37c402864e9370632 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 28 Feb 2016 14:33:21 +0530 Subject: [PATCH 3822/9938] pinctrl: digicolor: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and clean error path. Signed-off-by: Laxman Dewangan Cc: Baruch Siach Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-digicolor.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c index b347806215e7..30ee56427f56 100644 --- a/drivers/pinctrl/pinctrl-digicolor.c +++ b/drivers/pinctrl/pinctrl-digicolor.c @@ -280,7 +280,7 @@ static int dc_pinctrl_probe(struct platform_device *pdev) struct pinctrl_desc *pctl_desc; char *pin_names; int name_len = strlen("GP_xx") + 1; - int i, j, ret; + int i, j; pmap = devm_kzalloc(&pdev->dev, sizeof(*pmap), GFP_KERNEL); if (!pmap) @@ -326,26 +326,19 @@ static int dc_pinctrl_probe(struct platform_device *pdev) pmap->dev = &pdev->dev; - pmap->pctl = pinctrl_register(pctl_desc, &pdev->dev, pmap); + pmap->pctl = devm_pinctrl_register(&pdev->dev, pctl_desc, pmap); if (IS_ERR(pmap->pctl)) { dev_err(&pdev->dev, "pinctrl driver registration failed\n"); return PTR_ERR(pmap->pctl); } - ret = dc_gpiochip_add(pmap, pdev->dev.of_node); - if (ret < 0) { - pinctrl_unregister(pmap->pctl); - return ret; - } - - return 0; + return dc_gpiochip_add(pmap, pdev->dev.of_node); } static int dc_pinctrl_remove(struct platform_device *pdev) { struct dc_pinmap *pmap = platform_get_drvdata(pdev); - pinctrl_unregister(pmap->pctl); gpiochip_remove(&pmap->chip); return 0; -- GitLab From 280132d19841731964ac33a2d1b5742e1921f500 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3823/9938] pinctrl: lantiq: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Acked-by: John Crispin Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-lantiq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c index fc38a8540544..a4d647424600 100644 --- a/drivers/pinctrl/pinctrl-lantiq.c +++ b/drivers/pinctrl/pinctrl-lantiq.c @@ -336,7 +336,7 @@ int ltq_pinctrl_register(struct platform_device *pdev, desc->pmxops = <q_pmx_ops; info->dev = &pdev->dev; - info->pctrl = pinctrl_register(desc, &pdev->dev, info); + info->pctrl = devm_pinctrl_register(&pdev->dev, desc, info); if (IS_ERR(info->pctrl)) { dev_err(&pdev->dev, "failed to register LTQ pinmux driver\n"); return PTR_ERR(info->pctrl); -- GitLab From 19ba900bd28422e8a986e3fc2c5dda0a2054315a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3824/9938] pinctrl: lpc18xx: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Joachim Eastwood Acked-by: Joachim Eastwood Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-lpc18xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c index e897b63bd1bb..8a931c7ba2ff 100644 --- a/drivers/pinctrl/pinctrl-lpc18xx.c +++ b/drivers/pinctrl/pinctrl-lpc18xx.c @@ -1355,7 +1355,7 @@ static int lpc18xx_scu_probe(struct platform_device *pdev) platform_set_drvdata(pdev, scu); - scu->pctl = pinctrl_register(&lpc18xx_scu_desc, &pdev->dev, scu); + scu->pctl = devm_pinctrl_register(&pdev->dev, &lpc18xx_scu_desc, scu); if (IS_ERR(scu->pctl)) { dev_err(&pdev->dev, "Could not register pinctrl driver\n"); clk_disable_unprepare(scu->clk); @@ -1369,7 +1369,6 @@ static int lpc18xx_scu_remove(struct platform_device *pdev) { struct lpc18xx_scu_data *scu = platform_get_drvdata(pdev); - pinctrl_unregister(scu->pctl); clk_disable_unprepare(scu->clk); return 0; -- GitLab From 5039d27203aac887fa7bf0110e68aa6581c5a902 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3825/9938] pinctrl: palmas: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove the need of .remove callback. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-palmas.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/pinctrl-palmas.c b/drivers/pinctrl/pinctrl-palmas.c index 8f0163feda28..8edb3f8c72c8 100644 --- a/drivers/pinctrl/pinctrl-palmas.c +++ b/drivers/pinctrl/pinctrl-palmas.c @@ -1043,7 +1043,8 @@ static int palmas_pinctrl_probe(struct platform_device *pdev) palmas_pinctrl_desc.name = dev_name(&pdev->dev); palmas_pinctrl_desc.pins = palmas_pins_desc; palmas_pinctrl_desc.npins = ARRAY_SIZE(palmas_pins_desc); - pci->pctl = pinctrl_register(&palmas_pinctrl_desc, &pdev->dev, pci); + pci->pctl = devm_pinctrl_register(&pdev->dev, &palmas_pinctrl_desc, + pci); if (IS_ERR(pci->pctl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(pci->pctl); @@ -1051,21 +1052,12 @@ static int palmas_pinctrl_probe(struct platform_device *pdev) return 0; } -static int palmas_pinctrl_remove(struct platform_device *pdev) -{ - struct palmas_pctrl_chip_info *pci = platform_get_drvdata(pdev); - - pinctrl_unregister(pci->pctl); - return 0; -} - static struct platform_driver palmas_pinctrl_driver = { .driver = { .name = "palmas-pinctrl", .of_match_table = palmas_pinctrl_of_match, }, .probe = palmas_pinctrl_probe, - .remove = palmas_pinctrl_remove, }; module_platform_driver(palmas_pinctrl_driver); -- GitLab From a0f16cc30e47b878c746f601f415407255420cc5 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3826/9938] pinctrl: pic32: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Reviewed-by: Joshua Henderson Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-pic32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c index 87ee1c4e70a7..31ceb958b3fe 100644 --- a/drivers/pinctrl/pinctrl-pic32.c +++ b/drivers/pinctrl/pinctrl-pic32.c @@ -2194,7 +2194,8 @@ static int pic32_pinctrl_probe(struct platform_device *pdev) pic32_pinctrl_desc.custom_params = pic32_mpp_bindings; pic32_pinctrl_desc.num_custom_params = ARRAY_SIZE(pic32_mpp_bindings); - pctl->pctldev = pinctrl_register(&pic32_pinctrl_desc, &pdev->dev, pctl); + pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pic32_pinctrl_desc, + pctl); if (IS_ERR(pctl->pctldev)) { dev_err(&pdev->dev, "Failed to register pinctrl device\n"); return PTR_ERR(pctl->pctldev); -- GitLab From 082ec9063749bd58f557196249eb4b87120ee4a6 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3827/9938] pinctrl: pistachio: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-pistachio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c index 846fe91aa155..a532d8888559 100644 --- a/drivers/pinctrl/pinctrl-pistachio.c +++ b/drivers/pinctrl/pinctrl-pistachio.c @@ -1457,8 +1457,8 @@ static int pistachio_pinctrl_probe(struct platform_device *pdev) pistachio_pinctrl_desc.pins = pctl->pins; pistachio_pinctrl_desc.npins = pctl->npins; - pctl->pctldev = pinctrl_register(&pistachio_pinctrl_desc, &pdev->dev, - pctl); + pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pistachio_pinctrl_desc, + pctl); if (IS_ERR(pctl->pctldev)) { dev_err(&pdev->dev, "Failed to register pinctrl device\n"); return PTR_ERR(pctl->pctldev); -- GitLab From 0085a2b47b5f65cadc2d4146be30c6074fb21b0c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3828/9938] pinctrl: rockchip: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Heiko Stuebner Cc: linux-rockchip@lists.infradead.org Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-rockchip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 0b3fd02c069f..596b869d6c7d 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -1646,7 +1646,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, if (ret) return ret; - info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info); + info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info); if (IS_ERR(info->pctl_dev)) { dev_err(&pdev->dev, "could not register pinctrl driver\n"); return PTR_ERR(info->pctl_dev); -- GitLab From e8e2cb234f55355a75a48eab6ef4a26dfe05558d Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3829/9938] pinctrl: st: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Cc: Srinivas Kandagatla Cc: Maxime Coquelin Cc: Patrice Chotard Cc: kernel@stlinux.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index cab66c64149f..d0ba968af5bb 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -1724,7 +1724,7 @@ static int st_pctl_probe(struct platform_device *pdev) pctl_desc->confops = &st_confops; pctl_desc->name = dev_name(&pdev->dev); - info->pctl = pinctrl_register(pctl_desc, &pdev->dev, info); + info->pctl = devm_pinctrl_register(&pdev->dev, pctl_desc, info); if (IS_ERR(info->pctl)) { dev_err(&pdev->dev, "Failed pinctrl registration\n"); return PTR_ERR(info->pctl); -- GitLab From c3a6d9e0a37df77079f55c48901487fa9e731647 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3830/9938] pinctrl: tb10x: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-tb10x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c index 620af57f10ad..edfba506e958 100644 --- a/drivers/pinctrl/pinctrl-tb10x.c +++ b/drivers/pinctrl/pinctrl-tb10x.c @@ -806,7 +806,7 @@ static int tb10x_pinctrl_probe(struct platform_device *pdev) } } - state->pctl = pinctrl_register(&tb10x_pindesc, dev, state); + state->pctl = devm_pinctrl_register(dev, &tb10x_pindesc, state); if (IS_ERR(state->pctl)) { dev_err(dev, "could not register TB10x pin driver\n"); ret = PTR_ERR(state->pctl); @@ -824,7 +824,6 @@ static int tb10x_pinctrl_remove(struct platform_device *pdev) { struct tb10x_pinctrl *state = platform_get_drvdata(pdev); - pinctrl_unregister(state->pctl); mutex_destroy(&state->mutex); return 0; -- GitLab From 00b881b07dee87746dc1363ed9fee96f5b2af8d9 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3831/9938] pinctrl: tz1090-pdc: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove the need of .remove callback. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-tz1090-pdc.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/pinctrl/pinctrl-tz1090-pdc.c b/drivers/pinctrl/pinctrl-tz1090-pdc.c index b89ad3c0c731..e70e36283b3b 100644 --- a/drivers/pinctrl/pinctrl-tz1090-pdc.c +++ b/drivers/pinctrl/pinctrl-tz1090-pdc.c @@ -947,7 +947,8 @@ static int tz1090_pdc_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(pmx->regs)) return PTR_ERR(pmx->regs); - pmx->pctl = pinctrl_register(&tz1090_pdc_pinctrl_desc, &pdev->dev, pmx); + pmx->pctl = devm_pinctrl_register(&pdev->dev, &tz1090_pdc_pinctrl_desc, + pmx); if (IS_ERR(pmx->pctl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(pmx->pctl); @@ -960,15 +961,6 @@ static int tz1090_pdc_pinctrl_probe(struct platform_device *pdev) return 0; } -static int tz1090_pdc_pinctrl_remove(struct platform_device *pdev) -{ - struct tz1090_pdc_pmx *pmx = platform_get_drvdata(pdev); - - pinctrl_unregister(pmx->pctl); - - return 0; -} - static const struct of_device_id tz1090_pdc_pinctrl_of_match[] = { { .compatible = "img,tz1090-pdc-pinctrl", }, { }, @@ -980,7 +972,6 @@ static struct platform_driver tz1090_pdc_pinctrl_driver = { .of_match_table = tz1090_pdc_pinctrl_of_match, }, .probe = tz1090_pdc_pinctrl_probe, - .remove = tz1090_pdc_pinctrl_remove, }; static int __init tz1090_pdc_pinctrl_init(void) -- GitLab From 265559f7ca7b8b4518c31ece4236e75e32d00bec Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3832/9938] pinctrl: tz1090 Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove the need of .remove callback. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-tz1090.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/pinctrl/pinctrl-tz1090.c b/drivers/pinctrl/pinctrl-tz1090.c index 5425299d759d..04cbe530bf29 100644 --- a/drivers/pinctrl/pinctrl-tz1090.c +++ b/drivers/pinctrl/pinctrl-tz1090.c @@ -1962,7 +1962,8 @@ static int tz1090_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(pmx->regs)) return PTR_ERR(pmx->regs); - pmx->pctl = pinctrl_register(&tz1090_pinctrl_desc, &pdev->dev, pmx); + pmx->pctl = devm_pinctrl_register(&pdev->dev, &tz1090_pinctrl_desc, + pmx); if (IS_ERR(pmx->pctl)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); return PTR_ERR(pmx->pctl); @@ -1975,15 +1976,6 @@ static int tz1090_pinctrl_probe(struct platform_device *pdev) return 0; } -static int tz1090_pinctrl_remove(struct platform_device *pdev) -{ - struct tz1090_pmx *pmx = platform_get_drvdata(pdev); - - pinctrl_unregister(pmx->pctl); - - return 0; -} - static const struct of_device_id tz1090_pinctrl_of_match[] = { { .compatible = "img,tz1090-pinctrl", }, { }, @@ -1995,7 +1987,6 @@ static struct platform_driver tz1090_pinctrl_driver = { .of_match_table = tz1090_pinctrl_of_match, }, .probe = tz1090_pinctrl_probe, - .remove = tz1090_pinctrl_remove, }; static int __init tz1090_pinctrl_init(void) -- GitLab From 6ac47fd25a0b83fcea203308a319cb6e98091af1 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3833/9938] pinctrl: u300: Use devm_pinctrl_register() for pinctrl registration Use devm_pinctrl_register() for pin control registration and remove the need of .remove callback. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-u300.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c index c076021f37d2..d1af908a7060 100644 --- a/drivers/pinctrl/pinctrl-u300.c +++ b/drivers/pinctrl/pinctrl-u300.c @@ -1067,7 +1067,7 @@ static int u300_pmx_probe(struct platform_device *pdev) if (IS_ERR(upmx->virtbase)) return PTR_ERR(upmx->virtbase); - upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx); + upmx->pctl = devm_pinctrl_register(&pdev->dev, &u300_pmx_desc, upmx); if (IS_ERR(upmx->pctl)) { dev_err(&pdev->dev, "could not register U300 pinmux driver\n"); return PTR_ERR(upmx->pctl); @@ -1080,15 +1080,6 @@ static int u300_pmx_probe(struct platform_device *pdev) return 0; } -static int u300_pmx_remove(struct platform_device *pdev) -{ - struct u300_pmx *upmx = platform_get_drvdata(pdev); - - pinctrl_unregister(upmx->pctl); - - return 0; -} - static const struct of_device_id u300_pinctrl_match[] = { { .compatible = "stericsson,pinctrl-u300" }, {}, @@ -1101,7 +1092,6 @@ static struct platform_driver u300_pmx_driver = { .of_match_table = u300_pinctrl_match, }, .probe = u300_pmx_probe, - .remove = u300_pmx_remove, }; static int __init u300_pmx_init(void) -- GitLab From 3024f920eb5f6e60453d035f26ec963c7126f517 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 24 Feb 2016 14:44:07 +0530 Subject: [PATCH 3834/9938] pinctrl: zynq: Use devm_pinctrl_register() for pinctrl registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use devm_pinctrl_register() for pin control registration and remove the need of .remove callback. Signed-off-by: Laxman Dewangan Cc: Michal Simek Cc: Sören Brinkmann Cc: linux-gpio@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Acked-by: Sören Brinkmann Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 2 +- drivers/pinctrl/pinctrl-zynq.c | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 21df52e8192a..98d2a1bb44cb 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1883,7 +1883,7 @@ static int devm_pinctrl_dev_match(struct device *dev, void *res, void *data) { struct pctldev **r = res; - if (WARN_ON(!r || !*r) + if (WARN_ON(!r || !*r)) return 0; return *r == data; diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c index 3f1b55f675a5..8fdc60c5aeaf 100644 --- a/drivers/pinctrl/pinctrl-zynq.c +++ b/drivers/pinctrl/pinctrl-zynq.c @@ -1195,7 +1195,7 @@ static int zynq_pinctrl_probe(struct platform_device *pdev) pctrl->funcs = zynq_pmux_functions; pctrl->nfuncs = ARRAY_SIZE(zynq_pmux_functions); - pctrl->pctrl = pinctrl_register(&zynq_desc, &pdev->dev, pctrl); + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &zynq_desc, pctrl); if (IS_ERR(pctrl->pctrl)) return PTR_ERR(pctrl->pctrl); @@ -1206,15 +1206,6 @@ static int zynq_pinctrl_probe(struct platform_device *pdev) return 0; } -static int zynq_pinctrl_remove(struct platform_device *pdev) -{ - struct zynq_pinctrl *pctrl = platform_get_drvdata(pdev); - - pinctrl_unregister(pctrl->pctrl); - - return 0; -} - static const struct of_device_id zynq_pinctrl_of_match[] = { { .compatible = "xlnx,pinctrl-zynq" }, { } @@ -1227,7 +1218,6 @@ static struct platform_driver zynq_pinctrl_driver = { .of_match_table = zynq_pinctrl_of_match, }, .probe = zynq_pinctrl_probe, - .remove = zynq_pinctrl_remove, }; static int __init zynq_pinctrl_init(void) -- GitLab From 3f6813b9a5e0aaec162a10037c203771a1b2c110 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 1 Apr 2016 15:42:15 +0200 Subject: [PATCH 3835/9938] s390/fpu: allocate 'struct fpu' with the task_struct Analog to git commit 0c8c0f03e3a292e031596484275c14cf39c0ab7a "x86/fpu, sched: Dynamically allocate 'struct fpu'" move the struct fpu to the end of the struct thread_struct, set CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT and add the setup_task_size() function to calculate the correct size fo the task struct. For the performance_defconfig this increases the size of struct task_struct from 7424 bytes to 7936 bytes (MACHINE_HAS_VX==1) or 7552 bytes (MACHINE_HAS_VX==0). The dynamic allocation of the struct fpu is removed. The slab cache uses an 8KB block for the task struct in all cases, there is enough room for the struct fpu. For MACHINE_HAS_VX==1 each task now needs 512 bytes less memory. Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + arch/s390/include/asm/fpu/types.h | 10 ++++++---- arch/s390/include/asm/processor.h | 9 ++++++--- arch/s390/kernel/process.c | 23 ++--------------------- arch/s390/kernel/setup.c | 17 +++++++++++++++++ 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index bf24ab188921..212f34b2a58e 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -107,6 +107,7 @@ config S390 select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_WANTS_DYNAMIC_TASK_STRUCT select ARCH_WANTS_PROT_NUMA_PROT_NONE select ARCH_WANT_IPC_PARSE_VERSION select BUILDTIME_EXTABLE_SORT diff --git a/arch/s390/include/asm/fpu/types.h b/arch/s390/include/asm/fpu/types.h index 14a8b0c14f87..fe937c9b6471 100644 --- a/arch/s390/include/asm/fpu/types.h +++ b/arch/s390/include/asm/fpu/types.h @@ -11,11 +11,13 @@ #include struct fpu { - __u32 fpc; /* Floating-point control */ + __u32 fpc; /* Floating-point control */ + void *regs; /* Pointer to the current save area */ union { - void *regs; - freg_t *fprs; /* Floating-point register save area */ - __vector128 *vxrs; /* Vector register save area */ + /* Floating-point register save area */ + freg_t fprs[__NUM_FPRS]; + /* Vector register save area */ + __vector128 vxrs[__NUM_VXRS]; }; }; diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index d6fd22ea270d..332f4f7dc8d3 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -105,7 +105,6 @@ typedef struct { * Thread structure */ struct thread_struct { - struct fpu fpu; /* FP and VX register save area */ unsigned int acrs[NUM_ACRS]; unsigned long ksp; /* kernel stack pointer */ mm_segment_t mm_segment; @@ -120,6 +119,11 @@ struct thread_struct { /* cpu runtime instrumentation */ struct runtime_instr_cb *ri_cb; unsigned char trap_tdb[256]; /* Transaction abort diagnose block */ + /* + * Warning: 'fpu' is dynamically-sized. It *MUST* be at + * the end. + */ + struct fpu fpu; /* FP and VX register save area */ }; /* Flag to disable transactions. */ @@ -155,10 +159,9 @@ struct stack_frame { #define ARCH_MIN_TASKALIGN 8 -extern __vector128 init_task_fpu_regs[__NUM_VXRS]; #define INIT_THREAD { \ .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \ - .fpu.regs = (void *)&init_task_fpu_regs, \ + .fpu.regs = (void *) init_task.thread.fpu.fprs, \ } /* diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 2bba7df4ac51..adb346b70166 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -37,9 +37,6 @@ asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); -/* FPU save area for the init task */ -__vector128 init_task_fpu_regs[__NUM_VXRS] __init_task_data; - /* * Return saved PC of a blocked thread. used in kernel/sched. * resume in entry.S does not create a new stack frame, it @@ -85,35 +82,19 @@ void release_thread(struct task_struct *dead_task) void arch_release_task_struct(struct task_struct *tsk) { - /* Free either the floating-point or the vector register save area */ - kfree(tsk->thread.fpu.regs); } int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { - size_t fpu_regs_size; - - *dst = *src; - - /* - * If the vector extension is available, it is enabled for all tasks, - * and, thus, the FPU register save area must be allocated accordingly. - */ - fpu_regs_size = MACHINE_HAS_VX ? sizeof(__vector128) * __NUM_VXRS - : sizeof(freg_t) * __NUM_FPRS; - dst->thread.fpu.regs = kzalloc(fpu_regs_size, GFP_KERNEL|__GFP_REPEAT); - if (!dst->thread.fpu.regs) - return -ENOMEM; - /* * Save the floating-point or vector register state of the current * task and set the CIF_FPU flag to lazy restore the FPU register * state when returning to user space. */ save_fpu_regs(); - dst->thread.fpu.fpc = current->thread.fpu.fpc; - memcpy(dst->thread.fpu.regs, current->thread.fpu.regs, fpu_regs_size); + memcpy(dst, src, arch_task_struct_size); + dst->thread.fpu.regs = dst->thread.fpu.fprs; return 0; } diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index d3f9688f26b5..f31939147ccd 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -808,6 +808,22 @@ static void __init setup_randomness(void) free_page((unsigned long) vmms); } +/* + * Find the correct size for the task_struct. This depends on + * the size of the struct fpu at the end of the thread_struct + * which is embedded in the task_struct. + */ +static void __init setup_task_size(void) +{ + int task_size = sizeof(struct task_struct); + + if (!MACHINE_HAS_VX) { + task_size -= sizeof(__vector128) * __NUM_VXRS; + task_size += sizeof(freg_t) * __NUM_FPRS; + } + arch_task_struct_size = task_size; +} + /* * Setup function called from init/main.c just after the banner * was printed. @@ -846,6 +862,7 @@ void __init setup_arch(char **cmdline_p) os_info_init(); setup_ipl(); + setup_task_size(); /* Do some memory reservations *before* memory is added to memblock */ reserve_memory_end(); -- GitLab From 99d00a2bd3c4f24ef90960a563f6f190e81e4ed3 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 18 Apr 2016 09:52:05 +0200 Subject: [PATCH 3836/9938] s390/sclp: avoid compile warning in sclp_pci_report Fix the initialization of a local variable to remove this warning: All warnings (new ones prefixed by >>): drivers/s390/char/sclp_pci.c: In function 'sclp_pci_report': >> drivers/s390/char/sclp_pci.c:127:9: warning: missing braces around initializer [-Wmissing-braces] struct sclp_req req = {0}; ^ drivers/s390/char/sclp_pci.c:127:9: warning: (near initialization for 'req.list') [-Wmissing-braces] Fixes: 12283a4035691697 "s390/sclp: add error notification command" Reported-by: kbuild test robot Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c index 0c8973c45b48..4dbb3dfd4bc7 100644 --- a/drivers/s390/char/sclp_pci.c +++ b/drivers/s390/char/sclp_pci.c @@ -124,7 +124,7 @@ int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid) { DECLARE_COMPLETION_ONSTACK(completion); struct err_notify_sccb *sccb; - struct sclp_req req = {0}; + struct sclp_req req; int ret; ret = sclp_pci_check_report(report); @@ -147,6 +147,7 @@ int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid) goto out_unregister; } + memset(&req, 0, sizeof(req)); req.callback_data = &completion; req.callback = sclp_pci_callback; req.command = SCLP_CMDW_WRITE_EVENT_DATA; -- GitLab From 7072276e6c0eed95b08e8f8d07456112970eac06 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 18 Apr 2016 17:10:16 +0200 Subject: [PATCH 3837/9938] s390/Kconfig: make z196 the default processor type The current default processor type is z900. The BPF jit compiler depends on PACK_STACK && HAVE_MARCH_Z196_FEATURES. To have the BPF jit code included in compiles with 'make allmodconfig' set the default processor type to z196. Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 212f34b2a58e..e1d3ad4f58a6 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -211,7 +211,7 @@ config HAVE_MARCH_Z13_FEATURES choice prompt "Processor type" - default MARCH_Z900 + default MARCH_Z196 config MARCH_Z900 bool "IBM zSeries model z800 and z900" -- GitLab From 20d2cecbb7b9c35235c97f0dfa520525c28f8841 Mon Sep 17 00:00:00 2001 From: Jeremy McDermond Date: Wed, 20 Apr 2016 11:39:11 -0700 Subject: [PATCH 3838/9938] ASoC: tlv320aic32x4: Implement resistors on input pins The input pins of the aic3204 have resistors inline with them. The current code assumes that you want a 10k resistor inline with your inputs and implements it as a simple switch. This patch creates an enum for each pin and allows you to switch between not connected, 10k, 20k and 40k ohm values. This more closely models the acutal aic3204 part. These pin settings are documented in TI's SLAA557 pages 135 and 136 (http://www.ti.com/lit/ml/slaa557/slaa557.pdf). Signed-off-by: Jeremy McDermond Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 2f8480c93b3c..621f4210cd27 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -183,16 +183,34 @@ static const struct snd_kcontrol_new lor_output_mixer_controls[] = { SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0), }; +static const char * const resistor_text[] = { + "Off", "10 kOhm", "20 kOhm", "40 kOhm", +}; + +static SOC_ENUM_SINGLE_DECL(in1l_lpga_p_enum, AIC32X4_LMICPGAPIN, 6, + resistor_text); +static SOC_ENUM_SINGLE_DECL(in2l_lpga_p_enum, AIC32X4_LMICPGAPIN, 4, + resistor_text); +static SOC_ENUM_SINGLE_DECL(in3l_lpga_p_enum, AIC32X4_LMICPGAPIN, 2, + resistor_text); + static const struct snd_kcontrol_new left_input_mixer_controls[] = { - SOC_DAPM_SINGLE("IN1_L P Switch", AIC32X4_LMICPGAPIN, 6, 1, 0), - SOC_DAPM_SINGLE("IN2_L P Switch", AIC32X4_LMICPGAPIN, 4, 1, 0), - SOC_DAPM_SINGLE("IN3_L P Switch", AIC32X4_LMICPGAPIN, 2, 1, 0), + SOC_DAPM_ENUM("IN1_L P Switch", in1l_lpga_p_enum), + SOC_DAPM_ENUM("IN2_L P Switch", in2l_lpga_p_enum), + SOC_DAPM_ENUM("IN3_L P Switch", in3l_lpga_p_enum), }; +static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, + resistor_text); +static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, + resistor_text); +static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, + resistor_text); + static const struct snd_kcontrol_new right_input_mixer_controls[] = { - SOC_DAPM_SINGLE("IN1_R P Switch", AIC32X4_RMICPGAPIN, 6, 1, 0), - SOC_DAPM_SINGLE("IN2_R P Switch", AIC32X4_RMICPGAPIN, 4, 1, 0), - SOC_DAPM_SINGLE("IN3_R P Switch", AIC32X4_RMICPGAPIN, 2, 1, 0), + SOC_DAPM_ENUM("IN1_R P Switch", in1r_rpga_p_enum), + SOC_DAPM_ENUM("IN2_R P Switch", in2r_rpga_p_enum), + SOC_DAPM_ENUM("IN3_R P Switch", in3r_rpga_p_enum), }; static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { -- GitLab From 13a06ed55dba0ae3f983ef3c4ea70fc42066e1b5 Mon Sep 17 00:00:00 2001 From: Jeremy McDermond Date: Wed, 20 Apr 2016 11:39:12 -0700 Subject: [PATCH 3839/9938] ASoC: tlv320aic32x4: Add additional input pins The input mixers support routing the IN1_R pin to the Left PGA and the IN2_L pin to the Right PGA. This patch allows for those routings. Signed-off-by: Jeremy McDermond Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 621f4210cd27..0eb8acc8cd66 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -193,11 +193,14 @@ static SOC_ENUM_SINGLE_DECL(in2l_lpga_p_enum, AIC32X4_LMICPGAPIN, 4, resistor_text); static SOC_ENUM_SINGLE_DECL(in3l_lpga_p_enum, AIC32X4_LMICPGAPIN, 2, resistor_text); +static SOC_ENUM_SINGLE_DECL(in1r_lpga_p_enum, AIC32X4_LMICPGAPIN, 0, + resistor_text); static const struct snd_kcontrol_new left_input_mixer_controls[] = { SOC_DAPM_ENUM("IN1_L P Switch", in1l_lpga_p_enum), SOC_DAPM_ENUM("IN2_L P Switch", in2l_lpga_p_enum), SOC_DAPM_ENUM("IN3_L P Switch", in3l_lpga_p_enum), + SOC_DAPM_ENUM("IN1_R P Switch", in1r_lpga_p_enum), }; static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, @@ -206,11 +209,14 @@ static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text); static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text); +static SOC_ENUM_SINGLE_DECL(in2l_rpga_p_enum, AIC32X4_RMICPGAPIN, 0, + resistor_text); static const struct snd_kcontrol_new right_input_mixer_controls[] = { SOC_DAPM_ENUM("IN1_R P Switch", in1r_rpga_p_enum), SOC_DAPM_ENUM("IN2_R P Switch", in2r_rpga_p_enum), SOC_DAPM_ENUM("IN3_R P Switch", in3r_rpga_p_enum), + SOC_DAPM_ENUM("IN2_L P Switch", in2l_rpga_p_enum), }; static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { @@ -285,6 +291,7 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { {"Left Input Mixer", "IN1_L P Switch", "IN1_L"}, {"Left Input Mixer", "IN2_L P Switch", "IN2_L"}, {"Left Input Mixer", "IN3_L P Switch", "IN3_L"}, + {"Left Input Mixer", "IN1_R P Switch", "IN1_R"}, {"Left ADC", NULL, "Left Input Mixer"}, @@ -292,6 +299,7 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { {"Right Input Mixer", "IN1_R P Switch", "IN1_R"}, {"Right Input Mixer", "IN2_R P Switch", "IN2_R"}, {"Right Input Mixer", "IN3_R P Switch", "IN3_R"}, + {"Right Input Mixer", "IN2_L P Switch", "IN2_L"}, {"Right ADC", NULL, "Right Input Mixer"}, }; -- GitLab From 06d05463ee337e85e42c6073b6f2f46fbfb05b96 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Apr 2016 23:59:31 +0200 Subject: [PATCH 3840/9938] rtl8xxxu: hide unused tables The references to some arrays in the rtl8xxxu driver were moved inside of an #ifdef, but the symbols remain outside, resulting in build warnings: rtl8xxxu/rtl8xxxu.c:1506:33: error: 'rtl8188ru_radioa_1t_highpa_table' defined but not used rtl8xxxu/rtl8xxxu.c:1431:33: error: 'rtl8192cu_radioa_1t_init_table' defined but not used rtl8xxxu/rtl8xxxu.c:1407:33: error: 'rtl8192cu_radiob_2t_init_table' defined but not used rtl8xxxu/rtl8xxxu.c:1332:33: error: 'rtl8192cu_radioa_2t_init_table' defined but not used rtl8xxxu/rtl8xxxu.c:239:35: error: 'rtl8192c_power_base' defined but not used rtl8xxxu/rtl8xxxu.c:217:35: error: 'rtl8188r_power_base' defined but not used This adds an extra #ifdef around them to shut up the warnings. Signed-off-by: Arnd Bergmann Fixes: 2fc0b8e5a17d ("rtl8xxxu: Add TX power base values for gen1 parts") Fixes: 4062b8ffec36 ("rtl8xxxu: Move PHY RF init into device specific functions") Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 928ca56f751c..0ba84b5fe0d6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -214,6 +214,7 @@ static struct rtl8xxxu_reg8val rtl8192e_mac_init_table[] = { {0xffff, 0xff}, }; +#ifdef CONFIG_RTL8XXXU_UNTESTED static struct rtl8xxxu_power_base rtl8188r_power_base = { .reg_0e00 = 0x06080808, .reg_0e04 = 0x00040406, @@ -257,6 +258,7 @@ static struct rtl8xxxu_power_base rtl8192c_power_base = { .reg_084c = 0x0b0c0d0e, .reg_0868 = 0x01030509, }; +#endif static struct rtl8xxxu_power_base rtl8723a_power_base = { .reg_0e00 = 0x0a0c0c0c, @@ -1329,6 +1331,7 @@ static struct rtl8xxxu_rfregval rtl8723bu_radioa_1t_init_table[] = { {0xff, 0xffffffff} }; +#ifdef CONFIG_RTL8XXXU_UNTESTED static struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = { {0x00, 0x00030159}, {0x01, 0x00031284}, {0x02, 0x00098000}, {0x03, 0x00018c63}, @@ -1577,6 +1580,7 @@ static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = { {0x00, 0x00030159}, {0xff, 0xffffffff} }; +#endif static struct rtl8xxxu_rfregval rtl8192eu_radioa_init_table[] = { {0x7f, 0x00000082}, {0x81, 0x0003fc00}, -- GitLab From a563f7598198b8389e00451ef6f3f1c12efbfb99 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 4 Apr 2016 11:43:15 +0100 Subject: [PATCH 3841/9938] arm64: Reuse TCR field definitions for EL1 and EL2 TCR_EL1, TCR_EL2 and VTCR_EL2, all share some field positions (TG0, ORGN0, IRGN0 and SH0) and their corresponding value definitions. This patch makes the TCR_EL1 definitions reusable and uses them for TCR_EL2 and VTCR_EL2 fields. This also fixes a bug where we assume TG0 in {V}TCR_EL2 is 1bit field. Cc: Catalin Marinas Cc: Mark Rutland Acked-by: Marc Zyngier Acked-by: Will Deacon Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/kvm_arm.h | 48 ++++++++-------- arch/arm64/include/asm/pgtable-hwdef.h | 80 ++++++++++++++++++++------ 2 files changed, 88 insertions(+), 40 deletions(-) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 3f29887995bc..a46b39f62426 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -96,32 +96,34 @@ SCTLR_EL2_SA | SCTLR_EL2_I) /* TCR_EL2 Registers bits */ -#define TCR_EL2_RES1 ((1 << 31) | (1 << 23)) -#define TCR_EL2_TBI (1 << 20) -#define TCR_EL2_PS (7 << 16) -#define TCR_EL2_PS_40B (2 << 16) -#define TCR_EL2_TG0 (1 << 14) -#define TCR_EL2_SH0 (3 << 12) -#define TCR_EL2_ORGN0 (3 << 10) -#define TCR_EL2_IRGN0 (3 << 8) -#define TCR_EL2_T0SZ 0x3f -#define TCR_EL2_MASK (TCR_EL2_TG0 | TCR_EL2_SH0 | \ - TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ) +#define TCR_EL2_RES1 ((1 << 31) | (1 << 23)) +#define TCR_EL2_TBI (1 << 20) +#define TCR_EL2_PS_SHIFT 16 +#define TCR_EL2_PS_MASK (7 << TCR_EL2_PS_SHIFT) +#define TCR_EL2_PS_40B (2 << TCR_EL2_PS_SHIFT) +#define TCR_EL2_TG0_MASK TCR_TG0_MASK +#define TCR_EL2_SH0_MASK TCR_SH0_MASK +#define TCR_EL2_ORGN0_MASK TCR_ORGN0_MASK +#define TCR_EL2_IRGN0_MASK TCR_IRGN0_MASK +#define TCR_EL2_T0SZ_MASK 0x3f +#define TCR_EL2_MASK (TCR_EL2_TG0_MASK | TCR_EL2_SH0_MASK | \ + TCR_EL2_ORGN0_MASK | TCR_EL2_IRGN0_MASK | TCR_EL2_T0SZ_MASK) /* VTCR_EL2 Registers bits */ #define VTCR_EL2_RES1 (1 << 31) -#define VTCR_EL2_PS_MASK (7 << 16) -#define VTCR_EL2_TG0_MASK (1 << 14) -#define VTCR_EL2_TG0_4K (0 << 14) -#define VTCR_EL2_TG0_64K (1 << 14) -#define VTCR_EL2_SH0_MASK (3 << 12) -#define VTCR_EL2_SH0_INNER (3 << 12) -#define VTCR_EL2_ORGN0_MASK (3 << 10) -#define VTCR_EL2_ORGN0_WBWA (1 << 10) -#define VTCR_EL2_IRGN0_MASK (3 << 8) -#define VTCR_EL2_IRGN0_WBWA (1 << 8) -#define VTCR_EL2_SL0_MASK (3 << 6) -#define VTCR_EL2_SL0_LVL1 (1 << 6) +#define VTCR_EL2_PS_MASK TCR_EL2_PS_MASK +#define VTCR_EL2_TG0_MASK TCR_TG0_MASK +#define VTCR_EL2_TG0_4K TCR_TG0_4K +#define VTCR_EL2_TG0_64K TCR_TG0_64K +#define VTCR_EL2_SH0_MASK TCR_SH0_MASK +#define VTCR_EL2_SH0_INNER TCR_SH0_INNER +#define VTCR_EL2_ORGN0_MASK TCR_ORGN0_MASK +#define VTCR_EL2_ORGN0_WBWA TCR_ORGN0_WBWA +#define VTCR_EL2_IRGN0_MASK TCR_IRGN0_MASK +#define VTCR_EL2_IRGN0_WBWA TCR_IRGN0_WBWA +#define VTCR_EL2_SL0_SHIFT 6 +#define VTCR_EL2_SL0_MASK (3 << VTCR_EL2_SL0_SHIFT) +#define VTCR_EL2_SL0_LVL1 (1 << VTCR_EL2_SL0_SHIFT) #define VTCR_EL2_T0SZ_MASK 0x3f #define VTCR_EL2_T0SZ_40B 24 #define VTCR_EL2_VS_SHIFT 19 diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index 5c25b831273d..936f1732727c 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -208,23 +208,69 @@ #define TCR_T1SZ(x) ((UL(64) - (x)) << TCR_T1SZ_OFFSET) #define TCR_TxSZ(x) (TCR_T0SZ(x) | TCR_T1SZ(x)) #define TCR_TxSZ_WIDTH 6 -#define TCR_IRGN_NC ((UL(0) << 8) | (UL(0) << 24)) -#define TCR_IRGN_WBWA ((UL(1) << 8) | (UL(1) << 24)) -#define TCR_IRGN_WT ((UL(2) << 8) | (UL(2) << 24)) -#define TCR_IRGN_WBnWA ((UL(3) << 8) | (UL(3) << 24)) -#define TCR_IRGN_MASK ((UL(3) << 8) | (UL(3) << 24)) -#define TCR_ORGN_NC ((UL(0) << 10) | (UL(0) << 26)) -#define TCR_ORGN_WBWA ((UL(1) << 10) | (UL(1) << 26)) -#define TCR_ORGN_WT ((UL(2) << 10) | (UL(2) << 26)) -#define TCR_ORGN_WBnWA ((UL(3) << 10) | (UL(3) << 26)) -#define TCR_ORGN_MASK ((UL(3) << 10) | (UL(3) << 26)) -#define TCR_SHARED ((UL(3) << 12) | (UL(3) << 28)) -#define TCR_TG0_4K (UL(0) << 14) -#define TCR_TG0_64K (UL(1) << 14) -#define TCR_TG0_16K (UL(2) << 14) -#define TCR_TG1_16K (UL(1) << 30) -#define TCR_TG1_4K (UL(2) << 30) -#define TCR_TG1_64K (UL(3) << 30) + +#define TCR_IRGN0_SHIFT 8 +#define TCR_IRGN0_MASK (UL(3) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NC (UL(0) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_WBWA (UL(1) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_WT (UL(2) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_WBnWA (UL(3) << TCR_IRGN0_SHIFT) + +#define TCR_IRGN1_SHIFT 24 +#define TCR_IRGN1_MASK (UL(3) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_NC (UL(0) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_WBWA (UL(1) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_WT (UL(2) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_WBnWA (UL(3) << TCR_IRGN1_SHIFT) + +#define TCR_IRGN_NC (TCR_IRGN0_NC | TCR_IRGN1_NC) +#define TCR_IRGN_WBWA (TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) +#define TCR_IRGN_WT (TCR_IRGN0_WT | TCR_IRGN1_WT) +#define TCR_IRGN_WBnWA (TCR_IRGN0_WBnWA | TCR_IRGN1_WBnWA) +#define TCR_IRGN_MASK (TCR_IRGN0_MASK | TCR_IRGN1_MASK) + + +#define TCR_ORGN0_SHIFT 10 +#define TCR_ORGN0_MASK (UL(3) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NC (UL(0) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_WBWA (UL(1) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_WT (UL(2) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_WBnWA (UL(3) << TCR_ORGN0_SHIFT) + +#define TCR_ORGN1_SHIFT 26 +#define TCR_ORGN1_MASK (UL(3) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_NC (UL(0) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_WBWA (UL(1) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_WT (UL(2) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_WBnWA (UL(3) << TCR_ORGN1_SHIFT) + +#define TCR_ORGN_NC (TCR_ORGN0_NC | TCR_ORGN1_NC) +#define TCR_ORGN_WBWA (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA) +#define TCR_ORGN_WT (TCR_ORGN0_WT | TCR_ORGN1_WT) +#define TCR_ORGN_WBnWA (TCR_ORGN0_WBnWA | TCR_ORGN1_WBnWA) +#define TCR_ORGN_MASK (TCR_ORGN0_MASK | TCR_ORGN1_MASK) + +#define TCR_SH0_SHIFT 12 +#define TCR_SH0_MASK (UL(3) << TCR_SH0_SHIFT) +#define TCR_SH0_INNER (UL(3) << TCR_SH0_SHIFT) + +#define TCR_SH1_SHIFT 28 +#define TCR_SH1_MASK (UL(3) << TCR_SH1_SHIFT) +#define TCR_SH1_INNER (UL(3) << TCR_SH1_SHIFT) +#define TCR_SHARED (TCR_SH0_INNER | TCR_SH1_INNER) + +#define TCR_TG0_SHIFT 14 +#define TCR_TG0_MASK (UL(3) << TCR_TG0_SHIFT) +#define TCR_TG0_4K (UL(0) << TCR_TG0_SHIFT) +#define TCR_TG0_64K (UL(1) << TCR_TG0_SHIFT) +#define TCR_TG0_16K (UL(2) << TCR_TG0_SHIFT) + +#define TCR_TG1_SHIFT 30 +#define TCR_TG1_MASK (UL(3) << TCR_TG1_SHIFT) +#define TCR_TG1_16K (UL(1) << TCR_TG1_SHIFT) +#define TCR_TG1_4K (UL(2) << TCR_TG1_SHIFT) +#define TCR_TG1_64K (UL(3) << TCR_TG1_SHIFT) + #define TCR_ASID16 (UL(1) << 36) #define TCR_TBI0 (UL(1) << 37) #define TCR_HA (UL(1) << 39) -- GitLab From acd05010400215b281a9197a889bec3e67998654 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Mon, 4 Apr 2016 11:53:52 +0100 Subject: [PATCH 3842/9938] arm64: Cleanup VTCR_EL2 and VTTBR field values We share most of the bits for VTCR_EL2 for different page sizes, except for the TG0 value and the entry level value. This patch makes the definitions a bit more cleaner to reflect this fact. Also cleans up the VTTBR_X calculation. No functional changes. Cc: Marc Zyngier Acked-by: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/kvm_arm.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index a46b39f62426..1281d98392a0 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -144,30 +144,32 @@ * The magic numbers used for VTTBR_X in this patch can be found in Tables * D4-23 and D4-25 in ARM DDI 0487A.b. */ + +#define VTCR_EL2_T0SZ_IPA VTCR_EL2_T0SZ_40B +#define VTCR_EL2_COMMON_BITS (VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \ + VTCR_EL2_IRGN0_WBWA | VTCR_EL2_RES1) + #ifdef CONFIG_ARM64_64K_PAGES /* * Stage2 translation configuration: - * 40bits input (T0SZ = 24) * 64kB pages (TG0 = 1) * 2 level page tables (SL = 1) */ -#define VTCR_EL2_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \ - VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ - VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1) -#define VTTBR_X (38 - VTCR_EL2_T0SZ_40B) +#define VTCR_EL2_TGRAN_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SL0_LVL1) +#define VTTBR_X_TGRAN_MAGIC 38 #else /* * Stage2 translation configuration: - * 40bits input (T0SZ = 24) * 4kB pages (TG0 = 0) * 3 level page tables (SL = 1) */ -#define VTCR_EL2_FLAGS (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \ - VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ - VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1) -#define VTTBR_X (37 - VTCR_EL2_T0SZ_40B) +#define VTCR_EL2_TGRAN_FLAGS (VTCR_EL2_TG0_4K | VTCR_EL2_SL0_LVL1) +#define VTTBR_X_TGRAN_MAGIC 37 #endif +#define VTCR_EL2_FLAGS (VTCR_EL2_COMMON_BITS | VTCR_EL2_TGRAN_FLAGS) +#define VTTBR_X (VTTBR_X_TGRAN_MAGIC - VTCR_EL2_T0SZ_IPA) + #define VTTBR_BADDR_SHIFT (VTTBR_X - 1) #define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) #define VTTBR_VMID_SHIFT (UL(48)) -- GitLab From 120f0779c3ed89c25ef1db943feac8ed73a0d7f9 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 1 Mar 2016 10:03:06 +0000 Subject: [PATCH 3843/9938] kvm arm: Move fake PGD handling to arch specific files Rearrange the code for fake pgd handling, which is applicable only for arm64. This will later be removed once we introduce the stage2 page table walker macros. Reviewed-by: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm/include/asm/kvm_mmu.h | 11 ++++++-- arch/arm/kvm/mmu.c | 47 +++++--------------------------- arch/arm64/include/asm/kvm_mmu.h | 43 +++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index da44be9db4fa..c2b2b27b7da1 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -161,8 +161,6 @@ static inline bool kvm_page_empty(void *ptr) #define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp) #define kvm_pud_table_empty(kvm, pudp) (0) -#define KVM_PREALLOC_LEVEL 0 - static inline void *kvm_get_hwpgd(struct kvm *kvm) { return kvm->arch.pgd; @@ -173,6 +171,15 @@ static inline unsigned int kvm_get_hwpgd_size(void) return PTRS_PER_S2_PGD * sizeof(pgd_t); } +static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd) +{ + return hwpgd; +} + +static inline void kvm_free_fake_pgd(pgd_t *pgd) +{ +} + struct kvm; #define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 58dbd5c439df..774d00b8066b 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -684,47 +684,16 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm) if (!hwpgd) return -ENOMEM; - /* When the kernel uses more levels of page tables than the + /* + * When the kernel uses more levels of page tables than the * guest, we allocate a fake PGD and pre-populate it to point * to the next-level page table, which will be the real * initial page table pointed to by the VTTBR. - * - * When KVM_PREALLOC_LEVEL==2, we allocate a single page for - * the PMD and the kernel will use folded pud. - * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD - * pages. */ - if (KVM_PREALLOC_LEVEL > 0) { - int i; - - /* - * Allocate fake pgd for the page table manipulation macros to - * work. This is not used by the hardware and we have no - * alignment requirement for this allocation. - */ - pgd = kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t), - GFP_KERNEL | __GFP_ZERO); - - if (!pgd) { - kvm_free_hwpgd(hwpgd); - return -ENOMEM; - } - - /* Plug the HW PGD into the fake one. */ - for (i = 0; i < PTRS_PER_S2_PGD; i++) { - if (KVM_PREALLOC_LEVEL == 1) - pgd_populate(NULL, pgd + i, - (pud_t *)hwpgd + i * PTRS_PER_PUD); - else if (KVM_PREALLOC_LEVEL == 2) - pud_populate(NULL, pud_offset(pgd, 0) + i, - (pmd_t *)hwpgd + i * PTRS_PER_PMD); - } - } else { - /* - * Allocate actual first-level Stage-2 page table used by the - * hardware for Stage-2 page table walks. - */ - pgd = (pgd_t *)hwpgd; + pgd = kvm_setup_fake_pgd(hwpgd); + if (IS_ERR(pgd)) { + kvm_free_hwpgd(hwpgd); + return PTR_ERR(pgd); } kvm_clean_pgd(pgd); @@ -831,9 +800,7 @@ void kvm_free_stage2_pgd(struct kvm *kvm) unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); kvm_free_hwpgd(kvm_get_hwpgd(kvm)); - if (KVM_PREALLOC_LEVEL > 0) - kfree(kvm->arch.pgd); - + kvm_free_fake_pgd(kvm->arch.pgd); kvm->arch.pgd = NULL; } diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 22732a5e3119..9a3409f7b37a 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -208,6 +208,49 @@ static inline unsigned int kvm_get_hwpgd_size(void) return PTRS_PER_S2_PGD * sizeof(pgd_t); } +/* + * Allocate fake pgd for the host kernel page table macros to work. + * This is not used by the hardware and we have no alignment + * requirement for this allocation. + */ +static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd) +{ + int i; + pgd_t *pgd; + + if (!KVM_PREALLOC_LEVEL) + return hwpgd; + + /* + * When KVM_PREALLOC_LEVEL==2, we allocate a single page for + * the PMD and the kernel will use folded pud. + * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD + * pages. + */ + + pgd = kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t), + GFP_KERNEL | __GFP_ZERO); + if (!pgd) + return ERR_PTR(-ENOMEM); + + /* Plug the HW PGD into the fake one. */ + for (i = 0; i < PTRS_PER_S2_PGD; i++) { + if (KVM_PREALLOC_LEVEL == 1) + pgd_populate(NULL, pgd + i, + (pud_t *)hwpgd + i * PTRS_PER_PUD); + else if (KVM_PREALLOC_LEVEL == 2) + pud_populate(NULL, pud_offset(pgd, 0) + i, + (pmd_t *)hwpgd + i * PTRS_PER_PMD); + } + + return pgd; +} + +static inline void kvm_free_fake_pgd(pgd_t *pgd) +{ + if (KVM_PREALLOC_LEVEL > 0) + kfree(pgd); +} static inline bool kvm_page_empty(void *ptr) { struct page *ptr_page = virt_to_page(ptr); -- GitLab From 0dbd3b18c63c81dec1a8c47667d89c54ade9b52a Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 15 Mar 2016 10:46:34 +0000 Subject: [PATCH 3844/9938] arm64: Introduce pmd_thp_or_huge Add a helper to determine if a given pmd represents a huge page either by hugetlb or thp, as we have for arm. This will be used by KVM MMU code. Suggested-by: Mark Rutland Cc: Catalin Marinas Cc: Steve Capper Cc: Will Deacon Acked-by: Marc Zyngier Acked-by: Will Deacon Acked-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 989fef16d461..dda4aa9ba3f8 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -290,6 +290,8 @@ static inline pgprot_t mk_sect_prot(pgprot_t prot) #define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd))) #define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK)) +#define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd)) + #define __HAVE_ARCH_PMD_WRITE #define pmd_write(pmd) pte_write(pmd_pte(pmd)) -- GitLab From bbb3b6b35087539e75792b46e07b7ce5282d0979 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 1 Mar 2016 12:00:39 +0000 Subject: [PATCH 3845/9938] kvm-arm: Replace kvm_pmd_huge with pmd_thp_or_huge Both arm and arm64 now provides a helper, pmd_thp_or_huge() to check if the given pmd represents a huge page. Use that instead of our own custom check. Suggested-by: Mark Rutland Cc: Marc Zyngier Acked-by: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm/kvm/mmu.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 774d00b8066b..7837f0afa5a4 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -45,7 +45,6 @@ static phys_addr_t hyp_idmap_vector; #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t)) -#define kvm_pmd_huge(_x) (pmd_huge(_x) || pmd_trans_huge(_x)) #define kvm_pud_huge(_x) pud_huge(_x) #define KVM_S2PTE_FLAG_IS_IOMAP (1UL << 0) @@ -115,7 +114,7 @@ static bool kvm_is_device_pfn(unsigned long pfn) */ static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd) { - if (!kvm_pmd_huge(*pmd)) + if (!pmd_thp_or_huge(*pmd)) return; pmd_clear(pmd); @@ -177,7 +176,7 @@ static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) { pte_t *pte_table = pte_offset_kernel(pmd, 0); - VM_BUG_ON(kvm_pmd_huge(*pmd)); + VM_BUG_ON(pmd_thp_or_huge(*pmd)); pmd_clear(pmd); kvm_tlb_flush_vmid_ipa(kvm, addr); pte_free_kernel(NULL, pte_table); @@ -240,7 +239,7 @@ static void unmap_pmds(struct kvm *kvm, pud_t *pud, do { next = kvm_pmd_addr_end(addr, end); if (!pmd_none(*pmd)) { - if (kvm_pmd_huge(*pmd)) { + if (pmd_thp_or_huge(*pmd)) { pmd_t old_pmd = *pmd; pmd_clear(pmd); @@ -326,7 +325,7 @@ static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud, do { next = kvm_pmd_addr_end(addr, end); if (!pmd_none(*pmd)) { - if (kvm_pmd_huge(*pmd)) + if (pmd_thp_or_huge(*pmd)) kvm_flush_dcache_pmd(*pmd); else stage2_flush_ptes(kvm, pmd, addr, next); @@ -1050,7 +1049,7 @@ static void stage2_wp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end) do { next = kvm_pmd_addr_end(addr, end); if (!pmd_none(*pmd)) { - if (kvm_pmd_huge(*pmd)) { + if (pmd_thp_or_huge(*pmd)) { if (!kvm_s2pmd_readonly(pmd)) kvm_set_s2pmd_readonly(pmd); } else { @@ -1331,7 +1330,7 @@ static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa) if (!pmd || pmd_none(*pmd)) /* Nothing there */ goto out; - if (kvm_pmd_huge(*pmd)) { /* THP, HugeTLB */ + if (pmd_thp_or_huge(*pmd)) { /* THP, HugeTLB */ *pmd = pmd_mkyoung(*pmd); pfn = pmd_pfn(*pmd); pfn_valid = true; @@ -1555,7 +1554,7 @@ static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data) if (!pmd || pmd_none(*pmd)) /* Nothing there */ return 0; - if (kvm_pmd_huge(*pmd)) { /* THP, HugeTLB */ + if (pmd_thp_or_huge(*pmd)) { /* THP, HugeTLB */ if (pmd_young(*pmd)) { *pmd = pmd_mkold(*pmd); return 1; @@ -1585,7 +1584,7 @@ static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data) if (!pmd || pmd_none(*pmd)) /* Nothing there */ return 0; - if (kvm_pmd_huge(*pmd)) /* THP, HugeTLB */ + if (pmd_thp_or_huge(*pmd)) /* THP, HugeTLB */ return pmd_young(*pmd); pte = pte_offset_kernel(pmd, gpa); -- GitLab From 77b5665141a9a7e69d2f685ee2f2a3698fd27397 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 14:06:47 +0000 Subject: [PATCH 3846/9938] kvm-arm: Remove kvm_pud_huge() Get rid of kvm_pud_huge() which falls back to pud_huge. Use pud_huge instead. Acked-by: Christoffer Dall Acked-by: Marc Zyngier Signed-off-by: Suzuki K Poulose --- arch/arm/kvm/mmu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 7837f0afa5a4..d0c0ee92c378 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -45,8 +45,6 @@ static phys_addr_t hyp_idmap_vector; #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t)) -#define kvm_pud_huge(_x) pud_huge(_x) - #define KVM_S2PTE_FLAG_IS_IOMAP (1UL << 0) #define KVM_S2_FLAG_LOGGING_ACTIVE (1UL << 1) @@ -1077,7 +1075,7 @@ static void stage2_wp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end) next = kvm_pud_addr_end(addr, end); if (!pud_none(*pud)) { /* TODO:PUD not supported, revisit later if supported */ - BUG_ON(kvm_pud_huge(*pud)); + BUG_ON(pud_huge(*pud)); stage2_wp_pmds(pud, addr, next); } } while (pud++, addr = next, addr != end); -- GitLab From b1ae9a30f18d22e1ae544e4c37a032d018ebdac5 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 14:08:17 +0000 Subject: [PATCH 3847/9938] kvm-arm: arm32: Introduce stage2 page table helpers Define the page table helpers for walking the stage2 pagetable for arm. Since both hyp and stage2 have the same number of levels, as that of the host we reuse the host helpers. The exceptions are the p.d_addr_end routines which have to deal with IPA > 32bit, hence we use the open coded version of their host helpers which supports 64bit. Acked-by: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose Signed-off-by: Christoffer Dall --- arch/arm/include/asm/kvm_mmu.h | 1 + arch/arm/include/asm/stage2_pgtable.h | 61 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 arch/arm/include/asm/stage2_pgtable.h diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index c2b2b27b7da1..7d207b44a656 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -47,6 +47,7 @@ #include #include #include +#include int create_hyp_mappings(void *from, void *to); int create_hyp_io_mappings(void *from, void *to, phys_addr_t); diff --git a/arch/arm/include/asm/stage2_pgtable.h b/arch/arm/include/asm/stage2_pgtable.h new file mode 100644 index 000000000000..460d616bb2d6 --- /dev/null +++ b/arch/arm/include/asm/stage2_pgtable.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 - ARM Ltd + * + * stage2 page table helpers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ARM_S2_PGTABLE_H_ +#define __ARM_S2_PGTABLE_H_ + +#define stage2_pgd_none(pgd) pgd_none(pgd) +#define stage2_pgd_clear(pgd) pgd_clear(pgd) +#define stage2_pgd_present(pgd) pgd_present(pgd) +#define stage2_pgd_populate(pgd, pud) pgd_populate(NULL, pgd, pud) +#define stage2_pud_offset(pgd, address) pud_offset(pgd, address) +#define stage2_pud_free(pud) pud_free(NULL, pud) + +#define stage2_pud_none(pud) pud_none(pud) +#define stage2_pud_clear(pud) pud_clear(pud) +#define stage2_pud_present(pud) pud_present(pud) +#define stage2_pud_populate(pud, pmd) pud_populate(NULL, pud, pmd) +#define stage2_pmd_offset(pud, address) pmd_offset(pud, address) +#define stage2_pmd_free(pmd) pmd_free(NULL, pmd) + +#define stage2_pud_huge(pud) pud_huge(pud) + +/* Open coded p*d_addr_end that can deal with 64bit addresses */ +static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t boundary = (addr + PGDIR_SIZE) & PGDIR_MASK; + + return (boundary - 1 < end - 1) ? boundary : end; +} + +#define stage2_pud_addr_end(addr, end) (end) + +static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t boundary = (addr + PMD_SIZE) & PMD_MASK; + + return (boundary - 1 < end - 1) ? boundary : end; +} + +#define stage2_pgd_index(addr) pgd_index(addr) + +#define stage2_pte_table_empty(ptep) kvm_page_empty(ptep) +#define stage2_pmd_table_empty(pmdp) kvm_page_empty(pmdp) +#define stage2_pud_table_empty(pudp) false + +#endif /* __ARM_S2_PGTABLE_H_ */ -- GitLab From b1d030a73e9039dcdec951327e9ce9e8d682067f Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 17:15:55 +0000 Subject: [PATCH 3848/9938] kvm-arm: arm: Introduce hyp page table empty checks Introduce hyp_pxx_table_empty helpers for checking whether a given table entry is empty. This will be used explicitly once we switch to explicit routines for hyp page table walk. Acked-by: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose Signed-off-by: Christoffer Dall --- arch/arm/include/asm/kvm_mmu.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 7d207b44a656..5522cdd9dedf 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -160,7 +160,11 @@ static inline bool kvm_page_empty(void *ptr) #define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep) #define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp) -#define kvm_pud_table_empty(kvm, pudp) (0) +#define kvm_pud_table_empty(kvm, pudp) false + +#define hyp_pte_table_empty(ptep) kvm_page_empty(ptep) +#define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp) +#define hyp_pud_table_empty(pudp) false static inline void *kvm_get_hwpgd(struct kvm *kvm) { -- GitLab From c0ef6326dd393d84c9906240164e803536b5f3fc Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 14:16:52 +0000 Subject: [PATCH 3849/9938] kvm-arm: arm64: Introduce stage2 page table helpers Introduce stage2 page table helpers for arm64. With the fake page table level still in place, the stage2 table has the same number of levels as that of the host (and hyp), so they all fallback to the host version. Acked-by: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/kvm_mmu.h | 29 +-------- arch/arm64/include/asm/stage2_pgtable.h | 86 +++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 27 deletions(-) create mode 100644 arch/arm64/include/asm/stage2_pgtable.h diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 9a3409f7b37a..e3f53e3eb4d9 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -91,6 +91,8 @@ alternative_endif #define KVM_PHYS_SIZE (1UL << KVM_PHYS_SHIFT) #define KVM_PHYS_MASK (KVM_PHYS_SIZE - 1UL) +#include + int create_hyp_mappings(void *from, void *to); int create_hyp_io_mappings(void *from, void *to, phys_addr_t); void free_boot_hyp_pgd(void); @@ -156,35 +158,8 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd) #define kvm_pud_addr_end(addr, end) pud_addr_end(addr, end) #define kvm_pmd_addr_end(addr, end) pmd_addr_end(addr, end) -/* - * In the case where PGDIR_SHIFT is larger than KVM_PHYS_SHIFT, we can address - * the entire IPA input range with a single pgd entry, and we would only need - * one pgd entry. Note that in this case, the pgd is actually not used by - * the MMU for Stage-2 translations, but is merely a fake pgd used as a data - * structure for the kernel pgtable macros to work. - */ -#if PGDIR_SHIFT > KVM_PHYS_SHIFT -#define PTRS_PER_S2_PGD_SHIFT 0 -#else -#define PTRS_PER_S2_PGD_SHIFT (KVM_PHYS_SHIFT - PGDIR_SHIFT) -#endif -#define PTRS_PER_S2_PGD (1 << PTRS_PER_S2_PGD_SHIFT) - #define kvm_pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) -/* - * If we are concatenating first level stage-2 page tables, we would have less - * than or equal to 16 pointers in the fake PGD, because that's what the - * architecture allows. In this case, (4 - CONFIG_PGTABLE_LEVELS) - * represents the first level for the host, and we add 1 to go to the next - * level (which uses contatenation) for the stage-2 tables. - */ -#if PTRS_PER_S2_PGD <= 16 -#define KVM_PREALLOC_LEVEL (4 - CONFIG_PGTABLE_LEVELS + 1) -#else -#define KVM_PREALLOC_LEVEL (0) -#endif - static inline void *kvm_get_hwpgd(struct kvm *kvm) { pgd_t *pgd = kvm->arch.pgd; diff --git a/arch/arm64/include/asm/stage2_pgtable.h b/arch/arm64/include/asm/stage2_pgtable.h new file mode 100644 index 000000000000..0ec218fe83c5 --- /dev/null +++ b/arch/arm64/include/asm/stage2_pgtable.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2016 - ARM Ltd + * + * stage2 page table helpers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ARM64_S2_PGTABLE_H_ +#define __ARM64_S2_PGTABLE_H_ + +#include + +/* + * In the case where PGDIR_SHIFT is larger than KVM_PHYS_SHIFT, we can address + * the entire IPA input range with a single pgd entry, and we would only need + * one pgd entry. Note that in this case, the pgd is actually not used by + * the MMU for Stage-2 translations, but is merely a fake pgd used as a data + * structure for the kernel pgtable macros to work. + */ +#if PGDIR_SHIFT > KVM_PHYS_SHIFT +#define PTRS_PER_S2_PGD_SHIFT 0 +#else +#define PTRS_PER_S2_PGD_SHIFT (KVM_PHYS_SHIFT - PGDIR_SHIFT) +#endif +#define PTRS_PER_S2_PGD (1 << PTRS_PER_S2_PGD_SHIFT) + +/* + * If we are concatenating first level stage-2 page tables, we would have less + * than or equal to 16 pointers in the fake PGD, because that's what the + * architecture allows. In this case, (4 - CONFIG_PGTABLE_LEVELS) + * represents the first level for the host, and we add 1 to go to the next + * level (which uses contatenation) for the stage-2 tables. + */ +#if PTRS_PER_S2_PGD <= 16 +#define KVM_PREALLOC_LEVEL (4 - CONFIG_PGTABLE_LEVELS + 1) +#else +#define KVM_PREALLOC_LEVEL (0) +#endif + +#define stage2_pgd_none(pgd) pgd_none(pgd) +#define stage2_pgd_clear(pgd) pgd_clear(pgd) +#define stage2_pgd_present(pgd) pgd_present(pgd) +#define stage2_pgd_populate(pgd, pud) pgd_populate(NULL, pgd, pud) +#define stage2_pud_offset(pgd, address) pud_offset(pgd, address) +#define stage2_pud_free(pud) pud_free(NULL, pud) + +#define stage2_pud_none(pud) pud_none(pud) +#define stage2_pud_clear(pud) pud_clear(pud) +#define stage2_pud_present(pud) pud_present(pud) +#define stage2_pud_populate(pud, pmd) pud_populate(NULL, pud, pmd) +#define stage2_pmd_offset(pud, address) pmd_offset(pud, address) +#define stage2_pmd_free(pmd) pmd_free(NULL, pmd) + +#define stage2_pud_huge(pud) pud_huge(pud) + +#define stage2_pgd_addr_end(address, end) pgd_addr_end(address, end) +#define stage2_pud_addr_end(address, end) pud_addr_end(address, end) +#define stage2_pmd_addr_end(address, end) pmd_addr_end(address, end) + +#define stage2_pte_table_empty(ptep) kvm_page_empty(ptep) +#ifdef __PGTABLE_PMD_FOLDED +#define stage2_pmd_table_empty(pmdp) (0) +#else +#define stage2_pmd_table_empty(pmdp) ((KVM_PREALLOC_LEVEL < 2) && kvm_page_empty(pmdp)) +#endif + +#ifdef __PGTABLE_PUD_FOLDED +#define stage2_pud_table_empty(pudp) (0) +#else +#define stage2_pud_table_empty(pudp) ((KVM_PREALLOC_LEVEL < 1) && kvm_page_empty(pudp)) +#endif + +#define stage2_pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) + +#endif /* __ARM64_S2_PGTABLE_H_ */ -- GitLab From 66f877faf9cc23232f25b423758eaa167de1ad09 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 17:20:28 +0000 Subject: [PATCH 3850/9938] kvm-arm: arm64: Introduce hyp page table empty checks Introduce hyp_pxx_table_empty helpers for checking whether a given table entry is empty. This will be used explicitly once we switch to explicit routines for hyp page table walk. Acked-by: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/kvm_mmu.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index e3f53e3eb4d9..edf3c62c660e 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -249,6 +249,20 @@ static inline bool kvm_page_empty(void *ptr) #endif +#define hyp_pte_table_empty(ptep) kvm_page_empty(ptep) + +#ifdef __PAGETABLE_PMD_FOLDED +#define hyp_pmd_table_empty(pmdp) (0) +#else +#define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp) +#endif + +#ifdef __PAGETABLE_PUD_FOLDED +#define hyp_pud_table_empty(pudp) (0) +#else +#define hyp_pud_table_empty(pudp) kvm_page_empty(pudp) +#endif + struct kvm; #define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) -- GitLab From 70fd19068573e449d47eb2daa69cf5db541ef4f5 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 18:33:45 +0000 Subject: [PATCH 3851/9938] kvm-arm: Use explicit stage2 helper routines We have stage2 page table helpers for both arm and arm64. Switch to the stage2 helpers for routines that only deal with stage2 page table. Cc: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm/kvm/mmu.c | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index d0c0ee92c378..f93f717b5d8b 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -319,9 +319,9 @@ static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud, pmd_t *pmd; phys_addr_t next; - pmd = pmd_offset(pud, addr); + pmd = stage2_pmd_offset(pud, addr); do { - next = kvm_pmd_addr_end(addr, end); + next = stage2_pmd_addr_end(addr, end); if (!pmd_none(*pmd)) { if (pmd_thp_or_huge(*pmd)) kvm_flush_dcache_pmd(*pmd); @@ -337,11 +337,11 @@ static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd, pud_t *pud; phys_addr_t next; - pud = pud_offset(pgd, addr); + pud = stage2_pud_offset(pgd, addr); do { - next = kvm_pud_addr_end(addr, end); - if (!pud_none(*pud)) { - if (pud_huge(*pud)) + next = stage2_pud_addr_end(addr, end); + if (!stage2_pud_none(*pud)) { + if (stage2_pud_huge(*pud)) kvm_flush_dcache_pud(*pud); else stage2_flush_pmds(kvm, pud, addr, next); @@ -357,9 +357,9 @@ static void stage2_flush_memslot(struct kvm *kvm, phys_addr_t next; pgd_t *pgd; - pgd = kvm->arch.pgd + kvm_pgd_index(addr); + pgd = kvm->arch.pgd + stage2_pgd_index(addr); do { - next = kvm_pgd_addr_end(addr, end); + next = stage2_pgd_addr_end(addr, end); stage2_flush_puds(kvm, pgd, addr, next); } while (pgd++, addr = next, addr != end); } @@ -807,16 +807,16 @@ static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache pgd_t *pgd; pud_t *pud; - pgd = kvm->arch.pgd + kvm_pgd_index(addr); - if (WARN_ON(pgd_none(*pgd))) { + pgd = kvm->arch.pgd + stage2_pgd_index(addr); + if (WARN_ON(stage2_pgd_none(*pgd))) { if (!cache) return NULL; pud = mmu_memory_cache_alloc(cache); - pgd_populate(NULL, pgd, pud); + stage2_pgd_populate(pgd, pud); get_page(virt_to_page(pgd)); } - return pud_offset(pgd, addr); + return stage2_pud_offset(pgd, addr); } static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, @@ -826,15 +826,15 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache pmd_t *pmd; pud = stage2_get_pud(kvm, cache, addr); - if (pud_none(*pud)) { + if (stage2_pud_none(*pud)) { if (!cache) return NULL; pmd = mmu_memory_cache_alloc(cache); - pud_populate(NULL, pud, pmd); + stage2_pud_populate(pud, pmd); get_page(virt_to_page(pud)); } - return pmd_offset(pud, addr); + return stage2_pmd_offset(pud, addr); } static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache @@ -1042,10 +1042,10 @@ static void stage2_wp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end) pmd_t *pmd; phys_addr_t next; - pmd = pmd_offset(pud, addr); + pmd = stage2_pmd_offset(pud, addr); do { - next = kvm_pmd_addr_end(addr, end); + next = stage2_pmd_addr_end(addr, end); if (!pmd_none(*pmd)) { if (pmd_thp_or_huge(*pmd)) { if (!kvm_s2pmd_readonly(pmd)) @@ -1070,12 +1070,12 @@ static void stage2_wp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end) pud_t *pud; phys_addr_t next; - pud = pud_offset(pgd, addr); + pud = stage2_pud_offset(pgd, addr); do { - next = kvm_pud_addr_end(addr, end); - if (!pud_none(*pud)) { + next = stage2_pud_addr_end(addr, end); + if (!stage2_pud_none(*pud)) { /* TODO:PUD not supported, revisit later if supported */ - BUG_ON(pud_huge(*pud)); + BUG_ON(stage2_pud_huge(*pud)); stage2_wp_pmds(pud, addr, next); } } while (pud++, addr = next, addr != end); @@ -1092,7 +1092,7 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) pgd_t *pgd; phys_addr_t next; - pgd = kvm->arch.pgd + kvm_pgd_index(addr); + pgd = kvm->arch.pgd + stage2_pgd_index(addr); do { /* * Release kvm_mmu_lock periodically if the memory region is @@ -1104,8 +1104,8 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) if (need_resched() || spin_needbreak(&kvm->mmu_lock)) cond_resched_lock(&kvm->mmu_lock); - next = kvm_pgd_addr_end(addr, end); - if (pgd_present(*pgd)) + next = stage2_pgd_addr_end(addr, end); + if (stage2_pgd_present(*pgd)) stage2_wp_puds(pgd, addr, next); } while (pgd++, addr = next, addr != end); } -- GitLab From 64f324979210d4064adf64f19da40c125c9dd137 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 18:56:21 +0000 Subject: [PATCH 3852/9938] kvm-arm: Add explicit hyp page table modifiers We have common routines to modify hyp and stage2 page tables based on the 'kvm' parameter. For a smoother transition to using separate routines for each, duplicate the routines and modify the copy to work on hyp. Marks the forked routines with _hyp_ and gets rid of the kvm parameter which is no longer needed and is NULL for hyp. Also, gets rid of calls to kvm_tlb_flush_by_vmid_ipa() calls from the hyp versions. Uses explicit host page table accessors instead of the kvm_* page table helpers. Suggested-by: Christoffer Dall Cc: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm/kvm/mmu.c | 104 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index f93f717b5d8b..af526f67022c 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -388,6 +388,100 @@ static void stage2_flush_vm(struct kvm *kvm) srcu_read_unlock(&kvm->srcu, idx); } +static void clear_hyp_pgd_entry(pgd_t *pgd) +{ + pud_t *pud_table __maybe_unused = pud_offset(pgd, 0UL); + pgd_clear(pgd); + pud_free(NULL, pud_table); + put_page(virt_to_page(pgd)); +} + +static void clear_hyp_pud_entry(pud_t *pud) +{ + pmd_t *pmd_table __maybe_unused = pmd_offset(pud, 0); + VM_BUG_ON(pud_huge(*pud)); + pud_clear(pud); + pmd_free(NULL, pmd_table); + put_page(virt_to_page(pud)); +} + +static void clear_hyp_pmd_entry(pmd_t *pmd) +{ + pte_t *pte_table = pte_offset_kernel(pmd, 0); + VM_BUG_ON(pmd_thp_or_huge(*pmd)); + pmd_clear(pmd); + pte_free_kernel(NULL, pte_table); + put_page(virt_to_page(pmd)); +} + +static void unmap_hyp_ptes(pmd_t *pmd, phys_addr_t addr, phys_addr_t end) +{ + pte_t *pte, *start_pte; + + start_pte = pte = pte_offset_kernel(pmd, addr); + do { + if (!pte_none(*pte)) { + kvm_set_pte(pte, __pte(0)); + put_page(virt_to_page(pte)); + } + } while (pte++, addr += PAGE_SIZE, addr != end); + + if (hyp_pte_table_empty(start_pte)) + clear_hyp_pmd_entry(pmd); +} + +static void unmap_hyp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t next; + pmd_t *pmd, *start_pmd; + + start_pmd = pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); + /* Hyp doesn't use huge pmds */ + if (!pmd_none(*pmd)) + unmap_hyp_ptes(pmd, addr, next); + } while (pmd++, addr = next, addr != end); + + if (hyp_pmd_table_empty(start_pmd)) + clear_hyp_pud_entry(pud); +} + +static void unmap_hyp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t next; + pud_t *pud, *start_pud; + + start_pud = pud = pud_offset(pgd, addr); + do { + next = pud_addr_end(addr, end); + /* Hyp doesn't use huge puds */ + if (!pud_none(*pud)) + unmap_hyp_pmds(pud, addr, next); + } while (pud++, addr = next, addr != end); + + if (hyp_pud_table_empty(start_pud)) + clear_hyp_pgd_entry(pgd); +} + +static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size) +{ + pgd_t *pgd; + phys_addr_t addr = start, end = start + size; + phys_addr_t next; + + /* + * We don't unmap anything from HYP, except at the hyp tear down. + * Hence, we don't have to invalidate the TLBs here. + */ + pgd = pgdp + pgd_index(addr); + do { + next = pgd_addr_end(addr, end); + if (!pgd_none(*pgd)) + unmap_hyp_puds(pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} + /** * free_boot_hyp_pgd - free HYP boot page tables * @@ -398,14 +492,14 @@ void free_boot_hyp_pgd(void) mutex_lock(&kvm_hyp_pgd_mutex); if (boot_hyp_pgd) { - unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE); - unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); + unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE); + unmap_hyp_range(boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order); boot_hyp_pgd = NULL; } if (hyp_pgd) - unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); + unmap_hyp_range(hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); mutex_unlock(&kvm_hyp_pgd_mutex); } @@ -430,9 +524,9 @@ void free_hyp_pgds(void) if (hyp_pgd) { for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE) - unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); + unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) - unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); + unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); free_pages((unsigned long)hyp_pgd, hyp_pgd_order); hyp_pgd = NULL; -- GitLab From 7a1c831ee8553b8199f21183942a46adf808f174 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 23 Mar 2016 12:08:02 +0000 Subject: [PATCH 3853/9938] kvm-arm: Add stage2 page table modifiers Now that the hyp page table is handled by different set of routines, rename the original shared routines to stage2 handlers. Also make explicit use of the stage2 page table helpers. unmap_range has been merged to existing unmap_stage2_range. Cc: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm/kvm/mmu.c | 97 +++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index af526f67022c..f2a6d9b8ca2d 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -152,26 +152,26 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) return p; } -static void clear_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr) +static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr) { - pud_t *pud_table __maybe_unused = pud_offset(pgd, 0); - pgd_clear(pgd); + pud_t *pud_table __maybe_unused = stage2_pud_offset(pgd, 0UL); + stage2_pgd_clear(pgd); kvm_tlb_flush_vmid_ipa(kvm, addr); - pud_free(NULL, pud_table); + stage2_pud_free(pud_table); put_page(virt_to_page(pgd)); } -static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) +static void clear_stage2_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) { - pmd_t *pmd_table = pmd_offset(pud, 0); - VM_BUG_ON(pud_huge(*pud)); - pud_clear(pud); + pmd_t *pmd_table __maybe_unused = stage2_pmd_offset(pud, 0); + VM_BUG_ON(stage2_pud_huge(*pud)); + stage2_pud_clear(pud); kvm_tlb_flush_vmid_ipa(kvm, addr); - pmd_free(NULL, pmd_table); + stage2_pmd_free(pmd_table); put_page(virt_to_page(pud)); } -static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) +static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) { pte_t *pte_table = pte_offset_kernel(pmd, 0); VM_BUG_ON(pmd_thp_or_huge(*pmd)); @@ -201,7 +201,7 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) * the corresponding TLBs, we call kvm_flush_dcache_p*() to make sure * the IO subsystem will never hit in the cache. */ -static void unmap_ptes(struct kvm *kvm, pmd_t *pmd, +static void unmap_stage2_ptes(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr, phys_addr_t end) { phys_addr_t start_addr = addr; @@ -223,19 +223,19 @@ static void unmap_ptes(struct kvm *kvm, pmd_t *pmd, } } while (pte++, addr += PAGE_SIZE, addr != end); - if (kvm_pte_table_empty(kvm, start_pte)) - clear_pmd_entry(kvm, pmd, start_addr); + if (stage2_pte_table_empty(start_pte)) + clear_stage2_pmd_entry(kvm, pmd, start_addr); } -static void unmap_pmds(struct kvm *kvm, pud_t *pud, +static void unmap_stage2_pmds(struct kvm *kvm, pud_t *pud, phys_addr_t addr, phys_addr_t end) { phys_addr_t next, start_addr = addr; pmd_t *pmd, *start_pmd; - start_pmd = pmd = pmd_offset(pud, addr); + start_pmd = pmd = stage2_pmd_offset(pud, addr); do { - next = kvm_pmd_addr_end(addr, end); + next = stage2_pmd_addr_end(addr, end); if (!pmd_none(*pmd)) { if (pmd_thp_or_huge(*pmd)) { pmd_t old_pmd = *pmd; @@ -247,57 +247,64 @@ static void unmap_pmds(struct kvm *kvm, pud_t *pud, put_page(virt_to_page(pmd)); } else { - unmap_ptes(kvm, pmd, addr, next); + unmap_stage2_ptes(kvm, pmd, addr, next); } } } while (pmd++, addr = next, addr != end); - if (kvm_pmd_table_empty(kvm, start_pmd)) - clear_pud_entry(kvm, pud, start_addr); + if (stage2_pmd_table_empty(start_pmd)) + clear_stage2_pud_entry(kvm, pud, start_addr); } -static void unmap_puds(struct kvm *kvm, pgd_t *pgd, +static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr, phys_addr_t end) { phys_addr_t next, start_addr = addr; pud_t *pud, *start_pud; - start_pud = pud = pud_offset(pgd, addr); + start_pud = pud = stage2_pud_offset(pgd, addr); do { - next = kvm_pud_addr_end(addr, end); - if (!pud_none(*pud)) { - if (pud_huge(*pud)) { + next = stage2_pud_addr_end(addr, end); + if (!stage2_pud_none(*pud)) { + if (stage2_pud_huge(*pud)) { pud_t old_pud = *pud; - pud_clear(pud); + stage2_pud_clear(pud); kvm_tlb_flush_vmid_ipa(kvm, addr); - kvm_flush_dcache_pud(old_pud); - put_page(virt_to_page(pud)); } else { - unmap_pmds(kvm, pud, addr, next); + unmap_stage2_pmds(kvm, pud, addr, next); } } } while (pud++, addr = next, addr != end); - if (kvm_pud_table_empty(kvm, start_pud)) - clear_pgd_entry(kvm, pgd, start_addr); + if (stage2_pud_table_empty(start_pud)) + clear_stage2_pgd_entry(kvm, pgd, start_addr); } - -static void unmap_range(struct kvm *kvm, pgd_t *pgdp, - phys_addr_t start, u64 size) +/** + * unmap_stage2_range -- Clear stage2 page table entries to unmap a range + * @kvm: The VM pointer + * @start: The intermediate physical base address of the range to unmap + * @size: The size of the area to unmap + * + * Clear a range of stage-2 mappings, lowering the various ref-counts. Must + * be called while holding mmu_lock (unless for freeing the stage2 pgd before + * destroying the VM), otherwise another faulting VCPU may come in and mess + * with things behind our backs. + */ +static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) { pgd_t *pgd; phys_addr_t addr = start, end = start + size; phys_addr_t next; - pgd = pgdp + kvm_pgd_index(addr); + pgd = kvm->arch.pgd + stage2_pgd_index(addr); do { - next = kvm_pgd_addr_end(addr, end); - if (!pgd_none(*pgd)) - unmap_puds(kvm, pgd, addr, next); + next = stage2_pgd_addr_end(addr, end); + if (!stage2_pgd_none(*pgd)) + unmap_stage2_puds(kvm, pgd, addr, next); } while (pgd++, addr = next, addr != end); } @@ -792,22 +799,6 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm) return 0; } -/** - * unmap_stage2_range -- Clear stage2 page table entries to unmap a range - * @kvm: The VM pointer - * @start: The intermediate physical base address of the range to unmap - * @size: The size of the area to unmap - * - * Clear a range of stage-2 mappings, lowering the various ref-counts. Must - * be called while holding mmu_lock (unless for freeing the stage2 pgd before - * destroying the VM), otherwise another faulting VCPU may come in and mess - * with things behind our backs. - */ -static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) -{ - unmap_range(kvm, kvm->arch.pgd, start, size); -} - static void stage2_unmap_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) { -- GitLab From 8684e701df5a3f52e3ff580128cbd5d71fcd5f5c Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 17:14:25 +0000 Subject: [PATCH 3854/9938] kvm-arm: Cleanup kvm_* wrappers Now that we have switched to explicit page table routines, get rid of the obsolete kvm_* wrappers. Also, kvm_tlb_flush_vmid_by_ipa is now called only on stage2 page tables, hence get rid of the redundant check. Cc: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm/include/asm/kvm_mmu.h | 16 ---------------- arch/arm/kvm/mmu.c | 9 +-------- arch/arm64/include/asm/kvm_mmu.h | 24 ------------------------ 3 files changed, 1 insertion(+), 48 deletions(-) diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 5522cdd9dedf..a7736d53a408 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -136,22 +136,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd) return (pmd_val(*pmd) & L_PMD_S2_RDWR) == L_PMD_S2_RDONLY; } - -/* Open coded p*d_addr_end that can deal with 64bit addresses */ -#define kvm_pgd_addr_end(addr, end) \ -({ u64 __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \ - (__boundary - 1 < (end) - 1)? __boundary: (end); \ -}) - -#define kvm_pud_addr_end(addr,end) (end) - -#define kvm_pmd_addr_end(addr, end) \ -({ u64 __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \ - (__boundary - 1 < (end) - 1)? __boundary: (end); \ -}) - -#define kvm_pgd_index(addr) pgd_index(addr) - static inline bool kvm_page_empty(void *ptr) { struct page *ptr_page = virt_to_page(ptr); diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index f2a6d9b8ca2d..d3fa96e0f709 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -66,14 +66,7 @@ void kvm_flush_remote_tlbs(struct kvm *kvm) static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) { - /* - * This function also gets called when dealing with HYP page - * tables. As HYP doesn't have an associated struct kvm (and - * the HYP page tables are fairly static), we don't do - * anything there. - */ - if (kvm) - kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa); + kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa); } /* diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index edf3c62c660e..a3c0d05311ef 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -153,13 +153,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd) return (pmd_val(*pmd) & PMD_S2_RDWR) == PMD_S2_RDONLY; } - -#define kvm_pgd_addr_end(addr, end) pgd_addr_end(addr, end) -#define kvm_pud_addr_end(addr, end) pud_addr_end(addr, end) -#define kvm_pmd_addr_end(addr, end) pmd_addr_end(addr, end) - -#define kvm_pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) - static inline void *kvm_get_hwpgd(struct kvm *kvm) { pgd_t *pgd = kvm->arch.pgd; @@ -232,23 +225,6 @@ static inline bool kvm_page_empty(void *ptr) return page_count(ptr_page) == 1; } -#define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep) - -#ifdef __PAGETABLE_PMD_FOLDED -#define kvm_pmd_table_empty(kvm, pmdp) (0) -#else -#define kvm_pmd_table_empty(kvm, pmdp) \ - (kvm_page_empty(pmdp) && (!(kvm) || KVM_PREALLOC_LEVEL < 2)) -#endif - -#ifdef __PAGETABLE_PUD_FOLDED -#define kvm_pud_table_empty(kvm, pudp) (0) -#else -#define kvm_pud_table_empty(kvm, pudp) \ - (kvm_page_empty(pudp) && (!(kvm) || KVM_PREALLOC_LEVEL < 1)) -#endif - - #define hyp_pte_table_empty(ptep) kvm_page_empty(ptep) #ifdef __PAGETABLE_PMD_FOLDED -- GitLab From da04fa04dc91e7dae79629f28804391cbcf6e604 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 23 Mar 2016 12:22:33 +0000 Subject: [PATCH 3855/9938] kvm: arm64: Get rid of fake page table levels On arm64, the hardware supports concatenation of upto 16 tables, at entry level for stage2 translations and we make use that whenever possible. This could lead to reduced number of translation levels than the normal (stage1 table) table. Also, since the IPA(40bit) is smaller than the some of the supported VA_BITS (e.g, 48bit), there could be different number of levels in stage-1 vs stage-2 tables. To reuse the kernel host page table walker for stage2 we have been using a fake software page table level, not known to the hardware. But with 16K translations, there could be upto 2 fake software levels (with 48bit VA and 40bit IPA), which complicates the code. Hence, we want to get rid of the hack. Now that we have explicit accessors for hyp vs stage2 page tables, define the stage2 walker helpers accordingly based on the actual table used by the hardware. Once we know the number of translation levels used by the hardware, it is merely a job of defining the helpers based on whether a particular level is folded or not, looking at the number of levels. Some facts before we calculate the translation levels: 1) Smallest page size supported by arm64 is 4K. 2) The minimum number of bits resolved at any page table level is (PAGE_SHIFT - 3) at intermediate levels. Both of them implies, minimum number of bits required for a level change is 9. Since we can concatenate upto 16 tables at stage2 entry, the total number of page table levels used by the hardware for resolving N bits is same as that for (N - 4) bits (with concatenation), as there cannot be a level in between (N, N-4) as per the above rules. Hence, we have STAGE2_PGTABLE_LEVELS = PGTABLE_LEVELS(KVM_PHYS_SHIFT - 4) With the current IPA limit (40bit), for all supported translations and VA_BITS, we have the following condition (even for 36bit VA with 16K page size): CONFIG_PGTABLE_LEVELS >= STAGE2_PGTABLE_LEVELS. So, for e.g, if PUD is present in stage2, it is present in the hyp(host). Hence, we fall back to the host definition if we find that a level is not folded. Otherwise we redefine it accordingly. A build time check is added to make sure the above condition holds. If this condition breaks in future, we can rearrange the host level helpers and fix our code easily. Cc: Marc Zyngier Cc: Christoffer Dall Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/kvm_mmu.h | 64 +-------- arch/arm64/include/asm/stage2_pgtable-nopmd.h | 42 ++++++ arch/arm64/include/asm/stage2_pgtable-nopud.h | 39 ++++++ arch/arm64/include/asm/stage2_pgtable.h | 122 +++++++++++++----- 4 files changed, 172 insertions(+), 95 deletions(-) create mode 100644 arch/arm64/include/asm/stage2_pgtable-nopmd.h create mode 100644 arch/arm64/include/asm/stage2_pgtable-nopud.h diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index a3c0d05311ef..e3fee0acd1a2 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -45,18 +45,6 @@ */ #define TRAMPOLINE_VA (HYP_PAGE_OFFSET_MASK & PAGE_MASK) -/* - * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation - * levels in addition to the PGD and potentially the PUD which are - * pre-allocated (we pre-allocate the fake PGD and the PUD when the Stage-2 - * tables use one level of tables less than the kernel. - */ -#ifdef CONFIG_ARM64_64K_PAGES -#define KVM_MMU_CACHE_MIN_PAGES 1 -#else -#define KVM_MMU_CACHE_MIN_PAGES 2 -#endif - #ifdef __ASSEMBLY__ #include @@ -155,69 +143,21 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd) static inline void *kvm_get_hwpgd(struct kvm *kvm) { - pgd_t *pgd = kvm->arch.pgd; - pud_t *pud; - - if (KVM_PREALLOC_LEVEL == 0) - return pgd; - - pud = pud_offset(pgd, 0); - if (KVM_PREALLOC_LEVEL == 1) - return pud; - - BUG_ON(KVM_PREALLOC_LEVEL != 2); - return pmd_offset(pud, 0); + return kvm->arch.pgd; } static inline unsigned int kvm_get_hwpgd_size(void) { - if (KVM_PREALLOC_LEVEL > 0) - return PTRS_PER_S2_PGD * PAGE_SIZE; return PTRS_PER_S2_PGD * sizeof(pgd_t); } -/* - * Allocate fake pgd for the host kernel page table macros to work. - * This is not used by the hardware and we have no alignment - * requirement for this allocation. - */ static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd) { - int i; - pgd_t *pgd; - - if (!KVM_PREALLOC_LEVEL) - return hwpgd; - - /* - * When KVM_PREALLOC_LEVEL==2, we allocate a single page for - * the PMD and the kernel will use folded pud. - * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD - * pages. - */ - - pgd = kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t), - GFP_KERNEL | __GFP_ZERO); - if (!pgd) - return ERR_PTR(-ENOMEM); - - /* Plug the HW PGD into the fake one. */ - for (i = 0; i < PTRS_PER_S2_PGD; i++) { - if (KVM_PREALLOC_LEVEL == 1) - pgd_populate(NULL, pgd + i, - (pud_t *)hwpgd + i * PTRS_PER_PUD); - else if (KVM_PREALLOC_LEVEL == 2) - pud_populate(NULL, pud_offset(pgd, 0) + i, - (pmd_t *)hwpgd + i * PTRS_PER_PMD); - } - - return pgd; + return hwpgd; } static inline void kvm_free_fake_pgd(pgd_t *pgd) { - if (KVM_PREALLOC_LEVEL > 0) - kfree(pgd); } static inline bool kvm_page_empty(void *ptr) { diff --git a/arch/arm64/include/asm/stage2_pgtable-nopmd.h b/arch/arm64/include/asm/stage2_pgtable-nopmd.h new file mode 100644 index 000000000000..2656a0fd05a6 --- /dev/null +++ b/arch/arm64/include/asm/stage2_pgtable-nopmd.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 - ARM Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ARM64_S2_PGTABLE_NOPMD_H_ +#define __ARM64_S2_PGTABLE_NOPMD_H_ + +#include + +#define __S2_PGTABLE_PMD_FOLDED + +#define S2_PMD_SHIFT S2_PUD_SHIFT +#define S2_PTRS_PER_PMD 1 +#define S2_PMD_SIZE (1UL << S2_PMD_SHIFT) +#define S2_PMD_MASK (~(S2_PMD_SIZE-1)) + +#define stage2_pud_none(pud) (0) +#define stage2_pud_present(pud) (1) +#define stage2_pud_clear(pud) do { } while (0) +#define stage2_pud_populate(pud, pmd) do { } while (0) +#define stage2_pmd_offset(pud, address) ((pmd_t *)(pud)) + +#define stage2_pmd_free(pmd) do { } while (0) + +#define stage2_pmd_addr_end(addr, end) (end) + +#define stage2_pud_huge(pud) (0) +#define stage2_pmd_table_empty(pmdp) (0) + +#endif diff --git a/arch/arm64/include/asm/stage2_pgtable-nopud.h b/arch/arm64/include/asm/stage2_pgtable-nopud.h new file mode 100644 index 000000000000..5ee87b54ebf3 --- /dev/null +++ b/arch/arm64/include/asm/stage2_pgtable-nopud.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 - ARM Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ARM64_S2_PGTABLE_NOPUD_H_ +#define __ARM64_S2_PGTABLE_NOPUD_H_ + +#define __S2_PGTABLE_PUD_FOLDED + +#define S2_PUD_SHIFT S2_PGDIR_SHIFT +#define S2_PTRS_PER_PUD 1 +#define S2_PUD_SIZE (_AC(1, UL) << S2_PUD_SHIFT) +#define S2_PUD_MASK (~(S2_PUD_SIZE-1)) + +#define stage2_pgd_none(pgd) (0) +#define stage2_pgd_present(pgd) (1) +#define stage2_pgd_clear(pgd) do { } while (0) +#define stage2_pgd_populate(pgd, pud) do { } while (0) + +#define stage2_pud_offset(pgd, address) ((pud_t *)(pgd)) + +#define stage2_pud_free(x) do { } while (0) + +#define stage2_pud_addr_end(addr, end) (end) +#define stage2_pud_table_empty(pmdp) (0) + +#endif diff --git a/arch/arm64/include/asm/stage2_pgtable.h b/arch/arm64/include/asm/stage2_pgtable.h index 0ec218fe83c5..8b68099348e5 100644 --- a/arch/arm64/include/asm/stage2_pgtable.h +++ b/arch/arm64/include/asm/stage2_pgtable.h @@ -22,32 +22,61 @@ #include /* - * In the case where PGDIR_SHIFT is larger than KVM_PHYS_SHIFT, we can address - * the entire IPA input range with a single pgd entry, and we would only need - * one pgd entry. Note that in this case, the pgd is actually not used by - * the MMU for Stage-2 translations, but is merely a fake pgd used as a data - * structure for the kernel pgtable macros to work. + * The hardware supports concatenation of up to 16 tables at stage2 entry level + * and we use the feature whenever possible. + * + * Now, the minimum number of bits resolved at any level is (PAGE_SHIFT - 3). + * On arm64, the smallest PAGE_SIZE supported is 4k, which means + * (PAGE_SHIFT - 3) > 4 holds for all page sizes. + * This implies, the total number of page table levels at stage2 expected + * by the hardware is actually the number of levels required for (KVM_PHYS_SHIFT - 4) + * in normal translations(e.g, stage1), since we cannot have another level in + * the range (KVM_PHYS_SHIFT, KVM_PHYS_SHIFT - 4). */ -#if PGDIR_SHIFT > KVM_PHYS_SHIFT -#define PTRS_PER_S2_PGD_SHIFT 0 -#else -#define PTRS_PER_S2_PGD_SHIFT (KVM_PHYS_SHIFT - PGDIR_SHIFT) -#endif -#define PTRS_PER_S2_PGD (1 << PTRS_PER_S2_PGD_SHIFT) +#define STAGE2_PGTABLE_LEVELS ARM64_HW_PGTABLE_LEVELS(KVM_PHYS_SHIFT - 4) /* - * If we are concatenating first level stage-2 page tables, we would have less - * than or equal to 16 pointers in the fake PGD, because that's what the - * architecture allows. In this case, (4 - CONFIG_PGTABLE_LEVELS) - * represents the first level for the host, and we add 1 to go to the next - * level (which uses contatenation) for the stage-2 tables. + * With all the supported VA_BITs and 40bit guest IPA, the following condition + * is always true: + * + * STAGE2_PGTABLE_LEVELS <= CONFIG_PGTABLE_LEVELS + * + * We base our stage-2 page table walker helpers on this assumption and + * fall back to using the host version of the helper wherever possible. + * i.e, if a particular level is not folded (e.g, PUD) at stage2, we fall back + * to using the host version, since it is guaranteed it is not folded at host. + * + * If the condition breaks in the future, we can rearrange the host level + * definitions and reuse them for stage2. Till then... */ -#if PTRS_PER_S2_PGD <= 16 -#define KVM_PREALLOC_LEVEL (4 - CONFIG_PGTABLE_LEVELS + 1) -#else -#define KVM_PREALLOC_LEVEL (0) +#if STAGE2_PGTABLE_LEVELS > CONFIG_PGTABLE_LEVELS +#error "Unsupported combination of guest IPA and host VA_BITS." #endif +/* S2_PGDIR_SHIFT is the size mapped by top-level stage2 entry */ +#define S2_PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - STAGE2_PGTABLE_LEVELS) +#define S2_PGDIR_SIZE (_AC(1, UL) << S2_PGDIR_SHIFT) +#define S2_PGDIR_MASK (~(S2_PGDIR_SIZE - 1)) + +/* + * The number of PTRS across all concatenated stage2 tables given by the + * number of bits resolved at the initial level. + */ +#define PTRS_PER_S2_PGD (1 << (KVM_PHYS_SHIFT - S2_PGDIR_SHIFT)) + +/* + * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation + * levels in addition to the PGD. + */ +#define KVM_MMU_CACHE_MIN_PAGES (STAGE2_PGTABLE_LEVELS - 1) + + +#if STAGE2_PGTABLE_LEVELS > 3 + +#define S2_PUD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(1) +#define S2_PUD_SIZE (_AC(1, UL) << S2_PUD_SHIFT) +#define S2_PUD_MASK (~(S2_PUD_SIZE - 1)) + #define stage2_pgd_none(pgd) pgd_none(pgd) #define stage2_pgd_clear(pgd) pgd_clear(pgd) #define stage2_pgd_present(pgd) pgd_present(pgd) @@ -55,6 +84,24 @@ #define stage2_pud_offset(pgd, address) pud_offset(pgd, address) #define stage2_pud_free(pud) pud_free(NULL, pud) +#define stage2_pud_table_empty(pudp) kvm_page_empty(pudp) + +static inline phys_addr_t stage2_pud_addr_end(phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t boundary = (addr + S2_PUD_SIZE) & S2_PUD_MASK; + + return (boundary - 1 < end - 1) ? boundary : end; +} + +#endif /* STAGE2_PGTABLE_LEVELS > 3 */ + + +#if STAGE2_PGTABLE_LEVELS > 2 + +#define S2_PMD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(2) +#define S2_PMD_SIZE (_AC(1, UL) << S2_PMD_SHIFT) +#define S2_PMD_MASK (~(S2_PMD_SIZE - 1)) + #define stage2_pud_none(pud) pud_none(pud) #define stage2_pud_clear(pud) pud_clear(pud) #define stage2_pud_present(pud) pud_present(pud) @@ -63,24 +110,33 @@ #define stage2_pmd_free(pmd) pmd_free(NULL, pmd) #define stage2_pud_huge(pud) pud_huge(pud) +#define stage2_pmd_table_empty(pmdp) kvm_page_empty(pmdp) + +static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t boundary = (addr + S2_PMD_SIZE) & S2_PMD_MASK; -#define stage2_pgd_addr_end(address, end) pgd_addr_end(address, end) -#define stage2_pud_addr_end(address, end) pud_addr_end(address, end) -#define stage2_pmd_addr_end(address, end) pmd_addr_end(address, end) + return (boundary - 1 < end - 1) ? boundary : end; +} + +#endif /* STAGE2_PGTABLE_LEVELS > 2 */ #define stage2_pte_table_empty(ptep) kvm_page_empty(ptep) -#ifdef __PGTABLE_PMD_FOLDED -#define stage2_pmd_table_empty(pmdp) (0) -#else -#define stage2_pmd_table_empty(pmdp) ((KVM_PREALLOC_LEVEL < 2) && kvm_page_empty(pmdp)) -#endif -#ifdef __PGTABLE_PUD_FOLDED -#define stage2_pud_table_empty(pudp) (0) -#else -#define stage2_pud_table_empty(pudp) ((KVM_PREALLOC_LEVEL < 1) && kvm_page_empty(pudp)) +#if STAGE2_PGTABLE_LEVELS == 2 +#include +#elif STAGE2_PGTABLE_LEVELS == 3 +#include #endif -#define stage2_pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) + +#define stage2_pgd_index(addr) (((addr) >> S2_PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) + +static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t boundary = (addr + S2_PGDIR_SIZE) & S2_PGDIR_MASK; + + return (boundary - 1 < end - 1) ? boundary : end; +} #endif /* __ARM64_S2_PGTABLE_H_ */ -- GitLab From 9163ee23e72333e4712f7edd1a49aef06eae6304 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Mar 2016 17:01:21 +0000 Subject: [PATCH 3856/9938] kvm-arm: Cleanup stage2 pgd handling Now that we don't have any fake page table levels for arm64, cleanup the common code to get rid of the dead code. Cc: Marc Zyngier Acked-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm/include/asm/kvm_mmu.h | 19 ---------------- arch/arm/kvm/arm.c | 2 +- arch/arm/kvm/mmu.c | 37 ++++++-------------------------- arch/arm64/include/asm/kvm_mmu.h | 18 ---------------- 4 files changed, 7 insertions(+), 69 deletions(-) diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index a7736d53a408..6344ea0ad624 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -150,25 +150,6 @@ static inline bool kvm_page_empty(void *ptr) #define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp) #define hyp_pud_table_empty(pudp) false -static inline void *kvm_get_hwpgd(struct kvm *kvm) -{ - return kvm->arch.pgd; -} - -static inline unsigned int kvm_get_hwpgd_size(void) -{ - return PTRS_PER_S2_PGD * sizeof(pgd_t); -} - -static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd) -{ - return hwpgd; -} - -static inline void kvm_free_fake_pgd(pgd_t *pgd) -{ -} - struct kvm; #define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index dded1b763c16..be4b6394a062 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -448,7 +448,7 @@ static void update_vttbr(struct kvm *kvm) kvm_next_vmid &= (1 << kvm_vmid_bits) - 1; /* update vttbr to be used with the new vmid */ - pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm)); + pgd_phys = virt_to_phys(kvm->arch.pgd); BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits); kvm->arch.vttbr = pgd_phys | vmid; diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index d3fa96e0f709..42eefab3e8e1 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -43,6 +43,7 @@ static unsigned long hyp_idmap_start; static unsigned long hyp_idmap_end; static phys_addr_t hyp_idmap_vector; +#define S2_PGD_SIZE (PTRS_PER_S2_PGD * sizeof(pgd_t)) #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t)) #define KVM_S2PTE_FLAG_IS_IOMAP (1UL << 0) @@ -736,20 +737,6 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr) __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE); } -/* Free the HW pgd, one page at a time */ -static void kvm_free_hwpgd(void *hwpgd) -{ - free_pages_exact(hwpgd, kvm_get_hwpgd_size()); -} - -/* Allocate the HW PGD, making sure that each page gets its own refcount */ -static void *kvm_alloc_hwpgd(void) -{ - unsigned int size = kvm_get_hwpgd_size(); - - return alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); -} - /** * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation. * @kvm: The KVM struct pointer for the VM. @@ -764,29 +751,17 @@ static void *kvm_alloc_hwpgd(void) int kvm_alloc_stage2_pgd(struct kvm *kvm) { pgd_t *pgd; - void *hwpgd; if (kvm->arch.pgd != NULL) { kvm_err("kvm_arch already initialized?\n"); return -EINVAL; } - hwpgd = kvm_alloc_hwpgd(); - if (!hwpgd) + /* Allocate the HW PGD, making sure that each page gets its own refcount */ + pgd = alloc_pages_exact(S2_PGD_SIZE, GFP_KERNEL | __GFP_ZERO); + if (!pgd) return -ENOMEM; - /* - * When the kernel uses more levels of page tables than the - * guest, we allocate a fake PGD and pre-populate it to point - * to the next-level page table, which will be the real - * initial page table pointed to by the VTTBR. - */ - pgd = kvm_setup_fake_pgd(hwpgd); - if (IS_ERR(pgd)) { - kvm_free_hwpgd(hwpgd); - return PTR_ERR(pgd); - } - kvm_clean_pgd(pgd); kvm->arch.pgd = pgd; return 0; @@ -874,8 +849,8 @@ void kvm_free_stage2_pgd(struct kvm *kvm) return; unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); - kvm_free_hwpgd(kvm_get_hwpgd(kvm)); - kvm_free_fake_pgd(kvm->arch.pgd); + /* Free the HW pgd, one page at a time */ + free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE); kvm->arch.pgd = NULL; } diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index e3fee0acd1a2..249c4fc9c5f6 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -141,24 +141,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd) return (pmd_val(*pmd) & PMD_S2_RDWR) == PMD_S2_RDONLY; } -static inline void *kvm_get_hwpgd(struct kvm *kvm) -{ - return kvm->arch.pgd; -} - -static inline unsigned int kvm_get_hwpgd_size(void) -{ - return PTRS_PER_S2_PGD * sizeof(pgd_t); -} - -static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd) -{ - return hwpgd; -} - -static inline void kvm_free_fake_pgd(pgd_t *pgd) -{ -} static inline bool kvm_page_empty(void *ptr) { struct page *ptr_page = virt_to_page(ptr); -- GitLab From 02e0b7600f8350078f01328095c20dd715700921 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Thu, 17 Mar 2016 14:29:24 +0000 Subject: [PATCH 3857/9938] arm64: kvm: Add support for 16K pages Now that we can handle stage-2 page tables independent of the host page table levels, wire up the 16K page support. Cc: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/kvm_arm.h | 13 +++++++++++-- arch/arm64/kvm/Kconfig | 1 - 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 1281d98392a0..c6cbb361bbcf 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -114,6 +114,7 @@ #define VTCR_EL2_PS_MASK TCR_EL2_PS_MASK #define VTCR_EL2_TG0_MASK TCR_TG0_MASK #define VTCR_EL2_TG0_4K TCR_TG0_4K +#define VTCR_EL2_TG0_16K TCR_TG0_16K #define VTCR_EL2_TG0_64K TCR_TG0_64K #define VTCR_EL2_SH0_MASK TCR_SH0_MASK #define VTCR_EL2_SH0_INNER TCR_SH0_INNER @@ -139,7 +140,7 @@ * (see hyp-init.S). * * Note that when using 4K pages, we concatenate two first level page tables - * together. + * together. With 16K pages, we concatenate 16 first level page tables. * * The magic numbers used for VTTBR_X in this patch can be found in Tables * D4-23 and D4-25 in ARM DDI 0487A.b. @@ -157,7 +158,15 @@ */ #define VTCR_EL2_TGRAN_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SL0_LVL1) #define VTTBR_X_TGRAN_MAGIC 38 -#else +#elif defined(CONFIG_ARM64_16K_PAGES) +/* + * Stage2 translation configuration: + * 16kB pages (TG0 = 2) + * 2 level page tables (SL = 1) + */ +#define VTCR_EL2_TGRAN_FLAGS (VTCR_EL2_TG0_16K | VTCR_EL2_SL0_LVL1) +#define VTTBR_X_TGRAN_MAGIC 42 +#else /* 4K */ /* * Stage2 translation configuration: * 4kB pages (TG0 = 0) diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index de7450df7629..aa2e34e99582 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -22,7 +22,6 @@ config KVM_ARM_VGIC_V3 config KVM bool "Kernel-based Virtual Machine (KVM) support" depends on OF - depends on !ARM64_16K_PAGES select MMU_NOTIFIER select PREEMPT_NOTIFIERS select ANON_INODES -- GitLab From 8ed8ab40047a570fdd8043a40c104a57248dd3fd Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Fri, 15 Apr 2016 22:48:02 +1000 Subject: [PATCH 3858/9938] powerpc/book3s64: Fix branching to OOL handlers in relocatable kernel Some of the interrupt vectors on 64-bit POWER server processors are only 32 bytes long (8 instructions), which is not enough for the full first-level interrupt handler. For these we need to branch to an out-of-line (OOL) handler. But when we are running a relocatable kernel, interrupt vectors till __end_interrupts marker are copied down to real address 0x100. So, branching to labels (ie. OOL handlers) outside this section must be handled differently (see LOAD_HANDLER()), considering relocatable kernel, which would need at least 4 instructions. However, branching from interrupt vector means that we corrupt the CFAR (come-from address register) on POWER7 and later processors as mentioned in commit 1707dd16. So, EXCEPTION_PROLOG_0 (6 instructions) that contains the part up to the point where the CFAR is saved in the PACA should be part of the short interrupt vectors before we branch out to OOL handlers. But as mentioned already, there are interrupt vectors on 64-bit POWER server processors that are only 32 bytes long (like vectors 0x4f00, 0x4f20, etc.), which cannot accomodate the above two cases at the same time owing to space constraint. Currently, in these interrupt vectors, we simply branch out to OOL handlers, without using LOAD_HANDLER(), which leaves us vulnerable when running a relocatable kernel (eg. kdump case). While this has been the case for sometime now and kdump is used widely, we were fortunate not to see any problems so far, for three reasons: 1. In almost all cases, production kernel (relocatable) is used for kdump as well, which would mean that crashed kernel's OOL handler would be at the same place where we end up branching to, from short interrupt vector of kdump kernel. 2. Also, OOL handler was unlikely the reason for crash in almost all the kdump scenarios, which meant we had a sane OOL handler from crashed kernel that we branched to. 3. On most 64-bit POWER server processors, page size is large enough that marking interrupt vector code as executable (see commit 429d2e83) leads to marking OOL handler code from crashed kernel, that sits right below interrupt vector code from kdump kernel, as executable as well. Let us fix this by moving the __end_interrupts marker down past OOL handlers to make sure that we also copy OOL handlers to real address 0x100 when running a relocatable kernel. This fix has been tested successfully in kdump scenario, on an LPAR with 4K page size by using different default/production kernel and kdump kernel. Also tested by manually corrupting the OOL handlers in the first kernel and then kdump'ing, and then causing the OOL handlers to fire - mpe. Fixes: c1fb6816fb1b ("powerpc: Add relocation on exception vector handlers") Cc: stable@vger.kernel.org Signed-off-by: Hari Bathini Signed-off-by: Mahesh Salgaonkar Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/exceptions-64s.S | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index e0e1ff463556..b952173da029 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -915,11 +915,6 @@ hv_facility_unavailable_relon_trampoline: #endif STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist) - /* Other future vectors */ - .align 7 - .globl __end_interrupts -__end_interrupts: - .align 7 system_call_entry: b system_call_common @@ -1142,6 +1137,17 @@ __end_handlers: STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable) STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable) + /* + * The __end_interrupts marker must be past the out-of-line (OOL) + * handlers, so that they are copied to real address 0x100 when running + * a relocatable kernel. This ensures they can be reached from the short + * trampoline handlers (like 0x4f00, 0x4f20, etc.) which branch + * directly, without using LOAD_HANDLER(). + */ + .align 7 + .globl __end_interrupts +__end_interrupts: + #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) /* * Data area reserved for FWNMI option. -- GitLab From 057b6d7e62ea4e6b1809e2946929d0d586cad142 Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Fri, 8 Apr 2016 03:30:34 +0530 Subject: [PATCH 3859/9938] powerpc/book3s64: Remove __end_handlers marker The __end_handlers marker was intended to mark down upto code that gets called from exception prologs. But that hasn't kept pace with code changes. Case in point, slb_miss_realmode being called from exception prolog code but isn't below __end_handlers marker. So, __end_handlers marker is as good as a comment but could be misleading at times if it isn't in sync with the code, as is the case now. So, let us avoid this confusion by having a better comment and removing __end_handlers marker altogether. Signed-off-by: Hari Bathini Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/exceptions-64s.S | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index b952173da029..52d2d742f6e7 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -726,11 +726,10 @@ kvmppc_skip_Hinterrupt: #endif /* - * Code from here down to __end_handlers is invoked from the - * exception prologs above. Because the prologs assemble the - * addresses of these handlers using the LOAD_HANDLER macro, - * which uses an ori instruction, these handlers must be in - * the first 64k of the kernel image. + * Ensure that any handlers that get invoked from the exception prologs + * above are below the first 64KB (0x10000) of the kernel image because + * the prologs assemble the addresses of these handlers using the + * LOAD_HANDLER macro, which uses an ori instruction. */ /*** Common interrupt handlers ***/ @@ -1123,10 +1122,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) STD_EXCEPTION_COMMON(0xf60, facility_unavailable, facility_unavailable_exception) STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, facility_unavailable_exception) - .align 7 - .globl __end_handlers -__end_handlers: - /* Equivalents to the above handlers for relocation-on interrupt vectors */ STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist) MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell) -- GitLab From 1bfadabfebc671a6af0f5008b524b681ce757dec Mon Sep 17 00:00:00 2001 From: Anju T Date: Sat, 20 Feb 2016 10:32:45 +0530 Subject: [PATCH 3860/9938] powerpc/perf: Assign an id to each powerpc register The enum definition assigns an 'id' to each register in "struct pt_regs" of arch/powerpc. The order of these values in the enum definition are based on the order of members in pt_regs. Signed-off-by: Anju T [mpe: Rename LNK to LINK, use _UAPI_ASM for include guards] Signed-off-by: Michael Ellerman --- arch/powerpc/include/uapi/asm/perf_regs.h | 50 +++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 arch/powerpc/include/uapi/asm/perf_regs.h diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h b/arch/powerpc/include/uapi/asm/perf_regs.h new file mode 100644 index 000000000000..6a93209748a1 --- /dev/null +++ b/arch/powerpc/include/uapi/asm/perf_regs.h @@ -0,0 +1,50 @@ +#ifndef _UAPI_ASM_POWERPC_PERF_REGS_H +#define _UAPI_ASM_POWERPC_PERF_REGS_H + +enum perf_event_powerpc_regs { + PERF_REG_POWERPC_R0, + PERF_REG_POWERPC_R1, + PERF_REG_POWERPC_R2, + PERF_REG_POWERPC_R3, + PERF_REG_POWERPC_R4, + PERF_REG_POWERPC_R5, + PERF_REG_POWERPC_R6, + PERF_REG_POWERPC_R7, + PERF_REG_POWERPC_R8, + PERF_REG_POWERPC_R9, + PERF_REG_POWERPC_R10, + PERF_REG_POWERPC_R11, + PERF_REG_POWERPC_R12, + PERF_REG_POWERPC_R13, + PERF_REG_POWERPC_R14, + PERF_REG_POWERPC_R15, + PERF_REG_POWERPC_R16, + PERF_REG_POWERPC_R17, + PERF_REG_POWERPC_R18, + PERF_REG_POWERPC_R19, + PERF_REG_POWERPC_R20, + PERF_REG_POWERPC_R21, + PERF_REG_POWERPC_R22, + PERF_REG_POWERPC_R23, + PERF_REG_POWERPC_R24, + PERF_REG_POWERPC_R25, + PERF_REG_POWERPC_R26, + PERF_REG_POWERPC_R27, + PERF_REG_POWERPC_R28, + PERF_REG_POWERPC_R29, + PERF_REG_POWERPC_R30, + PERF_REG_POWERPC_R31, + PERF_REG_POWERPC_NIP, + PERF_REG_POWERPC_MSR, + PERF_REG_POWERPC_ORIG_R3, + PERF_REG_POWERPC_CTR, + PERF_REG_POWERPC_LINK, + PERF_REG_POWERPC_XER, + PERF_REG_POWERPC_CCR, + PERF_REG_POWERPC_SOFTE, + PERF_REG_POWERPC_TRAP, + PERF_REG_POWERPC_DAR, + PERF_REG_POWERPC_DSISR, + PERF_REG_POWERPC_MAX, +}; +#endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ -- GitLab From ed4a4ef85cf5b75231079501030db28dd59f920a Mon Sep 17 00:00:00 2001 From: Anju T Date: Sat, 20 Feb 2016 10:32:46 +0530 Subject: [PATCH 3861/9938] powerpc/perf: Add support for sampling interrupt register state The perf infrastructure uses a bit mask to find out valid registers to display. Define a register mask for supported registers defined in uapi/asm/perf_regs.h. The bit positions also correspond to register IDs which is used by perf infrastructure to fetch the register values. CONFIG_HAVE_PERF_REGS enables sampling of the interrupted machine state. Signed-off-by: Anju T [mpe: Add license, use CONFIG_PPC64, fix 32-bit build] Signed-off-by: Michael Ellerman --- arch/powerpc/Kconfig | 1 + arch/powerpc/perf/Makefile | 2 +- arch/powerpc/perf/perf_regs.c | 104 ++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/perf/perf_regs.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 9b5c7bcc06c4..b14966d67149 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -116,6 +116,7 @@ config PPC select GENERIC_ATOMIC64 if PPC32 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_PERF_EVENTS + select HAVE_PERF_REGS select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64 select ARCH_WANT_IPC_PARSE_VERSION diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index f9c083a5652a..77b6394a7c50 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile @@ -1,6 +1,6 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror -obj-$(CONFIG_PERF_EVENTS) += callchain.o +obj-$(CONFIG_PERF_EVENTS) += callchain.o perf_regs.o obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o bhrb.o obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c new file mode 100644 index 000000000000..d24a8a3668fa --- /dev/null +++ b/arch/powerpc/perf/perf_regs.c @@ -0,0 +1,104 @@ +/* + * Copyright 2016 Anju T, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) + +#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1)) + +static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { + PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R1, gpr[1]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R2, gpr[2]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R3, gpr[3]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R4, gpr[4]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R5, gpr[5]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R6, gpr[6]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R7, gpr[7]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R8, gpr[8]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R9, gpr[9]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R10, gpr[10]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R11, gpr[11]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R12, gpr[12]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R13, gpr[13]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R14, gpr[14]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R15, gpr[15]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R16, gpr[16]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R17, gpr[17]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R18, gpr[18]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R19, gpr[19]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R20, gpr[20]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R21, gpr[21]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R22, gpr[22]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R23, gpr[23]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R24, gpr[24]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R25, gpr[25]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R26, gpr[26]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R27, gpr[27]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R28, gpr[28]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R29, gpr[29]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R30, gpr[30]), + PT_REGS_OFFSET(PERF_REG_POWERPC_R31, gpr[31]), + PT_REGS_OFFSET(PERF_REG_POWERPC_NIP, nip), + PT_REGS_OFFSET(PERF_REG_POWERPC_MSR, msr), + PT_REGS_OFFSET(PERF_REG_POWERPC_ORIG_R3, orig_gpr3), + PT_REGS_OFFSET(PERF_REG_POWERPC_CTR, ctr), + PT_REGS_OFFSET(PERF_REG_POWERPC_LINK, link), + PT_REGS_OFFSET(PERF_REG_POWERPC_XER, xer), + PT_REGS_OFFSET(PERF_REG_POWERPC_CCR, ccr), +#ifdef CONFIG_PPC64 + PT_REGS_OFFSET(PERF_REG_POWERPC_SOFTE, softe), +#else + PT_REGS_OFFSET(PERF_REG_POWERPC_SOFTE, mq), +#endif + PT_REGS_OFFSET(PERF_REG_POWERPC_TRAP, trap), + PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar), + PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr), +}; + +u64 perf_reg_value(struct pt_regs *regs, int idx) +{ + if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX)) + return 0; + + return regs_get_register(regs, pt_regs_offset[idx]); +} + +int perf_reg_validate(u64 mask) +{ + if (!mask || mask & REG_RESERVED) + return -EINVAL; + return 0; +} + +u64 perf_reg_abi(struct task_struct *task) +{ +#ifdef CONFIG_PPC64 + if (!test_tsk_thread_flag(task, TIF_32BIT)) + return PERF_SAMPLE_REGS_ABI_64; + else +#endif + return PERF_SAMPLE_REGS_ABI_32; +} + +void perf_get_regs_user(struct perf_regs *regs_user, + struct pt_regs *regs, + struct pt_regs *regs_user_copy) +{ + regs_user->regs = task_pt_regs(current); + regs_user->abi = perf_reg_abi(current); +} -- GitLab From dc642e8388b63a9a221903584bb6b562e5055d0d Mon Sep 17 00:00:00 2001 From: Anju T Date: Sat, 20 Feb 2016 10:32:47 +0530 Subject: [PATCH 3862/9938] tools/perf: Map the ID values with register names Map ID values with corresponding register names. These names are then displayed when user issues perf record with the -I option followed by perf report/script with -D option. To test this patchset, Eg: $ perf record -I ls # record machine state at interrupt $ perf script -D # read the perf.data file Sample output obtained for this patch / output looks like as follows: 496768515470 0x1988 [0x188]: PERF_RECORD_SAMPLE(IP, 0x1): 4522/4522: 0xc0000000001e538c period: 1 addr: 0 ... intr regs: mask 0x7ffffffffff ABI 64-bit .... r0 0xc0000000001e5e34 .... r1 0xc000000fe733f9a0 .... r2 0xc000000001523100 .... r3 0xc000000ffaadeb60 .... r4 0xc000000003456800 .... r5 0x73a9b5e000 .... r6 0x1e000000 .... r7 0x0 .... r8 0x0 .... r9 0x0 .... r10 0x1 .... r11 0x0 .... r12 0x24022822 .... r13 0xc00000000feec180 .... r14 0x0 .... r15 0xc000001e4be18800 .... r16 0x0 .... r17 0xc000000ffaac5000 .... r18 0xc000000fe733f8a0 .... r19 0xc000000001523100 .... r20 0xc00000000009fd1c .... r21 0xc000000fcaa69000 .... r22 0xc0000000001e4968 .... r23 0xc000000001523100 .... r24 0xc000000fe733f850 .... r25 0xc000000fcaa69000 .... r26 0xc000000003b8fcf0 .... r27 0xfffffffffffffead .... r28 0x0 .... r29 0xc000000fcaa69000 .... r30 0x1 .... r31 0x0 .... nip 0xc0000000001dd320 .... msr 0x9000000000009032 .... orig_r3 0xc0000000001e538c .... ctr 0xc00000000009d550 .... link 0xc0000000001e5e34 .... xer 0x0 .... ccr 0x84022882 .... softe 0x0 .... trap 0xf01 .... dar 0x0 .... dsisr 0xf00040060000004 ... thread: :4522:4522 ...... dso: /root/.debug/.build-id/b0/ef11b1a1629e62ac9de75199117ee5ef9469e9 :4522 4522 496.768515: 1 cycles: c0000000001e538c .perf_event_context_sched_in (/boot/vmlinux) Signed-off-by: Anju T Acked-by: Arnaldo Carvalho de Melo Signed-off-by: Michael Ellerman --- tools/perf/arch/powerpc/include/perf_regs.h | 69 +++++++++++++++++++++ tools/perf/config/Makefile | 5 ++ 2 files changed, 74 insertions(+) create mode 100644 tools/perf/arch/powerpc/include/perf_regs.h diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h new file mode 100644 index 000000000000..75de0e92e71e --- /dev/null +++ b/tools/perf/arch/powerpc/include/perf_regs.h @@ -0,0 +1,69 @@ +#ifndef ARCH_PERF_REGS_H +#define ARCH_PERF_REGS_H + +#include +#include +#include + +#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) +#define PERF_REGS_MAX PERF_REG_POWERPC_MAX +#ifdef __powerpc64__ + #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64 +#else + #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32 +#endif + +#define PERF_REG_IP PERF_REG_POWERPC_NIP +#define PERF_REG_SP PERF_REG_POWERPC_R1 + +static const char *reg_names[] = { + [PERF_REG_POWERPC_R0] = "r0", + [PERF_REG_POWERPC_R1] = "r1", + [PERF_REG_POWERPC_R2] = "r2", + [PERF_REG_POWERPC_R3] = "r3", + [PERF_REG_POWERPC_R4] = "r4", + [PERF_REG_POWERPC_R5] = "r5", + [PERF_REG_POWERPC_R6] = "r6", + [PERF_REG_POWERPC_R7] = "r7", + [PERF_REG_POWERPC_R8] = "r8", + [PERF_REG_POWERPC_R9] = "r9", + [PERF_REG_POWERPC_R10] = "r10", + [PERF_REG_POWERPC_R11] = "r11", + [PERF_REG_POWERPC_R12] = "r12", + [PERF_REG_POWERPC_R13] = "r13", + [PERF_REG_POWERPC_R14] = "r14", + [PERF_REG_POWERPC_R15] = "r15", + [PERF_REG_POWERPC_R16] = "r16", + [PERF_REG_POWERPC_R17] = "r17", + [PERF_REG_POWERPC_R18] = "r18", + [PERF_REG_POWERPC_R19] = "r19", + [PERF_REG_POWERPC_R20] = "r20", + [PERF_REG_POWERPC_R21] = "r21", + [PERF_REG_POWERPC_R22] = "r22", + [PERF_REG_POWERPC_R23] = "r23", + [PERF_REG_POWERPC_R24] = "r24", + [PERF_REG_POWERPC_R25] = "r25", + [PERF_REG_POWERPC_R26] = "r26", + [PERF_REG_POWERPC_R27] = "r27", + [PERF_REG_POWERPC_R28] = "r28", + [PERF_REG_POWERPC_R29] = "r29", + [PERF_REG_POWERPC_R30] = "r30", + [PERF_REG_POWERPC_R31] = "r31", + [PERF_REG_POWERPC_NIP] = "nip", + [PERF_REG_POWERPC_MSR] = "msr", + [PERF_REG_POWERPC_ORIG_R3] = "orig_r3", + [PERF_REG_POWERPC_CTR] = "ctr", + [PERF_REG_POWERPC_LINK] = "link", + [PERF_REG_POWERPC_XER] = "xer", + [PERF_REG_POWERPC_CCR] = "ccr", + [PERF_REG_POWERPC_SOFTE] = "softe", + [PERF_REG_POWERPC_TRAP] = "trap", + [PERF_REG_POWERPC_DAR] = "dar", + [PERF_REG_POWERPC_DSISR] = "dsisr" +}; + +static inline const char *perf_reg_name(int id) +{ + return reg_names[id]; +} +#endif /* ARCH_PERF_REGS_H */ diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index f7d7f5a1cad5..eda1cfbbfb2d 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -23,6 +23,11 @@ $(call detected_var,ARCH) NO_PERF_REGS := 1 +# Additional ARCH settings for ppc +ifeq ($(ARCH),powerpc) + NO_PERF_REGS := 0 +endif + # Additional ARCH settings for x86 ifeq ($(ARCH),x86) $(call detected,CONFIG_X86) -- GitLab From bb62bad623deb7952aef13fcbe065fde5d1f03e5 Mon Sep 17 00:00:00 2001 From: Madhavan Srinivasan Date: Sat, 20 Feb 2016 10:32:48 +0530 Subject: [PATCH 3863/9938] tool/perf: Add sample_reg_mask to include all perf_regs Add sample_reg_mask array with pt_regs registers. This is needed for printing supported regs ( -I? option). Signed-off-by: Madhavan Srinivasan Acked-by: Arnaldo Carvalho de Melo Signed-off-by: Michael Ellerman --- tools/perf/arch/powerpc/util/Build | 1 + tools/perf/arch/powerpc/util/perf_regs.c | 49 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tools/perf/arch/powerpc/util/perf_regs.c diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build index c8fe2074d217..9ee335016592 100644 --- a/tools/perf/arch/powerpc/util/Build +++ b/tools/perf/arch/powerpc/util/Build @@ -1,6 +1,7 @@ libperf-y += header.o libperf-y += sym-handling.o libperf-y += kvm-stat.o +libperf-y += perf_regs.o libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_DWARF) += skip-callchain-idx.o diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c new file mode 100644 index 000000000000..a3c3e1ce6807 --- /dev/null +++ b/tools/perf/arch/powerpc/util/perf_regs.c @@ -0,0 +1,49 @@ +#include "../../perf.h" +#include "../../util/perf_regs.h" + +const struct sample_reg sample_reg_masks[] = { + SMPL_REG(r0, PERF_REG_POWERPC_R0), + SMPL_REG(r1, PERF_REG_POWERPC_R1), + SMPL_REG(r2, PERF_REG_POWERPC_R2), + SMPL_REG(r3, PERF_REG_POWERPC_R3), + SMPL_REG(r4, PERF_REG_POWERPC_R4), + SMPL_REG(r5, PERF_REG_POWERPC_R5), + SMPL_REG(r6, PERF_REG_POWERPC_R6), + SMPL_REG(r7, PERF_REG_POWERPC_R7), + SMPL_REG(r8, PERF_REG_POWERPC_R8), + SMPL_REG(r9, PERF_REG_POWERPC_R9), + SMPL_REG(r10, PERF_REG_POWERPC_R10), + SMPL_REG(r11, PERF_REG_POWERPC_R11), + SMPL_REG(r12, PERF_REG_POWERPC_R12), + SMPL_REG(r13, PERF_REG_POWERPC_R13), + SMPL_REG(r14, PERF_REG_POWERPC_R14), + SMPL_REG(r15, PERF_REG_POWERPC_R15), + SMPL_REG(r16, PERF_REG_POWERPC_R16), + SMPL_REG(r17, PERF_REG_POWERPC_R17), + SMPL_REG(r18, PERF_REG_POWERPC_R18), + SMPL_REG(r19, PERF_REG_POWERPC_R19), + SMPL_REG(r20, PERF_REG_POWERPC_R20), + SMPL_REG(r21, PERF_REG_POWERPC_R21), + SMPL_REG(r22, PERF_REG_POWERPC_R22), + SMPL_REG(r23, PERF_REG_POWERPC_R23), + SMPL_REG(r24, PERF_REG_POWERPC_R24), + SMPL_REG(r25, PERF_REG_POWERPC_R25), + SMPL_REG(r26, PERF_REG_POWERPC_R26), + SMPL_REG(r27, PERF_REG_POWERPC_R27), + SMPL_REG(r28, PERF_REG_POWERPC_R28), + SMPL_REG(r29, PERF_REG_POWERPC_R29), + SMPL_REG(r30, PERF_REG_POWERPC_R30), + SMPL_REG(r31, PERF_REG_POWERPC_R31), + SMPL_REG(nip, PERF_REG_POWERPC_NIP), + SMPL_REG(msr, PERF_REG_POWERPC_MSR), + SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3), + SMPL_REG(ctr, PERF_REG_POWERPC_CTR), + SMPL_REG(link, PERF_REG_POWERPC_LINK), + SMPL_REG(xer, PERF_REG_POWERPC_XER), + SMPL_REG(ccr, PERF_REG_POWERPC_CCR), + SMPL_REG(softe, PERF_REG_POWERPC_SOFTE), + SMPL_REG(trap, PERF_REG_POWERPC_TRAP), + SMPL_REG(dar, PERF_REG_POWERPC_DAR), + SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR), + SMPL_REG_END +}; -- GitLab From 962f5143b30568bf67be97365d0616b0050ddaa5 Mon Sep 17 00:00:00 2001 From: "dawei.chien@mediatek.com" Date: Tue, 15 Mar 2016 16:10:36 +0800 Subject: [PATCH 3864/9938] arm64: dts: mt8173: Add thermal zone node. This adds thermal zone node to Mediatek MT8173 dtsi file. Signed-off-by: Dawei Chien Acked-by: Eduardo Valentin Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 3bebe29ab192..05f89c4a5413 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -125,6 +125,49 @@ clock-output-names = "cpum_ck"; }; + thermal-zones { + cpu_thermal: cpu_thermal { + polling-delay-passive = <1000>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + thermal-sensors = <&thermal>; + sustainable-power = <1500>; /* milliwatts */ + + trips { + threshold: trip-point@0 { + temperature = <68000>; + hysteresis = <2000>; + type = "passive"; + }; + + target: trip-point@1 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit: cpu_crit@0 { + temperature = <115000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map@0 { + trip = <&target>; + cooling-device = <&cpu0 0 0>; + contribution = <1024>; + }; + map@1 { + trip = <&target>; + cooling-device = <&cpu2 0 0>; + contribution = <2048>; + }; + }; + }; + }; + timer { compatible = "arm,armv8-timer"; interrupt-parent = <&gic>; -- GitLab From 8e42db1eaab6c2558dbc2e6c1428730df0a295f4 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Thu, 21 Apr 2016 14:04:14 +0100 Subject: [PATCH 3865/9938] ASoC: arizona: Prefer lower FRATIO in pseudo-fractional mode When setting up an FLL in pseudo-fractional mode it is preferred to use a lower FRATIO if possible to give a higher reference clock frequency. This patch swaps the two loops in arizona_calc_fratio() so that lower FRATIOs are tried first. The decrementing loop is also changed to start from init_ratio because the original settings might already give a fractional value for N.K Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index d8a682302580..0caecc6f78df 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -2037,7 +2037,21 @@ static int arizona_calc_fratio(struct arizona_fll *fll, init_ratio, Fref, refdiv); while (div <= ARIZONA_FLL_MAX_REFDIV) { - for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; + /* start from init_ratio because this may already give a + * fractional N.K + */ + for (ratio = init_ratio; ratio > 0; ratio--) { + if (target % (ratio * Fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + arizona_fll_dbg(fll, + "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n", + Fref, refdiv, div, ratio); + return ratio; + } + } + + for (ratio = init_ratio + 1; ratio <= ARIZONA_FLL_MAX_FRATIO; ratio++) { if ((ARIZONA_FLL_VCO_CORNER / 2) / (fll->vco_mult * ratio) < Fref) { @@ -2063,17 +2077,6 @@ static int arizona_calc_fratio(struct arizona_fll *fll, } } - for (ratio = init_ratio - 1; ratio > 0; ratio--) { - if (target % (ratio * Fref)) { - cfg->refdiv = refdiv; - cfg->fratio = ratio - 1; - arizona_fll_dbg(fll, - "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n", - Fref, refdiv, div, ratio); - return ratio; - } - } - div *= 2; Fref /= 2; refdiv++; -- GitLab From d349caeb05104ef01392abc6c7cfc8ab516c7be4 Mon Sep 17 00:00:00 2001 From: PC Liao Date: Thu, 21 Apr 2016 19:38:14 +0800 Subject: [PATCH 3866/9938] ASoC: mediatek: Add second I2S on mt8173-rt5650 machine driver This patch adds second I2S connection to rt5650 codec for capture path on mt8173-rt5650 machine driver. Signed-off-by: PC Liao Signed-off-by: Mark Brown --- .../bindings/sound/mt8173-rt5650.txt | 10 ++++ sound/soc/mediatek/mt8173-rt5650.c | 50 +++++++++++++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt index fe5a5ef1714d..5bfa6b60530b 100644 --- a/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt +++ b/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt @@ -5,11 +5,21 @@ Required properties: - mediatek,audio-codec: the phandles of rt5650 codecs - mediatek,platform: the phandle of MT8173 ASoC platform +Optional subnodes: +- codec-capture : the subnode of rt5650 codec capture +Required codec-capture subnode properties: +- sound-dai: audio codec dai name on capture path + <&rt5650 0> : Default setting. Connect rt5650 I2S1 for capture. (dai_name = rt5645-aif1) + <&rt5650 1> : Connect rt5650 I2S2 for capture. (dai_name = rt5645-aif2) + Example: sound { compatible = "mediatek,mt8173-rt5650"; mediatek,audio-codec = <&rt5650>; mediatek,platform = <&afe>; + codec-capture { + sound-dai = <&rt5650 1>; + }; }; diff --git a/sound/soc/mediatek/mt8173-rt5650.c b/sound/soc/mediatek/mt8173-rt5650.c index bb09bb1b7f1c..a27a6673dbe3 100644 --- a/sound/soc/mediatek/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173-rt5650.c @@ -85,12 +85,29 @@ static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime) { struct snd_soc_card *card = runtime->card; struct snd_soc_codec *codec = runtime->codec_dais[0]->codec; + const char *codec_capture_dai = runtime->codec_dais[1]->name; int ret; rt5645_sel_asrc_clk_src(codec, - RT5645_DA_STEREO_FILTER | - RT5645_AD_STEREO_FILTER, + RT5645_DA_STEREO_FILTER, RT5645_CLK_SEL_I2S1_ASRC); + + if (!strcmp(codec_capture_dai, "rt5645-aif1")) { + rt5645_sel_asrc_clk_src(codec, + RT5645_AD_STEREO_FILTER, + RT5645_CLK_SEL_I2S1_ASRC); + } else if (!strcmp(codec_capture_dai, "rt5645-aif2")) { + rt5645_sel_asrc_clk_src(codec, + RT5645_AD_STEREO_FILTER, + RT5645_CLK_SEL_I2S2_ASRC); + } else { + dev_warn(card->dev, + "Only one dai codec found in DTS, enabled rt5645 AD filter\n"); + rt5645_sel_asrc_clk_src(codec, + RT5645_AD_STEREO_FILTER, + RT5645_CLK_SEL_I2S1_ASRC); + } + /* enable jack detection */ ret = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | @@ -110,6 +127,11 @@ static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime) static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = { { + /* Playback */ + .dai_name = "rt5645-aif1", + }, + { + /* Capture */ .dai_name = "rt5645-aif1", }, }; @@ -149,7 +171,7 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = { .cpu_dai_name = "I2S", .no_pcm = 1, .codecs = mt8173_rt5650_codecs, - .num_codecs = 1, + .num_codecs = 2, .init = mt8173_rt5650_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -177,6 +199,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) { struct snd_soc_card *card = &mt8173_rt5650_card; struct device_node *platform_node; + struct device_node *np; + const char *codec_capture_dai; int i, ret; platform_node = of_parse_phandle(pdev->dev.of_node, @@ -199,6 +223,26 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) "Property 'audio-codec' missing or invalid\n"); return -EINVAL; } + mt8173_rt5650_codecs[1].of_node = mt8173_rt5650_codecs[0].of_node; + + if (of_find_node_by_name(platform_node, "codec-capture")) { + np = of_get_child_by_name(pdev->dev.of_node, "codec-capture"); + if (!np) { + dev_err(&pdev->dev, + "%s: Can't find codec-capture DT node\n", + __func__); + return -EINVAL; + } + ret = snd_soc_of_get_dai_name(np, &codec_capture_dai); + if (ret < 0) { + dev_err(&pdev->dev, + "%s codec_capture_dai name fail %d\n", + __func__, ret); + return ret; + } + mt8173_rt5650_codecs[1].dai_name = codec_capture_dai; + } + card->dev = &pdev->dev; platform_set_drvdata(pdev, card); -- GitLab From 09305da97c7808b900985526aa9198233f32fb37 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Thu, 21 Apr 2016 11:45:22 +0530 Subject: [PATCH 3867/9938] ASoC: Intel: Skylake: Use UUID in binary format To avoid complex string manipulations with UUID in canonical form, use UUID in binary format. Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-sst-dsp.h | 2 +- sound/soc/intel/skylake/skl-sst.c | 9 ++++++--- sound/soc/intel/skylake/skl-topology.c | 6 ++---- sound/soc/intel/skylake/skl-topology.h | 2 +- sound/soc/intel/skylake/skl-tplg-interface.h | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index ff31e6615251..deabe7308d3b 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -118,7 +118,7 @@ struct skl_dsp_fw_ops { int (*set_state_D0)(struct sst_dsp *ctx); int (*set_state_D3)(struct sst_dsp *ctx); unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); - int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, char *mod_name); + int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name); int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id); }; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 348a734f8e24..bec4a7c486fd 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "../common/sst-dsp.h" #include "../common/sst-dsp-priv.h" #include "../common/sst-ipc.h" @@ -304,14 +305,16 @@ static int skl_transfer_module(struct sst_dsp *ctx, return ret; } -static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, char *guid) +static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) { struct skl_module_table *module_entry = NULL; int ret = 0; char mod_name[64]; /* guid str = 32 chars + 4 hyphens */ + uuid_le *uuid_mod; - snprintf(mod_name, sizeof(mod_name), "%s%s%s", - "intel/dsp_fw_", guid, ".bin"); + uuid_mod = (uuid_le *)guid; + snprintf(mod_name, sizeof(mod_name), "%s%pUL%s", + "intel/dsp_fw_", uuid_mod, ".bin"); module_entry = skl_module_get_from_id(ctx, mod_id); if (module_entry == NULL) { diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 545b4e77b8aa..4f27d82be0ed 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1550,6 +1550,8 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, return -ENOMEM; w->priv = mconfig; + memcpy(&mconfig->guid, &dfw_config->uuid, 16); + mconfig->id.module_id = dfw_config->module_id; mconfig->id.instance_id = dfw_config->instance_id; mconfig->mcps = dfw_config->max_mcps; @@ -1579,10 +1581,6 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, mconfig->time_slot = dfw_config->time_slot; mconfig->formats_config.caps_size = dfw_config->caps.caps_size; - if (dfw_config->is_loadable) - memcpy(mconfig->guid, dfw_config->uuid, - ARRAY_SIZE(dfw_config->uuid)); - mconfig->m_in_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) * sizeof(*mconfig->m_in_pin), GFP_KERNEL); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index de3c401284d9..22c913ddbab3 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -281,7 +281,7 @@ enum skl_module_state { }; struct skl_module_cfg { - char guid[SKL_UUID_STR_SZ]; + u8 guid[16]; struct skl_module_inst_id id; u8 domain; bool homogenous_inputs; diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 1db88a63ac17..a32e5e9cc530 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -181,7 +181,7 @@ struct skl_dfw_pipe { } __packed; struct skl_dfw_module { - char uuid[SKL_UUID_STR_SZ]; + u8 uuid[16]; u16 module_id; u16 instance_id; -- GitLab From c0133e3b0265341e7d62e150df18709af33c3a30 Mon Sep 17 00:00:00 2001 From: Koro Chen Date: Wed, 20 Apr 2016 10:59:56 +0200 Subject: [PATCH 3868/9938] ASoC: mediatek: Add HDMI dai-links in the mt8173-rt5650-rt5676 machine driver This creates pcmC0D2p for the HDMI playback in the same card. Signed-off-by: Koro Chen Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- .../bindings/sound/mt8173-rt5650-rt5676.txt | 5 ++-- sound/soc/mediatek/Kconfig | 1 + sound/soc/mediatek/mt8173-rt5650-rt5676.c | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt index f205ce9e31dd..ac28cdb4910e 100644 --- a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt +++ b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt @@ -1,15 +1,16 @@ -MT8173 with RT5650 RT5676 CODECS +MT8173 with RT5650 RT5676 CODECS and HDMI via I2S Required properties: - compatible : "mediatek,mt8173-rt5650-rt5676" - mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs + and of the hdmi encoder node - mediatek,platform: the phandle of MT8173 ASoC platform Example: sound { compatible = "mediatek,mt8173-rt5650-rt5676"; - mediatek,audio-codec = <&rt5650 &rt5676>; + mediatek,audio-codec = <&rt5650 &rt5676 &hdmi0>; mediatek,platform = <&afe>; }; diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index f7e789e97fbc..3abf51c07851 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -43,6 +43,7 @@ config SND_SOC_MT8173_RT5650_RT5676 depends on SND_SOC_MEDIATEK && I2C select SND_SOC_RT5645 select SND_SOC_RT5677 + select SND_SOC_HDMI_CODEC help This adds ASoC driver for Mediatek MT8173 boards with the RT5650 and RT5676 codecs. diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173-rt5650-rt5676.c index 5c4c58c69c51..bb593926c62d 100644 --- a/sound/soc/mediatek/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173-rt5650-rt5676.c @@ -134,7 +134,9 @@ static struct snd_soc_dai_link_component mt8173_rt5650_rt5676_codecs[] = { enum { DAI_LINK_PLAYBACK, DAI_LINK_CAPTURE, + DAI_LINK_HDMI, DAI_LINK_CODEC_I2S, + DAI_LINK_HDMI_I2S, DAI_LINK_INTERCODEC }; @@ -161,6 +163,16 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { .dynamic = 1, .dpcm_capture = 1, }, + [DAI_LINK_HDMI] = { + .name = "HDMI", + .stream_name = "HDMI PCM", + .cpu_dai_name = "HDMI", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dynamic = 1, + .dpcm_playback = 1, + }, /* Back End DAI links */ [DAI_LINK_CODEC_I2S] = { @@ -177,6 +189,13 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, }, + [DAI_LINK_HDMI_I2S] = { + .name = "HDMI BE", + .cpu_dai_name = "HDMIO", + .no_pcm = 1, + .codec_dai_name = "i2s-hifi", + .dpcm_playback = 1, + }, /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */ [DAI_LINK_INTERCODEC] = { .name = "rt5650_rt5676 intercodec", @@ -251,6 +270,14 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node = mt8173_rt5650_rt5676_codecs[1].of_node; + mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node = + of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 2); + if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); + return -EINVAL; + } + card->dev = &pdev->dev; platform_set_drvdata(pdev, card); -- GitLab From 81151cfb6bfe69f1c5a52b795eb005226a322c9e Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 20 Apr 2016 10:59:58 +0200 Subject: [PATCH 3869/9938] ASoC: hdmi-codec: Add ELD control ALSA doesn't know about all the different compressed audio formats, so there is no interface to let userspace enumerate the formats that are supported by the connected sink. Exporting the raw ELD bytes to userspace allows an application to select the appropriate audio format depending on the current capabilities of the connected HDMI sink device. Usually userspace then just pretends to ALSA that the data is in one of the raw 16-bit PCM audio formats and relies on the IEC controls to tell the sink how to interpret the data. Signed-off-by: Philipp Zabel Reviewed-by: Jyri Sarha Tested-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index b46b8edb9319..c78333b4311d 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -47,6 +47,42 @@ enum { DAI_ID_SPDIF, }; +static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); + + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = sizeof(hcp->eld); + + return 0; +} + +static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); + + mutex_lock(&hcp->eld_lock); + memcpy(ucontrol->value.bytes.data, hcp->eld, sizeof(hcp->eld)); + mutex_unlock(&hcp->eld_lock); + + return 0; +} + +static const struct snd_kcontrol_new hdmi_controls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "ELD", + .info = hdmi_eld_ctl_info, + .get = hdmi_eld_ctl_get, + }, +}; + static int hdmi_codec_new_stream(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -312,6 +348,8 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { }; static struct snd_soc_codec_driver hdmi_codec = { + .controls = hdmi_controls, + .num_controls = ARRAY_SIZE(hdmi_controls), .dapm_widgets = hdmi_widgets, .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), .dapm_routes = hdmi_routes, -- GitLab From 9ee35e4c6f42e792974872ee1ec4115718ce05bc Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 21 Apr 2016 18:21:31 +0200 Subject: [PATCH 3870/9938] iommu/amd: Don't use IS_ERR_VALUE to check integer values Use the better 'var < 0' check. Fixes: 7aba6cb9ee9d ('iommu/amd: Make call-sites of get_device_id aware of its return value') Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 12f77798a0a4..a2a51c164c7f 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -354,7 +354,7 @@ static void init_unity_mappings_for_device(struct device *dev, int devid; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return; list_for_each_entry(e, &amd_iommu_unity_map, list) { @@ -376,7 +376,7 @@ static bool check_device(struct device *dev) return false; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return false; /* Out of our scope? */ @@ -419,7 +419,7 @@ static int iommu_init_device(struct device *dev) return 0; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return devid; dev_data = find_dev_data(devid); @@ -447,7 +447,7 @@ static void iommu_ignore_device(struct device *dev) int devid; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return; alias = amd_iommu_alias_table[devid]; @@ -465,7 +465,7 @@ static void iommu_uninit_device(struct device *dev) struct iommu_dev_data *dev_data; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return; dev_data = search_dev_data(devid); @@ -2414,7 +2414,7 @@ static int amd_iommu_add_device(struct device *dev) return 0; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return devid; iommu = amd_iommu_rlookup_table[devid]; @@ -2460,7 +2460,7 @@ static void amd_iommu_remove_device(struct device *dev) return; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return; iommu = amd_iommu_rlookup_table[devid]; @@ -3158,7 +3158,7 @@ static void amd_iommu_detach_device(struct iommu_domain *dom, return; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return; if (dev_data->domain != NULL) @@ -3280,7 +3280,7 @@ static void amd_iommu_get_dm_regions(struct device *dev, int devid; devid = get_device_id(dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return; list_for_each_entry(entry, &amd_iommu_unity_map, list) { @@ -3983,7 +3983,7 @@ static struct irq_domain *get_irq_domain(struct irq_alloc_info *info) case X86_IRQ_ALLOC_TYPE_MSI: case X86_IRQ_ALLOC_TYPE_MSIX: devid = get_device_id(&info->msi_dev->dev); - if (IS_ERR_VALUE(devid)) + if (devid < 0) return NULL; iommu = amd_iommu_rlookup_table[devid]; -- GitLab From fd6c50ee3af3935d8dfa38b0a81b2386fd915cfe Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 21 Apr 2016 18:24:02 +0200 Subject: [PATCH 3871/9938] iommu/amd: Move get_device_id() and friends to beginning of file They will be needed there later. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 108 +++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index a2a51c164c7f..119148552aa0 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -164,60 +164,6 @@ struct dma_ops_domain { * ****************************************************************************/ -static struct protection_domain *to_pdomain(struct iommu_domain *dom) -{ - return container_of(dom, struct protection_domain, domain); -} - -static struct iommu_dev_data *alloc_dev_data(u16 devid) -{ - struct iommu_dev_data *dev_data; - unsigned long flags; - - dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); - if (!dev_data) - return NULL; - - dev_data->devid = devid; - - spin_lock_irqsave(&dev_data_list_lock, flags); - list_add_tail(&dev_data->dev_data_list, &dev_data_list); - spin_unlock_irqrestore(&dev_data_list_lock, flags); - - return dev_data; -} - -static struct iommu_dev_data *search_dev_data(u16 devid) -{ - struct iommu_dev_data *dev_data; - unsigned long flags; - - spin_lock_irqsave(&dev_data_list_lock, flags); - list_for_each_entry(dev_data, &dev_data_list, dev_data_list) { - if (dev_data->devid == devid) - goto out_unlock; - } - - dev_data = NULL; - -out_unlock: - spin_unlock_irqrestore(&dev_data_list_lock, flags); - - return dev_data; -} - -static struct iommu_dev_data *find_dev_data(u16 devid) -{ - struct iommu_dev_data *dev_data; - - dev_data = search_dev_data(devid); - - if (dev_data == NULL) - dev_data = alloc_dev_data(devid); - - return dev_data; -} - static inline int match_hid_uid(struct device *dev, struct acpihid_map_entry *entry) { @@ -272,6 +218,60 @@ static inline int get_device_id(struct device *dev) return devid; } +static struct protection_domain *to_pdomain(struct iommu_domain *dom) +{ + return container_of(dom, struct protection_domain, domain); +} + +static struct iommu_dev_data *alloc_dev_data(u16 devid) +{ + struct iommu_dev_data *dev_data; + unsigned long flags; + + dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); + if (!dev_data) + return NULL; + + dev_data->devid = devid; + + spin_lock_irqsave(&dev_data_list_lock, flags); + list_add_tail(&dev_data->dev_data_list, &dev_data_list); + spin_unlock_irqrestore(&dev_data_list_lock, flags); + + return dev_data; +} + +static struct iommu_dev_data *search_dev_data(u16 devid) +{ + struct iommu_dev_data *dev_data; + unsigned long flags; + + spin_lock_irqsave(&dev_data_list_lock, flags); + list_for_each_entry(dev_data, &dev_data_list, dev_data_list) { + if (dev_data->devid == devid) + goto out_unlock; + } + + dev_data = NULL; + +out_unlock: + spin_unlock_irqrestore(&dev_data_list_lock, flags); + + return dev_data; +} + +static struct iommu_dev_data *find_dev_data(u16 devid) +{ + struct iommu_dev_data *dev_data; + + dev_data = search_dev_data(devid); + + if (dev_data == NULL) + dev_data = alloc_dev_data(devid); + + return dev_data; +} + static struct iommu_dev_data *get_dev_data(struct device *dev) { return dev->archdata.iommu; -- GitLab From 226d89cbb242f3fbd3e93367dfd5138f524aae5c Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 19 Apr 2016 17:01:31 +0100 Subject: [PATCH 3872/9938] arm64/dma-mapping: Extend DMA ops workaround to PCI devices PCI devices now suffer the same hiccup as platform devices, in that they get their DMA ops configured before they have been added to their bus, and thus before we know whether they have successfully registered with an IOMMU or not. Until the necessary driver core changes to reorder calls during device creation have been worked out, extend our delayed notifier trick onto the PCI bus so as to avoid broken DMA ops once IOMMUs get plugged into the PCI code. Acked-by: Catalin Marinas Signed-off-by: Robin Murphy Signed-off-by: Will Deacon --- arch/arm64/mm/dma-mapping.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index a6e757cbab77..607e70911173 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -933,6 +933,10 @@ static int __init __iommu_dma_init(void) ret = register_iommu_dma_ops_notifier(&platform_bus_type); if (!ret) ret = register_iommu_dma_ops_notifier(&amba_bustype); +#ifdef CONFIG_PCI + if (!ret) + ret = register_iommu_dma_ops_notifier(&pci_bus_type); +#endif /* handle devices queued before this arch_initcall */ if (!ret) -- GitLab From 921b1f52c942ad2da971c38f54a2045ec7cfe9cb Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 19 Apr 2016 17:01:32 +0100 Subject: [PATCH 3873/9938] arm64/dma-mapping: Remove default domain workaround With the IOMMU core now taking care of default domains for groups regardless of bus type, we can gleefully rip out this stop-gap, as slight recompense for having to expand the other one. Acked-by: Catalin Marinas Signed-off-by: Robin Murphy Signed-off-by: Will Deacon --- arch/arm64/mm/dma-mapping.c | 52 ++++++------------------------------- 1 file changed, 8 insertions(+), 44 deletions(-) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 607e70911173..fd8b9426f140 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -804,57 +804,24 @@ struct iommu_dma_notifier_data { static LIST_HEAD(iommu_dma_masters); static DEFINE_MUTEX(iommu_dma_notifier_lock); -/* - * Temporarily "borrow" a domain feature flag to to tell if we had to resort - * to creating our own domain here, in case we need to clean it up again. - */ -#define __IOMMU_DOMAIN_FAKE_DEFAULT (1U << 31) - static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops, u64 dma_base, u64 size) { struct iommu_domain *domain = iommu_get_domain_for_dev(dev); /* - * Best case: The device is either part of a group which was - * already attached to a domain in a previous call, or it's - * been put in a default DMA domain by the IOMMU core. + * If the IOMMU driver has the DMA domain support that we require, + * then the IOMMU core will have already configured a group for this + * device, and allocated the default domain for that group. */ - if (!domain) { - /* - * Urgh. The IOMMU core isn't going to do default domains - * for non-PCI devices anyway, until it has some means of - * abstracting the entirely implementation-specific - * sideband data/SoC topology/unicorn dust that may or - * may not differentiate upstream masters. - * So until then, HORRIBLE HACKS! - */ - domain = ops->domain_alloc(IOMMU_DOMAIN_DMA); - if (!domain) - goto out_no_domain; - - domain->ops = ops; - domain->type = IOMMU_DOMAIN_DMA | __IOMMU_DOMAIN_FAKE_DEFAULT; - - if (iommu_attach_device(domain, dev)) - goto out_put_domain; + if (!domain || iommu_dma_init_domain(domain, dma_base, size)) { + pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", + dev_name(dev)); + return false; } - if (iommu_dma_init_domain(domain, dma_base, size)) - goto out_detach; - dev->archdata.dma_ops = &iommu_dma_ops; return true; - -out_detach: - iommu_detach_device(domain, dev); -out_put_domain: - if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT) - iommu_domain_free(domain); -out_no_domain: - pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", - dev_name(dev)); - return false; } static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops, @@ -971,11 +938,8 @@ void arch_teardown_dma_ops(struct device *dev) { struct iommu_domain *domain = iommu_get_domain_for_dev(dev); - if (domain) { + if (WARN_ON(domain)) iommu_detach_device(domain, dev); - if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT) - iommu_domain_free(domain); - } dev->archdata.dma_ops = NULL; } -- GitLab From 0ae3aeefabbeef26294e7a349b51f1c761d46c9f Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 8 Apr 2016 13:10:23 +0200 Subject: [PATCH 3874/9938] PM / Runtime: Fix error path in pm_runtime_force_resume() As pm_runtime_set_active() may fail because the device's parent isn't active, we can end up executing the ->runtime_resume() callback for the device when it isn't allowed. Fix this by invoking pm_runtime_set_active() before running the callback and let's also deal with the error code. Fixes: 37f204164dfb (PM: Add pm_runtime_suspend|resume_force functions) Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Cc: 3.15+ # 3.15+ Signed-off-by: Rafael J. Wysocki --- drivers/base/power/runtime.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 4c7055009bd6..b74690418504 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1506,11 +1506,16 @@ int pm_runtime_force_resume(struct device *dev) goto out; } - ret = callback(dev); + ret = pm_runtime_set_active(dev); if (ret) goto out; - pm_runtime_set_active(dev); + ret = callback(dev); + if (ret) { + pm_runtime_set_suspended(dev); + goto out; + } + pm_runtime_mark_last_busy(dev); out: pm_runtime_enable(dev); -- GitLab From c60c9840423f32117a5422511c53c39df0b4d1dd Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Mon, 18 Apr 2016 18:24:04 -0400 Subject: [PATCH 3875/9938] net: dsa: remove tag_protocol from dsa_switch Having the tag protocol in dsa_switch_driver for setup time and in dsa_switch_tree for runtime is enough. Remove dsa_switch's one. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- include/net/dsa.h | 5 ----- net/dsa/dsa.c | 5 ++--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index c4bc42bd3538..2d280aba97e2 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -135,11 +135,6 @@ struct dsa_switch { */ void *priv; - /* - * Tagging protocol understood by this switch - */ - enum dsa_tag_protocol tag_protocol; - /* * Configuration data for this switch. */ diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index efa612f0ab9b..d61ceed912be 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -267,7 +267,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) * switch. */ if (dst->cpu_switch == index) { - switch (ds->tag_protocol) { + switch (drv->tag_protocol) { #ifdef CONFIG_NET_DSA_TAG_DSA case DSA_TAG_PROTO_DSA: dst->rcv = dsa_netdev_ops.rcv; @@ -295,7 +295,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) goto out; } - dst->tag_protocol = ds->tag_protocol; + dst->tag_protocol = drv->tag_protocol; } /* @@ -411,7 +411,6 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ds->pd = pd; ds->drv = drv; ds->priv = priv; - ds->tag_protocol = drv->tag_protocol; ds->master_dev = host_dev; ret = dsa_switch_setup_one(ds, parent); -- GitLab From 85b67bcb7e4a23ced05e7020bf5843b9857f6881 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 18 Apr 2016 20:11:50 -0700 Subject: [PATCH 3876/9938] perf, bpf: minimize the size of perf_trace_() tracepoint handler move trace_call_bpf() into helper function to minimize the size of perf_trace_*() tracepoint handlers. text data bss dec hex filename 10541679 5526646 2945024 19013349 1221ee5 vmlinux_before 10509422 5526646 2945024 18981092 121a0e4 vmlinux_after It may seem that perf_fetch_caller_regs() can also be moved, but that is incorrect, since ip/sp will be wrong. bpf+tracepoint performance is not affected, since perf_swevent_put_recursion_context() is now inlined. export_symbol_gpl can also be dropped. No measurable change in normal perf tracepoints. Suggested-by: Steven Rostedt Signed-off-by: Alexei Starovoitov Acked-by: Peter Zijlstra (Intel) Acked-by: Steven Rostedt Signed-off-by: David S. Miller --- include/linux/trace_events.h | 5 +++++ include/trace/perf.h | 13 +++---------- kernel/events/core.c | 20 +++++++++++++++++++- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index fe6441203b59..222f6aa0418f 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -609,6 +609,11 @@ extern void ftrace_profile_free_filter(struct perf_event *event); void perf_trace_buf_update(void *record, u16 type); void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp); +void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx, + struct trace_event_call *call, u64 count, + struct pt_regs *regs, struct hlist_head *head, + struct task_struct *task); + static inline void perf_trace_buf_submit(void *raw_data, int size, int rctx, u16 type, u64 count, struct pt_regs *regs, void *head, diff --git a/include/trace/perf.h b/include/trace/perf.h index a182306eefd7..88de5c205e86 100644 --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -64,16 +64,9 @@ perf_trace_##call(void *__data, proto) \ \ { assign; } \ \ - if (prog) { \ - *(struct pt_regs **)entry = __regs; \ - if (!trace_call_bpf(prog, entry) || hlist_empty(head)) { \ - perf_swevent_put_recursion_context(rctx); \ - return; \ - } \ - } \ - perf_trace_buf_submit(entry, __entry_size, rctx, \ - event_call->event.type, __count, __regs, \ - head, __task); \ + perf_trace_run_bpf_submit(entry, __entry_size, rctx, \ + event_call, __count, __regs, \ + head, __task); \ } /* diff --git a/kernel/events/core.c b/kernel/events/core.c index 5056abffef27..9eb23dc27462 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6741,7 +6741,6 @@ void perf_swevent_put_recursion_context(int rctx) put_recursion_context(swhash->recursion, rctx); } -EXPORT_SYMBOL_GPL(perf_swevent_put_recursion_context); void ___perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr) { @@ -6998,6 +6997,25 @@ static int perf_tp_event_match(struct perf_event *event, return 1; } +void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx, + struct trace_event_call *call, u64 count, + struct pt_regs *regs, struct hlist_head *head, + struct task_struct *task) +{ + struct bpf_prog *prog = call->prog; + + if (prog) { + *(struct pt_regs **)raw_data = regs; + if (!trace_call_bpf(prog, raw_data) || hlist_empty(head)) { + perf_swevent_put_recursion_context(rctx); + return; + } + } + perf_tp_event(call->event.type, count, raw_data, size, regs, head, + rctx, task); +} +EXPORT_SYMBOL_GPL(perf_trace_run_bpf_submit); + void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, struct pt_regs *regs, struct hlist_head *head, int rctx, struct task_struct *task) -- GitLab From b7de529c793c9131e58ddca37d49fd26866aa867 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 19 Apr 2016 15:10:01 +0800 Subject: [PATCH 3877/9938] net: use jiffies_to_msecs to replace EXPIRES_IN_MS in inet/sctp_diag EXPIRES_IN_MS macro comes from net/ipv4/inet_diag.c and dates back to before jiffies_to_msecs() has been introduced. Now we can remove it and use jiffies_to_msecs(). Suggested-by: Jakub Sitnicki Signed-off-by: Xin Long Acked-by: Jakub Sitnicki Acked-by: Marcelo Ricardo Leitner Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 12 ++++++------ net/sctp/sctp_diag.c | 6 ++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 70212bddf0f8..ad7956fa659a 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -197,27 +197,27 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, goto out; } -#define EXPIRES_IN_MS(tmo) DIV_ROUND_UP((tmo - jiffies) * 1000, HZ) - if (icsk->icsk_pending == ICSK_TIME_RETRANS || icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS || icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { r->idiag_timer = 1; r->idiag_retrans = icsk->icsk_retransmits; - r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout); + r->idiag_expires = + jiffies_to_msecs(icsk->icsk_timeout - jiffies); } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) { r->idiag_timer = 4; r->idiag_retrans = icsk->icsk_probes_out; - r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout); + r->idiag_expires = + jiffies_to_msecs(icsk->icsk_timeout - jiffies); } else if (timer_pending(&sk->sk_timer)) { r->idiag_timer = 2; r->idiag_retrans = icsk->icsk_probes_out; - r->idiag_expires = EXPIRES_IN_MS(sk->sk_timer.expires); + r->idiag_expires = + jiffies_to_msecs(sk->sk_timer.expires - jiffies); } else { r->idiag_timer = 0; r->idiag_expires = 0; } -#undef EXPIRES_IN_MS if ((ext & (1 << (INET_DIAG_INFO - 1))) && handler->idiag_info_size) { attr = nla_reserve(skb, INET_DIAG_INFO, diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c index 98ecd16da0c9..bb2d8d9608e9 100644 --- a/net/sctp/sctp_diag.c +++ b/net/sctp/sctp_diag.c @@ -48,10 +48,8 @@ static void inet_diag_msg_sctpasoc_fill(struct inet_diag_msg *r, r->idiag_state = asoc->state; r->idiag_timer = SCTP_EVENT_TIMEOUT_T3_RTX; r->idiag_retrans = asoc->rtx_data_chunks; -#define EXPIRES_IN_MS(tmo) DIV_ROUND_UP((tmo - jiffies) * 1000, HZ) - r->idiag_expires = - EXPIRES_IN_MS(asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX]); -#undef EXPIRES_IN_MS + r->idiag_expires = jiffies_to_msecs( + asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] - jiffies); } static int inet_diag_msg_sctpladdrs_fill(struct sk_buff *skb, -- GitLab From f937572925d8d7beb5aca1cf180e8b9af623a903 Mon Sep 17 00:00:00 2001 From: Peter Heise Date: Tue, 19 Apr 2016 13:34:28 +0200 Subject: [PATCH 3878/9938] NLA_BINARY misuse bug in HSR Removed .type field from NLA to do proper length checking. Reported by Daniel Borkmann and Julia Lawall. Signed-off-by: Peter Heise Signed-off-by: David S. Miller --- net/hsr/hsr_netlink.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index 5425d87611fc..d4d1617f43a8 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -24,7 +24,7 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = { [IFLA_HSR_SLAVE2] = { .type = NLA_U32 }, [IFLA_HSR_MULTICAST_SPEC] = { .type = NLA_U8 }, [IFLA_HSR_VERSION] = { .type = NLA_U8 }, - [IFLA_HSR_SUPERVISION_ADDR] = { .type = NLA_BINARY, .len = ETH_ALEN }, + [IFLA_HSR_SUPERVISION_ADDR] = { .len = ETH_ALEN }, [IFLA_HSR_SEQ_NR] = { .type = NLA_U16 }, }; @@ -121,10 +121,9 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = { /* attribute policy */ -/* NLA_BINARY missing in libnl; use NLA_UNSPEC in userspace instead. */ static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = { - [HSR_A_NODE_ADDR] = { .type = NLA_BINARY, .len = ETH_ALEN }, - [HSR_A_NODE_ADDR_B] = { .type = NLA_BINARY, .len = ETH_ALEN }, + [HSR_A_NODE_ADDR] = { .len = ETH_ALEN }, + [HSR_A_NODE_ADDR_B] = { .len = ETH_ALEN }, [HSR_A_IFINDEX] = { .type = NLA_U32 }, [HSR_A_IF1_AGE] = { .type = NLA_U32 }, [HSR_A_IF2_AGE] = { .type = NLA_U32 }, -- GitLab From 1ba64facae5739d91884f8f34f25fef1cb66d930 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Apr 2016 17:30:56 +0300 Subject: [PATCH 3879/9938] geneve: testing the wrong variable in geneve6_build_skb() We intended to test "err" and not "skb". Fixes: aed069df099c ('ip_tunnel_core: iptunnel_handle_offloads returns int and doesn't free skb') Signed-off-by: Dan Carpenter Acked-by: Alexander Duyck Signed-off-by: David S. Miller --- drivers/net/geneve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index efbc7ceedc3a..512dbe013713 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -733,7 +733,7 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb, goto free_dst; err = udp_tunnel_handle_offloads(skb, udp_sum); - if (IS_ERR(skb)) + if (err) goto free_dst; gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); -- GitLab From b1c20f0b97b4e565fa50cde1e6b44c2fd327a1e0 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 19 Apr 2016 14:02:19 -0400 Subject: [PATCH 3880/9938] netdev_features: Fold NETIF_F_ALL_TSO into NETIF_F_GSO_SOFTWARE This patch folds NETIF_F_ALL_TSO into the bitmask for NETIF_F_GSO_SOFTWARE. The idea is to avoid duplication of defines since the only difference between the two was the GSO_UDP bit. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- include/linux/netdev_features.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 15eb0b12fff9..bc8736266749 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -152,11 +152,6 @@ enum { #define NETIF_F_GSO_MASK (__NETIF_F_BIT(NETIF_F_GSO_LAST + 1) - \ __NETIF_F_BIT(NETIF_F_GSO_SHIFT)) -/* List of features with software fallbacks. */ -#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ - NETIF_F_TSO_MANGLEID | \ - NETIF_F_TSO6 | NETIF_F_UFO) - /* List of IP checksum features. Note that NETIF_F_ HW_CSUM should not be * set in features when NETIF_F_IP_CSUM or NETIF_F_IPV6_CSUM are set-- * this would be contradictory @@ -170,6 +165,9 @@ enum { #define NETIF_F_ALL_FCOE (NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU | \ NETIF_F_FSO) +/* List of features with software fallbacks. */ +#define NETIF_F_GSO_SOFTWARE (NETIF_F_ALL_TSO | NETIF_F_UFO) + /* * If one device supports one of these features, then enable them * for all in netdev_increment_features. -- GitLab From 732912d727cd6deb3c1a05a8baa74b8ce8d510ac Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 19 Apr 2016 14:02:26 -0400 Subject: [PATCH 3881/9938] veth: Update features to include all tunnel GSO types This patch adds support for the checksum enabled versions of UDP and GRE tunnels. With this change we should be able to send and receive GSO frames of these types over the veth pair without needing to segment the packets. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- drivers/net/veth.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 4f30a6ae50d0..f37a6e61d4ad 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -312,10 +312,9 @@ static const struct net_device_ops veth_netdev_ops = { .ndo_set_rx_headroom = veth_set_rx_headroom, }; -#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ - NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_HIGHDMA | \ - NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL | \ - NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT | NETIF_F_UFO | \ +#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \ + NETIF_F_RXCSUM | NETIF_F_HIGHDMA | \ + NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL | \ NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | \ NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_STAG_RX ) -- GitLab From 089bf1a6a924b97a7e9f920bae6253a8ad581cf3 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 21 Apr 2016 18:58:24 +0200 Subject: [PATCH 3882/9938] libnl: add more helpers to align attributes on 64-bit Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/netlink.h | 39 +++++++++++++---- lib/nlattr.c | 99 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 8 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 3c1fd92a52c8..6f51a8a06498 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -244,13 +244,21 @@ int nla_memcpy(void *dest, const struct nlattr *src, int count); int nla_memcmp(const struct nlattr *nla, const void *data, size_t size); int nla_strcmp(const struct nlattr *nla, const char *str); struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen); +struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype, + int attrlen, int padattr); void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen); struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen); +struct nlattr *nla_reserve_64bit(struct sk_buff *skb, int attrtype, + int attrlen, int padattr); void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen); void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data); +void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen, + const void *data, int padattr); void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data); int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data); +int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen, + const void *data, int padattr); int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data); int nla_append(struct sk_buff *skb, int attrlen, const void *data); @@ -1230,6 +1238,27 @@ static inline int nla_validate_nested(const struct nlattr *start, int maxtype, return nla_validate(nla_data(start), nla_len(start), maxtype, policy); } +/** + * nla_need_padding_for_64bit - test 64-bit alignment of the next attribute + * @skb: socket buffer the message is stored in + * + * Return true if padding is needed to align the next attribute (nla_data()) to + * a 64-bit aligned area. + */ +static inline bool nla_need_padding_for_64bit(struct sk_buff *skb) +{ +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* The nlattr header is 4 bytes in size, that's why we test + * if the skb->data _is_ aligned. A NOP attribute, plus + * nlattr header for next attribute, will make nla_data() + * 8-byte aligned. + */ + if (IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8)) + return true; +#endif + return false; +} + /** * nla_align_64bit - 64-bit align the nla_data() of next attribute * @skb: socket buffer the message is stored in @@ -1244,16 +1273,10 @@ static inline int nla_validate_nested(const struct nlattr *start, int maxtype, */ static inline int nla_align_64bit(struct sk_buff *skb, int padattr) { -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - /* The nlattr header is 4 bytes in size, that's why we test - * if the skb->data _is_ aligned. This NOP attribute, plus - * nlattr header for next attribute, will make nla_data() - * 8-byte aligned. - */ - if (IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8) && + if (nla_need_padding_for_64bit(skb) && !nla_reserve(skb, padattr, 0)) return -EMSGSIZE; -#endif + return 0; } diff --git a/lib/nlattr.c b/lib/nlattr.c index f5907d23272d..2b82f1e2ebc2 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -354,6 +354,29 @@ struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) } EXPORT_SYMBOL(__nla_reserve); +/** + * __nla_reserve_64bit - reserve room for attribute on the skb and align it + * @skb: socket buffer to reserve room on + * @attrtype: attribute type + * @attrlen: length of attribute payload + * + * Adds a netlink attribute header to a socket buffer and reserves + * room for the payload but does not copy it. It also ensure that this + * attribute will be 64-bit aign. + * + * The caller is responsible to ensure that the skb provides enough + * tailroom for the attribute header and payload. + */ +struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype, + int attrlen, int padattr) +{ + if (nla_need_padding_for_64bit(skb)) + nla_align_64bit(skb, padattr); + + return __nla_reserve(skb, attrtype, attrlen); +} +EXPORT_SYMBOL(__nla_reserve_64bit); + /** * __nla_reserve_nohdr - reserve room for attribute without header * @skb: socket buffer to reserve room on @@ -396,6 +419,35 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) } EXPORT_SYMBOL(nla_reserve); +/** + * nla_reserve_64bit - reserve room for attribute on the skb and align it + * @skb: socket buffer to reserve room on + * @attrtype: attribute type + * @attrlen: length of attribute payload + * + * Adds a netlink attribute header to a socket buffer and reserves + * room for the payload but does not copy it. It also ensure that this + * attribute will be 64-bit aign. + * + * Returns NULL if the tailroom of the skb is insufficient to store + * the attribute header and payload. + */ +struct nlattr *nla_reserve_64bit(struct sk_buff *skb, int attrtype, int attrlen, + int padattr) +{ + size_t len; + + if (nla_need_padding_for_64bit(skb)) + len = nla_total_size_64bit(attrlen); + else + len = nla_total_size(attrlen); + if (unlikely(skb_tailroom(skb) < len)) + return NULL; + + return __nla_reserve_64bit(skb, attrtype, attrlen, padattr); +} +EXPORT_SYMBOL(nla_reserve_64bit); + /** * nla_reserve_nohdr - reserve room for attribute without header * @skb: socket buffer to reserve room on @@ -435,6 +487,26 @@ void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, } EXPORT_SYMBOL(__nla_put); +/** + * __nla_put_64bit - Add a netlink attribute to a socket buffer and align it + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @attrlen: length of attribute payload + * @data: head of attribute payload + * + * The caller is responsible to ensure that the skb provides enough + * tailroom for the attribute header and payload. + */ +void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen, + const void *data, int padattr) +{ + struct nlattr *nla; + + nla = __nla_reserve_64bit(skb, attrtype, attrlen, padattr); + memcpy(nla_data(nla), data, attrlen); +} +EXPORT_SYMBOL(__nla_put_64bit); + /** * __nla_put_nohdr - Add a netlink attribute without header * @skb: socket buffer to add attribute to @@ -473,6 +545,33 @@ int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data) } EXPORT_SYMBOL(nla_put); +/** + * nla_put_64bit - Add a netlink attribute to a socket buffer and align it + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @attrlen: length of attribute payload + * @data: head of attribute payload + * + * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store + * the attribute header and payload. + */ +int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen, + const void *data, int padattr) +{ + size_t len; + + if (nla_need_padding_for_64bit(skb)) + len = nla_total_size_64bit(attrlen); + else + len = nla_total_size(attrlen); + if (unlikely(skb_tailroom(skb) < len)) + return -EMSGSIZE; + + __nla_put_64bit(skb, attrtype, attrlen, data, padattr); + return 0; +} +EXPORT_SYMBOL(nla_put_64bit); + /** * nla_put_nohdr - Add a netlink attribute without header * @skb: socket buffer to add attribute to -- GitLab From 58414d32a37e4c2f79da91aebc2d2365918a1562 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 21 Apr 2016 18:58:25 +0200 Subject: [PATCH 3883/9938] rtnl: use the new API to align IFLA_STATS* Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4a47a9aceb1d..5ec059d52823 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1051,14 +1051,9 @@ static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb, { struct rtnl_link_stats64 *sp; struct nlattr *attr; - int err; - - err = nla_align_64bit(skb, IFLA_PAD); - if (err) - return err; - attr = nla_reserve(skb, IFLA_STATS64, - sizeof(struct rtnl_link_stats64)); + attr = nla_reserve_64bit(skb, IFLA_STATS64, + sizeof(struct rtnl_link_stats64), IFLA_PAD); if (!attr) return -EMSGSIZE; @@ -3469,17 +3464,10 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev, if (filter_mask & IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_64)) { struct rtnl_link_stats64 *sp; - int err; - - /* if necessary, add a zero length NOP attribute so that - * IFLA_STATS_LINK_64 will be 64-bit aligned - */ - err = nla_align_64bit(skb, IFLA_STATS_UNSPEC); - if (err) - goto nla_put_failure; - attr = nla_reserve(skb, IFLA_STATS_LINK_64, - sizeof(struct rtnl_link_stats64)); + attr = nla_reserve_64bit(skb, IFLA_STATS_LINK_64, + sizeof(struct rtnl_link_stats64), + IFLA_STATS_UNSPEC); if (!attr) goto nla_put_failure; -- GitLab From a9a080422ef7b0c7e69925e4a1474ad93f0f0117 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 21 Apr 2016 18:58:26 +0200 Subject: [PATCH 3884/9938] ipmr: align RTA_MFC_STATS on 64-bit Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/rtnetlink.h | 1 + net/ipv4/ipmr.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index cc885c4e9065..a94e0b69c769 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -317,6 +317,7 @@ enum rtattr_type_t { RTA_ENCAP_TYPE, RTA_ENCAP, RTA_EXPIRES, + RTA_PAD, __RTA_MAX }; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 395e2814a46d..21a38e296fe2 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -2104,7 +2104,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, mfcs.mfcs_packets = c->mfc_un.res.pkt; mfcs.mfcs_bytes = c->mfc_un.res.bytes; mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if; - if (nla_put(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs) < 0) + if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) < 0) return -EMSGSIZE; rtm->rtm_type = RTN_MULTICAST; @@ -2237,7 +2237,7 @@ static size_t mroute_msgsize(bool unresolved, int maxvif) + nla_total_size(0) /* RTA_MULTIPATH */ + maxvif * NLA_ALIGN(sizeof(struct rtnexthop)) /* RTA_MFC_STATS */ - + nla_total_size(sizeof(struct rta_mfc_stats)) + + nla_total_size_64bit(sizeof(struct rta_mfc_stats)) ; return len; -- GitLab From 3d6b66c1d1a8d348928996ca333730f258fbb838 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 21 Apr 2016 18:58:27 +0200 Subject: [PATCH 3885/9938] ip6mr: align RTA_MFC_STATS on 64-bit Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/ip6mr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index a10e77103c88..bf678324fd52 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -2268,7 +2268,7 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, mfcs.mfcs_packets = c->mfc_un.res.pkt; mfcs.mfcs_bytes = c->mfc_un.res.bytes; mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if; - if (nla_put(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs) < 0) + if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) < 0) return -EMSGSIZE; rtm->rtm_type = RTN_MULTICAST; @@ -2411,7 +2411,7 @@ static int mr6_msgsize(bool unresolved, int maxvif) + nla_total_size(0) /* RTA_MULTIPATH */ + maxvif * NLA_ALIGN(sizeof(struct rtnexthop)) /* RTA_MFC_STATS */ - + nla_total_size(sizeof(struct rta_mfc_stats)) + + nla_total_size_64bit(sizeof(struct rta_mfc_stats)) ; return len; -- GitLab From ba90950c94713f294e8778e891eef4143183957c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Apr 2016 11:37:08 -0700 Subject: [PATCH 3886/9938] net: bcmsysport: use __napi_schedule_irqoff() Both bcm_sysport_tx_isr() and bcm_sysport_rx_isr() run in hard irq context, we do not need to block irq again. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 993c780bdfab..9e3ec739d860 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -873,7 +873,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id) if (likely(napi_schedule_prep(&priv->napi))) { /* disable RX interrupts */ intrl2_0_mask_set(priv, INTRL2_0_RDMA_MBDONE); - __napi_schedule(&priv->napi); + __napi_schedule_irqoff(&priv->napi); } } @@ -916,7 +916,7 @@ static irqreturn_t bcm_sysport_tx_isr(int irq, void *dev_id) if (likely(napi_schedule_prep(&txr->napi))) { intrl2_1_mask_set(priv, BIT(ring)); - __napi_schedule(&txr->napi); + __napi_schedule_irqoff(&txr->napi); } } -- GitLab From c82f47efa021697722b1cfc84e48f72d45c9f5b2 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Apr 2016 11:37:09 -0700 Subject: [PATCH 3887/9938] net: bcmsysport: use napi_complete_done() By using napi_complete_done(), we allow fine tuning of /sys/class/net/ethX/gro_flush_timeout for higher GRO aggregation efficiency for a Gbit NIC. Check commit 24d2e4a50737 ("tg3: use napi_complete_done()") for details. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 9e3ec739d860..30b0c2895a56 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -831,7 +831,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget) rdma_writel(priv, priv->rx_c_index, RDMA_CONS_INDEX); if (work_done < budget) { - napi_complete(napi); + napi_complete_done(napi, work_done); /* re-enable RX interrupts */ intrl2_0_mask_clear(priv, INTRL2_0_RDMA_MBDONE); } -- GitLab From 237cd218099ce96edf2890a49aa191b38b84c2fc Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:09 +0300 Subject: [PATCH 3888/9938] net/mlx5: Introduce device queue counters A queue counter can collect several statistics for one or more hardware queues (QPs, RQs, etc ..) that the counter is attached to. For Ethernet it will provide an "out of buffer" counter which collects the number of all packets that are dropped due to lack of software buffers. Here we add device commands to alloc/query/dealloc queue counters. Signed-off-by: Tariq Toukan Signed-off-by: Rana Shahout Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/qp.c | 68 ++++++++++++++++++++ include/linux/mlx5/qp.h | 6 ++ 2 files changed, 74 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c index def289375ecb..b720a274220d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -538,3 +538,71 @@ void mlx5_core_destroy_sq_tracked(struct mlx5_core_dev *dev, mlx5_core_destroy_sq(dev, sq->qpn); } EXPORT_SYMBOL(mlx5_core_destroy_sq_tracked); + +int mlx5_core_alloc_q_counter(struct mlx5_core_dev *dev, u16 *counter_id) +{ + u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)]; + u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)]; + int err; + + memset(in, 0, sizeof(in)); + memset(out, 0, sizeof(out)); + + MLX5_SET(alloc_q_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_Q_COUNTER); + err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); + if (!err) + *counter_id = MLX5_GET(alloc_q_counter_out, out, + counter_set_id); + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_alloc_q_counter); + +int mlx5_core_dealloc_q_counter(struct mlx5_core_dev *dev, u16 counter_id) +{ + u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)]; + u32 out[MLX5_ST_SZ_DW(dealloc_q_counter_out)]; + + memset(in, 0, sizeof(in)); + memset(out, 0, sizeof(out)); + + MLX5_SET(dealloc_q_counter_in, in, opcode, + MLX5_CMD_OP_DEALLOC_Q_COUNTER); + MLX5_SET(dealloc_q_counter_in, in, counter_set_id, counter_id); + return mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, + sizeof(out)); +} +EXPORT_SYMBOL_GPL(mlx5_core_dealloc_q_counter); + +int mlx5_core_query_q_counter(struct mlx5_core_dev *dev, u16 counter_id, + int reset, void *out, int out_size) +{ + u32 in[MLX5_ST_SZ_DW(query_q_counter_in)]; + + memset(in, 0, sizeof(in)); + + MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER); + MLX5_SET(query_q_counter_in, in, clear, reset); + MLX5_SET(query_q_counter_in, in, counter_set_id, counter_id); + return mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_size); +} +EXPORT_SYMBOL_GPL(mlx5_core_query_q_counter); + +int mlx5_core_query_out_of_buffer(struct mlx5_core_dev *dev, u16 counter_id, + u32 *out_of_buffer) +{ + int outlen = MLX5_ST_SZ_BYTES(query_q_counter_out); + void *out; + int err; + + out = mlx5_vzalloc(outlen); + if (!out) + return -ENOMEM; + + err = mlx5_core_query_q_counter(dev, counter_id, 0, out, outlen); + if (!err) + *out_of_buffer = MLX5_GET(query_q_counter_out, out, + out_of_buffer); + + kfree(out); + return err; +} diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h index cf031a3f16c5..64221027bf1f 100644 --- a/include/linux/mlx5/qp.h +++ b/include/linux/mlx5/qp.h @@ -668,6 +668,12 @@ int mlx5_core_create_sq_tracked(struct mlx5_core_dev *dev, u32 *in, int inlen, struct mlx5_core_qp *sq); void mlx5_core_destroy_sq_tracked(struct mlx5_core_dev *dev, struct mlx5_core_qp *sq); +int mlx5_core_alloc_q_counter(struct mlx5_core_dev *dev, u16 *counter_id); +int mlx5_core_dealloc_q_counter(struct mlx5_core_dev *dev, u16 counter_id); +int mlx5_core_query_q_counter(struct mlx5_core_dev *dev, u16 counter_id, + int reset, void *out, int out_size); +int mlx5_core_query_out_of_buffer(struct mlx5_core_dev *dev, u16 counter_id, + u32 *out_of_buffer); static inline const char *mlx5_qp_type_str(int type) { -- GitLab From 593cf33829adfd3d5c75d42879cc42afded1b626 Mon Sep 17 00:00:00 2001 From: Rana Shahout Date: Wed, 20 Apr 2016 22:02:10 +0300 Subject: [PATCH 3889/9938] net/mlx5e: Allocate set of queue counters per netdev Connect all netdev RQs to this set of queue counters. Also, add an "rx_out_of_buffer" counter to ethtool, which indicates RX packet drops due to lack of receive buffers. Signed-off-by: Rana Shahout Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 11 +++++ .../ethernet/mellanox/mlx5/core/en_ethtool.c | 11 +++++ .../net/ethernet/mellanox/mlx5/core/en_main.c | 42 ++++++++++++++++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 879e6276c473..c4ddbe8501a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -236,6 +236,15 @@ struct mlx5e_pport_stats { __be64 RFC_2819_counters[NUM_RFC_2819_COUNTERS]; }; +static const char qcounter_stats_strings[][ETH_GSTRING_LEN] = { + "rx_out_of_buffer", +}; + +struct mlx5e_qcounter_stats { + u32 rx_out_of_buffer; +#define NUM_Q_COUNTERS 1 +}; + static const char rq_stats_strings[][ETH_GSTRING_LEN] = { "packets", "bytes", @@ -293,6 +302,7 @@ struct mlx5e_sq_stats { struct mlx5e_stats { struct mlx5e_vport_stats vport; struct mlx5e_pport_stats pport; + struct mlx5e_qcounter_stats qcnt; }; struct mlx5e_params { @@ -575,6 +585,7 @@ struct mlx5e_priv { struct net_device *netdev; struct mlx5e_stats stats; struct mlx5e_tstamp tstamp; + u16 q_counter; }; #define MLX5E_NET_IP_ALIGN 2 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 68834b715f6c..39c19021d154 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -165,6 +165,8 @@ static const struct { }, }; +#define MLX5E_NUM_Q_CNTRS(priv) (NUM_Q_COUNTERS * (!!priv->q_counter)) + static int mlx5e_get_sset_count(struct net_device *dev, int sset) { struct mlx5e_priv *priv = netdev_priv(dev); @@ -172,6 +174,7 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset) switch (sset) { case ETH_SS_STATS: return NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS + + MLX5E_NUM_Q_CNTRS(priv) + priv->params.num_channels * NUM_RQ_STATS + priv->params.num_channels * priv->params.num_tc * NUM_SQ_STATS; @@ -200,6 +203,11 @@ static void mlx5e_get_strings(struct net_device *dev, strcpy(data + (idx++) * ETH_GSTRING_LEN, vport_strings[i]); + /* Q counters */ + for (i = 0; i < MLX5E_NUM_Q_CNTRS(priv); i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, + qcounter_stats_strings[i]); + /* PPORT counters */ for (i = 0; i < NUM_PPORT_COUNTERS; i++) strcpy(data + (idx++) * ETH_GSTRING_LEN, @@ -240,6 +248,9 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev, for (i = 0; i < NUM_VPORT_COUNTERS; i++) data[idx++] = ((u64 *)&priv->stats.vport)[i]; + for (i = 0; i < MLX5E_NUM_Q_CNTRS(priv); i++) + data[idx++] = ((u32 *)&priv->stats.qcnt)[i]; + for (i = 0; i < NUM_PPORT_COUNTERS; i++) data[idx++] = be64_to_cpu(((__be64 *)&priv->stats.pport)[i]); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index e0adb604f461..7fbe1ba86294 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -129,6 +129,17 @@ static void mlx5e_update_pport_counters(struct mlx5e_priv *priv) kvfree(out); } +static void mlx5e_update_q_counter(struct mlx5e_priv *priv) +{ + struct mlx5e_qcounter_stats *qcnt = &priv->stats.qcnt; + + if (!priv->q_counter) + return; + + mlx5_core_query_out_of_buffer(priv->mdev, priv->q_counter, + &qcnt->rx_out_of_buffer); +} + void mlx5e_update_stats(struct mlx5e_priv *priv) { struct mlx5_core_dev *mdev = priv->mdev; @@ -250,6 +261,8 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) s->rx_csum_sw; mlx5e_update_pport_counters(priv); + mlx5e_update_q_counter(priv); + free_out: kvfree(out); } @@ -1055,6 +1068,7 @@ static void mlx5e_build_rq_param(struct mlx5e_priv *priv, MLX5_SET(wq, wq, log_wq_stride, ilog2(sizeof(struct mlx5e_rx_wqe))); MLX5_SET(wq, wq, log_wq_sz, priv->params.log_rq_size); MLX5_SET(wq, wq, pd, priv->pdn); + MLX5_SET(rqc, rqc, counter_set_id, priv->q_counter); param->wq.buf_numa_node = dev_to_node(&priv->mdev->pdev->dev); param->wq.linear = 1; @@ -2442,6 +2456,26 @@ static int mlx5e_create_mkey(struct mlx5e_priv *priv, u32 pdn, return err; } +static void mlx5e_create_q_counter(struct mlx5e_priv *priv) +{ + struct mlx5_core_dev *mdev = priv->mdev; + int err; + + err = mlx5_core_alloc_q_counter(mdev, &priv->q_counter); + if (err) { + mlx5_core_warn(mdev, "alloc queue counter failed, %d\n", err); + priv->q_counter = 0; + } +} + +static void mlx5e_destroy_q_counter(struct mlx5e_priv *priv) +{ + if (!priv->q_counter) + return; + + mlx5_core_dealloc_q_counter(priv->mdev, priv->q_counter); +} + static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) { struct net_device *netdev; @@ -2527,13 +2561,15 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) goto err_destroy_tirs; } + mlx5e_create_q_counter(priv); + mlx5e_init_eth_addr(priv); mlx5e_vxlan_init(priv); err = mlx5e_tc_init(priv); if (err) - goto err_destroy_flow_tables; + goto err_dealloc_q_counters; #ifdef CONFIG_MLX5_CORE_EN_DCB mlx5e_dcbnl_ieee_setets_core(priv, &priv->params.ets); @@ -2556,7 +2592,8 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) err_tc_cleanup: mlx5e_tc_cleanup(priv); -err_destroy_flow_tables: +err_dealloc_q_counters: + mlx5e_destroy_q_counter(priv); mlx5e_destroy_flow_tables(priv); err_destroy_tirs: @@ -2605,6 +2642,7 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv) unregister_netdev(netdev); mlx5e_tc_cleanup(priv); mlx5e_vxlan_cleanup(priv); + mlx5e_destroy_q_counter(priv); mlx5e_destroy_flow_tables(priv); mlx5e_destroy_tirs(priv); mlx5e_destroy_rqt(priv, MLX5E_SINGLE_RQ_RQT); -- GitLab From d8c9660dac6287490ef450bc892593f05d364531 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:11 +0300 Subject: [PATCH 3890/9938] net/mlx5e: Use only close NUMA node for default RSS Distribute default RSS table uniformly over the rings of the close NUMA node, instead of all available channels. This way we enforce the preference of close rings over far ones. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 ++- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index c4ddbe8501a7..7f19644689f2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -671,7 +671,8 @@ void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv); int mlx5e_open_locked(struct net_device *netdev); int mlx5e_close_locked(struct net_device *netdev); -void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len, +void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev, + u32 *indirection_rqt, int len, int num_channels); static inline void mlx5e_tx_notify_hw(struct mlx5e_sq *sq, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 39c19021d154..6f40ba448f07 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -397,7 +397,7 @@ static int mlx5e_set_channels(struct net_device *dev, mlx5e_close_locked(dev); priv->params.num_channels = count; - mlx5e_build_default_indir_rqt(priv->params.indirection_rqt, + mlx5e_build_default_indir_rqt(priv->mdev, priv->params.indirection_rqt, MLX5E_INDIR_RQT_SIZE, count); if (was_opened) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 7fbe1ba86294..9b58ef6cab93 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2297,11 +2297,22 @@ static void mlx5e_ets_init(struct mlx5e_priv *priv) } #endif -void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len, +void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev, + u32 *indirection_rqt, int len, int num_channels) { + int node = mdev->priv.numa_node; + int node_num_of_cores; int i; + if (node == -1) + node = first_online_node; + + node_num_of_cores = cpumask_weight(cpumask_of_node(node)); + + if (node_num_of_cores) + num_channels = min_t(int, num_channels, node_num_of_cores); + for (i = 0; i < len; i++) indirection_rqt[i] = i % num_channels; } @@ -2333,7 +2344,7 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev, netdev_rss_key_fill(priv->params.toeplitz_hash_key, sizeof(priv->params.toeplitz_hash_key)); - mlx5e_build_default_indir_rqt(priv->params.indirection_rqt, + mlx5e_build_default_indir_rqt(mdev, priv->params.indirection_rqt, MLX5E_INDIR_RQT_SIZE, num_channels); priv->params.lro_wqe_sz = -- GitLab From 2f48af128d9aa64dd4e8c6fe97491b0bde3681b2 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:12 +0300 Subject: [PATCH 3891/9938] net/mlx5e: Use function pointers for RX data path handling In preparation for Striding RQ feature, which will need its own RX handlers. This patch does not change any functionality. Signed-off-by: Tariq Toukan Signed-off-by: Achiad Shochat Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 33 ++++++--- .../net/ethernet/mellanox/mlx5/core/en_main.c | 2 + .../net/ethernet/mellanox/mlx5/core/en_rx.c | 74 ++++++++++--------- 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 7f19644689f2..61e249d8d7f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -72,6 +72,17 @@ #define MLX5E_SQ_BF_BUDGET 16 #define MLX5E_NUM_MAIN_GROUPS 9 +#define MLX5E_NET_IP_ALIGN 2 + +struct mlx5e_tx_wqe { + struct mlx5_wqe_ctrl_seg ctrl; + struct mlx5_wqe_eth_seg eth; +}; + +struct mlx5e_rx_wqe { + struct mlx5_wqe_srq_next_seg next; + struct mlx5_wqe_data_seg data; +}; #ifdef CONFIG_MLX5_CORE_EN_DCB #define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */ @@ -357,6 +368,12 @@ struct mlx5e_cq { struct mlx5_wq_ctrl wq_ctrl; } ____cacheline_aligned_in_smp; +struct mlx5e_rq; +typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq *rq, + struct mlx5_cqe64 *cqe); +typedef int (*mlx5e_fp_alloc_wqe)(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, + u16 ix); + struct mlx5e_rq { /* data path */ struct mlx5_wq_ll wq; @@ -368,6 +385,8 @@ struct mlx5e_rq { struct mlx5e_tstamp *tstamp; struct mlx5e_rq_stats stats; struct mlx5e_cq cq; + mlx5e_fp_handle_rx_cqe handle_rx_cqe; + mlx5e_fp_alloc_wqe alloc_wqe; unsigned long state; int ix; @@ -588,18 +607,6 @@ struct mlx5e_priv { u16 q_counter; }; -#define MLX5E_NET_IP_ALIGN 2 - -struct mlx5e_tx_wqe { - struct mlx5_wqe_ctrl_seg ctrl; - struct mlx5_wqe_eth_seg eth; -}; - -struct mlx5e_rx_wqe { - struct mlx5_wqe_srq_next_seg next; - struct mlx5_wqe_data_seg data; -}; - enum mlx5e_link_mode { MLX5E_1000BASE_CX_SGMII = 0, MLX5E_1000BASE_KX = 1, @@ -642,7 +649,9 @@ void mlx5e_cq_error_event(struct mlx5_core_cq *mcq, enum mlx5_event event); int mlx5e_napi_poll(struct napi_struct *napi, int budget); bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget); int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget); +void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq); +int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix); struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq); void mlx5e_update_stats(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 9b58ef6cab93..23ba12c3a738 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -357,6 +357,8 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, cpu_to_be32(byte_count | MLX5_HW_START_PADDING); } + rq->handle_rx_cqe = mlx5e_handle_rx_cqe; + rq->alloc_wqe = mlx5e_alloc_rx_wqe; rq->pdev = c->pdev; rq->netdev = c->netdev; rq->tstamp = &priv->tstamp; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 58d4e2f962c3..d7cccedddf34 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -42,8 +42,7 @@ static inline bool mlx5e_rx_hw_stamp(struct mlx5e_tstamp *tstamp) return tstamp->hwtstamp_config.rx_filter == HWTSTAMP_FILTER_ALL; } -static inline int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, - struct mlx5e_rx_wqe *wqe, u16 ix) +int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) { struct sk_buff *skb; dma_addr_t dma_addr; @@ -87,7 +86,7 @@ bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq) while (!mlx5_wq_ll_is_full(wq)) { struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(wq, wq->head); - if (unlikely(mlx5e_alloc_rx_wqe(rq, wqe, wq->head))) + if (unlikely(rq->alloc_wqe(rq, wqe, wq->head))) break; mlx5_wq_ll_push(wq, be16_to_cpu(wqe->next.next_wqe_index)); @@ -229,50 +228,55 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, skb->mark = be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK; } +void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) +{ + struct mlx5e_rx_wqe *wqe; + struct sk_buff *skb; + __be16 wqe_counter_be; + u16 wqe_counter; + + wqe_counter_be = cqe->wqe_counter; + wqe_counter = be16_to_cpu(wqe_counter_be); + wqe = mlx5_wq_ll_get_wqe(&rq->wq, wqe_counter); + skb = rq->skb[wqe_counter]; + prefetch(skb->data); + rq->skb[wqe_counter] = NULL; + + dma_unmap_single(rq->pdev, + *((dma_addr_t *)skb->cb), + rq->wqe_sz, + DMA_FROM_DEVICE); + + if (unlikely((cqe->op_own >> 4) != MLX5_CQE_RESP_SEND)) { + rq->stats.wqe_err++; + dev_kfree_skb(skb); + goto wq_ll_pop; + } + + mlx5e_build_rx_skb(cqe, rq, skb); + rq->stats.packets++; + rq->stats.bytes += be32_to_cpu(cqe->byte_cnt); + napi_gro_receive(rq->cq.napi, skb); + +wq_ll_pop: + mlx5_wq_ll_pop(&rq->wq, wqe_counter_be, + &wqe->next.next_wqe_index); +} + int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget) { struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq); int work_done; for (work_done = 0; work_done < budget; work_done++) { - struct mlx5e_rx_wqe *wqe; - struct mlx5_cqe64 *cqe; - struct sk_buff *skb; - __be16 wqe_counter_be; - u16 wqe_counter; + struct mlx5_cqe64 *cqe = mlx5e_get_cqe(cq); - cqe = mlx5e_get_cqe(cq); if (!cqe) break; mlx5_cqwq_pop(&cq->wq); - wqe_counter_be = cqe->wqe_counter; - wqe_counter = be16_to_cpu(wqe_counter_be); - wqe = mlx5_wq_ll_get_wqe(&rq->wq, wqe_counter); - skb = rq->skb[wqe_counter]; - prefetch(skb->data); - rq->skb[wqe_counter] = NULL; - - dma_unmap_single(rq->pdev, - *((dma_addr_t *)skb->cb), - rq->wqe_sz, - DMA_FROM_DEVICE); - - if (unlikely((cqe->op_own >> 4) != MLX5_CQE_RESP_SEND)) { - rq->stats.wqe_err++; - dev_kfree_skb(skb); - goto wq_ll_pop; - } - - mlx5e_build_rx_skb(cqe, rq, skb); - rq->stats.packets++; - rq->stats.bytes += be32_to_cpu(cqe->byte_cnt); - napi_gro_receive(cq->napi, skb); - -wq_ll_pop: - mlx5_wq_ll_pop(&rq->wq, wqe_counter_be, - &wqe->next.next_wqe_index); + rq->handle_rx_cqe(rq, cqe); } mlx5_cqwq_update_db_record(&cq->wq); -- GitLab From 461017cb006aa1b39b0f647ae0ee2d9d84eef05b Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:13 +0300 Subject: [PATCH 3892/9938] net/mlx5e: Support RX multi-packet WQE (Striding RQ) Introduce the feature of multi-packet WQE (RX Work Queue Element) referred to as (MPWQE or Striding RQ), in which WQEs are larger and serve multiple packets each. Every WQE consists of many strides of the same size, every received packet is aligned to a beginning of a stride and is written to consecutive strides within a WQE. In the regular approach, each regular WQE is big enough to be capable of serving one received packet of any size up to MTU or 64K in case of device LRO is enabled, making it very wasteful when dealing with small packets or device LRO is enabled. For its flexibility, MPWQE allows a better memory utilization (implying improvements in CPU utilization and packet rate) as packets consume strides according to their size, preserving the rest of the WQE to be available for other packets. MPWQE default configuration: Num of WQEs = 16 Strides Per WQE = 2048 Stride Size = 64 byte The default WQEs memory footprint went from 1024*mtu (~1.5MB) to 16 * 2048 * 64 = 2MB per ring. However, HW LRO can now be supported at no additional cost in memory footprint, and hence we turn it on by default and get an even better performance. Performance tested on ConnectX4-Lx 50G. To isolate the feature under test, the numbers below were measured with HW LRO turned off. We verified that the performance just improves when LRO is turned back on. * Netperf single TCP stream: - BW raised by 10-15% for representative packet sizes: default, 64B, 1024B, 1478B, 65536B. * Netperf multi TCP stream: - No degradation, line rate reached. * Pktgen: packet rate raised by 2-10% for traffic of different message sizes: 64B, 128B, 256B, 1024B, and 1500B. * Pktgen: packet loss in bursts of small messages (64byte), single stream: - | num packets | packets loss before | packets loss after | 2K | ~ 1K | 0 | 8K | ~ 6K | 0 | 16K | ~13K | 0 | 32K | ~28K | 0 | 64K | ~57K | ~24K As expected as the driver can receive as many small packets (<=64B) as the number of total strides in the ring (default = 2048 * 16) vs. 1024 (default ring size regardless of packets size) before this feature. Signed-off-by: Tariq Toukan Signed-off-by: Achiad Shochat Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 77 ++++++++- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 15 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 109 ++++++++++--- .../net/ethernet/mellanox/mlx5/core/en_rx.c | 153 ++++++++++++++++-- include/linux/mlx5/device.h | 39 ++++- 5 files changed, 349 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 61e249d8d7f8..f519148d7dcc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -57,12 +57,30 @@ #define MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE 0xa #define MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE 0xd +#define MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW 0x1 +#define MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW 0x4 +#define MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW 0x6 + +#define MLX5_MPWRQ_LOG_NUM_STRIDES 11 /* >= 9, HW restriction */ +#define MLX5_MPWRQ_LOG_STRIDE_SIZE 6 /* >= 6, HW restriction */ +#define MLX5_MPWRQ_NUM_STRIDES BIT(MLX5_MPWRQ_LOG_NUM_STRIDES) +#define MLX5_MPWRQ_STRIDE_SIZE BIT(MLX5_MPWRQ_LOG_STRIDE_SIZE) +#define MLX5_MPWRQ_LOG_WQE_SZ (MLX5_MPWRQ_LOG_NUM_STRIDES +\ + MLX5_MPWRQ_LOG_STRIDE_SIZE) +#define MLX5_MPWRQ_WQE_PAGE_ORDER (MLX5_MPWRQ_LOG_WQE_SZ - PAGE_SHIFT > 0 ? \ + MLX5_MPWRQ_LOG_WQE_SZ - PAGE_SHIFT : 0) +#define MLX5_MPWRQ_PAGES_PER_WQE BIT(MLX5_MPWRQ_WQE_PAGE_ORDER) +#define MLX5_MPWRQ_STRIDES_PER_PAGE (MLX5_MPWRQ_NUM_STRIDES >> \ + MLX5_MPWRQ_WQE_PAGE_ORDER) +#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (128) + #define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024) #define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC 0x10 #define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_PKTS 0x20 #define MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_USEC 0x10 #define MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_PKTS 0x20 #define MLX5E_PARAMS_DEFAULT_MIN_RX_WQES 0x80 +#define MLX5E_PARAMS_DEFAULT_MIN_RX_WQES_MPW 0x2 #define MLX5E_LOG_INDIR_RQT_SIZE 0x7 #define MLX5E_INDIR_RQT_SIZE BIT(MLX5E_LOG_INDIR_RQT_SIZE) @@ -74,6 +92,38 @@ #define MLX5E_NUM_MAIN_GROUPS 9 #define MLX5E_NET_IP_ALIGN 2 +static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size) +{ + switch (wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + return min_t(u16, MLX5E_PARAMS_DEFAULT_MIN_RX_WQES_MPW, + wq_size / 2); + default: + return min_t(u16, MLX5E_PARAMS_DEFAULT_MIN_RX_WQES, + wq_size / 2); + } +} + +static inline int mlx5_min_log_rq_size(int wq_type) +{ + switch (wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + return MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW; + default: + return MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE; + } +} + +static inline int mlx5_max_log_rq_size(int wq_type) +{ + switch (wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + return MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW; + default: + return MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; + } +} + struct mlx5e_tx_wqe { struct mlx5_wqe_ctrl_seg ctrl; struct mlx5_wqe_eth_seg eth; @@ -128,6 +178,7 @@ static const char vport_strings[][ETH_GSTRING_LEN] = { "tx_queue_wake", "tx_queue_dropped", "rx_wqe_err", + "rx_mpwqe_filler", }; struct mlx5e_vport_stats { @@ -169,8 +220,9 @@ struct mlx5e_vport_stats { u64 tx_queue_wake; u64 tx_queue_dropped; u64 rx_wqe_err; + u64 rx_mpwqe_filler; -#define NUM_VPORT_COUNTERS 35 +#define NUM_VPORT_COUNTERS 36 }; static const char pport_strings[][ETH_GSTRING_LEN] = { @@ -263,7 +315,8 @@ static const char rq_stats_strings[][ETH_GSTRING_LEN] = { "csum_sw", "lro_packets", "lro_bytes", - "wqe_err" + "wqe_err", + "mpwqe_filler", }; struct mlx5e_rq_stats { @@ -274,7 +327,8 @@ struct mlx5e_rq_stats { u64 lro_packets; u64 lro_bytes; u64 wqe_err; -#define NUM_RQ_STATS 7 + u64 mpwqe_filler; +#define NUM_RQ_STATS 8 }; static const char sq_stats_strings[][ETH_GSTRING_LEN] = { @@ -318,6 +372,7 @@ struct mlx5e_stats { struct mlx5e_params { u8 log_sq_size; + u8 rq_wq_type; u8 log_rq_size; u16 num_channels; u8 num_tc; @@ -374,11 +429,23 @@ typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq *rq, typedef int (*mlx5e_fp_alloc_wqe)(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix); +struct mlx5e_dma_info { + struct page *page; + dma_addr_t addr; +}; + +struct mlx5e_mpw_info { + struct mlx5e_dma_info dma_info; + u16 consumed_strides; + u16 skbs_frags[MLX5_MPWRQ_PAGES_PER_WQE]; +}; + struct mlx5e_rq { /* data path */ struct mlx5_wq_ll wq; u32 wqe_sz; struct sk_buff **skb; + struct mlx5e_mpw_info *wqe_info; struct device *pdev; struct net_device *netdev; @@ -393,6 +460,7 @@ struct mlx5e_rq { /* control */ struct mlx5_wq_ctrl wq_ctrl; + u8 wq_type; u32 rqn; struct mlx5e_channel *channel; struct mlx5e_priv *priv; @@ -649,9 +717,12 @@ void mlx5e_cq_error_event(struct mlx5_core_cq *mcq, enum mlx5_event event); int mlx5e_napi_poll(struct napi_struct *napi, int budget); bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget); int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget); + void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); +void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq); int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix); +int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix); struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq); void mlx5e_update_stats(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 6f40ba448f07..4077856aab76 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -273,8 +273,9 @@ static void mlx5e_get_ringparam(struct net_device *dev, struct ethtool_ringparam *param) { struct mlx5e_priv *priv = netdev_priv(dev); + int rq_wq_type = priv->params.rq_wq_type; - param->rx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; + param->rx_max_pending = 1 << mlx5_max_log_rq_size(rq_wq_type); param->tx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; param->rx_pending = 1 << priv->params.log_rq_size; param->tx_pending = 1 << priv->params.log_sq_size; @@ -285,6 +286,7 @@ static int mlx5e_set_ringparam(struct net_device *dev, { struct mlx5e_priv *priv = netdev_priv(dev); bool was_opened; + int rq_wq_type = priv->params.rq_wq_type; u16 min_rx_wqes; u8 log_rq_size; u8 log_sq_size; @@ -300,16 +302,16 @@ static int mlx5e_set_ringparam(struct net_device *dev, __func__); return -EINVAL; } - if (param->rx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { + if (param->rx_pending < (1 << mlx5_min_log_rq_size(rq_wq_type))) { netdev_info(dev, "%s: rx_pending (%d) < min (%d)\n", __func__, param->rx_pending, - 1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); + 1 << mlx5_min_log_rq_size(rq_wq_type)); return -EINVAL; } - if (param->rx_pending > (1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE)) { + if (param->rx_pending > (1 << mlx5_max_log_rq_size(rq_wq_type))) { netdev_info(dev, "%s: rx_pending (%d) > max (%d)\n", __func__, param->rx_pending, - 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE); + 1 << mlx5_max_log_rq_size(rq_wq_type)); return -EINVAL; } if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { @@ -327,8 +329,7 @@ static int mlx5e_set_ringparam(struct net_device *dev, log_rq_size = order_base_2(param->rx_pending); log_sq_size = order_base_2(param->tx_pending); - min_rx_wqes = min_t(u16, param->rx_pending - 1, - MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); + min_rx_wqes = mlx5_min_rx_wqes(rq_wq_type, param->rx_pending); if (log_rq_size == priv->params.log_rq_size && log_sq_size == priv->params.log_sq_size && diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 23ba12c3a738..871f3af204dd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -175,6 +175,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) s->rx_csum_none = 0; s->rx_csum_sw = 0; s->rx_wqe_err = 0; + s->rx_mpwqe_filler = 0; for (i = 0; i < priv->params.num_channels; i++) { rq_stats = &priv->channel[i]->rq.stats; @@ -185,6 +186,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) s->rx_csum_none += rq_stats->csum_none; s->rx_csum_sw += rq_stats->csum_sw; s->rx_wqe_err += rq_stats->wqe_err; + s->rx_mpwqe_filler += rq_stats->mpwqe_filler; for (j = 0; j < priv->params.num_tc; j++) { sq_stats = &priv->channel[i]->sq[j].stats; @@ -323,6 +325,7 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, struct mlx5_core_dev *mdev = priv->mdev; void *rqc = param->rqc; void *rqc_wq = MLX5_ADDR_OF(rqc, rqc, wq); + u32 byte_count; int wq_sz; int err; int i; @@ -337,28 +340,47 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, rq->wq.db = &rq->wq.db[MLX5_RCV_DBR]; wq_sz = mlx5_wq_ll_get_size(&rq->wq); - rq->skb = kzalloc_node(wq_sz * sizeof(*rq->skb), GFP_KERNEL, - cpu_to_node(c->cpu)); - if (!rq->skb) { - err = -ENOMEM; - goto err_rq_wq_destroy; - } - rq->wqe_sz = (priv->params.lro_en) ? priv->params.lro_wqe_sz : - MLX5E_SW2HW_MTU(priv->netdev->mtu); - rq->wqe_sz = SKB_DATA_ALIGN(rq->wqe_sz + MLX5E_NET_IP_ALIGN); + switch (priv->params.rq_wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + rq->wqe_info = kzalloc_node(wq_sz * sizeof(*rq->wqe_info), + GFP_KERNEL, cpu_to_node(c->cpu)); + if (!rq->wqe_info) { + err = -ENOMEM; + goto err_rq_wq_destroy; + } + rq->handle_rx_cqe = mlx5e_handle_rx_cqe_mpwrq; + rq->alloc_wqe = mlx5e_alloc_rx_mpwqe; + + rq->wqe_sz = MLX5_MPWRQ_NUM_STRIDES * MLX5_MPWRQ_STRIDE_SIZE; + byte_count = rq->wqe_sz; + break; + default: /* MLX5_WQ_TYPE_LINKED_LIST */ + rq->skb = kzalloc_node(wq_sz * sizeof(*rq->skb), GFP_KERNEL, + cpu_to_node(c->cpu)); + if (!rq->skb) { + err = -ENOMEM; + goto err_rq_wq_destroy; + } + rq->handle_rx_cqe = mlx5e_handle_rx_cqe; + rq->alloc_wqe = mlx5e_alloc_rx_wqe; + + rq->wqe_sz = (priv->params.lro_en) ? + priv->params.lro_wqe_sz : + MLX5E_SW2HW_MTU(priv->netdev->mtu); + rq->wqe_sz = SKB_DATA_ALIGN(rq->wqe_sz + MLX5E_NET_IP_ALIGN); + byte_count = rq->wqe_sz - MLX5E_NET_IP_ALIGN; + byte_count |= MLX5_HW_START_PADDING; + } for (i = 0; i < wq_sz; i++) { struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, i); - u32 byte_count = rq->wqe_sz - MLX5E_NET_IP_ALIGN; wqe->data.lkey = c->mkey_be; - wqe->data.byte_count = - cpu_to_be32(byte_count | MLX5_HW_START_PADDING); + wqe->data.byte_count = cpu_to_be32(byte_count); } - rq->handle_rx_cqe = mlx5e_handle_rx_cqe; - rq->alloc_wqe = mlx5e_alloc_rx_wqe; + rq->wq_type = priv->params.rq_wq_type; rq->pdev = c->pdev; rq->netdev = c->netdev; rq->tstamp = &priv->tstamp; @@ -376,7 +398,14 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, static void mlx5e_destroy_rq(struct mlx5e_rq *rq) { - kfree(rq->skb); + switch (rq->wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + kfree(rq->wqe_info); + break; + default: /* MLX5_WQ_TYPE_LINKED_LIST */ + kfree(rq->skb); + } + mlx5_wq_destroy(&rq->wq_ctrl); } @@ -1065,7 +1094,18 @@ static void mlx5e_build_rq_param(struct mlx5e_priv *priv, void *rqc = param->rqc; void *wq = MLX5_ADDR_OF(rqc, rqc, wq); - MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_LINKED_LIST); + switch (priv->params.rq_wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + MLX5_SET(wq, wq, log_wqe_num_of_strides, + MLX5_MPWRQ_LOG_NUM_STRIDES - 9); + MLX5_SET(wq, wq, log_wqe_stride_size, + MLX5_MPWRQ_LOG_STRIDE_SIZE - 6); + MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ); + break; + default: /* MLX5_WQ_TYPE_LINKED_LIST */ + MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_LINKED_LIST); + } + MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN); MLX5_SET(wq, wq, log_wq_stride, ilog2(sizeof(struct mlx5e_rx_wqe))); MLX5_SET(wq, wq, log_wq_sz, priv->params.log_rq_size); @@ -1111,8 +1151,18 @@ static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv, struct mlx5e_cq_param *param) { void *cqc = param->cqc; + u8 log_cq_size; - MLX5_SET(cqc, cqc, log_cq_size, priv->params.log_rq_size); + switch (priv->params.rq_wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + log_cq_size = priv->params.log_rq_size + + MLX5_MPWRQ_LOG_NUM_STRIDES; + break; + default: /* MLX5_WQ_TYPE_LINKED_LIST */ + log_cq_size = priv->params.log_rq_size; + } + + MLX5_SET(cqc, cqc, log_cq_size, log_cq_size); mlx5e_build_common_cq_param(priv, param); } @@ -1983,7 +2033,8 @@ static int mlx5e_set_features(struct net_device *netdev, if (changes & NETIF_F_LRO) { bool was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); - if (was_opened) + if (was_opened && (priv->params.rq_wq_type == + MLX5_WQ_TYPE_LINKED_LIST)) mlx5e_close_locked(priv->netdev); priv->params.lro_en = !!(features & NETIF_F_LRO); @@ -1992,7 +2043,8 @@ static int mlx5e_set_features(struct net_device *netdev, mlx5_core_warn(priv->mdev, "lro modify failed, %d\n", err); - if (was_opened) + if (was_opened && (priv->params.rq_wq_type == + MLX5_WQ_TYPE_LINKED_LIST)) err = mlx5e_open_locked(priv->netdev); } @@ -2327,8 +2379,21 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev, priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE; - priv->params.log_rq_size = - MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE; + priv->params.rq_wq_type = MLX5_CAP_GEN(mdev, striding_rq) ? + MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ : + MLX5_WQ_TYPE_LINKED_LIST; + + switch (priv->params.rq_wq_type) { + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: + priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW; + priv->params.lro_en = true; + break; + default: /* MLX5_WQ_TYPE_LINKED_LIST */ + priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE; + } + + priv->params.min_rx_wqes = mlx5_min_rx_wqes(priv->params.rq_wq_type, + BIT(priv->params.log_rq_size)); priv->params.rx_cq_moderation_usec = MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC; priv->params.rx_cq_moderation_pkts = @@ -2338,8 +2403,6 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev, priv->params.tx_cq_moderation_pkts = MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_PKTS; priv->params.tx_max_inline = mlx5e_get_max_inline_cap(mdev); - priv->params.min_rx_wqes = - MLX5E_PARAMS_DEFAULT_MIN_RX_WQES; priv->params.num_tc = 1; priv->params.rss_hfunc = ETH_RSS_HASH_XOR; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index d7cccedddf34..71f3a5d244ff 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -76,6 +76,41 @@ int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) return -ENOMEM; } +int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) +{ + struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; + gfp_t gfp_mask; + int i; + + gfp_mask = GFP_ATOMIC | __GFP_COLD | __GFP_MEMALLOC; + wi->dma_info.page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, + MLX5_MPWRQ_WQE_PAGE_ORDER); + if (unlikely(!wi->dma_info.page)) + return -ENOMEM; + + wi->dma_info.addr = dma_map_page(rq->pdev, wi->dma_info.page, 0, + rq->wqe_sz, PCI_DMA_FROMDEVICE); + if (unlikely(dma_mapping_error(rq->pdev, wi->dma_info.addr))) { + put_page(wi->dma_info.page); + return -ENOMEM; + } + + /* We split the high-order page into order-0 ones and manage their + * reference counter to minimize the memory held by small skb fragments + */ + split_page(wi->dma_info.page, MLX5_MPWRQ_WQE_PAGE_ORDER); + for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) { + atomic_add(MLX5_MPWRQ_STRIDES_PER_PAGE, + &wi->dma_info.page[i]._count); + wi->skbs_frags[i] = 0; + } + + wi->consumed_strides = 0; + wqe->data.addr = cpu_to_be64(wi->dma_info.addr); + + return 0; +} + bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq) { struct mlx5_wq_ll *wq = &rq->wq; @@ -100,7 +135,8 @@ bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq) return !mlx5_wq_ll_is_full(wq); } -static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe) +static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe, + u32 cqe_bcnt) { struct ethhdr *eth = (struct ethhdr *)(skb->data); struct iphdr *ipv4 = (struct iphdr *)(skb->data + ETH_HLEN); @@ -111,7 +147,7 @@ static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe) int tcp_ack = ((CQE_L4_HDR_TYPE_TCP_ACK_NO_DATA == l4_hdr_type) || (CQE_L4_HDR_TYPE_TCP_ACK_AND_DATA == l4_hdr_type)); - u16 tot_len = be32_to_cpu(cqe->byte_cnt) - ETH_HLEN; + u16 tot_len = cqe_bcnt - ETH_HLEN; if (eth->h_proto == htons(ETH_P_IP)) { tcp = (struct tcphdr *)(skb->data + ETH_HLEN + @@ -191,19 +227,17 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, } static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, + u32 cqe_bcnt, struct mlx5e_rq *rq, struct sk_buff *skb) { struct net_device *netdev = rq->netdev; - u32 cqe_bcnt = be32_to_cpu(cqe->byte_cnt); struct mlx5e_tstamp *tstamp = rq->tstamp; int lro_num_seg; - skb_put(skb, cqe_bcnt); - lro_num_seg = be32_to_cpu(cqe->srqn) >> 24; if (lro_num_seg > 1) { - mlx5e_lro_update_hdr(skb, cqe); + mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt); skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg); rq->stats.lro_packets++; rq->stats.lro_bytes += cqe_bcnt; @@ -228,12 +262,24 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, skb->mark = be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK; } +static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq, + struct mlx5_cqe64 *cqe, + u32 cqe_bcnt, + struct sk_buff *skb) +{ + rq->stats.packets++; + rq->stats.bytes += cqe_bcnt; + mlx5e_build_rx_skb(cqe, cqe_bcnt, rq, skb); + napi_gro_receive(rq->cq.napi, skb); +} + void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) { struct mlx5e_rx_wqe *wqe; struct sk_buff *skb; __be16 wqe_counter_be; u16 wqe_counter; + u32 cqe_bcnt; wqe_counter_be = cqe->wqe_counter; wqe_counter = be16_to_cpu(wqe_counter_be); @@ -253,16 +299,103 @@ void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) goto wq_ll_pop; } - mlx5e_build_rx_skb(cqe, rq, skb); - rq->stats.packets++; - rq->stats.bytes += be32_to_cpu(cqe->byte_cnt); - napi_gro_receive(rq->cq.napi, skb); + cqe_bcnt = be32_to_cpu(cqe->byte_cnt); + skb_put(skb, cqe_bcnt); + + mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); wq_ll_pop: mlx5_wq_ll_pop(&rq->wq, wqe_counter_be, &wqe->next.next_wqe_index); } +void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) +{ + u16 cstrides = mpwrq_get_cqe_consumed_strides(cqe); + u16 stride_ix = mpwrq_get_cqe_stride_index(cqe); + u16 wqe_id = be16_to_cpu(cqe->wqe_id); + struct mlx5e_mpw_info *wi = &rq->wqe_info[wqe_id]; + struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, wqe_id); + struct sk_buff *skb; + u32 consumed_bytes; + u32 head_offset; + u32 frag_offset; + u32 wqe_offset; + u32 page_idx; + u16 byte_cnt; + u16 cqe_bcnt; + u16 headlen; + int i; + + wi->consumed_strides += cstrides; + + if (unlikely((cqe->op_own >> 4) != MLX5_CQE_RESP_SEND)) { + rq->stats.wqe_err++; + goto mpwrq_cqe_out; + } + + if (unlikely(mpwrq_is_filler_cqe(cqe))) { + rq->stats.mpwqe_filler++; + goto mpwrq_cqe_out; + } + + skb = netdev_alloc_skb(rq->netdev, + ALIGN(MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, + sizeof(long))); + if (unlikely(!skb)) + goto mpwrq_cqe_out; + + prefetch(skb->data); + wqe_offset = stride_ix * MLX5_MPWRQ_STRIDE_SIZE; + consumed_bytes = cstrides * MLX5_MPWRQ_STRIDE_SIZE; + dma_sync_single_for_cpu(rq->pdev, wi->dma_info.addr + wqe_offset, + consumed_bytes, DMA_FROM_DEVICE); + + head_offset = wqe_offset & (PAGE_SIZE - 1); + page_idx = wqe_offset >> PAGE_SHIFT; + cqe_bcnt = mpwrq_get_cqe_byte_cnt(cqe); + headlen = min_t(u16, MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, cqe_bcnt); + frag_offset = head_offset + headlen; + + byte_cnt = cqe_bcnt - headlen; + while (byte_cnt) { + u32 pg_consumed_bytes = + min_t(u32, PAGE_SIZE - frag_offset, byte_cnt); + unsigned int truesize = + ALIGN(pg_consumed_bytes, MLX5_MPWRQ_STRIDE_SIZE); + + wi->skbs_frags[page_idx]++; + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + &wi->dma_info.page[page_idx], frag_offset, + pg_consumed_bytes, truesize); + byte_cnt -= pg_consumed_bytes; + frag_offset = 0; + page_idx++; + } + + skb_copy_to_linear_data(skb, + page_address(wi->dma_info.page) + wqe_offset, + ALIGN(headlen, sizeof(long))); + /* skb linear part was allocated with headlen and aligned to long */ + skb->tail += headlen; + skb->len += headlen; + + mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); + +mpwrq_cqe_out: + if (likely(wi->consumed_strides < MLX5_MPWRQ_NUM_STRIDES)) + return; + + dma_unmap_page(rq->pdev, wi->dma_info.addr, rq->wqe_sz, + PCI_DMA_FROMDEVICE); + for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) { + atomic_sub(MLX5_MPWRQ_STRIDES_PER_PAGE - wi->skbs_frags[i], + &wi->dma_info.page[i]._count); + put_page(&wi->dma_info.page[i]); + } + mlx5_wq_ll_pop(&rq->wq, cqe->wqe_id, &wqe->next.next_wqe_index); +} + int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget) { struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq); diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 8156e3c9239c..03f8d719b680 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -644,7 +644,8 @@ struct mlx5_err_cqe { }; struct mlx5_cqe64 { - u8 rsvd0[4]; + u8 rsvd0[2]; + __be16 wqe_id; u8 lro_tcppsh_abort_dupack; u8 lro_min_ttl; __be16 lro_tcp_win; @@ -696,6 +697,42 @@ static inline u64 get_cqe_ts(struct mlx5_cqe64 *cqe) return (u64)lo | ((u64)hi << 32); } +struct mpwrq_cqe_bc { + __be16 filler_consumed_strides; + __be16 byte_cnt; +}; + +static inline u16 mpwrq_get_cqe_byte_cnt(struct mlx5_cqe64 *cqe) +{ + struct mpwrq_cqe_bc *bc = (struct mpwrq_cqe_bc *)&cqe->byte_cnt; + + return be16_to_cpu(bc->byte_cnt); +} + +static inline u16 mpwrq_get_cqe_bc_consumed_strides(struct mpwrq_cqe_bc *bc) +{ + return 0x7fff & be16_to_cpu(bc->filler_consumed_strides); +} + +static inline u16 mpwrq_get_cqe_consumed_strides(struct mlx5_cqe64 *cqe) +{ + struct mpwrq_cqe_bc *bc = (struct mpwrq_cqe_bc *)&cqe->byte_cnt; + + return mpwrq_get_cqe_bc_consumed_strides(bc); +} + +static inline bool mpwrq_is_filler_cqe(struct mlx5_cqe64 *cqe) +{ + struct mpwrq_cqe_bc *bc = (struct mpwrq_cqe_bc *)&cqe->byte_cnt; + + return 0x8000 & be16_to_cpu(bc->filler_consumed_strides); +} + +static inline u16 mpwrq_get_cqe_stride_index(struct mlx5_cqe64 *cqe) +{ + return be16_to_cpu(cqe->wqe_counter); +} + enum { CQE_L4_HDR_TYPE_NONE = 0x0, CQE_L4_HDR_TYPE_TCP_NO_ACK = 0x1, -- GitLab From d3c9bc2743dc95b273ed0e6a3394a71ca314813c Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:14 +0300 Subject: [PATCH 3893/9938] net/mlx5e: Added ICO SQs Added ICO (Internal Control Operations) SQ per channel to be used for driver internal operations such as memory registration for fragmented memory and nop requests upon ifconfig up. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 7 + .../net/ethernet/mellanox/mlx5/core/en_main.c | 135 ++++++++++++++---- .../net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_txrx.c | 55 +++++++ 4 files changed, 174 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index f519148d7dcc..a757fcf19332 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -488,6 +488,11 @@ enum { MLX5E_SQ_STATE_BF_ENABLE, }; +struct mlx5e_ico_wqe_info { + u8 opcode; + u8 num_wqebbs; +}; + struct mlx5e_sq { /* data path */ @@ -529,6 +534,7 @@ struct mlx5e_sq { struct mlx5_uar uar; struct mlx5e_channel *channel; int tc; + struct mlx5e_ico_wqe_info *ico_wqe_info; } ____cacheline_aligned_in_smp; static inline bool mlx5e_sq_has_room_for(struct mlx5e_sq *sq, u16 n) @@ -545,6 +551,7 @@ struct mlx5e_channel { /* data path */ struct mlx5e_rq rq; struct mlx5e_sq sq[MLX5E_MAX_NUM_TC]; + struct mlx5e_sq icosq; /* internal control operations */ struct napi_struct napi; struct device *pdev; struct net_device *netdev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 871f3af204dd..b25b429ebabb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -48,6 +48,7 @@ struct mlx5e_sq_param { u32 sqc[MLX5_ST_SZ_DW(sqc)]; struct mlx5_wq_param wq; u16 max_inline; + bool icosq; }; struct mlx5e_cq_param { @@ -59,8 +60,10 @@ struct mlx5e_cq_param { struct mlx5e_channel_param { struct mlx5e_rq_param rq; struct mlx5e_sq_param sq; + struct mlx5e_sq_param icosq; struct mlx5e_cq_param rx_cq; struct mlx5e_cq_param tx_cq; + struct mlx5e_cq_param icosq_cq; }; static void mlx5e_update_carrier(struct mlx5e_priv *priv) @@ -502,6 +505,8 @@ static int mlx5e_open_rq(struct mlx5e_channel *c, struct mlx5e_rq_param *param, struct mlx5e_rq *rq) { + struct mlx5e_sq *sq = &c->icosq; + u16 pi = sq->pc & sq->wq.sz_m1; int err; err = mlx5e_create_rq(c, param, rq); @@ -517,7 +522,10 @@ static int mlx5e_open_rq(struct mlx5e_channel *c, goto err_disable_rq; set_bit(MLX5E_RQ_STATE_POST_WQES_ENABLE, &rq->state); - mlx5e_send_nop(&c->sq[0], true); /* trigger mlx5e_post_rx_wqes() */ + + sq->ico_wqe_info[pi].opcode = MLX5_OPCODE_NOP; + sq->ico_wqe_info[pi].num_wqebbs = 1; + mlx5e_send_nop(sq, true); /* trigger mlx5e_post_rx_wqes() */ return 0; @@ -583,7 +591,6 @@ static int mlx5e_create_sq(struct mlx5e_channel *c, void *sqc = param->sqc; void *sqc_wq = MLX5_ADDR_OF(sqc, sqc, wq); - int txq_ix; int err; err = mlx5_alloc_map_uar(mdev, &sq->uar, true); @@ -611,8 +618,24 @@ static int mlx5e_create_sq(struct mlx5e_channel *c, if (err) goto err_sq_wq_destroy; - txq_ix = c->ix + tc * priv->params.num_channels; - sq->txq = netdev_get_tx_queue(priv->netdev, txq_ix); + if (param->icosq) { + u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq); + + sq->ico_wqe_info = kzalloc_node(sizeof(*sq->ico_wqe_info) * + wq_sz, + GFP_KERNEL, + cpu_to_node(c->cpu)); + if (!sq->ico_wqe_info) { + err = -ENOMEM; + goto err_free_sq_db; + } + } else { + int txq_ix; + + txq_ix = c->ix + tc * priv->params.num_channels; + sq->txq = netdev_get_tx_queue(priv->netdev, txq_ix); + priv->txq_to_sq_map[txq_ix] = sq; + } sq->pdev = c->pdev; sq->tstamp = &priv->tstamp; @@ -621,10 +644,12 @@ static int mlx5e_create_sq(struct mlx5e_channel *c, sq->tc = tc; sq->edge = (sq->wq.sz_m1 + 1) - MLX5_SEND_WQE_MAX_WQEBBS; sq->bf_budget = MLX5E_SQ_BF_BUDGET; - priv->txq_to_sq_map[txq_ix] = sq; return 0; +err_free_sq_db: + mlx5e_free_sq_db(sq); + err_sq_wq_destroy: mlx5_wq_destroy(&sq->wq_ctrl); @@ -639,6 +664,7 @@ static void mlx5e_destroy_sq(struct mlx5e_sq *sq) struct mlx5e_channel *c = sq->channel; struct mlx5e_priv *priv = c->priv; + kfree(sq->ico_wqe_info); mlx5e_free_sq_db(sq); mlx5_wq_destroy(&sq->wq_ctrl); mlx5_unmap_free_uar(priv->mdev, &sq->uar); @@ -667,10 +693,10 @@ static int mlx5e_enable_sq(struct mlx5e_sq *sq, struct mlx5e_sq_param *param) memcpy(sqc, param->sqc, sizeof(param->sqc)); - MLX5_SET(sqc, sqc, tis_num_0, priv->tisn[sq->tc]); - MLX5_SET(sqc, sqc, cqn, c->sq[sq->tc].cq.mcq.cqn); + MLX5_SET(sqc, sqc, tis_num_0, param->icosq ? 0 : priv->tisn[sq->tc]); + MLX5_SET(sqc, sqc, cqn, sq->cq.mcq.cqn); MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST); - MLX5_SET(sqc, sqc, tis_lst_sz, 1); + MLX5_SET(sqc, sqc, tis_lst_sz, param->icosq ? 0 : 1); MLX5_SET(sqc, sqc, flush_in_error_en, 1); MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); @@ -745,9 +771,11 @@ static int mlx5e_open_sq(struct mlx5e_channel *c, if (err) goto err_disable_sq; - set_bit(MLX5E_SQ_STATE_WAKE_TXQ_ENABLE, &sq->state); - netdev_tx_reset_queue(sq->txq); - netif_tx_start_queue(sq->txq); + if (sq->txq) { + set_bit(MLX5E_SQ_STATE_WAKE_TXQ_ENABLE, &sq->state); + netdev_tx_reset_queue(sq->txq); + netif_tx_start_queue(sq->txq); + } return 0; @@ -768,15 +796,19 @@ static inline void netif_tx_disable_queue(struct netdev_queue *txq) static void mlx5e_close_sq(struct mlx5e_sq *sq) { - clear_bit(MLX5E_SQ_STATE_WAKE_TXQ_ENABLE, &sq->state); - napi_synchronize(&sq->channel->napi); /* prevent netif_tx_wake_queue */ - netif_tx_disable_queue(sq->txq); + if (sq->txq) { + clear_bit(MLX5E_SQ_STATE_WAKE_TXQ_ENABLE, &sq->state); + /* prevent netif_tx_wake_queue */ + napi_synchronize(&sq->channel->napi); + netif_tx_disable_queue(sq->txq); - /* ensure hw is notified of all pending wqes */ - if (mlx5e_sq_has_room_for(sq, 1)) - mlx5e_send_nop(sq, true); + /* ensure hw is notified of all pending wqes */ + if (mlx5e_sq_has_room_for(sq, 1)) + mlx5e_send_nop(sq, true); + + mlx5e_modify_sq(sq, MLX5_SQC_STATE_RDY, MLX5_SQC_STATE_ERR); + } - mlx5e_modify_sq(sq, MLX5_SQC_STATE_RDY, MLX5_SQC_STATE_ERR); while (sq->cc != sq->pc) /* wait till sq is empty */ msleep(20); @@ -1030,10 +1062,14 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64); - err = mlx5e_open_tx_cqs(c, cparam); + err = mlx5e_open_cq(c, &cparam->icosq_cq, &c->icosq.cq, 0, 0); if (err) goto err_napi_del; + err = mlx5e_open_tx_cqs(c, cparam); + if (err) + goto err_close_icosq_cq; + err = mlx5e_open_cq(c, &cparam->rx_cq, &c->rq.cq, priv->params.rx_cq_moderation_usec, priv->params.rx_cq_moderation_pkts); @@ -1042,10 +1078,14 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, napi_enable(&c->napi); - err = mlx5e_open_sqs(c, cparam); + err = mlx5e_open_sq(c, 0, &cparam->icosq, &c->icosq); if (err) goto err_disable_napi; + err = mlx5e_open_sqs(c, cparam); + if (err) + goto err_close_icosq; + err = mlx5e_open_rq(c, &cparam->rq, &c->rq); if (err) goto err_close_sqs; @@ -1058,6 +1098,9 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, err_close_sqs: mlx5e_close_sqs(c); +err_close_icosq: + mlx5e_close_sq(&c->icosq); + err_disable_napi: napi_disable(&c->napi); mlx5e_close_cq(&c->rq.cq); @@ -1065,6 +1108,9 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, err_close_tx_cqs: mlx5e_close_tx_cqs(c); +err_close_icosq_cq: + mlx5e_close_cq(&c->icosq.cq); + err_napi_del: netif_napi_del(&c->napi); napi_hash_del(&c->napi); @@ -1077,9 +1123,11 @@ static void mlx5e_close_channel(struct mlx5e_channel *c) { mlx5e_close_rq(&c->rq); mlx5e_close_sqs(c); + mlx5e_close_sq(&c->icosq); napi_disable(&c->napi); mlx5e_close_cq(&c->rq.cq); mlx5e_close_tx_cqs(c); + mlx5e_close_cq(&c->icosq.cq); netif_napi_del(&c->napi); napi_hash_del(&c->napi); @@ -1125,17 +1173,27 @@ static void mlx5e_build_drop_rq_param(struct mlx5e_rq_param *param) MLX5_SET(wq, wq, log_wq_stride, ilog2(sizeof(struct mlx5e_rx_wqe))); } -static void mlx5e_build_sq_param(struct mlx5e_priv *priv, - struct mlx5e_sq_param *param) +static void mlx5e_build_sq_param_common(struct mlx5e_priv *priv, + struct mlx5e_sq_param *param) { void *sqc = param->sqc; void *wq = MLX5_ADDR_OF(sqc, sqc, wq); - MLX5_SET(wq, wq, log_wq_sz, priv->params.log_sq_size); MLX5_SET(wq, wq, log_wq_stride, ilog2(MLX5_SEND_WQE_BB)); MLX5_SET(wq, wq, pd, priv->pdn); param->wq.buf_numa_node = dev_to_node(&priv->mdev->pdev->dev); +} + +static void mlx5e_build_sq_param(struct mlx5e_priv *priv, + struct mlx5e_sq_param *param) +{ + void *sqc = param->sqc; + void *wq = MLX5_ADDR_OF(sqc, sqc, wq); + + mlx5e_build_sq_param_common(priv, param); + MLX5_SET(wq, wq, log_wq_sz, priv->params.log_sq_size); + param->max_inline = priv->params.tx_max_inline; } @@ -1172,20 +1230,49 @@ static void mlx5e_build_tx_cq_param(struct mlx5e_priv *priv, { void *cqc = param->cqc; - MLX5_SET(cqc, cqc, log_cq_size, priv->params.log_sq_size); + MLX5_SET(cqc, cqc, log_cq_size, priv->params.log_sq_size); mlx5e_build_common_cq_param(priv, param); } +static void mlx5e_build_ico_cq_param(struct mlx5e_priv *priv, + struct mlx5e_cq_param *param, + u8 log_wq_size) +{ + void *cqc = param->cqc; + + MLX5_SET(cqc, cqc, log_cq_size, log_wq_size); + + mlx5e_build_common_cq_param(priv, param); +} + +static void mlx5e_build_icosq_param(struct mlx5e_priv *priv, + struct mlx5e_sq_param *param, + u8 log_wq_size) +{ + void *sqc = param->sqc; + void *wq = MLX5_ADDR_OF(sqc, sqc, wq); + + mlx5e_build_sq_param_common(priv, param); + + MLX5_SET(wq, wq, log_wq_sz, log_wq_size); + + param->icosq = true; +} + static void mlx5e_build_channel_param(struct mlx5e_priv *priv, struct mlx5e_channel_param *cparam) { + u8 icosq_log_wq_sz = 0; + memset(cparam, 0, sizeof(*cparam)); mlx5e_build_rq_param(priv, &cparam->rq); mlx5e_build_sq_param(priv, &cparam->sq); + mlx5e_build_icosq_param(priv, &cparam->icosq, icosq_log_wq_sz); mlx5e_build_rx_cq_param(priv, &cparam->rx_cq); mlx5e_build_tx_cq_param(priv, &cparam->tx_cq); + mlx5e_build_ico_cq_param(priv, &cparam->icosq_cq, icosq_log_wq_sz); } static int mlx5e_open_channels(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 1ffc7cb6f78c..a8d2935c50d0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -54,6 +54,7 @@ void mlx5e_send_nop(struct mlx5e_sq *sq, bool notify_hw) sq->skb[pi] = NULL; sq->pc++; + sq->stats.nop++; if (notify_hw) { cseg->fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE; @@ -387,7 +388,6 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) wi = &sq->wqe_info[ci]; if (unlikely(!skb)) { /* nop */ - sq->stats.nop++; sqcc++; continue; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c index 9bb4395aceeb..ad624cb6f147 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c @@ -49,6 +49,57 @@ struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq) return cqe; } +static void mlx5e_poll_ico_cq(struct mlx5e_cq *cq) +{ + struct mlx5_wq_cyc *wq; + struct mlx5_cqe64 *cqe; + struct mlx5e_sq *sq; + u16 sqcc; + + cqe = mlx5e_get_cqe(cq); + if (likely(!cqe)) + return; + + sq = container_of(cq, struct mlx5e_sq, cq); + wq = &sq->wq; + + /* sq->cc must be updated only after mlx5_cqwq_update_db_record(), + * otherwise a cq overrun may occur + */ + sqcc = sq->cc; + + do { + u16 ci = be16_to_cpu(cqe->wqe_counter) & wq->sz_m1; + struct mlx5e_ico_wqe_info *icowi = &sq->ico_wqe_info[ci]; + + mlx5_cqwq_pop(&cq->wq); + sqcc += icowi->num_wqebbs; + + if (unlikely((cqe->op_own >> 4) != MLX5_CQE_REQ)) { + WARN_ONCE(true, "mlx5e: Bad OP in ICOSQ CQE: 0x%x\n", + cqe->op_own); + break; + } + + switch (icowi->opcode) { + case MLX5_OPCODE_NOP: + break; + default: + WARN_ONCE(true, + "mlx5e: Bad OPCODE in ICOSQ WQE info: 0x%x\n", + icowi->opcode); + } + + } while ((cqe = mlx5e_get_cqe(cq))); + + mlx5_cqwq_update_db_record(&cq->wq); + + /* ensure cq space is freed before enabling more cqes */ + wmb(); + + sq->cc = sqcc; +} + int mlx5e_napi_poll(struct napi_struct *napi, int budget) { struct mlx5e_channel *c = container_of(napi, struct mlx5e_channel, @@ -64,6 +115,9 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget) work_done = mlx5e_poll_rx_cq(&c->rq.cq, budget); busy |= work_done == budget; + + mlx5e_poll_ico_cq(&c->icosq.cq); + busy |= mlx5e_post_rx_wqes(&c->rq); if (busy) @@ -80,6 +134,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget) for (i = 0; i < c->num_tc; i++) mlx5e_cq_arm(&c->sq[i].cq); mlx5e_cq_arm(&c->rq.cq); + mlx5e_cq_arm(&c->icosq.cq); return work_done; } -- GitLab From bc77b240b3c57236cdcc08d64ca390655d3a16ff Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:15 +0300 Subject: [PATCH 3894/9938] net/mlx5e: Add fragmented memory support for RX multi packet WQE If the allocation of a linear (physically continuous) MPWQE fails, we allocate a fragmented MPWQE. This is implemented via device's UMR (User Memory Registration) which allows to register multiple memory fragments into ConnectX hardware as a continuous buffer. UMR registration is an asynchronous operation and is done via ICO SQs. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 84 +++- .../net/ethernet/mellanox/mlx5/core/en_main.c | 64 ++- .../net/ethernet/mellanox/mlx5/core/en_rx.c | 427 +++++++++++++++--- .../net/ethernet/mellanox/mlx5/core/en_tx.c | 4 +- .../net/ethernet/mellanox/mlx5/core/en_txrx.c | 3 + 5 files changed, 514 insertions(+), 68 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index a757fcf19332..c99fdff74c97 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -72,6 +72,9 @@ #define MLX5_MPWRQ_PAGES_PER_WQE BIT(MLX5_MPWRQ_WQE_PAGE_ORDER) #define MLX5_MPWRQ_STRIDES_PER_PAGE (MLX5_MPWRQ_NUM_STRIDES >> \ MLX5_MPWRQ_WQE_PAGE_ORDER) +#define MLX5_CHANNEL_MAX_NUM_MTTS (ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8) * \ + BIT(MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW)) +#define MLX5_UMR_ALIGN (2048) #define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (128) #define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024) @@ -134,6 +137,13 @@ struct mlx5e_rx_wqe { struct mlx5_wqe_data_seg data; }; +struct mlx5e_umr_wqe { + struct mlx5_wqe_ctrl_seg ctrl; + struct mlx5_wqe_umr_ctrl_seg uctrl; + struct mlx5_mkey_seg mkc; + struct mlx5_wqe_data_seg data; +}; + #ifdef CONFIG_MLX5_CORE_EN_DCB #define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */ #define MLX5E_MIN_BW_ALLOC 1 /* Min percentage of BW allocation */ @@ -179,6 +189,7 @@ static const char vport_strings[][ETH_GSTRING_LEN] = { "tx_queue_dropped", "rx_wqe_err", "rx_mpwqe_filler", + "rx_mpwqe_frag", }; struct mlx5e_vport_stats { @@ -221,8 +232,9 @@ struct mlx5e_vport_stats { u64 tx_queue_dropped; u64 rx_wqe_err; u64 rx_mpwqe_filler; + u64 rx_mpwqe_frag; -#define NUM_VPORT_COUNTERS 36 +#define NUM_VPORT_COUNTERS 37 }; static const char pport_strings[][ETH_GSTRING_LEN] = { @@ -317,6 +329,7 @@ static const char rq_stats_strings[][ETH_GSTRING_LEN] = { "lro_bytes", "wqe_err", "mpwqe_filler", + "mpwqe_frag", }; struct mlx5e_rq_stats { @@ -328,7 +341,8 @@ struct mlx5e_rq_stats { u64 lro_bytes; u64 wqe_err; u64 mpwqe_filler; -#define NUM_RQ_STATS 8 + u64 mpwqe_frag; +#define NUM_RQ_STATS 9 }; static const char sq_stats_strings[][ETH_GSTRING_LEN] = { @@ -407,6 +421,7 @@ struct mlx5e_tstamp { enum { MLX5E_RQ_STATE_POST_WQES_ENABLE, + MLX5E_RQ_STATE_UMR_WQE_IN_PROGRESS, }; struct mlx5e_cq { @@ -434,18 +449,14 @@ struct mlx5e_dma_info { dma_addr_t addr; }; -struct mlx5e_mpw_info { - struct mlx5e_dma_info dma_info; - u16 consumed_strides; - u16 skbs_frags[MLX5_MPWRQ_PAGES_PER_WQE]; -}; - struct mlx5e_rq { /* data path */ struct mlx5_wq_ll wq; u32 wqe_sz; struct sk_buff **skb; struct mlx5e_mpw_info *wqe_info; + __be32 mkey_be; + __be32 umr_mkey_be; struct device *pdev; struct net_device *netdev; @@ -466,6 +477,36 @@ struct mlx5e_rq { struct mlx5e_priv *priv; } ____cacheline_aligned_in_smp; +struct mlx5e_umr_dma_info { + __be64 *mtt; + __be64 *mtt_no_align; + dma_addr_t mtt_addr; + struct mlx5e_dma_info *dma_info; +}; + +struct mlx5e_mpw_info { + union { + struct mlx5e_dma_info dma_info; + struct mlx5e_umr_dma_info umr; + }; + u16 consumed_strides; + u16 skbs_frags[MLX5_MPWRQ_PAGES_PER_WQE]; + + void (*dma_pre_sync)(struct device *pdev, + struct mlx5e_mpw_info *wi, + u32 wqe_offset, u32 len); + void (*add_skb_frag)(struct device *pdev, + struct sk_buff *skb, + struct mlx5e_mpw_info *wi, + u32 page_idx, u32 frag_offset, u32 len); + void (*copy_skb_header)(struct device *pdev, + struct sk_buff *skb, + struct mlx5e_mpw_info *wi, + u32 page_idx, u32 offset, + u32 headlen); + void (*free_wqe)(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi); +}; + struct mlx5e_tx_wqe_info { u32 num_bytes; u8 num_wqebbs; @@ -658,6 +699,7 @@ struct mlx5e_priv { u32 pdn; u32 tdn; struct mlx5_core_mkey mkey; + struct mlx5_core_mkey umr_mkey; struct mlx5e_rq drop_rq; struct mlx5e_channel **channel; @@ -730,6 +772,21 @@ void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq); int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix); int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix); +void mlx5e_post_rx_fragmented_mpwqe(struct mlx5e_rq *rq); +void mlx5e_complete_rx_linear_mpwqe(struct mlx5e_rq *rq, + struct mlx5_cqe64 *cqe, + u16 byte_cnt, + struct mlx5e_mpw_info *wi, + struct sk_buff *skb); +void mlx5e_complete_rx_fragmented_mpwqe(struct mlx5e_rq *rq, + struct mlx5_cqe64 *cqe, + u16 byte_cnt, + struct mlx5e_mpw_info *wi, + struct sk_buff *skb); +void mlx5e_free_rx_linear_mpwqe(struct mlx5e_rq *rq, + struct mlx5e_mpw_info *wi); +void mlx5e_free_rx_fragmented_mpwqe(struct mlx5e_rq *rq, + struct mlx5e_mpw_info *wi); struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq); void mlx5e_update_stats(struct mlx5e_priv *priv); @@ -763,7 +820,7 @@ void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev, int num_channels); static inline void mlx5e_tx_notify_hw(struct mlx5e_sq *sq, - struct mlx5e_tx_wqe *wqe, int bf_sz) + struct mlx5_wqe_ctrl_seg *ctrl, int bf_sz) { u16 ofst = MLX5_BF_OFFSET + sq->bf_offset; @@ -777,9 +834,9 @@ static inline void mlx5e_tx_notify_hw(struct mlx5e_sq *sq, */ wmb(); if (bf_sz) - __iowrite64_copy(sq->uar_map + ofst, &wqe->ctrl, bf_sz); + __iowrite64_copy(sq->uar_map + ofst, ctrl, bf_sz); else - mlx5_write64((__be32 *)&wqe->ctrl, sq->uar_map + ofst, NULL); + mlx5_write64((__be32 *)ctrl, sq->uar_map + ofst, NULL); /* flush the write-combining mapped buffer */ wmb(); @@ -800,6 +857,11 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev) MLX5E_MAX_NUM_CHANNELS); } +static inline int mlx5e_get_mtt_octw(int npages) +{ + return ALIGN(npages, 8) / 2; +} + extern const struct ethtool_ops mlx5e_ethtool_ops; #ifdef CONFIG_MLX5_CORE_EN_DCB extern const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index b25b429ebabb..942829e6d8ba 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -179,6 +179,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) s->rx_csum_sw = 0; s->rx_wqe_err = 0; s->rx_mpwqe_filler = 0; + s->rx_mpwqe_frag = 0; for (i = 0; i < priv->params.num_channels; i++) { rq_stats = &priv->channel[i]->rq.stats; @@ -190,6 +191,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) s->rx_csum_sw += rq_stats->csum_sw; s->rx_wqe_err += rq_stats->wqe_err; s->rx_mpwqe_filler += rq_stats->mpwqe_filler; + s->rx_mpwqe_frag += rq_stats->mpwqe_frag; for (j = 0; j < priv->params.num_tc; j++) { sq_stats = &priv->channel[i]->sq[j].stats; @@ -379,7 +381,6 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, for (i = 0; i < wq_sz; i++) { struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, i); - wqe->data.lkey = c->mkey_be; wqe->data.byte_count = cpu_to_be32(byte_count); } @@ -390,6 +391,8 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, rq->channel = c; rq->ix = c->ix; rq->priv = c->priv; + rq->mkey_be = c->mkey_be; + rq->umr_mkey_be = cpu_to_be32(c->priv->umr_mkey.key); return 0; @@ -1256,6 +1259,7 @@ static void mlx5e_build_icosq_param(struct mlx5e_priv *priv, mlx5e_build_sq_param_common(priv, param); MLX5_SET(wq, wq, log_wq_sz, log_wq_size); + MLX5_SET(sqc, sqc, reg_umr, MLX5_CAP_ETH(priv->mdev, reg_umr_sq)); param->icosq = true; } @@ -1263,7 +1267,7 @@ static void mlx5e_build_icosq_param(struct mlx5e_priv *priv, static void mlx5e_build_channel_param(struct mlx5e_priv *priv, struct mlx5e_channel_param *cparam) { - u8 icosq_log_wq_sz = 0; + u8 icosq_log_wq_sz = MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE; memset(cparam, 0, sizeof(*cparam)); @@ -2458,6 +2462,13 @@ void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev, indirection_rqt[i] = i % num_channels; } +static bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev) +{ + return MLX5_CAP_GEN(mdev, striding_rq) && + MLX5_CAP_GEN(mdev, umr_ptr_rlky) && + MLX5_CAP_ETH(mdev, reg_umr_sq); +} + static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev, struct net_device *netdev, int num_channels) @@ -2466,7 +2477,7 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev, priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE; - priv->params.rq_wq_type = MLX5_CAP_GEN(mdev, striding_rq) ? + priv->params.rq_wq_type = mlx5e_check_fragmented_striding_rq_cap(mdev) ? MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ : MLX5_WQ_TYPE_LINKED_LIST; @@ -2639,6 +2650,41 @@ static void mlx5e_destroy_q_counter(struct mlx5e_priv *priv) mlx5_core_dealloc_q_counter(priv->mdev, priv->q_counter); } +static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv) +{ + struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5_create_mkey_mbox_in *in; + struct mlx5_mkey_seg *mkc; + int inlen = sizeof(*in); + u64 npages = + mlx5e_get_max_num_channels(mdev) * MLX5_CHANNEL_MAX_NUM_MTTS; + int err; + + in = mlx5_vzalloc(inlen); + if (!in) + return -ENOMEM; + + mkc = &in->seg; + mkc->status = MLX5_MKEY_STATUS_FREE; + mkc->flags = MLX5_PERM_UMR_EN | + MLX5_PERM_LOCAL_READ | + MLX5_PERM_LOCAL_WRITE | + MLX5_ACCESS_MODE_MTT; + + mkc->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); + mkc->flags_pd = cpu_to_be32(priv->pdn); + mkc->len = cpu_to_be64(npages << PAGE_SHIFT); + mkc->xlt_oct_size = cpu_to_be32(mlx5e_get_mtt_octw(npages)); + mkc->log2_page_size = PAGE_SHIFT; + + err = mlx5_core_create_mkey(mdev, &priv->umr_mkey, in, inlen, NULL, + NULL, NULL); + + kvfree(in); + + return err; +} + static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) { struct net_device *netdev; @@ -2688,10 +2734,16 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) goto err_dealloc_transport_domain; } + err = mlx5e_create_umr_mkey(priv); + if (err) { + mlx5_core_err(mdev, "create umr mkey failed, %d\n", err); + goto err_destroy_mkey; + } + err = mlx5e_create_tises(priv); if (err) { mlx5_core_warn(mdev, "create tises failed, %d\n", err); - goto err_destroy_mkey; + goto err_destroy_umr_mkey; } err = mlx5e_open_drop_rq(priv); @@ -2774,6 +2826,9 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) err_destroy_tises: mlx5e_destroy_tises(priv); +err_destroy_umr_mkey: + mlx5_core_destroy_mkey(mdev, &priv->umr_mkey); + err_destroy_mkey: mlx5_core_destroy_mkey(mdev, &priv->mkey); @@ -2812,6 +2867,7 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv) mlx5e_destroy_rqt(priv, MLX5E_INDIRECTION_RQT); mlx5e_close_drop_rq(priv); mlx5e_destroy_tises(priv); + mlx5_core_destroy_mkey(priv->mdev, &priv->umr_mkey); mlx5_core_destroy_mkey(priv->mdev, &priv->mkey); mlx5_core_dealloc_transport_domain(priv->mdev, priv->tdn); mlx5_core_dealloc_pd(priv->mdev, priv->pdn); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 71f3a5d244ff..d71919ccf912 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -65,6 +65,7 @@ int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) *((dma_addr_t *)skb->cb) = dma_addr; wqe->data.addr = cpu_to_be64(dma_addr + MLX5E_NET_IP_ALIGN); + wqe->data.lkey = rq->mkey_be; rq->skb[ix] = skb; @@ -76,7 +77,295 @@ int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) return -ENOMEM; } -int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) +static inline void +mlx5e_dma_pre_sync_linear_mpwqe(struct device *pdev, + struct mlx5e_mpw_info *wi, + u32 wqe_offset, u32 len) +{ + dma_sync_single_for_cpu(pdev, wi->dma_info.addr + wqe_offset, + len, DMA_FROM_DEVICE); +} + +static inline void +mlx5e_dma_pre_sync_fragmented_mpwqe(struct device *pdev, + struct mlx5e_mpw_info *wi, + u32 wqe_offset, u32 len) +{ + /* No dma pre sync for fragmented MPWQE */ +} + +static inline void +mlx5e_add_skb_frag_linear_mpwqe(struct device *pdev, + struct sk_buff *skb, + struct mlx5e_mpw_info *wi, + u32 page_idx, u32 frag_offset, + u32 len) +{ + unsigned int truesize = ALIGN(len, MLX5_MPWRQ_STRIDE_SIZE); + + wi->skbs_frags[page_idx]++; + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + &wi->dma_info.page[page_idx], frag_offset, + len, truesize); +} + +static inline void +mlx5e_add_skb_frag_fragmented_mpwqe(struct device *pdev, + struct sk_buff *skb, + struct mlx5e_mpw_info *wi, + u32 page_idx, u32 frag_offset, + u32 len) +{ + unsigned int truesize = ALIGN(len, MLX5_MPWRQ_STRIDE_SIZE); + + dma_sync_single_for_cpu(pdev, + wi->umr.dma_info[page_idx].addr + frag_offset, + len, DMA_FROM_DEVICE); + wi->skbs_frags[page_idx]++; + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + wi->umr.dma_info[page_idx].page, frag_offset, + len, truesize); +} + +static inline void +mlx5e_copy_skb_header_linear_mpwqe(struct device *pdev, + struct sk_buff *skb, + struct mlx5e_mpw_info *wi, + u32 page_idx, u32 offset, + u32 headlen) +{ + struct page *page = &wi->dma_info.page[page_idx]; + + skb_copy_to_linear_data(skb, page_address(page) + offset, + ALIGN(headlen, sizeof(long))); +} + +static inline void +mlx5e_copy_skb_header_fragmented_mpwqe(struct device *pdev, + struct sk_buff *skb, + struct mlx5e_mpw_info *wi, + u32 page_idx, u32 offset, + u32 headlen) +{ + u16 headlen_pg = min_t(u32, headlen, PAGE_SIZE - offset); + struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[page_idx]; + unsigned int len; + + /* Aligning len to sizeof(long) optimizes memcpy performance */ + len = ALIGN(headlen_pg, sizeof(long)); + dma_sync_single_for_cpu(pdev, dma_info->addr + offset, len, + DMA_FROM_DEVICE); + skb_copy_to_linear_data_offset(skb, 0, + page_address(dma_info->page) + offset, + len); +#if (MLX5_MPWRQ_SMALL_PACKET_THRESHOLD >= MLX5_MPWRQ_STRIDE_SIZE) + if (unlikely(offset + headlen > PAGE_SIZE)) { + dma_info++; + headlen_pg = len; + len = ALIGN(headlen - headlen_pg, sizeof(long)); + dma_sync_single_for_cpu(pdev, dma_info->addr, len, + DMA_FROM_DEVICE); + skb_copy_to_linear_data_offset(skb, headlen_pg, + page_address(dma_info->page), + len); + } +#endif +} + +static u16 mlx5e_get_wqe_mtt_offset(u16 rq_ix, u16 wqe_ix) +{ + return rq_ix * MLX5_CHANNEL_MAX_NUM_MTTS + + wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8); +} + +static void mlx5e_build_umr_wqe(struct mlx5e_rq *rq, + struct mlx5e_sq *sq, + struct mlx5e_umr_wqe *wqe, + u16 ix) +{ + struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl; + struct mlx5_wqe_umr_ctrl_seg *ucseg = &wqe->uctrl; + struct mlx5_wqe_data_seg *dseg = &wqe->data; + struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; + u8 ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS); + u16 umr_wqe_mtt_offset = mlx5e_get_wqe_mtt_offset(rq->ix, ix); + + memset(wqe, 0, sizeof(*wqe)); + cseg->opmod_idx_opcode = + cpu_to_be32((sq->pc << MLX5_WQE_CTRL_WQE_INDEX_SHIFT) | + MLX5_OPCODE_UMR); + cseg->qpn_ds = cpu_to_be32((sq->sqn << MLX5_WQE_CTRL_QPN_SHIFT) | + ds_cnt); + cseg->fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE; + cseg->imm = rq->umr_mkey_be; + + ucseg->flags = MLX5_UMR_TRANSLATION_OFFSET_EN; + ucseg->klm_octowords = + cpu_to_be16(mlx5e_get_mtt_octw(MLX5_MPWRQ_PAGES_PER_WQE)); + ucseg->bsf_octowords = + cpu_to_be16(mlx5e_get_mtt_octw(umr_wqe_mtt_offset)); + ucseg->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE); + + dseg->lkey = sq->mkey_be; + dseg->addr = cpu_to_be64(wi->umr.mtt_addr); +} + +static void mlx5e_post_umr_wqe(struct mlx5e_rq *rq, u16 ix) +{ + struct mlx5e_sq *sq = &rq->channel->icosq; + struct mlx5_wq_cyc *wq = &sq->wq; + struct mlx5e_umr_wqe *wqe; + u8 num_wqebbs = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_BB); + u16 pi; + + /* fill sq edge with nops to avoid wqe wrap around */ + while ((pi = (sq->pc & wq->sz_m1)) > sq->edge) { + sq->ico_wqe_info[pi].opcode = MLX5_OPCODE_NOP; + sq->ico_wqe_info[pi].num_wqebbs = 1; + mlx5e_send_nop(sq, true); + } + + wqe = mlx5_wq_cyc_get_wqe(wq, pi); + mlx5e_build_umr_wqe(rq, sq, wqe, ix); + sq->ico_wqe_info[pi].opcode = MLX5_OPCODE_UMR; + sq->ico_wqe_info[pi].num_wqebbs = num_wqebbs; + sq->pc += num_wqebbs; + mlx5e_tx_notify_hw(sq, &wqe->ctrl, 0); +} + +static inline int mlx5e_get_wqe_mtt_sz(void) +{ + /* UMR copies MTTs in units of MLX5_UMR_MTT_ALIGNMENT bytes. + * To avoid copying garbage after the mtt array, we allocate + * a little more. + */ + return ALIGN(MLX5_MPWRQ_PAGES_PER_WQE * sizeof(__be64), + MLX5_UMR_MTT_ALIGNMENT); +} + +static int mlx5e_alloc_and_map_page(struct mlx5e_rq *rq, + struct mlx5e_mpw_info *wi, + int i) +{ + struct page *page; + + page = dev_alloc_page(); + if (unlikely(!page)) + return -ENOMEM; + + wi->umr.dma_info[i].page = page; + wi->umr.dma_info[i].addr = dma_map_page(rq->pdev, page, 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + if (unlikely(dma_mapping_error(rq->pdev, wi->umr.dma_info[i].addr))) { + put_page(page); + return -ENOMEM; + } + wi->umr.mtt[i] = cpu_to_be64(wi->umr.dma_info[i].addr | MLX5_EN_WR); + + return 0; +} + +static int mlx5e_alloc_rx_fragmented_mpwqe(struct mlx5e_rq *rq, + struct mlx5e_rx_wqe *wqe, + u16 ix) +{ + struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; + int mtt_sz = mlx5e_get_wqe_mtt_sz(); + u32 dma_offset = mlx5e_get_wqe_mtt_offset(rq->ix, ix) << PAGE_SHIFT; + int i; + + wi->umr.dma_info = kmalloc(sizeof(*wi->umr.dma_info) * + MLX5_MPWRQ_PAGES_PER_WQE, + GFP_ATOMIC); + if (unlikely(!wi->umr.dma_info)) + goto err_out; + + /* We allocate more than mtt_sz as we will align the pointer */ + wi->umr.mtt_no_align = kzalloc(mtt_sz + MLX5_UMR_ALIGN - 1, + GFP_ATOMIC); + if (unlikely(!wi->umr.mtt_no_align)) + goto err_free_umr; + + wi->umr.mtt = PTR_ALIGN(wi->umr.mtt_no_align, MLX5_UMR_ALIGN); + wi->umr.mtt_addr = dma_map_single(rq->pdev, wi->umr.mtt, mtt_sz, + PCI_DMA_TODEVICE); + if (unlikely(dma_mapping_error(rq->pdev, wi->umr.mtt_addr))) + goto err_free_mtt; + + for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) { + if (unlikely(mlx5e_alloc_and_map_page(rq, wi, i))) + goto err_unmap; + atomic_add(MLX5_MPWRQ_STRIDES_PER_PAGE, + &wi->umr.dma_info[i].page->_count); + wi->skbs_frags[i] = 0; + } + + wi->consumed_strides = 0; + wi->dma_pre_sync = mlx5e_dma_pre_sync_fragmented_mpwqe; + wi->add_skb_frag = mlx5e_add_skb_frag_fragmented_mpwqe; + wi->copy_skb_header = mlx5e_copy_skb_header_fragmented_mpwqe; + wi->free_wqe = mlx5e_free_rx_fragmented_mpwqe; + wqe->data.lkey = rq->umr_mkey_be; + wqe->data.addr = cpu_to_be64(dma_offset); + + return 0; + +err_unmap: + while (--i >= 0) { + dma_unmap_page(rq->pdev, wi->umr.dma_info[i].addr, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + atomic_sub(MLX5_MPWRQ_STRIDES_PER_PAGE, + &wi->umr.dma_info[i].page->_count); + put_page(wi->umr.dma_info[i].page); + } + dma_unmap_single(rq->pdev, wi->umr.mtt_addr, mtt_sz, PCI_DMA_TODEVICE); + +err_free_mtt: + kfree(wi->umr.mtt_no_align); + +err_free_umr: + kfree(wi->umr.dma_info); + +err_out: + return -ENOMEM; +} + +void mlx5e_free_rx_fragmented_mpwqe(struct mlx5e_rq *rq, + struct mlx5e_mpw_info *wi) +{ + int mtt_sz = mlx5e_get_wqe_mtt_sz(); + int i; + + for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) { + dma_unmap_page(rq->pdev, wi->umr.dma_info[i].addr, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + atomic_sub(MLX5_MPWRQ_STRIDES_PER_PAGE - wi->skbs_frags[i], + &wi->umr.dma_info[i].page->_count); + put_page(wi->umr.dma_info[i].page); + } + dma_unmap_single(rq->pdev, wi->umr.mtt_addr, mtt_sz, PCI_DMA_TODEVICE); + kfree(wi->umr.mtt_no_align); + kfree(wi->umr.dma_info); +} + +void mlx5e_post_rx_fragmented_mpwqe(struct mlx5e_rq *rq) +{ + struct mlx5_wq_ll *wq = &rq->wq; + struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(wq, wq->head); + + clear_bit(MLX5E_RQ_STATE_UMR_WQE_IN_PROGRESS, &rq->state); + mlx5_wq_ll_push(wq, be16_to_cpu(wqe->next.next_wqe_index)); + rq->stats.mpwqe_frag++; + + /* ensure wqes are visible to device before updating doorbell record */ + dma_wmb(); + + mlx5_wq_ll_update_db_record(wq); +} + +static int mlx5e_alloc_rx_linear_mpwqe(struct mlx5e_rq *rq, + struct mlx5e_rx_wqe *wqe, + u16 ix) { struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; gfp_t gfp_mask; @@ -106,16 +395,56 @@ int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) } wi->consumed_strides = 0; - wqe->data.addr = cpu_to_be64(wi->dma_info.addr); + wi->dma_pre_sync = mlx5e_dma_pre_sync_linear_mpwqe; + wi->add_skb_frag = mlx5e_add_skb_frag_linear_mpwqe; + wi->copy_skb_header = mlx5e_copy_skb_header_linear_mpwqe; + wi->free_wqe = mlx5e_free_rx_linear_mpwqe; + wqe->data.lkey = rq->mkey_be; + wqe->data.addr = cpu_to_be64(wi->dma_info.addr); + + return 0; +} + +void mlx5e_free_rx_linear_mpwqe(struct mlx5e_rq *rq, + struct mlx5e_mpw_info *wi) +{ + int i; + + dma_unmap_page(rq->pdev, wi->dma_info.addr, rq->wqe_sz, + PCI_DMA_FROMDEVICE); + for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) { + atomic_sub(MLX5_MPWRQ_STRIDES_PER_PAGE - wi->skbs_frags[i], + &wi->dma_info.page[i]._count); + put_page(&wi->dma_info.page[i]); + } +} + +int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) +{ + int err; + + err = mlx5e_alloc_rx_linear_mpwqe(rq, wqe, ix); + if (unlikely(err)) { + err = mlx5e_alloc_rx_fragmented_mpwqe(rq, wqe, ix); + if (unlikely(err)) + return err; + set_bit(MLX5E_RQ_STATE_UMR_WQE_IN_PROGRESS, &rq->state); + mlx5e_post_umr_wqe(rq, ix); + return -EBUSY; + } return 0; } +#define RQ_CANNOT_POST(rq) \ + (!test_bit(MLX5E_RQ_STATE_POST_WQES_ENABLE, &rq->state) || \ + test_bit(MLX5E_RQ_STATE_UMR_WQE_IN_PROGRESS, &rq->state)) + bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq) { struct mlx5_wq_ll *wq = &rq->wq; - if (unlikely(!test_bit(MLX5E_RQ_STATE_POST_WQES_ENABLE, &rq->state))) + if (unlikely(RQ_CANNOT_POST(rq))) return false; while (!mlx5_wq_ll_is_full(wq)) { @@ -309,23 +638,56 @@ void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) &wqe->next.next_wqe_index); } +static inline void mlx5e_mpwqe_fill_rx_skb(struct mlx5e_rq *rq, + struct mlx5_cqe64 *cqe, + struct mlx5e_mpw_info *wi, + u32 cqe_bcnt, + struct sk_buff *skb) +{ + u32 consumed_bytes = ALIGN(cqe_bcnt, MLX5_MPWRQ_STRIDE_SIZE); + u16 stride_ix = mpwrq_get_cqe_stride_index(cqe); + u32 wqe_offset = stride_ix * MLX5_MPWRQ_STRIDE_SIZE; + u32 head_offset = wqe_offset & (PAGE_SIZE - 1); + u32 page_idx = wqe_offset >> PAGE_SHIFT; + u32 head_page_idx = page_idx; + u16 headlen = min_t(u16, MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, cqe_bcnt); + u32 frag_offset = head_offset + headlen; + u16 byte_cnt = cqe_bcnt - headlen; + +#if (MLX5_MPWRQ_SMALL_PACKET_THRESHOLD >= MLX5_MPWRQ_STRIDE_SIZE) + if (unlikely(frag_offset >= PAGE_SIZE)) { + page_idx++; + frag_offset -= PAGE_SIZE; + } +#endif + wi->dma_pre_sync(rq->pdev, wi, wqe_offset, consumed_bytes); + + while (byte_cnt) { + u32 pg_consumed_bytes = + min_t(u32, PAGE_SIZE - frag_offset, byte_cnt); + + wi->add_skb_frag(rq->pdev, skb, wi, page_idx, frag_offset, + pg_consumed_bytes); + byte_cnt -= pg_consumed_bytes; + frag_offset = 0; + page_idx++; + } + /* copy header */ + wi->copy_skb_header(rq->pdev, skb, wi, head_page_idx, head_offset, + headlen); + /* skb linear part was allocated with headlen and aligned to long */ + skb->tail += headlen; + skb->len += headlen; +} + void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) { u16 cstrides = mpwrq_get_cqe_consumed_strides(cqe); - u16 stride_ix = mpwrq_get_cqe_stride_index(cqe); u16 wqe_id = be16_to_cpu(cqe->wqe_id); struct mlx5e_mpw_info *wi = &rq->wqe_info[wqe_id]; struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, wqe_id); struct sk_buff *skb; - u32 consumed_bytes; - u32 head_offset; - u32 frag_offset; - u32 wqe_offset; - u32 page_idx; - u16 byte_cnt; u16 cqe_bcnt; - u16 headlen; - int i; wi->consumed_strides += cstrides; @@ -346,53 +708,16 @@ void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) goto mpwrq_cqe_out; prefetch(skb->data); - wqe_offset = stride_ix * MLX5_MPWRQ_STRIDE_SIZE; - consumed_bytes = cstrides * MLX5_MPWRQ_STRIDE_SIZE; - dma_sync_single_for_cpu(rq->pdev, wi->dma_info.addr + wqe_offset, - consumed_bytes, DMA_FROM_DEVICE); - - head_offset = wqe_offset & (PAGE_SIZE - 1); - page_idx = wqe_offset >> PAGE_SHIFT; cqe_bcnt = mpwrq_get_cqe_byte_cnt(cqe); - headlen = min_t(u16, MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, cqe_bcnt); - frag_offset = head_offset + headlen; - - byte_cnt = cqe_bcnt - headlen; - while (byte_cnt) { - u32 pg_consumed_bytes = - min_t(u32, PAGE_SIZE - frag_offset, byte_cnt); - unsigned int truesize = - ALIGN(pg_consumed_bytes, MLX5_MPWRQ_STRIDE_SIZE); - - wi->skbs_frags[page_idx]++; - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, - &wi->dma_info.page[page_idx], frag_offset, - pg_consumed_bytes, truesize); - byte_cnt -= pg_consumed_bytes; - frag_offset = 0; - page_idx++; - } - - skb_copy_to_linear_data(skb, - page_address(wi->dma_info.page) + wqe_offset, - ALIGN(headlen, sizeof(long))); - /* skb linear part was allocated with headlen and aligned to long */ - skb->tail += headlen; - skb->len += headlen; + mlx5e_mpwqe_fill_rx_skb(rq, cqe, wi, cqe_bcnt, skb); mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); mpwrq_cqe_out: if (likely(wi->consumed_strides < MLX5_MPWRQ_NUM_STRIDES)) return; - dma_unmap_page(rq->pdev, wi->dma_info.addr, rq->wqe_sz, - PCI_DMA_FROMDEVICE); - for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) { - atomic_sub(MLX5_MPWRQ_STRIDES_PER_PAGE - wi->skbs_frags[i], - &wi->dma_info.page[i]._count); - put_page(&wi->dma_info.page[i]); - } + wi->free_wqe(rq, wi); mlx5_wq_ll_pop(&rq->wq, cqe->wqe_id, &wqe->next.next_wqe_index); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index a8d2935c50d0..229ab16fb8d3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -58,7 +58,7 @@ void mlx5e_send_nop(struct mlx5e_sq *sq, bool notify_hw) if (notify_hw) { cseg->fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE; - mlx5e_tx_notify_hw(sq, wqe, 0); + mlx5e_tx_notify_hw(sq, &wqe->ctrl, 0); } } @@ -310,7 +310,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) bf_sz = wi->num_wqebbs << 3; cseg->fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE; - mlx5e_tx_notify_hw(sq, wqe, bf_sz); + mlx5e_tx_notify_hw(sq, &wqe->ctrl, bf_sz); } /* fill sq edge with nops to avoid wqe wrap around */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c index ad624cb6f147..a3fd0f55ce2e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c @@ -84,6 +84,9 @@ static void mlx5e_poll_ico_cq(struct mlx5e_cq *cq) switch (icowi->opcode) { case MLX5_OPCODE_NOP: break; + case MLX5_OPCODE_UMR: + mlx5e_post_rx_fragmented_mpwqe(&sq->channel->rq); + break; default: WARN_ONCE(true, "mlx5e: Bad OPCODE in ICOSQ WQE info: 0x%x\n", -- GitLab From c5adb96f6c4a22aceff2e8220612c5b9239ffeb2 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:16 +0300 Subject: [PATCH 3895/9938] net/mlx5e: Use napi_alloc_skb for RX SKB allocations Instead of netdev_alloc_skb, we use the napi_alloc_skb function which is designated to allocate skbuff's for RX in a channel-specific NAPI instance, and implies the IP packet alignment. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 - drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 12 +++++------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index c99fdff74c97..303e6cdf9fcd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -93,7 +93,6 @@ #define MLX5E_SQ_BF_BUDGET 16 #define MLX5E_NUM_MAIN_GROUPS 9 -#define MLX5E_NET_IP_ALIGN 2 static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 942829e6d8ba..9b17bc064cc8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -373,8 +373,8 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, rq->wqe_sz = (priv->params.lro_en) ? priv->params.lro_wqe_sz : MLX5E_SW2HW_MTU(priv->netdev->mtu); - rq->wqe_sz = SKB_DATA_ALIGN(rq->wqe_sz + MLX5E_NET_IP_ALIGN); - byte_count = rq->wqe_sz - MLX5E_NET_IP_ALIGN; + rq->wqe_sz = SKB_DATA_ALIGN(rq->wqe_sz); + byte_count = rq->wqe_sz; byte_count |= MLX5_HW_START_PADDING; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index d71919ccf912..5bdcc0b69f76 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -47,7 +47,7 @@ int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) struct sk_buff *skb; dma_addr_t dma_addr; - skb = netdev_alloc_skb(rq->netdev, rq->wqe_sz); + skb = napi_alloc_skb(rq->cq.napi, rq->wqe_sz); if (unlikely(!skb)) return -ENOMEM; @@ -61,10 +61,8 @@ int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) if (unlikely(dma_mapping_error(rq->pdev, dma_addr))) goto err_free_skb; - skb_reserve(skb, MLX5E_NET_IP_ALIGN); - *((dma_addr_t *)skb->cb) = dma_addr; - wqe->data.addr = cpu_to_be64(dma_addr + MLX5E_NET_IP_ALIGN); + wqe->data.addr = cpu_to_be64(dma_addr); wqe->data.lkey = rq->mkey_be; rq->skb[ix] = skb; @@ -701,9 +699,9 @@ void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) goto mpwrq_cqe_out; } - skb = netdev_alloc_skb(rq->netdev, - ALIGN(MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, - sizeof(long))); + skb = napi_alloc_skb(rq->cq.napi, + ALIGN(MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, + sizeof(long))); if (unlikely(!skb)) goto mpwrq_cqe_out; -- GitLab From 1bfec31627bf9b351b93b8cef4520b90f48ca276 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:17 +0300 Subject: [PATCH 3896/9938] net/mlx5e: Remove redundant barrier The bit-op operation one line before is an explicit barrier by itself. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c index a3fd0f55ce2e..c38781fa567d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c @@ -147,7 +147,6 @@ void mlx5e_completion_event(struct mlx5_core_cq *mcq) struct mlx5e_cq *cq = container_of(mcq, struct mlx5e_cq, mcq); set_bit(MLX5E_CHANNEL_NAPI_SCHED, &cq->channel->flags); - barrier(); napi_schedule(cq->napi); } -- GitLab From e20a0db30454a07f03f3a34a79e9f35881cfaa9d Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Wed, 20 Apr 2016 22:02:18 +0300 Subject: [PATCH 3897/9938] net/mlx5e: Delay skb->data access Move mlx5e_handle_csum and eth_type_trans to the end of mlx5e_build_rx_skb to gain some more time before accessing skb->data, to reduce cache misses. Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 5bdcc0b69f76..ee5fa16aafd1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -573,10 +573,6 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, if (unlikely(mlx5e_rx_hw_stamp(tstamp))) mlx5e_fill_hwstamp(tstamp, get_cqe_ts(cqe), skb_hwtstamps(skb)); - mlx5e_handle_csum(netdev, cqe, rq, skb, !!lro_num_seg); - - skb->protocol = eth_type_trans(skb, netdev); - skb_record_rx_queue(skb, rq->ix); if (likely(netdev->features & NETIF_F_RXHASH)) @@ -587,6 +583,9 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, be16_to_cpu(cqe->vlan_info)); skb->mark = be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK; + + mlx5e_handle_csum(netdev, cqe, rq, skb, !!lro_num_seg); + skb->protocol = eth_type_trans(skb, netdev); } static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq, -- GitLab From 54984407564ef6b35488f52654f828c17b9d6fa8 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 20 Apr 2016 22:02:19 +0300 Subject: [PATCH 3898/9938] net/mlx5e: Add ethtool counter for RX buffer allocation failures Counts the number of RX buffer allocation failures and shows it in ethtool statistics. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 8 ++++++-- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 11 +++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 303e6cdf9fcd..6e24e821a1d8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -189,6 +189,7 @@ static const char vport_strings[][ETH_GSTRING_LEN] = { "rx_wqe_err", "rx_mpwqe_filler", "rx_mpwqe_frag", + "rx_buff_alloc_err", }; struct mlx5e_vport_stats { @@ -232,8 +233,9 @@ struct mlx5e_vport_stats { u64 rx_wqe_err; u64 rx_mpwqe_filler; u64 rx_mpwqe_frag; + u64 rx_buff_alloc_err; -#define NUM_VPORT_COUNTERS 37 +#define NUM_VPORT_COUNTERS 38 }; static const char pport_strings[][ETH_GSTRING_LEN] = { @@ -329,6 +331,7 @@ static const char rq_stats_strings[][ETH_GSTRING_LEN] = { "wqe_err", "mpwqe_filler", "mpwqe_frag", + "buff_alloc_err", }; struct mlx5e_rq_stats { @@ -341,7 +344,8 @@ struct mlx5e_rq_stats { u64 wqe_err; u64 mpwqe_filler; u64 mpwqe_frag; -#define NUM_RQ_STATS 9 + u64 buff_alloc_err; +#define NUM_RQ_STATS 10 }; static const char sq_stats_strings[][ETH_GSTRING_LEN] = { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 9b17bc064cc8..d485d1e4e100 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -180,6 +180,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) s->rx_wqe_err = 0; s->rx_mpwqe_filler = 0; s->rx_mpwqe_frag = 0; + s->rx_buff_alloc_err = 0; for (i = 0; i < priv->params.num_channels; i++) { rq_stats = &priv->channel[i]->rq.stats; @@ -192,6 +193,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) s->rx_wqe_err += rq_stats->wqe_err; s->rx_mpwqe_filler += rq_stats->mpwqe_filler; s->rx_mpwqe_frag += rq_stats->mpwqe_frag; + s->rx_buff_alloc_err += rq_stats->buff_alloc_err; for (j = 0; j < priv->params.num_tc; j++) { sq_stats = &priv->channel[i]->sq[j].stats; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index ee5fa16aafd1..918b7c7fd74f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -447,9 +447,14 @@ bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq) while (!mlx5_wq_ll_is_full(wq)) { struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(wq, wq->head); + int err; - if (unlikely(rq->alloc_wqe(rq, wqe, wq->head))) + err = rq->alloc_wqe(rq, wqe, wq->head); + if (unlikely(err)) { + if (err != -EBUSY) + rq->stats.buff_alloc_err++; break; + } mlx5_wq_ll_push(wq, be16_to_cpu(wqe->next.next_wqe_index)); } @@ -701,8 +706,10 @@ void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) skb = napi_alloc_skb(rq->cq.napi, ALIGN(MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, sizeof(long))); - if (unlikely(!skb)) + if (unlikely(!skb)) { + rq->stats.buff_alloc_err++; goto mpwrq_cqe_out; + } prefetch(skb->data); cqe_bcnt = mpwrq_get_cqe_byte_cnt(cqe); -- GitLab From 7f348a60762afd4cd0e4e7fa14cfa66331b7c30e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 20 Apr 2016 16:51:00 -0400 Subject: [PATCH 3899/9938] net: Add support for IP ID mangling TSO in cases that require encapsulation This patch adds support for NETIF_F_TSO_MANGLEID if a given tunnel supports NETIF_F_TSO. This way if needed a device can then later enable the TSO with IP ID mangling and the tunnels on top of that device can then also make use of the IP ID mangling as well. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/core/dev.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 52d446b2cb99..6324bc9267f7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7029,8 +7029,19 @@ int register_netdevice(struct net_device *dev) if (!(dev->flags & IFF_LOOPBACK)) dev->hw_features |= NETIF_F_NOCACHE_COPY; + /* If IPv4 TCP segmentation offload is supported we should also + * allow the device to enable segmenting the frame with the option + * of ignoring a static IP ID value. This doesn't enable the + * feature itself but allows the user to enable it later. + */ if (dev->hw_features & NETIF_F_TSO) dev->hw_features |= NETIF_F_TSO_MANGLEID; + if (dev->vlan_features & NETIF_F_TSO) + dev->vlan_features |= NETIF_F_TSO_MANGLEID; + if (dev->mpls_features & NETIF_F_TSO) + dev->mpls_features |= NETIF_F_TSO_MANGLEID; + if (dev->hw_enc_features & NETIF_F_TSO) + dev->hw_enc_features |= NETIF_F_TSO_MANGLEID; /* Make NETIF_F_HIGHDMA inheritable to VLAN devices. */ -- GitLab From ae35557bb04b3429321ba05442c88c7633713bc6 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 18 Apr 2016 06:31:22 +0300 Subject: [PATCH 3900/9938] ARM: LPC32xx: defconfig update The change is a result of "make lpc32xx_defconfig; make savedefconfig" run, a number of config options are removed: CONFIG_BINFMT_AOUT=y -- not needed, legacy CONFIG_FPE_NWFPE=y -- not needed, AEABI build CONFIG_IPV6_PRIVACY=y -- removed build option CONFIG_IPV6=y -- selected by default CONFIG_MII=y -- not needed, board phys don't select library CONFIG_MTD_CHAR=y -- removed build option CONFIG_MTD_M25P80=y -- not needed, AT25 EEPROM driver is in use CONFIG_USB_PHY=y -- selected by default Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/configs/lpc32xx_defconfig | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 9f56ca3985ae..430319934d62 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -17,8 +17,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set CONFIG_PARTITION_ADVANCED=y CONFIG_ARCH_LPC32XX=y -CONFIG_GPIO_PCA953X=y -CONFIG_KEYBOARD_GPIO_POLLED=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_ZBOOT_ROM_TEXT=0x0 @@ -27,10 +25,8 @@ CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CMDLINE="console=ttyS0,115200n81 root=/dev/ram0" CONFIG_CPU_IDLE=y -CONFIG_FPE_NWFPE=y CONFIG_VFP=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_BINFMT_AOUT=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -42,10 +38,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set -CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y # CONFIG_WIRELESS is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y @@ -53,9 +46,7 @@ CONFIG_DEVTMPFS_MOUNT=y # CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y -CONFIG_MTD_M25P80=y CONFIG_MTD_NAND=y CONFIG_MTD_NAND_SLC_LPC32XX=y CONFIG_MTD_NAND_MLC_LPC32XX=y @@ -70,7 +61,6 @@ CONFIG_EEPROM_AT25=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y -CONFIG_MII=y # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_NET_VENDOR_FARADAY is not set @@ -91,6 +81,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320 CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_GPIO_POLLED=y CONFIG_KEYBOARD_LPC32XX=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y @@ -99,8 +90,8 @@ CONFIG_SERIO_LIBPS2=y # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_HS_LPC32XX=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_HS_LPC32XX=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -108,19 +99,20 @@ CONFIG_I2C_PNX=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_EM=y +CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_PL061=y +CONFIG_GPIO_ADP5588=y +CONFIG_GPIO_ADNP=y CONFIG_GPIO_MAX7300=y CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCF857X=y CONFIG_GPIO_SX150X=y -CONFIG_GPIO_ADP5588=y -CONFIG_GPIO_ADNP=y +CONFIG_GPIO_74X164=y CONFIG_GPIO_MAX7301=y -CONFIG_GPIO_MCP23S08=y CONFIG_GPIO_MC33880=y -CONFIG_GPIO_74X164=y +CONFIG_GPIO_MCP23S08=y CONFIG_SENSORS_DS620=y CONFIG_SENSORS_MAX6639=y CONFIG_WATCHDOG=y @@ -147,7 +139,6 @@ CONFIG_SND_DEBUG_VERBOSE=y # CONFIG_SND_SPI is not set CONFIG_SND_SOC=y CONFIG_USB=y -CONFIG_USB_PHY=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y @@ -198,9 +189,9 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y +CONFIG_DEBUG_INFO=y # CONFIG_SCHED_DEBUG is not set # CONFIG_DEBUG_PREEMPT is not set -CONFIG_DEBUG_INFO=y # CONFIG_FTRACE is not set # CONFIG_ARM_UNWIND is not set CONFIG_DEBUG_LL=y -- GitLab From 3b3c6ad5353951cd01523add5a1930c743d4f807 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 18 Apr 2016 06:31:23 +0300 Subject: [PATCH 3901/9938] ARM: LPC32xx: add PL175 memory controller driver to defconfig The change enables build of ARM PrimeCell PL17x driver for LPC32xx platform, the memory controller is commonly used to interface NOR flash drives. Signed-off-by: Vladimir Zapolskiy --- arch/arm/configs/lpc32xx_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 430319934d62..6ba430d2b5b2 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -170,6 +170,8 @@ CONFIG_DMADEVICES=y CONFIG_AMBA_PL08X=y CONFIG_STAGING=y CONFIG_LPC32XX_ADC=y +CONFIG_MEMORY=y +CONFIG_ARM_PL172_MPMC=y CONFIG_IIO=y CONFIG_MAX517=y CONFIG_PWM=y -- GitLab From 73fdaa0f332fcf301327053cff7e523a85b0e7c7 Mon Sep 17 00:00:00 2001 From: Sylvain Lemieux Date: Wed, 20 Apr 2016 09:20:58 -0400 Subject: [PATCH 3902/9938] ARM: dts: lpc32xx: add clock properties to spi nodes The change adds clock properties to spi peripheral devices, clock ids are taken from dt-bindings/clock/lpc32xx-clock.h Signed-off-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/lpc32xx.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index d7b84cd209db..1b2f351e4a08 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -173,6 +173,7 @@ spi1: spi@20088000 { compatible = "nxp,lpc3220-spi"; reg = <0x20088000 0x1000>; + clocks = <&clk LPC32XX_CLK_SPI1>; }; ssp1: ssp@2008c000 { @@ -186,6 +187,7 @@ spi2: spi@20090000 { compatible = "nxp,lpc3220-spi"; reg = <0x20090000 0x1000>; + clocks = <&clk LPC32XX_CLK_SPI2>; }; i2s0: i2s@20094000 { -- GitLab From 9a96877c2b08865685bb80338db7254cf76af55f Mon Sep 17 00:00:00 2001 From: Sylvain Lemieux Date: Wed, 20 Apr 2016 09:20:59 -0400 Subject: [PATCH 3903/9938] ARM: dts: phy3250: enable ssp0 Preparatory change prior to disabling SSPx controllers by default in the shared LPC32xx DTSI file. Signed-off-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/phy3250.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index a00d7ce7802b..26e070fe9a58 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -146,6 +146,7 @@ #size-cells = <0>; num-cs = <1>; cs-gpios = <&gpio 3 5 0>; + status = "okay"; eeprom: at25@0 { pl022,interface = <0>; -- GitLab From 961212e3fd1ee29d31f3c362f0bc854868679f63 Mon Sep 17 00:00:00 2001 From: Sylvain Lemieux Date: Wed, 20 Apr 2016 09:21:00 -0400 Subject: [PATCH 3904/9938] ARM: dts: lpc32xx: disabled ssp0/spi1 & ssp1/spi2 by default The SSP0/SPI1 and SSP1/SPI2 shared pinout and should be disable by default. Board specific dts should enable them, as needed. Signed-off-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/lpc32xx.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index 1b2f351e4a08..73c474610efa 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -162,32 +162,44 @@ compatible = "simple-bus"; ranges = <0x20000000 0x20000000 0x30000000>; + /* + * ssp0 and spi1 are shared pins; + * enable one in your board dts, as needed. + */ ssp0: ssp@20084000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x20084000 0x1000>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_SSP0>; clock-names = "apb_pclk"; + status = "disabled"; }; spi1: spi@20088000 { compatible = "nxp,lpc3220-spi"; reg = <0x20088000 0x1000>; clocks = <&clk LPC32XX_CLK_SPI1>; + status = "disabled"; }; + /* + * ssp1 and spi2 are shared pins; + * enable one in your board dts, as needed. + */ ssp1: ssp@2008c000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x2008c000 0x1000>; interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_SSP1>; clock-names = "apb_pclk"; + status = "disabled"; }; spi2: spi@20090000 { compatible = "nxp,lpc3220-spi"; reg = <0x20090000 0x1000>; clocks = <&clk LPC32XX_CLK_SPI2>; + status = "disabled"; }; i2s0: i2s@20094000 { -- GitLab From 08d9910c3408531473766ec4d8b288e8ee2fe500 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Apr 2016 21:19:42 +0200 Subject: [PATCH 3905/9938] benet: be_resume needs to protect be_open with rtnl_lock be_open calls down to functions which expects rtnl lock to be held. Cc: Sathya Perla Cc: Ajit Khaparde Cc: Padmanabh Ratnakar Cc: Sriharsha Basavapatna Cc: Somnath Kotur Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 536686476369..ed98ef1ecac3 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4890,11 +4890,13 @@ static int be_resume(struct be_adapter *adapter) if (status) return status; - if (netif_running(netdev)) { + rtnl_lock(); + if (netif_running(netdev)) status = be_open(netdev); - if (status) - return status; - } + rtnl_unlock(); + + if (status) + return status; netif_device_attach(netdev); -- GitLab From 41419b9303f085e8912406140355e45230fed22f Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Apr 2016 21:19:43 +0200 Subject: [PATCH 3906/9938] fm10k: protect fm10k_open in fm10k_io_resume with rtnl_lock fm10k_open requires rtnl_lock to be held. Cc: Jeff Kirsher Cc: Jesse Brandeburg Cc: Shannon Nelson Cc: Carolyn Wyborny Cc: Don Skidmore Cc: Bruce Allan Cc: John Ronciak Cc: Mitch Williams Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 404f47ae14b6..206a466999ed 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -2287,8 +2287,10 @@ static void fm10k_io_resume(struct pci_dev *pdev) /* reassociate interrupts */ fm10k_mbx_request_irq(interface); + rtnl_lock(); if (netif_running(netdev)) err = fm10k_open(netdev); + rtnl_unlock(); /* final check of hardware state before registering the interface */ err = err ? : fm10k_hw_ready(interface); -- GitLab From 0c5c3252c43cc935bef05c2211fc7cb32facddf7 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Apr 2016 21:19:44 +0200 Subject: [PATCH 3907/9938] mlx4: protect mlx4_en_start_port in mlx4_en_restart with rtnl_lock mlx4_en_start_port requires rtnl_lock to be held. Cc: Eugenia Emantayev Cc: Yishai Hadas Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index b4b258c8ca47..8bd143dda95d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1856,6 +1856,7 @@ static void mlx4_en_restart(struct work_struct *work) en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port); + rtnl_lock(); mutex_lock(&mdev->state_lock); if (priv->port_up) { mlx4_en_stop_port(dev, 1); @@ -1863,6 +1864,7 @@ static void mlx4_en_restart(struct work_struct *work) en_err(priv, "Failed restarting port %d\n", priv->port); } mutex_unlock(&mdev->state_lock); + rtnl_unlock(); } static void mlx4_en_clear_stats(struct net_device *dev) -- GitLab From b1f99a787e8239da3ea859709f5fb60b3fd02c13 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Apr 2016 21:19:45 +0200 Subject: [PATCH 3908/9938] ixgbe: protect vxlan_get_rx_port in ixgbe_service_task with rtnl_lock vxlan_get_rx_port requires rtnl_lock to be held. Cc: Jeff Kirsher Cc: Jesse Brandeburg Cc: Shannon Nelson Cc: Carolyn Wyborny Cc: Don Skidmore Cc: Bruce Allan Cc: John Ronciak Cc: Mitch Williams Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 2976df77bf14..b2f2cf40f06a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7192,10 +7192,12 @@ static void ixgbe_service_task(struct work_struct *work) return; } #ifdef CONFIG_IXGBE_VXLAN + rtnl_lock(); if (adapter->flags2 & IXGBE_FLAG2_VXLAN_REREG_NEEDED) { adapter->flags2 &= ~IXGBE_FLAG2_VXLAN_REREG_NEEDED; vxlan_get_rx_port(adapter->netdev); } + rtnl_unlock(); #endif /* CONFIG_IXGBE_VXLAN */ ixgbe_reset_subtask(adapter); ixgbe_phy_interrupt_subtask(adapter); -- GitLab From 50d65d78897ff9785b7debbdca0030967cd5772d Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Apr 2016 21:19:46 +0200 Subject: [PATCH 3909/9938] qlcnic: protect qlicnic_attach_func with rtnl_lock qlcnic_attach_func requires rtnl_lock to be held. Cc: Dept-GELinuxNICDev@qlogic.com Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 1205f6f9c941..1c29105b6c36 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -3952,8 +3952,14 @@ static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev, static pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev) { - return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : - PCI_ERS_RESULT_RECOVERED; + pci_ers_result_t res; + + rtnl_lock(); + res = qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : + PCI_ERS_RESULT_RECOVERED; + rtnl_unlock(); + + return res; } static void qlcnic_82xx_io_resume(struct pci_dev *pdev) -- GitLab From b7aade15485a660cbf5161962c284131324a9534 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Apr 2016 21:19:47 +0200 Subject: [PATCH 3910/9938] vxlan: break dependency with netdev drivers Currently all drivers depend and autoload the vxlan module because how vxlan_get_rx_port is linked into them. Remove this dependency: By using a new event type in the netdevice notifier call chain we proxy the request from the drivers to flush and resetup the vxlan ports not directly via function call but by the already existing netdevice notifier call chain. I added a separate new event type, NETDEV_OFFLOAD_PUSH_VXLAN, to do so. We don't need to save those ids, as the event type field is an unsigned long and using specialized event types for this purpose seemed to be a more elegant way. This also comes in beneficial if in future we want to add offloading knobs for vxlan. Cc: Jesse Gross Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 14 +++++++++----- include/linux/netdevice.h | 1 + include/net/vxlan.h | 6 ++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index c2e22c2532a1..6fb93b57a724 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2527,7 +2527,7 @@ static struct device_type vxlan_type = { * supply the listening VXLAN udp ports. Callers are expected * to implement the ndo_add_vxlan_port. */ -void vxlan_get_rx_port(struct net_device *dev) +static void vxlan_push_rx_ports(struct net_device *dev) { struct vxlan_sock *vs; struct net *net = dev_net(dev); @@ -2536,6 +2536,9 @@ void vxlan_get_rx_port(struct net_device *dev) __be16 port; unsigned int i; + if (!dev->netdev_ops->ndo_add_vxlan_port) + return; + spin_lock(&vn->sock_lock); for (i = 0; i < PORT_HASH_SIZE; ++i) { hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) { @@ -2547,7 +2550,6 @@ void vxlan_get_rx_port(struct net_device *dev) } spin_unlock(&vn->sock_lock); } -EXPORT_SYMBOL_GPL(vxlan_get_rx_port); /* Initialize the device structure. */ static void vxlan_setup(struct net_device *dev) @@ -3283,20 +3285,22 @@ static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn, unregister_netdevice_many(&list_kill); } -static int vxlan_lowerdev_event(struct notifier_block *unused, - unsigned long event, void *ptr) +static int vxlan_netdevice_event(struct notifier_block *unused, + unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); if (event == NETDEV_UNREGISTER) vxlan_handle_lowerdev_unregister(vn, dev); + else if (event == NETDEV_OFFLOAD_PUSH_VXLAN) + vxlan_push_rx_ports(dev); return NOTIFY_DONE; } static struct notifier_block vxlan_notifier_block __read_mostly = { - .notifier_call = vxlan_lowerdev_event, + .notifier_call = vxlan_netdevice_event, }; static __net_init int vxlan_init_net(struct net *net) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a3bb534576a3..d4c8cd424f8d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2244,6 +2244,7 @@ struct netdev_lag_lower_state_info { #define NETDEV_BONDING_INFO 0x0019 #define NETDEV_PRECHANGEUPPER 0x001A #define NETDEV_CHANGELOWERSTATE 0x001B +#define NETDEV_OFFLOAD_PUSH_VXLAN 0x001C int register_netdevice_notifier(struct notifier_block *nb); int unregister_netdevice_notifier(struct notifier_block *nb); diff --git a/include/net/vxlan.h b/include/net/vxlan.h index d442eb3129cd..673e9f9e6da7 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -390,13 +390,11 @@ static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset) return vni_field; } -#if IS_ENABLED(CONFIG_VXLAN) -void vxlan_get_rx_port(struct net_device *netdev); -#else static inline void vxlan_get_rx_port(struct net_device *netdev) { + ASSERT_RTNL(); + call_netdevice_notifiers(NETDEV_OFFLOAD_PUSH_VXLAN, netdev); } -#endif static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs) { -- GitLab From 681e683ff30ada19f73c17c38a528528dd8824f1 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Apr 2016 21:19:48 +0200 Subject: [PATCH 3911/9938] geneve: break dependency with netdev drivers Equivalent to "vxlan: break dependency with netdev drivers", don't autoload geneve module in case the driver is loaded. Instead make the coupling weaker by using netdevice notifiers as proxy. Cc: Jesse Gross Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/geneve.c | 31 ++++++++++++++++++++++++++++--- include/linux/netdevice.h | 1 + include/net/geneve.h | 6 ++---- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 512dbe013713..9c40b88fabd5 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1172,7 +1172,7 @@ static struct device_type geneve_type = { * supply the listening GENEVE udp ports. Callers are expected * to implement the ndo_add_geneve_port. */ -void geneve_get_rx_port(struct net_device *dev) +static void geneve_push_rx_ports(struct net_device *dev) { struct net *net = dev_net(dev); struct geneve_net *gn = net_generic(net, geneve_net_id); @@ -1181,6 +1181,9 @@ void geneve_get_rx_port(struct net_device *dev) struct sock *sk; __be16 port; + if (!dev->netdev_ops->ndo_add_geneve_port) + return; + rcu_read_lock(); list_for_each_entry_rcu(gs, &gn->sock_list, list) { sk = gs->sock->sk; @@ -1190,7 +1193,6 @@ void geneve_get_rx_port(struct net_device *dev) } rcu_read_unlock(); } -EXPORT_SYMBOL_GPL(geneve_get_rx_port); /* Initialize the device structure. */ static void geneve_setup(struct net_device *dev) @@ -1538,6 +1540,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, } EXPORT_SYMBOL_GPL(geneve_dev_create_fb); +static int geneve_netdevice_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + + if (event == NETDEV_OFFLOAD_PUSH_GENEVE) + geneve_push_rx_ports(dev); + + return NOTIFY_DONE; +} + +static struct notifier_block geneve_notifier_block __read_mostly = { + .notifier_call = geneve_netdevice_event, +}; + static __net_init int geneve_init_net(struct net *net) { struct geneve_net *gn = net_generic(net, geneve_net_id); @@ -1590,11 +1607,18 @@ static int __init geneve_init_module(void) if (rc) goto out1; - rc = rtnl_link_register(&geneve_link_ops); + rc = register_netdevice_notifier(&geneve_notifier_block); if (rc) goto out2; + rc = rtnl_link_register(&geneve_link_ops); + if (rc) + goto out3; + return 0; + +out3: + unregister_netdevice_notifier(&geneve_notifier_block); out2: unregister_pernet_subsys(&geneve_net_ops); out1: @@ -1605,6 +1629,7 @@ late_initcall(geneve_init_module); static void __exit geneve_cleanup_module(void) { rtnl_link_unregister(&geneve_link_ops); + unregister_netdevice_notifier(&geneve_notifier_block); unregister_pernet_subsys(&geneve_net_ops); } module_exit(geneve_cleanup_module); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d4c8cd424f8d..1f6d5db471a2 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2245,6 +2245,7 @@ struct netdev_lag_lower_state_info { #define NETDEV_PRECHANGEUPPER 0x001A #define NETDEV_CHANGELOWERSTATE 0x001B #define NETDEV_OFFLOAD_PUSH_VXLAN 0x001C +#define NETDEV_OFFLOAD_PUSH_GENEVE 0x001D int register_netdevice_notifier(struct notifier_block *nb); int unregister_netdevice_notifier(struct notifier_block *nb); diff --git a/include/net/geneve.h b/include/net/geneve.h index e6c23dc765f7..cb544a530146 100644 --- a/include/net/geneve.h +++ b/include/net/geneve.h @@ -62,13 +62,11 @@ struct genevehdr { struct geneve_opt options[]; }; -#if IS_ENABLED(CONFIG_GENEVE) -void geneve_get_rx_port(struct net_device *netdev); -#else static inline void geneve_get_rx_port(struct net_device *netdev) { + ASSERT_RTNL(); + call_netdevice_notifiers(NETDEV_OFFLOAD_PUSH_GENEVE, netdev); } -#endif #ifdef CONFIG_INET struct net_device *geneve_dev_create_fb(struct net *net, const char *name, -- GitLab From 702b07fcc9b264c9afd372676bbdd50a762dcde0 Mon Sep 17 00:00:00 2001 From: Lukasz Anaczkowski Date: Thu, 21 Apr 2016 11:29:00 +0200 Subject: [PATCH 3912/9938] ACPI / SRAT: fix SRAT parsing order with both LAPIC and X2APIC present SRAT maps APIC ID to proximity domains ids (PXM). Mapping from PXM to NUMA node ids is based on order of entries in SRAT table. SRAT table has just LAPIC entires or mix of LAPIC and X2APIC entries. As long as there are only LAPIC entires, mapping from proximity domain id to NUMA node id is as assumed by BIOS. However, once APIC entries are mixed, X2APIC entries would be first mapped which causes unexpected NUMA node mapping. To fix that, change parsing to check each entry against both LAPIC and X2APIC so mapping is in the SRAT/PXM order. This is supplemental change to the fix made by commit d81056b5278 (Handle apic/x2apic entries in MADT in correct order) and using the mechanism introduced by 9b3fedd (ACPI / tables: Add acpi_subtable_proc to ACPI table parsers). Fixes: d81056b5278 (Handle apic/x2apic entries in MADT in correct order) Signed-off-by: Lukasz Anaczkowski [ rjw : Subject & changelog ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 72b6e9ef0ae9..d176e0ece470 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -327,10 +327,18 @@ int __init acpi_numa_init(void) /* SRAT: Static Resource Affinity Table */ if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { - acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, - acpi_parse_x2apic_affinity, 0); - acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, - acpi_parse_processor_affinity, 0); + struct acpi_subtable_proc srat_proc[2]; + + memset(srat_proc, 0, sizeof(srat_proc)); + srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY; + srat_proc[0].handler = acpi_parse_processor_affinity; + srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY; + srat_proc[1].handler = acpi_parse_x2apic_affinity; + + acpi_table_parse_entries_array(ACPI_SIG_SRAT, + sizeof(struct acpi_table_srat), + srat_proc, ARRAY_SIZE(srat_proc), 0); + cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); -- GitLab From 6e524a603f0b72281019e4ec29b1022388f9f231 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 29 Mar 2016 14:22:26 -0700 Subject: [PATCH 3913/9938] rcutorture: Add OS-jitter capability This commit adds a --jitter OS-jitter capability to expose bugs based on no-delay assumptions. Signed-off-by: Paul E. McKenney --- .../selftests/rcutorture/bin/jitter.sh | 90 +++++++++++++++++++ tools/testing/selftests/rcutorture/bin/kvm.sh | 18 ++++ 2 files changed, 108 insertions(+) create mode 100755 tools/testing/selftests/rcutorture/bin/jitter.sh diff --git a/tools/testing/selftests/rcutorture/bin/jitter.sh b/tools/testing/selftests/rcutorture/bin/jitter.sh new file mode 100755 index 000000000000..3633828375e3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/jitter.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# +# Alternate sleeping and spinning on randomly selected CPUs. The purpose +# of this script is to inflict random OS jitter on a concurrently running +# test. +# +# Usage: jitter.sh me duration [ sleepmax [ spinmax ] ] +# +# me: Random-number-generator seed salt. +# duration: Time to run in seconds. +# sleepmax: Maximum microseconds to sleep, defaults to one second. +# spinmax: Maximum microseconds to spin, defaults to one millisecond. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# Copyright (C) IBM Corporation, 2016 +# +# Authors: Paul E. McKenney + +me=$(($1 * 1000)) +duration=$2 +sleepmax=${3-1000000} +spinmax=${4-1000} + +n=1 + +starttime=`awk 'BEGIN { print systime(); }' < /dev/null` + +while : +do + # Check for done. + t=`awk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null` + if test "$t" -gt "$duration" + then + exit 0; + fi + + # Set affinity to randomly selected CPU + cpus=`ls /sys/devices/system/cpu/*/online | + sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//' | + grep -v '^0*$'` + cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN { + srand(n + me + systime()); + ncpus = split(cpus, ca); + curcpu = ca[int(rand() * ncpus + 1)]; + mask = lshift(1, curcpu); + if (mask + 0 <= 0) + mask = 1; + printf("%#x\n", mask); + }' < /dev/null` + n=$(($n+1)) + if ! taskset -p $cpumask $$ > /dev/null 2>&1 + then + echo taskset failure: '"taskset -p ' $cpumask $$ '"' + exit 1 + fi + + # Sleep a random duration + sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN { + srand(n + me + systime()); + printf("%06d", int(rand() * sleepmax)); + }' < /dev/null` + n=$(($n+1)) + sleep .$sleeptime + + # Spin a random duration + limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN { + srand(n + me + systime()); + printf("%06d", int(rand() * spinmax)); + }' < /dev/null` + n=$(($n+1)) + for i in {1..$limit} + do + echo > /dev/null + done +done + +exit 1 diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh index 704e219f67a7..0d598145873e 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm.sh @@ -48,6 +48,7 @@ resdir="" configs="" cpus=0 ds=`date +%Y.%m.%d-%H:%M:%S` +jitter=0 . functions.sh @@ -63,6 +64,7 @@ usage () { echo " --dryrun sched|script" echo " --duration minutes" echo " --interactive" + echo " --jitter N [ maxsleep (us) [ maxspin (us) ] ]" echo " --kmake-arg kernel-make-arguments" echo " --mac nn:nn:nn:nn:nn:nn" echo " --no-initrd" @@ -122,6 +124,11 @@ do --interactive) TORTURE_QEMU_INTERACTIVE=1; export TORTURE_QEMU_INTERACTIVE ;; + --jitter) + checkarg --jitter "(# threads [ sleep [ spin ] ])" $# "$2" '^-\{,1\}[0-9]\+\( \+[0-9]\+\)\{,2\} *$' '^error$' + jitter="$2" + shift + ;; --kmake-arg) checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$' TORTURE_KMAKE_ARG="$2" @@ -299,6 +306,7 @@ awk < $T/cfgcpu.pack \ -v CONFIGDIR="$CONFIGFRAG/" \ -v KVM="$KVM" \ -v ncpus=$cpus \ + -v jitter="$jitter" \ -v rd=$resdir/$ds/ \ -v dur=$dur \ -v TORTURE_QEMU_ARG="$TORTURE_QEMU_ARG" \ @@ -359,6 +367,16 @@ function dump(first, pastlast, batchnum) print "\techo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log"; print "fi" } + njitter = 0; + split(jitter, ja); + if (ja[1] == -1 && ncpus == 0) + njitter = 1; + else if (ja[1] == -1) + njitter = ncpus; + else + njitter = ja[1]; + for (j = 0; j < njitter; j++) + print "jitter.sh " j " " dur " " ja[2] " " ja[3] "&" print "wait" print "if test -z \"$TORTURE_BUILDONLY\"" print "then" -- GitLab From acc1adf5572205c5b3fc9e6983ca8dfb06c94520 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 30 Mar 2016 10:48:06 -0700 Subject: [PATCH 3914/9938] rcutorture: Don't rebuild identical kernel Currently, if the user specifies multiple runs of a given test configuration, the scripting does multiple kernel builds. This wastes both time and disk space, so this commit makes the scripting use the first build for all runs of a given test configuration. Signed-off-by: Paul E. McKenney --- .../rcutorture/bin/kvm-test-1-run.sh | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh index 73a265668421..4109f306d855 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh @@ -91,25 +91,33 @@ fi # CONFIG_PCMCIA=n # CONFIG_CARDBUS=n # CONFIG_YENTA=n -if kvm-build.sh $config_template $builddir $T +base_resdir=`echo $resdir | sed -e 's/\.[0-9]\+$//'` +if test "$base_resdir" != "$resdir" -a -f $base_resdir/bzImage -a -f $base_resdir/vmlinux then + # Rerunning previous test, so use that test's kernel. + QEMU="`identify_qemu $base_resdir/vmlinux`" + KERNEL=$base_resdir/bzImage + ln -s $base_resdir/Make*.out $resdir # for kvm-recheck.sh + ln -s $base_resdir/.config $resdir # for kvm-recheck.sh +elif kvm-build.sh $config_template $builddir $T +then + # Had to build a kernel for this test. QEMU="`identify_qemu $builddir/vmlinux`" BOOT_IMAGE="`identify_boot_image $QEMU`" cp $builddir/Make*.out $resdir + cp $builddir/vmlinux $resdir cp $builddir/.config $resdir if test -n "$BOOT_IMAGE" then cp $builddir/$BOOT_IMAGE $resdir + KERNEL=$resdir/bzImage else echo No identifiable boot image, not running KVM, see $resdir. echo Do the torture scripts know about your architecture? fi parse-build.sh $resdir/Make.out $title - if test -f $builddir.wait - then - mv $builddir.wait $builddir.ready - fi else + # Build failed. cp $builddir/Make*.out $resdir cp $builddir/.config $resdir || : echo Build failed, not running KVM, see $resdir. @@ -119,6 +127,10 @@ else fi exit 1 fi +if test -f $builddir.wait +then + mv $builddir.wait $builddir.ready +fi while test -f $builddir.ready do sleep 1 @@ -166,8 +178,8 @@ then exit 0 fi echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log -echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd -( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) & +echo $QEMU $qemu_args -m 512 -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd +( $QEMU $qemu_args -m 512 -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) & commandcompleted=0 sleep 10 # Give qemu's pid a chance to reach the file if test -s "$resdir/qemu_pid" -- GitLab From e9fb365a8847dfe8a9fccae0dce77abf7276b5da Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 30 Mar 2016 11:20:48 -0700 Subject: [PATCH 3915/9938] rcutorture: Dump trace buffer upon shutdown When running from the scripts, rcutorture is completely headless, so there is no way to to manually dump the trace buffer. This commit therefore unconditionally dumps the trace buffer upon timed shutdown. However, if you are using rmmod to end the test, it is still up to you to manually dump the trace buffer. Signed-off-by: Paul E. McKenney --- kernel/torture.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/torture.c b/kernel/torture.c index e912ccd960f0..fa0bdeee17ac 100644 --- a/kernel/torture.c +++ b/kernel/torture.c @@ -451,6 +451,7 @@ static int torture_shutdown(void *arg) torture_shutdown_hook(); else VERBOSE_TOROUT_STRING("No torture_shutdown_hook(), skipping."); + ftrace_dump(DUMP_ALL); kernel_power_off(); /* Shut down the system. */ return 0; } -- GitLab From 0aa67e75b3d59cfe412bfa54ca23797e6c2e3270 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 30 Mar 2016 11:40:44 -0700 Subject: [PATCH 3916/9938] rcutorture: Add irqs-disabled test for call_rcu() Mutation testing carried out by Iftekhar Ahmed of Oregon State University showed that rcutorture is failing to test invocations of call_rcu() having interrupts disabled. This commit therefore adds interrupt disabling around one of the existing invocations of call_rcu() (and friends). Signed-off-by: Paul E. McKenney --- kernel/rcu/rcutorture.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 633a68a09440..084a28a732eb 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -1478,7 +1478,9 @@ static int rcu_torture_barrier_cbs(void *arg) * The above smp_load_acquire() ensures barrier_phase load * is ordered before the folloiwng ->call(). */ + local_irq_disable(); /* Just to test no-irq call_rcu(). */ cur_ops->call(&rcu, rcu_torture_barrier_cbf); + local_irq_enable(); if (atomic_dec_and_test(&barrier_cbs_count)) wake_up(&barrier_wq); } while (!torture_must_stop()); -- GitLab From a54062c0d95921d4fb0edc8d268021bf387e6c75 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 30 Mar 2016 14:16:22 -0700 Subject: [PATCH 3917/9938] rcutorture: Add boot-time adjustment of leaf fanout Currently, the rcutorture scripts do not test boot-time adjustment of leaf fanout (via the rcutree.rcu_fanout_leaf boot parameter), as was noted during testing carried out by Iftekhar Ahmed of Oregon State University. This commit therefore adjusts TREE04's CONFIG_RCU_FANOUT_LEAF from 4 to 3, and also adds rcutree.rcu_fanout_leaf=4 to its boot parameters. This change forces RCU's boot-time geometry-change code to be exercised. Signed-off-by: Paul E. McKenney --- tools/testing/selftests/rcutorture/configs/rcu/TREE04 | 2 +- tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 index 39a2c6d7d7ec..17cbe098b115 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 @@ -14,7 +14,7 @@ CONFIG_HOTPLUG_CPU=n CONFIG_SUSPEND=n CONFIG_HIBERNATION=n CONFIG_RCU_FANOUT=4 -CONFIG_RCU_FANOUT_LEAF=4 +CONFIG_RCU_FANOUT_LEAF=3 CONFIG_RCU_NOCB_CPU=n CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot index 0fc8a3428938..e34c33430447 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot @@ -1 +1 @@ -rcutorture.torture_type=rcu_bh +rcutorture.torture_type=rcu_bh rcutree.rcu_fanout_leaf=4 -- GitLab From 074c6a422d86fff76e05cf31be25e0eb752e1bd4 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 14 Apr 2016 14:20:20 +0800 Subject: [PATCH 3918/9938] soc: rockchip: power-domain: support qos save and restore support qos save and restore when power domain on/off. Signed-off-by: Elaine Zhang Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 105 +++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index ac729fe42cc9..44842a205e4b 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -46,10 +46,20 @@ struct rockchip_pmu_info { const struct rockchip_domain_info *domain_info; }; +#define MAX_QOS_REGS_NUM 5 +#define QOS_PRIORITY 0x08 +#define QOS_MODE 0x0c +#define QOS_BANDWIDTH 0x10 +#define QOS_SATURATION 0x14 +#define QOS_EXTCONTROL 0x18 + struct rockchip_pm_domain { struct generic_pm_domain genpd; const struct rockchip_domain_info *info; struct rockchip_pmu *pmu; + int num_qos; + struct regmap **qos_regmap; + u32 *qos_save_regs[MAX_QOS_REGS_NUM]; int num_clks; struct clk *clks[]; }; @@ -118,6 +128,55 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, return 0; } +static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) +{ + int i; + + for (i = 0; i < pd->num_qos; i++) { + regmap_read(pd->qos_regmap[i], + QOS_PRIORITY, + &pd->qos_save_regs[0][i]); + regmap_read(pd->qos_regmap[i], + QOS_MODE, + &pd->qos_save_regs[1][i]); + regmap_read(pd->qos_regmap[i], + QOS_BANDWIDTH, + &pd->qos_save_regs[2][i]); + regmap_read(pd->qos_regmap[i], + QOS_SATURATION, + &pd->qos_save_regs[3][i]); + regmap_read(pd->qos_regmap[i], + QOS_EXTCONTROL, + &pd->qos_save_regs[4][i]); + } + return 0; +} + +static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd) +{ + int i; + + for (i = 0; i < pd->num_qos; i++) { + regmap_write(pd->qos_regmap[i], + QOS_PRIORITY, + pd->qos_save_regs[0][i]); + regmap_write(pd->qos_regmap[i], + QOS_MODE, + pd->qos_save_regs[1][i]); + regmap_write(pd->qos_regmap[i], + QOS_BANDWIDTH, + pd->qos_save_regs[2][i]); + regmap_write(pd->qos_regmap[i], + QOS_SATURATION, + pd->qos_save_regs[3][i]); + regmap_write(pd->qos_regmap[i], + QOS_EXTCONTROL, + pd->qos_save_regs[4][i]); + } + + return 0; +} + static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) { struct rockchip_pmu *pmu = pd->pmu; @@ -161,7 +220,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) clk_enable(pd->clks[i]); if (!power_on) { - /* FIXME: add code to save AXI_QOS */ + rockchip_pmu_save_qos(pd); /* if powering down, idle request to NIU first */ rockchip_pmu_set_idle_request(pd, true); @@ -173,7 +232,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) /* if powering up, leave idle mode */ rockchip_pmu_set_idle_request(pd, false); - /* FIXME: add code to restore AXI_QOS */ + rockchip_pmu_restore_qos(pd); } for (i = pd->num_clks - 1; i >= 0; i--) @@ -241,9 +300,10 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, { const struct rockchip_domain_info *pd_info; struct rockchip_pm_domain *pd; + struct device_node *qos_node; struct clk *clk; int clk_cnt; - int i; + int i, j; u32 id; int error; @@ -303,6 +363,45 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, clk, node->name); } + pd->num_qos = of_count_phandle_with_args(node, "pm_qos", + NULL); + + if (pd->num_qos > 0) { + pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos, + sizeof(*pd->qos_regmap), + GFP_KERNEL); + if (!pd->qos_regmap) { + error = -ENOMEM; + goto err_out; + } + + for (j = 0; j < MAX_QOS_REGS_NUM; j++) { + pd->qos_save_regs[j] = devm_kcalloc(pmu->dev, + pd->num_qos, + sizeof(u32), + GFP_KERNEL); + if (!pd->qos_save_regs[j]) { + error = -ENOMEM; + goto err_out; + } + } + + for (j = 0; j < pd->num_qos; j++) { + qos_node = of_parse_phandle(node, "pm_qos", j); + if (!qos_node) { + error = -ENODEV; + goto err_out; + } + pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); + if (IS_ERR(pd->qos_regmap[j])) { + error = -ENODEV; + of_node_put(qos_node); + goto err_out; + } + of_node_put(qos_node); + } + } + error = rockchip_pd_power(pd, true); if (error) { dev_err(pmu->dev, -- GitLab From 0bbd72b4c64fc0803a6efd86ea151184bf553f97 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 18 Apr 2016 12:01:35 +0200 Subject: [PATCH 3919/9938] clk: Add Oxford Semiconductor OXNAS Standard Clocks Add Oxford Semiconductor OXNAS SoC Family Standard Clocks support. Signed-off-by: Neil Armstrong [sboyd@codeaurora.org: Drop NULL/continue check in registration loop] Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 6 ++ drivers/clk/Makefile | 1 + drivers/clk/clk-oxnas.c | 195 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 drivers/clk/clk-oxnas.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c45554957499..2dd371deb23b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -197,6 +197,12 @@ config COMMON_CLK_PXA ---help--- Support for the Marvell PXA SoC. +config COMMON_CLK_OXNAS + bool "Clock driver for the OXNAS SoC Family" + select MFD_SYSCON + ---help--- + Support for the OXNAS SoC Family clocks. + source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/mvebu/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 54964eb43195..4ef71a13ab37 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o +obj-$(CONFIG_COMMON_CLK_OXNAS) += clk-oxnas.o obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c new file mode 100644 index 000000000000..efba7d4dbcfc --- /dev/null +++ b/drivers/clk/clk-oxnas.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2010 Broadcom + * Copyright (C) 2012 Stephen Warren + * Copyright (C) 2016 Neil Armstrong + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Standard regmap gate clocks */ +struct clk_oxnas { + struct clk_hw hw; + signed char bit; + struct regmap *regmap; +}; + +/* Regmap offsets */ +#define CLK_STAT_REGOFFSET 0x24 +#define CLK_SET_REGOFFSET 0x2c +#define CLK_CLR_REGOFFSET 0x30 + +static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw) +{ + return container_of(hw, struct clk_oxnas, hw); +} + +static int oxnas_clk_is_enabled(struct clk_hw *hw) +{ + struct clk_oxnas *std = to_clk_oxnas(hw); + int ret; + unsigned int val; + + ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val); + if (ret < 0) + return ret; + + return val & BIT(std->bit); +} + +static int oxnas_clk_enable(struct clk_hw *hw) +{ + struct clk_oxnas *std = to_clk_oxnas(hw); + + regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit)); + + return 0; +} + +static void oxnas_clk_disable(struct clk_hw *hw) +{ + struct clk_oxnas *std = to_clk_oxnas(hw); + + regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit)); +} + +static const struct clk_ops oxnas_clk_ops = { + .enable = oxnas_clk_enable, + .disable = oxnas_clk_disable, + .is_enabled = oxnas_clk_is_enabled, +}; + +static const char *const oxnas_clk_parents[] = { + "oscillator", +}; + +static const char *const eth_parents[] = { + "gmacclk", +}; + +#define DECLARE_STD_CLKP(__clk, __parent) \ +static const struct clk_init_data clk_##__clk##_init = { \ + .name = __stringify(__clk), \ + .ops = &oxnas_clk_ops, \ + .parent_names = __parent, \ + .num_parents = ARRAY_SIZE(__parent), \ +} + +#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents) + +/* Hardware Bit - Clock association */ +struct clk_oxnas_init_data { + unsigned long bit; + const struct clk_init_data *clk_init; +}; + +/* Clk init data declaration */ +DECLARE_STD_CLK(leon); +DECLARE_STD_CLK(dma_sgdma); +DECLARE_STD_CLK(cipher); +DECLARE_STD_CLK(sata); +DECLARE_STD_CLK(audio); +DECLARE_STD_CLK(usbmph); +DECLARE_STD_CLKP(etha, eth_parents); +DECLARE_STD_CLK(pciea); +DECLARE_STD_CLK(nand); + +/* Table index is clock indice */ +static const struct clk_oxnas_init_data clk_oxnas_init[] = { + [0] = {0, &clk_leon_init}, + [1] = {1, &clk_dma_sgdma_init}, + [2] = {2, &clk_cipher_init}, + /* Skip & Do not touch to DDR clock */ + [3] = {4, &clk_sata_init}, + [4] = {5, &clk_audio_init}, + [5] = {6, &clk_usbmph_init}, + [6] = {7, &clk_etha_init}, + [7] = {8, &clk_pciea_init}, + [8] = {9, &clk_nand_init}, +}; + +struct clk_oxnas_data { + struct clk_oxnas clk_oxnas[ARRAY_SIZE(clk_oxnas_init)]; + struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)]; + struct clk *clks[ARRAY_SIZE(clk_oxnas_init)]; +}; + +static int oxnas_stdclk_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct clk_oxnas_data *clk_oxnas; + struct regmap *regmap; + int i; + + clk_oxnas = devm_kzalloc(&pdev->dev, sizeof(*clk_oxnas), GFP_KERNEL); + if (!clk_oxnas) + return -ENOMEM; + + regmap = syscon_node_to_regmap(of_get_parent(np)); + if (!regmap) { + dev_err(&pdev->dev, "failed to have parent regmap\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) { + struct clk_oxnas *_clk; + + _clk = &clk_oxnas->clk_oxnas[i]; + _clk->bit = clk_oxnas_init[i].bit; + _clk->hw.init = clk_oxnas_init[i].clk_init; + _clk->regmap = regmap; + + clk_oxnas->clks[i] = + devm_clk_register(&pdev->dev, &_clk->hw); + if (WARN_ON(IS_ERR(clk_oxnas->clks[i]))) + return PTR_ERR(clk_oxnas->clks[i]); + } + + clk_oxnas->onecell_data->clks = clk_oxnas->clks; + clk_oxnas->onecell_data->clk_num = ARRAY_SIZE(clk_oxnas_init); + + return of_clk_add_provider(np, of_clk_src_onecell_get, + clk_oxnas->onecell_data); +} + +static int oxnas_stdclk_remove(struct platform_device *pdev) +{ + of_clk_del_provider(pdev->dev.of_node); + + return 0; +} + +static const struct of_device_id oxnas_stdclk_dt_ids[] = { + { .compatible = "oxsemi,ox810se-stdclk" }, + { } +}; +MODULE_DEVICE_TABLE(of, oxnas_stdclk_dt_ids); + +static struct platform_driver oxnas_stdclk_driver = { + .probe = oxnas_stdclk_probe, + .remove = oxnas_stdclk_remove, + .driver = { + .name = "oxnas-stdclk", + .of_match_table = oxnas_stdclk_dt_ids, + }, +}; + +module_platform_driver(oxnas_stdclk_driver); -- GitLab From 624b5ea624f368e8755304bc63a5ee5d0a899dcb Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 18 Apr 2016 12:01:36 +0200 Subject: [PATCH 3920/9938] dt-bindings: Add Oxford Semiconductor OXNAS Standard Clocks bindings Acked-by: Rob Herring Signed-off-by: Neil Armstrong Signed-off-by: Stephen Boyd --- .../bindings/clock/oxnas,stdclk.txt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/oxnas,stdclk.txt diff --git a/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt b/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt new file mode 100644 index 000000000000..208cca6ac4ec --- /dev/null +++ b/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt @@ -0,0 +1,35 @@ +Oxford Semiconductor OXNAS SoC Family Standard Clocks +================================================ + +Please also refer to clock-bindings.txt in this directory for common clock +bindings usage. + +Required properties: +- compatible: Should be "oxsemi,ox810se-stdclk" +- #clock-cells: 1, see below + +Parent node should have the following properties : +- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd" + +For OX810SE, the clock indices are : + - 0: LEON + - 1: DMA_SGDMA + - 2: CIPHER + - 3: SATA + - 4: AUDIO + - 5: USBMPH + - 6: ETHA + - 7: PCIA + - 8: NAND + +example: + +sys: sys-ctrl@000000 { + compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"; + reg = <0x000000 0x100000>; + + stdclk: stdclk { + compatible = "oxsemi,ox810se-stdclk"; + #clock-cells = <1>; + }; +}; -- GitLab From 92a39d9043ba5ff98adb1c31491f00c7bea5466e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Mar 2016 17:38:24 +0100 Subject: [PATCH 3921/9938] clk: composite: Add unregister function The composite clock didn't have any unregistration function, which forced us to use clk_unregister directly on it. While it was already not great from an API point of view, it also meant that we were leaking the clk_composite structure allocated in clk_register_composite. Add a clk_unregister_composite function to fix this. Signed-off-by: Maxime Ripard Signed-off-by: Stephen Boyd --- drivers/clk/clk-composite.c | 15 +++++++++++++++ include/linux/clk-provider.h | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 1f903e1f86a2..b0f3b84ebd13 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -286,3 +286,18 @@ struct clk *clk_register_composite(struct device *dev, const char *name, kfree(composite); return clk; } + +void clk_unregister_composite(struct clk *clk) +{ + struct clk_composite *composite; + struct clk_hw *hw; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + composite = to_clk_composite(hw); + + clk_unregister(clk); + kfree(composite); +} diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index da95258127aa..26a8c9b7be71 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -603,6 +603,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, struct clk_hw *rate_hw, const struct clk_ops *rate_ops, struct clk_hw *gate_hw, const struct clk_ops *gate_ops, unsigned long flags); +void clk_unregister_composite(struct clk *clk); /*** * struct clk_gpio_gate - gpio gated clock -- GitLab From 8f0767611a0ed719caf975d899d8431834ace2d8 Mon Sep 17 00:00:00 2001 From: Andrea Venturi Date: Mon, 21 Mar 2016 17:10:38 +0100 Subject: [PATCH 3922/9938] clk: sunxi: mod1 clock should modify it's parent add CLK_SET_RATE_PARENT to modify the rate on clk upstream Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-a10-mod1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi/clk-a10-mod1.c b/drivers/clk/sunxi/clk-a10-mod1.c index e9d870de165c..e2819fa09637 100644 --- a/drivers/clk/sunxi/clk-a10-mod1.c +++ b/drivers/clk/sunxi/clk-a10-mod1.c @@ -62,7 +62,7 @@ static void __init sun4i_mod1_clk_setup(struct device_node *node) clk = clk_register_composite(NULL, clk_name, parents, i, &mux->hw, &clk_mux_ops, NULL, NULL, - &gate->hw, &clk_gate_ops, 0); + &gate->hw, &clk_gate_ops, CLK_SET_RATE_PARENT); if (IS_ERR(clk)) goto err_free_gate; -- GitLab From 5ed400dd96d8222e667ee473c7ebd676f05113f8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 30 Mar 2016 18:43:29 +0200 Subject: [PATCH 3923/9938] clk: sunxi: Add sun6i/8i display support Add the clock type which is used by the sun6i/8i families for video display. Signed-off-by: Jean-Francois Moine Acked-by: Rob Herring Signed-off-by: Maxime Ripard --- .../devicetree/bindings/clock/sunxi.txt | 1 + drivers/clk/sunxi/clk-sunxi.c | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 834436fbe83d..9de34a832023 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -81,6 +81,7 @@ Required properties: "allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80 "allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80 "allwinner,sun4i-a10-ve-clk" - for the Video Engine clock + "allwinner,sun6i-a31-display-clk" - for the display clocks Required properties for all clocks: - reg : shall be the control register address for the clock. diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 91de0a006773..6ea7cf80a0ab 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -1127,3 +1127,41 @@ static void __init sun6i_pll6_clk_setup(struct device_node *node) } CLK_OF_DECLARE(sun6i_pll6, "allwinner,sun6i-a31-pll6-clk", sun6i_pll6_clk_setup); + +/* + * sun6i display + * + * rate = parent_rate / (m + 1); + */ +static void sun6i_display_factors(struct factors_request *req) +{ + u8 m; + + if (req->rate > req->parent_rate) + req->rate = req->parent_rate; + + m = DIV_ROUND_UP(req->parent_rate, req->rate); + + req->rate = req->parent_rate / m; + req->m = m - 1; +} + +static const struct clk_factors_config sun6i_display_config = { + .mshift = 0, + .mwidth = 4, +}; + +static const struct factors_data sun6i_display_data __initconst = { + .enable = 31, + .mux = 24, + .muxmask = BIT(2) | BIT(1) | BIT(0), + .table = &sun6i_display_config, + .getter = sun6i_display_factors, +}; + +static void __init sun6i_display_setup(struct device_node *node) +{ + sunxi_factors_clk_setup(node, &sun6i_display_data); +} +CLK_OF_DECLARE(sun6i_display, "allwinner,sun6i-a31-display-clk", + sun6i_display_setup); -- GitLab From f4b9ef653c047165f096d32816904be5ee337a63 Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Mon, 11 Apr 2016 10:23:03 +0530 Subject: [PATCH 3924/9938] clk: sunxi: Use resource_size Use the function resource_size instaed of explicit computation. Problem found using Coccinelle. Signed-off-by: Vaishali Thakkar Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sun9i-mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c index a9b176139aca..0c2dd02d8dec 100644 --- a/drivers/clk/sunxi/clk-sun9i-mmc.c +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c @@ -106,7 +106,7 @@ static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev) r = platform_get_resource(pdev, IORESOURCE_MEM, 0); /* one clock/reset pair per word */ - count = DIV_ROUND_UP((r->end - r->start + 1), SUN9I_MMC_WIDTH); + count = DIV_ROUND_UP((resource_size(r)), SUN9I_MMC_WIDTH); data->membase = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(data->membase)) return PTR_ERR(data->membase); -- GitLab From 7f2ea3847d47d49929d41573a3b26c80ddebbef5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Mar 2016 17:38:28 +0100 Subject: [PATCH 3925/9938] dt-bindings: clk: sun5i: add DRAM gates compatible The Allwinner SoCs have a gate controller to gate the access to the DRAM clock to the some devices that need to access the DRAM directly (mostly display / image related IPs). Use a simple gates driver to support the one found in the A13 / R8 SoCs. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Acked-by: Rob Herring Acked-by: Stephen Boyd Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 9de34a832023..1bf588e11d46 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -64,6 +64,7 @@ Required properties: "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3 "allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80 "allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10 + "allwinner,sun5i-a13-dram-gates-clk" - for the DRAM gates on A13 "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 "allwinner,sun4i-a10-mmc-clk" - for the MMC clock "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 -- GitLab From fa4d0ca104bfdcda7b7e2bac855b358f302fd310 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Mar 2016 17:38:26 +0100 Subject: [PATCH 3926/9938] clk: sunxi: Add PLL3 clock The A10 SoCs and relatives have a PLL controller to drive the PLL3 and PLL7, clocked from a 3MHz oscillator, that drives the display related clocks (GPU, display engine, TCON, etc.) Add a driver for it. Acked-by: Rob Herring Acked-by: Chen-Yu Tsai Acked-by: Stephen Boyd Signed-off-by: Maxime Ripard --- .../devicetree/bindings/clock/sunxi.txt | 1 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun4i-pll3.c | 98 +++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun4i-pll3.c diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 1bf588e11d46..005a24c6bd74 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -10,6 +10,7 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun4i-a10-pll3-clk" - for the video PLL clock on A10 "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 3fd7901d48e4..e2f72797bd9a 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile @@ -11,6 +11,7 @@ obj-y += clk-a10-ve.o obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-simple-gates.o +obj-y += clk-sun4i-pll3.o obj-y += clk-sun8i-bus-gates.o obj-y += clk-sun8i-mbus.o obj-y += clk-sun9i-core.o diff --git a/drivers/clk/sunxi/clk-sun4i-pll3.c b/drivers/clk/sunxi/clk-sun4i-pll3.c new file mode 100644 index 000000000000..f66267e77d9c --- /dev/null +++ b/drivers/clk/sunxi/clk-sun4i-pll3.c @@ -0,0 +1,98 @@ +/* + * Copyright 2015 Maxime Ripard + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#define SUN4I_A10_PLL3_GATE_BIT 31 +#define SUN4I_A10_PLL3_DIV_WIDTH 7 +#define SUN4I_A10_PLL3_DIV_SHIFT 0 + +static DEFINE_SPINLOCK(sun4i_a10_pll3_lock); + +static void __init sun4i_a10_pll3_setup(struct device_node *node) +{ + const char *clk_name = node->name, *parent; + struct clk_multiplier *mult; + struct clk_gate *gate; + struct resource res; + void __iomem *reg; + struct clk *clk; + int ret; + + of_property_read_string(node, "clock-output-names", &clk_name); + parent = of_clk_get_parent_name(node, 0); + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%s: Could not map the clock registers\n", clk_name); + return; + } + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto err_unmap; + + gate->reg = reg; + gate->bit_idx = SUN4I_A10_PLL3_GATE_BIT; + gate->lock = &sun4i_a10_pll3_lock; + + mult = kzalloc(sizeof(*mult), GFP_KERNEL); + if (!mult) + goto err_free_gate; + + mult->reg = reg; + mult->shift = SUN4I_A10_PLL3_DIV_SHIFT; + mult->width = SUN4I_A10_PLL3_DIV_WIDTH; + mult->lock = &sun4i_a10_pll3_lock; + + clk = clk_register_composite(NULL, clk_name, + &parent, 1, + NULL, NULL, + &mult->hw, &clk_multiplier_ops, + &gate->hw, &clk_gate_ops, + 0); + if (IS_ERR(clk)) { + pr_err("%s: Couldn't register the clock\n", clk_name); + goto err_free_mult; + } + + ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (ret) { + pr_err("%s: Couldn't register DT provider\n", + clk_name); + goto err_clk_unregister; + } + + return; + +err_clk_unregister: + clk_unregister_composite(clk); +err_free_mult: + kfree(mult); +err_free_gate: + kfree(gate); +err_unmap: + iounmap(reg); + of_address_to_resource(node, 0, &res); + release_mem_region(res.start, resource_size(&res)); +} + +CLK_OF_DECLARE(sun4i_a10_pll3, "allwinner,sun4i-a10-pll3-clk", + sun4i_a10_pll3_setup); -- GitLab From cc510c736b1b278a9925a4a051ecfa72ef8c21fc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 1 Jul 2015 15:48:37 +0200 Subject: [PATCH 3927/9938] clk: sunxi: Add TCON channel1 clock The TCON is a controller generating the timings to output videos signals, acting like both a CRTC and an encoder. It has two channels depending on the output, each channel being driven by its own clock (and own clock controller). Add a driver for the channel 1 clock. Signed-off-by: Maxime Ripard Acked-by: Rob Herring Acked-by: Stephen Boyd --- .../devicetree/bindings/clock/sunxi.txt | 1 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun4i-tcon-ch1.c | 300 ++++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun4i-tcon-ch1.c diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 005a24c6bd74..f70f500256bb 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -75,6 +75,7 @@ Required properties: "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23 "allwinner,sun7i-a20-out-clk" - for the external output clocks "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 + "allwinner,sun4i-a10-tcon-ch1-clk" - for the TCON channel 1 clock on the A10 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31 diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index e2f72797bd9a..2d77407a0037 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile @@ -12,6 +12,7 @@ obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-simple-gates.o obj-y += clk-sun4i-pll3.o +obj-y += clk-sun4i-tcon-ch1.o obj-y += clk-sun8i-bus-gates.o obj-y += clk-sun8i-mbus.o obj-y += clk-sun9i-core.o diff --git a/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c b/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c new file mode 100644 index 000000000000..98a4582de56a --- /dev/null +++ b/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c @@ -0,0 +1,300 @@ +/* + * Copyright 2015 Maxime Ripard + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#define TCON_CH1_SCLK2_PARENTS 4 + +#define TCON_CH1_SCLK2_GATE_BIT BIT(31) +#define TCON_CH1_SCLK2_MUX_MASK 3 +#define TCON_CH1_SCLK2_MUX_SHIFT 24 +#define TCON_CH1_SCLK2_DIV_MASK 0xf +#define TCON_CH1_SCLK2_DIV_SHIFT 0 + +#define TCON_CH1_SCLK1_GATE_BIT BIT(15) +#define TCON_CH1_SCLK1_HALF_BIT BIT(11) + +struct tcon_ch1_clk { + struct clk_hw hw; + spinlock_t lock; + void __iomem *reg; +}; + +#define hw_to_tclk(hw) container_of(hw, struct tcon_ch1_clk, hw) + +static void tcon_ch1_disable(struct clk_hw *hw) +{ + struct tcon_ch1_clk *tclk = hw_to_tclk(hw); + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&tclk->lock, flags); + reg = readl(tclk->reg); + reg &= ~(TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT); + writel(reg, tclk->reg); + spin_unlock_irqrestore(&tclk->lock, flags); +} + +static int tcon_ch1_enable(struct clk_hw *hw) +{ + struct tcon_ch1_clk *tclk = hw_to_tclk(hw); + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&tclk->lock, flags); + reg = readl(tclk->reg); + reg |= TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT; + writel(reg, tclk->reg); + spin_unlock_irqrestore(&tclk->lock, flags); + + return 0; +} + +static int tcon_ch1_is_enabled(struct clk_hw *hw) +{ + struct tcon_ch1_clk *tclk = hw_to_tclk(hw); + u32 reg; + + reg = readl(tclk->reg); + return reg & (TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT); +} + +static u8 tcon_ch1_get_parent(struct clk_hw *hw) +{ + struct tcon_ch1_clk *tclk = hw_to_tclk(hw); + int num_parents = clk_hw_get_num_parents(hw); + u32 reg; + + reg = readl(tclk->reg) >> TCON_CH1_SCLK2_MUX_SHIFT; + reg &= reg >> TCON_CH1_SCLK2_MUX_MASK; + + if (reg >= num_parents) + return -EINVAL; + + return reg; +} + +static int tcon_ch1_set_parent(struct clk_hw *hw, u8 index) +{ + struct tcon_ch1_clk *tclk = hw_to_tclk(hw); + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&tclk->lock, flags); + reg = readl(tclk->reg); + reg &= ~(TCON_CH1_SCLK2_MUX_MASK << TCON_CH1_SCLK2_MUX_SHIFT); + reg |= index << TCON_CH1_SCLK2_MUX_SHIFT; + writel(reg, tclk->reg); + spin_unlock_irqrestore(&tclk->lock, flags); + + return 0; +}; + +static unsigned long tcon_ch1_calc_divider(unsigned long rate, + unsigned long parent_rate, + u8 *div, + bool *half) +{ + unsigned long best_rate = 0; + u8 best_m = 0, m; + bool is_double; + + for (m = 1; m < 16; m++) { + u8 d; + + for (d = 1; d < 3; d++) { + unsigned long tmp_rate; + + tmp_rate = parent_rate / m / d; + + if (tmp_rate > rate) + continue; + + if (!best_rate || + (rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_m = m; + is_double = d; + } + } + } + + if (div && half) { + *div = best_m; + *half = is_double; + } + + return best_rate; +} + +static int tcon_ch1_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + long best_rate = -EINVAL; + int i; + + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { + unsigned long parent_rate; + unsigned long tmp_rate; + struct clk_hw *parent; + + parent = clk_hw_get_parent_by_index(hw, i); + if (!parent) + continue; + + parent_rate = clk_hw_get_rate(parent); + + tmp_rate = tcon_ch1_calc_divider(req->rate, parent_rate, + NULL, NULL); + + if (best_rate < 0 || + (req->rate - tmp_rate) < (req->rate - best_rate)) { + best_rate = tmp_rate; + req->best_parent_rate = parent_rate; + req->best_parent_hw = parent; + } + } + + if (best_rate < 0) + return best_rate; + + req->rate = best_rate; + return 0; +} + +static unsigned long tcon_ch1_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct tcon_ch1_clk *tclk = hw_to_tclk(hw); + u32 reg; + + reg = readl(tclk->reg); + + parent_rate /= (reg & TCON_CH1_SCLK2_DIV_MASK) + 1; + + if (reg & TCON_CH1_SCLK1_HALF_BIT) + parent_rate /= 2; + + return parent_rate; +} + +static int tcon_ch1_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct tcon_ch1_clk *tclk = hw_to_tclk(hw); + unsigned long flags; + bool half; + u8 div_m; + u32 reg; + + tcon_ch1_calc_divider(rate, parent_rate, &div_m, &half); + + spin_lock_irqsave(&tclk->lock, flags); + reg = readl(tclk->reg); + reg &= ~(TCON_CH1_SCLK2_DIV_MASK | TCON_CH1_SCLK1_HALF_BIT); + reg |= (div_m - 1) & TCON_CH1_SCLK2_DIV_MASK; + + if (half) + reg |= TCON_CH1_SCLK1_HALF_BIT; + + writel(reg, tclk->reg); + spin_unlock_irqrestore(&tclk->lock, flags); + + return 0; +} + +static const struct clk_ops tcon_ch1_ops = { + .disable = tcon_ch1_disable, + .enable = tcon_ch1_enable, + .is_enabled = tcon_ch1_is_enabled, + + .get_parent = tcon_ch1_get_parent, + .set_parent = tcon_ch1_set_parent, + + .determine_rate = tcon_ch1_determine_rate, + .recalc_rate = tcon_ch1_recalc_rate, + .set_rate = tcon_ch1_set_rate, +}; + +static void __init tcon_ch1_setup(struct device_node *node) +{ + const char *parents[TCON_CH1_SCLK2_PARENTS]; + const char *clk_name = node->name; + struct clk_init_data init; + struct tcon_ch1_clk *tclk; + struct resource res; + struct clk *clk; + void __iomem *reg; + int ret; + + of_property_read_string(node, "clock-output-names", &clk_name); + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%s: Could not map the clock registers\n", clk_name); + return; + } + + ret = of_clk_parent_fill(node, parents, TCON_CH1_SCLK2_PARENTS); + if (ret != TCON_CH1_SCLK2_PARENTS) { + pr_err("%s Could not retrieve the parents\n", clk_name); + goto err_unmap; + } + + tclk = kzalloc(sizeof(*tclk), GFP_KERNEL); + if (!tclk) + goto err_unmap; + + init.name = clk_name; + init.ops = &tcon_ch1_ops; + init.parent_names = parents; + init.num_parents = TCON_CH1_SCLK2_PARENTS; + init.flags = CLK_SET_RATE_PARENT; + + tclk->reg = reg; + tclk->hw.init = &init; + spin_lock_init(&tclk->lock); + + clk = clk_register(NULL, &tclk->hw); + if (IS_ERR(clk)) { + pr_err("%s: Couldn't register the clock\n", clk_name); + goto err_free_data; + } + + ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (ret) { + pr_err("%s: Couldn't register our clock provider\n", clk_name); + goto err_unregister_clk; + } + + return; + +err_unregister_clk: + clk_unregister(clk); +err_free_data: + kfree(tclk); +err_unmap: + iounmap(reg); + of_address_to_resource(node, 0, &res); + release_mem_region(res.start, resource_size(&res)); +} + +CLK_OF_DECLARE(tcon_ch1, "allwinner,sun4i-a10-tcon-ch1-clk", + tcon_ch1_setup); -- GitLab From 372a12ed9d99c02f105278a9b75f0cb176d15cc1 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 8 Apr 2016 13:40:53 +0200 Subject: [PATCH 3928/9938] PM / Runtime: Move ignore_children flag under CONFIG_PM The ignore_children flag is used only when CONFIG_PM is set, so let's move it into that section within the struct dev_pm_info. Move also the corresponding pm_suspend_ignore_children() API out of device.h into pm_runtime.h, to be consistent with similar APIs. Unfortunate this causes the Toshiba PCI SD mmc host driver to fail to compile as it needs pm_runtime.h, so let's fix this here as well. Signed-off-by: Ulf Hansson Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- drivers/mmc/host/toshsd.c | 1 + include/linux/device.h | 5 ----- include/linux/pm.h | 2 +- include/linux/pm_runtime.h | 6 ++++++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/toshsd.c b/drivers/mmc/host/toshsd.c index e2cdd5fb1423..553ef41bb806 100644 --- a/drivers/mmc/host/toshsd.c +++ b/drivers/mmc/host/toshsd.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/include/linux/device.h b/include/linux/device.h index 002c59728dbe..b130304f9b1b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -956,11 +956,6 @@ static inline bool device_async_suspend_enabled(struct device *dev) return !!dev->power.async_suspend; } -static inline void pm_suspend_ignore_children(struct device *dev, bool enable) -{ - dev->power.ignore_children = enable; -} - static inline void dev_pm_syscore_device(struct device *dev, bool val) { #ifdef CONFIG_PM_SLEEP diff --git a/include/linux/pm.h b/include/linux/pm.h index 6a5d654f4447..06eb353182ab 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -563,7 +563,6 @@ struct dev_pm_info { bool is_suspended:1; /* Ditto */ bool is_noirq_suspended:1; bool is_late_suspended:1; - bool ignore_children:1; bool early_init:1; /* Owned by the PM core */ bool direct_complete:1; /* Owned by the PM core */ spinlock_t lock; @@ -591,6 +590,7 @@ struct dev_pm_info { unsigned int deferred_resume:1; unsigned int run_wake:1; unsigned int runtime_auto:1; + bool ignore_children:1; unsigned int no_callbacks:1; unsigned int irq_safe:1; unsigned int use_autosuspend:1; diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 7af093d6a4dd..2e14d2667b6c 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -56,6 +56,11 @@ extern void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns); extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); +static inline void pm_suspend_ignore_children(struct device *dev, bool enable) +{ + dev->power.ignore_children = enable; +} + static inline bool pm_children_suspended(struct device *dev) { return dev->power.ignore_children @@ -156,6 +161,7 @@ static inline void __pm_runtime_disable(struct device *dev, bool c) {} static inline void pm_runtime_allow(struct device *dev) {} static inline void pm_runtime_forbid(struct device *dev) {} +static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {} static inline bool pm_children_suspended(struct device *dev) { return false; } static inline void pm_runtime_get_noresume(struct device *dev) {} static inline void pm_runtime_put_noidle(struct device *dev) {} -- GitLab From 350a73b4f896e620216d8e9429bbac16d89da8b0 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 21 Apr 2016 13:51:55 +1000 Subject: [PATCH 3929/9938] PCI: rcar-pcie: Remove Gen2 designation from Kconfig It appears that Gen2 is a misnomer for the R-Car PCIE driver which also supports Gen 1 and Gen 3 SoCs. Accordingly, drop Gen 2 from the help text and Kconfig symbol. Also, re-arange the Kconfig symbol name to use PCIE as the prefix. This appears to be in keeping with other PCIE Kconfig symbols. Reported-by: Geert Uytterhoeven Signed-off-by: Simon Horman Acked-by: Bjorn Helgaas Acked-by: Geert Uytterhoeven --- arch/arm/configs/multi_v7_defconfig | 2 +- arch/arm/configs/shmobile_defconfig | 2 +- arch/arm64/configs/defconfig | 2 +- drivers/pci/host/Kconfig | 4 ++-- drivers/pci/host/Makefile | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 28234906a064..f9fb719fb940 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -119,7 +119,7 @@ CONFIG_PCI_MSI=y CONFIG_PCI_MVEBU=y CONFIG_PCI_TEGRA=y CONFIG_PCI_RCAR_GEN2=y -CONFIG_PCI_RCAR_GEN2_PCIE=y +CONFIG_PCIE_RCAR=y CONFIG_PCIEPORTBUS=y CONFIG_SMP=y CONFIG_NR_CPUS=16 diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index b7b714c3958c..64547f453d94 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -24,7 +24,7 @@ CONFIG_PL310_ERRATA_588369=y CONFIG_ARM_ERRATA_754322=y CONFIG_PCI=y CONFIG_PCI_RCAR_GEN2=y -CONFIG_PCI_RCAR_GEN2_PCIE=y +CONFIG_PCIE_RCAR=y CONFIG_SMP=y CONFIG_SCHED_MC=y CONFIG_HAVE_ARM_ARCH_TIMER=y diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f70505186820..fb2f696b91e7 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -56,7 +56,7 @@ CONFIG_ARCH_ZYNQMP=y CONFIG_PCI=y CONFIG_PCI_MSI=y CONFIG_PCI_IOV=y -CONFIG_PCI_RCAR_GEN2_PCIE=y +CONFIG_PCIE_RCAR=y CONFIG_PCI_HOST_GENERIC=y CONFIG_PCI_XGENE=y CONFIG_PCI_LAYERSCAPE=y diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 7a0780d56d2d..8fb1cf54617d 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -69,11 +69,11 @@ config PCI_RCAR_GEN2 There are 3 internal PCI controllers available with a single built-in EHCI/OHCI host controller present on each one. -config PCI_RCAR_GEN2_PCIE +config PCIE_RCAR bool "Renesas R-Car PCIe controller" depends on ARCH_RENESAS || (ARM && COMPILE_TEST) help - Say Y here if you want PCIe controller support on R-Car Gen2 SoCs. + Say Y here if you want PCIe controller support on R-Car SoCs. config PCI_HOST_COMMON bool diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index d85b5faf9bbc..d3d8e1b36fb9 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o -obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o +obj-$(CONFIG_PCIE_RCAR) += pcie-rcar.o obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o -- GitLab From a03bd5735dfa87a5db585e162eda00794690c534 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 21 Apr 2016 20:39:32 +0900 Subject: [PATCH 3930/9938] arm64: defconfig: Add Renesas R-Car USB 3.0 driver support Signed-off-by: Yoshihiro Shimoda Signed-off-by: Simon Horman --- arch/arm64/configs/defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f70505186820..c3cdd640bea3 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -189,7 +189,7 @@ CONFIG_SND_SOC_AK4613=y CONFIG_USB=y CONFIG_USB_OTG=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_XHCI_RCAR=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_MSM=y CONFIG_USB_EHCI_HCD_PLATFORM=y -- GitLab From 9df3921e026532eb3bd2904745d990c0a9f0b4e4 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 31 Mar 2016 11:21:25 +0200 Subject: [PATCH 3931/9938] PM / Domains: Rename stop_ok to suspend_ok for the genpd governor The genpd governor validates the latency constraints to find out whether it's acceptable to runtime suspend a device. Earlier this validation was made to know whether it was okay to invoke the ->stop() callback for the device, hence the governor used the name "stop_ok" for the related variables. To clarify the code around this, let's rename these variables from "stop_ok" to "suspend_ok". Signed-off-by: Ulf Hansson Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 6 +++--- drivers/base/power/domain_governor.c | 20 ++++++++++---------- include/linux/pm_domain.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 56705b52758e..c62687d9fa5a 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -382,7 +382,7 @@ static void genpd_power_off_work_fn(struct work_struct *work) static int pm_genpd_runtime_suspend(struct device *dev) { struct generic_pm_domain *genpd; - bool (*stop_ok)(struct device *__dev); + bool (*suspend_ok)(struct device *__dev); struct gpd_timing_data *td = &dev_gpd_data(dev)->td; bool runtime_pm = pm_runtime_enabled(dev); ktime_t time_start; @@ -401,8 +401,8 @@ static int pm_genpd_runtime_suspend(struct device *dev) * runtime PM is disabled. Under these circumstances, we shall skip * validating/measuring the PM QoS latency. */ - stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; - if (runtime_pm && stop_ok && !stop_ok(dev)) + suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL; + if (runtime_pm && suspend_ok && !suspend_ok(dev)) return -EBUSY; /* Measure suspend latency. */ diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 00a5436dd44b..2e0fce711135 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -37,10 +37,10 @@ static int dev_update_qos_constraint(struct device *dev, void *data) } /** - * default_stop_ok - Default PM domain governor routine for stopping devices. + * default_suspend_ok - Default PM domain governor routine to suspend devices. * @dev: Device to check. */ -static bool default_stop_ok(struct device *dev) +static bool default_suspend_ok(struct device *dev) { struct gpd_timing_data *td = &dev_gpd_data(dev)->td; unsigned long flags; @@ -51,13 +51,13 @@ static bool default_stop_ok(struct device *dev) spin_lock_irqsave(&dev->power.lock, flags); if (!td->constraint_changed) { - bool ret = td->cached_stop_ok; + bool ret = td->cached_suspend_ok; spin_unlock_irqrestore(&dev->power.lock, flags); return ret; } td->constraint_changed = false; - td->cached_stop_ok = false; + td->cached_suspend_ok = false; td->effective_constraint_ns = -1; constraint_ns = __dev_pm_qos_read_value(dev); @@ -83,13 +83,13 @@ static bool default_stop_ok(struct device *dev) return false; } td->effective_constraint_ns = constraint_ns; - td->cached_stop_ok = constraint_ns >= 0; + td->cached_suspend_ok = constraint_ns >= 0; /* * The children have been suspended already, so we don't need to take - * their stop latencies into account here. + * their suspend latencies into account here. */ - return td->cached_stop_ok; + return td->cached_suspend_ok; } /** @@ -150,7 +150,7 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd, */ td = &to_gpd_data(pdd)->td; constraint_ns = td->effective_constraint_ns; - /* default_stop_ok() need not be called before us. */ + /* default_suspend_ok() need not be called before us. */ if (constraint_ns < 0) { constraint_ns = dev_pm_qos_read_value(pdd->dev); constraint_ns *= NSEC_PER_USEC; @@ -227,7 +227,7 @@ static bool always_on_power_down_ok(struct dev_pm_domain *domain) } struct dev_power_governor simple_qos_governor = { - .stop_ok = default_stop_ok, + .suspend_ok = default_suspend_ok, .power_down_ok = default_power_down_ok, }; @@ -236,5 +236,5 @@ struct dev_power_governor simple_qos_governor = { */ struct dev_power_governor pm_domain_always_on_gov = { .power_down_ok = always_on_power_down_ok, - .stop_ok = default_stop_ok, + .suspend_ok = default_suspend_ok, }; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 49cd8890b873..e91393954384 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -28,7 +28,7 @@ enum gpd_status { struct dev_power_governor { bool (*power_down_ok)(struct dev_pm_domain *domain); - bool (*stop_ok)(struct device *dev); + bool (*suspend_ok)(struct device *dev); }; struct gpd_dev_ops { @@ -94,7 +94,7 @@ struct gpd_timing_data { s64 resume_latency_ns; s64 effective_constraint_ns; bool constraint_changed; - bool cached_stop_ok; + bool cached_suspend_ok; }; struct pm_domain_data { -- GitLab From 795bd2e7e86967ced927948eff08fe8201ba5fc3 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 31 Mar 2016 11:21:26 +0200 Subject: [PATCH 3932/9938] PM / Domains: Rename pm_genpd_runtime_suspend|resume() Follow genpd's rule for names of static functions, by renaming pm_genpd_runtime_suspend|resume() to genpd_runtime_suspend|resume(). Signed-off-by: Ulf Hansson Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index c62687d9fa5a..75b994a63e71 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -372,14 +372,14 @@ static void genpd_power_off_work_fn(struct work_struct *work) } /** - * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain. + * genpd_runtime_suspend - Suspend a device belonging to I/O PM domain. * @dev: Device to suspend. * * Carry out a runtime suspend of a device under the assumption that its * pm_domain field points to the domain member of an object of type * struct generic_pm_domain representing a PM domain consisting of I/O devices. */ -static int pm_genpd_runtime_suspend(struct device *dev) +static int genpd_runtime_suspend(struct device *dev) { struct generic_pm_domain *genpd; bool (*suspend_ok)(struct device *__dev); @@ -446,14 +446,14 @@ static int pm_genpd_runtime_suspend(struct device *dev) } /** - * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain. + * genpd_runtime_resume - Resume a device belonging to I/O PM domain. * @dev: Device to resume. * * Carry out a runtime resume of a device under the assumption that its * pm_domain field points to the domain member of an object of type * struct generic_pm_domain representing a PM domain consisting of I/O devices. */ -static int pm_genpd_runtime_resume(struct device *dev) +static int genpd_runtime_resume(struct device *dev) { struct generic_pm_domain *genpd; struct gpd_timing_data *td = &dev_gpd_data(dev)->td; @@ -1498,8 +1498,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd, genpd->device_count = 0; genpd->max_off_time_ns = -1; genpd->max_off_time_changed = true; - genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; - genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; + genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; + genpd->domain.ops.runtime_resume = genpd_runtime_resume; genpd->domain.ops.prepare = pm_genpd_prepare; genpd->domain.ops.suspend = pm_genpd_suspend; genpd->domain.ops.suspend_late = pm_genpd_suspend_late; -- GitLab From 54eeddbf92d0de297d78f7419dde00079d553dec Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 31 Mar 2016 11:21:27 +0200 Subject: [PATCH 3933/9938] PM / Domains: Remove ->save|restore_state() callbacks As a part of the ongoing consolidation of genpd, it's become questionable whether clients actually needs to be able to assign their own set of ->save|restore_state() callbacks. Currently all users copes fine with the default callbacks, so let's remove the configuration option and stick to the default ones. This enables further clarifications of the related code and let's also rename pm_genpd_default_save|restore_state() into __genpd_runtime_suspend|resume() to apply the rule of static functionnames in genpd. Signed-off-by: Ulf Hansson Reviewed-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 113 ++++++++++++++++-------------------- include/linux/pm_domain.h | 2 - 2 files changed, 49 insertions(+), 66 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 75b994a63e71..4ce4ce0a2730 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -229,17 +229,6 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) return ret; } -static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) -{ - return GENPD_DEV_CALLBACK(genpd, int, save_state, dev); -} - -static int genpd_restore_dev(struct generic_pm_domain *genpd, - struct device *dev) -{ - return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev); -} - static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, unsigned long val, void *ptr) { @@ -371,6 +360,52 @@ static void genpd_power_off_work_fn(struct work_struct *work) mutex_unlock(&genpd->lock); } +/** + * __genpd_runtime_suspend - walk the hierarchy of ->runtime_suspend() callbacks + * @dev: Device to handle. + */ +static int __genpd_runtime_suspend(struct device *dev) +{ + int (*cb)(struct device *__dev); + + if (dev->type && dev->type->pm) + cb = dev->type->pm->runtime_suspend; + else if (dev->class && dev->class->pm) + cb = dev->class->pm->runtime_suspend; + else if (dev->bus && dev->bus->pm) + cb = dev->bus->pm->runtime_suspend; + else + cb = NULL; + + if (!cb && dev->driver && dev->driver->pm) + cb = dev->driver->pm->runtime_suspend; + + return cb ? cb(dev) : 0; +} + +/** + * __genpd_runtime_resume - walk the hierarchy of ->runtime_resume() callbacks + * @dev: Device to handle. + */ +static int __genpd_runtime_resume(struct device *dev) +{ + int (*cb)(struct device *__dev); + + if (dev->type && dev->type->pm) + cb = dev->type->pm->runtime_resume; + else if (dev->class && dev->class->pm) + cb = dev->class->pm->runtime_resume; + else if (dev->bus && dev->bus->pm) + cb = dev->bus->pm->runtime_resume; + else + cb = NULL; + + if (!cb && dev->driver && dev->driver->pm) + cb = dev->driver->pm->runtime_resume; + + return cb ? cb(dev) : 0; +} + /** * genpd_runtime_suspend - Suspend a device belonging to I/O PM domain. * @dev: Device to suspend. @@ -409,13 +444,13 @@ static int genpd_runtime_suspend(struct device *dev) if (runtime_pm) time_start = ktime_get(); - ret = genpd_save_dev(genpd, dev); + ret = __genpd_runtime_suspend(dev); if (ret) return ret; ret = genpd_stop_dev(genpd, dev); if (ret) { - genpd_restore_dev(genpd, dev); + __genpd_runtime_resume(dev); return ret; } @@ -491,7 +526,7 @@ static int genpd_runtime_resume(struct device *dev) if (ret) goto err_poweroff; - ret = genpd_restore_dev(genpd, dev); + ret = __genpd_runtime_resume(dev); if (ret) goto err_stop; @@ -1427,54 +1462,6 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, } EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); -/* Default device callbacks for generic PM domains. */ - -/** - * pm_genpd_default_save_state - Default "save device state" for PM domains. - * @dev: Device to handle. - */ -static int pm_genpd_default_save_state(struct device *dev) -{ - int (*cb)(struct device *__dev); - - if (dev->type && dev->type->pm) - cb = dev->type->pm->runtime_suspend; - else if (dev->class && dev->class->pm) - cb = dev->class->pm->runtime_suspend; - else if (dev->bus && dev->bus->pm) - cb = dev->bus->pm->runtime_suspend; - else - cb = NULL; - - if (!cb && dev->driver && dev->driver->pm) - cb = dev->driver->pm->runtime_suspend; - - return cb ? cb(dev) : 0; -} - -/** - * pm_genpd_default_restore_state - Default PM domains "restore device state". - * @dev: Device to handle. - */ -static int pm_genpd_default_restore_state(struct device *dev) -{ - int (*cb)(struct device *__dev); - - if (dev->type && dev->type->pm) - cb = dev->type->pm->runtime_resume; - else if (dev->class && dev->class->pm) - cb = dev->class->pm->runtime_resume; - else if (dev->bus && dev->bus->pm) - cb = dev->bus->pm->runtime_resume; - else - cb = NULL; - - if (!cb && dev->driver && dev->driver->pm) - cb = dev->driver->pm->runtime_resume; - - return cb ? cb(dev) : 0; -} - /** * pm_genpd_init - Initialize a generic I/O PM domain object. * @genpd: PM domain object to initialize. @@ -1520,8 +1507,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd, genpd->domain.ops.restore_early = pm_genpd_resume_early; genpd->domain.ops.restore = pm_genpd_resume; genpd->domain.ops.complete = pm_genpd_complete; - genpd->dev_ops.save_state = pm_genpd_default_save_state; - genpd->dev_ops.restore_state = pm_genpd_default_restore_state; if (genpd->flags & GENPD_FLAG_PM_CLK) { genpd->dev_ops.stop = pm_clk_suspend; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index e91393954384..39285c7bd3f5 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -34,8 +34,6 @@ struct dev_power_governor { struct gpd_dev_ops { int (*start)(struct device *dev); int (*stop)(struct device *dev); - int (*save_state)(struct device *dev); - int (*restore_state)(struct device *dev); bool (*active_wakeup)(struct device *dev); }; -- GitLab From 916633a403702549d37ea353e63a68e5b0dc27ad Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 7 Apr 2016 17:12:31 +0200 Subject: [PATCH 3934/9938] locking/rwsem: Provide down_write_killable() Now that all the architectures implement the necessary glue code we can introduce down_write_killable(). The only difference wrt. regular down_write() is that the slow path waits in TASK_KILLABLE state and the interruption by the fatal signal is reported as -EINTR to the caller. Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Chris Zankel Cc: David S. Miller Cc: Linus Torvalds Cc: Max Filippov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Signed-off-by: Davidlohr Bueso Cc: Signed-off-by: Jason Low Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-alpha@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linux-xtensa@linux-xtensa.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1460041951-22347-12-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/rwsem.h | 6 +++--- include/linux/lockdep.h | 15 +++++++++++++++ include/linux/rwsem.h | 1 + kernel/locking/rwsem.c | 19 +++++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h index d759c5f70f49..453744c1d347 100644 --- a/arch/x86/include/asm/rwsem.h +++ b/arch/x86/include/asm/rwsem.h @@ -102,9 +102,9 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) #define ____down_write(sem, slow_path) \ ({ \ long tmp; \ - struct rw_semaphore* ret = sem; \ + struct rw_semaphore* ret; \ asm volatile("# beginning down_write\n\t" \ - LOCK_PREFIX " xadd %1,(%2)\n\t" \ + LOCK_PREFIX " xadd %1,(%3)\n\t" \ /* adds 0xffff0001, returns the old value */ \ " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \ /* was the active mask 0 before? */\ @@ -112,7 +112,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) " call " slow_path "\n" \ "1:\n" \ "# ending down_write" \ - : "+m" (sem->count), "=d" (tmp), "+a" (ret) \ + : "+m" (sem->count), "=d" (tmp), "=a" (ret) \ : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \ : "memory", "cc"); \ ret; \ diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index d026b190c530..accfe56d8c51 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -444,6 +444,18 @@ do { \ lock_acquired(&(_lock)->dep_map, _RET_IP_); \ } while (0) +#define LOCK_CONTENDED_RETURN(_lock, try, lock) \ +({ \ + int ____err = 0; \ + if (!try(_lock)) { \ + lock_contended(&(_lock)->dep_map, _RET_IP_); \ + ____err = lock(_lock); \ + } \ + if (!____err) \ + lock_acquired(&(_lock)->dep_map, _RET_IP_); \ + ____err; \ +}) + #else /* CONFIG_LOCK_STAT */ #define lock_contended(lockdep_map, ip) do {} while (0) @@ -452,6 +464,9 @@ do { \ #define LOCK_CONTENDED(_lock, try, lock) \ lock(_lock) +#define LOCK_CONTENDED_RETURN(_lock, try, lock) \ + lock(_lock) + #endif /* CONFIG_LOCK_STAT */ #ifdef CONFIG_LOCKDEP diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 7d7ae029dac5..d1c12d160ace 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -118,6 +118,7 @@ extern int down_read_trylock(struct rw_semaphore *sem); * lock for writing */ extern void down_write(struct rw_semaphore *sem); +extern int __must_check down_write_killable(struct rw_semaphore *sem); /* * trylock for writing -- returns 1 if successful, 0 if contention diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index 205be0ce34de..c817216c1615 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -54,6 +54,25 @@ void __sched down_write(struct rw_semaphore *sem) EXPORT_SYMBOL(down_write); +/* + * lock for writing + */ +int __sched down_write_killable(struct rw_semaphore *sem) +{ + might_sleep(); + rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_); + + if (LOCK_CONTENDED_RETURN(sem, __down_write_trylock, __down_write_killable)) { + rwsem_release(&sem->dep_map, 1, _RET_IP_); + return -EINTR; + } + + rwsem_set_owner(sem); + return 0; +} + +EXPORT_SYMBOL(down_write_killable); + /* * trylock for writing -- returns 1 if successful, 0 if contention */ -- GitLab From 00fb16e26ac8559e69c3bb14284f4a548d28ee0d Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Wed, 13 Apr 2016 11:57:12 +0200 Subject: [PATCH 3935/9938] locking/rwsem, x86: Add frame annotation for call_rwsem_down_write_failed_killable() 3387a535ce62 ("x86/asm: Create stack frames in rwsem functions") has added FRAME_{BEGIN,END} annotations to rwsem asm stubs. The patch which has added call_rwsem_down_write_failed_killable() was based on an older tree so it didn't know about annotations. Let's add them. This addresses the following objtool warning: arch/x86/lib/rwsem.o: warning: objtool: call_rwsem_down_write_failed_killable()+0xe: call without frame pointer save/setup Reported-by: Ingo Molnar Signed-off-by: Michal Hocko Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-arch@vger.kernel.org Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1460541432-21631-1-git-send-email-mhocko@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/lib/rwsem.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/lib/rwsem.S b/arch/x86/lib/rwsem.S index 4534a7e912f3..a37462a23546 100644 --- a/arch/x86/lib/rwsem.S +++ b/arch/x86/lib/rwsem.S @@ -107,10 +107,12 @@ ENTRY(call_rwsem_down_write_failed) ENDPROC(call_rwsem_down_write_failed) ENTRY(call_rwsem_down_write_failed_killable) + FRAME_BEGIN save_common_regs movq %rax,%rdi call rwsem_down_write_failed_killable restore_common_regs + FRAME_END ret ENDPROC(call_rwsem_down_write_failed_killable) -- GitLab From be32bcbbd18213803ff24e480340d4d2cca1df4f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:36 +0200 Subject: [PATCH 3936/9938] soc: renesas: Move pm-rcar to drivers/soc/renesas/rcar-sysc Move the pm-rcar driver from arch/arm/mach-shmobile/ to drivers/soc/renesas/, and its header file to include/linux/soc/renesas/, so it can be shared between arm32 (R-Car H1 and Gen2) and arm64 (R-Car Gen3). Rename it to rcar-sysc as it's really a driver for the R-Car System Controller (SYSC). Kill the intermediate PM_RCAR config symbol, as it's not user configurable anymore, and to prepare for SoC-specific make rules. Add the missing #include to rcar-sysc.h, which was exposed by different include order. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- MAINTAINERS | 4 ++++ arch/arm/mach-shmobile/Kconfig | 11 ++++------- arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/pm-r8a7779.c | 3 ++- arch/arm/mach-shmobile/pm-rcar-gen2.c | 2 +- arch/arm/mach-shmobile/smp-r8a7779.c | 2 +- arch/arm/mach-shmobile/smp-r8a7790.c | 2 +- drivers/soc/Makefile | 3 ++- drivers/soc/renesas/Makefile | 5 +++++ .../pm-rcar.c => drivers/soc/renesas/rcar-sysc.c | 2 +- .../linux/soc/renesas/rcar-sysc.h | 8 +++++--- 11 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 drivers/soc/renesas/Makefile rename arch/arm/mach-shmobile/pm-rcar.c => drivers/soc/renesas/rcar-sysc.c (99%) rename arch/arm/mach-shmobile/pm-rcar.h => include/linux/soc/renesas/rcar-sysc.h (66%) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..a0e23922a90b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1491,6 +1491,8 @@ Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next S: Supported F: arch/arm64/boot/dts/renesas/ +F: drivers/soc/renesas/ +F: include/linux/soc/renesas/ ARM/RISCPC ARCHITECTURE M: Russell King @@ -1604,6 +1606,8 @@ F: arch/arm/configs/shmobile_defconfig F: arch/arm/include/debug/renesas-scif.S F: arch/arm/mach-shmobile/ F: drivers/sh/ +F: drivers/soc/renesas/ +F: include/linux/soc/renesas/ ARM/SOCFPGA ARCHITECTURE M: Dinh Nguyen diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index f2bc5c353119..fe4ccb52f921 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -4,11 +4,6 @@ config ARCH_SHMOBILE config ARCH_SHMOBILE_MULTI bool -config PM_RCAR - bool - select PM - select PM_GENERIC_DOMAINS - config PM_RMOBILE bool select PM @@ -16,13 +11,15 @@ config PM_RMOBILE config ARCH_RCAR_GEN1 bool - select PM_RCAR + select PM + select PM_GENERIC_DOMAINS select RENESAS_INTC_IRQPIN select SYS_SUPPORTS_SH_TMU config ARCH_RCAR_GEN2 bool - select PM_RCAR + select PM + select PM_GENERIC_DOMAINS select RENESAS_IRQC select SYS_SUPPORTS_SH_CMT select PCI_DOMAINS if PCI diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index a65c80ac9009..ebb909c55b85 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -39,7 +39,6 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o # PM objects obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o -obj-$(CONFIG_PM_RCAR) += pm-rcar.o obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c index 14c42a1bdf1e..4174cbcbc467 100644 --- a/arch/arm/mach-shmobile/pm-r8a7779.c +++ b/arch/arm/mach-shmobile/pm-r8a7779.c @@ -9,9 +9,10 @@ * for more details. */ +#include + #include -#include "pm-rcar.h" #include "r8a7779.h" /* SYSC */ diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c index 6815781ad116..691ac166a277 100644 --- a/arch/arm/mach-shmobile/pm-rcar-gen2.c +++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c @@ -13,9 +13,9 @@ #include #include #include +#include #include #include "common.h" -#include "pm-rcar.h" #include "rcar-gen2.h" /* RST */ diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index f5c31fbc10b2..c6951ee24588 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -19,13 +19,13 @@ #include #include #include +#include #include #include #include #include "common.h" -#include "pm-rcar.h" #include "r8a7779.h" #define AVECR IOMEM(0xfe700040) diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c index f6426c6fdefc..28f26d5362d8 100644 --- a/arch/arm/mach-shmobile/smp-r8a7790.c +++ b/arch/arm/mach-shmobile/smp-r8a7790.c @@ -17,12 +17,12 @@ #include #include #include +#include #include #include "common.h" #include "platsmp-apmu.h" -#include "pm-rcar.h" #include "rcar-gen2.h" #include "r8a7790.h" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 5ade71306ee1..380230f03874 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -9,7 +9,8 @@ obj-$(CONFIG_MACH_DOVE) += dove/ obj-y += fsl/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_QCOM) += qcom/ -obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ +obj-$(CONFIG_ARCH_RENESAS) += renesas/ +obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_SOC_SAMSUNG) += samsung/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile new file mode 100644 index 000000000000..2b64f6c94681 --- /dev/null +++ b/drivers/soc/renesas/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o diff --git a/arch/arm/mach-shmobile/pm-rcar.c b/drivers/soc/renesas/rcar-sysc.c similarity index 99% rename from arch/arm/mach-shmobile/pm-rcar.c rename to drivers/soc/renesas/rcar-sysc.c index 0af05d288b09..d59bcdf78f0b 100644 --- a/arch/arm/mach-shmobile/pm-rcar.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -13,7 +13,7 @@ #include #include #include -#include "pm-rcar.h" +#include /* SYSC Common */ #define SYSCSR 0x00 /* SYSC Status Register */ diff --git a/arch/arm/mach-shmobile/pm-rcar.h b/include/linux/soc/renesas/rcar-sysc.h similarity index 66% rename from arch/arm/mach-shmobile/pm-rcar.h rename to include/linux/soc/renesas/rcar-sysc.h index 1b901db4a24c..96f30c288388 100644 --- a/arch/arm/mach-shmobile/pm-rcar.h +++ b/include/linux/soc/renesas/rcar-sysc.h @@ -1,5 +1,7 @@ -#ifndef PM_RCAR_H -#define PM_RCAR_H +#ifndef __LINUX_SOC_RENESAS_RCAR_SYSC_H__ +#define __LINUX_SOC_RENESAS_RCAR_SYSC_H__ + +#include struct rcar_sysc_ch { u16 chan_offs; @@ -12,4 +14,4 @@ int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch); bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch); void __iomem *rcar_sysc_init(phys_addr_t base); -#endif /* PM_RCAR_H */ +#endif /* __LINUX_SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From 68667cebfc0d27d2153d7a6b489f3231b533d9bc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:37 +0200 Subject: [PATCH 3937/9938] soc: renesas: rcar-sysc: Improve rcar_sysc_power() debug info Print requested power domain state. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/rcar-sysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index d59bcdf78f0b..9ba5fd15c53b 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -128,7 +128,7 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) out: spin_unlock_irqrestore(&rcar_sysc_lock, flags); - pr_debug("sysc power domain %d: %08x -> %d\n", + pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret); return ret; } -- GitLab From dcc09fd143bb97c2e83e443f7343c07aa0a9a6c0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:38 +0200 Subject: [PATCH 3938/9938] soc: renesas: rcar-sysc: Add DT support for SYSC PM domains Populate the SYSC PM domains from DT, based on the presence of a device node for the System Controller. The actual power area hiearchy, and features of specific areas are obtained from tables in the C code. The SYSCIER and SYSCIMR register values are derived from the power areas present, which will help to get rid of the hardcoded values in R-Car H1 and R-Car Gen2 platform code later. Initialization is done from an early_initcall(), to make sure the PM Domains are initialized before secondary CPU bringup. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Ulf Hansson Signed-off-by: Simon Horman --- drivers/soc/renesas/rcar-sysc.c | 202 +++++++++++++++++++++++++++++++- drivers/soc/renesas/rcar-sysc.h | 53 +++++++++ 2 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/renesas/rcar-sysc.h diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 9ba5fd15c53b..95f2b59cbd76 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -2,6 +2,7 @@ * R-Car SYSC Power management support * * Copyright (C) 2014 Magnus Damm + * Copyright (C) 2015-2016 Glider bvba * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -11,10 +12,15 @@ #include #include #include +#include +#include +#include #include #include #include +#include "rcar-sysc.h" + /* SYSC Common */ #define SYSCSR 0x00 /* SYSC Status Register */ #define SYSCISR 0x04 /* Interrupt Status Register */ @@ -29,7 +35,8 @@ /* * Power Control Register Offsets inside the register block for each domain * Note: The "CR" registers for ARM cores exist on H1 only - * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2 + * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2 + * Use PSCI on R-Car Gen3 */ #define PWRSR_OFFS 0x00 /* Power Status Register */ #define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */ @@ -48,6 +55,8 @@ #define SYSCISR_RETRIES 1000 #define SYSCISR_DELAY_US 1 +#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */ + static void __iomem *rcar_sysc_base; static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */ @@ -162,3 +171,194 @@ void __iomem *rcar_sysc_init(phys_addr_t base) return rcar_sysc_base; } + +struct rcar_sysc_pd { + struct generic_pm_domain genpd; + struct rcar_sysc_ch ch; + unsigned int flags; + char name[0]; +}; + +static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d) +{ + return container_of(d, struct rcar_sysc_pd, genpd); +} + +static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd) +{ + struct rcar_sysc_pd *pd = to_rcar_pd(genpd); + + pr_debug("%s: %s\n", __func__, genpd->name); + + if (pd->flags & PD_NO_CR) { + pr_debug("%s: Cannot control %s\n", __func__, genpd->name); + return -EBUSY; + } + + if (pd->flags & PD_BUSY) { + pr_debug("%s: %s busy\n", __func__, genpd->name); + return -EBUSY; + } + + return rcar_sysc_power_down(&pd->ch); +} + +static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd) +{ + struct rcar_sysc_pd *pd = to_rcar_pd(genpd); + + pr_debug("%s: %s\n", __func__, genpd->name); + + if (pd->flags & PD_NO_CR) { + pr_debug("%s: Cannot control %s\n", __func__, genpd->name); + return 0; + } + + return rcar_sysc_power_up(&pd->ch); +} + +static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) +{ + struct generic_pm_domain *genpd = &pd->genpd; + const char *name = pd->genpd.name; + struct dev_power_governor *gov = &simple_qos_governor; + + if (pd->flags & PD_CPU) { + /* + * This domain contains a CPU core and therefore it should + * only be turned off if the CPU is not in use. + */ + pr_debug("PM domain %s contains %s\n", name, "CPU"); + pd->flags |= PD_BUSY; + gov = &pm_domain_always_on_gov; + } else if (pd->flags & PD_SCU) { + /* + * This domain contains an SCU and cache-controller, and + * therefore it should only be turned off if the CPU cores are + * not in use. + */ + pr_debug("PM domain %s contains %s\n", name, "SCU"); + pd->flags |= PD_BUSY; + gov = &pm_domain_always_on_gov; + } else if (pd->flags & PD_NO_CR) { + /* + * This domain cannot be turned off. + */ + pd->flags |= PD_BUSY; + gov = &pm_domain_always_on_gov; + } + + genpd->power_off = rcar_sysc_pd_power_off; + genpd->power_on = rcar_sysc_pd_power_on; + + if (pd->flags & (PD_CPU | PD_NO_CR)) { + /* Skip CPUs (handled by SMP code) and areas without control */ + pr_debug("%s: Not touching %s\n", __func__, genpd->name); + goto finalize; + } + + if (!rcar_sysc_power_is_off(&pd->ch)) { + pr_debug("%s: %s is already powered\n", __func__, genpd->name); + goto finalize; + } + + rcar_sysc_power_up(&pd->ch); + +finalize: + pm_genpd_init(genpd, gov, false); +} + +static const struct of_device_id rcar_sysc_matches[] = { + { /* sentinel */ } +}; + +struct rcar_pm_domains { + struct genpd_onecell_data onecell_data; + struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1]; +}; + +static int __init rcar_sysc_pd_init(void) +{ + const struct rcar_sysc_info *info; + const struct of_device_id *match; + struct rcar_pm_domains *domains; + struct device_node *np; + u32 syscier, syscimr; + void __iomem *base; + unsigned int i; + int error; + + np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match); + if (!np) + return -ENODEV; + + info = match->data; + + base = of_iomap(np, 0); + if (!base) { + pr_warn("%s: Cannot map regs\n", np->full_name); + error = -ENOMEM; + goto out_put; + } + + rcar_sysc_base = base; + + domains = kzalloc(sizeof(*domains), GFP_KERNEL); + if (!domains) { + error = -ENOMEM; + goto out_put; + } + + domains->onecell_data.domains = domains->domains; + domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); + + for (i = 0, syscier = 0; i < info->num_areas; i++) + syscier |= BIT(info->areas[i].isr_bit); + + /* + * Mask all interrupt sources to prevent the CPU from receiving them. + * Make sure not to clear reserved bits that were set before. + */ + syscimr = ioread32(base + SYSCIMR); + syscimr |= syscier; + pr_debug("%s: syscimr = 0x%08x\n", np->full_name, syscimr); + iowrite32(syscimr, base + SYSCIMR); + + /* + * SYSC needs all interrupt sources enabled to control power. + */ + pr_debug("%s: syscier = 0x%08x\n", np->full_name, syscier); + iowrite32(syscier, base + SYSCIER); + + for (i = 0; i < info->num_areas; i++) { + const struct rcar_sysc_area *area = &info->areas[i]; + struct rcar_sysc_pd *pd; + + pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL); + if (!pd) { + error = -ENOMEM; + goto out_put; + } + + strcpy(pd->name, area->name); + pd->genpd.name = pd->name; + pd->ch.chan_offs = area->chan_offs; + pd->ch.chan_bit = area->chan_bit; + pd->ch.isr_bit = area->isr_bit; + pd->flags = area->flags; + + rcar_sysc_pd_setup(pd); + if (area->parent >= 0) + pm_genpd_add_subdomain(domains->domains[area->parent], + &pd->genpd); + + domains->domains[area->isr_bit] = &pd->genpd; + } + + of_genpd_add_provider_onecell(np, &domains->onecell_data); + +out_put: + of_node_put(np); + return error; +} +early_initcall(rcar_sysc_pd_init); diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h new file mode 100644 index 000000000000..7bb48b4f7334 --- /dev/null +++ b/drivers/soc/renesas/rcar-sysc.h @@ -0,0 +1,53 @@ +/* + * Renesas R-Car System Controller + * + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ +#ifndef __SOC_RENESAS_RCAR_SYSC_H__ +#define __SOC_RENESAS_RCAR_SYSC_H__ + +#include + + +/* + * Power Domain flags + */ +#define PD_CPU BIT(0) /* Area contains main CPU core */ +#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */ +#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */ + +#define PD_BUSY BIT(3) /* Busy, for internal use only */ + +#define PD_CPU_CR PD_CPU /* CPU area has CR (R-Car H1) */ +#define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */ +#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */ + + +/* + * Description of a Power Area + */ + +struct rcar_sysc_area { + const char *name; + u16 chan_offs; /* Offset of PWRSR register for this area */ + u8 chan_bit; /* Bit in PWR* (except for PWRUP in PWRSR) */ + u8 isr_bit; /* Bit in SYSCI*R */ + int parent; /* -1 if none */ + unsigned int flags; /* See PD_* */ +}; + + +/* + * SoC-specific Power Area Description + */ + +struct rcar_sysc_info { + const struct rcar_sysc_area *areas; + unsigned int num_areas; +}; + +#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From 2f024cef5b064d5498fe466dfe9492d46b5b12a4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:39 +0200 Subject: [PATCH 3939/9938] soc: renesas: rcar-sysc: Make rcar_sysc_power_is_off() static As of commit b12ff41658171f53 ("ARM: shmobile: r8a7779: Remove legacy PM Domain remainings"), rcar_sysc_power_is_off() is no longer used from SoC-specific code. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/rcar-sysc.c | 2 +- include/linux/soc/renesas/rcar-sysc.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 95f2b59cbd76..4e760d63f2ab 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -152,7 +152,7 @@ int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch) return rcar_sysc_power(sysc_ch, true); } -bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch) +static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch) { unsigned int st; diff --git a/include/linux/soc/renesas/rcar-sysc.h b/include/linux/soc/renesas/rcar-sysc.h index 96f30c288388..92fc613ab23d 100644 --- a/include/linux/soc/renesas/rcar-sysc.h +++ b/include/linux/soc/renesas/rcar-sysc.h @@ -11,7 +11,6 @@ struct rcar_sysc_ch { int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch); int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch); -bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch); void __iomem *rcar_sysc_init(phys_addr_t base); #endif /* __LINUX_SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From 4252db10559fc3d1efc1e43613254fdd220b014b Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Wed, 20 Apr 2016 13:55:42 -0700 Subject: [PATCH 3940/9938] x86/KASLR: Update description for decompressor worst case size The comment that describes the analysis for the size of the decompressor code only took gzip into account (there are currently 6 other decompressors that could be used). The actual z_extract_offset calculation in code was already handling the correct maximum size, but this documentation hadn't been updated. This updates the documentation, fixes several typos, moves the comment to header.S, updates references, and adds a note at the end of the decompressor include list to remind us about updating the comment in the future. (Instead of moving the comment to mkpiggy.c, where the calculation is currently happening, it is being moved to header.S because the calculations in mkpiggy.c will be removed in favor of header.S calculations in a following patch, and it seemed like overkill to move the giant comment twice, especially when there's already reference to z_extract_offset in header.S.) Signed-off-by: Baoquan He [ Rewrote changelog, cleaned up comment style, moved comments around. ] Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1461185746-8017-2-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/kaslr.c | 2 +- arch/x86/boot/compressed/misc.c | 89 +++----------------------------- arch/x86/boot/header.S | 88 +++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 82 deletions(-) diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 9c29e7885ef0..7d86c5dd8e99 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -155,7 +155,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, /* * Avoid the region that is unsafe to overlap during - * decompression (see calculations at top of misc.c). + * decompression (see calculations in ../header.S). */ unsafe_len = (output_size >> 12) + 32768 + 18; unsafe = (unsigned long)input + input_size - unsafe_len; diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index ad8c01ac2885..e96829bdb6d2 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -14,90 +14,13 @@ #include "misc.h" #include "../string.h" -/* WARNING!! - * This code is compiled with -fPIC and it is relocated dynamically - * at run time, but no relocation processing is performed. - * This means that it is not safe to place pointers in static structures. - */ - /* - * Getting to provable safe in place decompression is hard. - * Worst case behaviours need to be analyzed. - * Background information: - * - * The file layout is: - * magic[2] - * method[1] - * flags[1] - * timestamp[4] - * extraflags[1] - * os[1] - * compressed data blocks[N] - * crc[4] orig_len[4] - * - * resulting in 18 bytes of non compressed data overhead. - * - * Files divided into blocks - * 1 bit (last block flag) - * 2 bits (block type) - * - * 1 block occurs every 32K -1 bytes or when there 50% compression - * has been achieved. The smallest block type encoding is always used. - * - * stored: - * 32 bits length in bytes. - * - * fixed: - * magic fixed tree. - * symbols. - * - * dynamic: - * dynamic tree encoding. - * symbols. - * - * - * The buffer for decompression in place is the length of the - * uncompressed data, plus a small amount extra to keep the algorithm safe. - * The compressed data is placed at the end of the buffer. The output - * pointer is placed at the start of the buffer and the input pointer - * is placed where the compressed data starts. Problems will occur - * when the output pointer overruns the input pointer. - * - * The output pointer can only overrun the input pointer if the input - * pointer is moving faster than the output pointer. A condition only - * triggered by data whose compressed form is larger than the uncompressed - * form. - * - * The worst case at the block level is a growth of the compressed data - * of 5 bytes per 32767 bytes. - * - * The worst case internal to a compressed block is very hard to figure. - * The worst case can at least be boundined by having one bit that represents - * 32764 bytes and then all of the rest of the bytes representing the very - * very last byte. - * - * All of which is enough to compute an amount of extra data that is required - * to be safe. To avoid problems at the block level allocating 5 extra bytes - * per 32767 bytes of data is sufficient. To avoind problems internal to a - * block adding an extra 32767 bytes (the worst case uncompressed block size) - * is sufficient, to ensure that in the worst case the decompressed data for - * block will stop the byte before the compressed data for a block begins. - * To avoid problems with the compressed data's meta information an extra 18 - * bytes are needed. Leading to the formula: - * - * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size. - * - * Adding 8 bytes per 32K is a bit excessive but much easier to calculate. - * Adding 32768 instead of 32767 just makes for round numbers. - * Adding the decompressor_size is necessary as it musht live after all - * of the data as well. Last I measured the decompressor is about 14K. - * 10K of actual data and 4K of bss. - * + * WARNING!! + * This code is compiled with -fPIC and it is relocated dynamically at + * run time, but no relocation processing is performed. This means that + * it is not safe to place pointers in static structures. */ -/* - * gzip declarations - */ #define STATIC static #undef memcpy @@ -148,6 +71,10 @@ static int lines, cols; #ifdef CONFIG_KERNEL_LZ4 #include "../../../../lib/decompress_unlz4.c" #endif +/* + * NOTE: When adding a new decompressor, please update the analysis in + * ../header.S. + */ static void scroll(void) { diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 6236b9ec4b76..fd85b9e4e953 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -440,6 +440,94 @@ setup_data: .quad 0 # 64-bit physical pointer to pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr +# +# Getting to provably safe in-place decompression is hard. Worst case +# behaviours need to be analyzed. Here let's take the decompression of +# a gzip-compressed kernel as example, to illustrate it: +# +# The file layout of gzip compressed kernel is: +# +# magic[2] +# method[1] +# flags[1] +# timestamp[4] +# extraflags[1] +# os[1] +# compressed data blocks[N] +# crc[4] orig_len[4] +# +# ... resulting in +18 bytes overhead of uncompressed data. +# +# (For more information, please refer to RFC 1951 and RFC 1952.) +# +# Files divided into blocks +# 1 bit (last block flag) +# 2 bits (block type) +# +# 1 block occurs every 32K -1 bytes or when there 50% compression +# has been achieved. The smallest block type encoding is always used. +# +# stored: +# 32 bits length in bytes. +# +# fixed: +# magic fixed tree. +# symbols. +# +# dynamic: +# dynamic tree encoding. +# symbols. +# +# +# The buffer for decompression in place is the length of the uncompressed +# data, plus a small amount extra to keep the algorithm safe. The +# compressed data is placed at the end of the buffer. The output pointer +# is placed at the start of the buffer and the input pointer is placed +# where the compressed data starts. Problems will occur when the output +# pointer overruns the input pointer. +# +# The output pointer can only overrun the input pointer if the input +# pointer is moving faster than the output pointer. A condition only +# triggered by data whose compressed form is larger than the uncompressed +# form. +# +# The worst case at the block level is a growth of the compressed data +# of 5 bytes per 32767 bytes. +# +# The worst case internal to a compressed block is very hard to figure. +# The worst case can at least be bounded by having one bit that represents +# 32764 bytes and then all of the rest of the bytes representing the very +# very last byte. +# +# All of which is enough to compute an amount of extra data that is required +# to be safe. To avoid problems at the block level allocating 5 extra bytes +# per 32767 bytes of data is sufficient. To avoid problems internal to a +# block adding an extra 32767 bytes (the worst case uncompressed block size) +# is sufficient, to ensure that in the worst case the decompressed data for +# block will stop the byte before the compressed data for a block begins. +# To avoid problems with the compressed data's meta information an extra 18 +# bytes are needed. Leading to the formula: +# +# extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size +# +# Adding 8 bytes per 32K is a bit excessive but much easier to calculate. +# Adding 32768 instead of 32767 just makes for round numbers. +# Adding the decompressor_size is necessary as it musht live after all +# of the data as well. Last I measured the decompressor is about 14K. +# 10K of actual data and 4K of bss. +# +# Above analysis is for decompressing gzip compressed kernel only. Up to +# now 6 different decompressor are supported all together. And among them +# xz stores data in chunks and has maximum chunk of 64K. Hence safety +# margin should be updated to cover all decompressors so that we don't +# need to deal with each of them separately. Please check +# the description in lib/decompressor_xxx.c for specific information. +# +# extra_bytes = (uncompressed_size >> 12) + 65536 + 128 +# +# Note that this calculation, which results in z_extract_offset (below), +# is currently generated in compressed/mkpiggy.c + #define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset) #define VO_INIT_SIZE (VO__end - VO__text) #if ZO_INIT_SIZE > VO_INIT_SIZE -- GitLab From e8581e3d67788b6b29d055fa42c6cb5b258fee64 Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Wed, 20 Apr 2016 13:55:43 -0700 Subject: [PATCH 3941/9938] x86/KASLR: Drop CONFIG_RANDOMIZE_BASE_MAX_OFFSET Currently CONFIG_RANDOMIZE_BASE_MAX_OFFSET is used to limit the maximum offset for kernel randomization. This limit doesn't need to be a CONFIG since it is tied completely to KERNEL_IMAGE_SIZE, and will make no sense once physical and virtual offsets are randomized separately. This patch removes CONFIG_RANDOMIZE_BASE_MAX_OFFSET and consolidates the Kconfig help text. [kees: rewrote changelog, dropped KERNEL_IMAGE_SIZE_DEFAULT, rewrote help] Signed-off-by: Baoquan He Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1461185746-8017-3-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 72 +++++++++++----------------- arch/x86/boot/compressed/kaslr.c | 12 ++--- arch/x86/include/asm/page_64_types.h | 8 ++-- arch/x86/mm/init_32.c | 3 -- 4 files changed, 36 insertions(+), 59 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2dc18605831f..5892d549596d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1932,54 +1932,38 @@ config RELOCATABLE (CONFIG_PHYSICAL_START) is used as the minimum location. config RANDOMIZE_BASE - bool "Randomize the address of the kernel image" + bool "Randomize the address of the kernel image (KASLR)" depends on RELOCATABLE default n ---help--- - Randomizes the physical and virtual address at which the - kernel image is decompressed, as a security feature that - deters exploit attempts relying on knowledge of the location - of kernel internals. + In support of Kernel Address Space Layout Randomization (KASLR), + this randomizes the physical address at which the kernel image + is decompressed and the virtual address where the kernel + image is mapped, as a security feature that deters exploit + attempts relying on knowledge of the location of kernel + code internals. + + The kernel physical and virtual address can be randomized + from 16MB up to 1GB on 64-bit and 512MB on 32-bit. (Note that + using RANDOMIZE_BASE reduces the memory space available to + kernel modules from 1.5GB to 1GB.) + + Entropy is generated using the RDRAND instruction if it is + supported. If RDTSC is supported, its value is mixed into + the entropy pool as well. If neither RDRAND nor RDTSC are + supported, then entropy is read from the i8254 timer. + + Since the kernel is built using 2GB addressing, and + PHYSICAL_ALIGN must be at a minimum of 2MB, only 10 bits of + entropy is theoretically possible. Currently, with the + default value for PHYSICAL_ALIGN and due to page table + layouts, 64-bit uses 9 bits of entropy and 32-bit uses 8 bits. + + If CONFIG_HIBERNATE is also enabled, KASLR is disabled at boot + time. To enable it, boot with "kaslr" on the kernel command + line (which will also disable hibernation). - Entropy is generated using the RDRAND instruction if it is - supported. If RDTSC is supported, it is used as well. If - neither RDRAND nor RDTSC are supported, then randomness is - read from the i8254 timer. - - The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET, - and aligned according to PHYSICAL_ALIGN. Since the kernel is - built using 2GiB addressing, and PHYSICAL_ALGIN must be at a - minimum of 2MiB, only 10 bits of entropy is theoretically - possible. At best, due to page table layouts, 64-bit can use - 9 bits of entropy and 32-bit uses 8 bits. - - If unsure, say N. - -config RANDOMIZE_BASE_MAX_OFFSET - hex "Maximum kASLR offset allowed" if EXPERT - depends on RANDOMIZE_BASE - range 0x0 0x20000000 if X86_32 - default "0x20000000" if X86_32 - range 0x0 0x40000000 if X86_64 - default "0x40000000" if X86_64 - ---help--- - The lesser of RANDOMIZE_BASE_MAX_OFFSET and available physical - memory is used to determine the maximal offset in bytes that will - be applied to the kernel when kernel Address Space Layout - Randomization (kASLR) is active. This must be a multiple of - PHYSICAL_ALIGN. - - On 32-bit this is limited to 512MiB by page table layouts. The - default is 512MiB. - - On 64-bit this is limited by how the kernel fixmap page table is - positioned, so this cannot be larger than 1GiB currently. Without - RANDOMIZE_BASE, there is a 512MiB to 1.5GiB split between kernel - and modules. When RANDOMIZE_BASE_MAX_OFFSET is above 512MiB, the - modules area will shrink to compensate, up to the current maximum - 1GiB to 1GiB split. The default is 1GiB. - - If unsure, leave at the default value. + If unsure, say N. # Relocation on x86 needs some additional build support config X86_NEED_RELOCS diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 7d86c5dd8e99..3ad71a0afa24 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -217,15 +217,13 @@ static bool mem_avoid_overlap(struct mem_vector *img) return false; } -static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / - CONFIG_PHYSICAL_ALIGN]; +static unsigned long slots[KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN]; static unsigned long slot_max; static void slots_append(unsigned long addr) { /* Overflowing the slots list should be impossible. */ - if (slot_max >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET / - CONFIG_PHYSICAL_ALIGN) + if (slot_max >= KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN) return; slots[slot_max++] = addr; @@ -251,7 +249,7 @@ static void process_e820_entry(struct e820entry *entry, return; /* Ignore entries entirely above our maximum. */ - if (entry->addr >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET) + if (entry->addr >= KERNEL_IMAGE_SIZE) return; /* Ignore entries entirely below our minimum. */ @@ -276,8 +274,8 @@ static void process_e820_entry(struct e820entry *entry, region.size -= region.start - entry->addr; /* Reduce maximum size to fit end of image within maximum limit. */ - if (region.start + region.size > CONFIG_RANDOMIZE_BASE_MAX_OFFSET) - region.size = CONFIG_RANDOMIZE_BASE_MAX_OFFSET - region.start; + if (region.start + region.size > KERNEL_IMAGE_SIZE) + region.size = KERNEL_IMAGE_SIZE - region.start; /* Walk each aligned slot and check for avoided areas. */ for (img.start = region.start, img.size = image_size ; diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h index 4928cf0d5af0..d5c2f8b40faa 100644 --- a/arch/x86/include/asm/page_64_types.h +++ b/arch/x86/include/asm/page_64_types.h @@ -47,12 +47,10 @@ * are fully set up. If kernel ASLR is configured, it can extend the * kernel page table mapping, reducing the size of the modules area. */ -#define KERNEL_IMAGE_SIZE_DEFAULT (512 * 1024 * 1024) -#if defined(CONFIG_RANDOMIZE_BASE) && \ - CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE_DEFAULT -#define KERNEL_IMAGE_SIZE CONFIG_RANDOMIZE_BASE_MAX_OFFSET +#if defined(CONFIG_RANDOMIZE_BASE) +#define KERNEL_IMAGE_SIZE (1024 * 1024 * 1024) #else -#define KERNEL_IMAGE_SIZE KERNEL_IMAGE_SIZE_DEFAULT +#define KERNEL_IMAGE_SIZE (512 * 1024 * 1024) #endif #endif /* _ASM_X86_PAGE_64_DEFS_H */ diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index bd7a9b9e2e14..f2ee42d61894 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -804,9 +804,6 @@ void __init mem_init(void) BUILD_BUG_ON(VMALLOC_START >= VMALLOC_END); #undef high_memory #undef __FIXADDR_TOP -#ifdef CONFIG_RANDOMIZE_BASE - BUILD_BUG_ON(CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE); -#endif #ifdef CONFIG_HIGHMEM BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE > FIXADDR_START); -- GitLab From 1f208de37d10bb9067f3b061d281363be0cd1805 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 13:55:44 -0700 Subject: [PATCH 3942/9938] x86/boot: Clean up things used by decompressors This rearranges the pieces needed to include the decompressor code in misc.c. It wasn't obvious why things were there, so a comment was added and definitions consolidated. Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1461185746-8017-4-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/misc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index e96829bdb6d2..0381e250a785 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -21,19 +21,19 @@ * it is not safe to place pointers in static structures. */ +/* Macros used by the included decompressor code below. */ #define STATIC static -#undef memcpy - /* - * Use a normal definition of memset() from string.c. There are already + * Use normal definitions of mem*() from string.c. There are already * included header files which expect a definition of memset() and by * the time we define memset macro, it is too late. */ +#undef memcpy #undef memset #define memzero(s, n) memset((s), 0, (n)) - +/* Functions used by the included decompressor code below. */ static void error(char *m); /* -- GitLab From bf0118dbba9542ceb5d33d4a86830a6c88b0bbf6 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 13:55:45 -0700 Subject: [PATCH 3943/9938] x86/boot: Make memcpy() handle overlaps Two uses of memcpy() (screen scrolling and ELF parsing) were handling overlapping memory areas. While there were no explicitly noticed bugs here (yet), it is best to fix this so that the copying will always be safe. Instead of making a new memmove() function that might collide with other memmove() definitions in the decompressors, this just makes the compressed boot code's copy of memcpy() overlap-safe. Suggested-by: Lasse Collin Reported-by: Yinghai Lu Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1461185746-8017-5-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/misc.c | 4 +--- arch/x86/boot/compressed/string.c | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 0381e250a785..eacc855ae08e 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -301,9 +301,7 @@ static void parse_elf(void *output) #else dest = (void *)(phdr->p_paddr); #endif - memcpy(dest, - output + phdr->p_offset, - phdr->p_filesz); + memcpy(dest, output + phdr->p_offset, phdr->p_filesz); break; default: /* Ignore other PT_* */ break; } diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index 00e788be1db9..1e10e40f49dd 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -1,7 +1,7 @@ #include "../string.c" #ifdef CONFIG_X86_32 -void *memcpy(void *dest, const void *src, size_t n) +void *__memcpy(void *dest, const void *src, size_t n) { int d0, d1, d2; asm volatile( @@ -15,7 +15,7 @@ void *memcpy(void *dest, const void *src, size_t n) return dest; } #else -void *memcpy(void *dest, const void *src, size_t n) +void *__memcpy(void *dest, const void *src, size_t n) { long d0, d1, d2; asm volatile( @@ -39,3 +39,21 @@ void *memset(void *s, int c, size_t n) ss[i] = c; return s; } + +/* + * This memcpy is overlap safe (i.e. it is memmove without conflicting + * with other definitions of memmove from the various decompressors. + */ +void *memcpy(void *dest, const void *src, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + + if (d <= s || d - s >= n) + return __memcpy(dest, src, n); + + while (n-- > 0) + d[n] = s[n]; + + return dest; +} -- GitLab From 0f8ede1b8c4cb845c53072d7e49d71ca24a61ced Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Apr 2016 13:55:46 -0700 Subject: [PATCH 3944/9938] x86/KASLR: Warn when KASLR is disabled If KASLR is built in but not available at run-time (either due to the current conflict with hibernation, command-line request, or e820 parsing failures), announce the state explicitly. To support this, a new "warn" function is created, based on the existing "error" function. Suggested-by: Ingo Molnar Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Dmitry Vyukov Cc: H. Peter Anvin Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1461185746-8017-6-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/kaslr.c | 6 +++--- arch/x86/boot/compressed/misc.c | 12 +++++++++--- arch/x86/boot/compressed/misc.h | 1 + 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 3ad71a0afa24..8741a6d83bfe 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -314,12 +314,12 @@ unsigned char *choose_random_location(unsigned char *input, #ifdef CONFIG_HIBERNATION if (!cmdline_find_option_bool("kaslr")) { - debug_putstr("KASLR disabled by default...\n"); + warn("KASLR disabled: 'kaslr' not on cmdline (hibernation selected)."); goto out; } #else if (cmdline_find_option_bool("nokaslr")) { - debug_putstr("KASLR disabled by cmdline...\n"); + warn("KASLR disabled: 'nokaslr' on cmdline."); goto out; } #endif @@ -333,7 +333,7 @@ unsigned char *choose_random_location(unsigned char *input, /* Walk e820 and find a random address. */ random_addr = find_random_addr(choice, output_size); if (!random_addr) { - debug_putstr("KASLR could not find suitable E820 region...\n"); + warn("KASLR disabled: could not find suitable E820 region!"); goto out; } diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index eacc855ae08e..c57d785ff955 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -166,11 +166,17 @@ void __puthex(unsigned long value) } } -static void error(char *x) +void warn(char *m) { error_putstr("\n\n"); - error_putstr(x); - error_putstr("\n\n -- System halted"); + error_putstr(m); + error_putstr("\n\n"); +} + +static void error(char *m) +{ + warn(m); + error_putstr(" -- System halted"); while (1) asm("hlt"); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 9887e0d4aaeb..e75f6cf9caaf 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -35,6 +35,7 @@ extern memptr free_mem_end_ptr; extern struct boot_params *boot_params; void __putstr(const char *s); void __puthex(unsigned long value); +void warn(char *m); #define error_putstr(__x) __putstr(__x) #define error_puthex(__x) __puthex(__x) -- GitLab From 18c78a96239749fc4aaee84ca1eb5a8e81f2601d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:31 -0700 Subject: [PATCH 3945/9938] x86/boot: Enumerate documentation for the x86 hardware_subarch Although hardware_subarch has been in place since the x86 boot protocol 2.07 it hasn't been used much. Enumerate current possible values to avoid misuses and help with semantics later at boot time should this be used further. These enums should only ever be used by architecture x86 code, and all that code should be well contained and compartamentalized, clarify that as well. Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-2-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/uapi/asm/bootparam.h | 41 ++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index 329254373479..c18ce67495fa 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -157,7 +157,46 @@ struct boot_params { __u8 _pad9[276]; /* 0xeec */ } __attribute__((packed)); -enum { +/** + * enum x86_hardware_subarch - x86 hardware subarchitecture + * + * The x86 hardware_subarch and hardware_subarch_data were added as of the x86 + * boot protocol 2.07 to help distinguish and support custom x86 boot + * sequences. This enum represents accepted values for the x86 + * hardware_subarch. Custom x86 boot sequences (not X86_SUBARCH_PC) do not + * have or simply *cannot* make use of natural stubs like BIOS or EFI, the + * hardware_subarch can be used on the Linux entry path to revector to a + * subarchitecture stub when needed. This subarchitecture stub can be used to + * set up Linux boot parameters or for special care to account for nonstandard + * handling of page tables. + * + * These enums should only ever be used by x86 code, and the code that uses + * it should be well contained and compartamentalized. + * + * KVM and Xen HVM do not have a subarch as these are expected to follow + * standard x86 boot entries. If there is a genuine need for "hypervisor" type + * that should be considered separately in the future. Future guest types + * should seriously consider working with standard x86 boot stubs such as + * the BIOS or EFI boot stubs. + * + * WARNING: this enum is only used for legacy hacks, for platform features that + * are not easily enumerated or discoverable. You should not ever use + * this for new features. + * + * @X86_SUBARCH_PC: Should be used if the hardware is enumerable using standard + * PC mechanisms (PCI, ACPI) and doesn't need a special boot flow. + * @X86_SUBARCH_LGUEST: Used for x86 hypervisor demo, lguest + * @X86_SUBARCH_XEN: Used for Xen guest types which follow the PV boot path, + * which start at asm startup_xen() entry point and later jump to the C + * xen_start_kernel() entry point. Both domU and dom0 type of guests are + * currently supportd through this PV boot path. + * @X86_SUBARCH_INTEL_MID: Used for Intel MID (Mobile Internet Device) platform + * systems which do not have the PCI legacy interfaces. + * @X86_SUBARCH_CE4100: Used for Intel CE media processor (CE4100) SoC for + * for settop boxes and media devices, the use of a subarch for CE4100 + * is more of a hack... + */ +enum x86_hardware_subarch { X86_SUBARCH_PC = 0, X86_SUBARCH_LGUEST, X86_SUBARCH_XEN, -- GitLab From ea1794812410e92c537c839bedeb2d2b2f87c80d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:32 -0700 Subject: [PATCH 3946/9938] x86/xen: Use X86_SUBARCH_XEN for PV guest boots The use of subarch should have no current effect on Xen PV guests, as such this should have no current functional effects. Signed-off-by: Luis R. Rodriguez Reviewed-by: David Vrabel Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-3-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 880862c7d9dd..61f4d9f67f60 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1670,6 +1670,7 @@ asmlinkage __visible void __init xen_start_kernel(void) boot_params.hdr.ramdisk_image = initrd_start; boot_params.hdr.ramdisk_size = xen_start_info->mod_len; boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line); + boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN; if (!xen_initial_domain()) { add_preferred_console("xenboot", 0, NULL); -- GitLab From 907bb655797427cc6498045d6977e77f8363fff7 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:33 -0700 Subject: [PATCH 3947/9938] tools/lguest: Make lguest launcher use X86_SUBARCH_LGUEST explicitly Be explicit and make use of X86_SUBARCH_LGUEST directly. Signed-off-by: Luis R. Rodriguez Acked-by: Rusty Russell Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-4-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- tools/lguest/lguest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 80159e6811c2..ff0aa580c6e1 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -3351,8 +3351,8 @@ int main(int argc, char *argv[]) /* Boot protocol version: 2.07 supports the fields for lguest. */ boot->hdr.version = 0x207; - /* The hardware_subarch value of "1" tells the Guest it's an lguest. */ - boot->hdr.hardware_subarch = 1; + /* X86_SUBARCH_LGUEST tells the Guest it's an lguest. */ + boot->hdr.hardware_subarch = X86_SUBARCH_LGUEST; /* Tell the entry path not to try to reload segment registers. */ boot->hdr.loadflags |= KEEP_SEGMENTS; -- GitLab From 8d152e7a5c7537b18b4e9e0eb96f549b016636dc Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:34 -0700 Subject: [PATCH 3948/9938] x86/rtc: Replace paravirt rtc check with platform legacy quirk We have 4 types of x86 platforms that disable RTC: * Intel MID * Lguest - uses paravirt * Xen dom-U - uses paravirt * x86 on legacy systems annotated with an ACPI legacy flag We can consolidate all of these into a platform specific legacy quirk set early in boot through i386_start_kernel() and through x86_64_start_reservations(). This deals with the RTC quirks which we can rely on through the hardware subarch, the ACPI check can be dealt with separately. For Xen things are bit more complex given that the @X86_SUBARCH_XEN x86_hardware_subarch is shared on for Xen which uses the PV path for both domU and dom0. Since the semantics for differentiating between the two are Xen specific we provide a platform helper to help override default legacy features -- x86_platform.set_legacy_features(). Use of this helper is highly discouraged, its only purpose should be to account for the lack of semantics available within your given x86_hardware_subarch. As per 0-day, this bumps the vmlinux size using i386-tinyconfig as follows: TOTAL TEXT init.text x86_early_init_platform_quirks() +70 +62 +62 +43 Only 8 bytes overhead total, as the main increase in size is all removed via __init. Suggested-by: Ingo Molnar Signed-off-by: Luis R. Rodriguez Reviewed-by: Juergen Gross Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-5-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/Makefile | 1 + arch/x86/include/asm/paravirt.h | 6 ------ arch/x86/include/asm/paravirt_types.h | 5 ----- arch/x86/include/asm/processor.h | 1 - arch/x86/include/asm/x86_init.h | 21 +++++++++++++++++++++ arch/x86/kernel/Makefile | 6 +++++- arch/x86/kernel/head32.c | 2 ++ arch/x86/kernel/head64.c | 1 + arch/x86/kernel/platform-quirks.c | 21 +++++++++++++++++++++ arch/x86/kernel/rtc.c | 7 ++----- arch/x86/lguest/boot.c | 1 - arch/x86/xen/enlighten.c | 10 +++++++--- 12 files changed, 60 insertions(+), 22 deletions(-) create mode 100644 arch/x86/kernel/platform-quirks.c diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 4086abca0b32..f9ed8a7ce2b6 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -209,6 +209,7 @@ endif head-y := arch/x86/kernel/head_$(BITS).o head-y += arch/x86/kernel/head$(BITS).o head-y += arch/x86/kernel/head.o +head-y += arch/x86/kernel/platform-quirks.o libs-y += arch/x86/lib/ diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 601f1b8f9961..6c7a4a192032 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -20,12 +20,6 @@ static inline int paravirt_enabled(void) return pv_info.paravirt_enabled; } -static inline int paravirt_has_feature(unsigned int feature) -{ - WARN_ON_ONCE(!pv_info.paravirt_enabled); - return (pv_info.features & feature); -} - static inline void load_sp0(struct tss_struct *tss, struct thread_struct *thread) { diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index e8c2326478c8..6acc1b26cf40 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -70,14 +70,9 @@ struct pv_info { #endif int paravirt_enabled; - unsigned int features; /* valid only if paravirt_enabled is set */ const char *name; }; -#define paravirt_has(x) paravirt_has_feature(PV_SUPPORTED_##x) -/* Supported features */ -#define PV_SUPPORTED_RTC (1<<0) - struct pv_init_ops { /* * Patch may replace one of the defined code sequences with diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 9264476f3d57..0c70c7daa6b8 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -474,7 +474,6 @@ static inline unsigned long current_top_of_stack(void) #else #define __cpuid native_cpuid #define paravirt_enabled() 0 -#define paravirt_has(x) 0 static inline void load_sp0(struct tss_struct *tss, struct thread_struct *thread) diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 1ae89a2721d6..8bb8c1a4615a 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -141,6 +141,15 @@ struct x86_cpuinit_ops { struct timespec; +/** + * struct x86_legacy_features - legacy x86 features + * + * @rtc: this device has a CMOS real-time clock present + */ +struct x86_legacy_features { + int rtc; +}; + /** * struct x86_platform_ops - platform specific runtime functions * @calibrate_tsc: calibrate TSC @@ -152,6 +161,14 @@ struct timespec; * @save_sched_clock_state: save state for sched_clock() on suspend * @restore_sched_clock_state: restore state for sched_clock() on resume * @apic_post_init: adjust apic if neeeded + * @legacy: legacy features + * @set_legacy_features: override legacy features. Use of this callback + * is highly discouraged. You should only need + * this if your hardware platform requires further + * custom fine tuning far beyong what may be + * possible in x86_early_init_platform_quirks() by + * only using the current x86_hardware_subarch + * semantics. */ struct x86_platform_ops { unsigned long (*calibrate_tsc)(void); @@ -165,6 +182,8 @@ struct x86_platform_ops { void (*save_sched_clock_state)(void); void (*restore_sched_clock_state)(void); void (*apic_post_init)(void); + struct x86_legacy_features legacy; + void (*set_legacy_features)(void); }; struct pci_dev; @@ -186,6 +205,8 @@ extern struct x86_cpuinit_ops x86_cpuinit; extern struct x86_platform_ops x86_platform; extern struct x86_msi_ops x86_msi; extern struct x86_io_apic_ops x86_io_apic_ops; + +extern void x86_early_init_platform_quirks(void); extern void x86_init_noop(void); extern void x86_init_uint_noop(unsigned int unused); diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 616ebd22ef9a..b81b22ee10ba 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -2,7 +2,11 @@ # Makefile for the linux kernel. # -extra-y := head_$(BITS).o head$(BITS).o head.o vmlinux.lds +extra-y := head_$(BITS).o +extra-y += head$(BITS).o +extra-y += head.o +extra-y += platform-quirks.o +extra-y += vmlinux.lds CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE) diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 2911ef3a9f1c..d784bb547a9d 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -34,6 +34,8 @@ asmlinkage __visible void __init i386_start_kernel(void) cr4_init_shadow(); sanitize_boot_params(&boot_params); + x86_early_init_platform_quirks(); + /* Call the subarch specific early setup function */ switch (boot_params.hdr.hardware_subarch) { case X86_SUBARCH_INTEL_MID: diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 1f4422d5c8d0..b72fb0b71dd1 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -182,6 +182,7 @@ void __init x86_64_start_reservations(char *real_mode_data) if (!boot_params.hdr.version) copy_bootdata(__va(real_mode_data)); + x86_early_init_platform_quirks(); reserve_ebda_region(); switch (boot_params.hdr.hardware_subarch) { diff --git a/arch/x86/kernel/platform-quirks.c b/arch/x86/kernel/platform-quirks.c new file mode 100644 index 000000000000..021a5f973ce3 --- /dev/null +++ b/arch/x86/kernel/platform-quirks.c @@ -0,0 +1,21 @@ +#include +#include + +#include +#include + +void __init x86_early_init_platform_quirks(void) +{ + x86_platform.legacy.rtc = 1; + + switch (boot_params.hdr.hardware_subarch) { + case X86_SUBARCH_XEN: + case X86_SUBARCH_LGUEST: + case X86_SUBARCH_INTEL_MID: + x86_platform.legacy.rtc = 0; + break; + } + + if (x86_platform.set_legacy_features) + x86_platform.set_legacy_features(); +} diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 4af8d063fb36..62c48da3889d 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_X86_32 /* @@ -188,10 +189,6 @@ static __init int add_rtc_cmos(void) if (of_have_populated_dt()) return 0; - /* Intel MID platforms don't have ioport rtc */ - if (intel_mid_identify_cpu()) - return -ENODEV; - #ifdef CONFIG_ACPI if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) { /* This warning can likely go away again in a year or two. */ @@ -200,7 +197,7 @@ static __init int add_rtc_cmos(void) } #endif - if (paravirt_enabled() && !paravirt_has(RTC)) + if (!x86_platform.legacy.rtc) return -ENODEV; platform_device_register(&rtc_device); diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index fd57d3ae7e16..f5497ee5fd2f 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -1414,7 +1414,6 @@ __init void lguest_init(void) pv_info.kernel_rpl = 1; /* Everyone except Xen runs with this set. */ pv_info.shared_kernel_pmd = 1; - pv_info.features = 0; /* * We set up all the lguest overrides for sensitive operations. These diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 61f4d9f67f60..752029d571bf 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1193,7 +1193,6 @@ static const struct pv_info xen_info __initconst = { #ifdef CONFIG_X86_64 .extra_user_64bit_cs = FLAT_USER_CS64, #endif - .features = 0, .name = "Xen", }; @@ -1506,6 +1505,11 @@ static void __init xen_pvh_early_guest_init(void) } #endif /* CONFIG_XEN_PVH */ +static void __init xen_dom0_set_legacy_features(void) +{ + x86_platform.legacy.rtc = 1; +} + /* First C function to be called on Xen boot */ asmlinkage __visible void __init xen_start_kernel(void) { @@ -1527,8 +1531,6 @@ asmlinkage __visible void __init xen_start_kernel(void) /* Install Xen paravirt ops */ pv_info = xen_info; - if (xen_initial_domain()) - pv_info.features |= PV_SUPPORTED_RTC; pv_init_ops = xen_init_ops; if (!xen_pvh_domain()) { pv_cpu_ops = xen_cpu_ops; @@ -1688,6 +1690,8 @@ asmlinkage __visible void __init xen_start_kernel(void) .u.firmware_info.type = XEN_FW_KBD_SHIFT_FLAGS, }; + x86_platform.set_legacy_features = + xen_dom0_set_legacy_features; xen_init_vga(info, xen_start_info->console.dom0.info_size); xen_start_info->console.domU.mfn = 0; xen_start_info->console.domU.evtchn = 0; -- GitLab From 088a8ef8207f19aadbade0971af21ad89fdc3815 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:35 -0700 Subject: [PATCH 3949/9938] x86/ACPI: Move ACPI_FADT_NO_CMOS_RTC check to ACPI boot code This moves the ACPI specific check into the ACPI boot code, it also takes advantage of the x86_platform.legacy.rtc which is checked for already on the RTC initialization code. This lets us remove the nasty #ifdefery and consolidate the checks to use only one toggle to disable the RTC init code. The works as RTC is initialized by device_initcall(add_rtc_cmos), this will run late in boot on start_kernel() during rest_init(), acpi_parse_fadt() gets called earlier during setup_arch(). Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-6-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 4 ++++ arch/x86/kernel/rtc.c | 8 -------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8c2f1ef6ca23..8c9c2bdba092 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -913,6 +913,10 @@ late_initcall(hpet_insert_resource); static int __init acpi_parse_fadt(struct acpi_table_header *table) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) { + pr_debug("ACPI: not registering RTC platform device\n"); + x86_platform.legacy.rtc = 0; + } #ifdef CONFIG_X86_PM_TIMER /* detect the location of the ACPI PM Timer */ diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 62c48da3889d..ff4f4180fefd 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -189,14 +189,6 @@ static __init int add_rtc_cmos(void) if (of_have_populated_dt()) return 0; -#ifdef CONFIG_ACPI - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) { - /* This warning can likely go away again in a year or two. */ - pr_info("ACPI: not registering RTC platform device\n"); - return -ENODEV; - } -#endif - if (!x86_platform.legacy.rtc) return -ENODEV; -- GitLab From 1330e3bc544a1951d81b7f3c7d4cecf77d906f67 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:36 -0700 Subject: [PATCH 3950/9938] x86/init: Use a platform legacy quirk for EBDA This replaces the paravirt_enabled() check with a proper x86 legacy platform quirk. As per 0-day, this bumps the vmlinux size using i386-tinyconfig as follows: TOTAL TEXT init.text x86_early_init_platform_quirks() +39 +35 +35 +25 That's a 4 byte total overhead, the rest is all cleared out upon init as its all __init text. v2: document 0-day vmlinux size impact Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-7-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/x86_init.h | 3 +++ arch/x86/kernel/head.c | 2 +- arch/x86/kernel/platform-quirks.c | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 8bb8c1a4615a..89d9d57e145d 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -145,9 +145,12 @@ struct timespec; * struct x86_legacy_features - legacy x86 features * * @rtc: this device has a CMOS real-time clock present + * @ebda_search: it's safe to search for the EBDA signature in the hardware's + * low RAM */ struct x86_legacy_features { int rtc; + int ebda_search; }; /** diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index 992f442ca155..afe65dffee80 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c @@ -38,7 +38,7 @@ void __init reserve_ebda_region(void) * that the paravirt case can handle memory setup * correctly, without our help. */ - if (paravirt_enabled()) + if (!x86_platform.legacy.ebda_search) return; /* end of low (conventional) memory */ diff --git a/arch/x86/kernel/platform-quirks.c b/arch/x86/kernel/platform-quirks.c index 021a5f973ce3..01b159781d96 100644 --- a/arch/x86/kernel/platform-quirks.c +++ b/arch/x86/kernel/platform-quirks.c @@ -7,8 +7,12 @@ void __init x86_early_init_platform_quirks(void) { x86_platform.legacy.rtc = 1; + x86_platform.legacy.ebda_search = 0; switch (boot_params.hdr.hardware_subarch) { + case X86_SUBARCH_PC: + x86_platform.legacy.ebda_search = 1; + break; case X86_SUBARCH_XEN: case X86_SUBARCH_LGUEST: case X86_SUBARCH_INTEL_MID: -- GitLab From 46504590321dc62a11065f8d00e1b12037c37018 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:37 -0700 Subject: [PATCH 3951/9938] tools/lguest: Force disable tboot and APM The paravirt_enabled() check is going away, the area tossed to the kernel on lguest is not zeroed out, so ensure lguest force disables tboot and APM just in case the kernel file being read might have this set for whatever reason. Signed-off-by: Luis R. Rodriguez Acked-by: Rusty Russell Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-8-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- tools/lguest/lguest.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index ff0aa580c6e1..d9836c5eb694 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -3357,6 +3357,12 @@ int main(int argc, char *argv[]) /* Tell the entry path not to try to reload segment registers. */ boot->hdr.loadflags |= KEEP_SEGMENTS; + /* We don't support tboot: */ + boot->tboot_addr = 0; + + /* Ensure this is 0 to prevent APM from loading: */ + boot->apm_bios_info.version = 0; + /* We tell the kernel to initialize the Guest. */ tell_kernel(start); -- GitLab From 8bc55f805697ec2a69c6a576fac8ee36ea9772bb Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:38 -0700 Subject: [PATCH 3952/9938] x86/apm32: Remove paravirt_enabled() use There is already a check for apm_info.bios == 0, the apm_info.bios is set from the boot_params.apm_bios_info. Both Xen and lguest, which are also the only ones that set paravirt_enabled to true, never set the apm_bios.info. The Xen folks are sure force disable to 0 is not needed because apm_info lives in .bss, we recently forced disabled this on lguest, and on the Xen side just to be sure Boris zeroed out the .bss for PV guests through commit 04b6b4a56884327c1648 ("xen/x86: Zero out .bss for PV guests"). With this care taken into consideration the paravirt_enabled() check is simply not needed anymore. Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-9-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/apm_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 9307f182fe30..c7364bd633e1 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -2267,7 +2267,7 @@ static int __init apm_init(void) dmi_check_system(apm_dmi_table); - if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) { + if (apm_info.bios.version == 0 || machine_is_olpc()) { printk(KERN_INFO "apm: BIOS not found.\n"); return -ENODEV; } -- GitLab From 44ecf0ef907fe45510566d308d670aa5823a4dd5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:39 -0700 Subject: [PATCH 3953/9938] x86/tboot: Remove paravirt_enabled() use There is already a check for boot_params.tboot_addr prior to paravirt_enabled(). Both Xen and lguest, which are also the only ones that set paravirt_enabled to true, never set the boot_params.tboot_addr. The Xen folks are sure a force disable to 0 is not needed, we recently forced disabled this on lguest. With this in place this check is no longer needed. Xen folks are sure force disable to 0 is not needed because apm_info lives in .bss, we recently forced disabled this on lguest, and on the Xen side just to be sure Boris zeroed out the .bss for PV guests through commit 04b6b4a56884327c1648 ("xen/x86: Zero out .bss for PV guests"). With this care taken into consideration the paravirt_enabled() check is simply not needed anymore. Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-10-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/tboot.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index e72a07f20b05..9b0185fbe3eb 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -74,12 +74,6 @@ void __init tboot_probe(void) return; } - /* only a natively booted kernel should be using TXT */ - if (paravirt_enabled()) { - pr_warning("non-0 tboot_addr but pv_ops is enabled\n"); - return; - } - /* Map and check for tboot UUID. */ set_fixmap(FIX_TBOOT_BASE, boot_params.tboot_addr); tboot = (struct tboot *)fix_to_virt(FIX_TBOOT_BASE); -- GitLab From fa392794ed8329379f3f637da7c3c2f078309a77 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:40 -0700 Subject: [PATCH 3954/9938] x86/cpu/intel: Remove not needed paravirt_enabled() use for F00F work around The X86_BUG_F00F work around is responsible for fixing up the error generated on attempted F00F exploitation from an OOPS to a SIGILL. There is no reason why this code should not be allowed to run on PV guest on a F00F-affected CPU -- it would simply never trigger. The pv_enabled() check was there only to avoid printing the f00f workaround, so removing the check is purely a cosmetic change. Suggested-by: Andy Lutomirski Signed-off-by: Luis R. Rodriguez Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-11-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 1f7fdb91a818..016b3d9ffa7d 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -233,7 +233,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c) * The Quark is also family 5, but does not have the same bug. */ clear_cpu_bug(c, X86_BUG_F00F); - if (!paravirt_enabled() && c->x86 == 5 && c->x86_model < 9) { + if (c->x86 == 5 && c->x86_model < 9) { static int f00f_workaround_enabled; set_cpu_bug(c, X86_BUG_F00F); -- GitLab From 80dfd83dfab6e49a31ab8fc484a801aef1c567bd Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:41 -0700 Subject: [PATCH 3955/9938] x86, drivers/pnpbios: Replace paravirt_enabled() check with legacy device check Since we are removing paravirt_enabled() replace it with a logical equivalent. Even though PNPBIOS is x86 specific we add an arch-specific type call, which can be implemented by any architecture to show how other legacy attribute devices can later be also checked for with other ACPI legacy attribute flags. This implicates the first ACPI 5.2.9.3 IA-PC Boot Architecture ACPI_FADT_LEGACY_DEVICES flag device, and shows how to add more. The reason pnpbios gets a defined structure and as such uses a different approach than the RTC legacy quirk is that ACPI has a respective RTC flag, while pnpbios does not. We fold the pnpbios quirk under ACPI_FADT_LEGACY_DEVICES ACPI flag use case, and use a struct of possible devices to enable future extensions of this. As per 0-day, this bumps the vmlinux size using i386-tinyconfig as follows: TOTAL TEXT init.text x86_early_init_platform_quirks() +32 +28 +28 +28 That's 4 byte overhead total, the rest is cleared out on init as its all __init text. v2: split out subarch handlng on switch to make it easier later to add other subarchs. The 'fall-through' switch handling can be confusing and we'll remove it later when we add handling for X86_SUBARCH_CE4100. v3: document vmlinux size impact as per 0-day, and also explain why pnpbios is treated differently than the RTC legacy feature. Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Greg Kroah-Hartman Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-12-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/x86_init.h | 26 ++++++++++++++++++++++++++ arch/x86/kernel/platform-quirks.c | 11 +++++++++++ drivers/pnp/pnpbios/core.c | 3 ++- include/linux/pnp.h | 2 ++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 89d9d57e145d..4dcdf74dfed8 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -141,16 +141,42 @@ struct x86_cpuinit_ops { struct timespec; +/** + * struct x86_legacy_devices - legacy x86 devices + * + * @pnpbios: this platform can have a PNPBIOS. If this is disabled the platform + * is known to never have a PNPBIOS. + * + * These are devices known to require LPC or ISA bus. The definition of legacy + * devices adheres to the ACPI 5.2.9.3 IA-PC Boot Architecture flag + * ACPI_FADT_LEGACY_DEVICES. These devices consist of user visible devices on + * the LPC or ISA bus. User visible devices are devices that have end-user + * accessible connectors (for example, LPT parallel port). Legacy devices on + * the LPC bus consist for example of serial and parallel ports, PS/2 keyboard + * / mouse, and the floppy disk controller. A system that lacks all known + * legacy devices can assume all devices can be detected exclusively via + * standard device enumeration mechanisms including the ACPI namespace. + * + * A system which has does not have ACPI_FADT_LEGACY_DEVICES enabled must not + * have any of the legacy devices enumerated below present. + */ +struct x86_legacy_devices { + int pnpbios; +}; + /** * struct x86_legacy_features - legacy x86 features * * @rtc: this device has a CMOS real-time clock present * @ebda_search: it's safe to search for the EBDA signature in the hardware's * low RAM + * @devices: legacy x86 devices, refer to struct x86_legacy_devices + * documentation for further details. */ struct x86_legacy_features { int rtc; int ebda_search; + struct x86_legacy_devices devices; }; /** diff --git a/arch/x86/kernel/platform-quirks.c b/arch/x86/kernel/platform-quirks.c index 01b159781d96..ab643825a7aa 100644 --- a/arch/x86/kernel/platform-quirks.c +++ b/arch/x86/kernel/platform-quirks.c @@ -8,6 +8,7 @@ void __init x86_early_init_platform_quirks(void) { x86_platform.legacy.rtc = 1; x86_platform.legacy.ebda_search = 0; + x86_platform.legacy.devices.pnpbios = 1; switch (boot_params.hdr.hardware_subarch) { case X86_SUBARCH_PC: @@ -15,6 +16,9 @@ void __init x86_early_init_platform_quirks(void) break; case X86_SUBARCH_XEN: case X86_SUBARCH_LGUEST: + x86_platform.legacy.devices.pnpbios = 0; + x86_platform.legacy.rtc = 0; + break; case X86_SUBARCH_INTEL_MID: x86_platform.legacy.rtc = 0; break; @@ -23,3 +27,10 @@ void __init x86_early_init_platform_quirks(void) if (x86_platform.set_legacy_features) x86_platform.set_legacy_features(); } + +#if defined(CONFIG_PNPBIOS) +bool __init arch_pnpbios_disabled(void) +{ + return x86_platform.legacy.devices.pnpbios == 0; +} +#endif diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index facd43b8516c..81603d99082b 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -521,10 +521,11 @@ static int __init pnpbios_init(void) int ret; if (pnpbios_disabled || dmi_check_system(pnpbios_dmi_table) || - paravirt_enabled()) { + arch_pnpbios_disabled()) { printk(KERN_INFO "PnPBIOS: Disabled\n"); return -ENODEV; } + #ifdef CONFIG_PNPACPI if (!acpi_disabled && !pnpacpi_disabled) { pnpbios_disabled = 1; diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 5df733b8f704..2588ca6a9028 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -337,9 +337,11 @@ extern struct mutex pnp_res_mutex; #ifdef CONFIG_PNPBIOS extern struct pnp_protocol pnpbios_protocol; +extern bool arch_pnpbios_disabled(void); #define pnp_device_is_pnpbios(dev) ((dev)->protocol == (&pnpbios_protocol)) #else #define pnp_device_is_pnpbios(dev) 0 +#define arch_pnpbios_disabled() false #endif #ifdef CONFIG_PNPACPI -- GitLab From 7a17b82ccd6671a4bb436df52eedeff906b02735 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:42 -0700 Subject: [PATCH 3956/9938] x86/ACPI: Parse ACPI_FADT_LEGACY_DEVICES ACPI 5.2.9.3 IA-PC Boot Architecture flag ACPI_FADT_LEGACY_DEVICES can be used to determine if a system has legacy devices LPC or ISA devices. The x86 platform already has a struct which lists known associated legacy devices, we start off careful only by disabling root devices we should not regress with. The struct and device list can be expanded with time to cover more root legacy components. Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-13-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8c9c2bdba092..c9a06e573fa5 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -913,6 +913,11 @@ late_initcall(hpet_insert_resource); static int __init acpi_parse_fadt(struct acpi_table_header *table) { + if (!(acpi_gbl_FADT.boot_flags & ACPI_FADT_LEGACY_DEVICES)) { + pr_debug("ACPI: no legacy devices present\n"); + x86_platform.legacy.devices.pnpbios = 0; + } + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) { pr_debug("ACPI: not registering RTC platform device\n"); x86_platform.legacy.rtc = 0; -- GitLab From f2d85299b7f11f73cc0a294e396cdae114e75787 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:43 -0700 Subject: [PATCH 3957/9938] x86/init: Rename EBDA code file This makes it clearer what this is. Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-14-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/Makefile | 2 +- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/{head.c => ebda.c} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename arch/x86/kernel/{head.c => ebda.c} (100%) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index f9ed8a7ce2b6..6fce7f096b88 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -208,7 +208,7 @@ endif head-y := arch/x86/kernel/head_$(BITS).o head-y += arch/x86/kernel/head$(BITS).o -head-y += arch/x86/kernel/head.o +head-y += arch/x86/kernel/ebda.o head-y += arch/x86/kernel/platform-quirks.o libs-y += arch/x86/lib/ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index b81b22ee10ba..9abf8551c7e4 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -4,7 +4,7 @@ extra-y := head_$(BITS).o extra-y += head$(BITS).o -extra-y += head.o +extra-y += ebda.o extra-y += platform-quirks.o extra-y += vmlinux.lds diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/ebda.c similarity index 100% rename from arch/x86/kernel/head.c rename to arch/x86/kernel/ebda.c -- GitLab From 867fe800b4c423bce46e66ccb2ce91bebbd5afc6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:44 -0700 Subject: [PATCH 3958/9938] x86/paravirt: Remove paravirt_enabled() Now that all previous paravirt_enabled() uses were replaced with proper x86 semantics by the previous patches we can remove the unused paravirt_enabled() mechanism. Signed-off-by: Luis R. Rodriguez Acked-by: Juergen Gross Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-15-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/paravirt.h | 5 ----- arch/x86/include/asm/paravirt_types.h | 1 - arch/x86/include/asm/processor.h | 1 - arch/x86/kernel/kvm.c | 8 -------- arch/x86/kernel/paravirt.c | 1 - arch/x86/lguest/boot.c | 2 -- arch/x86/xen/enlighten.c | 1 - 7 files changed, 19 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 6c7a4a192032..dff26bc91b17 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -15,11 +15,6 @@ #include #include -static inline int paravirt_enabled(void) -{ - return pv_info.paravirt_enabled; -} - static inline void load_sp0(struct tss_struct *tss, struct thread_struct *thread) { diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 6acc1b26cf40..7fedf24bd811 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -69,7 +69,6 @@ struct pv_info { u16 extra_user_64bit_cs; /* __USER_CS if none */ #endif - int paravirt_enabled; const char *name; }; diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 0c70c7daa6b8..8d326e822cb8 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -473,7 +473,6 @@ static inline unsigned long current_top_of_stack(void) #include #else #define __cpuid native_cpuid -#define paravirt_enabled() 0 static inline void load_sp0(struct tss_struct *tss, struct thread_struct *thread) diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 807950860fb7..c66546f29b81 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -285,14 +285,6 @@ static void __init paravirt_ops_setup(void) { pv_info.name = "KVM"; - /* - * KVM isn't paravirt in the sense of paravirt_enabled. A KVM - * guest kernel works like a bare metal kernel with additional - * features, and paravirt_enabled is about features that are - * missing. - */ - pv_info.paravirt_enabled = 0; - if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY)) pv_cpu_ops.io_delay = kvm_io_delay; diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index f08ac28b8136..71a2d8a05a66 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -294,7 +294,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void) struct pv_info pv_info = { .name = "bare hardware", - .paravirt_enabled = 0, .kernel_rpl = 0, .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */ diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index f5497ee5fd2f..3847e736702e 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -1408,8 +1408,6 @@ __init void lguest_init(void) { /* We're under lguest. */ pv_info.name = "lguest"; - /* Paravirt is enabled. */ - pv_info.paravirt_enabled = 1; /* We're running at privilege level 1, not 0 as normal. */ pv_info.kernel_rpl = 1; /* Everyone except Xen runs with this set. */ diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 752029d571bf..5fc20a1108c7 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1187,7 +1187,6 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, } static const struct pv_info xen_info __initconst = { - .paravirt_enabled = 1, .shared_kernel_pmd = 0, #ifdef CONFIG_X86_64 -- GitLab From f6935b7bfbf8345bea05f73dc48ce81b70f016e0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:45 -0700 Subject: [PATCH 3959/9938] x86/init: Disable pnpbios for X86_SUBARCH_INTEL_MID As per hpa Intel MID platforms can also disable pnpbios: ttp://lkml.kernel.org/r/5702B5C2.7070101@zytor.com As per 0-day, this bumps the vmlinux size using i386-tinyconfig as follows: TOTAL TEXT init.text x86_early_init_platform_quirks() -8 -8 -8 -8 Suggested-by: H. Peter Anvin Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-16-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/platform-quirks.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/platform-quirks.c b/arch/x86/kernel/platform-quirks.c index ab643825a7aa..853919484340 100644 --- a/arch/x86/kernel/platform-quirks.c +++ b/arch/x86/kernel/platform-quirks.c @@ -16,10 +16,8 @@ void __init x86_early_init_platform_quirks(void) break; case X86_SUBARCH_XEN: case X86_SUBARCH_LGUEST: - x86_platform.legacy.devices.pnpbios = 0; - x86_platform.legacy.rtc = 0; - break; case X86_SUBARCH_INTEL_MID: + x86_platform.legacy.devices.pnpbios = 0; x86_platform.legacy.rtc = 0; break; } -- GitLab From a50b22a7a1e60c48ca26cada362076b54823c501 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Apr 2016 17:04:46 -0700 Subject: [PATCH 3960/9938] x86/init: Disable pnpbios and rtc for X86_SUBARCH_CE4100 As per hpa CE4100 platforms can also disable pnpbios: http://lkml.kernel.org/r/5702B5C2.7070101@zytor.com Then Sebastian also recently noted that CE4100 also disables RTC probe, to do that Sebastian had long ago added the RTC of_have_populated_dt() check, he noted that it was meant to skip the RTC probe on all OF platforms but as of now, CE4100 was the only x86 DT using this. We can just fold this requirement into the platform quirk then. This now means that all of these match platform quirks for pnpbios and RTC preferences: * X86_SUBARCH_XEN * X86_SUBARCH_LGUEST * X86_SUBARCH_INTEL_MID * X86_SUBARCH_CE4100 Also see: http://lkml.kernel.org/r/570B52EA.60300@linutronix.de Suggested-by: H. Peter Anvin Suggested-by: Sebastian Andrzej Siewior Signed-off-by: Luis R. Rodriguez Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jgross@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-17-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/platform-quirks.c | 1 + arch/x86/kernel/rtc.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/platform-quirks.c b/arch/x86/kernel/platform-quirks.c index 853919484340..b2f8a33b36ff 100644 --- a/arch/x86/kernel/platform-quirks.c +++ b/arch/x86/kernel/platform-quirks.c @@ -17,6 +17,7 @@ void __init x86_early_init_platform_quirks(void) case X86_SUBARCH_XEN: case X86_SUBARCH_LGUEST: case X86_SUBARCH_INTEL_MID: + case X86_SUBARCH_CE4100: x86_platform.legacy.devices.pnpbios = 0; x86_platform.legacy.rtc = 0; break; diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index ff4f4180fefd..eceaa082ec3f 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -186,9 +186,6 @@ static __init int add_rtc_cmos(void) } } #endif - if (of_have_populated_dt()) - return 0; - if (!x86_platform.legacy.rtc) return -ENODEV; -- GitLab From 046982c760bcbb0d92981a7be577dbc081323a78 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 18:04:55 +0200 Subject: [PATCH 3961/9938] nios2: use correct void* return type for page_to_virt() To align with other architectures, the expression produced by expanding the macro page_to_virt() should be of type void*, since it returns a virtual address. Fix that, and also fix up an instance where page_to_virt was expected to return 'unsigned long', and drop another instance that was entirely unused (page_to_bus) Acked-by: Andrew Morton Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/nios2/include/asm/io.h | 1 - arch/nios2/include/asm/page.h | 2 +- arch/nios2/include/asm/pgtable.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/nios2/include/asm/io.h b/arch/nios2/include/asm/io.h index c5a62da22cd2..ce072ba0f8dd 100644 --- a/arch/nios2/include/asm/io.h +++ b/arch/nios2/include/asm/io.h @@ -50,7 +50,6 @@ static inline void iounmap(void __iomem *addr) /* Pages to physical address... */ #define page_to_phys(page) virt_to_phys(page_to_virt(page)) -#define page_to_bus(page) page_to_virt(page) /* Macros used for converting between virtual and physical mappings. */ #define phys_to_virt(vaddr) \ diff --git a/arch/nios2/include/asm/page.h b/arch/nios2/include/asm/page.h index 4b32d6fd9d98..c1683f51ad0f 100644 --- a/arch/nios2/include/asm/page.h +++ b/arch/nios2/include/asm/page.h @@ -84,7 +84,7 @@ extern struct page *mem_map; ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) #define page_to_virt(page) \ - ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) + ((void *)(((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) # define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) # define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && \ diff --git a/arch/nios2/include/asm/pgtable.h b/arch/nios2/include/asm/pgtable.h index a213e8c9aad0..298393c3cb42 100644 --- a/arch/nios2/include/asm/pgtable.h +++ b/arch/nios2/include/asm/pgtable.h @@ -209,7 +209,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { - unsigned long paddr = page_to_virt(pte_page(pteval)); + unsigned long paddr = (unsigned long)page_to_virt(pte_page(pteval)); flush_dcache_range(paddr, paddr + PAGE_SIZE); set_pte(ptep, pteval); -- GitLab From 86d618cd1d9fdf4b46b68eb014d4fbde08c4ae62 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 18:04:56 +0200 Subject: [PATCH 3962/9938] openrisc: drop wrongly typed definition of page_to_virt() To align with generic code and other architectures that expect the macro page_to_virt to produce an expression whose type is 'void*', drop the arch specific definition, which is never referenced anyway. Acked-by: Andrew Morton Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/openrisc/include/asm/page.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h index e613d3673034..35bcb7cd2cde 100644 --- a/arch/openrisc/include/asm/page.h +++ b/arch/openrisc/include/asm/page.h @@ -81,8 +81,6 @@ typedef struct page *pgtable_t; #define virt_to_page(addr) \ (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) -#define page_to_virt(page) \ - ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) -- GitLab From 1dff8083a024650c75a9c961c38082473ceae8cf Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 18:04:57 +0200 Subject: [PATCH 3963/9938] mm: replace open coded page to virt conversion with page_to_virt() The open coded conversion from struct page address to virtual address in lowmem_page_address() involves an intermediate conversion step to pfn number/physical address. Since the placement of the struct page array relative to the linear mapping may be completely independent from the placement of physical RAM (as is that case for arm64 after commit dfd55ad85e 'arm64: vmemmap: use virtual projection of linear region'), the conversion to physical address and back again should factor out of the equation, but unfortunately, the shifting and pointer arithmetic involved prevent this from happening, and the resulting calculation essentially subtracts the address of the start of physical memory and adds it back again, in a way that prevents the compiler from optimizing it away. Since the start of physical memory is not a build time constant on arm64, the resulting conversion involves an unnecessary memory access, which we would like to get rid of. So replace the open coded conversion with a call to page_to_virt(), and use the open coded conversion as its default definition, to be overriden by the architecture, if desired. The existing arch specific definitions of page_to_virt are all equivalent to this default definition, so by itself this patch is a no-op. Acked-by: Andrew Morton Acked-by: Will Deacon Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- include/linux/mm.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index ffcff53e3b2b..1c1e921edf93 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -72,6 +72,10 @@ extern int mmap_rnd_compat_bits __read_mostly; #define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0)) #endif +#ifndef page_to_virt +#define page_to_virt(x) __va(PFN_PHYS(page_to_pfn(x))) +#endif + /* * To prevent common memory management code establishing * a zero page mapping on a read fault. @@ -948,7 +952,7 @@ static inline struct mem_cgroup *page_memcg(struct page *page) static __always_inline void *lowmem_page_address(const struct page *page) { - return __va(PFN_PHYS(page_to_pfn(page))); + return page_to_virt(page); } #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) -- GitLab From db71336b9eec22c21cef65c90cea49130c464994 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 22 Apr 2016 10:40:11 +0200 Subject: [PATCH 3964/9938] ASoC: hdmi-codec: Add ELD control Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index c78333b4311d..8e36e883e453 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -65,9 +65,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); - mutex_lock(&hcp->eld_lock); memcpy(ucontrol->value.bytes.data, hcp->eld, sizeof(hcp->eld)); - mutex_unlock(&hcp->eld_lock); return 0; } -- GitLab From 2d80a91b2f2a96f38877bc328dac135d69564911 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Thu, 21 Apr 2016 17:23:21 +0100 Subject: [PATCH 3965/9938] regulator: core: Add debugfs to show constraint flags There are debugfs entries for voltage and current, but not for the constraint flags. It's useful for debugging to be able to see what these flags are so this patch adds a new debugfs file. We can't use debugfs_create_bool for this because the flags are bitfields, so as this needs a special read callback they have been collected into a single file that lists all the flags. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- drivers/regulator/core.c | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0b764284773..73381752ff78 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1272,6 +1272,55 @@ static void unset_regulator_supplies(struct regulator_dev *rdev) } } +#ifdef CONFIG_DEBUG_FS +static ssize_t constraint_flags_read_file(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + const struct regulator *regulator = file->private_data; + const struct regulation_constraints *c = regulator->rdev->constraints; + char *buf; + ssize_t ret; + + if (!c) + return 0; + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = snprintf(buf, PAGE_SIZE, + "always_on: %u\n" + "boot_on: %u\n" + "apply_uV: %u\n" + "ramp_disable: %u\n" + "soft_start: %u\n" + "pull_down: %u\n" + "over_current_protection: %u\n", + c->always_on, + c->boot_on, + c->apply_uV, + c->ramp_disable, + c->soft_start, + c->pull_down, + c->over_current_protection); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); + kfree(buf); + + return ret; +} + +#endif + +static const struct file_operations constraint_flags_fops = { +#ifdef CONFIG_DEBUG_FS + .open = simple_open, + .read = constraint_flags_read_file, + .llseek = default_llseek, +#endif +}; + #define REG_STR_SIZE 64 static struct regulator *create_regulator(struct regulator_dev *rdev, @@ -1327,6 +1376,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, ®ulator->min_uV); debugfs_create_u32("max_uV", 0444, regulator->debugfs, ®ulator->max_uV); + debugfs_create_file("constraint_flags", 0444, + regulator->debugfs, regulator, + &constraint_flags_fops); } /* -- GitLab From fba0d7066524ab7b8ccf60e7e95981d10ed008b0 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 22 Apr 2016 09:03:53 +0530 Subject: [PATCH 3966/9938] ASoC: Intel: Atom: fix boot warning Users have reported seeing this false warning on atom driver [ 5.647469] sst-mfld-platform sst-mfld-platform: Slot control: codec_out tx interleaver slot 0 doesn't have DAPM widget!!! [ 5.661612] sst-mfld-platform sst-mfld-platform: Slot control: codec_out tx interleaver slot 1 doesn't have DAPM widget!!! [ 5.661646] sst-mfld-platform sst-mfld-platform: Slot control: codec_out tx interleaver slot 2 doesn't have DAPM widget!!! [ 5.661681] sst-mfld-platform sst-mfld-platform: Slot control: codec_out tx interleaver slot 3 doesn't have DAPM widget!!! [ 5.661708] sst-mfld-platform sst-mfld-platform: Slot control: codec_in rx deinterleaver codec_in0_0 doesn't have DAPM widget!!! [ 5.661738] sst-mfld-platform sst-mfld-platform: Slot control: codec_in rx deinterleaver codec_in0_1 doesn't have DAPM widget!!! [ 5.661771] sst-mfld-platform sst-mfld-platform: Slot control: codec_in rx deinterleaver codec_in1_0 doesn't have DAPM widget!!! [ 5.661807] sst-mfld-platform sst-mfld-platform: Slot control: codec_in rx deinterleaver codec_in1_1 doesn't have DAPM widget!!! This is caused when check for control is not being associated with a dapm widget, but the check is wrong as the else case maybe triggered when widget is not powered up, so we should check if widget is associated before printing this message. Tested-by: Sandeep Tayal Tested-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-atom-controls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index b97e6adcf1b2..98720a93de8a 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -195,7 +195,7 @@ static int sst_check_and_send_slot_map(struct sst_data *drv, struct snd_kcontrol if (e->w && e->w->power) ret = sst_send_slot_map(drv); - else + else if (!e->w) dev_err(&drv->pdev->dev, "Slot control: %s doesn't have DAPM widget!!!\n", kcontrol->id.name); return ret; -- GitLab From 54aba08f13fab00f31938993c9f7a9b0cd54f666 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 22 Apr 2016 09:09:14 +0000 Subject: [PATCH 3967/9938] ASoC: tidyup alphabetical order for SND_SOC_Bxx Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 8 ++++---- sound/soc/codecs/Makefile | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 649e92a252ae..f7f64bd019a5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -43,6 +43,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_AK5386 select SND_SOC_ALC5623 if I2C select SND_SOC_ALC5632 if I2C + select SND_SOC_BT_SCO select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC select SND_SOC_CS35L32 if I2C select SND_SOC_CS42L51_I2C if I2C @@ -64,7 +65,6 @@ config SND_SOC_ALL_CODECS select SND_SOC_DA732X if I2C select SND_SOC_DA9055 if I2C select SND_SOC_DMIC - select SND_SOC_BT_SCO select SND_SOC_ES8328_SPI if SPI_MASTER select SND_SOC_ES8328_I2C if I2C select SND_SOC_GTM601 @@ -365,6 +365,9 @@ config SND_SOC_ALC5623 config SND_SOC_ALC5632 tristate +config SND_SOC_BT_SCO + tristate + config SND_SOC_CQ0093VC tristate @@ -471,9 +474,6 @@ config SND_SOC_DA732X config SND_SOC_DA9055 tristate -config SND_SOC_BT_SCO - tristate - config SND_SOC_DMIC tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 185a712a7fe7..12a1fe22eaa1 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -32,6 +32,7 @@ snd-soc-ak4642-objs := ak4642.o snd-soc-ak4671-objs := ak4671.o snd-soc-ak5386-objs := ak5386.o snd-soc-arizona-objs := arizona.o +snd-soc-bt-sco-objs := bt-sco.o snd-soc-cq93vc-objs := cq93vc.o snd-soc-cs35l32-objs := cs35l32.o snd-soc-cs42l51-objs := cs42l51.o @@ -55,7 +56,6 @@ snd-soc-da7218-objs := da7218.o snd-soc-da7219-objs := da7219.o da7219-aad.o snd-soc-da732x-objs := da732x.o snd-soc-da9055-objs := da9055.o -snd-soc-bt-sco-objs := bt-sco.o snd-soc-dmic-objs := dmic.o snd-soc-es8328-objs := es8328.o snd-soc-es8328-i2c-objs := es8328-i2c.o @@ -241,6 +241,7 @@ obj-$(CONFIG_SND_SOC_AK5386) += snd-soc-ak5386.o obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o +obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o @@ -264,7 +265,6 @@ obj-$(CONFIG_SND_SOC_DA7218) += snd-soc-da7218.o obj-$(CONFIG_SND_SOC_DA7219) += snd-soc-da7219.o obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o -obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o -- GitLab From fbb88b5ca1dc84416fc1fec34773948b6780492c Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 22 Apr 2016 12:25:33 +0800 Subject: [PATCH 3968/9938] ASoC: Add kerneldoc comments for snd_soc_find_dai snd_soc_find_dai() has been exported and so add the kerneldoc comments for it. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 07663def2db6..16369cad4803 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -930,6 +930,17 @@ static struct snd_soc_component *soc_find_component( return NULL; } +/** + * snd_soc_find_dai - Find a registered DAI + * + * @dlc: name of the DAI and optional component info to match + * + * This function will search all regsitered components and their DAIs to + * find the DAI of the same name. The component's of_node and name + * should also match if being specified. + * + * Return: pointer of DAI, or NULL if not found. + */ struct snd_soc_dai *snd_soc_find_dai( const struct snd_soc_dai_link_component *dlc) { -- GitLab From 7ddede6a58a0bd26efcfd2a5055611195411f514 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 21 Apr 2016 17:11:57 +0100 Subject: [PATCH 3969/9938] regulator: core: Don't terminate supply resolution early The function regulator_register_resolve_supply() is called from the context of class_for_each_dev() (during the regulator registration) to resolve any supplies added. regulator_register_resolve_supply() will return an error if a regulator's supply cannot be resolved and this will terminate the loop in class_for_each_dev(). This means that we will not attempt to resolve any other supplies after one has failed. Hence, this may delay the resolution of other regulator supplies until the failing one itself can be resolved. Rather than terminating the loop early, don't return an error code and keep attempting to resolve any other supplies for regulators that have been registered. Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- drivers/regulator/core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index fd0e4e37f4e1..9922922ce6bd 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3842,7 +3842,12 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) static int regulator_register_resolve_supply(struct device *dev, void *data) { - return regulator_resolve_supply(dev_to_rdev(dev)); + struct regulator_dev *rdev = dev_to_rdev(dev); + + if (regulator_resolve_supply(rdev)) + rdev_dbg(rdev, "unable to resolve supply\n"); + + return 0; } /** -- GitLab From 8e5356a73604f53da6a1e0756727cb8f9f7bba17 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 21 Apr 2016 17:11:58 +0100 Subject: [PATCH 3970/9938] regulator: core: Clear the supply pointer if enabling fails During the resolution of a regulator's supply, we may attempt to enable the supply if the regulator itself is already enabled. If enabling the supply fails, then we will call _regulator_put() for the supply. However, the pointer to the supply has not been cleared for the regulator and this will cause a crash if we then unregister the regulator and attempt to call regulator_put() a second time for the supply. Fix this by clearing the supply pointer if enabling the supply after fails when resolving the supply for a regulator. Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- drivers/regulator/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9922922ce6bd..bd9ec309b707 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1536,6 +1536,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) ret = regulator_enable(rdev->supply); if (ret < 0) { _regulator_put(rdev->supply); + rdev->supply = NULL; return ret; } } -- GitLab From c438b9d017362b65f6b1a9e54f7f35e7f873dc7c Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 21 Apr 2016 17:11:59 +0100 Subject: [PATCH 3971/9938] regulator: core: Move registration of regulator device The public functions to acquire a regulator, such as regulator_get(), internally look-up the regulator from the list of regulators that have been registered with the regulator device class. The registration of a new regulator with the regulator device class happens before the regulator has been completely setup. Therefore, it is possible that the regulator could be acquired before it has been setup successfully. To avoid this move the device registration of the regulator to the end of the regulator setup and update the error exit path accordingly. Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- drivers/regulator/core.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a17ce6cbbe77..8362a0a5105d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3970,14 +3970,6 @@ regulator_register(const struct regulator_desc *regulator_desc, if (ret < 0) goto wash; - ret = device_register(&rdev->dev); - if (ret != 0) { - put_device(&rdev->dev); - goto wash; - } - - dev_set_drvdata(&rdev->dev, rdev); - if (init_data && init_data->supply_regulator) rdev->supply_name = init_data->supply_regulator; else if (regulator_desc->supply_name) @@ -3997,9 +3989,17 @@ regulator_register(const struct regulator_desc *regulator_desc, } } - rdev_init_debugfs(rdev); mutex_unlock(®ulator_list_mutex); + ret = device_register(&rdev->dev); + if (ret != 0) { + put_device(&rdev->dev); + goto unset_supplies; + } + + dev_set_drvdata(&rdev->dev, rdev); + rdev_init_debugfs(rdev); + /* try to resolve regulators supply since a new one was registered */ class_for_each_device(®ulator_class, NULL, NULL, regulator_register_resolve_supply); @@ -4008,17 +4008,11 @@ regulator_register(const struct regulator_desc *regulator_desc, unset_supplies: unset_regulator_supplies(rdev); - regulator_ena_gpio_free(rdev); - device_unregister(&rdev->dev); - /* device core frees rdev */ - goto out; - wash: kfree(rdev->constraints); regulator_ena_gpio_free(rdev); clean: kfree(rdev); -out: mutex_unlock(®ulator_list_mutex); kfree(config); return ERR_PTR(ret); -- GitLab From e9fc71649b5361b8ac608898342c8904167cb63d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Apr 2016 13:02:55 +0300 Subject: [PATCH 3972/9938] Bluetooth: ath3k: Silence uninitialized variable warning We could print an uninitialized value in the error message. Signed-off-by: Dan Carpenter Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 47ca4b39d306..641c2d19fc57 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -206,7 +206,8 @@ static int ath3k_load_firmware(struct usb_device *udev, const struct firmware *firmware) { u8 *send_buf; - int err, pipe, len, size, sent = 0; + int len = 0; + int err, pipe, size, sent = 0; int count = firmware->size; BT_DBG("udev %p", udev); @@ -302,7 +303,8 @@ static int ath3k_load_fwfile(struct usb_device *udev, const struct firmware *firmware) { u8 *send_buf; - int err, pipe, len, size, count, sent = 0; + int len = 0; + int err, pipe, size, count, sent = 0; int ret; count = firmware->size; -- GitLab From dd1a571daee7cdd6504a5771721e34f9b118f17a Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 21 Apr 2016 17:12:01 +0100 Subject: [PATCH 3973/9938] regulator: helpers: Ensure bypass register field matches ON value When checking bypass state for a regulator, we check to see if any bits in the bypass mask are set. For most cases this is fine because there is typically, only a single bit used to determine if the regulator is in bypass. However, for some regulators, such as LDO6 on AS3722, the bypass state is indicate by a value rather than a single bit. Therefore, when checking the bypass state, check that the bypass field matches the ON value. Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- drivers/regulator/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index b1e32e7482e9..bcf38fd5106a 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -460,7 +460,7 @@ int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) if (ret != 0) return ret; - *enable = val & rdev->desc->bypass_mask; + *enable = (val & rdev->desc->bypass_mask) == rdev->desc->bypass_val_on; return 0; } -- GitLab From 1e48b695d79f9afb6357fe0217b2829e0faed77d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 5 Apr 2016 13:25:07 -0600 Subject: [PATCH 3974/9938] ARM: tegra: Fix naming in GPIO DT binding header According to the Tegra TRM, GPIOs are aggregated into /ports/ of 8 GPIOs, not into /banks/. Fix to correctly reflect this naming convention. While this seems like silly churn, it will become slightly more important once we introduce the GPIO binding for upcoming Tegra chips. Signed-off-by: Stephen Warren Acked-by: Thierry Reding Acked-by: Linus Walleij Signed-off-by: Thierry Reding --- include/dt-bindings/gpio/tegra-gpio.h | 68 +++++++++++++-------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/include/dt-bindings/gpio/tegra-gpio.h b/include/dt-bindings/gpio/tegra-gpio.h index 197dc28b676e..a1c09e88e80b 100644 --- a/include/dt-bindings/gpio/tegra-gpio.h +++ b/include/dt-bindings/gpio/tegra-gpio.h @@ -12,40 +12,40 @@ #include -#define TEGRA_GPIO_BANK_ID_A 0 -#define TEGRA_GPIO_BANK_ID_B 1 -#define TEGRA_GPIO_BANK_ID_C 2 -#define TEGRA_GPIO_BANK_ID_D 3 -#define TEGRA_GPIO_BANK_ID_E 4 -#define TEGRA_GPIO_BANK_ID_F 5 -#define TEGRA_GPIO_BANK_ID_G 6 -#define TEGRA_GPIO_BANK_ID_H 7 -#define TEGRA_GPIO_BANK_ID_I 8 -#define TEGRA_GPIO_BANK_ID_J 9 -#define TEGRA_GPIO_BANK_ID_K 10 -#define TEGRA_GPIO_BANK_ID_L 11 -#define TEGRA_GPIO_BANK_ID_M 12 -#define TEGRA_GPIO_BANK_ID_N 13 -#define TEGRA_GPIO_BANK_ID_O 14 -#define TEGRA_GPIO_BANK_ID_P 15 -#define TEGRA_GPIO_BANK_ID_Q 16 -#define TEGRA_GPIO_BANK_ID_R 17 -#define TEGRA_GPIO_BANK_ID_S 18 -#define TEGRA_GPIO_BANK_ID_T 19 -#define TEGRA_GPIO_BANK_ID_U 20 -#define TEGRA_GPIO_BANK_ID_V 21 -#define TEGRA_GPIO_BANK_ID_W 22 -#define TEGRA_GPIO_BANK_ID_X 23 -#define TEGRA_GPIO_BANK_ID_Y 24 -#define TEGRA_GPIO_BANK_ID_Z 25 -#define TEGRA_GPIO_BANK_ID_AA 26 -#define TEGRA_GPIO_BANK_ID_BB 27 -#define TEGRA_GPIO_BANK_ID_CC 28 -#define TEGRA_GPIO_BANK_ID_DD 29 -#define TEGRA_GPIO_BANK_ID_EE 30 -#define TEGRA_GPIO_BANK_ID_FF 31 +#define TEGRA_GPIO_PORT_A 0 +#define TEGRA_GPIO_PORT_B 1 +#define TEGRA_GPIO_PORT_C 2 +#define TEGRA_GPIO_PORT_D 3 +#define TEGRA_GPIO_PORT_E 4 +#define TEGRA_GPIO_PORT_F 5 +#define TEGRA_GPIO_PORT_G 6 +#define TEGRA_GPIO_PORT_H 7 +#define TEGRA_GPIO_PORT_I 8 +#define TEGRA_GPIO_PORT_J 9 +#define TEGRA_GPIO_PORT_K 10 +#define TEGRA_GPIO_PORT_L 11 +#define TEGRA_GPIO_PORT_M 12 +#define TEGRA_GPIO_PORT_N 13 +#define TEGRA_GPIO_PORT_O 14 +#define TEGRA_GPIO_PORT_P 15 +#define TEGRA_GPIO_PORT_Q 16 +#define TEGRA_GPIO_PORT_R 17 +#define TEGRA_GPIO_PORT_S 18 +#define TEGRA_GPIO_PORT_T 19 +#define TEGRA_GPIO_PORT_U 20 +#define TEGRA_GPIO_PORT_V 21 +#define TEGRA_GPIO_PORT_W 22 +#define TEGRA_GPIO_PORT_X 23 +#define TEGRA_GPIO_PORT_Y 24 +#define TEGRA_GPIO_PORT_Z 25 +#define TEGRA_GPIO_PORT_AA 26 +#define TEGRA_GPIO_PORT_BB 27 +#define TEGRA_GPIO_PORT_CC 28 +#define TEGRA_GPIO_PORT_DD 29 +#define TEGRA_GPIO_PORT_EE 30 +#define TEGRA_GPIO_PORT_FF 31 -#define TEGRA_GPIO(bank, offset) \ - ((TEGRA_GPIO_BANK_ID_##bank * 8) + offset) +#define TEGRA_GPIO(port, offset) \ + ((TEGRA_GPIO_PORT_##port * 8) + offset) #endif -- GitLab From ec6b925579b40225d58f0374ada0e40a003cde16 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 12 Apr 2016 11:46:37 -0600 Subject: [PATCH 3975/9938] ARM: tegra: Add DT binding for Tegra186 GPIO controllers Tegra186 contains two separate but mostly similar GPIO controllers. Register layout differs significantly from previous Tegra generations, and so a new binding is required to describe them in device tree. This patch adds that binding. Signed-off-by: Stephen Warren Acked-by: Rob Herring Acked-by: Linus Walleij Signed-off-by: Thierry Reding --- .../bindings/gpio/nvidia,tegra186-gpio.txt | 161 ++++++++++++++++++ include/dt-bindings/gpio/tegra186-gpio.h | 56 ++++++ 2 files changed, 217 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt create mode 100644 include/dt-bindings/gpio/tegra186-gpio.h diff --git a/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt new file mode 100644 index 000000000000..c82a2e221bc1 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt @@ -0,0 +1,161 @@ +NVIDIA Tegra186 GPIO controllers + +Tegra186 contains two GPIO controllers; a main controller and an "AON" +controller. This binding document applies to both controllers. The register +layouts for the controllers share many similarities, but also some significant +differences. Hence, this document describes closely related but different +bindings and compatible values. + +The Tegra186 GPIO controller allows software to set the IO direction of, and +read/write the value of, numerous GPIO signals. Routing of GPIO signals to +package balls is under the control of a separate pin controller HW block. Two +major sets of registers exist: + +a) Security registers, which allow configuration of allowed access to the GPIO +register set. These registers exist in a single contiguous block of physical +address space. The size of this block, and the security features available, +varies between the different GPIO controllers. + +Access to this set of registers is not necessary in all circumstances. Code +that wishes to configure access to the GPIO registers needs access to these +registers to do so. Code which simply wishes to read or write GPIO data does not +need access to these registers. + +b) GPIO registers, which allow manipulation of the GPIO signals. In some GPIO +controllers, these registers are exposed via multiple "physical aliases" in +address space, each of which access the same underlying state. See the hardware +documentation for rationale. Any particular GPIO client is expected to access +just one of these physical aliases. + +Tegra HW documentation describes a unified naming convention for all GPIOs +implemented by the SoC. Each GPIO is assigned to a port, and a port may control +a number of GPIOs. Thus, each GPIO is named according to an alphabetical port +name and an integer GPIO name within the port. For example, GPIO_PA0, GPIO_PN6, +or GPIO_PCC3. + +The number of ports implemented by each GPIO controller varies. The number of +implemented GPIOs within each port varies. GPIO registers within a controller +are grouped and laid out according to the port they affect. + +The mapping from port name to the GPIO controller that implements that port, and +the mapping from port name to register offset within a controller, are both +extremely non-linear. The header file +describes the port-level mapping. In that file, the naming convention for ports +matches the HW documentation. The values chosen for the names are alphabetically +sorted within a particular controller. Drivers need to map between the DT GPIO +IDs and HW register offsets using a lookup table. + +Each GPIO controller can generate a number of interrupt signals. Each signal +represents the aggregate status for all GPIOs within a set of ports. Thus, the +number of interrupt signals generated by a controller varies as a rough function +of the number of ports it implements. Note that the HW documentation refers to +both the overall controller HW module and the sets-of-ports as "controllers". + +Each GPIO controller in fact generates multiple interrupts signals for each set +of ports. Each GPIO may be configured to feed into a specific one of the +interrupt signals generated by a set-of-ports. The intent is for each generated +signal to be routed to a different CPU, thus allowing different CPUs to each +handle subsets of the interrupts within a port. The status of each of these +per-port-set signals is reported via a separate register. Thus, a driver needs +to know which status register to observe. This binding currently defines no +configuration mechanism for this. By default, drivers should use register +GPIO_${port}_INTERRUPT_STATUS_G1_0. Future revisions to the binding could +define a property to configure this. + +Required properties: +- compatible + Array of strings. + One of: + - "nvidia,tegra186-gpio". + - "nvidia,tegra186-gpio-aon". +- reg-names + Array of strings. + Contains a list of names for the register spaces described by the reg + property. May contain the following entries, in any order: + - "gpio": Mandatory. GPIO control registers. This may cover either: + a) The single physical alias that this OS should use. + b) All physical aliases that exist in the controller. This is + appropriate when the OS is responsible for managing assignment of + the physical aliases. + - "security": Optional. Security configuration registers. + Users of this binding MUST look up entries in the reg property by name, + using this reg-names property to do so. +- reg + Array of (physical base address, length) tuples. + Must contain one entry per entry in the reg-names property, in a matching + order. +- interrupts + Array of interrupt specifiers. + The interrupt outputs from the HW block, one per set of ports, in the + order the HW manual describes them. The number of entries required varies + depending on compatible value: + - "nvidia,tegra186-gpio": 6 entries. + - "nvidia,tegra186-gpio-aon": 1 entry. +- gpio-controller + Boolean. + Marks the device node as a GPIO controller/provider. +- #gpio-cells + Single-cell integer. + Must be <2>. + Indicates how many cells are used in a consumer's GPIO specifier. + In the specifier: + - The first cell is the pin number. + See . + - The second cell contains flags: + - Bit 0 specifies polarity + - 0: Active-high (normal). + - 1: Active-low (inverted). +- interrupt-controller + Boolean. + Marks the device node as an interrupt controller/provider. +- #interrupt-cells + Single-cell integer. + Must be <2>. + Indicates how many cells are used in a consumer's interrupt specifier. + In the specifier: + - The first cell is the GPIO number. + See . + - The second cell is contains flags: + - Bits [3:0] indicate trigger type and level: + - 1: Low-to-high edge triggered. + - 2: High-to-low edge triggered. + - 4: Active high level-sensitive. + - 8: Active low level-sensitive. + Valid combinations are 1, 2, 3, 4, 8. + +Example: + +#include + +gpio@2200000 { + compatible = "nvidia,tegra186-gpio"; + reg-names = "security", "gpio"; + reg = + <0x0 0x2200000 0x0 0x10000>, + <0x0 0x2210000 0x0 0x10000>; + interrupts = + <0 47 IRQ_TYPE_LEVEL_HIGH>, + <0 50 IRQ_TYPE_LEVEL_HIGH>, + <0 53 IRQ_TYPE_LEVEL_HIGH>, + <0 56 IRQ_TYPE_LEVEL_HIGH>, + <0 59 IRQ_TYPE_LEVEL_HIGH>, + <0 180 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +}; + +gpio@c2f0000 { + compatible = "nvidia,tegra186-gpio-aon"; + reg-names = "security", "gpio"; + reg = + <0x0 0xc2f0000 0x0 0x1000>, + <0x0 0xc2f1000 0x0 0x1000>; + interrupts = + <0 60 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +}; diff --git a/include/dt-bindings/gpio/tegra186-gpio.h b/include/dt-bindings/gpio/tegra186-gpio.h new file mode 100644 index 000000000000..38001c7023f1 --- /dev/null +++ b/include/dt-bindings/gpio/tegra186-gpio.h @@ -0,0 +1,56 @@ +/* + * This header provides constants for binding nvidia,tegra186-gpio*. + * + * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below + * provide names for this. + * + * The second cell contains standard flag values specified in gpio.h. + */ + +#ifndef _DT_BINDINGS_GPIO_TEGRA_GPIO_H +#define _DT_BINDINGS_GPIO_TEGRA_GPIO_H + +#include + +/* GPIOs implemented by main GPIO controller */ +#define TEGRA_MAIN_GPIO_PORT_A 0 +#define TEGRA_MAIN_GPIO_PORT_B 1 +#define TEGRA_MAIN_GPIO_PORT_C 2 +#define TEGRA_MAIN_GPIO_PORT_D 3 +#define TEGRA_MAIN_GPIO_PORT_E 4 +#define TEGRA_MAIN_GPIO_PORT_F 5 +#define TEGRA_MAIN_GPIO_PORT_G 6 +#define TEGRA_MAIN_GPIO_PORT_H 7 +#define TEGRA_MAIN_GPIO_PORT_I 8 +#define TEGRA_MAIN_GPIO_PORT_J 9 +#define TEGRA_MAIN_GPIO_PORT_K 10 +#define TEGRA_MAIN_GPIO_PORT_L 11 +#define TEGRA_MAIN_GPIO_PORT_M 12 +#define TEGRA_MAIN_GPIO_PORT_N 13 +#define TEGRA_MAIN_GPIO_PORT_O 14 +#define TEGRA_MAIN_GPIO_PORT_P 15 +#define TEGRA_MAIN_GPIO_PORT_Q 16 +#define TEGRA_MAIN_GPIO_PORT_R 17 +#define TEGRA_MAIN_GPIO_PORT_T 18 +#define TEGRA_MAIN_GPIO_PORT_X 19 +#define TEGRA_MAIN_GPIO_PORT_Y 20 +#define TEGRA_MAIN_GPIO_PORT_BB 21 +#define TEGRA_MAIN_GPIO_PORT_CC 22 + +#define TEGRA_MAIN_GPIO(port, offset) \ + ((TEGRA_MAIN_GPIO_PORT_##port * 8) + offset) + +/* GPIOs implemented by AON GPIO controller */ +#define TEGRA_AON_GPIO_PORT_S 0 +#define TEGRA_AON_GPIO_PORT_U 1 +#define TEGRA_AON_GPIO_PORT_V 2 +#define TEGRA_AON_GPIO_PORT_W 3 +#define TEGRA_AON_GPIO_PORT_Z 4 +#define TEGRA_AON_GPIO_PORT_AA 5 +#define TEGRA_AON_GPIO_PORT_EE 6 +#define TEGRA_AON_GPIO_PORT_FF 7 + +#define TEGRA_AON_GPIO(port, offset) \ + ((TEGRA_AON_GPIO_PORT_##port * 8) + offset) + +#endif -- GitLab From e009a7e858fed215cb4eed5174a31cadd42d8797 Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Mon, 21 Mar 2016 14:32:48 -0500 Subject: [PATCH 3976/9938] cxl: Allow initialization on timebase sync failures Failure to synchronize the PSL timebase currently prevents the initialization of the cxl card, thus rendering the card useless. This is too extreme for a feature which is rarely used, if at all. No hardware AFUs or software is currently using PSL timebase. This patch still tries to synchronize the PSL timebase when the card is initialized, but ignores the error if it can't. Instead, it reports a status via /sys. Signed-off-by: Frederic Barrat Acked-by: Ian Munsie Signed-off-by: Michael Ellerman --- Documentation/ABI/testing/sysfs-class-cxl | 8 ++++++++ drivers/misc/cxl/cxl.h | 1 + drivers/misc/cxl/guest.c | 6 ++++++ drivers/misc/cxl/pci.c | 21 ++++++++++++--------- drivers/misc/cxl/sysfs.c | 10 ++++++++++ 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-class-cxl b/Documentation/ABI/testing/sysfs-class-cxl index 7fd737eed38a..4ba0a2a61926 100644 --- a/Documentation/ABI/testing/sysfs-class-cxl +++ b/Documentation/ABI/testing/sysfs-class-cxl @@ -233,3 +233,11 @@ Description: read/write 0 = don't trust, the image may be different (default) 1 = trust that the image will not change. Users: https://github.com/ibm-capi/libcxl + +What: /sys/class/cxl//psl_timebase_synced +Date: March 2016 +Contact: linuxppc-dev@lists.ozlabs.org +Description: read only + Returns 1 if the psl timebase register is synchronized + with the core timebase register, 0 otherwise. +Users: https://github.com/ibm-capi/libcxl diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index 38e21cf7806e..dfdbfb025089 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h @@ -579,6 +579,7 @@ struct cxl { bool perst_loads_image; bool perst_select_user; bool perst_same_image; + bool psl_timebase_synced; }; int cxl_pci_alloc_one_irq(struct cxl *adapter); diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c index 8213372de2b7..a83acf9f8cd9 100644 --- a/drivers/misc/cxl/guest.c +++ b/drivers/misc/cxl/guest.c @@ -1101,6 +1101,12 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic adapter->dev.release = release_adapter; dev_set_drvdata(&pdev->dev, adapter); + /* + * Hypervisor controls PSL timebase initialization (p1 register). + * On FW840, PSL is initialized. + */ + adapter->psl_timebase_synced = true; + if ((rc = cxl_of_read_adapter_handle(adapter, np))) goto err1; diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 94fd3f71f838..c6d5cf5e3793 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -394,22 +394,24 @@ static int init_implementation_adapter_regs(struct cxl *adapter, struct pci_dev #define TBSYNC_CNT(n) (((u64)n & 0x7) << (63-6)) #define _2048_250MHZ_CYCLES 1 -static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) +static void cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) { u64 psl_tb; int delta; unsigned int retry = 0; struct device_node *np; + adapter->psl_timebase_synced = false; + if (!(np = pnv_pci_get_phb_node(dev))) - return -ENODEV; + return; /* Do not fail when CAPP timebase sync is not supported by OPAL */ of_node_get(np); if (! of_get_property(np, "ibm,capp-timebase-sync", NULL)) { of_node_put(np); - pr_err("PSL: Timebase sync: OPAL support missing\n"); - return 0; + dev_info(&dev->dev, "PSL timebase inactive: OPAL support missing\n"); + return; } of_node_put(np); @@ -428,8 +430,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) do { msleep(1); if (retry++ > 5) { - pr_err("PSL: Timebase sync: giving up!\n"); - return -EIO; + dev_info(&dev->dev, "PSL timebase can't synchronize\n"); + return; } psl_tb = cxl_p1_read(adapter, CXL_PSL_Timebase); delta = mftb() - psl_tb; @@ -437,7 +439,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) delta = -delta; } while (tb_to_ns(delta) > 16000); - return 0; + adapter->psl_timebase_synced = true; + return; } static int init_implementation_afu_regs(struct cxl_afu *afu) @@ -1183,8 +1186,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_ON))) goto err; - if ((rc = cxl_setup_psl_timebase(adapter, dev))) - goto err; + /* Ignore error, adapter init is not dependant on timebase sync */ + cxl_setup_psl_timebase(adapter, dev); if ((rc = cxl_native_register_psl_err_irq(adapter))) goto err; diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 25913c08794c..b043c20f158f 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c @@ -57,6 +57,15 @@ static ssize_t image_loaded_show(struct device *device, return scnprintf(buf, PAGE_SIZE, "factory\n"); } +static ssize_t psl_timebase_synced_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct cxl *adapter = to_cxl_adapter(device); + + return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced); +} + static ssize_t reset_adapter_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count) @@ -142,6 +151,7 @@ static struct device_attribute adapter_attrs[] = { __ATTR_RO(psl_revision), __ATTR_RO(base_image), __ATTR_RO(image_loaded), + __ATTR_RO(psl_timebase_synced), __ATTR_RW(load_image_on_perst), __ATTR_RW(perst_reloads_same_image), __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), -- GitLab From 4aec6ec0da9c72c0fa1a5b0d1133707481347bb3 Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Tue, 19 Apr 2016 18:34:24 +0200 Subject: [PATCH 3977/9938] cxl: Increase timeout for detection of AFU mmio hang PSL designers recommend a larger value for the mmio hang pulse, 256 us instead of 1 us. The CAIA architecture states that it needs to be smaller than 1/2 of the RTOS timeout set in the PHB for outbound non-posted transactions, which is still (easily) the case here. Signed-off-by: Frederic Barrat Acked-by: Ian Munsie Tested-by: Frank Haverkamp Tested-by: Manoj Kumar Signed-off-by: Michael Ellerman --- drivers/misc/cxl/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index c6d5cf5e3793..a08fcc888a71 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -375,8 +375,10 @@ static int init_implementation_adapter_regs(struct cxl *adapter, struct pci_dev return -ENODEV; } + psl_dsnctl = 0x0000900000000000ULL; /* pteupd ttype, scdone */ + psl_dsnctl |= (0x2ULL << (63-38)); /* MMIO hang pulse: 256 us */ /* Tell PSL where to route data to */ - psl_dsnctl = 0x0000900002000000ULL | (chipid << (63-5)); + psl_dsnctl |= (chipid << (63-5)); psl_dsnctl |= (capp_unit_id << (63-13)); cxl_p1_write(adapter, CXL_PSL_DSNDCTL, psl_dsnctl); -- GitLab From a7ab72390b77062420fb50e4451f71c9321aae05 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:38:50 +0200 Subject: [PATCH 3978/9938] i2c: mux: add common data for every i2c-mux instance All i2c-muxes have a parent adapter and one or many child adapters. A mux also has some means of selection. Previously, this was stored per child adapter, but it is only needed to keep track of this per mux. Add an i2c mux core, that keeps track of this consistently. Also add some glue for users of the old interface, which will create one implicit mux core per child adapter. Signed-off-by: Peter Rosin Tested-by: Antti Palosaari Tested-by: Crestez Dan Leonard Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-mux.c | 175 ++++++++++++++++++++++++++++++---------- include/linux/i2c-mux.h | 34 ++++++++ 2 files changed, 168 insertions(+), 41 deletions(-) diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index d4022878b2f0..5ce1b0704cb5 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -28,33 +28,34 @@ #include /* multiplexer per channel data */ +struct i2c_mux_priv_old { + void *mux_priv; + int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id); + int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id); +}; + struct i2c_mux_priv { struct i2c_adapter adap; struct i2c_algorithm algo; - - struct i2c_adapter *parent; - struct device *mux_dev; - void *mux_priv; + struct i2c_mux_core *muxc; u32 chan_id; - - int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id); - int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id); }; static int i2c_mux_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_adapter *parent = priv->parent; + struct i2c_mux_core *muxc = priv->muxc; + struct i2c_adapter *parent = muxc->parent; int ret; /* Switch to the right mux port and perform the transfer. */ - ret = priv->select(parent, priv->mux_priv, priv->chan_id); + ret = muxc->select(muxc, priv->chan_id); if (ret >= 0) ret = __i2c_transfer(parent, msgs, num); - if (priv->deselect) - priv->deselect(parent, priv->mux_priv, priv->chan_id); + if (muxc->deselect) + muxc->deselect(muxc, priv->chan_id); return ret; } @@ -65,17 +66,18 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, int size, union i2c_smbus_data *data) { struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_adapter *parent = priv->parent; + struct i2c_mux_core *muxc = priv->muxc; + struct i2c_adapter *parent = muxc->parent; int ret; /* Select the right mux port and perform the transfer. */ - ret = priv->select(parent, priv->mux_priv, priv->chan_id); + ret = muxc->select(muxc, priv->chan_id); if (ret >= 0) ret = parent->algo->smbus_xfer(parent, addr, flags, read_write, command, size, data); - if (priv->deselect) - priv->deselect(parent, priv->mux_priv, priv->chan_id); + if (muxc->deselect) + muxc->deselect(muxc, priv->chan_id); return ret; } @@ -84,7 +86,7 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, static u32 i2c_mux_functionality(struct i2c_adapter *adap) { struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_adapter *parent = priv->parent; + struct i2c_adapter *parent = priv->muxc->parent; return parent->algo->functionality(parent); } @@ -102,6 +104,20 @@ static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent) return class; } +static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc); + + return priv->select(muxc->parent, priv->mux_priv, chan); +} + +static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan) +{ + struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc); + + return priv->deselect(muxc->parent, priv->mux_priv, chan); +} + struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, struct device *mux_dev, void *mux_priv, u32 force_nr, u32 chan_id, @@ -111,21 +127,77 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, int (*deselect) (struct i2c_adapter *, void *, u32)) { + struct i2c_mux_core *muxc; + struct i2c_mux_priv_old *priv; + int ret; + + muxc = i2c_mux_alloc(parent, mux_dev, 1, sizeof(*priv), 0, + i2c_mux_select, i2c_mux_deselect); + if (!muxc) + return NULL; + + priv = i2c_mux_priv(muxc); + priv->select = select; + priv->deselect = deselect; + priv->mux_priv = mux_priv; + + ret = i2c_mux_add_adapter(muxc, force_nr, chan_id, class); + if (ret) { + devm_kfree(mux_dev, muxc); + return NULL; + } + + return muxc->adapter[0]; +} +EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); + +struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, + struct device *dev, int max_adapters, + int sizeof_priv, u32 flags, + int (*select)(struct i2c_mux_core *, u32), + int (*deselect)(struct i2c_mux_core *, u32)) +{ + struct i2c_mux_core *muxc; + + muxc = devm_kzalloc(dev, sizeof(*muxc) + + max_adapters * sizeof(muxc->adapter[0]) + + sizeof_priv, GFP_KERNEL); + if (!muxc) + return NULL; + if (sizeof_priv) + muxc->priv = &muxc->adapter[max_adapters]; + + muxc->parent = parent; + muxc->dev = dev; + muxc->select = select; + muxc->deselect = deselect; + muxc->max_adapters = max_adapters; + + return muxc; +} +EXPORT_SYMBOL_GPL(i2c_mux_alloc); + +int i2c_mux_add_adapter(struct i2c_mux_core *muxc, + u32 force_nr, u32 chan_id, + unsigned int class) +{ + struct i2c_adapter *parent = muxc->parent; struct i2c_mux_priv *priv; char symlink_name[20]; int ret; - priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL); + if (muxc->num_adapters >= muxc->max_adapters) { + dev_err(muxc->dev, "No room for more i2c-mux adapters\n"); + return -EINVAL; + } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) - return NULL; + return -ENOMEM; /* Set up private adapter data */ - priv->parent = parent; - priv->mux_dev = mux_dev; - priv->mux_priv = mux_priv; + priv->muxc = muxc; priv->chan_id = chan_id; - priv->select = select; - priv->deselect = deselect; /* Need to do algo dynamically because we don't know ahead * of time what sort of physical adapter we'll be dealing with. @@ -159,11 +231,11 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, * Try to populate the mux adapter's of_node, expands to * nothing if !CONFIG_OF. */ - if (mux_dev->of_node) { + if (muxc->dev->of_node) { struct device_node *child; u32 reg; - for_each_child_of_node(mux_dev->of_node, child) { + for_each_child_of_node(muxc->dev->of_node, child) { ret = of_property_read_u32(child, "reg", ®); if (ret) continue; @@ -177,8 +249,9 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, /* * Associate the mux channel with an ACPI node. */ - if (has_acpi_companion(mux_dev)) - acpi_preset_companion(&priv->adap.dev, ACPI_COMPANION(mux_dev), + if (has_acpi_companion(muxc->dev)) + acpi_preset_companion(&priv->adap.dev, + ACPI_COMPANION(muxc->dev), chan_id); if (force_nr) { @@ -192,33 +265,53 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, "failed to add mux-adapter (error=%d)\n", ret); kfree(priv); - return NULL; + return ret; } - WARN(sysfs_create_link(&priv->adap.dev.kobj, &mux_dev->kobj, "mux_device"), - "can't create symlink to mux device\n"); + WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj, + "mux_device"), + "can't create symlink to mux device\n"); snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id); - WARN(sysfs_create_link(&mux_dev->kobj, &priv->adap.dev.kobj, symlink_name), - "can't create symlink for channel %u\n", chan_id); + WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj, + symlink_name), + "can't create symlink for channel %u\n", chan_id); dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", i2c_adapter_id(&priv->adap)); - return &priv->adap; + muxc->adapter[muxc->num_adapters++] = &priv->adap; + return 0; } -EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); +EXPORT_SYMBOL_GPL(i2c_mux_add_adapter); -void i2c_del_mux_adapter(struct i2c_adapter *adap) +void i2c_mux_del_adapters(struct i2c_mux_core *muxc) { - struct i2c_mux_priv *priv = adap->algo_data; char symlink_name[20]; - snprintf(symlink_name, sizeof(symlink_name), "channel-%u", priv->chan_id); - sysfs_remove_link(&priv->mux_dev->kobj, symlink_name); + while (muxc->num_adapters) { + struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters]; + struct i2c_mux_priv *priv = adap->algo_data; + + muxc->adapter[muxc->num_adapters] = NULL; + + snprintf(symlink_name, sizeof(symlink_name), + "channel-%u", priv->chan_id); + sysfs_remove_link(&muxc->dev->kobj, symlink_name); + + sysfs_remove_link(&priv->adap.dev.kobj, "mux_device"); + i2c_del_adapter(adap); + kfree(priv); + } +} +EXPORT_SYMBOL_GPL(i2c_mux_del_adapters); + +void i2c_del_mux_adapter(struct i2c_adapter *adap) +{ + struct i2c_mux_priv *priv = adap->algo_data; + struct i2c_mux_core *muxc = priv->muxc; - sysfs_remove_link(&priv->adap.dev.kobj, "mux_device"); - i2c_del_adapter(adap); - kfree(priv); + i2c_mux_del_adapters(muxc); + devm_kfree(muxc->dev, muxc); } EXPORT_SYMBOL_GPL(i2c_del_mux_adapter); diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h index b5f9a007a3ab..71ac1b3f4f68 100644 --- a/include/linux/i2c-mux.h +++ b/include/linux/i2c-mux.h @@ -27,6 +27,31 @@ #ifdef __KERNEL__ +struct i2c_mux_core { + struct i2c_adapter *parent; + struct device *dev; + + void *priv; + + int (*select)(struct i2c_mux_core *, u32 chan_id); + int (*deselect)(struct i2c_mux_core *, u32 chan_id); + + int num_adapters; + int max_adapters; + struct i2c_adapter *adapter[0]; +}; + +struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, + struct device *dev, int max_adapters, + int sizeof_priv, u32 flags, + int (*select)(struct i2c_mux_core *, u32), + int (*deselect)(struct i2c_mux_core *, u32)); + +static inline void *i2c_mux_priv(struct i2c_mux_core *muxc) +{ + return muxc->priv; +} + /* * Called to create a i2c bus on a multiplexed bus segment. * The mux_dev and chan_id parameters are passed to the select @@ -41,8 +66,17 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, void *mux_dev, u32 chan_id), int (*deselect) (struct i2c_adapter *, void *mux_dev, u32 chan_id)); +/* + * Called to create an i2c bus on a multiplexed bus segment. + * The chan_id parameter is passed to the select and deselect + * callback functions to perform hardware-specific mux control. + */ +int i2c_mux_add_adapter(struct i2c_mux_core *muxc, + u32 force_nr, u32 chan_id, + unsigned int class); void i2c_del_mux_adapter(struct i2c_adapter *adap); +void i2c_mux_del_adapters(struct i2c_mux_core *muxc); #endif /* __KERNEL__ */ -- GitLab From bb44814763ff4f69d83818342c2b4ba09efbab0f Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:39:05 +0200 Subject: [PATCH 3979/9938] i2c: i2c-mux-gpio: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-mux-gpio.c | 55 +++++++++++++------------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index b8e11c16d98c..f6270ee934f9 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -18,8 +18,6 @@ #include struct gpiomux { - struct i2c_adapter *parent; - struct i2c_adapter **adap; /* child busses */ struct i2c_mux_gpio_platform_data data; unsigned gpio_base; }; @@ -33,18 +31,18 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val) val & (1 << i)); } -static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan) +static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan) { - struct gpiomux *mux = data; + struct gpiomux *mux = i2c_mux_priv(muxc); i2c_mux_gpio_set(mux, chan); return 0; } -static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan) +static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan) { - struct gpiomux *mux = data; + struct gpiomux *mux = i2c_mux_priv(muxc); i2c_mux_gpio_set(mux, mux->data.idle); @@ -136,19 +134,15 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, static int i2c_mux_gpio_probe(struct platform_device *pdev) { + struct i2c_mux_core *muxc; struct gpiomux *mux; struct i2c_adapter *parent; - int (*deselect) (struct i2c_adapter *, void *, u32); unsigned initial_state, gpio_base; int i, ret; mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); - if (!mux) { - dev_err(&pdev->dev, "Cannot allocate gpiomux structure"); + if (!mux) return -ENOMEM; - } - - platform_set_drvdata(pdev, mux); if (!dev_get_platdata(&pdev->dev)) { ret = i2c_mux_gpio_probe_dt(mux, pdev); @@ -180,24 +174,23 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) if (!parent) return -EPROBE_DEFER; - mux->parent = parent; - mux->gpio_base = gpio_base; - - mux->adap = devm_kzalloc(&pdev->dev, - sizeof(*mux->adap) * mux->data.n_values, - GFP_KERNEL); - if (!mux->adap) { - dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure"); + muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0, + i2c_mux_gpio_select, NULL); + if (!muxc) { ret = -ENOMEM; goto alloc_failed; } + muxc->priv = mux; + + platform_set_drvdata(pdev, muxc); + + mux->gpio_base = gpio_base; if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) { initial_state = mux->data.idle; - deselect = i2c_mux_gpio_deselect; + muxc->deselect = i2c_mux_gpio_deselect; } else { initial_state = mux->data.values[0]; - deselect = NULL; } for (i = 0; i < mux->data.n_gpios; i++) { @@ -223,11 +216,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0; unsigned int class = mux->data.classes ? mux->data.classes[i] : 0; - mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, - mux->data.values[i], class, - i2c_mux_gpio_select, deselect); - if (!mux->adap[i]) { - ret = -ENODEV; + ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class); + if (ret) { dev_err(&pdev->dev, "Failed to add adapter %d\n", i); goto add_adapter_failed; } @@ -239,8 +229,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) return 0; add_adapter_failed: - for (; i > 0; i--) - i2c_del_mux_adapter(mux->adap[i - 1]); + i2c_mux_del_adapters(muxc); i = mux->data.n_gpios; err_request_gpio: for (; i > 0; i--) @@ -253,16 +242,16 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) static int i2c_mux_gpio_remove(struct platform_device *pdev) { - struct gpiomux *mux = platform_get_drvdata(pdev); + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct gpiomux *mux = i2c_mux_priv(muxc); int i; - for (i = 0; i < mux->data.n_values; i++) - i2c_del_mux_adapter(mux->adap[i]); + i2c_mux_del_adapters(muxc); for (i = 0; i < mux->data.n_gpios; i++) gpio_free(mux->gpio_base + mux->data.gpios[i]); - i2c_put_adapter(mux->parent); + i2c_put_adapter(muxc->parent); return 0; } -- GitLab From 4bbe7fb0a23244937be315866ae166ba74e32d06 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:39:31 +0200 Subject: [PATCH 3980/9938] i2c: i2c-mux-pinctrl: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-mux-pinctrl.c | 83 +++++++++++------------------ 1 file changed, 30 insertions(+), 53 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index b5a982ba8898..1b8dc711815e 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -26,34 +26,29 @@ #include struct i2c_mux_pinctrl { - struct device *dev; struct i2c_mux_pinctrl_platform_data *pdata; struct pinctrl *pinctrl; struct pinctrl_state **states; struct pinctrl_state *state_idle; - struct i2c_adapter *parent; - struct i2c_adapter **busses; }; -static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data, - u32 chan) +static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan) { - struct i2c_mux_pinctrl *mux = data; + struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc); return pinctrl_select_state(mux->pinctrl, mux->states[chan]); } -static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data, - u32 chan) +static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan) { - struct i2c_mux_pinctrl *mux = data; + struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc); return pinctrl_select_state(mux->pinctrl, mux->state_idle); } #ifdef CONFIG_OF static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, - struct platform_device *pdev) + struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; int num_names, i, ret; @@ -64,15 +59,12 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, return 0; mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL); - if (!mux->pdata) { - dev_err(mux->dev, - "Cannot allocate i2c_mux_pinctrl_platform_data\n"); + if (!mux->pdata) return -ENOMEM; - } num_names = of_property_count_strings(np, "pinctrl-names"); if (num_names < 0) { - dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", + dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n", num_names); return num_names; } @@ -80,23 +72,22 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata->pinctrl_states) * num_names, GFP_KERNEL); - if (!mux->pdata->pinctrl_states) { - dev_err(mux->dev, "Cannot allocate pinctrl_states\n"); + if (!mux->pdata->pinctrl_states) return -ENOMEM; - } for (i = 0; i < num_names; i++) { ret = of_property_read_string_index(np, "pinctrl-names", i, &mux->pdata->pinctrl_states[mux->pdata->bus_count]); if (ret < 0) { - dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", + dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n", ret); return ret; } if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count], "idle")) { if (i != num_names - 1) { - dev_err(mux->dev, "idle state must be last\n"); + dev_err(&pdev->dev, + "idle state must be last\n"); return -EINVAL; } mux->pdata->pinctrl_state_idle = "idle"; @@ -107,13 +98,13 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, adapter_np = of_parse_phandle(np, "i2c-parent", 0); if (!adapter_np) { - dev_err(mux->dev, "Cannot parse i2c-parent\n"); + dev_err(&pdev->dev, "Cannot parse i2c-parent\n"); return -ENODEV; } adapter = of_find_i2c_adapter_by_node(adapter_np); of_node_put(adapter_np); if (!adapter) { - dev_err(mux->dev, "Cannot find parent bus\n"); + dev_err(&pdev->dev, "Cannot find parent bus\n"); return -EPROBE_DEFER; } mux->pdata->parent_bus_num = i2c_adapter_id(adapter); @@ -131,19 +122,15 @@ static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, static int i2c_mux_pinctrl_probe(struct platform_device *pdev) { + struct i2c_mux_core *muxc; struct i2c_mux_pinctrl *mux; - int (*deselect)(struct i2c_adapter *, void *, u32); int i, ret; mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); if (!mux) { - dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n"); ret = -ENOMEM; goto err; } - platform_set_drvdata(pdev, mux); - - mux->dev = &pdev->dev; mux->pdata = dev_get_platdata(&pdev->dev); if (!mux->pdata) { @@ -166,14 +153,15 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) goto err; } - mux->busses = devm_kzalloc(&pdev->dev, - sizeof(*mux->busses) * mux->pdata->bus_count, - GFP_KERNEL); - if (!mux->busses) { - dev_err(&pdev->dev, "Cannot allocate busses\n"); + muxc = i2c_mux_alloc(NULL, &pdev->dev, mux->pdata->bus_count, 0, 0, + i2c_mux_pinctrl_select, NULL); + if (!muxc) { ret = -ENOMEM; goto err; } + muxc->priv = mux; + + platform_set_drvdata(pdev, muxc); mux->pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(mux->pinctrl)) { @@ -203,13 +191,11 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) goto err; } - deselect = i2c_mux_pinctrl_deselect; - } else { - deselect = NULL; + muxc->deselect = i2c_mux_pinctrl_deselect; } - mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num); - if (!mux->parent) { + muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num); + if (!muxc->parent) { dev_err(&pdev->dev, "Parent adapter (%d) not found\n", mux->pdata->parent_bus_num); ret = -EPROBE_DEFER; @@ -220,12 +206,8 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) u32 bus = mux->pdata->base_bus_num ? (mux->pdata->base_bus_num + i) : 0; - mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, - mux, bus, i, 0, - i2c_mux_pinctrl_select, - deselect); - if (!mux->busses[i]) { - ret = -ENODEV; + ret = i2c_mux_add_adapter(muxc, bus, i, 0); + if (ret) { dev_err(&pdev->dev, "Failed to add adapter %d\n", i); goto err_del_adapter; } @@ -234,23 +216,18 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) return 0; err_del_adapter: - for (; i > 0; i--) - i2c_del_mux_adapter(mux->busses[i - 1]); - i2c_put_adapter(mux->parent); + i2c_mux_del_adapters(muxc); + i2c_put_adapter(muxc->parent); err: return ret; } static int i2c_mux_pinctrl_remove(struct platform_device *pdev) { - struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < mux->pdata->bus_count; i++) - i2c_del_mux_adapter(mux->busses[i]); - - i2c_put_adapter(mux->parent); + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + i2c_mux_del_adapters(muxc); + i2c_put_adapter(muxc->parent); return 0; } -- GitLab From 8aacd90166f6b60df83e0907b1e931e3971a92ab Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:39:46 +0200 Subject: [PATCH 3981/9938] i2c: i2c-arb-gpio-challenge: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 47 +++++++++------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index 402e3a6c671a..a90bbc4037dd 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -28,8 +28,6 @@ /** * struct i2c_arbitrator_data - Driver data for I2C arbitrator * - * @parent: Parent adapter - * @child: Child bus * @our_gpio: GPIO we'll use to claim. * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == * this then consider it released. @@ -42,8 +40,6 @@ */ struct i2c_arbitrator_data { - struct i2c_adapter *parent; - struct i2c_adapter *child; int our_gpio; int our_gpio_release; int their_gpio; @@ -59,9 +55,9 @@ struct i2c_arbitrator_data { * * Use the GPIO-based signalling protocol; return -EBUSY if we fail. */ -static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan) +static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan) { - const struct i2c_arbitrator_data *arb = data; + const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); unsigned long stop_retry, stop_time; /* Start a round of trying to claim the bus */ @@ -93,7 +89,7 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan) /* Give up, release our claim */ gpio_set_value(arb->our_gpio, arb->our_gpio_release); udelay(arb->slew_delay_us); - dev_err(&adap->dev, "Could not claim bus, timeout\n"); + dev_err(muxc->dev, "Could not claim bus, timeout\n"); return -EBUSY; } @@ -102,10 +98,9 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan) * * Release the I2C bus using the GPIO-based signalling protocol. */ -static int i2c_arbitrator_deselect(struct i2c_adapter *adap, void *data, - u32 chan) +static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan) { - const struct i2c_arbitrator_data *arb = data; + const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); /* Release the bus and wait for the other master to notice */ gpio_set_value(arb->our_gpio, arb->our_gpio_release); @@ -119,6 +114,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct device_node *parent_np; + struct i2c_mux_core *muxc; struct i2c_arbitrator_data *arb; enum of_gpio_flags gpio_flags; unsigned long out_init; @@ -134,12 +130,13 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) return -EINVAL; } - arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL); - if (!arb) { - dev_err(dev, "Cannot allocate i2c_arbitrator_data\n"); + muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), 0, + i2c_arbitrator_select, i2c_arbitrator_deselect); + if (!muxc) return -ENOMEM; - } - platform_set_drvdata(pdev, arb); + arb = i2c_mux_priv(muxc); + + platform_set_drvdata(pdev, muxc); /* Request GPIOs */ ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags); @@ -196,21 +193,18 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) dev_err(dev, "Cannot parse i2c-parent\n"); return -EINVAL; } - arb->parent = of_get_i2c_adapter_by_node(parent_np); + muxc->parent = of_get_i2c_adapter_by_node(parent_np); of_node_put(parent_np); - if (!arb->parent) { + if (!muxc->parent) { dev_err(dev, "Cannot find parent bus\n"); return -EPROBE_DEFER; } /* Actually add the mux adapter */ - arb->child = i2c_add_mux_adapter(arb->parent, dev, arb, 0, 0, 0, - i2c_arbitrator_select, - i2c_arbitrator_deselect); - if (!arb->child) { + ret = i2c_mux_add_adapter(muxc, 0, 0, 0); + if (ret) { dev_err(dev, "Failed to add adapter\n"); - ret = -ENODEV; - i2c_put_adapter(arb->parent); + i2c_put_adapter(muxc->parent); } return ret; @@ -218,11 +212,10 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) static int i2c_arbitrator_remove(struct platform_device *pdev) { - struct i2c_arbitrator_data *arb = platform_get_drvdata(pdev); - - i2c_del_mux_adapter(arb->child); - i2c_put_adapter(arb->parent); + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + i2c_mux_del_adapters(muxc); + i2c_put_adapter(muxc->parent); return 0; } -- GitLab From ab88b97c69ce375ef10c551133d6d19ffd55d763 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:40:02 +0200 Subject: [PATCH 3982/9938] i2c: i2c-mux-pca9541: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-mux-pca9541.c | 58 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index d0ba424adebc..3cb8af635db5 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -73,7 +73,7 @@ #define SELECT_DELAY_LONG 1000 struct pca9541 { - struct i2c_adapter *mux_adap; + struct i2c_client *client; unsigned long select_timeout; unsigned long arb_timeout; }; @@ -217,7 +217,8 @@ static const u8 pca9541_control[16] = { */ static int pca9541_arbitrate(struct i2c_client *client) { - struct pca9541 *data = i2c_get_clientdata(client); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); int reg; reg = pca9541_reg_read(client, PCA9541_CONTROL); @@ -285,9 +286,10 @@ static int pca9541_arbitrate(struct i2c_client *client) return 0; } -static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan) +static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) { - struct pca9541 *data = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; int ret; unsigned long timeout = jiffies + ARB2_TIMEOUT; /* give up after this time */ @@ -309,9 +311,11 @@ static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan) return -ETIMEDOUT; } -static int pca9541_release_chan(struct i2c_adapter *adap, - void *client, u32 chan) +static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) { + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + pca9541_release_bus(client); return 0; } @@ -324,20 +328,13 @@ static int pca9541_probe(struct i2c_client *client, { struct i2c_adapter *adap = client->adapter; struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct i2c_mux_core *muxc; struct pca9541 *data; int force; - int ret = -ENODEV; + int ret; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) - goto err; - - data = kzalloc(sizeof(struct pca9541), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } - - i2c_set_clientdata(client, data); + return -ENODEV; /* * I2C accesses are unprotected here. @@ -352,34 +349,33 @@ static int pca9541_probe(struct i2c_client *client, force = 0; if (pdata) force = pdata->modes[0].adap_id; - data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client, - force, 0, 0, - pca9541_select_chan, - pca9541_release_chan); + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0, + pca9541_select_chan, pca9541_release_chan); + if (!muxc) + return -ENOMEM; - if (data->mux_adap == NULL) { + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) { dev_err(&client->dev, "failed to register master selector\n"); - goto exit_free; + return ret; } dev_info(&client->dev, "registered master selector for I2C %s\n", client->name); return 0; - -exit_free: - kfree(data); -err: - return ret; } static int pca9541_remove(struct i2c_client *client) { - struct pca9541 *data = i2c_get_clientdata(client); - - i2c_del_mux_adapter(data->mux_adap); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); - kfree(data); + i2c_mux_del_adapters(muxc); return 0; } -- GitLab From 7fcac980717532a20762e03f0d228bfc58393ed3 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:40:14 +0200 Subject: [PATCH 3983/9938] i2c: i2c-mux-pca954x: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Add a mask to handle the case where not all child adapters should cause a mux deselect to happen, now that there is a common deselect op for all child adapters. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-mux-pca954x.c | 61 ++++++++++++++--------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index acfcef3d4068..528e755c468f 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -60,9 +60,10 @@ enum pca_type { struct pca954x { enum pca_type type; - struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; u8 last_chan; /* last register value */ + u8 deselect; + struct i2c_client *client; }; struct chip_desc { @@ -146,10 +147,10 @@ static int pca954x_reg_write(struct i2c_adapter *adap, return ret; } -static int pca954x_select_chan(struct i2c_adapter *adap, - void *client, u32 chan) +static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) { - struct pca954x *data = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; const struct chip_desc *chip = &chips[data->type]; u8 regval; int ret = 0; @@ -162,21 +163,24 @@ static int pca954x_select_chan(struct i2c_adapter *adap, /* Only select the channel if its different from the last channel */ if (data->last_chan != regval) { - ret = pca954x_reg_write(adap, client, regval); + ret = pca954x_reg_write(muxc->parent, client, regval); data->last_chan = regval; } return ret; } -static int pca954x_deselect_mux(struct i2c_adapter *adap, - void *client, u32 chan) +static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) { - struct pca954x *data = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + if (!(data->deselect & (1 << chan))) + return 0; /* Deselect active channel */ data->last_chan = 0; - return pca954x_reg_write(adap, client, data->last_chan); + return pca954x_reg_write(muxc->parent, client, data->last_chan); } /* @@ -191,17 +195,22 @@ static int pca954x_probe(struct i2c_client *client, bool idle_disconnect_dt; struct gpio_desc *gpio; int num, force, class; + struct i2c_mux_core *muxc; struct pca954x *data; int ret; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) return -ENODEV; - data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL); - if (!data) + muxc = i2c_mux_alloc(adap, &client->dev, + PCA954X_MAX_NCHANS, sizeof(*data), 0, + pca954x_select_chan, pca954x_deselect_mux); + if (!muxc) return -ENOMEM; + data = i2c_mux_priv(muxc); - i2c_set_clientdata(client, data); + i2c_set_clientdata(client, muxc); + data->client = client; /* Get the mux out of reset if a reset GPIO is specified. */ gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); @@ -238,16 +247,13 @@ static int pca954x_probe(struct i2c_client *client, /* discard unconfigured channels */ break; idle_disconnect_pd = pdata->modes[num].deselect_on_exit; + data->deselect |= (idle_disconnect_pd + || idle_disconnect_dt) << num; } - data->virt_adaps[num] = - i2c_add_mux_adapter(adap, &client->dev, client, - force, num, class, pca954x_select_chan, - (idle_disconnect_pd || idle_disconnect_dt) - ? pca954x_deselect_mux : NULL); + ret = i2c_mux_add_adapter(muxc, force, num, class); - if (data->virt_adaps[num] == NULL) { - ret = -ENODEV; + if (ret) { dev_err(&client->dev, "failed to register multiplexed adapter" " %d as bus %d\n", num, force); @@ -263,23 +269,15 @@ static int pca954x_probe(struct i2c_client *client, return 0; virt_reg_failed: - for (num--; num >= 0; num--) - i2c_del_mux_adapter(data->virt_adaps[num]); + i2c_mux_del_adapters(muxc); return ret; } static int pca954x_remove(struct i2c_client *client) { - struct pca954x *data = i2c_get_clientdata(client); - const struct chip_desc *chip = &chips[data->type]; - int i; - - for (i = 0; i < chip->nchans; ++i) - if (data->virt_adaps[i]) { - i2c_del_mux_adapter(data->virt_adaps[i]); - data->virt_adaps[i] = NULL; - } + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + i2c_mux_del_adapters(muxc); return 0; } @@ -287,7 +285,8 @@ static int pca954x_remove(struct i2c_client *client) static int pca954x_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct pca954x *data = i2c_get_clientdata(client); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); data->last_chan = 0; return i2c_smbus_write_byte(client, 0); -- GitLab From 193304aef8523265884f08144b1f98ad272e2d7e Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:40:27 +0200 Subject: [PATCH 3984/9938] i2c: i2c-mux-reg: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-mux-reg.c | 69 ++++++++++++--------------------- 1 file changed, 25 insertions(+), 44 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index 5fbd5bd0878f..6773cadf7c9f 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -21,8 +21,6 @@ #include struct regmux { - struct i2c_adapter *parent; - struct i2c_adapter **adap; /* child busses */ struct i2c_mux_reg_platform_data data; }; @@ -64,18 +62,16 @@ static int i2c_mux_reg_set(const struct regmux *mux, unsigned int chan_id) return 0; } -static int i2c_mux_reg_select(struct i2c_adapter *adap, void *data, - unsigned int chan) +static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan) { - struct regmux *mux = data; + struct regmux *mux = i2c_mux_priv(muxc); return i2c_mux_reg_set(mux, chan); } -static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data, - unsigned int chan) +static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan) { - struct regmux *mux = data; + struct regmux *mux = i2c_mux_priv(muxc); if (mux->data.idle_in_use) return i2c_mux_reg_set(mux, mux->data.idle); @@ -85,7 +81,7 @@ static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data, #ifdef CONFIG_OF static int i2c_mux_reg_probe_dt(struct regmux *mux, - struct platform_device *pdev) + struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct device_node *adapter_np, *child; @@ -107,7 +103,6 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux, if (!adapter) return -EPROBE_DEFER; - mux->parent = adapter; mux->data.parent = i2c_adapter_id(adapter); put_device(&adapter->dev); @@ -161,7 +156,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux, } #else static int i2c_mux_reg_probe_dt(struct regmux *mux, - struct platform_device *pdev) + struct platform_device *pdev) { return 0; } @@ -169,10 +164,10 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux, static int i2c_mux_reg_probe(struct platform_device *pdev) { + struct i2c_mux_core *muxc; struct regmux *mux; struct i2c_adapter *parent; struct resource *res; - int (*deselect)(struct i2c_adapter *, void *, u32); unsigned int class; int i, ret, nr; @@ -180,17 +175,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) if (!mux) return -ENOMEM; - platform_set_drvdata(pdev, mux); - if (dev_get_platdata(&pdev->dev)) { memcpy(&mux->data, dev_get_platdata(&pdev->dev), sizeof(mux->data)); - - parent = i2c_get_adapter(mux->data.parent); - if (!parent) - return -EPROBE_DEFER; - - mux->parent = parent; } else { ret = i2c_mux_reg_probe_dt(mux, pdev); if (ret < 0) { @@ -199,6 +186,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) } } + parent = i2c_get_adapter(mux->data.parent); + if (!parent) + return -EPROBE_DEFER; + if (!mux->data.reg) { dev_info(&pdev->dev, "Register not set, using platform resource\n"); @@ -215,55 +206,45 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) return -EINVAL; } - mux->adap = devm_kzalloc(&pdev->dev, - sizeof(*mux->adap) * mux->data.n_values, - GFP_KERNEL); - if (!mux->adap) { - dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure"); + muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0, + i2c_mux_reg_select, NULL); + if (!muxc) return -ENOMEM; - } + muxc->priv = mux; + + platform_set_drvdata(pdev, muxc); if (mux->data.idle_in_use) - deselect = i2c_mux_reg_deselect; - else - deselect = NULL; + muxc->deselect = i2c_mux_reg_deselect; for (i = 0; i < mux->data.n_values; i++) { nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0; class = mux->data.classes ? mux->data.classes[i] : 0; - mux->adap[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, mux, - nr, mux->data.values[i], - class, i2c_mux_reg_select, - deselect); - if (!mux->adap[i]) { - ret = -ENODEV; + ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class); + if (ret) { dev_err(&pdev->dev, "Failed to add adapter %d\n", i); goto add_adapter_failed; } } dev_dbg(&pdev->dev, "%d port mux on %s adapter\n", - mux->data.n_values, mux->parent->name); + mux->data.n_values, muxc->parent->name); return 0; add_adapter_failed: - for (; i > 0; i--) - i2c_del_mux_adapter(mux->adap[i - 1]); + i2c_mux_del_adapters(muxc); return ret; } static int i2c_mux_reg_remove(struct platform_device *pdev) { - struct regmux *mux = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < mux->data.n_values; i++) - i2c_del_mux_adapter(mux->adap[i]); + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); - i2c_put_adapter(mux->parent); + i2c_mux_del_adapters(muxc); + i2c_put_adapter(muxc->parent); return 0; } -- GitLab From 51f97f6dd73d9349f8e6a1d36ac5f7371d275fb3 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:40:49 +0200 Subject: [PATCH 3985/9938] iio: imu: inv_mpu6050: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Acked-by: Jonathan Cameron Tested-by: Crestez Dan Leonard Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 2 +- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 1 - drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 33 +++++++++++----------- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 3 +- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c index 2771106fd650..f62b8bd9ad7e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c @@ -183,7 +183,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client) } else return 0; /* no secondary addr, which is OK */ } - st->mux_client = i2c_new_device(st->mux_adapter, &info); + st->mux_client = i2c_new_device(st->muxc->adapter[0], &info); if (!st->mux_client) return -ENODEV; } diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index d192953e9a38..0c2bded2b5b7 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "inv_mpu_iio.h" diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index f581256d9d4c..3a078df84224 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include "inv_mpu_iio.h" @@ -52,10 +51,9 @@ static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client, return 0; } -static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, - u32 chan_id) +static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id) { - struct i2c_client *client = mux_priv; + struct i2c_client *client = i2c_mux_priv(muxc); struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); struct inv_mpu6050_state *st = iio_priv(indio_dev); int ret = 0; @@ -84,10 +82,9 @@ static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, return ret; } -static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, - void *mux_priv, u32 chan_id) +static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id) { - struct i2c_client *client = mux_priv; + struct i2c_client *client = i2c_mux_priv(muxc); struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); struct inv_mpu6050_state *st = iio_priv(indio_dev); @@ -136,16 +133,18 @@ static int inv_mpu_probe(struct i2c_client *client, return result; st = iio_priv(dev_get_drvdata(&client->dev)); - st->mux_adapter = i2c_add_mux_adapter(client->adapter, - &client->dev, - client, - 0, 0, 0, - inv_mpu6050_select_bypass, - inv_mpu6050_deselect_bypass); - if (!st->mux_adapter) { - result = -ENODEV; + st->muxc = i2c_mux_alloc(client->adapter, &client->dev, + 1, 0, 0, + inv_mpu6050_select_bypass, + inv_mpu6050_deselect_bypass); + if (!st->muxc) { + result = -ENOMEM; goto out_unreg_device; } + st->muxc->priv = dev_get_drvdata(&client->dev); + result = i2c_mux_add_adapter(st->muxc, 0, 0, 0); + if (result) + goto out_unreg_device; result = inv_mpu_acpi_create_mux_client(client); if (result) @@ -154,7 +153,7 @@ static int inv_mpu_probe(struct i2c_client *client, return 0; out_del_mux: - i2c_del_mux_adapter(st->mux_adapter); + i2c_mux_del_adapters(st->muxc); out_unreg_device: inv_mpu_core_remove(&client->dev); return result; @@ -166,7 +165,7 @@ static int inv_mpu_remove(struct i2c_client *client) struct inv_mpu6050_state *st = iio_priv(indio_dev); inv_mpu_acpi_delete_mux_client(client); - i2c_del_mux_adapter(st->mux_adapter); + i2c_mux_del_adapters(st->muxc); return inv_mpu_core_remove(&client->dev); } diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index e302a49703bf..bb3cef6d7059 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -11,6 +11,7 @@ * GNU General Public License for more details. */ #include +#include #include #include #include @@ -127,7 +128,7 @@ struct inv_mpu6050_state { const struct inv_mpu6050_hw *hw; enum inv_devices chip_type; spinlock_t time_stamp_lock; - struct i2c_adapter *mux_adapter; + struct i2c_mux_core *muxc; struct i2c_client *mux_client; unsigned int powerup_count; struct inv_mpu6050_platform_data plat_data; -- GitLab From e00fed40f48e43bdb5e018156d077c65b61f93bf Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:41:02 +0200 Subject: [PATCH 3986/9938] [media] m88ds3103: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select op to be in terms of the i2c mux core instead of the child adapter. Tested-by: Antti Palosaari Reviewed-by: Antti Palosaari Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/media/dvb-frontends/m88ds3103.c | 19 +++++++++++-------- drivers/media/dvb-frontends/m88ds3103_priv.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index 76883600ec6f..5557ef8fc704 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -1251,9 +1251,9 @@ static void m88ds3103_release(struct dvb_frontend *fe) i2c_unregister_device(client); } -static int m88ds3103_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) +static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan) { - struct m88ds3103_dev *dev = mux_priv; + struct m88ds3103_dev *dev = i2c_mux_priv(muxc); struct i2c_client *client = dev->client; int ret; struct i2c_msg msg = { @@ -1374,7 +1374,7 @@ static struct i2c_adapter *m88ds3103_get_i2c_adapter(struct i2c_client *client) dev_dbg(&client->dev, "\n"); - return dev->i2c_adapter; + return dev->muxc->adapter[0]; } static int m88ds3103_probe(struct i2c_client *client, @@ -1467,13 +1467,16 @@ static int m88ds3103_probe(struct i2c_client *client, goto err_kfree; /* create mux i2c adapter for tuner */ - dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, &client->dev, - dev, 0, 0, 0, m88ds3103_select, - NULL); - if (dev->i2c_adapter == NULL) { + dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0, + m88ds3103_select, NULL); + if (!dev->muxc) { ret = -ENOMEM; goto err_kfree; } + dev->muxc->priv = dev; + ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + if (ret) + goto err_kfree; /* create dvb_frontend */ memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); @@ -1502,7 +1505,7 @@ static int m88ds3103_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); - i2c_del_mux_adapter(dev->i2c_adapter); + i2c_mux_del_adapters(dev->muxc); kfree(dev); return 0; diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h index eee8c22c51ec..c5b4e177c6ea 100644 --- a/drivers/media/dvb-frontends/m88ds3103_priv.h +++ b/drivers/media/dvb-frontends/m88ds3103_priv.h @@ -42,7 +42,7 @@ struct m88ds3103_dev { enum fe_status fe_status; u32 dvbv3_ber; /* for old DVBv3 API read_ber */ bool warm; /* FW running */ - struct i2c_adapter *i2c_adapter; + struct i2c_mux_core *muxc; /* auto detect chip id to do different config */ u8 chip_id; /* main mclk is calculated for M88RS6000 dynamically */ -- GitLab From a0119159e66e2e67154384d7e20a0ebf46cfa32b Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:41:13 +0200 Subject: [PATCH 3987/9938] [media] rtl2830: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select op to be in terms of the i2c mux core instead of the child adapter. Tested-by: Antti Palosaari Reviewed-by: Antti Palosaari Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/media/dvb-frontends/rtl2830.c | 20 ++++++++++++-------- drivers/media/dvb-frontends/rtl2830_priv.h | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 3f96429af0e5..d25d1e0cd4ca 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -677,9 +677,9 @@ static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int on * adapter lock is already taken by tuner driver. * Gate is closed automatically after single I2C transfer. */ -static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) +static int rtl2830_select(struct i2c_mux_core *muxc, u32 chan_id) { - struct i2c_client *client = mux_priv; + struct i2c_client *client = i2c_mux_priv(muxc); struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; @@ -712,7 +712,7 @@ static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client) dev_dbg(&client->dev, "\n"); - return dev->adapter; + return dev->muxc->adapter[0]; } /* @@ -865,12 +865,16 @@ static int rtl2830_probe(struct i2c_client *client, goto err_regmap_exit; /* create muxed i2c adapter for tuner */ - dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, - client, 0, 0, 0, rtl2830_select, NULL); - if (dev->adapter == NULL) { - ret = -ENODEV; + dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0, + rtl2830_select, NULL); + if (!dev->muxc) { + ret = -ENOMEM; goto err_regmap_exit; } + dev->muxc->priv = client; + ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + if (ret) + goto err_regmap_exit; /* create dvb frontend */ memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops)); @@ -903,7 +907,7 @@ static int rtl2830_remove(struct i2c_client *client) /* stop statistics polling */ cancel_delayed_work_sync(&dev->stat_work); - i2c_del_mux_adapter(dev->adapter); + i2c_mux_del_adapters(dev->muxc); regmap_exit(dev->regmap); kfree(dev); diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index cf793f39a09b..da4909543da2 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -29,7 +29,7 @@ struct rtl2830_dev { struct rtl2830_platform_data *pdata; struct i2c_client *client; struct regmap *regmap; - struct i2c_adapter *adapter; + struct i2c_mux_core *muxc; struct dvb_frontend fe; bool sleeping; unsigned long filters; -- GitLab From cddcc40b1b1553010acb89add84c64b5d123ec94 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:41:25 +0200 Subject: [PATCH 3988/9938] [media] rtl2832: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Tested-by: Antti Palosaari Reviewed-by: Antti Palosaari Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/media/dvb-frontends/rtl2832.c | 25 ++++++++++++---------- drivers/media/dvb-frontends/rtl2832_priv.h | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 7c96f7679669..1b23788797b5 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -847,9 +847,9 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) dev_dbg(&client->dev, "failed=%d\n", ret); } -static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) +static int rtl2832_select(struct i2c_mux_core *muxc, u32 chan_id) { - struct rtl2832_dev *dev = mux_priv; + struct rtl2832_dev *dev = i2c_mux_priv(muxc); struct i2c_client *client = dev->client; int ret; @@ -870,10 +870,9 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) return ret; } -static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, - u32 chan_id) +static int rtl2832_deselect(struct i2c_mux_core *muxc, u32 chan_id) { - struct rtl2832_dev *dev = mux_priv; + struct rtl2832_dev *dev = i2c_mux_priv(muxc); schedule_delayed_work(&dev->i2c_gate_work, usecs_to_jiffies(100)); return 0; @@ -1059,7 +1058,7 @@ static struct i2c_adapter *rtl2832_get_i2c_adapter(struct i2c_client *client) struct rtl2832_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - return dev->i2c_adapter_tuner; + return dev->muxc->adapter[0]; } static int rtl2832_slave_ts_ctrl(struct i2c_client *client, bool enable) @@ -1242,12 +1241,16 @@ static int rtl2832_probe(struct i2c_client *client, goto err_regmap_exit; /* create muxed i2c adapter for demod tuner bus */ - dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, dev, - 0, 0, 0, rtl2832_select, rtl2832_deselect); - if (dev->i2c_adapter_tuner == NULL) { - ret = -ENODEV; + dev->muxc = i2c_mux_alloc(i2c, &i2c->dev, 1, 0, 0, + rtl2832_select, rtl2832_deselect); + if (!dev->muxc) { + ret = -ENOMEM; goto err_regmap_exit; } + dev->muxc->priv = dev; + ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + if (ret) + goto err_regmap_exit; /* create dvb_frontend */ memcpy(&dev->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); @@ -1282,7 +1285,7 @@ static int rtl2832_remove(struct i2c_client *client) cancel_delayed_work_sync(&dev->i2c_gate_work); - i2c_del_mux_adapter(dev->i2c_adapter_tuner); + i2c_mux_del_adapters(dev->muxc); regmap_exit(dev->regmap); diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 6b875f462f8b..d8f97d14f6fd 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -36,7 +36,7 @@ struct rtl2832_dev { struct mutex regmap_mutex; struct regmap_config regmap_config; struct regmap *regmap; - struct i2c_adapter *i2c_adapter_tuner; + struct i2c_mux_core *muxc; struct dvb_frontend fe; enum fe_status fe_status; u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */ -- GitLab From 58d7b541dd96535b03cc9dd13fe9efff2a5402e0 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:41:36 +0200 Subject: [PATCH 3989/9938] [media] si2168: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select/deselect ops to be in terms of the i2c mux core instead of the child adapter. Tested-by: Antti Palosaari Reviewed-by: Antti Palosaari Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/media/dvb-frontends/si2168.c | 25 ++++++++++++++--------- drivers/media/dvb-frontends/si2168_priv.h | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 821a8f481507..5583827c386e 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -615,9 +615,9 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe, * We must use unlocked I2C I/O because I2C adapter lock is already taken * by the caller (usually tuner driver). */ -static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) +static int si2168_select(struct i2c_mux_core *muxc, u32 chan) { - struct i2c_client *client = mux_priv; + struct i2c_client *client = i2c_mux_priv(muxc); int ret; struct si2168_cmd cmd; @@ -635,9 +635,9 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) return ret; } -static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) +static int si2168_deselect(struct i2c_mux_core *muxc, u32 chan) { - struct i2c_client *client = mux_priv; + struct i2c_client *client = i2c_mux_priv(muxc); int ret; struct si2168_cmd cmd; @@ -709,17 +709,22 @@ static int si2168_probe(struct i2c_client *client, } /* create mux i2c adapter for tuner */ - dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, - client, 0, 0, 0, si2168_select, si2168_deselect); - if (dev->adapter == NULL) { - ret = -ENODEV; + dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, + 1, 0, 0, + si2168_select, si2168_deselect); + if (!dev->muxc) { + ret = -ENOMEM; goto err_kfree; } + dev->muxc->priv = client; + ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + if (ret) + goto err_kfree; /* create dvb_frontend */ memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); dev->fe.demodulator_priv = client; - *config->i2c_adapter = dev->adapter; + *config->i2c_adapter = dev->muxc->adapter[0]; *config->fe = &dev->fe; dev->ts_mode = config->ts_mode; dev->ts_clock_inv = config->ts_clock_inv; @@ -743,7 +748,7 @@ static int si2168_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); - i2c_del_mux_adapter(dev->adapter); + i2c_mux_del_adapters(dev->muxc); dev->fe.ops.release = NULL; dev->fe.demodulator_priv = NULL; diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index c07e6fe2cb10..165bf1412063 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -29,7 +29,7 @@ /* state struct */ struct si2168_dev { - struct i2c_adapter *adapter; + struct i2c_mux_core *muxc; struct dvb_frontend fe; enum fe_delivery_system delivery_system; enum fe_status fe_status; -- GitLab From 05e0dfd0311bd6dd3cdb6cb32acd1e701c451e9b Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:42:17 +0200 Subject: [PATCH 3990/9938] [media] cx231xx: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select op to be in terms of the i2c mux core instead of the child adapter. Tested-by: Antti Palosaari Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/media/usb/cx231xx/cx231xx-core.c | 6 ++- drivers/media/usb/cx231xx/cx231xx-i2c.c | 47 ++++++++++++------------ drivers/media/usb/cx231xx/cx231xx.h | 4 +- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index f497888d94bf..f7aac2abd783 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -1304,6 +1304,9 @@ int cx231xx_dev_init(struct cx231xx *dev) cx231xx_i2c_register(&dev->i2c_bus[1]); cx231xx_i2c_register(&dev->i2c_bus[2]); + errCode = cx231xx_i2c_mux_create(dev); + if (errCode < 0) + return errCode; cx231xx_i2c_mux_register(dev, 0); cx231xx_i2c_mux_register(dev, 1); @@ -1426,8 +1429,7 @@ EXPORT_SYMBOL_GPL(cx231xx_dev_init); void cx231xx_dev_uninit(struct cx231xx *dev) { /* Un Initialize I2C bus */ - cx231xx_i2c_mux_unregister(dev, 1); - cx231xx_i2c_mux_unregister(dev, 0); + cx231xx_i2c_mux_unregister(dev); cx231xx_i2c_unregister(&dev->i2c_bus[2]); cx231xx_i2c_unregister(&dev->i2c_bus[1]); cx231xx_i2c_unregister(&dev->i2c_bus[0]); diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c index a29c345b027d..473cd3433fe5 100644 --- a/drivers/media/usb/cx231xx/cx231xx-i2c.c +++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c @@ -557,40 +557,41 @@ int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) * cx231xx_i2c_mux_select() * switch i2c master number 1 between port1 and port3 */ -static int cx231xx_i2c_mux_select(struct i2c_adapter *adap, - void *mux_priv, u32 chan_id) +static int cx231xx_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan_id) { - struct cx231xx *dev = mux_priv; + struct cx231xx *dev = i2c_mux_priv(muxc); return cx231xx_enable_i2c_port_3(dev, chan_id); } +int cx231xx_i2c_mux_create(struct cx231xx *dev) +{ + dev->muxc = i2c_mux_alloc(&dev->i2c_bus[1].i2c_adap, dev->dev, 2, 0, 0, + cx231xx_i2c_mux_select, NULL); + if (!dev->muxc) + return -ENOMEM; + dev->muxc->priv = dev; + return 0; +} + int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no) { - struct i2c_adapter *i2c_parent = &dev->i2c_bus[1].i2c_adap; - /* what is the correct mux_dev? */ - struct device *mux_dev = dev->dev; - - dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent, - mux_dev, - dev /* mux_priv */, - 0, - mux_no /* chan_id */, - 0 /* class */, - &cx231xx_i2c_mux_select, - NULL); - - if (!dev->i2c_mux_adap[mux_no]) + int rc; + + rc = i2c_mux_add_adapter(dev->muxc, + 0, + mux_no /* chan_id */, + 0 /* class */); + if (rc) dev_warn(dev->dev, "i2c mux %d register FAILED\n", mux_no); - return 0; + return rc; } -void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no) +void cx231xx_i2c_mux_unregister(struct cx231xx *dev) { - i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]); - dev->i2c_mux_adap[mux_no] = NULL; + i2c_mux_del_adapters(dev->muxc); } struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port) @@ -603,9 +604,9 @@ struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port) case I2C_2: return &dev->i2c_bus[2].i2c_adap; case I2C_1_MUX_1: - return dev->i2c_mux_adap[0]; + return dev->muxc->adapter[0]; case I2C_1_MUX_3: - return dev->i2c_mux_adap[1]; + return dev->muxc->adapter[1]; default: return NULL; } diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 69f6d20870f5..90c867683076 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -624,6 +624,7 @@ struct cx231xx { /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ struct cx231xx_i2c i2c_bus[3]; + struct i2c_mux_core *muxc; struct i2c_adapter *i2c_mux_adap[2]; unsigned int xc_fw_load_done:1; @@ -760,8 +761,9 @@ int cx231xx_reset_analog_tuner(struct cx231xx *dev); void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port); int cx231xx_i2c_register(struct cx231xx_i2c *bus); int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); +int cx231xx_i2c_mux_create(struct cx231xx *dev); int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no); -void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no); +void cx231xx_i2c_mux_unregister(struct cx231xx *dev); struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port); /* Internal block control functions */ -- GitLab From b6e3b7171b1e416963e36bb91ff6cce1caaaf675 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 20 Apr 2016 08:42:47 +0200 Subject: [PATCH 3991/9938] of/unittest: convert to use an explicit i2c mux core Allocate an explicit i2c mux core to handle parent and child adapters etc. Update the select op to be in terms of the i2c mux core instead of the child adapter. Acked-by: Rob Herring Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/of/unittest.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index e986e6ee52e0..c1ebbfb79453 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1692,13 +1692,7 @@ static struct i2c_driver unittest_i2c_dev_driver = { #if IS_BUILTIN(CONFIG_I2C_MUX) -struct unittest_i2c_mux_data { - int nchans; - struct i2c_adapter *adap[]; -}; - -static int unittest_i2c_mux_select_chan(struct i2c_adapter *adap, - void *client, u32 chan) +static int unittest_i2c_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) { return 0; } @@ -1706,11 +1700,11 @@ static int unittest_i2c_mux_select_chan(struct i2c_adapter *adap, static int unittest_i2c_mux_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int ret, i, nchans, size; + int ret, i, nchans; struct device *dev = &client->dev; struct i2c_adapter *adap = to_i2c_adapter(dev->parent); struct device_node *np = client->dev.of_node, *child; - struct unittest_i2c_mux_data *stm; + struct i2c_mux_core *muxc; u32 reg, max_reg; dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); @@ -1734,25 +1728,20 @@ static int unittest_i2c_mux_probe(struct i2c_client *client, return -EINVAL; } - size = offsetof(struct unittest_i2c_mux_data, adap[nchans]); - stm = devm_kzalloc(dev, size, GFP_KERNEL); - if (!stm) { - dev_err(dev, "Out of memory\n"); + muxc = i2c_mux_alloc(adap, dev, nchans, 0, 0, + unittest_i2c_mux_select_chan, NULL); + if (!muxc) return -ENOMEM; - } - stm->nchans = nchans; for (i = 0; i < nchans; i++) { - stm->adap[i] = i2c_add_mux_adapter(adap, dev, client, - 0, i, 0, unittest_i2c_mux_select_chan, NULL); - if (!stm->adap[i]) { + ret = i2c_mux_add_adapter(muxc, 0, i, 0); + if (ret) { dev_err(dev, "Failed to register mux #%d\n", i); - for (i--; i >= 0; i--) - i2c_del_mux_adapter(stm->adap[i]); + i2c_mux_del_adapters(muxc); return -ENODEV; } } - i2c_set_clientdata(client, stm); + i2c_set_clientdata(client, muxc); return 0; }; @@ -1761,12 +1750,10 @@ static int unittest_i2c_mux_remove(struct i2c_client *client) { struct device *dev = &client->dev; struct device_node *np = client->dev.of_node; - struct unittest_i2c_mux_data *stm = i2c_get_clientdata(client); - int i; + struct i2c_mux_core *muxc = i2c_get_clientdata(client); dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); - for (i = stm->nchans - 1; i >= 0; i--) - i2c_del_mux_adapter(stm->adap[i]); + i2c_mux_del_adapters(muxc); return 0; } -- GitLab From 23fe440c59b9f08afe108e7ec7b6714cb2a3b955 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 2 Mar 2016 15:14:22 +0100 Subject: [PATCH 3992/9938] i2c: mux: drop old unused i2c-mux api All i2c mux users are using an explicit i2c mux core, drop support for implicit i2c mux cores. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-mux.c | 63 ----------------------------------------- include/linux/i2c-mux.h | 15 ---------- 2 files changed, 78 deletions(-) diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 5ce1b0704cb5..25e9336b0e6e 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -28,12 +28,6 @@ #include /* multiplexer per channel data */ -struct i2c_mux_priv_old { - void *mux_priv; - int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id); - int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id); -}; - struct i2c_mux_priv { struct i2c_adapter adap; struct i2c_algorithm algo; @@ -104,53 +98,6 @@ static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent) return class; } -static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan) -{ - struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc); - - return priv->select(muxc->parent, priv->mux_priv, chan); -} - -static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan) -{ - struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc); - - return priv->deselect(muxc->parent, priv->mux_priv, chan); -} - -struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, - struct device *mux_dev, - void *mux_priv, u32 force_nr, u32 chan_id, - unsigned int class, - int (*select) (struct i2c_adapter *, - void *, u32), - int (*deselect) (struct i2c_adapter *, - void *, u32)) -{ - struct i2c_mux_core *muxc; - struct i2c_mux_priv_old *priv; - int ret; - - muxc = i2c_mux_alloc(parent, mux_dev, 1, sizeof(*priv), 0, - i2c_mux_select, i2c_mux_deselect); - if (!muxc) - return NULL; - - priv = i2c_mux_priv(muxc); - priv->select = select; - priv->deselect = deselect; - priv->mux_priv = mux_priv; - - ret = i2c_mux_add_adapter(muxc, force_nr, chan_id, class); - if (ret) { - devm_kfree(mux_dev, muxc); - return NULL; - } - - return muxc->adapter[0]; -} -EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); - struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, struct device *dev, int max_adapters, int sizeof_priv, u32 flags, @@ -305,16 +252,6 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc) } EXPORT_SYMBOL_GPL(i2c_mux_del_adapters); -void i2c_del_mux_adapter(struct i2c_adapter *adap) -{ - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - - i2c_mux_del_adapters(muxc); - devm_kfree(muxc->dev, muxc); -} -EXPORT_SYMBOL_GPL(i2c_del_mux_adapter); - MODULE_AUTHOR("Rodolfo Giometti "); MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses"); MODULE_LICENSE("GPL v2"); diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h index 71ac1b3f4f68..2fa93fe1345e 100644 --- a/include/linux/i2c-mux.h +++ b/include/linux/i2c-mux.h @@ -52,20 +52,6 @@ static inline void *i2c_mux_priv(struct i2c_mux_core *muxc) return muxc->priv; } -/* - * Called to create a i2c bus on a multiplexed bus segment. - * The mux_dev and chan_id parameters are passed to the select - * and deselect callback functions to perform hardware-specific - * mux control. - */ -struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, - struct device *mux_dev, - void *mux_priv, u32 force_nr, u32 chan_id, - unsigned int class, - int (*select) (struct i2c_adapter *, - void *mux_dev, u32 chan_id), - int (*deselect) (struct i2c_adapter *, - void *mux_dev, u32 chan_id)); /* * Called to create an i2c bus on a multiplexed bus segment. * The chan_id parameter is passed to the select and deselect @@ -75,7 +61,6 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, u32 force_nr, u32 chan_id, unsigned int class); -void i2c_del_mux_adapter(struct i2c_adapter *adap); void i2c_mux_del_adapters(struct i2c_mux_core *muxc); #endif /* __KERNEL__ */ -- GitLab From 5c0e03cd9f10d541b69b667a2b1b8980f196f432 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 22 Apr 2016 15:59:25 +0300 Subject: [PATCH 3993/9938] Bluetooth: Add defines for SPI and I2C Extend the set of possible HCI bus types with SPI and I2C. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 5d38d980b89d..eefcf3e96421 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -61,6 +61,8 @@ #define HCI_RS232 4 #define HCI_PCI 5 #define HCI_SDIO 6 +#define HCI_SPI 7 +#define HCI_I2C 8 /* HCI controller types */ #define HCI_BREDR 0x00 -- GitLab From 710a1d54452afbc9435bdb3f48f81f6801db14d6 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 22 Apr 2016 15:17:28 +0200 Subject: [PATCH 3994/9938] spi: spi-orion: enable the driver on ARCH_MVEBU platforms The SPI controller managed by the spi-orion is used on the new ARM64 Marvell Armada 7K/8K SoCs. In order to allow this driver to be built for this platform, we allow it to be selected for ARCH_MVEBU=y configurations. Signed-off-by: Thomas Petazzoni Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9d8c84bb1544..720c5ee515c7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -432,7 +432,7 @@ config SPI_OMAP_100K config SPI_ORION tristate "Orion SPI master" - depends on PLAT_ORION || COMPILE_TEST + depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST help This enables using the SPI master controller on the Orion chips. -- GitLab From 6b126245907a77642efe738f81837dc58e3a5d28 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 13 Apr 2016 12:24:58 +0000 Subject: [PATCH 3995/9938] ARM: dts: socfpga: Add samtec VIN|ING board Add support for board based on the popular Altera Cyclone V SoC. This board has the following properties: - 1 GiB of DRAM - 1 Gigabit ethernet - 1 USB gadget port - 1 USB host port with an on-board hub - 2 QSPI NORs connected to the Cadence QSPI core - Multiple I2C EEPROMs and one I2C temperature sensor Signed-off-by: Marek Vasut Cc: Dinh Nguyen Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/socfpga_cyclone5_vining_fpga.dts | 310 ++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..c2c9c048569c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -608,6 +608,7 @@ dtb-$(CONFIG_ARCH_SOCFPGA) += \ socfpga_cyclone5_de0_sockit.dtb \ socfpga_cyclone5_sockit.dtb \ socfpga_cyclone5_socrates.dtb \ + socfpga_cyclone5_vining_fpga.dtb \ socfpga_vt.dtb dtb-$(CONFIG_ARCH_SPEAR13XX) += \ spear1310-evb.dtb \ diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts new file mode 100644 index 000000000000..a3601e4c0a2e --- /dev/null +++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2015 Marek Vasut + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "socfpga_cyclone5.dtsi" +#include +#include + +/ { + model = "samtec VIN|ING FPGA"; + compatible = "altr,socfpga-cyclone5", "altr,socfpga"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory { + name = "memory"; + device_type = "memory"; + reg = <0x0 0x40000000>; /* 1GB */ + }; + + aliases { + /* + * This allow the ethaddr uboot environment variable contents + * to be added to the gmac1 device tree blob. + */ + ethernet0 = &gmac1; + }; + + leds { + compatible = "gpio-leds"; + + hps_led0 { + label = "hps:green:led0"; /* ALIVE_LED_GR */ + gpios = <&portb 19 0>; /* HPS_GPIO48 */ + linux,default-trigger = "heartbeat"; + }; + + hps_led1 { + label = "hps:red:led0"; /* ALIVE_LED_RD */ + gpios = <&portb 24 0>; /* HPS_GPIO53 */ + linux,default-trigger = "none"; + }; + + hps_led2 { + label = "hps:green:led1"; /* LINK2HOST_LED_GR */ + gpios = <&portb 25 0>; /* HPS_GPIO54 */ + linux,default-trigger = "heartbeat"; + }; + + hps_led3 { + label = "hps:red:led1"; /* LINK2HOST_LED_RD */ + gpios = <&portc 7 0>; /* HPS_GPIO65 */ + linux,default-trigger = "none"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + hps_temp0 { + label = "BTN_0"; /* TEMP_OS */ + gpios = <&portc 18 GPIO_ACTIVE_LOW>; /* HPS_GPIO60 */ + linux,code = ; + }; + + hps_hkey0 { + label = "BTN_1"; /* DIS_PWR */ + gpios = <&portc 19 GPIO_ACTIVE_LOW>; /* HPS_GPIO61 */ + linux,code = ; + }; + + hps_hkey1 { + label = "hps_hkey1"; /* POWER_DOWN */ + gpios = <&portc 20 GPIO_ACTIVE_LOW>; /* HPS_GPIO62 */ + linux,code = ; + }; + }; + + regulator-usb-nrst { + compatible = "regulator-fixed"; + regulator-name = "usb_nrst"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&portb 5 GPIO_ACTIVE_HIGH>; + startup-delay-us = <70000>; + enable-active-high; + regulator-always-on; + }; +}; + +&gmac1 { + status = "okay"; + phy-mode = "rgmii"; + + snps,reset-gpio = <&porta 0 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <10000 10000 10000>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy1: ethernet-phy@1 { + reg = <1>; + rxd0-skew-ps = <0>; + rxd1-skew-ps = <0>; + rxd2-skew-ps = <0>; + rxd3-skew-ps = <0>; + txen-skew-ps = <0>; + txc-skew-ps = <2600>; + rxdv-skew-ps = <0>; + rxc-skew-ps = <2000>; + }; + }; +}; + +&gpio0 { /* GPIO 0..29 */ + status = "okay"; +}; + +&gpio1 { /* GPIO 30..57 */ + status = "okay"; +}; + +&gpio2 { /* GPIO 58..66 (HLGPI 0..13 at offset 13) */ + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + gpio: pca9557@1f { + compatible = "nxp,pca9557"; + reg = <0x1f>; + gpio-controller; + #gpio-cells = <2>; + }; + + temp: lm75@48 { + compatible = "lm75"; + reg = <0x48>; + }; + + at24@50 { + compatible = "at24,24c01"; + pagesize = <8>; + reg = <0x50>; + }; + + i2cswitch@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + + i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + + i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + + i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + eeprom@51 { + compatible = "at,24c01"; + pagesize = <8>; + reg = <0x51>; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <100000>; + + at24@50 { + compatible = "at24,24c02"; + pagesize = <8>; + reg = <0x50>; + }; +}; + +&usb0 { + dr_mode = "host"; + status = "okay"; +}; + +&usb1 { + dr_mode = "peripheral"; + status = "okay"; +}; -- GitLab From 989ffc7bd6b0f5ea3423631981f87fde495a8acb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Apr 2016 12:55:24 +0300 Subject: [PATCH 3996/9938] spi: pic32-sqi: silence array overflow warning We read one element beyond the end of the array when we access "rdesc[i + 1]" so it causes a static checker warning. It's harmless because we write over it again on the next line. But let's just silence the warning. Signed-off-by: Dan Carpenter Reviewed-by: Purna Chandra Mandal Signed-off-by: Mark Brown --- drivers/spi/spi-pic32-sqi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index b21534782ada..74b9e684b10d 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -537,7 +537,7 @@ static int ring_desc_ring_alloc(struct pic32_sqi *sqi) } /* Prepare BD: chain to next BD(s) */ - for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT; i++) + for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT - 1; i++) bd[i].bd_nextp = rdesc[i + 1].bd_dma; bd[PESQI_BD_COUNT - 1].bd_nextp = 0; -- GitLab From ae48a35c408732413880d0ac0d6467baa5b3d68a Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Fri, 22 Apr 2016 14:16:26 +0100 Subject: [PATCH 3997/9938] ASoC: da7218: Update PLL ranges and dividers to improve locking The expected MCLK frequency ranges and the associated dividers are updated to improve PLL locking in a corner scenario, with low MCLK frequency near an input divider change boundary. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- sound/soc/codecs/da7218.c | 32 ++++++++++++++++---------------- sound/soc/codecs/da7218.h | 21 ++++++++++++--------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 93575f251866..99ce23e113bf 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -1868,27 +1868,27 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */ if (da7218->mclk_rate == 32768) { - indiv_bits = DA7218_PLL_INDIV_2_5_MHZ; - indiv = DA7218_PLL_INDIV_2_10_MHZ_VAL; + indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ; + indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL; } else if (da7218->mclk_rate < 2000000) { dev_err(codec->dev, "PLL input clock %d below valid range\n", da7218->mclk_rate); return -EINVAL; - } else if (da7218->mclk_rate <= 5000000) { - indiv_bits = DA7218_PLL_INDIV_2_5_MHZ; - indiv = DA7218_PLL_INDIV_2_10_MHZ_VAL; - } else if (da7218->mclk_rate <= 10000000) { - indiv_bits = DA7218_PLL_INDIV_5_10_MHZ; - indiv = DA7218_PLL_INDIV_2_10_MHZ_VAL; - } else if (da7218->mclk_rate <= 20000000) { - indiv_bits = DA7218_PLL_INDIV_10_20_MHZ; - indiv = DA7218_PLL_INDIV_10_20_MHZ_VAL; - } else if (da7218->mclk_rate <= 40000000) { - indiv_bits = DA7218_PLL_INDIV_20_40_MHZ; - indiv = DA7218_PLL_INDIV_20_40_MHZ_VAL; + } else if (da7218->mclk_rate <= 4500000) { + indiv_bits = DA7218_PLL_INDIV_2_TO_4_5_MHZ; + indiv = DA7218_PLL_INDIV_2_TO_4_5_MHZ_VAL; + } else if (da7218->mclk_rate <= 9000000) { + indiv_bits = DA7218_PLL_INDIV_4_5_TO_9_MHZ; + indiv = DA7218_PLL_INDIV_4_5_TO_9_MHZ_VAL; + } else if (da7218->mclk_rate <= 18000000) { + indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ; + indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL; + } else if (da7218->mclk_rate <= 36000000) { + indiv_bits = DA7218_PLL_INDIV_18_TO_36_MHZ; + indiv = DA7218_PLL_INDIV_18_TO_36_MHZ_VAL; } else if (da7218->mclk_rate <= 54000000) { - indiv_bits = DA7218_PLL_INDIV_40_54_MHZ; - indiv = DA7218_PLL_INDIV_40_54_MHZ_VAL; + indiv_bits = DA7218_PLL_INDIV_36_TO_54_MHZ; + indiv = DA7218_PLL_INDIV_36_TO_54_MHZ_VAL; } else { dev_err(codec->dev, "PLL input clock %d above valid range\n", da7218->mclk_rate); diff --git a/sound/soc/codecs/da7218.h b/sound/soc/codecs/da7218.h index c2c59049a2ad..477cd37723cf 100644 --- a/sound/soc/codecs/da7218.h +++ b/sound/soc/codecs/da7218.h @@ -876,15 +876,11 @@ /* DA7218_PLL_CTRL = 0x91 */ #define DA7218_PLL_INDIV_SHIFT 0 #define DA7218_PLL_INDIV_MASK (0x7 << 0) -#define DA7218_PLL_INDIV_2_5_MHZ (0x0 << 0) -#define DA7218_PLL_INDIV_5_10_MHZ (0x1 << 0) -#define DA7218_PLL_INDIV_10_20_MHZ (0x2 << 0) -#define DA7218_PLL_INDIV_20_40_MHZ (0x3 << 0) -#define DA7218_PLL_INDIV_40_54_MHZ (0x4 << 0) -#define DA7218_PLL_INDIV_2_10_MHZ_VAL 2 -#define DA7218_PLL_INDIV_10_20_MHZ_VAL 4 -#define DA7218_PLL_INDIV_20_40_MHZ_VAL 8 -#define DA7218_PLL_INDIV_40_54_MHZ_VAL 16 +#define DA7218_PLL_INDIV_2_TO_4_5_MHZ (0x0 << 0) +#define DA7218_PLL_INDIV_4_5_TO_9_MHZ (0x1 << 0) +#define DA7218_PLL_INDIV_9_TO_18_MHZ (0x2 << 0) +#define DA7218_PLL_INDIV_18_TO_36_MHZ (0x3 << 0) +#define DA7218_PLL_INDIV_36_TO_54_MHZ (0x4 << 0) #define DA7218_PLL_MCLK_SQR_EN_SHIFT 4 #define DA7218_PLL_MCLK_SQR_EN_MASK (0x1 << 4) #define DA7218_PLL_MODE_SHIFT 6 @@ -1336,6 +1332,13 @@ #define DA7218_PLL_FREQ_OUT_90316 90316800 #define DA7218_PLL_FREQ_OUT_98304 98304000 +/* PLL Frequency Dividers */ +#define DA7218_PLL_INDIV_2_TO_4_5_MHZ_VAL 1 +#define DA7218_PLL_INDIV_4_5_TO_9_MHZ_VAL 2 +#define DA7218_PLL_INDIV_9_TO_18_MHZ_VAL 4 +#define DA7218_PLL_INDIV_18_TO_36_MHZ_VAL 8 +#define DA7218_PLL_INDIV_36_TO_54_MHZ_VAL 16 + /* ALC Calibration */ #define DA7218_ALC_CALIB_DELAY_MIN 2500 #define DA7218_ALC_CALIB_DELAY_MAX 5000 -- GitLab From e7fc278ceb5725070e4e3ecfc2f259ab2101c30e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 22 Apr 2016 18:09:40 +0530 Subject: [PATCH 3998/9938] regulator: max77620: Add details of device specific ramp rate setting It is observed that the ramp rate measured on platform is not same as advertised ramp rate due to platform design variation. On this case, measured ramp rate is provided with property regulator-ramp-rate. For such cases, add DT property for device specific configurations. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- .../bindings/regulator/regulator-max77620.txt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/regulator-max77620.txt b/Documentation/devicetree/bindings/regulator/regulator-max77620.txt index b3c8ca672024..1c4bfe786736 100644 --- a/Documentation/devicetree/bindings/regulator/regulator-max77620.txt +++ b/Documentation/devicetree/bindings/regulator/regulator-max77620.txt @@ -94,6 +94,28 @@ Following are additional properties: This is applicable if suspend state FPS source is selected as FPS0, FPS1 or FPS2. +- maxim,ramp-rate-setting: integer, ramp rate(uV/us) setting to be + configured to the device. + The platform may have different ramp + rate than advertised ramp rate if it has + design variation from Maxim's + recommended. On this case, platform + specific ramp rate is used for ramp time + calculation and this property is used + for device register configurations. + The measured ramp rate of platform is + provided by the regulator-ramp-delay + as described in . + Maxim Max77620 supports following ramp + delay: + SD: 13.75mV/us, 27.5mV/us, 55mV/us + LDOs: 5mV/us, 100mV/us + +Note: If the measured ramp delay is same as advertised ramp delay then it is not +required to provide the ramp delay with property "maxim,ramp-rate-setting". The +ramp rate can be provided by the regulator-ramp-delay which will be used for +ramp time calculation for voltage change as well as for device configuration. Example: -------- -- GitLab From 5aa43599daddbe972f955b2357c76866a6f92973 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 22 Apr 2016 18:09:41 +0530 Subject: [PATCH 3999/9938] regulator: max77620: Add support for device specific ramp rate setting Maxim advertised the ramp rate of the rail with some recommended design specification like output capacitance of rail should be 2.2uF. This make sure that current change in the rail is within maximum current limit and hence meet the advertised ramp rate. If there is variation in design which causes the rail current to change more that maximum current limit then device applies the current limit. In this case, ramp rate is different than advertised ramp rate. Add device specific settings for ramp rate which need to be configure on device register when measure ramp rate on platform is deviated from advertised ramp rate. In this case, all delay time calculation for voltage change is done with measured ramp rate and device ramp rate is used for configuring the device register. If measured ramp rate in the platform is same as advertised ramp rate then regulator-ramp-delay is used for the device register configuration and ramp time calculation for voltage change. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/max77620-regulator.c | 83 +++++++++++++++++--------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c index 73a3356a5c19..321e804aeab0 100644 --- a/drivers/regulator/max77620-regulator.c +++ b/drivers/regulator/max77620-regulator.c @@ -81,6 +81,7 @@ struct max77620_regulator_pdata { int suspend_fps_pd_slot; int suspend_fps_pu_slot; int current_mode; + int ramp_rate_setting; }; struct max77620_regulator { @@ -307,6 +308,43 @@ static int max77620_read_slew_rate(struct max77620_regulator *pmic, int id) return 0; } +static int max77620_set_slew_rate(struct max77620_regulator *pmic, int id, + int slew_rate) +{ + struct max77620_regulator_info *rinfo = pmic->rinfo[id]; + unsigned int val; + int ret; + u8 mask; + + if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) { + if (slew_rate <= 13750) + val = 0; + else if (slew_rate <= 27500) + val = 1; + else if (slew_rate <= 55000) + val = 2; + else + val = 3; + val <<= MAX77620_SD_SR_SHIFT; + mask = MAX77620_SD_SR_MASK; + } else { + if (slew_rate <= 5000) + val = 1; + else + val = 0; + mask = MAX77620_LDO_SLEW_RATE_MASK; + } + + ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr, mask, val); + if (ret < 0) { + dev_err(pmic->dev, "Regulator %d slew rate set failed: %d\n", + id, ret); + return ret; + } + + return 0; +} + static int max77620_init_pmic(struct max77620_regulator *pmic, int id) { struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id]; @@ -351,6 +389,13 @@ static int max77620_init_pmic(struct max77620_regulator *pmic, int id) if (ret < 0) return ret; + if (rpdata->ramp_rate_setting) { + ret = max77620_set_slew_rate(pmic, id, + rpdata->ramp_rate_setting); + if (ret < 0) + return ret; + } + return 0; } @@ -502,35 +547,16 @@ static int max77620_regulator_set_ramp_delay(struct regulator_dev *rdev, { struct max77620_regulator *pmic = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); - struct max77620_regulator_info *rinfo = pmic->rinfo[id]; - int ret, val; - u8 mask; - - if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) { - if (ramp_delay <= 13750) - val = 0; - else if (ramp_delay <= 27500) - val = 1; - else if (ramp_delay <= 55000) - val = 2; - else - val = 3; - val <<= MAX77620_SD_SR_SHIFT; - mask = MAX77620_SD_SR_MASK; - } else { - if (ramp_delay <= 5000) - val = 1; - else - val = 0; - mask = MAX77620_LDO_SLEW_RATE_MASK; - } + struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id]; - ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr, mask, val); - if (ret < 0) - dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n", - rinfo->cfg_addr, ret); + /* Device specific ramp rate setting tells that platform has + * different ramp rate from advertised value. In this case, + * do not configure anything and just return success. + */ + if (rpdata->ramp_rate_setting) + return 0; - return ret; + return max77620_set_slew_rate(pmic, id, ramp_delay); } static int max77620_of_parse_cb(struct device_node *np, @@ -563,6 +589,9 @@ static int max77620_of_parse_cb(struct device_node *np, np, "maxim,suspend-fps-power-down-slot", &pval); rpdata->suspend_fps_pd_slot = (!ret) ? pval : -1; + ret = of_property_read_u32(np, "maxim,ramp-rate-setting", &pval); + rpdata->ramp_rate_setting = (!ret) ? pval : 0; + return max77620_init_pmic(pmic, desc->id); } -- GitLab From 298f2bc5db3851cf2e839a0025425256ef852139 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 15 Mar 2016 16:41:04 -0700 Subject: [PATCH 4000/9938] libnvdimm, pmem: kill pmem->ndns We can derive the common namespace from other information. We also do not need to cache it because all the usages are in slow paths. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/blk.c | 2 +- drivers/nvdimm/btt.c | 3 +-- drivers/nvdimm/nd.h | 2 +- drivers/nvdimm/pmem.c | 40 ++++++++++++++++++++++------------------ 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index e9ff9229d942..24649396b638 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -336,7 +336,7 @@ static int nd_blk_remove(struct device *dev) struct nd_blk_device *blk_dev = dev_get_drvdata(dev); if (is_nd_btt(dev)) - nvdimm_namespace_detach_btt(to_nd_btt(dev)->ndns); + nvdimm_namespace_detach_btt(to_nd_btt(dev)); else nd_blk_detach_disk(blk_dev); kfree(blk_dev); diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index f068b6513cd2..676c31a8fb6d 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -1406,9 +1406,8 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns) } EXPORT_SYMBOL(nvdimm_namespace_attach_btt); -int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns) +int nvdimm_namespace_detach_btt(struct nd_btt *nd_btt) { - struct nd_btt *nd_btt = to_nd_btt(ndns->claim); struct btt *btt = nd_btt->btt; btt_fini(btt); diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 875c524fafb0..b0a4ab91307b 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -263,7 +263,7 @@ struct resource *nvdimm_allocate_dpa(struct nvdimm_drvdata *ndd, resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns); struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev); int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns); -int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns); +int nvdimm_namespace_detach_btt(struct nd_btt *nd_btt); const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, char *name); void nvdimm_badblocks_populate(struct nd_region *nd_region, diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index f798899338ed..2b51d4d34207 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -35,7 +35,6 @@ struct pmem_device { struct request_queue *pmem_queue; struct gendisk *pmem_disk; - struct nd_namespace_common *ndns; /* One contiguous memory region per device */ phys_addr_t phys_addr; @@ -436,9 +435,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) return -ENXIO; } -static int nvdimm_namespace_detach_pfn(struct nd_namespace_common *ndns) +static int nvdimm_namespace_detach_pfn(struct nd_pfn *nd_pfn) { - struct nd_pfn *nd_pfn = to_nd_pfn(ndns->claim); struct pmem_device *pmem; /* free pmem disk */ @@ -537,7 +535,7 @@ static int __nvdimm_namespace_attach_pfn(struct nd_pfn *nd_pfn) return rc; err: - nvdimm_namespace_detach_pfn(ndns); + nvdimm_namespace_detach_pfn(nd_pfn); return rc; } @@ -573,7 +571,6 @@ static int nd_pmem_probe(struct device *dev) if (IS_ERR(pmem)) return PTR_ERR(pmem); - pmem->ndns = ndns; dev_set_drvdata(dev, pmem); ndns->rw_bytes = pmem_rw_bytes; if (devm_init_badblocks(dev, &pmem->bb)) @@ -607,9 +604,9 @@ static int nd_pmem_remove(struct device *dev) struct pmem_device *pmem = dev_get_drvdata(dev); if (is_nd_btt(dev)) - nvdimm_namespace_detach_btt(pmem->ndns); + nvdimm_namespace_detach_btt(to_nd_btt(dev)); else if (is_nd_pfn(dev)) - nvdimm_namespace_detach_pfn(pmem->ndns); + nvdimm_namespace_detach_pfn(to_nd_pfn(dev)); else pmem_detach_disk(pmem); @@ -618,26 +615,33 @@ static int nd_pmem_remove(struct device *dev) static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) { - struct pmem_device *pmem = dev_get_drvdata(dev); - struct nd_namespace_common *ndns = pmem->ndns; struct nd_region *nd_region = to_nd_region(dev->parent); - struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); - struct resource res = { - .start = nsio->res.start + pmem->data_offset, - .end = nsio->res.end, - }; + struct pmem_device *pmem = dev_get_drvdata(dev); + resource_size_t offset = 0, end_trunc = 0; + struct nd_namespace_common *ndns; + struct nd_namespace_io *nsio; + struct resource res; if (event != NVDIMM_REVALIDATE_POISON) return; - if (is_nd_pfn(dev)) { + if (is_nd_btt(dev)) { + struct nd_btt *nd_btt = to_nd_btt(dev); + + ndns = nd_btt->ndns; + } else if (is_nd_pfn(dev)) { struct nd_pfn *nd_pfn = to_nd_pfn(dev); struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; - res.start += __le32_to_cpu(pfn_sb->start_pad); - res.end -= __le32_to_cpu(pfn_sb->end_trunc); - } + ndns = nd_pfn->ndns; + offset = pmem->data_offset + __le32_to_cpu(pfn_sb->start_pad); + end_trunc = __le32_to_cpu(pfn_sb->end_trunc); + } else + ndns = to_ndns(dev); + nsio = to_nd_namespace_io(&ndns->dev); + res.start = nsio->res.start + offset; + res.end = nsio->res.end - end_trunc; nvdimm_badblocks_populate(nd_region, &pmem->bb, &res); } -- GitLab From bd032943b5b2b336994171dcebc11531a38b45ba Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Mar 2016 18:16:15 -0700 Subject: [PATCH 4001/9938] libnvdimm, pfn, convert nd_pfn_probe() to devm Pass the device performing the probe so we can use a devm allocation for the pfn superblock. Cc: Ross Zwisler Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/nd.h | 6 ++++-- drivers/nvdimm/pfn_devs.c | 27 +++++++++++++-------------- drivers/nvdimm/pmem.c | 30 +++++++++--------------------- 3 files changed, 26 insertions(+), 37 deletions(-) diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index b0a4ab91307b..c831caa3d60a 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -219,12 +219,14 @@ static inline struct device *nd_btt_create(struct nd_region *nd_region) struct nd_pfn *to_nd_pfn(struct device *dev); #if IS_ENABLED(CONFIG_NVDIMM_PFN) -int nd_pfn_probe(struct nd_namespace_common *ndns, void *drvdata); +int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns, + void *drvdata); bool is_nd_pfn(struct device *dev); struct device *nd_pfn_create(struct nd_region *nd_region); int nd_pfn_validate(struct nd_pfn *nd_pfn); #else -static inline int nd_pfn_probe(struct nd_namespace_common *ndns, void *drvdata) +static inline int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns, + void *drvdata) { return -ENODEV; } diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index e071e214feba..96aa5490c279 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -410,11 +410,12 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn) } EXPORT_SYMBOL(nd_pfn_validate); -int nd_pfn_probe(struct nd_namespace_common *ndns, void *drvdata) +int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns, + void *drvdata) { int rc; - struct device *dev; struct nd_pfn *nd_pfn; + struct device *pfn_dev; struct nd_pfn_sb *pfn_sb; struct nd_region *nd_region = to_nd_region(ndns->dev.parent); @@ -422,24 +423,22 @@ int nd_pfn_probe(struct nd_namespace_common *ndns, void *drvdata) return -ENODEV; nvdimm_bus_lock(&ndns->dev); - dev = __nd_pfn_create(nd_region, ndns); + pfn_dev = __nd_pfn_create(nd_region, ndns); nvdimm_bus_unlock(&ndns->dev); - if (!dev) + if (!pfn_dev) return -ENOMEM; - dev_set_drvdata(dev, drvdata); - pfn_sb = kzalloc(sizeof(*pfn_sb), GFP_KERNEL); - nd_pfn = to_nd_pfn(dev); + dev_set_drvdata(pfn_dev, drvdata); + pfn_sb = devm_kzalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); + nd_pfn = to_nd_pfn(pfn_dev); nd_pfn->pfn_sb = pfn_sb; rc = nd_pfn_validate(nd_pfn); - nd_pfn->pfn_sb = NULL; - kfree(pfn_sb); - dev_dbg(&ndns->dev, "%s: pfn: %s\n", __func__, - rc == 0 ? dev_name(dev) : ""); + dev_dbg(dev, "%s: pfn: %s\n", __func__, + rc == 0 ? dev_name(pfn_dev) : ""); if (rc < 0) { - __nd_detach_ndns(dev, &nd_pfn->ndns); - put_device(dev); + __nd_detach_ndns(pfn_dev, &nd_pfn->ndns); + put_device(pfn_dev); } else - __nd_device_register(&nd_pfn->dev); + __nd_device_register(pfn_dev); return rc; } diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 2b51d4d34207..4d8f5c55aade 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -330,18 +330,19 @@ static int pmem_rw_bytes(struct nd_namespace_common *ndns, static int nd_pfn_init(struct nd_pfn *nd_pfn) { - struct nd_pfn_sb *pfn_sb = kzalloc(sizeof(*pfn_sb), GFP_KERNEL); struct pmem_device *pmem = dev_get_drvdata(&nd_pfn->dev); struct nd_namespace_common *ndns = nd_pfn->ndns; u32 start_pad = 0, end_trunc = 0; resource_size_t start, size; struct nd_namespace_io *nsio; struct nd_region *nd_region; + struct nd_pfn_sb *pfn_sb; unsigned long npfns; phys_addr_t offset; u64 checksum; int rc; + pfn_sb = devm_kzalloc(&nd_pfn->dev, sizeof(*pfn_sb), GFP_KERNEL); if (!pfn_sb) return -ENOMEM; @@ -357,7 +358,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) dev_info(&nd_pfn->dev, "%s is read-only, unable to init metadata\n", dev_name(&nd_region->dev)); - goto err; + return -ENXIO; } memset(pfn_sb, 0, sizeof(*pfn_sb)); @@ -402,12 +403,12 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) else if (nd_pfn->mode == PFN_MODE_RAM) offset = ALIGN(start + SZ_8K, nd_pfn->align) - start; else - goto err; + return -ENXIO; if (offset + start_pad + end_trunc >= pmem->size) { dev_err(&nd_pfn->dev, "%s unable to satisfy requested alignment\n", dev_name(&ndns->dev)); - goto err; + return -ENXIO; } npfns = (pmem->size - offset - start_pad - end_trunc) / SZ_4K; @@ -424,30 +425,16 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb); pfn_sb->checksum = cpu_to_le64(checksum); - rc = nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb)); - if (rc) - goto err; - - return 0; - err: - nd_pfn->pfn_sb = NULL; - kfree(pfn_sb); - return -ENXIO; + return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb)); } -static int nvdimm_namespace_detach_pfn(struct nd_pfn *nd_pfn) +static void nvdimm_namespace_detach_pfn(struct nd_pfn *nd_pfn) { struct pmem_device *pmem; /* free pmem disk */ pmem = dev_get_drvdata(&nd_pfn->dev); pmem_detach_disk(pmem); - - /* release nd_pfn resources */ - kfree(nd_pfn->pfn_sb); - nd_pfn->pfn_sb = NULL; - - return 0; } /* @@ -587,7 +574,8 @@ static int nd_pmem_probe(struct device *dev) if (is_nd_pfn(dev)) return nvdimm_namespace_attach_pfn(ndns); - if (nd_btt_probe(ndns, pmem) == 0 || nd_pfn_probe(ndns, pmem) == 0) { + if (nd_btt_probe(ndns, pmem) == 0 + || nd_pfn_probe(dev, ndns, pmem) == 0) { /* * We'll come back as either btt-pmem, or pfn-pmem, so * drop the queue allocation for now. -- GitLab From e32bc729a3a486e20443db3379ecf67240b20616 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Mar 2016 18:23:09 -0700 Subject: [PATCH 4002/9938] libnvdimm, btt, convert nd_btt_probe() to devm Pass the device performing the probe so we can use a devm allocation for the btt superblock. Cc: Vishal Verma Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/blk.c | 2 +- drivers/nvdimm/btt.c | 17 ++++++----------- drivers/nvdimm/btt_devs.c | 26 +++++++++++++------------- drivers/nvdimm/nd.h | 6 ++++-- drivers/nvdimm/pmem.c | 2 +- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 24649396b638..c8215dc356cc 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -314,7 +314,7 @@ static int nd_blk_probe(struct device *dev) ndns->rw_bytes = nd_blk_rw_bytes; if (is_nd_btt(dev)) rc = nvdimm_namespace_attach_btt(ndns); - else if (nd_btt_probe(ndns, blk_dev) == 0) { + else if (nd_btt_probe(dev, ndns, blk_dev) == 0) { /* we'll come back as btt-blk */ rc = -ENXIO; } else diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index 676c31a8fb6d..cc9fafed9362 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -1306,7 +1306,7 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize, struct btt *btt; struct device *dev = &nd_btt->dev; - btt = kzalloc(sizeof(struct btt), GFP_KERNEL); + btt = devm_kzalloc(dev, sizeof(struct btt), GFP_KERNEL); if (!btt) return NULL; @@ -1321,13 +1321,13 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize, ret = discover_arenas(btt); if (ret) { dev_err(dev, "init: error in arena_discover: %d\n", ret); - goto out_free; + return NULL; } if (btt->init_state != INIT_READY && nd_region->ro) { dev_info(dev, "%s is read-only, unable to init btt metadata\n", dev_name(&nd_region->dev)); - goto out_free; + return NULL; } else if (btt->init_state != INIT_READY) { btt->num_arenas = (rawsize / ARENA_MAX_SIZE) + ((rawsize % ARENA_MAX_SIZE) ? 1 : 0); @@ -1337,29 +1337,25 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize, ret = create_arenas(btt); if (ret) { dev_info(dev, "init: create_arenas: %d\n", ret); - goto out_free; + return NULL; } ret = btt_meta_init(btt); if (ret) { dev_err(dev, "init: error in meta_init: %d\n", ret); - goto out_free; + return NULL; } } ret = btt_blk_init(btt); if (ret) { dev_err(dev, "init: error in blk_init: %d\n", ret); - goto out_free; + return NULL; } btt_debugfs_init(btt); return btt; - - out_free: - kfree(btt); - return NULL; } /** @@ -1377,7 +1373,6 @@ static void btt_fini(struct btt *btt) btt_blk_cleanup(btt); free_arenas(btt); debugfs_remove_recursive(btt->debugfs_dir); - kfree(btt); } } diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c index cb477518dd0e..1886171af80e 100644 --- a/drivers/nvdimm/btt_devs.c +++ b/drivers/nvdimm/btt_devs.c @@ -273,10 +273,11 @@ static int __nd_btt_probe(struct nd_btt *nd_btt, return 0; } -int nd_btt_probe(struct nd_namespace_common *ndns, void *drvdata) +int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns, + void *drvdata) { int rc; - struct device *dev; + struct device *btt_dev; struct btt_sb *btt_sb; struct nd_region *nd_region = to_nd_region(ndns->dev.parent); @@ -284,21 +285,20 @@ int nd_btt_probe(struct nd_namespace_common *ndns, void *drvdata) return -ENODEV; nvdimm_bus_lock(&ndns->dev); - dev = __nd_btt_create(nd_region, 0, NULL, ndns); + btt_dev = __nd_btt_create(nd_region, 0, NULL, ndns); nvdimm_bus_unlock(&ndns->dev); - if (!dev) + if (!btt_dev) return -ENOMEM; - dev_set_drvdata(dev, drvdata); - btt_sb = kzalloc(sizeof(*btt_sb), GFP_KERNEL); - rc = __nd_btt_probe(to_nd_btt(dev), ndns, btt_sb); - kfree(btt_sb); - dev_dbg(&ndns->dev, "%s: btt: %s\n", __func__, - rc == 0 ? dev_name(dev) : ""); + dev_set_drvdata(btt_dev, drvdata); + btt_sb = devm_kzalloc(dev, sizeof(*btt_sb), GFP_KERNEL); + rc = __nd_btt_probe(to_nd_btt(btt_dev), ndns, btt_sb); + dev_dbg(dev, "%s: btt: %s\n", __func__, + rc == 0 ? dev_name(btt_dev) : ""); if (rc < 0) { - struct nd_btt *nd_btt = to_nd_btt(dev); + struct nd_btt *nd_btt = to_nd_btt(btt_dev); - __nd_detach_ndns(dev, &nd_btt->ndns); - put_device(dev); + __nd_detach_ndns(btt_dev, &nd_btt->ndns); + put_device(btt_dev); } return rc; diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index c831caa3d60a..0fb14890ba26 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -197,11 +197,13 @@ struct nd_gen_sb { u64 nd_sb_checksum(struct nd_gen_sb *sb); #if IS_ENABLED(CONFIG_BTT) -int nd_btt_probe(struct nd_namespace_common *ndns, void *drvdata); +int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns, + void *drvdata); bool is_nd_btt(struct device *dev); struct device *nd_btt_create(struct nd_region *nd_region); #else -static inline int nd_btt_probe(struct nd_namespace_common *ndns, void *drvdata) +static inline int nd_btt_probe(struct device *dev, + struct nd_namespace_common *ndns, void *drvdata) { return -ENODEV; } diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 4d8f5c55aade..6fa39f55dbe3 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -574,7 +574,7 @@ static int nd_pmem_probe(struct device *dev) if (is_nd_pfn(dev)) return nvdimm_namespace_attach_pfn(ndns); - if (nd_btt_probe(ndns, pmem) == 0 + if (nd_btt_probe(dev, ndns, pmem) == 0 || nd_pfn_probe(dev, ndns, pmem) == 0) { /* * We'll come back as either btt-pmem, or pfn-pmem, so -- GitLab From 02fad5e9b433da3829d39f0afb3c51b4b6409ed5 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 9 Mar 2016 18:16:54 -0600 Subject: [PATCH 4003/9938] clocksource: Add missing include of of.h. This header uses OF_DELCARE_1 which is defined in linux/of.h. This fixes getting unhelpful compiler error messages about missing ')' before a string constant. Cc: Prarit Bhargava Cc: Richard Cochran Cc: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: David Lechner Signed-off-by: John Stultz --- include/linux/clocksource.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index a307bf62974f..44a1aff22566 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include -- GitLab From 457db29bfcfd1d9cc717587c446a89d60499d4a9 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 8 Apr 2016 14:02:11 +0800 Subject: [PATCH 4004/9938] security: Introduce security_settime64() security_settime() uses a timespec, which is not year 2038 safe on 32bit systems. Thus this patch introduces the security_settime64() function with timespec64 type. We also convert the cap_settime() helper function to use the 64bit types. This patch then moves security_settime() to the header file as an inline helper function so that existing users can be iteratively converted. None of the existing hooks is using the timespec argument and therefor the patch is not making any functional changes. Cc: Serge Hallyn , Cc: James Morris , Cc: "Serge E. Hallyn" , Cc: Paul Moore Cc: Stephen Smalley Cc: Kees Cook Cc: Prarit Bhargava Cc: Richard Cochran Cc: Thomas Gleixner Cc: Ingo Molnar Reviewed-by: James Morris Signed-off-by: Baolin Wang [jstultz: Reworded commit message] Signed-off-by: John Stultz --- include/linux/lsm_hooks.h | 5 +++-- include/linux/security.h | 20 +++++++++++++++++--- security/commoncap.c | 2 +- security/security.c | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index cdee11cbcdf1..41ab4662f95c 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1190,7 +1190,8 @@ * Return 0 if permission is granted. * @settime: * Check permission to change the system time. - * struct timespec and timezone are defined in include/linux/time.h + * struct timespec64 is defined in include/linux/time64.h and timezone + * is defined in include/linux/time.h * @ts contains new time * @tz contains new timezone * Return 0 if permission is granted. @@ -1327,7 +1328,7 @@ union security_list_options { int (*quotactl)(int cmds, int type, int id, struct super_block *sb); int (*quota_on)(struct dentry *dentry); int (*syslog)(int type); - int (*settime)(const struct timespec *ts, const struct timezone *tz); + int (*settime)(const struct timespec64 *ts, const struct timezone *tz); int (*vm_enough_memory)(struct mm_struct *mm, long pages); int (*bprm_set_creds)(struct linux_binprm *bprm); diff --git a/include/linux/security.h b/include/linux/security.h index 157f0cb1e4d2..35ac8d9d4739 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -71,7 +71,7 @@ struct timezone; /* These functions are in security/commoncap.c */ extern int cap_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit); -extern int cap_settime(const struct timespec *ts, const struct timezone *tz); +extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz); extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); extern int cap_ptrace_traceme(struct task_struct *parent); extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); @@ -208,7 +208,13 @@ int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, int security_quotactl(int cmds, int type, int id, struct super_block *sb); int security_quota_on(struct dentry *dentry); int security_syslog(int type); -int security_settime(const struct timespec *ts, const struct timezone *tz); +int security_settime64(const struct timespec64 *ts, const struct timezone *tz); +static inline int security_settime(const struct timespec *ts, const struct timezone *tz) +{ + struct timespec64 ts64 = timespec_to_timespec64(*ts); + + return security_settime64(&ts64, tz); +} int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); int security_bprm_set_creds(struct linux_binprm *bprm); int security_bprm_check(struct linux_binprm *bprm); @@ -462,10 +468,18 @@ static inline int security_syslog(int type) return 0; } +static inline int security_settime64(const struct timespec64 *ts, + const struct timezone *tz) +{ + return cap_settime(ts, tz); +} + static inline int security_settime(const struct timespec *ts, const struct timezone *tz) { - return cap_settime(ts, tz); + struct timespec64 ts64 = timespec_to_timespec64(*ts); + + return cap_settime(&ts64, tz); } static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) diff --git a/security/commoncap.c b/security/commoncap.c index 48071ed7c445..2074bf6a2fe3 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -111,7 +111,7 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, * Determine whether the current process may set the system clock and timezone * information, returning 0 if permission granted, -ve if denied. */ -int cap_settime(const struct timespec *ts, const struct timezone *tz) +int cap_settime(const struct timespec64 *ts, const struct timezone *tz) { if (!capable(CAP_SYS_TIME)) return -EPERM; diff --git a/security/security.c b/security/security.c index 3644b0344d29..8c44a64f191d 100644 --- a/security/security.c +++ b/security/security.c @@ -208,7 +208,7 @@ int security_syslog(int type) return call_int_hook(syslog, 0, type); } -int security_settime(const struct timespec *ts, const struct timezone *tz) +int security_settime64(const struct timespec64 *ts, const struct timezone *tz) { return call_int_hook(settime, 0, ts, tz); } -- GitLab From 86d3473224b004f920c107206d181d37db735145 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 8 Apr 2016 14:02:12 +0800 Subject: [PATCH 4005/9938] time: Introduce do_sys_settimeofday64() The do_sys_settimeofday() function uses a timespec, which is not year 2038 safe on 32bit systems. Thus this patch introduces do_sys_settimeofday64(), which allows us to transition users of do_sys_settimeofday() to using 64bit time types. Cc: Prarit Bhargava Cc: Richard Cochran Cc: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: Baolin Wang [jstultz: Include errno-base.h to avoid build issue on some arches] Signed-off-by: John Stultz --- include/linux/timekeeping.h | 17 +++++++++++++++-- kernel/time/time.c | 8 ++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 96f37bee3bc1..37dbacf84849 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -1,6 +1,8 @@ #ifndef _LINUX_TIMEKEEPING_H #define _LINUX_TIMEKEEPING_H +#include + /* Included from linux/ktime.h */ void timekeeping_init(void); @@ -11,8 +13,19 @@ extern int timekeeping_suspended; */ extern void do_gettimeofday(struct timeval *tv); extern int do_settimeofday64(const struct timespec64 *ts); -extern int do_sys_settimeofday(const struct timespec *tv, - const struct timezone *tz); +extern int do_sys_settimeofday64(const struct timespec64 *tv, + const struct timezone *tz); +static inline int do_sys_settimeofday(const struct timespec *tv, + const struct timezone *tz) +{ + struct timespec64 ts64; + + if (!tv) + return -EINVAL; + + ts64 = timespec_to_timespec64(*tv); + return do_sys_settimeofday64(&ts64, tz); +} /* * Kernel time accessors diff --git a/kernel/time/time.c b/kernel/time/time.c index be115b020d27..a4064b612066 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -160,15 +160,15 @@ static inline void warp_clock(void) * various programs will get confused when the clock gets warped. */ -int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz) +int do_sys_settimeofday64(const struct timespec64 *tv, const struct timezone *tz) { static int firsttime = 1; int error = 0; - if (tv && !timespec_valid(tv)) + if (tv && !timespec64_valid(tv)) return -EINVAL; - error = security_settime(tv, tz); + error = security_settime64(tv, tz); if (error) return error; @@ -186,7 +186,7 @@ int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz) } } if (tv) - return do_settimeofday(tv); + return do_settimeofday64(tv); return 0; } -- GitLab From 1b47b98acce2db0da632d056821420b33205b8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 19 Apr 2016 08:56:46 +0200 Subject: [PATCH 4006/9938] ARM: BCM5301X: Add DT entry for SPI controller and NOR flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Controller is present on every BCM4708* board but only few devices have serial flash attached so mark it as disabled by default. Signed-off-by: Rafał Miłecki Signed-off-by: Florian Fainelli --- arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts | 4 ++++ arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts | 4 ++++ arch/arm/boot/dts/bcm5301x.dtsi | 14 ++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts index c973f768dd14..1c7e53d60aa4 100644 --- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts +++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts @@ -59,3 +59,7 @@ &uart0 { status = "okay"; }; + +&spi_nor { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts index 4d610ff40e1b..8b0c440b2e71 100644 --- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts @@ -122,3 +122,7 @@ &uart0 { status = "okay"; }; + +&spi_nor { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index 9c06d91e0c8a..7d4d29bf0ed3 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -225,6 +225,20 @@ #address-cells = <1>; #size-cells = <1>; }; + + spi@29000 { + reg = <0x00029000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + spi_nor: spi-nor@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <20000000>; + linux,part-probe = "ofpart", "bcm47xxpart"; + status = "disabled"; + }; + }; }; lcpll0: lcpll0@1800c100 { -- GitLab From a9abb475a4fd3e23f2de8bf134b71e10b560b910 Mon Sep 17 00:00:00 2001 From: Luke Starrett Date: Wed, 20 Apr 2016 13:40:02 -0400 Subject: [PATCH 4007/9938] arm64: dts: NS2 secondary core enablement via PSCI Declare PSCI-1.0 node and enable CPU_ON method via PSCI. Spin-table memreserve has been removed as well as syscon based reset, as PSCI-1.0 expects reset implementation in firmware. Signed-off-by: Luke Starrett Acked-by: Scott Branden Signed-off-by: Florian Fainelli --- arch/arm64/boot/dts/broadcom/ns2.dtsi | 31 ++++++++------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index 123cd9c6a01b..ec68ec1a80c8 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -33,8 +33,6 @@ #include #include -/memreserve/ 0x84b00000 0x00000008; - / { compatible = "brcm,ns2"; interrupt-parent = <&gic>; @@ -49,8 +47,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0 0>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x84b00000>; + enable-method = "psci"; next-level-cache = <&CLUSTER0_L2>; }; @@ -58,8 +55,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0 1>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x84b00000>; + enable-method = "psci"; next-level-cache = <&CLUSTER0_L2>; }; @@ -67,8 +63,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0 2>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x84b00000>; + enable-method = "psci"; next-level-cache = <&CLUSTER0_L2>; }; @@ -76,8 +71,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0 3>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x84b00000>; + enable-method = "psci"; next-level-cache = <&CLUSTER0_L2>; }; @@ -86,6 +80,11 @@ }; }; + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + timer { compatible = "arm,armv8-timer"; interrupts = ; - }; - - reboot@65024000 { - compatible ="syscon-reboot"; - regmap = <&crmu>; - offset = <0x90>; - mask = <0xfffffffd>; - }; - gic: interrupt-controller@65210000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; -- GitLab From 9dec4892ca9afd6aad3c9c9e6c17480ecbd04440 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 22 Apr 2016 12:26:05 -0700 Subject: [PATCH 4008/9938] libnvdimm, btt: add btt startup debug Report the reason for btt probe failures when debug is enabled. Signed-off-by: Dan Williams --- drivers/nvdimm/btt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index f068b6513cd2..af09d6c26709 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -1388,11 +1388,15 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns) struct btt *btt; size_t rawsize; - if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize) + if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize) { + dev_dbg(&nd_btt->dev, "incomplete btt configuration\n"); return -ENODEV; + } rawsize = nvdimm_namespace_capacity(ndns) - SZ_4K; if (rawsize < ARENA_MIN_SIZE) { + dev_dbg(&nd_btt->dev, "%s must be at least %ld bytes\n", + dev_name(&ndns->dev), ARENA_MIN_SIZE + SZ_4K); return -ENXIO; } nd_region = to_nd_region(nd_btt->dev.parent); -- GitLab From d29cee120eb890027c69f5fe7cce8bd6a663900a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Mar 2016 20:08:28 -0700 Subject: [PATCH 4009/9938] libnvdimm, blk: use devm_add_action to release bdev resources Register a callback to clean up the request_queue and put the gendisk at driver disable time. Cc: Ross Zwisler Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/blk.c | 77 +++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index c8215dc356cc..27ff32a5e9cf 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -22,8 +22,6 @@ #include "nd.h" struct nd_blk_device { - struct request_queue *queue; - struct gendisk *disk; struct nd_namespace_blk *nsblk; struct nd_blk_region *ndbr; size_t disk_size; @@ -235,29 +233,47 @@ static const struct block_device_operations nd_blk_fops = { .revalidate_disk = nvdimm_revalidate_disk, }; -static int nd_blk_attach_disk(struct nd_namespace_common *ndns, - struct nd_blk_device *blk_dev) +static void nd_blk_release_queue(void *q) +{ + blk_cleanup_queue(q); +} + +static void nd_blk_release_disk(void *disk) +{ + del_gendisk(disk); + put_disk(disk); +} + +static int nd_blk_attach_disk(struct device *dev, + struct nd_namespace_common *ndns, struct nd_blk_device *blk_dev) { resource_size_t available_disk_size; + struct request_queue *q; struct gendisk *disk; u64 internal_nlba; internal_nlba = div_u64(blk_dev->disk_size, blk_dev->internal_lbasize); available_disk_size = internal_nlba * blk_dev->sector_size; - blk_dev->queue = blk_alloc_queue(GFP_KERNEL); - if (!blk_dev->queue) + q = blk_alloc_queue(GFP_KERNEL); + if (!q) + return -ENOMEM; + if (devm_add_action(dev, nd_blk_release_queue, q)) { + blk_cleanup_queue(q); return -ENOMEM; + } - blk_queue_make_request(blk_dev->queue, nd_blk_make_request); - blk_queue_max_hw_sectors(blk_dev->queue, UINT_MAX); - blk_queue_bounce_limit(blk_dev->queue, BLK_BOUNCE_ANY); - blk_queue_logical_block_size(blk_dev->queue, blk_dev->sector_size); - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, blk_dev->queue); + blk_queue_make_request(q, nd_blk_make_request); + blk_queue_max_hw_sectors(q, UINT_MAX); + blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); + blk_queue_logical_block_size(q, blk_dev->sector_size); + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); - disk = blk_dev->disk = alloc_disk(0); - if (!disk) { - blk_cleanup_queue(blk_dev->queue); + disk = alloc_disk(0); + if (!disk) + return -ENOMEM; + if (devm_add_action(dev, nd_blk_release_disk, disk)) { + put_disk(disk); return -ENOMEM; } @@ -265,7 +281,7 @@ static int nd_blk_attach_disk(struct nd_namespace_common *ndns, disk->first_minor = 0; disk->fops = &nd_blk_fops; disk->private_data = blk_dev; - disk->queue = blk_dev->queue; + disk->queue = q; disk->flags = GENHD_FL_EXT_DEVT; nvdimm_namespace_disk_name(ndns, disk->disk_name); set_capacity(disk, 0); @@ -274,12 +290,8 @@ static int nd_blk_attach_disk(struct nd_namespace_common *ndns, if (nd_blk_meta_size(blk_dev)) { int rc = nd_integrity_init(disk, nd_blk_meta_size(blk_dev)); - if (rc) { - del_gendisk(disk); - put_disk(disk); - blk_cleanup_queue(blk_dev->queue); + if (rc) return rc; - } } set_capacity(disk, available_disk_size >> SECTOR_SHIFT); @@ -292,13 +304,12 @@ static int nd_blk_probe(struct device *dev) struct nd_namespace_common *ndns; struct nd_namespace_blk *nsblk; struct nd_blk_device *blk_dev; - int rc; ndns = nvdimm_namespace_common_probe(dev); if (IS_ERR(ndns)) return PTR_ERR(ndns); - blk_dev = kzalloc(sizeof(*blk_dev), GFP_KERNEL); + blk_dev = devm_kzalloc(dev, sizeof(*blk_dev), GFP_KERNEL); if (!blk_dev) return -ENOMEM; @@ -313,34 +324,18 @@ static int nd_blk_probe(struct device *dev) ndns->rw_bytes = nd_blk_rw_bytes; if (is_nd_btt(dev)) - rc = nvdimm_namespace_attach_btt(ndns); + return nvdimm_namespace_attach_btt(ndns); else if (nd_btt_probe(dev, ndns, blk_dev) == 0) { /* we'll come back as btt-blk */ - rc = -ENXIO; + return -ENXIO; } else - rc = nd_blk_attach_disk(ndns, blk_dev); - if (rc) - kfree(blk_dev); - return rc; -} - -static void nd_blk_detach_disk(struct nd_blk_device *blk_dev) -{ - del_gendisk(blk_dev->disk); - put_disk(blk_dev->disk); - blk_cleanup_queue(blk_dev->queue); + return nd_blk_attach_disk(dev, ndns, blk_dev); } static int nd_blk_remove(struct device *dev) { - struct nd_blk_device *blk_dev = dev_get_drvdata(dev); - if (is_nd_btt(dev)) nvdimm_namespace_detach_btt(to_nd_btt(dev)); - else - nd_blk_detach_disk(blk_dev); - kfree(blk_dev); - return 0; } -- GitLab From d44077a7cddce18fc8d83194bb4c83a0225f0f40 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Mar 2016 23:45:45 -0700 Subject: [PATCH 4010/9938] libnvdimm, blk: use ->queuedata for driver private data Save a pointer chase by storing the driver private data in the request_queue rather than the gendisk. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/blk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 27ff32a5e9cf..c8635b3d88a8 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -159,8 +159,6 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) { - struct block_device *bdev = bio->bi_bdev; - struct gendisk *disk = bdev->bd_disk; struct bio_integrity_payload *bip; struct nd_blk_device *blk_dev; struct bvec_iter iter; @@ -181,7 +179,7 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) } bip = bio_integrity(bio); - blk_dev = disk->private_data; + blk_dev = q->queuedata; rw = bio_data_dir(bio); do_acct = nd_iostat_start(bio, &start); bio_for_each_segment(bvec, bio, iter) { @@ -268,6 +266,7 @@ static int nd_blk_attach_disk(struct device *dev, blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); blk_queue_logical_block_size(q, blk_dev->sector_size); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); + q->queuedata = blk_dev; disk = alloc_disk(0); if (!disk) @@ -280,7 +279,6 @@ static int nd_blk_attach_disk(struct device *dev, disk->driverfs_dev = &ndns->dev; disk->first_minor = 0; disk->fops = &nd_blk_fops; - disk->private_data = blk_dev; disk->queue = q; disk->flags = GENHD_FL_EXT_DEVT; nvdimm_namespace_disk_name(ndns, disk->disk_name); -- GitLab From bd842b8ca7f207b99a5476a8174e62c29a2ff80e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Mar 2016 23:47:43 -0700 Subject: [PATCH 4011/9938] libnvdimm, pmem: use ->queuedata for driver private data Save a pointer chase by storing the driver private data in the request_queue rather than the gendisk. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/pmem.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 6fa39f55dbe3..2238e3af48ae 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -135,8 +135,7 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio) unsigned long start; struct bio_vec bvec; struct bvec_iter iter; - struct block_device *bdev = bio->bi_bdev; - struct pmem_device *pmem = bdev->bd_disk->private_data; + struct pmem_device *pmem = q->queuedata; do_acct = nd_iostat_start(bio, &start); bio_for_each_segment(bvec, bio, iter) { @@ -161,7 +160,7 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio) static int pmem_rw_page(struct block_device *bdev, sector_t sector, struct page *page, int rw) { - struct pmem_device *pmem = bdev->bd_disk->private_data; + struct pmem_device *pmem = bdev->bd_queue->queuedata; int rc; rc = pmem_do_bvec(pmem, page, PAGE_SIZE, 0, rw, sector); @@ -183,7 +182,7 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector, static long pmem_direct_access(struct block_device *bdev, sector_t sector, void __pmem **kaddr, pfn_t *pfn) { - struct pmem_device *pmem = bdev->bd_disk->private_data; + struct pmem_device *pmem = bdev->bd_queue->queuedata; resource_size_t offset = sector * 512 + pmem->data_offset; *kaddr = pmem->virt_addr + offset; @@ -267,6 +266,7 @@ static int pmem_attach_disk(struct device *dev, blk_queue_max_hw_sectors(pmem->pmem_queue, UINT_MAX); blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, pmem->pmem_queue); + pmem->pmem_queue->queuedata = pmem; disk = alloc_disk_node(0, nid); if (!disk) { @@ -275,7 +275,6 @@ static int pmem_attach_disk(struct device *dev, } disk->fops = &pmem_fops; - disk->private_data = pmem; disk->queue = pmem->pmem_queue; disk->flags = GENHD_FL_EXT_DEVT; nvdimm_namespace_disk_name(ndns, disk->disk_name); -- GitLab From 8378af17a4021f01b3bed20c1bd19c3921c1f5ac Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 24 Mar 2016 18:06:07 -0700 Subject: [PATCH 4012/9938] libnvdimm, blk: quiet i/o error reporting I/O errors events have the potential to be a high frequency and a log message for each event can swamp the system. This message is also redundant with upper layer error reporting. Cc: Ross Zwisler Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index c8635b3d88a8..26d039879ba2 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -189,7 +189,7 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) err = nd_blk_do_bvec(blk_dev, bip, bvec.bv_page, len, bvec.bv_offset, rw, iter.bi_sector); if (err) { - dev_info(&blk_dev->nsblk->common.dev, + dev_dbg(&blk_dev->nsblk->common.dev, "io error in %s sector %lld, len %d,\n", (rw == READ) ? "READ" : "WRITE", (unsigned long long) iter.bi_sector, len); -- GitLab From 9d90725ddca347450c4ab177ad680ed76063afd4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Mar 2016 11:27:36 -0700 Subject: [PATCH 4013/9938] libnvdimm, blk: move i/o infrastructure to nd_namespace_blk Consolidate the information for issuing i/o to a blk-namespace, and eliminate some pointer chasing. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/blk.c | 137 ++++++++++++++++++++++--------------------- include/linux/nd.h | 2 + 2 files changed, 71 insertions(+), 68 deletions(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 26d039879ba2..4c14ecdc792b 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -21,17 +21,19 @@ #include #include "nd.h" -struct nd_blk_device { - struct nd_namespace_blk *nsblk; - struct nd_blk_region *ndbr; - size_t disk_size; - u32 sector_size; - u32 internal_lbasize; -}; +static u32 nsblk_meta_size(struct nd_namespace_blk *nsblk) +{ + return nsblk->lbasize - ((nsblk->lbasize >= 4096) ? 4096 : 512); +} -static u32 nd_blk_meta_size(struct nd_blk_device *blk_dev) +static u32 nsblk_internal_lbasize(struct nd_namespace_blk *nsblk) { - return blk_dev->nsblk->lbasize - blk_dev->sector_size; + return roundup(nsblk->lbasize, INT_LBASIZE_ALIGNMENT); +} + +static u32 nsblk_sector_size(struct nd_namespace_blk *nsblk) +{ + return nsblk->lbasize - nsblk_meta_size(nsblk); } static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk, @@ -55,20 +57,29 @@ static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk, return SIZE_MAX; } +static struct nd_blk_region *to_ndbr(struct nd_namespace_blk *nsblk) +{ + struct nd_region *nd_region; + struct device *parent; + + parent = nsblk->common.dev.parent; + nd_region = container_of(parent, struct nd_region, dev); + return container_of(nd_region, struct nd_blk_region, nd_region); +} + #ifdef CONFIG_BLK_DEV_INTEGRITY -static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, - struct bio_integrity_payload *bip, u64 lba, - int rw) +static int nd_blk_rw_integrity(struct nd_namespace_blk *nsblk, + struct bio_integrity_payload *bip, u64 lba, int rw) { - unsigned int len = nd_blk_meta_size(blk_dev); + struct nd_blk_region *ndbr = to_ndbr(nsblk); + unsigned int len = nsblk_meta_size(nsblk); resource_size_t dev_offset, ns_offset; - struct nd_namespace_blk *nsblk; - struct nd_blk_region *ndbr; + u32 internal_lbasize, sector_size; int err = 0; - nsblk = blk_dev->nsblk; - ndbr = blk_dev->ndbr; - ns_offset = lba * blk_dev->internal_lbasize + blk_dev->sector_size; + internal_lbasize = nsblk_internal_lbasize(nsblk); + sector_size = nsblk_sector_size(nsblk); + ns_offset = lba * internal_lbasize + sector_size; dev_offset = to_dev_offset(nsblk, ns_offset, len); if (dev_offset == SIZE_MAX) return -EIO; @@ -102,25 +113,26 @@ static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, } #else /* CONFIG_BLK_DEV_INTEGRITY */ -static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, - struct bio_integrity_payload *bip, u64 lba, - int rw) +static int nd_blk_rw_integrity(struct nd_namespace_blk *nsblk, + struct bio_integrity_payload *bip, u64 lba, int rw) { return 0; } #endif -static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, - struct bio_integrity_payload *bip, struct page *page, - unsigned int len, unsigned int off, int rw, - sector_t sector) +static int nsblk_do_bvec(struct nd_namespace_blk *nsblk, + struct bio_integrity_payload *bip, struct page *page, + unsigned int len, unsigned int off, int rw, sector_t sector) { - struct nd_blk_region *ndbr = blk_dev->ndbr; + struct nd_blk_region *ndbr = to_ndbr(nsblk); resource_size_t dev_offset, ns_offset; + u32 internal_lbasize, sector_size; int err = 0; void *iobuf; u64 lba; + internal_lbasize = nsblk_internal_lbasize(nsblk); + sector_size = nsblk_sector_size(nsblk); while (len) { unsigned int cur_len; @@ -130,11 +142,11 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, * Block Window setup/move steps. the do_io routine is capable * of handling len <= PAGE_SIZE. */ - cur_len = bip ? min(len, blk_dev->sector_size) : len; + cur_len = bip ? min(len, sector_size) : len; - lba = div_u64(sector << SECTOR_SHIFT, blk_dev->sector_size); - ns_offset = lba * blk_dev->internal_lbasize; - dev_offset = to_dev_offset(blk_dev->nsblk, ns_offset, cur_len); + lba = div_u64(sector << SECTOR_SHIFT, sector_size); + ns_offset = lba * internal_lbasize; + dev_offset = to_dev_offset(nsblk, ns_offset, cur_len); if (dev_offset == SIZE_MAX) return -EIO; @@ -145,13 +157,13 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, return err; if (bip) { - err = nd_blk_rw_integrity(blk_dev, bip, lba, rw); + err = nd_blk_rw_integrity(nsblk, bip, lba, rw); if (err) return err; } len -= cur_len; off += cur_len; - sector += blk_dev->sector_size >> SECTOR_SHIFT; + sector += sector_size >> SECTOR_SHIFT; } return err; @@ -160,7 +172,7 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) { struct bio_integrity_payload *bip; - struct nd_blk_device *blk_dev; + struct nd_namespace_blk *nsblk; struct bvec_iter iter; unsigned long start; struct bio_vec bvec; @@ -179,17 +191,17 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) } bip = bio_integrity(bio); - blk_dev = q->queuedata; + nsblk = q->queuedata; rw = bio_data_dir(bio); do_acct = nd_iostat_start(bio, &start); bio_for_each_segment(bvec, bio, iter) { unsigned int len = bvec.bv_len; BUG_ON(len > PAGE_SIZE); - err = nd_blk_do_bvec(blk_dev, bip, bvec.bv_page, len, - bvec.bv_offset, rw, iter.bi_sector); + err = nsblk_do_bvec(nsblk, bip, bvec.bv_page, len, + bvec.bv_offset, rw, iter.bi_sector); if (err) { - dev_dbg(&blk_dev->nsblk->common.dev, + dev_dbg(&nsblk->common.dev, "io error in %s sector %lld, len %d,\n", (rw == READ) ? "READ" : "WRITE", (unsigned long long) iter.bi_sector, len); @@ -205,17 +217,16 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) return BLK_QC_T_NONE; } -static int nd_blk_rw_bytes(struct nd_namespace_common *ndns, +static int nsblk_rw_bytes(struct nd_namespace_common *ndns, resource_size_t offset, void *iobuf, size_t n, int rw) { - struct nd_blk_device *blk_dev = dev_get_drvdata(ndns->claim); - struct nd_namespace_blk *nsblk = blk_dev->nsblk; - struct nd_blk_region *ndbr = blk_dev->ndbr; + struct nd_namespace_blk *nsblk = to_nd_namespace_blk(&ndns->dev); + struct nd_blk_region *ndbr = to_ndbr(nsblk); resource_size_t dev_offset; dev_offset = to_dev_offset(nsblk, offset, n); - if (unlikely(offset + n > blk_dev->disk_size)) { + if (unlikely(offset + n > nsblk->size)) { dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); return -EFAULT; } @@ -242,16 +253,16 @@ static void nd_blk_release_disk(void *disk) put_disk(disk); } -static int nd_blk_attach_disk(struct device *dev, - struct nd_namespace_common *ndns, struct nd_blk_device *blk_dev) +static int nsblk_attach_disk(struct nd_namespace_blk *nsblk) { + struct device *dev = &nsblk->common.dev; resource_size_t available_disk_size; struct request_queue *q; struct gendisk *disk; u64 internal_nlba; - internal_nlba = div_u64(blk_dev->disk_size, blk_dev->internal_lbasize); - available_disk_size = internal_nlba * blk_dev->sector_size; + internal_nlba = div_u64(nsblk->size, nsblk_internal_lbasize(nsblk)); + available_disk_size = internal_nlba * nsblk_sector_size(nsblk); q = blk_alloc_queue(GFP_KERNEL); if (!q) @@ -264,9 +275,9 @@ static int nd_blk_attach_disk(struct device *dev, blk_queue_make_request(q, nd_blk_make_request); blk_queue_max_hw_sectors(q, UINT_MAX); blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); - blk_queue_logical_block_size(q, blk_dev->sector_size); + blk_queue_logical_block_size(q, nsblk_sector_size(nsblk)); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); - q->queuedata = blk_dev; + q->queuedata = nsblk; disk = alloc_disk(0); if (!disk) @@ -276,17 +287,17 @@ static int nd_blk_attach_disk(struct device *dev, return -ENOMEM; } - disk->driverfs_dev = &ndns->dev; + disk->driverfs_dev = dev; disk->first_minor = 0; disk->fops = &nd_blk_fops; disk->queue = q; disk->flags = GENHD_FL_EXT_DEVT; - nvdimm_namespace_disk_name(ndns, disk->disk_name); + nvdimm_namespace_disk_name(&nsblk->common, disk->disk_name); set_capacity(disk, 0); add_disk(disk); - if (nd_blk_meta_size(blk_dev)) { - int rc = nd_integrity_init(disk, nd_blk_meta_size(blk_dev)); + if (nsblk_meta_size(nsblk)) { + int rc = nd_integrity_init(disk, nsblk_meta_size(nsblk)); if (rc) return rc; @@ -301,33 +312,23 @@ static int nd_blk_probe(struct device *dev) { struct nd_namespace_common *ndns; struct nd_namespace_blk *nsblk; - struct nd_blk_device *blk_dev; ndns = nvdimm_namespace_common_probe(dev); if (IS_ERR(ndns)) return PTR_ERR(ndns); - blk_dev = devm_kzalloc(dev, sizeof(*blk_dev), GFP_KERNEL); - if (!blk_dev) - return -ENOMEM; - nsblk = to_nd_namespace_blk(&ndns->dev); - blk_dev->disk_size = nvdimm_namespace_capacity(ndns); - blk_dev->ndbr = to_nd_blk_region(dev->parent); - blk_dev->nsblk = to_nd_namespace_blk(&ndns->dev); - blk_dev->internal_lbasize = roundup(nsblk->lbasize, - INT_LBASIZE_ALIGNMENT); - blk_dev->sector_size = ((nsblk->lbasize >= 4096) ? 4096 : 512); - dev_set_drvdata(dev, blk_dev); - - ndns->rw_bytes = nd_blk_rw_bytes; + nsblk->size = nvdimm_namespace_capacity(ndns); + dev_set_drvdata(dev, nsblk); + + ndns->rw_bytes = nsblk_rw_bytes; if (is_nd_btt(dev)) return nvdimm_namespace_attach_btt(ndns); - else if (nd_btt_probe(dev, ndns, blk_dev) == 0) { + else if (nd_btt_probe(dev, ndns, nsblk) == 0) { /* we'll come back as btt-blk */ return -ENXIO; } else - return nd_blk_attach_disk(dev, ndns, blk_dev); + return nsblk_attach_disk(nsblk); } static int nd_blk_remove(struct device *dev) diff --git a/include/linux/nd.h b/include/linux/nd.h index 5489ab756d1a..5ea4aec7fd63 100644 --- a/include/linux/nd.h +++ b/include/linux/nd.h @@ -82,6 +82,7 @@ struct nd_namespace_pmem { * @uuid: namespace name supplied in the dimm label * @id: ida allocated id * @lbasize: blk namespaces have a native sector size when btt not present + * @size: sum of all the resource ranges allocated to this namespace * @num_resources: number of dpa extents to claim * @res: discontiguous dpa extents for given dimm */ @@ -91,6 +92,7 @@ struct nd_namespace_blk { u8 *uuid; int id; unsigned long lbasize; + resource_size_t size; int num_resources; struct resource **res; }; -- GitLab From 030b99e39cad33b104474fbe688e0eb23d8209b4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Mar 2016 20:24:31 -0700 Subject: [PATCH 4014/9938] libnvdimm, pmem: use devm_add_action to release bdev resources Register a callback to clean up the request_queue and put the gendisk at driver disable time. Cc: Ross Zwisler Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/pmem.c | 88 +++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 2238e3af48ae..d936defdc1e2 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -198,6 +198,17 @@ static const struct block_device_operations pmem_fops = { .revalidate_disk = nvdimm_revalidate_disk, }; +static void pmem_release_queue(void *q) +{ + blk_cleanup_queue(q); +} + +void pmem_release_disk(void *disk) +{ + del_gendisk(disk); + put_disk(disk); +} + static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res, int id) { @@ -234,25 +245,22 @@ static struct pmem_device *pmem_alloc(struct device *dev, pmem->phys_addr, pmem->size, ARCH_MEMREMAP_PMEM); - if (IS_ERR(pmem->virt_addr)) { + /* + * At release time the queue must be dead before + * devm_memremap_pages is unwound + */ + if (devm_add_action(dev, pmem_release_queue, q)) { blk_cleanup_queue(q); - return (void __force *) pmem->virt_addr; + return ERR_PTR(-ENOMEM); } + if (IS_ERR(pmem->virt_addr)) + return (void __force *) pmem->virt_addr; + pmem->pmem_queue = q; return pmem; } -static void pmem_detach_disk(struct pmem_device *pmem) -{ - if (!pmem->pmem_disk) - return; - - del_gendisk(pmem->pmem_disk); - put_disk(pmem->pmem_disk); - blk_cleanup_queue(pmem->pmem_queue); -} - static int pmem_attach_disk(struct device *dev, struct nd_namespace_common *ndns, struct pmem_device *pmem) { @@ -269,8 +277,10 @@ static int pmem_attach_disk(struct device *dev, pmem->pmem_queue->queuedata = pmem; disk = alloc_disk_node(0, nid); - if (!disk) { - blk_cleanup_queue(pmem->pmem_queue); + if (!disk) + return -ENOMEM; + if (devm_add_action(dev, pmem_release_disk, disk)) { + put_disk(disk); return -ENOMEM; } @@ -427,15 +437,6 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb)); } -static void nvdimm_namespace_detach_pfn(struct nd_pfn *nd_pfn) -{ - struct pmem_device *pmem; - - /* free pmem disk */ - pmem = dev_get_drvdata(&nd_pfn->dev); - pmem_detach_disk(pmem); -} - /* * We hotplug memory at section granularity, pad the reserved area from * the previous section base to the namespace base address. @@ -458,7 +459,6 @@ static unsigned long init_altmap_reserve(resource_size_t base) static int __nvdimm_namespace_attach_pfn(struct nd_pfn *nd_pfn) { - int rc; struct resource res; struct request_queue *q; struct pmem_device *pmem; @@ -495,35 +495,33 @@ static int __nvdimm_namespace_attach_pfn(struct nd_pfn *nd_pfn) altmap = & __altmap; altmap->free = PHYS_PFN(pmem->data_offset - SZ_8K); altmap->alloc = 0; - } else { - rc = -ENXIO; - goto err; - } + } else + return -ENXIO; /* establish pfn range for lookup, and switch to direct map */ q = pmem->pmem_queue; memcpy(&res, &nsio->res, sizeof(res)); res.start += start_pad; res.end -= end_trunc; + devm_remove_action(dev, pmem_release_queue, q); devm_memunmap(dev, (void __force *) pmem->virt_addr); pmem->virt_addr = (void __pmem *) devm_memremap_pages(dev, &res, &q->q_usage_counter, altmap); pmem->pfn_flags |= PFN_MAP; - if (IS_ERR(pmem->virt_addr)) { - rc = PTR_ERR(pmem->virt_addr); - goto err; + + /* + * At release time the queue must be dead before + * devm_memremap_pages is unwound + */ + if (devm_add_action(dev, pmem_release_queue, q)) { + blk_cleanup_queue(q); + return -ENOMEM; } + if (IS_ERR(pmem->virt_addr)) + return PTR_ERR(pmem->virt_addr); /* attach pmem disk in "pfn-mode" */ - rc = pmem_attach_disk(dev, ndns, pmem); - if (rc) - goto err; - - return rc; - err: - nvdimm_namespace_detach_pfn(nd_pfn); - return rc; - + return pmem_attach_disk(dev, ndns, pmem); } static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns) @@ -565,8 +563,8 @@ static int nd_pmem_probe(struct device *dev) if (is_nd_btt(dev)) { /* btt allocates its own request_queue */ + devm_remove_action(dev, pmem_release_queue, pmem->pmem_queue); blk_cleanup_queue(pmem->pmem_queue); - pmem->pmem_queue = NULL; return nvdimm_namespace_attach_btt(ndns); } @@ -579,7 +577,6 @@ static int nd_pmem_probe(struct device *dev) * We'll come back as either btt-pmem, or pfn-pmem, so * drop the queue allocation for now. */ - blk_cleanup_queue(pmem->pmem_queue); return -ENXIO; } @@ -588,15 +585,8 @@ static int nd_pmem_probe(struct device *dev) static int nd_pmem_remove(struct device *dev) { - struct pmem_device *pmem = dev_get_drvdata(dev); - if (is_nd_btt(dev)) nvdimm_namespace_detach_btt(to_nd_btt(dev)); - else if (is_nd_pfn(dev)) - nvdimm_namespace_detach_pfn(to_nd_pfn(dev)); - else - pmem_detach_disk(pmem); - return 0; } -- GitLab From 947df02d255a6a81a3832e831c5ca02078cfd529 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Mar 2016 22:28:40 -0700 Subject: [PATCH 4015/9938] libnvdimm, pmem: clean up resource print / request The leading '0x' in front of %pa is redundant, also we can just use %pR to simplify the print statement. The request parameters can be directly taken from the resource as well. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/pmem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index d936defdc1e2..67d48e2e8ca2 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -224,10 +224,9 @@ static struct pmem_device *pmem_alloc(struct device *dev, if (!arch_has_wmb_pmem()) dev_warn(dev, "unable to guarantee persistence of writes\n"); - if (!devm_request_mem_region(dev, pmem->phys_addr, pmem->size, - dev_name(dev))) { - dev_warn(dev, "could not reserve region [0x%pa:0x%zx]\n", - &pmem->phys_addr, pmem->size); + if (!devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev))) { + dev_warn(dev, "could not reserve region %pR\n", res); return ERR_PTR(-EBUSY); } -- GitLab From 200c79da824c978fcf6eec1dc9c0a1e521133267 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Mar 2016 00:22:16 -0700 Subject: [PATCH 4016/9938] libnvdimm, pmem, pfn: make pmem_rw_bytes generic and refactor pfn setup In preparation for providing an alternative (to block device) access mechanism to persistent memory, convert pmem_rw_bytes() to nsio_rw_bytes(). This allows ->rw_bytes() functionality without requiring a 'struct pmem_device' to be instantiated. In other words, when ->rw_bytes() is in use i/o is driven through 'struct nd_namespace_io', otherwise it is driven through 'struct pmem_device' and the block layer. This consolidates the disjoint calls to devm_exit_badblocks() and devm_memunmap() into a common devm_nsio_disable() and cleans up the init path to use a unified pmem_attach_disk() implementation. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/blk.c | 2 +- drivers/nvdimm/btt_devs.c | 4 +- drivers/nvdimm/claim.c | 61 ++++++++ drivers/nvdimm/nd.h | 40 ++++- drivers/nvdimm/pfn_devs.c | 4 +- drivers/nvdimm/pmem.c | 236 +++++++++++------------------- include/linux/nd.h | 9 +- tools/testing/nvdimm/Kbuild | 1 + tools/testing/nvdimm/test/iomap.c | 27 +++- 9 files changed, 211 insertions(+), 173 deletions(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 4c14ecdc792b..495e06d9f7e7 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -324,7 +324,7 @@ static int nd_blk_probe(struct device *dev) ndns->rw_bytes = nsblk_rw_bytes; if (is_nd_btt(dev)) return nvdimm_namespace_attach_btt(ndns); - else if (nd_btt_probe(dev, ndns, nsblk) == 0) { + else if (nd_btt_probe(dev, ndns) == 0) { /* we'll come back as btt-blk */ return -ENXIO; } else diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c index 1886171af80e..816d0dae6398 100644 --- a/drivers/nvdimm/btt_devs.c +++ b/drivers/nvdimm/btt_devs.c @@ -273,8 +273,7 @@ static int __nd_btt_probe(struct nd_btt *nd_btt, return 0; } -int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns, - void *drvdata) +int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns) { int rc; struct device *btt_dev; @@ -289,7 +288,6 @@ int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns, nvdimm_bus_unlock(&ndns->dev); if (!btt_dev) return -ENOMEM; - dev_set_drvdata(btt_dev, drvdata); btt_sb = devm_kzalloc(dev, sizeof(*btt_sb), GFP_KERNEL); rc = __nd_btt_probe(to_nd_btt(btt_dev), ndns, btt_sb); dev_dbg(dev, "%s: btt: %s\n", __func__, diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c index e8f03b0e95e4..6bbd0a36994a 100644 --- a/drivers/nvdimm/claim.c +++ b/drivers/nvdimm/claim.c @@ -12,6 +12,7 @@ */ #include #include +#include #include "nd-core.h" #include "pfn.h" #include "btt.h" @@ -199,3 +200,63 @@ u64 nd_sb_checksum(struct nd_gen_sb *nd_gen_sb) return sum; } EXPORT_SYMBOL(nd_sb_checksum); + +static int nsio_rw_bytes(struct nd_namespace_common *ndns, + resource_size_t offset, void *buf, size_t size, int rw) +{ + struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); + + if (unlikely(offset + size > nsio->size)) { + dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); + return -EFAULT; + } + + if (rw == READ) { + unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); + + if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align))) + return -EIO; + return memcpy_from_pmem(buf, nsio->addr + offset, size); + } else { + memcpy_to_pmem(nsio->addr + offset, buf, size); + wmb_pmem(); + } + + return 0; +} + +int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) +{ + struct resource *res = &nsio->res; + struct nd_namespace_common *ndns = &nsio->common; + + nsio->size = resource_size(res); + if (!devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev))) { + dev_warn(dev, "could not reserve region %pR\n", res); + return -EBUSY; + } + + ndns->rw_bytes = nsio_rw_bytes; + if (devm_init_badblocks(dev, &nsio->bb)) + return -ENOMEM; + nvdimm_badblocks_populate(to_nd_region(ndns->dev.parent), &nsio->bb, + &nsio->res); + + nsio->addr = devm_memremap(dev, res->start, resource_size(res), + ARCH_MEMREMAP_PMEM); + if (IS_ERR(nsio->addr)) + return PTR_ERR(nsio->addr); + return 0; +} +EXPORT_SYMBOL_GPL(devm_nsio_enable); + +void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio) +{ + struct resource *res = &nsio->res; + + devm_memunmap(dev, nsio->addr); + devm_exit_badblocks(dev, &nsio->bb); + devm_release_mem_region(dev, res->start, resource_size(res)); +} +EXPORT_SYMBOL_GPL(devm_nsio_disable); diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 0fb14890ba26..10e23fe49012 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -13,6 +13,7 @@ #ifndef __ND_H__ #define __ND_H__ #include +#include #include #include #include @@ -197,13 +198,12 @@ struct nd_gen_sb { u64 nd_sb_checksum(struct nd_gen_sb *sb); #if IS_ENABLED(CONFIG_BTT) -int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns, - void *drvdata); +int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns); bool is_nd_btt(struct device *dev); struct device *nd_btt_create(struct nd_region *nd_region); #else static inline int nd_btt_probe(struct device *dev, - struct nd_namespace_common *ndns, void *drvdata) + struct nd_namespace_common *ndns) { return -ENODEV; } @@ -221,14 +221,13 @@ static inline struct device *nd_btt_create(struct nd_region *nd_region) struct nd_pfn *to_nd_pfn(struct device *dev); #if IS_ENABLED(CONFIG_NVDIMM_PFN) -int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns, - void *drvdata); +int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns); bool is_nd_pfn(struct device *dev); struct device *nd_pfn_create(struct nd_region *nd_region); int nd_pfn_validate(struct nd_pfn *nd_pfn); #else -static inline int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns, - void *drvdata) +static inline int nd_pfn_probe(struct device *dev, + struct nd_namespace_common *ndns) { return -ENODEV; } @@ -272,6 +271,20 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, char *name); void nvdimm_badblocks_populate(struct nd_region *nd_region, struct badblocks *bb, const struct resource *res); +#if IS_ENABLED(CONFIG_ND_CLAIM) +int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio); +void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio); +#else +static inline int devm_nsio_enable(struct device *dev, + struct nd_namespace_io *nsio) +{ + return -ENXIO; +} +static inline void devm_nsio_disable(struct device *dev, + struct nd_namespace_io *nsio) +{ +} +#endif int nd_blk_region_init(struct nd_region *nd_region); void __nd_iostat_start(struct bio *bio, unsigned long *start); static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) @@ -285,6 +298,19 @@ static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) return true; } void nd_iostat_end(struct bio *bio, unsigned long start); +static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, + unsigned int len) +{ + if (bb->count) { + sector_t first_bad; + int num_bad; + + return !!badblocks_check(bb, sector, len / 512, &first_bad, + &num_bad); + } + + return false; +} resource_size_t nd_namespace_blk_validate(struct nd_namespace_blk *nsblk); const u8 *nd_dev_to_uuid(struct device *dev); bool pmem_should_map_pages(struct device *dev); diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 96aa5490c279..9df081ae96e3 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -410,8 +410,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn) } EXPORT_SYMBOL(nd_pfn_validate); -int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns, - void *drvdata) +int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns) { int rc; struct nd_pfn *nd_pfn; @@ -427,7 +426,6 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns, nvdimm_bus_unlock(&ndns->dev); if (!pfn_dev) return -ENOMEM; - dev_set_drvdata(pfn_dev, drvdata); pfn_sb = devm_kzalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); nd_pfn = to_nd_pfn(pfn_dev); nd_pfn->pfn_sb = pfn_sb; diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 67d48e2e8ca2..b5f81b02205c 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -49,19 +49,6 @@ struct pmem_device { struct badblocks bb; }; -static bool is_bad_pmem(struct badblocks *bb, sector_t sector, unsigned int len) -{ - if (bb->count) { - sector_t first_bad; - int num_bad; - - return !!badblocks_check(bb, sector, len / 512, &first_bad, - &num_bad); - } - - return false; -} - static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, unsigned int len) { @@ -209,16 +196,40 @@ void pmem_release_disk(void *disk) put_disk(disk); } -static struct pmem_device *pmem_alloc(struct device *dev, - struct resource *res, int id) +static struct vmem_altmap *nvdimm_setup_pfn(struct nd_pfn *nd_pfn, + struct resource *res, struct vmem_altmap *altmap); + +static int pmem_attach_disk(struct device *dev, + struct nd_namespace_common *ndns) { + struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); + struct vmem_altmap __altmap, *altmap = NULL; + struct resource *res = &nsio->res; + struct nd_pfn *nd_pfn = NULL; + int nid = dev_to_node(dev); + struct nd_pfn_sb *pfn_sb; struct pmem_device *pmem; + struct resource pfn_res; struct request_queue *q; + struct gendisk *disk; + void *addr; + + /* while nsio_rw_bytes is active, parse a pfn info block if present */ + if (is_nd_pfn(dev)) { + nd_pfn = to_nd_pfn(dev); + altmap = nvdimm_setup_pfn(nd_pfn, &pfn_res, &__altmap); + if (IS_ERR(altmap)) + return PTR_ERR(altmap); + } + + /* we're attaching a block device, disable raw namespace access */ + devm_nsio_disable(dev, nsio); pmem = devm_kzalloc(dev, sizeof(*pmem), GFP_KERNEL); if (!pmem) - return ERR_PTR(-ENOMEM); + return -ENOMEM; + dev_set_drvdata(dev, pmem); pmem->phys_addr = res->start; pmem->size = resource_size(res); if (!arch_has_wmb_pmem()) @@ -227,22 +238,31 @@ static struct pmem_device *pmem_alloc(struct device *dev, if (!devm_request_mem_region(dev, res->start, resource_size(res), dev_name(dev))) { dev_warn(dev, "could not reserve region %pR\n", res); - return ERR_PTR(-EBUSY); + return -EBUSY; } q = blk_alloc_queue_node(GFP_KERNEL, dev_to_node(dev)); if (!q) - return ERR_PTR(-ENOMEM); + return -ENOMEM; + pmem->pmem_queue = q; pmem->pfn_flags = PFN_DEV; - if (pmem_should_map_pages(dev)) { - pmem->virt_addr = (void __pmem *) devm_memremap_pages(dev, res, + if (is_nd_pfn(dev)) { + addr = devm_memremap_pages(dev, &pfn_res, &q->q_usage_counter, + altmap); + pfn_sb = nd_pfn->pfn_sb; + pmem->data_offset = le64_to_cpu(pfn_sb->dataoff); + pmem->pfn_pad = resource_size(res) - resource_size(&pfn_res); + pmem->pfn_flags |= PFN_MAP; + res = &pfn_res; /* for badblocks populate */ + res->start += pmem->data_offset; + } else if (pmem_should_map_pages(dev)) { + addr = devm_memremap_pages(dev, &nsio->res, &q->q_usage_counter, NULL); pmem->pfn_flags |= PFN_MAP; } else - pmem->virt_addr = (void __pmem *) devm_memremap(dev, - pmem->phys_addr, pmem->size, - ARCH_MEMREMAP_PMEM); + addr = devm_memremap(dev, pmem->phys_addr, + pmem->size, ARCH_MEMREMAP_PMEM); /* * At release time the queue must be dead before @@ -250,23 +270,12 @@ static struct pmem_device *pmem_alloc(struct device *dev, */ if (devm_add_action(dev, pmem_release_queue, q)) { blk_cleanup_queue(q); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } - if (IS_ERR(pmem->virt_addr)) - return (void __force *) pmem->virt_addr; - - pmem->pmem_queue = q; - return pmem; -} - -static int pmem_attach_disk(struct device *dev, - struct nd_namespace_common *ndns, struct pmem_device *pmem) -{ - struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); - int nid = dev_to_node(dev); - struct resource bb_res; - struct gendisk *disk; + if (IS_ERR(addr)) + return PTR_ERR(addr); + pmem->virt_addr = (void __pmem *) addr; blk_queue_make_request(pmem->pmem_queue, pmem_make_request); blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE); @@ -291,20 +300,9 @@ static int pmem_attach_disk(struct device *dev, set_capacity(disk, (pmem->size - pmem->pfn_pad - pmem->data_offset) / 512); pmem->pmem_disk = disk; - devm_exit_badblocks(dev, &pmem->bb); if (devm_init_badblocks(dev, &pmem->bb)) return -ENOMEM; - bb_res.start = nsio->res.start + pmem->data_offset; - bb_res.end = nsio->res.end; - if (is_nd_pfn(dev)) { - struct nd_pfn *nd_pfn = to_nd_pfn(dev); - struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; - - bb_res.start += __le32_to_cpu(pfn_sb->start_pad); - bb_res.end -= __le32_to_cpu(pfn_sb->end_trunc); - } - nvdimm_badblocks_populate(to_nd_region(dev->parent), &pmem->bb, - &bb_res); + nvdimm_badblocks_populate(to_nd_region(dev->parent), &pmem->bb, res); disk->bb = &pmem->bb; add_disk(disk); revalidate_disk(disk); @@ -312,33 +310,8 @@ static int pmem_attach_disk(struct device *dev, return 0; } -static int pmem_rw_bytes(struct nd_namespace_common *ndns, - resource_size_t offset, void *buf, size_t size, int rw) -{ - struct pmem_device *pmem = dev_get_drvdata(ndns->claim); - - if (unlikely(offset + size > pmem->size)) { - dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); - return -EFAULT; - } - - if (rw == READ) { - unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); - - if (unlikely(is_bad_pmem(&pmem->bb, offset / 512, sz_align))) - return -EIO; - return memcpy_from_pmem(buf, pmem->virt_addr + offset, size); - } else { - memcpy_to_pmem(pmem->virt_addr + offset, buf, size); - wmb_pmem(); - } - - return 0; -} - static int nd_pfn_init(struct nd_pfn *nd_pfn) { - struct pmem_device *pmem = dev_get_drvdata(&nd_pfn->dev); struct nd_namespace_common *ndns = nd_pfn->ndns; u32 start_pad = 0, end_trunc = 0; resource_size_t start, size; @@ -404,7 +377,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) * ->direct_access() to those that are included in the memmap. */ start += start_pad; - npfns = (pmem->size - start_pad - end_trunc - SZ_8K) / SZ_4K; + size = resource_size(&nsio->res); + npfns = (size - start_pad - end_trunc - SZ_8K) / SZ_4K; if (nd_pfn->mode == PFN_MODE_PMEM) offset = ALIGN(start + SZ_8K + 64 * npfns, nd_pfn->align) - start; @@ -413,13 +387,13 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) else return -ENXIO; - if (offset + start_pad + end_trunc >= pmem->size) { + if (offset + start_pad + end_trunc >= size) { dev_err(&nd_pfn->dev, "%s unable to satisfy requested alignment\n", dev_name(&ndns->dev)); return -ENXIO; } - npfns = (pmem->size - offset - start_pad - end_trunc) / SZ_4K; + npfns = (size - offset - start_pad - end_trunc) / SZ_4K; pfn_sb->mode = cpu_to_le32(nd_pfn->mode); pfn_sb->dataoff = cpu_to_le64(offset); pfn_sb->npfns = cpu_to_le64(npfns); @@ -456,17 +430,14 @@ static unsigned long init_altmap_reserve(resource_size_t base) return reserve; } -static int __nvdimm_namespace_attach_pfn(struct nd_pfn *nd_pfn) +static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn, + struct resource *res, struct vmem_altmap *altmap) { - struct resource res; - struct request_queue *q; - struct pmem_device *pmem; - struct vmem_altmap *altmap; - struct device *dev = &nd_pfn->dev; struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; - struct nd_namespace_common *ndns = nd_pfn->ndns; + u64 offset = le64_to_cpu(pfn_sb->dataoff); u32 start_pad = __le32_to_cpu(pfn_sb->start_pad); u32 end_trunc = __le32_to_cpu(pfn_sb->end_trunc); + struct nd_namespace_common *ndns = nd_pfn->ndns; struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); resource_size_t base = nsio->res.start + start_pad; struct vmem_altmap __altmap = { @@ -474,112 +445,75 @@ static int __nvdimm_namespace_attach_pfn(struct nd_pfn *nd_pfn) .reserve = init_altmap_reserve(base), }; - pmem = dev_get_drvdata(dev); - pmem->data_offset = le64_to_cpu(pfn_sb->dataoff); - pmem->pfn_pad = start_pad + end_trunc; + memcpy(res, &nsio->res, sizeof(*res)); + res->start += start_pad; + res->end -= end_trunc; + nd_pfn->mode = le32_to_cpu(nd_pfn->pfn_sb->mode); if (nd_pfn->mode == PFN_MODE_RAM) { - if (pmem->data_offset < SZ_8K) - return -EINVAL; + if (offset < SZ_8K) + return ERR_PTR(-EINVAL); nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns); altmap = NULL; } else if (nd_pfn->mode == PFN_MODE_PMEM) { - nd_pfn->npfns = (pmem->size - pmem->pfn_pad - pmem->data_offset) - / PAGE_SIZE; + nd_pfn->npfns = (resource_size(res) - offset) / PAGE_SIZE; if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns) dev_info(&nd_pfn->dev, "number of pfns truncated from %lld to %ld\n", le64_to_cpu(nd_pfn->pfn_sb->npfns), nd_pfn->npfns); - altmap = & __altmap; - altmap->free = PHYS_PFN(pmem->data_offset - SZ_8K); + memcpy(altmap, &__altmap, sizeof(*altmap)); + altmap->free = PHYS_PFN(offset - SZ_8K); altmap->alloc = 0; } else - return -ENXIO; + return ERR_PTR(-ENXIO); - /* establish pfn range for lookup, and switch to direct map */ - q = pmem->pmem_queue; - memcpy(&res, &nsio->res, sizeof(res)); - res.start += start_pad; - res.end -= end_trunc; - devm_remove_action(dev, pmem_release_queue, q); - devm_memunmap(dev, (void __force *) pmem->virt_addr); - pmem->virt_addr = (void __pmem *) devm_memremap_pages(dev, &res, - &q->q_usage_counter, altmap); - pmem->pfn_flags |= PFN_MAP; - - /* - * At release time the queue must be dead before - * devm_memremap_pages is unwound - */ - if (devm_add_action(dev, pmem_release_queue, q)) { - blk_cleanup_queue(q); - return -ENOMEM; - } - if (IS_ERR(pmem->virt_addr)) - return PTR_ERR(pmem->virt_addr); - - /* attach pmem disk in "pfn-mode" */ - return pmem_attach_disk(dev, ndns, pmem); + return altmap; } -static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns) +/* + * Determine the effective resource range and vmem_altmap from an nd_pfn + * instance. + */ +static struct vmem_altmap *nvdimm_setup_pfn(struct nd_pfn *nd_pfn, + struct resource *res, struct vmem_altmap *altmap) { - struct nd_pfn *nd_pfn = to_nd_pfn(ndns->claim); int rc; if (!nd_pfn->uuid || !nd_pfn->ndns) - return -ENODEV; + return ERR_PTR(-ENODEV); rc = nd_pfn_init(nd_pfn); if (rc) - return rc; + return ERR_PTR(rc); + /* we need a valid pfn_sb before we can init a vmem_altmap */ - return __nvdimm_namespace_attach_pfn(nd_pfn); + return __nvdimm_setup_pfn(nd_pfn, res, altmap); } static int nd_pmem_probe(struct device *dev) { - struct nd_region *nd_region = to_nd_region(dev->parent); struct nd_namespace_common *ndns; - struct nd_namespace_io *nsio; - struct pmem_device *pmem; ndns = nvdimm_namespace_common_probe(dev); if (IS_ERR(ndns)) return PTR_ERR(ndns); - nsio = to_nd_namespace_io(&ndns->dev); - pmem = pmem_alloc(dev, &nsio->res, nd_region->id); - if (IS_ERR(pmem)) - return PTR_ERR(pmem); - - dev_set_drvdata(dev, pmem); - ndns->rw_bytes = pmem_rw_bytes; - if (devm_init_badblocks(dev, &pmem->bb)) - return -ENOMEM; - nvdimm_badblocks_populate(nd_region, &pmem->bb, &nsio->res); + if (devm_nsio_enable(dev, to_nd_namespace_io(&ndns->dev))) + return -ENXIO; - if (is_nd_btt(dev)) { - /* btt allocates its own request_queue */ - devm_remove_action(dev, pmem_release_queue, pmem->pmem_queue); - blk_cleanup_queue(pmem->pmem_queue); + if (is_nd_btt(dev)) return nvdimm_namespace_attach_btt(ndns); - } if (is_nd_pfn(dev)) - return nvdimm_namespace_attach_pfn(ndns); + return pmem_attach_disk(dev, ndns); - if (nd_btt_probe(dev, ndns, pmem) == 0 - || nd_pfn_probe(dev, ndns, pmem) == 0) { - /* - * We'll come back as either btt-pmem, or pfn-pmem, so - * drop the queue allocation for now. - */ + /* if we find a valid info-block we'll come back as that personality */ + if (nd_btt_probe(dev, ndns) == 0 || nd_pfn_probe(dev, ndns) == 0) return -ENXIO; - } - return pmem_attach_disk(dev, ndns, pmem); + /* ...otherwise we're just a raw pmem device */ + return pmem_attach_disk(dev, ndns); } static int nd_pmem_remove(struct device *dev) diff --git a/include/linux/nd.h b/include/linux/nd.h index 5ea4aec7fd63..aee2761d294c 100644 --- a/include/linux/nd.h +++ b/include/linux/nd.h @@ -15,6 +15,7 @@ #include #include #include +#include enum nvdimm_event { NVDIMM_REVALIDATE_POISON, @@ -55,13 +56,19 @@ static inline struct nd_namespace_common *to_ndns(struct device *dev) } /** - * struct nd_namespace_io - infrastructure for loading an nd_pmem instance + * struct nd_namespace_io - device representation of a persistent memory range * @dev: namespace device created by the nd region driver * @res: struct resource conversion of a NFIT SPA table + * @size: cached resource_size(@res) for fast path size checks + * @addr: virtual address to access the namespace range + * @bb: badblocks list for the namespace range */ struct nd_namespace_io { struct nd_namespace_common common; struct resource res; + resource_size_t size; + void __pmem *addr; + struct badblocks bb; }; /** diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index a34bfd0c8928..d5bc8c080b44 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild @@ -7,6 +7,7 @@ ldflags-y += --wrap=ioremap_nocache ldflags-y += --wrap=iounmap ldflags-y += --wrap=memunmap ldflags-y += --wrap=__devm_request_region +ldflags-y += --wrap=__devm_release_region ldflags-y += --wrap=__request_region ldflags-y += --wrap=__release_region ldflags-y += --wrap=devm_memremap_pages diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c index 0c1a7e65bb81..c842095f2801 100644 --- a/tools/testing/nvdimm/test/iomap.c +++ b/tools/testing/nvdimm/test/iomap.c @@ -239,13 +239,11 @@ struct resource *__wrap___devm_request_region(struct device *dev, } EXPORT_SYMBOL(__wrap___devm_request_region); -void __wrap___release_region(struct resource *parent, resource_size_t start, - resource_size_t n) +static bool nfit_test_release_region(struct resource *parent, + resource_size_t start, resource_size_t n) { - struct nfit_test_resource *nfit_res; - if (parent == &iomem_resource) { - nfit_res = get_nfit_res(start); + struct nfit_test_resource *nfit_res = get_nfit_res(start); if (nfit_res) { struct resource *res = nfit_res->res + 1; @@ -254,11 +252,26 @@ void __wrap___release_region(struct resource *parent, resource_size_t start, __func__, start, n, res); else memset(res, 0, sizeof(*res)); - return; + return true; } } - __release_region(parent, start, n); + return false; +} + +void __wrap___release_region(struct resource *parent, resource_size_t start, + resource_size_t n) +{ + if (!nfit_test_release_region(parent, start, n)) + __release_region(parent, start, n); } EXPORT_SYMBOL(__wrap___release_region); +void __wrap___devm_release_region(struct device *dev, struct resource *parent, + resource_size_t start, resource_size_t n) +{ + if (!nfit_test_release_region(parent, start, n)) + __devm_release_region(dev, parent, start, n); +} +EXPORT_SYMBOL(__wrap___devm_release_region); + MODULE_LICENSE("GPL v2"); -- GitLab From ac515c084be9b3995f7aef0ae87797e75e0260f0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Mar 2016 00:29:43 -0700 Subject: [PATCH 4017/9938] libnvdimm, pmem, pfn: move pfn setup to the core Now that pmem internals have been disentangled from pfn setup, that code can move to the core. This is in preparation for adding another user of the pfn-device capabilities. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/nd.h | 7 ++ drivers/nvdimm/pfn_devs.c | 181 +++++++++++++++++++++++++++++++++++++ drivers/nvdimm/pmem.c | 184 -------------------------------------- 3 files changed, 188 insertions(+), 184 deletions(-) diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 10e23fe49012..6c36509662e4 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -272,9 +272,16 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, void nvdimm_badblocks_populate(struct nd_region *nd_region, struct badblocks *bb, const struct resource *res); #if IS_ENABLED(CONFIG_ND_CLAIM) +struct vmem_altmap *nvdimm_setup_pfn(struct nd_pfn *nd_pfn, + struct resource *res, struct vmem_altmap *altmap); int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio); void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio); #else +static inline struct vmem_altmap *nvdimm_setup_pfn(struct nd_pfn *nd_pfn, + struct resource *res, struct vmem_altmap *altmap) +{ + return ERR_PTR(-ENXIO); +} static inline int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) { diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 9df081ae96e3..e8693fe65e49 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -10,6 +10,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ +#include #include #include #include @@ -441,3 +442,183 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns) return rc; } EXPORT_SYMBOL(nd_pfn_probe); + +/* + * We hotplug memory at section granularity, pad the reserved area from + * the previous section base to the namespace base address. + */ +static unsigned long init_altmap_base(resource_size_t base) +{ + unsigned long base_pfn = PHYS_PFN(base); + + return PFN_SECTION_ALIGN_DOWN(base_pfn); +} + +static unsigned long init_altmap_reserve(resource_size_t base) +{ + unsigned long reserve = PHYS_PFN(SZ_8K); + unsigned long base_pfn = PHYS_PFN(base); + + reserve += base_pfn - PFN_SECTION_ALIGN_DOWN(base_pfn); + return reserve; +} + +static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn, + struct resource *res, struct vmem_altmap *altmap) +{ + struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; + u64 offset = le64_to_cpu(pfn_sb->dataoff); + u32 start_pad = __le32_to_cpu(pfn_sb->start_pad); + u32 end_trunc = __le32_to_cpu(pfn_sb->end_trunc); + struct nd_namespace_common *ndns = nd_pfn->ndns; + struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); + resource_size_t base = nsio->res.start + start_pad; + struct vmem_altmap __altmap = { + .base_pfn = init_altmap_base(base), + .reserve = init_altmap_reserve(base), + }; + + memcpy(res, &nsio->res, sizeof(*res)); + res->start += start_pad; + res->end -= end_trunc; + + nd_pfn->mode = le32_to_cpu(nd_pfn->pfn_sb->mode); + if (nd_pfn->mode == PFN_MODE_RAM) { + if (offset < SZ_8K) + return ERR_PTR(-EINVAL); + nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns); + altmap = NULL; + } else if (nd_pfn->mode == PFN_MODE_PMEM) { + nd_pfn->npfns = (resource_size(res) - offset) / PAGE_SIZE; + if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns) + dev_info(&nd_pfn->dev, + "number of pfns truncated from %lld to %ld\n", + le64_to_cpu(nd_pfn->pfn_sb->npfns), + nd_pfn->npfns); + memcpy(altmap, &__altmap, sizeof(*altmap)); + altmap->free = PHYS_PFN(offset - SZ_8K); + altmap->alloc = 0; + } else + return ERR_PTR(-ENXIO); + + return altmap; +} + +static int nd_pfn_init(struct nd_pfn *nd_pfn) +{ + struct nd_namespace_common *ndns = nd_pfn->ndns; + u32 start_pad = 0, end_trunc = 0; + resource_size_t start, size; + struct nd_namespace_io *nsio; + struct nd_region *nd_region; + struct nd_pfn_sb *pfn_sb; + unsigned long npfns; + phys_addr_t offset; + u64 checksum; + int rc; + + pfn_sb = devm_kzalloc(&nd_pfn->dev, sizeof(*pfn_sb), GFP_KERNEL); + if (!pfn_sb) + return -ENOMEM; + + nd_pfn->pfn_sb = pfn_sb; + rc = nd_pfn_validate(nd_pfn); + if (rc != -ENODEV) + return rc; + + /* no info block, do init */; + nd_region = to_nd_region(nd_pfn->dev.parent); + if (nd_region->ro) { + dev_info(&nd_pfn->dev, + "%s is read-only, unable to init metadata\n", + dev_name(&nd_region->dev)); + return -ENXIO; + } + + memset(pfn_sb, 0, sizeof(*pfn_sb)); + + /* + * Check if pmem collides with 'System RAM' when section aligned and + * trim it accordingly + */ + nsio = to_nd_namespace_io(&ndns->dev); + start = PHYS_SECTION_ALIGN_DOWN(nsio->res.start); + size = resource_size(&nsio->res); + if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM, + IORES_DESC_NONE) == REGION_MIXED) { + start = nsio->res.start; + start_pad = PHYS_SECTION_ALIGN_UP(start) - start; + } + + start = nsio->res.start; + size = PHYS_SECTION_ALIGN_UP(start + size) - start; + if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM, + IORES_DESC_NONE) == REGION_MIXED) { + size = resource_size(&nsio->res); + end_trunc = start + size - PHYS_SECTION_ALIGN_DOWN(start + size); + } + + if (start_pad + end_trunc) + dev_info(&nd_pfn->dev, "%s section collision, truncate %d bytes\n", + dev_name(&ndns->dev), start_pad + end_trunc); + + /* + * Note, we use 64 here for the standard size of struct page, + * debugging options may cause it to be larger in which case the + * implementation will limit the pfns advertised through + * ->direct_access() to those that are included in the memmap. + */ + start += start_pad; + size = resource_size(&nsio->res); + npfns = (size - start_pad - end_trunc - SZ_8K) / SZ_4K; + if (nd_pfn->mode == PFN_MODE_PMEM) + offset = ALIGN(start + SZ_8K + 64 * npfns, nd_pfn->align) + - start; + else if (nd_pfn->mode == PFN_MODE_RAM) + offset = ALIGN(start + SZ_8K, nd_pfn->align) - start; + else + return -ENXIO; + + if (offset + start_pad + end_trunc >= size) { + dev_err(&nd_pfn->dev, "%s unable to satisfy requested alignment\n", + dev_name(&ndns->dev)); + return -ENXIO; + } + + npfns = (size - offset - start_pad - end_trunc) / SZ_4K; + pfn_sb->mode = cpu_to_le32(nd_pfn->mode); + pfn_sb->dataoff = cpu_to_le64(offset); + pfn_sb->npfns = cpu_to_le64(npfns); + memcpy(pfn_sb->signature, PFN_SIG, PFN_SIG_LEN); + memcpy(pfn_sb->uuid, nd_pfn->uuid, 16); + memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16); + pfn_sb->version_major = cpu_to_le16(1); + pfn_sb->version_minor = cpu_to_le16(1); + pfn_sb->start_pad = cpu_to_le32(start_pad); + pfn_sb->end_trunc = cpu_to_le32(end_trunc); + checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb); + pfn_sb->checksum = cpu_to_le64(checksum); + + return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb)); +} + +/* + * Determine the effective resource range and vmem_altmap from an nd_pfn + * instance. + */ +struct vmem_altmap *nvdimm_setup_pfn(struct nd_pfn *nd_pfn, + struct resource *res, struct vmem_altmap *altmap) +{ + int rc; + + if (!nd_pfn->uuid || !nd_pfn->ndns) + return ERR_PTR(-ENODEV); + + rc = nd_pfn_init(nd_pfn); + if (rc) + return ERR_PTR(rc); + + /* we need a valid pfn_sb before we can init a vmem_altmap */ + return __nvdimm_setup_pfn(nd_pfn, res, altmap); +} +EXPORT_SYMBOL_GPL(nvdimm_setup_pfn); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index b5f81b02205c..3fc68962c1fc 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -196,9 +196,6 @@ void pmem_release_disk(void *disk) put_disk(disk); } -static struct vmem_altmap *nvdimm_setup_pfn(struct nd_pfn *nd_pfn, - struct resource *res, struct vmem_altmap *altmap); - static int pmem_attach_disk(struct device *dev, struct nd_namespace_common *ndns) { @@ -310,187 +307,6 @@ static int pmem_attach_disk(struct device *dev, return 0; } -static int nd_pfn_init(struct nd_pfn *nd_pfn) -{ - struct nd_namespace_common *ndns = nd_pfn->ndns; - u32 start_pad = 0, end_trunc = 0; - resource_size_t start, size; - struct nd_namespace_io *nsio; - struct nd_region *nd_region; - struct nd_pfn_sb *pfn_sb; - unsigned long npfns; - phys_addr_t offset; - u64 checksum; - int rc; - - pfn_sb = devm_kzalloc(&nd_pfn->dev, sizeof(*pfn_sb), GFP_KERNEL); - if (!pfn_sb) - return -ENOMEM; - - nd_pfn->pfn_sb = pfn_sb; - rc = nd_pfn_validate(nd_pfn); - if (rc == -ENODEV) - /* no info block, do init */; - else - return rc; - - nd_region = to_nd_region(nd_pfn->dev.parent); - if (nd_region->ro) { - dev_info(&nd_pfn->dev, - "%s is read-only, unable to init metadata\n", - dev_name(&nd_region->dev)); - return -ENXIO; - } - - memset(pfn_sb, 0, sizeof(*pfn_sb)); - - /* - * Check if pmem collides with 'System RAM' when section aligned and - * trim it accordingly - */ - nsio = to_nd_namespace_io(&ndns->dev); - start = PHYS_SECTION_ALIGN_DOWN(nsio->res.start); - size = resource_size(&nsio->res); - if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM, - IORES_DESC_NONE) == REGION_MIXED) { - - start = nsio->res.start; - start_pad = PHYS_SECTION_ALIGN_UP(start) - start; - } - - start = nsio->res.start; - size = PHYS_SECTION_ALIGN_UP(start + size) - start; - if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM, - IORES_DESC_NONE) == REGION_MIXED) { - size = resource_size(&nsio->res); - end_trunc = start + size - PHYS_SECTION_ALIGN_DOWN(start + size); - } - - if (start_pad + end_trunc) - dev_info(&nd_pfn->dev, "%s section collision, truncate %d bytes\n", - dev_name(&ndns->dev), start_pad + end_trunc); - - /* - * Note, we use 64 here for the standard size of struct page, - * debugging options may cause it to be larger in which case the - * implementation will limit the pfns advertised through - * ->direct_access() to those that are included in the memmap. - */ - start += start_pad; - size = resource_size(&nsio->res); - npfns = (size - start_pad - end_trunc - SZ_8K) / SZ_4K; - if (nd_pfn->mode == PFN_MODE_PMEM) - offset = ALIGN(start + SZ_8K + 64 * npfns, nd_pfn->align) - - start; - else if (nd_pfn->mode == PFN_MODE_RAM) - offset = ALIGN(start + SZ_8K, nd_pfn->align) - start; - else - return -ENXIO; - - if (offset + start_pad + end_trunc >= size) { - dev_err(&nd_pfn->dev, "%s unable to satisfy requested alignment\n", - dev_name(&ndns->dev)); - return -ENXIO; - } - - npfns = (size - offset - start_pad - end_trunc) / SZ_4K; - pfn_sb->mode = cpu_to_le32(nd_pfn->mode); - pfn_sb->dataoff = cpu_to_le64(offset); - pfn_sb->npfns = cpu_to_le64(npfns); - memcpy(pfn_sb->signature, PFN_SIG, PFN_SIG_LEN); - memcpy(pfn_sb->uuid, nd_pfn->uuid, 16); - memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16); - pfn_sb->version_major = cpu_to_le16(1); - pfn_sb->version_minor = cpu_to_le16(1); - pfn_sb->start_pad = cpu_to_le32(start_pad); - pfn_sb->end_trunc = cpu_to_le32(end_trunc); - checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb); - pfn_sb->checksum = cpu_to_le64(checksum); - - return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb)); -} - -/* - * We hotplug memory at section granularity, pad the reserved area from - * the previous section base to the namespace base address. - */ -static unsigned long init_altmap_base(resource_size_t base) -{ - unsigned long base_pfn = PHYS_PFN(base); - - return PFN_SECTION_ALIGN_DOWN(base_pfn); -} - -static unsigned long init_altmap_reserve(resource_size_t base) -{ - unsigned long reserve = PHYS_PFN(SZ_8K); - unsigned long base_pfn = PHYS_PFN(base); - - reserve += base_pfn - PFN_SECTION_ALIGN_DOWN(base_pfn); - return reserve; -} - -static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn, - struct resource *res, struct vmem_altmap *altmap) -{ - struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; - u64 offset = le64_to_cpu(pfn_sb->dataoff); - u32 start_pad = __le32_to_cpu(pfn_sb->start_pad); - u32 end_trunc = __le32_to_cpu(pfn_sb->end_trunc); - struct nd_namespace_common *ndns = nd_pfn->ndns; - struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); - resource_size_t base = nsio->res.start + start_pad; - struct vmem_altmap __altmap = { - .base_pfn = init_altmap_base(base), - .reserve = init_altmap_reserve(base), - }; - - memcpy(res, &nsio->res, sizeof(*res)); - res->start += start_pad; - res->end -= end_trunc; - - nd_pfn->mode = le32_to_cpu(nd_pfn->pfn_sb->mode); - if (nd_pfn->mode == PFN_MODE_RAM) { - if (offset < SZ_8K) - return ERR_PTR(-EINVAL); - nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns); - altmap = NULL; - } else if (nd_pfn->mode == PFN_MODE_PMEM) { - nd_pfn->npfns = (resource_size(res) - offset) / PAGE_SIZE; - if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns) - dev_info(&nd_pfn->dev, - "number of pfns truncated from %lld to %ld\n", - le64_to_cpu(nd_pfn->pfn_sb->npfns), - nd_pfn->npfns); - memcpy(altmap, &__altmap, sizeof(*altmap)); - altmap->free = PHYS_PFN(offset - SZ_8K); - altmap->alloc = 0; - } else - return ERR_PTR(-ENXIO); - - return altmap; -} - -/* - * Determine the effective resource range and vmem_altmap from an nd_pfn - * instance. - */ -static struct vmem_altmap *nvdimm_setup_pfn(struct nd_pfn *nd_pfn, - struct resource *res, struct vmem_altmap *altmap) -{ - int rc; - - if (!nd_pfn->uuid || !nd_pfn->ndns) - return ERR_PTR(-ENODEV); - - rc = nd_pfn_init(nd_pfn); - if (rc) - return ERR_PTR(rc); - - /* we need a valid pfn_sb before we can init a vmem_altmap */ - return __nvdimm_setup_pfn(nd_pfn, res, altmap); -} - static int nd_pmem_probe(struct device *dev) { struct nd_namespace_common *ndns; -- GitLab From 5a92289f41311a54ededb5e4ed474cc38f5d85de Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Mar 2016 15:43:53 -0700 Subject: [PATCH 4018/9938] libnvdimm, pmem: kill ->pmem_queue and ->pmem_disk The devm conversion obviates the need to continue to remember the queue and disk locally in the driver. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/pmem.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 3fc68962c1fc..d9a0dbc2d023 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -33,9 +33,6 @@ #include "nd.h" struct pmem_device { - struct request_queue *pmem_queue; - struct gendisk *pmem_disk; - /* One contiguous memory region per device */ phys_addr_t phys_addr; /* when non-zero this device is hosting a 'pfn' instance */ @@ -52,7 +49,7 @@ struct pmem_device { static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, unsigned int len) { - struct device *dev = disk_to_dev(pmem->pmem_disk); + struct device *dev = pmem->bb.dev; sector_t sector; long cleared; @@ -241,7 +238,6 @@ static int pmem_attach_disk(struct device *dev, q = blk_alloc_queue_node(GFP_KERNEL, dev_to_node(dev)); if (!q) return -ENOMEM; - pmem->pmem_queue = q; pmem->pfn_flags = PFN_DEV; if (is_nd_pfn(dev)) { @@ -274,12 +270,12 @@ static int pmem_attach_disk(struct device *dev, return PTR_ERR(addr); pmem->virt_addr = (void __pmem *) addr; - blk_queue_make_request(pmem->pmem_queue, pmem_make_request); - blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE); - blk_queue_max_hw_sectors(pmem->pmem_queue, UINT_MAX); - blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY); - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, pmem->pmem_queue); - pmem->pmem_queue->queuedata = pmem; + blk_queue_make_request(q, pmem_make_request); + blk_queue_physical_block_size(q, PAGE_SIZE); + blk_queue_max_hw_sectors(q, UINT_MAX); + blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); + q->queuedata = pmem; disk = alloc_disk_node(0, nid); if (!disk) @@ -290,13 +286,12 @@ static int pmem_attach_disk(struct device *dev, } disk->fops = &pmem_fops; - disk->queue = pmem->pmem_queue; + disk->queue = q; disk->flags = GENHD_FL_EXT_DEVT; nvdimm_namespace_disk_name(ndns, disk->disk_name); disk->driverfs_dev = dev; set_capacity(disk, (pmem->size - pmem->pfn_pad - pmem->data_offset) / 512); - pmem->pmem_disk = disk; if (devm_init_badblocks(dev, &pmem->bb)) return -ENOMEM; nvdimm_badblocks_populate(to_nd_region(dev->parent), &pmem->bb, res); -- GitLab From 0bfb8dd3edd6e423b5053c86e10c97e92cf205ea Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 13 Apr 2016 17:06:48 -0700 Subject: [PATCH 4019/9938] libnvdimm: cleanup nvdimm_namespace_common_probe(), kill 'host' The 'host' variable can be killed as it is always the same as the passed in device. Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/namespace_devs.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index f5cb88601359..e5ad5162bf34 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -1379,21 +1379,16 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev) { struct nd_btt *nd_btt = is_nd_btt(dev) ? to_nd_btt(dev) : NULL; struct nd_pfn *nd_pfn = is_nd_pfn(dev) ? to_nd_pfn(dev) : NULL; - struct nd_namespace_common *ndns; + struct nd_namespace_common *ndns = NULL; resource_size_t size; if (nd_btt || nd_pfn) { - struct device *host = NULL; - - if (nd_btt) { - host = &nd_btt->dev; + if (nd_btt) ndns = nd_btt->ndns; - } else if (nd_pfn) { - host = &nd_pfn->dev; + else if (nd_pfn) ndns = nd_pfn->ndns; - } - if (!ndns || !host) + if (!ndns) return ERR_PTR(-ENODEV); /* @@ -1404,12 +1399,12 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev) device_unlock(&ndns->dev); if (ndns->dev.driver) { dev_dbg(&ndns->dev, "is active, can't bind %s\n", - dev_name(host)); + dev_name(dev)); return ERR_PTR(-EBUSY); } - if (dev_WARN_ONCE(&ndns->dev, ndns->claim != host, + if (dev_WARN_ONCE(&ndns->dev, ndns->claim != dev, "host (%s) vs claim (%s) mismatch\n", - dev_name(host), + dev_name(dev), dev_name(ndns->claim))) return ERR_PTR(-ENXIO); } else { -- GitLab From d29c9ab1a2c81ce404883baba91e15ae35411900 Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Fri, 22 Apr 2016 20:14:58 -0400 Subject: [PATCH 4020/9938] IB/core: Fix oops in ib_cache_gid_set_default_gid When we fail to find the default gid index, we can't continue processing in this routine or else we will pass a negative index to later routines resulting in invalid memory access attempts and a kernel oops. Fixes: 03db3a2d81e6 (IB/core: Add RoCE GID table management) Signed-off-by: Doug Ledford --- drivers/infiniband/core/cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index cb00d59da456..c2e257d97eff 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -691,7 +691,8 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port, NULL); /* Coudn't find default GID location */ - WARN_ON(ix < 0); + if (WARN_ON(ix < 0)) + goto release; zattr_type.gid_type = gid_type; -- GitLab From 2c911f6cac9388830d2afb350d29f43f115b1a28 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 16 Apr 2016 22:13:55 +0200 Subject: [PATCH 4021/9938] EDAC, altera: Remove useless casts The altera EDAC driver refers to its per-device data using a cast to '(void *)', which makes the pointer non-const, though both the source and destination are actually const. Removing the annotation makes the reference (almost) fit into a single line for improved readability, and ensures that it is actually defined as const. Signed-off-by: Arnd Bergmann Acked-by: Thor Thayer Cc: Alan Tull Cc: Dinh Nguyen Cc: linux-edac Link: http://lkml.kernel.org/r/1460837650-1237650-1-git-send-email-arnd@arndb.de Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 11775dc0b139..cc987b4ce908 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -232,8 +232,8 @@ static unsigned long get_total_mem(void) } static const struct of_device_id altr_sdram_ctrl_of_match[] = { - { .compatible = "altr,sdram-edac", .data = (void *)&c5_data}, - { .compatible = "altr,sdram-edac-a10", .data = (void *)&a10_data}, + { .compatible = "altr,sdram-edac", .data = &c5_data}, + { .compatible = "altr,sdram-edac-a10", .data = &a10_data}, {}, }; MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match); @@ -705,15 +705,12 @@ static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci, static const struct of_device_id altr_edac_device_of_match[] = { #ifdef CONFIG_EDAC_ALTERA_L2C - { .compatible = "altr,socfpga-l2-ecc", .data = (void *)&l2ecc_data }, - { .compatible = "altr,socfpga-a10-l2-ecc", - .data = (void *)&a10_l2ecc_data }, + { .compatible = "altr,socfpga-l2-ecc", .data = &l2ecc_data }, + { .compatible = "altr,socfpga-a10-l2-ecc", .data = &a10_l2ecc_data }, #endif #ifdef CONFIG_EDAC_ALTERA_OCRAM - { .compatible = "altr,socfpga-ocram-ecc", - .data = (void *)&ocramecc_data }, - { .compatible = "altr,socfpga-a10-ocram-ecc", - .data = (void *)&a10_ocramecc_data }, + { .compatible = "altr,socfpga-ocram-ecc", .data = &ocramecc_data }, + { .compatible = "altr,socfpga-a10-ocram-ecc", .data = &a10_ocramecc_data }, #endif {}, }; -- GitLab From 1aa6eb5c5b35771cfb28265eccd99b4b203b4154 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 16 Apr 2016 22:13:56 +0200 Subject: [PATCH 4022/9938] EDAC, altera: Avoid unused function warnings The recently added Arria10 OCRAM ECC support caused some new harmless warnings about unused functions when it is disabled: drivers/edac/altera_edac.c:1067:20: error: 'altr_edac_a10_ecc_irq' defined but not used [-Werror=unused-function] drivers/edac/altera_edac.c:658:12: error: 'altr_check_ecc_deps' defined but not used [-Werror=unused-function] This rearranges the code slightly to have those two functions inside of the same #ifdef that hides their callers. It also manages to avoid a forward declaration of the IRQ handler in the process. Signed-off-by: Arnd Bergmann Acked-by: Thor Thayer Cc: Alan Tull Cc: Dinh Nguyen Cc: linux-edac Fixes: c7b4be8db8bc ("EDAC, altera: Add Arria10 OCRAM ECC support") Link: http://lkml.kernel.org/r/1460837650-1237650-2-git-send-email-arnd@arndb.de Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 78 ++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index cc987b4ce908..5b4d223d6d68 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -649,26 +649,6 @@ static ssize_t altr_edac_device_trig(struct file *file, return count; } -/* - * Test for memory's ECC dependencies upon entry because platform specific - * startup should have initialized the memory and enabled the ECC. - * Can't turn on ECC here because accessing un-initialized memory will - * cause CE/UE errors possibly causing an ABORT. - */ -static int altr_check_ecc_deps(struct altr_edac_device_dev *device) -{ - void __iomem *base = device->base; - const struct edac_device_prv_data *prv = device->data; - - if (readl(base + prv->ecc_en_ofst) & prv->ecc_enable_mask) - return 0; - - edac_printk(KERN_ERR, EDAC_DEVICE, - "%s: No ECC present or ECC disabled.\n", - device->edac_dev_name); - return -ENODEV; -} - static const struct file_operations altr_edac_device_inject_fops = { .open = simple_open, .write = altr_edac_device_trig, @@ -848,6 +828,25 @@ module_platform_driver(altr_edac_device_driver); /*********************** OCRAM EDAC Device Functions *********************/ #ifdef CONFIG_EDAC_ALTERA_OCRAM +/* + * Test for memory's ECC dependencies upon entry because platform specific + * startup should have initialized the memory and enabled the ECC. + * Can't turn on ECC here because accessing un-initialized memory will + * cause CE/UE errors possibly causing an ABORT. + */ +static int altr_check_ecc_deps(struct altr_edac_device_dev *device) +{ + void __iomem *base = device->base; + const struct edac_device_prv_data *prv = device->data; + + if (readl(base + prv->ecc_en_ofst) & prv->ecc_enable_mask) + return 0; + + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s: No ECC present or ECC disabled.\n", + device->edac_dev_name); + return -ENODEV; +} static void *ocram_alloc_mem(size_t size, void **other) { @@ -883,6 +882,24 @@ static void ocram_free_mem(void *p, size_t size, void *other) gen_pool_free((struct gen_pool *)other, (u32)p, size); } +static irqreturn_t altr_edac_a10_ecc_irq(struct altr_edac_device_dev *dci, + bool sberr) +{ + void __iomem *base = dci->base; + + if (sberr) { + writel(ALTR_A10_ECC_SERRPENA, + base + ALTR_A10_ECC_INTSTAT_OFST); + edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name); + } else { + writel(ALTR_A10_ECC_DERRPENA, + base + ALTR_A10_ECC_INTSTAT_OFST); + edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name); + panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n"); + } + return IRQ_HANDLED; +} + const struct edac_device_prv_data ocramecc_data = { .setup = altr_check_ecc_deps, .ce_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_SERR), @@ -899,9 +916,6 @@ const struct edac_device_prv_data ocramecc_data = { .inject_fops = &altr_edac_device_inject_fops, }; -static irqreturn_t altr_edac_a10_ecc_irq(struct altr_edac_device_dev *dci, - bool sberr); - const struct edac_device_prv_data a10_ocramecc_data = { .setup = altr_check_ecc_deps, .ce_clear_mask = ALTR_A10_ECC_SERRPENA, @@ -1061,24 +1075,6 @@ static ssize_t altr_edac_a10_device_trig(struct file *file, return count; } -static irqreturn_t altr_edac_a10_ecc_irq(struct altr_edac_device_dev *dci, - bool sberr) -{ - void __iomem *base = dci->base; - - if (sberr) { - writel(ALTR_A10_ECC_SERRPENA, - base + ALTR_A10_ECC_INTSTAT_OFST); - edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name); - } else { - writel(ALTR_A10_ECC_DERRPENA, - base + ALTR_A10_ECC_INTSTAT_OFST); - edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name); - panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n"); - } - return IRQ_HANDLED; -} - static irqreturn_t altr_edac_a10_irq_handler(int irq, void *dev_id) { irqreturn_t rc = IRQ_NONE; -- GitLab From ab67b6c22d8506b060a66ed0ce1a3e14e3b075e4 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 21 Apr 2016 10:34:14 -0700 Subject: [PATCH 4023/9938] EDAC: Fix used after kfree() error in edac_unregister_sysfs() Code flow looks like this: device_unregister(&mci->dev); -> kobject_put+0x25/0x50 -> kobject_cleanup+0x77/0x190 -> device_release+0x32/0xa0 -> mci_attr_release+0x36/0x70 -> kfree(mci); bus_unregister(mci->bus); Fix is to grab a local copy of "mci->bus" and use that when we call bus_unregister(). Signed-off-by: Tony Luck Acked-by: Aristeu Rozanski Cc: Mauro Carvalho Chehab Cc: linux-edac Link: http://lkml.kernel.org/r/21d595b0ab3d718d9cb206647f4ec91c05e62ec4.1461261078.git.tony.luck@intel.com Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc_sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 26e65ab5932a..10c305b4a2e1 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -998,11 +998,12 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) void edac_unregister_sysfs(struct mem_ctl_info *mci) { + struct bus_type *bus = mci->bus; const char *name = mci->bus->name; edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); device_unregister(&mci->dev); - bus_unregister(mci->bus); + bus_unregister(bus); kfree(name); } -- GitLab From ad08c4e97485694fee5ebb181983514facedbb19 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 15 Apr 2016 14:50:32 -0700 Subject: [PATCH 4024/9938] EDAC, sb_edac: Remove double buffering of error records In the bad old days the functions from x86_mce_decoder_chain could be called in machine check context. So we used to carefully copy them and defer processing until later. But in f29a7aff4bd60 ("x86/mce: Avoid potential deadlock due to printk() in MCE context") we switched the logging code to save the record in a genpool, and call the functions that registered to be notified later from a work queue. So drop all the double buffering and do all the work we want to do as soon as sbridge_mce_check_error() is called. Signed-off-by: Tony Luck Cc: Aristeu Rozanski Cc: Mauro Carvalho Chehab Cc: linux-edac Cc: patrickg@supermicro.com Link: http://lkml.kernel.org/r/100025611cd780d9bca72792b2b2146760da53e0.1460756761.git.tony.luck@intel.com Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 88 ++---------------------------------------- 1 file changed, 3 insertions(+), 85 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 93f0d4120289..342167496626 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -363,16 +363,6 @@ struct sbridge_pvt { /* Memory type detection */ bool is_mirrored, is_lockstep, is_close_pg; - /* Fifo double buffers */ - struct mce mce_entry[MCE_LOG_LEN]; - struct mce mce_outentry[MCE_LOG_LEN]; - - /* Fifo in/out counters */ - unsigned mce_in, mce_out; - - /* Count indicator to show errors not got */ - unsigned mce_overrun; - /* Memory description */ u64 tolm, tohm; struct knl_pvt knl; @@ -3075,63 +3065,8 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, } /* - * sbridge_check_error Retrieve and process errors reported by the - * hardware. Called by the Core module. - */ -static void sbridge_check_error(struct mem_ctl_info *mci) -{ - struct sbridge_pvt *pvt = mci->pvt_info; - int i; - unsigned count = 0; - struct mce *m; - - /* - * MCE first step: Copy all mce errors into a temporary buffer - * We use a double buffering here, to reduce the risk of - * loosing an error. - */ - smp_rmb(); - count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in) - % MCE_LOG_LEN; - if (!count) - return; - - m = pvt->mce_outentry; - if (pvt->mce_in + count > MCE_LOG_LEN) { - unsigned l = MCE_LOG_LEN - pvt->mce_in; - - memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l); - smp_wmb(); - pvt->mce_in = 0; - count -= l; - m += l; - } - memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count); - smp_wmb(); - pvt->mce_in += count; - - smp_rmb(); - if (pvt->mce_overrun) { - sbridge_printk(KERN_ERR, "Lost %d memory errors\n", - pvt->mce_overrun); - smp_wmb(); - pvt->mce_overrun = 0; - } - - /* - * MCE second step: parse errors and display - */ - for (i = 0; i < count; i++) - sbridge_mce_output_error(mci, &pvt->mce_outentry[i]); -} - -/* - * sbridge_mce_check_error Replicates mcelog routine to get errors - * This routine simply queues mcelog errors, and - * return. The error itself should be handled later - * by sbridge_check_error. - * WARNING: As this routine should be called at NMI time, extra care should - * be taken to avoid deadlocks, and to be as fast as possible. + * Check that logging is enabled and that this is the right type + * of error for us to handle. */ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, void *data) @@ -3176,21 +3111,7 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, "%u APIC %x\n", mce->cpuvendor, mce->cpuid, mce->time, mce->socketid, mce->apicid); - smp_rmb(); - if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { - smp_wmb(); - pvt->mce_overrun++; - return NOTIFY_DONE; - } - - /* Copy memory error at the ringbuffer */ - memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce)); - smp_wmb(); - pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN; - - /* Handle fatal errors immediately */ - if (mce->mcgstatus & 1) - sbridge_check_error(mci); + sbridge_mce_output_error(mci, mce); /* Advice mcelog that the error were handled */ return NOTIFY_STOP; @@ -3276,9 +3197,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; - /* Set the function pointer to an actual operation function */ - mci->edac_check = sbridge_check_error; - pvt->info.type = type; switch (type) { case IVY_BRIDGE: -- GitLab From 8b92c3a78d40fb220dc5ab122e3274d1b126bfbb Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Fri, 15 Apr 2016 00:42:47 -0700 Subject: [PATCH 4025/9938] perf/x86/intel: Add Goldmont CPU support Add perf core PMU support for Intel Goldmont CPU cores: - The init code is based on Silvermont. - There is a new cache event list, based on the Silvermont cache event list. - Goldmont has 32 LBR entries. It also uses new LBRv6 format, which report the cycle information using upper 16-bit of the LBR_TO. - It's recommended to use CPU_CLK_UNHALTED.CORE_P + NPEBS for precise cycles. For details, please refer to the latest SDM058: http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3b-part-2-manual.pdf Signed-off-by: Kan Liang Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1460706167-45320-1-git-send-email-kan.liang@intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/core.c | 157 +++++++++++++++++++++++++++++++++++ arch/x86/events/intel/ds.c | 6 ++ arch/x86/events/intel/lbr.c | 13 ++- arch/x86/events/perf_event.h | 2 + 4 files changed, 177 insertions(+), 1 deletion(-) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index aff79884e17d..92fda6bb779e 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -1465,6 +1465,140 @@ static __initconst const u64 slm_hw_cache_event_ids }, }; +static struct extra_reg intel_glm_extra_regs[] __read_mostly = { + /* must define OFFCORE_RSP_X first, see intel_fixup_er() */ + INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x760005ffbfull, RSP_0), + INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0x360005ffbfull, RSP_1), + EVENT_EXTRA_END +}; + +#define GLM_DEMAND_DATA_RD BIT_ULL(0) +#define GLM_DEMAND_RFO BIT_ULL(1) +#define GLM_ANY_RESPONSE BIT_ULL(16) +#define GLM_SNP_NONE_OR_MISS BIT_ULL(33) +#define GLM_DEMAND_READ GLM_DEMAND_DATA_RD +#define GLM_DEMAND_WRITE GLM_DEMAND_RFO +#define GLM_DEMAND_PREFETCH (SNB_PF_DATA_RD|SNB_PF_RFO) +#define GLM_LLC_ACCESS GLM_ANY_RESPONSE +#define GLM_SNP_ANY (GLM_SNP_NONE_OR_MISS|SNB_NO_FWD|SNB_HITM) +#define GLM_LLC_MISS (GLM_SNP_ANY|SNB_NON_DRAM) + +static __initconst const u64 glm_hw_cache_event_ids + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = { + [C(L1D)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0x81d0, /* MEM_UOPS_RETIRED.ALL_LOADS */ + [C(RESULT_MISS)] = 0x0, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = 0x82d0, /* MEM_UOPS_RETIRED.ALL_STORES */ + [C(RESULT_MISS)] = 0x0, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = 0x0, + [C(RESULT_MISS)] = 0x0, + }, + }, + [C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0x0380, /* ICACHE.ACCESSES */ + [C(RESULT_MISS)] = 0x0280, /* ICACHE.MISSES */ + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS)] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = 0x0, + [C(RESULT_MISS)] = 0x0, + }, + }, + [C(LL)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0x1b7, /* OFFCORE_RESPONSE */ + [C(RESULT_MISS)] = 0x1b7, /* OFFCORE_RESPONSE */ + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = 0x1b7, /* OFFCORE_RESPONSE */ + [C(RESULT_MISS)] = 0x1b7, /* OFFCORE_RESPONSE */ + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = 0x1b7, /* OFFCORE_RESPONSE */ + [C(RESULT_MISS)] = 0x1b7, /* OFFCORE_RESPONSE */ + }, + }, + [C(DTLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0x81d0, /* MEM_UOPS_RETIRED.ALL_LOADS */ + [C(RESULT_MISS)] = 0x0, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = 0x82d0, /* MEM_UOPS_RETIRED.ALL_STORES */ + [C(RESULT_MISS)] = 0x0, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = 0x0, + [C(RESULT_MISS)] = 0x0, + }, + }, + [C(ITLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0x00c0, /* INST_RETIRED.ANY_P */ + [C(RESULT_MISS)] = 0x0481, /* ITLB.MISS */ + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS)] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS)] = -1, + }, + }, + [C(BPU)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */ + [C(RESULT_MISS)] = 0x00c5, /* BR_MISP_RETIRED.ALL_BRANCHES */ + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS)] = -1, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = -1, + [C(RESULT_MISS)] = -1, + }, + }, +}; + +static __initconst const u64 glm_hw_cache_extra_regs + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = { + [C(LL)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = GLM_DEMAND_READ| + GLM_LLC_ACCESS, + [C(RESULT_MISS)] = GLM_DEMAND_READ| + GLM_LLC_MISS, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = GLM_DEMAND_WRITE| + GLM_LLC_ACCESS, + [C(RESULT_MISS)] = GLM_DEMAND_WRITE| + GLM_LLC_MISS, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = GLM_DEMAND_PREFETCH| + GLM_LLC_ACCESS, + [C(RESULT_MISS)] = GLM_DEMAND_PREFETCH| + GLM_LLC_MISS, + }, + }, +}; + #define KNL_OT_L2_HITE BIT_ULL(19) /* Other Tile L2 Hit */ #define KNL_OT_L2_HITF BIT_ULL(20) /* Other Tile L2 Hit */ #define KNL_MCDRAM_LOCAL BIT_ULL(21) @@ -3456,6 +3590,29 @@ __init int intel_pmu_init(void) pr_cont("Silvermont events, "); break; + case 92: /* 14nm Atom "Goldmont" */ + case 95: /* 14nm Atom "Goldmont Denverton" */ + memcpy(hw_cache_event_ids, glm_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); + memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs, + sizeof(hw_cache_extra_regs)); + + intel_pmu_lbr_init_skl(); + + x86_pmu.event_constraints = intel_slm_event_constraints; + x86_pmu.pebs_constraints = intel_glm_pebs_event_constraints; + x86_pmu.extra_regs = intel_glm_extra_regs; + /* + * It's recommended to use CPU_CLK_UNHALTED.CORE_P + NPEBS + * for precise cycles. + * :pp is identical to :ppp + */ + x86_pmu.pebs_aliases = NULL; + x86_pmu.pebs_prec_dist = true; + x86_pmu.flags |= PMU_FL_HAS_RSP_1; + pr_cont("Goldmont events, "); + break; + case 37: /* 32nm Westmere */ case 44: /* 32nm Westmere-EP */ case 47: /* 32nm Westmere-EX */ diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 8584b90d8e0b..7ce9f3f669e6 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -645,6 +645,12 @@ struct event_constraint intel_slm_pebs_event_constraints[] = { EVENT_CONSTRAINT_END }; +struct event_constraint intel_glm_pebs_event_constraints[] = { + /* Allow all events as PEBS with no flags */ + INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), + EVENT_CONSTRAINT_END +}; + struct event_constraint intel_nehalem_pebs_event_constraints[] = { INTEL_PLD_CONSTRAINT(0x100b, 0xf), /* MEM_INST_RETIRED.* */ INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */ diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index 6c3b7c1780c9..ad26ca770c98 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -14,7 +14,8 @@ enum { LBR_FORMAT_EIP_FLAGS = 0x03, LBR_FORMAT_EIP_FLAGS2 = 0x04, LBR_FORMAT_INFO = 0x05, - LBR_FORMAT_MAX_KNOWN = LBR_FORMAT_INFO, + LBR_FORMAT_TIME = 0x06, + LBR_FORMAT_MAX_KNOWN = LBR_FORMAT_TIME, }; static enum { @@ -464,6 +465,16 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) abort = !!(info & LBR_INFO_ABORT); cycles = (info & LBR_INFO_CYCLES); } + + if (lbr_format == LBR_FORMAT_TIME) { + mis = !!(from & LBR_FROM_FLAG_MISPRED); + pred = !mis; + skip = 1; + cycles = ((to >> 48) & LBR_INFO_CYCLES); + + to = (u64)((((s64)to) << 16) >> 16); + } + if (lbr_flags & LBR_EIP_FLAGS) { mis = !!(from & LBR_FROM_FLAG_MISPRED); pred = !mis; diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index ad4dc7ffffb5..8b78481d1e64 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -859,6 +859,8 @@ extern struct event_constraint intel_atom_pebs_event_constraints[]; extern struct event_constraint intel_slm_pebs_event_constraints[]; +extern struct event_constraint intel_glm_pebs_event_constraints[]; + extern struct event_constraint intel_nehalem_pebs_event_constraints[]; extern struct event_constraint intel_westmere_pebs_event_constraints[]; -- GitLab From f21d5adceb7f2660e5227569faed278f6fb2072e Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Fri, 15 Apr 2016 00:53:45 -0700 Subject: [PATCH 4026/9938] perf/x86/intel: Add LBR filter support for Silvermont and Airmont CPUs LBR filtering is also supported on the Silvermont and Airmont microarchitectures. The layout of MSR_LBR_SELECT is the same as Nehalem. Signed-off-by: Kan Liang Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1460706825-46163-1-git-send-email-kan.liang@intel.com Signed-off-by: Ingo Molnar --- arch/x86/events/intel/core.c | 2 +- arch/x86/events/intel/lbr.c | 18 ++++++++++++++++++ arch/x86/events/perf_event.h | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 92fda6bb779e..79b59437f5ee 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3581,7 +3581,7 @@ __init int intel_pmu_init(void) memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs, sizeof(hw_cache_extra_regs)); - intel_pmu_lbr_init_atom(); + intel_pmu_lbr_init_slm(); x86_pmu.event_constraints = intel_slm_event_constraints; x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints; diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index ad26ca770c98..317e29e3869e 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -1058,6 +1058,24 @@ void __init intel_pmu_lbr_init_atom(void) pr_cont("8-deep LBR, "); } +/* slm */ +void __init intel_pmu_lbr_init_slm(void) +{ + x86_pmu.lbr_nr = 8; + x86_pmu.lbr_tos = MSR_LBR_TOS; + x86_pmu.lbr_from = MSR_LBR_CORE_FROM; + x86_pmu.lbr_to = MSR_LBR_CORE_TO; + + x86_pmu.lbr_sel_mask = LBR_SEL_MASK; + x86_pmu.lbr_sel_map = nhm_lbr_sel_map; + + /* + * SW branch filter usage: + * - compensate for lack of HW filter + */ + pr_cont("8-deep LBR, "); +} + /* Knights Landing */ void intel_pmu_lbr_init_knl(void) { diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index 8b78481d1e64..7d62a02f49a4 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -909,6 +909,8 @@ void intel_pmu_lbr_init_nhm(void); void intel_pmu_lbr_init_atom(void); +void intel_pmu_lbr_init_slm(void); + void intel_pmu_lbr_init_snb(void); void intel_pmu_lbr_init_hsw(void); -- GitLab From 9ecda41acb971ebd07c8fb35faf24005c0baea12 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Tue, 5 Apr 2016 14:11:18 +0000 Subject: [PATCH 4027/9938] perf/core: Add ::write_backward attribute to perf event This patch introduces 'write_backward' bit to perf_event_attr, which controls the direction of a ring buffer. After set, the corresponding ring buffer is written from end to beginning. This feature is design to support reading from overwritable ring buffer. Ring buffer can be created by mapping a perf event fd. Kernel puts event records into ring buffer, user tooling like perf fetch them from address returned by mmap(). To prevent racing between kernel and tooling, they communicate to each other through 'head' and 'tail' pointers. Kernel maintains 'head' pointer, points it to the next free area (tail of the last record). Tooling maintains 'tail' pointer, points it to the tail of last consumed record (record has already been fetched). Kernel determines the available space in a ring buffer using these two pointers to avoid overwrite unfetched records. By mapping without 'PROT_WRITE', an overwritable ring buffer is created. Different from normal ring buffer, tooling is unable to maintain 'tail' pointer because writing is forbidden. Therefore, for this type of ring buffers, kernel overwrite old records unconditionally, works like flight recorder. This feature would be useful if reading from overwritable ring buffer were as easy as reading from normal ring buffer. However, there's an obscure problem. The following figure demonstrates a full overwritable ring buffer. In this figure, the 'head' pointer points to the end of last record, and a long record 'E' is pending. For a normal ring buffer, a 'tail' pointer would have pointed to position (X), so kernel knows there's no more space in the ring buffer. However, for an overwritable ring buffer, kernel ignore the 'tail' pointer. (X) head . | . V +------+-------+----------+------+---+ |A....A|B.....B|C........C|D....D| | +------+-------+----------+------+---+ Record 'A' is overwritten by event 'E': head | V +--+---+-------+----------+------+---+ |.E|..A|B.....B|C........C|D....D|E..| +--+---+-------+----------+------+---+ Now tooling decides to read from this ring buffer. However, none of these two natural positions, 'head' and the start of this ring buffer, are pointing to the head of a record. Even the full ring buffer can be accessed by tooling, it is unable to find a position to start decoding. The first attempt tries to solve this problem AFAIK can be found from [1]. It makes kernel to maintain 'tail' pointer: updates it when ring buffer is half full. However, this approach introduces overhead to fast path. Test result shows a 1% overhead [2]. In addition, this method utilizes no more tham 50% records. Another attempt can be found from [3], which allows putting the size of an event at the end of each record. This approach allows tooling to find records in a backward manner from 'head' pointer by reading size of a record from its tail. However, because of alignment requirement, it needs 8 bytes to record the size of a record, which is a huge waste. Its performance is also not good, because more data need to be written. This approach also introduces some extra branch instructions to fast path. 'write_backward' is a better solution to this problem. Following figure demonstrates the state of the overwritable ring buffer when 'write_backward' is set before overwriting: head | V +---+------+----------+-------+------+ | |D....D|C........C|B.....B|A....A| +---+------+----------+-------+------+ and after overwriting: head | V +---+------+----------+-------+---+--+ |..E|D....D|C........C|B.....B|A..|E.| +---+------+----------+-------+---+--+ In each situation, 'head' points to the beginning of the newest record. From this record, tooling can iterate over the full ring buffer and fetch records one by one. The only limitation that needs to be considered is back-to-back reading. Due to the non-deterministic of user programs, it is impossible to ensure the ring buffer keeps stable during reading. Consider an extreme situation: tooling is scheduled out after reading record 'D', then a burst of events come, eat up the whole ring buffer (one or multiple rounds). When the tooling process comes back, reading after 'D' is incorrect now. To prevent this problem, we need to find a way to ensure the ring buffer is stable during reading. ioctl(PERF_EVENT_IOC_PAUSE_OUTPUT) is suggested because its overhead is lower than ioctl(PERF_EVENT_IOC_ENABLE). By carefully verifying 'header' pointer, reader can avoid pausing the ring-buffer. For example: /* A union of all possible events */ union perf_event event; p = head = perf_mmap__read_head(); while (true) { /* copy header of next event */ fetch(&event.header, p, sizeof(event.header)); /* read 'head' pointer */ head = perf_mmap__read_head(); /* check overwritten: is the header good? */ if (!verify(sizeof(event.header), p, head)) break; /* copy the whole event */ fetch(&event, p, event.header.size); /* read 'head' pointer again */ head = perf_mmap__read_head(); /* is the whole event good? */ if (!verify(event.header.size, p, head)) break; p += event.header.size; } However, the overhead is high because: a) In-place decoding is not safe. Copying-verifying-decoding is required. b) Fetching 'head' pointer requires additional synchronization. (From Alexei Starovoitov: Even when this trick works, pause is needed for more than stability of reading. When we collect the events into overwrite buffer we're waiting for some other trigger (like all cpu utilization spike or just one cpu running and all others are idle) and when it happens the buffer has valuable info from the past. At this point new events are no longer interesting and buffer should be paused, events read and unpaused until next trigger comes.) This patch utilizes event's default overflow_handler introduced previously. perf_event_output_backward() is created as the default overflow handler for backward ring buffers. To avoid extra overhead to fast path, original perf_event_output() becomes __perf_event_output() and marked '__always_inline'. In theory, there's no extra overhead introduced to fast path. Performance testing: Calling 3000000 times of 'close(-1)', use gettimeofday() to check duration. Use 'perf record -o /dev/null -e raw_syscalls:*' to capture system calls. In ns. Testing environment: CPU : Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz Kernel : v4.5.0 MEAN STDVAR BASE 800214.950 2853.083 PRE1 2253846.700 9997.014 PRE2 2257495.540 8516.293 POST 2250896.100 8933.921 Where 'BASE' is pure performance without capturing. 'PRE1' is test result of pure 'v4.5.0' kernel. 'PRE2' is test result before this patch. 'POST' is test result after this patch. See [4] for the detailed experimental setup. Considering the stdvar, this patch doesn't introduce performance overhead to the fast path. [1] http://lkml.iu.edu/hypermail/linux/kernel/1304.1/04584.html [2] http://lkml.iu.edu/hypermail/linux/kernel/1307.1/00535.html [3] http://lkml.iu.edu/hypermail/linux/kernel/1512.0/01265.html [4] http://lkml.kernel.org/g/56F89DCD.1040202@huawei.com Signed-off-by: Wang Nan Signed-off-by: Peter Zijlstra (Intel) Acked-by: Alexei Starovoitov Cc: Cc: Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Brendan Gregg Cc: He Kuang Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: Zefan Li Link: http://lkml.kernel.org/r/1459865478-53413-1-git-send-email-wangnan0@huawei.com [ Fixed the changelog some more. ] Signed-off-by: Ingo Molnar Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 28 ++++++++++++++++--- include/uapi/linux/perf_event.h | 3 ++- kernel/events/core.c | 48 +++++++++++++++++++++++++++++---- kernel/events/ring_buffer.c | 16 ++++++++++- 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index b8b195fbe787..85749ae8cb5f 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -834,14 +834,24 @@ extern int perf_event_overflow(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs); +extern void perf_event_output_forward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs); +extern void perf_event_output_backward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs); extern void perf_event_output(struct perf_event *event, - struct perf_sample_data *data, - struct pt_regs *regs); + struct perf_sample_data *data, + struct pt_regs *regs); static inline bool is_default_overflow_handler(struct perf_event *event) { - return (event->overflow_handler == perf_event_output); + if (likely(event->overflow_handler == perf_event_output_forward)) + return true; + if (unlikely(event->overflow_handler == perf_event_output_backward)) + return true; + return false; } extern void @@ -1051,8 +1061,20 @@ static inline bool has_aux(struct perf_event *event) return event->pmu->setup_aux; } +static inline bool is_write_backward(struct perf_event *event) +{ + return !!event->attr.write_backward; +} + extern int perf_output_begin(struct perf_output_handle *handle, struct perf_event *event, unsigned int size); +extern int perf_output_begin_forward(struct perf_output_handle *handle, + struct perf_event *event, + unsigned int size); +extern int perf_output_begin_backward(struct perf_output_handle *handle, + struct perf_event *event, + unsigned int size); + extern void perf_output_end(struct perf_output_handle *handle); extern unsigned int perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index a3c19034d5f8..43fc8d213472 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -340,7 +340,8 @@ struct perf_event_attr { comm_exec : 1, /* flag comm events that are due to an exec */ use_clockid : 1, /* use @clockid for time fields */ context_switch : 1, /* context switch data */ - __reserved_1 : 37; + write_backward : 1, /* Write ring buffer from end to beginning */ + __reserved_1 : 36; union { __u32 wakeup_events; /* wakeup every n events */ diff --git a/kernel/events/core.c b/kernel/events/core.c index 21ba024c9ed1..eabeb2aec00f 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5694,9 +5694,13 @@ void perf_prepare_sample(struct perf_event_header *header, } } -void perf_event_output(struct perf_event *event, - struct perf_sample_data *data, - struct pt_regs *regs) +static void __always_inline +__perf_event_output(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs, + int (*output_begin)(struct perf_output_handle *, + struct perf_event *, + unsigned int)) { struct perf_output_handle handle; struct perf_event_header header; @@ -5706,7 +5710,7 @@ void perf_event_output(struct perf_event *event, perf_prepare_sample(&header, data, event, regs); - if (perf_output_begin(&handle, event, header.size)) + if (output_begin(&handle, event, header.size)) goto exit; perf_output_sample(&handle, &header, data, event); @@ -5717,6 +5721,30 @@ void perf_event_output(struct perf_event *event, rcu_read_unlock(); } +void +perf_event_output_forward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + __perf_event_output(event, data, regs, perf_output_begin_forward); +} + +void +perf_event_output_backward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + __perf_event_output(event, data, regs, perf_output_begin_backward); +} + +void +perf_event_output(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + __perf_event_output(event, data, regs, perf_output_begin); +} + /* * read event_id */ @@ -8153,8 +8181,11 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, if (overflow_handler) { event->overflow_handler = overflow_handler; event->overflow_handler_context = context; + } else if (is_write_backward(event)){ + event->overflow_handler = perf_event_output_backward; + event->overflow_handler_context = NULL; } else { - event->overflow_handler = perf_event_output; + event->overflow_handler = perf_event_output_forward; event->overflow_handler_context = NULL; } @@ -8388,6 +8419,13 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event) if (output_event->clock != event->clock) goto out; + /* + * Either writing ring buffer from beginning or from end. + * Mixing is not allowed. + */ + if (is_write_backward(output_event) != is_write_backward(event)) + goto out; + /* * If both events generate aux data, they must be on the same PMU */ diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 60be55a64040..c49bab42dc57 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -230,10 +230,24 @@ __perf_output_begin(struct perf_output_handle *handle, return -ENOSPC; } +int perf_output_begin_forward(struct perf_output_handle *handle, + struct perf_event *event, unsigned int size) +{ + return __perf_output_begin(handle, event, size, false); +} + +int perf_output_begin_backward(struct perf_output_handle *handle, + struct perf_event *event, unsigned int size) +{ + return __perf_output_begin(handle, event, size, true); +} + int perf_output_begin(struct perf_output_handle *handle, struct perf_event *event, unsigned int size) { - return __perf_output_begin(handle, event, size, false); + + return __perf_output_begin(handle, event, size, + unlikely(is_write_backward(event))); } unsigned int perf_output_copy(struct perf_output_handle *handle, -- GitLab From dcee75b3b7f025cc6765e6c92ba0a4e59a4d25f4 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Sun, 17 Apr 2016 15:03:00 -0700 Subject: [PATCH 4028/9938] perf/x86/intel/rapl: Support Skylake RAPL domains Add Skylake client support for RAPL domains. In addition to RAPL domains in Broadwell clients, it has support for platform domain (aka PSys). The PSys domain controls the entire SoC instead of just a CPU package. Unlike package domain, PSys support requires more than just processor level implementation. The other parts in the system need additional HW level signaling, which OEMs need to support. When not supported, the energy counter register in PSys domain returns 0. Also corrected error in comment for GPU counter, which previously was DRAM counter. Signed-off-by: Srinivas Pandruvada Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: bp@alien8.de Cc: hpa@zytor.com Cc: jacob.jun.pan@linux.intel.com Cc: rjw@rjwysocki.net Link: http://lkml.kernel.org/r/1460930581-29748-2-git-send-email-srinivas.pandruvada@linux.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Ingo Molnar --- arch/x86/events/intel/rapl.c | 54 ++++++++++++++++++++++++++++++-- arch/x86/include/asm/msr-index.h | 2 ++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index c9b7489ae8ee..26c7d7d8a657 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -27,10 +27,14 @@ * event: rapl_energy_dram * perf code: 0x3 * - * dram counter: consumption of the builtin-gpu domain (client only) + * gpu counter: consumption of the builtin-gpu domain (client only) * event: rapl_energy_gpu * perf code: 0x4 * + * psys counter: consumption of the builtin-psys domain (client only) + * event: rapl_energy_psys + * perf code: 0x5 + * * We manage those counters as free running (read-only). They may be * use simultaneously by other tools, such as turbostat. * @@ -66,13 +70,16 @@ MODULE_LICENSE("GPL"); #define INTEL_RAPL_RAM 0x3 /* pseudo-encoding */ #define RAPL_IDX_PP1_NRG_STAT 3 /* gpu */ #define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */ +#define RAPL_IDX_PSYS_NRG_STAT 4 /* psys */ +#define INTEL_RAPL_PSYS 0x5 /* pseudo-encoding */ -#define NR_RAPL_DOMAINS 0x4 +#define NR_RAPL_DOMAINS 0x5 static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = { "pp0-core", "package", "dram", "pp1-gpu", + "psys", }; /* Clients have PP0, PKG */ @@ -91,6 +98,13 @@ static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = { 1< Date: Thu, 21 Apr 2016 15:14:17 +0200 Subject: [PATCH 4029/9938] x86/perf/rapl: Reorder model numbers Re-order the model array to match the order in events/intel/core.c, to easier spot gaps and such. Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Srinivas Pandruvada Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Signed-off-by: Ingo Molnar --- arch/x86/events/intel/rapl.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 26c7d7d8a657..1e7b1dfff1c7 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -787,17 +787,22 @@ static const struct intel_rapl_init_fun skl_rapl_init __initconst = { static const struct x86_cpu_id rapl_cpu_match[] __initconst = { X86_RAPL_MODEL_MATCH(42, snb_rapl_init), /* Sandy Bridge */ + X86_RAPL_MODEL_MATCH(45, snbep_rapl_init), /* Sandy Bridge-EP */ + X86_RAPL_MODEL_MATCH(58, snb_rapl_init), /* Ivy Bridge */ - X86_RAPL_MODEL_MATCH(63, hsx_rapl_init), /* Haswell-Server */ - X86_RAPL_MODEL_MATCH(79, hsx_rapl_init), /* Broadwell-Server */ + X86_RAPL_MODEL_MATCH(62, snbep_rapl_init), /* IvyTown */ + X86_RAPL_MODEL_MATCH(60, hsw_rapl_init), /* Haswell */ + X86_RAPL_MODEL_MATCH(63, hsx_rapl_init), /* Haswell-Server */ X86_RAPL_MODEL_MATCH(69, hsw_rapl_init), /* Haswell-Celeron */ X86_RAPL_MODEL_MATCH(70, hsw_rapl_init), /* Haswell GT3e */ + X86_RAPL_MODEL_MATCH(61, hsw_rapl_init), /* Broadwell */ X86_RAPL_MODEL_MATCH(71, hsw_rapl_init), /* Broadwell-H */ - X86_RAPL_MODEL_MATCH(45, snbep_rapl_init), /* Sandy Bridge-EP */ - X86_RAPL_MODEL_MATCH(62, snbep_rapl_init), /* IvyTown */ + X86_RAPL_MODEL_MATCH(79, hsx_rapl_init), /* Broadwell-Server */ + X86_RAPL_MODEL_MATCH(87, knl_rapl_init), /* Knights Landing */ + X86_RAPL_MODEL_MATCH(78, skl_rapl_init), /* Skylake */ X86_RAPL_MODEL_MATCH(94, skl_rapl_init), /* Skylake H/S */ {}, -- GitLab From 31b84310c79421d726621e800434c66a48a6c959 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 21 Apr 2016 15:15:47 +0200 Subject: [PATCH 4030/9938] x86/perf/rapl: Add missing Broadwell model With the array aligned as per events/intel/core.c it was fairly obvious we missed one, add it in. Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Srinivas Pandruvada Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Signed-off-by: Ingo Molnar --- arch/x86/events/intel/rapl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 1e7b1dfff1c7..99c4bab123cd 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -800,6 +800,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = { X86_RAPL_MODEL_MATCH(61, hsw_rapl_init), /* Broadwell */ X86_RAPL_MODEL_MATCH(71, hsw_rapl_init), /* Broadwell-H */ X86_RAPL_MODEL_MATCH(79, hsx_rapl_init), /* Broadwell-Server */ + X86_RAPL_MODEL_MATCH(86, hsx_rapl_init), /* Broadwell Xeon D */ X86_RAPL_MODEL_MATCH(87, knl_rapl_init), /* Knights Landing */ -- GitLab From 1f621e028baf391f6684003e32e009bc934b750f Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 6 Apr 2016 18:47:40 +0530 Subject: [PATCH 4031/9938] sched/fair: Fix asym packing to select correct CPU When asymmetric packing is set in the sched_domain and target CPU is busy, update_sd_pick_busiest() may not select the busiest runqueue. When target CPU is busy, find_busiest_group() will ignore checks for asym packing and may continue to load balance using the currently selected not-the-busiest runqueue as source runqueue. Selecting the busiest runqueue as source when the target CPU is busy, should result in achieving much better load balance. Also when target CPU is not busy and asymmetric packing is set in sd, select higher CPU as source CPU for load balancing. While doing this change, move the check to see if target CPU is busy into check_asym_packing(). The extent of performance benefit from this change decreases with the increasing load. However there is benefit in undercommit as well as overcommit conditions. 1. Record per second ebizzy (32 threads) on a 64 CPU power 7 box. (5 iterations) 4.6.0-rc2 Testcase: Min Max Avg StdDev ebizzy: 5223767.00 10368236.00 7946971.00 1753094.76 4.6.0-rc2+asym-changes Testcase: Min Max Avg StdDev %Change ebizzy: 8617191.00 13872356.00 11383980.00 1783400.89 +24.78% 2. Record per second ebizzy (64 threads) on a 64 CPU power 7 box. (5 iterations) 4.6.0-rc2 Testcase: Min Max Avg StdDev ebizzy: 6497666.00 18399783.00 10818093.20 4051452.08 4.6.0-rc2+asym-changes Testcase: Min Max Avg StdDev %Change ebizzy: 7567365.00 19456937.00 11674063.60 4295407.48 +4.40% 3. Record per second ebizzy (128 threads) on a 64 CPU power 7 box. (5 iterations) 4.6.0-rc2 Testcase: Min Max Avg StdDev ebizzy: 37073983.00 40341911.00 38776241.80 1259766.82 4.6.0-rc2+asym-changes Testcase: Min Max Avg StdDev %Change ebizzy: 38030399.00 41333378.00 39827404.40 1255001.86 +2.54% Signed-off-by: Srikar Dronamraju Signed-off-by: Peter Zijlstra (Intel) Cc: Gautham R Shenoy Cc: Michael Neuling Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Vaidyanathan Srinivasan Link: http://lkml.kernel.org/r/1459948660-16073-1-git-send-email-srikar@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index b8cc1c35cd7c..6e371f43fc80 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6679,6 +6679,9 @@ static bool update_sd_pick_busiest(struct lb_env *env, if (!(env->sd->flags & SD_ASYM_PACKING)) return true; + /* No ASYM_PACKING if target cpu is already busy */ + if (env->idle == CPU_NOT_IDLE) + return true; /* * ASYM_PACKING needs to move all the work to the lowest * numbered CPUs in the group, therefore mark all groups @@ -6688,7 +6691,8 @@ static bool update_sd_pick_busiest(struct lb_env *env, if (!sds->busiest) return true; - if (group_first_cpu(sds->busiest) > group_first_cpu(sg)) + /* Prefer to move from highest possible cpu's work */ + if (group_first_cpu(sds->busiest) < group_first_cpu(sg)) return true; } @@ -6834,6 +6838,9 @@ static int check_asym_packing(struct lb_env *env, struct sd_lb_stats *sds) if (!(env->sd->flags & SD_ASYM_PACKING)) return 0; + if (env->idle == CPU_NOT_IDLE) + return 0; + if (!sds->busiest) return 0; @@ -7026,8 +7033,7 @@ static struct sched_group *find_busiest_group(struct lb_env *env) busiest = &sds.busiest_stat; /* ASYM feature bypasses nice load balance check */ - if ((env->idle == CPU_IDLE || env->idle == CPU_NEWLY_IDLE) && - check_asym_packing(env, &sds)) + if (check_asym_packing(env, &sds)) return sds.busiest; /* There is no busy sibling group to pull tasks from */ -- GitLab From 21e96f88776deead303ecd30a17d1d7c2a1776e3 Mon Sep 17 00:00:00 2001 From: Steve Muckle Date: Mon, 21 Mar 2016 17:21:07 -0700 Subject: [PATCH 4032/9938] sched/fair: Move cpufreq hook to update_cfs_rq_load_avg() The cpufreq hook should be called whenever the root cfs_rq utilization changes so update_cfs_rq_load_avg() is a better place for it. The current location is not invoked in the enqueue_entity() or update_blocked_averages() paths. Suggested-by: Vincent Guittot Signed-off-by: Steve Muckle Signed-off-by: Peter Zijlstra (Intel) Cc: Dietmar Eggemann Cc: Juri Lelli Cc: Michael Turquette Cc: Mike Galbraith Cc: Morten Rasmussen Cc: Patrick Bellasi Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1458606068-7476-1-git-send-email-smuckle@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 50 +++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6e371f43fc80..6df80d47a525 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2878,7 +2878,9 @@ static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq); static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) { struct sched_avg *sa = &cfs_rq->avg; + struct rq *rq = rq_of(cfs_rq); int decayed, removed = 0; + int cpu = cpu_of(rq); if (atomic_long_read(&cfs_rq->removed_load_avg)) { s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0); @@ -2893,7 +2895,7 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) sa->util_sum = max_t(s32, sa->util_sum - r * LOAD_AVG_MAX, 0); } - decayed = __update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa, + decayed = __update_load_avg(now, cpu, sa, scale_load_down(cfs_rq->load.weight), cfs_rq->curr != NULL, cfs_rq); #ifndef CONFIG_64BIT @@ -2901,28 +2903,6 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) cfs_rq->load_last_update_time_copy = sa->last_update_time; #endif - return decayed || removed; -} - -/* Update task and its cfs_rq load average */ -static inline void update_load_avg(struct sched_entity *se, int update_tg) -{ - struct cfs_rq *cfs_rq = cfs_rq_of(se); - u64 now = cfs_rq_clock_task(cfs_rq); - struct rq *rq = rq_of(cfs_rq); - int cpu = cpu_of(rq); - - /* - * Track task load average for carrying it to new CPU after migrated, and - * track group sched_entity load average for task_h_load calc in migration - */ - __update_load_avg(now, cpu, &se->avg, - se->on_rq * scale_load_down(se->load.weight), - cfs_rq->curr == se, NULL); - - if (update_cfs_rq_load_avg(now, cfs_rq) && update_tg) - update_tg_load_avg(cfs_rq, 0); - if (cpu == smp_processor_id() && &rq->cfs == cfs_rq) { unsigned long max = rq->cpu_capacity_orig; @@ -2943,8 +2923,30 @@ static inline void update_load_avg(struct sched_entity *se, int update_tg) * See cpu_util(). */ cpufreq_update_util(rq_clock(rq), - min(cfs_rq->avg.util_avg, max), max); + min(sa->util_avg, max), max); } + + return decayed || removed; +} + +/* Update task and its cfs_rq load average */ +static inline void update_load_avg(struct sched_entity *se, int update_tg) +{ + struct cfs_rq *cfs_rq = cfs_rq_of(se); + u64 now = cfs_rq_clock_task(cfs_rq); + struct rq *rq = rq_of(cfs_rq); + int cpu = cpu_of(rq); + + /* + * Track task load average for carrying it to new CPU after migrated, and + * track group sched_entity load average for task_h_load calc in migration + */ + __update_load_avg(now, cpu, &se->avg, + se->on_rq * scale_load_down(se->load.weight), + cfs_rq->curr == se, NULL); + + if (update_cfs_rq_load_avg(now, cfs_rq) && update_tg) + update_tg_load_avg(cfs_rq, 0); } static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) -- GitLab From 41e0d37f7ac81297c07ba311e4ad39465b8c8295 Mon Sep 17 00:00:00 2001 From: Steve Muckle Date: Mon, 21 Mar 2016 17:21:08 -0700 Subject: [PATCH 4033/9938] sched/fair: Do not call cpufreq hook unless util changed There's no reason to call the cpufreq hook if the root cfs_rq utilization has not been modified. Signed-off-by: Steve Muckle Signed-off-by: Peter Zijlstra (Intel) Cc: Dietmar Eggemann Cc: Juri Lelli Cc: Michael Turquette Cc: Mike Galbraith Cc: Morten Rasmussen Cc: Patrick Bellasi Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Cc: Vincent Guittot Link: http://lkml.kernel.org/r/1458606068-7476-2-git-send-email-smuckle@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6df80d47a525..81552819444c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2879,20 +2879,21 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) { struct sched_avg *sa = &cfs_rq->avg; struct rq *rq = rq_of(cfs_rq); - int decayed, removed = 0; + int decayed, removed_load = 0, removed_util = 0; int cpu = cpu_of(rq); if (atomic_long_read(&cfs_rq->removed_load_avg)) { s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0); sa->load_avg = max_t(long, sa->load_avg - r, 0); sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0); - removed = 1; + removed_load = 1; } if (atomic_long_read(&cfs_rq->removed_util_avg)) { long r = atomic_long_xchg(&cfs_rq->removed_util_avg, 0); sa->util_avg = max_t(long, sa->util_avg - r, 0); sa->util_sum = max_t(s32, sa->util_sum - r * LOAD_AVG_MAX, 0); + removed_util = 1; } decayed = __update_load_avg(now, cpu, sa, @@ -2903,7 +2904,8 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) cfs_rq->load_last_update_time_copy = sa->last_update_time; #endif - if (cpu == smp_processor_id() && &rq->cfs == cfs_rq) { + if (cpu == smp_processor_id() && &rq->cfs == cfs_rq && + (decayed || removed_util)) { unsigned long max = rq->cpu_capacity_orig; /* @@ -2926,7 +2928,7 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) min(sa->util_avg, max), max); } - return decayed || removed; + return decayed || removed_load; } /* Update task and its cfs_rq load average */ -- GitLab From a2c6c91f98247fef0fe75216d607812485aeb0df Mon Sep 17 00:00:00 2001 From: Steve Muckle Date: Thu, 24 Mar 2016 15:26:07 -0700 Subject: [PATCH 4034/9938] sched/fair: Call cpufreq hook in additional paths The cpufreq hook should be called any time the root CFS rq utilization changes. This can occur when a task is switched to or from the fair class, or a task moves between groups or CPUs, but these paths currently do not call the cpufreq hook. Fix this by adding the hook to attach_entity_load_avg() and detach_entity_load_avg(). Suggested-by: Vincent Guittot Signed-off-by: Steve Muckle [ Added the .update_freq argument to update_cfs_rq_load_avg() to avoid a double cpufreq call. ] Signed-off-by: Peter Zijlstra (Intel) Cc: Byungchul Park Cc: Dietmar Eggemann Cc: Juri Lelli Cc: Michael Turquette Cc: Mike Galbraith Cc: Morten Rasmussen Cc: Patrick Bellasi Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1458858367-2831-1-git-send-email-smuckle@linaro.org Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 73 ++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 81552819444c..c328bd77fe35 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2874,13 +2874,41 @@ static inline void update_tg_load_avg(struct cfs_rq *cfs_rq, int force) {} static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq); +static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq) +{ + struct rq *rq = rq_of(cfs_rq); + int cpu = cpu_of(rq); + + if (cpu == smp_processor_id() && &rq->cfs == cfs_rq) { + unsigned long max = rq->cpu_capacity_orig; + + /* + * There are a few boundary cases this might miss but it should + * get called often enough that that should (hopefully) not be + * a real problem -- added to that it only calls on the local + * CPU, so if we enqueue remotely we'll miss an update, but + * the next tick/schedule should update. + * + * It will not get called when we go idle, because the idle + * thread is a different class (!fair), nor will the utilization + * number include things like RT tasks. + * + * As is, the util number is not freq-invariant (we'd have to + * implement arch_scale_freq_capacity() for that). + * + * See cpu_util(). + */ + cpufreq_update_util(rq_clock(rq), + min(cfs_rq->avg.util_avg, max), max); + } +} + /* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */ -static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) +static inline int +update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq) { struct sched_avg *sa = &cfs_rq->avg; - struct rq *rq = rq_of(cfs_rq); int decayed, removed_load = 0, removed_util = 0; - int cpu = cpu_of(rq); if (atomic_long_read(&cfs_rq->removed_load_avg)) { s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0); @@ -2896,7 +2924,7 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) removed_util = 1; } - decayed = __update_load_avg(now, cpu, sa, + decayed = __update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa, scale_load_down(cfs_rq->load.weight), cfs_rq->curr != NULL, cfs_rq); #ifndef CONFIG_64BIT @@ -2904,29 +2932,8 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) cfs_rq->load_last_update_time_copy = sa->last_update_time; #endif - if (cpu == smp_processor_id() && &rq->cfs == cfs_rq && - (decayed || removed_util)) { - unsigned long max = rq->cpu_capacity_orig; - - /* - * There are a few boundary cases this might miss but it should - * get called often enough that that should (hopefully) not be - * a real problem -- added to that it only calls on the local - * CPU, so if we enqueue remotely we'll miss an update, but - * the next tick/schedule should update. - * - * It will not get called when we go idle, because the idle - * thread is a different class (!fair), nor will the utilization - * number include things like RT tasks. - * - * As is, the util number is not freq-invariant (we'd have to - * implement arch_scale_freq_capacity() for that). - * - * See cpu_util(). - */ - cpufreq_update_util(rq_clock(rq), - min(sa->util_avg, max), max); - } + if (update_freq && (decayed || removed_util)) + cfs_rq_util_change(cfs_rq); return decayed || removed_load; } @@ -2947,7 +2954,7 @@ static inline void update_load_avg(struct sched_entity *se, int update_tg) se->on_rq * scale_load_down(se->load.weight), cfs_rq->curr == se, NULL); - if (update_cfs_rq_load_avg(now, cfs_rq) && update_tg) + if (update_cfs_rq_load_avg(now, cfs_rq, true) && update_tg) update_tg_load_avg(cfs_rq, 0); } @@ -2976,6 +2983,8 @@ static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s cfs_rq->avg.load_sum += se->avg.load_sum; cfs_rq->avg.util_avg += se->avg.util_avg; cfs_rq->avg.util_sum += se->avg.util_sum; + + cfs_rq_util_change(cfs_rq); } static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) @@ -2988,6 +2997,8 @@ static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s cfs_rq->avg.load_sum = max_t(s64, cfs_rq->avg.load_sum - se->avg.load_sum, 0); cfs_rq->avg.util_avg = max_t(long, cfs_rq->avg.util_avg - se->avg.util_avg, 0); cfs_rq->avg.util_sum = max_t(s32, cfs_rq->avg.util_sum - se->avg.util_sum, 0); + + cfs_rq_util_change(cfs_rq); } /* Add the load generated by se into cfs_rq's load average */ @@ -3005,7 +3016,7 @@ enqueue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) cfs_rq->curr == se, NULL); } - decayed = update_cfs_rq_load_avg(now, cfs_rq); + decayed = update_cfs_rq_load_avg(now, cfs_rq, !migrated); cfs_rq->runnable_load_avg += sa->load_avg; cfs_rq->runnable_load_sum += sa->load_sum; @@ -6213,7 +6224,7 @@ static void update_blocked_averages(int cpu) if (throttled_hierarchy(cfs_rq)) continue; - if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq)) + if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq, true)) update_tg_load_avg(cfs_rq, 0); } raw_spin_unlock_irqrestore(&rq->lock, flags); @@ -6274,7 +6285,7 @@ static inline void update_blocked_averages(int cpu) raw_spin_lock_irqsave(&rq->lock, flags); update_rq_clock(rq); - update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq); + update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq, true); raw_spin_unlock_irqrestore(&rq->lock, flags); } -- GitLab From cee1afce3053e7aa0793fbd5f2e845fa2cef9e33 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 13 Apr 2016 15:56:50 +0200 Subject: [PATCH 4035/9938] sched/fair: Gather CPU load functions under a more conventional namespace The CPU load update related functions have a weak naming convention currently, starting with update_cpu_load_*() which isn't ideal as "update" is a very generic concept. Since two of these functions are public already (and a third is to come) that's enough to introduce a more conventional naming scheme. So let's do the following rename instead: update_cpu_load_*() -> cpu_load_update_*() Signed-off-by: Frederic Weisbecker Signed-off-by: Peter Zijlstra (Intel) Cc: Byungchul Park Cc: Chris Metcalf Cc: Christoph Lameter Cc: Luiz Capitulino Cc: Mike Galbraith Cc: Paul E . McKenney Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1460555812-25375-2-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- Documentation/trace/ftrace.txt | 10 +++++----- include/linux/sched.h | 4 ++-- kernel/sched/core.c | 2 +- kernel/sched/fair.c | 24 ++++++++++++------------ kernel/sched/sched.h | 4 ++-- kernel/time/tick-sched.c | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt index f52f297cb406..9857606dd7b7 100644 --- a/Documentation/trace/ftrace.txt +++ b/Documentation/trace/ftrace.txt @@ -1562,12 +1562,12 @@ Doing the same with chrt -r 5 and function-trace set. -0 3dN.1 12us : menu_hrtimer_cancel <-tick_nohz_idle_exit -0 3dN.1 12us : ktime_get <-tick_nohz_idle_exit -0 3dN.1 12us : tick_do_update_jiffies64 <-tick_nohz_idle_exit - -0 3dN.1 13us : update_cpu_load_nohz <-tick_nohz_idle_exit - -0 3dN.1 13us : _raw_spin_lock <-update_cpu_load_nohz + -0 3dN.1 13us : cpu_load_update_nohz <-tick_nohz_idle_exit + -0 3dN.1 13us : _raw_spin_lock <-cpu_load_update_nohz -0 3dN.1 13us : add_preempt_count <-_raw_spin_lock - -0 3dN.2 13us : __update_cpu_load <-update_cpu_load_nohz - -0 3dN.2 14us : sched_avg_update <-__update_cpu_load - -0 3dN.2 14us : _raw_spin_unlock <-update_cpu_load_nohz + -0 3dN.2 13us : __cpu_load_update <-cpu_load_update_nohz + -0 3dN.2 14us : sched_avg_update <-__cpu_load_update + -0 3dN.2 14us : _raw_spin_unlock <-cpu_load_update_nohz -0 3dN.2 14us : sub_preempt_count <-_raw_spin_unlock -0 3dN.1 15us : calc_load_exit_idle <-tick_nohz_idle_exit -0 3dN.1 15us : touch_softlockup_watchdog <-tick_nohz_idle_exit diff --git a/include/linux/sched.h b/include/linux/sched.h index 13c1c1d07270..0b7f6028a50b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -178,9 +178,9 @@ extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load); extern void calc_global_load(unsigned long ticks); #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON) -extern void update_cpu_load_nohz(int active); +extern void cpu_load_update_nohz(int active); #else -static inline void update_cpu_load_nohz(int active) { } +static inline void cpu_load_update_nohz(int active) { } #endif extern void dump_cpu_task(int cpu); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 06efbb9c9544..c98a2688f390 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2917,7 +2917,7 @@ void scheduler_tick(void) raw_spin_lock(&rq->lock); update_rq_clock(rq); curr->sched_class->task_tick(rq, curr, 0); - update_cpu_load_active(rq); + cpu_load_update_active(rq); calc_global_load_tick(rq); raw_spin_unlock(&rq->lock); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index c328bd77fe35..ecd81c4ebb56 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4559,7 +4559,7 @@ decay_load_missed(unsigned long load, unsigned long missed_updates, int idx) } /** - * __update_cpu_load - update the rq->cpu_load[] statistics + * __cpu_load_update - update the rq->cpu_load[] statistics * @this_rq: The rq to update statistics for * @this_load: The current load * @pending_updates: The number of missed updates @@ -4594,7 +4594,7 @@ decay_load_missed(unsigned long load, unsigned long missed_updates, int idx) * see decay_load_misses(). For NOHZ_FULL we get to subtract and add the extra * term. See the @active paramter. */ -static void __update_cpu_load(struct rq *this_rq, unsigned long this_load, +static void __cpu_load_update(struct rq *this_rq, unsigned long this_load, unsigned long pending_updates, int active) { unsigned long tickless_load = active ? this_rq->cpu_load[0] : 0; @@ -4642,7 +4642,7 @@ static unsigned long weighted_cpuload(const int cpu) } #ifdef CONFIG_NO_HZ_COMMON -static void __update_cpu_load_nohz(struct rq *this_rq, +static void __cpu_load_update_nohz(struct rq *this_rq, unsigned long curr_jiffies, unsigned long load, int active) @@ -4657,7 +4657,7 @@ static void __update_cpu_load_nohz(struct rq *this_rq, * In the NOHZ_FULL case, we were non-idle, we should consider * its weighted load. */ - __update_cpu_load(this_rq, load, pending_updates, active); + __cpu_load_update(this_rq, load, pending_updates, active); } } @@ -4678,7 +4678,7 @@ static void __update_cpu_load_nohz(struct rq *this_rq, * Called from nohz_idle_balance() to update the load ratings before doing the * idle balance. */ -static void update_cpu_load_idle(struct rq *this_rq) +static void cpu_load_update_idle(struct rq *this_rq) { /* * bail if there's load or we're actually up-to-date. @@ -4686,13 +4686,13 @@ static void update_cpu_load_idle(struct rq *this_rq) if (weighted_cpuload(cpu_of(this_rq))) return; - __update_cpu_load_nohz(this_rq, READ_ONCE(jiffies), 0, 0); + __cpu_load_update_nohz(this_rq, READ_ONCE(jiffies), 0, 0); } /* * Called from tick_nohz_idle_exit() -- try and fix up the ticks we missed. */ -void update_cpu_load_nohz(int active) +void cpu_load_update_nohz(int active) { struct rq *this_rq = this_rq(); unsigned long curr_jiffies = READ_ONCE(jiffies); @@ -4702,7 +4702,7 @@ void update_cpu_load_nohz(int active) return; raw_spin_lock(&this_rq->lock); - __update_cpu_load_nohz(this_rq, curr_jiffies, load, active); + __cpu_load_update_nohz(this_rq, curr_jiffies, load, active); raw_spin_unlock(&this_rq->lock); } #endif /* CONFIG_NO_HZ */ @@ -4710,14 +4710,14 @@ void update_cpu_load_nohz(int active) /* * Called from scheduler_tick() */ -void update_cpu_load_active(struct rq *this_rq) +void cpu_load_update_active(struct rq *this_rq) { unsigned long load = weighted_cpuload(cpu_of(this_rq)); /* - * See the mess around update_cpu_load_idle() / update_cpu_load_nohz(). + * See the mess around cpu_load_update_idle() / cpu_load_update_nohz(). */ this_rq->last_load_update_tick = jiffies; - __update_cpu_load(this_rq, load, 1, 1); + __cpu_load_update(this_rq, load, 1, 1); } /* @@ -8031,7 +8031,7 @@ static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) if (time_after_eq(jiffies, rq->next_balance)) { raw_spin_lock_irq(&rq->lock); update_rq_clock(rq); - update_cpu_load_idle(rq); + cpu_load_update_idle(rq); raw_spin_unlock_irq(&rq->lock); rebalance_domains(rq, CPU_IDLE); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index a7cbad7b3ad2..32d9e22cfacf 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -31,9 +31,9 @@ extern void calc_global_load_tick(struct rq *this_rq); extern long calc_load_fold_active(struct rq *this_rq); #ifdef CONFIG_SMP -extern void update_cpu_load_active(struct rq *this_rq); +extern void cpu_load_update_active(struct rq *this_rq); #else -static inline void update_cpu_load_active(struct rq *this_rq) { } +static inline void cpu_load_update_active(struct rq *this_rq) { } #endif /* diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 58e3310c9b21..66bdc9acc283 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -806,7 +806,7 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now, int { /* Update jiffies first */ tick_do_update_jiffies64(now); - update_cpu_load_nohz(active); + cpu_load_update_nohz(active); calc_load_exit_idle(); touch_softlockup_watchdog_sched(); -- GitLab From 1f41906a6fda1114debd3898668bd7ab6470ee41 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 13 Apr 2016 15:56:51 +0200 Subject: [PATCH 4036/9938] sched/fair: Correctly handle nohz ticks CPU load accounting Ticks can happen while the CPU is in dynticks-idle or dynticks-singletask mode. In fact "nohz" or "dynticks" only mean that we exit the periodic mode and we try to minimize the ticks as much as possible. The nohz subsystem uses a confusing terminology with the internal state "ts->tick_stopped" which is also available through its public interface with tick_nohz_tick_stopped(). This is a misnomer as the tick is instead reduced with the best effort rather than stopped. In the best case the tick can indeed be actually stopped but there is no guarantee about that. If a timer needs to fire one second later, a tick will fire while the CPU is in nohz mode and this is a very common scenario. Now this confusion happens to be a problem with CPU load updates: cpu_load_update_active() doesn't handle nohz ticks correctly because it assumes that ticks are completely stopped in nohz mode and that cpu_load_update_active() can't be called in dynticks mode. When that happens, the whole previous tickless load is ignored and the function just records the load for the current tick, ignoring potentially long idle periods behind. In order to solve this, we could account the current load for the previous nohz time but there is a risk that we account the load of a task that got freshly enqueued for the whole nohz period. So instead, lets record the dynticks load on nohz frame entry so we know what to record in case of nohz ticks, then use this record to account the tickless load on nohz ticks and nohz frame end. Signed-off-by: Frederic Weisbecker Signed-off-by: Peter Zijlstra (Intel) Cc: Byungchul Park Cc: Chris Metcalf Cc: Christoph Lameter Cc: Luiz Capitulino Cc: Mike Galbraith Cc: Paul E . McKenney Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1460555812-25375-3-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- include/linux/sched.h | 6 ++- kernel/sched/fair.c | 97 ++++++++++++++++++++++++++-------------- kernel/time/tick-sched.c | 9 ++-- 3 files changed, 72 insertions(+), 40 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 0b7f6028a50b..d894f2d61388 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -178,9 +178,11 @@ extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load); extern void calc_global_load(unsigned long ticks); #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON) -extern void cpu_load_update_nohz(int active); +extern void cpu_load_update_nohz_start(void); +extern void cpu_load_update_nohz_stop(void); #else -static inline void cpu_load_update_nohz(int active) { } +static inline void cpu_load_update_nohz_start(void) { } +static inline void cpu_load_update_nohz_stop(void) { } #endif extern void dump_cpu_task(int cpu); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ecd81c4ebb56..b70367a3e1ef 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4563,7 +4563,6 @@ decay_load_missed(unsigned long load, unsigned long missed_updates, int idx) * @this_rq: The rq to update statistics for * @this_load: The current load * @pending_updates: The number of missed updates - * @active: !0 for NOHZ_FULL * * Update rq->cpu_load[] statistics. This function is usually called every * scheduler tick (TICK_NSEC). @@ -4592,12 +4591,12 @@ decay_load_missed(unsigned long load, unsigned long missed_updates, int idx) * load[i]_n = (1 - 1/2^i)^n * load[i]_0 * * see decay_load_misses(). For NOHZ_FULL we get to subtract and add the extra - * term. See the @active paramter. + * term. */ -static void __cpu_load_update(struct rq *this_rq, unsigned long this_load, - unsigned long pending_updates, int active) +static void cpu_load_update(struct rq *this_rq, unsigned long this_load, + unsigned long pending_updates) { - unsigned long tickless_load = active ? this_rq->cpu_load[0] : 0; + unsigned long tickless_load = this_rq->cpu_load[0]; int i, scale; this_rq->nr_load_updates++; @@ -4642,10 +4641,23 @@ static unsigned long weighted_cpuload(const int cpu) } #ifdef CONFIG_NO_HZ_COMMON -static void __cpu_load_update_nohz(struct rq *this_rq, - unsigned long curr_jiffies, - unsigned long load, - int active) +/* + * There is no sane way to deal with nohz on smp when using jiffies because the + * cpu doing the jiffies update might drift wrt the cpu doing the jiffy reading + * causing off-by-one errors in observed deltas; {0,2} instead of {1,1}. + * + * Therefore we need to avoid the delta approach from the regular tick when + * possible since that would seriously skew the load calculation. This is why we + * use cpu_load_update_periodic() for CPUs out of nohz. However we'll rely on + * jiffies deltas for updates happening while in nohz mode (idle ticks, idle + * loop exit, nohz_idle_balance, nohz full exit...) + * + * This means we might still be one tick off for nohz periods. + */ + +static void cpu_load_update_nohz(struct rq *this_rq, + unsigned long curr_jiffies, + unsigned long load) { unsigned long pending_updates; @@ -4657,23 +4669,10 @@ static void __cpu_load_update_nohz(struct rq *this_rq, * In the NOHZ_FULL case, we were non-idle, we should consider * its weighted load. */ - __cpu_load_update(this_rq, load, pending_updates, active); + cpu_load_update(this_rq, load, pending_updates); } } -/* - * There is no sane way to deal with nohz on smp when using jiffies because the - * cpu doing the jiffies update might drift wrt the cpu doing the jiffy reading - * causing off-by-one errors in observed deltas; {0,2} instead of {1,1}. - * - * Therefore we cannot use the delta approach from the regular tick since that - * would seriously skew the load calculation. However we'll make do for those - * updates happening while idle (nohz_idle_balance) or coming out of idle - * (tick_nohz_idle_exit). - * - * This means we might still be one tick off for nohz periods. - */ - /* * Called from nohz_idle_balance() to update the load ratings before doing the * idle balance. @@ -4686,26 +4685,56 @@ static void cpu_load_update_idle(struct rq *this_rq) if (weighted_cpuload(cpu_of(this_rq))) return; - __cpu_load_update_nohz(this_rq, READ_ONCE(jiffies), 0, 0); + cpu_load_update_nohz(this_rq, READ_ONCE(jiffies), 0); } /* - * Called from tick_nohz_idle_exit() -- try and fix up the ticks we missed. + * Record CPU load on nohz entry so we know the tickless load to account + * on nohz exit. cpu_load[0] happens then to be updated more frequently + * than other cpu_load[idx] but it should be fine as cpu_load readers + * shouldn't rely into synchronized cpu_load[*] updates. */ -void cpu_load_update_nohz(int active) +void cpu_load_update_nohz_start(void) { struct rq *this_rq = this_rq(); + + /* + * This is all lockless but should be fine. If weighted_cpuload changes + * concurrently we'll exit nohz. And cpu_load write can race with + * cpu_load_update_idle() but both updater would be writing the same. + */ + this_rq->cpu_load[0] = weighted_cpuload(cpu_of(this_rq)); +} + +/* + * Account the tickless load in the end of a nohz frame. + */ +void cpu_load_update_nohz_stop(void) +{ unsigned long curr_jiffies = READ_ONCE(jiffies); - unsigned long load = active ? weighted_cpuload(cpu_of(this_rq)) : 0; + struct rq *this_rq = this_rq(); + unsigned long load; if (curr_jiffies == this_rq->last_load_update_tick) return; + load = weighted_cpuload(cpu_of(this_rq)); raw_spin_lock(&this_rq->lock); - __cpu_load_update_nohz(this_rq, curr_jiffies, load, active); + cpu_load_update_nohz(this_rq, curr_jiffies, load); raw_spin_unlock(&this_rq->lock); } -#endif /* CONFIG_NO_HZ */ +#else /* !CONFIG_NO_HZ_COMMON */ +static inline void cpu_load_update_nohz(struct rq *this_rq, + unsigned long curr_jiffies, + unsigned long load) { } +#endif /* CONFIG_NO_HZ_COMMON */ + +static void cpu_load_update_periodic(struct rq *this_rq, unsigned long load) +{ + /* See the mess around cpu_load_update_nohz(). */ + this_rq->last_load_update_tick = READ_ONCE(jiffies); + cpu_load_update(this_rq, load, 1); +} /* * Called from scheduler_tick() @@ -4713,11 +4742,11 @@ void cpu_load_update_nohz(int active) void cpu_load_update_active(struct rq *this_rq) { unsigned long load = weighted_cpuload(cpu_of(this_rq)); - /* - * See the mess around cpu_load_update_idle() / cpu_load_update_nohz(). - */ - this_rq->last_load_update_tick = jiffies; - __cpu_load_update(this_rq, load, 1, 1); + + if (tick_nohz_tick_stopped()) + cpu_load_update_nohz(this_rq, READ_ONCE(jiffies), load); + else + cpu_load_update_periodic(this_rq, load); } /* diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 66bdc9acc283..31872bc53bc4 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -776,6 +776,7 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, if (!ts->tick_stopped) { nohz_balance_enter_idle(cpu); calc_load_enter_idle(); + cpu_load_update_nohz_start(); ts->last_tick = hrtimer_get_expires(&ts->sched_timer); ts->tick_stopped = 1; @@ -802,11 +803,11 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, return tick; } -static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now, int active) +static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now) { /* Update jiffies first */ tick_do_update_jiffies64(now); - cpu_load_update_nohz(active); + cpu_load_update_nohz_stop(); calc_load_exit_idle(); touch_softlockup_watchdog_sched(); @@ -833,7 +834,7 @@ static void tick_nohz_full_update_tick(struct tick_sched *ts) if (can_stop_full_tick(ts)) tick_nohz_stop_sched_tick(ts, ktime_get(), cpu); else if (ts->tick_stopped) - tick_nohz_restart_sched_tick(ts, ktime_get(), 1); + tick_nohz_restart_sched_tick(ts, ktime_get()); #endif } @@ -1024,7 +1025,7 @@ void tick_nohz_idle_exit(void) tick_nohz_stop_idle(ts, now); if (ts->tick_stopped) { - tick_nohz_restart_sched_tick(ts, now, 0); + tick_nohz_restart_sched_tick(ts, now); tick_nohz_account_idle_ticks(ts); } -- GitLab From 9fd81dd5ce0b12341c9f83346f8d32ac68bd3841 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 19 Apr 2016 17:36:51 +0200 Subject: [PATCH 4037/9938] sched/fair: Optimize !CONFIG_NO_HZ_COMMON CPU load updates Some code in CPU load update only concern NO_HZ configs but it is built on all configurations. When NO_HZ isn't built, that code is harmless but just happens to take some useless ressources in CPU and memory: 1) one useless field in struct rq 2) jiffies record on every tick that is never used (cpu_load_update_periodic) 3) decay_load_missed is called two times on every tick to eventually return immediately with no action taken. And that function is dead code. For pure optimization purposes, lets conditionally build the NO_HZ related code. Signed-off-by: Frederic Weisbecker Signed-off-by: Peter Zijlstra (Intel) Cc: Byungchul Park Cc: Chris Metcalf Cc: Christoph Lameter Cc: Luiz Capitulino Cc: Mike Galbraith Cc: Paul E . McKenney Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1461080211-16271-1-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 5 ++--- kernel/sched/fair.c | 9 +++++++-- kernel/sched/sched.h | 6 ++++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index c98a2688f390..71dffbb27ce6 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7381,8 +7381,6 @@ void __init sched_init(void) for (j = 0; j < CPU_LOAD_IDX_MAX; j++) rq->cpu_load[j] = 0; - rq->last_load_update_tick = jiffies; - #ifdef CONFIG_SMP rq->sd = NULL; rq->rd = NULL; @@ -7401,12 +7399,13 @@ void __init sched_init(void) rq_attach_root(rq, &def_root_domain); #ifdef CONFIG_NO_HZ_COMMON + rq->last_load_update_tick = jiffies; rq->nohz_flags = 0; #endif #ifdef CONFIG_NO_HZ_FULL rq->last_sched_tick = 0; #endif -#endif +#endif /* CONFIG_SMP */ init_rq_hrtick(rq); atomic_set(&rq->nr_iowait, 0); } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index b70367a3e1ef..b8a33abce650 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4491,7 +4491,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) } #ifdef CONFIG_SMP - +#ifdef CONFIG_NO_HZ_COMMON /* * per rq 'load' arrray crap; XXX kill this. */ @@ -4557,6 +4557,7 @@ decay_load_missed(unsigned long load, unsigned long missed_updates, int idx) } return load; } +#endif /* CONFIG_NO_HZ_COMMON */ /** * __cpu_load_update - update the rq->cpu_load[] statistics @@ -4596,7 +4597,7 @@ decay_load_missed(unsigned long load, unsigned long missed_updates, int idx) static void cpu_load_update(struct rq *this_rq, unsigned long this_load, unsigned long pending_updates) { - unsigned long tickless_load = this_rq->cpu_load[0]; + unsigned long __maybe_unused tickless_load = this_rq->cpu_load[0]; int i, scale; this_rq->nr_load_updates++; @@ -4609,6 +4610,7 @@ static void cpu_load_update(struct rq *this_rq, unsigned long this_load, /* scale is effectively 1 << i now, and >> i divides by scale */ old_load = this_rq->cpu_load[i]; +#ifdef CONFIG_NO_HZ_COMMON old_load = decay_load_missed(old_load, pending_updates - 1, i); if (tickless_load) { old_load -= decay_load_missed(tickless_load, pending_updates - 1, i); @@ -4619,6 +4621,7 @@ static void cpu_load_update(struct rq *this_rq, unsigned long this_load, */ old_load += tickless_load; } +#endif new_load = this_load; /* * Round up the averaging division if load is increasing. This @@ -4731,8 +4734,10 @@ static inline void cpu_load_update_nohz(struct rq *this_rq, static void cpu_load_update_periodic(struct rq *this_rq, unsigned long load) { +#ifdef CONFIG_NO_HZ_COMMON /* See the mess around cpu_load_update_nohz(). */ this_rq->last_load_update_tick = READ_ONCE(jiffies); +#endif cpu_load_update(this_rq, load, 1); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 32d9e22cfacf..69da6fcaa0e8 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -585,11 +585,13 @@ struct rq { #endif #define CPU_LOAD_IDX_MAX 5 unsigned long cpu_load[CPU_LOAD_IDX_MAX]; - unsigned long last_load_update_tick; #ifdef CONFIG_NO_HZ_COMMON +#ifdef CONFIG_SMP + unsigned long last_load_update_tick; +#endif /* CONFIG_SMP */ u64 nohz_stamp; unsigned long nohz_flags; -#endif +#endif /* CONFIG_NO_HZ_COMMON */ #ifdef CONFIG_NO_HZ_FULL unsigned long last_sched_tick; #endif -- GitLab From fec148c000d0f9ac21679601722811eb60b4cc52 Mon Sep 17 00:00:00 2001 From: Xunlei Pang Date: Thu, 14 Apr 2016 20:19:28 +0800 Subject: [PATCH 4038/9938] sched/deadline: Fix a bug in dl_overflow() I got a minus(very big) dl_b->total_bw during my deadline tests. # grep dl /proc/sched_debug dl_rq[0]: .dl_nr_running : 0 .dl_bw->bw : 996147 .dl_bw->total_bw : -222297900 Something unusual must have happened. After some digging, I finally noticed that when changing a deadline task to normal(cfs), and changing it back to deadline immediately, after it died, we will got the wrong dl_bw->total_bw. The root cause is in dl_overflow(), it has: if (new_bw == p->dl.dl_bw) return 0; 1) When a deadline task is changed to !deadline task, it will start dl timer in switched_from_dl(), and retain previous deadline parameter till the timer expires. 2) If we change it back to deadline with the same bandwidth parameter before the timer expires, as it keeps the old bandwidth although it is not a deadline task. dl_overflow() simply returns success without updating the right data, and got the wrong dl_bw->total_bw. The solution is simple, if @p is not deadline, don't return. Signed-off-by: Xunlei Pang Signed-off-by: Peter Zijlstra (Intel) Acked-by: Juri Lelli Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Steven Rostedt Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1460636368-1993-1-git-send-email-xlpang@redhat.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 71dffbb27ce6..9d84d6004745 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2378,7 +2378,8 @@ static int dl_overflow(struct task_struct *p, int policy, u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0; int cpus, err = -1; - if (new_bw == p->dl.dl_bw) + /* !deadline task may carry old deadline bandwidth */ + if (new_bw == p->dl.dl_bw && task_has_dl_policy(p)) return 0; /* -- GitLab From 993f88f1cc7f0879047ff353e824e5cc8f10adfc Mon Sep 17 00:00:00 2001 From: Emmanouil Maroudas Date: Sat, 23 Apr 2016 18:33:00 +0300 Subject: [PATCH 4039/9938] EDAC: Increment correct counter in edac_inc_ue_error() Fix typo in edac_inc_ue_error() to increment ue_noinfo_count instead of ce_noinfo_count. Signed-off-by: Emmanouil Maroudas Cc: Mauro Carvalho Chehab Cc: linux-edac Fixes: 4275be635597 ("edac: Change internal representation to work with layers") Link: http://lkml.kernel.org/r/1461425580-5898-1-git-send-email-emmanouil.maroudas@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 1472f48c8ac6..6aa256b0a1ed 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -923,7 +923,7 @@ static void edac_inc_ue_error(struct mem_ctl_info *mci, mci->ue_mc += count; if (!enable_per_layer_report) { - mci->ce_noinfo_count += count; + mci->ue_noinfo_count += count; return; } -- GitLab From c5fb04cc96c1812eb09a3b0f3672f4a00d76730c Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 11 Apr 2016 12:01:34 -0500 Subject: [PATCH 4040/9938] ARM: socfpga: Initialize Arria10 OCRAM ECC on startup Initialize ECC for Arria10 On-Chip RAM on machine startup. The OCRAM memory must be initialized before data is stored in memory otherwise the ECC will fail on reads. The previous check-in 2364d423a7b3 ("ARM: socfpga: Enable Arria10 OCRAM ECC on startup") added the OCRAM enable and initialization code but was not called on startup. Signed-off-by: Thor Thayer Acked-by: Dinh Nguyen Cc: Russell King Cc: linux-arm-kernel@lists.infradead.org Cc: linux-edac Link: http://lkml.kernel.org/r/1460394094-23326-1-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- arch/arm/mach-socfpga/core.h | 1 + arch/arm/mach-socfpga/socfpga.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h index bfbc78df15dd..65e1817d8afe 100644 --- a/arch/arm/mach-socfpga/core.h +++ b/arch/arm/mach-socfpga/core.h @@ -39,6 +39,7 @@ extern void socfpga_sysmgr_init(void); void socfpga_init_l2_ecc(void); void socfpga_init_ocram_ecc(void); void socfpga_init_arria10_l2_ecc(void); +void socfpga_init_arria10_ocram_ecc(void); extern void __iomem *sys_manager_base_addr; extern void __iomem *rst_manager_base_addr; diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index e9b5b603df4b..dde14f7bf2c3 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -72,6 +72,8 @@ static void __init socfpga_arria10_init_irq(void) socfpga_sysmgr_init(); if (IS_ENABLED(CONFIG_EDAC_ALTERA_L2C)) socfpga_init_arria10_l2_ecc(); + if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM)) + socfpga_init_arria10_ocram_ecc(); } static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd) -- GitLab From d9a15489210f3c25de39dee85861352d5e79e9c5 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 14 Apr 2016 00:30:13 +0200 Subject: [PATCH 4041/9938] cifs: Fix xattr name checks Use strcmp(str, name) instead of strncmp(str, name, strlen(name)) for checking if str and name are the same (as opposed to name being a prefix of str) in the gexattr and setxattr inode operations. Signed-off-by: Andreas Gruenbacher Signed-off-by: Al Viro --- fs/cifs/xattr.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 5d57c85703a9..6e73ba96a97f 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -129,7 +129,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; - if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) + if (strcmp(ea_name, CIFS_XATTR_DOS_ATTRIB) == 0) cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ @@ -147,8 +147,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, rc = pTcon->ses->server->ops->set_EA(xid, pTcon, full_path, ea_name, ea_value, (__u16)value_size, cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, - strlen(CIFS_XATTR_CIFS_ACL)) == 0) { + } else if (strcmp(ea_name, CIFS_XATTR_CIFS_ACL) == 0) { #ifdef CONFIG_CIFS_ACL struct cifs_ntsd *pacl; pacl = kmalloc(value_size, GFP_KERNEL); @@ -170,10 +169,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, cifs_dbg(FYI, "Set CIFS ACL not supported yet\n"); #endif /* CONFIG_CIFS_ACL */ } else { - int temp; - temp = strncmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS, - strlen(XATTR_NAME_POSIX_ACL_ACCESS)); - if (temp == 0) { + if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) { #ifdef CONFIG_CIFS_POSIX if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, @@ -184,8 +180,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, #else cifs_dbg(FYI, "set POSIX ACL not supported\n"); #endif - } else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT, - strlen(XATTR_NAME_POSIX_ACL_DEFAULT)) == 0) { + } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0) { #ifdef CONFIG_CIFS_POSIX if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, @@ -246,7 +241,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; - if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) { + if (strcmp(ea_name, CIFS_XATTR_DOS_ATTRIB) == 0) { cifs_dbg(FYI, "attempt to query cifs inode metadata\n"); /* revalidate/getattr then populate from inode */ } /* BB add else when above is implemented */ @@ -264,8 +259,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, full_path, ea_name, ea_value, buf_size, cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS, - strlen(XATTR_NAME_POSIX_ACL_ACCESS)) == 0) { + } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) { #ifdef CONFIG_CIFS_POSIX if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, @@ -275,8 +269,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, #else cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); #endif /* CONFIG_CIFS_POSIX */ - } else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT, - strlen(XATTR_NAME_POSIX_ACL_DEFAULT)) == 0) { + } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0) { #ifdef CONFIG_CIFS_POSIX if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, @@ -286,8 +279,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, #else cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n"); #endif /* CONFIG_CIFS_POSIX */ - } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, - strlen(CIFS_XATTR_CIFS_ACL)) == 0) { + } else if (strcmp(ea_name, CIFS_XATTR_CIFS_ACL) == 0) { #ifdef CONFIG_CIFS_ACL u32 acllen; struct cifs_ntsd *pacl; -- GitLab From 45987e006c49728611e41d1fc04ff7cc803959f5 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 14 Apr 2016 00:30:14 +0200 Subject: [PATCH 4042/9938] cifs: Check for equality with ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT The two values ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT are meant to be enumerations, not bits in a bit mask. Use '==' instead of '&' to check for these values. Signed-off-by: Andreas Gruenbacher Signed-off-by: Al Viro --- fs/cifs/cifssmb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 76fcb50295a3..f24a89c5a518 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3366,7 +3366,7 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen, if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION) return -EOPNOTSUPP; - if (acl_type & ACL_TYPE_ACCESS) { + if (acl_type == ACL_TYPE_ACCESS) { count = le16_to_cpu(cifs_acl->access_entry_count); pACE = &cifs_acl->ace_array[0]; size = sizeof(struct cifs_posix_acl); @@ -3377,7 +3377,7 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen, size_of_data_area, size); return -EINVAL; } - } else if (acl_type & ACL_TYPE_DEFAULT) { + } else if (acl_type == ACL_TYPE_DEFAULT) { count = le16_to_cpu(cifs_acl->access_entry_count); size = sizeof(struct cifs_posix_acl); size += sizeof(struct cifs_posix_ace) * count; -- GitLab From 534bb0c7bdaf7377e84e82f0eb4a9992eaa87fbb Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 14 Apr 2016 00:30:15 +0200 Subject: [PATCH 4043/9938] cifs: Fix removexattr for os2.* xattrs If cifs_removexattr finds a "user." or "os2." xattr name prefix, it skips 5 bytes, one byte too many for "os2.". Signed-off-by: Andreas Gruenbacher Signed-off-by: Al Viro --- fs/cifs/xattr.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 6e73ba96a97f..721c6db6fa81 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -61,15 +61,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) } if (ea_name == NULL) { cifs_dbg(FYI, "Null xattr names not supported\n"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - && (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) { - cifs_dbg(FYI, - "illegal xattr request %s (only user namespace supported)\n", - ea_name); - /* BB what if no namespace prefix? */ - /* Should we just pass them to server, except for - system and perhaps security prefixes? */ - } else { + } else if (!strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto remove_ea_exit; @@ -78,6 +70,22 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) rc = pTcon->ses->server->ops->set_EA(xid, pTcon, full_path, ea_name, NULL, (__u16)0, cifs_sb->local_nls, cifs_remap(cifs_sb)); + } else if (!strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + goto remove_ea_exit; + + ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ + if (pTcon->ses->server->ops->set_EA) + rc = pTcon->ses->server->ops->set_EA(xid, pTcon, + full_path, ea_name, NULL, (__u16)0, + cifs_sb->local_nls, cifs_remap(cifs_sb)); + } else { + cifs_dbg(FYI, + "illegal xattr request %s (only user namespace supported)\n", + ea_name); + /* BB what if no namespace prefix? */ + /* Should we just pass them to server, except for + system and perhaps security prefixes? */ } remove_ea_exit: kfree(full_path); -- GitLab From a9ae008f407b50fc92ef19588d2ea2be13a7f5e2 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Fri, 22 Apr 2016 12:11:38 +0200 Subject: [PATCH 4044/9938] cifs: Switch to generic xattr handlers Use xattr handlers for resolving attribute names. The amount of setup code required on cifs is nontrivial, so use the same get and set functions for all handlers, with switch statements for the different types of attributes in them. The set_EA handler can handle NULL values, so we don't need a separate removexattr function anymore. Remove the cifs_dbg statements related to xattr name resolution; they don't add much. Don't build xattr.o when CONFIG_CIFS_XATTR is not defined. Signed-off-by: Andreas Gruenbacher Signed-off-by: Al Viro --- fs/cifs/Makefile | 3 +- fs/cifs/cifsfs.c | 26 ++-- fs/cifs/cifsfs.h | 12 +- fs/cifs/xattr.c | 342 ++++++++++++++++++++--------------------------- 4 files changed, 165 insertions(+), 218 deletions(-) diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 1964d212ab08..eed7eb09f46f 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -5,9 +5,10 @@ obj-$(CONFIG_CIFS) += cifs.o cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ - cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ + cifs_unicode.o nterr.o cifsencrypt.o \ readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o +cifs-$(CONFIG_CIFS_XATTR) += xattr.o cifs-$(CONFIG_CIFS_ACL) += cifsacl.o cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 1d86fc620e5c..43cc522b11e4 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "cifsfs.h" #include "cifspdu.h" @@ -135,6 +136,7 @@ cifs_read_super(struct super_block *sb) sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_op = &cifs_super_ops; + sb->s_xattr = cifs_xattr_handlers; sb->s_bdi = &cifs_sb->bdi; sb->s_blocksize = CIFS_MAX_MSGSIZE; sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ @@ -892,12 +894,10 @@ const struct inode_operations cifs_dir_inode_ops = { .setattr = cifs_setattr, .symlink = cifs_symlink, .mknod = cifs_mknod, -#ifdef CONFIG_CIFS_XATTR - .setxattr = cifs_setxattr, - .getxattr = cifs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = cifs_listxattr, - .removexattr = cifs_removexattr, -#endif + .removexattr = generic_removexattr, }; const struct inode_operations cifs_file_inode_ops = { @@ -905,12 +905,10 @@ const struct inode_operations cifs_file_inode_ops = { .setattr = cifs_setattr, .getattr = cifs_getattr, /* do we need this anymore? */ .permission = cifs_permission, -#ifdef CONFIG_CIFS_XATTR - .setxattr = cifs_setxattr, - .getxattr = cifs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = cifs_listxattr, - .removexattr = cifs_removexattr, -#endif + .removexattr = generic_removexattr, }; const struct inode_operations cifs_symlink_inode_ops = { @@ -920,12 +918,10 @@ const struct inode_operations cifs_symlink_inode_ops = { /* BB add the following two eventually */ /* revalidate: cifs_revalidate, setattr: cifs_notify_change, *//* BB do we need notify change */ -#ifdef CONFIG_CIFS_XATTR - .setxattr = cifs_setxattr, - .getxattr = cifs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = cifs_listxattr, - .removexattr = cifs_removexattr, -#endif + .removexattr = generic_removexattr, }; static int cifs_clone_file_range(struct file *src_file, loff_t off, diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index c89ecd7a5c39..c1e749af749b 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -120,11 +120,15 @@ extern const char *cifs_get_link(struct dentry *, struct inode *, struct delayed_call *); extern int cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname); -extern int cifs_removexattr(struct dentry *, const char *); -extern int cifs_setxattr(struct dentry *, const char *, const void *, - size_t, int); -extern ssize_t cifs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); + +#ifdef CONFIG_CIFS_XATTR +extern const struct xattr_handler *cifs_xattr_handlers[]; extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); +#else +# define cifs_xattr_handlers NULL +# define cifs_listxattr NULL +#endif + extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); #ifdef CONFIG_CIFS_NFSD_EXPORT extern const struct export_operations cifs_export_ops; diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 721c6db6fa81..c8b77aa24a1d 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -32,76 +32,19 @@ #include "cifs_unicode.h" #define MAX_EA_VALUE_SIZE 65535 -#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* BB need to add server (Samba e.g) support for security and trusted prefix */ -int cifs_removexattr(struct dentry *direntry, const char *ea_name) -{ - int rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR - unsigned int xid; - struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - char *full_path = NULL; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); +enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT }; - xid = get_xid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto remove_ea_exit; - } - if (ea_name == NULL) { - cifs_dbg(FYI, "Null xattr names not supported\n"); - } else if (!strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto remove_ea_exit; - - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ - if (pTcon->ses->server->ops->set_EA) - rc = pTcon->ses->server->ops->set_EA(xid, pTcon, - full_path, ea_name, NULL, (__u16)0, - cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else if (!strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto remove_ea_exit; - - ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ - if (pTcon->ses->server->ops->set_EA) - rc = pTcon->ses->server->ops->set_EA(xid, pTcon, - full_path, ea_name, NULL, (__u16)0, - cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else { - cifs_dbg(FYI, - "illegal xattr request %s (only user namespace supported)\n", - ea_name); - /* BB what if no namespace prefix? */ - /* Should we just pass them to server, except for - system and perhaps security prefixes? */ - } -remove_ea_exit: - kfree(full_path); - free_xid(xid); - cifs_put_tlink(tlink); -#endif - return rc; -} - -int cifs_setxattr(struct dentry *direntry, const char *ea_name, - const void *ea_value, size_t value_size, int flags) +static int cifs_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) { int rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR unsigned int xid; - struct super_block *sb = direntry->d_sb; + struct super_block *sb = dentry->d_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct tcon_link *tlink; struct cifs_tcon *pTcon; @@ -114,10 +57,10 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, xid = get_xid(); - full_path = build_path_from_dentry(direntry); + full_path = build_path_from_dentry(dentry); if (full_path == NULL) { rc = -ENOMEM; - goto set_ea_exit; + goto out; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ @@ -125,104 +68,88 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, /* if proc/fs/cifs/streamstoxattr is set then search server for EAs or streams to returns as xattrs */ - if (value_size > MAX_EA_VALUE_SIZE) { + if (size > MAX_EA_VALUE_SIZE) { cifs_dbg(FYI, "size of EA value too large\n"); rc = -EOPNOTSUPP; - goto set_ea_exit; + goto out; } - if (ea_name == NULL) { - cifs_dbg(FYI, "Null xattr names not supported\n"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - == 0) { + switch (handler->flags) { + case XATTR_USER: if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto set_ea_exit; - if (strcmp(ea_name, CIFS_XATTR_DOS_ATTRIB) == 0) - cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); + goto out; - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ if (pTcon->ses->server->ops->set_EA) rc = pTcon->ses->server->ops->set_EA(xid, pTcon, - full_path, ea_name, ea_value, (__u16)value_size, + full_path, name, value, (__u16)size, cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) - == 0) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto set_ea_exit; + break; - ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ - if (pTcon->ses->server->ops->set_EA) - rc = pTcon->ses->server->ops->set_EA(xid, pTcon, - full_path, ea_name, ea_value, (__u16)value_size, - cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else if (strcmp(ea_name, CIFS_XATTR_CIFS_ACL) == 0) { + case XATTR_CIFS_ACL: { #ifdef CONFIG_CIFS_ACL struct cifs_ntsd *pacl; - pacl = kmalloc(value_size, GFP_KERNEL); + + if (!value) + goto out; + pacl = kmalloc(size, GFP_KERNEL); if (!pacl) { rc = -ENOMEM; } else { - memcpy(pacl, ea_value, value_size); - if (pTcon->ses->server->ops->set_acl) + memcpy(pacl, value, size); + if (value && + pTcon->ses->server->ops->set_acl) rc = pTcon->ses->server->ops->set_acl(pacl, - value_size, d_inode(direntry), + size, d_inode(dentry), full_path, CIFS_ACL_DACL); else rc = -EOPNOTSUPP; if (rc == 0) /* force revalidate of the inode */ - CIFS_I(d_inode(direntry))->time = 0; + CIFS_I(d_inode(dentry))->time = 0; kfree(pacl); } -#else - cifs_dbg(FYI, "Set CIFS ACL not supported yet\n"); #endif /* CONFIG_CIFS_ACL */ - } else { - if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) { + break; + } + + case XATTR_ACL_ACCESS: #ifdef CONFIG_CIFS_POSIX - if (sb->s_flags & MS_POSIXACL) - rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, - ea_value, (const int)value_size, - ACL_TYPE_ACCESS, cifs_sb->local_nls, - cifs_remap(cifs_sb)); - cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc); -#else - cifs_dbg(FYI, "set POSIX ACL not supported\n"); -#endif - } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0) { + if (!value) + goto out; + if (sb->s_flags & MS_POSIXACL) + rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, + value, (const int)size, + ACL_TYPE_ACCESS, cifs_sb->local_nls, + cifs_remap(cifs_sb)); +#endif /* CONFIG_CIFS_POSIX */ + break; + + case XATTR_ACL_DEFAULT: #ifdef CONFIG_CIFS_POSIX - if (sb->s_flags & MS_POSIXACL) - rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, - ea_value, (const int)value_size, - ACL_TYPE_DEFAULT, cifs_sb->local_nls, - cifs_remap(cifs_sb)); - cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc); -#else - cifs_dbg(FYI, "set default POSIX ACL not supported\n"); -#endif - } else { - cifs_dbg(FYI, "illegal xattr request %s (only user namespace supported)\n", - ea_name); - /* BB what if no namespace prefix? */ - /* Should we just pass them to server, except for - system and perhaps security prefixes? */ - } + if (!value) + goto out; + if (sb->s_flags & MS_POSIXACL) + rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, + value, (const int)size, + ACL_TYPE_DEFAULT, cifs_sb->local_nls, + cifs_remap(cifs_sb)); +#endif /* CONFIG_CIFS_POSIX */ + break; } -set_ea_exit: +out: kfree(full_path); free_xid(xid); cifs_put_tlink(tlink); -#endif return rc; } -ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, - const char *ea_name, void *ea_value, size_t buf_size) +static int cifs_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) { ssize_t rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR unsigned int xid; - struct super_block *sb = direntry->d_sb; + struct super_block *sb = dentry->d_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct tcon_link *tlink; struct cifs_tcon *pTcon; @@ -235,95 +162,72 @@ ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, xid = get_xid(); - full_path = build_path_from_dentry(direntry); + full_path = build_path_from_dentry(dentry); if (full_path == NULL) { rc = -ENOMEM; - goto get_ea_exit; + goto out; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ - if (ea_name == NULL) { - cifs_dbg(FYI, "Null xattr names not supported\n"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - == 0) { + switch (handler->flags) { + case XATTR_USER: if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto get_ea_exit; + goto out; - if (strcmp(ea_name, CIFS_XATTR_DOS_ATTRIB) == 0) { - cifs_dbg(FYI, "attempt to query cifs inode metadata\n"); - /* revalidate/getattr then populate from inode */ - } /* BB add else when above is implemented */ - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ if (pTcon->ses->server->ops->query_all_EAs) rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, - full_path, ea_name, ea_value, buf_size, + full_path, name, value, size, cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto get_ea_exit; + break; - ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ - if (pTcon->ses->server->ops->query_all_EAs) - rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, - full_path, ea_name, ea_value, buf_size, - cifs_sb->local_nls, cifs_remap(cifs_sb)); - } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) { + case XATTR_CIFS_ACL: { +#ifdef CONFIG_CIFS_ACL + u32 acllen; + struct cifs_ntsd *pacl; + + if (pTcon->ses->server->ops->get_acl == NULL) + goto out; /* rc already EOPNOTSUPP */ + + pacl = pTcon->ses->server->ops->get_acl(cifs_sb, + inode, full_path, &acllen); + if (IS_ERR(pacl)) { + rc = PTR_ERR(pacl); + cifs_dbg(VFS, "%s: error %zd getting sec desc\n", + __func__, rc); + } else { + if (value) { + if (acllen > size) + acllen = -ERANGE; + else + memcpy(value, pacl, acllen); + } + rc = acllen; + kfree(pacl); + } +#endif /* CONFIG_CIFS_ACL */ + break; + } + + case XATTR_ACL_ACCESS: #ifdef CONFIG_CIFS_POSIX if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, - ea_value, buf_size, ACL_TYPE_ACCESS, + value, size, ACL_TYPE_ACCESS, cifs_sb->local_nls, cifs_remap(cifs_sb)); -#else - cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); -#endif /* CONFIG_CIFS_POSIX */ - } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0) { +#endif /* CONFIG_CIFS_POSIX */ + break; + + case XATTR_ACL_DEFAULT: #ifdef CONFIG_CIFS_POSIX if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, - ea_value, buf_size, ACL_TYPE_DEFAULT, + value, size, ACL_TYPE_DEFAULT, cifs_sb->local_nls, cifs_remap(cifs_sb)); -#else - cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n"); -#endif /* CONFIG_CIFS_POSIX */ - } else if (strcmp(ea_name, CIFS_XATTR_CIFS_ACL) == 0) { -#ifdef CONFIG_CIFS_ACL - u32 acllen; - struct cifs_ntsd *pacl; - - if (pTcon->ses->server->ops->get_acl == NULL) - goto get_ea_exit; /* rc already EOPNOTSUPP */ - - pacl = pTcon->ses->server->ops->get_acl(cifs_sb, - inode, full_path, &acllen); - if (IS_ERR(pacl)) { - rc = PTR_ERR(pacl); - cifs_dbg(VFS, "%s: error %zd getting sec desc\n", - __func__, rc); - } else { - if (ea_value) { - if (acllen > buf_size) - acllen = -ERANGE; - else - memcpy(ea_value, pacl, acllen); - } - rc = acllen; - kfree(pacl); - } -#else - cifs_dbg(FYI, "Query CIFS ACL not supported yet\n"); -#endif /* CONFIG_CIFS_ACL */ - } else if (strncmp(ea_name, - XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { - cifs_dbg(FYI, "Trusted xattr namespace not supported yet\n"); - } else if (strncmp(ea_name, - XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { - cifs_dbg(FYI, "Security xattr namespace not supported yet\n"); - } else - cifs_dbg(FYI, - "illegal xattr request %s (only user namespace supported)\n", - ea_name); +#endif /* CONFIG_CIFS_POSIX */ + break; + } /* We could add an additional check for streams ie if proc/fs/cifs/streamstoxattr is set then @@ -333,18 +237,16 @@ ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode, if (rc == -EINVAL) rc = -EOPNOTSUPP; -get_ea_exit: +out: kfree(full_path); free_xid(xid); cifs_put_tlink(tlink); -#endif return rc; } ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) { ssize_t rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR unsigned int xid; struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); struct tcon_link *tlink; @@ -381,6 +283,50 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) kfree(full_path); free_xid(xid); cifs_put_tlink(tlink); -#endif return rc; } + +static const struct xattr_handler cifs_user_xattr_handler = { + .prefix = XATTR_USER_PREFIX, + .flags = XATTR_USER, + .get = cifs_xattr_get, + .set = cifs_xattr_set, +}; + +/* os2.* attributes are treated like user.* attributes */ +static const struct xattr_handler cifs_os2_xattr_handler = { + .prefix = XATTR_OS2_PREFIX, + .flags = XATTR_USER, + .get = cifs_xattr_get, + .set = cifs_xattr_set, +}; + +static const struct xattr_handler cifs_cifs_acl_xattr_handler = { + .name = CIFS_XATTR_CIFS_ACL, + .flags = XATTR_CIFS_ACL, + .get = cifs_xattr_get, + .set = cifs_xattr_set, +}; + +static const struct xattr_handler cifs_posix_acl_access_xattr_handler = { + .name = XATTR_NAME_POSIX_ACL_ACCESS, + .flags = XATTR_ACL_ACCESS, + .get = cifs_xattr_get, + .set = cifs_xattr_set, +}; + +static const struct xattr_handler cifs_posix_acl_default_xattr_handler = { + .name = XATTR_NAME_POSIX_ACL_DEFAULT, + .flags = XATTR_ACL_DEFAULT, + .get = cifs_xattr_get, + .set = cifs_xattr_set, +}; + +const struct xattr_handler *cifs_xattr_handlers[] = { + &cifs_user_xattr_handler, + &cifs_os2_xattr_handler, + &cifs_cifs_acl_xattr_handler, + &cifs_posix_acl_access_xattr_handler, + &cifs_posix_acl_default_xattr_handler, + NULL +}; -- GitLab From a26feccaba296bd0ae410eabce79cb3443c8a701 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 14 Apr 2016 00:30:16 +0200 Subject: [PATCH 4045/9938] ceph: Get rid of d_find_alias in ceph_set_acl Create a variant of ceph_setattr that takes an inode instead of a dentry. Change __ceph_setxattr (and also __ceph_removexattr) to take an inode instead of a dentry. Use those in ceph_set_acl so that we no longer need a dentry there. Signed-off-by: Andreas Gruenbacher Signed-off-by: "Yan, Zheng" Signed-off-by: Al Viro --- fs/ceph/acl.c | 14 +++++--------- fs/ceph/inode.c | 16 ++++++++++------ fs/ceph/super.h | 4 ++-- fs/ceph/xattr.c | 28 ++++++++++++---------------- 4 files changed, 29 insertions(+), 33 deletions(-) diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 5457f216e2e5..4f67227f69a5 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -90,7 +90,6 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) char *value = NULL; struct iattr newattrs; umode_t new_mode = inode->i_mode, old_mode = inode->i_mode; - struct dentry *dentry; switch (type) { case ACL_TYPE_ACCESS: @@ -128,29 +127,26 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) goto out_free; } - dentry = d_find_alias(inode); if (new_mode != old_mode) { newattrs.ia_mode = new_mode; newattrs.ia_valid = ATTR_MODE; - ret = ceph_setattr(dentry, &newattrs); + ret = __ceph_setattr(inode, &newattrs); if (ret) - goto out_dput; + goto out_free; } - ret = __ceph_setxattr(dentry, name, value, size, 0); + ret = __ceph_setxattr(inode, name, value, size, 0); if (ret) { if (new_mode != old_mode) { newattrs.ia_mode = old_mode; newattrs.ia_valid = ATTR_MODE; - ceph_setattr(dentry, &newattrs); + __ceph_setattr(inode, &newattrs); } - goto out_dput; + goto out_free; } ceph_set_cached_acl(inode, type, acl); -out_dput: - dput(dentry); out_free: kfree(value); out: diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index ed58b168904a..cadb6aee7f70 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1776,16 +1776,12 @@ static const struct inode_operations ceph_symlink_iops = { .removexattr = ceph_removexattr, }; -/* - * setattr - */ -int ceph_setattr(struct dentry *dentry, struct iattr *attr) +int __ceph_setattr(struct inode *inode, struct iattr *attr) { - struct inode *inode = d_inode(dentry); struct ceph_inode_info *ci = ceph_inode(inode); const unsigned int ia_valid = attr->ia_valid; struct ceph_mds_request *req; - struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; + struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; struct ceph_cap_flush *prealloc_cf; int issued; int release = 0, dirtied = 0; @@ -2009,6 +2005,14 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) return err; } +/* + * setattr + */ +int ceph_setattr(struct dentry *dentry, struct iattr *attr) +{ + return __ceph_setattr(d_inode(dentry), attr); +} + /* * Verify that we have a lease on the given mask. If not, * do a getattr against an mds. diff --git a/fs/ceph/super.h b/fs/ceph/super.h index beb893bb234f..1e41bc2eb2a8 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -785,6 +785,7 @@ static inline int ceph_do_getattr(struct inode *inode, int mask, bool force) return __ceph_do_getattr(inode, NULL, mask, force); } extern int ceph_permission(struct inode *inode, int mask); +extern int __ceph_setattr(struct inode *inode, struct iattr *attr); extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); @@ -792,9 +793,8 @@ extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, /* xattr.c */ extern int ceph_setxattr(struct dentry *, const char *, const void *, size_t, int); -int __ceph_setxattr(struct dentry *, const char *, const void *, size_t, int); +int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int); ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t); -int __ceph_removexattr(struct dentry *, const char *); extern ssize_t ceph_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); extern ssize_t ceph_listxattr(struct dentry *, char *, size_t); extern int ceph_removexattr(struct dentry *, const char *); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index c6e917d360f7..248e32e3ae7d 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -877,11 +877,10 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) return err; } -static int ceph_sync_setxattr(struct dentry *dentry, const char *name, +static int ceph_sync_setxattr(struct inode *inode, const char *name, const char *value, size_t size, int flags) { - struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); - struct inode *inode = d_inode(dentry); + struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb); struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_mds_request *req; struct ceph_mds_client *mdsc = fsc->mdsc; @@ -939,13 +938,12 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name, return err; } -int __ceph_setxattr(struct dentry *dentry, const char *name, +int __ceph_setxattr(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - struct inode *inode = d_inode(dentry); struct ceph_vxattr *vxattr; struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; + struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; struct ceph_cap_flush *prealloc_cf = NULL; int issued; int err; @@ -1056,7 +1054,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, "during filling trace\n", inode); err = -EBUSY; } else { - err = ceph_sync_setxattr(dentry, name, value, size, flags); + err = ceph_sync_setxattr(inode, name, value, size, flags); } out: ceph_free_cap_flush(prealloc_cf); @@ -1078,14 +1076,13 @@ int ceph_setxattr(struct dentry *dentry, const char *name, if (size == 0) value = ""; /* empty EA, do not remove */ - return __ceph_setxattr(dentry, name, value, size, flags); + return __ceph_setxattr(d_inode(dentry), name, value, size, flags); } -static int ceph_send_removexattr(struct dentry *dentry, const char *name) +static int ceph_send_removexattr(struct inode *inode, const char *name) { - struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); + struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb); struct ceph_mds_client *mdsc = fsc->mdsc; - struct inode *inode = d_inode(dentry); struct ceph_mds_request *req; int err; @@ -1106,12 +1103,11 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name) return err; } -int __ceph_removexattr(struct dentry *dentry, const char *name) +static int __ceph_removexattr(struct inode *inode, const char *name) { - struct inode *inode = d_inode(dentry); struct ceph_vxattr *vxattr; struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; + struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; struct ceph_cap_flush *prealloc_cf = NULL; int issued; int err; @@ -1192,7 +1188,7 @@ int __ceph_removexattr(struct dentry *dentry, const char *name) if (lock_snap_rwsem) up_read(&mdsc->snap_rwsem); ceph_free_cap_flush(prealloc_cf); - err = ceph_send_removexattr(dentry, name); + err = ceph_send_removexattr(inode, name); return err; } @@ -1204,7 +1200,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) return generic_removexattr(dentry, name); - return __ceph_removexattr(dentry, name); + return __ceph_removexattr(d_inode(dentry), name); } #ifdef CONFIG_SECURITY -- GitLab From 2cdeb1e472cf03dec4dc614623fd2e6bd8e5f271 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 14 Apr 2016 00:30:17 +0200 Subject: [PATCH 4046/9938] ceph: Switch to generic xattr handlers Add a catch-all xattr handler at the end of ceph_xattr_handlers. Check for valid attribute names there, and remove those checks from __ceph_{get,set,remove}xattr instead. No "system.*" xattrs need to be handled by the catch-all handler anymore. The set xattr handler is called with a NULL value to indicate that the attribute should be removed; __ceph_setxattr already handles that case correctly (ceph_set_acl could already calling __ceph_setxattr with a NULL value). Move the check for snapshots from ceph_{set,remove}xattr into __ceph_{set,remove}xattr. With that, ceph_{get,set,remove}xattr can be replaced with the generic iops. Signed-off-by: Andreas Gruenbacher Signed-off-by: "Yan, Zheng" Signed-off-by: Al Viro --- fs/ceph/dir.c | 7 +++--- fs/ceph/inode.c | 13 +++++----- fs/ceph/super.h | 4 --- fs/ceph/xattr.c | 66 ++++++++++++++++++++----------------------------- 4 files changed, 38 insertions(+), 52 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index fadc243dfb28..2e0afdc1da9e 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "super.h" #include "mds_client.h" @@ -1342,10 +1343,10 @@ const struct inode_operations ceph_dir_iops = { .permission = ceph_permission, .getattr = ceph_getattr, .setattr = ceph_setattr, - .setxattr = ceph_setxattr, - .getxattr = ceph_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ceph_listxattr, - .removexattr = ceph_removexattr, + .removexattr = generic_removexattr, .get_acl = ceph_get_acl, .set_acl = ceph_set_acl, .mknod = ceph_mknod, diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index cadb6aee7f70..addf8efb842d 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -92,10 +93,10 @@ const struct inode_operations ceph_file_iops = { .permission = ceph_permission, .setattr = ceph_setattr, .getattr = ceph_getattr, - .setxattr = ceph_setxattr, - .getxattr = ceph_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ceph_listxattr, - .removexattr = ceph_removexattr, + .removexattr = generic_removexattr, .get_acl = ceph_get_acl, .set_acl = ceph_set_acl, }; @@ -1770,10 +1771,10 @@ static const struct inode_operations ceph_symlink_iops = { .get_link = simple_get_link, .setattr = ceph_setattr, .getattr = ceph_getattr, - .setxattr = ceph_setxattr, - .getxattr = ceph_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ceph_listxattr, - .removexattr = ceph_removexattr, + .removexattr = generic_removexattr, }; int __ceph_setattr(struct inode *inode, struct iattr *attr) diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 1e41bc2eb2a8..7b99eb756477 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -791,13 +791,9 @@ extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); /* xattr.c */ -extern int ceph_setxattr(struct dentry *, const char *, const void *, - size_t, int); int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int); ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t); -extern ssize_t ceph_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); extern ssize_t ceph_listxattr(struct dentry *, char *, size_t); -extern int ceph_removexattr(struct dentry *, const char *); extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci); extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci); extern void __init ceph_xattr_init(void); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 248e32e3ae7d..8966e9d96bdb 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -16,6 +16,8 @@ static int __remove_xattr(struct ceph_inode_info *ci, struct ceph_inode_xattr *xattr); +const struct xattr_handler ceph_other_xattr_handler; + /* * List of handlers for synthetic system.* attributes. Other * attributes are handled directly. @@ -25,6 +27,7 @@ const struct xattr_handler *ceph_xattr_handlers[] = { &posix_acl_access_xattr_handler, &posix_acl_default_xattr_handler, #endif + &ceph_other_xattr_handler, NULL, }; @@ -33,7 +36,6 @@ static bool ceph_is_valid_xattr(const char *name) return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) || !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) || - !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); } @@ -740,9 +742,6 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, int req_mask; int err; - if (!ceph_is_valid_xattr(name)) - return -ENODATA; - /* let's see if a virtual xattr was requested */ vxattr = ceph_match_vxattr(inode, name); if (vxattr) { @@ -804,15 +803,6 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, return err; } -ssize_t ceph_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *value, size_t size) -{ - if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_getxattr(dentry, inode, name, value, size); - - return __ceph_getxattr(inode, name, value, size); -} - ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) { struct inode *inode = d_inode(dentry); @@ -956,8 +946,8 @@ int __ceph_setxattr(struct inode *inode, const char *name, int required_blob_size; bool lock_snap_rwsem = false; - if (!ceph_is_valid_xattr(name)) - return -EOPNOTSUPP; + if (ceph_snap(inode) != CEPH_NOSNAP) + return -EROFS; vxattr = ceph_match_vxattr(inode, name); if (vxattr && vxattr->readonly) @@ -1064,21 +1054,6 @@ int __ceph_setxattr(struct inode *inode, const char *name, return err; } -int ceph_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP) - return -EROFS; - - if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_setxattr(dentry, name, value, size, flags); - - if (size == 0) - value = ""; /* empty EA, do not remove */ - - return __ceph_setxattr(d_inode(dentry), name, value, size, flags); -} - static int ceph_send_removexattr(struct inode *inode, const char *name) { struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb); @@ -1115,8 +1090,8 @@ static int __ceph_removexattr(struct inode *inode, const char *name) int dirty; bool lock_snap_rwsem = false; - if (!ceph_is_valid_xattr(name)) - return -EOPNOTSUPP; + if (ceph_snap(inode) != CEPH_NOSNAP) + return -EROFS; vxattr = ceph_match_vxattr(inode, name); if (vxattr && vxattr->readonly) @@ -1192,17 +1167,30 @@ static int __ceph_removexattr(struct inode *inode, const char *name) return err; } -int ceph_removexattr(struct dentry *dentry, const char *name) +static int ceph_get_xattr_handler(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) { - if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP) - return -EROFS; - - if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_removexattr(dentry, name); + if (!ceph_is_valid_xattr(name)) + return -EOPNOTSUPP; + return __ceph_getxattr(inode, name, value, size); +} - return __ceph_removexattr(d_inode(dentry), name); +static int ceph_set_xattr_handler(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + if (!ceph_is_valid_xattr(name)) + return -EOPNOTSUPP; + return __ceph_setxattr(d_inode(dentry), name, value, size, flags); } +const struct xattr_handler ceph_other_xattr_handler = { + .prefix = "", /* match any name => handlers called with full name */ + .get = ceph_get_xattr_handler, + .set = ceph_set_xattr_handler, +}; + #ifdef CONFIG_SECURITY bool ceph_security_xattr_wanted(struct inode *in) { -- GitLab From b971e94e8f4c09ff775cfb2c4f846b4431a00598 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 14 Apr 2016 00:30:18 +0200 Subject: [PATCH 4047/9938] ceph: kill __ceph_removexattr() when removing a xattr, generic_removexattr() calls __ceph_setxattr() with NULL value and XATTR_REPLACE flag. __ceph_removexattr() is not used any more. Signed-off-by: "Yan, Zheng" Signed-off-by: Al Viro --- fs/ceph/xattr.c | 126 ------------------------------------------------ 1 file changed, 126 deletions(-) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 8966e9d96bdb..0d66722c6a52 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -498,19 +498,6 @@ static int __remove_xattr(struct ceph_inode_info *ci, return 0; } -static int __remove_xattr_by_name(struct ceph_inode_info *ci, - const char *name) -{ - struct rb_node **p; - struct ceph_inode_xattr *xattr; - int err; - - p = &ci->i_xattrs.index.rb_node; - xattr = __get_xattr(ci, name); - err = __remove_xattr(ci, xattr); - return err; -} - static char *__copy_xattr_names(struct ceph_inode_info *ci, char *dest) { @@ -1054,119 +1041,6 @@ int __ceph_setxattr(struct inode *inode, const char *name, return err; } -static int ceph_send_removexattr(struct inode *inode, const char *name) -{ - struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb); - struct ceph_mds_client *mdsc = fsc->mdsc; - struct ceph_mds_request *req; - int err; - - req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_RMXATTR, - USE_AUTH_MDS); - if (IS_ERR(req)) - return PTR_ERR(req); - req->r_path2 = kstrdup(name, GFP_NOFS); - if (!req->r_path2) - return -ENOMEM; - - req->r_inode = inode; - ihold(inode); - req->r_num_caps = 1; - req->r_inode_drop = CEPH_CAP_XATTR_SHARED; - err = ceph_mdsc_do_request(mdsc, NULL, req); - ceph_mdsc_put_request(req); - return err; -} - -static int __ceph_removexattr(struct inode *inode, const char *name) -{ - struct ceph_vxattr *vxattr; - struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; - struct ceph_cap_flush *prealloc_cf = NULL; - int issued; - int err; - int required_blob_size; - int dirty; - bool lock_snap_rwsem = false; - - if (ceph_snap(inode) != CEPH_NOSNAP) - return -EROFS; - - vxattr = ceph_match_vxattr(inode, name); - if (vxattr && vxattr->readonly) - return -EOPNOTSUPP; - - /* pass any unhandled ceph.* xattrs through to the MDS */ - if (!strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN)) - goto do_sync_unlocked; - - prealloc_cf = ceph_alloc_cap_flush(); - if (!prealloc_cf) - return -ENOMEM; - - err = -ENOMEM; - spin_lock(&ci->i_ceph_lock); -retry: - issued = __ceph_caps_issued(ci, NULL); - if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) - goto do_sync; - - if (!lock_snap_rwsem && !ci->i_head_snapc) { - lock_snap_rwsem = true; - if (!down_read_trylock(&mdsc->snap_rwsem)) { - spin_unlock(&ci->i_ceph_lock); - down_read(&mdsc->snap_rwsem); - spin_lock(&ci->i_ceph_lock); - goto retry; - } - } - - dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); - - __build_xattrs(inode); - - required_blob_size = __get_required_blob_size(ci, 0, 0); - - if (!ci->i_xattrs.prealloc_blob || - required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { - struct ceph_buffer *blob; - - spin_unlock(&ci->i_ceph_lock); - dout(" preaallocating new blob size=%d\n", required_blob_size); - blob = ceph_buffer_new(required_blob_size, GFP_NOFS); - if (!blob) - goto do_sync_unlocked; - spin_lock(&ci->i_ceph_lock); - if (ci->i_xattrs.prealloc_blob) - ceph_buffer_put(ci->i_xattrs.prealloc_blob); - ci->i_xattrs.prealloc_blob = blob; - goto retry; - } - - err = __remove_xattr_by_name(ceph_inode(inode), name); - - dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL, - &prealloc_cf); - ci->i_xattrs.dirty = true; - inode->i_ctime = current_fs_time(inode->i_sb); - spin_unlock(&ci->i_ceph_lock); - if (lock_snap_rwsem) - up_read(&mdsc->snap_rwsem); - if (dirty) - __mark_inode_dirty(inode, dirty); - ceph_free_cap_flush(prealloc_cf); - return err; -do_sync: - spin_unlock(&ci->i_ceph_lock); -do_sync_unlocked: - if (lock_snap_rwsem) - up_read(&mdsc->snap_rwsem); - ceph_free_cap_flush(prealloc_cf); - err = ceph_send_removexattr(inode, name); - return err; -} - static int ceph_get_xattr_handler(const struct xattr_handler *handler, struct dentry *dentry, struct inode *inode, const char *name, void *value, size_t size) -- GitLab From dfc57732ad38f93ae6232a3b4e64fd077383a0f1 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Wed, 20 Apr 2016 19:23:43 +0200 Subject: [PATCH 4048/9938] iio:core: mounting matrix support Expose a rotation matrix to indicate userspace the chip placement with respect to the overall hardware system. This is needed to adjust coordinates sampled from a sensor chip when its position deviates from the main hardware system. Final coordinates computation is delegated to userspace since: * computation may involve floating point arithmetics ; * it allows an application to combine adjustments with arbitrary transformations. This 3 dimentional space rotation matrix is expressed as 3x3 array of strings to support floating point numbers. It may be retrieved from a "[_][_]mount_matrix" sysfs attribute file. It is declared into a device / driver specific DTS property or platform data. Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 51 +++++++++++++++ drivers/iio/industrialio-core.c | 82 +++++++++++++++++++++++++ include/linux/iio/iio.h | 31 ++++++++++ 3 files changed, 164 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index f155eff910f9..ba8df69d40b0 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1512,3 +1512,54 @@ Contact: linux-iio@vger.kernel.org Description: Raw (unscaled no offset etc.) pH reading of a substance as a negative base-10 logarithm of hydrodium ions in a litre of water. + +What: /sys/bus/iio/devices/iio:deviceX/mount_matrix +What: /sys/bus/iio/devices/iio:deviceX/in_mount_matrix +What: /sys/bus/iio/devices/iio:deviceX/out_mount_matrix +KernelVersion: 4.6 +Contact: linux-iio@vger.kernel.org +Description: + Mounting matrix for IIO sensors. This is a rotation matrix which + informs userspace about sensor chip's placement relative to the + main hardware it is mounted on. + Main hardware placement is defined according to the local + reference frame related to the physical quantity the sensor + measures. + Given that the rotation matrix is defined in a board specific + way (platform data and / or device-tree), the main hardware + reference frame definition is left to the implementor's choice + (see below for a magnetometer example). + Applications should apply this rotation matrix to samples so + that when main hardware reference frame is aligned onto local + reference frame, then sensor chip reference frame is also + perfectly aligned with it. + Matrix is a 3x3 unitary matrix and typically looks like + [0, 1, 0; 1, 0, 0; 0, 0, -1]. Identity matrix + [1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and main hardware + are perfectly aligned with each other. + + For example, a mounting matrix for a magnetometer sensor informs + userspace about sensor chip's ORIENTATION relative to the main + hardware. + More specifically, main hardware orientation is defined with + respect to the LOCAL EARTH GEOMAGNETIC REFERENCE FRAME where : + * Y is in the ground plane and positive towards magnetic North ; + * X is in the ground plane, perpendicular to the North axis and + positive towards the East ; + * Z is perpendicular to the ground plane and positive upwards. + + An implementor might consider that for a hand-held device, a + 'natural' orientation would be 'front facing camera at the top'. + The main hardware reference frame could then be described as : + * Y is in the plane of the screen and is positive towards the + top of the screen ; + * X is in the plane of the screen, perpendicular to Y axis, and + positive towards the right hand side of the screen ; + * Z is perpendicular to the screen plane and positive out of the + screen. + Another example for a quadrotor UAV might be : + * Y is in the plane of the propellers and positive towards the + front-view camera; + * X is in the plane of the propellers, perpendicular to Y axis, + and positive towards the starboard side of the UAV ; + * Z is perpendicular to propellers plane and positive upwards. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 190a5939fd8c..e6319a9346b2 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -412,6 +412,88 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(iio_enum_write); +static const struct iio_mount_matrix iio_mount_idmatrix = { + .rotation = { + "1", "0", "0", + "0", "1", "0", + "0", "0", "1" + } +}; + +static int iio_setup_mount_idmatrix(const struct device *dev, + struct iio_mount_matrix *matrix) +{ + *matrix = iio_mount_idmatrix; + dev_info(dev, "mounting matrix not found: using identity...\n"); + return 0; +} + +ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv, + const struct iio_chan_spec *chan, char *buf) +{ + const struct iio_mount_matrix *mtx = ((iio_get_mount_matrix_t *) + priv)(indio_dev, chan); + + if (IS_ERR(mtx)) + return PTR_ERR(mtx); + + if (!mtx) + mtx = &iio_mount_idmatrix; + + return snprintf(buf, PAGE_SIZE, "%s, %s, %s; %s, %s, %s; %s, %s, %s\n", + mtx->rotation[0], mtx->rotation[1], mtx->rotation[2], + mtx->rotation[3], mtx->rotation[4], mtx->rotation[5], + mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]); +} +EXPORT_SYMBOL_GPL(iio_show_mount_matrix); + +/** + * of_iio_read_mount_matrix() - retrieve iio device mounting matrix from + * device-tree "mount-matrix" property + * @dev: device the mounting matrix property is assigned to + * @propname: device specific mounting matrix property name + * @matrix: where to store retrieved matrix + * + * If device is assigned no mounting matrix property, a default 3x3 identity + * matrix will be filled in. + * + * Return: 0 if success, or a negative error code on failure. + */ +#ifdef CONFIG_OF +int of_iio_read_mount_matrix(const struct device *dev, + const char *propname, + struct iio_mount_matrix *matrix) +{ + if (dev->of_node) { + int err = of_property_read_string_array(dev->of_node, + propname, matrix->rotation, + ARRAY_SIZE(iio_mount_idmatrix.rotation)); + + if (err == ARRAY_SIZE(iio_mount_idmatrix.rotation)) + return 0; + + if (err >= 0) + /* Invalid number of matrix entries. */ + return -EINVAL; + + if (err != -EINVAL) + /* Invalid matrix declaration format. */ + return err; + } + + /* Matrix was not declared at all: fallback to identity. */ + return iio_setup_mount_idmatrix(dev, matrix); +} +#else +int of_iio_read_mount_matrix(const struct device *dev, + const char *propname, + struct iio_mount_matrix *matrix) +{ + return iio_setup_mount_idmatrix(dev, matrix); +} +#endif +EXPORT_SYMBOL(of_iio_read_mount_matrix); + /** * iio_format_value() - Formats a IIO value into its string representation * @buf: The buffer to which the formatted value gets written diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 0b2773ada0ba..7c29cb0124ae 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -147,6 +147,37 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, .private = (uintptr_t)(_e), \ } +/** + * struct iio_mount_matrix - iio mounting matrix + * @rotation: 3 dimensional space rotation matrix defining sensor alignment with + * main hardware + */ +struct iio_mount_matrix { + const char *rotation[9]; +}; + +ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv, + const struct iio_chan_spec *chan, char *buf); +int of_iio_read_mount_matrix(const struct device *dev, const char *propname, + struct iio_mount_matrix *matrix); + +typedef const struct iio_mount_matrix * + (iio_get_mount_matrix_t)(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan); + +/** + * IIO_MOUNT_MATRIX() - Initialize mount matrix extended channel attribute + * @_shared: Whether the attribute is shared between all channels + * @_get: Pointer to an iio_get_mount_matrix_t accessor + */ +#define IIO_MOUNT_MATRIX(_shared, _get) \ +{ \ + .name = "mount_matrix", \ + .shared = (_shared), \ + .read = iio_show_mount_matrix, \ + .private = (uintptr_t)(_get), \ +} + /** * struct iio_event_spec - specification for a channel event * @type: Type of the event -- GitLab From 97eacb9166f4810368e180073dcbceeff0de34df Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Wed, 20 Apr 2016 19:23:44 +0200 Subject: [PATCH 4049/9938] iio:ak8975: add mounting matrix support Expose a rotation matrix to indicate userspace the chip orientation with respect to the overall hardware system. Matrix is retrieved from "in_mount_matrix". It is declared into ak8975 DTS entry as a "mount-matrix" property. Signed-off-by: Gregor Boirie Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/magnetometer/ak8975.txt | 10 ++++++ drivers/iio/magnetometer/ak8975.c | 34 ++++++++++++++++--- include/linux/iio/magnetometer/ak8975.h | 16 +++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 include/linux/iio/magnetometer/ak8975.h diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt index 34a3206eefdf..e1e7dd3259f6 100644 --- a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt +++ b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt @@ -9,6 +9,7 @@ Optional properties: - gpios : should be device tree identifier of the magnetometer DRDY pin - vdd-supply: an optional regulator that needs to be on to provide VDD + - mount-matrix: an optional 3x3 mounting rotation matrix Example: @@ -17,4 +18,13 @@ ak8975@0c { reg = <0x0c>; gpios = <&gpj0 7 0>; vdd-supply = <&ldo_3v3_gnss>; + mount-matrix = "-0.984807753012208", /* x0 */ + "0", /* y0 */ + "-0.173648177666930", /* z0 */ + "0", /* x1 */ + "-1", /* y1 */ + "0", /* z1 */ + "-0.173648177666930", /* x2 */ + "0", /* y2 */ + "0.984807753012208"; /* z2 */ }; diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index a2aac50a0149..dbf066129a04 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -40,7 +40,8 @@ #include #include #include -#include + +#include /* * Register definitions, as well as various shifts and masks to get at the @@ -376,6 +377,7 @@ struct ak8975_data { wait_queue_head_t data_ready_queue; unsigned long flags; u8 cntl_cache; + struct iio_mount_matrix orientation; struct regulator *vdd; }; @@ -726,6 +728,18 @@ static int ak8975_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +static const struct iio_mount_matrix * +ak8975_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + return &((struct ak8975_data *)iio_priv(indio_dev))->orientation; +} + +static const struct iio_chan_spec_ext_info ak8975_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, ak8975_get_mount_matrix), + { }, +}; + #define AK8975_CHANNEL(axis, index) \ { \ .type = IIO_MAGN, \ @@ -740,7 +754,8 @@ static int ak8975_read_raw(struct iio_dev *indio_dev, .realbits = 16, \ .storagebits = 16, \ .endianness = IIO_CPU \ - } \ + }, \ + .ext_info = ak8975_ext_info, \ } static const struct iio_chan_spec ak8975_channels[] = { @@ -837,10 +852,12 @@ static int ak8975_probe(struct i2c_client *client, int err; const char *name = NULL; enum asahi_compass_chipset chipset; + const struct ak8975_platform_data *pdata = + dev_get_platdata(&client->dev); /* Grab and set up the supplied GPIO. */ - if (client->dev.platform_data) - eoc_gpio = *(int *)(client->dev.platform_data); + if (pdata) + eoc_gpio = pdata->eoc_gpio; else if (client->dev.of_node) eoc_gpio = of_get_gpio(client->dev.of_node, 0); else @@ -874,6 +891,15 @@ static int ak8975_probe(struct i2c_client *client, data->eoc_gpio = eoc_gpio; data->eoc_irq = 0; + if (!pdata) { + err = of_iio_read_mount_matrix(&client->dev, + "mount-matrix", + &data->orientation); + if (err) + return err; + } else + data->orientation = pdata->orientation; + /* id will be NULL when enumerated via ACPI */ if (id) { chipset = (enum asahi_compass_chipset)(id->driver_data); diff --git a/include/linux/iio/magnetometer/ak8975.h b/include/linux/iio/magnetometer/ak8975.h new file mode 100644 index 000000000000..c8400959d197 --- /dev/null +++ b/include/linux/iio/magnetometer/ak8975.h @@ -0,0 +1,16 @@ +#ifndef __IIO_MAGNETOMETER_AK8975_H__ +#define __IIO_MAGNETOMETER_AK8975_H__ + +#include + +/** + * struct ak8975_platform_data - AK8975 magnetometer driver platform data + * @eoc_gpio: data ready event gpio + * @orientation: mounting matrix relative to main hardware + */ +struct ak8975_platform_data { + int eoc_gpio; + struct iio_mount_matrix orientation; +}; + +#endif -- GitLab From eb3798463f71afc77abd25b2f62708be06f7173b Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Wed, 20 Apr 2016 19:23:45 +0200 Subject: [PATCH 4050/9938] iio:imu:mpu6050: enhance mounting matrix support Add a new rotation matrix sysfs attribute compliant with IIO core mounting matrix API. Matrix is retrieved from "in_anglvel_mount_matrix" and "in_accel_mount_matrix" sysfs attributes. It is declared into mpu6050 DTS entry as a "mount-matrix" property. Old interface is kept for backward userspace compatibility and may be retrieved from legacy platform_data mechanism only. Signed-off-by: Gregor Boirie Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 2 ++ .../bindings/iio/imu/inv_mpu6050.txt | 13 +++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 36 +++++++++++++++++-- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 4 ++- .../linux/platform_data/invensense_mpu6050.h | 5 ++- 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index ba8df69d40b0..df44998e7506 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1516,6 +1516,8 @@ Description: What: /sys/bus/iio/devices/iio:deviceX/mount_matrix What: /sys/bus/iio/devices/iio:deviceX/in_mount_matrix What: /sys/bus/iio/devices/iio:deviceX/out_mount_matrix +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_mount_matrix +What: /sys/bus/iio/devices/iio:deviceX/in_accel_mount_matrix KernelVersion: 4.6 Contact: linux-iio@vger.kernel.org Description: diff --git a/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt b/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt index e4d8f1c52f4a..a9fc11e43b45 100644 --- a/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt +++ b/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt @@ -8,10 +8,23 @@ Required properties: - interrupt-parent : should be the phandle for the interrupt controller - interrupts : interrupt mapping for GPIO IRQ +Optional properties: + - mount-matrix: an optional 3x3 mounting rotation matrix + + Example: mpu6050@68 { compatible = "invensense,mpu6050"; reg = <0x68>; interrupt-parent = <&gpio1>; interrupts = <18 1>; + mount-matrix = "-0.984807753012208", /* x0 */ + "0", /* y0 */ + "-0.173648177666930", /* z0 */ + "0", /* x1 */ + "-1", /* y1 */ + "0", /* z1 */ + "-0.173648177666930", /* x2 */ + "0", /* y2 */ + "0.984807753012208"; /* z2 */ }; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index d192953e9a38..482a2490c53a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -600,6 +600,10 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr, /** * inv_attr_show() - calling this function will show current * parameters. + * + * Deprecated in favor of IIO mounting matrix API. + * + * See inv_get_mount_matrix() */ static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -644,6 +648,18 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev, return 0; } +static const struct iio_mount_matrix * +inv_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + return &((struct inv_mpu6050_state *)iio_priv(indio_dev))->orientation; +} + +static const struct iio_chan_spec_ext_info inv_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, inv_get_mount_matrix), + { }, +}; + #define INV_MPU6050_CHAN(_type, _channel2, _index) \ { \ .type = _type, \ @@ -660,6 +676,7 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev, .shift = 0, \ .endianness = IIO_BE, \ }, \ + .ext_info = inv_ext_info, \ } static const struct iio_chan_spec inv_mpu_channels[] = { @@ -692,14 +709,16 @@ static IIO_CONST_ATTR(in_accel_scale_available, "0.000598 0.001196 0.002392 0.004785"); static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show, inv_mpu6050_fifo_rate_store); + +/* Deprecated: kept for userspace backward compatibility. */ static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL, ATTR_GYRO_MATRIX); static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL, ATTR_ACCL_MATRIX); static struct attribute *inv_attributes[] = { - &iio_dev_attr_in_gyro_matrix.dev_attr.attr, - &iio_dev_attr_in_accel_matrix.dev_attr.attr, + &iio_dev_attr_in_gyro_matrix.dev_attr.attr, /* deprecated */ + &iio_dev_attr_in_accel_matrix.dev_attr.attr, /* deprecated */ &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_const_attr_in_accel_scale_available.dev_attr.attr, @@ -779,9 +798,20 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, st->powerup_count = 0; st->irq = irq; st->map = regmap; + pdata = dev_get_platdata(dev); - if (pdata) + if (!pdata) { + result = of_iio_read_mount_matrix(dev, "mount-matrix", + &st->orientation); + if (result) { + dev_err(dev, "Failed to retrieve mounting matrix %d\n", + result); + return result; + } + } else { st->plat_data = *pdata; + } + /* power is turned on inside check chip type*/ result = inv_check_and_setup_chip(st); if (result) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index e302a49703bf..52d60cdc9f16 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -114,7 +114,8 @@ struct inv_mpu6050_hw { * @hw: Other hardware-specific information. * @chip_type: chip type. * @time_stamp_lock: spin lock to time stamp. - * @plat_data: platform data. + * @plat_data: platform data (deprecated in favor of @orientation). + * @orientation: sensor chip orientation relative to main hardware. * @timestamps: kfifo queue to store time stamp. * @map regmap pointer. * @irq interrupt number. @@ -131,6 +132,7 @@ struct inv_mpu6050_state { struct i2c_client *mux_client; unsigned int powerup_count; struct inv_mpu6050_platform_data plat_data; + struct iio_mount_matrix orientation; DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE); struct regmap *map; int irq; diff --git a/include/linux/platform_data/invensense_mpu6050.h b/include/linux/platform_data/invensense_mpu6050.h index ad3aa7b95f35..554b59801aa8 100644 --- a/include/linux/platform_data/invensense_mpu6050.h +++ b/include/linux/platform_data/invensense_mpu6050.h @@ -16,13 +16,16 @@ /** * struct inv_mpu6050_platform_data - Platform data for the mpu driver - * @orientation: Orientation matrix of the chip + * @orientation: Orientation matrix of the chip (deprecated in favor of + * mounting matrix retrieved from device-tree) * * Contains platform specific information on how to configure the MPU6050 to * work on this platform. The orientation matricies are 3x3 rotation matricies * that are applied to the data to rotate from the mounting orientation to the * platform orientation. The values must be one of 0, 1, or -1 and each row and * column should have exactly 1 non-zero value. + * + * Deprecated in favor of mounting matrix retrieved from device-tree. */ struct inv_mpu6050_platform_data { __s8 orientation[9]; -- GitLab From f21122593d99c7e051891da1b148c771b7d56e07 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Apr 2016 13:04:14 +0300 Subject: [PATCH 4051/9938] iio: light: apds9960: silence uninitialized variable warning It causes a static checker warning if we use "buf" on the failure path so move that inside the if statement. Signed-off-by: Dan Carpenter Signed-off-by: Jonathan Cameron --- drivers/iio/light/apds9960.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index 47fcd5ad4ff2..35928fb1b66a 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -495,9 +495,10 @@ static int apds9960_read_raw(struct iio_dev *indio_dev, case IIO_INTENSITY: ret = regmap_bulk_read(data->regmap, chan->address, &buf, 2); - if (!ret) + if (!ret) { ret = IIO_VAL_INT; - *val = le16_to_cpu(buf); + *val = le16_to_cpu(buf); + } break; default: ret = -EINVAL; -- GitLab From 41c128cb25cee72be66397fae8ceb8dc0c2c6984 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Tue, 19 Apr 2016 15:02:11 +0300 Subject: [PATCH 4052/9938] iio: st_gyro: Add lsm9ds0-gyro support This device has an identical interface to other supported sensors and the patch only adds IDs. Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/st-sensors.txt | 1 + drivers/iio/gyro/Kconfig | 2 +- drivers/iio/gyro/st_gyro.h | 1 + drivers/iio/gyro/st_gyro_core.c | 1 + drivers/iio/gyro/st_gyro_i2c.c | 5 +++++ drivers/iio/gyro/st_gyro_spi.c | 1 + 6 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt index 637e283f4a8b..5844cf72862d 100644 --- a/Documentation/devicetree/bindings/iio/st-sensors.txt +++ b/Documentation/devicetree/bindings/iio/st-sensors.txt @@ -51,6 +51,7 @@ Gyroscopes: - st,l3gd20-gyro - st,l3g4is-gyro - st,lsm330-gyro +- st,lsm9ds0-gyro Magnetometers: - st,lsm303agr-magn diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index e816d29d6a62..205a84420ae9 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -93,7 +93,7 @@ config IIO_ST_GYRO_3AXIS select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) help Say yes here to build support for STMicroelectronics gyroscopes: - L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330. + L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330, LSM9DS0. This driver can also be built as a module. If so, these modules will be created: diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index 5353d6328c54..a5c5c4e29add 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -21,6 +21,7 @@ #define L3GD20_GYRO_DEV_NAME "l3gd20" #define L3G4IS_GYRO_DEV_NAME "l3g4is_ui" #define LSM330_GYRO_DEV_NAME "lsm330_gyro" +#define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" /** * struct st_sensors_platform_data - gyro platform data diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index be9057e89dc3..52a3c87c375c 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -204,6 +204,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { [2] = LSM330DLC_GYRO_DEV_NAME, [3] = L3G4IS_GYRO_DEV_NAME, [4] = LSM330_GYRO_DEV_NAME, + [5] = LSM9DS0_GYRO_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 6848451f817a..40056b821036 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -48,6 +48,10 @@ static const struct of_device_id st_gyro_of_match[] = { .compatible = "st,lsm330-gyro", .data = LSM330_GYRO_DEV_NAME, }, + { + .compatible = "st,lsm9ds0-gyro", + .data = LSM9DS0_GYRO_DEV_NAME, + }, {}, }; MODULE_DEVICE_TABLE(of, st_gyro_of_match); @@ -93,6 +97,7 @@ static const struct i2c_device_id st_gyro_id_table[] = { { L3GD20_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, + { LSM9DS0_GYRO_DEV_NAME }, {}, }; MODULE_DEVICE_TABLE(i2c, st_gyro_id_table); diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index d2b7a5fa344c..fbf2faed501c 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -54,6 +54,7 @@ static const struct spi_device_id st_gyro_id_table[] = { { L3GD20_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, + { LSM9DS0_GYRO_DEV_NAME }, {}, }; MODULE_DEVICE_TABLE(spi, st_gyro_id_table); -- GitLab From 11a99573079e15f11499ae8d21b07e3e3257fff1 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:16 +0200 Subject: [PATCH 4053/9938] libnl: fix help of _64bit functions Fix typo and describe 'padattr'. Fixes: 089bf1a6a924 ("libnl: add more helpers to align attributes on 64-bit") Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- lib/nlattr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/nlattr.c b/lib/nlattr.c index 2b82f1e2ebc2..fce1e9afc6d9 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -359,10 +359,11 @@ EXPORT_SYMBOL(__nla_reserve); * @skb: socket buffer to reserve room on * @attrtype: attribute type * @attrlen: length of attribute payload + * @padattr: attribute type for the padding * * Adds a netlink attribute header to a socket buffer and reserves * room for the payload but does not copy it. It also ensure that this - * attribute will be 64-bit aign. + * attribute will have a 64-bit aligned nla_data() area. * * The caller is responsible to ensure that the skb provides enough * tailroom for the attribute header and payload. @@ -424,10 +425,11 @@ EXPORT_SYMBOL(nla_reserve); * @skb: socket buffer to reserve room on * @attrtype: attribute type * @attrlen: length of attribute payload + * @padattr: attribute type for the padding * * Adds a netlink attribute header to a socket buffer and reserves * room for the payload but does not copy it. It also ensure that this - * attribute will be 64-bit aign. + * attribute will have a 64-bit aligned nla_data() area. * * Returns NULL if the tailroom of the skb is insufficient to store * the attribute header and payload. @@ -493,6 +495,7 @@ EXPORT_SYMBOL(__nla_put); * @attrtype: attribute type * @attrlen: length of attribute payload * @data: head of attribute payload + * @padattr: attribute type for the padding * * The caller is responsible to ensure that the skb provides enough * tailroom for the attribute header and payload. @@ -551,6 +554,7 @@ EXPORT_SYMBOL(nla_put); * @attrtype: attribute type * @attrlen: length of attribute payload * @data: head of attribute payload + * @padattr: attribute type for the padding * * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store * the attribute header and payload. -- GitLab From e7479122befd7026cf0fb3b3740f17ebd9c64d35 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:17 +0200 Subject: [PATCH 4054/9938] libnl: nla_put_le64(): align on a 64-bit area nla_data() is now aligned on a 64-bit area. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/netlink.h | 8 +++++--- include/net/nl802154.h | 6 ++++++ net/ieee802154/nl802154.c | 13 ++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 6f51a8a06498..7f6b99483ab7 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -878,14 +878,16 @@ static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value) } /** - * nla_put_le64 - Add a __le64 netlink attribute to a socket buffer + * nla_put_le64 - Add a __le64 netlink attribute to a socket buffer and align it * @skb: socket buffer to add attribute to * @attrtype: attribute type * @value: numeric value + * @padattr: attribute type for the padding */ -static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value) +static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value, + int padattr) { - return nla_put(skb, attrtype, sizeof(__le64), &value); + return nla_put_64bit(skb, attrtype, sizeof(__le64), &value, padattr); } /** diff --git a/include/net/nl802154.h b/include/net/nl802154.h index 32cb3e591e07..fcab4de49951 100644 --- a/include/net/nl802154.h +++ b/include/net/nl802154.h @@ -138,6 +138,8 @@ enum nl802154_attrs { NL802154_ATTR_SEC_KEY, #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ + NL802154_ATTR_PAD, + __NL802154_ATTR_AFTER_LAST, NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1 }; @@ -295,6 +297,7 @@ enum nl802154_dev_addr_attrs { NL802154_DEV_ADDR_ATTR_MODE, NL802154_DEV_ADDR_ATTR_SHORT, NL802154_DEV_ADDR_ATTR_EXTENDED, + NL802154_DEV_ADDR_ATTR_PAD, /* keep last */ __NL802154_DEV_ADDR_ATTR_AFTER_LAST, @@ -320,6 +323,7 @@ enum nl802154_key_id_attrs { NL802154_KEY_ID_ATTR_IMPLICIT, NL802154_KEY_ID_ATTR_SOURCE_SHORT, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, + NL802154_KEY_ID_ATTR_PAD, /* keep last */ __NL802154_KEY_ID_ATTR_AFTER_LAST, @@ -402,6 +406,7 @@ enum nl802154_dev { NL802154_DEV_ATTR_EXTENDED_ADDR, NL802154_DEV_ATTR_SECLEVEL_EXEMPT, NL802154_DEV_ATTR_KEY_MODE, + NL802154_DEV_ATTR_PAD, /* keep last */ __NL802154_DEV_ATTR_AFTER_LAST, @@ -414,6 +419,7 @@ enum nl802154_devkey { NL802154_DEVKEY_ATTR_FRAME_COUNTER, NL802154_DEVKEY_ATTR_EXTENDED_ADDR, NL802154_DEVKEY_ATTR_ID, + NL802154_DEVKEY_ATTR_PAD, /* keep last */ __NL802154_DEVKEY_ATTR_AFTER_LAST, diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 16ef0d9f566e..614072064d03 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -722,7 +722,8 @@ ieee802154_llsec_send_key_id(struct sk_buff *msg, break; case NL802154_DEV_ADDR_EXTENDED: if (nla_put_le64(msg, NL802154_DEV_ADDR_ATTR_EXTENDED, - desc->device_addr.extended_addr)) + desc->device_addr.extended_addr, + NL802154_DEV_ADDR_ATTR_PAD)) return -ENOBUFS; break; default: @@ -742,7 +743,8 @@ ieee802154_llsec_send_key_id(struct sk_buff *msg, break; case NL802154_KEY_ID_MODE_INDEX_EXTENDED: if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, - desc->extended_source)) + desc->extended_source, + NL802154_KEY_ID_ATTR_PAD)) return -ENOBUFS; break; default: @@ -819,7 +821,8 @@ nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, /* address settings */ if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR, - wpan_dev->extended_addr) || + wpan_dev->extended_addr, + NL802154_ATTR_PAD) || nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR, wpan_dev->short_addr) || nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id)) @@ -1614,7 +1617,7 @@ static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid, nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR, dev_desc->short_addr) || nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR, - dev_desc->hwaddr) || + dev_desc->hwaddr, NL802154_DEV_ATTR_PAD) || nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT, dev_desc->seclevel_exempt) || nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode)) @@ -1778,7 +1781,7 @@ static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid, goto nla_put_failure; if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR, - extended_addr) || + extended_addr, NL802154_DEVKEY_ATTR_PAD) || nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER, devkey->frame_counter)) goto nla_put_failure; -- GitLab From b46f6ded906ef0be52a4881ba50a084aeca64d7e Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:18 +0200 Subject: [PATCH 4055/9938] libnl: nla_put_be64(): align on a 64-bit area nla_data() is now aligned on a 64-bit area. A temporary version (nla_put_be64_32bit()) is added for nla_put_net64(). This function is removed in the next patch. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/netlink.h | 15 ++++++++---- include/uapi/linux/fib_rules.h | 1 + include/uapi/linux/lwtunnel.h | 2 ++ include/uapi/linux/netfilter/nf_tables.h | 8 +++++++ include/uapi/linux/netfilter/nfnetlink_acct.h | 1 + .../linux/netfilter/nfnetlink_conntrack.h | 3 +++ include/uapi/linux/openvswitch.h | 1 + net/core/fib_rules.c | 4 ++-- net/ipv4/ip_tunnel_core.c | 10 ++++---- net/netfilter/nf_conntrack_netlink.c | 18 ++++++++------ net/netfilter/nf_conntrack_proto_dccp.c | 4 +++- net/netfilter/nf_tables_api.c | 24 ++++++++++++------- net/netfilter/nf_tables_trace.c | 5 ++-- net/netfilter/nfnetlink_acct.c | 9 ++++--- net/netfilter/nft_counter.c | 6 +++-- net/netfilter/nft_dynset.c | 3 ++- net/netfilter/nft_limit.c | 6 +++-- net/openvswitch/flow_netlink.c | 5 ++-- 18 files changed, 87 insertions(+), 38 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 7f6b99483ab7..47d7d1356fa3 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -856,16 +856,23 @@ static inline int nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) } /** - * nla_put_be64 - Add a __be64 netlink attribute to a socket buffer + * nla_put_be64 - Add a __be64 netlink attribute to a socket buffer and align it * @skb: socket buffer to add attribute to * @attrtype: attribute type * @value: numeric value + * @padattr: attribute type for the padding */ -static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value) +static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value, + int padattr) { - return nla_put(skb, attrtype, sizeof(__be64), &value); + return nla_put_64bit(skb, attrtype, sizeof(__be64), &value, padattr); } +static inline int nla_put_be64_32bit(struct sk_buff *skb, int attrtype, + __be64 value) +{ + return nla_put(skb, attrtype, sizeof(__be64), &value); +} /** * nla_put_net64 - Add 64-bit network byte order netlink attribute to a socket buffer * @skb: socket buffer to add attribute to @@ -874,7 +881,7 @@ static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value) */ static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value) { - return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, value); + return nla_put_be64_32bit(skb, attrtype | NLA_F_NET_BYTEORDER, value); } /** diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h index 96161b8202b5..620c8a5ddc00 100644 --- a/include/uapi/linux/fib_rules.h +++ b/include/uapi/linux/fib_rules.h @@ -49,6 +49,7 @@ enum { FRA_TABLE, /* Extended table id */ FRA_FWMASK, /* mask for netfilter mark */ FRA_OIFNAME, + FRA_PAD, __FRA_MAX }; diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h index f8b01887a495..a478fe80e203 100644 --- a/include/uapi/linux/lwtunnel.h +++ b/include/uapi/linux/lwtunnel.h @@ -22,6 +22,7 @@ enum lwtunnel_ip_t { LWTUNNEL_IP_TTL, LWTUNNEL_IP_TOS, LWTUNNEL_IP_FLAGS, + LWTUNNEL_IP_PAD, __LWTUNNEL_IP_MAX, }; @@ -35,6 +36,7 @@ enum lwtunnel_ip6_t { LWTUNNEL_IP6_HOPLIMIT, LWTUNNEL_IP6_TC, LWTUNNEL_IP6_FLAGS, + LWTUNNEL_IP6_PAD, __LWTUNNEL_IP6_MAX, }; diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index eeffde196f80..660231363bb5 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -182,6 +182,7 @@ enum nft_chain_attributes { NFTA_CHAIN_USE, NFTA_CHAIN_TYPE, NFTA_CHAIN_COUNTERS, + NFTA_CHAIN_PAD, __NFTA_CHAIN_MAX }; #define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1) @@ -206,6 +207,7 @@ enum nft_rule_attributes { NFTA_RULE_COMPAT, NFTA_RULE_POSITION, NFTA_RULE_USERDATA, + NFTA_RULE_PAD, __NFTA_RULE_MAX }; #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) @@ -308,6 +310,7 @@ enum nft_set_attributes { NFTA_SET_TIMEOUT, NFTA_SET_GC_INTERVAL, NFTA_SET_USERDATA, + NFTA_SET_PAD, __NFTA_SET_MAX }; #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) @@ -341,6 +344,7 @@ enum nft_set_elem_attributes { NFTA_SET_ELEM_EXPIRATION, NFTA_SET_ELEM_USERDATA, NFTA_SET_ELEM_EXPR, + NFTA_SET_ELEM_PAD, __NFTA_SET_ELEM_MAX }; #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) @@ -584,6 +588,7 @@ enum nft_dynset_attributes { NFTA_DYNSET_SREG_DATA, NFTA_DYNSET_TIMEOUT, NFTA_DYNSET_EXPR, + NFTA_DYNSET_PAD, __NFTA_DYNSET_MAX, }; #define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1) @@ -806,6 +811,7 @@ enum nft_limit_attributes { NFTA_LIMIT_BURST, NFTA_LIMIT_TYPE, NFTA_LIMIT_FLAGS, + NFTA_LIMIT_PAD, __NFTA_LIMIT_MAX }; #define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1) @@ -820,6 +826,7 @@ enum nft_counter_attributes { NFTA_COUNTER_UNSPEC, NFTA_COUNTER_BYTES, NFTA_COUNTER_PACKETS, + NFTA_COUNTER_PAD, __NFTA_COUNTER_MAX }; #define NFTA_COUNTER_MAX (__NFTA_COUNTER_MAX - 1) @@ -1055,6 +1062,7 @@ enum nft_trace_attibutes { NFTA_TRACE_MARK, NFTA_TRACE_NFPROTO, NFTA_TRACE_POLICY, + NFTA_TRACE_PAD, __NFTA_TRACE_MAX }; #define NFTA_TRACE_MAX (__NFTA_TRACE_MAX - 1) diff --git a/include/uapi/linux/netfilter/nfnetlink_acct.h b/include/uapi/linux/netfilter/nfnetlink_acct.h index f3e34dbbf966..36047ec70f37 100644 --- a/include/uapi/linux/netfilter/nfnetlink_acct.h +++ b/include/uapi/linux/netfilter/nfnetlink_acct.h @@ -29,6 +29,7 @@ enum nfnl_acct_type { NFACCT_FLAGS, NFACCT_QUOTA, NFACCT_FILTER, + NFACCT_PAD, __NFACCT_MAX }; #define NFACCT_MAX (__NFACCT_MAX - 1) diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h index c1a4e1441a25..9df789709abe 100644 --- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h +++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h @@ -116,6 +116,7 @@ enum ctattr_protoinfo_dccp { CTA_PROTOINFO_DCCP_STATE, CTA_PROTOINFO_DCCP_ROLE, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + CTA_PROTOINFO_DCCP_PAD, __CTA_PROTOINFO_DCCP_MAX, }; #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) @@ -135,6 +136,7 @@ enum ctattr_counters { CTA_COUNTERS_BYTES, /* 64bit counters */ CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ + CTA_COUNTERS_PAD, __CTA_COUNTERS_MAX }; #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) @@ -143,6 +145,7 @@ enum ctattr_tstamp { CTA_TIMESTAMP_UNSPEC, CTA_TIMESTAMP_START, CTA_TIMESTAMP_STOP, + CTA_TIMESTAMP_PAD, __CTA_TIMESTAMP_MAX }; #define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1) diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index 616d04761730..0358f94af86e 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -351,6 +351,7 @@ enum ovs_tunnel_key_attr { OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS, /* Nested OVS_VXLAN_EXT_* */ OVS_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ + OVS_TUNNEL_KEY_ATTR_PAD, __OVS_TUNNEL_KEY_ATTR_MAX }; diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 365de66436ac..840acebbb80c 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -549,7 +549,7 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops, + nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */ + nla_total_size(4) /* FRA_FWMARK */ + nla_total_size(4) /* FRA_FWMASK */ - + nla_total_size(8); /* FRA_TUN_ID */ + + nla_total_size_64bit(8); /* FRA_TUN_ID */ if (ops->nlmsg_payload) payload += ops->nlmsg_payload(rule); @@ -607,7 +607,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, (rule->target && nla_put_u32(skb, FRA_GOTO, rule->target)) || (rule->tun_id && - nla_put_be64(skb, FRA_TUN_ID, rule->tun_id))) + nla_put_be64(skb, FRA_TUN_ID, rule->tun_id, FRA_PAD))) goto nla_put_failure; if (rule->suppress_ifgroup != -1) { diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index f46c5c873831..786fa7ca28e0 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -271,7 +271,8 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb, { struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate); - if (nla_put_be64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id) || + if (nla_put_be64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id, + LWTUNNEL_IP_PAD) || nla_put_in_addr(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) || nla_put_in_addr(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) || nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.tos) || @@ -284,7 +285,7 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb, static int ip_tun_encap_nlsize(struct lwtunnel_state *lwtstate) { - return nla_total_size(8) /* LWTUNNEL_IP_ID */ + return nla_total_size_64bit(8) /* LWTUNNEL_IP_ID */ + nla_total_size(4) /* LWTUNNEL_IP_DST */ + nla_total_size(4) /* LWTUNNEL_IP_SRC */ + nla_total_size(1) /* LWTUNNEL_IP_TOS */ @@ -366,7 +367,8 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb, { struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate); - if (nla_put_be64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id) || + if (nla_put_be64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id, + LWTUNNEL_IP6_PAD) || nla_put_in6_addr(skb, LWTUNNEL_IP6_DST, &tun_info->key.u.ipv6.dst) || nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, &tun_info->key.u.ipv6.src) || nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.tos) || @@ -379,7 +381,7 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb, static int ip6_tun_encap_nlsize(struct lwtunnel_state *lwtstate) { - return nla_total_size(8) /* LWTUNNEL_IP6_ID */ + return nla_total_size_64bit(8) /* LWTUNNEL_IP6_ID */ + nla_total_size(16) /* LWTUNNEL_IP6_DST */ + nla_total_size(16) /* LWTUNNEL_IP6_SRC */ + nla_total_size(1) /* LWTUNNEL_IP6_HOPLIMIT */ diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 355e8552fd5b..3362d65f3285 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -245,8 +245,10 @@ dump_counters(struct sk_buff *skb, struct nf_conn_acct *acct, if (!nest_count) goto nla_put_failure; - if (nla_put_be64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts)) || - nla_put_be64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes))) + if (nla_put_be64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts), + CTA_COUNTERS_PAD) || + nla_put_be64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes), + CTA_COUNTERS_PAD)) goto nla_put_failure; nla_nest_end(skb, nest_count); @@ -287,9 +289,11 @@ ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) if (!nest_count) goto nla_put_failure; - if (nla_put_be64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start)) || + if (nla_put_be64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start), + CTA_TIMESTAMP_PAD) || (tstamp->stop != 0 && nla_put_be64(skb, CTA_TIMESTAMP_STOP, - cpu_to_be64(tstamp->stop)))) + cpu_to_be64(tstamp->stop), + CTA_TIMESTAMP_PAD))) goto nla_put_failure; nla_nest_end(skb, nest_count); @@ -562,8 +566,8 @@ ctnetlink_acct_size(const struct nf_conn *ct) if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT)) return 0; return 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ - + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */ - + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */ + + 2 * nla_total_size_64bit(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */ + + 2 * nla_total_size_64bit(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */ ; } @@ -590,7 +594,7 @@ ctnetlink_timestamp_size(const struct nf_conn *ct) #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP)) return 0; - return nla_total_size(0) + 2 * nla_total_size(sizeof(uint64_t)); + return nla_total_size(0) + 2 * nla_total_size_64bit(sizeof(uint64_t)); #else return 0; #endif diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index fce1b1cca32d..399a38fd685a 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -645,7 +645,8 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, nla_put_u8(skb, CTA_PROTOINFO_DCCP_ROLE, ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]) || nla_put_be64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, - cpu_to_be64(ct->proto.dccp.handshake_seq))) + cpu_to_be64(ct->proto.dccp.handshake_seq), + CTA_PROTOINFO_DCCP_PAD)) goto nla_put_failure; nla_nest_end(skb, nest_parms); spin_unlock_bh(&ct->lock); @@ -660,6 +661,7 @@ static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 }, [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 }, [CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ] = { .type = NLA_U64 }, + [CTA_PROTOINFO_DCCP_PAD] = { .type = NLA_UNSPEC }, }; static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 2011977cd79d..7a85a9dd37ad 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -944,8 +944,10 @@ static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats) if (nest == NULL) goto nla_put_failure; - if (nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.pkts)) || - nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes))) + if (nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.pkts), + NFTA_COUNTER_PAD) || + nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes), + NFTA_COUNTER_PAD)) goto nla_put_failure; nla_nest_end(skb, nest); @@ -975,7 +977,8 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name)) goto nla_put_failure; - if (nla_put_be64(skb, NFTA_CHAIN_HANDLE, cpu_to_be64(chain->handle))) + if (nla_put_be64(skb, NFTA_CHAIN_HANDLE, cpu_to_be64(chain->handle), + NFTA_CHAIN_PAD)) goto nla_put_failure; if (nla_put_string(skb, NFTA_CHAIN_NAME, chain->name)) goto nla_put_failure; @@ -1803,13 +1806,15 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net, goto nla_put_failure; if (nla_put_string(skb, NFTA_RULE_CHAIN, chain->name)) goto nla_put_failure; - if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle))) + if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle), + NFTA_RULE_PAD)) goto nla_put_failure; if ((event != NFT_MSG_DELRULE) && (rule->list.prev != &chain->rules)) { prule = list_entry(rule->list.prev, struct nft_rule, list); if (nla_put_be64(skb, NFTA_RULE_POSITION, - cpu_to_be64(prule->handle))) + cpu_to_be64(prule->handle), + NFTA_RULE_PAD)) goto nla_put_failure; } @@ -2473,7 +2478,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, } if (set->timeout && - nla_put_be64(skb, NFTA_SET_TIMEOUT, cpu_to_be64(set->timeout))) + nla_put_be64(skb, NFTA_SET_TIMEOUT, cpu_to_be64(set->timeout), + NFTA_SET_PAD)) goto nla_put_failure; if (set->gc_int && nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int))) @@ -3076,7 +3082,8 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) && nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT, - cpu_to_be64(*nft_set_ext_timeout(ext)))) + cpu_to_be64(*nft_set_ext_timeout(ext)), + NFTA_SET_ELEM_PAD)) goto nla_put_failure; if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { @@ -3089,7 +3096,8 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, expires = 0; if (nla_put_be64(skb, NFTA_SET_ELEM_EXPIRATION, - cpu_to_be64(jiffies_to_msecs(expires)))) + cpu_to_be64(jiffies_to_msecs(expires)), + NFTA_SET_ELEM_PAD)) goto nla_put_failure; } diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c index e9e959f65d91..39eb1cc62e91 100644 --- a/net/netfilter/nf_tables_trace.c +++ b/net/netfilter/nf_tables_trace.c @@ -156,7 +156,8 @@ static int nf_trace_fill_rule_info(struct sk_buff *nlskb, return 0; return nla_put_be64(nlskb, NFTA_TRACE_RULE_HANDLE, - cpu_to_be64(info->rule->handle)); + cpu_to_be64(info->rule->handle), + NFTA_TRACE_PAD); } void nft_trace_notify(struct nft_traceinfo *info) @@ -174,7 +175,7 @@ void nft_trace_notify(struct nft_traceinfo *info) size = nlmsg_total_size(sizeof(struct nfgenmsg)) + nla_total_size(NFT_TABLE_MAXNAMELEN) + nla_total_size(NFT_CHAIN_MAXNAMELEN) + - nla_total_size(sizeof(__be64)) + /* rule handle */ + nla_total_size_64bit(sizeof(__be64)) + /* rule handle */ nla_total_size(sizeof(__be32)) + /* trace type */ nla_total_size(0) + /* VERDICT, nested */ nla_total_size(sizeof(u32)) + /* verdict code */ diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index 4c2b4c0c4d5f..d016066a25e3 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c @@ -160,15 +160,18 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, pkts = atomic64_read(&acct->pkts); bytes = atomic64_read(&acct->bytes); } - if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts)) || - nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes)) || + if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts), + NFACCT_PAD) || + nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes), + NFACCT_PAD) || nla_put_be32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt)))) goto nla_put_failure; if (acct->flags & NFACCT_F_QUOTA) { u64 *quota = (u64 *)acct->data; if (nla_put_be32(skb, NFACCT_FLAGS, htonl(old_flags)) || - nla_put_be64(skb, NFACCT_QUOTA, cpu_to_be64(*quota))) + nla_put_be64(skb, NFACCT_QUOTA, cpu_to_be64(*quota), + NFACCT_PAD)) goto nla_put_failure; } nlmsg_end(skb, nlh); diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c index c9743f78f219..77db8358ab14 100644 --- a/net/netfilter/nft_counter.c +++ b/net/netfilter/nft_counter.c @@ -76,8 +76,10 @@ static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr) nft_counter_fetch(priv->counter, &total); - if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes)) || - nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.packets))) + if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes), + NFTA_COUNTER_PAD) || + nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.packets), + NFTA_COUNTER_PAD)) goto nla_put_failure; return 0; diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index 9dec3bd1b63c..78d4914fb39c 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c @@ -227,7 +227,8 @@ static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr) goto nla_put_failure; if (nla_put_string(skb, NFTA_DYNSET_SET_NAME, priv->set->name)) goto nla_put_failure; - if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout))) + if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout), + NFTA_DYNSET_PAD)) goto nla_put_failure; if (priv->expr && nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr)) goto nla_put_failure; diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c index 99d18578afc6..070b98938e02 100644 --- a/net/netfilter/nft_limit.c +++ b/net/netfilter/nft_limit.c @@ -97,8 +97,10 @@ static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit, u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC); u64 rate = limit->rate - limit->burst; - if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) || - nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) || + if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate), + NFTA_LIMIT_PAD) || + nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs), + NFTA_LIMIT_PAD) || nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) || nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)) || nla_put_be32(skb, NFTA_LIMIT_FLAGS, htonl(flags))) diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 689c17264221..0bb650f4f219 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c @@ -261,7 +261,7 @@ size_t ovs_tun_key_attr_size(void) /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider * updating this function. */ - return nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */ + return nla_total_size_64bit(8) /* OVS_TUNNEL_KEY_ATTR_ID */ + nla_total_size(16) /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */ + nla_total_size(16) /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */ + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */ @@ -720,7 +720,8 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, unsigned short tun_proto) { if (output->tun_flags & TUNNEL_KEY && - nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id)) + nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id, + OVS_TUNNEL_KEY_ATTR_PAD)) return -EMSGSIZE; switch (tun_proto) { case AF_INET: -- GitLab From e9bbe898cbe89b17ad3993c136aa13d0431cd537 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:19 +0200 Subject: [PATCH 4056/9938] libnl: nla_put_net64(): align on a 64-bit area nla_data() is now aligned on a 64-bit area. The temporary function nla_put_be64_32bit() is removed in this patch. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/linux/netfilter/ipset/ip_set.h | 9 ++++++--- include/net/netlink.h | 14 ++++++-------- include/uapi/linux/netfilter/ipset/ip_set.h | 1 + 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index f48b8a664b0f..83b9a2e0d8d4 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -351,7 +351,8 @@ ip_set_put_skbinfo(struct sk_buff *skb, struct ip_set_skbinfo *skbinfo) return ((skbinfo->skbmark || skbinfo->skbmarkmask) && nla_put_net64(skb, IPSET_ATTR_SKBMARK, cpu_to_be64((u64)skbinfo->skbmark << 32 | - skbinfo->skbmarkmask))) || + skbinfo->skbmarkmask), + IPSET_ATTR_PAD)) || (skbinfo->skbprio && nla_put_net32(skb, IPSET_ATTR_SKBPRIO, cpu_to_be32(skbinfo->skbprio))) || @@ -374,9 +375,11 @@ static inline bool ip_set_put_counter(struct sk_buff *skb, struct ip_set_counter *counter) { return nla_put_net64(skb, IPSET_ATTR_BYTES, - cpu_to_be64(ip_set_get_bytes(counter))) || + cpu_to_be64(ip_set_get_bytes(counter)), + IPSET_ATTR_PAD) || nla_put_net64(skb, IPSET_ATTR_PACKETS, - cpu_to_be64(ip_set_get_packets(counter))); + cpu_to_be64(ip_set_get_packets(counter)), + IPSET_ATTR_PAD); } static inline void diff --git a/include/net/netlink.h b/include/net/netlink.h index 47d7d1356fa3..066a921e7cbe 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -868,20 +868,18 @@ static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value, return nla_put_64bit(skb, attrtype, sizeof(__be64), &value, padattr); } -static inline int nla_put_be64_32bit(struct sk_buff *skb, int attrtype, - __be64 value) -{ - return nla_put(skb, attrtype, sizeof(__be64), &value); -} /** - * nla_put_net64 - Add 64-bit network byte order netlink attribute to a socket buffer + * nla_put_net64 - Add 64-bit network byte order nlattr to a skb and align it * @skb: socket buffer to add attribute to * @attrtype: attribute type * @value: numeric value + * @padattr: attribute type for the padding */ -static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value) +static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value, + int padattr) { - return nla_put_be64_32bit(skb, attrtype | NLA_F_NET_BYTEORDER, value); + return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, value, + padattr); } /** diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h index 63b2e34f1b60..ebb5154976de 100644 --- a/include/uapi/linux/netfilter/ipset/ip_set.h +++ b/include/uapi/linux/netfilter/ipset/ip_set.h @@ -118,6 +118,7 @@ enum { IPSET_ATTR_SKBMARK, IPSET_ATTR_SKBPRIO, IPSET_ATTR_SKBQUEUE, + IPSET_ATTR_PAD, __IPSET_ATTR_ADT_MAX, }; #define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1) -- GitLab From 756a2f59b73cd6ed8afae3f6e8efb3fb829e4600 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:20 +0200 Subject: [PATCH 4057/9938] libnl: nla_put_s64(): align on a 64-bit area nla_data() is now aligned on a 64-bit area. In fact, there is no user of this function. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/netlink.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 066a921e7cbe..074215a59d19 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -102,7 +102,8 @@ * nla_put_s8(skb, type, value) add s8 attribute to skb * nla_put_s16(skb, type, value) add s16 attribute to skb * nla_put_s32(skb, type, value) add s32 attribute to skb - * nla_put_s64(skb, type, value) add s64 attribute to skb + * nla_put_s64(skb, type, value, + * padattr) add s64 attribute to skb * nla_put_string(skb, type, str) add string attribute to skb * nla_put_flag(skb, type) add flag attribute to skb * nla_put_msecs(skb, type, jiffies) add msecs attribute to skb @@ -929,14 +930,16 @@ static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) } /** - * nla_put_s64 - Add a s64 netlink attribute to a socket buffer + * nla_put_s64 - Add a s64 netlink attribute to a socket buffer and align it * @skb: socket buffer to add attribute to * @attrtype: attribute type * @value: numeric value + * @padattr: attribute type for the padding */ -static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value) +static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value, + int padattr) { - return nla_put(skb, attrtype, sizeof(s64), &value); + return nla_put_64bit(skb, attrtype, sizeof(s64), &value, padattr); } /** -- GitLab From 2175d87cc3561c02e605bc8ac81ee5d875a51b9e Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:21 +0200 Subject: [PATCH 4058/9938] libnl: nla_put_msecs(): align on a 64-bit area nla_data() is now aligned on a 64-bit area. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/netlink.h | 11 +++++++---- include/uapi/linux/l2tp.h | 1 + include/uapi/linux/neighbour.h | 2 ++ include/uapi/linux/tcp_metrics.h | 1 + net/core/neighbour.c | 19 ++++++++++--------- net/ipv4/tcp_metrics.c | 6 ++++-- net/l2tp/l2tp_netlink.c | 3 ++- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 074215a59d19..113b483b6ee8 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -106,7 +106,8 @@ * padattr) add s64 attribute to skb * nla_put_string(skb, type, str) add string attribute to skb * nla_put_flag(skb, type) add flag attribute to skb - * nla_put_msecs(skb, type, jiffies) add msecs attribute to skb + * nla_put_msecs(skb, type, jiffies, + * padattr) add msecs attribute to skb * nla_put_in_addr(skb, type, addr) add IPv4 address attribute to skb * nla_put_in6_addr(skb, type, addr) add IPv6 address attribute to skb * @@ -965,16 +966,18 @@ static inline int nla_put_flag(struct sk_buff *skb, int attrtype) } /** - * nla_put_msecs - Add a msecs netlink attribute to a socket buffer + * nla_put_msecs - Add a msecs netlink attribute to a skb and align it * @skb: socket buffer to add attribute to * @attrtype: attribute type * @njiffies: number of jiffies to convert to msecs + * @padattr: attribute type for the padding */ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, - unsigned long njiffies) + unsigned long njiffies, int padattr) { u64 tmp = jiffies_to_msecs(njiffies); - return nla_put(skb, attrtype, sizeof(u64), &tmp); + + return nla_put_64bit(skb, attrtype, sizeof(u64), &tmp, padattr); } /** diff --git a/include/uapi/linux/l2tp.h b/include/uapi/linux/l2tp.h index 347ef22a964e..3386a99e0397 100644 --- a/include/uapi/linux/l2tp.h +++ b/include/uapi/linux/l2tp.h @@ -126,6 +126,7 @@ enum { L2TP_ATTR_IP6_DADDR, /* struct in6_addr */ L2TP_ATTR_UDP_ZERO_CSUM6_TX, /* u8 */ L2TP_ATTR_UDP_ZERO_CSUM6_RX, /* u8 */ + L2TP_ATTR_PAD, __L2TP_ATTR_MAX, }; diff --git a/include/uapi/linux/neighbour.h b/include/uapi/linux/neighbour.h index 788655bfa0f3..bd99a8d80f36 100644 --- a/include/uapi/linux/neighbour.h +++ b/include/uapi/linux/neighbour.h @@ -128,6 +128,7 @@ enum { NDTPA_LOCKTIME, /* u64, msecs */ NDTPA_QUEUE_LENBYTES, /* u32 */ NDTPA_MCAST_REPROBES, /* u32 */ + NDTPA_PAD, __NDTPA_MAX }; #define NDTPA_MAX (__NDTPA_MAX - 1) @@ -160,6 +161,7 @@ enum { NDTA_PARMS, /* nested TLV NDTPA_* */ NDTA_STATS, /* struct ndt_stats, read-only */ NDTA_GC_INTERVAL, /* u64, msecs */ + NDTA_PAD, __NDTA_MAX }; #define NDTA_MAX (__NDTA_MAX - 1) diff --git a/include/uapi/linux/tcp_metrics.h b/include/uapi/linux/tcp_metrics.h index 93533926035c..80ad90d0cfc2 100644 --- a/include/uapi/linux/tcp_metrics.h +++ b/include/uapi/linux/tcp_metrics.h @@ -40,6 +40,7 @@ enum { TCP_METRICS_ATTR_FOPEN_COOKIE, /* binary */ TCP_METRICS_ATTR_SADDR_IPV4, /* u32 */ TCP_METRICS_ATTR_SADDR_IPV6, /* binary */ + TCP_METRICS_ATTR_PAD, __TCP_METRICS_ATTR_MAX, }; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f18ae91b652e..6a395d440228 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1763,21 +1763,22 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms) NEIGH_VAR(parms, MCAST_PROBES)) || nla_put_u32(skb, NDTPA_MCAST_REPROBES, NEIGH_VAR(parms, MCAST_REPROBES)) || - nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) || + nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time, + NDTPA_PAD) || nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME, - NEIGH_VAR(parms, BASE_REACHABLE_TIME)) || + NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) || nla_put_msecs(skb, NDTPA_GC_STALETIME, - NEIGH_VAR(parms, GC_STALETIME)) || + NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) || nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME, - NEIGH_VAR(parms, DELAY_PROBE_TIME)) || + NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) || nla_put_msecs(skb, NDTPA_RETRANS_TIME, - NEIGH_VAR(parms, RETRANS_TIME)) || + NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) || nla_put_msecs(skb, NDTPA_ANYCAST_DELAY, - NEIGH_VAR(parms, ANYCAST_DELAY)) || + NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) || nla_put_msecs(skb, NDTPA_PROXY_DELAY, - NEIGH_VAR(parms, PROXY_DELAY)) || + NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) || nla_put_msecs(skb, NDTPA_LOCKTIME, - NEIGH_VAR(parms, LOCKTIME))) + NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD)) goto nla_put_failure; return nla_nest_end(skb, nest); @@ -1804,7 +1805,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, ndtmsg->ndtm_pad2 = 0; if (nla_put_string(skb, NDTA_NAME, tbl->id) || - nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) || + nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) || nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) || nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) || nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3)) diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 7b7eec439906..b617826e2477 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -800,7 +800,8 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, } if (nla_put_msecs(msg, TCP_METRICS_ATTR_AGE, - jiffies - tm->tcpm_stamp) < 0) + jiffies - tm->tcpm_stamp, + TCP_METRICS_ATTR_PAD) < 0) goto nla_put_failure; if (tm->tcpm_ts_stamp) { if (nla_put_s32(msg, TCP_METRICS_ATTR_TW_TS_STAMP, @@ -864,7 +865,8 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, (nla_put_u16(msg, TCP_METRICS_ATTR_FOPEN_SYN_DROPS, tfom->syn_loss) < 0 || nla_put_msecs(msg, TCP_METRICS_ATTR_FOPEN_SYN_DROP_TS, - jiffies - tfom->last_syn_loss) < 0)) + jiffies - tfom->last_syn_loss, + TCP_METRICS_ATTR_PAD) < 0)) goto nla_put_failure; if (tfom->cookie.len > 0 && nla_put(msg, TCP_METRICS_ATTR_FOPEN_COOKIE, diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 2caaa84ce92d..24ed2e875c45 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -746,7 +746,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl nla_put_u8(skb, L2TP_ATTR_USING_IPSEC, 1)) || #endif (session->reorder_timeout && - nla_put_msecs(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout))) + nla_put_msecs(skb, L2TP_ATTR_RECV_TIMEOUT, + session->reorder_timeout, L2TP_ATTR_PAD))) goto nla_put_failure; nest = nla_nest_start(skb, L2TP_ATTR_STATS); -- GitLab From 73520786b0793c612ef4de3e9addb2ec411bea20 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:22 +0200 Subject: [PATCH 4059/9938] libnl: add nla_put_u64_64bit() helper With this function, nla_data() is aligned on a 64-bit area. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/netlink.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/net/netlink.h b/include/net/netlink.h index 113b483b6ee8..e589cb3dccee 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -857,6 +857,19 @@ static inline int nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) return nla_put(skb, attrtype, sizeof(u64), &value); } +/** + * nla_put_u64_64bit - Add a u64 netlink attribute to a skb and align it + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + * @padattr: attribute type for the padding + */ +static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype, + u64 value, int padattr) +{ + return nla_put_64bit(skb, attrtype, sizeof(u64), &value, padattr); +} + /** * nla_put_be64 - Add a __be64 netlink attribute to a socket buffer and align it * @skb: socket buffer to add attribute to -- GitLab From de95c4a46a6e608444ccaf541087594553c7df11 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:23 +0200 Subject: [PATCH 4060/9938] xfrm: align nlattr properly when needed Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/xfrm.h | 1 + net/xfrm/xfrm_user.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h index 2cd9e608d0d1..143338978b48 100644 --- a/include/uapi/linux/xfrm.h +++ b/include/uapi/linux/xfrm.h @@ -302,6 +302,7 @@ enum xfrm_attr_type_t { XFRMA_SA_EXTRA_FLAGS, /* __u32 */ XFRMA_PROTO, /* __u8 */ XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ + XFRMA_PAD, __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2cc7af858c6f..d516845e16e3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -809,7 +809,8 @@ static int copy_to_user_state_extra(struct xfrm_state *x, goto out; } if (x->lastused) { - ret = nla_put_u64(skb, XFRMA_LASTUSED, x->lastused); + ret = nla_put_u64_64bit(skb, XFRMA_LASTUSED, x->lastused, + XFRMA_PAD); if (ret) goto out; } @@ -1813,7 +1814,7 @@ static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x) return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) + nla_total_size(replay_size) - + nla_total_size(sizeof(struct xfrm_lifetime_cur)) + + nla_total_size_64bit(sizeof(struct xfrm_lifetime_cur)) + nla_total_size(sizeof(struct xfrm_mark)) + nla_total_size(4) /* XFRM_AE_RTHR */ + nla_total_size(4); /* XFRM_AE_ETHR */ @@ -1848,7 +1849,8 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct } if (err) goto out_cancel; - err = nla_put(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); + err = nla_put_64bit(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft, + XFRMA_PAD); if (err) goto out_cancel; @@ -2617,7 +2619,7 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) l += nla_total_size(sizeof(x->props.extra_flags)); /* Must count x->lastused as it may become non-zero behind our back. */ - l += nla_total_size(sizeof(u64)); + l += nla_total_size_64bit(sizeof(u64)); return l; } -- GitLab From 80df554275c21edca22ece02448bdb378c2ee9f1 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 22 Apr 2016 17:31:24 +0200 Subject: [PATCH 4061/9938] taskstats: use the libnl API to align nlattr on 64-bit Goal of this patch is to use the new libnl API to align netlink attribute when needed. The layout of the netlink message will be a bit different after the patch, because the padattr (TASKSTATS_TYPE_STATS) will be inside the nested attribute instead of before it. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- kernel/taskstats.c | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 21f82c29c914..b3f05ee20d18 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -357,10 +357,6 @@ static int parse(struct nlattr *na, struct cpumask *mask) return ret; } -#if defined(CONFIG_64BIT) && !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) -#define TASKSTATS_NEEDS_PADDING 1 -#endif - static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid) { struct nlattr *na, *ret; @@ -370,29 +366,6 @@ static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid) ? TASKSTATS_TYPE_AGGR_PID : TASKSTATS_TYPE_AGGR_TGID; - /* - * The taskstats structure is internally aligned on 8 byte - * boundaries but the layout of the aggregrate reply, with - * two NLA headers and the pid (each 4 bytes), actually - * force the entire structure to be unaligned. This causes - * the kernel to issue unaligned access warnings on some - * architectures like ia64. Unfortunately, some software out there - * doesn't properly unroll the NLA packet and assumes that the start - * of the taskstats structure will always be 20 bytes from the start - * of the netlink payload. Aligning the start of the taskstats - * structure breaks this software, which we don't want. So, for now - * the alignment only happens on architectures that require it - * and those users will have to update to fixed versions of those - * packages. Space is reserved in the packet only when needed. - * This ifdef should be removed in several years e.g. 2012 once - * we can be confident that fixed versions are installed on most - * systems. We add the padding before the aggregate since the - * aggregate is already a defined type. - */ -#ifdef TASKSTATS_NEEDS_PADDING - if (nla_put(skb, TASKSTATS_TYPE_NULL, 0, NULL) < 0) - goto err; -#endif na = nla_nest_start(skb, aggr); if (!na) goto err; @@ -401,7 +374,8 @@ static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid) nla_nest_cancel(skb, na); goto err; } - ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats)); + ret = nla_reserve_64bit(skb, TASKSTATS_TYPE_STATS, + sizeof(struct taskstats), TASKSTATS_TYPE_NULL); if (!ret) { nla_nest_cancel(skb, na); goto err; @@ -500,10 +474,9 @@ static size_t taskstats_packet_size(void) size_t size; size = nla_total_size(sizeof(u32)) + - nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); -#ifdef TASKSTATS_NEEDS_PADDING - size += nla_total_size(0); /* Padding for alignment */ -#endif + nla_total_size_64bit(sizeof(struct taskstats)) + + nla_total_size(0); + return size; } -- GitLab From 1f60fbe7274918adb8db2f616e321890730ab7e3 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 23 Apr 2016 22:50:07 -0400 Subject: [PATCH 4062/9938] ext4: allow readdir()'s of large empty directories to be interrupted If a directory has a large number of empty blocks, iterating over all of them can take a long time, leading to scheduler warnings and users getting irritated when they can't kill a process in the middle of one of these long-running readdir operations. Fix this by adding checks to ext4_readdir() and ext4_htree_fill_tree(). This was reverted earlier due to a typo in the original commit where I experimented with using signal_pending() instead of fatal_signal_pending(). The test was in the wrong place if we were going to return signal_pending() since we would end up returning duplicant entries. See 9f2394c9be47 for a more detailed explanation. Added fix as suggested by Linus to check for signal_pending() in in the filldir() functions. Reported-by: Benjamin LaHaise Google-Bug-Id: 27880676 Signed-off-by: Theodore Ts'o --- fs/compat.c | 4 ++++ fs/ext4/dir.c | 5 +++++ fs/ext4/namei.c | 5 +++++ fs/readdir.c | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/fs/compat.c b/fs/compat.c index a71936a3f4cb..f940cb20562f 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -936,6 +936,8 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen, } dirent = buf->previous; if (dirent) { + if (signal_pending(current)) + return -EINTR; if (__put_user(offset, &dirent->d_off)) goto efault; } @@ -1020,6 +1022,8 @@ static int compat_filldir64(struct dir_context *ctx, const char *name, dirent = buf->previous; if (dirent) { + if (signal_pending(current)) + return -EINTR; if (__put_user_unaligned(offset, &dirent->d_off)) goto efault; } diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 561d7308b393..4173bfe21114 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -150,6 +150,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) while (ctx->pos < inode->i_size) { struct ext4_map_blocks map; + if (fatal_signal_pending(current)) { + err = -ERESTARTSYS; + goto errout; + } + cond_resched(); map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb); map.m_len = 1; err = ext4_map_blocks(NULL, inode, &map, 0); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 48e4b8907826..c07422d254b6 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1107,6 +1107,11 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, } while (1) { + if (fatal_signal_pending(current)) { + err = -ERESTARTSYS; + goto errout; + } + cond_resched(); block = dx_get_block(frame->at); ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo, start_hash, start_minor_hash); diff --git a/fs/readdir.c b/fs/readdir.c index e69ef3b79787..5f2d4bee5a73 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -169,6 +169,8 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, } dirent = buf->previous; if (dirent) { + if (signal_pending(current)) + return -EINTR; if (__put_user(offset, &dirent->d_off)) goto efault; } @@ -248,6 +250,8 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, return -EINVAL; dirent = buf->previous; if (dirent) { + if (signal_pending(current)) + return -EINTR; if (__put_user(offset, &dirent->d_off)) goto efault; } -- GitLab From 06bd3c36a733ac27962fea7d6f47168841376824 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 24 Apr 2016 00:56:03 -0400 Subject: [PATCH 4063/9938] ext4: fix data exposure after a crash Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed. The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode. The only exception to the above rule are extending direct IO writes where blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks(). CC: stable@vger.kernel.org Fixes: f3b59291a69d0b734be1fc8be489fef2dd846d3d Reported-by: "HUANG Weller (CM/ESW12-CN)" Tested-by: "HUANG Weller (CM/ESW12-CN)" Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/inode.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 981a1fc30eaa..250c2df04a92 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -684,6 +684,21 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, ret = check_block_validity(inode, map); if (ret != 0) return ret; + + /* + * Inodes with freshly allocated blocks where contents will be + * visible after transaction commit must be on transaction's + * ordered data list. + */ + if (map->m_flags & EXT4_MAP_NEW && + !(map->m_flags & EXT4_MAP_UNWRITTEN) && + !(flags & EXT4_GET_BLOCKS_ZERO) && + !IS_NOQUOTA(inode) && + ext4_should_order_data(inode)) { + ret = ext4_jbd2_file_inode(handle, inode); + if (ret) + return ret; + } } return retval; } @@ -1289,15 +1304,6 @@ static int ext4_write_end(struct file *file, int i_size_changed = 0; trace_ext4_write_end(inode, pos, len, copied); - if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) { - ret = ext4_jbd2_file_inode(handle, inode); - if (ret) { - unlock_page(page); - put_page(page); - goto errout; - } - } - if (ext4_has_inline_data(inode)) { ret = ext4_write_inline_data_end(inode, pos, len, copied, page); -- GitLab From 3957ef53a5033bd519b19cf375061be1929bdb5f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 24 Apr 2016 00:56:05 -0400 Subject: [PATCH 4064/9938] ext4: remove EXT4_STATE_ORDERED_MODE This flag is just duplicating what ext4_should_order_data() tells you and is used in a single place. Furthermore it doesn't reflect changes to inode data journalling flag so it may be possibly misleading. Just remove it. Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/ext4.h | 1 - fs/ext4/inode.c | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 349afebe21ee..f75e9ebd4ca2 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1549,7 +1549,6 @@ enum { EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read nolocking */ EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */ - EXT4_STATE_ORDERED_MODE, /* data=ordered mode */ EXT4_STATE_EXT_PRECACHED, /* extents have been precached */ }; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 250c2df04a92..8ba46ad06aed 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3540,10 +3540,7 @@ void ext4_set_aops(struct inode *inode) { switch (ext4_inode_journal_mode(inode)) { case EXT4_INODE_ORDERED_DATA_MODE: - ext4_set_inode_state(inode, EXT4_STATE_ORDERED_MODE); - break; case EXT4_INODE_WRITEBACK_DATA_MODE: - ext4_clear_inode_state(inode, EXT4_STATE_ORDERED_MODE); break; case EXT4_INODE_JOURNAL_DATA_MODE: inode->i_mapping->a_ops = &ext4_journalled_aops; @@ -3636,7 +3633,7 @@ static int __ext4_block_zero_page_range(handle_t *handle, } else { err = 0; mark_buffer_dirty(bh); - if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) + if (ext4_should_order_data(inode)) err = ext4_jbd2_file_inode(handle, inode); } -- GitLab From 41617e1a8dec9fe082ba5dec26bacb154eb55482 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 24 Apr 2016 00:56:07 -0400 Subject: [PATCH 4065/9938] jbd2: add support for avoiding data writes during transaction commits Currently when filesystem needs to make sure data is on permanent storage before committing a transaction it adds inode to transaction's inode list. During transaction commit, jbd2 writes back all dirty buffers that have allocated underlying blocks and waits for the IO to finish. However when doing writeback for delayed allocated data, we allocate blocks and immediately submit the data. Thus asking jbd2 to write dirty pages just unnecessarily adds more work to jbd2 possibly writing back other redirtied blocks. Add support to jbd2 to allow filesystem to ask jbd2 to only wait for outstanding data writes before committing a transaction and thus avoid unnecessary writes. Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/ext4_jbd2.h | 3 ++- fs/jbd2/commit.c | 4 ++++ fs/jbd2/journal.c | 3 ++- fs/jbd2/transaction.c | 22 ++++++++++++++++++---- fs/ocfs2/journal.h | 2 +- include/linux/jbd2.h | 13 +++++++++++-- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index 5f5846211095..f1c940b38b30 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -362,7 +362,8 @@ static inline int ext4_journal_force_commit(journal_t *journal) static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) { if (ext4_handle_valid(handle)) - return jbd2_journal_file_inode(handle, EXT4_I(inode)->jinode); + return jbd2_journal_inode_add_write(handle, + EXT4_I(inode)->jinode); return 0; } diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 2ad98d6e19f4..70078096117d 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -219,6 +219,8 @@ static int journal_submit_data_buffers(journal_t *journal, spin_lock(&journal->j_list_lock); list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { + if (!(jinode->i_flags & JI_WRITE_DATA)) + continue; mapping = jinode->i_vfs_inode->i_mapping; jinode->i_flags |= JI_COMMIT_RUNNING; spin_unlock(&journal->j_list_lock); @@ -256,6 +258,8 @@ static int journal_finish_inode_data_buffers(journal_t *journal, /* For locking, see the comment in journal_submit_data_buffers() */ spin_lock(&journal->j_list_lock); list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { + if (!(jinode->i_flags & JI_WAIT_DATA)) + continue; jinode->i_flags |= JI_COMMIT_RUNNING; spin_unlock(&journal->j_list_lock); err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 435f0b26ac20..b31852f76f46 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -94,7 +94,8 @@ EXPORT_SYMBOL(jbd2_journal_blocks_per_page); EXPORT_SYMBOL(jbd2_journal_invalidatepage); EXPORT_SYMBOL(jbd2_journal_try_to_free_buffers); EXPORT_SYMBOL(jbd2_journal_force_commit); -EXPORT_SYMBOL(jbd2_journal_file_inode); +EXPORT_SYMBOL(jbd2_journal_inode_add_write); +EXPORT_SYMBOL(jbd2_journal_inode_add_wait); EXPORT_SYMBOL(jbd2_journal_init_jbd_inode); EXPORT_SYMBOL(jbd2_journal_release_jbd_inode); EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate); diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 67c103867bf8..be56c8ca34c2 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -2462,7 +2462,8 @@ void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh) /* * File inode in the inode list of the handle's transaction */ -int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) +static int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode, + unsigned long flags) { transaction_t *transaction = handle->h_transaction; journal_t *journal; @@ -2487,12 +2488,14 @@ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) * and if jinode->i_next_transaction == transaction, commit code * will only file the inode where we want it. */ - if (jinode->i_transaction == transaction || - jinode->i_next_transaction == transaction) + if ((jinode->i_transaction == transaction || + jinode->i_next_transaction == transaction) && + (jinode->i_flags & flags) == flags) return 0; spin_lock(&journal->j_list_lock); - + jinode->i_flags |= flags; + /* Is inode already attached where we need it? */ if (jinode->i_transaction == transaction || jinode->i_next_transaction == transaction) goto done; @@ -2523,6 +2526,17 @@ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) return 0; } +int jbd2_journal_inode_add_write(handle_t *handle, struct jbd2_inode *jinode) +{ + return jbd2_journal_file_inode(handle, jinode, + JI_WRITE_DATA | JI_WAIT_DATA); +} + +int jbd2_journal_inode_add_wait(handle_t *handle, struct jbd2_inode *jinode) +{ + return jbd2_journal_file_inode(handle, jinode, JI_WAIT_DATA); +} + /* * File truncate and transaction commit interact with each other in a * non-trivial way. If a transaction writing data block A is diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index f4cd3c3e9fb7..497a4171ef61 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -619,7 +619,7 @@ static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb, static inline int ocfs2_jbd2_file_inode(handle_t *handle, struct inode *inode) { - return jbd2_journal_file_inode(handle, &OCFS2_I(inode)->ip_jinode); + return jbd2_journal_inode_add_write(handle, &OCFS2_I(inode)->ip_jinode); } static inline int ocfs2_begin_ordered_truncate(struct inode *inode, diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index fd1083c46c61..39511484ad10 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -403,11 +403,19 @@ static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh) /* Flags in jbd_inode->i_flags */ #define __JI_COMMIT_RUNNING 0 -/* Commit of the inode data in progress. We use this flag to protect us from +#define __JI_WRITE_DATA 1 +#define __JI_WAIT_DATA 2 + +/* + * Commit of the inode data in progress. We use this flag to protect us from * concurrent deletion of inode. We cannot use reference to inode for this * since we cannot afford doing last iput() on behalf of kjournald */ #define JI_COMMIT_RUNNING (1 << __JI_COMMIT_RUNNING) +/* Write allocated dirty buffers in this inode before commit */ +#define JI_WRITE_DATA (1 << __JI_WRITE_DATA) +/* Wait for outstanding data writes for this inode before commit */ +#define JI_WAIT_DATA (1 << __JI_WAIT_DATA) /** * struct jbd_inode is the structure linking inodes in ordered mode @@ -1270,7 +1278,8 @@ extern int jbd2_journal_clear_err (journal_t *); extern int jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *); extern int jbd2_journal_force_commit(journal_t *); extern int jbd2_journal_force_commit_nested(journal_t *); -extern int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *inode); +extern int jbd2_journal_inode_add_write(handle_t *handle, struct jbd2_inode *inode); +extern int jbd2_journal_inode_add_wait(handle_t *handle, struct jbd2_inode *inode); extern int jbd2_journal_begin_ordered_truncate(journal_t *journal, struct jbd2_inode *inode, loff_t new_size); extern void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode); -- GitLab From ee0876bc69ee8d24d524fb2e9e41e3682aaebb11 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 24 Apr 2016 00:56:08 -0400 Subject: [PATCH 4066/9938] ext4: do not ask jbd2 to write data for delalloc buffers Currently we ask jbd2 to write all dirty allocated buffers before committing a transaction when doing writeback of delay allocated blocks. However this is unnecessary since we move all pages to writeback state before dropping a transaction handle and then submit all the necessary IO. We still need the transaction commit to wait for all the outstanding writeback before flushing disk caches during transaction commit to avoid data exposure issues though. Use the new jbd2 capability and ask it to only wait for outstanding writeback during transaction commit when writing back data in ext4_writepages(). Tested-by: "HUANG Weller (CM/ESW12-CN)" Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/ext4.h | 3 +++ fs/ext4/ext4_jbd2.h | 12 +++++++++++- fs/ext4/inode.c | 10 +++++++--- fs/ext4/move_extent.c | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f75e9ebd4ca2..cb00b1119ec9 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -581,6 +581,9 @@ enum { #define EXT4_GET_BLOCKS_ZERO 0x0200 #define EXT4_GET_BLOCKS_CREATE_ZERO (EXT4_GET_BLOCKS_CREATE |\ EXT4_GET_BLOCKS_ZERO) + /* Caller will submit data before dropping transaction handle. This + * allows jbd2 to avoid submitting data before commit. */ +#define EXT4_GET_BLOCKS_IO_SUBMIT 0x0400 /* * The bit position of these flags must not overlap with any of the diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index f1c940b38b30..09c1ef38cbe6 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -359,7 +359,8 @@ static inline int ext4_journal_force_commit(journal_t *journal) return 0; } -static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) +static inline int ext4_jbd2_inode_add_write(handle_t *handle, + struct inode *inode) { if (ext4_handle_valid(handle)) return jbd2_journal_inode_add_write(handle, @@ -367,6 +368,15 @@ static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) return 0; } +static inline int ext4_jbd2_inode_add_wait(handle_t *handle, + struct inode *inode) +{ + if (ext4_handle_valid(handle)) + return jbd2_journal_inode_add_wait(handle, + EXT4_I(inode)->jinode); + return 0; +} + static inline void ext4_update_inode_fsync_trans(handle_t *handle, struct inode *inode, int datasync) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8ba46ad06aed..17bfa42ac971 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -695,7 +695,10 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, !(flags & EXT4_GET_BLOCKS_ZERO) && !IS_NOQUOTA(inode) && ext4_should_order_data(inode)) { - ret = ext4_jbd2_file_inode(handle, inode); + if (flags & EXT4_GET_BLOCKS_IO_SUBMIT) + ret = ext4_jbd2_inode_add_wait(handle, inode); + else + ret = ext4_jbd2_inode_add_write(handle, inode); if (ret) return ret; } @@ -2319,7 +2322,8 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd) * the data was copied into the page cache. */ get_blocks_flags = EXT4_GET_BLOCKS_CREATE | - EXT4_GET_BLOCKS_METADATA_NOFAIL; + EXT4_GET_BLOCKS_METADATA_NOFAIL | + EXT4_GET_BLOCKS_IO_SUBMIT; dioread_nolock = ext4_should_dioread_nolock(inode); if (dioread_nolock) get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT; @@ -3634,7 +3638,7 @@ static int __ext4_block_zero_page_range(handle_t *handle, err = 0; mark_buffer_dirty(bh); if (ext4_should_order_data(inode)) - err = ext4_jbd2_file_inode(handle, inode); + err = ext4_jbd2_inode_add_write(handle, inode); } unlock: diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 325cef48b39a..a920c5d29fac 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -400,7 +400,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, /* Even in case of data=writeback it is reasonable to pin * inode to transaction, to prevent unexpected data loss */ - *err = ext4_jbd2_file_inode(handle, orig_inode); + *err = ext4_jbd2_inode_add_write(handle, orig_inode); unlock_pages: unlock_page(pagep[0]); -- GitLab From d8469e93a4af82110b15b28bbb003a1dbe4258d2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Apr 2016 16:05:24 +0200 Subject: [PATCH 4067/9938] iio: pressure: hp03: Add Hope RF HP03 sensor support Add support for HopeRF pressure and temperature sensor. This device uses two fixed I2C addresses, one for storing calibration coefficients and another for accessing the ADC. Signed-off-by: Marek Vasut Cc: Matt Ranostay Cc: Jonathan Cameron Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/pressure/hp03.txt | 17 + drivers/iio/pressure/Kconfig | 11 + drivers/iio/pressure/Makefile | 1 + drivers/iio/pressure/hp03.c | 312 ++++++++++++++++++ 4 files changed, 341 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/pressure/hp03.txt create mode 100644 drivers/iio/pressure/hp03.c diff --git a/Documentation/devicetree/bindings/iio/pressure/hp03.txt b/Documentation/devicetree/bindings/iio/pressure/hp03.txt new file mode 100644 index 000000000000..54e7e70bcea5 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/pressure/hp03.txt @@ -0,0 +1,17 @@ +HopeRF HP03 digital pressure/temperature sensors + +Required properties: +- compatible: must be "hoperf,hp03" +- xclr-gpio: must be device tree identifier of the XCLR pin. + The XCLR pin is a reset of the ADC in the chip, + it must be pulled HI before the conversion and + readout of the value from the ADC registers and + pulled LO afterward. + +Example: + +hp03@0x77 { + compatible = "hoperf,hp03"; + reg = <0x77>; + xclr-gpio = <&portc 0 0x0>; +}; diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 8de0192adea6..54c616520512 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -30,6 +30,17 @@ config HID_SENSOR_PRESS To compile this driver as a module, choose M here: the module will be called hid-sensor-press. +config HP03 + tristate "Hope RF HP03 temperature and pressure sensor driver" + depends on I2C + select REGMAP_I2C + help + Say yes here to build support for Hope RF HP03 pressure and + temperature sensor. + + To compile this driver as a module, choose M here: the module + will be called hp03. + config MPL115 tristate diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 6e60863c1086..17d6e7afa1ff 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -5,6 +5,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_BMP280) += bmp280.o obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o +obj-$(CONFIG_HP03) += hp03.o obj-$(CONFIG_MPL115) += mpl115.o obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c new file mode 100644 index 000000000000..ac76515d5d49 --- /dev/null +++ b/drivers/iio/pressure/hp03.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2016 Marek Vasut + * + * Driver for Hope RF HP03 digital temperature and pressure sensor. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "hp03: " fmt + +#include +#include +#include +#include +#include +#include +#include + +/* + * The HP03 sensor occupies two fixed I2C addresses: + * 0x50 ... read-only EEPROM with calibration data + * 0x77 ... read-write ADC for pressure and temperature + */ +#define HP03_EEPROM_ADDR 0x50 +#define HP03_ADC_ADDR 0x77 + +#define HP03_EEPROM_CX_OFFSET 0x10 +#define HP03_EEPROM_AB_OFFSET 0x1e +#define HP03_EEPROM_CD_OFFSET 0x20 + +#define HP03_ADC_WRITE_REG 0xff +#define HP03_ADC_READ_REG 0xfd +#define HP03_ADC_READ_PRESSURE 0xf0 /* D1 in datasheet */ +#define HP03_ADC_READ_TEMP 0xe8 /* D2 in datasheet */ + +struct hp03_priv { + struct i2c_client *client; + struct mutex lock; + struct gpio_desc *xclr_gpio; + + struct i2c_client *eeprom_client; + struct regmap *eeprom_regmap; + + s32 pressure; /* kPa */ + s32 temp; /* Deg. C */ +}; + +static const struct iio_chan_spec hp03_channels[] = { + { + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + }, + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static bool hp03_is_writeable_reg(struct device *dev, unsigned int reg) +{ + return false; +} + +static bool hp03_is_volatile_reg(struct device *dev, unsigned int reg) +{ + return false; +} + +static const struct regmap_config hp03_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = HP03_EEPROM_CD_OFFSET + 1, + .cache_type = REGCACHE_RBTREE, + + .writeable_reg = hp03_is_writeable_reg, + .volatile_reg = hp03_is_volatile_reg, +}; + +static int hp03_get_temp_pressure(struct hp03_priv *priv, const u8 reg) +{ + int ret; + + ret = i2c_smbus_write_byte_data(priv->client, HP03_ADC_WRITE_REG, reg); + if (ret < 0) + return ret; + + msleep(50); /* Wait for conversion to finish */ + + return i2c_smbus_read_word_data(priv->client, HP03_ADC_READ_REG); +} + +static int hp03_update_temp_pressure(struct hp03_priv *priv) +{ + struct device *dev = &priv->client->dev; + u8 coefs[18]; + u16 cx_val[7]; + int ab_val, d1_val, d2_val, diff_val, dut, off, sens, x; + int i, ret; + + /* Sample coefficients from EEPROM */ + ret = regmap_bulk_read(priv->eeprom_regmap, HP03_EEPROM_CX_OFFSET, + coefs, sizeof(coefs)); + if (ret < 0) { + dev_err(dev, "Failed to read EEPROM (reg=%02x)\n", + HP03_EEPROM_CX_OFFSET); + return ret; + } + + /* Sample Temperature and Pressure */ + gpiod_set_value_cansleep(priv->xclr_gpio, 1); + + ret = hp03_get_temp_pressure(priv, HP03_ADC_READ_PRESSURE); + if (ret < 0) { + dev_err(dev, "Failed to read pressure\n"); + goto err_adc; + } + d1_val = ret; + + ret = hp03_get_temp_pressure(priv, HP03_ADC_READ_TEMP); + if (ret < 0) { + dev_err(dev, "Failed to read temperature\n"); + goto err_adc; + } + d2_val = ret; + + gpiod_set_value_cansleep(priv->xclr_gpio, 0); + + /* The Cx coefficients and Temp/Pressure values are MSB first. */ + for (i = 0; i < 7; i++) + cx_val[i] = (coefs[2 * i] << 8) | (coefs[(2 * i) + 1] << 0); + d1_val = ((d1_val >> 8) & 0xff) | ((d1_val & 0xff) << 8); + d2_val = ((d2_val >> 8) & 0xff) | ((d2_val & 0xff) << 8); + + /* Coefficient voodoo from the HP03 datasheet. */ + if (d2_val >= cx_val[4]) + ab_val = coefs[14]; /* A-value */ + else + ab_val = coefs[15]; /* B-value */ + + diff_val = d2_val - cx_val[4]; + dut = (ab_val * (diff_val >> 7) * (diff_val >> 7)) >> coefs[16]; + dut = diff_val - dut; + + off = (cx_val[1] + (((cx_val[3] - 1024) * dut) >> 14)) * 4; + sens = cx_val[0] + ((cx_val[2] * dut) >> 10); + x = ((sens * (d1_val - 7168)) >> 14) - off; + + priv->pressure = ((x * 100) >> 5) + (cx_val[6] * 10); + priv->temp = 250 + ((dut * cx_val[5]) >> 16) - (dut >> coefs[17]); + + return 0; + +err_adc: + gpiod_set_value_cansleep(priv->xclr_gpio, 0); + return ret; +} + +static int hp03_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct hp03_priv *priv = iio_priv(indio_dev); + int ret; + + mutex_lock(&priv->lock); + ret = hp03_update_temp_pressure(priv); + mutex_unlock(&priv->lock); + + if (ret) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_PRESSURE: + *val = priv->pressure; + return IIO_VAL_INT; + case IIO_TEMP: + *val = priv->temp; + return IIO_VAL_INT; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PRESSURE: + *val = 0; + *val2 = 1000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + *val = 10; + return IIO_VAL_INT; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static const struct iio_info hp03_info = { + .driver_module = THIS_MODULE, + .read_raw = &hp03_read_raw, +}; + +static int hp03_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct iio_dev *indio_dev; + struct hp03_priv *priv; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + priv = iio_priv(indio_dev); + priv->client = client; + mutex_init(&priv->lock); + + indio_dev->dev.parent = dev; + indio_dev->name = id->name; + indio_dev->channels = hp03_channels; + indio_dev->num_channels = ARRAY_SIZE(hp03_channels); + indio_dev->info = &hp03_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + priv->xclr_gpio = devm_gpiod_get_index(dev, "xclr", 0, GPIOD_OUT_HIGH); + if (IS_ERR(priv->xclr_gpio)) { + dev_err(dev, "Failed to claim XCLR GPIO\n"); + ret = PTR_ERR(priv->xclr_gpio); + return ret; + } + + /* + * Allocate another device for the on-sensor EEPROM, + * which has it's dedicated I2C address and contains + * the calibration constants for the sensor. + */ + priv->eeprom_client = i2c_new_dummy(client->adapter, HP03_EEPROM_ADDR); + if (!priv->eeprom_client) { + dev_err(dev, "New EEPROM I2C device failed\n"); + return -ENODEV; + } + + priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client, + &hp03_regmap_config); + if (IS_ERR(priv->eeprom_regmap)) { + dev_err(dev, "Failed to allocate EEPROM regmap\n"); + ret = PTR_ERR(priv->eeprom_regmap); + goto err_cleanup_eeprom_client; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(dev, "Failed to register IIO device\n"); + goto err_cleanup_eeprom_regmap; + } + + i2c_set_clientdata(client, indio_dev); + + return 0; + +err_cleanup_eeprom_regmap: + regmap_exit(priv->eeprom_regmap); + +err_cleanup_eeprom_client: + i2c_unregister_device(priv->eeprom_client); + return ret; +} + +static int hp03_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct hp03_priv *priv = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + regmap_exit(priv->eeprom_regmap); + i2c_unregister_device(priv->eeprom_client); + + return 0; +} + +static const struct i2c_device_id hp03_id[] = { + { "hp03", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, hp03_id); + +static struct i2c_driver hp03_driver = { + .driver = { + .name = "hp03", + }, + .probe = hp03_probe, + .remove = hp03_remove, + .id_table = hp03_id, +}; +module_i2c_driver(hp03_driver); + +MODULE_AUTHOR("Marek Vasut "); +MODULE_DESCRIPTION("Driver for Hope RF HP03 pressure and temperature sensor"); +MODULE_LICENSE("GPL v2"); -- GitLab From 366a3270c1c5ce0a12d1451e2e2e6341385c331d Mon Sep 17 00:00:00 2001 From: Tiberiu Breana Date: Mon, 18 Apr 2016 17:50:43 +0300 Subject: [PATCH 4068/9938] iio: humidity: Add support for AM2315 Add basic support for the Aosong AM2315 relative humidity and ambient temperature sensor. Includes support for raw readings and ACPI detection. Datasheet: http://www.aosong.com/asp_bin/Products/en/AM2315.pdf Signed-off-by: Tiberiu Breana Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 10 ++ drivers/iio/humidity/Makefile | 1 + drivers/iio/humidity/am2315.c | 228 ++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/iio/humidity/am2315.c diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 866dda133336..738a86d9e4a9 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -3,6 +3,16 @@ # menu "Humidity sensors" +config AM2315 + tristate "Aosong AM2315 relative humidity and temperature sensor" + depends on I2C + help + If you say yes here you get support for the Aosong AM2315 + relative humidity and ambient temperature sensor. + + This driver can also be built as a module. If so, the module will + be called am2315. + config DHT11 tristate "DHT11 (and compatible sensors) driver" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile index c9f089a9a6b8..4a73442fcd9c 100644 --- a/drivers/iio/humidity/Makefile +++ b/drivers/iio/humidity/Makefile @@ -2,6 +2,7 @@ # Makefile for IIO humidity sensor drivers # +obj-$(CONFIG_AM2315) += am2315.o obj-$(CONFIG_DHT11) += dht11.o obj-$(CONFIG_HDC100X) += hdc100x.o obj-$(CONFIG_HTU21) += htu21.o diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c new file mode 100644 index 000000000000..d392fc8a9d16 --- /dev/null +++ b/drivers/iio/humidity/am2315.c @@ -0,0 +1,228 @@ +/** + * Aosong AM2315 relative humidity and temperature + * + * Copyright (c) 2016, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * 7-bit I2C address: 0x5C. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define AM2315_REG_HUM_MSB 0x00 +#define AM2315_REG_HUM_LSB 0x01 +#define AM2315_REG_TEMP_MSB 0x02 +#define AM2315_REG_TEMP_LSB 0x03 + +#define AM2315_FUNCTION_READ 0x03 +#define AM2315_HUM_OFFSET 2 +#define AM2315_TEMP_OFFSET 4 + +#define AM2315_DRIVER_NAME "am2315" + +struct am2315_data { + struct i2c_client *client; + struct mutex lock; +}; + +struct am2315_sensor_data { + s16 hum_data; + s16 temp_data; +}; + +static const struct iio_chan_spec am2315_channels[] = { + { + .type = IIO_HUMIDITYRELATIVE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) + }, + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) + }, +}; + +/* CRC calculation algorithm, as specified in the datasheet (page 13). */ +static u16 am2315_crc(u8 *data, u8 nr_bytes) +{ + int i; + u16 crc = 0xffff; + + while (nr_bytes--) { + crc ^= *data++; + for (i = 0; i < 8; i++) { + if (crc & 0x01) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + + return crc; +} + +/* Simple function that sends a few bytes to the device to wake it up. */ +static void am2315_ping(struct i2c_client *client) +{ + i2c_smbus_read_byte_data(client, AM2315_REG_HUM_MSB); +} + +static int am2315_read_data(struct am2315_data *data, + struct am2315_sensor_data *sensor_data) +{ + int ret; + /* tx_buf format: */ + u8 tx_buf[3] = { AM2315_FUNCTION_READ, AM2315_REG_HUM_MSB, 4 }; + /* + * rx_buf format: + * + * + * + */ + u8 rx_buf[8]; + u16 crc; + + /* First wake up the device. */ + am2315_ping(data->client); + + mutex_lock(&data->lock); + ret = i2c_master_send(data->client, tx_buf, sizeof(tx_buf)); + if (ret < 0) { + dev_err(&data->client->dev, "failed to send read request\n"); + goto exit_unlock; + } + /* Wait 2-3 ms, then read back the data sent by the device. */ + usleep_range(2000, 3000); + /* Do a bulk data read, then pick out what we need. */ + ret = i2c_master_recv(data->client, rx_buf, sizeof(rx_buf)); + if (ret < 0) { + dev_err(&data->client->dev, "failed to read sensor data\n"); + goto exit_unlock; + } + mutex_unlock(&data->lock); + /* + * Do a CRC check on the data and compare it to the value + * calculated by the device. + */ + crc = am2315_crc(rx_buf, sizeof(rx_buf) - 2); + if ((crc & 0xff) != rx_buf[6] || (crc >> 8) != rx_buf[7]) { + dev_err(&data->client->dev, "failed to verify sensor data\n"); + return -EIO; + } + + sensor_data->hum_data = (rx_buf[AM2315_HUM_OFFSET] << 8) | + rx_buf[AM2315_HUM_OFFSET + 1]; + sensor_data->temp_data = (rx_buf[AM2315_TEMP_OFFSET] << 8) | + rx_buf[AM2315_TEMP_OFFSET + 1]; + + return ret; + +exit_unlock: + mutex_unlock(&data->lock); + return ret; +} + +static int am2315_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + struct am2315_sensor_data sensor_data; + struct am2315_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = am2315_read_data(data, &sensor_data); + if (ret < 0) + return ret; + *val = (chan->type == IIO_HUMIDITYRELATIVE) ? + sensor_data.hum_data : sensor_data.temp_data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 100; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info am2315_info = { + .driver_module = THIS_MODULE, + .read_raw = am2315_read_raw, +}; + +static int am2315_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct am2315_data *data; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation failed!\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &am2315_info; + indio_dev->name = AM2315_DRIVER_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = am2315_channels; + indio_dev->num_channels = ARRAY_SIZE(am2315_channels); + + return iio_device_register(indio_dev); +} + +static int am2315_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return 0; +} + +static const struct i2c_device_id am2315_i2c_id[] = { + {"am2315", 0}, + {} +}; + +static const struct acpi_device_id am2315_acpi_id[] = { + {"AOS2315", 0}, + {} +}; + +MODULE_DEVICE_TABLE(acpi, am2315_acpi_id); + +static struct i2c_driver am2315_driver = { + .driver = { + .name = "am2315", + .acpi_match_table = ACPI_PTR(am2315_acpi_id), + }, + .probe = am2315_probe, + .remove = am2315_remove, + .id_table = am2315_i2c_id, +}; + +module_i2c_driver(am2315_driver); + +MODULE_AUTHOR("Tiberiu Breana "); +MODULE_DESCRIPTION("Aosong AM2315 relative humidity and temperature"); +MODULE_LICENSE("GPL v2"); -- GitLab From 0d96d5ead3f7f1303a6a445051f29bba7c7f4e47 Mon Sep 17 00:00:00 2001 From: Tiberiu Breana Date: Mon, 18 Apr 2016 17:50:44 +0300 Subject: [PATCH 4069/9938] iio: humidity: Add triggered buffer support for AM2315 Signed-off-by: Tiberiu Breana Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/am2315.c | 81 +++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index d392fc8a9d16..3be6d209a159 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -15,8 +15,11 @@ #include #include #include +#include #include #include +#include +#include #define AM2315_REG_HUM_MSB 0x00 #define AM2315_REG_HUM_LSB 0x01 @@ -26,12 +29,14 @@ #define AM2315_FUNCTION_READ 0x03 #define AM2315_HUM_OFFSET 2 #define AM2315_TEMP_OFFSET 4 +#define AM2315_ALL_CHANNEL_MASK GENMASK(1, 0) #define AM2315_DRIVER_NAME "am2315" struct am2315_data { struct i2c_client *client; struct mutex lock; + s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */ }; struct am2315_sensor_data { @@ -43,13 +48,28 @@ static const struct iio_chan_spec am2315_channels[] = { { .type = IIO_HUMIDITYRELATIVE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE) + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, }, { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE) + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, }, + IIO_CHAN_SOFT_TIMESTAMP(2), }; /* CRC calculation algorithm, as specified in the datasheet (page 13). */ @@ -134,6 +154,44 @@ static int am2315_read_data(struct am2315_data *data, return ret; } +static irqreturn_t am2315_trigger_handler(int irq, void *p) +{ + int i; + int ret; + int bit; + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct am2315_data *data = iio_priv(indio_dev); + struct am2315_sensor_data sensor_data; + + ret = am2315_read_data(data, &sensor_data); + if (ret < 0) { + mutex_unlock(&data->lock); + goto err; + } + + mutex_lock(&data->lock); + if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) { + data->buffer[0] = sensor_data.hum_data; + data->buffer[1] = sensor_data.temp_data; + } else { + i = 0; + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + data->buffer[i] = (bit ? sensor_data.temp_data : + sensor_data.hum_data); + i++; + } + } + mutex_unlock(&data->lock); + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + static int am2315_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -166,6 +224,7 @@ static const struct iio_info am2315_info = { static int am2315_probe(struct i2c_client *client, const struct i2c_device_id *id) { + int ret; struct iio_dev *indio_dev; struct am2315_data *data; @@ -187,7 +246,22 @@ static int am2315_probe(struct i2c_client *client, indio_dev->channels = am2315_channels; indio_dev->num_channels = ARRAY_SIZE(am2315_channels); - return iio_device_register(indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, NULL, + am2315_trigger_handler, NULL); + if (ret < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + return ret; + } + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto err_buffer_cleanup; + + return 0; + +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; } static int am2315_remove(struct i2c_client *client) @@ -195,6 +269,7 @@ static int am2315_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); return 0; } -- GitLab From b9567e6664643eb99367fb88d14fdba863b1688a Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Mon, 18 Apr 2016 17:31:53 +0300 Subject: [PATCH 4070/9938] max44000: Initial support This just adds support for reporting illuminance with default settings. Important default registers are written on probe because the device otherwise lacks a reset function. Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 11 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/max44000.c | 324 +++++++++++++++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 drivers/iio/light/max44000.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index cbd723236e38..7c566f516572 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -234,6 +234,17 @@ config LTR501 This driver can also be built as a module. If so, the module will be called ltr501. +config MAX44000 + tristate "MAX44000 Ambient and Infrared Proximity Sensor" + depends on I2C + select REGMAP_I2C + help + Say Y here if you want to build support for Maxim Integrated's + MAX44000 ambient and infrared proximity sensor device. + + To compile this driver as a module, choose M here: + the module will be called max44000. + config OPT3001 tristate "Texas Instruments OPT3001 Light Sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 8b246a604a92..6f2a3c62de27 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_ISL29125) += isl29125.o obj-$(CONFIG_JSA1212) += jsa1212.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_LTR501) += ltr501.o +obj-$(CONFIG_MAX44000) += max44000.o obj-$(CONFIG_OPT3001) += opt3001.o obj-$(CONFIG_PA12203001) += pa12203001.o obj-$(CONFIG_RPR0521) += rpr0521.o diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c new file mode 100644 index 000000000000..5ed79345bb42 --- /dev/null +++ b/drivers/iio/light/max44000.c @@ -0,0 +1,324 @@ +/* + * MAX44000 Ambient and Infrared Proximity Sensor + * + * Copyright (c) 2016, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * Data sheet: https://datasheets.maximintegrated.com/en/ds/MAX44000.pdf + * + * 7-bit I2C slave address 0x4a + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX44000_DRV_NAME "max44000" + +/* Registers in datasheet order */ +#define MAX44000_REG_STATUS 0x00 +#define MAX44000_REG_CFG_MAIN 0x01 +#define MAX44000_REG_CFG_RX 0x02 +#define MAX44000_REG_CFG_TX 0x03 +#define MAX44000_REG_ALS_DATA_HI 0x04 +#define MAX44000_REG_ALS_DATA_LO 0x05 +#define MAX44000_REG_PRX_DATA 0x16 +#define MAX44000_REG_ALS_UPTHR_HI 0x06 +#define MAX44000_REG_ALS_UPTHR_LO 0x07 +#define MAX44000_REG_ALS_LOTHR_HI 0x08 +#define MAX44000_REG_ALS_LOTHR_LO 0x09 +#define MAX44000_REG_PST 0x0a +#define MAX44000_REG_PRX_IND 0x0b +#define MAX44000_REG_PRX_THR 0x0c +#define MAX44000_REG_TRIM_GAIN_GREEN 0x0f +#define MAX44000_REG_TRIM_GAIN_IR 0x10 + +/* REG_CFG bits */ +#define MAX44000_CFG_ALSINTE 0x01 +#define MAX44000_CFG_PRXINTE 0x02 +#define MAX44000_CFG_MASK 0x1c +#define MAX44000_CFG_MODE_SHUTDOWN 0x00 +#define MAX44000_CFG_MODE_ALS_GIR 0x04 +#define MAX44000_CFG_MODE_ALS_G 0x08 +#define MAX44000_CFG_MODE_ALS_IR 0x0c +#define MAX44000_CFG_MODE_ALS_PRX 0x10 +#define MAX44000_CFG_MODE_PRX 0x14 +#define MAX44000_CFG_TRIM 0x20 + +/* + * Upper 4 bits are not documented but start as 1 on powerup + * Setting them to 0 causes proximity to misbehave so set them to 1 + */ +#define MAX44000_REG_CFG_RX_DEFAULT 0xf0 + +#define MAX44000_ALSDATA_OVERFLOW 0x4000 + +struct max44000_data { + struct mutex lock; + struct regmap *regmap; +}; + +/* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */ +#define MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2 5 + +static const struct iio_chan_spec max44000_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static int max44000_read_alsval(struct max44000_data *data) +{ + u16 regval; + int ret; + + ret = regmap_bulk_read(data->regmap, MAX44000_REG_ALS_DATA_HI, + ®val, sizeof(regval)); + if (ret < 0) + return ret; + + regval = be16_to_cpu(regval); + + /* + * Overflow is explained on datasheet page 17. + * + * It's a warning that either the G or IR channel has become saturated + * and that the value in the register is likely incorrect. + * + * The recommendation is to change the scale (ALSPGA). + * The driver just returns the max representable value. + */ + if (regval & MAX44000_ALSDATA_OVERFLOW) + return 0x3FFF; + + return regval; +} + +static int max44000_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct max44000_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_LIGHT: + mutex_lock(&data->lock); + ret = max44000_read_alsval(data); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_LIGHT: + *val = 1; + *val2 = MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2; + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } + + default: + return -EINVAL; + } +} + +static const struct iio_info max44000_info = { + .driver_module = THIS_MODULE, + .read_raw = max44000_read_raw, +}; + +static bool max44000_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX44000_REG_STATUS: + case MAX44000_REG_CFG_MAIN: + case MAX44000_REG_CFG_RX: + case MAX44000_REG_CFG_TX: + case MAX44000_REG_ALS_DATA_HI: + case MAX44000_REG_ALS_DATA_LO: + case MAX44000_REG_PRX_DATA: + case MAX44000_REG_ALS_UPTHR_HI: + case MAX44000_REG_ALS_UPTHR_LO: + case MAX44000_REG_ALS_LOTHR_HI: + case MAX44000_REG_ALS_LOTHR_LO: + case MAX44000_REG_PST: + case MAX44000_REG_PRX_IND: + case MAX44000_REG_PRX_THR: + case MAX44000_REG_TRIM_GAIN_GREEN: + case MAX44000_REG_TRIM_GAIN_IR: + return true; + default: + return false; + } +} + +static bool max44000_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX44000_REG_CFG_MAIN: + case MAX44000_REG_CFG_RX: + case MAX44000_REG_CFG_TX: + case MAX44000_REG_ALS_UPTHR_HI: + case MAX44000_REG_ALS_UPTHR_LO: + case MAX44000_REG_ALS_LOTHR_HI: + case MAX44000_REG_ALS_LOTHR_LO: + case MAX44000_REG_PST: + case MAX44000_REG_PRX_IND: + case MAX44000_REG_PRX_THR: + case MAX44000_REG_TRIM_GAIN_GREEN: + case MAX44000_REG_TRIM_GAIN_IR: + return true; + default: + return false; + } +} + +static bool max44000_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX44000_REG_STATUS: + case MAX44000_REG_ALS_DATA_HI: + case MAX44000_REG_ALS_DATA_LO: + case MAX44000_REG_PRX_DATA: + return true; + default: + return false; + } +} + +static bool max44000_precious_reg(struct device *dev, unsigned int reg) +{ + return reg == MAX44000_REG_STATUS; +} + +static const struct regmap_config max44000_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = MAX44000_REG_PRX_DATA, + .readable_reg = max44000_readable_reg, + .writeable_reg = max44000_writeable_reg, + .volatile_reg = max44000_volatile_reg, + .precious_reg = max44000_precious_reg, + + .use_single_rw = 1, + .cache_type = REGCACHE_RBTREE, +}; + +static int max44000_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct max44000_data *data; + struct iio_dev *indio_dev; + int ret, reg; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + data = iio_priv(indio_dev); + data->regmap = devm_regmap_init_i2c(client, &max44000_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(&client->dev, "regmap_init failed!\n"); + return PTR_ERR(data->regmap); + } + + i2c_set_clientdata(client, indio_dev); + mutex_init(&data->lock); + indio_dev->dev.parent = &client->dev; + indio_dev->info = &max44000_info; + indio_dev->name = MAX44000_DRV_NAME; + indio_dev->channels = max44000_channels; + indio_dev->num_channels = ARRAY_SIZE(max44000_channels); + + /* + * The device doesn't have a reset function so we just clear some + * important bits at probe time to ensure sane operation. + * + * Since we don't support interrupts/events the threshold values are + * not important. We also don't touch trim values. + */ + + /* Reset ALS scaling bits */ + ret = regmap_write(data->regmap, MAX44000_REG_CFG_RX, MAX44000_REG_CFG_RX_DEFAULT); + if (ret < 0) { + dev_err(&client->dev, "failed to write default CFG_RX: %d\n", ret); + return ret; + } + + /* Reset CFG bits to ALS-only mode and no interrupts */ + reg = MAX44000_CFG_TRIM | MAX44000_CFG_MODE_ALS_GIR; + ret = regmap_write(data->regmap, MAX44000_REG_CFG_MAIN, reg); + if (ret < 0) { + dev_err(&client->dev, "failed to write init config: %d\n", ret); + return ret; + } + + /* Read status at least once to clear any stale interrupt bits. */ + ret = regmap_read(data->regmap, MAX44000_REG_STATUS, ®); + if (ret < 0) { + dev_err(&client->dev, "failed to read init status: %d\n", ret); + return ret; + } + + return iio_device_register(indio_dev); +} + +static int max44000_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return 0; +} + +static const struct i2c_device_id max44000_id[] = { + {"max44000", 0}, + { } +}; +MODULE_DEVICE_TABLE(i2c, max44000_id); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id max44000_acpi_match[] = { + {"MAX44000", 0}, + { } +}; +MODULE_DEVICE_TABLE(acpi, max44000_acpi_match); +#endif + +static struct i2c_driver max44000_driver = { + .driver = { + .name = MAX44000_DRV_NAME, + .acpi_match_table = ACPI_PTR(max44000_acpi_match), + }, + .probe = max44000_probe, + .remove = max44000_remove, + .id_table = max44000_id, +}; + +module_i2c_driver(max44000_driver); + +MODULE_AUTHOR("Crestez Dan Leonard "); +MODULE_DESCRIPTION("MAX44000 Ambient and Infrared Proximity Sensor"); +MODULE_LICENSE("GPL v2"); -- GitLab From 35b651f391909c80d705533d3e0f7228d42b98a0 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Mon, 18 Apr 2016 17:31:54 +0300 Subject: [PATCH 4071/9938] max44000: Initial support for proximity reading The proximity sensor relies on sending pulses to an external IR led and it is disabled by default on powerup. The driver will enable it with a default power setting. Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/light/max44000.c | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index 5ed79345bb42..4bce7e152f9c 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -59,6 +59,11 @@ */ #define MAX44000_REG_CFG_RX_DEFAULT 0xf0 +/* REG_TX bits */ +#define MAX44000_LED_CURRENT_MASK 0xf +#define MAX44000_LED_CURRENT_MAX 11 +#define MAX44000_LED_CURRENT_DEFAULT 6 + #define MAX44000_ALSDATA_OVERFLOW 0x4000 struct max44000_data { @@ -75,6 +80,11 @@ static const struct iio_chan_spec max44000_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), }, + { + .type = IIO_PROXIMITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + }, }; static int max44000_read_alsval(struct max44000_data *data) @@ -104,11 +114,23 @@ static int max44000_read_alsval(struct max44000_data *data) return regval; } +static int max44000_write_led_current_raw(struct max44000_data *data, int val) +{ + /* Maybe we should clamp the value instead? */ + if (val < 0 || val > MAX44000_LED_CURRENT_MAX) + return -ERANGE; + if (val >= 8) + val += 4; + return regmap_write_bits(data->regmap, MAX44000_REG_CFG_TX, + MAX44000_LED_CURRENT_MASK, val); +} + static int max44000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct max44000_data *data = iio_priv(indio_dev); + unsigned int regval; int ret; switch (mask) { @@ -123,6 +145,15 @@ static int max44000_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; + case IIO_PROXIMITY: + mutex_lock(&data->lock); + ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, ®val); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = regval; + return IIO_VAL_INT; + default: return -EINVAL; } @@ -260,14 +291,26 @@ static int max44000_probe(struct i2c_client *client, */ /* Reset ALS scaling bits */ - ret = regmap_write(data->regmap, MAX44000_REG_CFG_RX, MAX44000_REG_CFG_RX_DEFAULT); + ret = regmap_write(data->regmap, MAX44000_REG_CFG_RX, + MAX44000_REG_CFG_RX_DEFAULT); + if (ret < 0) { + dev_err(&client->dev, "failed to write default CFG_RX: %d\n", + ret); + return ret; + } + + /* + * By default the LED pulse used for the proximity sensor is disabled. + * Set a middle value so that we get some sort of valid data by default. + */ + ret = max44000_write_led_current_raw(data, MAX44000_LED_CURRENT_DEFAULT); if (ret < 0) { - dev_err(&client->dev, "failed to write default CFG_RX: %d\n", ret); + dev_err(&client->dev, "failed to write init config: %d\n", ret); return ret; } - /* Reset CFG bits to ALS-only mode and no interrupts */ - reg = MAX44000_CFG_TRIM | MAX44000_CFG_MODE_ALS_GIR; + /* Reset CFG bits to ALS_PRX mode which allows easy reading of both values. */ + reg = MAX44000_CFG_TRIM | MAX44000_CFG_MODE_ALS_PRX; ret = regmap_write(data->regmap, MAX44000_REG_CFG_MAIN, reg); if (ret < 0) { dev_err(&client->dev, "failed to write init config: %d\n", ret); -- GitLab From 237a378b3bde0b3c1d1c47f7a3982c86a6728cdf Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Mon, 18 Apr 2016 17:31:55 +0300 Subject: [PATCH 4072/9938] max44000: Support controlling LED current output This is exposed as an output channel with "led" as an extend_name. Other sensors also have support for controlling an external LED. It's not clear that simply exposing an undecorated output channel is the correct approach. Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/light/max44000.c | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index 4bce7e152f9c..f0f1a8a6c615 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -85,6 +85,13 @@ static const struct iio_chan_spec max44000_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), }, + { + .type = IIO_CURRENT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .extend_name = "led", + .output = 1, + }, }; static int max44000_read_alsval(struct max44000_data *data) @@ -125,6 +132,20 @@ static int max44000_write_led_current_raw(struct max44000_data *data, int val) MAX44000_LED_CURRENT_MASK, val); } +static int max44000_read_led_current_raw(struct max44000_data *data) +{ + unsigned int regval; + int ret; + + ret = regmap_read(data->regmap, MAX44000_REG_CFG_TX, ®val); + if (ret < 0) + return ret; + regval &= MAX44000_LED_CURRENT_MASK; + if (regval >= 8) + regval -= 4; + return regval; +} + static int max44000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -154,12 +175,26 @@ static int max44000_read_raw(struct iio_dev *indio_dev, *val = regval; return IIO_VAL_INT; + case IIO_CURRENT: + mutex_lock(&data->lock); + ret = max44000_read_led_current_raw(data); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + default: return -EINVAL; } case IIO_CHAN_INFO_SCALE: switch (chan->type) { + case IIO_CURRENT: + /* Output register is in 10s of miliamps */ + *val = 10; + return IIO_VAL_INT; + case IIO_LIGHT: *val = 1; *val2 = MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2; @@ -174,9 +209,27 @@ static int max44000_read_raw(struct iio_dev *indio_dev, } } +static int max44000_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct max44000_data *data = iio_priv(indio_dev); + int ret; + + if (mask == IIO_CHAN_INFO_RAW && chan->type == IIO_CURRENT) { + mutex_lock(&data->lock); + ret = max44000_write_led_current_raw(data, val); + mutex_unlock(&data->lock); + return ret; + } + + return -EINVAL; +} + static const struct iio_info max44000_info = { .driver_module = THIS_MODULE, .read_raw = max44000_read_raw, + .write_raw = max44000_write_raw, }; static bool max44000_readable_reg(struct device *dev, unsigned int reg) -- GitLab From d5d8f49b634520a98337fd413eef86da4e63e4fd Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Mon, 18 Apr 2016 17:31:56 +0300 Subject: [PATCH 4073/9938] max44000: Expose ambient sensor scaling This patch exposes ALSTIM as illuminance_integration_time and ALSPGA as illuminance_scale. Changing ALSTIM also changes the number of bits available in the data register. This is handled inside raw value reading because: * It's very easy to shift a few bits * It allows SCALE and INT_TIME to be completely independent controls * Buffer support requires constant scan_type.realbits per-channel Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/light/max44000.c | 167 +++++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 5 deletions(-) diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index f0f1a8a6c615..05e11698201a 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -59,6 +59,12 @@ */ #define MAX44000_REG_CFG_RX_DEFAULT 0xf0 +/* REG_RX bits */ +#define MAX44000_CFG_RX_ALSTIM_MASK 0x0c +#define MAX44000_CFG_RX_ALSTIM_SHIFT 2 +#define MAX44000_CFG_RX_ALSPGA_MASK 0x03 +#define MAX44000_CFG_RX_ALSPGA_SHIFT 0 + /* REG_TX bits */ #define MAX44000_LED_CURRENT_MASK 0xf #define MAX44000_LED_CURRENT_MAX 11 @@ -74,11 +80,57 @@ struct max44000_data { /* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */ #define MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2 5 +/* Scale can be multiplied by up to 128x via ALSPGA for measurement gain */ +static const int max44000_alspga_shift[] = {0, 2, 4, 7}; +#define MAX44000_ALSPGA_MAX_SHIFT 7 + +/* + * Scale can be multiplied by up to 64x via ALSTIM because of lost resolution + * + * This scaling factor is hidden from userspace and instead accounted for when + * reading raw values from the device. + * + * This makes it possible to cleanly expose ALSPGA as IIO_CHAN_INFO_SCALE and + * ALSTIM as IIO_CHAN_INFO_INT_TIME without the values affecting each other. + * + * Handling this internally is also required for buffer support because the + * channel's scan_type can't be modified dynamically. + */ +static const int max44000_alstim_shift[] = {0, 2, 4, 6}; +#define MAX44000_ALSTIM_SHIFT(alstim) (2 * (alstim)) + +/* Available integration times with pretty manual alignment: */ +static const int max44000_int_time_avail_ns_array[] = { + 100000000, + 25000000, + 6250000, + 1562500, +}; +static const char max44000_int_time_avail_str[] = + "0.100 " + "0.025 " + "0.00625 " + "0.001625"; + +/* Available scales (internal to ulux) with pretty manual alignment: */ +static const int max44000_scale_avail_ulux_array[] = { + 31250, + 125000, + 500000, + 4000000, +}; +static const char max44000_scale_avail_str[] = + "0.03125 " + "0.125 " + "0.5 " + "4"; + static const struct iio_chan_spec max44000_channels[] = { { .type = IIO_LIGHT, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_INT_TIME), }, { .type = IIO_PROXIMITY, @@ -94,15 +146,54 @@ static const struct iio_chan_spec max44000_channels[] = { }, }; +static int max44000_read_alstim(struct max44000_data *data) +{ + unsigned int val; + int ret; + + ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val); + if (ret < 0) + return ret; + return (val & MAX44000_CFG_RX_ALSTIM_MASK) >> MAX44000_CFG_RX_ALSTIM_SHIFT; +} + +static int max44000_write_alstim(struct max44000_data *data, int val) +{ + return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX, + MAX44000_CFG_RX_ALSTIM_MASK, + val << MAX44000_CFG_RX_ALSTIM_SHIFT); +} + +static int max44000_read_alspga(struct max44000_data *data) +{ + unsigned int val; + int ret; + + ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val); + if (ret < 0) + return ret; + return (val & MAX44000_CFG_RX_ALSPGA_MASK) >> MAX44000_CFG_RX_ALSPGA_SHIFT; +} + +static int max44000_write_alspga(struct max44000_data *data, int val) +{ + return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX, + MAX44000_CFG_RX_ALSPGA_MASK, + val << MAX44000_CFG_RX_ALSPGA_SHIFT); +} + static int max44000_read_alsval(struct max44000_data *data) { u16 regval; - int ret; + int alstim, ret; ret = regmap_bulk_read(data->regmap, MAX44000_REG_ALS_DATA_HI, ®val, sizeof(regval)); if (ret < 0) return ret; + alstim = ret = max44000_read_alstim(data); + if (ret < 0) + return ret; regval = be16_to_cpu(regval); @@ -118,7 +209,7 @@ static int max44000_read_alsval(struct max44000_data *data) if (regval & MAX44000_ALSDATA_OVERFLOW) return 0x3FFF; - return regval; + return regval << MAX44000_ALSTIM_SHIFT(alstim); } static int max44000_write_led_current_raw(struct max44000_data *data, int val) @@ -151,6 +242,7 @@ static int max44000_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct max44000_data *data = iio_priv(indio_dev); + int alstim, alspga; unsigned int regval; int ret; @@ -196,14 +288,34 @@ static int max44000_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_LIGHT: - *val = 1; - *val2 = MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2; + mutex_lock(&data->lock); + alspga = ret = max44000_read_alspga(data); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + + /* Avoid negative shifts */ + *val = (1 << MAX44000_ALSPGA_MAX_SHIFT); + *val2 = MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2 + + MAX44000_ALSPGA_MAX_SHIFT + - max44000_alspga_shift[alspga]; return IIO_VAL_FRACTIONAL_LOG2; default: return -EINVAL; } + case IIO_CHAN_INFO_INT_TIME: + mutex_lock(&data->lock); + alstim = ret = max44000_read_alstim(data); + mutex_unlock(&data->lock); + + if (ret < 0) + return ret; + *val = 0; + *val2 = max44000_int_time_avail_ns_array[alstim]; + return IIO_VAL_INT_PLUS_NANO; + default: return -EINVAL; } @@ -221,15 +333,60 @@ static int max44000_write_raw(struct iio_dev *indio_dev, ret = max44000_write_led_current_raw(data, val); mutex_unlock(&data->lock); return ret; + } else if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) { + s64 valns = val * NSEC_PER_SEC + val2; + int alstim = find_closest_descending(valns, + max44000_int_time_avail_ns_array, + ARRAY_SIZE(max44000_int_time_avail_ns_array)); + mutex_lock(&data->lock); + ret = max44000_write_alstim(data, alstim); + mutex_unlock(&data->lock); + return ret; + } else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT) { + s64 valus = val * USEC_PER_SEC + val2; + int alspga = find_closest(valus, + max44000_scale_avail_ulux_array, + ARRAY_SIZE(max44000_scale_avail_ulux_array)); + mutex_lock(&data->lock); + ret = max44000_write_alspga(data, alspga); + mutex_unlock(&data->lock); + return ret; } return -EINVAL; } +static int max44000_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) + return IIO_VAL_INT_PLUS_NANO; + else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT) + return IIO_VAL_INT_PLUS_MICRO; + else + return IIO_VAL_INT; +} + +static IIO_CONST_ATTR(illuminance_integration_time_available, max44000_int_time_avail_str); +static IIO_CONST_ATTR(illuminance_scale_available, max44000_scale_avail_str); + +static struct attribute *max44000_attributes[] = { + &iio_const_attr_illuminance_integration_time_available.dev_attr.attr, + &iio_const_attr_illuminance_scale_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group max44000_attribute_group = { + .attrs = max44000_attributes, +}; + static const struct iio_info max44000_info = { .driver_module = THIS_MODULE, .read_raw = max44000_read_raw, .write_raw = max44000_write_raw, + .write_raw_get_fmt = max44000_write_raw_get_fmt, + .attrs = &max44000_attribute_group, }; static bool max44000_readable_reg(struct device *dev, unsigned int reg) -- GitLab From 06ad7ea10e2bcf70a602e504ea32ee6ef6d77aa9 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Mon, 18 Apr 2016 17:31:57 +0300 Subject: [PATCH 4074/9938] max44000: Initial triggered buffer support Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/light/max44000.c | 62 ++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index 05e11698201a..e01e58a9bd14 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include #define MAX44000_DRV_NAME "max44000" @@ -125,24 +128,41 @@ static const char max44000_scale_avail_str[] = "0.5 " "4"; +#define MAX44000_SCAN_INDEX_ALS 0 +#define MAX44000_SCAN_INDEX_PRX 1 + static const struct iio_chan_spec max44000_channels[] = { { .type = IIO_LIGHT, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_INT_TIME), + .scan_index = MAX44000_SCAN_INDEX_ALS, + .scan_type = { + .sign = 'u', + .realbits = 14, + .storagebits = 16, + } }, { .type = IIO_PROXIMITY, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .scan_index = MAX44000_SCAN_INDEX_PRX, + .scan_type = { + .sign = 'u', + .realbits = 8, + .storagebits = 16, + } }, + IIO_CHAN_SOFT_TIMESTAMP(2), { .type = IIO_CURRENT, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .extend_name = "led", .output = 1, + .scan_index = -1, }, }; @@ -467,6 +487,41 @@ static const struct regmap_config max44000_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static irqreturn_t max44000_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct max44000_data *data = iio_priv(indio_dev); + u16 buf[8]; /* 2x u16 + padding + 8 bytes timestamp */ + int index = 0; + unsigned int regval; + int ret; + + mutex_lock(&data->lock); + if (test_bit(MAX44000_SCAN_INDEX_ALS, indio_dev->active_scan_mask)) { + ret = max44000_read_alsval(data); + if (ret < 0) + goto out_unlock; + buf[index++] = ret; + } + if (test_bit(MAX44000_SCAN_INDEX_PRX, indio_dev->active_scan_mask)) { + ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, ®val); + if (ret < 0) + goto out_unlock; + buf[index] = regval; + } + mutex_unlock(&data->lock); + + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; + +out_unlock: + mutex_unlock(&data->lock); + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + static int max44000_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -534,6 +589,12 @@ static int max44000_probe(struct i2c_client *client, return ret; } + ret = iio_triggered_buffer_setup(indio_dev, NULL, max44000_trigger_handler, NULL); + if (ret < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + return ret; + } + return iio_device_register(indio_dev); } @@ -542,6 +603,7 @@ static int max44000_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); return 0; } -- GitLab From b51e13faf73fcc799a41ed085069f07203d8e7b7 Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Tue, 19 Apr 2016 22:50:47 -0700 Subject: [PATCH 4075/9938] tcp: Carry txstamp_ack in tcp_fragment_tstamp When a tcp skb is sliced into two smaller skbs (e.g. in tcp_fragment() and tso_fragment()), it does not carry the txstamp_ack bit to the newly created skb if it is needed. The end result is a timestamping event (SCM_TSTAMP_ACK) will be missing from the sk->sk_error_queue. This patch carries this bit to the new skb2 in tcp_fragment_tstamp(). BPF Output Before: ~~~~~~ BPF Output After: ~~~~~~ <...>-2050 [000] d.s. 100.928763: : ee_data:14599 Packetdrill Script: ~~~~~~ +0 `sysctl -q -w net.ipv4.tcp_min_tso_segs=10` +0 `sysctl -q -w net.ipv4.tcp_no_metrics_save=1` +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0 bind(3, ..., ...) = 0 +0 listen(3, 1) = 0 0.100 < S 0:0(0) win 32792 0.100 > S. 0:0(0) ack 1 0.200 < . 1:1(0) ack 1 win 257 0.200 accept(3, ..., ...) = 4 +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0 +0 setsockopt(4, SOL_SOCKET, 37, [2688], 4) = 0 0.200 write(4, ..., 14600) = 14600 +0 setsockopt(4, SOL_SOCKET, 37, [2176], 4) = 0 0.200 > . 1:7301(7300) ack 1 0.200 > P. 7301:14601(7300) ack 1 0.300 < . 1:1(0) ack 14601 win 257 0.300 close(4) = 0 0.300 > F. 14601:14601(0) ack 1 0.400 < F. 1:1(0) ack 16062 win 257 0.400 > . 14602:14602(0) ack 2 Signed-off-by: Martin KaFai Lau Cc: Eric Dumazet Cc: Neal Cardwell Cc: Soheil Hassas Yeganeh Cc: Willem de Bruijn Cc: Yuchung Cheng Acked-by: Soheil Hassas Yeganeh Tested-by: Soheil Hassas Yeganeh Acked-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 96182a2aabc9..f7c3bc053d27 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1123,6 +1123,8 @@ static void tcp_fragment_tstamp(struct sk_buff *skb, struct sk_buff *skb2) shinfo->tx_flags &= ~tsflags; shinfo2->tx_flags |= tsflags; swap(shinfo->tskey, shinfo2->tskey); + TCP_SKB_CB(skb2)->txstamp_ack = TCP_SKB_CB(skb)->txstamp_ack; + TCP_SKB_CB(skb)->txstamp_ack = 0; } } -- GitLab From 2de8023e7bb288e0bfbe0325a7690d32dc670873 Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Tue, 19 Apr 2016 22:50:48 -0700 Subject: [PATCH 4076/9938] tcp: Merge txstamp_ack in tcp_skb_collapse_tstamp When collapsing skbs, txstamp_ack also needs to be merged. Retrans Collapse Test: ~~~~~~ 0.200 accept(3, ..., ...) = 4 +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0 0.200 write(4, ..., 730) = 730 +0 setsockopt(4, SOL_SOCKET, 37, [2688], 4) = 0 0.200 write(4, ..., 730) = 730 +0 setsockopt(4, SOL_SOCKET, 37, [2176], 4) = 0 0.200 write(4, ..., 11680) = 11680 0.200 > P. 1:731(730) ack 1 0.200 > P. 731:1461(730) ack 1 0.200 > . 1461:8761(7300) ack 1 0.200 > P. 8761:13141(4380) ack 1 0.300 < . 1:1(0) ack 1 win 257 0.300 < . 1:1(0) ack 1 win 257 0.300 < . 1:1(0) ack 1 win 257 0.300 > P. 1:1461(1460) ack 1 0.400 < . 1:1(0) ack 13141 win 257 BPF Output Before: ~~~~~ BPF Output After: ~~~~~ <...>-2027 [007] d.s. 79.765921: : ee_data:1459 Sacks Collapse Test: ~~~~~ 0.200 accept(3, ..., ...) = 4 +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0 0.200 write(4, ..., 1460) = 1460 +0 setsockopt(4, SOL_SOCKET, 37, [2688], 4) = 0 0.200 write(4, ..., 13140) = 13140 +0 setsockopt(4, SOL_SOCKET, 37, [2176], 4) = 0 0.200 > P. 1:1461(1460) ack 1 0.200 > . 1461:8761(7300) ack 1 0.200 > P. 8761:14601(5840) ack 1 0.300 < . 1:1(0) ack 1 win 257 0.300 > P. 1:1461(1460) ack 1 0.400 < . 1:1(0) ack 14601 win 257 BPF Output Before: ~~~~~ BPF Output After: ~~~~~ <...>-2049 [007] d.s. 89.185538: : ee_data:14599 Signed-off-by: Martin KaFai Lau Cc: Eric Dumazet Cc: Neal Cardwell Cc: Soheil Hassas Yeganeh Cc: Willem de Bruijn Cc: Yuchung Cheng Acked-by: Soheil Hassas Yeganeh Tested-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f7c3bc053d27..a6e4a8353b02 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2454,6 +2454,8 @@ void tcp_skb_collapse_tstamp(struct sk_buff *skb, shinfo->tx_flags |= tsflags; shinfo->tskey = next_shinfo->tskey; + TCP_SKB_CB(skb)->txstamp_ack |= + TCP_SKB_CB(next_skb)->txstamp_ack; } } -- GitLab From 8cee83dd29dea4e7d27fda3b170381059f628868 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Thu, 21 Apr 2016 15:51:13 +0200 Subject: [PATCH 4077/9938] tipc: fix stale links after re-enabling bearer Commit 42b18f605fea ("tipc: refactor function tipc_link_timeout()"), introduced a bug which prevents sending of probe messages during link synchronization phase. This leads to hanging links, if the bearer is disabled/enabled after links are up. In this commit, we send the probe messages correctly. Fixes: 42b18f605fea ("tipc: refactor function tipc_link_timeout()") Acked-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/link.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 2e28a7d7e802..7059c94f33c5 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -721,8 +721,7 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) mtyp = STATE_MSG; state = bc_acked != bc_snt; probe = l->silent_intv_cnt; - if (probe) - l->silent_intv_cnt++; + l->silent_intv_cnt++; break; case LINK_RESET: setup = l->rst_cnt++ <= 4; -- GitLab From 10d3be569243def8d92ac3722395ef5a59c504e6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 21 Apr 2016 10:55:23 -0700 Subject: [PATCH 4078/9938] tcp-tso: do not split TSO packets at retransmit time Linux TCP stack painfully segments all TSO/GSO packets before retransmits. This was fine back in the days when TSO/GSO were emerging, with their bugs, but we believe the dark age is over. Keeping big packets in write queues, but also in stack traversal has a lot of benefits. - Less memory overhead, because write queues have less skbs - Less cpu overhead at ACK processing. - Better SACK processing, as lot of studies mentioned how awful linux was at this ;) - Less cpu overhead to send the rtx packets (IP stack traversal, netfilter traversal, drivers...) - Better latencies in presence of losses. - Smaller spikes in fq like packet schedulers, as retransmits are not constrained by TCP Small Queues. 1 % packet losses are common today, and at 100Gbit speeds, this translates to ~80,000 losses per second. Losses are often correlated, and we see many retransmit events leading to 1-MSS train of packets, at the time hosts are already under stress. Signed-off-by: Eric Dumazet Acked-by: Yuchung Cheng Signed-off-by: David S. Miller --- include/net/tcp.h | 4 +-- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_output.c | 64 ++++++++++++++++++++----------------------- net/ipv4/tcp_timer.c | 4 +-- 4 files changed, 34 insertions(+), 40 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index c0ef0544dfcf..7f2553da10d1 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -538,8 +538,8 @@ __u32 cookie_v6_init_sequence(const struct sk_buff *skb, __u16 *mss); void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, int nonagle); bool tcp_may_send_now(struct sock *sk); -int __tcp_retransmit_skb(struct sock *, struct sk_buff *); -int tcp_retransmit_skb(struct sock *, struct sk_buff *); +int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs); +int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs); void tcp_retransmit_timer(struct sock *sk); void tcp_xmit_retransmit_queue(struct sock *); void tcp_simple_retransmit(struct sock *); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 75e8336f6ecd..dcad8f9f96eb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5545,7 +5545,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, if (data) { /* Retransmit unacked data in SYN */ tcp_for_write_queue_from(data, sk) { if (data == tcp_send_head(sk) || - __tcp_retransmit_skb(sk, data)) + __tcp_retransmit_skb(sk, data, 1)) break; } tcp_rearm_rto(sk); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a6e4a8353b02..9d3b4b364652 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2268,7 +2268,7 @@ void tcp_send_loss_probe(struct sock *sk) if (WARN_ON(!skb || !tcp_skb_pcount(skb))) goto rearm_timer; - if (__tcp_retransmit_skb(sk, skb)) + if (__tcp_retransmit_skb(sk, skb, 1)) goto rearm_timer; /* Record snd_nxt for loss detection. */ @@ -2571,17 +2571,17 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to, * state updates are done by the caller. Returns non-zero if an * error occurred which prevented the send. */ -int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) +int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) { - struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); + struct tcp_sock *tp = tcp_sk(sk); unsigned int cur_mss; - int err; + int diff, len, err; + - /* Inconslusive MTU probe */ - if (icsk->icsk_mtup.probe_size) { + /* Inconclusive MTU probe */ + if (icsk->icsk_mtup.probe_size) icsk->icsk_mtup.probe_size = 0; - } /* Do not sent more than we queued. 1/4 is reserved for possible * copying overhead: fragmentation, tunneling, mangling etc. @@ -2614,30 +2614,27 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) TCP_SKB_CB(skb)->seq != tp->snd_una) return -EAGAIN; - if (skb->len > cur_mss) { - if (tcp_fragment(sk, skb, cur_mss, cur_mss, GFP_ATOMIC)) + len = cur_mss * segs; + if (skb->len > len) { + if (tcp_fragment(sk, skb, len, cur_mss, GFP_ATOMIC)) return -ENOMEM; /* We'll try again later. */ } else { - int oldpcount = tcp_skb_pcount(skb); + if (skb_unclone(skb, GFP_ATOMIC)) + return -ENOMEM; - if (unlikely(oldpcount > 1)) { - if (skb_unclone(skb, GFP_ATOMIC)) - return -ENOMEM; - tcp_init_tso_segs(skb, cur_mss); - tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb)); - } + diff = tcp_skb_pcount(skb); + tcp_set_skb_tso_segs(skb, cur_mss); + diff -= tcp_skb_pcount(skb); + if (diff) + tcp_adjust_pcount(sk, skb, diff); + if (skb->len < cur_mss) + tcp_retrans_try_collapse(sk, skb, cur_mss); } /* RFC3168, section 6.1.1.1. ECN fallback */ if ((TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN_ECN) == TCPHDR_SYN_ECN) tcp_ecn_clear_syn(sk, skb); - tcp_retrans_try_collapse(sk, skb, cur_mss); - - /* Make a copy, if the first transmission SKB clone we made - * is still in somebody's hands, else make a clone. - */ - /* make sure skb->data is aligned on arches that require it * and check if ack-trimming & collapsing extended the headroom * beyond what csum_start can cover. @@ -2653,20 +2650,22 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) } if (likely(!err)) { + segs = tcp_skb_pcount(skb); + TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS; /* Update global TCP statistics. */ - TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS); + TCP_ADD_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS, segs); if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); - tp->total_retrans++; + tp->total_retrans += segs; } return err; } -int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) +int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) { struct tcp_sock *tp = tcp_sk(sk); - int err = __tcp_retransmit_skb(sk, skb); + int err = __tcp_retransmit_skb(sk, skb, segs); if (err == 0) { #if FASTRETRANS_DEBUG > 0 @@ -2757,6 +2756,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk) tcp_for_write_queue_from(skb, sk) { __u8 sacked = TCP_SKB_CB(skb)->sacked; + int segs; if (skb == tcp_send_head(sk)) break; @@ -2764,14 +2764,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk) if (!hole) tp->retransmit_skb_hint = skb; - /* Assume this retransmit will generate - * only one packet for congestion window - * calculation purposes. This works because - * tcp_retransmit_skb() will chop up the - * packet to be MSS sized and all the - * packet counting works out. - */ - if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) + segs = tp->snd_cwnd - tcp_packets_in_flight(tp); + if (segs <= 0) return; if (fwd_rexmitting) { @@ -2808,7 +2802,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk) if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) continue; - if (tcp_retransmit_skb(sk, skb)) + if (tcp_retransmit_skb(sk, skb, segs)) return; NET_INC_STATS_BH(sock_net(sk), mib_idx); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 49bc474f8e35..373b03e78aaa 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -404,7 +404,7 @@ void tcp_retransmit_timer(struct sock *sk) goto out; } tcp_enter_loss(sk); - tcp_retransmit_skb(sk, tcp_write_queue_head(sk)); + tcp_retransmit_skb(sk, tcp_write_queue_head(sk), 1); __sk_dst_reset(sk); goto out_reset_timer; } @@ -436,7 +436,7 @@ void tcp_retransmit_timer(struct sock *sk) tcp_enter_loss(sk); - if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk)) > 0) { + if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk), 1) > 0) { /* Retransmission failed because of local congestion, * do not backoff. */ -- GitLab From afc34be05331962c2326c24bd0b47baff193b659 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 24 Mar 2016 20:59:16 +0200 Subject: [PATCH 4079/9938] i2c: dln2: Pass forward ACPI companion Share the ACPI companion for the platform device with the i2c adapter, so that the adapter has access to the properties defined in ACPI tables. Signed-off-by: Irina Tirdea Acked-by: Mika Westerberg Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-dln2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c index 1600edd57ce9..f2eb4f76591f 100644 --- a/drivers/i2c/busses/i2c-dln2.c +++ b/drivers/i2c/busses/i2c-dln2.c @@ -19,6 +19,7 @@ #include #include #include +#include #define DLN2_I2C_MODULE_ID 0x03 #define DLN2_I2C_CMD(cmd) DLN2_CMD(cmd, DLN2_I2C_MODULE_ID) @@ -210,6 +211,7 @@ static int dln2_i2c_probe(struct platform_device *pdev) dln2->adapter.algo = &dln2_i2c_usb_algorithm; dln2->adapter.quirks = &dln2_i2c_quirks; dln2->adapter.dev.parent = dev; + ACPI_COMPANION_SET(&dln2->adapter.dev, ACPI_COMPANION(&pdev->dev)); dln2->adapter.dev.of_node = dev->of_node; i2c_set_adapdata(&dln2->adapter, dln2); snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d", -- GitLab From 126a66caec4a00b8d66dbc3174b0efa905cf68c3 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 4 Apr 2016 16:55:23 +0300 Subject: [PATCH 4080/9938] i2c: omap: drop the lock hard irq context The lock is taken while reading two registers. On RT the first lock is taken in hard irq where it might sleep and in the threaded irq. The threaded irq runs in oneshot mode so the hard irq does not run until the thread the completes so there is no reason to grab the lock. Signed-off-by: Sebastian Andrzej Siewior [grygorii.strashko@ti.com: drop locking from isr completely and remove lock field from struct omap_i2c_dev] Signed-off-by: Grygorii Strashko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 13c45296ce5b..ab1279b8e240 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -185,7 +185,6 @@ enum { #define OMAP_I2C_IP_V2_INTERRUPTS_MASK 0x6FFF struct omap_i2c_dev { - spinlock_t lock; /* IRQ synchronization */ struct device *dev; void __iomem *base; /* virtual */ int irq; @@ -995,15 +994,12 @@ omap_i2c_isr(int irq, void *dev_id) u16 mask; u16 stat; - spin_lock(&omap->lock); - mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG); stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG); + mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG); if (stat & mask) ret = IRQ_WAKE_THREAD; - spin_unlock(&omap->lock); - return ret; } @@ -1011,12 +1007,10 @@ static irqreturn_t omap_i2c_isr_thread(int this_irq, void *dev_id) { struct omap_i2c_dev *omap = dev_id; - unsigned long flags; u16 bits; u16 stat; int err = 0, count = 0; - spin_lock_irqsave(&omap->lock, flags); do { bits = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG); stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG); @@ -1142,8 +1136,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) omap_i2c_complete_cmd(omap, err); out: - spin_unlock_irqrestore(&omap->lock, flags); - return IRQ_HANDLED; } @@ -1330,8 +1322,6 @@ omap_i2c_probe(struct platform_device *pdev) omap->dev = &pdev->dev; omap->irq = irq; - spin_lock_init(&omap->lock); - platform_set_drvdata(pdev, omap); init_completion(&omap->cmd_complete); -- GitLab From 98b32a9b041bff987454db944eb4ece4d780be11 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 17 Apr 2016 08:44:47 +0200 Subject: [PATCH 4081/9938] dt-bindings: add vendor-prefix for mqmaker Add vendor-prefix for Shenzen-based mqmaker Inc. Signed-off-by: Heiko Stuebner Acked-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 86740d4a270d..5f6db11b1b94 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -152,6 +152,7 @@ mitsubishi Mitsubishi Electric Corporation mosaixtech Mosaix Technologies, Inc. moxa Moxa mpl MPL AG +mqmaker mqmaker Inc. msi Micro-Star International Co. Ltd. mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.) mundoreader Mundo Reader S.L. -- GitLab From 162718cb1a76f75d76e4b335034e341e8b656a5c Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 18 Apr 2016 00:44:03 +0200 Subject: [PATCH 4082/9938] ARM: dts: rockchip: add MiQi board from mqmaker The MiQi is a rk3288-based devboard from Shenzen based mqmaker, with a footprint the size of a credit card. Main available outside connections are 4 usb ports, hdmi, gigabit ethernet and two expansion headers. Signed-off-by: Heiko Stuebner --- .../devicetree/bindings/arm/rockchip.txt | 4 + arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rk3288-miqi.dts | 472 ++++++++++++++++++ 3 files changed, 477 insertions(+) create mode 100644 arch/arm/boot/dts/rk3288-miqi.dts diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt index 078c14fcdaaa..585496f203df 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.txt +++ b/Documentation/devicetree/bindings/arm/rockchip.txt @@ -87,6 +87,10 @@ Rockchip platforms device tree bindings "google,veyron-speedy-rev3", "google,veyron-speedy-rev2", "google,veyron-speedy", "google,veyron", "rockchip,rk3288"; +- mqmaker MiQi: + Required root node properties: + - compatible = "mqmaker,miqi", "rockchip,rk3288"; + - Rockchip RK3368 evb: Required root node properties: - compatible = "rockchip,rk3368-evb-act8846", "rockchip,rk3368"; diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..3d54cb5a0749 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -565,6 +565,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-evb-rk808.dtb \ rk3288-firefly-beta.dtb \ rk3288-firefly.dtb \ + rk3288-miqi.dtb \ rk3288-popmetal.dtb \ rk3288-r89.dtb \ rk3288-rock2-square.dtb \ diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts new file mode 100644 index 000000000000..8643103d8cd8 --- /dev/null +++ b/arch/arm/boot/dts/rk3288-miqi.dts @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2016 Heiko Stuebner + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include +#include "rk3288.dtsi" + +/ { + model = "mqmaker MiQi"; + compatible = "mqmaker,miqi", "rockchip,rk3288"; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0 0x80000000>; + }; + + ext_gmac: external-gmac-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "ext_gmac"; + }; + + io_domains: io-domains { + compatible = "rockchip,rk3288-io-voltage-domain"; + + audio-supply = <&vcca_33>; + flash0-supply = <&vcc_flash>; + flash1-supply = <&vcc_lan>; + gpio30-supply = <&vcc_io>; + gpio1830-supply = <&vcc_io>; + lcdc-supply = <&vcc_io>; + sdcard-supply = <&vccio_sd>; + wifi-supply = <&vcc_18>; + }; + + leds { + compatible = "gpio-leds"; + + work { + gpios = <&gpio7 4 GPIO_ACTIVE_LOW>; + label = "miqi:green:user"; + linux,default-trigger = "default-on"; + pinctrl-names = "default"; + pinctrl-0 = <&led_ctl>; + }; + }; + + vcc_flash: flash-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_flash"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_io>; + }; + + vcc_host: usb-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 14 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio7 11 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwr>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + vin-supply = <&vcc_io>; + }; + + vcc_sys: vsys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&cpu0 { + cpu0-supply = <&vdd_cpu>; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + disable-wp; + non-removable; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_pwr>, <&emmc_bus8>; + vmmc-supply = <&vcc_io>; + vqmmc-supply = <&vcc_flash>; + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + clock_in_out = "input"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>; + phy-supply = <&vcc_lan>; + phy-mode = "rgmii"; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 1000000>; + snps,reset-gpio = <&gpio4 8 GPIO_ACTIVE_LOW>; + tx_delay = <0x30>; + rx_delay = <0x10>; + status = "ok"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c5>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + status = "okay"; + + vdd_cpu: syr827@40 { + compatible = "silergy,syr827"; + fcs,suspend-voltage-selector = <1>; + reg = <0x40>; + regulator-name = "vdd_cpu"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + regulator-enable-ramp-delay = <300>; + regulator-ramp-delay = <8000>; + vin-supply = <&vcc_sys>; + }; + + vdd_gpu: syr828@41 { + compatible = "silergy,syr828"; + fcs,suspend-voltage-selector = <1>; + reg = <0x41>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "xin32k"; + }; + + act8846: act8846@5a { + compatible = "active-semi,act8846"; + reg = <0x5a>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_vsel>; + system-power-controller; + + vp1-supply = <&vcc_sys>; + vp2-supply = <&vcc_sys>; + vp3-supply = <&vcc_sys>; + vp4-supply = <&vcc_sys>; + inl1-supply = <&vcc_sys>; + inl2-supply = <&vcc_sys>; + inl3-supply = <&vcc_20>; + + regulators { + vcc_ddr: REG1 { + regulator-name = "vcc_ddr"; + regulator-always-on; + }; + + vcc_io: REG2 { + regulator-name = "vcc_io"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdd_log: REG3 { + regulator-name = "vdd_log"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + vcc_20: REG4 { + regulator-name = "vcc_20"; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-always-on; + }; + + vccio_sd: REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdd10_lcd: REG6 { + regulator-name = "vdd10_lcd"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + vcca_18: REG7 { + regulator-name = "vcca_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vcca_33: REG8 { + regulator-name = "vcca_33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc_lan: REG9 { + regulator-name = "vcc_lan"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_10: REG10 { + regulator-name = "vdd_10"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + vcc_18: REG11 { + regulator-name = "vcc_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vcc18_lcd: REG12 { + regulator-name = "vcc18_lcd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&pinctrl { + pcfg_output_high: pcfg-output-high { + output-high; + }; + + pcfg_output_low: pcfg-output-low { + output-low; + }; + + pcfg_pull_up_drv_12ma: pcfg-pull-up-drv-12ma { + bias-pull-up; + drive-strength = <12>; + }; + + act8846 { + pmic_int: pmic-int { + rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + pmic_sleep: pmic-sleep { + rockchip,pins = <0 0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + pmic_vsel: pmic-vsel { + rockchip,pins = <7 1 RK_FUNC_GPIO &pcfg_output_low>; + }; + }; + + gmac { + phy_int: phy-int { + rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + phy_pmeb: phy-pmeb { + rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + phy_rst: phy-rst { + rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>; + }; + }; + + leds { + led_ctl: led-ctl { + rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdmmc { + /* + * Default drive strength isn't enough to achieve even + * high-speed mode on firefly board so bump up to 12ma. + */ + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_12ma>, + <6 17 RK_FUNC_1 &pcfg_pull_up_drv_12ma>, + <6 18 RK_FUNC_1 &pcfg_pull_up_drv_12ma>, + <6 19 RK_FUNC_1 &pcfg_pull_up_drv_12ma>; + }; + + sdmmc_clk: sdmmc-clk { + rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_12ma>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_12ma>; + }; + + sdmmc_pwr: sdmmc-pwr { + rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb_host { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&saradc { + vref-supply = <&vcc_18>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <200>; + disable-wp; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; + +&usb_host1 { + status = "okay"; +}; + +&usb_otg { + /* + * The otg controller is the only system power source, + * so needs to always stay in device mode. + */ + dr_mode = "peripheral"; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; -- GitLab From 2c89e5d88473429eec62de12f5ae6642cf6a02a5 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 22 Apr 2016 15:44:07 +0200 Subject: [PATCH 4083/9938] i2c: mux: pinctrl: fix indentation for better readability smatch rightfully says: drivers/i2c/muxes/i2c-mux-pinctrl.c:175 i2c_mux_pinctrl_probe() warn: inconsistent indenting Signed-off-by: Wolfram Sang Acked-by: Peter Rosin Signed-off-by: Wolfram Sang --- drivers/i2c/muxes/i2c-mux-pinctrl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 1b8dc711815e..f4e62f4a50cc 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -172,13 +172,13 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < mux->pdata->bus_count; i++) { mux->states[i] = pinctrl_lookup_state(mux->pinctrl, mux->pdata->pinctrl_states[i]); - if (IS_ERR(mux->states[i])) { - ret = PTR_ERR(mux->states[i]); - dev_err(&pdev->dev, - "Cannot look up pinctrl state %s: %d\n", - mux->pdata->pinctrl_states[i], ret); - goto err; - } + if (IS_ERR(mux->states[i])) { + ret = PTR_ERR(mux->states[i]); + dev_err(&pdev->dev, + "Cannot look up pinctrl state %s: %d\n", + mux->pdata->pinctrl_states[i], ret); + goto err; + } } if (mux->pdata->pinctrl_state_idle) { mux->state_idle = pinctrl_lookup_state(mux->pinctrl, -- GitLab From d4644becf86c710298a4af86f463c79375a21f21 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 14 Apr 2016 09:08:04 +0800 Subject: [PATCH 4084/9938] i2c: exynos5: Use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS instead of open-coded Use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS to simplify the code. Signed-off-by: Axel Lin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-exynos5.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index b29c7500461a..8710052eeb6b 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -847,14 +847,8 @@ static int exynos5_i2c_resume_noirq(struct device *dev) #endif static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = { -#ifdef CONFIG_PM_SLEEP - .suspend_noirq = exynos5_i2c_suspend_noirq, - .resume_noirq = exynos5_i2c_resume_noirq, - .freeze_noirq = exynos5_i2c_suspend_noirq, - .thaw_noirq = exynos5_i2c_resume_noirq, - .poweroff_noirq = exynos5_i2c_suspend_noirq, - .restore_noirq = exynos5_i2c_resume_noirq, -#endif + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos5_i2c_suspend_noirq, + exynos5_i2c_resume_noirq) }; static struct platform_driver exynos5_i2c_driver = { -- GitLab From f6903783eba49a2cbb6798b35fcf9d2ce61768b9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 14 Apr 2016 09:08:55 +0800 Subject: [PATCH 4085/9938] i2c: s3c2410: Use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS instead of open-coded Use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS to simplify the code. Signed-off-by: Axel Lin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-s3c2410.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 362a6de54833..1bc756313cb8 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1316,14 +1316,8 @@ static int s3c24xx_i2c_resume_noirq(struct device *dev) #ifdef CONFIG_PM static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { -#ifdef CONFIG_PM_SLEEP - .suspend_noirq = s3c24xx_i2c_suspend_noirq, - .resume_noirq = s3c24xx_i2c_resume_noirq, - .freeze_noirq = s3c24xx_i2c_suspend_noirq, - .thaw_noirq = s3c24xx_i2c_resume_noirq, - .poweroff_noirq = s3c24xx_i2c_suspend_noirq, - .restore_noirq = s3c24xx_i2c_resume_noirq, -#endif + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(s3c24xx_i2c_suspend_noirq, + s3c24xx_i2c_resume_noirq) }; #define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops) -- GitLab From 62547ba352e9c30912694eac4431ca6018da5ba2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 21 Apr 2016 11:11:23 +0900 Subject: [PATCH 4086/9938] ARM: dts: uniphier: add NAND pinmux node This commit adds pin-mux nodes for the NAND controller. Some SoCs support 2 chip selects and the others only support 1 chip select. Signed-off-by: Masahiro Yamada Signed-off-by: Arnd Bergmann --- arch/arm/boot/dts/uniphier-pinctrl.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/uniphier-pinctrl.dtsi b/arch/arm/boot/dts/uniphier-pinctrl.dtsi index 24592798a368..f2f3fbe2d517 100644 --- a/arch/arm/boot/dts/uniphier-pinctrl.dtsi +++ b/arch/arm/boot/dts/uniphier-pinctrl.dtsi @@ -68,6 +68,16 @@ function = "i2c4"; }; + pinctrl_nand: nand_grp { + groups = "nand"; + function = "nand"; + }; + + pinctrl_nand2cs: nand2cs_grp { + groups = "nand", "nand_cs1"; + function = "nand"; + }; + pinctrl_uart0: uart0_grp { groups = "uart0"; function = "uart0"; -- GitLab From 9b61aefce7b41cf3ae1c3c2b205fdfca3a537adc Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Mon, 14 Mar 2016 10:01:43 +0100 Subject: [PATCH 4087/9938] ARM: dts: artpec: update clock bindings in artpec6.dtsi The clock binding for the main clock controller was changed to an indexed controller style binding on request of the clk maintainers. This updates the dtsi to use the new bindings. Signed-off-by: Lars Persson Signed-off-by: Arnd Bergmann --- arch/arm/boot/dts/artpec6.dtsi | 99 +++++++--------------------------- 1 file changed, 20 insertions(+), 79 deletions(-) diff --git a/arch/arm/boot/dts/artpec6.dtsi b/arch/arm/boot/dts/artpec6.dtsi index 30430162b886..3fac4c4d0007 100644 --- a/arch/arm/boot/dts/artpec6.dtsi +++ b/arch/arm/boot/dts/artpec6.dtsi @@ -91,96 +91,32 @@ clock-frequency = <50000000>; }; - /* PLL1 is used by CPU and some peripherals */ - pll1_clk: pll1_clk@f8000000 { + eth_phy_ref_clk: eth_phy_ref_clk { #clock-cells = <0>; - compatible = "axis,artpec6-pll1-clock"; - reg = <0xf8000000 4>; - clocks = <&ext_clk>; - }; - - cpu_clk: cpu_clk { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <1>; - clock-mult = <1>; - clocks = <&pll1_clk>; - clock-output-names = "cpu_clk"; - }; - - cpu_clkdiv2: cpu_clkdiv2 { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <2>; - clock-mult = <1>; - clocks = <&cpu_clk>; - }; - - cpu_clkdiv4: cpu_clkdiv4 { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <4>; - clock-mult = <1>; - clocks = <&cpu_clk>; - }; - - apb_pclk: apb_pclk { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <8>; - clock-mult = <1>; - clocks = <&cpu_clk>; - clock-output-names = "apb_pclk"; + compatible = "fixed-clock"; + clock-frequency = <125000000>; }; - /* PLL2 is used by a number of peripherals, including UDL */ - pll2: pll2 { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <1>; - clock-mult = <24>; + clkctrl: clkctrl@0xf8000000 { + #clock-cells = <1>; + compatible = "axis,artpec6-clkctrl"; + reg = <0xf8000000 0x48>; clocks = <&ext_clk>; + clock-names = "sys_refclk"; }; - /* PLL2DIV2 is used by the Fractional Clock Divider, for i2s */ - pll2div2: pll2div2 { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <2>; - clock-mult = <1>; - clocks = <&pll2>; - }; - - pll2div12: pll2div12 { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <12>; - clock-mult = <1>; - clocks = <&pll2>; - }; - - pll2div24: pll2div24 { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <24>; - clock-mult = <1>; - clocks = <&pll2>; - clock-output-names = "uart_clk"; - }; - - gtimer@faf00200 { compatible = "arm,cortex-a9-global-timer"; reg = <0xfaf00200 0x20>; interrupts = ; - clocks = <&cpu_clkdiv2>; + clocks = <&clkctrl 1>; }; timer@faf00600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0xfaf00600 0x20>; interrupts = ; - clocks = <&cpu_clkdiv2>; + clocks = <&clkctrl 1>; status = "disabled"; }; @@ -220,7 +156,8 @@ ethernet: ethernet@f8010000 { clock-names = "phy_ref_clk", "apb_pclk"; - clocks = <&ext_clk>, <&apb_pclk>; + clocks = <ð_phy_ref_clk>, + <&clkctrl 4>; compatible = "snps,dwc-qos-ethernet-4.10"; interrupt-parent = <&intc>; interrupts = ; @@ -238,7 +175,8 @@ compatible = "arm,pl011", "arm,primecell"; reg = <0xf8036000 0x1000>; interrupts = ; - clocks = <&pll2div24>, <&apb_pclk>; + clocks = <&clkctrl 13>, + <&clkctrl 12>; clock-names = "uart_clk", "apb_pclk"; status = "disabled"; }; @@ -246,7 +184,8 @@ compatible = "arm,pl011", "arm,primecell"; reg = <0xf8037000 0x1000>; interrupts = ; - clocks = <&pll2div24>, <&apb_pclk>; + clocks = <&clkctrl 13>, + <&clkctrl 12>; clock-names = "uart_clk", "apb_pclk"; status = "disabled"; }; @@ -254,7 +193,8 @@ compatible = "arm,pl011", "arm,primecell"; reg = <0xf8038000 0x1000>; interrupts = ; - clocks = <&pll2div24>, <&apb_pclk>; + clocks = <&clkctrl 13>, + <&clkctrl 12>; clock-names = "uart_clk", "apb_pclk"; status = "disabled"; }; @@ -262,7 +202,8 @@ compatible = "arm,pl011", "arm,primecell"; reg = <0xf8039000 0x1000>; interrupts = ; - clocks = <&pll2div24>, <&apb_pclk>; + clocks = <&clkctrl 13>, + <&clkctrl 12>; clock-names = "uart_clk", "apb_pclk"; status = "disabled"; }; -- GitLab From 77f192af721440a9d91365438be6ecb98edd0310 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 18 Mar 2016 16:11:14 -0700 Subject: [PATCH 4088/9938] ixgbe: consolidate the configuration of spoof checking Consolidate the logic behind configuring spoof checking: Move the setting of the MAC, VLAN and Ethertype spoof checking into ixgbe_ndo_set_vf_spoofchk(). Change ixgbe_set_mac_anti_spoofing() to set MAC spoofing per VF similar to the VLAN and Ethertype functions - this allows us to call the helper functions in ixgbe_ndo_set_vf_spoofchk() for all spoof check types and only disable MAC spoof checking when creating MACVLAN. Signed-off-by: Emil Tantilov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ixgbe/ixgbe_common.c | 40 +++++------------ .../net/ethernet/intel/ixgbe/ixgbe_common.h | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 30 ++----------- .../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 43 ++++++++++++------- 4 files changed, 42 insertions(+), 73 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 737443a015d5..c9dffa6101b8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3310,43 +3310,25 @@ s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, /** * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing * @hw: pointer to hardware structure - * @enable: enable or disable switch for anti-spoofing - * @pf: Physical Function pool - do not enable anti-spoofing for the PF + * @enable: enable or disable switch for MAC anti-spoofing + * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing * **/ -void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf) +void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) { - int j; - int pf_target_reg = pf >> 3; - int pf_target_shift = pf % 8; - u32 pfvfspoof = 0; + int vf_target_reg = vf >> 3; + int vf_target_shift = vf % 8; + u32 pfvfspoof; if (hw->mac.type == ixgbe_mac_82598EB) return; + pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); if (enable) - pfvfspoof = IXGBE_SPOOF_MACAS_MASK; - - /* - * PFVFSPOOF register array is size 8 with 8 bits assigned to - * MAC anti-spoof enables in each register array element. - */ - for (j = 0; j < pf_target_reg; j++) - IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); - - /* - * The PF should be allowed to spoof so that it can support - * emulation mode NICs. Do not set the bits assigned to the PF - */ - pfvfspoof &= (1 << pf_target_shift) - 1; - IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); - - /* - * Remaining pools belong to the PF so they do not need to have - * anti-spoofing enabled. - */ - for (j++; j < IXGBE_PFVFSPOOF_REG_COUNT; j++) - IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), 0); + pfvfspoof |= BIT(vf_target_shift); + else + pfvfspoof &= ~BIT(vf_target_shift); + IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } /** diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 6f8e6a56e242..6d4c260d0cbd 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -106,7 +106,7 @@ s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked); s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); -void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf); +void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps); s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index b2f2cf40f06a..657e999befcb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3776,34 +3776,10 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); - - /* Enable MAC Anti-Spoofing */ - hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0), - adapter->num_vfs); - - /* Ensure LLDP and FC is set for Ethertype Antispoofing if we will be - * calling set_ethertype_anti_spoofing for each VF in loop below - */ - if (hw->mac.ops.set_ethertype_anti_spoofing) { - IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_LLDP), - (IXGBE_ETQF_FILTER_EN | - IXGBE_ETQF_TX_ANTISPOOF | - IXGBE_ETH_P_LLDP)); - - IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FC), - (IXGBE_ETQF_FILTER_EN | - IXGBE_ETQF_TX_ANTISPOOF | - ETH_P_PAUSE)); - } - - /* For VFs that have spoof checking turned off */ for (i = 0; i < adapter->num_vfs; i++) { - if (!adapter->vfinfo[i].spoofchk_enabled) - ixgbe_ndo_set_vf_spoofchk(adapter->netdev, i, false); - - /* enable ethertype anti spoofing if hw supports it */ - if (hw->mac.ops.set_ethertype_anti_spoofing) - hw->mac.ops.set_ethertype_anti_spoofing(hw, true, i); + /* configure spoof checking */ + ixgbe_ndo_set_vf_spoofchk(adapter->netdev, i, + adapter->vfinfo[i].spoofchk_enabled); /* Enable/Disable RSS query feature */ ixgbe_ndo_set_vf_rss_query_en(adapter->netdev, i, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index adcf00002483..cc635ced15d6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -964,8 +964,11 @@ static int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter, * If the VF is allowed to set MAC filters then turn off * anti-spoofing to avoid false positives. */ - if (adapter->vfinfo[vf].spoofchk_enabled) - ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false); + if (adapter->vfinfo[vf].spoofchk_enabled) { + struct ixgbe_hw *hw = &adapter->hw; + + hw->mac.ops.set_mac_anti_spoofing(hw, false, vf); + } } err = ixgbe_set_vf_macvlan(adapter, vf, index, new_mac); @@ -1525,27 +1528,35 @@ int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - int vf_target_reg = vf >> 3; - int vf_target_shift = vf % 8; struct ixgbe_hw *hw = &adapter->hw; - u32 regval; if (vf >= adapter->num_vfs) return -EINVAL; adapter->vfinfo[vf].spoofchk_enabled = setting; - regval = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); - regval &= ~(1 << vf_target_shift); - regval |= (setting << vf_target_shift); - IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), regval); - - if (adapter->vfinfo[vf].vlan_count) { - vf_target_shift += IXGBE_SPOOF_VLANAS_SHIFT; - regval = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); - regval &= ~(1 << vf_target_shift); - regval |= (setting << vf_target_shift); - IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), regval); + /* configure MAC spoofing */ + hw->mac.ops.set_mac_anti_spoofing(hw, setting, vf); + + /* configure VLAN spoofing */ + if (adapter->vfinfo[vf].vlan_count) + hw->mac.ops.set_vlan_anti_spoofing(hw, setting, vf); + + /* Ensure LLDP and FC is set for Ethertype Antispoofing if we will be + * calling set_ethertype_anti_spoofing for each VF in loop below + */ + if (hw->mac.ops.set_ethertype_anti_spoofing) { + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_LLDP), + (IXGBE_ETQF_FILTER_EN | + IXGBE_ETQF_TX_ANTISPOOF | + IXGBE_ETH_P_LLDP)); + + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FC), + (IXGBE_ETQF_FILTER_EN | + IXGBE_ETQF_TX_ANTISPOOF | + ETH_P_PAUSE)); + + hw->mac.ops.set_ethertype_anti_spoofing(hw, setting, vf); } return 0; -- GitLab From d3dec7c7c03351ae006f698501b523e7b1a38b3d Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Fri, 18 Mar 2016 16:11:19 -0700 Subject: [PATCH 4089/9938] ixgbe: set VLAN spoof checking unconditionally Previously the PF driver would only set VLAN spoof checking if the VF had created VLANs. This was done by setting and checking a counter (vlan_count) whenever a VLAN was created by the VF. However it is possible for the vlan_count to be !=0 while there are no VLANs assigned to the VF due to the count incrementing every time a VLAN 0 is added on ifdown/up, which resulted in VLAN spoofing always being set for those VFs. This patch cleans up the logic by unconditionally setting VLAN based on how the VF is configured (via ip link set ethX vf Y spoofchk on/off). This change also resolves an issue where the VLAN spoofing can remain set even after being disabled by the user due to the driver enabling VLAN spoof checking every time a VLAN is added to the VF, but would only allow changes in the setting if vlan_count != 0. Also default_vf_vlan_id and vlans_enabled were removed from the vf_data_storage structure since they are not being used in the driver. Signed-off-by: Emil Tantilov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 --- .../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 25 ++----------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index d10ed62993c1..61d8110d26c7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -143,14 +143,11 @@ struct vf_data_storage { unsigned char vf_mac_addresses[ETH_ALEN]; u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES]; u16 num_vf_mc_hashes; - u16 default_vf_vlan_id; - u16 vlans_enabled; bool clear_to_send; bool pf_set_mac; u16 pf_vlan; /* When set, guest VLAN config not allowed. */ u16 pf_qos; u16 tx_rate; - u16 vlan_count; u8 spoofchk_enabled; bool rss_query_enabled; u8 trusted; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index cc635ced15d6..e9f2558e65fc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -908,8 +908,6 @@ static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter, u32 add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT; u32 vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK); u8 tcs = netdev_get_num_tc(adapter->netdev); - struct ixgbe_hw *hw = &adapter->hw; - int err; if (adapter->vfinfo[vf].pf_vlan || tcs) { e_warn(drv, @@ -923,19 +921,7 @@ static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter, if (!vid && !add) return 0; - err = ixgbe_set_vf_vlan(adapter, add, vid, vf); - if (err) - return err; - - if (adapter->vfinfo[vf].spoofchk_enabled) - hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); - - if (add) - adapter->vfinfo[vf].vlan_count++; - else if (adapter->vfinfo[vf].vlan_count) - adapter->vfinfo[vf].vlan_count--; - - return 0; + return ixgbe_set_vf_vlan(adapter, add, vid, vf); } static int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter, @@ -1324,9 +1310,6 @@ static int ixgbe_enable_port_vlan(struct ixgbe_adapter *adapter, int vf, ixgbe_set_vmvir(adapter, vlan, qos, vf); ixgbe_set_vmolr(hw, vf, false); - if (adapter->vfinfo[vf].spoofchk_enabled) - hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); - adapter->vfinfo[vf].vlan_count++; /* enable hide vlan on X550 */ if (hw->mac.type >= ixgbe_mac_X550) @@ -1359,9 +1342,6 @@ static int ixgbe_disable_port_vlan(struct ixgbe_adapter *adapter, int vf) ixgbe_set_vf_vlan(adapter, true, 0, vf); ixgbe_clear_vmvir(adapter, vf); ixgbe_set_vmolr(hw, vf, true); - hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf); - if (adapter->vfinfo[vf].vlan_count) - adapter->vfinfo[vf].vlan_count--; /* disable hide VLAN on X550 */ if (hw->mac.type >= ixgbe_mac_X550) @@ -1539,8 +1519,7 @@ int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting) hw->mac.ops.set_mac_anti_spoofing(hw, setting, vf); /* configure VLAN spoofing */ - if (adapter->vfinfo[vf].vlan_count) - hw->mac.ops.set_vlan_anti_spoofing(hw, setting, vf); + hw->mac.ops.set_vlan_anti_spoofing(hw, setting, vf); /* Ensure LLDP and FC is set for Ethertype Antispoofing if we will be * calling set_ethertype_anti_spoofing for each VF in loop below -- GitLab From 4695886c644e48a02ca9d4c146a7ec4de8f2d2d8 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 24 Mar 2016 09:58:40 -0700 Subject: [PATCH 4090/9938] ixgbe: fix default mac->ops.setup_link for X550EM X550EM_a/x did not have a default value for mac->ops.setup_link which was causing link issues for backplane devices. This patch sets mac->ops.setup_link to ixgbe_setup_mac_link_X540 for X550EM_a/x which is also default for X550. This will result in mac->ops.setup_link calling the link setup function for the respective PHY type in case we do not need a special function to deal with it. Reported-by: Ken Cox Signed-off-by: Emil Tantilov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index c71e93ed4451..ea25f001f3bb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2908,7 +2908,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = { .get_media_type = &ixgbe_get_media_type_X550em, .get_san_mac_addr = NULL, .get_wwn_prefix = NULL, - .setup_link = NULL, /* defined later */ + .setup_link = &ixgbe_setup_mac_link_X540, .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, .get_bus_info = &ixgbe_get_bus_info_X550em, .setup_sfp = ixgbe_setup_sfp_modules_X550em, @@ -2926,7 +2926,7 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = { .get_media_type = ixgbe_get_media_type_X550em, .get_san_mac_addr = NULL, .get_wwn_prefix = NULL, - .setup_link = NULL, /* defined later */ + .setup_link = &ixgbe_setup_mac_link_X540, .get_link_capabilities = ixgbe_get_link_capabilities_X550em, .get_bus_info = ixgbe_get_bus_info_X550em, .setup_sfp = ixgbe_setup_sfp_modules_X550em, -- GitLab From 2a9ed5d1fc5e7e88a22da2d85bbaf6fc5b4c2fb8 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Fri, 1 Apr 2016 10:34:38 -0700 Subject: [PATCH 4091/9938] ixgbe: make 'action' field in struct ixgbe_fdir_filter a u64 value This field is used to record the RX queue index for a redirect action passed via ring_cookie field in struct ethtool_rx_flow_spec which is a u64 value. For ex: after adding a filter rule to redirect to a VF using ethtool # echo 4 > /sys/class/net/p4p1/device/sriov_numvfs # ethtool -N p4p1 flow-type ip4 src-ip 192.168.0.1 action 0x100000000 querying for the rule shows the Action as 'Direct to queue 0' # ethtool -n p4p1 4 RX rings available Total 1 rules Filter: 2045 Rule Type: Raw IPv4 Src IP addr: 192.168.0.1 mask: 0.0.0.0 Dest IP addr: 0.0.0.0 mask: 255.255.255.255 TOS: 0x0 mask: 0xff Protocol: 0 mask: 0xff L4 bytes: 0x0 mask: 0xffffffff VLAN EtherType: 0x0 mask: 0xffff VLAN: 0x0 mask: 0xffff User-defined: 0x0 mask: 0xffffffffffffffff Action: Direct to queue 0 With this fix, ethtool will report the right queue index even for VFs. Action: Direct to queue 4294967296 Here 4294967296 corresponds to 0x100000000. We need to update 'ethtool' to report the queue index as a Hex value so that it is more user friendly and matches with the 'action' value that is passed when adding the rule. Signed-off-by: Sridhar Samudrala Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 61d8110d26c7..94e39c13e7d4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -825,7 +825,7 @@ struct ixgbe_fdir_filter { struct hlist_node fdir_node; union ixgbe_atr_input filter; u16 sw_idx; - u16 action; + u64 action; }; enum ixgbe_state_t { -- GitLab From 15cfd40771e18a4e9b788c64c9db2606f958b93d Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 21 Apr 2016 16:13:01 -0700 Subject: [PATCH 4092/9938] hv_netvsc: Fix the list processing for network change event RNDIS_STATUS_NETWORK_CHANGE event is handled as two "half events" -- media disconnect & connect. The second half should be added to the list head, not to the tail. So all events are processed in normal order. Signed-off-by: Haiyang Zhang Reviewed-by: K. Y. Srinivasan Reviewed-by: Vitaly Kuznetsov Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index bfdb568ac6b8..ba3f3f3d48ef 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1125,7 +1125,7 @@ static void netvsc_link_change(struct work_struct *w) netif_tx_stop_all_queues(net); event->event = RNDIS_STATUS_MEDIA_CONNECT; spin_lock_irqsave(&ndev_ctx->lock, flags); - list_add_tail(&event->list, &ndev_ctx->reconfig_events); + list_add(&event->list, &ndev_ctx->reconfig_events); spin_unlock_irqrestore(&ndev_ctx->lock, flags); reschedule = true; } -- GitLab From 1ca79699cb958c17b0b08d9f9bd683e5011e7927 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 1 Apr 2016 17:44:39 +0200 Subject: [PATCH 4093/9938] ARM: dts: r8a7790: lager: Enable UHS-I SDR-50 Add the "1v8" pinctrl state and sd-uhs-sdr50 property to SDHI{0,2}. Signed-off-by: Ben Hutchings Signed-off-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 823a119cb1b4..749ba02b6a53 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -345,11 +345,25 @@ sdhi0_pins: sd0 { groups = "sdhi0_data4", "sdhi0_ctrl"; function = "sdhi0"; + power-source = <3300>; + }; + + sdhi0_pins_uhs: sd0_uhs { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <1800>; }; sdhi2_pins: sd2 { groups = "sdhi2_data4", "sdhi2_ctrl"; function = "sdhi2"; + power-source = <3300>; + }; + + sdhi2_pins_uhs: sd2_uhs { + groups = "sdhi2_data4", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <1800>; }; mmc1_pins: mmc1 { @@ -538,21 +552,25 @@ &sdhi0 { pinctrl-0 = <&sdhi0_pins>; - pinctrl-names = "default"; + pinctrl-1 = <&sdhi0_pins_uhs>; + pinctrl-names = "default", "state_uhs"; vmmc-supply = <&vcc_sdhi0>; vqmmc-supply = <&vccq_sdhi0>; cd-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; + sd-uhs-sdr50; status = "okay"; }; &sdhi2 { pinctrl-0 = <&sdhi2_pins>; - pinctrl-names = "default"; + pinctrl-1 = <&sdhi2_pins_uhs>; + pinctrl-names = "default", "state_uhs"; vmmc-supply = <&vcc_sdhi2>; vqmmc-supply = <&vccq_sdhi2>; cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>; + sd-uhs-sdr50; status = "okay"; }; -- GitLab From 7e2a1bcd2185c9d7d4c9b2910249a1a8fa841341 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 14 Apr 2016 11:58:42 +0200 Subject: [PATCH 4094/9938] ARM: dts: kzm9g: Configure NMI key as wake-up source Add a GPIO key with wake-up capability for the NMI button. This allows to wake up the system from s2ram without relying on the buttons on the optional switch board. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0-kzm9g.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/sh73a0-kzm9g.dts index e40a2f23b6cd..c2d8a080e392 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts @@ -149,6 +149,13 @@ label = "SW1"; wakeup-source; }; + + wakeup-key { + gpios = <&pfc 159 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "NMI"; + wakeup-source; + }; }; sound { -- GitLab From 21c7d0fcbe10a1a81fb791a9bdcca2381bc16c15 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 18 Apr 2016 11:41:30 +0200 Subject: [PATCH 4095/9938] ARM: dts: r8a7790: fix max-frequency for SDHI The wrong values come from an old datasheet (H2 v0.6). Anything later has the fixed value of 195MHz (H2 v0.7 up to Gen2-common V2.0). Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index b920facb0c3b..776a2aed81d2 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -589,7 +589,7 @@ clocks = <&mstp3_clks R8A7790_CLK_SDHI0>; dmas = <&dmac1 0xcd>, <&dmac1 0xce>; dma-names = "tx", "rx"; - max-frequency = <156000000>; + max-frequency = <195000000>; power-domains = <&cpg_clocks>; status = "disabled"; }; @@ -601,7 +601,7 @@ clocks = <&mstp3_clks R8A7790_CLK_SDHI1>; dmas = <&dmac1 0xc9>, <&dmac1 0xca>; dma-names = "tx", "rx"; - max-frequency = <156000000>; + max-frequency = <195000000>; power-domains = <&cpg_clocks>; status = "disabled"; }; -- GitLab From fc9ee228f5005437b9fdb1b85804b6d3f8d497be Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Mon, 18 Apr 2016 18:02:56 +0200 Subject: [PATCH 4096/9938] ARM: dts: r8a7793: Add SDHI controllers Same as on r8a7791. Signed-off-by: Ulrich Hecht Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7793.dtsi | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index bddc31283bd9..6186179fd66d 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -507,6 +507,39 @@ reg = <0 0xe6060000 0 0x250>; }; + sdhi0: sd@ee100000 { + compatible = "renesas,sdhi-r8a7793"; + reg = <0 0xee100000 0 0x328>; + interrupts = ; + clocks = <&mstp3_clks R8A7793_CLK_SDHI0>; + dmas = <&dmac0 0xcd>, <&dmac0 0xce>; + dma-names = "tx", "rx"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + + sdhi1: sd@ee140000 { + compatible = "renesas,sdhi-r8a7793"; + reg = <0 0xee140000 0 0x100>; + interrupts = ; + clocks = <&mstp3_clks R8A7793_CLK_SDHI1>; + dmas = <&dmac0 0xc1>, <&dmac0 0xc2>; + dma-names = "tx", "rx"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + + sdhi2: sd@ee160000 { + compatible = "renesas,sdhi-r8a7793"; + reg = <0 0xee160000 0 0x100>; + interrupts = ; + clocks = <&mstp3_clks R8A7793_CLK_SDHI2>; + dmas = <&dmac0 0xd3>, <&dmac0 0xd4>; + dma-names = "tx", "rx"; + power-domains = <&cpg_clocks>; + status = "disabled"; + }; + scifa0: serial@e6c40000 { compatible = "renesas,scifa-r8a7793", "renesas,rcar-gen2-scifa", "renesas,scifa"; -- GitLab From 6f92cb2f454c26d9bdada902e22af4bc361a5202 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Mon, 18 Apr 2016 18:02:57 +0200 Subject: [PATCH 4097/9938] ARM: dts: gose: Enable SDHI controllers Includes regulator and pin assignments. Signed-off-by: Ulrich Hecht Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7793-gose.dts | 119 +++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts index 3cd1c804621f..0ebc3ee34923 100644 --- a/arch/arm/boot/dts/r8a7793-gose.dts +++ b/arch/arm/boot/dts/r8a7793-gose.dts @@ -158,6 +158,78 @@ }; }; + vcc_sdhi0: regulator@0 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio7 17 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi0: regulator@1 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI0 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1 + 1800000 0>; + }; + + vcc_sdhi1: regulator@2 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI1 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio7 18 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi1: regulator@3 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI1 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1 + 1800000 0>; + }; + + vcc_sdhi2: regulator@4 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI2 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio7 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi2: regulator@5 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI2 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1 + 1800000 0>; + }; + audio_clock: audio_clock { compatible = "fixed-clock"; #clock-cells = <0>; @@ -273,6 +345,21 @@ function = "intc"; }; + sdhi0_pins: sd0 { + renesas,groups = "sdhi0_data4", "sdhi0_ctrl"; + renesas,function = "sdhi0"; + }; + + sdhi1_pins: sd1 { + renesas,groups = "sdhi1_data4", "sdhi1_ctrl"; + renesas,function = "sdhi1"; + }; + + sdhi2_pins: sd2 { + renesas,groups = "sdhi2_data4", "sdhi2_ctrl"; + renesas,function = "sdhi2"; + }; + qspi_pins: spi0 { groups = "qspi_ctrl", "qspi_data4"; function = "qspi"; @@ -328,6 +415,38 @@ status = "okay"; }; +&sdhi0 { + pinctrl-0 = <&sdhi0_pins>; + pinctrl-names = "default"; + + vmmc-supply = <&vcc_sdhi0>; + vqmmc-supply = <&vccq_sdhi0>; + cd-gpios = <&gpio6 6 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&sdhi1 { + pinctrl-0 = <&sdhi1_pins>; + pinctrl-names = "default"; + + vmmc-supply = <&vcc_sdhi1>; + vqmmc-supply = <&vccq_sdhi1>; + cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&sdhi2 { + pinctrl-0 = <&sdhi2_pins>; + pinctrl-names = "default"; + + vmmc-supply = <&vcc_sdhi2>; + vqmmc-supply = <&vccq_sdhi2>; + cd-gpios = <&gpio6 22 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + &qspi { pinctrl-0 = <&qspi_pins>; pinctrl-names = "default"; -- GitLab From b8199ff31f86ee94fa1166997259b03022ecb4de Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 24 Apr 2016 23:44:13 +0100 Subject: [PATCH 4098/9938] clk: rockchip: fix of spelling mistake on unsuccessful in pll clock type fix spelling mistake, unsucessful -> unsuccessful Signed-off-by: Colin Ian King Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 128a6b2fca7f..8ac73bc7f93d 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -236,7 +236,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, /* wait for the pll to lock */ ret = rockchip_pll_wait_lock(pll); if (ret) { - pr_warn("%s: pll update unsucessful, trying to restore old params\n", + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", __func__); rockchip_rk3036_pll_set_params(pll, &cur); } @@ -475,7 +475,7 @@ static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll, /* wait for the pll to lock */ ret = rockchip_pll_wait_lock(pll); if (ret) { - pr_warn("%s: pll update unsucessful, trying to restore old params\n", + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", __func__); rockchip_rk3066_pll_set_params(pll, &cur); } -- GitLab From f87305fa00b1d0633d2dc5fd7fb4995bed6a59e8 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Fri, 22 Apr 2016 18:02:53 +0800 Subject: [PATCH 4099/9938] ARM: dts: rockchip: move the rk3288 thermal data into rk3288.dtsi In order to be standard to manage for rockchip SoCs, move the thermal data into rk3288 dtsi, we needn't to add a new file for thermal. Signed-off-by: Caesar Wang Cc: Zhang Rui Cc: Eduardo Valentin Cc: Heiko Stuebner Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-thermal.dtsi | 118 -------------------------- arch/arm/boot/dts/rk3288.dtsi | 73 +++++++++++++++- 2 files changed, 72 insertions(+), 119 deletions(-) delete mode 100644 arch/arm/boot/dts/rk3288-thermal.dtsi diff --git a/arch/arm/boot/dts/rk3288-thermal.dtsi b/arch/arm/boot/dts/rk3288-thermal.dtsi deleted file mode 100644 index 651b962e3d53..000000000000 --- a/arch/arm/boot/dts/rk3288-thermal.dtsi +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Device Tree Source for RK3288 SoC thermal - * - * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include - -reserve_thermal: reserve_thermal { - polling-delay-passive = <1000>; /* milliseconds */ - polling-delay = <5000>; /* milliseconds */ - - thermal-sensors = <&tsadc 0>; -}; - -cpu_thermal: cpu_thermal { - polling-delay-passive = <100>; /* milliseconds */ - polling-delay = <5000>; /* milliseconds */ - - thermal-sensors = <&tsadc 1>; - - trips { - cpu_alert0: cpu_alert0 { - temperature = <70000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - cpu_alert1: cpu_alert1 { - temperature = <75000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - cpu_crit: cpu_crit { - temperature = <90000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu_alert0>; - cooling-device = - <&cpu0 THERMAL_NO_LIMIT 6>; - }; - map1 { - trip = <&cpu_alert1>; - cooling-device = - <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -gpu_thermal: gpu_thermal { - polling-delay-passive = <100>; /* milliseconds */ - polling-delay = <5000>; /* milliseconds */ - - thermal-sensors = <&tsadc 2>; - - trips { - gpu_alert0: gpu_alert0 { - temperature = <70000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - gpu_crit: gpu_crit { - temperature = <90000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&gpu_alert0>; - cooling-device = - <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 906818955215..3b44ef3cff12 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -445,7 +445,78 @@ }; thermal-zones { - #include "rk3288-thermal.dtsi" + reserve_thermal: reserve_thermal { + polling-delay-passive = <1000>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 0>; + }; + + cpu_thermal: cpu_thermal { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 1>; + + trips { + cpu_alert0: cpu_alert0 { + temperature = <70000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_alert1: cpu_alert1 { + temperature = <75000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_crit: cpu_crit { + temperature = <90000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT 6>; + }; + map1 { + trip = <&cpu_alert1>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu_thermal: gpu_thermal { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 2>; + + trips { + gpu_alert0: gpu_alert0 { + temperature = <70000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + gpu_crit: gpu_crit { + temperature = <90000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; }; tsadc: tsadc@ff280000 { -- GitLab From 6ddf93e05e67f81b6a95840c35e1aa6e042196a8 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Fri, 22 Apr 2016 18:02:54 +0800 Subject: [PATCH 4100/9938] arm64: dts: rockchip: move the rk3368 thermal data into rk3368.dtsi In order to be standard to manage for rockchip SoCs, move the thermal data into rk3368 dtsi, we needn't to add a new file for thermal. Signed-off-by: Caesar Wang Cc: Zhang Rui Cc: Eduardo Valentin Cc: Heiko Stuebner Signed-off-by: Heiko Stuebner --- .../boot/dts/rockchip/rk3368-thermal.dtsi | 112 ------------------ arch/arm64/boot/dts/rockchip/rk3368.dtsi | 66 ++++++++++- 2 files changed, 65 insertions(+), 113 deletions(-) delete mode 100644 arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi deleted file mode 100644 index a10010f92f96..000000000000 --- a/arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Device Tree Source for RK3368 SoC thermal - * - * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd - * Caesar Wang - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include - -cpu_thermal: cpu_thermal { - polling-delay-passive = <100>; /* milliseconds */ - polling-delay = <5000>; /* milliseconds */ - - thermal-sensors = <&tsadc 0>; - - trips { - cpu_alert0: cpu_alert0 { - temperature = <75000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - cpu_alert1: cpu_alert1 { - temperature = <80000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - cpu_crit: cpu_crit { - temperature = <95000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu_alert0>; - cooling-device = - <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - map1 { - trip = <&cpu_alert1>; - cooling-device = - <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -gpu_thermal: gpu_thermal { - polling-delay-passive = <100>; /* milliseconds */ - polling-delay = <5000>; /* milliseconds */ - - thermal-sensors = <&tsadc 1>; - - trips { - gpu_alert0: gpu_alert0 { - temperature = <80000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - gpu_crit: gpu_crit { - temperature = <1150000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&gpu_alert0>; - cooling-device = - <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index 7056a0fa1921..8b4a7c9154e9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -413,7 +413,71 @@ }; thermal-zones { - #include "rk3368-thermal.dtsi" + cpu { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 0>; + + trips { + cpu_alert0: cpu_alert0 { + temperature = <75000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_alert1: cpu_alert1 { + temperature = <80000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu_crit: cpu_crit { + temperature = <95000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + map1 { + trip = <&cpu_alert1>; + cooling-device = + <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu { + polling-delay-passive = <100>; /* milliseconds */ + polling-delay = <5000>; /* milliseconds */ + + thermal-sensors = <&tsadc 1>; + + trips { + gpu_alert0: gpu_alert0 { + temperature = <80000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + gpu_crit: gpu_crit { + temperature = <115000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = + <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; }; tsadc: tsadc@ff280000 { -- GitLab From b52e345d43cfe9214fecfa92375525a086d39581 Mon Sep 17 00:00:00 2001 From: Christopher Spinrath Date: Mon, 25 Apr 2016 01:02:58 +0200 Subject: [PATCH 4101/9938] ARM: dts: sun7i: Enable S/PDIF on the Cubietruck Enable the S/PDIF transmitter present on the Cubietruck. Signed-off-by: Christopher Spinrath Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 8da939ab8350..83f39b0362cb 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -94,6 +94,24 @@ pinctrl-0 = <&mmc3_pwrseq_pin_cubietruck>; reset-gpios = <&pio 7 9 GPIO_ACTIVE_LOW>; /* PH9 WIFI_EN */ }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "On-board SPDIF"; + + simple-audio-card,cpu { + sound-dai = <&spdif>; + }; + + simple-audio-card,codec { + sound-dai = <&spdif_out>; + }; + }; + + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; }; &ahci { @@ -301,6 +319,12 @@ status = "okay"; }; +&spdif { + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx_pins_a>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins_a>; -- GitLab From b610386c8afba397238329c50c45a3abc79ba45f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 31 Mar 2016 08:47:09 +0900 Subject: [PATCH 4102/9938] ALSA: firewire-tascam: deleyed registration of sound card When some tascam units are connected sequentially, userspace applications are involved at bus-reset state on IEEE 1394 bus. In the state, any communications can be canceled. Therefore, sound card registration should be delayed till the bus gets calm. This commit achieves it. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam.c | 118 +++++++++++++++++++++++---------- sound/firewire/tascam/tascam.h | 2 + 2 files changed, 84 insertions(+), 36 deletions(-) diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c index e281c338e562..9dc93a7eb9da 100644 --- a/sound/firewire/tascam/tascam.c +++ b/sound/firewire/tascam/tascam.c @@ -85,10 +85,8 @@ static int identify_model(struct snd_tscm *tscm) return 0; } -static void tscm_card_free(struct snd_card *card) +static void tscm_free(struct snd_tscm *tscm) { - struct snd_tscm *tscm = card->private_data; - snd_tscm_transaction_unregister(tscm); snd_tscm_stream_destroy_duplex(tscm); @@ -97,44 +95,36 @@ static void tscm_card_free(struct snd_card *card) mutex_destroy(&tscm->mutex); } -static int snd_tscm_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) +static void tscm_card_free(struct snd_card *card) { - struct snd_card *card; - struct snd_tscm *tscm; + tscm_free(card->private_data); +} + +static void do_registration(struct work_struct *work) +{ + struct snd_tscm *tscm = container_of(work, struct snd_tscm, dwork.work); int err; - /* create card */ - err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, - sizeof(struct snd_tscm), &card); + err = snd_card_new(&tscm->unit->device, -1, NULL, THIS_MODULE, 0, + &tscm->card); if (err < 0) - return err; - card->private_free = tscm_card_free; - - /* initialize myself */ - tscm = card->private_data; - tscm->card = card; - tscm->unit = fw_unit_get(unit); - - mutex_init(&tscm->mutex); - spin_lock_init(&tscm->lock); - init_waitqueue_head(&tscm->hwdep_wait); + return; err = identify_model(tscm); if (err < 0) goto error; - snd_tscm_proc_init(tscm); - - err = snd_tscm_stream_init_duplex(tscm); + err = snd_tscm_transaction_register(tscm); if (err < 0) goto error; - err = snd_tscm_create_pcm_devices(tscm); + err = snd_tscm_stream_init_duplex(tscm); if (err < 0) goto error; - err = snd_tscm_transaction_register(tscm); + snd_tscm_proc_init(tscm); + + err = snd_tscm_create_pcm_devices(tscm); if (err < 0) goto error; @@ -146,35 +136,91 @@ static int snd_tscm_probe(struct fw_unit *unit, if (err < 0) goto error; - err = snd_card_register(card); + err = snd_card_register(tscm->card); if (err < 0) goto error; - dev_set_drvdata(&unit->device, tscm); + /* + * After registered, tscm instance can be released corresponding to + * releasing the sound card instance. + */ + tscm->card->private_free = tscm_card_free; + tscm->card->private_data = tscm; + tscm->registered = true; - return err; + return; error: - snd_card_free(card); - return err; + snd_tscm_transaction_unregister(tscm); + snd_tscm_stream_destroy_duplex(tscm); + snd_card_free(tscm->card); + dev_info(&tscm->unit->device, + "Sound card registration failed: %d\n", err); +} + +static int snd_tscm_probe(struct fw_unit *unit, + const struct ieee1394_device_id *entry) +{ + struct snd_tscm *tscm; + + /* Allocate this independent of sound card instance. */ + tscm = kzalloc(sizeof(struct snd_tscm), GFP_KERNEL); + if (tscm == NULL) + return -ENOMEM; + + /* initialize myself */ + tscm->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, tscm); + + mutex_init(&tscm->mutex); + spin_lock_init(&tscm->lock); + init_waitqueue_head(&tscm->hwdep_wait); + + /* Allocate and register this sound card later. */ + INIT_DEFERRABLE_WORK(&tscm->dwork, do_registration); + snd_fw_schedule_registration(unit, &tscm->dwork); + + return 0; } static void snd_tscm_update(struct fw_unit *unit) { struct snd_tscm *tscm = dev_get_drvdata(&unit->device); + /* Postpone a workqueue for deferred registration. */ + if (!tscm->registered) + snd_fw_schedule_registration(unit, &tscm->dwork); + snd_tscm_transaction_reregister(tscm); - mutex_lock(&tscm->mutex); - snd_tscm_stream_update_duplex(tscm); - mutex_unlock(&tscm->mutex); + /* + * After registration, userspace can start packet streaming, then this + * code block works fine. + */ + if (tscm->registered) { + mutex_lock(&tscm->mutex); + snd_tscm_stream_update_duplex(tscm); + mutex_unlock(&tscm->mutex); + } } static void snd_tscm_remove(struct fw_unit *unit) { struct snd_tscm *tscm = dev_get_drvdata(&unit->device); - /* No need to wait for releasing card object in this context. */ - snd_card_free_when_closed(tscm->card); + /* + * Confirm to stop the work for registration before the sound card is + * going to be released. The work is not scheduled again because bus + * reset handler is not called anymore. + */ + cancel_delayed_work_sync(&tscm->dwork); + + if (tscm->registered) { + /* No need to wait for releasing card object in this context. */ + snd_card_free_when_closed(tscm->card); + } else { + /* Don't forget this case. */ + tscm_free(tscm); + } } static const struct ieee1394_device_id snd_tscm_id_table[] = { diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 30ab77e924f7..1f61011579a7 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -51,6 +51,8 @@ struct snd_tscm { struct mutex mutex; spinlock_t lock; + bool registered; + struct delayed_work dwork; const struct snd_tscm_spec *spec; struct fw_iso_resources tx_resources; -- GitLab From 34ce71a96dcba24c71b07f1b087bd179b885784d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 23 Apr 2016 02:58:05 +0200 Subject: [PATCH 4103/9938] ALSA: timer: remove legacy rtctimer There are no users of rtctimer left. Remove its code as this is the in-kernel user of the legacy PC RTC driver that will hopefully be removed at some point. Signed-off-by: Alexandre Belloni Signed-off-by: Takashi Iwai --- include/uapi/sound/asound.h | 2 +- sound/core/Kconfig | 29 ------ sound/core/Makefile | 1 - sound/core/rtctimer.c | 187 ------------------------------------ sound/core/seq/seq.c | 2 - sound/core/timer.c | 2 - 6 files changed, 1 insertion(+), 222 deletions(-) delete mode 100644 sound/core/rtctimer.c diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 67bf49d8c944..609cadb8739d 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -672,7 +672,7 @@ enum { /* global timers (device member) */ #define SNDRV_TIMER_GLOBAL_SYSTEM 0 -#define SNDRV_TIMER_GLOBAL_RTC 1 +#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */ #define SNDRV_TIMER_GLOBAL_HPET 2 #define SNDRV_TIMER_GLOBAL_HRTIMER 3 diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 6d12ca9bcb80..9749f9e8b45c 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -141,35 +141,6 @@ config SND_SEQ_HRTIMER_DEFAULT Say Y here to use the HR-timer backend as the default sequencer timer. -config SND_RTCTIMER - tristate "RTC Timer support" - depends on RTC - select SND_TIMER - help - Say Y here to enable RTC timer support for ALSA. ALSA uses - the RTC timer as a precise timing source and maps the RTC - timer to ALSA's timer interface. The ALSA sequencer code also - can use this timing source. - - To compile this driver as a module, choose M here: the module - will be called snd-rtctimer. - - Note that this option is exclusive with the new RTC drivers - (CONFIG_RTC_CLASS) since this requires the old API. - -config SND_SEQ_RTCTIMER_DEFAULT - bool "Use RTC as default sequencer timer" - depends on SND_RTCTIMER && SND_SEQUENCER - depends on !SND_SEQ_HRTIMER_DEFAULT - default y - help - Say Y here to use the RTC timer as the default sequencer - timer. This is strongly recommended because it ensures - precise MIDI timing even when the system timer runs at less - than 1000 Hz. - - If in doubt, say Y. - config SND_DYNAMIC_MINORS bool "Dynamic device file minor numbers" help diff --git a/sound/core/Makefile b/sound/core/Makefile index 48ab4b8f8279..e85d9dd12c2d 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -37,7 +37,6 @@ obj-$(CONFIG_SND) += snd.o obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o obj-$(CONFIG_SND_TIMER) += snd-timer.o obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o -obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o obj-$(CONFIG_SND_PCM) += snd-pcm.o obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c deleted file mode 100644 index f3420d11a12f..000000000000 --- a/sound/core/rtctimer.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * RTC based high-frequency timer - * - * Copyright (C) 2000 Takashi Iwai - * based on rtctimer.c by Steve Ratcliffe - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#if IS_ENABLED(CONFIG_RTC) - -#include - -#define RTC_FREQ 1024 /* default frequency */ -#define NANO_SEC 1000000000L /* 10^9 in sec */ - -/* - * prototypes - */ -static int rtctimer_open(struct snd_timer *t); -static int rtctimer_close(struct snd_timer *t); -static int rtctimer_start(struct snd_timer *t); -static int rtctimer_stop(struct snd_timer *t); - - -/* - * The hardware dependent description for this timer. - */ -static struct snd_timer_hardware rtc_hw = { - .flags = SNDRV_TIMER_HW_AUTO | - SNDRV_TIMER_HW_FIRST | - SNDRV_TIMER_HW_TASKLET, - .ticks = 100000000L, /* FIXME: XXX */ - .open = rtctimer_open, - .close = rtctimer_close, - .start = rtctimer_start, - .stop = rtctimer_stop, -}; - -static int rtctimer_freq = RTC_FREQ; /* frequency */ -static struct snd_timer *rtctimer; -static struct tasklet_struct rtc_tasklet; -static rtc_task_t rtc_task; - - -static int -rtctimer_open(struct snd_timer *t) -{ - int err; - - err = rtc_register(&rtc_task); - if (err < 0) - return err; - t->private_data = &rtc_task; - return 0; -} - -static int -rtctimer_close(struct snd_timer *t) -{ - rtc_task_t *rtc = t->private_data; - if (rtc) { - rtc_unregister(rtc); - tasklet_kill(&rtc_tasklet); - t->private_data = NULL; - } - return 0; -} - -static int -rtctimer_start(struct snd_timer *timer) -{ - rtc_task_t *rtc = timer->private_data; - if (snd_BUG_ON(!rtc)) - return -EINVAL; - rtc_control(rtc, RTC_IRQP_SET, rtctimer_freq); - rtc_control(rtc, RTC_PIE_ON, 0); - return 0; -} - -static int -rtctimer_stop(struct snd_timer *timer) -{ - rtc_task_t *rtc = timer->private_data; - if (snd_BUG_ON(!rtc)) - return -EINVAL; - rtc_control(rtc, RTC_PIE_OFF, 0); - return 0; -} - -static void rtctimer_tasklet(unsigned long data) -{ - snd_timer_interrupt((struct snd_timer *)data, 1); -} - -/* - * interrupt - */ -static void rtctimer_interrupt(void *private_data) -{ - tasklet_schedule(private_data); -} - - -/* - * ENTRY functions - */ -static int __init rtctimer_init(void) -{ - int err; - struct snd_timer *timer; - - if (rtctimer_freq < 2 || rtctimer_freq > 8192 || - !is_power_of_2(rtctimer_freq)) { - pr_err("ALSA: rtctimer: invalid frequency %d\n", rtctimer_freq); - return -EINVAL; - } - - /* Create a new timer and set up the fields */ - err = snd_timer_global_new("rtc", SNDRV_TIMER_GLOBAL_RTC, &timer); - if (err < 0) - return err; - - timer->module = THIS_MODULE; - strcpy(timer->name, "RTC timer"); - timer->hw = rtc_hw; - timer->hw.resolution = NANO_SEC / rtctimer_freq; - - tasklet_init(&rtc_tasklet, rtctimer_tasklet, (unsigned long)timer); - - /* set up RTC callback */ - rtc_task.func = rtctimer_interrupt; - rtc_task.private_data = &rtc_tasklet; - - err = snd_timer_global_register(timer); - if (err < 0) { - snd_timer_global_free(timer); - return err; - } - rtctimer = timer; /* remember this */ - - return 0; -} - -static void __exit rtctimer_exit(void) -{ - if (rtctimer) { - snd_timer_global_free(rtctimer); - rtctimer = NULL; - } -} - - -/* - * exported stuff - */ -module_init(rtctimer_init) -module_exit(rtctimer_exit) - -module_param(rtctimer_freq, int, 0444); -MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz"); - -MODULE_LICENSE("GPL"); - -MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC)); - -#endif /* IS_ENABLED(CONFIG_RTC) */ diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 7e0aabb808a6..639544b4fb04 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -47,8 +47,6 @@ int seq_default_timer_card = -1; int seq_default_timer_device = #ifdef CONFIG_SND_SEQ_HRTIMER_DEFAULT SNDRV_TIMER_GLOBAL_HRTIMER -#elif defined(CONFIG_SND_SEQ_RTCTIMER_DEFAULT) - SNDRV_TIMER_GLOBAL_RTC #else SNDRV_TIMER_GLOBAL_SYSTEM #endif diff --git a/sound/core/timer.c b/sound/core/timer.c index 6469bedda2f3..0cfc028c1193 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -37,8 +37,6 @@ #if IS_ENABLED(CONFIG_SND_HRTIMER) #define DEFAULT_TIMER_LIMIT 4 -#elif IS_ENABLED(CONFIG_SND_RTCTIMER) -#define DEFAULT_TIMER_LIMIT 2 #else #define DEFAULT_TIMER_LIMIT 1 #endif -- GitLab From ff2bb89335daec6053b5ac778369f7f72b931142 Mon Sep 17 00:00:00 2001 From: Jens Kuske Date: Fri, 18 Mar 2016 09:44:15 +0000 Subject: [PATCH 4104/9938] clk: sunxi: Let divs clocks read the base factor clock name from devicetree Currently, the sunxi clock driver gets the name for the base factor clock of divs clocks from the name field in factors_data. This prevents reusing of the factor clock for clocks with same properties, but different name. This commit makes the divs setup function try to get a name from clock-output-names in the devicetree. It also removes the name field where possible and merges the sun4i PLL5 and PLL6 clocks. [Andre: Make temporary name allocation dynamic.] Signed-off-by: Jens Kuske Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sunxi.c | 41 +++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 6ea7cf80a0ab..838b22aa8b67 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -523,21 +523,12 @@ static const struct factors_data sun4i_pll5_data __initconst = { .enable = 31, .table = &sun4i_pll5_config, .getter = sun4i_get_pll5_factors, - .name = "pll5", -}; - -static const struct factors_data sun4i_pll6_data __initconst = { - .enable = 31, - .table = &sun4i_pll5_config, - .getter = sun4i_get_pll5_factors, - .name = "pll6", }; static const struct factors_data sun6i_a31_pll6_data __initconst = { .enable = 31, .table = &sun6i_a31_pll6_config, .getter = sun6i_a31_get_pll6_factors, - .name = "pll6x2", }; static const struct factors_data sun5i_a13_ahb_data __initconst = { @@ -933,7 +924,7 @@ static const struct divs_data pll5_divs_data __initconst = { }; static const struct divs_data pll6_divs_data __initconst = { - .factors = &sun4i_pll6_data, + .factors = &sun4i_pll5_data, .ndivs = 4, .div = { { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ @@ -975,6 +966,8 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node, struct clk_gate *gate = NULL; struct clk_fixed_factor *fix_factor; struct clk_divider *divider; + struct factors_data factors = *data->factors; + char *derived_name = NULL; void __iomem *reg; int ndivs = SUNXI_DIVS_MAX_QTY, i = 0; int flags, clkflags; @@ -983,11 +976,37 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node, if (data->ndivs) ndivs = data->ndivs; + /* Try to find a name for base factor clock */ + for (i = 0; i < ndivs; i++) { + if (data->div[i].self) { + of_property_read_string_index(node, "clock-output-names", + i, &factors.name); + break; + } + } + /* If we don't have a .self clk use the first output-name up to '_' */ + if (factors.name == NULL) { + char *endp; + + of_property_read_string_index(node, "clock-output-names", + 0, &clk_name); + endp = strchr(clk_name, '_'); + if (endp) { + derived_name = kstrndup(clk_name, endp - clk_name, + GFP_KERNEL); + factors.name = derived_name; + } else { + factors.name = clk_name; + } + } + /* Set up factor clock that we will be dividing */ - pclk = sunxi_factors_clk_setup(node, data->factors); + pclk = sunxi_factors_clk_setup(node, &factors); if (!pclk) return NULL; + parent = __clk_get_name(pclk); + kfree(derived_name); reg = of_iomap(node, 0); if (!reg) { -- GitLab From 8d84c1973b69621bcb89d5d8a69699e8347a3d90 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 07:37:02 +0100 Subject: [PATCH 4105/9938] ALSA: doc: fix spelling mistakes Signed-off-by: Eric Engestrom Acked-by: Vinod Koul Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/compress_offload.txt | 2 +- Documentation/sound/alsa/soc/dapm.txt | 2 +- Documentation/sound/alsa/soc/overview.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/sound/alsa/compress_offload.txt b/Documentation/sound/alsa/compress_offload.txt index 630c492c3dc2..81476b4d400b 100644 --- a/Documentation/sound/alsa/compress_offload.txt +++ b/Documentation/sound/alsa/compress_offload.txt @@ -149,7 +149,7 @@ Gapless Playback ================ When playing thru an album, the decoders have the ability to skip the encoder delay and padding and directly move from one track content to another. The end -user can perceive this as gapless playback as we dont have silence while +user can perceive this as gapless playback as we don't have silence while switching from one track to another Also, there might be low-intensity noises due to encoding. Perfect gapless is diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt index 6faab4880006..c45bd79f291e 100644 --- a/Documentation/sound/alsa/soc/dapm.txt +++ b/Documentation/sound/alsa/soc/dapm.txt @@ -132,7 +132,7 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0), SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls, ARRAY_SIZE(wm8731_output_mixer_controls)), -If you dont want the mixer elements prefixed with the name of the mixer widget, +If you don't want the mixer elements prefixed with the name of the mixer widget, you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same as for SND_SOC_DAPM_MIXER. diff --git a/Documentation/sound/alsa/soc/overview.txt b/Documentation/sound/alsa/soc/overview.txt index ff88f52eec98..f3f28b7ae242 100644 --- a/Documentation/sound/alsa/soc/overview.txt +++ b/Documentation/sound/alsa/soc/overview.txt @@ -63,7 +63,7 @@ multiple re-usable component drivers :- and any audio DSP drivers for that platform. * Machine class driver: The machine driver class acts as the glue that - decribes and binds the other component drivers together to form an ALSA + describes and binds the other component drivers together to form an ALSA "sound card device". It handles any machine specific controls and machine level audio events (e.g. turning on an amp at start of playback). -- GitLab From bbf4ac9cfa9b681e3b657699f39fc855408904b8 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 20 Apr 2016 20:33:05 +0200 Subject: [PATCH 4106/9938] HID: thingm: remove not needed error message LED core takes care of handling failed calls to thingm_let_set. - print error message in set_brightness_delayed or - pass error to caller in led_set_brightness_sync Also the error message here doesn't provide any hint what actually went wrong. Therefore remove it. Signed-off-by: Heiner Kallweit Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-thingm.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c index 2507bbe0eea7..9ad9c6ec5bba 100644 --- a/drivers/hid/hid-thingm.c +++ b/drivers/hid/hid-thingm.c @@ -148,13 +148,8 @@ static int thingm_led_set(struct led_classdev *ldev, enum led_brightness brightness) { struct thingm_led *led = container_of(ldev, struct thingm_led, ldev); - int ret; - - ret = thingm_write_color(led->rgb); - if (ret) - hid_err(led->rgb->tdev->hdev, "failed to write color\n"); - return ret; + return thingm_write_color(led->rgb); } static int thingm_init_led(struct thingm_led *led, const char *color_name, -- GitLab From 2cff6dba57b74129e0fd6f201cedf236f49f97e9 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 7 Mar 2016 11:54:45 +0000 Subject: [PATCH 4107/9938] ARM: dts: vexpress: fix node name unit-address presence warnings Commit b993734718c0 ("scripts/dtc: Update to upstream version 53bf130b1cdd") added warnings on node name unit-address presence/absence mismatch in the device trees. This patch fixes those warning on all the vexpress platforms where unit-address is present in node name while the reg/ranges property is not present. Signed-off-by: Sudeep Holla --- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 44 ++++++++++----------- arch/arm/boot/dts/vexpress-v2m.dtsi | 44 ++++++++++----------- arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 34 ++++++++-------- arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 44 ++++++++++----------- arch/arm/boot/dts/vexpress-v2p-ca5s.dts | 24 +++++------ arch/arm/boot/dts/vexpress-v2p-ca9.dts | 28 ++++++------- 6 files changed, 109 insertions(+), 109 deletions(-) diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index 7a556b92e55c..3086efacd00e 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -75,19 +75,19 @@ compatible = "arm,vexpress-sysreg"; reg = <0x010000 0x1000>; - v2m_led_gpios: sys_led@08 { + v2m_led_gpios: sys_led { compatible = "arm,vexpress-sysreg,sys_led"; gpio-controller; #gpio-cells = <2>; }; - v2m_mmc_gpios: sys_mci@48 { + v2m_mmc_gpios: sys_mci { compatible = "arm,vexpress-sysreg,sys_mci"; gpio-controller; #gpio-cells = <2>; }; - v2m_flash_gpios: sys_flash@4c { + v2m_flash_gpios: sys_flash { compatible = "arm,vexpress-sysreg,sys_flash"; gpio-controller; #gpio-cells = <2>; @@ -286,7 +286,7 @@ }; }; - v2m_fixed_3v3: fixedregulator@0 { + v2m_fixed_3v3: fixed-regulator-0 { compatible = "regulator-fixed"; regulator-name = "3V3"; regulator-min-microvolt = <3300000>; @@ -318,49 +318,49 @@ leds { compatible = "gpio-leds"; - user@1 { + user1 { label = "v2m:green:user1"; gpios = <&v2m_led_gpios 0 0>; linux,default-trigger = "heartbeat"; }; - user@2 { + user2 { label = "v2m:green:user2"; gpios = <&v2m_led_gpios 1 0>; linux,default-trigger = "mmc0"; }; - user@3 { + user3 { label = "v2m:green:user3"; gpios = <&v2m_led_gpios 2 0>; linux,default-trigger = "cpu0"; }; - user@4 { + user4 { label = "v2m:green:user4"; gpios = <&v2m_led_gpios 3 0>; linux,default-trigger = "cpu1"; }; - user@5 { + user5 { label = "v2m:green:user5"; gpios = <&v2m_led_gpios 4 0>; linux,default-trigger = "cpu2"; }; - user@6 { + user6 { label = "v2m:green:user6"; gpios = <&v2m_led_gpios 5 0>; linux,default-trigger = "cpu3"; }; - user@7 { + user7 { label = "v2m:green:user7"; gpios = <&v2m_led_gpios 6 0>; linux,default-trigger = "cpu4"; }; - user@8 { + user8 { label = "v2m:green:user8"; gpios = <&v2m_led_gpios 7 0>; linux,default-trigger = "cpu5"; @@ -371,7 +371,7 @@ compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; - osc@0 { + oscclk0 { /* MCC static memory clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 0>; @@ -380,7 +380,7 @@ clock-output-names = "v2m:oscclk0"; }; - v2m_oscclk1: osc@1 { + v2m_oscclk1: oscclk1 { /* CLCD clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 1>; @@ -389,7 +389,7 @@ clock-output-names = "v2m:oscclk1"; }; - v2m_oscclk2: osc@2 { + v2m_oscclk2: oscclk2 { /* IO FPGA peripheral clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 2>; @@ -398,7 +398,7 @@ clock-output-names = "v2m:oscclk2"; }; - volt@0 { + volt-vio { /* Logic level voltage */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 0>; @@ -407,34 +407,34 @@ label = "VIO"; }; - temp@0 { + temp-mcc { /* MCC internal operating temperature */ compatible = "arm,vexpress-temp"; arm,vexpress-sysreg,func = <4 0>; label = "MCC"; }; - reset@0 { + reset { compatible = "arm,vexpress-reset"; arm,vexpress-sysreg,func = <5 0>; }; - muxfpga@0 { + muxfpga { compatible = "arm,vexpress-muxfpga"; arm,vexpress-sysreg,func = <7 0>; }; - shutdown@0 { + shutdown { compatible = "arm,vexpress-shutdown"; arm,vexpress-sysreg,func = <8 0>; }; - reboot@0 { + reboot { compatible = "arm,vexpress-reboot"; arm,vexpress-sysreg,func = <9 0>; }; - dvimode@0 { + dvimode { compatible = "arm,vexpress-dvimode"; arm,vexpress-sysreg,func = <11 0>; }; diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi index 47e4a115adef..c6393d3f1719 100644 --- a/arch/arm/boot/dts/vexpress-v2m.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m.dtsi @@ -74,19 +74,19 @@ compatible = "arm,vexpress-sysreg"; reg = <0x00000 0x1000>; - v2m_led_gpios: sys_led@08 { + v2m_led_gpios: sys_led { compatible = "arm,vexpress-sysreg,sys_led"; gpio-controller; #gpio-cells = <2>; }; - v2m_mmc_gpios: sys_mci@48 { + v2m_mmc_gpios: sys_mci { compatible = "arm,vexpress-sysreg,sys_mci"; gpio-controller; #gpio-cells = <2>; }; - v2m_flash_gpios: sys_flash@4c { + v2m_flash_gpios: sys_flash { compatible = "arm,vexpress-sysreg,sys_flash"; gpio-controller; #gpio-cells = <2>; @@ -285,7 +285,7 @@ }; }; - v2m_fixed_3v3: fixedregulator@0 { + v2m_fixed_3v3: fixed-regulator-0 { compatible = "regulator-fixed"; regulator-name = "3V3"; regulator-min-microvolt = <3300000>; @@ -317,49 +317,49 @@ leds { compatible = "gpio-leds"; - user@1 { + user1 { label = "v2m:green:user1"; gpios = <&v2m_led_gpios 0 0>; linux,default-trigger = "heartbeat"; }; - user@2 { + user2 { label = "v2m:green:user2"; gpios = <&v2m_led_gpios 1 0>; linux,default-trigger = "mmc0"; }; - user@3 { + user3 { label = "v2m:green:user3"; gpios = <&v2m_led_gpios 2 0>; linux,default-trigger = "cpu0"; }; - user@4 { + user4 { label = "v2m:green:user4"; gpios = <&v2m_led_gpios 3 0>; linux,default-trigger = "cpu1"; }; - user@5 { + user5 { label = "v2m:green:user5"; gpios = <&v2m_led_gpios 4 0>; linux,default-trigger = "cpu2"; }; - user@6 { + user6 { label = "v2m:green:user6"; gpios = <&v2m_led_gpios 5 0>; linux,default-trigger = "cpu3"; }; - user@7 { + user7 { label = "v2m:green:user7"; gpios = <&v2m_led_gpios 6 0>; linux,default-trigger = "cpu4"; }; - user@8 { + user8 { label = "v2m:green:user8"; gpios = <&v2m_led_gpios 7 0>; linux,default-trigger = "cpu5"; @@ -370,7 +370,7 @@ compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; - osc@0 { + oscclk0 { /* MCC static memory clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 0>; @@ -379,7 +379,7 @@ clock-output-names = "v2m:oscclk0"; }; - v2m_oscclk1: osc@1 { + v2m_oscclk1: oscclk1 { /* CLCD clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 1>; @@ -388,7 +388,7 @@ clock-output-names = "v2m:oscclk1"; }; - v2m_oscclk2: osc@2 { + v2m_oscclk2: oscclk2 { /* IO FPGA peripheral clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 2>; @@ -397,7 +397,7 @@ clock-output-names = "v2m:oscclk2"; }; - volt@0 { + volt-vio { /* Logic level voltage */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 0>; @@ -406,34 +406,34 @@ label = "VIO"; }; - temp@0 { + temp-mcc { /* MCC internal operating temperature */ compatible = "arm,vexpress-temp"; arm,vexpress-sysreg,func = <4 0>; label = "MCC"; }; - reset@0 { + reset { compatible = "arm,vexpress-reset"; arm,vexpress-sysreg,func = <5 0>; }; - muxfpga@0 { + muxfpga { compatible = "arm,vexpress-muxfpga"; arm,vexpress-sysreg,func = <7 0>; }; - shutdown@0 { + shutdown { compatible = "arm,vexpress-shutdown"; arm,vexpress-sysreg,func = <8 0>; }; - reboot@0 { + reboot { compatible = "arm,vexpress-reboot"; arm,vexpress-sysreg,func = <9 0>; }; - dvimode@0 { + dvimode { compatible = "arm,vexpress-dvimode"; arm,vexpress-sysreg,func = <11 0>; }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts index 9420053acc14..50af17728491 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts @@ -55,14 +55,14 @@ compatible = "arm,hdlcd"; reg = <0 0x2b000000 0 0x1000>; interrupts = <0 85 4>; - clocks = <&oscclk5>; + clocks = <&hdlcd_clk>; clock-names = "pxlclk"; }; memory-controller@2b0a0000 { compatible = "arm,pl341", "arm,primecell"; reg = <0 0x2b0a0000 0 0x1000>; - clocks = <&oscclk7>; + clocks = <&sys_pll>; clock-names = "apb_pclk"; }; @@ -71,7 +71,7 @@ status = "disabled"; reg = <0 0x2b060000 0 0x1000>; interrupts = <0 98 4>; - clocks = <&oscclk7>; + clocks = <&sys_pll>; clock-names = "apb_pclk"; }; @@ -92,7 +92,7 @@ reg = <0 0x7ffd0000 0 0x1000>; interrupts = <0 86 4>, <0 87 4>; - clocks = <&oscclk7>; + clocks = <&sys_pll>; clock-names = "apb_pclk"; }; @@ -104,7 +104,7 @@ <0 89 4>, <0 90 4>, <0 91 4>; - clocks = <&oscclk7>; + clocks = <&sys_pll>; clock-names = "apb_pclk"; }; @@ -126,7 +126,7 @@ compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; - osc@0 { + oscclk0 { /* CPU PLL reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 0>; @@ -135,7 +135,7 @@ clock-output-names = "oscclk0"; }; - osc@4 { + oscclk4 { /* Multiplexed AXI master clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 4>; @@ -144,7 +144,7 @@ clock-output-names = "oscclk4"; }; - oscclk5: osc@5 { + hdlcd_clk: oscclk5 { /* HDLCD PLL reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 5>; @@ -153,7 +153,7 @@ clock-output-names = "oscclk5"; }; - smbclk: osc@6 { + smbclk: oscclk6 { /* SMB clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 6>; @@ -162,7 +162,7 @@ clock-output-names = "oscclk6"; }; - oscclk7: osc@7 { + sys_pll: oscclk7 { /* SYS PLL reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 7>; @@ -171,7 +171,7 @@ clock-output-names = "oscclk7"; }; - osc@8 { + oscclk8 { /* DDR2 PLL reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 8>; @@ -180,7 +180,7 @@ clock-output-names = "oscclk8"; }; - volt@0 { + volt-cores { /* CPU core voltage */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 0>; @@ -191,28 +191,28 @@ label = "Cores"; }; - amp@0 { + amp-cores { /* Total current for the two cores */ compatible = "arm,vexpress-amp"; arm,vexpress-sysreg,func = <3 0>; label = "Cores"; }; - temp@0 { + temp-dcc { /* DCC internal temperature */ compatible = "arm,vexpress-temp"; arm,vexpress-sysreg,func = <4 0>; label = "DCC"; }; - power@0 { + power-cores { /* Total power */ compatible = "arm,vexpress-power"; arm,vexpress-sysreg,func = <12 0>; label = "Cores"; }; - energy@0 { + energy { /* Total energy */ compatible = "arm,vexpress-energy"; arm,vexpress-sysreg,func = <13 0>; @@ -220,7 +220,7 @@ }; }; - smb { + smb@08000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 17f63f7dfd9e..41690b90c805 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -109,7 +109,7 @@ compatible = "arm,hdlcd"; reg = <0 0x2b000000 0 0x1000>; interrupts = <0 85 4>; - clocks = <&oscclk5>; + clocks = <&hdlcd_clk>; clock-names = "pxlclk"; }; @@ -227,7 +227,7 @@ compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; - osc@0 { + oscclk0 { /* A15 PLL 0 reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 0>; @@ -236,7 +236,7 @@ clock-output-names = "oscclk0"; }; - osc@1 { + oscclk1 { /* A15 PLL 1 reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 1>; @@ -245,7 +245,7 @@ clock-output-names = "oscclk1"; }; - osc@2 { + oscclk2 { /* A7 PLL 0 reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 2>; @@ -254,7 +254,7 @@ clock-output-names = "oscclk2"; }; - osc@3 { + oscclk3 { /* A7 PLL 1 reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 3>; @@ -263,7 +263,7 @@ clock-output-names = "oscclk3"; }; - osc@4 { + oscclk4 { /* External AXI master clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 4>; @@ -272,7 +272,7 @@ clock-output-names = "oscclk4"; }; - oscclk5: osc@5 { + hdlcd_clk: oscclk5 { /* HDLCD PLL reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 5>; @@ -281,7 +281,7 @@ clock-output-names = "oscclk5"; }; - smbclk: osc@6 { + smbclk: oscclk6 { /* Static memory controller clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 6>; @@ -290,7 +290,7 @@ clock-output-names = "oscclk6"; }; - osc@7 { + oscclk7 { /* SYS PLL reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 7>; @@ -299,7 +299,7 @@ clock-output-names = "oscclk7"; }; - osc@8 { + oscclk8 { /* DDR2 PLL reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 8>; @@ -308,7 +308,7 @@ clock-output-names = "oscclk8"; }; - volt@0 { + volt-a15 { /* A15 CPU core voltage */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 0>; @@ -319,7 +319,7 @@ label = "A15 Vcore"; }; - volt@1 { + volt-a7 { /* A7 CPU core voltage */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 1>; @@ -330,49 +330,49 @@ label = "A7 Vcore"; }; - amp@0 { + amp-a15 { /* Total current for the two A15 cores */ compatible = "arm,vexpress-amp"; arm,vexpress-sysreg,func = <3 0>; label = "A15 Icore"; }; - amp@1 { + amp-a7 { /* Total current for the three A7 cores */ compatible = "arm,vexpress-amp"; arm,vexpress-sysreg,func = <3 1>; label = "A7 Icore"; }; - temp@0 { + temp-dcc { /* DCC internal temperature */ compatible = "arm,vexpress-temp"; arm,vexpress-sysreg,func = <4 0>; label = "DCC"; }; - power@0 { + power-a15 { /* Total power for the two A15 cores */ compatible = "arm,vexpress-power"; arm,vexpress-sysreg,func = <12 0>; label = "A15 Pcore"; }; - power@1 { + power-a7 { /* Total power for the three A7 cores */ compatible = "arm,vexpress-power"; arm,vexpress-sysreg,func = <12 1>; label = "A7 Pcore"; }; - energy@0 { + energy-a15 { /* Total energy for the two A15 cores */ compatible = "arm,vexpress-energy"; arm,vexpress-sysreg,func = <13 0>, <13 1>; label = "A15 Jcore"; }; - energy@2 { + energy-a7 { /* Total energy for the three A7 cores */ compatible = "arm,vexpress-energy"; arm,vexpress-sysreg,func = <13 2>, <13 3>; @@ -387,7 +387,7 @@ clocks = <&oscclk6a>; clock-names = "apb_pclk"; port { - etb_in_port: endpoint@0 { + etb_in_port: endpoint { slave-mode; remote-endpoint = <&replicator_out_port0>; }; @@ -401,7 +401,7 @@ clocks = <&oscclk6a>; clock-names = "apb_pclk"; port { - tpiu_in_port: endpoint@0 { + tpiu_in_port: endpoint { slave-mode; remote-endpoint = <&replicator_out_port1>; }; @@ -578,7 +578,7 @@ }; }; - smb { + smb@08000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts index d2709b73316b..7c7a1b465316 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts @@ -57,14 +57,14 @@ compatible = "arm,hdlcd"; reg = <0x2a110000 0x1000>; interrupts = <0 85 4>; - clocks = <&oscclk3>; + clocks = <&hdlcd_clk>; clock-names = "pxlclk"; }; memory-controller@2a150000 { compatible = "arm,pl341", "arm,primecell"; reg = <0x2a150000 0x1000>; - clocks = <&oscclk1>; + clocks = <&axi_clk>; clock-names = "apb_pclk"; }; @@ -73,7 +73,7 @@ reg = <0x2a190000 0x1000>; interrupts = <0 86 4>, <0 87 4>; - clocks = <&oscclk1>; + clocks = <&axi_clk>; clock-names = "apb_pclk"; }; @@ -93,7 +93,7 @@ "arm,cortex-a9-global-timer"; reg = <0x2c000200 0x20>; interrupts = <1 11 0x304>; - clocks = <&oscclk0>; + clocks = <&cpu_clk>; }; watchdog@2c000620 { @@ -128,7 +128,7 @@ compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; - oscclk0: osc@0 { + cpu_clk: oscclk0 { /* CPU and internal AXI reference clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 0>; @@ -137,7 +137,7 @@ clock-output-names = "oscclk0"; }; - oscclk1: osc@1 { + axi_clk: oscclk1 { /* Multiplexed AXI master clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 1>; @@ -146,7 +146,7 @@ clock-output-names = "oscclk1"; }; - osc@2 { + oscclk2 { /* DDR2 */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 2>; @@ -155,7 +155,7 @@ clock-output-names = "oscclk2"; }; - oscclk3: osc@3 { + hdlcd_clk: oscclk3 { /* HDLCD */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 3>; @@ -164,7 +164,7 @@ clock-output-names = "oscclk3"; }; - osc@4 { + oscclk4 { /* Test chip gate configuration */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 4>; @@ -173,7 +173,7 @@ clock-output-names = "oscclk4"; }; - smbclk: osc@5 { + smbclk: oscclk5 { /* SMB clock */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 5>; @@ -182,7 +182,7 @@ clock-output-names = "oscclk5"; }; - temp@0 { + temp-dcc { /* DCC internal operating temperature */ compatible = "arm,vexpress-temp"; arm,vexpress-sysreg,func = <4 0>; @@ -190,7 +190,7 @@ }; }; - smb { + smb@08000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts index d949facba376..cbf658b97265 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts @@ -190,7 +190,7 @@ compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; - osc@0 { + oscclk0: extsaxiclk { /* ACLK clock to the AXI master port on the test chip */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 0>; @@ -199,7 +199,7 @@ clock-output-names = "extsaxiclk"; }; - oscclk1: osc@1 { + oscclk1: clcdclk { /* Reference clock for the CLCD */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 1>; @@ -208,7 +208,7 @@ clock-output-names = "clcdclk"; }; - smbclk: oscclk2: osc@2 { + smbclk: oscclk2: tcrefclk { /* Reference clock for the test chip internal PLLs */ compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 2>; @@ -217,7 +217,7 @@ clock-output-names = "tcrefclk"; }; - volt@0 { + volt-vd10 { /* Test Chip internal logic voltage */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 0>; @@ -226,7 +226,7 @@ label = "VD10"; }; - volt@1 { + volt-vd10-s2 { /* PL310, L2 cache, RAM cell supply (not PL310 logic) */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 1>; @@ -235,7 +235,7 @@ label = "VD10_S2"; }; - volt@2 { + volt-vd10-s3 { /* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 2>; @@ -244,7 +244,7 @@ label = "VD10_S3"; }; - volt@3 { + volt-vcc1v8 { /* DDR2 SDRAM and Test Chip DDR2 I/O supply */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 3>; @@ -253,7 +253,7 @@ label = "VCC1V8"; }; - volt@4 { + volt-ddr2vtt { /* DDR2 SDRAM VTT termination voltage */ compatible = "arm,vexpress-volt"; arm,vexpress-sysreg,func = <2 4>; @@ -262,7 +262,7 @@ label = "DDR2VTT"; }; - volt@5 { + volt-vcc3v3 { /* Local board supply for miscellaneous logic external to the Test Chip */ arm,vexpress-sysreg,func = <2 5>; compatible = "arm,vexpress-volt"; @@ -271,28 +271,28 @@ label = "VCC3V3"; }; - amp@0 { + amp-vd10-s2 { /* PL310, L2 cache, RAM cell supply (not PL310 logic) */ compatible = "arm,vexpress-amp"; arm,vexpress-sysreg,func = <3 0>; label = "VD10_S2"; }; - amp@1 { + amp-vd10-s3 { /* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */ compatible = "arm,vexpress-amp"; arm,vexpress-sysreg,func = <3 1>; label = "VD10_S3"; }; - power@0 { + power-vd10-s2 { /* PL310, L2 cache, RAM cell supply (not PL310 logic) */ compatible = "arm,vexpress-power"; arm,vexpress-sysreg,func = <12 0>; label = "PVD10_S2"; }; - power@1 { + power-vd10-s3 { /* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */ compatible = "arm,vexpress-power"; arm,vexpress-sysreg,func = <12 1>; @@ -300,7 +300,7 @@ }; }; - smb { + smb@04000000 { compatible = "simple-bus"; #address-cells = <2>; -- GitLab From 2b4e38fd7c12d37ee1887834eb45ae30b5e8f4e3 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Thu, 14 Apr 2016 16:39:18 +0100 Subject: [PATCH 4108/9938] ARM: dts: vexpress: Add external expansion bus to DT The VExpress development platform has an external expansion bus which can be used for additional hardware (e.g. LogicTile Express daughter boards). Add this bus to the VExpress CoreTile device-trees.The bus is described for a CoreTile occupying site 1. Acked-by: Liviu Dudau Signed-off-by: Brian Starkey Signed-off-by: Sudeep Holla --- arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 13 +++++++++++++ arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 13 +++++++++++++ arch/arm/boot/dts/vexpress-v2p-ca5s.dts | 13 +++++++++++++ arch/arm/boot/dts/vexpress-v2p-ca9.dts | 13 +++++++++++++ 4 files changed, 52 insertions(+) diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts index 50af17728491..102838fcc588 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts @@ -280,4 +280,17 @@ /include/ "vexpress-v2m-rs1.dtsi" }; + + site2: hsb@40000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x40000000 0x3fef0000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 3>; + interrupt-map = <0 0 &gic 0 36 4>, + <0 1 &gic 0 37 4>, + <0 2 &gic 0 38 4>, + <0 3 &gic 0 39 4>; + }; }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 41690b90c805..0205c97efdef 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -638,4 +638,17 @@ /include/ "vexpress-v2m-rs1.dtsi" }; + + site2: hsb@40000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x40000000 0x3fef0000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 3>; + interrupt-map = <0 0 &gic 0 36 4>, + <0 1 &gic 0 37 4>, + <0 2 &gic 0 38 4>, + <0 3 &gic 0 39 4>; + }; }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts index 7c7a1b465316..1acecaf4b13d 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts @@ -250,4 +250,17 @@ /include/ "vexpress-v2m-rs1.dtsi" }; + + site2: hsb@40000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40000000 0x40000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 3>; + interrupt-map = <0 0 &gic 0 36 4>, + <0 1 &gic 0 37 4>, + <0 2 &gic 0 38 4>, + <0 3 &gic 0 39 4>; + }; }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts index cbf658b97265..b608a03ee02f 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts @@ -359,4 +359,17 @@ /include/ "vexpress-v2m.dtsi" }; + + site2: hsb@e0000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0xe0000000 0x20000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 3>; + interrupt-map = <0 0 &gic 0 36 4>, + <0 1 &gic 0 37 4>, + <0 2 &gic 0 38 4>, + <0 3 &gic 0 39 4>; + }; }; -- GitLab From 3c77f7c9e96bc40ac6985dd595cdd551afd34f2e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 9 Apr 2016 13:02:28 +0200 Subject: [PATCH 4109/9938] USB: serial: ftdi_sio: constify ftdi_sio_quirk structures The ftdi_sio_quirk structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Johan Hovold --- drivers/usb/serial/ftdi_sio.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3a814e802dee..00820809139a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -93,27 +93,27 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial); static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); -static struct ftdi_sio_quirk ftdi_jtag_quirk = { +static const struct ftdi_sio_quirk ftdi_jtag_quirk = { .probe = ftdi_jtag_probe, }; -static struct ftdi_sio_quirk ftdi_NDI_device_quirk = { +static const struct ftdi_sio_quirk ftdi_NDI_device_quirk = { .probe = ftdi_NDI_device_setup, }; -static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { +static const struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { .port_probe = ftdi_USB_UIRT_setup, }; -static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { +static const struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { .port_probe = ftdi_HE_TIRA1_setup, }; -static struct ftdi_sio_quirk ftdi_stmclite_quirk = { +static const struct ftdi_sio_quirk ftdi_stmclite_quirk = { .probe = ftdi_stmclite_probe, }; -static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { +static const struct ftdi_sio_quirk ftdi_8u2232c_quirk = { .probe = ftdi_8u2232c_probe, }; @@ -1775,7 +1775,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) static int ftdi_sio_probe(struct usb_serial *serial, const struct usb_device_id *id) { - struct ftdi_sio_quirk *quirk = + const struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info; if (quirk && quirk->probe) { @@ -1792,7 +1792,7 @@ static int ftdi_sio_probe(struct usb_serial *serial, static int ftdi_sio_port_probe(struct usb_serial_port *port) { struct ftdi_private *priv; - struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); + const struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); -- GitLab From 8c34d82e9dc67bb06e20e015ec677f82b72a26b3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 20 Apr 2016 14:26:58 -0400 Subject: [PATCH 4110/9938] USB: serial: use IS_ENABLED() instead of checking for FOO || FOO_MODULE The IS_ENABLED() macro checks if a Kconfig symbol has been enabled either built-in or as a module, use that macro instead of open coding the same. Signed-off-by: Javier Martinez Canillas Signed-off-by: Johan Hovold --- drivers/usb/serial/usb-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 46f1f13b41f1..7ecf4ff86b9a 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -815,7 +815,7 @@ static int usb_serial_probe(struct usb_interface *interface, } } -#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE) +#if IS_ENABLED(CONFIG_USB_SERIAL_PL2303) /* BEGIN HORRIBLE HACK FOR PL2303 */ /* this is needed due to the looney way its endpoints are set up */ if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && -- GitLab From 2f2219bea21118511c23d24dba5f2145f870a7db Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Thu, 7 Apr 2016 10:43:50 -0700 Subject: [PATCH 4111/9938] ixgbe: Add register wait for slow links Use a new register to wait for previous register writes to complete before issuing a register read. This is needed when slower links are in use. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 21 +++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 2 files changed, 22 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 657e999befcb..517f06e6c3d8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -371,6 +371,27 @@ u32 ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg) if (ixgbe_removed(reg_addr)) return IXGBE_FAILED_READ_REG; + if (unlikely(hw->phy.nw_mng_if_sel & + IXGBE_NW_MNG_IF_SEL_ENABLE_10_100M)) { + struct ixgbe_adapter *adapter; + int i; + + for (i = 0; i < 200; ++i) { + value = readl(reg_addr + IXGBE_MAC_SGMII_BUSY); + if (likely(!value)) + goto writes_completed; + if (value == IXGBE_FAILED_READ_REG) { + ixgbe_remove_adapter(hw); + return IXGBE_FAILED_READ_REG; + } + udelay(5); + } + + adapter = hw->back; + e_warn(hw, "register writes incomplete %08x\n", value); + } + +writes_completed: value = readl(reg_addr + reg); if (unlikely(value == IXGBE_FAILED_READ_REG)) ixgbe_check_remove(hw, reg); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index ba3b837c7e9d..29a1c423543b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1131,6 +1131,7 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_XPCSS 0x04290 #define IXGBE_MFLCN 0x04294 #define IXGBE_SERDESC 0x04298 +#define IXGBE_MAC_SGMII_BUSY 0x04298 #define IXGBE_MACS 0x0429C #define IXGBE_AUTOC 0x042A0 #define IXGBE_LINKS 0x042A4 -- GitLab From d72d6c19b583afc09ace22baf80b29b11139a8f3 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 7 Apr 2016 15:58:39 -0700 Subject: [PATCH 4112/9938] ixgbevf: refactor ethtool stats handling This brings the logic closer to how we handle the stats in ixgbe and it sets us up for introducing per-queue stats. Use IXGBEVF_STAT and IXGBEVF_NETDEV_STAT for accessing the driver and netdev stats respectively. This way we don't have to calculate the stats based on register values which could lead to the counters not being initialized properly when the interface is down. IXGBEVF_QUEUE_STATS_LEN is set to include the number of queues. Also some defines were renamed to use the IXGBEVF prefix. Signed-off-by: Emil Tantilov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ethtool.c | 126 ++++++++++--------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index d7aa4b203f40..cd4d311ea0b6 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -42,65 +42,62 @@ #define IXGBE_ALL_RAR_ENTRIES 16 +enum {NETDEV_STATS, IXGBEVF_STATS}; + struct ixgbe_stats { char stat_string[ETH_GSTRING_LEN]; - struct { - int sizeof_stat; - int stat_offset; - int base_stat_offset; - int saved_reset_offset; - }; + int type; + int sizeof_stat; + int stat_offset; }; -#define IXGBEVF_STAT(m, b, r) { \ - .sizeof_stat = FIELD_SIZEOF(struct ixgbevf_adapter, m), \ - .stat_offset = offsetof(struct ixgbevf_adapter, m), \ - .base_stat_offset = offsetof(struct ixgbevf_adapter, b), \ - .saved_reset_offset = offsetof(struct ixgbevf_adapter, r) \ +#define IXGBEVF_STAT(_name, _stat) { \ + .stat_string = _name, \ + .type = IXGBEVF_STATS, \ + .sizeof_stat = FIELD_SIZEOF(struct ixgbevf_adapter, _stat), \ + .stat_offset = offsetof(struct ixgbevf_adapter, _stat) \ } -#define IXGBEVF_ZSTAT(m) { \ - .sizeof_stat = FIELD_SIZEOF(struct ixgbevf_adapter, m), \ - .stat_offset = offsetof(struct ixgbevf_adapter, m), \ - .base_stat_offset = -1, \ - .saved_reset_offset = -1 \ +#define IXGBEVF_NETDEV_STAT(_net_stat) { \ + .stat_string = #_net_stat, \ + .type = NETDEV_STATS, \ + .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \ + .stat_offset = offsetof(struct net_device_stats, _net_stat) \ } -static const struct ixgbe_stats ixgbe_gstrings_stats[] = { - {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc, - stats.saved_reset_vfgprc)}, - {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc, - stats.saved_reset_vfgptc)}, - {"rx_bytes", IXGBEVF_STAT(stats.vfgorc, stats.base_vfgorc, - stats.saved_reset_vfgorc)}, - {"tx_bytes", IXGBEVF_STAT(stats.vfgotc, stats.base_vfgotc, - stats.saved_reset_vfgotc)}, - {"tx_busy", IXGBEVF_ZSTAT(tx_busy)}, - {"tx_restart_queue", IXGBEVF_ZSTAT(restart_queue)}, - {"tx_timeout_count", IXGBEVF_ZSTAT(tx_timeout_count)}, - {"multicast", IXGBEVF_STAT(stats.vfmprc, stats.base_vfmprc, - stats.saved_reset_vfmprc)}, - {"rx_csum_offload_errors", IXGBEVF_ZSTAT(hw_csum_rx_error)}, +static struct ixgbe_stats ixgbevf_gstrings_stats[] = { + IXGBEVF_NETDEV_STAT(rx_packets), + IXGBEVF_NETDEV_STAT(tx_packets), + IXGBEVF_NETDEV_STAT(rx_bytes), + IXGBEVF_NETDEV_STAT(tx_bytes), + IXGBEVF_STAT("tx_busy", tx_busy), + IXGBEVF_STAT("tx_restart_queue", restart_queue), + IXGBEVF_STAT("tx_timeout_count", tx_timeout_count), + IXGBEVF_NETDEV_STAT(multicast), + IXGBEVF_STAT("rx_csum_offload_errors", hw_csum_rx_error), #ifdef BP_EXTENDED_STATS - {"rx_bp_poll_yield", IXGBEVF_ZSTAT(bp_rx_yields)}, - {"rx_bp_cleaned", IXGBEVF_ZSTAT(bp_rx_cleaned)}, - {"rx_bp_misses", IXGBEVF_ZSTAT(bp_rx_missed)}, - {"tx_bp_napi_yield", IXGBEVF_ZSTAT(bp_tx_yields)}, - {"tx_bp_cleaned", IXGBEVF_ZSTAT(bp_tx_cleaned)}, - {"tx_bp_misses", IXGBEVF_ZSTAT(bp_tx_missed)}, + IXGBEVF_STAT("rx_bp_poll_yield", bp_rx_yields), + IXGBEVF_STAT("rx_bp_cleaned", bp_rx_cleaned), + IXGBEVF_STAT("rx_bp_misses", bp_rx_missed), + IXGBEVF_STAT("tx_bp_napi_yield", bp_tx_yields), + IXGBEVF_STAT("tx_bp_cleaned", bp_tx_cleaned), + IXGBEVF_STAT("tx_bp_misses", bp_tx_missed), #endif }; -#define IXGBE_QUEUE_STATS_LEN 0 -#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) +#define IXGBEVF_QUEUE_STATS_LEN ( \ + (((struct ixgbevf_adapter *)netdev_priv(netdev))->num_tx_queues + \ + ((struct ixgbevf_adapter *)netdev_priv(netdev))->num_rx_queues) * \ + (sizeof(struct ixgbe_stats) / sizeof(u64))) +#define IXGBEVF_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbevf_gstrings_stats) -#define IXGBEVF_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) +#define IXGBEVF_STATS_LEN (IXGBEVF_GLOBAL_STATS_LEN + IXGBEVF_QUEUE_STATS_LEN) static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Link test (on/offline)" }; -#define IXGBE_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) +#define IXGBEVF_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) static int ixgbevf_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) @@ -396,9 +393,9 @@ static int ixgbevf_get_sset_count(struct net_device *dev, int stringset) { switch (stringset) { case ETH_SS_TEST: - return IXGBE_TEST_LEN; + return IXGBEVF_TEST_LEN; case ETH_SS_STATS: - return IXGBE_GLOBAL_STATS_LEN; + return IXGBEVF_GLOBAL_STATS_LEN; default: return -EINVAL; } @@ -408,8 +405,11 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); - char *base = (char *)adapter; + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *net_stats; int i; + char *p; + #ifdef BP_EXTENDED_STATS u64 rx_yields = 0, rx_cleaned = 0, rx_missed = 0, tx_yields = 0, tx_cleaned = 0, tx_missed = 0; @@ -436,22 +436,24 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, #endif ixgbevf_update_stats(adapter); - for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { - char *p = base + ixgbe_gstrings_stats[i].stat_offset; - char *b = base + ixgbe_gstrings_stats[i].base_stat_offset; - char *r = base + ixgbe_gstrings_stats[i].saved_reset_offset; - - if (ixgbe_gstrings_stats[i].sizeof_stat == sizeof(u64)) { - if (ixgbe_gstrings_stats[i].base_stat_offset >= 0) - data[i] = *(u64 *)p - *(u64 *)b + *(u64 *)r; - else - data[i] = *(u64 *)p; - } else { - if (ixgbe_gstrings_stats[i].base_stat_offset >= 0) - data[i] = *(u32 *)p - *(u32 *)b + *(u32 *)r; - else - data[i] = *(u32 *)p; + net_stats = dev_get_stats(netdev, &temp); + for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { + switch (ixgbevf_gstrings_stats[i].type) { + case NETDEV_STATS: + p = (char *)net_stats + + ixgbevf_gstrings_stats[i].stat_offset; + break; + case IXGBEVF_STATS: + p = (char *)adapter + + ixgbevf_gstrings_stats[i].stat_offset; + break; + default: + data[i] = 0; + continue; } + + data[i] = (ixgbevf_gstrings_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } } @@ -464,11 +466,11 @@ static void ixgbevf_get_strings(struct net_device *netdev, u32 stringset, switch (stringset) { case ETH_SS_TEST: memcpy(data, *ixgbe_gstrings_test, - IXGBE_TEST_LEN * ETH_GSTRING_LEN); + IXGBEVF_TEST_LEN * ETH_GSTRING_LEN); break; case ETH_SS_STATS: - for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { - memcpy(p, ixgbe_gstrings_stats[i].stat_string, + for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { + memcpy(p, ixgbevf_gstrings_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } -- GitLab From a02a5a53418a6039893f5d5a9373cf18080fded2 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 7 Apr 2016 15:58:44 -0700 Subject: [PATCH 4113/9938] ixgbevf: add support for per-queue ethtool stats Implement per-queue statistics for packets, bytes and busy poll specific counters. Signed-off-by: Emil Tantilov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ethtool.c | 127 +++++++++++++------ drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 10 -- 2 files changed, 91 insertions(+), 46 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index cd4d311ea0b6..64d5c6e9343e 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -75,14 +75,6 @@ static struct ixgbe_stats ixgbevf_gstrings_stats[] = { IXGBEVF_STAT("tx_timeout_count", tx_timeout_count), IXGBEVF_NETDEV_STAT(multicast), IXGBEVF_STAT("rx_csum_offload_errors", hw_csum_rx_error), -#ifdef BP_EXTENDED_STATS - IXGBEVF_STAT("rx_bp_poll_yield", bp_rx_yields), - IXGBEVF_STAT("rx_bp_cleaned", bp_rx_cleaned), - IXGBEVF_STAT("rx_bp_misses", bp_rx_missed), - IXGBEVF_STAT("tx_bp_napi_yield", bp_tx_yields), - IXGBEVF_STAT("tx_bp_cleaned", bp_tx_cleaned), - IXGBEVF_STAT("tx_bp_misses", bp_tx_missed), -#endif }; #define IXGBEVF_QUEUE_STATS_LEN ( \ @@ -389,13 +381,13 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, return err; } -static int ixgbevf_get_sset_count(struct net_device *dev, int stringset) +static int ixgbevf_get_sset_count(struct net_device *netdev, int stringset) { switch (stringset) { case ETH_SS_TEST: return IXGBEVF_TEST_LEN; case ETH_SS_STATS: - return IXGBEVF_GLOBAL_STATS_LEN; + return IXGBEVF_STATS_LEN; default: return -EINVAL; } @@ -407,34 +399,11 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct rtnl_link_stats64 temp; const struct rtnl_link_stats64 *net_stats; - int i; + unsigned int start; + struct ixgbevf_ring *ring; + int i, j; char *p; -#ifdef BP_EXTENDED_STATS - u64 rx_yields = 0, rx_cleaned = 0, rx_missed = 0, - tx_yields = 0, tx_cleaned = 0, tx_missed = 0; - - for (i = 0; i < adapter->num_rx_queues; i++) { - rx_yields += adapter->rx_ring[i]->stats.yields; - rx_cleaned += adapter->rx_ring[i]->stats.cleaned; - rx_yields += adapter->rx_ring[i]->stats.yields; - } - - for (i = 0; i < adapter->num_tx_queues; i++) { - tx_yields += adapter->tx_ring[i]->stats.yields; - tx_cleaned += adapter->tx_ring[i]->stats.cleaned; - tx_yields += adapter->tx_ring[i]->stats.yields; - } - - adapter->bp_rx_yields = rx_yields; - adapter->bp_rx_cleaned = rx_cleaned; - adapter->bp_rx_missed = rx_missed; - - adapter->bp_tx_yields = tx_yields; - adapter->bp_tx_cleaned = tx_cleaned; - adapter->bp_tx_missed = tx_missed; -#endif - ixgbevf_update_stats(adapter); net_stats = dev_get_stats(netdev, &temp); for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { @@ -455,11 +424,68 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, data[i] = (ixgbevf_gstrings_stats[i].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } + + /* populate Tx queue data */ + for (j = 0; j < adapter->num_tx_queues; j++) { + ring = adapter->tx_ring[j]; + if (!ring) { + data[i++] = 0; + data[i++] = 0; +#ifdef BP_EXTENDED_STATS + data[i++] = 0; + data[i++] = 0; + data[i++] = 0; +#endif + continue; + } + + do { + start = u64_stats_fetch_begin_irq(&ring->syncp); + data[i] = ring->stats.packets; + data[i + 1] = ring->stats.bytes; + } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); + i += 2; +#ifdef BP_EXTENDED_STATS + data[i] = ring->stats.yields; + data[i + 1] = ring->stats.misses; + data[i + 2] = ring->stats.cleaned; + i += 3; +#endif + } + + /* populate Rx queue data */ + for (j = 0; j < adapter->num_rx_queues; j++) { + ring = adapter->rx_ring[j]; + if (!ring) { + data[i++] = 0; + data[i++] = 0; +#ifdef BP_EXTENDED_STATS + data[i++] = 0; + data[i++] = 0; + data[i++] = 0; +#endif + continue; + } + + do { + start = u64_stats_fetch_begin_irq(&ring->syncp); + data[i] = ring->stats.packets; + data[i + 1] = ring->stats.bytes; + } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); + i += 2; +#ifdef BP_EXTENDED_STATS + data[i] = ring->stats.yields; + data[i + 1] = ring->stats.misses; + data[i + 2] = ring->stats.cleaned; + i += 3; +#endif + } } static void ixgbevf_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { + struct ixgbevf_adapter *adapter = netdev_priv(netdev); char *p = (char *)data; int i; @@ -474,6 +500,35 @@ static void ixgbevf_get_strings(struct net_device *netdev, u32 stringset, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } + + for (i = 0; i < adapter->num_tx_queues; i++) { + sprintf(p, "tx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; +#ifdef BP_EXTENDED_STATS + sprintf(p, "tx_queue_%u_bp_napi_yield", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_queue_%u_bp_misses", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_queue_%u_bp_cleaned", i); + p += ETH_GSTRING_LEN; +#endif /* BP_EXTENDED_STATS */ + } + for (i = 0; i < adapter->num_rx_queues; i++) { + sprintf(p, "rx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; +#ifdef BP_EXTENDED_STATS + sprintf(p, "rx_queue_%u_bp_poll_yield", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_bp_misses", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_bp_cleaned", i); + p += ETH_GSTRING_LEN; +#endif /* BP_EXTENDED_STATS */ + } break; } } diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 5ac60eefb0cd..5ca3794aeb2e 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -422,16 +422,6 @@ struct ixgbevf_adapter { unsigned int tx_ring_count; unsigned int rx_ring_count; -#ifdef BP_EXTENDED_STATS - u64 bp_rx_yields; - u64 bp_rx_cleaned; - u64 bp_rx_missed; - - u64 bp_tx_yields; - u64 bp_tx_cleaned; - u64 bp_tx_missed; -#endif - u8 __iomem *io_addr; /* Mainly for iounmap use */ u32 link_speed; bool link_up; -- GitLab From bde569874b2afa6571eee6c373b236a8cd292115 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 21 Apr 2016 03:23:58 -0300 Subject: [PATCH 4114/9938] [media] tw686x-video: test for 60Hz instead of 50Hz When determining if the standard is 50 or 60 Hz it is standard practice to test for 60 Hz instead of 50 Hz. This doesn't matter normally, except if the user specifies both 60 and 50 Hz standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw686x/tw686x-video.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index 118e9fac9f28..60d38f19134b 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -25,7 +25,7 @@ #define TW686X_INPUTS_PER_CH 4 #define TW686X_VIDEO_WIDTH 720 -#define TW686X_VIDEO_HEIGHT(id) ((id & V4L2_STD_625_50) ? 576 : 480) +#define TW686X_VIDEO_HEIGHT(id) ((id & V4L2_STD_525_60) ? 480 : 576) static const struct tw686x_format formats[] = { { @@ -517,10 +517,10 @@ static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id) reg_write(vc->dev, SDT[vc->ch], val); val = reg_read(vc->dev, VIDEO_CONTROL1); - if (id & V4L2_STD_625_50) - val |= (1 << (SYS_MODE_DMA_SHIFT + vc->ch)); - else + if (id & V4L2_STD_525_60) val &= ~(1 << (SYS_MODE_DMA_SHIFT + vc->ch)); + else + val |= (1 << (SYS_MODE_DMA_SHIFT + vc->ch)); reg_write(vc->dev, VIDEO_CONTROL1, val); /* -- GitLab From 57c7598711b820b4253bcee94ec750ebc1c63af6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Apr 2016 06:06:58 -0300 Subject: [PATCH 4115/9938] [media] videodev2.h: remove 'experimental' annotations Most of what is marked as 'experimental' has been around for years. Time to drop that annotation. The only remaining 'experimental' bits of the API are the debug ioctls and structs: these should remain experimental since the only application that should use this is v4l2-dbg. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/videodev2.h | 38 +++++++++------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index e895975c5b0e..8f951917be74 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -138,10 +138,7 @@ enum v4l2_buf_type { V4L2_BUF_TYPE_VBI_OUTPUT = 5, V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, -#if 1 - /* Experimental */ V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, -#endif V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10, V4L2_BUF_TYPE_SDR_CAPTURE = 11, @@ -657,8 +654,7 @@ struct v4l2_fmtdesc { #define V4L2_FMT_FLAG_COMPRESSED 0x0001 #define V4L2_FMT_FLAG_EMULATED 0x0002 -#if 1 - /* Experimental Frame Size and frame rate enumeration */ + /* Frame Size and frame rate enumeration */ /* * F R A M E S I Z E E N U M E R A T I O N */ @@ -724,7 +720,6 @@ struct v4l2_frmivalenum { __u32 reserved[2]; /* Reserved space for future use */ }; -#endif /* * T I M E C O D E @@ -1728,8 +1723,6 @@ struct v4l2_audioout { /* * M P E G S E R V I C E S - * - * NOTE: EXPERIMENTAL API */ #if 1 #define V4L2_ENC_IDX_FRAME_I (0) @@ -2259,46 +2252,35 @@ struct v4l2_create_buffers { #define VIDIOC_ENCODER_CMD _IOWR('V', 77, struct v4l2_encoder_cmd) #define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct v4l2_encoder_cmd) -/* Experimental, meant for debugging, testing and internal use. - Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. - You must be root to use these ioctls. Never use these in applications! */ +/* + * Experimental, meant for debugging, testing and internal use. + * Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. + * You must be root to use these ioctls. Never use these in applications! + */ #define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) #define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) - #define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) #define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) #define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) #define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) #define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) - -/* Experimental, the below two ioctls may change over the next couple of kernel - versions */ #define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) #define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) - -/* Experimental selection API */ #define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) #define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) - -/* Experimental, these two ioctls may change over the next couple of kernel - versions. */ #define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) #define VIDIOC_TRY_DECODER_CMD _IOWR('V', 97, struct v4l2_decoder_cmd) - -/* Experimental, these three ioctls may change over the next couple of kernel - versions. */ #define VIDIOC_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings) #define VIDIOC_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings) #define VIDIOC_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap) - -/* Experimental, this ioctl may change over the next couple of kernel - versions. */ #define VIDIOC_ENUM_FREQ_BANDS _IOWR('V', 101, struct v4l2_frequency_band) -/* Experimental, meant for debugging, testing and internal use. - Never use these in applications! */ +/* + * Experimental, meant for debugging, testing and internal use. + * Never use this in applications! + */ #define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info) #define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) -- GitLab From c8f8cca483aa3ec1beb63ee8633de9c76bb3fe6f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 22 Apr 2016 18:48:03 +0200 Subject: [PATCH 4116/9938] arm64: ptdump: use static initializers for vmemmap region boundaries There is no need to initialize the vmemmap region boundaries dynamically, since they are compile time constants. So just add these constants to the global struct initializer, and drop the dynamic assignment and related code. Acked-by: Mark Rutland Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/mm/dump.c | 49 ++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c index a21f47421b0c..493461159462 100644 --- a/arch/arm64/mm/dump.c +++ b/arch/arm64/mm/dump.c @@ -32,37 +32,21 @@ struct addr_marker { const char *name; }; -enum address_markers_idx { - MODULES_START_NR = 0, - MODULES_END_NR, - VMALLOC_START_NR, - VMALLOC_END_NR, - FIXADDR_START_NR, - FIXADDR_END_NR, - PCI_START_NR, - PCI_END_NR, +static const struct addr_marker address_markers[] = { + { MODULES_VADDR, "Modules start" }, + { MODULES_END, "Modules end" }, + { VMALLOC_START, "vmalloc() Area" }, + { VMALLOC_END, "vmalloc() End" }, + { FIXADDR_START, "Fixmap start" }, + { FIXADDR_TOP, "Fixmap end" }, + { PCI_IO_START, "PCI I/O start" }, + { PCI_IO_END, "PCI I/O end" }, #ifdef CONFIG_SPARSEMEM_VMEMMAP - VMEMMAP_START_NR, - VMEMMAP_END_NR, + { VMEMMAP_START, "vmemmap start" }, + { VMEMMAP_START + VMEMMAP_SIZE, "vmemmap end" }, #endif - KERNEL_SPACE_NR, -}; - -static struct addr_marker address_markers[] = { - { MODULES_VADDR, "Modules start" }, - { MODULES_END, "Modules end" }, - { VMALLOC_START, "vmalloc() Area" }, - { VMALLOC_END, "vmalloc() End" }, - { FIXADDR_START, "Fixmap start" }, - { FIXADDR_TOP, "Fixmap end" }, - { PCI_IO_START, "PCI I/O start" }, - { PCI_IO_END, "PCI I/O end" }, -#ifdef CONFIG_SPARSEMEM_VMEMMAP - { 0, "vmemmap start" }, - { 0, "vmemmap end" }, -#endif - { PAGE_OFFSET, "Linear Mapping" }, - { -1, NULL }, + { PAGE_OFFSET, "Linear Mapping" }, + { -1, NULL }, }; /* @@ -347,13 +331,6 @@ static int ptdump_init(void) for (j = 0; j < pg_level[i].num; j++) pg_level[i].mask |= pg_level[i].bits[j].mask; -#ifdef CONFIG_SPARSEMEM_VMEMMAP - address_markers[VMEMMAP_START_NR].start_address = - (unsigned long)virt_to_page(PAGE_OFFSET); - address_markers[VMEMMAP_END_NR].start_address = - (unsigned long)virt_to_page(high_memory); -#endif - pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops); return pe ? 0 : -ENOMEM; -- GitLab From d8fc68a04d2ffa7327a5fd89d4cd9f2fe24659d3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 22 Apr 2016 18:48:04 +0200 Subject: [PATCH 4117/9938] arm64: ptdump: add region marker for kasan shadow region Annotate the KASAN shadow region with boundary markers, so that its mappings stand out in the page table dumper output. Acked-by: Mark Rutland Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/mm/dump.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c index 493461159462..8404190fe2bd 100644 --- a/arch/arm64/mm/dump.c +++ b/arch/arm64/mm/dump.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,10 @@ struct addr_marker { }; static const struct addr_marker address_markers[] = { +#ifdef CONFIG_KASAN + { KASAN_SHADOW_START, "Kasan shadow start" }, + { KASAN_SHADOW_END, "Kasan shadow end" }, +#endif { MODULES_VADDR, "Modules start" }, { MODULES_END, "Modules end" }, { VMALLOC_START, "vmalloc() Area" }, -- GitLab From 079dda54fe6e43b3db919e3ac3838a1355464c78 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Apr 2016 06:06:59 -0300 Subject: [PATCH 4118/9938] [media] DocBook media: drop 'experimental' annotations Drop the 'experimental' annotations. The only remaining part of the API that is still marked 'experimental' are the debug ioctls/structs, and that is intentional. Only the v4l2-dbg application should use those. All others have been around for years, so it is time to drop the 'experimental' designation. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 38 ------------------- Documentation/DocBook/media/v4l/controls.xml | 31 --------------- Documentation/DocBook/media/v4l/dev-sdr.xml | 6 --- .../DocBook/media/v4l/dev-subdev.xml | 6 --- Documentation/DocBook/media/v4l/io.xml | 6 --- .../DocBook/media/v4l/selection-api.xml | 9 +---- .../DocBook/media/v4l/subdev-formats.xml | 6 --- .../DocBook/media/v4l/vidioc-create-bufs.xml | 6 --- .../media/v4l/vidioc-dv-timings-cap.xml | 6 --- .../media/v4l/vidioc-enum-dv-timings.xml | 6 --- .../media/v4l/vidioc-enum-freq-bands.xml | 6 --- .../DocBook/media/v4l/vidioc-expbuf.xml | 6 --- .../DocBook/media/v4l/vidioc-g-selection.xml | 6 --- .../DocBook/media/v4l/vidioc-prepare-buf.xml | 6 --- .../media/v4l/vidioc-query-dv-timings.xml | 6 --- .../v4l/vidioc-subdev-enum-frame-interval.xml | 6 --- .../v4l/vidioc-subdev-enum-frame-size.xml | 6 --- .../v4l/vidioc-subdev-enum-mbus-code.xml | 6 --- .../DocBook/media/v4l/vidioc-subdev-g-fmt.xml | 6 --- .../v4l/vidioc-subdev-g-frame-interval.xml | 6 --- .../media/v4l/vidioc-subdev-g-selection.xml | 6 --- 21 files changed, 1 insertion(+), 185 deletions(-) diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 5399e8904715..82fa328abd58 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2685,10 +2685,6 @@ hardware may support both. and may change in the future. - - Video Output Overlay (OSD) Interface, . - &VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER; ioctls. @@ -2696,40 +2692,6 @@ ioctls. &VIDIOC-DBG-G-CHIP-INFO; ioctl. - - &VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and - &VIDIOC-DV-TIMINGS-CAP; ioctls. - - - Flash API. - - - &VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls. - - - Selection API. - - - Sub-device selection API: &VIDIOC-SUBDEV-G-SELECTION; - and &VIDIOC-SUBDEV-S-SELECTION; ioctls. - - - Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl. - - - Vendor and device specific media bus pixel formats. - . - - - Importing DMABUF file descriptors as a new IO method described - in . - - - Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl. - - - Software Defined Radio (SDR) Interface, . - diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 361040e6b0f4..81efa883f67d 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -4272,13 +4272,6 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
    Flash Control Reference - - Experimental - - This is an experimental -interface and may change in the future. - - The V4L2 flash controls are intended to provide generic access to flash controller devices. Flash controller devices are @@ -4743,14 +4736,6 @@ interface and may change in the future.
    Image Source Control Reference - - Experimental - - This is an experimental interface and may - change in the future. - - The Image Source control class is intended for low-level control of image source devices such as image sensors. The @@ -4862,14 +4847,6 @@ interface and may change in the future.
    Image Process Control Reference - - Experimental - - This is an experimental interface and may - change in the future. - - The Image Process control class is intended for low-level control of image processing functions. Unlike @@ -4955,14 +4932,6 @@ interface and may change in the future.
    Digital Video Control Reference - - Experimental - - This is an experimental interface and may - change in the future. - - The Digital Video control class is intended to control receivers and transmitters for VGA, diff --git a/Documentation/DocBook/media/v4l/dev-sdr.xml b/Documentation/DocBook/media/v4l/dev-sdr.xml index a659771f7b7c..6da1157fb5bd 100644 --- a/Documentation/DocBook/media/v4l/dev-sdr.xml +++ b/Documentation/DocBook/media/v4l/dev-sdr.xml @@ -1,11 +1,5 @@ Software Defined Radio Interface (SDR) - - Experimental - This is an experimental - interface and may change in the future. - - SDR is an abbreviation of Software Defined Radio, the radio device which uses application software for modulation or demodulation. This interface diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml index 4f0ba58c9bd9..f4bc27af83eb 100644 --- a/Documentation/DocBook/media/v4l/dev-subdev.xml +++ b/Documentation/DocBook/media/v4l/dev-subdev.xml @@ -1,11 +1,5 @@ Sub-device Interface - - Experimental - This is an experimental - interface and may change in the future. - - The complex nature of V4L2 devices, where hardware is often made of several integrated circuits that need to interact with each other in a controlled way, leads to complex V4L2 drivers. The drivers usually reflect diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml index 144158b3a5ac..e09025db92bd 100644 --- a/Documentation/DocBook/media/v4l/io.xml +++ b/Documentation/DocBook/media/v4l/io.xml @@ -475,12 +475,6 @@ rest should be evident.
    Streaming I/O (DMA buffer importing) - - Experimental - This is an experimental - interface and may change in the future. - - The DMABUF framework provides a generic method for sharing buffers between multiple devices. Device drivers that support DMABUF can export a DMA buffer to userspace as a file descriptor (known as the exporter role), import a diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml index 28cbded766c9..b764cba150d1 100644 --- a/Documentation/DocBook/media/v4l/selection-api.xml +++ b/Documentation/DocBook/media/v4l/selection-api.xml @@ -1,13 +1,6 @@
    - Experimental API for cropping, composing and scaling - - - Experimental - - This is an experimental -interface and may change in the future. - + API for cropping, composing and scaling
    Introduction diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml index 4e73345e3eab..199c84e3aede 100644 --- a/Documentation/DocBook/media/v4l/subdev-formats.xml +++ b/Documentation/DocBook/media/v4l/subdev-formats.xml @@ -4002,12 +4002,6 @@ see .
    Vendor and Device Specific Formats - - Experimental - This is an experimental -interface and may change in the future. - - This section lists complex data formats that are either vendor or device specific. diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml index d81fa0d4016b..6528e97b8990 100644 --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - This ioctl is used to create buffers for memory mapped or user pointer or DMA buffer I/O. It can be used as an alternative or in diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml index b6f47a6b14d5..ca9ffce9b4c1 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - To query the capabilities of the DV receiver/transmitter applications initialize the pad field to 0, zero the reserved array of &v4l2-dv-timings-cap; and call the VIDIOC_DV_TIMINGS_CAP ioctl on a video node diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml index 70ca76d1e6d2..9b3d42018b69 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - While some DV receivers or transmitters support a wide range of timings, others support only a limited number of timings. With this ioctl applications can enumerate a list of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also supports other diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml index 4e8ea65f7282..a0608abc1ab8 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - Enumerates the frequency bands that a tuner or modulator supports. To do this applications initialize the tuner, type and index fields, diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml index 0ae0b6a915d0..a6558a676ef3 100644 --- a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - This ioctl is an extension to the memory mapping I/O method, therefore it is available only for V4L2_MEMORY_MMAP buffers. It can be used to export a diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml index 7865351688da..9523bc5650f9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml @@ -50,12 +50,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - The ioctls are used to query and configure selection rectangles. To query the cropping (composing) rectangle set &v4l2-selection; diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml index fa7ad7e33228..7bde698760e4 100644 --- a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml @@ -48,12 +48,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - Applications can optionally call the VIDIOC_PREPARE_BUF ioctl to pass ownership of the buffer to the driver before actually enqueuing it, using the diff --git a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml index 0c93677d16b4..d41bf47ee5a2 100644 --- a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml @@ -50,12 +50,6 @@ input Description - - Experimental - This is an experimental - interface and may change in the future. - - The hardware may be able to detect the current DV timings automatically, similar to sensing the video standard. To do so, applications call VIDIOC_QUERY_DV_TIMINGS with a pointer to a diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml index cff59f5cbf04..9d0251a27e5f 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - This ioctl lets applications enumerate available frame intervals on a given sub-device pad. Frame intervals only makes sense for sub-devices that can control the frame period on their own. This includes, for instance, diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml index abd545ede67a..9b91b8332ba9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - This ioctl allows applications to enumerate all frame sizes supported by a sub-device on the given pad for the given media bus format. Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE; diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml index 0bcb278fd062..c67256ada87a 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - To enumerate media bus formats available at a given sub-device pad applications initialize the pad, which and index fields of &v4l2-subdev-mbus-code-enum; and diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml index a67cde6f8c54..781089cba453 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml @@ -50,12 +50,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - These ioctls are used to negotiate the frame format at specific subdev pads in the image pipeline. diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml index 0bc3ea22d31f..848ec789ddaa 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml @@ -50,12 +50,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - These ioctls are used to get and set the frame interval at specific subdev pads in the image pipeline. The frame interval only makes sense for sub-devices that can control the frame period on their own. This includes, diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml index c62a7360719b..8346b2e4a703 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - The selections are used to configure various image processing functionality performed by the subdevs which affect the image size. This currently includes cropping, scaling and -- GitLab From 20e01b264cc8557def19671defbad275828132f1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Apr 2016 07:03:30 -0300 Subject: [PATCH 4119/9938] [media] cx231xx: silence uninitialized variable warning We print an uninitialized "actlen" variable on the error path. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index f497888d94bf..6741fd02b50f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -752,7 +752,8 @@ EXPORT_SYMBOL_GPL(cx231xx_set_mode); int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size) { int errCode = 0; - int actlen, ret = -ENOMEM; + int actlen = -1; + int ret = -ENOMEM; u32 *buffer; buffer = kzalloc(4096, GFP_KERNEL); -- GitLab From a0254a70b4f91396ad04b1225dd7c10a680d38ff Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 8 Apr 2016 16:19:29 -0700 Subject: [PATCH 4120/9938] ixgbe: Use correct FC setup function for x550em_a Somehow the wrong fc_setup function was used for x550em_a, so correct that. Also set setup_link to NULL as its value is determined later, just like it is with X550EM_x. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index ea25f001f3bb..a17e398d56b8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2926,13 +2926,13 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = { .get_media_type = ixgbe_get_media_type_X550em, .get_san_mac_addr = NULL, .get_wwn_prefix = NULL, - .setup_link = &ixgbe_setup_mac_link_X540, + .setup_link = NULL, /* defined later */ .get_link_capabilities = ixgbe_get_link_capabilities_X550em, .get_bus_info = ixgbe_get_bus_info_X550em, .setup_sfp = ixgbe_setup_sfp_modules_X550em, .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, - .setup_fc = ixgbe_setup_fc_generic, + .setup_fc = ixgbe_setup_fc_x550em, .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, }; -- GitLab From 937feeed3f0ae8a0389d5732f6db63dd912acd99 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Apr 2016 10:03:37 -0300 Subject: [PATCH 4121/9938] [media] adv7180: fix broken standards handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The adv7180 attempts to autodetect the standard. Unfortunately this is seriously broken. This patch removes the autodetect completely. Only the querystd op will detect the standard. Since the design of the adv7180 requires that you switch to a special autodetect mode you cannot call querystd when you are streaming. So the s_stream op has been added so we know whether we are streaming or not, and if we are, then querystd returns EBUSY. After testing this with a signal generator is became obvious that a sleep is needed between changing the standard to autodetect and reading the status. So the autodetect can never have worked well. The s_std call now just sets the new standard without any querying. If the driver supports the interrupt, then when it detects a standard change it will signal that by sending the V4L2_EVENT_SOURCE_CHANGE event. With these changes this driver now behaves like all other video receivers. Signed-off-by: Hans Verkuil Acked-by: Federico Vaga Tested-by: Niklas Söderlund Acked-by: Lars-Peter Clausen Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 118 ++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 38 deletions(-) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 51a92b3b20cc..5a75a9154e2e 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -26,8 +26,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -192,8 +193,8 @@ struct adv7180_state { struct mutex mutex; /* mutual excl. when accessing chip */ int irq; v4l2_std_id curr_norm; - bool autodetect; bool powered; + bool streaming; u8 input; struct i2c_client *client; @@ -338,12 +339,26 @@ static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) if (err) return err; - /* when we are interrupt driven we know the state */ - if (!state->autodetect || state->irq > 0) - *std = state->curr_norm; - else - err = __adv7180_status(state, NULL, std); + if (state->streaming) { + err = -EBUSY; + goto unlock; + } + + err = adv7180_set_video_standard(state, + ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); + if (err) + goto unlock; + msleep(100); + __adv7180_status(state, NULL, std); + + err = v4l2_std_to_adv7180(state->curr_norm); + if (err < 0) + goto unlock; + + err = adv7180_set_video_standard(state, err); + +unlock: mutex_unlock(&state->mutex); return err; } @@ -387,23 +402,13 @@ static int adv7180_program_std(struct adv7180_state *state) { int ret; - if (state->autodetect) { - ret = adv7180_set_video_standard(state, - ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); - if (ret < 0) - return ret; - - __adv7180_status(state, NULL, &state->curr_norm); - } else { - ret = v4l2_std_to_adv7180(state->curr_norm); - if (ret < 0) - return ret; - - ret = adv7180_set_video_standard(state, ret); - if (ret < 0) - return ret; - } + ret = v4l2_std_to_adv7180(state->curr_norm); + if (ret < 0) + return ret; + ret = adv7180_set_video_standard(state, ret); + if (ret < 0) + return ret; return 0; } @@ -415,18 +420,12 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) if (ret) return ret; - /* all standards -> autodetect */ - if (std == V4L2_STD_ALL) { - state->autodetect = true; - } else { - /* Make sure we can support this std */ - ret = v4l2_std_to_adv7180(std); - if (ret < 0) - goto out; + /* Make sure we can support this std */ + ret = v4l2_std_to_adv7180(std); + if (ret < 0) + goto out; - state->curr_norm = std; - state->autodetect = false; - } + state->curr_norm = std; ret = adv7180_program_std(state); out: @@ -747,6 +746,40 @@ static int adv7180_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm) return 0; } +static int adv7180_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct adv7180_state *state = to_state(sd); + int ret; + + /* It's always safe to stop streaming, no need to take the lock */ + if (!enable) { + state->streaming = enable; + return 0; + } + + /* Must wait until querystd released the lock */ + ret = mutex_lock_interruptible(&state->mutex); + if (ret) + return ret; + state->streaming = enable; + mutex_unlock(&state->mutex); + return 0; +} + +static int adv7180_subscribe_event(struct v4l2_subdev *sd, + struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_SOURCE_CHANGE: + return v4l2_src_change_event_subdev_subscribe(sd, fh, sub); + case V4L2_EVENT_CTRL: + return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); + default: + return -EINVAL; + } +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .s_std = adv7180_s_std, .g_std = adv7180_g_std, @@ -756,10 +789,13 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { .g_mbus_config = adv7180_g_mbus_config, .cropcap = adv7180_cropcap, .g_tvnorms = adv7180_g_tvnorms, + .s_stream = adv7180_s_stream, }; static const struct v4l2_subdev_core_ops adv7180_core_ops = { .s_power = adv7180_s_power, + .subscribe_event = adv7180_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { @@ -784,8 +820,14 @@ static irqreturn_t adv7180_irq(int irq, void *devid) /* clear */ adv7180_write(state, ADV7180_REG_ICR3, isr3); - if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) - __adv7180_status(state, NULL, &state->curr_norm); + if (isr3 & ADV7180_IRQ3_AD_CHANGE) { + static const struct v4l2_event src_ch = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, + }; + + v4l2_subdev_notify_event(&state->sd, &src_ch); + } mutex_unlock(&state->mutex); return IRQ_HANDLED; @@ -1230,7 +1272,7 @@ static int adv7180_probe(struct i2c_client *client, state->irq = client->irq; mutex_init(&state->mutex); - state->autodetect = true; + state->curr_norm = V4L2_STD_NTSC; if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED) state->powered = true; else @@ -1238,7 +1280,7 @@ static int adv7180_probe(struct i2c_client *client, state->input = 0; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); - sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; ret = adv7180_init_controls(state); if (ret) -- GitLab From 7b9f31f3b3cab9bc367ba4da45af129ff858ce52 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Apr 2016 10:03:38 -0300 Subject: [PATCH 4122/9938] [media] sta2x11_vip: fix s_std The s_std ioctl was broken in this driver, partially due to the changes to the adv7180 driver (this affected the handling of V4L2_STD_ALL) and partially because the new standard was never stored in vip->std. The handling of V4L2_STD_ALL has been rewritten to just call querystd and the new standard is now stored correctly. Signed-off-by: Hans Verkuil Acked-by: Federico Vaga Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/sta2x11/sta2x11_vip.c | 26 ++++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 753411cbbc9a..c79623ca5fc3 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -444,27 +444,21 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) { struct sta2x11_vip *vip = video_drvdata(file); - v4l2_std_id oldstd = vip->std, newstd; + v4l2_std_id oldstd = vip->std; int status; - if (V4L2_STD_ALL == std) { - v4l2_subdev_call(vip->decoder, video, s_std, std); - ssleep(2); - v4l2_subdev_call(vip->decoder, video, querystd, &newstd); - v4l2_subdev_call(vip->decoder, video, g_input_status, &status); - if (status & V4L2_IN_ST_NO_SIGNAL) + /* + * This is here for backwards compatibility only. + * The use of V4L2_STD_ALL to trigger a querystd is non-standard. + */ + if (std == V4L2_STD_ALL) { + v4l2_subdev_call(vip->decoder, video, querystd, &std); + if (std == V4L2_STD_UNKNOWN) return -EIO; - std = vip->std = newstd; - if (oldstd != std) { - if (V4L2_STD_525_60 & std) - vip->format = formats_60[0]; - else - vip->format = formats_50[0]; - } - return 0; } - if (oldstd != std) { + if (vip->std != std) { + vip->std = std; if (V4L2_STD_525_60 & std) vip->format = formats_60[0]; else -- GitLab From 4319a7976722f6925b5bbbdac417d87a0cbde859 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Tue, 12 Apr 2016 19:25:10 -0400 Subject: [PATCH 4123/9938] ixgbe: Add work around for empty SFP+ cage crosstalk It is possible on some systems that crosstalk could lead to link flap on empty SFP+ cages. A new NVM bit was defined to let SW know it needs to implement the work around which consists of verifying that there is a module in the cage before acting on the LSC. Signed-off-by: Don Skidmore Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 39 +++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 3 files changed, 42 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 94e39c13e7d4..22cf2a9430b5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -803,6 +803,8 @@ struct ixgbe_adapter { #define IXGBE_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ u32 rss_key[IXGBE_RSS_KEY_SIZE / sizeof(u32)]; + + bool need_crosstalk_fix; }; static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 517f06e6c3d8..09d7c8bdcd5c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -5572,6 +5572,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) struct pci_dev *pdev = adapter->pdev; unsigned int rss, fdir; u32 fwsm; + u16 device_caps; #ifdef CONFIG_IXGBE_DCB int j; struct tc_configuration *tc; @@ -5737,6 +5738,22 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->tx_ring_count = IXGBE_DEFAULT_TXD; adapter->rx_ring_count = IXGBE_DEFAULT_RXD; + /* Cache bit indicating need for crosstalk fix */ + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X550EM_x: + case ixgbe_mac_x550em_a: + hw->mac.ops.get_device_caps(hw, &device_caps); + if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR) + adapter->need_crosstalk_fix = false; + else + adapter->need_crosstalk_fix = true; + break; + default: + adapter->need_crosstalk_fix = false; + break; + } + /* set default work limits */ adapter->tx_work_limit = IXGBE_DEFAULT_TX_WORK; @@ -6659,6 +6676,18 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter) link_up = true; } + /* If Crosstalk fix enabled do the sanity check of making sure + * the SFP+ cage is empty. + */ + if (adapter->need_crosstalk_fix) { + u32 sfp_cage_full; + + sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & + IXGBE_ESDP_SDP2; + if (ixgbe_is_sfp(hw) && link_up && !sfp_cage_full) + link_up = false; + } + if (adapter->ixgbe_ieee_pfc) pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en); @@ -7005,6 +7034,16 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; s32 err; + /* If crosstalk fix enabled verify the SFP+ cage is full */ + if (adapter->need_crosstalk_fix) { + u32 sfp_cage_full; + + sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & + IXGBE_ESDP_SDP2; + if (!sfp_cage_full) + return; + } + /* not searching for SFP so there is nothing to do here */ if (!(adapter->flags2 & IXGBE_FLAG2_SEARCH_FOR_SFP) && !(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET)) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 29a1c423543b..8e7decb3e078 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -2124,6 +2124,7 @@ enum { #define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3 #define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 #define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 +#define IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR BIT(7) #define IXGBE_FW_LESM_PARAMETERS_PTR 0x2 #define IXGBE_FW_LESM_STATE_1 0x1 #define IXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */ -- GitLab From dc96208582156fafd946368853bc108096dee9f9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Apr 2016 08:11:41 -0300 Subject: [PATCH 4124/9938] [media] sta2x11: remove unused vars Changeset 7b9f31f3b3ca ("[media] sta2x11_vip: fix s_std") removed autodetect code, but it kept two vars unused: drivers/media/pci/sta2x11/sta2x11_vip.c: In function 'vidioc_s_std': drivers/media/pci/sta2x11/sta2x11_vip.c:448:6: warning: unused variable 'status' [-Wunused-variable] int status; ^ drivers/media/pci/sta2x11/sta2x11_vip.c:447:14: warning: unused variable 'oldstd' [-Wunused-variable] v4l2_std_id oldstd = vip->std; ^ Remove them. Fixes: 7b9f31f3b3ca ("[media] sta2x11_vip: fix s_std") Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/sta2x11/sta2x11_vip.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index c79623ca5fc3..1fc195f89686 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -444,8 +444,6 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) { struct sta2x11_vip *vip = video_drvdata(file); - v4l2_std_id oldstd = vip->std; - int status; /* * This is here for backwards compatibility only. -- GitLab From c040a71f1a79caa132f718ef533d47ec63a0efd2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Apr 2016 10:03:40 -0300 Subject: [PATCH 4125/9938] [media] tc358743: drop bogus comment The control in question is not a private control, so drop that comment. Copy-and-paste left-over. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 73e0cef0ea61..6cf6d06737a5 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1863,7 +1863,6 @@ static int tc358743_probe(struct i2c_client *client, /* control handlers */ v4l2_ctrl_handler_init(&state->hdl, 3); - /* private controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&state->hdl, NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); -- GitLab From 035677761fec4a472491d53f4dfa5dbc8edd2f7a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Apr 2016 10:03:41 -0300 Subject: [PATCH 4126/9938] [media] media/i2c/adv*: make controls inheritable instead of private Marking these controls as private seemed a good idea at one time, but in practice it makes no sense. So drop this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ad9389b.c | 8 -------- drivers/media/i2c/adv7511.c | 6 ------ drivers/media/i2c/adv7604.c | 8 -------- drivers/media/i2c/adv7842.c | 6 ------ 4 files changed, 28 deletions(-) diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 788967dadd29..0462f461e679 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -1130,8 +1130,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * hdl = &state->hdl; v4l2_ctrl_handler_init(hdl, 5); - /* private controls */ - state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, 0, V4L2_DV_TX_MODE_DVI_D); @@ -1151,12 +1149,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * goto err_hdl; } - state->hdmi_mode_ctrl->is_private = true; - state->hotplug_ctrl->is_private = true; - state->rx_sense_ctrl->is_private = true; - state->have_edid0_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - state->pad.flags = MEDIA_PAD_FL_SINK; err = media_entity_pads_init(&sd->entity, 1, &state->pad); if (err) diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index bd822f032b08..39271c35da48 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -1502,12 +1502,6 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * err = hdl->error; goto err_hdl; } - state->hdmi_mode_ctrl->is_private = true; - state->hotplug_ctrl->is_private = true; - state->rx_sense_ctrl->is_private = true; - state->have_edid0_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - state->pad.flags = MEDIA_PAD_FL_SINK; err = media_entity_pads_init(&sd->entity, 1, &state->pad); if (err) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 41a1bfc5eaa7..beb2841ceae5 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -3141,7 +3141,6 @@ static int adv76xx_probe(struct i2c_client *client, if (ctrl) ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; - /* private controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, (1 << state->info->num_dv_ports) - 1, 0, 0); @@ -3164,13 +3163,6 @@ static int adv76xx_probe(struct i2c_client *client, err = hdl->error; goto err_hdl; } - state->detect_tx_5v_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - if (adv76xx_has_afe(state)) - state->analog_sampling_phase_ctrl->is_private = true; - state->free_run_color_manual_ctrl->is_private = true; - state->free_run_color_ctrl->is_private = true; - if (adv76xx_s_detect_tx_5v_ctrl(sd)) { err = -ENODEV; goto err_hdl; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 7ccb85d45224..ecaacb0a6fa1 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -3300,12 +3300,6 @@ static int adv7842_probe(struct i2c_client *client, err = hdl->error; goto err_hdl; } - state->detect_tx_5v_ctrl->is_private = true; - state->rgb_quantization_range_ctrl->is_private = true; - state->analog_sampling_phase_ctrl->is_private = true; - state->free_run_color_ctrl_manual->is_private = true; - state->free_run_color_ctrl->is_private = true; - if (adv7842_s_detect_tx_5v_ctrl(sd)) { err = -ENODEV; goto err_hdl; -- GitLab From b3c2fee5d66b0d1e977de1a56243002e532da6a5 Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Wed, 20 Apr 2016 09:55:12 -0500 Subject: [PATCH 4127/9938] crypto: ccp - Ensure all dependencies are specified A DMA_ENGINE requires DMADEVICES in Kconfig Signed-off-by: Gary R Hook Signed-off-by: Herbert Xu --- drivers/crypto/ccp/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig index 79cabfba2a2a..2238f77aa248 100644 --- a/drivers/crypto/ccp/Kconfig +++ b/drivers/crypto/ccp/Kconfig @@ -4,6 +4,7 @@ config CRYPTO_DEV_CCP_DD default m select HW_RANDOM select DMA_ENGINE + select DMADEVICES select CRYPTO_SHA1 select CRYPTO_SHA256 help -- GitLab From 3639ca840df953f9af6f15fc8a6bf77f19075ab1 Mon Sep 17 00:00:00 2001 From: Horia Geant? Date: Thu, 21 Apr 2016 19:24:55 +0300 Subject: [PATCH 4128/9938] crypto: talitos - fix ahash algorithms registration Provide hardware state import/export functionality, as mandated by commit 8996eafdcbad ("crypto: ahash - ensure statesize is non-zero") Cc: # 4.3+ Reported-by: Jonas Eymann Signed-off-by: Horia Geant? Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index a0d4a08313ae..f3b540153d0f 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -827,6 +827,16 @@ struct talitos_ahash_req_ctx { struct scatterlist *psrc; }; +struct talitos_export_state { + u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; + u8 buf[HASH_MAX_BLOCK_SIZE]; + unsigned int swinit; + unsigned int first; + unsigned int last; + unsigned int to_hash_later; + unsigned int nbuf; +}; + static int aead_setkey(struct crypto_aead *authenc, const u8 *key, unsigned int keylen) { @@ -1967,6 +1977,46 @@ static int ahash_digest(struct ahash_request *areq) return ahash_process_req(areq, areq->nbytes); } +static int ahash_export(struct ahash_request *areq, void *out) +{ + struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); + struct talitos_export_state *export = out; + + memcpy(export->hw_context, req_ctx->hw_context, + req_ctx->hw_context_size); + memcpy(export->buf, req_ctx->buf, req_ctx->nbuf); + export->swinit = req_ctx->swinit; + export->first = req_ctx->first; + export->last = req_ctx->last; + export->to_hash_later = req_ctx->to_hash_later; + export->nbuf = req_ctx->nbuf; + + return 0; +} + +static int ahash_import(struct ahash_request *areq, const void *in) +{ + struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); + const struct talitos_export_state *export = in; + + memset(req_ctx, 0, sizeof(*req_ctx)); + req_ctx->hw_context_size = + (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) + ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 + : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; + memcpy(req_ctx->hw_context, export->hw_context, + req_ctx->hw_context_size); + memcpy(req_ctx->buf, export->buf, export->nbuf); + req_ctx->swinit = export->swinit; + req_ctx->first = export->first; + req_ctx->last = export->last; + req_ctx->to_hash_later = export->to_hash_later; + req_ctx->nbuf = export->nbuf; + + return 0; +} + struct keyhash_result { struct completion completion; int err; @@ -2444,6 +2494,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = MD5_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "md5", .cra_driver_name = "md5-talitos", @@ -2459,6 +2510,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA1_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "sha1", .cra_driver_name = "sha1-talitos", @@ -2474,6 +2526,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA224_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "sha224", .cra_driver_name = "sha224-talitos", @@ -2489,6 +2542,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA256_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "sha256", .cra_driver_name = "sha256-talitos", @@ -2504,6 +2558,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA384_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "sha384", .cra_driver_name = "sha384-talitos", @@ -2519,6 +2574,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA512_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "sha512", .cra_driver_name = "sha512-talitos", @@ -2534,6 +2590,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = MD5_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "hmac(md5)", .cra_driver_name = "hmac-md5-talitos", @@ -2549,6 +2606,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA1_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "hmac(sha1)", .cra_driver_name = "hmac-sha1-talitos", @@ -2564,6 +2622,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA224_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "hmac(sha224)", .cra_driver_name = "hmac-sha224-talitos", @@ -2579,6 +2638,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA256_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "hmac(sha256)", .cra_driver_name = "hmac-sha256-talitos", @@ -2594,6 +2654,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA384_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "hmac(sha384)", .cra_driver_name = "hmac-sha384-talitos", @@ -2609,6 +2670,7 @@ static struct talitos_alg_template driver_algs[] = { { .type = CRYPTO_ALG_TYPE_AHASH, .alg.hash = { .halg.digestsize = SHA512_DIGEST_SIZE, + .halg.statesize = sizeof(struct talitos_export_state), .halg.base = { .cra_name = "hmac(sha512)", .cra_driver_name = "hmac-sha512-talitos", @@ -2787,6 +2849,8 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, t_alg->algt.alg.hash.finup = ahash_finup; t_alg->algt.alg.hash.digest = ahash_digest; t_alg->algt.alg.hash.setkey = ahash_setkey; + t_alg->algt.alg.hash.import = ahash_import; + t_alg->algt.alg.hash.export = ahash_export; if (!(priv->features & TALITOS_FTR_HMAC_OK) && !strncmp(alg->cra_name, "hmac", 4)) { -- GitLab From b908bd3d4c4110a8a2ed84e2b6ab56fa7201db25 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Apr 2016 12:56:31 +0300 Subject: [PATCH 4129/9938] crypto: mxc-scc - signedness bugs in mxc_scc_ablkcipher_req_init() ->src_nents and ->dst_nents are unsigned so they can't be less than zero. I fixed this by introducing a temporary "nents" variable. Fixes: d293b640ebd5 ('crypto: mxc-scc - add basic driver for the MXC SCC') Signed-off-by: Dan Carpenter Signed-off-by: Herbert Xu --- drivers/crypto/mxc-scc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/mxc-scc.c b/drivers/crypto/mxc-scc.c index 38b01bf141d3..9b348a78dd23 100644 --- a/drivers/crypto/mxc-scc.c +++ b/drivers/crypto/mxc-scc.c @@ -210,18 +210,21 @@ static int mxc_scc_ablkcipher_req_init(struct ablkcipher_request *req, struct mxc_scc_ctx *ctx) { struct mxc_scc *scc = ctx->scc; + int nents; - ctx->src_nents = sg_nents_for_len(req->src, req->nbytes); - if (ctx->src_nents < 0) { + nents = sg_nents_for_len(req->src, req->nbytes); + if (nents < 0) { dev_err(scc->dev, "Invalid number of src SC"); - return ctx->src_nents; + return nents; } + ctx->src_nents = nents; - ctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes); - if (ctx->dst_nents < 0) { + nents = sg_nents_for_len(req->dst, req->nbytes); + if (nents < 0) { dev_err(scc->dev, "Invalid number of dst SC"); - return ctx->dst_nents; + return nents; } + ctx->dst_nents = nents; ctx->size = 0; ctx->offset = 0; -- GitLab From 4c048af708a8d562d02c5a2c8f46e01de6d81e34 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Apr 2016 13:01:39 +0300 Subject: [PATCH 4130/9938] crypto: mxc-scc - fix unwinding in mxc_scc_crypto_register() There are two issues here: 1) We need to decrement "i" otherwise we unregister something that was not successfully registered. 2) The original code did not unregister the first element in the array where i is zero. Fixes: d293b640ebd5 ('crypto: mxc-scc - add basic driver for the MXC SCC') Signed-off-by: Dan Carpenter Signed-off-by: Herbert Xu --- drivers/crypto/mxc-scc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/mxc-scc.c b/drivers/crypto/mxc-scc.c index 9b348a78dd23..ff383ef83871 100644 --- a/drivers/crypto/mxc-scc.c +++ b/drivers/crypto/mxc-scc.c @@ -616,7 +616,7 @@ static struct mxc_scc_crypto_tmpl *scc_crypto_algs[] = { static int mxc_scc_crypto_register(struct mxc_scc *scc) { - unsigned int i; + int i; int err = 0; for (i = 0; i < ARRAY_SIZE(scc_crypto_algs); i++) { @@ -629,7 +629,7 @@ static int mxc_scc_crypto_register(struct mxc_scc *scc) return 0; err_out: - for (; i > 0; i--) + while (--i >= 0) crypto_unregister_alg(&scc_crypto_algs[i]->alg); return err; -- GitLab From 5e00c6040dfd367e35bdc7b8ef28861ff8b1dd64 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 22 Apr 2016 14:15:22 +0200 Subject: [PATCH 4131/9938] crypto: s5p-sss - Use common BIT macro The BIT() macro is obvious and well known, so prefer to use it instead of crafted own macro. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 95 ++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 71ca6a5d636d..b96532078d0c 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -31,45 +31,44 @@ #include #define _SBF(s, v) ((v) << (s)) -#define _BIT(b) _SBF(b, 1) /* Feed control registers */ #define SSS_REG_FCINTSTAT 0x0000 -#define SSS_FCINTSTAT_BRDMAINT _BIT(3) -#define SSS_FCINTSTAT_BTDMAINT _BIT(2) -#define SSS_FCINTSTAT_HRDMAINT _BIT(1) -#define SSS_FCINTSTAT_PKDMAINT _BIT(0) +#define SSS_FCINTSTAT_BRDMAINT BIT(3) +#define SSS_FCINTSTAT_BTDMAINT BIT(2) +#define SSS_FCINTSTAT_HRDMAINT BIT(1) +#define SSS_FCINTSTAT_PKDMAINT BIT(0) #define SSS_REG_FCINTENSET 0x0004 -#define SSS_FCINTENSET_BRDMAINTENSET _BIT(3) -#define SSS_FCINTENSET_BTDMAINTENSET _BIT(2) -#define SSS_FCINTENSET_HRDMAINTENSET _BIT(1) -#define SSS_FCINTENSET_PKDMAINTENSET _BIT(0) +#define SSS_FCINTENSET_BRDMAINTENSET BIT(3) +#define SSS_FCINTENSET_BTDMAINTENSET BIT(2) +#define SSS_FCINTENSET_HRDMAINTENSET BIT(1) +#define SSS_FCINTENSET_PKDMAINTENSET BIT(0) #define SSS_REG_FCINTENCLR 0x0008 -#define SSS_FCINTENCLR_BRDMAINTENCLR _BIT(3) -#define SSS_FCINTENCLR_BTDMAINTENCLR _BIT(2) -#define SSS_FCINTENCLR_HRDMAINTENCLR _BIT(1) -#define SSS_FCINTENCLR_PKDMAINTENCLR _BIT(0) +#define SSS_FCINTENCLR_BRDMAINTENCLR BIT(3) +#define SSS_FCINTENCLR_BTDMAINTENCLR BIT(2) +#define SSS_FCINTENCLR_HRDMAINTENCLR BIT(1) +#define SSS_FCINTENCLR_PKDMAINTENCLR BIT(0) #define SSS_REG_FCINTPEND 0x000C -#define SSS_FCINTPEND_BRDMAINTP _BIT(3) -#define SSS_FCINTPEND_BTDMAINTP _BIT(2) -#define SSS_FCINTPEND_HRDMAINTP _BIT(1) -#define SSS_FCINTPEND_PKDMAINTP _BIT(0) +#define SSS_FCINTPEND_BRDMAINTP BIT(3) +#define SSS_FCINTPEND_BTDMAINTP BIT(2) +#define SSS_FCINTPEND_HRDMAINTP BIT(1) +#define SSS_FCINTPEND_PKDMAINTP BIT(0) #define SSS_REG_FCFIFOSTAT 0x0010 -#define SSS_FCFIFOSTAT_BRFIFOFUL _BIT(7) -#define SSS_FCFIFOSTAT_BRFIFOEMP _BIT(6) -#define SSS_FCFIFOSTAT_BTFIFOFUL _BIT(5) -#define SSS_FCFIFOSTAT_BTFIFOEMP _BIT(4) -#define SSS_FCFIFOSTAT_HRFIFOFUL _BIT(3) -#define SSS_FCFIFOSTAT_HRFIFOEMP _BIT(2) -#define SSS_FCFIFOSTAT_PKFIFOFUL _BIT(1) -#define SSS_FCFIFOSTAT_PKFIFOEMP _BIT(0) +#define SSS_FCFIFOSTAT_BRFIFOFUL BIT(7) +#define SSS_FCFIFOSTAT_BRFIFOEMP BIT(6) +#define SSS_FCFIFOSTAT_BTFIFOFUL BIT(5) +#define SSS_FCFIFOSTAT_BTFIFOEMP BIT(4) +#define SSS_FCFIFOSTAT_HRFIFOFUL BIT(3) +#define SSS_FCFIFOSTAT_HRFIFOEMP BIT(2) +#define SSS_FCFIFOSTAT_PKFIFOFUL BIT(1) +#define SSS_FCFIFOSTAT_PKFIFOEMP BIT(0) #define SSS_REG_FCFIFOCTRL 0x0014 -#define SSS_FCFIFOCTRL_DESSEL _BIT(2) +#define SSS_FCFIFOCTRL_DESSEL BIT(2) #define SSS_HASHIN_INDEPENDENT _SBF(0, 0x00) #define SSS_HASHIN_CIPHER_INPUT _SBF(0, 0x01) #define SSS_HASHIN_CIPHER_OUTPUT _SBF(0, 0x02) @@ -77,52 +76,52 @@ #define SSS_REG_FCBRDMAS 0x0020 #define SSS_REG_FCBRDMAL 0x0024 #define SSS_REG_FCBRDMAC 0x0028 -#define SSS_FCBRDMAC_BYTESWAP _BIT(1) -#define SSS_FCBRDMAC_FLUSH _BIT(0) +#define SSS_FCBRDMAC_BYTESWAP BIT(1) +#define SSS_FCBRDMAC_FLUSH BIT(0) #define SSS_REG_FCBTDMAS 0x0030 #define SSS_REG_FCBTDMAL 0x0034 #define SSS_REG_FCBTDMAC 0x0038 -#define SSS_FCBTDMAC_BYTESWAP _BIT(1) -#define SSS_FCBTDMAC_FLUSH _BIT(0) +#define SSS_FCBTDMAC_BYTESWAP BIT(1) +#define SSS_FCBTDMAC_FLUSH BIT(0) #define SSS_REG_FCHRDMAS 0x0040 #define SSS_REG_FCHRDMAL 0x0044 #define SSS_REG_FCHRDMAC 0x0048 -#define SSS_FCHRDMAC_BYTESWAP _BIT(1) -#define SSS_FCHRDMAC_FLUSH _BIT(0) +#define SSS_FCHRDMAC_BYTESWAP BIT(1) +#define SSS_FCHRDMAC_FLUSH BIT(0) #define SSS_REG_FCPKDMAS 0x0050 #define SSS_REG_FCPKDMAL 0x0054 #define SSS_REG_FCPKDMAC 0x0058 -#define SSS_FCPKDMAC_BYTESWAP _BIT(3) -#define SSS_FCPKDMAC_DESCEND _BIT(2) -#define SSS_FCPKDMAC_TRANSMIT _BIT(1) -#define SSS_FCPKDMAC_FLUSH _BIT(0) +#define SSS_FCPKDMAC_BYTESWAP BIT(3) +#define SSS_FCPKDMAC_DESCEND BIT(2) +#define SSS_FCPKDMAC_TRANSMIT BIT(1) +#define SSS_FCPKDMAC_FLUSH BIT(0) #define SSS_REG_FCPKDMAO 0x005C /* AES registers */ #define SSS_REG_AES_CONTROL 0x00 -#define SSS_AES_BYTESWAP_DI _BIT(11) -#define SSS_AES_BYTESWAP_DO _BIT(10) -#define SSS_AES_BYTESWAP_IV _BIT(9) -#define SSS_AES_BYTESWAP_CNT _BIT(8) -#define SSS_AES_BYTESWAP_KEY _BIT(7) -#define SSS_AES_KEY_CHANGE_MODE _BIT(6) +#define SSS_AES_BYTESWAP_DI BIT(11) +#define SSS_AES_BYTESWAP_DO BIT(10) +#define SSS_AES_BYTESWAP_IV BIT(9) +#define SSS_AES_BYTESWAP_CNT BIT(8) +#define SSS_AES_BYTESWAP_KEY BIT(7) +#define SSS_AES_KEY_CHANGE_MODE BIT(6) #define SSS_AES_KEY_SIZE_128 _SBF(4, 0x00) #define SSS_AES_KEY_SIZE_192 _SBF(4, 0x01) #define SSS_AES_KEY_SIZE_256 _SBF(4, 0x02) -#define SSS_AES_FIFO_MODE _BIT(3) +#define SSS_AES_FIFO_MODE BIT(3) #define SSS_AES_CHAIN_MODE_ECB _SBF(1, 0x00) #define SSS_AES_CHAIN_MODE_CBC _SBF(1, 0x01) #define SSS_AES_CHAIN_MODE_CTR _SBF(1, 0x02) -#define SSS_AES_MODE_DECRYPT _BIT(0) +#define SSS_AES_MODE_DECRYPT BIT(0) #define SSS_REG_AES_STATUS 0x04 -#define SSS_AES_BUSY _BIT(2) -#define SSS_AES_INPUT_READY _BIT(1) -#define SSS_AES_OUTPUT_READY _BIT(0) +#define SSS_AES_BUSY BIT(2) +#define SSS_AES_INPUT_READY BIT(1) +#define SSS_AES_OUTPUT_READY BIT(0) #define SSS_REG_AES_IN_DATA(s) (0x10 + (s << 2)) #define SSS_REG_AES_OUT_DATA(s) (0x20 + (s << 2)) @@ -139,7 +138,7 @@ SSS_AES_REG(dev, reg)) /* HW engine modes */ -#define FLAGS_AES_DECRYPT _BIT(0) +#define FLAGS_AES_DECRYPT BIT(0) #define FLAGS_AES_MODE_MASK _SBF(1, 0x03) #define FLAGS_AES_CBC _SBF(1, 0x01) #define FLAGS_AES_CTR _SBF(1, 0x02) -- GitLab From 79152e8d085fd64484afd473ef6830b45518acba Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 22 Apr 2016 14:15:23 +0200 Subject: [PATCH 4132/9938] crypto: s5p-sss - Fix missed interrupts when working with 8 kB blocks The tcrypt testing module on Exynos5422-based Odroid XU3/4 board failed on testing 8 kB size blocks: $ sudo modprobe tcrypt sec=1 mode=500 testing speed of async ecb(aes) (ecb-aes-s5p) encryption test 0 (128 bit key, 16 byte blocks): 21971 operations in 1 seconds (351536 bytes) test 1 (128 bit key, 64 byte blocks): 21731 operations in 1 seconds (1390784 bytes) test 2 (128 bit key, 256 byte blocks): 21932 operations in 1 seconds (5614592 bytes) test 3 (128 bit key, 1024 byte blocks): 21685 operations in 1 seconds (22205440 bytes) test 4 (128 bit key, 8192 byte blocks): This was caused by a race issue of missed BRDMA_DONE ("Block cipher Receiving DMA") interrupt. Device starts processing the data in DMA mode immediately after setting length of DMA block: receiving (FCBRDMAL) or transmitting (FCBTDMAL). The driver sets these lengths from interrupt handler through s5p_set_dma_indata() function (or xxx_setdata()). However the interrupt handler was first dealing with receive buffer (dma-unmap old, dma-map new, set receive block length which starts the operation), then with transmit buffer and finally was clearing pending interrupts (FCINTPEND). Because of the time window between setting receive buffer length and clearing pending interrupts, the operation on receive buffer could end already and driver would miss new interrupt. User manual for Exynos5422 confirms in example code that setting DMA block lengths should be the last operation. The tcrypt hang could be also observed in following blocked-task dmesg: INFO: task modprobe:258 blocked for more than 120 seconds. Not tainted 4.6.0-rc4-next-20160419-00005-g9eac8b7b7753-dirty #42 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. modprobe D c06b09d8 0 258 256 0x00000000 [] (__schedule) from [] (schedule+0x40/0xac) [] (schedule) from [] (schedule_timeout+0x124/0x178) [] (schedule_timeout) from [] (wait_for_common+0xb8/0x144) [] (wait_for_common) from [] (test_acipher_speed+0x49c/0x740 [tcrypt]) [] (test_acipher_speed [tcrypt]) from [] (do_test+0x2240/0x30ec [tcrypt]) [] (do_test [tcrypt]) from [] (tcrypt_mod_init+0x48/0xa4 [tcrypt]) [] (tcrypt_mod_init [tcrypt]) from [] (do_one_initcall+0x3c/0x16c) [] (do_one_initcall) from [] (do_init_module+0x5c/0x1ac) [] (do_init_module) from [] (load_module+0x1a30/0x1d08) [] (load_module) from [] (SyS_finit_module+0x8c/0x98) [] (SyS_finit_module) from [] (ret_fast_syscall+0x0/0x3c) Fixes: a49e490c7a8a ("crypto: s5p-sss - add S5PV210 advanced crypto engine support") Cc: Signed-off-by: Krzysztof Kozlowski Tested-by: Marek Szyprowski Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 53 +++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index b96532078d0c..ac6d62b3be07 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -367,43 +367,55 @@ static int s5p_set_indata(struct s5p_aes_dev *dev, struct scatterlist *sg) return err; } -static void s5p_aes_tx(struct s5p_aes_dev *dev) +/* + * Returns true if new transmitting (output) data is ready and its + * address+length have to be written to device (by calling + * s5p_set_dma_outdata()). False otherwise. + */ +static bool s5p_aes_tx(struct s5p_aes_dev *dev) { int err = 0; + bool ret = false; s5p_unset_outdata(dev); if (!sg_is_last(dev->sg_dst)) { err = s5p_set_outdata(dev, sg_next(dev->sg_dst)); - if (err) { + if (err) s5p_aes_complete(dev, err); - return; - } - - s5p_set_dma_outdata(dev, dev->sg_dst); + else + ret = true; } else { s5p_aes_complete(dev, err); dev->busy = true; tasklet_schedule(&dev->tasklet); } + + return ret; } -static void s5p_aes_rx(struct s5p_aes_dev *dev) +/* + * Returns true if new receiving (input) data is ready and its + * address+length have to be written to device (by calling + * s5p_set_dma_indata()). False otherwise. + */ +static bool s5p_aes_rx(struct s5p_aes_dev *dev) { int err; + bool ret = false; s5p_unset_indata(dev); if (!sg_is_last(dev->sg_src)) { err = s5p_set_indata(dev, sg_next(dev->sg_src)); - if (err) { + if (err) s5p_aes_complete(dev, err); - return; - } - - s5p_set_dma_indata(dev, dev->sg_src); + else + ret = true; } + + return ret; } static irqreturn_t s5p_aes_interrupt(int irq, void *dev_id) @@ -412,17 +424,30 @@ static irqreturn_t s5p_aes_interrupt(int irq, void *dev_id) struct s5p_aes_dev *dev = platform_get_drvdata(pdev); uint32_t status; unsigned long flags; + bool set_dma_tx = false; + bool set_dma_rx = false; spin_lock_irqsave(&dev->lock, flags); status = SSS_READ(dev, FCINTSTAT); if (status & SSS_FCINTSTAT_BRDMAINT) - s5p_aes_rx(dev); + set_dma_rx = s5p_aes_rx(dev); if (status & SSS_FCINTSTAT_BTDMAINT) - s5p_aes_tx(dev); + set_dma_tx = s5p_aes_tx(dev); SSS_WRITE(dev, FCINTPEND, status); + /* + * Writing length of DMA block (either receiving or transmitting) + * will start the operation immediately, so this should be done + * at the end (even after clearing pending interrupts to not miss the + * interrupt). + */ + if (set_dma_tx) + s5p_set_dma_outdata(dev, dev->sg_dst); + if (set_dma_rx) + s5p_set_dma_indata(dev, dev->sg_src); + spin_unlock_irqrestore(&dev->lock, flags); return IRQ_HANDLED; -- GitLab From b4f47a483045a6e6b31be8ade76cdfef7091f18b Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 13 Apr 2016 16:08:22 -0700 Subject: [PATCH 4133/9938] ixgbe: use BIT() macro Several areas of ixgbe were written before widespread usage of the BIT(n) macro. With the impending release of GCC 6 and its associated new warnings, some usages such as (1 << 31) have been noted within the ixgbe driver source. Fix these wholesale and prevent future issues by simply using BIT macro instead of hand coded bit shifts. Also fix a few shifts that are shifting values into place by using the 'u' prefix to indicate unsigned. It doesn't strictly matter in these cases because we're not shifting by too large a value, but these are all unsigned values and should be indicated as such. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 68 +++---- .../net/ethernet/intel/ixgbe/ixgbe_82598.c | 6 +- .../net/ethernet/intel/ixgbe/ixgbe_82599.c | 16 +- .../net/ethernet/intel/ixgbe/ixgbe_common.c | 30 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c | 4 +- .../ethernet/intel/ixgbe/ixgbe_dcb_82598.c | 2 +- .../ethernet/intel/ixgbe/ixgbe_dcb_82599.c | 2 +- .../net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c | 6 +- .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 14 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 32 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c | 4 +- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 4 +- .../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 22 +-- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 166 +++++++++--------- drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 4 +- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 8 +- 17 files changed, 195 insertions(+), 195 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 22cf2a9430b5..781c8787ab66 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -170,7 +170,7 @@ struct vf_macvlans { }; #define IXGBE_MAX_TXD_PWR 14 -#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) +#define IXGBE_MAX_DATA_PER_TXD (1u << IXGBE_MAX_TXD_PWR) /* Tx Descriptors needed, worst case */ #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IXGBE_MAX_DATA_PER_TXD) @@ -620,44 +620,44 @@ struct ixgbe_adapter { * thus the additional *_CAPABLE flags. */ u32 flags; -#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 1) -#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 3) -#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 4) -#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 5) -#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 6) -#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 8) -#define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 9) -#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 10) -#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 11) -#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 12) -#define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 13) -#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 14) -#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 15) -#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 16) -#define IXGBE_FLAG_NEED_LINK_CONFIG (u32)(1 << 17) -#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 18) -#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 19) -#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 20) -#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 21) -#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 22) -#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 23) +#define IXGBE_FLAG_MSI_ENABLED BIT(1) +#define IXGBE_FLAG_MSIX_ENABLED BIT(3) +#define IXGBE_FLAG_RX_1BUF_CAPABLE BIT(4) +#define IXGBE_FLAG_RX_PS_CAPABLE BIT(5) +#define IXGBE_FLAG_RX_PS_ENABLED BIT(6) +#define IXGBE_FLAG_DCA_ENABLED BIT(8) +#define IXGBE_FLAG_DCA_CAPABLE BIT(9) +#define IXGBE_FLAG_IMIR_ENABLED BIT(10) +#define IXGBE_FLAG_MQ_CAPABLE BIT(11) +#define IXGBE_FLAG_DCB_ENABLED BIT(12) +#define IXGBE_FLAG_VMDQ_CAPABLE BIT(13) +#define IXGBE_FLAG_VMDQ_ENABLED BIT(14) +#define IXGBE_FLAG_FAN_FAIL_CAPABLE BIT(15) +#define IXGBE_FLAG_NEED_LINK_UPDATE BIT(16) +#define IXGBE_FLAG_NEED_LINK_CONFIG BIT(17) +#define IXGBE_FLAG_FDIR_HASH_CAPABLE BIT(18) +#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE BIT(19) +#define IXGBE_FLAG_FCOE_CAPABLE BIT(20) +#define IXGBE_FLAG_FCOE_ENABLED BIT(21) +#define IXGBE_FLAG_SRIOV_CAPABLE BIT(22) +#define IXGBE_FLAG_SRIOV_ENABLED BIT(23) #define IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE BIT(24) #define IXGBE_FLAG_RX_HWTSTAMP_ENABLED BIT(25) #define IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER BIT(26) u32 flags2; -#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1 << 0) -#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) -#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2) -#define IXGBE_FLAG2_TEMP_SENSOR_EVENT (u32)(1 << 3) -#define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4) -#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5) -#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6) -#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7) -#define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 8) -#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9) -#define IXGBE_FLAG2_PTP_PPS_ENABLED (u32)(1 << 10) -#define IXGBE_FLAG2_PHY_INTERRUPT (u32)(1 << 11) +#define IXGBE_FLAG2_RSC_CAPABLE BIT(0) +#define IXGBE_FLAG2_RSC_ENABLED BIT(1) +#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE BIT(2) +#define IXGBE_FLAG2_TEMP_SENSOR_EVENT BIT(3) +#define IXGBE_FLAG2_SEARCH_FOR_SFP BIT(4) +#define IXGBE_FLAG2_SFP_NEEDS_RESET BIT(5) +#define IXGBE_FLAG2_RESET_REQUESTED BIT(6) +#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT BIT(7) +#define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP BIT(8) +#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP BIT(9) +#define IXGBE_FLAG2_PTP_PPS_ENABLED BIT(10) +#define IXGBE_FLAG2_PHY_INTERRUPT BIT(11) #define IXGBE_FLAG2_VXLAN_REREG_NEEDED BIT(12) #define IXGBE_FLAG2_VLAN_PROMISC BIT(13) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index 6ecd598c6ef5..fb51be74dd4c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -792,7 +792,7 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) } gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); - gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); + gheccr &= ~(BIT(21) | BIT(18) | BIT(9) | BIT(6)); IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); /* @@ -914,10 +914,10 @@ static s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); if (vlan_on) /* Turn on this VLAN id */ - bits |= (1 << bitindex); + bits |= BIT(bitindex); else /* Turn off this VLAN id */ - bits &= ~(1 << bitindex); + bits &= ~BIT(bitindex); IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); return 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 01519787324a..47afed74a54d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -1296,17 +1296,17 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl) #define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \ do { \ u32 n = (_n); \ - if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \ + if (IXGBE_ATR_COMMON_HASH_KEY & BIT(n)) \ common_hash ^= lo_hash_dword >> n; \ - else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ + else if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n)) \ bucket_hash ^= lo_hash_dword >> n; \ - else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \ + else if (IXGBE_ATR_SIGNATURE_HASH_KEY & BIT(n)) \ sig_hash ^= lo_hash_dword << (16 - n); \ - if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \ + if (IXGBE_ATR_COMMON_HASH_KEY & BIT(n + 16)) \ common_hash ^= hi_hash_dword >> n; \ - else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ + else if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n + 16)) \ bucket_hash ^= hi_hash_dword >> n; \ - else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \ + else if (IXGBE_ATR_SIGNATURE_HASH_KEY & BIT(n + 16)) \ sig_hash ^= hi_hash_dword << (16 - n); \ } while (0) @@ -1440,9 +1440,9 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \ do { \ u32 n = (_n); \ - if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ + if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n)) \ bucket_hash ^= lo_hash_dword >> n; \ - if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ + if (IXGBE_ATR_BUCKET_HASH_KEY & BIT(n + 16)) \ bucket_hash ^= hi_hash_dword >> n; \ } while (0) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index c9dffa6101b8..902d2061ce73 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -825,8 +825,8 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) */ eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); - eeprom->word_size = 1 << (eeprom_size + - IXGBE_EEPROM_WORD_SIZE_SHIFT); + eeprom->word_size = BIT(eeprom_size + + IXGBE_EEPROM_WORD_SIZE_SHIFT); } if (eec & IXGBE_EEC_ADDR_SIZE) @@ -1502,7 +1502,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, * Mask is used to shift "count" bits of "data" out to the EEPROM * one bit at a time. Determine the starting bit based on count */ - mask = 0x01 << (count - 1); + mask = BIT(count - 1); for (i = 0; i < count; i++) { /* @@ -1991,7 +1991,7 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) */ vector_reg = (vector >> 5) & 0x7F; vector_bit = vector & 0x1F; - hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); + hw->mac.mta_shadow[vector_reg] |= BIT(vector_bit); } /** @@ -2921,10 +2921,10 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) mpsar_hi = 0; } } else if (vmdq < 32) { - mpsar_lo &= ~(1 << vmdq); + mpsar_lo &= ~BIT(vmdq); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); } else { - mpsar_hi &= ~(1 << (vmdq - 32)); + mpsar_hi &= ~BIT(vmdq - 32); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); } @@ -2953,11 +2953,11 @@ s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) if (vmdq < 32) { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); - mpsar |= 1 << vmdq; + mpsar |= BIT(vmdq); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); } else { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); - mpsar |= 1 << (vmdq - 32); + mpsar |= BIT(vmdq - 32); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); } return 0; @@ -2978,11 +2978,11 @@ s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) u32 rar = hw->mac.san_mac_rar_index; if (vmdq < 32) { - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), BIT(vmdq)); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); } else { IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32)); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), BIT(vmdq - 32)); } return 0; @@ -3082,7 +3082,7 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, * bits[4-0]: which bit in the register */ regidx = vlan / 32; - vfta_delta = 1 << (vlan % 32); + vfta_delta = BIT(vlan % 32); vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx)); /* vfta_delta represents the difference between the current value @@ -3113,12 +3113,12 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32)); /* set the pool bit */ - bits |= 1 << (vind % 32); + bits |= BIT(vind % 32); if (vlan_on) goto vlvf_update; /* clear the pool bit */ - bits ^= 1 << (vind % 32); + bits ^= BIT(vind % 32); if (!bits && !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) { @@ -3349,9 +3349,9 @@ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); if (enable) - pfvfspoof |= (1 << vf_target_shift); + pfvfspoof |= BIT(vf_target_shift); else - pfvfspoof &= ~(1 << vf_target_shift); + pfvfspoof &= ~BIT(vf_target_shift); IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c index f8fb2acc2632..072ef3b5fc61 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c @@ -186,7 +186,7 @@ void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en) for (*pfc_en = 0, tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) { if (tc_config[tc].dcb_pfc != pfc_disabled) - *pfc_en |= 1 << tc; + *pfc_en |= BIT(tc); } } @@ -232,7 +232,7 @@ void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *cfg, int direction, u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up) { struct tc_configuration *tc_config = &cfg->tc_config[0]; - u8 prio_mask = 1 << up; + u8 prio_mask = BIT(up); u8 tc = cfg->num_tcs.pg_tcs; /* If tc is 0 then DCB is likely not enabled or supported */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c index d3ba63f9ad37..b79e93a5b699 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c @@ -210,7 +210,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en) /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { - if (!(pfc_en & (1 << i))) { + if (!(pfc_en & BIT(i))) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0); continue; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c index b5cc989a3d23..1011d644978f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c @@ -248,7 +248,7 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc) int enabled = 0; for (j = 0; j < MAX_USER_PRIORITY; j++) { - if ((prio_tc[j] == i) && (pfc_en & (1 << j))) { + if ((prio_tc[j] == i) && (pfc_en & BIT(j))) { enabled = 1; break; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c index 2707bda37418..b8fc3cfec831 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c @@ -62,7 +62,7 @@ static int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max) }; u8 up = dcb_getapp(adapter->netdev, &app); - if (up && !(up & (1 << adapter->fcoe.up))) + if (up && !(up & BIT(adapter->fcoe.up))) changes |= BIT_APP_UPCHG; #endif @@ -657,7 +657,7 @@ static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev, app->protocol == ETH_P_FCOE) { u8 app_mask = dcb_ieee_getapp_mask(dev, app); - if (app_mask & (1 << adapter->fcoe.up)) + if (app_mask & BIT(adapter->fcoe.up)) return 0; adapter->fcoe.up = app->priority; @@ -700,7 +700,7 @@ static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev, app->protocol == ETH_P_FCOE) { u8 app_mask = dcb_ieee_getapp_mask(dev, app); - if (app_mask & (1 << adapter->fcoe.up)) + if (app_mask & BIT(adapter->fcoe.up)) return 0; adapter->fcoe.up = app_mask ? diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 9f76be1431b1..d3efcb4fecce 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -1586,7 +1586,7 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) /* Test each interrupt */ for (; i < 10; i++) { /* Interrupt to test */ - mask = 1 << i; + mask = BIT(i); if (!shared_int) { /* @@ -3014,14 +3014,14 @@ static int ixgbe_get_ts_info(struct net_device *dev, info->phc_index = -1; info->tx_types = - (1 << HWTSTAMP_TX_OFF) | - (1 << HWTSTAMP_TX_ON); + BIT(HWTSTAMP_TX_OFF) | + BIT(HWTSTAMP_TX_ON); info->rx_filters = - (1 << HWTSTAMP_FILTER_NONE) | - (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); + BIT(HWTSTAMP_FILTER_NONE) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); break; default: return ethtool_op_get_ts_info(dev, info); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 09d7c8bdcd5c..b41a26fe57de 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2245,7 +2245,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) /* Populate MSIX to EITR Select */ if (adapter->num_vfs > 32) { - u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1; + u32 eitrsel = BIT(adapter->num_vfs - 32) - 1; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, eitrsel); } @@ -2884,7 +2884,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget) if (adapter->rx_itr_setting & 1) ixgbe_set_itr(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx)); + ixgbe_irq_enable_queues(adapter, BIT_ULL(q_vector->v_idx)); return 0; } @@ -3177,15 +3177,15 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, * currently 40. */ if (!ring->q_vector || (ring->q_vector->itr < IXGBE_100K_ITR)) - txdctl |= (1 << 16); /* WTHRESH = 1 */ + txdctl |= 1u << 16; /* WTHRESH = 1 */ else - txdctl |= (8 << 16); /* WTHRESH = 8 */ + txdctl |= 8u << 16; /* WTHRESH = 8 */ /* * Setting PTHRESH to 32 both improves performance * and avoids a TX hang with DFP enabled */ - txdctl |= (1 << 8) | /* HTHRESH = 1 */ + txdctl |= (1u << 8) | /* HTHRESH = 1 */ 32; /* PTHRESH = 32 */ /* reinitialize flowdirector state */ @@ -3737,9 +3737,9 @@ static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter) return; if (rss_i > 3) - psrtype |= 2 << 29; + psrtype |= 2u << 29; else if (rss_i > 1) - psrtype |= 1 << 29; + psrtype |= 1u << 29; for_each_set_bit(pool, &adapter->fwd_bitmask, 32) IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(VMDQ_P(pool)), psrtype); @@ -3994,7 +3994,7 @@ void ixgbe_update_pf_promisc_vlvf(struct ixgbe_adapter *adapter, u32 vid) * entry other than the PF. */ word = idx * 2 + (VMDQ_P(0) / 32); - bits = ~(1 << (VMDQ_P(0)) % 32); + bits = ~BIT(VMDQ_P(0) % 32); bits &= IXGBE_READ_REG(hw, IXGBE_VLVFB(word)); /* Disable the filter so this falls into the default pool. */ @@ -4129,7 +4129,7 @@ static void ixgbe_vlan_promisc_enable(struct ixgbe_adapter *adapter) u32 reg_offset = IXGBE_VLVFB(i * 2 + VMDQ_P(0) / 32); u32 vlvfb = IXGBE_READ_REG(hw, reg_offset); - vlvfb |= 1 << (VMDQ_P(0) % 32); + vlvfb |= BIT(VMDQ_P(0) % 32); IXGBE_WRITE_REG(hw, reg_offset, vlvfb); } @@ -4159,7 +4159,7 @@ static void ixgbe_scrub_vfta(struct ixgbe_adapter *adapter, u32 vfta_offset) if (vlvf) { /* record VLAN ID in VFTA */ - vfta[(vid - vid_start) / 32] |= 1 << (vid % 32); + vfta[(vid - vid_start) / 32] |= BIT(vid % 32); /* if PF is part of this then continue */ if (test_bit(vid, adapter->active_vlans)) @@ -4168,7 +4168,7 @@ static void ixgbe_scrub_vfta(struct ixgbe_adapter *adapter, u32 vfta_offset) /* remove PF from the pool */ word = i * 2 + VMDQ_P(0) / 32; - bits = ~(1 << (VMDQ_P(0) % 32)); + bits = ~BIT(VMDQ_P(0) % 32); bits &= IXGBE_READ_REG(hw, IXGBE_VLVFB(word)); IXGBE_WRITE_REG(hw, IXGBE_VLVFB(word), bits); } @@ -4862,9 +4862,9 @@ static void ixgbe_fwd_psrtype(struct ixgbe_fwd_adapter *vadapter) return; if (rss_i > 3) - psrtype |= 2 << 29; + psrtype |= 2u << 29; else if (rss_i > 1) - psrtype |= 1 << 29; + psrtype |= 1u << 29; IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(VMDQ_P(pool)), psrtype); } @@ -4928,7 +4928,7 @@ static void ixgbe_disable_fwd_ring(struct ixgbe_fwd_adapter *vadapter, /* shutdown specific queue receive and wait for dma to settle */ ixgbe_disable_rx_queue(adapter, rx_ring); usleep_range(10000, 20000); - ixgbe_irq_disable_queues(adapter, ((u64)1 << index)); + ixgbe_irq_disable_queues(adapter, BIT_ULL(index)); ixgbe_clean_rx_ring(rx_ring); rx_ring->l2_accel_priv = NULL; } @@ -6645,7 +6645,7 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter) for (i = 0; i < adapter->num_q_vectors; i++) { struct ixgbe_q_vector *qv = adapter->q_vector[i]; if (qv->rx.ring || qv->tx.ring) - eics |= ((u64)1 << i); + eics |= BIT_ULL(i); } } @@ -9192,7 +9192,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_ioremap; } /* If EEPROM is valid (bit 8 = 1), use default otherwise use bit bang */ - if (!(eec & (1 << 8))) + if (!(eec & BIT(8))) hw->eeprom.ops.read = &ixgbe_read_eeprom_bit_bang_generic; /* PHY */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c index b2125e358f7b..a0cb84381cd0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c @@ -314,8 +314,8 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) break; } - if (vflre & (1 << vf_shift)) { - IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); + if (vflre & BIT(vf_shift)) { + IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), BIT(vf_shift)); hw->mbx.stats.rsts++; return 0; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index cdf4c3800801..cc735ec3e045 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -107,7 +107,7 @@ #define IXGBE_PE 0xE0 /* Port expander addr */ #define IXGBE_PE_OUTPUT 1 /* Output reg offset */ #define IXGBE_PE_CONFIG 3 /* Config reg offset */ -#define IXGBE_PE_BIT1 (1 << 1) +#define IXGBE_PE_BIT1 BIT(1) /* Flow control defines */ #define IXGBE_TAF_SYM_PAUSE 0x400 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index bdc8fdcc07a5..e5431bfe3339 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -396,7 +396,7 @@ static int ixgbe_ptp_adjfreq_82599(struct ptp_clock_info *ptp, s32 ppb) if (incval > 0x00FFFFFFULL) e_dev_warn("PTP ppb adjusted SYSTIME rate overflowed!\n"); IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, - (1 << IXGBE_INCPER_SHIFT_82599) | + BIT(IXGBE_INCPER_SHIFT_82599) | ((u32)incval & 0x00FFFFFFUL)); break; default: @@ -1114,7 +1114,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) incval >>= IXGBE_INCVAL_SHIFT_82599; cc.shift -= IXGBE_INCVAL_SHIFT_82599; IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, - (1 << IXGBE_INCPER_SHIFT_82599) | incval); + BIT(IXGBE_INCPER_SHIFT_82599) | incval); break; default: /* other devices aren't supported */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index e9f2558e65fc..c5caacdd193d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -406,7 +406,7 @@ static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, vector_reg = (vfinfo->vf_mc_hashes[i] >> 5) & 0x7F; vector_bit = vfinfo->vf_mc_hashes[i] & 0x1F; mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); - mta_reg |= (1 << vector_bit); + mta_reg |= BIT(vector_bit); IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); } vmolr |= IXGBE_VMOLR_ROMPE; @@ -433,7 +433,7 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) vector_reg = (vfinfo->vf_mc_hashes[j] >> 5) & 0x7F; vector_bit = vfinfo->vf_mc_hashes[j] & 0x1F; mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); - mta_reg |= (1 << vector_bit); + mta_reg |= BIT(vector_bit); IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); } @@ -536,9 +536,9 @@ static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf) /* enable or disable receive depending on error */ vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); if (err) - vfre &= ~(1 << vf_shift); + vfre &= ~BIT(vf_shift); else - vfre |= 1 << vf_shift; + vfre |= BIT(vf_shift); IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), vfre); if (err) { @@ -592,8 +592,8 @@ static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf) u32 vlvfb_mask, pool_mask, i; /* create mask for VF and other pools */ - pool_mask = ~(1 << (VMDQ_P(0) % 32)); - vlvfb_mask = 1 << (vf % 32); + pool_mask = ~BIT(VMDQ_P(0) % 32); + vlvfb_mask = BIT(vf % 32); /* post increment loop, covers VLVF_ENTRIES - 1 to 0 */ for (i = IXGBE_VLVF_ENTRIES; i--;) { @@ -629,7 +629,7 @@ static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf) goto update_vlvfb; vid = vlvf & VLAN_VID_MASK; - mask = 1 << (vid % 32); + mask = BIT(vid % 32); /* clear bit from VFTA */ vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(vid / 32)); @@ -813,7 +813,7 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) /* enable transmit for vf */ reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset)); - reg |= 1 << vf_shift; + reg |= BIT(vf_shift); IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg); /* force drop enable for all VF Rx queues */ @@ -821,7 +821,7 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) /* enable receive for vf */ reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); - reg |= 1 << vf_shift; + reg |= BIT(vf_shift); /* * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs. * For more info take a look at ixgbe_set_vf_lpe @@ -837,7 +837,7 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) #endif /* CONFIG_FCOE */ if (pf_max_frame > ETH_FRAME_LEN) - reg &= ~(1 << vf_shift); + reg &= ~BIT(vf_shift); } IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg); @@ -846,7 +846,7 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) /* Enable counting of spoofed packets in the SSVPC register */ reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset)); - reg |= (1 << vf_shift); + reg |= BIT(vf_shift); IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg); /* diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 8e7decb3e078..7af451460374 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -697,16 +697,16 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_FCDMARW 0x02420 /* FC Receive DMA RW */ #define IXGBE_FCINVST0 0x03FC0 /* FC Invalid DMA Context Status Reg 0 */ #define IXGBE_FCINVST(_i) (IXGBE_FCINVST0 + ((_i) * 4)) -#define IXGBE_FCBUFF_VALID (1 << 0) /* DMA Context Valid */ -#define IXGBE_FCBUFF_BUFFSIZE (3 << 3) /* User Buffer Size */ -#define IXGBE_FCBUFF_WRCONTX (1 << 7) /* 0: Initiator, 1: Target */ +#define IXGBE_FCBUFF_VALID BIT(0) /* DMA Context Valid */ +#define IXGBE_FCBUFF_BUFFSIZE (3u << 3) /* User Buffer Size */ +#define IXGBE_FCBUFF_WRCONTX BIT(7) /* 0: Initiator, 1: Target */ #define IXGBE_FCBUFF_BUFFCNT 0x0000ff00 /* Number of User Buffers */ #define IXGBE_FCBUFF_OFFSET 0xffff0000 /* User Buffer Offset */ #define IXGBE_FCBUFF_BUFFSIZE_SHIFT 3 #define IXGBE_FCBUFF_BUFFCNT_SHIFT 8 #define IXGBE_FCBUFF_OFFSET_SHIFT 16 -#define IXGBE_FCDMARW_WE (1 << 14) /* Write enable */ -#define IXGBE_FCDMARW_RE (1 << 15) /* Read enable */ +#define IXGBE_FCDMARW_WE BIT(14) /* Write enable */ +#define IXGBE_FCDMARW_RE BIT(15) /* Read enable */ #define IXGBE_FCDMARW_FCOESEL 0x000001ff /* FC X_ID: 11 bits */ #define IXGBE_FCDMARW_LASTSIZE 0xffff0000 /* Last User Buffer Size */ #define IXGBE_FCDMARW_LASTSIZE_SHIFT 16 @@ -723,23 +723,23 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_FCFLT 0x05108 /* FC FLT Context */ #define IXGBE_FCFLTRW 0x05110 /* FC Filter RW Control */ #define IXGBE_FCPARAM 0x051d8 /* FC Offset Parameter */ -#define IXGBE_FCFLT_VALID (1 << 0) /* Filter Context Valid */ -#define IXGBE_FCFLT_FIRST (1 << 1) /* Filter First */ +#define IXGBE_FCFLT_VALID BIT(0) /* Filter Context Valid */ +#define IXGBE_FCFLT_FIRST BIT(1) /* Filter First */ #define IXGBE_FCFLT_SEQID 0x00ff0000 /* Sequence ID */ #define IXGBE_FCFLT_SEQCNT 0xff000000 /* Sequence Count */ -#define IXGBE_FCFLTRW_RVALDT (1 << 13) /* Fast Re-Validation */ -#define IXGBE_FCFLTRW_WE (1 << 14) /* Write Enable */ -#define IXGBE_FCFLTRW_RE (1 << 15) /* Read Enable */ +#define IXGBE_FCFLTRW_RVALDT BIT(13) /* Fast Re-Validation */ +#define IXGBE_FCFLTRW_WE BIT(14) /* Write Enable */ +#define IXGBE_FCFLTRW_RE BIT(15) /* Read Enable */ /* FCoE Receive Control */ #define IXGBE_FCRXCTRL 0x05100 /* FC Receive Control */ -#define IXGBE_FCRXCTRL_FCOELLI (1 << 0) /* Low latency interrupt */ -#define IXGBE_FCRXCTRL_SAVBAD (1 << 1) /* Save Bad Frames */ -#define IXGBE_FCRXCTRL_FRSTRDH (1 << 2) /* EN 1st Read Header */ -#define IXGBE_FCRXCTRL_LASTSEQH (1 << 3) /* EN Last Header in Seq */ -#define IXGBE_FCRXCTRL_ALLH (1 << 4) /* EN All Headers */ -#define IXGBE_FCRXCTRL_FRSTSEQH (1 << 5) /* EN 1st Seq. Header */ -#define IXGBE_FCRXCTRL_ICRC (1 << 6) /* Ignore Bad FC CRC */ -#define IXGBE_FCRXCTRL_FCCRCBO (1 << 7) /* FC CRC Byte Ordering */ +#define IXGBE_FCRXCTRL_FCOELLI BIT(0) /* Low latency interrupt */ +#define IXGBE_FCRXCTRL_SAVBAD BIT(1) /* Save Bad Frames */ +#define IXGBE_FCRXCTRL_FRSTRDH BIT(2) /* EN 1st Read Header */ +#define IXGBE_FCRXCTRL_LASTSEQH BIT(3) /* EN Last Header in Seq */ +#define IXGBE_FCRXCTRL_ALLH BIT(4) /* EN All Headers */ +#define IXGBE_FCRXCTRL_FRSTSEQH BIT(5) /* EN 1st Seq. Header */ +#define IXGBE_FCRXCTRL_ICRC BIT(6) /* Ignore Bad FC CRC */ +#define IXGBE_FCRXCTRL_FCCRCBO BIT(7) /* FC CRC Byte Ordering */ #define IXGBE_FCRXCTRL_FCOEVER 0x00000f00 /* FCoE Version: 4 bits */ #define IXGBE_FCRXCTRL_FCOEVER_SHIFT 8 /* FCoE Redirection */ @@ -1256,20 +1256,20 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */ #define IXGBE_DCA_RXCTRL_CPUID_MASK_82599 0xFF000000 /* Rx CPUID Mask */ #define IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599 24 /* Rx CPUID Shift */ -#define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ -#define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */ -#define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */ -#define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */ -#define IXGBE_DCA_RXCTRL_DATA_WRO_EN (1 << 13) /* Rx wr data Relax Order */ -#define IXGBE_DCA_RXCTRL_HEAD_WRO_EN (1 << 15) /* Rx wr header RO */ +#define IXGBE_DCA_RXCTRL_DESC_DCA_EN BIT(5) /* DCA Rx Desc enable */ +#define IXGBE_DCA_RXCTRL_HEAD_DCA_EN BIT(6) /* DCA Rx Desc header enable */ +#define IXGBE_DCA_RXCTRL_DATA_DCA_EN BIT(7) /* DCA Rx Desc payload enable */ +#define IXGBE_DCA_RXCTRL_DESC_RRO_EN BIT(9) /* DCA Rx rd Desc Relax Order */ +#define IXGBE_DCA_RXCTRL_DATA_WRO_EN BIT(13) /* Rx wr data Relax Order */ +#define IXGBE_DCA_RXCTRL_HEAD_WRO_EN BIT(15) /* Rx wr header RO */ #define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_CPUID_MASK_82599 0xFF000000 /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599 24 /* Tx CPUID Shift */ -#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ -#define IXGBE_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ -#define IXGBE_DCA_TXCTRL_DESC_WRO_EN (1 << 11) /* Tx Desc writeback RO bit */ -#define IXGBE_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ +#define IXGBE_DCA_TXCTRL_DESC_DCA_EN BIT(5) /* DCA Tx Desc enable */ +#define IXGBE_DCA_TXCTRL_DESC_RRO_EN BIT(9) /* Tx rd Desc Relax Order */ +#define IXGBE_DCA_TXCTRL_DESC_WRO_EN BIT(11) /* Tx Desc writeback RO bit */ +#define IXGBE_DCA_TXCTRL_DATA_RRO_EN BIT(13) /* Tx rd data Relax Order */ #define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */ /* MSCA Bit Masks */ @@ -1748,7 +1748,7 @@ enum { #define IXGBE_ETQF_TX_ANTISPOOF 0x20000000 /* bit 29 */ #define IXGBE_ETQF_1588 0x40000000 /* bit 30 */ #define IXGBE_ETQF_FILTER_EN 0x80000000 /* bit 31 */ -#define IXGBE_ETQF_POOL_ENABLE (1 << 26) /* bit 26 */ +#define IXGBE_ETQF_POOL_ENABLE BIT(26) /* bit 26 */ #define IXGBE_ETQF_POOL_SHIFT 20 #define IXGBE_ETQS_RX_QUEUE 0x007F0000 /* bits 22:16 */ @@ -1874,20 +1874,20 @@ enum { #define IXGBE_AUTOC_1G_PMA_PMD_SHIFT 9 #define IXGBE_AUTOC_10G_PMA_PMD_MASK 0x00000180 #define IXGBE_AUTOC_10G_PMA_PMD_SHIFT 7 -#define IXGBE_AUTOC_10G_XAUI (0x0 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) -#define IXGBE_AUTOC_10G_KX4 (0x1 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) -#define IXGBE_AUTOC_10G_CX4 (0x2 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) -#define IXGBE_AUTOC_1G_BX (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) -#define IXGBE_AUTOC_1G_KX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) -#define IXGBE_AUTOC_1G_SFI (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) -#define IXGBE_AUTOC_1G_KX_BX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) +#define IXGBE_AUTOC_10G_XAUI (0u << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) +#define IXGBE_AUTOC_10G_KX4 (1u << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) +#define IXGBE_AUTOC_10G_CX4 (2u << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) +#define IXGBE_AUTOC_1G_BX (0u << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) +#define IXGBE_AUTOC_1G_KX (1u << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) +#define IXGBE_AUTOC_1G_SFI (0u << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) +#define IXGBE_AUTOC_1G_KX_BX (1u << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_UPPER_MASK 0xFFFF0000 #define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK 0x00030000 #define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT 16 -#define IXGBE_AUTOC2_10G_KR (0x0 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) -#define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) -#define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) +#define IXGBE_AUTOC2_10G_KR (0u << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) +#define IXGBE_AUTOC2_10G_XFI (1u << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) +#define IXGBE_AUTOC2_10G_SFI (2u << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK 0x50000000 #define IXGBE_AUTOC2_LINK_DISABLE_MASK 0x70000000 @@ -2840,15 +2840,15 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ #define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000/* ESP Encrypt Enable */ #define IXGBE_ADVTXT_TUCMD_FCOE 0x00008000 /* FCoE Frame Type */ -#define IXGBE_ADVTXD_FCOEF_EOF_MASK (0x3 << 10) /* FC EOF index */ -#define IXGBE_ADVTXD_FCOEF_SOF ((1 << 2) << 10) /* FC SOF index */ -#define IXGBE_ADVTXD_FCOEF_PARINC ((1 << 3) << 10) /* Rel_Off in F_CTL */ -#define IXGBE_ADVTXD_FCOEF_ORIE ((1 << 4) << 10) /* Orientation: End */ -#define IXGBE_ADVTXD_FCOEF_ORIS ((1 << 5) << 10) /* Orientation: Start */ -#define IXGBE_ADVTXD_FCOEF_EOF_N (0x0 << 10) /* 00: EOFn */ -#define IXGBE_ADVTXD_FCOEF_EOF_T (0x1 << 10) /* 01: EOFt */ -#define IXGBE_ADVTXD_FCOEF_EOF_NI (0x2 << 10) /* 10: EOFni */ -#define IXGBE_ADVTXD_FCOEF_EOF_A (0x3 << 10) /* 11: EOFa */ +#define IXGBE_ADVTXD_FCOEF_SOF (BIT(2) << 10) /* FC SOF index */ +#define IXGBE_ADVTXD_FCOEF_PARINC (BIT(3) << 10) /* Rel_Off in F_CTL */ +#define IXGBE_ADVTXD_FCOEF_ORIE (BIT(4) << 10) /* Orientation: End */ +#define IXGBE_ADVTXD_FCOEF_ORIS (BIT(5) << 10) /* Orientation: Start */ +#define IXGBE_ADVTXD_FCOEF_EOF_N (0u << 10) /* 00: EOFn */ +#define IXGBE_ADVTXD_FCOEF_EOF_T (1u << 10) /* 01: EOFt */ +#define IXGBE_ADVTXD_FCOEF_EOF_NI (2u << 10) /* 10: EOFni */ +#define IXGBE_ADVTXD_FCOEF_EOF_A (3u << 10) /* 11: EOFa */ +#define IXGBE_ADVTXD_FCOEF_EOF_MASK (3u << 10) /* FC EOF index */ #define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ @@ -3583,7 +3583,7 @@ struct ixgbe_info { #define IXGBE_FUSES0_GROUP(_i) (0x11158 + ((_i) * 4)) #define IXGBE_FUSES0_300MHZ BIT(5) -#define IXGBE_FUSES0_REV_MASK (3 << 6) +#define IXGBE_FUSES0_REV_MASK (3u << 6) #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010) #define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) @@ -3597,25 +3597,25 @@ struct ixgbe_info { #define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520) #define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00) -#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B (1 << 9) -#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS (1 << 11) +#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B BIT(9) +#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS BIT(11) -#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK (0x7 << 8) -#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G (2 << 8) -#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G (4 << 8) +#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK (7u << 8) +#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G (2u << 8) +#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G (4u << 8) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN BIT(12) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN BIT(13) -#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ (1 << 14) -#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC (1 << 15) -#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX (1 << 16) -#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR (1 << 18) -#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX (1 << 24) -#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR (1 << 26) -#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE (1 << 29) -#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART (1 << 31) - -#define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE (1 << 28) -#define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE (1 << 29) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ BIT(14) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC BIT(15) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX BIT(16) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR BIT(18) +#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX BIT(24) +#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR BIT(26) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE BIT(29) +#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART BIT(31) + +#define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE BIT(28) +#define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE BIT(29) #define IXGBE_KRM_AN_CNTL_8_LINEAR BIT(0) #define IXGBE_KRM_AN_CNTL_8_LIMITING BIT(1) @@ -3623,28 +3623,28 @@ struct ixgbe_info { #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D BIT(12) #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D BIT(19) -#define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN (1 << 6) -#define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN (1 << 15) -#define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN (1 << 16) +#define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN BIT(6) +#define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN BIT(15) +#define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN BIT(16) -#define IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL (1 << 4) -#define IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS (1 << 2) +#define IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL BIT(4) +#define IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS BIT(2) -#define IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK (0x3 << 16) +#define IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK (3u << 16) -#define IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN (1 << 1) -#define IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN (1 << 2) -#define IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN (1 << 3) -#define IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN (1 << 31) +#define IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN BIT(1) +#define IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN BIT(2) +#define IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN BIT(3) +#define IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN BIT(31) #define IXGBE_KX4_LINK_CNTL_1 0x4C -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX (1 << 16) -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 (1 << 17) -#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX (1 << 24) -#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX4 (1 << 25) -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE (1 << 29) -#define IXGBE_KX4_LINK_CNTL_1_TETH_FORCE_LINK_UP (1 << 30) -#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART (1 << 31) +#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX BIT(16) +#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 BIT(17) +#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX BIT(24) +#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX4 BIT(25) +#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE BIT(29) +#define IXGBE_KX4_LINK_CNTL_1_TETH_FORCE_LINK_UP BIT(30) +#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART BIT(31) #define IXGBE_SB_IOSF_INDIRECT_CTRL 0x00011144 #define IXGBE_SB_IOSF_INDIRECT_DATA 0x00011148 @@ -3660,7 +3660,7 @@ struct ixgbe_info { #define IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT 28 #define IXGBE_SB_IOSF_CTRL_TARGET_SELECT_MASK 0x7 #define IXGBE_SB_IOSF_CTRL_BUSY_SHIFT 31 -#define IXGBE_SB_IOSF_CTRL_BUSY (1 << IXGBE_SB_IOSF_CTRL_BUSY_SHIFT) +#define IXGBE_SB_IOSF_CTRL_BUSY BIT(IXGBE_SB_IOSF_CTRL_BUSY_SHIFT) #define IXGBE_SB_IOSF_TARGET_KR_PHY 0 #define IXGBE_SB_IOSF_TARGET_KX4_UNIPHY 1 #define IXGBE_SB_IOSF_TARGET_KX4_PCS0 2 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index 40824d85d807..f2b1d48a16c3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -214,8 +214,8 @@ s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw) eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); - eeprom->word_size = 1 << (eeprom_size + - IXGBE_EEPROM_WORD_SIZE_SHIFT); + eeprom->word_size = BIT(eeprom_size + + IXGBE_EEPROM_WORD_SIZE_SHIFT); hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", eeprom->type, eeprom->word_size); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index a17e398d56b8..c8a4f5ef06c0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -335,8 +335,8 @@ static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); - eeprom->word_size = 1 << (eeprom_size + - IXGBE_EEPROM_WORD_SIZE_SHIFT); + eeprom->word_size = BIT(eeprom_size + + IXGBE_EEPROM_WORD_SIZE_SHIFT); hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", eeprom->type, eeprom->word_size); @@ -2646,9 +2646,9 @@ static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); if (enable) - pfvfspoof |= (1 << vf_target_shift); + pfvfspoof |= BIT(vf_target_shift); else - pfvfspoof &= ~(1 << vf_target_shift); + pfvfspoof &= ~BIT(vf_target_shift); IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } -- GitLab From 511257e6ae1fb87a2d0ad59ccdd61d1d4a0b9384 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sun, 24 Apr 2016 21:24:11 -0300 Subject: [PATCH 4134/9938] [media] Documentation: dt: media: fix spelling mistake Fix spelling mistake. Signed-off-by: Eric Engestrom Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/xilinx/video.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/xilinx/video.txt b/Documentation/devicetree/bindings/media/xilinx/video.txt index cbd46fa0988f..68ac210e688e 100644 --- a/Documentation/devicetree/bindings/media/xilinx/video.txt +++ b/Documentation/devicetree/bindings/media/xilinx/video.txt @@ -20,7 +20,7 @@ The following properties are common to all Xilinx video IP cores. - xlnx,video-format: This property represents a video format transmitted on an AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream Video IP and System Design Guide" [UG934]. How the format relates to the IP - core is decribed in the IP core bindings documentation. + core is described in the IP core bindings documentation. - xlnx,video-width: This property qualifies the video format with the sample width expressed as a number of bits per pixel component. All components must -- GitLab From 0ba20cdcc51b1acb6ba5387ccae47ef5ef620a5b Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sun, 24 Apr 2016 21:24:20 -0300 Subject: [PATCH 4135/9938] [media] Documentation: DocBook: fix spelling mistake Fix spelling mistake. Signed-off-by: Eric Engestrom Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/dvb/net.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/dvb/net.xml b/Documentation/DocBook/media/dvb/net.xml index d2e44b7e07df..da095ed0b75c 100644 --- a/Documentation/DocBook/media/dvb/net.xml +++ b/Documentation/DocBook/media/dvb/net.xml @@ -15,7 +15,7 @@ that are present on the transport stream. This is done through /dev/dvb/adapter?/net? device node. The data will be available via virtual dvb?_? - network interfaces, and will be controled/routed via the standard + network interfaces, and will be controlled/routed via the standard ip tools (like ip, route, netstat, ifconfig, etc). Data types and and ioctl definitions are defined via linux/dvb/net.h header. -- GitLab From 3e973dc4b93da06e38b263c9bd7e239d8f3f251f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 13 Apr 2016 16:08:23 -0700 Subject: [PATCH 4136/9938] ixgbe: resolve shift of negative value warning Make use of GENMASK instead of open coding the equivalent operation incorrectly. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index b41a26fe57de..60592cfa5ca6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3766,9 +3766,9 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) reg_offset = (VMDQ_P(0) >= 32) ? 1 : 0; /* Enable only the PF's pool for Tx/Rx */ - IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (~0) << vf_shift); + IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), GENMASK(vf_shift, 31)); IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), reg_offset - 1); - IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (~0) << vf_shift); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), GENMASK(vf_shift, 31)); IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), reg_offset - 1); if (adapter->bridge_mode == BRIDGE_MODE_VEB) IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); -- GitLab From 8d055cc0c8be92cd6a77193460117f0ab0a05286 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 13 Apr 2016 16:08:24 -0700 Subject: [PATCH 4137/9938] ixgbevf: make use of BIT() macro to avoid shift of signed values Also cleanup a case where we're bit shifting a value into place, and use an unsigned constant. Make use of the unsigned postfix in places where BIT() macro is not appropriate. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/defines.h | 24 +++++++++---------- drivers/net/ethernet/intel/ixgbevf/ethtool.c | 3 ++- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 8 +++---- .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 18 +++++++------- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h index 58434584b16d..74901f7ef391 100644 --- a/drivers/net/ethernet/intel/ixgbevf/defines.h +++ b/drivers/net/ethernet/intel/ixgbevf/defines.h @@ -74,7 +74,7 @@ typedef u32 ixgbe_link_speed; #define IXGBE_RXDCTL_RLPML_EN 0x00008000 /* DCA Control */ -#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ +#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN BIT(11) /* Tx Desc writeback RO bit */ /* PSRTYPE bit definitions */ #define IXGBE_PSRTYPE_TCPHDR 0x00000010 @@ -296,16 +296,16 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wr-bk flushing */ #define IXGBE_TXDCTL_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */ -#define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* Rx Desc enable */ -#define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* Rx Desc header ena */ -#define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* Rx Desc payload ena */ -#define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* Rx rd Desc Relax Order */ -#define IXGBE_DCA_RXCTRL_DATA_WRO_EN (1 << 13) /* Rx wr data Relax Order */ -#define IXGBE_DCA_RXCTRL_HEAD_WRO_EN (1 << 15) /* Rx wr header RO */ - -#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ -#define IXGBE_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ -#define IXGBE_DCA_TXCTRL_DESC_WRO_EN (1 << 11) /* Tx Desc writeback RO bit */ -#define IXGBE_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ +#define IXGBE_DCA_RXCTRL_DESC_DCA_EN BIT(5) /* Rx Desc enable */ +#define IXGBE_DCA_RXCTRL_HEAD_DCA_EN BIT(6) /* Rx Desc header ena */ +#define IXGBE_DCA_RXCTRL_DATA_DCA_EN BIT(7) /* Rx Desc payload ena */ +#define IXGBE_DCA_RXCTRL_DESC_RRO_EN BIT(9) /* Rx rd Desc Relax Order */ +#define IXGBE_DCA_RXCTRL_DATA_WRO_EN BIT(13) /* Rx wr data Relax Order */ +#define IXGBE_DCA_RXCTRL_HEAD_WRO_EN BIT(15) /* Rx wr header RO */ + +#define IXGBE_DCA_TXCTRL_DESC_DCA_EN BIT(5) /* DCA Tx Desc enable */ +#define IXGBE_DCA_TXCTRL_DESC_RRO_EN BIT(9) /* Tx rd Desc Relax Order */ +#define IXGBE_DCA_TXCTRL_DESC_WRO_EN BIT(11) /* Tx Desc writeback RO bit */ +#define IXGBE_DCA_TXCTRL_DATA_RRO_EN BIT(13) /* Tx rd data Relax Order */ #endif /* _IXGBEVF_DEFINES_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index 64d5c6e9343e..508e72c5f1c2 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -166,7 +166,8 @@ static void ixgbevf_get_regs(struct net_device *netdev, memset(p, 0, regs_len); - regs->version = (1 << 24) | hw->revision_id << 16 | hw->device_id; + /* generate a number suitable for ethtool's register version */ + regs->version = (1u << 24) | (hw->revision_id << 16) | hw->device_id; /* General Registers */ regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_VFCTRL); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 5ca3794aeb2e..aa28c4fb1a43 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -166,10 +166,10 @@ struct ixgbevf_ring { #define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) -#define IXGBE_TX_FLAGS_CSUM (u32)(1) -#define IXGBE_TX_FLAGS_VLAN (u32)(1 << 1) -#define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) -#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) +#define IXGBE_TX_FLAGS_CSUM BIT(0) +#define IXGBE_TX_FLAGS_VLAN BIT(1) +#define IXGBE_TX_FLAGS_TSO BIT(2) +#define IXGBE_TX_FLAGS_IPV4 BIT(3) #define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 007cbe094990..e4e6060e6197 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1056,7 +1056,7 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) if (!test_bit(__IXGBEVF_DOWN, &adapter->state) && !test_bit(__IXGBEVF_REMOVING, &adapter->state)) ixgbevf_irq_enable_queues(adapter, - 1 << q_vector->v_idx); + BIT(q_vector->v_idx)); return 0; } @@ -1158,14 +1158,14 @@ static void ixgbevf_configure_msix(struct ixgbevf_adapter *adapter) } /* add q_vector eims value to global eims_enable_mask */ - adapter->eims_enable_mask |= 1 << v_idx; + adapter->eims_enable_mask |= BIT(v_idx); ixgbevf_write_eitr(q_vector); } ixgbevf_set_ivar(adapter, -1, 1, v_idx); /* setup eims_other and add value to global eims_enable_mask */ - adapter->eims_other = 1 << v_idx; + adapter->eims_other = BIT(v_idx); adapter->eims_enable_mask |= adapter->eims_other; } @@ -1589,8 +1589,8 @@ static void ixgbevf_configure_tx_ring(struct ixgbevf_adapter *adapter, txdctl |= (8 << 16); /* WTHRESH = 8 */ /* Setting PTHRESH to 32 both improves performance */ - txdctl |= (1 << 8) | /* HTHRESH = 1 */ - 32; /* PTHRESH = 32 */ + txdctl |= (1u << 8) | /* HTHRESH = 1 */ + 32; /* PTHRESH = 32 */ clear_bit(__IXGBEVF_HANG_CHECK_ARMED, &ring->state); @@ -1646,7 +1646,7 @@ static void ixgbevf_setup_psrtype(struct ixgbevf_adapter *adapter) IXGBE_PSRTYPE_L2HDR; if (adapter->num_rx_queues > 1) - psrtype |= 1 << 29; + psrtype |= BIT(29); IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); } @@ -2797,7 +2797,7 @@ static void ixgbevf_check_hang_subtask(struct ixgbevf_adapter *adapter) struct ixgbevf_q_vector *qv = adapter->q_vector[i]; if (qv->rx.ring || qv->tx.ring) - eics |= 1 << i; + eics |= BIT(i); } /* Cause software interrupt to ensure rings are cleaned */ @@ -3325,7 +3325,7 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring, /* mss_l4len_id: use 1 as index for TSO */ mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT; mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT; - mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT; + mss_l4len_idx |= (1u << IXGBE_ADVTXD_IDX_SHIFT); /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ vlan_macip_lens = skb_network_header_len(skb); @@ -3422,7 +3422,7 @@ static void ixgbevf_tx_olinfo_status(union ixgbe_adv_tx_desc *tx_desc, /* use index 1 context for TSO/FSO/FCOE */ if (tx_flags & IXGBE_TX_FLAGS_TSO) - olinfo_status |= cpu_to_le32(1 << IXGBE_ADVTXD_IDX_SHIFT); + olinfo_status |= cpu_to_le32(1u << IXGBE_ADVTXD_IDX_SHIFT); /* Check Context must be set if Tx switch is enabled, which it * always is for case where virtual functions are running -- GitLab From b83e30104bd9635765c562bd46b2e436350bd652 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 17:19:31 -0400 Subject: [PATCH 4138/9938] ixgbe/ixgbevf: Add support for GSO partial This patch adds support for partial GSO segmentation in the case of tunnels. Specifically with this change the driver an perform segmentation as long as the frame either has IPv6 inner headers, or we are allowed to mangle the IP IDs on the inner header. This is needed because we will not be modifying any fields from the start of the start of the outer transport header to the start of the inner transport header as we are treating them like they are just a block of IP options. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 133 ++++++++++++------ .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 129 ++++++++++++----- 2 files changed, 180 insertions(+), 82 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 60592cfa5ca6..0ef4a15bb23e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7256,9 +7256,18 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring, struct ixgbe_tx_buffer *first, u8 *hdr_len) { + u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; struct sk_buff *skb = first->skb; - u32 vlan_macip_lens, type_tucmd; - u32 mss_l4len_idx, l4len; + union { + struct iphdr *v4; + struct ipv6hdr *v6; + unsigned char *hdr; + } ip; + union { + struct tcphdr *tcp; + unsigned char *hdr; + } l4; + u32 paylen, l4_offset; int err; if (skb->ip_summed != CHECKSUM_PARTIAL) @@ -7271,46 +7280,52 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring, if (err < 0) return err; + ip.hdr = skb_network_header(skb); + l4.hdr = skb_checksum_start(skb); + /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP; - if (first->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = ip_hdr(skb); - iph->tot_len = 0; - iph->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); + /* initialize outer IP header fields */ + if (ip.v4->version == 4) { + /* IP header will have to cancel out any data that + * is not a part of the outer IP header + */ + ip.v4->check = csum_fold(csum_add(lco_csum(skb), + csum_unfold(l4.tcp->check))); type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; + + ip.v4->tot_len = 0; first->tx_flags |= IXGBE_TX_FLAGS_TSO | IXGBE_TX_FLAGS_CSUM | IXGBE_TX_FLAGS_IPV4; - } else if (skb_is_gso_v6(skb)) { - ipv6_hdr(skb)->payload_len = 0; - tcp_hdr(skb)->check = - ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); + } else { + ip.v6->payload_len = 0; first->tx_flags |= IXGBE_TX_FLAGS_TSO | IXGBE_TX_FLAGS_CSUM; } - /* compute header lengths */ - l4len = tcp_hdrlen(skb); - *hdr_len = skb_transport_offset(skb) + l4len; + /* determine offset of inner transport header */ + l4_offset = l4.hdr - skb->data; + + /* compute length of segmentation header */ + *hdr_len = (l4.tcp->doff * 4) + l4_offset; + + /* remove payload length from inner checksum */ + paylen = skb->len - l4_offset; + csum_replace_by_diff(&l4.tcp->check, htonl(paylen)); /* update gso size and bytecount with header size */ first->gso_segs = skb_shinfo(skb)->gso_segs; first->bytecount += (first->gso_segs - 1) * *hdr_len; /* mss_l4len_id: use 0 as index for TSO */ - mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT; + mss_l4len_idx = (*hdr_len - l4_offset) << IXGBE_ADVTXD_L4LEN_SHIFT; mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT; /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ - vlan_macip_lens = skb_network_header_len(skb); - vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens = l4.hdr - ip.hdr; + vlan_macip_lens |= (ip.hdr - skb->data) << IXGBE_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd, @@ -8898,17 +8913,36 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv) kfree(fwd_adapter); } -#define IXGBE_MAX_TUNNEL_HDR_LEN 80 +#define IXGBE_MAX_MAC_HDR_LEN 127 +#define IXGBE_MAX_NETWORK_HDR_LEN 511 + static netdev_features_t ixgbe_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features) { - if (!skb->encapsulation) - return features; - - if (unlikely(skb_inner_mac_header(skb) - skb_transport_header(skb) > - IXGBE_MAX_TUNNEL_HDR_LEN)) - return features & ~NETIF_F_CSUM_MASK; + unsigned int network_hdr_len, mac_hdr_len; + + /* Make certain the headers can be described by a context descriptor */ + mac_hdr_len = skb_network_header(skb) - skb->data; + if (unlikely(mac_hdr_len > IXGBE_MAX_MAC_HDR_LEN)) + return features & ~(NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_TSO | + NETIF_F_TSO6); + + network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb); + if (unlikely(network_hdr_len > IXGBE_MAX_NETWORK_HDR_LEN)) + return features & ~(NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_TSO | + NETIF_F_TSO6); + + /* We can only support IPV4 TSO in tunnels if we can mangle the + * inner IP ID field, so strip TSO if MANGLEID is not supported. + */ + if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) + features &= ~NETIF_F_TSO; return features; } @@ -9275,31 +9309,44 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_TSO6 | NETIF_F_RXHASH | NETIF_F_RXCSUM | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER; + NETIF_F_HW_CSUM; + +#define IXGBE_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ + NETIF_F_GSO_GRE_CSUM | \ + NETIF_F_GSO_IPIP | \ + NETIF_F_GSO_SIT | \ + NETIF_F_GSO_UDP_TUNNEL | \ + NETIF_F_GSO_UDP_TUNNEL_CSUM) + + netdev->gso_partial_features = IXGBE_GSO_PARTIAL_FEATURES; + netdev->features |= NETIF_F_GSO_PARTIAL | + IXGBE_GSO_PARTIAL_FEATURES; if (hw->mac.type >= ixgbe_mac_82599EB) netdev->features |= NETIF_F_SCTP_CRC; /* copy netdev features into list of user selectable features */ - netdev->hw_features |= netdev->features; - netdev->hw_features |= NETIF_F_RXALL | + netdev->hw_features |= netdev->features | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_RXALL | NETIF_F_HW_L2FW_DOFFLOAD; if (hw->mac.type >= ixgbe_mac_82599EB) netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; - netdev->vlan_features |= NETIF_F_SG | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_HW_CSUM | - NETIF_F_SCTP_CRC; + if (pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + + /* set this bit last since it cannot be part of vlan_features */ + netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_TX; + netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; + netdev->hw_enc_features |= netdev->vlan_features; netdev->mpls_features |= NETIF_F_HW_CSUM; - netdev->hw_enc_features |= NETIF_F_HW_CSUM; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; @@ -9330,10 +9377,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_FCOE_MTU; } #endif /* IXGBE_FCOE */ - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) netdev->hw_features |= NETIF_F_LRO; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index e4e6060e6197..eb91922bcb19 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3272,9 +3272,18 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring, struct ixgbevf_tx_buffer *first, u8 *hdr_len) { + u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; struct sk_buff *skb = first->skb; - u32 vlan_macip_lens, type_tucmd; - u32 mss_l4len_idx, l4len; + union { + struct iphdr *v4; + struct ipv6hdr *v6; + unsigned char *hdr; + } ip; + union { + struct tcphdr *tcp; + unsigned char *hdr; + } l4; + u32 paylen, l4_offset; int err; if (skb->ip_summed != CHECKSUM_PARTIAL) @@ -3287,49 +3296,53 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring, if (err < 0) return err; + ip.hdr = skb_network_header(skb); + l4.hdr = skb_checksum_start(skb); + /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP; - if (first->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = ip_hdr(skb); - - iph->tot_len = 0; - iph->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); + /* initialize outer IP header fields */ + if (ip.v4->version == 4) { + /* IP header will have to cancel out any data that + * is not a part of the outer IP header + */ + ip.v4->check = csum_fold(csum_add(lco_csum(skb), + csum_unfold(l4.tcp->check))); type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; + + ip.v4->tot_len = 0; first->tx_flags |= IXGBE_TX_FLAGS_TSO | IXGBE_TX_FLAGS_CSUM | IXGBE_TX_FLAGS_IPV4; - } else if (skb_is_gso_v6(skb)) { - ipv6_hdr(skb)->payload_len = 0; - tcp_hdr(skb)->check = - ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); + } else { + ip.v6->payload_len = 0; first->tx_flags |= IXGBE_TX_FLAGS_TSO | IXGBE_TX_FLAGS_CSUM; } - /* compute header lengths */ - l4len = tcp_hdrlen(skb); - *hdr_len += l4len; - *hdr_len = skb_transport_offset(skb) + l4len; + /* determine offset of inner transport header */ + l4_offset = l4.hdr - skb->data; + + /* compute length of segmentation header */ + *hdr_len = (l4.tcp->doff * 4) + l4_offset; - /* update GSO size and bytecount with header size */ + /* remove payload length from inner checksum */ + paylen = skb->len - l4_offset; + csum_replace_by_diff(&l4.tcp->check, htonl(paylen)); + + /* update gso size and bytecount with header size */ first->gso_segs = skb_shinfo(skb)->gso_segs; first->bytecount += (first->gso_segs - 1) * *hdr_len; /* mss_l4len_id: use 1 as index for TSO */ - mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT; + mss_l4len_idx = (*hdr_len - l4_offset) << IXGBE_ADVTXD_L4LEN_SHIFT; mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT; mss_l4len_idx |= (1u << IXGBE_ADVTXD_IDX_SHIFT); /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ - vlan_macip_lens = skb_network_header_len(skb); - vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens = l4.hdr - ip.hdr; + vlan_macip_lens |= (ip.hdr - skb->data) << IXGBE_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, @@ -3870,6 +3883,40 @@ static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev, return stats; } +#define IXGBEVF_MAX_MAC_HDR_LEN 127 +#define IXGBEVF_MAX_NETWORK_HDR_LEN 511 + +static netdev_features_t +ixgbevf_features_check(struct sk_buff *skb, struct net_device *dev, + netdev_features_t features) +{ + unsigned int network_hdr_len, mac_hdr_len; + + /* Make certain the headers can be described by a context descriptor */ + mac_hdr_len = skb_network_header(skb) - skb->data; + if (unlikely(mac_hdr_len > IXGBEVF_MAX_MAC_HDR_LEN)) + return features & ~(NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_TSO | + NETIF_F_TSO6); + + network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb); + if (unlikely(network_hdr_len > IXGBEVF_MAX_NETWORK_HDR_LEN)) + return features & ~(NETIF_F_HW_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_TSO | + NETIF_F_TSO6); + + /* We can only support IPV4 TSO in tunnels if we can mangle the + * inner IP ID field, so strip TSO if MANGLEID is not supported. + */ + if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) + features &= ~NETIF_F_TSO; + + return features; +} + static const struct net_device_ops ixgbevf_netdev_ops = { .ndo_open = ixgbevf_open, .ndo_stop = ixgbevf_close, @@ -3888,7 +3935,7 @@ static const struct net_device_ops ixgbevf_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ixgbevf_netpoll, #endif - .ndo_features_check = passthru_features_check, + .ndo_features_check = ixgbevf_features_check, }; static void ixgbevf_assign_netdev_ops(struct net_device *dev) @@ -3999,23 +4046,31 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_HW_CSUM | NETIF_F_SCTP_CRC; - netdev->features = netdev->hw_features | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER; +#define IXGBEVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ + NETIF_F_GSO_GRE_CSUM | \ + NETIF_F_GSO_IPIP | \ + NETIF_F_GSO_SIT | \ + NETIF_F_GSO_UDP_TUNNEL | \ + NETIF_F_GSO_UDP_TUNNEL_CSUM) - netdev->vlan_features |= NETIF_F_SG | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_HW_CSUM | - NETIF_F_SCTP_CRC; + netdev->gso_partial_features = IXGBEVF_GSO_PARTIAL_FEATURES; + netdev->hw_features |= NETIF_F_GSO_PARTIAL | + IXGBEVF_GSO_PARTIAL_FEATURES; - netdev->mpls_features |= NETIF_F_HW_CSUM; - netdev->hw_enc_features |= NETIF_F_HW_CSUM; + netdev->features = netdev->hw_features; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; + netdev->mpls_features |= NETIF_F_HW_CSUM; + netdev->hw_enc_features |= netdev->vlan_features; + + /* set this bit last since it cannot be part of vlan_features */ + netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_TX; + netdev->priv_flags |= IFF_UNICAST_FLT; if (IXGBE_REMOVED(hw->hw_addr)) { -- GitLab From 7921f4dc4c36e736d7a5b45dfa7b6a755a4fc012 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 14 Apr 2016 20:37:15 -0400 Subject: [PATCH 4139/9938] ixgbevf: Move API negotiation function into mac_ops This patch moves API negotiation into mac_ops. The general idea here is that with HyperV on the way we need to make certain that anything that will have different versions between HyperV and a standard VF needs to be abstracted enough so that we can have a separate function between the two so we can avoid changes in one breaking something in the other. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 2 +- drivers/net/ethernet/intel/ixgbevf/vf.c | 5 +++-- drivers/net/ethernet/intel/ixgbevf/vf.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index eb91922bcb19..319e25f29883 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -2056,7 +2056,7 @@ static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter) spin_lock_bh(&adapter->mbx_lock); while (api[idx] != ixgbe_mbox_api_unknown) { - err = ixgbevf_negotiate_api_version(hw, api[idx]); + err = hw->mac.ops.negotiate_api_version(hw, api[idx]); if (!err) break; idx++; diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c index 4d613a4f2a7f..987ad69d4918 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -670,11 +670,11 @@ void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size) } /** - * ixgbevf_negotiate_api_version - Negotiate supported API version + * ixgbevf_negotiate_api_version_vf - Negotiate supported API version * @hw: pointer to the HW structure * @api: integer containing requested API version **/ -int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api) +static int ixgbevf_negotiate_api_version_vf(struct ixgbe_hw *hw, int api) { int err; u32 msg[3]; @@ -769,6 +769,7 @@ static const struct ixgbe_mac_operations ixgbevf_mac_ops = { .stop_adapter = ixgbevf_stop_hw_vf, .setup_link = ixgbevf_setup_mac_link_vf, .check_link = ixgbevf_check_mac_link_vf, + .negotiate_api_version = ixgbevf_negotiate_api_version_vf, .set_rar = ixgbevf_set_rar_vf, .update_mc_addr_list = ixgbevf_update_mc_addr_list_vf, .update_xcast_mode = ixgbevf_update_xcast_mode, diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h index ef9f7736b4dc..8e623f9327ae 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.h +++ b/drivers/net/ethernet/intel/ixgbevf/vf.h @@ -51,6 +51,7 @@ struct ixgbe_mac_operations { s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*stop_adapter)(struct ixgbe_hw *); s32 (*get_bus_info)(struct ixgbe_hw *); + s32 (*negotiate_api_version)(struct ixgbe_hw *hw, int api); /* Link */ s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool); @@ -208,7 +209,6 @@ static inline u32 ixgbe_read_reg_array(struct ixgbe_hw *hw, u32 reg, #define IXGBE_READ_REG_ARRAY(h, r, o) ixgbe_read_reg_array(h, r, o) void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size); -int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api); int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs, unsigned int *default_tc); int ixgbevf_get_reta_locked(struct ixgbe_hw *hw, u32 *reta, int num_rx_queues); -- GitLab From d4f90d9dca26efef7a1112a8f4258c90b73bb37f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 16 Apr 2016 22:35:08 +0200 Subject: [PATCH 4140/9938] ixgbe: use msleep for long delays The newly added x550em_a support causes a link failure on ARM because of an overly long time passed into udelay(): ERROR: "__bad_udelay" [drivers/net/ethernet/intel/ixgbe/ixgbe.ko] undefined! There are multiple variants of the ixgbe_acquire_swfw_sync_*() function, and the other ones all use msleep(), so we can safely assume that all callers are allowed to sleep, which makes msleep() a better replacement than mdelay(). Signed-off-by: Arnd Bergmann Fixes: 49425dfc7451 ("ixgbe: Add support for x550em_a 10G MAC type") Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index c8a4f5ef06c0..19b75cd98682 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2765,7 +2765,7 @@ static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) ixgbe_release_swfw_sync_X540(hw, hmask); if (status != IXGBE_ERR_TOKEN_RETRY) return status; - udelay(FW_PHY_TOKEN_DELAY * 1000); + msleep(FW_PHY_TOKEN_DELAY); } return status; -- GitLab From 1a2b2c708c5f7187c4c33d002bed6130381a6698 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 03:37:03 -0300 Subject: [PATCH 4141/9938] [media] Documentation: video4linux: fix spelling mistakes Fix spelling mistakes. Signed-off-by: Eric Engestrom Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/vivid.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/video4linux/vivid.txt b/Documentation/video4linux/vivid.txt index e35d376b7f64..8da5d2a576bc 100644 --- a/Documentation/video4linux/vivid.txt +++ b/Documentation/video4linux/vivid.txt @@ -294,7 +294,7 @@ the result will be. These inputs support all combinations of the field setting. Special care has been taken to faithfully reproduce how fields are handled for the different -TV standards. This is particularly noticable when generating a horizontally +TV standards. This is particularly noticeable when generating a horizontally moving image so the temporal effect of using interlaced formats becomes clearly visible. For 50 Hz standards the top field is the oldest and the bottom field is the newest in time. For 60 Hz standards that is reversed: the bottom field @@ -313,7 +313,7 @@ will be SMPTE-170M. The pixel aspect ratio will depend on the TV standard. The video aspect ratio can be selected through the 'Standard Aspect Ratio' Vivid control. Choices are '4x3', '16x9' which will give letterboxed widescreen video and -'16x9 Anomorphic' which will give full screen squashed anamorphic widescreen +'16x9 Anamorphic' which will give full screen squashed anamorphic widescreen video that will need to be scaled accordingly. The TV 'tuner' supports a frequency range of 44-958 MHz. Channels are available @@ -862,7 +862,7 @@ RDS Radio Text: RDS Stereo: RDS Artificial Head: RDS Compressed: -RDS Dymanic PTY: +RDS Dynamic PTY: RDS Traffic Announcement: RDS Traffic Program: RDS Music: these are all controls that set the RDS data that is transmitted by -- GitLab From 363d79f1d5bd09158cc28db543ca18549a5d7e52 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Apr 2016 06:21:09 -0300 Subject: [PATCH 4142/9938] [media] tw686x: Don't go past array Depending on the compiler version, currently it produces the following warnings: tw686x-video.c: In function 'tw686x_video_init': tw686x-video.c:65:543: warning: array subscript is above array bounds [-Warray-bounds] This is actually bogus with the current code, as it currently hardcodes the framerate to 30 frames/sec, however a potential use after the array size could happen when the driver adds support for setting the framerate. So, fix it. Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw686x/tw686x-video.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index 60d38f19134b..d2a0147e6492 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -61,8 +61,17 @@ static unsigned int tw686x_fields_map(v4l2_std_id std, unsigned int fps) 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 0, 0 }; - unsigned int i = - (std & V4L2_STD_625_50) ? std_625_50[fps] : std_525_60[fps]; + unsigned int i; + + if (std & V4L2_STD_525_60) { + if (fps > ARRAY_SIZE(std_525_60)) + fps = 30; + i = std_525_60[fps]; + } else { + if (fps > ARRAY_SIZE(std_625_50)) + fps = 25; + i = std_625_50[fps]; + } return map[i]; } -- GitLab From 42c031dfaaadc48d0e7a8484b5ea383fe6054de0 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Fri, 15 Apr 2016 14:00:34 +0530 Subject: [PATCH 4143/9938] MAINTAINERS: fix stale TI DaVinci entries Fix stale git tree entry. Patchwork project has not been updated since TI DaVinci lost its dedicated mailing list. Remove that entry. Update mailing list to point to LAKML. Acked-by: Kevin Hilman Signed-off-by: Sekhar Nori --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..c0155f40909a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10148,8 +10148,8 @@ F: arch/arm/mach-s3c24xx/bast-irq.c TI DAVINCI MACHINE SUPPORT M: Sekhar Nori M: Kevin Hilman -T: git git://gitorious.org/linux-davinci/linux-davinci.git -Q: http://patchwork.kernel.org/project/linux-davinci/list/ +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +T: git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git S: Supported F: arch/arm/mach-davinci/ F: drivers/i2c/busses/i2c-davinci.c -- GitLab From 1e3404131bcee7e24fc441bb48defb12880f4b4c Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Fri, 15 Apr 2016 14:19:26 +0530 Subject: [PATCH 4144/9938] ARM: davinci_all_defconfig: support systemd CONFIG_FHANDLE is required by systemd[1], which is the default init system in more and more distributions. So lets enable it for DaVinci platforms as well. While at it, remove stale entry CONFIG_INOTIFY=y [1] https://github.com/systemd/systemd/blob/master/README#L37 Acked-by: Kevin Hilman Signed-off-by: Sekhar Nori --- arch/arm/configs/davinci_all_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index c5bccd9d010e..776fd8ad792f 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -2,6 +2,7 @@ CONFIG_EXPERIMENTAL=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -188,7 +189,6 @@ CONFIG_TI_EDMA=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_XFS_FS=m -CONFIG_INOTIFY=y CONFIG_AUTOFS4_FS=m CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y -- GitLab From a3efd81205b128a802025abb689925177a4607ed Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 18 Apr 2016 16:16:59 +0200 Subject: [PATCH 4145/9938] netfilter: conntrack: move generation seqcnt out of netns_ct We only allow rehash in init namespace, so we only use init_ns.generation. And even if we would allow it, it makes no sense as the conntrack locks are global; any ongoing rehash prevents insert/ delete. So make this private to nf_conntrack_core instead. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netns/conntrack.h | 1 - net/netfilter/nf_conntrack_core.c | 20 +++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 723b61c82b3f..b052785b1590 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -94,7 +94,6 @@ struct netns_ct { int sysctl_checksum; unsigned int htable_size; - seqcount_t generation; struct kmem_cache *nf_conntrack_cachep; struct hlist_nulls_head *hash; struct hlist_head *expect_hash; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 2fd607408998..a53c009fe510 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -69,6 +69,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(nf_conntrack_expect_lock); EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); static __read_mostly spinlock_t nf_conntrack_locks_all_lock; +static __read_mostly seqcount_t nf_conntrack_generation; static __read_mostly bool nf_conntrack_locks_all; void nf_conntrack_lock(spinlock_t *lock) __acquires(lock) @@ -107,7 +108,7 @@ static bool nf_conntrack_double_lock(struct net *net, unsigned int h1, spin_lock_nested(&nf_conntrack_locks[h1], SINGLE_DEPTH_NESTING); } - if (read_seqcount_retry(&net->ct.generation, sequence)) { + if (read_seqcount_retry(&nf_conntrack_generation, sequence)) { nf_conntrack_double_unlock(h1, h2); return true; } @@ -393,7 +394,7 @@ static void nf_ct_delete_from_lists(struct nf_conn *ct) local_bh_disable(); do { - sequence = read_seqcount_begin(&net->ct.generation); + sequence = read_seqcount_begin(&nf_conntrack_generation); hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); reply_hash = hash_conntrack(net, @@ -560,7 +561,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) local_bh_disable(); do { - sequence = read_seqcount_begin(&net->ct.generation); + sequence = read_seqcount_begin(&nf_conntrack_generation); hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); reply_hash = hash_conntrack(net, @@ -628,7 +629,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) local_bh_disable(); do { - sequence = read_seqcount_begin(&net->ct.generation); + sequence = read_seqcount_begin(&nf_conntrack_generation); /* reuse the hash saved before */ hash = *(unsigned long *)&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev; hash = hash_bucket(hash, net); @@ -771,12 +772,12 @@ static noinline int early_drop(struct net *net, unsigned int _hash) local_bh_disable(); restart: - sequence = read_seqcount_begin(&net->ct.generation); + sequence = read_seqcount_begin(&nf_conntrack_generation); hash = hash_bucket(_hash, net); for (; i < net->ct.htable_size; i++) { lockp = &nf_conntrack_locks[hash % CONNTRACK_LOCKS]; nf_conntrack_lock(lockp); - if (read_seqcount_retry(&net->ct.generation, sequence)) { + if (read_seqcount_retry(&nf_conntrack_generation, sequence)) { spin_unlock(lockp); goto restart; } @@ -1607,7 +1608,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) local_bh_disable(); nf_conntrack_all_lock(); - write_seqcount_begin(&init_net.ct.generation); + write_seqcount_begin(&nf_conntrack_generation); /* Lookups in the old hash might happen in parallel, which means we * might get false negatives during connection lookup. New connections @@ -1631,7 +1632,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) init_net.ct.htable_size = nf_conntrack_htable_size = hashsize; init_net.ct.hash = hash; - write_seqcount_end(&init_net.ct.generation); + write_seqcount_end(&nf_conntrack_generation); nf_conntrack_all_unlock(); local_bh_enable(); @@ -1657,6 +1658,8 @@ int nf_conntrack_init_start(void) int max_factor = 8; int i, ret, cpu; + seqcount_init(&nf_conntrack_generation); + for (i = 0; i < CONNTRACK_LOCKS; i++) spin_lock_init(&nf_conntrack_locks[i]); @@ -1783,7 +1786,6 @@ int nf_conntrack_init_net(struct net *net) int cpu; atomic_set(&net->ct.count, 0); - seqcount_init(&net->ct.generation); net->ct.pcpu_lists = alloc_percpu(struct ct_pcpu); if (!net->ct.pcpu_lists) -- GitLab From 7001c6d109ea41a88e7156f467cf9fb5f37f5036 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 18 Apr 2016 16:17:00 +0200 Subject: [PATCH 4146/9938] netfilter: conntrack: use get_random_once for nat and expectations Use a private seed and init it using get_random_once. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_expect.c | 7 +++---- net/netfilter/nf_nat_core.c | 6 ++++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 278927ab0948..c2f7c4f475b1 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -38,6 +38,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); unsigned int nf_ct_expect_max __read_mostly; static struct kmem_cache *nf_ct_expect_cachep __read_mostly; +static unsigned int nf_ct_expect_hashrnd __read_mostly; /* nf_conntrack_expect helper functions */ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, @@ -76,13 +77,11 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple { unsigned int hash; - if (unlikely(!nf_conntrack_hash_rnd)) { - init_nf_conntrack_hash_rnd(); - } + get_random_once(&nf_ct_expect_hashrnd, sizeof(nf_ct_expect_hashrnd)); hash = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all), (((tuple->dst.protonum ^ tuple->src.l3num) << 16) | - (__force __u16)tuple->dst.u.all) ^ nf_conntrack_hash_rnd); + (__force __u16)tuple->dst.u.all) ^ nf_ct_expect_hashrnd); return reciprocal_scale(hash, nf_ct_expect_hsize); } diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 06a9f45771ab..3d522715a167 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -37,7 +37,7 @@ static const struct nf_nat_l3proto __rcu *nf_nat_l3protos[NFPROTO_NUMPROTO] __read_mostly; static const struct nf_nat_l4proto __rcu **nf_nat_l4protos[NFPROTO_NUMPROTO] __read_mostly; - +static unsigned int nf_nat_hash_rnd __read_mostly; inline const struct nf_nat_l3proto * __nf_nat_l3proto_find(u8 family) @@ -122,9 +122,11 @@ hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple) { unsigned int hash; + get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd)); + /* Original src, to ensure we map it consistently if poss. */ hash = jhash2((u32 *)&tuple->src, sizeof(tuple->src) / sizeof(u32), - tuple->dst.protonum ^ nf_conntrack_hash_rnd); + tuple->dst.protonum ^ nf_nat_hash_rnd); return reciprocal_scale(hash, net->ct.nat_htable_size); } -- GitLab From 141658fb02c248e6243d619cb7d48a76158a66ac Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 18 Apr 2016 16:17:01 +0200 Subject: [PATCH 4147/9938] netfilter: conntrack: use get_random_once for conntrack hash seed As earlier commit removed accessed to the hash from other files we can also make it static. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack.h | 2 -- net/netfilter/nf_conntrack_core.c | 26 +++----------------------- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index fde4068eec0b..dd78bea227c8 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -289,8 +289,6 @@ struct kernel_param; int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); extern unsigned int nf_conntrack_htable_size; extern unsigned int nf_conntrack_max; -extern unsigned int nf_conntrack_hash_rnd; -void init_nf_conntrack_hash_rnd(void); struct nf_conn *nf_ct_tmpl_alloc(struct net *net, const struct nf_conntrack_zone *zone, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index a53c009fe510..1fd0ff1030c2 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -142,13 +142,14 @@ EXPORT_SYMBOL_GPL(nf_conntrack_max); DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked); EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); -unsigned int nf_conntrack_hash_rnd __read_mostly; -EXPORT_SYMBOL_GPL(nf_conntrack_hash_rnd); +static unsigned int nf_conntrack_hash_rnd __read_mostly; static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple) { unsigned int n; + get_random_once(&nf_conntrack_hash_rnd, sizeof(nf_conntrack_hash_rnd)); + /* The direction must be ignored, so we hash everything up to the * destination ports (which is a multiple of 4) and treat the last * three bytes manually. @@ -815,21 +816,6 @@ static noinline int early_drop(struct net *net, unsigned int _hash) return dropped; } -void init_nf_conntrack_hash_rnd(void) -{ - unsigned int rand; - - /* - * Why not initialize nf_conntrack_rnd in a "init()" function ? - * Because there isn't enough entropy when system initializing, - * and we initialize it as late as possible. - */ - do { - get_random_bytes(&rand, sizeof(rand)); - } while (!rand); - cmpxchg(&nf_conntrack_hash_rnd, 0, rand); -} - static struct nf_conn * __nf_conntrack_alloc(struct net *net, const struct nf_conntrack_zone *zone, @@ -839,12 +825,6 @@ __nf_conntrack_alloc(struct net *net, { struct nf_conn *ct; - if (unlikely(!nf_conntrack_hash_rnd)) { - init_nf_conntrack_hash_rnd(); - /* recompute the hash as nf_conntrack_hash_rnd is initialized */ - hash = hash_conntrack_raw(orig); - } - /* We don't want any race condition at early drop stage */ atomic_inc(&net->ct.count); -- GitLab From 0e9091d6862f60499fa3faec7c2060c1929d0763 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 12 Apr 2016 23:50:34 +0200 Subject: [PATCH 4148/9938] netfilter: nf_tables: introduce nft_setelem_parse_flags() helper This function parses the set element flags, thus, we can reuse the same handling when deleting elements. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 7a85a9dd37ad..1b3210b2b82d 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -3375,6 +3375,22 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem) } EXPORT_SYMBOL_GPL(nft_set_elem_destroy); +static int nft_setelem_parse_flags(const struct nft_set *set, + const struct nlattr *attr, u32 *flags) +{ + if (attr == NULL) + return 0; + + *flags = ntohl(nla_get_be32(attr)); + if (*flags & ~NFT_SET_ELEM_INTERVAL_END) + return -EINVAL; + if (!(set->flags & NFT_SET_INTERVAL) && + *flags & NFT_SET_ELEM_INTERVAL_END) + return -EINVAL; + + return 0; +} + static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, const struct nlattr *attr) { @@ -3388,8 +3404,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, struct nft_data data; enum nft_registers dreg; struct nft_trans *trans; + u32 flags = 0; u64 timeout; - u32 flags; u8 ulen; int err; @@ -3403,17 +3419,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, nft_set_ext_prepare(&tmpl); - flags = 0; - if (nla[NFTA_SET_ELEM_FLAGS] != NULL) { - flags = ntohl(nla_get_be32(nla[NFTA_SET_ELEM_FLAGS])); - if (flags & ~NFT_SET_ELEM_INTERVAL_END) - return -EINVAL; - if (!(set->flags & NFT_SET_INTERVAL) && - flags & NFT_SET_ELEM_INTERVAL_END) - return -EINVAL; - if (flags != 0) - nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS); - } + err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags); + if (err < 0) + return err; + if (flags != 0) + nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS); if (set->flags & NFT_SET_MAP) { if (nla[NFTA_SET_ELEM_DATA] == NULL && -- GitLab From 3971ca14350062fc30b2dd3ca182234f17d268c2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 12 Apr 2016 23:50:35 +0200 Subject: [PATCH 4149/9938] netfilter: nf_tables: parse element flags from nft_del_setelem() Parse flags and pass them to the set via ->deactivate() to check if we remove the right element from the intervals. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 38 ++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 1b3210b2b82d..73c8fad0b8ef 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -3592,9 +3592,13 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, const struct nlattr *attr) { struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; + struct nft_set_ext_tmpl tmpl; struct nft_data_desc desc; struct nft_set_elem elem; + struct nft_set_ext *ext; struct nft_trans *trans; + u32 flags = 0; + void *priv; int err; err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr, @@ -3606,6 +3610,14 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, if (nla[NFTA_SET_ELEM_KEY] == NULL) goto err1; + nft_set_ext_prepare(&tmpl); + + err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags); + if (err < 0) + return err; + if (flags != 0) + nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS); + err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc, nla[NFTA_SET_ELEM_KEY]); if (err < 0) @@ -3615,24 +3627,40 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) goto err2; + nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, desc.len); + + err = -ENOMEM; + elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, NULL, 0, + GFP_KERNEL); + if (elem.priv == NULL) + goto err2; + + ext = nft_set_elem_ext(set, elem.priv); + if (flags) + *nft_set_ext_flags(ext) = flags; + trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); if (trans == NULL) { err = -ENOMEM; - goto err2; + goto err3; } - elem.priv = set->ops->deactivate(set, &elem); - if (elem.priv == NULL) { + priv = set->ops->deactivate(set, &elem); + if (priv == NULL) { err = -ENOENT; - goto err3; + goto err4; } + kfree(elem.priv); + elem.priv = priv; nft_trans_elem(trans) = elem; list_add_tail(&trans->list, &ctx->net->nft.commit_list); return 0; -err3: +err4: kfree(trans); +err3: + kfree(elem.priv); err2: nft_data_uninit(&elem.key.val, desc.type); err1: -- GitLab From ef1d20e0f8a80ba2942a59331d472322794d6748 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 12 Apr 2016 23:50:36 +0200 Subject: [PATCH 4150/9938] netfilter: nft_rbtree: introduce nft_rbtree_interval_end() helper Add this new nft_rbtree_interval_end() helper function to check in the end interval is set. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_rbtree.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index 1c30f41cff5b..29f2ab88d787 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c @@ -29,6 +29,11 @@ struct nft_rbtree_elem { struct nft_set_ext ext; }; +static bool nft_rbtree_interval_end(const struct nft_rbtree_elem *rbe) +{ + return nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) && + (*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END); +} static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key, const struct nft_set_ext **ext) @@ -56,9 +61,7 @@ static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key, parent = parent->rb_left; continue; } - if (nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) && - *nft_set_ext_flags(&rbe->ext) & - NFT_SET_ELEM_INTERVAL_END) + if (nft_rbtree_interval_end(rbe)) goto out; spin_unlock_bh(&nft_rbtree_lock); -- GitLab From 2366c7fdb59812bbd1382afed69e250582c64187 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Thu, 7 Apr 2016 20:03:29 +0800 Subject: [PATCH 4151/9938] ARM64: ACPI: Check if it runs on Xen to enable or disable ACPI When it's a Xen domain0 booting with ACPI, it will supply a /chosen and a /hypervisor node in DT. So check if it needs to enable ACPI. Signed-off-by: Shannon Zhao Reviewed-by: Stefano Stabellini Acked-by: Hanjun Guo Tested-by: Julien Grall Acked-by: Mark Rutland Acked-by: Catalin Marinas Signed-off-by: Will Deacon --- arch/arm64/kernel/acpi.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index d1ce8e2f98b9..57ee31745af5 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -67,10 +67,15 @@ static int __init dt_scan_depth1_nodes(unsigned long node, { /* * Return 1 as soon as we encounter a node at depth 1 that is - * not the /chosen node. + * not the /chosen node, or /hypervisor node with compatible + * string "xen,xen". */ - if (depth == 1 && (strcmp(uname, "chosen") != 0)) - return 1; + if (depth == 1 && (strcmp(uname, "chosen") != 0)) { + if (strcmp(uname, "hypervisor") != 0 || + !of_flat_dt_is_compatible(node, "xen,xen")) + return 1; + } + return 0; } @@ -184,7 +189,8 @@ void __init acpi_boot_table_init(void) /* * Enable ACPI instead of device tree unless * - ACPI has been disabled explicitly (acpi=off), or - * - the device tree is not empty (it has more than just a /chosen node) + * - the device tree is not empty (it has more than just a /chosen node, + * and a /hypervisor node when running on Xen) * and ACPI has not been force enabled (acpi=force) */ if (param_acpi_off || -- GitLab From 9981293fb0f02e6127d6ab00218bf091f9f6c89b Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 25 Apr 2016 11:25:11 +0100 Subject: [PATCH 4152/9938] arm64: make dt_scan_depth1_nodes more readable Improve the readability of dt_scan_depth1_nodes by removing the nested conditionals. Signed-off-by: Mark Rutland Signed-off-by: Stefano Stabellini Signed-off-by: Will Deacon --- arch/arm64/kernel/acpi.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 57ee31745af5..6884c7678453 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -66,17 +66,24 @@ static int __init dt_scan_depth1_nodes(unsigned long node, void *data) { /* - * Return 1 as soon as we encounter a node at depth 1 that is - * not the /chosen node, or /hypervisor node with compatible - * string "xen,xen". + * Ignore anything not directly under the root node; we'll + * catch its parent instead. */ - if (depth == 1 && (strcmp(uname, "chosen") != 0)) { - if (strcmp(uname, "hypervisor") != 0 || - !of_flat_dt_is_compatible(node, "xen,xen")) - return 1; - } + if (depth != 1) + return 0; - return 0; + if (strcmp(uname, "chosen") == 0) + return 0; + + if (strcmp(uname, "hypervisor") == 0 && + of_flat_dt_is_compatible(node, "xen,xen")) + return 0; + + /* + * This node at depth 1 is neither a chosen node nor a xen node, + * which we do not expect. + */ + return 1; } /* -- GitLab From 8b182f395aa6e41973eff14619f3cdd36a6c67de Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 14 Apr 2016 17:49:53 -0700 Subject: [PATCH 4153/9938] ARM: davinci_all_defconfig: enable SPI and NOR as modules Enable SPI driver and SPI NOR flash support as modules. Tested with SPI NOR flash on DA850-EVM. Basic boot test only to confirm NOR flash device detection. Signed-off-by: Kevin Hilman Signed-off-by: Sekhar Nori --- arch/arm/configs/davinci_all_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index 776fd8ad792f..f33d042b1273 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -71,8 +71,10 @@ CONFIG_MTD_CFI=m CONFIG_MTD_CFI_INTELEXT=m CONFIG_MTD_CFI_AMDSTD=m CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_M25P80=m CONFIG_MTD_NAND=m CONFIG_MTD_NAND_DAVINCI=m +CONFIG_MTD_SPI_NOR=m CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_RAM=y @@ -118,6 +120,8 @@ CONFIG_SERIAL_OF_PLATFORM=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_DAVINCI=y +CONFIG_SPI=y +CONFIG_SPI_DAVINCI=m CONFIG_PINCTRL_SINGLE=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_PCF857X=y -- GitLab From ce29daf53e513e1e0c8797b647f8833526ed8f10 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Date: Thu, 21 Apr 2016 05:58:39 -0700 Subject: [PATCH 4154/9938] Documentation: arm64: pmu: Add Broadcom Vulcan PMU binding Document the compatible string for Broadcom Vulcan PMU. Also arranged the list in alphabetical order. Signed-off-by: Ashok Kumar Acked-by: Rob Herring Acked-by: Mark Rutland Signed-off-by: Will Deacon --- Documentation/devicetree/bindings/arm/pmu.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt index 6eb73be9433e..74d5417d0410 100644 --- a/Documentation/devicetree/bindings/arm/pmu.txt +++ b/Documentation/devicetree/bindings/arm/pmu.txt @@ -22,10 +22,11 @@ Required properties: "arm,arm11mpcore-pmu" "arm,arm1176-pmu" "arm,arm1136-pmu" + "brcm,vulcan-pmu" + "cavium,thunder-pmu" "qcom,scorpion-pmu" "qcom,scorpion-mp-pmu" "qcom,krait-pmu" - "cavium,thunder-pmu" - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a per-cpu interrupt (PPI) then 1 interrupt should be specified. -- GitLab From 713755d724065d0b191fc42fda2890a1430c5038 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Date: Thu, 21 Apr 2016 05:58:40 -0700 Subject: [PATCH 4155/9938] arm64: dts: Add Broadcom Vulcan PMU in dts Add "brcm,vulcan-pmu" compatible string for Broadcom Vulcan PMU. Signed-off-by: Ashok Kumar Acked-by: Mark Rutland Signed-off-by: Will Deacon --- arch/arm64/boot/dts/broadcom/vulcan.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/broadcom/vulcan.dtsi b/arch/arm64/boot/dts/broadcom/vulcan.dtsi index c49b5a85809c..03dd845394c0 100644 --- a/arch/arm64/boot/dts/broadcom/vulcan.dtsi +++ b/arch/arm64/boot/dts/broadcom/vulcan.dtsi @@ -86,7 +86,7 @@ }; pmu { - compatible = "arm,armv8-pmuv3"; + compatible = "brcm,vulcan-pmu", "arm,armv8-pmuv3"; interrupts = ; /* PMU overflow */ }; -- GitLab From 03598fdbc9deaecde3d981d42cd36f108fab4aa2 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Date: Thu, 21 Apr 2016 05:58:41 -0700 Subject: [PATCH 4156/9938] arm64/perf: Changed events naming as per the ARM ARM changed all the common events name definition as per the document ARM DDI 0487A.g SoC specific event names follow the general naming style in the file and doesn't reflect any document. changed ARMV8_A53_PERFCTR_PREFETCH_LINEFILL to ARMV8_A53_PERFCTR_PREF_LINEFILL to match with other SoC specific event names which use _PREF_ style. corrected typo l21 to l2i. Signed-off-by: Ashok Kumar Reviewed-by: Mark Rutland Signed-off-by: Will Deacon --- arch/arm64/kernel/perf_event.c | 306 ++++++++++++++++----------------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index f419a7c075a4..5dcdbffa28e7 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -33,43 +33,43 @@ */ /* Required events. */ -#define ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR 0x00 -#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL 0x03 -#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS 0x04 -#define ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED 0x10 -#define ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES 0x11 -#define ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED 0x12 +#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00 +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03 +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04 +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10 +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11 +#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12 /* At least one of the following is required. */ -#define ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED 0x08 -#define ARMV8_PMUV3_PERFCTR_OP_SPEC 0x1B +#define ARMV8_PMUV3_PERFCTR_INST_RETIRED 0x08 +#define ARMV8_PMUV3_PERFCTR_INST_SPEC 0x1B /* Common architectural events. */ -#define ARMV8_PMUV3_PERFCTR_MEM_READ 0x06 -#define ARMV8_PMUV3_PERFCTR_MEM_WRITE 0x07 +#define ARMV8_PMUV3_PERFCTR_LD_RETIRED 0x06 +#define ARMV8_PMUV3_PERFCTR_ST_RETIRED 0x07 #define ARMV8_PMUV3_PERFCTR_EXC_TAKEN 0x09 -#define ARMV8_PMUV3_PERFCTR_EXC_EXECUTED 0x0A -#define ARMV8_PMUV3_PERFCTR_CID_WRITE 0x0B -#define ARMV8_PMUV3_PERFCTR_PC_WRITE 0x0C -#define ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH 0x0D -#define ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN 0x0E -#define ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS 0x0F -#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE 0x1C +#define ARMV8_PMUV3_PERFCTR_EXC_RETURN 0x0A +#define ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED 0x0B +#define ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED 0x0C +#define ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED 0x0D +#define ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED 0x0E +#define ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED 0x0F +#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED 0x1C #define ARMV8_PMUV3_PERFCTR_CHAIN 0x1E #define ARMV8_PMUV3_PERFCTR_BR_RETIRED 0x21 /* Common microarchitectural events. */ -#define ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL 0x01 -#define ARMV8_PMUV3_PERFCTR_ITLB_REFILL 0x02 -#define ARMV8_PMUV3_PERFCTR_DTLB_REFILL 0x05 +#define ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL 0x01 +#define ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL 0x02 +#define ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL 0x05 #define ARMV8_PMUV3_PERFCTR_MEM_ACCESS 0x13 -#define ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS 0x14 -#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB 0x15 -#define ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS 0x16 -#define ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL 0x17 -#define ARMV8_PMUV3_PERFCTR_L2_CACHE_WB 0x18 +#define ARMV8_PMUV3_PERFCTR_L1I_CACHE 0x14 +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB 0x15 +#define ARMV8_PMUV3_PERFCTR_L2D_CACHE 0x16 +#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL 0x17 +#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB 0x18 #define ARMV8_PMUV3_PERFCTR_BUS_ACCESS 0x19 -#define ARMV8_PMUV3_PERFCTR_MEM_ERROR 0x1A +#define ARMV8_PMUV3_PERFCTR_MEMORY_ERROR 0x1A #define ARMV8_PMUV3_PERFCTR_BUS_CYCLES 0x1D #define ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE 0x1F #define ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE 0x20 @@ -85,71 +85,71 @@ #define ARMV8_PMUV3_PERFCTR_L3D_CACHE 0x2B #define ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB 0x2C #define ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL 0x2D -#define ARMV8_PMUV3_PERFCTR_L21_TLB_REFILL 0x2E +#define ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL 0x2E #define ARMV8_PMUV3_PERFCTR_L2D_TLB 0x2F -#define ARMV8_PMUV3_PERFCTR_L21_TLB 0x30 - -/* ARMv8 implementation defined event types. */ -#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD 0x40 -#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST 0x41 -#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD 0x42 -#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST 0x43 -#define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD 0x4C -#define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST 0x4D -#define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD 0x4E -#define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST 0x4F +#define ARMV8_PMUV3_PERFCTR_L2I_TLB 0x30 + +/* ARMv8 recommended implementation defined event types */ +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD 0x40 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x41 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD 0x42 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x43 +#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x4C +#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x4D +#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x4E +#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x4F /* ARMv8 Cortex-A53 specific event types. */ -#define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL 0xC2 +#define ARMV8_A53_PERFCTR_PREF_LINEFILL 0xC2 /* ARMv8 Cavium ThunderX specific event types. */ -#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST 0xE9 -#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS 0xEA -#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS 0xEB -#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS 0xEC -#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS 0xED +#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_MISS_ST 0xE9 +#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS 0xEA +#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS 0xEB +#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS 0xEC +#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS 0xED /* PMUv3 HW events mapping. */ static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { PERF_MAP_ALL_UNSUPPORTED, - [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, + [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED, + [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, }; /* ARM Cortex-A53 HW events mapping. */ static const unsigned armv8_a53_perf_map[PERF_COUNT_HW_MAX] = { PERF_MAP_ALL_UNSUPPORTED, - [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, + [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED, + [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED, + [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES, }; /* ARM Cortex-A57 and Cortex-A72 events mapping. */ static const unsigned armv8_a57_perf_map[PERF_COUNT_HW_MAX] = { PERF_MAP_ALL_UNSUPPORTED, - [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, + [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED, + [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES, }; static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = { PERF_MAP_ALL_UNSUPPORTED, - [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, + [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED, + [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED, + [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND, [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND, }; @@ -159,15 +159,15 @@ static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = { PERF_CACHE_MAP_ALL_UNSUPPORTED, - [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, + [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, - [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, }; static const unsigned armv8_a53_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] @@ -175,21 +175,21 @@ static const unsigned armv8_a53_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = { PERF_CACHE_MAP_ALL_UNSUPPORTED, - [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, - [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, - [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_A53_PERFCTR_PREFETCH_LINEFILL, + [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_A53_PERFCTR_PREF_LINEFILL, - [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS, - [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL, + [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE, + [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL, - [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL, + [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL, - [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, }; static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] @@ -197,23 +197,23 @@ static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = { PERF_CACHE_MAP_ALL_UNSUPPORTED, - [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD, - [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD, - [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST, - [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST, + [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD, + [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD, + [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR, + [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR, - [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS, - [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL, + [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE, + [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL, - [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD, - [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST, + [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD, + [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR, - [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL, + [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL, - [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, }; static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] @@ -221,29 +221,29 @@ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = { PERF_CACHE_MAP_ALL_UNSUPPORTED, - [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD, - [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD, - [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST, - [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST, - [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS, - [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS, - - [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS, - [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL, - [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS, - [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS, - - [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD, - [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD, - [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST, - [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST, - - [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL, - - [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, - [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, + [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD, + [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD, + [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR, + [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_MISS_ST, + [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS, + [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS, + + [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE, + [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL, + [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS, + [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS, + + [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD, + [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD, + [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR, + [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR, + + [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL, + + [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, }; #define ARMV8_EVENT_ATTR_RESOLVE(m) #m @@ -251,35 +251,35 @@ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] PMU_EVENT_ATTR_STRING(name, armv8_event_attr_##name, \ "event=" ARMV8_EVENT_ATTR_RESOLVE(config)) -ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR); -ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL); -ARMV8_EVENT_ATTR(l1i_tlb_refill, ARMV8_PMUV3_PERFCTR_ITLB_REFILL); -ARMV8_EVENT_ATTR(l1d_cache_refill, ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL); -ARMV8_EVENT_ATTR(l1d_cache, ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS); -ARMV8_EVENT_ATTR(l1d_tlb_refill, ARMV8_PMUV3_PERFCTR_DTLB_REFILL); -ARMV8_EVENT_ATTR(ld_retired, ARMV8_PMUV3_PERFCTR_MEM_READ); -ARMV8_EVENT_ATTR(st_retired, ARMV8_PMUV3_PERFCTR_MEM_WRITE); -ARMV8_EVENT_ATTR(inst_retired, ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED); +ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_SW_INCR); +ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL); +ARMV8_EVENT_ATTR(l1i_tlb_refill, ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL); +ARMV8_EVENT_ATTR(l1d_cache_refill, ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL); +ARMV8_EVENT_ATTR(l1d_cache, ARMV8_PMUV3_PERFCTR_L1D_CACHE); +ARMV8_EVENT_ATTR(l1d_tlb_refill, ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL); +ARMV8_EVENT_ATTR(ld_retired, ARMV8_PMUV3_PERFCTR_LD_RETIRED); +ARMV8_EVENT_ATTR(st_retired, ARMV8_PMUV3_PERFCTR_ST_RETIRED); +ARMV8_EVENT_ATTR(inst_retired, ARMV8_PMUV3_PERFCTR_INST_RETIRED); ARMV8_EVENT_ATTR(exc_taken, ARMV8_PMUV3_PERFCTR_EXC_TAKEN); -ARMV8_EVENT_ATTR(exc_return, ARMV8_PMUV3_PERFCTR_EXC_EXECUTED); -ARMV8_EVENT_ATTR(cid_write_retired, ARMV8_PMUV3_PERFCTR_CID_WRITE); -ARMV8_EVENT_ATTR(pc_write_retired, ARMV8_PMUV3_PERFCTR_PC_WRITE); -ARMV8_EVENT_ATTR(br_immed_retired, ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH); -ARMV8_EVENT_ATTR(br_return_retired, ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN); -ARMV8_EVENT_ATTR(unaligned_ldst_retired, ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS); -ARMV8_EVENT_ATTR(br_mis_pred, ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED); -ARMV8_EVENT_ATTR(cpu_cycles, ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES); -ARMV8_EVENT_ATTR(br_pred, ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED); +ARMV8_EVENT_ATTR(exc_return, ARMV8_PMUV3_PERFCTR_EXC_RETURN); +ARMV8_EVENT_ATTR(cid_write_retired, ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED); +ARMV8_EVENT_ATTR(pc_write_retired, ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED); +ARMV8_EVENT_ATTR(br_immed_retired, ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED); +ARMV8_EVENT_ATTR(br_return_retired, ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED); +ARMV8_EVENT_ATTR(unaligned_ldst_retired, ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED); +ARMV8_EVENT_ATTR(br_mis_pred, ARMV8_PMUV3_PERFCTR_BR_MIS_PRED); +ARMV8_EVENT_ATTR(cpu_cycles, ARMV8_PMUV3_PERFCTR_CPU_CYCLES); +ARMV8_EVENT_ATTR(br_pred, ARMV8_PMUV3_PERFCTR_BR_PRED); ARMV8_EVENT_ATTR(mem_access, ARMV8_PMUV3_PERFCTR_MEM_ACCESS); -ARMV8_EVENT_ATTR(l1i_cache, ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS); -ARMV8_EVENT_ATTR(l1d_cache_wb, ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB); -ARMV8_EVENT_ATTR(l2d_cache, ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS); -ARMV8_EVENT_ATTR(l2d_cache_refill, ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL); -ARMV8_EVENT_ATTR(l2d_cache_wb, ARMV8_PMUV3_PERFCTR_L2_CACHE_WB); +ARMV8_EVENT_ATTR(l1i_cache, ARMV8_PMUV3_PERFCTR_L1I_CACHE); +ARMV8_EVENT_ATTR(l1d_cache_wb, ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB); +ARMV8_EVENT_ATTR(l2d_cache, ARMV8_PMUV3_PERFCTR_L2D_CACHE); +ARMV8_EVENT_ATTR(l2d_cache_refill, ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL); +ARMV8_EVENT_ATTR(l2d_cache_wb, ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB); ARMV8_EVENT_ATTR(bus_access, ARMV8_PMUV3_PERFCTR_BUS_ACCESS); -ARMV8_EVENT_ATTR(memory_error, ARMV8_PMUV3_PERFCTR_MEM_ERROR); -ARMV8_EVENT_ATTR(inst_spec, ARMV8_PMUV3_PERFCTR_OP_SPEC); -ARMV8_EVENT_ATTR(ttbr_write_retired, ARMV8_PMUV3_PERFCTR_TTBR_WRITE); +ARMV8_EVENT_ATTR(memory_error, ARMV8_PMUV3_PERFCTR_MEMORY_ERROR); +ARMV8_EVENT_ATTR(inst_spec, ARMV8_PMUV3_PERFCTR_INST_SPEC); +ARMV8_EVENT_ATTR(ttbr_write_retired, ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED); ARMV8_EVENT_ATTR(bus_cycles, ARMV8_PMUV3_PERFCTR_BUS_CYCLES); ARMV8_EVENT_ATTR(chain, ARMV8_PMUV3_PERFCTR_CHAIN); ARMV8_EVENT_ATTR(l1d_cache_allocate, ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE); @@ -297,9 +297,9 @@ ARMV8_EVENT_ATTR(l3d_cache_refill, ARMV8_PMUV3_PERFCTR_L3D_CACHE_REFILL); ARMV8_EVENT_ATTR(l3d_cache, ARMV8_PMUV3_PERFCTR_L3D_CACHE); ARMV8_EVENT_ATTR(l3d_cache_wb, ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB); ARMV8_EVENT_ATTR(l2d_tlb_refill, ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL); -ARMV8_EVENT_ATTR(l21_tlb_refill, ARMV8_PMUV3_PERFCTR_L21_TLB_REFILL); +ARMV8_EVENT_ATTR(l2i_tlb_refill, ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL); ARMV8_EVENT_ATTR(l2d_tlb, ARMV8_PMUV3_PERFCTR_L2D_TLB); -ARMV8_EVENT_ATTR(l21_tlb, ARMV8_PMUV3_PERFCTR_L21_TLB); +ARMV8_EVENT_ATTR(l2i_tlb, ARMV8_PMUV3_PERFCTR_L2I_TLB); static struct attribute *armv8_pmuv3_event_attrs[] = { &armv8_event_attr_sw_incr.attr.attr, @@ -348,9 +348,9 @@ static struct attribute *armv8_pmuv3_event_attrs[] = { &armv8_event_attr_l3d_cache.attr.attr, &armv8_event_attr_l3d_cache_wb.attr.attr, &armv8_event_attr_l2d_tlb_refill.attr.attr, - &armv8_event_attr_l21_tlb_refill.attr.attr, + &armv8_event_attr_l2i_tlb_refill.attr.attr, &armv8_event_attr_l2d_tlb.attr.attr, - &armv8_event_attr_l21_tlb.attr.attr, + &armv8_event_attr_l2i_tlb.attr.attr, NULL, }; @@ -685,7 +685,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT; /* Always place a cycle counter into the cycle counter. */ - if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) { + if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) { if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) return -EAGAIN; -- GitLab From 0893f74545e615eda796c8d443cafee1959f3a73 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Date: Thu, 21 Apr 2016 05:58:42 -0700 Subject: [PATCH 4157/9938] arm64/perf: Define complete ARMv8 recommended implementation defined events Defined all the ARMv8 recommended implementation defined events from J3 - "ARM recommendations for IMPLEMENTATION DEFINED event numbers" in ARM DDI 0487A.g. Signed-off-by: Ashok Kumar Reviewed-by: Mark Rutland Signed-off-by: Will Deacon --- arch/arm64/kernel/perf_event.c | 79 ++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 5dcdbffa28e7..d5a02bc75667 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -94,10 +94,89 @@ #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x41 #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD 0x42 #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x43 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_INNER 0x44 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_OUTER 0x45 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_VICTIM 0x46 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_CLEAN 0x47 +#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_INVAL 0x48 + #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x4C #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x4D #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x4E #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x4F +#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_RD 0x50 +#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WR 0x51 +#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_RD 0x52 +#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_WR 0x53 + +#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_VICTIM 0x56 +#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_CLEAN 0x57 +#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_INVAL 0x58 + +#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_RD 0x5C +#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_WR 0x5D +#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_RD 0x5E +#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_WR 0x5F + +#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD 0x60 +#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR 0x61 +#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_SHARED 0x62 +#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NOT_SHARED 0x63 +#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NORMAL 0x64 +#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_PERIPH 0x65 + +#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_RD 0x66 +#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_WR 0x67 +#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LD_SPEC 0x68 +#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_ST_SPEC 0x69 +#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LDST_SPEC 0x6A + +#define ARMV8_IMPDEF_PERFCTR_LDREX_SPEC 0x6C +#define ARMV8_IMPDEF_PERFCTR_STREX_PASS_SPEC 0x6D +#define ARMV8_IMPDEF_PERFCTR_STREX_FAIL_SPEC 0x6E +#define ARMV8_IMPDEF_PERFCTR_STREX_SPEC 0x6F +#define ARMV8_IMPDEF_PERFCTR_LD_SPEC 0x70 +#define ARMV8_IMPDEF_PERFCTR_ST_SPEC 0x71 +#define ARMV8_IMPDEF_PERFCTR_LDST_SPEC 0x72 +#define ARMV8_IMPDEF_PERFCTR_DP_SPEC 0x73 +#define ARMV8_IMPDEF_PERFCTR_ASE_SPEC 0x74 +#define ARMV8_IMPDEF_PERFCTR_VFP_SPEC 0x75 +#define ARMV8_IMPDEF_PERFCTR_PC_WRITE_SPEC 0x76 +#define ARMV8_IMPDEF_PERFCTR_CRYPTO_SPEC 0x77 +#define ARMV8_IMPDEF_PERFCTR_BR_IMMED_SPEC 0x78 +#define ARMV8_IMPDEF_PERFCTR_BR_RETURN_SPEC 0x79 +#define ARMV8_IMPDEF_PERFCTR_BR_INDIRECT_SPEC 0x7A + +#define ARMV8_IMPDEF_PERFCTR_ISB_SPEC 0x7C +#define ARMV8_IMPDEF_PERFCTR_DSB_SPEC 0x7D +#define ARMV8_IMPDEF_PERFCTR_DMB_SPEC 0x7E + +#define ARMV8_IMPDEF_PERFCTR_EXC_UNDEF 0x81 +#define ARMV8_IMPDEF_PERFCTR_EXC_SVC 0x82 +#define ARMV8_IMPDEF_PERFCTR_EXC_PABORT 0x83 +#define ARMV8_IMPDEF_PERFCTR_EXC_DABORT 0x84 + +#define ARMV8_IMPDEF_PERFCTR_EXC_IRQ 0x86 +#define ARMV8_IMPDEF_PERFCTR_EXC_FIQ 0x87 +#define ARMV8_IMPDEF_PERFCTR_EXC_SMC 0x88 + +#define ARMV8_IMPDEF_PERFCTR_EXC_HVC 0x8A +#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_PABORT 0x8B +#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_DABORT 0x8C +#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_OTHER 0x8D +#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_IRQ 0x8E +#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_FIQ 0x8F +#define ARMV8_IMPDEF_PERFCTR_RC_LD_SPEC 0x90 +#define ARMV8_IMPDEF_PERFCTR_RC_ST_SPEC 0x91 + +#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_RD 0xA0 +#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WR 0xA1 +#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_RD 0xA2 +#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_WR 0xA3 + +#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_VICTIM 0xA6 +#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_CLEAN 0xA7 +#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_INVAL 0xA8 /* ARMv8 Cortex-A53 specific event types. */ #define ARMV8_A53_PERFCTR_PREF_LINEFILL 0xC2 -- GitLab From bf2d4782e7500b6e3e6f606b17b596751bc14013 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Date: Thu, 21 Apr 2016 05:58:43 -0700 Subject: [PATCH 4158/9938] arm64/perf: Access pmu register using _sys_reg changed pmu register access to make use of _sys_reg from sysreg.h instead of accessing them directly. Signed-off-by: Ashok Kumar Reviewed-by: Mark Rutland Signed-off-by: Will Deacon --- arch/arm64/kernel/perf_event.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index d5a02bc75667..946ce4badb8e 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -476,16 +477,14 @@ static const struct attribute_group *armv8_pmuv3_attr_groups[] = { static inline u32 armv8pmu_pmcr_read(void) { - u32 val; - asm volatile("mrs %0, pmcr_el0" : "=r" (val)); - return val; + return read_sysreg(pmcr_el0); } static inline void armv8pmu_pmcr_write(u32 val) { val &= ARMV8_PMU_PMCR_MASK; isb(); - asm volatile("msr pmcr_el0, %0" :: "r" (val)); + write_sysreg(val, pmcr_el0); } static inline int armv8pmu_has_overflowed(u32 pmovsr) @@ -507,7 +506,7 @@ static inline int armv8pmu_counter_has_overflowed(u32 pmnc, int idx) static inline int armv8pmu_select_counter(int idx) { u32 counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmselr_el0, %0" :: "r" (counter)); + write_sysreg(counter, pmselr_el0); isb(); return idx; @@ -524,9 +523,9 @@ static inline u32 armv8pmu_read_counter(struct perf_event *event) pr_err("CPU%u reading wrong counter %d\n", smp_processor_id(), idx); else if (idx == ARMV8_IDX_CYCLE_COUNTER) - asm volatile("mrs %0, pmccntr_el0" : "=r" (value)); + value = read_sysreg(pmccntr_el0); else if (armv8pmu_select_counter(idx) == idx) - asm volatile("mrs %0, pmxevcntr_el0" : "=r" (value)); + value = read_sysreg(pmxevcntr_el0); return value; } @@ -548,47 +547,47 @@ static inline void armv8pmu_write_counter(struct perf_event *event, u32 value) */ u64 value64 = 0xffffffff00000000ULL | value; - asm volatile("msr pmccntr_el0, %0" :: "r" (value64)); + write_sysreg(value64, pmccntr_el0); } else if (armv8pmu_select_counter(idx) == idx) - asm volatile("msr pmxevcntr_el0, %0" :: "r" (value)); + write_sysreg(value, pmxevcntr_el0); } static inline void armv8pmu_write_evtype(int idx, u32 val) { if (armv8pmu_select_counter(idx) == idx) { val &= ARMV8_PMU_EVTYPE_MASK; - asm volatile("msr pmxevtyper_el0, %0" :: "r" (val)); + write_sysreg(val, pmxevtyper_el0); } } static inline int armv8pmu_enable_counter(int idx) { u32 counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmcntenset_el0, %0" :: "r" (BIT(counter))); + write_sysreg(BIT(counter), pmcntenset_el0); return idx; } static inline int armv8pmu_disable_counter(int idx) { u32 counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmcntenclr_el0, %0" :: "r" (BIT(counter))); + write_sysreg(BIT(counter), pmcntenclr_el0); return idx; } static inline int armv8pmu_enable_intens(int idx) { u32 counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmintenset_el1, %0" :: "r" (BIT(counter))); + write_sysreg(BIT(counter), pmintenset_el1); return idx; } static inline int armv8pmu_disable_intens(int idx) { u32 counter = ARMV8_IDX_TO_COUNTER(idx); - asm volatile("msr pmintenclr_el1, %0" :: "r" (BIT(counter))); + write_sysreg(BIT(counter), pmintenclr_el1); isb(); /* Clear the overflow flag in case an interrupt is pending. */ - asm volatile("msr pmovsclr_el0, %0" :: "r" (BIT(counter))); + write_sysreg(BIT(counter), pmovsclr_el0); isb(); return idx; @@ -599,11 +598,11 @@ static inline u32 armv8pmu_getreset_flags(void) u32 value; /* Read */ - asm volatile("mrs %0, pmovsclr_el0" : "=r" (value)); + value = read_sysreg(pmovsclr_el0); /* Write to clear flags */ value &= ARMV8_PMU_OVSR_MASK; - asm volatile("msr pmovsclr_el0, %0" :: "r" (value)); + write_sysreg(value, pmovsclr_el0); return value; } -- GitLab From 4b1a9e6934ec6e38138c66c2f73cf6f3695a9c6c Mon Sep 17 00:00:00 2001 From: Ashok Kumar Date: Thu, 21 Apr 2016 05:58:44 -0700 Subject: [PATCH 4159/9938] arm64/perf: Filter common events based on PMCEIDn_EL0 The complete common architectural and micro-architectural event number structure is filtered based on PMCEIDn_EL0 and exposed to /sys using is_visibile function pointer in events attribute_group. To filter the events in is_visible function, pmceid based bitmap is stored in arm_pmu structure and the id field from perf_pmu_events_attr is used to check against the bitmap. The function which derives event bitmap from PMCEIDn_EL0 is executed in the cpus, which has the pmu being initialized, for heterogeneous pmu support. Acked-by: Mark Rutland Signed-off-by: Ashok Kumar Signed-off-by: Will Deacon --- arch/arm64/kernel/perf_event.c | 70 ++++++++++++++++++++++++++-------- include/linux/perf/arm_pmu.h | 2 + 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 946ce4badb8e..e6a0fdb2538d 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -326,10 +326,22 @@ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, }; + +static ssize_t +armv8pmu_events_sysfs_show(struct device *dev, + struct device_attribute *attr, char *page) +{ + struct perf_pmu_events_attr *pmu_attr; + + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); + + return sprintf(page, "event=0x%03llx\n", pmu_attr->id); +} + #define ARMV8_EVENT_ATTR_RESOLVE(m) #m #define ARMV8_EVENT_ATTR(name, config) \ - PMU_EVENT_ATTR_STRING(name, armv8_event_attr_##name, \ - "event=" ARMV8_EVENT_ATTR_RESOLVE(config)) + PMU_EVENT_ATTR(name, armv8_event_attr_##name, \ + config, armv8pmu_events_sysfs_show) ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_SW_INCR); ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL); @@ -434,9 +446,27 @@ static struct attribute *armv8_pmuv3_event_attrs[] = { NULL, }; +static umode_t +armv8pmu_event_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int unused) +{ + struct device *dev = kobj_to_dev(kobj); + struct pmu *pmu = dev_get_drvdata(dev); + struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu); + struct perf_pmu_events_attr *pmu_attr; + + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr); + + if (test_bit(pmu_attr->id, cpu_pmu->pmceid_bitmap)) + return attr->mode; + + return 0; +} + static struct attribute_group armv8_pmuv3_events_attr_group = { .name = "events", .attrs = armv8_pmuv3_event_attrs, + .is_visible = armv8pmu_event_attr_is_visible, }; PMU_FORMAT_ATTR(event, "config:0-9"); @@ -859,22 +889,31 @@ static int armv8_thunder_map_event(struct perf_event *event) ARMV8_PMU_EVTYPE_EVENT); } -static void armv8pmu_read_num_pmnc_events(void *info) +static void __armv8pmu_probe_pmu(void *info) { - int *nb_cnt = info; + struct arm_pmu *cpu_pmu = info; + u32 pmceid[2]; /* Read the nb of CNTx counters supported from PMNC */ - *nb_cnt = (armv8pmu_pmcr_read() >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK; + cpu_pmu->num_events = (armv8pmu_pmcr_read() >> ARMV8_PMU_PMCR_N_SHIFT) + & ARMV8_PMU_PMCR_N_MASK; /* Add the CPU cycles counter */ - *nb_cnt += 1; + cpu_pmu->num_events += 1; + + pmceid[0] = read_sysreg(pmceid0_el0); + pmceid[1] = read_sysreg(pmceid1_el0); + + bitmap_from_u32array(cpu_pmu->pmceid_bitmap, + ARMV8_PMUV3_MAX_COMMON_EVENTS, pmceid, + ARRAY_SIZE(pmceid)); } -static int armv8pmu_probe_num_events(struct arm_pmu *arm_pmu) +static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu) { - return smp_call_function_any(&arm_pmu->supported_cpus, - armv8pmu_read_num_pmnc_events, - &arm_pmu->num_events, 1); + return smp_call_function_any(&cpu_pmu->supported_cpus, + __armv8pmu_probe_pmu, + cpu_pmu, 1); } static void armv8_pmu_init(struct arm_pmu *cpu_pmu) @@ -897,7 +936,8 @@ static int armv8_pmuv3_init(struct arm_pmu *cpu_pmu) armv8_pmu_init(cpu_pmu); cpu_pmu->name = "armv8_pmuv3"; cpu_pmu->map_event = armv8_pmuv3_map_event; - return armv8pmu_probe_num_events(cpu_pmu); + cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + return armv8pmu_probe_pmu(cpu_pmu); } static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu) @@ -906,7 +946,7 @@ static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->name = "armv8_cortex_a53"; cpu_pmu->map_event = armv8_a53_map_event; cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; - return armv8pmu_probe_num_events(cpu_pmu); + return armv8pmu_probe_pmu(cpu_pmu); } static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu) @@ -915,7 +955,7 @@ static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->name = "armv8_cortex_a57"; cpu_pmu->map_event = armv8_a57_map_event; cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; - return armv8pmu_probe_num_events(cpu_pmu); + return armv8pmu_probe_pmu(cpu_pmu); } static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu) @@ -924,7 +964,7 @@ static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->name = "armv8_cortex_a72"; cpu_pmu->map_event = armv8_a57_map_event; cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; - return armv8pmu_probe_num_events(cpu_pmu); + return armv8pmu_probe_pmu(cpu_pmu); } static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu) @@ -933,7 +973,7 @@ static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->name = "armv8_cavium_thunder"; cpu_pmu->map_event = armv8_thunder_map_event; cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; - return armv8pmu_probe_num_events(cpu_pmu); + return armv8pmu_probe_pmu(cpu_pmu); } static const struct of_device_id armv8_pmu_of_device_ids[] = { diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index 4196c90a3c88..d28ac05c7f92 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h @@ -105,6 +105,8 @@ struct arm_pmu { struct mutex reserve_mutex; u64 max_period; bool secure_access; /* 32-bit ARM only */ +#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40 + DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS); struct platform_device *plat_device; struct pmu_hw_events __percpu *hw_events; struct notifier_block hotplug_nb; -- GitLab From 201a72b2829fa6d58443fb9857db944b52d77062 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Date: Thu, 21 Apr 2016 05:58:45 -0700 Subject: [PATCH 4160/9938] arm64/perf: Add Broadcom Vulcan PMU support Broadcom Vulcan uses ARMv8 PMUv3 and supports most of the ARMv8 recommended implementation defined events. Added Vulcan events mapping for perf and perf_cache map. Acked-by: Mark Rutland Signed-off-by: Ashok Kumar Signed-off-by: Will Deacon --- arch/arm64/kernel/perf_event.c | 60 ++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index e6a0fdb2538d..ca6beb10b592 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -234,6 +234,20 @@ static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND, }; +/* Broadcom Vulcan events mapping */ +static const unsigned armv8_vulcan_perf_map[PERF_COUNT_HW_MAX] = { + PERF_MAP_ALL_UNSUPPORTED, + [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, + [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED, + [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, + [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_BR_RETIRED, + [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES, + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND, + [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND, +}; + static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = { @@ -326,6 +340,35 @@ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, }; +static const unsigned armv8_vulcan_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = { + PERF_CACHE_MAP_ALL_UNSUPPORTED, + + [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD, + [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD, + [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR, + [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR, + + [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE, + [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL, + + [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL, + [C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB, + + [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD, + [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR, + [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD, + [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR, + + [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, + [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + + [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD, + [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR, +}; static ssize_t armv8pmu_events_sysfs_show(struct device *dev, @@ -889,6 +932,13 @@ static int armv8_thunder_map_event(struct perf_event *event) ARMV8_PMU_EVTYPE_EVENT); } +static int armv8_vulcan_map_event(struct perf_event *event) +{ + return armpmu_map_event(event, &armv8_vulcan_perf_map, + &armv8_vulcan_perf_cache_map, + ARMV8_PMU_EVTYPE_EVENT); +} + static void __armv8pmu_probe_pmu(void *info) { struct arm_pmu *cpu_pmu = info; @@ -976,12 +1026,22 @@ static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu) return armv8pmu_probe_pmu(cpu_pmu); } +static int armv8_vulcan_pmu_init(struct arm_pmu *cpu_pmu) +{ + armv8_pmu_init(cpu_pmu); + cpu_pmu->name = "armv8_brcm_vulcan"; + cpu_pmu->map_event = armv8_vulcan_map_event; + cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + return armv8pmu_probe_pmu(cpu_pmu); +} + static const struct of_device_id armv8_pmu_of_device_ids[] = { {.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_init}, {.compatible = "arm,cortex-a53-pmu", .data = armv8_a53_pmu_init}, {.compatible = "arm,cortex-a57-pmu", .data = armv8_a57_pmu_init}, {.compatible = "arm,cortex-a72-pmu", .data = armv8_a72_pmu_init}, {.compatible = "cavium,thunder-pmu", .data = armv8_thunder_pmu_init}, + {.compatible = "brcm,vulcan-pmu", .data = armv8_vulcan_pmu_init}, {}, }; -- GitLab From 4be4b28a404e431660d8188f175c02dfee961399 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 16 Apr 2016 12:00:17 -0500 Subject: [PATCH 4161/9938] ARM: dts: da850: add spi0 to device tree Add device node and pinmux for SoC spi0. Signed-off-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/boot/dts/da850.dtsi | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index c9bf27d5ee9c..8880d577b931 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -120,7 +120,19 @@ 0x4 0x00000004 0x0000000f >; }; - spi1_pins: pinmux_spi_pins { + spi0_pins: pinmux_spi0_pins { + pinctrl-single,bits = < + /* SIMO, SOMI, CLK */ + 0xc 0x00001101 0x0000ff0f + >; + }; + spi0_cs0_pin: pinmux_spi0_cs0 { + pinctrl-single,bits = < + /* CS0 */ + 0x10 0x00000010 0x000000f0 + >; + }; + spi1_pins: pinmux_spi1_pins { pinctrl-single,bits = < /* SIMO, SOMI, CLK */ 0x14 0x00110100 0x00ff0f00 @@ -291,6 +303,16 @@ reg = <0x308000 0x80>; status = "disabled"; }; + spi0: spi@41000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ti,da830-spi"; + reg = <0x41000 0x1000>; + num-cs = <6>; + ti,davinci-spi-intr-line = <1>; + interrupts = <20>; + status = "disabled"; + }; spi1: spi@30e000 { #address-cells = <1>; #size-cells = <0>; -- GitLab From 801a6aa9aabf5d8e1323dd8bbb748589e4706d44 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 16 Apr 2016 12:00:18 -0500 Subject: [PATCH 4162/9938] ARM: davinci: da8xx-dt: Add spi0 lookup for clock matching Add AUXDATA needed to match the device-tree node for spi0 to the non-device-tree clock. Signed-off-by: David Lechner Tested-by: Kevin Hilman [nsekhar@ti.com: commit description updates] Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da8xx-dt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index 880b94e64816..0ba3dc9963d4 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -40,6 +40,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("ti,da850-ecap", 0x01f06000, "ecap", NULL), OF_DEV_AUXDATA("ti,da850-ecap", 0x01f07000, "ecap", NULL), OF_DEV_AUXDATA("ti,da850-ecap", 0x01f08000, "ecap", NULL), + OF_DEV_AUXDATA("ti,da830-spi", 0x01c41000, "spi_davinci.0", NULL), OF_DEV_AUXDATA("ti,da830-spi", 0x01f0e000, "spi_davinci.1", NULL), OF_DEV_AUXDATA("ns16550a", 0x01c42000, "serial8250.0", NULL), OF_DEV_AUXDATA("ns16550a", 0x01d0c000, "serial8250.1", NULL), -- GitLab From 5209a8f19e9aa9aac26c4f53c868a13005dd2444 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 16 Apr 2016 12:00:19 -0500 Subject: [PATCH 4163/9938] ARM: dts: da850: disable mdio and eth0 in da850.dtsi Disable mdio and eth0 in da850.dtsi file. All other devices are disabled by default and not all boards will use these devices, so these should be disabled too. da850-evm.dtb already had status = "okay" for these devices. da850-enbw-cmc.dts did not, so they were added. Signed-off-by: David Lechner Tested-by: Kevin Hilman [nsekhar@ti.com: commit description updates] Signed-off-by: Sekhar Nori --- arch/arm/boot/dts/da850-enbw-cmc.dts | 6 ++++++ arch/arm/boot/dts/da850.dtsi | 2 ++ 2 files changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/da850-enbw-cmc.dts b/arch/arm/boot/dts/da850-enbw-cmc.dts index 101d1a16b0ac..14dff3e188ed 100644 --- a/arch/arm/boot/dts/da850-enbw-cmc.dts +++ b/arch/arm/boot/dts/da850-enbw-cmc.dts @@ -26,6 +26,12 @@ serial2: serial@10d000 { status = "okay"; }; + mdio: mdio@224000 { + status = "okay"; + }; + eth0: ethernet@220000 { + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index 8880d577b931..26fc081236eb 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -330,6 +330,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x224000 0x1000>; + status = "disabled"; }; eth0: ethernet@220000 { compatible = "ti,davinci-dm6467-emac"; @@ -344,6 +345,7 @@ 35 36 >; + status = "disabled"; }; gpio: gpio@226000 { compatible = "ti,dm6441-gpio"; -- GitLab From c6d3b5dd8e6fd802a354590314df28d6024906d8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 16 Apr 2016 12:00:20 -0500 Subject: [PATCH 4164/9938] ARM: dts: da850: There are 101 interrupts. Fix off by one error in da850 device tree in the number of INTC interrupts. Signed-off-by: David Lechner Tested-by: Kevin Hilman [nsekhar@ti.com: commit message update] Signed-off-by: Sekhar Nori --- arch/arm/boot/dts/da850.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index 26fc081236eb..cf1aad8190f1 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -19,7 +19,7 @@ compatible = "ti,cp-intc"; interrupt-controller; #interrupt-cells = <1>; - ti,intc-size = <100>; + ti,intc-size = <101>; reg = <0xfffee000 0x2000>; }; }; -- GitLab From e701001e7cbe88cdc937037f6f398669eef7e7ff Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 12 Apr 2016 23:50:37 +0200 Subject: [PATCH 4165/9938] netfilter: nft_rbtree: allow adjacent intervals with dynamic updates This patch fixes dynamic element updates for adjacent intervals in the rb-tree representation. Since elements are sorted in the rb-tree, in case of adjacent nodes with the same key, the assumption is that an interval end node must be placed before an interval opening. In tree lookup operations, the idea is to search for the closer element that is smaller than the one we're searching for. Given that we'll have two possible matchings, we have to take the opening interval in case of adjacent nodes. Range merges are not trivial with the current representation, specifically we have to check if node extensions are equal and make sure we keep the existing internal states around. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_rbtree.c | 40 +++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index 29f2ab88d787..f762094af7c1 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c @@ -35,6 +35,12 @@ static bool nft_rbtree_interval_end(const struct nft_rbtree_elem *rbe) (*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END); } +static bool nft_rbtree_equal(const struct nft_set *set, const void *this, + const struct nft_rbtree_elem *interval) +{ + return memcmp(this, nft_set_ext_key(&interval->ext), set->klen) == 0; +} + static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key, const struct nft_set_ext **ext) { @@ -42,6 +48,7 @@ static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key, const struct nft_rbtree_elem *rbe, *interval = NULL; const struct rb_node *parent; u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); + const void *this; int d; spin_lock_bh(&nft_rbtree_lock); @@ -49,9 +56,16 @@ static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key, while (parent != NULL) { rbe = rb_entry(parent, struct nft_rbtree_elem, node); - d = memcmp(nft_set_ext_key(&rbe->ext), key, set->klen); + this = nft_set_ext_key(&rbe->ext); + d = memcmp(this, key, set->klen); if (d < 0) { parent = parent->rb_left; + /* In case of adjacent ranges, we always see the high + * part of the range in first place, before the low one. + * So don't update interval if the keys are equal. + */ + if (interval && nft_rbtree_equal(set, this, interval)) + continue; interval = rbe; } else if (d > 0) parent = parent->rb_right; @@ -101,9 +115,16 @@ static int __nft_rbtree_insert(const struct nft_set *set, else if (d > 0) p = &parent->rb_right; else { - if (nft_set_elem_active(&rbe->ext, genmask)) - return -EEXIST; - p = &parent->rb_left; + if (nft_set_elem_active(&rbe->ext, genmask)) { + if (nft_rbtree_interval_end(rbe) && + !nft_rbtree_interval_end(new)) + p = &parent->rb_left; + else if (!nft_rbtree_interval_end(rbe) && + nft_rbtree_interval_end(new)) + p = &parent->rb_right; + else + return -EEXIST; + } } } rb_link_node(&new->node, parent, p); @@ -148,7 +169,7 @@ static void *nft_rbtree_deactivate(const struct nft_set *set, { const struct nft_rbtree *priv = nft_set_priv(set); const struct rb_node *parent = priv->root.rb_node; - struct nft_rbtree_elem *rbe; + struct nft_rbtree_elem *rbe, *this = elem->priv; u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); int d; @@ -166,6 +187,15 @@ static void *nft_rbtree_deactivate(const struct nft_set *set, parent = parent->rb_left; continue; } + if (nft_rbtree_interval_end(rbe) && + !nft_rbtree_interval_end(this)) { + parent = parent->rb_left; + continue; + } else if (!nft_rbtree_interval_end(rbe) && + nft_rbtree_interval_end(this)) { + parent = parent->rb_right; + continue; + } nft_set_elem_change_active(set, &rbe->ext); return rbe; } -- GitLab From 3bb398d925ec73e42b778cf823c8f4aecae359ea Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 14 Apr 2016 17:13:41 +0200 Subject: [PATCH 4166/9938] netfilter: nf_ct_helper: disable automatic helper assignment Four years ago we introduced a new sysctl knob to disable automatic helper assignment in 72110dfaa907 ("netfilter: nf_ct_helper: disable automatic helper assignment"). This knob kept this behaviour enabled by default to remain conservative. This measure was introduced to provide a secure way to configure iptables and connection tracking helpers through explicit rules. Give the time we have waited for this, let's turn off this by default now, worse case users still have a chance to recover the former behaviour by explicitly enabling this back through sysctl. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 3b40ec575cd5..498bf74f154d 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -38,10 +38,10 @@ unsigned int nf_ct_helper_hsize __read_mostly; EXPORT_SYMBOL_GPL(nf_ct_helper_hsize); static unsigned int nf_ct_helper_count __read_mostly; -static bool nf_ct_auto_assign_helper __read_mostly = true; +static bool nf_ct_auto_assign_helper __read_mostly = false; module_param_named(nf_conntrack_helper, nf_ct_auto_assign_helper, bool, 0644); MODULE_PARM_DESC(nf_conntrack_helper, - "Enable automatic conntrack helper assignment (default 1)"); + "Enable automatic conntrack helper assignment (default 0)"); #ifdef CONFIG_SYSCTL static struct ctl_table helper_sysctl_table[] = { -- GitLab From d2b484b577776f3c6f4d52505b27bad27ea1fe00 Mon Sep 17 00:00:00 2001 From: Liping Zhang Date: Fri, 22 Apr 2016 02:56:57 -0700 Subject: [PATCH 4167/9938] netfilter: ip6t_SYNPROXY: unnecessary to check whether ip6_route_output returns NULL ip6_route_output() will never return a NULL pointer, so there's no need to check it. Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/ip6t_SYNPROXY.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index 5d778dd11f66..06bed74cf5ee 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c @@ -60,7 +60,7 @@ synproxy_send_tcp(struct net *net, fl6.fl6_dport = nth->dest; security_skb_classify_flow((struct sk_buff *)skb, flowi6_to_flowi(&fl6)); dst = ip6_route_output(net, NULL, &fl6); - if (dst == NULL || dst->error) { + if (dst->error) { dst_release(dst); goto free_nskb; } -- GitLab From 2366b80f9122ab5100ad738f726a3c7539c1d1df Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 17:32:15 +0200 Subject: [PATCH 4168/9938] misc: sram: DT spelling s/#adress-cells/#address-cells/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/sram/sram.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sram/sram.txt b/Documentation/devicetree/bindings/sram/sram.txt index 227e3a341af1..add48f09015e 100644 --- a/Documentation/devicetree/bindings/sram/sram.txt +++ b/Documentation/devicetree/bindings/sram/sram.txt @@ -51,7 +51,7 @@ sram: sram@5c000000 { compatible = "mmio-sram"; reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */ - #adress-cells = <1>; + #address-cells = <1>; #size-cells = <1>; ranges = <0 0x5c000000 0x40000>; -- GitLab From 332bea1a26b90ccbe34a6fd3ce2baddabad9fdb3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 17:32:16 +0200 Subject: [PATCH 4169/9938] PCI: hisi: DT spelling s/interrupts-*/interrupt-*/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- .../devicetree/bindings/pci/hisilicon-pcie.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt index b721beacfe4d..59c2f47aa303 100644 --- a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt +++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt @@ -34,11 +34,11 @@ Hip05 Example (note that Hip06 is the same except compatible): ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>; num-lanes = <8>; port-id = <1>; - #interrupts-cells = <1>; - interrupts-map-mask = <0xf800 0 0 7>; - interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10 - 0x0 0 0 2 &mbigen_pcie 2 11 - 0x0 0 0 3 &mbigen_pcie 3 12 - 0x0 0 0 4 &mbigen_pcie 4 13>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xf800 0 0 7>; + interrupt-map = <0x0 0 0 1 &mbigen_pcie 1 10 + 0x0 0 0 2 &mbigen_pcie 2 11 + 0x0 0 0 3 &mbigen_pcie 3 12 + 0x0 0 0 4 &mbigen_pcie 4 13>; status = "ok"; }; -- GitLab From 109a553d7553997efd69be60818c1a79a6cb172c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 17:32:17 +0200 Subject: [PATCH 4170/9938] phy: phy-stih41x-usb: DT spelling s/#phy-cell/#phy-cells/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt b/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt index 00944a05ee6b..744b4809542e 100644 --- a/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt +++ b/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt @@ -17,7 +17,7 @@ Example: usb2_phy: usb2phy@0 { compatible = "st,stih416-usb-phy"; - #phy-cell = <0>; + #phy-cells = <0>; st,syscfg = <&syscfg_rear>; clocks = <&clk_sysin>; clock-names = "osc_phy"; -- GitLab From 3b56727105a2605240a62acfc4033ee12fb938d8 Mon Sep 17 00:00:00 2001 From: "Dr. H. Nikolaus Schaller" Date: Thu, 21 Apr 2016 18:03:15 +0200 Subject: [PATCH 4171/9938] Documentation: bindings: fix palmas-rtc documentation change 100mA -> 100uA Signed-off-by: H. Nikolaus Schaller Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/rtc/rtc-palmas.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/rtc/rtc-palmas.txt b/Documentation/devicetree/bindings/rtc/rtc-palmas.txt index adbccc0a51e1..eb1c7fdeb413 100644 --- a/Documentation/devicetree/bindings/rtc/rtc-palmas.txt +++ b/Documentation/devicetree/bindings/rtc/rtc-palmas.txt @@ -15,9 +15,9 @@ Optional properties: battery is chargeable or not. If charging battery then driver can enable the charging. - ti,backup-battery-charge-high-current: Enable high current charging in - backup battery. Device supports the < 100mA and > 100mA charging. - The high current will be > 100mA. Absence of this property will - charge battery to lower current i.e. < 100mA. + backup battery. Device supports the < 100uA and > 100uA charging. + The high current will be > 100uA. Absence of this property will + charge battery to lower current i.e. < 100uA. Example: palmas: tps65913@58 { -- GitLab From 8b4958573f8215ca052b2c084100ebbcd28be904 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 22 Apr 2016 17:29:16 +0200 Subject: [PATCH 4172/9938] serial: Move Marvell UART DT bindings to correct location All other UART DT binding documentation is under Documentation/devicetree/bindings/serial/. Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/{tty => }/serial/mvebu-uart.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/{tty => }/serial/mvebu-uart.txt (100%) diff --git a/Documentation/devicetree/bindings/tty/serial/mvebu-uart.txt b/Documentation/devicetree/bindings/serial/mvebu-uart.txt similarity index 100% rename from Documentation/devicetree/bindings/tty/serial/mvebu-uart.txt rename to Documentation/devicetree/bindings/serial/mvebu-uart.txt -- GitLab From d6cf8337c5b536eaa86068f14f6eef4f904e2218 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:05 +0100 Subject: [PATCH 4173/9938] Documentation: dt: arm: fix spelling mistakes Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/arm/cci.txt | 2 +- Documentation/devicetree/bindings/arm/spear-misc.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt index a1a5a7ecc2fb..0f2153e8fa7e 100644 --- a/Documentation/devicetree/bindings/arm/cci.txt +++ b/Documentation/devicetree/bindings/arm/cci.txt @@ -100,7 +100,7 @@ specific to ARM. "arm,cci-400-pmu,r0" "arm,cci-400-pmu,r1" "arm,cci-400-pmu" - DEPRECATED, permitted only where OS has - secure acces to CCI registers + secure access to CCI registers "arm,cci-500-pmu,r0" "arm,cci-550-pmu,r0" - reg: diff --git a/Documentation/devicetree/bindings/arm/spear-misc.txt b/Documentation/devicetree/bindings/arm/spear-misc.txt index cf649827ffcd..e404e2556b4a 100644 --- a/Documentation/devicetree/bindings/arm/spear-misc.txt +++ b/Documentation/devicetree/bindings/arm/spear-misc.txt @@ -6,4 +6,4 @@ few properties of different peripheral controllers. misc node required properties: - compatible Should be "st,spear1340-misc", "syscon". -- reg: Address range of misc space upto 8K +- reg: Address range of misc space up to 8K -- GitLab From d7fb8300d732a999c034ef4707d150d5579c27a8 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:06 +0100 Subject: [PATCH 4174/9938] Documentation: dt: clock: fix spelling mistakes Signed-off-by: Eric Engestrom Reviewed-by: Heiko Stuebner [robh: s/describe/described/] Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt | 2 +- Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt | 2 +- Documentation/devicetree/bindings/clock/st/st,clkgen.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt index 0c2bf5eba43e..7f368530a2e4 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt @@ -16,7 +16,7 @@ Required Properties: Optional Properties: - rockchip,grf: phandle to the syscon managing the "general register files" - If missing pll rates are not changable, due to the missing pll lock status. + If missing pll rates are not changeable, due to the missing pll lock status. Each clock is assigned an identifier and client nodes can use this identifier to specify the clock which they consume. All available clocks are defined as diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt index c9fbb76573e1..8cb47c39ba53 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt @@ -15,7 +15,7 @@ Required Properties: Optional Properties: - rockchip,grf: phandle to the syscon managing the "general register files" - If missing pll rates are not changable, due to the missing pll lock status. + If missing pll rates are not changeable, due to the missing pll lock status. Each clock is assigned an identifier and client nodes can use this identifier to specify the clock which they consume. All available clocks are defined as diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt index 78978f1f5158..b18bf86f926f 100644 --- a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt @@ -40,7 +40,7 @@ address is common of all subnode. }; This binding uses the common clock binding[1]. -Each subnode should use the binding discribe in [2]..[7] +Each subnode should use the binding described in [2]..[7] [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt -- GitLab From bfcfb84a4d7988d28e81638d7fbd2e26c02f44ce Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:07 +0100 Subject: [PATCH 4175/9938] Documentation: dt: display: fix spelling mistake Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- .../devicetree/bindings/display/exynos/exynos_dsim.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt index 22756b3dede2..a78265993665 100644 --- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt +++ b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt @@ -41,7 +41,7 @@ Video interfaces: endpoint node connected from mic node (reg = 0): - remote-endpoint: specifies the endpoint in mic node. This node is required for Exynos5433 mipi dsi. So mic can access to panel node - thoughout this dsi node. + throughout this dsi node. endpoint node connected to panel node (reg = 1): - remote-endpoint: specifies the endpoint in panel node. This node is required in all kinds of exynos mipi dsi to represent -- GitLab From 30729ab58609dbb727c33d504652955dfd0ac3f2 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:08 +0100 Subject: [PATCH 4176/9938] Documentation: dt: dma: fix spelling mistake Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt index 2291c4098730..3cf0072d3141 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt @@ -7,7 +7,7 @@ Required properties: - compatible: Should be "xlnx,axi-dma-1.00.a" - #dma-cells: Should be <1>, see "dmas" property below - reg: Should contain DMA registers location and length. -- dma-channel child node: Should have atleast one channel and can have upto +- dma-channel child node: Should have at least one channel and can have up to two channels per device. This node specifies the properties of each DMA channel (see child node properties below). -- GitLab From 25da0af697aa9b9e683bb94b10ffe6c994b06f4c Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:09 +0100 Subject: [PATCH 4177/9938] Documentation: dt: input: fix spelling mistakes Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/input/ads7846.txt | 2 +- .../devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/input/ads7846.txt b/Documentation/devicetree/bindings/input/ads7846.txt index c6cfe2e3ed41..9fc47b006fd1 100644 --- a/Documentation/devicetree/bindings/input/ads7846.txt +++ b/Documentation/devicetree/bindings/input/ads7846.txt @@ -29,7 +29,7 @@ Optional properties: ti,vref-delay-usecs vref supply delay in usecs, 0 for external vref (u16). ti,vref-mv The VREF voltage, in millivolts (u16). - Set to 0 to use internal refernce + Set to 0 to use internal references (ADS7846). ti,keep-vref-on set to keep vref on for differential measurements as well diff --git a/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt index cdf05f9b2329..abfcab3edc66 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt @@ -15,7 +15,7 @@ Optional properties: - fsl,pen-debounce-ns: Pen debounce time in nanoseconds. - fsl,pen-threshold: Pen-down threshold for the touchscreen. This is a value between 1 and 4096. It is the ratio between the internal reference voltage - and the measured voltage after the plate was precharged. Resistence between + and the measured voltage after the plate was precharged. Resistance between plates and therefore the voltage decreases with pressure so that a smaller value is equivalent to a higher pressure. - fsl,settling-time-ns: Settling time in nanoseconds. The settling time is before -- GitLab From 8f97c2814b5448d91a3c67081f7d978c097feabe Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:10 +0100 Subject: [PATCH 4178/9938] Documentation: dt: interrupt-controller: fix spelling mistakes Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- .../bindings/interrupt-controller/ti,omap4-wugen-mpu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu index 43effa0a4fe7..18d4f407bf0e 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu @@ -4,7 +4,7 @@ All TI OMAP4/5 (and their derivatives) an interrupt controller that routes interrupts to the GIC, and also serves as a wakeup source. It is also referred to as "WUGEN-MPU", hence the name of the binding. -Reguired properties: +Required properties: - compatible : should contain at least "ti,omap4-wugen-mpu" or "ti,omap5-wugen-mpu" @@ -20,7 +20,7 @@ Notes: - Because this HW ultimately routes interrupts to the GIC, the interrupt specifier must be that of the GIC. - Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs - are explicitly forbiden. + are explicitly forbidden. Example: -- GitLab From 70e044ba1e1bafbe28adf54beab6059690bdc90a Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:11 +0100 Subject: [PATCH 4179/9938] Documentation: dt: media: fix spelling mistake Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/media/xilinx/video.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/xilinx/video.txt b/Documentation/devicetree/bindings/media/xilinx/video.txt index cbd46fa0988f..68ac210e688e 100644 --- a/Documentation/devicetree/bindings/media/xilinx/video.txt +++ b/Documentation/devicetree/bindings/media/xilinx/video.txt @@ -20,7 +20,7 @@ The following properties are common to all Xilinx video IP cores. - xlnx,video-format: This property represents a video format transmitted on an AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream Video IP and System Design Guide" [UG934]. How the format relates to the IP - core is decribed in the IP core bindings documentation. + core is described in the IP core bindings documentation. - xlnx,video-width: This property qualifies the video format with the sample width expressed as a number of bits per pixel component. All components must -- GitLab From dc5b5140af500e9a8f022fede6bab5823cb7f43e Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:12 +0100 Subject: [PATCH 4180/9938] Documentation: dt: mfd: fix spelling mistakes Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mfd/qcom-rpm.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt index 5e97a9593ad7..b98b291a31ba 100644 --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt @@ -178,7 +178,7 @@ see regulator.txt - with additional custom properties described below: - qcom,force-mode: Usage: optional (default if no other qcom,force-mode is specified) Value type: - Defintion: indicates that the regulator should be forced to a + Definition: indicates that the regulator should be forced to a particular mode, valid values are: QCOM_RPM_FORCE_MODE_NONE - do not force any mode QCOM_RPM_FORCE_MODE_LPM - force into low power mode @@ -204,7 +204,7 @@ see regulator.txt - with additional custom properties described below: - qcom,force-mode: Usage: optional Value type: - Defintion: indicates that the regulator should not be forced to any + Definition: indicates that the regulator should not be forced to any particular mode, valid values are: QCOM_RPM_FORCE_MODE_NONE - do not force any mode QCOM_RPM_FORCE_MODE_LPM - force into low power mode -- GitLab From c312c2ec866e319a49249b0597f53c5271c7cb3e Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:13 +0100 Subject: [PATCH 4181/9938] Documentation: dt: mmc: fix spelling mistake Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt index 0cb827bf9435..3d965d57e00b 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt @@ -1,7 +1,7 @@ * The simple eMMC hardware reset provider The purpose of this driver is to perform standard eMMC hw reset -procedure, as descibed by Jedec 4.4 specification. This procedure is +procedure, as described by Jedec 4.4 specification. This procedure is performed just after MMC core enabled power to the given mmc host (to fix possible issues if bootloader has left eMMC card in initialized or unknown state), and before performing complete system reboot (also in -- GitLab From c7292b471bc9198f865d7bed56996648208e60c6 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:14 +0100 Subject: [PATCH 4182/9938] Documentation: dt: mtd: fix spelling mistake Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt index c2546ced9c02..0f6985b5de49 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt @@ -52,7 +52,7 @@ Optional properties: v7.0. Use this property to describe the rare earlier versions of this core that include WP - -- Additonal SoC-specific NAND controller properties -- + -- Additional SoC-specific NAND controller properties -- The NAND controller is integrated differently on the variety of SoCs on which it is found. Part of this integration involves providing status and enable bits -- GitLab From dd346f2728bc2fc4121288d5dbe8ed58f4d6005e Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:15 +0100 Subject: [PATCH 4183/9938] Documentation: dt: net: fix spelling mistakes Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt | 2 +- Documentation/devicetree/bindings/net/stmmac.txt | 4 ++-- Documentation/devicetree/bindings/net/ti,dp83867.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt index e6a9d1c30878..e911a635ce6e 100644 --- a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt +++ b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt @@ -8,7 +8,7 @@ Required properties: specifies a reference to the associating hardware driver node. see Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt - port-id: is the index of port provided by DSAF (the accelerator). DSAF can - connect to 8 PHYs. Port 0 to 1 are both used for adminstration purpose. They + connect to 8 PHYs. Port 0 to 1 are both used for administration purpose. They are called debug ports. The remaining 6 PHYs are taken according to the mode of DSAF. diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt index 6605d19601c2..9651dfdced44 100644 --- a/Documentation/devicetree/bindings/net/stmmac.txt +++ b/Documentation/devicetree/bindings/net/stmmac.txt @@ -51,8 +51,8 @@ Optional properties: AXI register inside the DMA module: - snps,lpi_en: enable Low Power Interface - snps,xit_frm: unlock on WoL - - snps,wr_osr_lmt: max write oustanding req. limit - - snps,rd_osr_lmt: max read oustanding req. limit + - snps,wr_osr_lmt: max write outstanding req. limit + - snps,rd_osr_lmt: max read outstanding req. limit - snps,kbbe: do not cross 1KiB boundary. - snps,axi_all: align address - snps,blen: this is a vector of supported burst length. diff --git a/Documentation/devicetree/bindings/net/ti,dp83867.txt b/Documentation/devicetree/bindings/net/ti,dp83867.txt index 58d935b58598..5d21141a68b5 100644 --- a/Documentation/devicetree/bindings/net/ti,dp83867.txt +++ b/Documentation/devicetree/bindings/net/ti,dp83867.txt @@ -2,7 +2,7 @@ Required properties: - reg - The ID number for the phy, usually a small integer - - ti,rx-internal-delay - RGMII Recieve Clock Delay - see dt-bindings/net/ti-dp83867.h + - ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h for applicable values - ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h for applicable values -- GitLab From baec7f1f5a67f4879a215d466f7b088aff9823d5 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:16 +0100 Subject: [PATCH 4184/9938] Documentation: dt: opp: fix spelling mistake Signed-off-by: Eric Engestrom Acked-by: Viresh Kumar Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/opp/opp.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt index 601256fe8c0d..ee91cbdd95ee 100644 --- a/Documentation/devicetree/bindings/opp/opp.txt +++ b/Documentation/devicetree/bindings/opp/opp.txt @@ -45,7 +45,7 @@ Devices supporting OPPs must set their "operating-points-v2" property with phandle to a OPP table in their DT node. The OPP core will use this phandle to find the operating points for the device. -If required, this can be extended for SoC vendor specfic bindings. Such bindings +If required, this can be extended for SoC vendor specific bindings. Such bindings should be documented as Documentation/devicetree/bindings/power/-opp.txt and should have a compatible description like: "operating-points-v2-". -- GitLab From 4e99a3bd49e4701f81ad0fd7c0ca3b67c6b0fc8b Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:17 +0100 Subject: [PATCH 4185/9938] Documentation: dt: pinctrl: fix spelling mistake Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt index a90c812ad642..a54c39ebbf8b 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt @@ -122,7 +122,7 @@ to specify in a pin configuration subnode: 2: 1.5uA (PMIC_GPIO_PULL_UP_1P5) 3: 31.5uA (PMIC_GPIO_PULL_UP_31P5) 4: 1.5uA + 30uA boost (PMIC_GPIO_PULL_UP_1P5_30) - If this property is ommited 30uA strength will be used if + If this property is omitted 30uA strength will be used if pull up is selected - bias-high-impedance: -- GitLab From b7f97b3a21582c88a9bc441db0bd9ad6cc2c0e37 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:18 +0100 Subject: [PATCH 4186/9938] Documentation: dt: power: fix spelling mistake Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- .../devicetree/bindings/power/qcom,coincell-charger.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt b/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt index 0e6d8754e7ec..747899223262 100644 --- a/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt +++ b/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt @@ -29,7 +29,7 @@ IC (PMIC) - qcom,charger-disable: Usage: optional Value type: - Definition: definining this property disables charging + Definition: defining this property disables charging This charger is a sub-node of one of the 8941 PMIC blocks, and is specified as a child node in DTS of that node. See ../mfd/qcom,spmi-pmic.txt and -- GitLab From 718756b5033f6f75562aab17601326df104527e8 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 01:24:19 +0100 Subject: [PATCH 4187/9938] Documentation: dt: soc: fix spelling mistakes Signed-off-by: Eric Engestrom Signed-off-by: Rob Herring --- .../devicetree/bindings/soc/ti/keystone-navigator-qmss.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt b/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt index d1ce21a4904d..64c66a5644e7 100644 --- a/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt +++ b/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt @@ -42,7 +42,7 @@ Required properties: - queue-pools : child node classifying the queue ranges into pools. Queue ranges are grouped into 3 type of pools: - qpend : pool of qpend(interruptible) queues - - general-purpose : pool of general queues, primarly used + - general-purpose : pool of general queues, primarily used as free descriptor queues or the transmit DMA queues. - accumulator : pool of queues on PDSP accumulator channel @@ -50,7 +50,7 @@ Required properties: -- qrange : number of queues to use per queue range, specified as <"base queue #" "# of queues">. -- interrupts : Optional property to specify the interrupt mapping - for interruptible queues. The driver additionaly sets + for interruptible queues. The driver additionally sets the interrupt affinity hint based on the cpu mask. -- qalloc-by-id : Optional property to specify that the queues in this range can only be allocated by queue id. @@ -80,7 +80,7 @@ Required properties: latency : time to delay the interrupt, specified in microseconds. -- multi-queue : Optional property to specify that the channel has to - monitor upto 32 queues starting at the base queue #. + monitor up to 32 queues starting at the base queue #. - descriptor-regions : child node describing the memory regions for keystone navigator packet DMA descriptors. The memory for descriptors will be allocated by the driver. -- GitLab From bdcaa23fb87260c8314f538f444ee845ea51e15d Mon Sep 17 00:00:00 2001 From: Philippe Longepe Date: Fri, 22 Apr 2016 11:46:09 -0700 Subject: [PATCH 4188/9938] cpufreq: intel_pstate: Use average P-State instead of current P-State The result returned by pid_calc() is subtracted from current_pstate (which is the P-State requested during the last period) in order to obtain the target P-State for the current iteration. However, current_pstate may not reflect the real current P-State of the CPU. In particular, that P-State may be higher because of the frequency sharing per module. The theory is: - The load is the percentage of time spent in C0 and is related to the average P-State during the same period. - The last requested P-State can be completely different than the average P-State (because of frequency sharing or throttling). - The P-State shift computed by the pid_calc is based on the load computed at average P-State, so the shift must be relative to this average P-State. Using the average P-State instead of current P-State improves power without significant performance penalty in cases when a task migrates from one core to other core sharing frequency and voltage. Performance and power comparison with this patch on Cherry Trail platform using Android: Benchmark ?Perf ?Power FishTank 10.45% 3.1% SmartBench-Gaming -0.1% -10.4% SmartBench-Productivity -0.8% -10.4% CandyCrush n/a -17.4% AngryBirds n/a -5.9% videoPlayback n/a -13.9% audioPlayback n/a -4.9% IcyRocks-20-50 0.0% -38.4% iozone RR -0.16% -1.3% iozone RW 0.74% -1.3% Signed-off-by: Philippe Longepe Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 12ae2e602e79..cfa6a6803e0e 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1061,6 +1061,12 @@ static inline int32_t get_avg_frequency(struct cpudata *cpu) cpu->pstate.scaling, cpu->sample.mperf); } +static inline int32_t get_avg_pstate(struct cpudata *cpu) +{ + return div64_u64(cpu->pstate.max_pstate_physical * cpu->sample.aperf, + cpu->sample.mperf); +} + static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu) { struct sample *sample = &cpu->sample; @@ -1093,7 +1099,7 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu) cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc); cpu->sample.busy_scaled = cpu_load; - return cpu->pstate.current_pstate - pid_calc(&cpu->pid, cpu_load); + return get_avg_pstate(cpu) - pid_calc(&cpu->pid, cpu_load); } static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) -- GitLab From a29a1e76781d112014761ba106ab03e097cc4492 Mon Sep 17 00:00:00 2001 From: Ashwin Chaugule Date: Thu, 14 Apr 2016 20:45:53 -0400 Subject: [PATCH 4189/9938] cpufreq: ACPI / CPPC: Add module support for cppc_cpufreq driver Add a function to cleanup at module exit and export appropriate GPL string to enable moduler support for the cppc_cpufreq driver. Reported-by: Srinivas Pandruvada Signed-off-by: Ashwin Chaugule Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cppc_cpufreq.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 7c0bdfb1a2ca..8882b8e2ecd0 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -173,4 +173,25 @@ static int __init cppc_cpufreq_init(void) return -ENODEV; } +static void __exit cppc_cpufreq_exit(void) +{ + struct cpudata *cpu; + int i; + + cpufreq_unregister_driver(&cppc_cpufreq_driver); + + for_each_possible_cpu(i) { + cpu = all_cpu_data[i]; + free_cpumask_var(cpu->shared_cpu_map); + kfree(cpu); + } + + kfree(all_cpu_data); +} + +module_exit(cppc_cpufreq_exit); +MODULE_AUTHOR("Ashwin Chaugule"); +MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec"); +MODULE_LICENSE("GPL"); + late_initcall(cppc_cpufreq_init); -- GitLab From 27b8fe8daf39c8a028d377a878b1405b73f5a10f Mon Sep 17 00:00:00 2001 From: Jia Hongtao Date: Mon, 18 Apr 2016 15:59:32 +0800 Subject: [PATCH 4190/9938] cpufreq: qoriq: Don't show cooling device messages if THERMAL_OF undefined When THERMAL_OF is undefined the cooling device messages should not be shown. -ENOSYS is returned from of_cpufreq_cooling_register() when THERMAL_OF is undefined. Signed-off-by: Jia Hongtao Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/qoriq-cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index b23e525a7af3..8b7758936fcf 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c @@ -333,8 +333,8 @@ static void qoriq_cpufreq_ready(struct cpufreq_policy *policy) cpud->cdev = of_cpufreq_cooling_register(np, policy->related_cpus); - if (IS_ERR(cpud->cdev)) { - pr_err("Failed to register cooling device cpu%d: %ld\n", + if (IS_ERR(cpud->cdev) && PTR_ERR(cpud->cdev) != -ENOSYS) { + pr_err("cpu%d is not running as cooling device: %ld\n", policy->cpu, PTR_ERR(cpud->cdev)); cpud->cdev = NULL; -- GitLab From 4ba2578fa7b557012b8f59ad7a9284ff15394338 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 25 Apr 2016 15:05:24 +0100 Subject: [PATCH 4191/9938] arm64: perf: don't expose CHAIN event in sysfs The CHAIN event allows two 32-bit counters to be treated as a single 64-bit counter, under certain allocation restrictions on the PMU. Whilst userspace could theoretically create CHAIN events using the raw event syntax, we don't really want to advertise this in sysfs, since it's useless in isolation. This patch removes the event from our /sys entries. Reported-by: Mark Rutland Signed-off-by: Will Deacon --- arch/arm64/kernel/perf_event.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index ca6beb10b592..838ccf123307 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -416,7 +416,7 @@ ARMV8_EVENT_ATTR(memory_error, ARMV8_PMUV3_PERFCTR_MEMORY_ERROR); ARMV8_EVENT_ATTR(inst_spec, ARMV8_PMUV3_PERFCTR_INST_SPEC); ARMV8_EVENT_ATTR(ttbr_write_retired, ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED); ARMV8_EVENT_ATTR(bus_cycles, ARMV8_PMUV3_PERFCTR_BUS_CYCLES); -ARMV8_EVENT_ATTR(chain, ARMV8_PMUV3_PERFCTR_CHAIN); +/* Don't expose the chain event in /sys, since it's useless in isolation */ ARMV8_EVENT_ATTR(l1d_cache_allocate, ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE); ARMV8_EVENT_ATTR(l2d_cache_allocate, ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE); ARMV8_EVENT_ATTR(br_retired, ARMV8_PMUV3_PERFCTR_BR_RETIRED); @@ -467,7 +467,6 @@ static struct attribute *armv8_pmuv3_event_attrs[] = { &armv8_event_attr_inst_spec.attr.attr, &armv8_event_attr_ttbr_write_retired.attr.attr, &armv8_event_attr_bus_cycles.attr.attr, - &armv8_event_attr_chain.attr.attr, &armv8_event_attr_l1d_cache_allocate.attr.attr, &armv8_event_attr_l2d_cache_allocate.attr.attr, &armv8_event_attr_br_retired.attr.attr, -- GitLab From 495c716f177ed8fb3eb6334e4d08c409a9a0bd0f Mon Sep 17 00:00:00 2001 From: Jia Hongtao Date: Tue, 19 Apr 2016 17:00:06 +0800 Subject: [PATCH 4192/9938] cpufreq: qoriq: Remove __exit macro from .exit callback .exit callback (qoriq_cpufreq_cpu_exit()) is also used during suspend. So __exit macro should be removed or the function will be discarded. Signed-off-by: Jia Hongtao Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/qoriq-cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 8b7758936fcf..e029079ee302 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c @@ -301,7 +301,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) return -ENODEV; } -static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) +static int qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) { struct cpu_data *data = policy->driver_data; @@ -348,7 +348,7 @@ static struct cpufreq_driver qoriq_cpufreq_driver = { .name = "qoriq_cpufreq", .flags = CPUFREQ_CONST_LOOPS, .init = qoriq_cpufreq_cpu_init, - .exit = __exit_p(qoriq_cpufreq_cpu_exit), + .exit = qoriq_cpufreq_cpu_exit, .verify = cpufreq_generic_frequency_table_verify, .target_index = qoriq_cpufreq_target, .get = cpufreq_generic_get, -- GitLab From 394cb8316b44e86f64c39ee943bc9bc4f813283b Mon Sep 17 00:00:00 2001 From: Jia Hongtao Date: Tue, 19 Apr 2016 17:00:07 +0800 Subject: [PATCH 4193/9938] cpufreq: qoriq: Fix cooling device registration issue during suspend Cooling device is registered by ready callback. It's also invoked while system resuming from sleep (Enabling non-boot cpus). Thus cooling device may be multiple registered. Matchable unregistration is added to exit callback to fix this issue. Signed-off-by: Jia Hongtao Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/qoriq-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index e029079ee302..53d8c3fb16f6 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c @@ -305,6 +305,7 @@ static int qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) { struct cpu_data *data = policy->driver_data; + cpufreq_cooling_unregister(data->cdev); kfree(data->pclk); kfree(data->table); kfree(data); -- GitLab From 2d74c6d565567e72c6ea303a452473c8fa7141e4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 21 Apr 2016 14:28:53 +0530 Subject: [PATCH 4194/9938] PM / OPP: Propagate the error returned by _find_opp_table() Don't send -EINVAL and propagate what's received from _find_opp_table(). Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c index ba2bdbd932ef..b7411a3cdcb1 100644 --- a/drivers/base/power/opp/cpu.c +++ b/drivers/base/power/opp/cpu.c @@ -131,7 +131,7 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) opp_table = _find_opp_table(cpu_dev); if (IS_ERR(opp_table)) { - ret = -EINVAL; + ret = PTR_ERR(opp_table); goto unlock; } -- GitLab From 45ca36ad7cd5784c6326504a8f54df4cccaa8852 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 21 Apr 2016 14:28:54 +0530 Subject: [PATCH 4195/9938] PM / OPP: Add missing doc style comments Few of the routines in cpu.c were missing these, add them. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/cpu.c | 59 +++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c index b7411a3cdcb1..b151401d1513 100644 --- a/drivers/base/power/opp/cpu.c +++ b/drivers/base/power/opp/cpu.c @@ -119,7 +119,22 @@ void dev_pm_opp_free_cpufreq_table(struct device *dev, EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table); #endif /* CONFIG_CPU_FREQ */ -/* Required only for V1 bindings, as v2 can manage it from DT itself */ +/** + * dev_pm_opp_set_sharing_cpus() - Mark OPP table as shared by few CPUs + * @cpu_dev: CPU device for which we do this operation + * @cpumask: cpumask of the CPUs which share the OPP table with @cpu_dev + * + * This marks OPP table of the @cpu_dev as shared by the CPUs present in + * @cpumask. + * + * Returns -ENODEV if OPP table isn't already present. + * + * Locking: The internal opp_table and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) { struct opp_device *opp_dev; @@ -161,6 +176,18 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); #ifdef CONFIG_OF +/** + * dev_pm_opp_of_cpumask_remove_table() - Removes OPP table for @cpumask + * @cpumask: cpumask for which OPP table needs to be removed + * + * This removes the OPP tables for CPUs present in the @cpumask. + * + * Locking: The internal opp_table and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask) { struct device *cpu_dev; @@ -181,6 +208,18 @@ void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask) } EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_remove_table); +/** + * dev_pm_opp_of_cpumask_add_table() - Adds OPP table for @cpumask + * @cpumask: cpumask for which OPP table needs to be added. + * + * This adds the OPP tables for CPUs present in the @cpumask. + * + * Locking: The internal opp_table and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ int dev_pm_opp_of_cpumask_add_table(cpumask_var_t cpumask) { struct device *cpu_dev; @@ -216,6 +255,24 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table); * * Returns -ENOENT if operating-points-v2 bindings aren't supported. */ +/** + * dev_pm_opp_of_get_sharing_cpus() - Get cpumask of CPUs sharing OPPs with + * @cpu_dev using operating-points-v2 + * bindings. + * + * @cpu_dev: CPU device for which we do this operation + * @cpumask: cpumask to update with information of sharing CPUs + * + * This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev. + * + * Returns -ENOENT if operating-points-v2 isn't present for @cpu_dev. + * + * Locking: The internal opp_table and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) { struct device_node *np, *tmp_np; -- GitLab From 642aa8cee7b84eee1dc4897e301611cffa6d5775 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 21 Apr 2016 14:28:55 +0530 Subject: [PATCH 4196/9938] PM / OPP: dev_pm_opp_set_sharing_cpus() doesn't depend on CONFIG_OF dev_pm_opp_set_sharing_cpus() doesn't do any DT specific stuff and its declarations are added within the CONFIG_OF ifdef by mistake. Take them out of that. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- include/linux/pm_opp.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index cccaf4a29e9f..5b6ad31403a5 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -65,6 +65,7 @@ void dev_pm_opp_put_prop_name(struct device *dev); int dev_pm_opp_set_regulator(struct device *dev, const char *name); void dev_pm_opp_put_regulator(struct device *dev); int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); +int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask); #else static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) { @@ -178,6 +179,11 @@ static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_f return -EINVAL; } +static inline int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) +{ + return -ENOSYS; +} + #endif /* CONFIG_PM_OPP */ #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF) @@ -186,7 +192,6 @@ void dev_pm_opp_of_remove_table(struct device *dev); int dev_pm_opp_of_cpumask_add_table(cpumask_var_t cpumask); void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask); int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask); -int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask); #else static inline int dev_pm_opp_of_add_table(struct device *dev) { @@ -210,11 +215,6 @@ static inline int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask { return -ENOSYS; } - -static inline int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) -{ - return -ENOSYS; -} #endif #endif /* __LINUX_OPP_H__ */ -- GitLab From 2c93104ff2d678b22bb8d5ca502ac5df21a68f69 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 21 Apr 2016 14:28:56 +0530 Subject: [PATCH 4197/9938] PM / OPP: Relocate dev_pm_opp_set_sharing_cpus() Move dev_pm_opp_set_sharing_cpus() towards the end of the file. This is required for better readability after the next patch is applied, which adds dev_pm_opp_get_sharing_cpus(). Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/cpu.c | 112 +++++++++++++++++------------------ 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c index b151401d1513..491e8684bd5f 100644 --- a/drivers/base/power/opp/cpu.c +++ b/drivers/base/power/opp/cpu.c @@ -119,62 +119,6 @@ void dev_pm_opp_free_cpufreq_table(struct device *dev, EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table); #endif /* CONFIG_CPU_FREQ */ -/** - * dev_pm_opp_set_sharing_cpus() - Mark OPP table as shared by few CPUs - * @cpu_dev: CPU device for which we do this operation - * @cpumask: cpumask of the CPUs which share the OPP table with @cpu_dev - * - * This marks OPP table of the @cpu_dev as shared by the CPUs present in - * @cpumask. - * - * Returns -ENODEV if OPP table isn't already present. - * - * Locking: The internal opp_table and opp structures are RCU protected. - * Hence this function internally uses RCU updater strategy with mutex locks - * to keep the integrity of the internal data structures. Callers should ensure - * that this function is *NOT* called under RCU protection or in contexts where - * mutex cannot be locked. - */ -int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) -{ - struct opp_device *opp_dev; - struct opp_table *opp_table; - struct device *dev; - int cpu, ret = 0; - - mutex_lock(&opp_table_lock); - - opp_table = _find_opp_table(cpu_dev); - if (IS_ERR(opp_table)) { - ret = PTR_ERR(opp_table); - goto unlock; - } - - for_each_cpu(cpu, cpumask) { - if (cpu == cpu_dev->id) - continue; - - dev = get_cpu_device(cpu); - if (!dev) { - dev_err(cpu_dev, "%s: failed to get cpu%d device\n", - __func__, cpu); - continue; - } - - opp_dev = _add_opp_dev(dev, opp_table); - if (!opp_dev) { - dev_err(dev, "%s: failed to add opp-dev for cpu%d device\n", - __func__, cpu); - continue; - } - } -unlock: - mutex_unlock(&opp_table_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); - #ifdef CONFIG_OF /** * dev_pm_opp_of_cpumask_remove_table() - Removes OPP table for @cpumask @@ -326,3 +270,59 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask } EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus); #endif + +/** + * dev_pm_opp_set_sharing_cpus() - Mark OPP table as shared by few CPUs + * @cpu_dev: CPU device for which we do this operation + * @cpumask: cpumask of the CPUs which share the OPP table with @cpu_dev + * + * This marks OPP table of the @cpu_dev as shared by the CPUs present in + * @cpumask. + * + * Returns -ENODEV if OPP table isn't already present. + * + * Locking: The internal opp_table and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ +int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) +{ + struct opp_device *opp_dev; + struct opp_table *opp_table; + struct device *dev; + int cpu, ret = 0; + + mutex_lock(&opp_table_lock); + + opp_table = _find_opp_table(cpu_dev); + if (IS_ERR(opp_table)) { + ret = PTR_ERR(opp_table); + goto unlock; + } + + for_each_cpu(cpu, cpumask) { + if (cpu == cpu_dev->id) + continue; + + dev = get_cpu_device(cpu); + if (!dev) { + dev_err(cpu_dev, "%s: failed to get cpu%d device\n", + __func__, cpu); + continue; + } + + opp_dev = _add_opp_dev(dev, opp_table); + if (!opp_dev) { + dev_err(dev, "%s: failed to add opp-dev for cpu%d device\n", + __func__, cpu); + continue; + } + } +unlock: + mutex_unlock(&opp_table_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); -- GitLab From 46e7a4e18397649fe1b9007ad99707d960eb138e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 21 Apr 2016 14:28:57 +0530 Subject: [PATCH 4198/9938] PM / OPP: Mark shared-opp for non-dt case opp core allows OPPs to be explicitly marked as shared from platform code, in case of operating-point v1 bindings. Though we do everything fine in that case, we don't set the flag in the opp-table to indicate that the OPPs are shared. It works fine today as the flag isn't used anywhere else in the core, but we should be doing the right thing by marking it set. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/cpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c index 491e8684bd5f..55cbf9bd8707 100644 --- a/drivers/base/power/opp/cpu.c +++ b/drivers/base/power/opp/cpu.c @@ -319,6 +319,9 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) __func__, cpu); continue; } + + /* Mark opp-table as multiple CPUs are sharing it now */ + opp_table->shared_opp = true; } unlock: mutex_unlock(&opp_table_lock); -- GitLab From 92406f0cc9e3d5cc77bf3de6d68c9c2373dcd701 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Fri, 22 Apr 2016 12:25:31 +0100 Subject: [PATCH 4199/9938] arm64: cpufeature: Add scope for capability check Add scope parameter to the arm64_cpu_capabilities::matches(), so that this can be reused for checking the capability on a given CPU vs the system wide. The system uses the default scope associated with the capability for initialising the CPU_HWCAPs and ELF_HWCAPs. Cc: James Morse Cc: Marc Zyngier Cc: Andre Przywara Cc: Will Deacon Reviewed-by: Catalin Marinas Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/include/asm/cpufeature.h | 9 +- arch/arm64/kernel/cpu_errata.c | 4 +- arch/arm64/kernel/cpufeature.c | 131 +++++++++++++++------------- 3 files changed, 83 insertions(+), 61 deletions(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index ca8fb4bcfb1a..e501e4af2ebd 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -78,10 +78,17 @@ struct arm64_ftr_reg { struct arm64_ftr_bits *ftr_bits; }; +/* scope of capability check */ +enum { + SCOPE_SYSTEM, + SCOPE_LOCAL_CPU, +}; + struct arm64_cpu_capabilities { const char *desc; u16 capability; - bool (*matches)(const struct arm64_cpu_capabilities *); + int def_scope; /* default scope */ + bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope); void (*enable)(void *); /* Called on all active CPUs */ union { struct { /* To be used for erratum handling only */ diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 06afd04e02c0..2fdecd72ce58 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -22,14 +22,16 @@ #include static bool __maybe_unused -is_affected_midr_range(const struct arm64_cpu_capabilities *entry) +is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope) { + WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model, entry->midr_range_min, entry->midr_range_max); } #define MIDR_RANGE(model, min, max) \ + .def_scope = SCOPE_LOCAL_CPU, \ .matches = is_affected_midr_range, \ .midr_model = model, \ .midr_range_min = min, \ diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 8e62d61f6c42..54abd9bd5c95 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -71,7 +71,8 @@ DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); /* meta feature for alternatives */ static bool __maybe_unused -cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry); +cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused); + static struct arm64_ftr_bits ftr_id_aa64isar0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), @@ -626,6 +627,49 @@ u64 read_system_reg(u32 id) return regp->sys_val; } +/* + * __raw_read_system_reg() - Used by a STARTING cpu before cpuinfo is populated. + * Read the system register on the current CPU + */ +static u64 __raw_read_system_reg(u32 sys_id) +{ + switch (sys_id) { + case SYS_ID_PFR0_EL1: return read_cpuid(ID_PFR0_EL1); + case SYS_ID_PFR1_EL1: return read_cpuid(ID_PFR1_EL1); + case SYS_ID_DFR0_EL1: return read_cpuid(ID_DFR0_EL1); + case SYS_ID_MMFR0_EL1: return read_cpuid(ID_MMFR0_EL1); + case SYS_ID_MMFR1_EL1: return read_cpuid(ID_MMFR1_EL1); + case SYS_ID_MMFR2_EL1: return read_cpuid(ID_MMFR2_EL1); + case SYS_ID_MMFR3_EL1: return read_cpuid(ID_MMFR3_EL1); + case SYS_ID_ISAR0_EL1: return read_cpuid(ID_ISAR0_EL1); + case SYS_ID_ISAR1_EL1: return read_cpuid(ID_ISAR1_EL1); + case SYS_ID_ISAR2_EL1: return read_cpuid(ID_ISAR2_EL1); + case SYS_ID_ISAR3_EL1: return read_cpuid(ID_ISAR3_EL1); + case SYS_ID_ISAR4_EL1: return read_cpuid(ID_ISAR4_EL1); + case SYS_ID_ISAR5_EL1: return read_cpuid(ID_ISAR4_EL1); + case SYS_MVFR0_EL1: return read_cpuid(MVFR0_EL1); + case SYS_MVFR1_EL1: return read_cpuid(MVFR1_EL1); + case SYS_MVFR2_EL1: return read_cpuid(MVFR2_EL1); + + case SYS_ID_AA64PFR0_EL1: return read_cpuid(ID_AA64PFR0_EL1); + case SYS_ID_AA64PFR1_EL1: return read_cpuid(ID_AA64PFR0_EL1); + case SYS_ID_AA64DFR0_EL1: return read_cpuid(ID_AA64DFR0_EL1); + case SYS_ID_AA64DFR1_EL1: return read_cpuid(ID_AA64DFR0_EL1); + case SYS_ID_AA64MMFR0_EL1: return read_cpuid(ID_AA64MMFR0_EL1); + case SYS_ID_AA64MMFR1_EL1: return read_cpuid(ID_AA64MMFR1_EL1); + case SYS_ID_AA64MMFR2_EL1: return read_cpuid(ID_AA64MMFR2_EL1); + case SYS_ID_AA64ISAR0_EL1: return read_cpuid(ID_AA64ISAR0_EL1); + case SYS_ID_AA64ISAR1_EL1: return read_cpuid(ID_AA64ISAR1_EL1); + + case SYS_CNTFRQ_EL0: return read_cpuid(CNTFRQ_EL0); + case SYS_CTR_EL0: return read_cpuid(CTR_EL0); + case SYS_DCZID_EL0: return read_cpuid(DCZID_EL0); + default: + BUG(); + return 0; + } +} + #include static bool @@ -637,19 +681,24 @@ feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry) } static bool -has_cpuid_feature(const struct arm64_cpu_capabilities *entry) +has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope) { u64 val; - val = read_system_reg(entry->sys_reg); + WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible()); + if (scope == SCOPE_SYSTEM) + val = read_system_reg(entry->sys_reg); + else + val = __raw_read_system_reg(entry->sys_reg); + return feature_matches(val, entry); } -static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry) +static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry, int scope) { bool has_sre; - if (!has_cpuid_feature(entry)) + if (!has_cpuid_feature(entry, scope)) return false; has_sre = gic_enable_sre(); @@ -660,7 +709,7 @@ static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry) return has_sre; } -static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry) +static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int __unused) { u32 midr = read_cpuid_id(); u32 rv_min, rv_max; @@ -672,7 +721,7 @@ static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry) return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX, rv_min, rv_max); } -static bool runs_at_el2(const struct arm64_cpu_capabilities *entry) +static bool runs_at_el2(const struct arm64_cpu_capabilities *entry, int __unused) { return is_kernel_in_hyp_mode(); } @@ -681,6 +730,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { { .desc = "GIC system register CPU interface", .capability = ARM64_HAS_SYSREG_GIC_CPUIF, + .def_scope = SCOPE_SYSTEM, .matches = has_useable_gicv3_cpuif, .sys_reg = SYS_ID_AA64PFR0_EL1, .field_pos = ID_AA64PFR0_GIC_SHIFT, @@ -691,6 +741,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { { .desc = "Privileged Access Never", .capability = ARM64_HAS_PAN, + .def_scope = SCOPE_SYSTEM, .matches = has_cpuid_feature, .sys_reg = SYS_ID_AA64MMFR1_EL1, .field_pos = ID_AA64MMFR1_PAN_SHIFT, @@ -703,6 +754,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { { .desc = "LSE atomic instructions", .capability = ARM64_HAS_LSE_ATOMICS, + .def_scope = SCOPE_SYSTEM, .matches = has_cpuid_feature, .sys_reg = SYS_ID_AA64ISAR0_EL1, .field_pos = ID_AA64ISAR0_ATOMICS_SHIFT, @@ -713,12 +765,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = { { .desc = "Software prefetching using PRFM", .capability = ARM64_HAS_NO_HW_PREFETCH, + .def_scope = SCOPE_SYSTEM, .matches = has_no_hw_prefetch, }, #ifdef CONFIG_ARM64_UAO { .desc = "User Access Override", .capability = ARM64_HAS_UAO, + .def_scope = SCOPE_SYSTEM, .matches = has_cpuid_feature, .sys_reg = SYS_ID_AA64MMFR2_EL1, .field_pos = ID_AA64MMFR2_UAO_SHIFT, @@ -729,17 +783,20 @@ static const struct arm64_cpu_capabilities arm64_features[] = { #ifdef CONFIG_ARM64_PAN { .capability = ARM64_ALT_PAN_NOT_UAO, + .def_scope = SCOPE_SYSTEM, .matches = cpufeature_pan_not_uao, }, #endif /* CONFIG_ARM64_PAN */ { .desc = "Virtualization Host Extensions", .capability = ARM64_HAS_VIRT_HOST_EXTN, + .def_scope = SCOPE_SYSTEM, .matches = runs_at_el2, }, { .desc = "32-bit EL0 Support", .capability = ARM64_HAS_32BIT_EL0, + .def_scope = SCOPE_SYSTEM, .matches = has_cpuid_feature, .sys_reg = SYS_ID_AA64PFR0_EL1, .sign = FTR_UNSIGNED, @@ -752,6 +809,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { #define HWCAP_CAP(reg, field, s, min_value, type, cap) \ { \ .desc = #cap, \ + .def_scope = SCOPE_SYSTEM, \ .matches = has_cpuid_feature, \ .sys_reg = reg, \ .field_pos = field, \ @@ -834,7 +892,7 @@ static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap) static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps) { for (; hwcaps->matches; hwcaps++) - if (hwcaps->matches(hwcaps)) + if (hwcaps->matches(hwcaps, hwcaps->def_scope)) cap_set_elf_hwcap(hwcaps); } @@ -842,7 +900,7 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, const char *info) { for (; caps->matches; caps++) { - if (!caps->matches(caps)) + if (!caps->matches(caps, caps->def_scope)) continue; if (!cpus_have_cap(caps->capability) && caps->desc) @@ -878,48 +936,6 @@ static inline void set_sys_caps_initialised(void) sys_caps_initialised = true; } -/* - * __raw_read_system_reg() - Used by a STARTING cpu before cpuinfo is populated. - */ -static u64 __raw_read_system_reg(u32 sys_id) -{ - switch (sys_id) { - case SYS_ID_PFR0_EL1: return read_cpuid(ID_PFR0_EL1); - case SYS_ID_PFR1_EL1: return read_cpuid(ID_PFR1_EL1); - case SYS_ID_DFR0_EL1: return read_cpuid(ID_DFR0_EL1); - case SYS_ID_MMFR0_EL1: return read_cpuid(ID_MMFR0_EL1); - case SYS_ID_MMFR1_EL1: return read_cpuid(ID_MMFR1_EL1); - case SYS_ID_MMFR2_EL1: return read_cpuid(ID_MMFR2_EL1); - case SYS_ID_MMFR3_EL1: return read_cpuid(ID_MMFR3_EL1); - case SYS_ID_ISAR0_EL1: return read_cpuid(ID_ISAR0_EL1); - case SYS_ID_ISAR1_EL1: return read_cpuid(ID_ISAR1_EL1); - case SYS_ID_ISAR2_EL1: return read_cpuid(ID_ISAR2_EL1); - case SYS_ID_ISAR3_EL1: return read_cpuid(ID_ISAR3_EL1); - case SYS_ID_ISAR4_EL1: return read_cpuid(ID_ISAR4_EL1); - case SYS_ID_ISAR5_EL1: return read_cpuid(ID_ISAR4_EL1); - case SYS_MVFR0_EL1: return read_cpuid(MVFR0_EL1); - case SYS_MVFR1_EL1: return read_cpuid(MVFR1_EL1); - case SYS_MVFR2_EL1: return read_cpuid(MVFR2_EL1); - - case SYS_ID_AA64PFR0_EL1: return read_cpuid(ID_AA64PFR0_EL1); - case SYS_ID_AA64PFR1_EL1: return read_cpuid(ID_AA64PFR0_EL1); - case SYS_ID_AA64DFR0_EL1: return read_cpuid(ID_AA64DFR0_EL1); - case SYS_ID_AA64DFR1_EL1: return read_cpuid(ID_AA64DFR0_EL1); - case SYS_ID_AA64MMFR0_EL1: return read_cpuid(ID_AA64MMFR0_EL1); - case SYS_ID_AA64MMFR1_EL1: return read_cpuid(ID_AA64MMFR1_EL1); - case SYS_ID_AA64MMFR2_EL1: return read_cpuid(ID_AA64MMFR2_EL1); - case SYS_ID_AA64ISAR0_EL1: return read_cpuid(ID_AA64ISAR0_EL1); - case SYS_ID_AA64ISAR1_EL1: return read_cpuid(ID_AA64ISAR1_EL1); - - case SYS_CNTFRQ_EL0: return read_cpuid(CNTFRQ_EL0); - case SYS_CTR_EL0: return read_cpuid(CTR_EL0); - case SYS_DCZID_EL0: return read_cpuid(DCZID_EL0); - default: - BUG(); - return 0; - } -} - /* * Check for CPU features that are used in early boot * based on the Boot CPU value. @@ -934,28 +950,25 @@ static void verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps) { - for (; caps->matches; caps++) { - if (!cpus_have_elf_hwcap(caps)) - continue; - if (!feature_matches(__raw_read_system_reg(caps->sys_reg), caps)) { + for (; caps->matches; caps++) + if (cpus_have_elf_hwcap(caps) && !caps->matches(caps, SCOPE_LOCAL_CPU)) { pr_crit("CPU%d: missing HWCAP: %s\n", smp_processor_id(), caps->desc); cpu_die_early(); } - } } static void verify_local_cpu_features(const struct arm64_cpu_capabilities *caps) { for (; caps->matches; caps++) { - if (!cpus_have_cap(caps->capability) || !caps->sys_reg) + if (!cpus_have_cap(caps->capability)) continue; /* * If the new CPU misses an advertised feature, we cannot proceed * further, park the cpu. */ - if (!feature_matches(__raw_read_system_reg(caps->sys_reg), caps)) { + if (!caps->matches(caps, SCOPE_LOCAL_CPU)) { pr_crit("CPU%d: missing feature: %s\n", smp_processor_id(), caps->desc); cpu_die_early(); @@ -1026,7 +1039,7 @@ void __init setup_cpu_features(void) } static bool __maybe_unused -cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry) +cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused) { return (cpus_have_cap(ARM64_HAS_PAN) && !cpus_have_cap(ARM64_HAS_UAO)); } -- GitLab From e3661b128e53ee281e1e7c589a5b647890bd6d7c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 22 Apr 2016 12:25:32 +0100 Subject: [PATCH 4200/9938] arm64: Allow a capability to be checked on a single CPU Now that the capabilities are only available once all the CPUs have booted, we're unable to check for a particular feature in any subsystem that gets initialized before then. In order to support this, introduce a local_cpu_has_cap() function that tests for the presence of a given capability independently of the whole framework. Reviewed-by: Catalin Marinas Signed-off-by: Marc Zyngier [ Added preemptible() check ] Signed-off-by: Suzuki K Poulose [will: remove duplicate initialisation of caps in this_cpu_has_cap] Signed-off-by: Will Deacon --- arch/arm64/include/asm/cpufeature.h | 2 ++ arch/arm64/kernel/cpufeature.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index e501e4af2ebd..d39db6387746 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -109,6 +109,8 @@ struct arm64_cpu_capabilities { extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); +bool this_cpu_has_cap(unsigned int cap); + static inline bool cpu_have_feature(unsigned int num) { return elf_hwcap & (1UL << num); diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 54abd9bd5c95..2b09dc477178 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1010,6 +1010,24 @@ static void __init setup_feature_capabilities(void) enable_cpu_capabilities(arm64_features); } +/* + * Check if the current CPU has a given feature capability. + * Should be called from non-preemptible context. + */ +bool this_cpu_has_cap(unsigned int cap) +{ + const struct arm64_cpu_capabilities *caps; + + if (WARN_ON(preemptible())) + return false; + + for (caps = arm64_features; caps->desc; caps++) + if (caps->capability == cap && caps->matches) + return caps->matches(caps, SCOPE_LOCAL_CPU); + + return false; +} + void __init setup_cpu_features(void) { u32 cwg; -- GitLab From 25fc11aead380501d70b701e136e89d321277177 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 22 Apr 2016 12:25:33 +0100 Subject: [PATCH 4201/9938] irqchip/gic: Restore CPU interface checking When introducing the whole CPU feature detection framework, we lost the capability to detect a mismatched GIC configuration (using the GICv2 MMIO interface, but having the system register interface enabled). In order to solve this, use the new this_cpu_has_cap() helper. Also move the check to the CPU interface path in order to catch systems where the first CPU has been correctly configured, but the secondaries are not. Reviewed-by: Catalin Marinas Signed-off-by: Marc Zyngier Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- drivers/irqchip/irq-gic.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 282344b95ec2..095bb5b5c3f2 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -55,7 +55,7 @@ static void gic_check_cpu_features(void) { - WARN_TAINT_ONCE(cpus_have_cap(ARM64_HAS_SYSREG_GIC_CPUIF), + WARN_TAINT_ONCE(this_cpu_has_cap(ARM64_HAS_SYSREG_GIC_CPUIF), TAINT_CPU_OUT_OF_SPEC, "GICv3 system registers enabled, broken firmware!\n"); } @@ -490,6 +490,7 @@ static void gic_cpu_init(struct gic_chip_data *gic) * Get what the GIC says our CPU mask is. */ BUG_ON(cpu >= NR_GIC_CPU_IF); + gic_check_cpu_features(); cpu_mask = gic_get_cpumask(gic); gic_cpu_map[cpu] = cpu_mask; @@ -1021,8 +1022,6 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start, BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); - gic_check_cpu_features(); - gic = &gic_data[gic_nr]; /* Initialize irq_chip */ -- GitLab From 6a6efbb45b7d95c84840010095367eb06a64f342 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Fri, 22 Apr 2016 12:25:34 +0100 Subject: [PATCH 4202/9938] arm64: Verify CPU errata work arounds on hotplugged CPU CPU Errata work arounds are detected and applied to the kernel code at boot time and the data is then freed up. If a new hotplugged CPU requires a work around which was not applied at boot time, there is nothing we can do but simply fail the booting. Cc: Will Deacon Cc: Mark Rutland Cc: Andre Przywara Reviewed-by: Catalin Marinas Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/include/asm/cpufeature.h | 1 + arch/arm64/kernel/cpu_errata.c | 20 ++++++++++++++++++++ arch/arm64/kernel/cpufeature.c | 1 + 3 files changed, 22 insertions(+) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index d39db6387746..224efe730e46 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -193,6 +193,7 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, const char *info); void check_local_cpu_errata(void); +void verify_local_cpu_errata(void); void verify_local_cpu_capabilities(void); u64 read_system_reg(u32 id); diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 2fdecd72ce58..d42789499f17 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -103,6 +103,26 @@ const struct arm64_cpu_capabilities arm64_errata[] = { } }; +/* + * The CPU Errata work arounds are detected and applied at boot time + * and the related information is freed soon after. If the new CPU requires + * an errata not detected at boot, fail this CPU. + */ +void verify_local_cpu_errata(void) +{ + const struct arm64_cpu_capabilities *caps = arm64_errata; + + for (; caps->matches; caps++) + if (!cpus_have_cap(caps->capability) && + caps->matches(caps, SCOPE_LOCAL_CPU)) { + pr_crit("CPU%d: Requires work around for %s, not detected" + " at boot time\n", + smp_processor_id(), + caps->desc ? : "an erratum"); + cpu_die_early(); + } +} + void check_local_cpu_errata(void) { update_cpu_capabilities(arm64_errata, "enabling workaround for"); diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 2b09dc477178..811773d1c1d0 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -998,6 +998,7 @@ void verify_local_cpu_capabilities(void) if (!sys_caps_initialised) return; + verify_local_cpu_errata(); verify_local_cpu_features(arm64_features); verify_local_elf_hwcaps(arm64_elf_hwcaps); if (system_supports_32bit_el0()) -- GitLab From 44dbcc93ab67145bf8ebe3e91123303443c4a3bf Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Fri, 22 Apr 2016 12:25:35 +0100 Subject: [PATCH 4203/9938] arm64: Fix behavior of maxcpus=N maxcpu=n sets the number of CPUs activated at boot time to a max of n, but allowing the remaining CPUs to be brought up later if the user decides to do so. However, on arm64 due to various reasons, we disallowed hotplugging CPUs beyond n, by marking them not present. Now that we have checks in place to make sure the hotplugged CPUs have compatible features with system and requires no new errata, relax the restriction. Cc: Will Deacon Cc: Mark Rutland Cc: James Morse Reviewed-by: Catalin Marinas Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon --- arch/arm64/kernel/smp.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index fef2e7337fc7..dc9647521c59 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -689,33 +689,18 @@ void __init smp_init_cpus(void) void __init smp_prepare_cpus(unsigned int max_cpus) { int err; - unsigned int cpu, ncores = num_possible_cpus(); + unsigned int cpu; init_cpu_topology(); smp_store_cpu_info(smp_processor_id()); - /* - * are we trying to boot more cores than exist? - */ - if (max_cpus > ncores) - max_cpus = ncores; - - /* Don't bother if we're effectively UP */ - if (max_cpus <= 1) - return; - /* * Initialise the present map (which describes the set of CPUs * actually populated at the present time) and release the * secondaries from the bootloader. - * - * Make sure we online at most (max_cpus - 1) additional CPUs. */ - max_cpus--; for_each_possible_cpu(cpu) { - if (max_cpus == 0) - break; if (cpu == smp_processor_id()) continue; @@ -728,7 +713,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) continue; set_cpu_present(cpu, true); - max_cpus--; } } -- GitLab From e92bb16674c5156ea9230ba7a3ab6d490750888f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:39 +0530 Subject: [PATCH 4204/9938] cpufreq: dt: Mark platdev machines array as __initconst The machines array in cpufreq-dt-platdev is used only once at boot time and so should be marked with __initconst, so that kernel can free up memory used for it, if required. Suggested-by: Geert Uytterhoeven Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt-platdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index f2ae7ad99a3c..00da8c8bee6c 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -11,7 +11,7 @@ #include #include -static const struct of_device_id machines[] = { +static const struct of_device_id machines[] __initconst = { { .compatible = "samsung,exynos3250", }, { .compatible = "samsung,exynos4210", }, { .compatible = "samsung,exynos4212", }, -- GitLab From a59511d1daa6406eede58a79f99250ffcd9a3566 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:40 +0530 Subject: [PATCH 4205/9938] cpufreq: berlin: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Signed-off-by: Viresh Kumar Acked-by: Antoine Tenart Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-berlin/berlin.c | 6 ------ drivers/cpufreq/cpufreq-dt-platdev.c | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c index 25d73870ccca..ac181c6797ee 100644 --- a/arch/arm/mach-berlin/berlin.c +++ b/arch/arm/mach-berlin/berlin.c @@ -18,11 +18,6 @@ #include #include -static void __init berlin_init_late(void) -{ - platform_device_register_simple("cpufreq-dt", -1, NULL, 0); -} - static const char * const berlin_dt_compat[] = { "marvell,berlin", NULL, @@ -30,7 +25,6 @@ static const char * const berlin_dt_compat[] = { DT_MACHINE_START(BERLIN_DT, "Marvell Berlin") .dt_compat = berlin_dt_compat, - .init_late = berlin_init_late, /* * with DT probing for L2CCs, berlin_init_machine can be removed. * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 00da8c8bee6c..3e1c8211c213 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -12,6 +12,8 @@ #include static const struct of_device_id machines[] __initconst = { + { .compatible = "marvell,berlin", }, + { .compatible = "samsung,exynos3250", }, { .compatible = "samsung,exynos4210", }, { .compatible = "samsung,exynos4212", }, -- GitLab From 7ead83f6df2b105e4973140fe323a93ccfd4f8f9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:41 +0530 Subject: [PATCH 4206/9938] cpufreq: imx: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Note that the complete routine imx27_dt_init() is removed as of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); has same effect as a NULL .init_machine machine callback pointer. Signed-off-by: Viresh Kumar Acked-by: Lucas Stach Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-imx/imx27-dt.c | 10 ---------- arch/arm/mach-imx/mach-imx51.c | 3 --- arch/arm/mach-imx/mach-imx53.c | 2 -- arch/arm/mach-imx/mach-imx7d.c | 6 ------ drivers/cpufreq/cpufreq-dt-platdev.c | 5 +++++ 5 files changed, 5 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index bd42d1bd10af..530a728c2acc 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -18,15 +18,6 @@ #include "common.h" #include "mx27.h" -static void __init imx27_dt_init(void) -{ - struct platform_device_info devinfo = { .name = "cpufreq-dt", }; - - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - - platform_device_register_full(&devinfo); -} - static const char * const imx27_dt_board_compat[] __initconst = { "fsl,imx27", NULL @@ -36,6 +27,5 @@ DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .init_machine = imx27_dt_init, .dt_compat = imx27_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx51.c b/arch/arm/mach-imx/mach-imx51.c index 6883fbaf9484..10a82a4f1e58 100644 --- a/arch/arm/mach-imx/mach-imx51.c +++ b/arch/arm/mach-imx/mach-imx51.c @@ -50,13 +50,10 @@ static void __init imx51_ipu_mipi_setup(void) static void __init imx51_dt_init(void) { - struct platform_device_info devinfo = { .name = "cpufreq-dt", }; - imx51_ipu_mipi_setup(); imx_src_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - platform_device_register_full(&devinfo); } static void __init imx51_init_late(void) diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c index 86316a979297..18b5c5c136db 100644 --- a/arch/arm/mach-imx/mach-imx53.c +++ b/arch/arm/mach-imx/mach-imx53.c @@ -40,8 +40,6 @@ static void __init imx53_dt_init(void) static void __init imx53_init_late(void) { imx53_pm_init(); - - platform_device_register_simple("cpufreq-dt", -1, NULL, 0); } static const char * const imx53_dt_board_compat[] __initconst = { diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c index 5a27f20c9a82..b450f525a670 100644 --- a/arch/arm/mach-imx/mach-imx7d.c +++ b/arch/arm/mach-imx/mach-imx7d.c @@ -105,11 +105,6 @@ static void __init imx7d_init_irq(void) irqchip_init(); } -static void __init imx7d_init_late(void) -{ - platform_device_register_simple("cpufreq-dt", -1, NULL, 0); -} - static const char *const imx7d_dt_compat[] __initconst = { "fsl,imx7d", NULL, @@ -117,7 +112,6 @@ static const char *const imx7d_dt_compat[] __initconst = { DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)") .init_irq = imx7d_init_irq, - .init_late = imx7d_init_late, .init_machine = imx7d_init_machine, .dt_compat = imx7d_dt_compat, MACHINE_END diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 3e1c8211c213..3843314389c7 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -12,6 +12,11 @@ #include static const struct of_device_id machines[] __initconst = { + { .compatible = "fsl,imx27", }, + { .compatible = "fsl,imx51", }, + { .compatible = "fsl,imx53", }, + { .compatible = "fsl,imx7d", }, + { .compatible = "marvell,berlin", }, { .compatible = "samsung,exynos3250", }, -- GitLab From 7694ca6e1d6f01122f05039b81f70f64b1ec4063 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:42 +0530 Subject: [PATCH 4207/9938] cpufreq: omap: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Signed-off-by: Viresh Kumar Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-omap2/pm.c | 7 ++----- drivers/cpufreq/cpufreq-dt-platdev.c | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 58920bc8807b..2f7b11da7d5d 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -277,13 +277,10 @@ static void __init omap4_init_voltages(void) static inline void omap_init_cpufreq(void) { - struct platform_device_info devinfo = { }; + struct platform_device_info devinfo = { .name = "omap-cpufreq" }; if (!of_have_populated_dt()) - devinfo.name = "omap-cpufreq"; - else - devinfo.name = "cpufreq-dt"; - platform_device_register_full(&devinfo); + platform_device_register_full(&devinfo); } static int __init omap2_common_pm_init(void) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 3843314389c7..4e525f6ec59f 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -28,6 +28,11 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "samsung,exynos5420", }, { .compatible = "samsung,exynos5800", }, #endif + + { .compatible = "ti,omap2", }, + { .compatible = "ti,omap3", }, + { .compatible = "ti,omap4", }, + { .compatible = "ti,omap5", }, }; static int __init cpufreq_dt_platdev_init(void) -- GitLab From 014400c127be352a0a129aaa8a9ac870a310c76c Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 22 Apr 2016 16:58:43 +0530 Subject: [PATCH 4208/9938] cpufreq: rockchip: Use generic platdev driver This patch add rockchip's compatible string to the compat list and remove similar code from platform code for supporting generic platdev driver. Signed-off-by: Finley Xiao Acked-by: Arnd Bergmann Signed-off-by: Viresh Kumar Reviewed-by: Heiko Stuebner Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-rockchip/rockchip.c | 1 - drivers/cpufreq/cpufreq-dt-platdev.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index 3f07cc5dfe5f..beb71da5d9c8 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -74,7 +74,6 @@ static void __init rockchip_dt_init(void) { rockchip_suspend_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - platform_device_register_simple("cpufreq-dt", 0, NULL, 0); } static const char * const rockchip_board_dt_compat[] = { diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 4e525f6ec59f..75fa921d8540 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -29,6 +29,17 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "samsung,exynos5800", }, #endif + { .compatible = "rockchip,rk2928", }, + { .compatible = "rockchip,rk3036", }, + { .compatible = "rockchip,rk3066a", }, + { .compatible = "rockchip,rk3066b", }, + { .compatible = "rockchip,rk3188", }, + { .compatible = "rockchip,rk3228", }, + { .compatible = "rockchip,rk3288", }, + { .compatible = "rockchip,rk3366", }, + { .compatible = "rockchip,rk3368", }, + { .compatible = "rockchip,rk3399", }, + { .compatible = "ti,omap2", }, { .compatible = "ti,omap3", }, { .compatible = "ti,omap4", }, -- GitLab From a399dc9fc5005321cebee6589d6bca780ed99c18 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:44 +0530 Subject: [PATCH 4209/9938] cpufreq: shmobile: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Signed-off-by: Viresh Kumar Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/common.h | 7 ------- arch/arm/mach-shmobile/cpufreq.c | 19 ------------------- drivers/cpufreq/cpufreq-dt-platdev.c | 12 ++++++++++++ 4 files changed, 12 insertions(+), 27 deletions(-) delete mode 100644 arch/arm/mach-shmobile/cpufreq.c diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index a65c80ac9009..c9ea0e6ff4f9 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -38,7 +38,6 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o # PM objects obj-$(CONFIG_SUSPEND) += suspend.o -obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_PM_RCAR) += pm-rcar.o obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index 5464b7a75e30..3b562d87826d 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -25,16 +25,9 @@ static inline int shmobile_suspend_init(void) { return 0; } static inline void shmobile_smp_apmu_suspend_init(void) { } #endif -#ifdef CONFIG_CPU_FREQ -int shmobile_cpufreq_init(void); -#else -static inline int shmobile_cpufreq_init(void) { return 0; } -#endif - static inline void __init shmobile_init_late(void) { shmobile_suspend_init(); - shmobile_cpufreq_init(); } #endif /* __ARCH_MACH_COMMON_H */ diff --git a/arch/arm/mach-shmobile/cpufreq.c b/arch/arm/mach-shmobile/cpufreq.c deleted file mode 100644 index 634d701c56a7..000000000000 --- a/arch/arm/mach-shmobile/cpufreq.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * CPUFreq support code for SH-Mobile ARM - * - * Copyright (C) 2014 Gaku Inami - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include - -#include "common.h" - -int __init shmobile_cpufreq_init(void) -{ - platform_device_register_simple("cpufreq-dt", -1, NULL, 0); - return 0; -} diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 75fa921d8540..4b94fe3427f9 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -29,6 +29,18 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "samsung,exynos5800", }, #endif + { .compatible = "renesas,emev2", }, + { .compatible = "renesas,r7s72100", }, + { .compatible = "renesas,r8a73a4", }, + { .compatible = "renesas,r8a7740", }, + { .compatible = "renesas,r8a7778", }, + { .compatible = "renesas,r8a7779", }, + { .compatible = "renesas,r8a7790", }, + { .compatible = "renesas,r8a7791", }, + { .compatible = "renesas,r8a7793", }, + { .compatible = "renesas,r8a7794", }, + { .compatible = "renesas,sh73a0", }, + { .compatible = "rockchip,rk2928", }, { .compatible = "rockchip,rk3036", }, { .compatible = "rockchip,rk3066a", }, -- GitLab From 117d4f59affa869f819ec53ed0cd54aedfdeffa0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:45 +0530 Subject: [PATCH 4210/9938] cpufreq: sunxi: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Signed-off-by: Viresh Kumar Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-sunxi/sunxi.c | 9 --------- drivers/cpufreq/cpufreq-dt-platdev.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 3c156190a1d4..95dca8c2c9ed 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -17,11 +17,6 @@ #include -static void __init sunxi_dt_cpufreq_init(void) -{ - platform_device_register_simple("cpufreq-dt", -1, NULL, 0); -} - static const char * const sunxi_board_dt_compat[] = { "allwinner,sun4i-a10", "allwinner,sun5i-a10s", @@ -32,7 +27,6 @@ static const char * const sunxi_board_dt_compat[] = { DT_MACHINE_START(SUNXI_DT, "Allwinner sun4i/sun5i Families") .dt_compat = sunxi_board_dt_compat, - .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun6i_board_dt_compat[] = { @@ -53,7 +47,6 @@ static void __init sun6i_timer_init(void) DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family") .init_time = sun6i_timer_init, .dt_compat = sun6i_board_dt_compat, - .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun7i_board_dt_compat[] = { @@ -63,7 +56,6 @@ static const char * const sun7i_board_dt_compat[] = { DT_MACHINE_START(SUN7I_DT, "Allwinner sun7i (A20) Family") .dt_compat = sun7i_board_dt_compat, - .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun8i_board_dt_compat[] = { @@ -77,7 +69,6 @@ static const char * const sun8i_board_dt_compat[] = { DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family") .init_time = sun6i_timer_init, .dt_compat = sun8i_board_dt_compat, - .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun9i_board_dt_compat[] = { diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 4b94fe3427f9..24dde5e256d4 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -12,6 +12,18 @@ #include static const struct of_device_id machines[] __initconst = { + { .compatible = "allwinner,sun4i-a10", }, + { .compatible = "allwinner,sun5i-a10s", }, + { .compatible = "allwinner,sun5i-a13", }, + { .compatible = "allwinner,sun5i-r8", }, + { .compatible = "allwinner,sun6i-a31", }, + { .compatible = "allwinner,sun6i-a31s", }, + { .compatible = "allwinner,sun7i-a20", }, + { .compatible = "allwinner,sun8i-a23", }, + { .compatible = "allwinner,sun8i-a33", }, + { .compatible = "allwinner,sun8i-a83t", }, + { .compatible = "allwinner,sun8i-h3", }, + { .compatible = "fsl,imx27", }, { .compatible = "fsl,imx51", }, { .compatible = "fsl,imx53", }, -- GitLab From 5e4249c6d9e596fdb26357997236a01b96c8902d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:46 +0530 Subject: [PATCH 4211/9938] cpufreq: zynq: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Signed-off-by: Viresh Kumar Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-zynq/common.c | 2 -- drivers/cpufreq/cpufreq-dt-platdev.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 860ffb663f02..da876d28ccbc 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -110,7 +110,6 @@ static void __init zynq_init_late(void) */ static void __init zynq_init_machine(void) { - struct platform_device_info devinfo = { .name = "cpufreq-dt", }; struct soc_device_attribute *soc_dev_attr; struct soc_device *soc_dev; struct device *parent = NULL; @@ -145,7 +144,6 @@ static void __init zynq_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); platform_device_register(&zynq_cpuidle_device); - platform_device_register_full(&devinfo); } static void __init zynq_timer_init(void) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 24dde5e256d4..5ad29383e862 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -68,6 +68,8 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "ti,omap3", }, { .compatible = "ti,omap4", }, { .compatible = "ti,omap5", }, + + { .compatible = "xlnx,zynq-7000", }, }; static int __init cpufreq_dt_platdev_init(void) -- GitLab From 3920be471ce7f66c05e6e0cd251a332b84520ef8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Apr 2016 16:58:47 +0530 Subject: [PATCH 4212/9938] cpufreq: hisilicon: Use generic platdev driver The cpufreq-dt-platdev driver supports creation of cpufreq-dt platform device now, reuse that and remove similar code from platform code. Signed-off-by: Viresh Kumar Acked-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/Kconfig.arm | 9 ------ drivers/cpufreq/Makefile | 1 - drivers/cpufreq/cpufreq-dt-platdev.c | 2 ++ drivers/cpufreq/hisi-acpu-cpufreq.c | 42 ---------------------------- 4 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 drivers/cpufreq/hisi-acpu-cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 14b1f9393b05..d89b8afe23b6 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -50,15 +50,6 @@ config ARM_HIGHBANK_CPUFREQ If in doubt, say N. -config ARM_HISI_ACPU_CPUFREQ - tristate "Hisilicon ACPU CPUfreq driver" - depends on ARCH_HISI && CPUFREQ_DT - select PM_OPP - help - This enables the hisilicon ACPU CPUfreq driver. - - If in doubt, say N. - config ARM_IMX6Q_CPUFREQ tristate "Freescale i.MX6 cpufreq support" depends on ARCH_MXC diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index d7b646c0f2e9..2cce2cd400f9 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -55,7 +55,6 @@ obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o -obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ) += hisi-acpu-cpufreq.o obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 5ad29383e862..ac4a0ba87c12 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -24,6 +24,8 @@ static const struct of_device_id machines[] __initconst = { { .compatible = "allwinner,sun8i-a83t", }, { .compatible = "allwinner,sun8i-h3", }, + { .compatible = "hisilicon,hi6220", }, + { .compatible = "fsl,imx27", }, { .compatible = "fsl,imx51", }, { .compatible = "fsl,imx53", }, diff --git a/drivers/cpufreq/hisi-acpu-cpufreq.c b/drivers/cpufreq/hisi-acpu-cpufreq.c deleted file mode 100644 index 026d5b2224de..000000000000 --- a/drivers/cpufreq/hisi-acpu-cpufreq.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Hisilicon Platforms Using ACPU CPUFreq Support - * - * Copyright (c) 2015 Hisilicon Limited. - * Copyright (c) 2015 Linaro Limited. - * - * Leo Yan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include - -static int __init hisi_acpu_cpufreq_driver_init(void) -{ - struct platform_device *pdev; - - if (!of_machine_is_compatible("hisilicon,hi6220")) - return -ENODEV; - - pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); - return PTR_ERR_OR_ZERO(pdev); -} -module_init(hisi_acpu_cpufreq_driver_init); - -MODULE_AUTHOR("Leo Yan "); -MODULE_DESCRIPTION("Hisilicon acpu cpufreq driver"); -MODULE_LICENSE("GPL v2"); -- GitLab From ba1ca654f30ddca8f208f43ebbf27cb933a97982 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 25 Apr 2016 16:21:34 +0200 Subject: [PATCH 4213/9938] cpufreq: governor: Fix prev_load initialization in cpufreq_governor_start() The way cpufreq_governor_start() initializes j_cdbs->prev_load is questionable. First off, j_cdbs->prev_cpu_wall used as a denominator in the computation may be zero. The case this happens is when get_cpu_idle_time_us() returns -1 and get_cpu_idle_time_jiffy() used to return that number is called exactly at the jiffies_64 wrap time. It is rather hard to trigger that error, but it is not impossible and it will just crash the kernel then. Second, j_cdbs->prev_load is computed as the average load during the entire time since the system started and it may not reflect the load in the previous sampling period (as it is expected to). That doesn't play well with the way dbs_update() uses that value. Namely, if the update time delta (wall_time) happens do be greater than twice the sampling rate on the first invocation of it, the initial value of j_cdbs->prev_load (which may be completely off) will be returned to the caller as the current load (unless it is equal to zero and unless another CPU sharing the same policy object has a greater load value). For this reason, notice that the prev_load field of struct cpu_dbs_info is only used by dbs_update() and only in that one place, so if cpufreq_governor_start() is modified to always initialize it to 0, it will make dbs_update() always compute the actual load first time it checks the update time delta against the doubled sampling rate (after initialization) and there won't be any side effects of it. Consequently, modify cpufreq_governor_start() as described. Fixes: 18b46abd0009 (cpufreq: governor: Be friendly towards latency-sensitive bursty workloads) Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq_governor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index db649c6d86c9..095f91cd4810 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -508,12 +508,12 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy) for_each_cpu(j, policy->cpus) { struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j); - unsigned int prev_load; j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall, io_busy); - - prev_load = j_cdbs->prev_cpu_wall - j_cdbs->prev_cpu_idle; - j_cdbs->prev_load = 100 * prev_load / (unsigned int)j_cdbs->prev_cpu_wall; + /* + * Make the first invocation of dbs_update() compute the load. + */ + j_cdbs->prev_load = 0; if (ignore_nice) j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; -- GitLab From d6a442df63b2f0043c0b4fc05504ac4ded96ae80 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 24 Apr 2016 22:55:47 +0100 Subject: [PATCH 4214/9938] hwmon: (sch5636) trivial fix of spelling mistake on revision fix spelling mistake, revison -> revision Signed-off-by: Colin Ian King Signed-off-by: Guenter Roeck --- drivers/hwmon/sch5636.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c index 131a2815dbda..d24d7b6047f2 100644 --- a/drivers/hwmon/sch5636.c +++ b/drivers/hwmon/sch5636.c @@ -449,7 +449,7 @@ static int sch5636_probe(struct platform_device *pdev) } revision[i] = val; } - pr_info("Found %s chip at %#hx, revison: %d.%02d\n", DEVNAME, + pr_info("Found %s chip at %#hx, revision: %d.%02d\n", DEVNAME, data->addr, revision[0], revision[1]); /* Read all temp + fan ctrl registers to determine which are active */ -- GitLab From 1f644a737340592a7c20a7c525e8d279e9a4f119 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 07:37:04 +0100 Subject: [PATCH 4215/9938] Documentation: virtual: fix spelling mistake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Eric Engestrom Acked-by: Cornelia Huck Signed-off-by: Radim Krčmář --- Documentation/virtual/kvm/devices/s390_flic.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt index 8478de1c0192..6b0e115301c8 100644 --- a/Documentation/virtual/kvm/devices/s390_flic.txt +++ b/Documentation/virtual/kvm/devices/s390_flic.txt @@ -74,7 +74,7 @@ struct kvm_s390_io_adapter { KVM_DEV_FLIC_ADAPTER_MODIFY Modifies attributes of an existing I/O adapter interrupt source. Takes - a kvm_s390_io_adapter_req specifiying the adapter and the operation: + a kvm_s390_io_adapter_req specifying the adapter and the operation: struct kvm_s390_io_adapter_req { __u32 id; -- GitLab From 1c986e3643d278d93e9ca67b3c752f486cc32318 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 20 Apr 2016 10:18:46 +0900 Subject: [PATCH 4216/9938] of: document refcount incrementation of of_get_cpu_node() This function increments refcount. This is worth noting. Signed-off-by: Masahiro Yamada Reviewed-by: Frank Rowand Signed-off-by: Rob Herring --- drivers/of/base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index e87e21df19d8..116666b088cc 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -394,7 +394,8 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, * before booting secondary cores. This function uses arch_match_cpu_phys_id * which can be overridden by architecture specific implementation. * - * Returns a node pointer for the logical cpu if found, else NULL. + * Returns a node pointer for the logical cpu with refcount incremented, use + * of_node_put() on it when done. Returns NULL if not found. */ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) { -- GitLab From 70a2cba972e5e4a5d850e4179381f1cd344c6828 Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Tue, 19 Apr 2016 11:17:27 +0300 Subject: [PATCH 4217/9938] perf buildid: Fix off-by-one in write_buildid() write_buildid() increments 'name_len' with intention to take into account trailing zero byte. However, 'name_len' was already incremented in machine__write_buildid_table() before. So this leads to out-of-bounds read in do_write(): $ ./perf record sleep 0 [ perf record: Woken up 1 times to write data ] ================================================================= ==15899==ERROR: AddressSanitizer: global-buffer-overflow on address 0x00000099fc92 at pc 0x7f1aa9c7eab5 bp 0x7fff940f84d0 sp 0x7fff940f7c78 READ of size 19 at 0x00000099fc92 thread T0 #0 0x7f1aa9c7eab4 (/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/libasan.so.2+0x44ab4) #1 0x649c5b in do_write util/header.c:67 #2 0x649c5b in write_padded util/header.c:82 #3 0x57e8bc in write_buildid util/build-id.c:239 #4 0x57e8bc in machine__write_buildid_table util/build-id.c:278 ... 0x00000099fc92 is located 0 bytes to the right of global variable '*.LC99' defined in 'util/symbol.c' (0x99fc80) of size 18 '*.LC99' is ascii string '[kernel.kallsyms]' ... Shadow bytes around the buggy address: 0x00008012bf80: f9 f9 f9 f9 00 00 00 00 00 00 03 f9 f9 f9 f9 f9 =>0x00008012bf90: 00 00[02]f9 f9 f9 f9 f9 00 00 00 00 00 05 f9 f9 0x00008012bfa0: f9 f9 f9 f9 00 03 f9 f9 f9 f9 f9 f9 00 00 00 00 Signed-off-by: Andrey Ryabinin Cc: Alexander Shishkin Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1461053847-5633-1-git-send-email-aryabinin@virtuozzo.com [ Remove the off-by one at the origin, to keep len(s) == strlen(s) assumption ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 0573c2ec861d..b6ecf87bc3e3 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -261,14 +261,14 @@ static int machine__write_buildid_table(struct machine *machine, int fd) if (dso__is_vdso(pos)) { name = pos->short_name; - name_len = pos->short_name_len + 1; + name_len = pos->short_name_len; } else if (dso__is_kcore(pos)) { machine__mmap_name(machine, nm, sizeof(nm)); name = nm; - name_len = strlen(nm) + 1; + name_len = strlen(nm); } else { name = pos->long_name; - name_len = pos->long_name_len + 1; + name_len = pos->long_name_len; } in_kernel = pos->kernel || -- GitLab From 0ae537cb35e63f6a61013e736a0557b83a0336ea Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 19 Apr 2016 16:00:01 -0300 Subject: [PATCH 4218/9938] perf trace: Extract evsel contructor from perf_evlist__add_pgfault Prep work for next patches, where we'll need access to the created evsels, to possibly configure callchains. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-2pcgsgnkgellhlcao4aub8tu@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 5e2614bbb48d..69b460354201 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2381,8 +2381,7 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) return true; } -static int perf_evlist__add_pgfault(struct perf_evlist *evlist, - u64 config) +static struct perf_evsel *perf_evsel__new_pgfault(u64 config) { struct perf_evsel *evsel; struct perf_event_attr attr = { @@ -2396,13 +2395,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist, event_attr_init(&attr); evsel = perf_evsel__new(&attr); - if (!evsel) - return -ENOMEM; - - evsel->handler = trace__pgfault; - perf_evlist__add(evlist, evsel); + if (evsel) + evsel->handler = trace__pgfault; - return 0; + return evsel; } static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) @@ -2504,7 +2500,7 @@ static int trace__set_ev_qualifier_filter(struct trace *trace) static int trace__run(struct trace *trace, int argc, const char **argv) { struct perf_evlist *evlist = trace->evlist; - struct perf_evsel *evsel; + struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL; int err = -1, i; unsigned long before; const bool forks = argc > 0; @@ -2518,14 +2514,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (trace->trace_syscalls) trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); - if ((trace->trace_pgfaults & TRACE_PFMAJ) && - perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) { - goto out_error_mem; + if ((trace->trace_pgfaults & TRACE_PFMAJ)) { + pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ); + if (pgfault_maj == NULL) + goto out_error_mem; + perf_evlist__add(evlist, pgfault_maj); } - if ((trace->trace_pgfaults & TRACE_PFMIN) && - perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN)) - goto out_error_mem; + if ((trace->trace_pgfaults & TRACE_PFMIN)) { + pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN); + if (pgfault_min == NULL) + goto out_error_mem; + perf_evlist__add(evlist, pgfault_min); + } if (trace->sched && perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", -- GitLab From 0c3a6ef4ea54a179328734a45b7f7698e44ad805 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 19 Apr 2016 16:31:12 -0300 Subject: [PATCH 4219/9938] perf trace: Make --pf maj/min/all use callchains too Forgot about page faults, a software event, when adding support for callchains, fix it: # trace --no-syscalls --pf maj --call dwarf 0.000 ( 0.000 ms): Xorg/2068 majfault [sfbSegment1+0x0] => /usr/lib64/xorg/modules/drivers/intel_drv.so@0x11b490 (x.) sfbSegment1+0x0 (/usr/lib64/xorg/modules/drivers/intel_drv.so) fbPolySegment32+0x361 (/usr/lib64/xorg/modules/drivers/intel_drv.so) sna_poly_segment+0x743 (/usr/lib64/xorg/modules/drivers/intel_drv.so) damagePolySegment+0x77 (/usr/libexec/Xorg) ProcPolySegment+0xe7 (/usr/libexec/Xorg) Dispatch+0x25f (/usr/libexec/Xorg) dix_main+0x3c3 (/usr/libexec/Xorg) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) _start+0x29 (/usr/libexec/Xorg) 0.257 ( 0.000 ms): Xorg/2068 majfault [miZeroClipLine+0x0] => /usr/libexec/Xorg@0x18e830 (x.) miZeroClipLine+0x0 (/usr/libexec/Xorg) _fbSegment+0x2c0 (/usr/lib64/xorg/modules/drivers/intel_drv.so) sfbSegment1+0x67 (/usr/lib64/xorg/modules/drivers/intel_drv.so) fbPolySegment32+0x361 (/usr/lib64/xorg/modules/drivers/intel_drv.so) sna_poly_segment+0x743 (/usr/lib64/xorg/modules/drivers/intel_drv.so) damagePolySegment+0x77 (/usr/libexec/Xorg) ProcPolySegment+0xe7 (/usr/libexec/Xorg) Dispatch+0x25f (/usr/libexec/Xorg) dix_main+0x3c3 (/usr/libexec/Xorg) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) _start+0x29 (/usr/libexec/Xorg) ^C# Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-8h6ssirw5z15qyhy2lwd6f89@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 59 ++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 69b460354201..d1bbcb9abca3 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2222,6 +2222,11 @@ static int trace__pgfault(struct trace *trace, print_location(trace->output, sample, &al, true, false); fprintf(trace->output, " (%c%c)\n", map_type, al.level); + + if (sample->callchain) { + if (trace__resolve_callchain(trace, evsel, sample, &callchain_cursor) == 0) + trace__fprintf_callchain(trace, sample); + } out: err = 0; out_put: @@ -2547,24 +2552,42 @@ static int trace__run(struct trace *trace, int argc, const char **argv) perf_evlist__config(evlist, &trace->opts, NULL); - if (callchain_param.enabled && trace->syscalls.events.sys_exit) { - perf_evsel__config_callchain(trace->syscalls.events.sys_exit, - &trace->opts, &callchain_param); - /* - * Now we have evsels with different sample_ids, use - * PERF_SAMPLE_IDENTIFIER to map from sample to evsel - * from a fixed position in each ring buffer record. - * - * As of this the changeset introducing this comment, this - * isn't strictly needed, as the fields that can come before - * PERF_SAMPLE_ID are all used, but we'll probably disable - * some of those for things like copying the payload of - * pointer syscall arguments, and for vfs_getname we don't - * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this - * here as a warning we need to use PERF_SAMPLE_IDENTIFIER. - */ - perf_evlist__set_sample_bit(evlist, IDENTIFIER); - perf_evlist__reset_sample_bit(evlist, ID); + if (callchain_param.enabled) { + bool use_identifier = false; + + if (trace->syscalls.events.sys_exit) { + perf_evsel__config_callchain(trace->syscalls.events.sys_exit, + &trace->opts, &callchain_param); + use_identifier = true; + } + + if (pgfault_maj) { + perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param); + use_identifier = true; + } + + if (pgfault_min) { + perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param); + use_identifier = true; + } + + if (use_identifier) { + /* + * Now we have evsels with different sample_ids, use + * PERF_SAMPLE_IDENTIFIER to map from sample to evsel + * from a fixed position in each ring buffer record. + * + * As of this the changeset introducing this comment, this + * isn't strictly needed, as the fields that can come before + * PERF_SAMPLE_ID are all used, but we'll probably disable + * some of those for things like copying the payload of + * pointer syscall arguments, and for vfs_getname we don't + * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this + * here as a warning we need to use PERF_SAMPLE_IDENTIFIER. + */ + perf_evlist__set_sample_bit(evlist, IDENTIFIER); + perf_evlist__reset_sample_bit(evlist, ID); + } } signal(SIGCHLD, sig_handler); -- GitLab From e557b674a9470dae99916be6105e6780b3a072ca Mon Sep 17 00:00:00 2001 From: Chris Phlipot Date: Tue, 19 Apr 2016 19:32:11 -0700 Subject: [PATCH 4220/9938] perf script: Fix segfault when printing callchains This fixes a bug caused by an unitialized callchain cursor. The crash frist appeared in: 6f736735e30f ("perf evsel: Require that callchains be resolved before calling fprintf_{sym,callchain}") The callchain cursor is a struct that contains pointers, that when uninitialized will cause unpredictable behavior (usually a crash) when trying to append to the callchain. The existing implementation has the following issues: 1. The callchain cursor used is not initialized, resulting in unpredictable behavior when used. 2. The cursor is declared on the stack. Even if it is properly initalized, the implmentation will leak memory when the function returns, since all the references to the callchain_nodes allocated by callchain_cursor_append will be lost when the cursor goes out of scope. 3. Storing the cursor on the stack is inefficient. Even if memory is properly freed when it goes out of scope, a performance penalty will be incurred due to reallocation of callchain nodes. callchain_cursor_append is designed to avoid these reallocations when an existing cursor is reused. This patch fixes the crash by replacing cursor_callchain with a reference to the global callchain_cursor which also resolves all 3 issues mentioned above. How to reproduce the crash: $ perf record --call-graph=dwarf stress -t 1 -c 1 $ perf script > /dev/null Segfault Signed-off-by: Chris Phlipot Tested-by: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Fixes: 6f736735e30f ("perf evsel: Require that callchains be resolved before calling fprintf_{sym,callchain}") Link: http://lkml.kernel.org/r/1461119531-2529-1-git-send-email-cphlipot0@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 5099740aa50b..f43b0c6f88f4 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -570,12 +570,12 @@ static void print_sample_bts(struct perf_sample *sample, /* print branch_from information */ if (PRINT_FIELD(IP)) { unsigned int print_opts = output[attr->type].print_ip_opts; - struct callchain_cursor *cursor = NULL, cursor_callchain; + struct callchain_cursor *cursor = NULL; if (symbol_conf.use_callchain && sample->callchain && - thread__resolve_callchain(al->thread, &cursor_callchain, evsel, + thread__resolve_callchain(al->thread, &callchain_cursor, evsel, sample, NULL, NULL, scripting_max_stack) == 0) - cursor = &cursor_callchain; + cursor = &callchain_cursor; if (cursor == NULL) { putchar(' '); @@ -789,12 +789,12 @@ static void process_event(struct perf_script *script, printf("%16" PRIu64, sample->weight); if (PRINT_FIELD(IP)) { - struct callchain_cursor *cursor = NULL, cursor_callchain; + struct callchain_cursor *cursor = NULL; if (symbol_conf.use_callchain && sample->callchain && - thread__resolve_callchain(al->thread, &cursor_callchain, evsel, + thread__resolve_callchain(al->thread, &callchain_cursor, evsel, sample, NULL, NULL, scripting_max_stack) == 0) - cursor = &cursor_callchain; + cursor = &callchain_cursor; putchar(cursor ? '\n' : ' '); sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout); -- GitLab From 7ad356159542e1f0dd4703ff3604f67390657f57 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 20 Apr 2016 19:55:48 -0300 Subject: [PATCH 4221/9938] perf trace: Make --event honour --min-stack too Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-shj0fazntmskhjild5i6x73l@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d1bbcb9abca3..fc276d718172 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2126,6 +2126,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { + int callchain_ret = 0; + + if (sample->callchain) { + callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor); + if (callchain_ret == 0) { + if (callchain_cursor.nr < trace->min_stack) + goto out; + callchain_ret = 1; + } + } + trace__printf_interrupted_entry(trace, sample); trace__fprintf_tstamp(trace, sample->time, trace->output); @@ -2144,11 +2155,11 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, fprintf(trace->output, ")\n"); - if (sample->callchain) { - if (trace__resolve_callchain(trace, evsel, sample, &callchain_cursor) == 0) - trace__fprintf_callchain(trace, sample); - } - + if (callchain_ret > 0) + trace__fprintf_callchain(trace, sample); + else if (callchain_ret < 0) + pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); +out: return 0; } -- GitLab From 1df54290463e84b7b5eb26e5e6472167c3749901 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 20 Apr 2016 20:06:02 -0300 Subject: [PATCH 4222/9938] perf trace: Make --pf honour --min-stack too To check deeply nested page fault callchains. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-wuji34xx003kr88nmqt6jkgf@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index fc276d718172..a4b133fac82b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2190,8 +2190,19 @@ static int trace__pgfault(struct trace *trace, char map_type = 'd'; struct thread_trace *ttrace; int err = -1; + int callchain_ret = 0; thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); + + if (sample->callchain) { + callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor); + if (callchain_ret == 0) { + if (callchain_cursor.nr < trace->min_stack) + goto out_put; + callchain_ret = 1; + } + } + ttrace = thread__trace(thread, trace->output); if (ttrace == NULL) goto out_put; @@ -2234,10 +2245,10 @@ static int trace__pgfault(struct trace *trace, fprintf(trace->output, " (%c%c)\n", map_type, al.level); - if (sample->callchain) { - if (trace__resolve_callchain(trace, evsel, sample, &callchain_cursor) == 0) - trace__fprintf_callchain(trace, sample); - } + if (callchain_ret > 0) + trace__fprintf_callchain(trace, sample); + else if (callchain_ret < 0) + pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); out: err = 0; out_put: -- GitLab From 5e91f6ce4c584d231763437a3ea3aded8e672363 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 25 Apr 2016 06:34:09 -0700 Subject: [PATCH 4223/9938] sock: relax WARN_ON() in sock_owned_by_user() Valdis reported tons of stack dumps caused by WARN_ON() in sock_owned_by_user() This test needs to be relaxed if/when lockdep disables itself. Note that other lockdep_sock_is_held() callers are all from rcu_dereference_protected() sections which already are disabled if/when lockdep has been disabled. Fixes: fafc4e1ea1a4 ("sock: tigthen lockdep checks for sock_owned_by_user") Reported-by: Valdis Kletnieks Signed-off-by: Eric Dumazet Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/net/sock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index 52448baf19d7..2fdb87f176cf 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1409,7 +1409,7 @@ static inline void unlock_sock_fast(struct sock *sk, bool slow) static inline bool sock_owned_by_user(const struct sock *sk) { #ifdef CONFIG_LOCKDEP - WARN_ON(!lockdep_sock_is_held(sk)); + WARN_ON_ONCE(!lockdep_sock_is_held(sk) && debug_locks); #endif return sk->sk_lock.owned; } -- GitLab From a34b027dca5ea840fbc84121db66488375acfdea Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Mon, 25 Apr 2016 13:39:38 +0000 Subject: [PATCH 4224/9938] ASoC: bcm2835: add 24bit support This adds 24 bit support to the I2S driver of the BCM2835 Code ported from bcm2708-i2s driver in Raspberry Pi tree. Signed-off-by: Florian Meier Signed-off-by: Matthias Reichl Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 1c1f2210387b..d2663e79ece1 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -259,6 +259,9 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S16_LE: data_length = 16; break; + case SNDRV_PCM_FORMAT_S24_LE: + data_length = 24; + break; case SNDRV_PCM_FORMAT_S32_LE: data_length = 32; break; @@ -279,7 +282,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, /* Setup the frame format */ format = BCM2835_I2S_CHEN; - if (data_length > 24) + if (data_length >= 24) format |= BCM2835_I2S_CHWEX; format |= BCM2835_I2S_CHWID((data_length-8)&0xf); @@ -570,6 +573,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = { .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE + | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE }, .capture = { @@ -577,6 +581,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = { .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE + | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE }, .ops = &bcm2835_i2s_dai_ops, -- GitLab From 60507fe191f524e82986fa737e5b27b4d3ad9289 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Mon, 25 Apr 2016 13:39:39 +0000 Subject: [PATCH 4225/9938] ASoC: bcm2835: setup clock only if CPU is clock master We only need to enable the clock if we are a clock master. Code ported from bcm2708-i2s driver in Raspberry Pi tree. Original work by Zoltan Szenczi. Signed-off-by: Matthias Reichl Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index d2663e79ece1..a0026e2d2f0a 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -276,8 +276,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, /* otherwise calculate a fitting block ratio */ bclk_ratio = 2 * data_length; - /* set target clock rate*/ - clk_set_rate(dev->clk, sampling_rate * bclk_ratio); + /* Clock should only be set up here if CPU is clock master */ + switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBS_CFM: + clk_set_rate(dev->clk, sampling_rate * bclk_ratio); + break; + default: + break; + } /* Setup the frame format */ format = BCM2835_I2S_CHEN; -- GitLab From d296ba60d8e2de23a350796a567a3aa90fe1cb6e Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Mon, 25 Apr 2016 10:42:12 -0400 Subject: [PATCH 4226/9938] soreuseport: Resolve merge conflict for v4/v6 ordering fix d894ba18d4e4 ("soreuseport: fix ordering for mixed v4/v6 sockets") was merged as a bug fix to the net tree. Two conflicting changes were committed to net-next before the above fix was merged back to net-next: ca065d0cf80f ("udp: no longer use SLAB_DESTROY_BY_RCU") 3b24d854cb35 ("tcp/dccp: do not touch listener sk_refcnt under synflood") These changes switched the datastructure used for TCP and UDP sockets from hlist_nulls to hlist. This patch applies the necessary parts of the net tree fix to net-next which were not automatic as part of the merge. Fixes: 1602f49b58ab ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net") Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- include/net/sock.h | 6 +++++- net/ipv4/inet_hashtables.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 2fdb87f176cf..d63b8494124e 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -630,7 +630,11 @@ static inline void sk_add_node(struct sock *sk, struct hlist_head *list) static inline void sk_add_node_rcu(struct sock *sk, struct hlist_head *list) { sock_hold(sk); - hlist_add_head_rcu(&sk->sk_node, list); + if (IS_ENABLED(CONFIG_IPV6) && sk->sk_reuseport && + sk->sk_family == AF_INET6) + hlist_add_tail_rcu(&sk->sk_node, list); + else + hlist_add_head_rcu(&sk->sk_node, list); } static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index fcadb670f50b..b76b0d7e59c1 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -479,7 +479,11 @@ int __inet_hash(struct sock *sk, struct sock *osk, if (err) goto unlock; } - hlist_add_head_rcu(&sk->sk_node, &ilb->head); + if (IS_ENABLED(CONFIG_IPV6) && sk->sk_reuseport && + sk->sk_family == AF_INET6) + hlist_add_tail_rcu(&sk->sk_node, &ilb->head); + else + hlist_add_head_rcu(&sk->sk_node, &ilb->head); sock_set_flag(sk, SOCK_RCU_FREE); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); unlock: -- GitLab From cd84042ce9040ad038e958bc67a46fcfc015c736 Mon Sep 17 00:00:00 2001 From: "Vittorio Gambaletta (VittGam)" Date: Mon, 11 Apr 2016 04:48:54 +0200 Subject: [PATCH 4227/9938] ath9k: Add a module parameter to invert LED polarity. The LED can be active high instead of active low on some hardware. Add the led_active_high module parameter. It defaults to -1 to obey platform data as before. Setting the parameter to 1 or 0 will force the LED respectively active high or active low. Cc: Cc: Cc: Cc: Signed-off-by: Vittorio Gambaletta Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fb702c48a233..535b1644501c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -49,6 +49,10 @@ int ath9k_led_blink; module_param_named(blink, ath9k_led_blink, int, 0444); MODULE_PARM_DESC(blink, "Enable LED blink on activity"); +static int ath9k_led_active_high = -1; +module_param_named(led_active_high, ath9k_led_active_high, int, 0444); +MODULE_PARM_DESC(led_active_high, "Invert LED polarity"); + static int ath9k_btcoex_enable; module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); @@ -600,6 +604,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, if (ret) return ret; + if (ath9k_led_active_high != -1) + ah->config.led_active_high = ath9k_led_active_high == 1; + /* * Enable WLAN/BT RX Antenna diversity only when: * -- GitLab From 0f9edcdd88a993914fa1d1dc369b35dc503979db Mon Sep 17 00:00:00 2001 From: "Vittorio Gambaletta (VittGam)" Date: Mon, 11 Apr 2016 04:48:55 +0200 Subject: [PATCH 4228/9938] ath9k: Fix LED polarity for some Mini PCI AR9220 MB92 cards. The Wistron DNMA-92 and Compex WLM200NX have inverted LED polarity (active high instead of active low). The same PCI Subsystem ID is used by both cards, which are based on the same Atheros MB92 design. Cc: Cc: Cc: Cc: Signed-off-by: Vittorio Gambaletta Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index e6fef1be9977..7cdaf40c3057 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -28,6 +28,16 @@ static const struct pci_device_id ath_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ + +#ifdef CONFIG_ATH9K_PCOEM + /* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0029, + PCI_VENDOR_ID_ATHEROS, + 0x2096), + .driver_data = ATH9K_PCI_LED_ACT_HI }, +#endif + { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ #ifdef CONFIG_ATH9K_PCOEM -- GitLab From 25d217d6e0723481bf90db1d8be02ab475d16002 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:39 -0700 Subject: [PATCH 4229/9938] wcn36xx: Clean up wcn36xx_smd_send_beacon Needed for coming improvements. No functional changes. Signed-off-by: Pontus Fuchs [bjorn: restored BEACON_TEMPLATE_SIZE define to 0x180] Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 5 ++++- drivers/net/wireless/ath/wcn36xx/smd.c | 12 +++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index b947de0fb2e5..d713204f755d 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2884,11 +2884,14 @@ struct update_beacon_rsp_msg { struct wcn36xx_hal_send_beacon_req_msg { struct wcn36xx_hal_msg_header header; + /* length of the template + 6. Only qcom knows why */ + u32 beacon_length6; + /* length of the template. */ u32 beacon_length; /* Beacon data. */ - u8 beacon[BEACON_TEMPLATE_SIZE]; + u8 beacon[BEACON_TEMPLATE_SIZE - sizeof(u32)]; u8 bssid[ETH_ALEN]; diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 74f56a81ad9a..ff3ed2461a69 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1380,19 +1380,17 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); - /* TODO need to find out why this is needed? */ - msg_body.beacon_length = skb_beacon->len + 6; + msg_body.beacon_length = skb_beacon->len; + /* TODO need to find out why + 6 is needed */ + msg_body.beacon_length6 = msg_body.beacon_length + 6; - if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { - memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); - memcpy(&(msg_body.beacon[4]), skb_beacon->data, - skb_beacon->len); - } else { + if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) { wcn36xx_err("Beacon is to big: beacon size=%d\n", msg_body.beacon_length); ret = -ENOMEM; goto out; } + memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len); memcpy(msg_body.bssid, vif->addr, ETH_ALEN); /* TODO need to find out why this is needed? */ -- GitLab From 91c3eeba45e13ab7edfb50610df8672d52809394 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:40 -0700 Subject: [PATCH 4230/9938] wcn36xx: Pad TIM PVM if needed The wcn36xx FW expects a fixed size TIM PVM in the beacon template. If supplied with a shorter than expected PVM it will overwrite the IE following the TIM. Squashed with fix from Jason Mobarak : Patch "wcn36xx: Pad TIM PVM if needed" has caused a regression in mesh beaconing. The field tim_off is always 0 for mesh mode, and thus pvm_len (referring to the TIM length field) and pad are both incorrectly calculated. Thus, msg_body.beacon_length is incorrectly calculated for mesh mode. Fix this. Signed-off-by: Pontus Fuchs Signed-off-by: Jason Mobarak [bjorn: squashed in Jason's fixup] Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 3 +++ drivers/net/wireless/ath/wcn36xx/smd.c | 27 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index d713204f755d..3af16cba3d12 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -54,6 +54,9 @@ /* Default Beacon template size */ #define BEACON_TEMPLATE_SIZE 0x180 +/* Minimum PVM size that the FW expects. See comment in smd.c for details. */ +#define TIM_MIN_PVM_SIZE 6 + /* Param Change Bitmap sent to HAL */ #define PARAM_BCN_INTERVAL_CHANGED (1 << 0) #define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index ff3ed2461a69..089a7e445cd6 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1375,12 +1375,19 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, u16 p2p_off) { struct wcn36xx_hal_send_beacon_req_msg msg_body; - int ret = 0; + int ret = 0, pad, pvm_len; mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); - msg_body.beacon_length = skb_beacon->len; + pvm_len = skb_beacon->data[tim_off + 1] - 3; + pad = TIM_MIN_PVM_SIZE - pvm_len; + + /* Padding is irrelevant to mesh mode since tim_off is always 0. */ + if (vif->type == NL80211_IFTYPE_MESH_POINT) + pad = 0; + + msg_body.beacon_length = skb_beacon->len + pad; /* TODO need to find out why + 6 is needed */ msg_body.beacon_length6 = msg_body.beacon_length + 6; @@ -1393,6 +1400,22 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len); memcpy(msg_body.bssid, vif->addr, ETH_ALEN); + if (pad > 0) { + /* + * The wcn36xx FW has a fixed size for the PVM in the TIM. If + * given the beacon template from mac80211 with a PVM shorter + * than the FW expectes it will overwrite the data after the + * TIM. + */ + wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n", + pad, pvm_len); + memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad], + &msg_body.beacon[tim_off + 5 + pvm_len], + skb_beacon->len - (tim_off + 5 + pvm_len)); + memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad); + msg_body.beacon[tim_off + 1] += pad; + } + /* TODO need to find out why this is needed? */ if (vif->type == NL80211_IFTYPE_MESH_POINT) /* mesh beacon don't need this, so push further down */ -- GitLab From ce75877f6c3da01cd5efe41683dd32beee1b4b33 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:41 -0700 Subject: [PATCH 4231/9938] wcn36xx: Add helper macros to cast vif to private vif and vice versa Makes the code a little easier to read. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/debug.c | 12 +++-------- drivers/net/wireless/ath/wcn36xx/main.c | 16 +++++++-------- drivers/net/wireless/ath/wcn36xx/pmc.c | 4 ++-- drivers/net/wireless/ath/wcn36xx/smd.c | 24 +++++++++------------- drivers/net/wireless/ath/wcn36xx/txrx.c | 8 ++------ drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 12 +++++++++++ 6 files changed, 36 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c b/drivers/net/wireless/ath/wcn36xx/debug.c index ef44a2da644d..2a6bb62e785c 100644 --- a/drivers/net/wireless/ath/wcn36xx/debug.c +++ b/drivers/net/wireless/ath/wcn36xx/debug.c @@ -33,9 +33,7 @@ static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf, char buf[3]; list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (NL80211_IFTYPE_STATION == vif->type) { if (vif_priv->pw_state == WCN36XX_BMPS) buf[0] = '1'; @@ -70,9 +68,7 @@ static ssize_t write_file_bool_bmps(struct file *file, case 'Y': case '1': list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (NL80211_IFTYPE_STATION == vif->type) { wcn36xx_enable_keep_alive_null_packet(wcn, vif); wcn36xx_pmc_enter_bmps_state(wcn, vif); @@ -83,9 +79,7 @@ static ssize_t write_file_bool_bmps(struct file *file, case 'N': case '0': list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (NL80211_IFTYPE_STATION == vif->type) wcn36xx_pmc_exit_bmps_state(wcn, vif); } diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index a27279c2c695..62cb9ffd854c 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -346,9 +346,7 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", ch); list_for_each_entry(tmp, &wcn->vif_list, list) { - vif = container_of((void *)tmp, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(tmp); wcn36xx_smd_switch_channel(wcn, vif, ch); } } @@ -387,7 +385,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key_conf) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = vif_priv->sta; int ret = 0; u8 key[WLAN_MAX_KEY_LEN]; @@ -590,7 +588,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, struct sk_buff *skb = NULL; u16 tim_off, tim_len; enum wcn36xx_hal_link_state link_state; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", vif, changed); @@ -757,7 +755,7 @@ static void wcn36xx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); list_del(&vif_priv->list); @@ -768,7 +766,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", vif, vif->type); @@ -792,7 +790,7 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", vif, sta->addr); @@ -817,7 +815,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c index 28b515c81b0e..589fe5f70971 100644 --- a/drivers/net/wireless/ath/wcn36xx/pmc.c +++ b/drivers/net/wireless/ath/wcn36xx/pmc.c @@ -22,7 +22,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, struct ieee80211_vif *vif) { int ret = 0; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); /* TODO: Make sure the TX chain clean */ ret = wcn36xx_smd_enter_bmps(wcn, vif); if (!ret) { @@ -42,7 +42,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, struct ieee80211_vif *vif) { - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); if (WCN36XX_BMPS != vif_priv->pw_state) { wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 089a7e445cd6..cc1b3b7a4ff9 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -191,7 +191,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct ieee80211_sta *sta, struct wcn36xx_hal_config_sta_params *sta_params) { - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *priv_sta = NULL; if (vif->type == NL80211_IFTYPE_ADHOC || vif->type == NL80211_IFTYPE_AP || @@ -726,7 +726,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, size_t len) { struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -1175,7 +1175,7 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, { struct wcn36xx_hal_config_bss_rsp_msg *rsp; struct wcn36xx_hal_config_bss_rsp_params *params; - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -1217,7 +1217,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct wcn36xx_hal_config_bss_req_msg msg; struct wcn36xx_hal_config_bss_params *bss; struct wcn36xx_hal_config_sta_params *sta_params; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1343,7 +1343,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_delete_bss_req_msg msg_body; - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1633,7 +1633,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_enter_bmps_req_msg msg_body; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1663,7 +1663,7 @@ int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_enter_bmps_req_msg msg_body; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1724,7 +1724,7 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, int packet_type) { struct wcn36xx_hal_keep_alive_req_msg msg_body; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -2027,9 +2027,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, list_for_each_entry(tmp, &wcn->vif_list, list) { wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", tmp->bss_index); - vif = container_of((void *)tmp, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(tmp); ieee80211_connection_loss(vif); } return 0; @@ -2044,9 +2042,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, if (tmp->bss_index == rsp->bss_index) { wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", rsp->bss_index); - vif = container_of((void *)tmp, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(tmp); ieee80211_connection_loss(vif); return 0; } diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 99c21aac68bd..b12c89b5940a 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -102,9 +102,7 @@ static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, struct wcn36xx_vif *vif_priv = NULL; struct ieee80211_vif *vif = NULL; list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (memcmp(vif->addr, addr, ETH_ALEN) == 0) return vif_priv; } @@ -167,9 +165,7 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, */ if (sta_priv) { __vif_priv = sta_priv->vif; - vif = container_of((void *)__vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(__vif_priv); bd->dpu_sign = sta_priv->ucast_dpu_sign; if (vif->type == NL80211_IFTYPE_STATION) { diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 7b41e833e18c..c3ba07ed1db5 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -263,4 +263,16 @@ struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv) return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv); } +static inline +struct wcn36xx_vif *wcn36xx_vif_to_priv(struct ieee80211_vif *vif) +{ + return (struct wcn36xx_vif *) vif->drv_priv; +} + +static inline +struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv) +{ + return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv); +} + #endif /* _WCN36XX_H_ */ -- GitLab From 657a49be13eda5a3befc161d1d499d413c348762 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:42 -0700 Subject: [PATCH 4232/9938] wcn36xx: Use consistent name for private vif Some code used priv_vif and some used vif_priv. Convert all to vif_priv for consistency. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index cc1b3b7a4ff9..170440ed5d85 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -191,7 +191,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct ieee80211_sta *sta, struct wcn36xx_hal_config_sta_params *sta_params) { - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *priv_sta = NULL; if (vif->type == NL80211_IFTYPE_ADHOC || vif->type == NL80211_IFTYPE_AP || @@ -215,7 +215,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, else memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); - sta_params->encrypt_type = priv_vif->encrypt_type; + sta_params->encrypt_type = vif_priv->encrypt_type; sta_params->short_preamble_supported = true; sta_params->rifs_mode = 0; @@ -224,7 +224,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sta_params->uapsd = 0; sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; sta_params->max_ampdu_duration = 0; - sta_params->bssid_index = priv_vif->bss_index; + sta_params->bssid_index = vif_priv->bss_index; sta_params->p2p = 0; if (sta) { @@ -726,7 +726,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, size_t len) { struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -743,8 +743,8 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, "hal add sta self status %d self_sta_index %d dpu_index %d\n", rsp->status, rsp->self_sta_index, rsp->dpu_index); - priv_vif->self_sta_index = rsp->self_sta_index; - priv_vif->self_dpu_desc_index = rsp->dpu_index; + vif_priv->self_sta_index = rsp->self_sta_index; + vif_priv->self_dpu_desc_index = rsp->dpu_index; return 0; } @@ -1175,7 +1175,7 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, { struct wcn36xx_hal_config_bss_rsp_msg *rsp; struct wcn36xx_hal_config_bss_rsp_params *params; - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -1198,14 +1198,14 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, params->bss_bcast_sta_idx, params->mac, params->tx_mgmt_power, params->ucast_dpu_signature); - priv_vif->bss_index = params->bss_index; + vif_priv->bss_index = params->bss_index; - if (priv_vif->sta) { - priv_vif->sta->bss_sta_index = params->bss_sta_index; - priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; + if (vif_priv->sta) { + vif_priv->sta->bss_sta_index = params->bss_sta_index; + vif_priv->sta->bss_dpu_desc_index = params->dpu_desc_index; } - priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature; + vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature; return 0; } @@ -1343,13 +1343,13 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_delete_bss_req_msg msg_body; - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); - msg_body.bss_index = priv_vif->bss_index; + msg_body.bss_index = vif_priv->bss_index; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); -- GitLab From 90023c034fefe51cf67c719065434b0e43e9baf9 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:43 -0700 Subject: [PATCH 4233/9938] wcn36xx: Use define for invalid index and fix typo Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 2 +- drivers/net/wireless/ath/wcn36xx/main.c | 4 ++-- drivers/net/wireless/ath/wcn36xx/smd.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 3af16cba3d12..433d9801a0ae 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -48,7 +48,7 @@ #define WCN36XX_HAL_IPV4_ADDR_LEN 4 -#define WALN_HAL_STA_INVALID_IDX 0xFF +#define WCN36XX_HAL_STA_INVALID_IDX 0xFF #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF /* Default Beacon template size */ diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 62cb9ffd854c..4781b5e8deb3 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -618,7 +618,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, if (!is_zero_ether_addr(bss_conf->bssid)) { vif_priv->is_joining = true; - vif_priv->bss_index = 0xff; + vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; wcn36xx_smd_join(wcn, bss_conf->bssid, vif->addr, WCN36XX_HW_CHANNEL(wcn)); wcn36xx_smd_config_bss(wcn, vif, NULL, @@ -711,7 +711,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, if (bss_conf->enable_beacon) { vif_priv->dtim_period = bss_conf->dtim_period; - vif_priv->bss_index = 0xff; + vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; wcn36xx_smd_config_bss(wcn, vif, NULL, vif->addr, false); skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 170440ed5d85..6d4aa9250ca8 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -197,7 +197,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT) { sta_params->type = 1; - sta_params->sta_index = 0xFF; + sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX; } else { sta_params->type = 0; sta_params->sta_index = 1; -- GitLab From a92e4696292199714d47d8e52c4bf0318324f77f Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:44 -0700 Subject: [PATCH 4234/9938] wcn36xx: Add helper macros to cast sta to priv While poking at this I also change two related things. I rename one variable to make the names consistent. I also move one assignment of priv_sta to the declaration to save a few lines. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 14 ++++++-------- drivers/net/wireless/ath/wcn36xx/smd.c | 12 ++++++------ drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 6 ++++++ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 4781b5e8deb3..30f015d3a9e6 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -373,7 +373,7 @@ static void wcn36xx_tx(struct ieee80211_hw *hw, struct wcn36xx_sta *sta_priv = NULL; if (control->sta) - sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; + sta_priv = wcn36xx_sta_to_priv(control->sta); if (wcn36xx_start_tx(wcn, sta_priv, skb)) ieee80211_free_txskb(wcn->hw, skb); @@ -518,7 +518,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, { int i, size; u16 *rates_table; - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); u32 rates = sta->supp_rates[band]; memset(&sta_priv->supported_rates, 0, @@ -661,7 +661,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, rcu_read_unlock(); goto out; } - sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); @@ -791,7 +791,7 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wcn36xx *wcn = hw->priv; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", vif, sta->addr); @@ -816,7 +816,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw, { struct wcn36xx *wcn = hw->priv; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", vif, sta->addr, sta_priv->sta_index); @@ -858,7 +858,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_ampdu_params *params) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_sta *sta_priv = NULL; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta); struct ieee80211_sta *sta = params->sta; enum ieee80211_ampdu_mlme_action action = params->action; u16 tid = params->tid; @@ -867,8 +867,6 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); - sta_priv = (struct wcn36xx_sta *)sta->drv_priv; - switch (action) { case IEEE80211_AMPDU_RX_START: sta_priv->tid = tid; diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 6d4aa9250ca8..ff56138528b6 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -192,7 +192,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct wcn36xx_hal_config_sta_params *sta_params) { struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *priv_sta = NULL; + struct wcn36xx_sta *sta_priv = NULL; if (vif->type == NL80211_IFTYPE_ADHOC || vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT) { @@ -228,17 +228,17 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sta_params->p2p = 0; if (sta) { - priv_sta = (struct wcn36xx_sta *)sta->drv_priv; + sta_priv = wcn36xx_sta_to_priv(sta); if (NL80211_IFTYPE_STATION == vif->type) memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); else memcpy(&sta_params->mac, sta->addr, ETH_ALEN); sta_params->wmm_enabled = sta->wme; sta_params->max_sp_len = sta->max_sp; - sta_params->aid = priv_sta->aid; + sta_params->aid = sta_priv->aid; wcn36xx_smd_set_sta_ht_params(sta, sta_params); - memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, - sizeof(priv_sta->supported_rates)); + memcpy(&sta_params->supported_rates, &sta_priv->supported_rates, + sizeof(sta_priv->supported_rates)); } else { wcn36xx_set_default_rates(&sta_params->supported_rates); wcn36xx_smd_set_sta_default_ht_params(sta_params); @@ -969,7 +969,7 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, { struct wcn36xx_hal_config_sta_rsp_msg *rsp; struct config_sta_rsp_params *params; - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); if (len < sizeof(*rsp)) return -EINVAL; diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index c3ba07ed1db5..c368a34c8de7 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -275,4 +275,10 @@ struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv) return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv); } +static inline +struct wcn36xx_sta *wcn36xx_sta_to_priv(struct ieee80211_sta *sta) +{ + return (struct wcn36xx_sta *)sta->drv_priv; +} + #endif /* _WCN36XX_H_ */ -- GitLab From 81c69263757788d77537fefdd9a55b05ed83c87b Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:45 -0700 Subject: [PATCH 4235/9938] wcn36xx: Fetch private sta data from sta entry instead of from vif For consistency with other code. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 30f015d3a9e6..a23738deb5b3 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -386,7 +386,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct wcn36xx *wcn = hw->priv; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *sta_priv = vif_priv->sta; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); int ret = 0; u8 key[WLAN_MAX_KEY_LEN]; -- GitLab From 25a44da26f2901308440a047b27a3a0054ea4a71 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:46 -0700 Subject: [PATCH 4236/9938] wcn36xx: Remove sta pointer in private vif struct This does not work with multiple sta's in a vif. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 3 --- drivers/net/wireless/ath/wcn36xx/smd.c | 28 ++++++++++++---------- drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 - 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index a23738deb5b3..7c06ca9fdd2c 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -796,7 +796,6 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, vif, sta->addr); spin_lock_init(&sta_priv->ampdu_lock); - vif_priv->sta = sta_priv; sta_priv->vif = vif_priv; /* * For STA mode HW will be configured on BSS_CHANGED_ASSOC because @@ -815,14 +814,12 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", vif, sta->addr, sta_priv->sta_index); wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); - vif_priv->sta = NULL; sta_priv->vif = NULL; return 0; } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index ff56138528b6..76c6856ed932 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1170,6 +1170,7 @@ static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, void *buf, size_t len) { @@ -1200,9 +1201,10 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, vif_priv->bss_index = params->bss_index; - if (vif_priv->sta) { - vif_priv->sta->bss_sta_index = params->bss_sta_index; - vif_priv->sta->bss_dpu_desc_index = params->dpu_desc_index; + if (sta) { + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); + sta_priv->bss_sta_index = params->bss_sta_index; + sta_priv->bss_dpu_desc_index = params->dpu_desc_index; } vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature; @@ -1329,6 +1331,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, } ret = wcn36xx_smd_config_bss_rsp(wcn, vif, + sta, wcn->hal_buf, wcn->hal_rsp_len); if (ret) { @@ -2058,25 +2061,24 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, { struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; struct wcn36xx_vif *tmp; - struct ieee80211_sta *sta = NULL; + struct ieee80211_sta *sta; if (len != sizeof(*rsp)) { wcn36xx_warn("Corrupted delete sta indication\n"); return -EIO; } + wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n", + rsp->addr2, rsp->sta_id); + list_for_each_entry(tmp, &wcn->vif_list, list) { - if (sta && (tmp->sta->sta_index == rsp->sta_id)) { - sta = container_of((void *)tmp->sta, - struct ieee80211_sta, - drv_priv); - wcn36xx_dbg(WCN36XX_DBG_HAL, - "delete station indication %pM index %d\n", - rsp->addr2, - rsp->sta_id); + rcu_read_lock(); + sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2); + if (sta) ieee80211_report_low_ack(sta, 0); + rcu_read_unlock(); + if (sta) return 0; - } } wcn36xx_warn("STA with addr %pM and index %d not found\n", diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index c368a34c8de7..54000db0af1a 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -125,7 +125,6 @@ struct wcn36xx_platform_ctrl_ops { */ struct wcn36xx_vif { struct list_head list; - struct wcn36xx_sta *sta; u8 dtim_period; enum ani_ed_type encrypt_type; bool is_joining; -- GitLab From 16be1ac55944412e8d132b1db26f994b368c5742 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:47 -0700 Subject: [PATCH 4237/9938] wcn36xx: Parse trigger_ba response properly This message does not follow the canonical format and needs it's own parser. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 76c6856ed932..7f315d098f52 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1968,6 +1968,17 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) return ret; } +static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len) +{ + struct wcn36xx_hal_trigger_ba_rsp_msg *rsp; + + if (len < sizeof(*rsp)) + return -EINVAL; + + rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf; + return rsp->status; +} + int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) { struct wcn36xx_hal_trigger_ba_req_msg msg_body; @@ -1992,8 +2003,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) wcn36xx_err("Sending hal_trigger_ba failed\n"); goto out; } - ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf, - wcn->hal_rsp_len); + ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len); if (ret) { wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); goto out; -- GitLab From df98c3294bdf1fc3094f5466accf6423ce968a74 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:48 -0700 Subject: [PATCH 4238/9938] wcn36xx: Copy all members in config_sta v1 conversion When converting to version 1 of the config_sta struct not all members where copied. This fixes the problem of multicast frames not being delivered on an encrypted network. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 7f315d098f52..ebb446272d21 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -949,17 +949,32 @@ static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, memcpy(&v1->mac, orig->mac, ETH_ALEN); v1->aid = orig->aid; v1->type = orig->type; + v1->short_preamble_supported = orig->short_preamble_supported; v1->listen_interval = orig->listen_interval; + v1->wmm_enabled = orig->wmm_enabled; v1->ht_capable = orig->ht_capable; - + v1->tx_channel_width_set = orig->tx_channel_width_set; + v1->rifs_mode = orig->rifs_mode; + v1->lsig_txop_protection = orig->lsig_txop_protection; v1->max_ampdu_size = orig->max_ampdu_size; v1->max_ampdu_density = orig->max_ampdu_density; v1->sgi_40mhz = orig->sgi_40mhz; v1->sgi_20Mhz = orig->sgi_20Mhz; - + v1->rmf = orig->rmf; + v1->encrypt_type = orig->encrypt_type; + v1->action = orig->action; + v1->uapsd = orig->uapsd; + v1->max_sp_len = orig->max_sp_len; + v1->green_field_capable = orig->green_field_capable; + v1->mimo_ps = orig->mimo_ps; + v1->delayed_ba_support = orig->delayed_ba_support; + v1->max_ampdu_duration = orig->max_ampdu_duration; + v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz; memcpy(&v1->supported_rates, &orig->supported_rates, sizeof(orig->supported_rates)); v1->sta_index = orig->sta_index; + v1->bssid_index = orig->bssid_index; + v1->p2p = orig->p2p; } static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, -- GitLab From 6d9cf123cd79277c65605faff8d25dbdd1b6ca64 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:49 -0700 Subject: [PATCH 4239/9938] wcn36xx: Use allocated self sta index instead of hard coded Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index ebb446272d21..e0d5631657c1 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -200,7 +200,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX; } else { sta_params->type = 0; - sta_params->sta_index = 1; + sta_params->sta_index = vif_priv->self_sta_index; } sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); -- GitLab From 2716a8ac655f17d17a7040f99f306a6244b08802 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:50 -0700 Subject: [PATCH 4240/9938] wcn36xx: Clear encrypt_type when deleting bss key This fixes a problem connecting to an open network after being connected to an encrypted network. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7c06ca9fdd2c..f9c77de94583 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -471,6 +471,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case DISABLE_KEY: if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { + vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE; wcn36xx_smd_remove_bsskey(wcn, vif_priv->encrypt_type, key_conf->keyidx); @@ -626,6 +627,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, } else { vif_priv->is_joining = false; wcn36xx_smd_delete_bss(wcn, vif); + vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE; } } -- GitLab From 043ce546190243bd9de05dbb6c82c9099b01a3a2 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:51 -0700 Subject: [PATCH 4241/9938] wcn36xx: Track association state Knowing the association state is needed for mc filtering. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 ++ drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index f9c77de94583..253cece1b660 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -655,6 +655,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, vif->addr, bss_conf->aid); + vif_priv->sta_assoc = true; rcu_read_lock(); sta = ieee80211_find_sta(vif, bss_conf->bssid); if (!sta) { @@ -686,6 +687,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, bss_conf->bssid, vif->addr, bss_conf->aid); + vif_priv->sta_assoc = false; wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr, diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 54000db0af1a..7433d67a5929 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -128,6 +128,7 @@ struct wcn36xx_vif { u8 dtim_period; enum ani_ed_type encrypt_type; bool is_joining; + bool sta_assoc; struct wcn36xx_hal_mac_ssid ssid; /* Power management */ -- GitLab From 20a779ede344a0b9778b7d5d9af76453d14474fc Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:52 -0700 Subject: [PATCH 4242/9938] wcn36xx: Implement multicast filtering Pass the multicast list to FW. This patch also adds a way to build the smd command in place. This is needed because the MC list command is too big for the stack. Signed-off-by: Pontus Fuchs [bjorn: dropped FIF_PROMISC_IN_BSS usage] Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 6 +-- drivers/net/wireless/ath/wcn36xx/main.c | 50 ++++++++++++++++++++++-- drivers/net/wireless/ath/wcn36xx/smd.c | 51 +++++++++++++++++++++++++ drivers/net/wireless/ath/wcn36xx/smd.h | 3 ++ 4 files changed, 104 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 433d9801a0ae..ec64c47f918b 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -4267,9 +4267,9 @@ struct wcn36xx_hal_rcv_flt_mc_addr_list_type { u8 data_offset; u32 mc_addr_count; - u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS]; + u8 mc_addr[WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS][ETH_ALEN]; u8 bss_index; -}; +} __packed; struct wcn36xx_hal_set_pkt_filter_rsp_msg { struct wcn36xx_hal_msg_header header; @@ -4323,7 +4323,7 @@ struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg { struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg { struct wcn36xx_hal_msg_header header; struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list; -}; +} __packed; struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 253cece1b660..c0ba7b0775b3 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -287,6 +287,7 @@ static int wcn36xx_start(struct ieee80211_hw *hw) } wcn36xx_detect_chip_version(wcn); + wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1); /* DMA channel initialization */ ret = wcn36xx_dxe_init(wcn); @@ -354,15 +355,57 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) return 0; } -#define WCN36XX_SUPPORTED_FILTERS (0) - static void wcn36xx_configure_filter(struct ieee80211_hw *hw, unsigned int changed, unsigned int *total, u64 multicast) { + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp; + struct wcn36xx *wcn = hw->priv; + struct wcn36xx_vif *tmp; + struct ieee80211_vif *vif = NULL; + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); - *total &= WCN36XX_SUPPORTED_FILTERS; + *total &= FIF_ALLMULTI; + + fp = (void *)(unsigned long)multicast; + list_for_each_entry(tmp, &wcn->vif_list, list) { + vif = wcn36xx_priv_to_vif(tmp); + + /* FW handles MC filtering only when connected as STA */ + if (*total & FIF_ALLMULTI) + wcn36xx_smd_set_mc_list(wcn, vif, NULL); + else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc) + wcn36xx_smd_set_mc_list(wcn, vif, fp); + } + kfree(fp); +} + +static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) +{ + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp; + struct netdev_hw_addr *ha; + + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n"); + fp = kzalloc(sizeof(*fp), GFP_ATOMIC); + if (!fp) { + wcn36xx_err("Out of memory setting filters.\n"); + return 0; + } + + fp->mc_addr_count = 0; + /* update multicast filtering parameters */ + if (netdev_hw_addr_list_count(mc_list) <= + WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) { + netdev_hw_addr_list_for_each(ha, mc_list) { + memcpy(fp->mc_addr[fp->mc_addr_count], + ha->addr, ETH_ALEN); + fp->mc_addr_count++; + } + } + + return (u64)(unsigned long)fp; } static void wcn36xx_tx(struct ieee80211_hw *hw, @@ -920,6 +963,7 @@ static const struct ieee80211_ops wcn36xx_ops = { .resume = wcn36xx_resume, #endif .config = wcn36xx_config, + .prepare_multicast = wcn36xx_prepare_multicast, .configure_filter = wcn36xx_configure_filter, .tx = wcn36xx_tx, .set_key = wcn36xx_set_key, diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index e0d5631657c1..b1bdc229e560 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -271,6 +271,16 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) return ret; } +static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, + enum wcn36xx_hal_host_msg_type msg_type, + size_t msg_size) +{ + memset(hdr, 0, msg_size + sizeof(*hdr)); + hdr->msg_type = msg_type; + hdr->msg_version = WCN36XX_HAL_MSG_VERSION0; + hdr->len = msg_size + sizeof(*hdr); +} + #define INIT_HAL_MSG(msg_body, type) \ do { \ memset(&msg_body, 0, sizeof(msg_body)); \ @@ -2144,6 +2154,46 @@ int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) mutex_unlock(&wcn->hal_mutex); return ret; } + +int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp) +{ + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); + struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL; + int ret = 0; + + mutex_lock(&wcn->hal_mutex); + + msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *) + wcn->hal_buf; + init_hal_msg(&msg_body->header, WCN36XX_HAL_8023_MULTICAST_LIST_REQ, + sizeof(msg_body->mc_addr_list)); + + /* An empty list means all mc traffic will be received */ + if (fp) + memcpy(&msg_body->mc_addr_list, fp, + sizeof(msg_body->mc_addr_list)); + else + msg_body->mc_addr_list.mc_addr_count = 0; + + msg_body->mc_addr_list.bss_index = vif_priv->bss_index; + + ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); + if (ret) { + wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n"); + goto out; + } + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); + if (ret) { + wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret); + goto out; + } +out: + mutex_unlock(&wcn->hal_mutex); + return ret; +} + static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) { struct wcn36xx_hal_msg_header *msg_header = buf; @@ -2185,6 +2235,7 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: case WCN36XX_HAL_CH_SWITCH_RSP: case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: + case WCN36XX_HAL_8023_MULTICAST_LIST_RSP: memcpy(wcn->hal_buf, buf, len); wcn->hal_rsp_len = len; complete(&wcn->hal_rsp_compl); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index 8361f9e3995b..c1b76d75cf85 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -136,4 +136,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); +int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp); #endif /* _SMD_H_ */ -- GitLab From 6770559b8f614d3569ced7a7e3a8e846115e77af Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:53 -0700 Subject: [PATCH 4243/9938] wcn36xx: Use correct command struct for EXIT_BMPS_REQ EXIT_BMPS_REQ was using the command struct for ENTER_BMPS_REQ. I spotted this when looking at command dumps. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index b1bdc229e560..c15501c06eb2 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1690,7 +1690,7 @@ int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) { - struct wcn36xx_hal_enter_bmps_req_msg msg_body; + struct wcn36xx_hal_exit_bmps_req_msg msg_body; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; -- GitLab From 5443918d050a1a1e5766544e3b895e98671adeef Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 18 Apr 2016 22:00:54 -0700 Subject: [PATCH 4244/9938] wcn36xx: Delete BSS before idling link When disabling the beacon we must delete the bss before idling the link. Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index c0ba7b0775b3..680217506b3d 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -779,9 +779,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, link_state); } else { + wcn36xx_smd_delete_bss(wcn, vif); wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, WCN36XX_HAL_LINK_IDLE_STATE); - wcn36xx_smd_delete_bss(wcn, vif); } } out: -- GitLab From 23c2aabb93c9c8efb7b8991707e2db59f7346783 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 18 Apr 2016 22:00:55 -0700 Subject: [PATCH 4245/9938] wcn36xx: Correct remove bss key response encoding The WCN36XX_HAL_RMV_BSSKEY_RSP carries a single u32 with "status", so we can use the standard status check function for decoding the result. This is the last user of the v2 status checker, so remove the struct and helper function. Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 19 +------------------ drivers/net/wireless/ath/wcn36xx/smd.h | 9 --------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index c15501c06eb2..5f6ca3124bd8 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -312,22 +312,6 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) return 0; } -static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf, - size_t len) -{ - struct wcn36xx_fw_msg_status_rsp_v2 *rsp; - - if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp)) - return wcn36xx_smd_rsp_status_check(buf, len); - - rsp = buf + sizeof(struct wcn36xx_hal_msg_header); - - if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) - return rsp->status; - - return 0; -} - int wcn36xx_smd_load_nv(struct wcn36xx *wcn) { struct nv_data *nv_d; @@ -1647,8 +1631,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, wcn36xx_err("Sending hal_remove_bsskey failed\n"); goto out; } - ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf, - wcn->hal_rsp_len); + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); if (ret) { wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); goto out; diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index c1b76d75cf85..d74d781f4c8d 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -44,15 +44,6 @@ struct wcn36xx_fw_msg_status_rsp { u32 status; } __packed; -/* wcn3620 returns this for tigger_ba */ - -struct wcn36xx_fw_msg_status_rsp_v2 { - u8 bss_id[6]; - u32 status __packed; - u16 count_following_candidates __packed; - /* candidate list follows */ -}; - struct wcn36xx_hal_ind_msg { struct list_head list; u8 *msg; -- GitLab From ffc03c331a1e7cafac3beb4f89c40fa7d6213d6e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 18 Apr 2016 22:00:56 -0700 Subject: [PATCH 4246/9938] wcn36xx: Fill in capability list Fill in the capability list with more values from the downstream driver. Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 39 ++++++++++++++++++++++++ drivers/net/wireless/ath/wcn36xx/main.c | 40 ++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index ec64c47f918b..658bfb8baabe 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -4389,6 +4389,45 @@ enum place_holder_in_cap_bitmap { RTT = 20, RATECTRL = 21, WOW = 22, + WLAN_ROAM_SCAN_OFFLOAD = 23, + SPECULATIVE_PS_POLL = 24, + SCAN_SCH = 25, + IBSS_HEARTBEAT_OFFLOAD = 26, + WLAN_SCAN_OFFLOAD = 27, + WLAN_PERIODIC_TX_PTRN = 28, + ADVANCE_TDLS = 29, + BATCH_SCAN = 30, + FW_IN_TX_PATH = 31, + EXTENDED_NSOFFLOAD_SLOT = 32, + CH_SWITCH_V1 = 33, + HT40_OBSS_SCAN = 34, + UPDATE_CHANNEL_LIST = 35, + WLAN_MCADDR_FLT = 36, + WLAN_CH144 = 37, + NAN = 38, + TDLS_SCAN_COEXISTENCE = 39, + LINK_LAYER_STATS_MEAS = 40, + MU_MIMO = 41, + EXTENDED_SCAN = 42, + DYNAMIC_WMM_PS = 43, + MAC_SPOOFED_SCAN = 44, + BMU_ERROR_GENERIC_RECOVERY = 45, + DISA = 46, + FW_STATS = 47, + WPS_PRBRSP_TMPL = 48, + BCN_IE_FLT_DELTA = 49, + TDLS_OFF_CHANNEL = 51, + RTT3 = 52, + MGMT_FRAME_LOGGING = 53, + ENHANCED_TXBD_COMPLETION = 54, + LOGGING_ENHANCEMENT = 55, + EXT_SCAN_ENHANCED = 56, + MEMORY_DUMP_SUPPORTED = 57, + PER_PKT_STATS_SUPPORTED = 58, + EXT_LL_STAT = 60, + WIFI_CONFIG = 61, + ANTENNA_DIVERSITY_SELECTION = 62, + MAX_FEATURE_SUPPORTED = 128, }; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 680217506b3d..fe81b2a7c8d9 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -201,7 +201,45 @@ static const char * const wcn36xx_caps_names[] = { "BCN_FILTER", /* 19 */ "RTT", /* 20 */ "RATECTRL", /* 21 */ - "WOW" /* 22 */ + "WOW", /* 22 */ + "WLAN_ROAM_SCAN_OFFLOAD", /* 23 */ + "SPECULATIVE_PS_POLL", /* 24 */ + "SCAN_SCH", /* 25 */ + "IBSS_HEARTBEAT_OFFLOAD", /* 26 */ + "WLAN_SCAN_OFFLOAD", /* 27 */ + "WLAN_PERIODIC_TX_PTRN", /* 28 */ + "ADVANCE_TDLS", /* 29 */ + "BATCH_SCAN", /* 30 */ + "FW_IN_TX_PATH", /* 31 */ + "EXTENDED_NSOFFLOAD_SLOT", /* 32 */ + "CH_SWITCH_V1", /* 33 */ + "HT40_OBSS_SCAN", /* 34 */ + "UPDATE_CHANNEL_LIST", /* 35 */ + "WLAN_MCADDR_FLT", /* 36 */ + "WLAN_CH144", /* 37 */ + "NAN", /* 38 */ + "TDLS_SCAN_COEXISTENCE", /* 39 */ + "LINK_LAYER_STATS_MEAS", /* 40 */ + "MU_MIMO", /* 41 */ + "EXTENDED_SCAN", /* 42 */ + "DYNAMIC_WMM_PS", /* 43 */ + "MAC_SPOOFED_SCAN", /* 44 */ + "BMU_ERROR_GENERIC_RECOVERY", /* 45 */ + "DISA", /* 46 */ + "FW_STATS", /* 47 */ + "WPS_PRBRSP_TMPL", /* 48 */ + "BCN_IE_FLT_DELTA", /* 49 */ + "TDLS_OFF_CHANNEL", /* 51 */ + "RTT3", /* 52 */ + "MGMT_FRAME_LOGGING", /* 53 */ + "ENHANCED_TXBD_COMPLETION", /* 54 */ + "LOGGING_ENHANCEMENT", /* 55 */ + "EXT_SCAN_ENHANCED", /* 56 */ + "MEMORY_DUMP_SUPPORTED", /* 57 */ + "PER_PKT_STATS_SUPPORTED", /* 58 */ + "EXT_LL_STAT", /* 60 */ + "WIFI_CONFIG", /* 61 */ + "ANTENNA_DIVERSITY_SELECTION", /* 62 */ }; static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x) -- GitLab From afcd666d9db0ebfbf2751cce1e07b548547ca82e Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Mon, 25 Apr 2016 15:20:43 +0200 Subject: [PATCH 4247/9938] regulator: rk808: remove linear range definitions with a single range The driver was using only linear ranges. Now we remove linear range definitions with a single range. So we have to add an ops struct for ranges and adjust all other ops functions accordingly. Signed-off-by: Wadim Egorov Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 90 ++++++++++++++++------------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index d86a3dcd61e2..964b95eed271 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -66,27 +66,11 @@ static const int rk808_buck_config_regs[] = { RK808_BUCK4_CONFIG_REG, }; -static const struct regulator_linear_range rk808_buck_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(712500, 0, 63, 12500), -}; - -static const struct regulator_linear_range rk808_buck4_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(1800000, 0, 15, 100000), -}; - -static const struct regulator_linear_range rk808_ldo_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(1800000, 0, 16, 100000), -}; - static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000), REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0), }; -static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000), -}; - static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); @@ -240,6 +224,21 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) } static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv) +{ + unsigned int reg; + int sel = regulator_map_voltage_linear(rdev, uv, uv); + + if (sel < 0) + return -EINVAL; + + reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->vsel_mask, + sel); +} + +static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) { unsigned int reg; int sel = regulator_map_voltage_linear_range(rdev, uv, uv); @@ -277,8 +276,8 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) } static struct regulator_ops rk808_buck1_2_ops = { - .list_voltage = regulator_list_voltage_linear_range, - .map_voltage = regulator_map_voltage_linear_range, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = rk808_buck1_2_get_voltage_sel_regmap, .set_voltage_sel = rk808_buck1_2_set_voltage_sel, .set_voltage_time_sel = rk808_buck1_2_set_voltage_time_sel, @@ -292,6 +291,19 @@ static struct regulator_ops rk808_buck1_2_ops = { }; static struct regulator_ops rk808_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_voltage = rk808_set_suspend_voltage, + .set_suspend_enable = rk808_set_suspend_enable, + .set_suspend_disable = rk808_set_suspend_disable, +}; + +static struct regulator_ops rk808_reg_ops_ranges = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -299,7 +311,7 @@ static struct regulator_ops rk808_reg_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, - .set_suspend_voltage = rk808_set_suspend_voltage, + .set_suspend_voltage = rk808_set_suspend_voltage_range, .set_suspend_enable = rk808_set_suspend_enable, .set_suspend_disable = rk808_set_suspend_disable, }; @@ -319,9 +331,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_DCDC1, .ops = &rk808_buck1_2_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 712500, + .uV_step = 12500, .n_voltages = 64, - .linear_ranges = rk808_buck_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges), .vsel_reg = RK808_BUCK1_ON_VSEL_REG, .vsel_mask = RK808_BUCK_VSEL_MASK, .enable_reg = RK808_DCDC_EN_REG, @@ -333,9 +345,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_DCDC2, .ops = &rk808_buck1_2_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 712500, + .uV_step = 12500, .n_voltages = 64, - .linear_ranges = rk808_buck_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges), .vsel_reg = RK808_BUCK2_ON_VSEL_REG, .vsel_mask = RK808_BUCK_VSEL_MASK, .enable_reg = RK808_DCDC_EN_REG, @@ -357,9 +369,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_DCDC4, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 1800000, + .uV_step = 100000, .n_voltages = 16, - .linear_ranges = rk808_buck4_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_buck4_voltage_ranges), .vsel_reg = RK808_BUCK4_ON_VSEL_REG, .vsel_mask = RK808_BUCK4_VSEL_MASK, .enable_reg = RK808_DCDC_EN_REG, @@ -371,9 +383,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_LDO1, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 1800000, + .uV_step = 100000, .n_voltages = 17, - .linear_ranges = rk808_ldo_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), .vsel_reg = RK808_LDO1_ON_VSEL_REG, .vsel_mask = RK808_LDO_VSEL_MASK, .enable_reg = RK808_LDO_EN_REG, @@ -386,9 +398,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_LDO2, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 1800000, + .uV_step = 100000, .n_voltages = 17, - .linear_ranges = rk808_ldo_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), .vsel_reg = RK808_LDO2_ON_VSEL_REG, .vsel_mask = RK808_LDO_VSEL_MASK, .enable_reg = RK808_LDO_EN_REG, @@ -416,9 +428,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_LDO4, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 1800000, + .uV_step = 100000, .n_voltages = 17, - .linear_ranges = rk808_ldo_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), .vsel_reg = RK808_LDO4_ON_VSEL_REG, .vsel_mask = RK808_LDO_VSEL_MASK, .enable_reg = RK808_LDO_EN_REG, @@ -431,9 +443,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_LDO5, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 1800000, + .uV_step = 100000, .n_voltages = 17, - .linear_ranges = rk808_ldo_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), .vsel_reg = RK808_LDO5_ON_VSEL_REG, .vsel_mask = RK808_LDO_VSEL_MASK, .enable_reg = RK808_LDO_EN_REG, @@ -446,9 +458,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_LDO6, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 800000, + .uV_step = 100000, .n_voltages = 18, - .linear_ranges = rk808_ldo6_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges), .vsel_reg = RK808_LDO6_ON_VSEL_REG, .vsel_mask = RK808_LDO_VSEL_MASK, .enable_reg = RK808_LDO_EN_REG, @@ -461,9 +473,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_LDO7, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 800000, + .uV_step = 100000, .n_voltages = 18, - .linear_ranges = rk808_ldo6_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges), .vsel_reg = RK808_LDO7_ON_VSEL_REG, .vsel_mask = RK808_LDO_VSEL_MASK, .enable_reg = RK808_LDO_EN_REG, @@ -476,9 +488,9 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_LDO8, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, + .min_uV = 1800000, + .uV_step = 100000, .n_voltages = 17, - .linear_ranges = rk808_ldo_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), .vsel_reg = RK808_LDO8_ON_VSEL_REG, .vsel_mask = RK808_LDO_VSEL_MASK, .enable_reg = RK808_LDO_EN_REG, -- GitLab From 198b618ab118c7d856278a985de1ed0eff77c02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giedrius=20Statkevi=C4=8Dius?= Date: Sat, 16 Apr 2016 03:27:12 +0300 Subject: [PATCH 4248/9938] asus-laptop: correct error handling in asus_read_brightness() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is possible that acpi_evaluate_integer might fail and value would not be set to any value so correct this defect by returning 0 in case of an error. This is also the correct thing to return because the backlight subsystem will print the old value of brightness in this case. Signed-off-by: Giedrius Statkevičius Signed-off-by: Darren Hart --- drivers/platform/x86/asus-laptop.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index f2b5d0a8adf0..a4cd78691ac9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -775,8 +775,10 @@ static int asus_read_brightness(struct backlight_device *bd) rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET, NULL, &value); - if (ACPI_FAILURE(rv)) + if (ACPI_FAILURE(rv)) { pr_warn("Error reading brightness\n"); + return 0; + } return value; } -- GitLab From 2ce6d9932db55cfc09dd6362d6d0d47a361f5f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giedrius=20Statkevi=C4=8Dius?= Date: Sat, 16 Apr 2016 03:01:56 +0300 Subject: [PATCH 4249/9938] asus-laptop: remove redundant initializers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initializing rv to AE_OK is pointless because later function results are assigned to them and only then the variable is used Signed-off-by: Giedrius Statkevičius Acked-by: Andy Shevchenko Signed-off-by: Darren Hart --- drivers/platform/x86/asus-laptop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index a4cd78691ac9..223090c9d433 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -771,7 +771,7 @@ static int asus_read_brightness(struct backlight_device *bd) { struct asus_laptop *asus = bl_get_data(bd); unsigned long long value; - acpi_status rv = AE_OK; + acpi_status rv; rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET, NULL, &value); @@ -867,7 +867,7 @@ static ssize_t infos_show(struct device *dev, struct device_attribute *attr, int len = 0; unsigned long long temp; char buf[16]; /* enough for all info */ - acpi_status rv = AE_OK; + acpi_status rv; /* * We use the easy way, we don't care of off and count, @@ -1267,7 +1267,7 @@ static DEVICE_ATTR_RO(ls_value); static int asus_gps_status(struct asus_laptop *asus) { unsigned long long status; - acpi_status rv = AE_OK; + acpi_status rv; rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS, NULL, &status); -- GitLab From 19d46ee1aec06de3dc1137c76c29e07bfd96d99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giedrius=20Statkevi=C4=8Dius?= Date: Sat, 16 Apr 2016 03:01:57 +0300 Subject: [PATCH 4250/9938] asus-laptop: correct error handling in sysfs_acpi_set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly return rv back to the caller in the case of an error in parse_arg. In the process remove a unused variable 'out'. Signed-off-by: Giedrius Statkevičius Signed-off-by: Darren Hart --- drivers/platform/x86/asus-laptop.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 223090c9d433..15f131146501 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -948,11 +948,10 @@ static ssize_t sysfs_acpi_set(struct asus_laptop *asus, const char *method) { int rv, value; - int out = 0; rv = parse_arg(buf, count, &value); - if (rv > 0) - out = value ? 1 : 0; + if (rv <= 0) + return rv; if (write_acpi_int(asus->handle, method, value)) return -ENODEV; -- GitLab From 7ba2f2757d84eae533679306f03c93c118437a87 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 23 Apr 2016 22:47:08 +0200 Subject: [PATCH 4251/9938] spi: core: add hook flash_read_supported to spi_master If hook spi_flash_read is implemented the fast flash read feature is enabled for all devices attached to the respective master. In most cases there is just one flash chip, however there are also devices with more than one flash chip, namely some WiFi routers. Then the fast flash read feature can be used for the first chip only. OpenWRT implemented an own handling of this case, using controller_data element of spi_device to hold the information whether fast flash read can be used for a device. This patch adds hook flash_read_supported to spi_master which is used to extend spi_flash_read_supported() by checking whether the fast flash read feature can be used for a specific spi_device. If the hook is not implemented the default behavior is to allow fast flash read for all devices (if spi_flash_read is implemented). Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 857a9a1d82b5..1f03483f61e5 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -372,6 +372,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @unprepare_message: undo any work done by prepare_message(). * @spi_flash_read: to support spi-controller hardwares that provide * accelerated interface to read from flash devices. + * @flash_read_supported: spi device supports flash read * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). @@ -529,6 +530,7 @@ struct spi_master { struct spi_message *message); int (*spi_flash_read)(struct spi_device *spi, struct spi_flash_read_message *msg); + bool (*flash_read_supported)(struct spi_device *spi); /* * These hooks are for drivers that use a generic implementation @@ -1158,7 +1160,9 @@ struct spi_flash_read_message { /* SPI core interface for flash read support */ static inline bool spi_flash_read_supported(struct spi_device *spi) { - return spi->master->spi_flash_read ? true : false; + return spi->master->spi_flash_read && + (!spi->master->flash_read_supported || + spi->master->flash_read_supported(spi)); } int spi_flash_read(struct spi_device *spi, -- GitLab From 8a34e979f684aa13e6c4bf23b394cca9dfabf4a9 Mon Sep 17 00:00:00 2001 From: WEN Pingbo Date: Sat, 23 Apr 2016 15:11:05 +0800 Subject: [PATCH 4252/9938] regulator: refactor valid_ops_mask checking code To make the code more compat and centralized, this patch add a unified function - regulator_ops_is_valid. So we can add some extra checking code easily later. Signed-off-by: WEN Pingbo Signed-off-by: Mark Brown --- drivers/regulator/core.c | 88 +++++++++++++--------------------------- 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 18dd7ee61455..bca9167d8c43 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -132,6 +132,19 @@ static bool have_full_constraints(void) return has_full_constraints || of_have_populated_dt(); } +static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops) +{ + if (!rdev->constraints) { + rdev_err(rdev, "no constraints\n"); + return false; + } + + if (rdev->constraints->valid_ops_mask & ops) + return true; + + return false; +} + static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) { if (rdev && rdev->supply) @@ -198,28 +211,13 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp return regnode; } -static int _regulator_can_change_status(struct regulator_dev *rdev) -{ - if (!rdev->constraints) - return 0; - - if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) - return 1; - else - return 0; -} - /* Platform voltage constraint check */ static int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV) { BUG_ON(*min_uV > *max_uV); - if (!rdev->constraints) { - rdev_err(rdev, "no constraints\n"); - return -ENODEV; - } - if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { rdev_err(rdev, "voltage operation not allowed\n"); return -EPERM; } @@ -275,11 +273,7 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, { BUG_ON(*min_uA > *max_uA); - if (!rdev->constraints) { - rdev_err(rdev, "no constraints\n"); - return -ENODEV; - } - if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { rdev_err(rdev, "current operation not allowed\n"); return -EPERM; } @@ -312,11 +306,7 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) return -EINVAL; } - if (!rdev->constraints) { - rdev_err(rdev, "no constraints\n"); - return -ENODEV; - } - if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { rdev_err(rdev, "mode operation not allowed\n"); return -EPERM; } @@ -333,20 +323,6 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) return -EINVAL; } -/* dynamic regulator mode switching constraint check */ -static int regulator_check_drms(struct regulator_dev *rdev) -{ - if (!rdev->constraints) { - rdev_err(rdev, "no constraints\n"); - return -ENODEV; - } - if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { - rdev_dbg(rdev, "drms operation not allowed\n"); - return -EPERM; - } - return 0; -} - static ssize_t regulator_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -692,8 +668,7 @@ static int drms_uA_update(struct regulator_dev *rdev) * first check to see if we can set modes at all, otherwise just * tell the consumer everything is OK. */ - err = regulator_check_drms(rdev); - if (err < 0) + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) return 0; if (!rdev->desc->ops->get_optimum_mode && @@ -893,7 +868,7 @@ static void print_constraints(struct regulator_dev *rdev) rdev_dbg(rdev, "%s\n", buf); if ((constraints->min_uV != constraints->max_uV) && - !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) + !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) rdev_warn(rdev, "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); } @@ -1354,7 +1329,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, * it is then we don't need to do nearly so much work for * enable/disable calls. */ - if (!_regulator_can_change_status(rdev) && + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && _regulator_is_enabled(rdev)) regulator->always_on = true; @@ -2131,15 +2106,15 @@ static int _regulator_enable(struct regulator_dev *rdev) lockdep_assert_held_once(&rdev->mutex); /* check voltage and requested load before enabling */ - if (rdev->constraints && - (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) + if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) drms_uA_update(rdev); if (rdev->use_count == 0) { /* The regulator may on if it's not switchable or left on */ ret = _regulator_is_enabled(rdev); if (ret == -EINVAL || ret == 0) { - if (!_regulator_can_change_status(rdev)) + if (!regulator_ops_is_valid(rdev, + REGULATOR_CHANGE_STATUS)) return -EPERM; ret = _regulator_do_enable(rdev); @@ -2241,7 +2216,7 @@ static int _regulator_disable(struct regulator_dev *rdev) (rdev->constraints && !rdev->constraints->always_on)) { /* we are last user */ - if (_regulator_can_change_status(rdev)) { + if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_DISABLE, NULL); @@ -2262,10 +2237,7 @@ static int _regulator_disable(struct regulator_dev *rdev) rdev->use_count = 0; } else if (rdev->use_count > 1) { - - if (rdev->constraints && - (rdev->constraints->valid_ops_mask & - REGULATOR_CHANGE_DRMS)) + if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) drms_uA_update(rdev); rdev->use_count--; @@ -2509,8 +2481,7 @@ int regulator_can_change_voltage(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; - if (rdev->constraints && - (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) return 1; @@ -2664,7 +2635,7 @@ int regulator_is_supported_voltage(struct regulator *regulator, int i, voltages, ret; /* If we can't change voltage check the current voltage */ - if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) return min_uV <= ret && ret <= max_uV; @@ -2870,7 +2841,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, * return successfully even though the regulator does not support * changing the voltage. */ - if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { current_uV = _regulator_get_voltage(rdev); if (min_uV <= current_uV && current_uV <= max_uV) { regulator->min_uV = min_uV; @@ -3385,8 +3356,7 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable) if (!rdev->desc->ops->set_bypass) return 0; - if (rdev->constraints && - !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) return 0; mutex_lock(&rdev->mutex); @@ -4406,7 +4376,7 @@ static int __init regulator_late_cleanup(struct device *dev, void *data) if (c && c->always_on) return 0; - if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) return 0; mutex_lock(&rdev->mutex); -- GitLab From 0569a88f3d1ffed94b15569d53872f16e2351099 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Mon, 25 Apr 2016 15:14:00 +0530 Subject: [PATCH 4253/9938] spi: return error if kmap'd buffers passed to spi_map_buf() Current spi_map_buf() implementation supports creates sg_table for vmalloc'd and kmalloc'd buffers. Therefore return error if kmap'd buffer (or any other buffer) is passed to spi_map_buf(). Signed-off-by: Vignesh R Signed-off-by: Mark Brown --- drivers/spi/spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6c4c050e6b65..a50f880a5036 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -717,9 +717,11 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, if (vmalloced_buf) { desc_len = min_t(int, max_seg_size, PAGE_SIZE); sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len); - } else { + } else if (virt_addr_valid(buf)) { desc_len = min_t(int, max_seg_size, master->max_dma_len); sgs = DIV_ROUND_UP(len, desc_len); + } else { + return -EINVAL; } ret = sg_alloc_table(sgt, sgs, GFP_KERNEL); -- GitLab From 6dba72eca7fb879bf2e0c8fdc784fb974cb4f9d5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 24 Apr 2016 22:52:10 +0900 Subject: [PATCH 4254/9938] iio: pressure: bmp280: add support for BMP180 This adds support for the BMP180 to the bmp280 iio driver. The BMP180 has already been supported by misc/bmp085 driver but it doesn't use iio framework. This change adds the kconfig dependency not to be selected both of them in order to avoid any issues. Signed-off-by: Akinobu Mita Acked-by: Vlad Dogaru Cc: Christoph Mair Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 7 +- drivers/iio/pressure/bmp280.c | 367 ++++++++++++++++++++++++++++++++-- 2 files changed, 357 insertions(+), 17 deletions(-) diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 54c616520512..cda9f128f3a4 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -6,12 +6,13 @@ menu "Pressure sensors" config BMP280 - tristate "Bosch Sensortec BMP280 pressure sensor driver" + tristate "Bosch Sensortec BMP180 and BMP280 pressure sensor driver" depends on I2C + depends on !(BMP085_I2C=y || BMP085_I2C=m) select REGMAP_I2C help - Say yes here to build support for Bosch Sensortec BMP280 - pressure and temperature sensor. + Say yes here to build support for Bosch Sensortec BMP180 and BMP280 + pressure and temperature sensors. To compile this driver as a module, choose M here: the module will be called bmp280. diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index a2602d8dd6d5..dcf3b0ae2b87 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c @@ -1,12 +1,15 @@ /* * Copyright (c) 2014 Intel Corporation * - * Driver for Bosch Sensortec BMP280 digital pressure sensor. + * Driver for Bosch Sensortec BMP180 and BMP280 digital pressure sensor. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * + * Datasheet: + * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf + * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf */ #define pr_fmt(fmt) "bmp280: " fmt @@ -15,9 +18,11 @@ #include #include #include +#include #include #include +/* BMP280 specific registers */ #define BMP280_REG_TEMP_XLSB 0xFC #define BMP280_REG_TEMP_LSB 0xFB #define BMP280_REG_TEMP_MSB 0xFA @@ -26,10 +31,7 @@ #define BMP280_REG_PRESS_MSB 0xF7 #define BMP280_REG_CONFIG 0xF5 -#define BMP280_REG_CTRL_MEAS 0xF4 #define BMP280_REG_STATUS 0xF3 -#define BMP280_REG_RESET 0xE0 -#define BMP280_REG_ID 0xD0 #define BMP280_REG_COMP_TEMP_START 0x88 #define BMP280_COMP_TEMP_REG_COUNT 6 @@ -65,6 +67,28 @@ #define BMP280_MODE_FORCED BIT(0) #define BMP280_MODE_NORMAL (BIT(1) | BIT(0)) +/* BMP180 specific registers */ +#define BMP180_REG_OUT_XLSB 0xF8 +#define BMP180_REG_OUT_LSB 0xF7 +#define BMP180_REG_OUT_MSB 0xF6 + +#define BMP180_REG_CALIB_START 0xAA +#define BMP180_REG_CALIB_COUNT 22 + +#define BMP180_MEAS_SCO BIT(5) +#define BMP180_MEAS_TEMP (0x0E | BMP180_MEAS_SCO) +#define BMP180_MEAS_PRESS_X(oss) ((oss) << 6 | 0x14 | BMP180_MEAS_SCO) +#define BMP180_MEAS_PRESS_1X BMP180_MEAS_PRESS_X(0) +#define BMP180_MEAS_PRESS_2X BMP180_MEAS_PRESS_X(1) +#define BMP180_MEAS_PRESS_4X BMP180_MEAS_PRESS_X(2) +#define BMP180_MEAS_PRESS_8X BMP180_MEAS_PRESS_X(3) + +/* BMP180 and BMP280 common registers */ +#define BMP280_REG_CTRL_MEAS 0xF4 +#define BMP280_REG_RESET 0xE0 +#define BMP280_REG_ID 0xD0 + +#define BMP180_CHIP_ID 0x55 #define BMP280_CHIP_ID 0x58 #define BMP280_SOFT_RESET_VAL 0xB6 @@ -72,6 +96,7 @@ struct bmp280_data { struct i2c_client *client; struct mutex lock; struct regmap *regmap; + const struct bmp280_chip_info *chip_info; /* * Carryover value from temperature conversion, used in pressure @@ -80,9 +105,17 @@ struct bmp280_data { s32 t_fine; }; +struct bmp280_chip_info { + const struct regmap_config *regmap_config; + + int (*chip_config)(struct bmp280_data *); + int (*read_temp)(struct bmp280_data *, int *); + int (*read_press)(struct bmp280_data *, int *, int *); +}; + /* * These enums are used for indexing into the array of compensation - * parameters. + * parameters for BMP280. */ enum { T1, T2, T3 }; enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 }; @@ -290,10 +323,10 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_PRESSURE: - ret = bmp280_read_press(data, val, val2); + ret = data->chip_info->read_press(data, val, val2); break; case IIO_TEMP: - ret = bmp280_read_temp(data, val); + ret = data->chip_info->read_temp(data, val); break; default: ret = -EINVAL; @@ -315,7 +348,7 @@ static const struct iio_info bmp280_info = { .read_raw = &bmp280_read_raw, }; -static int bmp280_chip_init(struct bmp280_data *data) +static int bmp280_chip_config(struct bmp280_data *data) { int ret; @@ -344,6 +377,296 @@ static int bmp280_chip_init(struct bmp280_data *data) return ret; } +static const struct bmp280_chip_info bmp280_chip_info = { + .regmap_config = &bmp280_regmap_config, + .chip_config = bmp280_chip_config, + .read_temp = bmp280_read_temp, + .read_press = bmp280_read_press, +}; + +static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP280_REG_CTRL_MEAS: + case BMP280_REG_RESET: + return true; + default: + return false; + }; +} + +static bool bmp180_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP180_REG_OUT_XLSB: + case BMP180_REG_OUT_LSB: + case BMP180_REG_OUT_MSB: + case BMP280_REG_CTRL_MEAS: + return true; + default: + return false; + } +} + +static const struct regmap_config bmp180_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = BMP180_REG_OUT_XLSB, + .cache_type = REGCACHE_RBTREE, + + .writeable_reg = bmp180_is_writeable_reg, + .volatile_reg = bmp180_is_volatile_reg, +}; + +static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) +{ + int ret; + const int conversion_time_max[] = { 4500, 7500, 13500, 25500 }; + unsigned int delay_us; + unsigned int ctrl; + + ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas); + if (ret) + return ret; + + if (ctrl_meas == BMP180_MEAS_TEMP) + delay_us = 4500; + else + delay_us = conversion_time_max[ilog2(8)]; + + usleep_range(delay_us, delay_us + 1000); + + ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl); + if (ret) + return ret; + + /* The value of this bit reset to "0" after conversion is complete */ + if (ctrl & BMP180_MEAS_SCO) + return -EIO; + + return 0; +} + +static int bmp180_read_adc_temp(struct bmp280_data *data, int *val) +{ + int ret; + __be16 tmp = 0; + + ret = bmp180_measure(data, BMP180_MEAS_TEMP); + if (ret) + return ret; + + ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 2); + if (ret) + return ret; + + *val = be16_to_cpu(tmp); + + return 0; +} + +/* + * These enums are used for indexing into the array of calibration + * coefficients for BMP180. + */ +enum { AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD }; + +struct bmp180_calib { + s16 AC1; + s16 AC2; + s16 AC3; + u16 AC4; + u16 AC5; + u16 AC6; + s16 B1; + s16 B2; + s16 MB; + s16 MC; + s16 MD; +}; + +static int bmp180_read_calib(struct bmp280_data *data, + struct bmp180_calib *calib) +{ + int ret; + int i; + __be16 buf[BMP180_REG_CALIB_COUNT / 2]; + + ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf, + sizeof(buf)); + + if (ret < 0) + return ret; + + /* None of the words has the value 0 or 0xFFFF */ + for (i = 0; i < ARRAY_SIZE(buf); i++) { + if (buf[i] == cpu_to_be16(0) || buf[i] == cpu_to_be16(0xffff)) + return -EIO; + } + + calib->AC1 = be16_to_cpu(buf[AC1]); + calib->AC2 = be16_to_cpu(buf[AC2]); + calib->AC3 = be16_to_cpu(buf[AC3]); + calib->AC4 = be16_to_cpu(buf[AC4]); + calib->AC5 = be16_to_cpu(buf[AC5]); + calib->AC6 = be16_to_cpu(buf[AC6]); + calib->B1 = be16_to_cpu(buf[B1]); + calib->B2 = be16_to_cpu(buf[B2]); + calib->MB = be16_to_cpu(buf[MB]); + calib->MC = be16_to_cpu(buf[MC]); + calib->MD = be16_to_cpu(buf[MD]); + + return 0; +} + +/* + * Returns temperature in DegC, resolution is 0.1 DegC. + * t_fine carries fine temperature as global value. + * + * Taken from datasheet, Section 3.5, "Calculating pressure and temperature". + */ +static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp) +{ + int ret; + s32 x1, x2; + struct bmp180_calib calib; + + ret = bmp180_read_calib(data, &calib); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to read calibration coefficients\n"); + return ret; + } + + x1 = ((adc_temp - calib.AC6) * calib.AC5) >> 15; + x2 = (calib.MC << 11) / (x1 + calib.MD); + data->t_fine = x1 + x2; + + return (data->t_fine + 8) >> 4; +} + +static int bmp180_read_temp(struct bmp280_data *data, int *val) +{ + int ret; + s32 adc_temp, comp_temp; + + ret = bmp180_read_adc_temp(data, &adc_temp); + if (ret) + return ret; + + comp_temp = bmp180_compensate_temp(data, adc_temp); + + /* + * val might be NULL if we're called by the read_press routine, + * who only cares about the carry over t_fine value. + */ + if (val) { + *val = comp_temp * 100; + return IIO_VAL_INT; + } + + return 0; +} + +static int bmp180_read_adc_press(struct bmp280_data *data, int *val) +{ + int ret; + __be32 tmp = 0; + u8 oss = ilog2(8); + + ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss)); + if (ret) + return ret; + + ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 3); + if (ret) + return ret; + + *val = (be32_to_cpu(tmp) >> 8) >> (8 - oss); + + return 0; +} + +/* + * Returns pressure in Pa, resolution is 1 Pa. + * + * Taken from datasheet, Section 3.5, "Calculating pressure and temperature". + */ +static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press) +{ + int ret; + s32 x1, x2, x3, p; + s32 b3, b6; + u32 b4, b7; + s32 oss = ilog2(8); + struct bmp180_calib calib; + + ret = bmp180_read_calib(data, &calib); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to read calibration coefficients\n"); + return ret; + } + + b6 = data->t_fine - 4000; + x1 = (calib.B2 * (b6 * b6 >> 12)) >> 11; + x2 = calib.AC2 * b6 >> 11; + x3 = x1 + x2; + b3 = ((((s32)calib.AC1 * 4 + x3) << oss) + 2) / 4; + x1 = calib.AC3 * b6 >> 13; + x2 = (calib.B1 * ((b6 * b6) >> 12)) >> 16; + x3 = (x1 + x2 + 2) >> 2; + b4 = calib.AC4 * (u32)(x3 + 32768) >> 15; + b7 = ((u32)adc_press - b3) * (50000 >> oss); + if (b7 < 0x80000000) + p = (b7 * 2) / b4; + else + p = (b7 / b4) * 2; + + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + + return p + ((x1 + x2 + 3791) >> 4); +} + +static int bmp180_read_press(struct bmp280_data *data, + int *val, int *val2) +{ + int ret; + s32 adc_press; + u32 comp_press; + + /* Read and compensate temperature so we get a reading of t_fine. */ + ret = bmp180_read_temp(data, NULL); + if (ret) + return ret; + + ret = bmp180_read_adc_press(data, &adc_press); + if (ret) + return ret; + + comp_press = bmp180_compensate_press(data, adc_press); + + *val = comp_press; + *val2 = 1000; + + return IIO_VAL_FRACTIONAL; +} + +static int bmp180_chip_config(struct bmp280_data *data) +{ + return 0; +} + +static const struct bmp280_chip_info bmp180_chip_info = { + .regmap_config = &bmp180_regmap_config, + .chip_config = bmp180_chip_config, + .read_temp = bmp180_read_temp, + .read_press = bmp180_read_press, +}; + static int bmp280_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -367,7 +690,19 @@ static int bmp280_probe(struct i2c_client *client, indio_dev->info = &bmp280_info; indio_dev->modes = INDIO_DIRECT_MODE; - data->regmap = devm_regmap_init_i2c(client, &bmp280_regmap_config); + switch (id->driver_data) { + case BMP180_CHIP_ID: + data->chip_info = &bmp180_chip_info; + break; + case BMP280_CHIP_ID: + data->chip_info = &bmp280_chip_info; + break; + default: + return -EINVAL; + } + + data->regmap = devm_regmap_init_i2c(client, + data->chip_info->regmap_config); if (IS_ERR(data->regmap)) { dev_err(&client->dev, "failed to allocate register map\n"); return PTR_ERR(data->regmap); @@ -376,13 +711,13 @@ static int bmp280_probe(struct i2c_client *client, ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id); if (ret < 0) return ret; - if (chip_id != BMP280_CHIP_ID) { + if (chip_id != id->driver_data) { dev_err(&client->dev, "bad chip id. expected %x got %x\n", BMP280_CHIP_ID, chip_id); return -EINVAL; } - ret = bmp280_chip_init(data); + ret = data->chip_info->chip_config(data); if (ret < 0) return ret; @@ -390,13 +725,17 @@ static int bmp280_probe(struct i2c_client *client, } static const struct acpi_device_id bmp280_acpi_match[] = { - {"BMP0280", 0}, + {"BMP0280", BMP280_CHIP_ID }, + {"BMP0180", BMP180_CHIP_ID }, + {"BMP0085", BMP180_CHIP_ID }, { }, }; MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match); static const struct i2c_device_id bmp280_id[] = { - {"bmp280", 0}, + {"bmp280", BMP280_CHIP_ID }, + {"bmp180", BMP180_CHIP_ID }, + {"bmp085", BMP180_CHIP_ID }, { }, }; MODULE_DEVICE_TABLE(i2c, bmp280_id); @@ -412,5 +751,5 @@ static struct i2c_driver bmp280_driver = { module_i2c_driver(bmp280_driver); MODULE_AUTHOR("Vlad Dogaru "); -MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP280 pressure and temperature sensor"); +MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP180/BMP280 pressure and temperature sensor"); MODULE_LICENSE("GPL v2"); -- GitLab From 62979904b0037430ecc7d8b682f684adced1340f Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 24 Apr 2016 22:52:11 +0900 Subject: [PATCH 4255/9938] iio: pressure: bmp280: add ability to control oversampling rate This adds ability to control the oversampling ratio of the temperature and pressure measurement for both bmp180 and bmp280. Signed-off-by: Akinobu Mita Acked-by: Vlad Dogaru Cc: Christoph Mair Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/bmp280.c | 203 +++++++++++++++++++++++++++++++--- 1 file changed, 185 insertions(+), 18 deletions(-) diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index dcf3b0ae2b87..2f1498e12bb2 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c @@ -48,19 +48,21 @@ #define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5)) #define BMP280_OSRS_TEMP_SKIP 0 -#define BMP280_OSRS_TEMP_1X BIT(5) -#define BMP280_OSRS_TEMP_2X BIT(6) -#define BMP280_OSRS_TEMP_4X (BIT(6) | BIT(5)) -#define BMP280_OSRS_TEMP_8X BIT(7) -#define BMP280_OSRS_TEMP_16X (BIT(7) | BIT(5)) +#define BMP280_OSRS_TEMP_X(osrs_t) ((osrs_t) << 5) +#define BMP280_OSRS_TEMP_1X BMP280_OSRS_TEMP_X(1) +#define BMP280_OSRS_TEMP_2X BMP280_OSRS_TEMP_X(2) +#define BMP280_OSRS_TEMP_4X BMP280_OSRS_TEMP_X(3) +#define BMP280_OSRS_TEMP_8X BMP280_OSRS_TEMP_X(4) +#define BMP280_OSRS_TEMP_16X BMP280_OSRS_TEMP_X(5) #define BMP280_OSRS_PRESS_MASK (BIT(4) | BIT(3) | BIT(2)) #define BMP280_OSRS_PRESS_SKIP 0 -#define BMP280_OSRS_PRESS_1X BIT(2) -#define BMP280_OSRS_PRESS_2X BIT(3) -#define BMP280_OSRS_PRESS_4X (BIT(3) | BIT(2)) -#define BMP280_OSRS_PRESS_8X BIT(4) -#define BMP280_OSRS_PRESS_16X (BIT(4) | BIT(2)) +#define BMP280_OSRS_PRESS_X(osrs_p) ((osrs_p) << 2) +#define BMP280_OSRS_PRESS_1X BMP280_OSRS_PRESS_X(1) +#define BMP280_OSRS_PRESS_2X BMP280_OSRS_PRESS_X(2) +#define BMP280_OSRS_PRESS_4X BMP280_OSRS_PRESS_X(3) +#define BMP280_OSRS_PRESS_8X BMP280_OSRS_PRESS_X(4) +#define BMP280_OSRS_PRESS_16X BMP280_OSRS_PRESS_X(5) #define BMP280_MODE_MASK (BIT(1) | BIT(0)) #define BMP280_MODE_SLEEP 0 @@ -98,6 +100,10 @@ struct bmp280_data { struct regmap *regmap; const struct bmp280_chip_info *chip_info; + /* log of base 2 of oversampling rate */ + u8 oversampling_press; + u8 oversampling_temp; + /* * Carryover value from temperature conversion, used in pressure * calculation. @@ -108,6 +114,12 @@ struct bmp280_data { struct bmp280_chip_info { const struct regmap_config *regmap_config; + const int *oversampling_temp_avail; + int num_oversampling_temp_avail; + + const int *oversampling_press_avail; + int num_oversampling_press_avail; + int (*chip_config)(struct bmp280_data *); int (*read_temp)(struct bmp280_data *, int *); int (*read_press)(struct bmp280_data *, int *, int *); @@ -123,11 +135,13 @@ enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 }; static const struct iio_chan_spec bmp280_channels[] = { { .type = IIO_PRESSURE, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), }, { .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), }, }; @@ -333,6 +347,21 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, break; } break; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + switch (chan->type) { + case IIO_PRESSURE: + *val = 1 << data->oversampling_press; + ret = IIO_VAL_INT; + break; + case IIO_TEMP: + *val = 1 << data->oversampling_temp; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + break; default: ret = -EINVAL; break; @@ -343,22 +372,135 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, return ret; } +static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, + int val) +{ + int i; + const int *avail = data->chip_info->oversampling_temp_avail; + const int n = data->chip_info->num_oversampling_temp_avail; + + for (i = 0; i < n; i++) { + if (avail[i] == val) { + data->oversampling_temp = ilog2(val); + + return data->chip_info->chip_config(data); + } + } + return -EINVAL; +} + +static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data, + int val) +{ + int i; + const int *avail = data->chip_info->oversampling_press_avail; + const int n = data->chip_info->num_oversampling_press_avail; + + for (i = 0; i < n; i++) { + if (avail[i] == val) { + data->oversampling_press = ilog2(val); + + return data->chip_info->chip_config(data); + } + } + return -EINVAL; +} + +static int bmp280_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret = 0; + struct bmp280_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + mutex_lock(&data->lock); + switch (chan->type) { + case IIO_PRESSURE: + ret = bmp280_write_oversampling_ratio_press(data, val); + break; + case IIO_TEMP: + ret = bmp280_write_oversampling_ratio_temp(data, val); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&data->lock); + break; + default: + return -EINVAL; + } + + return ret; +} + +static ssize_t bmp280_show_avail(char *buf, const int *vals, const int n) +{ + size_t len = 0; + int i; + + for (i = 0; i < n; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", vals[i]); + + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t bmp280_show_temp_oversampling_avail(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev)); + + return bmp280_show_avail(buf, data->chip_info->oversampling_temp_avail, + data->chip_info->num_oversampling_temp_avail); +} + +static ssize_t bmp280_show_press_oversampling_avail(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev)); + + return bmp280_show_avail(buf, data->chip_info->oversampling_press_avail, + data->chip_info->num_oversampling_press_avail); +} + +static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available, + S_IRUGO, bmp280_show_temp_oversampling_avail, NULL, 0); + +static IIO_DEVICE_ATTR(in_pressure_oversampling_ratio_available, + S_IRUGO, bmp280_show_press_oversampling_avail, NULL, 0); + +static struct attribute *bmp280_attributes[] = { + &iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr, + &iio_dev_attr_in_pressure_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group bmp280_attrs_group = { + .attrs = bmp280_attributes, +}; + static const struct iio_info bmp280_info = { .driver_module = THIS_MODULE, .read_raw = &bmp280_read_raw, + .write_raw = &bmp280_write_raw, + .attrs = &bmp280_attrs_group, }; static int bmp280_chip_config(struct bmp280_data *data) { int ret; + u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) | + BMP280_OSRS_PRESS_X(data->oversampling_press + 1); ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS, BMP280_OSRS_TEMP_MASK | BMP280_OSRS_PRESS_MASK | BMP280_MODE_MASK, - BMP280_OSRS_TEMP_2X | - BMP280_OSRS_PRESS_16X | - BMP280_MODE_NORMAL); + osrs | BMP280_MODE_NORMAL); if (ret < 0) { dev_err(&data->client->dev, "failed to write ctrl_meas register\n"); @@ -377,8 +519,17 @@ static int bmp280_chip_config(struct bmp280_data *data) return ret; } +static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 }; + static const struct bmp280_chip_info bmp280_chip_info = { .regmap_config = &bmp280_regmap_config, + + .oversampling_temp_avail = bmp280_oversampling_avail, + .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail), + + .oversampling_press_avail = bmp280_oversampling_avail, + .num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail), + .chip_config = bmp280_chip_config, .read_temp = bmp280_read_temp, .read_press = bmp280_read_press, @@ -433,7 +584,7 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) if (ctrl_meas == BMP180_MEAS_TEMP) delay_us = 4500; else - delay_us = conversion_time_max[ilog2(8)]; + delay_us = conversion_time_max[data->oversampling_press]; usleep_range(delay_us, delay_us + 1000); @@ -573,7 +724,7 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val) { int ret; __be32 tmp = 0; - u8 oss = ilog2(8); + u8 oss = data->oversampling_press; ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss)); if (ret) @@ -599,7 +750,7 @@ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press) s32 x1, x2, x3, p; s32 b3, b6; u32 b4, b7; - s32 oss = ilog2(8); + s32 oss = data->oversampling_press; struct bmp180_calib calib; ret = bmp180_read_calib(data, &calib); @@ -660,8 +811,20 @@ static int bmp180_chip_config(struct bmp280_data *data) return 0; } +static const int bmp180_oversampling_temp_avail[] = { 1 }; +static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 }; + static const struct bmp280_chip_info bmp180_chip_info = { .regmap_config = &bmp180_regmap_config, + + .oversampling_temp_avail = bmp180_oversampling_temp_avail, + .num_oversampling_temp_avail = + ARRAY_SIZE(bmp180_oversampling_temp_avail), + + .oversampling_press_avail = bmp180_oversampling_press_avail, + .num_oversampling_press_avail = + ARRAY_SIZE(bmp180_oversampling_press_avail), + .chip_config = bmp180_chip_config, .read_temp = bmp180_read_temp, .read_press = bmp180_read_press, @@ -693,9 +856,13 @@ static int bmp280_probe(struct i2c_client *client, switch (id->driver_data) { case BMP180_CHIP_ID: data->chip_info = &bmp180_chip_info; + data->oversampling_press = ilog2(8); + data->oversampling_temp = ilog2(1); break; case BMP280_CHIP_ID: data->chip_info = &bmp280_chip_info; + data->oversampling_press = ilog2(16); + data->oversampling_temp = ilog2(2); break; default: return -EINVAL; -- GitLab From aadd3076db9d37a593dca1f16b35a87e0bd59005 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Wed, 20 Apr 2016 16:15:09 +0300 Subject: [PATCH 4256/9938] iio: inv_mpu6050: Cleanup hw_info mapping The hw_info array was indexed by enum inv_devices chip_type despite the fact that the enumeration had more members than the array and was ordered differently. The patch cleans this up and adds explicit chip_types to i2c/spi/acpi IDs. It also adds some stricter checks inside the driver core. This happened to work so far because the differences between the supported models are very minor. Signed-off-by: Crestez Dan Leonard Acked-by: Ge Gao Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 15 ++++++++++++++- drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 2 +- drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 18 ++++++++++++++---- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 482a2490c53a..ec0ae6f85945 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -88,7 +88,14 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = { .accl_fs = INV_MPU6050_FS_02G, }; +/* Indexed by enum inv_devices */ static const struct inv_mpu6050_hw hw_info[] = { + { + .num_reg = 117, + .name = "MPU6050", + .reg = ®_set_6050, + .config = &chip_config_6050, + }, { .num_reg = 117, .name = "MPU6500", @@ -97,7 +104,7 @@ static const struct inv_mpu6050_hw hw_info[] = { }, { .num_reg = 117, - .name = "MPU6050", + .name = "MPU6000", .reg = ®_set_6050, .config = &chip_config_6050, }, @@ -793,6 +800,12 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, if (!indio_dev) return -ENOMEM; + BUILD_BUG_ON(ARRAY_SIZE(hw_info) != INV_NUM_PARTS); + if (chip_type < 0 || chip_type >= INV_NUM_PARTS) { + dev_err(dev, "Bad invensense chip_type=%d name=%s\n", + chip_type, name); + return -ENODEV; + } st = iio_priv(indio_dev); st->chip_type = chip_type; st->powerup_count = 0; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 5ee4e0dc093e..bb1a7b1462f5 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -208,7 +208,7 @@ static const struct i2c_device_id inv_mpu_id[] = { MODULE_DEVICE_TABLE(i2c, inv_mpu_id); static const struct acpi_device_id inv_acpi_match[] = { - {"INVN6500", 0}, + {"INVN6500", INV_MPU6500}, { }, }; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index 7bcb8d839f05..3972a4625127 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -44,9 +44,19 @@ static int inv_mpu_i2c_disable(struct iio_dev *indio_dev) static int inv_mpu_probe(struct spi_device *spi) { struct regmap *regmap; - const struct spi_device_id *id = spi_get_device_id(spi); - const char *name = id ? id->name : NULL; - const int chip_type = id ? id->driver_data : 0; + const struct spi_device_id *spi_id; + const struct acpi_device_id *acpi_id; + const char *name = NULL; + enum inv_devices chip_type; + + if ((spi_id = spi_get_device_id(spi))) { + chip_type = (enum inv_devices)spi_id->driver_data; + name = spi_id->name; + } else if ((acpi_id = acpi_match_device(spi->dev.driver->acpi_match_table, &spi->dev))) { + chip_type = (enum inv_devices)acpi_id->driver_data; + } else { + return -ENODEV; + } regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config); if (IS_ERR(regmap)) { @@ -76,7 +86,7 @@ static const struct spi_device_id inv_mpu_id[] = { MODULE_DEVICE_TABLE(spi, inv_mpu_id); static const struct acpi_device_id inv_acpi_match[] = { - {"INVN6000", 0}, + {"INVN6000", INV_MPU6000}, { }, }; MODULE_DEVICE_TABLE(acpi, inv_acpi_match); -- GitLab From 7bdd3181596d3d95ef39849bc3ef8e5b91cb6ae1 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Wed, 20 Apr 2016 16:15:10 +0300 Subject: [PATCH 4257/9938] iio: inv_mpu6050: Remove inv_mpu6050_hw.num_reg This field was unused and incorrect for mpu6500. Signed-off-by: Crestez Dan Leonard Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 3 --- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 -- 2 files changed, 5 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index ec0ae6f85945..84d5b6939e6a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -91,19 +91,16 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = { /* Indexed by enum inv_devices */ static const struct inv_mpu6050_hw hw_info[] = { { - .num_reg = 117, .name = "MPU6050", .reg = ®_set_6050, .config = &chip_config_6050, }, { - .num_reg = 117, .name = "MPU6500", .reg = ®_set_6500, .config = &chip_config_6050, }, { - .num_reg = 117, .name = "MPU6000", .reg = ®_set_6050, .config = &chip_config_6050, diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 52d60cdc9f16..26b63993ba00 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -93,13 +93,11 @@ struct inv_mpu6050_chip_config { /** * struct inv_mpu6050_hw - Other important hardware information. - * @num_reg: Number of registers on device. * @name: name of the chip. * @reg: register map of the chip. * @config: configuration of the chip. */ struct inv_mpu6050_hw { - u8 num_reg; u8 *name; const struct inv_mpu6050_reg_map *reg; const struct inv_mpu6050_chip_config *config; -- GitLab From f429ff10e691438c66d8f5dab9541d145b47ab60 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 14 Apr 2016 16:54:24 +0900 Subject: [PATCH 4258/9938] ARM: multi_v7_defconfig: enable Denali NAND controller This NAND controller device is used on UniPhier SoCs (and I know it is also used on SoC FPGA). Signed-off-by: Masahiro Yamada Signed-off-by: Arnd Bergmann --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6d5314864017..edf78515d478 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -187,6 +187,7 @@ CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_DENALI_DT=y CONFIG_MTD_NAND_ATMEL=y CONFIG_MTD_NAND_BRCMNAND=y CONFIG_MTD_NAND_VF610_NFC=y -- GitLab From 343a6d8e4955f298206d83ae764acf60d146b898 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:14 +0200 Subject: [PATCH 4259/9938] rtnl: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 1 + net/core/rtnetlink.c | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index ba69d4447249..5fdd3a42e377 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -666,6 +666,7 @@ enum { IFLA_VF_STATS_TX_BYTES, IFLA_VF_STATS_BROADCAST, IFLA_VF_STATS_MULTICAST, + IFLA_VF_STATS_PAD, __IFLA_VF_STATS_MAX, }; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5ec059d52823..9efc1f34ef3b 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -825,17 +825,17 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, nla_total_size(sizeof(struct ifla_vf_link_state)) + nla_total_size(sizeof(struct ifla_vf_rss_query_en)) + /* IFLA_VF_STATS_RX_PACKETS */ - nla_total_size(sizeof(__u64)) + + nla_total_size_64bit(sizeof(__u64)) + /* IFLA_VF_STATS_TX_PACKETS */ - nla_total_size(sizeof(__u64)) + + nla_total_size_64bit(sizeof(__u64)) + /* IFLA_VF_STATS_RX_BYTES */ - nla_total_size(sizeof(__u64)) + + nla_total_size_64bit(sizeof(__u64)) + /* IFLA_VF_STATS_TX_BYTES */ - nla_total_size(sizeof(__u64)) + + nla_total_size_64bit(sizeof(__u64)) + /* IFLA_VF_STATS_BROADCAST */ - nla_total_size(sizeof(__u64)) + + nla_total_size_64bit(sizeof(__u64)) + /* IFLA_VF_STATS_MULTICAST */ - nla_total_size(sizeof(__u64)) + + nla_total_size_64bit(sizeof(__u64)) + nla_total_size(sizeof(struct ifla_vf_trust))); return size; } else @@ -1153,18 +1153,18 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, nla_nest_cancel(skb, vfinfo); return -EMSGSIZE; } - if (nla_put_u64(skb, IFLA_VF_STATS_RX_PACKETS, - vf_stats.rx_packets) || - nla_put_u64(skb, IFLA_VF_STATS_TX_PACKETS, - vf_stats.tx_packets) || - nla_put_u64(skb, IFLA_VF_STATS_RX_BYTES, - vf_stats.rx_bytes) || - nla_put_u64(skb, IFLA_VF_STATS_TX_BYTES, - vf_stats.tx_bytes) || - nla_put_u64(skb, IFLA_VF_STATS_BROADCAST, - vf_stats.broadcast) || - nla_put_u64(skb, IFLA_VF_STATS_MULTICAST, - vf_stats.multicast)) + if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS, + vf_stats.rx_packets, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS, + vf_stats.tx_packets, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES, + vf_stats.rx_bytes, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES, + vf_stats.tx_bytes, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST, + vf_stats.broadcast, IFLA_VF_STATS_PAD) || + nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST, + vf_stats.multicast, IFLA_VF_STATS_PAD)) return -EMSGSIZE; nla_nest_end(skb, vfstats); nla_nest_end(skb, vf); -- GitLab From 2a51c1e8ecdcedfcb6f84efb3756822d0d0dfb36 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:15 +0200 Subject: [PATCH 4260/9938] sched: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/pkt_sched.h | 3 +++ net/sched/sch_htb.c | 6 ++++-- net/sched/sch_netem.c | 3 ++- net/sched/sch_tbf.c | 6 ++++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h index 8cb18b44968e..1c78c7454c7c 100644 --- a/include/uapi/linux/pkt_sched.h +++ b/include/uapi/linux/pkt_sched.h @@ -179,6 +179,7 @@ enum { TCA_TBF_PRATE64, TCA_TBF_BURST, TCA_TBF_PBURST, + TCA_TBF_PAD, __TCA_TBF_MAX, }; @@ -368,6 +369,7 @@ enum { TCA_HTB_DIRECT_QLEN, TCA_HTB_RATE64, TCA_HTB_CEIL64, + TCA_HTB_PAD, __TCA_HTB_MAX, }; @@ -531,6 +533,7 @@ enum { TCA_NETEM_RATE, TCA_NETEM_ECN, TCA_NETEM_RATE64, + TCA_NETEM_PAD, __TCA_NETEM_MAX, }; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 87b02ed3d5f2..f6bf5818ed4d 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1122,10 +1122,12 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt)) goto nla_put_failure; if ((cl->rate.rate_bytes_ps >= (1ULL << 32)) && - nla_put_u64(skb, TCA_HTB_RATE64, cl->rate.rate_bytes_ps)) + nla_put_u64_64bit(skb, TCA_HTB_RATE64, cl->rate.rate_bytes_ps, + TCA_HTB_PAD)) goto nla_put_failure; if ((cl->ceil.rate_bytes_ps >= (1ULL << 32)) && - nla_put_u64(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps)) + nla_put_u64_64bit(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps, + TCA_HTB_PAD)) goto nla_put_failure; return nla_nest_end(skb, nest); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 9640bb39a5d2..491d6fd6430c 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -994,7 +994,8 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) goto nla_put_failure; if (q->rate >= (1ULL << 32)) { - if (nla_put_u64(skb, TCA_NETEM_RATE64, q->rate)) + if (nla_put_u64_64bit(skb, TCA_NETEM_RATE64, q->rate, + TCA_NETEM_PAD)) goto nla_put_failure; rate.rate = ~0U; } else { diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index c2fbde742f37..83b90b584fae 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -472,11 +472,13 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) if (nla_put(skb, TCA_TBF_PARMS, sizeof(opt), &opt)) goto nla_put_failure; if (q->rate.rate_bytes_ps >= (1ULL << 32) && - nla_put_u64(skb, TCA_TBF_RATE64, q->rate.rate_bytes_ps)) + nla_put_u64_64bit(skb, TCA_TBF_RATE64, q->rate.rate_bytes_ps, + TCA_TBF_PAD)) goto nla_put_failure; if (tbf_peak_present(q) && q->peak.rate_bytes_ps >= (1ULL << 32) && - nla_put_u64(skb, TCA_TBF_PRATE64, q->peak.rate_bytes_ps)) + nla_put_u64_64bit(skb, TCA_TBF_PRATE64, q->peak.rate_bytes_ps, + TCA_TBF_PAD)) goto nla_put_failure; return nla_nest_end(skb, nest); -- GitLab From f13a82d87b21a3b7c2c3e3c75fe9cf810c332a09 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:16 +0200 Subject: [PATCH 4261/9938] ipv6: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/ila.h | 1 + net/ipv6/ila/ila_lwt.c | 3 ++- net/ipv6/ila/ila_xlat.c | 15 +++++++++------ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h index abde7bbd6f3b..cd97951680bf 100644 --- a/include/uapi/linux/ila.h +++ b/include/uapi/linux/ila.h @@ -14,6 +14,7 @@ enum { ILA_ATTR_LOCATOR_MATCH, /* u64 */ ILA_ATTR_IFINDEX, /* s32 */ ILA_ATTR_DIR, /* u32 */ + ILA_ATTR_PAD, __ILA_ATTR_MAX, }; diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index 2ae3c4fd8aab..9db3621b2126 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c @@ -109,7 +109,8 @@ static int ila_fill_encap_info(struct sk_buff *skb, { struct ila_params *p = ila_params_lwtunnel(lwtstate); - if (nla_put_u64(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator)) + if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator, + ILA_ATTR_PAD)) goto nla_put_failure; return 0; diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 0b03533453e4..0e9e579410da 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -418,12 +418,15 @@ static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg) { - if (nla_put_u64(msg, ILA_ATTR_IDENTIFIER, - (__force u64)ila->p.identifier) || - nla_put_u64(msg, ILA_ATTR_LOCATOR, - (__force u64)ila->p.ip.locator) || - nla_put_u64(msg, ILA_ATTR_LOCATOR_MATCH, - (__force u64)ila->p.ip.locator_match) || + if (nla_put_u64_64bit(msg, ILA_ATTR_IDENTIFIER, + (__force u64)ila->p.identifier, + ILA_ATTR_PAD) || + nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR, + (__force u64)ila->p.ip.locator, + ILA_ATTR_PAD) || + nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH, + (__force u64)ila->p.ip.locator_match, + ILA_ATTR_PAD) || nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->p.ifindex) || nla_put_u32(msg, ILA_ATTR_DIR, ila->p.dir)) return -1; -- GitLab From 0238b7204b7ff1bad1d2d4489f010d670cbd89f2 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:17 +0200 Subject: [PATCH 4262/9938] ovs: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/openvswitch.h | 1 + net/openvswitch/datapath.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index 0358f94af86e..d6be1fb778a5 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -519,6 +519,7 @@ enum ovs_flow_attr { * logging should be suppressed. */ OVS_FLOW_ATTR_UFID, /* Variable length unique flow identifier. */ OVS_FLOW_ATTR_UFID_FLAGS,/* u32 of OVS_UFID_F_*. */ + OVS_FLOW_ATTR_PAD, __OVS_FLOW_ATTR_MAX }; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 0cc66a4e492d..22d9a5316304 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -754,7 +754,8 @@ static int ovs_flow_cmd_fill_stats(const struct sw_flow *flow, ovs_flow_stats_get(flow, &stats, &used, &tcp_flags); if (used && - nla_put_u64(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used))) + nla_put_u64_64bit(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used), + OVS_FLOW_ATTR_PAD)) return -EMSGSIZE; if (stats.n_packets && -- GitLab From 12a0faa3bd76157b9dc096758d6818ff535e4586 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:18 +0200 Subject: [PATCH 4263/9938] bridge: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 2 ++ net/bridge/br_netlink.c | 62 +++++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 5fdd3a42e377..9300c08346c8 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -271,6 +271,7 @@ enum { IFLA_BR_NF_CALL_IP6TABLES, IFLA_BR_NF_CALL_ARPTABLES, IFLA_BR_VLAN_DEFAULT_PVID, + IFLA_BR_PAD, __IFLA_BR_MAX, }; @@ -313,6 +314,7 @@ enum { IFLA_BRPORT_HOLD_TIMER, IFLA_BRPORT_FLUSH, IFLA_BRPORT_MULTICAST_ROUTER, + IFLA_BRPORT_PAD, __IFLA_BRPORT_MAX }; #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index e9c635eae24d..6bae1125e36d 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -135,9 +135,9 @@ static inline size_t br_port_info_size(void) + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_NO */ + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_TOPOLOGY_CHANGE_ACK */ + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_CONFIG_PENDING */ - + nla_total_size(sizeof(u64)) /* IFLA_BRPORT_MESSAGE_AGE_TIMER */ - + nla_total_size(sizeof(u64)) /* IFLA_BRPORT_FORWARD_DELAY_TIMER */ - + nla_total_size(sizeof(u64)) /* IFLA_BRPORT_HOLD_TIMER */ + + nla_total_size_64bit(sizeof(u64)) /* IFLA_BRPORT_MESSAGE_AGE_TIMER */ + + nla_total_size_64bit(sizeof(u64)) /* IFLA_BRPORT_FORWARD_DELAY_TIMER */ + + nla_total_size_64bit(sizeof(u64)) /* IFLA_BRPORT_HOLD_TIMER */ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MULTICAST_ROUTER */ #endif @@ -190,13 +190,16 @@ static int br_port_fill_attrs(struct sk_buff *skb, return -EMSGSIZE; timerval = br_timer_value(&p->message_age_timer); - if (nla_put_u64(skb, IFLA_BRPORT_MESSAGE_AGE_TIMER, timerval)) + if (nla_put_u64_64bit(skb, IFLA_BRPORT_MESSAGE_AGE_TIMER, timerval, + IFLA_BRPORT_PAD)) return -EMSGSIZE; timerval = br_timer_value(&p->forward_delay_timer); - if (nla_put_u64(skb, IFLA_BRPORT_FORWARD_DELAY_TIMER, timerval)) + if (nla_put_u64_64bit(skb, IFLA_BRPORT_FORWARD_DELAY_TIMER, timerval, + IFLA_BRPORT_PAD)) return -EMSGSIZE; timerval = br_timer_value(&p->hold_timer); - if (nla_put_u64(skb, IFLA_BRPORT_HOLD_TIMER, timerval)) + if (nla_put_u64_64bit(skb, IFLA_BRPORT_HOLD_TIMER, timerval, + IFLA_BRPORT_PAD)) return -EMSGSIZE; #ifdef CONFIG_BRIDGE_IGMP_SNOOPING @@ -1087,10 +1090,10 @@ static size_t br_get_size(const struct net_device *brdev) nla_total_size(sizeof(u32)) + /* IFLA_BR_ROOT_PATH_COST */ nla_total_size(sizeof(u8)) + /* IFLA_BR_TOPOLOGY_CHANGE */ nla_total_size(sizeof(u8)) + /* IFLA_BR_TOPOLOGY_CHANGE_DETECTED */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_HELLO_TIMER */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_TCN_TIMER */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_TOPOLOGY_CHANGE_TIMER */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_GC_TIMER */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_HELLO_TIMER */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_TCN_TIMER */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_TOPOLOGY_CHANGE_TIMER */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_GC_TIMER */ nla_total_size(ETH_ALEN) + /* IFLA_BR_GROUP_ADDR */ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING nla_total_size(sizeof(u8)) + /* IFLA_BR_MCAST_ROUTER */ @@ -1101,12 +1104,12 @@ static size_t br_get_size(const struct net_device *brdev) nla_total_size(sizeof(u32)) + /* IFLA_BR_MCAST_HASH_MAX */ nla_total_size(sizeof(u32)) + /* IFLA_BR_MCAST_LAST_MEMBER_CNT */ nla_total_size(sizeof(u32)) + /* IFLA_BR_MCAST_STARTUP_QUERY_CNT */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_MCAST_LAST_MEMBER_INTVL */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_MCAST_MEMBERSHIP_INTVL */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_MCAST_QUERIER_INTVL */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_MCAST_QUERY_INTVL */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_MCAST_QUERY_RESPONSE_INTVL */ - nla_total_size(sizeof(u64)) + /* IFLA_BR_MCAST_STARTUP_QUERY_INTVL */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_LAST_MEMBER_INTVL */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_MEMBERSHIP_INTVL */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_QUERIER_INTVL */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_QUERY_INTVL */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_QUERY_RESPONSE_INTVL */ + nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_STARTUP_QUERY_INTVL */ #endif #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) nla_total_size(sizeof(u8)) + /* IFLA_BR_NF_CALL_IPTABLES */ @@ -1129,16 +1132,17 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) u64 clockval; clockval = br_timer_value(&br->hello_timer); - if (nla_put_u64(skb, IFLA_BR_HELLO_TIMER, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_HELLO_TIMER, clockval, IFLA_BR_PAD)) return -EMSGSIZE; clockval = br_timer_value(&br->tcn_timer); - if (nla_put_u64(skb, IFLA_BR_TCN_TIMER, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_TCN_TIMER, clockval, IFLA_BR_PAD)) return -EMSGSIZE; clockval = br_timer_value(&br->topology_change_timer); - if (nla_put_u64(skb, IFLA_BR_TOPOLOGY_CHANGE_TIMER, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_TOPOLOGY_CHANGE_TIMER, clockval, + IFLA_BR_PAD)) return -EMSGSIZE; clockval = br_timer_value(&br->gc_timer); - if (nla_put_u64(skb, IFLA_BR_GC_TIMER, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_GC_TIMER, clockval, IFLA_BR_PAD)) return -EMSGSIZE; if (nla_put_u32(skb, IFLA_BR_FORWARD_DELAY, forward_delay) || @@ -1182,22 +1186,28 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) return -EMSGSIZE; clockval = jiffies_to_clock_t(br->multicast_last_member_interval); - if (nla_put_u64(skb, IFLA_BR_MCAST_LAST_MEMBER_INTVL, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_MCAST_LAST_MEMBER_INTVL, clockval, + IFLA_BR_PAD)) return -EMSGSIZE; clockval = jiffies_to_clock_t(br->multicast_membership_interval); - if (nla_put_u64(skb, IFLA_BR_MCAST_MEMBERSHIP_INTVL, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_MCAST_MEMBERSHIP_INTVL, clockval, + IFLA_BR_PAD)) return -EMSGSIZE; clockval = jiffies_to_clock_t(br->multicast_querier_interval); - if (nla_put_u64(skb, IFLA_BR_MCAST_QUERIER_INTVL, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_MCAST_QUERIER_INTVL, clockval, + IFLA_BR_PAD)) return -EMSGSIZE; clockval = jiffies_to_clock_t(br->multicast_query_interval); - if (nla_put_u64(skb, IFLA_BR_MCAST_QUERY_INTVL, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_MCAST_QUERY_INTVL, clockval, + IFLA_BR_PAD)) return -EMSGSIZE; clockval = jiffies_to_clock_t(br->multicast_query_response_interval); - if (nla_put_u64(skb, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, clockval, + IFLA_BR_PAD)) return -EMSGSIZE; clockval = jiffies_to_clock_t(br->multicast_startup_query_interval); - if (nla_put_u64(skb, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, clockval)) + if (nla_put_u64_64bit(skb, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, clockval, + IFLA_BR_PAD)) return -EMSGSIZE; #endif #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) -- GitLab From 1c714a92833674c040e03be067accfb2b322221e Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:19 +0200 Subject: [PATCH 4264/9938] l2tp: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/l2tp.h | 1 + net/l2tp/l2tp_netlink.c | 80 +++++++++++++++++++++++---------------- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/include/uapi/linux/l2tp.h b/include/uapi/linux/l2tp.h index 3386a99e0397..4bd27d0270a2 100644 --- a/include/uapi/linux/l2tp.h +++ b/include/uapi/linux/l2tp.h @@ -143,6 +143,7 @@ enum { L2TP_ATTR_RX_SEQ_DISCARDS, /* u64 */ L2TP_ATTR_RX_OOS_PACKETS, /* u64 */ L2TP_ATTR_RX_ERRORS, /* u64 */ + L2TP_ATTR_STATS_PAD, __L2TP_ATTR_STATS_MAX, }; diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 24ed2e875c45..1d02e8d20e56 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -346,22 +346,30 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla if (nest == NULL) goto nla_put_failure; - if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, - atomic_long_read(&tunnel->stats.tx_packets)) || - nla_put_u64(skb, L2TP_ATTR_TX_BYTES, - atomic_long_read(&tunnel->stats.tx_bytes)) || - nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, - atomic_long_read(&tunnel->stats.tx_errors)) || - nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, - atomic_long_read(&tunnel->stats.rx_packets)) || - nla_put_u64(skb, L2TP_ATTR_RX_BYTES, - atomic_long_read(&tunnel->stats.rx_bytes)) || - nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, - atomic_long_read(&tunnel->stats.rx_seq_discards)) || - nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS, - atomic_long_read(&tunnel->stats.rx_oos_packets)) || - nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, - atomic_long_read(&tunnel->stats.rx_errors))) + if (nla_put_u64_64bit(skb, L2TP_ATTR_TX_PACKETS, + atomic_long_read(&tunnel->stats.tx_packets), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_TX_BYTES, + atomic_long_read(&tunnel->stats.tx_bytes), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_TX_ERRORS, + atomic_long_read(&tunnel->stats.tx_errors), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_PACKETS, + atomic_long_read(&tunnel->stats.rx_packets), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_BYTES, + atomic_long_read(&tunnel->stats.rx_bytes), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_SEQ_DISCARDS, + atomic_long_read(&tunnel->stats.rx_seq_discards), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_OOS_PACKETS, + atomic_long_read(&tunnel->stats.rx_oos_packets), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_ERRORS, + atomic_long_read(&tunnel->stats.rx_errors), + L2TP_ATTR_STATS_PAD)) goto nla_put_failure; nla_nest_end(skb, nest); @@ -754,22 +762,30 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl if (nest == NULL) goto nla_put_failure; - if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, - atomic_long_read(&session->stats.tx_packets)) || - nla_put_u64(skb, L2TP_ATTR_TX_BYTES, - atomic_long_read(&session->stats.tx_bytes)) || - nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, - atomic_long_read(&session->stats.tx_errors)) || - nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, - atomic_long_read(&session->stats.rx_packets)) || - nla_put_u64(skb, L2TP_ATTR_RX_BYTES, - atomic_long_read(&session->stats.rx_bytes)) || - nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, - atomic_long_read(&session->stats.rx_seq_discards)) || - nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS, - atomic_long_read(&session->stats.rx_oos_packets)) || - nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, - atomic_long_read(&session->stats.rx_errors))) + if (nla_put_u64_64bit(skb, L2TP_ATTR_TX_PACKETS, + atomic_long_read(&session->stats.tx_packets), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_TX_BYTES, + atomic_long_read(&session->stats.tx_bytes), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_TX_ERRORS, + atomic_long_read(&session->stats.tx_errors), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_PACKETS, + atomic_long_read(&session->stats.rx_packets), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_BYTES, + atomic_long_read(&session->stats.rx_bytes), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_SEQ_DISCARDS, + atomic_long_read(&session->stats.rx_seq_discards), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_OOS_PACKETS, + atomic_long_read(&session->stats.rx_oos_packets), + L2TP_ATTR_STATS_PAD) || + nla_put_u64_64bit(skb, L2TP_ATTR_RX_ERRORS, + atomic_long_read(&session->stats.rx_errors), + L2TP_ATTR_STATS_PAD)) goto nla_put_failure; nla_nest_end(skb, nest); -- GitLab From a558da0916b90c330940a106105d0a6a67cb77f7 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:20 +0200 Subject: [PATCH 4265/9938] ieee802154: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/linux/nl802154.h | 2 ++ net/ieee802154/nl-mac.c | 17 +++++++++++------ net/ieee802154/nl802154.c | 3 ++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h index 167342c2ce6b..0f6f6607f592 100644 --- a/include/linux/nl802154.h +++ b/include/linux/nl802154.h @@ -92,6 +92,8 @@ enum { IEEE802154_ATTR_LLSEC_DEV_OVERRIDE, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE, + IEEE802154_ATTR_PAD, + __IEEE802154_ATTR_MAX, }; diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index 3503c38954f9..d3cbb3258718 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -34,9 +34,11 @@ #include "ieee802154.h" -static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr) +static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr, + int padattr) { - return nla_put_u64(msg, type, swab64((__force u64)hwaddr)); + return nla_put_u64_64bit(msg, type, swab64((__force u64)hwaddr), + padattr); } static __le64 nla_get_hwaddr(const struct nlattr *nla) @@ -623,7 +625,8 @@ ieee802154_llsec_fill_key_id(struct sk_buff *msg, if (desc->device_addr.mode == IEEE802154_ADDR_LONG && nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, - desc->device_addr.extended_addr)) + desc->device_addr.extended_addr, + IEEE802154_ATTR_PAD)) return -EMSGSIZE; } @@ -638,7 +641,7 @@ ieee802154_llsec_fill_key_id(struct sk_buff *msg, if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX && nla_put_hwaddr(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED, - desc->extended_source)) + desc->extended_source, IEEE802154_ATTR_PAD)) return -EMSGSIZE; return 0; @@ -1063,7 +1066,8 @@ ieee802154_nl_fill_dev(struct sk_buff *msg, u32 portid, u32 seq, nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, desc->pan_id) || nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, desc->short_addr) || - nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, desc->hwaddr) || + nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, desc->hwaddr, + IEEE802154_ATTR_PAD) || nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, desc->frame_counter) || nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE, @@ -1167,7 +1171,8 @@ ieee802154_nl_fill_devkey(struct sk_buff *msg, u32 portid, u32 seq, if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || - nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, devaddr) || + nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, devaddr, + IEEE802154_ATTR_PAD) || nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, devkey->frame_counter) || ieee802154_llsec_fill_key_id(msg, &devkey->key_id)) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 614072064d03..8035c93dd527 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -813,7 +813,8 @@ nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) || nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) || - nla_put_u64(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev)) || + nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV, + wpan_dev_id(wpan_dev), NL802154_ATTR_PAD) || nla_put_u32(msg, NL802154_ATTR_GENERATION, rdev->devlist_generation ^ (cfg802154_rdev_list_generation << 2))) -- GitLab From cbdeafd7e18b77d147fc1f6c000d4126e53d48bb Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:21 +0200 Subject: [PATCH 4266/9938] netfilter/ipvs: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/ip_vs.h | 1 + net/netfilter/ipvs/ip_vs_ctl.c | 36 ++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h index 391395c06c7e..22d69894bc92 100644 --- a/include/uapi/linux/ip_vs.h +++ b/include/uapi/linux/ip_vs.h @@ -435,6 +435,7 @@ enum { IPVS_STATS_ATTR_OUTPPS, /* current out packet rate */ IPVS_STATS_ATTR_INBPS, /* current in byte rate */ IPVS_STATS_ATTR_OUTBPS, /* current out byte rate */ + IPVS_STATS_ATTR_PAD, __IPVS_STATS_ATTR_MAX, }; diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 404b2a4f4b5b..f35ebc02fa5c 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2875,8 +2875,10 @@ static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, if (nla_put_u32(skb, IPVS_STATS_ATTR_CONNS, (u32)kstats->conns) || nla_put_u32(skb, IPVS_STATS_ATTR_INPKTS, (u32)kstats->inpkts) || nla_put_u32(skb, IPVS_STATS_ATTR_OUTPKTS, (u32)kstats->outpkts) || - nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes) || - nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes, + IPVS_STATS_ATTR_PAD) || nla_put_u32(skb, IPVS_STATS_ATTR_CPS, (u32)kstats->cps) || nla_put_u32(skb, IPVS_STATS_ATTR_INPPS, (u32)kstats->inpps) || nla_put_u32(skb, IPVS_STATS_ATTR_OUTPPS, (u32)kstats->outpps) || @@ -2900,16 +2902,26 @@ static int ip_vs_genl_fill_stats64(struct sk_buff *skb, int container_type, if (!nl_stats) return -EMSGSIZE; - if (nla_put_u64(skb, IPVS_STATS_ATTR_CONNS, kstats->conns) || - nla_put_u64(skb, IPVS_STATS_ATTR_INPKTS, kstats->inpkts) || - nla_put_u64(skb, IPVS_STATS_ATTR_OUTPKTS, kstats->outpkts) || - nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes) || - nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes) || - nla_put_u64(skb, IPVS_STATS_ATTR_CPS, kstats->cps) || - nla_put_u64(skb, IPVS_STATS_ATTR_INPPS, kstats->inpps) || - nla_put_u64(skb, IPVS_STATS_ATTR_OUTPPS, kstats->outpps) || - nla_put_u64(skb, IPVS_STATS_ATTR_INBPS, kstats->inbps) || - nla_put_u64(skb, IPVS_STATS_ATTR_OUTBPS, kstats->outbps)) + if (nla_put_u64_64bit(skb, IPVS_STATS_ATTR_CONNS, kstats->conns, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_INPKTS, kstats->inpkts, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_OUTPKTS, kstats->outpkts, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_CPS, kstats->cps, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_INPPS, kstats->inpps, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_OUTPPS, kstats->outpps, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_INBPS, kstats->inbps, + IPVS_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, IPVS_STATS_ATTR_OUTBPS, kstats->outbps, + IPVS_STATS_ATTR_PAD)) goto nla_put_failure; nla_nest_end(skb, nl_stats); -- GitLab From 2dad624e6dd65c6048a9bbe0e16559fce182c87c Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 25 Apr 2016 10:25:22 +0200 Subject: [PATCH 4267/9938] wireless: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/nl80211.h | 4 ++ net/wireless/nl80211.c | 91 ++++++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 1df655d8aa52..2c55dd1894c3 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2197,6 +2197,8 @@ enum nl80211_attrs { NL80211_ATTR_STA_SUPPORT_P2P_PS, + NL80211_ATTR_PAD, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -3023,6 +3025,7 @@ enum nl80211_survey_info { NL80211_SURVEY_INFO_TIME_RX, NL80211_SURVEY_INFO_TIME_TX, NL80211_SURVEY_INFO_TIME_SCAN, + NL80211_SURVEY_INFO_PAD, /* keep last */ __NL80211_SURVEY_INFO_AFTER_LAST, @@ -3468,6 +3471,7 @@ enum nl80211_bss { NL80211_BSS_BEACON_TSF, NL80211_BSS_PRESP_DATA, NL80211_BSS_LAST_SEEN_BOOTTIME, + NL80211_BSS_PAD, /* keep last */ __NL80211_BSS_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fd7f34a2b10c..afeb1ef1b199 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2429,7 +2429,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) || nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->devlist_generation ^ @@ -6874,7 +6875,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex)) goto nla_put_failure; - if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) + if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD)) goto nla_put_failure; bss = nla_nest_start(msg, NL80211_ATTR_BSS); @@ -6895,7 +6897,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, */ ies = rcu_dereference(res->ies); if (ies) { - if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf)) + if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf, + NL80211_BSS_PAD)) goto fail_unlock_rcu; if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, ies->len, ies->data)) @@ -6905,7 +6908,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, /* and this pointer is always (unless driver didn't know) beacon data */ ies = rcu_dereference(res->beacon_ies); if (ies && ies->from_beacon) { - if (nla_put_u64(msg, NL80211_BSS_BEACON_TSF, ies->tsf)) + if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf, + NL80211_BSS_PAD)) goto fail_unlock_rcu; if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, ies->len, ies->data)) @@ -6924,8 +6928,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, goto nla_put_failure; if (intbss->ts_boottime && - nla_put_u64(msg, NL80211_BSS_LAST_SEEN_BOOTTIME, - intbss->ts_boottime)) + nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME, + intbss->ts_boottime, NL80211_BSS_PAD)) goto nla_put_failure; switch (rdev->wiphy.signal_type) { @@ -7045,28 +7049,28 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE)) goto nla_put_failure; if ((survey->filled & SURVEY_INFO_TIME) && - nla_put_u64(msg, NL80211_SURVEY_INFO_TIME, - survey->time)) + nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME, + survey->time, NL80211_SURVEY_INFO_PAD)) goto nla_put_failure; if ((survey->filled & SURVEY_INFO_TIME_BUSY) && - nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_BUSY, - survey->time_busy)) + nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY, + survey->time_busy, NL80211_SURVEY_INFO_PAD)) goto nla_put_failure; if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) && - nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY, - survey->time_ext_busy)) + nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY, + survey->time_ext_busy, NL80211_SURVEY_INFO_PAD)) goto nla_put_failure; if ((survey->filled & SURVEY_INFO_TIME_RX) && - nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_RX, - survey->time_rx)) + nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX, + survey->time_rx, NL80211_SURVEY_INFO_PAD)) goto nla_put_failure; if ((survey->filled & SURVEY_INFO_TIME_TX) && - nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_TX, - survey->time_tx)) + nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX, + survey->time_tx, NL80211_SURVEY_INFO_PAD)) goto nla_put_failure; if ((survey->filled & SURVEY_INFO_TIME_SCAN) && - nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_SCAN, - survey->time_scan)) + nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN, + survey->time_scan, NL80211_SURVEY_INFO_PAD)) goto nla_put_failure; nla_nest_end(msg, infoattr); @@ -7786,8 +7790,8 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, } if (wdev) { - if (nla_put_u64(skb, NL80211_ATTR_WDEV, - wdev_id(wdev))) + if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV, + wdev_id(wdev), NL80211_ATTR_PAD)) goto nla_put_failure; if (wdev->netdev && nla_put_u32(skb, NL80211_ATTR_IFINDEX, @@ -8380,7 +8384,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, if (err) goto free_msg; - if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie, + NL80211_ATTR_PAD)) goto nla_put_failure; genlmsg_end(msg, hdr); @@ -8792,7 +8797,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) goto free_msg; if (msg) { - if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie, + NL80211_ATTR_PAD)) goto nla_put_failure; genlmsg_end(msg, hdr); @@ -10078,7 +10084,8 @@ static int nl80211_probe_client(struct sk_buff *skb, if (err) goto free_msg; - if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie, + NL80211_ATTR_PAD)) goto nla_put_failure; genlmsg_end(msg, hdr); @@ -10503,8 +10510,9 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb, break; if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - (wdev && nla_put_u64(skb, NL80211_ATTR_WDEV, - wdev_id(wdev)))) { + (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV, + wdev_id(wdev), + NL80211_ATTR_PAD))) { genlmsg_cancel(skb, hdr); break; } @@ -11711,7 +11719,8 @@ static int nl80211_send_scan_msg(struct sk_buff *msg, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex)) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD)) goto nla_put_failure; /* ignore errors and send incomplete event anyway */ @@ -12378,11 +12387,13 @@ static void nl80211_send_remain_on_chan_event( if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex)) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD) || nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) || nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_NO_HT) || - nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) + nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie, + NL80211_ATTR_PAD)) goto nla_put_failure; if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL && @@ -12616,7 +12627,8 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD) || nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || (sig_dbm && nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || @@ -12659,9 +12671,11 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD) || nla_put(msg, NL80211_ATTR_FRAME, len, buf) || - nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || + nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie, + NL80211_ATTR_PAD) || (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) goto nla_put_failure; @@ -13041,7 +13055,8 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev = netdev->ieee80211_ptr; if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD)) goto nla_put_failure; } @@ -13086,7 +13101,8 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || - nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || + nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie, + NL80211_ATTR_PAD) || (acked && nla_put_flag(msg, NL80211_ATTR_ACK))) goto nla_put_failure; @@ -13231,7 +13247,8 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, goto free_msg; if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD)) goto free_msg; if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, @@ -13506,7 +13523,8 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp) goto nla_put_failure; if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD)) goto nla_put_failure; genlmsg_end(msg, hdr); @@ -13539,7 +13557,8 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD)) goto out; genlmsg_end(msg, hdr); -- GitLab From cec0154556f8fe6d3a7f5d370f715283888d1c02 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Wed, 20 Apr 2016 16:15:11 +0300 Subject: [PATCH 4268/9938] iio: inv_mpu6050: Check WHO_AM_I register on probe This can be used to distinguish mpu6500. This is a warning rather than an error because the differences are mostly irrelevant and it's nice to avoid breaking users with slightly incorrect ACPI/DT. Signed-off-by: Crestez Dan Leonard Acked-by: Ge Gao Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 15 +++++++++++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 84d5b6939e6a..4152f2fcf598 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -91,16 +91,19 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = { /* Indexed by enum inv_devices */ static const struct inv_mpu6050_hw hw_info[] = { { + .whoami = INV_MPU6050_WHOAMI_VALUE, .name = "MPU6050", .reg = ®_set_6050, .config = &chip_config_6050, }, { + .whoami = INV_MPU6500_WHOAMI_VALUE, .name = "MPU6500", .reg = ®_set_6500, .config = &chip_config_6050, }, { + .whoami = INV_MPU6000_WHOAMI_VALUE, .name = "MPU6000", .reg = ®_set_6050, .config = &chip_config_6050, @@ -749,6 +752,7 @@ static const struct iio_info mpu_info = { static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) { int result; + unsigned int regval; st->hw = &hw_info[st->chip_type]; st->reg = hw_info[st->chip_type].reg; @@ -759,6 +763,17 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) if (result) return result; msleep(INV_MPU6050_POWER_UP_TIME); + + /* check chip self-identification */ + result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, ®val); + if (result) + return result; + if (regval != st->hw->whoami) { + dev_warn(regmap_get_device(st->map), + "whoami mismatch got %#02x expected %#02hhx for %s\n", + regval, st->hw->whoami, st->hw->name); + } + /* * toggle power state. After reset, the sleep bit could be on * or off depending on the OTP settings. Toggling power would diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 26b63993ba00..fb45cc76e4e4 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -93,11 +93,13 @@ struct inv_mpu6050_chip_config { /** * struct inv_mpu6050_hw - Other important hardware information. + * @whoami: Self identification byte from WHO_AM_I register * @name: name of the chip. * @reg: register map of the chip. * @config: configuration of the chip. */ struct inv_mpu6050_hw { + u8 whoami; u8 *name; const struct inv_mpu6050_reg_map *reg; const struct inv_mpu6050_chip_config *config; @@ -215,6 +217,12 @@ struct inv_mpu6050_state { #define INV_MPU6050_MIN_FIFO_RATE 4 #define INV_MPU6050_ONE_K_HZ 1000 +#define INV_MPU6050_REG_WHOAMI 117 + +#define INV_MPU6000_WHOAMI_VALUE 0x68 +#define INV_MPU6050_WHOAMI_VALUE 0x68 +#define INV_MPU6500_WHOAMI_VALUE 0x70 + /* scan element definition */ enum inv_mpu6050_scan { INV_MPU6050_SCAN_ACCL_X, -- GitLab From bf1eb91274157ac521fd6f3712dac8be90bddca7 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Wed, 20 Apr 2016 16:15:12 +0300 Subject: [PATCH 4269/9938] iio: inv_mpu6050: Add spi_device_id for INV_MPU6500 Signed-off-by: Crestez Dan Leonard Acked-by: Ge Gao Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index 3972a4625127..a0f8df239933 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -80,6 +80,7 @@ static int inv_mpu_remove(struct spi_device *spi) */ static const struct spi_device_id inv_mpu_id[] = { {"mpu6000", INV_MPU6000}, + {"mpu6500", INV_MPU6500}, {} }; -- GitLab From fbced0e9465152d628ece5fd0d11de4e7a1f5ce5 Mon Sep 17 00:00:00 2001 From: Crestez Dan Leonard Date: Wed, 20 Apr 2016 16:15:13 +0300 Subject: [PATCH 4270/9938] iio: inv_mpu6050: Add explicit support for MPU9150 This device is a package containing a MPU6050-like sensor and an AK8975 magnetometer. The magnetometer component is supported by the existing ak8975 driver. This patch also rephrases the Kconfig descriptions. Signed-off-by: Crestez Dan Leonard Acked-by: Ge Gao Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 10 ++++------ drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 6 ++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 1 + drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 ++ drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 1 + 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index a7f557af4389..c05d474587d2 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -14,10 +14,8 @@ config INV_MPU6050_I2C select I2C_MUX select REGMAP_I2C help - This driver supports the Invensense MPU6050 devices. - This driver can also support MPU6500 in MPU6050 compatibility mode - and also in MPU6500 mode with some limitations. - It is a gyroscope/accelerometer combo device. + This driver supports the Invensense MPU6050/6500/9150 motion tracking + devices over I2C. This driver can be built as a module. The module will be called inv-mpu6050-i2c. @@ -27,7 +25,7 @@ config INV_MPU6050_SPI select INV_MPU6050_IIO select REGMAP_SPI help - This driver supports the Invensense MPU6050 devices. - It is a gyroscope/accelerometer combo device. + This driver supports the Invensense MPU6000/6500/9150 motion tracking + devices over SPI. This driver can be built as a module. The module will be called inv-mpu6050-spi. diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 4152f2fcf598..b269b375ca34 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -108,6 +108,12 @@ static const struct inv_mpu6050_hw hw_info[] = { .reg = ®_set_6050, .config = &chip_config_6050, }, + { + .whoami = INV_MPU9150_WHOAMI_VALUE, + .name = "MPU9150", + .reg = ®_set_6050, + .config = &chip_config_6050, + }, }; int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index bb1a7b1462f5..1a424a6561de 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -202,6 +202,7 @@ static int inv_mpu_remove(struct i2c_client *client) static const struct i2c_device_id inv_mpu_id[] = { {"mpu6050", INV_MPU6050}, {"mpu6500", INV_MPU6500}, + {"mpu9150", INV_MPU9150}, {} }; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index fb45cc76e4e4..47ca25b94a73 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -68,6 +68,7 @@ enum inv_devices { INV_MPU6050, INV_MPU6500, INV_MPU6000, + INV_MPU9150, INV_NUM_PARTS }; @@ -222,6 +223,7 @@ struct inv_mpu6050_state { #define INV_MPU6000_WHOAMI_VALUE 0x68 #define INV_MPU6050_WHOAMI_VALUE 0x68 #define INV_MPU6500_WHOAMI_VALUE 0x70 +#define INV_MPU9150_WHOAMI_VALUE 0x68 /* scan element definition */ enum inv_mpu6050_scan { diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index a0f8df239933..190a4a51c830 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -81,6 +81,7 @@ static int inv_mpu_remove(struct spi_device *spi) static const struct spi_device_id inv_mpu_id[] = { {"mpu6000", INV_MPU6000}, {"mpu6500", INV_MPU6500}, + {"mpu9150", INV_MPU9150}, {} }; -- GitLab From 1e9f8dcf892ddb183405cb2414bfc37b40300693 Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Mon, 11 Apr 2016 10:50:31 -0400 Subject: [PATCH 4271/9938] PCI: keystone: Remove unnecessary goto statement Fix the misuse of goto statement in ks_pcie_get_irq_controller_info() as simple return is more appropriate for this function. While at it add an error log for absence of interrupt controller node. [bhelgaas: drop "ret" altogether since we always know the return value] Signed-off-by: Murali Karicheri Signed-off-by: Bjorn Helgaas CC: Rob Herring CC: Pawel Moll CC: Mark Rutland CC: Ian Campbell CC: Kumar Gala --- drivers/pci/host/pci-keystone.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c index 58120009c819..6b8301ef21ca 100644 --- a/drivers/pci/host/pci-keystone.c +++ b/drivers/pci/host/pci-keystone.c @@ -160,7 +160,7 @@ static void ks_pcie_legacy_irq_handler(struct irq_desc *desc) static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, char *controller, int *num_irqs) { - int temp, max_host_irqs, legacy = 1, *host_irqs, ret = -EINVAL; + int temp, max_host_irqs, legacy = 1, *host_irqs; struct device *dev = ks_pcie->pp.dev; struct device_node *np_pcie = dev->of_node, **np_temp; @@ -181,11 +181,15 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, *np_temp = of_find_node_by_name(np_pcie, controller); if (!(*np_temp)) { dev_err(dev, "Node for %s is absent\n", controller); - goto out; + return -EINVAL; } + temp = of_irq_count(*np_temp); - if (!temp) - goto out; + if (!temp) { + dev_err(dev, "No IRQ entries in %s\n", controller); + return -EINVAL; + } + if (temp > max_host_irqs) dev_warn(dev, "Too many %s interrupts defined %u\n", (legacy ? "legacy" : "MSI"), temp); @@ -199,12 +203,13 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, if (!host_irqs[temp]) break; } + if (temp) { *num_irqs = temp; - ret = 0; + return 0; } -out: - return ret; + + return -EINVAL; } static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie) @@ -345,7 +350,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie, return ret; } - return ret; + return 0; } static const struct of_device_id ks_pcie_of_match[] = { @@ -374,7 +379,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev) struct resource *res; void __iomem *reg_p; struct phy *phy; - int ret = 0; + int ret; ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie), GFP_KERNEL); -- GitLab From a213b92e15cc5019156594c8f3ae9170915aac9f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 25 Apr 2016 16:45:29 -0300 Subject: [PATCH 4272/9938] perf evlist: Decode perf_event_attr->branch_sample_type While trying to use --call-graph lbr in 'perf trace', since we only are interested in the callchain for userspace, up to the callchain, I found that 'perf evlist' is not decoding the branch_sample_type field, fix it. Before: # perf record --call-graph lbr usleep 1 # perf evlist -v cycles:ppp: size: 112, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|BRANCH_STACK, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, task: 1, precise_ip: 3, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, branch_sample_type: 51201 ^^^^^^^^^^^^^^^^^^^^^^^^^ After: # perf evlist -v cycles:ppp: size: 112, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|BRANCH_STACK, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, task: 1, precise_ip: 3, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, branch_sample_type: USER|CALL_STACK|NO_FLAGS|NO_CYCLES ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-hozai7974u0ulgx13k96fcaw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 545bb3f0b2b0..334364e25bbe 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1231,6 +1231,21 @@ static void __p_sample_type(char *buf, size_t size, u64 value) __p_bits(buf, size, value, bits); } +static void __p_branch_sample_type(char *buf, size_t size, u64 value) +{ +#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n } + struct bit_names bits[] = { + bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY), + bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL), + bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX), + bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP), + bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES), + { .name = NULL, } + }; +#undef bit_name + __p_bits(buf, size, value, bits); +} + static void __p_read_format(char *buf, size_t size, u64 value) { #define bit_name(n) { PERF_FORMAT_##n, #n } @@ -1249,6 +1264,7 @@ static void __p_read_format(char *buf, size_t size, u64 value) #define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) #define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) #define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) +#define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val) #define p_read_format(val) __p_read_format(buf, BUF_SIZE, val) #define PRINT_ATTRn(_n, _f, _p) \ @@ -1305,7 +1321,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, PRINT_ATTRf(bp_type, p_unsigned); PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); - PRINT_ATTRf(branch_sample_type, p_unsigned); + PRINT_ATTRf(branch_sample_type, p_branch_sample_type); PRINT_ATTRf(sample_regs_user, p_hex); PRINT_ATTRf(sample_stack_user, p_unsigned); PRINT_ATTRf(clockid, p_signed); -- GitLab From 0aea76d35c9651d55bbaf746e7914e5f9ae5a25d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 21 Apr 2016 22:13:01 -0700 Subject: [PATCH 4273/9938] tcp: SYN packets are now simply consumed We now have proper per-listener but also per network namespace counters for SYN packets that might be dropped. We replace the kfree_skb() by consume_skb() to be drop monitor [1] friendly, and remove an obsolete comment. FastOpen SYN packets can carry payload in them just fine. [1] perf record -a -g -e skb:kfree_skb sleep 1; perf report Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index dcad8f9f96eb..967520dbe0bf 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5815,24 +5815,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) if (icsk->icsk_af_ops->conn_request(sk, skb) < 0) return 1; - /* Now we have several options: In theory there is - * nothing else in the frame. KA9Q has an option to - * send data with the syn, BSD accepts data with the - * syn up to the [to be] advertised window and - * Solaris 2.1 gives you a protocol error. For now - * we just ignore it, that fits the spec precisely - * and avoids incompatibilities. It would be nice in - * future to drop through and process the data. - * - * Now that TTCP is starting to be used we ought to - * queue this data. - * But, this leaves one open to an easy denial of - * service attack, and SYN cookies can't defend - * against this problem. So, we drop the data - * in the interest of security over speed unless - * it's still in use. - */ - kfree_skb(skb); + consume_skb(skb); return 0; } goto discard; -- GitLab From 960a26282f5b1f084313c59d22f76026e6637995 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 21 Apr 2016 22:27:32 -0700 Subject: [PATCH 4274/9938] net: better drop monitoring in ip{6}_recv_error() We should call consume_skb(skb) when skb is properly consumed, or kfree_skb(skb) when skb must be dropped in error case. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_sockglue.c | 10 +++++----- net/ipv6/datagram.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 279471c4e58f..bdb222c0c6a2 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -510,9 +510,10 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) copied = len; } err = skb_copy_datagram_msg(skb, 0, msg, copied); - if (err) - goto out_free_skb; - + if (unlikely(err)) { + kfree_skb(skb); + return err; + } sock_recv_timestamp(msg, sk, skb); serr = SKB_EXT_ERR(skb); @@ -544,8 +545,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) msg->msg_flags |= MSG_ERRQUEUE; err = copied; -out_free_skb: - kfree_skb(skb); + consume_skb(skb); out: return err; } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 3962b6c810fc..ea9ee5cce5cf 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -450,9 +450,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) copied = len; } err = skb_copy_datagram_msg(skb, 0, msg, copied); - if (err) - goto out_free_skb; - + if (unlikely(err)) { + kfree_skb(skb); + return err; + } sock_recv_timestamp(msg, sk, skb); serr = SKB_EXT_ERR(skb); @@ -509,8 +510,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) msg->msg_flags |= MSG_ERRQUEUE; err = copied; -out_free_skb: - kfree_skb(skb); + consume_skb(skb); out: return err; } -- GitLab From f3d40914d3d52e2f155c4e65bc2ab5f5d1efb0ab Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:12:10 +0800 Subject: [PATCH 4275/9938] clk: rockchip: fix the gate bit for i2c4 and i2c8 on rk3399 The gate bits of the i2c4 and i2c8 are incorrect due to the manual error, we need to fix them. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index e8f040be3fea..40b738460d47 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -1401,11 +1401,11 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = { COMPOSITE_NOMUX(SCLK_I2C4_PMU, "clk_i2c4_pmu", "ppll", 0, RK3399_PMU_CLKSEL_CON(3), 0, 7, DFLAGS, - RK3399_PMU_CLKGATE_CON(0), 11, GFLAGS), + RK3399_PMU_CLKGATE_CON(0), 10, GFLAGS), COMPOSITE_NOMUX(SCLK_I2C8_PMU, "clk_i2c8_pmu", "ppll", 0, RK3399_PMU_CLKSEL_CON(2), 8, 7, DFLAGS, - RK3399_PMU_CLKGATE_CON(0), 10, GFLAGS), + RK3399_PMU_CLKGATE_CON(0), 11, GFLAGS), DIV(0, "clk_32k_suspend_pmu", "xin24m", CLK_IGNORE_UNUSED, RK3399_PMU_CLKSEL_CON(4), 0, 10, DFLAGS), -- GitLab From d4967cf38fbd62467b8fb5cab63d7da1f5907ed7 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Fri, 22 Apr 2016 08:41:01 +0300 Subject: [PATCH 4276/9938] qed*: Align statistics names There's a difference in statsitics' names starting at qed and propagating to qede, where egress counters indicate ranges while ingress counters indiciate high-end. Align all statistcs to follow the same conventions - name indicates range. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_l2.c | 20 ++++++------- drivers/net/ethernet/qlogic/qede/qede.h | 20 ++++++------- .../net/ethernet/qlogic/qede/qede_ethtool.c | 20 ++++++------- drivers/net/ethernet/qlogic/qede/qede_main.c | 29 ++++++++++++------- include/linux/qed/qed_if.h | 20 ++++++------- 5 files changed, 59 insertions(+), 50 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index fb5f3b815340..31e1d510a991 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1415,16 +1415,16 @@ static void __qed_get_vport_port_stats(struct qed_hwfn *p_hwfn, sizeof(port_stats)); p_stats->rx_64_byte_packets += port_stats.pmm.r64; - p_stats->rx_127_byte_packets += port_stats.pmm.r127; - p_stats->rx_255_byte_packets += port_stats.pmm.r255; - p_stats->rx_511_byte_packets += port_stats.pmm.r511; - p_stats->rx_1023_byte_packets += port_stats.pmm.r1023; - p_stats->rx_1518_byte_packets += port_stats.pmm.r1518; - p_stats->rx_1522_byte_packets += port_stats.pmm.r1522; - p_stats->rx_2047_byte_packets += port_stats.pmm.r2047; - p_stats->rx_4095_byte_packets += port_stats.pmm.r4095; - p_stats->rx_9216_byte_packets += port_stats.pmm.r9216; - p_stats->rx_16383_byte_packets += port_stats.pmm.r16383; + p_stats->rx_65_to_127_byte_packets += port_stats.pmm.r127; + p_stats->rx_128_to_255_byte_packets += port_stats.pmm.r255; + p_stats->rx_256_to_511_byte_packets += port_stats.pmm.r511; + p_stats->rx_512_to_1023_byte_packets += port_stats.pmm.r1023; + p_stats->rx_1024_to_1518_byte_packets += port_stats.pmm.r1518; + p_stats->rx_1519_to_1522_byte_packets += port_stats.pmm.r1522; + p_stats->rx_1519_to_2047_byte_packets += port_stats.pmm.r2047; + p_stats->rx_2048_to_4095_byte_packets += port_stats.pmm.r4095; + p_stats->rx_4096_to_9216_byte_packets += port_stats.pmm.r9216; + p_stats->rx_9217_to_16383_byte_packets += port_stats.pmm.r16383; p_stats->rx_crc_errors += port_stats.pmm.rfcs; p_stats->rx_mac_crtl_frames += port_stats.pmm.rxcf; p_stats->rx_pause_frames += port_stats.pmm.rxpf; diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 16df1591388f..a687e7a1dc8d 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -59,16 +59,16 @@ struct qede_stats { /* port */ u64 rx_64_byte_packets; - u64 rx_127_byte_packets; - u64 rx_255_byte_packets; - u64 rx_511_byte_packets; - u64 rx_1023_byte_packets; - u64 rx_1518_byte_packets; - u64 rx_1522_byte_packets; - u64 rx_2047_byte_packets; - u64 rx_4095_byte_packets; - u64 rx_9216_byte_packets; - u64 rx_16383_byte_packets; + u64 rx_65_to_127_byte_packets; + u64 rx_128_to_255_byte_packets; + u64 rx_256_to_511_byte_packets; + u64 rx_512_to_1023_byte_packets; + u64 rx_1024_to_1518_byte_packets; + u64 rx_1519_to_1522_byte_packets; + u64 rx_1519_to_2047_byte_packets; + u64 rx_2048_to_4095_byte_packets; + u64 rx_4096_to_9216_byte_packets; + u64 rx_9217_to_16383_byte_packets; u64 rx_crc_errors; u64 rx_mac_crtl_frames; u64 rx_pause_frames; diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index f0982f163670..f87e83b41d5d 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -59,16 +59,16 @@ static const struct { QEDE_STAT(tx_bcast_pkts), QEDE_PF_STAT(rx_64_byte_packets), - QEDE_PF_STAT(rx_127_byte_packets), - QEDE_PF_STAT(rx_255_byte_packets), - QEDE_PF_STAT(rx_511_byte_packets), - QEDE_PF_STAT(rx_1023_byte_packets), - QEDE_PF_STAT(rx_1518_byte_packets), - QEDE_PF_STAT(rx_1522_byte_packets), - QEDE_PF_STAT(rx_2047_byte_packets), - QEDE_PF_STAT(rx_4095_byte_packets), - QEDE_PF_STAT(rx_9216_byte_packets), - QEDE_PF_STAT(rx_16383_byte_packets), + QEDE_PF_STAT(rx_65_to_127_byte_packets), + QEDE_PF_STAT(rx_128_to_255_byte_packets), + QEDE_PF_STAT(rx_256_to_511_byte_packets), + QEDE_PF_STAT(rx_512_to_1023_byte_packets), + QEDE_PF_STAT(rx_1024_to_1518_byte_packets), + QEDE_PF_STAT(rx_1519_to_1522_byte_packets), + QEDE_PF_STAT(rx_1519_to_2047_byte_packets), + QEDE_PF_STAT(rx_2048_to_4095_byte_packets), + QEDE_PF_STAT(rx_4096_to_9216_byte_packets), + QEDE_PF_STAT(rx_9217_to_16383_byte_packets), QEDE_PF_STAT(tx_64_byte_packets), QEDE_PF_STAT(tx_65_to_127_byte_packets), QEDE_PF_STAT(tx_128_to_255_byte_packets), diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 197ef85684da..1e3ee49bae24 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -1638,16 +1638,25 @@ void qede_fill_by_demand_stats(struct qede_dev *edev) edev->stats.coalesced_bytes = stats.tpa_coalesced_bytes; edev->stats.rx_64_byte_packets = stats.rx_64_byte_packets; - edev->stats.rx_127_byte_packets = stats.rx_127_byte_packets; - edev->stats.rx_255_byte_packets = stats.rx_255_byte_packets; - edev->stats.rx_511_byte_packets = stats.rx_511_byte_packets; - edev->stats.rx_1023_byte_packets = stats.rx_1023_byte_packets; - edev->stats.rx_1518_byte_packets = stats.rx_1518_byte_packets; - edev->stats.rx_1522_byte_packets = stats.rx_1522_byte_packets; - edev->stats.rx_2047_byte_packets = stats.rx_2047_byte_packets; - edev->stats.rx_4095_byte_packets = stats.rx_4095_byte_packets; - edev->stats.rx_9216_byte_packets = stats.rx_9216_byte_packets; - edev->stats.rx_16383_byte_packets = stats.rx_16383_byte_packets; + edev->stats.rx_65_to_127_byte_packets = stats.rx_65_to_127_byte_packets; + edev->stats.rx_128_to_255_byte_packets = + stats.rx_128_to_255_byte_packets; + edev->stats.rx_256_to_511_byte_packets = + stats.rx_256_to_511_byte_packets; + edev->stats.rx_512_to_1023_byte_packets = + stats.rx_512_to_1023_byte_packets; + edev->stats.rx_1024_to_1518_byte_packets = + stats.rx_1024_to_1518_byte_packets; + edev->stats.rx_1519_to_1522_byte_packets = + stats.rx_1519_to_1522_byte_packets; + edev->stats.rx_1519_to_2047_byte_packets = + stats.rx_1519_to_2047_byte_packets; + edev->stats.rx_2048_to_4095_byte_packets = + stats.rx_2048_to_4095_byte_packets; + edev->stats.rx_4096_to_9216_byte_packets = + stats.rx_4096_to_9216_byte_packets; + edev->stats.rx_9217_to_16383_byte_packets = + stats.rx_9217_to_16383_byte_packets; edev->stats.rx_crc_errors = stats.rx_crc_errors; edev->stats.rx_mac_crtl_frames = stats.rx_mac_crtl_frames; edev->stats.rx_pause_frames = stats.rx_pause_frames; diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 67e8c206b2c1..82a7fe011068 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -384,16 +384,16 @@ struct qed_eth_stats { /* port */ u64 rx_64_byte_packets; - u64 rx_127_byte_packets; - u64 rx_255_byte_packets; - u64 rx_511_byte_packets; - u64 rx_1023_byte_packets; - u64 rx_1518_byte_packets; - u64 rx_1522_byte_packets; - u64 rx_2047_byte_packets; - u64 rx_4095_byte_packets; - u64 rx_9216_byte_packets; - u64 rx_16383_byte_packets; + u64 rx_65_to_127_byte_packets; + u64 rx_128_to_255_byte_packets; + u64 rx_256_to_511_byte_packets; + u64 rx_512_to_1023_byte_packets; + u64 rx_1024_to_1518_byte_packets; + u64 rx_1519_to_1522_byte_packets; + u64 rx_1519_to_2047_byte_packets; + u64 rx_2048_to_4095_byte_packets; + u64 rx_4096_to_9216_byte_packets; + u64 rx_9217_to_16383_byte_packets; u64 rx_crc_errors; u64 rx_mac_crtl_frames; u64 rx_pause_frames; -- GitLab From f3e72109f04c36ee45e62c0e6e1323179287c3e4 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Fri, 22 Apr 2016 08:41:02 +0300 Subject: [PATCH 4277/9938] qede: Add support for ethtool private flags Adds a getter for the interfaces private flags. The only parameter currently supported is whether the interface is a coupled function [required for supporting 100g]. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- .../net/ethernet/qlogic/qede/qede_ethtool.c | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index f87e83b41d5d..2ac98d44c1e1 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -116,6 +116,15 @@ static const struct { #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) +enum { + QEDE_PRI_FLAG_CMT, + QEDE_PRI_FLAG_LEN, +}; + +static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { + "Coupled-Function", +}; + static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) { int i, j, k; @@ -139,6 +148,10 @@ static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) case ETH_SS_STATS: qede_get_strings_stats(edev, buf); break; + case ETH_SS_PRIV_FLAGS: + memcpy(buf, qede_private_arr, + ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); + break; default: DP_VERBOSE(edev, QED_MSG_DEBUG, "Unsupported stringset 0x%08x\n", stringset); @@ -177,6 +190,8 @@ static int qede_get_sset_count(struct net_device *dev, int stringset) switch (stringset) { case ETH_SS_STATS: return num_stats + QEDE_NUM_RQSTATS; + case ETH_SS_PRIV_FLAGS: + return QEDE_PRI_FLAG_LEN; default: DP_VERBOSE(edev, QED_MSG_DEBUG, @@ -185,6 +200,13 @@ static int qede_get_sset_count(struct net_device *dev, int stringset) } } +static u32 qede_get_priv_flags(struct net_device *dev) +{ + struct qede_dev *edev = netdev_priv(dev); + + return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT; +} + static int qede_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct qede_dev *edev = netdev_priv(dev); @@ -814,6 +836,7 @@ static const struct ethtool_ops qede_ethtool_ops = { .get_strings = qede_get_strings, .set_phys_id = qede_set_phys_id, .get_ethtool_stats = qede_get_ethtool_stats, + .get_priv_flags = qede_get_priv_flags, .get_sset_count = qede_get_sset_count, .get_rxnfc = qede_get_rxnfc, .set_rxnfc = qede_set_rxnfc, -- GitLab From fe7cd2bfdac4d8739bc8665eef040e668e6b428f Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Fri, 22 Apr 2016 08:41:03 +0300 Subject: [PATCH 4278/9938] qed*: Conditions for changing link There's some inconsistency in current logic determining whether the link settings of a given interface can be changed; I.e., in all modes other than the so-called `deault' mode the interfaces are forbidden from changing the configuration - but even this rule is not applied to all user APIs that may change the configuration. Instead, let the core-module [qed] decide whether an interface can change the configuration by supporting a new API function. We also revise the current rule, allowing all interfaces to change their configurations while laying the infrastructure for future modes where an interface would be blocked from making such a configuration. Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_main.c | 6 ++++++ drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 14 ++++++++++---- include/linux/qed/qed_if.h | 10 ++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 1e9f321f1ac4..d189871e8e23 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -915,6 +915,11 @@ static u32 qed_sb_release(struct qed_dev *cdev, return rc; } +static bool qed_can_link_change(struct qed_dev *cdev) +{ + return true; +} + static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params) { @@ -1177,6 +1182,7 @@ const struct qed_common_ops qed_common_ops_pass = { .sb_release = &qed_sb_release, .simd_handler_config = &qed_simd_handler_config, .simd_handler_clean = &qed_simd_handler_clean, + .can_link_change = &qed_can_link_change, .set_link = &qed_set_link, .get_link = &qed_get_current_link, .drain = &qed_drain, diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 2ac98d44c1e1..f1dd25ac5552 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -239,9 +239,9 @@ static int qede_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct qed_link_params params; u32 speed; - if (!edev->dev_info.common.is_mf_default) { + if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { DP_INFO(edev, - "Link parameters can not be changed in non-default mode\n"); + "Link settings are not allowed to be changed\n"); return -EOPNOTSUPP; } @@ -350,6 +350,12 @@ static int qede_nway_reset(struct net_device *dev) struct qed_link_output current_link; struct qed_link_params link_params; + if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { + DP_INFO(edev, + "Link settings are not allowed to be changed\n"); + return -EOPNOTSUPP; + } + if (!netif_running(dev)) return 0; @@ -450,9 +456,9 @@ static int qede_set_pauseparam(struct net_device *dev, struct qed_link_params params; struct qed_link_output current_link; - if (!edev->dev_info.common.is_mf_default) { + if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { DP_INFO(edev, - "Pause parameters can not be updated in non-default mode\n"); + "Pause settings are not allowed to be changed\n"); return -EOPNOTSUPP; } diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 82a7fe011068..e5de42b62976 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -211,6 +211,16 @@ struct qed_common_ops { void (*simd_handler_clean)(struct qed_dev *cdev, int index); + +/** + * @brief can_link_change - can the instance change the link or not + * + * @param cdev + * + * @return true if link-change is allowed, false otherwise. + */ + bool (*can_link_change)(struct qed_dev *cdev); + /** * @brief set_link - set links according to params * -- GitLab From a43f235f12e9da60a7e181f6a9524ea1e212e39d Mon Sep 17 00:00:00 2001 From: Sudarsana Reddy Kalluru Date: Fri, 22 Apr 2016 08:41:04 +0300 Subject: [PATCH 4279/9938] qed: add support for link pause configuration. The APIs for making this sort of configuration [e.g., via ethtool] are already present in qede, but the current configuration flow in qed doesn't respect it. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index d189871e8e23..1918b83f0a97 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -962,6 +962,20 @@ static int qed_set_link(struct qed_dev *cdev, } if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) link_params->speed.forced_speed = params->forced_speed; + if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) { + if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) + link_params->pause.autoneg = true; + else + link_params->pause.autoneg = false; + if (params->pause_config & QED_LINK_PAUSE_RX_ENABLE) + link_params->pause.forced_rx = true; + else + link_params->pause.forced_rx = false; + if (params->pause_config & QED_LINK_PAUSE_TX_ENABLE) + link_params->pause.forced_tx = true; + else + link_params->pause.forced_tx = false; + } rc = qed_mcp_set_link(hwfn, ptt, params->link_up); -- GitLab From 0868e2538e45a9ed68e2b14adc42b020a36aae1d Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Fri, 22 Apr 2016 12:40:02 +0200 Subject: [PATCH 4280/9938] route: move lwtunnel state to a single place Commit 751a587ac9f9 ("route: fix breakage after moving lwtunnel state") moved lwtstate to the end of dst_entry for 32bit archs. This makes it share the cacheline with __refcnt which had an unkown effect on performance. For this reason, the pointer was kept in place for 64bit archs. However, later performance measurements showed this is of no concern. It turns out that every performance sensitive path that accesses lwtstate accesses also struct rtable or struct rt6_info which share the same cache line. Thus, to get rid of a few #ifdefs, move the field to the end of the struct also for 64bit. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- include/net/dst.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 5c98443c1c9e..6835d224d47b 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -85,12 +85,11 @@ struct dst_entry { #endif #ifdef CONFIG_64BIT - struct lwtunnel_state *lwtstate; /* * Align __refcnt to a 64 bytes alignment * (L1_CACHE_SIZE would be too much) */ - long __pad_to_align_refcnt[1]; + long __pad_to_align_refcnt[2]; #endif /* * __refcnt wants to be on a different cache line from @@ -99,9 +98,7 @@ struct dst_entry { atomic_t __refcnt; /* client references */ int __use; unsigned long lastuse; -#ifndef CONFIG_64BIT struct lwtunnel_state *lwtstate; -#endif union { struct dst_entry *next; struct rtable __rcu *rt_next; -- GitLab From e425974feaa545575135f04e646f0495439b4c54 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 22 Apr 2016 14:02:42 +0200 Subject: [PATCH 4281/9938] macsec: Convert to using IFF_NO_QUEUE Signed-off-by: Phil Sutter Acked-by: Sabrina Dubroca Signed-off-by: David S. Miller --- drivers/net/macsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 84d3e5ca8817..6caa72402de7 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2826,7 +2826,7 @@ static void macsec_free_netdev(struct net_device *dev) static void macsec_setup(struct net_device *dev) { ether_setup(dev); - dev->tx_queue_len = 0; + dev->priv_flags |= IFF_NO_QUEUE; dev->netdev_ops = &macsec_netdev_ops; dev->destructor = macsec_free_netdev; -- GitLab From 79bdc4c862af7cf11a135a6fdf8093622043c862 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 22 Apr 2016 14:15:58 +0200 Subject: [PATCH 4282/9938] codel: generalize the implementation This strips out qdisc specific bits from the code and makes it slightly more reusable. Codel will be used by wireless/mac80211 in the future. Signed-off-by: Michal Kazior Signed-off-by: David S. Miller --- include/net/codel.h | 64 ++++++++++++++++++++++++---------------- net/sched/sch_codel.c | 20 +++++++++++-- net/sched/sch_fq_codel.c | 19 +++++++++--- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/include/net/codel.h b/include/net/codel.h index d168aca115cc..06ac687b4909 100644 --- a/include/net/codel.h +++ b/include/net/codel.h @@ -176,12 +176,10 @@ struct codel_stats { #define CODEL_DISABLED_THRESHOLD INT_MAX -static void codel_params_init(struct codel_params *params, - const struct Qdisc *sch) +static void codel_params_init(struct codel_params *params) { params->interval = MS2TIME(100); params->target = MS2TIME(5); - params->mtu = psched_mtu(qdisc_dev(sch)); params->ce_threshold = CODEL_DISABLED_THRESHOLD; params->ecn = false; } @@ -226,28 +224,38 @@ static codel_time_t codel_control_law(codel_time_t t, return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT); } +typedef u32 (*codel_skb_len_t)(const struct sk_buff *skb); +typedef codel_time_t (*codel_skb_time_t)(const struct sk_buff *skb); +typedef void (*codel_skb_drop_t)(struct sk_buff *skb, void *ctx); +typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars, + void *ctx); + static bool codel_should_drop(const struct sk_buff *skb, - struct Qdisc *sch, + void *ctx, struct codel_vars *vars, struct codel_params *params, struct codel_stats *stats, + codel_skb_len_t skb_len_func, + codel_skb_time_t skb_time_func, + u32 *backlog, codel_time_t now) { bool ok_to_drop; + u32 skb_len; if (!skb) { vars->first_above_time = 0; return false; } - vars->ldelay = now - codel_get_enqueue_time(skb); - sch->qstats.backlog -= qdisc_pkt_len(skb); + skb_len = skb_len_func(skb); + vars->ldelay = now - skb_time_func(skb); - if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket)) - stats->maxpacket = qdisc_pkt_len(skb); + if (unlikely(skb_len > stats->maxpacket)) + stats->maxpacket = skb_len; if (codel_time_before(vars->ldelay, params->target) || - sch->qstats.backlog <= params->mtu) { + *backlog <= params->mtu) { /* went below - stay below for at least interval */ vars->first_above_time = 0; return false; @@ -264,16 +272,17 @@ static bool codel_should_drop(const struct sk_buff *skb, return ok_to_drop; } -typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars, - struct Qdisc *sch); - -static struct sk_buff *codel_dequeue(struct Qdisc *sch, +static struct sk_buff *codel_dequeue(void *ctx, + u32 *backlog, struct codel_params *params, struct codel_vars *vars, struct codel_stats *stats, + codel_skb_len_t skb_len_func, + codel_skb_time_t skb_time_func, + codel_skb_drop_t drop_func, codel_skb_dequeue_t dequeue_func) { - struct sk_buff *skb = dequeue_func(vars, sch); + struct sk_buff *skb = dequeue_func(vars, ctx); codel_time_t now; bool drop; @@ -282,7 +291,8 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, return skb; } now = codel_get_time(); - drop = codel_should_drop(skb, sch, vars, params, stats, now); + drop = codel_should_drop(skb, ctx, vars, params, stats, + skb_len_func, skb_time_func, backlog, now); if (vars->dropping) { if (!drop) { /* sojourn time below target - leave dropping state */ @@ -310,12 +320,15 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, vars->rec_inv_sqrt); goto end; } - stats->drop_len += qdisc_pkt_len(skb); - qdisc_drop(skb, sch); + stats->drop_len += skb_len_func(skb); + drop_func(skb, ctx); stats->drop_count++; - skb = dequeue_func(vars, sch); - if (!codel_should_drop(skb, sch, - vars, params, stats, now)) { + skb = dequeue_func(vars, ctx); + if (!codel_should_drop(skb, ctx, + vars, params, stats, + skb_len_func, + skb_time_func, + backlog, now)) { /* leave dropping state */ vars->dropping = false; } else { @@ -333,13 +346,14 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, if (params->ecn && INET_ECN_set_ce(skb)) { stats->ecn_mark++; } else { - stats->drop_len += qdisc_pkt_len(skb); - qdisc_drop(skb, sch); + stats->drop_len += skb_len_func(skb); + drop_func(skb, ctx); stats->drop_count++; - skb = dequeue_func(vars, sch); - drop = codel_should_drop(skb, sch, vars, params, - stats, now); + skb = dequeue_func(vars, ctx); + drop = codel_should_drop(skb, ctx, vars, params, + stats, skb_len_func, + skb_time_func, backlog, now); } vars->dropping = true; /* if min went above target close to when we last went below it diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index 9b7e2980ee5c..512a94abe351 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c @@ -64,20 +64,33 @@ struct codel_sched_data { * to dequeue a packet from queue. Note: backlog is handled in * codel, we dont need to reduce it here. */ -static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch) +static struct sk_buff *dequeue_func(struct codel_vars *vars, void *ctx) { + struct Qdisc *sch = ctx; struct sk_buff *skb = __skb_dequeue(&sch->q); + if (skb) + sch->qstats.backlog -= qdisc_pkt_len(skb); + prefetch(&skb->end); /* we'll need skb_shinfo() */ return skb; } +static void drop_func(struct sk_buff *skb, void *ctx) +{ + struct Qdisc *sch = ctx; + + qdisc_drop(skb, sch); +} + static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch) { struct codel_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; - skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue); + skb = codel_dequeue(sch, &sch->qstats.backlog, &q->params, &q->vars, + &q->stats, qdisc_pkt_len, codel_get_enqueue_time, + drop_func, dequeue_func); /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, * or HTB crashes. Defer it for next round. @@ -173,9 +186,10 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt) sch->limit = DEFAULT_CODEL_LIMIT; - codel_params_init(&q->params, sch); + codel_params_init(&q->params); codel_vars_init(&q->vars); codel_stats_init(&q->stats); + q->params.mtu = psched_mtu(qdisc_dev(sch)); if (opt) { int err = codel_change(sch, opt); diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index d3fc8f9dd3d4..dcf7266e6901 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -220,8 +220,9 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) * to dequeue a packet from queue. Note: backlog is handled in * codel, we dont need to reduce it here. */ -static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch) +static struct sk_buff *dequeue_func(struct codel_vars *vars, void *ctx) { + struct Qdisc *sch = ctx; struct fq_codel_sched_data *q = qdisc_priv(sch); struct fq_codel_flow *flow; struct sk_buff *skb = NULL; @@ -231,10 +232,18 @@ static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch) skb = dequeue_head(flow); q->backlogs[flow - q->flows] -= qdisc_pkt_len(skb); sch->q.qlen--; + sch->qstats.backlog -= qdisc_pkt_len(skb); } return skb; } +static void drop_func(struct sk_buff *skb, void *ctx) +{ + struct Qdisc *sch = ctx; + + qdisc_drop(skb, sch); +} + static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch) { struct fq_codel_sched_data *q = qdisc_priv(sch); @@ -263,8 +272,9 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch) prev_ecn_mark = q->cstats.ecn_mark; prev_backlog = sch->qstats.backlog; - skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats, - dequeue); + skb = codel_dequeue(sch, &sch->qstats.backlog, &q->cparams, + &flow->cvars, &q->cstats, qdisc_pkt_len, + codel_get_enqueue_time, drop_func, dequeue_func); flow->dropped += q->cstats.drop_count - prev_drop_count; flow->dropped += q->cstats.ecn_mark - prev_ecn_mark; @@ -423,9 +433,10 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) q->perturbation = prandom_u32(); INIT_LIST_HEAD(&q->new_flows); INIT_LIST_HEAD(&q->old_flows); - codel_params_init(&q->cparams, sch); + codel_params_init(&q->cparams); codel_stats_init(&q->cstats); q->cparams.ecn = true; + q->cparams.mtu = psched_mtu(qdisc_dev(sch)); if (opt) { int err = fq_codel_change(sch, opt); -- GitLab From d068ca2ae2e614b9a418fb3b5f1fd4cf996ff032 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 22 Apr 2016 14:15:59 +0200 Subject: [PATCH 4283/9938] codel: split into multiple files It was impossible to include codel.h for the purpose of having access to codel_params or codel_vars structure definitions and using them for embedding in other more complex structures. This splits allows codel.h itself to be treated like any other header file while codel_qdisc.h and codel_impl.h contain function definitions with logic that was previously in codel.h. This copies over copyrights and doesn't involve code changes other than adding a few additional include directives to net/sched/sch*codel.c. Signed-off-by: Michal Kazior Signed-off-by: David S. Miller --- include/net/codel.h | 223 --------------------------------- include/net/codel_impl.h | 255 ++++++++++++++++++++++++++++++++++++++ include/net/codel_qdisc.h | 73 +++++++++++ net/sched/sch_codel.c | 2 + net/sched/sch_fq_codel.c | 2 + 5 files changed, 332 insertions(+), 223 deletions(-) create mode 100644 include/net/codel_impl.h create mode 100644 include/net/codel_qdisc.h diff --git a/include/net/codel.h b/include/net/codel.h index 06ac687b4909..a6e428f80135 100644 --- a/include/net/codel.h +++ b/include/net/codel.h @@ -87,27 +87,6 @@ static inline codel_time_t codel_get_time(void) ((s32)((a) - (b)) >= 0)) #define codel_time_before_eq(a, b) codel_time_after_eq(b, a) -/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */ -struct codel_skb_cb { - codel_time_t enqueue_time; -}; - -static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb) -{ - qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb)); - return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data; -} - -static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb) -{ - return get_codel_cb(skb)->enqueue_time; -} - -static void codel_set_enqueue_time(struct sk_buff *skb) -{ - get_codel_cb(skb)->enqueue_time = codel_get_time(); -} - static inline u32 codel_time_to_us(codel_time_t val) { u64 valns = ((u64)val << CODEL_SHIFT); @@ -176,212 +155,10 @@ struct codel_stats { #define CODEL_DISABLED_THRESHOLD INT_MAX -static void codel_params_init(struct codel_params *params) -{ - params->interval = MS2TIME(100); - params->target = MS2TIME(5); - params->ce_threshold = CODEL_DISABLED_THRESHOLD; - params->ecn = false; -} - -static void codel_vars_init(struct codel_vars *vars) -{ - memset(vars, 0, sizeof(*vars)); -} - -static void codel_stats_init(struct codel_stats *stats) -{ - stats->maxpacket = 0; -} - -/* - * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots - * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) - * - * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32 - */ -static void codel_Newton_step(struct codel_vars *vars) -{ - u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT; - u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32; - u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2); - - val >>= 2; /* avoid overflow in following multiply */ - val = (val * invsqrt) >> (32 - 2 + 1); - - vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT; -} - -/* - * CoDel control_law is t + interval/sqrt(count) - * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid - * both sqrt() and divide operation. - */ -static codel_time_t codel_control_law(codel_time_t t, - codel_time_t interval, - u32 rec_inv_sqrt) -{ - return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT); -} - typedef u32 (*codel_skb_len_t)(const struct sk_buff *skb); typedef codel_time_t (*codel_skb_time_t)(const struct sk_buff *skb); typedef void (*codel_skb_drop_t)(struct sk_buff *skb, void *ctx); typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars, void *ctx); -static bool codel_should_drop(const struct sk_buff *skb, - void *ctx, - struct codel_vars *vars, - struct codel_params *params, - struct codel_stats *stats, - codel_skb_len_t skb_len_func, - codel_skb_time_t skb_time_func, - u32 *backlog, - codel_time_t now) -{ - bool ok_to_drop; - u32 skb_len; - - if (!skb) { - vars->first_above_time = 0; - return false; - } - - skb_len = skb_len_func(skb); - vars->ldelay = now - skb_time_func(skb); - - if (unlikely(skb_len > stats->maxpacket)) - stats->maxpacket = skb_len; - - if (codel_time_before(vars->ldelay, params->target) || - *backlog <= params->mtu) { - /* went below - stay below for at least interval */ - vars->first_above_time = 0; - return false; - } - ok_to_drop = false; - if (vars->first_above_time == 0) { - /* just went above from below. If we stay above - * for at least interval we'll say it's ok to drop - */ - vars->first_above_time = now + params->interval; - } else if (codel_time_after(now, vars->first_above_time)) { - ok_to_drop = true; - } - return ok_to_drop; -} - -static struct sk_buff *codel_dequeue(void *ctx, - u32 *backlog, - struct codel_params *params, - struct codel_vars *vars, - struct codel_stats *stats, - codel_skb_len_t skb_len_func, - codel_skb_time_t skb_time_func, - codel_skb_drop_t drop_func, - codel_skb_dequeue_t dequeue_func) -{ - struct sk_buff *skb = dequeue_func(vars, ctx); - codel_time_t now; - bool drop; - - if (!skb) { - vars->dropping = false; - return skb; - } - now = codel_get_time(); - drop = codel_should_drop(skb, ctx, vars, params, stats, - skb_len_func, skb_time_func, backlog, now); - if (vars->dropping) { - if (!drop) { - /* sojourn time below target - leave dropping state */ - vars->dropping = false; - } else if (codel_time_after_eq(now, vars->drop_next)) { - /* It's time for the next drop. Drop the current - * packet and dequeue the next. The dequeue might - * take us out of dropping state. - * If not, schedule the next drop. - * A large backlog might result in drop rates so high - * that the next drop should happen now, - * hence the while loop. - */ - while (vars->dropping && - codel_time_after_eq(now, vars->drop_next)) { - vars->count++; /* dont care of possible wrap - * since there is no more divide - */ - codel_Newton_step(vars); - if (params->ecn && INET_ECN_set_ce(skb)) { - stats->ecn_mark++; - vars->drop_next = - codel_control_law(vars->drop_next, - params->interval, - vars->rec_inv_sqrt); - goto end; - } - stats->drop_len += skb_len_func(skb); - drop_func(skb, ctx); - stats->drop_count++; - skb = dequeue_func(vars, ctx); - if (!codel_should_drop(skb, ctx, - vars, params, stats, - skb_len_func, - skb_time_func, - backlog, now)) { - /* leave dropping state */ - vars->dropping = false; - } else { - /* and schedule the next drop */ - vars->drop_next = - codel_control_law(vars->drop_next, - params->interval, - vars->rec_inv_sqrt); - } - } - } - } else if (drop) { - u32 delta; - - if (params->ecn && INET_ECN_set_ce(skb)) { - stats->ecn_mark++; - } else { - stats->drop_len += skb_len_func(skb); - drop_func(skb, ctx); - stats->drop_count++; - - skb = dequeue_func(vars, ctx); - drop = codel_should_drop(skb, ctx, vars, params, - stats, skb_len_func, - skb_time_func, backlog, now); - } - vars->dropping = true; - /* if min went above target close to when we last went below it - * assume that the drop rate that controlled the queue on the - * last cycle is a good starting point to control it now. - */ - delta = vars->count - vars->lastcount; - if (delta > 1 && - codel_time_before(now - vars->drop_next, - 16 * params->interval)) { - vars->count = delta; - /* we dont care if rec_inv_sqrt approximation - * is not very precise : - * Next Newton steps will correct it quadratically. - */ - codel_Newton_step(vars); - } else { - vars->count = 1; - vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT; - } - vars->lastcount = vars->count; - vars->drop_next = codel_control_law(now, params->interval, - vars->rec_inv_sqrt); - } -end: - if (skb && codel_time_after(vars->ldelay, params->ce_threshold) && - INET_ECN_set_ce(skb)) - stats->ce_mark++; - return skb; -} #endif diff --git a/include/net/codel_impl.h b/include/net/codel_impl.h new file mode 100644 index 000000000000..d289b91dcd65 --- /dev/null +++ b/include/net/codel_impl.h @@ -0,0 +1,255 @@ +#ifndef __NET_SCHED_CODEL_IMPL_H +#define __NET_SCHED_CODEL_IMPL_H + +/* + * Codel - The Controlled-Delay Active Queue Management algorithm + * + * Copyright (C) 2011-2012 Kathleen Nichols + * Copyright (C) 2011-2012 Van Jacobson + * Copyright (C) 2012 Michael D. Taht + * Copyright (C) 2012,2015 Eric Dumazet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + */ + +/* Controlling Queue Delay (CoDel) algorithm + * ========================================= + * Source : Kathleen Nichols and Van Jacobson + * http://queue.acm.org/detail.cfm?id=2209336 + * + * Implemented on linux by Dave Taht and Eric Dumazet + */ + +static void codel_params_init(struct codel_params *params) +{ + params->interval = MS2TIME(100); + params->target = MS2TIME(5); + params->ce_threshold = CODEL_DISABLED_THRESHOLD; + params->ecn = false; +} + +static void codel_vars_init(struct codel_vars *vars) +{ + memset(vars, 0, sizeof(*vars)); +} + +static void codel_stats_init(struct codel_stats *stats) +{ + stats->maxpacket = 0; +} + +/* + * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots + * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) + * + * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32 + */ +static void codel_Newton_step(struct codel_vars *vars) +{ + u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT; + u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32; + u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2); + + val >>= 2; /* avoid overflow in following multiply */ + val = (val * invsqrt) >> (32 - 2 + 1); + + vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT; +} + +/* + * CoDel control_law is t + interval/sqrt(count) + * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid + * both sqrt() and divide operation. + */ +static codel_time_t codel_control_law(codel_time_t t, + codel_time_t interval, + u32 rec_inv_sqrt) +{ + return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT); +} + +static bool codel_should_drop(const struct sk_buff *skb, + void *ctx, + struct codel_vars *vars, + struct codel_params *params, + struct codel_stats *stats, + codel_skb_len_t skb_len_func, + codel_skb_time_t skb_time_func, + u32 *backlog, + codel_time_t now) +{ + bool ok_to_drop; + u32 skb_len; + + if (!skb) { + vars->first_above_time = 0; + return false; + } + + skb_len = skb_len_func(skb); + vars->ldelay = now - skb_time_func(skb); + + if (unlikely(skb_len > stats->maxpacket)) + stats->maxpacket = skb_len; + + if (codel_time_before(vars->ldelay, params->target) || + *backlog <= params->mtu) { + /* went below - stay below for at least interval */ + vars->first_above_time = 0; + return false; + } + ok_to_drop = false; + if (vars->first_above_time == 0) { + /* just went above from below. If we stay above + * for at least interval we'll say it's ok to drop + */ + vars->first_above_time = now + params->interval; + } else if (codel_time_after(now, vars->first_above_time)) { + ok_to_drop = true; + } + return ok_to_drop; +} + +static struct sk_buff *codel_dequeue(void *ctx, + u32 *backlog, + struct codel_params *params, + struct codel_vars *vars, + struct codel_stats *stats, + codel_skb_len_t skb_len_func, + codel_skb_time_t skb_time_func, + codel_skb_drop_t drop_func, + codel_skb_dequeue_t dequeue_func) +{ + struct sk_buff *skb = dequeue_func(vars, ctx); + codel_time_t now; + bool drop; + + if (!skb) { + vars->dropping = false; + return skb; + } + now = codel_get_time(); + drop = codel_should_drop(skb, ctx, vars, params, stats, + skb_len_func, skb_time_func, backlog, now); + if (vars->dropping) { + if (!drop) { + /* sojourn time below target - leave dropping state */ + vars->dropping = false; + } else if (codel_time_after_eq(now, vars->drop_next)) { + /* It's time for the next drop. Drop the current + * packet and dequeue the next. The dequeue might + * take us out of dropping state. + * If not, schedule the next drop. + * A large backlog might result in drop rates so high + * that the next drop should happen now, + * hence the while loop. + */ + while (vars->dropping && + codel_time_after_eq(now, vars->drop_next)) { + vars->count++; /* dont care of possible wrap + * since there is no more divide + */ + codel_Newton_step(vars); + if (params->ecn && INET_ECN_set_ce(skb)) { + stats->ecn_mark++; + vars->drop_next = + codel_control_law(vars->drop_next, + params->interval, + vars->rec_inv_sqrt); + goto end; + } + stats->drop_len += skb_len_func(skb); + drop_func(skb, ctx); + stats->drop_count++; + skb = dequeue_func(vars, ctx); + if (!codel_should_drop(skb, ctx, + vars, params, stats, + skb_len_func, + skb_time_func, + backlog, now)) { + /* leave dropping state */ + vars->dropping = false; + } else { + /* and schedule the next drop */ + vars->drop_next = + codel_control_law(vars->drop_next, + params->interval, + vars->rec_inv_sqrt); + } + } + } + } else if (drop) { + u32 delta; + + if (params->ecn && INET_ECN_set_ce(skb)) { + stats->ecn_mark++; + } else { + stats->drop_len += skb_len_func(skb); + drop_func(skb, ctx); + stats->drop_count++; + + skb = dequeue_func(vars, ctx); + drop = codel_should_drop(skb, ctx, vars, params, + stats, skb_len_func, + skb_time_func, backlog, now); + } + vars->dropping = true; + /* if min went above target close to when we last went below it + * assume that the drop rate that controlled the queue on the + * last cycle is a good starting point to control it now. + */ + delta = vars->count - vars->lastcount; + if (delta > 1 && + codel_time_before(now - vars->drop_next, + 16 * params->interval)) { + vars->count = delta; + /* we dont care if rec_inv_sqrt approximation + * is not very precise : + * Next Newton steps will correct it quadratically. + */ + codel_Newton_step(vars); + } else { + vars->count = 1; + vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT; + } + vars->lastcount = vars->count; + vars->drop_next = codel_control_law(now, params->interval, + vars->rec_inv_sqrt); + } +end: + if (skb && codel_time_after(vars->ldelay, params->ce_threshold) && + INET_ECN_set_ce(skb)) + stats->ce_mark++; + return skb; +} + +#endif diff --git a/include/net/codel_qdisc.h b/include/net/codel_qdisc.h new file mode 100644 index 000000000000..8144d9cd2908 --- /dev/null +++ b/include/net/codel_qdisc.h @@ -0,0 +1,73 @@ +#ifndef __NET_SCHED_CODEL_QDISC_H +#define __NET_SCHED_CODEL_QDISC_H + +/* + * Codel - The Controlled-Delay Active Queue Management algorithm + * + * Copyright (C) 2011-2012 Kathleen Nichols + * Copyright (C) 2011-2012 Van Jacobson + * Copyright (C) 2012 Michael D. Taht + * Copyright (C) 2012,2015 Eric Dumazet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + */ + +/* Controlling Queue Delay (CoDel) algorithm + * ========================================= + * Source : Kathleen Nichols and Van Jacobson + * http://queue.acm.org/detail.cfm?id=2209336 + * + * Implemented on linux by Dave Taht and Eric Dumazet + */ + +/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */ +struct codel_skb_cb { + codel_time_t enqueue_time; +}; + +static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb) +{ + qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb)); + return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data; +} + +static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb) +{ + return get_codel_cb(skb)->enqueue_time; +} + +static void codel_set_enqueue_time(struct sk_buff *skb) +{ + get_codel_cb(skb)->enqueue_time = codel_get_time(); +} + +#endif diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index 512a94abe351..dddf3bb65a32 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c @@ -49,6 +49,8 @@ #include #include #include +#include +#include #define DEFAULT_CODEL_LIMIT 1000 diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index dcf7266e6901..a5e420b3d4ab 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include /* Fair Queue CoDel. * -- GitLab From 557fc4a098039cf296fe33f118bab99a925fd881 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 22 Apr 2016 14:20:13 +0200 Subject: [PATCH 4284/9938] fq: add fair queuing framework This works on the same implementation principle as codel*.h, i.e. there's a generic header with structures and macros and a implementation header carrying function definitions to include in given, e.g. driver or module. The fairness logic comes from net/sched/sch_fq_codel.c but is generalized so it is more flexible and easier to re-use. Signed-off-by: Michal Kazior Signed-off-by: David S. Miller --- include/net/fq.h | 95 +++++++++++++++ include/net/fq_impl.h | 269 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 364 insertions(+) create mode 100644 include/net/fq.h create mode 100644 include/net/fq_impl.h diff --git a/include/net/fq.h b/include/net/fq.h new file mode 100644 index 000000000000..268b49049c37 --- /dev/null +++ b/include/net/fq.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016 Qualcomm Atheros, Inc + * + * GPL v2 + * + * Based on net/sched/sch_fq_codel.c + */ +#ifndef __NET_SCHED_FQ_H +#define __NET_SCHED_FQ_H + +struct fq_tin; + +/** + * struct fq_flow - per traffic flow queue + * + * @tin: owner of this flow. Used to manage collisions, i.e. when a packet + * hashes to an index which points to a flow that is already owned by a + * different tin the packet is destined to. In such case the implementer + * must provide a fallback flow + * @flowchain: can be linked to fq_tin's new_flows or old_flows. Used for DRR++ + * (deficit round robin) based round robin queuing similar to the one + * found in net/sched/sch_fq_codel.c + * @backlogchain: can be linked to other fq_flow and fq. Used to keep track of + * fat flows and efficient head-dropping if packet limit is reached + * @queue: sk_buff queue to hold packets + * @backlog: number of bytes pending in the queue. The number of packets can be + * found in @queue.qlen + * @deficit: used for DRR++ + */ +struct fq_flow { + struct fq_tin *tin; + struct list_head flowchain; + struct list_head backlogchain; + struct sk_buff_head queue; + u32 backlog; + int deficit; +}; + +/** + * struct fq_tin - a logical container of fq_flows + * + * Used to group fq_flows into a logical aggregate. DRR++ scheme is used to + * pull interleaved packets out of the associated flows. + * + * @new_flows: linked list of fq_flow + * @old_flows: linked list of fq_flow + */ +struct fq_tin { + struct list_head new_flows; + struct list_head old_flows; + u32 backlog_bytes; + u32 backlog_packets; + u32 overlimit; + u32 collisions; + u32 flows; + u32 tx_bytes; + u32 tx_packets; +}; + +/** + * struct fq - main container for fair queuing purposes + * + * @backlogs: linked to fq_flows. Used to maintain fat flows for efficient + * head-dropping when @backlog reaches @limit + * @limit: max number of packets that can be queued across all flows + * @backlog: number of packets queued across all flows + */ +struct fq { + struct fq_flow *flows; + struct list_head backlogs; + spinlock_t lock; + u32 flows_cnt; + u32 perturbation; + u32 limit; + u32 quantum; + u32 backlog; + u32 overlimit; + u32 collisions; +}; + +typedef struct sk_buff *fq_tin_dequeue_t(struct fq *, + struct fq_tin *, + struct fq_flow *flow); + +typedef void fq_skb_free_t(struct fq *, + struct fq_tin *, + struct fq_flow *, + struct sk_buff *); + +typedef struct fq_flow *fq_flow_get_default_t(struct fq *, + struct fq_tin *, + int idx, + struct sk_buff *); + +#endif diff --git a/include/net/fq_impl.h b/include/net/fq_impl.h new file mode 100644 index 000000000000..02eab7c51adb --- /dev/null +++ b/include/net/fq_impl.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2016 Qualcomm Atheros, Inc + * + * GPL v2 + * + * Based on net/sched/sch_fq_codel.c + */ +#ifndef __NET_SCHED_FQ_IMPL_H +#define __NET_SCHED_FQ_IMPL_H + +#include + +/* functions that are embedded into includer */ + +static struct sk_buff *fq_flow_dequeue(struct fq *fq, + struct fq_flow *flow) +{ + struct fq_tin *tin = flow->tin; + struct fq_flow *i; + struct sk_buff *skb; + + lockdep_assert_held(&fq->lock); + + skb = __skb_dequeue(&flow->queue); + if (!skb) + return NULL; + + tin->backlog_bytes -= skb->len; + tin->backlog_packets--; + flow->backlog -= skb->len; + fq->backlog--; + + if (flow->backlog == 0) { + list_del_init(&flow->backlogchain); + } else { + i = flow; + + list_for_each_entry_continue(i, &fq->backlogs, backlogchain) + if (i->backlog < flow->backlog) + break; + + list_move_tail(&flow->backlogchain, + &i->backlogchain); + } + + return skb; +} + +static struct sk_buff *fq_tin_dequeue(struct fq *fq, + struct fq_tin *tin, + fq_tin_dequeue_t dequeue_func) +{ + struct fq_flow *flow; + struct list_head *head; + struct sk_buff *skb; + + lockdep_assert_held(&fq->lock); + +begin: + head = &tin->new_flows; + if (list_empty(head)) { + head = &tin->old_flows; + if (list_empty(head)) + return NULL; + } + + flow = list_first_entry(head, struct fq_flow, flowchain); + + if (flow->deficit <= 0) { + flow->deficit += fq->quantum; + list_move_tail(&flow->flowchain, + &tin->old_flows); + goto begin; + } + + skb = dequeue_func(fq, tin, flow); + if (!skb) { + /* force a pass through old_flows to prevent starvation */ + if ((head == &tin->new_flows) && + !list_empty(&tin->old_flows)) { + list_move_tail(&flow->flowchain, &tin->old_flows); + } else { + list_del_init(&flow->flowchain); + flow->tin = NULL; + } + goto begin; + } + + flow->deficit -= skb->len; + tin->tx_bytes += skb->len; + tin->tx_packets++; + + return skb; +} + +static struct fq_flow *fq_flow_classify(struct fq *fq, + struct fq_tin *tin, + struct sk_buff *skb, + fq_flow_get_default_t get_default_func) +{ + struct fq_flow *flow; + u32 hash; + u32 idx; + + lockdep_assert_held(&fq->lock); + + hash = skb_get_hash_perturb(skb, fq->perturbation); + idx = reciprocal_scale(hash, fq->flows_cnt); + flow = &fq->flows[idx]; + + if (flow->tin && flow->tin != tin) { + flow = get_default_func(fq, tin, idx, skb); + tin->collisions++; + fq->collisions++; + } + + if (!flow->tin) + tin->flows++; + + return flow; +} + +static void fq_tin_enqueue(struct fq *fq, + struct fq_tin *tin, + struct sk_buff *skb, + fq_skb_free_t free_func, + fq_flow_get_default_t get_default_func) +{ + struct fq_flow *flow; + struct fq_flow *i; + + lockdep_assert_held(&fq->lock); + + flow = fq_flow_classify(fq, tin, skb, get_default_func); + + flow->tin = tin; + flow->backlog += skb->len; + tin->backlog_bytes += skb->len; + tin->backlog_packets++; + fq->backlog++; + + if (list_empty(&flow->backlogchain)) + list_add_tail(&flow->backlogchain, &fq->backlogs); + + i = flow; + list_for_each_entry_continue_reverse(i, &fq->backlogs, + backlogchain) + if (i->backlog > flow->backlog) + break; + + list_move(&flow->backlogchain, &i->backlogchain); + + if (list_empty(&flow->flowchain)) { + flow->deficit = fq->quantum; + list_add_tail(&flow->flowchain, + &tin->new_flows); + } + + __skb_queue_tail(&flow->queue, skb); + + if (fq->backlog > fq->limit) { + flow = list_first_entry_or_null(&fq->backlogs, + struct fq_flow, + backlogchain); + if (!flow) + return; + + skb = fq_flow_dequeue(fq, flow); + if (!skb) + return; + + free_func(fq, flow->tin, flow, skb); + + flow->tin->overlimit++; + fq->overlimit++; + } +} + +static void fq_flow_reset(struct fq *fq, + struct fq_flow *flow, + fq_skb_free_t free_func) +{ + struct sk_buff *skb; + + while ((skb = fq_flow_dequeue(fq, flow))) + free_func(fq, flow->tin, flow, skb); + + if (!list_empty(&flow->flowchain)) + list_del_init(&flow->flowchain); + + if (!list_empty(&flow->backlogchain)) + list_del_init(&flow->backlogchain); + + flow->tin = NULL; + + WARN_ON_ONCE(flow->backlog); +} + +static void fq_tin_reset(struct fq *fq, + struct fq_tin *tin, + fq_skb_free_t free_func) +{ + struct list_head *head; + struct fq_flow *flow; + + for (;;) { + head = &tin->new_flows; + if (list_empty(head)) { + head = &tin->old_flows; + if (list_empty(head)) + break; + } + + flow = list_first_entry(head, struct fq_flow, flowchain); + fq_flow_reset(fq, flow, free_func); + } + + WARN_ON_ONCE(tin->backlog_bytes); + WARN_ON_ONCE(tin->backlog_packets); +} + +static void fq_flow_init(struct fq_flow *flow) +{ + INIT_LIST_HEAD(&flow->flowchain); + INIT_LIST_HEAD(&flow->backlogchain); + __skb_queue_head_init(&flow->queue); +} + +static void fq_tin_init(struct fq_tin *tin) +{ + INIT_LIST_HEAD(&tin->new_flows); + INIT_LIST_HEAD(&tin->old_flows); +} + +static int fq_init(struct fq *fq, int flows_cnt) +{ + int i; + + memset(fq, 0, sizeof(fq[0])); + INIT_LIST_HEAD(&fq->backlogs); + spin_lock_init(&fq->lock); + fq->flows_cnt = max_t(u32, flows_cnt, 1); + fq->perturbation = prandom_u32(); + fq->quantum = 300; + fq->limit = 8192; + + fq->flows = kcalloc(fq->flows_cnt, sizeof(fq->flows[0]), GFP_KERNEL); + if (!fq->flows) + return -ENOMEM; + + for (i = 0; i < fq->flows_cnt; i++) + fq_flow_init(&fq->flows[i]); + + return 0; +} + +static void fq_reset(struct fq *fq, + fq_skb_free_t free_func) +{ + int i; + + for (i = 0; i < fq->flows_cnt; i++) + fq_flow_reset(fq, &fq->flows[i], free_func); + + kfree(fq->flows); + fq->flows = NULL; +} + +#endif -- GitLab From f73b5042b9a9c45477246acd478bf49487197a31 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:06:49 +0800 Subject: [PATCH 4285/9938] clk: rockchip: add general gpu soft-reset on rk3399 Add the id for the general gpu soft-reset, that got documented only in newer TRM versions. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3399-cru.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h index f60fe6e4b16e..3370bde7fa38 100644 --- a/include/dt-bindings/clock/rk3399-cru.h +++ b/include/dt-bindings/clock/rk3399-cru.h @@ -671,6 +671,7 @@ #define SRST_P_EDP_CTRL 285 /* cru_softrst_con18 */ +#define SRST_A_GPU 288 #define SRST_A_GPU_NOC 289 #define SRST_A_GPU_GRF 290 #define SRST_PVTM_GPU 291 -- GitLab From 003e6eb71ed3c884d55443cdb95b909374ade7bc Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:06:49 +0800 Subject: [PATCH 4286/9938] clk: rockchip: rename rga clock-id on rk3399 The rga clock supplying the working clock on the rk3399 is actually called rga-core in the manual. As the clock id has neither been assigned nor released with a full kernel release, we can still change the id to the more appropriate naming. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3399-cru.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h index 3370bde7fa38..91852ee13801 100644 --- a/include/dt-bindings/clock/rk3399-cru.h +++ b/include/dt-bindings/clock/rk3399-cru.h @@ -72,7 +72,7 @@ #define SCLK_MACREF_OUT 106 #define SCLK_VOP0_PWM 107 #define SCLK_VOP1_PWM 108 -#define SCLK_RGA 109 +#define SCLK_RGA_CORE 109 #define SCLK_ISP0 110 #define SCLK_ISP1 111 #define SCLK_HDMI_CEC 112 -- GitLab From 55df45843901847f33816f8246ca2538aadd339a Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:06:49 +0800 Subject: [PATCH 4287/9938] clk: rockchip: export some necessary rk3399 clock ids We export some clock IDs for the reference drivers need them. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3399-cru.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h index 91852ee13801..50a44cffb070 100644 --- a/include/dt-bindings/clock/rk3399-cru.h +++ b/include/dt-bindings/clock/rk3399-cru.h @@ -129,6 +129,8 @@ #define SCLK_DPHY_TX0_CFG 163 #define SCLK_DPHY_TX1RX1_CFG 164 #define SCLK_DPHY_RX0_CFG 165 +#define SCLK_RMII_SRC 166 +#define SCLK_PCIEPHY_REF100M 167 #define DCLK_VOP0 180 #define DCLK_VOP1 181 -- GitLab From 3f92a05440f92f2734c9b754af39afa3244dfb5b Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:06:49 +0800 Subject: [PATCH 4288/9938] clk: rockchip: assign more necessary rk3399 clock ids Assign newly added clock ids. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 40b738460d47..35cb2d73c1ca 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -554,7 +554,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKSEL_CON(20), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(5), 5, GFLAGS), - MUX(0, "clk_rmii_src", mux_rmii_p, CLK_SET_RATE_PARENT, + MUX(SCLK_RMII_SRC, "clk_rmii_src", mux_rmii_p, CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(19), 4, 1, MFLAGS), GATE(SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(5), 6, GFLAGS), @@ -780,7 +780,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(16), 1, GFLAGS), /* rga */ - COMPOSITE(0, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_RGA_CORE, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(4), 10, GFLAGS), @@ -896,7 +896,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKSEL_CON(17), 8, 3, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(6), 2, GFLAGS), - COMPOSITE_NOMUX(0, "clk_pciephy_ref100m", "npll", CLK_IGNORE_UNUSED, + COMPOSITE_NOMUX(SCLK_PCIEPHY_REF100M, "clk_pciephy_ref100m", "npll", CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(18), 11, 5, DFLAGS, RK3399_CLKGATE_CON(12), 6, GFLAGS), MUX(SCLK_PCIEPHY_REF, "clk_pciephy_ref", mux_pll_src_24m_pciephy_p, CLK_SET_RATE_PARENT, @@ -1191,10 +1191,10 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(10), 15, GFLAGS), /* isp */ - COMPOSITE(0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(ACLK_ISP0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(53), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(12), 8, GFLAGS), - COMPOSITE_NOMUX(0, "hclk_isp0", "aclk_isp0", 0, + COMPOSITE_NOMUX(HCLK_ISP0, "hclk_isp0", "aclk_isp0", 0, RK3399_CLKSEL_CON(53), 8, 5, DFLAGS, RK3399_CLKGATE_CON(12), 9, GFLAGS), @@ -1217,7 +1217,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE(ACLK_ISP1, "aclk_isp1", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(54), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(12), 10, GFLAGS), - COMPOSITE_NOMUX(0, "hclk_isp1", "aclk_isp1", 0, + COMPOSITE_NOMUX(HCLK_ISP1, "hclk_isp1", "aclk_isp1", 0, RK3399_CLKSEL_CON(54), 8, 5, DFLAGS, RK3399_CLKGATE_CON(12), 11, GFLAGS), -- GitLab From aa2897ceb7dc01b8e081eaf4d2f7e54cbd495834 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:06:50 +0800 Subject: [PATCH 4289/9938] clk: rockchip: add some frequencies on the rk3399 PLL table This patch add some necessary frequencies for the RK3399 clock. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 35cb2d73c1ca..c64a412d84c0 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -92,13 +92,18 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0), RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), - RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0), + RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0), RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), + RK3036_PLL_RATE( 297000000, 1, 99, 4, 2, 1, 0), RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), + RK3036_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0), RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), + RK3036_PLL_RATE( 74250000, 2, 99, 4, 4, 1, 0), + RK3036_PLL_RATE( 54000000, 1, 54, 6, 4, 1, 0), + RK3036_PLL_RATE( 27000000, 1, 27, 6, 4, 1, 0), { /* sentinel */ }, }; @@ -359,6 +364,8 @@ static struct rockchip_cpuclk_rate_table rk3399_cpuclkl_rates[] __initdata = { RK3399_CPUCLKL_RATE( 600000000, 1, 3, 3), RK3399_CPUCLKL_RATE( 408000000, 1, 2, 2), RK3399_CPUCLKL_RATE( 312000000, 1, 1, 1), + RK3399_CPUCLKL_RATE( 216000000, 1, 1, 1), + RK3399_CPUCLKL_RATE( 96000000, 1, 1, 1), }; static struct rockchip_cpuclk_rate_table rk3399_cpuclkb_rates[] __initdata = { @@ -381,6 +388,8 @@ static struct rockchip_cpuclk_rate_table rk3399_cpuclkb_rates[] __initdata = { RK3399_CPUCLKB_RATE( 600000000, 1, 3, 3), RK3399_CPUCLKB_RATE( 408000000, 1, 2, 2), RK3399_CPUCLKB_RATE( 312000000, 1, 1, 1), + RK3399_CPUCLKB_RATE( 216000000, 1, 1, 1), + RK3399_CPUCLKB_RATE( 96000000, 1, 1, 1), }; static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { -- GitLab From 50961e8314babfac525be4d00f3e1f65091251a4 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:06:51 +0800 Subject: [PATCH 4290/9938] clk: rockchip: drop unnecessary CLK_IGNORE_UNUSED flags from rk3399 We don't need to many clocks enable after startup, to reduce some power consumption. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 314 +++++++++++++++--------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index c64a412d84c0..7ecb7d68a328 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -413,50 +413,50 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0, RK3399_CLKSEL_CON(14), 15, 1, MFLAGS), - COMPOSITE_NODIV(SCLK_HSICPHY, "clk_hsicphy", mux_pll_src_cpll_gpll_npll_usbphy480m_p, CLK_IGNORE_UNUSED, + COMPOSITE_NODIV(SCLK_HSICPHY, "clk_hsicphy", mux_pll_src_cpll_gpll_npll_usbphy480m_p, 0, RK3399_CLKSEL_CON(19), 0, 2, MFLAGS, RK3399_CLKGATE_CON(6), 4, GFLAGS), - COMPOSITE(ACLK_USB3, "aclk_usb3", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(ACLK_USB3, "aclk_usb3", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(39), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(12), 0, GFLAGS), GATE(ACLK_USB3_NOC, "aclk_usb3_noc", "aclk_usb3", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(30), 0, GFLAGS), - GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", CLK_IGNORE_UNUSED, + GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", 0, RK3399_CLKGATE_CON(30), 1, GFLAGS), - GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", CLK_IGNORE_UNUSED, + GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", 0, RK3399_CLKGATE_CON(30), 2, GFLAGS), - GATE(ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", CLK_IGNORE_UNUSED, + GATE(ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", 0, RK3399_CLKGATE_CON(30), 3, GFLAGS), - GATE(ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", CLK_IGNORE_UNUSED, + GATE(ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", 0, RK3399_CLKGATE_CON(30), 4, GFLAGS), - GATE(SCLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", 0, RK3399_CLKGATE_CON(12), 1, GFLAGS), - GATE(SCLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", 0, RK3399_CLKGATE_CON(12), 2, GFLAGS), - COMPOSITE(SCLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", mux_pll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", mux_pll_p, 0, RK3399_CLKSEL_CON(40), 15, 1, MFLAGS, 0, 10, DFLAGS, RK3399_CLKGATE_CON(12), 3, GFLAGS), - COMPOSITE(SCLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", mux_pll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", mux_pll_p, 0, RK3399_CLKSEL_CON(41), 15, 1, MFLAGS, 0, 10, DFLAGS, RK3399_CLKGATE_CON(12), 4, GFLAGS), - COMPOSITE(SCLK_UPHY0_TCPDPHY_REF, "clk_uphy0_tcpdphy_ref", mux_pll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_UPHY0_TCPDPHY_REF, "clk_uphy0_tcpdphy_ref", mux_pll_p, 0, RK3399_CLKSEL_CON(64), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(13), 4, GFLAGS), - COMPOSITE(SCLK_UPHY0_TCPDCORE, "clk_uphy0_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_UPHY0_TCPDCORE, "clk_uphy0_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0, RK3399_CLKSEL_CON(64), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(13), 5, GFLAGS), - COMPOSITE(SCLK_UPHY1_TCPDPHY_REF, "clk_uphy1_tcpdphy_ref", mux_pll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_UPHY1_TCPDPHY_REF, "clk_uphy1_tcpdphy_ref", mux_pll_p, 0, RK3399_CLKSEL_CON(65), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(13), 6, GFLAGS), - COMPOSITE(SCLK_UPHY1_TCPDCORE, "clk_uphy1_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_UPHY1_TCPDCORE, "clk_uphy1_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0, RK3399_CLKSEL_CON(65), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(13), 7, GFLAGS), @@ -540,42 +540,42 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(6), 9, GFLAGS), GATE(0, "gpll_aclk_gmac_src", "gpll", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(6), 8, GFLAGS), - COMPOSITE(0, "aclk_gmac_pre", mux_aclk_gmac_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "aclk_gmac_pre", mux_aclk_gmac_p, 0, RK3399_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(6), 10, GFLAGS), - GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", 0, RK3399_CLKGATE_CON(32), 0, GFLAGS), GATE(ACLK_GMAC_NOC, "aclk_gmac_noc", "aclk_gmac_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(32), 1, GFLAGS), - GATE(ACLK_PERF_GMAC, "aclk_perf_gmac", "aclk_gmac_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_PERF_GMAC, "aclk_perf_gmac", "aclk_gmac_pre", 0, RK3399_CLKGATE_CON(32), 4, GFLAGS), COMPOSITE_NOMUX(0, "pclk_gmac_pre", "aclk_gmac_pre", 0, RK3399_CLKSEL_CON(19), 8, 3, DFLAGS, RK3399_CLKGATE_CON(6), 11, GFLAGS), - GATE(PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", CLK_IGNORE_UNUSED, + GATE(PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", 0, RK3399_CLKGATE_CON(32), 2, GFLAGS), GATE(PCLK_GMAC_NOC, "pclk_gmac_noc", "pclk_gmac_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(32), 3, GFLAGS), - COMPOSITE(SCLK_MAC, "clk_gmac", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_MAC, "clk_gmac", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(20), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(5), 5, GFLAGS), MUX(SCLK_RMII_SRC, "clk_rmii_src", mux_rmii_p, CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(19), 4, 1, MFLAGS), - GATE(SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", CLK_IGNORE_UNUSED, + GATE(SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", 0, RK3399_CLKGATE_CON(5), 6, GFLAGS), - GATE(SCLK_MACREF, "clk_mac_ref", "clk_rmii_src", CLK_IGNORE_UNUSED, + GATE(SCLK_MACREF, "clk_mac_ref", "clk_rmii_src", 0, RK3399_CLKGATE_CON(5), 7, GFLAGS), - GATE(SCLK_MAC_RX, "clk_rmii_rx", "clk_rmii_src", CLK_IGNORE_UNUSED, + GATE(SCLK_MAC_RX, "clk_rmii_rx", "clk_rmii_src", 0, RK3399_CLKGATE_CON(5), 8, GFLAGS), - GATE(SCLK_MAC_TX, "clk_rmii_tx", "clk_rmii_src", CLK_IGNORE_UNUSED, + GATE(SCLK_MAC_TX, "clk_rmii_tx", "clk_rmii_src", 0, RK3399_CLKGATE_CON(5), 9, GFLAGS), /* spdif */ - COMPOSITE(0, "clk_spdif_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "clk_spdif_div", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(8), 13, GFLAGS), COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div", CLK_SET_RATE_PARENT, @@ -585,11 +585,11 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(SCLK_SPDIF_8CH, "clk_spdif", "clk_spdif_mux", CLK_SET_RATE_PARENT, RK3399_CLKGATE_CON(8), 15, GFLAGS), - COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(10), 6, GFLAGS), /* i2s */ - COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(28), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(8), 3, GFLAGS), COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", CLK_SET_RATE_PARENT, @@ -599,7 +599,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(SCLK_I2S0_8CH, "clk_i2s0", "clk_i2s0_mux", CLK_SET_RATE_PARENT, RK3399_CLKGATE_CON(8), 5, GFLAGS), - COMPOSITE(0, "clk_i2s1_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "clk_i2s1_div", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(29), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(8), 6, GFLAGS), COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", CLK_SET_RATE_PARENT, @@ -609,7 +609,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(SCLK_I2S1_8CH, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT, RK3399_CLKGATE_CON(8), 8, GFLAGS), - COMPOSITE(0, "clk_i2s2_div", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "clk_i2s2_div", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(30), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(8), 9, GFLAGS), COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", CLK_SET_RATE_PARENT, @@ -737,21 +737,21 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "hclk_vcodec_pre", "aclk_vcodec_pre", 0, RK3399_CLKSEL_CON(7), 8, 5, DFLAGS, RK3399_CLKGATE_CON(4), 1, GFLAGS), - GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, RK3399_CLKGATE_CON(17), 2, GFLAGS), GATE(0, "hclk_vcodec_noc", "hclk_vcodec_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(17), 3, GFLAGS), - GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0, RK3399_CLKGATE_CON(17), 0, GFLAGS), GATE(0, "aclk_vcodec_noc", "aclk_vcodec_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(17), 1, GFLAGS), /* vdu */ - COMPOSITE(SCLK_VDU_CORE, "clk_vdu_core", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_VDU_CORE, "clk_vdu_core", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(4), 4, GFLAGS), - COMPOSITE(SCLK_VDU_CA, "clk_vdu_ca", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_VDU_CA, "clk_vdu_ca", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(9), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(4), 5, GFLAGS), @@ -761,50 +761,50 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "hclk_vdu_pre", "aclk_vdu_pre", 0, RK3399_CLKSEL_CON(8), 8, 5, DFLAGS, RK3399_CLKGATE_CON(4), 3, GFLAGS), - GATE(HCLK_VDU, "hclk_vdu", "hclk_vdu_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_VDU, "hclk_vdu", "hclk_vdu_pre", 0, RK3399_CLKGATE_CON(17), 10, GFLAGS), GATE(HCLK_VDU_NOC, "hclk_vdu_noc", "hclk_vdu_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(17), 11, GFLAGS), - GATE(ACLK_VDU, "aclk_vdu", "aclk_vdu_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_VDU, "aclk_vdu", "aclk_vdu_pre", 0, RK3399_CLKGATE_CON(17), 8, GFLAGS), GATE(ACLK_VDU_NOC, "aclk_vdu_noc", "aclk_vdu_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(17), 9, GFLAGS), /* iep */ - COMPOSITE(0, "aclk_iep_pre", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "aclk_iep_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, RK3399_CLKSEL_CON(10), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(4), 6, GFLAGS), COMPOSITE_NOMUX(0, "hclk_iep_pre", "aclk_iep_pre", 0, RK3399_CLKSEL_CON(10), 8, 5, DFLAGS, RK3399_CLKGATE_CON(4), 7, GFLAGS), - GATE(HCLK_IEP, "hclk_iep", "hclk_iep_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_IEP, "hclk_iep", "hclk_iep_pre", 0, RK3399_CLKGATE_CON(16), 2, GFLAGS), GATE(HCLK_IEP_NOC, "hclk_iep_noc", "hclk_iep_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(16), 3, GFLAGS), - GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0, RK3399_CLKGATE_CON(16), 0, GFLAGS), GATE(ACLK_IEP_NOC, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(16), 1, GFLAGS), /* rga */ - COMPOSITE(SCLK_RGA_CORE, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_RGA_CORE, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, 0, RK3399_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(4), 10, GFLAGS), - COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_npll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, RK3399_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(4), 8, GFLAGS), COMPOSITE_NOMUX(0, "hclk_rga_pre", "aclk_rga_pre", 0, RK3399_CLKSEL_CON(11), 8, 5, DFLAGS, RK3399_CLKGATE_CON(4), 9, GFLAGS), - GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", 0, RK3399_CLKGATE_CON(16), 10, GFLAGS), GATE(HCLK_RGA_NOC, "hclk_rga_noc", "hclk_rga_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(16), 11, GFLAGS), - GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3399_CLKGATE_CON(16), 8, GFLAGS), GATE(ACLK_RGA_NOC, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(16), 9, GFLAGS), @@ -822,13 +822,13 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { COMPOSITE(0, "aclk_gpu_pre", mux_pll_src_ppll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, RK3399_CLKSEL_CON(13), 5, 3, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(13), 0, GFLAGS), - GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK3399_CLKGATE_CON(30), 8, GFLAGS), - GATE(ACLK_PERF_GPU, "aclk_perf_gpu", "aclk_gpu_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_PERF_GPU, "aclk_perf_gpu", "aclk_gpu_pre", 0, RK3399_CLKGATE_CON(30), 10, GFLAGS), - GATE(ACLK_GPU_GRF, "aclk_gpu_grf", "aclk_gpu_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_GPU_GRF, "aclk_gpu_grf", "aclk_gpu_pre", 0, RK3399_CLKGATE_CON(30), 11, GFLAGS), - GATE(SCLK_PVTM_GPU, "aclk_pvtm_gpu", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_PVTM_GPU, "aclk_pvtm_gpu", "xin24m", 0, RK3399_CLKGATE_CON(13), 1, GFLAGS), /* perihp */ @@ -853,15 +853,15 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(0, "aclk_perihp_noc", "aclk_perihp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(20), 12, GFLAGS), - GATE(HCLK_HOST0, "hclk_host0", "hclk_perihp", CLK_IGNORE_UNUSED, + GATE(HCLK_HOST0, "hclk_host0", "hclk_perihp", 0, RK3399_CLKGATE_CON(20), 5, GFLAGS), - GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", CLK_IGNORE_UNUSED, + GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", 0, RK3399_CLKGATE_CON(20), 6, GFLAGS), - GATE(HCLK_HOST1, "hclk_host1", "hclk_perihp", CLK_IGNORE_UNUSED, + GATE(HCLK_HOST1, "hclk_host1", "hclk_perihp", 0, RK3399_CLKGATE_CON(20), 7, GFLAGS), - GATE(HCLK_HOST1_ARB, "hclk_host1_arb", "hclk_perihp", CLK_IGNORE_UNUSED, + GATE(HCLK_HOST1_ARB, "hclk_host1_arb", "hclk_perihp", 0, RK3399_CLKGATE_CON(20), 8, GFLAGS), - GATE(HCLK_HSIC, "hclk_hsic", "hclk_perihp", CLK_IGNORE_UNUSED, + GATE(HCLK_HSIC, "hclk_hsic", "hclk_perihp", 0, RK3399_CLKGATE_CON(20), 9, GFLAGS), GATE(0, "hclk_perihp_noc", "hclk_perihp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(20), 13, GFLAGS), @@ -870,27 +870,27 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(PCLK_PERIHP_GRF, "pclk_perihp_grf", "pclk_perihp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(20), 4, GFLAGS), - GATE(PCLK_PCIE, "pclk_pcie", "pclk_perihp", CLK_IGNORE_UNUSED, + GATE(PCLK_PCIE, "pclk_pcie", "pclk_perihp", 0, RK3399_CLKGATE_CON(20), 11, GFLAGS), GATE(0, "pclk_perihp_noc", "pclk_perihp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(20), 14, GFLAGS), - GATE(PCLK_HSICPHY, "pclk_hsicphy", "pclk_perihp", CLK_IGNORE_UNUSED, + GATE(PCLK_HSICPHY, "pclk_hsicphy", "pclk_perihp", 0, RK3399_CLKGATE_CON(31), 8, GFLAGS), /* sdio & sdmmc */ - COMPOSITE(0, "hclk_sd", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "hclk_sd", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(13), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(12), 13, GFLAGS), - GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", CLK_IGNORE_UNUSED, + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", 0, RK3399_CLKGATE_CON(33), 8, GFLAGS), GATE(0, "hclk_sdmmc_noc", "hclk_sd", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 9, GFLAGS), - COMPOSITE(SCLK_SDIO, "clk_sdio", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_SDIO, "clk_sdio", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0, RK3399_CLKSEL_CON(15), 8, 3, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(6), 0, GFLAGS), - COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0, RK3399_CLKSEL_CON(16), 8, 3, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(6), 1, GFLAGS), @@ -901,24 +901,24 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", RK3399_SDIO_CON1, 1), /* pcie */ - COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, 0, RK3399_CLKSEL_CON(17), 8, 3, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(6), 2, GFLAGS), - COMPOSITE_NOMUX(SCLK_PCIEPHY_REF100M, "clk_pciephy_ref100m", "npll", CLK_IGNORE_UNUSED, + COMPOSITE_NOMUX(SCLK_PCIEPHY_REF100M, "clk_pciephy_ref100m", "npll", 0, RK3399_CLKSEL_CON(18), 11, 5, DFLAGS, RK3399_CLKGATE_CON(12), 6, GFLAGS), MUX(SCLK_PCIEPHY_REF, "clk_pciephy_ref", mux_pll_src_24m_pciephy_p, CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(18), 10, 1, MFLAGS), - COMPOSITE(0, "clk_pcie_core_cru", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "clk_pcie_core_cru", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(6), 3, GFLAGS), MUX(SCLK_PCIE_CORE, "clk_pcie_core", mux_pciecore_cru_phy_p, CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(18), 7, 1, MFLAGS), /* emmc */ - COMPOSITE(SCLK_EMMC, "clk_emmc", mux_pll_src_cpll_gpll_npll_upll_24m_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_EMMC, "clk_emmc", mux_pll_src_cpll_gpll_npll_upll_24m_p, 0, RK3399_CLKSEL_CON(22), 8, 3, MFLAGS, 0, 7, DFLAGS, RK3399_CLKGATE_CON(6), 14, GFLAGS), @@ -962,42 +962,42 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS), GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS), GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS), - GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 7, GFLAGS), + GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS), /* hclk_perilp0 gates */ GATE(HCLK_ROM, "hclk_rom", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 4, GFLAGS), - GATE(HCLK_M_CRYPTO0, "hclk_m_crypto0", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 5, GFLAGS), - GATE(HCLK_S_CRYPTO0, "hclk_s_crypto0", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 6, GFLAGS), - GATE(HCLK_M_CRYPTO1, "hclk_m_crypto1", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 14, GFLAGS), - GATE(HCLK_S_CRYPTO1, "hclk_s_crypto1", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 15, GFLAGS), + GATE(HCLK_M_CRYPTO0, "hclk_m_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 5, GFLAGS), + GATE(HCLK_S_CRYPTO0, "hclk_s_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 6, GFLAGS), + GATE(HCLK_M_CRYPTO1, "hclk_m_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 14, GFLAGS), + GATE(HCLK_S_CRYPTO1, "hclk_s_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 15, GFLAGS), GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS), /* pclk_perilp0 gates */ GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS), /* crypto */ - COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0, RK3399_CLKSEL_CON(24), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(7), 7, GFLAGS), - COMPOSITE(SCLK_CRYPTO1, "clk_crypto1", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_CRYPTO1, "clk_crypto1", mux_pll_src_cpll_gpll_ppll_p, 0, RK3399_CLKSEL_CON(26), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(7), 8, GFLAGS), /* cm0s_perilp */ - GATE(0, "cpll_fclk_cm0s_src", "cpll", CLK_IGNORE_UNUSED, + GATE(0, "cpll_fclk_cm0s_src", "cpll", 0, RK3399_CLKGATE_CON(7), 6, GFLAGS), - GATE(0, "gpll_fclk_cm0s_src", "gpll", CLK_IGNORE_UNUSED, + GATE(0, "gpll_fclk_cm0s_src", "gpll", 0, RK3399_CLKGATE_CON(7), 5, GFLAGS), - COMPOSITE(FCLK_CM0S, "fclk_cm0s", mux_fclk_cm0s_p, CLK_IGNORE_UNUSED, + COMPOSITE(FCLK_CM0S, "fclk_cm0s", mux_fclk_cm0s_p, 0, RK3399_CLKSEL_CON(24), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(7), 9, GFLAGS), /* fclk_cm0s gates */ - GATE(SCLK_M0_PERILP, "sclk_m0_perilp", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 8, GFLAGS), - GATE(HCLK_M0_PERILP, "hclk_m0_perilp", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 9, GFLAGS), - GATE(DCLK_M0_PERILP, "dclk_m0_perilp", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 10, GFLAGS), - GATE(SCLK_M0_PERILP_DEC, "clk_m0_perilp_dec", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 11, GFLAGS), + GATE(SCLK_M0_PERILP, "sclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 8, GFLAGS), + GATE(HCLK_M0_PERILP, "hclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 9, GFLAGS), + GATE(DCLK_M0_PERILP, "dclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 10, GFLAGS), + GATE(SCLK_M0_PERILP_DEC, "clk_m0_perilp_dec", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 11, GFLAGS), GATE(HCLK_M0_PERILP_NOC, "hclk_m0_perilp_noc", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 11, GFLAGS), /* perilp1 */ @@ -1014,12 +1014,12 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { /* hclk_perilp1 gates */ GATE(0, "hclk_perilp1_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 9, GFLAGS), GATE(0, "hclk_sdio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 12, GFLAGS), - GATE(HCLK_I2S0_8CH, "hclk_i2s0", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 0, GFLAGS), - GATE(HCLK_I2S1_8CH, "hclk_i2s1", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 1, GFLAGS), - GATE(HCLK_I2S2_8CH, "hclk_i2s2", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 2, GFLAGS), - GATE(HCLK_SPDIF, "hclk_spdif", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 3, GFLAGS), - GATE(HCLK_SDIO, "hclk_sdio", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 4, GFLAGS), - GATE(PCLK_SPI5, "pclk_spi5", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 5, GFLAGS), + GATE(HCLK_I2S0_8CH, "hclk_i2s0", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 0, GFLAGS), + GATE(HCLK_I2S1_8CH, "hclk_i2s1", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 1, GFLAGS), + GATE(HCLK_I2S2_8CH, "hclk_i2s2", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 2, GFLAGS), + GATE(HCLK_SPDIF, "hclk_spdif", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 3, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 4, GFLAGS), + GATE(PCLK_SPI5, "pclk_spi5", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 5, GFLAGS), GATE(0, "hclk_sdioaudio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 6, GFLAGS), /* pclk_perilp1 gates */ @@ -1051,7 +1051,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(9), 11, GFLAGS), /* tsadc */ - COMPOSITE(SCLK_TSADC, "clk_tsadc", mux_pll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_TSADC, "clk_tsadc", mux_pll_p, 0, RK3399_CLKSEL_CON(27), 15, 1, MFLAGS, 0, 10, DFLAGS, RK3399_CLKGATE_CON(9), 10, GFLAGS), @@ -1079,85 +1079,85 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(ACLK_VIO_NOC, "aclk_vio_noc", "aclk_vio", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(29), 0, GFLAGS), - GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "pclk_vio", CLK_IGNORE_UNUSED, + GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "pclk_vio", 0, RK3399_CLKGATE_CON(29), 1, GFLAGS), - GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "pclk_vio", CLK_IGNORE_UNUSED, + GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "pclk_vio", 0, RK3399_CLKGATE_CON(29), 2, GFLAGS), GATE(PCLK_VIO_GRF, "pclk_vio_grf", "pclk_vio", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(29), 12, GFLAGS), /* hdcp */ - COMPOSITE(ACLK_HDCP, "aclk_hdcp", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(ACLK_HDCP, "aclk_hdcp", mux_pll_src_cpll_gpll_ppll_p, 0, RK3399_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(11), 12, GFLAGS), - COMPOSITE_NOMUX(HCLK_HDCP, "hclk_hdcp", "aclk_hdcp", CLK_IGNORE_UNUSED, + COMPOSITE_NOMUX(HCLK_HDCP, "hclk_hdcp", "aclk_hdcp", 0, RK3399_CLKSEL_CON(43), 5, 5, DFLAGS, RK3399_CLKGATE_CON(11), 3, GFLAGS), - COMPOSITE_NOMUX(PCLK_HDCP, "pclk_hdcp", "aclk_hdcp", CLK_IGNORE_UNUSED, + COMPOSITE_NOMUX(PCLK_HDCP, "pclk_hdcp", "aclk_hdcp", 0, RK3399_CLKSEL_CON(43), 10, 5, DFLAGS, RK3399_CLKGATE_CON(11), 10, GFLAGS), GATE(ACLK_HDCP_NOC, "aclk_hdcp_noc", "aclk_hdcp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(29), 4, GFLAGS), - GATE(ACLK_HDCP22, "aclk_hdcp22", "aclk_hdcp", CLK_IGNORE_UNUSED, + GATE(ACLK_HDCP22, "aclk_hdcp22", "aclk_hdcp", 0, RK3399_CLKGATE_CON(29), 10, GFLAGS), GATE(HCLK_HDCP_NOC, "hclk_hdcp_noc", "hclk_hdcp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(29), 5, GFLAGS), - GATE(HCLK_HDCP22, "hclk_hdcp22", "hclk_hdcp", CLK_IGNORE_UNUSED, + GATE(HCLK_HDCP22, "hclk_hdcp22", "hclk_hdcp", 0, RK3399_CLKGATE_CON(29), 9, GFLAGS), GATE(PCLK_HDCP_NOC, "pclk_hdcp_noc", "pclk_hdcp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(29), 3, GFLAGS), - GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_hdcp", CLK_IGNORE_UNUSED, + GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_hdcp", 0, RK3399_CLKGATE_CON(29), 6, GFLAGS), - GATE(PCLK_DP_CTRL, "pclk_dp_ctrl", "pclk_hdcp", CLK_IGNORE_UNUSED, + GATE(PCLK_DP_CTRL, "pclk_dp_ctrl", "pclk_hdcp", 0, RK3399_CLKGATE_CON(29), 7, GFLAGS), - GATE(PCLK_HDCP22, "pclk_hdcp22", "pclk_hdcp", CLK_IGNORE_UNUSED, + GATE(PCLK_HDCP22, "pclk_hdcp22", "pclk_hdcp", 0, RK3399_CLKGATE_CON(29), 8, GFLAGS), - GATE(PCLK_GASKET, "pclk_gasket", "pclk_hdcp", CLK_IGNORE_UNUSED, + GATE(PCLK_GASKET, "pclk_gasket", "pclk_hdcp", 0, RK3399_CLKGATE_CON(29), 11, GFLAGS), /* edp */ - COMPOSITE(SCLK_DP_CORE, "clk_dp_core", mux_pll_src_npll_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_DP_CORE, "clk_dp_core", mux_pll_src_npll_cpll_gpll_p, 0, RK3399_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(11), 8, GFLAGS), - COMPOSITE(PCLK_EDP, "pclk_edp", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(PCLK_EDP, "pclk_edp", mux_pll_src_cpll_gpll_p, 0, RK3399_CLKSEL_CON(44), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(11), 11, GFLAGS), GATE(PCLK_EDP_NOC, "pclk_edp_noc", "pclk_edp", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(32), 12, GFLAGS), - GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_edp", CLK_IGNORE_UNUSED, + GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_edp", 0, RK3399_CLKGATE_CON(32), 13, GFLAGS), /* hdmi */ - GATE(SCLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", CLK_IGNORE_UNUSED, + GATE(SCLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", 0, RK3399_CLKGATE_CON(11), 6, GFLAGS), - COMPOSITE(SCLK_HDMI_CEC, "clk_hdmi_cec", mux_pll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_HDMI_CEC, "clk_hdmi_cec", mux_pll_p, 0, RK3399_CLKSEL_CON(45), 15, 1, MFLAGS, 0, 10, DFLAGS, RK3399_CLKGATE_CON(11), 7, GFLAGS), /* vop0 */ - COMPOSITE(ACLK_VOP0_PRE, "aclk_vop0_pre", mux_pll_src_vpll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(ACLK_VOP0_PRE, "aclk_vop0_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(47), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(10), 8, GFLAGS), COMPOSITE_NOMUX(0, "hclk_vop0_pre", "aclk_vop0_pre", 0, RK3399_CLKSEL_CON(47), 8, 5, DFLAGS, RK3399_CLKGATE_CON(10), 9, GFLAGS), - GATE(ACLK_VOP0, "aclk_vop0", "aclk_vop0_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_VOP0, "aclk_vop0", "aclk_vop0_pre", 0, RK3399_CLKGATE_CON(28), 3, GFLAGS), GATE(ACLK_VOP0_NOC, "aclk_vop0_noc", "aclk_vop0_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(28), 1, GFLAGS), - GATE(HCLK_VOP0, "hclk_vop0", "hclk_vop0_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_VOP0, "hclk_vop0", "hclk_vop0_pre", 0, RK3399_CLKGATE_CON(28), 2, GFLAGS), GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(28), 0, GFLAGS), - COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0, RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS, RK3399_CLKGATE_CON(10), 12, GFLAGS), @@ -1165,29 +1165,29 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKSEL_CON(106), 0, &rk3399_dclk_vop0_fracmux), - COMPOSITE(SCLK_VOP0_PWM, "clk_vop0_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_VOP0_PWM, "clk_vop0_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, 0, RK3399_CLKSEL_CON(51), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(10), 14, GFLAGS), /* vop1 */ - COMPOSITE(ACLK_VOP1_PRE, "aclk_vop1_pre", mux_pll_src_vpll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(ACLK_VOP1_PRE, "aclk_vop1_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(10), 10, GFLAGS), COMPOSITE_NOMUX(0, "hclk_vop1_pre", "aclk_vop1_pre", 0, RK3399_CLKSEL_CON(48), 8, 5, DFLAGS, RK3399_CLKGATE_CON(10), 11, GFLAGS), - GATE(ACLK_VOP1, "aclk_vop1", "aclk_vop1_pre", CLK_IGNORE_UNUSED, + GATE(ACLK_VOP1, "aclk_vop1", "aclk_vop1_pre", 0, RK3399_CLKGATE_CON(28), 7, GFLAGS), GATE(ACLK_VOP1_NOC, "aclk_vop1_noc", "aclk_vop1_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(28), 5, GFLAGS), - GATE(HCLK_VOP1, "hclk_vop1", "hclk_vop1_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_VOP1, "hclk_vop1", "hclk_vop1_pre", 0, RK3399_CLKGATE_CON(28), 6, GFLAGS), GATE(HCLK_VOP1_NOC, "hclk_vop1_noc", "hclk_vop1_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(28), 4, GFLAGS), - COMPOSITE(DCLK_VOP1_DIV, "dclk_vop1_div", mux_pll_src_vpll_cpll_gpll_p, CLK_IGNORE_UNUSED, + COMPOSITE(DCLK_VOP1_DIV, "dclk_vop1_div", mux_pll_src_vpll_cpll_gpll_p, 0, RK3399_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 8, DFLAGS, RK3399_CLKGATE_CON(10), 13, GFLAGS), @@ -1200,7 +1200,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(10), 15, GFLAGS), /* isp */ - COMPOSITE(ACLK_ISP0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(ACLK_ISP0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, 0, RK3399_CLKSEL_CON(53), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(12), 8, GFLAGS), COMPOSITE_NOMUX(HCLK_ISP0, "hclk_isp0", "aclk_isp0", 0, @@ -1209,21 +1209,21 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(ACLK_ISP0_NOC, "aclk_isp0_noc", "aclk_isp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(27), 1, GFLAGS), - GATE(ACLK_ISP0_WRAPPER, "aclk_isp0_wrapper", "aclk_isp0", CLK_IGNORE_UNUSED, + GATE(ACLK_ISP0_WRAPPER, "aclk_isp0_wrapper", "aclk_isp0", 0, RK3399_CLKGATE_CON(27), 5, GFLAGS), - GATE(HCLK_ISP1_WRAPPER, "hclk_isp1_wrapper", "aclk_isp0", CLK_IGNORE_UNUSED, + GATE(HCLK_ISP1_WRAPPER, "hclk_isp1_wrapper", "aclk_isp0", 0, RK3399_CLKGATE_CON(27), 7, GFLAGS), GATE(HCLK_ISP0_NOC, "hclk_isp0_noc", "hclk_isp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(27), 0, GFLAGS), - GATE(HCLK_ISP0_WRAPPER, "hclk_isp0_wrapper", "hclk_isp0", CLK_IGNORE_UNUSED, + GATE(HCLK_ISP0_WRAPPER, "hclk_isp0_wrapper", "hclk_isp0", 0, RK3399_CLKGATE_CON(27), 4, GFLAGS), - COMPOSITE(SCLK_ISP0, "clk_isp0", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_ISP0, "clk_isp0", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(11), 4, GFLAGS), - COMPOSITE(ACLK_ISP1, "aclk_isp1", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(ACLK_ISP1, "aclk_isp1", mux_pll_src_cpll_gpll_ppll_p, 0, RK3399_CLKSEL_CON(54), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(12), 10, GFLAGS), COMPOSITE_NOMUX(HCLK_ISP1, "hclk_isp1", "aclk_isp1", 0, @@ -1235,10 +1235,10 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(HCLK_ISP1_NOC, "hclk_isp1_noc", "hclk_isp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(27), 2, GFLAGS), - GATE(ACLK_ISP1_WRAPPER, "aclk_isp1_wrapper", "hclk_isp1", CLK_IGNORE_UNUSED, + GATE(ACLK_ISP1_WRAPPER, "aclk_isp1_wrapper", "hclk_isp1", 0, RK3399_CLKGATE_CON(27), 8, GFLAGS), - COMPOSITE(SCLK_ISP1, "clk_isp1", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_ISP1, "clk_isp1", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(55), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(11), 5, GFLAGS), @@ -1250,11 +1250,11 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { * |GSC20_9|-- pclkin_cifmux -- |G27_6| -- pclkin_isp1_wrapper * pclkin_cif --|-------/ */ - GATE(PCLK_ISP1_WRAPPER, "pclkin_isp1_wrapper", "pclkin_cif", CLK_IGNORE_UNUSED, + GATE(PCLK_ISP1_WRAPPER, "pclkin_isp1_wrapper", "pclkin_cif", 0, RK3399_CLKGATE_CON(27), 6, GFLAGS), /* cif */ - COMPOSITE(0, "clk_cifout_div", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "clk_cifout_div", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(56), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(10), 7, GFLAGS), MUX(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, CLK_SET_RATE_PARENT, @@ -1285,18 +1285,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { GATE(PCLK_GRF, "pclk_grf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 1, GFLAGS), GATE(PCLK_INTR_ARB, "pclk_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 2, GFLAGS), - GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 3, GFLAGS), - GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 4, GFLAGS), - GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 5, GFLAGS), - GATE(PCLK_TIMER0, "pclk_timer0", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 6, GFLAGS), - GATE(PCLK_TIMER1, "pclk_timer1", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 7, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 3, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 4, GFLAGS), + GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 5, GFLAGS), + GATE(PCLK_TIMER0, "pclk_timer0", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 6, GFLAGS), + GATE(PCLK_TIMER1, "pclk_timer1", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 7, GFLAGS), GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS), GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS), - GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(11), 14, GFLAGS), + GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", 0, RK3399_CLKGATE_CON(11), 14, GFLAGS), GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS), - GATE(SCLK_MIPIDPHY_CFG, "clk_mipidphy_cfg", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(11), 15, GFLAGS), + GATE(SCLK_MIPIDPHY_CFG, "clk_mipidphy_cfg", "xin24m", 0, RK3399_CLKGATE_CON(11), 15, GFLAGS), GATE(SCLK_DPHY_TX0_CFG, "clk_dphy_tx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 1, GFLAGS), GATE(SCLK_DPHY_TX1RX1_CFG, "clk_dphy_tx1rx1_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 2, GFLAGS), GATE(SCLK_DPHY_RX0_CFG, "clk_dphy_rx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 3, GFLAGS), @@ -1358,18 +1358,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(10), 5, GFLAGS), /* timer */ - GATE(SCLK_TIMER00, "clk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 0, GFLAGS), - GATE(SCLK_TIMER01, "clk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 1, GFLAGS), - GATE(SCLK_TIMER02, "clk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 2, GFLAGS), - GATE(SCLK_TIMER03, "clk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 3, GFLAGS), - GATE(SCLK_TIMER04, "clk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 4, GFLAGS), - GATE(SCLK_TIMER05, "clk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 5, GFLAGS), - GATE(SCLK_TIMER06, "clk_timer06", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 6, GFLAGS), - GATE(SCLK_TIMER07, "clk_timer07", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 7, GFLAGS), - GATE(SCLK_TIMER08, "clk_timer08", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 8, GFLAGS), - GATE(SCLK_TIMER09, "clk_timer09", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 9, GFLAGS), - GATE(SCLK_TIMER10, "clk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 10, GFLAGS), - GATE(SCLK_TIMER11, "clk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(26), 11, GFLAGS), + GATE(SCLK_TIMER00, "clk_timer00", "xin24m", 0, RK3399_CLKGATE_CON(26), 0, GFLAGS), + GATE(SCLK_TIMER01, "clk_timer01", "xin24m", 0, RK3399_CLKGATE_CON(26), 1, GFLAGS), + GATE(SCLK_TIMER02, "clk_timer02", "xin24m", 0, RK3399_CLKGATE_CON(26), 2, GFLAGS), + GATE(SCLK_TIMER03, "clk_timer03", "xin24m", 0, RK3399_CLKGATE_CON(26), 3, GFLAGS), + GATE(SCLK_TIMER04, "clk_timer04", "xin24m", 0, RK3399_CLKGATE_CON(26), 4, GFLAGS), + GATE(SCLK_TIMER05, "clk_timer05", "xin24m", 0, RK3399_CLKGATE_CON(26), 5, GFLAGS), + GATE(SCLK_TIMER06, "clk_timer06", "xin24m", 0, RK3399_CLKGATE_CON(26), 6, GFLAGS), + GATE(SCLK_TIMER07, "clk_timer07", "xin24m", 0, RK3399_CLKGATE_CON(26), 7, GFLAGS), + GATE(SCLK_TIMER08, "clk_timer08", "xin24m", 0, RK3399_CLKGATE_CON(26), 8, GFLAGS), + GATE(SCLK_TIMER09, "clk_timer09", "xin24m", 0, RK3399_CLKGATE_CON(26), 9, GFLAGS), + GATE(SCLK_TIMER10, "clk_timer10", "xin24m", 0, RK3399_CLKGATE_CON(26), 10, GFLAGS), + GATE(SCLK_TIMER11, "clk_timer11", "xin24m", 0, RK3399_CLKGATE_CON(26), 11, GFLAGS), /* clk_test */ /* clk_test_pre is controlled by CRU_MISC_CON[3] */ @@ -1383,13 +1383,13 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = { * PMU CRU Clock-Architecture */ - GATE(0, "fclk_cm0s_pmu_ppll_src", "ppll", CLK_IGNORE_UNUSED, + GATE(0, "fclk_cm0s_pmu_ppll_src", "ppll", 0, RK3399_PMU_CLKGATE_CON(0), 1, GFLAGS), - COMPOSITE_NOGATE(FCLK_CM0S_SRC_PMU, "fclk_cm0s_src_pmu", mux_fclk_cm0s_pmu_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE_NOGATE(FCLK_CM0S_SRC_PMU, "fclk_cm0s_src_pmu", mux_fclk_cm0s_pmu_ppll_p, 0, RK3399_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS), - COMPOSITE(SCLK_SPI3_PMU, "clk_spi3_pmu", mux_24m_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(SCLK_SPI3_PMU, "clk_spi3_pmu", mux_24m_ppll_p, 0, RK3399_PMU_CLKSEL_CON(1), 7, 1, MFLAGS, 0, 7, DFLAGS, RK3399_PMU_CLKGATE_CON(0), 2, GFLAGS), @@ -1421,7 +1421,7 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = { MUX(0, "clk_testout_2io", mux_clk_testout2_2io_p, CLK_IGNORE_UNUSED, RK3399_PMU_CLKSEL_CON(4), 15, 1, MFLAGS), - COMPOSITE(0, "clk_uart4_div", mux_24m_ppll_p, CLK_IGNORE_UNUSED, + COMPOSITE(0, "clk_uart4_div", mux_24m_ppll_p, 0, RK3399_PMU_CLKSEL_CON(5), 10, 1, MFLAGS, 0, 7, DFLAGS, RK3399_PMU_CLKGATE_CON(0), 5, GFLAGS), @@ -1434,32 +1434,32 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = { RK3399_PMU_CLKSEL_CON(0), 0, 5, DFLAGS), /* pmu clock gates */ - GATE(SCLK_TIMER12_PMU, "clk_timer0_pmu", "clk_timer_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 3, GFLAGS), - GATE(SCLK_TIMER13_PMU, "clk_timer1_pmu", "clk_timer_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 4, GFLAGS), + GATE(SCLK_TIMER12_PMU, "clk_timer0_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 3, GFLAGS), + GATE(SCLK_TIMER13_PMU, "clk_timer1_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 4, GFLAGS), GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 7, GFLAGS), GATE(PCLK_PMU, "pclk_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 0, GFLAGS), GATE(PCLK_PMUGRF_PMU, "pclk_pmugrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 1, GFLAGS), GATE(PCLK_INTMEM1_PMU, "pclk_intmem1_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 2, GFLAGS), - GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 3, GFLAGS), - GATE(PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 4, GFLAGS), + GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 3, GFLAGS), + GATE(PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 4, GFLAGS), GATE(PCLK_SGRF_PMU, "pclk_sgrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 5, GFLAGS), GATE(PCLK_NOC_PMU, "pclk_noc_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 6, GFLAGS), - GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 7, GFLAGS), - GATE(PCLK_I2C4_PMU, "pclk_i2c4_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 8, GFLAGS), - GATE(PCLK_I2C8_PMU, "pclk_i2c8_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 9, GFLAGS), - GATE(PCLK_RKPWM_PMU, "pclk_rkpwm_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 10, GFLAGS), - GATE(PCLK_SPI3_PMU, "pclk_spi3_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 11, GFLAGS), - GATE(PCLK_TIMER_PMU, "pclk_timer_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 12, GFLAGS), - GATE(PCLK_MAILBOX_PMU, "pclk_mailbox_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 13, GFLAGS), - GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS), - GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS), - - GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS), - GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS), - GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS), - GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS), + GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 7, GFLAGS), + GATE(PCLK_I2C4_PMU, "pclk_i2c4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 8, GFLAGS), + GATE(PCLK_I2C8_PMU, "pclk_i2c8_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 9, GFLAGS), + GATE(PCLK_RKPWM_PMU, "pclk_rkpwm_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 10, GFLAGS), + GATE(PCLK_SPI3_PMU, "pclk_spi3_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 11, GFLAGS), + GATE(PCLK_TIMER_PMU, "pclk_timer_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 12, GFLAGS), + GATE(PCLK_MAILBOX_PMU, "pclk_mailbox_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 13, GFLAGS), + GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS), + GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS), + + GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS), + GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS), + GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS), + GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS), GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS), }; -- GitLab From 6fa01ccd883021105e9f8af7d04b9f156fa3494a Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Fri, 22 Apr 2016 18:36:35 -0700 Subject: [PATCH 4291/9938] skbuff: Add pskb_extract() helper function A pattern of skb usage seen in modules such as RDS-TCP is to extract `to_copy' bytes from the received TCP segment, starting at some offset `off' into a new skb `clone'. This is done in the ->data_ready callback, where the clone skb is queued up for rx on the PF_RDS socket, while the parent TCP segment is returned unchanged back to the TCP engine. The existing code uses the sequence clone = skb_clone(..); pskb_pull(clone, off, ..); pskb_trim(clone, to_copy, ..); with the intention of discarding the first `off' bytes. However, skb_clone() + pskb_pull() implies pksb_expand_head(), which ends up doing a redundant memcpy of bytes that will then get discarded in __pskb_pull_tail(). To avoid this inefficiency, this commit adds pskb_extract() that creates the clone, and memcpy's only the relevant header/frag/frag_list to the start of `clone'. pskb_trim() is then invoked to trim clone down to the requested to_copy bytes. Signed-off-by: Sowmini Varadhan Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 + net/core/skbuff.c | 242 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index da0ace389fec..a1ce63979ad8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2986,6 +2986,8 @@ struct sk_buff *skb_vlan_untag(struct sk_buff *skb); int skb_ensure_writable(struct sk_buff *skb, int write_len); int skb_vlan_pop(struct sk_buff *skb); int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); +struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy, + gfp_t gfp); static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len) { diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 7ff7788b0151..7a1d48983f81 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4622,3 +4622,245 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len, return NULL; } EXPORT_SYMBOL(alloc_skb_with_frags); + +/* carve out the first off bytes from skb when off < headlen */ +static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off, + const int headlen, gfp_t gfp_mask) +{ + int i; + int size = skb_end_offset(skb); + int new_hlen = headlen - off; + u8 *data; + int doff = 0; + + size = SKB_DATA_ALIGN(size); + + if (skb_pfmemalloc(skb)) + gfp_mask |= __GFP_MEMALLOC; + data = kmalloc_reserve(size + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), + gfp_mask, NUMA_NO_NODE, NULL); + if (!data) + return -ENOMEM; + + size = SKB_WITH_OVERHEAD(ksize(data)); + + /* Copy real data, and all frags */ + skb_copy_from_linear_data_offset(skb, off, data, new_hlen); + skb->len -= off; + + memcpy((struct skb_shared_info *)(data + size), + skb_shinfo(skb), + offsetof(struct skb_shared_info, + frags[skb_shinfo(skb)->nr_frags])); + if (skb_cloned(skb)) { + /* drop the old head gracefully */ + if (skb_orphan_frags(skb, gfp_mask)) { + kfree(data); + return -ENOMEM; + } + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + skb_frag_ref(skb, i); + if (skb_has_frag_list(skb)) + skb_clone_fraglist(skb); + skb_release_data(skb); + } else { + /* we can reuse existing recount- all we did was + * relocate values + */ + skb_free_head(skb); + } + + doff = (data - skb->head); + skb->head = data; + skb->data = data; + skb->head_frag = 0; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb->end = size; + doff = 0; +#else + skb->end = skb->head + size; +#endif + skb_set_tail_pointer(skb, skb_headlen(skb)); + skb_headers_offset_update(skb, 0); + skb->cloned = 0; + skb->hdr_len = 0; + skb->nohdr = 0; + atomic_set(&skb_shinfo(skb)->dataref, 1); + + return 0; +} + +static int pskb_carve(struct sk_buff *skb, const u32 off, gfp_t gfp); + +/* carve out the first eat bytes from skb's frag_list. May recurse into + * pskb_carve() + */ +static int pskb_carve_frag_list(struct sk_buff *skb, + struct skb_shared_info *shinfo, int eat, + gfp_t gfp_mask) +{ + struct sk_buff *list = shinfo->frag_list; + struct sk_buff *clone = NULL; + struct sk_buff *insp = NULL; + + do { + if (!list) { + pr_err("Not enough bytes to eat. Want %d\n", eat); + return -EFAULT; + } + if (list->len <= eat) { + /* Eaten as whole. */ + eat -= list->len; + list = list->next; + insp = list; + } else { + /* Eaten partially. */ + if (skb_shared(list)) { + clone = skb_clone(list, gfp_mask); + if (!clone) + return -ENOMEM; + insp = list->next; + list = clone; + } else { + /* This may be pulled without problems. */ + insp = list; + } + if (pskb_carve(list, eat, gfp_mask) < 0) { + kfree_skb(clone); + return -ENOMEM; + } + break; + } + } while (eat); + + /* Free pulled out fragments. */ + while ((list = shinfo->frag_list) != insp) { + shinfo->frag_list = list->next; + kfree_skb(list); + } + /* And insert new clone at head. */ + if (clone) { + clone->next = list; + shinfo->frag_list = clone; + } + return 0; +} + +/* carve off first len bytes from skb. Split line (off) is in the + * non-linear part of skb + */ +static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off, + int pos, gfp_t gfp_mask) +{ + int i, k = 0; + int size = skb_end_offset(skb); + u8 *data; + const int nfrags = skb_shinfo(skb)->nr_frags; + struct skb_shared_info *shinfo; + int doff = 0; + + size = SKB_DATA_ALIGN(size); + + if (skb_pfmemalloc(skb)) + gfp_mask |= __GFP_MEMALLOC; + data = kmalloc_reserve(size + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), + gfp_mask, NUMA_NO_NODE, NULL); + if (!data) + return -ENOMEM; + + size = SKB_WITH_OVERHEAD(ksize(data)); + + memcpy((struct skb_shared_info *)(data + size), + skb_shinfo(skb), offsetof(struct skb_shared_info, + frags[skb_shinfo(skb)->nr_frags])); + if (skb_orphan_frags(skb, gfp_mask)) { + kfree(data); + return -ENOMEM; + } + shinfo = (struct skb_shared_info *)(data + size); + for (i = 0; i < nfrags; i++) { + int fsize = skb_frag_size(&skb_shinfo(skb)->frags[i]); + + if (pos + fsize > off) { + shinfo->frags[k] = skb_shinfo(skb)->frags[i]; + + if (pos < off) { + /* Split frag. + * We have two variants in this case: + * 1. Move all the frag to the second + * part, if it is possible. F.e. + * this approach is mandatory for TUX, + * where splitting is expensive. + * 2. Split is accurately. We make this. + */ + shinfo->frags[0].page_offset += off - pos; + skb_frag_size_sub(&shinfo->frags[0], off - pos); + } + skb_frag_ref(skb, i); + k++; + } + pos += fsize; + } + shinfo->nr_frags = k; + if (skb_has_frag_list(skb)) + skb_clone_fraglist(skb); + + if (k == 0) { + /* split line is in frag list */ + pskb_carve_frag_list(skb, shinfo, off - pos, gfp_mask); + } + skb_release_data(skb); + + doff = (data - skb->head); + skb->head = data; + skb->head_frag = 0; + skb->data = data; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb->end = size; + doff = 0; +#else + skb->end = skb->head + size; +#endif + skb_reset_tail_pointer(skb); + skb_headers_offset_update(skb, 0); + skb->cloned = 0; + skb->hdr_len = 0; + skb->nohdr = 0; + skb->len -= off; + skb->data_len = skb->len; + atomic_set(&skb_shinfo(skb)->dataref, 1); + return 0; +} + +/* remove len bytes from the beginning of the skb */ +static int pskb_carve(struct sk_buff *skb, const u32 len, gfp_t gfp) +{ + int headlen = skb_headlen(skb); + + if (len < headlen) + return pskb_carve_inside_header(skb, len, headlen, gfp); + else + return pskb_carve_inside_nonlinear(skb, len, headlen, gfp); +} + +/* Extract to_copy bytes starting at off from skb, and return this in + * a new skb + */ +struct sk_buff *pskb_extract(struct sk_buff *skb, int off, + int to_copy, gfp_t gfp) +{ + struct sk_buff *clone = skb_clone(skb, gfp); + + if (!clone) + return NULL; + + if (pskb_carve(clone, off, gfp) < 0 || + pskb_trim(clone, to_copy)) { + kfree_skb(clone); + return NULL; + } + return clone; +} +EXPORT_SYMBOL(pskb_extract); -- GitLab From 947d2756cddec83c72af99b02010002ddc57aeb3 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Fri, 22 Apr 2016 18:36:36 -0700 Subject: [PATCH 4292/9938] RDS: TCP: Call pskb_extract() helper function rds-stress experiments with request size 256 bytes, 8K acks, using 16 threads show a 40% improvment when pskb_extract() replaces the {skb_clone(..); pskb_pull(..); pskb_trim(..);} pattern in the Rx path, so we leverage the perf gain with this commit. Signed-off-by: Sowmini Varadhan Signed-off-by: David S. Miller --- net/rds/tcp_recv.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index 27a992154804..d75d8b56a9e3 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c @@ -207,22 +207,14 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb, } if (left && tc->t_tinc_data_rem) { - clone = skb_clone(skb, arg->gfp); + to_copy = min(tc->t_tinc_data_rem, left); + + clone = pskb_extract(skb, offset, to_copy, arg->gfp); if (!clone) { desc->error = -ENOMEM; goto out; } - to_copy = min(tc->t_tinc_data_rem, left); - if (!pskb_pull(clone, offset) || - pskb_trim(clone, to_copy)) { - pr_warn("rds_tcp_data_recv: pull/trim failed " - "left %zu data_rem %zu skb_len %d\n", - left, tc->t_tinc_data_rem, skb->len); - kfree_skb(clone); - desc->error = -ENOMEM; - goto out; - } skb_queue_tail(&tinc->ti_skb_list, clone); rdsdebug("skb %p data %p len %d off %u to_copy %zu -> " -- GitLab From fd8bc829336a24b770247eb893111bcb8f1ddedb Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 20 Apr 2016 19:11:32 +0800 Subject: [PATCH 4293/9938] clk: rockchip: fix the rk3399 cifout clock The cifout clock is incorrect due to the manual error, we need to fix it. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 7ecb7d68a328..5248726af86d 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -158,7 +158,7 @@ PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", PNAME(mux_dclk_vop1_p) = { "dclk_vop1_div", "dclk_vop1_frac" }; -PNAME(mux_clk_cif_p) = { "clk_cifout_div", "xin24m" }; +PNAME(mux_clk_cif_p) = { "clk_cifout_src", "xin24m" }; PNAME(mux_pll_src_24m_usbphy480m_p) = { "xin24m", "clk_usbphy_480m" }; PNAME(mux_pll_src_24m_pciephy_p) = { "xin24m", "clk_pciephy_ref100m" }; @@ -1254,11 +1254,12 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(27), 6, GFLAGS), /* cif */ - COMPOSITE(0, "clk_cifout_div", mux_pll_src_cpll_gpll_npll_p, 0, - RK3399_CLKSEL_CON(56), 6, 2, MFLAGS, 0, 5, DFLAGS, + COMPOSITE_NODIV(0, "clk_cifout_src", mux_pll_src_cpll_gpll_npll_p, 0, + RK3399_CLKSEL_CON(56), 6, 2, MFLAGS, RK3399_CLKGATE_CON(10), 7, GFLAGS), - MUX(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, CLK_SET_RATE_PARENT, - RK3399_CLKSEL_CON(56), 5, 1, MFLAGS), + + COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, 0, + RK3399_CLKSEL_CON(56), 5, 1, MFLAGS, 0, 5, DFLAGS), /* gic */ COMPOSITE(ACLK_GIC_PRE, "aclk_gic_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, -- GitLab From 6404436a63a463d03ef9b5d7cd5edd371e711a95 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 25 Apr 2016 22:17:17 +0200 Subject: [PATCH 4294/9938] perf tools: Make the x86 clean quiet Turn current clean output: $ make clean rm -f arch/x86/include/generated/asm/syscalls_64.c CLEAN libbpf CLEAN libapi into: $ make clean CLEAN x86 CLEAN libapi CLEAN libbpf Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: TJ Link: http://lkml.kernel.org/r/1461615438-27894-1-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index a33729173b13..6c9211b18ec0 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile @@ -24,6 +24,6 @@ $(header): $(sys)/syscall_64.tbl $(systbl) $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@ clean:: - rm -f $(header) + $(call QUIET_CLEAN, x86) $(RM) $(header) archheaders: $(header) -- GitLab From b455f0a1cc51f35a9e714554c6e3234fd806ce02 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 21 Apr 2016 14:58:41 +0900 Subject: [PATCH 4295/9938] arm64: dts: uniphier: use Daughter board on PH1-LD20 reference board Include the development base board, which is equipped with some devices such as EEPROM. Signed-off-by: Masahiro Yamada Signed-off-by: Arnd Bergmann --- arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts | 1 + arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi | 1 + 2 files changed, 2 insertions(+) create mode 120000 arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi diff --git a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts b/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts index 727ae5f8c4e7..6aebcf3a0be4 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts +++ b/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts @@ -44,6 +44,7 @@ /dts-v1/; /include/ "uniphier-ph1-ld20.dtsi" +/include/ "uniphier-ref-daughter.dtsi" /include/ "uniphier-support-card.dtsi" / { diff --git a/arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi new file mode 120000 index 000000000000..4685a8d89cba --- /dev/null +++ b/arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi @@ -0,0 +1 @@ +../../../../arm/boot/dts/uniphier-ref-daughter.dtsi \ No newline at end of file -- GitLab From fb89cf36b6041ac87ad75ad0f5f23b2643fc6f97 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 21 Apr 2016 15:01:09 +0900 Subject: [PATCH 4296/9938] arm64: dts: uniphier: add reference clock node for PH1-LD20 Add a master clock node generated by a 25MHz crystal oscillator. Signed-off-by: Masahiro Yamada Signed-off-by: Arnd Bergmann --- arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi index e682a3f52791..8b908cd7eb04 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi @@ -106,6 +106,12 @@ }; clocks { + refclk: ref { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + uart_clk: uart_clk { #clock-cells = <0>; compatible = "fixed-clock"; -- GitLab From ca620723d4ff9ea7ed484eab46264c3af871b9ae Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 7 Apr 2016 17:15:14 -0700 Subject: [PATCH 4297/9938] PCI: Supply CPU physical address (not bus address) to iomem_is_exclusive() iomem_is_exclusive() requires a CPU physical address, but on some arches we supplied a PCI bus address instead. On most arches, pci_resource_to_user(res) returns "res->start", which is a CPU physical address. But on microblaze, mips, powerpc, and sparc, it returns the PCI bus address corresponding to "res->start". The result is that pci_mmap_resource() may fail when it shouldn't (if the bus address happens to match an existing resource), or it may succeed when it should fail (if the resource is exclusive but the bus address doesn't match it). Call iomem_is_exclusive() with "res->start", which is always a CPU physical address, not the result of pci_resource_to_user(). Fixes: e8de1481fd71 ("resource: allow MMIO exclusivity for device drivers") Suggested-by: Yinghai Lu Signed-off-by: Bjorn Helgaas CC: Arjan van de Ven --- drivers/pci/pci-sysfs.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index e982010f0ed1..cbb13be1ba28 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1008,6 +1008,9 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, if (i >= PCI_ROM_RESOURCE) return -ENODEV; + if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start)) + return -EINVAL; + if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) { WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n", current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff, @@ -1024,10 +1027,6 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, pci_resource_to_user(pdev, i, res, &start, &end); vma->vm_pgoff += start >> PAGE_SHIFT; mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; - - if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(start)) - return -EINVAL; - return pci_mmap_page_range(pdev, vma, mmap_type, write_combine); } -- GitLab From ab362f5a95ff72a895c446e9d5ef548cac2fea07 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 25 Apr 2016 22:17:18 +0200 Subject: [PATCH 4298/9938] tools build: Fix perf_clean target Fix perf_clean target to follow the same logic as perf target. Fixes the following make invokation: $ cd && make tools/perf_clean Reported-by: TJ Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=116411 Link: http://lkml.kernel.org/r/1461615438-27894-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/Makefile b/tools/Makefile index 60c7e6c8ff17..6bf68fe7dd29 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -137,7 +137,8 @@ libsubcmd_clean: $(call descend,lib/subcmd,clean) perf_clean: - $(call descend,$(@:_clean=),clean) + $(Q)mkdir -p $(PERF_O) . + $(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean selftests_clean: $(call descend,testing/$(@:_clean=),clean) -- GitLab From c20e128030caf0537d5e906753eac1c28fefdb75 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 25 Apr 2016 15:59:50 -0500 Subject: [PATCH 4299/9938] alpha/PCI: Call iomem_is_exclusive() for IORESOURCE_MEM, but not IORESOURCE_IO The alpha pci_mmap_resource() is used for both IORESOURCE_MEM and IORESOURCE_IO resources, but iomem_is_exclusive() is only applicable for IORESOURCE_MEM. Call iomem_is_exclusive() only for IORESOURCE_MEM resources, and do it earlier to match the generic version of pci_mmap_resource(). Fixes: 10a0ef39fbd1 ("PCI/alpha: pci sysfs resources") Signed-off-by: Bjorn Helgaas CC: Ivan Kokshaysky --- arch/alpha/kernel/pci-sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index 99e8d4796c96..92c0d460815b 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -77,10 +77,10 @@ static int pci_mmap_resource(struct kobject *kobj, if (i >= PCI_ROM_RESOURCE) return -ENODEV; - if (!__pci_mmap_fits(pdev, i, vma, sparse)) + if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start)) return -EINVAL; - if (iomem_is_exclusive(res->start)) + if (!__pci_mmap_fits(pdev, i, vma, sparse)) return -EINVAL; pcibios_resource_to_bus(pdev->bus, &bar, res); -- GitLab From 9e4cc255e6e18418ddbeea447efa506bb43d57a2 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Mon, 25 Apr 2016 14:02:16 -0700 Subject: [PATCH 4300/9938] Input: twl6040-vibra - remove mutex The mutex does not seem to be needed. twl4030-vibra doesn't use one either. Signed-off-by: H. Nikolaus Schaller Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl6040-vibra.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index ea63fad48de6..36c8182b7bd2 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -47,7 +47,7 @@ struct vibra_info { struct input_dev *input_dev; struct workqueue_struct *workqueue; struct work_struct play_work; - struct mutex mutex; + int irq; bool enabled; @@ -183,8 +183,6 @@ static void vibra_play_work(struct work_struct *work) struct vibra_info *info = container_of(work, struct vibra_info, play_work); - mutex_lock(&info->mutex); - if (info->weak_speed || info->strong_speed) { if (!info->enabled) twl6040_vibra_enable(info); @@ -193,7 +191,6 @@ static void vibra_play_work(struct work_struct *work) } else if (info->enabled) twl6040_vibra_disable(info); - mutex_unlock(&info->mutex); } static int vibra_play(struct input_dev *input, void *data, @@ -228,12 +225,8 @@ static void twl6040_vibra_close(struct input_dev *input) cancel_work_sync(&info->play_work); - mutex_lock(&info->mutex); - if (info->enabled) twl6040_vibra_disable(info); - - mutex_unlock(&info->mutex); } static int __maybe_unused twl6040_vibra_suspend(struct device *dev) @@ -241,13 +234,11 @@ static int __maybe_unused twl6040_vibra_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct vibra_info *info = platform_get_drvdata(pdev); - mutex_lock(&info->mutex); + cancel_work_sync(&info->play_work); if (info->enabled) twl6040_vibra_disable(info); - mutex_unlock(&info->mutex); - return 0; } @@ -305,8 +296,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev) return -EINVAL; } - mutex_init(&info->mutex); - error = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, twl6040_vib_irq_handler, IRQF_ONESHOT, -- GitLab From 3b556bced46aa6b1873da7faa18eff235e896adc Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 10:47:54 +0100 Subject: [PATCH 4301/9938] perf tools: Remove duplicate const qualifier Signed-off-by: Eric Engestrom Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1461577678-29517-1-git-send-email-eric.engestrom@imgtec.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index dfd00c6dad6e..de2036d1251b 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -233,7 +233,7 @@ void thread__find_cpumode_addr_location(struct thread *thread, struct addr_location *al) { size_t i; - const u8 const cpumodes[] = { + const u8 cpumodes[] = { PERF_RECORD_MISC_USER, PERF_RECORD_MISC_KERNEL, PERF_RECORD_MISC_GUEST_USER, -- GitLab From b4c715d04006ccc17d9ae0cf673b2f65267c042b Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 25 Apr 2016 16:33:30 +0200 Subject: [PATCH 4302/9938] i2c: octeon: Improve error status checking Introduce a function that checks for valid status codes depending on the phase of a transmit or receive. Also add all existing status codes and improve error handling for various states. The Octeon TWSI has an "assert acknowledge" bit (TWSI_CTL_AAK) that is required to be set in master receive mode until the last byte is requested. The state check needs to consider if this bit was set. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 129 ++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 23 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 4275007c2907..471d06eb8434 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -55,13 +55,35 @@ #define TWSI_CTL_IFLG 0x08 /* HW event, SW writes 0 to ACK */ #define TWSI_CTL_AAK 0x04 /* Assert ACK */ -/* Some status values */ +/* Status values */ +#define STAT_ERROR 0x00 #define STAT_START 0x08 -#define STAT_RSTART 0x10 +#define STAT_REP_START 0x10 #define STAT_TXADDR_ACK 0x18 +#define STAT_TXADDR_NAK 0x20 #define STAT_TXDATA_ACK 0x28 +#define STAT_TXDATA_NAK 0x30 +#define STAT_LOST_ARB_38 0x38 #define STAT_RXADDR_ACK 0x40 +#define STAT_RXADDR_NAK 0x48 #define STAT_RXDATA_ACK 0x50 +#define STAT_RXDATA_NAK 0x58 +#define STAT_SLAVE_60 0x60 +#define STAT_LOST_ARB_68 0x68 +#define STAT_SLAVE_70 0x70 +#define STAT_LOST_ARB_78 0x78 +#define STAT_SLAVE_80 0x80 +#define STAT_SLAVE_88 0x88 +#define STAT_GENDATA_ACK 0x90 +#define STAT_GENDATA_NAK 0x98 +#define STAT_SLAVE_A0 0xA0 +#define STAT_SLAVE_A8 0xA8 +#define STAT_LOST_ARB_B0 0xB0 +#define STAT_SLAVE_LOST 0xB8 +#define STAT_SLAVE_NAK 0xC0 +#define STAT_SLAVE_ACK 0xC8 +#define STAT_AD2W_ACK 0xD0 +#define STAT_AD2W_NAK 0xD8 #define STAT_IDLE 0xF8 /* TWSI_INT values */ @@ -225,6 +247,67 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) return 0; } +static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) +{ + u8 stat = octeon_i2c_stat_read(i2c); + + switch (stat) { + /* Everything is fine */ + case STAT_IDLE: + case STAT_AD2W_ACK: + case STAT_RXADDR_ACK: + case STAT_TXADDR_ACK: + case STAT_TXDATA_ACK: + return 0; + + /* ACK allowed on pre-terminal bytes only */ + case STAT_RXDATA_ACK: + if (!final_read) + return 0; + return -EIO; + + /* NAK allowed on terminal byte only */ + case STAT_RXDATA_NAK: + if (final_read) + return 0; + return -EIO; + + /* Arbitration lost */ + case STAT_LOST_ARB_38: + case STAT_LOST_ARB_68: + case STAT_LOST_ARB_78: + case STAT_LOST_ARB_B0: + return -EAGAIN; + + /* Being addressed as slave, should back off & listen */ + case STAT_SLAVE_60: + case STAT_SLAVE_70: + case STAT_GENDATA_ACK: + case STAT_GENDATA_NAK: + return -EOPNOTSUPP; + + /* Core busy as slave */ + case STAT_SLAVE_80: + case STAT_SLAVE_88: + case STAT_SLAVE_A0: + case STAT_SLAVE_A8: + case STAT_SLAVE_LOST: + case STAT_SLAVE_NAK: + case STAT_SLAVE_ACK: + return -EOPNOTSUPP; + + case STAT_TXDATA_NAK: + return -EIO; + case STAT_TXADDR_NAK: + case STAT_RXADDR_NAK: + case STAT_AD2W_NAK: + return -ENXIO; + default: + dev_err(i2c->dev, "unhandled state: %d\n", stat); + return -EIO; + } +} + /* calculate and set clock divisors */ static void octeon_i2c_set_clock(struct octeon_i2c *i2c) { @@ -318,7 +401,7 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) } data = octeon_i2c_stat_read(i2c); - if ((data != STAT_START) && (data != STAT_RSTART)) { + if ((data != STAT_START) && (data != STAT_REP_START)) { dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data); return -EIO; } @@ -347,7 +430,6 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, const u8 *data, int length) { int i, result; - u8 tmp; result = octeon_i2c_start(i2c); if (result) @@ -361,14 +443,9 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, return result; for (i = 0; i < length; i++) { - tmp = octeon_i2c_stat_read(i2c); - - if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) { - dev_err(i2c->dev, - "%s: bad status before write (0x%x)\n", - __func__, tmp); - return -EIO; - } + result = octeon_i2c_check_status(i2c, false); + if (result) + return result; octeon_i2c_data_write(i2c, data[i]); octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); @@ -397,7 +474,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, u8 *data, u16 *rlength, bool recv_len) { int i, result, length = *rlength; - u8 tmp; + bool final_read = false; if (length < 1) return -EINVAL; @@ -413,19 +490,21 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, if (result) return result; + /* address OK ? */ + result = octeon_i2c_check_status(i2c, false); + if (result) + return result; + for (i = 0; i < length; i++) { - tmp = octeon_i2c_stat_read(i2c); - if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) { - dev_err(i2c->dev, - "%s: bad status before read (0x%x)\n", - __func__, tmp); - return -EIO; - } + /* for the last byte TWSI_CTL_AAK must not be set */ + if (i + 1 == length) + final_read = true; - if (i + 1 < length) - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK); - else + /* clear iflg to allow next event */ + if (final_read) octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + else + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK); result = octeon_i2c_wait(i2c); if (result) @@ -441,6 +520,10 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, } length += data[i]; } + + result = octeon_i2c_check_status(i2c, final_read); + if (result) + return result; } *rlength = length; return 0; -- GitLab From c981e34eee146fe560c46704396342ff979346d7 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 25 Apr 2016 16:33:31 +0200 Subject: [PATCH 4303/9938] i2c: octeon: Use i2c recovery framework Switch to the i2c bus recovery framework using generic SCL recovery. If this fails try to reset the hardware. The recovery is triggered during START on timeout of the interrupt or failure to reach the START / repeated-START condition. The START function is moved to xfer and while at it remove the xfer debug message (i2c core already provides a debug message for this). Signed-off-by: Jan Glauber [wsa: removed one empty line] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 159 +++++++++++++++++++------------- 1 file changed, 96 insertions(+), 63 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 471d06eb8434..f83f6b8892b5 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -90,6 +90,8 @@ #define TWSI_INT_CORE_EN BIT_ULL(6) #define TWSI_INT_SDA_OVR BIT_ULL(8) #define TWSI_INT_SCL_OVR BIT_ULL(9) +#define TWSI_INT_SDA BIT_ULL(10) +#define TWSI_INT_SCL BIT_ULL(11) struct octeon_i2c { wait_queue_head_t queue; @@ -152,6 +154,17 @@ static u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg) #define octeon_i2c_stat_read(i2c) \ octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) +/** + * octeon_i2c_read_int - read the TWSI_INT register + * @i2c: The struct octeon_i2c + * + * Returns the value of the register. + */ +static u64 octeon_i2c_read_int(struct octeon_i2c *i2c) +{ + return __raw_readq(i2c->twsi_base + TWSI_INT); +} + /** * octeon_i2c_write_int - write the TWSI_INT register * @i2c: The struct octeon_i2c @@ -182,33 +195,6 @@ static void octeon_i2c_int_disable(struct octeon_i2c *i2c) octeon_i2c_write_int(i2c, 0); } -/** - * octeon_i2c_unblock - unblock the bus - * @i2c: The struct octeon_i2c - * - * If there was a reset while a device was driving 0 to bus, bus is blocked. - * We toggle it free manually by some clock cycles and send a stop. - */ -static void octeon_i2c_unblock(struct octeon_i2c *i2c) -{ - int i; - - dev_dbg(i2c->dev, "%s\n", __func__); - - for (i = 0; i < 9; i++) { - octeon_i2c_write_int(i2c, 0); - udelay(5); - octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR); - udelay(5); - } - /* hand-crank a STOP */ - octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR | TWSI_INT_SCL_OVR); - udelay(5); - octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR); - udelay(5); - octeon_i2c_write_int(i2c, 0); -} - /* interrupt service routine */ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) { @@ -371,6 +357,17 @@ static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) return -EIO; } +static int octeon_i2c_recovery(struct octeon_i2c *i2c) +{ + int ret; + + ret = i2c_recover_bus(&i2c->adap); + if (ret) + /* recover failed, try hardware re-init */ + ret = octeon_i2c_init_lowlevel(i2c); + return ret; +} + /** * octeon_i2c_start - send START to the bus * @i2c: The struct octeon_i2c @@ -379,34 +376,23 @@ static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) */ static int octeon_i2c_start(struct octeon_i2c *i2c) { - int result; - u8 data; + int ret; + u8 stat; octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); + ret = octeon_i2c_wait(i2c); + if (ret) + goto error; - result = octeon_i2c_wait(i2c); - if (result) { - if (octeon_i2c_stat_read(i2c) == STAT_IDLE) { - /* - * Controller refused to send start flag May - * be a client is holding SDA low - let's try - * to free it. - */ - octeon_i2c_unblock(i2c); - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); - result = octeon_i2c_wait(i2c); - } - if (result) - return result; - } - - data = octeon_i2c_stat_read(i2c); - if ((data != STAT_START) && (data != STAT_REP_START)) { - dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data); - return -EIO; - } + stat = octeon_i2c_stat_read(i2c); + if (stat == STAT_START || stat == STAT_REP_START) + /* START successful, bail out */ + return 0; - return 0; +error: + /* START failed, try to recover */ + ret = octeon_i2c_recovery(i2c); + return (ret) ? ret : -EAGAIN; } /* send STOP to the bus */ @@ -431,10 +417,6 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int target, { int i, result; - result = octeon_i2c_start(i2c); - if (result) - return result; - octeon_i2c_data_write(i2c, target << 1); octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); @@ -479,10 +461,6 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, if (length < 1) return -EINVAL; - result = octeon_i2c_start(i2c); - if (result) - return result; - octeon_i2c_data_write(i2c, (target << 1) | 1); octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); @@ -546,10 +524,10 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, for (i = 0; ret == 0 && i < num; i++) { struct i2c_msg *pmsg = &msgs[i]; - dev_dbg(i2c->dev, - "Doing %s %d byte(s) to/from 0x%02x - %d of %d messages\n", - pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->len, pmsg->addr, i + 1, num); + ret = octeon_i2c_start(i2c); + if (ret) + return ret; + if (pmsg->flags & I2C_M_RD) ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf, &pmsg->len, pmsg->flags & I2C_M_RECV_LEN); @@ -562,6 +540,60 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, return (ret != 0) ? ret : num; } +static int octeon_i2c_get_scl(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + u64 state; + + state = octeon_i2c_read_int(i2c); + return state & TWSI_INT_SCL; +} + +static void octeon_i2c_set_scl(struct i2c_adapter *adap, int val) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + + octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR); +} + +static int octeon_i2c_get_sda(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + u64 state; + + state = octeon_i2c_read_int(i2c); + return state & TWSI_INT_SDA; +} + +static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + + /* + * The stop resets the state machine, does not _transmit_ STOP unless + * engine was active. + */ + octeon_i2c_stop(i2c); + + octeon_i2c_write_int(i2c, 0); +} + +static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap) +{ + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + + octeon_i2c_write_int(i2c, 0); +} + +static struct i2c_bus_recovery_info octeon_i2c_recovery_info = { + .recover_bus = i2c_generic_scl_recovery, + .get_scl = octeon_i2c_get_scl, + .set_scl = octeon_i2c_set_scl, + .get_sda = octeon_i2c_get_sda, + .prepare_recovery = octeon_i2c_prepare_recovery, + .unprepare_recovery = octeon_i2c_unprepare_recovery, +}; + static u32 octeon_i2c_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | @@ -642,6 +674,7 @@ static int octeon_i2c_probe(struct platform_device *pdev) i2c->adap = octeon_i2c_ops; i2c->adap.timeout = msecs_to_jiffies(2); i2c->adap.retries = 5; + i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info; i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.of_node = node; i2c_set_adapdata(&i2c->adap, i2c); -- GitLab From 30c24b25142a9171d38e8074758b3a370906fc7d Mon Sep 17 00:00:00 2001 From: Peter Swain Date: Mon, 25 Apr 2016 16:33:33 +0200 Subject: [PATCH 4304/9938] i2c: octeon: Add flush writeq helper function Add helper function that reads back a value after writing to make sure the write is finished and use it in octeon_i2c_write_int(). Signed-off-by: Peter Swain Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index f83f6b8892b5..08ca66505ce2 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -103,6 +103,12 @@ struct octeon_i2c { struct device *dev; }; +static void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) +{ + __raw_writeq(val, addr); + __raw_readq(addr); /* wait for write to land */ +} + /** * octeon_i2c_reg_write - write an I2C core register * @i2c: The struct octeon_i2c @@ -172,8 +178,7 @@ static u64 octeon_i2c_read_int(struct octeon_i2c *i2c) */ static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) { - __raw_writeq(data, i2c->twsi_base + TWSI_INT); - __raw_readq(i2c->twsi_base + TWSI_INT); + octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT); } /** -- GitLab From d1fbff8944bf88e449ae387abd498e5220a2ee10 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 25 Apr 2016 16:33:34 +0200 Subject: [PATCH 4305/9938] i2c: octeon: Enable High-Level Controller Use High-Level Controller (HLC) when possible. The HLC can read/write up to 8 bytes and is completely optional. The most important difference of the HLC is that it only requires one interrupt for a transfer (up to 8 bytes) where the low-level read/write requires 2 interrupts plus one interrupt per transferred byte. Since the interrupts are costly using the HLC improves the performance. Also, the HLC provides improved error handling. Signed-off-by: David Daney Signed-off-by: Jan Glauber [wsa: fixed trivial checkpatch warnings] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 347 +++++++++++++++++++++++++++++++- 1 file changed, 337 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 08ca66505ce2..3273db714310 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -29,13 +29,23 @@ /* Register offsets */ #define SW_TWSI 0x00 #define TWSI_INT 0x10 +#define SW_TWSI_EXT 0x18 /* Controller command patterns */ #define SW_TWSI_V BIT_ULL(63) /* Valid bit */ +#define SW_TWSI_EIA BIT_ULL(61) /* Extended internal address */ #define SW_TWSI_R BIT_ULL(56) /* Result or read bit */ +#define SW_TWSI_SOVR BIT_ULL(55) /* Size override */ +#define SW_TWSI_SIZE_SHIFT 52 +#define SW_TWSI_ADDR_SHIFT 40 +#define SW_TWSI_IA_SHIFT 32 /* Internal address */ /* Controller opcode word (bits 60:57) */ #define SW_TWSI_OP_SHIFT 57 +#define SW_TWSI_OP_7 (0ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_7_IA (1ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_10 (2ULL << SW_TWSI_OP_SHIFT) +#define SW_TWSI_OP_10_IA (3ULL << SW_TWSI_OP_SHIFT) #define SW_TWSI_OP_TWSI_CLK (4ULL << SW_TWSI_OP_SHIFT) #define SW_TWSI_OP_EOP (6ULL << SW_TWSI_OP_SHIFT) /* Extended opcode */ @@ -48,7 +58,7 @@ #define SW_TWSI_EOP_TWSI_RST (SW_TWSI_OP_EOP | 7ULL << SW_TWSI_EOP_SHIFT) /* Controller command and status bits */ -#define TWSI_CTL_CE 0x80 +#define TWSI_CTL_CE 0x80 /* High level controller enable */ #define TWSI_CTL_ENAB 0x40 /* Bus enable */ #define TWSI_CTL_STA 0x20 /* Master-mode start, HW clears when done */ #define TWSI_CTL_STP 0x10 /* Master-mode stop, HW clears when done */ @@ -87,6 +97,11 @@ #define STAT_IDLE 0xF8 /* TWSI_INT values */ +#define TWSI_INT_ST_INT BIT_ULL(0) +#define TWSI_INT_TS_INT BIT_ULL(1) +#define TWSI_INT_CORE_INT BIT_ULL(2) +#define TWSI_INT_ST_EN BIT_ULL(4) +#define TWSI_INT_TS_EN BIT_ULL(5) #define TWSI_INT_CORE_EN BIT_ULL(6) #define TWSI_INT_SDA_OVR BIT_ULL(8) #define TWSI_INT_SCL_OVR BIT_ULL(9) @@ -101,6 +116,7 @@ struct octeon_i2c { int sys_freq; void __iomem *twsi_base; struct device *dev; + bool hlc_enabled; }; static void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) @@ -200,6 +216,47 @@ static void octeon_i2c_int_disable(struct octeon_i2c *i2c) octeon_i2c_write_int(i2c, 0); } +/* + * Cleanup low-level state & enable high-level controller. + */ +static void octeon_i2c_hlc_enable(struct octeon_i2c *i2c) +{ + int try = 0; + u64 val; + + if (i2c->hlc_enabled) + return; + i2c->hlc_enabled = true; + + while (1) { + val = octeon_i2c_ctl_read(i2c); + if (!(val & (TWSI_CTL_STA | TWSI_CTL_STP))) + break; + + /* clear IFLG event */ + if (val & TWSI_CTL_IFLG) + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); + + if (try++ > 100) { + pr_err("%s: giving up\n", __func__); + break; + } + + /* spin until any start/stop has finished */ + udelay(10); + } + octeon_i2c_ctl_write(i2c, TWSI_CTL_CE | TWSI_CTL_AAK | TWSI_CTL_ENAB); +} + +static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c) +{ + if (!i2c->hlc_enabled) + return; + + i2c->hlc_enabled = false; + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); +} + /* interrupt service routine */ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) { @@ -299,6 +356,245 @@ static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) } } +static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c) +{ + u64 val = __raw_readq(i2c->twsi_base + SW_TWSI); + + return (val & SW_TWSI_V) == 0; +} + +static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c) +{ + octeon_i2c_write_int(i2c, TWSI_INT_ST_EN); +} + +static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c) +{ + /* clear ST/TS events, listen for neither */ + octeon_i2c_write_int(i2c, TWSI_INT_ST_INT | TWSI_INT_TS_INT); +} + +/** + * octeon_i2c_hlc_wait - wait for an HLC operation to complete + * @i2c: The struct octeon_i2c + * + * Returns 0 on success, otherwise -ETIMEDOUT. + */ +static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) +{ + int time_left; + + octeon_i2c_hlc_int_enable(i2c); + time_left = wait_event_timeout(i2c->queue, + octeon_i2c_hlc_test_ready(i2c), + i2c->adap.timeout); + octeon_i2c_int_disable(i2c); + if (!time_left) { + octeon_i2c_hlc_int_clear(i2c); + return -ETIMEDOUT; + } + return 0; +} + +/* high-level-controller pure read of up to 8 bytes */ +static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + int i, j, ret = 0; + u64 cmd; + + octeon_i2c_hlc_enable(i2c); + octeon_i2c_hlc_int_clear(i2c); + + cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10; + else + cmd |= SW_TWSI_OP_7; + + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) + msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; + + if (msgs[0].len > 4) { + cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); + for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) + msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff; + } + +err: + return ret; +} + +/* high-level-controller pure write of up to 8 bytes */ +static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + int i, j, ret = 0; + u64 cmd; + + octeon_i2c_hlc_enable(i2c); + octeon_i2c_hlc_int_clear(i2c); + + cmd = SW_TWSI_V | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10; + else + cmd |= SW_TWSI_OP_7; + + for (i = 0, j = msgs[0].len - 1; i < msgs[0].len && i < 4; i++, j--) + cmd |= (u64)msgs[0].buf[j] << (8 * i); + + if (msgs[0].len > 4) { + u64 ext = 0; + + for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--) + ext |= (u64)msgs[0].buf[j] << (8 * i); + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + } + + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + ret = octeon_i2c_check_status(i2c, false); + +err: + return ret; +} + +/* high-level-controller composite write+read, msg0=addr, msg1=data */ +static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + int i, j, ret = 0; + u64 cmd; + + octeon_i2c_hlc_enable(i2c); + + cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10_IA; + else + cmd |= SW_TWSI_OP_7_IA; + + if (msgs[0].len == 2) { + u64 ext = 0; + + cmd |= SW_TWSI_EIA; + ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + } else { + cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + } + + octeon_i2c_hlc_int_clear(i2c); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) + msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; + + if (msgs[1].len > 4) { + cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT); + for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--) + msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff; + } + +err: + return ret; +} + +/* high-level-controller composite write+write, m[0]len<=2, m[1]len<=8 */ +static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs) +{ + bool set_ext = false; + int i, j, ret = 0; + u64 cmd, ext = 0; + + octeon_i2c_hlc_enable(i2c); + + cmd = SW_TWSI_V | SW_TWSI_SOVR; + /* SIZE */ + cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT; + /* A */ + cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT; + + if (msgs[0].flags & I2C_M_TEN) + cmd |= SW_TWSI_OP_10_IA; + else + cmd |= SW_TWSI_OP_7_IA; + + if (msgs[0].len == 2) { + cmd |= SW_TWSI_EIA; + ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + set_ext = true; + cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT; + } else { + cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT; + } + + for (i = 0, j = msgs[1].len - 1; i < msgs[1].len && i < 4; i++, j--) + cmd |= (u64)msgs[1].buf[j] << (8 * i); + + if (msgs[1].len > 4) { + for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--) + ext |= (u64)msgs[1].buf[j] << (8 * i); + set_ext = true; + } + if (set_ext) + octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT); + + octeon_i2c_hlc_int_clear(i2c); + octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI); + + ret = octeon_i2c_hlc_wait(i2c); + if (ret) + goto err; + + cmd = __raw_readq(i2c->twsi_base + SW_TWSI); + if ((cmd & SW_TWSI_R) == 0) + return -EAGAIN; + + ret = octeon_i2c_check_status(i2c, false); + +err: + return ret; +} + /* calculate and set clock divisors */ static void octeon_i2c_set_clock(struct octeon_i2c *i2c) { @@ -343,23 +639,29 @@ static void octeon_i2c_set_clock(struct octeon_i2c *i2c) static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c) { - u8 status; + u8 status = 0; int tries; - /* disable high level controller, enable bus access */ - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); - /* reset controller */ octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0); - for (tries = 10; tries; tries--) { + for (tries = 10; tries && status != STAT_IDLE; tries--) { udelay(1); status = octeon_i2c_stat_read(i2c); if (status == STAT_IDLE) - return 0; + break; } - dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status); - return -EIO; + + if (status != STAT_IDLE) { + dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", + __func__, status); + return -EIO; + } + + /* toggle twice to force both teardowns */ + octeon_i2c_hlc_enable(i2c); + octeon_i2c_hlc_disable(i2c); + return 0; } static int octeon_i2c_recovery(struct octeon_i2c *i2c) @@ -384,6 +686,8 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) int ret; u8 stat; + octeon_i2c_hlc_disable(i2c); + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); ret = octeon_i2c_wait(i2c); if (ret) @@ -526,6 +830,28 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, struct octeon_i2c *i2c = i2c_get_adapdata(adap); int i, ret = 0; + if (num == 1) { + if (msgs[0].len > 0 && msgs[0].len <= 8) { + if (msgs[0].flags & I2C_M_RD) + ret = octeon_i2c_hlc_read(i2c, msgs); + else + ret = octeon_i2c_hlc_write(i2c, msgs); + goto out; + } + } else if (num == 2) { + if ((msgs[0].flags & I2C_M_RD) == 0 && + (msgs[1].flags & I2C_M_RECV_LEN) == 0 && + msgs[0].len > 0 && msgs[0].len <= 2 && + msgs[1].len > 0 && msgs[1].len <= 8 && + msgs[0].addr == msgs[1].addr) { + if (msgs[1].flags & I2C_M_RD) + ret = octeon_i2c_hlc_comp_read(i2c, msgs); + else + ret = octeon_i2c_hlc_comp_write(i2c, msgs); + goto out; + } + } + for (i = 0; ret == 0 && i < num; i++) { struct i2c_msg *pmsg = &msgs[i]; @@ -541,7 +867,7 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, pmsg->len); } octeon_i2c_stop(i2c); - +out: return (ret != 0) ? ret : num; } @@ -580,6 +906,7 @@ static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap) */ octeon_i2c_stop(i2c); + octeon_i2c_hlc_disable(i2c); octeon_i2c_write_int(i2c, 0); } -- GitLab From 1d2d8de44a6c20af262b4c3d3b93ef7ec3c5488e Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 20 Apr 2016 11:20:27 +0100 Subject: [PATCH 4306/9938] drivers: firmware: psci: drop duplicate const from psci_of_match This is to fix below sparse warning: drivers/firmware/psci.c:mmm:nn: warning: duplicate const Signed-off-by: Jisheng Zhang Signed-off-by: Lorenzo Pieralisi Signed-off-by: Arnd Bergmann --- drivers/firmware/psci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index 11bfee8b79a9..0ab477ba6564 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -563,7 +563,7 @@ static int __init psci_0_1_init(struct device_node *np) return err; } -static const struct of_device_id const psci_of_match[] __initconst = { +static const struct of_device_id psci_of_match[] __initconst = { { .compatible = "arm,psci", .data = psci_0_1_init}, { .compatible = "arm,psci-0.2", .data = psci_0_2_init}, { .compatible = "arm,psci-1.0", .data = psci_0_2_init}, -- GitLab From 21e8868e661ededd2c45c8ec27f6fd5354b88b71 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 20 Apr 2016 11:20:28 +0100 Subject: [PATCH 4307/9938] drivers: firmware: psci: make two helper functions static psci_power_state_loses_context() and psci_power_state_is_valid are only used internally now, so make them static. Signed-off-by: Jisheng Zhang Signed-off-by: Lorenzo Pieralisi Signed-off-by: Arnd Bergmann --- drivers/firmware/psci.c | 4 ++-- include/linux/psci.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index 0ab477ba6564..04f2ac54e5ab 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -91,7 +91,7 @@ static inline bool psci_has_ext_power_state(void) PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK; } -bool psci_power_state_loses_context(u32 state) +static bool psci_power_state_loses_context(u32 state) { const u32 mask = psci_has_ext_power_state() ? PSCI_1_0_EXT_POWER_STATE_TYPE_MASK : @@ -100,7 +100,7 @@ bool psci_power_state_loses_context(u32 state) return state & mask; } -bool psci_power_state_is_valid(u32 state) +static bool psci_power_state_is_valid(u32 state) { const u32 valid_mask = psci_has_ext_power_state() ? PSCI_1_0_EXT_POWER_STATE_MASK : diff --git a/include/linux/psci.h b/include/linux/psci.h index 393efe2edf9a..bdea1cb5e1db 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -21,8 +21,6 @@ #define PSCI_POWER_STATE_TYPE_POWER_DOWN 1 bool psci_tos_resident_on(int cpu); -bool psci_power_state_loses_context(u32 state); -bool psci_power_state_is_valid(u32 state); int psci_cpu_init_idle(unsigned int cpu); int psci_cpu_suspend_enter(unsigned long index); -- GitLab From 4729cbe038fdd321839d7780ee93ce1ccf1e7b29 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 25 Apr 2016 16:33:35 +0200 Subject: [PATCH 4308/9938] i2c: octeon: Add support for cn78xx chips cn78xx has a different interrupt architecture, so we have to manage the interrupts differently. Signed-off-by: David Daney Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- .../devicetree/bindings/i2c/i2c-octeon.txt | 6 + drivers/i2c/busses/i2c-octeon.c | 129 ++++++++++++++++-- 2 files changed, 125 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-octeon.txt b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt index dced82ebe31d..872d485dffab 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-octeon.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt @@ -4,6 +4,12 @@ Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + or + + compatible: "cavium,octeon-7890-twsi" + + Compatibility with cn78XX SOCs. + - reg: The base address of the TWSI/I2C bus controller register bank. - #address-cells: Must be <1>. diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 3273db714310..6a4f0581a7e0 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -11,6 +11,7 @@ * warranty of any kind, whether express or implied. */ +#include #include #include #include @@ -112,11 +113,18 @@ struct octeon_i2c { wait_queue_head_t queue; struct i2c_adapter adap; int irq; + int hlc_irq; /* For cn7890 only */ u32 twsi_freq; int sys_freq; void __iomem *twsi_base; struct device *dev; bool hlc_enabled; + void (*int_enable)(struct octeon_i2c *); + void (*int_disable)(struct octeon_i2c *); + void (*hlc_int_enable)(struct octeon_i2c *); + void (*hlc_int_disable)(struct octeon_i2c *); + atomic_t int_enable_cnt; + atomic_t hlc_int_enable_cnt; }; static void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) @@ -216,6 +224,58 @@ static void octeon_i2c_int_disable(struct octeon_i2c *i2c) octeon_i2c_write_int(i2c, 0); } +/** + * octeon_i2c_int_enable78 - enable the CORE interrupt + * @i2c: The struct octeon_i2c + * + * The interrupt will be asserted when there is non-STAT_IDLE state in the + * SW_TWSI_EOP_TWSI_STAT register. + */ +static void octeon_i2c_int_enable78(struct octeon_i2c *i2c) +{ + atomic_inc_return(&i2c->int_enable_cnt); + enable_irq(i2c->irq); +} + +static void __octeon_i2c_irq_disable(atomic_t *cnt, int irq) +{ + int count; + + /* + * The interrupt can be disabled in two places, but we only + * want to make the disable_irq_nosync() call once, so keep + * track with the atomic variable. + */ + count = atomic_dec_if_positive(cnt); + if (count >= 0) + disable_irq_nosync(irq); +} + +/* disable the CORE interrupt */ +static void octeon_i2c_int_disable78(struct octeon_i2c *i2c) +{ + __octeon_i2c_irq_disable(&i2c->int_enable_cnt, i2c->irq); +} + +/** + * octeon_i2c_hlc_int_enable78 - enable the ST interrupt + * @i2c: The struct octeon_i2c + * + * The interrupt will be asserted when there is non-STAT_IDLE state in + * the SW_TWSI_EOP_TWSI_STAT register. + */ +static void octeon_i2c_hlc_int_enable78(struct octeon_i2c *i2c) +{ + atomic_inc_return(&i2c->hlc_int_enable_cnt); + enable_irq(i2c->hlc_irq); +} + +/* disable the ST interrupt */ +static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c) +{ + __octeon_i2c_irq_disable(&i2c->hlc_int_enable_cnt, i2c->hlc_irq); +} + /* * Cleanup low-level state & enable high-level controller. */ @@ -262,7 +322,18 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) { struct octeon_i2c *i2c = dev_id; - octeon_i2c_int_disable(i2c); + i2c->int_disable(i2c); + wake_up(&i2c->queue); + + return IRQ_HANDLED; +} + +/* HLC interrupt service routine */ +static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id) +{ + struct octeon_i2c *i2c = dev_id; + + i2c->hlc_int_disable(i2c); wake_up(&i2c->queue); return IRQ_HANDLED; @@ -283,10 +354,10 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) { long time_left; - octeon_i2c_int_enable(i2c); + i2c->int_enable(i2c); time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c), i2c->adap.timeout); - octeon_i2c_int_disable(i2c); + i2c->int_disable(i2c); if (!time_left) { dev_dbg(i2c->dev, "%s: timeout\n", __func__); return -ETIMEDOUT; @@ -384,11 +455,11 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) { int time_left; - octeon_i2c_hlc_int_enable(i2c); + i2c->hlc_int_enable(i2c); time_left = wait_event_timeout(i2c->queue, octeon_i2c_hlc_test_ready(i2c), i2c->adap.timeout); - octeon_i2c_int_disable(i2c); + i2c->hlc_int_disable(i2c); if (!time_left) { octeon_i2c_hlc_int_clear(i2c); return -ETIMEDOUT; @@ -946,14 +1017,26 @@ static struct i2c_adapter octeon_i2c_ops = { static int octeon_i2c_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; + int irq, result = 0, hlc_irq = 0; struct resource *res_mem; struct octeon_i2c *i2c; - int irq, result = 0; + bool cn78xx_style; + + cn78xx_style = of_device_is_compatible(node, "cavium,octeon-7890-twsi"); + if (cn78xx_style) { + hlc_irq = platform_get_irq(pdev, 0); + if (hlc_irq < 0) + return hlc_irq; - /* All adaptors have an irq. */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + irq = platform_get_irq(pdev, 2); + if (irq < 0) + return irq; + } else { + /* All adaptors have an irq. */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + } i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) { @@ -988,6 +1071,31 @@ static int octeon_i2c_probe(struct platform_device *pdev) i2c->irq = irq; + if (cn78xx_style) { + i2c->hlc_irq = hlc_irq; + + i2c->int_enable = octeon_i2c_int_enable78; + i2c->int_disable = octeon_i2c_int_disable78; + i2c->hlc_int_enable = octeon_i2c_hlc_int_enable78; + i2c->hlc_int_disable = octeon_i2c_hlc_int_disable78; + + irq_set_status_flags(i2c->irq, IRQ_NOAUTOEN); + irq_set_status_flags(i2c->hlc_irq, IRQ_NOAUTOEN); + + result = devm_request_irq(&pdev->dev, i2c->hlc_irq, + octeon_i2c_hlc_isr78, 0, + DRV_NAME, i2c); + if (result < 0) { + dev_err(i2c->dev, "failed to attach interrupt\n"); + goto out; + } + } else { + i2c->int_enable = octeon_i2c_int_enable; + i2c->int_disable = octeon_i2c_int_disable; + i2c->hlc_int_enable = octeon_i2c_hlc_int_enable; + i2c->hlc_int_disable = octeon_i2c_int_disable; + } + result = devm_request_irq(&pdev->dev, i2c->irq, octeon_i2c_isr, 0, DRV_NAME, i2c); if (result < 0) { @@ -1034,6 +1142,7 @@ static int octeon_i2c_remove(struct platform_device *pdev) static const struct of_device_id octeon_i2c_match[] = { { .compatible = "cavium,octeon-3860-twsi", }, + { .compatible = "cavium,octeon-7890-twsi", }, {}, }; MODULE_DEVICE_TABLE(of, octeon_i2c_match); -- GitLab From 01bbcdffa90d13f61d8034ef82a68484edbc2f5c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 15 Apr 2016 19:48:29 +0900 Subject: [PATCH 4309/9938] ARM: uniphier: correct the call order of of_node_put() Put nodes after of_address_to_resource() in case the nodes might be released while parsing in them. Signed-off-by: Masahiro Yamada Signed-off-by: Arnd Bergmann --- arch/arm/mach-uniphier/platsmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-uniphier/platsmp.c b/arch/arm/mach-uniphier/platsmp.c index 69141357afe8..8693b7c15d59 100644 --- a/arch/arm/mach-uniphier/platsmp.c +++ b/arch/arm/mach-uniphier/platsmp.c @@ -99,16 +99,16 @@ static int __init uniphier_smp_prepare_trampoline(unsigned int max_cpus) int ret; np = of_find_compatible_node(NULL, NULL, "socionext,uniphier-smpctrl"); - of_node_put(np); ret = of_address_to_resource(np, 0, &res); + of_node_put(np); if (!ret) { rom_rsv2_phys = res.start + UNIPHIER_SMPCTRL_ROM_RSV2; } else { /* try old binding too */ np = of_find_compatible_node(NULL, NULL, "socionext,uniphier-system-bus-controller"); - of_node_put(np); ret = of_address_to_resource(np, 1, &res); + of_node_put(np); if (ret) { pr_err("failed to get resource of SMP control\n"); return ret; -- GitLab From b1b3df2fc808187e3c9e50162b55fb458035b0ab Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 21 Apr 2016 09:04:49 +0200 Subject: [PATCH 4310/9938] i2c: s3c2410: Add missing clock unprepare on probe() error path If during probe() the s3c24xx_i2c_init() failed, the clock was left in disabled but prepared state. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-s3c2410.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 1bc756313cb8..3f16f30edbd2 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1200,6 +1200,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) clk_disable(i2c->clk); if (ret != 0) { dev_err(&pdev->dev, "I2C controller init failed\n"); + clk_unprepare(i2c->clk); return ret; } /* find the IRQ for this unit (note, this relies on the init call to -- GitLab From ec7c34a4c6c71487a5de4c1b2d47beb2c334aa0d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 21 Apr 2016 09:04:50 +0200 Subject: [PATCH 4311/9938] i2c: s3c2410: Minor function-level comment cleanup Cleanup the weird function-level comments and remove obvious documentation for probe/remove. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-s3c2410.c | 110 +++++++++---------------------- 1 file changed, 32 insertions(+), 78 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 3f16f30edbd2..7245c81366be 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -163,11 +163,9 @@ static const struct of_device_id s3c24xx_i2c_match[] = { MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); #endif -/* s3c24xx_get_device_quirks - * +/* * Get controller type either from device tree or platform device variant. -*/ - + */ static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *pdev) { if (pdev->dev.of_node) { @@ -179,12 +177,10 @@ static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *p return platform_get_device_id(pdev)->driver_data; } -/* s3c24xx_i2c_master_complete - * - * complete the message and wake up the caller, using the given return code, +/* + * Complete the message and wake up the caller, using the given return code, * or zero to mean ok. -*/ - + */ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) { dev_dbg(i2c->dev, "master_complete %d\n", ret); @@ -217,7 +213,6 @@ static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c) } /* irq enable/disable functions */ - static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c) { unsigned long tmp; @@ -251,11 +246,9 @@ static bool is_ack(struct s3c24xx_i2c *i2c) return false; } -/* s3c24xx_i2c_message_start - * +/* * put the start of a message onto the bus -*/ - + */ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, struct i2c_msg *msg) { @@ -364,21 +357,17 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) /* helper functions to determine the current state in the set of * messages we are sending */ -/* is_lastmsg() - * +/* * returns TRUE if the current message is the last in the set -*/ - + */ static inline int is_lastmsg(struct s3c24xx_i2c *i2c) { return i2c->msg_idx >= (i2c->msg_num - 1); } -/* is_msglast - * +/* * returns TRUE if we this is the last byte in the current message -*/ - + */ static inline int is_msglast(struct s3c24xx_i2c *i2c) { /* msg->len is always 1 for the first byte of smbus block read. @@ -390,21 +379,17 @@ static inline int is_msglast(struct s3c24xx_i2c *i2c) return i2c->msg_ptr == i2c->msg->len-1; } -/* is_msgend - * +/* * returns TRUE if we reached the end of the current message -*/ - + */ static inline int is_msgend(struct s3c24xx_i2c *i2c) { return i2c->msg_ptr >= i2c->msg->len; } -/* i2c_s3c_irq_nextbyte - * +/* * process an interrupt and work out what to do */ - static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) { unsigned long tmp; @@ -568,11 +553,9 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) return ret; } -/* s3c24xx_i2c_irq - * +/* * top level IRQ servicing routine -*/ - + */ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id) { struct s3c24xx_i2c *i2c = dev_id; @@ -630,11 +613,9 @@ static inline void s3c24xx_i2c_disable_bus(struct s3c24xx_i2c *i2c) } -/* s3c24xx_i2c_set_master - * +/* * get the i2c bus for a master transaction -*/ - + */ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) { unsigned long iicstat; @@ -652,11 +633,9 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) return -ETIMEDOUT; } -/* s3c24xx_i2c_wait_idle - * +/* * wait for the i2c bus to become idle. -*/ - + */ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c) { unsigned long iicstat; @@ -706,11 +685,9 @@ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c) dev_warn(i2c->dev, "timeout waiting for bus idle\n"); } -/* s3c24xx_i2c_doxfer - * +/* * this starts an i2c transfer -*/ - + */ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) { @@ -771,12 +748,10 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, return ret; } -/* s3c24xx_i2c_xfer - * +/* * first port of call from the i2c bus code when an message needs * transferring across the i2c bus. -*/ - + */ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { @@ -814,17 +789,14 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) } /* i2c bus registration info */ - static const struct i2c_algorithm s3c24xx_i2c_algorithm = { .master_xfer = s3c24xx_i2c_xfer, .functionality = s3c24xx_i2c_func, }; -/* s3c24xx_i2c_calcdivisor - * +/* * return the divisor settings for a given frequency -*/ - + */ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted, unsigned int *div1, unsigned int *divs) { @@ -850,13 +822,11 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted, return clkin / (calc_divs * calc_div1); } -/* s3c24xx_i2c_clockrate - * +/* * work out a divisor for the user requested frequency setting, * either by the requested frequency, or scanning the acceptable * range of frequencies until something is found -*/ - + */ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) { struct s3c2410_platform_i2c *pdata = i2c->pdata; @@ -1028,11 +998,9 @@ static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) } #endif -/* s3c24xx_i2c_init - * +/* * initialise the controller, set the IO lines and frequency -*/ - + */ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) { struct s3c2410_platform_i2c *pdata; @@ -1068,11 +1036,9 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) } #ifdef CONFIG_OF -/* s3c24xx_i2c_parse_dt - * +/* * Parse the device tree node and retreive the platform data. -*/ - + */ static void s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) { @@ -1111,11 +1077,6 @@ s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) } #endif -/* s3c24xx_i2c_probe - * - * called by the bus driver when a suitable device is found -*/ - static int s3c24xx_i2c_probe(struct platform_device *pdev) { struct s3c24xx_i2c *i2c; @@ -1258,11 +1219,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return 0; } -/* s3c24xx_i2c_remove - * - * called when device is removed from the bus -*/ - static int s3c24xx_i2c_remove(struct platform_device *pdev) { struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); @@ -1326,8 +1282,6 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { #define S3C24XX_DEV_PM_OPS NULL #endif -/* device driver for platform bus bits */ - static struct platform_driver s3c24xx_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, -- GitLab From 0915833bd5f9987fdcdb491da1e75026bae05683 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 21 Apr 2016 09:04:51 +0200 Subject: [PATCH 4312/9938] i2c: s3c2410: Cleanup indentation and comment style Improve the readability by: - fixing indentation, - switching to proper block comments, - removing spurious blank lines, - checkpatch: void function return statements are not generally useful, - checkpatch: braces {} are not necessary for any arm of this statement, - checkpatch: missing a blank line after declarations. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-s3c2410.c | 113 ++++++++++++++++--------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 7245c81366be..dde1abce07ee 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -170,6 +170,7 @@ static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *p { if (pdev->dev.of_node) { const struct of_device_id *match; + match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node); return (kernel_ulong_t)match->data; } @@ -277,9 +278,10 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); writeb(addr, i2c->regs + S3C2410_IICDS); - /* delay here to ensure the data byte has gotten onto the bus - * before the transaction is started */ - + /* + * delay here to ensure the data byte has gotten onto the bus + * before the transaction is started + */ ndelay(i2c->tx_setup); dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); @@ -354,8 +356,10 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) s3c24xx_i2c_disable_irq(i2c); } -/* helper functions to determine the current state in the set of - * messages we are sending */ +/* + * helper functions to determine the current state in the set of + * messages we are sending + */ /* * returns TRUE if the current message is the last in the set @@ -370,9 +374,11 @@ static inline int is_lastmsg(struct s3c24xx_i2c *i2c) */ static inline int is_msglast(struct s3c24xx_i2c *i2c) { - /* msg->len is always 1 for the first byte of smbus block read. + /* + * msg->len is always 1 for the first byte of smbus block read. * Actual length will be read from slave. More bytes will be - * read according to the length then. */ + * read according to the length then. + */ if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1) return 0; @@ -408,14 +414,13 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) goto out_ack; case STATE_START: - /* last thing we did was send a start condition on the + /* + * last thing we did was send a start condition on the * bus, or started a new i2c message */ - if (iicstat & S3C2410_IICSTAT_LASTBIT && !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { /* ack was not received... */ - dev_dbg(i2c->dev, "ack was not received\n"); s3c24xx_i2c_stop(i2c, -ENXIO); goto out_ack; @@ -426,9 +431,10 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) else i2c->state = STATE_WRITE; - /* terminate the transfer if there is nothing to do - * as this is used by the i2c probe to find devices. */ - + /* + * Terminate the transfer if there is nothing to do + * as this is used by the i2c probe to find devices. + */ if (is_lastmsg(i2c) && i2c->msg->len == 0) { s3c24xx_i2c_stop(i2c, 0); goto out_ack; @@ -437,14 +443,16 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) if (i2c->state == STATE_READ) goto prepare_read; - /* fall through to the write state, as we will need to - * send a byte as well */ + /* + * fall through to the write state, as we will need to + * send a byte as well + */ case STATE_WRITE: - /* we are writing data to the device... check for the + /* + * we are writing data to the device... check for the * end of the message, and if so, work out what to do */ - if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { if (iicstat & S3C2410_IICSTAT_LASTBIT) { dev_dbg(i2c->dev, "WRITE: No Ack\n"); @@ -460,12 +468,13 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) byte = i2c->msg->buf[i2c->msg_ptr++]; writeb(byte, i2c->regs + S3C2410_IICDS); - /* delay after writing the byte to allow the + /* + * delay after writing the byte to allow the * data setup time on the bus, as writing the * data to the register causes the first bit * to appear on SDA, and SCL will change as - * soon as the interrupt is acknowledged */ - + * soon as the interrupt is acknowledged + */ ndelay(i2c->tx_setup); } else if (!is_lastmsg(i2c)) { @@ -481,10 +490,11 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) if (i2c->msg->flags & I2C_M_NOSTART) { if (i2c->msg->flags & I2C_M_RD) { - /* cannot do this, the controller + /* + * cannot do this, the controller * forces us to send a new START - * when we change direction */ - + * when we change direction + */ s3c24xx_i2c_stop(i2c, -EINVAL); } @@ -497,17 +507,16 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) } else { /* send stop */ - s3c24xx_i2c_stop(i2c, 0); } break; case STATE_READ: - /* we have a byte of data in the data register, do + /* + * we have a byte of data in the data register, do * something with it, and then work out whether we are * going to do any more read/write */ - byte = readb(i2c->regs + S3C2410_IICDS); i2c->msg->buf[i2c->msg_ptr++] = byte; @@ -522,9 +531,10 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) s3c24xx_i2c_disable_ack(i2c); } else if (is_msgend(i2c)) { - /* ok, we've read the entire buffer, see if there - * is anything else we need to do */ - + /* + * ok, we've read the entire buffer, see if there + * is anything else we need to do + */ if (is_lastmsg(i2c)) { /* last message, send stop and complete */ dev_dbg(i2c->dev, "READ: Send Stop\n"); @@ -578,9 +588,10 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id) goto out; } - /* pretty much this leaves us with the fact that we've - * transmitted or received whatever byte we last sent */ - + /* + * pretty much this leaves us with the fact that we've + * transmitted or received whatever byte we last sent + */ i2c_s3c_irq_nextbyte(i2c, status); out: @@ -726,9 +737,10 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, ret = i2c->msg_idx; - /* having these next two as dev_err() makes life very - * noisy when doing an i2cdetect */ - + /* + * Having these next two as dev_err() makes life very + * noisy when doing an i2cdetect + */ if (timeout == 0) dev_dbg(i2c->dev, "timeout\n"); else if (ret != num) @@ -1071,10 +1083,7 @@ s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) } #else static void -s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) -{ - return; -} +s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) { } #endif static int s3c24xx_i2c_probe(struct platform_device *pdev) @@ -1117,7 +1126,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); /* find the clock and enable it */ - i2c->dev = &pdev->dev; i2c->clk = devm_clk_get(&pdev->dev, "i2c"); if (IS_ERR(i2c->clk)) { @@ -1127,9 +1135,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); - /* map the registers */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2c->regs = devm_ioremap_resource(&pdev->dev, res); @@ -1140,22 +1146,17 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) i2c->regs, res); /* setup info block for the i2c core */ - i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &pdev->dev; - i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev); /* inititalise the i2c gpio lines */ - - if (i2c->pdata->cfg_gpio) { + if (i2c->pdata->cfg_gpio) i2c->pdata->cfg_gpio(to_platform_device(i2c->dev)); - } else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) { + else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) return -EINVAL; - } /* initialise the i2c controller */ - clk_prepare_enable(i2c->clk); ret = s3c24xx_i2c_init(i2c); clk_disable(i2c->clk); @@ -1164,10 +1165,11 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) clk_unprepare(i2c->clk); return ret; } - /* find the IRQ for this unit (note, this relies on the init call to + + /* + * find the IRQ for this unit (note, this relies on the init call to * ensure no current IRQs pending */ - if (!(i2c->quirks & QUIRK_POLL)) { i2c->irq = ret = platform_get_irq(pdev, 0); if (ret <= 0) { @@ -1176,9 +1178,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return ret; } - ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0, - dev_name(&pdev->dev), i2c); - + ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, + 0, dev_name(&pdev->dev), i2c); if (ret != 0) { dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); clk_unprepare(i2c->clk); @@ -1193,12 +1194,12 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return ret; } - /* Note, previous versions of the driver used i2c_add_adapter() + /* + * Note, previous versions of the driver used i2c_add_adapter() * to add the bus at any number. We now pass the bus number via * the platform data, so if unset it will now default to always * being bus 0. */ - i2c->adap.nr = i2c->pdata->bus_num; i2c->adap.dev.of_node = pdev->dev.of_node; -- GitLab From 8f8edd491ac64c3cfe4e8ffff2b7385df5c02860 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 20 Apr 2016 10:37:55 -0400 Subject: [PATCH 4313/9938] i2c: s3c2410: Print errno code in error logs The driver not always prints the error code in case of a failure but this information can be very useful for debugging. So let's print if available. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-s3c2410.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index dde1abce07ee..c08830549578 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -926,7 +926,7 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, i2c_unlock_adapter(&i2c->adap); if (ret < 0) - dev_err(i2c->dev, "cannot find frequency\n"); + dev_err(i2c->dev, "cannot find frequency (%d)\n", ret); else dev_info(i2c->dev, "setting freq %d\n", got); } @@ -977,7 +977,8 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) ret = gpio_request(gpio, "i2c-bus"); if (ret) { - dev_err(i2c->dev, "gpio [%d] request failed\n", gpio); + dev_err(i2c->dev, "gpio [%d] request failed (%d)\n", + gpio, ret); goto free_gpio; } } -- GitLab From d16415b2627e91a45778e1888bfdd5c6744294bf Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 20 Apr 2016 10:37:56 -0400 Subject: [PATCH 4314/9938] i2c: s3c2410: Check clk_prepare_enable() return value The clk_prepare_enable() function can fail so check the return value and propagate the error in case of a failure. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-s3c2410.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index c08830549578..38dc1cacfd8b 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1158,7 +1158,12 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return -EINVAL; /* initialise the i2c controller */ - clk_prepare_enable(i2c->clk); + ret = clk_prepare_enable(i2c->clk); + if (ret) { + dev_err(&pdev->dev, "I2C clock enable failed\n"); + return ret; + } + ret = s3c24xx_i2c_init(i2c); clk_disable(i2c->clk); if (ret != 0) { -- GitLab From 55441070ca1cbd47ce1ad2959bbf4b47aed9b83b Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Fri, 22 Apr 2016 18:06:11 +0200 Subject: [PATCH 4315/9938] Bluetooth: 6lowpan: Fix memory corruption of ipv6 destination address The memcpy of ipv6 header destination address to the skb control block (sbk->cb) in header_create() results in currupted memory when bt_xmit() is issued. The skb->cb is "released" in the return of header_create() making room for lower layer to minipulate the skb->cb. The value retrieved in bt_xmit is not persistent across header creation and sending, and the lower layer will overwrite portions of skb->cb, making the copied destination address wrong. The memory corruption will lead to non-working multicast as the first 4 bytes of the copied destination address is replaced by a value that resolves into a non-multicast prefix. This fix removes the dependency on the skb control block between header creation and send, by moving the destination address memcpy to the send function path (setup_create, which is called from bt_xmit). Signed-off-by: Glenn Ruben Bakke Acked-by: Jukka Rissanen Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org # 4.5+ --- net/bluetooth/6lowpan.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 38e82ddd7ccd..780089d75915 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -434,15 +434,18 @@ static int setup_header(struct sk_buff *skb, struct net_device *netdev, bdaddr_t *peer_addr, u8 *peer_addr_type) { struct in6_addr ipv6_daddr; + struct ipv6hdr *hdr; struct lowpan_btle_dev *dev; struct lowpan_peer *peer; bdaddr_t addr, *any = BDADDR_ANY; u8 *daddr = any->b; int err, status = 0; + hdr = ipv6_hdr(skb); + dev = lowpan_btle_dev(netdev); - memcpy(&ipv6_daddr, &lowpan_cb(skb)->addr, sizeof(ipv6_daddr)); + memcpy(&ipv6_daddr, &hdr->daddr, sizeof(ipv6_daddr)); if (ipv6_addr_is_multicast(&ipv6_daddr)) { lowpan_cb(skb)->chan = NULL; @@ -492,15 +495,9 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev, unsigned short type, const void *_daddr, const void *_saddr, unsigned int len) { - struct ipv6hdr *hdr; - if (type != ETH_P_IPV6) return -EINVAL; - hdr = ipv6_hdr(skb); - - memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, sizeof(struct in6_addr)); - return 0; } -- GitLab From d3829c1b8443a83324419eb129c7e4c780bf435f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Apr 2016 00:53:40 +0200 Subject: [PATCH 4316/9938] soc: brcmstb: select SOC_BUS The newly added code for the SoC bus fails to link if the bus is not built: drivers/soc/built-in.o: In function `brcmstb_soc_device_init': :(.init.text+0x110): undefined reference to `soc_device_register' This adds a 'select' statement to avoid the error. Signed-off-by: Arnd Bergmann Fixes: cef4bafcea2c ("soc: brcmstb: add SoC driver to brcmstb") Acked-by: Florian Fainelli --- drivers/soc/brcmstb/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig index 39cab3bd544d..7fec3b4c80a1 100644 --- a/drivers/soc/brcmstb/Kconfig +++ b/drivers/soc/brcmstb/Kconfig @@ -1,6 +1,7 @@ menuconfig SOC_BRCMSTB bool "Broadcom STB SoC drivers" depends on ARM + select SOC_BUS help Enables drivers for the Broadcom Set-Top Box (STB) series of chips. This option alone enables only some support code, while the drivers -- GitLab From 8d3fd357a28e420b1e154daf1cabdaa103911c08 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 25 Apr 2016 16:08:09 -0700 Subject: [PATCH 4317/9938] soc: brcmstb: Unmap sun_top_ctrl_base on errors Do not leak a ioremap()'d cookie around, unmaping it in case of errors Fixes: cef4bafcea2c ("soc: brcmstb: add SoC driver to brcmstb") Signed-off-by: Florian Fainelli Signed-off-by: Arnd Bergmann --- drivers/soc/brcmstb/common.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c index daf86acf9d01..94e7335553f4 100644 --- a/drivers/soc/brcmstb/common.c +++ b/drivers/soc/brcmstb/common.c @@ -51,6 +51,7 @@ static int __init brcmstb_soc_device_init(void) struct soc_device *soc_dev; struct device_node *sun_top_ctrl; void __iomem *sun_top_ctrl_base; + int ret = 0; sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); if (!sun_top_ctrl) @@ -64,8 +65,10 @@ static int __init brcmstb_soc_device_init(void) product_id = readl(sun_top_ctrl_base + 0x4); soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); - if (!soc_dev_attr) - return -ENOMEM; + if (!soc_dev_attr) { + ret = -ENOMEM; + goto out; + } soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x", family_id >> 28 ? @@ -83,9 +86,14 @@ static int __init brcmstb_soc_device_init(void) kfree(soc_dev_attr->soc_id); kfree(soc_dev_attr->revision); kfree(soc_dev_attr); - return -ENODEV; + ret = -ENODEV; + goto out; } return 0; + +out: + iounmap(sun_top_ctrl_base); + return ret; } arch_initcall(brcmstb_soc_device_init); -- GitLab From c5f9d6b1379a4584b47dd80271ab3a6883f979a9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Apr 2016 01:01:40 +0200 Subject: [PATCH 4318/9938] physmap_of: ensure versatile code is reachable With the newly added physmap_of_versatile code, we get a build error when physmap_of is in a module, because of_flash_probe_versatile is not exported: ERROR: "of_flash_probe_versatile" [drivers/mtd/maps/physmap_of.ko] undefined! This adds the export, and changes the Makefile so that the code is also put into a loadable module rather than built-in when physmap_of itself is a module. Signed-off-by: Arnd Bergmann --- drivers/mtd/maps/Makefile | 4 +++- drivers/mtd/maps/physmap_of_versatile.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 188873a72f1d..644f7d36d35d 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -18,7 +18,9 @@ obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o obj-$(CONFIG_MTD_PHYSMAP) += physmap.o obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o -obj-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o +ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE +obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of_versatile.o +endif obj-$(CONFIG_MTD_PISMO) += pismo.o obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o diff --git a/drivers/mtd/maps/physmap_of_versatile.c b/drivers/mtd/maps/physmap_of_versatile.c index fa40539e0d7f..0f39b2a015f4 100644 --- a/drivers/mtd/maps/physmap_of_versatile.c +++ b/drivers/mtd/maps/physmap_of_versatile.c @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ +#include #include #include #include @@ -251,3 +252,4 @@ int of_flash_probe_versatile(struct platform_device *pdev, return 0; } +EXPORT_SYMBOL_GPL(of_flash_probe_versatile); -- GitLab From 8daef508b0a144970e5cbc587525c351663fec63 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 23 Apr 2016 14:45:54 +0100 Subject: [PATCH 4319/9938] perf tests: Replace assignment with comparison on assert check The current assert check is checking an assignment, which will always be true. Instead, the assert should be checking if scale is equal to 0.122 Signed-off-by: Colin Ian King Reviewed-by: Masami Hiramatsu Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1461419154-16918-1-git-send-email-colin.king@canonical.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/event_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index 012eab5d1df1..63ecf21750eb 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -30,7 +30,7 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused, TEST_ASSERT_VAL("wrong id", ev->id == 123); TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE); - TEST_ASSERT_VAL("wrong scale", ev_data->scale = 0.123); + TEST_ASSERT_VAL("wrong scale", ev_data->scale == 0.123); return 0; } -- GitLab From 73b1794e252b0476cc6e46461c7612cbaa88be45 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Wed, 20 Apr 2016 20:14:07 -0700 Subject: [PATCH 4320/9938] perf bench futex: Simplify wrapper for LOCK_PI Given that the 'val' parameter is ignored for FUTEX_LOCK_PI, get rid of the bogus deadlock detection flag in the wrapper code and avoid the extra argument, making it resemble its unlock counterpart. And if nothing else, we already only pass 0 anyway. Signed-off-by: Davidlohr Bueso Cc: Davidlohr Bueso Link: http://lkml.kernel.org/r/1461208447-29328-1-git-send-email-dave@stgolabs.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/futex-lock-pi.c | 2 +- tools/perf/bench/futex.h | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c index 6a18ce21f865..6952db65508a 100644 --- a/tools/perf/bench/futex-lock-pi.c +++ b/tools/perf/bench/futex-lock-pi.c @@ -83,7 +83,7 @@ static void *workerfn(void *arg) do { int ret; again: - ret = futex_lock_pi(w->futex, NULL, 0, futex_flag); + ret = futex_lock_pi(w->futex, NULL, futex_flag); if (ret) { /* handle lock acquisition */ if (!silent) diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h index d44de9f44281..b2e06d1190d0 100644 --- a/tools/perf/bench/futex.h +++ b/tools/perf/bench/futex.h @@ -57,13 +57,11 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags) /** * futex_lock_pi() - block on uaddr as a PI mutex - * @detect: whether (1) or not (0) to perform deadlock detection */ static inline int -futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int detect, - int opflags) +futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags) { - return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags); + return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags); } /** -- GitLab From c0664893050cc6b2d8b02d3e035f82fbfd0cd4cf Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 24 Apr 2016 19:56:43 +0100 Subject: [PATCH 4321/9938] perf intel-pt: Fix off-by-one comparison on maximum code The check for the maximum code is off-by-one; the current comparison of a code that is INTEL_PT_ERR_MAX will cause the strlcpy to perform an out of bounds array access on the intel_pt_err_msgs array. Fix this with a >= comparison. Signed-off-by: Colin Ian King Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1461524203-10224-1-git-send-email-colin.king@canonical.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 9409d014b46c..9c8f15da86ce 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -356,7 +356,7 @@ static const char *intel_pt_err_msgs[] = { int intel_pt__strerror(int code, char *buf, size_t buflen) { - if (code < 1 || code > INTEL_PT_ERR_MAX) + if (code < 1 || code >= INTEL_PT_ERR_MAX) code = INTEL_PT_ERR_UNK; strlcpy(buf, intel_pt_err_msgs[code], buflen); return 0; -- GitLab From 09623d79466e996f5dc2753e16f04fda6f078041 Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Sun, 24 Apr 2016 23:28:09 -0700 Subject: [PATCH 4322/9938] perf hists: Clear dummy entry accumulated period The accumulated period for dummy entry should also be 0. Otherwise, the total overhead could be overcounted. $ perf record -e '{LLC-load-misses,cpu/instructions/}' --call-graph=lbr ./tchain $ perf report --stdio # To display the perf.data header info, please use --header/--header-only options. # # Total Lost Samples: 0 # # Samples: 21K of event 'anon group { LLC-load-misses, cpu/instructions/ }' # Event count (approx.): 16313667937 # # Children Self Command Shared Object Symbol # ................ ................ ........... ................ ............................ # 4769.98% 0.01% 0.00% 0.01% tchain_edit [kernel.vmlinux] [k] update_fast_timekeeper 4356.18% 0.01% 0.00% 0.01% tchain_edit [kernel.vmlinux] [k] trigger_load_balance 3181.12% 0.01% 0.00% 0.01% tchain_edit [kernel.vmlinux] [k] irq_work_tick 1592.37% 0.00% 0.00% 0.00% tchain_edit [kernel.vmlinux] [k] cpu_needs_another_gp Signed-off-by: Kan Liang Acked-by: Jiri Olsa Cc: Andi Kleen Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1461565689-5862-1-git-send-email-kan.liang@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 991a351a8a41..0f33d7e698c4 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2062,6 +2062,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, if (he) { memset(&he->stat, 0, sizeof(he->stat)); he->hists = hists; + if (symbol_conf.cumulate_callchain) + memset(he->stat_acc, 0, sizeof(he->stat)); rb_link_node(&he->rb_node_in, parent, p); rb_insert_color(&he->rb_node_in, root); hists__inc_stats(hists, he); -- GitLab From 1c8c77f52d1037c61468539e1d68c44f9e710536 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:40 +0200 Subject: [PATCH 4323/9938] soc: renesas: rcar-sysc: Enable Clock Domain for I/O devices On R-Car H3, some power areas (e.g. A3VP) contain I/O devices, which are also part of the CPG/MSSR Clock Domain. On all R-Car SoCs, devices in the "always-on" PM Domain are part of the Clock Domain served by the CPG/MSSR or CPG/MSTP driver. Hook up the CPG/MSTP or CPG/MSSR Clock Domain attach/detach callbacks to enable power management using module clocks. Which callback to hook up depends on the presence of device nodes compatible with "renesas,cpg-mstp-clocks". This clears the path for a future migration from the CPG/MSTP to the CPG/MSSR driver on R-Car H1 and Gen2. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Ulf Hansson Signed-off-by: Simon Horman --- drivers/soc/renesas/rcar-sysc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 4e760d63f2ab..0d49a25de740 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -9,6 +9,7 @@ * for more details. */ +#include #include #include #include @@ -217,6 +218,8 @@ static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd) return rcar_sysc_power_up(&pd->ch); } +static bool has_cpg_mstp; + static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) { struct generic_pm_domain *genpd = &pd->genpd; @@ -248,6 +251,18 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) gov = &pm_domain_always_on_gov; } + if (!(pd->flags & (PD_CPU | PD_SCU))) { + /* Enable Clock Domain for I/O devices */ + genpd->flags = GENPD_FLAG_PM_CLK; + if (has_cpg_mstp) { + genpd->attach_dev = cpg_mstp_attach_dev; + genpd->detach_dev = cpg_mstp_detach_dev; + } else { + genpd->attach_dev = cpg_mssr_attach_dev; + genpd->detach_dev = cpg_mssr_detach_dev; + } + } + genpd->power_off = rcar_sysc_pd_power_off; genpd->power_on = rcar_sysc_pd_power_on; @@ -294,6 +309,9 @@ static int __init rcar_sysc_pd_init(void) info = match->data; + has_cpg_mstp = of_find_compatible_node(NULL, NULL, + "renesas,cpg-mstp-clocks"); + base = of_iomap(np, 0); if (!base) { pr_warn("%s: Cannot map regs\n", np->full_name); -- GitLab From 9b83ea17b0d9b5461ee46a2f5a668e6b10743f1a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:41 +0200 Subject: [PATCH 4324/9938] soc: renesas: rcar-sysc: Add support for R-Car H1 power areas Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/Makefile | 2 +- drivers/soc/renesas/r8a7779-sysc.c | 34 ++++++++++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 +++ drivers/soc/renesas/rcar-sysc.h | 1 + 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/renesas/r8a7779-sysc.c diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 2b64f6c94681..b8aa9db4fdd9 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -1,4 +1,4 @@ -obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o diff --git a/drivers/soc/renesas/r8a7779-sysc.c b/drivers/soc/renesas/r8a7779-sysc.c new file mode 100644 index 000000000000..9e8e6b7faa04 --- /dev/null +++ b/drivers/soc/renesas/r8a7779-sysc.c @@ -0,0 +1,34 @@ +/* + * Renesas R-Car H1 System Controller + * + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a7779_areas[] __initconst = { + { "always-on", 0, 0, R8A7779_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "arm1", 0x40, 1, R8A7779_PD_ARM1, R8A7779_PD_ALWAYS_ON, + PD_CPU_CR }, + { "arm2", 0x40, 2, R8A7779_PD_ARM2, R8A7779_PD_ALWAYS_ON, + PD_CPU_CR }, + { "arm3", 0x40, 3, R8A7779_PD_ARM3, R8A7779_PD_ALWAYS_ON, + PD_CPU_CR }, + { "sgx", 0xc0, 0, R8A7779_PD_SGX, R8A7779_PD_ALWAYS_ON }, + { "vdp", 0x100, 0, R8A7779_PD_VDP, R8A7779_PD_ALWAYS_ON }, + { "imp", 0x140, 0, R8A7779_PD_IMP, R8A7779_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7779_sysc_info __initconst = { + .areas = r8a7779_areas, + .num_areas = ARRAY_SIZE(r8a7779_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 0d49a25de740..858ad23ae03a 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -284,6 +284,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) } static const struct of_device_id rcar_sysc_matches[] = { +#ifdef CONFIG_ARCH_R8A7779 + { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, +#endif { /* sentinel */ } }; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 7bb48b4f7334..7cf58b9cd544 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -50,4 +50,5 @@ struct rcar_sysc_info { unsigned int num_areas; }; +extern const struct rcar_sysc_info r8a7779_sysc_info; #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From ad7c9dbc25d19c2fbf4414a8cb4f02f7933611d6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:42 +0200 Subject: [PATCH 4325/9938] soc: renesas: rcar-sysc: Add support for R-Car H2 power areas Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/Makefile | 2 +- drivers/soc/renesas/r8a7790-sysc.c | 48 ++++++++++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 ++ drivers/soc/renesas/rcar-sysc.h | 1 + 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/renesas/r8a7790-sysc.c diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index b8aa9db4fdd9..6588be3c6776 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o -obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o diff --git a/drivers/soc/renesas/r8a7790-sysc.c b/drivers/soc/renesas/r8a7790-sysc.c new file mode 100644 index 000000000000..7a567ad0ff73 --- /dev/null +++ b/drivers/soc/renesas/r8a7790-sysc.c @@ -0,0 +1,48 @@ +/* + * Renesas R-Car H2 System Controller + * + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a7790_areas[] __initconst = { + { "always-on", 0, 0, R8A7790_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca15-scu", 0x180, 0, R8A7790_PD_CA15_SCU, R8A7790_PD_ALWAYS_ON, + PD_SCU }, + { "ca15-cpu0", 0x40, 0, R8A7790_PD_CA15_CPU0, R8A7790_PD_CA15_SCU, + PD_CPU_NOCR }, + { "ca15-cpu1", 0x40, 1, R8A7790_PD_CA15_CPU1, R8A7790_PD_CA15_SCU, + PD_CPU_NOCR }, + { "ca15-cpu2", 0x40, 2, R8A7790_PD_CA15_CPU2, R8A7790_PD_CA15_SCU, + PD_CPU_NOCR }, + { "ca15-cpu3", 0x40, 3, R8A7790_PD_CA15_CPU3, R8A7790_PD_CA15_SCU, + PD_CPU_NOCR }, + { "ca7-scu", 0x100, 0, R8A7790_PD_CA7_SCU, R8A7790_PD_ALWAYS_ON, + PD_SCU }, + { "ca7-cpu0", 0x1c0, 0, R8A7790_PD_CA7_CPU0, R8A7790_PD_CA7_SCU, + PD_CPU_NOCR }, + { "ca7-cpu1", 0x1c0, 1, R8A7790_PD_CA7_CPU1, R8A7790_PD_CA7_SCU, + PD_CPU_NOCR }, + { "ca7-cpu2", 0x1c0, 2, R8A7790_PD_CA7_CPU2, R8A7790_PD_CA7_SCU, + PD_CPU_NOCR }, + { "ca7-cpu3", 0x1c0, 3, R8A7790_PD_CA7_CPU3, R8A7790_PD_CA7_SCU, + PD_CPU_NOCR }, + { "sh-4a", 0x80, 0, R8A7790_PD_SH_4A, R8A7790_PD_ALWAYS_ON }, + { "rgx", 0xc0, 0, R8A7790_PD_RGX, R8A7790_PD_ALWAYS_ON }, + { "imp", 0x140, 0, R8A7790_PD_IMP, R8A7790_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7790_sysc_info __initconst = { + .areas = r8a7790_areas, + .num_areas = ARRAY_SIZE(r8a7790_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 858ad23ae03a..07ea25925e85 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -286,6 +286,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) static const struct of_device_id rcar_sysc_matches[] = { #ifdef CONFIG_ARCH_R8A7779 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, +#endif +#ifdef CONFIG_ARCH_R8A7790 + { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info }, #endif { /* sentinel */ } }; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 7cf58b9cd544..33c8f2d00a01 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -51,4 +51,5 @@ struct rcar_sysc_info { }; extern const struct rcar_sysc_info r8a7779_sysc_info; +extern const struct rcar_sysc_info r8a7790_sysc_info; #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From c5fbb3c08897c8941852e9096f8507785d8a18f2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:43 +0200 Subject: [PATCH 4326/9938] soc: renesas: rcar-sysc: Add support for R-Car M2-W power areas Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/Makefile | 2 +- drivers/soc/renesas/r8a7791-sysc.c | 33 ++++++++++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 +++ drivers/soc/renesas/rcar-sysc.h | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/renesas/r8a7791-sysc.c diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 6588be3c6776..96463c05ee59 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o -obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o diff --git a/drivers/soc/renesas/r8a7791-sysc.c b/drivers/soc/renesas/r8a7791-sysc.c new file mode 100644 index 000000000000..03b9f41a34e6 --- /dev/null +++ b/drivers/soc/renesas/r8a7791-sysc.c @@ -0,0 +1,33 @@ +/* + * Renesas R-Car M2-W/N System Controller + * + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a7791_areas[] __initconst = { + { "always-on", 0, 0, R8A7791_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca15-scu", 0x180, 0, R8A7791_PD_CA15_SCU, R8A7791_PD_ALWAYS_ON, + PD_SCU }, + { "ca15-cpu0", 0x40, 0, R8A7791_PD_CA15_CPU0, R8A7791_PD_CA15_SCU, + PD_CPU_NOCR }, + { "ca15-cpu1", 0x40, 1, R8A7791_PD_CA15_CPU1, R8A7791_PD_CA15_SCU, + PD_CPU_NOCR }, + { "sh-4a", 0x80, 0, R8A7791_PD_SH_4A, R8A7791_PD_ALWAYS_ON }, + { "sgx", 0xc0, 0, R8A7791_PD_SGX, R8A7791_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7791_sysc_info __initconst = { + .areas = r8a7791_areas, + .num_areas = ARRAY_SIZE(r8a7791_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 07ea25925e85..5b70b93a2aa7 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -289,6 +289,9 @@ static const struct of_device_id rcar_sysc_matches[] = { #endif #ifdef CONFIG_ARCH_R8A7790 { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info }, +#endif +#ifdef CONFIG_ARCH_R8A7791 + { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info }, #endif { /* sentinel */ } }; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 33c8f2d00a01..d58b39400e79 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -52,4 +52,5 @@ struct rcar_sysc_info { extern const struct rcar_sysc_info r8a7779_sysc_info; extern const struct rcar_sysc_info r8a7790_sysc_info; +extern const struct rcar_sysc_info r8a7791_sysc_info; #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From a247eb93ef73b56aab68c47608245e2b4a713585 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:44 +0200 Subject: [PATCH 4327/9938] soc: renesas: rcar-sysc: Add support for R-Car M2-N power areas R-Car M2-N is identical to R-Car M2-W w.r.t. power domains, so reuse the definitions from the latter. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/Makefile | 3 ++- drivers/soc/renesas/rcar-sysc.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 96463c05ee59..c6c4ce7ef8a1 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o -obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o +# R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. +obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 5b70b93a2aa7..d8eaf8b2ee20 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -292,6 +292,10 @@ static const struct of_device_id rcar_sysc_matches[] = { #endif #ifdef CONFIG_ARCH_R8A7791 { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info }, +#endif +#ifdef CONFIG_ARCH_R8A7793 + /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */ + { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info }, #endif { /* sentinel */ } }; -- GitLab From 9af1dbcc3028e1de8cac2d7e32345965353edde0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:45 +0200 Subject: [PATCH 4328/9938] soc: renesas: rcar-sysc: Add support for R-Car E2 power areas Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/Makefile | 2 +- drivers/soc/renesas/r8a7794-sysc.c | 33 ++++++++++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 +++ drivers/soc/renesas/rcar-sysc.h | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/renesas/r8a7794-sysc.c diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index c6c4ce7ef8a1..b328205fef36 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o # R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o -obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o +obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o diff --git a/drivers/soc/renesas/r8a7794-sysc.c b/drivers/soc/renesas/r8a7794-sysc.c new file mode 100644 index 000000000000..c4da2941e06c --- /dev/null +++ b/drivers/soc/renesas/r8a7794-sysc.c @@ -0,0 +1,33 @@ +/* + * Renesas R-Car E2 System Controller + * + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a7794_areas[] __initconst = { + { "always-on", 0, 0, R8A7794_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca7-scu", 0x100, 0, R8A7794_PD_CA7_SCU, R8A7794_PD_ALWAYS_ON, + PD_SCU }, + { "ca7-cpu0", 0x1c0, 0, R8A7794_PD_CA7_CPU0, R8A7794_PD_CA7_SCU, + PD_CPU_NOCR }, + { "ca7-cpu1", 0x1c0, 1, R8A7794_PD_CA7_CPU1, R8A7794_PD_CA7_SCU, + PD_CPU_NOCR }, + { "sh-4a", 0x80, 0, R8A7794_PD_SH_4A, R8A7794_PD_ALWAYS_ON }, + { "sgx", 0xc0, 0, R8A7794_PD_SGX, R8A7794_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7794_sysc_info __initconst = { + .areas = r8a7794_areas, + .num_areas = ARRAY_SIZE(r8a7794_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index d8eaf8b2ee20..e2cd99027303 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -296,6 +296,9 @@ static const struct of_device_id rcar_sysc_matches[] = { #ifdef CONFIG_ARCH_R8A7793 /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */ { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info }, +#endif +#ifdef CONFIG_ARCH_R8A7794 + { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info }, #endif { /* sentinel */ } }; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index d58b39400e79..d64258cfaa20 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -53,4 +53,5 @@ struct rcar_sysc_info { extern const struct rcar_sysc_info r8a7779_sysc_info; extern const struct rcar_sysc_info r8a7790_sysc_info; extern const struct rcar_sysc_info r8a7791_sysc_info; +extern const struct rcar_sysc_info r8a7794_sysc_info; #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From 23f1e2ecdecee9f2ec45de0a468b82bb1f7f3ca2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 14:02:46 +0200 Subject: [PATCH 4329/9938] soc: renesas: rcar-sysc: Add support for R-Car H3 power areas Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/r8a7795-sysc.c | 56 ++++++++++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 ++ drivers/soc/renesas/rcar-sysc.h | 1 + 4 files changed, 61 insertions(+) create mode 100644 drivers/soc/renesas/r8a7795-sysc.c diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index b328205fef36..151fcd3f025b 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o # R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o +obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o diff --git a/drivers/soc/renesas/r8a7795-sysc.c b/drivers/soc/renesas/r8a7795-sysc.c new file mode 100644 index 000000000000..5e7537c96f7b --- /dev/null +++ b/drivers/soc/renesas/r8a7795-sysc.c @@ -0,0 +1,56 @@ +/* + * Renesas R-Car H3 System Controller + * + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a7795_areas[] __initconst = { + { "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON, + PD_SCU }, + { "ca57-cpu0", 0x80, 0, R8A7795_PD_CA57_CPU0, R8A7795_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca57-cpu1", 0x80, 1, R8A7795_PD_CA57_CPU1, R8A7795_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca57-cpu2", 0x80, 2, R8A7795_PD_CA57_CPU2, R8A7795_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca57-cpu3", 0x80, 3, R8A7795_PD_CA57_CPU3, R8A7795_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca53-scu", 0x140, 0, R8A7795_PD_CA53_SCU, R8A7795_PD_ALWAYS_ON, + PD_SCU }, + { "ca53-cpu0", 0x200, 0, R8A7795_PD_CA53_CPU0, R8A7795_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu1", 0x200, 1, R8A7795_PD_CA53_CPU1, R8A7795_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu2", 0x200, 2, R8A7795_PD_CA53_CPU2, R8A7795_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu3", 0x200, 3, R8A7795_PD_CA53_CPU3, R8A7795_PD_CA53_SCU, + PD_CPU_NOCR }, + { "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON }, + { "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON }, + { "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON }, + { "a2vc0", 0x3c0, 0, R8A7795_PD_A2VC0, R8A7795_PD_A3VC }, + { "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC }, + { "3dg-a", 0x100, 0, R8A7795_PD_3DG_A, R8A7795_PD_ALWAYS_ON }, + { "3dg-b", 0x100, 1, R8A7795_PD_3DG_B, R8A7795_PD_3DG_A }, + { "3dg-c", 0x100, 2, R8A7795_PD_3DG_C, R8A7795_PD_3DG_B }, + { "3dg-d", 0x100, 3, R8A7795_PD_3DG_D, R8A7795_PD_3DG_C }, + { "3dg-e", 0x100, 4, R8A7795_PD_3DG_E, R8A7795_PD_3DG_D }, + { "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7795_sysc_info __initconst = { + .areas = r8a7795_areas, + .num_areas = ARRAY_SIZE(r8a7795_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index e2cd99027303..79dbc770895f 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -299,6 +299,9 @@ static const struct of_device_id rcar_sysc_matches[] = { #endif #ifdef CONFIG_ARCH_R8A7794 { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info }, +#endif +#ifdef CONFIG_ARCH_R8A7795 + { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info }, #endif { /* sentinel */ } }; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index d64258cfaa20..5e766174c2f4 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -54,4 +54,5 @@ extern const struct rcar_sysc_info r8a7779_sysc_info; extern const struct rcar_sysc_info r8a7790_sysc_info; extern const struct rcar_sysc_info r8a7791_sysc_info; extern const struct rcar_sysc_info r8a7794_sysc_info; +extern const struct rcar_sysc_info r8a7795_sysc_info; #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ -- GitLab From 2b9cf18982b0ba7317f258663560e181594a9bf8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Apr 2016 02:13:30 +0200 Subject: [PATCH 4330/9938] drivers: firmware: psci: make two helper functions inline The previous patch marked these two as 'static' which showed that they are sometimes unused: drivers/firmware/psci.c:103:13: error: 'psci_power_state_is_valid' defined but not used [-Werror=unused-function] static bool psci_power_state_is_valid(u32 state) drivers/firmware/psci.c:94:13: error: 'psci_power_state_loses_context' defined but not used [-Werror=unused-function] static bool psci_power_state_loses_context(u32 state) This also marks the functions 'inline', which has the main effect of silently ignoring them when they are unused. The compiler will typically inline small static functions anyway, so this seems more appropriate than using __maybe_unused, which would have the same result otherwise. Signed-off-by: Arnd Bergmann Fixes: 21e8868 ("drivers: firmware: psci: make two helper functions static") --- drivers/firmware/psci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index 04f2ac54e5ab..89fcbddefb0a 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -91,7 +91,7 @@ static inline bool psci_has_ext_power_state(void) PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK; } -static bool psci_power_state_loses_context(u32 state) +static inline bool psci_power_state_loses_context(u32 state) { const u32 mask = psci_has_ext_power_state() ? PSCI_1_0_EXT_POWER_STATE_TYPE_MASK : @@ -100,7 +100,7 @@ static bool psci_power_state_loses_context(u32 state) return state & mask; } -static bool psci_power_state_is_valid(u32 state) +static inline bool psci_power_state_is_valid(u32 state) { const u32 valid_mask = psci_has_ext_power_state() ? PSCI_1_0_EXT_POWER_STATE_MASK : -- GitLab From e93e59ce5b85e6c2b444f09fd1f707274ec066dc Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 21 Apr 2016 10:56:30 +0200 Subject: [PATCH 4331/9938] cpuidle: Replace ktime_get() with local_clock() The ktime_get() can have a non negligeable overhead, use local_clock() instead. In order to test the difference between ktime_get() and local_clock(), a quick hack has been added to trigger, via debugfs, 10000 times a call to ktime_get() and local_clock() and measure the elapsed time. Then the average value, the min and max is computed for each call. From userspace, the test above was called 100 times every 2 seconds. So, ktime_get() and local_clock() have been called 1000000 times in total. The results are: ktime_get(): ============ * average: 101 ns (stddev: 27.4) * maximum: 38313 ns * minimum: 65 ns local_clock(): ============== * average: 60 ns (stddev: 9.8) * maximum: 13487 ns * minimum: 46 ns The local_clock() is faster and more stable. Even if it is a drop in the ocean, changing the ktime_get() by the local_clock() allows to save 80ns at idle time (entry + exit). And in some circumstances, especially when there are several CPUs racing for the clock access, we save tens of microseconds. The idle duration resulting from a diff is converted from nanosec to microsec. This could be done with integer division (div 1000) - which is an expensive operation or by 10 bits shifting (div 1024) - which is fast but unprecise. The following table gives some results at the limits. ------------------------------------------ | nsec | div(1000) | div(1024) | ------------------------------------------ | 1e3 | 1 usec | 976 nsec | ------------------------------------------ | 1e6 | 1000 usec | 976 usec | ------------------------------------------ | 1e9 | 1000000 usec | 976562 usec | ------------------------------------------ There is a linear deviation of 2.34%. This loss of precision is acceptable in the context of the resulting diff which is used for statistics. These ones are processed to guess estimate an approximation of the duration of the next idle period which ends up into an idle state selection. The selection criteria takes into account the next duration based on large intervals, represented by the idle state's target residency. The 2^10 division is enough because the approximation regarding the 1e3 division is lost in all the approximations done for the next idle duration computation. Signed-off-by: Daniel Lezcano Acked-by: Peter Zijlstra (Intel) [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index c2dd99ab1648..2b8e6ce62e81 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -173,7 +173,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, struct cpuidle_state *target_state = &drv->states[index]; bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP); - ktime_t time_start, time_end; + u64 time_start, time_end; s64 diff; /* @@ -195,13 +195,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, sched_idle_set_state(target_state); trace_cpu_idle_rcuidle(index, dev->cpu); - time_start = ktime_get(); + time_start = local_clock(); stop_critical_timings(); entered_state = target_state->enter(dev, drv, index); start_critical_timings(); - time_end = ktime_get(); + time_end = local_clock(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); /* The cpu is no longer idle or about to enter idle. */ @@ -217,7 +217,11 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, if (!cpuidle_state_is_coupled(drv, entered_state)) local_irq_enable(); - diff = ktime_to_us(ktime_sub(time_end, time_start)); + /* + * local_clock() returns the time in nanosecond, let's shift + * by 10 (divide by 1024) to have microsecond based time. + */ + diff = (time_end - time_start) >> 10; if (diff > INT_MAX) diff = INT_MAX; -- GitLab From 49bdedb36271fe6259dd251bb63c5879fa7834e1 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Mon, 25 Apr 2016 19:12:38 -0600 Subject: [PATCH 4332/9938] skd: remove broken discard support Simply creating a file system on an skd device, followed by mount and fstrim will result in errors in the logs and then a BUG(). Let's remove discard support from that driver. As far as I can tell, it hasn't worked right since it was merged. This patch also has a side-effect of cleaning up an unintentional shadowed declaration inside of skd_end_request. I tested to ensure that I can still do I/O to the device using xfstests ./check -g quick. I didn't do anything more extensive than that, though. Signed-off-by: Jeff Moyer Signed-off-by: Jens Axboe --- drivers/block/skd_main.c | 59 +--------------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 41aaae30c005..910e065918af 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -133,7 +133,6 @@ MODULE_VERSION(DRV_VERSION "-" DRV_BUILD_ID); #define SKD_TIMER_MINUTES(minutes) ((minutes) * (60)) #define INQ_STD_NBYTES 36 -#define SKD_DISCARD_CDB_LENGTH 24 enum skd_drvr_state { SKD_DRVR_STATE_LOAD, @@ -212,7 +211,6 @@ struct skd_request_context { struct request *req; u8 flush_cmd; - u8 discard_page; u32 timeout_stamp; u8 sg_data_dir; @@ -230,7 +228,6 @@ struct skd_request_context { }; #define SKD_DATA_DIR_HOST_TO_CARD 1 #define SKD_DATA_DIR_CARD_TO_HOST 2 -#define SKD_DATA_DIR_NONE 3 /* especially for DISCARD requests. */ struct skd_special_context { struct skd_request_context req; @@ -540,31 +537,6 @@ skd_prep_zerosize_flush_cdb(struct skd_scsi_request *scsi_req, scsi_req->cdb[9] = 0; } -static void -skd_prep_discard_cdb(struct skd_scsi_request *scsi_req, - struct skd_request_context *skreq, - struct page *page, - u32 lba, u32 count) -{ - char *buf; - unsigned long len; - struct request *req; - - buf = page_address(page); - len = SKD_DISCARD_CDB_LENGTH; - - scsi_req->cdb[0] = UNMAP; - scsi_req->cdb[8] = len; - - put_unaligned_be16(6 + 16, &buf[0]); - put_unaligned_be16(16, &buf[2]); - put_unaligned_be64(lba, &buf[8]); - put_unaligned_be32(count, &buf[16]); - - req = skreq->req; - blk_add_request_payload(req, page, 0, len); -} - static void skd_request_fn_not_online(struct request_queue *q); static void skd_request_fn(struct request_queue *q) @@ -575,7 +547,6 @@ static void skd_request_fn(struct request_queue *q) struct skd_request_context *skreq; struct request *req = NULL; struct skd_scsi_request *scsi_req; - struct page *page; unsigned long io_flags; int error; u32 lba; @@ -669,7 +640,6 @@ static void skd_request_fn(struct request_queue *q) skreq->flush_cmd = 0; skreq->n_sg = 0; skreq->sg_byte_count = 0; - skreq->discard_page = 0; /* * OK to now dequeue request from q. @@ -735,18 +705,7 @@ static void skd_request_fn(struct request_queue *q) else skreq->sg_data_dir = SKD_DATA_DIR_HOST_TO_CARD; - if (io_flags & REQ_DISCARD) { - page = alloc_page(GFP_ATOMIC | __GFP_ZERO); - if (!page) { - pr_err("request_fn:Page allocation failed.\n"); - skd_end_request(skdev, skreq, -ENOMEM); - break; - } - skreq->discard_page = 1; - req->completion_data = page; - skd_prep_discard_cdb(scsi_req, skreq, page, lba, count); - - } else if (flush == SKD_FLUSH_ZERO_SIZE_FIRST) { + if (flush == SKD_FLUSH_ZERO_SIZE_FIRST) { skd_prep_zerosize_flush_cdb(scsi_req, skreq); SKD_ASSERT(skreq->flush_cmd == 1); @@ -851,16 +810,6 @@ static void skd_request_fn(struct request_queue *q) static void skd_end_request(struct skd_device *skdev, struct skd_request_context *skreq, int error) { - struct request *req = skreq->req; - unsigned int io_flags = req->cmd_flags; - - if ((io_flags & REQ_DISCARD) && - (skreq->discard_page == 1)) { - pr_debug("%s:%s:%d, free the page!", - skdev->name, __func__, __LINE__); - __free_page(req->completion_data); - } - if (unlikely(error)) { struct request *req = skreq->req; char *cmd = (rq_data_dir(req) == READ) ? "read" : "write"; @@ -4419,12 +4368,6 @@ static int skd_cons_disk(struct skd_device *skdev) /* set sysfs ptimal_io_size to 8K */ blk_queue_io_opt(q, 8192); - /* DISCARD Flag initialization. */ - q->limits.discard_granularity = 8192; - q->limits.discard_alignment = 0; - blk_queue_max_discard_sectors(q, UINT_MAX >> 9); - q->limits.discard_zeroes_data = 1; - queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q); -- GitLab From 1fcbcc333f1fae6e11cc0839a6e72bc1a3e830bf Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 25 Apr 2016 16:50:14 -0700 Subject: [PATCH 4333/9938] block: copy NOMERGE flag from bio to request bio might have NOMERGE flag set, for example blk_queue_split sets it. When we initiate request, copy this flag too. Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe --- include/linux/blk_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 86a38ea1823f..77e5d81f07aa 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -208,7 +208,7 @@ enum rq_flag_bits { #define REQ_COMMON_MASK \ (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \ REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \ - REQ_SECURE | REQ_INTEGRITY) + REQ_SECURE | REQ_INTEGRITY | REQ_NOMERGE) #define REQ_CLONE_MASK REQ_COMMON_MASK #define BIO_NO_ADVANCE_ITER_MASK (REQ_DISCARD|REQ_WRITE_SAME) -- GitLab From b8ac0cc78b56e798851f1435bc673761d3fb877e Mon Sep 17 00:00:00 2001 From: Joe Lawrence Date: Mon, 18 Apr 2016 10:50:12 -0400 Subject: [PATCH 4334/9938] mpt3sas - remove unused fw_event_work elements Firmware events are queued up using the fw_event_work's struct work, not its delayed_work member. The initial driver for SAS2 controllers had handled firmware reset using the rescan barrier and was later redesigned through "mpt2sas: [Resend] Host Reset code cleanup". The delayed_work variables are now unused and may provoke CONFIG_DEBUG_OBJECTS_TIMERS "assert_init not available" false warnings in _scsih_fw_event_cleanup_queue. Cleanup fw_event_work's unused entries, update its kerneldoc, and update _scsih_fw_event_cleanup_queue accordingly. Fixes: 146b16c8071f (mpt3sas: Refcount fw_events and fix unsafe list usage) Signed-off-by: Joe Lawrence Acked-by: Chaitra P B Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index e0e4920d0fa6..f2139e5604a3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -174,13 +174,13 @@ struct sense_info { * struct fw_event_work - firmware event struct * @list: link list framework * @work: work object (ioc->fault_reset_work_q) - * @cancel_pending_work: flag set during reset handling * @ioc: per adapter object * @device_handle: device handle * @VF_ID: virtual function id * @VP_ID: virtual port id * @ignore: flag meaning this event has been marked to ignore - * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h + * @event: firmware event MPI2_EVENT_XXX defined in mpi2_ioc.h + * @refcount: kref for this event * @event_data: reply event data payload follows * * This object stored on ioc->fw_event_list. @@ -188,8 +188,6 @@ struct sense_info { struct fw_event_work { struct list_head list; struct work_struct work; - u8 cancel_pending_work; - struct delayed_work delayed_work; struct MPT3SAS_ADAPTER *ioc; u16 device_handle; @@ -2804,12 +2802,12 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) /* * Wait on the fw_event to complete. If this returns 1, then * the event was never executed, and we need a put for the - * reference the delayed_work had on the fw_event. + * reference the work had on the fw_event. * * If it did execute, we wait for it to finish, and the put will * happen from _firmware_event_work() */ - if (cancel_delayed_work_sync(&fw_event->delayed_work)) + if (cancel_work_sync(&fw_event->work)) fw_event_work_put(fw_event); fw_event_work_put(fw_event); -- GitLab From aa105695732daa6604cb017ceb59a05ef34956bd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Apr 2016 12:37:44 +0300 Subject: [PATCH 4335/9938] hpsa: set the enclosure identifier to zero This has only called from show_sas_rphy_enclosure_identifier(). The caller expects that we set an identifier, otherwise it uses an uninitialized variable. [mkp: fixed typo] Signed-off-by: Dan Carpenter Acked-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5be944c8b71c..25aa219ea2d2 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -9602,6 +9602,7 @@ hpsa_sas_get_linkerrors(struct sas_phy *phy) static int hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) { + *identifier = 0; return 0; } -- GitLab From 9c8a76d5f00dbfd1da6ea242a9263a47133e4053 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Apr 2016 12:40:06 +0300 Subject: [PATCH 4336/9938] bnx2i: silence uninitialized variable warnings Presumably it isn't possible to have empty lists here, but my static checker doesn't know that and complains that "ep" can be used uninitialized. Signed-off-by: Dan Carpenter Acked-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 72894378ffcf..133901fd3e35 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -675,7 +675,7 @@ bnx2i_find_ep_in_ofld_list(struct bnx2i_hba *hba, u32 iscsi_cid) { struct list_head *list; struct list_head *tmp; - struct bnx2i_endpoint *ep; + struct bnx2i_endpoint *ep = NULL; read_lock_bh(&hba->ep_rdwr_lock); list_for_each_safe(list, tmp, &hba->ep_ofld_list) { @@ -703,7 +703,7 @@ bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid) { struct list_head *list; struct list_head *tmp; - struct bnx2i_endpoint *ep; + struct bnx2i_endpoint *ep = NULL; read_lock_bh(&hba->ep_rdwr_lock); list_for_each_safe(list, tmp, &hba->ep_destroy_list) { -- GitLab From 718924180a6a79afa558bd978c8a3436c39691ff Mon Sep 17 00:00:00 2001 From: Sebastian Herbszt Date: Sun, 17 Apr 2016 13:27:27 +0200 Subject: [PATCH 4337/9938] lpfc: remove incorrect lockdep assertion Remove incorrect lockdep assertion from lpfc_sli_hbqbuf_find() which acquires the hbalock itself. Fix the comment which resulted in this mistake. Fixes: 1c2ba475eb0e ("lpfc: Add lockdep assertions") Signed-off-by: Sebastian Herbszt Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 6b267b67f845..70edf21ae1b9 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2000,10 +2000,9 @@ lpfc_sli_hbqbuf_get(struct list_head *rb_list) * @phba: Pointer to HBA context object. * @tag: Tag of the hbq buffer. * - * This function is called with hbalock held. This function searches - * for the hbq buffer associated with the given tag in the hbq buffer - * list. If it finds the hbq buffer, it returns the hbq_buffer other wise - * it returns NULL. + * This function searches for the hbq buffer associated with the given tag in + * the hbq buffer list. If it finds the hbq buffer, it returns the hbq_buffer + * otherwise it returns NULL. **/ static struct hbq_dmabuf * lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) @@ -2012,8 +2011,6 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) struct hbq_dmabuf *hbq_buf; uint32_t hbqno; - lockdep_assert_held(&phba->hbalock); - hbqno = tag >> 16; if (hbqno >= LPFC_MAX_HBQS) return NULL; -- GitLab From 5e4fabb6eb058f6d473e22b6db3ef299acf00f1c Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Mon, 18 Apr 2016 08:47:18 +0300 Subject: [PATCH 4338/9938] st: clear ILI if Medium Error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some drives set the ILI flag together with MEDIUM ERROR sense code. Clear the ILI flag in this case so that the medium error will be handled. The problem was reported by Maurizio Lombardi. Signed-off-by: Kai Mäkisara Reviewed-by: Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/scsi/st.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index dbf1882cfbac..7af5226aa55b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1974,9 +1974,12 @@ static long read_tape(struct scsi_tape *STp, long count, transfer = (int)cmdstatp->uremainder64; else transfer = 0; - if (STp->block_size == 0 && - cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR) - transfer = bytes; + if (cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR) { + if (STp->block_size == 0) + transfer = bytes; + /* Some drives set ILI with MEDIUM ERROR */ + cmdstatp->flags &= ~SENSE_ILI; + } if (cmdstatp->flags & SENSE_ILI) { /* ILI */ if (STp->block_size == 0 && -- GitLab From 71d397581d52c24c9903d9729aae09828f956801 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 23 Apr 2016 12:20:07 +1000 Subject: [PATCH 4339/9938] MAINTAINERS: Update the file list for the NCR 5380 entry The file atari_NCR5380.c has been removed from the tree so remove it from the MAINTAINERS file as well. While we are here, add the file dtc3x80.txt as it is only relevant to the dtc driver. Signed-off-by: Finn Thain Signed-off-by: Martin K. Petersen --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 61a323a6b2cf..a87defae88c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7539,10 +7539,10 @@ M: Michael Schmitz L: linux-scsi@vger.kernel.org S: Maintained F: Documentation/scsi/g_NCR5380.txt +F: Documentation/scsi/dtc3x80.txt F: drivers/scsi/NCR5380.* F: drivers/scsi/arm/cumana_1.c F: drivers/scsi/arm/oak.c -F: drivers/scsi/atari_NCR5380.c F: drivers/scsi/atari_scsi.* F: drivers/scsi/dmx3191d.c F: drivers/scsi/dtc.* -- GitLab From 205506228b69be4efbb3809957a69420f26a8d9f Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Mon, 25 Apr 2016 22:40:12 -0400 Subject: [PATCH 4340/9938] tracing: Do not inherit event-fork option for instances As the event-fork option requires doing work when enabled and disabled, it can not be passed down to created instances. The instance must clear this flag when it is created, and must clear it when its removed. As more options may be created with this need, a macro ZEROED_TRACE_FLAGS is created that holds the flags that must not be inherited by the top level instance, and must be cleared on removal of instances. Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 988a35263fdd..5e3ad3481e4b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -253,6 +253,9 @@ unsigned long long ns2usecs(cycle_t nsec) #define TOP_LEVEL_TRACE_FLAGS (TRACE_ITER_PRINTK | \ TRACE_ITER_PRINTK_MSGONLY | TRACE_ITER_RECORD_CMD) +/* trace_flags that are default zero for instances */ +#define ZEROED_TRACE_FLAGS \ + TRACE_ITER_EVENT_FORK /* * The global_trace is the descriptor that holds the tracing @@ -6710,7 +6713,7 @@ static int instance_mkdir(const char *name) if (!alloc_cpumask_var(&tr->tracing_cpumask, GFP_KERNEL)) goto out_free_tr; - tr->trace_flags = global_trace.trace_flags; + tr->trace_flags = global_trace.trace_flags & ~ZEROED_TRACE_FLAGS; cpumask_copy(tr->tracing_cpumask, cpu_all_mask); @@ -6784,6 +6787,12 @@ static int instance_rmdir(const char *name) list_del(&tr->list); + /* Disable all the flags that were enabled coming in */ + for (i = 0; i < TRACE_FLAGS_MAX_SIZE; i++) { + if ((1 << i) & ZEROED_TRACE_FLAGS) + set_tracer_flag(tr, 1 << i, 0); + } + tracing_set_nop(tr); event_trace_del_tracer(tr); ftrace_destroy_function_files(tr); -- GitLab From 7532c98f3ac212ca1f19be7e628356247b616c74 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Mon, 18 Apr 2016 17:19:43 -0400 Subject: [PATCH 4341/9938] ARM: dts: imx6q-b850v3: Remove ldb panel Remove ldb panel entry for the following reasons: - The b850v3 has an onboard LVDS to DisplayPort converter (STDP4028). So we should not limit the monitors that can be connected by hardcoding the auo,b133htn01 1080p panel. - The default resolution on the LVDS interface needs to be WXGA or less. Otherwise when a 1080p monitor is connected to the HDMI port there is no output on both the LVDS and HDMI ports since a single IPU on i.MX6 can not handle two 1080p displays. With the panel entry removed from the devicetree, drm driver defaults the resolution on LVDS interface to XGA. Once in userspace, applications can set the desired resolution on LVDS interface over IPU2 CRTC. Signed-off-by: Akshay Bhat Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-b850v3.dts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-b850v3.dts b/arch/arm/boot/dts/imx6q-b850v3.dts index 984d00000403..dc4b06f27d38 100644 --- a/arch/arm/boot/dts/imx6q-b850v3.dts +++ b/arch/arm/boot/dts/imx6q-b850v3.dts @@ -51,18 +51,6 @@ chosen { stdout-path = &uart3; }; - - panel-lvds0 { - compatible = "auo,b133htn01"; - backlight = <&backlight_lvds>; - ddc-i2c-bus = <&mux2_i2c2>; - - port { - panel_in_lvds0: endpoint { - remote-endpoint = <&lvds0_out>; - }; - }; - }; }; &ldb { @@ -77,14 +65,6 @@ fsl,data-mapping = "spwg"; fsl,data-width = <24>; status = "okay"; - - port@4 { - reg = <4>; - - lvds0_out: endpoint { - remote-endpoint = <&panel_in_lvds0>; - }; - }; }; }; -- GitLab From b492b8744da9b205b9b303b111a138b16d56e712 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Mon, 18 Apr 2016 17:19:44 -0400 Subject: [PATCH 4342/9938] ARM: dts: imx6q-b850v3: Update display clock source The default monitor that ships with B850v3 requires a 65MHz pixel clock. 65MHz can not be achieved using PLL3 (480MHz/7=68.5MHz). Hence set the LDB_DIx clock source to PLL5. Since PLL5 is already in use by IPU1_DIx, set the clock source for IPU1_DIx to PLL2_PFD2 to allow simultaneous display on both LVDS and HDMI interface. Signed-off-by: Akshay Bhat Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-b850v3.dts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-b850v3.dts b/arch/arm/boot/dts/imx6q-b850v3.dts index dc4b06f27d38..167f7446722a 100644 --- a/arch/arm/boot/dts/imx6q-b850v3.dts +++ b/arch/arm/boot/dts/imx6q-b850v3.dts @@ -53,11 +53,18 @@ }; }; -&ldb { +&clks { assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, - <&clks IMX6QDL_CLK_LDB_DI1_SEL>; - assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>, - <&clks IMX6QDL_CLK_PLL3_USB_OTG>; + <&clks IMX6QDL_CLK_LDB_DI1_SEL>, + <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>, + <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>; + assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, + <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, + <&clks IMX6QDL_CLK_PLL2_PFD2_396M>, + <&clks IMX6QDL_CLK_PLL2_PFD2_396M>; +}; + +&ldb { fsl,dual-channel; status = "okay"; -- GitLab From 15ef03b8624724ed1b7e660e14d310fa54be393f Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Mon, 18 Apr 2016 17:19:45 -0400 Subject: [PATCH 4343/9938] ARM: dts: imx: b450/b650v3: Move ldb_di clk assignment Previously the LDB_DIx clocks could be specified in the ldb node. With the ERR009219 errata fix applied, the ldb_di clocks now needs to be specified in the clks node to ensure the clocks are setup early in the boot process. Signed-off-by: Akshay Bhat Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-b450v3.dts | 5 ++++- arch/arm/boot/dts/imx6q-b650v3.dts | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-b450v3.dts b/arch/arm/boot/dts/imx6q-b450v3.dts index 3101be5bafa7..f0a2be5268e3 100644 --- a/arch/arm/boot/dts/imx6q-b450v3.dts +++ b/arch/arm/boot/dts/imx6q-b450v3.dts @@ -65,11 +65,14 @@ }; }; -&ldb { +&clks { assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>; assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>, <&clks IMX6QDL_CLK_PLL3_USB_OTG>; +}; + +&ldb { status = "okay"; lvds0: lvds-channel@0 { diff --git a/arch/arm/boot/dts/imx6q-b650v3.dts b/arch/arm/boot/dts/imx6q-b650v3.dts index 823f55ccb60f..33cb71acadcc 100644 --- a/arch/arm/boot/dts/imx6q-b650v3.dts +++ b/arch/arm/boot/dts/imx6q-b650v3.dts @@ -65,11 +65,14 @@ }; }; -&ldb { +&clks { assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>; assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>, <&clks IMX6QDL_CLK_PLL3_USB_OTG>; +}; + +&ldb { status = "okay"; lvds0: lvds-channel@0 { -- GitLab From 7b8081912d75df1d910d6969f0a374b66ef242bf Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 25 Apr 2016 23:13:17 -0400 Subject: [PATCH 4344/9938] ext4: fix jbd2 handle extension in ext4_ext_truncate_extend_restart() The function jbd2_journal_extend() takes as its argument the number of new credits to be added to the handle. We weren't taking into account the currently unused handle credits; worse, we would try to extend the handle by N credits when it had N credits available. In the case where jbd2_journal_extend() fails because the transaction is too large, when jbd2_journal_restart() gets called, the N credits owned by the handle gets returned to the transaction, and the transaction commit is asynchronously requested, and then start_this_handle() will be able to successfully attach the handle to the current transaction since the required credits are now available. This is mostly harmless, but since ext4_ext_truncate_extend_restart() returns EAGAIN, the truncate machinery will once again try to call ext4_ext_truncate_extend_restart(), which will do the above sequence over and over again until the transaction has committed. This was found while I was debugging a lockup in caused by running xfstests generic/074 in the data=journal case. I'm still not sure why we ended up looping forever, which suggests there may still be another bug hiding in the transaction accounting machinery, but this commit prevents us from looping in the first place. Signed-off-by: Theodore Ts'o --- fs/ext4/extents.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 95bf4679ac54..ba2be53a61d2 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -120,9 +120,14 @@ static int ext4_ext_truncate_extend_restart(handle_t *handle, if (!ext4_handle_valid(handle)) return 0; - if (handle->h_buffer_credits > needed) + if (handle->h_buffer_credits >= needed) return 0; - err = ext4_journal_extend(handle, needed); + /* + * If we need to extend the journal get a few extra blocks + * while we're at it for efficiency's sake. + */ + needed += 3; + err = ext4_journal_extend(handle, needed - handle->h_buffer_credits); if (err <= 0) return err; err = ext4_truncate_restart_trans(handle, inode, needed); -- GitLab From 025ce02d92b67d6c702676c11f7f1f5e8f0a81fa Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 27 Mar 2016 12:13:54 -0400 Subject: [PATCH 4345/9938] mtd: maps: make uclinux.c driver more explicitly non-modular The Kconfig for this support is currently declared with: config MTD_UCLINUX bool "Generic uClinux RAM/ROM filesystem support" ...meaning that it currently is not being built as a module by anyone. Lets remove as much of the modular evidence that we can, so that when reading the driver there is less doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also replace module.h with moduleparam.h since the file does use a module_param, and leaving it as such is currently the easiest way to remain compatible with existing boot arg use cases. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: David Woodhouse Cc: Greg Ungerer Signed-off-by: Paul Gortmaker Signed-off-by: Brian Norris --- drivers/mtd/maps/uclinux.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index c1af83db5202..00a8190797ec 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -4,11 +4,13 @@ * uclinux.c -- generic memory mapped MTD driver for uclinux * * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) + * + * License: GPL */ /****************************************************************************/ -#include +#include #include #include #include @@ -117,27 +119,6 @@ static int __init uclinux_mtd_init(void) return(0); } - -/****************************************************************************/ - -static void __exit uclinux_mtd_cleanup(void) -{ - if (uclinux_ram_mtdinfo) { - mtd_device_unregister(uclinux_ram_mtdinfo); - map_destroy(uclinux_ram_mtdinfo); - uclinux_ram_mtdinfo = NULL; - } - if (uclinux_ram_map.virt) - uclinux_ram_map.virt = 0; -} - -/****************************************************************************/ - -module_init(uclinux_mtd_init); -module_exit(uclinux_mtd_cleanup); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Ungerer "); -MODULE_DESCRIPTION("Generic MTD for uClinux"); +device_initcall(uclinux_mtd_init); /****************************************************************************/ -- GitLab From 4c54659269ecb799133758330e7ea2a6fa4c65ca Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Mon, 25 Apr 2016 23:21:00 -0400 Subject: [PATCH 4346/9938] ext4: handle unwritten or delalloc buffers before enabling data journaling We already allocate delalloc blocks before changing the inode mode into "per-file data journal" mode to prevent delalloc blocks from remaining not allocated, but another issue concerned with "BH_Unwritten" status still exists. For example, by fallocate(), several buffers' status change into "BH_Unwritten", but these buffers cannot be processed by ext4_alloc_da_blocks(). So, they still remain in unwritten status after per-file data journaling is enabled and they cannot be changed into written status any more and, if they are journaled and eventually checkpointed, these unwritten buffer will cause a kernel panic by the below BUG_ON() function of submit_bh_wbc() when they are submitted during checkpointing. static int submit_bh_wbc(int rw, struct buffer_head *bh,... { ... BUG_ON(buffer_unwritten(bh)); Moreover, when "dioread_nolock" option is enabled, the status of a buffer is changed into "BH_Unwritten" after write_begin() completes and the "BH_Unwritten" status will be cleared after I/O is done. Therefore, if a buffer's status is changed into unwrutten but the buffer's I/O is not submitted and completed, it can cause the same problem after enabling per-file data journaling. You can easily generate this bug by executing the following command. ./kvm-xfstests -C 10000 -m nodelalloc,dioread_nolock generic/269 To resolve these problems and define a boundary between the previous mode and per-file data journaling mode, we need to flush and wait all the I/O of buffers of a file before enabling per-file data journaling of the file. Signed-off-by: Daeho Jeong Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/ext4/inode.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 17bfa42ac971..779ef4c11bc1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5452,22 +5452,29 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) return 0; if (is_journal_aborted(journal)) return -EROFS; - /* We have to allocate physical blocks for delalloc blocks - * before flushing journal. otherwise delalloc blocks can not - * be allocated any more. even more truncate on delalloc blocks - * could trigger BUG by flushing delalloc blocks in journal. - * There is no delalloc block in non-journal data mode. - */ - if (val && test_opt(inode->i_sb, DELALLOC)) { - err = ext4_alloc_da_blocks(inode); - if (err < 0) - return err; - } /* Wait for all existing dio workers */ ext4_inode_block_unlocked_dio(inode); inode_dio_wait(inode); + /* + * Before flushing the journal and switching inode's aops, we have + * to flush all dirty data the inode has. There can be outstanding + * delayed allocations, there can be unwritten extents created by + * fallocate or buffered writes in dioread_nolock mode covered by + * dirty data which can be converted only after flushing the dirty + * data (and journalled aops don't know how to handle these cases). + */ + if (val) { + down_write(&EXT4_I(inode)->i_mmap_sem); + err = filemap_write_and_wait(inode->i_mapping); + if (err < 0) { + up_write(&EXT4_I(inode)->i_mmap_sem); + ext4_inode_resume_unlocked_dio(inode); + return err; + } + } + jbd2_journal_lock_updates(journal); /* @@ -5492,6 +5499,8 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) ext4_set_aops(inode); jbd2_journal_unlock_updates(journal); + if (val) + up_write(&EXT4_I(inode)->i_mmap_sem); ext4_inode_resume_unlocked_dio(inode); /* Finally we can mark the inode as dirty. */ -- GitLab From c0b20d6f4113313d8cd0566aa30f337d3697ac75 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Tue, 19 Apr 2016 12:30:01 -0400 Subject: [PATCH 4347/9938] ARM: dts: imx6q-ba16: use wdog external reset The BA16 module has a PMIC that uses the WDOG_B output from iMX6 to reset the system on a watchdog timeout. Configure the watchdog to assert the external reset signal (WDOG_B) using fsl,ext-reset-output property. Signed-off-by: Akshay Bhat Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-ba16.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/imx6q-ba16.dtsi b/arch/arm/boot/dts/imx6q-ba16.dtsi index 8122e5bbfebe..f7e17e2004ac 100644 --- a/arch/arm/boot/dts/imx6q-ba16.dtsi +++ b/arch/arm/boot/dts/imx6q-ba16.dtsi @@ -400,6 +400,7 @@ &wdog1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; }; &iomuxc { -- GitLab From c8585c6fcaf2011de54c3592e80a634a2b9e1a7f Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Mon, 25 Apr 2016 23:22:35 -0400 Subject: [PATCH 4348/9938] ext4: fix races between changing inode journal mode and ext4_writepages In ext4, there is a race condition between changing inode journal mode and ext4_writepages(). While ext4_writepages() is executed on a non-journalled mode inode, the inode's journal mode could be enabled by ioctl() and then, some pages dirtied after switching the journal mode will be still exposed to ext4_writepages() in non-journaled mode. To resolve this problem, we use fs-wide per-cpu rw semaphore by Jan Kara's suggestion because we don't want to waste ext4_inode_info's space for this extra rare case. Signed-off-by: Daeho Jeong Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/ext4/ext4.h | 4 ++++ fs/ext4/inode.c | 15 ++++++++++++--- fs/ext4/super.c | 4 ++++ kernel/locking/percpu-rwsem.c | 1 + 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index cb00b1119ec9..ba5aecc07fbc 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef __KERNEL__ #include #endif @@ -1508,6 +1509,9 @@ struct ext4_sb_info { struct ratelimit_state s_err_ratelimit_state; struct ratelimit_state s_warning_ratelimit_state; struct ratelimit_state s_msg_ratelimit_state; + + /* Barrier between changing inodes' journal flags and writepages ops. */ + struct percpu_rw_semaphore s_journal_flag_rwsem; }; static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 779ef4c11bc1..4d8ebbe00456 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2612,11 +2612,14 @@ static int ext4_writepages(struct address_space *mapping, struct blk_plug plug; bool give_up_on_write = false; + percpu_down_read(&sbi->s_journal_flag_rwsem); trace_ext4_writepages(inode, wbc); - if (dax_mapping(mapping)) - return dax_writeback_mapping_range(mapping, inode->i_sb->s_bdev, - wbc); + if (dax_mapping(mapping)) { + ret = dax_writeback_mapping_range(mapping, inode->i_sb->s_bdev, + wbc); + goto out_writepages; + } /* * No pages to write? This is mainly a kludge to avoid starting @@ -2786,6 +2789,7 @@ static int ext4_writepages(struct address_space *mapping, out_writepages: trace_ext4_writepages_result(inode, wbc, ret, nr_to_write - wbc->nr_to_write); + percpu_up_read(&sbi->s_journal_flag_rwsem); return ret; } @@ -5436,6 +5440,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) journal_t *journal; handle_t *handle; int err; + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); /* * We have to be very careful here: changing a data block's @@ -5475,6 +5480,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) } } + percpu_down_write(&sbi->s_journal_flag_rwsem); jbd2_journal_lock_updates(journal); /* @@ -5491,6 +5497,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) err = jbd2_journal_flush(journal); if (err < 0) { jbd2_journal_unlock_updates(journal); + percpu_up_write(&sbi->s_journal_flag_rwsem); ext4_inode_resume_unlocked_dio(inode); return err; } @@ -5499,6 +5506,8 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) ext4_set_aops(inode); jbd2_journal_unlock_updates(journal); + percpu_up_write(&sbi->s_journal_flag_rwsem); + if (val) up_write(&EXT4_I(inode)->i_mmap_sem); ext4_inode_resume_unlocked_dio(inode); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 304c712dbe12..20c5d52253b4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -859,6 +859,7 @@ static void ext4_put_super(struct super_block *sb) percpu_counter_destroy(&sbi->s_freeinodes_counter); percpu_counter_destroy(&sbi->s_dirs_counter); percpu_counter_destroy(&sbi->s_dirtyclusters_counter); + percpu_free_rwsem(&sbi->s_journal_flag_rwsem); brelse(sbi->s_sbh); #ifdef CONFIG_QUOTA for (i = 0; i < EXT4_MAXQUOTAS; i++) @@ -3930,6 +3931,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (!err) err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0, GFP_KERNEL); + if (!err) + err = percpu_init_rwsem(&sbi->s_journal_flag_rwsem); + if (err) { ext4_msg(sb, KERN_ERR, "insufficient memory"); goto failed_mount6; diff --git a/kernel/locking/percpu-rwsem.c b/kernel/locking/percpu-rwsem.c index f231e0bb311c..bec0b647f9cc 100644 --- a/kernel/locking/percpu-rwsem.c +++ b/kernel/locking/percpu-rwsem.c @@ -37,6 +37,7 @@ void percpu_free_rwsem(struct percpu_rw_semaphore *brw) free_percpu(brw->fast_read_ctr); brw->fast_read_ctr = NULL; /* catch use after free bugs */ } +EXPORT_SYMBOL_GPL(percpu_free_rwsem); /* * This is the fast-path for down_read/up_read. If it succeeds we rely -- GitLab From 852224038560768f919af83ca2015f0d31be82c1 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Tue, 19 Apr 2016 16:53:08 -0500 Subject: [PATCH 4349/9938] Documentation: fsl-mc: binding updates for MSIs, ranges, PHYs -The Freescale Management Complex and all associated objects use message interrupts, and thus an msi-parent is required. -Define a ranges property to specify the mapping between the MC address space and the system address space. -The fsl-mc node may optionally have dpmac sub-nodes that describe the relationship between the Ethernet MACs which belong to the MC and the Ethernet PHYs on the system board. Signed-off-by: Stuart Yoder Acked-by: J. German Rivera Acked-by: Rob Herring Signed-off-by: Shawn Guo --- .../devicetree/bindings/misc/fsl,qoriq-mc.txt | 81 ++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt index c7a26ca8da12..6611a7c2053a 100644 --- a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt +++ b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt @@ -30,11 +30,90 @@ Required properties: region may not be present in some scenarios, such as in the device tree presented to a virtual machine. + - msi-parent + Value type: + Definition: Must be present and point to the MSI controller node + handling message interrupts for the MC. + + - ranges + Value type: + Definition: A standard property. Defines the mapping between the child + MC address space and the parent system address space. + + The MC address space is defined by 3 components: + + + Valid values for region type are + 0x0 - MC portals + 0x1 - QBMAN portals + + - #address-cells + Value type: + Definition: Must be 3. (see definition in 'ranges' property) + + - #size-cells + Value type: + Definition: Must be 1. + +Sub-nodes: + + The fsl-mc node may optionally have dpmac sub-nodes that describe + the relationship between the Ethernet MACs which belong to the MC + and the Ethernet PHYs on the system board. + + The dpmac nodes must be under a node named "dpmacs" which contains + the following properties: + + - #address-cells + Value type: + Definition: Must be present if dpmac sub-nodes are defined and must + have a value of 1. + + - #size-cells + Value type: + Definition: Must be present if dpmac sub-nodes are defined and must + have a value of 0. + + These nodes must have the following properties: + + - compatible + Value type: + Definition: Must be "fsl,qoriq-mc-dpmac". + + - reg + Value type: + Definition: Specifies the id of the dpmac. + + - phy-handle + Value type: + Definition: Specifies the phandle to the PHY device node associated + with the this dpmac. + Example: fsl_mc: fsl-mc@80c000000 { compatible = "fsl,qoriq-mc"; reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ - }; + msi-parent = <&its>; + #address-cells = <3>; + #size-cells = <1>; + + /* + * Region type 0x0 - MC portals + * Region type 0x1 - QBMAN portals + */ + ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000 + 0x1 0x0 0x0 0x8 0x18000000 0x8000000>; + dpmacs { + #address-cells = <1>; + #size-cells = <0>; + + dpmac@1 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <1>; + phy-handle = <&mdio0_phy0>; + } + } + }; -- GitLab From bb4b4e93febc139003e2af2f36e438df58b4803c Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Tue, 19 Apr 2016 16:53:17 -0500 Subject: [PATCH 4350/9938] arm64: dts: ls2080a: fsl-mc dt node updates updates to the fsl-mc node for full functionality: -msi-parent is needed for interrupt support -ranges is needed to enable the bus driver to translate bus addresses -dpmac nodes provide a basis for relating dpmac objects to PHYs Signed-off-by: Stuart Yoder Signed-off-by: Shawn Guo --- .../arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi index 6195916fc448..3187c822afa3 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi @@ -265,6 +265,104 @@ compatible = "fsl,qoriq-mc"; reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ + msi-parent = <&its>; + #address-cells = <3>; + #size-cells = <1>; + + /* + * Region type 0x0 - MC portals + * Region type 0x1 - QBMAN portals + */ + ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000 + 0x1 0x0 0x0 0x8 0x18000000 0x8000000>; + + /* + * Define the maximum number of MACs present on the SoC. + */ + dpmacs { + #address-cells = <1>; + #size-cells = <0>; + + dpmac1: dpmac@1 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x1>; + }; + + dpmac2: dpmac@2 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x2>; + }; + + dpmac3: dpmac@3 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x3>; + }; + + dpmac4: dpmac@4 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x4>; + }; + + dpmac5: dpmac@5 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x5>; + }; + + dpmac6: dpmac@6 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x6>; + }; + + dpmac7: dpmac@7 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x7>; + }; + + dpmac8: dpmac@8 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x8>; + }; + + dpmac9: dpmac@9 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x9>; + }; + + dpmac10: dpmac@a { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xa>; + }; + + dpmac11: dpmac@b { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xb>; + }; + + dpmac12: dpmac@c { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xc>; + }; + + dpmac13: dpmac@d { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xd>; + }; + + dpmac14: dpmac@e { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xe>; + }; + + dpmac15: dpmac@f { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xf>; + }; + + dpmac16: dpmac@10 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x10>; + }; + }; }; smmu: iommu@5000000 { -- GitLab From e093bf60ca498a03b4ea8f5d6cf1d520a68e5d2e Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 28 Mar 2016 23:32:24 +0200 Subject: [PATCH 4351/9938] dmaengine: pxa: handle bus errors In the current state, upon bus error the driver will spin endlessly, relaunching the last tx, which will fail again and again : - a bus error happens - pxad_chan_handler() is called - as PXA_DCSR_STOPSTATE is true, the last non-terminated transaction is lauched, which is the one triggering the bus error, as it didn't terminate - moreover, the STOP interrupt fires a new, as the STOPIRQEN is still active Break this logic by stopping the automatic relaunch of a dma channel upon a bus error, even if there are still pending issued requests on it. As dma_cookie_status() seems unable to return DMA_ERROR in its current form, ie. there seems no way to mark a DMA_ERROR on a per-async-tx basis, it is chosen in this patch to remember on the channel which transaction failed, and report it in pxad_tx_status(). It's a bit misleading because if T1, T2, T3 and T4 were queued, and T1 was completed while T2 causes a bus error, the status of T3 and T4 will be reported as DMA_IN_PROGRESS, while the channel is actually stopped. Signed-off-by: Robert Jarzmik Signed-off-by: Vinod Koul --- drivers/dma/pxa_dma.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 77c1c44009d8..6d17dfd67881 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -117,6 +117,7 @@ struct pxad_chan { /* protected by vc->lock */ struct pxad_phy *phy; struct dma_pool *desc_pool; /* Descriptors pool */ + dma_cookie_t bus_error; }; struct pxad_device { @@ -563,6 +564,7 @@ static void pxad_launch_chan(struct pxad_chan *chan, return; } } + chan->bus_error = 0; /* * Program the descriptor's address into the DMA controller, @@ -666,6 +668,7 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) struct virt_dma_desc *vd, *tmp; unsigned int dcsr; unsigned long flags; + dma_cookie_t last_started = 0; BUG_ON(!chan); @@ -678,6 +681,7 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) dev_dbg(&chan->vc.chan.dev->device, "%s(): checking txd %p[%x]: completed=%d\n", __func__, vd, vd->tx.cookie, is_desc_completed(vd)); + last_started = vd->tx.cookie; if (to_pxad_sw_desc(vd)->cyclic) { vchan_cyclic_callback(vd); break; @@ -690,7 +694,12 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) } } - if (dcsr & PXA_DCSR_STOPSTATE) { + if (dcsr & PXA_DCSR_BUSERR) { + chan->bus_error = last_started; + phy_disable(phy); + } + + if (!chan->bus_error && dcsr & PXA_DCSR_STOPSTATE) { dev_dbg(&chan->vc.chan.dev->device, "%s(): channel stopped, submitted_empty=%d issued_empty=%d", __func__, @@ -1249,6 +1258,9 @@ static enum dma_status pxad_tx_status(struct dma_chan *dchan, struct pxad_chan *chan = to_pxad_chan(dchan); enum dma_status ret; + if (cookie == chan->bus_error) + return DMA_ERROR; + ret = dma_cookie_status(dchan, cookie, txstate); if (likely(txstate && (ret != DMA_ERROR))) dma_set_residue(txstate, pxad_residue(chan, cookie)); -- GitLab From 128fe7e9a0b99da1d7346528526bd424f705774b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 22 Apr 2016 08:14:33 +0200 Subject: [PATCH 4352/9938] dmaengine: sun6i: Fix the access of the IRQ register The IRQ register number is computed, but this number was not used and the register was the one indexed by the channel index instead. Then, only the first DMA channel was working. Acked-by: Maxime Ripard Signed-off-by: Jean-Francois Moine Signed-off-by: Vinod Koul --- drivers/dma/sun6i-dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 2db12e493c53..2ec320dc68b3 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -381,9 +381,9 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) irq_reg = pchan->idx / DMA_IRQ_CHAN_NR; irq_offset = pchan->idx % DMA_IRQ_CHAN_NR; - irq_val = readl(sdev->base + DMA_IRQ_EN(irq_offset)); + irq_val = readl(sdev->base + DMA_IRQ_EN(irq_reg)); irq_val |= DMA_IRQ_QUEUE << (irq_offset * DMA_IRQ_CHAN_WIDTH); - writel(irq_val, sdev->base + DMA_IRQ_EN(irq_offset)); + writel(irq_val, sdev->base + DMA_IRQ_EN(irq_reg)); writel(pchan->desc->p_lli, pchan->base + DMA_CHAN_LLI_ADDR); writel(DMA_CHAN_ENABLE_START, pchan->base + DMA_CHAN_ENABLE); -- GitLab From dc6a58c17cd443bfdd2e05c45aec80106d59fdb2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 22 Apr 2016 08:17:14 +0200 Subject: [PATCH 4353/9938] dmaengine: sun6i: Fix impossible settings of burst and bus width In the commit 1f9cd915b64bb95f ("dmaengine: sun6i: Fix memcpy operation"), the signed values returned by convert_burst() and convert_buswidth() were stored in an unsigned value. Then, these values were considered as errors when non null. As a result, DMA transfers were rejected when the burst or buswidth had values different from 1, as 8 for the burst or 4 for the bus width. Acked-by: Maxime Ripard Signed-off-by: Jean-Francois Moine Signed-off-by: Vinod Koul --- drivers/dma/sun6i-dma.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 2ec320dc68b3..3579ee741329 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -281,25 +281,25 @@ static inline int sun6i_dma_cfg_lli(struct sun6i_dma_lli *lli, dma_addr_t dst, u32 len, struct dma_slave_config *config) { - u8 src_width, dst_width, src_burst, dst_burst; + s8 src_width, dst_width, src_burst, dst_burst; if (!config) return -EINVAL; src_burst = convert_burst(config->src_maxburst); - if (src_burst) + if (src_burst < 0) return src_burst; dst_burst = convert_burst(config->dst_maxburst); - if (dst_burst) + if (dst_burst < 0) return dst_burst; src_width = convert_buswidth(config->src_addr_width); - if (src_width) + if (src_width < 0) return src_width; dst_width = convert_buswidth(config->dst_addr_width); - if (dst_width) + if (dst_width < 0) return dst_width; lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) | -- GitLab From 52c871798ff84b6bfb095c3d3cc69af517f72396 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 22 Apr 2016 08:47:29 +0200 Subject: [PATCH 4354/9938] dmaengine: sun6i: Simplify lli setting Checking the DMA config before setting the lli list avoids to do tests inside the setting loop. Signed-off-by: Jean-Francois Moine Signed-off-by: Vinod Koul --- drivers/dma/sun6i-dma.c | 102 ++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 3579ee741329..b08245ef71d1 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -276,45 +276,6 @@ static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev, return next; } -static inline int sun6i_dma_cfg_lli(struct sun6i_dma_lli *lli, - dma_addr_t src, - dma_addr_t dst, u32 len, - struct dma_slave_config *config) -{ - s8 src_width, dst_width, src_burst, dst_burst; - - if (!config) - return -EINVAL; - - src_burst = convert_burst(config->src_maxburst); - if (src_burst < 0) - return src_burst; - - dst_burst = convert_burst(config->dst_maxburst); - if (dst_burst < 0) - return dst_burst; - - src_width = convert_buswidth(config->src_addr_width); - if (src_width < 0) - return src_width; - - dst_width = convert_buswidth(config->dst_addr_width); - if (dst_width < 0) - return dst_width; - - lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) | - DMA_CHAN_CFG_SRC_WIDTH(src_width) | - DMA_CHAN_CFG_DST_BURST(dst_burst) | - DMA_CHAN_CFG_DST_WIDTH(dst_width); - - lli->src = src; - lli->dst = dst; - lli->len = len; - lli->para = NORMAL_WAIT; - - return 0; -} - static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan, struct sun6i_dma_lli *lli) { @@ -502,6 +463,35 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id) return ret; } +static int set_config(struct sun6i_dma_dev *sdev, + struct dma_slave_config *sconfig, + enum dma_transfer_direction direction, + u32 *p_cfg) +{ + s8 src_width, dst_width, src_burst, dst_burst; + + src_burst = convert_burst(sconfig->src_maxburst); + src_width = convert_buswidth(sconfig->src_addr_width); + dst_burst = convert_burst(sconfig->dst_maxburst); + dst_width = convert_buswidth(sconfig->dst_addr_width); + + if (src_burst < 0) + return src_burst; + if (src_width < 0) + return src_width; + if (dst_burst < 0) + return dst_burst; + if (dst_width < 0) + return dst_width; + + *p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) | + DMA_CHAN_CFG_SRC_WIDTH(src_width) | + DMA_CHAN_CFG_DST_BURST(dst_burst) | + DMA_CHAN_CFG_DST_WIDTH(dst_width); + + return 0; +} + static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, size_t len, unsigned long flags) @@ -569,6 +559,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( struct sun6i_desc *txd; struct scatterlist *sg; dma_addr_t p_lli; + u32 lli_cfg; int i, ret; if (!sgl) @@ -579,6 +570,12 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( return NULL; } + ret = set_config(sdev, sconfig, dir, &lli_cfg); + if (ret) { + dev_err(chan2dev(chan), "Invalid DMA configuration\n"); + return NULL; + } + txd = kzalloc(sizeof(*txd), GFP_NOWAIT); if (!txd) return NULL; @@ -588,14 +585,14 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( if (!v_lli) goto err_lli_free; - if (dir == DMA_MEM_TO_DEV) { - ret = sun6i_dma_cfg_lli(v_lli, sg_dma_address(sg), - sconfig->dst_addr, sg_dma_len(sg), - sconfig); - if (ret) - goto err_cur_lli_free; + v_lli->len = sg_dma_len(sg); + v_lli->para = NORMAL_WAIT; - v_lli->cfg |= DMA_CHAN_CFG_DST_IO_MODE | + if (dir == DMA_MEM_TO_DEV) { + v_lli->src = sg_dma_address(sg); + v_lli->dst = sconfig->dst_addr; + v_lli->cfg = lli_cfg | + DMA_CHAN_CFG_DST_IO_MODE | DMA_CHAN_CFG_SRC_LINEAR_MODE | DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) | DMA_CHAN_CFG_DST_DRQ(vchan->port); @@ -607,13 +604,10 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( sg_dma_len(sg), flags); } else { - ret = sun6i_dma_cfg_lli(v_lli, sconfig->src_addr, - sg_dma_address(sg), sg_dma_len(sg), - sconfig); - if (ret) - goto err_cur_lli_free; - - v_lli->cfg |= DMA_CHAN_CFG_DST_LINEAR_MODE | + v_lli->src = sconfig->src_addr; + v_lli->dst = sg_dma_address(sg); + v_lli->cfg = lli_cfg | + DMA_CHAN_CFG_DST_LINEAR_MODE | DMA_CHAN_CFG_SRC_IO_MODE | DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) | DMA_CHAN_CFG_SRC_DRQ(vchan->port); @@ -634,8 +628,6 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( return vchan_tx_prep(&vchan->vc, &txd->vd, flags); -err_cur_lli_free: - dma_pool_free(sdev->pool, v_lli, p_lli); err_lli_free: for (prev = txd->v_lli; prev; prev = prev->v_lli_next) dma_pool_free(sdev->pool, prev, virt_to_phys(prev)); -- GitLab From 4899f78a3dccda41ffdaa1a2cbf78209753e0f70 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 12:37:37 -0500 Subject: [PATCH 4355/9938] mailbox/omap: drop legacy platform device support OMAP mailbox devices can no longer be created in legacy non-DT mode, all the relevant code has been cleaned up. The OMAP mailbox driver will only support devices created from DT going forward, so drop the legacy platform device support from the driver. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 101 +++++++++------------ include/linux/platform_data/mailbox-omap.h | 58 ------------ 2 files changed, 41 insertions(+), 118 deletions(-) delete mode 100644 include/linux/platform_data/mailbox-omap.h diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index b7f636f15cac..8754d810ef05 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -2,7 +2,7 @@ * OMAP mailbox driver * * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. - * Copyright (C) 2013-2014 Texas Instruments Inc. + * Copyright (C) 2013-2016 Texas Instruments Incorporated - http://www.ti.com * * Contact: Hiroshi DOYU * Suman Anna @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -69,6 +68,10 @@ #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32)) +/* Interrupt register configuration types */ +#define MBOX_INTR_CFG_TYPE1 0 +#define MBOX_INTR_CFG_TYPE2 1 + struct omap_mbox_fifo { unsigned long msg; unsigned long fifo_stat; @@ -696,8 +699,6 @@ static int omap_mbox_probe(struct platform_device *pdev) int ret; struct mbox_chan *chnls; struct omap_mbox **list, *mbox, *mboxblk; - struct omap_mbox_pdata *pdata = pdev->dev.platform_data; - struct omap_mbox_dev_info *info = NULL; struct omap_mbox_fifo_info *finfo, *finfoblk; struct omap_mbox_device *mdev; struct omap_mbox_fifo *fifo; @@ -710,36 +711,26 @@ static int omap_mbox_probe(struct platform_device *pdev) u32 l; int i; - if (!node && (!pdata || !pdata->info_cnt || !pdata->info)) { - pr_err("%s: platform not supported\n", __func__); + if (!node) { + pr_err("%s: only DT-based devices are supported\n", __func__); return -ENODEV; } - if (node) { - match = of_match_device(omap_mailbox_of_match, &pdev->dev); - if (!match) - return -ENODEV; - intr_type = (u32)match->data; + match = of_match_device(omap_mailbox_of_match, &pdev->dev); + if (!match) + return -ENODEV; + intr_type = (u32)match->data; - if (of_property_read_u32(node, "ti,mbox-num-users", - &num_users)) - return -ENODEV; + if (of_property_read_u32(node, "ti,mbox-num-users", &num_users)) + return -ENODEV; - if (of_property_read_u32(node, "ti,mbox-num-fifos", - &num_fifos)) - return -ENODEV; + if (of_property_read_u32(node, "ti,mbox-num-fifos", &num_fifos)) + return -ENODEV; - info_count = of_get_available_child_count(node); - if (!info_count) { - dev_err(&pdev->dev, "no available mbox devices found\n"); - return -ENODEV; - } - } else { /* non-DT device creation */ - info_count = pdata->info_cnt; - info = pdata->info; - intr_type = pdata->intr_type; - num_users = pdata->num_users; - num_fifos = pdata->num_fifos; + info_count = of_get_available_child_count(node); + if (!info_count) { + dev_err(&pdev->dev, "no available mbox devices found\n"); + return -ENODEV; } finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk), @@ -750,38 +741,28 @@ static int omap_mbox_probe(struct platform_device *pdev) finfo = finfoblk; child = NULL; for (i = 0; i < info_count; i++, finfo++) { - if (node) { - child = of_get_next_available_child(node, child); - ret = of_property_read_u32_array(child, "ti,mbox-tx", - tmp, ARRAY_SIZE(tmp)); - if (ret) - return ret; - finfo->tx_id = tmp[0]; - finfo->tx_irq = tmp[1]; - finfo->tx_usr = tmp[2]; - - ret = of_property_read_u32_array(child, "ti,mbox-rx", - tmp, ARRAY_SIZE(tmp)); - if (ret) - return ret; - finfo->rx_id = tmp[0]; - finfo->rx_irq = tmp[1]; - finfo->rx_usr = tmp[2]; - - finfo->name = child->name; - - if (of_find_property(child, "ti,mbox-send-noirq", NULL)) - finfo->send_no_irq = true; - } else { - finfo->tx_id = info->tx_id; - finfo->rx_id = info->rx_id; - finfo->tx_usr = info->usr_id; - finfo->tx_irq = info->irq_id; - finfo->rx_usr = info->usr_id; - finfo->rx_irq = info->irq_id; - finfo->name = info->name; - info++; - } + child = of_get_next_available_child(node, child); + ret = of_property_read_u32_array(child, "ti,mbox-tx", tmp, + ARRAY_SIZE(tmp)); + if (ret) + return ret; + finfo->tx_id = tmp[0]; + finfo->tx_irq = tmp[1]; + finfo->tx_usr = tmp[2]; + + ret = of_property_read_u32_array(child, "ti,mbox-rx", tmp, + ARRAY_SIZE(tmp)); + if (ret) + return ret; + finfo->rx_id = tmp[0]; + finfo->rx_irq = tmp[1]; + finfo->rx_usr = tmp[2]; + + finfo->name = child->name; + + if (of_find_property(child, "ti,mbox-send-noirq", NULL)) + finfo->send_no_irq = true; + if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos || finfo->tx_usr >= num_users || finfo->rx_usr >= num_users) return -EINVAL; diff --git a/include/linux/platform_data/mailbox-omap.h b/include/linux/platform_data/mailbox-omap.h deleted file mode 100644 index 4631dbb4255e..000000000000 --- a/include/linux/platform_data/mailbox-omap.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * mailbox-omap.h - * - * Copyright (C) 2013 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _PLAT_MAILBOX_H -#define _PLAT_MAILBOX_H - -/* Interrupt register configuration types */ -#define MBOX_INTR_CFG_TYPE1 (0) -#define MBOX_INTR_CFG_TYPE2 (1) - -/** - * struct omap_mbox_dev_info - OMAP mailbox device attribute info - * @name: name of the mailbox device - * @tx_id: mailbox queue id used for transmitting messages - * @rx_id: mailbox queue id on which messages are received - * @irq_id: irq identifier number to use from the hwmod data - * @usr_id: mailbox user id for identifying the interrupt into - * the MPU interrupt controller. - */ -struct omap_mbox_dev_info { - const char *name; - u32 tx_id; - u32 rx_id; - u32 irq_id; - u32 usr_id; -}; - -/** - * struct omap_mbox_pdata - OMAP mailbox platform data - * @intr_type: type of interrupt configuration registers used - while programming mailbox queue interrupts - * @num_users: number of users (processor devices) that the mailbox - * h/w block can interrupt - * @num_fifos: number of h/w fifos within the mailbox h/w block - * @info_cnt: number of mailbox devices for the platform - * @info: array of mailbox device attributes - */ -struct omap_mbox_pdata { - u32 intr_type; - u32 num_users; - u32 num_fifos; - u32 info_cnt; - struct omap_mbox_dev_info *info; -}; - -#endif /* _PLAT_MAILBOX_H */ -- GitLab From 86f6f5e2e2c0c520dfb0bea336cbda1f190c0357 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 12:37:38 -0500 Subject: [PATCH 4356/9938] mailbox/omap: use variable name for sizeof() operator Fix the code formatting to use the kernel preferred style of using the actual variables to determize the size using the sizeof() operator. This fixes the corresponding checkpatch warning as well. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index 8754d810ef05..ba15a49af06e 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -384,7 +384,7 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, if (!work) return NULL; - mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); + mq = kzalloc(sizeof(*mq), GFP_KERNEL); if (!mq) return NULL; -- GitLab From 0196fa3945970170d8c00684b2a7a32d304a66fb Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 12:37:39 -0500 Subject: [PATCH 4357/9938] mailbox/omap: remove FSF mailing address paragraph Remove the paragraph about writing to the Free Software Foundation's mailing address from the GPL license header as this address can change. This fixes the corresponding checkpatch warning. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index ba15a49af06e..99a66e11ec1e 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -15,12 +15,6 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #include -- GitLab From 2665a4c1d456460aea7a2f2bf7113ffdc63077bf Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 12:37:40 -0500 Subject: [PATCH 4358/9938] mailbox/omap: add blank lines after declarations Fix couple of checkpatch warnings of the type, "WARNING: Missing a blank line after declarations" Also, fixed a warning about a space after a typecast while at this. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index 99a66e11ec1e..224b73c31f22 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -154,24 +154,28 @@ void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs) static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) { struct omap_mbox_fifo *fifo = &mbox->rx_fifo; - return (mbox_msg_t) mbox_read_reg(mbox->parent, fifo->msg); + + return (mbox_msg_t)mbox_read_reg(mbox->parent, fifo->msg); } static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) { struct omap_mbox_fifo *fifo = &mbox->tx_fifo; + mbox_write_reg(mbox->parent, msg, fifo->msg); } static int mbox_fifo_empty(struct omap_mbox *mbox) { struct omap_mbox_fifo *fifo = &mbox->rx_fifo; + return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0); } static int mbox_fifo_full(struct omap_mbox *mbox) { struct omap_mbox_fifo *fifo = &mbox->tx_fifo; + return mbox_read_reg(mbox->parent, fifo->fifo_stat); } @@ -522,6 +526,7 @@ static int omap_mbox_register(struct omap_mbox_device *mdev) mboxes = mdev->mboxes; for (i = 0; mboxes[i]; i++) { struct omap_mbox *mbox = mboxes[i]; + mbox->dev = device_create(&omap_mbox_class, mdev->dev, 0, mbox, "%s", mbox->name); if (IS_ERR(mbox->dev)) { -- GitLab From 2240f8aefcaea151653e70fbf3eef09650fa027c Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 18:37:17 -0500 Subject: [PATCH 4359/9938] mailbox/omap: store mailbox interrupt type in omap_mbox_device The interrupt type used for identifying the layout of the interrupt configuration registers between OMAP4+ SoCs and older SoCs is stored only in the sub-mailbox structures for easier access. Store this type in the the omap_mbox_device structure as well along with the other global variables. This is being done to facilitate the context save and restore of appropriate registers during system suspend/resume. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index 224b73c31f22..d837def4c390 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -90,6 +90,7 @@ struct omap_mbox_device { void __iomem *mbox_base; u32 num_users; u32 num_fifos; + u32 intr_type; struct omap_mbox **mboxes; struct mbox_controller controller; struct list_head elem; @@ -828,6 +829,7 @@ static int omap_mbox_probe(struct platform_device *pdev) mdev->dev = &pdev->dev; mdev->num_users = num_users; mdev->num_fifos = num_fifos; + mdev->intr_type = intr_type; mdev->mboxes = list; /* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */ -- GitLab From af1d2f5cb9d24f0e477158dada6baf893a32ee04 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 18:37:18 -0500 Subject: [PATCH 4360/9938] mailbox/omap: add support for suspend/resume Support has been added to the OMAP mailbox driver to allow it to work across a system suspend/resume. The OMAP mailbox driver requires only the interrupt configuration registers to be saved and restored, and this is done in the suspend/resume callbacks. The registers need to be saved only if there are active clients at the time of suspend. The enabling and disabling of the mailbox clocks is done automatically by the omap_device layer. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index d837def4c390..e402aa23226d 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -88,6 +88,7 @@ struct omap_mbox_device { struct device *dev; struct mutex cfg_lock; void __iomem *mbox_base; + u32 *irq_ctx; u32 num_users; u32 num_fifos; u32 intr_type; @@ -650,6 +651,44 @@ static const struct mbox_chan_ops omap_mbox_chan_ops = { .shutdown = omap_mbox_chan_shutdown, }; +#ifdef CONFIG_PM_SLEEP +static int omap_mbox_suspend(struct device *dev) +{ + struct omap_mbox_device *mdev = dev_get_drvdata(dev); + u32 usr, reg; + + if (pm_runtime_status_suspended(dev)) + return 0; + + for (usr = 0; usr < mdev->num_users; usr++) { + reg = MAILBOX_IRQENABLE(mdev->intr_type, usr); + mdev->irq_ctx[usr] = mbox_read_reg(mdev, reg); + } + + return 0; +} + +static int omap_mbox_resume(struct device *dev) +{ + struct omap_mbox_device *mdev = dev_get_drvdata(dev); + u32 usr, reg; + + if (pm_runtime_status_suspended(dev)) + return 0; + + for (usr = 0; usr < mdev->num_users; usr++) { + reg = MAILBOX_IRQENABLE(mdev->intr_type, usr); + mbox_write_reg(mdev, mdev->irq_ctx[usr], reg); + } + + return 0; +} +#endif + +static const struct dev_pm_ops omap_mbox_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(omap_mbox_suspend, omap_mbox_resume) +}; + static const struct of_device_id omap_mailbox_of_match[] = { { .compatible = "ti,omap2-mailbox", @@ -777,6 +816,11 @@ static int omap_mbox_probe(struct platform_device *pdev) if (IS_ERR(mdev->mbox_base)) return PTR_ERR(mdev->mbox_base); + mdev->irq_ctx = devm_kzalloc(&pdev->dev, num_users * sizeof(u32), + GFP_KERNEL); + if (!mdev->irq_ctx) + return -ENOMEM; + /* allocate one extra for marking end of list */ list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list), GFP_KERNEL); @@ -887,6 +931,7 @@ static struct platform_driver omap_mbox_driver = { .remove = omap_mbox_remove, .driver = { .name = "omap-mailbox", + .pm = &omap_mbox_pm_ops, .of_match_table = of_match_ptr(omap_mailbox_of_match), }, }; -- GitLab From 9f0cee984a25a34c169dac67a11d9c951727e47a Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 18:37:19 -0500 Subject: [PATCH 4361/9938] mailbox/omap: check for any unread messages during suspend The OMAP mailbox driver is used by clients to communicate with remote processors in general. The mailbox clients are expected to have stopped communicating with these remote processors during a system suspend. The OMAP mailbox fifos are expected to not have any messages as such. Add a check for any pending unprocessed messages in the suspend callback, to detect any communication protocol issues of the mailbox clients. The system suspend is aborted if any messages are found. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index e402aa23226d..d8d3a4bc5262 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -655,11 +655,19 @@ static const struct mbox_chan_ops omap_mbox_chan_ops = { static int omap_mbox_suspend(struct device *dev) { struct omap_mbox_device *mdev = dev_get_drvdata(dev); - u32 usr, reg; + u32 usr, fifo, reg; if (pm_runtime_status_suspended(dev)) return 0; + for (fifo = 0; fifo < mdev->num_fifos; fifo++) { + if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) { + dev_err(mdev->dev, "fifo %d has unexpected unread messages\n", + fifo); + return -EBUSY; + } + } + for (usr = 0; usr < mdev->num_users; usr++) { reg = MAILBOX_IRQENABLE(mdev->intr_type, usr); mdev->irq_ctx[usr] = mbox_read_reg(mdev, reg); -- GitLab From dd28216528cf67339cd4f5854166fbd4eefd7fa8 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 6 Apr 2016 18:37:20 -0500 Subject: [PATCH 4362/9938] mailbox/omap: kill omap_mbox_{save/restore}_ctx() functions The omap_mbox_save_ctx() and omap_mbox_restore_ctx() API were previously provided to OMAP mailbox clients to save and restore the mailbox context during system suspend/resume. The save and restore functionality is now implemented through System PM driver callbacks, and there is no need for these functions, so kill these API. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/omap-mailbox.c | 51 ---------------------------------- include/linux/omap-mailbox.h | 2 -- 2 files changed, 53 deletions(-) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index d8d3a4bc5262..c5e8b9cb170d 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -55,13 +55,6 @@ #define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m))) #define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1)) -#define MBOX_REG_SIZE 0x120 - -#define OMAP4_MBOX_REG_SIZE 0x130 - -#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) -#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32)) - /* Interrupt register configuration types */ #define MBOX_INTR_CFG_TYPE1 0 #define MBOX_INTR_CFG_TYPE2 1 @@ -118,7 +111,6 @@ struct omap_mbox { struct omap_mbox_device *parent; struct omap_mbox_fifo tx_fifo; struct omap_mbox_fifo rx_fifo; - u32 ctx[OMAP4_MBOX_NR_REGS]; u32 intr_type; struct mbox_chan *chan; bool send_no_irq; @@ -209,49 +201,6 @@ static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) return (int)(enable & status & bit); } -void omap_mbox_save_ctx(struct mbox_chan *chan) -{ - int i; - int nr_regs; - struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan); - - if (WARN_ON(!mbox)) - return; - - if (mbox->intr_type) - nr_regs = OMAP4_MBOX_NR_REGS; - else - nr_regs = MBOX_NR_REGS; - for (i = 0; i < nr_regs; i++) { - mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32)); - - dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, - i, mbox->ctx[i]); - } -} -EXPORT_SYMBOL(omap_mbox_save_ctx); - -void omap_mbox_restore_ctx(struct mbox_chan *chan) -{ - int i; - int nr_regs; - struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan); - - if (WARN_ON(!mbox)) - return; - - if (mbox->intr_type) - nr_regs = OMAP4_MBOX_NR_REGS; - else - nr_regs = MBOX_NR_REGS; - for (i = 0; i < nr_regs; i++) { - mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32)); - dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, - i, mbox->ctx[i]); - } -} -EXPORT_SYMBOL(omap_mbox_restore_ctx); - static void _omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { u32 l; diff --git a/include/linux/omap-mailbox.h b/include/linux/omap-mailbox.h index 587bbdd31f5a..c726bd833761 100644 --- a/include/linux/omap-mailbox.h +++ b/include/linux/omap-mailbox.h @@ -21,8 +21,6 @@ struct mbox_client; struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl, const char *chan_name); -void omap_mbox_save_ctx(struct mbox_chan *chan); -void omap_mbox_restore_ctx(struct mbox_chan *chan); void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq); void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq); -- GitLab From 89a440932b6f2eb7fee78dbde05870e2b95e6151 Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:05 +0800 Subject: [PATCH 4363/9938] net: hns: add a new dsaf mode for debug port This patch adds a new dsaf mode named "single-port" mode for debug port. This mode only contains one debug port. This patch also changes the method of distinguishing the port type. Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 2 +- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 8 +- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 16 ++- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 2 + .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 4 +- .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 6 +- .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 132 ++++++++---------- .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.h | 2 +- .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 1 - 9 files changed, 84 insertions(+), 89 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 159142272afb..1e8bf222ef3a 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -96,7 +96,7 @@ static struct ring_pair_cb *hns_ae_get_base_ring_pair( int q_num = rcb_comm->max_q_per_vf; int vf_num = rcb_comm->max_vfn; - if (common_idx == HNS_DSAF_COMM_SERVICE_NW_IDX) + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) return &rcb_comm->ring_pair_cb[port * q_num * vf_num]; else return &rcb_comm->ring_pair_cb[0]; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 10c367d20955..353b9e7502b5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -249,7 +249,7 @@ int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, struct mac_entry_idx *old_entry; old_entry = &mac_cb->addr_entry_idx[vmid]; - if (dsaf_dev) { + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); mac_entry.in_vlan_id = old_entry->vlan_id; mac_entry.in_port_num = mac_cb->mac_id; @@ -289,7 +289,7 @@ int hns_mac_set_multi(struct hns_mac_cb *mac_cb, struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; struct dsaf_drv_mac_single_dest_entry mac_entry; - if (dsaf_dev && addr) { + if (!HNS_DSAF_IS_DEBUG(dsaf_dev) && addr) { memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); mac_entry.in_vlan_id = 0;/*vlan_id;*/ mac_entry.in_port_num = mac_cb->mac_id; @@ -380,7 +380,7 @@ static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb, if (mac_cb->mac_type == HNAE_PORT_DEBUG) return 0; - if (dsaf_dev) { + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); mac_entry.in_vlan_id = vlan_id; mac_entry.in_port_num = mac_cb->mac_id; @@ -418,7 +418,7 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable) uc_mac_entry = &mac_cb->addr_entry_idx[vmid]; - if (dsaf_dev) { + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); mac_entry.in_vlan_id = uc_mac_entry->vlan_id; mac_entry.in_port_num = mac_cb->mac_id; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 8439f6d8e360..769285375341 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -28,6 +28,7 @@ const char *g_dsaf_mode_match[DSAF_MODE_MAX] = { [DSAF_MODE_DISABLE_2PORT_64VM] = "2port-64vf", [DSAF_MODE_DISABLE_6PORT_0VM] = "6port-16rss", [DSAF_MODE_DISABLE_6PORT_16VM] = "6port-16vf", + [DSAF_MODE_DISABLE_SP] = "single-port", }; int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) @@ -217,9 +218,7 @@ static void hns_dsaf_mix_def_qid_cfg(struct dsaf_device *dsaf_dev) u32 q_id, q_num_per_port; u32 i; - hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode, - HNS_DSAF_COMM_SERVICE_NW_IDX, - &max_vfn, &max_q_per_vf); + hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode, &max_vfn, &max_q_per_vf); q_num_per_port = max_vfn * max_q_per_vf; for (i = 0, q_id = 0; i < DSAF_SERVICE_NW_NUM; i++) { @@ -239,9 +238,7 @@ static void hns_dsaf_inner_qid_cfg(struct dsaf_device *dsaf_dev) if (AE_IS_VER1(dsaf_dev->dsaf_ver)) return; - hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode, - HNS_DSAF_COMM_SERVICE_NW_IDX, - &max_vfn, &max_q_per_vf); + hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode, &max_vfn, &max_q_per_vf); q_num_per_port = max_vfn * max_q_per_vf; for (mac_id = 0, q_id = 0; mac_id < DSAF_SERVICE_NW_NUM; mac_id++) { @@ -712,7 +709,9 @@ static void hns_dsaf_tbl_tcam_data_ucast_pul( void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en) { - dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_MIX_MODE_S, !!en); + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) + dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, + DSAF_CFG_MIX_MODE_S, !!en); } void hns_dsaf_set_inner_lb(struct dsaf_device *dsaf_dev, u32 mac_id, u32 en) @@ -1307,6 +1306,9 @@ static int hns_dsaf_init(struct dsaf_device *dsaf_dev) u32 i; int ret; + if (HNS_DSAF_IS_DEBUG(dsaf_dev)) + return 0; + ret = hns_dsaf_init_hw(dsaf_dev); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index e8eedc571296..a783019deace 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -41,6 +41,7 @@ struct hns_mac_cb; #define DSAF_STATIC_NUM 28 #define DSAF_STATS_READ(p, offset) (*((u64 *)((u8 *)(p) + (offset)))) +#define HNS_DSAF_IS_DEBUG(dev) (dev->dsaf_mode == DSAF_MODE_DISABLE_SP) enum hal_dsaf_mode { HRD_DSAF_NO_DSAF_MODE = 0x0, @@ -117,6 +118,7 @@ enum dsaf_mode { DSAF_MODE_ENABLE_32VM, /**< en DSAF-mode, support 32 VM */ DSAF_MODE_ENABLE_128VM, /**< en DSAF-mode, support 128 VM */ DSAF_MODE_ENABLE, /**< before is enable DSAF mode*/ + DSAF_MODE_DISABLE_SP, /* = DSAF_GE_NUM) return; - if (port < DSAF_SERVICE_NW_NUM) { + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { reg_val_1 = 0x1 << port; /* there is difference between V1 and V2 in register.*/ if (AE_IS_VER1(dsaf_dev->dsaf_ver)) @@ -218,7 +218,7 @@ void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) u32 reg_val; u32 reg_addr; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { reg_val = RESET_REQ_OR_DREQ; if (val == 0) reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c index ab27b3b14ca3..3f59a8a30c86 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -68,7 +68,7 @@ static void __iomem *hns_ppe_common_get_ioaddr( int idx = ppe_common->comm_index; - if (idx == HNS_DSAF_COMM_SERVICE_NW_IDX) + if (!HNS_DSAF_IS_DEBUG(ppe_common->dsaf_dev)) base_addr = ppe_common->dsaf_dev->ppe_base + PPE_COMMON_REG_OFFSET; else @@ -90,7 +90,7 @@ int hns_ppe_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index) struct ppe_common_cb *ppe_common; int ppe_num; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) ppe_num = HNS_PPE_SERVICE_NW_ENGINE_NUM; else ppe_num = HNS_PPE_DEBUG_NW_ENGINE_NUM; @@ -103,7 +103,7 @@ int hns_ppe_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index) ppe_common->ppe_num = ppe_num; ppe_common->dsaf_dev = dsaf_dev; ppe_common->comm_index = comm_index; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) ppe_common->ppe_mode = PPE_COMMON_MODE_SERVICE; else ppe_common->ppe_mode = PPE_COMMON_MODE_DEBUG; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 28ee26e5c478..121ba4e56dc4 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -270,7 +270,7 @@ static void hns_rcb_set_port_timeout( static int hns_rcb_common_get_port_num(struct rcb_common_cb *rcb_common) { - if (rcb_common->comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + if (!HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) return HNS_RCB_SERVICE_NW_ENGINE_NUM; else return HNS_RCB_DEBUG_NW_ENGINE_NUM; @@ -430,11 +430,10 @@ static void hns_rcb_ring_pair_get_cfg(struct ring_pair_cb *ring_pair_cb) static int hns_rcb_get_port_in_comm( struct rcb_common_cb *rcb_common, int ring_idx) { - int comm_index = rcb_common->comm_index; int port; int q_num; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + if (!HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) { q_num = (int)rcb_common->max_q_per_vf * rcb_common->max_vfn; port = ring_idx / q_num; } else { @@ -455,7 +454,7 @@ static int hns_rcb_get_base_irq_idx(struct rcb_common_cb *rcb_common) int comm_index = rcb_common->comm_index; bool is_ver1 = AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver); - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + if (!HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) return SERVICE_RING_IRQ_IDX(is_ver1); else return DEBUG_RING_IRQ_IDX(is_ver1) + @@ -549,7 +548,7 @@ int hns_rcb_set_coalesce_usecs( return 0; if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) { - if (rcb_common->comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + if (!HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) { dev_err(rcb_common->dsaf_dev->dev, "error: not support coalesce_usecs setting!\n"); return -EINVAL; @@ -601,74 +600,67 @@ int hns_rcb_set_coalesced_frames( *@max_vfn : max vfn number *@max_q_per_vf:max ring number per vm */ -void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index, - u16 *max_vfn, u16 *max_q_per_vf) +void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, u16 *max_vfn, + u16 *max_q_per_vf) { - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { - switch (dsaf_mode) { - case DSAF_MODE_DISABLE_6PORT_0VM: - *max_vfn = 1; - *max_q_per_vf = 16; - break; - case DSAF_MODE_DISABLE_FIX: - *max_vfn = 1; - *max_q_per_vf = 1; - break; - case DSAF_MODE_DISABLE_2PORT_64VM: - *max_vfn = 64; - *max_q_per_vf = 1; - break; - case DSAF_MODE_DISABLE_6PORT_16VM: - *max_vfn = 16; - *max_q_per_vf = 1; - break; - default: - *max_vfn = 1; - *max_q_per_vf = 16; - break; - } - } else { + switch (dsaf_mode) { + case DSAF_MODE_DISABLE_6PORT_0VM: + *max_vfn = 1; + *max_q_per_vf = 16; + break; + case DSAF_MODE_DISABLE_FIX: + case DSAF_MODE_DISABLE_SP: *max_vfn = 1; *max_q_per_vf = 1; + break; + case DSAF_MODE_DISABLE_2PORT_64VM: + *max_vfn = 64; + *max_q_per_vf = 1; + break; + case DSAF_MODE_DISABLE_6PORT_16VM: + *max_vfn = 16; + *max_q_per_vf = 1; + break; + default: + *max_vfn = 1; + *max_q_per_vf = 16; + break; } } -int hns_rcb_get_ring_num(struct dsaf_device *dsaf_dev, int comm_index) +int hns_rcb_get_ring_num(struct dsaf_device *dsaf_dev) { - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { - switch (dsaf_dev->dsaf_mode) { - case DSAF_MODE_ENABLE_FIX: - return 1; - - case DSAF_MODE_DISABLE_FIX: - return 6; - - case DSAF_MODE_ENABLE_0VM: - return 32; - - case DSAF_MODE_DISABLE_6PORT_0VM: - case DSAF_MODE_ENABLE_16VM: - case DSAF_MODE_DISABLE_6PORT_2VM: - case DSAF_MODE_DISABLE_6PORT_16VM: - case DSAF_MODE_DISABLE_6PORT_4VM: - case DSAF_MODE_ENABLE_8VM: - return 96; - - case DSAF_MODE_DISABLE_2PORT_16VM: - case DSAF_MODE_DISABLE_2PORT_8VM: - case DSAF_MODE_ENABLE_32VM: - case DSAF_MODE_DISABLE_2PORT_64VM: - case DSAF_MODE_ENABLE_128VM: - return 128; - - default: - dev_warn(dsaf_dev->dev, - "get ring num fail,use default!dsaf_mode=%d\n", - dsaf_dev->dsaf_mode); - return 128; - } - } else { + switch (dsaf_dev->dsaf_mode) { + case DSAF_MODE_ENABLE_FIX: + case DSAF_MODE_DISABLE_SP: return 1; + + case DSAF_MODE_DISABLE_FIX: + return 6; + + case DSAF_MODE_ENABLE_0VM: + return 32; + + case DSAF_MODE_DISABLE_6PORT_0VM: + case DSAF_MODE_ENABLE_16VM: + case DSAF_MODE_DISABLE_6PORT_2VM: + case DSAF_MODE_DISABLE_6PORT_16VM: + case DSAF_MODE_DISABLE_6PORT_4VM: + case DSAF_MODE_ENABLE_8VM: + return 96; + + case DSAF_MODE_DISABLE_2PORT_16VM: + case DSAF_MODE_DISABLE_2PORT_8VM: + case DSAF_MODE_ENABLE_32VM: + case DSAF_MODE_DISABLE_2PORT_64VM: + case DSAF_MODE_ENABLE_128VM: + return 128; + + default: + dev_warn(dsaf_dev->dev, + "get ring num fail,use default!dsaf_mode=%d\n", + dsaf_dev->dsaf_mode); + return 128; } } @@ -677,7 +669,7 @@ void __iomem *hns_rcb_common_get_vaddr(struct dsaf_device *dsaf_dev, { void __iomem *base_addr; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) base_addr = dsaf_dev->ppe_base + RCB_COMMON_REG_OFFSET; else base_addr = dsaf_dev->sds_base @@ -697,7 +689,7 @@ static phys_addr_t hns_rcb_common_get_paddr(struct dsaf_device *dsaf_dev, u64 size = 0; int index = 0; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { index = 2; addr_offset = RCB_COMMON_REG_OFFSET; } else { @@ -717,7 +709,7 @@ int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, enum dsaf_mode dsaf_mode = dsaf_dev->dsaf_mode; u16 max_vfn; u16 max_q_per_vf; - int ring_num = hns_rcb_get_ring_num(dsaf_dev, comm_index); + int ring_num = hns_rcb_get_ring_num(dsaf_dev); rcb_common = devm_kzalloc(dsaf_dev->dev, sizeof(*rcb_common) + @@ -732,7 +724,7 @@ int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, rcb_common->desc_num = dsaf_dev->desc_num; - hns_rcb_get_queue_mode(dsaf_mode, comm_index, &max_vfn, &max_q_per_vf); + hns_rcb_get_queue_mode(dsaf_mode, &max_vfn, &max_q_per_vf); rcb_common->max_vfn = max_vfn; rcb_common->max_q_per_vf = max_q_per_vf; @@ -932,7 +924,7 @@ void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data) { u32 *regs = data; bool is_ver1 = AE_IS_VER1(rcb_com->dsaf_dev->dsaf_ver); - bool is_dbg = (rcb_com->comm_index != HNS_DSAF_COMM_SERVICE_NW_IDX); + bool is_dbg = HNS_DSAF_IS_DEBUG(rcb_com->dsaf_dev); u32 reg_tmp; u32 reg_num_tmp; u32 i = 0; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h index eb61014ad615..bd54dac82ee0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h @@ -111,7 +111,7 @@ void hns_rcb_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index); int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common); void hns_rcb_start(struct hnae_queue *q, u32 val); void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common); -void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index, +void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, u16 *max_vfn, u16 *max_q_per_vf); void hns_rcb_common_init_commit_hw(struct rcb_common_cb *rcb_common); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 7ff195e60b02..cffd244f1ded 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -23,7 +23,6 @@ #define DSAF_COMM_DEV_NUM 3 #define DSAF_PPE_INODE_BASE 6 -#define HNS_DSAF_COMM_SERVICE_NW_IDX 0 #define DSAF_DEBUG_NW_NUM 2 #define DSAF_SERVICE_NW_NUM 6 #define DSAF_COMM_CHN DSAF_SERVICE_NW_NUM -- GitLab From a542458cb7211a5e092c6a3cd6150404a5b1aa46 Mon Sep 17 00:00:00 2001 From: Daode Huang Date: Sat, 23 Apr 2016 17:05:06 +0800 Subject: [PATCH 4364/9938] net: hns: set debug port irq index to 0 As debug ports are moved from service dsaf to debug dsaf, the interrupts offset should start from 0, So this patch re-defines the offset index of debug ports. Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 8 +------- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 5 +---- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 121ba4e56dc4..054f391a3eeb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -445,20 +445,14 @@ static int hns_rcb_get_port_in_comm( #define SERVICE_RING_IRQ_IDX(v1) \ ((v1) ? HNS_SERVICE_RING_IRQ_IDX : HNSV2_SERVICE_RING_IRQ_IDX) -#define DEBUG_RING_IRQ_IDX(v1) \ - ((v1) ? HNS_DEBUG_RING_IRQ_IDX : HNSV2_DEBUG_RING_IRQ_IDX) -#define DEBUG_RING_IRQ_OFFSET(v1) \ - ((v1) ? HNS_DEBUG_RING_IRQ_OFFSET : HNSV2_DEBUG_RING_IRQ_OFFSET) static int hns_rcb_get_base_irq_idx(struct rcb_common_cb *rcb_common) { - int comm_index = rcb_common->comm_index; bool is_ver1 = AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver); if (!HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) return SERVICE_RING_IRQ_IDX(is_ver1); else - return DEBUG_RING_IRQ_IDX(is_ver1) + - (comm_index - 1) * DEBUG_RING_IRQ_OFFSET(is_ver1); + return HNS_DEBUG_RING_IRQ_IDX; } #define RCB_COMM_BASE_TO_RING_BASE(base, ringid)\ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index cffd244f1ded..87826087f08b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -10,12 +10,9 @@ #ifndef _DSAF_REG_H_ #define _DSAF_REG_H_ -#define HNS_DEBUG_RING_IRQ_IDX 55 +#define HNS_DEBUG_RING_IRQ_IDX 0 #define HNS_SERVICE_RING_IRQ_IDX 59 -#define HNS_DEBUG_RING_IRQ_OFFSET 2 -#define HNSV2_DEBUG_RING_IRQ_IDX 409 #define HNSV2_SERVICE_RING_IRQ_IDX 25 -#define HNSV2_DEBUG_RING_IRQ_OFFSET 9 #define DSAF_MAX_PORT_NUM_PER_CHIP 8 #define DSAF_SERVICE_PORT_NUM_PER_DSAF 6 -- GitLab From 406adee9a9fc38c11671f26180e694976f45237c Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:07 +0800 Subject: [PATCH 4365/9938] net: hns: add attribute port-idx-in-ae in enet node. This patch parse port-idx-in-ae in enet node. In NIC mode of DSAF, all 6 PHYs of service DSAF are taken as ethernet ports to the CPU. The port-idx-in-ae can be 0 to 5. Here is the diagram: +-----+---------------+ | CPU | +-+-+-+---+-+-+-+-+-+-+ | | | | | | | | debug debug service port port port (0) (0) (0-5) In Switch mode of DSAF, all 6 PHYs of service DSAF are taken as physical ports connect to a LAN Switch while the CPU side assume itself have one single NIC connect to this switch. In this case, the port-idx-in-ae will be 0 only. +-----+-----+------+------+ | CPU | +-+-+-+-+-+-+-+-+-+-+-+-+-+ | | service| port(0) debug debug +------------+ port port | switch | (0) (0) +-+-+-+-+-+-++ | | | | | | external port when port-idx-in-ae is not exists, old attribute port-id will be used (only for compatible purpose, not recommended to use port-id in new code). Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 33 ++++--------------- .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 1 - drivers/net/ethernet/hisilicon/hns/hns_enet.c | 17 +++++++--- drivers/net/ethernet/hisilicon/hns/hns_enet.h | 3 ++ 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 1e8bf222ef3a..1c86336d6475 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -29,25 +29,6 @@ static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle) return vf_cb->mac_cb; } -/** - * hns_ae_map_eport_to_dport - translate enet port id to dsaf port id - * @port_id: enet port id - *: debug port 0-1, service port 2 -7 (dsaf mode only 2) - * return: dsaf port id - *: service ports 0 - 5, debug port 6-7 - **/ -static int hns_ae_map_eport_to_dport(u32 port_id) -{ - int port_index; - - if (port_id < DSAF_DEBUG_NW_NUM) - port_index = port_id + DSAF_SERVICE_PORT_NUM_PER_DSAF; - else - port_index = port_id - DSAF_DEBUG_NW_NUM; - - return port_index; -} - static struct dsaf_device *hns_ae_get_dsaf_dev(struct hnae_ae_dev *dev) { return container_of(dev, struct dsaf_device, ae_dev); @@ -110,7 +91,6 @@ static struct ring_pair_cb *hns_ae_get_ring_pair(struct hnae_queue *q) struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, u32 port_id) { - int port_idx; int vfnum_per_port; int qnum_per_vf; int i; @@ -120,11 +100,10 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, struct hnae_vf_cb *vf_cb; dsaf_dev = hns_ae_get_dsaf_dev(dev); - port_idx = hns_ae_map_eport_to_dport(port_id); - ring_pair_cb = hns_ae_get_base_ring_pair(dsaf_dev, port_idx); - vfnum_per_port = hns_ae_get_vf_num_per_port(dsaf_dev, port_idx); - qnum_per_vf = hns_ae_get_q_num_per_vf(dsaf_dev, port_idx); + ring_pair_cb = hns_ae_get_base_ring_pair(dsaf_dev, port_id); + vfnum_per_port = hns_ae_get_vf_num_per_port(dsaf_dev, port_id); + qnum_per_vf = hns_ae_get_q_num_per_vf(dsaf_dev, port_id); vf_cb = kzalloc(sizeof(*vf_cb) + qnum_per_vf * sizeof(struct hnae_queue *), GFP_KERNEL); @@ -163,14 +142,14 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, } vf_cb->dsaf_dev = dsaf_dev; - vf_cb->port_index = port_idx; - vf_cb->mac_cb = &dsaf_dev->mac_cb[port_idx]; + vf_cb->port_index = port_id; + vf_cb->mac_cb = &dsaf_dev->mac_cb[port_id]; ae_handle->phy_if = vf_cb->mac_cb->phy_if; ae_handle->phy_node = vf_cb->mac_cb->phy_node; ae_handle->if_support = vf_cb->mac_cb->if_support; ae_handle->port_type = vf_cb->mac_cb->mac_type; - ae_handle->dport_id = port_idx; + ae_handle->dport_id = port_id; return ae_handle; vf_id_err: diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 87826087f08b..ed0043a4dbe1 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -24,7 +24,6 @@ #define DSAF_SERVICE_NW_NUM 6 #define DSAF_COMM_CHN DSAF_SERVICE_NW_NUM #define DSAF_GE_NUM ((DSAF_SERVICE_NW_NUM) + (DSAF_DEBUG_NW_NUM)) -#define DSAF_PORT_NUM ((DSAF_SERVICE_NW_NUM) + (DSAF_DEBUG_NW_NUM)) #define DSAF_XGE_NUM DSAF_SERVICE_NW_NUM #define DSAF_PORT_TYPE_NUM 3 #define DSAF_NODE_NUM 18 diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 687204b780b0..e47aff250b15 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1873,6 +1873,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev) struct net_device *ndev; struct hns_nic_priv *priv; struct device_node *node = dev->of_node; + u32 port_id; int ret; ndev = alloc_etherdev_mq(sizeof(struct hns_nic_priv), NIC_MAX_Q_PER_VF); @@ -1896,10 +1897,18 @@ static int hns_nic_dev_probe(struct platform_device *pdev) dev_err(dev, "not find ae-handle\n"); goto out_read_prop_fail; } - - ret = of_property_read_u32(node, "port-id", &priv->port_id); - if (ret) - goto out_read_prop_fail; + /* try to find port-idx-in-ae first */ + ret = of_property_read_u32(node, "port-idx-in-ae", &port_id); + if (ret) { + /* only for old code compatible */ + ret = of_property_read_u32(node, "port-id", &port_id); + if (ret) + goto out_read_prop_fail; + /* for old dts, we need to caculate the port offset */ + port_id = port_id < HNS_SRV_OFFSET ? port_id + HNS_DEBUG_OFFSET + : port_id - HNS_SRV_OFFSET; + } + priv->port_id = port_id; hns_init_mac_addr(ndev); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h index c68ab3d34fc2..337efa582bac 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h @@ -18,6 +18,9 @@ #include "hnae.h" +#define HNS_DEBUG_OFFSET 6 +#define HNS_SRV_OFFSET 2 + enum hns_nic_state { NIC_STATE_TESTING = 0, NIC_STATE_RESETTING, -- GitLab From 422c3107ed2cc6297f051109f3d4b6d855eaae14 Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:08 +0800 Subject: [PATCH 4366/9938] net: hns: add attribute reset-field-offset for dsaf node Add the subctrl reset offset for dsaf, this property is used to reset xge/ge ports for different dsaf. If this attribute is not present, default value 0 will be used. Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 8 ++++ .../ethernet/hisilicon/hns/hns_dsaf_main.h | 1 + .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 40 +++++++++++++------ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 769285375341..b418d4201290 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -36,6 +36,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) int ret, i; u32 desc_num; u32 buf_size; + u32 reset_offset = 0; const char *mode_str; struct device_node *np = dsaf_dev->dev->of_node; @@ -119,6 +120,13 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) } dsaf_dev->desc_num = desc_num; + ret = of_property_read_u32(np, "reset-field-offset", &reset_offset); + if (ret < 0) { + dev_dbg(dsaf_dev->dev, + "get reset-field-offset fail, ret=%d!\r\n", ret); + } + dsaf_dev->reset_offset = reset_offset; + ret = of_property_read_u32(np, "buf-size", &buf_size); if (ret < 0) { dev_err(dsaf_dev->dev, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index a783019deace..47e768b9ec97 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -281,6 +281,7 @@ struct dsaf_device { u32 desc_num; /* desc num per queue*/ u32 buf_size; /* ring buffer size */ + u32 reset_offset; /* reset field offset in sub sysctrl */ int buf_size_type; /* ring buffer size-type */ enum dsaf_mode dsaf_mode; /* dsaf mode */ enum hal_dsaf_mode dsaf_en; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 8cb13d9059f9..91e0382391eb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -110,7 +110,11 @@ void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) return; reg_val |= RESET_REQ_OR_DREQ; - reg_val |= 0x2082082 << port; + + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) + reg_val |= 0x2082082 << port; + else + reg_val |= 0x2082082 << (dsaf_dev->reset_offset + 6); if (val == 0) reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; @@ -129,7 +133,11 @@ void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, if (port >= DSAF_XGE_NUM) return; - reg_val |= XGMAC_TRX_CORE_SRST_M << port; + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) + reg_val |= XGMAC_TRX_CORE_SRST_M << port; + else + reg_val |= XGMAC_TRX_CORE_SRST_M << + (dsaf_dev->reset_offset + 6); if (val == 0) reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; @@ -173,8 +181,8 @@ void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) reg_val_1); } } else { - reg_val_1 = 0x15540 << (port - 6); - reg_val_2 = 0x100 << (port - 6); + reg_val_1 = 0x15540 << dsaf_dev->reset_offset; + reg_val_2 = 0x100 << dsaf_dev->reset_offset; if (val == 0) { dsaf_write_reg(dsaf_dev->sc_base, @@ -201,7 +209,11 @@ void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) u32 reg_val = 0; u32 reg_addr; - reg_val |= RESET_REQ_OR_DREQ << port; + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) + reg_val |= RESET_REQ_OR_DREQ << port; + else + reg_val |= RESET_REQ_OR_DREQ << + (dsaf_dev->reset_offset + 6); if (val == 0) reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; @@ -213,7 +225,6 @@ void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) { - int comm_index = ppe_common->comm_index; struct dsaf_device *dsaf_dev = ppe_common->dsaf_dev; u32 reg_val; u32 reg_addr; @@ -226,7 +237,7 @@ void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG; } else { - reg_val = 0x100 << (comm_index - 1); + reg_val = 0x100 << dsaf_dev->reset_offset; if (val == 0) reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; @@ -247,14 +258,16 @@ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) u32 mode; u32 reg; u32 shift; + u32 phy_offset; bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr; int mac_id = mac_cb->mac_id; phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; - if (is_ver1 && (mac_id >= 6 && mac_id <= 7)) { + if (is_ver1 && HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) { phy_if = PHY_INTERFACE_MODE_SGMII; - } else if (mac_id >= 0 && mac_id <= 3) { + } else if (mac_id >= 0 && mac_id <= 3 && + !HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) { reg = is_ver1 ? HNS_MAC_HILINK4_REG : HNS_MAC_HILINK4V2_REG; mode = dsaf_read_reg(sys_ctl_vaddr, reg); /* mac_id 0, 1, 2, 3 ---> hilink4 lane 0, 1, 2, 3 */ @@ -263,11 +276,14 @@ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) phy_if = PHY_INTERFACE_MODE_XGMII; else phy_if = PHY_INTERFACE_MODE_SGMII; - } else if (mac_id >= 4 && mac_id <= 7) { + } else { reg = is_ver1 ? HNS_MAC_HILINK3_REG : HNS_MAC_HILINK3V2_REG; mode = dsaf_read_reg(sys_ctl_vaddr, reg); - /* mac_id 4, 5, 6, 7 ---> hilink3 lane 2, 3, 0, 1 */ - shift = is_ver1 ? 0 : mac_id <= 5 ? mac_id - 2 : mac_id - 6; + /* mac_id 4, 5,---> hilink3 lane 2, 3 + * debug port 0(6), 1(7) ---> hilink3 lane 0, 1 + */ + phy_offset = mac_cb->dsaf_dev->reset_offset - 1; + shift = is_ver1 ? 0 : mac_id >= 4 ? mac_id - 2 : phy_offset; if (dsaf_get_bit(mode, shift)) phy_if = PHY_INTERFACE_MODE_XGMII; else -- GitLab From 86897c960b490e62714f4b123b7d20b04945d773 Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:09 +0800 Subject: [PATCH 4367/9938] net: hns: add syscon operation for dsaf This patch provides the read/write function for dsaf to access the registers through syscon methods. Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index ed0043a4dbe1..6a03c94821d5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -10,6 +10,7 @@ #ifndef _DSAF_REG_H_ #define _DSAF_REG_H_ +#include #define HNS_DEBUG_RING_IRQ_IDX 0 #define HNS_SERVICE_RING_IRQ_IDX 59 #define HNSV2_SERVICE_RING_IRQ_IDX 25 @@ -989,6 +990,19 @@ static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg) return readl(reg_addr + reg); } +static inline void dsaf_write_syscon(struct regmap *base, u32 reg, u32 value) +{ + regmap_write(base, reg, value); +} + +static inline u32 dsaf_read_syscon(struct regmap *base, u32 reg) +{ + unsigned int val; + + regmap_read(base, reg, &val); + return val; +} + #define dsaf_read_dev(a, reg) \ dsaf_read_reg((a)->io_base, (reg)) -- GitLab From 2e2591b130c43dd241e7aa8b0f2d74dbf3cc334b Mon Sep 17 00:00:00 2001 From: Daode Huang Date: Sat, 23 Apr 2016 17:05:10 +0800 Subject: [PATCH 4368/9938] net: hns: sort the header file by alphabetical order This patch tunes the header file by the alphabetical order. Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 12 ++++++------ drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 12 ++++++------ drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 353b9e7502b5..37303852e9a9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -7,18 +7,18 @@ * (at your option) any later version. */ -#include -#include #include -#include -#include #include -#include +#include +#include +#include #include #include +#include +#include -#include "hns_dsaf_misc.h" #include "hns_dsaf_main.h" +#include "hns_dsaf_misc.h" #include "hns_dsaf_rcb.h" #define MAC_EN_FLAG_V 0xada0328 diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index b418d4201290..98e0e8302190 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -7,22 +7,22 @@ * (at your option) any later version. */ -#include -#include +#include #include #include +#include +#include #include -#include #include #include #include -#include +#include #include +#include "hns_dsaf_mac.h" #include "hns_dsaf_main.h" -#include "hns_dsaf_rcb.h" #include "hns_dsaf_ppe.h" -#include "hns_dsaf_mac.h" +#include "hns_dsaf_rcb.h" const char *g_dsaf_mode_match[DSAF_MODE_MAX] = { [DSAF_MODE_DISABLE_2PORT_64VM] = "2port-64vf", diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 91e0382391eb..67c8b9e8b90f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -7,10 +7,10 @@ * (at your option) any later version. */ -#include "hns_dsaf_misc.h" #include "hns_dsaf_mac.h" -#include "hns_dsaf_reg.h" +#include "hns_dsaf_misc.h" #include "hns_dsaf_ppe.h" +#include "hns_dsaf_reg.h" void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, u16 speed, int data) -- GitLab From 831d828bf2cc8535b74fa33c705a6f83e2e34eec Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:11 +0800 Subject: [PATCH 4369/9938] net: hns: separate debug dsaf device from service dsaf device There are two kinds of dsaf device in hns, one is for service ports, contains crossbar in it, can work under different mode. Another is for debug port, only can work under "single-port" mode. The current code only declared a dsaf device for both service ports and debug ports. This patch separate it to three platform devices. Here is the diagram of all port in one platform device(old): CPU | | DSAF(one platform device) -------------------------------------------------------------- / | | | | | / | PPE PPE PPE | / | | | | | / | | | | | / | crossbar | | | / | | | | |/ | ----------------------------------- | | | | | | | | | | | | | | | | | | | | | | | | MAC MAC MAC MAC MAC MAC MAC MAC | | | | | | | | | | | -------------------------------------------------------------- | | | | | | | | PHY PHY PHY PHY PHY PHY PHY PHY Here is the diagram of separate all ports to three platform(new): CPU | ----------------------------------- | | | ---------------------------------------------- --------- --------- | | | | | | | | | PPE | | PPE | | PPE | | | | | | | | | | | | | | | | | | | | crossbar | | | | | | | | | | | | | | | | | ---------------------------------- | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | MAC MAC MAC MAC MAC MAC | | MAC | | MAC | | | | | | | | | | | | | | | ---------------------------------------------- --------- --------- | | | | | | \ / | / | PHY PHY PHY PHY PHY PHY \ / PHY / PHY \ / / \ / / DSAF(three platform device) Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 40 ++--- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 152 +++++++++++++----- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 7 +- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 93 +++++++---- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 12 +- .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 72 +++++---- .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 57 ++----- .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.h | 1 - .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 53 ++---- .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 15 +- 10 files changed, 261 insertions(+), 241 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 1c86336d6475..58341dad8042 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -37,50 +37,35 @@ static struct dsaf_device *hns_ae_get_dsaf_dev(struct hnae_ae_dev *dev) static struct hns_ppe_cb *hns_get_ppe_cb(struct hnae_handle *handle) { int ppe_index; - int ppe_common_index; struct ppe_common_cb *ppe_comm; struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); - if (vf_cb->port_index < DSAF_SERVICE_PORT_NUM_PER_DSAF) { - ppe_index = vf_cb->port_index; - ppe_common_index = 0; - } else { - ppe_index = 0; - ppe_common_index = - vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1; - } - ppe_comm = vf_cb->dsaf_dev->ppe_common[ppe_common_index]; + ppe_comm = vf_cb->dsaf_dev->ppe_common[0]; + ppe_index = vf_cb->port_index; + return &ppe_comm->ppe_cb[ppe_index]; } static int hns_ae_get_q_num_per_vf( struct dsaf_device *dsaf_dev, int port) { - int common_idx = hns_dsaf_get_comm_idx_by_port(port); - - return dsaf_dev->rcb_common[common_idx]->max_q_per_vf; + return dsaf_dev->rcb_common[0]->max_q_per_vf; } static int hns_ae_get_vf_num_per_port( struct dsaf_device *dsaf_dev, int port) { - int common_idx = hns_dsaf_get_comm_idx_by_port(port); - - return dsaf_dev->rcb_common[common_idx]->max_vfn; + return dsaf_dev->rcb_common[0]->max_vfn; } static struct ring_pair_cb *hns_ae_get_base_ring_pair( struct dsaf_device *dsaf_dev, int port) { - int common_idx = hns_dsaf_get_comm_idx_by_port(port); - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[common_idx]; + struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[0]; int q_num = rcb_comm->max_q_per_vf; int vf_num = rcb_comm->max_vfn; - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) - return &rcb_comm->ring_pair_cb[port * q_num * vf_num]; - else - return &rcb_comm->ring_pair_cb[0]; + return &rcb_comm->ring_pair_cb[port * q_num * vf_num]; } static struct ring_pair_cb *hns_ae_get_ring_pair(struct hnae_queue *q) @@ -143,7 +128,7 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, vf_cb->dsaf_dev = dsaf_dev; vf_cb->port_index = port_id; - vf_cb->mac_cb = &dsaf_dev->mac_cb[port_id]; + vf_cb->mac_cb = dsaf_dev->mac_cb[port_id]; ae_handle->phy_if = vf_cb->mac_cb->phy_if; ae_handle->phy_node = vf_cb->mac_cb->phy_node; @@ -299,11 +284,8 @@ static void hns_ae_reset(struct hnae_handle *handle) struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); if (vf_cb->mac_cb->mac_type == HNAE_PORT_DEBUG) { - u8 ppe_common_index = - vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1; - hns_mac_reset(vf_cb->mac_cb); - hns_ppe_reset_common(vf_cb->dsaf_dev, ppe_common_index); + hns_ppe_reset_common(vf_cb->dsaf_dev, 0); } } @@ -702,7 +684,6 @@ int hns_ae_cpld_set_led_id(struct hnae_handle *handle, void hns_ae_get_regs(struct hnae_handle *handle, void *data) { u32 *p = data; - u32 rcb_com_idx; int i; struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle); @@ -710,8 +691,7 @@ void hns_ae_get_regs(struct hnae_handle *handle, void *data) hns_ppe_get_regs(ppe_cb, p); p += hns_ppe_get_regs_count(); - rcb_com_idx = hns_dsaf_get_comm_idx_by_port(vf_cb->port_index); - hns_rcb_get_common_regs(vf_cb->dsaf_dev->rcb_common[rcb_com_idx], p); + hns_rcb_get_common_regs(vf_cb->dsaf_dev->rcb_common[0], p); p += hns_rcb_get_common_regs_count(); for (i = 0; i < handle->q_num; i++) { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 37303852e9a9..a731777415dc 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -168,10 +169,9 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, u8 vmid, u8 *port_num) { u8 tmp_port; - u32 comm_idx; if (mac_cb->dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE) { - if (mac_cb->mac_id != DSAF_MAX_PORT_NUM_PER_CHIP) { + if (mac_cb->mac_id != DSAF_MAX_PORT_NUM) { dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d !\n", mac_cb->dsaf_dev->ae_dev.name, @@ -179,7 +179,7 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, return -EINVAL; } } else if (mac_cb->dsaf_dev->dsaf_mode < DSAF_MODE_MAX) { - if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM_PER_CHIP) { + if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM) { dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d!\n", mac_cb->dsaf_dev->ae_dev.name, @@ -192,9 +192,7 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, return -EINVAL; } - comm_idx = hns_dsaf_get_comm_idx_by_port(mac_cb->mac_id); - - if (vmid >= mac_cb->dsaf_dev->rcb_common[comm_idx]->max_vfn) { + if (vmid >= mac_cb->dsaf_dev->rcb_common[0]->max_vfn) { dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d !\n", mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vmid); return -EINVAL; @@ -234,7 +232,7 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, } /** - *hns_mac_get_inner_port_num - change vf mac address + *hns_mac_change_vf_addr - change vf mac address *@mac_cb: mac device *@vmid: vmid *@addr:mac address @@ -651,14 +649,15 @@ static int hns_mac_init_ex(struct hns_mac_cb *mac_cb) } /** - *mac_free_dev - get mac information from device node + *hns_mac_get_info - get mac information from device node *@mac_cb: mac device *@np:device node - *@mac_mode_idx:mac mode index + * return: 0 --success, negative --fail */ -static void hns_mac_get_info(struct hns_mac_cb *mac_cb, - struct device_node *np, u32 mac_mode_idx) +static int hns_mac_get_info(struct hns_mac_cb *mac_cb) { + struct device_node *np = mac_cb->dev->of_node; + struct regmap *syscon; mac_cb->link = false; mac_cb->half_duplex = false; mac_cb->speed = mac_phy_to_speed[mac_cb->phy_if]; @@ -675,11 +674,34 @@ static void hns_mac_get_info(struct hns_mac_cb *mac_cb, mac_cb->max_frm = MAC_DEFAULT_MTU; mac_cb->tx_pause_frm_time = MAC_DEFAULT_PAUSE_TIME; - /* Get the rest of the PHY information */ - mac_cb->phy_node = of_parse_phandle(np, "phy-handle", mac_cb->mac_id); + /* if the dsaf node doesn't contain a port subnode, get phy-handle + * from dsaf node + */ + if (!mac_cb->fw_port) { + mac_cb->phy_node = of_parse_phandle(np, "phy-handle", + mac_cb->mac_id); + if (mac_cb->phy_node) + dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n", + mac_cb->mac_id, mac_cb->phy_node->name); + return 0; + } + if (!is_of_node(mac_cb->fw_port)) + return -EINVAL; + /* parse property from port subnode in dsaf */ + mac_cb->phy_node = of_parse_phandle(to_of_node(mac_cb->fw_port), + "phy-handle", 0); if (mac_cb->phy_node) dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n", mac_cb->mac_id, mac_cb->phy_node->name); + syscon = syscon_node_to_regmap( + of_parse_phandle(to_of_node(mac_cb->fw_port), + "serdes-syscon", 0)); + if (IS_ERR_OR_NULL(syscon)) { + dev_err(mac_cb->dev, "serdes-syscon is needed!\n"); + return -EINVAL; + } + mac_cb->serdes_ctrl = syscon; + return 0; } /** @@ -709,31 +731,27 @@ u8 __iomem *hns_mac_get_vaddr(struct dsaf_device *dsaf_dev, return base + 0x40000 + mac_id * 0x4000 - mac_mode_idx * 0x20000; else - return mac_cb->serdes_vaddr + 0x1000 - + (mac_id - DSAF_SERVICE_PORT_NUM_PER_DSAF) * 0x100000; + return dsaf_dev->ppe_base + 0x1000; } /** * hns_mac_get_cfg - get mac cfg from dtb or acpi table * @dsaf_dev: dsa fabric device struct pointer - * @mac_idx: mac index - * retuen 0 - success , negative --fail + * @mac_cb: mac control block + * return 0 - success , negative --fail */ -int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx) +int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, struct hns_mac_cb *mac_cb) { int ret; u32 mac_mode_idx; - struct hns_mac_cb *mac_cb = &dsaf_dev->mac_cb[mac_idx]; mac_cb->dsaf_dev = dsaf_dev; mac_cb->dev = dsaf_dev->dev; - mac_cb->mac_id = mac_idx; mac_cb->sys_ctl_vaddr = dsaf_dev->sc_base; mac_cb->serdes_vaddr = dsaf_dev->sds_base; - if (dsaf_dev->cpld_base && - mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) { + if (dsaf_dev->cpld_base && !HNS_DSAF_IS_DEBUG(dsaf_dev)) { mac_cb->cpld_vaddr = dsaf_dev->cpld_base + mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET; cpld_led_reset(mac_cb); @@ -742,7 +760,7 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx) mac_cb->txpkt_for_led = 0; mac_cb->rxpkt_for_led = 0; - if (mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) mac_cb->mac_type = HNAE_PORT_SERVICE; else mac_cb->mac_type = HNAE_PORT_DEBUG; @@ -758,53 +776,99 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx) } mac_mode_idx = (u32)ret; - hns_mac_get_info(mac_cb, mac_cb->dev->of_node, mac_mode_idx); + ret = hns_mac_get_info(mac_cb); + if (ret) + return ret; mac_cb->vaddr = hns_mac_get_vaddr(dsaf_dev, mac_cb, mac_mode_idx); return 0; } +static int hns_mac_get_max_port_num(struct dsaf_device *dsaf_dev) +{ + if (HNS_DSAF_IS_DEBUG(dsaf_dev)) + return 1; + else + return DSAF_MAX_PORT_NUM; +} + /** * hns_mac_init - init mac * @dsaf_dev: dsa fabric device struct pointer - * retuen 0 - success , negative --fail + * return 0 - success , negative --fail */ int hns_mac_init(struct dsaf_device *dsaf_dev) { - int i; + bool found = false; int ret; - size_t size; + u32 port_id; + int max_port_num = hns_mac_get_max_port_num(dsaf_dev); struct hns_mac_cb *mac_cb; + struct fwnode_handle *child; - size = sizeof(struct hns_mac_cb) * DSAF_MAX_PORT_NUM_PER_CHIP; - dsaf_dev->mac_cb = devm_kzalloc(dsaf_dev->dev, size, GFP_KERNEL); - if (!dsaf_dev->mac_cb) - return -ENOMEM; + device_for_each_child_node(dsaf_dev->dev, child) { + ret = fwnode_property_read_u32(child, "port-id", &port_id); + if (ret) { + dev_err(dsaf_dev->dev, + "get port-id fail, ret=%d!\n", ret); + return ret; + } + if (port_id >= max_port_num) { + dev_err(dsaf_dev->dev, + "port-id(%u) out of range!\n", port_id); + return -EINVAL; + } + mac_cb = devm_kzalloc(dsaf_dev->dev, sizeof(*mac_cb), + GFP_KERNEL); + if (!mac_cb) + return -ENOMEM; + mac_cb->fw_port = child; + mac_cb->mac_id = (u8)port_id; + dsaf_dev->mac_cb[port_id] = mac_cb; + found = true; + } - for (i = 0; i < DSAF_MAX_PORT_NUM_PER_CHIP; i++) { - ret = hns_mac_get_cfg(dsaf_dev, i); - if (ret) - goto free_mac_cb; + /* if don't get any port subnode from dsaf node + * will init all port then, this is compatible with the old dts + */ + if (!found) { + for (port_id = 0; port_id < max_port_num; port_id++) { + mac_cb = devm_kzalloc(dsaf_dev->dev, sizeof(*mac_cb), + GFP_KERNEL); + if (!mac_cb) + return -ENOMEM; + + mac_cb->mac_id = port_id; + dsaf_dev->mac_cb[port_id] = mac_cb; + } + } + /* init mac_cb for all port */ + for (port_id = 0; port_id < max_port_num; port_id++) { + mac_cb = dsaf_dev->mac_cb[port_id]; + if (!mac_cb) + continue; - mac_cb = &dsaf_dev->mac_cb[i]; + ret = hns_mac_get_cfg(dsaf_dev, mac_cb); + if (ret) + return ret; ret = hns_mac_init_ex(mac_cb); if (ret) - goto free_mac_cb; + return ret; } return 0; - -free_mac_cb: - dsaf_dev->mac_cb = NULL; - - return ret; } void hns_mac_uninit(struct dsaf_device *dsaf_dev) { - cpld_led_reset(dsaf_dev->mac_cb); - dsaf_dev->mac_cb = NULL; + int i; + int max_port_num = hns_mac_get_max_port_num(dsaf_dev); + + for (i = 0; i < max_port_num; i++) { + cpld_led_reset(dsaf_dev->mac_cb[i]); + dsaf_dev->mac_cb[i] = NULL; + } } int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 823b6e78c8aa..45c5f16ae735 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -10,9 +10,10 @@ #ifndef _HNS_DSAF_MAC_H #define _HNS_DSAF_MAC_H -#include -#include #include +#include +#include +#include #include "hns_dsaf_main.h" struct dsaf_device; @@ -310,10 +311,12 @@ struct hns_mac_cb { struct device *dev; struct dsaf_device *dsaf_dev; struct mac_priv priv; + struct fwnode_handle *fw_port; u8 __iomem *vaddr; u8 __iomem *cpld_vaddr; u8 __iomem *sys_ctl_vaddr; u8 __iomem *serdes_vaddr; + struct regmap *serdes_ctrl; struct mac_entry_idx addr_entry_idx[DSAF_MAX_VM_NUM]; u8 sfp_prsnt; u8 cpld_led_value; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 98e0e8302190..33cdb215a547 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -37,8 +38,12 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) u32 desc_num; u32 buf_size; u32 reset_offset = 0; + u32 res_idx = 0; const char *mode_str; + struct regmap *syscon; + struct resource *res; struct device_node *np = dsaf_dev->dev->of_node; + struct platform_device *pdev = to_platform_device(dsaf_dev->dev); if (of_device_is_compatible(np, "hisilicon,hns-dsaf-v1")) dsaf_dev->dsaf_ver = AE_VERSION_1; @@ -75,42 +80,68 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) else dsaf_dev->dsaf_tc_mode = HRD_DSAF_4TC_MODE; - dsaf_dev->sc_base = of_iomap(np, 0); - if (!dsaf_dev->sc_base) { - dev_err(dsaf_dev->dev, - "%s of_iomap 0 fail!\n", dsaf_dev->ae_dev.name); - ret = -ENOMEM; - goto unmap_base_addr; - } + syscon = syscon_node_to_regmap( + of_parse_phandle(np, "subctrl-syscon", 0)); + if (IS_ERR_OR_NULL(syscon)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx++); + if (!res) { + dev_err(dsaf_dev->dev, "subctrl info is needed!\n"); + return -ENOMEM; + } + dsaf_dev->sc_base = devm_ioremap_resource(&pdev->dev, res); + if (!dsaf_dev->sc_base) { + dev_err(dsaf_dev->dev, "subctrl can not map!\n"); + return -ENOMEM; + } - dsaf_dev->sds_base = of_iomap(np, 1); - if (!dsaf_dev->sds_base) { - dev_err(dsaf_dev->dev, - "%s of_iomap 1 fail!\n", dsaf_dev->ae_dev.name); - ret = -ENOMEM; - goto unmap_base_addr; + res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx++); + if (!res) { + dev_err(dsaf_dev->dev, "serdes-ctrl info is needed!\n"); + return -ENOMEM; + } + dsaf_dev->sds_base = devm_ioremap_resource(&pdev->dev, res); + if (!dsaf_dev->sds_base) { + dev_err(dsaf_dev->dev, "serdes-ctrl can not map!\n"); + return -ENOMEM; + } + } else { + dsaf_dev->sub_ctrl = syscon; } - dsaf_dev->ppe_base = of_iomap(np, 2); - if (!dsaf_dev->ppe_base) { - dev_err(dsaf_dev->dev, - "%s of_iomap 2 fail!\n", dsaf_dev->ae_dev.name); - ret = -ENOMEM; - goto unmap_base_addr; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ppe-base"); + if (!res) { + res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx++); + if (!res) { + dev_err(dsaf_dev->dev, "ppe-base info is needed!\n"); + return -ENOMEM; + } } - - dsaf_dev->io_base = of_iomap(np, 3); - if (!dsaf_dev->io_base) { - dev_err(dsaf_dev->dev, - "%s of_iomap 3 fail!\n", dsaf_dev->ae_dev.name); - ret = -ENOMEM; - goto unmap_base_addr; + dsaf_dev->ppe_base = devm_ioremap_resource(&pdev->dev, res); + if (!dsaf_dev->ppe_base) { + dev_err(dsaf_dev->dev, "ppe-base resource can not map!\n"); + return -ENOMEM; + } + dsaf_dev->ppe_paddr = res->start; + + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "dsaf-base"); + if (!res) { + res = platform_get_resource(pdev, IORESOURCE_MEM, + res_idx); + if (!res) { + dev_err(dsaf_dev->dev, + "dsaf-base info is needed!\n"); + return -ENOMEM; + } + } + dsaf_dev->io_base = devm_ioremap_resource(&pdev->dev, res); + if (!dsaf_dev->io_base) { + dev_err(dsaf_dev->dev, "dsaf-base resource can not map!\n"); + return -ENOMEM; + } } - dsaf_dev->cpld_base = of_iomap(np, 4); - if (!dsaf_dev->cpld_base) - dev_dbg(dsaf_dev->dev, "NO CPLD ADDR"); - ret = of_property_read_u32(np, "desc-num", &desc_num); if (ret < 0 || desc_num < HNS_DSAF_MIN_DESC_CNT || desc_num > HNS_DSAF_MAX_DESC_CNT) { @@ -725,7 +756,7 @@ void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en) void hns_dsaf_set_inner_lb(struct dsaf_device *dsaf_dev, u32 mac_id, u32 en) { if (AE_IS_VER1(dsaf_dev->dsaf_ver) || - dsaf_dev->mac_cb[mac_id].mac_type == HNAE_PORT_DEBUG) + dsaf_dev->mac_cb[mac_id]->mac_type == HNAE_PORT_DEBUG) return; dsaf_set_dev_bit(dsaf_dev, DSAFV2_SERDES_LBK_0_REG + 4 * mac_id, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 47e768b9ec97..a48ef2644355 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -278,6 +278,8 @@ struct dsaf_device { u8 __iomem *ppe_base; u8 __iomem *io_base; u8 __iomem *cpld_base; + struct regmap *sub_ctrl; + phys_addr_t ppe_paddr; u32 desc_num; /* desc num per queue*/ u32 buf_size; /* ring buffer size */ @@ -290,7 +292,7 @@ struct dsaf_device { struct ppe_common_cb *ppe_common[DSAF_COMM_DEV_NUM]; struct rcb_common_cb *rcb_common[DSAF_COMM_DEV_NUM]; - struct hns_mac_cb *mac_cb; + struct hns_mac_cb *mac_cb[DSAF_MAX_PORT_NUM]; struct dsaf_hw_stats hw_stats[DSAF_NODE_NUM]; struct dsaf_int_stat int_stat; @@ -362,14 +364,6 @@ static inline void hns_dsaf_tbl_line_addr_cfg(struct dsaf_device *dsaf_dev, tab_line_addr); } -static inline int hns_dsaf_get_comm_idx_by_port(int port) -{ - if ((port < DSAF_COMM_CHN) || (port == DSAF_MAX_PORT_NUM_PER_CHIP)) - return 0; - else - return (port - DSAF_COMM_CHN + 1); -} - static inline struct hnae_vf_cb *hns_ae_get_vf_cb( struct hnae_handle *handle) { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 67c8b9e8b90f..972eab0ad89d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -12,6 +12,26 @@ #include "hns_dsaf_ppe.h" #include "hns_dsaf_reg.h" +static void dsaf_write_sub(struct dsaf_device *dsaf_dev, u32 reg, u32 val) +{ + if (dsaf_dev->sub_ctrl) + dsaf_write_syscon(dsaf_dev->sub_ctrl, reg, val); + else + dsaf_write_reg(dsaf_dev->sc_base, reg, val); +} + +static u32 dsaf_read_sub(struct dsaf_device *dsaf_dev, u32 reg) +{ + u32 ret; + + if (dsaf_dev->sub_ctrl) + ret = dsaf_read_syscon(dsaf_dev->sub_ctrl, reg); + else + ret = dsaf_read_reg(dsaf_dev->sc_base, reg); + + return ret; +} + void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, u16 speed, int data) { @@ -95,10 +115,8 @@ void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val) nt_reg_addr = DSAF_SUB_SC_NT_RESET_DREQ_REG; } - dsaf_write_reg(dsaf_dev->sc_base, xbar_reg_addr, - RESET_REQ_OR_DREQ); - dsaf_write_reg(dsaf_dev->sc_base, nt_reg_addr, - RESET_REQ_OR_DREQ); + dsaf_write_sub(dsaf_dev, xbar_reg_addr, RESET_REQ_OR_DREQ); + dsaf_write_sub(dsaf_dev, nt_reg_addr, RESET_REQ_OR_DREQ); } void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) @@ -121,7 +139,7 @@ void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) else reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; - dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); + dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, @@ -144,7 +162,7 @@ void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, else reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; - dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); + dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) @@ -164,20 +182,16 @@ void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) reg_val_2 = 0x2082082 << port; if (val == 0) { - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_GE_RESET_REQ1_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG, reg_val_1); - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_GE_RESET_REQ0_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ0_REG, reg_val_2); } else { - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_GE_RESET_DREQ0_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_DREQ0_REG, reg_val_2); - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_GE_RESET_DREQ1_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_DREQ1_REG, reg_val_1); } } else { @@ -185,20 +199,16 @@ void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) reg_val_2 = 0x100 << dsaf_dev->reset_offset; if (val == 0) { - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_GE_RESET_REQ1_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG, reg_val_1); - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_PPE_RESET_REQ_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_PPE_RESET_REQ_REG, reg_val_2); } else { - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_GE_RESET_DREQ1_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_DREQ1_REG, reg_val_1); - dsaf_write_reg(dsaf_dev->sc_base, - DSAF_SUB_SC_PPE_RESET_DREQ_REG, + dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_PPE_RESET_DREQ_REG, reg_val_2); } } @@ -220,7 +230,7 @@ void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) else reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; - dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); + dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) @@ -245,7 +255,7 @@ void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; } - dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); + dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } /** @@ -260,7 +270,6 @@ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) u32 shift; u32 phy_offset; bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); - void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr; int mac_id = mac_cb->mac_id; phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; @@ -269,7 +278,7 @@ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) } else if (mac_id >= 0 && mac_id <= 3 && !HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) { reg = is_ver1 ? HNS_MAC_HILINK4_REG : HNS_MAC_HILINK4V2_REG; - mode = dsaf_read_reg(sys_ctl_vaddr, reg); + mode = dsaf_read_sub(mac_cb->dsaf_dev, reg); /* mac_id 0, 1, 2, 3 ---> hilink4 lane 0, 1, 2, 3 */ shift = is_ver1 ? 0 : mac_id; if (dsaf_get_bit(mode, shift)) @@ -278,7 +287,7 @@ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) phy_if = PHY_INTERFACE_MODE_SGMII; } else { reg = is_ver1 ? HNS_MAC_HILINK3_REG : HNS_MAC_HILINK3V2_REG; - mode = dsaf_read_reg(sys_ctl_vaddr, reg); + mode = dsaf_read_sub(mac_cb->dsaf_dev, reg); /* mac_id 4, 5,---> hilink3 lane 2, 3 * debug port 0(6), 1(7) ---> hilink3 lane 0, 1 */ @@ -328,7 +337,14 @@ int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en) pr_info("no sfp in this eth\n"); } - dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, !!en); + if (mac_cb->serdes_ctrl) { + u32 origin = dsaf_read_syscon(mac_cb->serdes_ctrl, reg_offset); + + dsaf_set_field(origin, 1ull << 10, 10, !!en); + dsaf_write_syscon(mac_cb->serdes_ctrl, reg_offset, origin); + } else { + dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, !!en); + } return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c index 3f59a8a30c86..8cd151a5245e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -61,22 +61,10 @@ void hns_ppe_set_indir_table(struct hns_ppe_cb *ppe_cb, } } -static void __iomem *hns_ppe_common_get_ioaddr( - struct ppe_common_cb *ppe_common) +static void __iomem * +hns_ppe_common_get_ioaddr(struct ppe_common_cb *ppe_common) { - void __iomem *base_addr; - - int idx = ppe_common->comm_index; - - if (!HNS_DSAF_IS_DEBUG(ppe_common->dsaf_dev)) - base_addr = ppe_common->dsaf_dev->ppe_base - + PPE_COMMON_REG_OFFSET; - else - base_addr = ppe_common->dsaf_dev->sds_base - + (idx - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET - + PPE_COMMON_REG_OFFSET; - - return base_addr; + return ppe_common->dsaf_dev->ppe_base + PPE_COMMON_REG_OFFSET; } /** @@ -124,32 +112,8 @@ void hns_ppe_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index) static void __iomem *hns_ppe_get_iobase(struct ppe_common_cb *ppe_common, int ppe_idx) { - void __iomem *base_addr; - int common_idx = ppe_common->comm_index; - - if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) { - base_addr = ppe_common->dsaf_dev->ppe_base + - ppe_idx * PPE_REG_OFFSET; - - } else { - base_addr = ppe_common->dsaf_dev->sds_base + - (common_idx - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET; - } - return base_addr; -} - -static int hns_ppe_get_port(struct ppe_common_cb *ppe_common, int idx) -{ - int port; - - if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) - port = idx; - else - port = HNS_PPE_SERVICE_NW_ENGINE_NUM - + ppe_common->comm_index - 1; - - return port; + return ppe_common->dsaf_dev->ppe_base + ppe_idx * PPE_REG_OFFSET; } static void hns_ppe_get_cfg(struct ppe_common_cb *ppe_common) @@ -164,7 +128,6 @@ static void hns_ppe_get_cfg(struct ppe_common_cb *ppe_common) ppe_cb->next = NULL; ppe_cb->ppe_common_cb = ppe_common; ppe_cb->index = i; - ppe_cb->port = hns_ppe_get_port(ppe_common, i); ppe_cb->io_base = hns_ppe_get_iobase(ppe_common, i); ppe_cb->virq = 0; } @@ -318,7 +281,7 @@ static void hns_ppe_exc_irq_en(struct hns_ppe_cb *ppe_cb, int en) static void hns_ppe_init_hw(struct hns_ppe_cb *ppe_cb) { struct ppe_common_cb *ppe_common_cb = ppe_cb->ppe_common_cb; - u32 port = ppe_cb->port; + u32 port = ppe_cb->index; struct dsaf_device *dsaf_dev = ppe_common_cb->dsaf_dev; int i; @@ -377,7 +340,8 @@ void hns_ppe_uninit_ex(struct ppe_common_cb *ppe_common) u32 i; for (i = 0; i < ppe_common->ppe_num; i++) { - hns_ppe_uninit_hw(&ppe_common->ppe_cb[i]); + if (ppe_common->dsaf_dev->mac_cb[i]) + hns_ppe_uninit_hw(&ppe_common->ppe_cb[i]); memset(&ppe_common->ppe_cb[i], 0, sizeof(struct hns_ppe_cb)); } } @@ -410,8 +374,11 @@ void hns_ppe_reset_common(struct dsaf_device *dsaf_dev, u8 ppe_common_index) if (ret) return; - for (i = 0; i < ppe_common->ppe_num; i++) - hns_ppe_init_hw(&ppe_common->ppe_cb[i]); + for (i = 0; i < ppe_common->ppe_num; i++) { + /* We only need to initiate ppe when the port exists */ + if (dsaf_dev->mac_cb[i]) + hns_ppe_init_hw(&ppe_common->ppe_cb[i]); + } ret = hns_rcb_common_init_hw(dsaf_dev->rcb_common[ppe_common_index]); if (ret) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h index e9c0ec2fa0dd..9d8e643e8aa6 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h @@ -80,7 +80,6 @@ struct hns_ppe_cb { struct hns_ppe_hw_stats hw_stats; u8 index; /* index in a ppe common device */ - u8 port; /* port id in dsaf */ void __iomem *io_base; int virq; u32 rss_indir_table[HNS_PPEV2_RSS_IND_TBL_SIZE]; /*shadow indir tab */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 054f391a3eeb..4ef6d23d998e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -430,17 +430,8 @@ static void hns_rcb_ring_pair_get_cfg(struct ring_pair_cb *ring_pair_cb) static int hns_rcb_get_port_in_comm( struct rcb_common_cb *rcb_common, int ring_idx) { - int port; - int q_num; - if (!HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) { - q_num = (int)rcb_common->max_q_per_vf * rcb_common->max_vfn; - port = ring_idx / q_num; - } else { - port = 0; /* config debug-ports port_id_in_comm to 0*/ - } - - return port; + return ring_idx / (rcb_common->max_q_per_vf * rcb_common->max_vfn); } #define SERVICE_RING_IRQ_IDX(v1) \ @@ -658,42 +649,18 @@ int hns_rcb_get_ring_num(struct dsaf_device *dsaf_dev) } } -void __iomem *hns_rcb_common_get_vaddr(struct dsaf_device *dsaf_dev, - int comm_index) +void __iomem *hns_rcb_common_get_vaddr(struct rcb_common_cb *rcb_common) { - void __iomem *base_addr; - - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) - base_addr = dsaf_dev->ppe_base + RCB_COMMON_REG_OFFSET; - else - base_addr = dsaf_dev->sds_base - + (comm_index - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET - + RCB_COMMON_REG_OFFSET; + struct dsaf_device *dsaf_dev = rcb_common->dsaf_dev; - return base_addr; + return dsaf_dev->ppe_base + RCB_COMMON_REG_OFFSET; } -static phys_addr_t hns_rcb_common_get_paddr(struct dsaf_device *dsaf_dev, - int comm_index) +static phys_addr_t hns_rcb_common_get_paddr(struct rcb_common_cb *rcb_common) { - struct device_node *np = dsaf_dev->dev->of_node; - phys_addr_t phy_addr; - const __be32 *tmp_addr; - u64 addr_offset = 0; - u64 size = 0; - int index = 0; - - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { - index = 2; - addr_offset = RCB_COMMON_REG_OFFSET; - } else { - index = 1; - addr_offset = (comm_index - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET + - RCB_COMMON_REG_OFFSET; - } - tmp_addr = of_get_address(np, index, &size, NULL); - phy_addr = of_translate_address(np, tmp_addr); - return phy_addr + addr_offset; + struct dsaf_device *dsaf_dev = rcb_common->dsaf_dev; + + return dsaf_dev->ppe_paddr + RCB_COMMON_REG_OFFSET; } int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, @@ -722,8 +689,8 @@ int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, rcb_common->max_vfn = max_vfn; rcb_common->max_q_per_vf = max_q_per_vf; - rcb_common->io_base = hns_rcb_common_get_vaddr(dsaf_dev, comm_index); - rcb_common->phy_base = hns_rcb_common_get_paddr(dsaf_dev, comm_index); + rcb_common->io_base = hns_rcb_common_get_vaddr(rcb_common); + rcb_common->phy_base = hns_rcb_common_get_paddr(rcb_common); dsaf_dev->rcb_common[comm_index] = rcb_common; return 0; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 6a03c94821d5..7c3b5103d151 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -11,16 +11,15 @@ #define _DSAF_REG_H_ #include -#define HNS_DEBUG_RING_IRQ_IDX 0 -#define HNS_SERVICE_RING_IRQ_IDX 59 -#define HNSV2_SERVICE_RING_IRQ_IDX 25 +#define HNS_DEBUG_RING_IRQ_IDX 0 +#define HNS_SERVICE_RING_IRQ_IDX 59 +#define HNSV2_SERVICE_RING_IRQ_IDX 25 -#define DSAF_MAX_PORT_NUM_PER_CHIP 8 -#define DSAF_SERVICE_PORT_NUM_PER_DSAF 6 -#define DSAF_MAX_VM_NUM 128 +#define DSAF_MAX_PORT_NUM 6 +#define DSAF_MAX_VM_NUM 128 -#define DSAF_COMM_DEV_NUM 3 -#define DSAF_PPE_INODE_BASE 6 +#define DSAF_COMM_DEV_NUM 1 +#define DSAF_PPE_INODE_BASE 6 #define DSAF_DEBUG_NW_NUM 2 #define DSAF_SERVICE_NW_NUM 6 #define DSAF_COMM_CHN DSAF_SERVICE_NW_NUM -- GitLab From 31d4446dca9112ce7b9eada8e6d631a7580e2feb Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:12 +0800 Subject: [PATCH 4370/9938] net: hns: add attribute cpld_ctrl for dsaf port node This patch adds attribute cpld_ctrl for dsaf port node, parses the syscon for mac_cb from dts, and changes the method of access the cpld related registers through syscon. Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 2 +- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 38 ++++++++++--------- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 3 +- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 5 --- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 1 - .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 36 +++++++++++++----- 6 files changed, 51 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 58341dad8042..7a757e88c89a 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -664,7 +664,7 @@ void hns_ae_update_led_status(struct hnae_handle *handle) assert(handle); mac_cb = hns_get_mac_cb(handle); - if (!mac_cb->cpld_vaddr) + if (!mac_cb->cpld_ctrl) return; hns_set_led_opt(mac_cb); } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index a731777415dc..7073ca23af56 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -82,17 +82,6 @@ static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb) } } -int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt) -{ - if (!mac_cb->cpld_vaddr) - return -ENODEV; - - *sfp_prsnt = !dsaf_read_b((u8 *)mac_cb->cpld_vaddr - + MAC_SFP_PORT_OFFSET); - - return 0; -} - void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status) { struct mac_driver *mac_ctrl_drv; @@ -658,6 +647,8 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) { struct device_node *np = mac_cb->dev->of_node; struct regmap *syscon; + u32 ret; + mac_cb->link = false; mac_cb->half_duplex = false; mac_cb->speed = mac_phy_to_speed[mac_cb->phy_if]; @@ -701,6 +692,23 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) return -EINVAL; } mac_cb->serdes_ctrl = syscon; + + syscon = syscon_node_to_regmap( + of_parse_phandle(to_of_node(mac_cb->fw_port), + "cpld-syscon", 0)); + if (IS_ERR_OR_NULL(syscon)) { + dev_dbg(mac_cb->dev, "no cpld-syscon found!\n"); + mac_cb->cpld_ctrl = NULL; + } else { + mac_cb->cpld_ctrl = syscon; + ret = fwnode_property_read_u32(mac_cb->fw_port, + "cpld-ctrl-reg", + &mac_cb->cpld_ctrl_reg); + if (ret) { + dev_err(mac_cb->dev, "get cpld-ctrl-reg fail!\n"); + return ret; + } + } return 0; } @@ -751,11 +759,6 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, struct hns_mac_cb *mac_cb) mac_cb->sys_ctl_vaddr = dsaf_dev->sc_base; mac_cb->serdes_vaddr = dsaf_dev->sds_base; - if (dsaf_dev->cpld_base && !HNS_DSAF_IS_DEBUG(dsaf_dev)) { - mac_cb->cpld_vaddr = dsaf_dev->cpld_base + - mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET; - cpld_led_reset(mac_cb); - } mac_cb->sfp_prsnt = 0; mac_cb->txpkt_for_led = 0; mac_cb->rxpkt_for_led = 0; @@ -780,6 +783,7 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, struct hns_mac_cb *mac_cb) if (ret) return ret; + cpld_led_reset(mac_cb); mac_cb->vaddr = hns_mac_get_vaddr(dsaf_dev, mac_cb, mac_mode_idx); return 0; @@ -956,7 +960,7 @@ void hns_set_led_opt(struct hns_mac_cb *mac_cb) int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb, enum hnae_led_state status) { - if (!mac_cb || !mac_cb->cpld_vaddr) + if (!mac_cb || !mac_cb->cpld_ctrl) return 0; return cpld_set_led_id(mac_cb, status); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 45c5f16ae735..719816bf4606 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -313,10 +313,11 @@ struct hns_mac_cb { struct mac_priv priv; struct fwnode_handle *fw_port; u8 __iomem *vaddr; - u8 __iomem *cpld_vaddr; u8 __iomem *sys_ctl_vaddr; u8 __iomem *serdes_vaddr; struct regmap *serdes_ctrl; + struct regmap *cpld_ctrl; + u32 cpld_ctrl_reg; struct mac_entry_idx addr_entry_idx[DSAF_MAX_VM_NUM]; u8 sfp_prsnt; u8 cpld_led_value; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 33cdb215a547..1c2ddb25e776 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -189,8 +189,6 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) iounmap(dsaf_dev->sds_base); if (dsaf_dev->sc_base) iounmap(dsaf_dev->sc_base); - if (dsaf_dev->cpld_base) - iounmap(dsaf_dev->cpld_base); return ret; } @@ -207,9 +205,6 @@ static void hns_dsaf_free_cfg(struct dsaf_device *dsaf_dev) if (dsaf_dev->sc_base) iounmap(dsaf_dev->sc_base); - - if (dsaf_dev->cpld_base) - iounmap(dsaf_dev->cpld_base); } /** diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index a48ef2644355..f0502ba0a677 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -277,7 +277,6 @@ struct dsaf_device { u8 __iomem *sds_base; u8 __iomem *ppe_base; u8 __iomem *io_base; - u8 __iomem *cpld_base; struct regmap *sub_ctrl; phys_addr_t ppe_paddr; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 972eab0ad89d..c549aa832df7 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -42,8 +42,8 @@ void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, pr_err("sfp_led_opt mac_dev is null!\n"); return; } - if (!mac_cb->cpld_vaddr) { - dev_err(mac_cb->dev, "mac_id=%d, cpld_vaddr is null !\n", + if (!mac_cb->cpld_ctrl) { + dev_err(mac_cb->dev, "mac_id=%d, cpld syscon is null !\n", mac_cb->mac_id); return; } @@ -60,21 +60,24 @@ void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, dsaf_set_bit(value, DSAF_LED_DATA_B, data); if (value != mac_cb->cpld_led_value) { - dsaf_write_b(mac_cb->cpld_vaddr, value); + dsaf_write_syscon(mac_cb->cpld_ctrl, + mac_cb->cpld_ctrl_reg, value); mac_cb->cpld_led_value = value; } } else { - dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE); + dsaf_write_syscon(mac_cb->cpld_ctrl, mac_cb->cpld_ctrl_reg, + CPLD_LED_DEFAULT_VALUE); mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; } } void cpld_led_reset(struct hns_mac_cb *mac_cb) { - if (!mac_cb || !mac_cb->cpld_vaddr) + if (!mac_cb || !mac_cb->cpld_ctrl) return; - dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE); + dsaf_write_syscon(mac_cb->cpld_ctrl, mac_cb->cpld_ctrl_reg, + CPLD_LED_DEFAULT_VALUE); mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; } @@ -83,15 +86,19 @@ int cpld_set_led_id(struct hns_mac_cb *mac_cb, { switch (status) { case HNAE_LED_ACTIVE: - mac_cb->cpld_led_value = dsaf_read_b(mac_cb->cpld_vaddr); + mac_cb->cpld_led_value = + dsaf_read_syscon(mac_cb->cpld_ctrl, + mac_cb->cpld_ctrl_reg); dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, CPLD_LED_ON_VALUE); - dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); + dsaf_write_syscon(mac_cb->cpld_ctrl, mac_cb->cpld_ctrl_reg, + mac_cb->cpld_led_value); return 2; case HNAE_LED_INACTIVE: dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, CPLD_LED_DEFAULT_VALUE); - dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); + dsaf_write_syscon(mac_cb->cpld_ctrl, mac_cb->cpld_ctrl_reg, + mac_cb->cpld_led_value); break; default: break; @@ -301,6 +308,17 @@ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) return phy_if; } +int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt) +{ + if (!mac_cb->cpld_ctrl) + return -ENODEV; + + *sfp_prsnt = !dsaf_read_syscon(mac_cb->cpld_ctrl, mac_cb->cpld_ctrl_reg + + MAC_SFP_PORT_OFFSET); + + return 0; +} + /** * hns_mac_config_sds_loopback - set loop back for serdes * @mac_cb: mac control block -- GitLab From 850bfa3b78ea8849fef78ed74f5f2ccf947db0ca Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:13 +0800 Subject: [PATCH 4371/9938] net: hns: add attribute port-rst-offset for dsaf port node The reset offset for each port in a dsaf is different. The current code is not so readability. This patch adds configuration named port-rst-offset to make the code simple and more readability. If this attribute doesn't exist, default value of this attribute is equal to its port index. Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 10 ++++++++ .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 1 + .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 25 ++++++------------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 7073ca23af56..52d757df623e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -664,6 +664,7 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) mac_cb->max_frm = MAC_DEFAULT_MTU; mac_cb->tx_pause_frm_time = MAC_DEFAULT_PAUSE_TIME; + mac_cb->port_rst_off = mac_cb->mac_id; /* if the dsaf node doesn't contain a port subnode, get phy-handle * from dsaf node @@ -693,6 +694,15 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) } mac_cb->serdes_ctrl = syscon; + ret = fwnode_property_read_u32(mac_cb->fw_port, + "port-rst-offset", + &mac_cb->port_rst_off); + if (ret) { + dev_dbg(mac_cb->dev, + "mac%d port-rst-offset not found, use default value.\n", + mac_cb->mac_id); + } + syscon = syscon_node_to_regmap( of_parse_phandle(to_of_node(mac_cb->fw_port), "cpld-syscon", 0)); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 719816bf4606..7be71043133b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -318,6 +318,7 @@ struct hns_mac_cb { struct regmap *serdes_ctrl; struct regmap *cpld_ctrl; u32 cpld_ctrl_reg; + u32 port_rst_off; struct mac_entry_idx addr_entry_idx[DSAF_MAX_VM_NUM]; u8 sfp_prsnt; u8 cpld_led_value; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index c549aa832df7..e549a11420b4 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -135,11 +135,7 @@ void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) return; reg_val |= RESET_REQ_OR_DREQ; - - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) - reg_val |= 0x2082082 << port; - else - reg_val |= 0x2082082 << (dsaf_dev->reset_offset + 6); + reg_val |= 0x2082082 << dsaf_dev->mac_cb[port]->port_rst_off; if (val == 0) reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; @@ -158,11 +154,8 @@ void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, if (port >= DSAF_XGE_NUM) return; - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) - reg_val |= XGMAC_TRX_CORE_SRST_M << port; - else - reg_val |= XGMAC_TRX_CORE_SRST_M << - (dsaf_dev->reset_offset + 6); + reg_val |= XGMAC_TRX_CORE_SRST_M + << dsaf_dev->mac_cb[port]->port_rst_off; if (val == 0) reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; @@ -176,17 +169,19 @@ void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) { u32 reg_val_1; u32 reg_val_2; + u32 port_rst_off; if (port >= DSAF_GE_NUM) return; if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { reg_val_1 = 0x1 << port; + port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off; /* there is difference between V1 and V2 in register.*/ if (AE_IS_VER1(dsaf_dev->dsaf_ver)) - reg_val_2 = 0x1041041 << port; + reg_val_2 = 0x1041041 << port_rst_off; else - reg_val_2 = 0x2082082 << port; + reg_val_2 = 0x2082082 << port_rst_off; if (val == 0) { dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG, @@ -226,11 +221,7 @@ void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) u32 reg_val = 0; u32 reg_addr; - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) - reg_val |= RESET_REQ_OR_DREQ << port; - else - reg_val |= RESET_REQ_OR_DREQ << - (dsaf_dev->reset_offset + 6); + reg_val |= RESET_REQ_OR_DREQ << dsaf_dev->mac_cb[port]->port_rst_off; if (val == 0) reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; -- GitLab From 0d768fc62def08628affa4a2abe4f319926027a9 Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:14 +0800 Subject: [PATCH 4372/9938] net: hns: add attribute port-mode-offset for dsaf port node Port mode offset for each dsaf port is different. The current code is not so readability. This patch adds configuration named port-mode-offset to make the code simple and more readability. If port-mode-offset isn't exists, default value 0 will be used. Signed-off-by: Daode Huang Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 10 +++++ .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 1 + .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 44 ++++++++----------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 52d757df623e..1c8fdd316ca0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -665,6 +665,7 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) mac_cb->max_frm = MAC_DEFAULT_MTU; mac_cb->tx_pause_frm_time = MAC_DEFAULT_PAUSE_TIME; mac_cb->port_rst_off = mac_cb->mac_id; + mac_cb->port_mode_off = 0; /* if the dsaf node doesn't contain a port subnode, get phy-handle * from dsaf node @@ -703,6 +704,15 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) mac_cb->mac_id); } + ret = fwnode_property_read_u32(mac_cb->fw_port, + "port-mode-offset", + &mac_cb->port_mode_off); + if (ret) { + dev_dbg(mac_cb->dev, + "mac%d port-mode-offset not found, use default value.\n", + mac_cb->mac_id); + } + syscon = syscon_node_to_regmap( of_parse_phandle(to_of_node(mac_cb->fw_port), "cpld-syscon", 0)); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 7be71043133b..97ce9a750aaf 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -319,6 +319,7 @@ struct hns_mac_cb { struct regmap *cpld_ctrl; u32 cpld_ctrl_reg; u32 port_rst_off; + u32 port_mode_off; struct mac_entry_idx addr_entry_idx[DSAF_MAX_VM_NUM]; u8 sfp_prsnt; u8 cpld_led_value; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index e549a11420b4..a837bb9e3839 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -265,37 +265,31 @@ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) { u32 mode; u32 reg; - u32 shift; - u32 phy_offset; bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); int mac_id = mac_cb->mac_id; - phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; + phy_interface_t phy_if; - if (is_ver1 && HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) { - phy_if = PHY_INTERFACE_MODE_SGMII; - } else if (mac_id >= 0 && mac_id <= 3 && - !HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) { - reg = is_ver1 ? HNS_MAC_HILINK4_REG : HNS_MAC_HILINK4V2_REG; - mode = dsaf_read_sub(mac_cb->dsaf_dev, reg); - /* mac_id 0, 1, 2, 3 ---> hilink4 lane 0, 1, 2, 3 */ - shift = is_ver1 ? 0 : mac_id; - if (dsaf_get_bit(mode, shift)) - phy_if = PHY_INTERFACE_MODE_XGMII; + if (is_ver1) { + if (HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) + return PHY_INTERFACE_MODE_SGMII; + + if (mac_id >= 0 && mac_id <= 3) + reg = HNS_MAC_HILINK4_REG; else - phy_if = PHY_INTERFACE_MODE_SGMII; - } else { - reg = is_ver1 ? HNS_MAC_HILINK3_REG : HNS_MAC_HILINK3V2_REG; - mode = dsaf_read_sub(mac_cb->dsaf_dev, reg); - /* mac_id 4, 5,---> hilink3 lane 2, 3 - * debug port 0(6), 1(7) ---> hilink3 lane 0, 1 - */ - phy_offset = mac_cb->dsaf_dev->reset_offset - 1; - shift = is_ver1 ? 0 : mac_id >= 4 ? mac_id - 2 : phy_offset; - if (dsaf_get_bit(mode, shift)) - phy_if = PHY_INTERFACE_MODE_XGMII; + reg = HNS_MAC_HILINK3_REG; + } else{ + if (!HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev) && mac_id <= 3) + reg = HNS_MAC_HILINK4V2_REG; else - phy_if = PHY_INTERFACE_MODE_SGMII; + reg = HNS_MAC_HILINK3V2_REG; } + + mode = dsaf_read_sub(mac_cb->dsaf_dev, reg); + if (dsaf_get_bit(mode, mac_cb->port_mode_off)) + phy_if = PHY_INTERFACE_MODE_XGMII; + else + phy_if = PHY_INTERFACE_MODE_SGMII; + return phy_if; } -- GitLab From 2fc695a1bb00141a0f5df74e7a19e125f4babaa5 Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:15 +0800 Subject: [PATCH 4373/9938] Documentation: Bindings: Update DT binding for separating dsaf dev support Because debug dsaf port was separated from service dsaf port, this patch updates the related information of DT binding. Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../bindings/net/hisilicon-hns-dsaf.txt | 59 +++++++++++++++---- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt index ecacfa44b1eb..5ccd4f002a67 100644 --- a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt +++ b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt @@ -7,19 +7,47 @@ Required properties: - mode: dsa fabric mode string. only support one of dsaf modes like these: "2port-64vf", "6port-16rss", - "6port-16vf". + "6port-16vf", + "single-port". - interrupt-parent: the interrupt parent of this device. - interrupts: should contain the DSA Fabric and rcb interrupt. - reg: specifies base physical address(es) and size of the device registers. - The first region is external interface control register base and size. - The second region is SerDes base register and size. + The first region is external interface control register base and size(optional, + only be used when subctrl-syscon is not exists). It is recommended using + subctrl-syscon rather than this address. + The second region is SerDes base register and size(optional, only be used when + serdes-syscon in port node is not exists. It is recommended using + serdes-syscon rather than this address. The third region is the PPE register base and size. - The fourth region is dsa fabric base register and size. - The fifth region is cpld base register and size, it is not required if do not use cpld. -- phy-handle: phy handle of physicl port, 0 if not any phy device. see ethernet.txt [1]. + The fourth region is dsa fabric base register and size. It is not required for + single-port mode. +- reg-names: may be ppe-base and(or) dsaf-base. It is used to find the + corresponding reg's index. + +- phy-handle: phy handle of physicl port, 0 if not any phy device. It is optional + attribute. If port node is exists, phy-handle in each port node will be used. + see ethernet.txt [1]. +- subctrl-syscon: is syscon handle for external interface control register. +- reset-field-offset: is offset of reset field. Its value depends on the hardware + user manual. - buf-size: rx buffer size, should be 16-1024. - desc-num: number of description in TX and RX queue, should be 512, 1024, 2048 or 4096. +- port: subnodes of dsaf. A dsaf node may contain several port nodes(Depending + on mode of dsaf). Port node contain some attributes listed below: +- port-id: is physical port index in one dsaf. +- phy-handle: phy handle of physicl port. It is not required if there isn't + phy device. see ethernet.txt [1]. +- serdes-syscon: is syscon handle for SerDes register. +- cpld-syscon: is syscon handle for cpld register. It is not required if there + isn't cpld device. +- cpld-ctrl-reg: is cpld register offset. It is not required if there isn't + cpld-syscon. +- port-rst-offset: is offset of reset field for each port in dsaf. Its value + depends on the hardware user manual. +- port-mode-offset: is offset of port mode field for each port in dsaf. Its + value depends on the hardware user manual. + [1] Documentation/devicetree/bindings/net/phy.txt Example: @@ -28,11 +56,11 @@ dsaf0: dsa@c7000000 { compatible = "hisilicon,hns-dsaf-v1"; mode = "6port-16rss"; interrupt-parent = <&mbigen_dsa>; - reg = <0x0 0xC0000000 0x0 0x420000 - 0x0 0xC2000000 0x0 0x300000 - 0x0 0xc5000000 0x0 0x890000 + reg = <0x0 0xc5000000 0x0 0x890000 0x0 0xc7000000 0x0 0x60000>; - phy-handle = <0 0 0 0 &soc0_phy4 &soc0_phy5 0 0>; + reg-names = "ppe-base", "dsaf-base"; + subctrl-syscon = <&subctrl>; + reset-field-offset = 0; interrupts = <131 4>,<132 4>, <133 4>,<134 4>, <135 4>,<136 4>, <137 4>,<138 4>, <139 4>,<140 4>, <141 4>,<142 4>, @@ -43,4 +71,15 @@ dsaf0: dsa@c7000000 { buf-size = <4096>; desc-num = <1024>; dma-coherent; + + prot@0 { + port-id = 0; + phy-handle = <&phy0>; + serdes-syscon = <&serdes>; + }; + + prot@1 { + port-id = 1; + serdes-syscon = <&serdes>; + }; }; -- GitLab From c132cdccb71ee000d6456ec63acdf0535b5f35da Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:16 +0800 Subject: [PATCH 4374/9938] Documentation: Bindings: add port-idx-in-ae for enet node This patch adds description for port-idx-in-ae attribute. Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../bindings/net/hisilicon-hns-nic.txt | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt index e6a9d1c30878..b9ff4ba6454e 100644 --- a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt +++ b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt @@ -36,6 +36,34 @@ Required properties: | | | | | | external port + This attribute is remained for compatible purpose. It is not recommended to + use it in new code. + +- port-idx-in-ae: is the index of port provided by AE. + In NIC mode of DSAF, all 6 PHYs of service DSAF are taken as ethernet ports + to the CPU. The port-idx-in-ae can be 0 to 5. Here is the diagram: + +-----+---------------+ + | CPU | + +-+-+-+---+-+-+-+-+-+-+ + | | | | | | | | + debug debug service + port port port + (0) (0) (0-5) + + In Switch mode of DSAF, all 6 PHYs of service DSAF are taken as physical + ports connected to a LAN Switch while the CPU side assume itself have one + single NIC connected to this switch. In this case, the port-idx-in-ae + will be 0 only. + +-----+-----+------+------+ + | CPU | + +-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | service| port(0) + debug debug +------------+ + port port | switch | + (0) (0) +-+-+-+-+-+-++ + | | | | | | + external port + - local-mac-address: mac addr of the ethernet interface Example: @@ -43,6 +71,6 @@ Example: ethernet@0{ compatible = "hisilicon,hns-nic-v1"; ae-handle = <&dsaf0>; - port-id = <0>; + port-idx-in-ae = <0>; local-mac-address = [a2 14 e4 4b 56 76]; }; -- GitLab From 218afd68a2e6de8226c4048e4dd051075648a9c6 Mon Sep 17 00:00:00 2001 From: "Yisen.Zhuang\\(Zhuangyuzeng\\)" Date: Sat, 23 Apr 2016 17:05:17 +0800 Subject: [PATCH 4375/9938] dts: hisi: update hns dst for separating dsaf dev support Because debug dsaf port was separated from service dsaf port, this patch updates the related configurations of hns dts, changes it to match with the new binding files. This also removes enet nodes which don't exist in d02 board. Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi | 72 ++++++++------------ 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi index 933cba359918..7d625141c917 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi @@ -28,13 +28,13 @@ soc0: soc@000000000 { mode = "6port-16rss"; interrupt-parent = <&mbigen_dsa>; - reg = <0x0 0xC0000000 0x0 0x420000 - 0x0 0xC2000000 0x0 0x300000 - 0x0 0xc5000000 0x0 0x890000 + reg = <0x0 0xc5000000 0x0 0x890000 0x0 0xc7000000 0x0 0x60000 >; - phy-handle = <0 0 0 0 &soc0_phy0 &soc0_phy1 0 0>; + reg-names = "ppe-base","dsaf-base"; + subctrl-syscon = <&dsaf_subctrl>; + reset-field-offset = <0>; interrupts = < /* [14] ge fifo err 8 / xge 6**/ 149 0x4 150 0x4 151 0x4 152 0x4 @@ -122,12 +122,31 @@ soc0: soc@000000000 { buf-size = <4096>; desc-num = <1024>; dma-coherent; + + port@0 { + port-id = <0>; + serdes-syscon = <&serdes_ctrl0>; + }; + port@1 { + port-id = <1>; + serdes-syscon = <&serdes_ctrl0>; + }; + port@4 { + port-id = <4>; + phy-handle = <&soc0_phy0>; + serdes-syscon = <&serdes_ctrl1>; + }; + port@5 { + port-id = <5>; + phy-handle = <&soc0_phy1>; + serdes-syscon = <&serdes_ctrl1>; + }; }; eth0: ethernet@0{ compatible = "hisilicon,hns-nic-v1"; ae-handle = <&dsaf0>; - port-id = <0>; + port-idx-in-ae = <0>; local-mac-address = [00 00 00 01 00 58]; status = "disabled"; dma-coherent; @@ -135,56 +154,25 @@ soc0: soc@000000000 { eth1: ethernet@1{ compatible = "hisilicon,hns-nic-v1"; ae-handle = <&dsaf0>; - port-id = <1>; + port-idx-in-ae = <1>; + local-mac-address = [00 00 00 01 00 59]; status = "disabled"; dma-coherent; }; - eth2: ethernet@2{ + eth2: ethernet@4{ compatible = "hisilicon,hns-nic-v1"; ae-handle = <&dsaf0>; - port-id = <2>; + port-idx-in-ae = <4>; local-mac-address = [00 00 00 01 00 5a]; status = "disabled"; dma-coherent; }; - eth3: ethernet@3{ + eth3: ethernet@5{ compatible = "hisilicon,hns-nic-v1"; ae-handle = <&dsaf0>; - port-id = <3>; + port-idx-in-ae = <5>; local-mac-address = [00 00 00 01 00 5b]; status = "disabled"; dma-coherent; }; - eth4: ethernet@4{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-id = <4>; - local-mac-address = [00 00 00 01 00 5c]; - status = "disabled"; - dma-coherent; - }; - eth5: ethernet@5{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-id = <5>; - local-mac-address = [00 00 00 01 00 5d]; - status = "disabled"; - dma-coherent; - }; - eth6: ethernet@6{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-id = <6>; - local-mac-address = [00 00 00 01 00 5e]; - status = "disabled"; - dma-coherent; - }; - eth7: ethernet@7{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-id = <7>; - local-mac-address = [00 00 00 01 00 5f]; - status = "disabled"; - dma-coherent; - }; }; -- GitLab From a843311d87b69540641d491b97b328309d3a28a1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 23 Apr 2016 11:07:02 +0200 Subject: [PATCH 4376/9938] net: tsi108: use NULL for pointer-typed argument The first argument of pci_free_consistent has type struct pci_dev *, so use NULL instead of 0. The semantic patch that performs this transformation is as follows: (http://coccinelle.lip6.fr/) // @@ @@ pci_free_consistent( - 0 + NULL , ...) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/tundra/tsi108_eth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index 520cf50a3d5a..01a77145a0fa 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1314,7 +1314,8 @@ static int tsi108_open(struct net_device *dev) data->txring = dma_zalloc_coherent(NULL, txring_size, &data->txdma, GFP_KERNEL); if (!data->txring) { - pci_free_consistent(0, rxring_size, data->rxring, data->rxdma); + pci_free_consistent(NULL, rxring_size, data->rxring, + data->rxdma); return -ENOMEM; } -- GitLab From 351596aad54a7e07de63fde38496656514661b07 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Sat, 23 Apr 2016 11:46:55 -0700 Subject: [PATCH 4377/9938] ila: Add struct definitions and helpers Add structures for identifiers, locators, and an ila address which is composed of a locator and identifier and in6_addr can be cast to it. This includes a three bit type field and enums for the types defined in ILA I-D. In ILA lwt don't allow user to set a translation for a non-ILA address (type of identifier is zero meaning it is an IID). This also requires that the destination prefix is at least 65 bytes (64 bit locator and first byte of identifier). Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- net/ipv6/ila/ila.h | 67 +++++++++++++++++++- net/ipv6/ila/ila_common.c | 11 ++-- net/ipv6/ila/ila_lwt.c | 39 ++++++++---- net/ipv6/ila/ila_xlat.c | 126 +++++++++++++++++++------------------- 4 files changed, 161 insertions(+), 82 deletions(-) diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h index 28542cb2b387..f532967d9ed7 100644 --- a/net/ipv6/ila/ila.h +++ b/net/ipv6/ila/ila.h @@ -23,9 +23,70 @@ #include #include +struct ila_locator { + union { + __u8 v8[8]; + __be16 v16[4]; + __be32 v32[2]; + __be64 v64; + }; +}; + +struct ila_identifier { + union { + struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 __space:5; + u8 type:3; +#elif defined(__BIG_ENDIAN_BITFIELD) + u8 type:3; + u8 __space:5; +#else +#error "Adjust your defines" +#endif + u8 __space2[7]; + }; + __u8 v8[8]; + __be16 v16[4]; + __be32 v32[2]; + __be64 v64; + }; +}; + +enum { + ILA_ATYPE_IID = 0, + ILA_ATYPE_LUID, + ILA_ATYPE_VIRT_V4, + ILA_ATYPE_VIRT_UNI_V6, + ILA_ATYPE_VIRT_MULTI_V6, + ILA_ATYPE_RSVD_1, + ILA_ATYPE_RSVD_2, + ILA_ATYPE_RSVD_3, +}; + +struct ila_addr { + union { + struct in6_addr addr; + struct { + struct ila_locator loc; + struct ila_identifier ident; + }; + }; +}; + +static inline struct ila_addr *ila_a2i(struct in6_addr *addr) +{ + return (struct ila_addr *)addr; +} + +static inline bool ila_addr_is_ila(struct ila_addr *iaddr) +{ + return (iaddr->ident.type != ILA_ATYPE_IID); +} + struct ila_params { - __be64 locator; - __be64 locator_match; + struct ila_locator locator; + struct ila_locator locator_match; __wsum csum_diff; }; @@ -38,7 +99,7 @@ static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to) return csum_partial(diff, sizeof(diff), 0); } -void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p); +void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p); int ila_lwt_init(void); void ila_lwt_fini(void); diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c index 30613050e4ca..c3078d0b64e1 100644 --- a/net/ipv6/ila/ila_common.c +++ b/net/ipv6/ila/ila_common.c @@ -15,17 +15,20 @@ static __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p) { - if (*(__be64 *)&ip6h->daddr == p->locator_match) + struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); + + if (iaddr->loc.v64 == p->locator_match.v64) return p->csum_diff; else - return compute_csum_diff8((__be32 *)&ip6h->daddr, + return compute_csum_diff8((__be32 *)&iaddr->loc, (__be32 *)&p->locator); } -void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) +void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) { __wsum diff; struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); size_t nhoff = sizeof(struct ipv6hdr); /* First update checksum */ @@ -68,7 +71,7 @@ void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) } /* Now change destination address */ - *(__be64 *)&ip6h->daddr = p->locator; + iaddr->loc = p->locator; } static int __init ila_init(void) diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index 9db3621b2126..de7f6d76e928 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c @@ -26,7 +26,7 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) if (skb->protocol != htons(ETH_P_IPV6)) goto drop; - update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate)); + ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate)); return dst->lwtstate->orig_output(net, sk, skb); @@ -42,7 +42,7 @@ static int ila_input(struct sk_buff *skb) if (skb->protocol != htons(ETH_P_IPV6)) goto drop; - update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate)); + ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate)); return dst->lwtstate->orig_input(skb); @@ -64,11 +64,26 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla, size_t encap_len = sizeof(*p); struct lwtunnel_state *newts; const struct fib6_config *cfg6 = cfg; + struct ila_addr *iaddr; int ret; if (family != AF_INET6) return -EINVAL; + if (cfg6->fc_dst_len < sizeof(struct ila_locator) + 1) { + /* Need to have full locator and at least type field + * included in destination + */ + return -EINVAL; + } + + iaddr = (struct ila_addr *)&cfg6->fc_dst; + + if (!ila_addr_is_ila(iaddr)) { + /* Don't allow setting a translation for a non-ILA address */ + return -EINVAL; + } + ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy); if (ret < 0) @@ -84,16 +99,14 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla, newts->len = encap_len; p = ila_params_lwtunnel(newts); - p->locator = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]); + p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]); - if (cfg6->fc_dst_len > sizeof(__be64)) { - /* Precompute checksum difference for translation since we - * know both the old locator and the new one. - */ - p->locator_match = *(__be64 *)&cfg6->fc_dst; - p->csum_diff = compute_csum_diff8( - (__be32 *)&p->locator_match, (__be32 *)&p->locator); - } + /* Precompute checksum difference for translation since we + * know both the old locator and the new one. + */ + p->locator_match = iaddr->loc; + p->csum_diff = compute_csum_diff8( + (__be32 *)&p->locator_match, (__be32 *)&p->locator); newts->type = LWTUNNEL_ENCAP_ILA; newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT | @@ -109,7 +122,7 @@ static int ila_fill_encap_info(struct sk_buff *skb, { struct ila_params *p = ila_params_lwtunnel(lwtstate); - if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator, + if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64, ILA_ATTR_PAD)) goto nla_put_failure; @@ -130,7 +143,7 @@ static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b) struct ila_params *a_p = ila_params_lwtunnel(a); struct ila_params *b_p = ila_params_lwtunnel(b); - return (a_p->locator != b_p->locator); + return (a_p->locator.v64 != b_p->locator.v64); } static const struct lwtunnel_encap_ops ila_encap_ops = { diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 0e9e579410da..020153bc47f5 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -11,13 +11,13 @@ struct ila_xlat_params { struct ila_params ip; - __be64 identifier; + struct ila_identifier identifier; int ifindex; unsigned int dir; }; struct ila_map { - struct ila_xlat_params p; + struct ila_xlat_params xp; struct rhash_head node; struct ila_map __rcu *next; struct rcu_head rcu; @@ -66,31 +66,35 @@ static __always_inline void __ila_hash_secret_init(void) net_get_random_once(&hashrnd, sizeof(hashrnd)); } -static inline u32 ila_identifier_hash(__be64 identifier) +static inline u32 ila_identifier_hash(struct ila_identifier ident) { - u32 *v = (u32 *)&identifier; + u32 *v = (u32 *)ident.v32; return jhash_2words(v[0], v[1], hashrnd); } -static inline spinlock_t *ila_get_lock(struct ila_net *ilan, __be64 identifier) +static inline spinlock_t *ila_get_lock(struct ila_net *ilan, + struct ila_identifier ident) { - return &ilan->locks[ila_identifier_hash(identifier) & ilan->locks_mask]; + return &ilan->locks[ila_identifier_hash(ident) & ilan->locks_mask]; } -static inline int ila_cmp_wildcards(struct ila_map *ila, __be64 loc, - int ifindex, unsigned int dir) +static inline int ila_cmp_wildcards(struct ila_map *ila, + struct ila_addr *iaddr, int ifindex, + unsigned int dir) { - return (ila->p.ip.locator_match && ila->p.ip.locator_match != loc) || - (ila->p.ifindex && ila->p.ifindex != ifindex) || - !(ila->p.dir & dir); + return (ila->xp.ip.locator_match.v64 && + ila->xp.ip.locator_match.v64 != iaddr->loc.v64) || + (ila->xp.ifindex && ila->xp.ifindex != ifindex) || + !(ila->xp.dir & dir); } -static inline int ila_cmp_params(struct ila_map *ila, struct ila_xlat_params *p) +static inline int ila_cmp_params(struct ila_map *ila, + struct ila_xlat_params *xp) { - return (ila->p.ip.locator_match != p->ip.locator_match) || - (ila->p.ifindex != p->ifindex) || - (ila->p.dir != p->dir); + return (ila->xp.ip.locator_match.v64 != xp->ip.locator_match.v64) || + (ila->xp.ifindex != xp->ifindex) || + (ila->xp.dir != xp->dir); } static int ila_cmpfn(struct rhashtable_compare_arg *arg, @@ -98,17 +102,17 @@ static int ila_cmpfn(struct rhashtable_compare_arg *arg, { const struct ila_map *ila = obj; - return (ila->p.identifier != *(__be64 *)arg->key); + return (ila->xp.identifier.v64 != *(__be64 *)arg->key); } static inline int ila_order(struct ila_map *ila) { int score = 0; - if (ila->p.ip.locator_match) + if (ila->xp.ip.locator_match.v64) score += 1 << 0; - if (ila->p.ifindex) + if (ila->xp.ifindex) score += 1 << 1; return score; @@ -117,7 +121,7 @@ static inline int ila_order(struct ila_map *ila) static const struct rhashtable_params rht_params = { .nelem_hint = 1024, .head_offset = offsetof(struct ila_map, node), - .key_offset = offsetof(struct ila_map, p.identifier), + .key_offset = offsetof(struct ila_map, xp.identifier), .key_len = sizeof(u64), /* identifier */ .max_size = 1048576, .min_size = 256, @@ -144,42 +148,43 @@ static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { }; static int parse_nl_config(struct genl_info *info, - struct ila_xlat_params *p) + struct ila_xlat_params *xp) { - memset(p, 0, sizeof(*p)); + memset(xp, 0, sizeof(*xp)); if (info->attrs[ILA_ATTR_IDENTIFIER]) - p->identifier = (__force __be64)nla_get_u64( + xp->identifier.v64 = (__force __be64)nla_get_u64( info->attrs[ILA_ATTR_IDENTIFIER]); if (info->attrs[ILA_ATTR_LOCATOR]) - p->ip.locator = (__force __be64)nla_get_u64( + xp->ip.locator.v64 = (__force __be64)nla_get_u64( info->attrs[ILA_ATTR_LOCATOR]); if (info->attrs[ILA_ATTR_LOCATOR_MATCH]) - p->ip.locator_match = (__force __be64)nla_get_u64( + xp->ip.locator_match.v64 = (__force __be64)nla_get_u64( info->attrs[ILA_ATTR_LOCATOR_MATCH]); if (info->attrs[ILA_ATTR_IFINDEX]) - p->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]); + xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]); if (info->attrs[ILA_ATTR_DIR]) - p->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]); + xp->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]); return 0; } /* Must be called with rcu readlock */ -static inline struct ila_map *ila_lookup_wildcards(__be64 id, __be64 loc, +static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr, int ifindex, unsigned int dir, struct ila_net *ilan) { struct ila_map *ila; - ila = rhashtable_lookup_fast(&ilan->rhash_table, &id, rht_params); + ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->ident, + rht_params); while (ila) { - if (!ila_cmp_wildcards(ila, loc, ifindex, dir)) + if (!ila_cmp_wildcards(ila, iaddr, ifindex, dir)) return ila; ila = rcu_access_pointer(ila->next); } @@ -188,15 +193,15 @@ static inline struct ila_map *ila_lookup_wildcards(__be64 id, __be64 loc, } /* Must be called with rcu readlock */ -static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *p, +static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp, struct ila_net *ilan) { struct ila_map *ila; - ila = rhashtable_lookup_fast(&ilan->rhash_table, &p->identifier, + ila = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier, rht_params); while (ila) { - if (!ila_cmp_params(ila, p)) + if (!ila_cmp_params(ila, xp)) return ila; ila = rcu_access_pointer(ila->next); } @@ -241,11 +246,11 @@ static struct nf_hook_ops ila_nf_hook_ops[] __read_mostly = { }, }; -static int ila_add_mapping(struct net *net, struct ila_xlat_params *p) +static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) { struct ila_net *ilan = net_generic(net, ila_net_id); struct ila_map *ila, *head; - spinlock_t *lock = ila_get_lock(ilan, p->identifier); + spinlock_t *lock = ila_get_lock(ilan, xp->identifier); int err = 0, order; if (!ilan->hooks_registered) { @@ -264,22 +269,22 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *p) if (!ila) return -ENOMEM; - ila->p = *p; + ila->xp = *xp; - if (p->ip.locator_match) { + if (xp->ip.locator_match.v64) { /* Precompute checksum difference for translation since we * know both the old identifier and the new one. */ - ila->p.ip.csum_diff = compute_csum_diff8( - (__be32 *)&p->ip.locator_match, - (__be32 *)&p->ip.locator); + ila->xp.ip.csum_diff = compute_csum_diff8( + (__be32 *)&xp->ip.locator_match, + (__be32 *)&xp->ip.locator); } order = ila_order(ila); spin_lock(lock); - head = rhashtable_lookup_fast(&ilan->rhash_table, &p->identifier, + head = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier, rht_params); if (!head) { /* New entry for the rhash_table */ @@ -289,7 +294,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *p) struct ila_map *tila = head, *prev = NULL; do { - if (!ila_cmp_params(tila, p)) { + if (!ila_cmp_params(tila, xp)) { err = -EEXIST; goto out; } @@ -326,23 +331,23 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *p) return err; } -static int ila_del_mapping(struct net *net, struct ila_xlat_params *p) +static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp) { struct ila_net *ilan = net_generic(net, ila_net_id); struct ila_map *ila, *head, *prev; - spinlock_t *lock = ila_get_lock(ilan, p->identifier); + spinlock_t *lock = ila_get_lock(ilan, xp->identifier); int err = -ENOENT; spin_lock(lock); head = rhashtable_lookup_fast(&ilan->rhash_table, - &p->identifier, rht_params); + &xp->identifier, rht_params); ila = head; prev = NULL; while (ila) { - if (ila_cmp_params(ila, p)) { + if (ila_cmp_params(ila, xp)) { prev = ila; ila = rcu_dereference_protected(ila->next, lockdep_is_held(lock)); @@ -404,14 +409,14 @@ static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info) static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); - struct ila_xlat_params p; + struct ila_xlat_params xp; int err; - err = parse_nl_config(info, &p); + err = parse_nl_config(info, &xp); if (err) return err; - ila_del_mapping(net, &p); + ila_del_mapping(net, &xp); return 0; } @@ -419,16 +424,16 @@ static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg) { if (nla_put_u64_64bit(msg, ILA_ATTR_IDENTIFIER, - (__force u64)ila->p.identifier, + (__force u64)ila->xp.identifier.v64, ILA_ATTR_PAD) || nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR, - (__force u64)ila->p.ip.locator, + (__force u64)ila->xp.ip.locator.v64, ILA_ATTR_PAD) || nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH, - (__force u64)ila->p.ip.locator_match, + (__force u64)ila->xp.ip.locator_match.v64, ILA_ATTR_PAD) || - nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->p.ifindex) || - nla_put_u32(msg, ILA_ATTR_DIR, ila->p.dir)) + nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) || + nla_put_u32(msg, ILA_ATTR_DIR, ila->xp.dir)) return -1; return 0; @@ -460,11 +465,11 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) struct net *net = genl_info_net(info); struct ila_net *ilan = net_generic(net, ila_net_id); struct sk_buff *msg; - struct ila_xlat_params p; + struct ila_xlat_params xp; struct ila_map *ila; int ret; - ret = parse_nl_config(info, &p); + ret = parse_nl_config(info, &xp); if (ret) return ret; @@ -474,7 +479,7 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) rcu_read_lock(); - ila = ila_lookup_by_params(&p, ilan); + ila = ila_lookup_by_params(&xp, ilan); if (ila) { ret = ila_dump_info(ila, info->snd_portid, @@ -623,21 +628,18 @@ static int ila_xlat_addr(struct sk_buff *skb, int dir) struct ipv6hdr *ip6h = ipv6_hdr(skb); struct net *net = dev_net(skb->dev); struct ila_net *ilan = net_generic(net, ila_net_id); - __be64 identifier, locator_match; + struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); size_t nhoff; /* Assumes skb contains a valid IPv6 header that is pulled */ - identifier = *(__be64 *)&ip6h->daddr.in6_u.u6_addr8[8]; - locator_match = *(__be64 *)&ip6h->daddr.in6_u.u6_addr8[0]; nhoff = sizeof(struct ipv6hdr); rcu_read_lock(); - ila = ila_lookup_wildcards(identifier, locator_match, - skb->dev->ifindex, dir, ilan); + ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, dir, ilan); if (ila) - update_ipv6_locator(skb, &ila->p.ip); + ila_update_ipv6_locator(skb, &ila->xp.ip); rcu_read_unlock(); -- GitLab From 642c2c95585dac4ea977140dbb1149fd1e2e7f7f Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Sat, 23 Apr 2016 11:46:56 -0700 Subject: [PATCH 4378/9938] ila: xlat changes Change model of xlat to be used only for input where lookup is done on the locator part of an address (comparing to locator_match as key in rhashtable). This is needed for checksum neutral translation which obfuscates the low order 16 bits of the identifier. It also permits hosts to be in muliple ILA domains (each locator can map to a different SIR address). A check is also added to disallow translating non-ILA addresses (check of type in identifier). Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- net/ipv6/ila/ila_xlat.c | 103 +++++++++++++--------------------------- 1 file changed, 34 insertions(+), 69 deletions(-) diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 020153bc47f5..2e6cb97aee19 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -11,9 +11,7 @@ struct ila_xlat_params { struct ila_params ip; - struct ila_identifier identifier; int ifindex; - unsigned int dir; }; struct ila_map { @@ -66,35 +64,29 @@ static __always_inline void __ila_hash_secret_init(void) net_get_random_once(&hashrnd, sizeof(hashrnd)); } -static inline u32 ila_identifier_hash(struct ila_identifier ident) +static inline u32 ila_locator_hash(struct ila_locator loc) { - u32 *v = (u32 *)ident.v32; + u32 *v = (u32 *)loc.v32; return jhash_2words(v[0], v[1], hashrnd); } static inline spinlock_t *ila_get_lock(struct ila_net *ilan, - struct ila_identifier ident) + struct ila_locator loc) { - return &ilan->locks[ila_identifier_hash(ident) & ilan->locks_mask]; + return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask]; } static inline int ila_cmp_wildcards(struct ila_map *ila, - struct ila_addr *iaddr, int ifindex, - unsigned int dir) + struct ila_addr *iaddr, int ifindex) { - return (ila->xp.ip.locator_match.v64 && - ila->xp.ip.locator_match.v64 != iaddr->loc.v64) || - (ila->xp.ifindex && ila->xp.ifindex != ifindex) || - !(ila->xp.dir & dir); + return (ila->xp.ifindex && ila->xp.ifindex != ifindex); } static inline int ila_cmp_params(struct ila_map *ila, struct ila_xlat_params *xp) { - return (ila->xp.ip.locator_match.v64 != xp->ip.locator_match.v64) || - (ila->xp.ifindex != xp->ifindex) || - (ila->xp.dir != xp->dir); + return (ila->xp.ifindex != xp->ifindex); } static int ila_cmpfn(struct rhashtable_compare_arg *arg, @@ -102,16 +94,13 @@ static int ila_cmpfn(struct rhashtable_compare_arg *arg, { const struct ila_map *ila = obj; - return (ila->xp.identifier.v64 != *(__be64 *)arg->key); + return (ila->xp.ip.locator_match.v64 != *(__be64 *)arg->key); } static inline int ila_order(struct ila_map *ila) { int score = 0; - if (ila->xp.ip.locator_match.v64) - score += 1 << 0; - if (ila->xp.ifindex) score += 1 << 1; @@ -121,7 +110,7 @@ static inline int ila_order(struct ila_map *ila) static const struct rhashtable_params rht_params = { .nelem_hint = 1024, .head_offset = offsetof(struct ila_map, node), - .key_offset = offsetof(struct ila_map, xp.identifier), + .key_offset = offsetof(struct ila_map, xp.ip.locator_match), .key_len = sizeof(u64), /* identifier */ .max_size = 1048576, .min_size = 256, @@ -140,11 +129,9 @@ static struct genl_family ila_nl_family = { }; static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { - [ILA_ATTR_IDENTIFIER] = { .type = NLA_U64, }, [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, }, [ILA_ATTR_IFINDEX] = { .type = NLA_U32, }, - [ILA_ATTR_DIR] = { .type = NLA_U32, }, }; static int parse_nl_config(struct genl_info *info, @@ -152,10 +139,6 @@ static int parse_nl_config(struct genl_info *info, { memset(xp, 0, sizeof(*xp)); - if (info->attrs[ILA_ATTR_IDENTIFIER]) - xp->identifier.v64 = (__force __be64)nla_get_u64( - info->attrs[ILA_ATTR_IDENTIFIER]); - if (info->attrs[ILA_ATTR_LOCATOR]) xp->ip.locator.v64 = (__force __be64)nla_get_u64( info->attrs[ILA_ATTR_LOCATOR]); @@ -167,24 +150,20 @@ static int parse_nl_config(struct genl_info *info, if (info->attrs[ILA_ATTR_IFINDEX]) xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]); - if (info->attrs[ILA_ATTR_DIR]) - xp->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]); - return 0; } /* Must be called with rcu readlock */ static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr, int ifindex, - unsigned int dir, struct ila_net *ilan) { struct ila_map *ila; - ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->ident, + ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc, rht_params); while (ila) { - if (!ila_cmp_wildcards(ila, iaddr, ifindex, dir)) + if (!ila_cmp_wildcards(ila, iaddr, ifindex)) return ila; ila = rcu_access_pointer(ila->next); } @@ -198,7 +177,8 @@ static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp, { struct ila_map *ila; - ila = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier, + ila = rhashtable_lookup_fast(&ilan->rhash_table, + &xp->ip.locator_match, rht_params); while (ila) { if (!ila_cmp_params(ila, xp)) @@ -226,14 +206,14 @@ static void ila_free_cb(void *ptr, void *arg) } } -static int ila_xlat_addr(struct sk_buff *skb, int dir); +static int ila_xlat_addr(struct sk_buff *skb); static unsigned int ila_nf_input(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - ila_xlat_addr(skb, ILA_DIR_IN); + ila_xlat_addr(skb); return NF_ACCEPT; } @@ -250,7 +230,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) { struct ila_net *ilan = net_generic(net, ila_net_id); struct ila_map *ila, *head; - spinlock_t *lock = ila_get_lock(ilan, xp->identifier); + spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match); int err = 0, order; if (!ilan->hooks_registered) { @@ -271,20 +251,19 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) ila->xp = *xp; - if (xp->ip.locator_match.v64) { - /* Precompute checksum difference for translation since we - * know both the old identifier and the new one. - */ - ila->xp.ip.csum_diff = compute_csum_diff8( - (__be32 *)&xp->ip.locator_match, - (__be32 *)&xp->ip.locator); - } + /* Precompute checksum difference for translation since we + * know both the old identifier and the new one. + */ + ila->xp.ip.csum_diff = compute_csum_diff8( + (__be32 *)&xp->ip.locator_match, + (__be32 *)&xp->ip.locator); order = ila_order(ila); spin_lock(lock); - head = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier, + head = rhashtable_lookup_fast(&ilan->rhash_table, + &xp->ip.locator_match, rht_params); if (!head) { /* New entry for the rhash_table */ @@ -335,13 +314,13 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp) { struct ila_net *ilan = net_generic(net, ila_net_id); struct ila_map *ila, *head, *prev; - spinlock_t *lock = ila_get_lock(ilan, xp->identifier); + spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match); int err = -ENOENT; spin_lock(lock); head = rhashtable_lookup_fast(&ilan->rhash_table, - &xp->identifier, rht_params); + &xp->ip.locator_match, rht_params); ila = head; prev = NULL; @@ -423,17 +402,13 @@ static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg) { - if (nla_put_u64_64bit(msg, ILA_ATTR_IDENTIFIER, - (__force u64)ila->xp.identifier.v64, - ILA_ATTR_PAD) || - nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR, + if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR, (__force u64)ila->xp.ip.locator.v64, ILA_ATTR_PAD) || nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH, (__force u64)ila->xp.ip.locator_match.v64, ILA_ATTR_PAD) || - nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) || - nla_put_u32(msg, ILA_ATTR_DIR, ila->xp.dir)) + nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex)) return -1; return 0; @@ -622,22 +597,24 @@ static struct pernet_operations ila_net_ops = { .size = sizeof(struct ila_net), }; -static int ila_xlat_addr(struct sk_buff *skb, int dir) +static int ila_xlat_addr(struct sk_buff *skb) { struct ila_map *ila; struct ipv6hdr *ip6h = ipv6_hdr(skb); struct net *net = dev_net(skb->dev); struct ila_net *ilan = net_generic(net, ila_net_id); struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); - size_t nhoff; /* Assumes skb contains a valid IPv6 header that is pulled */ - nhoff = sizeof(struct ipv6hdr); + if (!ila_addr_is_ila(iaddr)) { + /* Type indicates this is not an ILA address */ + return 0; + } rcu_read_lock(); - ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, dir, ilan); + ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan); if (ila) ila_update_ipv6_locator(skb, &ila->xp.ip); @@ -646,18 +623,6 @@ static int ila_xlat_addr(struct sk_buff *skb, int dir) return 0; } -int ila_xlat_incoming(struct sk_buff *skb) -{ - return ila_xlat_addr(skb, ILA_DIR_IN); -} -EXPORT_SYMBOL(ila_xlat_incoming); - -int ila_xlat_outgoing(struct sk_buff *skb) -{ - return ila_xlat_addr(skb, ILA_DIR_OUT); -} -EXPORT_SYMBOL(ila_xlat_outgoing); - int ila_xlat_init(void) { int ret; -- GitLab From 90bfe662db13d49cadc6714b0b8ed7e2d0535c5c Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Sat, 23 Apr 2016 11:46:57 -0700 Subject: [PATCH 4379/9938] ila: add checksum neutral ILA translations Support checksum neutral ILA as described in the ILA draft. The low order 16 bits of the identifier are used to contain the checksum adjustment value. The csum-mode parameter is added to described checksum processing. There are three values: - adjust transport checksum (previous behavior) - do checksum neutral mapping - do nothing On output the csum-mode in the ila_params is checked and acted on. If mode is checksum neutral mapping then to mapping and set C-bit. On input, C-bit is checked. If it is set checksum-netural mapping is done (regardless of csum-mode in ila params) and C-bit will be cleared. If it is not set then action in csum-mode is taken. Signed-off-by: Tom Herbert Signed-off-by: David S. Miller --- include/uapi/linux/ila.h | 7 ++++ net/ipv6/ila/ila.h | 16 +++++++-- net/ipv6/ila/ila_common.c | 74 +++++++++++++++++++++++++++++++++++++-- net/ipv6/ila/ila_lwt.c | 14 ++++++-- net/ipv6/ila/ila_xlat.c | 16 ++++----- 5 files changed, 112 insertions(+), 15 deletions(-) diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h index cd97951680bf..948c0a91e11b 100644 --- a/include/uapi/linux/ila.h +++ b/include/uapi/linux/ila.h @@ -15,6 +15,7 @@ enum { ILA_ATTR_IFINDEX, /* s32 */ ILA_ATTR_DIR, /* u32 */ ILA_ATTR_PAD, + ILA_ATTR_CSUM_MODE, /* u8 */ __ILA_ATTR_MAX, }; @@ -35,4 +36,10 @@ enum { #define ILA_DIR_IN (1 << 0) #define ILA_DIR_OUT (1 << 1) +enum { + ILA_CSUM_ADJUST_TRANSPORT, + ILA_CSUM_NEUTRAL_MAP, + ILA_CSUM_NO_ACTION, +}; + #endif /* _UAPI_LINUX_ILA_H */ diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h index f532967d9ed7..d08fd2d48a78 100644 --- a/net/ipv6/ila/ila.h +++ b/net/ipv6/ila/ila.h @@ -36,11 +36,13 @@ struct ila_identifier { union { struct { #if defined(__LITTLE_ENDIAN_BITFIELD) - u8 __space:5; + u8 __space:4; + u8 csum_neutral:1; u8 type:3; #elif defined(__BIG_ENDIAN_BITFIELD) u8 type:3; - u8 __space:5; + u8 csum_neutral:1; + u8 __space:4; #else #error "Adjust your defines" #endif @@ -64,6 +66,8 @@ enum { ILA_ATYPE_RSVD_3, }; +#define CSUM_NEUTRAL_FLAG htonl(0x10000000) + struct ila_addr { union { struct in6_addr addr; @@ -88,6 +92,7 @@ struct ila_params { struct ila_locator locator; struct ila_locator locator_match; __wsum csum_diff; + u8 csum_mode; }; static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to) @@ -99,8 +104,15 @@ static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to) return csum_partial(diff, sizeof(diff), 0); } +static inline bool ila_csum_neutral_set(struct ila_identifier ident) +{ + return !!(ident.csum_neutral); +} + void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p); +void ila_init_saved_csum(struct ila_params *p); + int ila_lwt_init(void); void ila_lwt_fini(void); int ila_xlat_init(void); diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c index c3078d0b64e1..0e94042d1289 100644 --- a/net/ipv6/ila/ila_common.c +++ b/net/ipv6/ila/ila_common.c @@ -17,21 +17,50 @@ static __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p) { struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); - if (iaddr->loc.v64 == p->locator_match.v64) + if (p->locator_match.v64) return p->csum_diff; else return compute_csum_diff8((__be32 *)&iaddr->loc, (__be32 *)&p->locator); } -void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) +static void ila_csum_do_neutral(struct ila_addr *iaddr, + struct ila_params *p) +{ + __sum16 *adjust = (__force __sum16 *)&iaddr->ident.v16[3]; + __wsum diff, fval; + + /* Check if checksum adjust value has been cached */ + if (p->locator_match.v64) { + diff = p->csum_diff; + } else { + diff = compute_csum_diff8((__be32 *)iaddr, + (__be32 *)&p->locator); + } + + fval = (__force __wsum)(ila_csum_neutral_set(iaddr->ident) ? + ~CSUM_NEUTRAL_FLAG : CSUM_NEUTRAL_FLAG); + + diff = csum_add(diff, fval); + + *adjust = ~csum_fold(csum_add(diff, csum_unfold(*adjust))); + + /* Flip the csum-neutral bit. Either we are doing a SIR->ILA + * translation with ILA_CSUM_NEUTRAL_MAP as the csum_method + * and the C-bit is not set, or we are doing an ILA-SIR + * tranlsation and the C-bit is set. + */ + iaddr->ident.csum_neutral ^= 1; +} + +static void ila_csum_adjust_transport(struct sk_buff *skb, + struct ila_params *p) { __wsum diff; struct ipv6hdr *ip6h = ipv6_hdr(skb); struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); size_t nhoff = sizeof(struct ipv6hdr); - /* First update checksum */ switch (ip6h->nexthdr) { case NEXTHDR_TCP: if (likely(pskb_may_pull(skb, nhoff + sizeof(struct tcphdr)))) { @@ -74,6 +103,45 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) iaddr->loc = p->locator; } +void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) +{ + struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); + + /* First deal with the transport checksum */ + if (ila_csum_neutral_set(iaddr->ident)) { + /* C-bit is set in the locator indicating that this + * is a locator being translated to a SIR address. + * Perform (receiver) checksum-neutral translation. + */ + ila_csum_do_neutral(iaddr, p); + } else { + switch (p->csum_mode) { + case ILA_CSUM_ADJUST_TRANSPORT: + ila_csum_adjust_transport(skb, p); + break; + case ILA_CSUM_NEUTRAL_MAP: + ila_csum_do_neutral(iaddr, p); + break; + case ILA_CSUM_NO_ACTION: + break; + } + } + + /* Now change destination address */ + iaddr->loc = p->locator; +} + +void ila_init_saved_csum(struct ila_params *p) +{ + if (!p->locator_match.v64) + return; + + p->csum_diff = compute_csum_diff8( + (__be32 *)&p->locator_match, + (__be32 *)&p->locator); +} + static int __init ila_init(void) { int ret; diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index de7f6d76e928..4985e1a735a6 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c @@ -53,6 +53,7 @@ static int ila_input(struct sk_buff *skb) static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, + [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, }, }; static int ila_build_state(struct net_device *dev, struct nlattr *nla, @@ -79,8 +80,10 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla, iaddr = (struct ila_addr *)&cfg6->fc_dst; - if (!ila_addr_is_ila(iaddr)) { - /* Don't allow setting a translation for a non-ILA address */ + if (!ila_addr_is_ila(iaddr) || ila_csum_neutral_set(iaddr->ident)) { + /* Don't allow translation for a non-ILA address or checksum + * neutral flag to be set. + */ return -EINVAL; } @@ -108,6 +111,11 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla, p->csum_diff = compute_csum_diff8( (__be32 *)&p->locator_match, (__be32 *)&p->locator); + if (tb[ILA_ATTR_CSUM_MODE]) + p->csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]); + + ila_init_saved_csum(p); + newts->type = LWTUNNEL_ENCAP_ILA; newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT | LWTUNNEL_STATE_INPUT_REDIRECT; @@ -125,6 +133,8 @@ static int ila_fill_encap_info(struct sk_buff *skb, if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64, ILA_ATTR_PAD)) goto nla_put_failure; + if (nla_put_u64(skb, ILA_ATTR_CSUM_MODE, (__force u8)p->csum_mode)) + goto nla_put_failure; return 0; diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 2e6cb97aee19..a90e57229c6c 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -132,6 +132,7 @@ static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, }, [ILA_ATTR_IFINDEX] = { .type = NLA_U32, }, + [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, }, }; static int parse_nl_config(struct genl_info *info, @@ -147,6 +148,9 @@ static int parse_nl_config(struct genl_info *info, xp->ip.locator_match.v64 = (__force __be64)nla_get_u64( info->attrs[ILA_ATTR_LOCATOR_MATCH]); + if (info->attrs[ILA_ATTR_CSUM_MODE]) + xp->ip.csum_mode = nla_get_u8(info->attrs[ILA_ATTR_CSUM_MODE]); + if (info->attrs[ILA_ATTR_IFINDEX]) xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]); @@ -249,14 +253,9 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) if (!ila) return -ENOMEM; - ila->xp = *xp; + ila_init_saved_csum(&xp->ip); - /* Precompute checksum difference for translation since we - * know both the old identifier and the new one. - */ - ila->xp.ip.csum_diff = compute_csum_diff8( - (__be32 *)&xp->ip.locator_match, - (__be32 *)&xp->ip.locator); + ila->xp = *xp; order = ila_order(ila); @@ -408,7 +407,8 @@ static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg) nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH, (__force u64)ila->xp.ip.locator_match.v64, ILA_ATTR_PAD) || - nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex)) + nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) || + nla_put_u32(msg, ILA_ATTR_CSUM_MODE, ila->xp.ip.csum_mode)) return -1; return 0; -- GitLab From e4106a7c8236eb7b91686d36f3bf33ee43db94b4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 19 Apr 2016 14:33:33 +0200 Subject: [PATCH 4380/9938] mtd: maps: add __init attribute Add __init attribute on functions that are only called from other __init functions and that are not inlined, at least with gcc version 4.8.4 on an x86 machine with allyesconfig. Currently, the functions are put in the .text.unlikely segment. Declaring them as __init will cause them to be put in the .init.text and to disappear after initialization. The result of objdump -x on the functions before the change is as follows: 00000000000001bc l F .text.unlikely 00000000000006a2 ck804xrom_init_one.isra.1 00000000000001aa l F .text.unlikely 0000000000000764 esb2rom_init_one.isra.1 00000000000001db l F .text.unlikely 0000000000000716 ichxrom_init_one.isra.1 And after the change it is as follows: 0000000000000000 l F .init.text 000000000000069d ck804xrom_init_one.isra.1 0000000000000000 l F .init.text 000000000000075f esb2rom_init_one.isra.1 0000000000000000 l F .init.text 0000000000000711 ichxrom_init_one.isra.1 Done with the help of Coccinelle. The semantic patch checks for local static non-init functions that are called from an __init function and are not called from any other function. Note that in each case, the function is stored in the probe field of a pci_driver structure, but this code is under an #if 0. The #if 0s have been unchanged since 2009 at the latest. Signed-off-by: Julia Lawall Signed-off-by: Brian Norris --- drivers/mtd/maps/ck804xrom.c | 4 ++-- drivers/mtd/maps/esb2rom.c | 4 ++-- drivers/mtd/maps/ichxrom.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 0455166f05fa..4f206a99164c 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -112,8 +112,8 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window) } -static int ck804xrom_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init ck804xrom_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; u8 byte; diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 76ed651b515b..9646b0766ce0 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c @@ -144,8 +144,8 @@ static void esb2rom_cleanup(struct esb2rom_window *window) pci_dev_put(window->pdev); } -static int esb2rom_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init esb2rom_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; struct esb2rom_window *window = &esb2rom_window; diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index 8636bba42200..e17d02ae03f0 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -84,8 +84,8 @@ static void ichxrom_cleanup(struct ichxrom_window *window) } -static int ichxrom_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init ichxrom_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; struct ichxrom_window *window = &ichxrom_window; -- GitLab From abbbc60a0c69e05c965ce51cb75c0bee56dc0025 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 19 Apr 2016 14:33:34 +0200 Subject: [PATCH 4381/9938] mtd: pmc551: add __init attribute Add __init attribute on a function that is only called from other __init functions and that is not inlined, at least with gcc version 4.8.4 on an x86 machine with allyesconfig. Currently, the function is put in the .text.unlikely segment. Declaring it as __init will cause it to be put in the .init.text and to disappear after initialization. The result of objdump -x on the function before the change is as follows: 00000000000000c6 l F .text.unlikely 000000000000091c fixup_pmc551 And after the change it is as follows: 0000000000000000 l F .init.text 0000000000000917 fixup_pmc551 Done with the help of Coccinelle. The semantic patch checks for local static non-init functions that are called from an __init function and are not called from any other function. Signed-off-by: Julia Lawall Signed-off-by: Brian Norris --- drivers/mtd/devices/pmc551.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 708b7e8c8b18..220f9200fa52 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -353,7 +353,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len, * mechanism * returns the size of the memory region found. */ -static int fixup_pmc551(struct pci_dev *dev) +static int __init fixup_pmc551(struct pci_dev *dev) { #ifdef CONFIG_MTD_PMC551_BUGFIX u32 dram_data; -- GitLab From a47241cdeee2689ee7089ec95cadfcf66588fbdb Mon Sep 17 00:00:00 2001 From: Alden Tondettar Date: Mon, 25 Apr 2016 19:27:56 -0700 Subject: [PATCH 4382/9938] udf: Prevent stack overflow on corrupted filesystem mount Presently, a corrupted or malicious UDF filesystem containing a very large number (or cycle) of Logical Volume Integrity Descriptor extent indirections may trigger a stack overflow and kernel panic in udf_load_logicalvolint() on mount. Replace the unnecessary recursion in udf_load_logicalvolint() with simple iteration. Set an arbitrary limit of 1000 indirections (which would have almost certainly overflowed the stack without this fix), and treat such cases as if there were no LVID. Signed-off-by: Alden Tondettar Signed-off-by: Jan Kara --- fs/udf/super.c | 67 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 36661acaf33b..5e2c8c814e1b 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -78,6 +78,15 @@ #define VSD_FIRST_SECTOR_OFFSET 32768 #define VSD_MAX_SECTOR_OFFSET 0x800000 +/* + * Maximum number of Terminating Descriptor / Logical Volume Integrity + * Descriptor redirections. The chosen numbers are arbitrary - just that we + * hopefully don't limit any real use of rewritten inode on write-once media + * but avoid looping for too long on corrupted media. + */ +#define UDF_MAX_TD_NESTING 64 +#define UDF_MAX_LVID_NESTING 1000 + enum { UDF_MAX_LINKS = 0xffff }; /* These are the "meat" - everything else is stuffing */ @@ -1541,42 +1550,52 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, } /* - * udf_load_logicalvolint - * + * Find the prevailing Logical Volume Integrity Descriptor. */ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc) { - struct buffer_head *bh = NULL; + struct buffer_head *bh, *final_bh; uint16_t ident; struct udf_sb_info *sbi = UDF_SB(sb); struct logicalVolIntegrityDesc *lvid; + int indirections = 0; + + while (++indirections <= UDF_MAX_LVID_NESTING) { + final_bh = NULL; + while (loc.extLength > 0 && + (bh = udf_read_tagged(sb, loc.extLocation, + loc.extLocation, &ident))) { + if (ident != TAG_IDENT_LVID) { + brelse(bh); + break; + } + + brelse(final_bh); + final_bh = bh; - while (loc.extLength > 0 && - (bh = udf_read_tagged(sb, loc.extLocation, - loc.extLocation, &ident)) && - ident == TAG_IDENT_LVID) { - sbi->s_lvid_bh = bh; - lvid = (struct logicalVolIntegrityDesc *)bh->b_data; + loc.extLength -= sb->s_blocksize; + loc.extLocation++; + } - if (lvid->nextIntegrityExt.extLength) - udf_load_logicalvolint(sb, - leea_to_cpu(lvid->nextIntegrityExt)); + if (!final_bh) + return; - if (sbi->s_lvid_bh != bh) - brelse(bh); - loc.extLength -= sb->s_blocksize; - loc.extLocation++; + brelse(sbi->s_lvid_bh); + sbi->s_lvid_bh = final_bh; + + lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data; + if (lvid->nextIntegrityExt.extLength == 0) + return; + + loc = leea_to_cpu(lvid->nextIntegrityExt); } - if (sbi->s_lvid_bh != bh) - brelse(bh); + + udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n", + UDF_MAX_LVID_NESTING); + brelse(sbi->s_lvid_bh); + sbi->s_lvid_bh = NULL; } -/* - * Maximum number of Terminating Descriptor redirections. The chosen number is - * arbitrary - just that we hopefully don't limit any real use of rewritten - * inode on write-once media but avoid looping for too long on corrupted media. - */ -#define UDF_MAX_TD_NESTING 64 /* * Process a main/reserve volume descriptor sequence. -- GitLab From 0187d321a5092fe09687f69ee29ebe8ab75544c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Mon, 25 Apr 2016 13:39:19 +0200 Subject: [PATCH 4383/9938] clk: renesas: r8a7795: Add CSI2 clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Niklas Söderlund Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 6af7f5b6e824..f6a0a9d67229 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -120,6 +120,7 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244), + DEF_DIV6P1("csi0", R8A7795_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), @@ -190,6 +191,10 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("ehci1", 702, R8A7795_CLK_S3D4), DEF_MOD("ehci0", 703, R8A7795_CLK_S3D4), DEF_MOD("hsusb", 704, R8A7795_CLK_S3D4), + DEF_MOD("csi21", 713, R8A7795_CLK_CSI0), + DEF_MOD("csi20", 714, R8A7795_CLK_CSI0), + DEF_MOD("csi41", 715, R8A7795_CLK_CSI0), + DEF_MOD("csi40", 716, R8A7795_CLK_CSI0), DEF_MOD("du3", 721, R8A7795_CLK_S2D1), DEF_MOD("du2", 722, R8A7795_CLK_S2D1), DEF_MOD("du1", 723, R8A7795_CLK_S2D1), -- GitLab From ccce262de1c5035513d7974ab1550dd757d25bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Mon, 25 Apr 2016 13:39:20 +0200 Subject: [PATCH 4384/9938] clk: renesas: r8a7795: Add VIN clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Niklas Söderlund Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index f6a0a9d67229..ca5519c583d4 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -202,6 +202,14 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("lvds", 727, R8A7795_CLK_S2D1), DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), + DEF_MOD("vin7", 804, R8A7795_CLK_S2D1), + DEF_MOD("vin6", 805, R8A7795_CLK_S2D1), + DEF_MOD("vin5", 806, R8A7795_CLK_S2D1), + DEF_MOD("vin4", 807, R8A7795_CLK_S2D1), + DEF_MOD("vin3", 808, R8A7795_CLK_S2D1), + DEF_MOD("vin2", 809, R8A7795_CLK_S2D1), + DEF_MOD("vin1", 810, R8A7795_CLK_S2D1), + DEF_MOD("vin0", 811, R8A7795_CLK_S2D1), DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2), DEF_MOD("sata0", 815, R8A7795_CLK_S3D2), DEF_MOD("gpio7", 905, R8A7795_CLK_CP), -- GitLab From d2c5cf88d5282de258f4eb6ab40040b80a075cd8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 24 Apr 2016 22:52:18 +0200 Subject: [PATCH 4385/9938] ALSA: hrtimer: Handle start/stop more properly This patch tries to address the still remaining issues in ALSA hrtimer driver: - Spurious use-after-free was detected in hrtimer callback - Incorrect rescheduling due to delayed start - WARN_ON() is triggered in hrtimer_forward() invoked in hrtimer callback The first issue happens only when the new timer is scheduled even while hrtimer is being closed. It's related with the second and third items; since ALSA timer core invokes hw.start callback during hrtimer interrupt, this may result in the explicit call of hrtimer_start(). Also, the similar problem is seen for the stop; ALSA timer core invokes hw.stop callback even in the hrtimer handler, too. Since we must not call the synced hrtimer_cancel() in such a context, it's just a hrtimer_try_to_cancel() call that doesn't properly work. Another culprit of the second and third items is the call of hrtimer_forward_now() before snd_timer_interrupt(). The timer->stick value may change during snd_timer_interrupt() call, but this possibility is ignored completely. For covering these subtle and messy issues, the following changes have been done in this patch: - A new flag, in_callback, is introduced in the private data to indicate that the hrtimer handler is being processed. - Both start and stop callbacks skip when called from (during) in_callback flag. - The hrtimer handler returns properly HRTIMER_RESTART and NORESTART depending on the running state now. - The hrtimer handler reprograms the expiry properly after snd_timer_interrupt() call, instead of before. - The close callback clears running flag and sets in_callback flag to block any further start/stop calls. Signed-off-by: Takashi Iwai --- sound/core/hrtimer.c | 56 ++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 656d9a9032dc..e2f27022b363 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -38,37 +38,53 @@ static unsigned int resolution; struct snd_hrtimer { struct snd_timer *timer; struct hrtimer hrt; - atomic_t running; + bool in_callback; }; static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) { struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); struct snd_timer *t = stime->timer; - unsigned long oruns; - - if (!atomic_read(&stime->running)) - return HRTIMER_NORESTART; - - oruns = hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); - snd_timer_interrupt(stime->timer, t->sticks * oruns); + ktime_t delta; + unsigned long ticks; + enum hrtimer_restart ret = HRTIMER_NORESTART; + + spin_lock(&t->lock); + if (!t->running) + goto out; /* fast path */ + stime->in_callback = true; + ticks = t->sticks; + spin_unlock(&t->lock); + + /* calculate the drift */ + delta = ktime_sub(hrt->base->get_time(), hrtimer_get_expires(hrt)); + if (delta.tv64 > 0) + ticks += ktime_divns(delta, ticks * resolution); + + snd_timer_interrupt(stime->timer, ticks); + + spin_lock(&t->lock); + if (t->running) { + hrtimer_add_expires_ns(hrt, t->sticks * resolution); + ret = HRTIMER_RESTART; + } - if (!atomic_read(&stime->running)) - return HRTIMER_NORESTART; - return HRTIMER_RESTART; + stime->in_callback = false; + out: + spin_unlock(&t->lock); + return ret; } static int snd_hrtimer_open(struct snd_timer *t) { struct snd_hrtimer *stime; - stime = kmalloc(sizeof(*stime), GFP_KERNEL); + stime = kzalloc(sizeof(*stime), GFP_KERNEL); if (!stime) return -ENOMEM; hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); stime->timer = t; stime->hrt.function = snd_hrtimer_callback; - atomic_set(&stime->running, 0); t->private_data = stime; return 0; } @@ -78,6 +94,11 @@ static int snd_hrtimer_close(struct snd_timer *t) struct snd_hrtimer *stime = t->private_data; if (stime) { + spin_lock_irq(&t->lock); + t->running = 0; /* just to be sure */ + stime->in_callback = 1; /* skip start/stop */ + spin_unlock_irq(&t->lock); + hrtimer_cancel(&stime->hrt); kfree(stime); t->private_data = NULL; @@ -89,18 +110,19 @@ static int snd_hrtimer_start(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; - atomic_set(&stime->running, 0); - hrtimer_try_to_cancel(&stime->hrt); + if (stime->in_callback) + return 0; hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), HRTIMER_MODE_REL); - atomic_set(&stime->running, 1); return 0; } static int snd_hrtimer_stop(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; - atomic_set(&stime->running, 0); + + if (stime->in_callback) + return 0; hrtimer_try_to_cancel(&stime->hrt); return 0; } -- GitLab From 739960f128e5a1f251659a4430a8898087701099 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 7 Apr 2016 19:59:34 +0530 Subject: [PATCH 4386/9938] cfg80211/nl80211: Add support for NL80211_STA_INFO_RX_DURATION Add support for the a station statistics netlink attribute: NL80211_STA_INFO_RX_DURATION. If present, this attribute contains the aggregate PPDU duration (in microseconds) for all the frames from the peer. This is useful to help understand the total time spent transmitting to us by all of the connected peers. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 4 +++- include/uapi/linux/nl80211.h | 3 +++ net/wireless/nl80211.c | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 183916e168f1..c8414962683d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1045,11 +1045,12 @@ struct cfg80211_tid_stats { * @rx_beacon: number of beacons received from this peer * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received * from this peer + * @rx_duration: aggregate PPDU duration(usecs) for all the frames from a peer * @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last * (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs. */ struct station_info { - u32 filled; + u64 filled; u32 connected_time; u32 inactive_time; u64 rx_bytes; @@ -1088,6 +1089,7 @@ struct station_info { u32 expected_throughput; u64 rx_beacon; + u64 rx_duration; u8 rx_beacon_signal_avg; struct cfg80211_tid_stats pertid[IEEE80211_NUM_TIDS + 1]; }; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 2c55dd1894c3..51fc4abf6491 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2513,6 +2513,8 @@ enum nl80211_sta_bss_param { * TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames; * each one of those is again nested with &enum nl80211_tid_stats * attributes carrying the actual values. + * @NL80211_STA_INFO_RX_DURATION: aggregate PPDU duration for all frames + * received from the station (u64, usec) * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -2549,6 +2551,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_BEACON_RX, NL80211_STA_INFO_BEACON_SIGNAL_AVG, NL80211_STA_INFO_TID_STATS, + NL80211_STA_INFO_RX_DURATION, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index afeb1ef1b199..5b0d2c8c2165 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3755,7 +3755,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, goto nla_put_failure; #define PUT_SINFO(attr, memb, type) do { \ - if (sinfo->filled & BIT(NL80211_STA_INFO_ ## attr) && \ + if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \ nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \ sinfo->memb)) \ goto nla_put_failure; \ @@ -3781,6 +3781,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, PUT_SINFO(LLID, llid, u16); PUT_SINFO(PLID, plid, u16); PUT_SINFO(PLINK_STATE, plink_state, u8); + PUT_SINFO(RX_DURATION, rx_duration, u64); switch (rdev->wiphy.signal_type) { case CFG80211_SIGNAL_TYPE_MBM: -- GitLab From e705498945ad3a3b945771c5d683df064bb9819c Mon Sep 17 00:00:00 2001 From: "Kanchanapally, Vidyullatha" Date: Mon, 11 Apr 2016 15:16:01 +0530 Subject: [PATCH 4387/9938] cfg80211: Add option to report the bss entry in connect result Since cfg80211 maintains separate BSS table entries for APs if the same BSSID, SSID pair is seen on multiple channels, it is possible that it can map the current_bss to a BSS entry on the wrong channel. This current_bss will not get flushed unless disconnected and cfg80211 reports a wrong channel as the associated channel. Fix this by introducing a new cfg80211_connect_bss() function which is similar to cfg80211_connect_result(), but it includes an additional parameter: the bss the STA is connected to. This allows drivers to provide the exact bss entry that matches the BSS to which the connection was completed. Reviewed-by: Jouni Malinen Signed-off-by: Vidyullatha Kanchanapally Signed-off-by: Sunil Dutt Signed-off-by: Johannes Berg --- Documentation/DocBook/80211.tmpl | 1 + include/net/cfg80211.h | 39 ++++++++++++++++++++++++++++---- net/wireless/core.h | 1 + net/wireless/sme.c | 28 ++++++++++++++++++----- net/wireless/util.c | 2 +- 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index f2a312b35875..5f7c55999c77 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -135,6 +135,7 @@ !Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt !Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_connect_result +!Finclude/net/cfg80211.h cfg80211_connect_bss !Finclude/net/cfg80211.h cfg80211_roamed !Finclude/net/cfg80211.h cfg80211_disconnected !Finclude/net/cfg80211.h cfg80211_ready_on_channel diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index c8414962683d..1e008cddd41d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4651,6 +4651,32 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) #define CFG80211_TESTMODE_DUMP(cmd) #endif +/** + * cfg80211_connect_bss - notify cfg80211 of connection result + * + * @dev: network device + * @bssid: the BSSID of the AP + * @bss: entry of bss to which STA got connected to, can be obtained + * through cfg80211_get_bss (may be %NULL) + * @req_ie: association request IEs (maybe be %NULL) + * @req_ie_len: association request IEs length + * @resp_ie: association response IEs (may be %NULL) + * @resp_ie_len: assoc response IEs length + * @status: status code, 0 for successful connection, use + * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you + * the real status code for failures. + * @gfp: allocation flags + * + * It should be called by the underlying driver whenever connect() has + * succeeded. This is similar to cfg80211_connect_result(), but with the + * option of identifying the exact bss entry for the connection. Only one of + * these functions should be called. + */ +void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, + struct cfg80211_bss *bss, const u8 *req_ie, + size_t req_ie_len, const u8 *resp_ie, + size_t resp_ie_len, u16 status, gfp_t gfp); + /** * cfg80211_connect_result - notify cfg80211 of connection result * @@ -4668,10 +4694,15 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) * It should be called by the underlying driver whenever connect() has * succeeded. */ -void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp); +static inline void +cfg80211_connect_result(struct net_device *dev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, + const u8 *resp_ie, size_t resp_ie_len, + u16 status, gfp_t gfp) +{ + cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie, + resp_ie_len, status, gfp); +} /** * cfg80211_roamed - notify cfg80211 of roaming diff --git a/net/wireless/core.h b/net/wireless/core.h index 022ccad06cbe..ac44e77ac2f2 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -214,6 +214,7 @@ struct cfg80211_event { const u8 *resp_ie; size_t req_ie_len; size_t resp_ie_len; + struct cfg80211_bss *bss; u16 status; } cr; struct { diff --git a/net/wireless/sme.c b/net/wireless/sme.c index e22e5b83cfa9..d814279fb556 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -753,19 +753,32 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, kfree(country_ie); } -void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp) +/* Consumes bss object one way or another */ +void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, + struct cfg80211_bss *bss, const u8 *req_ie, + size_t req_ie_len, const u8 *resp_ie, + size_t resp_ie_len, u16 status, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_event *ev; unsigned long flags; + if (bss) { + /* Make sure the bss entry provided by the driver is valid. */ + struct cfg80211_internal_bss *ibss = bss_from_pub(bss); + + if (WARN_ON(list_empty(&ibss->list))) { + cfg80211_put_bss(wdev->wiphy, bss); + return; + } + } + ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); - if (!ev) + if (!ev) { + cfg80211_put_bss(wdev->wiphy, bss); return; + } ev->type = EVENT_CONNECT_RESULT; if (bssid) @@ -780,6 +793,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ev->cr.resp_ie_len = resp_ie_len; memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); } + if (bss) + cfg80211_hold_bss(bss_from_pub(bss)); + ev->cr.bss = bss; ev->cr.status = status; spin_lock_irqsave(&wdev->event_lock, flags); @@ -787,7 +803,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, spin_unlock_irqrestore(&wdev->event_lock, flags); queue_work(cfg80211_wq, &rdev->event_work); } -EXPORT_SYMBOL(cfg80211_connect_result); +EXPORT_SYMBOL(cfg80211_connect_bss); /* Consumes bss object one way or another */ void __cfg80211_roamed(struct wireless_dev *wdev, diff --git a/net/wireless/util.c b/net/wireless/util.c index f36039888eb5..7cfabd6e83c6 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -950,7 +950,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) ev->cr.resp_ie, ev->cr.resp_ie_len, ev->cr.status, ev->cr.status == WLAN_STATUS_SUCCESS, - NULL); + ev->cr.bss); break; case EVENT_ROAMED: __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, -- GitLab From 9b95fe59b18bcc891a6c60ae11d725c9c679574b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 26 Apr 2016 09:42:39 +0200 Subject: [PATCH 4388/9938] nl80211: add missing kerneldoc for new *_PAD attributes Nicolas's patch missed this, now generating docbook warnings. Add the missing descriptions to address that. Fixes: 2dad624e6dd6 ("wireless: use nla_put_u64_64bit()") Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 51fc4abf6491..f958a7173eb4 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1817,6 +1817,8 @@ enum nl80211_commands { * @NL80211_ATTR_STA_SUPPORT_P2P_PS: whether P2P PS mechanism supported * or not. u8, one of the values of &enum nl80211_sta_p2p_ps_status * + * @NL80211_ATTR_PAD: attribute used for padding for 64-bit alignment + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3013,6 +3015,7 @@ enum nl80211_user_reg_hint_type { * transmitting data (on channel or globally) * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan * (on this channel or globally) + * @NL80211_SURVEY_INFO_PAD: attribute used for padding for 64-bit alignment * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number * currently defined * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use @@ -3454,6 +3457,7 @@ enum nl80211_bss_scan_width { * @NL80211_BSS_LAST_SEEN_BOOTTIME: CLOCK_BOOTTIME timestamp when this entry * was last updated by a received frame. The value is expected to be * accurate to about 10ms. (u64, nanoseconds) + * @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ -- GitLab From 1adea8b8bd1d12aef0a2f2baf7ed7a0ffbb1c505 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 7 Mar 2016 15:49:08 +0100 Subject: [PATCH 4389/9938] irqchip: versatile-fpga: add new compatible for OX810SE SoC Under the OX810SE, this exact same interface is used as "Reference Peripheral Specification" Interrupt Controller, so add a new compatible string in order to support the Oxford Semiconductor OX810SE SoC interrupt controller. Acked-by: Marc Zyngier Signed-off-by: Neil Armstrong --- drivers/irqchip/irq-versatile-fpga.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c index 598ab3f0e0ac..37dd4645bf18 100644 --- a/drivers/irqchip/irq-versatile-fpga.c +++ b/drivers/irqchip/irq-versatile-fpga.c @@ -227,4 +227,5 @@ int __init fpga_irq_of_init(struct device_node *node, } IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init); IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init); +IRQCHIP_DECLARE(ox810se_rps, "oxsemi,ox810se-rps-irq", fpga_irq_of_init); #endif -- GitLab From 8c9184b7d95859b24bba1201780886aabdab8ce1 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 3 Mar 2016 10:42:15 +0100 Subject: [PATCH 4390/9938] ARM: Add new mach-oxnas Add mach-oxnas directory containing Kconfig. Signed-off-by: Neil Armstrong --- arch/arm/Kconfig | 2 ++ arch/arm/mach-oxnas/Kconfig | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 arch/arm/mach-oxnas/Kconfig diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index cdfa6c2b7626..4d48e23ece0a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -804,6 +804,8 @@ source "arch/arm/plat-pxa/Kconfig" source "arch/arm/mach-mmp/Kconfig" +source "arch/arm/mach-oxnas/Kconfig" + source "arch/arm/mach-qcom/Kconfig" source "arch/arm/mach-realview/Kconfig" diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig new file mode 100644 index 000000000000..4fff3c7666df --- /dev/null +++ b/arch/arm/mach-oxnas/Kconfig @@ -0,0 +1,24 @@ +menuconfig ARCH_OXNAS + bool "Oxford Semiconductor OXNAS Family SoCs" + select ARCH_REQUIRE_GPIOLIB + select ARCH_HAS_RESET_CONTROLLER + select PINCTRL + depends on ARCH_MULTI_V5 + help + Support for OxNas SoC family developed by Oxford Semiconductor. + +if ARCH_OXNAS + +config MACH_OX810SE + bool "Support OX810SE Based Products" + select ARM_TIMER_SP804 + select COMMON_CLK_OXNAS + select CPU_ARM926T + select MFD_SYSCON + select PINCTRL_OXNAS + select RESET_OXNAS + select VERSATILE_FPGA_IRQ + help + Include Support for the Oxford Semiconductor OX810SE SoC Based Products. + +endif -- GitLab From e557959d5599037899dd974f4a79419c664dcf79 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 1 Apr 2016 14:56:16 +0200 Subject: [PATCH 4391/9938] MAINTAINERS: add maintainer entry for ARM/OXNAS platform Add a maintainer entry for ARM/OXNAS platform and add myself as a maintainer. Signed-off-by: Neil Armstrong --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 61a323a6b2cf..ca68706a60d9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1355,6 +1355,15 @@ W: http://www.digriz.org.uk/ts78xx/kernel S: Maintained F: arch/arm/mach-orion5x/ts78xx-* +ARM/OXNAS platform support +M: Neil Armstrong +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-oxnas/ +F: arch/arm/boot/dts/oxnas* +F: arch/arm/boot/dts/wd-mbwe.dts +N: oxnas + ARM/Mediatek RTC DRIVER M: Eddie Huang L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -- GitLab From 145f8a155c3e8e6c7a4cf8ddb4c5be7b53d6adf1 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 7 Mar 2016 15:50:52 +0100 Subject: [PATCH 4392/9938] dt-bindings: irq: arm,versatile-fpga: add compatible string for OX810SE SoC Under the OX810SE, this same controller is used as "Reference Peripheral Specification" Interrupt Controller, so add new compatible string to support the Oxford Semiconductor OX810SE SoC Interrupt Controller. Acked-by: Marc Zyngier Signed-off-by: Neil Armstrong --- .../bindings/interrupt-controller/arm,versatile-fpga-irq.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt index c9cf605bb995..2a1d16bdf834 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt @@ -6,7 +6,7 @@ controllers are OR:ed together and fed to the CPU tile's IRQ input. Each instance can handle up to 32 interrupts. Required properties: -- compatible: "arm,versatile-fpga-irq" +- compatible: "arm,versatile-fpga-irq" or "oxsemi,ox810se-rps-irq" - interrupt-controller: Identifies the node as an interrupt controller - #interrupt-cells: The number of cells to define the interrupts. Must be 1 as the FPGA IRQ controller has no configuration options for interrupt -- GitLab From cc86e3e2a3ff19c86a3c4a979d7da5a92e41c9cc Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 3 Mar 2016 14:34:14 +0100 Subject: [PATCH 4393/9938] dt-bindings: Add Oxford Semiconductor to vendor prefixes Acked-by: Rob Herring Signed-off-by: Neil Armstrong --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 86740d4a270d..53ca9a2a3d6a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -177,6 +177,7 @@ option Option NV ortustech Ortus Technology Co., Ltd. ovti OmniVision Technologies ORCL Oracle Corporation +oxsemi Oxford Semiconductor, Ltd. panasonic Panasonic Corporation parade Parade Technologies Inc. pericom Pericom Technology Inc. -- GitLab From 84316f4ef141cfee1e8ccd1b5749998eba2496ee Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 3 Mar 2016 10:52:58 +0100 Subject: [PATCH 4394/9938] ARM: boot: dts: Add Oxford Semiconductor OX810SE dtsi Signed-off-by: Neil Armstrong --- arch/arm/boot/dts/ox810se.dtsi | 336 +++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 arch/arm/boot/dts/ox810se.dtsi diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi new file mode 100644 index 000000000000..ce13705c38d4 --- /dev/null +++ b/arch/arm/boot/dts/ox810se.dtsi @@ -0,0 +1,336 @@ +/* + * ox810se.dtsi - Device tree file for Oxford Semiconductor OX810SE SoC + * + * Copyright (C) 2016 Neil Armstrong + * + * Licensed under GPLv2 or later + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "oxsemi,ox810se"; + + cpus { + #address-cells = <0>; + #size-cells = <0>; + + cpu { + device_type = "cpu"; + compatible = "arm,arm926ej-s"; + clocks = <&armclk>; + }; + }; + + memory { + /* Max 256MB @ 0x48000000 */ + reg = <0x48000000 0x10000000>; + }; + + clocks { + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + gmacclk: gmacclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + }; + + rpsclk: rpsclk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <1>; + clock-mult = <1>; + clocks = <&osc>; + }; + + pll400: pll400 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <733333333>; + }; + + sysclk: sysclk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clocks = <&pll400>; + }; + + armclk: armclk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clocks = <&pll400>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + interrupt-parent = <&intc>; + + apb-bridge@44000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0 0x44000000 0x1000000>; + + pinctrl: pinctrl { + compatible = "oxsemi,ox810se-pinctrl"; + + /* Regmap for sys registers */ + oxsemi,sys-ctrl = <&sys>; + + pinctrl_uart0: uart0 { + uart0a { + pins = "gpio31"; + function = "fct3"; + }; + uart0b { + pins = "gpio32"; + function = "fct3"; + }; + }; + + pinctrl_uart0_modem: uart0_modem { + uart0c { + pins = "gpio27"; + function = "fct3"; + }; + uart0d { + pins = "gpio28"; + function = "fct3"; + }; + uart0e { + pins = "gpio29"; + function = "fct3"; + }; + uart0f { + pins = "gpio30"; + function = "fct3"; + }; + uart0g { + pins = "gpio33"; + function = "fct3"; + }; + uart0h { + pins = "gpio34"; + function = "fct3"; + }; + }; + + pinctrl_uart1: uart1 { + uart1a { + pins = "gpio20"; + function = "fct3"; + }; + uart1b { + pins = "gpio22"; + function = "fct3"; + }; + }; + + pinctrl_uart1_modem: uart1_modem { + uart1c { + pins = "gpio8"; + function = "fct3"; + }; + uart1d { + pins = "gpio9"; + function = "fct3"; + }; + uart1e { + pins = "gpio23"; + function = "fct3"; + }; + uart1f { + pins = "gpio24"; + function = "fct3"; + }; + uart1g { + pins = "gpio25"; + function = "fct3"; + }; + uart1h { + pins = "gpio26"; + function = "fct3"; + }; + }; + + pinctrl_uart2: uart2 { + uart2a { + pins = "gpio6"; + function = "fct3"; + }; + uart2b { + pins = "gpio7"; + function = "fct3"; + }; + }; + + pinctrl_uart2_modem: uart2_modem { + uart2c { + pins = "gpio0"; + function = "fct3"; + }; + uart2d { + pins = "gpio1"; + function = "fct3"; + }; + uart2e { + pins = "gpio2"; + function = "fct3"; + }; + uart2f { + pins = "gpio3"; + function = "fct3"; + }; + uart2g { + pins = "gpio4"; + function = "fct3"; + }; + uart2h { + pins = "gpio5"; + function = "fct3"; + }; + }; + }; + + gpio0: gpio@000000 { + compatible = "oxsemi,ox810se-gpio"; + reg = <0x000000 0x100000>; + interrupts = <21>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + ngpios = <32>; + oxsemi,gpio-bank = <0>; + gpio-ranges = <&pinctrl 0 0 32>; + }; + + gpio1: gpio@100000 { + compatible = "oxsemi,ox810se-gpio"; + reg = <0x100000 0x100000>; + interrupts = <22>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + ngpios = <3>; + oxsemi,gpio-bank = <1>; + gpio-ranges = <&pinctrl 0 32 3>; + }; + + uart0: serial@200000 { + compatible = "ns16550a"; + reg = <0x200000 0x100000>; + clocks = <&sysclk>; + interrupts = <23>; + reg-shift = <0>; + fifo-size = <16>; + reg-io-width = <1>; + current-speed = <115200>; + no-loopback-test; + status = "disabled"; + resets = <&reset 17>; + }; + + uart1: serial@300000 { + compatible = "ns16550a"; + reg = <0x300000 0x100000>; + clocks = <&sysclk>; + interrupts = <24>; + reg-shift = <0>; + fifo-size = <16>; + reg-io-width = <1>; + current-speed = <115200>; + no-loopback-test; + status = "disabled"; + resets = <&reset 18>; + }; + + uart2: serial@900000 { + compatible = "ns16550a"; + reg = <0x900000 0x100000>; + clocks = <&sysclk>; + interrupts = <29>; + reg-shift = <0>; + fifo-size = <16>; + reg-io-width = <1>; + current-speed = <115200>; + no-loopback-test; + status = "disabled"; + resets = <&reset 22>; + }; + + uart3: serial@a00000 { + compatible = "ns16550a"; + reg = <0xa00000 0x100000>; + clocks = <&sysclk>; + interrupts = <30>; + reg-shift = <0>; + fifo-size = <16>; + reg-io-width = <1>; + current-speed = <115200>; + no-loopback-test; + status = "disabled"; + resets = <&reset 23>; + }; + }; + + apb-bridge@45000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0 0x45000000 0x1000000>; + + sys: sys-ctrl@000000 { + compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"; + reg = <0x000000 0x100000>; + + reset: reset-controller { + compatible = "oxsemi,ox810se-reset"; + #reset-cells = <1>; + }; + + stdclk: stdclk { + compatible = "oxsemi,ox810se-stdclk"; + #clock-cells = <1>; + }; + }; + + rps@300000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0 0x300000 0x100000>; + + intc: interrupt-controller@0 { + compatible = "oxsemi,ox810se-rps-irq"; + interrupt-controller; + reg = <0 0x200>; + #interrupt-cells = <1>; + valid-mask = <0xFFFFFFFF>; + clear-mask = <0>; + }; + + timer0: timer@200 { + compatible = "oxsemi,ox810se-rps-timer"; + reg = <0x200 0x40>; + clocks = <&rpsclk>; + interrupts = <4 5>; + }; + }; + }; + }; +}; -- GitLab From 07609675add33ef34e880db05aaeef3c93d1aab2 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 3 Mar 2016 10:45:50 +0100 Subject: [PATCH 4395/9938] dt-bindings: Add OXNAS bindings Acked-by: Rob Herring Signed-off-by: Neil Armstrong --- Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt new file mode 100644 index 000000000000..b9e49711ba05 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/oxnas.txt @@ -0,0 +1,9 @@ +Oxford Semiconductor OXNAS SoCs Family device tree bindings +------------------------------------------- + +Boards with the OX810SE SoC shall have the following properties: + Required root node property: + compatible: "oxsemi,ox810se" + +Board compatible values: + - "wd,mbwe" (OX810SE) -- GitLab From f85d8ffbecadf72d2d80077f5fabba820ea4c55b Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 3 Mar 2016 10:53:31 +0100 Subject: [PATCH 4396/9938] dt-bindings: Add Western Digital to vendor prefixes Acked-by: Rob Herring Signed-off-by: Neil Armstrong --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 53ca9a2a3d6a..56aa17ff3a3a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -260,6 +260,7 @@ via VIA Technologies, Inc. virtio Virtual I/O Device Specification, developed by the OASIS consortium vivante Vivante Corporation voipac Voipac Technologies s.r.o. +wd Western Digital Corp. wexler Wexler winbond Winbond Electronics corp. wlf Wolfson Microelectronics -- GitLab From 0767a5cb425374aafa89d33d6b1190a01d7f6b0e Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 3 Mar 2016 10:53:57 +0100 Subject: [PATCH 4397/9938] ARM: boot: dts: Add Western Digital My Book World Edition device tree Add Western Digital My Book World Edition device tree based on Oxford Semiconductor OX810SE SoC. Signed-off-by: Neil Armstrong --- arch/arm/boot/dts/Makefile | 2 + arch/arm/boot/dts/wd-mbwe.dts | 112 ++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 arch/arm/boot/dts/wd-mbwe.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..7005585030ae 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -538,6 +538,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \ orion5x-rd88f5182-nas.dtb dtb-$(CONFIG_ARCH_PRIMA2) += \ prima2-evb.dtb +dtb-$(CONFIG_ARCH_OXNAS) += \ + wd-mbwe.dtb dtb-$(CONFIG_ARCH_QCOM) += \ qcom-apq8064-cm-qs600.dtb \ qcom-apq8064-ifc6410.dtb \ diff --git a/arch/arm/boot/dts/wd-mbwe.dts b/arch/arm/boot/dts/wd-mbwe.dts new file mode 100644 index 000000000000..ac3250ae8fc4 --- /dev/null +++ b/arch/arm/boot/dts/wd-mbwe.dts @@ -0,0 +1,112 @@ +/* + * wd-mbwe.dtsi - Device tree file for Western Digital My Book World Edition + * + * Copyright (C) 2016 Neil Armstrong + * + * Licensed under GPLv2 or later + */ + +/dts-v1/; +#include "ox810se.dtsi" + +/ { + model = "Western Digital My Book World Edition"; + + compatible = "wd,mbwe", "oxsemi,ox810se"; + + chosen { + bootargs = "console=ttyS1,115200n8 earlyprintk=serial"; + }; + + memory { + /* 128Mbytes DDR */ + reg = <0x48000000 0x8000000>; + }; + + aliases { + serial1 = &uart1; + gpio0 = &gpio0; + gpio1 = &gpio1; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + power { + label = "power"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + recovery { + label = "recovery"; + gpios = <&gpio0 4 1>; + linux,code = <0xab>; + }; + }; + + leds { + compatible = "gpio-leds"; + + a0 { + label = "activity0"; + gpios = <&gpio0 25 0>; + default-state = "keep"; + }; + + a1 { + label = "activity1"; + gpios = <&gpio0 26 0>; + default-state = "keep"; + }; + + a2 { + label = "activity2"; + gpios = <&gpio0 5 0>; + default-state = "keep"; + }; + + a3 { + label = "activity3"; + gpios = <&gpio0 6 0>; + default-state = "keep"; + }; + + a4 { + label = "activity4"; + gpios = <&gpio0 7 0>; + default-state = "keep"; + }; + + a5 { + label = "activity5"; + gpios = <&gpio1 2 0>; + default-state = "keep"; + }; + }; + + i2c-gpio { + compatible = "i2c-gpio"; + gpios = <&gpio0 3 0 /* sda */ + &gpio0 2 0 /* scl */ + >; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + + rtc0: rtc@48 { + compatible = "st,m41t00"; + reg = <0x68>; + }; + }; +}; + +&uart1 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; +}; -- GitLab From 58a8738cfcdec389b3764a636303f97b57f85193 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 10 Mar 2016 21:03:09 +0100 Subject: [PATCH 4398/9938] ALSA: au88x0: Fix overlapped PCM pointer au88x0 hardware seems returning the current pointer at the buffer boundary instead of going back to zero. This results in spewing warnings from PCM core. This patch corrects the return value from the pointer callback within the proper value range, just returning zero if the position is equal or above the buffer size. Signed-off-by: Takashi Iwai --- sound/pci/au88x0/au88x0_pcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index a6d6d8d0867a..df5741a78fd2 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c @@ -432,7 +432,10 @@ static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substr #endif //printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr); spin_unlock(&chip->lock); - return (bytes_to_frames(substream->runtime, current_ptr)); + current_ptr = bytes_to_frames(substream->runtime, current_ptr); + if (current_ptr >= substream->runtime->buffer_size) + current_ptr = 0; + return current_ptr; } /* operators */ -- GitLab From ba79d401f1aee52186ff09607e9405cfb805307d Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 25 Apr 2016 17:55:08 +0200 Subject: [PATCH 4399/9938] kbuild: fix call to adjust_autoksyms.sh when output directory specified When a different output directory is specified during the build process (with O= or KBUILD_OUTPUT), the call to adjust_autoksyms.sh script fails with the following error: /bin/sh scripts/adjust_autoksyms.sh \ "make KBUILD_MODULES=1 -f ../Makefile autoksyms_recursive" /bin/sh: scripts/adjust_autoksyms.sh: No such file or directory make[2]: *** [vmlinux] Error 127 make[1]: *** [sub-make] Error 2 make: *** [__sub-make] Error 2 Using the absolute path with $(srctree) variable solves the problem. This is in case the CONFIG_TRIM_UNUSED_KSYMS option is specified. Signed-off-by: Nicolas Ferre Fixes: 23121ca2b56b ("kbuild: create/adjust generated/autoksyms.h") Cc: Nicolas Pitre Cc: Rusty Russell Signed-off-by: Michal Marek --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e3af48068c65..e9ad498238e7 100644 --- a/Makefile +++ b/Makefile @@ -934,7 +934,7 @@ quiet_cmd_link-vmlinux = LINK $@ # execute if the rest of the kernel build went well. vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE ifdef CONFIG_TRIM_UNUSED_KSYMS - $(Q)$(CONFIG_SHELL) scripts/adjust_autoksyms.sh \ + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile autoksyms_recursive" endif ifdef CONFIG_HEADERS_CHECK @@ -949,13 +949,13 @@ endif +$(call if_changed,link-vmlinux) autoksyms_recursive: $(vmlinux-deps) - $(Q)$(CONFIG_SHELL) scripts/adjust_autoksyms.sh \ + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile autoksyms_recursive" PHONY += autoksyms_recursive # standalone target for easier testing include/generated/autoksyms.h: FORCE - $(Q)$(CONFIG_SHELL) scripts/adjust_autoksyms.sh true + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh true # Build samples along the rest of the kernel ifdef CONFIG_SAMPLES -- GitLab From 2441e78b19192cd9ea1ce93027a5732a2117f026 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 22 Apr 2016 15:25:00 -0400 Subject: [PATCH 4400/9938] kbuild: better abstract vmlinux sequential prerequisites When CONFIG_TRIM_UNUSED_KSYMS=y and CONFIG_BUILD_DOCSRC=y it is possible to get the following error: ERROR: "cn_del_callback" [Documentation/connector/cn_test.ko] undefined! ERROR: "cn_add_callback" [Documentation/connector/cn_test.ko] undefined! ERROR: "cn_netlink_send" [Documentation/connector/cn_test.ko] undefined! ../scripts/Makefile.modpost:91: recipe for target '__modpost' failed It is not sufficient to do "vmlinux-dirs += Documentation" as this also depends on the headers_check target, and all of this needs to be done before adjust_autoksyms.sh is executed. Let's sort this out by gathering those sequential prerequisites in a make target of their own, separate from the vmlinux target. And by doing so, the special autoksyms_recursive target is no longer needed. Signed-off-by: Nicolas Pitre Acked-by: Randy Dunlap Tested-by: Randy Dunlap --- Makefile | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index e9ad498238e7..3f1eb6a1bf8d 100644 --- a/Makefile +++ b/Makefile @@ -926,17 +926,11 @@ export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) arch Doc vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) -# Final link of vmlinux - cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -quiet_cmd_link-vmlinux = LINK $@ - -# Include targets which we want to -# execute if the rest of the kernel build went well. -vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE -ifdef CONFIG_TRIM_UNUSED_KSYMS - $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ - "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile autoksyms_recursive" -endif +# Include targets which we want to execute sequentially if the rest of the +# kernel build went well. If CONFIG_TRIM_UNUSED_KSYMS is set, this might be +# evaluated more than once. +PHONY += vmlinux_prereq +vmlinux_prereq: $(vmlinux-deps) FORCE ifdef CONFIG_HEADERS_CHECK $(Q)$(MAKE) -f $(srctree)/Makefile headers_check endif @@ -946,17 +940,22 @@ endif ifdef CONFIG_GDB_SCRIPTS $(Q)ln -fsn `cd $(srctree) && /bin/pwd`/scripts/gdb/vmlinux-gdb.py endif - +$(call if_changed,link-vmlinux) - -autoksyms_recursive: $(vmlinux-deps) +ifdef CONFIG_TRIM_UNUSED_KSYMS $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ - "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile autoksyms_recursive" -PHONY += autoksyms_recursive + "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile vmlinux_prereq" +endif # standalone target for easier testing include/generated/autoksyms.h: FORCE $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh true +# Final link of vmlinux + cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) +quiet_cmd_link-vmlinux = LINK $@ + +vmlinux: scripts/link-vmlinux.sh vmlinux_prereq FORCE + +$(call if_changed,link-vmlinux) + # Build samples along the rest of the kernel ifdef CONFIG_SAMPLES vmlinux-dirs += samples -- GitLab From 44c7288f791fa804a88f97496291ecf698fb3887 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 24 Apr 2016 11:36:59 +0200 Subject: [PATCH 4401/9938] gpio: move gpiod_set_array_value_priv() This renames gpiod_set_array_value_priv() to gpiod_set_array_value_complex() and moves it to the gpiolib.h private header file so we can reuse it in the subsystem. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 24 ++++++++++++------------ drivers/gpio/gpiolib.h | 4 ++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 59a0d8e98a04..bb3195d5e3af 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1825,10 +1825,10 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip, } } -static void gpiod_set_array_value_priv(bool raw, bool can_sleep, - unsigned int array_size, - struct gpio_desc **desc_array, - int *value_array) +void gpiod_set_array_value_complex(bool raw, bool can_sleep, + unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array) { int i = 0; @@ -1934,8 +1934,8 @@ void gpiod_set_raw_array_value(unsigned int array_size, { if (!desc_array) return; - gpiod_set_array_value_priv(true, false, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(true, false, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value); @@ -1956,8 +1956,8 @@ void gpiod_set_array_value(unsigned int array_size, { if (!desc_array) return; - gpiod_set_array_value_priv(false, false, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(false, false, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_array_value); @@ -2160,8 +2160,8 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size, might_sleep_if(extra_checks); if (!desc_array) return; - gpiod_set_array_value_priv(true, true, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(true, true, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep); @@ -2183,8 +2183,8 @@ void gpiod_set_array_value_cansleep(unsigned int array_size, might_sleep_if(extra_checks); if (!desc_array) return; - gpiod_set_array_value_priv(false, true, array_size, desc_array, - value_array); + gpiod_set_array_value_complex(false, true, array_size, desc_array, + value_array); } EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index e30e5fdb1214..2d9ea5e0cab3 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -141,6 +141,10 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags); struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum); +void gpiod_set_array_value_complex(bool raw, bool can_sleep, + unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array); extern struct spinlock gpio_lock; extern struct list_head gpio_devices; -- GitLab From a89d6cb3b3c3226dfd8118eea7ec2b19635738f6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 14:47:50 +0200 Subject: [PATCH 4402/9938] gpio: revert bank bindings Keep the words talking about what a GPIO bank is, but remove the binding. We have not agreed that this is something we want to have. Acked-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index f509ecf03ece..c88d2ccb05ca 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -138,12 +138,6 @@ exposed in the device tree as an individual gpio-controller node, reflecting the fact that the hardware was synthesized by reusing the same IP block a few times over. -A GPIO controller may specify a bank ID. This is a hardware index that -indicate the logical order of the GPIO controller in the hardware architecture, -usually in the sequence 0, 1, 2 .. n. The hardware index may be different -from the order of register ranges and related to the backplane of how this -one bank is connected to the outside through a pin controller for example. - Optionally, a GPIO controller may have a "ngpios" property. This property indicates the number of in-use slots of available slots for GPIOs. The typical example is something like this: the hardware register is 32 bits @@ -165,7 +159,6 @@ gpio-controller@00000000 { reg = <0x00000000 0x1000>; gpio-controller; #gpio-cells = <2>; - gpio-bank = <0>; ngpios = <18>; } -- GitLab From e4c8b456c53d4beee5adaf5768c762171e2244f3 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 18 Mar 2016 13:27:09 +1100 Subject: [PATCH 4403/9938] rtl818x_pci: Fix a memory leak in rtl8180_init_rx_ring When dev_alloc_skb or pci_dma_mapping_error in rtl8180_init_rx_ring fails, the memory allocated by pci_zalloc_consistent is not freed. This patch fixes the bug by adding pci_free_consistent in error handling code. Signed-off-by: Jia-Ju Bai Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index ba242d0160ec..e895a84481da 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -1018,6 +1018,8 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) dma_addr_t *mapping; entry = priv->rx_ring + priv->rx_ring_sz*i; if (!skb) { + pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32, + priv->rx_ring, priv->rx_ring_dma); wiphy_err(dev->wiphy, "Cannot allocate RX skb\n"); return -ENOMEM; } @@ -1028,6 +1030,8 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) if (pci_dma_mapping_error(priv->pdev, *mapping)) { kfree_skb(skb); + pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32, + priv->rx_ring, priv->rx_ring_dma); wiphy_err(dev->wiphy, "Cannot map DMA for RX skb\n"); return -ENOMEM; } -- GitLab From 706a527ca32b3bf950754631fa42982c0f1c060b Mon Sep 17 00:00:00 2001 From: Tina Ruchandani Date: Tue, 12 Apr 2016 23:09:16 -0700 Subject: [PATCH 4404/9938] prism54: isl_38xx: Replace 'struct timeval' 'struct timeval' uses a 32-bit seconds field which will overflow in year 2038 and beyond. This patch is part of a larger effort to remove all instances of 'struct timeval' from the kernel and replace them with 64-bit timekeeping variables. The patch also fixes the debug printf specifier to avoid the seconds value being truncated. The patch was build-tested / debugged by removing the "if VERBOSE > SHOW_ERROR_MESSAGES" guards. Signed-off-by: Tina Ruchandani Suggested-by: Arnd Bergmann Signed-off-by: Kalle Valo --- .../net/wireless/intersil/prism54/isl_38xx.c | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/intersil/prism54/isl_38xx.c b/drivers/net/wireless/intersil/prism54/isl_38xx.c index 333c1a2f882e..6700387ef9ab 100644 --- a/drivers/net/wireless/intersil/prism54/isl_38xx.c +++ b/drivers/net/wireless/intersil/prism54/isl_38xx.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -113,7 +114,7 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) #if VERBOSE > SHOW_ERROR_MESSAGES u32 counter = 0; - struct timeval current_time; + struct timespec64 current_ts64; DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); #endif @@ -121,22 +122,22 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) if (asleep) { /* device is in powersave, trigger the device for wakeup */ #if VERBOSE > SHOW_ERROR_MESSAGES - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", - current_time.tv_sec, (long)current_time.tv_usec); + ktime_get_real_ts64(¤t_ts64); + DEBUG(SHOW_TRACING, "%lld.%09ld Device wakeup triggered\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec); - DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, + DEBUG(SHOW_TRACING, "%lld.%09ld Device register read %08x\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, readl(device_base + ISL38XX_CTRL_STAT_REG)); #endif reg = readl(device_base + ISL38XX_INT_IDENT_REG); if (reg == 0xabadface) { #if VERBOSE > SHOW_ERROR_MESSAGES - do_gettimeofday(¤t_time); + ktime_get_real_ts64(¤t_ts64); DEBUG(SHOW_TRACING, - "%08li.%08li Device register abadface\n", - current_time.tv_sec, (long)current_time.tv_usec); + "%lld.%09ld Device register abadface\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec); #endif /* read the Device Status Register until Sleepmode bit is set */ while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG), @@ -149,13 +150,13 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, - "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, + "%lld.%09ld Device register read %08x\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, readl(device_base + ISL38XX_CTRL_STAT_REG)); - do_gettimeofday(¤t_time); + ktime_get_real_ts64(¤t_ts64); DEBUG(SHOW_TRACING, - "%08li.%08li Device asleep counter %i\n", - current_time.tv_sec, (long)current_time.tv_usec, + "%lld.%09ld Device asleep counter %i\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, counter); #endif } @@ -168,9 +169,9 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) /* perform another read on the Device Status Register */ reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, reg); + ktime_get_real_ts64(¤t_ts64); + DEBUG(SHOW_TRACING, "%lld.%00ld Device register read %08x\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, reg); #endif } else { /* device is (still) awake */ -- GitLab From 005a425b24e101d312eca669b96a6b71d75e97fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Fri, 15 Apr 2016 08:50:25 +0200 Subject: [PATCH 4405/9938] rtlwifi: rtl8821ae: Make sure loop counter is signed on all architectures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The for-loop condition does not work correctly on architectures where "char" is unsigned. Fix it by using an "int", which may also result in more efficient code. Signed-off-by: David Müller Acked-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index ddf74d527017..0c3b9ce86e2e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -959,7 +959,7 @@ static void _rtl8821ae_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, u8 end, u8 base_val) { - char i = 0; + int i; u8 temp_value = 0; u32 temp_data = 0; -- GitLab From 7705ba6f7badb8cf38a0a19dad71e11a77ecb9cd Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Sun, 17 Apr 2016 16:44:58 +0200 Subject: [PATCH 4406/9938] brcmfmac: add support for nl80211 BSS_SELECT feature Announce support for nl80211 feature BSS_SELECT and process BSS selection behaviour provided in .connect() callback. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Lei Zhang Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 64 +++++++++++++++++++ .../broadcom/brcm80211/brcmfmac/common.c | 38 ++++++----- .../broadcom/brcm80211/brcmfmac/core.h | 1 + .../broadcom/brcm80211/brcmfmac/fwil.h | 1 + 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 8daad782b3c3..d0631b6cfd53 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -250,6 +250,20 @@ struct parsed_vndr_ies { struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; }; +static u8 nl80211_band_to_fwil(enum nl80211_band band) +{ + switch (band) { + case NL80211_BAND_2GHZ: + return WLC_BAND_2G; + case NL80211_BAND_5GHZ: + return WLC_BAND_5G; + default: + WARN_ON(1); + break; + } + return 0; +} + static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, struct cfg80211_chan_def *ch) { @@ -1796,6 +1810,50 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, return type; } +static void brcmf_set_join_pref(struct brcmf_if *ifp, + struct cfg80211_bss_selection *bss_select) +{ + struct brcmf_join_pref_params join_pref_params[2]; + enum nl80211_band band; + int err, i = 0; + + join_pref_params[i].len = 2; + join_pref_params[i].rssi_gain = 0; + + if (bss_select->behaviour != NL80211_BSS_SELECT_ATTR_BAND_PREF) + brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_ASSOC_PREFER, WLC_BAND_AUTO); + + switch (bss_select->behaviour) { + case __NL80211_BSS_SELECT_ATTR_INVALID: + brcmf_c_set_joinpref_default(ifp); + return; + case NL80211_BSS_SELECT_ATTR_BAND_PREF: + join_pref_params[i].type = BRCMF_JOIN_PREF_BAND; + band = bss_select->param.band_pref; + join_pref_params[i].band = nl80211_band_to_fwil(band); + i++; + break; + case NL80211_BSS_SELECT_ATTR_RSSI_ADJUST: + join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI_DELTA; + band = bss_select->param.adjust.band; + join_pref_params[i].band = nl80211_band_to_fwil(band); + join_pref_params[i].rssi_gain = bss_select->param.adjust.delta; + i++; + break; + case NL80211_BSS_SELECT_ATTR_RSSI: + default: + break; + } + join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI; + join_pref_params[i].len = 2; + join_pref_params[i].rssi_gain = 0; + join_pref_params[i].band = 0; + err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, + sizeof(join_pref_params)); + if (err) + brcmf_err("Set join_pref error (%d)\n", err); +} + static s32 brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) @@ -1952,6 +2010,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, ext_join_params->scan_le.nprobes = cpu_to_le32(-1); } + brcmf_set_join_pref(ifp, &sme->bss_select); + err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params, join_params_size); kfree(ext_join_params); @@ -6280,6 +6340,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites); if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) wiphy->n_cipher_suites--; + wiphy->bss_select_support = BIT(NL80211_BSS_SELECT_ATTR_RSSI) | + BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) | + BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST); + wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 9e909e3c2f0c..3e15d64c6481 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -38,7 +38,7 @@ const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 -/* boost value for RSSI_DELTA in preferred join selection */ +/* default boost value for RSSI_DELTA in preferred join selection */ #define BRCMF_JOIN_PREF_RSSI_BOOST 8 #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ @@ -83,11 +83,31 @@ MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging"); static struct brcmfmac_platform_data *brcmfmac_pdata; struct brcmf_mp_global_t brcmf_mp_global; +void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) +{ + struct brcmf_join_pref_params join_pref_params[2]; + int err; + + /* Setup join_pref to select target by RSSI (boost on 5GHz) */ + join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; + join_pref_params[0].len = 2; + join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; + join_pref_params[0].band = WLC_BAND_5G; + + join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; + join_pref_params[1].len = 2; + join_pref_params[1].rssi_gain = 0; + join_pref_params[1].band = 0; + err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, + sizeof(join_pref_params)); + if (err) + brcmf_err("Set join_pref error (%d)\n", err); +} + int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) { s8 eventmask[BRCMF_EVENTING_MASK_LEN]; u8 buf[BRCMF_DCMD_SMLEN]; - struct brcmf_join_pref_params join_pref_params[2]; struct brcmf_rev_info_le revinfo; struct brcmf_rev_info *ri; char *ptr; @@ -154,19 +174,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) goto done; } - /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ - join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; - join_pref_params[0].len = 2; - join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; - join_pref_params[0].band = WLC_BAND_5G; - join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; - join_pref_params[1].len = 2; - join_pref_params[1].rssi_gain = 0; - join_pref_params[1].band = 0; - err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, - sizeof(join_pref_params)); - if (err) - brcmf_err("Set join_pref error (%d)\n", err); + brcmf_c_set_joinpref_default(ifp); /* Setup event_msgs, enable E_IF */ err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 241ee8d13e54..647d3cc2a4dc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -223,6 +223,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); +void brcmf_c_set_joinpref_default(struct brcmf_if *ifp); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index 6b72df17744e..3a9a76dd9222 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -78,6 +78,7 @@ #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 +#define BRCMF_C_SET_ASSOC_PREFER 205 #define BRCMF_C_GET_VALID_CHANNELS 217 #define BRCMF_C_GET_KEY_PRIMARY 235 #define BRCMF_C_SET_KEY_PRIMARY 236 -- GitLab From 53985dccb1c98b7af080e2314bff0c5024e781b0 Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Sun, 17 Apr 2016 15:25:03 +0200 Subject: [PATCH 4407/9938] brcmf: Fix null pointer exception in bcdc_hdrpull In fwsignal.c: brcmf_fws_commit_skb() ... if (rc < 0) { entry->transit_count--; if (entry->suppressed) entry->suppr_transit_count--; (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL); ^^^^^^^ goto rollback; } ... The call to hdrpull will trigger a null pointer exception unless a null check is made in the method implementation. Signed-off-by: Per Forlin Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 288fe906c80e..d1bc51f92686 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -321,7 +321,8 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, if (pktbuf->len == 0) return -ENODATA; - *ifp = tmp_if; + if (ifp != NULL) + *ifp = tmp_if; return 0; } -- GitLab From 84039920bdff60030b2b79e50e4c9d230ae00dad Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 18 Apr 2016 05:22:22 -0700 Subject: [PATCH 4408/9938] dt: bindings: add MARVELL's sd8xxx wireless device Add device tree binding documentation for MARVELL's sd8xxx (sd8897 and sd8997) wlan chip. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Acked-by: Rob Herring Signed-off-by: Kalle Valo --- .../bindings/net/wireless/marvell-sd8xxx.txt | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt diff --git a/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt b/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt new file mode 100644 index 000000000000..c421aba0a5bc --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt @@ -0,0 +1,63 @@ +Marvell 8897/8997 (sd8897/sd8997) SDIO devices +------ + +This node provides properties for controlling the marvell sdio wireless device. +The node is expected to be specified as a child node to the SDIO controller that +connects the device to the system. + +Required properties: + + - compatible : should be one of the following: + * "marvell,sd8897" + * "marvell,sd8997" + +Optional properties: + + - marvell,caldata* : A series of properties with marvell,caldata prefix, + represent calibration data downloaded to the device during + initialization. This is an array of unsigned 8-bit values. + the properties should follow below property name and + corresponding array length: + "marvell,caldata-txpwrlimit-2g" (length = 566). + "marvell,caldata-txpwrlimit-5g-sub0" (length = 502). + "marvell,caldata-txpwrlimit-5g-sub1" (length = 688). + "marvell,caldata-txpwrlimit-5g-sub2" (length = 750). + "marvell,caldata-txpwrlimit-5g-sub3" (length = 502). + - marvell,wakeup-pin : a wakeup pin number of wifi chip which will be configured + to firmware. Firmware will wakeup the host using this pin + during suspend/resume. + - interrupt-parent: phandle of the parent interrupt controller + - interrupts : interrupt pin number to the cpu. driver will request an irq based on + this interrupt number. during system suspend, the irq will be enabled + so that the wifi chip can wakeup host platform under certain condition. + during system resume, the irq will be disabled to make sure + unnecessary interrupt is not received. + +Example: + +Tx power limit calibration data is configured in below example. +The calibration data is an array of unsigned values, the length +can vary between hw versions. +IRQ pin 38 is used as system wakeup source interrupt. wakeup pin 3 is configured +so that firmware can wakeup host using this device side pin. + +&mmc3 { + status = "okay"; + vmmc-supply = <&wlan_en_reg>; + bus-width = <4>; + cap-power-off-card; + keep-power-in-suspend; + + #address-cells = <1>; + #size-cells = <0>; + mwifiex: wifi@1 { + compatible = "marvell,sd8897"; + reg = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_LOW>; + + marvell,caldata_00_txpwrlimit_2g_cfg_set = /bits/ 8 < + 0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01>; + marvell,wakeup-pin = <3>; + }; +}; -- GitLab From ce4f6f0c353b7bfd7b527667287a87fd83aea119 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 18 Apr 2016 05:22:23 -0700 Subject: [PATCH 4409/9938] mwifiex: add platform specific wakeup interrupt support On some arm-based platforms, we need to configure platform specific parameters by device tree node and also define our node as a child node of parent SDIO host controller. This patch parses these parameters from device tree. It includes calibration data dowoload to firmware, wakeup pin configured to firmware, and soc specific wake up gpio, which will be set as wakeup interrupt pin. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.h | 11 +++ drivers/net/wireless/marvell/mwifiex/sdio.c | 77 +++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/sdio.h | 7 ++ .../net/wireless/marvell/mwifiex/sta_cmd.c | 14 +++- 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 63069dd8b8e8..4c742a597cb0 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -37,6 +37,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "decl.h" #include "ioctl.h" diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index a0aec3e00457..cbd9dcd88b98 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -73,6 +73,66 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = { {"EXTLAST", NULL, 0, 0xFE}, }; +static const struct of_device_id mwifiex_sdio_of_match_table[] = { + { .compatible = "marvell,sd8897" }, + { .compatible = "marvell,sd8997" }, + { } +}; + +static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv) +{ + struct mwifiex_plt_wake_cfg *cfg = priv; + + if (cfg->irq_wifi >= 0) { + pr_info("%s: wake by wifi", __func__); + cfg->wake_by_wifi = true; + disable_irq_nosync(irq); + } + + return IRQ_HANDLED; +} + +/* This function parse device tree node using mmc subnode devicetree API. + * The device node is saved in card->plt_of_node. + * if the device tree node exist and include interrupts attributes, this + * function will also request platform specific wakeup interrupt. + */ +static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card) +{ + struct mwifiex_plt_wake_cfg *cfg; + int ret; + + if (!dev->of_node || + !of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) { + pr_err("sdio platform data not available"); + return -1; + } + + card->plt_of_node = dev->of_node; + card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg), + GFP_KERNEL); + cfg = card->plt_wake_cfg; + if (cfg && card->plt_of_node) { + cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0); + if (!cfg->irq_wifi) { + dev_err(dev, "fail to parse irq_wifi from device tree"); + } else { + ret = devm_request_irq(dev, cfg->irq_wifi, + mwifiex_wake_irq_wifi, + IRQF_TRIGGER_LOW, + "wifi_wake", cfg); + if (ret) { + dev_err(dev, + "Failed to request irq_wifi %d (%d)\n", + cfg->irq_wifi, ret); + } + disable_irq(cfg->irq_wifi); + } + } + + return 0; +} + /* * SDIO probe. * @@ -127,6 +187,9 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) return -EIO; } + /* device tree node parsing and platform specific configuration*/ + mwifiex_sdio_probe_of(&func->dev, card); + if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops, MWIFIEX_SDIO)) { pr_err("%s: add card failed\n", __func__); @@ -183,6 +246,13 @@ static int mwifiex_sdio_resume(struct device *dev) mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), MWIFIEX_SYNC_CMD); + /* Disable platform specific wakeup interrupt */ + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) { + disable_irq_wake(card->plt_wake_cfg->irq_wifi); + if (!card->plt_wake_cfg->wake_by_wifi) + disable_irq(card->plt_wake_cfg->irq_wifi); + } + return 0; } @@ -262,6 +332,13 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; + /* Enable platform specific wakeup interrupt */ + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) { + card->plt_wake_cfg->wake_by_wifi = false; + enable_irq(card->plt_wake_cfg->irq_wifi); + enable_irq_wake(card->plt_wake_cfg->irq_wifi); + } + /* Enable the Host Sleep */ if (!mwifiex_enable_hs(adapter)) { mwifiex_dbg(adapter, ERROR, diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h index b9fbc5cf6262..db837f12c547 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.h +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h @@ -154,6 +154,11 @@ a->mpa_rx.start_port = 0; \ } while (0) +struct mwifiex_plt_wake_cfg { + int irq_wifi; + bool wake_by_wifi; +}; + /* data structure for SDIO MPA TX */ struct mwifiex_sdio_mpa_tx { /* multiport tx aggregation buffer pointer */ @@ -237,6 +242,8 @@ struct mwifiex_sdio_card_reg { struct sdio_mmc_card { struct sdio_func *func; struct mwifiex_adapter *adapter; + struct device_node *plt_of_node; + struct mwifiex_plt_wake_cfg *plt_wake_cfg; const char *firmware; const struct mwifiex_sdio_card_reg *reg; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 8cb895b7f2ee..e436574b1698 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -2162,6 +2162,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) enum state_11d_t state_11d; struct mwifiex_ds_11n_tx_cfg tx_cfg; u8 sdio_sp_rx_aggr_enable; + int data; if (first_sta) { if (priv->adapter->iface_type == MWIFIEX_PCIE) { @@ -2182,9 +2183,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) * The cal-data can be read from device tree and/or * a configuration file and downloaded to firmware. */ - adapter->dt_node = - of_find_node_by_name(NULL, "marvell_cfgdata"); - if (adapter->dt_node) { + if (priv->adapter->iface_type == MWIFIEX_SDIO && + adapter->dev->of_node) { + adapter->dt_node = adapter->dev->of_node; + if (of_property_read_u32(adapter->dt_node, + "marvell,wakeup-pin", + &data) == 0) { + pr_debug("Wakeup pin = 0x%x\n", data); + adapter->hs_cfg.gpio = data; + } + ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, "marvell,caldata"); if (ret) -- GitLab From eaf46b5fda3acd75df68f02d25754dccb446ec2d Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 18 Apr 2016 06:42:55 -0700 Subject: [PATCH 4410/9938] mwifiex: stop background scan when net device closed Transmit data path should not touch background scan. We will stop background scan when net device is closed. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index b459c70dc43f..8b67a552a690 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -702,6 +702,13 @@ mwifiex_close(struct net_device *dev) priv->scan_aborting = true; } + if (priv->sched_scanning) { + mwifiex_dbg(priv->adapter, INFO, + "aborting bgscan on ndo_stop\n"); + mwifiex_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); + } + return 0; } @@ -753,13 +760,6 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) mwifiex_queue_main_work(priv->adapter); - if (priv->sched_scanning) { - mwifiex_dbg(priv->adapter, INFO, - "aborting bgscan on ndo_stop\n"); - mwifiex_stop_bg_scan(priv); - cfg80211_sched_scan_stopped(priv->wdev.wiphy); - } - return 0; } -- GitLab From a8c8dfa5931970a31794eeb65ced790fcff099d0 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:21 -0400 Subject: [PATCH 4411/9938] rtl8xxxu: Rename rtl8723bu_update_rate_mask() to rtl8xxxu_gen2_update_rate_mask() Update the name of rtl8723bu_update_rate_mask() to make it reflect it's applicable for all/most gen2 N parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 0ba84b5fe0d6..bea45095944f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8223,8 +8223,8 @@ static void rtl8723au_update_rate_mask(struct rtl8xxxu_priv *priv, rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.ramask)); } -static void rtl8723bu_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, int sgi) +static void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, + u32 ramask, int sgi) { struct h2c_cmd h2c; u8 bw = 0; @@ -9925,7 +9925,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .disable_rf = rtl8723b_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, - .update_rate_mask = rtl8723bu_update_rate_mask, + .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, .report_connect = rtl8723bu_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, @@ -9996,7 +9996,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .disable_rf = rtl8723b_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, - .update_rate_mask = rtl8723bu_update_rate_mask, + .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, .report_connect = rtl8723bu_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, -- GitLab From 32353a784f431185690919049b6951d309dc186e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:22 -0400 Subject: [PATCH 4412/9938] rtl8xxxu: Rename rtl8723bu_report_connect() to rtl8xxxu_gen2_report_connect() Make the name reflect this is for most/all gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index bea45095944f..4af0c33b71bd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8266,8 +8266,8 @@ static void rtl8723au_report_connect(struct rtl8xxxu_priv *priv, rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.joinbss)); } -static void rtl8723bu_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect) +static void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, + u8 macid, bool connect) { struct h2c_cmd h2c; @@ -9926,7 +9926,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, - .report_connect = rtl8723bu_report_connect, + .report_connect = rtl8xxxu_gen2_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, @@ -9997,7 +9997,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, - .report_connect = rtl8723bu_report_connect, + .report_connect = rtl8xxxu_gen2_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, -- GitLab From beb5531619c615f9b1d204d6d300dfe9e2fd454e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:23 -0400 Subject: [PATCH 4413/9938] rtl8xxxu: Rename rtl8723au_report_connect() to rtl8xxxu_gen1_report_connect() Rename the function to reflect it is for all/most gen1 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 4af0c33b71bd..882fa12266f9 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8249,8 +8249,8 @@ static void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.b_macid_cfg)); } -static void rtl8723au_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect) +static void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, + u8 macid, bool connect) { struct h2c_cmd h2c; @@ -9890,7 +9890,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, - .report_connect = rtl8723au_report_connect, + .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, @@ -9962,7 +9962,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, - .report_connect = rtl8723au_report_connect, + .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, -- GitLab From 3a56bf6aa13c1bb6e4012824e0897f32acbb1f04 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:24 -0400 Subject: [PATCH 4414/9938] rtl8xxxu: Rename rtl8723bu_config_channel() to rtl8xxxu_gen2_config_channel() Rename the function to indicate it is applicable to most/all gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 882fa12266f9..88e8fe92688f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2345,7 +2345,7 @@ static void rtl8723au_config_channel(struct ieee80211_hw *hw) } } -static void rtl8723bu_config_channel(struct ieee80211_hw *hw) +static void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; u32 val32, rsr; @@ -9917,7 +9917,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .init_phy_rf = rtl8723bu_init_phy_rf, .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, - .config_channel = rtl8723bu_config_channel, + .config_channel = rtl8xxxu_gen2_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .init_aggregation = rtl8723bu_init_aggregation, .init_statistics = rtl8723bu_init_statistics, @@ -9990,7 +9990,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .init_phy_bb = rtl8192eu_init_phy_bb, .init_phy_rf = rtl8192eu_init_phy_rf, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, - .config_channel = rtl8723bu_config_channel, + .config_channel = rtl8xxxu_gen2_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8192e_enable_rf, .disable_rf = rtl8723b_disable_rf, -- GitLab From 6a07b7915afe876195f8c8715ebc438c0b1d1348 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:25 -0400 Subject: [PATCH 4415/9938] rtl8xxxu: Rename rtl8723b_disable_rf() to rtl8xxxu_gen2_disable_rf() At least for now, all gen2 parts use the same disable_rf() function Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 88e8fe92688f..3499f9b2b9f6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7663,7 +7663,7 @@ static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv) rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.ignore_wlan)); } -static void rtl8723b_disable_rf(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen2_disable_rf(struct rtl8xxxu_priv *priv) { u32 val32; @@ -9922,7 +9922,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .init_aggregation = rtl8723bu_init_aggregation, .init_statistics = rtl8723bu_init_statistics, .enable_rf = rtl8723b_enable_rf, - .disable_rf = rtl8723b_disable_rf, + .disable_rf = rtl8xxxu_gen2_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, @@ -9993,7 +9993,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .config_channel = rtl8xxxu_gen2_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8192e_enable_rf, - .disable_rf = rtl8723b_disable_rf, + .disable_rf = rtl8xxxu_gen2_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, -- GitLab From 7eb1400c247934dc485817a2c2b62540121a6e55 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:26 -0400 Subject: [PATCH 4416/9938] rtl8xxxu: Rename rtl8723a_disable_rf() to rtl8xxxu_gen1_disable_rf() All currently supported gen1 parts use the same disable_rf() routine, so rename the function to reflect that. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3499f9b2b9f6..0d2beef089ff 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2124,7 +2124,7 @@ static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); } -static void rtl8723a_disable_rf(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_disable_rf(struct rtl8xxxu_priv *priv) { u8 sps0; u32 val32; @@ -9886,7 +9886,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, - .disable_rf = rtl8723a_disable_rf, + .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, @@ -9958,7 +9958,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, - .disable_rf = rtl8723a_disable_rf, + .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, -- GitLab From e09718c2fddfc68a14503ea2016970e48872e722 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:27 -0400 Subject: [PATCH 4417/9938] rtl8xxxu: Rename rtl8723au_config_channel() to rtl8xxxu_gen1_config_channel() All supported gen1 parts use the same config_channel() function, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 0d2beef089ff..e7f8039abe80 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2223,7 +2223,7 @@ static int rtl8723b_channel_to_group(int channel) return group; } -static void rtl8723au_config_channel(struct ieee80211_hw *hw) +static void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; u32 val32, rsr; @@ -9883,7 +9883,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8723au_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, - .config_channel = rtl8723au_config_channel, + .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, @@ -9955,7 +9955,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8192cu_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, - .config_channel = rtl8723au_config_channel, + .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, -- GitLab From c6e39da02e17bf3521f1c08df1555b6ffa77dee4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:28 -0400 Subject: [PATCH 4418/9938] rtl8xxxu: Rename rtl8723au_update_rate_mask() to rtl8xxxu_update_rate_mask() All currently supported gen1 parts use the same function for updating the rate mask, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index e7f8039abe80..c6d5d7267954 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8203,8 +8203,8 @@ static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); } -static void rtl8723au_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, int sgi) +static void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, + u32 ramask, int sgi) { struct h2c_cmd h2c; @@ -9889,7 +9889,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, - .update_rate_mask = rtl8723au_update_rate_mask, + .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT_0, @@ -9961,7 +9961,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, - .update_rate_mask = rtl8723au_update_rate_mask, + .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT_0, -- GitLab From 28466e9214029ef0978acfbaae0f02f78caa4ae9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:29 -0400 Subject: [PATCH 4419/9938] rtl8xxxu: Rename rtl8723au_phy_iq_calibrate() to rtl8xxxu_gen1_phy_iq_calibrate() All supported gen1 parts use the same phy_iq_calibrate() function (unlike their gen2 counterparts). Rename the function to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c6d5d7267954..31918475cd85 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6107,7 +6107,7 @@ static void rtl8xxxu_prepare_calibrate(struct rtl8xxxu_priv *priv, u8 start) rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.bt_wlan_calibration)); } -static void rtl8723au_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv) { struct device *dev = &priv->udev->dev; int result[4][8]; /* last is final result */ @@ -9882,7 +9882,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8723au_init_phy_rf, - .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, + .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, @@ -9954,7 +9954,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8192cu_init_phy_rf, - .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, + .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, -- GitLab From de7c189c342da635d8b17460b851fbe9b7f1e898 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:30 -0400 Subject: [PATCH 4420/9938] rtl8xxxu: Rename rtl8723au_init_phy_bb() to rtl8xxxu_gen1_init_phy_bb() All gen1 parts use the same init_phy_bb() function, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 31918475cd85..a0b9bd9cbad1 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3814,7 +3814,7 @@ static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, return 0; } -static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv) { u8 val8, ldoa15, ldov12d, lpldo, ldohci12; u16 val16; @@ -9880,7 +9880,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, - .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_bb = rtl8xxxu_gen1_init_phy_bb, .init_phy_rf = rtl8723au_init_phy_rf, .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, @@ -9952,7 +9952,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, - .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_bb = rtl8xxxu_gen1_init_phy_bb, .init_phy_rf = rtl8192cu_init_phy_rf, .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, -- GitLab From 42a3bc7a2a8525f9a3679e5dad19866ef34e2c09 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:31 -0400 Subject: [PATCH 4421/9938] rtl8xxxu: Rename rtl8723a_set_tx_power() to rtl8xxxu_gen1_set_tx_power() All gen1 parts use the same interface for setting TX power, so rename the function to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index a0b9bd9cbad1..843d4eac0d5a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2476,7 +2476,7 @@ static void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) } static void -rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) { struct rtl8xxxu_power_base *power_base = priv->power_base; u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS]; @@ -9888,7 +9888,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, - .set_tx_power = rtl8723a_set_tx_power, + .set_tx_power = rtl8xxxu_gen1_set_tx_power, .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 1024, @@ -9960,7 +9960,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, - .set_tx_power = rtl8723a_set_tx_power, + .set_tx_power = rtl8xxxu_gen1_set_tx_power, .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 128, -- GitLab From 8396a41cf7478f950f4682c1333771e1e4cf0b36 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:32 -0400 Subject: [PATCH 4422/9938] rtl8xxxu: Rename rtl8723a_enable_rf() to rtl8xxxu_gen1_enable_rf() All gen1 parts use the same enable_rf() function, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 843d4eac0d5a..7ed685cc3cbb 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2080,7 +2080,7 @@ static void rtl8723bu_write_btreg(struct rtl8xxxu_priv *priv, u8 reg, u8 data) rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.bt_mp_oper)); } -static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_enable_rf(struct rtl8xxxu_priv *priv) { u8 val8; u32 val32; @@ -9885,7 +9885,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, - .enable_rf = rtl8723a_enable_rf, + .enable_rf = rtl8xxxu_gen1_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8xxxu_gen1_set_tx_power, @@ -9957,7 +9957,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, - .enable_rf = rtl8723a_enable_rf, + .enable_rf = rtl8xxxu_gen1_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8xxxu_gen1_set_tx_power, -- GitLab From 8db71451e5c4ab5813e70b22a876e67a29a57a3f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:33 -0400 Subject: [PATCH 4423/9938] rtl8xxxu: Rename rtl8723a_mac_init_table to rtl8xxxu_gen1_mac_init_table All currently supported gen1 parts use the same mac_init_table, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7ed685cc3cbb..84c4bc65117b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -128,7 +128,7 @@ static struct ieee80211_supported_band rtl8xxxu_supported_band = { .n_bitrates = ARRAY_SIZE(rtl8xxxu_rates), }; -static struct rtl8xxxu_reg8val rtl8723a_mac_init_table[] = { +static struct rtl8xxxu_reg8val rtl8xxxu_gen1_mac_init_table[] = { {0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00}, {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05}, {0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00}, @@ -9903,7 +9903,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .trxff_boundary = 0x27ff, .pbp_rx = PBP_PAGE_SIZE_128, .pbp_tx = PBP_PAGE_SIZE_128, - .mactable = rtl8723a_mac_init_table, + .mactable = rtl8xxxu_gen1_mac_init_table, }; static struct rtl8xxxu_fileops rtl8723bu_fops = { @@ -9975,7 +9975,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .trxff_boundary = 0x27ff, .pbp_rx = PBP_PAGE_SIZE_128, .pbp_tx = PBP_PAGE_SIZE_128, - .mactable = rtl8723a_mac_init_table, + .mactable = rtl8xxxu_gen1_mac_init_table, }; #endif -- GitLab From 5ac74145487dbf93a109a06c8aec0da1395c35f5 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:34 -0400 Subject: [PATCH 4424/9938] rtl8xxxu: Rename rtl8723b_channel_to_group() This renames rtl8723b_channel_to_group() to rtl8xxxu_gen2_channel_to_group() to reflect it is used by all currently supported gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 84c4bc65117b..1f517d0bb4bb 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2205,7 +2205,7 @@ static int rtl8723a_channel_to_group(int channel) /* * Valid for rtl8723bu and rtl8192eu */ -static int rtl8723b_channel_to_group(int channel) +static int rtl8xxxu_gen2_channel_to_group(int channel) { int group; @@ -2617,7 +2617,7 @@ rtl8723b_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) int group, tx_idx; tx_idx = 0; - group = rtl8723b_channel_to_group(channel); + group = rtl8xxxu_gen2_channel_to_group(channel); cck = priv->cck_tx_power_index_B[group]; val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32); @@ -2656,7 +2656,7 @@ rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) int group, tx_idx; tx_idx = 0; - group = rtl8723b_channel_to_group(channel); + group = rtl8xxxu_gen2_channel_to_group(channel); cck = priv->cck_tx_power_index_A[group]; -- GitLab From 85f466350abf3a7eeb579a3abd75f85e36d591fa Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:35 -0400 Subject: [PATCH 4425/9938] rtl8xxxu: Rename rtl8723bu_simularity_compare() This renames rtl8723bu_simularity_compare() to rtl8xxxu_gen2_simularity_compare() to reflect it is used for all gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 1f517d0bb4bb..7d4645588ab9 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4595,8 +4595,8 @@ static bool rtl8xxxu_simularity_compare(struct rtl8xxxu_priv *priv, return false; } -static bool rtl8723bu_simularity_compare(struct rtl8xxxu_priv *priv, - int result[][8], int c1, int c2) +static bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv, + int result[][8], int c1, int c2) { u32 i, j, diff, simubitmap, bound = 0; int candidate[2] = {-1, -1}; /* for path A and path B */ @@ -6237,7 +6237,8 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8723bu_phy_iqcalibrate(priv, result, i); if (i == 1) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 1); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 1); if (simu) { candidate = 0; break; @@ -6245,13 +6246,15 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) } if (i == 2) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 2); if (simu) { candidate = 0; break; } - simu = rtl8723bu_simularity_compare(priv, result, 1, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 1, 2); if (simu) { candidate = 1; } else { @@ -6352,7 +6355,8 @@ static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8192eu_phy_iqcalibrate(priv, result, i); if (i == 1) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 1); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 1); if (simu) { candidate = 0; break; @@ -6360,13 +6364,15 @@ static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) } if (i == 2) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 2); if (simu) { candidate = 0; break; } - simu = rtl8723bu_simularity_compare(priv, result, 1, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 1, 2); if (simu) candidate = 1; else -- GitLab From 04a74a9f8af0cd61598e886c260ad0644b1dd5c0 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:36 -0400 Subject: [PATCH 4426/9938] rtl8xxxu: Rename rtl8723au_iqk_phy_iq_bb_reg There is nothing 8723au specific about rtl8723au_iqk_phy_iq_bb_reg so rename the array to rtl8xxxu_iqk_phy_iq_bb_reg. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7d4645588ab9..f2ce8c9a31cf 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1747,7 +1747,7 @@ static struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = { }, }; -static const u32 rtl8723au_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { +static const u32 rtl8xxxu_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { REG_OFDM0_XA_RX_IQ_IMBALANCE, REG_OFDM0_XB_RX_IQ_IMBALANCE, REG_OFDM0_ENERGY_CCA_THRES, @@ -6205,7 +6205,7 @@ static void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, candidate, (reg_ec4 == 0)); - rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg, priv->bb_recovery_backup, RTL8XXXU_BB_REGS); rtl8xxxu_prepare_calibrate(priv, 0); @@ -6313,7 +6313,7 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, candidate, (reg_ec4 == 0)); - rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg, priv->bb_recovery_backup, RTL8XXXU_BB_REGS); rtl8xxxu_write32(priv, REG_BT_CONTROL_8723BU, bt_control); @@ -6424,7 +6424,7 @@ static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, candidate, (reg_ec4 == 0)); - rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg, priv->bb_recovery_backup, RTL8XXXU_BB_REGS); } -- GitLab From e0bdef0f75f0ee0d4747b72fa75310da78dbfa56 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Apr 2016 07:21:58 -0700 Subject: [PATCH 4427/9938] mwifiex: missing error code on allocation failure We accidentally return success instead of -ENOMEM. Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index 05108618430d..cdd8f9a867a9 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -1017,8 +1017,10 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, /* Allocate memory for receive */ recv_buff = kzalloc(FW_DNLD_RX_BUF_SIZE, GFP_KERNEL); - if (!recv_buff) + if (!recv_buff) { + ret = -ENOMEM; goto cleanup; + } do { /* Send pseudo data to check winner status first */ -- GitLab From 394f0ed53108d5e038910e3eb733ccd3f0d9c464 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Apr 2016 07:23:44 -0700 Subject: [PATCH 4428/9938] mwifiex: fix loop timeout in mwifiex_prog_fw_w_helper() USB8XXX_FW_MAX_RETRY is 3. We were using a post-op loop "while (retries--) {" but then the lines after that assume the loop exits with retries set to zero. I've fixed this by changing to a pre-op loop. I started with retries set to 4 instead of 3 so that we still go through the loop the same number of times. Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/usb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index cdd8f9a867a9..0857575c5c39 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -995,7 +995,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, { int ret = 0; u8 *firmware = fw->fw_buf, *recv_buff; - u32 retries = USB8XXX_FW_MAX_RETRY, dlen; + u32 retries = USB8XXX_FW_MAX_RETRY + 1; + u32 dlen; u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0; struct fw_data *fwdata; struct fw_sync_header sync_fw; @@ -1043,7 +1044,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, } /* If the send/receive fails or CRC occurs then retry */ - while (retries--) { + while (--retries) { u8 *buf = (u8 *)fwdata; u32 len = FW_DATA_XMIT_SIZE; @@ -1103,7 +1104,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, continue; } - retries = USB8XXX_FW_MAX_RETRY; + retries = USB8XXX_FW_MAX_RETRY + 1; break; } fw_seqnum++; -- GitLab From d7e182a10903e34da9eb79e5c99f0b28432d00be Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Sat, 2 Apr 2016 19:47:51 +0800 Subject: [PATCH 4429/9938] arm64: defconfig: Enable the PMIC and regulator for Hi6220 and 96boards HiKey This patch enables a number of devices currently supported by the Hi6220 and 96boards HiKey. These include a) Hi655x PMIC and regulator b) Hi6220 I2C, USB, MMC, mailbox, and reset c) CONFIG_PINCTRL_SINGLE, and CONFIG_LEDS_GPIO Since b) and c) are already in the 4.6-rc3, so kept a) only in this patch and updated subject as well. v2: - rebase to next-20160310, CONFIG_MMC_BLOCK_MINORS=16 is already in. - set CONFIG_I2C_DESIGNWARE_PLATFORM to be build as module Signed-off-by: Guodong Xu Reviewed-by: Arnd Bergmann Signed-off-by: Wei Xu --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index a44ef995d8ae..e6bf527cbb35 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -173,8 +173,10 @@ CONFIG_THERMAL_EMULATION=y CONFIG_EXYNOS_THERMAL=y CONFIG_MFD_SPMI_PMIC=y CONFIG_MFD_SEC_CORE=y +CONFIG_MFD_HI655X_PMIC=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_HI655X=y CONFIG_REGULATOR_QCOM_SMD_RPM=y CONFIG_REGULATOR_QCOM_SPMI=y CONFIG_REGULATOR_S2MPS11=y -- GitLab From 81542fac6eae586e0d6fd502618342e8e20b4c5a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Apr 2016 07:25:43 -0700 Subject: [PATCH 4430/9938] brcmfmac: testing the wrong variable in brcmf_rx_hdrpull() Smatch complains about this code: drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c:335 brcmf_rx_hdrpull() error: we previously assumed '*ifp' could be null (see line 333) The problem is that we recently changed these from "ifp" to "*ifp" but there was one that we didn't update. - if (ret || !ifp || !ifp->ndev) { + if (ret || !(*ifp) || !(*ifp)->ndev) { if (ret != -ENODATA && ifp) ^^^ - ifp->stats.rx_errors++; + (*ifp)->stats.rx_errors++; I have updated it to *ifp as well. We always call this function is a non-NULL "ifp" pointer, btw. Fixes: c462ebcdfe42 ('brcmfmac: create common function for handling brcmf_proto_hdrpull()') Signed-off-by: Dan Carpenter Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 1b476d1fec2c..b590499f6883 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -331,7 +331,7 @@ static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb, ret = brcmf_proto_hdrpull(drvr, true, skb, ifp); if (ret || !(*ifp) || !(*ifp)->ndev) { - if (ret != -ENODATA && ifp) + if (ret != -ENODATA && *ifp) (*ifp)->stats.rx_errors++; brcmu_pkt_buf_free_skb(skb); return -ENODATA; -- GitLab From d3098f224fd3492f4234ab2014c8579425b1d6fc Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Sat, 2 Apr 2016 19:47:52 +0800 Subject: [PATCH 4431/9938] arm64: defconfig: add CONFIG_SPI_SPIDEV as module add CONFIG_SPI_SPIDEV as module, for arm64. Signed-off-by: Guodong Xu Reviewed-by: Arnd Bergmann Signed-off-by: Wei Xu --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index e6bf527cbb35..37999b712aa5 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -155,6 +155,7 @@ CONFIG_I2C_RCAR=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=m CONFIG_SPMI=y CONFIG_PINCTRL_SINGLE=y CONFIG_PINCTRL_MSM8916=y -- GitLab From 3cf5d6c046cfbae007d7b60f41888a3687435c25 Mon Sep 17 00:00:00 2001 From: Akira Tsukamoto Date: Sat, 2 Apr 2016 19:47:53 +0800 Subject: [PATCH 4432/9938] arm64: defconfig: enable several common USB network adapters The arm64 system is likely to be used as a host computer instead of embedded devices and adding USB-Ethernet dongles to make it behave as host PC is mandatory. Changelog: v2: Changed drivers to be as modules instead of built-in. Signed-off-by: Akira Tsukamoto Signed-off-by: Guodong Xu Reviewed-by: Arnd Bergmann Signed-off-by: Wei Xu --- arch/arm64/configs/defconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 37999b712aa5..ddce9cdf67f2 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -118,6 +118,16 @@ CONFIG_RAVB=y CONFIG_SMC91X=y CONFIG_SMSC911X=y CONFIG_MICREL_PHY=y +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m # CONFIG_WLAN is not set CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y -- GitLab From 2557654df14b95141f1410127c33ed1661a8abbb Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Thu, 21 Apr 2016 00:41:34 +0800 Subject: [PATCH 4433/9938] rt2800lib: enable MFP if hw crypt is disabled If rt2800usb is loaded with nohwcrypt=1, mac80211 takes care of the crypto with software encryption/decryption and thus, MFP can be used. Tested for secured mesh using ath9k_htc and ath9k. Signed-off-by: Chun-Yeow Yeoh Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index c36fa4e03fb6..bf3f0a39908c 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -7492,6 +7492,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) if (!rt2x00_is_usb(rt2x00dev)) ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING); + /* Set MFP if HW crypto is disabled. */ + if (rt2800_hwcrypt_disabled(rt2x00dev)) + ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE); + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2800_eeprom_addr(rt2x00dev, -- GitLab From f0d8f38cd909e072833a06b79939256c4aebe3a0 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 25 Apr 2016 20:02:09 +0300 Subject: [PATCH 4434/9938] iwlwifi: fix fw version reading for DVM devices In commit 97f95c93c8ed ("iwlwifi: remove support for fw older than -16.ucode") we accidentally changed the fw version reading code for DVM devices. The code intended to remove the old fw version API, because all MVM firmwares version 16 and above that we support don't use it anymore. But DVM devices still use the old FW API. Fix that by bringing the code back in. Reported-by: Pat Erley Tested-by: Kalle Valo Fixes: 97f95c93c8ed ("iwlwifi: remove support for fw older than-16.ucode") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 48e873732d4e..4f495d9153a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1280,7 +1280,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) if (err) goto try_again; - api_ver = drv->fw.ucode_ver; + if (fw_has_api(&drv->fw.ucode_capa, IWL_UCODE_TLV_API_NEW_VERSION)) + api_ver = drv->fw.ucode_ver; + else + api_ver = IWL_UCODE_API(drv->fw.ucode_ver); /* * api_ver should match the api version forming part of the diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 843232bd8bbe..37dc09e8b6a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -251,6 +251,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params + * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format * @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority * instead of 3. * @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size @@ -263,6 +264,7 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, + IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20, IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24, IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27, -- GitLab From d1b4cad61ba1273755c41fa40ae0feb53c3e49b2 Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Sat, 2 Apr 2016 19:47:54 +0800 Subject: [PATCH 4435/9938] arm64: defconfig: enable configs for WLAN and TI WL1835 as modules This patch enables TI WL1835 and builds as module. It also enables CFG80211, MAC80211, RFKILL and several CRYPTOs which are required by WLAN. 96boards HiKey uses TI WLAN/BT combo module WL1835MOD. Signed-off-by: Guodong Xu Reviewed-by: Arnd Bergmann Signed-off-by: Wei Xu --- arch/arm64/configs/defconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index ddce9cdf67f2..da3df55bf02a 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -84,7 +84,10 @@ CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IPV6 is not set CONFIG_BPF_JIT=y -# CONFIG_WIRELESS is not set +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_LEDS=y +CONFIG_RFKILL=m CONFIG_NET_9P=y CONFIG_NET_9P_VIRTIO=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" @@ -128,7 +131,8 @@ CONFIG_USB_NET_SMSC75XX=m CONFIG_USB_NET_SMSC95XX=m CONFIG_USB_NET_PLUSB=m CONFIG_USB_NET_MCS7830=m -# CONFIG_WLAN is not set +CONFIG_WL18XX=m +CONFIG_WLCORE_SDIO=m CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_SERIO_SERPORT is not set -- GitLab From 45c175c4ae9695d6d2f30a45ab7f3866cfac184b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Apr 2016 06:33:06 -0300 Subject: [PATCH 4436/9938] [media] tw686x: avoid going past array Fix those two warnings: drivers/media/pci/tw686x/tw686x-video.c:69 tw686x_fields_map() error: buffer overflow 'std_525_60' 31 <= 31 drivers/media/pci/tw686x/tw686x-video.c:73 tw686x_fields_map() error: buffer overflow 'std_625_50' 26 <= 26 I had those changes at the last version of my patch, but I ended by merging the previous version by mistake. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw686x/tw686x-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index d2a0147e6492..253e10823ba3 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -64,11 +64,11 @@ static unsigned int tw686x_fields_map(v4l2_std_id std, unsigned int fps) unsigned int i; if (std & V4L2_STD_525_60) { - if (fps > ARRAY_SIZE(std_525_60)) + if (fps >= ARRAY_SIZE(std_525_60)) fps = 30; i = std_525_60[fps]; } else { - if (fps > ARRAY_SIZE(std_625_50)) + if (fps >= ARRAY_SIZE(std_625_50)) fps = 25; i = std_625_50[fps]; } -- GitLab From 2b905d3a8d7e40c3486abbf585419fafa220a8f8 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 21 Jan 2016 18:53:48 +0800 Subject: [PATCH 4437/9938] arm64: Kconfig: select sp804 timer for ARCH_HISI Select sp804 timer for ARCH_HISI, which is used as broadcast timer. Signed-off-by: Leo Yan Signed-off-by: Wei Xu --- arch/arm64/Kconfig.platforms | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index efa77c146415..759a7e0c50ab 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -45,6 +45,7 @@ config ARCH_LAYERSCAPE config ARCH_HISI bool "Hisilicon SoC Family" + select ARM_TIMER_SP804 select HISILICON_IRQ_MBIGEN help This enables support for Hisilicon ARMv8 SoC family -- GitLab From b1f3a3b03eb5f61b4051e2da9aa15653e705e111 Mon Sep 17 00:00:00 2001 From: Florian Vallee Date: Tue, 19 Apr 2016 17:50:05 +0200 Subject: [PATCH 4438/9938] ARM: dts: at91: fix typo in sama5d2 PIN_PD24 description Fix a typo on PIN_PD24 for UTXD2 and FLEXCOM4_IO3 which were wrongly linked to PIN_PD23). Signed-off-by: Florian Vallee Fixes: 7f16cb676c00 ("ARM: at91/dt: add sama5d2 pinmux") Cc: stable@vger.kernel.org # v4.4+ [nicolas.ferre@atmel.com: add commit message, changed subject] Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/sama5d2-pinfunc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sama5d2-pinfunc.h b/arch/arm/boot/dts/sama5d2-pinfunc.h index b0c912feaa2f..8a394f336003 100644 --- a/arch/arm/boot/dts/sama5d2-pinfunc.h +++ b/arch/arm/boot/dts/sama5d2-pinfunc.h @@ -837,8 +837,8 @@ #define PIN_PD23__ISC_FIELD PINMUX_PIN(PIN_PD23, 6, 4) #define PIN_PD24 120 #define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0) -#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD23, 1, 2) -#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD23, 3, 3) +#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD24, 1, 2) +#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD24, 3, 3) #define PIN_PD25 121 #define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0) #define PIN_PD25__SPI1_SPCK PINMUX_PIN(PIN_PD25, 1, 3) -- GitLab From 3c9e014c442caefa14c71494ca4473121007f60f Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Apr 2016 18:07:10 +0800 Subject: [PATCH 4439/9938] ASoC: rt298: reset AD dilter is there is no MCLK rt298 need to reset AD filter and the ADC settings will take effort. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt298.c | 20 ++++++++++++++++++++ sound/soc/codecs/rt298.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index f0e6c06e89ac..178b1cc22e05 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -481,6 +481,26 @@ static int rt298_adc_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 0x7080, 0x7000); + /* If MCLK doesn't exist, reset AD filter */ + if (!(snd_soc_read(codec, RT298_VAD_CTRL) & 0x200)) { + pr_info("NO MCLK\n"); + switch (nid) { + case RT298_ADC_IN1: + snd_soc_update_bits(codec, + RT298_D_FILTER_CTRL, 0x2, 0x2); + mdelay(10); + snd_soc_update_bits(codec, + RT298_D_FILTER_CTRL, 0x2, 0x0); + break; + case RT298_ADC_IN2: + snd_soc_update_bits(codec, + RT298_D_FILTER_CTRL, 0x4, 0x4); + mdelay(10); + snd_soc_update_bits(codec, + RT298_D_FILTER_CTRL, 0x4, 0x0); + break; + } + } break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, diff --git a/sound/soc/codecs/rt298.h b/sound/soc/codecs/rt298.h index d66f8847b676..3638f3d61209 100644 --- a/sound/soc/codecs/rt298.h +++ b/sound/soc/codecs/rt298.h @@ -137,6 +137,7 @@ #define RT298_A_BIAS_CTRL2 0x02 #define RT298_POWER_CTRL1 0x03 #define RT298_A_BIAS_CTRL3 0x04 +#define RT298_D_FILTER_CTRL 0x05 #define RT298_POWER_CTRL2 0x08 #define RT298_I2S_CTRL1 0x09 #define RT298_I2S_CTRL2 0x0a @@ -148,6 +149,7 @@ #define RT298_IRQ_CTRL 0x33 #define RT298_WIND_FILTER_CTRL 0x46 #define RT298_PLL_CTRL1 0x49 +#define RT298_VAD_CTRL 0x4e #define RT298_CBJ_CTRL1 0x4f #define RT298_CBJ_CTRL2 0x50 #define RT298_PLL_CTRL 0x63 -- GitLab From 9ff49ce475cfeaf486321a2db8132a9500740faa Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Apr 2016 18:07:11 +0800 Subject: [PATCH 4440/9938] ASoC: rt298: fix capture doesn't work at some cases RT298_CBJ_CTRL1(0x4f) bit 10 is needed for headset capture. It will be turned off when "VREF" widget is on and be turned on when bias level is ON. It is odd. And if "VREF" is turned on in bias level is ON, RT298_CBJ_CTRL1(0x4f) bit 10 will be turned off. This patch move the bit control from rt298_set_bias_level and rt298_vref_event to rt298_jack_detect. So it will be turned on once a jack is plugged in. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt298.c | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 178b1cc22e05..68cf8d5a174f 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -275,6 +275,8 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) } else { *mic = false; regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20); + regmap_update_bits(rt298->regmap, + RT298_CBJ_CTRL1, 0x0400, 0x0000); } } else { regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); @@ -539,30 +541,12 @@ static int rt298_mic1_event(struct snd_soc_dapm_widget *w, return 0; } -static int rt298_vref_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - snd_soc_update_bits(codec, - RT298_CBJ_CTRL1, 0x0400, 0x0000); - mdelay(50); - break; - default: - return 0; - } - - return 0; -} - static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1, 12, 1, NULL, 0), SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1, - 0, 1, rt298_vref_event, SND_SOC_DAPM_PRE_PMU), + 0, 1, NULL, 0), SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2, @@ -953,18 +937,9 @@ static int rt298_set_bias_level(struct snd_soc_codec *codec, } break; - case SND_SOC_BIAS_ON: - mdelay(30); - snd_soc_update_bits(codec, - RT298_CBJ_CTRL1, 0x0400, 0x0400); - - break; - case SND_SOC_BIAS_STANDBY: snd_soc_write(codec, RT298_SET_AUDIO_POWER, AC_PWRST_D3); - snd_soc_update_bits(codec, - RT298_CBJ_CTRL1, 0x0400, 0x0000); break; default: -- GitLab From 4a5ed8c1adc39f86a2887183c71b007bc962fdce Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Apr 2016 11:19:26 +0200 Subject: [PATCH 4441/9938] regulator: rk808: remove unused rk808_reg_ops_ranges After removing all uses of the range operations in a recent patch, we get a warning about the symbol not being referenced anywhere: drivers/regulator/rk808-regulator.c:306:29: 'rk808_reg_ops_ranges' defined but not used This removes the now-unused structure along with the rk808_set_suspend_voltage_range function that is only referenced from rk808_reg_ops_ranges. Fixes: afcd666d9db0 ("regulator: rk808: remove linear range definitions with a single range") Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 964b95eed271..67f72feed815 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -238,21 +238,6 @@ static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv) sel); } -static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) -{ - unsigned int reg; - int sel = regulator_map_voltage_linear_range(rdev, uv, uv); - - if (sel < 0) - return -EINVAL; - - reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET; - - return regmap_update_bits(rdev->regmap, reg, - rdev->desc->vsel_mask, - sel); -} - static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; @@ -303,19 +288,6 @@ static struct regulator_ops rk808_reg_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; -static struct regulator_ops rk808_reg_ops_ranges = { - .list_voltage = regulator_list_voltage_linear_range, - .map_voltage = regulator_map_voltage_linear_range, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .set_suspend_voltage = rk808_set_suspend_voltage_range, - .set_suspend_enable = rk808_set_suspend_enable, - .set_suspend_disable = rk808_set_suspend_disable, -}; - static struct regulator_ops rk808_switch_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, -- GitLab From 66ec246eb9982e7eb8e15e1fc55f543230310dd0 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 26 Apr 2016 10:08:26 +0300 Subject: [PATCH 4442/9938] spi: pxa2xx: Do not detect number of enabled chip selects on Intel SPT Certain Intel Sunrisepoint PCH variants report zero chip selects in SPI capabilities register even they have one per port. Detection in pxa2xx_spi_probe() sets master->num_chipselect to 0 leading to -EINVAL from spi_register_master() where chip select count is validated. Fix this by not using SPI capabilities register on Sunrisepoint. They don't have more than one chip select so use the default value 1 instead of detection. Fixes: 8b136baa5892 ("spi: pxa2xx: Detect number of enabled Intel LPSS SPI chip select signals") Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-pxa2xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 85e59a406a4c..86138e4101b0 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -126,7 +126,7 @@ static const struct lpss_config lpss_platforms[] = { .reg_general = -1, .reg_ssp = 0x20, .reg_cs_ctrl = 0x24, - .reg_capabilities = 0xfc, + .reg_capabilities = -1, .rx_threshold = 1, .tx_threshold_lo = 32, .tx_threshold_hi = 56, -- GitLab From 2452ee25255af95d122ff66ea390facb67a61fc3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 26 Apr 2016 07:31:15 +0800 Subject: [PATCH 4443/9938] spi: pic32: Set proper bits_per_word_mask This driver only supports 8/16/32 bits_per_word, so set master->bits_per_word_mask accordingly. With this change, we can remove the spi->bits_per_word checking in pic32_spi_setup as it's done by spi core. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi-pic32.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index f8313ea11a34..4eeb8a85b030 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -592,16 +592,6 @@ static int pic32_spi_setup(struct spi_device *spi) return -EINVAL; } - switch (spi->bits_per_word) { - case 8: - case 16: - case 32: - break; - default: - dev_err(&spi->dev, "Invalid bits_per_word defined\n"); - return -EINVAL; - } - /* PIC32 spi controller can drive /CS during transfer depending * on tx fifo fill-level. /CS will stay asserted as long as TX * fifo is non-empty, else will be deasserted indicating @@ -791,7 +781,8 @@ static int pic32_spi_probe(struct platform_device *pdev) master->setup = pic32_spi_setup; master->cleanup = pic32_spi_cleanup; master->flags = SPI_MASTER_MUST_TX | SPI_MASTER_MUST_RX; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | + SPI_BPW_MASK(32); master->transfer_one = pic32_spi_one_transfer; master->prepare_message = pic32_spi_prepare_message; master->unprepare_message = pic32_spi_unprepare_message; -- GitLab From b0fe3306432796c8f7adbede8ccd479bb7b53d0a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 2 Apr 2016 00:05:14 -0700 Subject: [PATCH 4444/9938] i40e/i40evf: Clean up feature flags The feature flags list for i40e and i40evf is beginning to become pretty massive. I plan to add another 4 or so features to these drivers and duplicating the flags for each and every flags list is becoming a bit repetitive. The primary change here is that we now build our features list around hw_encap_features. After that we assign that to vlan_features, hw_features, and finally map that onto features. In addition we end up throwing features onto hw_encap_features that end up having no effect such as the Rx offloads and SCTP_CRC. However that should have no impact and makes things a bit easier for us as hw_encap_features is one of the less updated features maps available. For i40evf I went through and sanity checked a few features as well. Specifically RXCSUM was being set as a read-only feature which didn't make much sense. I have updated things so we can clear the NETIF_F_RXCSUM flag since that is really a software feature and not a hardware one anyway so disabling it is just a matter of ignoring the result from the hardware. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 61 ++++++++--------- .../net/ethernet/intel/i40evf/i40evf_main.c | 66 +++++++++---------- 2 files changed, 58 insertions(+), 69 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 0b071cea305d..f2e83fe4d66c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9111,40 +9111,36 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) np = netdev_priv(netdev); np->vsi = vsi; - netdev->hw_enc_features |= NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_TSO_ECN | - NETIF_F_GSO_GRE | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | + netdev->hw_enc_features |= NETIF_F_SG | + NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_HIGHDMA | + NETIF_F_SOFT_FEATURES | + NETIF_F_TSO | + NETIF_F_TSO_ECN | + NETIF_F_TSO6 | + NETIF_F_GSO_GRE | + NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_RXHASH | + NETIF_F_RXCSUM | 0; - netdev->features = NETIF_F_SG | - NETIF_F_IP_CSUM | - NETIF_F_SCTP_CRC | - NETIF_F_HIGHDMA | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_GRE | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER | - NETIF_F_IPV6_CSUM | - NETIF_F_TSO | - NETIF_F_TSO_ECN | - NETIF_F_TSO6 | - NETIF_F_RXCSUM | - NETIF_F_RXHASH | - 0; + if (!(pf->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE)) + netdev->hw_enc_features ^= NETIF_F_GSO_UDP_TUNNEL_CSUM; + + /* record features VLANs can make use of */ + netdev->vlan_features |= netdev->hw_enc_features; if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) - netdev->features |= NETIF_F_NTUPLE; - if (pf->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE) - netdev->features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; + netdev->hw_features |= NETIF_F_NTUPLE; + + netdev->hw_features |= netdev->hw_enc_features | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; - /* copy netdev features into list of user selectable features */ - netdev->hw_features |= netdev->features; + netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER; if (vsi->type == I40E_VSI_MAIN) { SET_NETDEV_DEV(netdev, &pf->pdev->dev); @@ -9183,12 +9179,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) ether_addr_copy(netdev->dev_addr, mac_addr); ether_addr_copy(netdev->perm_addr, mac_addr); - /* vlan gets same features (except vlan offload) - * after any tweaks for specific VSI types - */ - netdev->vlan_features = netdev->features & ~(NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER); + netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; /* Setup netdev TC information */ diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 9110319a8f00..e3857d890cfb 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2337,40 +2337,38 @@ int i40evf_process_config(struct i40evf_adapter *adapter) return -ENODEV; } - netdev->features |= NETIF_F_HIGHDMA | - NETIF_F_SG | - NETIF_F_IP_CSUM | - NETIF_F_SCTP_CRC | - NETIF_F_IPV6_CSUM | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_TSO_ECN | - NETIF_F_GSO_GRE | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_RXCSUM | - NETIF_F_GRO; - - netdev->hw_enc_features |= NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_TSO_ECN | - NETIF_F_GSO_GRE | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM; - - if (adapter->flags & I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE) - netdev->features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; - - /* always clear VLAN features because they can change at every reset */ - netdev->features &= ~(I40EVF_VLAN_FEATURES); - /* copy netdev features into list of user selectable features */ - netdev->hw_features |= netdev->features; - - if (vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_VLAN) { - netdev->vlan_features = netdev->features; - netdev->features |= I40EVF_VLAN_FEATURES; - } + netdev->hw_enc_features |= NETIF_F_SG | + NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_HIGHDMA | + NETIF_F_SOFT_FEATURES | + NETIF_F_TSO | + NETIF_F_TSO_ECN | + NETIF_F_TSO6 | + NETIF_F_GSO_GRE | + NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | + NETIF_F_SCTP_CRC | + NETIF_F_RXHASH | + NETIF_F_RXCSUM | + 0; + + if (!(adapter->flags & I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE)) + netdev->hw_enc_features ^= NETIF_F_GSO_UDP_TUNNEL_CSUM; + + /* record features VLANs can make use of */ + netdev->vlan_features |= netdev->hw_enc_features; + + /* Write features and hw_features separately to avoid polluting + * with, or dropping, features that are set when we registgered. + */ + netdev->hw_features |= netdev->hw_enc_features; + + netdev->features |= netdev->hw_enc_features | I40EVF_VLAN_FEATURES; + + /* disable VLAN features if not supported */ + if (!(vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_VLAN)) + netdev->features ^= I40EVF_VLAN_FEATURES; adapter->vsi.id = adapter->vsi_res->vsi_id; -- GitLab From 27becea06e73c96b825ecddd8b3a59642364514a Mon Sep 17 00:00:00 2001 From: PC Liao Date: Tue, 26 Apr 2016 14:30:18 +0800 Subject: [PATCH 4445/9938] ASoC: mediatek: HDMI audio LR channel swapped Because LRCK of TDM use High to Low as default setting, this patch changes the TDM setting to inverse LRCK. Signed-off-by: PC Liao Signed-off-by: Mark Brown --- sound/soc/mediatek/mtk-afe-pcm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c index f1c58a2c12fb..2b5df2ef51a3 100644 --- a/sound/soc/mediatek/mtk-afe-pcm.c +++ b/sound/soc/mediatek/mtk-afe-pcm.c @@ -123,6 +123,7 @@ #define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8) #define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4) #define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3) +#define AFE_TDM_CON1_LRCK_INV (0x1 << 2) #define AFE_TDM_CON1_BCK_INV (0x1 << 1) #define AFE_TDM_CON1_EN (0x1 << 0) @@ -449,6 +450,7 @@ static int mtk_afe_hdmi_prepare(struct snd_pcm_substream *substream, runtime->rate * runtime->channels * 32); val = AFE_TDM_CON1_BCK_INV | + AFE_TDM_CON1_LRCK_INV | AFE_TDM_CON1_1_BCK_DELAY | AFE_TDM_CON1_MSB_ALIGNED | /* I2S mode */ AFE_TDM_CON1_WLEN_32BIT | -- GitLab From 577389a5db766c44400e75e6a79f39d9b0d585f8 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 2 Apr 2016 00:06:56 -0700 Subject: [PATCH 4446/9938] i40e/i40evf: Add support for IPIP and SIT offloads Looking over the documentation it turns out enabling IPIP and SIT offloads for i40e is pretty straightforward. As such I decided to enable them with this patch. In my testing I am seeing an improvement of 8 to 10 Gb/s for IPIP and SIT tunnels with this offload enabled. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ drivers/net/ethernet/intel/i40e/i40e_txrx.c | 24 ++++++++++++------- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 24 ++++++++++++------- .../net/ethernet/intel/i40evf/i40evf_main.c | 2 ++ 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f2e83fe4d66c..ec94ad6c783a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9120,6 +9120,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GSO_GRE | + NETIF_F_GSO_IPIP | + NETIF_F_GSO_SIT | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC | diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 39efba0636fd..6e44cf118843 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2299,7 +2299,10 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss) ip.v6->payload_len = 0; } - if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE | + if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE | + SKB_GSO_IPIP | + SKB_GSO_SIT | + SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM)) { if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) { /* determine offset of outer transport header */ @@ -2442,13 +2445,6 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, &l4_proto, &frag_off); } - /* compute outer L3 header size */ - tunnel |= ((l4.hdr - ip.hdr) / 4) << - I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT; - - /* switch IP header pointer from outer to inner header */ - ip.hdr = skb_inner_network_header(skb); - /* define outer transport */ switch (l4_proto) { case IPPROTO_UDP: @@ -2459,6 +2455,11 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, tunnel |= I40E_TXD_CTX_GRE_TUNNELING; *tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL; break; + case IPPROTO_IPIP: + case IPPROTO_IPV6: + *tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL; + l4.hdr = skb_inner_network_header(skb); + break; default: if (*tx_flags & I40E_TX_FLAGS_TSO) return -1; @@ -2467,6 +2468,13 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, return 0; } + /* compute outer L3 header size */ + tunnel |= ((l4.hdr - ip.hdr) / 4) << + I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT; + + /* switch IP header pointer from outer to inner header */ + ip.hdr = skb_inner_network_header(skb); + /* compute tunnel header size */ tunnel |= ((ip.hdr - l4.hdr) / 2) << I40E_TXD_CTX_QW0_NATLEN_SHIFT; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index fc228182dc88..f101895ecf4a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1564,7 +1564,10 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss) ip.v6->payload_len = 0; } - if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE | + if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE | + SKB_GSO_IPIP | + SKB_GSO_SIT | + SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM)) { if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) { /* determine offset of outer transport header */ @@ -1665,13 +1668,6 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, &l4_proto, &frag_off); } - /* compute outer L3 header size */ - tunnel |= ((l4.hdr - ip.hdr) / 4) << - I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT; - - /* switch IP header pointer from outer to inner header */ - ip.hdr = skb_inner_network_header(skb); - /* define outer transport */ switch (l4_proto) { case IPPROTO_UDP: @@ -1682,6 +1678,11 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, tunnel |= I40E_TXD_CTX_GRE_TUNNELING; *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL; break; + case IPPROTO_IPIP: + case IPPROTO_IPV6: + *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL; + l4.hdr = skb_inner_network_header(skb); + break; default: if (*tx_flags & I40E_TX_FLAGS_TSO) return -1; @@ -1690,6 +1691,13 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, return 0; } + /* compute outer L3 header size */ + tunnel |= ((l4.hdr - ip.hdr) / 4) << + I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT; + + /* switch IP header pointer from outer to inner header */ + ip.hdr = skb_inner_network_header(skb); + /* compute tunnel header size */ tunnel |= ((ip.hdr - l4.hdr) / 2) << I40E_TXD_CTX_QW0_NATLEN_SHIFT; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index e3857d890cfb..806da2686623 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2346,6 +2346,8 @@ int i40evf_process_config(struct i40evf_adapter *adapter) NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GSO_GRE | + NETIF_F_GSO_IPIP | + NETIF_F_GSO_SIT | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC | -- GitLab From c4e1868c3aa1992de1cba600e7083fcd49bd20b8 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 12 Apr 2016 08:30:40 -0700 Subject: [PATCH 4447/9938] i40e: Add support for configuring VF RSS Add support for configuring RSS on behalf of the VFs. This removes the burden of dealing with different hardware interfaces from the VF drivers, allowing for better future compatibility. Change-ID: Icea75d3f37241ee8e447be5779e5abb53ddf04c0 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 35 +++- .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 193 +++++++++++++++++- 3 files changed, 217 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index d25b3be5ba89..e312adf64260 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -202,6 +202,7 @@ struct i40e_lump_tracking { #define I40E_HKEY_ARRAY_SIZE ((I40E_PFQF_HKEY_MAX_INDEX + 1) * 4) #define I40E_HLUT_ARRAY_SIZE ((I40E_PFQF_HLUT_MAX_INDEX + 1) * 4) +#define I40E_VF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT1_MAX_INDEX + 1) * 4) enum i40e_fd_stat_idx { I40E_FD_STAT_ATR, diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index ec94ad6c783a..39b3b56d3a9f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8082,24 +8082,45 @@ static int i40e_config_rss_reg(struct i40e_vsi *vsi, const u8 *seed, { struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; + u16 vf_id = vsi->vf_id; u8 i; /* Fill out hash function seed */ if (seed) { u32 *seed_dw = (u32 *)seed; - for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) - i40e_write_rx_ctl(hw, I40E_PFQF_HKEY(i), seed_dw[i]); + if (vsi->type == I40E_VSI_MAIN) { + for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) + i40e_write_rx_ctl(hw, I40E_PFQF_HKEY(i), + seed_dw[i]); + } else if (vsi->type == I40E_VSI_SRIOV) { + for (i = 0; i <= I40E_VFQF_HKEY1_MAX_INDEX; i++) + i40e_write_rx_ctl(hw, + I40E_VFQF_HKEY1(i, vf_id), + seed_dw[i]); + } else { + dev_err(&pf->pdev->dev, "Cannot set RSS seed - invalid VSI type\n"); + } } if (lut) { u32 *lut_dw = (u32 *)lut; - if (lut_size != I40E_HLUT_ARRAY_SIZE) - return -EINVAL; - - for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++) - wr32(hw, I40E_PFQF_HLUT(i), lut_dw[i]); + if (vsi->type == I40E_VSI_MAIN) { + if (lut_size != I40E_HLUT_ARRAY_SIZE) + return -EINVAL; + for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++) + wr32(hw, I40E_PFQF_HLUT(i), lut_dw[i]); + } else if (vsi->type == I40E_VSI_SRIOV) { + if (lut_size != I40E_VF_HLUT_ARRAY_SIZE) + return -EINVAL; + for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) + i40e_write_rx_ctl(hw, + I40E_VFQF_HLUT1(i, vf_id), + lut_dw[i]); + } else { + dev_err(&pf->pdev->dev, "Cannot set RSS LUT - invalid VSI type\n"); + } } i40e_flush(hw); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 30f8cbe6b54b..c3645886670e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1348,12 +1348,16 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) set_bit(I40E_VF_STAT_IWARPENA, &vf->vf_states); } - if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) { - if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ) - vfres->vf_offload_flags |= - I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ; + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) { + vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF; } else { - vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG; + if ((pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) && + (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ)) + vfres->vf_offload_flags |= + I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ; + else + vfres->vf_offload_flags |= + I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG; } if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) { @@ -1382,6 +1386,9 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) vfres->num_vsis = num_vsis; vfres->num_queue_pairs = vf->num_queue_pairs; vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf; + vfres->rss_key_size = I40E_HKEY_ARRAY_SIZE; + vfres->rss_lut_size = I40E_VF_HLUT_ARRAY_SIZE; + if (vf->lan_vsi_idx) { vfres->vsi_res[0].vsi_id = vf->lan_vsi_id; vfres->vsi_res[0].vsi_type = I40E_VSI_SRIOV; @@ -2041,6 +2048,139 @@ static int i40e_vc_iwarp_qvmap_msg(struct i40e_vf *vf, u8 *msg, u16 msglen, aq_ret); } +/** + * i40e_vc_config_rss_key + * @vf: pointer to the VF info + * @msg: pointer to the msg buffer + * @msglen: msg length + * + * Configure the VF's RSS key + **/ +static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg, u16 msglen) +{ + struct i40e_virtchnl_rss_key *vrk = + (struct i40e_virtchnl_rss_key *)msg; + struct i40e_pf *pf = vf->pf; + struct i40e_vsi *vsi = NULL; + u16 vsi_id = vrk->vsi_id; + i40e_status aq_ret = 0; + + if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || + !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) || + !i40e_vc_isvalid_vsi_id(vf, vsi_id) || + (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } + + vsi = pf->vsi[vf->lan_vsi_idx]; + aq_ret = i40e_config_rss(vsi, vrk->key, NULL, 0); +err: + /* send the response to the VF */ + return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_RSS_KEY, + aq_ret); +} + +/** + * i40e_vc_config_rss_lut + * @vf: pointer to the VF info + * @msg: pointer to the msg buffer + * @msglen: msg length + * + * Configure the VF's RSS LUT + **/ +static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg, u16 msglen) +{ + struct i40e_virtchnl_rss_lut *vrl = + (struct i40e_virtchnl_rss_lut *)msg; + struct i40e_pf *pf = vf->pf; + struct i40e_vsi *vsi = NULL; + u16 vsi_id = vrl->vsi_id; + i40e_status aq_ret = 0; + + if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || + !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) || + !i40e_vc_isvalid_vsi_id(vf, vsi_id) || + (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } + + vsi = pf->vsi[vf->lan_vsi_idx]; + aq_ret = i40e_config_rss(vsi, NULL, vrl->lut, I40E_VF_HLUT_ARRAY_SIZE); + /* send the response to the VF */ +err: + return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_RSS_LUT, + aq_ret); +} + +/** + * i40e_vc_get_rss_hena + * @vf: pointer to the VF info + * @msg: pointer to the msg buffer + * @msglen: msg length + * + * Return the RSS HENA bits allowed by the hardware + **/ +static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen) +{ + struct i40e_virtchnl_rss_hena *vrh = NULL; + struct i40e_pf *pf = vf->pf; + i40e_status aq_ret = 0; + int len = 0; + + if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || + !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } + len = sizeof(struct i40e_virtchnl_rss_hena); + + vrh = kzalloc(len, GFP_KERNEL); + if (!vrh) { + aq_ret = I40E_ERR_NO_MEMORY; + len = 0; + goto err; + } + vrh->hena = i40e_pf_get_default_rss_hena(pf); +err: + /* send the response back to the VF */ + aq_ret = i40e_vc_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS, + aq_ret, (u8 *)vrh, len); + return aq_ret; +} + +/** + * i40e_vc_set_rss_hena + * @vf: pointer to the VF info + * @msg: pointer to the msg buffer + * @msglen: msg length + * + * Set the RSS HENA bits for the VF + **/ +static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen) +{ + struct i40e_virtchnl_rss_hena *vrh = + (struct i40e_virtchnl_rss_hena *)msg; + struct i40e_pf *pf = vf->pf; + struct i40e_hw *hw = &pf->hw; + i40e_status aq_ret = 0; + + if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || + !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } + i40e_write_rx_ctl(hw, I40E_VFQF_HENA1(0, vf->vf_id), (u32)vrh->hena); + i40e_write_rx_ctl(hw, I40E_VFQF_HENA1(1, vf->vf_id), + (u32)(vrh->hena >> 32)); + + /* send the response to the VF */ +err: + return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_SET_RSS_HENA, + aq_ret); +} + /** * i40e_vc_validate_vf_msg * @vf: pointer to the VF info @@ -2162,6 +2302,36 @@ static int i40e_vc_validate_vf_msg(struct i40e_vf *vf, u32 v_opcode, sizeof(struct i40e_virtchnl_iwarp_qv_info)); } break; + case I40E_VIRTCHNL_OP_CONFIG_RSS_KEY: + valid_len = sizeof(struct i40e_virtchnl_rss_key); + if (msglen >= valid_len) { + struct i40e_virtchnl_rss_key *vrk = + (struct i40e_virtchnl_rss_key *)msg; + if (vrk->key_len != I40E_HKEY_ARRAY_SIZE) { + err_msg_format = true; + break; + } + valid_len += vrk->key_len - 1; + } + break; + case I40E_VIRTCHNL_OP_CONFIG_RSS_LUT: + valid_len = sizeof(struct i40e_virtchnl_rss_lut); + if (msglen >= valid_len) { + struct i40e_virtchnl_rss_lut *vrl = + (struct i40e_virtchnl_rss_lut *)msg; + if (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) { + err_msg_format = true; + break; + } + valid_len += vrl->lut_entries - 1; + } + break; + case I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS: + valid_len = 0; + break; + case I40E_VIRTCHNL_OP_SET_RSS_HENA: + valid_len = sizeof(struct i40e_virtchnl_rss_hena); + break; /* These are always errors coming from the VF. */ case I40E_VIRTCHNL_OP_EVENT: case I40E_VIRTCHNL_OP_UNKNOWN: @@ -2260,6 +2430,19 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode, case I40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP: ret = i40e_vc_iwarp_qvmap_msg(vf, msg, msglen, false); break; + case I40E_VIRTCHNL_OP_CONFIG_RSS_KEY: + ret = i40e_vc_config_rss_key(vf, msg, msglen); + break; + case I40E_VIRTCHNL_OP_CONFIG_RSS_LUT: + ret = i40e_vc_config_rss_lut(vf, msg, msglen); + break; + case I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS: + ret = i40e_vc_get_rss_hena(vf, msg, msglen); + break; + case I40E_VIRTCHNL_OP_SET_RSS_HENA: + ret = i40e_vc_set_rss_hena(vf, msg, msglen); + break; + case I40E_VIRTCHNL_OP_UNKNOWN: default: dev_err(&pf->pdev->dev, "Unsupported opcode %d from VF %d\n", -- GitLab From c0913c2e431c86026acba667f8655d90979bb79c Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 12 Apr 2016 08:30:41 -0700 Subject: [PATCH 4448/9938] i40evf: Don't Panic Under some circumstances the driver remove function may be called before the driver is fully initialized. So we can't assume that we know where our towel is at, or that all of the data structures are initialized. To ensure that we don't panic, check that the vsi_res pointer is valid before dereferencing it. Then drink beer and eat peanuts. Change-ID: If697b4db57348e39f9538793e16aa755e3e1af03 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index e657eccd232c..017c83b6271f 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -256,8 +256,10 @@ struct i40evf_adapter { bool netdev_registered; bool link_up; enum i40e_virtchnl_ops current_op; -#define CLIENT_ENABLED(_a) ((_a)->vf_res->vf_offload_flags & \ - I40E_VIRTCHNL_VF_OFFLOAD_IWARP) +#define CLIENT_ENABLED(_a) ((_a)->vf_res ? \ + (_a)->vf_res->vf_offload_flags & \ + I40E_VIRTCHNL_VF_OFFLOAD_IWARP : \ + 0) #define RSS_AQ(_a) ((_a)->vf_res->vf_offload_flags & \ I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ) #define VLAN_ALLOWED(_a) ((_a)->vf_res->vf_offload_flags & \ -- GitLab From 1847119dcc9841120dbdc45c0d049f37beed7a71 Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Mon, 25 Apr 2016 09:49:13 +0100 Subject: [PATCH 4449/9938] ARM: vexpress/mps2: introduce MPS2 platform The Cortex-M Prototyping System (or V2M-MPS2) is designed for prototyping and evaluation Cortex-M family of processors including the latest Cortex-M7 It comes with a range of useful peripherals including 8MB single cycle SRAM, 16MB PSRAM, Ethernet, QSVGA touch screen panel, 4bit RGB VGA connector, Audio, SPI and GPIO. Signed-off-by: Vladimir Murzin Signed-off-by: Sudeep Holla --- arch/arm/Kconfig | 12 ++++++++++++ arch/arm/Makefile | 1 + arch/arm/mach-vexpress/Makefile | 4 +++- arch/arm/mach-vexpress/Makefile.boot | 3 +++ arch/arm/mach-vexpress/v2m-mps2.c | 21 +++++++++++++++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-vexpress/Makefile.boot create mode 100644 arch/arm/mach-vexpress/v2m-mps2.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index cdfa6c2b7626..6cda5dc5575b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -892,6 +892,18 @@ config MACH_STM32F429 depends on ARCH_STM32 default y +config ARCH_MPS2 + bool "ARM MPS2 paltform" + depends on ARM_SINGLE_ARMV7M + select ARM_AMBA + select CLKSRC_MPS2 + help + Support for Cortex-M Prototyping System (or V2M-MPS2) which comes + with a range of available cores like Cortex-M3/M4/M7. + + Please, note that depends which Application Note is used memory map + for the platform may vary, so adjustment of RAM base might be needed. + # Definitions to make life easier config ARCH_ACORN bool diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 8c3ce2ac44c4..274e8a6582f1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -183,6 +183,7 @@ machine-$(CONFIG_ARCH_LPC18XX) += lpc18xx machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx machine-$(CONFIG_ARCH_MESON) += meson machine-$(CONFIG_ARCH_MMP) += mmp +machine-$(CONFIG_ARCH_MPS2) += vexpress machine-$(CONFIG_ARCH_MOXART) += moxart machine-$(CONFIG_ARCH_MV78XX0) += mv78xx0 machine-$(CONFIG_ARCH_MVEBU) += mvebu diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index f5c1006dd6a1..73caae71f307 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -4,7 +4,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := \ -I$(srctree)/arch/arm/plat-versatile/include -obj-y := v2m.o +obj-$(CONFIG_ARCH_VEXPRESS) := v2m.o obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o CFLAGS_dcscb.o += -march=armv7-a CFLAGS_REMOVE_dcscb.o = -pg @@ -15,3 +15,5 @@ CFLAGS_tc2_pm.o += -march=armv7-a CFLAGS_REMOVE_tc2_pm.o = -pg obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o + +obj-$(CONFIG_ARCH_MPS2) += v2m-mps2.o diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot new file mode 100644 index 000000000000..eacfc3f5c33e --- /dev/null +++ b/arch/arm/mach-vexpress/Makefile.boot @@ -0,0 +1,3 @@ +# Empty file waiting for deletion once Makefile.boot isn't needed any more. +# Patch waits for application at +# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 . diff --git a/arch/arm/mach-vexpress/v2m-mps2.c b/arch/arm/mach-vexpress/v2m-mps2.c new file mode 100644 index 000000000000..e7ad9c27231c --- /dev/null +++ b/arch/arm/mach-vexpress/v2m-mps2.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015 ARM Limited + * + * Author: Vladimir Murzin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include + +static const char *const mps2_compat[] __initconst = { + "arm,mps2", + NULL +}; + +DT_MACHINE_START(MPS2DT, "MPS2 (Device Tree Support)") + .dt_compat = mps2_compat, +MACHINE_END -- GitLab From 46a600eac9984037e027da4225f9b36d3f106da5 Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Mon, 25 Apr 2016 09:49:17 +0100 Subject: [PATCH 4450/9938] MAINTAINERS: Update ARM Versatile Express platform entry This patch update ARM Versatile Express entry to cover bits needed for Cortex-M Prototyping System (MPS2 platform). So patches for the latter are collected by existing Vexpress and Juno maintainers (Liviu, Sudeep, Lorenzo) and find their way upstream via Vexpess and/or Juno trees. Signed-off-by: Vladimir Murzin Signed-off-by: Sudeep Holla --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5d4286c7e42c..aaf47b1cf1b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1773,6 +1773,7 @@ F: */*/vexpress* F: */*/*/vexpress* F: drivers/clk/versatile/clk-vexpress-osc.c F: drivers/clocksource/versatile.c +N: mps2 ARM/VFP SUPPORT M: Russell King -- GitLab From f915ea5e7fd99861385b203e5a8582fdaa3a9b7c Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Mon, 25 Apr 2016 09:49:15 +0100 Subject: [PATCH 4451/9938] ARM: dts: introduce MPS2 AN385/AN386 Application Notes 385 and 386 shares the same memory map and features except the CPU is used. AN385 is supplied with Cortex-M3 CPU and AN386 is supplied with Cortex-M4. Reviewed-by: Linus Walleij Signed-off-by: Vladimir Murzin Signed-off-by: Sudeep Holla --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/mps2-an385.dts | 92 ++++++++++++ arch/arm/boot/dts/mps2.dtsi | 241 +++++++++++++++++++++++++++++++ 3 files changed, 334 insertions(+) create mode 100644 arch/arm/boot/dts/mps2-an385.dts create mode 100644 arch/arm/boot/dts/mps2.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f57199f40e19..5a4f50eac350 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -257,6 +257,7 @@ dtb-$(CONFIG_ARCH_MMP) += \ dtb-$(CONFIG_MACH_MESON8B) += \ meson8b-mxq.dtb \ meson8b-odroidc1.dtb +dtb-$(CONFIG_ARCH_MPS2) += mps2-an385.dtb dtb-$(CONFIG_ARCH_MOXART) += \ moxart-uc7112lx.dtb dtb-$(CONFIG_SOC_IMX1) += \ diff --git a/arch/arm/boot/dts/mps2-an385.dts b/arch/arm/boot/dts/mps2-an385.dts new file mode 100644 index 000000000000..31c374d72a6f --- /dev/null +++ b/arch/arm/boot/dts/mps2-an385.dts @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2015 ARM Limited + * + * Author: Vladimir Murzin + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "mps2.dtsi" + +/ { + model = "ARM MPS2 Application Note 385/386"; + compatible = "arm,mps2"; + + aliases { + serial0 = &uart0; + }; + + chosen { + bootargs = "earlycon"; + stdout-path = "serial0:9600n8"; + }; + + memory { + device_type = "memory"; + reg = <0x21000000 0x1000000>; + }; + + smb { + ethernet@0,0 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0 0x0 0x10000>; + interrupts = <13>; + interrupt-parent = <&nvic>; + smsc,irq-active-high; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/mps2.dtsi b/arch/arm/boot/dts/mps2.dtsi new file mode 100644 index 000000000000..e3fed8d34558 --- /dev/null +++ b/arch/arm/boot/dts/mps2.dtsi @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2015 ARM Limited + * + * Author: Vladimir Murzin + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "armv7-m.dtsi" + +/ { + oscclk0: clk-osc0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + }; + + oscclk1: clk-osc1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24576000>; + }; + + oscclk2: clk-osc2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + cfgclk: clk-cfg { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <5000000>; + }; + + spicfgclk: clk-spicfg { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <75000000>; + }; + + sysclk: clk-sys { + compatible = "fixed-factor-clock"; + clocks = <&oscclk0>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + }; + + audmclk: clk-audm { + compatible = "fixed-factor-clock"; + clocks = <&oscclk1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + }; + + audsclk: clk-auds { + compatible = "fixed-factor-clock"; + clocks = <&oscclk1>; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + }; + + spiclcd: clk-cpiclcd { + compatible = "fixed-factor-clock"; + clocks = <&oscclk0>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + }; + + spicon: clk-spicon { + compatible = "fixed-factor-clock"; + clocks = <&oscclk0>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + }; + + i2cclcd: clk-i2cclcd { + compatible = "fixed-factor-clock"; + clocks = <&oscclk0>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + }; + + i2caud: clk-i2caud { + compatible = "fixed-factor-clock"; + clocks = <&oscclk0>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + }; + + soc { + compatible = "simple-bus"; + ranges; + + apb@40000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40000000 0x10000>; + + timer0: mps2-timer0@0 { + compatible = "arm,mps2-timer"; + reg = <0x0 0x1000>; + interrupts = <8>; + clocks = <&sysclk>; + status = "disabled"; + }; + + timer1: mps2-timer1@1000 { + compatible = "arm,mps2-timer"; + reg = <0x1000 0x1000>; + interrupts = <9>; + clocks = <&sysclk>; + status = "disabled"; + }; + + timer2: dual-timer@2000 { + compatible = "arm,sp804"; + reg = <0x2000 0x1000>; + clocks = <&sysclk>; + interrupts = <10>; + status = "disabled"; + }; + + uart0: serial@4000 { + compatible = "arm,mps2-uart"; + reg = <0x4000 0x1000>; + interrupts = <0 1 12>; + clocks = <&sysclk>; + status = "disabled"; + }; + + uart1: serial@5000 { + compatible = "arm,mps2-uart"; + reg = <0x5000 0x1000>; + interrupts = <2 3 12>; + clocks = <&sysclk>; + status = "disabled"; + }; + + uart2: serial@6000 { + compatible = "arm,mps2-uart"; + reg = <0x6000 0x1000>; + interrupts = <4 5 12>; + clocks = <&sysclk>; + status = "disabled"; + }; + + wdt: watchdog@8000 { + compatible = "arm,sp805", "arm,primecell"; + arm,primecell-periphid = <0x00141805>; + reg = <0x8000 0x1000>; + interrupts = <0>; + clocks = <&sysclk>; + clock-names = "apb_pclk"; + status = "disabled"; + }; + }; + }; + + fpga@40020000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40020000 0x10000>; + + fpgaio@8000 { + compatible = "syscon", "simple-mfd"; + reg = <0x8000 0x10>; + + led0 { + compatible = "register-bit-led"; + offset = <0x0>; + mask = <0x01>; + label = "userled:0"; + linux,default-trigger = "heartbeat"; + default-state = "on"; + }; + + led1 { + compatible = "register-bit-led"; + offset = <0x0>; + mask = <0x02>; + label = "userled:1"; + linux,default-trigger = "usr"; + default-state = "off"; + }; + }; + }; + + smb { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x40200000 0x10000>, + <1 0 0xa0000000 0x10000>; + }; +}; -- GitLab From 1fb75865d8b80b216a6f540b32f6cd1480f8c843 Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Mon, 25 Apr 2016 09:49:16 +0100 Subject: [PATCH 4452/9938] ARM: dts: introduce MPS2 AN399/AN400 Application Notes 399 and 400 shares the same memory map and features. Both are shipped with Cortex-M7 and have the same peripheral as AN385/AN386, but with different location of PSRAM and Ethernet controller. Signed-off-by: Vladimir Murzin Signed-off-by: Sudeep Holla --- arch/arm/boot/dts/Makefile | 4 +- arch/arm/boot/dts/mps2-an399.dts | 92 ++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/mps2-an399.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 5a4f50eac350..4b4f086730ca 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -257,7 +257,9 @@ dtb-$(CONFIG_ARCH_MMP) += \ dtb-$(CONFIG_MACH_MESON8B) += \ meson8b-mxq.dtb \ meson8b-odroidc1.dtb -dtb-$(CONFIG_ARCH_MPS2) += mps2-an385.dtb +dtb-$(CONFIG_ARCH_MPS2) += \ + mps2-an385.dtb \ + mps2-an399.dtb dtb-$(CONFIG_ARCH_MOXART) += \ moxart-uc7112lx.dtb dtb-$(CONFIG_SOC_IMX1) += \ diff --git a/arch/arm/boot/dts/mps2-an399.dts b/arch/arm/boot/dts/mps2-an399.dts new file mode 100644 index 000000000000..5e7e5ca2edbf --- /dev/null +++ b/arch/arm/boot/dts/mps2-an399.dts @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2015 ARM Limited + * + * Author: Vladimir Murzin + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "mps2.dtsi" + +/ { + model = "ARM MPS2 Application Note 399/400"; + compatible = "arm,mps2"; + + aliases { + serial0 = &uart0; + }; + + chosen { + bootargs = "earlycon"; + stdout-path = "serial0:9600n8"; + }; + + memory { + device_type = "memory"; + reg = <0x60000000 0x1000000>; + }; + + smb { + ethernet@1,0 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <1 0x0 0x10000>; + interrupts = <13>; + interrupt-parent = <&nvic>; + smsc,irq-active-high; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; -- GitLab From 58e696d111ff3c111118126d9ffd790517acb131 Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Mon, 25 Apr 2016 09:49:14 +0100 Subject: [PATCH 4453/9938] ARM: configs: add MPS2 defconfig This patch adds a new config for MPS2 platform. Signed-off-by: Vladimir Murzin Signed-off-by: Sudeep Holla --- arch/arm/configs/mps2_defconfig | 109 ++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 arch/arm/configs/mps2_defconfig diff --git a/arch/arm/configs/mps2_defconfig b/arch/arm/configs/mps2_defconfig new file mode 100644 index 000000000000..19d119f5b77e --- /dev/null +++ b/arch/arm/configs/mps2_defconfig @@ -0,0 +1,109 @@ +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +# CONFIG_UID16 is not set +# CONFIG_BASE_FULL is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +# CONFIG_SIGNALFD is not set +# CONFIG_EVENTFD is not set +# CONFIG_AIO is not set +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_BLOCK is not set +# CONFIG_MMU is not set +CONFIG_ARCH_MPS2=y +CONFIG_SET_MEM_PARAM=y +CONFIG_DRAM_BASE=0x21000000 +CONFIG_DRAM_SIZE=0x1000000 +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_ATAGS is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_BINFMT_FLAT=y +CONFIG_BINFMT_SHARED_FLAT=y +# CONFIG_COREDUMP is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_FW_LOADER is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_CORE is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_MPS2_UART_CONSOLE=y +CONFIG_SERIAL_MPS2_UART=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_MFD_SYSCON=y +# CONFIG_USB_SUPPORT is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_SYSCON=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_ARM_TIMER_SP804=y +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V4=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_ROOT_NFS=y +CONFIG_NLS=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_DEBUG_FS=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_MEMTEST=y -- GitLab From 71c5e53b42f3641f6066c34b2c060dfe64d0ac2e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 26 Apr 2016 18:53:12 +0800 Subject: [PATCH 4454/9938] spi: Drop duplicate code to set master->dev.parent It's done by spi_alloc_master(). Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 1 - drivers/spi/spi-dln2.c | 1 - drivers/spi/spi-pxa2xx.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index c968ab210a51..2b1456e5e221 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -525,7 +525,6 @@ static int spi_engine_probe(struct platform_device *pdev) if (ret) goto err_ref_clk_disable; - master->dev.parent = &pdev->dev; master->dev.of_node = pdev->dev.of_node; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; master->bits_per_word_mask = SPI_BPW_MASK(8); diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index 4e8a8629d514..b62a99caacc0 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -701,7 +701,6 @@ static int dln2_spi_probe(struct platform_device *pdev) } dln2->master = master; - dln2->master->dev.parent = dev; dln2->master->dev.of_node = dev->of_node; dln2->pdev = pdev; dln2->port = pdata->port; diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 85e59a406a4c..e48320667b37 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1543,7 +1543,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) drv_data->pdev = pdev; drv_data->ssp = ssp; - master->dev.parent = &pdev->dev; master->dev.of_node = pdev->dev.of_node; /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; -- GitLab From bab3a34bb5f0b4056e37edf1bf6d097b147de453 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 12 Apr 2016 08:30:42 -0700 Subject: [PATCH 4455/9938] i40e: Code cleanup in i40e_add_fdir_ethtool A little bit of code cleanup in prep for more cloud filter work. Change-ID: I0dc33ce0d4c207944336a07437640fef920c100c Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 8a83d4514812..8e56c43c4104 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2506,7 +2506,6 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi, if (!vsi) return -EINVAL; - pf = vsi->back; if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED)) @@ -2564,15 +2563,18 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi, input->src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst; if (ntohl(fsp->m_ext.data[1])) { - if (ntohl(fsp->h_ext.data[1]) >= pf->num_alloc_vfs) { - netif_info(pf, drv, vsi->netdev, "Invalid VF id\n"); + vf_id = ntohl(fsp->h_ext.data[1]); + if (vf_id >= pf->num_alloc_vfs) { + netif_info(pf, drv, vsi->netdev, + "Invalid VF id %d\n", vf_id); goto free_input; } - vf_id = ntohl(fsp->h_ext.data[1]); /* Find vsi id from vf id and override dest vsi */ input->dest_vsi = pf->vf[vf_id].lan_vsi_id; if (input->q_index >= pf->vf[vf_id].num_queue_pairs) { - netif_info(pf, drv, vsi->netdev, "Invalid queue id\n"); + netif_info(pf, drv, vsi->netdev, + "Invalid queue id %d for VF %d\n", + input->q_index, vf_id); goto free_input; } } -- GitLab From 3b9d78a4f3886f84db0a58dc986fbabb937799c6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Apr 2016 15:13:10 +0200 Subject: [PATCH 4456/9938] ARM: debug: remove extraneous DEBUG_HI3716_UART option DEBUG_HI3716_UART was supposed to be renamed to DEBUG_HIX5HD2_UART, but accidentally both got left in place, which results in a build error when CONFIG_DEBUG_UART_PHYS is not set as it should be. This removes the old symbol. Signed-off-by: Arnd Bergmann Fixes: 12aae3097454 ("ARM: debug: Rename Hi3716 to HIX5HD2") Acked-by: Wei Xu --- arch/arm/Kconfig.debug | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 1098e91d6d3f..19a3dcf5eb2e 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -268,14 +268,6 @@ choice Say Y here if you want kernel low-level debugging support on HI3620 UART. - config DEBUG_HI3716_UART - bool "Hisilicon Hi3716 Debug UART" - depends on ARCH_HI3xxx - select DEBUG_UART_PL01X - help - Say Y here if you want kernel low-level debugging support - on HI3716 UART. - config DEBUG_HIGHBANK_UART bool "Kernel low-level debugging messages via Highbank UART" depends on ARCH_HIGHBANK -- GitLab From 3b1dbfa14f97188ec33fdfc7acb66bea59a3bb21 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 20 Apr 2016 03:59:47 -0400 Subject: [PATCH 4457/9938] cxl: Fix DAR check & use REGION_ID instead of opencoding The current code will set _PAGE_USER to the access flags for any fault address, because the ~ operation will be true for all address we take a fault on. But setting _PAGE_USER also means that the fault will be handled only if the page table have _PAGE_USER set. Hence there is no security hole with the current code. Now if it is an user space access, then the change in this patch really don't have an impact because we have (!ctx->kernel) set true and we take the if condition true. Now kernel context created fault on an address in the kernel range will result in a fault loop because we will not insert the hash pte due to access and pte permission mismatch. This patch fix the above issue. Fixes: f204e0b8cedd ("cxl: Driver code for powernv PCIe based cards for userspace access") Reviewed-by: Andrew Donnellan Acked-by: Ian Munsie Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- drivers/misc/cxl/fault.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c index 9a8650bcb042..9a236543da23 100644 --- a/drivers/misc/cxl/fault.c +++ b/drivers/misc/cxl/fault.c @@ -152,7 +152,7 @@ static void cxl_handle_page_fault(struct cxl_context *ctx, access = _PAGE_PRESENT; if (dsisr & CXL_PSL_DSISR_An_S) access |= _PAGE_RW; - if ((!ctx->kernel) || ~(dar & (1ULL << 63))) + if ((!ctx->kernel) || (REGION_ID(dar) == USER_REGION_ID)) access |= _PAGE_USER; if (dsisr & DSISR_NOHPTE) -- GitLab From de06f22f717b30641229036439b804ae79a7ad4d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 25 Apr 2016 19:30:39 -0400 Subject: [PATCH 4458/9938] ASoC: cs42l56: Use IS_ENABLED() instead of checking for built-in or module The IS_ENABLED() macro checks if a Kconfig symbol has been enabled either built-in or as a module, use that macro instead of open coding the same. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index 7cd5f769bb61..eec1ff853b98 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -56,7 +56,7 @@ struct cs42l56_private { u8 iface; u8 iface_fmt; u8 iface_inv; -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) +#if IS_ENABLED(CONFIG_INPUT) struct input_dev *beep; struct work_struct beep_work; int beep_rate; -- GitLab From 190c056fc32a528979807cb5d5a0d68285933073 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:41 +0200 Subject: [PATCH 4459/9938] arm64: kernel: don't export local symbols from head.S This unexports some symbols from head.S that are only used locally. Acked-by: Catalin Marinas Acked-by: Mark Rutland Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/head.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index b43417618847..ac27d8d937b2 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -638,7 +638,7 @@ ENDPROC(el2_setup) * Sets the __boot_cpu_mode flag depending on the CPU boot mode passed * in x20. See arch/arm64/include/asm/virt.h for more info. */ -ENTRY(set_cpu_boot_mode_flag) +set_cpu_boot_mode_flag: adr_l x1, __boot_cpu_mode cmp w20, #BOOT_CPU_MODE_EL2 b.ne 1f @@ -691,7 +691,7 @@ ENTRY(secondary_entry) b secondary_startup ENDPROC(secondary_entry) -ENTRY(secondary_startup) +secondary_startup: /* * Common entry point for secondary CPUs. */ @@ -706,7 +706,7 @@ ENTRY(secondary_startup) ENDPROC(secondary_startup) 0: .long (_text - TEXT_OFFSET) - __secondary_switched -ENTRY(__secondary_switched) +__secondary_switched: adr_l x5, vectors msr vbar_el1, x5 isb -- GitLab From e5ebeec879b726c755af0c1c15f3699b53268cd5 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:42 +0200 Subject: [PATCH 4460/9938] arm64: kernel: use literal for relocated address of __secondary_switched We can simply use a relocated 64-bit literal to store the address of __secondary_switched(), and the relocation code will ensure that it holds the correct value at secondary entry time, as long as we make sure that the literal is not dereferenced until after we have enabled the MMU. So jump via a small __secondary_switch() function covered by the ID map that performs the literal load and branch-to-register. Acked-by: Catalin Marinas Acked-by: Mark Rutland Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/head.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index ac27d8d937b2..f13276d4ca91 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -468,9 +468,7 @@ __mmap_switched: str x15, [x11, x23] b 0b -2: adr_l x8, kimage_vaddr // make relocated kimage_vaddr - dc cvac, x8 // value visible to secondaries - dsb sy // with MMU off +2: #endif adr_l sp, initial_sp, x4 @@ -699,12 +697,9 @@ secondary_startup: adrp x26, swapper_pg_dir bl __cpu_setup // initialise processor - ldr x8, kimage_vaddr - ldr w9, 0f - sub x27, x8, w9, sxtw // address to jump to after enabling the MMU + adr_l x27, __secondary_switch // address to jump to after enabling the MMU b __enable_mmu ENDPROC(secondary_startup) -0: .long (_text - TEXT_OFFSET) - __secondary_switched __secondary_switched: adr_l x5, vectors @@ -806,3 +801,8 @@ __no_granule_support: wfi b 1b ENDPROC(__no_granule_support) + +__secondary_switch: + ldr x8, =__secondary_switched + br x8 +ENDPROC(__secondary_switch) -- GitLab From 0cd3defe0af4153ffc5fe39bcfa4abfc301984e9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:43 +0200 Subject: [PATCH 4461/9938] arm64: kernel: perform relocation processing from ID map Refactor the relocation processing so that the code executes from the ID map while accessing the relocation tables via the virtual mapping. This way, we can use literals containing virtual addresses as before, instead of having to use convoluted absolute expressions. For symmetry with the secondary code path, the relocation code and the subsequent jump to the virtual entry point are implemented in a function called __primary_switch(), and __mmap_switched() is renamed to __primary_switched(). Also, the call sequence in stext() is aligned with the one in secondary_startup(), by replacing the awkward 'adr_l lr' and 'b cpu_setup' sequence with a simple branch and link. Acked-by: Catalin Marinas Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/head.S | 96 +++++++++++++++++---------------- arch/arm64/kernel/vmlinux.lds.S | 7 +-- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index f13276d4ca91..0d487d90d221 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -223,13 +223,11 @@ ENTRY(stext) * On return, the CPU will be ready for the MMU to be turned on and * the TCR will have been set. */ - ldr x27, 0f // address to jump to after - neg x27, x27 // MMU has been enabled - adr_l lr, __enable_mmu // return (PIC) address - b __cpu_setup // initialise processor + bl __cpu_setup // initialise processor + adr_l x27, __primary_switch // address to jump to after + // MMU has been enabled + b __enable_mmu ENDPROC(stext) - .align 3 -0: .quad (_text - TEXT_OFFSET) - __mmap_switched - KIMAGE_VADDR /* * Preserve the arguments passed by the bootloader in x0 .. x3 @@ -421,7 +419,7 @@ ENDPROC(__create_page_tables) * The following fragment of code is executed with the MMU enabled. */ .set initial_sp, init_thread_union + THREAD_START_SP -__mmap_switched: +__primary_switched: mov x28, lr // preserve LR adr_l x8, vectors // load VBAR_EL1 with virtual msr vbar_el1, x8 // vector table address @@ -435,42 +433,6 @@ __mmap_switched: bl __pi_memset dsb ishst // Make zero page visible to PTW -#ifdef CONFIG_RELOCATABLE - - /* - * Iterate over each entry in the relocation table, and apply the - * relocations in place. - */ - adr_l x8, __dynsym_start // start of symbol table - adr_l x9, __reloc_start // start of reloc table - adr_l x10, __reloc_end // end of reloc table - -0: cmp x9, x10 - b.hs 2f - ldp x11, x12, [x9], #24 - ldr x13, [x9, #-8] - cmp w12, #R_AARCH64_RELATIVE - b.ne 1f - add x13, x13, x23 // relocate - str x13, [x11, x23] - b 0b - -1: cmp w12, #R_AARCH64_ABS64 - b.ne 0b - add x12, x12, x12, lsl #1 // symtab offset: 24x top word - add x12, x8, x12, lsr #(32 - 3) // ... shifted into bottom word - ldrsh w14, [x12, #6] // Elf64_Sym::st_shndx - ldr x15, [x12, #8] // Elf64_Sym::st_value - cmp w14, #-0xf // SHN_ABS (0xfff1) ? - add x14, x15, x23 // relocate - csel x15, x14, x15, ne - add x15, x13, x15 - str x15, [x11, x23] - b 0b - -2: -#endif - adr_l sp, initial_sp, x4 mov x4, sp and x4, x4, #~(THREAD_SIZE - 1) @@ -496,7 +458,7 @@ __mmap_switched: 0: #endif b start_kernel -ENDPROC(__mmap_switched) +ENDPROC(__primary_switched) /* * end early head section, begin head code that is also used for @@ -788,7 +750,6 @@ __enable_mmu: ic iallu // flush instructions fetched dsb nsh // via old mapping isb - add x27, x27, x23 // relocated __mmap_switched #endif br x27 ENDPROC(__enable_mmu) @@ -802,6 +763,51 @@ __no_granule_support: b 1b ENDPROC(__no_granule_support) +__primary_switch: +#ifdef CONFIG_RELOCATABLE + /* + * Iterate over each entry in the relocation table, and apply the + * relocations in place. + */ + ldr w8, =__dynsym_offset // offset to symbol table + ldr w9, =__rela_offset // offset to reloc table + ldr w10, =__rela_size // size of reloc table + + ldr x11, =KIMAGE_VADDR // default virtual offset + add x11, x11, x23 // actual virtual offset + add x8, x8, x11 // __va(.dynsym) + add x9, x9, x11 // __va(.rela) + add x10, x9, x10 // __va(.rela) + sizeof(.rela) + +0: cmp x9, x10 + b.hs 2f + ldp x11, x12, [x9], #24 + ldr x13, [x9, #-8] + cmp w12, #R_AARCH64_RELATIVE + b.ne 1f + add x13, x13, x23 // relocate + str x13, [x11, x23] + b 0b + +1: cmp w12, #R_AARCH64_ABS64 + b.ne 0b + add x12, x12, x12, lsl #1 // symtab offset: 24x top word + add x12, x8, x12, lsr #(32 - 3) // ... shifted into bottom word + ldrsh w14, [x12, #6] // Elf64_Sym::st_shndx + ldr x15, [x12, #8] // Elf64_Sym::st_value + cmp w14, #-0xf // SHN_ABS (0xfff1) ? + add x14, x15, x23 // relocate + csel x15, x14, x15, ne + add x15, x13, x15 + str x15, [x11, x23] + b 0b + +2: +#endif + ldr x8, =__primary_switched + br x8 +ENDPROC(__primary_switch) + __secondary_switch: ldr x8, =__secondary_switched br x8 diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 77d86c976abd..8918b303cc61 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -158,12 +158,9 @@ SECTIONS *(.altinstr_replacement) } .rela : ALIGN(8) { - __reloc_start = .; *(.rela .rela*) - __reloc_end = .; } .dynsym : ALIGN(8) { - __dynsym_start = .; *(.dynsym) } .dynstr : { @@ -173,6 +170,10 @@ SECTIONS *(.hash) } + __rela_offset = ADDR(.rela) - KIMAGE_VADDR; + __rela_size = SIZEOF(.rela); + __dynsym_offset = ADDR(.dynsym) - KIMAGE_VADDR; + . = ALIGN(SEGMENT_ALIGN); __init_end = .; -- GitLab From 30b5ba5cf333cc650e474eaf2cc1ae91bc7cf89f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:44 +0200 Subject: [PATCH 4462/9938] arm64: introduce mov_q macro to move a constant into a 64-bit register Implement a macro mov_q that can be used to move an immediate constant into a 64-bit register, using between 2 and 4 movz/movk instructions (depending on the operand) Acked-by: Catalin Marinas Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/include/asm/assembler.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 972fb55af9f1..f9b6f7af75ac 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -221,4 +221,24 @@ lr .req x30 // link register .long \sym\()_hi32 .endm + /* + * mov_q - move an immediate constant into a 64-bit register using + * between 2 and 4 movz/movk instructions (depending on the + * magnitude and sign of the operand) + */ + .macro mov_q, reg, val + .if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff) + movz \reg, :abs_g1_s:\val + .else + .if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff) + movz \reg, :abs_g2_s:\val + .else + movz \reg, :abs_g3:\val + movk \reg, :abs_g2_nc:\val + .endif + movk \reg, :abs_g1_nc:\val + .endif + movk \reg, :abs_g0_nc:\val + .endm + #endif /* __ASM_ASSEMBLER_H */ -- GitLab From b03cc885328e3c0de61843737d42eb0a0f112aab Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:45 +0200 Subject: [PATCH 4463/9938] arm64: kernel: replace early 64-bit literal loads with move-immediates When building a relocatable kernel, we currently rely on the fact that early 64-bit literal loads need to be deferred to after the relocation has been performed only if they involve symbol references, and not if they involve assemble time constants. While this is not an unreasonable assumption to make, it is better to switch to movk/movz sequences, since these are guaranteed to be resolved at link time, simply because there are no dynamic relocation types to describe them. Acked-by: Catalin Marinas Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/head.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 0d487d90d221..dae9cabaadf5 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -337,7 +337,7 @@ __create_page_tables: cmp x0, x6 b.lo 1b - ldr x7, =SWAPPER_MM_MMUFLAGS + mov x7, SWAPPER_MM_MMUFLAGS /* * Create the identity mapping. @@ -393,7 +393,7 @@ __create_page_tables: * Map the kernel image (starting with PHYS_OFFSET). */ mov x0, x26 // swapper_pg_dir - ldr x5, =KIMAGE_VADDR + mov_q x5, KIMAGE_VADDR add x5, x5, x23 // add KASLR displacement create_pgd_entry x0, x5, x3, x6 ldr w6, =kernel_img_size @@ -631,7 +631,7 @@ ENTRY(secondary_holding_pen) bl el2_setup // Drop to EL1, w20=cpu_boot_mode bl set_cpu_boot_mode_flag mrs x0, mpidr_el1 - ldr x1, =MPIDR_HWID_BITMASK + mov_q x1, MPIDR_HWID_BITMASK and x0, x0, x1 adr_l x3, secondary_holding_pen_release pen: ldr x4, [x3] @@ -773,7 +773,7 @@ __primary_switch: ldr w9, =__rela_offset // offset to reloc table ldr w10, =__rela_size // size of reloc table - ldr x11, =KIMAGE_VADDR // default virtual offset + mov_q x11, KIMAGE_VADDR // default virtual offset add x11, x11, x23 // actual virtual offset add x8, x8, x11 // __va(.dynsym) add x9, x9, x11 // __va(.rela) -- GitLab From 18b9c0d641938242d8bcdba3c14a8f2beec2a97e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:46 +0200 Subject: [PATCH 4464/9938] arm64: don't map TEXT_OFFSET bytes below the kernel if we can avoid it For historical reasons, the kernel Image must be loaded into physical memory at a 512 KB offset above a 2 MB aligned base address. The region between the base address and the start of the kernel Image has no significance to the kernel itself, but it is currently mapped explicitly into the early kernel VMA range for all translation granules. In some cases (i.e., 4 KB granule), this is unavoidable, due to the 2 MB granularity of the early kernel mappings. However, in other cases, e.g., when running with larger page sizes, or in the future, with more granular KASLR, there is no reason to map it explicitly like we do currently. So update the logic so that the region is mapped only if that happens as a side effect of rounding the start address of the kernel to swapper block size, and leave it unmapped otherwise. Since the symbol kernel_img_size now simply resolves to the memory footprint of the kernel Image, we can drop its definition from image.h and opencode its calculation. Acked-by: Catalin Marinas Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/head.S | 9 +++++---- arch/arm64/kernel/image.h | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index dae9cabaadf5..c5e5edca6897 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -393,12 +393,13 @@ __create_page_tables: * Map the kernel image (starting with PHYS_OFFSET). */ mov x0, x26 // swapper_pg_dir - mov_q x5, KIMAGE_VADDR + mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text) add x5, x5, x23 // add KASLR displacement create_pgd_entry x0, x5, x3, x6 - ldr w6, =kernel_img_size - add x6, x6, x5 - mov x3, x24 // phys offset + adrp x6, _end // runtime __pa(_end) + adrp x3, _text // runtime __pa(_text) + sub x6, x6, x3 // _end - _text + add x6, x6, x5 // runtime __va(_end) create_block_map x0, x7, x3, x5, x6 /* diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h index 4fd72da646a3..86d444f9c2c1 100644 --- a/arch/arm64/kernel/image.h +++ b/arch/arm64/kernel/image.h @@ -71,8 +71,6 @@ DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \ DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS); -kernel_img_size = _end - (_text - TEXT_OFFSET); - #ifdef CONFIG_EFI __efistub_stext_offset = stext - _text; -- GitLab From 08cdac619c81b3fa8cd73aeed2330ffe0a0b73ca Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:47 +0200 Subject: [PATCH 4465/9938] arm64: relocatable: deal with physically misaligned kernel images When booting a relocatable kernel image, there is no practical reason to refuse an image whose load address is not exactly TEXT_OFFSET bytes above a 2 MB aligned base address, as long as the physical and virtual misalignment with respect to the swapper block size are equal, and are both aligned to THREAD_SIZE. Since the virtual misalignment is under our control when we first enter the kernel proper, we can simply choose its value to be equal to the physical misalignment. So treat the misalignment of the physical load address as the initial KASLR offset, and fix up the remaining code to deal with that. Acked-by: Catalin Marinas Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- arch/arm64/kernel/head.S | 9 ++++++--- arch/arm64/kernel/kaslr.c | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index c5e5edca6897..00a32101ab51 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -213,8 +214,8 @@ efi_header_end: ENTRY(stext) bl preserve_boot_args bl el2_setup // Drop to EL1, w20=cpu_boot_mode - mov x23, xzr // KASLR offset, defaults to 0 adrp x24, __PHYS_OFFSET + and x23, x24, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0 bl set_cpu_boot_mode_flag bl __create_page_tables // x25=TTBR0, x26=TTBR1 /* @@ -449,11 +450,13 @@ __primary_switched: bl kasan_early_init #endif #ifdef CONFIG_RANDOMIZE_BASE - cbnz x23, 0f // already running randomized? + tst x23, ~(MIN_KIMG_ALIGN - 1) // already running randomized? + b.ne 0f mov x0, x21 // pass FDT address in x0 + mov x1, x23 // pass modulo offset in x1 bl kaslr_early_init // parse FDT for KASLR options cbz x0, 0f // KASLR disabled? just proceed - mov x23, x0 // record KASLR offset + orr x23, x23, x0 // record KASLR offset ret x28 // we must enable KASLR, return // to __enable_mmu() 0: diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index 582983920054..b05469173ba5 100644 --- a/arch/arm64/kernel/kaslr.c +++ b/arch/arm64/kernel/kaslr.c @@ -74,7 +74,7 @@ extern void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, * containing function pointers) to be reinitialized, and zero-initialized * .bss variables will be reset to 0. */ -u64 __init kaslr_early_init(u64 dt_phys) +u64 __init kaslr_early_init(u64 dt_phys, u64 modulo_offset) { void *fdt; u64 seed, offset, mask, module_range; @@ -132,8 +132,8 @@ u64 __init kaslr_early_init(u64 dt_phys) * boundary (for 4KB/16KB/64KB granule kernels, respectively). If this * happens, increase the KASLR offset by the size of the kernel image. */ - if ((((u64)_text + offset) >> SWAPPER_TABLE_SHIFT) != - (((u64)_end + offset) >> SWAPPER_TABLE_SHIFT)) + if ((((u64)_text + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT) != + (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT)) offset = (offset + (u64)(_end - _text)) & mask; if (IS_ENABLED(CONFIG_KASAN)) -- GitLab From 296ad4acb8efeffa456e344c73dc9459f4e9e1a0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 10:39:21 +0200 Subject: [PATCH 4466/9938] gpio: remove deps on ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPIOLIB symbol currently require that ARCH_WANT_OPTIONAL_GPIOLIB or ARCH_REQUIRE_GPIOLIB is selected to be selectable. The ARCH_REQUIRE_GPIOLIB does only one thing: select GPIOLIB. This is just confusing: architectures that want GPIOLIB should be able to configure it in no matter what, and those who require it should just select GPIOLIB. It also creates problems for drivers that need to state "select GPIOLIB" to get dependencies: those depend on the selected architecture to select ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB first, and will cause compile errors for the few archs that state neither. These intermediary symbols need to go. As a first step, remove the dependencies so that: - ARCH_WANT_OPTIONAL_GPIOLIB becomes a noop (GPIOLIB will be available for everyone) and - "select ARCH_REQUIRE_GPIOLIB" can be replaced by just "select GPIOLIB" After this patch we can follow up with patches cleaning up the architectures one-by one and eventually remove the ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB symbols altogether. Reported-by: Michael Hennerich Cc: Michael Büsch Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f73f26b43532..a68d83808f37 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -33,7 +33,6 @@ config ARCH_REQUIRE_GPIOLIB menuconfig GPIOLIB bool "GPIO Support" - depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB help This enables GPIO support through the generic GPIO library. You only need to enable this, if you also want to enable -- GitLab From 5a161394aeb0b36c1be7ef6f54103cd13c95b8a1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 11:10:42 +0200 Subject: [PATCH 4467/9938] avr32: do away with ARCH_REQUIRE_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB" as this can now be selected directly. Cc: Michael Büsch Cc: Haavard Skinnemoen Acked-by: Acked-by: Hans-Christian Noren Egtvedt Signed-off-by: Linus Walleij --- arch/avr32/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index b6878eb64884..18b88779e701 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -74,7 +74,7 @@ config PLATFORM_AT32AP select SUBARCH_AVR32B select MMU select PERFORMANCE_COUNTERS - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select GENERIC_ALLOCATOR select HAVE_FB_ATMEL -- GitLab From 769e4b8a3d84712db667a0fe55f6bdd4e1cfce8d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:32:21 +0200 Subject: [PATCH 4468/9938] metag: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: linux-metag@vger.kernel.org Acked-by: James Hogan Signed-off-by: Linus Walleij --- arch/metag/Kconfig.soc | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/metag/Kconfig.soc b/arch/metag/Kconfig.soc index 973640f46752..50f979c2b02d 100644 --- a/arch/metag/Kconfig.soc +++ b/arch/metag/Kconfig.soc @@ -16,7 +16,6 @@ config META21_FPGA config SOC_TZ1090 bool "Toumaz Xenif TZ1090 SoC (Comet)" - select ARCH_WANT_OPTIONAL_GPIOLIB select IMGPDC_IRQ select METAG_LNKGET_AROUND_CACHE select METAG_META21 -- GitLab From 513527c87a7feab2a5b31db07e5b07864d3c08f7 Mon Sep 17 00:00:00 2001 From: Alan Liu Date: Tue, 26 Apr 2016 14:41:33 +0300 Subject: [PATCH 4469/9938] ath10k: add max_tx_power for QCA6174 WLAN.RM.2.0 firmware QCA6174 WLAN.RM.2.0 firmware uses max_tx_power instead of using max_reg_power to set transmission power. The tx power was about -50dbm, after applying this change, it become -32dbm. Signed-off-by: Alan Liu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 1 + drivers/net/wireless/ath/ath10k/wmi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 621019f43531..39a54a544d45 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1633,6 +1633,7 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, ch->max_power = arg->max_power; ch->reg_power = arg->max_reg_power; ch->antenna_max = arg->max_antenna_gain; + ch->max_tx_power = arg->max_power; /* mode & flags share storage */ ch->mode = arg->mode; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index db2553522d8b..fe36b2c99018 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1795,6 +1795,7 @@ struct wmi_channel { __le32 reginfo1; struct { u8 antenna_max; + u8 max_tx_power; } __packed; } __packed; } __packed; -- GitLab From f70844460f03e6ad6cfb148f4c394fdda1b50363 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 25 Apr 2016 16:38:47 -0300 Subject: [PATCH 4470/9938] ARM: dts: imx6ul: Fix operating points Adjust the VDD_ARM_CAP and VDD_SOC_CAP voltages according to Table-11 from MX6UL datasheet: http://cache.nxp.com/files/32bit/doc/data_sheet/IMX6ULCEC.pdf (a 25mV offset is added to the minimum allowed values for safety). Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 71778992f03d..4356b655ef02 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -55,15 +55,15 @@ clock-latency = <61036>; /* two CLK32 periods */ operating-points = < /* kHz uV */ - 528000 1250000 - 396000 1150000 - 198000 1150000 + 528000 1175000 + 396000 1025000 + 198000 950000 >; fsl,soc-operating-points = < /* KHz uV */ - 528000 1250000 - 396000 1150000 - 198000 1150000 + 528000 1175000 + 396000 1175000 + 198000 1175000 >; clocks = <&clks IMX6UL_CLK_ARM>, <&clks IMX6UL_CLK_PLL2_BUS>, -- GitLab From fe4266baba600218e076e01bc446e36f30e85d29 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 25 Apr 2016 16:38:48 -0300 Subject: [PATCH 4471/9938] ARM: dts: imx6sx: Add 198MHz operating point 198MHz is a valid operating point for mx6sx. Add entries for VDD_ARM_CAP and VDD_SOC_CAP voltages for 198MHz according to the imx6sx datahseet: http://cache.nxp.com/files/32bit/doc/data_sheet/IMX6SXIEC.pdf (a 25mV offset is added to the minimum allowed values for safety). These values also match the ones from the NXP kernel. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index d02ab324c7ba..6a993bfda248 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -63,12 +63,14 @@ 996000 1250000 792000 1175000 396000 1075000 + 198000 975000 >; fsl,soc-operating-points = < /* ARM kHz SOC uV */ 996000 1175000 792000 1175000 396000 1175000 + 198000 1175000 >; clock-latency = <61036>; /* two CLK32 periods */ clocks = <&clks IMX6SX_CLK_ARM>, -- GitLab From 46350b71a09ccf3573649e03db55d4b61d5da231 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 25 Apr 2016 17:37:17 -0300 Subject: [PATCH 4472/9938] ARM: dts: imx6dl: Fix the VDD_ARM_CAP voltage for 396MHz operation Table 8 from MX6DL datasheet (IMX6SDLCEC Rev. 5, 06/2015): http://cache.nxp.com/files/32bit/doc/data_sheet/IMX6SDLCEC.pdf states the following: "LDO Output Set Point (VDD_ARM_CAP) = 1.125 V minimum for operation up to 396 MHz." So fix the entry by adding the 25mV margin value as done in the other entries of the table, which results in 1.15V for 396MHz operation. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi index c13a73aa55ca..9a4c22c2dade 100644 --- a/arch/arm/boot/dts/imx6dl.dtsi +++ b/arch/arm/boot/dts/imx6dl.dtsi @@ -30,7 +30,7 @@ /* kHz uV */ 996000 1250000 792000 1175000 - 396000 1075000 + 396000 1150000 >; fsl,soc-operating-points = < /* ARM kHz SOC-PU uV */ -- GitLab From 416196cd90999c29b04ca04cfbd713c73784a4ef Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Mon, 25 Apr 2016 18:09:33 -0700 Subject: [PATCH 4473/9938] ARM: dts: imx6: fix dtc warnings for ipu endpoints When compiled with "W=1", dtc complains: e.g. "Warning (unit_address_vs_reg): Node /soc/ipu@02800000/port@2/endpoint@0 has a unit name, but no reg property" Endpoint nodes don't have a reg property, and the addresses in their node names are ordinals without any special meaning so remove them and swap them for semantic node names. Signed-off-by: Joshua Clayton Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q.dtsi | 18 +++++++++--------- arch/arm/boot/dts/imx6qdl.dtsi | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index cd10c8de1904..c30c8368cae0 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -154,22 +154,22 @@ #size-cells = <0>; reg = <2>; - ipu2_di0_disp0: endpoint@0 { + ipu2_di0_disp0: disp0-endpoint { }; - ipu2_di0_hdmi: endpoint@1 { + ipu2_di0_hdmi: hdmi-endpoint { remote-endpoint = <&hdmi_mux_2>; }; - ipu2_di0_mipi: endpoint@2 { + ipu2_di0_mipi: mipi-endpoint { remote-endpoint = <&mipi_mux_2>; }; - ipu2_di0_lvds0: endpoint@3 { + ipu2_di0_lvds0: lvds0-endpoint { remote-endpoint = <&lvds0_mux_2>; }; - ipu2_di0_lvds1: endpoint@4 { + ipu2_di0_lvds1: lvds1-endpoint { remote-endpoint = <&lvds1_mux_2>; }; }; @@ -179,19 +179,19 @@ #size-cells = <0>; reg = <3>; - ipu2_di1_hdmi: endpoint@1 { + ipu2_di1_hdmi: hdmi-endpoint { remote-endpoint = <&hdmi_mux_3>; }; - ipu2_di1_mipi: endpoint@2 { + ipu2_di1_mipi: mipi-endpoint { remote-endpoint = <&mipi_mux_3>; }; - ipu2_di1_lvds0: endpoint@3 { + ipu2_di1_lvds0: lvds0-endpoint { remote-endpoint = <&lvds0_mux_3>; }; - ipu2_di1_lvds1: endpoint@4 { + ipu2_di1_lvds1: lvds1-endpoint { remote-endpoint = <&lvds1_mux_3>; }; }; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index b42822aa14f2..294afa7734b7 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -1230,22 +1230,22 @@ #size-cells = <0>; reg = <2>; - ipu1_di0_disp0: endpoint@0 { + ipu1_di0_disp0: disp0-endpoint { }; - ipu1_di0_hdmi: endpoint@1 { + ipu1_di0_hdmi: hdmi-endpoint { remote-endpoint = <&hdmi_mux_0>; }; - ipu1_di0_mipi: endpoint@2 { + ipu1_di0_mipi: mipi-endpoint { remote-endpoint = <&mipi_mux_0>; }; - ipu1_di0_lvds0: endpoint@3 { + ipu1_di0_lvds0: lvds0-endpoint { remote-endpoint = <&lvds0_mux_0>; }; - ipu1_di0_lvds1: endpoint@4 { + ipu1_di0_lvds1: lvds1-endpoint { remote-endpoint = <&lvds1_mux_0>; }; }; @@ -1255,22 +1255,22 @@ #size-cells = <0>; reg = <3>; - ipu1_di0_disp1: endpoint@0 { + ipu1_di0_disp1: disp1-endpoint { }; - ipu1_di1_hdmi: endpoint@1 { + ipu1_di1_hdmi: hdmi-endpoint { remote-endpoint = <&hdmi_mux_1>; }; - ipu1_di1_mipi: endpoint@2 { + ipu1_di1_mipi: mipi-endpoint { remote-endpoint = <&mipi_mux_1>; }; - ipu1_di1_lvds0: endpoint@3 { + ipu1_di1_lvds0: lvds0-endpoint { remote-endpoint = <&lvds0_mux_1>; }; - ipu1_di1_lvds1: endpoint@4 { + ipu1_di1_lvds1: lvds1-endpoint { remote-endpoint = <&lvds1_mux_1>; }; }; -- GitLab From 6dfdbfc78a2fb1a59680e9a1ee2f462cc768f386 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 26 Apr 2016 14:41:36 +0300 Subject: [PATCH 4474/9938] ath10k: fix a typo in ath10k_start() fix a typo (spelling mistake) in 'ath10k_start' Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0e24f9ee8bff..de31eb66cedf 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4346,7 +4346,7 @@ static int ath10k_start(struct ieee80211_hw *hw) /* * This makes sense only when restarting hw. It is harmless to call - * uncoditionally. This is necessary to make sure no HTT/WMI tx + * unconditionally. This is necessary to make sure no HTT/WMI tx * commands will be submitted while restarting. */ ath10k_drain_tx(ar); -- GitLab From 907ec43a486df72891e79e1f47a718ee17e36ee2 Mon Sep 17 00:00:00 2001 From: Steve deRosier Date: Tue, 26 Apr 2016 14:41:37 +0300 Subject: [PATCH 4475/9938] ath6kl: fix missing uart debug pin for 6004 HW 3.0 For some reason, the 6004 HW 3.0 definition was missing the value for the uarttx_pin (used for firmware debug). This corrects this situation. Signed-off-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index da557dc742e6..3daeb27978ee 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -173,6 +173,7 @@ static const struct ath6kl_hw hw_list[] = { .reserved_ram_size = 7168, .board_addr = 0x436400, .testscript_addr = 0, + .uarttx_pin = 11, .flags = 0, .fw = { -- GitLab From f8a68c9668a63249d0105444101a99d9eccd7cc2 Mon Sep 17 00:00:00 2001 From: Steve deRosier Date: Tue, 26 Apr 2016 14:41:37 +0300 Subject: [PATCH 4476/9938] ath6kl: add ability to set debug uart baud rate It's useful to permit the customization of the debug uart baud rate. Enable this and send down the value to the chip if we're enabling debug. Signed-off-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.c | 3 +++ drivers/net/wireless/ath/ath6kl/core.h | 1 + drivers/net/wireless/ath/ath6kl/init.c | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 4ec02cea0f43..ebb9f163710f 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -31,6 +31,7 @@ unsigned int debug_mask; static unsigned int suspend_mode; static unsigned int wow_mode; static unsigned int uart_debug; +static unsigned int uart_rate = 115200; static unsigned int ath6kl_p2p; static unsigned int testmode; static unsigned int recovery_enable; @@ -40,6 +41,7 @@ module_param(debug_mask, uint, 0644); module_param(suspend_mode, uint, 0644); module_param(wow_mode, uint, 0644); module_param(uart_debug, uint, 0644); +module_param(uart_rate, uint, 0644); module_param(ath6kl_p2p, uint, 0644); module_param(testmode, uint, 0644); module_param(recovery_enable, uint, 0644); @@ -180,6 +182,7 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) if (uart_debug) ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; + ar->hw.uarttx_rate = uart_rate; set_bit(FIRST_BOOT, &ar->flag); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 713a571a27ce..7a1970e484a6 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -781,6 +781,7 @@ struct ath6kl { u32 board_addr; u32 refclk_hz; u32 uarttx_pin; + u32 uarttx_rate; u32 testscript_addr; u8 tx_ant; u8 rx_ant; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 3daeb27978ee..58fb227a849f 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -651,6 +651,14 @@ int ath6kl_configure_target(struct ath6kl *ar) if (status) return status; + /* Only set the baud rate if we're actually doing debug */ + if (ar->conf_flags & ATH6KL_CONF_UART_DEBUG) { + status = ath6kl_bmi_write_hi32(ar, hi_desired_baud_rate, + ar->hw.uarttx_rate); + if (status) + return status; + } + /* Configure target refclk_hz */ if (ar->hw.refclk_hz != 0) { status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, -- GitLab From 290206fa7e04ea4c1620aea2624e4d998bc27a0a Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 26 Apr 2016 14:41:38 +0300 Subject: [PATCH 4477/9938] wil6210: add function name to wil log macros Add __func__ to wil_err and wil_info for easier debugging. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debug.c | 6 +++--- drivers/net/wireless/ath/wil6210/wil6210.h | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c index 3249562d93b4..0a301277c06d 100644 --- a/drivers/net/wireless/ath/wil6210/debug.c +++ b/drivers/net/wireless/ath/wil6210/debug.c @@ -17,7 +17,7 @@ #include "wil6210.h" #include "trace.h" -void wil_err(struct wil6210_priv *wil, const char *fmt, ...) +void __wil_err(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { @@ -32,7 +32,7 @@ void wil_err(struct wil6210_priv *wil, const char *fmt, ...) va_end(args); } -void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) +void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) { if (net_ratelimit()) { struct net_device *ndev = wil_to_ndev(wil); @@ -49,7 +49,7 @@ void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) } } -void wil_info(struct wil6210_priv *wil, const char *fmt, ...) +void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 4d699ea46373..5dee909735bb 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -635,11 +635,11 @@ struct wil6210_priv { __printf(2, 3) void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); __printf(2, 3) -void wil_err(struct wil6210_priv *wil, const char *fmt, ...); +void __wil_err(struct wil6210_priv *wil, const char *fmt, ...); __printf(2, 3) -void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...); +void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...); __printf(2, 3) -void wil_info(struct wil6210_priv *wil, const char *fmt, ...); +void __wil_info(struct wil6210_priv *wil, const char *fmt, ...); #define wil_dbg(wil, fmt, arg...) do { \ netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ wil_dbg_trace(wil, fmt, ##arg); \ @@ -650,6 +650,10 @@ void wil_info(struct wil6210_priv *wil, const char *fmt, ...); #define wil_dbg_wmi(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg) #define wil_dbg_misc(wil, fmt, arg...) wil_dbg(wil, "DBG[MISC]" fmt, ##arg) #define wil_dbg_pm(wil, fmt, arg...) wil_dbg(wil, "DBG[ PM ]" fmt, ##arg) +#define wil_err(wil, fmt, arg...) __wil_err(wil, "%s: " fmt, __func__, ##arg) +#define wil_info(wil, fmt, arg...) __wil_info(wil, "%s: " fmt, __func__, ##arg) +#define wil_err_ratelimited(wil, fmt, arg...) \ + __wil_err_ratelimited(wil, "%s: " fmt, __func__, ##arg) /* target operations */ /* register read */ -- GitLab From 321a000bfadd5535089a198b42d714a8bf8469b7 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 26 Apr 2016 14:41:38 +0300 Subject: [PATCH 4478/9938] wil6210: support regular scan on P2P_DEVICE interface P2P search can only run on the social channel (channel 2). When issuing a scan request on the P2P_DEVICE interface, driver ignored the channels argument and always performed a P2P search. Fix this by checking the channels argument, if it is not specified (meaning full scan) or if a non-social channel was specified, perform a regular scan and not a P2P search. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 5 +++-- drivers/net/wireless/ath/wil6210/p2p.c | 6 ++++++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 0fb3a7941d84..5769811291bf 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -375,8 +375,9 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } - /* scan on P2P_DEVICE is handled as p2p search */ - if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { + /* social scan on P2P_DEVICE is handled as p2p search */ + if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE && + wil_p2p_is_social_scan(request)) { wil->scan_request = request; wil->radio_wdev = wdev; rc = wil_p2p_search(wil, request); diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index 2c1b8958180e..1c9153894dca 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -22,6 +22,12 @@ #define P2P_SEARCH_DURATION_MS 500 #define P2P_DEFAULT_BI 100 +bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request) +{ + return (request->n_channels == 1) && + (request->channels[0]->hw_value == P2P_DMG_SOCIAL_CHANNEL); +} + void wil_p2p_discovery_timer_fn(ulong x) { struct wil6210_priv *wil = (void *)x; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 5dee909735bb..b6fc256183f0 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -776,6 +776,7 @@ void wil_disable_irq(struct wil6210_priv *wil); void wil_enable_irq(struct wil6210_priv *wil); /* P2P */ +bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request); void wil_p2p_discovery_timer_fn(ulong x); int wil_p2p_search(struct wil6210_priv *wil, struct cfg80211_scan_request *request); -- GitLab From b523d35b5bffda70bf149cb6ae87c7eb1013dcdd Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 26 Apr 2016 14:41:39 +0300 Subject: [PATCH 4479/9938] wil6210: change RX_HTRSH interrupt print level to debug When using interrupt moderation RX_HTRSH interrupt can occur frequently during high throughput and should not be considered as error. Such print-outs can degrade the performance hence should be printed in debug print level. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/interrupt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index fe66b2b646f0..6897754f2722 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -228,11 +228,8 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) */ if (likely(isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH))) { - wil_dbg_irq(wil, "RX done\n"); - - if (unlikely(isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)) - wil_err_ratelimited(wil, - "Received \"Rx buffer is in risk of overflow\" interrupt\n"); + wil_dbg_irq(wil, "RX done / RX_HTRSH received, ISR (0x%x)\n", + isr); isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH); -- GitLab From d8ed043accdee611bce8be7c4224b4e26bdc2ab5 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 26 Apr 2016 14:41:39 +0300 Subject: [PATCH 4480/9938] wil6210: print debug message when transmitting while disconnected Network stack can try to transmit data while AP / STA is disconnected. Change this print-out to debug level as this should not be handled as error. This patch also adds wil_dbg_ratelimited, used to limit the above print-out. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debug.c | 16 ++++++++++++++++ drivers/net/wireless/ath/wil6210/txrx.c | 2 +- drivers/net/wireless/ath/wil6210/wil6210.h | 2 ++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c index 0a301277c06d..c312a667c12a 100644 --- a/drivers/net/wireless/ath/wil6210/debug.c +++ b/drivers/net/wireless/ath/wil6210/debug.c @@ -49,6 +49,22 @@ void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) } } +void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + if (!net_ratelimit()) + return; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + netdev_dbg(wil_to_ndev(wil), "%pV", &vaf); + trace_wil6210_log_dbg(&vaf); + va_end(args); +} + void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index f260b232fd57..a4e43796addb 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1759,7 +1759,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) goto drop; } if (unlikely(!test_bit(wil_status_fwconnected, wil->status))) { - wil_err_ratelimited(wil, "FW not connected\n"); + wil_dbg_ratelimited(wil, "FW not connected, packet dropped\n"); goto drop; } if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) { diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index b6fc256183f0..50acd136d967 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -640,6 +640,8 @@ __printf(2, 3) void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...); __printf(2, 3) void __wil_info(struct wil6210_priv *wil, const char *fmt, ...); +__printf(2, 3) +void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...); #define wil_dbg(wil, fmt, arg...) do { \ netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ wil_dbg_trace(wil, fmt, ##arg); \ -- GitLab From 54eaa8c69e72dca4c824cd390b616cb48b2c4e30 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 26 Apr 2016 14:41:40 +0300 Subject: [PATCH 4481/9938] wil6210: unmask RX_HTRSH interrupt only when connected RX_HTRSH interrupt sometimes triggered during device reset procedure. To prevent handling this interrupt when not required, unmask this interrupt only if we are connected and mask it when disconnected. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/interrupt.c | 6 +++++- drivers/net/wireless/ath/wil6210/main.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 6897754f2722..22592f338c1e 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -38,6 +38,8 @@ #define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) #define WIL6210_IMC_RX (BIT_DMA_EP_RX_ICR_RX_DONE | \ BIT_DMA_EP_RX_ICR_RX_HTRSH) +#define WIL6210_IMC_RX_NO_RX_HTRSH (WIL6210_IMC_RX & \ + (~(BIT_DMA_EP_RX_ICR_RX_HTRSH))) #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) #define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \ @@ -109,8 +111,10 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil) void wil6210_unmask_irq_rx(struct wil6210_priv *wil) { + bool unmask_rx_htrsh = test_bit(wil_status_fwconnected, wil->status); + wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC), - WIL6210_IMC_RX); + unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); } static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 8d4e8843004e..261bdabccc83 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -194,6 +194,18 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) memset(&sta->stats, 0, sizeof(sta->stats)); } +static bool wil_ap_is_connected(struct wil6210_priv *wil) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + if (wil->sta[i].status == wil_sta_connected) + return true; + } + + return false; +} + static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, u16 reason_code, bool from_event) { @@ -247,6 +259,11 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, } clear_bit(wil_status_fwconnecting, wil->status); break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + if (!wil_ap_is_connected(wil)) + clear_bit(wil_status_fwconnected, wil->status); + break; default: break; } -- GitLab From 349214c1e7d718684e19dc3559dffe4e62f55296 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Tue, 26 Apr 2016 14:41:41 +0300 Subject: [PATCH 4482/9938] wil6210: prevent deep sleep of 60G device in critical paths In idle times 60G device can enter deep sleep and turn off its XTAL clock. Host access triggers the device power-up flow which will hold the AHB during XTAL stabilization until device switches from slow-clock to XTAL clock. This behavior can stall the PCIe bus for some arbitrary period of time. In order to prevent this stall, host can vote for High Latency Access Policy (HALP) before reading from PCIe bus. This vote will wakeup the device from deep sleep and prevent deep sleep until unvote is done. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debugfs.c | 22 ++++-- drivers/net/wireless/ath/wil6210/interrupt.c | 80 ++++++++++++++++---- drivers/net/wireless/ath/wil6210/main.c | 75 +++++++++++++++++- drivers/net/wireless/ath/wil6210/wil6210.h | 29 ++++++- drivers/net/wireless/ath/wil6210/wmi.c | 20 +++-- 5 files changed, 194 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index b338a09175ad..5d8823da51fd 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -171,6 +171,8 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, int rsize; uint i; + wil_halp_vote(wil); + wil_memcpy_fromio_32(&r, off, sizeof(r)); wil_mbox_ring_le2cpus(&r); /* @@ -236,6 +238,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, } out: seq_puts(s, "}\n"); + wil_halp_unvote(wil); } static int wil_mbox_debugfs_show(struct seq_file *s, void *data) @@ -500,9 +503,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { enum { max_count = 4096 }; - struct debugfs_blob_wrapper *blob = file->private_data; + struct wil_blob_wrapper *wil_blob = file->private_data; loff_t pos = *ppos; - size_t available = blob->size; + size_t available = wil_blob->blob.size; void *buf; size_t ret; @@ -521,8 +524,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; - wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + - pos, count); + wil_memcpy_fromio_halp_vote(wil_blob->wil, buf, + (const volatile void __iomem *) + wil_blob->blob.data + pos, count); ret = copy_to_user(user_buf, buf, count); kfree(buf); @@ -545,9 +549,9 @@ static struct dentry *wil_debugfs_create_ioblob(const char *name, umode_t mode, struct dentry *parent, - struct debugfs_blob_wrapper *blob) + struct wil_blob_wrapper *wil_blob) { - return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); + return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob); } /*---reset---*/ @@ -1445,16 +1449,18 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, char name[32]; for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { - struct debugfs_blob_wrapper *blob = &wil->blobs[i]; + struct wil_blob_wrapper *wil_blob = &wil->blobs[i]; + struct debugfs_blob_wrapper *blob = &wil_blob->blob; const struct fw_map *map = &fw_mapping[i]; if (!map->name) continue; + wil_blob->wil = wil; blob->data = (void * __force)wil->csr + HOSTADDR(map->host); blob->size = map->to - map->from; snprintf(name, sizeof(name), "blob_%s", map->name); - wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob); + wil_debugfs_create_ioblob(name, S_IRUGO, dbg, wil_blob); } } diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 22592f338c1e..011e7412dcc0 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -35,17 +35,19 @@ * */ -#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) +#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) +#define WIL6210_IRQ_DISABLE_NO_HALP (0xF7FFFFFFUL) #define WIL6210_IMC_RX (BIT_DMA_EP_RX_ICR_RX_DONE | \ BIT_DMA_EP_RX_ICR_RX_HTRSH) #define WIL6210_IMC_RX_NO_RX_HTRSH (WIL6210_IMC_RX & \ (~(BIT_DMA_EP_RX_ICR_RX_HTRSH))) #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) -#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \ - ISR_MISC_MBOX_EVT | \ - ISR_MISC_FW_ERROR) - +#define WIL6210_IMC_MISC_NO_HALP (ISR_MISC_FW_READY | \ + ISR_MISC_MBOX_EVT | \ + ISR_MISC_FW_ERROR) +#define WIL6210_IMC_MISC (WIL6210_IMC_MISC_NO_HALP | \ + BIT_DMA_EP_MISC_ICR_HALP) #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ BIT_DMA_PSEUDO_CAUSE_TX | \ BIT_DMA_PSEUDO_CAUSE_MISC)) @@ -53,6 +55,7 @@ #if defined(CONFIG_WIL6210_ISR_COR) /* configure to Clear-On-Read mode */ #define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) +#define WIL_ICR_ICC_MISC_VALUE (0xF7FFFFFFUL) static inline void wil_icr_clear(u32 x, void __iomem *addr) { @@ -60,6 +63,7 @@ static inline void wil_icr_clear(u32 x, void __iomem *addr) #else /* defined(CONFIG_WIL6210_ISR_COR) */ /* configure to Write-1-to-Clear mode */ #define WIL_ICR_ICC_VALUE (0UL) +#define WIL_ICR_ICC_MISC_VALUE (0UL) static inline void wil_icr_clear(u32 x, void __iomem *addr) { @@ -88,10 +92,21 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil) WIL6210_IRQ_DISABLE); } -static void wil6210_mask_irq_misc(struct wil6210_priv *wil) +static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp) { + wil_dbg_irq(wil, "%s: mask_halp(%s)\n", __func__, + mask_halp ? "true" : "false"); + wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), - WIL6210_IRQ_DISABLE); + mask_halp ? WIL6210_IRQ_DISABLE : WIL6210_IRQ_DISABLE_NO_HALP); +} + +static void wil6210_mask_halp(struct wil6210_priv *wil) +{ + wil_dbg_irq(wil, "%s()\n", __func__); + + wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), + BIT_DMA_EP_MISC_ICR_HALP); } static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) @@ -117,10 +132,21 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil) unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); } -static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) +static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) { + wil_dbg_irq(wil, "%s: unmask_halp(%s)\n", __func__, + unmask_halp ? "true" : "false"); + wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), - WIL6210_IMC_MISC); + unmask_halp ? WIL6210_IMC_MISC : WIL6210_IMC_MISC_NO_HALP); +} + +static void wil6210_unmask_halp(struct wil6210_priv *wil) +{ + wil_dbg_irq(wil, "%s()\n", __func__); + + wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), + BIT_DMA_EP_MISC_ICR_HALP); } static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) @@ -138,7 +164,7 @@ void wil_mask_irq(struct wil6210_priv *wil) wil6210_mask_irq_tx(wil); wil6210_mask_irq_rx(wil); - wil6210_mask_irq_misc(wil); + wil6210_mask_irq_misc(wil, true); wil6210_mask_irq_pseudo(wil); } @@ -151,12 +177,12 @@ void wil_unmask_irq(struct wil6210_priv *wil) wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_VALUE); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC), - WIL_ICR_ICC_VALUE); + WIL_ICR_ICC_MISC_VALUE); wil6210_unmask_irq_pseudo(wil); wil6210_unmask_irq_tx(wil); wil6210_unmask_irq_rx(wil); - wil6210_unmask_irq_misc(wil); + wil6210_unmask_irq_misc(wil, true); } void wil_configure_interrupt_moderation(struct wil6210_priv *wil) @@ -345,7 +371,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) return IRQ_NONE; } - wil6210_mask_irq_misc(wil); + wil6210_mask_irq_misc(wil, false); if (isr & ISR_MISC_FW_ERROR) { u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); @@ -373,12 +399,19 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) isr &= ~ISR_MISC_FW_READY; } + if (isr & BIT_DMA_EP_MISC_ICR_HALP) { + wil_dbg_irq(wil, "%s: HALP IRQ invoked\n", __func__); + wil6210_mask_halp(wil); + isr &= ~BIT_DMA_EP_MISC_ICR_HALP; + complete(&wil->halp.comp); + } + wil->isr_misc = isr; if (isr) { return IRQ_WAKE_THREAD; } else { - wil6210_unmask_irq_misc(wil); + wil6210_unmask_irq_misc(wil, false); return IRQ_HANDLED; } } @@ -415,7 +448,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) wil->isr_misc = 0; - wil6210_unmask_irq_misc(wil); + wil6210_unmask_irq_misc(wil, false); return IRQ_HANDLED; } @@ -557,6 +590,23 @@ void wil6210_clear_irq(struct wil6210_priv *wil) wmb(); /* make sure write completed */ } +void wil6210_set_halp(struct wil6210_priv *wil) +{ + wil_dbg_misc(wil, "%s()\n", __func__); + + wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS), + BIT_DMA_EP_MISC_ICR_HALP); +} + +void wil6210_clear_halp(struct wil6210_priv *wil) +{ + wil_dbg_misc(wil, "%s()\n", __func__); + + wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR), + BIT_DMA_EP_MISC_ICR_HALP); + wil6210_unmask_halp(wil); +} + int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi) { int rc; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 261bdabccc83..f7ed65144742 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -23,6 +23,8 @@ #include "wmi.h" #include "boot_loader.h" +#define WAIT_FOR_HALP_VOTE_MS 100 + bool debug_fw; /* = false; */ module_param(debug_fw, bool, S_IRUGO); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); @@ -132,6 +134,14 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, *d++ = __raw_readl(s++); } +void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst, + const volatile void __iomem *src, size_t count) +{ + wil_halp_vote(wil); + wil_memcpy_fromio_32(dst, src, count); + wil_halp_unvote(wil); +} + void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count) { @@ -142,6 +152,15 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, __raw_writel(*s++, d++); } +void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil, + volatile void __iomem *dst, + const void *src, size_t count) +{ + wil_halp_vote(wil); + wil_memcpy_toio_32(dst, src, count); + wil_halp_unvote(wil); +} + static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, u16 reason_code, bool from_event) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) @@ -474,9 +493,11 @@ int wil_priv_init(struct wil6210_priv *wil) mutex_init(&wil->wmi_mutex); mutex_init(&wil->probe_client_mutex); mutex_init(&wil->p2p_wdev_mutex); + mutex_init(&wil->halp.lock); init_completion(&wil->wmi_ready); init_completion(&wil->wmi_call); + init_completion(&wil->halp.comp); wil->bcast_vring = -1; setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); @@ -572,11 +593,10 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable) { wil_info(wil, "%s: enable=%d\n", __func__, enable); - if (enable) { + if (enable) wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); - } else { + else wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); - } } static int wil_target_reset(struct wil6210_priv *wil) @@ -888,6 +908,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); + reinit_completion(&wil->halp.comp); if (load_fw) { wil_configure_interrupt_moderation(wil); @@ -1078,3 +1099,51 @@ int wil_find_cid(struct wil6210_priv *wil, const u8 *mac) return rc; } + +void wil_halp_vote(struct wil6210_priv *wil) +{ + unsigned long rc; + unsigned long to_jiffies = msecs_to_jiffies(WAIT_FOR_HALP_VOTE_MS); + + mutex_lock(&wil->halp.lock); + + wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); + + if (++wil->halp.ref_cnt == 1) { + wil6210_set_halp(wil); + rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); + if (!rc) + wil_err(wil, "%s: HALP vote timed out\n", __func__); + else + wil_dbg_misc(wil, + "%s: HALP vote completed after %d ms\n", + __func__, + jiffies_to_msecs(to_jiffies - rc)); + } + + wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); + + mutex_unlock(&wil->halp.lock); +} + +void wil_halp_unvote(struct wil6210_priv *wil) +{ + WARN_ON(wil->halp.ref_cnt == 0); + + mutex_lock(&wil->halp.lock); + + wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); + + if (--wil->halp.ref_cnt == 0) { + wil6210_clear_halp(wil); + wil_dbg_misc(wil, "%s: HALP unvote\n", __func__); + } + + wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); + + mutex_unlock(&wil->halp.lock); +} diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 50acd136d967..74bc2c5c1a44 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -168,6 +168,7 @@ struct RGF_ICR { #define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) + #define BIT_DMA_EP_MISC_ICR_HALP BIT(27) #define BIT_DMA_EP_MISC_ICR_FW_INT(n) BIT(28+n) /* n = [0..3] */ /* Legacy interrupt moderation control (before Sparrow v2)*/ @@ -534,6 +535,17 @@ struct pmc_ctx { int descriptor_size; }; +struct wil_halp { + struct mutex lock; /* protect halp ref_cnt */ + unsigned int ref_cnt; + struct completion comp; +}; + +struct wil_blob_wrapper { + struct wil6210_priv *wil; + struct debugfs_blob_wrapper blob; +}; + struct wil6210_priv { struct pci_dev *pdev; struct wireless_dev *wdev; @@ -606,7 +618,7 @@ struct wil6210_priv { atomic_t isr_count_rx, isr_count_tx; /* debugfs */ struct dentry *debug; - struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)]; + struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)]; u8 discovery_mode; void *platform_handle; @@ -622,6 +634,10 @@ struct wil6210_priv { struct wireless_dev *p2p_wdev; struct mutex p2p_wdev_mutex; /* protect @p2p_wdev */ struct wireless_dev *radio_wdev; + + /* High Access Latency Policy voting */ + struct wil_halp halp; + }; #define wil_to_wiphy(i) (i->wdev->wiphy) @@ -713,6 +729,12 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, size_t count); void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count); +void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst, + const volatile void __iomem *src, + size_t count); +void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil, + volatile void __iomem *dst, + const void *src, size_t count); void *wil_if_alloc(struct device *dev); void wil_if_free(struct wil6210_priv *wil); @@ -849,4 +871,9 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime); int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size); void wil_fw_core_dump(struct wil6210_priv *wil); +void wil_halp_vote(struct wil6210_priv *wil); +void wil_halp_unvote(struct wil6210_priv *wil); +void wil6210_set_halp(struct wil6210_priv *wil); +void wil6210_clear_halp(struct wil6210_priv *wil); + #endif /* __WIL6210_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 6ca28c3eff0a..2e347efc39d8 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -194,6 +194,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) void __iomem *dst; void __iomem *head = wmi_addr(wil, r->head); uint retry; + int rc = 0; if (sizeof(cmd) + len > r->entry_size) { wil_err(wil, "WMI size too large: %d bytes, max is %d\n", @@ -212,6 +213,9 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head); return -EINVAL; } + + wil_halp_vote(wil); + /* read Tx head till it is not busy */ for (retry = 5; retry > 0; retry--) { wil_memcpy_fromio_32(&d_head, head, sizeof(d_head)); @@ -221,7 +225,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) } if (d_head.sync != 0) { wil_err(wil, "WMI head busy\n"); - return -EBUSY; + rc = -EBUSY; + goto out; } /* next head */ next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); @@ -230,7 +235,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) for (retry = 5; retry > 0; retry--) { if (!test_bit(wil_status_fwready, wil->status)) { wil_err(wil, "WMI: cannot send command while FW not ready\n"); - return -EAGAIN; + rc = -EAGAIN; + goto out; } r->tail = wil_r(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, tx.tail)); @@ -240,13 +246,15 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) } if (next_head == r->tail) { wil_err(wil, "WMI ring full\n"); - return -EBUSY; + rc = -EBUSY; + goto out; } dst = wmi_buffer(wil, d_head.addr); if (!dst) { wil_err(wil, "invalid WMI buffer: 0x%08x\n", le32_to_cpu(d_head.addr)); - return -EINVAL; + rc = -EAGAIN; + goto out; } cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); /* set command */ @@ -269,7 +277,9 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS), SW_INT_MBOX); - return 0; +out: + wil_halp_unvote(wil); + return rc; } int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) -- GitLab From 92cd663e4cd02c10f321ec2cf3c417b29fe8b387 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:30:21 +0200 Subject: [PATCH 4483/9938] alpha: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: linux-alpha@vger.kernel.org Acked-by: Matt Turner Signed-off-by: Linus Walleij --- arch/alpha/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9d8a85801ed1..fe99f894e57d 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -13,7 +13,6 @@ config ALPHA select GENERIC_IRQ_PROBE select AUTO_IRQ_AFFINITY if SMP select GENERIC_IRQ_SHOW - select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_IPC_PARSE_VERSION select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE -- GitLab From e944b10ab03568e821145e38198197da2913af54 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:35:14 +0200 Subject: [PATCH 4484/9938] xtensa: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: Chris Zankel Cc: linux-xtensa@linux-xtensa.org Acked-by: Max Filippov Signed-off-by: Linus Walleij --- arch/xtensa/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index e832d3e9835e..85257afe71c3 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -5,7 +5,6 @@ config XTENSA def_bool y select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_IPC_PARSE_VERSION - select ARCH_WANT_OPTIONAL_GPIOLIB select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS select COMMON_CLK -- GitLab From e05f2e187814b7b102c0f54c9a72c01e6bdb5360 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 11:17:49 +0200 Subject: [PATCH 4485/9938] m68k: do away with ARCH_REQUIRE_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB" as this can now be selected directly. Cc: Michael Büsch Cc: Geert Uytterhoeven Cc: linux-m68k@lists.linux-m68k.org Acked-by: Greg Ungerer Signed-off-by: Linus Walleij --- arch/m68k/Kconfig.cpu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 0dfcf1281e9c..c1beb5ae181f 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -22,11 +22,11 @@ config M68KCLASSIC config COLDFIRE bool "Coldfire CPU family support" - select ARCH_REQUIRE_GPIOLIB select ARCH_HAVE_CUSTOM_GPIO_H select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 select GENERIC_CSUM + select GPIOLIB select HAVE_CLK endchoice -- GitLab From 2735e4c305be13b38680c5e2ddce131da2755ad5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:33:48 +0200 Subject: [PATCH 4486/9938] nios2: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: nios2-dev@lists.rocketboards.org Acked-by: Ley Foon Tan Signed-off-by: Linus Walleij --- arch/nios2/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index 437555424bda..87ca653eb5f3 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig @@ -1,6 +1,5 @@ config NIOS2 def_bool y - select ARCH_WANT_OPTIONAL_GPIOLIB select CLKSRC_OF select GENERIC_ATOMIC64 select GENERIC_CLOCKEVENTS -- GitLab From f518abf00d503dc2cc330d189229fed926c424d8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 11:13:38 +0200 Subject: [PATCH 4487/9938] cris: do away with ARCH_REQUIRE_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace "select ARCH_REQUIRE_GPIOLIB" with "select GPIOLIB" as this can now be selected directly. Cc: Michael Büsch Cc: Mikael Starvik Cc: linux-cris-kernel@axis.com Acked-by: Jesper Nilsson Signed-off-by: Linus Walleij --- arch/cris/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index e086f9e93728..99bda1ba3d2f 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -61,7 +61,7 @@ config CRIS select CLONE_BACKWARDS2 select OLD_SIGSUSPEND select OLD_SIGACTION - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select IRQ_DOMAIN if ETRAX_ARCH_V32 select OF if ETRAX_ARCH_V32 select OF_EARLY_FLATTREE if ETRAX_ARCH_V32 -- GitLab From 30d473d4db623a84b3e8d708d332934ed2537fd8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 13:34:34 +0200 Subject: [PATCH 4488/9938] sparc: remove ARCH_WANT_OPTIONAL_GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbols is not needed to get access to selecting the GPIOLIB anymore: any arch can select GPIOLIB. Cc: Michael Büsch Cc: sparclinux@vger.kernel.org Acked-by: David S. Miller Signed-off-by: Linus Walleij --- arch/sparc/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 57ffaf285c2f..6bd1b1c3f5cc 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -21,7 +21,6 @@ config SPARC select HAVE_ARCH_KGDB if !SMP || SPARC64 select HAVE_ARCH_TRACEHOOK select SYSCTL_EXCEPTION_TRACE - select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select RTC_CLASS select RTC_DRV_M48T59 -- GitLab From 59851aa87c2ca92a1fd6b73e78a254242306b116 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Apr 2016 10:45:14 +0200 Subject: [PATCH 4489/9938] arc: select GPIOLIB directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of indirectly selecting GPIOLIB via the ARCH_REQUIRE_GPIOLIB symbol, just select GPIOLIB. Cc: Michael Büsch Cc: linux-snps-arc@lists.infradead.org Acked-by: Vineet Gupta Signed-off-by: Linus Walleij --- arch/arc/plat-axs10x/Kconfig | 2 +- arch/arc/plat-tb10x/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig index 426ac4b8bb39..c54d1ae57fe0 100644 --- a/arch/arc/plat-axs10x/Kconfig +++ b/arch/arc/plat-axs10x/Kconfig @@ -13,7 +13,7 @@ menuconfig ARC_PLAT_AXS10X select OF_GPIO select MIGHT_HAVE_PCI select GENERIC_IRQ_CHIP - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB help Support for the ARC AXS10x Software Development Platforms. diff --git a/arch/arc/plat-tb10x/Kconfig b/arch/arc/plat-tb10x/Kconfig index d14b3d3c5dfd..149e0917645d 100644 --- a/arch/arc/plat-tb10x/Kconfig +++ b/arch/arc/plat-tb10x/Kconfig @@ -21,7 +21,7 @@ menuconfig ARC_PLAT_TB10X select PINCTRL select PINCTRL_TB10X select PINMUX - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select GPIO_TB10X select TB10X_IRQC help -- GitLab From 037ad463ba408d76d85f377d258d135062bab658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 26 Apr 2016 09:58:30 +0200 Subject: [PATCH 4490/9938] arm64: dts: marvell: clean up armada-7040-db MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of duplicating the node hierarchy, reference the nodes by label, adding labels where necessary. Drop some trailing or inconsistent white lines while at it. Cc: Thomas Petazzoni Signed-off-by: Andreas Färber [Thomas: drop Fixes tag as it is not a bug fix.] Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- .../arm64/boot/dts/marvell/armada-7040-db.dts | 52 +++++++++---------- .../boot/dts/marvell/armada-ap806-dual.dtsi | 1 - .../boot/dts/marvell/armada-ap806-quad.dtsi | 2 - arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 7 +-- 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts index 064a251346dd..ee5778395bea 100644 --- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts @@ -55,38 +55,34 @@ device_type = "memory"; reg = <0x0 0x0 0x0 0x80000000>; }; +}; - ap806 { - config-space { - spi@510600 { - status = "okay"; - - spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "n25q128a13"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <10000000>; +&i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; - partition@0 { - label = "U-Boot"; - reg = <0 0x200000>; - }; - partition@400000 { - label = "Filesystem"; - reg = <0x200000 0xce0000>; - }; - }; - }; +&spi0 { + status = "okay"; - i2c@511000 { - status = "okay"; - clock-frequency = <100000>; - }; + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <10000000>; - serial@512000 { - status = "okay"; - }; + partition@0 { + label = "U-Boot"; + reg = <0 0x200000>; + }; + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xce0000>; }; }; }; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi index f25c5c17fad7..95a1ff60f6c1 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi @@ -68,4 +68,3 @@ }; }; }; - diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi index baa7d9a516b3..ba43a4357b89 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi @@ -79,6 +79,4 @@ enable-method = "psci"; }; }; - }; - diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index 556a92bcc2f6..3ecf9b1798fa 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -59,7 +59,6 @@ method = "smc"; }; - ap806 { #address-cells = <2>; #size-cells = <2>; @@ -190,7 +189,7 @@ status = "disabled"; }; - serial@512000 { + uart0: serial@512000 { compatible = "snps,dw-apb-uart"; reg = <0x512000 0x100>; reg-shift = <2>; @@ -200,7 +199,7 @@ status = "disabled"; }; - serial@512100 { + uart1: serial@512100 { compatible = "snps,dw-apb-uart"; reg = <0x512100 0x100>; reg-shift = <2>; @@ -232,6 +231,4 @@ }; }; }; - }; - -- GitLab From 1093e5f6fc398eaab21bb9182806854fbde4edc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 26 Apr 2016 09:58:31 +0200 Subject: [PATCH 4491/9938] arm64: dts: marvell: rename armada-ap806 XOR nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Node names should not contain an instance number, the unit address serves to distinguish nodes of the same name. So rename the XOR nodes to just xor@
    . Cc: Thomas Petazzoni Signed-off-by: Andreas Färber [Thomas: - remove labels, they are really not needed for XOR engines. - remove the Fixes: tag, as this is not a fix.] Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index 3ecf9b1798fa..ca42c3648004 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -135,7 +135,7 @@ marvell,spi-base = <128>, <136>, <144>, <152>; }; - xor0@400000 { + xor@400000 { compatible = "marvell,mv-xor-v2"; reg = <0x400000 0x1000>, <0x410000 0x1000>; @@ -143,7 +143,7 @@ dma-coherent; }; - xor1@420000 { + xor@420000 { compatible = "marvell,mv-xor-v2"; reg = <0x420000 0x1000>, <0x430000 0x1000>; @@ -151,7 +151,7 @@ dma-coherent; }; - xor2@440000 { + xor@440000 { compatible = "marvell,mv-xor-v2"; reg = <0x440000 0x1000>, <0x450000 0x1000>; @@ -159,7 +159,7 @@ dma-coherent; }; - xor3@460000 { + xor@460000 { compatible = "marvell,mv-xor-v2"; reg = <0x460000 0x1000>, <0x470000 0x1000>; -- GitLab From bf151162162b21e27fd9e94776aac67f648c0c4c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:32 +0200 Subject: [PATCH 4492/9938] arm64: dts: marvell: add UART aliases and define stdout-path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds the necessary UART aliases to the main Armada 7K/8K .dtsi file, and uses them to define the /chosen/stdout-path property on the Armada 7040 DB board. Suggested-by: Andreas Färber Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- arch/arm64/boot/dts/marvell/armada-7040-db.dts | 4 ++++ arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts index ee5778395bea..4b01744038b3 100644 --- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts @@ -51,6 +51,10 @@ compatible = "marvell,armada7040-db", "marvell,armada7040", "marvell,armada-ap806-quad", "marvell,armada-ap806"; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory@00000000 { device_type = "memory"; reg = <0x0 0x0 0x0 0x80000000>; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index ca42c3648004..9e2c1f9e78bc 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -54,6 +54,11 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + psci { compatible = "arm,psci-0.2"; method = "smc"; -- GitLab From bb233a9319ea1999d637a9c7e6c3c4a578a1fc94 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:33 +0200 Subject: [PATCH 4493/9938] arm64: dts: marvell: use new clock binding on Armada AP806 This commit updates the Marvell AP806 Device Tree description to make use of the accepted clock Device Tree binding. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index 9e2c1f9e78bc..38be1928f550 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -179,7 +179,7 @@ #size-cells = <0>; cell-index = <0>; interrupts = ; - clocks = <&ringclk 2>; + clocks = <&ap_syscon 3>; status = "disabled"; }; @@ -190,7 +190,7 @@ #size-cells = <0>; interrupts = ; timeout-ms = <1000>; - clocks = <&ringclk 2>; + clocks = <&ap_syscon 3>; status = "disabled"; }; @@ -200,7 +200,7 @@ reg-shift = <2>; interrupts = ; reg-io-width = <1>; - clocks = <&ringclk 2>; + clocks = <&ap_syscon 3>; status = "disabled"; }; @@ -210,29 +210,19 @@ reg-shift = <2>; interrupts = ; reg-io-width = <1>; - clocks = <&ringclk 2>; + clocks = <&ap_syscon 3>; status = "disabled"; }; - dfx-server@6f8000 { - compatible = "simple-mfd", "syscon"; - reg = <0x6f8000 0x70000>; - - coreclk: clk@204 { - compatible = "marvell,armada-ap806-core-clock"; - #clock-cells = <1>; - clock-output-names = "ddr", "ring", "cpu"; - }; - - ringclk: clk@250 { - compatible = "marvell,armada-ap806-ring-clock"; - #clock-cells = <1>; - clock-output-names = "ring-0", "ring-2", - "ring-3", "ring-4", - "ring-5"; - clocks = <&coreclk 1>; - }; + ap_syscon: system-controller@6f4000 { + compatible = "marvell,ap806-system-controller", + "syscon"; + #clock-cells = <1>; + clock-output-names = "ap-cpu-cluster-0", + "ap-cpu-cluster-1", + "ap-fixed", "ap-mss"; + reg = <0x6f4000 0x1000>; }; }; }; -- GitLab From fe85e20e970041e9540820964926dc01a0a0f7f2 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:34 +0200 Subject: [PATCH 4494/9938] arm64: dts: marvell: improve SPI flash description on Armada 7040-DB This commit slightly improves the description of the SPI flash connected to the SPI controller of the Armada 7040, by: - Using the more generic "jedec,spi-nor" compatible string, which lets the driver auto-detect the exact SPI flash type. - Removing the silly comment about the Chip Select, since reg = <0> is explicit enough. - Switching to the new Device Tree binding to describe flash partitions. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- .../arm64/boot/dts/marvell/armada-7040-db.dts | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts index 4b01744038b3..95dd7c74f7ed 100644 --- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts @@ -72,17 +72,23 @@ spi-flash@0 { #address-cells = <1>; #size-cells = <1>; - compatible = "n25q128a13"; - reg = <0>; /* Chip select 0 */ + compatible = "jedec,spi-nor"; + reg = <0>; spi-max-frequency = <10000000>; - partition@0 { - label = "U-Boot"; - reg = <0 0x200000>; - }; - partition@400000 { - label = "Filesystem"; - reg = <0x200000 0xce0000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0 0x200000>; + }; + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xce0000>; + }; }; }; }; -- GitLab From d8b330a3e3135ed4cbc23c672deb7c978a686375 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:35 +0200 Subject: [PATCH 4495/9938] arm64: dts: marvell: use the proper I2C controller compatible string for 7K/8K The I2C controller found in the Marvell Armada 7K/8K provides the bridge/offloading features, so the Device Tree should use the marvell,mv78230-i2c compatible string instead of marvell,mv64xxx-i2c. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index 38be1928f550..20d256b32670 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -184,7 +184,7 @@ }; i2c0: i2c@511000 { - compatible = "marvell,mv64xxx-i2c"; + compatible = "marvell,mv78230-i2c"; reg = <0x511000 0x20>; #address-cells = <1>; #size-cells = <0>; -- GitLab From 728dacc7f4dd5d99b2a7e127b969165f54b6eece Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:36 +0200 Subject: [PATCH 4496/9938] arm64: dts: marvell: initial DT description of Armada 7K/8K CP110 master This commit adds an initial Device Tree description for the CP110 master that is found in the Armada 7K and 8K SoCs. This initial description describes: - the system controller (to provide clocks) - three PCIe interfaces - the SATA interface - the I2C controllers - the SPI controllers For the record, the organization of the SoCs is as follows: - 7020: dual-core AP, one CP110 (master) - 7040: quad-core AP, one CP110 (master) - 8020: dual-core AP, two CP110s (master and slave) - 8040: quad-core AP, two CP110s (master and slave) For this reason, all of the 7020, 7040, 8020 and 8040 include armada-cp110-master.dtsi. When support for the second CP110 (slave) used in 8020 and 8040 will be added, the .dtsi files for those SoCs will in addition include armada-cp110-slave.dtsi. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- arch/arm64/boot/dts/marvell/armada-7020.dtsi | 1 + arch/arm64/boot/dts/marvell/armada-7040.dtsi | 1 + arch/arm64/boot/dts/marvell/armada-8020.dtsi | 1 + arch/arm64/boot/dts/marvell/armada-8040.dtsi | 1 + .../boot/dts/marvell/armada-cp110-master.dtsi | 228 ++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi diff --git a/arch/arm64/boot/dts/marvell/armada-7020.dtsi b/arch/arm64/boot/dts/marvell/armada-7020.dtsi index 52575756d0be..975e73302753 100644 --- a/arch/arm64/boot/dts/marvell/armada-7020.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-7020.dtsi @@ -46,6 +46,7 @@ */ #include "armada-ap806-dual.dtsi" +#include "armada-cp110-master.dtsi" / { model = "Marvell Armada 7020"; diff --git a/arch/arm64/boot/dts/marvell/armada-7040.dtsi b/arch/arm64/boot/dts/marvell/armada-7040.dtsi index 7a2de8bf7907..78d995d62707 100644 --- a/arch/arm64/boot/dts/marvell/armada-7040.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-7040.dtsi @@ -46,6 +46,7 @@ */ #include "armada-ap806-quad.dtsi" +#include "armada-cp110-master.dtsi" / { model = "Marvell Armada 7040"; diff --git a/arch/arm64/boot/dts/marvell/armada-8020.dtsi b/arch/arm64/boot/dts/marvell/armada-8020.dtsi index 73d69d99513f..3753c1c6d54d 100644 --- a/arch/arm64/boot/dts/marvell/armada-8020.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-8020.dtsi @@ -46,6 +46,7 @@ */ #include "armada-ap806-dual.dtsi" +#include "armada-cp110-master.dtsi" / { model = "Marvell Armada 8020"; diff --git a/arch/arm64/boot/dts/marvell/armada-8040.dtsi b/arch/arm64/boot/dts/marvell/armada-8040.dtsi index a1406a40959e..8bd0d8f8ad4c 100644 --- a/arch/arm64/boot/dts/marvell/armada-8040.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-8040.dtsi @@ -46,6 +46,7 @@ */ #include "armada-ap806-quad.dtsi" +#include "armada-cp110-master.dtsi" / { model = "Marvell Armada 8040"; diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi new file mode 100644 index 000000000000..367138bae3e0 --- /dev/null +++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Device Tree file for Marvell Armada CP110 Master. + */ + +/ { + cp110-master { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + config-space { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges = <0x0 0x0 0xf2000000 0x2000000>; + + cpm_syscon0: system-controller@440000 { + compatible = "marvell,cp110-system-controller0", + "syscon"; + reg = <0x440000 0x1000>; + #clock-cells = <2>; + core-clock-output-names = + "cpm-apll", "cpm-ppv2-core", "cpm-eip", + "cpm-core", "cpm-nand-core"; + gate-clock-output-names = + "cpm-audio", "cpm-communit", "cpm-nand", + "cpm-ppv2", "cpm-sdio", "cpm-mg-domain", + "cpm-mg-core", "cpm-xor1", "cpm-xor0", + "cpm-gop-dp", "none", "cpm-pcie_x10", + "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", + "cpm-sata", "cpm-sata-usb", "cpm-main", + "cpm-sd-mmc", "none", "none", + "cpm-slow-io", "cpm-usb3h0", "cpm-usb3h1", + "cpm-usb3dev", "cpm-eip150", "cpm-eip197"; + }; + + cpm_sata0: sata@540000 { + compatible = "marvell,armada-8k-ahci"; + reg = <0x540000 0x30000>; + interrupts = ; + clocks = <&cpm_syscon0 1 15>; + status = "disabled"; + }; + + cpm_usb3_0: usb3@500000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x500000 0x4000>; + dma-coherent; + interrupts = ; + clocks = <&cpm_syscon0 1 22>; + status = "disabled"; + }; + + cpm_usb3_1: usb3@510000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x510000 0x4000>; + dma-coherent; + interrupts = ; + clocks = <&cpm_syscon0 1 23>; + status = "disabled"; + }; + + cpm_spi0: spi@700600 { + compatible = "marvell,armada-380-spi"; + reg = <0x700600 0x50>; + #address-cells = <0x1>; + #size-cells = <0x0>; + cell-index = <1>; + clocks = <&cpm_syscon0 0 3>; + status = "disabled"; + }; + + cpm_spi1: spi@700680 { + compatible = "marvell,armada-380-spi"; + reg = <0x700680 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <2>; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + + cpm_i2c0: i2c@701000 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + + cpm_i2c1: i2c@701100 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + }; + + cpm_pcie0: pcie@f2600000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2600000 0 0x10000>, + <0 0xf6f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9000000 0 0xf9000000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; + num-lanes = <1>; + clocks = <&cpm_syscon0 1 13>; + status = "disabled"; + }; + + cpm_pcie1: pcie@f2620000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2620000 0 0x10000>, + <0 0xf7f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9010000 0 0xf9010000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf7000000 0 0xf7000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; + + num-lanes = <1>; + clocks = <&cpm_syscon0 1 11>; + status = "disabled"; + }; + + cpm_pcie2: pcie@f2640000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2640000 0 0x10000>, + <0 0xf8f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9020000 0 0xf9020000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf8000000 0 0xf8000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; + + num-lanes = <1>; + clocks = <&cpm_syscon0 1 12>; + status = "disabled"; + }; + }; +}; -- GitLab From fea144987932dbc88b3051c6d258ffdcace7f1fa Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:37 +0200 Subject: [PATCH 4497/9938] arm64: dts: marvell: enable several CP interfaces on Armada 7040-DB This commit enables several interfaces of the CP side of the Armada 7040 for the Armada 7040 DB board: - one PCIe interface - one SPI controller with an attached SPI flash - one I2C controller - one SATA controller - two USB3 controllers Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- .../arm64/boot/dts/marvell/armada-7040-db.dts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts index 95dd7c74f7ed..070b589680c5 100644 --- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts @@ -96,3 +96,53 @@ &uart0 { status = "okay"; }; + + +&cpm_pcie2 { + status = "okay"; +}; + +&cpm_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&cpm_spi1 { + status = "okay"; + + spi-flash@0 { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <20000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x200000>; + }; + + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xe00000>; + }; + }; + }; +}; + +&cpm_sata0 { + status = "okay"; +}; + +&cpm_usb3_0 { + status = "okay"; +}; + +&cpm_usb3_1 { + status = "okay"; +}; -- GitLab From ad87c0f6692ecfe975b9c4f53bde9b24aa0b5173 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:29 +0200 Subject: [PATCH 4498/9938] arm64: marvell: enable AP806 and CP110 syscon driver The Marvell Armada 7K/8K support needs the AP806 and CP110 syscon drivers to be enabled, as they provide amongst other things, the main clocks for those platforms. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- arch/arm64/Kconfig.platforms | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index efa77c146415..60f4bb55fec9 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -64,8 +64,8 @@ config ARCH_MESON config ARCH_MVEBU bool "Marvell EBU SoC Family" - select ARMADA_AP806_CORE_CLK - select ARMADA_AP806_RING_CLK + select ARMADA_AP806_SYSCON + select ARMADA_CP110_SYSCON select MVEBU_ODMI help This enables support for Marvell EBU familly, including: -- GitLab From 1f664ab7d9d46abdcde294e3e6e9d5d98a2e6f73 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 09:58:39 +0200 Subject: [PATCH 4499/9938] MAINTAINERS: update entry for Marvell ARM platform maintainers The Marvell platform support is no longer limited to Armada 370, 375, 38x and XP, but now also includes the 32-bits Armada 39x and the 64-bits Armada 3700 and 7K/8K. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..d03f276cd841 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1310,7 +1310,7 @@ ARM/MAGICIAN MACHINE SUPPORT M: Philipp Zabel S: Maintained -ARM/Marvell Kirkwood and Armada 370, 375, 38x, XP SOC support +ARM/Marvell Kirkwood and Armada 370, 375, 38x, 39x, XP, 3700, 7K/8K SOC support M: Jason Cooper M: Andrew Lunn M: Gregory Clement -- GitLab From d3baee37f1488b0dea726597bb12a0086b233f8b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 16:29:50 +0100 Subject: [PATCH 4500/9938] input: adp5588-keys: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Michael Hennerich Acked-by: Michael Hennerich Acked-by: Dmitry Torokhov Signed-off-by: Linus Walleij --- drivers/input/keyboard/adp5588-keys.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 21a62d0fa764..53fe9a3fb620 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -73,7 +73,7 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val) #ifdef CONFIG_GPIOLIB static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); int val; @@ -93,7 +93,7 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) static void adp5588_gpio_set_value(struct gpio_chip *chip, unsigned off, int val) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); @@ -112,7 +112,7 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip, static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); int ret; @@ -130,7 +130,7 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) static int adp5588_gpio_direction_output(struct gpio_chip *chip, unsigned off, int val) { - struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc); + struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); int ret; @@ -210,7 +210,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad) mutex_init(&kpad->gpio_lock); - error = gpiochip_add(&kpad->gc); + error = gpiochip_add_data(&kpad->gc, kpad); if (error) { dev_err(dev, "gpiochip_add failed, err: %d\n", error); return error; -- GitLab From 3769a895b4a61b66085f97f8124df4833ee6e577 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 22:54:20 +0100 Subject: [PATCH 4501/9938] platform: x86: intel-pmic: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Feng Tang Signed-off-by: Linus Walleij --- drivers/platform/x86/intel_pmic_gpio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c index 0e73fd10ba72..63b371d6ee55 100644 --- a/drivers/platform/x86/intel_pmic_gpio.c +++ b/drivers/platform/x86/intel_pmic_gpio.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -174,7 +174,7 @@ static int pmic_irq_type(struct irq_data *data, unsigned type) static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip); + struct pmic_gpio *pg = gpiochip_get_data(chip); return pg->irq_base + offset; } @@ -279,7 +279,7 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) mutex_init(&pg->buslock); pg->chip.parent = dev; - retval = gpiochip_add(&pg->chip); + retval = gpiochip_add_data(&pg->chip, pg); if (retval) { pr_err("Can not add pmic gpio chip\n"); goto err; -- GitLab From 2d4443be10a70100cfdc1abcf1475a86bc62534b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:00:46 +0100 Subject: [PATCH 4502/9938] ssb: gpio_driver: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Hauke Mehrtens Cc: Michael Buesch Signed-off-by: Linus Walleij --- drivers/ssb/driver_gpio.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c index f92e266d48f8..180e027b1c8a 100644 --- a/drivers/ssb/driver_gpio.c +++ b/drivers/ssb/driver_gpio.c @@ -8,7 +8,7 @@ * Licensed under the GNU/GPL. See COPYING for details. */ -#include +#include #include #include #include @@ -22,15 +22,10 @@ * Shared **************************************************/ -static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) -{ - return container_of(chip, struct ssb_bus, gpio); -} - #if IS_ENABLED(CONFIG_SSB_EMBEDDED) static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); if (bus->bustype == SSB_BUSTYPE_SSB) return irq_find_mapping(bus->irq_domain, gpio); @@ -45,7 +40,7 @@ static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio); } @@ -53,7 +48,7 @@ static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); } @@ -61,7 +56,7 @@ static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0); return 0; @@ -70,7 +65,7 @@ static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio); ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); @@ -79,7 +74,7 @@ static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0); /* clear pulldown */ @@ -92,7 +87,7 @@ static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); /* clear pullup */ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); @@ -246,7 +241,7 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus) if (err) return err; - err = gpiochip_add(chip); + err = gpiochip_add_data(chip, bus); if (err) { ssb_gpio_irq_chipco_domain_exit(bus); return err; @@ -263,7 +258,7 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus) static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio); } @@ -271,7 +266,7 @@ static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); } @@ -279,7 +274,7 @@ static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, unsigned gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0); return 0; @@ -288,7 +283,7 @@ static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio); ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); @@ -439,7 +434,7 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus) if (err) return err; - err = gpiochip_add(chip); + err = gpiochip_add_data(chip, bus); if (err) { ssb_gpio_irq_extif_domain_exit(bus); return err; -- GitLab From cbc3f10f9ead9c9f664a9dc6697c31312e36d50e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:06:50 +0100 Subject: [PATCH 4503/9938] staging: vme: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Manohar Vanga Cc: devel@driverdev.osuosl.org Acked-by: Martyn Welch Acked-by: Greg Kroah-Hartman Signed-off-by: Linus Walleij --- drivers/staging/vme/devices/vme_pio2_gpio.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c index df992c3cb5ce..6d361201d98c 100644 --- a/drivers/staging/vme/devices/vme_pio2_gpio.c +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -25,16 +25,11 @@ static const char driver_name[] = "pio2_gpio"; -static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip) -{ - return container_of(chip, struct pio2_card, gc); -} - static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset) { u8 reg; int retval; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -71,7 +66,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, { u8 reg; int retval; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -100,7 +95,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) { int data; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -119,7 +114,7 @@ static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) { int data; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -205,7 +200,7 @@ int pio2_gpio_init(struct pio2_card *card) card->gc.set = pio2_gpio_set; /* This function adds a memory mapped GPIO chip */ - retval = gpiochip_add(&card->gc); + retval = gpiochip_add_data(&card->gc, card); if (retval) { dev_err(&card->vdev->dev, "Unable to register GPIO\n"); kfree(card->gc.label); -- GitLab From a00d60a0a2896bced073810fc86ea0764ac54939 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:11:05 +0100 Subject: [PATCH 4504/9938] serial: max310x: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Jiri Slaby Acked-by: Greg Kroah-Hartman Signed-off-by: Linus Walleij --- drivers/tty/serial/max310x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 3f98165b479c..3f6e0ab725fe 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1036,7 +1036,7 @@ static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) { unsigned int val; - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; val = max310x_port_read(port, MAX310X_GPIODATA_REG); @@ -1046,7 +1046,7 @@ static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4), @@ -1055,7 +1055,7 @@ static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; max310x_port_update(port, MAX310X_GPIOCFG_REG, 1 << (offset % 4), 0); @@ -1066,7 +1066,7 @@ static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int max310x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct max310x_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[offset / 4].port; max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4), @@ -1183,7 +1183,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, s->gpio.base = -1; s->gpio.ngpio = devtype->nr * 4; s->gpio.can_sleep = 1; - ret = gpiochip_add(&s->gpio); + ret = gpiochip_add_data(&s->gpio, s); if (ret) goto out_uart; #endif -- GitLab From dee07cea5452a5d50c6273f7a0d3c1aaa7ce9508 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:15:53 +0100 Subject: [PATCH 4505/9938] serial: sc16is7xx: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Jiri Slaby Acked-by: Greg Kroah-Hartman Signed-off-by: Linus Walleij --- drivers/tty/serial/sc16is7xx.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 025a4264430e..e6393619405a 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1104,8 +1104,7 @@ static const struct uart_ops sc16is7xx_ops = { static int sc16is7xx_gpio_get(struct gpio_chip *chip, unsigned offset) { unsigned int val; - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; val = sc16is7xx_port_read(port, SC16IS7XX_IOSTATE_REG); @@ -1115,8 +1114,7 @@ static int sc16is7xx_gpio_get(struct gpio_chip *chip, unsigned offset) static void sc16is7xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset), @@ -1126,8 +1124,7 @@ static void sc16is7xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) static int sc16is7xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset), 0); @@ -1138,8 +1135,7 @@ static int sc16is7xx_gpio_direction_input(struct gpio_chip *chip, static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int val) { - struct sc16is7xx_port *s = container_of(chip, struct sc16is7xx_port, - gpio); + struct sc16is7xx_port *s = gpiochip_get_data(chip); struct uart_port *port = &s->p[0].port; sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset), @@ -1210,7 +1206,7 @@ static int sc16is7xx_probe(struct device *dev, s->gpio.base = -1; s->gpio.ngpio = devtype->nr_gpio; s->gpio.can_sleep = 1; - ret = gpiochip_add(&s->gpio); + ret = gpiochip_add_data(&s->gpio, s); if (ret) goto out_thread; } -- GitLab From 14900363454b8244b41f77f42013a22db20bb2e2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:27:09 +0100 Subject: [PATCH 4506/9938] ASoC: rt5677: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Bard Liao Cc: Oder Chiou Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Mark Brown Signed-off-by: Linus Walleij --- sound/soc/codecs/rt5677.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 33e290b703df..60212266d5d1 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4520,14 +4520,9 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, } #ifdef CONFIG_GPIOLIB -static inline struct rt5677_priv *gpio_to_rt5677(struct gpio_chip *chip) -{ - return container_of(chip, struct rt5677_priv, gpio_chip); -} - static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); switch (offset) { case RT5677_GPIO1 ... RT5677_GPIO5: @@ -4548,7 +4543,7 @@ static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int rt5677_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); switch (offset) { case RT5677_GPIO1 ... RT5677_GPIO5: @@ -4572,7 +4567,7 @@ static int rt5677_gpio_direction_out(struct gpio_chip *chip, static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); int value, ret; ret = regmap_read(rt5677->regmap, RT5677_GPIO_ST, &value); @@ -4584,7 +4579,7 @@ static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset) static int rt5677_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); switch (offset) { case RT5677_GPIO1 ... RT5677_GPIO5: @@ -4638,7 +4633,7 @@ static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset, static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) { - struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); + struct rt5677_priv *rt5677 = gpiochip_get_data(chip); struct regmap_irq_chip_data *data = rt5677->irq_data; int irq; @@ -4697,7 +4692,7 @@ static void rt5677_init_gpio(struct i2c_client *i2c) rt5677->gpio_chip.parent = &i2c->dev; rt5677->gpio_chip.base = -1; - ret = gpiochip_add(&rt5677->gpio_chip); + ret = gpiochip_add_data(&rt5677->gpio_chip, rt5677); if (ret != 0) dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret); } -- GitLab From db1d127053c4c525086673e39691d274668a458d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:31:28 +0100 Subject: [PATCH 4507/9938] ASoC: wm5100: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij --- sound/soc/codecs/wm5100.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 171a23ddd15d..512a9d25fe6f 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -2236,14 +2237,9 @@ static irqreturn_t wm5100_edge_irq(int irq, void *data) } #ifdef CONFIG_GPIOLIB -static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip) -{ - return container_of(chip, struct wm5100_priv, gpio_chip); -} - static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT); @@ -2252,7 +2248,7 @@ static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int wm5100_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); int val, ret; val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT); @@ -2268,7 +2264,7 @@ static int wm5100_gpio_direction_out(struct gpio_chip *chip, static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); unsigned int reg; int ret; @@ -2281,7 +2277,7 @@ static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset) static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); + struct wm5100_priv *wm5100 = gpiochip_get_data(chip); return regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, WM5100_GP1_FN_MASK | WM5100_GP1_DIR, @@ -2313,7 +2309,7 @@ static void wm5100_init_gpio(struct i2c_client *i2c) else wm5100->gpio_chip.base = -1; - ret = gpiochip_add(&wm5100->gpio_chip); + ret = gpiochip_add_data(&wm5100->gpio_chip, wm5100); if (ret != 0) dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret); } -- GitLab From 8f4160661fd251e651f24f61b7ba4c36898e2621 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:38:20 +0100 Subject: [PATCH 4508/9938] ASoC: wm8903: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij --- sound/soc/codecs/wm8903.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index a82b8bc2cfc0..a26ca490cf31 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -1766,11 +1766,6 @@ static int wm8903_resume(struct snd_soc_codec *codec) } #ifdef CONFIG_GPIOLIB -static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8903_priv, gpio_chip); -} - static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) { if (offset >= WM8903_NUM_GPIO) @@ -1781,7 +1776,7 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int mask, val; int ret; @@ -1799,7 +1794,7 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int reg; regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, ®); @@ -1810,7 +1805,7 @@ static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) static int wm8903_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); unsigned int mask, val; int ret; @@ -1828,7 +1823,7 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); + struct wm8903_priv *wm8903 = gpiochip_get_data(chip); regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, WM8903_GP1_LVL_MASK, @@ -1860,7 +1855,7 @@ static void wm8903_init_gpio(struct wm8903_priv *wm8903) else wm8903->gpio_chip.base = -1; - ret = gpiochip_add(&wm8903->gpio_chip); + ret = gpiochip_add_data(&wm8903->gpio_chip, wm8903); if (ret != 0) dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret); } -- GitLab From f42b6f5800b6d06442c193d4beb423b0186e7b6a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:41:55 +0100 Subject: [PATCH 4509/9938] ASoC: wm8962: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij --- sound/soc/codecs/wm8962.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 88223608a33f..7976df02d090 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -3307,14 +3307,9 @@ static void wm8962_set_gpio_mode(struct wm8962_priv *wm8962, int gpio) } #ifdef CONFIG_GPIOLIB -static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8962_priv, gpio_chip); -} - static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset) { - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); + struct wm8962_priv *wm8962 = gpiochip_get_data(chip); /* The WM8962 GPIOs aren't linearly numbered. For simplicity * we export linear numbers and error out if the unsupported @@ -3337,7 +3332,7 @@ static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset) static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); + struct wm8962_priv *wm8962 = gpiochip_get_data(chip); struct snd_soc_codec *codec = wm8962->codec; snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, @@ -3347,7 +3342,7 @@ static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int wm8962_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); + struct wm8962_priv *wm8962 = gpiochip_get_data(chip); struct snd_soc_codec *codec = wm8962->codec; int ret, val; @@ -3386,7 +3381,7 @@ static void wm8962_init_gpio(struct snd_soc_codec *codec) else wm8962->gpio_chip.base = -1; - ret = gpiochip_add(&wm8962->gpio_chip); + ret = gpiochip_add_data(&wm8962->gpio_chip, wm8962); if (ret != 0) dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); } -- GitLab From c2aea142af6179d757424a21110da3fc90127e02 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:44:39 +0100 Subject: [PATCH 4510/9938] ASoC: wm8996: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Charles Keepax Acked-by: Mark Brown Signed-off-by: Linus Walleij --- sound/soc/codecs/wm8996.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index f99b34f7647b..a73044251218 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -2139,14 +2140,9 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, } #ifdef CONFIG_GPIOLIB -static inline struct wm8996_priv *gpio_to_wm8996(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8996_priv, gpio_chip); -} - static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset, WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT); @@ -2155,7 +2151,7 @@ static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int wm8996_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); int val; val = (1 << WM8996_GP1_FN_SHIFT) | (!!value << WM8996_GP1_LVL_SHIFT); @@ -2167,7 +2163,7 @@ static int wm8996_gpio_direction_out(struct gpio_chip *chip, static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); unsigned int reg; int ret; @@ -2180,7 +2176,7 @@ static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset) static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); + struct wm8996_priv *wm8996 = gpiochip_get_data(chip); return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset, WM8996_GP1_FN_MASK | WM8996_GP1_DIR, @@ -2211,7 +2207,7 @@ static void wm8996_init_gpio(struct wm8996_priv *wm8996) else wm8996->gpio_chip.base = -1; - ret = gpiochip_add(&wm8996->gpio_chip); + ret = gpiochip_add_data(&wm8996->gpio_chip, wm8996); if (ret != 0) dev_err(wm8996->dev, "Failed to add GPIOs: %d\n", ret); } -- GitLab From f7cb5120c4e0de10c3e069f5318417da0326fb45 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Dec 2015 23:48:29 +0100 Subject: [PATCH 4511/9938] ASoC: ac97: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Liam Girdwood Cc: alsa-devel@alsa-project.org Acked-by: Mark Brown Signed-off-by: Linus Walleij --- sound/soc/soc-ac97.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index 7e0acd83b0e6..bc4a55bb3fd9 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -59,8 +59,7 @@ static void soc_ac97_device_release(struct device *dev) #ifdef CONFIG_GPIOLIB static inline struct snd_soc_codec *gpio_to_codec(struct gpio_chip *chip) { - struct snd_ac97_gpio_priv *gpio_priv = - container_of(chip, struct snd_ac97_gpio_priv, gpio_chip); + struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip); return gpio_priv->codec; } @@ -98,8 +97,7 @@ static int snd_soc_ac97_gpio_get(struct gpio_chip *chip, unsigned offset) static void snd_soc_ac97_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct snd_ac97_gpio_priv *gpio_priv = - container_of(chip, struct snd_ac97_gpio_priv, gpio_chip); + struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip); struct snd_soc_codec *codec = gpio_to_codec(chip); gpio_priv->gpios_set &= ~(1 << offset); @@ -145,7 +143,7 @@ static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97, gpio_priv->gpio_chip.parent = codec->dev; gpio_priv->gpio_chip.base = -1; - ret = gpiochip_add(&gpio_priv->gpio_chip); + ret = gpiochip_add_data(&gpio_priv->gpio_chip, gpio_priv); if (ret != 0) dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); return ret; -- GitLab From 6a1f5471144754f165427a93f35c897f85680594 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 12 Apr 2016 16:09:11 +0200 Subject: [PATCH 4512/9938] arm64: acpi: add acpi=on cmdline option to prefer ACPI boot over DT If both ACPI and DT platform descriptions are available, and the kernel was configured at build time to support both flavours, the default policy is to prefer DT over ACPI, and preferring ACPI over DT while still allowing DT as a fallback is not possible. Since some enterprise features (such as RAS) depend on ACPI, it may be desirable for, e.g., distro installers to prefer ACPI boot but fall back to DT rather than failing completely if no ACPI tables are available. So introduce the 'acpi=on' kernel command line parameter for arm64, which signifies that ACPI should be used if available, and DT should only be used as a fallback. Acked-by: Catalin Marinas Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon --- Documentation/kernel-parameters.txt | 6 ++++-- arch/arm64/kernel/acpi.c | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ecc74fa4bfde..748129c85f35 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -167,16 +167,18 @@ bytes respectively. Such letter suffixes can also be entirely omitted. acpi= [HW,ACPI,X86,ARM64] Advanced Configuration and Power Interface - Format: { force | off | strict | noirq | rsdt | + Format: { force | on | off | strict | noirq | rsdt | copy_dsdt } force -- enable ACPI if default was off + on -- enable ACPI but allow fallback to DT [arm64] off -- disable ACPI if default was on noirq -- do not use ACPI for IRQ routing strict -- Be less tolerant of platforms that are not strictly ACPI specification compliant. rsdt -- prefer RSDT over (default) XSDT copy_dsdt -- copy DSDT to memory - For ARM64, ONLY "acpi=off" or "acpi=force" are available + For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force" + are available See also Documentation/power/runtime_pm.txt, pci=noacpi diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 6884c7678453..3e4f1a45b125 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -42,6 +42,7 @@ int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ EXPORT_SYMBOL(acpi_pci_disabled); static bool param_acpi_off __initdata; +static bool param_acpi_on __initdata; static bool param_acpi_force __initdata; static int __init parse_acpi(char *arg) @@ -52,6 +53,8 @@ static int __init parse_acpi(char *arg) /* "acpi=off" disables both ACPI table parsing and interpreter */ if (strcmp(arg, "off") == 0) param_acpi_off = true; + else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */ + param_acpi_on = true; else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */ param_acpi_force = true; else @@ -198,10 +201,11 @@ void __init acpi_boot_table_init(void) * - ACPI has been disabled explicitly (acpi=off), or * - the device tree is not empty (it has more than just a /chosen node, * and a /hypervisor node when running on Xen) - * and ACPI has not been force enabled (acpi=force) + * and ACPI has not been [force] enabled (acpi=on|force) */ if (param_acpi_off || - (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) + (!param_acpi_on && !param_acpi_force && + of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) return; /* -- GitLab From 4812952f9c94f67b3cc78ad0a6482bf182aa5a44 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 23 Apr 2016 13:23:47 +0300 Subject: [PATCH 4513/9938] tracing: checking for NULL instead of IS_ERR() tracing_map_elt_alloc() returns ERR_PTRs on error, never NULL. Fixes: 08d43a5fa063 ('tracing: Add lock-free tracing_map') Link: http://lkml.kernel.org/r/20160423102347.GA11136@mwanda Acked-by: Tom Zanussi Signed-off-by: Dan Carpenter Signed-off-by: Steven Rostedt --- kernel/trace/tracing_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index e0f172932eca..e7dfc5eec669 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -814,7 +814,7 @@ static struct tracing_map_elt *copy_elt(struct tracing_map_elt *elt) unsigned int i; dup_elt = tracing_map_elt_alloc(elt->map); - if (!dup_elt) + if (IS_ERR(dup_elt)) return NULL; if (elt->map->ops && elt->map->ops->elt_copy) -- GitLab From 432480c58219eff32904b879eb3fcc1d268a3b06 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Mon, 25 Apr 2016 14:01:27 -0500 Subject: [PATCH 4514/9938] tracing: Add check for NULL event field when creating hist field Smatch flagged create_hist_field() as possibly being able to dereference a NULL pointer, although the current code exits in all cases where the event field could be NULL, so it's not actually a problem. Still, to prevent future changes to the code from overlooking new cases, make the NULL pointer check explicit and warn once in that case. Link: http://lkml.kernel.org/r/cfbc003f534a3e441b4313272fd412310aba6336.1461610073.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index f98b6b3a2804..0c05b8a99806 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -371,6 +371,9 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field, goto out; } + if (WARN_ON_ONCE(!field)) + goto out; + if (is_string_field(field)) { flags |= HIST_FIELD_FL_STRING; -- GitLab From 6e4cf657defa8fb06dbf9ed91adb78414758f259 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Mon, 25 Apr 2016 14:01:28 -0500 Subject: [PATCH 4515/9938] tracing: Handle tracing_map_alloc_elts() error path correctly If tracing_map_elt_alloc() fails, it will return ERR_PTR() instead of NULL, so change the check to IS_ERROR(). We also need to set the failed entry in the map->elts array to NULL instead of ERR_PTR() so tracing_map_free_elts() doesn't try freeing an ERR_PTR(). tracing_map_free_elts() should also zero out what it frees so a reentrant call won't find previously freed elements. Link: http://lkml.kernel.org/r/f29d03b00bce3aac8cf151a8a30e6c83e5fee66d.1461610073.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt --- kernel/trace/tracing_map.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index e7dfc5eec669..0a689bbb78ef 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -366,10 +366,13 @@ static void tracing_map_free_elts(struct tracing_map *map) if (!map->elts) return; - for (i = 0; i < map->max_elts; i++) + for (i = 0; i < map->max_elts; i++) { tracing_map_elt_free(*(TRACING_MAP_ELT(map->elts, i))); + *(TRACING_MAP_ELT(map->elts, i)) = NULL; + } tracing_map_array_free(map->elts); + map->elts = NULL; } static int tracing_map_alloc_elts(struct tracing_map *map) @@ -383,7 +386,8 @@ static int tracing_map_alloc_elts(struct tracing_map *map) for (i = 0; i < map->max_elts; i++) { *(TRACING_MAP_ELT(map->elts, i)) = tracing_map_elt_alloc(map); - if (!(*(TRACING_MAP_ELT(map->elts, i)))) { + if (IS_ERR(*(TRACING_MAP_ELT(map->elts, i)))) { + *(TRACING_MAP_ELT(map->elts, i)) = NULL; tracing_map_free_elts(map); return -ENOMEM; -- GitLab From 85f5251792abcd6dae897df8eb4ca0e890bc5882 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 30 Mar 2016 13:42:48 +0200 Subject: [PATCH 4516/9938] tile/defconfigs: Remove CONFIG_IPV6_PRIVACY Option is long gone, see 5d9efa7ee99e ("ipv6: Remove privacy config option.") Signed-off-by: Borislav Petkov Cc: Chris Metcalf Signed-off-by: Chris Metcalf --- arch/tile/configs/tilegx_defconfig | 1 - arch/tile/configs/tilepro_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig index 3f3dfb8b150a..e5fe22c48851 100644 --- a/arch/tile/configs/tilegx_defconfig +++ b/arch/tile/configs/tilegx_defconfig @@ -89,7 +89,6 @@ CONFIG_TCP_CONG_YEAH=m CONFIG_TCP_CONG_ILLINOIS=m CONFIG_TCP_MD5SIG=y CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig index ef9e27eb2f50..766e27edddee 100644 --- a/arch/tile/configs/tilepro_defconfig +++ b/arch/tile/configs/tilepro_defconfig @@ -85,7 +85,6 @@ CONFIG_TCP_CONG_YEAH=m CONFIG_TCP_CONG_ILLINOIS=m CONFIG_TCP_MD5SIG=y CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y -- GitLab From 71324fdc72ef0163e57631aa814a9a81e9e4770b Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Wed, 20 Apr 2016 11:24:17 +0930 Subject: [PATCH 4517/9938] pinctrl: exynos5440: Use off-stack memory for pinctrl_gpio_range The range is registered into a linked list which can be referenced throughout the lifetime of the driver. Ensure the range's memory is useful for the same lifetime by adding it to the driver's private data structure. The bug was introduced in the driver's initial commit, which was present in v3.10. Fixes: f0b9a7e521fa ("pinctrl: exynos5440: add pinctrl driver for Samsung EXYNOS5440 SoC") Cc: stable@vger.kernel.org Signed-off-by: Andrew Jeffery Acked-by: Tomasz Figa Reviewed-by: Krzysztof Kozlowski Signed-off-by: Linus Walleij --- drivers/pinctrl/samsung/pinctrl-exynos5440.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c index 71f9f13e826d..fb71fc3e5aa0 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c @@ -107,6 +107,7 @@ struct exynos5440_pmx_func { * @nr_groups: number of pin groups available. * @pmx_functions: list of pin functions parsed from device tree. * @nr_functions: number of pin functions available. + * @range: gpio range to register with pinctrl */ struct exynos5440_pinctrl_priv_data { void __iomem *reg_base; @@ -117,6 +118,7 @@ struct exynos5440_pinctrl_priv_data { unsigned int nr_groups; const struct exynos5440_pmx_func *pmx_functions; unsigned int nr_functions; + struct pinctrl_gpio_range range; }; /** @@ -742,7 +744,6 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev, struct pinctrl_desc *ctrldesc; struct pinctrl_dev *pctl_dev; struct pinctrl_pin_desc *pindesc, *pdesc; - struct pinctrl_gpio_range grange; char *pin_names; int pin, ret; @@ -794,12 +795,12 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev, return PTR_ERR(pctl_dev); } - grange.name = "exynos5440-pctrl-gpio-range"; - grange.id = 0; - grange.base = 0; - grange.npins = EXYNOS5440_MAX_PINS; - grange.gc = priv->gc; - pinctrl_add_gpio_range(pctl_dev, &grange); + priv->range.name = "exynos5440-pctrl-gpio-range"; + priv->range.id = 0; + priv->range.base = 0; + priv->range.npins = EXYNOS5440_MAX_PINS; + priv->range.gc = priv->gc; + pinctrl_add_gpio_range(pctl_dev, &priv->range); return 0; } -- GitLab From 153847586b0aaa9482e42bc7e95b24adb87a1859 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 26 Apr 2016 09:54:56 -0400 Subject: [PATCH 4518/9938] tile: clarify barrier semantics of atomic_add_return A recent discussion on LKML made it clear that the one-line comment previously in atomic_add_return() was not clear enough: https://lkml.kernel.org/r/571E87E2.3010306@mellanox.com Signed-off-by: Chris Metcalf --- arch/tile/include/asm/atomic_64.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h index 51cabc26e387..b0531a623653 100644 --- a/arch/tile/include/asm/atomic_64.h +++ b/arch/tile/include/asm/atomic_64.h @@ -37,12 +37,25 @@ static inline void atomic_add(int i, atomic_t *v) __insn_fetchadd4((void *)&v->counter, i); } +/* + * Note a subtlety of the locking here. We are required to provide a + * full memory barrier before and after the operation. However, we + * only provide an explicit mb before the operation. After the + * operation, we use barrier() to get a full mb for free, because: + * + * (1) The barrier directive to the compiler prohibits any instructions + * being statically hoisted before the barrier; + * (2) the microarchitecture will not issue any further instructions + * until the fetchadd result is available for the "+ i" add instruction; + * (3) the smb_mb before the fetchadd ensures that no other memory + * operations are in flight at this point. + */ static inline int atomic_add_return(int i, atomic_t *v) { int val; smp_mb(); /* barrier for proper semantics */ val = __insn_fetchadd4((void *)&v->counter, i) + i; - barrier(); /* the "+ i" above will wait on memory */ + barrier(); /* equivalent to smp_mb(); see block comment above */ return val; } @@ -95,7 +108,7 @@ static inline long atomic64_add_return(long i, atomic64_t *v) int val; smp_mb(); /* barrier for proper semantics */ val = __insn_fetchadd((void *)&v->counter, i) + i; - barrier(); /* the "+ i" above will wait on memory */ + barrier(); /* equivalent to smp_mb; see atomic_add_return() */ return val; } -- GitLab From b04b7023751bf6519eee64467b6477f0e7fb82a1 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Tue, 26 Apr 2016 02:28:54 +0000 Subject: [PATCH 4519/9938] perf evlist: Enforce ring buffer reading Don't read broken data after 'head' pointer. Following commits will feed perf_evlist__mmap_read() with some 'head' pointers not maintained by kernel. If 'head' pointer breaks an event, we should avoid reading from the broken event. This can happen in backward ring buffer. For example: old head | | V V +---+------+----------+----+-----+--+ |..E|D....D|C........C|B..B|A....|E.| +---+------+----------+----+-----+--+ 'old' pointer points to the beginning of 'A' and trying read from it, but 'A' has been overwritten. In this case, don't try to read from 'A', simply return NULL. Signed-off-by: Wang Nan Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1461637738-62722-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 6fb5725821de..85271e54a63b 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -684,6 +684,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) struct perf_mmap *md = &evlist->mmap[idx]; u64 head; u64 old = md->prev; + int diff; unsigned char *data = md->base + page_size; union perf_event *event = NULL; @@ -694,6 +695,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) return NULL; head = perf_mmap__read_head(md); + diff = head - old; if (evlist->overwrite) { /* * If we're further behind than half the buffer, there's a chance @@ -703,7 +705,6 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) * * In either case, truncate and restart at head. */ - int diff = head - old; if (diff > md->mask / 2 || diff < 0) { fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); @@ -711,15 +712,21 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) * head points to a known good entry, start there. */ old = head; + diff = 0; } } - if (old != head) { + if (diff >= (int)sizeof(event->header)) { size_t size; event = (union perf_event *)&data[old & md->mask]; size = event->header.size; + if (size < sizeof(event->header) || diff < (int)size) { + event = NULL; + goto broken_event; + } + /* * Event straddles the mmap boundary -- header should always * be inside due to u64 alignment of output. @@ -743,6 +750,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) old += size; } +broken_event: md->prev = old; return event; -- GitLab From 062d6c2aec0e087be956494a73221c04eca115fe Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 26 Apr 2016 15:47:37 +0900 Subject: [PATCH 4520/9938] perf probe: Close target file on error path Fix a bug to close target elf file in get_text_start_address(). Signed-off-by: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20160426064737.1443.44093.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 8319fbb08636..97b7f8e5fe69 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -486,8 +486,10 @@ static int get_text_start_address(const char *exec, unsigned long *address) return -errno; elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) - return -EINVAL; + if (elf == NULL) { + ret = -EINVAL; + goto out_close; + } if (gelf_getehdr(elf, &ehdr) == NULL) goto out; @@ -499,6 +501,9 @@ static int get_text_start_address(const char *exec, unsigned long *address) ret = 0; out: elf_end(elf); +out_close: + close(fd); + return ret; } -- GitLab From 0c0451e7634564052a045d4398a91ea4ef1f755b Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 12 Apr 2016 13:52:31 +0300 Subject: [PATCH 4521/9938] gpio: omap: fix irq triggering in smart-idle wakeup mode Now GPIO IRQ loss is observed on dra7-evm after suspend/resume cycle in the following case: extcon_usb1(id_irq) -> pcf8575.gpio1 -> omapgpio6.gpio11 -> gic the extcon_usb1 is wake up source and it enables IRQ wake up for id_irq by calling enable/disable_irq_wake() during suspend/resume which, in turn, causes execution of omap_gpio_wake_enable(). And omap_gpio_wake_enable() will set/clear corresponding bit in GPIO_IRQWAKEN_x register. omapgpio6 configuration after boot - wakeup is enabled for GPIO IRQs by default from omap_gpio_irq_type: GPIO_IRQSTATUS_SET_0 | 0x00000400 GPIO_IRQSTATUS_CLR_0 | 0x00000400 GPIO_IRQWAKEN_0 | 0x00000400 GPIO_RISINGDETECT | 0x00000000 GPIO_FALLINGDETECT | 0x00000400 omapgpio6 configuration after after suspend/resume cycle: GPIO_IRQSTATUS_SET_0 | 0x00000400 GPIO_IRQSTATUS_CLR_0 | 0x00000400 GPIO_IRQWAKEN_0 | 0x00000000 <--- GPIO_RISINGDETECT | 0x00000000 GPIO_FALLINGDETECT | 0x00000400 As result, system will start to lose interrupts from pcf8575 GPIO expander, because when OMAP GPIO IP is in smart-idle wakeup mode, there is no guarantee that transition(s) on input non wake up GPIO pin will trigger asynchronous wake-up request to PRCM and then IRQ generation. IRQ will be generated when GPIO is in active mode - for example, some time after accessing GPIO bank registers IRQs will be generated normally, but issue will happen again once PRCM will put GPIO in low power smart-idle wakeup mode. Note 1. Issue is not reproduced if debounce clk is enabled for GPIO bank. Note 2. Issue hardly reproducible if GPIO pins group contains both wakeup/non-wakeup gpios - for example, it will be hard to reproduce issue with pin2 if GPIO_IRQWAKEN_0=0x1 GPIO_IRQSTATUS_SET_0=0x3 GPIO_FALLINGDETECT = 0x3 (TRM "Power Saving by Grouping the Edge/Level Detection"). Note 3. There nothing common bitween System wake up and OMAP GPIO bank IP wake up logic - the last one defines how the GPIO bank ON-IDLE-ON transition will happen inside SoC under control of PRCM. Hence, fix the problem by removing omap_set_gpio_wakeup() function completely and so keeping always in sync GPIO IRQ mask/unmask (IRQSTATUS_SET) and wake up enable (GPIO_IRQWAKEN) bits; and adding IRQCHIP_MASK_ON_SUSPEND flag in OMAP GPIO irqchip. That way non wakeup GPIO IRQs will be properly masked/unmask by IRQ PM core during suspend/resume cycle. Cc: Roger Quadros Signed-off-by: Grygorii Strashko Acked-by: Tony Lindgren Acked-by: Santosh Shilimkar Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 42 ++-------------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 551dfa9d97ab..b98ede78c9d8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -611,51 +611,12 @@ static inline void omap_set_gpio_irqenable(struct gpio_bank *bank, omap_disable_gpio_irqbank(bank, BIT(offset)); } -/* - * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register. - * 1510 does not seem to have a wake-up register. If JTAG is connected - * to the target, system will wake up always on GPIO events. While - * system is running all registered GPIO interrupts need to have wake-up - * enabled. When system is suspended, only selected GPIO interrupts need - * to have wake-up enabled. - */ -static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset, - int enable) -{ - u32 gpio_bit = BIT(offset); - unsigned long flags; - - if (bank->non_wakeup_gpios & gpio_bit) { - dev_err(bank->chip.parent, - "Unable to modify wakeup on non-wakeup GPIO%d\n", - offset); - return -EINVAL; - } - - raw_spin_lock_irqsave(&bank->lock, flags); - if (enable) - bank->context.wake_en |= gpio_bit; - else - bank->context.wake_en &= ~gpio_bit; - - writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); - raw_spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable) { struct gpio_bank *bank = omap_irq_data_get_bank(d); - unsigned offset = d->hwirq; - int ret; - ret = omap_set_gpio_wakeup(bank, offset, enable); - if (!ret) - ret = irq_set_irq_wake(bank->irq, enable); - - return ret; + return irq_set_irq_wake(bank->irq, enable); } static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -1187,6 +1148,7 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_bus_lock = omap_gpio_irq_bus_lock, irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, irqc->name = dev_name(&pdev->dev); + irqc->flags = IRQCHIP_MASK_ON_SUSPEND; bank->irq = platform_get_irq(pdev, 0); if (bank->irq <= 0) { -- GitLab From 296471ad51780996d3b1f2dfb65bc4dbdea69a1e Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Sat, 2 Apr 2016 10:55:21 -0700 Subject: [PATCH 4522/9938] localmodconfig: Fix parsing of Kconfig "source" statements The parameter of Kconfig "source" statements does not need to be quoted. The current regex causes many kconfig files to be skipped and hence, dependencies to be missed. Also fix the whitespace repeat count. Link: http://lkml.kernel.org/r/1459619722-13695-1-git-send-email-bpoirier@suse.com Tested-by: Lee, Chun-Yi Signed-off-by: Benjamin Poirier Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index f3d3fb42b873..7036ae306db6 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -188,7 +188,7 @@ sub read_kconfig { $cont = 0; # collect any Kconfig sources - if (/^source\s*"(.*)"/) { + if (/^source\s+"?([^"]+)/) { my $kconfig = $1; # prevent reading twice. if (!defined($read_kconfigs{$kconfig})) { -- GitLab From 27b7156886d875f2f54fab8790144e1fa80b7160 Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Sun, 10 Apr 2016 17:06:30 -0700 Subject: [PATCH 4523/9938] localmodconfig: Recognize more keywords that end a menu entry Based on the list in Documentation/kbuild/kconfig-language.txt This removes junk from %depends because parsing of a menu entry spilled over to another menu entry. Link: http://lkml.kernel.org/r/1460333193-16361-1-git-send-email-bpoirier@suse.com Signed-off-by: Benjamin Poirier Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 7036ae306db6..64d750cc5ae4 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -256,8 +256,8 @@ sub read_kconfig { $iflevel-- if ($iflevel); - # stop on "help" - } elsif (/^\s*help\s*$/) { + # stop on "help" and keywords that end a menu entry + } elsif (/^\s*help\s*$/ || /^(comment|choice|menu)\b/) { $state = "NONE"; } } -- GitLab From a77ed525d0120e244937eaa74c6086da1dab283a Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Sun, 10 Apr 2016 17:06:31 -0700 Subject: [PATCH 4524/9938] localmodconfig: Fix parsing of "help" text Help text may start with "help" or "---help---". This patch fixes read_kconfig() to recognize the second variant. This removes useless junk from %depends and %selects. That junk is due to help text that contains the words "selects" and "depends". Link: http://lkml.kernel.org/r/1460333193-16361-2-git-send-email-bpoirier@suse.com Signed-off-by: Benjamin Poirier Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 64d750cc5ae4..b2f904a24c5c 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -257,7 +257,7 @@ sub read_kconfig { $iflevel-- if ($iflevel); # stop on "help" and keywords that end a menu entry - } elsif (/^\s*help\s*$/ || /^(comment|choice|menu)\b/) { + } elsif (/^\s*(---)?help(---)?\s*$/ || /^(comment|choice|menu)\b/) { $state = "NONE"; } } -- GitLab From 6fef79536505be6bf3b0b4ebac70a20f24cffebb Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4525/9938] ARM: dts: STi: STiH407: Provide generic (safe) DVFS configuration You'll notice that the voltage cell is populated with 0's. Voltage information is very platform specific, even depends on 'cut' and 'substrate' versions. Thus it is left blank for a generic (safe) implementation. If other nodes/properties are provided by the bootloader, the ST CPUFreq driver will over-ride these generic values. Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 81f81214cdf9..9fa1e58557ef 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -22,15 +22,29 @@ device_type = "cpu"; compatible = "arm,cortex-a9"; reg = <0>; + /* u-boot puts hpen in SBC dmem at 0xa4 offset */ cpu-release-addr = <0x94100A4>; + + /* kHz uV */ + operating-points = <1500000 0 + 1200000 0 + 800000 0 + 500000 0>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a9"; reg = <1>; + /* u-boot puts hpen in SBC dmem at 0xa4 offset */ cpu-release-addr = <0x94100A4>; + + /* kHz uV */ + operating-points = <1500000 0 + 1200000 0 + 800000 0 + 500000 0>; }; }; -- GitLab From 5169192bc1d51cac1ccd57757a849657fb3bdf93 Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Sun, 10 Apr 2016 17:06:32 -0700 Subject: [PATCH 4526/9938] localmodconfig: Add missing $ to reference a variable That is clearly what the original intention was. This does not change the output .config but it prevents some useless processing. ! eq "m" is changed to the simpler eq "y"; symbols with values other than m|y are not included in %orig_configs. Link: http://lkml.kernel.org/r/1460333193-16361-3-git-send-email-bpoirier@suse.com Signed-off-by: Benjamin Poirier Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index b2f904a24c5c..01b53eccfe2f 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -454,7 +454,7 @@ sub parse_config_depends $p =~ s/^[^$valid]*[$valid]+//; # We only need to process if the depend config is a module - if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") { + if (!defined($orig_configs{$conf}) || $orig_configs{$conf} eq "y") { next; } -- GitLab From 4ad8f3ac12dc7a1420d7b995c007255c73740113 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4527/9938] ARM: dts: STi: STiH407: Provide CPU with clocking information Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 9fa1e58557ef..af9233bb7a26 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -31,6 +31,10 @@ 1200000 0 800000 0 500000 0>; + + clocks = <&clk_m_a9>; + clock-names = "cpu"; + clock-latency = <100000>; }; cpu@1 { device_type = "cpu"; -- GitLab From fe7de3c3c6f3cbd715e8bcf6fbcb6dc01f2a7aad Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4528/9938] ARM: dts: STi: STiH407: Link CPU with its voltage supply Used for Voltage Scaling using CPUFreq. Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index af9233bb7a26..d0e639cd3967 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -35,6 +35,7 @@ clocks = <&clk_m_a9>; clock-names = "cpu"; clock-latency = <100000>; + cpu0-supply = <&pwm_regulator>; }; cpu@1 { device_type = "cpu"; -- GitLab From 5609263014c452f4c5f5a470b13e226f2fb0e578 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4529/9938] ARM: dts: STi: STiH407: Provide CPU with a means to look-up Major number This is used for CPU Frequency Scaling. Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index d0e639cd3967..eb2601ffe080 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -36,6 +36,7 @@ clock-names = "cpu"; clock-latency = <100000>; cpu0-supply = <&pwm_regulator>; + st,syscfg = <&syscfg_core 0x8e0>; }; cpu@1 { device_type = "cpu"; -- GitLab From 6e966f13dc7b01e0134e6c8d72e23625b7be8b94 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4530/9938] ARM: dts: STi: stih407-family: Add nodes for Mailbox This patch supplies the Mailbox Controller nodes. In order to request channels, these nodes will be referenced by Mailbox Client nodes. Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index eb2601ffe080..680b7c10618e 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -714,5 +714,38 @@ clocks = <&clk_sysin>; status = "okay"; }; + + mailbox0: mailbox@8f00000 { + compatible = "st,stih407-mailbox"; + reg = <0x8f00000 0x1000>; + interrupts = ; + #mbox-cells = <2>; + mbox-name = "a9"; + status = "okay"; + }; + + mailbox1: mailbox@8f01000 { + compatible = "st,stih407-mailbox"; + reg = <0x8f01000 0x1000>; + #mbox-cells = <2>; + mbox-name = "st231_gp_1"; + status = "okay"; + }; + + mailbox2: mailbox@8f02000 { + compatible = "st,stih407-mailbox"; + reg = <0x8f02000 0x1000>; + #mbox-cells = <2>; + mbox-name = "st231_gp_0"; + status = "okay"; + }; + + mailbox3: mailbox@8f03000 { + compatible = "st,stih407-mailbox"; + reg = <0x8f03000 0x1000>; + #mbox-cells = <2>; + mbox-name = "st231_audio_video"; + status = "okay"; + }; }; }; -- GitLab From 3ff0a019d7f2e3c600d5aab935a059454060fe4c Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4531/9938] ARM: dts: STiH407: Add nodes for RemoteProc Signed-off-by: Ludovic Barre Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 680b7c10618e..7cd358b4ec68 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -747,5 +747,45 @@ mbox-name = "st231_audio_video"; status = "okay"; }; + + st231_gp0: remote-processor@40000000 { + compatible = "st,st231-rproc"; + reg = <0x40000000 0x01000000>; + resets = <&softreset STIH407_ST231_GP0_SOFTRESET>; + reset-names = "sw_reset"; + clocks = <&clk_s_c0_flexgen CLK_ST231_GP_0>; + clock-frequency = <600000000>; + st,syscfg = <&syscfg_core 0x22c>; + }; + + st231_gp1: remote-processor@41000000 { + compatible = "st,st231-rproc"; + reg = <0x41000000 0x01000000>; + resets = <&softreset STIH407_ST231_GP1_SOFTRESET>; + reset-names = "sw_reset"; + clocks = <&clk_s_c0_flexgen CLK_ST231_GP_1>; + clock-frequency = <600000000>; + st,syscfg = <&syscfg_core 0x220>; + }; + + st231_audio: remote-processor@42000000 { + compatible = "st,st231-rproc"; + reg = <0x42000000 0x01000000>; + resets = <&softreset STIH407_ST231_AUD_SOFTRESET>; + reset-names = "sw_reset"; + clocks = <&clk_s_c0_flexgen CLK_ST231_AUD_0>; + clock-frequency = <600000000>; + st,syscfg = <&syscfg_core 0x228>; + }; + + st231_dmu: remote-processor@43000000 { + compatible = "st,st231-rproc"; + reg = <0x43000000 0x01000000>; + resets = <&softreset STIH407_ST231_DMU_SOFTRESET>; + reset-names = "sw_reset"; + clocks = <&clk_s_c0_flexgen CLK_ST231_DMU>; + clock-frequency = <600000000>; + st,syscfg = <&syscfg_core 0x224>; + }; }; }; -- GitLab From fe135c636a5e3c2eb2856366ad3e54849bf06e64 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4532/9938] ARM: dts: STiH407: Move over to using the 'reserved-memory' API for obtaining DMA memory Doing so saves quite a bit of code in the driver. For more information on the 'reserved-memory' bindings see: Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt Suggested-by: Suman Anna Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 47 ++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 7cd358b4ec68..33de73616d39 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -15,6 +15,36 @@ #address-cells = <1>; #size-cells = <1>; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gp0_reserved: rproc@40000000 { + compatible = "shared-dma-pool"; + reg = <0x40000000 0x01000000>; + no-map; + }; + + gp1_reserved: rproc@41000000 { + compatible = "shared-dma-pool"; + reg = <0x41000000 0x01000000>; + no-map; + }; + + audio_reserved: rproc@42000000 { + compatible = "shared-dma-pool"; + reg = <0x42000000 0x01000000>; + no-map; + }; + + dmu_reserved: rproc@43000000 { + compatible = "shared-dma-pool"; + reg = <0x43000000 0x01000000>; + no-map; + }; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -748,9 +778,9 @@ status = "okay"; }; - st231_gp0: remote-processor@40000000 { + st231_gp0: remote-processor { compatible = "st,st231-rproc"; - reg = <0x40000000 0x01000000>; + memory-region = <&gp0_reserved>; resets = <&softreset STIH407_ST231_GP0_SOFTRESET>; reset-names = "sw_reset"; clocks = <&clk_s_c0_flexgen CLK_ST231_GP_0>; @@ -758,9 +788,10 @@ st,syscfg = <&syscfg_core 0x22c>; }; - st231_gp1: remote-processor@41000000 { + + st231_gp1: remote-processor { compatible = "st,st231-rproc"; - reg = <0x41000000 0x01000000>; + memory-region = <&gp1_reserved>; resets = <&softreset STIH407_ST231_GP1_SOFTRESET>; reset-names = "sw_reset"; clocks = <&clk_s_c0_flexgen CLK_ST231_GP_1>; @@ -768,9 +799,9 @@ st,syscfg = <&syscfg_core 0x220>; }; - st231_audio: remote-processor@42000000 { + st231_audio: remote-processor { compatible = "st,st231-rproc"; - reg = <0x42000000 0x01000000>; + memory-region = <&audio_reserved>; resets = <&softreset STIH407_ST231_AUD_SOFTRESET>; reset-names = "sw_reset"; clocks = <&clk_s_c0_flexgen CLK_ST231_AUD_0>; @@ -778,9 +809,9 @@ st,syscfg = <&syscfg_core 0x228>; }; - st231_dmu: remote-processor@43000000 { + st231_dmu: remote-processor { compatible = "st,st231-rproc"; - reg = <0x43000000 0x01000000>; + memory-region = <&dmu_reserved>; resets = <&softreset STIH407_ST231_DMU_SOFTRESET>; reset-names = "sw_reset"; clocks = <&clk_s_c0_flexgen CLK_ST231_DMU>; -- GitLab From 3d90bc051361c6f867df494d838d4fe1215d475a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Apr 2016 17:07:00 +0200 Subject: [PATCH 4533/9938] ARM: dts: STi: STih407: Switch LPC mode from RTC to Clocksource This aligns with the internal configuration. Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 33de73616d39..ad8ba10764a3 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -584,7 +584,7 @@ reg = <0x8788000 0x1000>; interrupts = ; clocks = <&clk_s_d3_flexgen CLK_LPC_1>; - st,lpc-mode = ; + st,lpc-mode = ; }; sata0: sata@9b20000 { -- GitLab From 76e3914ae51714b0535c38d9472d89124e0b6b96 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 16 Apr 2016 14:57:58 -0400 Subject: [PATCH 4534/9938] nvme: fix cntlid type Controller IDs in NVMe are unsigned 16-bit types. In the Fabrics driver we actually pass ctrl->id by reference, so we need it to have the correct type. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/nvme.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 8e8fae8722f8..9b96e7586194 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -84,7 +84,7 @@ struct nvme_ctrl { char serial[20]; char model[40]; char firmware_rev[8]; - int cntlid; + u16 cntlid; u32 ctrl_config; -- GitLab From b31356dfde571d925768783f1bb63ca8e156d0b3 Mon Sep 17 00:00:00 2001 From: Wang Sheng-Hui Date: Wed, 20 Apr 2016 10:04:32 +0800 Subject: [PATCH 4535/9938] NVMe: small typo in section BLK_DEV_NVME_SCSI of host/Kconfig "as well as " is miss typed "as well a " in section "config BLK_DEV_NVME_SCSI" Signed-off-by: Wang Sheng-Hui Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index c894841c6456..d296fc3ae06e 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -18,7 +18,7 @@ config BLK_DEV_NVME_SCSI depends on NVME_CORE ---help--- This adds support for the SG_IO ioctl on the NVMe character - and block devices nodes, as well a a translation for a small + and block devices nodes, as well as a translation for a small number of selected SCSI commands to NVMe commands to the NVMe driver. If you don't know what this means you probably want to say N here, unless you run a distro that abuses the SCSI -- GitLab From 8d4d5c3a7c25e69075e60e5e70c1e05c205aef89 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 26 Apr 2016 16:00:51 +0200 Subject: [PATCH 4536/9938] regulator: axp20x: Fix LDO4 linear voltage range The current linear voltage range for the LDO4 regulator found in the APX20X PMICs assumes that the voltage is linear between 2.5 and 3.1V. However, the PMIC can output up to 3.3V on that regulator by skipping the 2.6V and 2.9V steps. Fix the ranges to read and set the proper voltages. Fixes: 13d57e64352a ("regulator: axp20x: Use linear voltage ranges for AXP20X LDO4") Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 40cd894e4df5..29ab0985b46e 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -157,7 +157,9 @@ static struct regulator_ops axp20x_ops_sw = { static const struct regulator_linear_range axp20x_ldo4_ranges[] = { REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0), REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000), - REGULATOR_LINEAR_RANGE(2500000, 0x9, 0xf, 100000), + REGULATOR_LINEAR_RANGE(2500000, 0x9, 0x9, 0), + REGULATOR_LINEAR_RANGE(2700000, 0xa, 0xb, 100000), + REGULATOR_LINEAR_RANGE(3000000, 0xc, 0xf, 100000), }; static const struct regulator_desc axp20x_regulators[] = { -- GitLab From 989ff7754a27a1fcc0c3b2794c985b31811871a0 Mon Sep 17 00:00:00 2001 From: Jim Lodes Date: Mon, 25 Apr 2016 11:10:07 -0500 Subject: [PATCH 4537/9938] ASoC: omap-pcm: Initialize DMA configuration Initialize the dma_slave_config for PCM DMA transfers, instead of leaving it uninitialized. Keeps previous data on the stack from giving us invalid values in uninitialized members of the config structure. Signed-off-by: Jim Lodes Signed-off-by: J.D. Schroeder Acked-by: Jarkko Nikula Reviewed-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/omap-pcm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 6bb623a2a4df..eb81b9a2293a 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -82,6 +82,8 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, struct dma_chan *chan; int err = 0; + memset(&config, 0x00, sizeof(config)); + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); /* return if this is a bufferless transfer e.g. -- GitLab From f60d94c009685da0632d93297cae971c5898a04b Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:11 +0200 Subject: [PATCH 4538/9938] macsec: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- drivers/net/macsec.c | 121 ++++++++++++++++++++++++--------- include/uapi/linux/if_link.h | 1 + include/uapi/linux/if_macsec.h | 6 ++ 3 files changed, 95 insertions(+), 33 deletions(-) diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 6caa72402de7..a172a1ffa151 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -1405,9 +1405,10 @@ static sci_t nla_get_sci(const struct nlattr *nla) return (__force sci_t)nla_get_u64(nla); } -static int nla_put_sci(struct sk_buff *skb, int attrtype, sci_t value) +static int nla_put_sci(struct sk_buff *skb, int attrtype, sci_t value, + int padattr) { - return nla_put_u64(skb, attrtype, (__force u64)value); + return nla_put_u64_64bit(skb, attrtype, (__force u64)value, padattr); } static struct macsec_tx_sa *get_txsa_from_nl(struct net *net, @@ -2131,16 +2132,36 @@ static int copy_rx_sc_stats(struct sk_buff *skb, sum.InPktsUnusedSA += tmp.InPktsUnusedSA; } - if (nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED, sum.InOctetsValidated) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED, sum.InOctetsDecrypted) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED, sum.InPktsUnchecked) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED, sum.InPktsDelayed) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK, sum.InPktsOK) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID, sum.InPktsInvalid) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE, sum.InPktsLate) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, sum.InPktsNotValid) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, sum.InPktsNotUsingSA) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, sum.InPktsUnusedSA)) + if (nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED, + sum.InOctetsValidated, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED, + sum.InOctetsDecrypted, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED, + sum.InPktsUnchecked, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED, + sum.InPktsDelayed, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK, + sum.InPktsOK, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID, + sum.InPktsInvalid, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE, + sum.InPktsLate, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, + sum.InPktsNotValid, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, + sum.InPktsNotUsingSA, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, + sum.InPktsUnusedSA, + MACSEC_RXSC_STATS_ATTR_PAD)) return -EMSGSIZE; return 0; @@ -2169,10 +2190,18 @@ static int copy_tx_sc_stats(struct sk_buff *skb, sum.OutOctetsEncrypted += tmp.OutOctetsEncrypted; } - if (nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED, sum.OutPktsProtected) || - nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, sum.OutPktsEncrypted) || - nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, sum.OutOctetsProtected) || - nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, sum.OutOctetsEncrypted)) + if (nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED, + sum.OutPktsProtected, + MACSEC_TXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, + sum.OutPktsEncrypted, + MACSEC_TXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, + sum.OutOctetsProtected, + MACSEC_TXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, + sum.OutOctetsEncrypted, + MACSEC_TXSC_STATS_ATTR_PAD)) return -EMSGSIZE; return 0; @@ -2205,14 +2234,30 @@ static int copy_secy_stats(struct sk_buff *skb, sum.InPktsOverrun += tmp.InPktsOverrun; } - if (nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED, sum.OutPktsUntagged) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED, sum.InPktsUntagged) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG, sum.OutPktsTooLong) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG, sum.InPktsNoTag) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG, sum.InPktsBadTag) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, sum.InPktsUnknownSCI) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, sum.InPktsNoSCI) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, sum.InPktsOverrun)) + if (nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED, + sum.OutPktsUntagged, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED, + sum.InPktsUntagged, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG, + sum.OutPktsTooLong, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG, + sum.InPktsNoTag, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG, + sum.InPktsBadTag, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, + sum.InPktsUnknownSCI, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, + sum.InPktsNoSCI, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, + sum.InPktsOverrun, + MACSEC_SECY_STATS_ATTR_PAD)) return -EMSGSIZE; return 0; @@ -2226,8 +2271,11 @@ static int nla_put_secy(struct macsec_secy *secy, struct sk_buff *skb) if (!secy_nest) return 1; - if (nla_put_sci(skb, MACSEC_SECY_ATTR_SCI, secy->sci) || - nla_put_u64(skb, MACSEC_SECY_ATTR_CIPHER_SUITE, DEFAULT_CIPHER_ID) || + if (nla_put_sci(skb, MACSEC_SECY_ATTR_SCI, secy->sci, + MACSEC_SECY_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_ATTR_CIPHER_SUITE, + DEFAULT_CIPHER_ID, + MACSEC_SECY_ATTR_PAD) || nla_put_u8(skb, MACSEC_SECY_ATTR_ICV_LEN, secy->icv_len) || nla_put_u8(skb, MACSEC_SECY_ATTR_OPER, secy->operational) || nla_put_u8(skb, MACSEC_SECY_ATTR_PROTECT, secy->protect_frames) || @@ -2312,7 +2360,9 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, if (nla_put_u8(skb, MACSEC_SA_ATTR_AN, i) || nla_put_u32(skb, MACSEC_SA_ATTR_PN, tx_sa->next_pn) || - nla_put_u64(skb, MACSEC_SA_ATTR_KEYID, tx_sa->key.id) || + nla_put_u64_64bit(skb, MACSEC_SA_ATTR_KEYID, + tx_sa->key.id, + MACSEC_SA_ATTR_PAD) || nla_put_u8(skb, MACSEC_SA_ATTR_ACTIVE, tx_sa->active)) { nla_nest_cancel(skb, txsa_nest); nla_nest_cancel(skb, txsa_list); @@ -2353,7 +2403,8 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, } if (nla_put_u8(skb, MACSEC_RXSC_ATTR_ACTIVE, rx_sc->active) || - nla_put_sci(skb, MACSEC_RXSC_ATTR_SCI, rx_sc->sci)) { + nla_put_sci(skb, MACSEC_RXSC_ATTR_SCI, rx_sc->sci, + MACSEC_RXSC_ATTR_PAD)) { nla_nest_cancel(skb, rxsc_nest); nla_nest_cancel(skb, rxsc_list); goto nla_put_failure; @@ -2413,7 +2464,9 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, if (nla_put_u8(skb, MACSEC_SA_ATTR_AN, i) || nla_put_u32(skb, MACSEC_SA_ATTR_PN, rx_sa->next_pn) || - nla_put_u64(skb, MACSEC_SA_ATTR_KEYID, rx_sa->key.id) || + nla_put_u64_64bit(skb, MACSEC_SA_ATTR_KEYID, + rx_sa->key.id, + MACSEC_SA_ATTR_PAD) || nla_put_u8(skb, MACSEC_SA_ATTR_ACTIVE, rx_sa->active)) { nla_nest_cancel(skb, rxsa_nest); nla_nest_cancel(skb, rxsc_nest); @@ -3145,9 +3198,9 @@ static struct net *macsec_get_link_net(const struct net_device *dev) static size_t macsec_get_size(const struct net_device *dev) { return 0 + - nla_total_size(8) + /* SCI */ + nla_total_size_64bit(8) + /* SCI */ nla_total_size(1) + /* ICV_LEN */ - nla_total_size(8) + /* CIPHER_SUITE */ + nla_total_size_64bit(8) + /* CIPHER_SUITE */ nla_total_size(4) + /* WINDOW */ nla_total_size(1) + /* ENCODING_SA */ nla_total_size(1) + /* ENCRYPT */ @@ -3166,9 +3219,11 @@ static int macsec_fill_info(struct sk_buff *skb, struct macsec_secy *secy = &macsec_priv(dev)->secy; struct macsec_tx_sc *tx_sc = &secy->tx_sc; - if (nla_put_sci(skb, IFLA_MACSEC_SCI, secy->sci) || + if (nla_put_sci(skb, IFLA_MACSEC_SCI, secy->sci, + IFLA_MACSEC_PAD) || nla_put_u8(skb, IFLA_MACSEC_ICV_LEN, secy->icv_len) || - nla_put_u64(skb, IFLA_MACSEC_CIPHER_SUITE, DEFAULT_CIPHER_ID) || + nla_put_u64_64bit(skb, IFLA_MACSEC_CIPHER_SUITE, + DEFAULT_CIPHER_ID, IFLA_MACSEC_PAD) || nla_put_u8(skb, IFLA_MACSEC_ENCODING_SA, tx_sc->encoding_sa) || nla_put_u8(skb, IFLA_MACSEC_ENCRYPT, tx_sc->encrypt) || nla_put_u8(skb, IFLA_MACSEC_PROTECT, secy->protect_frames) || diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 9300c08346c8..d82de331bb6b 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -434,6 +434,7 @@ enum { IFLA_MACSEC_SCB, IFLA_MACSEC_REPLAY_PROTECT, IFLA_MACSEC_VALIDATION, + IFLA_MACSEC_PAD, __IFLA_MACSEC_MAX, }; diff --git a/include/uapi/linux/if_macsec.h b/include/uapi/linux/if_macsec.h index 26b0d1e3e3e7..4c623d617b84 100644 --- a/include/uapi/linux/if_macsec.h +++ b/include/uapi/linux/if_macsec.h @@ -55,6 +55,7 @@ enum macsec_secy_attrs { MACSEC_SECY_ATTR_INC_SCI, MACSEC_SECY_ATTR_ES, MACSEC_SECY_ATTR_SCB, + MACSEC_SECY_ATTR_PAD, __MACSEC_SECY_ATTR_END, NUM_MACSEC_SECY_ATTR = __MACSEC_SECY_ATTR_END, MACSEC_SECY_ATTR_MAX = __MACSEC_SECY_ATTR_END - 1, @@ -66,6 +67,7 @@ enum macsec_rxsc_attrs { MACSEC_RXSC_ATTR_ACTIVE, /* config/dump, u8 0..1 */ MACSEC_RXSC_ATTR_SA_LIST, /* dump, nested */ MACSEC_RXSC_ATTR_STATS, /* dump, nested, macsec_rxsc_stats_attr */ + MACSEC_RXSC_ATTR_PAD, __MACSEC_RXSC_ATTR_END, NUM_MACSEC_RXSC_ATTR = __MACSEC_RXSC_ATTR_END, MACSEC_RXSC_ATTR_MAX = __MACSEC_RXSC_ATTR_END - 1, @@ -79,6 +81,7 @@ enum macsec_sa_attrs { MACSEC_SA_ATTR_KEY, /* config, data */ MACSEC_SA_ATTR_KEYID, /* config/dump, u64 */ MACSEC_SA_ATTR_STATS, /* dump, nested, macsec_sa_stats_attr */ + MACSEC_SA_ATTR_PAD, __MACSEC_SA_ATTR_END, NUM_MACSEC_SA_ATTR = __MACSEC_SA_ATTR_END, MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1, @@ -110,6 +113,7 @@ enum macsec_rxsc_stats_attr { MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, + MACSEC_RXSC_STATS_ATTR_PAD, __MACSEC_RXSC_STATS_ATTR_END, NUM_MACSEC_RXSC_STATS_ATTR = __MACSEC_RXSC_STATS_ATTR_END, MACSEC_RXSC_STATS_ATTR_MAX = __MACSEC_RXSC_STATS_ATTR_END - 1, @@ -137,6 +141,7 @@ enum macsec_txsc_stats_attr { MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, + MACSEC_TXSC_STATS_ATTR_PAD, __MACSEC_TXSC_STATS_ATTR_END, NUM_MACSEC_TXSC_STATS_ATTR = __MACSEC_TXSC_STATS_ATTR_END, MACSEC_TXSC_STATS_ATTR_MAX = __MACSEC_TXSC_STATS_ATTR_END - 1, @@ -153,6 +158,7 @@ enum macsec_secy_stats_attr { MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, + MACSEC_SECY_STATS_ATTR_PAD, __MACSEC_SECY_STATS_ATTR_END, NUM_MACSEC_SECY_STATS_ATTR = __MACSEC_SECY_STATS_ATTR_END, MACSEC_SECY_STATS_ATTR_MAX = __MACSEC_SECY_STATS_ATTR_END - 1, -- GitLab From 08f4cbb8f207e2b8f40e8acc2a4e3a7df642b095 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:12 +0200 Subject: [PATCH 4539/9938] drivers/wireless: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/net/wireless/mac80211_hwsim.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c757f14c4c00..9ed0ed1bf514 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1030,7 +1030,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, data->pending_cookie++; cookie = data->pending_cookie; info->rate_driver_data[0] = (void *)cookie; - if (nla_put_u64(skb, HWSIM_ATTR_COOKIE, cookie)) + if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD)) goto nla_put_failure; genlmsg_end(skb, msg_head); diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index 66e1c73bd507..39f22467ca2a 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -148,6 +148,7 @@ enum { HWSIM_ATTR_RADIO_NAME, HWSIM_ATTR_NO_VIF, HWSIM_ATTR_FREQ, + HWSIM_ATTR_PAD, __HWSIM_ATTR_MAX, }; #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) -- GitLab From 3c6f3714d6a9e051eb84759e4fa5a2f4a3e730c6 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:13 +0200 Subject: [PATCH 4540/9938] fs/quota: use nla_put_u64_64bit() Signed-off-by: Nicolas Dichtel Acked-by: Jan Kara Signed-off-by: David S. Miller --- fs/quota/netlink.c | 12 +++++++----- include/uapi/linux/quota.h | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c index d07a2f91d858..8b252673d454 100644 --- a/fs/quota/netlink.c +++ b/fs/quota/netlink.c @@ -47,7 +47,7 @@ void quota_send_warning(struct kqid qid, dev_t dev, void *msg_head; int ret; int msg_size = 4 * nla_total_size(sizeof(u32)) + - 2 * nla_total_size(sizeof(u64)); + 2 * nla_total_size_64bit(sizeof(u64)); /* We have to allocate using GFP_NOFS as we are called from a * filesystem performing write and thus further recursion into @@ -68,8 +68,9 @@ void quota_send_warning(struct kqid qid, dev_t dev, ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, qid.type); if (ret) goto attr_err_out; - ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, - from_kqid_munged(&init_user_ns, qid)); + ret = nla_put_u64_64bit(skb, QUOTA_NL_A_EXCESS_ID, + from_kqid_munged(&init_user_ns, qid), + QUOTA_NL_A_PAD); if (ret) goto attr_err_out; ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); @@ -81,8 +82,9 @@ void quota_send_warning(struct kqid qid, dev_t dev, ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev)); if (ret) goto attr_err_out; - ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, - from_kuid_munged(&init_user_ns, current_uid())); + ret = nla_put_u64_64bit(skb, QUOTA_NL_A_CAUSED_ID, + from_kuid_munged(&init_user_ns, current_uid()), + QUOTA_NL_A_PAD); if (ret) goto attr_err_out; genlmsg_end(skb, msg_head); diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h index 38baddb807f5..4d2489ef6f10 100644 --- a/include/uapi/linux/quota.h +++ b/include/uapi/linux/quota.h @@ -191,6 +191,7 @@ enum { QUOTA_NL_A_DEV_MAJOR, QUOTA_NL_A_DEV_MINOR, QUOTA_NL_A_CAUSED_ID, + QUOTA_NL_A_PAD, __QUOTA_NL_A_MAX, }; #define QUOTA_NL_A_MAX (__QUOTA_NL_A_MAX - 1) -- GitLab From 6ed46d1247a595c58b6c04481fa77cf532f45de0 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:14 +0200 Subject: [PATCH 4541/9938] sock_diag: align nlattr properly when needed I also fix the value of INET_DIAG_MAX. It's wrong since commit 8f840e47f190 which is only in net-next right now, thus I didn't make a separate patch. Fixes: 8f840e47f190 ("sctp: add the sctp_diag.c file") Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/inet_diag.h | 4 +++- net/core/sock_diag.c | 2 +- net/ipv4/inet_diag.c | 9 ++++++--- net/sctp/sctp_diag.c | 5 +++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h index f5f3629dd553..a16643705669 100644 --- a/include/uapi/linux/inet_diag.h +++ b/include/uapi/linux/inet_diag.h @@ -115,9 +115,11 @@ enum { INET_DIAG_SKV6ONLY, INET_DIAG_LOCALS, INET_DIAG_PEERS, + INET_DIAG_PAD, + __INET_DIAG_MAX, }; -#define INET_DIAG_MAX INET_DIAG_SKV6ONLY +#define INET_DIAG_MAX (__INET_DIAG_MAX - 1) /* INET_DIAG_MEM */ diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index ca9e35bbe13c..6b10573cc9fa 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -120,7 +120,7 @@ static size_t sock_diag_nlmsg_size(void) { return NLMSG_ALIGN(sizeof(struct inet_diag_msg) + nla_total_size(sizeof(u8)) /* INET_DIAG_PROTOCOL */ - + nla_total_size(sizeof(struct tcp_info))); /* INET_DIAG_INFO */ + + nla_total_size_64bit(sizeof(struct tcp_info))); /* INET_DIAG_INFO */ } static void sock_diag_broadcast_destroy_work(struct work_struct *work) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index ad7956fa659a..25af1243649b 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -220,8 +220,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, } if ((ext & (1 << (INET_DIAG_INFO - 1))) && handler->idiag_info_size) { - attr = nla_reserve(skb, INET_DIAG_INFO, - handler->idiag_info_size); + attr = nla_reserve_64bit(skb, INET_DIAG_INFO, + handler->idiag_info_size, + INET_DIAG_PAD); if (!attr) goto errout; @@ -1078,7 +1079,9 @@ int inet_diag_handler_get_info(struct sk_buff *skb, struct sock *sk) } attr = handler->idiag_info_size - ? nla_reserve(skb, INET_DIAG_INFO, handler->idiag_info_size) + ? nla_reserve_64bit(skb, INET_DIAG_INFO, + handler->idiag_info_size, + INET_DIAG_PAD) : NULL; if (attr) info = nla_data(attr); diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c index bb2d8d9608e9..84829fff3bc9 100644 --- a/net/sctp/sctp_diag.c +++ b/net/sctp/sctp_diag.c @@ -161,8 +161,9 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc, if (ext & (1 << (INET_DIAG_INFO - 1))) { struct nlattr *attr; - attr = nla_reserve(skb, INET_DIAG_INFO, - sizeof(struct sctp_info)); + attr = nla_reserve_64bit(skb, INET_DIAG_INFO, + sizeof(struct sctp_info), + INET_DIAG_PAD); if (!attr) goto errout; -- GitLab From 66c7a5ee1a6b7c69d41dfd68d207fdd54efba56a Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:15 +0200 Subject: [PATCH 4542/9938] ovs: align nlattr properly when needed I also fix commit 8b32ab9e6ef1: use nla_total_size_64bit() for OVS_FLOW_ATTR_USED in ovs_flow_cmd_msg_size(). Fixes: 8b32ab9e6ef1 ("ovs: use nla_put_u64_64bit()") Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/openvswitch.h | 2 ++ net/openvswitch/datapath.c | 27 +++++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index d6be1fb778a5..bb0d515b7654 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -84,6 +84,7 @@ enum ovs_datapath_attr { OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */ OVS_DP_ATTR_MEGAFLOW_STATS, /* struct ovs_dp_megaflow_stats */ OVS_DP_ATTR_USER_FEATURES, /* OVS_DP_F_* */ + OVS_DP_ATTR_PAD, __OVS_DP_ATTR_MAX }; @@ -253,6 +254,7 @@ enum ovs_vport_attr { OVS_VPORT_ATTR_UPCALL_PID, /* array of u32 Netlink socket PIDs for */ /* receiving upcalls */ OVS_VPORT_ATTR_STATS, /* struct ovs_vport_stats */ + OVS_VPORT_ATTR_PAD, __OVS_VPORT_ATTR_MAX }; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 22d9a5316304..856bd8dba676 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -738,9 +738,9 @@ static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts, len += nla_total_size(acts->orig_len); return len - + nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */ + + nla_total_size_64bit(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */ + nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */ - + nla_total_size(8); /* OVS_FLOW_ATTR_USED */ + + nla_total_size_64bit(8); /* OVS_FLOW_ATTR_USED */ } /* Called with ovs_mutex or RCU read lock. */ @@ -759,7 +759,9 @@ static int ovs_flow_cmd_fill_stats(const struct sw_flow *flow, return -EMSGSIZE; if (stats.n_packets && - nla_put(skb, OVS_FLOW_ATTR_STATS, sizeof(struct ovs_flow_stats), &stats)) + nla_put_64bit(skb, OVS_FLOW_ATTR_STATS, + sizeof(struct ovs_flow_stats), &stats, + OVS_FLOW_ATTR_PAD)) return -EMSGSIZE; if ((u8)ntohs(tcp_flags) && @@ -1435,8 +1437,8 @@ static size_t ovs_dp_cmd_msg_size(void) size_t msgsize = NLMSG_ALIGN(sizeof(struct ovs_header)); msgsize += nla_total_size(IFNAMSIZ); - msgsize += nla_total_size(sizeof(struct ovs_dp_stats)); - msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats)); + msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_stats)); + msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_megaflow_stats)); msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */ return msgsize; @@ -1463,13 +1465,13 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, goto nla_put_failure; get_dp_stats(dp, &dp_stats, &dp_megaflow_stats); - if (nla_put(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats), - &dp_stats)) + if (nla_put_64bit(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats), + &dp_stats, OVS_DP_ATTR_PAD)) goto nla_put_failure; - if (nla_put(skb, OVS_DP_ATTR_MEGAFLOW_STATS, - sizeof(struct ovs_dp_megaflow_stats), - &dp_megaflow_stats)) + if (nla_put_64bit(skb, OVS_DP_ATTR_MEGAFLOW_STATS, + sizeof(struct ovs_dp_megaflow_stats), + &dp_megaflow_stats, OVS_DP_ATTR_PAD)) goto nla_put_failure; if (nla_put_u32(skb, OVS_DP_ATTR_USER_FEATURES, dp->user_features)) @@ -1838,8 +1840,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, goto nla_put_failure; ovs_vport_get_stats(vport, &vport_stats); - if (nla_put(skb, OVS_VPORT_ATTR_STATS, sizeof(struct ovs_vport_stats), - &vport_stats)) + if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS, + sizeof(struct ovs_vport_stats), &vport_stats, + OVS_VPORT_ATTR_PAD)) goto nla_put_failure; if (ovs_vport_get_upcall_portids(vport, skb)) -- GitLab From 270cb4d05b2923a4a4d712276e61f64c82567138 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:16 +0200 Subject: [PATCH 4543/9938] rtnl: align nlattr properly when needed Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9efc1f34ef3b..5503dfe6a050 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -876,7 +876,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ + nla_total_size(IFALIASZ) /* IFLA_IFALIAS */ + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ - + nla_total_size(sizeof(struct rtnl_link_ifmap)) + + nla_total_size_64bit(sizeof(struct rtnl_link_ifmap)) + nla_total_size(sizeof(struct rtnl_link_stats)) + nla_total_size_64bit(sizeof(struct rtnl_link_stats64)) + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ @@ -1181,7 +1181,7 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev) .dma = dev->dma, .port = dev->if_port, }; - if (nla_put(skb, IFLA_MAP, sizeof(map), &map)) + if (nla_put_64bit(skb, IFLA_MAP, sizeof(map), &map, IFLA_PAD)) return -EMSGSIZE; return 0; -- GitLab From b676338fb3aab0b63b4a2489feb8f35003db22e8 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:17 +0200 Subject: [PATCH 4544/9938] neigh: align nlattr properly when needed Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/core/neighbour.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 6a395d440228..29dd8cc22bbf 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1857,7 +1857,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, ndst.ndts_table_fulls += st->table_fulls; } - if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst)) + if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst, + NDTA_PAD)) goto nla_put_failure; } -- GitLab From 9854518ea04db33738602d45ebc96a200e6f5198 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 26 Apr 2016 10:06:18 +0200 Subject: [PATCH 4545/9938] sched: align nlattr properly when needed Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- Documentation/networking/gen_stats.txt | 6 +++-- include/net/gen_stats.h | 6 +++-- include/uapi/linux/gen_stats.h | 1 + include/uapi/linux/pkt_cls.h | 2 ++ include/uapi/linux/rtnetlink.h | 1 + include/uapi/linux/tc_act/tc_bpf.h | 1 + include/uapi/linux/tc_act/tc_connmark.h | 1 + include/uapi/linux/tc_act/tc_csum.h | 1 + include/uapi/linux/tc_act/tc_defact.h | 1 + include/uapi/linux/tc_act/tc_gact.h | 1 + include/uapi/linux/tc_act/tc_ife.h | 1 + include/uapi/linux/tc_act/tc_ipt.h | 1 + include/uapi/linux/tc_act/tc_mirred.h | 1 + include/uapi/linux/tc_act/tc_nat.h | 1 + include/uapi/linux/tc_act/tc_pedit.h | 1 + include/uapi/linux/tc_act/tc_skbedit.h | 1 + include/uapi/linux/tc_act/tc_vlan.h | 1 + net/core/gen_stats.c | 35 +++++++++++++++---------- net/sched/act_api.c | 7 +++-- net/sched/act_bpf.c | 3 ++- net/sched/act_connmark.c | 3 ++- net/sched/act_csum.c | 2 +- net/sched/act_gact.c | 2 +- net/sched/act_ife.c | 2 +- net/sched/act_ipt.c | 2 +- net/sched/act_mirred.c | 2 +- net/sched/act_nat.c | 2 +- net/sched/act_pedit.c | 2 +- net/sched/act_simple.c | 2 +- net/sched/act_skbedit.c | 2 +- net/sched/act_vlan.c | 2 +- net/sched/cls_u32.c | 7 ++--- net/sched/sch_api.c | 6 +++-- 33 files changed, 72 insertions(+), 37 deletions(-) diff --git a/Documentation/networking/gen_stats.txt b/Documentation/networking/gen_stats.txt index 70e6275b757a..ff630a87b511 100644 --- a/Documentation/networking/gen_stats.txt +++ b/Documentation/networking/gen_stats.txt @@ -33,7 +33,8 @@ my_dumping_routine(struct sk_buff *skb, ...) { struct gnet_dump dump; - if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump) < 0) + if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump, + TCA_PAD) < 0) goto rtattr_failure; if (gnet_stats_copy_basic(&dump, &mystruct->bstats) < 0 || @@ -56,7 +57,8 @@ existing TLV types. my_dumping_routine(struct sk_buff *skb, ...) { if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, - TCA_XSTATS, &mystruct->lock, &dump) < 0) + TCA_XSTATS, &mystruct->lock, &dump, + TCA_PAD) < 0) goto rtattr_failure; ... } diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index cbafa3768d48..610cd397890e 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h @@ -19,17 +19,19 @@ struct gnet_dump { /* Backward compatibility */ int compat_tc_stats; int compat_xstats; + int padattr; void * xstats; int xstats_len; struct tc_stats tc_stats; }; int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, - struct gnet_dump *d); + struct gnet_dump *d, int padattr); int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, int xstats_type, - spinlock_t *lock, struct gnet_dump *d); + spinlock_t *lock, struct gnet_dump *d, + int padattr); int gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_cpu __percpu *cpu, diff --git a/include/uapi/linux/gen_stats.h b/include/uapi/linux/gen_stats.h index 6487317ea619..52deccc2128e 100644 --- a/include/uapi/linux/gen_stats.h +++ b/include/uapi/linux/gen_stats.h @@ -10,6 +10,7 @@ enum { TCA_STATS_QUEUE, TCA_STATS_APP, TCA_STATS_RATE_EST64, + TCA_STATS_PAD, __TCA_STATS_MAX, }; #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h index c43c5f78b9c4..84660905fedf 100644 --- a/include/uapi/linux/pkt_cls.h +++ b/include/uapi/linux/pkt_cls.h @@ -66,6 +66,7 @@ enum { TCA_ACT_OPTIONS, TCA_ACT_INDEX, TCA_ACT_STATS, + TCA_ACT_PAD, __TCA_ACT_MAX }; @@ -173,6 +174,7 @@ enum { TCA_U32_PCNT, TCA_U32_MARK, TCA_U32_FLAGS, + TCA_U32_PAD, __TCA_U32_MAX }; diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index a94e0b69c769..262f0379d83a 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -542,6 +542,7 @@ enum { TCA_FCNT, TCA_STATS2, TCA_STAB, + TCA_PAD, __TCA_MAX }; diff --git a/include/uapi/linux/tc_act/tc_bpf.h b/include/uapi/linux/tc_act/tc_bpf.h index 07f17cc70bb3..063d9d465119 100644 --- a/include/uapi/linux/tc_act/tc_bpf.h +++ b/include/uapi/linux/tc_act/tc_bpf.h @@ -26,6 +26,7 @@ enum { TCA_ACT_BPF_OPS, TCA_ACT_BPF_FD, TCA_ACT_BPF_NAME, + TCA_ACT_BPF_PAD, __TCA_ACT_BPF_MAX, }; #define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_connmark.h b/include/uapi/linux/tc_act/tc_connmark.h index 994b0971bce2..62a5e944c554 100644 --- a/include/uapi/linux/tc_act/tc_connmark.h +++ b/include/uapi/linux/tc_act/tc_connmark.h @@ -15,6 +15,7 @@ enum { TCA_CONNMARK_UNSPEC, TCA_CONNMARK_PARMS, TCA_CONNMARK_TM, + TCA_CONNMARK_PAD, __TCA_CONNMARK_MAX }; #define TCA_CONNMARK_MAX (__TCA_CONNMARK_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_csum.h b/include/uapi/linux/tc_act/tc_csum.h index a047c49a3153..8ac8041ab5f1 100644 --- a/include/uapi/linux/tc_act/tc_csum.h +++ b/include/uapi/linux/tc_act/tc_csum.h @@ -10,6 +10,7 @@ enum { TCA_CSUM_UNSPEC, TCA_CSUM_PARMS, TCA_CSUM_TM, + TCA_CSUM_PAD, __TCA_CSUM_MAX }; #define TCA_CSUM_MAX (__TCA_CSUM_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_defact.h b/include/uapi/linux/tc_act/tc_defact.h index 17dddb40f740..d2a3abb77aeb 100644 --- a/include/uapi/linux/tc_act/tc_defact.h +++ b/include/uapi/linux/tc_act/tc_defact.h @@ -12,6 +12,7 @@ enum { TCA_DEF_TM, TCA_DEF_PARMS, TCA_DEF_DATA, + TCA_DEF_PAD, __TCA_DEF_MAX }; #define TCA_DEF_MAX (__TCA_DEF_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_gact.h b/include/uapi/linux/tc_act/tc_gact.h index f7bf94eed510..70b536a8f8b2 100644 --- a/include/uapi/linux/tc_act/tc_gact.h +++ b/include/uapi/linux/tc_act/tc_gact.h @@ -25,6 +25,7 @@ enum { TCA_GACT_TM, TCA_GACT_PARMS, TCA_GACT_PROB, + TCA_GACT_PAD, __TCA_GACT_MAX }; #define TCA_GACT_MAX (__TCA_GACT_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_ife.h b/include/uapi/linux/tc_act/tc_ife.h index d648ff66586f..4ece02a77b9a 100644 --- a/include/uapi/linux/tc_act/tc_ife.h +++ b/include/uapi/linux/tc_act/tc_ife.h @@ -23,6 +23,7 @@ enum { TCA_IFE_SMAC, TCA_IFE_TYPE, TCA_IFE_METALST, + TCA_IFE_PAD, __TCA_IFE_MAX }; #define TCA_IFE_MAX (__TCA_IFE_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_ipt.h b/include/uapi/linux/tc_act/tc_ipt.h index 130aaadf6fac..7c6e155dd981 100644 --- a/include/uapi/linux/tc_act/tc_ipt.h +++ b/include/uapi/linux/tc_act/tc_ipt.h @@ -14,6 +14,7 @@ enum { TCA_IPT_CNT, TCA_IPT_TM, TCA_IPT_TARG, + TCA_IPT_PAD, __TCA_IPT_MAX }; #define TCA_IPT_MAX (__TCA_IPT_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_mirred.h b/include/uapi/linux/tc_act/tc_mirred.h index 7561750e8fd6..3d7a2b352a62 100644 --- a/include/uapi/linux/tc_act/tc_mirred.h +++ b/include/uapi/linux/tc_act/tc_mirred.h @@ -20,6 +20,7 @@ enum { TCA_MIRRED_UNSPEC, TCA_MIRRED_TM, TCA_MIRRED_PARMS, + TCA_MIRRED_PAD, __TCA_MIRRED_MAX }; #define TCA_MIRRED_MAX (__TCA_MIRRED_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_nat.h b/include/uapi/linux/tc_act/tc_nat.h index 6663aeba0b9a..923457c9ebf0 100644 --- a/include/uapi/linux/tc_act/tc_nat.h +++ b/include/uapi/linux/tc_act/tc_nat.h @@ -10,6 +10,7 @@ enum { TCA_NAT_UNSPEC, TCA_NAT_PARMS, TCA_NAT_TM, + TCA_NAT_PAD, __TCA_NAT_MAX }; #define TCA_NAT_MAX (__TCA_NAT_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_pedit.h b/include/uapi/linux/tc_act/tc_pedit.h index 716cfabcd5b2..6389959a5157 100644 --- a/include/uapi/linux/tc_act/tc_pedit.h +++ b/include/uapi/linux/tc_act/tc_pedit.h @@ -10,6 +10,7 @@ enum { TCA_PEDIT_UNSPEC, TCA_PEDIT_TM, TCA_PEDIT_PARMS, + TCA_PEDIT_PAD, __TCA_PEDIT_MAX }; #define TCA_PEDIT_MAX (__TCA_PEDIT_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_skbedit.h b/include/uapi/linux/tc_act/tc_skbedit.h index 7a2e910a5f08..fecb5cc48c40 100644 --- a/include/uapi/linux/tc_act/tc_skbedit.h +++ b/include/uapi/linux/tc_act/tc_skbedit.h @@ -39,6 +39,7 @@ enum { TCA_SKBEDIT_PRIORITY, TCA_SKBEDIT_QUEUE_MAPPING, TCA_SKBEDIT_MARK, + TCA_SKBEDIT_PAD, __TCA_SKBEDIT_MAX }; #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1) diff --git a/include/uapi/linux/tc_act/tc_vlan.h b/include/uapi/linux/tc_act/tc_vlan.h index f7b8d448b960..31151ff6264f 100644 --- a/include/uapi/linux/tc_act/tc_vlan.h +++ b/include/uapi/linux/tc_act/tc_vlan.h @@ -28,6 +28,7 @@ enum { TCA_VLAN_PARMS, TCA_VLAN_PUSH_VLAN_ID, TCA_VLAN_PUSH_VLAN_PROTOCOL, + TCA_VLAN_PAD, __TCA_VLAN_MAX, }; #define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1) diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index e640462ea8bf..f96ee8b9478d 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c @@ -25,9 +25,9 @@ static inline int -gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size) +gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size, int padattr) { - if (nla_put(d->skb, type, size, buf)) + if (nla_put_64bit(d->skb, type, size, buf, padattr)) goto nla_put_failure; return 0; @@ -59,7 +59,8 @@ gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size) */ int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, - int xstats_type, spinlock_t *lock, struct gnet_dump *d) + int xstats_type, spinlock_t *lock, + struct gnet_dump *d, int padattr) __acquires(lock) { memset(d, 0, sizeof(*d)); @@ -71,16 +72,17 @@ gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, d->skb = skb; d->compat_tc_stats = tc_stats_type; d->compat_xstats = xstats_type; + d->padattr = padattr; if (d->tail) - return gnet_stats_copy(d, type, NULL, 0); + return gnet_stats_copy(d, type, NULL, 0, padattr); return 0; } EXPORT_SYMBOL(gnet_stats_start_copy_compat); /** - * gnet_stats_start_copy_compat - start dumping procedure in compatibility mode + * gnet_stats_start_copy - start dumping procedure in compatibility mode * @skb: socket buffer to put statistics TLVs into * @type: TLV type for top level statistic TLV * @lock: statistics lock @@ -94,9 +96,9 @@ EXPORT_SYMBOL(gnet_stats_start_copy_compat); */ int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, - struct gnet_dump *d) + struct gnet_dump *d, int padattr) { - return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d); + return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d, padattr); } EXPORT_SYMBOL(gnet_stats_start_copy); @@ -169,7 +171,8 @@ gnet_stats_copy_basic(struct gnet_dump *d, memset(&sb, 0, sizeof(sb)); sb.bytes = bstats.bytes; sb.packets = bstats.packets; - return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb)); + return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb), + TCA_STATS_PAD); } return 0; } @@ -208,11 +211,13 @@ gnet_stats_copy_rate_est(struct gnet_dump *d, } if (d->tail) { - res = gnet_stats_copy(d, TCA_STATS_RATE_EST, &est, sizeof(est)); + res = gnet_stats_copy(d, TCA_STATS_RATE_EST, &est, sizeof(est), + TCA_STATS_PAD); if (res < 0 || est.bps == r->bps) return res; /* emit 64bit stats only if needed */ - return gnet_stats_copy(d, TCA_STATS_RATE_EST64, r, sizeof(*r)); + return gnet_stats_copy(d, TCA_STATS_RATE_EST64, r, sizeof(*r), + TCA_STATS_PAD); } return 0; @@ -286,7 +291,8 @@ gnet_stats_copy_queue(struct gnet_dump *d, if (d->tail) return gnet_stats_copy(d, TCA_STATS_QUEUE, - &qstats, sizeof(qstats)); + &qstats, sizeof(qstats), + TCA_STATS_PAD); return 0; } @@ -316,7 +322,8 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) } if (d->tail) - return gnet_stats_copy(d, TCA_STATS_APP, st, len); + return gnet_stats_copy(d, TCA_STATS_APP, st, len, + TCA_STATS_PAD); return 0; @@ -347,12 +354,12 @@ gnet_stats_finish_copy(struct gnet_dump *d) if (d->compat_tc_stats) if (gnet_stats_copy(d, d->compat_tc_stats, &d->tc_stats, - sizeof(d->tc_stats)) < 0) + sizeof(d->tc_stats), d->padattr) < 0) return -1; if (d->compat_xstats && d->xstats) { if (gnet_stats_copy(d, d->compat_xstats, d->xstats, - d->xstats_len) < 0) + d->xstats_len, d->padattr) < 0) return -1; } diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 96066665e376..336774a535c3 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -657,12 +657,15 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, if (compat_mode) { if (a->type == TCA_OLD_COMPAT) err = gnet_stats_start_copy_compat(skb, 0, - TCA_STATS, TCA_XSTATS, &p->tcfc_lock, &d); + TCA_STATS, + TCA_XSTATS, + &p->tcfc_lock, &d, + TCA_PAD); else return 0; } else err = gnet_stats_start_copy(skb, TCA_ACT_STATS, - &p->tcfc_lock, &d); + &p->tcfc_lock, &d, TCA_ACT_PAD); if (err < 0) goto errout; diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index 8c9f1f0459ab..4fd703362563 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c @@ -156,7 +156,8 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act, tm.lastuse = jiffies_to_clock_t(jiffies - prog->tcf_tm.lastuse); tm.expires = jiffies_to_clock_t(prog->tcf_tm.expires); - if (nla_put(skb, TCA_ACT_BPF_TM, sizeof(tm), &tm)) + if (nla_put_64bit(skb, TCA_ACT_BPF_TM, sizeof(tm), &tm, + TCA_ACT_BPF_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index c0ed93ce2391..2ba700c765e0 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -163,7 +163,8 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, t.install = jiffies_to_clock_t(jiffies - ci->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - ci->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(ci->tcf_tm.expires); - if (nla_put(skb, TCA_CONNMARK_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t, + TCA_CONNMARK_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index d22426cdebc0..28e934ed038a 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c @@ -549,7 +549,7 @@ static int tcf_csum_dump(struct sk_buff *skb, t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(p->tcf_tm.expires); - if (nla_put(skb, TCA_CSUM_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_CSUM_TM, sizeof(t), &t, TCA_CSUM_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 887fc1f209ff..1a6e09fbb2a5 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -177,7 +177,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(gact->tcf_tm.expires); - if (nla_put(skb, TCA_GACT_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_GACT_TM, sizeof(t), &t, TCA_GACT_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index c589a9ba506a..556f44c9c454 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c @@ -550,7 +550,7 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, t.install = jiffies_to_clock_t(jiffies - ife->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - ife->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(ife->tcf_tm.expires); - if (nla_put(skb, TCA_IFE_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_IFE_TM, sizeof(t), &t, TCA_IFE_PAD)) goto nla_put_failure; if (!is_zero_ether_addr(ife->eth_dst)) { diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 350e134cffb3..1464f6a09446 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -275,7 +275,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install); tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse); tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires); - if (nla_put(skb, TCA_IPT_TM, sizeof (tm), &tm)) + if (nla_put_64bit(skb, TCA_IPT_TM, sizeof(tm), &tm, TCA_IPT_PAD)) goto nla_put_failure; kfree(t); return skb->len; diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index e8a760cf7775..dea57c1ec90c 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -214,7 +214,7 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(m->tcf_tm.expires); - if (nla_put(skb, TCA_MIRRED_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_MIRRED_TM, sizeof(t), &t, TCA_MIRRED_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 0f65cdfbfb1d..c0a879f940de 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c @@ -267,7 +267,7 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(p->tcf_tm.expires); - if (nla_put(skb, TCA_NAT_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_NAT_TM, sizeof(t), &t, TCA_NAT_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 429c3ab65142..c6e18f230af6 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -203,7 +203,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(p->tcf_tm.expires); - if (nla_put(skb, TCA_PEDIT_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_PEDIT_TM, sizeof(t), &t, TCA_PEDIT_PAD)) goto nla_put_failure; kfree(opt); return skb->len; diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 75b2be13fbcc..2057fd56d74c 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -155,7 +155,7 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(d->tcf_tm.expires); - if (nla_put(skb, TCA_DEF_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_DEF_TM, sizeof(t), &t, TCA_DEF_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index cfcdbdc00c9b..51b24998904f 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c @@ -167,7 +167,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(d->tcf_tm.expires); - if (nla_put(skb, TCA_SKBEDIT_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index bab8ae0cefc0..c1682ab9bc7e 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c @@ -175,7 +175,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, t.install = jiffies_to_clock_t(jiffies - v->tcf_tm.install); t.lastuse = jiffies_to_clock_t(jiffies - v->tcf_tm.lastuse); t.expires = jiffies_to_clock_t(v->tcf_tm.expires); - if (nla_put(skb, TCA_VLAN_TM, sizeof(t), &t)) + if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD)) goto nla_put_failure; return skb->len; diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 563cdad76448..e64877a3c084 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -1140,9 +1140,10 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, gpf->kcnts[i] += pf->kcnts[i]; } - if (nla_put(skb, TCA_U32_PCNT, - sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64), - gpf)) { + if (nla_put_64bit(skb, TCA_U32_PCNT, + sizeof(struct tc_u32_pcnt) + + n->sel.nkeys * sizeof(u64), + gpf, TCA_U32_PAD)) { kfree(gpf); goto nla_put_failure; } diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 3b180ff72f79..64f71a2155f3 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1365,7 +1365,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, goto nla_put_failure; if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS, - qdisc_root_sleeping_lock(q), &d) < 0) + qdisc_root_sleeping_lock(q), &d, + TCA_PAD) < 0) goto nla_put_failure; if (q->ops->dump_stats && q->ops->dump_stats(q, &d) < 0) @@ -1679,7 +1680,8 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, goto nla_put_failure; if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS, - qdisc_root_sleeping_lock(q), &d) < 0) + qdisc_root_sleeping_lock(q), &d, + TCA_PAD) < 0) goto nla_put_failure; if (cl_ops->dump_stats && cl_ops->dump_stats(q, cl, &d) < 0) -- GitLab From e640bc306ab4bfd416668a1c0a59c1fd9937b678 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 17:32:07 +0200 Subject: [PATCH 4546/9938] ARM: dts: omap5-board-common: DT spelling s/interrupt-name/interrupt-names/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5-board-common.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi index 902657d6713b..cdd144acbd3f 100644 --- a/arch/arm/boot/dts/omap5-board-common.dtsi +++ b/arch/arm/boot/dts/omap5-board-common.dtsi @@ -395,7 +395,7 @@ compatible = "ti,palmas-pmic"; interrupt-parent = <&palmas>; interrupts = <14 IRQ_TYPE_NONE>; - interrupt-name = "short-irq"; + interrupt-names = "short-irq"; ti,ldo6-vibrator; -- GitLab From ed53f623476f3f3b46340d75b415205c79c72681 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 17:32:08 +0200 Subject: [PATCH 4547/9938] ARM: dts: omap5-cm-t54: DT spelling s/interrupt-name/interrupt-names/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5-cm-t54.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts index ecc591dc0778..467291d71e96 100644 --- a/arch/arm/boot/dts/omap5-cm-t54.dts +++ b/arch/arm/boot/dts/omap5-cm-t54.dts @@ -434,7 +434,7 @@ compatible = "ti,palmas-pmic"; interrupt-parent = <&palmas>; interrupts = <14 IRQ_TYPE_NONE>; - interrupt-name = "short-irq"; + interrupt-names = "short-irq"; ti,ldo6-vibrator; -- GitLab From 3023aa4ad8138066a69e25cf4d1b6880204e5e05 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Apr 2016 17:32:09 +0200 Subject: [PATCH 4548/9938] ARM: dts: OMAP36xx: : DT spelling s/#address-cell/#address-cells/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap36xx.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi index ce1e242d4dc0..8b7979153008 100644 --- a/arch/arm/boot/dts/omap36xx.dtsi +++ b/arch/arm/boot/dts/omap36xx.dtsi @@ -44,7 +44,7 @@ abb_mpu_iva: regulator-abb-mpu { compatible = "ti,abb-v1"; regulator-name = "abb_mpu_iva"; - #address-cell = <0>; + #address-cells = <0>; #size-cells = <0>; reg = <0x483072f0 0x8>, <0x48306818 0x4>; reg-names = "base-address", "int-address"; -- GitLab From e1ce726e1db2522b4848b3acffb7ece12439517c Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 26 Apr 2016 18:02:42 +0900 Subject: [PATCH 4549/9938] perf tools: Add lsdir() helper to read a directory As a utility function, add lsdir() which reads given directory and store entry name into a strlist. lsdir accepts a filter function so that user can filter out unneeded entries. Signed-off-by: Masami Hiramatsu Signed-off-by: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Cc: Hemant Kumar Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20160426090242.11891.79014.stgit@devbox [ Do not use the 'dirname' it is used in some distros ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/util.c | 34 ++++++++++++++++++++++++++++++++++ tools/perf/util/util.h | 3 +++ 2 files changed, 37 insertions(+) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index b7766c577b01..9473d46c00bb 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -117,6 +117,40 @@ int rm_rf(char *path) return rmdir(path); } +/* A filter which removes dot files */ +bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) +{ + return d->d_name[0] != '.'; +} + +/* lsdir reads a directory and store it in strlist */ +struct strlist *lsdir(const char *name, + bool (*filter)(const char *, struct dirent *)) +{ + struct strlist *list = NULL; + DIR *dir; + struct dirent *d; + + dir = opendir(name); + if (!dir) + return NULL; + + list = strlist__new(NULL, NULL); + if (!list) { + errno = -ENOMEM; + goto out; + } + + while ((d = readdir(dir)) != NULL) { + if (!filter || filter(name, d)) + strlist__add(list, d->d_name); + } + +out: + closedir(dir); + return list; +} + static int slow_copyfile(const char *from, const char *to) { int err = -1; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 3bf3de86d429..26a924651e7b 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -79,6 +79,7 @@ #include #include #include +#include "strlist.h" extern const char *graph_line; extern const char *graph_dotted_line; @@ -222,6 +223,8 @@ static inline int sane_case(int x, int high) int mkdir_p(char *path, mode_t mode); int rm_rf(char *path); +struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *)); +bool lsdir_no_dot_filter(const char *name, struct dirent *d); int copyfile(const char *from, const char *to); int copyfile_mode(const char *from, const char *to, mode_t mode); int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); -- GitLab From 6ed0720a74d90eea51284c07592369d45d56f1f7 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 26 Apr 2016 18:03:04 +0900 Subject: [PATCH 4550/9938] perf probe: Let probe_file__add_event return 0 if succeeded Since other methods return 0 if succeeded (or filedesc), let probe_file__add_event() return 0 instead of the length of written bytes. Signed-off-by: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Cc: Hemant Kumar Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20160426090303.11891.18232.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-file.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c index e3b3b92e4458..3fe6214970e6 100644 --- a/tools/perf/util/probe-file.c +++ b/tools/perf/util/probe-file.c @@ -220,8 +220,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev) pr_debug("Writing event: %s\n", buf); if (!probe_event_dry_run) { - ret = write(fd, buf, strlen(buf)); - if (ret <= 0) { + if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) { ret = -errno; pr_warning("Failed to write event: %s\n", strerror_r(errno, sbuf, sizeof(sbuf))); -- GitLab From 2a12ec13cc4ca8690ad2690c09bf8bff17c228d9 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 26 Apr 2016 18:04:13 +0900 Subject: [PATCH 4551/9938] perf probe: Set default kprobe group name if it is not given Set kprobe group name as "probe" if it is not given. Signed-off-by: Masami Hiramatsu Signed-off-by: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Cc: Hemant Kumar Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20160426090413.11891.95640.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 97b7f8e5fe69..0de5d10dda71 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -2748,9 +2748,13 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, { int ret; - if (pev->uprobes && !pev->group) { - /* Replace group name if not given */ - ret = convert_exec_to_group(pev->target, &pev->group); + if (!pev->group) { + /* Set group name if not given */ + if (!pev->uprobes) { + pev->group = strdup(PERFPROBE_GROUP); + ret = pev->group ? 0 : -ENOMEM; + } else + ret = convert_exec_to_group(pev->target, &pev->group); if (ret != 0) { pr_warning("Failed to make a group name.\n"); return ret; -- GitLab From 62de344e4fed23a42048c02dfa841f7d7ce9e88e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Apr 2016 11:03:03 -0300 Subject: [PATCH 4552/9938] perf trace: Move perf_flags beautifier to tools/perf/trace/beauty/ To reduce the size of builtin-trace.c. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-8r3gmymyn3r0ynt4yuzspp9g@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 45 +---------------------- tools/perf/trace/beauty/perf_event_open.c | 43 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 44 deletions(-) create mode 100644 tools/perf/trace/beauty/perf_event_open.c diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a4b133fac82b..903deda92d9e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -56,22 +56,6 @@ # define MSG_CMSG_CLOEXEC 0x40000000 #endif -#ifndef PERF_FLAG_FD_NO_GROUP -# define PERF_FLAG_FD_NO_GROUP (1UL << 0) -#endif - -#ifndef PERF_FLAG_FD_OUTPUT -# define PERF_FLAG_FD_OUTPUT (1UL << 1) -#endif - -#ifndef PERF_FLAG_PID_CGROUP -# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */ -#endif - -#ifndef PERF_FLAG_FD_CLOEXEC -# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */ -#endif - struct trace { struct perf_tool tool; struct syscalltbl *sctbl; @@ -674,34 +658,6 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags -static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, - struct syscall_arg *arg) -{ - int printed = 0, flags = arg->val; - - if (flags == 0) - return 0; - -#define P_FLAG(n) \ - if (flags & PERF_FLAG_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ - flags &= ~PERF_FLAG_##n; \ - } - - P_FLAG(FD_NO_GROUP); - P_FLAG(FD_OUTPUT); - P_FLAG(PID_CGROUP); - P_FLAG(FD_CLOEXEC); -#undef P_FLAG - - if (flags) - printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); - - return printed; -} - -#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags - static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, struct syscall_arg *arg) { @@ -894,6 +850,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, #include "trace/beauty/pid.c" #include "trace/beauty/mmap.c" #include "trace/beauty/mode_t.c" +#include "trace/beauty/perf_event_open.c" #include "trace/beauty/sched_policy.c" #include "trace/beauty/socket_type.c" #include "trace/beauty/waitid_options.c" diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c new file mode 100644 index 000000000000..311f09dd718d --- /dev/null +++ b/tools/perf/trace/beauty/perf_event_open.c @@ -0,0 +1,43 @@ +#ifndef PERF_FLAG_FD_NO_GROUP +# define PERF_FLAG_FD_NO_GROUP (1UL << 0) +#endif + +#ifndef PERF_FLAG_FD_OUTPUT +# define PERF_FLAG_FD_OUTPUT (1UL << 1) +#endif + +#ifndef PERF_FLAG_PID_CGROUP +# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */ +#endif + +#ifndef PERF_FLAG_FD_CLOEXEC +# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */ +#endif + +static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, + struct syscall_arg *arg) +{ + int printed = 0, flags = arg->val; + + if (flags == 0) + return 0; + +#define P_FLAG(n) \ + if (flags & PERF_FLAG_##n) { \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + flags &= ~PERF_FLAG_##n; \ + } + + P_FLAG(FD_NO_GROUP); + P_FLAG(FD_OUTPUT); + P_FLAG(PID_CGROUP); + P_FLAG(FD_CLOEXEC); +#undef P_FLAG + + if (flags) + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); + + return printed; +} + +#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags -- GitLab From ccd9b2a7f82b069b8e8ac892fd9c1c22e7b11eba Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Apr 2016 11:40:17 -0300 Subject: [PATCH 4553/9938] perf trace: Do not beautify the 'pid' parameter as a simple integer Leave it alone so that it ends up assigned to SCA_PID via its type, 'pid_t', that will look up the pid on the machine thread rb_tree and possibly find its COMM. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-r7dujgmhtxxfajuunpt1bkuo@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 903deda92d9e..48b00f042599 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1043,8 +1043,7 @@ static struct syscall_fmt { [1] = SCA_FILENAME, /* filename */ [2] = SCA_OPEN_FLAGS, /* flags */ }, }, { .name = "perf_event_open", .errmsg = true, - .arg_scnprintf = { [1] = SCA_INT, /* pid */ - [2] = SCA_INT, /* cpu */ + .arg_scnprintf = { [2] = SCA_INT, /* cpu */ [3] = SCA_FD, /* group_fd */ [4] = SCA_PERF_FLAGS, /* flags */ }, }, { .name = "pipe2", .errmsg = true, -- GitLab From 4bd112df3eea4db63fe90fb4e83c48d3f3bd6512 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Apr 2016 12:31:16 -0300 Subject: [PATCH 4554/9938] tools lib api fs: Add helper to read string from procfs file To read things like /proc/self/comm. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-ztpkbmseidt0hq2psr46o0h9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/api/fs/fs.c | 13 +++++++++++++ tools/lib/api/fs/fs.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c index ef78c22ff44d..08556cf2c70d 100644 --- a/tools/lib/api/fs/fs.c +++ b/tools/lib/api/fs/fs.c @@ -351,6 +351,19 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep) return err; } +int procfs__read_str(const char *entry, char **buf, size_t *sizep) +{ + char path[PATH_MAX]; + const char *procfs = procfs__mountpoint(); + + if (!procfs) + return -1; + + snprintf(path, sizeof(path), "%s/%s", procfs, entry); + + return filename__read_str(path, buf, sizep); +} + int sysfs__read_ull(const char *entry, unsigned long long *value) { char path[PATH_MAX]; diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h index 9f6598098dc5..16c9c2ed7c5b 100644 --- a/tools/lib/api/fs/fs.h +++ b/tools/lib/api/fs/fs.h @@ -29,6 +29,8 @@ int filename__read_int(const char *filename, int *value); int filename__read_ull(const char *filename, unsigned long long *value); int filename__read_str(const char *filename, char **buf, size_t *sizep); +int procfs__read_str(const char *entry, char **buf, size_t *sizep); + int sysctl__read_int(const char *sysctl, int *value); int sysfs__read_int(const char *entry, int *value); int sysfs__read_ull(const char *entry, unsigned long long *value); -- GitLab From 2f3027ac28bf6bc3ac7eb851eab06f2a38af5caa Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Apr 2016 12:32:50 -0300 Subject: [PATCH 4555/9938] perf thread: Introduce method to set comm from /proc/pid/self Will be used for lazy comm loading in 'perf trace'. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-7ogbkuoka1y2qsmcckqxvl5m@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.c | 19 +++++++++++++++++++ tools/perf/util/thread.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index de2036d1251b..45fcb715a36b 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -10,6 +10,8 @@ #include "comm.h" #include "unwind.h" +#include + int thread__init_map_groups(struct thread *thread, struct machine *machine) { struct thread *leader; @@ -153,6 +155,23 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, return 0; } +int thread__set_comm_from_proc(struct thread *thread) +{ + char path[64]; + char *comm = NULL; + size_t sz; + int err = -1; + + if (!(snprintf(path, sizeof(path), "%d/task/%d/comm", + thread->pid_, thread->tid) >= (int)sizeof(path)) && + procfs__read_str(path, &comm, &sz) == 0) { + comm[sz - 1] = '\0'; + err = thread__set_comm(thread, comm, 0); + } + + return err; +} + const char *thread__comm_str(const struct thread *thread) { const struct comm *comm = thread__comm(thread); diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index e214207bb13a..45fba13c800b 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -71,6 +71,8 @@ static inline int thread__set_comm(struct thread *thread, const char *comm, return __thread__set_comm(thread, comm, timestamp, false); } +int thread__set_comm_from_proc(struct thread *thread); + int thread__comm_len(struct thread *thread); struct comm *thread__comm(const struct thread *thread); struct comm *thread__exec_comm(const struct thread *thread); -- GitLab From 073e5fca53d30ffe9e2fc637a001c78b2cdca7dd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Apr 2016 12:33:46 -0300 Subject: [PATCH 4556/9938] perf trace: Read thread's COMM from /proc when not set We get notifications for threads that gets created while we're tracing, but for preexisting threads we may end not having synthesized them, like when tracing a 'perf trace' session that will use '--pid' to trace some other thread. And besides we should probably stop synthesizing those records and instead read thread information in a lazy way, i.e. just when we need, like done in this patch: Now the 'pid_t' argument in 'perf_event_open' gets translated to a COMM: # perf trace -e perf_event_open perf stat -e cycles -p 31601 0.027 ( 0.027 ms): perf/23393 perf_event_open(attr_uptr: 0x2fdd0d8, pid: 31601 (abrt-dump-journ), cpu: -1, group_fd: -1, flags: FD_CLOEXEC) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 3 ^C And in other syscalls containing pid_t without thread->comm_set at the time of the formatting. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-ioeps6dlwst17d6oozc9shtk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/trace/beauty/pid.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c index 111ae08d38f1..07486ea65ae3 100644 --- a/tools/perf/trace/beauty/pid.c +++ b/tools/perf/trace/beauty/pid.c @@ -3,9 +3,12 @@ static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_a int pid = arg->val; struct trace *trace = arg->trace; size_t printed = scnprintf(bf, size, "%d", pid); - struct thread *thread = machine__find_thread(trace->host, pid, pid); + struct thread *thread = machine__findnew_thread(trace->host, pid, pid); if (thread != NULL) { + if (!thread->comm_set) + thread__set_comm_from_proc(thread); + if (thread->comm_set) printed += scnprintf(bf + printed, size - printed, " (%s)", thread__comm_str(thread)); -- GitLab From 63a29613d7c69f17b6a3266bfc338986698b2546 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Tue, 26 Apr 2016 19:55:41 +0530 Subject: [PATCH 4557/9938] perf probe: Fix offline module name missmatch issue Perf can add a probe on kernel module which has not been loaded yet. The current implementation finds the module name from path. But if the filename is different from the actual module name then perf fails to register a probe while loading module because of mismatch in the names. For example, samples/kobject/kobject-example.ko is loaded as kobject_example. Before applying patch: $ sudo ./perf probe -m /linux/samples/kobject/kobject-example.ko foo_show Added new event: probe:foo_show (on foo_show in kobject-example) You can now use it in all perf tools, such as: perf record -e probe:foo_show -aR sleep 1 $ cat /sys/kernel/debug/tracing/kprobe_events p:probe/foo_show kobject-example:foo_show $ insmod kobject-example.ko $ lsmod Module Size Used by kobject_example 16384 0 Generate read to /sys/kernel/kobject_example/foo while recording data with below command $ sudo ./perf record -e probe:foo_show -a [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.093 MB perf.data ] $./perf report --stdio -F overhead,comm,dso,sym Error: The perf.data.old file has no samples! After applying patch: $ sudo ./perf probe -m /linux/samples/kobject/kobject-example.ko foo_show Added new event: probe:foo_show (on foo_show in kobject_example) You can now use it in all perf tools, such as: perf record -e probe:foo_show -aR sleep 1 $ sudo cat /sys/kernel/debug/tracing/kprobe_events p:probe/foo_show kobject_example:foo_show $ insmod kobject-example.ko $ lsmod Module Size Used by kobject_example 16384 0 Generate read to /sys/kernel/kobject_example/foo while recording data with below command $ sudo ./perf record -e probe:foo_show -a [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.097 MB perf.data (8 samples) ] $ sudo ./perf report --stdio -F overhead,comm,dso,sym ... # Samples: 8 of event 'probe:foo_show' # Event count (approx.): 8 # # Overhead Command Shared Object Symbol # ........ ....... ................. ............ # 100.00% cat [kobject_example] [k] foo_show Signed-off-by: Ravi Bangoria Acked-by: Masami Hiramatsu Cc: Alexander Shishkin Cc: Namhyung Kim Cc: Naveen N. Rao Cc: Peter Zijlstra Cc: Srikar Dronamraju Cc: Wang Nan Link: http://lkml.kernel.org/r/1461680741-12517-2-git-send-email-ravi.bangoria@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 0de5d10dda71..bc2eb7cda2d1 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -588,32 +588,23 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, int ntevs, const char *module) { int i, ret = 0; - char *tmp; + char *mod_name = NULL; if (!module) return 0; - tmp = strrchr(module, '/'); - if (tmp) { - /* This is a module path -- get the module name */ - module = strdup(tmp + 1); - if (!module) - return -ENOMEM; - tmp = strchr(module, '.'); - if (tmp) - *tmp = '\0'; - tmp = (char *)module; /* For free() */ - } + mod_name = find_module_name(module); for (i = 0; i < ntevs; i++) { - tevs[i].point.module = strdup(module); + tevs[i].point.module = + strdup(mod_name ? mod_name : module); if (!tevs[i].point.module) { ret = -ENOMEM; break; } } - free(tmp); + free(mod_name); return ret; } -- GitLab From c61fb959df898b994382d586046d7704476ff503 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Tue, 26 Apr 2016 19:55:40 +0530 Subject: [PATCH 4558/9938] perf probe: Fix module probe issue if no dwarf support Perf is not able to register probe in kernel module when dwarf supprt is not there(and so it goes for symtab). Perf passes full path of module where only module name is required which is causing the problem. This patch fixes this issue. Before applying patch: $ dpkg -s libdw-dev dpkg-query: package 'libdw-dev' is not installed and no information is... $ sudo ./perf probe -m /linux/samples/kprobes/kprobe_example.ko kprobe_init Added new event: probe:kprobe_init (on kprobe_init in /linux/samples/kprobes/kprobe_example.ko) You can now use it in all perf tools, such as: perf record -e probe:kprobe_init -aR sleep 1 $ sudo cat /sys/kernel/debug/tracing/kprobe_events p:probe/kprobe_init /linux/samples/kprobes/kprobe_example.ko:kprobe_init $ sudo ./perf record -a -e probe:kprobe_init [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.105 MB perf.data ] $ sudo ./perf script # No output here After applying patch: $ sudo ./perf probe -m /linux/samples/kprobes/kprobe_example.ko kprobe_init Added new event: probe:kprobe_init (on kprobe_init in kprobe_example) You can now use it in all perf tools, such as: perf record -e probe:kprobe_init -aR sleep 1 $ sudo cat /sys/kernel/debug/tracing/kprobe_events p:probe/kprobe_init kprobe_example:kprobe_init $ sudo ./perf record -a -e probe:kprobe_init [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.105 MB perf.data (2 samples) ] $ sudo ./perf script insmod 13990 [002] 5961.216833: probe:kprobe_init: ... insmod 13995 [002] 5962.889384: probe:kprobe_init: ... Signed-off-by: Ravi Bangoria Acked-by: Masami Hiramatsu Cc: Alexander Shishkin Cc: Namhyung Kim Cc: Naveen N. Rao Cc: Peter Zijlstra Cc: Srikar Dronamraju Cc: Wang Nan Link: http://lkml.kernel.org/r/1461680741-12517-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 76 +++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index bc2eb7cda2d1..a9774628c6f6 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -265,6 +265,65 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address) return true; } +/* + * NOTE: + * '.gnu.linkonce.this_module' section of kernel module elf directly + * maps to 'struct module' from linux/module.h. This section contains + * actual module name which will be used by kernel after loading it. + * But, we cannot use 'struct module' here since linux/module.h is not + * exposed to user-space. Offset of 'name' has remained same from long + * time, so hardcoding it here. + */ +#ifdef __LP64__ +#define MOD_NAME_OFFSET 24 +#else +#define MOD_NAME_OFFSET 12 +#endif + +/* + * @module can be module name of module file path. In case of path, + * inspect elf and find out what is actual module name. + * Caller has to free mod_name after using it. + */ +static char *find_module_name(const char *module) +{ + int fd; + Elf *elf; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + Elf_Data *data; + Elf_Scn *sec; + char *mod_name = NULL; + + fd = open(module, O_RDONLY); + if (fd < 0) + return NULL; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) + goto elf_err; + + if (gelf_getehdr(elf, &ehdr) == NULL) + goto ret_err; + + sec = elf_section_by_name(elf, &ehdr, &shdr, + ".gnu.linkonce.this_module", NULL); + if (!sec) + goto ret_err; + + data = elf_getdata(sec, NULL); + if (!data || !data->d_buf) + goto ret_err; + + mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET); + +ret_err: + elf_end(elf); +elf_err: + close(fd); + return mod_name; +} + #ifdef HAVE_DWARF_SUPPORT static int kernel_get_module_dso(const char *module, struct dso **pdso) @@ -2512,6 +2571,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, struct probe_trace_point *tp; int num_matched_functions; int ret, i, j, skipped = 0; + char *mod_name; map = get_target_map(pev->target, pev->uprobes); if (!map) { @@ -2596,9 +2656,19 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, tp->realname = strdup_or_goto(sym->name, nomem_out); tp->retprobe = pp->retprobe; - if (pev->target) - tev->point.module = strdup_or_goto(pev->target, - nomem_out); + if (pev->target) { + if (pev->uprobes) { + tev->point.module = strdup_or_goto(pev->target, + nomem_out); + } else { + mod_name = find_module_name(pev->target); + tev->point.module = + strdup(mod_name ? mod_name : pev->target); + free(mod_name); + if (!tev->point.module) + goto nomem_out; + } + } tev->uprobes = pev->uprobes; tev->nargs = pev->nargs; if (tev->nargs) { -- GitLab From 042a181086077bdb83e38626b35fb96adbe45039 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Apr 2016 12:58:45 -0300 Subject: [PATCH 4559/9938] perf tools: Update x86's syscall_64.tbl, adding preadv2 & pwritev2 Introduced in commit 4babf2c5efb7 ("x86: wire up preadv2 and pwritev2"). This will make 'perf trace' aware of them. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-vojoylgce2cetsy36446s5ny@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl index 2e5b565adacc..cac6d17ce5db 100644 --- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl @@ -333,6 +333,8 @@ 324 common membarrier sys_membarrier 325 common mlock2 sys_mlock2 326 common copy_file_range sys_copy_file_range +327 64 preadv2 sys_preadv2 +328 64 pwritev2 sys_pwritev2 # # x32-specific system call numbers start at 512 to avoid cache impact -- GitLab From fed2db99824334b3a7219da6b45d70f448449d7d Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 12 Apr 2016 08:30:43 -0700 Subject: [PATCH 4560/9938] i40e: Specify AQ event opcode to wait for To add a little flexibility to the nvmupdate facility, this code adds the ability to specify an AQ event opcode to wait on after the Exec_AQ request. Change-ID: Iddbfd63c3de8df3edb9d3e90678b08989bc4946e Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 49 ++++++++++++++++--- drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index f2cea3d25de3..954efe3118db 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -693,10 +693,10 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, /* early check for status command and debug msgs */ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); - i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n", + i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d opc 0x%04x cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n", i40e_nvm_update_state_str[upd_cmd], hw->nvmupd_state, - hw->nvm_release_on_done, + hw->nvm_release_on_done, hw->nvm_wait_opcode, cmd->command, cmd->config, cmd->offset, cmd->data_size); if (upd_cmd == I40E_NVMUPD_INVALID) { @@ -710,7 +710,18 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, * going into the state machine */ if (upd_cmd == I40E_NVMUPD_STATUS) { + if (!cmd->data_size) { + *perrno = -EFAULT; + return I40E_ERR_BUF_TOO_SHORT; + } + bytes[0] = hw->nvmupd_state; + + if (cmd->data_size >= 4) { + bytes[1] = 0; + *((u16 *)&bytes[2]) = hw->nvm_wait_opcode; + } + return 0; } @@ -729,6 +740,14 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, case I40E_NVMUPD_STATE_INIT_WAIT: case I40E_NVMUPD_STATE_WRITE_WAIT: + /* if we need to stop waiting for an event, clear + * the wait info and return before doing anything else + */ + if (cmd->offset == 0xffff) { + i40e_nvmupd_check_wait_event(hw, hw->nvm_wait_opcode); + return 0; + } + status = I40E_ERR_NOT_READY; *perrno = -EBUSY; break; @@ -800,6 +819,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, i40e_release_nvm(hw); } else { hw->nvm_release_on_done = true; + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_erase; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } } @@ -816,6 +836,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, i40e_release_nvm(hw); } else { hw->nvm_release_on_done = true; + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } } @@ -828,10 +849,12 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); - if (status) + if (status) { i40e_release_nvm(hw); - else + } else { + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update; hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT; + } } break; @@ -850,6 +873,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, i40e_release_nvm(hw); } else { hw->nvm_release_on_done = true; + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } } @@ -940,8 +964,10 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, switch (upd_cmd) { case I40E_NVMUPD_WRITE_CON: status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); - if (!status) + if (!status) { + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update; hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT; + } break; case I40E_NVMUPD_WRITE_LCB: @@ -954,6 +980,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; } else { hw->nvm_release_on_done = true; + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } break; @@ -967,6 +994,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, -EIO; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; } else { + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update; hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT; } break; @@ -981,6 +1009,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; } else { hw->nvm_release_on_done = true; + hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } break; @@ -1036,14 +1065,14 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, **/ void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode) { - if (opcode == i40e_aqc_opc_nvm_erase || - opcode == i40e_aqc_opc_nvm_update) { + if (opcode == hw->nvm_wait_opcode) { i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: clearing wait on opcode 0x%04x\n", opcode); if (hw->nvm_release_on_done) { i40e_release_nvm(hw); hw->nvm_release_on_done = false; } + hw->nvm_wait_opcode = 0; switch (hw->nvmupd_state) { case I40E_NVMUPD_STATE_INIT_WAIT: @@ -1220,6 +1249,12 @@ static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw, *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } + /* should we wait for a followup event? */ + if (cmd->offset) { + hw->nvm_wait_opcode = cmd->offset; + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; + } + return status; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 793036b259e5..bb57cd909c47 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -550,6 +550,7 @@ struct i40e_hw { struct i40e_aq_desc nvm_wb_desc; struct i40e_virt_mem nvm_buff; bool nvm_release_on_done; + u16 nvm_wait_opcode; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 4a78c18e0b7b..b72071363a8f 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -523,6 +523,7 @@ struct i40e_hw { struct i40e_aq_desc nvm_wb_desc; struct i40e_virt_mem nvm_buff; bool nvm_release_on_done; + u16 nvm_wait_opcode; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ -- GitLab From 43a3d9ba34c9ca313573201d3f45de5ab3494cec Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Tue, 12 Apr 2016 08:30:44 -0700 Subject: [PATCH 4561/9938] i40evf: Allow PF driver to configure RSS If the PF driver reports proper support, allow the PF driver to configure RSS on the behalf of the VF driver. This will allow for RSS support on future hardware without changes to the VF driver. Unfortunately, the old RSS code still needs to stay as the driver needs to be compatible with PF drivers that don't support this interface. But this change still simplifies the data structures a bunch and makes this code simpler to read and maintain. Change-ID: I0375aad40788ecdc0cb24d5cfeccf07804e69771 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf.h | 30 +- .../ethernet/intel/i40evf/i40evf_ethtool.c | 121 +++---- .../net/ethernet/intel/i40evf/i40evf_main.c | 308 ++++++------------ .../ethernet/intel/i40evf/i40evf_virtchnl.c | 119 +++++++ 4 files changed, 294 insertions(+), 284 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 017c83b6271f..63f7aae2c8ce 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -67,8 +67,6 @@ struct i40e_vsi { u16 rx_itr_setting; u16 tx_itr_setting; u16 qs_handle; - u8 *rss_hkey_user; /* User configured hash keys */ - u8 *rss_lut_user; /* User configured lookup table entries */ }; /* How many Rx Buffers do we bundle into one write to the hardware ? */ @@ -239,8 +237,13 @@ struct i40evf_adapter { #define I40EVF_FLAG_AQ_CONFIGURE_QUEUES BIT(6) #define I40EVF_FLAG_AQ_MAP_VECTORS BIT(7) #define I40EVF_FLAG_AQ_HANDLE_RESET BIT(8) -#define I40EVF_FLAG_AQ_CONFIGURE_RSS BIT(9) +#define I40EVF_FLAG_AQ_CONFIGURE_RSS BIT(9) /* direct AQ config */ #define I40EVF_FLAG_AQ_GET_CONFIG BIT(10) +/* Newer style, RSS done by the PF so we can ignore hardware vagaries. */ +#define I40EVF_FLAG_AQ_GET_HENA BIT(11) +#define I40EVF_FLAG_AQ_SET_HENA BIT(12) +#define I40EVF_FLAG_AQ_SET_RSS_KEY BIT(13) +#define I40EVF_FLAG_AQ_SET_RSS_LUT BIT(14) /* OS defined structs */ struct net_device *netdev; @@ -260,8 +263,14 @@ struct i40evf_adapter { (_a)->vf_res->vf_offload_flags & \ I40E_VIRTCHNL_VF_OFFLOAD_IWARP : \ 0) +/* RSS by the PF should be preferred over RSS via other methods. */ +#define RSS_PF(_a) ((_a)->vf_res->vf_offload_flags & \ + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) #define RSS_AQ(_a) ((_a)->vf_res->vf_offload_flags & \ I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ) +#define RSS_REG(_a) (!((_a)->vf_res->vf_offload_flags & \ + (I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ | \ + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF))) #define VLAN_ALLOWED(_a) ((_a)->vf_res->vf_offload_flags & \ I40E_VIRTCHNL_VF_OFFLOAD_VLAN) struct i40e_virtchnl_vf_resource *vf_res; /* incl. all VSIs */ @@ -273,6 +282,12 @@ struct i40evf_adapter { struct i40e_eth_stats current_stats; struct i40e_vsi vsi; u32 aq_wait_count; + /* RSS stuff */ + u64 hena; + u16 rss_key_size; + u16 rss_lut_size; + u8 *rss_key; + u8 *rss_lut; }; @@ -316,11 +331,12 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter); void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags); void i40evf_request_stats(struct i40evf_adapter *adapter); void i40evf_request_reset(struct i40evf_adapter *adapter); +void i40evf_get_hena(struct i40evf_adapter *adapter); +void i40evf_set_hena(struct i40evf_adapter *adapter); +void i40evf_set_rss_key(struct i40evf_adapter *adapter); +void i40evf_set_rss_lut(struct i40evf_adapter *adapter); void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, enum i40e_virtchnl_ops v_opcode, i40e_status v_retval, u8 *msg, u16 msglen); -int i40evf_config_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut, - u16 lut_size); -int i40evf_get_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut, - u16 lut_size); +int i40evf_config_rss(struct i40evf_adapter *adapter); #endif /* _I40EVF_H_ */ diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index dd4430aae7fa..9f7657c68688 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -387,20 +387,16 @@ static int i40evf_set_coalesce(struct net_device *netdev, static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter, struct ethtool_rxnfc *cmd) { - struct i40e_hw *hw = &adapter->hw; - u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) | - ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32); - /* We always hash on IP src and dest addresses */ cmd->data = RXH_IP_SRC | RXH_IP_DST; switch (cmd->flow_type) { case TCP_V4_FLOW: - if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP)) + if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP)) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; break; case UDP_V4_FLOW: - if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP)) + if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP)) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; break; @@ -412,11 +408,11 @@ static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter, break; case TCP_V6_FLOW: - if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP)) + if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP)) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; break; case UDP_V6_FLOW: - if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP)) + if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP)) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; break; @@ -476,9 +472,6 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, struct i40e_hw *hw = &adapter->hw; u32 flags = adapter->vf_res->vf_offload_flags; - u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) | - ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32); - /* RSS does not support anything other than hashing * to queues on src and dst IPs and ports */ @@ -495,10 +488,11 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, case TCP_V4_FLOW: if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) - hena |= + adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); - hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); + adapter->hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); } else { return -EINVAL; } @@ -506,10 +500,11 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, case TCP_V6_FLOW: if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) - hena |= + adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); - hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); + adapter->hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); } else { return -EINVAL; } @@ -517,11 +512,12 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, case UDP_V4_FLOW: if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) - hena |= + adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP); - hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | + adapter->hena |= + (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); } else { return -EINVAL; @@ -530,11 +526,12 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, case UDP_V6_FLOW: if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) - hena |= + adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP); - hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | + adapter->hena |= + (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); } else { return -EINVAL; @@ -547,7 +544,7 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, if ((nfc->data & RXH_L4_B_0_1) || (nfc->data & RXH_L4_B_2_3)) return -EINVAL; - hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER); + adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER); break; case AH_ESP_V6_FLOW: case AH_V6_FLOW: @@ -556,23 +553,27 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, if ((nfc->data & RXH_L4_B_0_1) || (nfc->data & RXH_L4_B_2_3)) return -EINVAL; - hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER); + adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER); break; case IPV4_FLOW: - hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); + adapter->hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | + BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); break; case IPV6_FLOW: - hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); + adapter->hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | + BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); break; default: return -EINVAL; } - wr32(hw, I40E_VFQF_HENA(0), (u32)hena); - wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); - i40e_flush(hw); + if (RSS_PF(adapter)) { + adapter->aq_required = I40EVF_FLAG_AQ_SET_HENA; + } else { + wr32(hw, I40E_VFQF_HENA(0), (u32)adapter->hena); + wr32(hw, I40E_VFQF_HENA(1), (u32)(adapter->hena >> 32)); + i40e_flush(hw); + } return 0; } @@ -623,6 +624,19 @@ static void i40evf_get_channels(struct net_device *netdev, ch->combined_count = adapter->num_active_queues; } +/** + * i40evf_get_rxfh_key_size - get the RSS hash key size + * @netdev: network interface device structure + * + * Returns the table size. + **/ +static u32 i40evf_get_rxfh_key_size(struct net_device *netdev) +{ + struct i40evf_adapter *adapter = netdev_priv(netdev); + + return adapter->rss_key_size; +} + /** * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size * @netdev: network interface device structure @@ -631,7 +645,9 @@ static void i40evf_get_channels(struct net_device *netdev, **/ static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev) { - return (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4; + struct i40evf_adapter *adapter = netdev_priv(netdev); + + return adapter->rss_lut_size; } /** @@ -646,9 +662,6 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) { struct i40evf_adapter *adapter = netdev_priv(netdev); - struct i40e_vsi *vsi = &adapter->vsi; - u8 *seed = NULL, *lut; - int ret; u16 i; if (hfunc) @@ -656,24 +669,13 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, if (!indir) return 0; - seed = key; - - lut = kzalloc(I40EVF_HLUT_ARRAY_SIZE, GFP_KERNEL); - if (!lut) - return -ENOMEM; - - ret = i40evf_get_rss(vsi, seed, lut, I40EVF_HLUT_ARRAY_SIZE); - if (ret) - goto out; + memcpy(key, adapter->rss_key, adapter->rss_key_size); /* Each 32 bits pointed by 'indir' is stored with a lut entry */ - for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++) - indir[i] = (u32)lut[i]; + for (i = 0; i < adapter->rss_lut_size; i++) + indir[i] = (u32)adapter->rss_lut[i]; -out: - kfree(lut); - - return ret; + return 0; } /** @@ -689,8 +691,6 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, const u8 hfunc) { struct i40evf_adapter *adapter = netdev_priv(netdev); - struct i40e_vsi *vsi = &adapter->vsi; - u8 *seed = NULL; u16 i; /* We do not allow change in unsupported parameters */ @@ -701,28 +701,14 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir, return 0; if (key) { - if (!vsi->rss_hkey_user) { - vsi->rss_hkey_user = kzalloc(I40EVF_HKEY_ARRAY_SIZE, - GFP_KERNEL); - if (!vsi->rss_hkey_user) - return -ENOMEM; - } - memcpy(vsi->rss_hkey_user, key, I40EVF_HKEY_ARRAY_SIZE); - seed = vsi->rss_hkey_user; - } - if (!vsi->rss_lut_user) { - vsi->rss_lut_user = kzalloc(I40EVF_HLUT_ARRAY_SIZE, - GFP_KERNEL); - if (!vsi->rss_lut_user) - return -ENOMEM; + memcpy(adapter->rss_key, key, adapter->rss_key_size); } /* Each 32 bits pointed by 'indir' is stored with a lut entry */ - for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++) - vsi->rss_lut_user[i] = (u8)(indir[i]); + for (i = 0; i < adapter->rss_lut_size; i++) + adapter->rss_lut[i] = (u8)(indir[i]); - return i40evf_config_rss(vsi, seed, vsi->rss_lut_user, - I40EVF_HLUT_ARRAY_SIZE); + return i40evf_config_rss(adapter); } /** @@ -794,6 +780,7 @@ static const struct ethtool_ops i40evf_ethtool_ops = { .get_rxfh = i40evf_get_rxfh, .set_rxfh = i40evf_set_rxfh, .get_channels = i40evf_get_channels, + .get_rxfh_key_size = i40evf_get_rxfh_key_size, }; /** diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 806da2686623..af53159010ab 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1224,24 +1224,18 @@ static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter) } /** - * i40e_config_rss_aq - Prepare for RSS using AQ commands - * @vsi: vsi structure - * @seed: RSS hash seed - * @lut: Lookup table - * @lut_size: Lookup table size + * i40e_config_rss_aq - Configure RSS keys and lut by using AQ commands + * @adapter: board private structure * * Return 0 on success, negative on failure **/ -static int i40evf_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed, - u8 *lut, u16 lut_size) +static int i40evf_config_rss_aq(struct i40evf_adapter *adapter) { - struct i40evf_adapter *adapter = vsi->back; + struct i40e_aqc_get_set_rss_key_data *rss_key = + (struct i40e_aqc_get_set_rss_key_data *)adapter->rss_key; struct i40e_hw *hw = &adapter->hw; int ret = 0; - if (!vsi->id) - return -EINVAL; - if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ dev_err(&adapter->pdev->dev, "Cannot configure RSS, command %d pending\n", @@ -1249,198 +1243,82 @@ static int i40evf_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed, return -EBUSY; } - if (seed) { - struct i40e_aqc_get_set_rss_key_data *rss_key = - (struct i40e_aqc_get_set_rss_key_data *)seed; - ret = i40evf_aq_set_rss_key(hw, vsi->id, rss_key); - if (ret) { - dev_err(&adapter->pdev->dev, "Cannot set RSS key, err %s aq_err %s\n", - i40evf_stat_str(hw, ret), - i40evf_aq_str(hw, hw->aq.asq_last_status)); - return ret; - } + ret = i40evf_aq_set_rss_key(hw, adapter->vsi.id, rss_key); + if (ret) { + dev_err(&adapter->pdev->dev, "Cannot set RSS key, err %s aq_err %s\n", + i40evf_stat_str(hw, ret), + i40evf_aq_str(hw, hw->aq.asq_last_status)); + return ret; + } - if (lut) { - ret = i40evf_aq_set_rss_lut(hw, vsi->id, false, lut, lut_size); - if (ret) { - dev_err(&adapter->pdev->dev, - "Cannot set RSS lut, err %s aq_err %s\n", - i40evf_stat_str(hw, ret), - i40evf_aq_str(hw, hw->aq.asq_last_status)); - return ret; - } + ret = i40evf_aq_set_rss_lut(hw, adapter->vsi.id, false, + adapter->rss_lut, adapter->rss_lut_size); + if (ret) { + dev_err(&adapter->pdev->dev, "Cannot set RSS lut, err %s aq_err %s\n", + i40evf_stat_str(hw, ret), + i40evf_aq_str(hw, hw->aq.asq_last_status)); } return ret; + } /** * i40evf_config_rss_reg - Configure RSS keys and lut by writing registers - * @vsi: Pointer to vsi structure - * @seed: RSS hash seed - * @lut: Lookup table - * @lut_size: Lookup table size + * @adapter: board private structure * * Returns 0 on success, negative on failure **/ -static int i40evf_config_rss_reg(struct i40e_vsi *vsi, const u8 *seed, - const u8 *lut, u16 lut_size) +static int i40evf_config_rss_reg(struct i40evf_adapter *adapter) { - struct i40evf_adapter *adapter = vsi->back; struct i40e_hw *hw = &adapter->hw; + u32 *dw; u16 i; - if (seed) { - u32 *seed_dw = (u32 *)seed; - - for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) - wr32(hw, I40E_VFQF_HKEY(i), seed_dw[i]); - } - - if (lut) { - u32 *lut_dw = (u32 *)lut; + dw = (u32 *)adapter->rss_key; + for (i = 0; i <= adapter->rss_key_size / 4; i++) + wr32(hw, I40E_VFQF_HKEY(i), dw[i]); - if (lut_size != I40EVF_HLUT_ARRAY_SIZE) - return -EINVAL; + dw = (u32 *)adapter->rss_lut; + for (i = 0; i <= adapter->rss_lut_size / 4; i++) + wr32(hw, I40E_VFQF_HLUT(i), dw[i]); - for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) - wr32(hw, I40E_VFQF_HLUT(i), lut_dw[i]); - } i40e_flush(hw); return 0; } -/** - * * i40evf_get_rss_aq - Get RSS keys and lut by using AQ commands - * @vsi: Pointer to vsi structure - * @seed: RSS hash seed - * @lut: Lookup table - * @lut_size: Lookup table size - * - * Return 0 on success, negative on failure - **/ -static int i40evf_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed, - u8 *lut, u16 lut_size) -{ - struct i40evf_adapter *adapter = vsi->back; - struct i40e_hw *hw = &adapter->hw; - int ret = 0; - - if (seed) { - ret = i40evf_aq_get_rss_key(hw, vsi->id, - (struct i40e_aqc_get_set_rss_key_data *)seed); - if (ret) { - dev_err(&adapter->pdev->dev, - "Cannot get RSS key, err %s aq_err %s\n", - i40evf_stat_str(hw, ret), - i40evf_aq_str(hw, hw->aq.asq_last_status)); - return ret; - } - } - - if (lut) { - ret = i40evf_aq_get_rss_lut(hw, vsi->id, false, lut, lut_size); - if (ret) { - dev_err(&adapter->pdev->dev, - "Cannot get RSS lut, err %s aq_err %s\n", - i40evf_stat_str(hw, ret), - i40evf_aq_str(hw, hw->aq.asq_last_status)); - return ret; - } - } - - return ret; -} - -/** - * * i40evf_get_rss_reg - Get RSS keys and lut by reading registers - * @vsi: Pointer to vsi structure - * @seed: RSS hash seed - * @lut: Lookup table - * @lut_size: Lookup table size - * - * Returns 0 on success, negative on failure - **/ -static int i40evf_get_rss_reg(struct i40e_vsi *vsi, const u8 *seed, - const u8 *lut, u16 lut_size) -{ - struct i40evf_adapter *adapter = vsi->back; - struct i40e_hw *hw = &adapter->hw; - u16 i; - - if (seed) { - u32 *seed_dw = (u32 *)seed; - - for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) - seed_dw[i] = rd32(hw, I40E_VFQF_HKEY(i)); - } - - if (lut) { - u32 *lut_dw = (u32 *)lut; - - if (lut_size != I40EVF_HLUT_ARRAY_SIZE) - return -EINVAL; - - for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) - lut_dw[i] = rd32(hw, I40E_VFQF_HLUT(i)); - } - - return 0; -} - /** * i40evf_config_rss - Configure RSS keys and lut - * @vsi: Pointer to vsi structure - * @seed: RSS hash seed - * @lut: Lookup table - * @lut_size: Lookup table size - * - * Returns 0 on success, negative on failure - **/ -int i40evf_config_rss(struct i40e_vsi *vsi, const u8 *seed, - u8 *lut, u16 lut_size) -{ - struct i40evf_adapter *adapter = vsi->back; - - if (RSS_AQ(adapter)) - return i40evf_config_rss_aq(vsi, seed, lut, lut_size); - else - return i40evf_config_rss_reg(vsi, seed, lut, lut_size); -} - -/** - * i40evf_get_rss - Get RSS keys and lut - * @vsi: Pointer to vsi structure - * @seed: RSS hash seed - * @lut: Lookup table - * @lut_size: Lookup table size + * @adapter: board private structure * * Returns 0 on success, negative on failure **/ -int i40evf_get_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut, u16 lut_size) +int i40evf_config_rss(struct i40evf_adapter *adapter) { - struct i40evf_adapter *adapter = vsi->back; - if (RSS_AQ(adapter)) - return i40evf_get_rss_aq(vsi, seed, lut, lut_size); - else - return i40evf_get_rss_reg(vsi, seed, lut, lut_size); + if (RSS_PF(adapter)) { + adapter->aq_required |= I40EVF_FLAG_AQ_SET_RSS_LUT | + I40EVF_FLAG_AQ_SET_RSS_KEY; + return 0; + } else if (RSS_AQ(adapter)) { + return i40evf_config_rss_aq(adapter); + } else { + return i40evf_config_rss_reg(adapter); + } } /** * i40evf_fill_rss_lut - Fill the lut with default values - * @lut: Lookup table to be filled with - * @rss_table_size: Lookup table size - * @rss_size: Range of queue number for hashing + * @adapter: board private structure **/ -static void i40evf_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size) +static void i40evf_fill_rss_lut(struct i40evf_adapter *adapter) { u16 i; - for (i = 0; i < rss_table_size; i++) - lut[i] = i % rss_size; + for (i = 0; i < adapter->rss_lut_size; i++) + adapter->rss_lut[i] = i % adapter->num_active_queues; } /** @@ -1451,42 +1329,25 @@ static void i40evf_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size) **/ static int i40evf_init_rss(struct i40evf_adapter *adapter) { - struct i40e_vsi *vsi = &adapter->vsi; struct i40e_hw *hw = &adapter->hw; - u8 seed[I40EVF_HKEY_ARRAY_SIZE]; - u64 hena; - u8 *lut; int ret; - /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */ - if (adapter->vf_res->vf_offload_flags & - I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) - hena = I40E_DEFAULT_RSS_HENA_EXPANDED; - else - hena = I40E_DEFAULT_RSS_HENA; - wr32(hw, I40E_VFQF_HENA(0), (u32)hena); - wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); + if (!RSS_PF(adapter)) { + /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */ + if (adapter->vf_res->vf_offload_flags & + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + adapter->hena = I40E_DEFAULT_RSS_HENA_EXPANDED; + else + adapter->hena = I40E_DEFAULT_RSS_HENA; - lut = kzalloc(I40EVF_HLUT_ARRAY_SIZE, GFP_KERNEL); - if (!lut) - return -ENOMEM; + wr32(hw, I40E_VFQF_HENA(0), (u32)adapter->hena); + wr32(hw, I40E_VFQF_HENA(1), (u32)(adapter->hena >> 32)); + } - /* Use user configured lut if there is one, otherwise use default */ - if (vsi->rss_lut_user) - memcpy(lut, vsi->rss_lut_user, I40EVF_HLUT_ARRAY_SIZE); - else - i40evf_fill_rss_lut(lut, I40EVF_HLUT_ARRAY_SIZE, - adapter->num_active_queues); + i40evf_fill_rss_lut(adapter); - /* Use user configured hash key if there is one, otherwise - * user default. - */ - if (vsi->rss_hkey_user) - memcpy(seed, vsi->rss_hkey_user, I40EVF_HKEY_ARRAY_SIZE); - else - netdev_rss_key_fill((void *)seed, I40EVF_HKEY_ARRAY_SIZE); - ret = i40evf_config_rss(vsi, seed, lut, I40EVF_HLUT_ARRAY_SIZE); - kfree(lut); + netdev_rss_key_fill((void *)adapter->rss_key, adapter->rss_key_size); + ret = i40evf_config_rss(adapter); return ret; } @@ -1601,19 +1462,16 @@ int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter) } /** - * i40evf_clear_rss_config_user - Clear user configurations of RSS - * @vsi: Pointer to VSI structure + * i40evf_free_rss - Free memory used by RSS structs + * @adapter: board private structure **/ -static void i40evf_clear_rss_config_user(struct i40e_vsi *vsi) +static void i40evf_free_rss(struct i40evf_adapter *adapter) { - if (!vsi) - return; - - kfree(vsi->rss_hkey_user); - vsi->rss_hkey_user = NULL; + kfree(adapter->rss_key); + adapter->rss_key = NULL; - kfree(vsi->rss_lut_user); - vsi->rss_lut_user = NULL; + kfree(adapter->rss_lut); + adapter->rss_lut = NULL; } /** @@ -1747,6 +1605,22 @@ static void i40evf_watchdog_task(struct work_struct *work) adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_RSS; goto watchdog_done; } + if (adapter->aq_required & I40EVF_FLAG_AQ_GET_HENA) { + i40evf_get_hena(adapter); + goto watchdog_done; + } + if (adapter->aq_required & I40EVF_FLAG_AQ_SET_HENA) { + i40evf_set_hena(adapter); + goto watchdog_done; + } + if (adapter->aq_required & I40EVF_FLAG_AQ_SET_RSS_KEY) { + i40evf_set_rss_key(adapter); + goto watchdog_done; + } + if (adapter->aq_required & I40EVF_FLAG_AQ_SET_RSS_LUT) { + i40evf_set_rss_lut(adapter); + goto watchdog_done; + } if (adapter->state == __I40EVF_RUNNING) i40evf_request_stats(adapter); @@ -2325,6 +2199,7 @@ int i40evf_process_config(struct i40evf_adapter *adapter) { struct i40e_virtchnl_vf_resource *vfres = adapter->vf_res; struct net_device *netdev = adapter->netdev; + struct i40e_vsi *vsi = &adapter->vsi; int i; /* got VF config message back from PF, now we can parse it */ @@ -2381,8 +2256,16 @@ int i40evf_process_config(struct i40evf_adapter *adapter) ITR_REG_TO_USEC(I40E_ITR_RX_DEF)); adapter->vsi.tx_itr_setting = (I40E_ITR_DYNAMIC | ITR_REG_TO_USEC(I40E_ITR_TX_DEF)); - adapter->vsi.netdev = adapter->netdev; - adapter->vsi.qs_handle = adapter->vsi_res->qset_handle; + vsi->netdev = adapter->netdev; + vsi->qs_handle = adapter->vsi_res->qset_handle; + if (vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) { + adapter->rss_key_size = vfres->rss_key_size; + adapter->rss_lut_size = vfres->rss_lut_size; + } else { + adapter->rss_key_size = I40EVF_HKEY_ARRAY_SIZE; + adapter->rss_lut_size = I40EVF_HLUT_ARRAY_SIZE; + } + return 0; } @@ -2578,6 +2461,11 @@ static void i40evf_init_task(struct work_struct *work) set_bit(__I40E_DOWN, &adapter->vsi.state); i40evf_misc_irq_enable(adapter); + adapter->rss_key = kzalloc(adapter->rss_key_size, GFP_KERNEL); + adapter->rss_lut = kzalloc(adapter->rss_lut_size, GFP_KERNEL); + if (!adapter->rss_key || !adapter->rss_lut) + goto err_mem; + if (RSS_AQ(adapter)) { adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS; mod_timer_pending(&adapter->watchdog_timer, jiffies + 1); @@ -2588,7 +2476,8 @@ static void i40evf_init_task(struct work_struct *work) restart: schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(30)); return; - +err_mem: + i40evf_free_rss(adapter); err_register: i40evf_free_misc_irq(adapter); err_sw_init: @@ -2870,8 +2759,7 @@ static void i40evf_remove(struct pci_dev *pdev) flush_scheduled_work(); - /* Clear user configurations for RSS */ - i40evf_clear_rss_config_user(&adapter->vsi); + i40evf_free_rss(adapter); if (hw->aq.asq.count) i40evf_shutdown_adminq(hw); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index 488e738f76c6..e62c56b5a141 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -681,6 +681,115 @@ void i40evf_request_stats(struct i40evf_adapter *adapter) /* if the request failed, don't lock out others */ adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN; } + +/** + * i40evf_get_hena + * @adapter: adapter structure + * + * Request hash enable capabilities from PF + **/ +void i40evf_get_hena(struct i40evf_adapter *adapter) +{ + if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { + /* bail because we already have a command pending */ + dev_err(&adapter->pdev->dev, "Cannot get RSS hash capabilities, command %d pending\n", + adapter->current_op); + return; + } + adapter->current_op = I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS; + adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_HENA; + i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS, + NULL, 0); +} + +/** + * i40evf_set_hena + * @adapter: adapter structure + * + * Request the PF to set our RSS hash capabilities + **/ +void i40evf_set_hena(struct i40evf_adapter *adapter) +{ + struct i40e_virtchnl_rss_hena vrh; + + if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { + /* bail because we already have a command pending */ + dev_err(&adapter->pdev->dev, "Cannot set RSS hash enable, command %d pending\n", + adapter->current_op); + return; + } + vrh.hena = adapter->hena; + adapter->current_op = I40E_VIRTCHNL_OP_SET_RSS_HENA; + adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_HENA; + i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_SET_RSS_HENA, + (u8 *)&vrh, sizeof(vrh)); +} + +/** + * i40evf_set_rss_key + * @adapter: adapter structure + * + * Request the PF to set our RSS hash key + **/ +void i40evf_set_rss_key(struct i40evf_adapter *adapter) +{ + struct i40e_virtchnl_rss_key *vrk; + int len; + + if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { + /* bail because we already have a command pending */ + dev_err(&adapter->pdev->dev, "Cannot set RSS key, command %d pending\n", + adapter->current_op); + return; + } + len = sizeof(struct i40e_virtchnl_rss_key) + + (adapter->rss_key_size * sizeof(u8)) - 1; + vrk = kzalloc(len, GFP_KERNEL); + if (!vrk) + return; + vrk->vsi_id = adapter->vsi.id; + vrk->key_len = adapter->rss_key_size; + memcpy(vrk->key, adapter->rss_key, adapter->rss_key_size); + + adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_RSS_KEY; + adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_KEY; + i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_RSS_KEY, + (u8 *)vrk, len); + kfree(vrk); +} + +/** + * i40evf_set_rss_lut + * @adapter: adapter structure + * + * Request the PF to set our RSS lookup table + **/ +void i40evf_set_rss_lut(struct i40evf_adapter *adapter) +{ + struct i40e_virtchnl_rss_lut *vrl; + int len; + + if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { + /* bail because we already have a command pending */ + dev_err(&adapter->pdev->dev, "Cannot set RSS LUT, command %d pending\n", + adapter->current_op); + return; + } + len = sizeof(struct i40e_virtchnl_rss_lut) + + (adapter->rss_lut_size * sizeof(u8)) - 1; + vrl = kzalloc(len, GFP_KERNEL); + if (!vrl) + return; + vrl->vsi_id = adapter->vsi.id; + vrl->lut_entries = adapter->rss_lut_size; + memcpy(vrl->lut, adapter->rss_lut, adapter->rss_lut_size); + adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_RSS_LUT; + adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_LUT; + i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_RSS_LUT, + (u8 *)vrl, len); + kfree(vrl); +} + /** * i40evf_request_reset * @adapter: adapter structure @@ -820,6 +929,16 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, if (v_opcode != adapter->current_op) return; break; + case I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS: { + struct i40e_virtchnl_rss_hena *vrh = + (struct i40e_virtchnl_rss_hena *)msg; + if (msglen == sizeof(*vrh)) + adapter->hena = vrh->hena; + else + dev_warn(&adapter->pdev->dev, + "Invalid message %d from PF\n", v_opcode); + } + break; default: if (v_opcode != adapter->current_op) dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n", -- GitLab From c2a218c63ba36946aca5943c0c8ebd3a42e3dc4b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Apr 2016 13:27:23 -0300 Subject: [PATCH 4562/9938] perf bench: Remove one more die() call Propagate the error instead. Cc: David Ahern Cc: Hitoshi Mitake Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-z6erjg35d1gekevwujoa0223@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/mem-functions.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c index a91aa85d80ff..2b54d0f2672a 100644 --- a/tools/perf/bench/mem-functions.c +++ b/tools/perf/bench/mem-functions.c @@ -6,6 +6,7 @@ * Written by Hitoshi Mitake */ +#include "debug.h" #include "../perf.h" #include "../util/util.h" #include @@ -63,14 +64,16 @@ static struct perf_event_attr cycle_attr = { .config = PERF_COUNT_HW_CPU_CYCLES }; -static void init_cycles(void) +static int init_cycles(void) { cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag()); - if (cycles_fd < 0 && errno == ENOSYS) - die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); - else - BUG_ON(cycles_fd < 0); + if (cycles_fd < 0 && errno == ENOSYS) { + pr_debug("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); + return -1; + } + + return cycles_fd; } static u64 get_cycles(void) @@ -155,8 +158,13 @@ static int bench_mem_common(int argc, const char **argv, struct bench_mem_info * argc = parse_options(argc, argv, options, info->usage, 0); - if (use_cycles) - init_cycles(); + if (use_cycles) { + i = init_cycles(); + if (i < 0) { + fprintf(stderr, "Failed to open cycles counter\n"); + return i; + } + } size = (size_t)perf_atoll((char *)size_str); size_total = (double)size * nr_loops; -- GitLab From 4e0def887d717598ae8062b46e55f9e00d3a5783 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 10:47:56 +0100 Subject: [PATCH 4563/9938] dmaengine: pxa_dma: remove duplicate const qualifier Signed-off-by: Eric Engestrom Acked-by: Robert Jarzmik Signed-off-by: Vinod Koul --- drivers/dma/pxa_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 6d17dfd67881..e756a30ccba2 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -1333,7 +1333,7 @@ static int pxad_init_phys(struct platform_device *op, return 0; } -static const struct of_device_id const pxad_dt_ids[] = { +static const struct of_device_id pxad_dt_ids[] = { { .compatible = "marvell,pdma-1.0", }, {} }; -- GitLab From 2ab8e744a437d39619b323d7303fa2e6513274b2 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 26 Apr 2016 17:06:20 +0100 Subject: [PATCH 4564/9938] ASoC: arizona: No need to update_bits when writing AEC clock control The bits in the ARIZONA_CLOCK_CONTROL register only respond to writes of a '1', a write of '0' is ignored. So there's no need to use update_bits. We can do a simple write to set bits. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 0caecc6f78df..0239639823b1 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1124,7 +1124,6 @@ int arizona_anc_ev(struct snd_soc_dapm_widget *w, int event) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); - unsigned int mask = 0x3 << w->shift; unsigned int val; switch (event) { @@ -1138,7 +1137,7 @@ int arizona_anc_ev(struct snd_soc_dapm_widget *w, return 0; } - snd_soc_update_bits(codec, ARIZONA_CLOCK_CONTROL, mask, val); + snd_soc_write(codec, ARIZONA_CLOCK_CONTROL, val); return 0; } -- GitLab From 358158014f3b20c68e5f33caa032cfdb58a06bcf Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 28 Mar 2016 18:23:00 +0900 Subject: [PATCH 4565/9938] dt-bindings: gk20a: Fix typo in compatible name The correct compatible name is "nvidia,gk20a". Signed-off-by: Alexandre Courbot Acked-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt index 23bfe8e1f7cc..914f0ff4020e 100644 --- a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt +++ b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt @@ -1,9 +1,9 @@ NVIDIA GK20A Graphics Processing Unit Required properties: -- compatible: "nvidia,-" +- compatible: "nvidia," Currently recognized values: - - nvidia,tegra124-gk20a + - nvidia,gk20a - reg: Physical base address and length of the controller's registers. Must contain two entries: - first entry for bar0 -- GitLab From 375d2447029fc6092ca6d08329c1af61901dd8b6 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 28 Mar 2016 18:23:01 +0900 Subject: [PATCH 4566/9938] dt-bindings: gk20a: Document iommus property GK20A can optionally make use of an IOMMU. Signed-off-by: Alexandre Courbot Acked-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt index 914f0ff4020e..1e3748337319 100644 --- a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt +++ b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt @@ -24,6 +24,9 @@ Required properties: - reset-names: Must include the following entries: - gpu +Optional properties: +- iommus: A reference to the IOMMU. See ../iommu/iommu.txt for details. + Example: gpu@0,57000000 { @@ -39,5 +42,6 @@ Example: clock-names = "gpu", "pwr"; resets = <&tegra_car 184>; reset-names = "gpu"; + iommus = <&mc TEGRA_SWGROUP_GPU>; status = "disabled"; }; -- GitLab From 53cafb93da6fdafc5904c27a3da83123e72e7c13 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 28 Mar 2016 18:23:02 +0900 Subject: [PATCH 4567/9938] dt-bindings: Add documentation for GM20B GPU GM20B's definition is mostly similar to GK20A's, but requires an additional clock. Signed-off-by: Alexandre Courbot Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../devicetree/bindings/gpu/nvidia,gk20a.txt | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt index 1e3748337319..ff3db65e50de 100644 --- a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt +++ b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt @@ -1,9 +1,10 @@ -NVIDIA GK20A Graphics Processing Unit +NVIDIA Tegra Graphics Processing Units Required properties: - compatible: "nvidia," Currently recognized values: - nvidia,gk20a + - nvidia,gm20b - reg: Physical base address and length of the controller's registers. Must contain two entries: - first entry for bar0 @@ -19,6 +20,9 @@ Required properties: - clock-names: Must include the following entries: - gpu - pwr +If the compatible string is "nvidia,gm20b", then the following clock +is also required: + - ref - resets: Must contain an entry for each entry in reset-names. See ../reset/reset.txt for details. - reset-names: Must include the following entries: @@ -27,9 +31,9 @@ Required properties: Optional properties: - iommus: A reference to the IOMMU. See ../iommu/iommu.txt for details. -Example: +Example for GK20A: - gpu@0,57000000 { + gpu@57000000 { compatible = "nvidia,gk20a"; reg = <0x0 0x57000000 0x0 0x01000000>, <0x0 0x58000000 0x0 0x01000000>; @@ -45,3 +49,22 @@ Example: iommus = <&mc TEGRA_SWGROUP_GPU>; status = "disabled"; }; + +Example for GM20B: + + gpu@57000000 { + compatible = "nvidia,gm20b"; + reg = <0x0 0x57000000 0x0 0x01000000>, + <0x0 0x58000000 0x0 0x01000000>; + interrupts = , + ; + interrupt-names = "stall", "nonstall"; + clocks = <&tegra_car TEGRA210_CLK_GPU>, + <&tegra_car TEGRA210_CLK_PLL_P_OUT5>, + <&tegra_car TEGRA210_CLK_PLL_G_REF>; + clock-names = "gpu", "pwr", "ref"; + resets = <&tegra_car 184>; + reset-names = "gpu"; + iommus = <&mc TEGRA_SWGROUP_GPU>; + status = "disabled"; + }; -- GitLab From 4a0778e98f31709ab3c2dcb19b56a6dc7f44241a Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 28 Mar 2016 18:23:03 +0900 Subject: [PATCH 4568/9938] arm64: tegra: Add reference clock to GM20B on Tegra210 This clock is required for the GPU to operate. Signed-off-by: Alexandre Courbot Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 23b0630602cf..687d354439ea 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -226,8 +226,9 @@ ; interrupt-names = "stall", "nonstall"; clocks = <&tegra_car TEGRA210_CLK_GPU>, - <&tegra_car TEGRA210_CLK_PLL_P_OUT5>; - clock-names = "gpu", "pwr"; + <&tegra_car TEGRA210_CLK_PLL_P_OUT5>, + <&tegra_car TEGRA210_CLK_PLL_G_REF>; + clock-names = "gpu", "pwr", "ref"; resets = <&tegra_car 184>; reset-names = "gpu"; status = "disabled"; -- GitLab From e0341f1732237777d65bdda7184ea4b11fb31d53 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 26 Apr 2016 11:36:42 -0500 Subject: [PATCH 4569/9938] regulator: tps65917/palmas: Add bypass "On" value When commit b554e1450658 ("regulator: tps65917/palmas: Add bypass ops for LDOs with bypass capability") introduced bypass capability to palmas regulator, it went with the assumption that regulator regmap helpers just check val against the bypass_mask. Unfortunately, this ignored the explicit "on" and "off" values when the register value is masked with bypass_mask in commit ca5d1b3524b4 ("regulator: helpers: Modify helpers enabling multi-bit control"). With the recent commit dd1a571daee7 ("regulator: helpers: Ensure bypass register field matches ON value"), this issue gets highlighted and fails tps65917/palmas based platforms which need regulators/ldos that have bypass capability. Introduce the bypass_on value appropriately for tps65917/palmas regulator. Fixes: b554e1450658 ("regulator: tps65917/palmas: Add bypass ops for LDOs with bypass capability") Cc: Keerthy Cc: Mark Brown Signed-off-by: Nishanth Menon Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 6efc7ee8aea3..c83e06b2cedb 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -944,6 +944,8 @@ static int palmas_ldo_registration(struct palmas_pmic *pmic, if (id == PALMAS_REG_LDO9) { desc->ops = &palmas_ops_ldo9; desc->bypass_reg = desc->enable_reg; + desc->bypass_val_on = + PALMAS_LDO9_CTRL_LDO_BYPASS_EN; desc->bypass_mask = PALMAS_LDO9_CTRL_LDO_BYPASS_EN; } @@ -1055,6 +1057,8 @@ static int tps65917_ldo_registration(struct palmas_pmic *pmic, id == TPS65917_REG_LDO2) { desc->ops = &tps65917_ops_ldo_1_2; desc->bypass_reg = desc->enable_reg; + desc->bypass_val_on = + TPS65917_LDO1_CTRL_BYPASS_EN; desc->bypass_mask = TPS65917_LDO1_CTRL_BYPASS_EN; } @@ -1206,6 +1210,7 @@ static int palmas_smps_registration(struct palmas_pmic *pmic, desc->enable_mask = SMPS10_BOOST_EN; desc->bypass_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, PALMAS_SMPS10_CTRL); + desc->bypass_val_on = SMPS10_BYPASS_EN; desc->bypass_mask = SMPS10_BYPASS_EN; desc->min_uV = 3750000; desc->uV_step = 1250000; -- GitLab From 30f949bc6682d4912dbc74e7e757c66b3e3a6469 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 28 Mar 2016 18:23:04 +0900 Subject: [PATCH 4570/9938] arm64: tegra: Add IOMMU node to GM20B on Tegra210 The operating system driver can take advantage of the IOMMU to remove the need for physically contiguous memory buffers. Signed-off-by: Alexandre Courbot Signed-off-by: Thierry Reding --- arch/arm64/boot/dts/nvidia/tegra210.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 687d354439ea..d0b426b9aeaf 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -231,6 +231,9 @@ clock-names = "gpu", "pwr", "ref"; resets = <&tegra_car 184>; reset-names = "gpu"; + + iommus = <&mc TEGRA_SWGROUP_GPU>; + status = "disabled"; }; -- GitLab From 54d03c5d8b2a8af15b25e748fa9bc6e572060125 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 20 Apr 2016 03:18:39 -0500 Subject: [PATCH 4571/9938] ARM: dts: AM57xx/DRA7: Update SoC voltage rail limits to match data sheet As per the data sheet starting from SPRUHQ0H (Nov 2015 - Latest[1]), VDD_CORE can vary from 0.85v to 1.15v for AVS class0. VDD GPU/DSP et.al. can range from 0.85v to 1.25V with AVS class0 Since dynamic voltage scaling is disabled for DRA7/AM57xx SoCs for all SoC rails other than MPU, the bootloader is responsible for setting up the AVS class0 voltage, however, with wrong voltage machine constraints in dtb, regulator framework will lower the voltage below the required voltage levels for certain samples in production flow. This can cause catastrophic failures which can be pretty hard to identify. Update board files which don't match required specification. [1] http://www.ti.com/product/AM5728/datasheet/specifications#SPRT637-7340 Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 4 ++-- arch/arm/boot/dts/dra7-evm.dts | 4 ++-- arch/arm/boot/dts/dra72-evm-common.dtsi | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 75d04b1bbd1b..779466e18d34 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -438,7 +438,7 @@ /* VDD_DSPEVE, VDD_IVA, VDD_GPU */ regulator-name = "smps45"; regulator-min-microvolt = < 850000>; - regulator-max-microvolt = <1150000>; + regulator-max-microvolt = <1250000>; regulator-always-on; regulator-boot-on; }; @@ -447,7 +447,7 @@ /* VDD_CORE */ regulator-name = "smps6"; regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1030000>; + regulator-max-microvolt = <1150000>; regulator-always-on; regulator-boot-on; }; diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index d272cf140197..e94cbb7dd3c5 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -431,7 +431,7 @@ /* VDD_DSPEVE */ regulator-name = "smps45"; regulator-min-microvolt = < 850000>; - regulator-max-microvolt = <1150000>; + regulator-max-microvolt = <1250000>; regulator-always-on; regulator-boot-on; }; @@ -449,7 +449,7 @@ /* CORE_VDD */ regulator-name = "smps7"; regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1060000>; + regulator-max-microvolt = <1150000>; regulator-always-on; regulator-boot-on; }; diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi index 2c880501ba2e..874bdf1db306 100644 --- a/arch/arm/boot/dts/dra72-evm-common.dtsi +++ b/arch/arm/boot/dts/dra72-evm-common.dtsi @@ -328,7 +328,7 @@ /* VDD_CORE */ regulator-name = "smps2"; regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1060000>; + regulator-max-microvolt = <1150000>; regulator-boot-on; regulator-always-on; }; -- GitLab From 86f196f87fbd549a3114c81a95ba49d7daeab845 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 25 Apr 2016 15:53:54 +0300 Subject: [PATCH 4572/9938] ARM: dts: dra7xx: Fix compatible string for PCF8575 chip The boards use a TI variant of the PCF8575 so specify that in the compatible string. Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7-evm.dts | 6 +++--- arch/arm/boot/dts/dra72-evm-common.dtsi | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index e94cbb7dd3c5..cf4e62174f3c 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -556,7 +556,7 @@ }; pcf_lcd: gpio@20 { - compatible = "nxp,pcf8575"; + compatible = "ti,pcf8575", "nxp,pcf8575"; reg = <0x20>; gpio-controller; #gpio-cells = <2>; @@ -567,7 +567,7 @@ }; pcf_gpio_21: gpio@21 { - compatible = "nxp,pcf8575"; + compatible = "ti,pcf8575", "nxp,pcf8575"; reg = <0x21>; lines-initial-states = <0x1408>; gpio-controller; @@ -601,7 +601,7 @@ clock-frequency = <400000>; pcf_hdmi: gpio@26 { - compatible = "nxp,pcf8575"; + compatible = "ti,pcf8575", "nxp,pcf8575"; reg = <0x26>; gpio-controller; #gpio-cells = <2>; diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi index 874bdf1db306..fd56f1fb7f10 100644 --- a/arch/arm/boot/dts/dra72-evm-common.dtsi +++ b/arch/arm/boot/dts/dra72-evm-common.dtsi @@ -408,7 +408,7 @@ }; pcf_gpio_21: gpio@21 { - compatible = "nxp,pcf8575"; + compatible = "ti,pcf8575", "nxp,pcf8575"; reg = <0x21>; lines-initial-states = <0x1408>; gpio-controller; @@ -440,7 +440,7 @@ clock-frequency = <400000>; pcf_hdmi: pcf8575@26 { - compatible = "nxp,pcf8575"; + compatible = "ti,pcf8575", "nxp,pcf8575"; reg = <0x26>; gpio-controller; #gpio-cells = <2>; -- GitLab From 80014ad5d59cc5a141b21f46371b81736de1c44a Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 10:31:45 +0200 Subject: [PATCH 4573/9938] dt-bindings: pci: add DT binding for Marvell Armada 7K/8K PCIe controller This commit adds the Device Tree binding documentation that allows to describe the PCIe controller found in Marvell Armada 7K/8K SoCs. Signed-off-by: Thomas Petazzoni Acked-by: Rob Herring Signed-off-by: Bjorn Helgaas --- .../devicetree/bindings/pci/pci-armada8k.txt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/pci-armada8k.txt diff --git a/Documentation/devicetree/bindings/pci/pci-armada8k.txt b/Documentation/devicetree/bindings/pci/pci-armada8k.txt new file mode 100644 index 000000000000..598533a57d79 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/pci-armada8k.txt @@ -0,0 +1,38 @@ +* Marvell Armada 7K/8K PCIe interface + +This PCIe host controller is based on the Synopsis Designware PCIe IP +and thus inherits all the common properties defined in designware-pcie.txt. + +Required properties: +- compatible: "marvell,armada8k-pcie" +- reg: must contain two register regions + - the control register region + - the config space region +- reg-names: + - "ctrl" for the control register region + - "config" for the config space region +- interrupts: Interrupt specifier for the PCIe controler +- clocks: reference to the PCIe controller clock + +Example: + + pcie@f2600000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2600000 0 0x10000>, <0 0xf6f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = <0x81000000 0 0xf9000000 0 0xf9000000 0 0x10000 /* downstream I/O */ + 0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>; /* non-prefetchable memory */ + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; + num-lanes = <1>; + clocks = <&cpm_syscon0 1 13>; + status = "disabled"; + }; -- GitLab From 1c52a5139fcf3cebfd61be9293bc0da529968c0d Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Apr 2016 10:31:46 +0200 Subject: [PATCH 4574/9938] PCI: armada: Add driver for Marvell Armada 7K/8K PCIe controller The Marvell Armada 7K/8K SoCs integrate a PCIe controller from Synopsys. Add a new driver that provides the small glue needed to use the existing Designware driver to make it work on Marvell Armada 7K/8K SoCs. The MSI support will be enabled at a later point. [bhelgaas: use dev_dbg(), dw_pcie_wait_for_link()] Signed-off-by: Thomas Petazzoni Signed-off-by: Bjorn Helgaas --- drivers/pci/host/Kconfig | 11 ++ drivers/pci/host/Makefile | 1 + drivers/pci/host/pcie-armada8k.c | 262 +++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 drivers/pci/host/pcie-armada8k.c diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 7a0780d56d2d..a3b6f24be7c5 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -231,4 +231,15 @@ config PCI_HOST_THUNDER_ECAM help Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs. +config PCIE_ARMADA_8K + bool "Marvell Armada-8K PCIe controller" + depends on ARCH_MVEBU + select PCIE_DW + select PCIEPORTBUS + help + Say Y here if you want to enable PCIe controller support on + Armada-8K SoCs. The PCIe controller on Armada-8K is based on + Designware hardware and therefore the driver re-uses the + Designware core functions to implement the driver. + endmenu diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index d85b5faf9bbc..a6f85e3987c0 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -28,3 +28,4 @@ obj-$(CONFIG_PCI_HISI) += pcie-hisi.o obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o +obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o diff --git a/drivers/pci/host/pcie-armada8k.c b/drivers/pci/host/pcie-armada8k.c new file mode 100644 index 000000000000..55723567b5d4 --- /dev/null +++ b/drivers/pci/host/pcie-armada8k.c @@ -0,0 +1,262 @@ +/* + * PCIe host controller driver for Marvell Armada-8K SoCs + * + * Armada-8K PCIe Glue Layer Source Code + * + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie-designware.h" + +struct armada8k_pcie { + void __iomem *base; + struct clk *clk; + struct pcie_port pp; +}; + +#define PCIE_VENDOR_REGS_OFFSET 0x8000 + +#define PCIE_GLOBAL_CONTROL_REG 0x0 +#define PCIE_APP_LTSSM_EN BIT(2) +#define PCIE_DEVICE_TYPE_SHIFT 4 +#define PCIE_DEVICE_TYPE_MASK 0xF +#define PCIE_DEVICE_TYPE_RC 0x4 /* Root complex */ + +#define PCIE_GLOBAL_STATUS_REG 0x8 +#define PCIE_GLB_STS_RDLH_LINK_UP BIT(1) +#define PCIE_GLB_STS_PHY_LINK_UP BIT(9) + +#define PCIE_GLOBAL_INT_CAUSE1_REG 0x1C +#define PCIE_GLOBAL_INT_MASK1_REG 0x20 +#define PCIE_INT_A_ASSERT_MASK BIT(9) +#define PCIE_INT_B_ASSERT_MASK BIT(10) +#define PCIE_INT_C_ASSERT_MASK BIT(11) +#define PCIE_INT_D_ASSERT_MASK BIT(12) + +#define PCIE_ARCACHE_TRC_REG 0x50 +#define PCIE_AWCACHE_TRC_REG 0x54 +#define PCIE_ARUSER_REG 0x5C +#define PCIE_AWUSER_REG 0x60 +/* + * AR/AW Cache defauls: Normal memory, Write-Back, Read / Write + * allocate + */ +#define ARCACHE_DEFAULT_VALUE 0x3511 +#define AWCACHE_DEFAULT_VALUE 0x5311 + +#define DOMAIN_OUTER_SHAREABLE 0x2 +#define AX_USER_DOMAIN_MASK 0x3 +#define AX_USER_DOMAIN_SHIFT 4 + +#define to_armada8k_pcie(x) container_of(x, struct armada8k_pcie, pp) + +static int armada8k_pcie_link_up(struct pcie_port *pp) +{ + struct armada8k_pcie *pcie = to_armada8k_pcie(pp); + u32 reg; + u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP; + + reg = readl(pcie->base + PCIE_GLOBAL_STATUS_REG); + + if ((reg & mask) == mask) + return 1; + + dev_dbg(pp->dev, "No link detected (Global-Status: 0x%08x).\n", reg); + return 0; +} + +static void armada8k_pcie_establish_link(struct pcie_port *pp) +{ + struct armada8k_pcie *pcie = to_armada8k_pcie(pp); + void __iomem *base = pcie->base; + u32 reg; + + if (!dw_pcie_link_up(pp)) { + /* Disable LTSSM state machine to enable configuration */ + reg = readl(base + PCIE_GLOBAL_CONTROL_REG); + reg &= ~(PCIE_APP_LTSSM_EN); + writel(reg, base + PCIE_GLOBAL_CONTROL_REG); + } + + /* Set the device to root complex mode */ + reg = readl(base + PCIE_GLOBAL_CONTROL_REG); + reg &= ~(PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_SHIFT); + reg |= PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_SHIFT; + writel(reg, base + PCIE_GLOBAL_CONTROL_REG); + + /* Set the PCIe master AxCache attributes */ + writel(ARCACHE_DEFAULT_VALUE, base + PCIE_ARCACHE_TRC_REG); + writel(AWCACHE_DEFAULT_VALUE, base + PCIE_AWCACHE_TRC_REG); + + /* Set the PCIe master AxDomain attributes */ + reg = readl(base + PCIE_ARUSER_REG); + reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT); + reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT; + writel(reg, base + PCIE_ARUSER_REG); + + reg = readl(base + PCIE_AWUSER_REG); + reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT); + reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT; + writel(reg, base + PCIE_AWUSER_REG); + + /* Enable INT A-D interrupts */ + reg = readl(base + PCIE_GLOBAL_INT_MASK1_REG); + reg |= PCIE_INT_A_ASSERT_MASK | PCIE_INT_B_ASSERT_MASK | + PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK; + writel(reg, base + PCIE_GLOBAL_INT_MASK1_REG); + + if (!dw_pcie_link_up(pp)) { + /* Configuration done. Start LTSSM */ + reg = readl(base + PCIE_GLOBAL_CONTROL_REG); + reg |= PCIE_APP_LTSSM_EN; + writel(reg, base + PCIE_GLOBAL_CONTROL_REG); + } + + /* Wait until the link becomes active again */ + if (dw_pcie_wait_for_link(pp)) + dev_err(pp->dev, "Link not up after reconfiguration\n"); +} + +static void armada8k_pcie_host_init(struct pcie_port *pp) +{ + dw_pcie_setup_rc(pp); + armada8k_pcie_establish_link(pp); +} + +static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg) +{ + struct pcie_port *pp = arg; + struct armada8k_pcie *pcie = to_armada8k_pcie(pp); + void __iomem *base = pcie->base; + u32 val; + + /* + * Interrupts are directly handled by the device driver of the + * PCI device. However, they are also latched into the PCIe + * controller, so we simply discard them. + */ + val = readl(base + PCIE_GLOBAL_INT_CAUSE1_REG); + writel(val, base + PCIE_GLOBAL_INT_CAUSE1_REG); + + return IRQ_HANDLED; +} + +static struct pcie_host_ops armada8k_pcie_host_ops = { + .link_up = armada8k_pcie_link_up, + .host_init = armada8k_pcie_host_init, +}; + +static int armada8k_add_pcie_port(struct pcie_port *pp, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret; + + pp->root_bus_nr = -1; + pp->ops = &armada8k_pcie_host_ops; + + pp->irq = platform_get_irq(pdev, 0); + if (!pp->irq) { + dev_err(dev, "failed to get irq for port\n"); + return -ENODEV; + } + + ret = devm_request_irq(dev, pp->irq, armada8k_pcie_irq_handler, + IRQF_SHARED, "armada8k-pcie", pp); + if (ret) { + dev_err(dev, "failed to request irq %d\n", pp->irq); + return ret; + } + + ret = dw_pcie_host_init(pp); + if (ret) { + dev_err(dev, "failed to initialize host: %d\n", ret); + return ret; + } + + return 0; +} + +static int armada8k_pcie_probe(struct platform_device *pdev) +{ + struct armada8k_pcie *pcie; + struct pcie_port *pp; + struct device *dev = &pdev->dev; + struct resource *base; + int ret; + + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + + pcie->clk = devm_clk_get(dev, NULL); + if (IS_ERR(pcie->clk)) + return PTR_ERR(pcie->clk); + + clk_prepare_enable(pcie->clk); + + pp = &pcie->pp; + pp->dev = dev; + platform_set_drvdata(pdev, pcie); + + /* Get the dw-pcie unit configuration/control registers base. */ + base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); + pp->dbi_base = devm_ioremap_resource(dev, base); + if (IS_ERR(pp->dbi_base)) { + dev_err(dev, "couldn't remap regs base %p\n", base); + ret = PTR_ERR(pp->dbi_base); + goto fail; + } + + pcie->base = pp->dbi_base + PCIE_VENDOR_REGS_OFFSET; + + ret = armada8k_add_pcie_port(pp, pdev); + if (ret) + goto fail; + + return 0; + +fail: + if (!IS_ERR(pcie->clk)) + clk_disable_unprepare(pcie->clk); + + return ret; +} + +static const struct of_device_id armada8k_pcie_of_match[] = { + { .compatible = "marvell,armada8k-pcie", }, + {}, +}; +MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match); + +static struct platform_driver armada8k_pcie_driver = { + .probe = armada8k_pcie_probe, + .driver = { + .name = "armada8k-pcie", + .of_match_table = of_match_ptr(armada8k_pcie_of_match), + }, +}; + +module_platform_driver(armada8k_pcie_driver); + +MODULE_DESCRIPTION("Armada 8k PCIe host controller driver"); +MODULE_AUTHOR("Yehuda Yitshak "); +MODULE_AUTHOR("Shadi Ammouri "); +MODULE_LICENSE("GPL v2"); -- GitLab From bc19b9a81da009fd1d797d756d41b518ac7e5f14 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 31 Mar 2016 15:48:42 +0200 Subject: [PATCH 4575/9938] PM / AVS: rockchip-io: make io-domains a child of the GRF IO-domain handling is part of the general register files, so should live under the grf directly. This change allows the grf to be a simple-mfd and the io-domains fetching the syscon regmap from that parent-node. The old binding is of course preserved, though deprecated. Signed-off-by: Heiko Stuebner Acked-by: Kevin Hilman Tested-by: David Wu Signed-off-by: Rafael J. Wysocki --- .../devicetree/bindings/power/rockchip-io-domain.txt | 4 +++- drivers/power/avs/rockchip-io-domain.c | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/power/rockchip-io-domain.txt b/Documentation/devicetree/bindings/power/rockchip-io-domain.txt index c84fb47265eb..d23dc002a87e 100644 --- a/Documentation/devicetree/bindings/power/rockchip-io-domain.txt +++ b/Documentation/devicetree/bindings/power/rockchip-io-domain.txt @@ -37,8 +37,10 @@ Required properties: - "rockchip,rk3368-pmu-io-voltage-domain" for rk3368 pmu-domains - "rockchip,rk3399-io-voltage-domain" for rk3399 - "rockchip,rk3399-pmu-io-voltage-domain" for rk3399 pmu-domains -- rockchip,grf: phandle to the syscon managing the "general register files" +Deprecated properties: +- rockchip,grf: phandle to the syscon managing the "general register files" + Systems should move the io-domains to a sub-node of the grf simple-mfd. You specify supplies using the standard regulator bindings by including a phandle the relevant regulator. All specified supplies must be able diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/power/avs/rockchip-io-domain.c index 8986382718dd..01b6d3f9b8fb 100644 --- a/drivers/power/avs/rockchip-io-domain.c +++ b/drivers/power/avs/rockchip-io-domain.c @@ -336,6 +336,7 @@ static int rockchip_iodomain_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; struct rockchip_iodomain *iod; + struct device *parent; int i, ret = 0; if (!np) @@ -351,7 +352,14 @@ static int rockchip_iodomain_probe(struct platform_device *pdev) match = of_match_node(rockchip_iodomain_match, np); iod->soc_data = (struct rockchip_iodomain_soc_data *)match->data; - iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + parent = pdev->dev.parent; + if (parent && parent->of_node) { + iod->grf = syscon_node_to_regmap(parent->of_node); + } else { + dev_dbg(&pdev->dev, "falling back to old binding\n"); + iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + } + if (IS_ERR(iod->grf)) { dev_err(&pdev->dev, "couldn't find grf regmap\n"); return PTR_ERR(iod->grf); -- GitLab From 0de727383c46510f12932d32e4b66292854be508 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:22 +0530 Subject: [PATCH 4576/9938] cxgb4: add new routine to get adapter info Add new routine to print out general adapter information (various version numbers, adapter name, part number, serial number, etc.) and remove redundant information dumped in the Port Information. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 4 + .../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 78 +++++++++++++++++-- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 14 ++++ drivers/net/ethernet/chelsio/cxgb4/t4_hw.h | 7 ++ 4 files changed, 95 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 326d4009525e..459775884cad 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -324,7 +324,9 @@ struct adapter_params { unsigned int sf_fw_start; /* start of FW image in flash */ unsigned int fw_vers; + unsigned int bs_vers; /* bootstrap version */ unsigned int tp_vers; + unsigned int er_vers; /* expansion ROM version */ u8 api_vers[7]; unsigned short mtus[NMTUS]; @@ -731,6 +733,7 @@ struct adapter { u32 t4_bar0; struct pci_dev *pdev; struct device *pdev_dev; + const char *name; unsigned int mbox; unsigned int pf; unsigned int flags; @@ -1306,6 +1309,7 @@ int t4_fl_pkt_align(struct adapter *adap); unsigned int t4_flash_cfg_addr(struct adapter *adapter); int t4_check_fw_version(struct adapter *adap); int t4_get_fw_version(struct adapter *adapter, u32 *vers); +int t4_get_bs_version(struct adapter *adapter, u32 *vers); int t4_get_tp_version(struct adapter *adapter, u32 *vers); int t4_get_exprom_version(struct adapter *adapter, u32 *vers); int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a1e329ec24cd..b8dc7921b258 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3738,7 +3738,10 @@ static int adap_init0(struct adapter *adap) * is excessively mismatched relative to the driver.) */ t4_get_fw_version(adap, &adap->params.fw_vers); + t4_get_bs_version(adap, &adap->params.bs_vers); t4_get_tp_version(adap, &adap->params.tp_vers); + t4_get_exprom_version(adap, &adap->params.er_vers); + ret = t4_check_fw_version(adap); /* If firmware is too old (not supported by driver) force an update. */ if (ret) @@ -4652,6 +4655,68 @@ static void cxgb4_check_pcie_caps(struct adapter *adap) "suggested for optimal performance.\n"); } +/* Dump basic information about the adapter */ +static void print_adapter_info(struct adapter *adapter) +{ + /* Device information */ + dev_info(adapter->pdev_dev, "Chelsio %s rev %d\n", + adapter->params.vpd.id, + CHELSIO_CHIP_RELEASE(adapter->params.chip)); + dev_info(adapter->pdev_dev, "S/N: %s, P/N: %s\n", + adapter->params.vpd.sn, adapter->params.vpd.pn); + + /* Firmware Version */ + if (!adapter->params.fw_vers) + dev_warn(adapter->pdev_dev, "No firmware loaded\n"); + else + dev_info(adapter->pdev_dev, "Firmware version: %u.%u.%u.%u\n", + FW_HDR_FW_VER_MAJOR_G(adapter->params.fw_vers), + FW_HDR_FW_VER_MINOR_G(adapter->params.fw_vers), + FW_HDR_FW_VER_MICRO_G(adapter->params.fw_vers), + FW_HDR_FW_VER_BUILD_G(adapter->params.fw_vers)); + + /* Bootstrap Firmware Version. (Some adapters don't have Bootstrap + * Firmware, so dev_info() is more appropriate here.) + */ + if (!adapter->params.bs_vers) + dev_info(adapter->pdev_dev, "No bootstrap loaded\n"); + else + dev_info(adapter->pdev_dev, "Bootstrap version: %u.%u.%u.%u\n", + FW_HDR_FW_VER_MAJOR_G(adapter->params.bs_vers), + FW_HDR_FW_VER_MINOR_G(adapter->params.bs_vers), + FW_HDR_FW_VER_MICRO_G(adapter->params.bs_vers), + FW_HDR_FW_VER_BUILD_G(adapter->params.bs_vers)); + + /* TP Microcode Version */ + if (!adapter->params.tp_vers) + dev_warn(adapter->pdev_dev, "No TP Microcode loaded\n"); + else + dev_info(adapter->pdev_dev, + "TP Microcode version: %u.%u.%u.%u\n", + FW_HDR_FW_VER_MAJOR_G(adapter->params.tp_vers), + FW_HDR_FW_VER_MINOR_G(adapter->params.tp_vers), + FW_HDR_FW_VER_MICRO_G(adapter->params.tp_vers), + FW_HDR_FW_VER_BUILD_G(adapter->params.tp_vers)); + + /* Expansion ROM version */ + if (!adapter->params.er_vers) + dev_info(adapter->pdev_dev, "No Expansion ROM loaded\n"); + else + dev_info(adapter->pdev_dev, + "Expansion ROM version: %u.%u.%u.%u\n", + FW_HDR_FW_VER_MAJOR_G(adapter->params.er_vers), + FW_HDR_FW_VER_MINOR_G(adapter->params.er_vers), + FW_HDR_FW_VER_MICRO_G(adapter->params.er_vers), + FW_HDR_FW_VER_BUILD_G(adapter->params.er_vers)); + + /* Software/Hardware configuration */ + dev_info(adapter->pdev_dev, "Configuration: %sNIC %s, %s capable\n", + is_offload(adapter) ? "R" : "", + ((adapter->flags & USING_MSIX) ? "MSI-X" : + (adapter->flags & USING_MSI) ? "MSI" : ""), + is_offload(adapter) ? "Offload" : "non-Offload"); +} + static void print_port_info(const struct net_device *dev) { char buf[80]; @@ -4679,14 +4744,8 @@ static void print_port_info(const struct net_device *dev) --bufp; sprintf(bufp, "BASE-%s", t4_get_port_type_description(pi->port_type)); - netdev_info(dev, "Chelsio %s rev %d %s %sNIC %s\n", - adap->params.vpd.id, - CHELSIO_CHIP_RELEASE(adap->params.chip), buf, - is_offload(adap) ? "R" : "", - (adap->flags & USING_MSIX) ? " MSI-X" : - (adap->flags & USING_MSI) ? " MSI" : ""); - netdev_info(dev, "S/N: %s, P/N: %s\n", - adap->params.vpd.sn, adap->params.vpd.pn); + netdev_info(dev, "%s: Chelsio %s (%s) %s\n", + dev->name, adap->params.vpd.id, adap->name, buf); } static void enable_pcie_relaxed_ordering(struct pci_dev *dev) @@ -4844,6 +4903,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->regs = regs; adapter->pdev = pdev; adapter->pdev_dev = &pdev->dev; + adapter->name = pci_name(pdev); adapter->mbox = func; adapter->pf = func; adapter->msg_enable = dflt_msg_enable; @@ -5074,6 +5134,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (is_offload(adapter)) attach_ulds(adapter); + print_adapter_info(adapter); + sriov: #ifdef CONFIG_PCI_IOV if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 71586a3e0f61..2ced24fc569d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2936,6 +2936,20 @@ int t4_get_fw_version(struct adapter *adapter, u32 *vers) vers, 0); } +/** + * t4_get_bs_version - read the firmware bootstrap version + * @adapter: the adapter + * @vers: where to place the version + * + * Reads the FW Bootstrap version from flash. + */ +int t4_get_bs_version(struct adapter *adapter, u32 *vers) +{ + return t4_read_flash(adapter, FLASH_FWBOOTSTRAP_START + + offsetof(struct fw_hdr, fw_ver), 1, + vers, 0); +} + /** * t4_get_tp_version - read the TP microcode version * @adapter: the adapter diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h index 2fc60e83a7a1..7f59ca458431 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h @@ -220,6 +220,13 @@ enum { FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC), FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS), + /* Location of bootstrap firmware image in FLASH. + */ + FLASH_FWBOOTSTRAP_START_SEC = 27, + FLASH_FWBOOTSTRAP_NSECS = 1, + FLASH_FWBOOTSTRAP_START = FLASH_START(FLASH_FWBOOTSTRAP_START_SEC), + FLASH_FWBOOTSTRAP_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FWBOOTSTRAP_NSECS), + /* * iSCSI persistent/crash information. */ -- GitLab From ed98c85ee9a16373f73afeb5bcd7b37b65c2a62f Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:23 +0530 Subject: [PATCH 4577/9938] cxgb4: Add llseek operation for flash debugfs entry Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 0bb41e9b9b1c..9506c5cd11b9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -1572,6 +1572,7 @@ static const struct file_operations flash_debugfs_fops = { .owner = THIS_MODULE, .open = mem_open, .read = flash_read, + .llseek = default_llseek, }; static inline void tcamxy2valmask(u64 x, u64 y, u8 *addr, u64 *mask) -- GitLab From fbe8077687330a55e87bc26745d4992991c101ec Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:24 +0530 Subject: [PATCH 4578/9938] cxgb4: Avoids race and deadlock while freeing tx descriptor There could be race between t4_eth_xmit() and t4_free_sge_resources() while freeing tx descriptors, take txq lock in t4_free_sge_resources(). We need to stop the xmit frame path which runs in bottom half context while unloading the driver using _bh variant of the lock. This is to prevent the deadlock between xmit and driver unload. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/sge.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 6278e5a74b74..bad253beb8c8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -3006,7 +3006,9 @@ void t4_free_sge_resources(struct adapter *adap) if (etq->q.desc) { t4_eth_eq_free(adap, adap->mbox, adap->pf, 0, etq->q.cntxt_id); + __netif_tx_lock_bh(etq->txq); free_tx_desc(adap, &etq->q, etq->q.in_use, true); + __netif_tx_unlock_bh(etq->txq); kfree(etq->q.sdesc); free_txq(adap, &etq->q); } -- GitLab From be81a2deb1134c47fadb10cb0bd6540caf6f32d7 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:25 +0530 Subject: [PATCH 4579/9938] cxgb4: Properly decode port module type Decode and log port module error, unknown modules and unsupported modules. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index b8dc7921b258..abc425bfc744 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -337,6 +337,17 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id) netdev_info(dev, "port module unplugged\n"); else if (pi->mod_type < ARRAY_SIZE(mod_str)) netdev_info(dev, "%s module inserted\n", mod_str[pi->mod_type]); + else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) + netdev_info(dev, "%s: unsupported port module inserted\n", + dev->name); + else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) + netdev_info(dev, "%s: unknown port module inserted\n", + dev->name); + else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR) + netdev_info(dev, "%s: transceiver module error\n", dev->name); + else + netdev_info(dev, "%s: unknown module type %d inserted\n", + dev->name, pi->mod_type); } int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */ -- GitLab From c3e324e3d0662661f53c80fee28d70b6713f9dc8 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:26 +0530 Subject: [PATCH 4580/9938] cxgb4: Refactor t4_port_init function Refactor t4_port_init() so that the core functionality is done by t4_init_portinfo() for a particular port. Also rename variables to sensible ones. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 2 + drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 93 ++++++++++++---------- 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 459775884cad..f69119bc5990 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -1333,6 +1333,8 @@ int t4_init_sge_params(struct adapter *adapter); int t4_init_tp_params(struct adapter *adap); int t4_filter_field_shift(const struct adapter *adap, int filter_sel); int t4_init_rss_mode(struct adapter *adap, int mbox); +int t4_init_portinfo(struct port_info *pi, int mbox, + int port, int pf, int vf, u8 mac[]); int t4_port_init(struct adapter *adap, int mbox, int pf, int vf); void t4_fatal_err(struct adapter *adapter); int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 2ced24fc569d..1ebbbb9323e3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -7668,61 +7668,74 @@ int t4_init_rss_mode(struct adapter *adap, int mbox) return 0; } -int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) +/** + * t4_init_portinfo - allocate a virtual interface amd initialize port_info + * @pi: the port_info + * @mbox: mailbox to use for the FW command + * @port: physical port associated with the VI + * @pf: the PF owning the VI + * @vf: the VF owning the VI + * @mac: the MAC address of the VI + * + * Allocates a virtual interface for the given physical port. If @mac is + * not %NULL it contains the MAC address of the VI as assigned by FW. + * @mac should be large enough to hold an Ethernet address. + * Returns < 0 on error. + */ +int t4_init_portinfo(struct port_info *pi, int mbox, + int port, int pf, int vf, u8 mac[]) { - u8 addr[6]; - int ret, i, j = 0; + int ret; struct fw_port_cmd c; - struct fw_rss_vi_config_cmd rvc; + unsigned int rss_size; memset(&c, 0, sizeof(c)); - memset(&rvc, 0, sizeof(rvc)); + c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | + FW_CMD_REQUEST_F | FW_CMD_READ_F | + FW_PORT_CMD_PORTID_V(port)); + c.action_to_len16 = cpu_to_be32( + FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) | + FW_LEN16(c)); + ret = t4_wr_mbox(pi->adapter, mbox, &c, sizeof(c), &c); + if (ret) + return ret; + + ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, mac, &rss_size); + if (ret < 0) + return ret; + + pi->viid = ret; + pi->tx_chan = port; + pi->lport = port; + pi->rss_size = rss_size; + + ret = be32_to_cpu(c.u.info.lstatus_to_modtype); + pi->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP_F) ? + FW_PORT_CMD_MDIOADDR_G(ret) : -1; + pi->port_type = FW_PORT_CMD_PTYPE_G(ret); + pi->mod_type = FW_PORT_MOD_TYPE_NA; + + init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap)); + return 0; +} + +int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) +{ + u8 addr[6]; + int ret, i, j = 0; for_each_port(adap, i) { - unsigned int rss_size; - struct port_info *p = adap2pinfo(adap, i); + struct port_info *pi = adap2pinfo(adap, i); while ((adap->params.portvec & (1 << j)) == 0) j++; - c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | - FW_CMD_REQUEST_F | FW_CMD_READ_F | - FW_PORT_CMD_PORTID_V(j)); - c.action_to_len16 = cpu_to_be32( - FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) | - FW_LEN16(c)); - ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); + ret = t4_init_portinfo(pi, mbox, j, pf, vf, addr); if (ret) return ret; - ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size); - if (ret < 0) - return ret; - - p->viid = ret; - p->tx_chan = j; - p->lport = j; - p->rss_size = rss_size; memcpy(adap->port[i]->dev_addr, addr, ETH_ALEN); adap->port[i]->dev_port = j; - - ret = be32_to_cpu(c.u.info.lstatus_to_modtype); - p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP_F) ? - FW_PORT_CMD_MDIOADDR_G(ret) : -1; - p->port_type = FW_PORT_CMD_PTYPE_G(ret); - p->mod_type = FW_PORT_MOD_TYPE_NA; - - rvc.op_to_viid = - cpu_to_be32(FW_CMD_OP_V(FW_RSS_VI_CONFIG_CMD) | - FW_CMD_REQUEST_F | FW_CMD_READ_F | - FW_RSS_VI_CONFIG_CMD_VIID(p->viid)); - rvc.retval_len16 = cpu_to_be32(FW_LEN16(rvc)); - ret = t4_wr_mbox(adap, mbox, &rvc, sizeof(rvc), &rvc); - if (ret) - return ret; - p->rss_mode = be32_to_cpu(rvc.u.basicvirtual.defaultq_to_udpen); - - init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap)); j++; } return 0; -- GitLab From 134491fdc319037f37adc5f8ec51093e5cd5ada1 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:27 +0530 Subject: [PATCH 4581/9938] cxgb4: DCB message handler needs to use correct portid to netdev mapping Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c index 052c660aca80..6ee2ed30626b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c @@ -253,7 +253,7 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap, { const union fw_port_dcb *fwdcb = &pcmd->u.dcb; int port = FW_PORT_CMD_PORTID_G(be32_to_cpu(pcmd->op_to_portid)); - struct net_device *dev = adap->port[port]; + struct net_device *dev = adap->port[adap->chan_map[port]]; struct port_info *pi = netdev_priv(dev); struct port_dcb_info *dcb = &pi->dcb; int dcb_type = pcmd->u.dcb.pgid.type; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index abc425bfc744..4f627f3edb98 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -515,7 +515,7 @@ EXPORT_SYMBOL(cxgb4_dcb_enabled); static void dcb_rpl(struct adapter *adap, const struct fw_port_cmd *pcmd) { int port = FW_PORT_CMD_PORTID_G(ntohl(pcmd->op_to_portid)); - struct net_device *dev = adap->port[port]; + struct net_device *dev = adap->port[adap->chan_map[port]]; int old_dcb_enabled = cxgb4_dcb_enabled(dev); int new_dcb_enabled; @@ -645,7 +645,8 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, action == FW_PORT_ACTION_GET_PORT_INFO) { int port = FW_PORT_CMD_PORTID_G( be32_to_cpu(pcmd->op_to_portid)); - struct net_device *dev = q->adap->port[port]; + struct net_device *dev = + q->adap->port[q->adap->chan_map[port]]; int state_input = ((pcmd->u.info.dcbxdis_pkd & FW_PORT_CMD_DCBXDIS_F) ? CXGB4_DCB_INPUT_FW_DISABLED -- GitLab From 23853a0a9a7621922a21759eeed8c5bc09c71c54 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:28 +0530 Subject: [PATCH 4582/9938] cxgb4: Don't assume FW_PORT_CMD reply is always port info msg The firmware can send a set of asynchronous replies through FW_PORT_CMD with DCBX information when that's negotiated with the Link Peer. The old code always assumed that a FW_PORT_CMD reply was always a Get Port Information message. This change conditionalizes the code to only handle the Get Port Information messages and throws a warning if we don't understand what we've been given. Also refactor t4_handle_fw_rpl() so that core functionality performed by t4_handle_get_port_info() for a specified port. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 + drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 110 ++++++++++++++------- 2 files changed, 74 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index f69119bc5990..911fe11d32c6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -1470,6 +1470,7 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid); int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox); +void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl); int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); void t4_db_full(struct adapter *adapter); void t4_db_dropped(struct adapter *adapter); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 1ebbbb9323e3..cf3efbf4a37a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -7103,52 +7103,88 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, } /** - * t4_handle_fw_rpl - process a FW reply message - * @adap: the adapter + * t4_handle_get_port_info - process a FW reply message + * @pi: the port info * @rpl: start of the FW message * - * Processes a FW message, such as link state change messages. + * Processes a GET_PORT_INFO FW reply message. + */ +void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) +{ + const struct fw_port_cmd *p = (const void *)rpl; + struct adapter *adap = pi->adapter; + + /* link/module state change message */ + int speed = 0, fc = 0; + struct link_config *lc; + u32 stat = be32_to_cpu(p->u.info.lstatus_to_modtype); + int link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0; + u32 mod = FW_PORT_CMD_MODTYPE_G(stat); + + if (stat & FW_PORT_CMD_RXPAUSE_F) + fc |= PAUSE_RX; + if (stat & FW_PORT_CMD_TXPAUSE_F) + fc |= PAUSE_TX; + if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) + speed = 100; + else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) + speed = 1000; + else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) + speed = 10000; + else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) + speed = 40000; + + lc = &pi->link_cfg; + + if (mod != pi->mod_type) { + pi->mod_type = mod; + t4_os_portmod_changed(adap, pi->port_id); + } + if (link_ok != lc->link_ok || speed != lc->speed || + fc != lc->fc) { /* something changed */ + lc->link_ok = link_ok; + lc->speed = speed; + lc->fc = fc; + lc->supported = be16_to_cpu(p->u.info.pcap); + t4_os_link_changed(adap, pi->port_id, link_ok); + } +} + +/** + * t4_handle_fw_rpl - process a FW reply message + * @adap: the adapter + * @rpl: start of the FW message + * + * Processes a FW message, such as link state change messages. */ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) { u8 opcode = *(const u8 *)rpl; - if (opcode == FW_PORT_CMD) { /* link/module state change message */ - int speed = 0, fc = 0; - const struct fw_port_cmd *p = (void *)rpl; + /* This might be a port command ... this simplifies the following + * conditionals ... We can get away with pre-dereferencing + * action_to_len16 because it's in the first 16 bytes and all messages + * will be at least that long. + */ + const struct fw_port_cmd *p = (const void *)rpl; + unsigned int action = + FW_PORT_CMD_ACTION_G(be32_to_cpu(p->action_to_len16)); + + if (opcode == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO) { + int i; int chan = FW_PORT_CMD_PORTID_G(be32_to_cpu(p->op_to_portid)); - int port = adap->chan_map[chan]; - struct port_info *pi = adap2pinfo(adap, port); - struct link_config *lc = &pi->link_cfg; - u32 stat = be32_to_cpu(p->u.info.lstatus_to_modtype); - int link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0; - u32 mod = FW_PORT_CMD_MODTYPE_G(stat); - - if (stat & FW_PORT_CMD_RXPAUSE_F) - fc |= PAUSE_RX; - if (stat & FW_PORT_CMD_TXPAUSE_F) - fc |= PAUSE_TX; - if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) - speed = 100; - else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) - speed = 1000; - else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) - speed = 10000; - else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) - speed = 40000; - - if (link_ok != lc->link_ok || speed != lc->speed || - fc != lc->fc) { /* something changed */ - lc->link_ok = link_ok; - lc->speed = speed; - lc->fc = fc; - lc->supported = be16_to_cpu(p->u.info.pcap); - t4_os_link_changed(adap, port, link_ok); - } - if (mod != pi->mod_type) { - pi->mod_type = mod; - t4_os_portmod_changed(adap, port); + struct port_info *pi = NULL; + + for_each_port(adap, i) { + pi = adap2pinfo(adap, i); + if (pi->tx_chan == chan) + break; } + + t4_handle_get_port_info(pi, rpl); + } else { + dev_warn(adap->pdev_dev, "Unknown firmware reply %d\n", opcode); + return -EINVAL; } return 0; } -- GitLab From ddc7740d9a7c7e61650309a81037f12d5cfad88e Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Tue, 26 Apr 2016 20:10:29 +0530 Subject: [PATCH 4583/9938] cxgb4: Decode link down reason code obtained from firmware Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 + drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 34 +++++++++++++++++++ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 5 +++ 3 files changed, 40 insertions(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 911fe11d32c6..6af5242e6d21 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -396,6 +396,7 @@ struct link_config { unsigned char fc; /* actual link flow control */ unsigned char autoneg; /* autonegotiating? */ unsigned char link_ok; /* link up? */ + unsigned char link_down_rc; /* link down reason */ }; #define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index cf3efbf4a37a..7907d85efa4c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -7102,6 +7102,32 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } +/** + * t4_link_down_rc_str - return a string for a Link Down Reason Code + * @adap: the adapter + * @link_down_rc: Link Down Reason Code + * + * Returns a string representation of the Link Down Reason Code. + */ +static const char *t4_link_down_rc_str(unsigned char link_down_rc) +{ + static const char * const reason[] = { + "Link Down", + "Remote Fault", + "Auto-negotiation Failure", + "Reserved", + "Insufficient Airflow", + "Unable To Determine Reason", + "No RX Signal Detected", + "Reserved", + }; + + if (link_down_rc >= ARRAY_SIZE(reason)) + return "Bad Reason Code"; + + return reason[link_down_rc]; +} + /** * t4_handle_get_port_info - process a FW reply message * @pi: the port info @@ -7142,6 +7168,14 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) } if (link_ok != lc->link_ok || speed != lc->speed || fc != lc->fc) { /* something changed */ + if (!link_ok && lc->link_ok) { + unsigned char rc = FW_PORT_CMD_LINKDNRC_G(stat); + + lc->link_down_rc = rc; + dev_warn(adap->pdev_dev, + "Port %d link down, reason: %s\n", + pi->port_id, t4_link_down_rc_str(rc)); + } lc->link_ok = link_ok; lc->speed = speed; lc->fc = fc; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 7ad6d4e75b2a..392d6644fdd8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -2510,6 +2510,11 @@ struct fw_port_cmd { #define FW_PORT_CMD_PTYPE_G(x) \ (((x) >> FW_PORT_CMD_PTYPE_S) & FW_PORT_CMD_PTYPE_M) +#define FW_PORT_CMD_LINKDNRC_S 5 +#define FW_PORT_CMD_LINKDNRC_M 0x7 +#define FW_PORT_CMD_LINKDNRC_G(x) \ + (((x) >> FW_PORT_CMD_LINKDNRC_S) & FW_PORT_CMD_LINKDNRC_M) + #define FW_PORT_CMD_MODTYPE_S 0 #define FW_PORT_CMD_MODTYPE_M 0x1f #define FW_PORT_CMD_MODTYPE_V(x) ((x) << FW_PORT_CMD_MODTYPE_S) -- GitLab From bcb0bcd9c893dd97005a1d2dfd08abbbe1909050 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Mon, 18 Apr 2016 20:20:57 +0200 Subject: [PATCH 4584/9938] ARM: dts: twl6030: describe gpadc tested on Pandaboard ES. Signed-off-by: H. Nikolaus Schaller Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/twl6030.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/twl6030.dtsi b/arch/arm/boot/dts/twl6030.dtsi index 55eb35f068fb..c45f97f37563 100644 --- a/arch/arm/boot/dts/twl6030.dtsi +++ b/arch/arm/boot/dts/twl6030.dtsi @@ -99,4 +99,10 @@ compatible = "ti,twl6030-pwmled"; #pwm-cells = <2>; }; + + gpadc { + compatible = "ti,twl6030-gpadc"; + interrupts = <3>; + #io-channel-cells = <1>; + }; }; -- GitLab From cecc77c8e54ac6874e4f92cae47cc3f2f5df3f74 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Mon, 18 Apr 2016 20:20:58 +0200 Subject: [PATCH 4585/9938] ARM: dts: omap5-board-common: describe gpadc for Palmas tested on OMP5432 EVM Signed-off-by: H. Nikolaus Schaller Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5-board-common.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi index cdd144acbd3f..d0990606d16e 100644 --- a/arch/arm/boot/dts/omap5-board-common.dtsi +++ b/arch/arm/boot/dts/omap5-board-common.dtsi @@ -391,6 +391,16 @@ ti,backup-battery-charge-high-current; }; + gpadc { + compatible = "ti,palmas-gpadc"; + interrupts = <18 0 + 16 0 + 17 0>; + #io-channel-cells = <1>; + ti,channel0-current-microamp = <5>; + ti,channel3-current-microamp = <10>; + }; + palmas_pmic { compatible = "ti,palmas-pmic"; interrupt-parent = <&palmas>; -- GitLab From 5da86baf694c5aca752b30b076d4789e05947add Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 22 Apr 2016 13:53:19 -0400 Subject: [PATCH 4586/9938] ARM: omap2plus_defconfig: Fix warning due invalid RXKAD symbol value Commit 648af7fca159 ("rxrpc: Absorb the rxkad security module") changed the RXKAD Kconfig symbol from tristate to boolean but the commit didn't update the omap2plus_defconfig that was enabling CONFIG_RXKAD as module. This leads to the following warning when using the omap2plus_defconfig: arch/arm/configs/omap2plus_defconfig:112:warning: symbol value 'm' invalid for RXKAD Signed-off-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 9edf8a493f07..c48cbd78e08f 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -109,7 +109,7 @@ CONFIG_BT_HCIVHCI=m CONFIG_BT_MRVL=m CONFIG_BT_MRVL_SDIO=m CONFIG_AF_RXRPC=m -CONFIG_RXKAD=m +CONFIG_RXKAD=y CONFIG_CFG80211=m CONFIG_MAC80211=m CONFIG_DEVTMPFS=y -- GitLab From f309f549243fc2813099622df5b17e1b9f1f8aea Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 26 Apr 2016 10:31:23 -0700 Subject: [PATCH 4587/9938] ARM: omap2plus_defconfig: Enable twl6030 USB phy as loadable module This is in use on omap4 boards. Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c48cbd78e08f..5bd5d364b5fd 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -364,6 +364,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_USB_SERIAL_PL2303=m CONFIG_USB_TEST=m CONFIG_AM335X_PHY_USB=y +CONFIG_TWL6030_USB=m CONFIG_USB_GADGET=m CONFIG_USB_GADGET_DEBUG=y CONFIG_USB_GADGET_DEBUG_FILES=y -- GitLab From 626180785f5d9443c475d2b2760f64bb510f2b66 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Wed, 20 Apr 2016 17:02:59 +0530 Subject: [PATCH 4588/9938] ARM: dts: dra7x: Remove QSPI pinmux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRA7 family of processors from Texas Instruments, have a hardware module called IODELAYCONFIG Module which is expected to be configured. This block allows very specific custom fine tuning for electrical characteristics of IO pins that are necessary for functionality and device lifetime requirements. IODelay module has it's own register space with registers to configure various pins. According to AM572x TRM SPRUHZ6E October 2014–Revised January 2016[1] section 18.4.6.1 Pad Configuration, in addition to pinmuxing(MUXMODE), when operating a pad in certain mode, Virtual/Manual IO Timing Mode must also be configured to ensure that IO timings are met (DELAYMODE and MODESELECT fields of pad's IODELAYCONFIG module register). According to section 18.4.6.1.7 Isolation Requirements of above TRM, when reprogramming MUXMODE, DELAYMODE, and MODESELECT fields, there is a potential for a significant glitch on the corresponding IO. It is hence recommended to do this with I/O isolation (which can only be done in initial stages of bootloader). QSPI is one such module that requires IODELAY configuration. So, this patch removes the pinmux for QSPI for DRA74/DRA72 EVM as it needs to be done in bootloader (U-Boot) and cannot be done in kernel. Users should migrate to U-Boot v2016.05-rc1 or higher. [1] http://www.ti.com/lit/ug/spruhz6e/spruhz6e.pdf Signed-off-by: Vignesh R Acked-by: Rob Herring Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7-evm.dts | 17 ----------------- arch/arm/boot/dts/dra72-evm-common.dtsi | 14 -------------- 2 files changed, 31 deletions(-) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index cf4e62174f3c..98bc5ca43340 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -226,21 +226,6 @@ >; }; - qspi1_pins: pinmux_qspi1_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x344c, PIN_INPUT | MUX_MODE1) /* gpmc_a3.qspi1_cs2 */ - DRA7XX_CORE_IOPAD(0x3450, PIN_INPUT | MUX_MODE1) /* gpmc_a4.qspi1_cs3 */ - DRA7XX_CORE_IOPAD(0x3474, PIN_INPUT | MUX_MODE1) /* gpmc_a13.qspi1_rtclk */ - DRA7XX_CORE_IOPAD(0x3478, PIN_INPUT | MUX_MODE1) /* gpmc_a14.qspi1_d3 */ - DRA7XX_CORE_IOPAD(0x347c, PIN_INPUT | MUX_MODE1) /* gpmc_a15.qspi1_d2 */ - DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1) /* gpmc_a16.qspi1_d1 */ - DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1) /* gpmc_a17.qspi1_d0 */ - DRA7XX_CORE_IOPAD(0x3488, PIN_INPUT | MUX_MODE1) /* qpmc_a18.qspi1_sclk */ - DRA7XX_CORE_IOPAD(0x34b8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs2.qspi1_cs0 */ - DRA7XX_CORE_IOPAD(0x34bc, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs3.qspi1_cs1 */ - >; - }; - usb1_pins: pinmux_usb1_pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */ @@ -678,8 +663,6 @@ &qspi { status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&qspi1_pins>; spi-max-frequency = <48000000>; m25p80@0 { diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi index fd56f1fb7f10..2894759276d0 100644 --- a/arch/arm/boot/dts/dra72-evm-common.dtsi +++ b/arch/arm/boot/dts/dra72-evm-common.dtsi @@ -241,18 +241,6 @@ >; }; - qspi1_pins: pinmux_qspi1_pins { - pinctrl-single,pins = < - DRA7XX_CORE_IOPAD(0x3474, PIN_OUTPUT | MUX_MODE1) /* gpmc_a13.qspi1_rtclk */ - DRA7XX_CORE_IOPAD(0x3478, PIN_INPUT | MUX_MODE1) /* gpmc_a14.qspi1_d3 */ - DRA7XX_CORE_IOPAD(0x347c, PIN_INPUT | MUX_MODE1) /* gpmc_a15.qspi1_d2 */ - DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1) /* gpmc_a16.qspi1_d1 */ - DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1) /* gpmc_a17.qspi1_d0 */ - DRA7XX_CORE_IOPAD(0x3488, PIN_OUTPUT | MUX_MODE1) /* qpmc_a18.qspi1_sclk */ - DRA7XX_CORE_IOPAD(0x34b8, PIN_OUTPUT | MUX_MODE1) /* gpmc_cs2.qspi1_cs0 */ - >; - }; - hdmi_pins: pinmux_hdmi_pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */ @@ -692,8 +680,6 @@ &qspi { status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&qspi1_pins>; spi-max-frequency = <48000000>; m25p80@0 { -- GitLab From b7a1922814c617884a3fee9b107ffb784fa4cf94 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Wed, 20 Apr 2016 17:03:00 +0530 Subject: [PATCH 4589/9938] ARM: dts: dra7x: Support QSPI MODE-0 operation at 64MHz According to Data Manual(SPRS915P) of AM57x, TI QSPI controller on DRA74(rev 1.1+)/DRA72 EVM can support up to 64MHz in MODE-0, whereas MODE-3 is limited to 48MHz. Hence, switch to MODE-0 for better throughput. Signed-off-by: Vignesh R Acked-by: Rob Herring Signed-off-by: Tony Lindgren --- Documentation/devicetree/bindings/spi/ti_qspi.txt | 7 +++++++ arch/arm/boot/dts/dra7-evm.dts | 6 ++---- arch/arm/boot/dts/dra72-evm-common.dtsi | 6 ++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/ti_qspi.txt b/Documentation/devicetree/bindings/spi/ti_qspi.txt index cc8304aa64ac..50b14f6b53a3 100644 --- a/Documentation/devicetree/bindings/spi/ti_qspi.txt +++ b/Documentation/devicetree/bindings/spi/ti_qspi.txt @@ -19,6 +19,13 @@ Optional properties: - syscon-chipselects: Handle to system control region contains QSPI chipselect register and offset of that register. +NOTE: TI QSPI controller requires different pinmux and IODelay +paramaters for Mode-0 and Mode-3 operations, which needs to be set up by +the bootloader (U-Boot). Default configuration only supports Mode-0 +operation. Hence, "spi-cpol" and "spi-cpha" DT properties cannot be +specified in the slave nodes of TI QSPI controller without appropriate +modification to bootloader. + Example: For am4372: diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 98bc5ca43340..bafcfac067ec 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -664,15 +664,13 @@ &qspi { status = "okay"; - spi-max-frequency = <48000000>; + spi-max-frequency = <64000000>; m25p80@0 { compatible = "s25fl256s1"; - spi-max-frequency = <48000000>; + spi-max-frequency = <64000000>; reg = <0>; spi-tx-bus-width = <1>; spi-rx-bus-width = <4>; - spi-cpol; - spi-cpha; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi index 2894759276d0..093538ea5b5f 100644 --- a/arch/arm/boot/dts/dra72-evm-common.dtsi +++ b/arch/arm/boot/dts/dra72-evm-common.dtsi @@ -681,15 +681,13 @@ &qspi { status = "okay"; - spi-max-frequency = <48000000>; + spi-max-frequency = <64000000>; m25p80@0 { compatible = "s25fl256s1"; - spi-max-frequency = <48000000>; + spi-max-frequency = <64000000>; reg = <0>; spi-tx-bus-width = <1>; spi-rx-bus-width = <4>; - spi-cpol; - spi-cpha; #address-cells = <1>; #size-cells = <1>; -- GitLab From bcd197c81f63afa4610e481ed353d1507ba401d0 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Tue, 26 Apr 2016 10:56:08 -0400 Subject: [PATCH 4590/9938] qed: Add vport WFQ configuration APIs This patch adds relevant APIs needed to configure WFQ (Weighted fair queueing) values for the vports. WFQ configuration is used per vport basis when minimum bandwidth update/configuration is notified to the PF by the management firmware. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 11 + drivers/net/ethernet/qlogic/qed/qed_dev.c | 188 +++++++++++++++++- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 2 + .../ethernet/qlogic/qed/qed_init_fw_funcs.c | 25 +++ .../net/ethernet/qlogic/qed/qed_reg_addr.h | 1 + 5 files changed, 223 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 33e2ed60c18f..cceac3272cce 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -32,6 +32,8 @@ extern const struct qed_common_ops qed_common_ops_pass; #define NAME_SIZE 16 #define VER_SIZE 16 +#define QED_WFQ_UNIT 100 + /* cau states */ enum qed_coalescing_mode { QED_COAL_MODE_DISABLE, @@ -237,6 +239,12 @@ struct qed_dmae_info { struct dmae_cmd *p_dmae_cmd; }; +struct qed_wfq_data { + /* when feature is configured for at least 1 vport */ + u32 min_speed; + bool configured; +}; + struct qed_qm_info { struct init_qm_pq_params *qm_pq_params; struct init_qm_vport_params *qm_vport_params; @@ -257,6 +265,7 @@ struct qed_qm_info { bool vport_wfq_en; u8 pf_wfq; u32 pf_rl; + struct qed_wfq_data *wfq_data; }; struct storm_stats { @@ -526,6 +535,8 @@ static inline u8 qed_concrete_to_sw_fid(struct qed_dev *cdev, #define PURE_LB_TC 8 +void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate); + #define QED_LEADING_HWFN(dev) (&dev->hwfns[0]) /* Other Linux specific common definitions */ diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index bdae5a55afa4..28e0619a290e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -105,6 +105,8 @@ static void qed_qm_info_free(struct qed_hwfn *p_hwfn) qm_info->qm_vport_params = NULL; kfree(qm_info->qm_port_params); qm_info->qm_port_params = NULL; + kfree(qm_info->wfq_data); + qm_info->wfq_data = NULL; } void qed_resc_free(struct qed_dev *cdev) @@ -175,6 +177,11 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn) if (!qm_info->qm_port_params) goto alloc_err; + qm_info->wfq_data = kcalloc(num_vports, sizeof(*qm_info->wfq_data), + GFP_KERNEL); + if (!qm_info->wfq_data) + goto alloc_err; + vport_id = (u8)RESC_START(p_hwfn, QED_VPORT); /* First init per-TC PQs */ @@ -221,10 +228,7 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn) alloc_err: DP_NOTICE(p_hwfn, "Failed to allocate memory for QM params\n"); - kfree(qm_info->qm_pq_params); - kfree(qm_info->qm_vport_params); - kfree(qm_info->qm_port_params); - + qed_qm_info_free(p_hwfn); return -ENOMEM; } @@ -1595,3 +1599,179 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, return 0; } + +/* Calculate final WFQ values for all vports and configure them. + * After this configuration each vport will have + * approx min rate = min_pf_rate * (vport_wfq / QED_WFQ_UNIT) + */ +static void qed_configure_wfq_for_all_vports(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 min_pf_rate) +{ + struct init_qm_vport_params *vport_params; + int i; + + vport_params = p_hwfn->qm_info.qm_vport_params; + + for (i = 0; i < p_hwfn->qm_info.num_vports; i++) { + u32 wfq_speed = p_hwfn->qm_info.wfq_data[i].min_speed; + + vport_params[i].vport_wfq = (wfq_speed * QED_WFQ_UNIT) / + min_pf_rate; + qed_init_vport_wfq(p_hwfn, p_ptt, + vport_params[i].first_tx_pq_id, + vport_params[i].vport_wfq); + } +} + +static void qed_init_wfq_default_param(struct qed_hwfn *p_hwfn, + u32 min_pf_rate) + +{ + int i; + + for (i = 0; i < p_hwfn->qm_info.num_vports; i++) + p_hwfn->qm_info.qm_vport_params[i].vport_wfq = 1; +} + +static void qed_disable_wfq_for_all_vports(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 min_pf_rate) +{ + struct init_qm_vport_params *vport_params; + int i; + + vport_params = p_hwfn->qm_info.qm_vport_params; + + for (i = 0; i < p_hwfn->qm_info.num_vports; i++) { + qed_init_wfq_default_param(p_hwfn, min_pf_rate); + qed_init_vport_wfq(p_hwfn, p_ptt, + vport_params[i].first_tx_pq_id, + vport_params[i].vport_wfq); + } +} + +/* This function performs several validations for WFQ + * configuration and required min rate for a given vport + * 1. req_rate must be greater than one percent of min_pf_rate. + * 2. req_rate should not cause other vports [not configured for WFQ explicitly] + * rates to get less than one percent of min_pf_rate. + * 3. total_req_min_rate [all vports min rate sum] shouldn't exceed min_pf_rate. + */ +static int qed_init_wfq_param(struct qed_hwfn *p_hwfn, + u16 vport_id, u32 req_rate, + u32 min_pf_rate) +{ + u32 total_req_min_rate = 0, total_left_rate = 0, left_rate_per_vp = 0; + int non_requested_count = 0, req_count = 0, i, num_vports; + + num_vports = p_hwfn->qm_info.num_vports; + + /* Accounting for the vports which are configured for WFQ explicitly */ + for (i = 0; i < num_vports; i++) { + u32 tmp_speed; + + if ((i != vport_id) && + p_hwfn->qm_info.wfq_data[i].configured) { + req_count++; + tmp_speed = p_hwfn->qm_info.wfq_data[i].min_speed; + total_req_min_rate += tmp_speed; + } + } + + /* Include current vport data as well */ + req_count++; + total_req_min_rate += req_rate; + non_requested_count = num_vports - req_count; + + if (req_rate < min_pf_rate / QED_WFQ_UNIT) { + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Vport [%d] - Requested rate[%d Mbps] is less than one percent of configured PF min rate[%d Mbps]\n", + vport_id, req_rate, min_pf_rate); + return -EINVAL; + } + + if (num_vports > QED_WFQ_UNIT) { + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Number of vports is greater than %d\n", + QED_WFQ_UNIT); + return -EINVAL; + } + + if (total_req_min_rate > min_pf_rate) { + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Total requested min rate for all vports[%d Mbps] is greater than configured PF min rate[%d Mbps]\n", + total_req_min_rate, min_pf_rate); + return -EINVAL; + } + + total_left_rate = min_pf_rate - total_req_min_rate; + + left_rate_per_vp = total_left_rate / non_requested_count; + if (left_rate_per_vp < min_pf_rate / QED_WFQ_UNIT) { + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Non WFQ configured vports rate [%d Mbps] is less than one percent of configured PF min rate[%d Mbps]\n", + left_rate_per_vp, min_pf_rate); + return -EINVAL; + } + + p_hwfn->qm_info.wfq_data[vport_id].min_speed = req_rate; + p_hwfn->qm_info.wfq_data[vport_id].configured = true; + + for (i = 0; i < num_vports; i++) { + if (p_hwfn->qm_info.wfq_data[i].configured) + continue; + + p_hwfn->qm_info.wfq_data[i].min_speed = left_rate_per_vp; + } + + return 0; +} + +static int __qed_configure_vp_wfq_on_link_change(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 min_pf_rate) +{ + bool use_wfq = false; + int rc = 0; + u16 i; + + /* Validate all pre configured vports for wfq */ + for (i = 0; i < p_hwfn->qm_info.num_vports; i++) { + u32 rate; + + if (!p_hwfn->qm_info.wfq_data[i].configured) + continue; + + rate = p_hwfn->qm_info.wfq_data[i].min_speed; + use_wfq = true; + + rc = qed_init_wfq_param(p_hwfn, i, rate, min_pf_rate); + if (rc) { + DP_NOTICE(p_hwfn, + "WFQ validation failed while configuring min rate\n"); + break; + } + } + + if (!rc && use_wfq) + qed_configure_wfq_for_all_vports(p_hwfn, p_ptt, min_pf_rate); + else + qed_disable_wfq_for_all_vports(p_hwfn, p_ptt, min_pf_rate); + + return rc; +} + +/* API to configure WFQ from mcp link change */ +void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate) +{ + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + __qed_configure_vp_wfq_on_link_change(p_hwfn, + p_hwfn->p_dpc_ptt, + min_pf_rate); + } +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 15e02ab9be5a..7d5ed0c17da7 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -5116,4 +5116,6 @@ struct hw_set_image { struct hw_set_info hw_sets[1]; }; +int qed_init_vport_wfq(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + u16 first_tx_pq_id[NUM_OF_TCS], u16 vport_wfq); #endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c index 1dd53248b984..e646987a3d41 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c +++ b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c @@ -732,6 +732,31 @@ int qed_init_pf_rl(struct qed_hwfn *p_hwfn, return 0; } +int qed_init_vport_wfq(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 first_tx_pq_id[NUM_OF_TCS], + u16 vport_wfq) +{ + u32 inc_val = QM_WFQ_INC_VAL(vport_wfq); + u8 tc; + + if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, "Invalid VPORT WFQ weight configuration"); + return -1; + } + + for (tc = 0; tc < NUM_OF_TCS; tc++) { + u16 vport_pq_id = first_tx_pq_id[tc]; + + if (vport_pq_id != QM_INVALID_PQ_ID) + qed_wr(p_hwfn, p_ptt, + QM_REG_WFQVPWEIGHT + vport_pq_id * 4, + inc_val); + } + + return 0; +} + int qed_init_vport_rl(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u8 vport_id, diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index 55451a4dc587..d2f57301cb3e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -458,4 +458,5 @@ #define PBF_REG_NGE_COMP_VER 0xd80524UL #define PRS_REG_NGE_COMP_VER 0x1f0878UL +#define QM_REG_WFQVPWEIGHT 0x2fa000UL #endif -- GitLab From 4b01e5192bd26ed4d0c3c271611cc74ae2c164f2 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Tue, 26 Apr 2016 10:56:09 -0400 Subject: [PATCH 4591/9938] qed: Add PF max bandwidth configuration support This patch adds support for PF maximum bandwidth update or configuration notified by management firmware. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_dev.c | 68 ++++++++++- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 138 +++++++++++++--------- drivers/net/ethernet/qlogic/qed/qed_mcp.h | 14 ++- 4 files changed, 165 insertions(+), 57 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 28e0619a290e..4e99108d9427 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -579,7 +579,7 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, p_hwfn->qm_info.pf_wfq = p_info->bandwidth_min; /* Update rate limit once we'll actually have a link */ - p_hwfn->qm_info.pf_rl = 100; + p_hwfn->qm_info.pf_rl = 100000; } qed_cxt_hw_init_pf(p_hwfn); @@ -1775,3 +1775,69 @@ void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate) min_pf_rate); } } + +int __qed_configure_pf_max_bandwidth(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_mcp_link_state *p_link, + u8 max_bw) +{ + int rc = 0; + + p_hwfn->mcp_info->func_info.bandwidth_max = max_bw; + + if (!p_link->line_speed && (max_bw != 100)) + return rc; + + p_link->speed = (p_link->line_speed * max_bw) / 100; + p_hwfn->qm_info.pf_rl = p_link->speed; + + /* Since the limiter also affects Tx-switched traffic, we don't want it + * to limit such traffic in case there's no actual limit. + * In that case, set limit to imaginary high boundary. + */ + if (max_bw == 100) + p_hwfn->qm_info.pf_rl = 100000; + + rc = qed_init_pf_rl(p_hwfn, p_ptt, p_hwfn->rel_pf_id, + p_hwfn->qm_info.pf_rl); + + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Configured MAX bandwidth to be %08x Mb/sec\n", + p_link->speed); + + return rc; +} + +/* Main API to configure PF max bandwidth where bw range is [1 - 100] */ +int qed_configure_pf_max_bandwidth(struct qed_dev *cdev, u8 max_bw) +{ + int i, rc = -EINVAL; + + if (max_bw < 1 || max_bw > 100) { + DP_NOTICE(cdev, "PF max bw valid range is [1-100]\n"); + return rc; + } + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + struct qed_hwfn *p_lead = QED_LEADING_HWFN(cdev); + struct qed_mcp_link_state *p_link; + struct qed_ptt *p_ptt; + + p_link = &p_lead->mcp_info->link_output; + + p_ptt = qed_ptt_acquire(p_hwfn); + if (!p_ptt) + return -EBUSY; + + rc = __qed_configure_pf_max_bandwidth(p_hwfn, p_ptt, + p_link, max_bw); + + qed_ptt_release(p_hwfn, p_ptt); + + if (rc) + break; + } + + return rc; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 7d5ed0c17da7..81cf62573ec4 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -3837,7 +3837,7 @@ struct public_drv_mb { #define DRV_MSG_CODE_SET_LLDP 0x24000000 #define DRV_MSG_CODE_SET_DCBX 0x25000000 - +#define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000 #define DRV_MSG_CODE_NIG_DRAIN 0x30000000 #define DRV_MSG_CODE_INITIATE_FLR 0x02000000 diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index b89c9a8e1655..578b09c2ae18 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -473,6 +473,7 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, { struct qed_mcp_link_state *p_link; u32 status = 0; + u8 max_bw; p_link = &p_hwfn->mcp_info->link_output; memset(p_link, 0, sizeof(*p_link)); @@ -527,17 +528,15 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, p_link->speed = 0; } + if (p_link->link_up && p_link->speed) + p_link->line_speed = p_link->speed; + else + p_link->line_speed = 0; + + max_bw = p_hwfn->mcp_info->func_info.bandwidth_max; + /* Correct speed according to bandwidth allocation */ - if (p_hwfn->mcp_info->func_info.bandwidth_max && p_link->speed) { - p_link->speed = p_link->speed * - p_hwfn->mcp_info->func_info.bandwidth_max / - 100; - qed_init_pf_rl(p_hwfn, p_ptt, p_hwfn->rel_pf_id, - p_link->speed); - DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, - "Configured MAX bandwidth to be %08x Mb/sec\n", - p_link->speed); - } + __qed_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw); p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED); p_link->an_complete = !!(status & @@ -648,6 +647,76 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, return 0; } +static void qed_read_pf_bandwidth(struct qed_hwfn *p_hwfn, + struct public_func *p_shmem_info) +{ + struct qed_mcp_function_info *p_info; + + p_info = &p_hwfn->mcp_info->func_info; + + p_info->bandwidth_min = (p_shmem_info->config & + FUNC_MF_CFG_MIN_BW_MASK) >> + FUNC_MF_CFG_MIN_BW_SHIFT; + if (p_info->bandwidth_min < 1 || p_info->bandwidth_min > 100) { + DP_INFO(p_hwfn, + "bandwidth minimum out of bounds [%02x]. Set to 1\n", + p_info->bandwidth_min); + p_info->bandwidth_min = 1; + } + + p_info->bandwidth_max = (p_shmem_info->config & + FUNC_MF_CFG_MAX_BW_MASK) >> + FUNC_MF_CFG_MAX_BW_SHIFT; + if (p_info->bandwidth_max < 1 || p_info->bandwidth_max > 100) { + DP_INFO(p_hwfn, + "bandwidth maximum out of bounds [%02x]. Set to 100\n", + p_info->bandwidth_max); + p_info->bandwidth_max = 100; + } +} + +static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct public_func *p_data, + int pfid) +{ + u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, + PUBLIC_FUNC); + u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr); + u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid); + u32 i, size; + + memset(p_data, 0, sizeof(*p_data)); + + size = min_t(u32, sizeof(*p_data), + QED_SECTION_SIZE(mfw_path_offsize)); + for (i = 0; i < size / sizeof(u32); i++) + ((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt, + func_addr + (i << 2)); + return size; +} + +static void qed_mcp_update_bw(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_mcp_function_info *p_info; + struct public_func shmem_info; + u32 resp = 0, param = 0; + + qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, + MCP_PF_ID(p_hwfn)); + + qed_read_pf_bandwidth(p_hwfn, &shmem_info); + + p_info = &p_hwfn->mcp_info->func_info; + + qed_configure_pf_max_bandwidth(p_hwfn->cdev, p_info->bandwidth_max); + + /* Acknowledge the MFW */ + qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BW_UPDATE_ACK, 0, &resp, + ¶m); +} + int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { @@ -679,6 +748,9 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE: qed_mcp_handle_transceiver_change(p_hwfn, p_ptt); break; + case MFW_DRV_MSG_BW_UPDATE: + qed_mcp_update_bw(p_hwfn, p_ptt); + break; default: DP_NOTICE(p_hwfn, "Unimplemented MFW message %d\n", i); rc = -EINVAL; @@ -758,28 +830,6 @@ int qed_mcp_get_media_type(struct qed_dev *cdev, return 0; } -static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct public_func *p_data, - int pfid) -{ - u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, - PUBLIC_FUNC); - u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr); - u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid); - u32 i, size; - - memset(p_data, 0, sizeof(*p_data)); - - size = min_t(u32, sizeof(*p_data), - QED_SECTION_SIZE(mfw_path_offsize)); - for (i = 0; i < size / sizeof(u32); i++) - ((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt, - func_addr + (i << 2)); - - return size; -} - static int qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn, struct public_func *p_info, @@ -818,26 +868,7 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, return -EINVAL; } - - info->bandwidth_min = (shmem_info.config & - FUNC_MF_CFG_MIN_BW_MASK) >> - FUNC_MF_CFG_MIN_BW_SHIFT; - if (info->bandwidth_min < 1 || info->bandwidth_min > 100) { - DP_INFO(p_hwfn, - "bandwidth minimum out of bounds [%02x]. Set to 1\n", - info->bandwidth_min); - info->bandwidth_min = 1; - } - - info->bandwidth_max = (shmem_info.config & - FUNC_MF_CFG_MAX_BW_MASK) >> - FUNC_MF_CFG_MAX_BW_SHIFT; - if (info->bandwidth_max < 1 || info->bandwidth_max > 100) { - DP_INFO(p_hwfn, - "bandwidth maximum out of bounds [%02x]. Set to 100\n", - info->bandwidth_max); - info->bandwidth_max = 100; - } + qed_read_pf_bandwidth(p_hwfn, &shmem_info); if (shmem_info.mac_upper || shmem_info.mac_lower) { info->mac[0] = (u8)(shmem_info.mac_upper >> 8); @@ -938,9 +969,10 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, p_drv_version = &union_data.drv_version; p_drv_version->version = p_ver->version; + for (i = 0; i < MCP_DRV_VER_STR_SIZE - 1; i += 4) { val = cpu_to_be32(p_ver->name[i]); - *(u32 *)&p_drv_version->name[i * sizeof(u32)] = val; + *(__be32 *)&p_drv_version->name[i * sizeof(u32)] = val; } memset(&mb_params, 0, sizeof(mb_params)); diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 50917a2131a5..29a51ada038c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -40,7 +40,13 @@ struct qed_mcp_link_capabilities { struct qed_mcp_link_state { bool link_up; - u32 speed; /* In Mb/s */ + /* Actual link speed in Mb/s */ + u32 line_speed; + + /* PF max speed in Mb/s, deduced from line_speed + * according to PF max bandwidth configuration. + */ + u32 speed; bool full_duplex; bool an; @@ -388,5 +394,9 @@ int qed_mcp_reset(struct qed_hwfn *p_hwfn, * @return true iff MFW is running and mcp_info is initialized */ bool qed_mcp_is_init(struct qed_hwfn *p_hwfn); - +int qed_configure_pf_max_bandwidth(struct qed_dev *cdev, u8 max_bw); +int __qed_configure_pf_max_bandwidth(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_mcp_link_state *p_link, + u8 max_bw); #endif -- GitLab From a64b02d5301cc7da7ac33ae3b3531ab1262d196e Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Tue, 26 Apr 2016 10:56:10 -0400 Subject: [PATCH 4592/9938] qed: Add PF min bandwidth configuration support This patch adds support for PF minimum bandwidth update or configuration notified by management firmware. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_dev.c | 71 +++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_hsi.h | 2 + .../ethernet/qlogic/qed/qed_init_fw_funcs.c | 15 ++++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 10 ++- drivers/net/ethernet/qlogic/qed/qed_mcp.h | 7 ++ .../net/ethernet/qlogic/qed/qed_reg_addr.h | 1 + 6 files changed, 104 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 4e99108d9427..b500c86d7d06 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -220,9 +220,13 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn) qm_info->start_vport = (u8)RESC_START(p_hwfn, QED_VPORT); + for (i = 0; i < qm_info->num_vports; i++) + qm_info->qm_vport_params[i].vport_wfq = 1; + qm_info->pf_wfq = 0; qm_info->pf_rl = 0; qm_info->vport_rl_en = 1; + qm_info->vport_wfq_en = 1; return 0; @@ -1841,3 +1845,70 @@ int qed_configure_pf_max_bandwidth(struct qed_dev *cdev, u8 max_bw) return rc; } + +int __qed_configure_pf_min_bandwidth(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_mcp_link_state *p_link, + u8 min_bw) +{ + int rc = 0; + + p_hwfn->mcp_info->func_info.bandwidth_min = min_bw; + p_hwfn->qm_info.pf_wfq = min_bw; + + if (!p_link->line_speed) + return rc; + + p_link->min_pf_rate = (p_link->line_speed * min_bw) / 100; + + rc = qed_init_pf_wfq(p_hwfn, p_ptt, p_hwfn->rel_pf_id, min_bw); + + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Configured MIN bandwidth to be %d Mb/sec\n", + p_link->min_pf_rate); + + return rc; +} + +/* Main API to configure PF min bandwidth where bw range is [1-100] */ +int qed_configure_pf_min_bandwidth(struct qed_dev *cdev, u8 min_bw) +{ + int i, rc = -EINVAL; + + if (min_bw < 1 || min_bw > 100) { + DP_NOTICE(cdev, "PF min bw valid range is [1-100]\n"); + return rc; + } + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + struct qed_hwfn *p_lead = QED_LEADING_HWFN(cdev); + struct qed_mcp_link_state *p_link; + struct qed_ptt *p_ptt; + + p_link = &p_lead->mcp_info->link_output; + + p_ptt = qed_ptt_acquire(p_hwfn); + if (!p_ptt) + return -EBUSY; + + rc = __qed_configure_pf_min_bandwidth(p_hwfn, p_ptt, + p_link, min_bw); + if (rc) { + qed_ptt_release(p_hwfn, p_ptt); + return rc; + } + + if (p_link->min_pf_rate) { + u32 min_rate = p_link->min_pf_rate; + + rc = __qed_configure_vp_wfq_on_link_change(p_hwfn, + p_ptt, + min_rate); + } + + qed_ptt_release(p_hwfn, p_ptt); + } + + return rc; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 81cf62573ec4..5aa78a9ae17f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -5116,6 +5116,8 @@ struct hw_set_image { struct hw_set_info hw_sets[1]; }; +int qed_init_pf_wfq(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + u8 pf_id, u16 pf_wfq); int qed_init_vport_wfq(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u16 first_tx_pq_id[NUM_OF_TCS], u16 vport_wfq); #endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c index e646987a3d41..e8a3b9da59b5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c +++ b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c @@ -712,6 +712,21 @@ int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn, return 0; } +int qed_init_pf_wfq(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 pf_id, u16 pf_wfq) +{ + u32 inc_val = QM_WFQ_INC_VAL(pf_wfq); + + if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration"); + return -1; + } + + qed_wr(p_hwfn, p_ptt, QM_REG_WFQPFWEIGHT + pf_id * 4, inc_val); + return 0; +} + int qed_init_pf_rl(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u8 pf_id, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 578b09c2ae18..cb46dbdf47dd 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -472,8 +472,8 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, bool b_reset) { struct qed_mcp_link_state *p_link; + u8 max_bw, min_bw; u32 status = 0; - u8 max_bw; p_link = &p_hwfn->mcp_info->link_output; memset(p_link, 0, sizeof(*p_link)); @@ -534,10 +534,15 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, p_link->line_speed = 0; max_bw = p_hwfn->mcp_info->func_info.bandwidth_max; + min_bw = p_hwfn->mcp_info->func_info.bandwidth_min; - /* Correct speed according to bandwidth allocation */ + /* Max bandwidth configuration */ __qed_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw); + /* Min bandwidth configuration */ + __qed_configure_pf_min_bandwidth(p_hwfn, p_ptt, p_link, min_bw); + qed_configure_vp_wfq_on_link_change(p_hwfn->cdev, p_link->min_pf_rate); + p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED); p_link->an_complete = !!(status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE); @@ -710,6 +715,7 @@ static void qed_mcp_update_bw(struct qed_hwfn *p_hwfn, p_info = &p_hwfn->mcp_info->func_info; + qed_configure_pf_min_bandwidth(p_hwfn->cdev, p_info->bandwidth_min); qed_configure_pf_max_bandwidth(p_hwfn->cdev, p_info->bandwidth_max); /* Acknowledge the MFW */ diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 29a51ada038c..608bcb2403cb 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -40,6 +40,8 @@ struct qed_mcp_link_capabilities { struct qed_mcp_link_state { bool link_up; + u32 min_pf_rate; + /* Actual link speed in Mb/s */ u32 line_speed; @@ -394,9 +396,14 @@ int qed_mcp_reset(struct qed_hwfn *p_hwfn, * @return true iff MFW is running and mcp_info is initialized */ bool qed_mcp_is_init(struct qed_hwfn *p_hwfn); +int qed_configure_pf_min_bandwidth(struct qed_dev *cdev, u8 min_bw); int qed_configure_pf_max_bandwidth(struct qed_dev *cdev, u8 max_bw); int __qed_configure_pf_max_bandwidth(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, struct qed_mcp_link_state *p_link, u8 max_bw); +int __qed_configure_pf_min_bandwidth(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_mcp_link_state *p_link, + u8 min_bw); #endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index d2f57301cb3e..bf4d7ccd56bb 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -458,5 +458,6 @@ #define PBF_REG_NGE_COMP_VER 0xd80524UL #define PRS_REG_NGE_COMP_VER 0x1f0878UL +#define QM_REG_WFQPFWEIGHT 0x2f4e80UL #define QM_REG_WFQVPWEIGHT 0x2fa000UL #endif -- GitLab From 262178b6b8e500bdd07c6f369dffa6eeecf015b8 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Tue, 26 Apr 2016 15:00:24 +0200 Subject: [PATCH 4593/9938] ARM: dts: split am335x-baltos-ir5221 into dts and dtsi files Introduce am335x-baltos.dtsi, that provides common configuration for the whole device family based on the same SODIMM module. Signed-off-by: Yegor Yefremov Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-baltos-ir5221.dts | 387 +------------------ arch/arm/boot/dts/am335x-baltos.dtsi | 408 +++++++++++++++++++++ 2 files changed, 409 insertions(+), 386 deletions(-) create mode 100644 arch/arm/boot/dts/am335x-baltos.dtsi diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts index c743d5db1064..227cdfb4df08 100644 --- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts +++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts @@ -13,83 +13,19 @@ /dts-v1/; -#include "am33xx.dtsi" -#include -#include +#include "am335x-baltos.dtsi" / { model = "OnRISC Baltos iR 5221"; - compatible = "vscom,onrisc", "ti,am33xx"; - - cpus { - cpu@0 { - cpu0-supply = <&vdd1_reg>; - }; - }; - - memory { - device_type = "memory"; - reg = <0x80000000 0x10000000>; /* 256 MB */ - }; - - vbat: fixedregulator@0 { - compatible = "regulator-fixed"; - regulator-name = "vbat"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-boot-on; - }; - - wl12xx_vmmc: fixedregulator@2 { - pinctrl-names = "default"; - pinctrl-0 = <&wl12xx_gpio>; - compatible = "regulator-fixed"; - regulator-name = "vwl1271"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio3 8 0>; - startup-delay-us = <70000>; - enable-active-high; - }; }; &am33xx_pinmux { - mmc2_pins: pinmux_mmc2_pins { - pinctrl-single,pins = < - AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad8.mmc1_dat0_mux0 */ - AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad9.mmc1_dat1_mux0 */ - AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad10.mmc1_dat2_mux0 */ - AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad11.mmc1_dat3_mux0 */ - AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk_mux0 */ - AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd_mux0 */ - AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLUP | MUX_MODE7) /* emu0.gpio3[7] */ - >; - }; - - wl12xx_gpio: pinmux_wl12xx_gpio { - pinctrl-single,pins = < - AM33XX_IOPAD(0x9e8, PIN_OUTPUT_PULLUP | MUX_MODE7) /* emu1.gpio3[8] */ - >; - }; - - tps65910_pins: pinmux_tps65910_pins { - pinctrl-single,pins = < - AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ben1.gpio1[28] */ - >; - }; - tca6416_pins: pinmux_tca6416_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7) /* xdma_event_intr1.gpio0[20] tca6416 stuff */ >; }; - i2c1_pins: pinmux_i2c1_pins { - pinctrl-single,pins = < - AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE2) /* spi0_d1.i2c1_sda_mux3 */ - AM33XX_IOPAD(0x95c, PIN_INPUT | MUX_MODE2) /* spi0_cs0.i2c1_scl_mux3 */ - >; - }; dcan1_pins: pinmux_dcan1_pins { pinctrl-single,pins = < @@ -98,13 +34,6 @@ >; }; - uart0_pins: pinmux_uart0_pins { - pinctrl-single,pins = < - AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ - AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ - >; - }; - uart1_pins: pinmux_uart1_pins { pinctrl-single,pins = < AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd */ @@ -133,152 +62,6 @@ >; }; - cpsw_default: cpsw_default { - pinctrl-single,pins = < - /* Slave 1 */ - AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ - AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_tx_en.rmii1_txen */ - AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ - AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ - AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ - AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ - AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii1_refclk */ - - - /* Slave 2 */ - AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ - AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */ - AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */ - AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */ - AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */ - AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */ - AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */ - AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */ - AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */ - AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */ - AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */ - AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */ - >; - }; - - cpsw_sleep: cpsw_sleep { - pinctrl-single,pins = < - /* Slave 1 reset value */ - AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) - - /* Slave 2 reset value*/ - AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7) - >; - }; - - davinci_mdio_default: davinci_mdio_default { - pinctrl-single,pins = < - /* MDIO */ - AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ - AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ - >; - }; - - davinci_mdio_sleep: davinci_mdio_sleep { - pinctrl-single,pins = < - /* MDIO reset value */ - AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) - AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) - >; - }; - - nandflash_pins_s0: nandflash_pins_s0 { - pinctrl-single,pins = < - AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ - AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ - AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ - AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ - AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ - AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ - AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ - AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ - AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ - AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ - AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ - AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ - AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ - AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ - AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ - >; - }; -}; - -&elm { - status = "okay"; -}; - -&gpmc { - pinctrl-names = "default"; - pinctrl-0 = <&nandflash_pins_s0>; - ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ - status = "okay"; - - nand@0,0 { - compatible = "ti,omap2-nand"; - reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ - interrupt-parent = <&gpmc>; - interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ - <1 IRQ_TYPE_NONE>; /* termcount */ - rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ - nand-bus-width = <8>; - ti,nand-ecc-opt = "bch8"; - ti,nand-xfer-type = "polled"; - - gpmc,device-nand = "true"; - gpmc,device-width = <1>; - gpmc,sync-clk-ps = <0>; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <44>; - gpmc,cs-wr-off-ns = <44>; - gpmc,adv-on-ns = <6>; - gpmc,adv-rd-off-ns = <34>; - gpmc,adv-wr-off-ns = <44>; - gpmc,we-on-ns = <0>; - gpmc,we-off-ns = <40>; - gpmc,oe-on-ns = <0>; - gpmc,oe-off-ns = <54>; - gpmc,access-ns = <64>; - gpmc,rd-cycle-ns = <82>; - gpmc,wr-cycle-ns = <82>; - gpmc,bus-turnaround-ns = <0>; - gpmc,cycle2cycle-delay-ns = <0>; - gpmc,clk-activation-ns = <0>; - gpmc,wr-access-ns = <40>; - gpmc,wr-data-mux-bus-ns = <0>; - - #address-cells = <1>; - #size-cells = <1>; - elm_id = <&elm>; - }; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - - status = "okay"; }; &uart1 { @@ -304,28 +87,6 @@ }; &i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; - - status = "okay"; - clock-frequency = <400000>; - - tps: tps@2d { - reg = <0x2d>; - gpio-controller; - #gpio-cells = <2>; - interrupt-parent = <&gpio1>; - interrupts = <28 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&tps65910_pins>; - }; - - at24@50 { - compatible = "at24,24c02"; - pagesize = <8>; - reg = <0x50>; - }; - tca6416: gpio@20 { compatible = "ti,tca6416"; reg = <0x20>; @@ -338,14 +99,6 @@ }; }; -&usb { - status = "okay"; -}; - -&usb_ctrl_mod { - status = "okay"; -}; - &usb0_phy { status = "okay"; }; @@ -364,108 +117,6 @@ dr_mode = "otg"; }; -&cppi41dma { - status = "okay"; -}; - -#include "tps65910.dtsi" - -&tps { - vcc1-supply = <&vbat>; - vcc2-supply = <&vbat>; - vcc3-supply = <&vbat>; - vcc4-supply = <&vbat>; - vcc5-supply = <&vbat>; - vcc6-supply = <&vbat>; - vcc7-supply = <&vbat>; - vccio-supply = <&vbat>; - - ti,en-ck32k-xtal = <1>; - - regulators { - vrtc_reg: regulator@0 { - regulator-always-on; - }; - - vio_reg: regulator@1 { - regulator-always-on; - }; - - vdd1_reg: regulator@2 { - /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ - regulator-name = "vdd_mpu"; - regulator-min-microvolt = <912500>; - regulator-max-microvolt = <1312500>; - regulator-boot-on; - regulator-always-on; - }; - - vdd2_reg: regulator@3 { - /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ - regulator-name = "vdd_core"; - regulator-min-microvolt = <912500>; - regulator-max-microvolt = <1150000>; - regulator-boot-on; - regulator-always-on; - }; - - vdd3_reg: regulator@4 { - regulator-always-on; - }; - - vdig1_reg: regulator@5 { - regulator-always-on; - }; - - vdig2_reg: regulator@6 { - regulator-always-on; - }; - - vpll_reg: regulator@7 { - regulator-always-on; - }; - - vdac_reg: regulator@8 { - regulator-always-on; - }; - - vaux1_reg: regulator@9 { - regulator-always-on; - }; - - vaux2_reg: regulator@10 { - regulator-always-on; - }; - - vaux33_reg: regulator@11 { - regulator-always-on; - }; - - vmmc_reg: regulator@12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - }; -}; - -&mac { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&cpsw_default>; - pinctrl-1 = <&cpsw_sleep>; - dual_emac = <1>; - - status = "okay"; -}; - -&davinci_mdio { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&davinci_mdio_default>; - pinctrl-1 = <&davinci_mdio_sleep>; - - status = "okay"; -}; - &cpsw_emac0 { phy_id = <&davinci_mdio>, <0>; phy-mode = "rmii"; @@ -482,42 +133,6 @@ rmii-clock-ext = <1>; }; -&mmc1 { - vmmc-supply = <&vmmc_reg>; - status = "okay"; -}; - -&mmc2 { - status = "okay"; - vmmc-supply = <&wl12xx_vmmc>; - ti,non-removable; - bus-width = <4>; - cap-power-off-card; - pinctrl-names = "default"; - pinctrl-0 = <&mmc2_pins>; - - #address-cells = <1>; - #size-cells = <0>; - wlcore: wlcore@2 { - compatible = "ti,wl1835"; - reg = <2>; - interrupt-parent = <&gpio3>; - interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; - }; -}; - -&sham { - status = "okay"; -}; - -&aes { - status = "okay"; -}; - -&gpio0 { - ti,no-reset-on-init; -}; - &dcan1 { pinctrl-names = "default"; pinctrl-0 = <&dcan1_pins>; diff --git a/arch/arm/boot/dts/am335x-baltos.dtsi b/arch/arm/boot/dts/am335x-baltos.dtsi new file mode 100644 index 000000000000..c8609d8d2c55 --- /dev/null +++ b/arch/arm/boot/dts/am335x-baltos.dtsi @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * VScom OnRISC + * http://www.vscom.de + */ + +#include "am33xx.dtsi" +#include +#include + +/ { + compatible = "vscom,onrisc", "ti,am33xx"; + + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + wl12xx_vmmc: fixedregulator@2 { + pinctrl-names = "default"; + pinctrl-0 = <&wl12xx_gpio>; + compatible = "regulator-fixed"; + regulator-name = "vwl1271"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 8 0>; + startup-delay-us = <70000>; + enable-active-high; + }; +}; + +&am33xx_pinmux { + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad8.mmc1_dat0_mux0 */ + AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad9.mmc1_dat1_mux0 */ + AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad10.mmc1_dat2_mux0 */ + AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad11.mmc1_dat3_mux0 */ + AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk_mux0 */ + AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd_mux0 */ + AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLUP | MUX_MODE7) /* emu0.gpio3[7] */ + >; + }; + + wl12xx_gpio: pinmux_wl12xx_gpio { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9e8, PIN_OUTPUT_PULLUP | MUX_MODE7) /* emu1.gpio3[8] */ + >; + }; + + tps65910_pins: pinmux_tps65910_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ben1.gpio1[28] */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE2) /* spi0_d1.i2c1_sda_mux3 */ + AM33XX_IOPAD(0x95c, PIN_INPUT | MUX_MODE2) /* spi0_cs0.i2c1_scl_mux3 */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ + AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_tx_en.rmii1_txen */ + AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii1_refclk */ + + + /* Slave 2 */ + AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ + AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */ + AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */ + AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */ + AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */ + AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */ + AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */ + AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */ + AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */ + AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */ + AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */ + AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) + + /* Slave 2 reset value*/ + AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + nandflash_pins_s0: nandflash_pins_s0 { + pinctrl-single,pins = < + AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ + AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins_s0>; + ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ + status = "okay"; + + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ + nand-bus-width = <8>; + ti,nand-ecc-opt = "bch8"; + ti,nand-xfer-type = "polled"; + + gpmc,device-nand = "true"; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + elm_id = <&elm>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + status = "okay"; + clock-frequency = <400000>; + + tps: tps@2d { + reg = <0x2d>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio1>; + interrupts = <28 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&tps65910_pins>; + }; + + at24@50 { + compatible = "at24,24c02"; + pagesize = <8>; + reg = <0x50>; + }; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + ti,en-ck32k-xtal = <1>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + dual_emac = <1>; + + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + + status = "okay"; +}; + +&mmc1 { + vmmc-supply = <&vmmc_reg>; + status = "okay"; +}; + +&mmc2 { + status = "okay"; + vmmc-supply = <&wl12xx_vmmc>; + ti,non-removable; + bus-width = <4>; + cap-power-off-card; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + + #address-cells = <1>; + #size-cells = <0>; + wlcore: wlcore@2 { + compatible = "ti,wl1835"; + reg = <2>; + interrupt-parent = <&gpio3>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&gpio0 { + ti,no-reset-on-init; +}; -- GitLab From d78b610eea83ba3e6a7810e07ac8f6e9859da493 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Tue, 26 Apr 2016 15:00:25 +0200 Subject: [PATCH 4594/9938] ARM: dts: add DTS for Baltos IR3220 Signed-off-by: Yegor Yefremov Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/am335x-baltos-ir3220.dts | 119 +++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 arch/arm/boot/dts/am335x-baltos-ir3220.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index e32392228748..2c19cd9f39a6 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -485,6 +485,7 @@ dtb-$(CONFIG_SOC_TI81XX) += \ dm8168-evm.dtb \ dra62x-j5eco-evm.dtb dtb-$(CONFIG_SOC_AM33XX) += \ + am335x-baltos-ir3220.dtb \ am335x-baltos-ir5221.dtb \ am335x-base0033.dtb \ am335x-bone.dtb \ diff --git a/arch/arm/boot/dts/am335x-baltos-ir3220.dts b/arch/arm/boot/dts/am335x-baltos-ir3220.dts new file mode 100644 index 000000000000..fe002a17c04b --- /dev/null +++ b/arch/arm/boot/dts/am335x-baltos-ir3220.dts @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * VScom OnRISC + * http://www.vscom.de + */ + +/dts-v1/; + +#include "am335x-baltos.dtsi" + +/ { + model = "OnRISC Baltos iR 3220"; +}; + +&am33xx_pinmux { + tca6416_pins: pinmux_tca6416_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7) /* xdma_event_intr1.gpio0[20] tca6416 stuff */ + >; + }; + + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd */ + AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0) /* uart1_txd */ + AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart1_ctsn */ + AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn */ + AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.gpio2[22] DTR */ + AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2[23] DSR */ + AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.gpio2[24] DCD */ + AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.gpio2[25] RI */ + >; + }; + + uart2_pins: pinmux_uart2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd_mux3 */ + AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd_mux3 */ + AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2) /* i2c0_sda.uart2_ctsn_mux0 */ + AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* i2c0_scl.uart2_rtsn_mux0 */ + AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.gpio1[12] DTR */ + AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.gpio1[13] DSR */ + AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.gpio1[14] DCD */ + AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.gpio1[15] RI */ + + AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7) /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */ + >; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>; + dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; + dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>; + rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&i2c1 { + tca6416: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio0>; + interrupts = <20 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&tca6416_pins>; + }; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&cpsw_emac0 { + phy-mode = "rmii"; + dual_emac_res_vlan = <1>; + fixed-link { + speed = <100>; + full-duplex; + }; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <7>; + phy-mode = "rgmii-txid"; + dual_emac_res_vlan = <2>; +}; + +&phy_sel { + rmii-clock-ext = <1>; +}; -- GitLab From c2fc0ad945d0cdb97a871046dc4ff1096e3ce266 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Tue, 26 Apr 2016 15:00:26 +0200 Subject: [PATCH 4595/9938] ARM: dts: add DTS for Baltos IR2110 Signed-off-by: Yegor Yefremov Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/am335x-baltos-ir2110.dts | 71 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 arch/arm/boot/dts/am335x-baltos-ir2110.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 2c19cd9f39a6..64a2bc6b30ec 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -485,6 +485,7 @@ dtb-$(CONFIG_SOC_TI81XX) += \ dm8168-evm.dtb \ dra62x-j5eco-evm.dtb dtb-$(CONFIG_SOC_AM33XX) += \ + am335x-baltos-ir2110.dtb \ am335x-baltos-ir3220.dtb \ am335x-baltos-ir5221.dtb \ am335x-base0033.dtb \ diff --git a/arch/arm/boot/dts/am335x-baltos-ir2110.dts b/arch/arm/boot/dts/am335x-baltos-ir2110.dts new file mode 100644 index 000000000000..a9a97307d66c --- /dev/null +++ b/arch/arm/boot/dts/am335x-baltos-ir2110.dts @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * VScom OnRISC + * http://www.vscom.de + */ + +/dts-v1/; + +#include "am335x-baltos.dtsi" + +/ { + model = "OnRISC Baltos iR 2110"; +}; + +&am33xx_pinmux { + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd */ + AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0) /* uart1_txd */ + AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart1_ctsn */ + AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn */ + AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.gpio2[22] DTR */ + AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2[23] DSR */ + AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.gpio2[24] DCD */ + AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.gpio2[25] RI */ + >; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>; + dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; + dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>; + rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <7>; + phy-mode = "rgmii-txid"; + dual_emac_res_vlan = <2>; +}; + +&phy_sel { + rmii-clock-ext = <1>; +}; -- GitLab From 4afe6495e5cb3c352d95f07512cbb227e607e2ce Mon Sep 17 00:00:00 2001 From: Wang Xiaoqiang Date: Mon, 18 Apr 2016 15:23:29 +0800 Subject: [PATCH 4596/9938] tracing: Don't use the address of the buffer array name in copy_from_user With the following code snippet: ... char buf[64]; ... if (copy_from_user(&buf, ubuf, cnt)) ... Even though the value of "&buf" equals "buf", but there is no need to get the address of the "buf" again. Use "buf" instead of "&buf". Link: http://lkml.kernel.org/r/20160418152329.18b72bea@debian Signed-off-by: Wang Xiaoqiang Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 5e3ad3481e4b..46028d47d252 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3664,7 +3664,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf, if (cnt >= sizeof(buf)) return -EINVAL; - if (copy_from_user(&buf, ubuf, cnt)) + if (copy_from_user(buf, ubuf, cnt)) return -EFAULT; buf[cnt] = 0; @@ -4537,7 +4537,7 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, if (cnt > MAX_TRACER_SIZE) cnt = MAX_TRACER_SIZE; - if (copy_from_user(&buf, ubuf, cnt)) + if (copy_from_user(buf, ubuf, cnt)) return -EFAULT; buf[cnt] = 0; @@ -5327,7 +5327,7 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf, if (cnt >= sizeof(buf)) return -EINVAL; - if (copy_from_user(&buf, ubuf, cnt)) + if (copy_from_user(buf, ubuf, cnt)) return -EFAULT; buf[cnt] = 0; -- GitLab From 0b26985a7d76645598d98fec6922ddd1ec8cbc55 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 16 Apr 2016 13:50:03 +0100 Subject: [PATCH 4597/9938] PM / clk: ensure we don't allocate a -ve size of count clks It is entirely possible for of_count_phandle_wit_args to return a -ve error return value so we need to check for this otherwise we end up allocating a negative number of clk objects. Signed-off-by: Colin Ian King Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- drivers/base/power/clock_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 0e64a1b5e62a..3657ac1cb801 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -159,7 +159,7 @@ int of_pm_clk_add_clks(struct device *dev) count = of_count_phandle_with_args(dev->of_node, "clocks", "#clock-cells"); - if (count == 0) + if (count <= 0) return -ENODEV; clks = kcalloc(count, sizeof(*clks), GFP_KERNEL); -- GitLab From 308379607548524b8d86dbf20134681024935e0b Mon Sep 17 00:00:00 2001 From: Francesco Ruggeri Date: Sat, 23 Apr 2016 15:03:32 -0700 Subject: [PATCH 4598/9938] macvlan: fix failure during registration v3 If macvlan_common_newlink fails in register_netdevice after macvlan_init then it decrements port->count twice, first in macvlan_uninit (from register_netdevice or rollback_registered) and then again in macvlan_common_newlink. A similar problem may exist in the ipvlan driver. This patch consolidates modifications to port->count into macvlan_init and macvlan_uninit (thanks to Eric Biederman for suggesting this approach). v3: remove macvtap specific bits. Signed-off-by: Francesco Ruggeri Acked-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 2bcf1f321bea..cb01023eab41 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -795,6 +795,7 @@ static int macvlan_init(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); const struct net_device *lowerdev = vlan->lowerdev; + struct macvlan_port *port = vlan->port; dev->state = (dev->state & ~MACVLAN_STATE_MASK) | (lowerdev->state & MACVLAN_STATE_MASK); @@ -812,6 +813,8 @@ static int macvlan_init(struct net_device *dev) if (!vlan->pcpu_stats) return -ENOMEM; + port->count += 1; + return 0; } @@ -1312,10 +1315,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, return err; } - port->count += 1; err = register_netdevice(dev); if (err < 0) - goto destroy_port; + return err; dev->priv_flags |= IFF_MACVLAN; err = netdev_upper_dev_link(lowerdev, dev); @@ -1330,10 +1332,6 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, unregister_netdev: unregister_netdevice(dev); -destroy_port: - port->count -= 1; - if (!port->count) - macvlan_port_destroy(lowerdev); return err; } -- GitLab From e96c37f185529d1db4ebc021e4f56822d43945bb Mon Sep 17 00:00:00 2001 From: Francesco Ruggeri Date: Sat, 23 Apr 2016 15:04:31 -0700 Subject: [PATCH 4599/9938] macvtap: check minor when unregistering macvtap_device_event(NETDEV_UNREGISTER) should check vlan->minor to determine if it is being invoked in the context of a macvtap_newlink that failed, for example in this code sequence: macvtap_newlink macvlan_common_newlink register_netdevice call_netdevice_notifiers(NETDEV_REGISTER, dev) macvtap_device_event(NETDEV_REGISTER) minor = 0> rollback_registered(dev); rollback_registered_many call_netdevice_notifiers(NETDEV_UNREGISTER, dev); macvtap_device_event(NETDEV_UNREGISTER) Signed-off-by: Francesco Ruggeri Acked-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 95394edd1ed5..74cb15a2e032 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -1303,6 +1303,9 @@ static int macvtap_device_event(struct notifier_block *unused, } break; case NETDEV_UNREGISTER: + /* vlan->minor == 0 if NETDEV_REGISTER above failed */ + if (vlan->minor == 0) + break; devt = MKDEV(MAJOR(macvtap_major), vlan->minor); device_destroy(macvtap_class, devt); macvtap_free_minor(vlan); -- GitLab From f052f20a825a80c4662dafd3899dddafd4c8f036 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sun, 24 Apr 2016 23:21:22 +0800 Subject: [PATCH 4600/9938] sctp: sctp_diag should fill RMEM_ALLOC with asoc->rmem_alloc when rcvbuf_policy is set For sctp assoc, when rcvbuf_policy is set, it will has it's own rmem_alloc, when we dump asoc info in sctp_diag, we should use that value on RMEM_ALLOC as well, just like WMEM_ALLOC. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/sctp_diag.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c index 84829fff3bc9..8e3e769dc9ea 100644 --- a/net/sctp/sctp_diag.c +++ b/net/sctp/sctp_diag.c @@ -145,7 +145,11 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc, else amt = sk_wmem_alloc_get(sk); mem[SK_MEMINFO_WMEM_ALLOC] = amt; - mem[SK_MEMINFO_RMEM_ALLOC] = sk_rmem_alloc_get(sk); + if (asoc && asoc->ep->rcvbuf_policy) + amt = atomic_read(&asoc->rmem_alloc); + else + amt = sk_rmem_alloc_get(sk); + mem[SK_MEMINFO_RMEM_ALLOC] = amt; mem[SK_MEMINFO_RCVBUF] = sk->sk_rcvbuf; mem[SK_MEMINFO_SNDBUF] = sk->sk_sndbuf; mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc; -- GitLab From 6c51cc0203de25aeaff9d0236d6c2b497be93e3b Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Fri, 22 Apr 2016 10:17:19 -0700 Subject: [PATCH 4601/9938] powercap/intel_rapl: Add support for Kabylake Kabylake is similar to Skylake in terms of RAPL. Signed-off-by: Jacob Pan Signed-off-by: Rafael J. Wysocki --- drivers/powercap/intel_rapl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 8fad0a7044d3..470bb622fd8c 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -1101,6 +1101,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { RAPL_CPU(0X5C, rapl_defaults_core),/* Broxton */ RAPL_CPU(0x5E, rapl_defaults_core),/* Skylake-H/S */ RAPL_CPU(0x57, rapl_defaults_hsw_server),/* Knights Landing */ + RAPL_CPU(0x8E, rapl_defaults_core),/* Kabylake */ + RAPL_CPU(0x9E, rapl_defaults_core),/* Kabylake */ {} }; MODULE_DEVICE_TABLE(x86cpu, rapl_ids); -- GitLab From f796721040f933bb51b33f53899a382b4872b3e6 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 19:11:07 +0300 Subject: [PATCH 4602/9938] sh_eth: get rid of the 2nd parameter to sh_eth_dev_init() sh_eth_dev_init() is now always called with 'true' as the 2nd argument, so that there's no more sense in having 2 parameters to this function... Signed-off-by: Sergei Shtylyov Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index ceea74cc2229..edf6356c7034 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1229,7 +1229,7 @@ static int sh_eth_ring_init(struct net_device *ndev) return -ENOMEM; } -static int sh_eth_dev_init(struct net_device *ndev, bool start) +static int sh_eth_dev_init(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); int ret; @@ -1279,10 +1279,8 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start) RFLR); sh_eth_modify(ndev, EESR, 0, 0); - if (start) { - mdp->irq_enabled = true; - sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); - } + mdp->irq_enabled = true; + sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); /* PAUSE Prohibition */ sh_eth_write(ndev, ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | @@ -1295,8 +1293,7 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start) sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR); /* E-MAC Interrupt Enable register */ - if (start) - sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR); + sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR); /* Set MAC address */ update_mac_address(ndev); @@ -1309,10 +1306,8 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start) if (mdp->cd->tpauser) sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER); - if (start) { - /* Setting the Rx mode will start the Rx process. */ - sh_eth_write(ndev, EDRRR_R, EDRRR); - } + /* Setting the Rx mode will start the Rx process. */ + sh_eth_write(ndev, EDRRR_R, EDRRR); return ret; } @@ -2194,7 +2189,7 @@ static int sh_eth_set_ringparam(struct net_device *ndev, __func__); return ret; } - ret = sh_eth_dev_init(ndev, true); + ret = sh_eth_dev_init(ndev); if (ret < 0) { netdev_err(ndev, "%s: sh_eth_dev_init failed.\n", __func__); @@ -2246,7 +2241,7 @@ static int sh_eth_open(struct net_device *ndev) goto out_free_irq; /* device init */ - ret = sh_eth_dev_init(ndev, true); + ret = sh_eth_dev_init(ndev); if (ret) goto out_free_irq; @@ -2299,7 +2294,7 @@ static void sh_eth_tx_timeout(struct net_device *ndev) } /* device init */ - sh_eth_dev_init(ndev, true); + sh_eth_dev_init(ndev); netif_start_queue(ndev); } -- GitLab From b74766a0a0feeef5c779709cc5d109451c0d5b17 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 20:25:23 +0300 Subject: [PATCH 4603/9938] phylib: don't return NULL from get_phy_device() Arnd Bergmann asked that get_phy_device() returns either NULL or the error value, not both on error. Do as he said, return ERR_PTR(-ENODEV) instead of NULL when the PHY ID registers read as all ones. Suggested-by: Arnd Bergmann Signed-off-by: Sergei Shtylyov Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 10e39c2fbf81..e977ba931878 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -529,7 +529,7 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45) /* If the phy_id is mostly Fs, there is no device there */ if ((phy_id & 0x1fffffff) == 0x1fffffff) - return NULL; + return ERR_PTR(-ENODEV); return phy_device_create(bus, addr, phy_id, is_c45, &c45_ids); } -- GitLab From fb1116ab7cf55f9b022c2a2d40a0f0c4464eb201 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 20:27:49 +0300 Subject: [PATCH 4604/9938] xgene: get_phy_device() doesn't return NULL anymore Now that get_phy_device() no longer returns NULL on error, we don't need to check for it... Signed-off-by: Sergei Shtylyov Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 39e081a70f5b..457f74500242 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -824,7 +824,7 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata, return -EINVAL; phy = get_phy_device(mdio, phy_id, false); - if (!phy || IS_ERR(phy)) + if (IS_ERR(phy)) return -EIO; ret = phy_device_register(phy); -- GitLab From 4914a584b1d66680532b20898cba1cf7d5ae63e4 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 20:29:23 +0300 Subject: [PATCH 4605/9938] fixed_phy: get_phy_device() doesn't return NULL anymore Now that get_phy_device() no longer returns NULL on error, we don't need to check for it... Signed-off-by: Sergei Shtylyov Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/fixed_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index fc07a8866020..9050f21e6f33 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -328,7 +328,7 @@ struct phy_device *fixed_phy_register(unsigned int irq, return ERR_PTR(ret); phy = get_phy_device(fmb->mii_bus, phy_addr, false); - if (!phy || IS_ERR(phy)) { + if (IS_ERR(phy)) { fixed_phy_del(phy_addr); return ERR_PTR(-EINVAL); } -- GitLab From 66c239e71adee694bc35f44387fb373942cfd957 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 20:30:53 +0300 Subject: [PATCH 4606/9938] mdio_bus: get_phy_device() doesn't return NULL anymore Now that get_phy_device() no longer returns NULL on error, we don't need to check for it... Signed-off-by: Sergei Shtylyov Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 751202a285a6..499003ee8055 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -419,7 +419,7 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) int err; phydev = get_phy_device(bus, addr, false); - if (IS_ERR(phydev) || phydev == NULL) + if (IS_ERR(phydev)) return phydev; /* -- GitLab From af5840a968fcb175900e5b821f37363a089f5b75 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 20:31:42 +0300 Subject: [PATCH 4607/9938] of_mdio: get_phy_device() doesn't return NULL anymore Now that get_phy_device() no longer returns NULL on error, we don't need to check for it... Signed-off-by: Sergei Shtylyov Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 2c1e52e06102..b622b33dbf93 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -56,7 +56,7 @@ static void of_mdiobus_register_phy(struct mii_bus *mdio, phy = phy_device_create(mdio, addr, phy_id, 0, NULL); else phy = get_phy_device(mdio, addr, is_c45); - if (IS_ERR_OR_NULL(phy)) + if (IS_ERR(phy)) return; rc = irq_of_parse_and_map(child, 0); -- GitLab From 8e4ff6f228e4722cac74db716e308d1da33d744f Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 8 Apr 2016 13:52:00 -0400 Subject: [PATCH 4608/9938] selinux: distinguish non-init user namespace capability checks Distinguish capability checks against a target associated with the init user namespace versus capability checks against a target associated with a non-init user namespace by defining and using separate security classes for the latter. This is needed to support e.g. Chrome usage of user namespaces for the Chrome sandbox without needing to allow Chrome to also exercise capabilities on targets in the init user namespace. Suggested-by: Dan Walsh Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/hooks.c | 14 +++++++------- security/selinux/include/classmap.h | 28 ++++++++++++++++++---------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 474011c46bbd..bbff80c6d3f2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1631,7 +1631,7 @@ static int current_has_perm(const struct task_struct *tsk, /* Check whether a task is allowed to use a capability. */ static int cred_has_capability(const struct cred *cred, - int cap, int audit) + int cap, int audit, bool initns) { struct common_audit_data ad; struct av_decision avd; @@ -1645,10 +1645,10 @@ static int cred_has_capability(const struct cred *cred, switch (CAP_TO_INDEX(cap)) { case 0: - sclass = SECCLASS_CAPABILITY; + sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS; break; case 1: - sclass = SECCLASS_CAPABILITY2; + sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS; break; default: printk(KERN_ERR @@ -2152,7 +2152,7 @@ static int selinux_capset(struct cred *new, const struct cred *old, static int selinux_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit) { - return cred_has_capability(cred, cap, audit); + return cred_has_capability(cred, cap, audit, ns == &init_user_ns); } static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) @@ -2230,7 +2230,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) int rc, cap_sys_admin = 0; rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, - SECURITY_CAP_NOAUDIT); + SECURITY_CAP_NOAUDIT, true); if (rc == 0) cap_sys_admin = 1; @@ -3213,7 +3213,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void SECURITY_CAP_NOAUDIT); if (!error) error = cred_has_capability(current_cred(), CAP_MAC_ADMIN, - SECURITY_CAP_NOAUDIT); + SECURITY_CAP_NOAUDIT, true); isec = inode_security(inode); if (!error) error = security_sid_to_context_force(isec->sid, &context, @@ -3390,7 +3390,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, case KDSKBENT: case KDSKBSENT: error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, - SECURITY_CAP_AUDIT); + SECURITY_CAP_AUDIT, true); break; /* default case assumes that the command will go diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 8fbd1383d75e..1f1f4b2f6018 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -12,6 +12,18 @@ #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ "write", "associate", "unix_read", "unix_write" +#define COMMON_CAP_PERMS "chown", "dac_override", "dac_read_search", \ + "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", \ + "linux_immutable", "net_bind_service", "net_broadcast", \ + "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", \ + "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", \ + "sys_boot", "sys_nice", "sys_resource", "sys_time", \ + "sys_tty_config", "mknod", "lease", "audit_write", \ + "audit_control", "setfcap" + +#define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \ + "wake_alarm", "block_suspend", "audit_read" + /* * Note: The name for any socket class should be suffixed by "socket", * and doesn't contain more than one substr of "socket". @@ -34,14 +46,7 @@ struct security_class_mapping secclass_map[] = { { "ipc_info", "syslog_read", "syslog_mod", "syslog_console", "module_request", "module_load", NULL } }, { "capability", - { "chown", "dac_override", "dac_read_search", - "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", - "linux_immutable", "net_bind_service", "net_broadcast", - "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", - "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", - "sys_boot", "sys_nice", "sys_resource", "sys_time", - "sys_tty_config", "mknod", "lease", "audit_write", - "audit_control", "setfcap", NULL } }, + { COMMON_CAP_PERMS, NULL } }, { "filesystem", { "mount", "remount", "unmount", "getattr", "relabelfrom", "relabelto", "associate", "quotamod", @@ -150,12 +155,15 @@ struct security_class_mapping secclass_map[] = { { "memprotect", { "mmap_zero", NULL } }, { "peer", { "recv", NULL } }, { "capability2", - { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", - "audit_read", NULL } }, + { COMMON_CAP2_PERMS, NULL } }, { "kernel_service", { "use_as_override", "create_files_as", NULL } }, { "tun_socket", { COMMON_SOCK_PERMS, "attach_queue", NULL } }, { "binder", { "impersonate", "call", "set_context_mgr", "transfer", NULL } }, + { "cap_userns", + { COMMON_CAP_PERMS, NULL } }, + { "cap2_userns", + { COMMON_CAP2_PERMS, NULL } }, { NULL } }; -- GitLab From c2316dbf124257ae19fd2e29cb5ec51060649d38 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 8 Apr 2016 13:55:03 -0400 Subject: [PATCH 4609/9938] selinux: apply execstack check on thread stacks The execstack check was only being applied on the main process stack. Thread stacks allocated via mmap were only subject to the execmem permission check. Augment the check to apply to the current thread stack as well. Note that this does NOT prevent making a different thread's stack executable. Suggested-by: Nick Kralevich Acked-by: Nick Kralevich Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/hooks.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index bbff80c6d3f2..a00ab81ab719 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3479,8 +3479,9 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, vma->vm_end <= vma->vm_mm->brk) { rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); } else if (!vma->vm_file && - vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack) { + ((vma->vm_start <= vma->vm_mm->start_stack && + vma->vm_end >= vma->vm_mm->start_stack) || + vma_is_stack_for_task(vma, current))) { rc = current_has_perm(current, PROCESS__EXECSTACK); } else if (vma->vm_file && vma->anon_vma) { /* -- GitLab From 96bab35d1c4ab706922abd7cef8262fdca07664a Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Tue, 26 Apr 2016 11:52:01 -0700 Subject: [PATCH 4610/9938] localmodconfig: Reset certificate paths When using `make localmodconfig` and friends, if the input config comes from a kernel that was built in a different environment (for example, the canonical case of using localmodconfig to trim a distribution kernel config) the key files for module signature checking will not be available and should be regenerated or omitted. Otherwise, the user will be faced with annoying errors when trying to build with the generated .config: make[1]: *** No rule to make target 'keyring.crt', needed by 'certs/x509_certificate_list'. Stop. Makefile:1576: recipe for target 'certs/' failed Link: http://lkml.kernel.org/r/1461696721-3001-1-git-send-email-bpoirier@suse.com Signed-off-by: Benjamin Poirier Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 01b53eccfe2f..95a6f2b888d4 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -610,6 +610,40 @@ foreach my $line (@config_file) { next; } + if (/CONFIG_MODULE_SIG_KEY="(.+)"/) { + my $orig_cert = $1; + my $default_cert = "certs/signing_key.pem"; + + # Check that the logic in this script still matches the one in Kconfig + if (!defined($depends{"MODULE_SIG_KEY"}) || + $depends{"MODULE_SIG_KEY"} !~ /"\Q$default_cert\E"/) { + print STDERR "WARNING: MODULE_SIG_KEY assertion failure, ", + "update needed to ", __FILE__, " line ", __LINE__, "\n"; + print; + } elsif ($orig_cert ne $default_cert && ! -f $orig_cert) { + print STDERR "Module signature verification enabled but ", + "module signing key \"$orig_cert\" not found. Resetting ", + "signing key to default value.\n"; + print "CONFIG_MODULE_SIG_KEY=\"$default_cert\"\n"; + } else { + print; + } + next; + } + + if (/CONFIG_SYSTEM_TRUSTED_KEYS="(.+)"/) { + my $orig_keys = $1; + + if (! -f $orig_keys) { + print STDERR "System keyring enabled but keys \"$orig_keys\" ", + "not found. Resetting keys to default value.\n"; + print "CONFIG_SYSTEM_TRUSTED_KEYS=\"\"\n"; + } else { + print; + } + next; + } + if (/^(CONFIG.*)=(m|y)/) { if (defined($configs{$1})) { if ($localyesconfig) { -- GitLab From 47975cd1022d12735f02046ef8ada83f8ad24087 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 24 Apr 2016 21:38:09 +0200 Subject: [PATCH 4611/9938] RDMA/nes: remove use of NETDEV_TX_LOCKED ndo_start_xmit never returns it to stack, but nes_nic_send helper used it if skb could not be queued to hardware. Switch to bool instead. Cc: Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_nic.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 3ea9e055fdd3..b09a6db80201 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -356,7 +356,7 @@ static int nes_netdev_stop(struct net_device *netdev) /** * nes_nic_send */ -static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev) +static bool nes_nic_send(struct sk_buff *skb, struct net_device *netdev) { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; @@ -413,7 +413,7 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev) netdev->name, skb_shinfo(skb)->nr_frags + 2, skb_headlen(skb)); kfree_skb(skb); nesvnic->tx_sw_dropped++; - return NETDEV_TX_LOCKED; + return false; } set_bit(nesnic->sq_head, nesnic->first_frag_overflow); bus_address = pci_map_single(nesdev->pcidev, skb->data + NES_FIRST_FRAG_SIZE, @@ -454,8 +454,7 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev) set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX, wqe_misc); nesnic->sq_head++; nesnic->sq_head &= nesnic->sq_size - 1; - - return NETDEV_TX_OK; + return true; } @@ -673,13 +672,11 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev) skb_linearize(skb); skb_set_transport_header(skb, hoffset); skb_set_network_header(skb, nhoffset); - send_rc = nes_nic_send(skb, netdev); - if (send_rc != NETDEV_TX_OK) + if (!nes_nic_send(skb, netdev)) return NETDEV_TX_OK; } } else { - send_rc = nes_nic_send(skb, netdev); - if (send_rc != NETDEV_TX_OK) + if (!nes_nic_send(skb, netdev)) return NETDEV_TX_OK; } -- GitLab From 353e3bd5a7081f23a9f015cbf172ec25b1412b93 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 24 Apr 2016 21:38:10 +0200 Subject: [PATCH 4612/9938] atl1c: remove private tx lock AFAICS this is safe: the lock is only used in the .ndo_start_xmit function and this driver does not set LLTX. Gets rid of TX_LOCKED return value, followup patches will remove it. Cc: Jay Cliburn Cc: Chris Snook Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1c/atl1c.h | 3 +-- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 11 ----------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h index b9203d928938..c46b489ce9b4 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c.h +++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h @@ -488,7 +488,7 @@ struct atl1c_tpd_ring { dma_addr_t dma; /* descriptor ring physical address */ u16 size; /* descriptor ring length in bytes */ u16 count; /* number of descriptors in the ring */ - u16 next_to_use; /* this is protectd by adapter->tx_lock */ + u16 next_to_use; atomic_t next_to_clean; struct atl1c_buffer *buffer_info; }; @@ -542,7 +542,6 @@ struct atl1c_adapter { u16 link_duplex; spinlock_t mdio_lock; - spinlock_t tx_lock; atomic_t irq_sem; struct work_struct common_task; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index d0084d4d1a9b..a3200ea6d765 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -821,7 +821,6 @@ static int atl1c_sw_init(struct atl1c_adapter *adapter) atl1c_set_rxbufsize(adapter, adapter->netdev); atomic_set(&adapter->irq_sem, 1); spin_lock_init(&adapter->mdio_lock); - spin_lock_init(&adapter->tx_lock); set_bit(__AT_DOWN, &adapter->flags); return 0; @@ -2206,7 +2205,6 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct atl1c_adapter *adapter = netdev_priv(netdev); - unsigned long flags; u16 tpd_req = 1; struct atl1c_tpd_desc *tpd; enum atl1c_trans_queue type = atl1c_trans_normal; @@ -2217,16 +2215,10 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, } tpd_req = atl1c_cal_tpd_req(skb); - if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) { - if (netif_msg_pktdata(adapter)) - dev_info(&adapter->pdev->dev, "tx locked\n"); - return NETDEV_TX_LOCKED; - } if (atl1c_tpd_avail(adapter, type) < tpd_req) { /* no enough descriptor, just stop queue */ netif_stop_queue(netdev); - spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_BUSY; } @@ -2234,7 +2226,6 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, /* do TSO and check sum */ if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) { - spin_unlock_irqrestore(&adapter->tx_lock, flags); dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -2257,12 +2248,10 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, "tx-skb droppted due to dma error\n"); /* roll back tpd/buffer */ atl1c_tx_rollback(adapter, tpd, type); - spin_unlock_irqrestore(&adapter->tx_lock, flags); dev_kfree_skb_any(skb); } else { netdev_sent_queue(adapter->netdev, skb->len); atl1c_tx_queue(adapter, skb, tpd, type); - spin_unlock_irqrestore(&adapter->tx_lock, flags); } return NETDEV_TX_OK; -- GitLab From 4acff371f2e3f386422253c7fce0092a793ec1a4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 24 Apr 2016 21:38:11 +0200 Subject: [PATCH 4613/9938] atle1: remove LLTX support and TX_UNLOCKED similar to atl1c: lock is only used in ndo_start_xmit, but we also advertised LLTX, so remove that as well and let core stack handle tx locking. Allows to remove the TX_LOCKED return value from the driver. Cc: Jay Cliburn Cc: Chris Snook Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1e/atl1e.h | 1 - drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 12 +----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h index 0212dac7e23a..632bb843aed6 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e.h +++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h @@ -442,7 +442,6 @@ struct atl1e_adapter { u16 link_duplex; spinlock_t mdio_lock; - spinlock_t tx_lock; atomic_t irq_sem; struct work_struct reset_task; diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 59a03a193e83..974713b19ab6 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -648,7 +648,6 @@ static int atl1e_sw_init(struct atl1e_adapter *adapter) atomic_set(&adapter->irq_sem, 1); spin_lock_init(&adapter->mdio_lock); - spin_lock_init(&adapter->tx_lock); set_bit(__AT_DOWN, &adapter->flags); @@ -1866,7 +1865,6 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct atl1e_adapter *adapter = netdev_priv(netdev); - unsigned long flags; u16 tpd_req = 1; struct atl1e_tpd_desc *tpd; @@ -1880,13 +1878,10 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } tpd_req = atl1e_cal_tdp_req(skb); - if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) - return NETDEV_TX_LOCKED; if (atl1e_tpd_avail(adapter) < tpd_req) { /* no enough descriptor, just stop queue */ netif_stop_queue(netdev); - spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_BUSY; } @@ -1910,7 +1905,6 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, /* do TSO and check sum */ if (atl1e_tso_csum(adapter, skb, tpd) != 0) { - spin_unlock_irqrestore(&adapter->tx_lock, flags); dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -1921,10 +1915,7 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, } atl1e_tx_queue(adapter, tpd_req, tpd); - - netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ out: - spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_OK; } @@ -2285,8 +2276,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_RX; - netdev->features = netdev->hw_features | NETIF_F_LLTX | - NETIF_F_HW_VLAN_CTAG_TX; + netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_TX; /* not enabled by default */ netdev->hw_features |= NETIF_F_RXALL | NETIF_F_RXFCS; return 0; -- GitLab From 926f27300100f4233c7665649f68fcf615f58d68 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 24 Apr 2016 21:38:12 +0200 Subject: [PATCH 4614/9938] drivers: net: use NETDEV_TX_OK instead of NETDEV_TX_LOCKED These drivers already call netif_stop_queue() so we should not be called unless tx space is available. Just free the skb and return TX_OK. Followup patch will remove NETDEV_TX_LOCKED from the kernel. Cc: linux-parisc@vger.kernel.org Cc: linux-hams@vger.kernel.org Cc: Thomas Sailer Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/7990.c | 8 +++++--- drivers/net/ethernet/amd/a2065.c | 7 +++---- drivers/net/ethernet/dec/tulip/de4x5.c | 7 +++++-- drivers/net/hamradio/baycom_epp.c | 6 ++++-- drivers/net/hamradio/hdlcdrv.c | 6 ++++-- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/amd/7990.c b/drivers/net/ethernet/amd/7990.c index 66d0b73c39c0..8e7575571531 100644 --- a/drivers/net/ethernet/amd/7990.c +++ b/drivers/net/ethernet/amd/7990.c @@ -543,11 +543,13 @@ int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) static int outs; unsigned long flags; - if (!TX_BUFFS_AVAIL) - return NETDEV_TX_LOCKED; - netif_stop_queue(dev); + if (!TX_BUFFS_AVAIL) { + dev_consume_skb_any(skb); + return NETDEV_TX_OK; + } + skblen = skb->len; #ifdef DEBUG_DRIVER diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index 56139184b801..2a18d34d2610 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c @@ -547,10 +547,8 @@ static netdev_tx_t lance_start_xmit(struct sk_buff *skb, local_irq_save(flags); - if (!lance_tx_buffs_avail(lp)) { - local_irq_restore(flags); - return NETDEV_TX_LOCKED; - } + if (!lance_tx_buffs_avail(lp)) + goto out_free; #ifdef DEBUG /* dump the packet */ @@ -573,6 +571,7 @@ static netdev_tx_t lance_start_xmit(struct sk_buff *skb, /* Kick the lance: transmit now */ ll->rdp = LE_C0_INEA | LE_C0_TDMD; + out_free: dev_kfree_skb(skb); local_irq_restore(flags); diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 3acde3b9b767..d88fbab378aa 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -1465,7 +1465,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); if (!lp->tx_enable) /* Cannot send for now */ - return NETDEV_TX_LOCKED; + goto tx_err; /* ** Clean out the TX ring asynchronously to interrupts - sometimes the @@ -1478,7 +1478,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) /* Test if cache is already locked - requeue skb if so */ if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt) - return NETDEV_TX_LOCKED; + goto tx_err; /* Transmit descriptor ring full or stale skb */ if (netif_queue_stopped(dev) || (u_long) lp->tx_skb[lp->tx_new] > 1) { @@ -1519,6 +1519,9 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) lp->cache.lock = 0; return NETDEV_TX_OK; +tx_err: + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } /* diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 72c9f1f352b4..eb6663866c9f 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -780,8 +780,10 @@ static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb(skb); return NETDEV_TX_OK; } - if (bc->skb) - return NETDEV_TX_LOCKED; + if (bc->skb) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } /* strip KISS byte */ if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) { dev_kfree_skb(skb); diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 49fe59b180a8..4bad0b894e9c 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -412,8 +412,10 @@ static netdev_tx_t hdlcdrv_send_packet(struct sk_buff *skb, dev_kfree_skb(skb); return NETDEV_TX_OK; } - if (sm->skb) - return NETDEV_TX_LOCKED; + if (sm->skb) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } netif_stop_queue(dev); sm->skb = skb; return NETDEV_TX_OK; -- GitLab From a6086a893718db07ef9e7af5624ec27cb376ef0a Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 24 Apr 2016 21:38:13 +0200 Subject: [PATCH 4615/9938] drivers: net: remove NETDEV_TX_LOCKED replace the trylock by a full spin_lock and remove TX_LOCKED return value. Followup patch will remove TX_LOCKED from the kernel. Cc: Jon Mason Cc: Andy Gospodarek Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb/sge.c | 3 +-- drivers/net/ethernet/neterion/s2io.c | 9 +-------- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 6 ++---- drivers/net/ethernet/tehuti/tehuti.c | 8 +------- drivers/net/rionet.c | 6 +----- 5 files changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c index 526ea74e82d9..86f467a2c485 100644 --- a/drivers/net/ethernet/chelsio/cxgb/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb/sge.c @@ -1664,8 +1664,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, struct cmdQ *q = &sge->cmdQ[qid]; unsigned int credits, pidx, genbit, count, use_sched_skb = 0; - if (!spin_trylock(&q->lock)) - return NETDEV_TX_LOCKED; + spin_lock(&q->lock); reclaim_completed_tx(sge, q); diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 9ba975853ec6..2874dffe77de 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -4021,7 +4021,6 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags = 0; u16 vlan_tag = 0; struct fifo_info *fifo = NULL; - int do_spin_lock = 1; int offload_type; int enable_per_list_interrupt = 0; struct config_param *config = &sp->config; @@ -4074,7 +4073,6 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev) queue += sp->udp_fifo_idx; if (skb->len > 1024) enable_per_list_interrupt = 1; - do_spin_lock = 0; } } } @@ -4084,12 +4082,7 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev) [skb->priority & (MAX_TX_FIFOS - 1)]; fifo = &mac_control->fifos[queue]; - if (do_spin_lock) - spin_lock_irqsave(&fifo->tx_lock, flags); - else { - if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags))) - return NETDEV_TX_LOCKED; - } + spin_lock_irqsave(&fifo->tx_lock, flags); if (sp->config.multiq) { if (__netif_subqueue_stopped(dev, fifo->fifo_no)) { diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 3b98b263bad0..4475dcc687a2 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2137,10 +2137,8 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; unsigned long flags; - if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) { - /* Collision - tell upper layer to requeue */ - return NETDEV_TX_LOCKED; - } + spin_trylock_irqsave(&tx_ring->tx_lock, flags); + if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) { netif_stop_queue(netdev); spin_unlock_irqrestore(&tx_ring->tx_lock, flags); diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 14c9d1baa85c..2524a69db318 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -1610,7 +1610,6 @@ static inline int bdx_tx_space(struct bdx_priv *priv) * o NETDEV_TX_BUSY Cannot transmit packet, try later * Usually a bug, means queue start/stop flow control is broken in * the driver. Note: the driver must NOT put the skb in its DMA ring. - * o NETDEV_TX_LOCKED Locking failed, please retry quickly. */ static netdev_tx_t bdx_tx_transmit(struct sk_buff *skb, struct net_device *ndev) @@ -1630,12 +1629,7 @@ static netdev_tx_t bdx_tx_transmit(struct sk_buff *skb, ENTER; local_irq_save(flags); - if (!spin_trylock(&priv->tx_lock)) { - local_irq_restore(flags); - DBG("%s[%s]: TX locked, returning NETDEV_TX_LOCKED\n", - BDX_DRV_NAME, ndev->name); - return NETDEV_TX_LOCKED; - } + spin_lock(&priv->tx_lock); /* build tx descriptor */ BDX_ASSERT(f->m.wptr >= f->m.memsz); /* started with valid wptr */ diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 9cfe6aeac84e..a31f4610b493 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -179,11 +179,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) unsigned long flags; int add_num = 1; - local_irq_save(flags); - if (!spin_trylock(&rnet->tx_lock)) { - local_irq_restore(flags); - return NETDEV_TX_LOCKED; - } + spin_lock_irqsave(&rnet->tx_lock, flags); if (is_multicast_ether_addr(eth->h_dest)) add_num = nets[rnet->mport->id].nact; -- GitLab From f0cdf76c103ffa34ca5ac87dcdef7edffc722cbf Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 24 Apr 2016 21:38:14 +0200 Subject: [PATCH 4616/9938] net: remove NETDEV_TX_LOCKED support No more users in the tree, remove NETDEV_TX_LOCKED support. Adds another hole in softnet_stats struct, but better than keeping the unused collision counter around. Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- Documentation/networking/netdev-features.txt | 10 +++--- Documentation/networking/netdevices.txt | 9 ++---- include/linux/netdevice.h | 3 -- net/core/net-procfs.c | 3 +- net/core/pktgen.c | 1 - net/sched/sch_generic.c | 32 -------------------- 6 files changed, 9 insertions(+), 49 deletions(-) diff --git a/Documentation/networking/netdev-features.txt b/Documentation/networking/netdev-features.txt index f310edec8a77..7413eb05223b 100644 --- a/Documentation/networking/netdev-features.txt +++ b/Documentation/networking/netdev-features.txt @@ -131,13 +131,11 @@ stack. Driver should not change behaviour based on them. * LLTX driver (deprecated for hardware drivers) -NETIF_F_LLTX should be set in drivers that implement their own locking in -transmit path or don't need locking at all (e.g. software tunnels). -In ndo_start_xmit, it is recommended to use a try_lock and return -NETDEV_TX_LOCKED when the spin lock fails. The locking should also properly -protect against other callbacks (the rules you need to find out). +NETIF_F_LLTX is meant to be used by drivers that don't need locking at all, +e.g. software tunnels. -Don't use it for new drivers. +This is also used in a few legacy drivers that implement their +own locking, don't use it for new (hardware) drivers. * netns-local device diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 0b1cf6b2a592..7fec2061a334 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -69,10 +69,9 @@ ndo_start_xmit: When the driver sets NETIF_F_LLTX in dev->features this will be called without holding netif_tx_lock. In this case the driver - has to lock by itself when needed. It is recommended to use a try lock - for this and return NETDEV_TX_LOCKED when the spin lock fails. - The locking there should also properly protect against - set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated. + has to lock by itself when needed. + The locking there should also properly protect against + set_rx_mode. WARNING: use of NETIF_F_LLTX is deprecated. Don't use it for new drivers. Context: Process with BHs disabled or BH (timer), @@ -83,8 +82,6 @@ ndo_start_xmit: o NETDEV_TX_BUSY Cannot transmit packet, try later Usually a bug, means queue start/stop flow control is broken in the driver. Note: the driver must NOT put the skb in its DMA ring. - o NETDEV_TX_LOCKED Locking failed, please retry quickly. - Only valid when NETIF_F_LLTX is set. ndo_tx_timeout: Synchronization: netif_tx_lock spinlock; all TX queues frozen. diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1f6d5db471a2..18d8394f2e5d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -106,7 +106,6 @@ enum netdev_tx { __NETDEV_TX_MIN = INT_MIN, /* make sure enum is signed */ NETDEV_TX_OK = 0x00, /* driver took care of packet */ NETDEV_TX_BUSY = 0x10, /* driver tx path was busy*/ - NETDEV_TX_LOCKED = 0x20, /* driver tx lock was already taken */ }; typedef enum netdev_tx netdev_tx_t; @@ -831,7 +830,6 @@ struct tc_to_netdev { * the queue before that can happen; it's for obsolete devices and weird * corner cases, but the stack really does a non-trivial amount * of useless work if you return NETDEV_TX_BUSY. - * (can also return NETDEV_TX_LOCKED iff NETIF_F_LLTX) * Required; cannot be NULL. * * netdev_features_t (*ndo_fix_features)(struct net_device *dev, @@ -2737,7 +2735,6 @@ struct softnet_data { /* stats */ unsigned int processed; unsigned int time_squeeze; - unsigned int cpu_collision; unsigned int received_rps; #ifdef CONFIG_RPS struct softnet_data *rps_ipi_list; diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c index 2bf83299600a..14d09345f00d 100644 --- a/net/core/net-procfs.c +++ b/net/core/net-procfs.c @@ -162,7 +162,8 @@ static int softnet_seq_show(struct seq_file *seq, void *v) "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", sd->processed, sd->dropped, sd->time_squeeze, 0, 0, 0, 0, 0, /* was fastroute */ - sd->cpu_collision, sd->received_rps, flow_limit_count); + 0, /* was cpu_collision */ + sd->received_rps, flow_limit_count); return 0; } diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 20999aa596dd..8604ae245960 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3472,7 +3472,6 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) pkt_dev->odevname, ret); pkt_dev->errors++; /* fallthru */ - case NETDEV_TX_LOCKED: case NETDEV_TX_BUSY: /* Retry it next time */ atomic_dec(&(pkt_dev->skb->users)); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 80742edea96f..9c7756237904 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -108,35 +108,6 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, return skb; } -static inline int handle_dev_cpu_collision(struct sk_buff *skb, - struct netdev_queue *dev_queue, - struct Qdisc *q) -{ - int ret; - - if (unlikely(dev_queue->xmit_lock_owner == smp_processor_id())) { - /* - * Same CPU holding the lock. It may be a transient - * configuration error, when hard_start_xmit() recurses. We - * detect it by checking xmit owner and drop the packet when - * deadloop is detected. Return OK to try the next skb. - */ - kfree_skb_list(skb); - net_warn_ratelimited("Dead loop on netdevice %s, fix it urgently!\n", - dev_queue->dev->name); - ret = qdisc_qlen(q); - } else { - /* - * Another cpu is holding lock, requeue & delay xmits for - * some time. - */ - __this_cpu_inc(softnet_data.cpu_collision); - ret = dev_requeue_skb(skb, q); - } - - return ret; -} - /* * Transmit possibly several skbs, and handle the return status as * required. Holding the __QDISC___STATE_RUNNING bit guarantees that @@ -174,9 +145,6 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, if (dev_xmit_complete(ret)) { /* Driver sent out skb successfully or skb was consumed */ ret = qdisc_qlen(q); - } else if (ret == NETDEV_TX_LOCKED) { - /* Driver try lock failed */ - ret = handle_dev_cpu_collision(skb, txq, q); } else { /* Driver returned NETDEV_TX_BUSY - requeue skb */ if (unlikely(ret != NETDEV_TX_BUSY)) -- GitLab From 4e095a9a6ee50ba8a9820a4991b6a2a27c67bdb4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Apr 2016 15:57:19 -0400 Subject: [PATCH 4617/9938] infiniband: nes: Kill unused variable in nes_netdev_start_xmit() Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_nic.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index b09a6db80201..99cef26e74b4 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -478,7 +478,6 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev) u32 tso_wqe_length; u32 curr_tcp_seq; u32 wqe_count=1; - u32 send_rc; struct iphdr *iph; __le16 *wqe_fragment_length; u32 nr_frags; -- GitLab From 269e6b3af3bfbc4e50b497924c2abb1c4cf3364e Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:46 +0300 Subject: [PATCH 4618/9938] net/mlx5e: Report additional error statistics in get stats ndo Provide rtnl_link_stats64 with information regarding physical errors to be seen in ifconfig and ip tool. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en_main.c | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index d485d1e4e100..6270f8d539db 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2074,18 +2074,45 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_vport_stats *vstats = &priv->stats.vport; + struct mlx5e_pport_stats *pstats = &priv->stats.pport; stats->rx_packets = vstats->rx_packets; stats->rx_bytes = vstats->rx_bytes; stats->tx_packets = vstats->tx_packets; stats->tx_bytes = vstats->tx_bytes; - stats->multicast = vstats->rx_multicast_packets + - vstats->tx_multicast_packets; - stats->tx_errors = vstats->tx_error_packets; - stats->rx_errors = vstats->rx_error_packets; + +#define PPCNT_GET_802_3_CTR(fld) \ + (MLX5_GET64(eth_802_3_cntrs_grp_data_layout, \ + pstats->IEEE_802_3_counters, fld##_high)) + +#define PPCNT_GET_2863_CTR(fld) \ + (MLX5_GET64(eth_2863_cntrs_grp_data_layout, \ + pstats->RFC_2863_counters, fld##_high)) + + stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer; stats->tx_dropped = vstats->tx_queue_dropped; - stats->rx_crc_errors = 0; - stats->rx_length_errors = 0; + + stats->rx_length_errors = + PPCNT_GET_802_3_CTR(a_in_range_length_errors) + + PPCNT_GET_802_3_CTR(a_out_of_range_length_field) + + PPCNT_GET_802_3_CTR(a_frame_too_long_errors); + stats->rx_crc_errors = + PPCNT_GET_802_3_CTR(a_frame_check_sequence_errors); + stats->rx_frame_errors = + PPCNT_GET_802_3_CTR(a_alignment_errors); + stats->tx_aborted_errors = + PPCNT_GET_2863_CTR(if_out_discards); + stats->tx_carrier_errors = + PPCNT_GET_802_3_CTR(a_symbol_error_during_carrier); + stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + + stats->rx_frame_errors; + stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors; + + /* vport multicast also counts packets that are dropped due to steering + * or rx out of buffer + */ + stats->multicast = vstats->rx_multicast_packets; + return stats; } -- GitLab From 9218b44dcc059e08e249f6f7614b8e391eb041d8 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:47 +0300 Subject: [PATCH 4619/9938] net/mlx5e: Statistics handling refactoring Redesign ethtool statistics handling and reporting in the driver: 1. Move counters to a separate file (en_stats.h). 2. Remove unnecessary dependencies between stats and strings. 3. Use counter descriptors which hold a name and offset for each counter, and will be used to decide which counters will be exposed. For example when adding a new software counter to ethtool, instead of: 1. Add to stats struct. 2. Add to strings struct in the same order. 3. Change macro defining number of software counters. The only thing needed is to link the new counter to a counter descriptor. VPort counters are a set of hardware traffic counters created automatically for each virtual port opened. PPort counters are a set of counters describing per physical port performance statistics. These counters are gathered from hardware register and divided to groups according to different protocols. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 240 +------------ .../ethernet/mellanox/mlx5/core/en_ethtool.c | 132 +++++--- .../net/ethernet/mellanox/mlx5/core/en_main.c | 232 +++++-------- .../ethernet/mellanox/mlx5/core/en_stats.h | 318 ++++++++++++++++++ include/linux/mlx5/device.h | 1 + 5 files changed, 483 insertions(+), 440 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_stats.h diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 6e24e821a1d8..e903eff2574f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -46,6 +46,7 @@ #include #include "wq.h" #include "mlx5_core.h" +#include "en_stats.h" #define MLX5E_MAX_NUM_TC 8 @@ -148,245 +149,6 @@ struct mlx5e_umr_wqe { #define MLX5E_MIN_BW_ALLOC 1 /* Min percentage of BW allocation */ #endif -static const char vport_strings[][ETH_GSTRING_LEN] = { - /* vport statistics */ - "rx_packets", - "rx_bytes", - "tx_packets", - "tx_bytes", - "rx_error_packets", - "rx_error_bytes", - "tx_error_packets", - "tx_error_bytes", - "rx_unicast_packets", - "rx_unicast_bytes", - "tx_unicast_packets", - "tx_unicast_bytes", - "rx_multicast_packets", - "rx_multicast_bytes", - "tx_multicast_packets", - "tx_multicast_bytes", - "rx_broadcast_packets", - "rx_broadcast_bytes", - "tx_broadcast_packets", - "tx_broadcast_bytes", - - /* SW counters */ - "tso_packets", - "tso_bytes", - "tso_inner_packets", - "tso_inner_bytes", - "lro_packets", - "lro_bytes", - "rx_csum_good", - "rx_csum_none", - "rx_csum_sw", - "tx_csum_offload", - "tx_csum_inner", - "tx_queue_stopped", - "tx_queue_wake", - "tx_queue_dropped", - "rx_wqe_err", - "rx_mpwqe_filler", - "rx_mpwqe_frag", - "rx_buff_alloc_err", -}; - -struct mlx5e_vport_stats { - /* HW counters */ - u64 rx_packets; - u64 rx_bytes; - u64 tx_packets; - u64 tx_bytes; - u64 rx_error_packets; - u64 rx_error_bytes; - u64 tx_error_packets; - u64 tx_error_bytes; - u64 rx_unicast_packets; - u64 rx_unicast_bytes; - u64 tx_unicast_packets; - u64 tx_unicast_bytes; - u64 rx_multicast_packets; - u64 rx_multicast_bytes; - u64 tx_multicast_packets; - u64 tx_multicast_bytes; - u64 rx_broadcast_packets; - u64 rx_broadcast_bytes; - u64 tx_broadcast_packets; - u64 tx_broadcast_bytes; - - /* SW counters */ - u64 tso_packets; - u64 tso_bytes; - u64 tso_inner_packets; - u64 tso_inner_bytes; - u64 lro_packets; - u64 lro_bytes; - u64 rx_csum_good; - u64 rx_csum_none; - u64 rx_csum_sw; - u64 tx_csum_offload; - u64 tx_csum_inner; - u64 tx_queue_stopped; - u64 tx_queue_wake; - u64 tx_queue_dropped; - u64 rx_wqe_err; - u64 rx_mpwqe_filler; - u64 rx_mpwqe_frag; - u64 rx_buff_alloc_err; - -#define NUM_VPORT_COUNTERS 38 -}; - -static const char pport_strings[][ETH_GSTRING_LEN] = { - /* IEEE802.3 counters */ - "frames_tx", - "frames_rx", - "check_seq_err", - "alignment_err", - "octets_tx", - "octets_received", - "multicast_xmitted", - "broadcast_xmitted", - "multicast_rx", - "broadcast_rx", - "in_range_len_errors", - "out_of_range_len", - "too_long_errors", - "symbol_err", - "mac_control_tx", - "mac_control_rx", - "unsupported_op_rx", - "pause_ctrl_rx", - "pause_ctrl_tx", - - /* RFC2863 counters */ - "in_octets", - "in_ucast_pkts", - "in_discards", - "in_errors", - "in_unknown_protos", - "out_octets", - "out_ucast_pkts", - "out_discards", - "out_errors", - "in_multicast_pkts", - "in_broadcast_pkts", - "out_multicast_pkts", - "out_broadcast_pkts", - - /* RFC2819 counters */ - "drop_events", - "octets", - "pkts", - "broadcast_pkts", - "multicast_pkts", - "crc_align_errors", - "undersize_pkts", - "oversize_pkts", - "fragments", - "jabbers", - "collisions", - "p64octets", - "p65to127octets", - "p128to255octets", - "p256to511octets", - "p512to1023octets", - "p1024to1518octets", - "p1519to2047octets", - "p2048to4095octets", - "p4096to8191octets", - "p8192to10239octets", -}; - -#define NUM_IEEE_802_3_COUNTERS 19 -#define NUM_RFC_2863_COUNTERS 13 -#define NUM_RFC_2819_COUNTERS 21 -#define NUM_PPORT_COUNTERS (NUM_IEEE_802_3_COUNTERS + \ - NUM_RFC_2863_COUNTERS + \ - NUM_RFC_2819_COUNTERS) - -struct mlx5e_pport_stats { - __be64 IEEE_802_3_counters[NUM_IEEE_802_3_COUNTERS]; - __be64 RFC_2863_counters[NUM_RFC_2863_COUNTERS]; - __be64 RFC_2819_counters[NUM_RFC_2819_COUNTERS]; -}; - -static const char qcounter_stats_strings[][ETH_GSTRING_LEN] = { - "rx_out_of_buffer", -}; - -struct mlx5e_qcounter_stats { - u32 rx_out_of_buffer; -#define NUM_Q_COUNTERS 1 -}; - -static const char rq_stats_strings[][ETH_GSTRING_LEN] = { - "packets", - "bytes", - "csum_none", - "csum_sw", - "lro_packets", - "lro_bytes", - "wqe_err", - "mpwqe_filler", - "mpwqe_frag", - "buff_alloc_err", -}; - -struct mlx5e_rq_stats { - u64 packets; - u64 bytes; - u64 csum_none; - u64 csum_sw; - u64 lro_packets; - u64 lro_bytes; - u64 wqe_err; - u64 mpwqe_filler; - u64 mpwqe_frag; - u64 buff_alloc_err; -#define NUM_RQ_STATS 10 -}; - -static const char sq_stats_strings[][ETH_GSTRING_LEN] = { - "packets", - "bytes", - "tso_packets", - "tso_bytes", - "tso_inner_packets", - "tso_inner_bytes", - "csum_offload_inner", - "nop", - "csum_offload_none", - "stopped", - "wake", - "dropped", -}; - -struct mlx5e_sq_stats { - /* commonly accessed in data path */ - u64 packets; - u64 bytes; - u64 tso_packets; - u64 tso_bytes; - u64 tso_inner_packets; - u64 tso_inner_bytes; - u64 csum_offload_inner; - u64 nop; - /* less likely accessed in data path */ - u64 csum_offload_none; - u64 stopped; - u64 wake; - u64 dropped; -#define NUM_SQ_STATS 12 -}; - -struct mlx5e_stats { - struct mlx5e_vport_stats vport; - struct mlx5e_pport_stats pport; - struct mlx5e_qcounter_stats qcnt; -}; - struct mlx5e_params { u8 log_sq_size; u8 rq_wq_type; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 4077856aab76..f1649d543475 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -166,6 +166,12 @@ static const struct { }; #define MLX5E_NUM_Q_CNTRS(priv) (NUM_Q_COUNTERS * (!!priv->q_counter)) +#define MLX5E_NUM_RQ_STATS(priv) \ + (NUM_RQ_STATS * priv->params.num_channels * \ + test_bit(MLX5E_STATE_OPENED, &priv->state)) +#define MLX5E_NUM_SQ_STATS(priv) \ + (NUM_SQ_STATS * priv->params.num_channels * priv->params.num_tc * \ + test_bit(MLX5E_STATE_OPENED, &priv->state)) static int mlx5e_get_sset_count(struct net_device *dev, int sset) { @@ -173,21 +179,68 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset) switch (sset) { case ETH_SS_STATS: - return NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS + + return NUM_SW_COUNTERS + MLX5E_NUM_Q_CNTRS(priv) + - priv->params.num_channels * NUM_RQ_STATS + - priv->params.num_channels * priv->params.num_tc * - NUM_SQ_STATS; + NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS + + MLX5E_NUM_RQ_STATS(priv) + + MLX5E_NUM_SQ_STATS(priv); /* fallthrough */ default: return -EOPNOTSUPP; } } +static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data) +{ + int i, j, tc, idx = 0; + + /* SW counters */ + for (i = 0; i < NUM_SW_COUNTERS; i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, sw_stats_desc[i].name); + + /* Q counters */ + for (i = 0; i < MLX5E_NUM_Q_CNTRS(priv); i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, q_stats_desc[i].name); + + /* VPORT counters */ + for (i = 0; i < NUM_VPORT_COUNTERS; i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, + vport_stats_desc[i].name); + + /* PPORT counters */ + for (i = 0; i < NUM_PPORT_802_3_COUNTERS; i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, + pport_802_3_stats_desc[i].name); + + for (i = 0; i < NUM_PPORT_2863_COUNTERS; i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, + pport_2863_stats_desc[i].name); + + for (i = 0; i < NUM_PPORT_2819_COUNTERS; i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, + pport_2819_stats_desc[i].name); + + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) + return; + + /* per channel counters */ + for (i = 0; i < priv->params.num_channels; i++) + for (j = 0; j < NUM_RQ_STATS; j++) + sprintf(data + (idx++) * ETH_GSTRING_LEN, "rx%d_%s", i, + rq_stats_desc[j].name); + + for (tc = 0; tc < priv->params.num_tc; tc++) + for (i = 0; i < priv->params.num_channels; i++) + for (j = 0; j < NUM_SQ_STATS; j++) + sprintf(data + (idx++) * ETH_GSTRING_LEN, + "tx%d_%s", + priv->channeltc_to_txq_map[i][tc], + sq_stats_desc[j].name); +} + static void mlx5e_get_strings(struct net_device *dev, uint32_t stringset, uint8_t *data) { - int i, j, tc, idx = 0; struct mlx5e_priv *priv = netdev_priv(dev); switch (stringset) { @@ -198,35 +251,7 @@ static void mlx5e_get_strings(struct net_device *dev, break; case ETH_SS_STATS: - /* VPORT counters */ - for (i = 0; i < NUM_VPORT_COUNTERS; i++) - strcpy(data + (idx++) * ETH_GSTRING_LEN, - vport_strings[i]); - - /* Q counters */ - for (i = 0; i < MLX5E_NUM_Q_CNTRS(priv); i++) - strcpy(data + (idx++) * ETH_GSTRING_LEN, - qcounter_stats_strings[i]); - - /* PPORT counters */ - for (i = 0; i < NUM_PPORT_COUNTERS; i++) - strcpy(data + (idx++) * ETH_GSTRING_LEN, - pport_strings[i]); - - /* per channel counters */ - for (i = 0; i < priv->params.num_channels; i++) - for (j = 0; j < NUM_RQ_STATS; j++) - sprintf(data + (idx++) * ETH_GSTRING_LEN, - "rx%d_%s", i, rq_stats_strings[j]); - - for (tc = 0; tc < priv->params.num_tc; tc++) - for (i = 0; i < priv->params.num_channels; i++) - for (j = 0; j < NUM_SQ_STATS; j++) - sprintf(data + - (idx++) * ETH_GSTRING_LEN, - "tx%d_%s", - priv->channeltc_to_txq_map[i][tc], - sq_stats_strings[j]); + mlx5e_fill_stats_strings(priv, data); break; } } @@ -245,28 +270,45 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev, mlx5e_update_stats(priv); mutex_unlock(&priv->state_lock); - for (i = 0; i < NUM_VPORT_COUNTERS; i++) - data[idx++] = ((u64 *)&priv->stats.vport)[i]; + for (i = 0; i < NUM_SW_COUNTERS; i++) + data[idx++] = MLX5E_READ_CTR64_CPU(&priv->stats.sw, + sw_stats_desc, i); for (i = 0; i < MLX5E_NUM_Q_CNTRS(priv); i++) - data[idx++] = ((u32 *)&priv->stats.qcnt)[i]; + data[idx++] = MLX5E_READ_CTR32_CPU(&priv->stats.qcnt, + q_stats_desc, i); + + for (i = 0; i < NUM_VPORT_COUNTERS; i++) + data[idx++] = MLX5E_READ_CTR64_BE(priv->stats.vport.query_vport_out, + vport_stats_desc, i); + + for (i = 0; i < NUM_PPORT_802_3_COUNTERS; i++) + data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.IEEE_802_3_counters, + pport_802_3_stats_desc, i); - for (i = 0; i < NUM_PPORT_COUNTERS; i++) - data[idx++] = be64_to_cpu(((__be64 *)&priv->stats.pport)[i]); + for (i = 0; i < NUM_PPORT_2863_COUNTERS; i++) + data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.RFC_2863_counters, + pport_2863_stats_desc, i); + + for (i = 0; i < NUM_PPORT_2819_COUNTERS; i++) + data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.RFC_2819_counters, + pport_2819_stats_desc, i); + + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) + return; /* per channel counters */ for (i = 0; i < priv->params.num_channels; i++) for (j = 0; j < NUM_RQ_STATS; j++) - data[idx++] = !test_bit(MLX5E_STATE_OPENED, - &priv->state) ? 0 : - ((u64 *)&priv->channel[i]->rq.stats)[j]; + data[idx++] = + MLX5E_READ_CTR64_CPU(&priv->channel[i]->rq.stats, + rq_stats_desc, j); for (tc = 0; tc < priv->params.num_tc; tc++) for (i = 0; i < priv->params.num_channels; i++) for (j = 0; j < NUM_SQ_STATS; j++) - data[idx++] = !test_bit(MLX5E_STATE_OPENED, - &priv->state) ? 0 : - ((u64 *)&priv->channel[i]->sq[tc].stats)[j]; + data[idx++] = MLX5E_READ_CTR64_CPU(&priv->channel[i]->sq[tc].stats, + sq_stats_desc, j); } static void mlx5e_get_ringparam(struct net_device *dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 6270f8d539db..0c532367ff13 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -91,96 +91,15 @@ static void mlx5e_update_carrier_work(struct work_struct *work) mutex_unlock(&priv->state_lock); } -static void mlx5e_update_pport_counters(struct mlx5e_priv *priv) -{ - struct mlx5_core_dev *mdev = priv->mdev; - struct mlx5e_pport_stats *s = &priv->stats.pport; - u32 *in; - u32 *out; - int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); - - in = mlx5_vzalloc(sz); - out = mlx5_vzalloc(sz); - if (!in || !out) - goto free_out; - - MLX5_SET(ppcnt_reg, in, local_port, 1); - - MLX5_SET(ppcnt_reg, in, grp, MLX5_IEEE_802_3_COUNTERS_GROUP); - mlx5_core_access_reg(mdev, in, sz, out, - sz, MLX5_REG_PPCNT, 0, 0); - memcpy(s->IEEE_802_3_counters, - MLX5_ADDR_OF(ppcnt_reg, out, counter_set), - sizeof(s->IEEE_802_3_counters)); - - MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2863_COUNTERS_GROUP); - mlx5_core_access_reg(mdev, in, sz, out, - sz, MLX5_REG_PPCNT, 0, 0); - memcpy(s->RFC_2863_counters, - MLX5_ADDR_OF(ppcnt_reg, out, counter_set), - sizeof(s->RFC_2863_counters)); - - MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2819_COUNTERS_GROUP); - mlx5_core_access_reg(mdev, in, sz, out, - sz, MLX5_REG_PPCNT, 0, 0); - memcpy(s->RFC_2819_counters, - MLX5_ADDR_OF(ppcnt_reg, out, counter_set), - sizeof(s->RFC_2819_counters)); - -free_out: - kvfree(in); - kvfree(out); -} - -static void mlx5e_update_q_counter(struct mlx5e_priv *priv) -{ - struct mlx5e_qcounter_stats *qcnt = &priv->stats.qcnt; - - if (!priv->q_counter) - return; - - mlx5_core_query_out_of_buffer(priv->mdev, priv->q_counter, - &qcnt->rx_out_of_buffer); -} - -void mlx5e_update_stats(struct mlx5e_priv *priv) +static void mlx5e_update_sw_counters(struct mlx5e_priv *priv) { - struct mlx5_core_dev *mdev = priv->mdev; - struct mlx5e_vport_stats *s = &priv->stats.vport; + struct mlx5e_sw_stats *s = &priv->stats.sw; struct mlx5e_rq_stats *rq_stats; struct mlx5e_sq_stats *sq_stats; - u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)]; - u32 *out; - int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); - u64 tx_offload_none; + u64 tx_offload_none = 0; int i, j; - out = mlx5_vzalloc(outlen); - if (!out) - return; - - /* Collect firts the SW counters and then HW for consistency */ - s->rx_packets = 0; - s->rx_bytes = 0; - s->tx_packets = 0; - s->tx_bytes = 0; - s->tso_packets = 0; - s->tso_bytes = 0; - s->tso_inner_packets = 0; - s->tso_inner_bytes = 0; - s->tx_queue_stopped = 0; - s->tx_queue_wake = 0; - s->tx_queue_dropped = 0; - s->tx_csum_inner = 0; - tx_offload_none = 0; - s->lro_packets = 0; - s->lro_bytes = 0; - s->rx_csum_none = 0; - s->rx_csum_sw = 0; - s->rx_wqe_err = 0; - s->rx_mpwqe_filler = 0; - s->rx_mpwqe_frag = 0; - s->rx_buff_alloc_err = 0; + memset(s, 0, sizeof(*s)); for (i = 0; i < priv->params.num_channels; i++) { rq_stats = &priv->channel[i]->rq.stats; @@ -212,7 +131,19 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) } } - /* HW counters */ + /* Update calculated offload counters */ + s->tx_csum_offload = s->tx_packets - tx_offload_none - s->tx_csum_inner; + s->rx_csum_good = s->rx_packets - s->rx_csum_none - + s->rx_csum_sw; +} + +static void mlx5e_update_vport_counters(struct mlx5e_priv *priv) +{ + int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out); + u32 *out = (u32 *)priv->stats.vport.query_vport_out; + u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)]; + struct mlx5_core_dev *mdev = priv->mdev; + memset(in, 0, sizeof(in)); MLX5_SET(query_vport_counter_in, in, opcode, @@ -222,58 +153,56 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) memset(out, 0, outlen); - if (mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen)) + mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen); +} + +static void mlx5e_update_pport_counters(struct mlx5e_priv *priv) +{ + struct mlx5e_pport_stats *pstats = &priv->stats.pport; + struct mlx5_core_dev *mdev = priv->mdev; + int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); + void *out; + u32 *in; + + in = mlx5_vzalloc(sz); + if (!in) goto free_out; -#define MLX5_GET_CTR(p, x) \ - MLX5_GET64(query_vport_counter_out, p, x) - - s->rx_error_packets = - MLX5_GET_CTR(out, received_errors.packets); - s->rx_error_bytes = - MLX5_GET_CTR(out, received_errors.octets); - s->tx_error_packets = - MLX5_GET_CTR(out, transmit_errors.packets); - s->tx_error_bytes = - MLX5_GET_CTR(out, transmit_errors.octets); - - s->rx_unicast_packets = - MLX5_GET_CTR(out, received_eth_unicast.packets); - s->rx_unicast_bytes = - MLX5_GET_CTR(out, received_eth_unicast.octets); - s->tx_unicast_packets = - MLX5_GET_CTR(out, transmitted_eth_unicast.packets); - s->tx_unicast_bytes = - MLX5_GET_CTR(out, transmitted_eth_unicast.octets); - - s->rx_multicast_packets = - MLX5_GET_CTR(out, received_eth_multicast.packets); - s->rx_multicast_bytes = - MLX5_GET_CTR(out, received_eth_multicast.octets); - s->tx_multicast_packets = - MLX5_GET_CTR(out, transmitted_eth_multicast.packets); - s->tx_multicast_bytes = - MLX5_GET_CTR(out, transmitted_eth_multicast.octets); - - s->rx_broadcast_packets = - MLX5_GET_CTR(out, received_eth_broadcast.packets); - s->rx_broadcast_bytes = - MLX5_GET_CTR(out, received_eth_broadcast.octets); - s->tx_broadcast_packets = - MLX5_GET_CTR(out, transmitted_eth_broadcast.packets); - s->tx_broadcast_bytes = - MLX5_GET_CTR(out, transmitted_eth_broadcast.octets); + MLX5_SET(ppcnt_reg, in, local_port, 1); - /* Update calculated offload counters */ - s->tx_csum_offload = s->tx_packets - tx_offload_none - s->tx_csum_inner; - s->rx_csum_good = s->rx_packets - s->rx_csum_none - - s->rx_csum_sw; + out = pstats->IEEE_802_3_counters; + MLX5_SET(ppcnt_reg, in, grp, MLX5_IEEE_802_3_COUNTERS_GROUP); + mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0); - mlx5e_update_pport_counters(priv); - mlx5e_update_q_counter(priv); + out = pstats->RFC_2863_counters; + MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2863_COUNTERS_GROUP); + mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0); + + out = pstats->RFC_2819_counters; + MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2819_COUNTERS_GROUP); + mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0); free_out: - kvfree(out); + kvfree(in); +} + +static void mlx5e_update_q_counter(struct mlx5e_priv *priv) +{ + struct mlx5e_qcounter_stats *qcnt = &priv->stats.qcnt; + + if (!priv->q_counter) + return; + + mlx5_core_query_out_of_buffer(priv->mdev, priv->q_counter, + &qcnt->rx_out_of_buffer); +} + +void mlx5e_update_stats(struct mlx5e_priv *priv) +{ + mlx5e_update_sw_counters(priv); + mlx5e_update_q_counter(priv); + mlx5e_update_vport_counters(priv); + mlx5e_update_pport_counters(priv); } static void mlx5e_update_stats_work(struct work_struct *work) @@ -2073,37 +2002,28 @@ static struct rtnl_link_stats64 * mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct mlx5e_priv *priv = netdev_priv(dev); + struct mlx5e_sw_stats *sstats = &priv->stats.sw; struct mlx5e_vport_stats *vstats = &priv->stats.vport; struct mlx5e_pport_stats *pstats = &priv->stats.pport; - stats->rx_packets = vstats->rx_packets; - stats->rx_bytes = vstats->rx_bytes; - stats->tx_packets = vstats->tx_packets; - stats->tx_bytes = vstats->tx_bytes; - -#define PPCNT_GET_802_3_CTR(fld) \ - (MLX5_GET64(eth_802_3_cntrs_grp_data_layout, \ - pstats->IEEE_802_3_counters, fld##_high)) - -#define PPCNT_GET_2863_CTR(fld) \ - (MLX5_GET64(eth_2863_cntrs_grp_data_layout, \ - pstats->RFC_2863_counters, fld##_high)) + stats->rx_packets = sstats->rx_packets; + stats->rx_bytes = sstats->rx_bytes; + stats->tx_packets = sstats->tx_packets; + stats->tx_bytes = sstats->tx_bytes; stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer; - stats->tx_dropped = vstats->tx_queue_dropped; + stats->tx_dropped = sstats->tx_queue_dropped; stats->rx_length_errors = - PPCNT_GET_802_3_CTR(a_in_range_length_errors) + - PPCNT_GET_802_3_CTR(a_out_of_range_length_field) + - PPCNT_GET_802_3_CTR(a_frame_too_long_errors); + PPORT_802_3_GET(pstats, a_in_range_length_errors) + + PPORT_802_3_GET(pstats, a_out_of_range_length_field) + + PPORT_802_3_GET(pstats, a_frame_too_long_errors); stats->rx_crc_errors = - PPCNT_GET_802_3_CTR(a_frame_check_sequence_errors); - stats->rx_frame_errors = - PPCNT_GET_802_3_CTR(a_alignment_errors); - stats->tx_aborted_errors = - PPCNT_GET_2863_CTR(if_out_discards); + PPORT_802_3_GET(pstats, a_frame_check_sequence_errors); + stats->rx_frame_errors = PPORT_802_3_GET(pstats, a_alignment_errors); + stats->tx_aborted_errors = PPORT_2863_GET(pstats, if_out_discards); stats->tx_carrier_errors = - PPCNT_GET_802_3_CTR(a_symbol_error_during_carrier); + PPORT_802_3_GET(pstats, a_symbol_error_during_carrier); stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + stats->rx_frame_errors; stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors; @@ -2111,8 +2031,8 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) /* vport multicast also counts packets that are dropped due to steering * or rx out of buffer */ - stats->multicast = vstats->rx_multicast_packets; - + stats->multicast = + VPORT_COUNTER_GET(vstats, received_eth_multicast.packets); return stats; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h new file mode 100644 index 000000000000..116320d8fc42 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2015-2016, Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __MLX5_EN_STATS_H__ +#define __MLX5_EN_STATS_H__ + +#define MLX5E_READ_CTR64_CPU(ptr, dsc, i) \ + (*(u64 *)((char *)ptr + dsc[i].offset)) +#define MLX5E_READ_CTR64_BE(ptr, dsc, i) \ + be64_to_cpu(*(__be64 *)((char *)ptr + dsc[i].offset)) +#define MLX5E_READ_CTR32_CPU(ptr, dsc, i) \ + (*(u32 *)((char *)ptr + dsc[i].offset)) +#define MLX5E_READ_CTR32_BE(ptr, dsc, i) \ + be64_to_cpu(*(__be32 *)((char *)ptr + dsc[i].offset)) + +#define MLX5E_DECLARE_STAT(type, fld) #fld, offsetof(type, fld) + +struct counter_desc { + char name[ETH_GSTRING_LEN]; + int offset; /* Byte offset */ +}; + +struct mlx5e_sw_stats { + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + u64 tso_packets; + u64 tso_bytes; + u64 tso_inner_packets; + u64 tso_inner_bytes; + u64 lro_packets; + u64 lro_bytes; + u64 rx_csum_good; + u64 rx_csum_none; + u64 rx_csum_sw; + u64 tx_csum_offload; + u64 tx_csum_inner; + u64 tx_queue_stopped; + u64 tx_queue_wake; + u64 tx_queue_dropped; + u64 rx_wqe_err; + u64 rx_mpwqe_filler; + u64 rx_mpwqe_frag; + u64 rx_buff_alloc_err; +}; + +static const struct counter_desc sw_stats_desc[] = { + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tso_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tso_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tso_inner_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tso_inner_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, lro_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, lro_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_good) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_none) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_sw) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_offload) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_inner) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_stopped) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_wake) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_dropped) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_wqe_err) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_frag) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_buff_alloc_err) }, +}; + +struct mlx5e_qcounter_stats { + u32 rx_out_of_buffer; +}; + +static const struct counter_desc q_stats_desc[] = { + { MLX5E_DECLARE_STAT(struct mlx5e_qcounter_stats, rx_out_of_buffer) }, +}; + +#define VPORT_COUNTER_OFF(c) MLX5_BYTE_OFF(query_vport_counter_out, c) +#define VPORT_COUNTER_GET(vstats, c) MLX5_GET64(query_vport_counter_out, \ + vstats->query_vport_out, c) + +struct mlx5e_vport_stats { + __be64 query_vport_out[MLX5_ST_SZ_QW(query_vport_counter_out)]; +}; + +static const struct counter_desc vport_stats_desc[] = { + { "rx_error_packets", VPORT_COUNTER_OFF(received_errors.packets) }, + { "rx_error_bytes", VPORT_COUNTER_OFF(received_errors.octets) }, + { "tx_error_packets", VPORT_COUNTER_OFF(transmit_errors.packets) }, + { "tx_error_bytes", VPORT_COUNTER_OFF(transmit_errors.octets) }, + { "rx_unicast_packets", + VPORT_COUNTER_OFF(received_eth_unicast.packets) }, + { "rx_unicast_bytes", VPORT_COUNTER_OFF(received_eth_unicast.octets) }, + { "tx_unicast_packets", + VPORT_COUNTER_OFF(transmitted_eth_unicast.packets) }, + { "tx_unicast_bytes", + VPORT_COUNTER_OFF(transmitted_eth_unicast.octets) }, + { "rx_multicast_packets", + VPORT_COUNTER_OFF(received_eth_multicast.packets) }, + { "rx_multicast_bytes", + VPORT_COUNTER_OFF(received_eth_multicast.octets) }, + { "tx_multicast_packets", + VPORT_COUNTER_OFF(transmitted_eth_multicast.packets) }, + { "tx_multicast_bytes", + VPORT_COUNTER_OFF(transmitted_eth_multicast.octets) }, + { "rx_broadcast_packets", + VPORT_COUNTER_OFF(received_eth_broadcast.packets) }, + { "rx_broadcast_bytes", + VPORT_COUNTER_OFF(received_eth_broadcast.octets) }, + { "tx_broadcast_packets", + VPORT_COUNTER_OFF(transmitted_eth_broadcast.packets) }, + { "tx_broadcast_bytes", + VPORT_COUNTER_OFF(transmitted_eth_broadcast.octets) }, +}; + +#define PPORT_802_3_OFF(c) \ + MLX5_BYTE_OFF(ppcnt_reg, \ + counter_set.eth_802_3_cntrs_grp_data_layout.c##_high) +#define PPORT_802_3_GET(pstats, c) \ + MLX5_GET64(ppcnt_reg, pstats->IEEE_802_3_counters, \ + counter_set.eth_802_3_cntrs_grp_data_layout.c##_high) +#define PPORT_2863_OFF(c) \ + MLX5_BYTE_OFF(ppcnt_reg, \ + counter_set.eth_2863_cntrs_grp_data_layout.c##_high) +#define PPORT_2863_GET(pstats, c) \ + MLX5_GET64(ppcnt_reg, pstats->RFC_2863_counters, \ + counter_set.eth_2863_cntrs_grp_data_layout.c##_high) +#define PPORT_2819_OFF(c) \ + MLX5_BYTE_OFF(ppcnt_reg, \ + counter_set.eth_2819_cntrs_grp_data_layout.c##_high) +#define PPORT_2819_GET(pstats, c) \ + MLX5_GET64(ppcnt_reg, pstats->RFC_2819_counters, \ + counter_set.eth_2819_cntrs_grp_data_layout.c##_high) + +struct mlx5e_pport_stats { + __be64 IEEE_802_3_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; + __be64 RFC_2863_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; + __be64 RFC_2819_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; +}; + +static const struct counter_desc pport_802_3_stats_desc[] = { + { "frames_tx", PPORT_802_3_OFF(a_frames_transmitted_ok) }, + { "frames_rx", PPORT_802_3_OFF(a_frames_received_ok) }, + { "check_seq_err", PPORT_802_3_OFF(a_frame_check_sequence_errors) }, + { "alignment_err", PPORT_802_3_OFF(a_alignment_errors) }, + { "octets_tx", PPORT_802_3_OFF(a_octets_transmitted_ok) }, + { "octets_received", PPORT_802_3_OFF(a_octets_received_ok) }, + { "multicast_xmitted", PPORT_802_3_OFF(a_multicast_frames_xmitted_ok) }, + { "broadcast_xmitted", PPORT_802_3_OFF(a_broadcast_frames_xmitted_ok) }, + { "multicast_rx", PPORT_802_3_OFF(a_multicast_frames_received_ok) }, + { "broadcast_rx", PPORT_802_3_OFF(a_broadcast_frames_received_ok) }, + { "in_range_len_errors", PPORT_802_3_OFF(a_in_range_length_errors) }, + { "out_of_range_len", PPORT_802_3_OFF(a_out_of_range_length_field) }, + { "too_long_errors", PPORT_802_3_OFF(a_frame_too_long_errors) }, + { "symbol_err", PPORT_802_3_OFF(a_symbol_error_during_carrier) }, + { "mac_control_tx", PPORT_802_3_OFF(a_mac_control_frames_transmitted) }, + { "mac_control_rx", PPORT_802_3_OFF(a_mac_control_frames_received) }, + { "unsupported_op_rx", + PPORT_802_3_OFF(a_unsupported_opcodes_received) }, + { "pause_ctrl_rx", PPORT_802_3_OFF(a_pause_mac_ctrl_frames_received) }, + { "pause_ctrl_tx", + PPORT_802_3_OFF(a_pause_mac_ctrl_frames_transmitted) }, +}; + +static const struct counter_desc pport_2863_stats_desc[] = { + { "in_octets", PPORT_2863_OFF(if_in_octets) }, + { "in_ucast_pkts", PPORT_2863_OFF(if_in_ucast_pkts) }, + { "in_discards", PPORT_2863_OFF(if_in_discards) }, + { "in_errors", PPORT_2863_OFF(if_in_errors) }, + { "in_unknown_protos", PPORT_2863_OFF(if_in_unknown_protos) }, + { "out_octets", PPORT_2863_OFF(if_out_octets) }, + { "out_ucast_pkts", PPORT_2863_OFF(if_out_ucast_pkts) }, + { "out_discards", PPORT_2863_OFF(if_out_discards) }, + { "out_errors", PPORT_2863_OFF(if_out_errors) }, + { "in_multicast_pkts", PPORT_2863_OFF(if_in_multicast_pkts) }, + { "in_broadcast_pkts", PPORT_2863_OFF(if_in_broadcast_pkts) }, + { "out_multicast_pkts", PPORT_2863_OFF(if_out_multicast_pkts) }, + { "out_broadcast_pkts", PPORT_2863_OFF(if_out_broadcast_pkts) }, +}; + +static const struct counter_desc pport_2819_stats_desc[] = { + { "drop_events", PPORT_2819_OFF(ether_stats_drop_events) }, + { "octets", PPORT_2819_OFF(ether_stats_octets) }, + { "pkts", PPORT_2819_OFF(ether_stats_pkts) }, + { "broadcast_pkts", PPORT_2819_OFF(ether_stats_broadcast_pkts) }, + { "multicast_pkts", PPORT_2819_OFF(ether_stats_multicast_pkts) }, + { "crc_align_errors", PPORT_2819_OFF(ether_stats_crc_align_errors) }, + { "undersize_pkts", PPORT_2819_OFF(ether_stats_undersize_pkts) }, + { "oversize_pkts", PPORT_2819_OFF(ether_stats_oversize_pkts) }, + { "fragments", PPORT_2819_OFF(ether_stats_fragments) }, + { "jabbers", PPORT_2819_OFF(ether_stats_jabbers) }, + { "collisions", PPORT_2819_OFF(ether_stats_collisions) }, + { "p64octets", PPORT_2819_OFF(ether_stats_pkts64octets) }, + { "p65to127octets", PPORT_2819_OFF(ether_stats_pkts65to127octets) }, + { "p128to255octets", PPORT_2819_OFF(ether_stats_pkts128to255octets) }, + { "p256to511octets", PPORT_2819_OFF(ether_stats_pkts256to511octets) }, + { "p512to1023octets", PPORT_2819_OFF(ether_stats_pkts512to1023octets) }, + { "p1024to1518octets", + PPORT_2819_OFF(ether_stats_pkts1024to1518octets) }, + { "p1519to2047octets", + PPORT_2819_OFF(ether_stats_pkts1519to2047octets) }, + { "p2048to4095octets", + PPORT_2819_OFF(ether_stats_pkts2048to4095octets) }, + { "p4096to8191octets", + PPORT_2819_OFF(ether_stats_pkts4096to8191octets) }, + { "p8192to10239octets", + PPORT_2819_OFF(ether_stats_pkts8192to10239octets) }, +}; + +struct mlx5e_rq_stats { + u64 packets; + u64 bytes; + u64 csum_none; + u64 csum_sw; + u64 lro_packets; + u64 lro_bytes; + u64 wqe_err; + u64 mpwqe_filler; + u64 mpwqe_frag; + u64 buff_alloc_err; +}; + +static const struct counter_desc rq_stats_desc[] = { + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_none) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_sw) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, lro_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, lro_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, wqe_err) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, mpwqe_filler) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, mpwqe_frag) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, buff_alloc_err) }, +}; + +struct mlx5e_sq_stats { + /* commonly accessed in data path */ + u64 packets; + u64 bytes; + u64 tso_packets; + u64 tso_bytes; + u64 tso_inner_packets; + u64 tso_inner_bytes; + u64 csum_offload_inner; + u64 nop; + /* less likely accessed in data path */ + u64 csum_offload_none; + u64 stopped; + u64 wake; + u64 dropped; +}; + +static const struct counter_desc sq_stats_desc[] = { + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, tso_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, tso_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, tso_inner_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, tso_inner_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, csum_offload_inner) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, nop) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, csum_offload_none) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, stopped) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, wake) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sq_stats, dropped) }, +}; + +#define NUM_SW_COUNTERS ARRAY_SIZE(sw_stats_desc) +#define NUM_Q_COUNTERS ARRAY_SIZE(q_stats_desc) +#define NUM_VPORT_COUNTERS ARRAY_SIZE(vport_stats_desc) +#define NUM_PPORT_802_3_COUNTERS ARRAY_SIZE(pport_802_3_stats_desc) +#define NUM_PPORT_2863_COUNTERS ARRAY_SIZE(pport_2863_stats_desc) +#define NUM_PPORT_2819_COUNTERS ARRAY_SIZE(pport_2819_stats_desc) +#define NUM_PPORT_COUNTERS (NUM_PPORT_802_3_COUNTERS + \ + NUM_PPORT_2863_COUNTERS + \ + NUM_PPORT_2819_COUNTERS) +#define NUM_RQ_STATS ARRAY_SIZE(rq_stats_desc) +#define NUM_SQ_STATS ARRAY_SIZE(sq_stats_desc) + +struct mlx5e_stats { + struct mlx5e_sw_stats sw; + struct mlx5e_qcounter_stats qcnt; + struct mlx5e_vport_stats vport; + struct mlx5e_pport_stats pport; +}; + +#endif /* __MLX5_EN_STATS_H__ */ diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 03f8d719b680..8be44ca777ed 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -59,6 +59,7 @@ #define MLX5_FLD_SZ_BYTES(typ, fld) (__mlx5_bit_sz(typ, fld) / 8) #define MLX5_ST_SZ_BYTES(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8) #define MLX5_ST_SZ_DW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 32) +#define MLX5_ST_SZ_QW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 64) #define MLX5_UN_SZ_BYTES(typ) (sizeof(union mlx5_ifc_##typ##_bits) / 8) #define MLX5_UN_SZ_DW(typ) (sizeof(union mlx5_ifc_##typ##_bits) / 32) #define MLX5_BYTE_OFF(typ, fld) (__mlx5_bit_off(typ, fld) / 8) -- GitLab From 8075cb72382bf854a3a95f74ea4f9d19ebe29fd5 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:48 +0300 Subject: [PATCH 4620/9938] net/mlx5e: Rename VPort counters VPort and software counters names are confusing and may be unclear, all VPort counters now have a prefix of rx/tx_vport_*. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlx5/core/en_stats.h | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 116320d8fc42..4f3a08d7e8ed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -115,32 +115,35 @@ struct mlx5e_vport_stats { }; static const struct counter_desc vport_stats_desc[] = { - { "rx_error_packets", VPORT_COUNTER_OFF(received_errors.packets) }, - { "rx_error_bytes", VPORT_COUNTER_OFF(received_errors.octets) }, - { "tx_error_packets", VPORT_COUNTER_OFF(transmit_errors.packets) }, - { "tx_error_bytes", VPORT_COUNTER_OFF(transmit_errors.octets) }, - { "rx_unicast_packets", + { "rx_vport_error_packets", + VPORT_COUNTER_OFF(received_errors.packets) }, + { "rx_vport_error_bytes", VPORT_COUNTER_OFF(received_errors.octets) }, + { "tx_vport_error_packets", + VPORT_COUNTER_OFF(transmit_errors.packets) }, + { "tx_vport_error_bytes", VPORT_COUNTER_OFF(transmit_errors.octets) }, + { "rx_vport_unicast_packets", VPORT_COUNTER_OFF(received_eth_unicast.packets) }, - { "rx_unicast_bytes", VPORT_COUNTER_OFF(received_eth_unicast.octets) }, - { "tx_unicast_packets", + { "rx_vport_unicast_bytes", + VPORT_COUNTER_OFF(received_eth_unicast.octets) }, + { "tx_vport_unicast_packets", VPORT_COUNTER_OFF(transmitted_eth_unicast.packets) }, - { "tx_unicast_bytes", + { "tx_vport_unicast_bytes", VPORT_COUNTER_OFF(transmitted_eth_unicast.octets) }, - { "rx_multicast_packets", + { "rx_vport_multicast_packets", VPORT_COUNTER_OFF(received_eth_multicast.packets) }, - { "rx_multicast_bytes", + { "rx_vport_multicast_bytes", VPORT_COUNTER_OFF(received_eth_multicast.octets) }, - { "tx_multicast_packets", + { "tx_vport_multicast_packets", VPORT_COUNTER_OFF(transmitted_eth_multicast.packets) }, - { "tx_multicast_bytes", + { "tx_vport_multicast_bytes", VPORT_COUNTER_OFF(transmitted_eth_multicast.octets) }, - { "rx_broadcast_packets", + { "rx_vport_broadcast_packets", VPORT_COUNTER_OFF(received_eth_broadcast.packets) }, - { "rx_broadcast_bytes", + { "rx_vport_broadcast_bytes", VPORT_COUNTER_OFF(received_eth_broadcast.octets) }, - { "tx_broadcast_packets", + { "tx_vport_broadcast_packets", VPORT_COUNTER_OFF(transmitted_eth_broadcast.packets) }, - { "tx_broadcast_bytes", + { "tx_vport_broadcast_bytes", VPORT_COUNTER_OFF(transmitted_eth_broadcast.octets) }, }; -- GitLab From cf678570d5a1022c4c4dbda7792f2a36f0b9fec0 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:49 +0300 Subject: [PATCH 4621/9938] net/mlx5e: Add per priority group to PPort counters Expose counters providing information for each priority level (PCP) through ethtool -S option and DCBNL. This includes rx/tx bytes, frames, and pause counters. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlx5/core/en_dcbnl.c | 6 +++ .../ethernet/mellanox/mlx5/core/en_ethtool.c | 51 +++++++++++++++++-- .../net/ethernet/mellanox/mlx5/core/en_main.c | 9 ++++ .../ethernet/mellanox/mlx5/core/en_stats.h | 31 ++++++++++- 4 files changed, 93 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 3036f279a8fd..b2db180ae2a5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -174,8 +174,14 @@ static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev, { struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5e_pport_stats *pstats = &priv->stats.pport; + int i; pfc->pfc_cap = mlx5_max_tc(mdev) + 1; + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + pfc->requests[i] = PPORT_PER_PRIO_GET(pstats, i, tx_pause); + pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause); + } return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index f1649d543475..522d584bc05f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -165,6 +165,18 @@ static const struct { }, }; +static unsigned long mlx5e_query_pfc_combined(struct mlx5e_priv *priv) +{ + struct mlx5_core_dev *mdev = priv->mdev; + u8 pfc_en_tx; + u8 pfc_en_rx; + int err; + + err = mlx5_query_port_pfc(mdev, &pfc_en_tx, &pfc_en_rx); + + return err ? 0 : pfc_en_tx | pfc_en_rx; +} + #define MLX5E_NUM_Q_CNTRS(priv) (NUM_Q_COUNTERS * (!!priv->q_counter)) #define MLX5E_NUM_RQ_STATS(priv) \ (NUM_RQ_STATS * priv->params.num_channels * \ @@ -172,6 +184,7 @@ static const struct { #define MLX5E_NUM_SQ_STATS(priv) \ (NUM_SQ_STATS * priv->params.num_channels * priv->params.num_tc * \ test_bit(MLX5E_STATE_OPENED, &priv->state)) +#define MLX5E_NUM_PFC_COUNTERS(priv) hweight8(mlx5e_query_pfc_combined(priv)) static int mlx5e_get_sset_count(struct net_device *dev, int sset) { @@ -183,7 +196,8 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset) MLX5E_NUM_Q_CNTRS(priv) + NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS + MLX5E_NUM_RQ_STATS(priv) + - MLX5E_NUM_SQ_STATS(priv); + MLX5E_NUM_SQ_STATS(priv) + + MLX5E_NUM_PFC_COUNTERS(priv); /* fallthrough */ default: return -EOPNOTSUPP; @@ -192,7 +206,8 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset) static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data) { - int i, j, tc, idx = 0; + int i, j, tc, prio, idx = 0; + unsigned long pfc_combined; /* SW counters */ for (i = 0; i < NUM_SW_COUNTERS; i++) @@ -220,6 +235,21 @@ static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data) strcpy(data + (idx++) * ETH_GSTRING_LEN, pport_2819_stats_desc[i].name); + for (prio = 0; prio < NUM_PPORT_PRIO; prio++) { + for (i = 0; i < NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS; i++) + sprintf(data + (idx++) * ETH_GSTRING_LEN, "prio%d_%s", + prio, + pport_per_prio_traffic_stats_desc[i].name); + } + + pfc_combined = mlx5e_query_pfc_combined(priv); + for_each_set_bit(prio, &pfc_combined, NUM_PPORT_PRIO) { + for (i = 0; i < NUM_PPORT_PER_PRIO_PFC_COUNTERS; i++) { + sprintf(data + (idx++) * ETH_GSTRING_LEN, "prio%d_%s", + prio, pport_per_prio_pfc_stats_desc[i].name); + } + } + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) return; @@ -260,7 +290,8 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { struct mlx5e_priv *priv = netdev_priv(dev); - int i, j, tc, idx = 0; + int i, j, tc, prio, idx = 0; + unsigned long pfc_combined; if (!data) return; @@ -294,6 +325,20 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev, data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.RFC_2819_counters, pport_2819_stats_desc, i); + for (prio = 0; prio < NUM_PPORT_PRIO; prio++) { + for (i = 0; i < NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS; i++) + data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.per_prio_counters[prio], + pport_per_prio_traffic_stats_desc, i); + } + + pfc_combined = mlx5e_query_pfc_combined(priv); + for_each_set_bit(prio, &pfc_combined, NUM_PPORT_PRIO) { + for (i = 0; i < NUM_PPORT_PER_PRIO_PFC_COUNTERS; i++) { + data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.per_prio_counters[prio], + pport_per_prio_pfc_stats_desc, i); + } + } + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) return; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 0c532367ff13..ef66ba65f5cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -161,6 +161,7 @@ static void mlx5e_update_pport_counters(struct mlx5e_priv *priv) struct mlx5e_pport_stats *pstats = &priv->stats.pport; struct mlx5_core_dev *mdev = priv->mdev; int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); + int prio; void *out; u32 *in; @@ -182,6 +183,14 @@ static void mlx5e_update_pport_counters(struct mlx5e_priv *priv) MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2819_COUNTERS_GROUP); mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0); + MLX5_SET(ppcnt_reg, in, grp, MLX5_PER_PRIORITY_COUNTERS_GROUP); + for (prio = 0; prio < NUM_PPORT_PRIO; prio++) { + out = pstats->per_prio_counters[prio]; + MLX5_SET(ppcnt_reg, in, prio_tc, prio); + mlx5_core_access_reg(mdev, in, sz, out, sz, + MLX5_REG_PPCNT, 0, 0); + } + free_out: kvfree(in); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 4f3a08d7e8ed..de27eeaa3bd2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -165,11 +165,19 @@ static const struct counter_desc vport_stats_desc[] = { #define PPORT_2819_GET(pstats, c) \ MLX5_GET64(ppcnt_reg, pstats->RFC_2819_counters, \ counter_set.eth_2819_cntrs_grp_data_layout.c##_high) +#define PPORT_PER_PRIO_OFF(c) \ + MLX5_BYTE_OFF(ppcnt_reg, \ + counter_set.eth_per_prio_grp_data_layout.c##_high) +#define PPORT_PER_PRIO_GET(pstats, prio, c) \ + MLX5_GET64(ppcnt_reg, pstats->per_prio_counters[prio], \ + counter_set.eth_per_prio_grp_data_layout.c##_high) +#define NUM_PPORT_PRIO 8 struct mlx5e_pport_stats { __be64 IEEE_802_3_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; __be64 RFC_2863_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; __be64 RFC_2819_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; + __be64 per_prio_counters[NUM_PPORT_PRIO][MLX5_ST_SZ_QW(ppcnt_reg)]; }; static const struct counter_desc pport_802_3_stats_desc[] = { @@ -241,6 +249,21 @@ static const struct counter_desc pport_2819_stats_desc[] = { PPORT_2819_OFF(ether_stats_pkts8192to10239octets) }, }; +static const struct counter_desc pport_per_prio_traffic_stats_desc[] = { + { "rx_octets", PPORT_PER_PRIO_OFF(rx_octets) }, + { "rx_frames", PPORT_PER_PRIO_OFF(rx_frames) }, + { "tx_octets", PPORT_PER_PRIO_OFF(tx_octets) }, + { "tx_frames", PPORT_PER_PRIO_OFF(tx_frames) }, +}; + +static const struct counter_desc pport_per_prio_pfc_stats_desc[] = { + { "rx_pause", PPORT_PER_PRIO_OFF(rx_pause) }, + { "rx_pause_duration", PPORT_PER_PRIO_OFF(rx_pause_duration) }, + { "tx_pause", PPORT_PER_PRIO_OFF(tx_pause) }, + { "tx_pause_duration", PPORT_PER_PRIO_OFF(tx_pause_duration) }, + { "rx_pause_transition", PPORT_PER_PRIO_OFF(rx_pause_transition) }, +}; + struct mlx5e_rq_stats { u64 packets; u64 bytes; @@ -305,9 +328,15 @@ static const struct counter_desc sq_stats_desc[] = { #define NUM_PPORT_802_3_COUNTERS ARRAY_SIZE(pport_802_3_stats_desc) #define NUM_PPORT_2863_COUNTERS ARRAY_SIZE(pport_2863_stats_desc) #define NUM_PPORT_2819_COUNTERS ARRAY_SIZE(pport_2819_stats_desc) +#define NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS \ + ARRAY_SIZE(pport_per_prio_traffic_stats_desc) +#define NUM_PPORT_PER_PRIO_PFC_COUNTERS \ + ARRAY_SIZE(pport_per_prio_pfc_stats_desc) #define NUM_PPORT_COUNTERS (NUM_PPORT_802_3_COUNTERS + \ NUM_PPORT_2863_COUNTERS + \ - NUM_PPORT_2819_COUNTERS) + NUM_PPORT_2819_COUNTERS + \ + NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS * \ + NUM_PPORT_PRIO) #define NUM_RQ_STATS ARRAY_SIZE(rq_stats_desc) #define NUM_SQ_STATS ARRAY_SIZE(sq_stats_desc) -- GitLab From 121fcdc84d8240d4dfe1f737befd5814b12623ee Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:50 +0300 Subject: [PATCH 4622/9938] net/mlx5e: Add link down events counter Expose link_down_events counter through ethtool -S. This counter is read from PPort statistics, then proccessed and stored as a special handling software counter. This counter is stored along software counters since it is the only PPort counter that it's size is not 64 bits. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 10 +++++++++- drivers/net/ethernet/mellanox/mlx5/core/en_stats.h | 5 +++++ include/linux/mlx5/device.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index ef66ba65f5cd..61e261c3d247 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -135,6 +135,10 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv) s->tx_csum_offload = s->tx_packets - tx_offload_none - s->tx_csum_inner; s->rx_csum_good = s->rx_packets - s->rx_csum_none - s->rx_csum_sw; + + s->link_down_events = MLX5_GET(ppcnt_reg, + priv->stats.pport.phy_counters, + counter_set.phys_layer_cntrs.link_down_events); } static void mlx5e_update_vport_counters(struct mlx5e_priv *priv) @@ -183,6 +187,10 @@ static void mlx5e_update_pport_counters(struct mlx5e_priv *priv) MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2819_COUNTERS_GROUP); mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0); + out = pstats->phy_counters; + MLX5_SET(ppcnt_reg, in, grp, MLX5_PHYSICAL_LAYER_COUNTERS_GROUP); + mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0); + MLX5_SET(ppcnt_reg, in, grp, MLX5_PER_PRIORITY_COUNTERS_GROUP); for (prio = 0; prio < NUM_PPORT_PRIO; prio++) { out = pstats->per_prio_counters[prio]; @@ -208,10 +216,10 @@ static void mlx5e_update_q_counter(struct mlx5e_priv *priv) void mlx5e_update_stats(struct mlx5e_priv *priv) { - mlx5e_update_sw_counters(priv); mlx5e_update_q_counter(priv); mlx5e_update_vport_counters(priv); mlx5e_update_pport_counters(priv); + mlx5e_update_sw_counters(priv); } static void mlx5e_update_stats_work(struct work_struct *work) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index de27eeaa3bd2..7cd8cb44b2ab 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -71,6 +71,9 @@ struct mlx5e_sw_stats { u64 rx_mpwqe_filler; u64 rx_mpwqe_frag; u64 rx_buff_alloc_err; + + /* Special handling counters */ + u64 link_down_events; }; static const struct counter_desc sw_stats_desc[] = { @@ -96,6 +99,7 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_frag) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_buff_alloc_err) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, link_down_events) }, }; struct mlx5e_qcounter_stats { @@ -178,6 +182,7 @@ struct mlx5e_pport_stats { __be64 RFC_2863_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; __be64 RFC_2819_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; __be64 per_prio_counters[NUM_PPORT_PRIO][MLX5_ST_SZ_QW(ppcnt_reg)]; + __be64 phy_counters[MLX5_ST_SZ_QW(ppcnt_reg)]; }; static const struct counter_desc pport_802_3_stats_desc[] = { diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 8be44ca777ed..942bccacd7b7 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -1369,6 +1369,7 @@ enum { MLX5_ETHERNET_EXTENDED_COUNTERS_GROUP = 0x5, MLX5_PER_PRIORITY_COUNTERS_GROUP = 0x10, MLX5_PER_TRAFFIC_CLASS_COUNTERS_GROUP = 0x11, + MLX5_PHYSICAL_LAYER_COUNTERS_GROUP = 0x12, MLX5_INFINIBAND_PORT_COUNTERS_GROUP = 0x20, }; -- GitLab From 0e405443e803a3ce9ba22f11be37e2a74f3fb9ad Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:51 +0300 Subject: [PATCH 4623/9938] net/mlx5e: Improve set features ndo resiliency In current mlx5e ndo_set_features implementation, setting some features can success while others can fail. Today, we return one error code which doesn't reflect the current features status of the netdev at the end of the ndo callback. Set netdev->features with features which were successfully set in order to keep the current status in case of failure. For this purpose, define new Macro to set/unset specific feature in netdev->features. This patch introduces a mechanism that uses feature handlers for each feature. Set features will call a generic handler, which will then call a specific handler in his turn and update netdev->features according to it's return value. Each specific handler is responsible to perform driver specific actions, and updating params if needed. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en_main.c | 110 +++++++++++++----- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 61e261c3d247..d82bc6b697f9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2078,50 +2078,104 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr) return 0; } -static int mlx5e_set_features(struct net_device *netdev, - netdev_features_t features) +#define MLX5E_SET_FEATURE(netdev, feature, enable) \ + do { \ + if (enable) \ + netdev->features |= feature; \ + else \ + netdev->features &= ~feature; \ + } while (0) + +typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable); + +static int set_feature_lro(struct net_device *netdev, bool enable) { struct mlx5e_priv *priv = netdev_priv(netdev); - int err = 0; - netdev_features_t changes = features ^ netdev->features; + bool was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); + int err; mutex_lock(&priv->state_lock); - if (changes & NETIF_F_LRO) { - bool was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); - - if (was_opened && (priv->params.rq_wq_type == - MLX5_WQ_TYPE_LINKED_LIST)) - mlx5e_close_locked(priv->netdev); - - priv->params.lro_en = !!(features & NETIF_F_LRO); - err = mlx5e_modify_tirs_lro(priv); - if (err) - mlx5_core_warn(priv->mdev, "lro modify failed, %d\n", - err); + if (was_opened && (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST)) + mlx5e_close_locked(priv->netdev); - if (was_opened && (priv->params.rq_wq_type == - MLX5_WQ_TYPE_LINKED_LIST)) - err = mlx5e_open_locked(priv->netdev); + priv->params.lro_en = enable; + err = mlx5e_modify_tirs_lro(priv); + if (err) { + netdev_err(netdev, "lro modify failed, %d\n", err); + priv->params.lro_en = !enable; } + if (was_opened && (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST)) + mlx5e_open_locked(priv->netdev); + mutex_unlock(&priv->state_lock); - if (changes & NETIF_F_HW_VLAN_CTAG_FILTER) { - if (features & NETIF_F_HW_VLAN_CTAG_FILTER) - mlx5e_enable_vlan_filter(priv); - else - mlx5e_disable_vlan_filter(priv); - } + return err; +} + +static int set_feature_vlan_filter(struct net_device *netdev, bool enable) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + + if (enable) + mlx5e_enable_vlan_filter(priv); + else + mlx5e_disable_vlan_filter(priv); + + return 0; +} + +static int set_feature_tc_num_filters(struct net_device *netdev, bool enable) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); - if ((changes & NETIF_F_HW_TC) && !(features & NETIF_F_HW_TC) && - mlx5e_tc_num_filters(priv)) { + if (!enable && mlx5e_tc_num_filters(priv)) { netdev_err(netdev, "Active offloaded tc filters, can't turn hw_tc_offload off\n"); return -EINVAL; } - return err; + return 0; +} + +static int mlx5e_handle_feature(struct net_device *netdev, + netdev_features_t wanted_features, + netdev_features_t feature, + mlx5e_feature_handler feature_handler) +{ + netdev_features_t changes = wanted_features ^ netdev->features; + bool enable = !!(wanted_features & feature); + int err; + + if (!(changes & feature)) + return 0; + + err = feature_handler(netdev, enable); + if (err) { + netdev_err(netdev, "%s feature 0x%llx failed err %d\n", + enable ? "Enable" : "Disable", feature, err); + return err; + } + + MLX5E_SET_FEATURE(netdev, feature, enable); + return 0; +} + +static int mlx5e_set_features(struct net_device *netdev, + netdev_features_t features) +{ + int err; + + err = mlx5e_handle_feature(netdev, features, NETIF_F_LRO, + set_feature_lro); + err |= mlx5e_handle_feature(netdev, features, + NETIF_F_HW_VLAN_CTAG_FILTER, + set_feature_vlan_filter); + err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_TC, + set_feature_tc_num_filters); + + return err ? -EINVAL : 0; } static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu) -- GitLab From 94cb1ebbafd509210887eea6ced55c40da7b4baa Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Sun, 24 Apr 2016 22:51:52 +0300 Subject: [PATCH 4624/9938] net/mlx5e: Add support for RXALL netdev feature Introduce new access register named Ports Check Mask Register (PCMR) to control all HW checks on port. With this register, the driver can enable/disable Hardware FCS validation. When RXALL is enabled/disabled using ndo_set_features, enable/disable fcs check at HW. User can change HW configuration using rx-all flag at ethtool. Signed-off-by: Eran Ben Elisha Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en_main.c | 20 ++++++++ .../net/ethernet/mellanox/mlx5/core/port.c | 49 +++++++++++++++++++ include/linux/mlx5/driver.h | 1 + include/linux/mlx5/port.h | 4 ++ 4 files changed, 74 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index d82bc6b697f9..ad0cb4aa593b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2139,6 +2139,14 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable) return 0; } +static int set_feature_rx_all(struct net_device *netdev, bool enable) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + struct mlx5_core_dev *mdev = priv->mdev; + + return mlx5_set_port_fcs(mdev, !enable); +} + static int mlx5e_handle_feature(struct net_device *netdev, netdev_features_t wanted_features, netdev_features_t feature, @@ -2174,6 +2182,8 @@ static int mlx5e_set_features(struct net_device *netdev, set_feature_vlan_filter); err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_TC, set_feature_tc_num_filters); + err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXALL, + set_feature_rx_all); return err ? -EINVAL : 0; } @@ -2564,6 +2574,8 @@ static void mlx5e_build_netdev(struct net_device *netdev) { struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5_core_dev *mdev = priv->mdev; + bool fcs_supported; + bool fcs_enabled; SET_NETDEV_DEV(netdev, &mdev->pdev->dev); @@ -2607,10 +2619,18 @@ static void mlx5e_build_netdev(struct net_device *netdev) netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL; } + mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled); + + if (fcs_supported) + netdev->hw_features |= NETIF_F_RXALL; + netdev->features = netdev->hw_features; if (!priv->params.lro_en) netdev->features &= ~NETIF_F_LRO; + if (fcs_enabled) + netdev->features &= ~NETIF_F_RXALL; + #define FT_CAP(f) MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.f) if (FT_CAP(flow_modify_en) && FT_CAP(modify_root) && diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index ae378c575deb..c37740f30fbe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -607,3 +607,52 @@ int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode) return err; } EXPORT_SYMBOL_GPL(mlx5_query_port_wol); + +static int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, + int outlen) +{ + u32 in[MLX5_ST_SZ_DW(pcmr_reg)]; + + memset(in, 0, sizeof(in)); + MLX5_SET(pcmr_reg, in, local_port, 1); + + return mlx5_core_access_reg(mdev, in, sizeof(in), out, + outlen, MLX5_REG_PCMR, 0, 0); +} + +static int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen) +{ + u32 out[MLX5_ST_SZ_DW(pcmr_reg)]; + + return mlx5_core_access_reg(mdev, in, inlen, out, + sizeof(out), MLX5_REG_PCMR, 0, 1); +} + +int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable) +{ + u32 in[MLX5_ST_SZ_DW(pcmr_reg)]; + + memset(in, 0, sizeof(in)); + MLX5_SET(pcmr_reg, in, local_port, 1); + MLX5_SET(pcmr_reg, in, fcs_chk, enable); + + return mlx5_set_ports_check(mdev, in, sizeof(in)); +} + +void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported, + bool *enabled) +{ + u32 out[MLX5_ST_SZ_DW(pcmr_reg)]; + /* Default values for FW which do not support MLX5_REG_PCMR */ + *supported = false; + *enabled = true; + + if (!MLX5_CAP_GEN(mdev, ports_check)) + return; + + if (mlx5_query_ports_check(mdev, out, sizeof(out))) + return; + + *supported = !!(MLX5_GET(pcmr_reg, out, fcs_cap)); + *enabled = !!(MLX5_GET(pcmr_reg, out, fcs_chk)); +} diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index dcd5ac8d3b14..497a4dbd91b0 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -112,6 +112,7 @@ enum { MLX5_REG_PMPE = 0x5010, MLX5_REG_PELC = 0x500e, MLX5_REG_PVLC = 0x500f, + MLX5_REG_PCMR = 0x5041, MLX5_REG_PMLP = 0, /* TBD */ MLX5_REG_NODE_DESC = 0x6001, MLX5_REG_HOST_ENDIANNESS = 0x7004, diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h index a1d145abd4eb..577e953d0aa7 100644 --- a/include/linux/mlx5/port.h +++ b/include/linux/mlx5/port.h @@ -84,4 +84,8 @@ int mlx5_query_port_ets_rate_limit(struct mlx5_core_dev *mdev, int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode); int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode); +int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable); +void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported, + bool *enabled); + #endif /* __MLX5_PORT_H__ */ -- GitLab From da54d24ec3ef736de04c61a01653776a9750334f Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:53 +0300 Subject: [PATCH 4625/9938] net/mlx5e: Add ethtool support for interface identify (LED blinking) Add the needed hardware command and mlx5_ifc structs for managing LED control. Add set_phys_id ethtool callback to support ethtool -p flag. Signed-off-by: Gal Pressman Signed-off-by: Eugenia Emantayev Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 25 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/port.c | 13 ++++++++++ include/linux/mlx5/driver.h | 1 + include/linux/mlx5/port.h | 6 +++++ 4 files changed, 45 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 522d584bc05f..a2c444ec191b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1135,6 +1135,30 @@ static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) return mlx5_set_port_wol(mdev, mlx5_wol_mode); } +static int mlx5e_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + struct mlx5_core_dev *mdev = priv->mdev; + u16 beacon_duration; + + if (!MLX5_CAP_GEN(mdev, beacon_led)) + return -EOPNOTSUPP; + + switch (state) { + case ETHTOOL_ID_ACTIVE: + beacon_duration = MLX5_BEACON_DURATION_INF; + break; + case ETHTOOL_ID_INACTIVE: + beacon_duration = MLX5_BEACON_DURATION_OFF; + break; + default: + return -EOPNOTSUPP; + } + + return mlx5_set_port_beacon(mdev, beacon_duration); +} + const struct ethtool_ops mlx5e_ethtool_ops = { .get_drvinfo = mlx5e_get_drvinfo, .get_link = ethtool_op_get_link, @@ -1159,6 +1183,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = { .get_pauseparam = mlx5e_get_pauseparam, .set_pauseparam = mlx5e_set_pauseparam, .get_ts_info = mlx5e_get_ts_info, + .set_phys_id = mlx5e_set_phys_id, .get_wol = mlx5e_get_wol, .set_wol = mlx5e_set_wol, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index c37740f30fbe..446549f63b5c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -115,6 +115,19 @@ int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, } EXPORT_SYMBOL_GPL(mlx5_query_port_ptys); +int mlx5_set_port_beacon(struct mlx5_core_dev *dev, u16 beacon_duration) +{ + u32 out[MLX5_ST_SZ_DW(mlcr_reg)]; + u32 in[MLX5_ST_SZ_DW(mlcr_reg)]; + + memset(in, 0, sizeof(in)); + MLX5_SET(mlcr_reg, in, local_port, 1); + MLX5_SET(mlcr_reg, in, beacon_duration, beacon_duration); + + return mlx5_core_access_reg(dev, in, sizeof(in), out, + sizeof(out), MLX5_REG_MLCR, 0, 1); +} + int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev, u32 *proto_cap, int proto_mask) { diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 497a4dbd91b0..2e8758d1b19e 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -116,6 +116,7 @@ enum { MLX5_REG_PMLP = 0, /* TBD */ MLX5_REG_NODE_DESC = 0x6001, MLX5_REG_HOST_ENDIANNESS = 0x7004, + MLX5_REG_MLCR = 0x902b, }; enum { diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h index 577e953d0aa7..a364ab1737a0 100644 --- a/include/linux/mlx5/port.h +++ b/include/linux/mlx5/port.h @@ -35,6 +35,11 @@ #include +enum mlx5_beacon_duration { + MLX5_BEACON_DURATION_OFF = 0x0, + MLX5_BEACON_DURATION_INF = 0xffff, +}; + int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps); int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, int ptys_size, int proto_mask, u8 local_port); @@ -53,6 +58,7 @@ int mlx5_set_port_admin_status(struct mlx5_core_dev *dev, enum mlx5_port_status status); int mlx5_query_port_admin_status(struct mlx5_core_dev *dev, enum mlx5_port_status *status); +int mlx5_set_port_beacon(struct mlx5_core_dev *dev, u16 beacon_duration); int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu, u8 port); void mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu, u8 port); -- GitLab From bb64143eee8c036a89b31daa4e9bf8360a8bded1 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:54 +0300 Subject: [PATCH 4626/9938] net/mlx5e: Add ethtool support for dump module EEPROM Add query MCIA, PMLP registers infrastructure and commands. Add ethtool support for get_module_info() and get_module_eeprom() callbacks. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 80 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/port.c | 76 ++++++++++++++++++ include/linux/mlx5/driver.h | 3 +- include/linux/mlx5/port.h | 15 ++++ 4 files changed, 173 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index a2c444ec191b..0518c8658507 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1159,6 +1159,84 @@ static int mlx5e_set_phys_id(struct net_device *dev, return mlx5_set_port_beacon(mdev, beacon_duration); } +static int mlx5e_get_module_info(struct net_device *netdev, + struct ethtool_modinfo *modinfo) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + struct mlx5_core_dev *dev = priv->mdev; + int size_read = 0; + u8 data[4]; + + size_read = mlx5_query_module_eeprom(dev, 0, 2, data); + if (size_read < 2) + return -EIO; + + /* data[0] = identifier byte */ + switch (data[0]) { + case MLX5_MODULE_ID_QSFP: + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + break; + case MLX5_MODULE_ID_QSFP_PLUS: + case MLX5_MODULE_ID_QSFP28: + /* data[1] = revision id */ + if (data[0] == MLX5_MODULE_ID_QSFP28 || data[1] >= 0x3) { + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + } else { + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + } + break; + case MLX5_MODULE_ID_SFP: + modinfo->type = ETH_MODULE_SFF_8472; + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; + break; + default: + netdev_err(priv->netdev, "%s: cable type not recognized:0x%x\n", + __func__, data[0]); + return -EINVAL; + } + + return 0; +} + +static int mlx5e_get_module_eeprom(struct net_device *netdev, + struct ethtool_eeprom *ee, + u8 *data) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + struct mlx5_core_dev *mdev = priv->mdev; + int offset = ee->offset; + int size_read; + int i = 0; + + if (!ee->len) + return -EINVAL; + + memset(data, 0, ee->len); + + while (i < ee->len) { + size_read = mlx5_query_module_eeprom(mdev, offset, ee->len - i, + data + i); + + if (!size_read) + /* Done reading */ + return 0; + + if (size_read < 0) { + netdev_err(priv->netdev, "%s: mlx5_query_eeprom failed:0x%x\n", + __func__, size_read); + return 0; + } + + i += size_read; + offset += size_read; + } + + return 0; +} + const struct ethtool_ops mlx5e_ethtool_ops = { .get_drvinfo = mlx5e_get_drvinfo, .get_link = ethtool_op_get_link, @@ -1186,4 +1264,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = { .set_phys_id = mlx5e_set_phys_id, .get_wol = mlx5e_get_wol, .set_wol = mlx5e_set_wol, + .get_module_info = mlx5e_get_module_info, + .get_module_eeprom = mlx5e_get_module_eeprom, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 446549f63b5c..4cb2a44510fa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -310,6 +310,82 @@ void mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu, } EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu); +static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) +{ + u32 out[MLX5_ST_SZ_DW(pmlp_reg)]; + u32 in[MLX5_ST_SZ_DW(pmlp_reg)]; + int module_mapping; + int err; + + memset(in, 0, sizeof(in)); + + MLX5_SET(pmlp_reg, in, local_port, 1); + + err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), + MLX5_REG_PMLP, 0, 0); + if (err) + return err; + + module_mapping = MLX5_GET(pmlp_reg, out, lane0_module_mapping); + *module_num = module_mapping & MLX5_EEPROM_IDENTIFIER_BYTE_MASK; + + return 0; +} + +int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, + u16 offset, u16 size, u8 *data) +{ + u32 out[MLX5_ST_SZ_DW(mcia_reg)]; + u32 in[MLX5_ST_SZ_DW(mcia_reg)]; + int module_num; + u16 i2c_addr; + int status; + int err; + void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); + + err = mlx5_query_module_num(dev, &module_num); + if (err) + return err; + + memset(in, 0, sizeof(in)); + size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); + + if (offset < MLX5_EEPROM_PAGE_LENGTH && + offset + size > MLX5_EEPROM_PAGE_LENGTH) + /* Cross pages read, read until offset 256 in low page */ + size -= offset + size - MLX5_EEPROM_PAGE_LENGTH; + + i2c_addr = MLX5_I2C_ADDR_LOW; + if (offset >= MLX5_EEPROM_PAGE_LENGTH) { + i2c_addr = MLX5_I2C_ADDR_HIGH; + offset -= MLX5_EEPROM_PAGE_LENGTH; + } + + MLX5_SET(mcia_reg, in, l, 0); + MLX5_SET(mcia_reg, in, module, module_num); + MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); + MLX5_SET(mcia_reg, in, page_number, 0); + MLX5_SET(mcia_reg, in, device_address, offset); + MLX5_SET(mcia_reg, in, size, size); + + err = mlx5_core_access_reg(dev, in, sizeof(in), out, + sizeof(out), MLX5_REG_MCIA, 0, 0); + if (err) + return err; + + status = MLX5_GET(mcia_reg, out, status); + if (status) { + mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n", + status); + return -EIO; + } + + memcpy(data, ptr, size); + + return size; +} +EXPORT_SYMBOL_GPL(mlx5_query_module_eeprom); + static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc, int pvlc_size, u8 local_port) { diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 2e8758d1b19e..1a170672c656 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -113,9 +113,10 @@ enum { MLX5_REG_PELC = 0x500e, MLX5_REG_PVLC = 0x500f, MLX5_REG_PCMR = 0x5041, - MLX5_REG_PMLP = 0, /* TBD */ + MLX5_REG_PMLP = 0x5002, MLX5_REG_NODE_DESC = 0x6001, MLX5_REG_HOST_ENDIANNESS = 0x7004, + MLX5_REG_MCIA = 0x9014, MLX5_REG_MLCR = 0x902b, }; diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h index a364ab1737a0..7391eb833253 100644 --- a/include/linux/mlx5/port.h +++ b/include/linux/mlx5/port.h @@ -40,6 +40,19 @@ enum mlx5_beacon_duration { MLX5_BEACON_DURATION_INF = 0xffff, }; +enum mlx5_module_id { + MLX5_MODULE_ID_SFP = 0x3, + MLX5_MODULE_ID_QSFP = 0xC, + MLX5_MODULE_ID_QSFP_PLUS = 0xD, + MLX5_MODULE_ID_QSFP28 = 0x11, +}; + +#define MLX5_EEPROM_MAX_BYTES 32 +#define MLX5_EEPROM_IDENTIFIER_BYTE_MASK 0x000000ff +#define MLX5_I2C_ADDR_LOW 0x50 +#define MLX5_I2C_ADDR_HIGH 0x51 +#define MLX5_EEPROM_PAGE_LENGTH 256 + int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps); int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, int ptys_size, int proto_mask, u8 local_port); @@ -93,5 +106,7 @@ int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode); int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable); void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported, bool *enabled); +int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, + u16 offset, u16 size, u8 *data); #endif /* __MLX5_PORT_H__ */ -- GitLab From 363501145e3faa650193722fe7047b767ed87172 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 24 Apr 2016 22:51:55 +0300 Subject: [PATCH 4627/9938] net/mlx5e: Add ethtool support for rxvlan-offload (vlan stripping) Use ethtool -K rxvlan to enable/disable C-TAG vlan stripping by hardware. Signed-off-by: Gal Pressman Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 + .../net/ethernet/mellanox/mlx5/core/en_main.c | 74 ++++++++++++++++++- include/linux/mlx5/driver.h | 4 + 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index e903eff2574f..8abc289ac1fb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -166,6 +166,7 @@ struct mlx5e_params { u8 rss_hfunc; u8 toeplitz_hash_key[40]; u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE]; + bool vlan_strip_disable; #ifdef CONFIG_MLX5_CORE_EN_DCB struct ieee_ets ets; #endif @@ -575,6 +576,8 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto, void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv); void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv); +int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd); + int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix); void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index ad0cb4aa593b..6c9c10c131a0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -388,6 +388,7 @@ static int mlx5e_enable_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param) MLX5_SET(rqc, rqc, cqn, rq->cq.mcq.cqn); MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST); MLX5_SET(rqc, rqc, flush_in_error_en, 1); + MLX5_SET(rqc, rqc, vsd, priv->params.vlan_strip_disable); MLX5_SET(wq, wq, log_wq_pg_sz, rq->wq_ctrl.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT); MLX5_SET64(wq, wq, dbr_addr, rq->wq_ctrl.db.dma); @@ -402,7 +403,8 @@ static int mlx5e_enable_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param) return err; } -static int mlx5e_modify_rq(struct mlx5e_rq *rq, int curr_state, int next_state) +static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, + int next_state) { struct mlx5e_channel *c = rq->channel; struct mlx5e_priv *priv = c->priv; @@ -430,6 +432,36 @@ static int mlx5e_modify_rq(struct mlx5e_rq *rq, int curr_state, int next_state) return err; } +static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd) +{ + struct mlx5e_channel *c = rq->channel; + struct mlx5e_priv *priv = c->priv; + struct mlx5_core_dev *mdev = priv->mdev; + + void *in; + void *rqc; + int inlen; + int err; + + inlen = MLX5_ST_SZ_BYTES(modify_rq_in); + in = mlx5_vzalloc(inlen); + if (!in) + return -ENOMEM; + + rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx); + + MLX5_SET(modify_rq_in, in, rq_state, MLX5_RQC_STATE_RDY); + MLX5_SET64(modify_rq_in, in, modify_bitmask, MLX5_RQ_BITMASK_VSD); + MLX5_SET(rqc, rqc, vsd, vsd); + MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RDY); + + err = mlx5_core_modify_rq(mdev, rq->rqn, in, inlen); + + kvfree(in); + + return err; +} + static void mlx5e_disable_rq(struct mlx5e_rq *rq) { mlx5_core_destroy_rq(rq->priv->mdev, rq->rqn); @@ -468,7 +500,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c, if (err) goto err_destroy_rq; - err = mlx5e_modify_rq(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY); + err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY); if (err) goto err_disable_rq; @@ -493,7 +525,7 @@ static void mlx5e_close_rq(struct mlx5e_rq *rq) clear_bit(MLX5E_RQ_STATE_POST_WQES_ENABLE, &rq->state); napi_synchronize(&rq->channel->napi); /* prevent mlx5e_post_rx_wqes */ - mlx5e_modify_rq(rq, MLX5_RQC_STATE_RDY, MLX5_RQC_STATE_ERR); + mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RDY, MLX5_RQC_STATE_ERR); while (!mlx5_wq_ll_is_empty(&rq->wq)) msleep(20); @@ -1963,6 +1995,23 @@ static void mlx5e_destroy_tirs(struct mlx5e_priv *priv) mlx5e_destroy_tir(priv, i); } +int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd) +{ + int err = 0; + int i; + + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) + return 0; + + for (i = 0; i < priv->params.num_channels; i++) { + err = mlx5e_modify_rq_vsd(&priv->channel[i]->rq, vsd); + if (err) + return err; + } + + return 0; +} + static int mlx5e_setup_tc(struct net_device *netdev, u8 tc) { struct mlx5e_priv *priv = netdev_priv(netdev); @@ -2147,6 +2196,23 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable) return mlx5_set_port_fcs(mdev, !enable); } +static int set_feature_rx_vlan(struct net_device *netdev, bool enable) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + int err; + + mutex_lock(&priv->state_lock); + + priv->params.vlan_strip_disable = !enable; + err = mlx5e_modify_rqs_vsd(priv, !enable); + if (err) + priv->params.vlan_strip_disable = enable; + + mutex_unlock(&priv->state_lock); + + return err; +} + static int mlx5e_handle_feature(struct net_device *netdev, netdev_features_t wanted_features, netdev_features_t feature, @@ -2184,6 +2250,8 @@ static int mlx5e_set_features(struct net_device *netdev, set_feature_tc_num_filters); err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXALL, set_feature_rx_all); + err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX, + set_feature_rx_vlan); return err ? -EINVAL : 0; } diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 1a170672c656..2cc5e9fd5913 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -45,6 +45,10 @@ #include #include +enum { + MLX5_RQ_BITMASK_VSD = 1 << 1, +}; + enum { MLX5_BOARD_ID_LEN = 64, MLX5_MAX_NAME_LEN = 16, -- GitLab From 1b223dd391622fde05e03829d813c3c6cc998685 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Sun, 24 Apr 2016 22:51:56 +0300 Subject: [PATCH 4628/9938] net/mlx5e: Fix checksum handling for non-stripped vlan packets Now as rx-vlan offload can be disabled, packets can be received with vlan tag not stripped, which means is_first_ethertype_ip will return false, for that we need to check if the hardware reported csum OK so we will report CHECKSUM_UNNECESSARY for those packets. Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en_main.c | 1 + .../net/ethernet/mellanox/mlx5/core/en_rx.c | 20 +++++++++++++----- .../ethernet/mellanox/mlx5/core/en_stats.h | 8 +++++-- include/linux/mlx5/device.h | 21 ++++++++++++++----- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 6c9c10c131a0..5bad17d37d7b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -109,6 +109,7 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv) s->lro_bytes += rq_stats->lro_bytes; s->rx_csum_none += rq_stats->csum_none; s->rx_csum_sw += rq_stats->csum_sw; + s->rx_csum_inner += rq_stats->csum_inner; s->rx_wqe_err += rq_stats->wqe_err; s->rx_mpwqe_filler += rq_stats->mpwqe_filler; s->rx_mpwqe_frag += rq_stats->mpwqe_frag; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 918b7c7fd74f..23adfe2fcba9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -543,16 +543,26 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, if (lro) { skb->ip_summed = CHECKSUM_UNNECESSARY; - } else if (likely(is_first_ethertype_ip(skb))) { + return; + } + + if (is_first_ethertype_ip(skb)) { skb->ip_summed = CHECKSUM_COMPLETE; skb->csum = csum_unfold((__force __sum16)cqe->check_sum); rq->stats.csum_sw++; - } else { - goto csum_none; + return; } - return; - + if (likely((cqe->hds_ip_ext & CQE_L3_OK) && + (cqe->hds_ip_ext & CQE_L4_OK))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (cqe_is_tunneled(cqe)) { + skb->csum_level = 1; + skb->encapsulation = 1; + rq->stats.csum_inner++; + } + return; + } csum_none: skb->ip_summed = CHECKSUM_NONE; rq->stats.csum_none++; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 7cd8cb44b2ab..115752b53d85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -62,6 +62,7 @@ struct mlx5e_sw_stats { u64 rx_csum_good; u64 rx_csum_none; u64 rx_csum_sw; + u64 rx_csum_inner; u64 tx_csum_offload; u64 tx_csum_inner; u64 tx_queue_stopped; @@ -90,6 +91,7 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_good) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_none) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_sw) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_inner) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_offload) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_inner) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_stopped) }, @@ -272,8 +274,9 @@ static const struct counter_desc pport_per_prio_pfc_stats_desc[] = { struct mlx5e_rq_stats { u64 packets; u64 bytes; - u64 csum_none; u64 csum_sw; + u64 csum_inner; + u64 csum_none; u64 lro_packets; u64 lro_bytes; u64 wqe_err; @@ -285,8 +288,9 @@ struct mlx5e_rq_stats { static const struct counter_desc rq_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, packets) }, { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, bytes) }, - { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_none) }, { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_sw) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_inner) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, csum_none) }, { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, lro_packets) }, { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, lro_bytes) }, { MLX5E_DECLARE_STAT(struct mlx5e_rq_stats, wqe_err) }, diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 942bccacd7b7..6bd429b53b77 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -645,8 +645,9 @@ struct mlx5_err_cqe { }; struct mlx5_cqe64 { - u8 rsvd0[2]; - __be16 wqe_id; + u8 outer_l3_tunneled; + u8 rsvd0; + __be16 wqe_id; u8 lro_tcppsh_abort_dupack; u8 lro_min_ttl; __be16 lro_tcp_win; @@ -659,7 +660,7 @@ struct mlx5_cqe64 { __be16 slid; __be32 flags_rqpn; u8 hds_ip_ext; - u8 l4_hdr_type_etc; + u8 l4_l3_hdr_type; __be16 vlan_info; __be32 srqn; /* [31:24]: lro_num_seg, [23:0]: srqn */ __be32 imm_inval_pkey; @@ -680,12 +681,22 @@ static inline int get_cqe_lro_tcppsh(struct mlx5_cqe64 *cqe) static inline u8 get_cqe_l4_hdr_type(struct mlx5_cqe64 *cqe) { - return (cqe->l4_hdr_type_etc >> 4) & 0x7; + return (cqe->l4_l3_hdr_type >> 4) & 0x7; +} + +static inline u8 get_cqe_l3_hdr_type(struct mlx5_cqe64 *cqe) +{ + return (cqe->l4_l3_hdr_type >> 2) & 0x3; +} + +static inline u8 cqe_is_tunneled(struct mlx5_cqe64 *cqe) +{ + return cqe->outer_l3_tunneled & 0x1; } static inline int cqe_has_vlan(struct mlx5_cqe64 *cqe) { - return !!(cqe->l4_hdr_type_etc & 0x1); + return !!(cqe->l4_l3_hdr_type & 0x1); } static inline u64 get_cqe_ts(struct mlx5_cqe64 *cqe) -- GitLab From 97717edc69eabdcc8b1859af75a363790c3e9cb6 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 23:45:23 +0300 Subject: [PATCH 4629/9938] sh_eth: use EDMR_SRST_GETHER in sh_eth_check_reset() sh_eth_check_reset() uses a bare number where EDMR_SRST_GETHER would fit, i.e. the receive/trasmit software reset bits that comprise EDMR_SRST_GETHER read as 1 while the corresponding reset is in progress and thus, when both are 0, the reset is complete. Signed-off-by: Sergei Shtylyov Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index edf6356c7034..3d7a40af5aab 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -899,7 +899,7 @@ static int sh_eth_check_reset(struct net_device *ndev) int cnt = 100; while (cnt > 0) { - if (!(sh_eth_read(ndev, EDMR) & 0x3)) + if (!(sh_eth_read(ndev, EDMR) & EDMR_SRST_GETHER)) break; mdelay(1); cnt--; -- GitLab From ec65cfce508885e433445036ab46f4ec91d32c5c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 24 Apr 2016 23:46:15 +0300 Subject: [PATCH 4630/9938] sh_eth: rename ARSTR register bit The Renesas RZ/A1H manual names the software reset bit in the software reset register (ARSTR) ARST which makes a bit more sense than the ARSTR_ARSTR name used now by the driver -- rename the latter to ARSTR_ARST. Signed-off-by: Sergei Shtylyov Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 6 +++--- drivers/net/ethernet/renesas/sh_eth.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 3d7a40af5aab..07e29638299f 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -482,7 +482,7 @@ static void sh_eth_chip_reset(struct net_device *ndev) struct sh_eth_private *mdp = netdev_priv(ndev); /* reset device */ - sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR); + sh_eth_tsu_write(mdp, ARSTR_ARST, ARSTR); mdelay(1); } @@ -540,7 +540,7 @@ static void sh_eth_chip_reset_r8a7740(struct net_device *ndev) struct sh_eth_private *mdp = netdev_priv(ndev); /* reset device */ - sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR); + sh_eth_tsu_write(mdp, ARSTR_ARST, ARSTR); mdelay(1); sh_eth_select_mii(ndev); @@ -735,7 +735,7 @@ static void sh_eth_chip_reset_giga(struct net_device *ndev) } /* reset device */ - iowrite32(ARSTR_ARSTR, (void *)(SH_GIGA_ETH_BASE + 0x1800)); + iowrite32(ARSTR_ARST, (void *)(SH_GIGA_ETH_BASE + 0x1800)); mdelay(1); /* restore MAHR and MALR */ diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 8fa4ef3a7fdd..c62380e34a1d 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -394,7 +394,7 @@ enum RPADIR_BIT { #define DEFAULT_FDR_INIT 0x00000707 /* ARSTR */ -enum ARSTR_BIT { ARSTR_ARSTR = 0x00000001, }; +enum ARSTR_BIT { ARSTR_ARST = 0x00000001, }; /* TSU_FWEN0 */ enum TSU_FWEN0_BIT { -- GitLab From 624c8df7d2823ec0df9609025480309322886ed3 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 26 Apr 2016 08:47:17 +0200 Subject: [PATCH 4631/9938] PM / Domains: Remove redundant pm_runtime_get|put*() in pm_genpd_prepare() The PM core increases and decreases the runtime PM usage count in the system PM prepare phase. This makes some of the pm_runtime_get|put*() calls in pm_genpd_prepare() redundant, so let's remove them. Signed-off-by: Ulf Hansson Reviewed-by: Kevin Hilman Reviewed-by: Laurent Pinchart Reviewed-by: Laurent Pinchart Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 4ce4ce0a2730..60a357386705 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -730,14 +730,11 @@ static int pm_genpd_prepare(struct device *dev) * at this point and a system wakeup event should be reported if it's * set up to wake up the system from sleep states. */ - pm_runtime_get_noresume(dev); if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) pm_wakeup_event(dev, 0); - if (pm_wakeup_pending()) { - pm_runtime_put(dev); + if (pm_wakeup_pending()) return -EBUSY; - } if (resume_needed(dev, genpd)) pm_runtime_resume(dev); @@ -751,10 +748,8 @@ static int pm_genpd_prepare(struct device *dev) mutex_unlock(&genpd->lock); - if (genpd->suspend_power_off) { - pm_runtime_put_noidle(dev); + if (genpd->suspend_power_off) return 0; - } /* * The PM domain must be in the GPD_STATE_ACTIVE state at this point, @@ -776,7 +771,6 @@ static int pm_genpd_prepare(struct device *dev) pm_runtime_enable(dev); } - pm_runtime_put(dev); return ret; } -- GitLab From 164a2159a2d6789bc7e3c4b126dde7f3ce865992 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 26 Apr 2016 08:47:18 +0200 Subject: [PATCH 4632/9938] PM / Domains: Drop unnecessary wakeup code from pm_genpd_prepare() As the PM core already have wakeup management during the system PM phase, it seems reasonable that genpd and its users should be able to rely on that. Therefore let's remove this from pm_genpd_prepare(). Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 60a357386705..de23b648fce3 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -730,12 +730,6 @@ static int pm_genpd_prepare(struct device *dev) * at this point and a system wakeup event should be reported if it's * set up to wake up the system from sleep states. */ - if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) - pm_wakeup_event(dev, 0); - - if (pm_wakeup_pending()) - return -EBUSY; - if (resume_needed(dev, genpd)) pm_runtime_resume(dev); -- GitLab From 6df795ff139a85eba8767a1504414c41e8814a1a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Apr 2016 08:53:41 +0100 Subject: [PATCH 4633/9938] ACPI / ARM64: Don't enable ACPI by default on ARM64 If ACPI is selectable it is enabled by default. This is a good choice for architectures where the overwhelming majority of systems use ACPI like x86 and IA-64 but is less clear for architectures where it's less common like ARM64. Change the default selection so that it's only done explicitly on those architectures where ACPI is universally used. Signed-off-by: Mark Brown Acked-by: Catalin Marinas Acked-by: Hanjun Guo Acked-by: Olof Johansson Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 82b96ee8624c..2fcf87a6d270 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -8,7 +8,7 @@ menuconfig ACPI depends on IA64 || X86 || (ARM64 && EXPERT) depends on PCI select PNP - default y + default y if (IA64 || X86) help Advanced Configuration and Power Interface (ACPI) support for Linux requires an ACPI-compliant platform (hardware/firmware), -- GitLab From 46bcc6b1f3f77ff0a5b88b87a6be5954ed0c3ce6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Apr 2016 08:53:42 +0100 Subject: [PATCH 4634/9938] ACPI / ARM64: Remove EXPERT dependency for ACPI on ARM64 When ACPI was originally merged for arm64 it had only been tested on emulators and not on real physical platforms and no platforms were relying on it. This meant that there were concerns that there might be serious issues attempting to use it on practical systems so it had a dependency on EXPERT added to warn people that it was in an early stage of development with very little practical testing. Since then things have moved on a bit. We have seen people testing on real hardware and now have people starting to produce some platforms (the most prominent being the 96boards Cello) which only have ACPI support and which build and run to some useful extent with mainline. This is not to say that ACPI support or support for these systems is completely done, there are still areas being worked on such as PCI, but at this point it seems that we can be reasonably sure that ACPI will be viable for use on ARM64 and that the already merged support works for the cases it handles. For the AMD Seattle based platforms support outside of PCI has been fairly complete in mainline a few releases now. This is also not to say that we don't have vendors working with ACPI who are trying do things that we would not consider optimal but it does not appear that the EXPERT dependency is having a substantial impact on these vendors. Given all this it seems that at this point the EXPERT dependency mainly creates inconvenience for users with systems that are doing the right thing and gets in the way of including the ACPI code in the testing that people are doing on mainline. Removing it should help our ongoing testing cover those platforms with only ACPI support and help ensure that when ACPI code is merged any problems it causes for other users are more easily discovered. Signed-off-by: Mark Brown Acked-by: Graeme Gregory Acked-by: Ard Biesheuvel Reviewed-by: Al Stone Acked-by: Hanjun Guo Acked-by: Catalin Marinas Acked-by: Roy Franz Acked-by: Olof Johansson Acked-by: Timur Tabi Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 2fcf87a6d270..fa0d319283e3 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -5,7 +5,7 @@ menuconfig ACPI bool "ACPI (Advanced Configuration and Power Interface) Support" depends on !IA64_HP_SIM - depends on IA64 || X86 || (ARM64 && EXPERT) + depends on IA64 || X86 || ARM64 depends on PCI select PNP default y if (IA64 || X86) -- GitLab From 2b13f01b90fc07334911b424709901bb88517746 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Apr 2016 08:53:43 +0100 Subject: [PATCH 4635/9938] arm64: defconfig: Enable ACPI Enable ACPI by default to support testing of ACPI only systems and ensure that defconfig will boot on anything, for arm64 this is not done in Kconfig since a very large proportion of arm64 systems have no ACPI at all. Signed-off-by: Mark Brown Acked-by: Catalin Marinas Acked-by: Hanjun Guo Acked-by: Roy Franz Signed-off-by: Rafael J. Wysocki --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index a44ef995d8ae..c5e0132eec57 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -264,6 +264,7 @@ CONFIG_PHY_RCAR_GEN3_USB2=y CONFIG_PHY_HI6220_USB=y CONFIG_PHY_XGENE=y CONFIG_ARM_SCPI_PROTOCOL=y +CONFIG_ACPI=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_FANOTIFY=y -- GitLab From 392d01de2d2476e8a50cf30f049e369deaaea127 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Tue, 26 Apr 2016 16:26:52 +0200 Subject: [PATCH 4636/9938] i2c: octeon: Remove zero-length message support Zero-length message support (SMBUS QUICK or i2c) never worked with the Octeon hardware. Disable SMBUS QUICK support and bail out in case of a zero-length i2c request. After this change 'i2c-detect -q' will return an error on Octeon but the previously reported results were wrong anyway. Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 6a4f0581a7e0..4fc471ce173e 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -838,9 +838,6 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, int i, result, length = *rlength; bool final_read = false; - if (length < 1) - return -EINVAL; - octeon_i2c_data_write(i2c, (target << 1) | 1); octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); @@ -926,6 +923,12 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, for (i = 0; ret == 0 && i < num; i++) { struct i2c_msg *pmsg = &msgs[i]; + /* zero-length messages are not supported */ + if (!pmsg->len) { + ret = -EOPNOTSUPP; + break; + } + ret = octeon_i2c_start(i2c); if (ret) return ret; @@ -999,7 +1002,7 @@ static struct i2c_bus_recovery_info octeon_i2c_recovery_info = { static u32 octeon_i2c_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL; } -- GitLab From db0a6fb5d97afe01fd9c47d37c6daa82d4d4001d Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 21 Apr 2016 14:14:01 -0400 Subject: [PATCH 4637/9938] audit: add tty field to LOGIN event The tty field was missing from AUDIT_LOGIN events. Refactor code to create a new function audit_get_tty(), using it to replace the call in audit_log_task_info() and to add it to audit_log_set_loginuid(). Lock and bump the kref to protect it, adding audit_put_tty() alias to decrement it. Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- include/linux/audit.h | 24 ++++++++++++++++++++++++ kernel/audit.c | 18 +++++------------- kernel/auditsc.c | 8 ++++++-- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index b40ed5df5542..32cdafb312d8 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -26,6 +26,7 @@ #include #include #include +#include #define AUDIT_INO_UNSET ((unsigned long)-1) #define AUDIT_DEV_UNSET ((dev_t)-1) @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->sessionid; } +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) +{ + struct tty_struct *tty = NULL; + unsigned long flags; + + spin_lock_irqsave(&tsk->sighand->siglock, flags); + if (tsk->signal) + tty = tty_kref_get(tsk->signal->tty); + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); + return tty; +} + +static inline void audit_put_tty(struct tty_struct *tty) +{ + tty_kref_put(tty); +} + extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); extern void __audit_bprm(struct linux_binprm *bprm); @@ -500,6 +518,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { return -1; } +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) +{ + return NULL; +} +static inline void audit_put_tty(struct tty_struct *tty) +{ } static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) { } static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, diff --git a/kernel/audit.c b/kernel/audit.c index f52fbefede09..384374a1d232 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -64,7 +64,6 @@ #include #endif #include -#include #include #include @@ -1871,21 +1870,14 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) { const struct cred *cred; char comm[sizeof(tsk->comm)]; - char *tty; + struct tty_struct *tty; if (!ab) return; /* tsk == current */ cred = current_cred(); - - spin_lock_irq(&tsk->sighand->siglock); - if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) - tty = tsk->signal->tty->name; - else - tty = "(none)"; - spin_unlock_irq(&tsk->sighand->siglock); - + tty = audit_get_tty(tsk); audit_log_format(ab, " ppid=%d pid=%d auid=%u uid=%u gid=%u" " euid=%u suid=%u fsuid=%u" @@ -1901,11 +1893,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) from_kgid(&init_user_ns, cred->egid), from_kgid(&init_user_ns, cred->sgid), from_kgid(&init_user_ns, cred->fsgid), - tty, audit_get_sessionid(tsk)); - + tty ? tty_name(tty) : "(none)", + audit_get_sessionid(tsk)); + audit_put_tty(tty); audit_log_format(ab, " comm="); audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); - audit_log_d_path_exe(ab, tsk->mm); audit_log_task_context(ab); } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 195ffaee50b9..71e14d836e69 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, { struct audit_buffer *ab; uid_t uid, oldloginuid, loginuid; + struct tty_struct *tty; if (!audit_enabled) return; @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, uid = from_kuid(&init_user_ns, task_uid(current)); oldloginuid = from_kuid(&init_user_ns, koldloginuid); loginuid = from_kuid(&init_user_ns, kloginuid), + tty = audit_get_tty(current); ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); if (!ab) return; audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); audit_log_task_context(ab); - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", - oldloginuid, loginuid, oldsessionid, sessionid, !rc); + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", + oldsessionid, sessionid, !rc); + audit_put_tty(tty); audit_log_end(ab); } -- GitLab From 1bb1ff3e7c74f4569dddf7bda8054a0bb6ed0073 Mon Sep 17 00:00:00 2001 From: Peter Swain Date: Mon, 25 Apr 2016 16:33:37 +0200 Subject: [PATCH 4638/9938] i2c: octeon: Improve performance if interrupt is early MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a race between the TWSI interrupt and the condition that is required before proceeding: Low-level: interrupt flag bit must be set High-level controller: valid bit must be clear If the interrupt comes too early and the condition is not met the wait will time out, and the transfer is aborted leading to very poor performance. To avoid this race retry for the condition ~80 µs later. The retry is avoided on the very first invocation of wait_event_timeout() (which tests the condition before entering the wait and is therefore always wrong in this case). EEPROM reads on 100kHz i2c now measure ~5.2kB/s, about 1/2 what's achievable, and much better than the worst-case 100 bytes/sec before. While at it remove the debug print from the low-level wait function. Signed-off-by: Peter Swain Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 55 +++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 4fc471ce173e..cb418140cbbe 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -109,6 +109,8 @@ #define TWSI_INT_SDA BIT_ULL(10) #define TWSI_INT_SCL BIT_ULL(11) +#define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */ + struct octeon_i2c { wait_queue_head_t queue; struct i2c_adapter adap; @@ -339,11 +341,29 @@ static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id) return IRQ_HANDLED; } -static int octeon_i2c_test_iflg(struct octeon_i2c *i2c) +static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c) { return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG); } +static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first) +{ + if (octeon_i2c_test_iflg(i2c)) + return true; + + if (*first) { + *first = false; + return false; + } + + /* + * IRQ has signaled an event but IFLG hasn't changed. + * Sleep and retry once. + */ + usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT); + return octeon_i2c_test_iflg(i2c); +} + /** * octeon_i2c_wait - wait for the IFLG to be set * @i2c: The struct octeon_i2c @@ -353,15 +373,14 @@ static int octeon_i2c_test_iflg(struct octeon_i2c *i2c) static int octeon_i2c_wait(struct octeon_i2c *i2c) { long time_left; + bool first = 1; i2c->int_enable(i2c); - time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c), + time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first), i2c->adap.timeout); i2c->int_disable(i2c); - if (!time_left) { - dev_dbg(i2c->dev, "%s: timeout\n", __func__); + if (!time_left) return -ETIMEDOUT; - } return 0; } @@ -427,11 +446,28 @@ static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) } } -static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c) +static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c) +{ + return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0; +} + +static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first) { - u64 val = __raw_readq(i2c->twsi_base + SW_TWSI); + /* check if valid bit is cleared */ + if (octeon_i2c_hlc_test_valid(i2c)) + return true; - return (val & SW_TWSI_V) == 0; + if (*first) { + *first = false; + return false; + } + + /* + * IRQ has signaled an event but valid bit isn't cleared. + * Sleep and retry once. + */ + usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT); + return octeon_i2c_hlc_test_valid(i2c); } static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c) @@ -453,11 +489,12 @@ static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c) */ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) { + bool first = 1; int time_left; i2c->hlc_int_enable(i2c); time_left = wait_event_timeout(i2c->queue, - octeon_i2c_hlc_test_ready(i2c), + octeon_i2c_hlc_test_ready(i2c, &first), i2c->adap.timeout); i2c->hlc_int_disable(i2c); if (!time_left) { -- GitLab From eca76e783cf5970db36edfda7e66487d897ea222 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 13 Apr 2016 16:14:38 -0700 Subject: [PATCH 4639/9938] f2fs: avoid needless lock for node pages when fsyncing a file When fsync is called, sync_node_pages finds a proper direct node pages to flush. But, it locks unrelated direct node pages together unnecessarily. Acked-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/node.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 095fc2c96e16..cccee5006cdd 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1272,10 +1272,14 @@ int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, * we should not skip writing node pages. */ lock_node: - if (ino && ino_of_node(page) == ino) - lock_page(page); - else if (!trylock_page(page)) + if (ino) { + if (ino_of_node(page) == ino) + lock_page(page); + else + continue; + } else if (!trylock_page(page)) { continue; + } if (unlikely(page->mapping != NODE_MAPPING(sbi))) { continue_unlock: -- GitLab From e6e5f5610d585551785ec654b6db9277b19a0664 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 14 Apr 2016 16:48:52 -0700 Subject: [PATCH 4640/9938] f2fs: avoid writing 0'th page in volatile writes The first page of volatile writes usually contains a sort of header information which will be used for recovery. (e.g., journal header of sqlite) If this is written without other journal data, user needs to handle the stale journal information. Acked-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index c29bcf4cfca1..e54489b970ae 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1177,8 +1177,10 @@ static int f2fs_write_data_page(struct page *page, goto redirty_out; if (f2fs_is_drop_cache(inode)) goto out; - if (f2fs_is_volatile_file(inode) && !wbc->for_reclaim && - available_free_memory(sbi, BASE_CHECK)) + /* we should not write 0'th page having journal header */ + if (f2fs_is_volatile_file(inode) && (!page->index || + (!wbc->for_reclaim && + available_free_memory(sbi, BASE_CHECK)))) goto redirty_out; /* Dentry blocks are controlled by checkpoint */ -- GitLab From 5268137564920843e581304d9bfb06fb9502cf24 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 13 Apr 2016 16:24:44 -0700 Subject: [PATCH 4641/9938] f2fs: split sync_node_pages with fsync_node_pages This patch splits the existing sync_node_pages into (f)sync_node_pages. The fsync_node_pages is used for f2fs_sync_file only. Acked-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 3 +- fs/f2fs/file.c | 2 +- fs/f2fs/gc.c | 2 +- fs/f2fs/node.c | 108 +++++++++++++++++++++++++++++++------------ 5 files changed, 84 insertions(+), 33 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index b92782f40643..bf040b51989d 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -892,7 +892,7 @@ static int block_operations(struct f2fs_sb_info *sbi) if (get_pages(sbi, F2FS_DIRTY_NODES)) { up_write(&sbi->node_write); - err = sync_node_pages(sbi, 0, &wbc); + err = sync_node_pages(sbi, &wbc); if (err) { f2fs_unlock_all(sbi); goto out; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 3f1551395244..269abe5959e7 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1784,7 +1784,8 @@ void ra_node_page(struct f2fs_sb_info *, nid_t); struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); struct page *get_node_page_ra(struct page *, int); void sync_inode_page(struct dnode_of_data *); -int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *); +int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *); +int sync_node_pages(struct f2fs_sb_info *, struct writeback_control *); bool alloc_nid(struct f2fs_sb_info *, nid_t *); void alloc_nid_done(struct f2fs_sb_info *, nid_t); void alloc_nid_failed(struct f2fs_sb_info *, nid_t); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7de90e60abd1..3d53ee058aae 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -256,7 +256,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) goto out; } sync_nodes: - sync_node_pages(sbi, ino, &wbc); + fsync_node_pages(sbi, ino, &wbc); /* if cp_error was enabled, we should avoid infinite loop */ if (unlikely(f2fs_cp_error(sbi))) { diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b0051a97824c..e82046523186 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -841,7 +841,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, .nr_to_write = LONG_MAX, .for_reclaim = 0, }; - sync_node_pages(sbi, 0, &wbc); + sync_node_pages(sbi, &wbc); } else { f2fs_submit_merged_bio(sbi, DATA, WRITE); } diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index cccee5006cdd..675b7304c02a 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1222,12 +1222,84 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) iput(inode); } -int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, +int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, struct writeback_control *wbc) { pgoff_t index, end; struct pagevec pvec; - int step = ino ? 2 : 0; + int nwritten = 0; + + pagevec_init(&pvec, 0); + index = 0; + end = ULONG_MAX; + + while (index <= end) { + int i, nr_pages; + nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, + PAGECACHE_TAG_DIRTY, + min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); + if (nr_pages == 0) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + if (unlikely(f2fs_cp_error(sbi))) { + pagevec_release(&pvec); + return -EIO; + } + + if (!IS_DNODE(page) || !is_cold_node(page)) + continue; + if (ino_of_node(page) != ino) + continue; + + lock_page(page); + + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { +continue_unlock: + unlock_page(page); + continue; + } + if (ino_of_node(page) != ino) + goto continue_unlock; + + if (!PageDirty(page)) { + /* someone wrote it for us */ + goto continue_unlock; + } + + f2fs_wait_on_page_writeback(page, NODE, true); + BUG_ON(PageWriteback(page)); + if (!clear_page_dirty_for_io(page)) + goto continue_unlock; + + set_fsync_mark(page, 1); + if (IS_INODE(page)) + set_dentry_mark(page, + need_dentry_mark(sbi, ino)); + nwritten++; + + if (NODE_MAPPING(sbi)->a_ops->writepage(page, wbc)) + unlock_page(page); + + if (--wbc->nr_to_write == 0) + break; + } + pagevec_release(&pvec); + cond_resched(); + + if (wbc->nr_to_write == 0) + break; + } + return nwritten; +} + +int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc) +{ + pgoff_t index, end; + struct pagevec pvec; + int step = 0; int nwritten = 0; pagevec_init(&pvec, 0); @@ -1266,28 +1338,15 @@ int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, if (step == 2 && (!IS_DNODE(page) || !is_cold_node(page))) continue; - - /* - * If an fsync mode, - * we should not skip writing node pages. - */ lock_node: - if (ino) { - if (ino_of_node(page) == ino) - lock_page(page); - else - continue; - } else if (!trylock_page(page)) { + if (!trylock_page(page)) continue; - } if (unlikely(page->mapping != NODE_MAPPING(sbi))) { continue_unlock: unlock_page(page); continue; } - if (ino && ino_of_node(page) != ino) - goto continue_unlock; if (!PageDirty(page)) { /* someone wrote it for us */ @@ -1295,7 +1354,7 @@ int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, } /* flush inline_data */ - if (!ino && is_inline_node(page)) { + if (is_inline_node(page)) { clear_inline_node(page); unlock_page(page); flush_inline_data(sbi, ino_of_node(page)); @@ -1308,17 +1367,8 @@ int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, if (!clear_page_dirty_for_io(page)) goto continue_unlock; - /* called by fsync() */ - if (ino && IS_DNODE(page)) { - set_fsync_mark(page, 1); - if (IS_INODE(page)) - set_dentry_mark(page, - need_dentry_mark(sbi, ino)); - nwritten++; - } else { - set_fsync_mark(page, 0); - set_dentry_mark(page, 0); - } + set_fsync_mark(page, 0); + set_dentry_mark(page, 0); if (NODE_MAPPING(sbi)->a_ops->writepage(page, wbc)) unlock_page(page); @@ -1466,7 +1516,7 @@ static int f2fs_write_node_pages(struct address_space *mapping, diff = nr_pages_to_write(sbi, NODE, wbc); wbc->sync_mode = WB_SYNC_NONE; - sync_node_pages(sbi, 0, wbc); + sync_node_pages(sbi, wbc); wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); return 0; -- GitLab From c267ec1526da2d3b12c80a89ebd8eb9b6a01d636 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 15 Apr 2016 09:25:04 -0700 Subject: [PATCH 4642/9938] f2fs: report unwritten status in fsync_node_pages The fsync_node_pages should return pass or failure so that user could know fsync is completed or not. Acked-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 4 +++- fs/f2fs/node.c | 13 ++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 3d53ee058aae..60fd64c59cce 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -256,7 +256,9 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) goto out; } sync_nodes: - fsync_node_pages(sbi, ino, &wbc); + ret = fsync_node_pages(sbi, ino, &wbc); + if (ret) + goto out; /* if cp_error was enabled, we should avoid infinite loop */ if (unlikely(f2fs_cp_error(sbi))) { diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 675b7304c02a..8a1e21144ecb 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1227,7 +1227,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, { pgoff_t index, end; struct pagevec pvec; - int nwritten = 0; + int ret = 0; pagevec_init(&pvec, 0); index = 0; @@ -1278,21 +1278,20 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, if (IS_INODE(page)) set_dentry_mark(page, need_dentry_mark(sbi, ino)); - nwritten++; - if (NODE_MAPPING(sbi)->a_ops->writepage(page, wbc)) + ret = NODE_MAPPING(sbi)->a_ops->writepage(page, wbc); + if (ret) { unlock_page(page); - - if (--wbc->nr_to_write == 0) break; + } } pagevec_release(&pvec); cond_resched(); - if (wbc->nr_to_write == 0) + if (ret) break; } - return nwritten; + return ret ? -EIO: 0; } int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc) -- GitLab From 608514deba38c8611ad330d6a3c8e2b9a1f68e4b Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 15 Apr 2016 09:43:17 -0700 Subject: [PATCH 4643/9938] f2fs: set fsync mark only for the last dnode In order to give atomic writes, we should consider power failure during sync_node_pages in fsync. So, this patch marks fsync flag only in the last dnode block. Acked-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 4 +- fs/f2fs/file.c | 14 ++++-- fs/f2fs/node.c | 106 +++++++++++++++++++++++++++++++++++++++++---- fs/f2fs/recovery.c | 9 ++-- 4 files changed, 113 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 269abe5959e7..ca828b0e7d6d 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -159,7 +159,6 @@ struct fsync_inode_entry { struct inode *inode; /* vfs inode pointer */ block_t blkaddr; /* block address locating the last fsync */ block_t last_dentry; /* block address locating the last dentry */ - block_t last_inode; /* block address locating the last inode */ }; #define nats_in_cursum(jnl) (le16_to_cpu(jnl->n_nats)) @@ -1784,7 +1783,8 @@ void ra_node_page(struct f2fs_sb_info *, nid_t); struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); struct page *get_node_page_ra(struct page *, int); void sync_inode_page(struct dnode_of_data *); -int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *); +int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *, + bool); int sync_node_pages(struct f2fs_sb_info *, struct writeback_control *); bool alloc_nid(struct f2fs_sb_info *, nid_t *); void alloc_nid_done(struct f2fs_sb_info *, nid_t); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 60fd64c59cce..dc47d5c7b882 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -182,7 +182,8 @@ static void try_to_fix_pino(struct inode *inode) } } -int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) +static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end, + int datasync, bool atomic) { struct inode *inode = file->f_mapping->host; struct f2fs_inode_info *fi = F2FS_I(inode); @@ -256,7 +257,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) goto out; } sync_nodes: - ret = fsync_node_pages(sbi, ino, &wbc); + ret = fsync_node_pages(sbi, ino, &wbc, atomic); if (ret) goto out; @@ -290,6 +291,11 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) return ret; } +int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) +{ + return f2fs_do_sync_file(file, start, end, datasync, false); +} + static pgoff_t __get_first_dirty_index(struct address_space *mapping, pgoff_t pgofs, int whence) { @@ -1407,7 +1413,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) } } - ret = f2fs_sync_file(filp, 0, LLONG_MAX, 0); + ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true); err_out: mnt_drop_write_file(filp); return ret; @@ -1465,7 +1471,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp) drop_inmem_pages(inode); if (f2fs_is_volatile_file(inode)) { clear_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); - ret = f2fs_sync_file(filp, 0, LLONG_MAX, 0); + ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true); } mnt_drop_write_file(filp); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 8a1e21144ecb..de070a524fd2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1222,13 +1222,81 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) iput(inode); } +static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) +{ + pgoff_t index, end; + struct pagevec pvec; + struct page *last_page = NULL; + + pagevec_init(&pvec, 0); + index = 0; + end = ULONG_MAX; + + while (index <= end) { + int i, nr_pages; + nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, + PAGECACHE_TAG_DIRTY, + min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); + if (nr_pages == 0) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + if (unlikely(f2fs_cp_error(sbi))) { + f2fs_put_page(last_page, 0); + pagevec_release(&pvec); + return ERR_PTR(-EIO); + } + + if (!IS_DNODE(page) || !is_cold_node(page)) + continue; + if (ino_of_node(page) != ino) + continue; + + lock_page(page); + + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { +continue_unlock: + unlock_page(page); + continue; + } + if (ino_of_node(page) != ino) + goto continue_unlock; + + if (!PageDirty(page)) { + /* someone wrote it for us */ + goto continue_unlock; + } + + if (last_page) + f2fs_put_page(last_page, 0); + + get_page(page); + last_page = page; + unlock_page(page); + } + pagevec_release(&pvec); + cond_resched(); + } + return last_page; +} + int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, - struct writeback_control *wbc) + struct writeback_control *wbc, bool atomic) { pgoff_t index, end; struct pagevec pvec; int ret = 0; + struct page *last_page = NULL; + bool marked = false; + if (atomic) { + last_page = last_fsync_dnode(sbi, ino); + if (IS_ERR_OR_NULL(last_page)) + return PTR_ERR_OR_ZERO(last_page); + } +retry: pagevec_init(&pvec, 0); index = 0; end = ULONG_MAX; @@ -1245,6 +1313,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, struct page *page = pvec.pages[i]; if (unlikely(f2fs_cp_error(sbi))) { + f2fs_put_page(last_page, 0); pagevec_release(&pvec); return -EIO; } @@ -1264,33 +1333,54 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, if (ino_of_node(page) != ino) goto continue_unlock; - if (!PageDirty(page)) { + if (!PageDirty(page) && page != last_page) { /* someone wrote it for us */ goto continue_unlock; } f2fs_wait_on_page_writeback(page, NODE, true); BUG_ON(PageWriteback(page)); - if (!clear_page_dirty_for_io(page)) - goto continue_unlock; - set_fsync_mark(page, 1); - if (IS_INODE(page)) - set_dentry_mark(page, + if (!atomic || page == last_page) { + set_fsync_mark(page, 1); + if (IS_INODE(page)) + set_dentry_mark(page, need_dentry_mark(sbi, ino)); + /* may be written by other thread */ + if (!PageDirty(page)) + set_page_dirty(page); + } + + if (!clear_page_dirty_for_io(page)) + goto continue_unlock; ret = NODE_MAPPING(sbi)->a_ops->writepage(page, wbc); if (ret) { unlock_page(page); + f2fs_put_page(last_page, 0); + break; + } + if (page == last_page) { + f2fs_put_page(page, 0); + marked = true; break; } } pagevec_release(&pvec); cond_resched(); - if (ret) + if (ret || marked) break; } + if (!ret && atomic && !marked) { + f2fs_msg(sbi->sb, KERN_DEBUG, + "Retry to write fsync mark: ino=%u, idx=%lx", + ino, last_page->index); + lock_page(last_page); + set_page_dirty(last_page); + unlock_page(last_page); + goto retry; + } return ret ? -EIO: 0; } diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 2c87c12b6f1c..a646d3ba3b25 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -257,11 +257,8 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) } entry->blkaddr = blkaddr; - if (IS_INODE(page)) { - entry->last_inode = blkaddr; - if (is_dent_dnode(page)) - entry->last_dentry = blkaddr; - } + if (IS_INODE(page) && is_dent_dnode(page)) + entry->last_dentry = blkaddr; next: /* check next segment */ blkaddr = next_blkaddr_of_node(page); @@ -521,7 +518,7 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *head) * In this case, we can lose the latest inode(x). * So, call recover_inode for the inode update. */ - if (entry->last_inode == blkaddr) + if (IS_INODE(page)) recover_inode(entry->inode, page); if (entry->last_dentry == blkaddr) { err = recover_dentry(entry->inode, page); -- GitLab From 6bfc49197eba070b799ab4ca8755d3a9fd1700da Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 18 Apr 2016 17:07:44 -0400 Subject: [PATCH 4644/9938] f2fs: issue cache flush on direct IO Under direct IO path with O_(D)SYNC, it needs to set proper APPEND or UPDATE flags, so taht f2fs_sync_file can make its data safe. Acked-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e54489b970ae..38ce5d6f8583 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -673,6 +673,9 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, err = reserve_new_block(&dn); } else { err = __allocate_data_block(&dn); + if (!err) + set_inode_flag(F2FS_I(inode), + FI_APPEND_WRITE); } if (err) goto sync_out; @@ -1685,8 +1688,12 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter)); err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio); - if (err < 0 && iov_iter_rw(iter) == WRITE) - f2fs_write_failed(mapping, offset + count); + if (iov_iter_rw(iter) == WRITE) { + if (err > 0) + set_inode_flag(F2FS_I(inode), FI_UPDATE_WRITE); + else if (err < 0) + f2fs_write_failed(mapping, offset + count); + } trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err); -- GitLab From 2b899f34e1db9adef8716d07e872a800dfa60790 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Tue, 26 Apr 2016 08:27:46 +0200 Subject: [PATCH 4645/9938] i2c: imx: reduce load by using usleep_range instead of udelay Documentation/timers/timers-howto.txt recommends to use usleep_range on delays > 10usec. According to my test results with Neonode zForce touchscreen driver, usleep_range indeed reduces CPU load. Stats collected with "./perf record -a -g -F 1000 sleep 10" i2c-imx with udelay(50): 34.19% 0.00% irq/220-Neonode [kernel.kallsyms] [k] irq_thread ---irq_thread |--33.75%--irq_thread_fn | |--19.27%--0x7f08a878 | | i2c_master_recv | | i2c_transfer | | __i2c_transfer | | i2c_imx_xfer | | |--11.71%--i2c_imx_trx_complete | | |--5.70%--i2c_imx_start <<<<---------------- | | | |--5.38%--__timer_const_udelay | | | | __timer_delay | | | | --5.07%--read_current_timer i2c-imx with usleep_range(50,100) 29.08% 0.00% irq/220-Neonode [kernel.kallsyms] [k] irq_thread ---irq_thread |--28.89%--irq_thread_fn | |--17.21%--0x7f08a878 | | i2c_master_recv | | |--17.14%--i2c_transfer | | | __i2c_transfer | | | i2c_imx_xfer | | | |--14.29%--i2c_imx_trx_complete | | | |--1.42%--i2c_imx_start <<<<---------- | | | | |--0.71%--usleep_range | | | | |--0.53%--i2c_imx_bus_busy Signed-off-by: Oleksij Rempel Signed-off-by: Dirk Behme Reviewed-by: Vladimir Zapolskiy Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 1ca7ef2314f7..1844bc9f7cd5 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -525,7 +525,7 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR); /* Wait controller to be stable */ - udelay(50); + usleep_range(50, 150); /* Start I2C transaction */ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); -- GitLab From 0e7dd0c9c3cde901f79f04260aa706bbfdc0c67e Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 26 Apr 2016 23:14:30 +0200 Subject: [PATCH 4646/9938] pch_gbe: fix bogus trylock conversion Should have converted 'if (trylock)' to 'lock'. Fixes: a6086a893718db ("drivers: net: remove NETDEV_TX_LOCKED") Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 4475dcc687a2..ca4add749410 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2137,7 +2137,7 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; unsigned long flags; - spin_trylock_irqsave(&tx_ring->tx_lock, flags); + spin_lock_irqsave(&tx_ring->tx_lock, flags); if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) { netif_stop_queue(netdev); -- GitLab From dd485951e79a6dcbf18ba1612ad91d45e4cfa9a7 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 26 Apr 2016 13:22:33 -0400 Subject: [PATCH 4647/9938] i2c: nforce2: Use IS_ENABLED() instead of checking for built-in or module The IS_ENABLED() macro checks if a Kconfig symbol has been enabled either built-in or as a module, use that macro instead of open coding the same. Signed-off-by: Javier Martinez Canillas Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nforce2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 70b3c9158509..42fcc9458432 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -127,7 +127,7 @@ static struct pci_driver nforce2_driver; /* For multiplexing support, we need a global reference to the 1st SMBus channel */ -#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE +#if IS_ENABLED(CONFIG_I2C_NFORCE2_S4985) struct i2c_adapter *nforce2_smbus; EXPORT_SYMBOL_GPL(nforce2_smbus); -- GitLab From 5ad9a7fde07a95b326da9e650b4f0a41b85e47b5 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Mon, 25 Apr 2016 15:34:58 -0600 Subject: [PATCH 4648/9938] acpi/nfit: Update nfit driver to comply with ACPI 6.1 ACPI 6.1, Table 5-133, updates NVDIMM Control Region Structure as follows. - Valid Fields, Manufacturing Location, and Manufacturing Date are added from reserved range. No change in the structure size. - IDs (SPD values) are stored as arrays of bytes (i.e. big-endian format). The spec clarifies that they need to be represented as arrays of bytes as well. This patch makes the following changes to support this update. - Change the NFIT driver to show SPD ID values in big-endian format. - Change sprintf format to use "0x" instead of "#" since "%#02x" does not prepend '0'. link: http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf Signed-off-by: Toshi Kani Cc: Rafael J. Wysocki Cc: Dan Williams Cc: Robert Moore Cc: Robert Elliott Signed-off-by: Dan Williams --- drivers/acpi/nfit.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index d0f35e63640b..5dc243c65dee 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c @@ -816,7 +816,7 @@ static ssize_t vendor_show(struct device *dev, { struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); - return sprintf(buf, "%#x\n", dcr->vendor_id); + return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->vendor_id)); } static DEVICE_ATTR_RO(vendor); @@ -825,7 +825,7 @@ static ssize_t rev_id_show(struct device *dev, { struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); - return sprintf(buf, "%#x\n", dcr->revision_id); + return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->revision_id)); } static DEVICE_ATTR_RO(rev_id); @@ -834,7 +834,7 @@ static ssize_t device_show(struct device *dev, { struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); - return sprintf(buf, "%#x\n", dcr->device_id); + return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->device_id)); } static DEVICE_ATTR_RO(device); @@ -843,7 +843,7 @@ static ssize_t format_show(struct device *dev, { struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); - return sprintf(buf, "%#x\n", dcr->code); + return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->code)); } static DEVICE_ATTR_RO(format); @@ -852,7 +852,7 @@ static ssize_t serial_show(struct device *dev, { struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); - return sprintf(buf, "%#x\n", dcr->serial_number); + return sprintf(buf, "0x%08x\n", be32_to_cpu(dcr->serial_number)); } static DEVICE_ATTR_RO(serial); -- GitLab From 38a879ba9c0a6849fe26c36e325f754a89848da7 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Mon, 25 Apr 2016 15:34:59 -0600 Subject: [PATCH 4649/9938] acpi/nfit: Add sysfs "id" for NVDIMM ID ACPI 6.1, section 5.2.25.9, defines an identifier for an NVDIMM. Change the NFIT driver to add a new sysfs file "id" under nfit directory. Signed-off-by: Toshi Kani Cc: Rafael J. Wysocki Cc: Dan Williams Cc: Robert Moore Cc: Robert Elliott Signed-off-by: Dan Williams --- drivers/acpi/nfit.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index 5dc243c65dee..5a7199db2e06 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c @@ -870,6 +870,24 @@ static ssize_t flags_show(struct device *dev, } static DEVICE_ATTR_RO(flags); +static ssize_t id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); + + if (dcr->valid_fields & ACPI_NFIT_CONTROL_MFG_INFO_VALID) + return sprintf(buf, "%04x-%02x-%04x-%08x\n", + be16_to_cpu(dcr->vendor_id), + dcr->manufacturing_location, + be16_to_cpu(dcr->manufacturing_date), + be32_to_cpu(dcr->serial_number)); + else + return sprintf(buf, "%04x-%08x\n", + be16_to_cpu(dcr->vendor_id), + be32_to_cpu(dcr->serial_number)); +} +static DEVICE_ATTR_RO(id); + static struct attribute *acpi_nfit_dimm_attributes[] = { &dev_attr_handle.attr, &dev_attr_phys_id.attr, @@ -879,6 +897,7 @@ static struct attribute *acpi_nfit_dimm_attributes[] = { &dev_attr_serial.attr, &dev_attr_rev_id.attr, &dev_attr_flags.attr, + &dev_attr_id.attr, NULL, }; -- GitLab From dd80b54b18db3d76a43558daaa6ea3aa67f5aacd Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 20 Apr 2016 15:39:11 +0200 Subject: [PATCH 4650/9938] USB: LTM also for USB 3.1 LTM is also defined for SS+. The correct test is to check for anything slower than SS not exactly SS. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/usb.h b/include/linux/usb.h index 6a9a0c28415d..29aba76017ee 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -720,7 +720,7 @@ extern void usb_enable_ltm(struct usb_device *udev); static inline bool usb_device_supports_ltm(struct usb_device *udev) { - if (udev->speed != USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap) + if (udev->speed < USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap) return false; return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT; } -- GitLab From fca504f6054f2a62d966afde23a0cfbf9e3dc32f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 20 Apr 2016 15:39:12 +0200 Subject: [PATCH 4651/9938] USB: correct intervals for SS+ SS+ also expresses intervals in units of 125ms. Testing must be for SS or faster, not SS exactly. Signed-off-by: Oliver neukum Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/usb.h b/include/linux/usb.h index 29aba76017ee..7824f4557d50 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1569,7 +1569,7 @@ static inline void usb_fill_bulk_urb(struct urb *urb, * Initializes a interrupt urb with the proper information needed to submit * it to a device. * - * Note that High Speed and SuperSpeed interrupt endpoints use a logarithmic + * Note that High Speed and SuperSpeed(+) interrupt endpoints use a logarithmic * encoding of the endpoint interval, and express polling intervals in * microframes (eight per millisecond) rather than in frames (one per * millisecond). @@ -1595,7 +1595,7 @@ static inline void usb_fill_int_urb(struct urb *urb, urb->complete = complete_fn; urb->context = context; - if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) { + if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) { /* make sure interval is within allowed range */ interval = clamp(interval, 1, 16); -- GitLab From d64aab0c6fdc67113f2332a295d244b53bf694d6 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 20 Apr 2016 16:28:09 +0200 Subject: [PATCH 4652/9938] hub: admit devices are SS+ If a port can do 10 Gb/s the kernel should say so. The corresponding check needs to be added. Signed-off.by: Oliver Neukum > Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 38cc4bae0a82..c2270d8fac12 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -104,6 +104,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev); static inline char *portspeed(struct usb_hub *hub, int portstatus) { + if (hub_is_superspeedplus(hub->hdev)) + return "10.0 Gb/s"; if (hub_is_superspeed(hub->hdev)) return "5.0 Gb/s"; if (portstatus & USB_PORT_STAT_HIGH_SPEED) -- GitLab From 779b457f66e10de3471479373463b27fd308dc85 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 18 Apr 2016 13:09:09 +0300 Subject: [PATCH 4653/9938] usb: storage: scsiglue: further describe our 240 sector limit Just so we have some sort of documentation as to why we limit our Mass Storage transfers to 240 sectors, let's update the comment to make clearer that devices were found that would choke with larger transfers. While at that, also make sure to clarify that other operating systems have similar, albeit different, limits on mass storage transfers. Signed-off-by: Felipe Balbi Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 90901861bfc0..9da1fb3d0ff4 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -565,7 +565,24 @@ static const struct scsi_host_template usb_stor_host_template = { /* lots of sg segments can be handled */ .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, - /* limit the total size of a transfer to 120 KB */ + + /* + * Limit the total size of a transfer to 120 KB. + * + * Some devices are known to choke with anything larger. It seems like + * the problem stems from the fact that original IDE controllers had + * only an 8-bit register to hold the number of sectors in one transfer + * and even those couldn't handle a full 256 sectors. + * + * Because we want to make sure we interoperate with as many devices as + * possible, we will maintain a 240 sector transfer size limit for USB + * Mass Storage devices. + * + * Tests show that other operating have similar limits with Microsoft + * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3 + * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2 + * and 2048 for USB3 devices. + */ .max_sectors = 240, /* merge commands... this seems to help performance, but -- GitLab From 5b91dfe187bbe3a8116432016375f39fff91a237 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 18 Apr 2016 13:09:10 +0300 Subject: [PATCH 4654/9938] usb: storage: scsiglue: limit USB3 devices to 2048 sectors USB3 devices, because they are much newer, have much less chance of having issues with larger transfers. We still keep a limit because anything above 2048 sectors really rendered negligible speed improvements, so we will simply ignore that. Transferring 1MiB should already give us pretty good performance. Signed-off-by: Felipe Balbi Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 9da1fb3d0ff4..88920142e375 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -133,6 +133,11 @@ static int slave_configure(struct scsi_device *sdev) * let the queue segment size sort out the real limit. */ blk_queue_max_hw_sectors(sdev->request_queue, 0x7FFFFF); + } else if (us->pusb_dev->speed >= USB_SPEED_SUPER) { + /* USB3 devices will be limited to 2048 sectors. This gives us + * better throughput on most devices. + */ + blk_queue_max_hw_sectors(sdev->request_queue, 2048); } /* Some USB host controllers can't do DMA; they have to use PIO. -- GitLab From f0183a338e4f90e59a4b4daa10cba0fae8e3fca7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 18 Apr 2016 13:09:11 +0300 Subject: [PATCH 4655/9938] usb: storage: fix multi-line comment style No functional changes here, just making sure our storage driver uses a consistent multi-line comment style. Signed-off-by: Felipe Balbi Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/alauda.c | 22 +- drivers/usb/storage/cypress_atacb.c | 34 +-- drivers/usb/storage/datafab.c | 22 +- drivers/usb/storage/debug.c | 3 +- drivers/usb/storage/debug.h | 3 +- drivers/usb/storage/ene_ub6250.c | 25 +- drivers/usb/storage/freecom.c | 75 ++++-- drivers/usb/storage/initializers.c | 15 +- drivers/usb/storage/initializers.h | 15 +- drivers/usb/storage/isd200.c | 51 ++-- drivers/usb/storage/jumpshot.c | 22 +- drivers/usb/storage/karma.c | 3 +- drivers/usb/storage/option_ms.c | 6 +- drivers/usb/storage/protocol.c | 12 +- drivers/usb/storage/protocol.h | 3 +- drivers/usb/storage/realtek_cr.c | 12 +- drivers/usb/storage/scsiglue.c | 147 +++++++---- drivers/usb/storage/scsiglue.h | 3 +- drivers/usb/storage/sddr09.c | 82 +++--- drivers/usb/storage/sddr55.c | 45 ++-- drivers/usb/storage/shuttle_usbat.c | 16 +- drivers/usb/storage/sierra_ms.c | 3 +- drivers/usb/storage/transport.c | 165 +++++++----- drivers/usb/storage/transport.h | 3 +- drivers/usb/storage/uas.c | 3 +- drivers/usb/storage/unusual_alauda.h | 3 +- drivers/usb/storage/unusual_cypress.h | 3 +- drivers/usb/storage/unusual_datafab.h | 6 +- drivers/usb/storage/unusual_devs.h | 334 ++++++++++++++++--------- drivers/usb/storage/unusual_freecom.h | 3 +- drivers/usb/storage/unusual_isd200.h | 3 +- drivers/usb/storage/unusual_jumpshot.h | 3 +- drivers/usb/storage/unusual_karma.h | 3 +- drivers/usb/storage/unusual_onetouch.h | 6 +- drivers/usb/storage/unusual_realtek.h | 3 +- drivers/usb/storage/unusual_sddr09.h | 3 +- drivers/usb/storage/unusual_sddr55.h | 3 +- drivers/usb/storage/unusual_uas.h | 3 +- drivers/usb/storage/unusual_usbat.h | 3 +- drivers/usb/storage/usb.c | 98 +++++--- drivers/usb/storage/usb.h | 14 +- drivers/usb/storage/usual-tables.c | 3 +- 42 files changed, 829 insertions(+), 455 deletions(-) diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 171fa7d793bc..1d8b03c81030 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -829,8 +829,10 @@ static int alauda_write_lba(struct us_data *us, u16 lba, pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset]; if (pba == 1) { - /* Maybe it is impossible to write to PBA 1. - Fake success, but don't do anything. */ + /* + * Maybe it is impossible to write to PBA 1. + * Fake success, but don't do anything. + */ printk(KERN_WARNING "alauda_write_lba: avoid writing to pba 1\n"); return USB_STOR_TRANSPORT_GOOD; @@ -977,10 +979,12 @@ static int alauda_read_data(struct us_data *us, unsigned long address, usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n", pages, lba, page); - /* This is not really an error. It just means - that the block has never been written. - Instead of returning USB_STOR_TRANSPORT_ERROR - it is better to return all zero data. */ + /* + * This is not really an error. It just means + * that the block has never been written. + * Instead of returning USB_STOR_TRANSPORT_ERROR + * it is better to return all zero data. + */ memset(buffer, 0, len); } else { @@ -1222,8 +1226,10 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) } if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { - /* sure. whatever. not like we can stop the user from popping - the media out of the device (no locking doors, etc) */ + /* + * sure. whatever. not like we can stop the user from popping + * the media out of the device (no locking doors, etc) + */ return USB_STOR_TRANSPORT_GOOD; } diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index c80d3dec9a34..5e4af44d7d9f 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -110,13 +110,17 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) /* first build the ATACB command */ srb->cmd_len = 16; - srb->cmnd[0] = 0x24; /* bVSCBSignature : vendor-specific command - this value can change, but most(all ?) manufacturers - keep the cypress default : 0x24 */ + srb->cmnd[0] = 0x24; /* + * bVSCBSignature : vendor-specific command + * this value can change, but most(all ?) manufacturers + * keep the cypress default : 0x24 + */ srb->cmnd[1] = 0x24; /* bVSCBSubCommand : 0x24 for ATACB */ - srb->cmnd[3] = 0xff - 1; /* features, sector count, lba low, lba med - lba high, device, command are valid */ + srb->cmnd[3] = 0xff - 1; /* + * features, sector count, lba low, lba med + * lba high, device, command are valid + */ srb->cmnd[4] = 1; /* TransferBlockCount : 512 */ if (save_cmnd[0] == ATA_16) { @@ -155,8 +159,7 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) usb_stor_transparent_scsi_command(srb, us); - /* if the device doesn't support ATACB - */ + /* if the device doesn't support ATACB */ if (srb->result == SAM_STAT_CHECK_CONDITION && memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB)) == 0) { @@ -164,7 +167,8 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) goto end; } - /* if ck_cond flags is set, and there wasn't critical error, + /* + * if ck_cond flags is set, and there wasn't critical error, * build the special sense */ if ((srb->result != (DID_ERROR << 16) && @@ -176,11 +180,11 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) unsigned char *desc = sb + 8; int tmp_result; - /* build the command for - * reading the ATA registers */ + /* build the command for reading the ATA registers */ scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs)); - /* we use the same command as before, but we set + /* + * we use the same command as before, but we set * the read taskfile bit, for not executing atacb command, * but reading register selected in srb->cmnd[4] */ @@ -204,10 +208,11 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) sb[2] = 0; /* ATA PASS THROUGH INFORMATION AVAILABLE */ sb[3] = 0x1D; - /* XXX we should generate sk, asc, ascq from status and error + /* + * XXX we should generate sk, asc, ascq from status and error * regs * (see 11.1 Error translation ATA device error to SCSI error - * map, and ata_to_sense_error from libata.) + * map, and ata_to_sense_error from libata.) */ /* Sense data is current and format is descriptor. */ @@ -258,7 +263,8 @@ static int cypress_probe(struct usb_interface *intf, if (result) return result; - /* Among CY7C68300 chips, the A revision does not support Cypress ATACB + /* + * Among CY7C68300 chips, the A revision does not support Cypress ATACB * Filter out this revision from EEPROM default descriptor values */ device = interface_to_usbdev(intf); diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index aa4f51944a4a..723197af6ec5 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -1,4 +1,5 @@ -/* Driver for Datafab USB Compact Flash reader +/* + * Driver for Datafab USB Compact Flash reader * * datafab driver v0.1: * @@ -693,18 +694,23 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us) } if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { - // sure. whatever. not like we can stop the user from - // popping the media out of the device (no locking doors, etc) - // + /* + * sure. whatever. not like we can stop the user from + * popping the media out of the device (no locking doors, etc) + */ return USB_STOR_TRANSPORT_GOOD; } if (srb->cmnd[0] == START_STOP) { - /* this is used by sd.c'check_scsidisk_media_change to detect - media change */ + /* + * this is used by sd.c'check_scsidisk_media_change to detect + * media change + */ usb_stor_dbg(us, "START_STOP\n"); - /* the first datafab_id_device after a media change returns - an error (determined experimentally) */ + /* + * the first datafab_id_device after a media change returns + * an error (determined experimentally) + */ rc = datafab_id_device(us, info); if (rc == USB_STOR_TRANSPORT_GOOD) { info->sense_key = NO_SENSE; diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c index 5a12c03138f8..8d20804a59e6 100644 --- a/drivers/usb/storage/debug.c +++ b/drivers/usb/storage/debug.c @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * Debugging Functions Source Code File * * Current development and maintenance by: diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h index 6b365ce4e610..8ab73299b650 100644 --- a/drivers/usb/storage/debug.h +++ b/drivers/usb/storage/debug.h @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * Debugging Functions Header File * * Current development and maintenance by: diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index d3a17c65a702..02bdaa912164 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -560,8 +560,10 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) /* check bulk status */ residue = le32_to_cpu(bcs->Residue); - /* try to compute the actual residue, based on how much data - * was really transferred and what the device tells us */ + /* + * try to compute the actual residue, based on how much data + * was really transferred and what the device tells us + */ if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { residue = min(residue, transfer_length); if (us->srb != NULL) @@ -862,9 +864,6 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, u8 ExtBuf[4]; u32 bn = PhyBlockAddr * 0x20 + PageNum; - /* printk(KERN_INFO "MS --- MS_ReaderReadPage, - PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */ - result = ene_load_bincode(us, MS_RW_PATTERN); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1141,8 +1140,6 @@ static int ms_read_copyblock(struct us_data *us, u16 oldphy, u16 newphy, struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; - /* printk(KERN_INFO "MS_ReaderCopyBlock --- PhyBlockAddr = %x, - PageNum = %x\n", PhyBlockAddr, PageNum); */ result = ene_load_bincode(us, MS_RW_PATTERN); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1176,8 +1173,6 @@ static int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr) int result; u32 bn = PhyBlockAddr; - /* printk(KERN_INFO "MS --- ms_read_eraseblock, - PhyBlockAddr = %x\n", PhyBlockAddr); */ result = ene_load_bincode(us, MS_RW_PATTERN); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1255,8 +1250,6 @@ static int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr, struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; - /* printk("MS --- MS_LibOverwriteExtra, - PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */ result = ene_load_bincode(us, MS_RW_PATTERN); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1342,7 +1335,6 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, int result; u8 ExtBuf[4]; - /* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum); */ memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4; @@ -1541,9 +1533,6 @@ static int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock, struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; - /* printk("MS_LibReadExtraBlock --- PhyBlock = %x, - PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen); */ - /* Read Extra Data */ memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -2390,8 +2379,10 @@ static int ene_ub6250_reset_resume(struct usb_interface *iface) /* Report the reset to the SCSI core */ usb_stor_reset_resume(iface); - /* FIXME: Notify the subdrivers that they need to reinitialize - * the device */ + /* + * FIXME: Notify the subdrivers that they need to reinitialize + * the device + */ info->Power_IsResum = true; /*info->SD_Status.Ready = 0; */ info->SD_Status = *(struct SD_STATUS *)&tmp; diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 3f2b08966b9d..c0a5d954414b 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -1,4 +1,5 @@ -/* Driver for Freecom USB/IDE adaptor +/* + * Driver for Freecom USB/IDE adaptor * * Freecom v0.1: * @@ -84,25 +85,33 @@ struct freecom_status { u8 Pad[60]; }; -/* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide - * register. */ +/* + * Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide + * register. + */ #define FCM_INT_STATUS 0x02 /* INDEX_STAT */ #define FCM_STATUS_BUSY 0x80 -/* These are the packet types. The low bit indicates that this command - * should wait for an interrupt. */ +/* + * These are the packet types. The low bit indicates that this command + * should wait for an interrupt. + */ #define FCM_PACKET_ATAPI 0x21 #define FCM_PACKET_STATUS 0x20 -/* Receive data from the IDE interface. The ATAPI packet has already - * waited, so the data should be immediately available. */ +/* + * Receive data from the IDE interface. The ATAPI packet has already + * waited, so the data should be immediately available. + */ #define FCM_PACKET_INPUT 0x81 /* Send data to the IDE interface. */ #define FCM_PACKET_OUTPUT 0x01 -/* Write a value to an ide register. Or the ide register to write after - * munging the address a bit. */ +/* + * Write a value to an ide register. Or the ide register to write after + * munging the address a bit. + */ #define FCM_PACKET_IDE_WRITE 0x40 #define FCM_PACKET_IDE_READ 0xC0 @@ -251,16 +260,20 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); - /* The Freecom device will only fail if there is something wrong in + /* + * The Freecom device will only fail if there is something wrong in * USB land. It returns the status in its own registers, which - * come back in the bulk pipe. */ + * come back in the bulk pipe. + */ if (result != USB_STOR_XFER_GOOD) { usb_stor_dbg(us, "freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } - /* There are times we can optimize out this status read, but it - * doesn't hurt us to always do it now. */ + /* + * There are times we can optimize out this status read, but it + * doesn't hurt us to always do it now. + */ result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_STATUS_PACKET_LENGTH, &partial); usb_stor_dbg(us, "foo Status result %d %u\n", result, partial); @@ -269,7 +282,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUG(pdump(us, (void *)fst, partial)); - /* The firmware will time-out commands after 20 seconds. Some commands + /* + * The firmware will time-out commands after 20 seconds. Some commands * can legitimately take longer than this, so we use a different * command that only waits for the interrupt and then sends status, * without having to send a new ATAPI command to the device. @@ -291,7 +305,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); - /* The Freecom device will only fail if there is something + /* + * The Freecom device will only fail if there is something * wrong in USB land. It returns the status in its own * registers, which come back in the bulk pipe. */ @@ -318,9 +333,11 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } - /* The device might not have as much data available as we + /* + * The device might not have as much data available as we * requested. If you ask for more than the device has, this reads - * and such will hang. */ + * and such will hang. + */ usb_stor_dbg(us, "Device indicates that it has %d bytes available\n", le16_to_cpu(fst->Count)); usb_stor_dbg(us, "SCSI requested %d\n", scsi_bufflen(srb)); @@ -344,16 +361,20 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) length); } - /* What we do now depends on what direction the data is supposed to - * move in. */ + /* + * What we do now depends on what direction the data is supposed to + * move in. + */ switch (us->srb->sc_data_direction) { case DMA_FROM_DEVICE: /* catch bogus "read 0 length" case */ if (!length) break; - /* Make sure that the status indicates that the device - * wants data as well. */ + /* + * Make sure that the status indicates that the device + * wants data as well. + */ if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) { usb_stor_dbg(us, "SCSI wants data, drive doesn't have any\n"); return USB_STOR_TRANSPORT_FAILED; @@ -384,8 +405,10 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) /* catch bogus "write 0 length" case */ if (!length) break; - /* Make sure the status indicates that the device wants to - * send us data. */ + /* + * Make sure the status indicates that the device wants to + * send us data. + */ /* !!IMPLEMENT!! */ result = freecom_writedata (srb, us, ipipe, opipe, length); if (result != USB_STOR_TRANSPORT_GOOD) @@ -431,7 +454,8 @@ static int init_freecom(struct us_data *us) int result; char *buffer = us->iobuf; - /* The DMA-mapped I/O buffer is 64 bytes long, just right for + /* + * The DMA-mapped I/O buffer is 64 bytes long, just right for * all our packets. No need to allocate any extra buffer space. */ @@ -440,7 +464,8 @@ static int init_freecom(struct us_data *us) buffer[32] = '\0'; usb_stor_dbg(us, "String returned from FC init is: %s\n", buffer); - /* Special thanks to the people at Freecom for providing me with + /* + * Special thanks to the people at Freecom for providing me with * this "magic sequence", which they use in their Windows and MacOS * drivers to make sure that all the attached perhiperals are * properly reset. diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 31fa2e92065b..d9d8c17e05d1 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -1,4 +1,5 @@ -/* Special Initializers for certain USB Mass Storage devices +/* + * Special Initializers for certain USB Mass Storage devices * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -42,8 +43,10 @@ #include "debug.h" #include "transport.h" -/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target - * mode */ +/* + * This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target + * mode + */ int usb_stor_euscsi_init(struct us_data *us) { int result; @@ -57,8 +60,10 @@ int usb_stor_euscsi_init(struct us_data *us) return 0; } -/* This function is required to activate all four slots on the UCR-61S2B - * flash reader */ +/* + * This function is required to activate all four slots on the UCR-61S2B + * flash reader + */ int usb_stor_ucr61s2b_init(struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap*) us->iobuf; diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 529327fbb06b..039abf4d1cb7 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -1,4 +1,5 @@ -/* Header file for Special Initializers for certain USB Mass Storage devices +/* + * Header file for Special Initializers for certain USB Mass Storage devices * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -38,12 +39,16 @@ #include "usb.h" #include "transport.h" -/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target - * mode */ +/* + * This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target + * mode + */ int usb_stor_euscsi_init(struct us_data *us); -/* This function is required to activate all four slots on the UCR-61S2B - * flash reader */ +/* + * This function is required to activate all four slots on the UCR-61S2B + * flash reader + */ int usb_stor_ucr61s2b_init(struct us_data *us); /* This places the HUAWEI E220 devices in multi-port mode */ diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 39afd7045c43..fba4005dd737 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1,4 +1,5 @@ -/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC +/* + * Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC * * Current development and maintenance: * (C) 2001-2002 Björn Stenberg (bjorn@haxx.se) @@ -628,7 +629,8 @@ static void isd200_invoke_transport( struct us_data *us, srb->cmd_len = sizeof(ataCdb->generic); transferStatus = usb_stor_Bulk_transport(srb, us); - /* if the command gets aborted by the higher layers, we need to + /* + * if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { @@ -695,15 +697,18 @@ static void isd200_invoke_transport( struct us_data *us, } } - /* Regardless of auto-sense, if we _know_ we have an error + /* + * Regardless of auto-sense, if we _know_ we have an error * condition, show that in the result code */ if (transferStatus == USB_STOR_TRANSPORT_FAILED) srb->result = SAM_STAT_CHECK_CONDITION; return; - /* abort processing: the bulk-only transport requires a reset - * following an abort */ + /* + * abort processing: the bulk-only transport requires a reset + * following an abort + */ Handle_Abort: srb->result = DID_ABORT << 16; @@ -965,20 +970,22 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, info->DeviceHead = master_slave; break; } - /* check Cylinder High/Low to - determine if it is an ATAPI device - */ + /* + * check Cylinder High/Low to + * determine if it is an ATAPI device + */ else if (regs[ATA_REG_HCYL_OFFSET] == 0xEB && regs[ATA_REG_LCYL_OFFSET] == 0x14) { - /* It seems that the RICOH - MP6200A CD/RW drive will - report itself okay as a - slave when it is really a - master. So this check again - as a master device just to - make sure it doesn't report - itself okay as a master also - */ + /* + * It seems that the RICOH + * MP6200A CD/RW drive will + * report itself okay as a + * slave when it is really a + * master. So this check again + * as a master device just to + * make sure it doesn't report + * itself okay as a master also + */ if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) && !recheckAsMaster) { usb_stor_dbg(us, " Identified ATAPI device as slave. Rechecking again as master\n"); @@ -1176,9 +1183,11 @@ static int isd200_get_inquiry_data( struct us_data *us ) if (id[ATA_ID_COMMAND_SET_2] & COMMANDSET_MEDIA_STATUS) { usb_stor_dbg(us, " Device supports Media Status Notification\n"); - /* Indicate that it is enabled, even though it is not - * This allows the lock/unlock of the media to work - * correctly. + /* + * Indicate that it is enabled, even + * though it is not. + * This allows the lock/unlock of the + * media to work correctly. */ info->DeviceFlags |= DF_MEDIA_STATUS_ENABLED; } @@ -1197,7 +1206,7 @@ static int isd200_get_inquiry_data( struct us_data *us ) usb_stor_dbg(us, "Protocol changed to: %s\n", us->protocol_name); - /* Free driver structure */ + /* Free driver structure */ us->extra_destructor(info); kfree(info); us->extra = NULL; diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index ee613e258db0..011e5270690a 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -1,4 +1,5 @@ -/* Driver for Lexar "Jumpshot" Compact Flash reader +/* + * Driver for Lexar "Jumpshot" Compact Flash reader * * jumpshot driver v0.1: * @@ -618,18 +619,23 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us) } if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { - // sure. whatever. not like we can stop the user from popping - // the media out of the device (no locking doors, etc) - // + /* + * sure. whatever. not like we can stop the user from popping + * the media out of the device (no locking doors, etc) + */ return USB_STOR_TRANSPORT_GOOD; } if (srb->cmnd[0] == START_STOP) { - /* this is used by sd.c'check_scsidisk_media_change to detect - media change */ + /* + * this is used by sd.c'check_scsidisk_media_change to detect + * media change + */ usb_stor_dbg(us, "START_STOP\n"); - /* the first jumpshot_id_device after a media change returns - an error (determined experimentally) */ + /* + * the first jumpshot_id_device after a media change returns + * an error (determined experimentally) + */ rc = jumpshot_id_device(us, info); if (rc == USB_STOR_TRANSPORT_GOOD) { info->sense_key = NO_SENSE; diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index ae201e69475c..f9d407f0b508 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -1,4 +1,5 @@ -/* Driver for Rio Karma +/* + * Driver for Rio Karma * * (c) 2006 Bob Copeland * (c) 2006 Keith Bennett diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c index b2b35b1d7de8..57282f12317b 100644 --- a/drivers/usb/storage/option_ms.c +++ b/drivers/usb/storage/option_ms.c @@ -65,7 +65,8 @@ static int option_rezero(struct us_data *us) goto out; } - /* Some of the devices need to be asked for a response, but we don't + /* + * Some of the devices need to be asked for a response, but we don't * care what that response is. */ usb_stor_bulk_transfer_buf(us, @@ -140,7 +141,8 @@ int option_ms_init(struct us_data *us) usb_stor_dbg(us, "Option MS: %s\n", "option_ms_init called"); - /* Additional test for vendor information via INQUIRY, + /* + * Additional test for vendor information via INQUIRY, * because some vendor/product IDs are ambiguous */ result = option_inquiry(us); diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 12e3c2fac642..74c38870a17e 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -75,7 +76,8 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us) { - /* fix some commands -- this is a form of mode translation + /* + * fix some commands -- this is a form of mode translation * UFI devices only accept 12 byte long commands * * NOTE: This only works because a scsi_cmnd struct field contains @@ -127,7 +129,8 @@ EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command); * Scatter-gather transfer buffer access routines ***********************************************************************/ -/* Copy a buffer of length buflen to/from the srb's transfer buffer. +/* + * Copy a buffer of length buflen to/from the srb's transfer buffer. * Update the **sgptr and *offset variables so that the next copy will * pick up from where this one left off. */ @@ -175,7 +178,8 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, } EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf); -/* Store the contents of buffer into srb's transfer buffer and set the +/* + * Store the contents of buffer into srb's transfer buffer and set the * SCSI residue. */ void usb_stor_set_xfer_buf(unsigned char *buffer, diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h index ffc3e2af0156..a55666880b7b 100644 --- a/drivers/usb/storage/protocol.h +++ b/drivers/usb/storage/protocol.h @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * Protocol Functions Header File * * Current development and maintenance by: diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 20433563a601..4176d1af9bf2 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -1,4 +1,5 @@ -/* Driver for Realtek RTS51xx USB card reader +/* + * Driver for Realtek RTS51xx USB card reader * * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. * @@ -267,8 +268,10 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, if (bcs->Tag != us->tag) return USB_STOR_TRANSPORT_ERROR; - /* try to compute the actual residue, based on how much data - * was really transferred and what the device tells us */ + /* + * try to compute the actual residue, based on how much data + * was really transferred and what the device tells us + */ if (residue) residue = residue < buf_len ? residue : buf_len; @@ -286,7 +289,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, return USB_STOR_TRANSPORT_FAILED; case US_BULK_STAT_PHASE: - /* phase error -- note that a transport reset will be + /* + * phase error -- note that a transport reset will be * invoked by the invoke_transport() function */ return USB_STOR_TRANSPORT_ERROR; diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 88920142e375..7adb6c9c7018 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * SCSI layer glue code * * Current development and maintenance by: @@ -58,7 +59,8 @@ #include "transport.h" #include "protocol.h" -/* Vendor IDs for companies that seem to include the READ CAPACITY bug +/* + * Vendor IDs for companies that seem to include the READ CAPACITY bug * in all their devices */ #define VENDOR_ID_NOKIA 0x0421 @@ -87,7 +89,8 @@ static int slave_alloc (struct scsi_device *sdev) */ sdev->inquiry_len = 36; - /* USB has unusual DMA-alignment requirements: Although the + /* + * USB has unusual DMA-alignment requirements: Although the * starting address of each scatter-gather element doesn't matter, * the length of each element except the last must be divisible * by the Bulk maxpacket value. There's currently no way to @@ -115,7 +118,8 @@ static int slave_configure(struct scsi_device *sdev) { struct us_data *us = host_to_us(sdev->host); - /* Many devices have trouble transferring more than 32KB at a time, + /* + * Many devices have trouble transferring more than 32KB at a time, * while others have trouble with more than 64K. At this time we * are limiting both to 32K (64 sectores). */ @@ -128,19 +132,22 @@ static int slave_configure(struct scsi_device *sdev) blk_queue_max_hw_sectors(sdev->request_queue, max_sectors); } else if (sdev->type == TYPE_TAPE) { - /* Tapes need much higher max_sector limits, so just + /* + * Tapes need much higher max_sector limits, so just * raise it to the maximum possible (4 GB / 512) and * let the queue segment size sort out the real limit. */ blk_queue_max_hw_sectors(sdev->request_queue, 0x7FFFFF); } else if (us->pusb_dev->speed >= USB_SPEED_SUPER) { - /* USB3 devices will be limited to 2048 sectors. This gives us + /* + * USB3 devices will be limited to 2048 sectors. This gives us * better throughput on most devices. */ blk_queue_max_hw_sectors(sdev->request_queue, 2048); } - /* Some USB host controllers can't do DMA; they have to use PIO. + /* + * Some USB host controllers can't do DMA; they have to use PIO. * They indicate this by setting their dma_mask to NULL. For * such controllers we need to make sure the block layer sets * up bounce buffers in addressable memory. @@ -148,17 +155,21 @@ static int slave_configure(struct scsi_device *sdev) if (!us->pusb_dev->bus->controller->dma_mask) blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); - /* We can't put these settings in slave_alloc() because that gets + /* + * We can't put these settings in slave_alloc() because that gets * called before the device type is known. Consequently these - * settings can't be overridden via the scsi devinfo mechanism. */ + * settings can't be overridden via the scsi devinfo mechanism. + */ if (sdev->type == TYPE_DISK) { - /* Some vendors seem to put the READ CAPACITY bug into + /* + * Some vendors seem to put the READ CAPACITY bug into * all their devices -- primarily makers of cell phones * and digital cameras. Since these devices always use * flash media and can be expected to have an even number * of sectors, we will always enable the CAPACITY_HEURISTICS - * flag unless told otherwise. */ + * flag unless told otherwise. + */ switch (le16_to_cpu(us->pusb_dev->descriptor.idVendor)) { case VENDOR_ID_NOKIA: case VENDOR_ID_NIKON: @@ -170,28 +181,36 @@ static int slave_configure(struct scsi_device *sdev) break; } - /* Disk-type devices use MODE SENSE(6) if the protocol + /* + * Disk-type devices use MODE SENSE(6) if the protocol * (SubClass) is Transparent SCSI, otherwise they use - * MODE SENSE(10). */ + * MODE SENSE(10). + */ if (us->subclass != USB_SC_SCSI && us->subclass != USB_SC_CYP_ATACB) sdev->use_10_for_ms = 1; - /* Many disks only accept MODE SENSE transfer lengths of - * 192 bytes (that's what Windows uses). */ + /* + *Many disks only accept MODE SENSE transfer lengths of + * 192 bytes (that's what Windows uses). + */ sdev->use_192_bytes_for_3f = 1; - /* Some devices don't like MODE SENSE with page=0x3f, + /* + * Some devices don't like MODE SENSE with page=0x3f, * which is the command used for checking if a device * is write-protected. Now that we tell the sd driver * to do a 192-byte transfer with this command the * majority of devices work fine, but a few still can't * handle it. The sd driver will simply assume those - * devices are write-enabled. */ + * devices are write-enabled. + */ if (us->fflags & US_FL_NO_WP_DETECT) sdev->skip_ms_page_3f = 1; - /* A number of devices have problems with MODE SENSE for - * page x08, so we will skip it. */ + /* + * A number of devices have problems with MODE SENSE for + * page x08, so we will skip it. + */ sdev->skip_ms_page_8 = 1; /* Some devices don't handle VPD pages correctly */ @@ -203,15 +222,19 @@ static int slave_configure(struct scsi_device *sdev) /* Do not attempt to use WRITE SAME */ sdev->no_write_same = 1; - /* Some disks return the total number of blocks in response + /* + * Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. - * If this device makes that mistake, tell the sd driver. */ + * If this device makes that mistake, tell the sd driver. + */ if (us->fflags & US_FL_FIX_CAPACITY) sdev->fix_capacity = 1; - /* A few disks have two indistinguishable version, one of + /* + * A few disks have two indistinguishable version, one of * which reports the correct capacity and the other does not. - * The sd driver has to guess which is the case. */ + * The sd driver has to guess which is the case. + */ if (us->fflags & US_FL_CAPACITY_HEURISTICS) sdev->guess_capacity = 1; @@ -232,26 +255,34 @@ static int slave_configure(struct scsi_device *sdev) if (sdev->scsi_level > SCSI_SPC_2) us->fflags |= US_FL_SANE_SENSE; - /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable + /* + * USB-IDE bridges tend to report SK = 0x04 (Non-recoverable * Hardware Error) when any low-level error occurs, * recoverable or not. Setting this flag tells the SCSI * midlayer to retry such commands, which frequently will * succeed and fix the error. The worst this can lead to - * is an occasional series of retries that will all fail. */ + * is an occasional series of retries that will all fail. + */ sdev->retry_hwerror = 1; - /* USB disks should allow restart. Some drives spin down - * automatically, requiring a START-STOP UNIT command. */ + /* + * USB disks should allow restart. Some drives spin down + * automatically, requiring a START-STOP UNIT command. + */ sdev->allow_restart = 1; - /* Some USB cardreaders have trouble reading an sdcard's last + /* + * Some USB cardreaders have trouble reading an sdcard's last * sector in a larger then 1 sector read, since the performance - * impact is negligible we set this flag for all USB disks */ + * impact is negligible we set this flag for all USB disks + */ sdev->last_sector_bug = 1; - /* Enable last-sector hacks for single-target devices using + /* + * Enable last-sector hacks for single-target devices using * the Bulk-only transport, unless we already know the - * capacity will be decremented or is correct. */ + * capacity will be decremented or is correct. + */ if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK | US_FL_SCM_MULT_TARG)) && us->protocol == USB_PR_BULK) @@ -267,9 +298,11 @@ static int slave_configure(struct scsi_device *sdev) } else { - /* Non-disk-type devices don't need to blacklist any pages + /* + * Non-disk-type devices don't need to blacklist any pages * or to force 192-byte transfer lengths for MODE SENSE. - * But they do need to use MODE SENSE(10). */ + * But they do need to use MODE SENSE(10). + */ sdev->use_10_for_ms = 1; /* Some (fake) usb cdrom devices don't like READ_DISC_INFO */ @@ -277,7 +310,8 @@ static int slave_configure(struct scsi_device *sdev) sdev->no_read_disc_info = 1; } - /* The CB and CBI transports have no way to pass LUN values + /* + * The CB and CBI transports have no way to pass LUN values * other than the bits in the second byte of a CDB. But those * bits don't get set to the LUN value if the device reports * scsi_level == 0 (UNKNOWN). Hence such devices must necessarily @@ -287,13 +321,17 @@ static int slave_configure(struct scsi_device *sdev) sdev->scsi_level == SCSI_UNKNOWN) us->max_lun = 0; - /* Some devices choke when they receive a PREVENT-ALLOW MEDIUM - * REMOVAL command, so suppress those commands. */ + /* + * Some devices choke when they receive a PREVENT-ALLOW MEDIUM + * REMOVAL command, so suppress those commands. + */ if (us->fflags & US_FL_NOT_LOCKABLE) sdev->lockable = 0; - /* this is to satisfy the compiler, tho I don't think the - * return code is ever checked anywhere. */ + /* + * this is to satisfy the compiler, tho I don't think the + * return code is ever checked anywhere. + */ return 0; } @@ -367,8 +405,10 @@ static int command_abort(struct scsi_cmnd *srb) usb_stor_dbg(us, "%s called\n", __func__); - /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING - * bits are protected by the host lock. */ + /* + * us->srb together with the TIMED_OUT, RESETTING, and ABORTING + * bits are protected by the host lock. + */ scsi_lock(us_to_host(us)); /* Is this command still active? */ @@ -378,11 +418,13 @@ static int command_abort(struct scsi_cmnd *srb) return FAILED; } - /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if + /* + * Set the TIMED_OUT bit. Also set the ABORTING bit, but only if * a device reset isn't already in progress (to avoid interfering * with the reset). Note that we must retain the host lock while * calling usb_stor_stop_transport(); otherwise it might interfere - * with an auto-reset that begins as soon as we release the lock. */ + * with an auto-reset that begins as soon as we release the lock. + */ set_bit(US_FLIDX_TIMED_OUT, &us->dflags); if (!test_bit(US_FLIDX_RESETTING, &us->dflags)) { set_bit(US_FLIDX_ABORTING, &us->dflags); @@ -395,8 +437,10 @@ static int command_abort(struct scsi_cmnd *srb) return SUCCESS; } -/* This invokes the transport reset mechanism to reset the state of the - * device */ +/* + * This invokes the transport reset mechanism to reset the state of the + * device + */ static int device_reset(struct scsi_cmnd *srb) { struct us_data *us = host_to_us(srb->device->host); @@ -424,9 +468,11 @@ static int bus_reset(struct scsi_cmnd *srb) return result < 0 ? FAILED : SUCCESS; } -/* Report a driver-initiated device reset to the SCSI layer. +/* + * Report a driver-initiated device reset to the SCSI layer. * Calling this for a SCSI-initiated reset is unnecessary but harmless. - * The caller must own the SCSI host lock. */ + * The caller must own the SCSI host lock. + */ void usb_stor_report_device_reset(struct us_data *us) { int i; @@ -439,9 +485,11 @@ void usb_stor_report_device_reset(struct us_data *us) } } -/* Report a driver-initiated bus reset to the SCSI layer. +/* + * Report a driver-initiated bus reset to the SCSI layer. * Calling this for a SCSI-initiated reset is unnecessary but harmless. - * The caller must not own the SCSI host lock. */ + * The caller must not own the SCSI host lock. + */ void usb_stor_report_bus_reset(struct us_data *us) { struct Scsi_Host *host = us_to_host(us); @@ -590,7 +638,8 @@ static const struct scsi_host_template usb_stor_host_template = { */ .max_sectors = 240, - /* merge commands... this seems to help performance, but + /* + * merge commands... this seems to help performance, but * periodically someone should test to see which setting is more * optimal. */ diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h index 5494d87607fb..d0a331dd9bc5 100644 --- a/drivers/usb/storage/scsiglue.h +++ b/drivers/usb/storage/scsiglue.h @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * SCSI Connecting Glue Header File * * Current development and maintenance by: diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 79224fcf9b59..c5797fa2125e 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1,4 +1,5 @@ -/* Driver for SanDisk SDDR-09 SmartMedia reader +/* + * Driver for SanDisk SDDR-09 SmartMedia reader * * (c) 2000, 2001 Robert Baruch (autophile@starband.net) * (c) 2002 Andries Brouwer (aeb@cwi.nl) @@ -799,10 +800,12 @@ sddr09_read_data(struct us_data *us, usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n", pages, lba, page); - /* This is not really an error. It just means - that the block has never been written. - Instead of returning an error - it is better to return all zero data. */ + /* + * This is not really an error. It just means + * that the block has never been written. + * Instead of returning an error + * it is better to return all zero data. + */ memset(buffer, 0, len); @@ -890,8 +893,10 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, } if (pba == 1) { - /* Maybe it is impossible to write to PBA 1. - Fake success, but don't do anything. */ + /* + * Maybe it is impossible to write to PBA 1. + * Fake success, but don't do anything. + */ printk(KERN_WARNING "sddr09: avoid writing to pba 1\n"); return 0; } @@ -979,18 +984,22 @@ sddr09_write_data(struct us_data *us, struct scatterlist *sg; int result; - // Figure out the initial LBA and page + /* Figure out the initial LBA and page */ lba = address >> info->blockshift; page = (address & info->blockmask); maxlba = info->capacity >> (info->pageshift + info->blockshift); if (lba >= maxlba) return -EIO; - // blockbuffer is used for reading in the old data, overwriting - // with the new data, and performing ECC calculations + /* + * blockbuffer is used for reading in the old data, overwriting + * with the new data, and performing ECC calculations + */ - /* TODO: instead of doing kmalloc/kfree for each write, - add a bufferpointer to the info structure */ + /* + * TODO: instead of doing kmalloc/kfree for each write, + * add a bufferpointer to the info structure + */ pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT); blocklen = (pagelen << info->blockshift); @@ -1000,9 +1009,11 @@ sddr09_write_data(struct us_data *us, return -ENOMEM; } - // Since we don't write the user data directly to the device, - // we have to create a bounce buffer and move the data a piece - // at a time between the bounce buffer and the actual transfer buffer. + /* + * Since we don't write the user data directly to the device, + * we have to create a bounce buffer and move the data a piece + * at a time between the bounce buffer and the actual transfer buffer. + */ len = min(sectors, (unsigned int) info->blocksize) * info->pagesize; buffer = kmalloc(len, GFP_NOIO); @@ -1018,7 +1029,7 @@ sddr09_write_data(struct us_data *us, while (sectors > 0) { - // Write as many sectors as possible in this block + /* Write as many sectors as possible in this block */ pages = min(sectors, info->blocksize - page); len = (pages << info->pageshift); @@ -1031,7 +1042,7 @@ sddr09_write_data(struct us_data *us, break; } - // Get the data from the transfer buffer + /* Get the data from the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, us->srb, &sg, &offset, FROM_XFER_BUF); @@ -1168,9 +1179,11 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { /* Byte 1 is the device type */ cardinfo = nand_find_id(deviceID[1]); if (cardinfo) { - /* MB or MiB? It is neither. A 16 MB card has - 17301504 raw bytes, of which 16384000 are - usable for user data. */ + /* + * MB or MiB? It is neither. A 16 MB card has + * 17301504 raw bytes, of which 16384000 are + * usable for user data. + */ sprintf(blurbtxt + strlen(blurbtxt), ", %d MB", 1<<(cardinfo->chipshift - 20)); } else { @@ -1211,14 +1224,18 @@ sddr09_read_map(struct us_data *us) { if (!info->capacity) return -1; - // size of a block is 1 << (blockshift + pageshift) bytes - // divide into the total capacity to get the number of blocks + /* + * size of a block is 1 << (blockshift + pageshift) bytes + * divide into the total capacity to get the number of blocks + */ numblocks = info->capacity >> (info->blockshift + info->pageshift); - // read 64 bytes for every block (actually 1 << CONTROL_SHIFT) - // but only use a 64 KB buffer - // buffer size used must be a multiple of (1 << CONTROL_SHIFT) + /* + * read 64 bytes for every block (actually 1 << CONTROL_SHIFT) + * but only use a 64 KB buffer + * buffer size used must be a multiple of (1 << CONTROL_SHIFT) + */ #define SDDR09_READ_MAP_BUFSZ 65536 alloc_blocks = min(numblocks, SDDR09_READ_MAP_BUFSZ >> CONTROL_SHIFT); @@ -1575,8 +1592,10 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) havefakesense = 1; - /* Dummy up a response for INQUIRY since SDDR09 doesn't - respond to INQUIRY commands */ + /* + * Dummy up a response for INQUIRY since SDDR09 doesn't + * respond to INQUIRY commands + */ if (srb->cmnd[0] == INQUIRY) { memcpy(ptr, inquiry_response, 8); @@ -1628,8 +1647,10 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) if (srb->cmnd[0] == MODE_SENSE_10) { int modepage = (srb->cmnd[2] & 0x3F); - /* They ask for the Read/Write error recovery page, - or for all pages. */ + /* + * They ask for the Read/Write error recovery page, + * or for all pages. + */ /* %% We should check DBD %% */ if (modepage == 0x01 || modepage == 0x3F) { usb_stor_dbg(us, "Dummy up request for mode page 0x%x\n", @@ -1682,7 +1703,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) USB_STOR_TRANSPORT_ERROR); } - /* catch-all for all other commands, except + /* + * catch-all for all other commands, except * pass TEST_UNIT_READY and REQUEST_SENSE through */ if (srb->cmnd[0] != TEST_UNIT_READY && diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index e5e0a25ecd96..147c50b3e00f 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -1,4 +1,5 @@ -/* Driver for SanDisk SDDR-55 SmartMedia reader +/* + * Driver for SanDisk SDDR-55 SmartMedia reader * * SDDR55 driver v0.1: * @@ -130,7 +131,8 @@ sddr55_bulk_transport(struct us_data *us, int direction, return usb_stor_bulk_transfer_buf(us, pipe, data, len, NULL); } -/* check if card inserted, if there is, update read_only status +/* + * check if card inserted, if there is, update read_only status * return non zero if no card */ @@ -714,15 +716,18 @@ static int sddr55_read_map(struct us_data *us) { if (max_lba > 1000) max_lba = 1000; - // Each block is 64 bytes of control data, so block i is located in - // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) + /* + * Each block is 64 bytes of control data, so block i is located in + * scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) + */ for (i=0; isense_data, 0, sizeof info->sense_data); - /* Dummy up a response for INQUIRY since SDDR55 doesn't - respond to INQUIRY commands */ + /* + * Dummy up a response for INQUIRY since SDDR55 doesn't + * respond to INQUIRY commands + */ if (srb->cmnd[0] == INQUIRY) { memcpy(ptr, inquiry_response, 8); @@ -833,7 +841,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } - /* only check card status if the map isn't allocated, ie no card seen yet + /* + * only check card status if the map isn't allocated, ie no card seen yet * or if it's been over half a second since we last accessed it */ if (info->lba_to_pba == NULL || time_after(jiffies, info->last_access + HZ/2)) { @@ -849,8 +858,10 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) } } - /* if we detected a problem with the map when writing, - don't allow any more access */ + /* + * if we detected a problem with the map when writing, + * don't allow any more access + */ if (info->fatal_error) { set_sense_info (3, 0x31, 0); @@ -868,12 +879,16 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) info->capacity = capacity; - /* figure out the maximum logical block number, allowing for - * the fact that only 250 out of every 256 are used */ + /* + * figure out the maximum logical block number, allowing for + * the fact that only 250 out of every 256 are used + */ info->max_log_blks = ((info->capacity >> (info->pageshift + info->blockshift)) / 256) * 250; - /* Last page in the card, adjust as we only use 250 out of - * every 256 pages */ + /* + * Last page in the card, adjust as we only use 250 out of + * every 256 pages + */ capacity = (capacity / 256) * 250; capacity /= PAGESIZE; diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index a3ec86b913a1..3b0294e4df93 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1,4 +1,5 @@ -/* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable +/* + * Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable * * Current development and maintenance by: * (c) 2000, 2001 Robert Baruch (autophile@starband.net) @@ -408,7 +409,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes) int result; unsigned char *status = us->iobuf; - /* Synchronizing cache on a CDR could take a heck of a long time, + /* + * Synchronizing cache on a CDR could take a heck of a long time, * but probably not more than 10 minutes or so. On the other hand, * doing a full blank on a CDRW at speed 1 will take about 75 * minutes! @@ -1570,9 +1572,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) len = scsi_bufflen(srb); - /* Send A0 (ATA PACKET COMMAND). - Note: I guess we're never going to get any of the ATA - commands... just ATA Packet Commands. + /* + * Send A0 (ATA PACKET COMMAND). + * Note: I guess we're never going to get any of the ATA + * commands... just ATA Packet Commands. */ registers[0] = USBAT_ATA_FEATURES; @@ -1851,7 +1854,8 @@ static int usbat_probe(struct usb_interface *intf, if (result) return result; - /* The actual transport will be determined later by the + /* + * The actual transport will be determined later by the * initialization routine; this is just a placeholder. */ us->transport_name = "Shuttle USBAT"; diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c index 2ea657be14c8..9a51019ac7b2 100644 --- a/drivers/usb/storage/sierra_ms.c +++ b/drivers/usb/storage/sierra_ms.c @@ -177,7 +177,8 @@ int sierra_ms_init(struct us_data *us) debug_swoc(&us->pusb_dev->dev, swocInfo); - /* If there is not Linux software on the TRU-Install device + /* + * If there is not Linux software on the TRU-Install device * then switch to modem mode */ if (!containsFullLinuxPackage(swocInfo)) { diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 5e67f63b2e46..ffd086733421 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * * Current development and maintenance by: * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -109,7 +110,8 @@ * called more than once or from being called during usb_submit_urb(). */ -/* This is the completion handler which will wake us up when an URB +/* + * This is the completion handler which will wake us up when an URB * completes. */ static void usb_stor_blocking_completion(struct urb *urb) @@ -119,7 +121,8 @@ static void usb_stor_blocking_completion(struct urb *urb) complete(urb_done_ptr); } -/* This is the common part of the URB message submission code +/* + * This is the common part of the URB message submission code * * All URBs from the usb-storage driver involved in handling a queued scsi * command _must_ pass through this function (or something like it) for the @@ -142,10 +145,12 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) us->current_urb->context = &urb_done; us->current_urb->transfer_flags = 0; - /* we assume that if transfer_buffer isn't us->iobuf then it + /* + * we assume that if transfer_buffer isn't us->iobuf then it * hasn't been mapped for DMA. Yes, this is clunky, but it's * easier than always having the caller tell us whether the - * transfer buffer has already been mapped. */ + * transfer buffer has already been mapped. + */ if (us->current_urb->transfer_buffer == us->iobuf) us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; us->current_urb->transfer_dma = us->iobuf_dma; @@ -157,8 +162,10 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) return status; } - /* since the URB has been submitted successfully, it's now okay - * to cancel it */ + /* + * since the URB has been submitted successfully, it's now okay + * to cancel it + */ set_bit(US_FLIDX_URB_ACTIVE, &us->dflags); /* did an abort occur during the submission? */ @@ -220,7 +227,8 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, } EXPORT_SYMBOL_GPL(usb_stor_control_msg); -/* This is a version of usb_clear_halt() that allows early termination and +/* + * This is a version of usb_clear_halt() that allows early termination and * doesn't read the status from the device -- this is because some devices * crash their internal firmware when the status is requested after a halt. * @@ -280,8 +288,10 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe, /* stalled */ case -EPIPE: - /* for control endpoints, (used by CB[I]) a stall indicates - * a failed command */ + /* + * for control endpoints, (used by CB[I]) a stall indicates + * a failed command + */ if (usb_pipecontrol(pipe)) { usb_stor_dbg(us, "-- stall on control pipe\n"); return USB_STOR_XFER_STALLED; @@ -433,8 +443,10 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, return USB_STOR_XFER_ERROR; } - /* since the block has been initialized successfully, it's now - * okay to cancel it */ + /* + * since the block has been initialized successfully, it's now + * okay to cancel it + */ set_bit(US_FLIDX_SG_ACTIVE, &us->dflags); /* did an abort occur during the submission? */ @@ -515,7 +527,8 @@ EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg); * Transport routines ***********************************************************************/ -/* There are so many devices that report the capacity incorrectly, +/* + * There are so many devices that report the capacity incorrectly, * this routine was written to counteract some of the resulting * problems. */ @@ -533,7 +546,8 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) [12] = 0x14 /* Record Not Found */ }; - /* If last-sector problems can't occur, whether because the + /* + * If last-sector problems can't occur, whether because the * capacity was already decremented or because the device is * known to report the correct capacity, then we don't need * to do anything. @@ -559,13 +573,15 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) { - /* The command succeeded. We know this device doesn't + /* + * The command succeeded. We know this device doesn't * have the last-sector bug, so stop checking it. */ us->use_last_sector_hacks = 0; } else { - /* The command failed. Allow up to 3 retries in case this + /* + * The command failed. Allow up to 3 retries in case this * is some normal sort of failure. After that, assume the * capacity is wrong and we're trying to access the sector * beyond the end. Replace the result code and sense data @@ -581,7 +597,8 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) } done: - /* Don't reset the retry counter for TEST UNIT READY commands, + /* + * Don't reset the retry counter for TEST UNIT READY commands, * because they get issued after device resets which might be * caused by a failed last-sector access. */ @@ -589,7 +606,8 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) us->last_sector_retries = 0; } -/* Invoke the transport and basic error-handling/recovery methods +/* + * Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. @@ -603,7 +621,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) scsi_set_resid(srb, 0); result = us->transport(srb, us); - /* if the command gets aborted by the higher layers, we need to + /* + * if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { @@ -628,7 +647,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) srb->result = SAM_STAT_GOOD; - /* Determine if we need to auto-sense + /* + * Determine if we need to auto-sense * * I normally don't use a flag like this, but it's almost impossible * to understand what's going on here if I don't. @@ -728,7 +748,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) goto Handle_Errors; } - /* Some devices claim to support larger sense but fail when + /* + * Some devices claim to support larger sense but fail when * trying to request it. When a transport failure happens * using US_FS_SANE_SENSE, we always retry with a standard * (small) sense request. This fixes some USB GSM modems @@ -746,7 +767,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) if (temp_result != USB_STOR_TRANSPORT_GOOD) { usb_stor_dbg(us, "-- auto-sense failure\n"); - /* we skip the reset if this happens to be a + /* + * we skip the reset if this happens to be a * multi-target device, since failure of an * auto-sense is perfectly valid */ @@ -756,7 +778,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) return; } - /* If the sense data returned is larger than 18-bytes then we + /* + * If the sense data returned is larger than 18-bytes then we * assume this device supports requesting more in the future. * The response code must be 70h through 73h inclusive. */ @@ -767,7 +790,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) usb_stor_dbg(us, "-- SANE_SENSE support enabled\n"); us->fflags |= US_FL_SANE_SENSE; - /* Indicate to the user that we truncated their sense + /* + * Indicate to the user that we truncated their sense * because we didn't know it supported larger sense. */ usb_stor_dbg(us, "-- Sense data truncated to %i from %i\n", @@ -795,13 +819,15 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) SCSI_SENSE_BUFFERSIZE, 4); fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0; - /* We often get empty sense data. This could indicate that + /* + * We often get empty sense data. This could indicate that * everything worked or that there was an unspecified * problem. We have to decide which. */ if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 && fm_ili == 0) { - /* If things are really okay, then let's show that. + /* + * If things are really okay, then let's show that. * Zero out the sense buffer so the higher layers * won't realize we did an unsolicited auto-sense. */ @@ -809,7 +835,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; - /* If there was a problem, report an unspecified + /* + * If there was a problem, report an unspecified * hardware error to prevent the higher layers from * entering an infinite retry loop. */ @@ -860,20 +887,26 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) last_sector_hacks(us, srb); return; - /* Error and abort processing: try to resynchronize with the device + /* + * Error and abort processing: try to resynchronize with the device * by issuing a port reset. If that fails, try a class-specific - * device reset. */ + * device reset. + */ Handle_Errors: - /* Set the RESETTING bit, and clear the ABORTING bit so that - * the reset may proceed. */ + /* + * Set the RESETTING bit, and clear the ABORTING bit so that + * the reset may proceed. + */ scsi_lock(us_to_host(us)); set_bit(US_FLIDX_RESETTING, &us->dflags); clear_bit(US_FLIDX_ABORTING, &us->dflags); scsi_unlock(us_to_host(us)); - /* We must release the device lock because the pre_reset routine - * will want to acquire it. */ + /* + * We must release the device lock because the pre_reset routine + * will want to acquire it. + */ mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); mutex_lock(&us->dev_mutex); @@ -891,10 +924,12 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* Stop the current URB transfer */ void usb_stor_stop_transport(struct us_data *us) { - /* If the state machine is blocked waiting for an URB, + /* + * If the state machine is blocked waiting for an URB, * let's wake it up. The test_and_clear_bit() call * guarantees that if a URB has just been submitted, - * it won't be cancelled more than once. */ + * it won't be cancelled more than once. + */ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) { usb_stor_dbg(us, "-- cancelling URB\n"); usb_unlink_urb(us->current_urb); @@ -955,7 +990,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) /* STATUS STAGE */ - /* NOTE: CB does not have a status stage. Silly, I know. So + /* + * NOTE: CB does not have a status stage. Silly, I know. So * we have to catch this at a higher level. */ if (us->protocol != USB_PR_CBI) @@ -967,7 +1003,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - /* UFI gives us ASC and ASCQ, like a request sense + /* + * UFI gives us ASC and ASCQ, like a request sense * * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI * devices, so we ignore the information for those commands. Note @@ -983,7 +1020,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } - /* If not UFI, we interpret the data as a result code + /* + * If not UFI, we interpret the data as a result code * The first byte should always be a 0x0. * * Some bogus devices don't follow that rule. They stuff the ASC @@ -1005,7 +1043,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) } return USB_STOR_TRANSPORT_ERROR; - /* the CBI spec requires that the bulk pipe must be cleared + /* + * the CBI spec requires that the bulk pipe must be cleared * following any data-in/out command failure (section 2.4.3.1.3) */ Failed: @@ -1107,9 +1146,11 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* DATA STAGE */ /* send/receive data payload, if there is any */ - /* Some USB-IDE converter chips need a 100us delay between the + /* + * Some USB-IDE converter chips need a 100us delay between the * command phase and the data phase. Some devices need a little - * more than that, probably because of clock rate inaccuracies. */ + * more than that, probably because of clock rate inaccuracies. + */ if (unlikely(us->fflags & US_FL_GO_SLOW)) usleep_range(125, 150); @@ -1121,7 +1162,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) if (result == USB_STOR_XFER_ERROR) return USB_STOR_TRANSPORT_ERROR; - /* If the device tried to send back more data than the + /* + * If the device tried to send back more data than the * amount requested, the spec requires us to transfer * the CSW anyway. Since there's no point retrying the * the command, we'll return fake sense data indicating @@ -1156,7 +1198,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) } } - /* See flow chart on pg 15 of the Bulk Only Transport spec for + /* + * See flow chart on pg 15 of the Bulk Only Transport spec for * an explanation of how this code works. */ @@ -1165,7 +1208,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen); - /* Some broken devices add unnecessary zero-length packets to the + /* + * Some broken devices add unnecessary zero-length packets to the * end of their data transfers. Such packets show up as 0-length * CSWs. If we encounter such a thing, try to read the CSW again. */ @@ -1201,7 +1245,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_ERROR; } - /* Some broken devices report odd signatures, so we do not check them + /* + * Some broken devices report odd signatures, so we do not check them * for validity against the spec. We store the first one we see, * and check subsequent transfers for validity against this signature. */ @@ -1217,11 +1262,14 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_ERROR; } - /* try to compute the actual residue, based on how much data - * was really transferred and what the device tells us */ + /* + * try to compute the actual residue, based on how much data + * was really transferred and what the device tells us + */ if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { - /* Heuristically detect devices that generate bogus residues + /* + * Heuristically detect devices that generate bogus residues * by seeing what happens with INQUIRY and READ CAPACITY * commands. */ @@ -1259,7 +1307,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; case US_BULK_STAT_PHASE: - /* phase error -- note that a transport reset will be + /* + * phase error -- note that a transport reset will be * invoked by the invoke_transport() function */ return USB_STOR_TRANSPORT_ERROR; @@ -1274,7 +1323,8 @@ EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport); * Reset routines ***********************************************************************/ -/* This is the common part of the device reset code. +/* + * This is the common part of the device reset code. * * It's handy that every transport mechanism uses the control endpoint for * resets. @@ -1302,8 +1352,10 @@ static int usb_stor_reset_common(struct us_data *us, return result; } - /* Give the device some time to recover from the reset, - * but don't delay disconnect processing. */ + /* + * Give the device some time to recover from the reset, + * but don't delay disconnect processing. + */ wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->dflags), HZ*6); @@ -1328,8 +1380,7 @@ static int usb_stor_reset_common(struct us_data *us, return result; } -/* This issues a CB[I] Reset to the device in question - */ +/* This issues a CB[I] Reset to the device in question */ #define CB_RESET_CMD_SIZE 12 int usb_stor_CB_reset(struct us_data *us) @@ -1343,7 +1394,8 @@ int usb_stor_CB_reset(struct us_data *us) } EXPORT_SYMBOL_GPL(usb_stor_CB_reset); -/* This issues a Bulk-only Reset to the device in question, including +/* + * This issues a Bulk-only Reset to the device in question, including * clearing the subsequent endpoint halts that may occur. */ int usb_stor_Bulk_reset(struct us_data *us) @@ -1354,7 +1406,8 @@ int usb_stor_Bulk_reset(struct us_data *us) } EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset); -/* Issue a USB port reset to the device. The caller must not hold +/* + * Issue a USB port reset to the device. The caller must not hold * us->dev_mutex. */ int usb_stor_port_reset(struct us_data *us) diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 9369d752d419..dae3ecd2e6cf 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * Transport Functions Header File * * Current development and maintenance by: diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 16bc679dc2fc..4d49fce406e1 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -799,7 +799,8 @@ static int uas_slave_alloc(struct scsi_device *sdev) sdev->hostdata = devinfo; - /* USB has unusual DMA-alignment requirements: Although the + /* + * USB has unusual DMA-alignment requirements: Although the * starting address of each scatter-gather element doesn't matter, * the length of each element except the last must be divisible * by the Bulk maxpacket value. There's currently no way to diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h index fa3e9edaa2cf..763bc03032a1 100644 --- a/drivers/usb/storage/unusual_alauda.h +++ b/drivers/usb/storage/unusual_alauda.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for the Alauda-based card readers +/* + * Unusual Devices File for the Alauda-based card readers * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index 82e8ed0324e3..e9a2eb88869a 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for devices based on the Cypress USB/ATA bridge +/* + * Unusual Devices File for devices based on the Cypress USB/ATA bridge * with support for ATACB * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h index 582a603c78be..5049b6bbe5d5 100644 --- a/drivers/usb/storage/unusual_datafab.h +++ b/drivers/usb/storage/unusual_datafab.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for the Datafab USB Compact Flash reader +/* + * Unusual Devices File for the Datafab USB Compact Flash reader * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -79,7 +80,8 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), -/* Reported by Felix Moeller +/* + * Reported by Felix Moeller * in Germany this is sold by Hama with the productnumber 46952 * as "DualSlot CompactFlash(TM) & MStick Drive USB" */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 7ffe4209067b..aa3539238848 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * Unusual Devices File * * Current development and maintenance by: @@ -25,13 +26,15 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* IMPORTANT NOTE: This file must be included in another file which does +/* + * IMPORTANT NOTE: This file must be included in another file which does * the following thing for it to work: * The UNUSUAL_DEV, COMPLIANT_DEV, and USUAL_DEV macros must be defined * before this file is included. */ -/* If you edit this file, please try to keep it sorted first by VendorID, +/* + * If you edit this file, please try to keep it sorted first by VendorID, * then by ProductID. * * If you want to add an entry for this file, be sure to include the @@ -47,13 +50,15 @@ * */ -/* Note: If you add an entry only in order to set the CAPACITY_OK flag, +/* + * Note: If you add an entry only in order to set the CAPACITY_OK flag, * use the COMPLIANT_DEV macro instead of UNUSUAL_DEV. This is * because such entries mark devices which actually work correctly, * as opposed to devices that do something strangely or wrongly. */ -/* In-kernel mode switching is deprecated. Do not add new devices to +/* + * In-kernel mode switching is deprecated. Do not add new devices to * this list for the sole purpose of switching them to a different * mode. Existing userspace solutions are superior. * @@ -66,8 +71,7 @@ #define NO_SDDR09 #endif -/* patch submitted by Vivian Bregier - */ +/* patch submitted by Vivian Bregier */ UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, "ATMEL", "SND1 Storage", @@ -93,7 +97,8 @@ UNUSUAL_DEV( 0x03f0, 0x070c, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -/* Reported by Grant Grundler +/* + * Reported by Grant Grundler * HP r707 camera in "Disk" mode with 2.00.23 or 2.00.24 firmware. */ UNUSUAL_DEV( 0x03f0, 0x4002, 0x0001, 0x0001, @@ -107,7 +112,8 @@ UNUSUAL_DEV( 0x03f3, 0x0001, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -/* Reported by Sebastian Kapfer +/* + * Reported by Sebastian Kapfer * and Olaf Hering (different bcd's, same vendor/product) * for USB floppies that need the SINGLE_LUN enforcement. */ @@ -124,7 +130,8 @@ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Deduced by Jonathan Woithe +/* + * Deduced by Jonathan Woithe * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message * always fails and confuses drive. */ @@ -167,8 +174,10 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Andrew Nayenko - * Updated for new firmware by Phillip Potter */ +/* + * Reported by Andrew Nayenko + * Updated for new firmware by Phillip Potter + */ UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0610, "Nokia", "Nokia 6288", @@ -196,16 +205,20 @@ UNUSUAL_DEV( 0x0421, 0x0434, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), -/* Reported by Sumedha Swamy and - * Einar Th. Einarsson */ +/* + * Reported by Sumedha Swamy and + * Einar Th. Einarsson + */ UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, "Nokia", "N91", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), -/* Reported by Jiri Slaby and - * Rene C. Castberg */ +/* + * Reported by Jiri Slaby and + * Rene C. Castberg + */ UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100, "Nokia", "N80", @@ -269,8 +282,10 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, US_FL_SINGLE_LUN ), #endif -/* Patch submitted by Daniel Drake - * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */ +/* + * Patch submitted by Daniel Drake + * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 + */ UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100, "Neuros Audio", "USB 2.0 HD 2.5", @@ -288,17 +303,18 @@ UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* -* Bohdan Linda -* 1GB USB sticks MyFlash High Speed. I have restricted -* the revision to my model only -*/ + * Bohdan Linda + * 1GB USB sticks MyFlash High Speed. I have restricted + * the revision to my model only + */ UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, "USB 2.0", "Flash Disk", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -/* Reported by Tamas Kerecsen +/* + * Reported by Tamas Kerecsen * Obviously the PROM has not been customized by the VAR; * the Vendor and Product string descriptors are: * Generic Mass Storage (PROTOTYPE--Remember to change idVendor) @@ -347,24 +363,30 @@ UNUSUAL_DEV( 0x0482, 0x0107, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE), -/* Reported by Paul Stewart - * This entry is needed because the device reports Sub=ff */ +/* + * Reported by Paul Stewart + * This entry is needed because the device reports Sub=ff + */ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, "Hitachi", "DVD-CAM DZ-MV100A Camcorder", USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN), -/* BENQ DC5330 +/* + * BENQ DC5330 * Reported by Manuel Fombuena and - * Frank Copeland */ + * Frank Copeland + */ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, "Tekom Technologies, Inc", "300_CAMERA", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Patch for Nikon coolpix 2000 - * Submitted by Fabien Cosse */ +/* + * Patch for Nikon coolpix 2000 + * Submitted by Fabien Cosse + */ UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, "NIKON", "NIKON DSC E2000", @@ -378,21 +400,26 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_CB, NULL, US_FL_MAX_SECTORS_MIN), -/* Reported by Simon Levitt - * This entry needs Sub and Proto fields */ +/* + * Reported by Simon Levitt + * This entry needs Sub and Proto fields + */ UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, "Epson", "875DC Storage", USB_SC_SCSI, USB_PR_CB, NULL, US_FL_FIX_INQUIRY), -/* Reported by Khalid Aziz - * This entry is needed because the device reports Sub=ff */ +/* + * Reported by Khalid Aziz + * This entry is needed because the device reports Sub=ff + */ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, "Epson", "785EPX Storage", USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_SINGLE_LUN), -/* Not sure who reported this originally but +/* + * Not sure who reported this originally but * Pavel Machek reported that the extra US_FL_SINGLE_LUN * flag be added */ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, @@ -400,7 +427,8 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, "FinePix 1400Zoom", USB_SC_UFI, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN), -/* Reported by Ondrej Zary +/* + * Reported by Ondrej Zary * The device reports one sector more and breaks when that sector is accessed */ UNUSUAL_DEV( 0x04ce, 0x0002, 0x026c, 0x026c, @@ -409,7 +437,8 @@ UNUSUAL_DEV( 0x04ce, 0x0002, 0x026c, 0x026c, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), -/* Reported by Kriston Fincher +/* + * Reported by Kriston Fincher * Patch submitted by Sean Millichamp * This is to support the Panasonic PalmCam PV-SD4090 * This entry is needed because the device reports Sub=ff @@ -419,8 +448,10 @@ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200, "LS-120 Camera", USB_SC_UFI, USB_PR_DEVICE, NULL, 0), -/* From Yukihiro Nakai, via zaitcev@yahoo.com. - * This is needed for CB instead of CBI */ +/* + * From Yukihiro Nakai, via zaitcev@yahoo.com. + * This is needed for CB instead of CBI + */ UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000, "Sharp CE-CW05", "CD-R/RW Drive", @@ -440,7 +471,8 @@ UNUSUAL_DEV( 0x04da, 0x2373, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ), -/* Most of the following entries were developed with the help of +/* + * Most of the following entries were developed with the help of * Shuttle/SCM directly. */ UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200, @@ -536,7 +568,8 @@ UNUSUAL_DEV( 0x04e8, 0x5136, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64), -/* Entry and supporting patch by Theodore Kilgore . +/* + * Entry and supporting patch by Theodore Kilgore . * Device uses standards-violating 32-byte Bulk Command Block Wrappers and * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. */ @@ -553,7 +586,8 @@ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133, USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -/* Iomega Clik! Drive +/* + * Iomega Clik! Drive * Reported by David Chatenay * The reason this is needed is not fully known. */ @@ -570,7 +604,8 @@ COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_CAPACITY_OK ), -/* Yakumo Mega Image 37 +/* + * Yakumo Mega Image 37 * Submitted by Stephan Fuhrmann */ UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, "Tekom Technologies, Inc", @@ -578,8 +613,10 @@ UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Another Yakumo camera. - * Reported by Michele Alzetta */ +/* + * Another Yakumo camera. + * Reported by Michele Alzetta + */ UNUSUAL_DEV( 0x052b, 0x1804, 0x0100, 0x0100, "Tekom Technologies, Inc", "300_CAMERA", @@ -593,16 +630,20 @@ UNUSUAL_DEV( 0x052b, 0x1807, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Yakumo Mega Image 47 - * Reported by Bjoern Paetzel */ +/* + * Yakumo Mega Image 47 + * Reported by Bjoern Paetzel + */ UNUSUAL_DEV( 0x052b, 0x1905, 0x0100, 0x0100, "Tekom Technologies, Inc", "400_CAMERA", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Paul Ortyl - * Note that it's similar to the device above, only different prodID */ +/* + * Reported by Paul Ortyl + * Note that it's similar to the device above, only different prodID + */ UNUSUAL_DEV( 0x052b, 0x1911, 0x0100, 0x0100, "Tekom Technologies, Inc", "400_CAMERA", @@ -615,8 +656,10 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, USB_SC_SCSI, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ), -/* Submitted by Lars Jacob - * This entry is needed because the device reports Sub=ff */ +/* + * Submitted by Lars Jacob + * This entry is needed because the device reports Sub=ff + */ UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0610, "Sony", "DSC-T1/T5/H5", @@ -719,7 +762,8 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, USB_SC_DEVICE, USB_PR_CB, NULL, US_FL_SINGLE_LUN), -/* Reported by Johann Cardon +/* + * Reported by Johann Cardon * This entry is needed only because the device reports * bInterfaceClass = 0xff (vendor-specific) */ @@ -741,7 +785,8 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Digital Camera EX-20 DSC", USB_SC_8070, USB_PR_DEVICE, NULL, 0 ), -/* Reported by Andre Welter +/* + * Reported by Andre Welter * This antique device predates the release of the Bulk-only Transport * spec, and if it gets a Get-Max-LUN then it requires the host to do a * Clear-Halt on the bulk endpoints. The SINGLE_LUN flag will prevent @@ -773,7 +818,8 @@ UNUSUAL_DEV( 0x059f, 0x0651, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT ), -/* Submitted by Joel Bourquard +/* + * Submitted by Joel Bourquard * Some versions of this device need the SubClass and Protocol overrides * while others don't. */ @@ -783,7 +829,8 @@ UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), -/* Submitted by Sven Anderson +/* + * Submitted by Sven Anderson * There are at least four ProductIDs used for iPods, so I added 0x1202 and * 0x1204. They just need the US_FL_FIX_CAPACITY. As the bcdDevice appears * to change with firmware updates, I changed the range to maximum for all @@ -824,7 +871,8 @@ UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), -/* Reported by Dan Williams +/* + * Reported by Dan Williams * Option N.V. mobile broadband modems * Ignore driver CD mode and force into modem mode by default. */ @@ -843,7 +891,8 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* The following two entries are for a Genesys USB to IDE +/* + * The following two entries are for a Genesys USB to IDE * converter chip, but it changes its ProductId depending * on whether or not a disk or an optical device is enclosed * They were originally reported by Alexander Oltu @@ -873,8 +922,10 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -/* Reported by Hanno Boeck - * Taken from the Lycoris Kernel */ +/* + * Reported by Hanno Boeck + * Taken from the Lycoris Kernel + */ UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, "Vivitar", "Vivicam 35Xx", @@ -908,8 +959,10 @@ UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001, US_FL_NOT_LOCKABLE ), /* Reported by Richard -=[]=- */ -/* Change to bcdDeviceMin (0x0100 to 0x0001) reported by - * Thomas Bartosik */ +/* + * Change to bcdDeviceMin (0x0100 to 0x0001) reported by + * Thomas Bartosik + */ UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100, "Prolific Technology Inc.", "Mass Storage Device", @@ -961,7 +1014,8 @@ UNUSUAL_DEV( 0x071b, 0x3203, 0x0000, 0x0000, US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64 | US_FL_NO_READ_CAPACITY_16), -/* Reported by Jean-Baptiste Onofre +/* + * Reported by Jean-Baptiste Onofre * Support the following product : * "Dane-Elec MediaTouch" */ @@ -971,7 +1025,8 @@ UNUSUAL_DEV( 0x071b, 0x32bb, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), -/* Reported by Massimiliano Ghilardi +/* + * Reported by Massimiliano Ghilardi * This USB MP3/AVI player device fails and disconnects if more than 128 * sectors (64kB) are read/written in a single command, and may be present * at least in the following products: @@ -1040,7 +1095,8 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, US_FL_SINGLE_LUN ), #endif -/* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 +/* + * Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 * Only revision 1.13 tested (same for all of the above devices, * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. * Submitted by Marek Michalkiewicz . @@ -1052,7 +1108,8 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ), -/* Reported by Rauch Wolke +/* + * Reported by Rauch Wolke * and augmented by binbin (Bugzilla #12882) */ UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff, @@ -1061,7 +1118,8 @@ UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ), -/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant +/* + * Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant * to the USB storage specification in two ways: * - They tell us they are using transport protocol CBI. In reality they * are using transport protocol CB. @@ -1119,7 +1177,8 @@ UNUSUAL_DEV( 0x084b, 0xa001, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -/* Entry and supporting patch by Theodore Kilgore . +/* + * Entry and supporting patch by Theodore Kilgore . * Flag will support Bulk devices which use a standards-violating 32-byte * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with * Grandtech GT892x chip, which request "Proprietary SCSI Bulk" support. @@ -1131,7 +1190,8 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BULK32), -/* Reported by +/* + * Reported by * The device reports a vendor-specific device class, requiring an * explicit vendor/product match. */ @@ -1140,11 +1200,12 @@ UNUSUAL_DEV( 0x0851, 0x1542, 0x0002, 0x0002, "FW_Omega2", USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0), -/* Andrew Lunn +/* + * Andrew Lunn * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL * on LUN 4. * Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera" -*/ + */ UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, "PanDigital", "Photo Frame", @@ -1170,7 +1231,8 @@ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN), -/* Submitted by Dylan Taft +/* + * Submitted by Dylan Taft * US_FL_IGNORE_RESIDUE Needed */ UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100, @@ -1179,7 +1241,8 @@ UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE), -/* Entry needed for flags. Moreover, all devices with this ID use +/* + * Entry needed for flags. Moreover, all devices with this ID use * bulk-only transport, but _some_ falsely report Control/Bulk instead. * One example is "Trumpion Digital Research MYMP3". * Submitted by Bjoern Brill @@ -1190,7 +1253,8 @@ UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), -/* Reported by Filippo Bardelli +/* + * Reported by Filippo Bardelli * The device reports a subclass of RBC, which is wrong. */ UNUSUAL_DEV( 0x090a, 0x1050, 0x0100, 0x0100, @@ -1213,7 +1277,8 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), -/* Reported by Paul Hartman +/* + * Reported by Paul Hartman * This card reader returns "Illegal Request, Logical Block Address * Out of Range" for the first READ(10) after a new card is inserted. */ @@ -1223,7 +1288,8 @@ UNUSUAL_DEV( 0x090c, 0x6000, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_INITIAL_READ10 ), -/* This Pentax still camera is not conformant +/* + * This Pentax still camera is not conformant * to the USB storage specification: - * - It does not like the INQUIRY command. So we must handle this command * of the SCSI layer ourselves. @@ -1236,8 +1302,10 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* These are virtual windows driver CDs, which the zd1211rw driver - * automatically converts into WLAN devices. */ +/* + * These are virtual windows driver CDs, which the zd1211rw driver + * automatically converts into WLAN devices. + */ UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, "ZyXEL", "G-220F USB-WLAN Install", @@ -1250,7 +1318,8 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), -/* Reported by Dan Williams +/* + * Reported by Dan Williams * Option N.V. mobile broadband modems * Ignore driver CD mode and force into modem mode by default. */ @@ -1262,20 +1331,24 @@ UNUSUAL_DEV( 0x0af0, 0x6971, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, 0), -/* Reported by F. Aben +/* + * Reported by F. Aben * This device (wrongly) has a vendor-specific device descriptor. * The entry is needed so usb-storage can bind to it's mass-storage - * interface as an interface driver */ + * interface as an interface driver + */ UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, "Option", "GI 0401 SD-Card", USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), -/* Reported by Jan Dumon +/* + * Reported by Jan Dumon * These devices (wrongly) have a vendor-specific device descriptor. * These entries are needed so usb-storage can bind to their mass-storage - * interface as an interface driver */ + * interface as an interface driver + */ UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000, "Option", "GI 0431 SD-Card", @@ -1419,7 +1492,8 @@ UNUSUAL_DEV( 0x0dc4, 0x0073, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), -/* Reported by Lubomir Blaha +/* + * Reported by Lubomir Blaha * I _REALLY_ don't know what 3rd, 4th number and all defines mean, but this * works for me. Can anybody correct these values? (I able to test corrected * version.) @@ -1430,8 +1504,10 @@ UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* Reported by Edward Chapman (taken from linux-usb mailing list) - Netac OnlyDisk Mini U2CV2 512MB USB 2.0 Flash Drive */ +/* + * Reported by Edward Chapman (taken from linux-usb mailing list) + * Netac OnlyDisk Mini U2CV2 512MB USB 2.0 Flash Drive + */ UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999, "Netac", "USB Flash Disk", @@ -1439,8 +1515,10 @@ UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999, US_FL_IGNORE_RESIDUE ), -/* Patch by Stephan Walter - * I don't know why, but it works... */ +/* + * Patch by Stephan Walter + * I don't know why, but it works... + */ UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012, "WINWARD", "Music Disk", @@ -1468,8 +1546,10 @@ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* Submitted by Daniel Drake - * Reported by dayul on the Gentoo Forums */ +/* + * Submitted by Daniel Drake + * Reported by dayul on the Gentoo Forums + */ UNUSUAL_DEV( 0x0ea0, 0x2168, 0x0110, 0x0110, "Ours Technology", "Flash Disk", @@ -1483,15 +1563,18 @@ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Benjamin Schiller - * It is also sold by Easylite as DJ 20 */ +/* + * Reported by Benjamin Schiller + * It is also sold by Easylite as DJ 20 + */ UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103, "Typhoon", "My DJ 1820", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64), -/* Patch by Leonid Petrov mail at lpetrov.net +/* + * Patch by Leonid Petrov mail at lpetrov.net * Reported by Robert Spitzenpfeil * http://www.qbik.ch/usb/devices/showdev.php?id=1705 * Updated to 103 device by MJ Ray mjr at phonecoop.coop @@ -1502,7 +1585,8 @@ UNUSUAL_DEV( 0x0f19, 0x0103, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* David Kuehling : +/* + * David Kuehling : * for MP3-Player AVOX WSX-300ER (bought in Japan). Reports lots of SCSI * errors when trying to write. */ @@ -1540,8 +1624,10 @@ UNUSUAL_DEV( 0x0fce, 0xd0e1, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE), -/* Reported by Jan Mate - * and by Soeren Sonnenburg */ +/* + * Reported by Jan Mate + * and by Soeren Sonnenburg + */ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, "Sony Ericsson", "P990i", @@ -1562,7 +1648,8 @@ UNUSUAL_DEV( 0x0fce, 0xe092, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Kevin Cernekee +/* + * Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. * Devices with bcd > 110 seem to not need it while those @@ -1586,7 +1673,8 @@ UNUSUAL_DEV(0x1058, 0x070a, 0x0000, 0x9999, "My Passport HDD", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_WRITE_CACHE), -/* Reported by Fabio Venturi +/* + * Reported by Fabio Venturi * The device reports a vendor-specific bDeviceClass. */ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100, @@ -1595,7 +1683,8 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0), -/* Reported by Pascal Terjan +/* + * Reported by Pascal Terjan * Ignore driver CD mode and force into modem mode by default. */ UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000, @@ -1603,7 +1692,8 @@ UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000, "USB Mass Storage", USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE), -/* Reported by Kevin Lloyd +/* + * Reported by Kevin Lloyd * Entry is needed for the initializer function override, * which instructs the device to load as a modem * device. @@ -1614,7 +1704,8 @@ UNUSUAL_DEV( 0x1199, 0x0fff, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, sierra_ms_init, 0), -/* Reported by Jaco Kroon +/* + * Reported by Jaco Kroon * The usb-storage module found on the Digitech GNX4 (and supposedly other * devices) misbehaves and causes a bunch of invalid I/O errors. */ @@ -1624,7 +1715,8 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by fangxiaozhi +/* + * Reported by fangxiaozhi * This brings the HUAWEI data card devices into multi-port mode */ UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000, @@ -1993,7 +2085,8 @@ UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0116, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA ), -/* Reported by Alexandre Oliva +/* + * Reported by Alexandre Oliva * JMicron responds to USN and several other SCSI ioctls with a * residue that causes subsequent I/O requests to fail. */ UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, @@ -2009,7 +2102,8 @@ UNUSUAL_DEV( 0x152d, 0x2566, 0x0114, 0x0114, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA ), -/* Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI) +/* + * Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI) * and Mac USB Dock USB-SCSI */ UNUSUAL_DEV( 0x1645, 0x0007, 0x0100, 0x0133, "Entrega Technologies", @@ -2017,8 +2111,10 @@ UNUSUAL_DEV( 0x1645, 0x0007, 0x0100, 0x0133, USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -/* Reported by Robert Schedel - * Note: this is a 'super top' device like the above 14cd/6600 device */ +/* + * Reported by Robert Schedel + * Note: this is a 'super top' device like the above 14cd/6600 device + */ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, "Teac", "HD-35PUK-B", @@ -2045,10 +2141,12 @@ UNUSUAL_DEV( 0x1822, 0x0001, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -/* Reported by Hans de Goede +/* + * Reported by Hans de Goede * These Appotech controllers are found in Picture Frames, they provide a * (buggy) emulation of a cdrom drive which contains the windows software - * Uploading of pictures happens over the corresponding /dev/sg device. */ + * Uploading of pictures happens over the corresponding /dev/sg device. + */ UNUSUAL_DEV( 0x1908, 0x1315, 0x0000, 0x0000, "BUILDWIN", "Photo Frame", @@ -2065,19 +2163,22 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_READ_DISC_INFO ), -/* Reported by Oliver Neukum +/* + * Reported by Oliver Neukum * This device morphes spontaneously into another device if the access * pattern of Windows isn't followed. Thus writable media would be dirty * if the initial instance is used. So the device is limited to its * virtual CD. - * And yes, the concept that BCD goes up to 9 is not heeded */ + * And yes, the concept that BCD goes up to 9 is not heeded + */ UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff, "ZTE,Incorporated", "ZTE WCDMA Technologies MSM", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -/* Reported by Sven Geggus +/* + * Reported by Sven Geggus * This encrypted pen drive returns bogus data for the initial READ(10). */ UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200, @@ -2086,7 +2187,8 @@ UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_INITIAL_READ10 ), -/* Reported by Hans de Goede +/* + * Reported by Hans de Goede * These are mini projectors using USB for both power and video data transport * The usb-storage interface is a virtual windows driver CD, which the gm12u320 * driver automatically converts into framebuffer & kms dri device nodes. @@ -2097,9 +2199,11 @@ UNUSUAL_DEV( 0x1de1, 0xc102, 0x0000, 0xffff, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), -/* Patch by Richard Schütz +/* + * Patch by Richard Schütz * This external hard drive enclosure uses a JMicron chip which - * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ + * needs the US_FL_IGNORE_RESIDUE flag to work properly. + */ UNUSUAL_DEV( 0x1e68, 0x001b, 0x0000, 0x0000, "TrekStor GmbH & Co. KG", "DataStation maxi g.u", @@ -2126,7 +2230,8 @@ UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), -/* patch submitted by Davide Perini +/* + * patch submitted by Davide Perini * and Renato Perini */ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, @@ -2153,7 +2258,8 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_GO_SLOW ), -/* Reported by Frederic Marchal +/* + * Reported by Frederic Marchal * Mio Moov 330 */ UNUSUAL_DEV( 0x3340, 0xffff, 0x0000, 0x0000, diff --git a/drivers/usb/storage/unusual_freecom.h b/drivers/usb/storage/unusual_freecom.h index 59a261155b98..1f5aab42ece2 100644 --- a/drivers/usb/storage/unusual_freecom.h +++ b/drivers/usb/storage/unusual_freecom.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for the Freecom USB/IDE adaptor +/* + * Unusual Devices File for the Freecom USB/IDE adaptor * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h index 14cca0c48302..9b6862ec3d4f 100644 --- a/drivers/usb/storage/unusual_isd200.h +++ b/drivers/usb/storage/unusual_isd200.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for In-System Design, Inc. ISD200 ASIC +/* + * Unusual Devices File for In-System Design, Inc. ISD200 ASIC * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/unusual_jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h index 54be78b5d643..413e64fa6b95 100644 --- a/drivers/usb/storage/unusual_jumpshot.h +++ b/drivers/usb/storage/unusual_jumpshot.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for the Lexar "Jumpshot" Compact Flash reader +/* + * Unusual Devices File for the Lexar "Jumpshot" Compact Flash reader * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h index 6df03972a22c..e6fad3aeae20 100644 --- a/drivers/usb/storage/unusual_karma.h +++ b/drivers/usb/storage/unusual_karma.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for the Rio Karma +/* + * Unusual Devices File for the Rio Karma * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h index 0abb819c7405..425dc22f345a 100644 --- a/drivers/usb/storage/unusual_onetouch.h +++ b/drivers/usb/storage/unusual_onetouch.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for the Maxtor OneTouch USB hard drive's button +/* + * Unusual Devices File for the Maxtor OneTouch USB hard drive's button * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -18,7 +19,8 @@ #if defined(CONFIG_USB_STORAGE_ONETOUCH) || \ defined(CONFIG_USB_STORAGE_ONETOUCH_MODULE) -/* Submitted by: Nick Sillik +/* + * Submitted by: Nick Sillik * Needed for OneTouch extension to usb-storage */ UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h index e41f50c95ed4..8fe624ad302a 100644 --- a/drivers/usb/storage/unusual_realtek.h +++ b/drivers/usb/storage/unusual_realtek.h @@ -1,4 +1,5 @@ -/* Driver for Realtek RTS51xx USB card reader +/* + * Driver for Realtek RTS51xx USB card reader * * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. * diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h index 59a7e37b6c11..d9d38ac4abf9 100644 --- a/drivers/usb/storage/unusual_sddr09.h +++ b/drivers/usb/storage/unusual_sddr09.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for SanDisk SDDR-09 SmartMedia reader +/* + * Unusual Devices File for SanDisk SDDR-09 SmartMedia reader * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h index fcb7e12c598f..ebb1d1c6c467 100644 --- a/drivers/usb/storage/unusual_sddr55.h +++ b/drivers/usb/storage/unusual_sddr55.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for SanDisk SDDR-55 SmartMedia reader +/* + * Unusual Devices File for SanDisk SDDR-55 SmartMedia reader * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index 53341a77d89f..cbea9f329e71 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -1,4 +1,5 @@ -/* Driver for USB Attached SCSI devices - Unusual Devices File +/* + * Driver for USB Attached SCSI devices - Unusual Devices File * * (c) 2013 Hans de Goede * diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h index 38e79c4e6d6a..2044ad5ef5e4 100644 --- a/drivers/usb/storage/unusual_usbat.h +++ b/drivers/usb/storage/unusual_usbat.h @@ -1,4 +1,5 @@ -/* Unusual Devices File for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable +/* + * Unusual Devices File for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 9de988a0f856..ef2d8cde6ef7 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * * Current development and maintenance by: * (c) 1999-2003 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -97,7 +98,8 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); * with the entries in usb_storage_usb_ids[], defined in usual-tables.c. */ -/* The vendor name should be kept at eight characters or less, and +/* + *The vendor name should be kept at eight characters or less, and * the product name should be kept at 16 characters or less. If a device * has the US_FL_FIX_INQUIRY flag, then the vendor and product names * normally generated by a device through the INQUIRY response will be @@ -191,8 +193,10 @@ int usb_stor_suspend(struct usb_interface *iface, pm_message_t message) if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_SUSPEND); - /* When runtime PM is working, we'll set a flag to indicate - * whether we should autoresume when a SCSI request arrives. */ + /* + * When runtime PM is working, we'll set a flag to indicate + * whether we should autoresume when a SCSI request arrives. + */ mutex_unlock(&us->dev_mutex); return 0; @@ -220,8 +224,10 @@ int usb_stor_reset_resume(struct usb_interface *iface) /* Report the reset to the SCSI core */ usb_stor_report_bus_reset(us); - /* FIXME: Notify the subdrivers that they need to reinitialize - * the device */ + /* + * FIXME: Notify the subdrivers that they need to reinitialize + * the device + */ return 0; } EXPORT_SYMBOL_GPL(usb_stor_reset_resume); @@ -250,8 +256,10 @@ int usb_stor_post_reset(struct usb_interface *iface) /* Report the reset to the SCSI core */ usb_stor_report_bus_reset(us); - /* FIXME: Notify the subdrivers that they need to reinitialize - * the device */ + /* + * FIXME: Notify the subdrivers that they need to reinitialize + * the device + */ mutex_unlock(&us->dev_mutex); return 0; @@ -274,15 +282,17 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, return; memset(data+8, ' ', 28); - if (data[0]&0x20) { /* USB device currently not connected. Return - peripheral qualifier 001b ("...however, the - physical device is not currently connected - to this logical unit") and leave vendor and - product identification empty. ("If the target - does store some of the INQUIRY data on the - device, it may return zeros or ASCII spaces - (20h) in those fields until the data is - available from the device."). */ + if (data[0]&0x20) { /* + * USB device currently not connected. Return + * peripheral qualifier 001b ("...however, the + * physical device is not currently connected + * to this logical unit") and leave vendor and + * product identification empty. ("If the target + * does store some of the INQUIRY data on the + * device, it may return zeros or ASCII spaces + * (20h) in those fields until the data is + * available from the device."). + */ } else { u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice); int n; @@ -336,7 +346,8 @@ static int usb_stor_control_thread(void * __us) scsi_unlock(host); - /* reject the command if the direction indicator + /* + * reject the command if the direction indicator * is UNKNOWN */ if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) { @@ -344,7 +355,8 @@ static int usb_stor_control_thread(void * __us) us->srb->result = DID_ERROR << 16; } - /* reject if target != 0 or if LUN is higher than + /* + * reject if target != 0 or if LUN is higher than * the maximum known LUN */ else if (us->srb->device->id && @@ -362,8 +374,10 @@ static int usb_stor_control_thread(void * __us) us->srb->result = DID_BAD_TARGET << 16; } - /* Handle those devices which need us to fake - * their inquiry data */ + /* + * Handle those devices which need us to fake + * their inquiry data + */ else if ((us->srb->cmnd[0] == INQUIRY) && (us->fflags & US_FL_FIX_INQUIRY)) { unsigned char data_ptr[36] = { @@ -395,11 +409,13 @@ static int usb_stor_control_thread(void * __us) usb_stor_dbg(us, "scsi command aborted\n"); } - /* If an abort request was received we need to signal that + /* + * If an abort request was received we need to signal that * the abort has finished. The proper test for this is * the TIMED_OUT flag, not srb->result == DID_ABORT, because * the timeout might have occurred after the command had - * already completed with a different result code. */ + * already completed with a different result code. + */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { complete(&(us->notify)); @@ -610,7 +626,8 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id, le16_to_cpu(dev->descriptor.idProduct), us->fflags); - /* Log a message if a non-generic unusual_dev entry contains an + /* + * Log a message if a non-generic unusual_dev entry contains an * unnecessary subclass or protocol override. This may stimulate * reports from users that will help us remove unneeded entries * from the unusual_devs.h table. @@ -782,8 +799,10 @@ static int usb_stor_acquire_resources(struct us_data *us) return -ENOMEM; } - /* Just before we start our control thread, initialize - * the device if it needs initialization */ + /* + * Just before we start our control thread, initialize + * the device if it needs initialization + */ if (us->unusual_dev->initFunction) { p = us->unusual_dev->initFunction(us); if (p) @@ -805,7 +824,8 @@ static int usb_stor_acquire_resources(struct us_data *us) /* Release all our dynamic resources */ static void usb_stor_release_resources(struct us_data *us) { - /* Tell the control thread to exit. The SCSI host must + /* + * Tell the control thread to exit. The SCSI host must * already have been removed and the DISCONNECTING flag set * so that we won't accept any more commands. */ @@ -836,7 +856,8 @@ static void dissociate_dev(struct us_data *us) usb_set_intfdata(us->pusb_intf, NULL); } -/* First stage of disconnect processing: stop SCSI scanning, +/* + * First stage of disconnect processing: stop SCSI scanning, * remove the host, and stop accepting new commands */ static void quiesce_and_remove_host(struct us_data *us) @@ -849,7 +870,8 @@ static void quiesce_and_remove_host(struct us_data *us) wake_up(&us->delay_wait); } - /* Prevent SCSI scanning (if it hasn't started yet) + /* + * Prevent SCSI scanning (if it hasn't started yet) * or wait for the SCSI-scanning routine to stop. */ cancel_delayed_work_sync(&us->scan_dwork); @@ -858,12 +880,14 @@ static void quiesce_and_remove_host(struct us_data *us) if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags)) usb_autopm_put_interface_no_suspend(us->pusb_intf); - /* Removing the host will perform an orderly shutdown: caches + /* + * Removing the host will perform an orderly shutdown: caches * synchronized, disks spun down, etc. */ scsi_remove_host(host); - /* Prevent any new commands from being accepted and cut short + /* + * Prevent any new commands from being accepted and cut short * reset delays. */ scsi_lock(host); @@ -878,8 +902,10 @@ static void release_everything(struct us_data *us) usb_stor_release_resources(us); dissociate_dev(us); - /* Drop our reference to the host; the SCSI core will free it - * (and "us" along with it) when the refcount becomes 0. */ + /* + * Drop our reference to the host; the SCSI core will free it + * (and "us" along with it) when the refcount becomes 0. + */ scsi_host_put(us_to_host(us)); } @@ -900,7 +926,8 @@ static void usb_stor_scan_dwork(struct work_struct *work) us->max_lun = usb_stor_Bulk_max_lun(us); /* * Allow proper scanning of devices that present more than 8 LUNs - * While not affecting other devices that may need the previous behavior + * While not affecting other devices that may need the previous + * behavior */ if (us->max_lun >= 8) us_to_host(us)->max_lun = us->max_lun+1; @@ -975,7 +1002,8 @@ int usb_stor_probe1(struct us_data **pus, get_transport(us); get_protocol(us); - /* Give the caller a chance to fill in specialized transport + /* + * Give the caller a chance to fill in specialized transport * or protocol settings. */ return 0; diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index da0ad3241728..8fae28b40bb4 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage compliant devices +/* + * Driver for USB Mass Storage compliant devices * Main Header File * * Current development and maintenance by: @@ -100,7 +101,8 @@ typedef void (*pm_hook)(struct us_data *, int); /* power management hook */ /* we allocate one of these for every device that we remember */ struct us_data { - /* The device we're working with + /* + * The device we're working with * It's important to note: * (o) you must hold dev_mutex to change pusb_dev */ @@ -125,7 +127,7 @@ struct us_data { u8 max_lun; u8 ifnum; /* interface number */ - u8 ep_bInterval; /* interrupt interval */ + u8 ep_bInterval; /* interrupt interval */ /* function pointers for this device */ trans_cmnd transport; /* transport function */ @@ -175,8 +177,10 @@ static inline struct us_data *host_to_us(struct Scsi_Host *host) { extern void fill_inquiry_response(struct us_data *us, unsigned char *data, unsigned int data_len); -/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the - * single queue element srb for write access */ +/* + * The scsi_lock() and scsi_unlock() macros protect the sm_state and the + * single queue element srb for write access + */ #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 5ef8ce74aae4..499669bcf700 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -1,4 +1,5 @@ -/* Driver for USB Mass Storage devices +/* + * Driver for USB Mass Storage devices * Usual Tables File for usb-storage and libusual * * Copyright (C) 2009 Alan Stern (stern@rowland.harvard.edu) -- GitLab From ee3b6f1e6de5e93856fce5c87d53e26b078b254c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 12 Apr 2016 12:16:01 -0400 Subject: [PATCH 4656/9938] staging: lustre: selftest: convert lstcon_test_t to proper struct Turn typedef lstcon_test_t to proper structure Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conctl.c | 2 +- drivers/staging/lustre/lnet/selftest/conrpc.c | 5 ++-- .../staging/lustre/lnet/selftest/console.c | 26 +++++++++---------- .../staging/lustre/lnet/selftest/console.h | 7 ++--- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index a76f1c3b86df..408c614b6ca3 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -743,7 +743,7 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) if (args->lstio_tes_param && (args->lstio_tes_param_len <= 0 || args->lstio_tes_param_len > - PAGE_SIZE - sizeof(lstcon_test_t))) + PAGE_SIZE - sizeof(struct lstcon_test))) return -EINVAL; LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1); diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 31d7b4f4a9e4..bc96ef8ba5f9 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -807,7 +807,7 @@ lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) int lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, - lstcon_test_t *test, struct lstcon_rpc **crpc) + struct lstcon_test *test, struct lstcon_rpc **crpc) { struct lstcon_group *sgrp = test->tes_src_grp; struct lstcon_group *dgrp = test->tes_dst_grp; @@ -1128,7 +1128,8 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, case LST_TRANS_TSBCLIADD: case LST_TRANS_TSBSRVADD: rc = lstcon_testrpc_prep(nd, transop, feats, - (lstcon_test_t *)arg, &rpc); + (struct lstcon_test *)arg, + &rpc); break; case LST_TRANS_TSBRUN: case LST_TRANS_TSBSTOP: diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 03c73b014b2c..6568e8e105b9 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -934,7 +934,7 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, lstcon_test_batch_ent_t *entp; struct list_head *clilst; struct list_head *srvlst; - lstcon_test_t *test = NULL; + struct lstcon_test *test = NULL; struct lstcon_batch *bat; struct lstcon_ndlink *ndl; int rc; @@ -1091,14 +1091,14 @@ static void lstcon_batch_destroy(struct lstcon_batch *bat) { struct lstcon_ndlink *ndl; - lstcon_test_t *test; + struct lstcon_test *test; int i; list_del(&bat->bat_link); while (!list_empty(&bat->bat_test_list)) { test = list_entry(bat->bat_test_list.next, - lstcon_test_t, tes_link); + struct lstcon_test, tes_link); LASSERT(list_empty(&test->tes_trans_list)); list_del(&test->tes_link); @@ -1106,7 +1106,7 @@ lstcon_batch_destroy(struct lstcon_batch *bat) lstcon_group_decref(test->tes_src_grp); lstcon_group_decref(test->tes_dst_grp); - LIBCFS_FREE(test, offsetof(lstcon_test_t, + LIBCFS_FREE(test, offsetof(struct lstcon_test, tes_param[test->tes_paramlen])); } @@ -1143,13 +1143,13 @@ lstcon_batch_destroy(struct lstcon_batch *bat) static int lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg) { - lstcon_test_t *test; + struct lstcon_test *test; struct lstcon_batch *batch; struct lstcon_ndlink *ndl; struct list_head *hash; struct list_head *head; - test = (lstcon_test_t *)arg; + test = (struct lstcon_test *)arg; LASSERT(test); batch = test->tes_batch; @@ -1185,7 +1185,7 @@ lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg) } static int -lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up) +lstcon_test_nodes_add(struct lstcon_test *test, struct list_head __user *result_up) { struct lstcon_rpc_trans *trans; struct lstcon_group *grp; @@ -1283,7 +1283,7 @@ lstcon_test_add(char *batch_name, int type, int loop, void *param, int paramlen, int *retp, struct list_head __user *result_up) { - lstcon_test_t *test = NULL; + struct lstcon_test *test = NULL; int rc; struct lstcon_group *src_grp = NULL; struct lstcon_group *dst_grp = NULL; @@ -1309,7 +1309,7 @@ lstcon_test_add(char *batch_name, int type, int loop, if (dst_grp->grp_userland) *retp = 1; - LIBCFS_ALLOC(test, offsetof(lstcon_test_t, tes_param[paramlen])); + LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen])); if (!test) { CERROR("Can't allocate test descriptor\n"); rc = -ENOMEM; @@ -1356,7 +1356,7 @@ lstcon_test_add(char *batch_name, int type, int loop, return rc; out: if (test) - LIBCFS_FREE(test, offsetof(lstcon_test_t, tes_param[paramlen])); + LIBCFS_FREE(test, offsetof(struct lstcon_test, tes_param[paramlen])); if (dst_grp) lstcon_group_decref(dst_grp); @@ -1368,9 +1368,9 @@ lstcon_test_add(char *batch_name, int type, int loop, } static int -lstcon_test_find(struct lstcon_batch *batch, int idx, lstcon_test_t **testpp) +lstcon_test_find(struct lstcon_batch *batch, int idx, struct lstcon_test **testpp) { - lstcon_test_t *test; + struct lstcon_test *test; list_for_each_entry(test, &batch->bat_test_list, tes_link) { if (idx == test->tes_hdr.tsb_index) { @@ -1408,7 +1408,7 @@ lstcon_test_batch_query(char *name, int testidx, int client, struct list_head *ndlist; struct lstcon_tsb_hdr *hdr; struct lstcon_batch *batch; - lstcon_test_t *test = NULL; + struct lstcon_test *test = NULL; int transop; int rc; diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index ccd4982b0cd6..becd22e41da9 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -99,7 +99,7 @@ struct lstcon_batch { * for run, force for stop */ char bat_name[LST_NAME_SIZE];/* name of batch */ - struct list_head bat_test_list; /* list head of tests (lstcon_test_t) + struct list_head bat_test_list; /* list head of tests (struct lstcon_test) */ struct list_head bat_trans_list; /* list head of transaction */ struct list_head bat_cli_list; /* list head of client nodes @@ -109,7 +109,8 @@ struct lstcon_batch { struct list_head *bat_srv_hash; /* hash table of server nodes */ }; -typedef struct lstcon_test { +/* a single test descriptor */ +struct lstcon_test { struct lstcon_tsb_hdr tes_hdr; /* test batch header */ struct list_head tes_link; /* chain on batch's tests list */ struct lstcon_batch *tes_batch; /* pointer to batch */ @@ -129,7 +130,7 @@ typedef struct lstcon_test { int tes_paramlen; /* test parameter length */ char tes_param[0]; /* test parameter */ -} lstcon_test_t; /* a single test descriptor */ +}; #define LST_GLOBAL_HASHSIZE 503 /* global nodes hash table size */ #define LST_NODE_HASHSIZE 239 /* node hash table (for batch or group) */ -- GitLab From 45d2f4fb5a19d4aa5d7d81796081aa6cba9e4e70 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 12 Apr 2016 12:16:02 -0400 Subject: [PATCH 4657/9938] staging: lustre: selftest: convert wire protocol to use struct Change all the wire protocol typedefs to proper structures Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/brw_test.c | 22 +-- drivers/staging/lustre/lnet/selftest/conrpc.c | 44 ++--- .../staging/lustre/lnet/selftest/console.c | 10 +- .../staging/lustre/lnet/selftest/framework.c | 54 +++---- .../staging/lustre/lnet/selftest/ping_test.c | 10 +- drivers/staging/lustre/lnet/selftest/rpc.c | 6 +- drivers/staging/lustre/lnet/selftest/rpc.h | 150 +++++++++--------- .../staging/lustre/lnet/selftest/selftest.h | 13 +- 8 files changed, 155 insertions(+), 154 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 7f539f92321c..a63d86c4c10d 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -81,7 +81,7 @@ brw_client_init(struct sfw_test_instance *tsi) LASSERT(tsi->tsi_is_client); if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { - test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; + struct test_bulk_req *breq = &tsi->tsi_u.bulk_v0; opc = breq->blk_opc; flags = breq->blk_flags; @@ -92,7 +92,7 @@ brw_client_init(struct sfw_test_instance *tsi) */ len = npg * PAGE_SIZE; } else { - test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; + struct test_bulk_req_v1 *breq = &tsi->tsi_u.bulk_v1; /* * I should never get this step if it's unknown feature @@ -261,7 +261,7 @@ brw_client_prep_rpc(struct sfw_test_unit *tsu, struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; struct srpc_client_rpc *rpc; - srpc_brw_reqst_t *req; + struct srpc_brw_reqst *req; int flags; int npg; int len; @@ -272,14 +272,14 @@ brw_client_prep_rpc(struct sfw_test_unit *tsu, LASSERT(bulk); if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { - test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; + struct test_bulk_req *breq = &tsi->tsi_u.bulk_v0; opc = breq->blk_opc; flags = breq->blk_flags; npg = breq->blk_npg; len = npg * PAGE_SIZE; } else { - test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; + struct test_bulk_req_v1 *breq = &tsi->tsi_u.bulk_v1; /* * I should never get this step if it's unknown feature @@ -319,8 +319,8 @@ brw_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc) struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; struct srpc_msg *msg = &rpc->crpc_replymsg; - srpc_brw_reply_t *reply = &msg->msg_body.brw_reply; - srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; + struct srpc_brw_reply *reply = &msg->msg_body.brw_reply; + struct srpc_brw_reqst *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; LASSERT(sn); @@ -382,8 +382,8 @@ static int brw_bulk_ready(struct srpc_server_rpc *rpc, int status) { __u64 magic = BRW_MAGIC; - srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply; - srpc_brw_reqst_t *reqst; + struct srpc_brw_reply *reply = &rpc->srpc_replymsg.msg_body.brw_reply; + struct srpc_brw_reqst *reqst; struct srpc_msg *reqstmsg; LASSERT(rpc->srpc_bulk); @@ -420,8 +420,8 @@ brw_server_handle(struct srpc_server_rpc *rpc) struct srpc_service *sv = rpc->srpc_scd->scd_svc; struct srpc_msg *replymsg = &rpc->srpc_replymsg; struct srpc_msg *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; - srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply; - srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst; + struct srpc_brw_reply *reply = &replymsg->msg_body.brw_reply; + struct srpc_brw_reqst *reqst = &reqstmsg->msg_body.brw_reqst; int npg; int rc; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index bc96ef8ba5f9..6f687581117d 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -390,7 +390,7 @@ lstcon_rpc_get_reply(struct lstcon_rpc *crpc, struct srpc_msg **msgpp) { struct lstcon_node *nd = crpc->crp_node; struct srpc_client_rpc *rpc = crpc->crp_rpc; - srpc_generic_reply_t *rep; + struct srpc_generic_reply *rep; LASSERT(nd && rpc); LASSERT(crpc->crp_stamp); @@ -473,7 +473,7 @@ lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans, struct list_head tmp; struct list_head __user *next; lstcon_rpc_ent_t *ent; - srpc_generic_reply_t *rep; + struct srpc_generic_reply *rep; struct lstcon_rpc *crpc; struct srpc_msg *msg; struct lstcon_node *nd; @@ -520,7 +520,7 @@ lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans, continue; /* RPC is done */ - rep = (srpc_generic_reply_t *)&msg->msg_body.reply; + rep = (struct srpc_generic_reply *)&msg->msg_body.reply; if (copy_to_user(&ent->rpe_sid, &rep->sid, sizeof(lst_sid_t)) || copy_to_user(&ent->rpe_fwk_errno, &rep->status, @@ -595,8 +595,8 @@ int lstcon_sesrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, struct lstcon_rpc **crpc) { - srpc_mksn_reqst_t *msrq; - srpc_rmsn_reqst_t *rsrq; + struct srpc_mksn_reqst *msrq; + struct srpc_rmsn_reqst *rsrq; int rc; switch (transop) { @@ -633,7 +633,7 @@ lstcon_sesrpc_prep(struct lstcon_node *nd, int transop, int lstcon_dbgrpc_prep(struct lstcon_node *nd, unsigned feats, struct lstcon_rpc **crpc) { - srpc_debug_reqst_t *drq; + struct srpc_debug_reqst *drq; int rc; rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, feats, 0, 0, crpc); @@ -653,7 +653,7 @@ lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, struct lstcon_tsb_hdr *tsb, struct lstcon_rpc **crpc) { struct lstcon_batch *batch; - srpc_batch_reqst_t *brq; + struct srpc_batch_reqst *brq; int rc; rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, feats, 0, 0, crpc); @@ -684,7 +684,7 @@ lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, int lstcon_statrpc_prep(struct lstcon_node *nd, unsigned feats, struct lstcon_rpc **crpc) { - srpc_stat_reqst_t *srq; + struct srpc_stat_reqst *srq; int rc; rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, feats, 0, 0, crpc); @@ -769,9 +769,9 @@ lstcon_dstnodes_prep(struct lstcon_group *grp, int idx, } static int -lstcon_pingrpc_prep(lst_test_ping_param_t *param, srpc_test_reqst_t *req) +lstcon_pingrpc_prep(lst_test_ping_param_t *param, struct srpc_test_reqst *req) { - test_ping_req_t *prq = &req->tsr_u.ping; + struct test_ping_req *prq = &req->tsr_u.ping; prq->png_size = param->png_size; prq->png_flags = param->png_flags; @@ -780,9 +780,9 @@ lstcon_pingrpc_prep(lst_test_ping_param_t *param, srpc_test_reqst_t *req) } static int -lstcon_bulkrpc_v0_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) +lstcon_bulkrpc_v0_prep(lst_test_bulk_param_t *param, struct srpc_test_reqst *req) { - test_bulk_req_t *brq = &req->tsr_u.bulk_v0; + struct test_bulk_req *brq = &req->tsr_u.bulk_v0; brq->blk_opc = param->blk_opc; brq->blk_npg = (param->blk_size + PAGE_SIZE - 1) / @@ -793,9 +793,9 @@ lstcon_bulkrpc_v0_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) } static int -lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) +lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, struct srpc_test_reqst *req) { - test_bulk_req_v1_t *brq = &req->tsr_u.bulk_v1; + struct test_bulk_req_v1 *brq = &req->tsr_u.bulk_v1; brq->blk_opc = param->blk_opc; brq->blk_flags = param->blk_flags; @@ -811,7 +811,7 @@ lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, { struct lstcon_group *sgrp = test->tes_src_grp; struct lstcon_group *dgrp = test->tes_dst_grp; - srpc_test_reqst_t *trq; + struct srpc_test_reqst *trq; struct srpc_bulk *bulk; int i; int npg = 0; @@ -918,7 +918,7 @@ static int lstcon_sesnew_stat_reply(struct lstcon_rpc_trans *trans, struct lstcon_node *nd, struct srpc_msg *reply) { - srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply; + struct srpc_mksn_reply *mksn_rep = &reply->msg_body.mksn_reply; int status = mksn_rep->mksn_status; if (!status && @@ -965,11 +965,11 @@ void lstcon_rpc_stat_reply(struct lstcon_rpc_trans *trans, struct srpc_msg *msg, struct lstcon_node *nd, lstcon_trans_stat_t *stat) { - srpc_rmsn_reply_t *rmsn_rep; - srpc_debug_reply_t *dbg_rep; - srpc_batch_reply_t *bat_rep; - srpc_test_reply_t *test_rep; - srpc_stat_reply_t *stat_rep; + struct srpc_rmsn_reply *rmsn_rep; + struct srpc_debug_reply *dbg_rep; + struct srpc_batch_reply *bat_rep; + struct srpc_test_reply *test_rep; + struct srpc_stat_reply *stat_rep; int rc = 0; switch (trans->tas_opc) { @@ -1173,7 +1173,7 @@ lstcon_rpc_pinger(void *arg) struct lstcon_rpc_trans *trans; struct lstcon_rpc *crpc; struct srpc_msg *rep; - srpc_debug_reqst_t *drq; + struct srpc_debug_reqst *drq; struct lstcon_ndlink *ndl; struct lstcon_node *nd; int intv; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 6568e8e105b9..a03e52d29d3f 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -373,7 +373,7 @@ static int lstcon_sesrpc_readent(int transop, struct srpc_msg *msg, lstcon_rpc_ent_t __user *ent_up) { - srpc_debug_reply_t *rep; + struct srpc_debug_reply *rep; switch (transop) { case LST_TRANS_SESNEW: @@ -1386,7 +1386,7 @@ static int lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg, lstcon_rpc_ent_t __user *ent_up) { - srpc_batch_reply_t *rep = &msg->msg_body.bat_reply; + struct srpc_batch_reply *rep = &msg->msg_body.bat_reply; LASSERT(transop == LST_TRANS_TSBCLIQRY || transop == LST_TRANS_TSBSRVQRY); @@ -1465,7 +1465,7 @@ static int lstcon_statrpc_readent(int transop, struct srpc_msg *msg, lstcon_rpc_ent_t __user *ent_up) { - srpc_stat_reply_t *rep = &msg->msg_body.stat_reply; + struct srpc_stat_reply *rep = &msg->msg_body.stat_reply; sfw_counters_t __user *sfwk_stat; srpc_counters_t __user *srpc_stat; lnet_counters_t __user *lnet_stat; @@ -1907,8 +1907,8 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) { struct srpc_msg *rep = &rpc->srpc_replymsg; struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg; - srpc_join_reqst_t *jreq = &req->msg_body.join_reqst; - srpc_join_reply_t *jrep = &rep->msg_body.join_reply; + struct srpc_join_reqst *jreq = &req->msg_body.join_reqst; + struct srpc_join_reply *jrep = &rep->msg_body.join_reply; struct lstcon_group *grp = NULL; struct lstcon_ndlink *ndl; int rc = 0; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index ef3cc8264daa..30e4f71f14c2 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -361,7 +361,7 @@ sfw_bid2batch(lst_bid_t bid) } static int -sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply) +sfw_get_stats(struct srpc_stat_reqst *request, struct srpc_stat_reply *reply) { struct sfw_session *sn = sfw_data.fw_session; sfw_counters_t *cnt = &reply->str_fw; @@ -402,7 +402,7 @@ sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply) } int -sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) +sfw_make_session(struct srpc_mksn_reqst *request, struct srpc_mksn_reply *reply) { struct sfw_session *sn = sfw_data.fw_session; struct srpc_msg *msg = container_of(request, struct srpc_msg, @@ -473,7 +473,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) } static int -sfw_remove_session(srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply) +sfw_remove_session(struct srpc_rmsn_reqst *request, struct srpc_rmsn_reply *reply) { struct sfw_session *sn = sfw_data.fw_session; @@ -505,7 +505,7 @@ sfw_remove_session(srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply) } static int -sfw_debug_session(srpc_debug_reqst_t *request, srpc_debug_reply_t *reply) +sfw_debug_session(struct srpc_debug_reqst *request, struct srpc_debug_reply *reply) { struct sfw_session *sn = sfw_data.fw_session; @@ -687,7 +687,7 @@ sfw_destroy_session(struct sfw_session *sn) static void sfw_unpack_addtest_req(struct srpc_msg *msg) { - srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; + struct srpc_test_reqst *req = &msg->msg_body.tes_reqst; LASSERT(msg->msg_type == SRPC_MSG_TEST_REQST); LASSERT(req->tsr_is_client); @@ -699,14 +699,14 @@ sfw_unpack_addtest_req(struct srpc_msg *msg) if (req->tsr_service == SRPC_SERVICE_BRW) { if (!(msg->msg_ses_feats & LST_FEAT_BULK_LEN)) { - test_bulk_req_t *bulk = &req->tsr_u.bulk_v0; + struct test_bulk_req *bulk = &req->tsr_u.bulk_v0; __swab32s(&bulk->blk_opc); __swab32s(&bulk->blk_npg); __swab32s(&bulk->blk_flags); } else { - test_bulk_req_v1_t *bulk = &req->tsr_u.bulk_v1; + struct test_bulk_req_v1 *bulk = &req->tsr_u.bulk_v1; __swab16s(&bulk->blk_opc); __swab16s(&bulk->blk_flags); @@ -718,7 +718,7 @@ sfw_unpack_addtest_req(struct srpc_msg *msg) } if (req->tsr_service == SRPC_SERVICE_PING) { - test_ping_req_t *ping = &req->tsr_u.ping; + struct test_ping_req *ping = &req->tsr_u.ping; __swab32s(&ping->png_size); __swab32s(&ping->png_flags); @@ -732,7 +732,7 @@ static int sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) { struct srpc_msg *msg = &rpc->srpc_reqstbuf->buf_msg; - srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; + struct srpc_test_reqst *req = &msg->msg_body.tes_reqst; struct srpc_bulk *bk = rpc->srpc_bulk; int ndest = req->tsr_ndest; struct sfw_test_unit *tsu; @@ -1068,7 +1068,7 @@ sfw_stop_batch(struct sfw_batch *tsb, int force) } static int -sfw_query_batch(struct sfw_batch *tsb, int testidx, srpc_batch_reply_t *reply) +sfw_query_batch(struct sfw_batch *tsb, int testidx, struct srpc_batch_reply *reply) { struct sfw_test_instance *tsi; @@ -1116,8 +1116,8 @@ static int sfw_add_test(struct srpc_server_rpc *rpc) { struct sfw_session *sn = sfw_data.fw_session; - srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply; - srpc_test_reqst_t *request; + struct srpc_test_reply *reply = &rpc->srpc_replymsg.msg_body.tes_reply; + struct srpc_test_reqst *request; int rc; struct sfw_batch *bat; @@ -1183,7 +1183,7 @@ sfw_add_test(struct srpc_server_rpc *rpc) } static int -sfw_control_batch(srpc_batch_reqst_t *request, srpc_batch_reply_t *reply) +sfw_control_batch(struct srpc_batch_reqst *request, struct srpc_batch_reply *reply) { struct sfw_session *sn = sfw_data.fw_session; int rc = 0; @@ -1424,7 +1424,7 @@ sfw_unpack_message(struct srpc_msg *msg) LASSERT(msg->msg_magic == __swab32(SRPC_MSG_MAGIC)); if (msg->msg_type == SRPC_MSG_STAT_REQST) { - srpc_stat_reqst_t *req = &msg->msg_body.stat_reqst; + struct srpc_stat_reqst *req = &msg->msg_body.stat_reqst; __swab32s(&req->str_type); __swab64s(&req->str_rpyid); @@ -1433,7 +1433,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_STAT_REPLY) { - srpc_stat_reply_t *rep = &msg->msg_body.stat_reply; + struct srpc_stat_reply *rep = &msg->msg_body.stat_reply; __swab32s(&rep->str_status); sfw_unpack_sid(rep->str_sid); @@ -1444,7 +1444,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_MKSN_REQST) { - srpc_mksn_reqst_t *req = &msg->msg_body.mksn_reqst; + struct srpc_mksn_reqst *req = &msg->msg_body.mksn_reqst; __swab64s(&req->mksn_rpyid); __swab32s(&req->mksn_force); @@ -1453,7 +1453,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_MKSN_REPLY) { - srpc_mksn_reply_t *rep = &msg->msg_body.mksn_reply; + struct srpc_mksn_reply *rep = &msg->msg_body.mksn_reply; __swab32s(&rep->mksn_status); __swab32s(&rep->mksn_timeout); @@ -1462,7 +1462,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_RMSN_REQST) { - srpc_rmsn_reqst_t *req = &msg->msg_body.rmsn_reqst; + struct srpc_rmsn_reqst *req = &msg->msg_body.rmsn_reqst; __swab64s(&req->rmsn_rpyid); sfw_unpack_sid(req->rmsn_sid); @@ -1470,7 +1470,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_RMSN_REPLY) { - srpc_rmsn_reply_t *rep = &msg->msg_body.rmsn_reply; + struct srpc_rmsn_reply *rep = &msg->msg_body.rmsn_reply; __swab32s(&rep->rmsn_status); sfw_unpack_sid(rep->rmsn_sid); @@ -1478,7 +1478,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_DEBUG_REQST) { - srpc_debug_reqst_t *req = &msg->msg_body.dbg_reqst; + struct srpc_debug_reqst *req = &msg->msg_body.dbg_reqst; __swab64s(&req->dbg_rpyid); __swab32s(&req->dbg_flags); @@ -1487,7 +1487,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_DEBUG_REPLY) { - srpc_debug_reply_t *rep = &msg->msg_body.dbg_reply; + struct srpc_debug_reply *rep = &msg->msg_body.dbg_reply; __swab32s(&rep->dbg_nbatch); __swab32s(&rep->dbg_timeout); @@ -1496,7 +1496,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_BATCH_REQST) { - srpc_batch_reqst_t *req = &msg->msg_body.bat_reqst; + struct srpc_batch_reqst *req = &msg->msg_body.bat_reqst; __swab32s(&req->bar_opc); __swab64s(&req->bar_rpyid); @@ -1508,7 +1508,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_BATCH_REPLY) { - srpc_batch_reply_t *rep = &msg->msg_body.bat_reply; + struct srpc_batch_reply *rep = &msg->msg_body.bat_reply; __swab32s(&rep->bar_status); sfw_unpack_sid(rep->bar_sid); @@ -1516,7 +1516,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_TEST_REQST) { - srpc_test_reqst_t *req = &msg->msg_body.tes_reqst; + struct srpc_test_reqst *req = &msg->msg_body.tes_reqst; __swab64s(&req->tsr_rpyid); __swab64s(&req->tsr_bulkid); @@ -1530,7 +1530,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_TEST_REPLY) { - srpc_test_reply_t *rep = &msg->msg_body.tes_reply; + struct srpc_test_reply *rep = &msg->msg_body.tes_reply; __swab32s(&rep->tsr_status); sfw_unpack_sid(rep->tsr_sid); @@ -1538,7 +1538,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_JOIN_REQST) { - srpc_join_reqst_t *req = &msg->msg_body.join_reqst; + struct srpc_join_reqst *req = &msg->msg_body.join_reqst; __swab64s(&req->join_rpyid); sfw_unpack_sid(req->join_sid); @@ -1546,7 +1546,7 @@ sfw_unpack_message(struct srpc_msg *msg) } if (msg->msg_type == SRPC_MSG_JOIN_REPLY) { - srpc_join_reply_t *rep = &msg->msg_body.join_reply; + struct srpc_join_reply *rep = &msg->msg_body.join_reply; __swab32s(&rep->join_status); __swab32s(&rep->join_timeout); diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index 8a9d7a41f7de..ad26fe9dd4af 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -89,7 +89,7 @@ static int ping_client_prep_rpc(struct sfw_test_unit *tsu, lnet_process_id_t dest, struct srpc_client_rpc **rpc) { - srpc_ping_reqst_t *req; + struct srpc_ping_reqst *req; struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; struct timespec64 ts; @@ -122,8 +122,8 @@ ping_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc) { struct sfw_test_instance *tsi = tsu->tsu_instance; struct sfw_session *sn = tsi->tsi_batch->bat_session; - srpc_ping_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.ping_reqst; - srpc_ping_reply_t *reply = &rpc->crpc_replymsg.msg_body.ping_reply; + struct srpc_ping_reqst *reqst = &rpc->crpc_reqstmsg.msg_body.ping_reqst; + struct srpc_ping_reply *reply = &rpc->crpc_replymsg.msg_body.ping_reply; struct timespec64 ts; LASSERT(sn); @@ -173,8 +173,8 @@ ping_server_handle(struct srpc_server_rpc *rpc) struct srpc_service *sv = rpc->srpc_scd->scd_svc; struct srpc_msg *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; struct srpc_msg *replymsg = &rpc->srpc_replymsg; - srpc_ping_reqst_t *req = &reqstmsg->msg_body.ping_reqst; - srpc_ping_reply_t *rep = &rpc->srpc_replymsg.msg_body.ping_reply; + struct srpc_ping_reqst *req = &reqstmsg->msg_body.ping_reqst; + struct srpc_ping_reply *rep = &rpc->srpc_replymsg.msg_body.ping_reply; LASSERT(sv->sv_id == SRPC_SERVICE_PING); diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 561e28c644b1..3c45a7cfae18 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -997,7 +997,7 @@ srpc_handle_rpc(struct swi_workitem *wi) LBUG(); case SWI_STATE_NEWBORN: { struct srpc_msg *msg; - srpc_generic_reply_t *reply; + struct srpc_generic_reply *reply; msg = &rpc->srpc_reqstbuf->buf_msg; reply = &rpc->srpc_replymsg.msg_body.reply; @@ -1238,7 +1238,7 @@ srpc_send_rpc(struct swi_workitem *wi) wi->swi_state = SWI_STATE_REQUEST_SENT; /* perhaps more events, fall thru */ case SWI_STATE_REQUEST_SENT: { - srpc_msg_type_t type = srpc_service2reply(rpc->crpc_service); + enum srpc_msg_type type = srpc_service2reply(rpc->crpc_service); if (!rpc->crpc_replyev.ev_fired) break; @@ -1417,7 +1417,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) struct srpc_buffer *buffer; struct srpc_service *sv; struct srpc_msg *msg; - srpc_msg_type_t type; + enum srpc_msg_type type; LASSERT(!in_interrupt()); diff --git a/drivers/staging/lustre/lnet/selftest/rpc.h b/drivers/staging/lustre/lnet/selftest/rpc.h index fdf881ffd9ad..c9b904cade16 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.h +++ b/drivers/staging/lustre/lnet/selftest/rpc.h @@ -44,7 +44,7 @@ * * XXX: *REPLY == *REQST + 1 */ -typedef enum { +enum srpc_msg_type { SRPC_MSG_MKSN_REQST = 0, SRPC_MSG_MKSN_REPLY = 1, SRPC_MSG_RMSN_REQST = 2, @@ -63,7 +63,7 @@ typedef enum { SRPC_MSG_PING_REPLY = 15, SRPC_MSG_JOIN_REQST = 16, SRPC_MSG_JOIN_REPLY = 17, -} srpc_msg_type_t; +}; /* CAVEAT EMPTOR: * All srpc_*_reqst_t's 1st field must be matchbits of reply buffer, @@ -72,122 +72,122 @@ typedef enum { * All srpc_*_reply_t's 1st field must be a __u32 status, and 2nd field * session id if needed. */ -typedef struct { +struct srpc_generic_reqst { __u64 rpyid; /* reply buffer matchbits */ __u64 bulkid; /* bulk buffer matchbits */ -} WIRE_ATTR srpc_generic_reqst_t; +} WIRE_ATTR; -typedef struct { +struct srpc_generic_reply { __u32 status; lst_sid_t sid; -} WIRE_ATTR srpc_generic_reply_t; +} WIRE_ATTR; /* FRAMEWORK RPCs */ -typedef struct { +struct srpc_mksn_reqst { __u64 mksn_rpyid; /* reply buffer matchbits */ lst_sid_t mksn_sid; /* session id */ __u32 mksn_force; /* use brute force */ char mksn_name[LST_NAME_SIZE]; -} WIRE_ATTR srpc_mksn_reqst_t; /* make session request */ +} WIRE_ATTR; /* make session request */ -typedef struct { +struct srpc_mksn_reply { __u32 mksn_status; /* session status */ lst_sid_t mksn_sid; /* session id */ __u32 mksn_timeout; /* session timeout */ char mksn_name[LST_NAME_SIZE]; -} WIRE_ATTR srpc_mksn_reply_t; /* make session reply */ +} WIRE_ATTR; /* make session reply */ -typedef struct { +struct srpc_rmsn_reqst { __u64 rmsn_rpyid; /* reply buffer matchbits */ lst_sid_t rmsn_sid; /* session id */ -} WIRE_ATTR srpc_rmsn_reqst_t; /* remove session request */ +} WIRE_ATTR; /* remove session request */ -typedef struct { +struct srpc_rmsn_reply { __u32 rmsn_status; lst_sid_t rmsn_sid; /* session id */ -} WIRE_ATTR srpc_rmsn_reply_t; /* remove session reply */ +} WIRE_ATTR; /* remove session reply */ -typedef struct { +struct srpc_join_reqst { __u64 join_rpyid; /* reply buffer matchbits */ lst_sid_t join_sid; /* session id to join */ char join_group[LST_NAME_SIZE]; /* group name */ -} WIRE_ATTR srpc_join_reqst_t; +} WIRE_ATTR; -typedef struct { +struct srpc_join_reply { __u32 join_status; /* returned status */ lst_sid_t join_sid; /* session id */ __u32 join_timeout; /* # seconds' inactivity to * expire */ char join_session[LST_NAME_SIZE]; /* session name */ -} WIRE_ATTR srpc_join_reply_t; +} WIRE_ATTR; -typedef struct { +struct srpc_debug_reqst { __u64 dbg_rpyid; /* reply buffer matchbits */ lst_sid_t dbg_sid; /* session id */ __u32 dbg_flags; /* bitmap of debug */ -} WIRE_ATTR srpc_debug_reqst_t; +} WIRE_ATTR; -typedef struct { +struct srpc_debug_reply { __u32 dbg_status; /* returned code */ lst_sid_t dbg_sid; /* session id */ __u32 dbg_timeout; /* session timeout */ __u32 dbg_nbatch; /* # of batches in the node */ char dbg_name[LST_NAME_SIZE]; /* session name */ -} WIRE_ATTR srpc_debug_reply_t; +} WIRE_ATTR; #define SRPC_BATCH_OPC_RUN 1 #define SRPC_BATCH_OPC_STOP 2 #define SRPC_BATCH_OPC_QUERY 3 -typedef struct { +struct srpc_batch_reqst { __u64 bar_rpyid; /* reply buffer matchbits */ lst_sid_t bar_sid; /* session id */ lst_bid_t bar_bid; /* batch id */ __u32 bar_opc; /* create/start/stop batch */ __u32 bar_testidx; /* index of test */ __u32 bar_arg; /* parameters */ -} WIRE_ATTR srpc_batch_reqst_t; +} WIRE_ATTR; -typedef struct { +struct srpc_batch_reply { __u32 bar_status; /* status of request */ lst_sid_t bar_sid; /* session id */ __u32 bar_active; /* # of active tests in batch/test */ __u32 bar_time; /* remained time */ -} WIRE_ATTR srpc_batch_reply_t; +} WIRE_ATTR; -typedef struct { +struct srpc_stat_reqst { __u64 str_rpyid; /* reply buffer matchbits */ lst_sid_t str_sid; /* session id */ __u32 str_type; /* type of stat */ -} WIRE_ATTR srpc_stat_reqst_t; +} WIRE_ATTR; -typedef struct { +struct srpc_stat_reply { __u32 str_status; lst_sid_t str_sid; sfw_counters_t str_fw; srpc_counters_t str_rpc; lnet_counters_t str_lnet; -} WIRE_ATTR srpc_stat_reply_t; +} WIRE_ATTR; -typedef struct { +struct test_bulk_req { __u32 blk_opc; /* bulk operation code */ __u32 blk_npg; /* # of pages */ __u32 blk_flags; /* reserved flags */ -} WIRE_ATTR test_bulk_req_t; +} WIRE_ATTR; -typedef struct { +struct test_bulk_req_v1 { __u16 blk_opc; /* bulk operation code */ __u16 blk_flags; /* data check flags */ __u32 blk_len; /* data length */ __u32 blk_offset; /* reserved: offset */ -} WIRE_ATTR test_bulk_req_v1_t; +} WIRE_ATTR; -typedef struct { +struct test_ping_req { __u32 png_size; /* size of ping message */ __u32 png_flags; /* reserved flags */ -} WIRE_ATTR test_ping_req_t; +} WIRE_ATTR; -typedef struct { +struct srpc_test_reqst { __u64 tsr_rpyid; /* reply buffer matchbits */ __u64 tsr_bulkid; /* bulk buffer matchbits */ lst_sid_t tsr_sid; /* session id */ @@ -201,43 +201,43 @@ typedef struct { __u32 tsr_ndest; /* # of dest nodes */ union { - test_ping_req_t ping; - test_bulk_req_t bulk_v0; - test_bulk_req_v1_t bulk_v1; - } tsr_u; -} WIRE_ATTR srpc_test_reqst_t; + struct test_ping_req ping; + struct test_bulk_req bulk_v0; + struct test_bulk_req_v1 bulk_v1; + } tsr_u; +} WIRE_ATTR; -typedef struct { +struct srpc_test_reply { __u32 tsr_status; /* returned code */ lst_sid_t tsr_sid; -} WIRE_ATTR srpc_test_reply_t; +} WIRE_ATTR; /* TEST RPCs */ -typedef struct { +struct srpc_ping_reqst { __u64 pnr_rpyid; __u32 pnr_magic; __u32 pnr_seq; __u64 pnr_time_sec; __u64 pnr_time_usec; -} WIRE_ATTR srpc_ping_reqst_t; +} WIRE_ATTR; -typedef struct { +struct srpc_ping_reply { __u32 pnr_status; __u32 pnr_magic; __u32 pnr_seq; -} WIRE_ATTR srpc_ping_reply_t; +} WIRE_ATTR; -typedef struct { +struct srpc_brw_reqst { __u64 brw_rpyid; /* reply buffer matchbits */ __u64 brw_bulkid; /* bulk buffer matchbits */ __u32 brw_rw; /* read or write */ __u32 brw_len; /* bulk data len */ __u32 brw_flags; /* bulk data patterns */ -} WIRE_ATTR srpc_brw_reqst_t; /* bulk r/w request */ +} WIRE_ATTR; /* bulk r/w request */ -typedef struct { +struct srpc_brw_reply { __u32 brw_status; -} WIRE_ATTR srpc_brw_reply_t; /* bulk r/w reply */ +} WIRE_ATTR; /* bulk r/w reply */ #define SRPC_MSG_MAGIC 0xeeb0f00d #define SRPC_MSG_VERSION 1 @@ -245,33 +245,33 @@ typedef struct { struct srpc_msg { __u32 msg_magic; /* magic number */ __u32 msg_version; /* message version number */ - __u32 msg_type; /* type of message body: srpc_msg_type_t */ + __u32 msg_type; /* type of message body: srpc_msg_type */ __u32 msg_reserved0; __u32 msg_reserved1; __u32 msg_ses_feats; /* test session features */ union { - srpc_generic_reqst_t reqst; - srpc_generic_reply_t reply; - - srpc_mksn_reqst_t mksn_reqst; - srpc_mksn_reply_t mksn_reply; - srpc_rmsn_reqst_t rmsn_reqst; - srpc_rmsn_reply_t rmsn_reply; - srpc_debug_reqst_t dbg_reqst; - srpc_debug_reply_t dbg_reply; - srpc_batch_reqst_t bat_reqst; - srpc_batch_reply_t bat_reply; - srpc_stat_reqst_t stat_reqst; - srpc_stat_reply_t stat_reply; - srpc_test_reqst_t tes_reqst; - srpc_test_reply_t tes_reply; - srpc_join_reqst_t join_reqst; - srpc_join_reply_t join_reply; - - srpc_ping_reqst_t ping_reqst; - srpc_ping_reply_t ping_reply; - srpc_brw_reqst_t brw_reqst; - srpc_brw_reply_t brw_reply; + struct srpc_generic_reqst reqst; + struct srpc_generic_reply reply; + + struct srpc_mksn_reqst mksn_reqst; + struct srpc_mksn_reply mksn_reply; + struct srpc_rmsn_reqst rmsn_reqst; + struct srpc_rmsn_reply rmsn_reply; + struct srpc_debug_reqst dbg_reqst; + struct srpc_debug_reply dbg_reply; + struct srpc_batch_reqst bat_reqst; + struct srpc_batch_reply bat_reply; + struct srpc_stat_reqst stat_reqst; + struct srpc_stat_reply stat_reply; + struct srpc_test_reqst tes_reqst; + struct srpc_test_reply tes_reply; + struct srpc_join_reqst join_reqst; + struct srpc_join_reply join_reply; + + struct srpc_ping_reqst ping_reqst; + struct srpc_ping_reply ping_reply; + struct srpc_brw_reqst brw_reqst; + struct srpc_brw_reply brw_reply; } msg_body; } WIRE_ATTR; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 1dac777daf63..4eac1c9e639f 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -93,7 +93,7 @@ struct sfw_test_instance; /* all reply/bulk RDMAs go to this portal */ #define SRPC_RDMA_PORTAL 52 -static inline srpc_msg_type_t +static inline enum srpc_msg_type srpc_service2request(int service) { switch (service) { @@ -128,7 +128,7 @@ srpc_service2request(int service) } } -static inline srpc_msg_type_t +static inline enum srpc_msg_type srpc_service2reply(int service) { return srpc_service2request(service) + 1; @@ -385,9 +385,9 @@ struct sfw_test_instance { struct list_head tsi_active_rpcs; /* active rpcs */ union { - test_ping_req_t ping; /* ping parameter */ - test_bulk_req_t bulk_v0; /* bulk parameter */ - test_bulk_req_v1_t bulk_v1; /* bulk v1 parameter */ + struct test_ping_req ping; /* ping parameter */ + struct test_bulk_req bulk_v0; /* bulk parameter */ + struct test_bulk_req_v1 bulk_v1; /* bulk v1 parameter */ } tsi_u; }; @@ -428,7 +428,8 @@ void sfw_free_pages(struct srpc_server_rpc *rpc); void sfw_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i); int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, int sink); -int sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply); +int sfw_make_session(struct srpc_mksn_reqst *request, + struct srpc_mksn_reply *reply); struct srpc_client_rpc * srpc_create_client_rpc(lnet_process_id_t peer, int service, -- GitLab From abcdb1e471e2adbe036123d12d625d65bb2ba8ef Mon Sep 17 00:00:00 2001 From: Aleksei Fedotov Date: Tue, 12 Apr 2016 14:05:49 +0300 Subject: [PATCH 4658/9938] staging: lustre: libcfs: Fix libcfs_ioctl() prototype. Fix libcfs_ioctl() prototype according to its definition in libcfs/module.c. Signed-off-by: Aleksei Fedotov Acked-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 9158c61f6851..4141afb101bb 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -106,7 +106,7 @@ int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, const struct libcfs_ioctl_hdr __user *uparam); int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data); -int libcfs_ioctl(unsigned long cmd, void *arg); +int libcfs_ioctl(unsigned long cmd, void __user *arg); /* container_of depends on "likely" which is defined in libcfs_private.h */ static inline void *__container_of(void *ptr, unsigned long shift) -- GitLab From 6a6514719455fd114a17c0e8c6ffff0f8c5151d6 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Tue, 12 Apr 2016 21:11:08 -0400 Subject: [PATCH 4659/9938] staging/lustre: Fix blank line after/before {/} style This patch fixes all checkpatch occurences of CHECK: Blank lines aren't necessary after an open brace '{' CHECK: Blank lines aren't necessary before a close brace '}' in Lustre code. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fld/fld_request.c | 1 - drivers/staging/lustre/lustre/include/lu_object.h | 1 - drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 1 - drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 1 - drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 1 - drivers/staging/lustre/lustre/llite/dir.c | 2 -- drivers/staging/lustre/lustre/llite/lproc_llite.c | 1 - drivers/staging/lustre/lustre/llite/xattr.c | 1 - drivers/staging/lustre/lustre/llite/xattr_cache.c | 1 - drivers/staging/lustre/lustre/lov/lov_io.c | 1 - drivers/staging/lustre/lustre/lov/lov_obd.c | 1 - drivers/staging/lustre/lustre/lov/lov_pack.c | 1 - drivers/staging/lustre/lustre/lov/lov_request.c | 1 - drivers/staging/lustre/lustre/lov/lovsub_object.c | 1 - drivers/staging/lustre/lustre/mdc/mdc_lib.c | 1 - drivers/staging/lustre/lustre/mdc/mdc_locks.c | 1 - drivers/staging/lustre/lustre/mgc/mgc_request.c | 1 - drivers/staging/lustre/lustre/obdclass/class_obd.c | 1 - drivers/staging/lustre/lustre/obdclass/genops.c | 1 - drivers/staging/lustre/lustre/obdclass/llog.c | 1 - drivers/staging/lustre/lustre/obdclass/lu_object.c | 2 -- drivers/staging/lustre/lustre/obdclass/obd_config.c | 1 - drivers/staging/lustre/lustre/obdecho/echo_client.c | 2 -- drivers/staging/lustre/lustre/osc/osc_cache.c | 1 - drivers/staging/lustre/lustre/osc/osc_io.c | 1 - drivers/staging/lustre/lustre/osc/osc_page.c | 1 - drivers/staging/lustre/lustre/osc/osc_request.c | 1 - drivers/staging/lustre/lustre/ptlrpc/client.c | 1 - drivers/staging/lustre/lustre/ptlrpc/events.c | 1 - drivers/staging/lustre/lustre/ptlrpc/import.c | 3 --- drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c | 1 - drivers/staging/lustre/lustre/ptlrpc/nrs.c | 1 - drivers/staging/lustre/lustre/ptlrpc/pack_generic.c | 3 --- 33 files changed, 40 deletions(-) diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 2dfdb51445df..64c387e8cddd 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -95,7 +95,6 @@ static void fld_exit_request(struct client_obd *cli) spin_lock(&cli->cl_loi_list_lock); cli->cl_r_in_flight--; list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { /* No free request slots anymore */ break; diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 0f70acd1a750..b5b0c81caff2 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -198,7 +198,6 @@ typedef int (*lu_printer_t)(const struct lu_env *env, * Operations specific for particular lu_object. */ struct lu_object_operations { - /** * Allocate lower-layer parts of the object by calling * lu_device_operations::ldo_object_alloc() of the corresponding diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 9e58b1c7177b..bc951c0cac49 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -429,7 +429,6 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) ldlm_put_ref(); err: return rc; - } EXPORT_SYMBOL(client_obd_setup); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 3f9b85262770..6c27b23bd879 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -810,7 +810,6 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode) } else if (!lock->l_readers && !lock->l_writers && !(lock->l_flags & LDLM_FL_NO_LRU) && !(lock->l_flags & LDLM_FL_BL_AST)) { - LDLM_DEBUG(lock, "add lock into lru list"); /* If this is a client-side namespace and this was the last diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 880efdc2fa96..861e4be35250 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1803,7 +1803,6 @@ static void ldlm_namespace_foreach(struct ldlm_namespace *ns, cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_res_iter_helper, &helper); - } /* non-blocking function to manipulate a lock whose cb_data is being put away. diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 2f0873ee7824..1d5366b15a1b 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1059,7 +1059,6 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy) /* hpk_errval must be >= 0 */ hpk.hpk_errval = EBUSY; } - } progress: @@ -1388,7 +1387,6 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) lmv_out_free: obd_ioctl_freedata(buf, len); return rc; - } case LL_IOC_LOV_SETSTRIPE: { struct lov_user_md_v3 lumv3; diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index d99d8c3d602a..4a9f6693feba 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -254,7 +254,6 @@ static ssize_t max_read_ahead_mb_store(struct kobject *kobj, pages_number *= 1 << (20 - PAGE_SHIFT); /* MB -> pages */ if (pages_number > totalram_pages / 2) { - CERROR("can't set file readahead more than %lu MB\n", totalram_pages >> (20 - PAGE_SHIFT + 1)); /*1/2 of RAM*/ return -ERANGE; diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 9f6fcfe8b988..43b2d08fca40 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -339,7 +339,6 @@ int ll_getxattr_common(struct inode *inode, const char *name, */ if (xattr_type == XATTR_ACL_ACCESS_T && !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) { - struct posix_acl *acl; spin_lock(&lli->lli_lock); diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c index 3480ce2bb3cc..d7e17abbe361 100644 --- a/drivers/staging/lustre/lustre/llite/xattr_cache.c +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -229,7 +229,6 @@ static int ll_xattr_cache_valid(struct ll_inode_info *lli) */ static int ll_xattr_cache_destroy_locked(struct ll_inode_info *lli) { - if (!ll_xattr_cache_valid(lli)) return 0; diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index da4784b474e4..86cb3f8f9246 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -442,7 +442,6 @@ static int lov_io_rw_iter_init(const struct lu_env *env, /* fast path for common case. */ if (lio->lis_nr_subios != 1 && !cl_io_is_append(io)) { - lov_do_div64(start, ssize); next = (start + 1) * ssize; if (next <= start * ssize) diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 1a9e3e8cdda9..6d02914b198b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -964,7 +964,6 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg, CERROR("Unknown command: %d\n", lcfg->lcfg_command); rc = -EINVAL; goto out; - } } out: diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index d983a30b1e3a..0215ea54df8d 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -136,7 +136,6 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); return -EINVAL; - } if (lsm) { diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 7178a02d6267..8226ab25790f 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -235,7 +235,6 @@ static int common_attr_done(struct lov_request_set *set) if (tmp_oa) kmem_cache_free(obdo_cachep, tmp_oa); return rc; - } int lov_fini_getattr_set(struct lov_request_set *set) diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c index 3f51f0db02ad..bcaae1e5b840 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_object.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c @@ -71,7 +71,6 @@ int lovsub_object_init(const struct lu_env *env, struct lu_object *obj, result = -ENOMEM; } return result; - } static void lovsub_object_free(const struct lu_env *env, struct lu_object *obj) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 53cd56f286b7..856c54e03b6b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -438,7 +438,6 @@ void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, char *tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); LOGL0(op_data->op_name, op_data->op_namelen, tmp); - } } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 958a164f620d..9e970ab92887 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -963,7 +963,6 @@ static int mdc_finish_intent_lock(struct obd_export *exp, if (fid_is_sane(&op_data->op_fid2) && it->it_create_mode & M_CHECK_STALE && it->it_op != IT_GETATTR) { - /* Also: did we find the same inode? */ /* sever can return one of two fids: * op_fid2 - new allocated fid - if file is created. diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 3924b095bfb0..0c3bd1648a88 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -1720,7 +1720,6 @@ static int mgc_process_config(struct obd_device *obd, u32 len, void *buf) CERROR("Unknown command: %d\n", lcfg->lcfg_command); rc = -EINVAL; goto out; - } } out: diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 799e5585b64d..a3c7e7b4ed90 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -335,7 +335,6 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) err = 0; goto out; } - } if (data->ioc_dev == OBD_DEV_BY_DEVNAME) { diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index cf97b8f06764..d95f11d62a32 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -604,7 +604,6 @@ int obd_init_caches(void) out: obd_cleanup_caches(); return -ENOMEM; - } /* map connection to client */ diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 992573eae1b1..79194d8cb587 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -265,7 +265,6 @@ static int llog_process_thread(void *arg) for (rec = (struct llog_rec_hdr *)buf; (char *)rec < buf + LLOG_CHUNK_SIZE; rec = (struct llog_rec_hdr *)((char *)rec + rec->lrh_len)) { - CDEBUG(D_OTHER, "processing rec 0x%p type %#x\n", rec, rec->lrh_type); diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 990e9394c8f1..e04385760f21 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -104,7 +104,6 @@ void lu_object_put(const struct lu_env *env, struct lu_object *o) if (!cfs_hash_bd_dec_and_lock(site->ls_obj_hash, &bd, &top->loh_ref)) { if (lu_object_is_dying(top)) { - /* * somebody may be waiting for this, currently only * used for cl_object, see cl_object_put_last(). @@ -358,7 +357,6 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) if (count > 0 && --count == 0) break; - } cfs_hash_bd_unlock(s->ls_obj_hash, &bd, 1); cond_resched(); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 5395e994deab..318a2e3e72ab 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -961,7 +961,6 @@ int class_process_config(struct lustre_cfg *lcfg) default: { err = obd_process_config(obd, sizeof(*lcfg), lcfg); goto out; - } } out: diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index b271895d4395..6aa6d8696251 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1354,7 +1354,6 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, for (i = 0, pgp = pga, off = offset; i < npages; i++, pgp++, off += PAGE_SIZE) { - LASSERT(!pgp->pg); /* for cleanup */ rc = -ENOMEM; @@ -1831,7 +1830,6 @@ static int __init obdecho_init(void) static void /*__exit*/ obdecho_exit(void) { echo_client_exit(); - } MODULE_AUTHOR("OpenSFS, Inc. "); diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index ef6882107e93..de8c8255ce4f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1820,7 +1820,6 @@ static void osc_process_ar(struct osc_async_rc *ar, __u64 xid, ar->ar_force_sync = 1; ar->ar_min_xid = ptlrpc_sample_next_xid(); return; - } if (ar->ar_force_sync && (xid >= ar->ar_min_xid)) diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index c1efcb306f24..9d67fca2bc59 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -782,7 +782,6 @@ static void osc_req_attr_set(const struct lu_env *env, oa->o_valid |= OBD_MD_FLID; } if (flags & OBD_MD_FLHANDLE) { - clerq = slice->crs_req; LASSERT(!list_empty(&clerq->crq_pages)); apage = container_of(clerq->crq_pages.next, diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index b55f46739dfa..5ec550855f2e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -759,7 +759,6 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, LASSERT(atomic_read(cli->cl_lru_left) >= 0); while (!atomic_add_unless(cli->cl_lru_left, -1, 0)) { - /* run out of LRU spaces, try to drop some by itself */ rc = osc_lru_reclaim(cli); if (rc < 0) diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 4d0f831990f2..e5794fb58fd7 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -837,7 +837,6 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, spin_unlock(&cli->cl_loi_list_lock); CDEBUG(D_CACHE, "dirty: %llu undirty: %u dropped %u grant: %llu\n", oa->o_dirty, oa->o_undirty, oa->o_dropped, oa->o_grant); - } void osc_update_next_shrink(struct client_obd *cli) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index e02d95d1d537..4b7912a2cb52 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1082,7 +1082,6 @@ static int ptlrpc_console_allow(struct ptlrpc_request *req) */ if ((lustre_handle_is_used(&req->rq_import->imp_remote_handle)) && (opc == OST_CONNECT || opc == MDS_CONNECT || opc == MGS_CONNECT)) { - /* Suppress timed out reconnect requests */ if (req->rq_timedout) return 0; diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index 47be21ac9f10..fdcde9bbd788 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -69,7 +69,6 @@ void request_out_callback(lnet_event_t *ev) req->rq_req_unlink = 0; if (ev->type == LNET_EVENT_UNLINK || ev->status != 0) { - /* Failed send: make it seem like the reply timed out, just * like failing sends in client.c does currently... */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index cd94fed0ffdf..bf7b9d2aaa2b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -1001,7 +1001,6 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, return 0; } } else { - spin_lock(&imp->imp_lock); list_del(&imp->imp_conn_current->oic_item); list_add(&imp->imp_conn_current->oic_item, &imp->imp_conn_list); @@ -1370,7 +1369,6 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp) if (rc) goto out; } - } if (imp->imp_state == LUSTRE_IMP_REPLAY_WAIT) { @@ -1453,7 +1451,6 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose) back_to_sleep, LWI_ON_SIGNAL_NOOP, NULL); rc = l_wait_event(imp->imp_recovery_waitq, !ptlrpc_import_in_recovery(imp), &lwi); - } spin_lock(&imp->imp_lock); diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index a35b56ec687e..6dba4ee9ea46 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -1321,6 +1321,5 @@ int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer, up_read(&obd->u.cli.cl_sem); return count; - } EXPORT_SYMBOL(lprocfs_wr_pinger_recov); diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index 710fb806f122..99ff6e82871a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -1038,7 +1038,6 @@ static int nrs_policy_unregister_locked(struct ptlrpc_nrs_pol_desc *desc) LASSERT(mutex_is_locked(&ptlrpc_all_services_mutex)); list_for_each_entry(svc, &ptlrpc_all_services, srv_list) { - if (!nrs_policy_compatible(svc, desc) || unlikely(svc->srv_is_stopping)) continue; diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 492d63fad6f9..811acf6fc786 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1160,7 +1160,6 @@ __u32 lustre_msg_get_timeout(struct lustre_msg *msg) if (!pb) { CERROR("invalid msg %p: no ptlrpc body!\n", msg); return 0; - } return pb->pb_timeout; } @@ -1179,7 +1178,6 @@ __u32 lustre_msg_get_service_time(struct lustre_msg *msg) if (!pb) { CERROR("invalid msg %p: no ptlrpc body!\n", msg); return 0; - } return pb->pb_service_time; } @@ -1572,7 +1570,6 @@ static void lustre_swab_obdo(struct obdo *o) CLASSERT(offsetof(typeof(*o), o_padding_4) != 0); CLASSERT(offsetof(typeof(*o), o_padding_5) != 0); CLASSERT(offsetof(typeof(*o), o_padding_6) != 0); - } void lustre_swab_obd_statfs(struct obd_statfs *os) -- GitLab From 06d2fccd6b551be8c1efb8b37d01c511d2b3e905 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Tue, 12 Apr 2016 21:11:09 -0400 Subject: [PATCH 4660/9938] staging/lustre/llite: suppress non active IO error message Current CLIO does not support fadvise, suppress the error message. Signed-off-by: Bobi Jam Reviewed-on: http://review.whamcloud.com/9658 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4717 Reviewed-by: Jinshan Xiong Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/rw.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index fee319ce472d..4ddf8b360be0 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -111,16 +111,9 @@ struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) vio = vvp_env_io(env); io = vio->vui_cl.cis_io; lcc->lcc_io = io; - if (!io) { - struct inode *inode = file_inode(file); - - CERROR("%s: " DFID " no active IO, please file a ticket.\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode))); - dump_stack(); - + if (!io) result = -EIO; - } + if (result == 0 && vmpage) { struct cl_page *page; -- GitLab From 82281bc0c31ccd3a0733c678ad0f0a19ca59246d Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Tue, 12 Apr 2016 16:14:01 -0400 Subject: [PATCH 4661/9938] staging: lustre: osc: fix race issues thanks to oap_lock Fix 'data race condition' defects found by Coverity version 6.5.0: Data race condition (MISSING_LOCK) Accessing variable without holding lock. Elsewhere, this variable is accessed with lock held. This patch is dedicated to code fragments involving oap_lock. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2744 Reviewed-on: http://review.whamcloud.com/6572 Reviewed-by: Oleg Drokin Reviewed-by: Andreas Dilger Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_cache.c | 8 ++++++++ drivers/staging/lustre/lustre/osc/osc_io.c | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index de8c8255ce4f..8263a85495ac 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1147,7 +1147,9 @@ static int osc_extent_make_ready(const struct lu_env *env, last->oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE); LASSERT(last->oap_count > 0); LASSERT(last->oap_page_off + last->oap_count <= PAGE_SIZE); + spin_lock(&last->oap_lock); last->oap_async_flags |= ASYNC_COUNT_STABLE; + spin_unlock(&last->oap_lock); } /* for the rest of pages, we don't need to call osf_refresh_count() @@ -1156,7 +1158,9 @@ static int osc_extent_make_ready(const struct lu_env *env, list_for_each_entry(oap, &ext->oe_pages, oap_pending_item) { if (!(oap->oap_async_flags & ASYNC_COUNT_STABLE)) { oap->oap_count = PAGE_SIZE - oap->oap_page_off; + spin_lock(&last->oap_lock); oap->oap_async_flags |= ASYNC_COUNT_STABLE; + spin_unlock(&last->oap_lock); } } @@ -2327,6 +2331,10 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, oap->oap_cmd = cmd; oap->oap_page_off = ops->ops_from; oap->oap_count = ops->ops_to - ops->ops_from; + /* + * No need to hold a lock here, + * since this page is not in any list yet. + */ oap->oap_async_flags = 0; oap->oap_brw_flags = brw_flags; diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 9d67fca2bc59..d534b0e0edf6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -168,8 +168,10 @@ static int osc_io_submit(const struct lu_env *env, } cl_page_list_move(qout, qin, page); + spin_lock(&oap->oap_lock); oap->oap_async_flags = ASYNC_URGENT|ASYNC_READY; oap->oap_async_flags |= ASYNC_COUNT_STABLE; + spin_unlock(&oap->oap_lock); osc_page_submit(env, opg, crt, brw_flags); list_add_tail(&oap->oap_pending_item, &list); -- GitLab From 800548b1b1a71bb12e74bedae7a575b155ced851 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Tue, 12 Apr 2016 16:14:02 -0400 Subject: [PATCH 4662/9938] staging: lustre: clio: incorrect assertions in 'enable-invariants' Fixed several incorrect assumptions in 'enable-invariants'. Signed-off-by: Niu Yawei Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3521 Reviewed-on: http://review.whamcloud.com/6832 Reviewed-by: Bobi Jam Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/cl_page.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 39095e7a0a9d..b754f516e557 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -498,7 +498,7 @@ void cl_page_disown0(const struct lu_env *env, state = pg->cp_state; PINVRNT(env, pg, state == CPS_OWNED || state == CPS_FREEING); - PINVRNT(env, pg, cl_page_invariant(pg)); + PINVRNT(env, pg, cl_page_invariant(pg) || state == CPS_FREEING); cl_page_owner_clear(pg); if (state == CPS_OWNED) @@ -670,7 +670,8 @@ EXPORT_SYMBOL(cl_page_unassume); void cl_page_disown(const struct lu_env *env, struct cl_io *io, struct cl_page *pg) { - PINVRNT(env, pg, cl_page_is_owned(pg, io)); + PINVRNT(env, pg, cl_page_is_owned(pg, io) || + pg->cp_state == CPS_FREEING); io = cl_io_top(io); cl_page_disown0(env, io, pg); -- GitLab From 7e74e54f08294a81b82b686e86b9d784ad65a5f9 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Tue, 12 Apr 2016 16:14:03 -0400 Subject: [PATCH 4663/9938] staging: lustre: ldlm: Fix a race during FLock handling Protect against race where lock could have been just destroyed due to overlap, in ldlm_process_flock_lock(). Easy reproducer is BULL's NFS Locktests in pthread mode. (http://nfsv4.bullopensource.org/tools/tests/locktest.php) Signed-off-by: Bruno Faccini Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1126 Reviewed-on: http://review.whamcloud.com/7134 Reviewed-by: Oleg Drokin Reviewed-by: John L. Hammond Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 3f97e1ca7192..5102d782dc2e 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -520,11 +520,6 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) granted: OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT, 10); - if (lock->l_flags & LDLM_FL_DESTROYED) { - LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed"); - return 0; - } - if (lock->l_flags & LDLM_FL_FAILED) { LDLM_DEBUG(lock, "client-side enqueue waking up: failed"); return -EIO; @@ -534,6 +529,16 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) lock_res_and_lock(lock); + /* + * Protect against race where lock could have been just destroyed + * due to overlap in ldlm_process_flock_lock(). + */ + if (lock->l_flags & LDLM_FL_DESTROYED) { + unlock_res_and_lock(lock); + LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed"); + return 0; + } + /* ldlm_lock_enqueue() has already placed lock on the granted list. */ list_del_init(&lock->l_res_link); -- GitLab From e9ada6fa3c9e3dbd02eda3da4179b4d1417ef171 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Tue, 12 Apr 2016 16:14:04 -0400 Subject: [PATCH 4664/9938] staging: lustre: ldlm: refine LU-2665 patch for POSIX compliance Follow-on to patch introduced to fix LU-2665 ticket (Gerrit Change at http://review.whamcloud.com/6415 with Change-Id: I8faa331712abeadee46eabe111ee1c23a05840d5). Original patch introduced regressions against POSIX test suite (fcntl.18/fcntl.35 tests in LSB-VSX POSIX test suite at http://www.opengroup.org/testing/linux-test/lsb-vsx.html), so the idea is to only resend F_UNLCKs to have both LU-2665 bug and POSIX test suite happy. Signed-off-by: Bruno Faccini Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3701 Reviewed-on: http://review.whamcloud.com/7453 Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 9e970ab92887..3b1bc9111b93 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -869,7 +869,9 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, * (explicits or automatically generated by Kernel to clean * current FLocks upon exit) that can't be trashed */ - if ((rc == -EINTR) || (rc == -ETIMEDOUT)) + if (((rc == -EINTR) || (rc == -ETIMEDOUT)) && + (einfo->ei_type == LDLM_FLOCK) && + (einfo->ei_mode == LCK_NL)) goto resend; return rc; } -- GitLab From 96d61c247ec02518ba2ff453f71ee15feb522456 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Tue, 12 Apr 2016 16:14:05 -0400 Subject: [PATCH 4665/9938] staging: lustre: llite: variable rename in namei.c With the patch 6648 a fee variables were renamed. We do these renames in broken out patch to the fix obvious. Signed-off-by: Andrew Perepechko Reviewed-by: Alexander Boyko Reviewed-by: Vitaly Fertman Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3473 Xyratex-bug-id: MRP-1027 Reviewed-on: http://review.whamcloud.com/6648 Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/namei.c | 52 ++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 856170762ef7..73e61cfe9a7f 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -929,23 +929,23 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) * is any lock existing. They will recycle dentries and inodes based upon locks * too. b=20433 */ -static int ll_unlink(struct inode *dir, struct dentry *dentry) +static int ll_unlink(struct inode *dir, struct dentry *dchild) { struct ptlrpc_request *request = NULL; struct md_op_data *op_data; int rc; CDEBUG(D_VFSTRACE, "VFS Op:name=%pd,dir=%lu/%u(%p)\n", - dentry, dir->i_ino, dir->i_generation, dir); + dchild, dir->i_ino, dir->i_generation, dir); op_data = ll_prep_md_op_data(NULL, dir, NULL, - dentry->d_name.name, - dentry->d_name.len, + dchild->d_name.name, + dchild->d_name.len, 0, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) return PTR_ERR(op_data); - ll_get_child_fid(dentry, &op_data->op_fid3); + ll_get_child_fid(dchild, &op_data->op_fid3); op_data->op_fid2 = op_data->op_fid3; rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); ll_finish_md_op_data(op_data); @@ -979,23 +979,23 @@ static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) return err; } -static int ll_rmdir(struct inode *dir, struct dentry *dentry) +static int ll_rmdir(struct inode *dir, struct dentry *dchild) { struct ptlrpc_request *request = NULL; struct md_op_data *op_data; int rc; CDEBUG(D_VFSTRACE, "VFS Op:name=%pd,dir=%lu/%u(%p)\n", - dentry, dir->i_ino, dir->i_generation, dir); + dchild, dir->i_ino, dir->i_generation, dir); op_data = ll_prep_md_op_data(NULL, dir, NULL, - dentry->d_name.name, - dentry->d_name.len, + dchild->d_name.name, + dchild->d_name.len, S_IFDIR, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) return PTR_ERR(op_data); - ll_get_child_fid(dentry, &op_data->op_fid3); + ll_get_child_fid(dchild, &op_data->op_fid3); op_data->op_fid2 = op_data->op_fid3; rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); ll_finish_md_op_data(op_data); @@ -1058,42 +1058,42 @@ static int ll_link(struct dentry *old_dentry, struct inode *dir, return err; } -static int ll_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) +static int ll_rename(struct inode *src, struct dentry *src_dchild, + struct inode *tgt, struct dentry *tgt_dchild) { struct ptlrpc_request *request = NULL; - struct ll_sb_info *sbi = ll_i2sbi(old_dir); + struct ll_sb_info *sbi = ll_i2sbi(src); struct md_op_data *op_data; int err; CDEBUG(D_VFSTRACE, "VFS Op:oldname=%pd,src_dir=%lu/%u(%p),newname=%pd,tgt_dir=%lu/%u(%p)\n", - old_dentry, old_dir->i_ino, old_dir->i_generation, old_dir, - new_dentry, new_dir->i_ino, new_dir->i_generation, new_dir); + src_dchild, src->i_ino, src->i_generation, src, + tgt_dchild, tgt->i_ino, tgt->i_generation, tgt); - op_data = ll_prep_md_op_data(NULL, old_dir, new_dir, NULL, 0, 0, + op_data = ll_prep_md_op_data(NULL, src, tgt, NULL, 0, 0, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) return PTR_ERR(op_data); - ll_get_child_fid(old_dentry, &op_data->op_fid3); - ll_get_child_fid(new_dentry, &op_data->op_fid4); + ll_get_child_fid(src_dchild, &op_data->op_fid3); + ll_get_child_fid(tgt_dchild, &op_data->op_fid4); err = md_rename(sbi->ll_md_exp, op_data, - old_dentry->d_name.name, - old_dentry->d_name.len, - new_dentry->d_name.name, - new_dentry->d_name.len, &request); + src_dchild->d_name.name, + src_dchild->d_name.len, + tgt_dchild->d_name.name, + tgt_dchild->d_name.len, &request); ll_finish_md_op_data(op_data); if (!err) { - ll_update_times(request, old_dir); - ll_update_times(request, new_dir); + ll_update_times(request, src); + ll_update_times(request, tgt); ll_stats_ops_tally(sbi, LPROC_LL_RENAME, 1); - err = ll_objects_destroy(request, old_dir); + err = ll_objects_destroy(request, src); } ptlrpc_req_finished(request); if (!err) - d_move(old_dentry, new_dentry); + d_move(src_dchild, tgt_dchild); return err; } -- GitLab From 3c4b9d09729cb04070edb167c813884507f4e433 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Tue, 12 Apr 2016 16:14:06 -0400 Subject: [PATCH 4666/9938] staging: lustre: llite: speedup in unlink/rmdir Assume dchild argument is fully initialized in ->unlink and ->rmdir callbacks, so additional lookup for ELC is not needed. Signed-off-by: Andrew Perepechko Reviewed-by: Alexander Boyko Reviewed-by: Vitaly Fertman Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3473 Xyratex-bug-id: MRP-1027 Reviewed-on: http://review.whamcloud.com/6648 Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/namei.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 73e61cfe9a7f..9fa862b37547 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -847,12 +847,6 @@ static int ll_create_nd(struct inode *dir, struct dentry *dentry, return rc; } -static inline void ll_get_child_fid(struct dentry *child, struct lu_fid *fid) -{ - if (d_really_is_positive(child)) - *fid = *ll_inode2fid(d_inode(child)); -} - int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) { struct mdt_body *body; @@ -945,7 +939,9 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) if (IS_ERR(op_data)) return PTR_ERR(op_data); - ll_get_child_fid(dchild, &op_data->op_fid3); + if (dchild && dchild->d_inode) + op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); + op_data->op_fid2 = op_data->op_fid3; rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); ll_finish_md_op_data(op_data); @@ -995,7 +991,9 @@ static int ll_rmdir(struct inode *dir, struct dentry *dchild) if (IS_ERR(op_data)) return PTR_ERR(op_data); - ll_get_child_fid(dchild, &op_data->op_fid3); + if (dchild && dchild->d_inode) + op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); + op_data->op_fid2 = op_data->op_fid3; rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); ll_finish_md_op_data(op_data); @@ -1076,8 +1074,11 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild, if (IS_ERR(op_data)) return PTR_ERR(op_data); - ll_get_child_fid(src_dchild, &op_data->op_fid3); - ll_get_child_fid(tgt_dchild, &op_data->op_fid4); + if (src_dchild && src_dchild->d_inode) + op_data->op_fid3 = *ll_inode2fid(src_dchild->d_inode); + if (tgt_dchild && tgt_dchild->d_inode) + op_data->op_fid4 = *ll_inode2fid(tgt_dchild->d_inode); + err = md_rename(sbi->ll_md_exp, op_data, src_dchild->d_name.name, src_dchild->d_name.len, -- GitLab From 32cc01c42fc0fefaed58d22b4b1657f56e11f0fb Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 12 Apr 2016 16:14:07 -0400 Subject: [PATCH 4667/9938] staging: lustre: llite: error setting max_cache_mb at mount time The root cause is that when max_cache_mb conf parameter is applied, the client isn't connected to the OST yet so that sbi->ll_dt_exp is NULL. However, it's not necessary to shrink the cache memory in this case so success should be returned. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3676 Reviewed-on: http://review.whamcloud.com/7194 Reviewed-by: Andreas Dilger Reviewed-by: Bobi Jam Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/lproc_llite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 4a9f6693feba..501b93b82c06 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -460,8 +460,8 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, break; if (!sbi->ll_dt_exp) { /* being initialized */ - rc = -ENODEV; - break; + rc = 0; + goto out; } /* difficult - have to ask OSCs to drop LRU slots. */ -- GitLab From 489d82fcd8f39ad43a65d72abe9bf835a5af3f63 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Tue, 12 Apr 2016 16:14:08 -0400 Subject: [PATCH 4668/9938] staging: lustre: obd: MDT mount fails on MDS w/o MGS on it If we specify multiple --mgsnode for a MDT, when we start MDS upon it while MGS is no the other node, the MGC import connection will always select the local nid (which is one of the candidate mgsnode) since it think its the closest connection. This patch treats further --mgsnode nids as failover nids, so that multiple import connections are added for the MGC import. Signed-off-by: Bobi Jam Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3829 Reviewed-on: http://review.whamcloud.com/7509 Reviewed-by: Liang Zhen Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/obd_mount.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index d3e28a389ac1..9474aa902bd0 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -307,7 +307,8 @@ int lustre_start_mgc(struct super_block *sb) while (class_parse_nid(ptr, &nid, &ptr) == 0) { rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID, niduuid, NULL, NULL, NULL); - i++; + if (!rc) + i++; /* Stop at the first failover nid */ if (*ptr == ':') break; @@ -345,16 +346,18 @@ int lustre_start_mgc(struct super_block *sb) sprintf(niduuid, "%s_%x", mgcname, i); j = 0; while (class_parse_nid_quiet(ptr, &nid, &ptr) == 0) { - j++; - rc = do_lcfg(mgcname, nid, - LCFG_ADD_UUID, niduuid, NULL, NULL, NULL); + rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID, niduuid, + NULL, NULL, NULL); + if (!rc) + ++j; if (*ptr == ':') break; } if (j > 0) { rc = do_lcfg(mgcname, 0, LCFG_ADD_CONN, niduuid, NULL, NULL, NULL); - i++; + if (!rc) + i++; } else { /* at ":/fsname" */ break; -- GitLab From cc3b77589617b32c4fe610d9d6302a159f1fde13 Mon Sep 17 00:00:00 2001 From: Swapnil Pimpale Date: Tue, 12 Apr 2016 16:14:09 -0400 Subject: [PATCH 4669/9938] staging: lustre: ptlrpc: return a meaningful status from ptlrpcd_init() This patch has the following: 1) Fix for the return value from ptlrpcd_init(). It will now return a correct status instead of returning zero always. 2) ptlrpcd_addref() should not increment ptlrpcd_users on error. 3) Added code in a mdc_setup() and mgc_setup() to test the return value of ptlrpcd_addref() and return on error. Signed-off-by: Swapnil Pimpale Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3808 Reviewed-on: http://review.whamcloud.com/7522 Reviewed-by: John L. Hammond Reviewed-by: Andreas Dilger Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_request.c | 9 ++++++--- drivers/staging/lustre/lustre/mgc/mgc_request.c | 5 ++++- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c | 5 ++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 6023c2c1386b..5f1ac58c6fe2 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2314,12 +2314,14 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg) return -ENOMEM; mdc_init_rpc_lock(cli->cl_rpc_lock); - ptlrpcd_addref(); + rc = ptlrpcd_addref(); + if (rc < 0) + goto err_rpc_lock; cli->cl_close_lock = kzalloc(sizeof(*cli->cl_close_lock), GFP_NOFS); if (!cli->cl_close_lock) { rc = -ENOMEM; - goto err_rpc_lock; + goto err_ptlrpcd_decref; } mdc_init_rpc_lock(cli->cl_close_lock); @@ -2345,9 +2347,10 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg) err_close_lock: kfree(cli->cl_close_lock); +err_ptlrpcd_decref: + ptlrpcd_decref(); err_rpc_lock: kfree(cli->cl_rpc_lock); - ptlrpcd_decref(); return rc; } diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 0c3bd1648a88..933f6f628350 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -734,7 +734,9 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) struct task_struct *task; int rc; - ptlrpcd_addref(); + rc = ptlrpcd_addref(); + if (rc < 0) + goto err_noref; rc = client_obd_setup(obd, lcfg); if (rc) @@ -773,6 +775,7 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) client_obd_cleanup(obd); err_decref: ptlrpcd_decref(); +err_noref: return rc; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index dbc3376328cd..76a355a9db8b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -909,8 +909,11 @@ int ptlrpcd_addref(void) int rc = 0; mutex_lock(&ptlrpcd_mutex); - if (++ptlrpcd_users == 1) + if (++ptlrpcd_users == 1) { rc = ptlrpcd_init(); + if (rc < 0) + ptlrpcd_users--; + } mutex_unlock(&ptlrpcd_mutex); return rc; } -- GitLab From 1b1594da71c4286ce52009073ef0d7b6edc80ec5 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 12 Apr 2016 16:14:10 -0400 Subject: [PATCH 4670/9938] staging: lustre: llite: Truncate to restore file Truncate up is safe so it won't trigger restore. Copy optimization for truncate down - only copy the part under truncate length. If a file is truncated to zero usually it'll be followed by write so I choose to restore the file and set correct stripe information. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3817 Reviewed-on: http://review.whamcloud.com/7505 Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Henri Doreau Reviewed-by: Aurelien Degremont Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 5 +- .../lustre/lustre/llite/llite_internal.h | 2 +- .../staging/lustre/lustre/llite/llite_lib.c | 60 +++++++++---------- drivers/staging/lustre/lustre/llite/vvp_io.c | 5 +- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 9b553d2ab336..24fa24b5cd29 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3621,7 +3621,7 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) /** * This function send a restore request to the MDT */ -int ll_layout_restore(struct inode *inode) +int ll_layout_restore(struct inode *inode, loff_t offset, __u64 length) { struct hsm_user_request *hur; int len, rc; @@ -3637,7 +3637,8 @@ int ll_layout_restore(struct inode *inode) hur->hur_request.hr_flags = 0; memcpy(&hur->hur_user_item[0].hui_fid, &ll_i2info(inode)->lli_fid, sizeof(hur->hur_user_item[0].hui_fid)); - hur->hur_user_item[0].hui_extent.length = -1; + hur->hur_user_item[0].hui_extent.offset = offset; + hur->hur_user_item[0].hui_extent.length = length; hur->hur_request.hr_itemcount = 1; rc = obd_iocontrol(LL_IOC_HSM_REQUEST, ll_i2sbi(inode)->ll_md_exp, len, hur, NULL); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 2a11664325ef..22e998911018 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1377,7 +1377,7 @@ enum { int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf); int ll_layout_refresh(struct inode *inode, __u32 *gen); -int ll_layout_restore(struct inode *inode); +int ll_layout_restore(struct inode *inode, loff_t start, __u64 length); int ll_xattr_init(void); void ll_xattr_fini(void); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b0948a7b860b..9f338b161b50 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1266,14 +1266,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime), (s64)ktime_get_real_seconds()); - /* If we are changing file size, file content is modified, flag it. */ - if (attr->ia_valid & ATTR_SIZE) { - attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; - spin_lock(&lli->lli_lock); - lli->lli_flags |= LLIF_DATA_MODIFIED; - spin_unlock(&lli->lli_lock); - } - /* We always do an MDS RPC, even if we're only changing the size; * only the MDS knows whether truncate() should fail with -ETXTBUSY */ @@ -1285,13 +1277,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) if (!S_ISDIR(inode->i_mode)) inode_unlock(inode); - memcpy(&op_data->op_attr, attr, sizeof(*attr)); - - /* Open epoch for truncate. */ - if (exp_connect_som(ll_i2mdexp(inode)) && - (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) - op_data->op_flags = MF_EPOCH_OPEN; - /* truncate on a released file must failed with -ENODATA, * so size must not be set on MDS for released file * but other attributes must be set @@ -1305,29 +1290,40 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) if (lsm && lsm->lsm_pattern & LOV_PATTERN_F_RELEASED) file_is_released = true; ccc_inode_lsm_put(inode, lsm); + + if (!hsm_import && attr->ia_valid & ATTR_SIZE) { + if (file_is_released) { + rc = ll_layout_restore(inode, 0, attr->ia_size); + if (rc < 0) + goto out; + + file_is_released = false; + ll_layout_refresh(inode, &gen); + } + + /* + * If we are changing file size, file content is + * modified, flag it. + */ + attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + spin_lock(&lli->lli_lock); + lli->lli_flags |= LLIF_DATA_MODIFIED; + spin_unlock(&lli->lli_lock); + op_data->op_bias |= MDS_DATA_MODIFIED; + } } - /* if not in HSM import mode, clear size attr for released file - * we clear the attribute send to MDT in op_data, not the original - * received from caller in attr which is used later to - * decide return code - */ - if (file_is_released && (attr->ia_valid & ATTR_SIZE) && !hsm_import) - op_data->op_attr.ia_valid &= ~ATTR_SIZE; + memcpy(&op_data->op_attr, attr, sizeof(*attr)); + + /* Open epoch for truncate. */ + if (exp_connect_som(ll_i2mdexp(inode)) && !hsm_import && + (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) + op_data->op_flags = MF_EPOCH_OPEN; rc = ll_md_setattr(dentry, op_data, &mod); if (rc) goto out; - /* truncate failed (only when non HSM import), others succeed */ - if (file_is_released) { - if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) - rc = -ENODATA; - else - rc = 0; - goto out; - } - /* RPC to MDT is sent, cancel data modification flag */ if (op_data->op_bias & MDS_DATA_MODIFIED) { spin_lock(&lli->lli_lock); @@ -1336,7 +1332,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) } ll_ioepoch_open(lli, op_data->op_ioepoch); - if (!S_ISREG(inode->i_mode)) { + if (!S_ISREG(inode->i_mode) || file_is_released) { rc = 0; goto out; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 26dfbf1d2345..5bf9592ae5d2 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -294,6 +294,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; struct vvp_io *vio = cl2vvp_io(env, ios); + struct inode *inode = vvp_object_inode(obj); CLOBINVRNT(env, obj, vvp_object_invariant(obj)); @@ -309,7 +310,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) /* file was detected release, we need to restore it * before finishing the io */ - rc = ll_layout_restore(vvp_object_inode(obj)); + rc = ll_layout_restore(inode, 0, OBD_OBJECT_EOF); /* if restore registration failed, no restart, * we will return -ENODATA */ @@ -335,7 +336,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) __u32 gen = 0; /* check layout version */ - ll_layout_refresh(vvp_object_inode(obj), &gen); + ll_layout_refresh(inode, &gen); io->ci_need_restart = vio->vui_layout_gen != gen; if (io->ci_need_restart) { CDEBUG(D_VFSTRACE, -- GitLab From b59d812d0021b4f76adb05452a382898a6e225dc Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 12 Apr 2016 16:14:11 -0400 Subject: [PATCH 4671/9938] staging: lustre: osc: osc_extent_wait() shouldn't be interruptible Otherwise it will hit the assertion at cl_lock.c: cl_lock.c:1967:discard_cb()) ASSERTION( (!(page->cp_type == CPT_CACHEABLE) || (!PageWriteback(cl_page_vmpage(env, page)))) ) failed: This is because in osc_lock_flush() we have to make sure the IO is finished before discarding the pages. Signed-off-by: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2779 Reviewed-on: http://review.whamcloud.com/5419 Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 8263a85495ac..43d8bcc3dbdb 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -965,7 +965,7 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, "%s: wait ext to %d timedout, recovery in progress?\n", osc_export(obj)->exp_obd->obd_name, state); - lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + lwi = LWI_INTR(NULL, NULL); rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), &lwi); } -- GitLab From b3ffe666ca1a747ce399d7d0966a132235e40e66 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Tue, 12 Apr 2016 16:14:12 -0400 Subject: [PATCH 4672/9938] staging: lustre: lprocfs: implement log2 using bitops This patch implements log2 using fls. Signed-off-by: Andrew Perepechko Reviewed-by: Alexander Boyko Reviewed-by: alexander_zarochentsev@xyratex.com Reviewed-by: Vitaly Fertman Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3496 Xyratex-bug-id: MRP-999 Reviewed-on: http://review.whamcloud.com/6757 Reviewed-by: John L. Hammond Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lprocfs_status.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 9824c8868cdf..b2f309d97c85 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1472,10 +1472,10 @@ EXPORT_SYMBOL(lprocfs_oh_tally); void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value) { - unsigned int val; + unsigned int val = 0; - for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++) - ; + if (likely(value != 0)) + val = min(fls(value - 1), OBD_HIST_MAX); lprocfs_oh_tally(oh, val); } -- GitLab From ad1daf47c98f524ed6a517486a10e4114b450ff8 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Tue, 12 Apr 2016 16:14:13 -0400 Subject: [PATCH 4673/9938] staging: lustre: lov: return minimal FIEMAP for released files Since st_blocks = NULL is returned for released files, FIEMAP should at least return a minimal mapping to make users aware that file contains data but it is not immediately available. This will make coreutils and tools such tar happy and have them presume file is sparse. Also, add a new test_228 in sanity-hsm to verify it works for "[cp,tar] --sparse" commands. Also fix a LBUG ("lov_fiemap()) ASSERTION( fm_local ) failed") likely to occur when no-object/ENOMEM conditions and also now when released. Signed-off-by: Bruno Faccini Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3864 Reviewed-on: http://review.whamcloud.com/7584 Reviewed-by: Andreas Dilger Reviewed-by: Aurelien Degremont Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_obd.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 6d02914b198b..2de925556d3b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1732,6 +1732,27 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, unsigned int buffer_size = FIEMAP_BUFFER_SIZE; if (!lsm_has_objects(lsm)) { + if (lsm && lsm_is_released(lsm) && (fm_key->fiemap.fm_start < + fm_key->oa.o_size)) { + /* + * released file, return a minimal FIEMAP if + * request fits in file-size. + */ + fiemap->fm_mapped_extents = 1; + fiemap->fm_extents[0].fe_logical = + fm_key->fiemap.fm_start; + if (fm_key->fiemap.fm_start + fm_key->fiemap.fm_length < + fm_key->oa.o_size) { + fiemap->fm_extents[0].fe_length = + fm_key->fiemap.fm_length; + } else { + fiemap->fm_extents[0].fe_length = + fm_key->oa.o_size - fm_key->fiemap.fm_start; + fiemap->fm_extents[0].fe_flags |= + (FIEMAP_EXTENT_UNKNOWN | + FIEMAP_EXTENT_LAST); + } + } rc = 0; goto out; } -- GitLab From 554f0724af5bab4b263ff3c2f0324db79e868aae Mon Sep 17 00:00:00 2001 From: Andriy Skulysh Date: Tue, 12 Apr 2016 16:14:14 -0400 Subject: [PATCH 4674/9938] staging: lustre: lov: Don't wait for active target with OBD_STATFS_NODELAY Patch for LU-631 which was landed before the upstream merge broke OBD_STATFS_NODELAY behaviour. It adds unnecessary delay while running df command with inactive OSTs. We shouldn't try to recover connection to OST in this case. Signed-off-by: Andriy Skulysh Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4010 Reviewed-on: http://review.whamcloud.com/7762 Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_request.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 8226ab25790f..4d7073e7cef4 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -715,12 +715,15 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, struct lov_request *req; if (!lov->lov_tgts[i] || - (!lov_check_and_wait_active(lov, i) && - (oinfo->oi_flags & OBD_STATFS_NODELAY))) { + (oinfo->oi_flags & OBD_STATFS_NODELAY && + !lov->lov_tgts[i]->ltd_active)) { CDEBUG(D_HA, "lov idx %d inactive\n", i); continue; } + if (!lov->lov_tgts[i]->ltd_active) + lov_check_and_wait_active(lov, i); + /* skip targets that have been explicitly disabled by the * administrator */ -- GitLab From 1cc28b77798d48e31e5dc16cea4274eb52972fd4 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 12 Apr 2016 16:14:15 -0400 Subject: [PATCH 4675/9938] staging: lustre: hsm: permission checks for HSM ioctl operations In the LL_IOC_HSM_CT_START case of ll_dir_ioctl() require CAP_SYS_ADMIN, since the local handler for this ioctl may modify the global KUC table. Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3866 Reviewed-on: http://review.whamcloud.com/7565 Reviewed-by: Aurelien Degremont Reviewed-by: Faccini Bruno Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 1d5366b15a1b..b457c28d0a29 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1843,6 +1843,9 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return rc; } case LL_IOC_HSM_CT_START: + if (!capable(CFS_CAP_SYS_ADMIN)) + return -EPERM; + rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg, sizeof(struct lustre_kernelcomm)); return rc; -- GitLab From abe958236ff9f1a68becf4e1d27a6ceb8e10e2b7 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 12 Apr 2016 16:14:16 -0400 Subject: [PATCH 4676/9938] staging: lustre: hsm: don't use real suppgid In the MDC HSM handlers that do not pack a real suppgid, use -1 rather than 0 for the suppgid in mdt_body. Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3866 Reviewed-on: http://review.whamcloud.com/7565 Reviewed-by: Aurelien Degremont Reviewed-by: Faccini Bruno Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_request.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 5f1ac58c6fe2..46e3a7506703 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1169,7 +1169,7 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp, goto out; } - mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, 0, 0); + mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, -1, 0); /* Copy hsm_progress struct */ req_hpk = req_capsule_client_get(&req->rq_pill, &RMF_MDS_HSM_PROGRESS); @@ -1203,7 +1203,7 @@ static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archives) goto out; } - mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, 0, 0); + mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, -1, 0); /* Copy hsm_progress struct */ archive_mask = req_capsule_client_get(&req->rq_pill, @@ -1278,7 +1278,7 @@ static int mdc_ioc_hsm_ct_unregister(struct obd_import *imp) goto out; } - mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, 0, 0); + mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, -1, 0); ptlrpc_request_set_replen(req); @@ -1395,7 +1395,7 @@ static int mdc_ioc_hsm_request(struct obd_export *exp, return rc; } - mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, 0, 0); + mdc_pack_body(req, NULL, OBD_MD_FLRMTPERM, 0, -1, 0); /* Copy hsm_request struct */ req_hr = req_capsule_client_get(&req->rq_pill, &RMF_MDS_HSM_REQUEST); -- GitLab From 610cc3a49fdc563395bc3e65fa4a6aa8f97651eb Mon Sep 17 00:00:00 2001 From: Iban Rodriguez Date: Tue, 12 Apr 2016 23:08:34 +0200 Subject: [PATCH 4677/9938] Staging: lustre: Make lustre_profile_list static Variable lustre_profile_list is only used inside obd_config.c, better make it static Signed-off-by: Iban Rodriguez Acked-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/obd_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 318a2e3e72ab..ae3884423d1c 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -606,7 +606,7 @@ static int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg) return rc; } -LIST_HEAD(lustre_profile_list); +static LIST_HEAD(lustre_profile_list); struct lustre_profile *class_get_profile(const char *prof) { -- GitLab From 602364fdaaa6e7d78eac18332d3aca554190fdf4 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:48:56 +0100 Subject: [PATCH 4678/9938] usbip: vudc: Add header for USB/IP UDC Add header with definitions needed by vudc driver. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik [Some small improvements] Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc.h | 190 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 drivers/usb/usbip/vudc.h diff --git a/drivers/usb/usbip/vudc.h b/drivers/usb/usbip/vudc.h new file mode 100644 index 000000000000..847892339675 --- /dev/null +++ b/drivers/usb/usbip/vudc.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2015 Karol Kosik + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __USBIP_VUDC_H +#define __USBIP_VUDC_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usbip_common.h" + +#define GADGET_NAME "usbip-vudc" + +struct vep { + struct usb_ep ep; + unsigned type:2; /* type, as USB_ENDPOINT_XFER_* */ + char name[8]; /* space for ep name */ + + const struct usb_endpoint_descriptor *desc; + struct usb_gadget *gadget; + struct list_head req_queue; /* Request queue */ + unsigned halted:1; + unsigned wedged:1; + unsigned already_seen:1; + unsigned setup_stage:1; +}; + +struct vrequest { + struct usb_request req; + struct vudc *udc; + struct list_head req_entry; /* Request queue */ +}; + +struct urbp { + struct urb *urb; + struct vep *ep; + struct list_head urb_entry; /* urb queue */ + unsigned long seqnum; + unsigned type:2; /* for tx, since ep type can change after */ + unsigned new:1; +}; + +struct v_unlink { + unsigned long seqnum; + __u32 status; +}; + +enum tx_type { + TX_UNLINK, + TX_SUBMIT, +}; + +struct tx_item { + struct list_head tx_entry; + enum tx_type type; + union { + struct urbp *s; + struct v_unlink *u; + }; +}; + +enum tr_state { + VUDC_TR_RUNNING, + VUDC_TR_IDLE, + VUDC_TR_STOPPED, +}; + +struct transfer_timer { + struct timer_list timer; + enum tr_state state; + unsigned long frame_start; + int frame_limit; +}; + +struct vudc { + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + struct platform_device *pdev; + + struct usb_device_descriptor dev_desc; + + struct usbip_device ud; + struct transfer_timer tr_timer; + struct timeval start_time; + + struct list_head urb_queue; + + spinlock_t lock_tx; + struct list_head tx_queue; + wait_queue_head_t tx_waitq; + + spinlock_t lock; + struct vep *ep; + int address; + u16 devstatus; + + unsigned pullup:1; + unsigned connected:1; + unsigned desc_cached:1; +}; + +struct vudc_device { + struct platform_device *pdev; + struct list_head dev_entry; +}; + +extern const struct attribute_group vudc_attr_group; + +/* visible everywhere */ + +static inline struct vep *to_vep(struct usb_ep *_ep) +{ + return container_of(_ep, struct vep, ep); +} + +static inline struct vrequest *to_vrequest( + struct usb_request *_req) +{ + return container_of(_req, struct vrequest, req); +} + +static inline struct vudc *usb_gadget_to_vudc( + struct usb_gadget *_gadget) +{ + return container_of(_gadget, struct vudc, gadget); +} + +static inline struct vudc *ep_to_vudc(struct vep *ep) +{ + return container_of(ep->gadget, struct vudc, gadget); +} + +/* vudc_sysfs.c */ + +int get_gadget_descs(struct vudc *udc); + +/* vudc_tx.c */ + +int v_tx_loop(void *data); +void v_enqueue_ret_unlink(struct vudc *udc, __u32 seqnum, __u32 status); +void v_enqueue_ret_submit(struct vudc *udc, struct urbp *urb_p); + +/* vudc_rx.c */ + +int v_rx_loop(void *data); + +/* vudc_transfer.c */ + +void v_init_timer(struct vudc *udc); +void v_start_timer(struct vudc *udc); +void v_kick_timer(struct vudc *udc, unsigned long time); +void v_stop_timer(struct vudc *udc); + +/* vudc_dev.c */ + +struct urbp *alloc_urbp(void); +void free_urbp_and_urb(struct urbp *urb_p); + +struct vep *find_endpoint(struct vudc *udc, u8 address); + +struct vudc_device *alloc_vudc_device(int devid); +void put_vudc_device(struct vudc_device *udc_dev); + +int vudc_probe(struct platform_device *pdev); +int vudc_remove(struct platform_device *pdev); + +#endif /* __USBIP_VUDC_H */ -- GitLab From c7af4c221878ad684f0412eba2a1f18fa126c6d5 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:48:57 +0100 Subject: [PATCH 4679/9938] usbip: vudc: Make usbip_common vudc-aware Add constants for VUDC events in usbip_common.h and make use of them in usbip_common.c. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik [Small fixes and commit message update] Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/usbip_common.c | 10 ++++++---- drivers/usb/usbip/usbip_common.h | 10 ++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c index 2e5cf6392a8e..8b232290be6b 100644 --- a/drivers/usb/usbip/usbip_common.c +++ b/drivers/usb/usbip/usbip_common.c @@ -1,5 +1,7 @@ /* * Copyright (C) 2003-2008 Takahiro Hirofuchi + * Copyright (C) 2015-2016 Samsung Electronics + * Krzysztof Opasiak * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -643,7 +645,7 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) ret); kfree(buff); - if (ud->side == USBIP_STUB) + if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); else usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); @@ -665,7 +667,7 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) "total length of iso packets %d not equal to actual length of buffer %d\n", total_length, urb->actual_length); - if (ud->side == USBIP_STUB) + if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); else usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); @@ -723,7 +725,7 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) int ret; int size; - if (ud->side == USBIP_STUB) { + if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) { /* the direction of urb must be OUT. */ if (usb_pipein(urb->pipe)) return 0; @@ -755,7 +757,7 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); if (ret != size) { dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); - if (ud->side == USBIP_STUB) { + if (ud->side == USBIP_STUB || ud->side == USBIP_VUDC) { usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); } else { usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h index 2fbbc643b888..c7508cbce3ce 100644 --- a/drivers/usb/usbip/usbip_common.h +++ b/drivers/usb/usbip/usbip_common.h @@ -1,5 +1,7 @@ /* * Copyright (C) 2003-2008 Takahiro Hirofuchi + * Copyright (C) 2015-2016 Samsung Electronics + * Krzysztof Opasiak * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -234,6 +236,7 @@ struct usbip_iso_packet_descriptor { enum usbip_side { USBIP_VHCI, USBIP_STUB, + USBIP_VUDC, }; /* event handler */ @@ -248,6 +251,13 @@ enum usbip_side { #define SDEV_EVENT_ERROR_SUBMIT (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) #define SDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) +#define VUDC_EVENT_REMOVED (USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE) +#define VUDC_EVENT_DOWN (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) +#define VUDC_EVENT_ERROR_TCP (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) +/* catastrophic emulated usb error */ +#define VUDC_EVENT_ERROR_USB (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) +#define VUDC_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) + #define VDEV_EVENT_REMOVED (USBIP_EH_SHUTDOWN | USBIP_EH_BYE) #define VDEV_EVENT_DOWN (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) #define VDEV_EVENT_ERROR_TCP (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) -- GitLab From 80fd9cd52de6a5fb263b3bdcb8bd8982dc50a070 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:48:58 +0100 Subject: [PATCH 4680/9938] usbip: vudc: Add VUDC main file Add main vudc module file. This allows us to register suitable platform device and driver (just like dummy_hcd does). Currently number of vudc instances is determined using module parameter but whole infrastructure is suitable to make vudc creation dynamic (for example via configfs). This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik [Various bug fixes and commit message update] Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_main.c | 113 ++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 drivers/usb/usbip/vudc_main.c diff --git a/drivers/usb/usbip/vudc_main.c b/drivers/usb/usbip/vudc_main.c new file mode 100644 index 000000000000..9e655714e389 --- /dev/null +++ b/drivers/usb/usbip/vudc_main.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2015 Karol Kosik + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "vudc.h" + +static unsigned int vudc_number = 1; + +module_param_named(num, vudc_number, uint, S_IRUGO); +MODULE_PARM_DESC(num, "number of emulated controllers"); + +static struct platform_driver vudc_driver = { + .probe = vudc_probe, + .remove = vudc_remove, + .driver = { + .name = GADGET_NAME, + }, +}; + +static struct list_head vudc_devices = LIST_HEAD_INIT(vudc_devices); + +static int __init init(void) +{ + int retval = -ENOMEM; + int i; + struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL; + + if (usb_disabled()) + return -ENODEV; + + if (vudc_number < 1) { + pr_err("Number of emulated UDC must be no less than 1"); + return -EINVAL; + } + + retval = platform_driver_register(&vudc_driver); + if (retval < 0) + goto out; + + for (i = 0; i < vudc_number; i++) { + udc_dev = alloc_vudc_device(i); + if (!udc_dev) { + retval = -ENOMEM; + goto cleanup; + } + + retval = platform_device_add(udc_dev->pdev); + if (retval < 0) { + put_vudc_device(udc_dev); + goto cleanup; + } + + list_add_tail(&udc_dev->dev_entry, &vudc_devices); + if (!platform_get_drvdata(udc_dev->pdev)) { + /* + * The udc was added successfully but its probe + * function failed for some reason. + */ + retval = -EINVAL; + goto cleanup; + } + } + goto out; + +cleanup: + list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) { + list_del(&udc_dev->dev_entry); + platform_device_del(udc_dev->pdev); + put_vudc_device(udc_dev); + } + + platform_driver_unregister(&vudc_driver); +out: + return retval; +} +module_init(init); + +static void __exit cleanup(void) +{ + struct vudc_device *udc_dev = NULL, *udc_dev2 = NULL; + + list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) { + list_del(&udc_dev->dev_entry); + platform_device_unregister(udc_dev->pdev); + put_vudc_device(udc_dev); + } + platform_driver_unregister(&vudc_driver); +} +module_exit(cleanup); + +MODULE_DESCRIPTION("USB over IP Device Controller"); +MODULE_AUTHOR("Krzysztof Opasiak, Karol Kosik, Igor Kotrasinski"); +MODULE_LICENSE("GPL"); -- GitLab From 79c02cb1fd5c1fc8af16d18294804acc5dbfdee2 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:48:59 +0100 Subject: [PATCH 4681/9938] usbip: vudc: Add vudc_rx Add functions which allows to receive urbs from the client. It receives traffic in a loop in a separate thread. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_rx.c | 234 ++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 drivers/usb/usbip/vudc_rx.c diff --git a/drivers/usb/usbip/vudc_rx.c b/drivers/usb/usbip/vudc_rx.c new file mode 100644 index 000000000000..0b7abbc3f13b --- /dev/null +++ b/drivers/usb/usbip/vudc_rx.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2015 Karol Kosik + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "usbip_common.h" +#include "vudc.h" + +static int alloc_urb_from_cmd(struct urb **urbp, + struct usbip_header *pdu, u8 type) +{ + struct urb *urb; + + if (type == USB_ENDPOINT_XFER_ISOC) + urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, + GFP_KERNEL); + else + urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!urb) + goto err; + + usbip_pack_pdu(pdu, urb, USBIP_CMD_SUBMIT, 0); + + if (urb->transfer_buffer_length > 0) { + urb->transfer_buffer = kzalloc(urb->transfer_buffer_length, + GFP_KERNEL); + if (!urb->transfer_buffer) + goto free_urb; + } + + urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8, + GFP_KERNEL); + if (!urb->setup_packet) + goto free_buffer; + + /* + * FIXME - we only setup pipe enough for usbip functions + * to behave nicely + */ + urb->pipe |= pdu->base.direction == USBIP_DIR_IN ? + USB_DIR_IN : USB_DIR_OUT; + + *urbp = urb; + return 0; + +free_buffer: + kfree(urb->transfer_buffer); + urb->transfer_buffer = NULL; +free_urb: + usb_free_urb(urb); +err: + return -ENOMEM; +} + +static int v_recv_cmd_unlink(struct vudc *udc, + struct usbip_header *pdu) +{ + unsigned long flags; + struct urbp *urb_p; + + spin_lock_irqsave(&udc->lock, flags); + list_for_each_entry(urb_p, &udc->urb_queue, urb_entry) { + if (urb_p->seqnum != pdu->u.cmd_unlink.seqnum) + continue; + urb_p->urb->unlinked = -ECONNRESET; + urb_p->seqnum = pdu->base.seqnum; + v_kick_timer(udc, jiffies); + spin_unlock_irqrestore(&udc->lock, flags); + return 0; + } + /* Not found, completed / not queued */ + spin_lock(&udc->lock_tx); + v_enqueue_ret_unlink(udc, pdu->base.seqnum, 0); + wake_up(&udc->tx_waitq); + spin_unlock(&udc->lock_tx); + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static int v_recv_cmd_submit(struct vudc *udc, + struct usbip_header *pdu) +{ + int ret = 0; + struct urbp *urb_p; + u8 address; + unsigned long flags; + + urb_p = alloc_urbp(); + if (!urb_p) { + usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_MALLOC); + return -ENOMEM; + } + + /* base.ep is pipeendpoint(pipe) */ + address = pdu->base.ep; + if (pdu->base.direction == USBIP_DIR_IN) + address |= USB_DIR_IN; + + spin_lock_irq(&udc->lock); + urb_p->ep = find_endpoint(udc, address); + if (!urb_p->ep) { + /* we don't know the type, there may be isoc data! */ + dev_err(&udc->pdev->dev, "request to nonexistent endpoint"); + spin_unlock_irq(&udc->lock); + usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_TCP); + ret = -EPIPE; + goto free_urbp; + } + urb_p->type = urb_p->ep->type; + spin_unlock_irq(&udc->lock); + + urb_p->new = 1; + urb_p->seqnum = pdu->base.seqnum; + + ret = alloc_urb_from_cmd(&urb_p->urb, pdu, urb_p->ep->type); + if (ret) { + usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_MALLOC); + ret = -ENOMEM; + goto free_urbp; + } + + urb_p->urb->status = -EINPROGRESS; + + /* FIXME: more pipe setup to please usbip_common */ + urb_p->urb->pipe &= ~(11 << 30); + switch (urb_p->ep->type) { + case USB_ENDPOINT_XFER_BULK: + urb_p->urb->pipe |= (PIPE_BULK << 30); + break; + case USB_ENDPOINT_XFER_INT: + urb_p->urb->pipe |= (PIPE_INTERRUPT << 30); + break; + case USB_ENDPOINT_XFER_CONTROL: + urb_p->urb->pipe |= (PIPE_CONTROL << 30); + break; + case USB_ENDPOINT_XFER_ISOC: + urb_p->urb->pipe |= (PIPE_ISOCHRONOUS << 30); + break; + } + ret = usbip_recv_xbuff(&udc->ud, urb_p->urb); + if (ret < 0) + goto free_urbp; + + ret = usbip_recv_iso(&udc->ud, urb_p->urb); + if (ret < 0) + goto free_urbp; + + spin_lock_irqsave(&udc->lock, flags); + v_kick_timer(udc, jiffies); + list_add_tail(&urb_p->urb_entry, &udc->urb_queue); + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; + +free_urbp: + free_urbp_and_urb(urb_p); + return ret; +} + +static int v_rx_pdu(struct usbip_device *ud) +{ + int ret; + struct usbip_header pdu; + struct vudc *udc = container_of(ud, struct vudc, ud); + + memset(&pdu, 0, sizeof(pdu)); + ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu)); + if (ret != sizeof(pdu)) { + usbip_event_add(ud, VUDC_EVENT_ERROR_TCP); + if (ret >= 0) + return -EPIPE; + return ret; + } + usbip_header_correct_endian(&pdu, 0); + + spin_lock_irq(&ud->lock); + ret = (ud->status == SDEV_ST_USED); + spin_unlock_irq(&ud->lock); + if (!ret) { + usbip_event_add(ud, VUDC_EVENT_ERROR_TCP); + return -EBUSY; + } + + switch (pdu.base.command) { + case USBIP_CMD_UNLINK: + ret = v_recv_cmd_unlink(udc, &pdu); + break; + case USBIP_CMD_SUBMIT: + ret = v_recv_cmd_submit(udc, &pdu); + break; + default: + ret = -EPIPE; + pr_err("rx: unknown command"); + break; + } + return ret; +} + +int v_rx_loop(void *data) +{ + struct usbip_device *ud = data; + int ret = 0; + + while (!kthread_should_stop()) { + if (usbip_event_happened(ud)) + break; + ret = v_rx_pdu(ud); + if (ret < 0) { + pr_warn("v_rx exit with error %d", ret); + break; + } + } + return ret; +} -- GitLab From abdb2957432242de09ad52d044b5221a4b56c15a Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:49:00 +0100 Subject: [PATCH 4682/9938] usbip: vudc: Add vudc_transfer This file contains a function that simulates USB traffic, based on the one in dummy_hcd. Is also handles udc-directed control requests, and contains functions for setting up and controlling a timer for the emulation. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_transfer.c | 506 ++++++++++++++++++++++++++++++ 1 file changed, 506 insertions(+) create mode 100644 drivers/usb/usbip/vudc_transfer.c diff --git a/drivers/usb/usbip/vudc_transfer.c b/drivers/usb/usbip/vudc_transfer.c new file mode 100644 index 000000000000..5ccde5295041 --- /dev/null +++ b/drivers/usb/usbip/vudc_transfer.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2015 Karol Kosik + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * + * Based on dummy_hcd.c, which is: + * Copyright (C) 2003 David Brownell + * Copyright (C) 2003-2005 Alan Stern + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "vudc.h" + +#define DEV_REQUEST (USB_TYPE_STANDARD | USB_RECIP_DEVICE) +#define DEV_INREQUEST (DEV_REQUEST | USB_DIR_IN) +#define INTF_REQUEST (USB_TYPE_STANDARD | USB_RECIP_INTERFACE) +#define INTF_INREQUEST (INTF_REQUEST | USB_DIR_IN) +#define EP_REQUEST (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT) +#define EP_INREQUEST (EP_REQUEST | USB_DIR_IN) + +static int get_frame_limit(enum usb_device_speed speed) +{ + switch (speed) { + case USB_SPEED_LOW: + return 8 /*bytes*/ * 12 /*packets*/; + case USB_SPEED_FULL: + return 64 /*bytes*/ * 19 /*packets*/; + case USB_SPEED_HIGH: + return 512 /*bytes*/ * 13 /*packets*/ * 8 /*uframes*/; + case USB_SPEED_SUPER: + /* Bus speed is 500000 bytes/ms, so use a little less */ + return 490000; + default: + /* error */ + return -1; + } + +} + +/* + * handle_control_request() - handles all control transfers + * @udc: pointer to vudc + * @urb: the urb request to handle + * @setup: pointer to the setup data for a USB device control + * request + * @status: pointer to request handling status + * + * Return 0 - if the request was handled + * 1 - if the request wasn't handles + * error code on error + * + * Adapted from drivers/usb/gadget/udc/dummy_hcd.c + */ +static int handle_control_request(struct vudc *udc, struct urb *urb, + struct usb_ctrlrequest *setup, + int *status) +{ + struct vep *ep2; + int ret_val = 1; + unsigned w_index; + unsigned w_value; + + w_index = le16_to_cpu(setup->wIndex); + w_value = le16_to_cpu(setup->wValue); + switch (setup->bRequest) { + case USB_REQ_SET_ADDRESS: + if (setup->bRequestType != DEV_REQUEST) + break; + udc->address = w_value; + ret_val = 0; + *status = 0; + break; + case USB_REQ_SET_FEATURE: + if (setup->bRequestType == DEV_REQUEST) { + ret_val = 0; + switch (w_value) { + case USB_DEVICE_REMOTE_WAKEUP: + break; + case USB_DEVICE_B_HNP_ENABLE: + udc->gadget.b_hnp_enable = 1; + break; + case USB_DEVICE_A_HNP_SUPPORT: + udc->gadget.a_hnp_support = 1; + break; + case USB_DEVICE_A_ALT_HNP_SUPPORT: + udc->gadget.a_alt_hnp_support = 1; + break; + default: + ret_val = -EOPNOTSUPP; + } + if (ret_val == 0) { + udc->devstatus |= (1 << w_value); + *status = 0; + } + } else if (setup->bRequestType == EP_REQUEST) { + /* endpoint halt */ + ep2 = find_endpoint(udc, w_index); + if (!ep2 || ep2->ep.name == udc->ep[0].ep.name) { + ret_val = -EOPNOTSUPP; + break; + } + ep2->halted = 1; + ret_val = 0; + *status = 0; + } + break; + case USB_REQ_CLEAR_FEATURE: + if (setup->bRequestType == DEV_REQUEST) { + ret_val = 0; + switch (w_value) { + case USB_DEVICE_REMOTE_WAKEUP: + w_value = USB_DEVICE_REMOTE_WAKEUP; + break; + + case USB_DEVICE_U1_ENABLE: + case USB_DEVICE_U2_ENABLE: + case USB_DEVICE_LTM_ENABLE: + ret_val = -EOPNOTSUPP; + break; + default: + ret_val = -EOPNOTSUPP; + break; + } + if (ret_val == 0) { + udc->devstatus &= ~(1 << w_value); + *status = 0; + } + } else if (setup->bRequestType == EP_REQUEST) { + /* endpoint halt */ + ep2 = find_endpoint(udc, w_index); + if (!ep2) { + ret_val = -EOPNOTSUPP; + break; + } + if (!ep2->wedged) + ep2->halted = 0; + ret_val = 0; + *status = 0; + } + break; + case USB_REQ_GET_STATUS: + if (setup->bRequestType == DEV_INREQUEST + || setup->bRequestType == INTF_INREQUEST + || setup->bRequestType == EP_INREQUEST) { + char *buf; + /* + * device: remote wakeup, selfpowered + * interface: nothing + * endpoint: halt + */ + buf = (char *)urb->transfer_buffer; + if (urb->transfer_buffer_length > 0) { + if (setup->bRequestType == EP_INREQUEST) { + ep2 = find_endpoint(udc, w_index); + if (!ep2) { + ret_val = -EOPNOTSUPP; + break; + } + buf[0] = ep2->halted; + } else if (setup->bRequestType == + DEV_INREQUEST) { + buf[0] = (u8)udc->devstatus; + } else + buf[0] = 0; + } + if (urb->transfer_buffer_length > 1) + buf[1] = 0; + urb->actual_length = min_t(u32, 2, + urb->transfer_buffer_length); + ret_val = 0; + *status = 0; + } + break; + } + return ret_val; +} + +/* Adapted from dummy_hcd.c ; caller must hold lock */ +static int transfer(struct vudc *udc, + struct urb *urb, struct vep *ep, int limit) +{ + struct vrequest *req; + int sent = 0; +top: + /* if there's no request queued, the device is NAKing; return */ + list_for_each_entry(req, &ep->req_queue, req_entry) { + unsigned host_len, dev_len, len; + void *ubuf_pos, *rbuf_pos; + int is_short, to_host; + int rescan = 0; + + /* + * 1..N packets of ep->ep.maxpacket each ... the last one + * may be short (including zero length). + * + * writer can send a zlp explicitly (length 0) or implicitly + * (length mod maxpacket zero, and 'zero' flag); they always + * terminate reads. + */ + host_len = urb->transfer_buffer_length - urb->actual_length; + dev_len = req->req.length - req->req.actual; + len = min(host_len, dev_len); + + to_host = usb_pipein(urb->pipe); + if (unlikely(len == 0)) + is_short = 1; + else { + /* send multiple of maxpacket first, then remainder */ + if (len >= ep->ep.maxpacket) { + is_short = 0; + if (len % ep->ep.maxpacket > 0) + rescan = 1; + len -= len % ep->ep.maxpacket; + } else { + is_short = 1; + } + + ubuf_pos = urb->transfer_buffer + urb->actual_length; + rbuf_pos = req->req.buf + req->req.actual; + + if (urb->pipe & USB_DIR_IN) + memcpy(ubuf_pos, rbuf_pos, len); + else + memcpy(rbuf_pos, ubuf_pos, len); + + urb->actual_length += len; + req->req.actual += len; + sent += len; + } + + /* + * short packets terminate, maybe with overflow/underflow. + * it's only really an error to write too much. + * + * partially filling a buffer optionally blocks queue advances + * (so completion handlers can clean up the queue) but we don't + * need to emulate such data-in-flight. + */ + if (is_short) { + if (host_len == dev_len) { + req->req.status = 0; + urb->status = 0; + } else if (to_host) { + req->req.status = 0; + if (dev_len > host_len) + urb->status = -EOVERFLOW; + else + urb->status = 0; + } else { + urb->status = 0; + if (host_len > dev_len) + req->req.status = -EOVERFLOW; + else + req->req.status = 0; + } + + /* many requests terminate without a short packet */ + /* also check if we need to send zlp */ + } else { + if (req->req.length == req->req.actual) { + if (req->req.zero && to_host) + rescan = 1; + else + req->req.status = 0; + } + if (urb->transfer_buffer_length == urb->actual_length) { + if (urb->transfer_flags & URB_ZERO_PACKET && + !to_host) + rescan = 1; + else + urb->status = 0; + } + } + + /* device side completion --> continuable */ + if (req->req.status != -EINPROGRESS) { + + list_del_init(&req->req_entry); + spin_unlock(&udc->lock); + usb_gadget_giveback_request(&ep->ep, &req->req); + spin_lock(&udc->lock); + + /* requests might have been unlinked... */ + rescan = 1; + } + + /* host side completion --> terminate */ + if (urb->status != -EINPROGRESS) + break; + + /* rescan to continue with any other queued i/o */ + if (rescan) + goto top; + } + return sent; +} + +static void v_timer(unsigned long _vudc) +{ + struct vudc *udc = (struct vudc *) _vudc; + struct transfer_timer *timer = &udc->tr_timer; + struct urbp *urb_p, *tmp; + unsigned long flags; + struct usb_ep *_ep; + struct vep *ep; + int ret = 0; + int total, limit; + + spin_lock_irqsave(&udc->lock, flags); + + total = get_frame_limit(udc->gadget.speed); + if (total < 0) { /* unknown speed, or not set yet */ + timer->state = VUDC_TR_IDLE; + spin_unlock_irqrestore(&udc->lock, flags); + return; + } + /* is it next frame now? */ + if (time_after(jiffies, timer->frame_start + msecs_to_jiffies(1))) { + timer->frame_limit = total; + /* FIXME: how to make it accurate? */ + timer->frame_start = jiffies; + } else { + total = timer->frame_limit; + } + + list_for_each_entry(_ep, &udc->gadget.ep_list, ep_list) { + ep = to_vep(_ep); + ep->already_seen = 0; + } + +restart: + list_for_each_entry_safe(urb_p, tmp, &udc->urb_queue, urb_entry) { + struct urb *urb = urb_p->urb; + + ep = urb_p->ep; + if (urb->unlinked) + goto return_urb; + if (timer->state != VUDC_TR_RUNNING) + continue; + + if (!ep) { + urb->status = -EPROTO; + goto return_urb; + } + + /* Used up bandwidth? */ + if (total <= 0 && ep->type == USB_ENDPOINT_XFER_BULK) + continue; + + if (ep->already_seen) + continue; + ep->already_seen = 1; + if (ep == &udc->ep[0] && urb_p->new) { + ep->setup_stage = 1; + urb_p->new = 0; + } + if (ep->halted && !ep->setup_stage) { + urb->status = -EPIPE; + goto return_urb; + } + + if (ep == &udc->ep[0] && ep->setup_stage) { + /* TODO - flush any stale requests */ + ep->setup_stage = 0; + ep->halted = 0; + + ret = handle_control_request(udc, urb, + (struct usb_ctrlrequest *) urb->setup_packet, + (&urb->status)); + if (ret > 0) { + spin_unlock(&udc->lock); + ret = udc->driver->setup(&udc->gadget, + (struct usb_ctrlrequest *) + urb->setup_packet); + spin_lock(&udc->lock); + } + if (ret >= 0) { + /* no delays (max 64kb data stage) */ + limit = 64 * 1024; + goto treat_control_like_bulk; + } else { + urb->status = -EPIPE; + urb->actual_length = 0; + goto return_urb; + } + } + + limit = total; + switch (ep->type) { + case USB_ENDPOINT_XFER_ISOC: + /* TODO: support */ + urb->status = -EXDEV; + break; + + case USB_ENDPOINT_XFER_INT: + /* + * TODO: figure out bandwidth guarantees + * for now, give unlimited bandwidth + */ + limit += urb->transfer_buffer_length; + /* fallthrough */ + default: +treat_control_like_bulk: + total -= transfer(udc, urb, ep, limit); + } + if (urb->status == -EINPROGRESS) + continue; + +return_urb: + if (ep) + ep->already_seen = ep->setup_stage = 0; + + spin_lock(&udc->lock_tx); + list_del(&urb_p->urb_entry); + if (!urb->unlinked) { + v_enqueue_ret_submit(udc, urb_p); + } else { + v_enqueue_ret_unlink(udc, urb_p->seqnum, + urb->unlinked); + free_urbp_and_urb(urb_p); + } + wake_up(&udc->tx_waitq); + spin_unlock(&udc->lock_tx); + + goto restart; + } + + /* TODO - also wait on empty usb_request queues? */ + if (list_empty(&udc->urb_queue)) + timer->state = VUDC_TR_IDLE; + else + mod_timer(&timer->timer, + timer->frame_start + msecs_to_jiffies(1)); + + spin_unlock_irqrestore(&udc->lock, flags); +} + +/* All timer functions are run with udc->lock held */ + +void v_init_timer(struct vudc *udc) +{ + struct transfer_timer *t = &udc->tr_timer; + + setup_timer(&t->timer, v_timer, (unsigned long) udc); + t->state = VUDC_TR_STOPPED; +} + +void v_start_timer(struct vudc *udc) +{ + struct transfer_timer *t = &udc->tr_timer; + + dev_dbg(&udc->pdev->dev, "timer start"); + switch (t->state) { + case VUDC_TR_RUNNING: + return; + case VUDC_TR_IDLE: + return v_kick_timer(udc, jiffies); + case VUDC_TR_STOPPED: + t->state = VUDC_TR_IDLE; + t->frame_start = jiffies; + t->frame_limit = get_frame_limit(udc->gadget.speed); + return v_kick_timer(udc, jiffies); + } +} + +void v_kick_timer(struct vudc *udc, unsigned long time) +{ + struct transfer_timer *t = &udc->tr_timer; + + dev_dbg(&udc->pdev->dev, "timer kick"); + switch (t->state) { + case VUDC_TR_RUNNING: + return; + case VUDC_TR_IDLE: + t->state = VUDC_TR_RUNNING; + /* fallthrough */ + case VUDC_TR_STOPPED: + /* we may want to kick timer to unqueue urbs */ + mod_timer(&t->timer, time); + } +} + +void v_stop_timer(struct vudc *udc) +{ + struct transfer_timer *t = &udc->tr_timer; + + /* timer itself will take care of stopping */ + dev_dbg(&udc->pdev->dev, "timer stop"); + t->state = VUDC_TR_STOPPED; +} -- GitLab From d62ba981a9de7e2999b850fb8ff274da2a9387c5 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:49:01 +0100 Subject: [PATCH 4683/9938] usbip: vudc: Add vudc_tx This file contains functions for returning requests to the client. It also has functions that add requests completed in vudc_rx and vudc_transfer to the return queue. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_tx.c | 289 ++++++++++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 drivers/usb/usbip/vudc_tx.c diff --git a/drivers/usb/usbip/vudc_tx.c b/drivers/usb/usbip/vudc_tx.c new file mode 100644 index 000000000000..234661782fa0 --- /dev/null +++ b/drivers/usb/usbip/vudc_tx.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2015 Karol Kosik + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "usbip_common.h" +#include "vudc.h" + +static inline void setup_base_pdu(struct usbip_header_basic *base, + __u32 command, __u32 seqnum) +{ + base->command = command; + base->seqnum = seqnum; + base->devid = 0; + base->ep = 0; + base->direction = 0; +} + +static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urbp *urb_p) +{ + setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, urb_p->seqnum); + usbip_pack_pdu(rpdu, urb_p->urb, USBIP_RET_SUBMIT, 1); +} + +static void setup_ret_unlink_pdu(struct usbip_header *rpdu, + struct v_unlink *unlink) +{ + setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum); + rpdu->u.ret_unlink.status = unlink->status; +} + +static int v_send_ret_unlink(struct vudc *udc, struct v_unlink *unlink) +{ + struct msghdr msg; + struct kvec iov[1]; + size_t txsize; + + int ret; + struct usbip_header pdu_header; + + txsize = 0; + memset(&pdu_header, 0, sizeof(pdu_header)); + memset(&msg, 0, sizeof(msg)); + memset(&iov, 0, sizeof(iov)); + + /* 1. setup usbip_header */ + setup_ret_unlink_pdu(&pdu_header, unlink); + usbip_header_correct_endian(&pdu_header, 1); + + iov[0].iov_base = &pdu_header; + iov[0].iov_len = sizeof(pdu_header); + txsize += sizeof(pdu_header); + + ret = kernel_sendmsg(udc->ud.tcp_socket, &msg, iov, + 1, txsize); + if (ret != txsize) { + usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_TCP); + if (ret >= 0) + return -EPIPE; + return ret; + } + kfree(unlink); + + return txsize; +} + +static int v_send_ret_submit(struct vudc *udc, struct urbp *urb_p) +{ + struct urb *urb = urb_p->urb; + struct usbip_header pdu_header; + struct usbip_iso_packet_descriptor *iso_buffer = NULL; + struct kvec *iov = NULL; + int iovnum = 0; + int ret = 0; + size_t txsize; + struct msghdr msg; + + txsize = 0; + memset(&pdu_header, 0, sizeof(pdu_header)); + memset(&msg, 0, sizeof(msg)); + + if (urb_p->type == USB_ENDPOINT_XFER_ISOC) + iovnum = 2 + urb->number_of_packets; + else + iovnum = 2; + + iov = kcalloc(iovnum, sizeof(*iov), GFP_KERNEL); + if (!iov) { + usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_MALLOC); + ret = -ENOMEM; + goto out; + } + iovnum = 0; + + /* 1. setup usbip_header */ + setup_ret_submit_pdu(&pdu_header, urb_p); + usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n", + pdu_header.base.seqnum, urb); + usbip_header_correct_endian(&pdu_header, 1); + + iov[iovnum].iov_base = &pdu_header; + iov[iovnum].iov_len = sizeof(pdu_header); + iovnum++; + txsize += sizeof(pdu_header); + + /* 2. setup transfer buffer */ + if (urb_p->type != USB_ENDPOINT_XFER_ISOC && + usb_pipein(urb->pipe) && urb->actual_length > 0) { + iov[iovnum].iov_base = urb->transfer_buffer; + iov[iovnum].iov_len = urb->actual_length; + iovnum++; + txsize += urb->actual_length; + } else if (urb_p->type == USB_ENDPOINT_XFER_ISOC && + usb_pipein(urb->pipe)) { + /* FIXME - copypasted from stub_tx, refactor */ + int i; + + for (i = 0; i < urb->number_of_packets; i++) { + iov[iovnum].iov_base = urb->transfer_buffer + + urb->iso_frame_desc[i].offset; + iov[iovnum].iov_len = + urb->iso_frame_desc[i].actual_length; + iovnum++; + txsize += urb->iso_frame_desc[i].actual_length; + } + + if (txsize != sizeof(pdu_header) + urb->actual_length) { + usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_TCP); + ret = -EPIPE; + goto out; + } + } + /* else - no buffer to send */ + + /* 3. setup iso_packet_descriptor */ + if (urb_p->type == USB_ENDPOINT_XFER_ISOC) { + ssize_t len = 0; + + iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); + if (!iso_buffer) { + usbip_event_add(&udc->ud, + VUDC_EVENT_ERROR_MALLOC); + ret = -ENOMEM; + goto out; + } + + iov[iovnum].iov_base = iso_buffer; + iov[iovnum].iov_len = len; + txsize += len; + iovnum++; + } + + ret = kernel_sendmsg(udc->ud.tcp_socket, &msg, + iov, iovnum, txsize); + if (ret != txsize) { + usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_TCP); + if (ret >= 0) + ret = -EPIPE; + goto out; + } + +out: + kfree(iov); + kfree(iso_buffer); + free_urbp_and_urb(urb_p); + if (ret < 0) + return ret; + return txsize; +} + +static int v_send_ret(struct vudc *udc) +{ + unsigned long flags; + struct tx_item *txi; + size_t total_size = 0; + int ret = 0; + + spin_lock_irqsave(&udc->lock_tx, flags); + while (!list_empty(&udc->tx_queue)) { + txi = list_first_entry(&udc->tx_queue, struct tx_item, + tx_entry); + list_del(&txi->tx_entry); + spin_unlock_irqrestore(&udc->lock_tx, flags); + + switch (txi->type) { + case TX_SUBMIT: + ret = v_send_ret_submit(udc, txi->s); + break; + case TX_UNLINK: + ret = v_send_ret_unlink(udc, txi->u); + break; + } + kfree(txi); + + if (ret < 0) + return ret; + + total_size += ret; + + spin_lock_irqsave(&udc->lock_tx, flags); + } + + spin_unlock_irqrestore(&udc->lock_tx, flags); + return total_size; +} + + +int v_tx_loop(void *data) +{ + struct usbip_device *ud = (struct usbip_device *) data; + struct vudc *udc = container_of(ud, struct vudc, ud); + int ret; + + while (!kthread_should_stop()) { + if (usbip_event_happened(&udc->ud)) + break; + ret = v_send_ret(udc); + if (ret < 0) { + pr_warn("v_tx exit with error %d", ret); + break; + } + wait_event_interruptible(udc->tx_waitq, + (!list_empty(&udc->tx_queue) || + kthread_should_stop())); + } + + return 0; +} + +/* called with spinlocks held */ +void v_enqueue_ret_unlink(struct vudc *udc, __u32 seqnum, __u32 status) +{ + struct tx_item *txi; + struct v_unlink *unlink; + + txi = kzalloc(sizeof(*txi), GFP_ATOMIC); + if (!txi) { + usbip_event_add(&udc->ud, VDEV_EVENT_ERROR_MALLOC); + return; + } + unlink = kzalloc(sizeof(*unlink), GFP_ATOMIC); + if (!unlink) { + kfree(txi); + usbip_event_add(&udc->ud, VDEV_EVENT_ERROR_MALLOC); + return; + } + + unlink->seqnum = seqnum; + unlink->status = status; + txi->type = TX_UNLINK; + txi->u = unlink; + + list_add_tail(&txi->tx_entry, &udc->tx_queue); +} + +/* called with spinlocks held */ +void v_enqueue_ret_submit(struct vudc *udc, struct urbp *urb_p) +{ + struct tx_item *txi; + + txi = kzalloc(sizeof(*txi), GFP_ATOMIC); + if (!txi) { + usbip_event_add(&udc->ud, VDEV_EVENT_ERROR_MALLOC); + return; + } + + txi->type = TX_SUBMIT; + txi->s = urb_p; + + list_add_tail(&txi->tx_entry, &udc->tx_queue); +} -- GitLab From b6a0ca11186759ad7045d68a5447b1e89f658384 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:49:02 +0100 Subject: [PATCH 4684/9938] usbip: vudc: Add UDC specific ops Add endpoints definitions and ops for both endpoints and gadget. Add also a suitable platform driver and functions for handling usbip events. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik [Various bug fixes, improvements and commit msg update] Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_dev.c | 662 +++++++++++++++++++++++++++++++++++ 1 file changed, 662 insertions(+) create mode 100644 drivers/usb/usbip/vudc_dev.c diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c new file mode 100644 index 000000000000..43047f4fbca2 --- /dev/null +++ b/drivers/usb/usbip/vudc_dev.c @@ -0,0 +1,662 @@ +/* + * Copyright (C) 2015 Karol Kosik + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usbip_common.h" +#include "vudc.h" + +#define VIRTUAL_ENDPOINTS (1 /* ep0 */ + 15 /* in eps */ + 15 /* out eps */) + +/* urb-related structures alloc / free */ + + +static void free_urb(struct urb *urb) +{ + if (!urb) + return; + + kfree(urb->setup_packet); + urb->setup_packet = NULL; + + kfree(urb->transfer_buffer); + urb->transfer_buffer = NULL; + + usb_free_urb(urb); +} + +struct urbp *alloc_urbp(void) +{ + struct urbp *urb_p; + + urb_p = kzalloc(sizeof(*urb_p), GFP_KERNEL); + if (!urb_p) + return urb_p; + + urb_p->urb = NULL; + urb_p->ep = NULL; + INIT_LIST_HEAD(&urb_p->urb_entry); + return urb_p; +} + +static void free_urbp(struct urbp *urb_p) +{ + kfree(urb_p); +} + +void free_urbp_and_urb(struct urbp *urb_p) +{ + if (!urb_p) + return; + free_urb(urb_p->urb); + free_urbp(urb_p); +} + + +/* utilities ; almost verbatim from dummy_hcd.c */ + +/* called with spinlock held */ +static void nuke(struct vudc *udc, struct vep *ep) +{ + struct vrequest *req; + + while (!list_empty(&ep->req_queue)) { + req = list_first_entry(&ep->req_queue, struct vrequest, + req_entry); + list_del_init(&req->req_entry); + req->req.status = -ESHUTDOWN; + + spin_unlock(&udc->lock); + usb_gadget_giveback_request(&ep->ep, &req->req); + spin_lock(&udc->lock); + } +} + +/* caller must hold lock */ +static void stop_activity(struct vudc *udc) +{ + int i; + struct urbp *urb_p, *tmp; + + udc->address = 0; + + for (i = 0; i < VIRTUAL_ENDPOINTS; i++) + nuke(udc, &udc->ep[i]); + + list_for_each_entry_safe(urb_p, tmp, &udc->urb_queue, urb_entry) { + list_del(&urb_p->urb_entry); + free_urbp_and_urb(urb_p); + } +} + +struct vep *find_endpoint(struct vudc *udc, u8 address) +{ + int i; + + if ((address & ~USB_DIR_IN) == 0) + return &udc->ep[0]; + + for (i = 1; i < VIRTUAL_ENDPOINTS; i++) { + struct vep *ep = &udc->ep[i]; + + if (!ep->desc) + continue; + if (ep->desc->bEndpointAddress == address) + return ep; + } + return NULL; +} + +/* gadget ops */ + +/* FIXME - this will probably misbehave when suspend/resume is added */ +static int vgadget_get_frame(struct usb_gadget *_gadget) +{ + struct timeval now; + struct vudc *udc = usb_gadget_to_vudc(_gadget); + + do_gettimeofday(&now); + return ((now.tv_sec - udc->start_time.tv_sec) * 1000 + + (now.tv_usec - udc->start_time.tv_usec) / 1000) + % 0x7FF; +} + +static int vgadget_set_selfpowered(struct usb_gadget *_gadget, int value) +{ + struct vudc *udc = usb_gadget_to_vudc(_gadget); + + if (value) + udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED); + else + udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); + return 0; +} + +static int vgadget_pullup(struct usb_gadget *_gadget, int value) +{ + struct vudc *udc = usb_gadget_to_vudc(_gadget); + unsigned long flags; + int ret; + + + spin_lock_irqsave(&udc->lock, flags); + value = !!value; + if (value == udc->pullup) + goto unlock; + + udc->pullup = value; + if (value) { + udc->gadget.speed = min_t(u8, USB_SPEED_HIGH, + udc->driver->max_speed); + udc->ep[0].ep.maxpacket = 64; + /* + * This is the first place where we can ask our + * gadget driver for descriptors. + */ + ret = get_gadget_descs(udc); + if (ret) { + dev_err(&udc->gadget.dev, "Unable go get desc: %d", ret); + goto unlock; + } + + spin_unlock_irqrestore(&udc->lock, flags); + usbip_start_eh(&udc->ud); + } else { + /* Invalidate descriptors */ + udc->desc_cached = 0; + + spin_unlock_irqrestore(&udc->lock, flags); + usbip_event_add(&udc->ud, VUDC_EVENT_REMOVED); + usbip_stop_eh(&udc->ud); /* Wait for eh completion */ + } + + return 0; + +unlock: + spin_unlock_irqrestore(&udc->lock, flags); + return 0; +} + +static int vgadget_udc_start(struct usb_gadget *g, + struct usb_gadget_driver *driver) +{ + struct vudc *udc = usb_gadget_to_vudc(g); + unsigned long flags; + + spin_lock_irqsave(&udc->lock, flags); + udc->driver = driver; + udc->pullup = udc->connected = udc->desc_cached = 0; + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static int vgadget_udc_stop(struct usb_gadget *g) +{ + struct vudc *udc = usb_gadget_to_vudc(g); + unsigned long flags; + + spin_lock_irqsave(&udc->lock, flags); + udc->driver = NULL; + spin_unlock_irqrestore(&udc->lock, flags); + return 0; +} + +static const struct usb_gadget_ops vgadget_ops = { + .get_frame = vgadget_get_frame, + .set_selfpowered = vgadget_set_selfpowered, + .pullup = vgadget_pullup, + .udc_start = vgadget_udc_start, + .udc_stop = vgadget_udc_stop, +}; + + +/* endpoint ops */ + +static int vep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) +{ + struct vep *ep; + struct vudc *udc; + unsigned maxp; + unsigned long flags; + + ep = to_vep(_ep); + udc = ep_to_vudc(ep); + + if (!_ep || !desc || ep->desc || _ep->caps.type_control + || desc->bDescriptorType != USB_DT_ENDPOINT) + return -EINVAL; + + if (!udc->driver) + return -ESHUTDOWN; + + spin_lock_irqsave(&udc->lock, flags); + + maxp = usb_endpoint_maxp(desc) & 0x7ff; + _ep->maxpacket = maxp; + ep->desc = desc; + ep->type = usb_endpoint_type(desc); + ep->halted = ep->wedged = 0; + + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static int vep_disable(struct usb_ep *_ep) +{ + struct vep *ep; + struct vudc *udc; + unsigned long flags; + + ep = to_vep(_ep); + udc = ep_to_vudc(ep); + if (!_ep || !ep->desc || _ep->caps.type_control) + return -EINVAL; + + spin_lock_irqsave(&udc->lock, flags); + ep->desc = NULL; + nuke(udc, ep); + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static struct usb_request *vep_alloc_request(struct usb_ep *_ep, + gfp_t mem_flags) +{ + struct vep *ep; + struct vrequest *req; + + if (!_ep) + return NULL; + ep = to_vep(_ep); + + req = kzalloc(sizeof(*req), mem_flags); + if (!req) + return NULL; + + INIT_LIST_HEAD(&req->req_entry); + + return &req->req; +} + +static void vep_free_request(struct usb_ep *_ep, struct usb_request *_req) +{ + struct vrequest *req; + + if (!_ep || !_req) { + WARN_ON(1); + return; + } + req = to_vrequest(_req); + kfree(req); +} + +static int vep_queue(struct usb_ep *_ep, struct usb_request *_req, + gfp_t mem_flags) +{ + struct vep *ep; + struct vrequest *req; + struct vudc *udc; + unsigned long flags; + + if (!_ep || !_req) + return -EINVAL; + + ep = to_vep(_ep); + req = to_vrequest(_req); + udc = ep_to_vudc(ep); + + spin_lock_irqsave(&udc->lock, flags); + _req->actual = 0; + _req->status = -EINPROGRESS; + + list_add_tail(&req->req_entry, &ep->req_queue); + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static int vep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct vep *ep; + struct vrequest *req; + struct vudc *udc; + struct vrequest *lst; + unsigned long flags; + int ret = -EINVAL; + + if (!_ep || !_req) + return ret; + + ep = to_vep(_ep); + req = to_vrequest(_req); + udc = req->udc; + + if (!udc->driver) + return -ESHUTDOWN; + + spin_lock_irqsave(&udc->lock, flags); + list_for_each_entry(lst, &ep->req_queue, req_entry) { + if (&lst->req == _req) { + list_del_init(&lst->req_entry); + _req->status = -ECONNRESET; + ret = 0; + break; + } + } + spin_unlock_irqrestore(&udc->lock, flags); + + if (ret == 0) + usb_gadget_giveback_request(_ep, _req); + + return ret; +} + +static int +vep_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged) +{ + struct vep *ep; + struct vudc *udc; + unsigned long flags; + int ret = 0; + + ep = to_vep(_ep); + if (!_ep) + return -EINVAL; + + udc = ep_to_vudc(ep); + if (!udc->driver) + return -ESHUTDOWN; + + spin_lock_irqsave(&udc->lock, flags); + if (!value) + ep->halted = ep->wedged = 0; + else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && + !list_empty(&ep->req_queue)) + ret = -EAGAIN; + else { + ep->halted = 1; + if (wedged) + ep->wedged = 1; + } + + spin_unlock_irqrestore(&udc->lock, flags); + return ret; +} + +static int +vep_set_halt(struct usb_ep *_ep, int value) +{ + return vep_set_halt_and_wedge(_ep, value, 0); +} + +static int vep_set_wedge(struct usb_ep *_ep) +{ + return vep_set_halt_and_wedge(_ep, 1, 1); +} + +static const struct usb_ep_ops vep_ops = { + .enable = vep_enable, + .disable = vep_disable, + + .alloc_request = vep_alloc_request, + .free_request = vep_free_request, + + .queue = vep_queue, + .dequeue = vep_dequeue, + + .set_halt = vep_set_halt, + .set_wedge = vep_set_wedge, +}; + + +/* shutdown / reset / error handlers */ + +static void vudc_shutdown(struct usbip_device *ud) +{ + struct vudc *udc = container_of(ud, struct vudc, ud); + int call_disconnect = 0; + unsigned long flags; + + dev_dbg(&udc->pdev->dev, "device shutdown"); + if (ud->tcp_socket) + kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR); + + if (ud->tcp_tx) { + kthread_stop_put(ud->tcp_rx); + ud->tcp_rx = NULL; + } + if (ud->tcp_tx) { + kthread_stop_put(ud->tcp_tx); + ud->tcp_tx = NULL; + } + + if (ud->tcp_socket) { + sockfd_put(ud->tcp_socket); + ud->tcp_socket = NULL; + } + + spin_lock_irqsave(&udc->lock, flags); + stop_activity(udc); + if (udc->connected && udc->driver->disconnect) + call_disconnect = 1; + udc->connected = 0; + spin_unlock_irqrestore(&udc->lock, flags); + if (call_disconnect) + udc->driver->disconnect(&udc->gadget); +} + +static void vudc_device_reset(struct usbip_device *ud) +{ + struct vudc *udc = container_of(ud, struct vudc, ud); + unsigned long flags; + + dev_dbg(&udc->pdev->dev, "device reset"); + spin_lock_irqsave(&udc->lock, flags); + stop_activity(udc); + spin_unlock_irqrestore(&udc->lock, flags); + if (udc->driver) + usb_gadget_udc_reset(&udc->gadget, udc->driver); + spin_lock_irqsave(&ud->lock, flags); + ud->status = SDEV_ST_AVAILABLE; + spin_unlock_irqrestore(&ud->lock, flags); +} + +static void vudc_device_unusable(struct usbip_device *ud) +{ + unsigned long flags; + + spin_lock_irqsave(&ud->lock, flags); + ud->status = SDEV_ST_ERROR; + spin_unlock_irqrestore(&ud->lock, flags); +} + +/* device setup / cleanup */ + +struct vudc_device *alloc_vudc_device(int devid) +{ + struct vudc_device *udc_dev = NULL; + + udc_dev = kzalloc(sizeof(*udc_dev), GFP_KERNEL); + if (!udc_dev) + goto out; + + INIT_LIST_HEAD(&udc_dev->dev_entry); + + udc_dev->pdev = platform_device_alloc(GADGET_NAME, devid); + if (!udc_dev->pdev) { + kfree(udc_dev); + udc_dev = NULL; + } + +out: + return udc_dev; +} + +void put_vudc_device(struct vudc_device *udc_dev) +{ + platform_device_put(udc_dev->pdev); + kfree(udc_dev); +} + +static int init_vudc_hw(struct vudc *udc) +{ + int i; + struct usbip_device *ud = &udc->ud; + struct vep *ep; + + udc->ep = kcalloc(VIRTUAL_ENDPOINTS, sizeof(*udc->ep), GFP_KERNEL); + if (!udc->ep) + goto nomem_ep; + + INIT_LIST_HEAD(&udc->gadget.ep_list); + + /* create ep0 and 15 in, 15 out general purpose eps */ + for (i = 0; i < VIRTUAL_ENDPOINTS; ++i) { + int is_out = i % 2; + int num = (i + 1) / 2; + + ep = &udc->ep[i]; + + sprintf(ep->name, "ep%d%s", num, + i ? (is_out ? "out" : "in") : ""); + ep->ep.name = ep->name; + if (i == 0) { + ep->ep.caps.type_control = true; + ep->ep.caps.dir_out = true; + ep->ep.caps.dir_in = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_int = true; + ep->ep.caps.type_bulk = true; + } + + if (is_out) + ep->ep.caps.dir_out = true; + else + ep->ep.caps.dir_in = true; + + ep->ep.ops = &vep_ops; + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + ep->halted = ep->wedged = ep->already_seen = + ep->setup_stage = 0; + usb_ep_set_maxpacket_limit(&ep->ep, ~0); + ep->ep.max_streams = 16; + ep->gadget = &udc->gadget; + ep->desc = NULL; + INIT_LIST_HEAD(&ep->req_queue); + } + + spin_lock_init(&udc->lock); + spin_lock_init(&udc->lock_tx); + INIT_LIST_HEAD(&udc->urb_queue); + INIT_LIST_HEAD(&udc->tx_queue); + init_waitqueue_head(&udc->tx_waitq); + + spin_lock_init(&ud->lock); + ud->status = SDEV_ST_AVAILABLE; + ud->side = USBIP_VUDC; + + ud->eh_ops.shutdown = vudc_shutdown; + ud->eh_ops.reset = vudc_device_reset; + ud->eh_ops.unusable = vudc_device_unusable; + + udc->gadget.ep0 = &udc->ep[0].ep; + list_del_init(&udc->ep[0].ep.ep_list); + + v_init_timer(udc); + return 0; + +nomem_ep: + return -ENOMEM; +} + +static void cleanup_vudc_hw(struct vudc *udc) +{ + kfree(udc->ep); +} + +/* platform driver ops */ + +int vudc_probe(struct platform_device *pdev) +{ + struct vudc *udc; + int ret = -ENOMEM; + + udc = kzalloc(sizeof(*udc), GFP_KERNEL); + if (!udc) + goto out; + + udc->gadget.name = GADGET_NAME; + udc->gadget.ops = &vgadget_ops; + udc->gadget.max_speed = USB_SPEED_HIGH; + udc->gadget.dev.parent = &pdev->dev; + udc->pdev = pdev; + + ret = init_vudc_hw(udc); + if (ret) + goto err_init_vudc_hw; + + ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget); + if (ret < 0) + goto err_add_udc; + + ret = sysfs_create_group(&pdev->dev.kobj, &vudc_attr_group); + if (ret) { + dev_err(&udc->pdev->dev, "create sysfs files\n"); + goto err_sysfs; + } + + platform_set_drvdata(pdev, udc); + + return ret; + +err_sysfs: + usb_del_gadget_udc(&udc->gadget); +err_add_udc: + cleanup_vudc_hw(udc); +err_init_vudc_hw: + kfree(udc); +out: + return ret; +} + +int vudc_remove(struct platform_device *pdev) +{ + struct vudc *udc = platform_get_drvdata(pdev); + + sysfs_remove_group(&pdev->dev.kobj, &vudc_attr_group); + usb_del_gadget_udc(&udc->gadget); + cleanup_vudc_hw(udc); + kfree(udc); + return 0; +} -- GitLab From ea6873a45a22f35c8ab0f9c025df6a6c6dd532f3 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:49:03 +0100 Subject: [PATCH 4685/9938] usbip: vudc: Add SysFS infrastructure for VUDC Add sysfs attributes to allow controlling vudc from usbip tools. dev_desc - device descriptor of current gadget. This is required to be consisten with current usbip protocol and allow to list exportable devices on given machine. usbip_sockfd - allows to pass socket to kernel to start usbip transfer. usbip_status - currnent status of device This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Karol Kosik [Various bug fixes, improvements and commit msg update] Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_sysfs.c | 221 +++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 drivers/usb/usbip/vudc_sysfs.c diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c new file mode 100644 index 000000000000..25ca16ab0073 --- /dev/null +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2015 Karol Kosik + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "usbip_common.h" +#include "vudc.h" + +#include + +/* called with udc->lock held */ +int get_gadget_descs(struct vudc *udc) +{ + struct vrequest *usb_req; + struct vep *ep0 = to_vep(udc->gadget.ep0); + struct usb_device_descriptor *ddesc = &udc->dev_desc; + struct usb_ctrlrequest req; + int ret; + + if (!udc || !udc->driver || !udc->pullup) + return -EINVAL; + + req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; + req.bRequest = USB_REQ_GET_DESCRIPTOR; + req.wValue = cpu_to_le16(USB_DT_DEVICE << 8); + req.wIndex = cpu_to_le16(0); + req.wLength = cpu_to_le16(sizeof(*ddesc)); + + spin_unlock(&udc->lock); + ret = udc->driver->setup(&(udc->gadget), &req); + spin_lock(&udc->lock); + if (ret < 0) + goto out; + + /* assuming request queue is empty; request is now on top */ + usb_req = list_last_entry(&ep0->req_queue, struct vrequest, req_entry); + list_del(&usb_req->req_entry); + + if (usb_req->req.length > sizeof(*ddesc)) { + ret = -EOVERFLOW; + goto giveback_req; + } + + memcpy(ddesc, usb_req->req.buf, sizeof(*ddesc)); + udc->desc_cached = 1; + ret = 0; +giveback_req: + usb_req->req.status = 0; + usb_req->req.actual = usb_req->req.length; + usb_gadget_giveback_request(&(ep0->ep), &(usb_req->req)); +out: + return ret; +} + +/* + * Exposes device descriptor from the gadget driver. + */ +static ssize_t dev_desc_show(struct device *dev, + struct device_attribute *attr, char *out) +{ + struct vudc *udc = (struct vudc *)dev_get_drvdata(dev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&udc->lock, flags); + if (!udc->desc_cached) { + ret = -ENODEV; + goto unlock; + } + + memcpy(out, &udc->dev_desc, sizeof(udc->dev_desc)); + ret = sizeof(udc->dev_desc); +unlock: + spin_unlock_irqrestore(&udc->lock, flags); + return ret; +} +static DEVICE_ATTR_RO(dev_desc); + +static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, + const char *in, size_t count) +{ + struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); + int rv; + int sockfd = 0; + int err; + struct socket *socket; + unsigned long flags; + int ret; + + rv = kstrtoint(in, 0, &sockfd); + if (rv != 0) + return -EINVAL; + + spin_lock_irqsave(&udc->lock, flags); + /* Don't export what we don't have */ + if (!udc || !udc->driver || !udc->pullup) { + dev_err(dev, "no device or gadget not bound"); + ret = -ENODEV; + goto unlock; + } + + if (sockfd != -1) { + if (udc->connected) { + dev_err(dev, "Device already connected"); + ret = -EBUSY; + goto unlock; + } + + spin_lock_irq(&udc->ud.lock); + + if (udc->ud.status != SDEV_ST_AVAILABLE) { + ret = -EINVAL; + goto unlock_ud; + } + + socket = sockfd_lookup(sockfd, &err); + if (!socket) { + dev_err(dev, "failed to lookup sock"); + ret = -EINVAL; + goto unlock_ud; + } + + udc->ud.tcp_socket = socket; + + spin_unlock_irq(&udc->ud.lock); + spin_unlock_irqrestore(&udc->lock, flags); + + udc->ud.tcp_rx = kthread_get_run(&v_rx_loop, + &udc->ud, "vudc_rx"); + udc->ud.tcp_tx = kthread_get_run(&v_tx_loop, + &udc->ud, "vudc_tx"); + + spin_lock_irqsave(&udc->lock, flags); + spin_lock_irq(&udc->ud.lock); + udc->ud.status = SDEV_ST_USED; + spin_unlock_irq(&udc->ud.lock); + + do_gettimeofday(&udc->start_time); + v_start_timer(udc); + udc->connected = 1; + } else { + if (!udc->connected) { + dev_err(dev, "Device not connected"); + ret = -EINVAL; + goto unlock; + } + + spin_lock_irq(&udc->ud.lock); + if (udc->ud.status != SDEV_ST_USED) { + ret = -EINVAL; + goto unlock_ud; + } + spin_unlock_irq(&udc->ud.lock); + + usbip_event_add(&udc->ud, VUDC_EVENT_DOWN); + } + + spin_unlock_irqrestore(&udc->lock, flags); + + return count; + +unlock_ud: + spin_unlock_irq(&udc->ud.lock); +unlock: + spin_unlock_irqrestore(&udc->lock, flags); + + return ret; +} +static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); + +static ssize_t usbip_status_show(struct device *dev, + struct device_attribute *attr, char *out) +{ + struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); + int status; + + if (!udc) { + dev_err(&udc->pdev->dev, "no device"); + return -ENODEV; + } + spin_lock_irq(&udc->ud.lock); + status = udc->ud.status; + spin_unlock_irq(&udc->ud.lock); + + return snprintf(out, PAGE_SIZE, "%d\n", status); +} +static DEVICE_ATTR_RO(usbip_status); + +static struct attribute *dev_attrs[] = { + &dev_attr_dev_desc.attr, + &dev_attr_usbip_sockfd.attr, + &dev_attr_usbip_status.attr, + NULL, +}; + +const struct attribute_group vudc_attr_group = { + .attrs = dev_attrs, +}; -- GitLab From 3391ba0e2792411dc3372b76a4662971d6eaa405 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Tue, 8 Mar 2016 21:49:04 +0100 Subject: [PATCH 4686/9938] usbip: tools: Extract generic code to be shared with vudc backend Extract the code from current stub driver backend and a common interface for both stub driver and vudc. This allows to share most of the usbipd code for both of them. Based on code created in cooperation with Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- tools/usb/usbip/libsrc/Makefile.am | 3 +- tools/usb/usbip/libsrc/usbip_host_common.c | 273 +++++++++++++++++++++ tools/usb/usbip/libsrc/usbip_host_common.h | 104 ++++++++ tools/usb/usbip/libsrc/usbip_host_driver.c | 269 ++------------------ tools/usb/usbip/libsrc/usbip_host_driver.h | 27 +- tools/usb/usbip/src/usbipd.c | 30 ++- 6 files changed, 428 insertions(+), 278 deletions(-) create mode 100644 tools/usb/usbip/libsrc/usbip_host_common.c create mode 100644 tools/usb/usbip/libsrc/usbip_host_common.h diff --git a/tools/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am index 7c8f8a4d54e4..eb62f99cc0ee 100644 --- a/tools/usb/usbip/libsrc/Makefile.am +++ b/tools/usb/usbip/libsrc/Makefile.am @@ -4,5 +4,6 @@ libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@ lib_LTLIBRARIES := libusbip.la libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \ - usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \ + usbip_common.c usbip_common.h usbip_host_common.h \ + usbip_host_common.c vhci_driver.c vhci_driver.h \ sysfs_utils.c sysfs_utils.h diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c new file mode 100644 index 000000000000..9d415228883d --- /dev/null +++ b/tools/usb/usbip/libsrc/usbip_host_common.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak + * + * Refactored from usbip_host_driver.c, which is: + * Copyright (C) 2011 matt mooney + * 2005-2007 Takahiro Hirofuchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include + +#include + +#include "usbip_common.h" +#include "usbip_host_common.h" +#include "list.h" +#include "sysfs_utils.h" + +struct udev *udev_context; + +static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) +{ + char status_attr_path[SYSFS_PATH_MAX]; + int fd; + int length; + char status; + int value = 0; + + snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status", + udev->path); + + fd = open(status_attr_path, O_RDONLY); + if (fd < 0) { + err("error opening attribute %s", status_attr_path); + return -1; + } + + length = read(fd, &status, 1); + if (length < 0) { + err("error reading attribute %s", status_attr_path); + close(fd); + return -1; + } + + value = atoi(&status); + + return value; +} + +static +struct usbip_exported_device *usbip_exported_device_new( + struct usbip_host_driver *hdriver, const char *sdevpath) +{ + struct usbip_exported_device *edev = NULL; + struct usbip_exported_device *edev_old; + size_t size; + int i; + + edev = calloc(1, sizeof(struct usbip_exported_device)); + + edev->sudev = + udev_device_new_from_syspath(udev_context, sdevpath); + if (!edev->sudev) { + err("udev_device_new_from_syspath: %s", sdevpath); + goto err; + } + + if (hdriver->ops.read_device(edev->sudev, &edev->udev) < 0) + goto err; + + edev->status = read_attr_usbip_status(&edev->udev); + if (edev->status < 0) + goto err; + + /* reallocate buffer to include usb interface data */ + size = sizeof(struct usbip_exported_device) + + edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface); + + edev_old = edev; + edev = realloc(edev, size); + if (!edev) { + edev = edev_old; + dbg("realloc failed"); + goto err; + } + + for (i = 0; i < edev->udev.bNumInterfaces; i++) { + /* vudc does not support reading interfaces */ + if (!hdriver->ops.read_interface) + break; + hdriver->ops.read_interface(&edev->udev, i, &edev->uinf[i]); + } + + return edev; +err: + if (edev->sudev) + udev_device_unref(edev->sudev); + if (edev) + free(edev); + + return NULL; +} + +static int refresh_exported_devices(struct usbip_host_driver *hdriver) +{ + struct usbip_exported_device *edev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + const char *path; + + enumerate = udev_enumerate_new(udev_context); + udev_enumerate_add_match_subsystem(enumerate, hdriver->udev_subsystem); + udev_enumerate_scan_devices(enumerate); + + devices = udev_enumerate_get_list_entry(enumerate); + + udev_list_entry_foreach(dev_list_entry, devices) { + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev_context, + path); + if (dev == NULL) + continue; + + /* Check whether device uses usbip driver. */ + if (hdriver->ops.is_my_device(dev)) { + edev = usbip_exported_device_new(hdriver, path); + if (!edev) { + dbg("usbip_exported_device_new failed"); + continue; + } + + list_add(&edev->node, &hdriver->edev_list); + hdriver->ndevs++; + } + } + + return 0; +} + +static void usbip_exported_device_destroy(struct list_head *devs) +{ + struct list_head *i, *tmp; + struct usbip_exported_device *edev; + + list_for_each_safe(i, tmp, devs) { + edev = list_entry(i, struct usbip_exported_device, node); + list_del(i); + free(edev); + } +} + +int usbip_generic_driver_open(struct usbip_host_driver *hdriver) +{ + int rc; + + udev_context = udev_new(); + if (!udev_context) { + err("udev_new failed"); + return -1; + } + + rc = refresh_exported_devices(hdriver); + if (rc < 0) + goto err; + return 0; +err: + udev_unref(udev_context); + return -1; +} + +void usbip_generic_driver_close(struct usbip_host_driver *hdriver) +{ + if (!hdriver) + return; + + usbip_exported_device_destroy(&hdriver->edev_list); + + udev_unref(udev_context); +} + +int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver) +{ + int rc; + + usbip_exported_device_destroy(&hdriver->edev_list); + + hdriver->ndevs = 0; + INIT_LIST_HEAD(&hdriver->edev_list); + + rc = refresh_exported_devices(hdriver); + if (rc < 0) + return -1; + + return 0; +} + +int usbip_export_device(struct usbip_exported_device *edev, int sockfd) +{ + char attr_name[] = "usbip_sockfd"; + char sockfd_attr_path[SYSFS_PATH_MAX]; + char sockfd_buff[30]; + int ret; + + if (edev->status != SDEV_ST_AVAILABLE) { + dbg("device not available: %s", edev->udev.busid); + switch (edev->status) { + case SDEV_ST_ERROR: + dbg("status SDEV_ST_ERROR"); + break; + case SDEV_ST_USED: + dbg("status SDEV_ST_USED"); + break; + default: + dbg("status unknown: 0x%x", edev->status); + } + return -1; + } + + /* only the first interface is true */ + snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s", + edev->udev.path, attr_name); + + snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); + + ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff, + strlen(sockfd_buff)); + if (ret < 0) { + err("write_sysfs_attribute failed: sockfd %s to %s", + sockfd_buff, sockfd_attr_path); + return ret; + } + + info("connect: %s", edev->udev.busid); + + return ret; +} + +struct usbip_exported_device *usbip_generic_get_device( + struct usbip_host_driver *hdriver, int num) +{ + struct list_head *i; + struct usbip_exported_device *edev; + int cnt = 0; + + list_for_each(i, &hdriver->edev_list) { + edev = list_entry(i, struct usbip_exported_device, node); + if (num == cnt) + return edev; + cnt++; + } + + return NULL; +} diff --git a/tools/usb/usbip/libsrc/usbip_host_common.h b/tools/usb/usbip/libsrc/usbip_host_common.h new file mode 100644 index 000000000000..a64b8033fe64 --- /dev/null +++ b/tools/usb/usbip/libsrc/usbip_host_common.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak + * + * Refactored from usbip_host_driver.c, which is: + * Copyright (C) 2011 matt mooney + * 2005-2007 Takahiro Hirofuchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __USBIP_HOST_COMMON_H +#define __USBIP_HOST_COMMON_H + +#include +#include +#include +#include "list.h" +#include "usbip_common.h" +#include "sysfs_utils.h" + +struct usbip_host_driver; + +struct usbip_host_driver_ops { + int (*open)(struct usbip_host_driver *hdriver); + void (*close)(struct usbip_host_driver *hdriver); + int (*refresh_device_list)(struct usbip_host_driver *hdriver); + struct usbip_exported_device * (*get_device)( + struct usbip_host_driver *hdriver, int num); + + int (*read_device)(struct udev_device *sdev, + struct usbip_usb_device *dev); + int (*read_interface)(struct usbip_usb_device *udev, int i, + struct usbip_usb_interface *uinf); + int (*is_my_device)(struct udev_device *udev); +}; + +struct usbip_host_driver { + int ndevs; + /* list of exported device */ + struct list_head edev_list; + const char *udev_subsystem; + struct usbip_host_driver_ops ops; +}; + +struct usbip_exported_device { + struct udev_device *sudev; + int32_t status; + struct usbip_usb_device udev; + struct list_head node; + struct usbip_usb_interface uinf[]; +}; + +/* External API to access the driver */ +static inline int usbip_driver_open(struct usbip_host_driver *hdriver) +{ + if (!hdriver->ops.open) + return -EOPNOTSUPP; + return hdriver->ops.open(hdriver); +} + +static inline void usbip_driver_close(struct usbip_host_driver *hdriver) +{ + if (!hdriver->ops.close) + return; + hdriver->ops.close(hdriver); +} + +static inline int usbip_refresh_device_list(struct usbip_host_driver *hdriver) +{ + if (!hdriver->ops.refresh_device_list) + return -EOPNOTSUPP; + return hdriver->ops.refresh_device_list(hdriver); +} + +static inline struct usbip_exported_device * +usbip_get_device(struct usbip_host_driver *hdriver, int num) +{ + if (!hdriver->ops.get_device) + return NULL; + return hdriver->ops.get_device(hdriver, num); +} + +/* Helper functions for implementing driver backend */ +int usbip_generic_driver_open(struct usbip_host_driver *hdriver); +void usbip_generic_driver_close(struct usbip_host_driver *hdriver); +int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver); +int usbip_export_device(struct usbip_exported_device *edev, int sockfd); +struct usbip_exported_device *usbip_generic_get_device( + struct usbip_host_driver *hdriver, int num); + +#endif /* __USBIP_HOST_COMMON_H */ diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.c b/tools/usb/usbip/libsrc/usbip_host_driver.c index bef08d5c44e8..4de6edc54d35 100644 --- a/tools/usb/usbip/libsrc/usbip_host_driver.c +++ b/tools/usb/usbip/libsrc/usbip_host_driver.c @@ -1,6 +1,9 @@ /* * Copyright (C) 2011 matt mooney * 2005-2007 Takahiro Hirofuchi + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,265 +19,47 @@ * along with this program. If not, see . */ -#include -#include -#include - -#include #include - #include -#include "usbip_common.h" +#include "usbip_host_common.h" #include "usbip_host_driver.h" -#include "list.h" -#include "sysfs_utils.h" #undef PROGNAME #define PROGNAME "libusbip" -struct usbip_host_driver *host_driver; -struct udev *udev_context; - -static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) -{ - char status_attr_path[SYSFS_PATH_MAX]; - int fd; - int length; - char status; - int value = 0; - - snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status", - udev->path); - - fd = open(status_attr_path, O_RDONLY); - if (fd < 0) { - err("error opening attribute %s", status_attr_path); - return -1; - } - - length = read(fd, &status, 1); - if (length < 0) { - err("error reading attribute %s", status_attr_path); - close(fd); - return -1; - } - - value = atoi(&status); - - return value; -} - -static -struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath) -{ - struct usbip_exported_device *edev = NULL; - struct usbip_exported_device *edev_old; - size_t size; - int i; - - edev = calloc(1, sizeof(struct usbip_exported_device)); - - edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath); - if (!edev->sudev) { - err("udev_device_new_from_syspath: %s", sdevpath); - goto err; - } - - read_usb_device(edev->sudev, &edev->udev); - - edev->status = read_attr_usbip_status(&edev->udev); - if (edev->status < 0) - goto err; - - /* reallocate buffer to include usb interface data */ - size = sizeof(struct usbip_exported_device) + - edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface); - - edev_old = edev; - edev = realloc(edev, size); - if (!edev) { - edev = edev_old; - dbg("realloc failed"); - goto err; - } - - for (i = 0; i < edev->udev.bNumInterfaces; i++) - read_usb_interface(&edev->udev, i, &edev->uinf[i]); - - return edev; -err: - if (edev->sudev) - udev_device_unref(edev->sudev); - if (edev) - free(edev); - - return NULL; -} - -static int refresh_exported_devices(void) +static int is_my_device(struct udev_device *dev) { - struct usbip_exported_device *edev; - struct udev_enumerate *enumerate; - struct udev_list_entry *devices, *dev_list_entry; - struct udev_device *dev; - const char *path; const char *driver; - enumerate = udev_enumerate_new(udev_context); - udev_enumerate_add_match_subsystem(enumerate, "usb"); - udev_enumerate_scan_devices(enumerate); - - devices = udev_enumerate_get_list_entry(enumerate); - - udev_list_entry_foreach(dev_list_entry, devices) { - path = udev_list_entry_get_name(dev_list_entry); - dev = udev_device_new_from_syspath(udev_context, path); - if (dev == NULL) - continue; - - /* Check whether device uses usbip-host driver. */ - driver = udev_device_get_driver(dev); - if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) { - edev = usbip_exported_device_new(path); - if (!edev) { - dbg("usbip_exported_device_new failed"); - continue; - } - - list_add(&edev->node, &host_driver->edev_list); - host_driver->ndevs++; - } - } - - return 0; -} - -static void usbip_exported_device_destroy(void) -{ - struct list_head *i, *tmp; - struct usbip_exported_device *edev; - - list_for_each_safe(i, tmp, &host_driver->edev_list) { - edev = list_entry(i, struct usbip_exported_device, node); - list_del(i); - free(edev); - } + driver = udev_device_get_driver(dev); + return driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME); } -int usbip_host_driver_open(void) +static int usbip_host_driver_open(struct usbip_host_driver *hdriver) { - int rc; - - udev_context = udev_new(); - if (!udev_context) { - err("udev_new failed"); - return -1; - } - - host_driver = calloc(1, sizeof(*host_driver)); - - host_driver->ndevs = 0; - INIT_LIST_HEAD(&host_driver->edev_list); - - rc = refresh_exported_devices(); - if (rc < 0) - goto err_free_host_driver; - - return 0; - -err_free_host_driver: - free(host_driver); - host_driver = NULL; - - udev_unref(udev_context); - - return -1; -} - -void usbip_host_driver_close(void) -{ - if (!host_driver) - return; - - usbip_exported_device_destroy(); - - free(host_driver); - host_driver = NULL; - - udev_unref(udev_context); -} - -int usbip_host_refresh_device_list(void) -{ - int rc; - - usbip_exported_device_destroy(); - - host_driver->ndevs = 0; - INIT_LIST_HEAD(&host_driver->edev_list); - - rc = refresh_exported_devices(); - if (rc < 0) - return -1; - - return 0; -} - -int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd) -{ - char attr_name[] = "usbip_sockfd"; - char sockfd_attr_path[SYSFS_PATH_MAX]; - char sockfd_buff[30]; int ret; - if (edev->status != SDEV_ST_AVAILABLE) { - dbg("device not available: %s", edev->udev.busid); - switch (edev->status) { - case SDEV_ST_ERROR: - dbg("status SDEV_ST_ERROR"); - break; - case SDEV_ST_USED: - dbg("status SDEV_ST_USED"); - break; - default: - dbg("status unknown: 0x%x", edev->status); - } - return -1; - } - - /* only the first interface is true */ - snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s", - edev->udev.path, attr_name); - - snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); - - ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff, - strlen(sockfd_buff)); - if (ret < 0) { - err("write_sysfs_attribute failed: sockfd %s to %s", - sockfd_buff, sockfd_attr_path); - return ret; - } - - info("connect: %s", edev->udev.busid); + hdriver->ndevs = 0; + INIT_LIST_HEAD(&hdriver->edev_list); + ret = usbip_generic_driver_open(hdriver); + if (ret) + err("please load " USBIP_CORE_MOD_NAME ".ko and " + USBIP_HOST_DRV_NAME ".ko!"); return ret; } -struct usbip_exported_device *usbip_host_get_device(int num) -{ - struct list_head *i; - struct usbip_exported_device *edev; - int cnt = 0; - - list_for_each(i, &host_driver->edev_list) { - edev = list_entry(i, struct usbip_exported_device, node); - if (num == cnt) - return edev; - else - cnt++; - } - - return NULL; -} +struct usbip_host_driver host_driver = { + .edev_list = LIST_HEAD_INIT(host_driver.edev_list), + .udev_subsystem = "usb", + .ops = { + .open = usbip_host_driver_open, + .close = usbip_generic_driver_close, + .refresh_device_list = usbip_generic_refresh_device_list, + .get_device = usbip_generic_get_device, + .read_device = read_usb_device, + .read_interface = read_usb_interface, + .is_my_device = is_my_device, + }, +}; diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.h b/tools/usb/usbip/libsrc/usbip_host_driver.h index 2a31f855c616..77f07e72a7fe 100644 --- a/tools/usb/usbip/libsrc/usbip_host_driver.h +++ b/tools/usb/usbip/libsrc/usbip_host_driver.h @@ -1,6 +1,9 @@ /* * Copyright (C) 2011 matt mooney * 2005-2007 Takahiro Hirofuchi + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,28 +25,8 @@ #include #include "usbip_common.h" #include "list.h" +#include "usbip_host_common.h" -struct usbip_host_driver { - int ndevs; - /* list of exported device */ - struct list_head edev_list; -}; - -struct usbip_exported_device { - struct udev_device *sudev; - int32_t status; - struct usbip_usb_device udev; - struct list_head node; - struct usbip_usb_interface uinf[]; -}; - -extern struct usbip_host_driver *host_driver; - -int usbip_host_driver_open(void); -void usbip_host_driver_close(void); - -int usbip_host_refresh_device_list(void); -int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd); -struct usbip_exported_device *usbip_host_get_device(int num); +extern struct usbip_host_driver host_driver; #endif /* __USBIP_HOST_DRIVER_H */ diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c index 2a7cd2b8d966..8a2ec4dab4bd 100644 --- a/tools/usb/usbip/src/usbipd.c +++ b/tools/usb/usbip/src/usbipd.c @@ -1,6 +1,9 @@ /* * Copyright (C) 2011 matt mooney * 2005-2007 Takahiro Hirofuchi + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +44,7 @@ #include #include "usbip_host_driver.h" +#include "usbip_host_common.h" #include "usbip_common.h" #include "usbip_network.h" #include "list.h" @@ -83,6 +87,8 @@ static const char usbipd_help_string[] = " -v, --version\n" " Show version.\n"; +static struct usbip_host_driver *driver; + static void usbipd_help(void) { printf("%s\n", usbipd_help_string); @@ -107,7 +113,7 @@ static int recv_request_import(int sockfd) } PACK_OP_IMPORT_REQUEST(0, &req); - list_for_each(i, &host_driver->edev_list) { + list_for_each(i, &driver->edev_list) { edev = list_entry(i, struct usbip_exported_device, node); if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { info("found requested device: %s", req.busid); @@ -121,7 +127,7 @@ static int recv_request_import(int sockfd) usbip_net_set_nodelay(sockfd); /* export device needs a TCP/IP socket descriptor */ - rc = usbip_host_export_device(edev, sockfd); + rc = usbip_export_device(edev, sockfd); if (rc < 0) error = 1; } else { @@ -166,7 +172,7 @@ static int send_reply_devlist(int connfd) reply.ndev = 0; /* number of exported devices */ - list_for_each(j, &host_driver->edev_list) { + list_for_each(j, &driver->edev_list) { reply.ndev += 1; } info("exportable devices: %d", reply.ndev); @@ -184,7 +190,7 @@ static int send_reply_devlist(int connfd) return -1; } - list_for_each(j, &host_driver->edev_list) { + list_for_each(j, &driver->edev_list) { edev = list_entry(j, struct usbip_exported_device, node); dump_usb_device(&edev->udev); memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); @@ -246,7 +252,7 @@ static int recv_pdu(int connfd) return -1; } - ret = usbip_host_refresh_device_list(); + ret = usbip_refresh_device_list(driver); if (ret < 0) { dbg("could not refresh device list: %d", ret); return -1; @@ -491,16 +497,13 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) struct timespec timeout; sigset_t sigmask; - if (usbip_host_driver_open()) { - err("please load " USBIP_CORE_MOD_NAME ".ko and " - USBIP_HOST_DRV_NAME ".ko!"); + if (usbip_driver_open(driver)) return -1; - } if (daemonize) { if (daemon(0, 0) < 0) { err("daemonizing failed: %s", strerror(errno)); - usbip_host_driver_close(); + usbip_driver_close(driver); return -1; } umask(0); @@ -525,7 +528,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) ai_head = do_getaddrinfo(NULL, family); if (!ai_head) { - usbip_host_driver_close(); + usbip_driver_close(driver); return -1; } nsockfd = listen_all_addrinfo(ai_head, sockfdlist, @@ -533,7 +536,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) freeaddrinfo(ai_head); if (nsockfd <= 0) { err("failed to open a listening socket"); - usbip_host_driver_close(); + usbip_driver_close(driver); return -1; } @@ -574,7 +577,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) info("shutting down " PROGNAME); free(fds); - usbip_host_driver_close(); + usbip_driver_close(driver); return 0; } @@ -613,6 +616,7 @@ int main(int argc, char *argv[]) err("not running as root?"); cmd = cmd_standalone_mode; + driver = &host_driver; for (;;) { opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL); -- GitLab From 7b3f74f7e0601b2767aee7e188b1e3a912c082a2 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Tue, 8 Mar 2016 21:49:05 +0100 Subject: [PATCH 4687/9938] usbip: tools: Add vudc backend to usbip tools Adds an equivalent of usbip_host_driver for the vudc. Most of the code is already shared, but this adds some vudc specific code for getting information about devices. Based on code created in cooperation with Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- tools/usb/usbip/libsrc/Makefile.am | 1 + tools/usb/usbip/libsrc/usbip_common.h | 3 + tools/usb/usbip/libsrc/usbip_device_driver.c | 163 +++++++++++++++++++ tools/usb/usbip/libsrc/usbip_device_driver.h | 34 ++++ 4 files changed, 201 insertions(+) create mode 100644 tools/usb/usbip/libsrc/usbip_device_driver.c create mode 100644 tools/usb/usbip/libsrc/usbip_device_driver.h diff --git a/tools/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am index eb62f99cc0ee..90daf95c0804 100644 --- a/tools/usb/usbip/libsrc/Makefile.am +++ b/tools/usb/usbip/libsrc/Makefile.am @@ -4,6 +4,7 @@ libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@ lib_LTLIBRARIES := libusbip.la libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \ + usbip_device_driver.c usbip_device_driver.h \ usbip_common.c usbip_common.h usbip_host_common.h \ usbip_host_common.c vhci_driver.c vhci_driver.h \ sysfs_utils.c sysfs_utils.h diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h index 15fe792e1e96..51ef5fe485dd 100644 --- a/tools/usb/usbip/libsrc/usbip_common.h +++ b/tools/usb/usbip/libsrc/usbip_common.h @@ -25,9 +25,12 @@ #define VHCI_STATE_PATH "/var/run/vhci_hcd" #endif +#define VUDC_DEVICE_DESCR_FILE "dev_desc" + /* kernel module names */ #define USBIP_CORE_MOD_NAME "usbip-core" #define USBIP_HOST_DRV_NAME "usbip-host" +#define USBIP_DEVICE_DRV_NAME "usbip-vudc" #define USBIP_VHCI_DRV_NAME "vhci_hcd" /* sysfs constants */ diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.c b/tools/usb/usbip/libsrc/usbip_device_driver.c new file mode 100644 index 000000000000..e059b7d1ec5b --- /dev/null +++ b/tools/usb/usbip/libsrc/usbip_device_driver.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2015 Karol Kosik + * 2015 Samsung Electronics + * Author: Igor Kotrasinski + * + * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is: + * Copyright (C) 2011 matt mooney + * 2005-2007 Takahiro Hirofuchi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include + +#include "usbip_host_common.h" +#include "usbip_device_driver.h" + +#undef PROGNAME +#define PROGNAME "libusbip" + +#define copy_descr_attr16(dev, descr, attr) \ + ((dev)->attr = le16toh((descr)->attr)) \ + +#define copy_descr_attr(dev, descr, attr) \ + ((dev)->attr = (descr)->attr) \ + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +static struct { + enum usb_device_speed speed; + const char *name; +} speed_names[] = { + { + .speed = USB_SPEED_UNKNOWN, + .name = "UNKNOWN", + }, + { + .speed = USB_SPEED_LOW, + .name = "low-speed", + }, + { + .speed = USB_SPEED_FULL, + .name = "full-speed", + }, + { + .speed = USB_SPEED_HIGH, + .name = "high-speed", + }, + { + .speed = USB_SPEED_WIRELESS, + .name = "wireless", + }, + { + .speed = USB_SPEED_SUPER, + .name = "super-speed", + }, +}; + +static +int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev) +{ + const char *path, *name; + char filepath[SYSFS_PATH_MAX]; + struct usb_device_descriptor descr; + unsigned i; + FILE *fd = NULL; + struct udev_device *plat; + const char *speed; + int ret = 0; + + plat = udev_device_get_parent(sdev); + path = udev_device_get_syspath(plat); + snprintf(filepath, SYSFS_PATH_MAX, "%s/%s", + path, VUDC_DEVICE_DESCR_FILE); + fd = fopen(filepath, "r"); + if (!fd) + return -1; + ret = fread((char *) &descr, sizeof(descr), 1, fd); + if (ret < 0) + return -1; + fclose(fd); + + copy_descr_attr(dev, &descr, bDeviceClass); + copy_descr_attr(dev, &descr, bDeviceSubClass); + copy_descr_attr(dev, &descr, bDeviceProtocol); + copy_descr_attr(dev, &descr, bNumConfigurations); + copy_descr_attr16(dev, &descr, idVendor); + copy_descr_attr16(dev, &descr, idProduct); + copy_descr_attr16(dev, &descr, bcdDevice); + + strncpy(dev->path, path, SYSFS_PATH_MAX); + + dev->speed = USB_SPEED_UNKNOWN; + speed = udev_device_get_sysattr_value(sdev, "current_speed"); + if (speed) { + for (i = 0; i < ARRAY_SIZE(speed_names); i++) { + if (!strcmp(speed_names[i].name, speed)) { + dev->speed = speed_names[i].speed; + break; + } + } + } + + /* Only used for user output, little sense to output them in general */ + dev->bNumInterfaces = 0; + dev->bConfigurationValue = 0; + dev->busnum = 0; + + name = udev_device_get_sysname(plat); + strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE); + return 0; +} + +static int is_my_device(struct udev_device *dev) +{ + const char *driver; + + driver = udev_device_get_property_value(dev, "USB_UDC_NAME"); + return driver != NULL && !strcmp(driver, USBIP_DEVICE_DRV_NAME); +} + +static int usbip_device_driver_open(struct usbip_host_driver *hdriver) +{ + int ret; + + hdriver->ndevs = 0; + INIT_LIST_HEAD(&hdriver->edev_list); + + ret = usbip_generic_driver_open(hdriver); + if (ret) + err("please load " USBIP_CORE_MOD_NAME ".ko and " + USBIP_DEVICE_DRV_NAME ".ko!"); + + return ret; +} + +struct usbip_host_driver device_driver = { + .edev_list = LIST_HEAD_INIT(device_driver.edev_list), + .udev_subsystem = "udc", + .ops = { + .open = usbip_device_driver_open, + .close = usbip_generic_driver_close, + .refresh_device_list = usbip_generic_refresh_device_list, + .get_device = usbip_generic_get_device, + .read_device = read_usb_vudc_device, + .is_my_device = is_my_device, + }, +}; diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.h b/tools/usb/usbip/libsrc/usbip_device_driver.h new file mode 100644 index 000000000000..54cb658b37a3 --- /dev/null +++ b/tools/usb/usbip/libsrc/usbip_device_driver.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015 Karol Kosik + * 2015 Samsung Electronics + * Author: Igor Kotrasinski + * + * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is: + * Copyright (C) 2011 matt mooney + * 2005-2007 Takahiro Hirofuchi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __USBIP_DEVICE_DRIVER_H +#define __USBIP_DEVICE_DRIVER_H + +#include +#include "usbip_common.h" +#include "usbip_host_common.h" +#include "list.h" + +extern struct usbip_host_driver device_driver; + +#endif /* __USBIP_DEVICE_DRIVER_H */ -- GitLab From e0546fd8b748b19d8edd1550530da8ebad6e4b31 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:49:06 +0100 Subject: [PATCH 4688/9938] usbip: tools: Start using VUDC backend in usbip tools Modify userspace tools to allow exporting and connecting to vudc. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Ewelina Kosmider <3w3lfin@gmail.com> [Various bug fixes and improvements] Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- tools/usb/usbip/src/usbip_attach.c | 10 +++- tools/usb/usbip/src/usbip_list.c | 96 +++++++++++++++++++++++++++++- tools/usb/usbip/src/usbipd.c | 12 +++- 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c index d58a14dfc094..70a6b507fb62 100644 --- a/tools/usb/usbip/src/usbip_attach.c +++ b/tools/usb/usbip/src/usbip_attach.c @@ -1,6 +1,9 @@ /* * Copyright (C) 2011 matt mooney * 2005-2007 Takahiro Hirofuchi + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,7 +39,8 @@ static const char usbip_attach_usage_string[] = "usbip attach \n" " -r, --remote= The machine with exported USB devices\n" - " -b, --busid= Busid of the device on \n"; + " -b, --busid= Busid of the device on \n" + " -d, --device= Id of the virtual UDC on \n"; void usbip_attach_usage(void) { @@ -203,6 +207,7 @@ int usbip_attach(int argc, char *argv[]) static const struct option opts[] = { { "remote", required_argument, NULL, 'r' }, { "busid", required_argument, NULL, 'b' }, + { "device", required_argument, NULL, 'd' }, { NULL, 0, NULL, 0 } }; char *host = NULL; @@ -211,7 +216,7 @@ int usbip_attach(int argc, char *argv[]) int ret = -1; for (;;) { - opt = getopt_long(argc, argv, "r:b:", opts, NULL); + opt = getopt_long(argc, argv, "d:r:b:", opts, NULL); if (opt == -1) break; @@ -220,6 +225,7 @@ int usbip_attach(int argc, char *argv[]) case 'r': host = optarg; break; + case 'd': case 'b': busid = optarg; break; diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c index d5ce34a410e7..f1b38e866dd7 100644 --- a/tools/usb/usbip/src/usbip_list.c +++ b/tools/usb/usbip/src/usbip_list.c @@ -1,6 +1,9 @@ /* * Copyright (C) 2011 matt mooney * 2005-2007 Takahiro Hirofuchi + * Copyright (C) 2015-2016 Samsung Electronics + * Igor Kotrasinski + * Krzysztof Opasiak * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +33,10 @@ #include #include +#include + +#include + #include "usbip_common.h" #include "usbip_network.h" #include "usbip.h" @@ -205,8 +212,10 @@ static int list_devices(bool parsable) /* Get device information. */ idVendor = udev_device_get_sysattr_value(dev, "idVendor"); idProduct = udev_device_get_sysattr_value(dev, "idProduct"); - bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue"); - bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces"); + bConfValue = udev_device_get_sysattr_value(dev, + "bConfigurationValue"); + bNumIntfs = udev_device_get_sysattr_value(dev, + "bNumInterfaces"); busid = udev_device_get_sysname(dev); if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { err("problem getting device attributes: %s", @@ -237,12 +246,90 @@ static int list_devices(bool parsable) return ret; } +static int list_gadget_devices(bool parsable) +{ + int ret = -1; + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + const char *path; + const char *driver; + + const struct usb_device_descriptor *d_desc; + const char *descriptors; + char product_name[128]; + + uint16_t idVendor; + char idVendor_buf[8]; + uint16_t idProduct; + char idProduct_buf[8]; + const char *busid; + + udev = udev_new(); + enumerate = udev_enumerate_new(udev); + + udev_enumerate_add_match_subsystem(enumerate, "platform"); + + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + + udev_list_entry_foreach(dev_list_entry, devices) { + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev, path); + + driver = udev_device_get_driver(dev); + /* We only have mechanism to enumerate gadgets bound to vudc */ + if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME)) + continue; + + /* Get device information. */ + descriptors = udev_device_get_sysattr_value(dev, + VUDC_DEVICE_DESCR_FILE); + + if (!descriptors) { + err("problem getting device attributes: %s", + strerror(errno)); + goto err_out; + } + + d_desc = (const struct usb_device_descriptor *) descriptors; + + idVendor = le16toh(d_desc->idVendor); + sprintf(idVendor_buf, "0x%4x", idVendor); + idProduct = le16toh(d_desc->idProduct); + sprintf(idProduct_buf, "0x%4x", idVendor); + busid = udev_device_get_sysname(dev); + + /* Get product name. */ + usbip_names_get_product(product_name, sizeof(product_name), + le16toh(idVendor), + le16toh(idProduct)); + + /* Print information. */ + print_device(busid, idVendor_buf, idProduct_buf, parsable); + print_product_name(product_name, parsable); + + printf("\n"); + + udev_device_unref(dev); + } + ret = 0; + +err_out: + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return ret; +} + int usbip_list(int argc, char *argv[]) { static const struct option opts[] = { { "parsable", no_argument, NULL, 'p' }, { "remote", required_argument, NULL, 'r' }, { "local", no_argument, NULL, 'l' }, + { "device", no_argument, NULL, 'd' }, { NULL, 0, NULL, 0 } }; @@ -254,7 +341,7 @@ int usbip_list(int argc, char *argv[]) err("failed to open %s", USBIDS_FILE); for (;;) { - opt = getopt_long(argc, argv, "pr:l", opts, NULL); + opt = getopt_long(argc, argv, "pr:ld", opts, NULL); if (opt == -1) break; @@ -269,6 +356,9 @@ int usbip_list(int argc, char *argv[]) case 'l': ret = list_devices(parsable); goto out; + case 'd': + ret = list_gadget_devices(parsable); + goto out; default: goto err_out; } diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c index 8a2ec4dab4bd..a0972dea9e6c 100644 --- a/tools/usb/usbip/src/usbipd.c +++ b/tools/usb/usbip/src/usbipd.c @@ -45,6 +45,7 @@ #include "usbip_host_driver.h" #include "usbip_host_common.h" +#include "usbip_device_driver.h" #include "usbip_common.h" #include "usbip_network.h" #include "list.h" @@ -68,6 +69,11 @@ static const char usbipd_help_string[] = " -6, --ipv6\n" " Bind to IPv6. Default is both.\n" "\n" + " -e, --device\n" + " Run in device mode.\n" + " Rather than drive an attached device, create\n" + " a virtual UDC to bind gadgets to.\n" + "\n" " -D, --daemon\n" " Run as a daemon process.\n" "\n" @@ -590,6 +596,7 @@ int main(int argc, char *argv[]) { "daemon", no_argument, NULL, 'D' }, { "daemon", no_argument, NULL, 'D' }, { "debug", no_argument, NULL, 'd' }, + { "device", no_argument, NULL, 'e' }, { "pid", optional_argument, NULL, 'P' }, { "tcp-port", required_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, @@ -618,7 +625,7 @@ int main(int argc, char *argv[]) cmd = cmd_standalone_mode; driver = &host_driver; for (;;) { - opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL); + opt = getopt_long(argc, argv, "46DdeP::t:hv", longopts, NULL); if (opt == -1) break; @@ -648,6 +655,9 @@ int main(int argc, char *argv[]) case 'v': cmd = cmd_version; break; + case 'e': + driver = &device_driver; + break; case '?': usbipd_help(); default: -- GitLab From 9360575c5837cfee841ad350de5be830b840d972 Mon Sep 17 00:00:00 2001 From: Igor Kotrasinski Date: Tue, 8 Mar 2016 21:49:07 +0100 Subject: [PATCH 4689/9938] usbip: vudc: Add vudc to Kconfig Add the driver to Kconfig to make it visible in menuconfig and allow people to compile it. This commit is a result of cooperation between Samsung R&D Institute Poland and Open Operating Systems Student Society at University of Warsaw (O2S3@UW) consisting of: Igor Kotrasinski Karol Kosik Ewelina Kosmider <3w3lfin@gmail.com> Dawid Lazarczyk Piotr Szulc Tutor and project owner: Krzysztof Opasiak Signed-off-by: Igor Kotrasinski Signed-off-by: Krzysztof Opasiak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/Kconfig | 11 +++++++++++ drivers/usb/usbip/Makefile | 3 +++ 2 files changed, 14 insertions(+) diff --git a/drivers/usb/usbip/Kconfig b/drivers/usb/usbip/Kconfig index bd99e9e47e50..ebf4ff050890 100644 --- a/drivers/usb/usbip/Kconfig +++ b/drivers/usb/usbip/Kconfig @@ -34,6 +34,17 @@ config USBIP_HOST To compile this driver as a module, choose M here: the module will be called usbip-host. +config USBIP_VUDC + tristate "VUDC driver" + depends on USBIP_CORE + ---help--- + This enables the USB/IP virtual USB device controller + driver, which is run on the host machine, allowing the + machine itself to act as a device. + + To compile this driver as a module, choose M here: the + module will be called usbip-vudc. + config USBIP_DEBUG bool "Debug messages for USB/IP" depends on USBIP_CORE diff --git a/drivers/usb/usbip/Makefile b/drivers/usb/usbip/Makefile index 9ecd61545be1..d843a9e68852 100644 --- a/drivers/usb/usbip/Makefile +++ b/drivers/usb/usbip/Makefile @@ -8,3 +8,6 @@ vhci-hcd-y := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o obj-$(CONFIG_USBIP_HOST) += usbip-host.o usbip-host-y := stub_dev.o stub_main.o stub_rx.o stub_tx.o + +obj-$(CONFIG_USBIP_VUDC) += usbip-vudc.o +usbip-vudc-y := vudc_dev.o vudc_sysfs.o vudc_tx.o vudc_rx.o vudc_transfer.o vudc_main.o -- GitLab From 98b74b0ee57af1bcb6e8b2e76e707a71c5ef8ec9 Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Tue, 8 Mar 2016 14:42:48 -0700 Subject: [PATCH 4690/9938] drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit. usb_submit_urb() may take quite long to execute. For example, a single sg list may have 30 or more entries, possibly leading to that many calls to DMA-map pages. This can cause interrupt latency of several hundred micro-seconds. Avoid the problem by releasing the io->lock spinlock and re-enabling interrupts before calling usb_submit_urb(). This opens races with usb_sg_cancel() and sg_complete(). Handle those races by using usb_block_urb() to stop URBs from being submitted after usb_sg_cancel() or sg_complete() with error. Note that usb_unlink_urb() is guaranteed to return -ENODEV if !io->urbs[i]->dev and since the -ENODEV case is already handled, we don't have to check for !io->urbs[i]->dev explicitly. Before this change, reading 512MB from an ext3 filesystem on a USB memory stick showed a throughput of 12 MB/s with about 500 missed deadlines. With this change, reading the same file gave the same throughput but only one or two missed deadlines. Signed-off-by: David Mosberger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 8e641b5893ed..e13a2e557715 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -302,9 +302,10 @@ static void sg_complete(struct urb *urb) */ spin_unlock(&io->lock); for (i = 0, found = 0; i < io->entries; i++) { - if (!io->urbs[i] || !io->urbs[i]->dev) + if (!io->urbs[i]) continue; if (found) { + usb_block_urb(io->urbs[i]); retval = usb_unlink_urb(io->urbs[i]); if (retval != -EINPROGRESS && retval != -ENODEV && @@ -515,12 +516,10 @@ void usb_sg_wait(struct usb_sg_request *io) int retval; io->urbs[i]->dev = io->dev; - retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC); - - /* after we submit, let completions or cancellations fire; - * we handshake using io->status. - */ spin_unlock_irq(&io->lock); + + retval = usb_submit_urb(io->urbs[i], GFP_NOIO); + switch (retval) { /* maybe we retrying will recover */ case -ENXIO: /* hc didn't queue this one */ @@ -590,8 +589,8 @@ void usb_sg_cancel(struct usb_sg_request *io) for (i = 0; i < io->entries; i++) { int retval; - if (!io->urbs[i]->dev) - continue; + usb_block_urb(io->urbs[i]); + retval = usb_unlink_urb(io->urbs[i]); if (retval != -EINPROGRESS && retval != -ENODEV -- GitLab From 5f2e5fb873e269fcb806165715d237f0de4ecf1d Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Tue, 8 Mar 2016 14:42:49 -0700 Subject: [PATCH 4691/9938] drivers: usb: core: Minimize irq disabling in usb_sg_cancel() Restructure usb_sg_cancel() so we don't have to disable interrupts while cancelling the URBs. Suggested-by: Alan Stern Signed-off-by: David Mosberger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index e13a2e557715..ea681f157368 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -577,31 +577,28 @@ EXPORT_SYMBOL_GPL(usb_sg_wait); void usb_sg_cancel(struct usb_sg_request *io) { unsigned long flags; + int i, retval; spin_lock_irqsave(&io->lock, flags); + if (io->status) { + spin_unlock_irqrestore(&io->lock, flags); + return; + } + /* shut everything down */ + io->status = -ECONNRESET; + spin_unlock_irqrestore(&io->lock, flags); - /* shut everything down, if it didn't already */ - if (!io->status) { - int i; + for (i = io->entries - 1; i >= 0; --i) { + usb_block_urb(io->urbs[i]); - io->status = -ECONNRESET; - spin_unlock(&io->lock); - for (i = 0; i < io->entries; i++) { - int retval; - - usb_block_urb(io->urbs[i]); - - retval = usb_unlink_urb(io->urbs[i]); - if (retval != -EINPROGRESS - && retval != -ENODEV - && retval != -EBUSY - && retval != -EIDRM) - dev_warn(&io->dev->dev, "%s, unlink --> %d\n", - __func__, retval); - } - spin_lock(&io->lock); + retval = usb_unlink_urb(io->urbs[i]); + if (retval != -EINPROGRESS + && retval != -ENODEV + && retval != -EBUSY + && retval != -EIDRM) + dev_warn(&io->dev->dev, "%s, unlink --> %d\n", + __func__, retval); } - spin_unlock_irqrestore(&io->lock, flags); } EXPORT_SYMBOL_GPL(usb_sg_cancel); -- GitLab From 5bcba792bb304e8341217d759ec486969a3b4258 Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Tue, 26 Apr 2016 11:56:38 -0700 Subject: [PATCH 4692/9938] localmodconfig: Fix whitespace repeat count after "tristate" Also recognize standalone "prompt". Before this patch we incorrectly identified some symbols as not having a prompt and potentially needing to be selected by something else. Note that this patch could theoretically change the resulting .config, causing it to have fewer symbols turned on. However, given the current set of Kconfig files, this situation does not occur because the symbols newly added to %prompts are absent from %selects. Link: http://lkml.kernel.org/r/1461696998-3953-1-git-send-email-bpoirier@suse.com Signed-off-by: Benjamin Poirier Signed-off-by: Steven Rostedt --- scripts/kconfig/streamline_config.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 95a6f2b888d4..b8c7b29affc5 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -237,7 +237,7 @@ sub read_kconfig { } # configs without prompts must be selected - } elsif ($state ne "NONE" && /^\s*tristate\s\S/) { + } elsif ($state ne "NONE" && /^\s*(tristate\s+\S|prompt\b)/) { # note if the config has a prompt $prompts{$config} = 1; -- GitLab From d2510342fe93d5ac8b807bc1d44b613eb5d9c64d Mon Sep 17 00:00:00 2001 From: Alexandr Ivanov Date: Fri, 22 Apr 2016 13:17:09 +0300 Subject: [PATCH 4693/9938] usb: xhci: merge xhci_queue_bulk_tx and queue_bulk_sg_tx functions In drivers/usb/host/xhci-ring.c there are two functions (xhci_queue_bulk_tx and queue_bulk_sg_tx) that are very similar, so a lot of code duplication. This patch merges these functions into to one xhci_queue_bulk_tx. Also counting the needed TRBs is merged and refactored. Signed-off-by: Alexandr Ivanov Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 406 ++++++++++------------------------- drivers/usb/host/xhci.h | 3 + 2 files changed, 121 insertions(+), 288 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 251e29954711..d7dd32edf7f1 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2938,46 +2938,55 @@ static int prepare_transfer(struct xhci_hcd *xhci, return 0; } -static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) +static unsigned int count_trbs(u64 addr, u64 len) +{ + unsigned int num_trbs; + + num_trbs = DIV_ROUND_UP(len + (addr & (TRB_MAX_BUFF_SIZE - 1)), + TRB_MAX_BUFF_SIZE); + if (num_trbs == 0) + num_trbs++; + + return num_trbs; +} + +static inline unsigned int count_trbs_needed(struct urb *urb) +{ + return count_trbs(urb->transfer_dma, urb->transfer_buffer_length); +} + +static unsigned int count_sg_trbs_needed(struct urb *urb) { - int num_sgs, num_trbs, running_total, temp, i; struct scatterlist *sg; + unsigned int i, len, full_len, num_trbs = 0; - sg = NULL; - num_sgs = urb->num_mapped_sgs; - temp = urb->transfer_buffer_length; + full_len = urb->transfer_buffer_length; - num_trbs = 0; - for_each_sg(urb->sg, sg, num_sgs, i) { - unsigned int len = sg_dma_len(sg); - - /* Scatter gather list entries may cross 64KB boundaries */ - running_total = TRB_MAX_BUFF_SIZE - - (sg_dma_address(sg) & (TRB_MAX_BUFF_SIZE - 1)); - running_total &= TRB_MAX_BUFF_SIZE - 1; - if (running_total != 0) - num_trbs++; - - /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total < sg_dma_len(sg) && running_total < temp) { - num_trbs++; - running_total += TRB_MAX_BUFF_SIZE; - } - len = min_t(int, len, temp); - temp -= len; - if (temp == 0) + for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { + len = sg_dma_len(sg); + num_trbs += count_trbs(sg_dma_address(sg), len); + len = min_t(unsigned int, len, full_len); + full_len -= len; + if (full_len == 0) break; } + return num_trbs; } -static void check_trb_math(struct urb *urb, int num_trbs, int running_total) +static unsigned int count_isoc_trbs_needed(struct urb *urb, int i) +{ + u64 addr, len; + + addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset); + len = urb->iso_frame_desc[i].length; + + return count_trbs(addr, len); +} + +static void check_trb_math(struct urb *urb, int running_total) { - if (num_trbs != 0) - dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated number of " - "TRBs, %d left\n", __func__, - urb->ep->desc.bEndpointAddress, num_trbs); - if (running_total != urb->transfer_buffer_length) + if (unlikely(running_total != urb->transfer_buffer_length)) dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, " "queued %#x (%d), asked for %#x (%d)\n", __func__, @@ -3086,44 +3095,47 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, return (total_packet_count - ((transferred + trb_buff_len) / maxp)); } - -static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, +/* This is very similar to what ehci-q.c qtd_fill() does */ +int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) { struct xhci_ring *ep_ring; - unsigned int num_trbs; struct urb_priv *urb_priv; struct xhci_td *td; - struct scatterlist *sg; - int num_sgs; - int trb_buff_len, this_sg_len, running_total, ret; - unsigned int total_packet_count; + struct xhci_generic_trb *start_trb; + struct scatterlist *sg = NULL; + bool more_trbs_coming; bool zero_length_needed; - bool first_trb; - int last_trb_num; + unsigned int num_trbs, last_trb_num, i; + unsigned int start_cycle, num_sgs = 0; + unsigned int running_total, block_len, trb_buff_len; + unsigned int full_len; + int ret; + u32 field, length_field, remainder; u64 addr; - bool more_trbs_coming; - - struct xhci_generic_trb *start_trb; - int start_cycle; ep_ring = xhci_urb_to_transfer_ring(xhci, urb); if (!ep_ring) return -EINVAL; - num_trbs = count_sg_trbs_needed(xhci, urb); - num_sgs = urb->num_mapped_sgs; - total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, - usb_endpoint_maxp(&urb->ep->desc)); + /* If we have scatter/gather list, we use it. */ + if (urb->num_sgs) { + num_sgs = urb->num_mapped_sgs; + sg = urb->sg; + num_trbs = count_sg_trbs_needed(urb); + } else + num_trbs = count_trbs_needed(urb); ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, mem_flags); - if (ret < 0) + if (unlikely(ret < 0)) return ret; urb_priv = urb->hcpriv; + last_trb_num = num_trbs - 1; + /* Deal with URB_ZERO_PACKET - need one more td/trb */ zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && urb_priv->length == 2; @@ -3133,7 +3145,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, 1, urb, 1, mem_flags); - if (ret < 0) + if (unlikely(ret < 0)) return ret; } @@ -3147,228 +3159,58 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, start_trb = &ep_ring->enqueue->generic; start_cycle = ep_ring->cycle_state; + full_len = urb->transfer_buffer_length; running_total = 0; - /* - * How much data is in the first TRB? - * - * There are three forces at work for TRB buffer pointers and lengths: - * 1. We don't want to walk off the end of this sg-list entry buffer. - * 2. The transfer length that the driver requested may be smaller than - * the amount of memory allocated for this scatter-gather list. - * 3. TRBs buffers can't cross 64KB boundaries. - */ - sg = urb->sg; - addr = (u64) sg_dma_address(sg); - this_sg_len = sg_dma_len(sg); - trb_buff_len = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1)); - trb_buff_len = min_t(int, trb_buff_len, this_sg_len); - if (trb_buff_len > urb->transfer_buffer_length) - trb_buff_len = urb->transfer_buffer_length; - - first_trb = true; - last_trb_num = zero_length_needed ? 2 : 1; - /* Queue the first TRB, even if it's zero-length */ - do { - u32 field = 0; - u32 length_field = 0; - u32 remainder = 0; + block_len = 0; - /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) { - first_trb = false; - if (start_cycle == 0) - field |= 0x1; - } else - field |= ep_ring->cycle_state; - - /* Chain all the TRBs together; clear the chain bit in the last - * TRB to indicate it's the last TRB in the chain. - */ - if (num_trbs > last_trb_num) { - field |= TRB_CHAIN; - } else if (num_trbs == last_trb_num) { - td->last_trb = ep_ring->enqueue; - field |= TRB_IOC; - } else if (zero_length_needed && num_trbs == 1) { - trb_buff_len = 0; - urb_priv->td[1]->last_trb = ep_ring->enqueue; - field |= TRB_IOC; - } - - /* Only set interrupt on short packet for IN endpoints */ - if (usb_urb_dir_in(urb)) - field |= TRB_ISP; + /* Queue the TRBs, even if they are zero-length */ + for (i = 0; i < num_trbs; i++) { + field = TRB_TYPE(TRB_NORMAL); - if (TRB_MAX_BUFF_SIZE - - (addr & (TRB_MAX_BUFF_SIZE - 1)) < trb_buff_len) { - xhci_warn(xhci, "WARN: sg dma xfer crosses 64KB boundaries!\n"); - xhci_dbg(xhci, "Next boundary at %#x, end dma = %#x\n", - (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1), - (unsigned int) addr + trb_buff_len); - } - - /* Set the TRB length, TD size, and interrupter fields. */ - remainder = xhci_td_remainder(xhci, running_total, trb_buff_len, - urb->transfer_buffer_length, - urb, num_trbs - 1); - - length_field = TRB_LEN(trb_buff_len) | - TRB_TD_SIZE(remainder) | - TRB_INTR_TARGET(0); - - if (num_trbs > 1) - more_trbs_coming = true; - else - more_trbs_coming = false; - queue_trb(xhci, ep_ring, more_trbs_coming, - lower_32_bits(addr), - upper_32_bits(addr), - length_field, - field | TRB_TYPE(TRB_NORMAL)); - --num_trbs; - running_total += trb_buff_len; - - /* Calculate length for next transfer -- - * Are we done queueing all the TRBs for this sg entry? - */ - this_sg_len -= trb_buff_len; - if (this_sg_len == 0) { - --num_sgs; - if (num_sgs == 0) - break; - sg = sg_next(sg); - addr = (u64) sg_dma_address(sg); - this_sg_len = sg_dma_len(sg); + if (block_len == 0) { + /* A new contiguous block. */ + if (sg) { + addr = (u64) sg_dma_address(sg); + block_len = sg_dma_len(sg); + } else { + addr = (u64) urb->transfer_dma; + block_len = full_len; + } + /* TRB buffer should not cross 64KB boundaries */ + trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(addr); + trb_buff_len = min_t(unsigned int, + trb_buff_len, + block_len); } else { - addr += trb_buff_len; + /* Further through the contiguous block. */ + trb_buff_len = block_len; + if (trb_buff_len > TRB_MAX_BUFF_SIZE) + trb_buff_len = TRB_MAX_BUFF_SIZE; } - trb_buff_len = TRB_MAX_BUFF_SIZE - - (addr & (TRB_MAX_BUFF_SIZE - 1)); - trb_buff_len = min_t(int, trb_buff_len, this_sg_len); - if (running_total + trb_buff_len > urb->transfer_buffer_length) - trb_buff_len = - urb->transfer_buffer_length - running_total; - } while (num_trbs > 0); - - check_trb_math(urb, num_trbs, running_total); - giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, - start_cycle, start_trb); - return 0; -} - -/* This is very similar to what ehci-q.c qtd_fill() does */ -int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, - struct urb *urb, int slot_id, unsigned int ep_index) -{ - struct xhci_ring *ep_ring; - struct urb_priv *urb_priv; - struct xhci_td *td; - int num_trbs; - struct xhci_generic_trb *start_trb; - bool first_trb; - int last_trb_num; - bool more_trbs_coming; - bool zero_length_needed; - int start_cycle; - u32 field, length_field; - - int running_total, trb_buff_len, ret; - unsigned int total_packet_count; - u64 addr; - - if (urb->num_sgs) - return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index); - - ep_ring = xhci_urb_to_transfer_ring(xhci, urb); - if (!ep_ring) - return -EINVAL; - - num_trbs = 0; - /* How much data is (potentially) left before the 64KB boundary? */ - running_total = TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1)); - running_total &= TRB_MAX_BUFF_SIZE - 1; - - /* If there's some data on this 64KB chunk, or we have to send a - * zero-length transfer, we need at least one TRB - */ - if (running_total != 0 || urb->transfer_buffer_length == 0) - num_trbs++; - /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total < urb->transfer_buffer_length) { - num_trbs++; - running_total += TRB_MAX_BUFF_SIZE; - } - - ret = prepare_transfer(xhci, xhci->devs[slot_id], - ep_index, urb->stream_id, - num_trbs, urb, 0, mem_flags); - if (ret < 0) - return ret; - - urb_priv = urb->hcpriv; - - /* Deal with URB_ZERO_PACKET - need one more td/trb */ - zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && - urb_priv->length == 2; - if (zero_length_needed) { - num_trbs++; - xhci_dbg(xhci, "Creating zero length td.\n"); - ret = prepare_transfer(xhci, xhci->devs[slot_id], - ep_index, urb->stream_id, - 1, urb, 1, mem_flags); - if (ret < 0) - return ret; - } - - td = urb_priv->td[0]; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ep_ring->enqueue->generic; - start_cycle = ep_ring->cycle_state; - - running_total = 0; - total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, - usb_endpoint_maxp(&urb->ep->desc)); - /* How much data is in the first TRB? */ - addr = (u64) urb->transfer_dma; - trb_buff_len = TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1)); - if (trb_buff_len > urb->transfer_buffer_length) - trb_buff_len = urb->transfer_buffer_length; - - first_trb = true; - last_trb_num = zero_length_needed ? 2 : 1; - /* Queue the first TRB, even if it's zero-length */ - do { - u32 remainder = 0; - field = 0; + if (running_total + trb_buff_len > full_len) + trb_buff_len = full_len - running_total; /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) { - first_trb = false; + if (i == 0) { if (start_cycle == 0) - field |= 0x1; + field |= TRB_CYCLE; } else field |= ep_ring->cycle_state; /* Chain all the TRBs together; clear the chain bit in the last * TRB to indicate it's the last TRB in the chain. */ - if (num_trbs > last_trb_num) { + if (i < last_trb_num) { field |= TRB_CHAIN; - } else if (num_trbs == last_trb_num) { - td->last_trb = ep_ring->enqueue; - field |= TRB_IOC; - } else if (zero_length_needed && num_trbs == 1) { - trb_buff_len = 0; - urb_priv->td[1]->last_trb = ep_ring->enqueue; + } else { field |= TRB_IOC; + if (i == last_trb_num) + td->last_trb = ep_ring->enqueue; + else if (zero_length_needed) { + trb_buff_len = 0; + urb_priv->td[1]->last_trb = ep_ring->enqueue; + } } /* Only set interrupt on short packet for IN endpoints */ @@ -3376,15 +3218,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field |= TRB_ISP; /* Set the TRB length, TD size, and interrupter fields. */ - remainder = xhci_td_remainder(xhci, running_total, trb_buff_len, - urb->transfer_buffer_length, - urb, num_trbs - 1); + remainder = xhci_td_remainder(xhci, running_total, + trb_buff_len, full_len, + urb, num_trbs - i - 1); length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0); - if (num_trbs > 1) + if (i < num_trbs - 1) more_trbs_coming = true; else more_trbs_coming = false; @@ -3392,18 +3234,24 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, lower_32_bits(addr), upper_32_bits(addr), length_field, - field | TRB_TYPE(TRB_NORMAL)); - --num_trbs; - running_total += trb_buff_len; + field); - /* Calculate length for next transfer */ + running_total += trb_buff_len; addr += trb_buff_len; - trb_buff_len = urb->transfer_buffer_length - running_total; - if (trb_buff_len > TRB_MAX_BUFF_SIZE) - trb_buff_len = TRB_MAX_BUFF_SIZE; - } while (num_trbs > 0); + block_len -= trb_buff_len; + + if (sg) { + if (block_len == 0) { + /* New sg entry */ + --num_sgs; + if (num_sgs == 0) + break; + sg = sg_next(sg); + } + } + } - check_trb_math(urb, num_trbs, running_total); + check_trb_math(urb, running_total); giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, start_cycle, start_trb); return 0; @@ -3532,23 +3380,6 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return 0; } -static int count_isoc_trbs_needed(struct xhci_hcd *xhci, - struct urb *urb, int i) -{ - int num_trbs = 0; - u64 addr, td_len; - - addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset); - td_len = urb->iso_frame_desc[i].length; - - num_trbs = DIV_ROUND_UP(td_len + (addr & (TRB_MAX_BUFF_SIZE - 1)), - TRB_MAX_BUFF_SIZE); - if (num_trbs == 0) - num_trbs++; - - return num_trbs; -} - /* * The transfer burst count field of the isochronous TRB defines the number of * bursts that are required to move all packets in this TD. Only SuperSpeed @@ -3746,7 +3577,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, last_burst_pkt_count = xhci_get_last_burst_packet_count(xhci, urb, total_pkt_count); - trbs_per_td = count_isoc_trbs_needed(xhci, urb, i); + trbs_per_td = count_isoc_trbs_needed(urb, i); ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, trbs_per_td, urb, i, mem_flags); @@ -3807,8 +3638,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field |= TRB_BEI; } /* Calculate TRB length */ - trb_buff_len = TRB_MAX_BUFF_SIZE - - (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); + trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(addr); if (trb_buff_len > td_remain_len) trb_buff_len = td_remain_len; @@ -3912,7 +3742,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, num_trbs = 0; num_tds = urb->number_of_packets; for (i = 0; i < num_tds; i++) - num_trbs += count_isoc_trbs_needed(xhci, urb, i); + num_trbs += count_isoc_trbs_needed(urb, i); /* Check the ring to guarantee there is enough room for the whole urb. * Do not insert any td of the urb to the ring if the check failed. diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6c629c97f8ad..8fd35a65913d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1338,6 +1338,9 @@ union xhci_trb { /* TRB buffer pointers can't cross 64KB boundaries */ #define TRB_MAX_BUFF_SHIFT 16 #define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT) +/* How much data is left before the 64KB boundary? */ +#define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_BUFF_SIZE - \ + (addr & (TRB_MAX_BUFF_SIZE - 1))) struct xhci_segment { union xhci_trb *trbs; -- GitLab From 75b040ec60a8bf0ef7f69fcfc8dd81c8f75eabc7 Mon Sep 17 00:00:00 2001 From: Alexandr Ivanov Date: Fri, 22 Apr 2016 13:17:10 +0300 Subject: [PATCH 4694/9938] usb: xhci: remove duplicate function xhci_urb_to_transfer_ring Remove duplicate function xhci_urb_to_transfer_ring from xhci.c. We have same function in xhci-ring.c. Signed-off-by: Alexandr Ivanov Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 17 +++++---------- drivers/usb/host/xhci.c | 41 ------------------------------------ drivers/usb/host/xhci.h | 11 ++++++++++ 3 files changed, 16 insertions(+), 53 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index d7dd32edf7f1..c3ecbd1b37fe 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -373,7 +373,11 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci, } } -static struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, +/* Get the right ring for the given slot_id, ep_index and stream_id. + * If the endpoint supports streams, boundary check the URB's stream ID. + * If the endpoint doesn't support streams, return the singular endpoint ring. + */ +struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id) { @@ -405,17 +409,6 @@ static struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, return NULL; } -/* Get the right ring for the given URB. - * If the endpoint supports streams, boundary check the URB's stream ID. - * If the endpoint doesn't support streams, return the singular endpoint ring. - */ -static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, - struct urb *urb) -{ - return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, - xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); -} - /* * Move the xHC's endpoint ring dequeue pointer past cur_td. * Record the new state of the xHC's endpoint ring dequeue segment, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9e71c96ad74a..fa7e1ef36cd9 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1459,47 +1459,6 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) return ret; } -/* Get the right ring for the given URB. - * If the endpoint supports streams, boundary check the URB's stream ID. - * If the endpoint doesn't support streams, return the singular endpoint ring. - */ -static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, - struct urb *urb) -{ - unsigned int slot_id; - unsigned int ep_index; - unsigned int stream_id; - struct xhci_virt_ep *ep; - - slot_id = urb->dev->slot_id; - ep_index = xhci_get_endpoint_index(&urb->ep->desc); - stream_id = urb->stream_id; - ep = &xhci->devs[slot_id]->eps[ep_index]; - /* Common case: no streams */ - if (!(ep->ep_state & EP_HAS_STREAMS)) - return ep->ring; - - if (stream_id == 0) { - xhci_warn(xhci, - "WARN: Slot ID %u, ep index %u has streams, " - "but URB has no stream ID.\n", - slot_id, ep_index); - return NULL; - } - - if (stream_id < ep->stream_info->num_streams) - return ep->stream_info->stream_rings[stream_id]; - - xhci_warn(xhci, - "WARN: Slot ID %u, ep index %u has " - "stream IDs 1 to %u allocated, " - "but stream ID %u is requested.\n", - slot_id, ep_index, - ep->stream_info->num_streams - 1, - stream_id); - return NULL; -} - /* * Remove the URB's TD from the endpoint ring. This may cause the HC to stop * USB transfers, potentially stopping in the middle of a TRB buffer. The HC diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8fd35a65913d..b0b8d0f8791a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1968,4 +1968,15 @@ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index); +struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, + unsigned int slot_id, unsigned int ep_index, + unsigned int stream_id); +static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, + struct urb *urb) +{ + return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, + xhci_get_endpoint_index(&urb->ep->desc), + urb->stream_id); +} + #endif /* __LINUX_XHCI_HCD_H */ -- GitLab From 78140156f47ed8a9b07fd6a5766d03d3d837aaca Mon Sep 17 00:00:00 2001 From: Alexandr Ivanov Date: Fri, 22 Apr 2016 13:17:11 +0300 Subject: [PATCH 4695/9938] usb: xhci: remove duplicate code of interval checking Move duplicate code from xhci_queue_intr_tx() and xhci_queue_isoc_tx_prepare() to the check_interval() function. Signed-off-by: Alexandr Ivanov Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 53 ++++++++++++++---------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c3ecbd1b37fe..52deae4b7eac 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3005,26 +3005,20 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); } -/* - * xHCI uses normal TRBs for both bulk and interrupt. When the interrupt - * endpoint is to be serviced, the xHC will consume (at most) one TD. A TD - * (comprised of sg list entries) can take several service intervals to - * transmit. - */ -int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, - struct urb *urb, int slot_id, unsigned int ep_index) +static void check_interval(struct xhci_hcd *xhci, struct urb *urb, + struct xhci_ep_ctx *ep_ctx) { - struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, - xhci->devs[slot_id]->out_ctx, ep_index); int xhci_interval; int ep_interval; xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info)); ep_interval = urb->interval; + /* Convert to microframes */ if (urb->dev->speed == USB_SPEED_LOW || urb->dev->speed == USB_SPEED_FULL) ep_interval *= 8; + /* FIXME change this to a warning and a suggestion to use the new API * to set the polling interval (once the API is added). */ @@ -3039,6 +3033,22 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb->dev->speed == USB_SPEED_FULL) urb->interval /= 8; } +} + +/* + * xHCI uses normal TRBs for both bulk and interrupt. When the interrupt + * endpoint is to be serviced, the xHC will consume (at most) one TD. A TD + * (comprised of sg list entries) can take several service intervals to + * transmit. + */ +int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + struct urb *urb, int slot_id, unsigned int ep_index) +{ + struct xhci_ep_ctx *ep_ctx; + + ep_ctx = xhci_get_ep_ctx(xhci, xhci->devs[slot_id]->out_ctx, ep_index); + check_interval(xhci, urb, ep_ctx); + return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index); } @@ -3720,8 +3730,6 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_ring *ep_ring; struct xhci_ep_ctx *ep_ctx; int start_frame; - int xhci_interval; - int ep_interval; int num_tds, num_trbs, i; int ret; struct xhci_virt_ep *xep; @@ -3749,26 +3757,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, * Check interval value. This should be done before we start to * calculate the start frame value. */ - xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info)); - ep_interval = urb->interval; - /* Convert to microframes */ - if (urb->dev->speed == USB_SPEED_LOW || - urb->dev->speed == USB_SPEED_FULL) - ep_interval *= 8; - /* FIXME change this to a warning and a suggestion to use the new API - * to set the polling interval (once the API is added). - */ - if (xhci_interval != ep_interval) { - dev_dbg_ratelimited(&urb->dev->dev, - "Driver uses different interval (%d microframe%s) than xHCI (%d microframe%s)\n", - ep_interval, ep_interval == 1 ? "" : "s", - xhci_interval, xhci_interval == 1 ? "" : "s"); - urb->interval = xhci_interval; - /* Convert back to frames for LS/FS devices */ - if (urb->dev->speed == USB_SPEED_LOW || - urb->dev->speed == USB_SPEED_FULL) - urb->interval /= 8; - } + check_interval(xhci, urb, ep_ctx); /* Calculate the start frame and put it in urb->start_frame. */ if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) { -- GitLab From 2dc240a3308b269ac344036e2f41fc48532c2f04 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Apr 2016 13:17:12 +0300 Subject: [PATCH 4696/9938] usb: host: xhci: rcar: retire use of xhci_plat_type_is() We're preparing to remove xhci_plat_type_is() in favor of a better approach where we define function pointers ahead of time. This will let us make assumptions about which platforms we're running on and which platform-specific functions we should call. Acked-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi [delete extra comma in function parameters -Mathias] Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-rcar.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index 623100e9385e..0e4535e632ec 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "xhci.h" @@ -76,6 +77,24 @@ static void xhci_rcar_start_gen2(struct usb_hcd *hcd) writel(RCAR_USB3_TX_POL_VAL, hcd->regs + RCAR_USB3_TX_POL); } +static int xhci_rcar_is_gen2(struct device *dev) +{ + struct device_node *node = dev->of_node; + + return of_device_is_compatible(node, "renesas,xhci-r8a7790") || + of_device_is_compatible(node, "renesas,xhci-r8a7791") || + of_device_is_compatible(node, "renesas,xhci-r8a7793") || + of_device_is_compatible(node, "renensas,rcar-gen2-xhci"); +} + +static int xhci_rcar_is_gen3(struct device *dev) +{ + struct device_node *node = dev->of_node; + + return of_device_is_compatible(node, "renesas,xhci-r8a7795") || + of_device_is_compatible(node, "renesas,rcar-gen3-xhci"); +} + void xhci_rcar_start(struct usb_hcd *hcd) { u32 temp; @@ -85,7 +104,7 @@ void xhci_rcar_start(struct usb_hcd *hcd) temp = readl(hcd->regs + RCAR_USB3_INT_ENA); temp |= RCAR_USB3_INT_ENA_VAL; writel(temp, hcd->regs + RCAR_USB3_INT_ENA); - if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_RENESAS_RCAR_GEN2)) + if (xhci_rcar_is_gen2(hcd->self.controller)) xhci_rcar_start_gen2(hcd); } } @@ -156,9 +175,22 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd) /* This function needs to initialize a "phy" of usb before */ int xhci_rcar_init_quirk(struct usb_hcd *hcd) { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + /* If hcd->regs is NULL, we don't just call the following function */ if (!hcd->regs) return 0; + /* + * On R-Car Gen2 and Gen3, the AC64 bit (bit 0) of HCCPARAMS1 is set + * to 1. However, these SoCs don't support 64-bit address memory + * pointers. So, this driver clears the AC64 bit of xhci->hcc_params + * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in + * xhci_gen_setup(). + */ + if (xhci_rcar_is_gen2(hcd->self.controller) || + xhci_rcar_is_gen3(hcd->self.controller)) + xhci->quirks |= XHCI_NO_64BIT_SUPPORT; + return xhci_rcar_download_firmware(hcd); } -- GitLab From 7eca937ec8b9a2e9c495ea9232ffe2b71d036bb1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Apr 2016 13:17:13 +0300 Subject: [PATCH 4697/9938] usb: xhci: plat: add ->plat_start() and ->init_quirk() methods these two methods will be used to hide platform-specific details so we can get rid of xhci_plat_type_is() in a later patch. Acked-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 529c3c40f901..3cc9b2208683 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -22,6 +22,8 @@ enum xhci_plat_type { struct xhci_plat_priv { enum xhci_plat_type type; const char *firmware_name; + void (*plat_start)(struct usb_hcd *); + int (*init_quirk)(struct usb_hcd *); }; #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) -- GitLab From 3bdb263d6b3c2384d98745897ba9db676806ed04 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Apr 2016 13:17:14 +0300 Subject: [PATCH 4698/9938] usb: host: xhci: plat: move mvebu init_quirk() to xhci_plat_setup() xhci_plat_setup() is the rightful place for xhci_mvebu_mbus_init_quirk(), so let's move it there in order to make it simpler to get rid of xhci_plat_type_is() later on. Acked-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 474b5fa14900..4fcb3418e7a7 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -72,6 +72,15 @@ static int xhci_plat_setup(struct usb_hcd *hcd) return ret; } + if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_MARVELL_ARMADA)) { + struct platform_device *pdev; + + pdev = to_platform_device(hcd->self.controller); + ret = xhci_mvebu_mbus_init_quirk(pdev); + if (ret) + return ret; + } + return xhci_gen_setup(hcd, xhci_plat_quirks); } @@ -207,12 +216,6 @@ static int xhci_plat_probe(struct platform_device *pdev) *priv = *priv_match; } - if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_MARVELL_ARMADA)) { - ret = xhci_mvebu_mbus_init_quirk(pdev); - if (ret) - goto disable_clk; - } - device_wakeup_enable(hcd->self.controller); xhci->clk = clk; -- GitLab From 72d4b2847d3d31fcc3910e18b72d026987626c8d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Apr 2016 13:17:15 +0300 Subject: [PATCH 4699/9938] usb: host: xhci: plat: change type of mvebu init_quirk() Just like RCAR's init_quirk() we want mvebu's to use struct usb_hcd * as argument too. This is another step towards removing xhci_plat_type_is(). Acked-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mvebu.c | 7 ++++++- drivers/usb/host/xhci-mvebu.h | 7 +++++-- drivers/usb/host/xhci-plat.c | 5 +---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c index 1eefc988192d..85908a3ecb8f 100644 --- a/drivers/usb/host/xhci-mvebu.c +++ b/drivers/usb/host/xhci-mvebu.c @@ -12,6 +12,9 @@ #include #include +#include +#include + #include "xhci-mvebu.h" #define USB3_MAX_WINDOWS 4 @@ -41,8 +44,10 @@ static void xhci_mvebu_mbus_config(void __iomem *base, } } -int xhci_mvebu_mbus_init_quirk(struct platform_device *pdev) +int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) { + struct device *dev = hcd->self.controller; + struct platform_device *pdev = to_platform_device(dev); struct resource *res; void __iomem *base; const struct mbus_dram_target_info *dram; diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h index 7ede92aa41f6..301fc984cae6 100644 --- a/drivers/usb/host/xhci-mvebu.h +++ b/drivers/usb/host/xhci-mvebu.h @@ -10,10 +10,13 @@ #ifndef __LINUX_XHCI_MVEBU_H #define __LINUX_XHCI_MVEBU_H + +struct usb_hcd; + #if IS_ENABLED(CONFIG_USB_XHCI_MVEBU) -int xhci_mvebu_mbus_init_quirk(struct platform_device *pdev); +int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd); #else -static inline int xhci_mvebu_mbus_init_quirk(struct platform_device *pdev) +static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) { return 0; } diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 4fcb3418e7a7..9bdf016d9080 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -73,10 +73,7 @@ static int xhci_plat_setup(struct usb_hcd *hcd) } if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_MARVELL_ARMADA)) { - struct platform_device *pdev; - - pdev = to_platform_device(hcd->self.controller); - ret = xhci_mvebu_mbus_init_quirk(pdev); + ret = xhci_mvebu_mbus_init_quirk(hcd); if (ret) return ret; } -- GitLab From b1c127ae990bccf0187d741c1695a61e54de1943 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Apr 2016 13:17:16 +0300 Subject: [PATCH 4700/9938] usb: host: xhci: plat: make use of new methods in xhci_plat_priv Now that the code has been refactored enough, switching over to using ->plat_start() and ->init_quirk() becomes a very simple patch. After this patch, there are no further uses for xhci_plat_type_is() which will be removed in a follow-up patch. Acked-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 55 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 9bdf016d9080..9e84992805d6 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -37,27 +37,32 @@ static const struct xhci_driver_overrides xhci_plat_overrides __initconst = { .start = xhci_plat_start, }; -static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) +static void xhci_priv_plat_start(struct usb_hcd *hcd) +{ + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + + if (priv->plat_start) + priv->plat_start(hcd); +} + +static int xhci_priv_init_quirk(struct usb_hcd *hcd) { - struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + + if (!priv->init_quirk) + return 0; + return priv->init_quirk(hcd); +} + +static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) +{ /* * As of now platform drivers don't provide MSI support so we ensure * here that the generic code does not try to make a pci_dev from our * dev struct in order to setup MSI */ xhci->quirks |= XHCI_PLAT; - - /* - * On R-Car Gen2 and Gen3, the AC64 bit (bit 0) of HCCPARAMS1 is set - * to 1. However, these SoCs don't support 64-bit address memory - * pointers. So, this driver clears the AC64 bit of xhci->hcc_params - * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in - * xhci_gen_setup(). - */ - if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_RENESAS_RCAR_GEN2) || - xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_RENESAS_RCAR_GEN3)) - xhci->quirks |= XHCI_NO_64BIT_SUPPORT; } /* called during probe() after chip reset completes */ @@ -65,44 +70,38 @@ static int xhci_plat_setup(struct usb_hcd *hcd) { int ret; - if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_RENESAS_RCAR_GEN2) || - xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_RENESAS_RCAR_GEN3)) { - ret = xhci_rcar_init_quirk(hcd); - if (ret) - return ret; - } - if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_MARVELL_ARMADA)) { - ret = xhci_mvebu_mbus_init_quirk(hcd); - if (ret) - return ret; - } + ret = xhci_priv_init_quirk(hcd); + if (ret) + return ret; return xhci_gen_setup(hcd, xhci_plat_quirks); } static int xhci_plat_start(struct usb_hcd *hcd) { - if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_RENESAS_RCAR_GEN2) || - xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_RENESAS_RCAR_GEN3)) - xhci_rcar_start(hcd); - + xhci_priv_plat_start(hcd); return xhci_run(hcd); } #ifdef CONFIG_OF static const struct xhci_plat_priv xhci_plat_marvell_armada = { .type = XHCI_PLAT_TYPE_MARVELL_ARMADA, + .init_quirk = xhci_mvebu_mbus_init_quirk, }; static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = { .type = XHCI_PLAT_TYPE_RENESAS_RCAR_GEN2, .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1, + .init_quirk = xhci_rcar_init_quirk, + .plat_start = xhci_rcar_start, }; static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { .type = XHCI_PLAT_TYPE_RENESAS_RCAR_GEN3, .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V2, + .init_quirk = xhci_rcar_init_quirk, + .plat_start = xhci_rcar_start, }; static const struct of_device_id usb_xhci_of_match[] = { -- GitLab From c06fac7fa0a09a791b01f2cd963cbacdc878d69f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Apr 2016 13:17:17 +0300 Subject: [PATCH 4701/9938] usb: host: xhci: plat: finally get rid of xhci_plat_type_is() Now that there are no more users for xhci_plat_type_is(), we can safely remove it. Acked-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 3 --- drivers/usb/host/xhci-plat.h | 18 ------------------ 2 files changed, 21 deletions(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 9e84992805d6..676ea458148b 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -86,19 +86,16 @@ static int xhci_plat_start(struct usb_hcd *hcd) #ifdef CONFIG_OF static const struct xhci_plat_priv xhci_plat_marvell_armada = { - .type = XHCI_PLAT_TYPE_MARVELL_ARMADA, .init_quirk = xhci_mvebu_mbus_init_quirk, }; static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = { - .type = XHCI_PLAT_TYPE_RENESAS_RCAR_GEN2, .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1, .init_quirk = xhci_rcar_init_quirk, .plat_start = xhci_rcar_start, }; static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { - .type = XHCI_PLAT_TYPE_RENESAS_RCAR_GEN3, .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V2, .init_quirk = xhci_rcar_init_quirk, .plat_start = xhci_rcar_start, diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 3cc9b2208683..9af0cb48053f 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -13,29 +13,11 @@ #include "xhci.h" /* for hcd_to_xhci() */ -enum xhci_plat_type { - XHCI_PLAT_TYPE_MARVELL_ARMADA = 1, - XHCI_PLAT_TYPE_RENESAS_RCAR_GEN2, - XHCI_PLAT_TYPE_RENESAS_RCAR_GEN3, -}; - struct xhci_plat_priv { - enum xhci_plat_type type; const char *firmware_name; void (*plat_start)(struct usb_hcd *); int (*init_quirk)(struct usb_hcd *); }; #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) - -static inline bool xhci_plat_type_is(struct usb_hcd *hcd, - enum xhci_plat_type type) -{ - struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); - - if (priv && priv->type == type) - return true; - else - return false; -} #endif /* _XHCI_PLAT_H */ -- GitLab From 1507372b97a098fd51b92c4dbdbbcd65cba26939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 23 Mar 2016 12:37:11 +0100 Subject: [PATCH 4702/9938] USB: bcma: use simpler devm helper for getting vcc GPIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to switching to devm_gpiod_get: 1) We don't have to pass fwnode pointer 2) We can request initial GPIO value at getting call This was successfully tested on Netgear R6250 (BCM4708). Signed-off-by: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/bcma-hcd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 963e2d0e8f92..172ef17911aa 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -352,10 +352,8 @@ static int bcma_hcd_probe(struct bcma_device *core) usb_dev->core = core; if (core->dev.of_node) - usb_dev->gpio_desc = devm_get_gpiod_from_child(&core->dev, "vcc", - &core->dev.of_node->fwnode); - if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) - gpiod_direction_output(usb_dev->gpio_desc, 1); + usb_dev->gpio_desc = devm_gpiod_get(&core->dev, "vcc", + GPIOD_OUT_HIGH); switch (core->id.id) { case BCMA_CORE_USB20_HOST: -- GitLab From 328fafb94fa136bfa19b4ebc54d1f8cfcad13801 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 26 Mar 2016 21:03:53 +0000 Subject: [PATCH 4703/9938] usb: hcd: do not call whc_clean_up on wch_init call failure whc_init already calls whc_clean_up if an error occurs during the initialization, so calling it again if whc_init fails at the end of wch_probe will cause double free errors. Fix this by bailing out on an whc_init failure to a new label that avoids doing the duplicated whc_clean_up. Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/whci/hcd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 43626c44683b..5b3603c360ab 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c @@ -257,14 +257,14 @@ static int whc_probe(struct umc_dev *umc) ret = whc_init(whc); if (ret) - goto error; + goto error_whc_init; wusbhc->dev = dev; wusbhc->uwb_rc = uwb_rc_get_by_grandpa(umc->dev.parent); if (!wusbhc->uwb_rc) { ret = -ENODEV; dev_err(dev, "cannot get radio controller\n"); - goto error; + goto error_uwb_rc; } if (whc->n_devices > USB_MAXCHILDREN) { @@ -311,8 +311,9 @@ static int whc_probe(struct umc_dev *umc) wusbhc_destroy(wusbhc); error_wusbhc_create: uwb_rc_put(wusbhc->uwb_rc); -error: +error_uwb_rc: whc_clean_up(whc); +error_whc_init: usb_put_hcd(usb_hcd); return ret; } -- GitLab From 2d5217840ff1d0cf0f88201a922ab35bd083f7fb Mon Sep 17 00:00:00 2001 From: Andrew Donnellan Date: Tue, 26 Apr 2016 15:02:50 +1000 Subject: [PATCH 4704/9938] powerpc/eeh: fix misleading indentation Found by smatch. Signed-off-by: Andrew Donnellan Acked-by: Russell Currey Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/eeh_pe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index eea48d8baf49..f0520da85759 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -249,7 +249,7 @@ static void *__eeh_pe_get(void *data, void *flag) } else { if (edev->pe_config_addr && (edev->pe_config_addr == pe->addr)) - return pe; + return pe; } /* Try BDF address */ -- GitLab From 4ad5e8831e1cb663f17112e44406b5ca9649ba1f Mon Sep 17 00:00:00 2001 From: Andrew Donnellan Date: Tue, 26 Apr 2016 17:55:04 +1000 Subject: [PATCH 4705/9938] powerpc/mpic: handle subsys_system_register() failure mpic_init_sys() currently doesn't check whether subsys_system_register() succeeded or not. Check the return code of subsys_system_register() and clean up if there's an error. Signed-off-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- arch/powerpc/sysdev/mpic.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index afe3c7cd395d..7de45b2df366 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -2004,8 +2004,15 @@ static struct syscore_ops mpic_syscore_ops = { static int mpic_init_sys(void) { + int rc; + register_syscore_ops(&mpic_syscore_ops); - subsys_system_register(&mpic_subsys, NULL); + rc = subsys_system_register(&mpic_subsys, NULL); + if (rc) { + unregister_syscore_ops(&mpic_syscore_ops); + pr_err("mpic: Failed to register subsystem!\n"); + return rc; + } return 0; } -- GitLab From 8a649045e75a4b9091ea9d041f5bb599f8ec1f8a Mon Sep 17 00:00:00 2001 From: Chris Smart Date: Tue, 26 Apr 2016 10:28:50 +1000 Subject: [PATCH 4706/9938] powerpc: Add support for userspace P9 copy paste The copy paste facility introduced in POWER9 provides an optimised mechanism for a userspace application to copy a cacheline. This is provided by a pair of instructions, copy and paste, while a third, cp_abort (copy paste abort), provides a clean up of the state in case of a failure. The copy instruction will read a 128 byte cacheline and store it in an internal buffer. The subsequent paste instruction will store this internal buffer to memory and set a CR field if the paste succeeds. Since the state of the copy paste buffer is internal (and not architecturally visible), in the unlikely event of a context switch, the state cannot be stored and the paste should therefore fail. The cp_abort instruction exists to fail and clean up any such interrupted copy paste sequence and is to be called by the kernel as part of the context switch. Doing so prevents data from a preceding copy in one process leaking into the paste of another. This code enables use of the cp_abort instruction if a supported processor is detected. NOTE: this is for userspace only, not in kernel, and does not deal with KVM guests. Patch created with much assistance from Michael Neuling Signed-off-by: Chris Smart Reviewed-by: Cyril Bur Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/ppc-opcode.h | 2 ++ arch/powerpc/kernel/entry_64.S | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 7ab04fc59e24..1d035c1cc889 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -131,6 +131,7 @@ /* sorted alphabetically */ #define PPC_INST_BHRBE 0x7c00025c #define PPC_INST_CLRBHRB 0x7c00035c +#define PPC_INST_CP_ABORT 0x7c00068c #define PPC_INST_DCBA 0x7c0005ec #define PPC_INST_DCBA_MASK 0xfc0007fe #define PPC_INST_DCBAL 0x7c2005ec @@ -285,6 +286,7 @@ #endif /* Deal with instructions that older assemblers aren't aware of */ +#define PPC_CP_ABORT stringify_in_c(.long PPC_INST_CP_ABORT) #define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \ __PPC_RA(a) | __PPC_RB(b)) #define PPC_DCBZL(a, b) stringify_in_c(.long PPC_INST_DCBZL | \ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 39a79c89a4b6..4fd492209d90 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -37,6 +37,7 @@ #include #include #include +#include /* * System calls. @@ -509,6 +510,14 @@ BEGIN_FTR_SECTION ldarx r6,0,r1 END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS) +BEGIN_FTR_SECTION +/* + * A cp_abort (copy paste abort) here ensures that when context switching, a + * copy from one process can't leak into the paste of another. + */ + PPC_CP_ABORT +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) + #ifdef CONFIG_PPC_BOOK3S /* Cancel all explict user streams as they will have no use after context * switch and will stop the HW from creating streams itself -- GitLab From 8fe088850f13eabf8197df5b0bf38668fa6c1294 Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 26 Apr 2016 23:49:09 +1000 Subject: [PATCH 4707/9938] powerpc: rework sparse for lib/xor_vmx.c Sparse doesn't seem to be passing -maltivec around properly, leading to lots of errors: .../include/altivec.h:34:2: error: Use the "-maltivec" flag to enable PowerPC AltiVec support arch/powerpc/lib/xor_vmx.c:27:16: error: Expected ; at end of declaration arch/powerpc/lib/xor_vmx.c:27:16: error: got signed arch/powerpc/lib/xor_vmx.c:60:9: error: No right hand side of '*'-expression arch/powerpc/lib/xor_vmx.c:60:9: error: Expected ; at end of statement arch/powerpc/lib/xor_vmx.c:60:9: error: got v1_in ... arch/powerpc/lib/xor_vmx.c:87:9: error: too many errors Only include the altivec.h header for non-__CHECKER__ builds. For builds with __CHECKER__, make up some stubs instead, as suggested by Balbir. (The vector size of 16 is arbitrary.) Suggested-by: Balbir Singh Signed-off-by: Daniel Axtens Tested-by: Balbir Singh Signed-off-by: Michael Ellerman --- arch/powerpc/lib/xor_vmx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/powerpc/lib/xor_vmx.c b/arch/powerpc/lib/xor_vmx.c index 07f49f1568e5..f9de69a04e88 100644 --- a/arch/powerpc/lib/xor_vmx.c +++ b/arch/powerpc/lib/xor_vmx.c @@ -17,7 +17,17 @@ * * Author: Anton Blanchard */ + +/* + * Sparse (as at v0.5.0) gets very, very confused by this file. + * Make it a bit simpler for it. + */ +#if !defined(__CHECKER__) #include +#else +#define vec_xor(a, b) a ^ b +#define vector __attribute__((vector_size(16))) +#endif #include #include -- GitLab From 7132e2d669bd42c3783327f301aaac5f4463299b Mon Sep 17 00:00:00 2001 From: Thiago Jung Bauermann Date: Mon, 25 Apr 2016 18:56:14 -0300 Subject: [PATCH 4708/9938] ftrace: Match dot symbols when searching functions on ppc64 In the ppc64 big endian ABI, function symbols point to function descriptors. The symbols which point to the function entry points have a dot in front of the function name. Consequently, when the ftrace filter mechanism searches for the symbol corresponding to an entry point address, it gets the dot symbol. As a result, ftrace filter users have to be aware of this ABI detail on ppc64 and prepend a dot to the function name when setting the filter. The perf probe command insulates the user from this by ignoring the dot in front of the symbol name when matching function names to symbols, but the sysfs interface does not. This patch makes the ftrace filter mechanism do the same when searching symbols. Fixes the following failure in ftracetest's kprobe_ftrace.tc: .../kprobe_ftrace.tc: line 9: echo: write error: Invalid argument That failure is on this line of kprobe_ftrace.tc: echo _do_fork > set_ftrace_filter This is because there's no _do_fork entry in the functions list: # cat available_filter_functions | grep _do_fork ._do_fork This change introduces no regressions on the perf and ftracetest testsuite results. Cc: Steven Rostedt Cc: Ingo Molnar Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Thiago Jung Bauermann Acked-by: Steven Rostedt Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/ftrace.c | 10 ++++++++++ kernel/trace/ftrace.c | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 9dac18dabd03..1123a4d8d8dd 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -607,3 +607,13 @@ unsigned long __init arch_syscall_addr(int nr) return sys_call_table[nr*2]; } #endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */ + +#if defined(CONFIG_PPC64) && (!defined(_CALL_ELF) || _CALL_ELF != 2) +char *arch_ftrace_match_adjust(char *str, const char *search) +{ + if (str[0] == '.' && search[0] != '.') + return str + 1; + else + return str; +} +#endif /* defined(CONFIG_PPC64) && (!defined(_CALL_ELF) || _CALL_ELF != 2) */ diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 7e8d792da963..a6c8252d7776 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3456,11 +3456,23 @@ struct ftrace_glob { int type; }; +/* + * If symbols in an architecture don't correspond exactly to the user-visible + * name of what they represent, it is possible to define this function to + * perform the necessary adjustments. +*/ +char * __weak arch_ftrace_match_adjust(char *str, const char *search) +{ + return str; +} + static int ftrace_match(char *str, struct ftrace_glob *g) { int matched = 0; int slen; + str = arch_ftrace_match_adjust(str, g->search); + switch (g->type) { case MATCH_FULL: if (strcmp(str, g->search) == 0) -- GitLab From b7bde4178a61a6855e1afebb60db4358dbbb6830 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 27 Apr 2016 02:15:15 +0200 Subject: [PATCH 4709/9938] btrfs: rename and document compression workspace members The names are confusing, pick more fitting names and add comments. Signed-off-by: David Sterba --- fs/btrfs/compression.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index ff61a41ac90b..4d5cd9624bb3 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -743,8 +743,11 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, static struct { struct list_head idle_ws; spinlock_t ws_lock; - int num_ws; - atomic_t alloc_ws; + /* Number of free workspaces */ + int free_ws; + /* Total number of allocated workspaces */ + atomic_t total_ws; + /* Waiters for a free workspace */ wait_queue_head_t ws_wait; } btrfs_comp_ws[BTRFS_COMPRESS_TYPES]; @@ -760,7 +763,7 @@ void __init btrfs_init_compress(void) for (i = 0; i < BTRFS_COMPRESS_TYPES; i++) { INIT_LIST_HEAD(&btrfs_comp_ws[i].idle_ws); spin_lock_init(&btrfs_comp_ws[i].ws_lock); - atomic_set(&btrfs_comp_ws[i].alloc_ws, 0); + atomic_set(&btrfs_comp_ws[i].total_ws, 0); init_waitqueue_head(&btrfs_comp_ws[i].ws_wait); } } @@ -777,35 +780,35 @@ static struct list_head *find_workspace(int type) struct list_head *idle_ws = &btrfs_comp_ws[idx].idle_ws; spinlock_t *ws_lock = &btrfs_comp_ws[idx].ws_lock; - atomic_t *alloc_ws = &btrfs_comp_ws[idx].alloc_ws; + atomic_t *total_ws = &btrfs_comp_ws[idx].total_ws; wait_queue_head_t *ws_wait = &btrfs_comp_ws[idx].ws_wait; - int *num_ws = &btrfs_comp_ws[idx].num_ws; + int *free_ws = &btrfs_comp_ws[idx].free_ws; again: spin_lock(ws_lock); if (!list_empty(idle_ws)) { workspace = idle_ws->next; list_del(workspace); - (*num_ws)--; + (*free_ws)--; spin_unlock(ws_lock); return workspace; } - if (atomic_read(alloc_ws) > cpus) { + if (atomic_read(total_ws) > cpus) { DEFINE_WAIT(wait); spin_unlock(ws_lock); prepare_to_wait(ws_wait, &wait, TASK_UNINTERRUPTIBLE); - if (atomic_read(alloc_ws) > cpus && !*num_ws) + if (atomic_read(total_ws) > cpus && !*free_ws) schedule(); finish_wait(ws_wait, &wait); goto again; } - atomic_inc(alloc_ws); + atomic_inc(total_ws); spin_unlock(ws_lock); workspace = btrfs_compress_op[idx]->alloc_workspace(); if (IS_ERR(workspace)) { - atomic_dec(alloc_ws); + atomic_dec(total_ws); wake_up(ws_wait); } return workspace; @@ -820,21 +823,21 @@ static void free_workspace(int type, struct list_head *workspace) int idx = type - 1; struct list_head *idle_ws = &btrfs_comp_ws[idx].idle_ws; spinlock_t *ws_lock = &btrfs_comp_ws[idx].ws_lock; - atomic_t *alloc_ws = &btrfs_comp_ws[idx].alloc_ws; + atomic_t *total_ws = &btrfs_comp_ws[idx].total_ws; wait_queue_head_t *ws_wait = &btrfs_comp_ws[idx].ws_wait; - int *num_ws = &btrfs_comp_ws[idx].num_ws; + int *free_ws = &btrfs_comp_ws[idx].free_ws; spin_lock(ws_lock); - if (*num_ws < num_online_cpus()) { + if (*free_ws < num_online_cpus()) { list_add(workspace, idle_ws); - (*num_ws)++; + (*free_ws)++; spin_unlock(ws_lock); goto wake; } spin_unlock(ws_lock); btrfs_compress_op[idx]->free_workspace(workspace); - atomic_dec(alloc_ws); + atomic_dec(total_ws); wake: /* * Make sure counter is updated before we wake up waiters. @@ -857,7 +860,7 @@ static void free_workspaces(void) workspace = btrfs_comp_ws[i].idle_ws.next; list_del(workspace); btrfs_compress_op[i]->free_workspace(workspace); - atomic_dec(&btrfs_comp_ws[i].alloc_ws); + atomic_dec(&btrfs_comp_ws[i].total_ws); } } } -- GitLab From 3853368b95f27d9bdaf9e15bc1e11753f11e3c43 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 27 Apr 2016 02:55:15 +0200 Subject: [PATCH 4710/9938] btrfs: preallocate compression workspaces Preallocate one workspace for each compression type so we can guarantee forward progress in the worst case. A failure cannot be a hard error as we might not use compression at all on the filesystem. If we can't allocate the workspaces later when need them, it might actually deadlock, but in such situation the system has effectively not enough memory to operate properly. Signed-off-by: David Sterba --- fs/btrfs/compression.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 4d5cd9624bb3..38c058bcf359 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -761,10 +761,26 @@ void __init btrfs_init_compress(void) int i; for (i = 0; i < BTRFS_COMPRESS_TYPES; i++) { + struct list_head *workspace; + INIT_LIST_HEAD(&btrfs_comp_ws[i].idle_ws); spin_lock_init(&btrfs_comp_ws[i].ws_lock); atomic_set(&btrfs_comp_ws[i].total_ws, 0); init_waitqueue_head(&btrfs_comp_ws[i].ws_wait); + + /* + * Preallocate one workspace for each compression type so + * we can guarantee forward progress in the worst case + */ + workspace = btrfs_compress_op[i]->alloc_workspace(); + if (IS_ERR(workspace)) { + printk(KERN_WARNING + "BTRFS: cannot preallocate compression workspace, will try later"); + } else { + atomic_set(&btrfs_comp_ws[i].total_ws, 1); + btrfs_comp_ws[i].free_ws = 1; + list_add(workspace, &btrfs_comp_ws[i].idle_ws); + } } } -- GitLab From 3b501d18aa4f75fe23af5b0bf592d62fd82cca5b Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 27 Apr 2016 02:41:17 +0200 Subject: [PATCH 4711/9938] btrfs: make find_workspace always succeed With just one preallocated workspace we can guarantee forward progress even if there's no memory available for new workspaces. The cost is more waiting but we also get rid of several error paths. On average, there will be several idle workspaces, so the waiting penalty won't be so bad. In the worst case, all cpus will compete for one workspace until there's some memory. Attempts to allocate a new one are done each time the waiters are woken up. Signed-off-by: David Sterba --- fs/btrfs/compression.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 38c058bcf359..c70625560265 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -785,8 +785,10 @@ void __init btrfs_init_compress(void) } /* - * this finds an available workspace or allocates a new one - * ERR_PTR is returned if things go bad. + * This finds an available workspace or allocates a new one. + * If it's not possible to allocate a new one, waits until there's one. + * Preallocation makes a forward progress guarantees and we do not return + * errors. */ static struct list_head *find_workspace(int type) { @@ -826,6 +828,14 @@ static struct list_head *find_workspace(int type) if (IS_ERR(workspace)) { atomic_dec(total_ws); wake_up(ws_wait); + + /* + * Do not return the error but go back to waiting. There's a + * workspace preallocated for each type and the compression + * time is bounded so we get to a workspace eventually. This + * makes our caller's life easier. + */ + goto again; } return workspace; } @@ -913,8 +923,6 @@ int btrfs_compress_pages(int type, struct address_space *mapping, int ret; workspace = find_workspace(type); - if (IS_ERR(workspace)) - return PTR_ERR(workspace); ret = btrfs_compress_op[type-1]->compress_pages(workspace, mapping, start, len, pages, @@ -949,8 +957,6 @@ static int btrfs_decompress_biovec(int type, struct page **pages_in, int ret; workspace = find_workspace(type); - if (IS_ERR(workspace)) - return PTR_ERR(workspace); ret = btrfs_compress_op[type-1]->decompress_biovec(workspace, pages_in, disk_start, @@ -971,8 +977,6 @@ int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page, int ret; workspace = find_workspace(type); - if (IS_ERR(workspace)) - return PTR_ERR(workspace); ret = btrfs_compress_op[type-1]->decompress(workspace, data_in, dest_page, start_byte, -- GitLab From ae55b9ec7ac117c05ff866500425fe8b4accfebe Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 27 Apr 2016 03:07:39 +0200 Subject: [PATCH 4712/9938] btrfs: make find_workspace warn if there are no workspaces Be verbose if there are no workspaces at all, ie. the module init time preallocation failed. Signed-off-by: David Sterba --- fs/btrfs/compression.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index c70625560265..658c39b70fba 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -834,7 +834,21 @@ static struct list_head *find_workspace(int type) * workspace preallocated for each type and the compression * time is bounded so we get to a workspace eventually. This * makes our caller's life easier. + * + * To prevent silent and low-probability deadlocks (when the + * initial preallocation fails), check if there are any + * workspaces at all. */ + if (atomic_read(total_ws) == 0) { + static DEFINE_RATELIMIT_STATE(_rs, + /* once per minute */ 60 * HZ, + /* no burst */ 1); + + if (__ratelimit(&_rs)) { + printk(KERN_WARNING + "no compression workspaces, low memory, retrying"); + } + } goto again; } return workspace; -- GitLab From dad56ee742a3abbb5d9e8108f8537d412bff3f57 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 26 Apr 2016 21:22:22 -0400 Subject: [PATCH 4713/9938] tracing: Move event_trigger_unlock_commit{_regs}() to local header The functions event_trigger_unlock_commit() and event_trigger_unlock_commit_regs() are no longer used outside the tracing system. Move them out of the generic headers and into the local one. Along with __event_trigger_test_discard() that is only used by them. Signed-off-by: Steven Rostedt --- include/linux/trace_events.h | 94 ------------------------------------ kernel/trace/trace.h | 94 ++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 94 deletions(-) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 5f89a5b0c7e6..70a181cb3585 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -452,100 +452,6 @@ trace_trigger_soft_disabled(struct trace_event_file *file) return false; } -/* - * Helper function for event_trigger_unlock_commit{_regs}(). - * If there are event triggers attached to this event that requires - * filtering against its fields, then they wil be called as the - * entry already holds the field information of the current event. - * - * It also checks if the event should be discarded or not. - * It is to be discarded if the event is soft disabled and the - * event was only recorded to process triggers, or if the event - * filter is active and this event did not match the filters. - * - * Returns true if the event is discarded, false otherwise. - */ -static inline bool -__event_trigger_test_discard(struct trace_event_file *file, - struct ring_buffer *buffer, - struct ring_buffer_event *event, - void *entry, - enum event_trigger_type *tt) -{ - unsigned long eflags = file->flags; - - if (eflags & EVENT_FILE_FL_TRIGGER_COND) - *tt = event_triggers_call(file, entry); - - if (test_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags)) - ring_buffer_discard_commit(buffer, event); - else if (!filter_check_discard(file, entry, buffer, event)) - return false; - - return true; -} - -/** - * event_trigger_unlock_commit - handle triggers and finish event commit - * @file: The file pointer assoctiated to the event - * @buffer: The ring buffer that the event is being written to - * @event: The event meta data in the ring buffer - * @entry: The event itself - * @irq_flags: The state of the interrupts at the start of the event - * @pc: The state of the preempt count at the start of the event. - * - * This is a helper function to handle triggers that require data - * from the event itself. It also tests the event against filters and - * if the event is soft disabled and should be discarded. - */ -static inline void -event_trigger_unlock_commit(struct trace_event_file *file, - struct ring_buffer *buffer, - struct ring_buffer_event *event, - void *entry, unsigned long irq_flags, int pc) -{ - enum event_trigger_type tt = ETT_NONE; - - if (!__event_trigger_test_discard(file, buffer, event, entry, &tt)) - trace_buffer_unlock_commit(file->tr, buffer, event, irq_flags, pc); - - if (tt) - event_triggers_post_call(file, tt, entry); -} - -/** - * event_trigger_unlock_commit_regs - handle triggers and finish event commit - * @file: The file pointer assoctiated to the event - * @buffer: The ring buffer that the event is being written to - * @event: The event meta data in the ring buffer - * @entry: The event itself - * @irq_flags: The state of the interrupts at the start of the event - * @pc: The state of the preempt count at the start of the event. - * - * This is a helper function to handle triggers that require data - * from the event itself. It also tests the event against filters and - * if the event is soft disabled and should be discarded. - * - * Same as event_trigger_unlock_commit() but calls - * trace_buffer_unlock_commit_regs() instead of trace_buffer_unlock_commit(). - */ -static inline void -event_trigger_unlock_commit_regs(struct trace_event_file *file, - struct ring_buffer *buffer, - struct ring_buffer_event *event, - void *entry, unsigned long irq_flags, int pc, - struct pt_regs *regs) -{ - enum event_trigger_type tt = ETT_NONE; - - if (!__event_trigger_test_discard(file, buffer, event, entry, &tt)) - trace_buffer_unlock_commit_regs(file->tr, buffer, event, - irq_flags, pc, regs); - - if (tt) - event_triggers_post_call(file, tt, entry); -} - #ifdef CONFIG_BPF_EVENTS unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx); #else diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 727a3d28bce5..c0eac7b1e5a6 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1065,6 +1065,100 @@ struct trace_subsystem_dir { int nr_events; }; +/* + * Helper function for event_trigger_unlock_commit{_regs}(). + * If there are event triggers attached to this event that requires + * filtering against its fields, then they wil be called as the + * entry already holds the field information of the current event. + * + * It also checks if the event should be discarded or not. + * It is to be discarded if the event is soft disabled and the + * event was only recorded to process triggers, or if the event + * filter is active and this event did not match the filters. + * + * Returns true if the event is discarded, false otherwise. + */ +static inline bool +__event_trigger_test_discard(struct trace_event_file *file, + struct ring_buffer *buffer, + struct ring_buffer_event *event, + void *entry, + enum event_trigger_type *tt) +{ + unsigned long eflags = file->flags; + + if (eflags & EVENT_FILE_FL_TRIGGER_COND) + *tt = event_triggers_call(file, entry); + + if (test_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags)) + ring_buffer_discard_commit(buffer, event); + else if (!filter_check_discard(file, entry, buffer, event)) + return false; + + return true; +} + +/** + * event_trigger_unlock_commit - handle triggers and finish event commit + * @file: The file pointer assoctiated to the event + * @buffer: The ring buffer that the event is being written to + * @event: The event meta data in the ring buffer + * @entry: The event itself + * @irq_flags: The state of the interrupts at the start of the event + * @pc: The state of the preempt count at the start of the event. + * + * This is a helper function to handle triggers that require data + * from the event itself. It also tests the event against filters and + * if the event is soft disabled and should be discarded. + */ +static inline void +event_trigger_unlock_commit(struct trace_event_file *file, + struct ring_buffer *buffer, + struct ring_buffer_event *event, + void *entry, unsigned long irq_flags, int pc) +{ + enum event_trigger_type tt = ETT_NONE; + + if (!__event_trigger_test_discard(file, buffer, event, entry, &tt)) + trace_buffer_unlock_commit(file->tr, buffer, event, irq_flags, pc); + + if (tt) + event_triggers_post_call(file, tt, entry); +} + +/** + * event_trigger_unlock_commit_regs - handle triggers and finish event commit + * @file: The file pointer assoctiated to the event + * @buffer: The ring buffer that the event is being written to + * @event: The event meta data in the ring buffer + * @entry: The event itself + * @irq_flags: The state of the interrupts at the start of the event + * @pc: The state of the preempt count at the start of the event. + * + * This is a helper function to handle triggers that require data + * from the event itself. It also tests the event against filters and + * if the event is soft disabled and should be discarded. + * + * Same as event_trigger_unlock_commit() but calls + * trace_buffer_unlock_commit_regs() instead of trace_buffer_unlock_commit(). + */ +static inline void +event_trigger_unlock_commit_regs(struct trace_event_file *file, + struct ring_buffer *buffer, + struct ring_buffer_event *event, + void *entry, unsigned long irq_flags, int pc, + struct pt_regs *regs) +{ + enum event_trigger_type tt = ETT_NONE; + + if (!__event_trigger_test_discard(file, buffer, event, entry, &tt)) + trace_buffer_unlock_commit_regs(file->tr, buffer, event, + irq_flags, pc, regs); + + if (tt) + event_triggers_post_call(file, tt, entry); +} + #define FILTER_PRED_INVALID ((unsigned short)-1) #define FILTER_PRED_IS_RIGHT (1 << 15) #define FILTER_PRED_FOLD (1 << 15) -- GitLab From 7d698272f10cadcdb73f744b8642d70db1ca8fe8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 25 Apr 2016 16:08:31 +0200 Subject: [PATCH 4714/9938] ARM: dts: r8a7778: Don't disable referenced optional clocks clk_get() on a disabled clock node will return -EPROBE_DEFER, which can cause drivers to be deferred forever if such clocks are referenced in their devices' clocks properties. Update the various disabled external clock nodes to default to a frequency of 0, but don't disable them, to prevent this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7778.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi index 99c10ebbaca2..fe787b4751d2 100644 --- a/arch/arm/boot/dts/r8a7778.dtsi +++ b/arch/arm/boot/dts/r8a7778.dtsi @@ -455,7 +455,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* Special CPG clocks */ -- GitLab From 55ee434728ebf0a0087bbe749d6be7d7170a514c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 25 Apr 2016 16:08:32 +0200 Subject: [PATCH 4715/9938] ARM: dts: r8a7779: Don't disable referenced optional clocks clk_get() on a disabled clock node will return -EPROBE_DEFER, which can cause drivers to be deferred forever if such clocks are referenced in their devices' clocks properties. Update the various disabled external clock nodes to default to a frequency of 0, but don't disable them, to prevent this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index 5c1d48d712a1..0c82097daffc 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -458,7 +458,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* Special CPG clocks */ -- GitLab From 03adc1811cefae9494deb2002c7ab44f31d782d7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 25 Apr 2016 16:08:33 +0200 Subject: [PATCH 4716/9938] ARM: dts: r8a7790: Don't disable referenced optional clocks clk_get() on a disabled clock node will return -EPROBE_DEFER, which can cause drivers to be deferred forever if such clocks are referenced in their devices' clocks properties. Update the various disabled external clock nodes to default to a frequency of 0, but don't disable them, to prevent this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 776a2aed81d2..935064fe7b13 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1032,8 +1032,7 @@ pcie_bus_clk: pcie_bus { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <100000000>; - status = "disabled"; + clock-frequency = <0>; }; /* @@ -1062,7 +1061,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* External USB clock - can be overridden by the board */ @@ -1078,7 +1076,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* Special CPG clocks */ -- GitLab From 15bb4bfa3a788be349ab8f8cd1e356b7925be5eb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 25 Apr 2016 16:08:34 +0200 Subject: [PATCH 4717/9938] ARM: dts: r8a7793: Don't disable referenced optional clocks clk_get() on a disabled clock node will return -EPROBE_DEFER, which can cause drivers to be deferred forever if such clocks are referenced in their devices' clocks properties. Update the various disabled external clock nodes to default to a frequency of 0, but don't disable them, to prevent this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7793.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index 6186179fd66d..cf6dc2aeef20 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -907,7 +907,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* External SCIF clock */ @@ -916,7 +915,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* Special CPG clocks */ -- GitLab From c9006ac628ca30dd0d06dad47677d338e243bb95 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 25 Apr 2016 16:08:35 +0200 Subject: [PATCH 4718/9938] ARM: dts: r8a7794: Don't disable referenced optional clocks clk_get() on a disabled clock node will return -EPROBE_DEFER, which can cause drivers to be deferred forever if such clocks are referenced in their devices' clocks properties. Update the various disabled external clock nodes to default to a frequency of 0, but don't disable them, to prevent this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index b0bce43779f1..e45b23f31149 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -906,7 +906,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* External SCIF clock */ @@ -915,7 +914,6 @@ #clock-cells = <0>; /* This value must be overridden by the board. */ clock-frequency = <0>; - status = "disabled"; }; /* Special CPG clocks */ -- GitLab From 9251024a6a148abd628785d53e3b7a42e8217cc9 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 5 Apr 2016 11:51:26 +0100 Subject: [PATCH 4719/9938] arm64: dts: r8a7795: Add PCIe nodes Signed-off-by: Phil Edworthy Acked-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 57 ++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index 868c10eaea48..11f9971a8543 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -131,6 +131,14 @@ status = "disabled"; }; + /* External PCIe clock - can be overridden by the board */ + pcie_bus_clk: pcie_bus { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + status = "disabled"; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&gic>; @@ -1156,5 +1164,54 @@ power-domains = <&cpg>; status = "disabled"; }; + pciec0: pcie@fe000000 { + compatible = "renesas,pcie-r8a7795"; + reg = <0 0xfe000000 0 0x80000>; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x00 0xff>; + device_type = "pci"; + ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000 + 0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000 + 0x02000000 0 0x30000000 0 0x30000000 0 0x08000000 + 0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; + /* Map all possible DDR as inbound ranges */ + dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>; + interrupts = , + , + ; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>; + clock-names = "pcie", "pcie_bus"; + power-domains = <&cpg>; + status = "disabled"; + }; + + pciec1: pcie@ee800000 { + compatible = "renesas,pcie-r8a7795"; + reg = <0 0xee800000 0 0x80000>; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x00 0xff>; + device_type = "pci"; + ranges = <0x01000000 0 0x00000000 0 0xee900000 0 0x00100000 + 0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000 + 0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000 + 0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; + /* Map all possible DDR as inbound ranges */ + dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>; + interrupts = , + , + ; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 318>, <&pcie_bus_clk>; + clock-names = "pcie", "pcie_bus"; + power-domains = <&cpg>; + status = "disabled"; + }; }; }; -- GitLab From bbd273047b765b431411103c2f7a2688b7288c85 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 5 Apr 2016 11:51:27 +0100 Subject: [PATCH 4720/9938] arm64: dts: r8a7795: enable PCIe on Salvator-X Signed-off-by: Phil Edworthy Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index b992b1a3d956..7c40ac8232f3 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -388,3 +388,15 @@ &ohci2 { status = "okay"; }; + +&pcie_bus_clk { + status = "okay"; +}; + +&pciec0 { + status = "okay"; +}; + +&pciec1 { + status = "okay"; +}; -- GitLab From de5a79f125dd8c260d8c39b2bdced2a8fa957518 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 30 Mar 2016 16:58:22 +0200 Subject: [PATCH 4721/9938] arm64: dts: salvator-x: populate EXTALR It can be used for the watchdog. Signed-off-by: Wolfram Sang Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index 7c40ac8232f3..78c02937697e 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -141,6 +141,10 @@ clock-frequency = <16666666>; }; +&extalr_clk { + clock-frequency = <32768>; +}; + &pfc { pinctrl-0 = <&scif_clk_pins>; pinctrl-names = "default"; -- GitLab From 9f33a8a9e1b7dbb0b91a58af958d1c301a6fab1a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 25 Apr 2016 16:08:30 +0200 Subject: [PATCH 4722/9938] arm64: dts: r8a7795: Don't disable referenced optional clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clk_get() on a disabled clock node will return -EPROBE_DEFER, which can cause drivers to be deferred forever if such clocks are referenced in their devices' clocks properties. Update the various disabled external clock nodes to default to a frequency of 0, but don't disable them, to prevent this. Reported-by: Jürg Billeter Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 1 + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index 78c02937697e..8d8de245a845 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -394,6 +394,7 @@ }; &pcie_bus_clk { + clock-frequency = <100000000>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index 11f9971a8543..7cb2d72e7378 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -120,7 +120,6 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - status = "disabled"; }; /* External SCIF clock - to be overridden by boards that provide it */ @@ -128,15 +127,13 @@ compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; - status = "disabled"; }; /* External PCIe clock - can be overridden by the board */ pcie_bus_clk: pcie_bus { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <100000000>; - status = "disabled"; + clock-frequency = <0>; }; soc { -- GitLab From 585a60f24bf86671b17ca7420e82b9404ff18502 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 29 Jan 2016 14:49:24 -0800 Subject: [PATCH 4723/9938] clk: imx: return correct frequency for Ethernet PLL The i.MX 7 designs Ethernet PLL provides a 1000MHz reference clock. Store the reference clock in the clk_pllv3 structure according to the PLL type. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pllv3.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index c05c43d56a94..4826b3c9e19e 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -44,6 +44,7 @@ struct clk_pllv3 { u32 powerdown; u32 div_mask; u32 div_shift; + unsigned long ref_clock; }; #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) @@ -286,7 +287,9 @@ static const struct clk_ops clk_pllv3_av_ops = { static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - return 500000000; + struct clk_pllv3 *pll = to_clk_pllv3(hw); + + return pll->ref_clock; } static const struct clk_ops clk_pllv3_enet_ops = { @@ -326,7 +329,11 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, break; case IMX_PLLV3_ENET_IMX7: pll->powerdown = IMX7_ENET_PLL_POWER; + pll->ref_clock = 1000000000; + ops = &clk_pllv3_enet_ops; + break; case IMX_PLLV3_ENET: + pll->ref_clock = 500000000; ops = &clk_pllv3_enet_ops; break; default: -- GitLab From 7bd2c71bbd76683a110d8c37bc8828becb2846cc Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 20 Apr 2016 10:57:28 -0500 Subject: [PATCH 4724/9938] arm64: defconfig: cleanup the defconfig When doing: make defconfig make savedefconfig ...without making any changes, the newly saved defconfig does not match arch/arm64/configs/defconfig, and the diff looks like: $ diff defconfig arch/arm64/configs/defconfig 3a4 > CONFIG_FHANDLE=y Clean that up by committing the output of savedefconfig. Signed-off-by: Stuart Yoder Acked-by: Arnd Bergmann Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index a44ef995d8ae..248c242282db 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1,7 +1,6 @@ # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y -CONFIG_FHANDLE=y CONFIG_AUDIT=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y -- GitLab From 211102d85f71dc5a01dde771e3f833f60b494661 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 20 Apr 2016 10:57:34 -0500 Subject: [PATCH 4725/9938] arm64: defconfig: enable 48-bit virtual addresses Some armv8 SoCs (e.g. ls2080a) have physical memory maps with discontiguous DDR regions that require 48-bit VA to have the linear map cover the entire range of DDR. Signed-off-by: Stuart Yoder Acked-by: Arnd Bergmann Acked-by: Catalin Marinas Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 248c242282db..e8bc2639179d 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -61,6 +61,7 @@ CONFIG_PCI_XGENE=y CONFIG_PCI_LAYERSCAPE=y CONFIG_PCI_HISI=y CONFIG_PCIE_QCOM=y +CONFIG_ARM64_VA_BITS_48=y CONFIG_SCHED_MC=y CONFIG_PREEMPT=y CONFIG_KSM=y -- GitLab From 3892132c2716e2747e562dd9a4c025387c19c329 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Wed, 20 Apr 2016 10:57:40 -0500 Subject: [PATCH 4726/9938] arm64: defconfig: enable freescale/nxp config options enable standard drivers for the NXP/Freescale ls2080a and ls1043a SoCs: -system clock driver -sata (AHCI) -sd/mmc (ESDHC) -i2c support and i2c mux -i2c rtc clock -i2c sensors (as modules) Signed-off-by: Stuart Yoder Acked-by: Arnd Bergmann Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index e8bc2639179d..523e19dd68b9 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -102,6 +102,7 @@ CONFIG_SATA_AHCI_PLATFORM=y CONFIG_AHCI_CEVA=y CONFIG_AHCI_MVEBU=y CONFIG_AHCI_XGENE=y +CONFIG_AHCI_QORIQ=y CONFIG_SATA_RCAR=y CONFIG_PATA_PLATFORM=y CONFIG_PATA_OF_PLATFORM=y @@ -146,7 +147,10 @@ CONFIG_SERIAL_MVEBU_UART=y CONFIG_VIRTIO_CONSOLE=y # CONFIG_HW_RANDOM is not set CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_IMX=y CONFIG_I2C_MV64XXX=y CONFIG_I2C_QUP=y CONFIG_I2C_TEGRA=y @@ -167,7 +171,8 @@ CONFIG_GPIO_XGENE=y CONFIG_POWER_RESET_MSM=y CONFIG_POWER_RESET_XGENE=y CONFIG_POWER_RESET_SYSCON=y -# CONFIG_HWMON is not set +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_INA2XX=m CONFIG_THERMAL=y CONFIG_THERMAL_EMULATION=y CONFIG_EXYNOS_THERMAL=y @@ -213,6 +218,7 @@ CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_ARMMMCI=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ESDHC=y CONFIG_MMC_SDHCI_TEGRA=y CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_SPI=y @@ -229,6 +235,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_CPU=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_S5M=y +CONFIG_RTC_DRV_DS3232=y CONFIG_RTC_DRV_EFI=y CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_SUN6I=y @@ -246,6 +253,7 @@ CONFIG_XEN_GNTDEV=y CONFIG_XEN_GRANT_DEV_ALLOC=y CONFIG_COMMON_CLK_SCPI=y CONFIG_COMMON_CLK_CS2000_CP=y +CONFIG_CLK_QORIQ=y CONFIG_COMMON_CLK_QCOM=y CONFIG_MSM_GCC_8916=y CONFIG_HWSPINLOCK_QCOM=y -- GitLab From b18f909376352aa1c1e755aed87f8061d9e14510 Mon Sep 17 00:00:00 2001 From: Sergio Prado Date: Tue, 26 Apr 2016 20:38:22 -0300 Subject: [PATCH 4727/9938] ARM: dts: imx6: Add dts for Embest MarS Board Embest MarS Board [1] is a multi-core platform based on Freescale i.MX6 Cortex-A9 Dual Core, running up to 1GHz with 1 GB of RAM, 4GB of eMMC and with a 4MB SPI flash. [1] http://www.embest-tech.com/shop/star/marsboard.html Signed-off-by: Sergio Prado Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6q-marsboard.dts | 403 ++++++++++++++++++++++++++ 2 files changed, 404 insertions(+) create mode 100644 arch/arm/boot/dts/imx6q-marsboard.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index a7d40426c141..dcfe30a73d54 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -350,6 +350,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6q-gw552x.dtb \ imx6q-hummingboard.dtb \ imx6q-icore-rqs.dtb \ + imx6q-marsboard.dtb \ imx6q-nitrogen6x.dtb \ imx6q-nitrogen6_max.dtb \ imx6q-novena.dtb \ diff --git a/arch/arm/boot/dts/imx6q-marsboard.dts b/arch/arm/boot/dts/imx6q-marsboard.dts new file mode 100644 index 000000000000..3f8013c85fb9 --- /dev/null +++ b/arch/arm/boot/dts/imx6q-marsboard.dts @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2016 Sergio Prado (sergio.prado@e-labworks.com) + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This file is distributed in the hope that it will be useful + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include + +/ { + model = "Embest MarS Board i.MX6Dual"; + compatible = "embest,imx6q-marsboard", "fsl,imx6q"; + + memory { + reg = <0x10000000 0x40000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_usb_otg_vbus: regulator-usb-otg-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_otg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_led>; + + user1 { + label = "imx6:green:user1"; + gpios = <&gpio5 2 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "heartbeat"; + }; + + user2 { + label = "imx6:green:user2"; + gpios = <&gpio3 28 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; +}; + +&audmux { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux>; + status = "okay"; +}; + +&ecspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + cs-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>; + fsl,spi-num-chipselects = <1>; + status = "okay"; + + m25p80@0 { + compatible = "microchip,sst25vf016b"; + spi-max-frequency = <20000000>; + reg = <0>; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + phy-reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c2>; + status = "okay"; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + +&pwm1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; + status = "okay"; +}; + +&pwm2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; + status = "okay"; +}; + +&pwm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm3>; + status = "okay"; +}; + +&pwm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm4>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&usbh1 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usbotg { + vbus-supply = <®_usb_otg_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg>; + dr_mode = "otg"; + disable-over-current; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + vmmc-supply = <®_3p3v>; + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + vmmc-supply = <®_3p3v>; + non-removable; + status = "okay"; +}; + +&iomuxc { + + pinctrl_audmux: audmuxgrp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* CAM_MCLK */ + >; + }; + + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 + MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x000b1 /* CS0 */ + >; + }; + + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */ + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1 + /* AR8035 pin strapping: IO voltage: pull up */ + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + /* AR8035 pin strapping: PHYADDR#0: pull down */ + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x130b0 + /* AR8035 pin strapping: PHYADDR#1: pull down */ + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x130b0 + /* AR8035 pin strapping: MODE#1: pull up */ + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + /* AR8035 pin strapping: MODE#3: pull up */ + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + /* AR8035 pin strapping: MODE#0: pull down */ + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0 + /* GPIO16 -> AR8035 25MHz */ + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 + /* RGMII_nRST */ + MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0 + /* AR8035 interrupt */ + MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x180b0 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1 + MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 + >; + }; + + pinctrl_led: ledgrp { + fsl,pins = < + MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* LED1 */ + MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b1 /* LED2 */ + >; + }; + + pinctrl_pwm1: pwm1grp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1 + >; + }; + + pinctrl_pwm2: pwm2grp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT9__PWM2_OUT 0x1b0b1 + >; + }; + + pinctrl_pwm3: pwm3grp { + fsl,pins = < + MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1 + >; + }; + + pinctrl_pwm4: pwm4grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 + MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_usbotg: usbotggrp { + fsl,pins = < + MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059 + MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0 + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0 /* USB OTG POWER ENABLE */ + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* CD */ + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1f0b0 /* WP */ + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17009 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10009 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17009 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17009 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17009 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17009 + MX6QDL_PAD_SD3_RST__SD3_RESET 0x17009 + >; + }; +}; -- GitLab From b26a68c1fbdf34d5fcc49f9208b2bb114839a2d0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 26 Apr 2016 22:28:29 -0300 Subject: [PATCH 4728/9938] ARM: dts: imx6: Do not hardcode the CLKO clock Using "IMX6QDL_CLK_CKO" for the clock is easier to read instead of the hardcoded clock number. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl-riotboard.dts | 2 +- arch/arm/boot/dts/imx6q-gw5400-a.dts | 2 +- arch/arm/boot/dts/imx6q-tbs2910.dts | 2 +- arch/arm/boot/dts/imx6qdl-apalis.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-apf6dev.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-gw52xx.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-gw53xx.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-gw54xx.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-rex.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-udoo.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-wandboard.dtsi | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts index 5111f5170d53..bfbed52ce1bd 100644 --- a/arch/arm/boot/dts/imx6dl-riotboard.dts +++ b/arch/arm/boot/dts/imx6dl-riotboard.dts @@ -114,7 +114,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/imx6q-gw5400-a.dts index a51834e1dd27..0511137d1e23 100644 --- a/arch/arm/boot/dts/imx6q-gw5400-a.dts +++ b/arch/arm/boot/dts/imx6q-gw5400-a.dts @@ -327,7 +327,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <&sw4_reg>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts index 2401c6b54361..1926b1348a62 100644 --- a/arch/arm/boot/dts/imx6q-tbs2910.dts +++ b/arch/arm/boot/dts/imx6q-tbs2910.dts @@ -159,7 +159,7 @@ status = "okay"; sgtl5000: sgtl5000@0a { - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; compatible = "fsl,sgtl5000"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sgtl5000>; diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi index b33e5a95a0f0..922b1dd06fda 100644 --- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi +++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi @@ -324,7 +324,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi b/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi index a8f3500ee522..865c9a264a43 100644 --- a/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi +++ b/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi @@ -213,7 +213,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_3p3v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi index 8dd74e98ffd6..7191b84770b9 100644 --- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi @@ -244,7 +244,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_1p8v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi index ec3fe7444e15..40d06b09deba 100644 --- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi @@ -237,7 +237,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_1p8v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi index 367cc49eea0d..d6dbe2a88ee6 100644 --- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi @@ -328,7 +328,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <&sw4_reg>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi index 24d7d3f18464..e456b5cc1b03 100644 --- a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi @@ -269,7 +269,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sgtl5000>; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi index dc74aa395ff5..657da6b6ccd2 100644 --- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi +++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi @@ -402,7 +402,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi index c6c590d1e940..73915db704a0 100644 --- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi +++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi @@ -304,7 +304,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/imx6qdl-rex.dtsi index a50356243888..cacf5933707d 100644 --- a/arch/arm/boot/dts/imx6qdl-rex.dtsi +++ b/arch/arm/boot/dts/imx6qdl-rex.dtsi @@ -126,7 +126,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_3p3v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index 0f1aca450fe6..c47fe6c79b36 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -290,7 +290,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi index 0dd5aa1b45e0..3bee2f910067 100644 --- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi +++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi @@ -260,7 +260,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usbh>; vbus-supply = <®_usb_h1_vbus>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi index 9e096d811bed..8e7c40e114dd 100644 --- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi @@ -85,7 +85,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; }; -- GitLab From abbecab1a0b8c2cc07edc30c8bced855ca4e239d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Aug 2015 13:47:07 +0200 Subject: [PATCH 4729/9938] arm64: dts: r8a7795: Add SYSC PM Domains Add a device node for the System Controller. Hook up the Cortex-A57 CPU cores and the Cortex-A57 and Cortex A53 L2 caches/SCUs to their respective PM Domains. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index 7cb2d72e7378..f96d0732b2a8 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -10,6 +10,7 @@ #include #include +#include / { compatible = "renesas,r8a7795"; @@ -39,6 +40,7 @@ compatible = "arm,cortex-a57", "arm,armv8"; reg = <0x0>; device_type = "cpu"; + power-domains = <&sysc R8A7795_PD_CA57_CPU0>; next-level-cache = <&L2_CA57>; enable-method = "psci"; }; @@ -47,6 +49,7 @@ compatible = "arm,cortex-a57","arm,armv8"; reg = <0x1>; device_type = "cpu"; + power-domains = <&sysc R8A7795_PD_CA57_CPU1>; next-level-cache = <&L2_CA57>; enable-method = "psci"; }; @@ -54,6 +57,7 @@ compatible = "arm,cortex-a57","arm,armv8"; reg = <0x2>; device_type = "cpu"; + power-domains = <&sysc R8A7795_PD_CA57_CPU2>; next-level-cache = <&L2_CA57>; enable-method = "psci"; }; @@ -61,6 +65,7 @@ compatible = "arm,cortex-a57","arm,armv8"; reg = <0x3>; device_type = "cpu"; + power-domains = <&sysc R8A7795_PD_CA57_CPU3>; next-level-cache = <&L2_CA57>; enable-method = "psci"; }; @@ -68,12 +73,14 @@ L2_CA57: cache-controller@0 { compatible = "cache"; + power-domains = <&sysc R8A7795_PD_CA57_SCU>; cache-unified; cache-level = <2>; }; L2_CA53: cache-controller@1 { compatible = "cache"; + power-domains = <&sysc R8A7795_PD_CA53_SCU>; cache-unified; cache-level = <2>; }; @@ -302,6 +309,12 @@ #power-domain-cells = <0>; }; + sysc: system-controller@e6180000 { + compatible = "renesas,r8a7795-sysc"; + reg = <0 0xe6180000 0 0x0400>; + #power-domain-cells = <1>; + }; + audma0: dma-controller@ec700000 { compatible = "renesas,rcar-dmac"; reg = <0 0xec700000 0 0x10000>; -- GitLab From 38dbb45ee4bc7dda4aabba2178eebff2f93380d1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Aug 2015 13:47:07 +0200 Subject: [PATCH 4730/9938] arm64: dts: r8a7795: Use SYSC "always-on" PM Domain Hook up all devices that are part of the CPG/MSSR Clock Domain to the SYSC "always-on" PM Domain, for a more consistent device-power-area description in DT. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 110 +++++++++++------------ 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index f96d0732b2a8..3285a9286786 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -175,7 +175,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 912>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; gpio1: gpio@e6051000 { @@ -189,7 +189,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 911>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; gpio2: gpio@e6052000 { @@ -203,7 +203,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 910>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; gpio3: gpio@e6053000 { @@ -217,7 +217,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 909>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; gpio4: gpio@e6054000 { @@ -231,7 +231,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 908>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; gpio5: gpio@e6055000 { @@ -245,7 +245,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 907>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; gpio6: gpio@e6055400 { @@ -259,7 +259,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 906>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; gpio7: gpio@e6055800 { @@ -273,7 +273,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 905>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; pmu_a57 { @@ -342,7 +342,7 @@ "ch12", "ch13", "ch14", "ch15"; clocks = <&cpg CPG_MOD 502>; clock-names = "fck"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <16>; }; @@ -374,7 +374,7 @@ "ch12", "ch13", "ch14", "ch15"; clocks = <&cpg CPG_MOD 501>; clock-names = "fck"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <16>; }; @@ -396,7 +396,7 @@ GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 407>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; }; dmac0: dma-controller@e6700000 { @@ -427,7 +427,7 @@ "ch12", "ch13", "ch14", "ch15"; clocks = <&cpg CPG_MOD 219>; clock-names = "fck"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <16>; }; @@ -460,7 +460,7 @@ "ch12", "ch13", "ch14", "ch15"; clocks = <&cpg CPG_MOD 218>; clock-names = "fck"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <16>; }; @@ -493,7 +493,7 @@ "ch12", "ch13", "ch14", "ch15"; clocks = <&cpg CPG_MOD 217>; clock-names = "fck"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <16>; }; @@ -535,7 +535,7 @@ "ch20", "ch21", "ch22", "ch23", "ch24"; clocks = <&cpg CPG_MOD 812>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; phy-mode = "rgmii-id"; #address-cells = <1>; #size-cells = <0>; @@ -552,7 +552,7 @@ clock-names = "clkp1", "clkp2", "can_clk"; assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>; assigned-clock-rates = <40000000>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -567,7 +567,7 @@ clock-names = "clkp1", "clkp2", "can_clk"; assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>; assigned-clock-rates = <40000000>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -583,7 +583,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac1 0x31>, <&dmac1 0x30>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -599,7 +599,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac1 0x33>, <&dmac1 0x32>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -615,7 +615,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac1 0x35>, <&dmac1 0x34>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -631,7 +631,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x37>, <&dmac0 0x36>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -647,7 +647,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x39>, <&dmac0 0x38>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -662,7 +662,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac1 0x51>, <&dmac1 0x50>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -677,7 +677,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac1 0x53>, <&dmac1 0x52>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -692,7 +692,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac1 0x13>, <&dmac1 0x12>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -707,7 +707,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x57>, <&dmac0 0x56>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -722,7 +722,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x59>, <&dmac0 0x58>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -737,7 +737,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac1 0x5b>, <&dmac1 0x5a>; dma-names = "tx", "rx"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -748,7 +748,7 @@ reg = <0 0xe6500000 0 0x40>; interrupts = ; clocks = <&cpg CPG_MOD 931>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -760,7 +760,7 @@ reg = <0 0xe6508000 0 0x40>; interrupts = ; clocks = <&cpg CPG_MOD 930>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -772,7 +772,7 @@ reg = <0 0xe6510000 0 0x40>; interrupts = ; clocks = <&cpg CPG_MOD 929>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -784,7 +784,7 @@ reg = <0 0xe66d0000 0 0x40>; interrupts = ; clocks = <&cpg CPG_MOD 928>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -796,7 +796,7 @@ reg = <0 0xe66d8000 0 0x40>; interrupts = ; clocks = <&cpg CPG_MOD 927>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -808,7 +808,7 @@ reg = <0 0xe66e0000 0 0x40>; interrupts = ; clocks = <&cpg CPG_MOD 919>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -820,7 +820,7 @@ reg = <0 0xe66e8000 0 0x40>; interrupts = ; clocks = <&cpg CPG_MOD 918>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -870,7 +870,7 @@ "src.1", "src.0", "dvc.0", "dvc.1", "clk_a", "clk_b", "clk_c", "clk_i"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; rcar_sound,dvc { @@ -1004,7 +1004,7 @@ reg = <0 0xee000000 0 0xc00>; interrupts = ; clocks = <&cpg CPG_MOD 328>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1013,7 +1013,7 @@ reg = <0 0xee040000 0 0xc00>; interrupts = ; clocks = <&cpg CPG_MOD 327>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1025,7 +1025,7 @@ GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "ch0", "ch1"; clocks = <&cpg CPG_MOD 330>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <2>; }; @@ -1038,7 +1038,7 @@ GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "ch0", "ch1"; clocks = <&cpg CPG_MOD 331>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <2>; }; @@ -1048,7 +1048,7 @@ reg = <0 0xee100000 0 0x2000>; interrupts = ; clocks = <&cpg CPG_MOD 314>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1057,7 +1057,7 @@ reg = <0 0xee120000 0 0x2000>; interrupts = ; clocks = <&cpg CPG_MOD 313>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1066,7 +1066,7 @@ reg = <0 0xee140000 0 0x2000>; interrupts = ; clocks = <&cpg CPG_MOD 312>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; cap-mmc-highspeed; status = "disabled"; }; @@ -1076,7 +1076,7 @@ reg = <0 0xee160000 0 0x2000>; interrupts = ; clocks = <&cpg CPG_MOD 311>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; cap-mmc-highspeed; status = "disabled"; }; @@ -1086,7 +1086,7 @@ reg = <0 0xee080200 0 0x700>; interrupts = ; clocks = <&cpg CPG_MOD 703>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #phy-cells = <0>; status = "disabled"; }; @@ -1095,7 +1095,7 @@ compatible = "renesas,usb2-phy-r8a7795"; reg = <0 0xee0a0200 0 0x700>; clocks = <&cpg CPG_MOD 702>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #phy-cells = <0>; status = "disabled"; }; @@ -1104,7 +1104,7 @@ compatible = "renesas,usb2-phy-r8a7795"; reg = <0 0xee0c0200 0 0x700>; clocks = <&cpg CPG_MOD 701>; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; #phy-cells = <0>; status = "disabled"; }; @@ -1116,7 +1116,7 @@ clocks = <&cpg CPG_MOD 703>; phys = <&usb2_phy0>; phy-names = "usb"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1127,7 +1127,7 @@ clocks = <&cpg CPG_MOD 702>; phys = <&usb2_phy1>; phy-names = "usb"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1138,7 +1138,7 @@ clocks = <&cpg CPG_MOD 701>; phys = <&usb2_phy2>; phy-names = "usb"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1149,7 +1149,7 @@ clocks = <&cpg CPG_MOD 703>; phys = <&usb2_phy0>; phy-names = "usb"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1160,7 +1160,7 @@ clocks = <&cpg CPG_MOD 702>; phys = <&usb2_phy1>; phy-names = "usb"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1171,7 +1171,7 @@ clocks = <&cpg CPG_MOD 701>; phys = <&usb2_phy2>; phy-names = "usb"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; pciec0: pcie@fe000000 { @@ -1195,7 +1195,7 @@ interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>; clock-names = "pcie", "pcie_bus"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1220,7 +1220,7 @@ interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 318>, <&pcie_bus_clk>; clock-names = "pcie", "pcie_bus"; - power-domains = <&cpg>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; }; -- GitLab From b2df3aa487395a1b7170b719569769bc78939dd1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Jun 2015 10:14:01 +0200 Subject: [PATCH 4731/9938] ARM: dts: r8a7779: Add SYSC PM Domains Add a device node for the System Controller. Hook up ARM CPU cores 1-3 to their respective PM Domains. Note that ARM CPU core 0 cannot be shut off. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index 5c1d48d712a1..e02875a8c040 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -14,6 +14,7 @@ #include #include #include +#include / { compatible = "renesas,r8a7779"; @@ -34,18 +35,21 @@ compatible = "arm,cortex-a9"; reg = <1>; clock-frequency = <1000000000>; + power-domains = <&sysc R8A7779_PD_ARM1>; }; cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a9"; reg = <2>; clock-frequency = <1000000000>; + power-domains = <&sysc R8A7779_PD_ARM2>; }; cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a9"; reg = <3>; clock-frequency = <1000000000>; + power-domains = <&sysc R8A7779_PD_ARM3>; }; }; @@ -586,4 +590,10 @@ "mmc1", "mmc0"; }; }; + + sysc: system-controller@ffd85000 { + compatible = "renesas,r8a7779-sysc"; + reg = <0xffd85000 0x0200>; + #power-domain-cells = <1>; + }; }; -- GitLab From 4c8eb3c8896d842d3fb4802dc6e5f39733596733 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 20 Jan 2015 14:44:58 +0100 Subject: [PATCH 4732/9938] ARM: dts: r8a7790: Add SYSC PM Domains Add a device node for the System Controller. Hook up the Cortex-A15 and Cortex-A7 CPU cores and L2 caches/SCUs to their respective PM Domains. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 776a2aed81d2..36c91d921771 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include / { compatible = "renesas,r8a7790"; @@ -52,6 +53,7 @@ voltage-tolerance = <1>; /* 1% */ clocks = <&cpg_clocks R8A7790_CLK_Z>; clock-latency = <300000>; /* 300 us */ + power-domains = <&sysc R8A7790_PD_CA15_CPU0>; next-level-cache = <&L2_CA15>; /* kHz - uV - OPPs unknown yet */ @@ -68,6 +70,7 @@ compatible = "arm,cortex-a15"; reg = <1>; clock-frequency = <1300000000>; + power-domains = <&sysc R8A7790_PD_CA15_CPU1>; next-level-cache = <&L2_CA15>; }; @@ -76,6 +79,7 @@ compatible = "arm,cortex-a15"; reg = <2>; clock-frequency = <1300000000>; + power-domains = <&sysc R8A7790_PD_CA15_CPU2>; next-level-cache = <&L2_CA15>; }; @@ -84,6 +88,7 @@ compatible = "arm,cortex-a15"; reg = <3>; clock-frequency = <1300000000>; + power-domains = <&sysc R8A7790_PD_CA15_CPU3>; next-level-cache = <&L2_CA15>; }; @@ -92,6 +97,7 @@ compatible = "arm,cortex-a7"; reg = <0x100>; clock-frequency = <780000000>; + power-domains = <&sysc R8A7790_PD_CA7_CPU0>; next-level-cache = <&L2_CA7>; }; @@ -100,6 +106,7 @@ compatible = "arm,cortex-a7"; reg = <0x101>; clock-frequency = <780000000>; + power-domains = <&sysc R8A7790_PD_CA7_CPU1>; next-level-cache = <&L2_CA7>; }; @@ -108,6 +115,7 @@ compatible = "arm,cortex-a7"; reg = <0x102>; clock-frequency = <780000000>; + power-domains = <&sysc R8A7790_PD_CA7_CPU2>; next-level-cache = <&L2_CA7>; }; @@ -116,6 +124,7 @@ compatible = "arm,cortex-a7"; reg = <0x103>; clock-frequency = <780000000>; + power-domains = <&sysc R8A7790_PD_CA7_CPU3>; next-level-cache = <&L2_CA7>; }; }; @@ -141,12 +150,14 @@ L2_CA15: cache-controller@0 { compatible = "cache"; + power-domains = <&sysc R8A7790_PD_CA15_SCU>; cache-unified; cache-level = <2>; }; L2_CA7: cache-controller@1 { compatible = "cache"; + power-domains = <&sysc R8A7790_PD_CA7_SCU>; cache-unified; cache-level = <2>; }; @@ -1450,6 +1461,12 @@ }; }; + sysc: system-controller@e6180000 { + compatible = "renesas,r8a7790-sysc"; + reg = <0 0xe6180000 0 0x0200>; + #power-domain-cells = <1>; + }; + qspi: spi@e6b10000 { compatible = "renesas,qspi-r8a7790", "renesas,qspi"; reg = <0 0xe6b10000 0 0x2c>; -- GitLab From 8574de861978d5187da4f2b7dcf127a5795e967f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 20 Jan 2015 14:44:58 +0100 Subject: [PATCH 4733/9938] ARM: dts: r8a7791: Add SYSC PM Domains Add a device node for the System Controller. Hook up the Cortex-A15 CPU cores and the Cortex-A15 L2 cache/SCU to their respective PM Domains. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 6d4a0b6e4df9..e30200c9476a 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include / { compatible = "renesas,r8a7791"; @@ -51,6 +52,7 @@ voltage-tolerance = <1>; /* 1% */ clocks = <&cpg_clocks R8A7791_CLK_Z>; clock-latency = <300000>; /* 300 us */ + power-domains = <&sysc R8A7791_PD_CA15_CPU0>; next-level-cache = <&L2_CA15>; /* kHz - uV - OPPs unknown yet */ @@ -67,6 +69,7 @@ compatible = "arm,cortex-a15"; reg = <1>; clock-frequency = <1500000000>; + power-domains = <&sysc R8A7791_PD_CA15_CPU1>; next-level-cache = <&L2_CA15>; }; }; @@ -92,6 +95,7 @@ L2_CA15: cache-controller@0 { compatible = "cache"; + power-domains = <&sysc R8A7791_PD_CA15_SCU>; cache-unified; cache-level = <2>; }; @@ -1466,6 +1470,12 @@ }; }; + sysc: system-controller@e6180000 { + compatible = "renesas,r8a7791-sysc"; + reg = <0 0xe6180000 0 0x0200>; + #power-domain-cells = <1>; + }; + qspi: spi@e6b10000 { compatible = "renesas,qspi-r8a7791", "renesas,qspi"; reg = <0 0xe6b10000 0 0x2c>; -- GitLab From a7ede1abeefd69330c5dd45b335d22af1e2baf2e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Jun 2015 10:43:13 +0200 Subject: [PATCH 4734/9938] ARM: dts: r8a7793: Add SYSC PM Domains Add a device node for the System Controller. Hook up the first Cortex-A15 CPU core and the Cortex-A15 L2 cache/SCU to their respective PM Domains. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7793.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index 6186179fd66d..53e235e3279d 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { compatible = "renesas,r8a7793"; @@ -43,6 +44,7 @@ voltage-tolerance = <1>; /* 1% */ clocks = <&cpg_clocks R8A7793_CLK_Z>; clock-latency = <300000>; /* 300 us */ + power-domains = <&sysc R8A7793_PD_CA15_CPU0>; /* kHz - uV - OPPs unknown yet */ operating-points = <1500000 1000000>, @@ -76,6 +78,7 @@ L2_CA15: cache-controller@0 { compatible = "cache"; + power-domains = <&sysc R8A7793_PD_CA15_SCU>; cache-unified; cache-level = <2>; }; @@ -1223,6 +1226,12 @@ }; }; + sysc: system-controller@e6180000 { + compatible = "renesas,r8a7793-sysc"; + reg = <0 0xe6180000 0 0x0200>; + #power-domain-cells = <1>; + }; + ipmmu_sy0: mmu@e6280000 { compatible = "renesas,ipmmu-r8a7793", "renesas,ipmmu-vmsa"; reg = <0 0xe6280000 0 0x1000>; -- GitLab From 0761ff2ad0c581f37067eff8c4bde65f07029fc8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 20 Jan 2015 14:44:58 +0100 Subject: [PATCH 4735/9938] ARM: dts: r8a7794: Add SYSC PM Domains Add a device node for the System Controller. Hook up the Cortex-A7 CPU cores and the Cortex-A7 L2 cache/SCU to their respective PM Domains. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index b0bce43779f1..70eff80a813e 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include / { compatible = "renesas,r8a7794"; @@ -42,6 +43,7 @@ compatible = "arm,cortex-a7"; reg = <0>; clock-frequency = <1000000000>; + power-domains = <&sysc R8A7794_PD_CA7_CPU0>; next-level-cache = <&L2_CA7>; }; @@ -50,12 +52,14 @@ compatible = "arm,cortex-a7"; reg = <1>; clock-frequency = <1000000000>; + power-domains = <&sysc R8A7794_PD_CA7_CPU1>; next-level-cache = <&L2_CA7>; }; }; L2_CA7: cache-controller@1 { compatible = "cache"; + power-domains = <&sysc R8A7794_PD_CA7_SCU>; cache-unified; cache-level = <2>; }; @@ -1215,6 +1219,12 @@ }; }; + sysc: system-controller@e6180000 { + compatible = "renesas,r8a7794-sysc"; + reg = <0 0xe6180000 0 0x0200>; + #power-domain-cells = <1>; + }; + ipmmu_sy0: mmu@e6280000 { compatible = "renesas,ipmmu-r8a7794", "renesas,ipmmu-vmsa"; reg = <0 0xe6280000 0 0x1000>; -- GitLab From 751e29bbb64ad091c6f51704f31224aaec560f69 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Jun 2015 10:14:01 +0200 Subject: [PATCH 4736/9938] ARM: dts: r8a7779: Use SYSC "always-on" PM Domain Hook up all devices that are part of the CPG/MSTP Clock Domain to the SYSC "always-on" PM Domain, for a more consistent device-power-area description in DT. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index e02875a8c040..d43e3b2105ae 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -177,7 +177,7 @@ reg = <0xffc70000 0x1000>; interrupts = ; clocks = <&mstp0_clks R8A7779_CLK_I2C0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -188,7 +188,7 @@ reg = <0xffc71000 0x1000>; interrupts = ; clocks = <&mstp0_clks R8A7779_CLK_I2C1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -199,7 +199,7 @@ reg = <0xffc72000 0x1000>; interrupts = ; clocks = <&mstp0_clks R8A7779_CLK_I2C2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -210,7 +210,7 @@ reg = <0xffc73000 0x1000>; interrupts = ; clocks = <&mstp0_clks R8A7779_CLK_I2C3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -222,7 +222,7 @@ clocks = <&mstp0_clks R8A7779_CLK_SCIF0>, <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>; clock-names = "fck", "brg_int", "scif_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -234,7 +234,7 @@ clocks = <&mstp0_clks R8A7779_CLK_SCIF1>, <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>; clock-names = "fck", "brg_int", "scif_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -246,7 +246,7 @@ clocks = <&mstp0_clks R8A7779_CLK_SCIF2>, <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>; clock-names = "fck", "brg_int", "scif_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -258,7 +258,7 @@ clocks = <&mstp0_clks R8A7779_CLK_SCIF3>, <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>; clock-names = "fck", "brg_int", "scif_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -270,7 +270,7 @@ clocks = <&mstp0_clks R8A7779_CLK_SCIF4>, <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>; clock-names = "fck", "brg_int", "scif_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -282,7 +282,7 @@ clocks = <&mstp0_clks R8A7779_CLK_SCIF5>, <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>; clock-names = "fck", "brg_int", "scif_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -304,7 +304,7 @@ ; clocks = <&mstp0_clks R8A7779_CLK_TMU0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; #renesas,channels = <3>; @@ -319,7 +319,7 @@ ; clocks = <&mstp0_clks R8A7779_CLK_TMU1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; #renesas,channels = <3>; @@ -334,7 +334,7 @@ ; clocks = <&mstp0_clks R8A7779_CLK_TMU2>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; #renesas,channels = <3>; @@ -346,7 +346,7 @@ reg = <0xfc600000 0x2000>; interrupts = ; clocks = <&mstp1_clks R8A7779_CLK_SATA>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; }; sdhi0: sd@ffe4c000 { @@ -354,7 +354,7 @@ reg = <0xffe4c000 0x100>; interrupts = ; clocks = <&mstp3_clks R8A7779_CLK_SDHI0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -363,7 +363,7 @@ reg = <0xffe4d000 0x100>; interrupts = ; clocks = <&mstp3_clks R8A7779_CLK_SDHI1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -372,7 +372,7 @@ reg = <0xffe4e000 0x100>; interrupts = ; clocks = <&mstp3_clks R8A7779_CLK_SDHI2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -381,7 +381,7 @@ reg = <0xffe4f000 0x100>; interrupts = ; clocks = <&mstp3_clks R8A7779_CLK_SDHI3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -392,7 +392,7 @@ #address-cells = <1>; #size-cells = <0>; clocks = <&mstp0_clks R8A7779_CLK_HSPI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -403,7 +403,7 @@ #address-cells = <1>; #size-cells = <0>; clocks = <&mstp0_clks R8A7779_CLK_HSPI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -414,7 +414,7 @@ #address-cells = <1>; #size-cells = <0>; clocks = <&mstp0_clks R8A7779_CLK_HSPI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; }; @@ -423,7 +423,7 @@ reg = <0 0xfff80000 0 0x40000>; interrupts = ; clocks = <&mstp1_clks R8A7779_CLK_DU>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; ports { -- GitLab From 36ee3c277e018f71d456e3d7eac2c2887128a4db Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 20 Jan 2015 14:44:58 +0100 Subject: [PATCH 4737/9938] ARM: dts: r8a7790: Use SYSC "always-on" PM Domain Hook up all devices that are part of the CPG/MSTP Clock Domain to the SYSC "always-on" PM Domain, for a more consistent device-power-area description in DT. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 138 ++++++++++++++++----------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 36c91d921771..dc8497b15586 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -184,7 +184,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7790_CLK_GPIO0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; gpio1: gpio@e6051000 { @@ -197,7 +197,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7790_CLK_GPIO1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; gpio2: gpio@e6052000 { @@ -210,7 +210,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7790_CLK_GPIO2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; gpio3: gpio@e6053000 { @@ -223,7 +223,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7790_CLK_GPIO3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; gpio4: gpio@e6054000 { @@ -236,7 +236,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7790_CLK_GPIO4>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; gpio5: gpio@e6055000 { @@ -249,7 +249,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7790_CLK_GPIO5>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; thermal: thermal@e61f0000 { @@ -259,7 +259,7 @@ reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>; interrupts = ; clocks = <&mstp5_clks R8A7790_CLK_THERMAL>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #thermal-sensor-cells = <0>; }; @@ -278,7 +278,7 @@ ; clocks = <&mstp1_clks R8A7790_CLK_CMT0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; renesas,channels-mask = <0x60>; @@ -298,7 +298,7 @@ ; clocks = <&mstp3_clks R8A7790_CLK_CMT1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; renesas,channels-mask = <0xff>; @@ -315,7 +315,7 @@ , ; clocks = <&mstp4_clks R8A7790_CLK_IRQC>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; dmac0: dma-controller@e6700000 { @@ -344,7 +344,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -375,7 +375,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -404,7 +404,7 @@ "ch12"; clocks = <&mstp5_clks R8A7790_CLK_AUDIO_DMAC0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <13>; }; @@ -433,7 +433,7 @@ "ch12"; clocks = <&mstp5_clks R8A7790_CLK_AUDIO_DMAC1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <13>; }; @@ -445,7 +445,7 @@ GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "ch0", "ch1"; clocks = <&mstp3_clks R8A7790_CLK_USBDMAC0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <2>; }; @@ -457,7 +457,7 @@ GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "ch0", "ch1"; clocks = <&mstp3_clks R8A7790_CLK_USBDMAC1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <2>; }; @@ -469,7 +469,7 @@ reg = <0 0xe6508000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7790_CLK_I2C0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -481,7 +481,7 @@ reg = <0 0xe6518000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7790_CLK_I2C1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -493,7 +493,7 @@ reg = <0 0xe6530000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7790_CLK_I2C2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -505,7 +505,7 @@ reg = <0 0xe6540000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7790_CLK_I2C3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -519,7 +519,7 @@ clocks = <&mstp3_clks R8A7790_CLK_IIC0>; dmas = <&dmac0 0x61>, <&dmac0 0x62>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -532,7 +532,7 @@ clocks = <&mstp3_clks R8A7790_CLK_IIC1>; dmas = <&dmac0 0x65>, <&dmac0 0x66>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -545,7 +545,7 @@ clocks = <&mstp3_clks R8A7790_CLK_IIC2>; dmas = <&dmac0 0x69>, <&dmac0 0x6a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -558,7 +558,7 @@ clocks = <&mstp9_clks R8A7790_CLK_IICDVFS>; dmas = <&dmac0 0x77>, <&dmac0 0x78>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -569,7 +569,7 @@ clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>; dmas = <&dmac0 0xd1>, <&dmac0 0xd2>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; reg-io-width = <4>; status = "disabled"; max-frequency = <97500000>; @@ -582,7 +582,7 @@ clocks = <&mstp3_clks R8A7790_CLK_MMCIF1>; dmas = <&dmac0 0xe1>, <&dmac0 0xe2>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; reg-io-width = <4>; status = "disabled"; max-frequency = <97500000>; @@ -601,7 +601,7 @@ dmas = <&dmac1 0xcd>, <&dmac1 0xce>; dma-names = "tx", "rx"; max-frequency = <195000000>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -613,7 +613,7 @@ dmas = <&dmac1 0xc9>, <&dmac1 0xca>; dma-names = "tx", "rx"; max-frequency = <195000000>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -625,7 +625,7 @@ dmas = <&dmac1 0xc1>, <&dmac1 0xc2>; dma-names = "tx", "rx"; max-frequency = <97500000>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -637,7 +637,7 @@ dmas = <&dmac1 0xd3>, <&dmac1 0xd4>; dma-names = "tx", "rx"; max-frequency = <97500000>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -650,7 +650,7 @@ clock-names = "fck"; dmas = <&dmac0 0x21>, <&dmac0 0x22>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -663,7 +663,7 @@ clock-names = "fck"; dmas = <&dmac0 0x25>, <&dmac0 0x26>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -676,7 +676,7 @@ clock-names = "fck"; dmas = <&dmac0 0x27>, <&dmac0 0x28>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -689,7 +689,7 @@ clock-names = "fck"; dmas = <&dmac0 0x3d>, <&dmac0 0x3e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -702,7 +702,7 @@ clock-names = "fck"; dmas = <&dmac0 0x19>, <&dmac0 0x1a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -715,7 +715,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1d>, <&dmac0 0x1e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -729,7 +729,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x29>, <&dmac0 0x2a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -743,7 +743,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2d>, <&dmac0 0x2e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -757,7 +757,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2b>, <&dmac0 0x2c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -771,7 +771,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x39>, <&dmac0 0x3a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -785,7 +785,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x4d>, <&dmac0 0x4e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -794,7 +794,7 @@ reg = <0 0xee700000 0 0x400>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_ETHER>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; phy-mode = "rmii"; #address-cells = <1>; #size-cells = <0>; @@ -807,7 +807,7 @@ reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_ETHERAVB>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -818,7 +818,7 @@ reg = <0 0xee300000 0 0x2000>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_SATA0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -827,7 +827,7 @@ reg = <0 0xee500000 0 0x2000>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_SATA1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -839,7 +839,7 @@ dmas = <&usb_dmac0 0>, <&usb_dmac0 1>, <&usb_dmac1 0>, <&usb_dmac1 1>; dma-names = "ch0", "ch1", "ch2", "ch3"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; renesas,buswait = <4>; phys = <&usb0 1>; phy-names = "usb"; @@ -853,7 +853,7 @@ #size-cells = <0>; clocks = <&mstp7_clks R8A7790_CLK_HSUSB>; clock-names = "usbhs"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; usb0: usb-channel@0 { @@ -871,7 +871,7 @@ reg = <0 0xe6ef0000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_VIN0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -880,7 +880,7 @@ reg = <0 0xe6ef1000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_VIN1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -889,7 +889,7 @@ reg = <0 0xe6ef2000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_VIN2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -898,7 +898,7 @@ reg = <0 0xe6ef3000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7790_CLK_VIN3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -907,7 +907,7 @@ reg = <0 0xfe920000 0 0x8000>; interrupts = ; clocks = <&mstp1_clks R8A7790_CLK_VSP1_R>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; renesas,has-sru; renesas,#rpf = <5>; @@ -920,7 +920,7 @@ reg = <0 0xfe928000 0 0x8000>; interrupts = ; clocks = <&mstp1_clks R8A7790_CLK_VSP1_S>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; renesas,has-lut; renesas,has-sru; @@ -934,7 +934,7 @@ reg = <0 0xfe930000 0 0x8000>; interrupts = ; clocks = <&mstp1_clks R8A7790_CLK_VSP1_DU0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; renesas,has-lif; renesas,has-lut; @@ -948,7 +948,7 @@ reg = <0 0xfe938000 0 0x8000>; interrupts = ; clocks = <&mstp1_clks R8A7790_CLK_VSP1_DU1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; renesas,has-lif; renesas,has-lut; @@ -1003,7 +1003,7 @@ clocks = <&mstp9_clks R8A7790_CLK_RCAN0>, <&cpg_clocks R8A7790_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1014,7 +1014,7 @@ clocks = <&mstp9_clks R8A7790_CLK_RCAN1>, <&cpg_clocks R8A7790_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1023,7 +1023,7 @@ reg = <0 0xfe980000 0 0x10300>; interrupts = ; clocks = <&mstp1_clks R8A7790_CLK_JPU>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; }; clocks { @@ -1474,7 +1474,7 @@ clocks = <&mstp9_clks R8A7790_CLK_QSPI_MOD>; dmas = <&dmac0 0x17>, <&dmac0 0x18>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; num-cs = <1>; #address-cells = <1>; #size-cells = <0>; @@ -1488,7 +1488,7 @@ clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>; dmas = <&dmac0 0x51>, <&dmac0 0x52>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1501,7 +1501,7 @@ clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>; dmas = <&dmac0 0x55>, <&dmac0 0x56>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1514,7 +1514,7 @@ clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>; dmas = <&dmac0 0x41>, <&dmac0 0x42>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1527,7 +1527,7 @@ clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>; dmas = <&dmac0 0x45>, <&dmac0 0x46>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1538,7 +1538,7 @@ reg = <0 0xee000000 0 0xc00>; interrupts = ; clocks = <&mstp3_clks R8A7790_CLK_SSUSB>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; phys = <&usb2 1>; phy-names = "usb"; status = "disabled"; @@ -1551,7 +1551,7 @@ <0 0xee080000 0 0x1100>; interrupts = ; clocks = <&mstp7_clks R8A7790_CLK_EHCI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; bus-range = <0 0>; @@ -1586,7 +1586,7 @@ <0 0xee0a0000 0 0x1100>; interrupts = ; clocks = <&mstp7_clks R8A7790_CLK_EHCI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; bus-range = <1 1>; @@ -1604,7 +1604,7 @@ compatible = "renesas,pci-r8a7790", "renesas,pci-rcar-gen2"; device_type = "pci"; clocks = <&mstp7_clks R8A7790_CLK_EHCI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; reg = <0 0xee0d0000 0 0xc00>, <0 0xee0c0000 0 0x1100>; interrupts = ; @@ -1657,7 +1657,7 @@ interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7790_CLK_PCIEC>, <&pcie_bus_clk>; clock-names = "pcie", "pcie_bus"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1700,7 +1700,7 @@ "mix.0", "mix.1", "dvc.0", "dvc.1", "clk_a", "clk_b", "clk_c", "clk_i"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; status = "disabled"; -- GitLab From 5aa806503b48367e2e6e5ae2a6890805e40c4776 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 20 Jan 2015 14:44:58 +0100 Subject: [PATCH 4738/9938] ARM: dts: r8a7791: Use SYSC "always-on" PM Domain Hook up all devices that are part of the CPG/MSTP Clock Domain to the SYSC "always-on" PM Domain, for a more consistent device-power-area description in DT. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 146 ++++++++++++++++----------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index e30200c9476a..c40f950dfc19 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -122,7 +122,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; gpio1: gpio@e6051000 { @@ -135,7 +135,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; gpio2: gpio@e6052000 { @@ -148,7 +148,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; gpio3: gpio@e6053000 { @@ -161,7 +161,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; gpio4: gpio@e6054000 { @@ -174,7 +174,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO4>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; gpio5: gpio@e6055000 { @@ -187,7 +187,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO5>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; gpio6: gpio@e6055400 { @@ -200,7 +200,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO6>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; gpio7: gpio@e6055800 { @@ -213,7 +213,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7791_CLK_GPIO7>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; thermal: thermal@e61f0000 { @@ -223,7 +223,7 @@ reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>; interrupts = ; clocks = <&mstp5_clks R8A7791_CLK_THERMAL>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #thermal-sensor-cells = <0>; }; @@ -242,7 +242,7 @@ ; clocks = <&mstp1_clks R8A7791_CLK_CMT0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; renesas,channels-mask = <0x60>; @@ -262,7 +262,7 @@ ; clocks = <&mstp3_clks R8A7791_CLK_CMT1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; renesas,channels-mask = <0xff>; @@ -285,7 +285,7 @@ , ; clocks = <&mstp4_clks R8A7791_CLK_IRQC>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; dmac0: dma-controller@e6700000 { @@ -314,7 +314,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7791_CLK_SYS_DMAC0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -345,7 +345,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7791_CLK_SYS_DMAC1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -374,7 +374,7 @@ "ch12"; clocks = <&mstp5_clks R8A7791_CLK_AUDIO_DMAC0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <13>; }; @@ -403,7 +403,7 @@ "ch12"; clocks = <&mstp5_clks R8A7791_CLK_AUDIO_DMAC1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <13>; }; @@ -415,7 +415,7 @@ GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "ch0", "ch1"; clocks = <&mstp3_clks R8A7791_CLK_USBDMAC0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <2>; }; @@ -427,7 +427,7 @@ GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "ch0", "ch1"; clocks = <&mstp3_clks R8A7791_CLK_USBDMAC1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <2>; }; @@ -440,7 +440,7 @@ reg = <0 0xe6508000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_I2C0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -452,7 +452,7 @@ reg = <0 0xe6518000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_I2C1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -464,7 +464,7 @@ reg = <0 0xe6530000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_I2C2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -476,7 +476,7 @@ reg = <0 0xe6540000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_I2C3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -488,7 +488,7 @@ reg = <0 0xe6520000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_I2C4>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -501,7 +501,7 @@ reg = <0 0xe6528000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7791_CLK_I2C5>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -516,7 +516,7 @@ clocks = <&mstp9_clks R8A7791_CLK_IICDVFS>; dmas = <&dmac0 0x77>, <&dmac0 0x78>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -529,7 +529,7 @@ clocks = <&mstp3_clks R8A7791_CLK_IIC0>; dmas = <&dmac0 0x61>, <&dmac0 0x62>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -542,7 +542,7 @@ clocks = <&mstp3_clks R8A7791_CLK_IIC1>; dmas = <&dmac0 0x65>, <&dmac0 0x66>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -558,7 +558,7 @@ clocks = <&mstp3_clks R8A7791_CLK_MMCIF0>; dmas = <&dmac0 0xd1>, <&dmac0 0xd2>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; reg-io-width = <4>; status = "disabled"; max-frequency = <97500000>; @@ -571,7 +571,7 @@ clocks = <&mstp3_clks R8A7791_CLK_SDHI0>; dmas = <&dmac1 0xcd>, <&dmac1 0xce>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -582,7 +582,7 @@ clocks = <&mstp3_clks R8A7791_CLK_SDHI1>; dmas = <&dmac1 0xc1>, <&dmac1 0xc2>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -593,7 +593,7 @@ clocks = <&mstp3_clks R8A7791_CLK_SDHI2>; dmas = <&dmac1 0xd3>, <&dmac1 0xd4>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -606,7 +606,7 @@ clock-names = "fck"; dmas = <&dmac0 0x21>, <&dmac0 0x22>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -619,7 +619,7 @@ clock-names = "fck"; dmas = <&dmac0 0x25>, <&dmac0 0x26>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -632,7 +632,7 @@ clock-names = "fck"; dmas = <&dmac0 0x27>, <&dmac0 0x28>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -645,7 +645,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1b>, <&dmac0 0x1c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -658,7 +658,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1f>, <&dmac0 0x20>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -671,7 +671,7 @@ clock-names = "fck"; dmas = <&dmac0 0x23>, <&dmac0 0x24>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -684,7 +684,7 @@ clock-names = "fck"; dmas = <&dmac0 0x3d>, <&dmac0 0x3e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -697,7 +697,7 @@ clock-names = "fck"; dmas = <&dmac0 0x19>, <&dmac0 0x1a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -710,7 +710,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1d>, <&dmac0 0x1e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -724,7 +724,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x29>, <&dmac0 0x2a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -738,7 +738,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2d>, <&dmac0 0x2e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -752,7 +752,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2b>, <&dmac0 0x2c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -766,7 +766,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2f>, <&dmac0 0x30>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -780,7 +780,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0xfb>, <&dmac0 0xfc>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -794,7 +794,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0xfd>, <&dmac0 0xfe>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -808,7 +808,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x39>, <&dmac0 0x3a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -822,7 +822,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x4d>, <&dmac0 0x4e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -836,7 +836,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x3b>, <&dmac0 0x3c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -845,7 +845,7 @@ reg = <0 0xee700000 0 0x400>; interrupts = ; clocks = <&mstp8_clks R8A7791_CLK_ETHER>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; phy-mode = "rmii"; #address-cells = <1>; #size-cells = <0>; @@ -858,7 +858,7 @@ reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>; interrupts = ; clocks = <&mstp8_clks R8A7791_CLK_ETHERAVB>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -869,7 +869,7 @@ reg = <0 0xee300000 0 0x2000>; interrupts = ; clocks = <&mstp8_clks R8A7791_CLK_SATA0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -878,7 +878,7 @@ reg = <0 0xee500000 0 0x2000>; interrupts = ; clocks = <&mstp8_clks R8A7791_CLK_SATA1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -890,7 +890,7 @@ dmas = <&usb_dmac0 0>, <&usb_dmac0 1>, <&usb_dmac1 0>, <&usb_dmac1 1>; dma-names = "ch0", "ch1", "ch2", "ch3"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; renesas,buswait = <4>; phys = <&usb0 1>; phy-names = "usb"; @@ -904,7 +904,7 @@ #size-cells = <0>; clocks = <&mstp7_clks R8A7791_CLK_HSUSB>; clock-names = "usbhs"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; usb0: usb-channel@0 { @@ -922,7 +922,7 @@ reg = <0 0xe6ef0000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7791_CLK_VIN0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -931,7 +931,7 @@ reg = <0 0xe6ef1000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7791_CLK_VIN1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -940,7 +940,7 @@ reg = <0 0xe6ef2000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7791_CLK_VIN2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -949,7 +949,7 @@ reg = <0 0xfe928000 0 0x8000>; interrupts = ; clocks = <&mstp1_clks R8A7791_CLK_VSP1_S>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; renesas,has-lut; renesas,has-sru; @@ -963,7 +963,7 @@ reg = <0 0xfe930000 0 0x8000>; interrupts = ; clocks = <&mstp1_clks R8A7791_CLK_VSP1_DU0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; renesas,has-lif; renesas,has-lut; @@ -977,7 +977,7 @@ reg = <0 0xfe938000 0 0x8000>; interrupts = ; clocks = <&mstp1_clks R8A7791_CLK_VSP1_DU1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; renesas,has-lif; renesas,has-lut; @@ -1023,7 +1023,7 @@ clocks = <&mstp9_clks R8A7791_CLK_RCAN0>, <&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1034,7 +1034,7 @@ clocks = <&mstp9_clks R8A7791_CLK_RCAN1>, <&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1043,7 +1043,7 @@ reg = <0 0xfe980000 0 0x10300>; interrupts = ; clocks = <&mstp1_clks R8A7791_CLK_JPU>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; }; clocks { @@ -1483,7 +1483,7 @@ clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>; dmas = <&dmac0 0x17>, <&dmac0 0x18>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; num-cs = <1>; #address-cells = <1>; #size-cells = <0>; @@ -1497,7 +1497,7 @@ clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>; dmas = <&dmac0 0x51>, <&dmac0 0x52>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1510,7 +1510,7 @@ clocks = <&mstp2_clks R8A7791_CLK_MSIOF1>; dmas = <&dmac0 0x55>, <&dmac0 0x56>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1523,7 +1523,7 @@ clocks = <&mstp2_clks R8A7791_CLK_MSIOF2>; dmas = <&dmac0 0x41>, <&dmac0 0x42>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1534,7 +1534,7 @@ reg = <0 0xee000000 0 0xc00>; interrupts = ; clocks = <&mstp3_clks R8A7791_CLK_SSUSB>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; phys = <&usb2 1>; phy-names = "usb"; status = "disabled"; @@ -1547,7 +1547,7 @@ <0 0xee080000 0 0x1100>; interrupts = ; clocks = <&mstp7_clks R8A7791_CLK_EHCI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; bus-range = <0 0>; @@ -1582,7 +1582,7 @@ <0 0xee0c0000 0 0x1100>; interrupts = ; clocks = <&mstp7_clks R8A7791_CLK_EHCI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; bus-range = <1 1>; @@ -1632,7 +1632,7 @@ interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7791_CLK_PCIEC>, <&pcie_bus_clk>; clock-names = "pcie", "pcie_bus"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1735,7 +1735,7 @@ "mix.0", "mix.1", "dvc.0", "dvc.1", "clk_a", "clk_b", "clk_c", "clk_i"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; status = "disabled"; -- GitLab From f1ba73eae71fde882dcb6ca5fa61f1b3bffb7e3e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Jun 2015 10:43:13 +0200 Subject: [PATCH 4739/9938] ARM: dts: r8a7793: Use SYSC "always-on" PM Domain Hook up all devices that are part of the CPG/MSTP Clock Domain to the SYSC "always-on" PM Domain, for a more consistent device-power-area description in DT. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7793.dtsi | 102 ++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index 53e235e3279d..2abf2e489699 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -105,7 +105,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; gpio1: gpio@e6051000 { @@ -118,7 +118,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; gpio2: gpio@e6052000 { @@ -131,7 +131,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; gpio3: gpio@e6053000 { @@ -144,7 +144,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; gpio4: gpio@e6054000 { @@ -157,7 +157,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO4>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; gpio5: gpio@e6055000 { @@ -170,7 +170,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO5>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; gpio6: gpio@e6055400 { @@ -183,7 +183,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO6>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; gpio7: gpio@e6055800 { @@ -196,7 +196,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7793_CLK_GPIO7>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; thermal: thermal@e61f0000 { @@ -206,7 +206,7 @@ reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>; interrupts = ; clocks = <&mstp5_clks R8A7793_CLK_THERMAL>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; #thermal-sensor-cells = <0>; }; @@ -225,7 +225,7 @@ ; clocks = <&mstp1_clks R8A7793_CLK_CMT0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; renesas,channels-mask = <0x60>; @@ -245,7 +245,7 @@ ; clocks = <&mstp3_clks R8A7793_CLK_CMT1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; renesas,channels-mask = <0xff>; @@ -268,7 +268,7 @@ , ; clocks = <&mstp4_clks R8A7793_CLK_IRQC>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; }; dmac0: dma-controller@e6700000 { @@ -297,7 +297,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7793_CLK_SYS_DMAC0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -328,7 +328,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7793_CLK_SYS_DMAC1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -357,7 +357,7 @@ "ch12"; clocks = <&mstp5_clks R8A7793_CLK_AUDIO_DMAC0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <13>; }; @@ -386,7 +386,7 @@ "ch12"; clocks = <&mstp5_clks R8A7793_CLK_AUDIO_DMAC1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <13>; }; @@ -399,7 +399,7 @@ reg = <0 0xe6508000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7793_CLK_I2C0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -411,7 +411,7 @@ reg = <0 0xe6518000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7793_CLK_I2C1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -423,7 +423,7 @@ reg = <0 0xe6530000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7793_CLK_I2C2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -435,7 +435,7 @@ reg = <0 0xe6540000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7793_CLK_I2C3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -447,7 +447,7 @@ reg = <0 0xe6520000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7793_CLK_I2C4>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <6>; status = "disabled"; }; @@ -460,7 +460,7 @@ reg = <0 0xe6528000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7793_CLK_I2C5>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; i2c-scl-internal-delay-ns = <110>; status = "disabled"; }; @@ -475,7 +475,7 @@ clocks = <&mstp9_clks R8A7793_CLK_IICDVFS>; dmas = <&dmac0 0x77>, <&dmac0 0x78>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -488,7 +488,7 @@ clocks = <&mstp3_clks R8A7793_CLK_IIC0>; dmas = <&dmac0 0x61>, <&dmac0 0x62>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -501,7 +501,7 @@ clocks = <&mstp3_clks R8A7793_CLK_IIC1>; dmas = <&dmac0 0x65>, <&dmac0 0x66>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -517,7 +517,7 @@ clocks = <&mstp3_clks R8A7793_CLK_SDHI0>; dmas = <&dmac0 0xcd>, <&dmac0 0xce>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -528,7 +528,7 @@ clocks = <&mstp3_clks R8A7793_CLK_SDHI1>; dmas = <&dmac0 0xc1>, <&dmac0 0xc2>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -539,7 +539,7 @@ clocks = <&mstp3_clks R8A7793_CLK_SDHI2>; dmas = <&dmac0 0xd3>, <&dmac0 0xd4>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -552,7 +552,7 @@ clock-names = "fck"; dmas = <&dmac0 0x21>, <&dmac0 0x22>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -565,7 +565,7 @@ clock-names = "fck"; dmas = <&dmac0 0x25>, <&dmac0 0x26>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -578,7 +578,7 @@ clock-names = "fck"; dmas = <&dmac0 0x27>, <&dmac0 0x28>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -591,7 +591,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1b>, <&dmac0 0x1c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -604,7 +604,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1f>, <&dmac0 0x20>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -617,7 +617,7 @@ clock-names = "fck"; dmas = <&dmac0 0x23>, <&dmac0 0x24>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -630,7 +630,7 @@ clock-names = "fck"; dmas = <&dmac0 0x3d>, <&dmac0 0x3e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -643,7 +643,7 @@ clock-names = "fck"; dmas = <&dmac0 0x19>, <&dmac0 0x1a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -656,7 +656,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1d>, <&dmac0 0x1e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -670,7 +670,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x29>, <&dmac0 0x2a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -684,7 +684,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2d>, <&dmac0 0x2e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -698,7 +698,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2b>, <&dmac0 0x2c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -712,7 +712,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2f>, <&dmac0 0x30>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -726,7 +726,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0xfb>, <&dmac0 0xfc>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -740,7 +740,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0xfd>, <&dmac0 0xfe>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -754,7 +754,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x39>, <&dmac0 0x3a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -768,7 +768,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x4d>, <&dmac0 0x4e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -782,7 +782,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x3b>, <&dmac0 0x3c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -791,7 +791,7 @@ reg = <0 0xee700000 0 0x400>; interrupts = ; clocks = <&mstp8_clks R8A7793_CLK_ETHER>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; phy-mode = "rmii"; #address-cells = <1>; #size-cells = <0>; @@ -805,7 +805,7 @@ clocks = <&mstp9_clks R8A7793_CLK_QSPI_MOD>; dmas = <&dmac0 0x17>, <&dmac0 0x18>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; num-cs = <1>; #address-cells = <1>; #size-cells = <0>; @@ -849,7 +849,7 @@ clocks = <&mstp9_clks R8A7793_CLK_RCAN0>, <&cpg_clocks R8A7793_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -860,7 +860,7 @@ clocks = <&mstp9_clks R8A7793_CLK_RCAN1>, <&cpg_clocks R8A7793_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1327,7 +1327,7 @@ "src.4", "src.3", "src.2", "src.1", "src.0", "dvc.0", "dvc.1", "clk_a", "clk_b", "clk_c", "clk_i"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7793_PD_ALWAYS_ON>; status = "disabled"; -- GitLab From 25611e4ef5bb290805305d499715a840826462f3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 20 Jan 2015 14:44:58 +0100 Subject: [PATCH 4740/9938] ARM: dts: r8a7794: Use SYSC "always-on" PM Domain Hook up all devices that are part of the CPG/MSTP Clock Domain to the SYSC "always-on" PM Domain, for a more consistent device-power-area description in DT. Signed-off-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 106 ++++++++++++++++----------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 70eff80a813e..136911c1dc74 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -86,7 +86,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7794_CLK_GPIO0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; gpio1: gpio@e6051000 { @@ -99,7 +99,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7794_CLK_GPIO1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; gpio2: gpio@e6052000 { @@ -112,7 +112,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7794_CLK_GPIO2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; gpio3: gpio@e6053000 { @@ -125,7 +125,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7794_CLK_GPIO3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; gpio4: gpio@e6054000 { @@ -138,7 +138,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7794_CLK_GPIO4>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; gpio5: gpio@e6055000 { @@ -151,7 +151,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7794_CLK_GPIO5>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; gpio6: gpio@e6055400 { @@ -164,7 +164,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&mstp9_clks R8A7794_CLK_GPIO6>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; cmt0: timer@ffca0000 { @@ -174,7 +174,7 @@ ; clocks = <&mstp1_clks R8A7794_CLK_CMT0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; renesas,channels-mask = <0x60>; @@ -194,7 +194,7 @@ ; clocks = <&mstp3_clks R8A7794_CLK_CMT1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; renesas,channels-mask = <0xff>; @@ -225,7 +225,7 @@ , ; clocks = <&mstp4_clks R8A7794_CLK_IRQC>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; }; pfc: pin-controller@e6060000 { @@ -259,7 +259,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7794_CLK_SYS_DMAC0>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -290,7 +290,7 @@ "ch12", "ch13", "ch14"; clocks = <&mstp2_clks R8A7794_CLK_SYS_DMAC1>; clock-names = "fck"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #dma-cells = <1>; dma-channels = <15>; }; @@ -304,7 +304,7 @@ clock-names = "fck"; dmas = <&dmac0 0x21>, <&dmac0 0x22>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -317,7 +317,7 @@ clock-names = "fck"; dmas = <&dmac0 0x25>, <&dmac0 0x26>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -330,7 +330,7 @@ clock-names = "fck"; dmas = <&dmac0 0x27>, <&dmac0 0x28>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -343,7 +343,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1b>, <&dmac0 0x1c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -356,7 +356,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1f>, <&dmac0 0x20>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -369,7 +369,7 @@ clock-names = "fck"; dmas = <&dmac0 0x23>, <&dmac0 0x24>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -382,7 +382,7 @@ clock-names = "fck"; dmas = <&dmac0 0x3d>, <&dmac0 0x3e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -395,7 +395,7 @@ clock-names = "fck"; dmas = <&dmac0 0x19>, <&dmac0 0x1a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -408,7 +408,7 @@ clock-names = "fck"; dmas = <&dmac0 0x1d>, <&dmac0 0x1e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -422,7 +422,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x29>, <&dmac0 0x2a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -436,7 +436,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2d>, <&dmac0 0x2e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -450,7 +450,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2b>, <&dmac0 0x2c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -464,7 +464,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x2f>, <&dmac0 0x30>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -478,7 +478,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0xfb>, <&dmac0 0xfc>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -492,7 +492,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0xfd>, <&dmac0 0xfe>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -506,7 +506,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x39>, <&dmac0 0x3a>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -520,7 +520,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x4d>, <&dmac0 0x4e>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -534,7 +534,7 @@ clock-names = "fck", "brg_int", "scif_clk"; dmas = <&dmac0 0x3b>, <&dmac0 0x3c>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -543,7 +543,7 @@ reg = <0 0xee700000 0 0x400>; interrupts = ; clocks = <&mstp8_clks R8A7794_CLK_ETHER>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; phy-mode = "rmii"; #address-cells = <1>; #size-cells = <0>; @@ -556,7 +556,7 @@ reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>; interrupts = ; clocks = <&mstp8_clks R8A7794_CLK_ETHERAVB>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -568,7 +568,7 @@ reg = <0 0xe6508000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7794_CLK_I2C0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; i2c-scl-internal-delay-ns = <6>; @@ -580,7 +580,7 @@ reg = <0 0xe6518000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7794_CLK_I2C1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; i2c-scl-internal-delay-ns = <6>; @@ -592,7 +592,7 @@ reg = <0 0xe6530000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7794_CLK_I2C2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; i2c-scl-internal-delay-ns = <6>; @@ -604,7 +604,7 @@ reg = <0 0xe6540000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7794_CLK_I2C3>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; i2c-scl-internal-delay-ns = <6>; @@ -616,7 +616,7 @@ reg = <0 0xe6520000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7794_CLK_I2C4>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; i2c-scl-internal-delay-ns = <6>; @@ -628,7 +628,7 @@ reg = <0 0xe6528000 0 0x40>; interrupts = ; clocks = <&mstp9_clks R8A7794_CLK_I2C5>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; i2c-scl-internal-delay-ns = <6>; @@ -642,7 +642,7 @@ clocks = <&mstp3_clks R8A7794_CLK_IIC0>; dmas = <&dmac0 0x61>, <&dmac0 0x62>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -655,7 +655,7 @@ clocks = <&mstp3_clks R8A7794_CLK_IIC1>; dmas = <&dmac0 0x65>, <&dmac0 0x66>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -668,7 +668,7 @@ clocks = <&mstp3_clks R8A7794_CLK_MMCIF0>; dmas = <&dmac0 0xd1>, <&dmac0 0xd2>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; reg-io-width = <4>; status = "disabled"; }; @@ -678,7 +678,7 @@ reg = <0 0xee100000 0 0x200>; interrupts = ; clocks = <&mstp3_clks R8A7794_CLK_SDHI0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -687,7 +687,7 @@ reg = <0 0xee140000 0 0x100>; interrupts = ; clocks = <&mstp3_clks R8A7794_CLK_SDHI1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -696,7 +696,7 @@ reg = <0 0xee160000 0 0x100>; interrupts = ; clocks = <&mstp3_clks R8A7794_CLK_SDHI2>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -707,7 +707,7 @@ clocks = <&mstp9_clks R8A7794_CLK_QSPI_MOD>; dmas = <&dmac0 0x17>, <&dmac0 0x18>; dma-names = "tx", "rx"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; num-cs = <1>; #address-cells = <1>; #size-cells = <0>; @@ -719,7 +719,7 @@ reg = <0 0xe6ef0000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7794_CLK_VIN0>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -728,7 +728,7 @@ reg = <0 0xe6ef1000 0 0x1000>; interrupts = ; clocks = <&mstp8_clks R8A7794_CLK_VIN1>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -739,7 +739,7 @@ <0 0xee080000 0 0x1100>; interrupts = ; clocks = <&mstp7_clks R8A7794_CLK_EHCI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; bus-range = <0 0>; @@ -774,7 +774,7 @@ <0 0xee0c0000 0 0x1100>; interrupts = ; clocks = <&mstp7_clks R8A7794_CLK_EHCI>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; bus-range = <1 1>; @@ -807,7 +807,7 @@ reg = <0 0xe6590000 0 0x100>; interrupts = ; clocks = <&mstp7_clks R8A7794_CLK_HSUSB>; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; renesas,buswait = <4>; phys = <&usb0 1>; phy-names = "usb"; @@ -821,7 +821,7 @@ #size-cells = <0>; clocks = <&mstp7_clks R8A7794_CLK_HSUSB>; clock-names = "usbhs"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; usb0: usb-channel@0 { @@ -869,7 +869,7 @@ clocks = <&mstp9_clks R8A7794_CLK_RCAN0>, <&cpg_clocks R8A7794_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; @@ -880,7 +880,7 @@ clocks = <&mstp9_clks R8A7794_CLK_RCAN1>, <&cpg_clocks R8A7794_CLK_RCAN>, <&can_clk>; clock-names = "clkp1", "clkp2", "can_clk"; - power-domains = <&cpg_clocks>; + power-domains = <&sysc R8A7794_PD_ALWAYS_ON>; status = "disabled"; }; -- GitLab From 8d2ae1cbe8a984d7a755755fb53955de2f60a2f9 Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Wed, 27 Apr 2016 01:11:21 -0400 Subject: [PATCH 4741/9938] ext4: remove trailing \n from ext4_warning/ext4_error calls Messages passed to ext4_warning() or ext4_error() don't need trailing newlines, because these function add the newlines themselves. Signed-off-by: Jakub Wilk --- fs/ext4/extents.c | 4 ++-- fs/ext4/extents_status.c | 2 +- fs/ext4/file.c | 2 +- fs/ext4/inline.c | 2 +- fs/ext4/mballoc.c | 2 +- fs/ext4/mmp.c | 4 ++-- fs/ext4/namei.c | 2 +- fs/ext4/resize.c | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ba2be53a61d2..c53d5a8d2a79 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2588,7 +2588,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, } } else ext4_error(sbi->s_sb, "strange request: removal(2) " - "%u-%u from %u:%u\n", + "%u-%u from %u:%u", from, to, le32_to_cpu(ex->ee_block), ee_len); return 0; } @@ -3743,7 +3743,7 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle, if (ee_block != map->m_lblk || ee_len > map->m_len) { #ifdef EXT4_DEBUG ext4_warning("Inode (%ld) finished: extent logical block %llu," - " len %u; IO logical block %llu, len %u\n", + " len %u; IO logical block %llu, len %u", inode->i_ino, (unsigned long long)ee_block, ee_len, (unsigned long long)map->m_lblk, map->m_len); #endif diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index e38b987ac7f5..37e059202cd2 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -707,7 +707,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, (status & EXTENT_STATUS_WRITTEN)) { ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as " " delayed and written which can potentially " - " cause data loss.\n", lblk, len); + " cause data loss.", lblk, len); WARN_ON(1); } diff --git a/fs/ext4/file.c b/fs/ext4/file.c index fa2208bae2e1..3e850b988923 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -378,7 +378,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) if (ext4_encrypted_inode(d_inode(dir)) && !ext4_is_child_context_consistent_with_parent(d_inode(dir), inode)) { ext4_warning(inode->i_sb, - "Inconsistent encryption contexts: %lu/%lu\n", + "Inconsistent encryption contexts: %lu/%lu", (unsigned long) d_inode(dir)->i_ino, (unsigned long) inode->i_ino); dput(dir); diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 7bc6c855cc18..ff7538c26992 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1780,7 +1780,7 @@ int empty_inline_dir(struct inode *dir, int *has_inline_data) ext4_warning(dir->i_sb, "bad inline directory (dir #%lu) - " "inode %u, rec_len %u, name_len %d" - "inline size %d\n", + "inline size %d", dir->i_ino, le32_to_cpu(de->inode), le16_to_cpu(de->rec_len), de->name_len, inline_size); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index eeeade76012e..efa111a7606d 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4935,7 +4935,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, * boundary. */ if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) { - ext4_warning(sb, "too much blocks added to group %u\n", + ext4_warning(sb, "too much blocks added to group %u", block_group); err = -EINVAL; goto error_return; diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index 24445275d330..23d436d6f8b8 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -121,7 +121,7 @@ void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp, __ext4_warning(sb, function, line, "%s", msg); __ext4_warning(sb, function, line, "MMP failure info: last update time: %llu, last update " - "node: %s, last update device: %s\n", + "node: %s, last update device: %s", (long long unsigned int) le64_to_cpu(mmp->mmp_time), mmp->mmp_nodename, mmp->mmp_bdevname); } @@ -353,7 +353,7 @@ int ext4_multi_mount_protect(struct super_block *sb, * wait for MMP interval and check mmp_seq. */ if (schedule_timeout_interruptible(HZ * wait_time) != 0) { - ext4_warning(sb, "MMP startup interrupted, failing mount\n"); + ext4_warning(sb, "MMP startup interrupted, failing mount"); goto failed; } diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index c07422d254b6..6e6b3230ee45 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1618,7 +1618,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi if (nokey) return ERR_PTR(-ENOKEY); ext4_warning(inode->i_sb, - "Inconsistent encryption contexts: %lu/%lu\n", + "Inconsistent encryption contexts: %lu/%lu", (unsigned long) dir->i_ino, (unsigned long) inode->i_ino); return ERR_PTR(-EPERM); diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 34038e3598d5..cf681004b196 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -41,7 +41,7 @@ int ext4_resize_begin(struct super_block *sb) */ if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) { ext4_warning(sb, "There are errors in the filesystem, " - "so online resizing is not allowed\n"); + "so online resizing is not allowed"); return -EPERM; } -- GitLab From 5bcca743cb6e3ab97ff400ef92c7f57c787020f6 Mon Sep 17 00:00:00 2001 From: Madhavan Srinivasan Date: Thu, 21 Apr 2016 15:46:34 +0530 Subject: [PATCH 4742/9938] powerpc/perf: Replace raw event hex values with #defines Minor cleanup patch to replace the raw event hex values in power8-pmu.c with #defines. Signed-off-by: Madhavan Srinivasan Signed-off-by: Michael Ellerman --- arch/powerpc/perf/power8-events-list.h | 40 +++++++++++++++++++++++++ arch/powerpc/perf/power8-pmu.c | 41 +++++++++++++------------- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/perf/power8-events-list.h b/arch/powerpc/perf/power8-events-list.h index 741b77edd03e..3a2e6e8ebb92 100644 --- a/arch/powerpc/perf/power8-events-list.h +++ b/arch/powerpc/perf/power8-events-list.h @@ -49,3 +49,43 @@ EVENT(PM_L3_PREF_ALL, 0x4e052) EVENT(PM_DTLB_MISS, 0x300fc) /* ITLB Reloaded */ EVENT(PM_ITLB_MISS, 0x400fc) +/* Run_Instructions */ +EVENT(PM_RUN_INST_CMPL, 0x500fa) +/* Alternate event code for PM_RUN_INST_CMPL */ +EVENT(PM_RUN_INST_CMPL_ALT, 0x400fa) +/* Run_cycles */ +EVENT(PM_RUN_CYC, 0x600f4) +/* Alternate event code for Run_cycles */ +EVENT(PM_RUN_CYC_ALT, 0x200f4) +/* Marked store completed */ +EVENT(PM_MRK_ST_CMPL, 0x10134) +/* Alternate event code for Marked store completed */ +EVENT(PM_MRK_ST_CMPL_ALT, 0x301e2) +/* Marked two path branch */ +EVENT(PM_BR_MRK_2PATH, 0x10138) +/* Alternate event code for PM_BR_MRK_2PATH */ +EVENT(PM_BR_MRK_2PATH_ALT, 0x40138) +/* L3 castouts in Mepf state */ +EVENT(PM_L3_CO_MEPF, 0x18082) +/* Alternate event code for PM_L3_CO_MEPF */ +EVENT(PM_L3_CO_MEPF_ALT, 0x3e05e) +/* Data cache was reloaded from a location other than L2 due to a marked load */ +EVENT(PM_MRK_DATA_FROM_L2MISS, 0x1d14e) +/* Alternate event code for PM_MRK_DATA_FROM_L2MISS */ +EVENT(PM_MRK_DATA_FROM_L2MISS_ALT, 0x401e8) +/* Alternate event code for PM_CMPLU_STALL */ +EVENT(PM_CMPLU_STALL_ALT, 0x1e054) +/* Two path branch */ +EVENT(PM_BR_2PATH, 0x20036) +/* Alternate event code for PM_BR_2PATH */ +EVENT(PM_BR_2PATH_ALT, 0x40036) +/* # PPC Dispatched */ +EVENT(PM_INST_DISP, 0x200f2) +/* Alternate event code for PM_INST_DISP */ +EVENT(PM_INST_DISP_ALT, 0x300f2) +/* Marked filter Match */ +EVENT(PM_MRK_FILT_MATCH, 0x2013c) +/* Alternate event code for PM_MRK_FILT_MATCH */ +EVENT(PM_MRK_FILT_MATCH_ALT, 0x3012e) +/* Alternate event code for PM_LD_MISS_L1 */ +EVENT(PM_LD_MISS_L1_ALT, 0x400f0) diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 690d9186a855..7cf3b4378192 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c @@ -274,7 +274,8 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long /* Ignore Linux defined bits when checking event below */ base_event = event & ~EVENT_LINUX_MASK; - if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4) + if (pmc >= 5 && base_event != PM_RUN_INST_CMPL && + base_event != PM_RUN_CYC) return -1; mask |= CNST_PMC_MASK(pmc); @@ -488,17 +489,17 @@ static int power8_compute_mmcr(u64 event[], int n_ev, /* Table of alternatives, sorted by column 0 */ static const unsigned int event_alternatives[][MAX_ALT] = { - { 0x10134, 0x301e2 }, /* PM_MRK_ST_CMPL */ - { 0x10138, 0x40138 }, /* PM_BR_MRK_2PATH */ - { 0x18082, 0x3e05e }, /* PM_L3_CO_MEPF */ - { 0x1d14e, 0x401e8 }, /* PM_MRK_DATA_FROM_L2MISS */ - { 0x1e054, 0x4000a }, /* PM_CMPLU_STALL */ - { 0x20036, 0x40036 }, /* PM_BR_2PATH */ - { 0x200f2, 0x300f2 }, /* PM_INST_DISP */ - { 0x200f4, 0x600f4 }, /* PM_RUN_CYC */ - { 0x2013c, 0x3012e }, /* PM_MRK_FILT_MATCH */ - { 0x3e054, 0x400f0 }, /* PM_LD_MISS_L1 */ - { 0x400fa, 0x500fa }, /* PM_RUN_INST_CMPL */ + { PM_MRK_ST_CMPL, PM_MRK_ST_CMPL_ALT }, + { PM_BR_MRK_2PATH, PM_BR_MRK_2PATH_ALT }, + { PM_L3_CO_MEPF, PM_L3_CO_MEPF_ALT }, + { PM_MRK_DATA_FROM_L2MISS, PM_MRK_DATA_FROM_L2MISS_ALT }, + { PM_CMPLU_STALL_ALT, PM_CMPLU_STALL }, + { PM_BR_2PATH, PM_BR_2PATH_ALT }, + { PM_INST_DISP, PM_INST_DISP_ALT }, + { PM_RUN_CYC_ALT, PM_RUN_CYC }, + { PM_MRK_FILT_MATCH, PM_MRK_FILT_MATCH_ALT }, + { PM_LD_MISS_L1, PM_LD_MISS_L1_ALT }, + { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL }, }; /* @@ -546,17 +547,17 @@ static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[]) j = num_alt; for (i = 0; i < num_alt; ++i) { switch (alt[i]) { - case 0x1e: /* PM_CYC */ - alt[j++] = 0x600f4; /* PM_RUN_CYC */ + case PM_CYC: + alt[j++] = PM_RUN_CYC; break; - case 0x600f4: /* PM_RUN_CYC */ - alt[j++] = 0x1e; + case PM_RUN_CYC: + alt[j++] = PM_CYC; break; - case 0x2: /* PM_PPC_CMPL */ - alt[j++] = 0x500fa; /* PM_RUN_INST_CMPL */ + case PM_INST_CMPL: + alt[j++] = PM_RUN_INST_CMPL; break; - case 0x500fa: /* PM_RUN_INST_CMPL */ - alt[j++] = 0x2; /* PM_PPC_CMPL */ + case PM_RUN_INST_CMPL: + alt[j++] = PM_INST_CMPL; break; } } -- GitLab From da20dfe6b50ea4c1a82797b7ee8655a370535d73 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 21 Apr 2016 12:53:29 -0700 Subject: [PATCH 4743/9938] fs: fix over-zealous use of "const" When I was fixing up const recommendations from checkpatch.pl, I went overboard. This fixes the warning (during a W=1 build): include/linux/fs.h:2627:74: warning: type qualifiers ignored on function return type [-Wignored-qualifiers] static inline const char * const kernel_read_file_id_str(enum kernel_read_file_id id) Reported-by: Andy Shevchenko Signed-off-by: Kees Cook Signed-off-by: James Morris --- include/linux/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 90477550b935..9847d5c49a0e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2600,7 +2600,7 @@ static const char * const kernel_read_file_str[] = { __kernel_read_file_id(__fid_stringify) }; -static inline const char * const kernel_read_file_id_str(enum kernel_read_file_id id) +static inline const char *kernel_read_file_id_str(enum kernel_read_file_id id) { if (id < 0 || id >= READING_MAX_ID) return kernel_read_file_str[READING_UNKNOWN]; -- GitLab From c769c43f858a356010061694d99dd4c8c7de8ad7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 18 Apr 2016 09:44:13 +0200 Subject: [PATCH 4744/9938] ARM: dts: exynos: Remove unsupported s2mps11 regulator bindings from Exynos5420 boards The bindings like s2mps11,buck6-ramp-enable or s2mps11,buck2-ramp-delay were ignored. They were never parsed by s2mps11 regulator driver. Also the values used in these bindings were equal to default reset values of S2MPS11 device. It is safe to remove them. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas --- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 7 ------- arch/arm/boot/dts/exynos5420-smdk5420.dts | 7 ------- arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 7 ------- 3 files changed, 21 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index a103ce8c3985..60bc861d0f9d 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -75,13 +75,6 @@ s2mps11_pmic@66 { compatible = "samsung,s2mps11-pmic"; reg = <0x66>; - s2mps11,buck2-ramp-delay = <12>; - s2mps11,buck34-ramp-delay = <12>; - s2mps11,buck16-ramp-delay = <12>; - s2mps11,buck6-ramp-enable = <1>; - s2mps11,buck2-ramp-enable = <1>; - s2mps11,buck3-ramp-enable = <1>; - s2mps11,buck4-ramp-enable = <1>; interrupt-parent = <&gpx3>; interrupts = <2 IRQ_TYPE_EDGE_FALLING>; diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 99160f796851..9b77940c9201 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -142,13 +142,6 @@ s2mps11_pmic@66 { compatible = "samsung,s2mps11-pmic"; reg = <0x66>; - s2mps11,buck2-ramp-delay = <12>; - s2mps11,buck34-ramp-delay = <12>; - s2mps11,buck16-ramp-delay = <12>; - s2mps11,buck6-ramp-enable = <1>; - s2mps11,buck2-ramp-enable = <1>; - s2mps11,buck3-ramp-enable = <1>; - s2mps11,buck4-ramp-enable = <1>; s2mps11_osc: clocks { #clock-cells = <1>; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 0e71d4253205..20fa7612080d 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -92,13 +92,6 @@ s2mps11_pmic@66 { compatible = "samsung,s2mps11-pmic"; reg = <0x66>; - s2mps11,buck2-ramp-delay = <12>; - s2mps11,buck34-ramp-delay = <12>; - s2mps11,buck16-ramp-delay = <12>; - s2mps11,buck6-ramp-enable = <1>; - s2mps11,buck2-ramp-enable = <1>; - s2mps11,buck3-ramp-enable = <1>; - s2mps11,buck4-ramp-enable = <1>; samsung,s2mps11-acokb-ground; interrupt-parent = <&gpx0>; -- GitLab From 6dc62f12630a9ecf0c5427c5e25df759729ebe73 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Fri, 12 Feb 2016 22:31:40 +0900 Subject: [PATCH 4745/9938] ARM: dts: exynos: Add exynos5420-fimd compatible This patch changes the compatible of Exynos5420 fimd to "exynos5420-fimd". To support MIC bypass from display path, the new compatible is introduced for Exynos5420. Cc: Inki Dae Signed-off-by: Chanho Park Reviewed-by: Krzysztof Kozlowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5420.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 385491aa539a..4c8523471c65 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -1199,6 +1199,7 @@ }; &fimd { + compatible = "samsung,exynos5420-fimd"; clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>; clock-names = "sclk_fimd", "fimd"; power-domains = <&disp_pd>; -- GitLab From 8691f91b5f5b8687515654b065ebca447ba8b13a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 25 Apr 2016 11:29:56 +0200 Subject: [PATCH 4746/9938] ARM: dts: exynos: Enable PRNG and SSS for all Exynos4 devices There is no external dependency for Security SubSystem (SSS) block so the nodes for Pseudo Random Number Generator and AES hardware acceleration can be enabled always for all Exynos4 devices. Suggested-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4.dtsi | 2 -- arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 4 ---- arch/arm/boot/dts/exynos4412-trats2.dts | 8 -------- 3 files changed, 14 deletions(-) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 021f52d43ff7..2b8a45ffb44b 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -987,7 +987,6 @@ interrupts = <0 112 0>; clocks = <&clock CLK_SSS>; clock-names = "secss"; - status = "disabled"; }; prng: rng@10830400 { @@ -995,6 +994,5 @@ reg = <0x10830400 0x200>; clocks = <&clock CLK_SSS>; clock-names = "secss"; - status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index acd7e7b5fd13..cab0f07d7d28 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -496,10 +496,6 @@ status = "okay"; }; -&sss { - status = "okay"; -}; - &tmu { vtmu-supply = <&ldo10_reg>; status = "okay"; diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 27dbf1687754..5d1eaea3f778 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -1234,10 +1234,6 @@ status = "okay"; }; -&prng { - status = "okay"; -}; - &rtc { status = "okay"; clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>; @@ -1286,10 +1282,6 @@ }; }; -&sss { - status = "okay"; -}; - &tmu { vtmu-supply = <&ldo10_reg>; status = "okay"; -- GitLab From 451938d52fe838c766687484fd9a69e35d8a68bc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 27 Apr 2016 10:23:44 +0200 Subject: [PATCH 4747/9938] gpio: clarify open drain/source docs Make the text clearer, remove reference to confusing "positive" and "negative" and elaborate a bit. Signed-off-by: Linus Walleij --- Documentation/gpio/driver.txt | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt index ae6e0299b16c..6cb35a78eff4 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/gpio/driver.txt @@ -100,6 +100,10 @@ Both usecases require that the line be equipped with a pull-up resistor. This resistor will make the line tend to high level unless one of the transistors on the rail actively pulls it down. +The level on the line will go as high as the VDD on the pull-up resistor, which +may be higher than the level supported by the transistor, achieveing a +level-shift to the higher VDD. + Integrated electronics often have an output driver stage in the form of a CMOS "totem-pole" with one N-MOS and one P-MOS transistor where one of them drives the line high and one of them drives the line low. This is called a push-pull @@ -110,14 +114,18 @@ output. The "totem-pole" looks like so: OD ||--+ +--/ ---o|| P-MOS-FET | ||--+ -in --+ +----- out +IN --+ +----- out | ||--+ +--/ ----|| N-MOS-FET OS ||--+ | GND -You see the little "switches" named "OD" and "OS" that enable/disable the +The desired output signal (e.g. coming directly from some GPIO output register) +arrives at IN. The switches named "OD" and "OS" are normally closed, creating +a push-pull circuit. + +Consider the little "switches" named "OD" and "OS" that enable/disable the P-MOS or N-MOS transistor right after the split of the input. As you can see, either transistor will go totally numb if this switch is open. The totem-pole is then halved and give high impedance instead of actively driving the line @@ -128,8 +136,8 @@ Some GPIO hardware come in open drain / open source configuration. Some are hard-wired lines that will only support open drain or open source no matter what: there is only one transistor there. Some are software-configurable: by flipping a bit in a register the output can be configured as open drain -or open source, by flicking open the switches labeled "OD" and "OS" in the -drawing above. +or open source, in practice by flicking open the switches labeled "OD" and "OS" +in the drawing above. By disabling the P-MOS transistor, the output can be driven between GND and high impedance (open drain), and by disabling the N-MOS transistor, the output @@ -146,8 +154,8 @@ set in the machine file, or coming from other hardware descriptions. If this state can not be configured in hardware, i.e. if the GPIO hardware does not support open drain/open source in hardware, the GPIO library will instead use a trick: when a line is set as output, if the line is flagged as open -drain, and the output value is negative, it will be driven low as usual. But -if the output value is set to positive, it will instead *NOT* be driven high, +drain, and the IN output value is low, it will be driven low as usual. But +if the IN output value is set to high, it will instead *NOT* be driven high, instead it will be switched to input, as input mode is high impedance, thus achieveing an "open drain emulation" of sorts: electrically the behaviour will be identical, with the exception of possible hardware glitches when switching -- GitLab From edf69470f9ccd08cf799a5909b6de47d969ca29a Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 Apr 2016 16:48:44 -0400 Subject: [PATCH 4748/9938] kbuild: Fix dependencies for final vmlinux link The if_changed directive is useless against phony targets. Reported-by: Stephen Rothwell Fixes: 2441e78b1919 ("kbuild: better abstract vmlinux sequential prerequisites") Signed-off-by: Nicolas Pitre Signed-off-by: Michal Marek --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3f1eb6a1bf8d..5806729cef64 100644 --- a/Makefile +++ b/Makefile @@ -953,7 +953,7 @@ include/generated/autoksyms.h: FORCE cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) quiet_cmd_link-vmlinux = LINK $@ -vmlinux: scripts/link-vmlinux.sh vmlinux_prereq FORCE +vmlinux: scripts/link-vmlinux.sh vmlinux_prereq $(vmlinux-deps) FORCE +$(call if_changed,link-vmlinux) # Build samples along the rest of the kernel -- GitLab From 366f4856f0ef1f3dbdb85b0cc57bef2a77c08b86 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 Apr 2016 11:21:34 -0400 Subject: [PATCH 4749/9938] kbuild: adjust ksym_dep_filter for some cmd_* renames The following renames occurred recently: cmd_cc_i_c --> cmd_cpp_i_c cmd_as_s_S --> cmd_cpp_s_S The respective cc_*_c and as_*_S patterns no longer match the above therefore additional patterns are needed. Signed-off-by: Nicolas Pitre Signed-off-by: Michal Marek --- scripts/Kbuild.include | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index a09927e02713..36e9475395aa 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -275,10 +275,12 @@ else flags_nodeps = $(filter-out -Wp$(comma)-M%, $($(1))) ksym_dep_filter = \ case "$(1)" in \ - cc_*_c) $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ - as_*_S) $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ - boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ - *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ + cc_*_c|cpp_i_c) \ + $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ + as_*_S|cpp_s_S) \ + $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ + boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ + *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ esac | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' cmd_and_fixdep = \ -- GitLab From d686b920abb7136e0575ec974cd5a24f51a7a549 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 26 Apr 2016 09:54:11 +0200 Subject: [PATCH 4750/9938] nl80211: use nla_put_u64_64bit() for the remaining u64 attributes Nicolas converted most users, but didn't realize some were generated by macros. Convert those over as well. Signed-off-by: Johannes Berg Acked-by: Nicolas Dichtel Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 4 ++++ net/wireless/nl80211.c | 36 ++++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f958a7173eb4..e23d78685a01 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2517,6 +2517,7 @@ enum nl80211_sta_bss_param { * attributes carrying the actual values. * @NL80211_STA_INFO_RX_DURATION: aggregate PPDU duration for all frames * received from the station (u64, usec) + * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -2554,6 +2555,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_BEACON_SIGNAL_AVG, NL80211_STA_INFO_TID_STATS, NL80211_STA_INFO_RX_DURATION, + NL80211_STA_INFO_PAD, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -2570,6 +2572,7 @@ enum nl80211_sta_info { * transmitted MSDUs (not counting the first attempt; u64) * @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted * MSDUs (u64) + * @NL80211_TID_STATS_PAD: attribute used for padding for 64-bit alignment * @NUM_NL80211_TID_STATS: number of attributes here * @NL80211_TID_STATS_MAX: highest numbered attribute here */ @@ -2579,6 +2582,7 @@ enum nl80211_tid_stats { NL80211_TID_STATS_TX_MSDU, NL80211_TID_STATS_TX_MSDU_RETRIES, NL80211_TID_STATS_TX_MSDU_FAILED, + NL80211_TID_STATS_PAD, /* keep last */ NUM_NL80211_TID_STATS, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5b0d2c8c2165..9bc84a2ddd34 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3755,11 +3755,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, goto nla_put_failure; #define PUT_SINFO(attr, memb, type) do { \ + BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \ if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \ nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \ sinfo->memb)) \ goto nla_put_failure; \ } while (0) +#define PUT_SINFO_U64(attr, memb) do { \ + if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \ + nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \ + sinfo->memb, NL80211_STA_INFO_PAD)) \ + goto nla_put_failure; \ + } while (0) PUT_SINFO(CONNECTED_TIME, connected_time, u32); PUT_SINFO(INACTIVE_TIME, inactive_time, u32); @@ -3776,12 +3783,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, (u32)sinfo->tx_bytes)) goto nla_put_failure; - PUT_SINFO(RX_BYTES64, rx_bytes, u64); - PUT_SINFO(TX_BYTES64, tx_bytes, u64); + PUT_SINFO_U64(RX_BYTES64, rx_bytes); + PUT_SINFO_U64(TX_BYTES64, tx_bytes); PUT_SINFO(LLID, llid, u16); PUT_SINFO(PLID, plid, u16); PUT_SINFO(PLINK_STATE, plink_state, u8); - PUT_SINFO(RX_DURATION, rx_duration, u64); + PUT_SINFO_U64(RX_DURATION, rx_duration); switch (rdev->wiphy.signal_type) { case CFG80211_SIGNAL_TYPE_MBM: @@ -3849,12 +3856,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, &sinfo->sta_flags)) goto nla_put_failure; - PUT_SINFO(T_OFFSET, t_offset, u64); - PUT_SINFO(RX_DROP_MISC, rx_dropped_misc, u64); - PUT_SINFO(BEACON_RX, rx_beacon, u64); + PUT_SINFO_U64(T_OFFSET, t_offset); + PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc); + PUT_SINFO_U64(BEACON_RX, rx_beacon); PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8); #undef PUT_SINFO +#undef PUT_SINFO_U64 if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) { struct nlattr *tidsattr; @@ -3877,19 +3885,19 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, if (!tidattr) goto nla_put_failure; -#define PUT_TIDVAL(attr, memb, type) do { \ +#define PUT_TIDVAL_U64(attr, memb) do { \ if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \ - nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr, \ - tidstats->memb)) \ + nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \ + tidstats->memb, NL80211_TID_STATS_PAD)) \ goto nla_put_failure; \ } while (0) - PUT_TIDVAL(RX_MSDU, rx_msdu, u64); - PUT_TIDVAL(TX_MSDU, tx_msdu, u64); - PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64); - PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64); + PUT_TIDVAL_U64(RX_MSDU, rx_msdu); + PUT_TIDVAL_U64(TX_MSDU, tx_msdu); + PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries); + PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed); -#undef PUT_TIDVAL +#undef PUT_TIDVAL_U64 nla_nest_end(msg, tidattr); } -- GitLab From 282bf1fe6dca4b768d6bedc14aea1b82c36241c1 Mon Sep 17 00:00:00 2001 From: Trent Lloyd Date: Thu, 9 Jul 2015 13:38:50 +0800 Subject: [PATCH 4751/9938] HID: usbhid: quirks for Corsair RGB keyboard & mice (K70R, K95RGB, M65RGB, K70RGB, K65RGB) These devices feature multiple interfaces/endpoints: a legacy BIOS/boot interface (endpoint 0x81), as well as 2 corsair-specific keyboard interfaces (endpoint 0x82, 0x83 IN/0x03 OUT) and an RGB LED control interface (endpoint 0x84 IN/0x04 OUT) Because the extra 3 interfaces are not of subclass USB_INTERFACE_SUBCLASS_BOOT, HID_QUIRK_NOGET is not automatically set on them and a 10s timeout per-endpoint (30s per device) occurs initialising reports on boot. We configure HID_QUIRK_NO_INIT_REPORTS for these devices. Additionally the left-side G1-G18 macro keys on the K95RGB generate output on the un-opened 0x82/0x83 endpoints which causes the keyboard to stop responding waiting for this event to be collected. We enable HID_QUIRK_ALWAYS_POLL to prevent this situation from occurring. Signed-off-by: Trent Lloyd Tested-by: SUGNIAUX Wilfried Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 7 +++++++ drivers/hid/usbhid/hid-quirks.c | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5c0e43ed5c53..fa5b1287c0ae 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -258,6 +258,13 @@ #define USB_VENDOR_ID_CORSAIR 0x1b1c #define USB_DEVICE_ID_CORSAIR_K90 0x1b02 +#define USB_VENDOR_ID_CORSAIR 0x1b1c +#define USB_DEVICE_ID_CORSAIR_K70R 0x1b09 +#define USB_DEVICE_ID_CORSAIR_K95RGB 0x1b11 +#define USB_DEVICE_ID_CORSAIR_M65RGB 0x1b12 +#define USB_DEVICE_ID_CORSAIR_K70RGB 0x1b13 +#define USB_DEVICE_ID_CORSAIR_K65RGB 0x1b17 + #define USB_VENDOR_ID_CREATIVELABS 0x041e #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index ed2f68edc8f1..0ffcaf9cbe81 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -71,6 +71,11 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL }, -- GitLab From de0336b30de1b3e3ad6b76b5ccf0b4920d328313 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 27 Apr 2016 12:21:21 +0200 Subject: [PATCH 4752/9938] EDAC, amd64_edac: Issue driver banner only on success ... and don't mislead users into thinking that the driver has loaded successfully. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index d87a47547ba5..651d96c93f22 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3006,8 +3006,6 @@ static int __init amd64_edac_init(void) { int err = -ENODEV; - printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION); - opstate_init(); if (amd_cache_northbridges() < 0) @@ -3036,6 +3034,8 @@ static int __init amd64_edac_init(void) amd64_err("%s on 32-bit is unsupported. USE AT YOUR OWN RISK!\n", EDAC_MOD_STR); #endif + printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION); + return 0; err_no_instances: -- GitLab From 6fc9ebbdeb75197df780c52f5ebcc3eeffb9cd91 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 14 Apr 2016 14:13:35 -0500 Subject: [PATCH 4753/9938] ARM: davinci: Move clock init after ioremap. Some clocks (such as the USB PHY clocks in DA8xx) will need to use iomem. The davinci_common_init() function must be called before the ioremap, so the clock init is now split out as separate function. Signed-off-by: David Lechner Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/clock.c | 2 +- arch/arm/mach-davinci/common.c | 6 ------ arch/arm/mach-davinci/da830.c | 2 ++ arch/arm/mach-davinci/da850.c | 2 ++ arch/arm/mach-davinci/dm355.c | 1 + arch/arm/mach-davinci/dm365.c | 1 + arch/arm/mach-davinci/dm644x.c | 1 + arch/arm/mach-davinci/dm646x.c | 1 + 8 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 34b4f9fda35d..df42c93a93d6 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -577,7 +577,7 @@ EXPORT_SYMBOL(davinci_set_pllrate); * than that used by default in .c file. The reference clock rate * should be updated early in the boot process; ideally soon after the * clock tree has been initialized once with the default reference clock - * rate (davinci_common_init()). + * rate (davinci_clk_init()). * * Returns 0 on success, error otherwise. */ diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c index f55ef2ef2f92..6bc8c22b8ace 100644 --- a/arch/arm/mach-davinci/common.c +++ b/arch/arm/mach-davinci/common.c @@ -103,12 +103,6 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info) if (ret < 0) goto err; - if (davinci_soc_info.cpu_clks) { - ret = davinci_clk_init(davinci_soc_info.cpu_clks); - - if (ret != 0) - goto err; - } return; diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 7187e7fc2822..426fd7477357 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1214,4 +1214,6 @@ void __init da830_init(void) da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K); WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"); + + davinci_clk_init(davinci_soc_info_da830.cpu_clks); } diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 97d8779a9a65..1f85bbca2e55 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1346,4 +1346,6 @@ void __init da850_init(void) v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG)); v &= ~CFGCHIP3_PLL1_MASTER_LOCK; __raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG)); + + davinci_clk_init(davinci_soc_info_da850.cpu_clks); } diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index a0ecf499c2f2..5a19cca7ed6a 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -1052,6 +1052,7 @@ void __init dm355_init(void) { davinci_common_init(&davinci_soc_info_dm355); davinci_map_sysmod(); + davinci_clk_init(davinci_soc_info_dm355.cpu_clks); } int __init dm355_init_video(struct vpfe_config *vpfe_cfg, diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 384d3674dd9b..8aa004b02fe9 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1176,6 +1176,7 @@ void __init dm365_init(void) { davinci_common_init(&davinci_soc_info_dm365); davinci_map_sysmod(); + davinci_clk_init(davinci_soc_info_dm365.cpu_clks); } static struct resource dm365_vpss_resources[] = { diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index b4b3a8b9ca20..0afa279ec460 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -932,6 +932,7 @@ void __init dm644x_init(void) { davinci_common_init(&davinci_soc_info_dm644x); davinci_map_sysmod(); + davinci_clk_init(davinci_soc_info_dm644x.cpu_clks); } int __init dm644x_init_video(struct vpfe_config *vpfe_cfg, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index a43db0f5fbaa..da21353cac45 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -956,6 +956,7 @@ void __init dm646x_init(void) { davinci_common_init(&davinci_soc_info_dm646x); davinci_map_sysmod(); + davinci_clk_init(davinci_soc_info_dm646x.cpu_clks); } static int __init dm646x_init_devices(void) -- GitLab From 3f2a09d57bb12ca55f92209b3ef0c0684cdb20b0 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 14 Apr 2016 14:13:36 -0500 Subject: [PATCH 4754/9938] ARM: davinci: da850: use clk->set_parent for async3 The da850 family of processors has an async3 clock domain that can be muxed to either pll0_sysclk2 or pll1_sysclk2. Now that the davinci clocks have a set_parent callback, we can use this to control the async3 mux instead of a stand-alone function. This adds a new async3_clk and sets the appropriate child clocks. The default is use to pll1_sysclk2 since it is not affected by processor frequency scaling. Signed-off-by: David Lechner [nsekhar@ti.com: drop unnecessary comment] Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/da850.c | 81 ++++++++++++++--------------------- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 1f85bbca2e55..239886299968 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -34,9 +34,6 @@ #include "clock.h" #include "mux.h" -/* SoC specific clock flags */ -#define DA850_CLK_ASYNC3 BIT(16) - #define DA850_PLL1_BASE 0x01e1a000 #define DA850_TIMER64P2_BASE 0x01f0c000 #define DA850_TIMER64P3_BASE 0x01f0d000 @@ -161,6 +158,32 @@ static struct clk pll1_sysclk3 = { .div_reg = PLLDIV3, }; +static int da850_async3_set_parent(struct clk *clk, struct clk *parent) +{ + u32 val; + + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG)); + + if (parent == &pll0_sysclk2) { + val &= ~CFGCHIP3_ASYNC3_CLKSRC; + } else if (parent == &pll1_sysclk2) { + val |= CFGCHIP3_ASYNC3_CLKSRC; + } else { + pr_err("Bad parent on async3 clock mux\n"); + return -EINVAL; + } + + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG)); + + return 0; +} + +static struct clk async3_clk = { + .name = "async3", + .parent = &pll1_sysclk2, + .set_parent = da850_async3_set_parent, +}; + static struct clk i2c0_clk = { .name = "i2c0", .parent = &pll0_aux_clk, @@ -234,18 +257,16 @@ static struct clk uart0_clk = { static struct clk uart1_clk = { .name = "uart1", - .parent = &pll0_sysclk2, + .parent = &async3_clk, .lpsc = DA8XX_LPSC1_UART1, .gpsc = 1, - .flags = DA850_CLK_ASYNC3, }; static struct clk uart2_clk = { .name = "uart2", - .parent = &pll0_sysclk2, + .parent = &async3_clk, .lpsc = DA8XX_LPSC1_UART2, .gpsc = 1, - .flags = DA850_CLK_ASYNC3, }; static struct clk aintc_clk = { @@ -300,10 +321,9 @@ static struct clk emac_clk = { static struct clk mcasp_clk = { .name = "mcasp", - .parent = &pll0_sysclk2, + .parent = &async3_clk, .lpsc = DA8XX_LPSC1_McASP0, .gpsc = 1, - .flags = DA850_CLK_ASYNC3, }; static struct clk lcdc_clk = { @@ -355,10 +375,9 @@ static struct clk spi0_clk = { static struct clk spi1_clk = { .name = "spi1", - .parent = &pll0_sysclk2, + .parent = &async3_clk, .lpsc = DA8XX_LPSC1_SPI1, .gpsc = 1, - .flags = DA850_CLK_ASYNC3, }; static struct clk vpif_clk = { @@ -386,10 +405,9 @@ static struct clk dsp_clk = { static struct clk ehrpwm_clk = { .name = "ehrpwm", - .parent = &pll0_sysclk2, + .parent = &async3_clk, .lpsc = DA8XX_LPSC1_PWM, .gpsc = 1, - .flags = DA850_CLK_ASYNC3, }; #define DA8XX_EHRPWM_TBCLKSYNC BIT(12) @@ -421,10 +439,9 @@ static struct clk ehrpwm_tbclk = { static struct clk ecap_clk = { .name = "ecap", - .parent = &pll0_sysclk2, + .parent = &async3_clk, .lpsc = DA8XX_LPSC1_ECAP, .gpsc = 1, - .flags = DA850_CLK_ASYNC3, }; static struct clk_lookup da850_clks[] = { @@ -442,6 +459,7 @@ static struct clk_lookup da850_clks[] = { CLK(NULL, "pll1_aux", &pll1_aux_clk), CLK(NULL, "pll1_sysclk2", &pll1_sysclk2), CLK(NULL, "pll1_sysclk3", &pll1_sysclk3), + CLK(NULL, "async3", &async3_clk), CLK("i2c_davinci.1", NULL, &i2c0_clk), CLK(NULL, "timer0", &timerp64_0_clk), CLK("davinci-wdt", NULL, &timerp64_1_clk), @@ -909,30 +927,6 @@ static struct davinci_timer_info da850_timer_info = { .clocksource_id = T0_TOP, }; -static void da850_set_async3_src(int pllnum) -{ - struct clk *clk, *newparent = pllnum ? &pll1_sysclk2 : &pll0_sysclk2; - struct clk_lookup *c; - unsigned int v; - int ret; - - for (c = da850_clks; c->clk; c++) { - clk = c->clk; - if (clk->flags & DA850_CLK_ASYNC3) { - ret = clk_set_parent(clk, newparent); - WARN(ret, "DA850: unable to re-parent clock %s", - clk->name); - } - } - - v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG)); - if (pllnum) - v |= CFGCHIP3_ASYNC3_CLKSRC; - else - v &= ~CFGCHIP3_ASYNC3_CLKSRC; - __raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG)); -} - #ifdef CONFIG_CPU_FREQ /* * Notes: @@ -1328,15 +1322,6 @@ void __init da850_init(void) if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module")) return; - /* - * Move the clock source of Async3 domain to PLL1 SYSCLK2. - * This helps keeping the peripherals on this domain insulated - * from CPU frequency changes caused by DVFS. The firmware sets - * both PLL0 and PLL1 to the same frequency so, there should not - * be any noticeable change even in non-DVFS use cases. - */ - da850_set_async3_src(1); - /* Unlock writing to PLL0 registers */ v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG)); v &= ~CFGCHIP0_PLL_MASTER_LOCK; -- GitLab From 313a98faf1e33945c59872da5a0425260ffb39b5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:40:04 -0700 Subject: [PATCH 4755/9938] ARM: mv78xx0: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Cc: Andrew Lunn Cc: Jason Cooper Signed-off-by: Stephen Boyd Signed-off-by: Gregory CLEMENT --- arch/arm/mach-mv78xx0/common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index 99cc93900a24..45a05207b418 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -168,8 +168,7 @@ static struct clk *tclk; static void __init clk_init(void) { - tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT, - get_tclk()); + tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, get_tclk()); orion_clkdev_init(tclk); } -- GitLab From cc1e18967c540c9a3ffc30ea63e500ecaa61812a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:38:50 -0700 Subject: [PATCH 4756/9938] ARM: orion5x: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Cc: Andrew Lunn Signed-off-by: Stephen Boyd Signed-off-by: Gregory CLEMENT --- arch/arm/mach-orion5x/common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 70c3366c8d03..058994e99570 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -66,8 +66,7 @@ static struct clk *tclk; void __init clk_init(void) { - tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT, - orion5x_tclk); + tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, orion5x_tclk); orion_clkdev_init(tclk); } -- GitLab From 3a1a4559624a51e1f4ed8954d546ccc7367bb8d4 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:45:48 -0700 Subject: [PATCH 4757/9938] ARM: dove: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Cc: Andrew Lunn Signed-off-by: Stephen Boyd Signed-off-by: Gregory CLEMENT --- arch/arm/mach-dove/common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index 0cdaa3851d2e..0d420a2bfe3e 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -88,8 +88,7 @@ static void __init dove_clk_init(void) struct clk *nand, *camera, *i2s0, *i2s1, *crypto, *ac97, *pdma; struct clk *xor0, *xor1, *ge, *gephy; - tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT, - dove_tclk); + tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, dove_tclk); usb0 = dove_register_gate("usb0", "tclk", CLOCK_GATING_BIT_USB0); usb1 = dove_register_gate("usb1", "tclk", CLOCK_GATING_BIT_USB1); -- GitLab From 8527f68849caadd0b7c560c613f2e18c9e1f8d47 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 21 Apr 2016 14:09:42 -0700 Subject: [PATCH 4758/9938] wcn36xx: Set SMD timeout to 10 seconds After booting the wireless subsystem and uploading the NV blob to the WCNSS_CTRL service the remote continues to do things and will not start servicing wlan-requests for another 2-5 seconds (measured). The downstream code does not have any special handling for this case, but has a timeout of 10 seconds for the communication layer. By extending the wcn36xx timeout to match this we follows the same flow for the boot procedure and can successfully configure WiFi as wlan0 is registered. Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index d74d781f4c8d..d93e3fd73831 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -24,7 +24,7 @@ #define WCN36XX_HAL_BUF_SIZE 4096 -#define HAL_MSG_TIMEOUT 500 +#define HAL_MSG_TIMEOUT 10000 #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 /* The PNO version info be contained in the rsp msg */ -- GitLab From 2b1b2f0e764d349f7455aaca9c17d4b0c2f1ee1b Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 15:44:30 +0200 Subject: [PATCH 4759/9938] ARM: at91/defconfig: add the HDMA controller to sama5_defconfig Selection of the HDMAC option is now needed to allow some sama5 devices to have the DMA driver compiled and available. Signed-off-by: Nicolas Ferre Acked-by: Alexandre Belloni --- arch/arm/configs/sama5_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index afbda413d61a..e002b3bba5b4 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -183,6 +183,7 @@ CONFIG_LEDS_TRIGGER_GPIO=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AT91RM9200=y CONFIG_DMADEVICES=y +CONFIG_AT_HDMAC=y CONFIG_AT_XDMAC=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_IIO=y -- GitLab From a331acbd553f37c15eba9be342766b01ae527be2 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 16:20:07 +0200 Subject: [PATCH 4760/9938] ARM: at91/defconfig: add HLCDC driver to sama5_defconfig Add the LCD DRM driver with all its dependencies: - the MFD driver - the backlight PWM - the simple panel driver Remove the CONFIG_FB as it is not needed on any sama5 device. Signed-off-by: Nicolas Ferre Acked-by: Alexandre Belloni --- arch/arm/configs/sama5_defconfig | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index e002b3bba5b4..f5a3966f6793 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -133,6 +133,7 @@ CONFIG_WATCHDOG=y CONFIG_AT91SAM9X_WATCHDOG=y CONFIG_SAMA5D4_WATCHDOG=y CONFIG_MFD_ATMEL_FLEXCOM=y +CONFIG_MFD_ATMEL_HLCDC=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_ACT8865=y @@ -142,11 +143,14 @@ CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_SOC_CAMERA=y CONFIG_VIDEO_ATMEL_ISI=y CONFIG_SOC_CAMERA_OV2640=y -CONFIG_FB=y +CONFIG_DRM=y +CONFIG_DRM_ATMEL_HLCDC=y +CONFIG_DRM_PANEL_SIMPLE=y CONFIG_BACKLIGHT_LCD_SUPPORT=y -# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_LCD_CLASS_DEVICE=y CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_PWM=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_SOUND=y CONFIG_SND=y @@ -191,6 +195,7 @@ CONFIG_AT91_ADC=y CONFIG_AT91_SAMA5D2_ADC=y CONFIG_PWM=y CONFIG_PWM_ATMEL=y +CONFIG_PWM_ATMEL_HLCDC_PWM=y CONFIG_PWM_ATMEL_TCB=y CONFIG_EXT4_FS=y CONFIG_FANOTIFY=y -- GitLab From 35f110ec54e7683d7850f1897a00a7e5cf4190b0 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 17:36:31 +0200 Subject: [PATCH 4761/9938] ARM: at91/defconfig: add PDMIC driver to sama5_defconfig Add Pulse Density Modulation Interface Controller (PDMIC) driver compilation for sama5 default configuration. Is used by sama5d2 SoC for instance. Signed-off-by: Nicolas Ferre Acked-by: Alexandre Belloni --- arch/arm/configs/sama5_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index f5a3966f6793..32a082888adf 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -158,6 +158,7 @@ CONFIG_SND_SOC=y CONFIG_SND_ATMEL_SOC=y CONFIG_SND_ATMEL_SOC_WM8904=y # CONFIG_HID_GENERIC is not set +CONFIG_SND_ATMEL_SOC_PDMIC=y CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_EHCI_HCD=y -- GitLab From a95c630724e368e97e7e38b84f4036f9eed49c08 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 30 Mar 2016 16:19:37 +0200 Subject: [PATCH 4762/9938] ARM: multi_v7_defconfig: add HLCDC drivers as modules Add the HLCDC drivers to multi_v7_defconfig. Signed-off-by: Boris Brezillon Signed-off-by: Nicolas Ferre --- arch/arm/configs/multi_v7_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 28234906a064..af1e0c91a6f2 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -441,6 +441,7 @@ CONFIG_DIGICOLOR_WATCHDOG=y CONFIG_MFD_AS3711=y CONFIG_MFD_AS3722=y CONFIG_MFD_ATMEL_FLEXCOM=y +CONFIG_MFD_ATMEL_HLCDC=m CONFIG_MFD_BCM590XX=y CONFIG_MFD_AXP20X=y CONFIG_MFD_AXP20X_I2C=m @@ -533,6 +534,7 @@ CONFIG_DRM_EXYNOS_FIMD=y CONFIG_DRM_EXYNOS_HDMI=y CONFIG_DRM_ROCKCHIP=m CONFIG_ROCKCHIP_DW_HDMI=m +CONFIG_DRM_ATMEL_HLCDC=m CONFIG_DRM_RCAR_DU=m CONFIG_DRM_RCAR_HDMI=y CONFIG_DRM_RCAR_LVDS=y @@ -775,6 +777,7 @@ CONFIG_AK8975=y CONFIG_RASPBERRYPI_POWER=y CONFIG_PWM=y CONFIG_PWM_ATMEL=m +CONFIG_PWM_ATMEL_HLCDC_PWM=m CONFIG_PWM_ATMEL_TCB=m CONFIG_PWM_FSL_FTM=m CONFIG_PWM_RENESAS_TPU=y -- GitLab From 54b31de0be58d9a9704f91930af0e7a15866de99 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 17:59:18 +0200 Subject: [PATCH 4763/9938] ARM: multi_v7_defconfig: add Atmel watchdog timers Add both Atmel watchdog timers to the multi_v7_defconfig. They are added as part of the kernel because it's a core piece of the system. Signed-off-by: Nicolas Ferre --- arch/arm/configs/multi_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index af1e0c91a6f2..d72ee27cecae 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -430,6 +430,8 @@ CONFIG_WATCHDOG=y CONFIG_DA9063_WATCHDOG=m CONFIG_XILINX_WATCHDOG=y CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_AT91SAM9X_WATCHDOG=y +CONFIG_SAMA5D4_WATCHDOG=y CONFIG_ORION_WATCHDOG=y CONFIG_ST_LPC_WATCHDOG=y CONFIG_SUNXI_WATCHDOG=y -- GitLab From 955c1129ae8c0ff8b97d16fdd4787b1d820b837a Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 18:00:24 +0200 Subject: [PATCH 4764/9938] ARM: multi_v7_defconfig: add Atmel ISI (Image Sensor Interface) driver Add the Atmel Image Sensor Interface (ISI) VIDEO driver as a module. Signed-off-by: Nicolas Ferre --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index d72ee27cecae..901eaf55c5a7 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -517,6 +517,7 @@ CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_SOC_CAMERA=m CONFIG_SOC_CAMERA_PLATFORM=m CONFIG_VIDEO_RCAR_VIN=m +CONFIG_VIDEO_ATMEL_ISI=m CONFIG_V4L_MEM2MEM_DRIVERS=y CONFIG_VIDEO_RENESAS_JPU=m CONFIG_VIDEO_RENESAS_VSP1=m -- GitLab From 49518015fc53a33df0baa432d7fcf7ece33e9a04 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 18:02:22 +0200 Subject: [PATCH 4765/9938] ARM: multi_v7_defconfig: add the Atmel Audio microphone interface PDMIC Add the Atmel Pulse Density Modulation Interface Controller (PDMIC) driver as a module. It's used by sama5d2 SoC for instance. Signed-off-by: Nicolas Ferre --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 901eaf55c5a7..6a62ebbcae28 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -569,6 +569,7 @@ CONFIG_SND_USB_AUDIO=m CONFIG_SND_SOC=m CONFIG_SND_ATMEL_SOC=m CONFIG_SND_ATMEL_SOC_WM8904=m +CONFIG_SND_ATMEL_SOC_PDMIC=m CONFIG_SND_SOC_FSL_SAI=m CONFIG_SND_SOC_ROCKCHIP=m CONFIG_SND_SOC_ROCKCHIP_SPDIF=m -- GitLab From ed87957b18f238516e578e5dbd44a5db11300831 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 18:04:36 +0200 Subject: [PATCH 4766/9938] ARM: multi_v7_defconfig: add the Atmel sama5d2-compatible ADC driver Add the new sama5d2-compatible ADC driver as a module. Signed-off-by: Nicolas Ferre --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6a62ebbcae28..1aed38fd4337 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -773,6 +773,7 @@ CONFIG_EXTCON=y CONFIG_TI_AEMIF=y CONFIG_IIO=y CONFIG_AT91_ADC=m +CONFIG_AT91_SAMA5D2_ADC=m CONFIG_BERLIN2_ADC=m CONFIG_EXYNOS_ADC=m CONFIG_VF610_ADC=m -- GitLab From 20ce85130df56ceb2cfaa11743e5a0fe0265ebde Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 13:32:47 +0200 Subject: [PATCH 4767/9938] ARM: dts: at91: sama5d4: add watchdog interrupt property The "interrupts" property is missing from the watchdog node. Add it with highest priority value of 7. Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/sama5d4.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index db1151c18466..058e56e431cd 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -1302,6 +1302,7 @@ watchdog@fc068640 { compatible = "atmel,sama5d4-wdt"; reg = <0xfc068640 0x10>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&clk32k>; status = "disabled"; }; -- GitLab From e4b9a21b25f0ca087cbe00d2ee183a5a28f12ea3 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 14:19:25 +0200 Subject: [PATCH 4768/9938] ARM: dts: at91: sama5d2: add shutdown controller node Add the SAMA5D2-Compatible Shutdown Controller node to sama5d2.dtsi and the use of it in the sama5d2 Xplained board dts file. Enable the RTC wakeup event and the "wake up" button support through the input "0" that is present on the board. Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-sama5d2_xplained.dts | 9 +++++++++ arch/arm/boot/dts/sama5d2.dtsi | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index 21c780fab761..eb4f1ac96271 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -234,6 +234,15 @@ }; }; + shdwc@f8048010 { + atmel,shdwc-debouncer = <976>; + + input@0 { + reg = <0>; + atmel,wakeup-type = "low"; + }; + }; + watchdog@f8048040 { status = "okay"; }; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 12cc1d34097d..43015c2ad395 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -1030,6 +1030,15 @@ clocks = <&clk32k>; }; + shdwc@f8048010 { + compatible = "atmel,sama5d2-shdwc"; + reg = <0xf8048010 0x10>; + clocks = <&clk32k>; + #address-cells = <1>; + #size-cells = <0>; + atmel,wakeup-rtc-timer; + }; + pit: timer@f8048030 { compatible = "atmel,at91sam9260-pit"; reg = <0xf8048030 0x10>; -- GitLab From 517550075c31917dc729d7cec0b4a0ca65294f14 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 15:08:47 +0200 Subject: [PATCH 4769/9938] ARM: dts: at91: sama5d2: add slow clock to watchdog node As the watchdog timer needs the slow clock, add it to the currently defined wdt node. Reported-by: Alexandre Belloni Signed-off-by: Nicolas Ferre Acked-by: Alexandre Belloni --- arch/arm/boot/dts/sama5d2.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 43015c2ad395..84eed47ffb0a 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -1050,6 +1050,7 @@ compatible = "atmel,sama5d4-wdt"; reg = <0xf8048040 0x10>; interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&clk32k>; status = "disabled"; }; -- GitLab From 88677db54dba68ce19952d5bcdf0fda43094b31f Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Apr 2016 12:11:28 +0200 Subject: [PATCH 4770/9938] ARM: dts: at91: VInCo: fix phy reset gpio flag Fix gpio active flag for the phy reset-gpios property. The line is active low instead of active high. Actually, this flags was never used by the macb driver. Reported-by: Sergei Shtylyov Cc: Andrew Lunn Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-vinco.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/at91-vinco.dts b/arch/arm/boot/dts/at91-vinco.dts index 79aec55e1ebc..6a366ee952a8 100644 --- a/arch/arm/boot/dts/at91-vinco.dts +++ b/arch/arm/boot/dts/at91-vinco.dts @@ -118,7 +118,7 @@ ethernet-phy@1 { reg = <0x1>; - reset-gpios = <&pioE 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&pioE 8 GPIO_ACTIVE_LOW>; interrupt-parent = <&pioB>; interrupts = <15 IRQ_TYPE_EDGE_FALLING>; }; @@ -162,7 +162,7 @@ reg = <0x1>; interrupt-parent = <&pioB>; interrupts = <31 IRQ_TYPE_EDGE_FALLING>; - reset-gpios = <&pioE 6 GPIO_ACTIVE_HIGH>; + reset-gpios = <&pioE 6 GPIO_ACTIVE_LOW>; }; }; -- GitLab From c5dfd78eb79851e278b7973031b9ca363da87a7e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 21 Apr 2016 12:28:50 -0300 Subject: [PATCH 4771/9938] perf core: Allow setting up max frame stack depth via sysctl The default remains 127, which is good for most cases, and not even hit most of the time, but then for some cases, as reported by Brendan, 1024+ deep frames are appearing on the radar for things like groovy, ruby. And in some workloads putting a _lower_ cap on this may make sense. One that is per event still needs to be put in place tho. The new file is: # cat /proc/sys/kernel/perf_event_max_stack 127 Chaging it: # echo 256 > /proc/sys/kernel/perf_event_max_stack # cat /proc/sys/kernel/perf_event_max_stack 256 But as soon as there is some event using callchains we get: # echo 512 > /proc/sys/kernel/perf_event_max_stack -bash: echo: write error: Device or resource busy # Because we only allocate the callchain percpu data structures when there is a user, which allows for changing the max easily, its just a matter of having no callchain users at that point. Reported-and-Tested-by: Brendan Gregg Reviewed-by: Frederic Weisbecker Acked-by: Alexei Starovoitov Acked-by: David Ahern Cc: Adrian Hunter Cc: Alexander Shishkin Cc: He Kuang Cc: Jiri Olsa Cc: Linus Torvalds Cc: Masami Hiramatsu Cc: Milian Wolff Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: Wang Nan Cc: Zefan Li Link: http://lkml.kernel.org/r/20160426002928.GB16708@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- Documentation/sysctl/kernel.txt | 14 ++++++++++++ arch/arm/kernel/perf_callchain.c | 2 +- arch/arm64/kernel/perf_callchain.c | 4 ++-- arch/metag/kernel/perf_callchain.c | 2 +- arch/mips/kernel/perf_event.c | 4 ++-- arch/powerpc/perf/callchain.c | 4 ++-- arch/sparc/kernel/perf_event.c | 6 ++--- arch/x86/events/core.c | 4 ++-- arch/xtensa/kernel/perf_event.c | 4 ++-- include/linux/perf_event.h | 8 +++++-- kernel/bpf/stackmap.c | 8 +++---- kernel/events/callchain.c | 35 ++++++++++++++++++++++++++++-- kernel/sysctl.c | 12 ++++++++++ 13 files changed, 84 insertions(+), 23 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 57653a44b128..260cde08e92e 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -60,6 +60,7 @@ show up in /proc/sys/kernel: - panic_on_warn - perf_cpu_time_max_percent - perf_event_paranoid +- perf_event_max_stack - pid_max - powersave-nap [ PPC only ] - printk @@ -654,6 +655,19 @@ users (without CAP_SYS_ADMIN). The default value is 1. ============================================================== +perf_event_max_stack: + +Controls maximum number of stack frames to copy for (attr.sample_type & +PERF_SAMPLE_CALLCHAIN) configured events, for instance, when using +'perf record -g' or 'perf trace --call-graph fp'. + +This can only be done when no events are in use that have callchains +enabled, otherwise writing to this file will return -EBUSY. + +The default value is 127. + +============================================================== + pid_max: PID allocation wrap value. When the kernel's next PID value diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c index 4e02ae5950ff..27563befa8a2 100644 --- a/arch/arm/kernel/perf_callchain.c +++ b/arch/arm/kernel/perf_callchain.c @@ -75,7 +75,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) tail = (struct frame_tail __user *)regs->ARM_fp - 1; - while ((entry->nr < PERF_MAX_STACK_DEPTH) && + while ((entry->nr < sysctl_perf_event_max_stack) && tail && !((unsigned long)tail & 0x3)) tail = user_backtrace(tail, entry); } diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c index ff4665462a02..32c3c6e70119 100644 --- a/arch/arm64/kernel/perf_callchain.c +++ b/arch/arm64/kernel/perf_callchain.c @@ -122,7 +122,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, tail = (struct frame_tail __user *)regs->regs[29]; - while (entry->nr < PERF_MAX_STACK_DEPTH && + while (entry->nr < sysctl_perf_event_max_stack && tail && !((unsigned long)tail & 0xf)) tail = user_backtrace(tail, entry); } else { @@ -132,7 +132,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, tail = (struct compat_frame_tail __user *)regs->compat_fp - 1; - while ((entry->nr < PERF_MAX_STACK_DEPTH) && + while ((entry->nr < sysctl_perf_event_max_stack) && tail && !((unsigned long)tail & 0x3)) tail = compat_user_backtrace(tail, entry); #endif diff --git a/arch/metag/kernel/perf_callchain.c b/arch/metag/kernel/perf_callchain.c index 315633461a94..252abc12a5a3 100644 --- a/arch/metag/kernel/perf_callchain.c +++ b/arch/metag/kernel/perf_callchain.c @@ -65,7 +65,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) --frame; - while ((entry->nr < PERF_MAX_STACK_DEPTH) && frame) + while ((entry->nr < sysctl_perf_event_max_stack) && frame) frame = user_backtrace(frame, entry); } diff --git a/arch/mips/kernel/perf_event.c b/arch/mips/kernel/perf_event.c index c1cf9c6c3f77..5021c546ad07 100644 --- a/arch/mips/kernel/perf_event.c +++ b/arch/mips/kernel/perf_event.c @@ -35,7 +35,7 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry, addr = *sp++; if (__kernel_text_address(addr)) { perf_callchain_store(entry, addr); - if (entry->nr >= PERF_MAX_STACK_DEPTH) + if (entry->nr >= sysctl_perf_event_max_stack) break; } } @@ -59,7 +59,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, } do { perf_callchain_store(entry, pc); - if (entry->nr >= PERF_MAX_STACK_DEPTH) + if (entry->nr >= sysctl_perf_event_max_stack) break; pc = unwind_stack(current, &sp, pc, &ra); } while (pc); diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index e04a6752b399..22d9015c1acc 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -247,7 +247,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, sp = regs->gpr[1]; perf_callchain_store(entry, next_ip); - while (entry->nr < PERF_MAX_STACK_DEPTH) { + while (entry->nr < sysctl_perf_event_max_stack) { fp = (unsigned long __user *) sp; if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp)) return; @@ -453,7 +453,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, sp = regs->gpr[1]; perf_callchain_store(entry, next_ip); - while (entry->nr < PERF_MAX_STACK_DEPTH) { + while (entry->nr < sysctl_perf_event_max_stack) { fp = (unsigned int __user *) (unsigned long) sp; if (!valid_user_sp(sp, 0) || read_user_stack_32(fp, &next_sp)) return; diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 6596f66ce112..a4b8b5aed21c 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1756,7 +1756,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, } } #endif - } while (entry->nr < PERF_MAX_STACK_DEPTH); + } while (entry->nr < sysctl_perf_event_max_stack); } static inline int @@ -1790,7 +1790,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, pc = sf.callers_pc; ufp = (unsigned long)sf.fp + STACK_BIAS; perf_callchain_store(entry, pc); - } while (entry->nr < PERF_MAX_STACK_DEPTH); + } while (entry->nr < sysctl_perf_event_max_stack); } static void perf_callchain_user_32(struct perf_callchain_entry *entry, @@ -1822,7 +1822,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, ufp = (unsigned long)sf.fp; } perf_callchain_store(entry, pc); - } while (entry->nr < PERF_MAX_STACK_DEPTH); + } while (entry->nr < sysctl_perf_event_max_stack); } void diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 041e442a3e28..41d93d0e972b 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2277,7 +2277,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) fp = compat_ptr(ss_base + regs->bp); pagefault_disable(); - while (entry->nr < PERF_MAX_STACK_DEPTH) { + while (entry->nr < sysctl_perf_event_max_stack) { unsigned long bytes; frame.next_frame = 0; frame.return_address = 0; @@ -2337,7 +2337,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) return; pagefault_disable(); - while (entry->nr < PERF_MAX_STACK_DEPTH) { + while (entry->nr < sysctl_perf_event_max_stack) { unsigned long bytes; frame.next_frame = NULL; frame.return_address = 0; diff --git a/arch/xtensa/kernel/perf_event.c b/arch/xtensa/kernel/perf_event.c index 54f01188c29c..a6b00b3af429 100644 --- a/arch/xtensa/kernel/perf_event.c +++ b/arch/xtensa/kernel/perf_event.c @@ -332,14 +332,14 @@ static int callchain_trace(struct stackframe *frame, void *data) void perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) { - xtensa_backtrace_kernel(regs, PERF_MAX_STACK_DEPTH, + xtensa_backtrace_kernel(regs, sysctl_perf_event_max_stack, callchain_trace, NULL, entry); } void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) { - xtensa_backtrace_user(regs, PERF_MAX_STACK_DEPTH, + xtensa_backtrace_user(regs, sysctl_perf_event_max_stack, callchain_trace, entry); } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 85749ae8cb5f..a090700cccca 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -58,7 +58,7 @@ struct perf_guest_info_callbacks { struct perf_callchain_entry { __u64 nr; - __u64 ip[PERF_MAX_STACK_DEPTH]; + __u64 ip[0]; /* /proc/sys/kernel/perf_event_max_stack */ }; struct perf_raw_record { @@ -993,9 +993,11 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, extern int get_callchain_buffers(void); extern void put_callchain_buffers(void); +extern int sysctl_perf_event_max_stack; + static inline int perf_callchain_store(struct perf_callchain_entry *entry, u64 ip) { - if (entry->nr < PERF_MAX_STACK_DEPTH) { + if (entry->nr < sysctl_perf_event_max_stack) { entry->ip[entry->nr++] = ip; return 0; } else { @@ -1017,6 +1019,8 @@ extern int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +int perf_event_max_stack_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); static inline bool perf_paranoid_tracepoint_raw(void) { diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 499d9e933f8e..f5a19548be12 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -66,7 +66,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr) /* check sanity of attributes */ if (attr->max_entries == 0 || attr->key_size != 4 || value_size < 8 || value_size % 8 || - value_size / 8 > PERF_MAX_STACK_DEPTH) + value_size / 8 > sysctl_perf_event_max_stack) return ERR_PTR(-EINVAL); /* hash table size must be power of 2 */ @@ -124,8 +124,8 @@ static u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) struct perf_callchain_entry *trace; struct stack_map_bucket *bucket, *new_bucket, *old_bucket; u32 max_depth = map->value_size / 8; - /* stack_map_alloc() checks that max_depth <= PERF_MAX_STACK_DEPTH */ - u32 init_nr = PERF_MAX_STACK_DEPTH - max_depth; + /* stack_map_alloc() checks that max_depth <= sysctl_perf_event_max_stack */ + u32 init_nr = sysctl_perf_event_max_stack - max_depth; u32 skip = flags & BPF_F_SKIP_FIELD_MASK; u32 hash, id, trace_nr, trace_len; bool user = flags & BPF_F_USER_STACK; @@ -143,7 +143,7 @@ static u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) return -EFAULT; /* get_perf_callchain() guarantees that trace->nr >= init_nr - * and trace-nr <= PERF_MAX_STACK_DEPTH, so trace_nr <= max_depth + * and trace-nr <= sysctl_perf_event_max_stack, so trace_nr <= max_depth */ trace_nr = trace->nr - init_nr; diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index 343c22f5e867..b9325e7dcba1 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c @@ -18,6 +18,14 @@ struct callchain_cpus_entries { struct perf_callchain_entry *cpu_entries[0]; }; +int sysctl_perf_event_max_stack __read_mostly = PERF_MAX_STACK_DEPTH; + +static inline size_t perf_callchain_entry__sizeof(void) +{ + return (sizeof(struct perf_callchain_entry) + + sizeof(__u64) * sysctl_perf_event_max_stack); +} + static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]); static atomic_t nr_callchain_events; static DEFINE_MUTEX(callchain_mutex); @@ -73,7 +81,7 @@ static int alloc_callchain_buffers(void) if (!entries) return -ENOMEM; - size = sizeof(struct perf_callchain_entry) * PERF_NR_CONTEXTS; + size = perf_callchain_entry__sizeof() * PERF_NR_CONTEXTS; for_each_possible_cpu(cpu) { entries->cpu_entries[cpu] = kmalloc_node(size, GFP_KERNEL, @@ -147,7 +155,8 @@ static struct perf_callchain_entry *get_callchain_entry(int *rctx) cpu = smp_processor_id(); - return &entries->cpu_entries[cpu][*rctx]; + return (((void *)entries->cpu_entries[cpu]) + + (*rctx * perf_callchain_entry__sizeof())); } static void @@ -215,3 +224,25 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, return entry; } + +int perf_event_max_stack_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int new_value = sysctl_perf_event_max_stack, ret; + struct ctl_table new_table = *table; + + new_table.data = &new_value; + ret = proc_dointvec_minmax(&new_table, write, buffer, lenp, ppos); + if (ret || !write) + return ret; + + mutex_lock(&callchain_mutex); + if (atomic_read(&nr_callchain_events)) + ret = -EBUSY; + else + sysctl_perf_event_max_stack = new_value; + + mutex_unlock(&callchain_mutex); + + return ret; +} diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 725587f10667..c8b318663525 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -130,6 +130,9 @@ static int one_thousand = 1000; #ifdef CONFIG_PRINTK static int ten_thousand = 10000; #endif +#ifdef CONFIG_PERF_EVENTS +static int six_hundred_forty_kb = 640 * 1024; +#endif /* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */ static unsigned long dirty_bytes_min = 2 * PAGE_SIZE; @@ -1144,6 +1147,15 @@ static struct ctl_table kern_table[] = { .extra1 = &zero, .extra2 = &one_hundred, }, + { + .procname = "perf_event_max_stack", + .data = NULL, /* filled in by handler */ + .maxlen = sizeof(sysctl_perf_event_max_stack), + .mode = 0644, + .proc_handler = perf_event_max_stack_handler, + .extra1 = &zero, + .extra2 = &six_hundred_forty_kb, + }, #endif #ifdef CONFIG_KMEMCHECK { -- GitLab From 4cb93446c587d56e2a54f4f83113daba2c0b6dee Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 27 Apr 2016 10:16:24 -0300 Subject: [PATCH 4772/9938] perf tools: Set the maximum allowed stack from /proc/sys/kernel/perf_event_max_stack There is an upper limit to what tooling considers a valid callchain, and it was tied to the hardcoded value in the kernel, PERF_MAX_STACK_DEPTH (127), now that this can be tuned via a sysctl, make it read it and use that as the upper limit, falling back to PERF_MAX_STACK_DEPTH for kernels where this sysctl isn't present. Cc: Adrian Hunter Cc: Brendan Gregg Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-yjqsd30nnkogvj5oyx9ghir9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-report.txt | 2 +- tools/perf/Documentation/perf-script.txt | 2 +- tools/perf/Documentation/perf-top.txt | 2 +- tools/perf/Documentation/perf-trace.txt | 2 +- tools/perf/builtin-report.c | 4 ++-- tools/perf/builtin-script.c | 4 +++- tools/perf/builtin-top.c | 4 ++-- tools/perf/builtin-trace.c | 4 ++-- tools/perf/perf.c | 5 +++++ tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_filter.c | 2 +- tools/perf/tests/hists_output.c | 2 +- tools/perf/util/machine.c | 6 +++--- tools/perf/util/scripting-engines/trace-event-perl.c | 2 +- tools/perf/util/util.c | 2 ++ tools/perf/util/util.h | 1 + 16 files changed, 28 insertions(+), 18 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 496d42cdf02b..ebaf849e30ef 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -248,7 +248,7 @@ OPTIONS Note that when using the --itrace option the synthesized callchain size will override this value if the synthesized callchain size is bigger. - Default: 127 + Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. -G:: --inverted:: diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 4fc44c75263f..a856a1095893 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -267,7 +267,7 @@ include::itrace.txt[] Note that when using the --itrace option the synthesized callchain size will override this value if the synthesized callchain size is bigger. - Default: 127 + Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. --ns:: Use 9 decimal places when displaying time (i.e. show the nanoseconds) diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 19f046f027cd..91d638df3a6b 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt @@ -177,7 +177,7 @@ Default is to monitor all CPUS. between information loss and faster processing especially for workloads that can have a very long callchain stack. - Default: 127 + Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. --ignore-callees=:: Ignore callees of the function(s) matching the given regex. diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index c075c002eaa4..6afe20121bc0 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -143,7 +143,7 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. Implies '--call-graph dwarf' when --call-graph not present on the command line, on systems where DWARF unwinding was built in. - Default: 127 + Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. --min-stack:: Set the stack depth limit when parsing the callchain, anything diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1d5be0bd426f..8d9b88af901d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) .ordered_events = true, .ordering_requires_timestamps = true, }, - .max_stack = PERF_MAX_STACK_DEPTH, + .max_stack = sysctl_perf_event_max_stack, .pretty_printing_style = "normal", .socket_filter = -1, }; @@ -744,7 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) OPT_INTEGER(0, "max-stack", &report.max_stack, "Set the maximum stack depth when parsing the callchain, " "anything beyond the specified depth will be ignored. " - "Default: " __stringify(PERF_MAX_STACK_DEPTH)), + "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, "alias for inverted call graph"), OPT_CALLBACK(0, "ignore-callees", NULL, "regex", diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index f43b0c6f88f4..efca81679bb3 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2031,7 +2031,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) OPT_UINTEGER(0, "max-stack", &scripting_max_stack, "Set the maximum stack depth when parsing the callchain, " "anything beyond the specified depth will be ignored. " - "Default: " __stringify(PERF_MAX_STACK_DEPTH)), + "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), OPT_BOOLEAN('I', "show-info", &show_full_info, "display extended information from perf.data file"), OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, @@ -2067,6 +2067,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) NULL }; + scripting_max_stack = sysctl_perf_event_max_stack; + setup_scripting(); argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c130a11d3a0d..da18517b1d40 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1103,7 +1103,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) }, .proc_map_timeout = 500, }, - .max_stack = PERF_MAX_STACK_DEPTH, + .max_stack = sysctl_perf_event_max_stack, .sym_pcnt_filter = 5, }; struct record_opts *opts = &top.record_opts; @@ -1171,7 +1171,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) "Accumulate callchains of children and show total overhead as well"), OPT_INTEGER(0, "max-stack", &top.max_stack, "Set the maximum stack depth when parsing the callchain. " - "Default: " __stringify(PERF_MAX_STACK_DEPTH)), + "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), OPT_CALLBACK(0, "ignore-callees", NULL, "regex", "ignore callees of these functions in call graphs", report_parse_ignore_callees_opt), diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 48b00f042599..f4f3389c92c7 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3106,7 +3106,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) OPT_UINTEGER(0, "max-stack", &trace.max_stack, "Set the maximum stack depth when parsing the callchain, " "anything beyond the specified depth will be ignored. " - "Default: " __stringify(PERF_MAX_STACK_DEPTH)), + "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, "per thread proc mmap processing timeout in ms"), OPT_END() @@ -3150,7 +3150,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) mmap_pages_user_set = false; if (trace.max_stack == UINT_MAX) { - trace.max_stack = PERF_MAX_STACK_DEPTH; + trace.max_stack = sysctl_perf_event_max_stack; max_stack_user_set = false; } diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 7b2df2b46525..83ffe7cd7330 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -17,6 +17,7 @@ #include #include "util/bpf-loader.h" #include "util/debug.h" +#include #include #include #include @@ -533,6 +534,7 @@ int main(int argc, const char **argv) { const char *cmd; char sbuf[STRERR_BUFSIZE]; + int value; /* libsubcmd init */ exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT); @@ -542,6 +544,9 @@ int main(int argc, const char **argv) page_size = sysconf(_SC_PAGE_SIZE); cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) + sysctl_perf_event_max_stack = value; + cmd = extract_argv0_path(argv[0]); if (!cmd) cmd = "perf-help"; diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index ed5aa9eaeb6c..4a2bbff9b1ee 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -101,7 +101,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) if (machine__resolve(machine, &al, &sample) < 0) goto out; - if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, + if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack, NULL) < 0) { addr_location__put(&al); goto out; diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index b825d24f8186..e846f8c42013 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -81,7 +81,7 @@ static int add_hist_entries(struct perf_evlist *evlist, al.socket = fake_samples[i].socket; if (hist_entry_iter__add(&iter, &al, - PERF_MAX_STACK_DEPTH, NULL) < 0) { + sysctl_perf_event_max_stack, NULL) < 0) { addr_location__put(&al); goto out; } diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index d3556fbe8c5c..7cd8738e842f 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -67,7 +67,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) if (machine__resolve(machine, &al, &sample) < 0) goto out; - if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, + if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack, NULL) < 0) { addr_location__put(&al); goto out; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 656c1d7ee7d4..2cb95bbf9ea6 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1764,7 +1764,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, */ int mix_chain_nr = i + 1 + lbr_nr + 1; - if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) { + if (mix_chain_nr > (int)sysctl_perf_event_max_stack + PERF_MAX_BRANCH_DEPTH) { pr_warning("corrupted callchain. skipping...\n"); return 0; } @@ -1825,7 +1825,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, * Based on DWARF debug information, some architectures skip * a callchain entry saved by the kernel. */ - if (chain->nr < PERF_MAX_STACK_DEPTH) + if (chain->nr < sysctl_perf_event_max_stack) skip_idx = arch_skip_callchain_idx(thread, chain); /* @@ -1886,7 +1886,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, } check_calls: - if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) { + if (chain->nr > sysctl_perf_event_max_stack && (int)chain->nr > max_stack) { pr_warning("corrupted callchain. skipping...\n"); return 0; } diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index ae1cebc307c5..62c7f6988e0e 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -265,7 +265,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, sample, NULL, NULL, - PERF_MAX_STACK_DEPTH) != 0) { + sysctl_perf_event_max_stack) != 0) { pr_err("Failed to resolve callchain. Skipping\n"); goto exit; } diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 9473d46c00bb..619ba2061b62 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -33,6 +33,8 @@ struct callchain_param callchain_param = { unsigned int page_size; int cacheline_size; +unsigned int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; + bool test_attr__enabled; bool perf_host = true; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 26a924651e7b..88f607af1f47 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -267,6 +267,7 @@ void sighandler_dump_stack(int sig); extern unsigned int page_size; extern int cacheline_size; +extern unsigned int sysctl_perf_event_max_stack; struct parse_tag { char tag; -- GitLab From 80833ff0eea693d8e0c3305a869159a64141fdad Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 27 Apr 2016 09:06:49 +0200 Subject: [PATCH 4773/9938] ASoC: atmel_ssc_dai: read DSP mode A data on rising edges of bclk Signed-off-by: Peter Rosin Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_ssc_dai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 276897033639..1267e1af0fae 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -652,7 +652,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | SSC_BF(RCMR_STTDLY, 1) | SSC_BF(RCMR_START, SSC_START_RISING_RF) - | SSC_BF(RCMR_CKI, SSC_CKI_FALLING) + | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_DIV); @@ -692,7 +692,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, rcmr = SSC_BF(RCMR_PERIOD, 0) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, SSC_START_RISING_RF) - | SSC_BF(RCMR_CKI, SSC_CKI_FALLING) + | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? SSC_CKS_PIN : SSC_CKS_CLOCK); -- GitLab From bb28c28ee10559c5bc5b5f48c2d6f6f2f6bd5586 Mon Sep 17 00:00:00 2001 From: Marty Faltesek Date: Wed, 20 Apr 2016 00:19:35 -0400 Subject: [PATCH 4774/9938] mwifiex: bridged packets cause wmm_tx_pending counter to go negative When a packet is queued from the bridge, wmm_tx_pending is not incremented, but when the packet is dequeued the counter is decremented. Signed-off-by: Marty Faltesek Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index c95b61dc87c2..666e91af59d7 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -102,6 +102,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, int hdr_chop; struct ethhdr *p_ethhdr; struct mwifiex_sta_node *src_node; + int index; uap_rx_pd = (struct uap_rxpd *)(skb->data); rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); @@ -208,6 +209,9 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, } __net_timestamp(skb); + + index = mwifiex_1d_to_wmm_queue[skb->priority]; + atomic_inc(&priv->wmm_tx_pending[index]); mwifiex_wmm_add_buf_txqueue(priv, skb); atomic_inc(&adapter->tx_pending); atomic_inc(&adapter->pending_bridged_pkts); -- GitLab From b977d305ad20e05212c0ded2a7ef90e411edc1b3 Mon Sep 17 00:00:00 2001 From: Marty Faltesek Date: Wed, 20 Apr 2016 00:20:52 -0400 Subject: [PATCH 4775/9938] mwifiex: fw download does not release sdio bus during failure Signed-off-by: Marty Faltesek Reviewed-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sdio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index cbd9dcd88b98..099722e1f867 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1103,13 +1103,12 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, offset += txlen; } while (true); - sdio_release_host(card->func); - mwifiex_dbg(adapter, MSG, "info: FW download over, size %d bytes\n", offset); ret = 0; done: + sdio_release_host(card->func); kfree(fwbuf); return ret; } -- GitLab From 8d666302df95ab585f5cc7b2fb779991f8797eb5 Mon Sep 17 00:00:00 2001 From: Marty Faltesek Date: Wed, 20 Apr 2016 00:22:01 -0400 Subject: [PATCH 4776/9938] mwifiex: transmit packet stats incorrect. tx_packets counter is incremented for aggregated packets, when it had already been incremented for the aggregated packet's constituent parts. Removing the extra count. Signed-off-by: Marty Faltesek Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/txrx.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c index bf6182b646a5..abdd0cf710bf 100644 --- a/drivers/net/wireless/marvell/mwifiex/txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/txrx.c @@ -297,6 +297,13 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, goto done; mwifiex_set_trans_start(priv->netdev); + + if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) + atomic_dec_return(&adapter->pending_bridged_pkts); + + if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) + goto done; + if (!status) { priv->stats.tx_packets++; priv->stats.tx_bytes += tx_info->pkt_len; @@ -306,12 +313,6 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, priv->stats.tx_errors++; } - if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) - atomic_dec_return(&adapter->pending_bridged_pkts); - - if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) - goto done; - if (aggr) /* For skb_aggr, do not wake up tx queue */ goto done; -- GitLab From 3f210e2f1269ffe83188db2f1f5839da907fc722 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 21 Apr 2016 08:07:54 -0700 Subject: [PATCH 4777/9938] mwifiex: fix coding style Redundant space in case statement is removed. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 6db202fa7157..369ea06eca52 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3388,7 +3388,7 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) break; case CONTROL_FRAME_MATCHED: break; - case MANAGEMENT_FRAME_MATCHED: + case MANAGEMENT_FRAME_MATCHED: break; case GTK_REKEY_FAILURE: if (wiphy->wowlan_config->gtk_rekey_failure) -- GitLab From df2288623ee0ce77743d76ed8ca816e92246e77b Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 21 Apr 2016 08:07:55 -0700 Subject: [PATCH 4778/9938] mwifiex: report wowlan wakeup reasons correctly It's been observed that wakeup on GTK rekey failure wasn't reported to cfg80211. This patch corrects the check so that all valid wakeup reasons are reported. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 369ea06eca52..734cf67b79c1 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3344,6 +3344,7 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) struct mwifiex_ds_wakeup_reason wakeup_reason; struct cfg80211_wowlan_wakeup wakeup_report; int i; + bool report_wakeup_reason = true; for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; @@ -3386,20 +3387,16 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) if (wiphy->wowlan_config->n_patterns) wakeup_report.pattern_idx = 1; break; - case CONTROL_FRAME_MATCHED: - break; - case MANAGEMENT_FRAME_MATCHED: - break; case GTK_REKEY_FAILURE: if (wiphy->wowlan_config->gtk_rekey_failure) wakeup_report.gtk_rekey_failure = true; break; default: + report_wakeup_reason = false; break; } - if ((wakeup_reason.hs_wakeup_reason > 0) && - (wakeup_reason.hs_wakeup_reason <= 7)) + if (report_wakeup_reason) cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report, GFP_KERNEL); -- GitLab From d286af9bf40ab88f2035aef293f6ecae4187c6bb Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 21 Apr 2016 08:07:56 -0700 Subject: [PATCH 4779/9938] mwifiex: avoid querying wakeup reason when wowlan is disabled In cfg80211 resume handler, we query wakeup reason from firmware and report to cfg80211. if wowlan is disabled, connection is already terminated during suspend. We don't need to query wakeup reason in this case. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 734cf67b79c1..ff948a922222 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3355,6 +3355,9 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) } } + if (!wiphy->wowlan_config) + goto done; + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); mwifiex_get_wakeup_reason(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD, &wakeup_reason); @@ -3400,6 +3403,7 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report, GFP_KERNEL); +done: if (adapter->nd_info) { for (i = 0 ; i < adapter->nd_info->n_matches ; i++) kfree(adapter->nd_info->matches[i]); -- GitLab From 1b499cb72f26bbf44f2fa158c2d1487730aae96a Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Sun, 24 Apr 2016 23:49:51 -0700 Subject: [PATCH 4780/9938] mwifiex: disable channel filtering feature in firmware As 2.4Ghz channels are overlapping, sometimes AP responds to probe request even if it's operating on neighbouring channel. Currently firmware drops those scan entries, as current channel doesn't match with APs channel. This patch enables MWIFIEX_DISABLE_CHAN_FILT flag in scan command to disable the feature so that better scan results will be received in 2.4Ghz band. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 36cc9cca95fc..bc5e52cebce1 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -498,11 +498,13 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, &= ~MWIFIEX_PASSIVE_SCAN; scan_chan_list[chan_idx].chan_number = (u32) ch->hw_value; + + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_DISABLE_CHAN_FILT; + if (filtered_scan) { scan_chan_list[chan_idx].max_scan_time = cpu_to_le16(adapter->specific_scan_time); - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_DISABLE_CHAN_FILT; } chan_idx++; } @@ -1060,9 +1062,8 @@ mwifiex_config_scan(struct mwifiex_private *priv, scan_chan_list[chan_idx].chan_scan_mode_bitmap &= ~MWIFIEX_PASSIVE_SCAN; - if (*filtered_scan) - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_DISABLE_CHAN_FILT; + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_DISABLE_CHAN_FILT; if (user_scan_in->chan_list[chan_idx].scan_time) { scan_dur = (u16) user_scan_in-> -- GitLab From 9d3f65b0c2ddb926340af96eb89ad9be589865c0 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Sun, 24 Apr 2016 23:49:52 -0700 Subject: [PATCH 4781/9938] mwifiex: increase dwell time for active scan It's been observed that sometimes AP's probe response is received after scan duration gets completed for the channel. This happens especially when wildcard scan is performed along with specific SSID scan. We will increase the time from 30 msecs to 40 msecs. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 4c742a597cb0..0207af00be42 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -111,8 +111,8 @@ enum { #define SCAN_BEACON_ENTRY_PAD 6 #define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110 -#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 30 -#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 30 +#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 40 +#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 40 #define MWIFIEX_DEF_SCAN_CHAN_GAP_TIME 50 #define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) -- GitLab From 65da9a0a3bf2202c2432f42d41eb908f2fa30579 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 27 Apr 2016 10:13:46 -0400 Subject: [PATCH 4782/9938] tracing: Make filter_check_discard() local Nothing outside of the tracing directory calls filter_check_discard() or check_filter_check_discard(). They should not be called by modules. Move their prototypes into the local tracing header and remove their EXPORT_SYMBOL() macros. Signed-off-by: Steven Rostedt --- include/linux/trace_events.h | 6 ------ kernel/trace/trace.c | 2 -- kernel/trace/trace.h | 6 ++++++ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 70a181cb3585..bb383af35cc7 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -413,12 +413,6 @@ enum event_trigger_type { extern int filter_match_preds(struct event_filter *filter, void *rec); -extern int filter_check_discard(struct trace_event_file *file, void *rec, - struct ring_buffer *buffer, - struct ring_buffer_event *event); -extern int call_filter_check_discard(struct trace_event_call *call, void *rec, - struct ring_buffer *buffer, - struct ring_buffer_event *event); extern enum event_trigger_type event_triggers_call(struct trace_event_file *file, void *rec); extern void event_triggers_post_call(struct trace_event_file *file, diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 46028d47d252..02f5a5f51d49 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -318,7 +318,6 @@ int filter_check_discard(struct trace_event_file *file, void *rec, return 0; } -EXPORT_SYMBOL_GPL(filter_check_discard); int call_filter_check_discard(struct trace_event_call *call, void *rec, struct ring_buffer *buffer, @@ -332,7 +331,6 @@ int call_filter_check_discard(struct trace_event_call *call, void *rec, return 0; } -EXPORT_SYMBOL_GPL(call_filter_check_discard); static cycle_t buffer_ftrace_now(struct trace_buffer *buf, int cpu) { diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index c0eac7b1e5a6..ee8691c66bfe 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1065,6 +1065,12 @@ struct trace_subsystem_dir { int nr_events; }; +extern int filter_check_discard(struct trace_event_file *file, void *rec, + struct ring_buffer *buffer, + struct ring_buffer_event *event); +extern int call_filter_check_discard(struct trace_event_call *call, void *rec, + struct ring_buffer *buffer, + struct ring_buffer_event *event); /* * Helper function for event_trigger_unlock_commit{_regs}(). * If there are event triggers attached to this event that requires -- GitLab From 70896650732afd64c410f85c819281dbce8a0974 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Fri, 8 Apr 2016 15:31:50 +0800 Subject: [PATCH 4783/9938] arm64: dts: hip05: fix its node without msi-cells Fix commit abf9c25d55e8 ("arm64: dts: hip05: Append all gicv3 ITS entries"), it forgets the property msi-cell, see arm,gic-v3.txt. Signed-off-by: Kefeng Wang Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hip05.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi index 6319ff3b03ea..52d06ab816db 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi @@ -249,24 +249,28 @@ its_peri: interrupt-controller@8c000000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0x8c000000 0x0 0x40000>; }; its_m3: interrupt-controller@a3000000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0xa3000000 0x0 0x40000>; }; its_pcie: interrupt-controller@b7000000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0xb7000000 0x0 0x40000>; }; its_dsa: interrupt-controller@c6000000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0xc6000000 0x0 0x40000>; }; }; -- GitLab From 162d23bfd18cec10bd5940ff264debf3c6121f34 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Fri, 8 Apr 2016 15:31:51 +0800 Subject: [PATCH 4784/9938] arm64: dts: hip05: Add nor flash support This patch is to add support nor-flash. Notice, the pre-defined partitions may not be used. Signed-off-by: Kefeng Wang Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/hip05-d02.dts | 34 +++++++++++++++++++++ arch/arm64/boot/dts/hisilicon/hip05.dtsi | 6 ++++ 2 files changed, 40 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hip05-d02.dts b/arch/arm64/boot/dts/hisilicon/hip05-d02.dts index e9436c0d81f7..abba750b87f8 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05-d02.dts +++ b/arch/arm64/boot/dts/hisilicon/hip05-d02.dts @@ -52,3 +52,37 @@ &peri_gpio0 { status = "ok"; }; + +&lbc { + status = "ok"; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x0 0x90000000 0x08000000>, + <1 0 0x0 0x98000000 0x08000000>; + + nor-flash@0,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "numonyx,js28f00a", "cfi-flash"; + reg = <0 0x0 0x08000000>; + bank-width = <2>; + /* The three parts may not used */ + partition@0 { + label = "BIOS"; + reg = <0x0 0x300000>; + }; + partition@300000 { + label = "Linux"; + reg = <0x300000 0xa00000>; + }; + partition@1000000 { + label = "Rootfs"; + reg = <0x01000000 0x02000000>; + }; + }; + + cpld@1,0 { + compatible = "hisilicon,hip05-cpld"; + reg = <1 0x0 0x100>; + }; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi index 52d06ab816db..bf322ed038b8 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi @@ -327,6 +327,12 @@ status = "disabled"; }; + lbc: localbus@80380000 { + compatible = "hisilicon,hisi-localbus", "simple-bus"; + reg = <0x0 0x80380000 0x0 0x10000>; + status = "disabled"; + }; + peri_gpio0: gpio@802e0000 { #address-cells = <1>; #size-cells = <0>; -- GitLab From aa8d3e74f54d0af737c46c77de35b39d9a44592b Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Fri, 8 Apr 2016 15:27:11 +0800 Subject: [PATCH 4785/9938] arm64: dts: Add initial dts for Hisilicon Hip06 D03 board The Hip06 soc has same cpu topology compared with Hip05, four clusters and each cluster has quard Cortex-A57, but with different IO part, like HNS, SAS and PCI, they are all upgraded. There are also not same in ITS, MBIGEN and SMMU, etc. This patch adds the initial dts for hip06 d03 board. Note, there is no serial, because the soc use LPC uart, the serial node is not needed. Signed-off-by: Kefeng Wang Signed-off-by: Wei Xu --- arch/arm64/boot/dts/hisilicon/Makefile | 4 +- arch/arm64/boot/dts/hisilicon/hip06-d03.dts | 34 +++ arch/arm64/boot/dts/hisilicon/hip06.dtsi | 307 ++++++++++++++++++++ 3 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/hisilicon/hip06-d03.dts create mode 100644 arch/arm64/boot/dts/hisilicon/hip06.dtsi diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile index cd158b80e29b..d5f43a06b1c1 100644 --- a/arch/arm64/boot/dts/hisilicon/Makefile +++ b/arch/arm64/boot/dts/hisilicon/Makefile @@ -1,4 +1,6 @@ -dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb hip05-d02.dtb +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb +dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb +dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/hisilicon/hip06-d03.dts b/arch/arm64/boot/dts/hisilicon/hip06-d03.dts new file mode 100644 index 000000000000..f3e5323e430b --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hip06-d03.dts @@ -0,0 +1,34 @@ +/** + * dts file for Hisilicon D03 Development Board + * + * Copyright (C) 2016 Hisilicon Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + * + */ + +/dts-v1/; + +#include "hip06.dtsi" + +/ { + model = "Hisilicon Hip06 D03 Development Board"; + compatible = "hisilicon,hip06-d03"; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x00000000 0x0 0x40000000>; + }; + + chosen { }; +}; + +&usb_ohci { + status = "ok"; +}; + +&usb_ehci { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi new file mode 100644 index 000000000000..5927bc472f1b --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi @@ -0,0 +1,307 @@ +/** + * dts file for Hisilicon D03 Development Board + * + * Copyright (C) 2016 Hisilicon Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + * + */ + +#include + +/ { + compatible = "hisilicon,hip06-d03"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + cluster1 { + core0 { + cpu = <&cpu4>; + }; + core1 { + cpu = <&cpu5>; + }; + core2 { + cpu = <&cpu6>; + }; + core3 { + cpu = <&cpu7>; + }; + }; + cluster2 { + core0 { + cpu = <&cpu8>; + }; + core1 { + cpu = <&cpu9>; + }; + core2 { + cpu = <&cpu10>; + }; + core3 { + cpu = <&cpu11>; + }; + }; + cluster3 { + core0 { + cpu = <&cpu12>; + }; + core1 { + cpu = <&cpu13>; + }; + core2 { + cpu = <&cpu14>; + }; + core3 { + cpu = <&cpu15>; + }; + }; + }; + + cpu0: cpu@10000 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10000>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + }; + + cpu1: cpu@10001 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10001>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + }; + + cpu2: cpu@10002 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10002>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + }; + + cpu3: cpu@10003 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10003>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + }; + + cpu4: cpu@10100 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10100>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + }; + + cpu5: cpu@10101 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10101>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + }; + + cpu6: cpu@10102 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10102>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + }; + + cpu7: cpu@10103 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10103>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + }; + + cpu8: cpu@10200 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10200>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + }; + + cpu9: cpu@10201 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10201>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + }; + + cpu10: cpu@10202 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10202>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + }; + + cpu11: cpu@10203 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10203>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + }; + + cpu12: cpu@10300 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10300>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + }; + + cpu13: cpu@10301 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10301>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + }; + + cpu14: cpu@10302 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10302>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + }; + + cpu15: cpu@10303 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x10303>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + }; + + cluster0_l2: l2-cache0 { + compatible = "cache"; + }; + + cluster1_l2: l2-cache1 { + compatible = "cache"; + }; + + cluster2_l2: l2-cache2 { + compatible = "cache"; + }; + + cluster3_l2: l2-cache3 { + compatible = "cache"; + }; + }; + + gic: interrupt-controller@4d000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + #redistributor-regions = <1>; + redistributor-stride = <0x0 0x30000>; + reg = <0x0 0x4d000000 0 0x10000>, /* GICD */ + <0x0 0x4d100000 0 0x300000>, /* GICR */ + <0x0 0xfe000000 0 0x10000>, /* GICC */ + <0x0 0xfe010000 0 0x10000>, /* GICH */ + <0x0 0xfe020000 0 0x10000>; /* GICV */ + interrupts = ; + + its_dsa: interrupt-controller@c6000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0xc6000000 0x0 0x40000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + pmu { + compatible = "arm,cortex-a57-pmu"; + interrupts = ; + }; + + mbigen_pcie@a0080000 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x0 0xa0080000 0x0 0x10000>; + + mbigen_usb: intc_usb { + msi-parent = <&its_dsa 0x40080>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <2>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + usb_ohci: ohci@a7030000 { + compatible = "generic-ohci"; + reg = <0x0 0xa7030000 0x0 0x10000>; + interrupt-parent = <&mbigen_usb>; + interrupts = <64 4>; + dma-coherent; + status = "disabled"; + }; + + usb_ehci: ehci@a7020000 { + compatible = "generic-ehci"; + reg = <0x0 0xa7020000 0x0 0x10000>; + interrupt-parent = <&mbigen_usb>; + interrupts = <65 4>; + dma-coherent; + status = "disabled"; + }; + }; + +}; -- GitLab From 4cfcb35189f62ae351194827fca1787053a66235 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Fri, 8 Apr 2016 15:27:12 +0800 Subject: [PATCH 4786/9938] Documentation: arm64: Add Hisilicon Hip06 D03 dts binding This patch adds documentation for the devicetree bindings used by the DT files of Hisilicon Hip06 D03 board. Meanwhile, reorder the soc/board name alphabetically. Signed-off-by: Kefeng Wang Signed-off-by: Wei Xu --- .../bindings/arm/hisilicon/hisilicon.txt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt index e3ccab114006..83fe816ae050 100644 --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt @@ -1,29 +1,33 @@ Hisilicon Platforms Device Tree Bindings ---------------------------------------------------- -Hi6220 SoC -Required root node properties: - - compatible = "hisilicon,hi6220"; - Hi4511 Board Required root node properties: - compatible = "hisilicon,hi3620-hi4511"; -HiP04 D01 Board +Hi6220 SoC Required root node properties: - - compatible = "hisilicon,hip04-d01"; + - compatible = "hisilicon,hi6220"; + +HiKey Board +Required root node properties: + - compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220"; HiP01 ca9x2 Board Required root node properties: - compatible = "hisilicon,hip01-ca9x2"; -HiKey Board +HiP04 D01 Board Required root node properties: - - compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220"; + - compatible = "hisilicon,hip04-d01"; HiP05 D02 Board Required root node properties: - compatible = "hisilicon,hip05-d02"; +HiP06 D03 Board +Required root node properties: + - compatible = "hisilicon,hip06-d03"; + Hisilicon system controller Required properties: -- GitLab From a2262e5a12e05389ab4c7fc5cf60016b041dd8dc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 27 Apr 2016 15:59:27 +0200 Subject: [PATCH 4787/9938] regulator: axp20x: Fix axp22x ldo_io voltage ranges The minium voltage of 1800mV is a copy and paste error from the axp20x regulator info. The correct minimum voltage for the ldo_io regulators on the axp22x is 700mV. Fixes: 1b82b4e4f954 ("regulator: axp20x: Add support for AXP22X regulators") Signed-off-by: Hans de Goede Acked-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 29ab0985b46e..89f684295657 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -217,10 +217,10 @@ static const struct regulator_desc axp22x_regulators[] = { AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)), AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100, AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)), - AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 1800, 3300, 100, + AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100, AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07, AXP22X_IO_ENABLED, AXP22X_IO_DISABLED), - AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 1800, 3300, 100, + AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100, AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07, AXP22X_IO_ENABLED, AXP22X_IO_DISABLED), AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000), -- GitLab From 05195ed3ec96926388d253608a40d7f2b4b07413 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 27 Apr 2016 15:59:27 +0200 Subject: [PATCH 4788/9938] regulator: axp20x: Fix axp22x ldo_io voltage ranges The minium voltage of 1800mV is a copy and paste error from the axp20x regulator info. The correct minimum voltage for the ldo_io regulators on the axp22x is 700mV. Fixes: 1b82b4e4f954 ("regulator: axp20x: Add support for AXP22X regulators") Signed-off-by: Hans de Goede Acked-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 40cd894e4df5..0c0e7a31ba49 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -215,10 +215,10 @@ static const struct regulator_desc axp22x_regulators[] = { AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)), AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100, AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)), - AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 1800, 3300, 100, + AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100, AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07, AXP22X_IO_ENABLED, AXP22X_IO_DISABLED), - AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 1800, 3300, 100, + AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100, AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07, AXP22X_IO_ENABLED, AXP22X_IO_DISABLED), AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000), -- GitLab From 66225e98b985047ef214632413cc404a6341c960 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 27 Apr 2016 14:58:27 +0100 Subject: [PATCH 4789/9938] ASoC: wm_adsp: free memory when unloaded or closed The patch adds a wm_adsp2_remove() function to ensure that memory is freed when the driver is unloaded or shut down. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 20 ++++++++++++++++++++ sound/soc/codecs/wm_adsp.h | 1 + 2 files changed, 21 insertions(+) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index d3b1cb15e7f0..5f8727af912b 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -944,6 +944,13 @@ static void wm_adsp_ctl_work(struct work_struct *work) kfree(ctl_work); } +static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl) +{ + kfree(ctl->cache); + kfree(ctl->name); + kfree(ctl); +} + static int wm_adsp_create_control(struct wm_adsp *dsp, const struct wm_adsp_alg_region *alg_region, unsigned int offset, unsigned int len, @@ -2340,6 +2347,19 @@ int wm_adsp2_init(struct wm_adsp *dsp) } EXPORT_SYMBOL_GPL(wm_adsp2_init); +void wm_adsp2_remove(struct wm_adsp *dsp) +{ + struct wm_coeff_ctl *ctl; + + while (!list_empty(&dsp->ctl_list)) { + ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl, + list); + list_del(&ctl->list); + wm_adsp_free_ctl_blk(ctl); + } +} +EXPORT_SYMBOL_GPL(wm_adsp2_remove); + int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream) { struct wm_adsp_compr *compr; diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index b61cb57e600f..feb61e2c4bb4 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -92,6 +92,7 @@ extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; int wm_adsp1_init(struct wm_adsp *dsp); int wm_adsp2_init(struct wm_adsp *dsp); +void wm_adsp2_remove(struct wm_adsp *dsp); int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec); int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec); int wm_adsp1_event(struct snd_soc_dapm_widget *w, -- GitLab From 401cf1466a59139ec1805e2171d43a32be92f89c Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 27 Apr 2016 14:58:28 +0100 Subject: [PATCH 4790/9938] ASoC: arizona: call wm_adsp2_remove when codec driver is removed Ensure that the wm_adsp driver cleans up when the codec driver is removed. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 5 +++++ sound/soc/codecs/wm5102.c | 4 ++++ sound/soc/codecs/wm5110.c | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 576087bda330..29313780a38a 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1238,10 +1238,15 @@ static int cs47l24_probe(struct platform_device *pdev) static int cs47l24_remove(struct platform_device *pdev) { + struct cs47l24_priv *cs47l24 = platform_get_drvdata(pdev); + snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_codec(&pdev->dev); pm_runtime_disable(&pdev->dev); + wm_adsp2_remove(&cs47l24->core.adsp[1]); + wm_adsp2_remove(&cs47l24->core.adsp[2]); + return 0; } diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index a8b3e3f701f9..7a539e0529c0 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -2093,10 +2093,14 @@ static int wm5102_probe(struct platform_device *pdev) static int wm5102_remove(struct platform_device *pdev) { + struct wm5102_priv *wm5102 = platform_get_drvdata(pdev); + snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_codec(&pdev->dev); pm_runtime_disable(&pdev->dev); + wm_adsp2_remove(&wm5102->core.adsp[0]); + return 0; } diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 83ba70fe16e6..dd87af1ffa23 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2435,10 +2435,16 @@ static int wm5110_probe(struct platform_device *pdev) static int wm5110_remove(struct platform_device *pdev) { + struct wm5110_priv *wm5110 = platform_get_drvdata(pdev); + int i; + snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_codec(&pdev->dev); pm_runtime_disable(&pdev->dev); + for (i = 0; i < WM5110_NUM_ADSP; i++) + wm_adsp2_remove(&wm5110->core.adsp[i]); + return 0; } -- GitLab From 56574d541f93cf8c9449f9ecadc83d97323cfcec Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 27 Apr 2016 14:58:29 +0100 Subject: [PATCH 4791/9938] ASoC: wm_adsp: factor out freeing of alg regions Add a function to delete and free the contents of the alg_regions list. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 5f8727af912b..8cde7bb4c52b 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1571,6 +1571,19 @@ static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp, return alg_region; } +static void wm_adsp_free_alg_regions(struct wm_adsp *dsp) +{ + struct wm_adsp_alg_region *alg_region; + + while (!list_empty(&dsp->alg_regions)) { + alg_region = list_first_entry(&dsp->alg_regions, + struct wm_adsp_alg_region, + list); + list_del(&alg_region->list); + kfree(alg_region); + } +} + static int wm_adsp1_setup_algs(struct wm_adsp *dsp) { struct wmfw_adsp1_id_hdr adsp1_id; @@ -2001,7 +2014,6 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsp = &dsps[w->shift]; - struct wm_adsp_alg_region *alg_region; struct wm_coeff_ctl *ctl; int ret; unsigned int val; @@ -2081,13 +2093,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, list_for_each_entry(ctl, &dsp->ctl_list, list) ctl->enabled = 0; - while (!list_empty(&dsp->alg_regions)) { - alg_region = list_first_entry(&dsp->alg_regions, - struct wm_adsp_alg_region, - list); - list_del(&alg_region->list); - kfree(alg_region); - } + + wm_adsp_free_alg_regions(dsp); break; default: @@ -2229,7 +2236,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsp = &dsps[w->shift]; - struct wm_adsp_alg_region *alg_region; struct wm_coeff_ctl *ctl; int ret; @@ -2276,13 +2282,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, list_for_each_entry(ctl, &dsp->ctl_list, list) ctl->enabled = 0; - while (!list_empty(&dsp->alg_regions)) { - alg_region = list_first_entry(&dsp->alg_regions, - struct wm_adsp_alg_region, - list); - list_del(&alg_region->list); - kfree(alg_region); - } + wm_adsp_free_alg_regions(dsp); if (wm_adsp_fw[dsp->fw].num_caps != 0) wm_adsp_buffer_free(dsp); -- GitLab From c145344763192042135ef6172b779baaf4a16c1e Mon Sep 17 00:00:00 2001 From: Yuan Yao Date: Wed, 27 Apr 2016 16:12:36 +0800 Subject: [PATCH 4792/9938] spi: spi-fsl-dspi: Update DT binding documentation DSPI driver support the register on the controller with big endian mode R/W. But not use the regmap API. So update the binding documentation for "big-endian". Signed-off-by: Yuan Yao Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt index fa77f874e321..d2969d2ceb4b 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt @@ -13,8 +13,7 @@ Required properties: Optional property: - big-endian: If present the dspi device's registers are implemented - in big endian mode, otherwise in native mode(same with CPU), for more - detail please see: Documentation/devicetree/bindings/regmap/regmap.txt. + in big endian mode. Optional SPI slave node properties: - fsl,spi-cs-sck-delay: a delay in nanoseconds between activating chip -- GitLab From 45389c47526d1eca70f96872c172aea0941e8520 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 26 Apr 2016 11:29:45 +0100 Subject: [PATCH 4793/9938] regulator: core: Add early supply resolution for regulators The call to set_machine_constraints() in regulator_register(), will attempt to get the voltage for the regulator. If a regulator is in bypass will fail to get the voltage (ie. it's bypass voltage) and hence register the regulator, because the supply for the regulator has not been resolved yet. To fix this, add a call to regulator_resolve_supply() before we call set_machine_constraints(). If the call to regulator_resolve_supply() fails, rather than returning an error at this point, allow the registration of the regulator to continue because for some regulators resolving the supply at this point may not be necessary and it will be resolved later as more regulators are added. Furthermore, if the supply is still not resolved for a bypassed regulator, this will be detected when we attempt to get the voltage for the regulator and an error will be propagated at this point. If a bypassed regulator does not have a supply when we attempt to get the voltage, rather than returing -EINVAL, return -EPROBE_DEFER instead to allow the registration of the regulator to be deferred and tried again later. Please note that regulator_resolve_supply() will call regulator_dev_lookup() which may acquire the regulator_list_mutex. To avoid any deadlocks we cannot hold the regulator_list_mutex when calling regulator_resolve_supply(). Therefore, rather than holding the lock around a large portion of the registration code, just hold the lock when aquiring any GPIOs and setting up supplies because these sections may add entries to the regulator_map_list and regulator_ena_gpio_list, respectively. Signed-off-by: Jon Hunter Signed-off-by: Mark Brown --- drivers/regulator/core.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f6d624dfcf9f..f4ab8c8bab23 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3118,8 +3118,11 @@ static int _regulator_get_voltage(struct regulator_dev *rdev) return ret; if (bypassed) { /* if bypassed the regulator must have a supply */ - if (!rdev->supply) - return -EINVAL; + if (!rdev->supply) { + rdev_err(rdev, + "bypassed regulator has no supply!\n"); + return -EPROBE_DEFER; + } return _regulator_get_voltage(rdev->supply->rdev); } @@ -3936,8 +3939,6 @@ regulator_register(const struct regulator_desc *regulator_desc, rdev->dev.of_node = of_node_get(config->of_node); } - mutex_lock(®ulator_list_mutex); - mutex_init(&rdev->mutex); rdev->reg_data = config->driver_data; rdev->owner = regulator_desc->owner; @@ -3962,7 +3963,9 @@ regulator_register(const struct regulator_desc *regulator_desc, if ((config->ena_gpio || config->ena_gpio_initialized) && gpio_is_valid(config->ena_gpio)) { + mutex_lock(®ulator_list_mutex); ret = regulator_ena_gpio_request(rdev, config); + mutex_unlock(®ulator_list_mutex); if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", config->ena_gpio, ret); @@ -3980,31 +3983,40 @@ regulator_register(const struct regulator_desc *regulator_desc, if (init_data) constraints = &init_data->constraints; - ret = set_machine_constraints(rdev, constraints); - if (ret < 0) - goto wash; - if (init_data && init_data->supply_regulator) rdev->supply_name = init_data->supply_regulator; else if (regulator_desc->supply_name) rdev->supply_name = regulator_desc->supply_name; + /* + * Attempt to resolve the regulator supply, if specified, + * but don't return an error if we fail because we will try + * to resolve it again later as more regulators are added. + */ + if (regulator_resolve_supply(rdev)) + rdev_dbg(rdev, "unable to resolve supply\n"); + + ret = set_machine_constraints(rdev, constraints); + if (ret < 0) + goto wash; + /* add consumers devices */ if (init_data) { + mutex_lock(®ulator_list_mutex); for (i = 0; i < init_data->num_consumer_supplies; i++) { ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev_name, init_data->consumer_supplies[i].supply); if (ret < 0) { + mutex_unlock(®ulator_list_mutex); dev_err(dev, "Failed to set supply %s\n", init_data->consumer_supplies[i].supply); goto unset_supplies; } } + mutex_unlock(®ulator_list_mutex); } - mutex_unlock(®ulator_list_mutex); - ret = device_register(&rdev->dev); if (ret != 0) { put_device(&rdev->dev); @@ -4021,13 +4033,16 @@ regulator_register(const struct regulator_desc *regulator_desc, return rdev; unset_supplies: + mutex_lock(®ulator_list_mutex); unset_regulator_supplies(rdev); + mutex_unlock(®ulator_list_mutex); wash: kfree(rdev->constraints); + mutex_lock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); + mutex_unlock(®ulator_list_mutex); clean: kfree(rdev); - mutex_unlock(®ulator_list_mutex); kfree(config); return ERR_PTR(ret); } -- GitLab From 4e2f17be8f63a6ad9ebd4cdfce627e3dd25d80bb Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Tue, 26 Apr 2016 17:15:56 -0500 Subject: [PATCH 4794/9938] ASoC: add TA5720 digital amplifier DT bindings The Texas Instruments TAS5720L/M device is a high-efficiency mono Class-D audio power amplifier optimized for high transient power capability to use the dynamic power headroom of small loudspeakers. Its digital time division multiplexed (TDM) interface enables up to 16 devices to share the same bus. Signed-off-by: Andreas Dannenberg Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tas5720.txt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tas5720.txt diff --git a/Documentation/devicetree/bindings/sound/tas5720.txt b/Documentation/devicetree/bindings/sound/tas5720.txt new file mode 100644 index 000000000000..806ea7381483 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tas5720.txt @@ -0,0 +1,25 @@ +Texas Instruments TAS5720 Mono Audio amplifier + +The TAS5720 serial control bus communicates through the I2C protocol only. The +serial bus is also used for periodic codec fault checking/reporting during +audio playback. For more product information please see the links below: + +http://www.ti.com/product/TAS5720L +http://www.ti.com/product/TAS5720M + +Required properties: + +- compatible : "ti,tas5720" +- reg : I2C slave address +- dvdd-supply : phandle to a 3.3-V supply for the digital circuitry +- pvdd-supply : phandle to a supply used for the Class-D amp and the analog + +Example: + +tas5720: tas5720@6c { + status = "okay"; + compatible = "ti,tas5720"; + reg = <0x6c>; + dvdd-supply = <&vdd_3v3_reg>; + pvdd-supply = <&_supply_reg>; +}; -- GitLab From bd023ada36a66fe3d2fde619926b49b9a0428133 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Tue, 26 Apr 2016 17:15:57 -0500 Subject: [PATCH 4795/9938] ASoC: add support for TAS5720 digital amplifier The Texas Instruments TAS5720L/M device is a high-efficiency mono Class-D audio power amplifier optimized for high transient power capability to use the dynamic power headroom of small loudspeakers. Its digital time division multiplexed (TDM) interface enables up to 16 devices to share the same bus. Signed-off-by: Andreas Dannenberg Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 8 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tas5720.c | 620 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas5720.h | 90 ++++++ 4 files changed, 720 insertions(+) create mode 100644 sound/soc/codecs/tas5720.c create mode 100644 sound/soc/codecs/tas5720.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index c011f076d58b..06d298b79b9b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -124,6 +124,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TAS2552 if I2C select SND_SOC_TAS5086 if I2C select SND_SOC_TAS571X if I2C + select SND_SOC_TAS5720 if I2C select SND_SOC_TFA9879 if I2C select SND_SOC_TLV320AIC23_I2C if I2C select SND_SOC_TLV320AIC23_SPI if SPI_MASTER @@ -740,6 +741,13 @@ config SND_SOC_TAS571X tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers" depends on I2C +config SND_SOC_TAS5720 + tristate "Texas Instruments TAS5720 Mono Audio amplifier" + depends on I2C + help + Enable support for Texas Instruments TAS5720L/M high-efficiency mono + Class-D audio power amplifiers. + config SND_SOC_TFA9879 tristate "NXP Semiconductors TFA9879 amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 185a712a7fe7..83d352ede6fd 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -129,6 +129,7 @@ snd-soc-stac9766-objs := stac9766.o snd-soc-sti-sas-objs := sti-sas.o snd-soc-tas5086-objs := tas5086.o snd-soc-tas571x-objs := tas571x.o +snd-soc-tas5720-objs := tas5720.o snd-soc-tfa9879-objs := tfa9879.o snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o @@ -335,6 +336,7 @@ obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o +obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c new file mode 100644 index 000000000000..f54fb46b77c2 --- /dev/null +++ b/sound/soc/codecs/tas5720.c @@ -0,0 +1,620 @@ +/* + * tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier + * + * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Andreas Dannenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "tas5720.h" + +/* Define how often to check (and clear) the fault status register (in ms) */ +#define TAS5720_FAULT_CHECK_INTERVAL 200 + +static const char * const tas5720_supply_names[] = { + "dvdd", /* Digital power supply. Connect to 3.3-V supply. */ + "pvdd", /* Class-D amp and analog power supply (connected). */ +}; + +#define TAS5720_NUM_SUPPLIES ARRAY_SIZE(tas5720_supply_names) + +struct tas5720_data { + struct snd_soc_codec *codec; + struct regmap *regmap; + struct i2c_client *tas5720_client; + struct regulator_bulk_data supplies[TAS5720_NUM_SUPPLIES]; + struct delayed_work fault_check_work; + unsigned int last_fault; +}; + +static int tas5720_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + unsigned int rate = params_rate(params); + bool ssz_ds; + int ret; + + switch (rate) { + case 44100: + case 48000: + ssz_ds = false; + break; + case 88200: + case 96000: + ssz_ds = true; + break; + default: + dev_err(codec->dev, "unsupported sample rate: %u\n", rate); + return -EINVAL; + } + + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, + TAS5720_SSZ_DS, ssz_ds); + if (ret < 0) { + dev_err(codec->dev, "error setting sample rate: %d\n", ret); + return ret; + } + + return 0; +} + +static int tas5720_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + u8 serial_format; + int ret; + + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { + dev_vdbg(codec->dev, "DAI Format master is not found\n"); + return -EINVAL; + } + + switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | + SND_SOC_DAIFMT_INV_MASK)) { + case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): + /* 1st data bit occur one BCLK cycle after the frame sync */ + serial_format = TAS5720_SAIF_I2S; + break; + case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF): + /* + * Note that although the TAS5720 does not have a dedicated DSP + * mode it doesn't care about the LRCLK duty cycle during TDM + * operation. Therefore we can use the device's I2S mode with + * its delaying of the 1st data bit to receive DSP_A formatted + * data. See device datasheet for additional details. + */ + serial_format = TAS5720_SAIF_I2S; + break; + case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF): + /* + * Similar to DSP_A, we can use the fact that the TAS5720 does + * not care about the LRCLK duty cycle during TDM to receive + * DSP_B formatted data in LEFTJ mode (no delaying of the 1st + * data bit). + */ + serial_format = TAS5720_SAIF_LEFTJ; + break; + case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): + /* No delay after the frame sync */ + serial_format = TAS5720_SAIF_LEFTJ; + break; + default: + dev_vdbg(codec->dev, "DAI Format is not found\n"); + return -EINVAL; + } + + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, + TAS5720_SAIF_FORMAT_MASK, + serial_format); + if (ret < 0) { + dev_err(codec->dev, "error setting SAIF format: %d\n", ret); + return ret; + } + + return 0; +} + +static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_codec *codec = dai->codec; + unsigned int first_slot; + int ret; + + if (!tx_mask) { + dev_err(codec->dev, "tx masks must not be 0\n"); + return -EINVAL; + } + + /* + * Determine the first slot that is being requested. We will only + * use the first slot that is found since the TAS5720 is a mono + * amplifier. + */ + first_slot = __ffs(tx_mask); + + if (first_slot > 7) { + dev_err(codec->dev, "slot selection out of bounds (%u)\n", + first_slot); + return -EINVAL; + } + + /* Enable manual TDM slot selection (instead of I2C ID based) */ + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, + TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC); + if (ret < 0) + goto error_snd_soc_update_bits; + + /* Configure the TDM slot to process audio from */ + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, + TAS5720_TDM_SLOT_SEL_MASK, first_slot); + if (ret < 0) + goto error_snd_soc_update_bits; + + return 0; + +error_snd_soc_update_bits: + dev_err(codec->dev, "error configuring TDM mode: %d\n", ret); + return ret; +} + +static int tas5720_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + int ret; + + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, + TAS5720_MUTE, mute ? TAS5720_MUTE : 0); + if (ret < 0) { + dev_err(codec->dev, "error (un-)muting device: %d\n", ret); + return ret; + } + + return 0; +} + +static void tas5720_fault_check_work(struct work_struct *work) +{ + struct tas5720_data *tas5720 = container_of(work, struct tas5720_data, + fault_check_work.work); + struct device *dev = tas5720->codec->dev; + unsigned int curr_fault; + int ret; + + ret = regmap_read(tas5720->regmap, TAS5720_FAULT_REG, &curr_fault); + if (ret < 0) { + dev_err(dev, "failed to read FAULT register: %d\n", ret); + goto out; + } + + /* Check/handle all errors except SAIF clock errors */ + curr_fault &= TAS5720_OCE | TAS5720_DCE | TAS5720_OTE; + + /* + * Only flag errors once for a given occurrence. This is needed as + * the TAS5720 will take time clearing the fault condition internally + * during which we don't want to bombard the system with the same + * error message over and over. + */ + if ((curr_fault & TAS5720_OCE) && !(tas5720->last_fault & TAS5720_OCE)) + dev_crit(dev, "experienced an over current hardware fault\n"); + + if ((curr_fault & TAS5720_DCE) && !(tas5720->last_fault & TAS5720_DCE)) + dev_crit(dev, "experienced a DC detection fault\n"); + + if ((curr_fault & TAS5720_OTE) && !(tas5720->last_fault & TAS5720_OTE)) + dev_crit(dev, "experienced an over temperature fault\n"); + + /* Store current fault value so we can detect any changes next time */ + tas5720->last_fault = curr_fault; + + if (!curr_fault) + goto out; + + /* + * Periodically toggle SDZ (shutdown bit) H->L->H to clear any latching + * faults as long as a fault condition persists. Always going through + * the full sequence no matter the first return value to minimizes + * chances for the device to end up in shutdown mode. + */ + ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, + TAS5720_SDZ, 0); + if (ret < 0) + dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret); + + ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, + TAS5720_SDZ, TAS5720_SDZ); + if (ret < 0) + dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret); + +out: + /* Schedule the next fault check at the specified interval */ + schedule_delayed_work(&tas5720->fault_check_work, + msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL)); +} + +static int tas5720_codec_probe(struct snd_soc_codec *codec) +{ + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); + unsigned int device_id; + int ret; + + tas5720->codec = codec; + + ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), + tas5720->supplies); + if (ret != 0) { + dev_err(codec->dev, "failed to enable supplies: %d\n", ret); + return ret; + } + + ret = regmap_read(tas5720->regmap, TAS5720_DEVICE_ID_REG, &device_id); + if (ret < 0) { + dev_err(codec->dev, "failed to read device ID register: %d\n", + ret); + goto probe_fail; + } + + if (device_id != TAS5720_DEVICE_ID) { + dev_err(codec->dev, "wrong device ID. expected: %u read: %u\n", + TAS5720_DEVICE_ID, device_id); + ret = -ENODEV; + goto probe_fail; + } + + /* Set device to mute */ + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, + TAS5720_MUTE, TAS5720_MUTE); + if (ret < 0) + goto error_snd_soc_update_bits; + + /* + * Enter shutdown mode - our default when not playing audio - to + * minimize current consumption. On the TAS5720 there is no real down + * side doing so as all device registers are preserved and the wakeup + * of the codec is rather quick which we do using a dapm widget. + */ + ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, + TAS5720_SDZ, 0); + if (ret < 0) + goto error_snd_soc_update_bits; + + INIT_DELAYED_WORK(&tas5720->fault_check_work, tas5720_fault_check_work); + + return 0; + +error_snd_soc_update_bits: + dev_err(codec->dev, "error configuring device registers: %d\n", ret); + +probe_fail: + regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), + tas5720->supplies); + return ret; +} + +static int tas5720_codec_remove(struct snd_soc_codec *codec) +{ + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); + int ret; + + cancel_delayed_work_sync(&tas5720->fault_check_work); + + ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), + tas5720->supplies); + if (ret < 0) + dev_err(codec->dev, "failed to disable supplies: %d\n", ret); + + return ret; +}; + +static int tas5720_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); + int ret; + + if (event & SND_SOC_DAPM_POST_PMU) { + /* Take TAS5720 out of shutdown mode */ + ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, + TAS5720_SDZ, TAS5720_SDZ); + if (ret < 0) { + dev_err(codec->dev, "error waking codec: %d\n", ret); + return ret; + } + + /* + * Observe codec shutdown-to-active time. The datasheet only + * lists a nominal value however just use-it as-is without + * additional padding to minimize the delay introduced in + * starting to play audio (actually there is other setup done + * by the ASoC framework that will provide additional delays, + * so we should always be safe). + */ + msleep(25); + + /* Turn on TAS5720 periodic fault checking/handling */ + tas5720->last_fault = 0; + schedule_delayed_work(&tas5720->fault_check_work, + msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL)); + } else if (event & SND_SOC_DAPM_PRE_PMD) { + /* Disable TAS5720 periodic fault checking/handling */ + cancel_delayed_work_sync(&tas5720->fault_check_work); + + /* Place TAS5720 in shutdown mode to minimize current draw */ + ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, + TAS5720_SDZ, 0); + if (ret < 0) { + dev_err(codec->dev, "error shutting down codec: %d\n", + ret); + return ret; + } + } + + return 0; +} + +#ifdef CONFIG_PM +static int tas5720_suspend(struct snd_soc_codec *codec) +{ + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); + int ret; + + regcache_cache_only(tas5720->regmap, true); + regcache_mark_dirty(tas5720->regmap); + + ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), + tas5720->supplies); + if (ret < 0) + dev_err(codec->dev, "failed to disable supplies: %d\n", ret); + + return ret; +} + +static int tas5720_resume(struct snd_soc_codec *codec) +{ + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), + tas5720->supplies); + if (ret < 0) { + dev_err(codec->dev, "failed to enable supplies: %d\n", ret); + return ret; + } + + regcache_cache_only(tas5720->regmap, false); + + ret = regcache_sync(tas5720->regmap); + if (ret < 0) { + dev_err(codec->dev, "failed to sync regcache: %d\n", ret); + return ret; + } + + return 0; +} +#else +#define tas5720_suspend NULL +#define tas5720_resume NULL +#endif + +static bool tas5720_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TAS5720_DEVICE_ID_REG: + case TAS5720_FAULT_REG: + return true; + default: + return false; + } +} + +static const struct regmap_config tas5720_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = TAS5720_MAX_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = tas5720_is_volatile_reg, +}; + +/* + * DAC analog gain. There are four discrete values to select from, ranging + * from 19.2 dB to 26.3dB. + */ +static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, + 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0), + 0x1, 0x1, TLV_DB_SCALE_ITEM(2070, 0, 0), + 0x2, 0x2, TLV_DB_SCALE_ITEM(2350, 0, 0), + 0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0), +); + +/* + * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that + * setting the gain below -100 dB (register value <0x7) is effectively a MUTE + * as per device datasheet. + */ +static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0); + +static const struct snd_kcontrol_new tas5720_snd_controls[] = { + SOC_SINGLE_TLV("Speaker Driver Playback Volume", + TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, dac_tlv), + SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, + TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), +}; + +static const struct snd_soc_dapm_widget tas5720_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas5720_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUTPUT("OUT") +}; + +static const struct snd_soc_dapm_route tas5720_audio_map[] = { + { "DAC", NULL, "DAC IN" }, + { "OUT", NULL, "DAC" }, +}; + +static struct snd_soc_codec_driver soc_codec_dev_tas5720 = { + .probe = tas5720_codec_probe, + .remove = tas5720_codec_remove, + .suspend = tas5720_suspend, + .resume = tas5720_resume, + + .controls = tas5720_snd_controls, + .num_controls = ARRAY_SIZE(tas5720_snd_controls), + .dapm_widgets = tas5720_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), + .dapm_routes = tas5720_audio_map, + .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), +}; + +/* PCM rates supported by the TAS5720 driver */ +#define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) + +/* Formats supported by TAS5720 driver */ +#define TAS5720_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) + +static struct snd_soc_dai_ops tas5720_speaker_dai_ops = { + .hw_params = tas5720_hw_params, + .set_fmt = tas5720_set_dai_fmt, + .set_tdm_slot = tas5720_set_dai_tdm_slot, + .digital_mute = tas5720_mute, +}; + +/* + * TAS5720 DAI structure + * + * Note that were are advertising .playback.channels_max = 2 despite this being + * a mono amplifier. The reason for that is that some serial ports such as TI's + * McASP module have a minimum number of channels (2) that they can output. + * Advertising more channels than we have will allow us to interface with such + * a serial port without really any negative side effects as the TAS5720 will + * simply ignore any extra channel(s) asides from the one channel that is + * configured to be played back. + */ +static struct snd_soc_dai_driver tas5720_dai[] = { + { + .name = "tas5720-amplifier", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAS5720_RATES, + .formats = TAS5720_FORMATS, + }, + .ops = &tas5720_speaker_dai_ops, + }, +}; + +static int tas5720_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct tas5720_data *data; + int ret; + int i; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->tas5720_client = client; + data->regmap = devm_regmap_init_i2c(client, &tas5720_regmap_config); + if (IS_ERR(data->regmap)) { + ret = PTR_ERR(data->regmap); + dev_err(dev, "failed to allocate register map: %d\n", ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(data->supplies); i++) + data->supplies[i].supply = tas5720_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), + data->supplies); + if (ret != 0) { + dev_err(dev, "failed to request supplies: %d\n", ret); + return ret; + } + + dev_set_drvdata(dev, data); + + ret = snd_soc_register_codec(&client->dev, + &soc_codec_dev_tas5720, + tas5720_dai, ARRAY_SIZE(tas5720_dai)); + if (ret < 0) { + dev_err(dev, "failed to register codec: %d\n", ret); + return ret; + } + + return 0; +} + +static int tas5720_remove(struct i2c_client *client) +{ + struct device *dev = &client->dev; + + snd_soc_unregister_codec(dev); + + return 0; +} + +static const struct i2c_device_id tas5720_id[] = { + { "tas5720", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tas5720_id); + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id tas5720_of_match[] = { + { .compatible = "ti,tas5720", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tas5720_of_match); +#endif + +static struct i2c_driver tas5720_i2c_driver = { + .driver = { + .name = "tas5720", + .of_match_table = of_match_ptr(tas5720_of_match), + }, + .probe = tas5720_probe, + .remove = tas5720_remove, + .id_table = tas5720_id, +}; + +module_i2c_driver(tas5720_i2c_driver); + +MODULE_AUTHOR("Andreas Dannenberg "); +MODULE_DESCRIPTION("TAS5720 Audio amplifier driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tas5720.h b/sound/soc/codecs/tas5720.h new file mode 100644 index 000000000000..3d077c779b12 --- /dev/null +++ b/sound/soc/codecs/tas5720.h @@ -0,0 +1,90 @@ +/* + * tas5720.h - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier + * + * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Andreas Dannenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __TAS5720_H__ +#define __TAS5720_H__ + +/* Register Address Map */ +#define TAS5720_DEVICE_ID_REG 0x00 +#define TAS5720_POWER_CTRL_REG 0x01 +#define TAS5720_DIGITAL_CTRL1_REG 0x02 +#define TAS5720_DIGITAL_CTRL2_REG 0x03 +#define TAS5720_VOLUME_CTRL_REG 0x04 +#define TAS5720_ANALOG_CTRL_REG 0x06 +#define TAS5720_FAULT_REG 0x08 +#define TAS5720_DIGITAL_CLIP2_REG 0x10 +#define TAS5720_DIGITAL_CLIP1_REG 0x11 +#define TAS5720_MAX_REG TAS5720_DIGITAL_CLIP1_REG + +/* TAS5720_DEVICE_ID_REG */ +#define TAS5720_DEVICE_ID 0x01 + +/* TAS5720_POWER_CTRL_REG */ +#define TAS5720_DIG_CLIP_MASK GENMASK(7, 2) +#define TAS5720_SLEEP BIT(1) +#define TAS5720_SDZ BIT(0) + +/* TAS5720_DIGITAL_CTRL1_REG */ +#define TAS5720_HPF_BYPASS BIT(7) +#define TAS5720_TDM_CFG_SRC BIT(6) +#define TAS5720_SSZ_DS BIT(3) +#define TAS5720_SAIF_RIGHTJ_24BIT (0x0) +#define TAS5720_SAIF_RIGHTJ_20BIT (0x1) +#define TAS5720_SAIF_RIGHTJ_18BIT (0x2) +#define TAS5720_SAIF_RIGHTJ_16BIT (0x3) +#define TAS5720_SAIF_I2S (0x4) +#define TAS5720_SAIF_LEFTJ (0x5) +#define TAS5720_SAIF_FORMAT_MASK GENMASK(2, 0) + +/* TAS5720_DIGITAL_CTRL2_REG */ +#define TAS5720_MUTE BIT(4) +#define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0) + +/* TAS5720_ANALOG_CTRL_REG */ +#define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4) +#define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4) +#define TAS5720_PWM_RATE_10_5_FSYNC (0x2 << 4) +#define TAS5720_PWM_RATE_12_6_FSYNC (0x3 << 4) +#define TAS5720_PWM_RATE_14_7_FSYNC (0x4 << 4) +#define TAS5720_PWM_RATE_16_8_FSYNC (0x5 << 4) +#define TAS5720_PWM_RATE_20_10_FSYNC (0x6 << 4) +#define TAS5720_PWM_RATE_24_12_FSYNC (0x7 << 4) +#define TAS5720_PWM_RATE_MASK GENMASK(6, 4) +#define TAS5720_ANALOG_GAIN_19_2DBV (0x0 << 2) +#define TAS5720_ANALOG_GAIN_20_7DBV (0x1 << 2) +#define TAS5720_ANALOG_GAIN_23_5DBV (0x2 << 2) +#define TAS5720_ANALOG_GAIN_26_3DBV (0x3 << 2) +#define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2) +#define TAS5720_ANALOG_GAIN_SHIFT (0x2) + +/* TAS5720_FAULT_REG */ +#define TAS5720_OC_THRESH_100PCT (0x0 << 4) +#define TAS5720_OC_THRESH_75PCT (0x1 << 4) +#define TAS5720_OC_THRESH_50PCT (0x2 << 4) +#define TAS5720_OC_THRESH_25PCT (0x3 << 4) +#define TAS5720_OC_THRESH_MASK GENMASK(5, 4) +#define TAS5720_CLKE BIT(3) +#define TAS5720_OCE BIT(2) +#define TAS5720_DCE BIT(1) +#define TAS5720_OTE BIT(0) +#define TAS5720_FAULT_MASK GENMASK(3, 0) + +/* TAS5720_DIGITAL_CLIP1_REG */ +#define TAS5720_CLIP1_MASK GENMASK(7, 2) +#define TAS5720_CLIP1_SHIFT (0x2) + +#endif /* __TAS5720_H__ */ -- GitLab From 7b01cff5ccc3cd6c366ab9040d789e3e5e2debb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Mar 2016 23:24:18 +0100 Subject: [PATCH 4796/9938] arm64: dts: marvell: Clean up armada-3720-db MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of duplicating the SoC's node hierarchy, including a bus node named "internal-regs", reference the actually desired nodes by label, like Berlin already does. Add labels where necessary. Drop an inconsistent white line while at it. Cc: Gregory CLEMENT Signed-off-by: Andreas Färber Signed-off-by: Gregory CLEMENT [gregory.clement@free-electrons.com: drop Fixes tag as it is not a bug fix.] --- .../arm64/boot/dts/marvell/armada-3720-db.dts | 32 +++++++------------ arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 - arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 4 +-- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts index 359050154511..86110a6ae330 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts @@ -60,27 +60,19 @@ device_type = "memory"; reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; +}; - soc { - internal-regs { - /* - * Exported on the micro USB connector CON32 - * through an FTDI - */ - uart0: serial@12000 { - status = "okay"; - }; - - /* CON31 */ - usb3@58000 { - status = "okay"; - }; +/* CON3 */ +&sata { + status = "okay"; +}; - /* CON3 */ - sata@e0000 { - status = "okay"; - }; - }; - }; +/* Exported on the micro USB connector CON32 through an FTDI */ +&uart0 { + status = "okay"; }; +/* CON31 */ +&usb3 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/marvell/armada-372x.dtsi b/arch/arm64/boot/dts/marvell/armada-372x.dtsi index f292a00ce97c..5120296596c2 100644 --- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi @@ -59,5 +59,4 @@ enable-method = "psci"; }; }; - }; diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi index ba9df7ff2a72..4328c2408a8a 100644 --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi @@ -105,14 +105,14 @@ status = "disabled"; }; - usb3@58000 { + usb3: usb3@58000 { compatible = "generic-xhci"; reg = <0x58000 0x4000>; interrupts = ; status = "disabled"; }; - sata@e0000 { + sata: sata@e0000 { compatible = "marvell,armada-3700-ahci"; reg = <0xe0000 0x2000>; interrupts = ; -- GitLab From cc2684c449a4f637cb9f978f66747e5dc8ae9f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 23 Mar 2016 23:24:19 +0100 Subject: [PATCH 4797/9938] arm64: dts: marvell: Rename armada-37xx USB node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to reflect the USB version in the node name. Cc: Gregory CLEMENT Signed-off-by: Andreas Färber Signed-off-by: Gregory CLEMENT [gregory.clement@free-electrons.com: drop Fixes tag as it is not a bug fix.] --- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi index 4328c2408a8a..55a861d60fae 100644 --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi @@ -105,7 +105,7 @@ status = "disabled"; }; - usb3: usb3@58000 { + usb3: usb@58000 { compatible = "generic-xhci"; reg = <0x58000 0x4000>; interrupts = ; -- GitLab From 150fa1128438746280d9d9b403f0a42883a0e70c Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 27 Apr 2016 15:36:42 +0200 Subject: [PATCH 4798/9938] arm64: dts: marvell: Use a SoC-specific compatible for xHCI on Armada37xx Even if the Armada 37xx does not any specific setup, the device tree binding documentation requires to use a SoC-specific version corresponding to the platform first followed by the generic version. This patch introduce this new compatible string and updates the documentation accordingly. Signed-off-by: Gregory CLEMENT --- Documentation/devicetree/bindings/usb/usb-xhci.txt | 1 + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt index 6a17aa85c4d5..966885c636d0 100644 --- a/Documentation/devicetree/bindings/usb/usb-xhci.txt +++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt @@ -4,6 +4,7 @@ Required properties: - compatible: should be one or more of - "generic-xhci" for generic XHCI device + - "marvell,armada3700-xhci" for Armada 37xx SoCs - "marvell,armada-375-xhci" for Armada 375 SoCs - "marvell,armada-380-xhci" for Armada 38x SoCs - "renesas,xhci-r8a7790" for r8a7790 SoC diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi index 55a861d60fae..1d4fb4d27787 100644 --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi @@ -106,7 +106,8 @@ }; usb3: usb@58000 { - compatible = "generic-xhci"; + compatible = "marvell,armada3700-xhci", + "generic-xhci"; reg = <0x58000 0x4000>; interrupts = ; status = "disabled"; -- GitLab From 129d7cf98f5c739014ae5aa0311e48f6a64b0758 Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Tue, 26 Apr 2016 16:54:04 +0200 Subject: [PATCH 4799/9938] regulator: rk808: Add rk808_reg_ops_ranges for LDO3 LDO_REG3 descriptor is using linear_ranges. Add and use proper ops for LDO_REG3. Signed-off-by: Wadim Egorov Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 30 ++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 67f72feed815..6601ab5fcc2d 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -238,6 +238,21 @@ static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv) sel); } +static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) +{ + unsigned int reg; + int sel = regulator_map_voltage_linear_range(rdev, uv, uv); + + if (sel < 0) + return -EINVAL; + + reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->vsel_mask, + sel); +} + static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; @@ -288,6 +303,19 @@ static struct regulator_ops rk808_reg_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; +static struct regulator_ops rk808_reg_ops_ranges = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_voltage = rk808_set_suspend_voltage_range, + .set_suspend_enable = rk808_set_suspend_enable, + .set_suspend_disable = rk808_set_suspend_disable, +}; + static struct regulator_ops rk808_switch_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -383,7 +411,7 @@ static const struct regulator_desc rk808_reg[] = { .name = "LDO_REG3", .supply_name = "vcc7", .id = RK808_ID_LDO3, - .ops = &rk808_reg_ops, + .ops = &rk808_reg_ops_ranges, .type = REGULATOR_VOLTAGE, .n_voltages = 16, .linear_ranges = rk808_ldo3_voltage_ranges, -- GitLab From 7de76b621f77aba456f594e4621eca2e94a146f3 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Wed, 27 Apr 2016 14:52:38 +0800 Subject: [PATCH 4800/9938] ASoC: topology: Check failure to create a widget Stop loading topology info if error happens when creating a widget. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index ca5f82885031..0224a6458f3b 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1500,9 +1500,11 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, for (i = 0; i < count; i++) { widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; ret = soc_tplg_dapm_widget_create(tplg, widget); - if (ret < 0) + if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to load widget %s\n", widget->name); + return ret; + } } return 0; -- GitLab From 06eb49f72fa57f5a49acdf9f4af84d2d326513b3 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Wed, 27 Apr 2016 14:52:56 +0800 Subject: [PATCH 4801/9938] ASoC: topology: Check size mismatch of ABI objects before parsing If size mismatch of manifest, ABI headers or elements is found, stop parsing topology info and return the error. New fields may be append to the tail of ABI objects which will cause object size to increase. If user space and kernel use different versions of ABI, size mismatch will be detected here. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 0224a6458f3b..29ae3d3a0f8a 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1023,6 +1023,11 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; + if (control_hdr->size != sizeof(*control_hdr)) { + dev_err(tplg->dev, "ASoC: invalid control size\n"); + return -EINVAL; + } + switch (control_hdr->ops.info) { case SND_SOC_TPLG_CTL_VOLSW: case SND_SOC_TPLG_CTL_STROBE: @@ -1499,6 +1504,11 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, for (i = 0; i < count; i++) { widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; + if (widget->size != sizeof(*widget)) { + dev_err(tplg->dev, "ASoC: invalid widget size\n"); + return -EINVAL; + } + ret = soc_tplg_dapm_widget_create(tplg, widget); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to load widget %s\n", @@ -1652,8 +1662,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) return 0; - pcm = (struct snd_soc_tplg_pcm *)tplg->pos; - if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_pcm), count, hdr->payload_size, "PCM DAI")) { @@ -1663,7 +1671,13 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, } /* create the FE DAIs and DAI links */ + pcm = (struct snd_soc_tplg_pcm *)tplg->pos; for (i = 0; i < count; i++) { + if (pcm->size != sizeof(*pcm)) { + dev_err(tplg->dev, "ASoC: invalid pcm size\n"); + return -EINVAL; + } + soc_tplg_pcm_create(tplg, pcm); pcm++; } @@ -1683,6 +1697,11 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, return 0; manifest = (struct snd_soc_tplg_manifest *)tplg->pos; + if (manifest->size != sizeof(*manifest)) { + dev_err(tplg->dev, "ASoC: invalid manifest size\n"); + return -EINVAL; + } + tplg->pos += sizeof(struct snd_soc_tplg_manifest); if (tplg->comp && tplg->ops && tplg->ops->manifest) @@ -1699,6 +1718,14 @@ static int soc_valid_header(struct soc_tplg *tplg, if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) return 0; + if (hdr->size != sizeof(*hdr)) { + dev_err(tplg->dev, + "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n", + hdr->type, soc_tplg_get_hdr_offset(tplg), + tplg->fw->size); + return -EINVAL; + } + /* big endian firmware objects not supported atm */ if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) { dev_err(tplg->dev, -- GitLab From 73fe01cfb3babff01748a9fbc95cc3ea2079cc7f Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Wed, 27 Apr 2016 15:26:51 +0200 Subject: [PATCH 4802/9938] ASoC: dmaengine_pcm: Add support for packed transfers dmaengine_pcm currently only supports setups where FIFO reads/writes correspond to exactly one sample, eg 16-bit sample data is transferred via 16-bit FIFO accesses, 32-bit data via 32-bit accesses. This patch adds support for setups with fixed width FIFOs where multiple samples are packed into a larger word. For example setups with a 32-bit wide FIFO register that expect 16-bit sample transfers to be done with the left+right sample data packed into a 32-bit word. Support for packed transfers is controlled via the SND_DMAENGINE_PCM_DAI_FLAG_PACK flag in snd_dmaengine_dai_dma_data.flags If this flag is set dmaengine_pcm doesn't put any restriction on the supported formats and sets the DMA transfer width to undefined. This means control over the constraints is now transferred to the DAI driver and it's responsible to provide proper configuration and check for possible corner cases that aren't handled by the ALSA core. Signed-off-by: Matthias Reichl Acked-by: Lars-Peter Clausen Tested-by: Martin Sperl Signed-off-by: Mark Brown --- include/sound/dmaengine_pcm.h | 12 ++++++ sound/core/pcm_dmaengine.c | 11 +++++- sound/soc/soc-generic-dmaengine-pcm.c | 57 ++++++++++++++++----------- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index f86ef5ea9b01..67be2445941a 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -51,6 +51,16 @@ struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, void *filter_data); struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + /** * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data * @addr: Address of the DAI data source or destination register. @@ -63,6 +73,7 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) * requesting the DMA channel. * @chan_name: Custom channel name to use when requesting DMA channel. * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now */ struct snd_dmaengine_dai_dma_data { dma_addr_t addr; @@ -72,6 +83,7 @@ struct snd_dmaengine_dai_dma_data { void *filter_data; const char *chan_name; unsigned int fifo_size; + unsigned int flags; }; void snd_dmaengine_pcm_set_config_from_dai_data( diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 697c166acf05..8eb58c709b14 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -106,8 +106,9 @@ EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); * direction of the substream. If the substream is a playback stream the dst * fields will be initialized, if it is a capture stream the src fields will be * initialized. The {dst,src}_addr_width field will only be initialized if the - * addr_width field of the DAI DMA data struct is not equal to - * DMA_SLAVE_BUSWIDTH_UNDEFINED. + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. */ void snd_dmaengine_pcm_set_config_from_dai_data( const struct snd_pcm_substream *substream, @@ -117,11 +118,17 @@ void snd_dmaengine_pcm_set_config_from_dai_data( if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { slave_config->dst_addr = dma_data->addr; slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) slave_config->dst_addr_width = dma_data->addr_width; } else { slave_config->src_addr = dma_data->addr; slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) slave_config->src_addr_width = dma_data->addr_width; } diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 6fd1906af387..6cef3977507a 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -163,31 +163,42 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea } /* - * Prepare formats mask for valid/allowed sample types. If the dma does - * not have support for the given physical word size, it needs to be - * masked out so user space can not use the format which produces - * corrupted audio. - * In case the dma driver does not implement the slave_caps the default - * assumption is that it supports 1, 2 and 4 bytes widths. + * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep + * hw.formats set to 0, meaning no restrictions are in place. + * In this case it's the responsibility of the DAI driver to + * provide the supported format information. */ - for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { - int bits = snd_pcm_format_physical_width(i); - - /* Enable only samples with DMA supported physical widths */ - switch (bits) { - case 8: - case 16: - case 24: - case 32: - case 64: - if (addr_widths & (1 << (bits / 8))) - hw.formats |= (1LL << i); - break; - default: - /* Unsupported types */ - break; + if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) + /* + * Prepare formats mask for valid/allowed sample types. If the + * dma does not have support for the given physical word size, + * it needs to be masked out so user space can not use the + * format which produces corrupted audio. + * In case the dma driver does not implement the slave_caps the + * default assumption is that it supports 1, 2 and 4 bytes + * widths. + */ + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + int bits = snd_pcm_format_physical_width(i); + + /* + * Enable only samples with DMA supported physical + * widths + */ + switch (bits) { + case 8: + case 16: + case 24: + case 32: + case 64: + if (addr_widths & (1 << (bits / 8))) + hw.formats |= (1LL << i); + break; + default: + /* Unsupported types */ + break; + } } - } return snd_soc_set_runtime_hwparams(substream, &hw); } -- GitLab From beff053c0ef6983897e3481169292e6435ef0a2d Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Wed, 27 Apr 2016 15:26:52 +0200 Subject: [PATCH 4803/9938] ASoC: bcm2835: Add S16_LE support via packed DMA transfers The bcm2835-i2s driver already has support for the S16_LE format but that format hasn't been made available because dmaengine_pcm didn't support packed data transfers. bcm2835-i2s needs 16-bit left+right channel data to be packed into a 32-bit word, the FIFO register is 32-bit only and doesn't support 16-bit access. Now that dmaengine_pcm supports packed transfers the format can be made available by setting the SND_DMAENGINE_PCM_DAI_FLAG_PACK flag. No further configuration is necessary: - snd_dmaengine_dai_dma_data.addr_width is already set to DMA_SLAVE_BUSWIDTH_4_BYTES to force 32-bit DMA transfers - dmaengine_pcm will pick up the S16_LE format from the DAI configuration and make it available since it's no longer masked out due to the PACK flag. - there are no further corner cases to catch in hw_params, since the channel count is fixed at 2 we always have two 16-bit stereo samples that can be transferred via 32-bit DMA Signed-off-by: Matthias Reichl Tested-by: Martin Sperl Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index a0026e2d2f0a..6ba20498202e 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -690,6 +690,15 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; + /* + * Set the PACK flag to enable S16_LE support (2 S16_LE values + * packed into 32-bit transfers). + */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].flags = + SND_DMAENGINE_PCM_DAI_FLAG_PACK; + dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].flags = + SND_DMAENGINE_PCM_DAI_FLAG_PACK; + /* BCLK ratio - use default */ dev->bclk_ratio = 0; -- GitLab From 714749313da9800ecc10bfc2bfab87540a349e97 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 27 Apr 2016 09:40:09 -0700 Subject: [PATCH 4804/9938] ARM: omap2plus_defconfig: Enable PWM and ir-rx51 as loadable modules These are available on n900. Reviewed-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 5bd5d364b5fd..ac717cccd2b5 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -284,8 +284,12 @@ CONFIG_REGULATOR_TPS65910=y CONFIG_REGULATOR_TWL4030=y CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_LIRC=m +CONFIG_RC_DEVICES=y +CONFIG_IR_RX51=m CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_VIDEO_OMAP3=m # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set @@ -422,6 +426,7 @@ CONFIG_TI_EMIF=m CONFIG_IIO=m CONFIG_TI_AM335X_ADC=m CONFIG_PWM=y +CONFIG_PWM_OMAP_DMTIMER=m CONFIG_PWM_TIECAP=m CONFIG_PWM_TIEHRPWM=m CONFIG_PWM_TWL=m -- GitLab From 570d8e9398011a63590c281a36cdce311196608e Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 27 Apr 2016 17:53:08 +0200 Subject: [PATCH 4805/9938] taskstats: fix nl parsing in accounting/getdelays.c The type TASKSTATS_TYPE_NULL should always be ignored. When jumping to the next attribute, only the length of the current attribute should be added, not the length of all nested attributes. This last bug was not visible before commit 80df554275c2, because the kernel didn't put more than two nested attributes. Fixes: a3baf649ca9c ("[PATCH] per-task-delay-accounting: documentation") Fixes: 80df554275c2 ("taskstats: use the libnl API to align nlattr on 64-bit") Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- Documentation/accounting/getdelays.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c index 7785fb5eb93f..b5ca536e56a8 100644 --- a/Documentation/accounting/getdelays.c +++ b/Documentation/accounting/getdelays.c @@ -505,6 +505,8 @@ int main(int argc, char *argv[]) if (!loop) goto done; break; + case TASKSTATS_TYPE_NULL: + break; default: fprintf(stderr, "Unknown nested" " nla_type %d\n", @@ -512,7 +514,8 @@ int main(int argc, char *argv[]) break; } len2 += NLA_ALIGN(na->nla_len); - na = (struct nlattr *) ((char *) na + len2); + na = (struct nlattr *)((char *)na + + NLA_ALIGN(na->nla_len)); } break; -- GitLab From fe600cf6424ff45712a175351b11c3ff1206ff2c Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 27 Apr 2016 11:44:39 +0200 Subject: [PATCH 4806/9938] i2c: octeon: Add workaround for broken irqs on CN3860 CN3860 does not interrupt the CPU when the i2c status changes. If we get a timeout, and see the status has in fact changed, we know we have this problem, and drop back to polling. Signed-off-by: David Daney Signed-off-by: Jan Glauber Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-octeon.c | 53 +++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index cb418140cbbe..aa5f01efd826 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -121,6 +121,8 @@ struct octeon_i2c { void __iomem *twsi_base; struct device *dev; bool hlc_enabled; + bool broken_irq_mode; + bool broken_irq_check; void (*int_enable)(struct octeon_i2c *); void (*int_disable)(struct octeon_i2c *); void (*hlc_int_enable)(struct octeon_i2c *); @@ -375,10 +377,32 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) long time_left; bool first = 1; + /* + * Some chip revisions don't assert the irq in the interrupt + * controller. So we must poll for the IFLG change. + */ + if (i2c->broken_irq_mode) { + u64 end = get_jiffies_64() + i2c->adap.timeout; + + while (!octeon_i2c_test_iflg(i2c) && + time_before64(get_jiffies_64(), end)) + usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT); + + return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT; + } + i2c->int_enable(i2c); time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first), i2c->adap.timeout); i2c->int_disable(i2c); + + if (i2c->broken_irq_check && !time_left && + octeon_i2c_test_iflg(i2c)) { + dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n"); + i2c->broken_irq_mode = true; + return 0; + } + if (!time_left) return -ETIMEDOUT; @@ -492,15 +516,37 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c) bool first = 1; int time_left; + /* + * Some cn38xx boards don't assert the irq in the interrupt + * controller. So we must poll for the valid bit change. + */ + if (i2c->broken_irq_mode) { + u64 end = get_jiffies_64() + i2c->adap.timeout; + + while (!octeon_i2c_hlc_test_valid(i2c) && + time_before64(get_jiffies_64(), end)) + usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT); + + return octeon_i2c_hlc_test_valid(i2c) ? 0 : -ETIMEDOUT; + } + i2c->hlc_int_enable(i2c); time_left = wait_event_timeout(i2c->queue, octeon_i2c_hlc_test_ready(i2c, &first), i2c->adap.timeout); i2c->hlc_int_disable(i2c); - if (!time_left) { + if (!time_left) octeon_i2c_hlc_int_clear(i2c); - return -ETIMEDOUT; + + if (i2c->broken_irq_check && !time_left && + octeon_i2c_hlc_test_valid(i2c)) { + dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n"); + i2c->broken_irq_mode = true; + return 0; } + + if (!time_left) + return -ETIMEDOUT; return 0; } @@ -1143,6 +1189,9 @@ static int octeon_i2c_probe(struct platform_device *pdev) goto out; } + if (OCTEON_IS_MODEL(OCTEON_CN38XX)) + i2c->broken_irq_check = true; + result = octeon_i2c_init_lowlevel(i2c); if (result) { dev_err(i2c->dev, "init low level failed\n"); -- GitLab From 05872b8039101867e7312c6c3a560b887b2d9079 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 22 Apr 2016 15:19:51 +0200 Subject: [PATCH 4807/9938] i2c: mv64xxx: enable the driver on ARCH_MVEBU The new ARM64 Marvell Armada 7K/8K SoC family is using the same I2C controller as the 32-bits Marvell EBU SoCs, so this commit allows mv64xxx to be enabled when ARCH_MVEBU=y. Signed-off-by: Thomas Petazzoni Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index faa8e6821fea..29664338aab1 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -663,7 +663,7 @@ config I2C_MT65XX config I2C_MV64XXX tristate "Marvell mv64xxx I2C Controller" - depends on MV64X60 || PLAT_ORION || ARCH_SUNXI + depends on MV64X60 || PLAT_ORION || ARCH_SUNXI || ARCH_MVEBU help If you say yes to this option, support will be included for the built-in I2C interface on the Marvell 64xxx line of host bridges. -- GitLab From 9f4d6f164229d4221272186597d9393f654adbb9 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 22 Apr 2016 15:19:52 +0200 Subject: [PATCH 4808/9938] i2c: mv64xxx: handle probe deferral for the clock If a clock is registered by a platform driver and not by the OF_CLK_DECLARE() mechanism, it might show up after the first attempt to probe i2c-mv64xxx. In order to solve this, we need to handle -EPROBE_PREFER as a special return value of devm_clk_get(), and return the same error code from probe(). This gives us three situations: - There is no reference to a clock in the DT. In this case, devm_clk_get() returns an error that is not -EPROBE_DEFER (something like -ENODEV), and we continue the probing without enabling the clock. - There is a reference to the clock in the DT, and the clock is ready. devm_clk_get() returns a valid reference to the clock, and we prepare/enable it. - There is a reference to the clock in the DT, but the clock is not ready. devm_clk_get() returns -EPROBE_DEFER, and we exit from probe() with the same error code so that probe() is tried again later. This is needed for Marvell Armada 7K/8K, where the clock driver is a platform driver. Signed-off-by: Thomas Petazzoni Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mv64xxx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 43207f52e5a3..4c6282a78109 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -910,6 +910,8 @@ mv64xxx_i2c_probe(struct platform_device *pd) #if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ drv_data->clk = devm_clk_get(&pd->dev, NULL); + if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; if (!IS_ERR(drv_data->clk)) { clk_prepare(drv_data->clk); clk_enable(drv_data->clk); -- GitLab From 70719350ca250a8397b74f416a45df3d1868a1d2 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 22 Apr 2016 15:19:53 +0200 Subject: [PATCH 4809/9938] i2c: mv64xxx: use clk_{prepare_enable,disable_unprepare} Instead of separately calling clk_prepare()/clk_enable(), use clk_prepare_enable(), and instead of calling clk_disable()/clk_unprepare(), use clk_disable_unprepare(). Those handy shortcuts have been introduced specifically to simplify the numerous call sites were both functions were called in sequence. Signed-off-by: Thomas Petazzoni Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mv64xxx.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 4c6282a78109..e87db0344708 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -912,10 +912,8 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->clk = devm_clk_get(&pd->dev, NULL); if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER) return -EPROBE_DEFER; - if (!IS_ERR(drv_data->clk)) { - clk_prepare(drv_data->clk); - clk_enable(drv_data->clk); - } + if (!IS_ERR(drv_data->clk)) + clk_prepare_enable(drv_data->clk); #endif if (pdata) { drv_data->freq_m = pdata->freq_m; @@ -968,10 +966,8 @@ mv64xxx_i2c_probe(struct platform_device *pd) exit_clk: #if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ - if (!IS_ERR(drv_data->clk)) { - clk_disable(drv_data->clk); - clk_unprepare(drv_data->clk); - } + if (!IS_ERR(drv_data->clk)) + clk_disable_unprepare(drv_data->clk); #endif return rc; } @@ -987,10 +983,8 @@ mv64xxx_i2c_remove(struct platform_device *dev) reset_control_assert(drv_data->rstc); #if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ - if (!IS_ERR(drv_data->clk)) { - clk_disable(drv_data->clk); - clk_unprepare(drv_data->clk); - } + if (!IS_ERR(drv_data->clk)) + clk_disable_unprepare(drv_data->clk); #endif return 0; -- GitLab From f3a36fbdd359608bf73d674533cc419bf7e65aae Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 22 Apr 2016 15:19:54 +0200 Subject: [PATCH 4810/9938] i2c: mv64xxx: remove CONFIG_HAVE_CLK conditionals When clock support was added to the i2c-mv64xxx, not all clk functions had stubs when for !CONFIG_HAVE_CLK configurations. However, nowadays, both "struct clk" and all the clock framework functions have stubs when CONFIG_HAVE_CLK is not enabled, so it no longer makes sense to carry such compile-time conditionals in the driver. This commit was compile tested on both ARM64 (which has both CONFIG_OF=y and CONFIG_HAVE_CLK=y) and PowerPC c2k_defconfig (which has CONFIG_OF=y, CONFIG_HAVE_CLK disabled, and the i2c-mv64xxx driver enabled). The only non-trivial change is in the mv64xxx_of_config() function, which was returning -ENODEV unconditionally if CONFIG_HAVE_CLK was disabled. Simply removing this condition works fine because the first test done by the function is to verify if drv_data->clk points to a valid clock, and if it doesn't, we return -ENODEV. When CONFIG_HAVE_CLK is disabled, devm_clk_get() unconditionally returns NULL, so mv64xxx_of_config() will return -ENODEV when no clock is provided, which is the intended behavior. Signed-off-by: Thomas Petazzoni Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mv64xxx.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index e87db0344708..b4dec0841bc2 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -134,9 +134,7 @@ struct mv64xxx_i2c_data { int rc; u32 freq_m; u32 freq_n; -#if defined(CONFIG_HAVE_CLK) struct clk *clk; -#endif wait_queue_head_t waitq; spinlock_t lock; struct i2c_msg *msg; @@ -757,7 +755,6 @@ static const struct of_device_id mv64xxx_i2c_of_match_table[] = { MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); #ifdef CONFIG_OF -#ifdef CONFIG_HAVE_CLK static int mv64xxx_calc_freq(struct mv64xxx_i2c_data *drv_data, const int tclk, const int n, const int m) @@ -791,25 +788,20 @@ mv64xxx_find_baud_factors(struct mv64xxx_i2c_data *drv_data, return false; return true; } -#endif /* CONFIG_HAVE_CLK */ static int mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, struct device *dev) { - /* CLK is mandatory when using DT to describe the i2c bus. We - * need to know tclk in order to calculate bus clock - * factors. - */ -#if !defined(CONFIG_HAVE_CLK) - /* Have OF but no CLK */ - return -ENODEV; -#else const struct of_device_id *device; struct device_node *np = dev->of_node; u32 bus_freq, tclk; int rc = 0; + /* CLK is mandatory when using DT to describe the i2c bus. We + * need to know tclk in order to calculate bus clock + * factors. + */ if (IS_ERR(drv_data->clk)) { rc = -ENODEV; goto out; @@ -869,7 +861,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, out: return rc; -#endif } #else /* CONFIG_OF */ static int @@ -907,14 +898,13 @@ mv64xxx_i2c_probe(struct platform_device *pd) init_waitqueue_head(&drv_data->waitq); spin_lock_init(&drv_data->lock); -#if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ drv_data->clk = devm_clk_get(&pd->dev, NULL); if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER) return -EPROBE_DEFER; if (!IS_ERR(drv_data->clk)) clk_prepare_enable(drv_data->clk); -#endif + if (pdata) { drv_data->freq_m = pdata->freq_m; drv_data->freq_n = pdata->freq_n; @@ -964,11 +954,10 @@ mv64xxx_i2c_probe(struct platform_device *pd) if (!IS_ERR_OR_NULL(drv_data->rstc)) reset_control_assert(drv_data->rstc); exit_clk: -#if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ if (!IS_ERR(drv_data->clk)) clk_disable_unprepare(drv_data->clk); -#endif + return rc; } @@ -981,11 +970,9 @@ mv64xxx_i2c_remove(struct platform_device *dev) free_irq(drv_data->irq, drv_data); if (!IS_ERR_OR_NULL(drv_data->rstc)) reset_control_assert(drv_data->rstc); -#if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ if (!IS_ERR(drv_data->clk)) clk_disable_unprepare(drv_data->clk); -#endif return 0; } -- GitLab From 8a350183010a5557287a10c2a13b1a4cbaa7b130 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 21 Apr 2016 15:12:44 +0900 Subject: [PATCH 4811/9938] i2c: uniphier: add "\n" at the end of error log Just in case. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 2 +- drivers/i2c/busses/i2c-uniphier.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 213ba55e17c3..aeead0d27d10 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -524,7 +524,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "failed to get IRQ number"); + dev_err(dev, "failed to get IRQ number\n"); return irq; } diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index 89eaa8a7e1e0..475a5eb514e2 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -381,7 +381,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "failed to get IRQ number"); + dev_err(dev, "failed to get IRQ number\n"); return irq; } -- GitLab From ae9b9a9d3c480376b8225c212735fb298d7c799f Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Sun, 24 Apr 2016 21:54:51 +0800 Subject: [PATCH 4812/9938] MAINTAINERS: update my email address I've changed employer, update my email address to the new one. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1d5b4becab6f..a121f4605805 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4707,7 +4707,7 @@ F: include/linux/fscache*.h F2FS FILE SYSTEM M: Jaegeuk Kim M: Changman Lee -R: Chao Yu +R: Chao Yu L: linux-f2fs-devel@lists.sourceforge.net W: http://en.wikipedia.org/wiki/F2FS T: git git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git -- GitLab From 411963a6eb6258e3ee8a52bcb5b80af1be14f197 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Wed, 27 Apr 2016 15:54:50 +0800 Subject: [PATCH 4813/9938] dt-bindings: rockchip-dw-mshc: add description for rk3399 Add "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc" for dwmmc on rk3399 platform. Signed-off-by: Shawn Lin Signed-off-by: Jianqun Xu Acked-by: Rob Herring Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt index ea5614b6f613..07184e8f894e 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt @@ -15,6 +15,7 @@ Required Properties: - "rockchip,rk3288-dw-mshc": for Rockchip RK3288 - "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3036 - "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3368 + - "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399 Optional Properties: * clocks: from common clock binding: if ciu_drive and ciu_sample are -- GitLab From 8c14586fc320acfed8a0048eb21d1f2e2856fc36 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Sun, 24 Apr 2016 21:26:04 -0700 Subject: [PATCH 4814/9938] net: ipv6: Use passed in table for nexthop lookups Similar to 3bfd847203c6 ("net: Use passed in table for nexthop lookups") for IPv4, if the route spec contains a table id use that to lookup the next hop first and fall back to a full lookup if it fails (per the fix 4c9bcd117918b ("net: Fix nexthop lookups")). Example: root@kenny:~# ip -6 ro ls table red local 2100:1::1 dev lo proto none metric 0 pref medium 2100:1::/120 dev eth1 proto kernel metric 256 pref medium local 2100:2::1 dev lo proto none metric 0 pref medium 2100:2::/120 dev eth2 proto kernel metric 256 pref medium local fe80::e0:f9ff:fe09:3cac dev lo proto none metric 0 pref medium local fe80::e0:f9ff:fe1c:b974 dev lo proto none metric 0 pref medium fe80::/64 dev eth1 proto kernel metric 256 pref medium fe80::/64 dev eth2 proto kernel metric 256 pref medium ff00::/8 dev red metric 256 pref medium ff00::/8 dev eth1 metric 256 pref medium ff00::/8 dev eth2 metric 256 pref medium unreachable default dev lo metric 240 error -113 pref medium root@kenny:~# ip -6 ro add table red 2100:3::/64 via 2100:1::64 RTNETLINK answers: No route to host Route add fails even though 2100:1::64 is a reachable next hop: root@kenny:~# ping6 -I red 2100:1::64 ping6: Warning: source address might be selected on device other than red. PING 2100:1::64(2100:1::64) from 2100:1::1 red: 56 data bytes 64 bytes from 2100:1::64: icmp_seq=1 ttl=64 time=1.33 ms With this patch: root@kenny:~# ip -6 ro add table red 2100:3::/64 via 2100:1::64 root@kenny:~# ip -6 ro ls table red local 2100:1::1 dev lo proto none metric 0 pref medium 2100:1::/120 dev eth1 proto kernel metric 256 pref medium local 2100:2::1 dev lo proto none metric 0 pref medium 2100:2::/120 dev eth2 proto kernel metric 256 pref medium 2100:3::/64 via 2100:1::64 dev eth1 metric 1024 pref medium local fe80::e0:f9ff:fe09:3cac dev lo proto none metric 0 pref medium local fe80::e0:f9ff:fe1c:b974 dev lo proto none metric 0 pref medium fe80::/64 dev eth1 proto kernel metric 256 pref medium fe80::/64 dev eth2 proto kernel metric 256 pref medium ff00::/8 dev red metric 256 pref medium ff00::/8 dev eth1 metric 256 pref medium ff00::/8 dev eth2 metric 256 pref medium unreachable default dev lo metric 240 error -113 pref medium Signed-off-by: David Ahern Signed-off-by: David S. Miller --- net/ipv6/route.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d916d6ab9ad2..af46e19205f5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1769,6 +1769,37 @@ static int ip6_convert_metrics(struct mx6_config *mxc, return -EINVAL; } +static struct rt6_info *ip6_nh_lookup_table(struct net *net, + struct fib6_config *cfg, + const struct in6_addr *gw_addr) +{ + struct flowi6 fl6 = { + .flowi6_oif = cfg->fc_ifindex, + .daddr = *gw_addr, + .saddr = cfg->fc_prefsrc, + }; + struct fib6_table *table; + struct rt6_info *rt; + int flags = 0; + + table = fib6_get_table(net, cfg->fc_table); + if (!table) + return NULL; + + if (!ipv6_addr_any(&cfg->fc_prefsrc)) + flags |= RT6_LOOKUP_F_HAS_SADDR; + + rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags); + + /* if table lookup failed, fall back to full lookup */ + if (rt == net->ipv6.ip6_null_entry) { + ip6_rt_put(rt); + rt = NULL; + } + + return rt; +} + static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg) { struct net *net = cfg->fc_nlinfo.nl_net; @@ -1940,7 +1971,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg) rt->rt6i_gateway = *gw_addr; if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { - struct rt6_info *grt; + struct rt6_info *grt = NULL; /* IPv6 strictly inhibits using not link-local addresses as nexthop address. @@ -1952,7 +1983,12 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg) if (!(gwa_type & IPV6_ADDR_UNICAST)) goto out; - grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); + if (cfg->fc_table) + grt = ip6_nh_lookup_table(net, cfg, gw_addr); + + if (!grt) + grt = rt6_lookup(net, gw_addr, NULL, + cfg->fc_ifindex, 1); err = -EHOSTUNREACH; if (!grt) -- GitLab From 5e4e38446a62a4f50d77b0dd11d4b379dee08988 Mon Sep 17 00:00:00 2001 From: Petr Mladek Date: Mon, 25 Apr 2016 17:14:35 +0200 Subject: [PATCH 4815/9938] livepatch: Add some basic livepatch documentation livepatch framework deserves some documentation, definitely. This is an attempt to provide some basic info. I hope that it will be useful for both LivePatch producers and also potential developers of the framework itself. [jkosina@suse.cz: - incorporated feedback (grammar fixes) from Chris J Arges - s/LivePatch/livepatch in changelog as pointed out by Josh Poimboeuf - incorporated part of feedback (grammar fixes / reformulations) from Balbir Singh ] Acked-by: Jessica Yu Signed-off-by: Petr Mladek Signed-off-by: Jiri Kosina --- Documentation/livepatch/livepatch.txt | 394 ++++++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 395 insertions(+) create mode 100644 Documentation/livepatch/livepatch.txt diff --git a/Documentation/livepatch/livepatch.txt b/Documentation/livepatch/livepatch.txt new file mode 100644 index 000000000000..6c43f6ebee8d --- /dev/null +++ b/Documentation/livepatch/livepatch.txt @@ -0,0 +1,394 @@ +========= +Livepatch +========= + +This document outlines basic information about kernel livepatching. + +Table of Contents: + +1. Motivation +2. Kprobes, Ftrace, Livepatching +3. Consistency model +4. Livepatch module + 4.1. New functions + 4.2. Metadata + 4.3. Livepatch module handling +5. Livepatch life-cycle + 5.1. Registration + 5.2. Enabling + 5.3. Disabling + 5.4. Unregistration +6. Sysfs +7. Limitations + + +1. Motivation +============= + +There are many situations where users are reluctant to reboot a system. It may +be because their system is performing complex scientific computations or under +heavy load during peak usage. In addition to keeping systems up and running, +users want to also have a stable and secure system. Livepatching gives users +both by allowing for function calls to be redirected; thus, fixing critical +functions without a system reboot. + + +2. Kprobes, Ftrace, Livepatching +================================ + +There are multiple mechanisms in the Linux kernel that are directly related +to redirection of code execution; namely: kernel probes, function tracing, +and livepatching: + + + The kernel probes are the most generic. The code can be redirected by + putting a breakpoint instruction instead of any instruction. + + + The function tracer calls the code from a predefined location that is + close to the function entry point. This location is generated by the + compiler using the '-pg' gcc option. + + + Livepatching typically needs to redirect the code at the very beginning + of the function entry before the function parameters or the stack + are in any way modified. + +All three approaches need to modify the existing code at runtime. Therefore +they need to be aware of each other and not step over each other's toes. +Most of these problems are solved by using the dynamic ftrace framework as +a base. A Kprobe is registered as a ftrace handler when the function entry +is probed, see CONFIG_KPROBES_ON_FTRACE. Also an alternative function from +a live patch is called with the help of a custom ftrace handler. But there are +some limitations, see below. + + +3. Consistency model +==================== + +Functions are there for a reason. They take some input parameters, get or +release locks, read, process, and even write some data in a defined way, +have return values. In other words, each function has a defined semantic. + +Many fixes do not change the semantic of the modified functions. For +example, they add a NULL pointer or a boundary check, fix a race by adding +a missing memory barrier, or add some locking around a critical section. +Most of these changes are self contained and the function presents itself +the same way to the rest of the system. In this case, the functions might +be updated independently one by one. + +But there are more complex fixes. For example, a patch might change +ordering of locking in multiple functions at the same time. Or a patch +might exchange meaning of some temporary structures and update +all the relevant functions. In this case, the affected unit +(thread, whole kernel) need to start using all new versions of +the functions at the same time. Also the switch must happen only +when it is safe to do so, e.g. when the affected locks are released +or no data are stored in the modified structures at the moment. + +The theory about how to apply functions a safe way is rather complex. +The aim is to define a so-called consistency model. It attempts to define +conditions when the new implementation could be used so that the system +stays consistent. The theory is not yet finished. See the discussion at +http://thread.gmane.org/gmane.linux.kernel/1823033/focus=1828189 + +The current consistency model is very simple. It guarantees that either +the old or the new function is called. But various functions get redirected +one by one without any synchronization. + +In other words, the current implementation _never_ modifies the behavior +in the middle of the call. It is because it does _not_ rewrite the entire +function in the memory. Instead, the function gets redirected at the +very beginning. But this redirection is used immediately even when +some other functions from the same patch have not been redirected yet. + +See also the section "Limitations" below. + + +4. Livepatch module +=================== + +Livepatches are distributed using kernel modules, see +samples/livepatch/livepatch-sample.c. + +The module includes a new implementation of functions that we want +to replace. In addition, it defines some structures describing the +relation between the original and the new implementation. Then there +is code that makes the kernel start using the new code when the livepatch +module is loaded. Also there is code that cleans up before the +livepatch module is removed. All this is explained in more details in +the next sections. + + +4.1. New functions +------------------ + +New versions of functions are typically just copied from the original +sources. A good practice is to add a prefix to the names so that they +can be distinguished from the original ones, e.g. in a backtrace. Also +they can be declared as static because they are not called directly +and do not need the global visibility. + +The patch contains only functions that are really modified. But they +might want to access functions or data from the original source file +that may only be locally accessible. This can be solved by a special +relocation section in the generated livepatch module, see +Documentation/livepatch/module-elf-format.txt for more details. + + +4.2. Metadata +------------ + +The patch is described by several structures that split the information +into three levels: + + + struct klp_func is defined for each patched function. It describes + the relation between the original and the new implementation of a + particular function. + + The structure includes the name, as a string, of the original function. + The function address is found via kallsyms at runtime. + + Then it includes the address of the new function. It is defined + directly by assigning the function pointer. Note that the new + function is typically defined in the same source file. + + As an optional parameter, the symbol position in the kallsyms database can + be used to disambiguate functions of the same name. This is not the + absolute position in the database, but rather the order it has been found + only for a particular object ( vmlinux or a kernel module ). Note that + kallsyms allows for searching symbols according to the object name. + + + struct klp_object defines an array of patched functions (struct + klp_func) in the same object. Where the object is either vmlinux + (NULL) or a module name. + + The structure helps to group and handle functions for each object + together. Note that patched modules might be loaded later than + the patch itself and the relevant functions might be patched + only when they are available. + + + + struct klp_patch defines an array of patched objects (struct + klp_object). + + This structure handles all patched functions consistently and eventually, + synchronously. The whole patch is applied only when all patched + symbols are found. The only exception are symbols from objects + (kernel modules) that have not been loaded yet. Also if a more complex + consistency model is supported then a selected unit (thread, + kernel as a whole) will see the new code from the entire patch + only when it is in a safe state. + + +4.3. Livepatch module handling +------------------------------ + +The usual behavior is that the new functions will get used when +the livepatch module is loaded. For this, the module init() function +has to register the patch (struct klp_patch) and enable it. See the +section "Livepatch life-cycle" below for more details about these +two operations. + +Module removal is only safe when there are no users of the underlying +functions. The immediate consistency model is not able to detect this; +therefore livepatch modules cannot be removed. See "Limitations" below. + +5. Livepatch life-cycle +======================= + +Livepatching defines four basic operations that define the life cycle of each +live patch: registration, enabling, disabling and unregistration. There are +several reasons why it is done this way. + +First, the patch is applied only when all patched symbols for already +loaded objects are found. The error handling is much easier if this +check is done before particular functions get redirected. + +Second, the immediate consistency model does not guarantee that anyone is not +sleeping in the new code after the patch is reverted. This means that the new +code needs to stay around "forever". If the code is there, one could apply it +again. Therefore it makes sense to separate the operations that might be done +once and those that need to be repeated when the patch is enabled (applied) +again. + +Third, it might take some time until the entire system is migrated +when a more complex consistency model is used. The patch revert might +block the livepatch module removal for too long. Therefore it is useful +to revert the patch using a separate operation that might be called +explicitly. But it does not make sense to remove all information +until the livepatch module is really removed. + + +5.1. Registration +----------------- + +Each patch first has to be registered using klp_register_patch(). This makes +the patch known to the livepatch framework. Also it does some preliminary +computing and checks. + +In particular, the patch is added into the list of known patches. The +addresses of the patched functions are found according to their names. +The special relocations, mentioned in the section "New functions", are +applied. The relevant entries are created under +/sys/kernel/livepatch/. The patch is rejected when any operation +fails. + + +5.2. Enabling +------------- + +Registered patches might be enabled either by calling klp_enable_patch() or +by writing '1' to /sys/kernel/livepatch//enabled. The system will +start using the new implementation of the patched functions at this stage. + +In particular, if an original function is patched for the first time, a +function specific struct klp_ops is created and an universal ftrace handler +is registered. + +Functions might be patched multiple times. The ftrace handler is registered +only once for the given function. Further patches just add an entry to the +list (see field `func_stack`) of the struct klp_ops. The last added +entry is chosen by the ftrace handler and becomes the active function +replacement. + +Note that the patches might be enabled in a different order than they were +registered. + + +5.3. Disabling +-------------- + +Enabled patches might get disabled either by calling klp_disable_patch() or +by writing '0' to /sys/kernel/livepatch//enabled. At this stage +either the code from the previously enabled patch or even the original +code gets used. + +Here all the functions (struct klp_func) associated with the to-be-disabled +patch are removed from the corresponding struct klp_ops. The ftrace handler +is unregistered and the struct klp_ops is freed when the func_stack list +becomes empty. + +Patches must be disabled in exactly the reverse order in which they were +enabled. It makes the problem and the implementation much easier. + + +5.4. Unregistration +------------------- + +Disabled patches might be unregistered by calling klp_unregister_patch(). +This can be done only when the patch is disabled and the code is no longer +used. It must be called before the livepatch module gets unloaded. + +At this stage, all the relevant sys-fs entries are removed and the patch +is removed from the list of known patches. + + +6. Sysfs +======== + +Information about the registered patches can be found under +/sys/kernel/livepatch. The patches could be enabled and disabled +by writing there. + +See Documentation/ABI/testing/sysfs-kernel-livepatch for more details. + + +7. Limitations +============== + +The current Livepatch implementation has several limitations: + + + + The patch must not change the semantic of the patched functions. + + The current implementation guarantees only that either the old + or the new function is called. The functions are patched one + by one. It means that the patch must _not_ change the semantic + of the function. + + + + Data structures can not be patched. + + There is no support to version data structures or anyhow migrate + one structure into another. Also the simple consistency model does + not allow to switch more functions atomically. + + Once there is more complex consistency mode, it will be possible to + use some workarounds. For example, it will be possible to use a hole + for a new member because the data structure is aligned. Or it will + be possible to use an existing member for something else. + + There are no plans to add more generic support for modified structures + at the moment. + + + + Only functions that can be traced could be patched. + + Livepatch is based on the dynamic ftrace. In particular, functions + implementing ftrace or the livepatch ftrace handler could not be + patched. Otherwise, the code would end up in an infinite loop. A + potential mistake is prevented by marking the problematic functions + by "notrace". + + + + Anything inlined into __schedule() can not be patched. + + The switch_to macro is inlined into __schedule(). It switches the + context between two processes in the middle of the macro. It does + not save RIP in x86_64 version (contrary to 32-bit version). Instead, + the currently used __schedule()/switch_to() handles both processes. + + Now, let's have two different tasks. One calls the original + __schedule(), its registers are stored in a defined order and it + goes to sleep in the switch_to macro and some other task is restored + using the original __schedule(). Then there is the second task which + calls patched__schedule(), it goes to sleep there and the first task + is picked by the patched__schedule(). Its RSP is restored and now + the registers should be restored as well. But the order is different + in the new patched__schedule(), so... + + There is work in progress to remove this limitation. + + + + Livepatch modules can not be removed. + + The current implementation just redirects the functions at the very + beginning. It does not check if the functions are in use. In other + words, it knows when the functions get called but it does not + know when the functions return. Therefore it can not decide when + the livepatch module can be safely removed. + + This will get most likely solved once a more complex consistency model + is supported. The idea is that a safe state for patching should also + mean a safe state for removing the patch. + + Note that the patch itself might get disabled by writing zero + to /sys/kernel/livepatch//enabled. It causes that the new + code will not longer get called. But it does not guarantee + that anyone is not sleeping anywhere in the new code. + + + + Livepatch works reliably only when the dynamic ftrace is located at + the very beginning of the function. + + The function need to be redirected before the stack or the function + parameters are modified in any way. For example, livepatch requires + using -fentry gcc compiler option on x86_64. + + One exception is the PPC port. It uses relative addressing and TOC. + Each function has to handle TOC and save LR before it could call + the ftrace handler. This operation has to be reverted on return. + Fortunately, the generic ftrace code has the same problem and all + this is is handled on the ftrace level. + + + + Kretprobes using the ftrace framework conflict with the patched + functions. + + Both kretprobes and livepatches use a ftrace handler that modifies + the return address. The first user wins. Either the probe or the patch + is rejected when the handler is already in use by the other. + + + + Kprobes in the original function are ignored when the code is + redirected to the new implementation. + + There is a work in progress to add warnings about this situation. diff --git a/MAINTAINERS b/MAINTAINERS index 94ea42b76b30..c6baaa68a3af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6605,6 +6605,7 @@ F: kernel/livepatch/ F: include/linux/livepatch.h F: arch/x86/include/asm/livepatch.h F: arch/x86/kernel/livepatch.c +F: Documentation/livepatch/ F: Documentation/ABI/testing/sysfs-kernel-livepatch F: samples/livepatch/ L: live-patching@vger.kernel.org -- GitLab From 68a1c5a777f8e94d3bb0b0e287443492316ea5b5 Mon Sep 17 00:00:00 2001 From: Michal Kosiarz Date: Tue, 12 Apr 2016 08:30:46 -0700 Subject: [PATCH 4816/9938] i40e: Add device capability which defines if update is available Add device capability which defines if update is available and security check is needed during update process. Change-ID: I380787c878275e1df18b39198df3ee3666342282 Signed-off-by: Michal Kosiarz Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 1 + drivers/net/ethernet/intel/i40e/i40e_common.c | 6 ++++++ drivers/net/ethernet/intel/i40e/i40e_type.h | 5 +++++ drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 5 +++++ 5 files changed, 18 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 8d5c65ab6267..5179b3b25acb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -429,6 +429,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_SDP 0x0062 #define I40E_AQ_CAP_ID_MDIO 0x0063 #define I40E_AQ_CAP_ID_WSR_PROT 0x0064 +#define I40E_AQ_CAP_ID_NVM_MGMT 0x0080 #define I40E_AQ_CAP_ID_FLEX10 0x00F1 #define I40E_AQ_CAP_ID_CEM 0x00F2 diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index f3c1d8890cbb..34e86f55b2c0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -3138,6 +3138,12 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, p->wr_csr_prot = (u64)number; p->wr_csr_prot |= (u64)logical_id << 32; break; + case I40E_AQ_CAP_ID_NVM_MGMT: + if (number & I40E_NVM_MGMT_SEC_REV_DISABLED) + p->sec_rev_disabled = true; + if (number & I40E_NVM_MGMT_UPDATE_DISABLED) + p->update_disabled = true; + break; default: break; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index bb57cd909c47..8aa14aacdd35 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -275,6 +275,11 @@ struct i40e_hw_capabilities { #define I40E_FLEX10_STATUS_DCC_ERROR 0x1 #define I40E_FLEX10_STATUS_VC_MODE 0x2 + bool sec_rev_disabled; + bool update_disabled; +#define I40E_NVM_MGMT_SEC_REV_DISABLED 0x1 +#define I40E_NVM_MGMT_UPDATE_DISABLED 0x2 + bool mgmt_cem; bool ieee_1588; bool iwarp; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index aad8d6277110..1bcb8cf89801 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -426,6 +426,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_SDP 0x0062 #define I40E_AQ_CAP_ID_MDIO 0x0063 #define I40E_AQ_CAP_ID_WSR_PROT 0x0064 +#define I40E_AQ_CAP_ID_NVM_MGMT 0x0080 #define I40E_AQ_CAP_ID_FLEX10 0x00F1 #define I40E_AQ_CAP_ID_CEM 0x00F2 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index b72071363a8f..bfc97c2f22bb 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -258,6 +258,11 @@ struct i40e_hw_capabilities { #define I40E_FLEX10_STATUS_DCC_ERROR 0x1 #define I40E_FLEX10_STATUS_VC_MODE 0x2 + bool sec_rev_disabled; + bool update_disabled; +#define I40E_NVM_MGMT_SEC_REV_DISABLED 0x1 +#define I40E_NVM_MGMT_UPDATE_DISABLED 0x2 + bool mgmt_cem; bool ieee_1588; bool iwarp; -- GitLab From bccf474435b668312e9fc8bd9586c2e256b66841 Mon Sep 17 00:00:00 2001 From: Kamil Krawczyk Date: Tue, 12 Apr 2016 08:30:47 -0700 Subject: [PATCH 4817/9938] i40e: Add DeviceID for X722 QSFP+ Change-ID: I1370fbc7774e815ac1ad56561e97488e829592fc Signed-off-by: Kamil Krawczyk Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 1 + drivers/net/ethernet/intel/i40e/i40e_devids.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_common.c | 1 + drivers/net/ethernet/intel/i40evf/i40e_devids.h | 1 + 4 files changed, 4 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 34e86f55b2c0..1db4790423f1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -61,6 +61,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_1G_BASE_T_X722: case I40E_DEV_ID_10G_BASE_T_X722: case I40E_DEV_ID_SFP_I_X722: + case I40E_DEV_ID_QSFP_I_X722: hw->mac.type = I40E_MAC_X722; break; default: diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h index dd4457d29e98..d701861c6e1e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h @@ -45,6 +45,7 @@ #define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 #define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 #define I40E_DEV_ID_SFP_I_X722 0x37D3 +#define I40E_DEV_ID_QSFP_I_X722 0x37D4 #define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \ (d) == I40E_DEV_ID_QSFP_B || \ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index 4db0c0326185..8f64204000fb 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -59,6 +59,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_1G_BASE_T_X722: case I40E_DEV_ID_10G_BASE_T_X722: case I40E_DEV_ID_SFP_I_X722: + case I40E_DEV_ID_QSFP_I_X722: hw->mac.type = I40E_MAC_X722; break; case I40E_DEV_ID_X722_VF: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h index 70235706915e..d34972bab09c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_devids.h @@ -45,6 +45,7 @@ #define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 #define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 #define I40E_DEV_ID_SFP_I_X722 0x37D3 +#define I40E_DEV_ID_QSFP_I_X722 0x37D4 #define I40E_DEV_ID_X722_VF 0x37CD #define I40E_DEV_ID_X722_VF_HV 0x37D9 -- GitLab From db0772782f6b99adbd8548e1d3830fe019c9f250 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Tue, 12 Apr 2016 08:30:48 -0700 Subject: [PATCH 4818/9938] i40e: Remove zero check A mirror rule ID may be zero so do not return invalid parameter when the user passes in a zero value for a rule ID. Change-ID: I261b8c24725ce2c6ed32f859da81093dfcbe2970 Signed-off-by: Greg Rose Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 1db4790423f1..25872f2012c5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2668,10 +2668,7 @@ i40e_status i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid, u16 *rules_used, u16 *rules_free) { /* Rule ID has to be valid except rule_type: INGRESS VLAN mirroring */ - if (rule_type != I40E_AQC_MIRROR_RULE_TYPE_VLAN) { - if (!rule_id) - return I40E_ERR_PARAM; - } else { + if (rule_type == I40E_AQC_MIRROR_RULE_TYPE_VLAN) { /* count and mr_list shall be valid for rule_type INGRESS VLAN * mirroring. For other rule_type, count and rule_type should * not matter. -- GitLab From a149f2c323b62bc6cff91d874d853250250e8497 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 12 Apr 2016 08:30:49 -0700 Subject: [PATCH 4819/9938] i40e/i40evf: Only offload VLAN tag if enabled The driver was offloading the VLAN tag into the skb any time there was a VLAN tag and the hardware stripping was enabled. Just check to make sure it's enabled before put_tag. Change-Id: Ife95290c06edd9a616393b38679923938b382241 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 ++- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 6e44cf118843..285efe955c64 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1370,7 +1370,8 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring, { struct i40e_q_vector *q_vector = rx_ring->q_vector; - if (vlan_tag & VLAN_VID_MASK) + if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && + (vlan_tag & VLAN_VID_MASK)) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); napi_gro_receive(&q_vector->napi, skb); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index f101895ecf4a..4633235ee70b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -842,7 +842,8 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring, { struct i40e_q_vector *q_vector = rx_ring->q_vector; - if (vlan_tag & VLAN_VID_MASK) + if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && + (vlan_tag & VLAN_VID_MASK)) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); napi_gro_receive(&q_vector->napi, skb); -- GitLab From 6c41a7606967803702d0b5c2ba57acce71ec8d9d Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Tue, 12 Apr 2016 08:30:50 -0700 Subject: [PATCH 4820/9938] i40e: Add promiscuous on VLAN support NFV use cases require the ability to steer packets to VSIs by VLAN tag alone while being in promiscuous mode for multicast and unicast MAC addresses. These two new functions support that ability. Signed-off-by: Greg Rose Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 70 +++++++++++++++++++ .../net/ethernet/intel/i40e/i40e_prototype.h | 8 +++ 2 files changed, 78 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 25872f2012c5..0e8552b2fba0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2038,6 +2038,76 @@ i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw, return status; } +/** + * i40e_aq_set_vsi_mc_promisc_on_vlan + * @hw: pointer to the hw struct + * @seid: vsi number + * @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN + * @vid: The VLAN tag filter - capture any multicast packet with this VLAN tag + * @cmd_details: pointer to command details structure or NULL + **/ +enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw, + u16 seid, bool enable, + u16 vid, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_set_vsi_promiscuous_modes *cmd = + (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw; + enum i40e_status_code status; + u16 flags = 0; + + i40e_fill_default_direct_cmd_desc(&desc, + i40e_aqc_opc_set_vsi_promiscuous_modes); + + if (enable) + flags |= I40E_AQC_SET_VSI_PROMISC_MULTICAST; + + cmd->promiscuous_flags = cpu_to_le16(flags); + cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_MULTICAST); + cmd->seid = cpu_to_le16(seid); + cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID); + + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + + return status; +} + +/** + * i40e_aq_set_vsi_uc_promisc_on_vlan + * @hw: pointer to the hw struct + * @seid: vsi number + * @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN + * @vid: The VLAN tag filter - capture any unicast packet with this VLAN tag + * @cmd_details: pointer to command details structure or NULL + **/ +enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw, + u16 seid, bool enable, + u16 vid, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_set_vsi_promiscuous_modes *cmd = + (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw; + enum i40e_status_code status; + u16 flags = 0; + + i40e_fill_default_direct_cmd_desc(&desc, + i40e_aqc_opc_set_vsi_promiscuous_modes); + + if (enable) + flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST; + + cmd->promiscuous_flags = cpu_to_le16(flags); + cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_UNICAST); + cmd->seid = cpu_to_le16(seid); + cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID); + + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + + return status; +} + /** * i40e_aq_set_vsi_broadcast * @hw: pointer to the hw struct diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index 134035f53f2c..8afb2375ec9f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -133,6 +133,14 @@ i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw, u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw, + u16 seid, bool enable, + u16 vid, + struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw, + u16 seid, bool enable, + u16 vid, + struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw, u16 seid, bool enable, struct i40e_asq_cmd_details *cmd_details); -- GitLab From 5676a8b9cd9a1c9822cdb3d88109f449eb2126c1 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 12 Apr 2016 08:30:51 -0700 Subject: [PATCH 4821/9938] i40e: Add VF promiscuous mode driver support Add infrastructure for Network Function Virtualization VLAN tagged packet steering feature. Change-Id: I9b873d8fcc253858e6baba65ac68ec5b9363944e Signed-off-by: Anjali Singhai Jain Signed-off-by: Greg Rose Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 153 +++++++++++++++++- .../ethernet/intel/i40e/i40e_virtchnl_pf.h | 2 + 2 files changed, 149 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index c3645886670e..f47b0e8d02bb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1426,6 +1426,25 @@ static void i40e_vc_reset_vf_msg(struct i40e_vf *vf) i40e_reset_vf(vf, false); } +/** + * i40e_getnum_vf_vsi_vlan_filters + * @vsi: pointer to the vsi + * + * called to get the number of VLANs offloaded on this VF + **/ +static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi) +{ + struct i40e_mac_filter *f; + int num_vlans = 0; + + list_for_each_entry(f, &vsi->mac_filter_list, list) { + if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) + num_vlans++; + } + + return num_vlans; +} + /** * i40e_vc_config_promiscuous_mode_msg * @vf: pointer to the VF info @@ -1442,22 +1461,122 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, (struct i40e_virtchnl_promisc_info *)msg; struct i40e_pf *pf = vf->pf; struct i40e_hw *hw = &pf->hw; - struct i40e_vsi *vsi; + struct i40e_mac_filter *f; + i40e_status aq_ret = 0; bool allmulti = false; - i40e_status aq_ret; + struct i40e_vsi *vsi; + bool alluni = false; + int aq_err = 0; vsi = i40e_find_vsi_from_id(pf, info->vsi_id); if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) || - !i40e_vc_isvalid_vsi_id(vf, info->vsi_id) || - (vsi->type != I40E_VSI_FCOE)) { + !i40e_vc_isvalid_vsi_id(vf, info->vsi_id)) { + dev_err(&pf->pdev->dev, + "VF %d doesn't meet requirements to enter promiscuous mode\n", + vf->vf_id); aq_ret = I40E_ERR_PARAM; goto error_param; } + /* Multicast promiscuous handling*/ if (info->flags & I40E_FLAG_VF_MULTICAST_PROMISC) allmulti = true; - aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, - allmulti, NULL); + + if (vf->port_vlan_id) { + aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, vsi->seid, + allmulti, + vf->port_vlan_id, + NULL); + } else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) { + list_for_each_entry(f, &vsi->mac_filter_list, list) { + if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) + aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan + (hw, + vsi->seid, + allmulti, + f->vlan, + NULL); + aq_err = pf->hw.aq.asq_last_status; + if (aq_ret) { + dev_err(&pf->pdev->dev, + "Could not add VLAN %d to multicast promiscuous domain err %s aq_err %s\n", + f->vlan, + i40e_stat_str(&pf->hw, aq_ret), + i40e_aq_str(&pf->hw, aq_err)); + break; + } + } + } else { + aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, + allmulti, NULL); + aq_err = pf->hw.aq.asq_last_status; + if (aq_ret) { + dev_err(&pf->pdev->dev, + "VF %d failed to set multicast promiscuous mode err %s aq_err %s\n", + vf->vf_id, + i40e_stat_str(&pf->hw, aq_ret), + i40e_aq_str(&pf->hw, aq_err)); + goto error_param_int; + } + } + + if (!aq_ret) { + dev_info(&pf->pdev->dev, + "VF %d successfully set multicast promiscuous mode\n", + vf->vf_id); + if (allmulti) + set_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states); + else + clear_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states); + } + + if (info->flags & I40E_FLAG_VF_UNICAST_PROMISC) + alluni = true; + if (vf->port_vlan_id) { + aq_ret = i40e_aq_set_vsi_uc_promisc_on_vlan(hw, vsi->seid, + alluni, + vf->port_vlan_id, + NULL); + } else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) { + list_for_each_entry(f, &vsi->mac_filter_list, list) { + aq_ret = 0; + if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) + aq_ret = + i40e_aq_set_vsi_uc_promisc_on_vlan(hw, + vsi->seid, + alluni, + f->vlan, + NULL); + aq_err = pf->hw.aq.asq_last_status; + if (aq_ret) + dev_err(&pf->pdev->dev, + "Could not add VLAN %d to Unicast promiscuous domain err %s aq_err %s\n", + f->vlan, + i40e_stat_str(&pf->hw, aq_ret), + i40e_aq_str(&pf->hw, aq_err)); + } + } else { + aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid, + allmulti, NULL); + aq_err = pf->hw.aq.asq_last_status; + if (aq_ret) + dev_err(&pf->pdev->dev, + "VF %d failed to set unicast promiscuous mode %8.8x err %s aq_err %s\n", + vf->vf_id, info->flags, + i40e_stat_str(&pf->hw, aq_ret), + i40e_aq_str(&pf->hw, aq_err)); + } + +error_param_int: + if (!aq_ret) { + dev_info(&pf->pdev->dev, + "VF %d successfully set unicast promiscuous mode\n", + vf->vf_id); + if (alluni) + set_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states); + else + clear_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states); + } error_param: /* send the response to the VF */ @@ -1919,6 +2038,17 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) /* add new VLAN filter */ int ret = i40e_vsi_add_vlan(vsi, vfl->vlan_id[i]); + if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states)) + i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid, + true, + vfl->vlan_id[i], + NULL); + if (test_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states)) + i40e_aq_set_vsi_mc_promisc_on_vlan(&pf->hw, vsi->seid, + true, + vfl->vlan_id[i], + NULL); + if (ret) dev_err(&pf->pdev->dev, "Unable to add VLAN filter %d for VF %d, error %d\n", @@ -1971,6 +2101,17 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) for (i = 0; i < vfl->num_elements; i++) { int ret = i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]); + if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states)) + i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid, + false, + vfl->vlan_id[i], + NULL); + if (test_bit(I40E_VF_STAT_MC_PROMISC, &vf->vf_states)) + i40e_aq_set_vsi_mc_promisc_on_vlan(&pf->hw, vsi->seid, + false, + vfl->vlan_id[i], + NULL); + if (ret) dev_err(&pf->pdev->dev, "Unable to delete VLAN filter %d for VF %d, error %d\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index 838cbd2299a4..8cbf57988607 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -61,6 +61,8 @@ enum i40e_vf_states { I40E_VF_STAT_IWARPENA, I40E_VF_STAT_FCOEENA, I40E_VF_STAT_DISABLED, + I40E_VF_STAT_MC_PROMISC, + I40E_VF_STAT_UC_PROMISC, }; /* VF capabilities */ -- GitLab From 47d3483988f649739ad8d6462eaa1723e5d077c3 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 12 Apr 2016 08:30:52 -0700 Subject: [PATCH 4822/9938] i40evf: Add driver support for promiscuous mode Add necessary Linux Ethernet driver support for promiscuous mode operation. Add a flag so the VF knows it is in promiscuous mode and two state flags to discreetly track multicast and unicast promiscuous states. Change-Id: Ib2f2dc7a7582304fec90fc917ebb7ded21ba1de4 Signed-off-by: Anjali Singhai Jain Signed-off-by: Greg Rose Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 14 +++++++------- drivers/net/ethernet/intel/i40evf/i40evf.h | 3 +++ .../net/ethernet/intel/i40evf/i40evf_main.c | 19 +++++++++++++++++++ .../ethernet/intel/i40evf/i40evf_virtchnl.c | 11 +++++++++++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index f47b0e8d02bb..c226c2dad247 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1489,13 +1489,13 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, NULL); } else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) { list_for_each_entry(f, &vsi->mac_filter_list, list) { - if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) - aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan - (hw, - vsi->seid, - allmulti, - f->vlan, - NULL); + if (f->vlan < 0 || f->vlan > I40E_MAX_VLANID) + continue; + aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, + vsi->seid, + allmulti, + f->vlan, + NULL); aq_err = pf->hw.aq.asq_last_status; if (aq_ret) { dev_err(&pf->pdev->dev, diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 63f7aae2c8ce..25afabf999d0 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -220,6 +220,7 @@ struct i40evf_adapter { #define I40EVF_FLAG_WB_ON_ITR_CAPABLE BIT(11) #define I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE BIT(12) #define I40EVF_FLAG_ADDR_SET_BY_PF BIT(13) +#define I40EVF_FLAG_PROMISC_ON BIT(15) /* duplicates for common code */ #define I40E_FLAG_FDIR_ATR_ENABLED 0 #define I40E_FLAG_DCB_ENABLED 0 @@ -244,6 +245,8 @@ struct i40evf_adapter { #define I40EVF_FLAG_AQ_SET_HENA BIT(12) #define I40EVF_FLAG_AQ_SET_RSS_KEY BIT(13) #define I40EVF_FLAG_AQ_SET_RSS_LUT BIT(14) +#define I40EVF_FLAG_AQ_REQUEST_PROMISC BIT(15) +#define I40EVF_FLAG_AQ_RELEASE_PROMISC BIT(16) /* OS defined structs */ struct net_device *netdev; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index af53159010ab..d1c4afdd9435 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -943,6 +943,14 @@ static void i40evf_set_rx_mode(struct net_device *netdev) bottom_of_search_loop: continue; } + + if (netdev->flags & IFF_PROMISC && + !(adapter->flags & I40EVF_FLAG_PROMISC_ON)) + adapter->aq_required |= I40EVF_FLAG_AQ_REQUEST_PROMISC; + else if (!(netdev->flags & IFF_PROMISC) && + adapter->flags & I40EVF_FLAG_PROMISC_ON) + adapter->aq_required |= I40EVF_FLAG_AQ_RELEASE_PROMISC; + clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); } @@ -1622,6 +1630,17 @@ static void i40evf_watchdog_task(struct work_struct *work) goto watchdog_done; } + if (adapter->aq_required & I40EVF_FLAG_AQ_REQUEST_PROMISC) { + i40evf_set_promiscuous(adapter, I40E_FLAG_VF_UNICAST_PROMISC | + I40E_FLAG_VF_MULTICAST_PROMISC); + goto watchdog_done; + } + + if (adapter->aq_required & I40EVF_FLAG_AQ_RELEASE_PROMISC) { + i40evf_set_promiscuous(adapter, 0); + goto watchdog_done; + } + if (adapter->state == __I40EVF_RUNNING) i40evf_request_stats(adapter); watchdog_done: diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index e62c56b5a141..ba7fbc0608a6 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -652,6 +652,17 @@ void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags) adapter->current_op); return; } + + if (flags) { + adapter->flags |= I40EVF_FLAG_PROMISC_ON; + adapter->aq_required &= ~I40EVF_FLAG_AQ_REQUEST_PROMISC; + dev_info(&adapter->pdev->dev, "Entering promiscuous mode\n"); + } else { + adapter->flags &= ~I40EVF_FLAG_PROMISC_ON; + adapter->aq_required &= ~I40EVF_FLAG_AQ_RELEASE_PROMISC; + dev_info(&adapter->pdev->dev, "Leaving promiscuous mode\n"); + } + adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE; vpi.vsi_id = adapter->vsi_res->vsi_id; vpi.flags = flags; -- GitLab From 6de0dc4b536110d63a83021b7e6dce3e1955297b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 26 Apr 2016 20:14:13 -0400 Subject: [PATCH 4823/9938] cpufreq: e_powersaver: Use IS_ENABLED() instead of checking for built-in or module The IS_ENABLED() macro checks if a Kconfig symbol has been enabled either built-in or as a module, use that macro instead of open coding the same. Signed-off-by: Javier Martinez Canillas Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/e_powersaver.c | 14 +++++++------- drivers/cpufreq/ppc_cbe_cpufreq.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 5ec87e3a97bd..cdf097b29862 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -22,7 +22,7 @@ #include #include -#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE +#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) #include #include #endif @@ -35,7 +35,7 @@ struct eps_cpu_data { u32 fsb; -#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE +#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) u32 bios_limit; #endif struct cpufreq_frequency_table freq_table[]; @@ -48,7 +48,7 @@ static int freq_failsafe_off; static int voltage_failsafe_off; static int set_max_voltage; -#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE +#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) static int ignore_acpi_limit; static struct acpi_processor_performance *eps_acpi_cpu_perf; @@ -186,7 +186,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) int k, step, voltage; int ret; int states; -#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE +#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) unsigned int limit; #endif @@ -286,7 +286,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Calc FSB speed */ fsb = cpu_khz / current_multiplier; -#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE +#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) /* Check for ACPI processor speed limit */ if (!ignore_acpi_limit && !eps_acpi_init()) { if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) { @@ -333,7 +333,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Copy basic values */ centaur->fsb = fsb; -#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE +#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) centaur->bios_limit = limit; #endif @@ -418,7 +418,7 @@ module_param(freq_failsafe_off, int, 0644); MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check"); module_param(voltage_failsafe_off, int, 0644); MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check"); -#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE +#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) module_param(ignore_acpi_limit, int, 0644); MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit"); #endif diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.h b/drivers/cpufreq/ppc_cbe_cpufreq.h index b4c00a5a6a59..3eace725ccd6 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.h +++ b/drivers/cpufreq/ppc_cbe_cpufreq.h @@ -17,7 +17,7 @@ int cbe_cpufreq_get_pmode(int cpu); int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode); -#if defined(CONFIG_CPU_FREQ_CBE_PMI) || defined(CONFIG_CPU_FREQ_CBE_PMI_MODULE) +#if IS_ENABLED(CONFIG_CPU_FREQ_CBE_PMI) extern bool cbe_cpufreq_has_pmi; #else #define cbe_cpufreq_has_pmi (0) -- GitLab From a4a13f582c6d36b78b1c0459ee0b28f17bb2fb06 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 27 Apr 2016 22:22:20 +0800 Subject: [PATCH 4824/9938] f2fs: be aware of invalid filename length The filename length in dirent of may become zero-sized after random junk data injection, once encounter such dirent, find_target_dentry or f2fs_add_inline_entries will run into an infinite loop. So let f2fs being aware of that to avoid deadloop. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/dir.c | 14 +++++--------- fs/f2fs/inline.c | 14 ++++++-------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index e90380d82214..3b1c14e4eeea 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -101,11 +101,6 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, else kunmap(dentry_page); - /* - * For the most part, it should be a bug when name_len is zero. - * We stop here for figuring out where the bugs has occurred. - */ - f2fs_bug_on(F2FS_P_SB(dentry_page), d.max < 0); return de; } @@ -130,6 +125,11 @@ struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname, de = &d->dentry[bit_pos]; + if (unlikely(!de->name_len)) { + bit_pos++; + continue; + } + /* encrypted case */ de_name.name = d->filename[bit_pos]; de_name.len = le16_to_cpu(de->name_len); @@ -147,10 +147,6 @@ struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname, *max_slots = max_len; max_len = 0; - /* remain bug on condition */ - if (unlikely(!de->name_len)) - d->max = -1; - bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 772056587eb9..e61084cac5f1 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -303,11 +303,6 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, else f2fs_put_page(ipage, 0); - /* - * For the most part, it should be a bug when name_len is zero. - * We stop here for figuring out where the bugs has occurred. - */ - f2fs_bug_on(sbi, d.max < 0); return de; } @@ -437,6 +432,12 @@ static int f2fs_add_inline_entries(struct inode *dir, } de = &d.dentry[bit_pos]; + + if (unlikely(!de->name_len)) { + bit_pos++; + continue; + } + new_name.name = d.filename[bit_pos]; new_name.len = de->name_len; @@ -448,9 +449,6 @@ static int f2fs_add_inline_entries(struct inode *dir, if (err) goto punch_dentry_pages; - if (unlikely(!de->name_len)) - d.max = -1; - bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } return 0; -- GitLab From da011cc0da8cf4a60ddf4d2ae8b42902a3d71e5f Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 27 Apr 2016 21:40:15 +0800 Subject: [PATCH 4825/9938] f2fs: move node pages only in victim section during GC For foreground GC, we cache node blocks in victim section and set them dirty, then we call sync_node_pages to flush these node pages, but meanwhile, those node pages which does not locate in victim section will be flushed together, so more bandwidth and continuous free space would be occupied. So for this condition, it's better to leave those unrelated node page in cache for further write hit, and let CP or VM to flush them afterward. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 1 + fs/f2fs/gc.c | 25 ++++--------------------- fs/f2fs/node.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ca828b0e7d6d..6a482411e6d4 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1783,6 +1783,7 @@ void ra_node_page(struct f2fs_sb_info *, nid_t); struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); struct page *get_node_page_ra(struct page *, int); void sync_inode_page(struct dnode_of_data *); +void move_node_page(struct page *, int); int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *, bool); int sync_node_pages(struct f2fs_sb_info *, struct writeback_control *); diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index e82046523186..19e9fafc5c70 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -465,15 +465,7 @@ static void gc_node_segment(struct f2fs_sb_info *sbi, continue; } - /* set page dirty and write it */ - if (gc_type == FG_GC) { - f2fs_wait_on_page_writeback(node_page, NODE, true); - set_page_dirty(node_page); - } else { - if (!PageWriteback(node_page)) - set_page_dirty(node_page); - } - f2fs_put_page(node_page, 1); + move_node_page(node_page, gc_type); stat_inc_node_blk_count(sbi, 1, gc_type); } @@ -834,18 +826,9 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, f2fs_put_page(sum_page, 0); } - if (gc_type == FG_GC) { - if (type == SUM_TYPE_NODE) { - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = LONG_MAX, - .for_reclaim = 0, - }; - sync_node_pages(sbi, &wbc); - } else { - f2fs_submit_merged_bio(sbi, DATA, WRITE); - } - } + if (gc_type == FG_GC) + f2fs_submit_merged_bio(sbi, + (type == SUM_TYPE_NODE) ? NODE : DATA, WRITE); blk_finish_plug(&plug); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index de070a524fd2..f80cfb6beac6 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1222,6 +1222,37 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) iput(inode); } +void move_node_page(struct page *node_page, int gc_type) +{ + if (gc_type == FG_GC) { + struct f2fs_sb_info *sbi = F2FS_P_SB(node_page); + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = 1, + .for_reclaim = 0, + }; + + set_page_dirty(node_page); + f2fs_wait_on_page_writeback(node_page, NODE, true); + + f2fs_bug_on(sbi, PageWriteback(node_page)); + if (!clear_page_dirty_for_io(node_page)) + goto out_page; + + if (NODE_MAPPING(sbi)->a_ops->writepage(node_page, &wbc)) + unlock_page(node_page); + goto release_page; + } else { + /* set page dirty and write it */ + if (!PageWriteback(node_page)) + set_page_dirty(node_page); + } +out_page: + unlock_page(node_page); +release_page: + f2fs_put_page(node_page, 0); +} + static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) { pgoff_t index, end; -- GitLab From fe216c7a0ff993cdac885109d8544ba02e6f9127 Mon Sep 17 00:00:00 2001 From: Yunlong Song Date: Wed, 27 Apr 2016 20:32:37 +0800 Subject: [PATCH 4826/9938] f2fs: fix to return 0 if err == -ENOENT in f2fs_readdir Commit 57b62d29ad5b384775974973087d47755a8c6fcc ("f2fs: fix to report error in f2fs_readdir") causes f2fs_readdir to return -ENOENT when get_lock_data_page returns -ENOENT. However, the original logic is to continue when get_lock_data_page returns -ENOENT, but it forgets to reset err to 0. This will cause getdents64 incorretly return -ENOENT when lastdirent is NULL in getdents64. This will lead to a wrong return value for syscall caller. Signed-off-by: Yunlong Song Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/dir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 3b1c14e4eeea..dbfc1d1375a0 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -888,6 +888,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) kunmap(dentry_page); f2fs_put_page(dentry_page, 1); } + err = 0; out: fscrypt_fname_free_buffer(&fstr); return err; -- GitLab From 188e3c5cd2b672620291e64a21f1598fe91e40b6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 27 Apr 2016 11:56:04 +0200 Subject: [PATCH 4827/9938] tty: provide tty_name() even without CONFIG_TTY The audit subsystem just started printing the name of the tty, but that causes a build failure when CONFIG_TTY is disabled: kernel/built-in.o: In function `audit_log_task_info': memremap.c:(.text+0x5e34c): undefined reference to `tty_name' kernel/built-in.o: In function `audit_set_loginuid': memremap.c:(.text+0x63b34): undefined reference to `tty_name' This adds tty_name() to the list of functions that are provided as trivial stubs in that configuration. Signed-off-by: Arnd Bergmann Fixes: db0a6fb5d97a ("audit: add tty field to LOGIN event") Signed-off-by: Paul Moore --- include/linux/tty.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/tty.h b/include/linux/tty.h index d9fb4b043f56..a93cce297832 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -371,6 +371,7 @@ extern void proc_clear_tty(struct task_struct *p); extern struct tty_struct *get_current_tty(void); /* tty_io.c */ extern int __init tty_init(void); +extern const char *tty_name(const struct tty_struct *tty); #else static inline void console_init(void) { } @@ -391,6 +392,8 @@ static inline struct tty_struct *get_current_tty(void) /* tty_io.c */ static inline int __init tty_init(void) { return 0; } +static inline const char *tty_name(const struct tty_struct *tty) +{ return "(none)"; } #endif extern struct ktermios tty_std_termios; @@ -415,7 +418,6 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty) return tty; } -extern const char *tty_name(const struct tty_struct *tty); extern const char *tty_driver_name(const struct tty_struct *tty); extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); extern int __tty_check_change(struct tty_struct *tty, int sig); -- GitLab From d839e821efc06031c927cabbbc1e976bc71f5d4f Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 25 Apr 2016 04:00:23 +0300 Subject: [PATCH 4828/9938] dt-bindings: interrupt-controllers: add description of SIC1 and SIC2 NXP LPC32xx has three interrupt controllers, namely root Main Interrupt Controller (MIC) and two supplementary Sub Interrupt Controllers (SIC1 and SIC2), four interrupt outputs from SIC1 and SIC2 are connected to MIC. Acked-by: Rob Herring Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- .../interrupt-controller/nxp,lpc3220-mic.txt | 70 ++++++++++++------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt b/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt index 539adca19e8f..38211f344dc8 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt @@ -1,38 +1,60 @@ -* NXP LPC32xx Main Interrupt Controller - (MIC, including SIC1 and SIC2 secondary controllers) +* NXP LPC32xx MIC, SIC1 and SIC2 Interrupt Controllers Required properties: -- compatible: Should be "nxp,lpc3220-mic" -- interrupt-controller: Identifies the node as an interrupt controller. -- interrupt-parent: Empty for the interrupt controller itself -- #interrupt-cells: The number of cells to define the interrupts. Should be 2. - The first cell is the IRQ number - The second cell is used to specify mode: - 1 = low-to-high edge triggered - 2 = high-to-low edge triggered - 4 = active high level-sensitive - 8 = active low level-sensitive - Default for internal sources should be set to 4 (active high). -- reg: Should contain MIC registers location and length +- compatible: "nxp,lpc3220-mic" or "nxp,lpc3220-sic". +- reg: should contain IC registers location and length. +- interrupt-controller: identifies the node as an interrupt controller. +- #interrupt-cells: the number of cells to define an interrupt, should be 2. + The first cell is the IRQ number, the second cell is used to specify + one of the supported IRQ types: + IRQ_TYPE_EDGE_RISING = low-to-high edge triggered, + IRQ_TYPE_EDGE_FALLING = high-to-low edge triggered, + IRQ_TYPE_LEVEL_HIGH = active high level-sensitive, + IRQ_TYPE_LEVEL_LOW = active low level-sensitive. + Reset value is IRQ_TYPE_LEVEL_LOW. + +Optional properties: +- interrupt-parent: empty for MIC interrupt controller, link to parent + MIC interrupt controller for SIC1 and SIC2 +- interrupts: empty for MIC interrupt controller, cascaded MIC + hardware interrupts for SIC1 and SIC2 Examples: - /* - * MIC - */ + + /* LPC32xx MIC, SIC1 and SIC2 interrupt controllers */ mic: interrupt-controller@40008000 { compatible = "nxp,lpc3220-mic"; + reg = <0x40008000 0x4000>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + sic1: interrupt-controller@4000c000 { + compatible = "nxp,lpc3220-sic"; + reg = <0x4000c000 0x4000>; interrupt-controller; - interrupt-parent; #interrupt-cells = <2>; - reg = <0x40008000 0xC000>; + + interrupt-parent = <&mic>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>, + <30 IRQ_TYPE_LEVEL_LOW>; }; - /* - * ADC - */ + sic2: interrupt-controller@40010000 { + compatible = "nxp,lpc3220-sic"; + reg = <0x40010000 0x4000>; + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&mic>; + interrupts = <1 IRQ_TYPE_LEVEL_LOW>, + <31 IRQ_TYPE_LEVEL_LOW>; + }; + + /* ADC */ adc@40048000 { compatible = "nxp,lpc3220-adc"; reg = <0x40048000 0x1000>; - interrupt-parent = <&mic>; - interrupts = <39 4>; + interrupt-parent = <&sic1>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; }; -- GitLab From 9b8ad3fb81ae198ac669a61717d3a55af1f06bf2 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 26 Apr 2016 00:02:23 +0300 Subject: [PATCH 4829/9938] ARM: dts: lpc32xx: reparent SIC1 and SIC2 interrupts from MIC The change adds separate device nodes for SIC1 and SIC2 interrupt controllers and reparents all defined SIC1 and SIC2 interrupt producers to the correspondent interrupt controller, this is needed to perform switching to a new LPC32xx MIC/SIC interrupt controller driver. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/lpc32xx.dtsi | 60 ++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index 73c474610efa..e295e1ec82a5 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -92,7 +92,8 @@ ohci: ohci@0 { compatible = "nxp,ohci-nxp", "usb-ohci"; reg = <0x0 0x300>; - interrupts = <59 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&sic1>; + interrupts = <27 IRQ_TYPE_LEVEL_HIGH>; clocks = <&usbclk LPC32XX_USB_CLK_HOST>; status = "disabled"; }; @@ -100,10 +101,11 @@ usbd: usbd@0 { compatible = "nxp,lpc3220-udc"; reg = <0x0 0x300>; - interrupts = <61 IRQ_TYPE_LEVEL_HIGH>, - <62 IRQ_TYPE_LEVEL_HIGH>, - <60 IRQ_TYPE_LEVEL_HIGH>, - <58 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&sic1>; + interrupts = <29 IRQ_TYPE_LEVEL_HIGH>, + <30 IRQ_TYPE_LEVEL_HIGH>, + <28 IRQ_TYPE_LEVEL_HIGH>, + <26 IRQ_TYPE_LEVEL_LOW>; clocks = <&usbclk LPC32XX_USB_CLK_DEVICE>; status = "disabled"; }; @@ -111,7 +113,8 @@ i2cusb: i2c@300 { compatible = "nxp,pnx-i2c"; reg = <0x300 0x100>; - interrupts = <63 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&sic1>; + interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; clocks = <&usbclk LPC32XX_USB_CLK_I2C>; #address-cells = <1>; #size-cells = <0>; @@ -263,7 +266,8 @@ i2c1: i2c@400A0000 { compatible = "nxp,pnx-i2c"; reg = <0x400A0000 0x100>; - interrupts = <51 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&sic1>; + interrupts = <19 IRQ_TYPE_LEVEL_LOW>; #address-cells = <1>; #size-cells = <0>; pnx,timeout = <0x64>; @@ -273,7 +277,8 @@ i2c2: i2c@400A8000 { compatible = "nxp,pnx-i2c"; reg = <0x400A8000 0x100>; - interrupts = <50 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&sic1>; + interrupts = <18 IRQ_TYPE_LEVEL_LOW>; #address-cells = <1>; #size-cells = <0>; pnx,timeout = <0x64>; @@ -314,19 +319,35 @@ }; }; - /* - * MIC Interrupt controller includes: - * MIC @40008000 - * SIC1 @4000C000 - * SIC2 @40010000 - */ mic: interrupt-controller@40008000 { compatible = "nxp,lpc3220-mic"; + reg = <0x40008000 0x4000>; interrupt-controller; - reg = <0x40008000 0xC000>; #interrupt-cells = <2>; }; + sic1: interrupt-controller@4000c000 { + compatible = "nxp,lpc3220-sic"; + reg = <0x4000c000 0x4000>; + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&mic>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>, + <30 IRQ_TYPE_LEVEL_LOW>; + }; + + sic2: interrupt-controller@40010000 { + compatible = "nxp,lpc3220-sic"; + reg = <0x40010000 0x4000>; + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&mic>; + interrupts = <1 IRQ_TYPE_LEVEL_LOW>, + <31 IRQ_TYPE_LEVEL_LOW>; + }; + uart1: serial@40014000 { compatible = "nxp,lpc3220-hsuart"; reg = <0x40014000 0x1000>; @@ -351,7 +372,8 @@ rtc: rtc@40024000 { compatible = "nxp,lpc3220-rtc"; reg = <0x40024000 0x1000>; - interrupts = <52 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&sic1>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_RTC>; }; @@ -404,7 +426,8 @@ adc: adc@40048000 { compatible = "nxp,lpc3220-adc"; reg = <0x40048000 0x1000>; - interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&sic1>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_ADC>; status = "disabled"; }; @@ -412,7 +435,8 @@ tsc: tsc@40048000 { compatible = "nxp,lpc3220-tsc"; reg = <0x40048000 0x1000>; - interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&sic1>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_ADC>; status = "disabled"; }; -- GitLab From 1a096afc7c27f059ebec0805bd1f52a0152e6cbf Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 27 Apr 2016 00:10:28 +0300 Subject: [PATCH 4830/9938] ARM: dts: lpc32xx: ea3250: avoid extension of device nodes by absolute path The change simplifies layout of EA3250 board description by referencing device nodes of LPC32xx controllers by label. No functional change intended. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/ea3250.dts | 226 +++++++++++++++++------------------ 1 file changed, 110 insertions(+), 116 deletions(-) diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/ea3250.dts index a4a281fe82af..7cf815a51235 100644 --- a/arch/arm/boot/dts/ea3250.dts +++ b/arch/arm/boot/dts/ea3250.dts @@ -25,119 +25,6 @@ reg = <0x80000000 0x4000000>; }; - ahb { - mac: ethernet@31060000 { - phy-mode = "rmii"; - use-iram; - }; - - /* 128MB Flash via SLC NAND controller */ - slc: flash@20020000 { - status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - - nxp,wdr-clks = <14>; - nxp,wwidth = <260000000>; - nxp,whold = <104000000>; - nxp,wsetup = <200000000>; - nxp,rdr-clks = <14>; - nxp,rwidth = <34666666>; - nxp,rhold = <104000000>; - nxp,rsetup = <200000000>; - nand-on-flash-bbt; - gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ - - mtd0@00000000 { - label = "ea3250-boot"; - reg = <0x00000000 0x00080000>; - read-only; - }; - - mtd1@00080000 { - label = "ea3250-uboot"; - reg = <0x00080000 0x000c0000>; - read-only; - }; - - mtd2@00140000 { - label = "ea3250-kernel"; - reg = <0x00140000 0x00400000>; - }; - - mtd3@00540000 { - label = "ea3250-rootfs"; - reg = <0x00540000 0x07ac0000>; - }; - }; - - apb { - uart5: serial@40090000 { - status = "okay"; - }; - - uart3: serial@40080000 { - status = "okay"; - }; - - uart6: serial@40098000 { - status = "okay"; - }; - - i2c1: i2c@400A0000 { - clock-frequency = <100000>; - - eeprom@50 { - compatible = "at,24c256"; - reg = <0x50>; - }; - - eeprom@57 { - compatible = "at,24c64"; - reg = <0x57>; - }; - - uda1380: uda1380@18 { - compatible = "nxp,uda1380"; - reg = <0x18>; - power-gpio = <&gpio 0x59 0>; - reset-gpio = <&gpio 0x51 0>; - dac-clk = "wspll"; - }; - - pca9532: pca9532@60 { - compatible = "nxp,pca9532"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x60>; - }; - }; - - i2c2: i2c@400A8000 { - clock-frequency = <100000>; - }; - - sd@20098000 { - wp-gpios = <&pca9532 5 0>; - cd-gpios = <&pca9532 4 0>; - cd-inverted; - bus-width = <4>; - status = "okay"; - }; - }; - - fab { - uart1: serial@40014000 { - status = "okay"; - }; - - /* 3-axis accelerometer X,Y,Z (or AD-IN instead of Z) */ - adc@40048000 { - status = "okay"; - }; - }; - }; - gpio_keys { compatible = "gpio-keys"; #address-cells = <1>; @@ -258,12 +145,44 @@ }; }; -/* Here, choose exactly one from: ohci, usbd */ -&ohci /* &usbd */ { - transceiver = <&isp1301>; +/* 3-axis accelerometer X,Y,Z (or AD-IN instead of Z) */ +&adc { status = "okay"; }; +&i2c1 { + clock-frequency = <100000>; + + uda1380: uda1380@18 { + compatible = "nxp,uda1380"; + reg = <0x18>; + power-gpio = <&gpio 0x59 0>; + reset-gpio = <&gpio 0x51 0>; + dac-clk = "wspll"; + }; + + eeprom@50 { + compatible = "at,24c256"; + reg = <0x50>; + }; + + eeprom@57 { + compatible = "at,24c64"; + reg = <0x57>; + }; + + pca9532: pca9532@60 { + compatible = "nxp,pca9532"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60>; + }; +}; + +&i2c2 { + clock-frequency = <100000>; +}; + &i2cusb { clock-frequency = <100000>; @@ -272,3 +191,78 @@ reg = <0x2d>; }; }; + +&mac { + phy-mode = "rmii"; + use-iram; +}; + +/* Here, choose exactly one from: ohci, usbd */ +&ohci /* &usbd */ { + transceiver = <&isp1301>; + status = "okay"; +}; + +&sd { + wp-gpios = <&pca9532 5 0>; + cd-gpios = <&pca9532 4 0>; + cd-inverted; + bus-width = <4>; + status = "okay"; +}; + +/* 128MB Flash via SLC NAND controller */ +&slc { + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + nxp,wdr-clks = <14>; + nxp,wwidth = <260000000>; + nxp,whold = <104000000>; + nxp,wsetup = <200000000>; + nxp,rdr-clks = <14>; + nxp,rwidth = <34666666>; + nxp,rhold = <104000000>; + nxp,rsetup = <200000000>; + nand-on-flash-bbt; + gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ + + mtd0@00000000 { + label = "ea3250-boot"; + reg = <0x00000000 0x00080000>; + read-only; + }; + + mtd1@00080000 { + label = "ea3250-uboot"; + reg = <0x00080000 0x000c0000>; + read-only; + }; + + mtd2@00140000 { + label = "ea3250-kernel"; + reg = <0x00140000 0x00400000>; + }; + + mtd3@00540000 { + label = "ea3250-rootfs"; + reg = <0x00540000 0x07ac0000>; + }; +}; + +&uart1 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&uart5 { + status = "okay"; +}; + +&uart6 { + status = "okay"; +}; -- GitLab From 72fa28e266317488738cded858c18c67488c2c04 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 27 Apr 2016 00:10:29 +0300 Subject: [PATCH 4831/9938] ARM: dts: lpc32xx: ea3250: add NAND partitions device node To declare MTD OF partitions NAND controller device node should have a special 'partitions' subnode, the change removes a debug message from mtd/ofpart on boot: nxp_lpc3220_slc: 'partitions' subnode not found on /ahb/flash@20020000. Trying to parse direct subnodes as partitions. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/ea3250.dts | 42 ++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/ea3250.dts index 7cf815a51235..9637ac507302 100644 --- a/arch/arm/boot/dts/ea3250.dts +++ b/arch/arm/boot/dts/ea3250.dts @@ -213,8 +213,6 @@ /* 128MB Flash via SLC NAND controller */ &slc { - #address-cells = <1>; - #size-cells = <1>; status = "okay"; nxp,wdr-clks = <14>; @@ -228,26 +226,32 @@ nand-on-flash-bbt; gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ - mtd0@00000000 { - label = "ea3250-boot"; - reg = <0x00000000 0x00080000>; - read-only; - }; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - mtd1@00080000 { - label = "ea3250-uboot"; - reg = <0x00080000 0x000c0000>; - read-only; - }; + mtd0@00000000 { + label = "ea3250-boot"; + reg = <0x00000000 0x00080000>; + read-only; + }; - mtd2@00140000 { - label = "ea3250-kernel"; - reg = <0x00140000 0x00400000>; - }; + mtd1@00080000 { + label = "ea3250-uboot"; + reg = <0x00080000 0x000c0000>; + read-only; + }; - mtd3@00540000 { - label = "ea3250-rootfs"; - reg = <0x00540000 0x07ac0000>; + mtd2@00140000 { + label = "ea3250-kernel"; + reg = <0x00140000 0x00400000>; + }; + + mtd3@00540000 { + label = "ea3250-rootfs"; + reg = <0x00540000 0x07ac0000>; + }; }; }; -- GitLab From 118e24cd626b8857b94eefec6f1108fef4017e51 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 27 Apr 2016 00:10:30 +0300 Subject: [PATCH 4832/9938] ARM: dts: lpc32xx: ea3250: fix Atmel at24 eeprom vendor There is no 'at' hardware vendor defined yet, correct vendor prefix for Atmel is 'atmel'. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/ea3250.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/ea3250.dts index 9637ac507302..52b3ed10283a 100644 --- a/arch/arm/boot/dts/ea3250.dts +++ b/arch/arm/boot/dts/ea3250.dts @@ -162,12 +162,12 @@ }; eeprom@50 { - compatible = "at,24c256"; + compatible = "atmel,24c256"; reg = <0x50>; }; eeprom@57 { - compatible = "at,24c64"; + compatible = "atmel,24c64"; reg = <0x57>; }; -- GitLab From d9a95d57647bc93f41f13a4ec6eafc1ebef7b533 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 27 Apr 2016 00:10:31 +0300 Subject: [PATCH 4833/9938] ARM: dts: lpc32xx: ea3250: add SoC name prefix to board dts file To simplify matching of DTS files of all NXP LPC32xx powered boards by a file name add 'lpc3250' prefix to Embedded Artists LPC3250 board dts file. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/Makefile | 3 ++- arch/arm/boot/dts/{ea3250.dts => lpc3250-ea3250.dts} | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename arch/arm/boot/dts/{ea3250.dts => lpc3250-ea3250.dts} (100%) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 95c1923ce6fa..9f8b14fd5b26 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -241,7 +241,8 @@ dtb-$(CONFIG_ARCH_LPC18XX) += \ lpc4350-hitex-eval.dtb \ lpc4357-ea4357-devkit.dtb dtb-$(CONFIG_ARCH_LPC32XX) += \ - ea3250.dtb phy3250.dtb + lpc3250-ea3250.dtb \ + phy3250.dtb dtb-$(CONFIG_MACH_MESON6) += \ meson6-atv1200.dtb dtb-$(CONFIG_MACH_MESON8) += \ diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/lpc3250-ea3250.dts similarity index 100% rename from arch/arm/boot/dts/ea3250.dts rename to arch/arm/boot/dts/lpc3250-ea3250.dts -- GitLab From 6101f4bcb3d087b39a1d105d07bc72c9bd1194cb Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 27 Apr 2016 00:10:32 +0300 Subject: [PATCH 4834/9938] ARM: dts: lpc32xx: phy3250: avoid extension of device nodes by absolute path The change simplifies layout of PHY3250 board description by referencing device nodes of LPC32xx controllers by label. No functional change intended. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/phy3250.dts | 282 +++++++++++++++++----------------- 1 file changed, 138 insertions(+), 144 deletions(-) diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index 26e070fe9a58..c1a6e624bf19 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -56,147 +56,6 @@ }; }; - ahb { - mac: ethernet@31060000 { - phy-mode = "rmii"; - use-iram; - }; - - clcd@31040000 { - status = "okay"; - }; - - /* 64MB Flash via SLC NAND controller */ - slc: flash@20020000 { - status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - - nxp,wdr-clks = <14>; - nxp,wwidth = <40000000>; - nxp,whold = <100000000>; - nxp,wsetup = <100000000>; - nxp,rdr-clks = <14>; - nxp,rwidth = <40000000>; - nxp,rhold = <66666666>; - nxp,rsetup = <100000000>; - nand-on-flash-bbt; - gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ - - mtd0@00000000 { - label = "phy3250-boot"; - reg = <0x00000000 0x00064000>; - read-only; - }; - - mtd1@00064000 { - label = "phy3250-uboot"; - reg = <0x00064000 0x00190000>; - read-only; - }; - - mtd2@001f4000 { - label = "phy3250-ubt-prms"; - reg = <0x001f4000 0x00010000>; - }; - - mtd3@00204000 { - label = "phy3250-kernel"; - reg = <0x00204000 0x00400000>; - }; - - mtd4@00604000 { - label = "phy3250-rootfs"; - reg = <0x00604000 0x039fc000>; - }; - }; - - apb { - uart5: serial@40090000 { - status = "okay"; - }; - - uart3: serial@40080000 { - status = "okay"; - }; - - i2c1: i2c@400A0000 { - clock-frequency = <100000>; - - pcf8563: rtc@51 { - compatible = "nxp,pcf8563"; - reg = <0x51>; - }; - - uda1380: uda1380@18 { - compatible = "nxp,uda1380"; - reg = <0x18>; - power-gpio = <&gpio 0x59 0>; - reset-gpio = <&gpio 0x51 0>; - dac-clk = "wspll"; - }; - }; - - i2c2: i2c@400A8000 { - clock-frequency = <100000>; - }; - - ssp0: ssp@20084000 { - #address-cells = <1>; - #size-cells = <0>; - num-cs = <1>; - cs-gpios = <&gpio 3 5 0>; - status = "okay"; - - eeprom: at25@0 { - pl022,interface = <0>; - pl022,com-mode = <0>; - pl022,rx-level-trig = <1>; - pl022,tx-level-trig = <1>; - pl022,ctrl-len = <11>; - pl022,wait-state = <0>; - pl022,duplex = <0>; - - at25,byte-len = <0x8000>; - at25,addr-mode = <2>; - at25,page-size = <64>; - - compatible = "atmel,at25"; - reg = <0>; - spi-max-frequency = <5000000>; - }; - }; - - sd@20098000 { - wp-gpios = <&gpio 3 0 0>; - cd-gpios = <&gpio 3 1 0>; - cd-inverted; - bus-width = <4>; - vmmc-supply = <&sd_reg>; - status = "okay"; - }; - }; - - fab { - uart2: serial@40018000 { - status = "okay"; - }; - - tsc@40048000 { - status = "okay"; - }; - - key@40050000 { - status = "okay"; - keypad,num-rows = <1>; - keypad,num-columns = <1>; - nxp,debounce-delay-ms = <3>; - nxp,scan-delay-ms = <34>; - linux,keymap = <0x00000002>; - }; - }; - }; - leds { compatible = "gpio-leds"; @@ -212,12 +71,31 @@ }; }; -/* Here, choose exactly one from: ohci, usbd */ -&ohci /* &usbd */ { - transceiver = <&isp1301>; +&clcd { status = "okay"; }; +&i2c1 { + clock-frequency = <100000>; + + uda1380: uda1380@18 { + compatible = "nxp,uda1380"; + reg = <0x18>; + power-gpio = <&gpio 0x59 0>; + reset-gpio = <&gpio 0x51 0>; + dac-clk = "wspll"; + }; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&i2c2 { + clock-frequency = <100000>; +}; + &i2cusb { clock-frequency = <100000>; @@ -226,3 +104,119 @@ reg = <0x2c>; }; }; + +&key { + keypad,num-rows = <1>; + keypad,num-columns = <1>; + nxp,debounce-delay-ms = <3>; + nxp,scan-delay-ms = <34>; + linux,keymap = <0x00000002>; + status = "okay"; +}; + +&mac { + phy-mode = "rmii"; + use-iram; +}; + +/* Here, choose exactly one from: ohci, usbd */ +&ohci /* &usbd */ { + transceiver = <&isp1301>; + status = "okay"; +}; + +&sd { + wp-gpios = <&gpio 3 0 0>; + cd-gpios = <&gpio 3 1 0>; + cd-inverted; + bus-width = <4>; + vmmc-supply = <&sd_reg>; + status = "okay"; +}; + +/* 64MB Flash via SLC NAND controller */ +&slc { + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + nxp,wdr-clks = <14>; + nxp,wwidth = <40000000>; + nxp,whold = <100000000>; + nxp,wsetup = <100000000>; + nxp,rdr-clks = <14>; + nxp,rwidth = <40000000>; + nxp,rhold = <66666666>; + nxp,rsetup = <100000000>; + nand-on-flash-bbt; + gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ + + mtd0@00000000 { + label = "phy3250-boot"; + reg = <0x00000000 0x00064000>; + read-only; + }; + + mtd1@00064000 { + label = "phy3250-uboot"; + reg = <0x00064000 0x00190000>; + read-only; + }; + + mtd2@001f4000 { + label = "phy3250-ubt-prms"; + reg = <0x001f4000 0x00010000>; + }; + + mtd3@00204000 { + label = "phy3250-kernel"; + reg = <0x00204000 0x00400000>; + }; + + mtd4@00604000 { + label = "phy3250-rootfs"; + reg = <0x00604000 0x039fc000>; + }; +}; + +&ssp0 { + #address-cells = <1>; + #size-cells = <0>; + num-cs = <1>; + cs-gpios = <&gpio 3 5 0>; + status = "okay"; + + eeprom: at25@0 { + compatible = "atmel,at25"; + reg = <0>; + spi-max-frequency = <5000000>; + + pl022,interface = <0>; + pl022,com-mode = <0>; + pl022,rx-level-trig = <1>; + pl022,tx-level-trig = <1>; + pl022,ctrl-len = <11>; + pl022,wait-state = <0>; + pl022,duplex = <0>; + + at25,byte-len = <0x8000>; + at25,addr-mode = <2>; + at25,page-size = <64>; + }; +}; + +&tsc { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&uart5 { + status = "okay"; +}; -- GitLab From 9cfde0a1fede26cbeff0b6eba48bf7fd375e5c8c Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 27 Apr 2016 00:10:33 +0300 Subject: [PATCH 4835/9938] ARM: dts: lpc32xx: phy3250: add NAND partitions device node To declare MTD OF partitions NAND controller device node should have a special 'partitions' subnode, the change removes a debug message from mtd/ofpart on boot: nxp_lpc3220_slc: 'partitions' subnode not found on /ahb/flash@20020000. Trying to parse direct subnodes as partitions. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/phy3250.dts | 50 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts index c1a6e624bf19..fd95e2b10357 100644 --- a/arch/arm/boot/dts/phy3250.dts +++ b/arch/arm/boot/dts/phy3250.dts @@ -136,8 +136,6 @@ /* 64MB Flash via SLC NAND controller */ &slc { - #address-cells = <1>; - #size-cells = <1>; status = "okay"; nxp,wdr-clks = <14>; @@ -151,31 +149,37 @@ nand-on-flash-bbt; gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */ - mtd0@00000000 { - label = "phy3250-boot"; - reg = <0x00000000 0x00064000>; - read-only; - }; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - mtd1@00064000 { - label = "phy3250-uboot"; - reg = <0x00064000 0x00190000>; - read-only; - }; + mtd0@00000000 { + label = "phy3250-boot"; + reg = <0x00000000 0x00064000>; + read-only; + }; - mtd2@001f4000 { - label = "phy3250-ubt-prms"; - reg = <0x001f4000 0x00010000>; - }; + mtd1@00064000 { + label = "phy3250-uboot"; + reg = <0x00064000 0x00190000>; + read-only; + }; - mtd3@00204000 { - label = "phy3250-kernel"; - reg = <0x00204000 0x00400000>; - }; + mtd2@001f4000 { + label = "phy3250-ubt-prms"; + reg = <0x001f4000 0x00010000>; + }; - mtd4@00604000 { - label = "phy3250-rootfs"; - reg = <0x00604000 0x039fc000>; + mtd3@00204000 { + label = "phy3250-kernel"; + reg = <0x00204000 0x00400000>; + }; + + mtd4@00604000 { + label = "phy3250-rootfs"; + reg = <0x00604000 0x039fc000>; + }; }; }; -- GitLab From 3ff11fe8e8195d87090df9ffabfc85b4d35054c2 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 27 Apr 2016 00:10:34 +0300 Subject: [PATCH 4836/9938] ARM: dts: lpc32xx: phy3250: add SoC name prefix to board dts file To simplify matching of DTS files of all NXP LPC32xx powered boards by a file name add 'lpc3250' prefix to PHYTEC PHYCORE-LPC3250 board dts file. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/boot/dts/Makefile | 2 +- arch/arm/boot/dts/{phy3250.dts => lpc3250-phy3250.dts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/arm/boot/dts/{phy3250.dts => lpc3250-phy3250.dts} (100%) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9f8b14fd5b26..4733ec9e5b23 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -242,7 +242,7 @@ dtb-$(CONFIG_ARCH_LPC18XX) += \ lpc4357-ea4357-devkit.dtb dtb-$(CONFIG_ARCH_LPC32XX) += \ lpc3250-ea3250.dtb \ - phy3250.dtb + lpc3250-phy3250.dtb dtb-$(CONFIG_MACH_MESON6) += \ meson6-atv1200.dtb dtb-$(CONFIG_MACH_MESON8) += \ diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/lpc3250-phy3250.dts similarity index 100% rename from arch/arm/boot/dts/phy3250.dts rename to arch/arm/boot/dts/lpc3250-phy3250.dts -- GitLab From cdd9a6b2a7461021a5ee24bc130592c1bdc54cd8 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:27:46 -0700 Subject: [PATCH 4837/9938] ACPI / APD: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Signed-off-by: Stephen Boyd Acked-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_apd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index f245bf35bedb..1daf9c46df8e 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -62,8 +62,7 @@ static int acpi_apd_setup(struct apd_private_data *pdata) if (dev_desc->fixed_clk_rate) { clk = clk_register_fixed_rate(&pdata->adev->dev, dev_name(&pdata->adev->dev), - NULL, CLK_IS_ROOT, - dev_desc->fixed_clk_rate); + NULL, 0, dev_desc->fixed_clk_rate); clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev)); pdata->clk = clk; } -- GitLab From 628e35baa8e1e19217eb11b6ccfa96c273757d18 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 19 Apr 2016 18:28:38 -0700 Subject: [PATCH 4838/9938] ACPI / amba: Remove CLK_IS_ROOT This flag is a no-op now (see commit 47b0eeb3dc8a "clk: Deprecate CLK_IS_ROOT", 2016-02-02) so remove it. Signed-off-by: Stephen Boyd Acked-by: Graeme Gregory Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_amba.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/acpi/acpi_amba.c b/drivers/acpi/acpi_amba.c index 2a61b54ab968..7f77c071709a 100644 --- a/drivers/acpi/acpi_amba.c +++ b/drivers/acpi/acpi_amba.c @@ -35,8 +35,7 @@ static void amba_register_dummy_clk(void) if (amba_dummy_clk) return; - amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, - CLK_IS_ROOT, 0); + amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 0); clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL); } -- GitLab From 715552aa30ffe3bd776bb7635056f6622a29133d Mon Sep 17 00:00:00 2001 From: Sylvain Lemieux Date: Mon, 4 Apr 2016 15:48:34 -0400 Subject: [PATCH 4839/9938] ARM: lpc32xx: remove reboot header file The header file "reboot.h" is no longer needed, following the migration of the restart code into the pnx4008 watchdog. Signed-off-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/mach-lpc32xx/common.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h index 2d90801ed1e1..9b5ae42d3a6f 100644 --- a/arch/arm/mach-lpc32xx/common.h +++ b/arch/arm/mach-lpc32xx/common.h @@ -21,7 +21,6 @@ #include #include -#include /* * Other arch specific structures and functions -- GitLab From d82b4b0a5ebeb55c3b88e49b38135a847736e6b5 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 18 Apr 2016 04:05:25 +0300 Subject: [PATCH 4840/9938] ARM: lpc32xx: remove leftovers of legacy clock source and provider drivers After switching the platform to common clock framework there is no more need to keep dead code in arch/arm/mach-lpc32xx, which glued legacy clock source and clock provider drivers, remove the leftovers. Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/mach-lpc32xx/common.c | 95 ---------------------------------- arch/arm/mach-lpc32xx/common.h | 23 +------- 2 files changed, 1 insertion(+), 117 deletions(-) diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c index 5b7a1e78c3a5..2f6067bce7c3 100644 --- a/arch/arm/mach-lpc32xx/common.c +++ b/arch/arm/mach-lpc32xx/common.c @@ -17,13 +17,6 @@ */ #include -#include -#include -#include -#include -#include -#include -#include #include #include @@ -43,19 +36,6 @@ void lpc32xx_get_uid(u32 devid[4]) devid[i] = __raw_readl(LPC32XX_CLKPWR_DEVID(i << 2)); } -/* - * Returns SYSCLK source - * 0 = PLL397, 1 = main oscillator - */ -int clk_is_sysclk_mainosc(void) -{ - if ((__raw_readl(LPC32XX_CLKPWR_SYSCLK_CTRL) & - LPC32XX_CLKPWR_SYSCTRL_SYSCLKMUX) == 0) - return 1; - - return 0; -} - /* * Detects and returns IRAM size for the device variation */ @@ -87,81 +67,6 @@ u32 lpc32xx_return_iram_size(void) } EXPORT_SYMBOL_GPL(lpc32xx_return_iram_size); -/* - * Computes PLL rate from PLL register and input clock - */ -u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup) -{ - u32 ilfreq, p, m, n, fcco, fref, cfreq; - int mode; - - /* - * PLL requirements - * ifreq must be >= 1MHz and <= 20MHz - * FCCO must be >= 156MHz and <= 320MHz - * FREF must be >= 1MHz and <= 27MHz - * Assume the passed input data is not valid - */ - - ilfreq = ifreq; - m = pllsetup->pll_m; - n = pllsetup->pll_n; - p = pllsetup->pll_p; - - mode = (pllsetup->cco_bypass_b15 << 2) | - (pllsetup->direct_output_b14 << 1) | - pllsetup->fdbk_div_ctrl_b13; - - switch (mode) { - case 0x0: /* Non-integer mode */ - cfreq = (m * ilfreq) / (2 * p * n); - fcco = (m * ilfreq) / n; - fref = ilfreq / n; - break; - - case 0x1: /* integer mode */ - cfreq = (m * ilfreq) / n; - fcco = (m * ilfreq) / (n * 2 * p); - fref = ilfreq / n; - break; - - case 0x2: - case 0x3: /* Direct mode */ - cfreq = (m * ilfreq) / n; - fcco = cfreq; - fref = ilfreq / n; - break; - - case 0x4: - case 0x5: /* Bypass mode */ - cfreq = ilfreq / (2 * p); - fcco = 156000000; - fref = 1000000; - break; - - case 0x6: - case 0x7: /* Direct bypass mode */ - default: - cfreq = ilfreq; - fcco = 156000000; - fref = 1000000; - break; - } - - if (fcco < 156000000 || fcco > 320000000) - cfreq = 0; - - if (fref < 1000000 || fref > 27000000) - cfreq = 0; - - return (u32) cfreq; -} - -u32 clk_get_pclk_div(void) -{ - return 1 + ((__raw_readl(LPC32XX_CLKPWR_HCLK_DIV) >> 2) & 0x1F); -} - static struct map_desc lpc32xx_io_desc[] __initdata = { { .virtual = (unsigned long)IO_ADDRESS(LPC32XX_AHB0_START), diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h index 9b5ae42d3a6f..30c9e64fc65b 100644 --- a/arch/arm/mach-lpc32xx/common.h +++ b/arch/arm/mach-lpc32xx/common.h @@ -19,36 +19,15 @@ #ifndef __LPC32XX_COMMON_H #define __LPC32XX_COMMON_H -#include -#include +#include /* * Other arch specific structures and functions */ -extern void lpc32xx_timer_init(void); extern void __init lpc32xx_init_irq(void); extern void __init lpc32xx_map_io(void); extern void __init lpc32xx_serial_init(void); - -/* - * Structure used for setting up and querying the PLLS - */ -struct clk_pll_setup { - int analog_on; - int cco_bypass_b15; - int direct_output_b14; - int fdbk_div_ctrl_b13; - int pll_p; - int pll_n; - u32 pll_m; -}; - -extern int clk_is_sysclk_mainosc(void); -extern u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup); -extern u32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval); -extern u32 clk_get_pclk_div(void); - /* * Returns the LPC32xx unique 128-bit chip ID */ -- GitLab From 71d42e9c71d7fca2eca98eac315cb485b5d2314d Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Mon, 18 Apr 2016 04:37:38 +0300 Subject: [PATCH 4841/9938] ARM: lpc32xx: remove duplicate const on lpc32xx_auxdata_lookup Remove redundant duplicate const, which is found by smatch: arch/arm/mach-lpc32xx/phy3250.c:162:42: warning: duplicate const Acked-by: Sylvain Lemieux Signed-off-by: Vladimir Zapolskiy --- arch/arm/mach-lpc32xx/phy3250.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index b2f9e226febe..1ae723072521 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -159,7 +159,7 @@ static struct lpc32xx_mlc_platform_data lpc32xx_mlc_data = { .dma_filter = pl08x_filter_id, }; -static const struct of_dev_auxdata const lpc32xx_auxdata_lookup[] __initconst = { +static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", NULL), OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", NULL), OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data), -- GitLab From 2920e9ce8f43a946e3c257a7c0ee35b02149fca7 Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Tue, 19 Apr 2016 15:28:00 +0530 Subject: [PATCH 4842/9938] cpufreq: powernv: Remove flag use-case of policy->driver_data commit 1b0289848d5d ("cpufreq: powernv: Add sysfs attributes to show throttle stats") used policy->driver_data as a flag for one-time creation of throttle sysfs files. Instead of this use 'kernfs_find_and_get()' to check if the attribute already exists. This is required as policy->driver_data is used for other purposes in the later patch. Signed-off-by: Shilpasri G Bhat Signed-off-by: Akshay Adiga Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 39ac78c94be0..e2e221904d25 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -455,13 +455,15 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) { int base, i; + struct kernfs_node *kn; base = cpu_first_thread_sibling(policy->cpu); for (i = 0; i < threads_per_core; i++) cpumask_set_cpu(base + i, policy->cpus); - if (!policy->driver_data) { + kn = kernfs_find_and_get(policy->kobj.sd, throttle_attr_grp.name); + if (!kn) { int ret; ret = sysfs_create_group(&policy->kobj, &throttle_attr_grp); @@ -470,11 +472,8 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpu); return ret; } - /* - * policy->driver_data is used as a flag for one-time - * creation of throttle sysfs files. - */ - policy->driver_data = policy; + } else { + kernfs_put(kn); } return cpufreq_table_validate_and_show(policy, powernv_freqs); } -- GitLab From eaa2c3aeef83f096cd1ec73df1310712e423337b Mon Sep 17 00:00:00 2001 From: Akshay Adiga Date: Tue, 19 Apr 2016 15:28:01 +0530 Subject: [PATCH 4843/9938] cpufreq: powernv: Ramp-down global pstate slower than local-pstate The frequency transition latency from pmin to pmax is observed to be in few millisecond granurality. And it usually happens to take a performance penalty during sudden frequency rampup requests. This patch set solves this problem by using an entity called "global pstates". The global pstate is a Chip-level entity, so the global entitiy (Voltage) is managed across the cores. The local pstate is a Core-level entity, so the local entity (frequency) is managed across threads. This patch brings down global pstate at a slower rate than the local pstate. Hence by holding global pstates higher than local pstate makes the subsequent rampups faster. A per policy structure is maintained to keep track of the global and local pstate changes. The global pstate is brought down using a parabolic equation. The ramp down time to pmin is set to ~5 seconds. To make sure that the global pstates are dropped at regular interval , a timer is queued for every 2 seconds during ramp-down phase, which eventually brings the pstate down to local pstate. Iozone results show fairly consistent performance boost. YCSB on redis shows improved Max latencies in most cases. Iozone write/rewite test were made with filesizes 200704Kb and 401408Kb with different record sizes . The following table shows IOoperations/sec with and without patch. Iozone Results ( in op/sec) ( mean over 3 iterations ) --------------------------------------------------------------------- file size- with without % recordsize-IOtype patch patch change ---------------------------------------------------------------------- 200704-1-SeqWrite 1616532 1615425 0.06 200704-1-Rewrite 2423195 2303130 5.21 200704-2-SeqWrite 1628577 1602620 1.61 200704-2-Rewrite 2428264 2312154 5.02 200704-4-SeqWrite 1617605 1617182 0.02 200704-4-Rewrite 2430524 2351238 3.37 200704-8-SeqWrite 1629478 1600436 1.81 200704-8-Rewrite 2415308 2298136 5.09 200704-16-SeqWrite 1619632 1618250 0.08 200704-16-Rewrite 2396650 2352591 1.87 200704-32-SeqWrite 1632544 1598083 2.15 200704-32-Rewrite 2425119 2329743 4.09 200704-64-SeqWrite 1617812 1617235 0.03 200704-64-Rewrite 2402021 2321080 3.48 200704-128-SeqWrite 1631998 1600256 1.98 200704-128-Rewrite 2422389 2304954 5.09 200704-256 SeqWrite 1617065 1616962 0.00 200704-256-Rewrite 2432539 2301980 5.67 200704-512-SeqWrite 1632599 1598656 2.12 200704-512-Rewrite 2429270 2323676 4.54 200704-1024-SeqWrite 1618758 1616156 0.16 200704-1024-Rewrite 2431631 2315889 4.99 401408-1-SeqWrite 1631479 1608132 1.45 401408-1-Rewrite 2501550 2459409 1.71 401408-2-SeqWrite 1617095 1626069 -0.55 401408-2-Rewrite 2507557 2443621 2.61 401408-4-SeqWrite 1629601 1611869 1.10 401408-4-Rewrite 2505909 2462098 1.77 401408-8-SeqWrite 1617110 1626968 -0.60 401408-8-Rewrite 2512244 2456827 2.25 401408-16-SeqWrite 1632609 1609603 1.42 401408-16-Rewrite 2500792 2451405 2.01 401408-32-SeqWrite 1619294 1628167 -0.54 401408-32-Rewrite 2510115 2451292 2.39 401408-64-SeqWrite 1632709 1603746 1.80 401408-64-Rewrite 2506692 2433186 3.02 401408-128-SeqWrite 1619284 1627461 -0.50 401408-128-Rewrite 2518698 2453361 2.66 401408-256-SeqWrite 1634022 1610681 1.44 401408-256-Rewrite 2509987 2446328 2.60 401408-512-SeqWrite 1617524 1628016 -0.64 401408-512-Rewrite 2504409 2442899 2.51 401408-1024-SeqWrite 1629812 1611566 1.13 401408-1024-Rewrite 2507620 2442968 2.64 Tested with YCSB workload (50% update + 50% read) over redis for 1 million records and 1 million operation. Each test was carried out with target operations per second and persistence disabled. Max-latency (in us)( mean over 5 iterations ) --------------------------------------------------------------- op/s Operation with patch without patch %change --------------------------------------------------------------- 15000 Read 61480.6 50261.4 22.32 15000 cleanup 215.2 293.6 -26.70 15000 update 25666.2 25163.8 2.00 25000 Read 32626.2 89525.4 -63.56 25000 cleanup 292.2 263.0 11.10 25000 update 32293.4 90255.0 -64.22 35000 Read 34783.0 33119.0 5.02 35000 cleanup 321.2 395.8 -18.8 35000 update 36047.0 38747.8 -6.97 40000 Read 38562.2 42357.4 -8.96 40000 cleanup 371.8 384.6 -3.33 40000 update 27861.4 41547.8 -32.94 45000 Read 42271.0 88120.6 -52.03 45000 cleanup 263.6 383.0 -31.17 45000 update 29755.8 81359.0 -63.43 (test without target op/s) 47659 Read 83061.4 136440.6 -39.12 47659 cleanup 195.8 193.8 1.03 47659 update 73429.4 124971.8 -41.24 Signed-off-by: Akshay Adiga Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 258 +++++++++++++++++++++++++++++- 1 file changed, 251 insertions(+), 7 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index e2e221904d25..144c73211926 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -36,12 +36,56 @@ #include #include /* Required for cpu_sibling_mask() in UP configs */ #include +#include #define POWERNV_MAX_PSTATES 256 #define PMSR_PSAFE_ENABLE (1UL << 30) #define PMSR_SPR_EM_DISABLE (1UL << 31) #define PMSR_MAX(x) ((x >> 32) & 0xFF) +#define MAX_RAMP_DOWN_TIME 5120 +/* + * On an idle system we want the global pstate to ramp-down from max value to + * min over a span of ~5 secs. Also we want it to initially ramp-down slowly and + * then ramp-down rapidly later on. + * + * This gives a percentage rampdown for time elapsed in milliseconds. + * ramp_down_percentage = ((ms * ms) >> 18) + * ~= 3.8 * (sec * sec) + * + * At 0 ms ramp_down_percent = 0 + * At 5120 ms ramp_down_percent = 100 + */ +#define ramp_down_percent(time) ((time * time) >> 18) + +/* Interval after which the timer is queued to bring down global pstate */ +#define GPSTATE_TIMER_INTERVAL 2000 + +/** + * struct global_pstate_info - Per policy data structure to maintain history of + * global pstates + * @highest_lpstate: The local pstate from which we are ramping down + * @elapsed_time: Time in ms spent in ramping down from + * highest_lpstate + * @last_sampled_time: Time from boot in ms when global pstates were + * last set + * @last_lpstate,last_gpstate: Last set values for local and global pstates + * @timer: Is used for ramping down if cpu goes idle for + * a long time with global pstate held high + * @gpstate_lock: A spinlock to maintain synchronization between + * routines called by the timer handler and + * governer's target_index calls + */ +struct global_pstate_info { + int highest_lpstate; + unsigned int elapsed_time; + unsigned int last_sampled_time; + int last_lpstate; + int last_gpstate; + spinlock_t gpstate_lock; + struct timer_list timer; +}; + static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; static bool rebooting, throttled, occ_reset; @@ -94,6 +138,17 @@ static struct powernv_pstate_info { int nr_pstates; } powernv_pstate_info; +static inline void reset_gpstates(struct cpufreq_policy *policy) +{ + struct global_pstate_info *gpstates = policy->driver_data; + + gpstates->highest_lpstate = 0; + gpstates->elapsed_time = 0; + gpstates->last_sampled_time = 0; + gpstates->last_lpstate = 0; + gpstates->last_gpstate = 0; +} + /* * Initialize the freq table based on data obtained * from the firmware passed via device-tree @@ -285,6 +340,7 @@ static inline void set_pmspr(unsigned long sprn, unsigned long val) struct powernv_smp_call_data { unsigned int freq; int pstate_id; + int gpstate_id; }; /* @@ -343,19 +399,21 @@ static unsigned int powernv_cpufreq_get(unsigned int cpu) * (struct powernv_smp_call_data *) and the pstate_id which needs to be set * on this CPU should be present in freq_data->pstate_id. */ -static void set_pstate(void *freq_data) +static void set_pstate(void *data) { unsigned long val; - unsigned long pstate_ul = - ((struct powernv_smp_call_data *) freq_data)->pstate_id; + struct powernv_smp_call_data *freq_data = data; + unsigned long pstate_ul = freq_data->pstate_id; + unsigned long gpstate_ul = freq_data->gpstate_id; val = get_pmspr(SPRN_PMCR); val = val & 0x0000FFFFFFFFFFFFULL; pstate_ul = pstate_ul & 0xFF; + gpstate_ul = gpstate_ul & 0xFF; /* Set both global(bits 56..63) and local(bits 48..55) PStates */ - val = val | (pstate_ul << 56) | (pstate_ul << 48); + val = val | (gpstate_ul << 56) | (pstate_ul << 48); pr_debug("Setting cpu %d pmcr to %016lX\n", raw_smp_processor_id(), val); @@ -424,6 +482,110 @@ static void powernv_cpufreq_throttle_check(void *data) } } +/** + * calc_global_pstate - Calculate global pstate + * @elapsed_time: Elapsed time in milliseconds + * @local_pstate: New local pstate + * @highest_lpstate: pstate from which its ramping down + * + * Finds the appropriate global pstate based on the pstate from which its + * ramping down and the time elapsed in ramping down. It follows a quadratic + * equation which ensures that it reaches ramping down to pmin in 5sec. + */ +static inline int calc_global_pstate(unsigned int elapsed_time, + int highest_lpstate, int local_pstate) +{ + int pstate_diff; + + /* + * Using ramp_down_percent we get the percentage of rampdown + * that we are expecting to be dropping. Difference between + * highest_lpstate and powernv_pstate_info.min will give a absolute + * number of how many pstates we will drop eventually by the end of + * 5 seconds, then just scale it get the number pstates to be dropped. + */ + pstate_diff = ((int)ramp_down_percent(elapsed_time) * + (highest_lpstate - powernv_pstate_info.min)) / 100; + + /* Ensure that global pstate is >= to local pstate */ + if (highest_lpstate - pstate_diff < local_pstate) + return local_pstate; + else + return highest_lpstate - pstate_diff; +} + +static inline void queue_gpstate_timer(struct global_pstate_info *gpstates) +{ + unsigned int timer_interval; + + /* + * Setting up timer to fire after GPSTATE_TIMER_INTERVAL ms, But + * if it exceeds MAX_RAMP_DOWN_TIME ms for ramp down time. + * Set timer such that it fires exactly at MAX_RAMP_DOWN_TIME + * seconds of ramp down time. + */ + if ((gpstates->elapsed_time + GPSTATE_TIMER_INTERVAL) + > MAX_RAMP_DOWN_TIME) + timer_interval = MAX_RAMP_DOWN_TIME - gpstates->elapsed_time; + else + timer_interval = GPSTATE_TIMER_INTERVAL; + + mod_timer_pinned(&gpstates->timer, jiffies + + msecs_to_jiffies(timer_interval)); +} + +/** + * gpstate_timer_handler + * + * @data: pointer to cpufreq_policy on which timer was queued + * + * This handler brings down the global pstate closer to the local pstate + * according quadratic equation. Queues a new timer if it is still not equal + * to local pstate + */ +void gpstate_timer_handler(unsigned long data) +{ + struct cpufreq_policy *policy = (struct cpufreq_policy *)data; + struct global_pstate_info *gpstates = policy->driver_data; + int gpstate_id; + unsigned int time_diff = jiffies_to_msecs(jiffies) + - gpstates->last_sampled_time; + struct powernv_smp_call_data freq_data; + + if (!spin_trylock(&gpstates->gpstate_lock)) + return; + + gpstates->last_sampled_time += time_diff; + gpstates->elapsed_time += time_diff; + freq_data.pstate_id = gpstates->last_lpstate; + + if ((gpstates->last_gpstate == freq_data.pstate_id) || + (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) { + gpstate_id = freq_data.pstate_id; + reset_gpstates(policy); + gpstates->highest_lpstate = freq_data.pstate_id; + } else { + gpstate_id = calc_global_pstate(gpstates->elapsed_time, + gpstates->highest_lpstate, + freq_data.pstate_id); + } + + /* + * If local pstate is equal to global pstate, rampdown is over + * So timer is not required to be queued. + */ + if (gpstate_id != freq_data.pstate_id) + queue_gpstate_timer(gpstates); + + freq_data.gpstate_id = gpstate_id; + gpstates->last_gpstate = freq_data.gpstate_id; + gpstates->last_lpstate = freq_data.pstate_id; + + /* Timer may get migrated to a different cpu on cpu hot unplug */ + smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1); + spin_unlock(&gpstates->gpstate_lock); +} + /* * powernv_cpufreq_target_index: Sets the frequency corresponding to * the cpufreq table entry indexed by new_index on the cpus in the @@ -433,6 +595,9 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, unsigned int new_index) { struct powernv_smp_call_data freq_data; + unsigned int cur_msec, gpstate_id; + unsigned long flags; + struct global_pstate_info *gpstates = policy->driver_data; if (unlikely(rebooting) && new_index != get_nominal_index()) return 0; @@ -440,22 +605,70 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, if (!throttled) powernv_cpufreq_throttle_check(NULL); + cur_msec = jiffies_to_msecs(get_jiffies_64()); + + spin_lock_irqsave(&gpstates->gpstate_lock, flags); freq_data.pstate_id = powernv_freqs[new_index].driver_data; + if (!gpstates->last_sampled_time) { + gpstate_id = freq_data.pstate_id; + gpstates->highest_lpstate = freq_data.pstate_id; + goto gpstates_done; + } + + if (gpstates->last_gpstate > freq_data.pstate_id) { + gpstates->elapsed_time += cur_msec - + gpstates->last_sampled_time; + + /* + * If its has been ramping down for more than MAX_RAMP_DOWN_TIME + * we should be resetting all global pstate related data. Set it + * equal to local pstate to start fresh. + */ + if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) { + reset_gpstates(policy); + gpstates->highest_lpstate = freq_data.pstate_id; + gpstate_id = freq_data.pstate_id; + } else { + /* Elaspsed_time is less than 5 seconds, continue to rampdown */ + gpstate_id = calc_global_pstate(gpstates->elapsed_time, + gpstates->highest_lpstate, + freq_data.pstate_id); + } + } else { + reset_gpstates(policy); + gpstates->highest_lpstate = freq_data.pstate_id; + gpstate_id = freq_data.pstate_id; + } + + /* + * If local pstate is equal to global pstate, rampdown is over + * So timer is not required to be queued. + */ + if (gpstate_id != freq_data.pstate_id) + queue_gpstate_timer(gpstates); + +gpstates_done: + freq_data.gpstate_id = gpstate_id; + gpstates->last_sampled_time = cur_msec; + gpstates->last_gpstate = freq_data.gpstate_id; + gpstates->last_lpstate = freq_data.pstate_id; + /* * Use smp_call_function to send IPI and execute the * mtspr on target CPU. We could do that without IPI * if current CPU is within policy->cpus (core) */ smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1); - + spin_unlock_irqrestore(&gpstates->gpstate_lock, flags); return 0; } static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) { - int base, i; + int base, i, ret; struct kernfs_node *kn; + struct global_pstate_info *gpstates; base = cpu_first_thread_sibling(policy->cpu); @@ -475,7 +688,34 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) } else { kernfs_put(kn); } - return cpufreq_table_validate_and_show(policy, powernv_freqs); + + gpstates = kzalloc(sizeof(*gpstates), GFP_KERNEL); + if (!gpstates) + return -ENOMEM; + + policy->driver_data = gpstates; + + /* initialize timer */ + init_timer_deferrable(&gpstates->timer); + gpstates->timer.data = (unsigned long)policy; + gpstates->timer.function = gpstate_timer_handler; + gpstates->timer.expires = jiffies + + msecs_to_jiffies(GPSTATE_TIMER_INTERVAL); + spin_lock_init(&gpstates->gpstate_lock); + ret = cpufreq_table_validate_and_show(policy, powernv_freqs); + + if (ret < 0) + kfree(policy->driver_data); + + return ret; +} + +static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + /* timer is deleted in cpufreq_cpu_stop() */ + kfree(policy->driver_data); + + return 0; } static int powernv_cpufreq_reboot_notifier(struct notifier_block *nb, @@ -603,15 +843,19 @@ static struct notifier_block powernv_cpufreq_opal_nb = { static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy) { struct powernv_smp_call_data freq_data; + struct global_pstate_info *gpstates = policy->driver_data; freq_data.pstate_id = powernv_pstate_info.min; + freq_data.gpstate_id = powernv_pstate_info.min; smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1); + del_timer_sync(&gpstates->timer); } static struct cpufreq_driver powernv_cpufreq_driver = { .name = "powernv-cpufreq", .flags = CPUFREQ_CONST_LOOPS, .init = powernv_cpufreq_cpu_init, + .exit = powernv_cpufreq_cpu_exit, .verify = cpufreq_generic_frequency_table_verify, .target_index = powernv_cpufreq_target_index, .get = powernv_cpufreq_get, -- GitLab From 9bf292bfca94694a721449e3fd752493856710f6 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Wed, 27 Apr 2016 14:36:05 -0700 Subject: [PATCH 4844/9938] misc: mic: Fix for double fetch security bug in VOP driver The MIC VOP driver does two successive reads from user space to read a variable length data structure. Kernel memory corruption can result if the data structure changes between the two reads. This patch disallows the chance of this happening. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=116651 Reported by: Pengfei Wang Reviewed-by: Sudeep Dutt Signed-off-by: Ashutosh Dixit Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/vop/vop_vringh.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c index e94c7fb6712a..88e45234d527 100644 --- a/drivers/misc/mic/vop/vop_vringh.c +++ b/drivers/misc/mic/vop/vop_vringh.c @@ -945,6 +945,11 @@ static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ret = -EFAULT; goto free_ret; } + /* Ensure desc has not changed between the two reads */ + if (memcmp(&dd, dd_config, sizeof(dd))) { + ret = -EINVAL; + goto free_ret; + } mutex_lock(&vdev->vdev_mutex); mutex_lock(&vi->vop_mutex); ret = vop_virtio_add_device(vdev, dd_config); -- GitLab From 9522a2ff9cde26ef48c30e0c9ca9ae4dfb669764 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 27 Apr 2016 15:48:06 -0700 Subject: [PATCH 4845/9938] cpufreq: intel_pstate: Enforce _PPC limits Use ACPI _PPC notification to limit max P state driver will request. ACPI _PPC change notification is sent by BIOS to limit max P state in several cases: - Reduce impact of platform thermal condition - When Config TDP feature is used, a changed _PPC is sent to follow TDP change - Remote node managers in server want to control platform power via baseboard management controller (BMC) This change registers with ACPI processor performance lib so that _PPC changes are notified to cpufreq core, which in turns will result in call to .setpolicy() callback. Also the way _PSS table identifies a turbo frequency is not compatible to max turbo frequency in intel_pstate, so the very first entry in _PSS needs to be adjusted. This feature can be turned on by using kernel parameters: intel_pstate=support_acpi_ppc Signed-off-by: Srinivas Pandruvada [ rjw: Minor cleanups ] Signed-off-by: Rafael J. Wysocki --- Documentation/kernel-parameters.txt | 2 + drivers/cpufreq/Kconfig.x86 | 1 + drivers/cpufreq/intel_pstate.c | 136 +++++++++++++++++++++++++++- 3 files changed, 137 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ecc74fa4bfde..31c094fb1141 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1661,6 +1661,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. hwp_only Only load intel_pstate on systems which support hardware P state control (HWP) if available. + support_acpi_ppc + Enforce ACPI _PPC performance limits. intremap= [X86-64, Intel-IOMMU] on enable Interrupt Remapping (default) diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index c59bdcb83217..adbd1de1cea5 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -5,6 +5,7 @@ config X86_INTEL_PSTATE bool "Intel P state control" depends on X86 + select ACPI_PROCESSOR if ACPI help This driver provides a P state for Intel core processors. The driver implements an internal governor and will become diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index cfa6a6803e0e..c72a82a45872 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -41,6 +41,10 @@ #define ATOM_TURBO_RATIOS 0x66c #define ATOM_TURBO_VIDS 0x66d +#ifdef CONFIG_ACPI +#include +#endif + #define FRAC_BITS 8 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) #define fp_toint(X) ((X) >> FRAC_BITS) @@ -174,6 +178,8 @@ struct _pid { * @prev_cummulative_iowait: IO Wait time difference from last and * current sample * @sample: Storage for storing last Sample data + * @acpi_perf_data: Stores ACPI perf information read from _PSS + * @valid_pss_table: Set to true for valid ACPI _PSS entries found * * This structure stores per CPU instance data for all CPUs. */ @@ -192,6 +198,10 @@ struct cpudata { u64 prev_tsc; u64 prev_cummulative_iowait; struct sample sample; +#ifdef CONFIG_ACPI + struct acpi_processor_performance acpi_perf_data; + bool valid_pss_table; +#endif }; static struct cpudata **all_cpu_data; @@ -260,6 +270,9 @@ static struct pstate_adjust_policy pid_params; static struct pstate_funcs pstate_funcs; static int hwp_active; +#ifdef CONFIG_ACPI +static bool acpi_ppc; +#endif /** * struct perf_limits - Store user and policy limits @@ -333,6 +346,111 @@ static struct perf_limits *limits = &performance_limits; static struct perf_limits *limits = &powersave_limits; #endif +#ifdef CONFIG_ACPI +/* + * The max target pstate ratio is a 8 bit value in both PLATFORM_INFO MSR and + * in TURBO_RATIO_LIMIT MSR, which pstate driver stores in max_pstate and + * max_turbo_pstate fields. The PERF_CTL MSR contains 16 bit value for P state + * ratio, out of it only high 8 bits are used. For example 0x1700 is setting + * target ratio 0x17. The _PSS control value stores in a format which can be + * directly written to PERF_CTL MSR. But in intel_pstate driver this shift + * occurs during write to PERF_CTL (E.g. for cores core_set_pstate()). + * This function converts the _PSS control value to intel pstate driver format + * for comparison and assignment. + */ +static int convert_to_native_pstate_format(struct cpudata *cpu, int index) +{ + return cpu->acpi_perf_data.states[index].control >> 8; +} + +static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy) +{ + struct cpudata *cpu; + int turbo_pss_ctl; + int ret; + int i; + + if (!acpi_ppc) + return; + + cpu = all_cpu_data[policy->cpu]; + + ret = acpi_processor_register_performance(&cpu->acpi_perf_data, + policy->cpu); + if (ret) + return; + + /* + * Check if the control value in _PSS is for PERF_CTL MSR, which should + * guarantee that the states returned by it map to the states in our + * list directly. + */ + if (cpu->acpi_perf_data.control_register.space_id != + ACPI_ADR_SPACE_FIXED_HARDWARE) + goto err; + + /* + * If there is only one entry _PSS, simply ignore _PSS and continue as + * usual without taking _PSS into account + */ + if (cpu->acpi_perf_data.state_count < 2) + goto err; + + pr_debug("CPU%u - ACPI _PSS perf data\n", policy->cpu); + for (i = 0; i < cpu->acpi_perf_data.state_count; i++) { + pr_debug(" %cP%d: %u MHz, %u mW, 0x%x\n", + (i == cpu->acpi_perf_data.state ? '*' : ' '), i, + (u32) cpu->acpi_perf_data.states[i].core_frequency, + (u32) cpu->acpi_perf_data.states[i].power, + (u32) cpu->acpi_perf_data.states[i].control); + } + + /* + * The _PSS table doesn't contain whole turbo frequency range. + * This just contains +1 MHZ above the max non turbo frequency, + * with control value corresponding to max turbo ratio. But + * when cpufreq set policy is called, it will call with this + * max frequency, which will cause a reduced performance as + * this driver uses real max turbo frequency as the max + * frequency. So correct this frequency in _PSS table to + * correct max turbo frequency based on the turbo ratio. + * Also need to convert to MHz as _PSS freq is in MHz. + */ + turbo_pss_ctl = convert_to_native_pstate_format(cpu, 0); + if (turbo_pss_ctl > cpu->pstate.max_pstate) + cpu->acpi_perf_data.states[0].core_frequency = + policy->cpuinfo.max_freq / 1000; + cpu->valid_pss_table = true; + pr_info("_PPC limits will be enforced\n"); + + return; + + err: + cpu->valid_pss_table = false; + acpi_processor_unregister_performance(policy->cpu); +} + +static void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy) +{ + struct cpudata *cpu; + + cpu = all_cpu_data[policy->cpu]; + if (!cpu->valid_pss_table) + return; + + acpi_processor_unregister_performance(policy->cpu); +} + +#else +static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy) +{ +} + +static void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy) +{ +} +#endif + static inline void pid_reset(struct _pid *pid, int setpoint, int busy, int deadband, int integral) { pid->setpoint = int_tofp(setpoint); @@ -1398,18 +1516,27 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + intel_pstate_init_acpi_perf_limits(policy); policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; cpumask_set_cpu(policy->cpu, policy->cpus); return 0; } +static int intel_pstate_cpu_exit(struct cpufreq_policy *policy) +{ + intel_pstate_exit_perf_limits(policy); + + return 0; +} + static struct cpufreq_driver intel_pstate_driver = { .flags = CPUFREQ_CONST_LOOPS, .verify = intel_pstate_verify_policy, .setpolicy = intel_pstate_set_policy, .get = intel_pstate_get, .init = intel_pstate_cpu_init, + .exit = intel_pstate_cpu_exit, .stop_cpu = intel_pstate_stop_cpu, .name = "intel_pstate", }; @@ -1453,8 +1580,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) } -#if IS_ENABLED(CONFIG_ACPI) -#include +#ifdef CONFIG_ACPI static bool intel_pstate_no_acpi_pss(void) { @@ -1660,6 +1786,12 @@ static int __init intel_pstate_setup(char *str) force_load = 1; if (!strcmp(str, "hwp_only")) hwp_only = 1; + +#ifdef CONFIG_ACPI + if (!strcmp(str, "support_acpi_ppc")) + acpi_ppc = true; +#endif + return 0; } early_param("intel_pstate", intel_pstate_setup); -- GitLab From 3be9200d512bfa8d6292f5dce6c02aa151821e09 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 27 Apr 2016 15:48:07 -0700 Subject: [PATCH 4846/9938] cpufreq: intel_pstate: Adjust policy->max When policy->max is changed via _PPC or sysfs and is more than the max non turbo frequency, it does not really change resulting performance in some processors. When policy->max results in a P-State ratio more than the turbo activation ratio, then processor can choose any P-State up to max turbo. So the user or _PPC setting has no value, but this can cause undesirable side effects like: - Showing reduced max percentage in Intel P-State sysfs - It can cause reduced max performance under certain boundary conditions: The requested max scaling frequency either via _PPC or via cpufreq-sysfs, will be converted into a fixed floating point max percent scale. In majority of the cases this will result in correct max. But not 100% of the time. If the _PPC is requested at a point where the calculation lead to a lower max, this can result in a lower P-State then expected and it will impact performance. Example of this condition using a Broadwell laptop with config TDP. ACPI _PSS table from a Broadwell laptop 2301000 2300000 2200000 2000000 1900000 1800000 1700000 1500000 1400000 1300000 1100000 1000000 900000 800000 600000 500000 The actual results by disabling config TDP so that we can get what is requested on or below 2300000Khz. scaling_max_freq Max Requested P-State Resultant scaling max ---------------------------------------- ---------------------- 2400000 18 2900000 (max turbo) 2300000 17 2300000 (max physical non turbo) 2200000 15 2100000 2100000 15 2100000 2000000 13 1900000 1900000 13 1900000 1800000 12 1800000 1700000 11 1700000 1600000 10 1600000 1500000 f 1500000 1400000 e 1400000 1300000 d 1300000 1200000 c 1200000 1100000 a 1000000 1000000 a 1000000 900000 9 900000 800000 8 800000 700000 7 700000 600000 6 600000 500000 5 500000 ------------------------------------------------------------------ Now set the config TDP level 1 ratio as 0x0b (equivalent to 1100000KHz) in BIOS (not every system will let you adjust this). The turbo activation ratio will be set to one less than that, which will be 0x0a (So any request above 1000000KHz should result in turbo region assuming no thermal limits). Here _PPC will request max to 1100000KHz (which basically should still result in turbo as this is more than the turbo activation ratio up to max allowable turbo frequency), but actual calculation resulted in a max ceiling P-State which is 0x0a. So under any load condition, this driver will not request turbo P-States. This will be a huge performance hit. When config TDP feature is ON, if the _PPC points to a frequency above turbo activation ratio, the performance can still reach max turbo. In this case we don't need to treat this as the reduced frequency in set_policy callback. In this change when config TDP is active (by checking if the physical max non turbo ratio is more than the current max non turbo ratio), any request above current max non turbo is treated as full performance. Signed-off-by: Srinivas Pandruvada [ rjw : Minor cleanups ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index c72a82a45872..31f6ffe0cf10 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1418,11 +1418,22 @@ static void intel_pstate_set_performance_limits(struct perf_limits *limits) static int intel_pstate_set_policy(struct cpufreq_policy *policy) { + struct cpudata *cpu; + if (!policy->cpuinfo.max_freq) return -ENODEV; intel_pstate_clear_update_util_hook(policy->cpu); + cpu = all_cpu_data[0]; + if (cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate) { + if (policy->max < policy->cpuinfo.max_freq && + policy->max > cpu->pstate.max_pstate * cpu->pstate.scaling) { + pr_debug("policy->max > max non turbo frequency\n"); + policy->max = policy->cpuinfo.max_freq; + } + } + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { limits = &performance_limits; if (policy->max >= policy->cpuinfo.max_freq) { -- GitLab From 2b3ec765058449caa27e2806a939a4bffcbeba64 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 27 Apr 2016 15:48:08 -0700 Subject: [PATCH 4847/9938] cpufreq: intel_pstate: Enable PPC enforcement for servers For platforms which are controlled via remove node manager, enable _PPC by default. These platforms are mostly categorized as enterprise server or performance servers. These platforms needs to go through some certifications tests, which tests control via _PPC. The relative risk of enabling by default is low as this is is less likely that these systems have broken _PSS table. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- Documentation/kernel-parameters.txt | 5 ++++- drivers/cpufreq/intel_pstate.c | 12 +++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 31c094fb1141..1cffa3f24732 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1662,7 +1662,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Only load intel_pstate on systems which support hardware P state control (HWP) if available. support_acpi_ppc - Enforce ACPI _PPC performance limits. + Enforce ACPI _PPC performance limits. If the Fixed ACPI + Description Table, specifies preferred power management + profile as "Enterprise Server" or "Performance Server", + then this feature is turned on by default. intremap= [X86-64, Intel-IOMMU] on enable Interrupt Remapping (default) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 31f6ffe0cf10..a0823e84ceca 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -347,6 +347,16 @@ static struct perf_limits *limits = &powersave_limits; #endif #ifdef CONFIG_ACPI + +static bool intel_pstate_get_ppc_enable_status(void) +{ + if (acpi_gbl_FADT.preferred_profile == PM_ENTERPRISE_SERVER || + acpi_gbl_FADT.preferred_profile == PM_PERFORMANCE_SERVER) + return true; + + return acpi_ppc; +} + /* * The max target pstate ratio is a 8 bit value in both PLATFORM_INFO MSR and * in TURBO_RATIO_LIMIT MSR, which pstate driver stores in max_pstate and @@ -370,7 +380,7 @@ static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy) int ret; int i; - if (!acpi_ppc) + if (!intel_pstate_get_ppc_enable_status()) return; cpu = all_cpu_data[policy->cpu]; -- GitLab From 9e209fcfb804da262e38e5cd2e680c47a41f0f95 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Mon, 25 Apr 2016 07:32:19 -0700 Subject: [PATCH 4848/9938] crypto: qat - fix invalid pf2vf_resp_wq logic The pf2vf_resp_wq is a global so it has to be created at init and destroyed at exit, instead of per device. Cc: Tested-by: Suresh Marikkannu Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- .../crypto/qat/qat_common/adf_common_drv.h | 2 ++ drivers/crypto/qat/qat_common/adf_ctl_drv.c | 6 +++++ drivers/crypto/qat/qat_common/adf_sriov.c | 26 ++++++++++++------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index 0e82ce3c383e..155510277c54 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -144,6 +144,8 @@ void adf_disable_aer(struct adf_accel_dev *accel_dev); void adf_dev_restore(struct adf_accel_dev *accel_dev); int adf_init_aer(void); void adf_exit_aer(void); +int adf_init_pf_wq(void); +void adf_exit_pf_wq(void); int adf_init_admin_comms(struct adf_accel_dev *accel_dev); void adf_exit_admin_comms(struct adf_accel_dev *accel_dev); int adf_send_admin_init(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c index 5c897e6e7994..3c3f948290ca 100644 --- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c @@ -462,12 +462,17 @@ static int __init adf_register_ctl_device_driver(void) if (adf_init_aer()) goto err_aer; + if (adf_init_pf_wq()) + goto err_pf_wq; + if (qat_crypto_register()) goto err_crypto_register; return 0; err_crypto_register: + adf_exit_pf_wq(); +err_pf_wq: adf_exit_aer(); err_aer: adf_chr_drv_destroy(); @@ -480,6 +485,7 @@ static void __exit adf_unregister_ctl_device_driver(void) { adf_chr_drv_destroy(); adf_exit_aer(); + adf_exit_pf_wq(); qat_crypto_unregister(); adf_clean_vf_map(false); mutex_destroy(&adf_ctl_lock); diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c index 1117a8b58280..38a0415e767d 100644 --- a/drivers/crypto/qat/qat_common/adf_sriov.c +++ b/drivers/crypto/qat/qat_common/adf_sriov.c @@ -119,11 +119,6 @@ static int adf_enable_sriov(struct adf_accel_dev *accel_dev) int i; u32 reg; - /* Workqueue for PF2VF responses */ - pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq"); - if (!pf2vf_resp_wq) - return -ENOMEM; - for (i = 0, vf_info = accel_dev->pf.vf_info; i < totalvfs; i++, vf_info++) { /* This ptr will be populated when VFs will be created */ @@ -216,11 +211,6 @@ void adf_disable_sriov(struct adf_accel_dev *accel_dev) kfree(accel_dev->pf.vf_info); accel_dev->pf.vf_info = NULL; - - if (pf2vf_resp_wq) { - destroy_workqueue(pf2vf_resp_wq); - pf2vf_resp_wq = NULL; - } } EXPORT_SYMBOL_GPL(adf_disable_sriov); @@ -304,3 +294,19 @@ int adf_sriov_configure(struct pci_dev *pdev, int numvfs) return numvfs; } EXPORT_SYMBOL_GPL(adf_sriov_configure); + +int __init adf_init_pf_wq(void) +{ + /* Workqueue for PF2VF responses */ + pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq"); + + return !pf2vf_resp_wq ? -ENOMEM : 0; +} + +void adf_exit_pf_wq(void) +{ + if (pf2vf_resp_wq) { + destroy_workqueue(pf2vf_resp_wq); + pf2vf_resp_wq = NULL; + } +} -- GitLab From d1497977fecb9acce05988d6322ad415ef93bb39 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 26 Apr 2016 09:29:26 +0200 Subject: [PATCH 4849/9938] crypto: s5p-sss - fix incorrect usage of scatterlists api sg_dma_len() macro can be used only on scattelists which are mapped, so all calls to it before dma_map_sg() are invalid. Replace them by proper check for direct sg segment length read. Fixes: a49e490c7a8a ("crypto: s5p-sss - add S5PV210 advanced crypto engine support") Fixes: 9e4a1100a445 ("crypto: s5p-sss - Handle unaligned buffers") Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index ac6d62b3be07..2b3a0cfe3331 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -327,7 +327,7 @@ static int s5p_set_outdata(struct s5p_aes_dev *dev, struct scatterlist *sg) { int err; - if (!sg_dma_len(sg)) { + if (!sg->length) { err = -EINVAL; goto exit; } @@ -349,7 +349,7 @@ static int s5p_set_indata(struct s5p_aes_dev *dev, struct scatterlist *sg) { int err; - if (!sg_dma_len(sg)) { + if (!sg->length) { err = -EINVAL; goto exit; } @@ -474,7 +474,7 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, static bool s5p_is_sg_aligned(struct scatterlist *sg) { while (sg) { - if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) + if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE)) return false; sg = sg_next(sg); } -- GitLab From 35ef7d689d7d54ab345b179e50c749fe3a2529eb Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 27 Apr 2016 05:43:48 +0900 Subject: [PATCH 4850/9938] net: w5100: support W5500 This adds support for W5500 chip. W5500 has similar register and memory organization with W5100 and W5200. There are a few important differences listed below but it is still possible to share common code with W5100 and W5200. * W5500 register and memory are organized by multiple blocks. Each one is selected by 16bits offset address and 5bits block select bits. But the existing register access operations take u16 address. This change extends the addess by u32 address and put offset address to lower 16bits and block select bits to upper 16bits. This change also adds the offset addresses for socket register and TX/RX memory blocks to the driver private data structure in order to reduce conditional switches for each chip. * W5500 has the different register offset for socket interrupt mask register. Newly added internal functions w5100_enable_intr() and w5100_disable_intr() take care of the diffrence. * W5500 has the different register offset for retry time-value register. But this register is only used to verify that the reset value is correctly read at initialization. So move the verification to w5100_hw_reset() which already does different things for different chips. Signed-off-by: Akinobu Mita Cc: Mike Sinkovsky Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ethernet/wiznet/Kconfig | 2 +- drivers/net/ethernet/wiznet/w5100-spi.c | 192 +++++++++++++++++-- drivers/net/ethernet/wiznet/w5100.c | 243 +++++++++++++++++------- drivers/net/ethernet/wiznet/w5100.h | 13 +- 4 files changed, 365 insertions(+), 85 deletions(-) diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig index f3385a1999a2..1981e88c18dc 100644 --- a/drivers/net/ethernet/wiznet/Kconfig +++ b/drivers/net/ethernet/wiznet/Kconfig @@ -70,7 +70,7 @@ config WIZNET_BUS_ANY endchoice config WIZNET_W5100_SPI - tristate "WIZnet W5100/W5200 Ethernet support for SPI mode" + tristate "WIZnet W5100/W5200/W5500 Ethernet support for SPI mode" depends on WIZNET_BUS_ANY && WIZNET_W5100 depends on SPI ---help--- diff --git a/drivers/net/ethernet/wiznet/w5100-spi.c b/drivers/net/ethernet/wiznet/w5100-spi.c index 598a7b00fdb9..b868e458d0b5 100644 --- a/drivers/net/ethernet/wiznet/w5100-spi.c +++ b/drivers/net/ethernet/wiznet/w5100-spi.c @@ -1,5 +1,5 @@ /* - * Ethernet driver for the WIZnet W5100/W5200 chip. + * Ethernet driver for the WIZnet W5100/W5200/W5500 chip. * * Copyright (C) 2016 Akinobu Mita * @@ -8,6 +8,7 @@ * Datasheet: * http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Document/W5100_Datasheet_v1.2.6.pdf * http://wiznethome.cafe24.com/wp-content/uploads/wiznethome/Chip/W5200/Documents/W5200_DS_V140E.pdf + * http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:w5500_ds_v106e_141230.pdf */ #include @@ -21,7 +22,7 @@ #define W5100_SPI_WRITE_OPCODE 0xf0 #define W5100_SPI_READ_OPCODE 0x0f -static int w5100_spi_read(struct net_device *ndev, u16 addr) +static int w5100_spi_read(struct net_device *ndev, u32 addr) { struct spi_device *spi = to_spi_device(ndev->dev.parent); u8 cmd[3] = { W5100_SPI_READ_OPCODE, addr >> 8, addr & 0xff }; @@ -33,7 +34,7 @@ static int w5100_spi_read(struct net_device *ndev, u16 addr) return ret ? ret : data; } -static int w5100_spi_write(struct net_device *ndev, u16 addr, u8 data) +static int w5100_spi_write(struct net_device *ndev, u32 addr, u8 data) { struct spi_device *spi = to_spi_device(ndev->dev.parent); u8 cmd[4] = { W5100_SPI_WRITE_OPCODE, addr >> 8, addr & 0xff, data}; @@ -41,7 +42,7 @@ static int w5100_spi_write(struct net_device *ndev, u16 addr, u8 data) return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); } -static int w5100_spi_read16(struct net_device *ndev, u16 addr) +static int w5100_spi_read16(struct net_device *ndev, u32 addr) { u16 data; int ret; @@ -55,7 +56,7 @@ static int w5100_spi_read16(struct net_device *ndev, u16 addr) return ret < 0 ? ret : data | ret; } -static int w5100_spi_write16(struct net_device *ndev, u16 addr, u16 data) +static int w5100_spi_write16(struct net_device *ndev, u32 addr, u16 data) { int ret; @@ -66,7 +67,7 @@ static int w5100_spi_write16(struct net_device *ndev, u16 addr, u16 data) return w5100_spi_write(ndev, addr + 1, data & 0xff); } -static int w5100_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf, +static int w5100_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf, int len) { int i; @@ -82,7 +83,7 @@ static int w5100_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf, return 0; } -static int w5100_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf, +static int w5100_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf, int len) { int i; @@ -134,7 +135,7 @@ static int w5200_spi_init(struct net_device *ndev) return 0; } -static int w5200_spi_read(struct net_device *ndev, u16 addr) +static int w5200_spi_read(struct net_device *ndev, u32 addr) { struct spi_device *spi = to_spi_device(ndev->dev.parent); u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 1 }; @@ -146,7 +147,7 @@ static int w5200_spi_read(struct net_device *ndev, u16 addr) return ret ? ret : data; } -static int w5200_spi_write(struct net_device *ndev, u16 addr, u8 data) +static int w5200_spi_write(struct net_device *ndev, u32 addr, u8 data) { struct spi_device *spi = to_spi_device(ndev->dev.parent); u8 cmd[5] = { addr >> 8, addr & 0xff, W5200_SPI_WRITE_OPCODE, 1, data }; @@ -154,7 +155,7 @@ static int w5200_spi_write(struct net_device *ndev, u16 addr, u8 data) return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); } -static int w5200_spi_read16(struct net_device *ndev, u16 addr) +static int w5200_spi_read16(struct net_device *ndev, u32 addr) { struct spi_device *spi = to_spi_device(ndev->dev.parent); u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 2 }; @@ -166,7 +167,7 @@ static int w5200_spi_read16(struct net_device *ndev, u16 addr) return ret ? ret : be16_to_cpu(data); } -static int w5200_spi_write16(struct net_device *ndev, u16 addr, u16 data) +static int w5200_spi_write16(struct net_device *ndev, u32 addr, u16 data) { struct spi_device *spi = to_spi_device(ndev->dev.parent); u8 cmd[6] = { @@ -178,7 +179,7 @@ static int w5200_spi_write16(struct net_device *ndev, u16 addr, u16 data) return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); } -static int w5200_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf, +static int w5200_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf, int len) { struct spi_device *spi = to_spi_device(ndev->dev.parent); @@ -208,7 +209,7 @@ static int w5200_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf, return ret; } -static int w5200_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf, +static int w5200_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf, int len) { struct spi_device *spi = to_spi_device(ndev->dev.parent); @@ -250,6 +251,164 @@ static const struct w5100_ops w5200_ops = { .init = w5200_spi_init, }; +#define W5500_SPI_BLOCK_SELECT(addr) (((addr) >> 16) & 0x1f) +#define W5500_SPI_READ_CONTROL(addr) (W5500_SPI_BLOCK_SELECT(addr) << 3) +#define W5500_SPI_WRITE_CONTROL(addr) \ + ((W5500_SPI_BLOCK_SELECT(addr) << 3) | BIT(2)) + +struct w5500_spi_priv { + /* Serialize access to cmd_buf */ + struct mutex cmd_lock; + + /* DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u8 cmd_buf[3] ____cacheline_aligned; +}; + +static struct w5500_spi_priv *w5500_spi_priv(struct net_device *ndev) +{ + return w5100_ops_priv(ndev); +} + +static int w5500_spi_init(struct net_device *ndev) +{ + struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev); + + mutex_init(&spi_priv->cmd_lock); + + return 0; +} + +static int w5500_spi_read(struct net_device *ndev, u32 addr) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[3] = { + addr >> 8, + addr, + W5500_SPI_READ_CONTROL(addr) + }; + u8 data; + int ret; + + ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1); + + return ret ? ret : data; +} + +static int w5500_spi_write(struct net_device *ndev, u32 addr, u8 data) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[4] = { + addr >> 8, + addr, + W5500_SPI_WRITE_CONTROL(addr), + data + }; + + return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); +} + +static int w5500_spi_read16(struct net_device *ndev, u32 addr) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[3] = { + addr >> 8, + addr, + W5500_SPI_READ_CONTROL(addr) + }; + __be16 data; + int ret; + + ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data)); + + return ret ? ret : be16_to_cpu(data); +} + +static int w5500_spi_write16(struct net_device *ndev, u32 addr, u16 data) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + u8 cmd[5] = { + addr >> 8, + addr, + W5500_SPI_WRITE_CONTROL(addr), + data >> 8, + data + }; + + return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); +} + +static int w5500_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf, + int len) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev); + struct spi_transfer xfer[] = { + { + .tx_buf = spi_priv->cmd_buf, + .len = sizeof(spi_priv->cmd_buf), + }, + { + .rx_buf = buf, + .len = len, + }, + }; + int ret; + + mutex_lock(&spi_priv->cmd_lock); + + spi_priv->cmd_buf[0] = addr >> 8; + spi_priv->cmd_buf[1] = addr; + spi_priv->cmd_buf[2] = W5500_SPI_READ_CONTROL(addr); + ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); + + mutex_unlock(&spi_priv->cmd_lock); + + return ret; +} + +static int w5500_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf, + int len) +{ + struct spi_device *spi = to_spi_device(ndev->dev.parent); + struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev); + struct spi_transfer xfer[] = { + { + .tx_buf = spi_priv->cmd_buf, + .len = sizeof(spi_priv->cmd_buf), + }, + { + .tx_buf = buf, + .len = len, + }, + }; + int ret; + + mutex_lock(&spi_priv->cmd_lock); + + spi_priv->cmd_buf[0] = addr >> 8; + spi_priv->cmd_buf[1] = addr; + spi_priv->cmd_buf[2] = W5500_SPI_WRITE_CONTROL(addr); + ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); + + mutex_unlock(&spi_priv->cmd_lock); + + return ret; +} + +static const struct w5100_ops w5500_ops = { + .may_sleep = true, + .chip_id = W5500, + .read = w5500_spi_read, + .write = w5500_spi_write, + .read16 = w5500_spi_read16, + .write16 = w5500_spi_write16, + .readbulk = w5500_spi_readbulk, + .writebulk = w5500_spi_writebulk, + .init = w5500_spi_init, +}; + static int w5100_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -265,6 +424,10 @@ static int w5100_spi_probe(struct spi_device *spi) ops = &w5200_ops; priv_size = sizeof(struct w5200_spi_priv); break; + case W5500: + ops = &w5500_ops; + priv_size = sizeof(struct w5500_spi_priv); + break; default: return -EINVAL; } @@ -280,6 +443,7 @@ static int w5100_spi_remove(struct spi_device *spi) static const struct spi_device_id w5100_spi_ids[] = { { "w5100", W5100 }, { "w5200", W5200 }, + { "w5500", W5500 }, {} }; MODULE_DEVICE_TABLE(spi, w5100_spi_ids); @@ -295,6 +459,6 @@ static struct spi_driver w5100_spi_driver = { }; module_spi_driver(w5100_spi_driver); -MODULE_DESCRIPTION("WIZnet W5100/W5200 Ethernet driver for SPI mode"); +MODULE_DESCRIPTION("WIZnet W5100/W5200/W5500 Ethernet driver for SPI mode"); MODULE_AUTHOR("Akinobu Mita "); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index 09149c9ebeff..8ed0c7735ee3 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -38,7 +38,7 @@ MODULE_ALIAS("platform:"DRV_NAME); MODULE_LICENSE("GPL"); /* - * W5100 and W5100 common registers + * W5100/W5200/W5500 common registers */ #define W5100_COMMON_REGS 0x0000 #define W5100_MR 0x0000 /* Mode Register */ @@ -48,10 +48,6 @@ MODULE_LICENSE("GPL"); #define MR_IND 0x01 /* Indirect mode */ #define W5100_SHAR 0x0009 /* Source MAC address */ #define W5100_IR 0x0015 /* Interrupt Register */ -#define W5100_IMR 0x0016 /* Interrupt Mask Register */ -#define IR_S0 0x01 /* S0 interrupt */ -#define W5100_RTR 0x0017 /* Retry Time-value Register */ -#define RTR_DEFAULT 2000 /* =0x07d0 (2000) */ #define W5100_COMMON_REGS_LEN 0x0040 #define W5100_Sn_MR 0x0000 /* Sn Mode Register */ @@ -64,7 +60,7 @@ MODULE_LICENSE("GPL"); #define W5100_Sn_RX_RSR 0x0026 /* Sn Receive free memory size */ #define W5100_Sn_RX_RD 0x0028 /* Sn Receive memory read pointer */ -#define S0_REGS(priv) (is_w5200(priv) ? W5200_S0_REGS : W5100_S0_REGS) +#define S0_REGS(priv) ((priv)->s0_regs) #define W5100_S0_MR(priv) (S0_REGS(priv) + W5100_Sn_MR) #define S0_MR_MACRAW 0x04 /* MAC RAW mode (promiscuous) */ @@ -88,7 +84,15 @@ MODULE_LICENSE("GPL"); #define W5100_S0_REGS_LEN 0x0040 /* - * W5100 specific registers + * W5100 and W5200 common registers + */ +#define W5100_IMR 0x0016 /* Interrupt Mask Register */ +#define IR_S0 0x01 /* S0 interrupt */ +#define W5100_RTR 0x0017 /* Retry Time-value Register */ +#define RTR_DEFAULT 2000 /* =0x07d0 (2000) */ + +/* + * W5100 specific register and memory */ #define W5100_RMSR 0x001a /* Receive Memory Size */ #define W5100_TMSR 0x001b /* Transmit Memory Size */ @@ -101,25 +105,57 @@ MODULE_LICENSE("GPL"); #define W5100_RX_MEM_SIZE 0x2000 /* - * W5200 specific registers + * W5200 specific register and memory */ #define W5200_S0_REGS 0x4000 #define W5200_Sn_RXMEM_SIZE(n) (0x401e + (n) * 0x0100) /* Sn RX Memory Size */ #define W5200_Sn_TXMEM_SIZE(n) (0x401f + (n) * 0x0100) /* Sn TX Memory Size */ -#define W5200_S0_IMR 0x402c /* S0 Interrupt Mask Register */ #define W5200_TX_MEM_START 0x8000 #define W5200_TX_MEM_SIZE 0x4000 #define W5200_RX_MEM_START 0xc000 #define W5200_RX_MEM_SIZE 0x4000 +/* + * W5500 specific register and memory + * + * W5500 register and memory are organized by multiple blocks. Each one is + * selected by 16bits offset address and 5bits block select bits. So we + * encode it into 32bits address. (lower 16bits is offset address and + * upper 16bits is block select bits) + */ +#define W5500_SIMR 0x0018 /* Socket Interrupt Mask Register */ +#define W5500_RTR 0x0019 /* Retry Time-value Register */ + +#define W5500_S0_REGS 0x10000 + +#define W5500_Sn_RXMEM_SIZE(n) \ + (0x1001e + (n) * 0x40000) /* Sn RX Memory Size */ +#define W5500_Sn_TXMEM_SIZE(n) \ + (0x1001f + (n) * 0x40000) /* Sn TX Memory Size */ + +#define W5500_TX_MEM_START 0x20000 +#define W5500_TX_MEM_SIZE 0x04000 +#define W5500_RX_MEM_START 0x30000 +#define W5500_RX_MEM_SIZE 0x04000 + /* * Device driver private data structure */ struct w5100_priv { const struct w5100_ops *ops; + + /* Socket 0 register offset address */ + u32 s0_regs; + /* Socket 0 TX buffer offset address and size */ + u32 s0_tx_buf; + u16 s0_tx_buf_size; + /* Socket 0 RX buffer offset address and size */ + u32 s0_rx_buf; + u16 s0_rx_buf_size; + int irq; int link_irq; int link_gpio; @@ -172,12 +208,12 @@ static inline void __iomem *w5100_mmio(struct net_device *ndev) * * 0x8000 bytes are required for memory space. */ -static inline int w5100_read_direct(struct net_device *ndev, u16 addr) +static inline int w5100_read_direct(struct net_device *ndev, u32 addr) { return ioread8(w5100_mmio(ndev) + (addr << CONFIG_WIZNET_BUS_SHIFT)); } -static inline int __w5100_write_direct(struct net_device *ndev, u16 addr, +static inline int __w5100_write_direct(struct net_device *ndev, u32 addr, u8 data) { iowrite8(data, w5100_mmio(ndev) + (addr << CONFIG_WIZNET_BUS_SHIFT)); @@ -185,7 +221,7 @@ static inline int __w5100_write_direct(struct net_device *ndev, u16 addr, return 0; } -static inline int w5100_write_direct(struct net_device *ndev, u16 addr, u8 data) +static inline int w5100_write_direct(struct net_device *ndev, u32 addr, u8 data) { __w5100_write_direct(ndev, addr, data); mmiowb(); @@ -193,7 +229,7 @@ static inline int w5100_write_direct(struct net_device *ndev, u16 addr, u8 data) return 0; } -static int w5100_read16_direct(struct net_device *ndev, u16 addr) +static int w5100_read16_direct(struct net_device *ndev, u32 addr) { u16 data; data = w5100_read_direct(ndev, addr) << 8; @@ -201,7 +237,7 @@ static int w5100_read16_direct(struct net_device *ndev, u16 addr) return data; } -static int w5100_write16_direct(struct net_device *ndev, u16 addr, u16 data) +static int w5100_write16_direct(struct net_device *ndev, u32 addr, u16 data) { __w5100_write_direct(ndev, addr, data >> 8); __w5100_write_direct(ndev, addr + 1, data); @@ -210,7 +246,7 @@ static int w5100_write16_direct(struct net_device *ndev, u16 addr, u16 data) return 0; } -static int w5100_readbulk_direct(struct net_device *ndev, u16 addr, u8 *buf, +static int w5100_readbulk_direct(struct net_device *ndev, u32 addr, u8 *buf, int len) { int i; @@ -221,7 +257,7 @@ static int w5100_readbulk_direct(struct net_device *ndev, u16 addr, u8 *buf, return 0; } -static int w5100_writebulk_direct(struct net_device *ndev, u16 addr, +static int w5100_writebulk_direct(struct net_device *ndev, u32 addr, const u8 *buf, int len) { int i; @@ -275,7 +311,7 @@ static const struct w5100_ops w5100_mmio_direct_ops = { #define W5100_IDM_AR 0x01 /* Indirect Mode Address Register */ #define W5100_IDM_DR 0x03 /* Indirect Mode Data Register */ -static int w5100_read_indirect(struct net_device *ndev, u16 addr) +static int w5100_read_indirect(struct net_device *ndev, u32 addr) { struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; @@ -289,7 +325,7 @@ static int w5100_read_indirect(struct net_device *ndev, u16 addr) return data; } -static int w5100_write_indirect(struct net_device *ndev, u16 addr, u8 data) +static int w5100_write_indirect(struct net_device *ndev, u32 addr, u8 data) { struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; @@ -302,7 +338,7 @@ static int w5100_write_indirect(struct net_device *ndev, u16 addr, u8 data) return 0; } -static int w5100_read16_indirect(struct net_device *ndev, u16 addr) +static int w5100_read16_indirect(struct net_device *ndev, u32 addr) { struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; @@ -317,7 +353,7 @@ static int w5100_read16_indirect(struct net_device *ndev, u16 addr) return data; } -static int w5100_write16_indirect(struct net_device *ndev, u16 addr, u16 data) +static int w5100_write16_indirect(struct net_device *ndev, u32 addr, u16 data) { struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); unsigned long flags; @@ -331,7 +367,7 @@ static int w5100_write16_indirect(struct net_device *ndev, u16 addr, u16 data) return 0; } -static int w5100_readbulk_indirect(struct net_device *ndev, u16 addr, u8 *buf, +static int w5100_readbulk_indirect(struct net_device *ndev, u32 addr, u8 *buf, int len) { struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); @@ -350,7 +386,7 @@ static int w5100_readbulk_indirect(struct net_device *ndev, u16 addr, u8 *buf, return 0; } -static int w5100_writebulk_indirect(struct net_device *ndev, u16 addr, +static int w5100_writebulk_indirect(struct net_device *ndev, u32 addr, const u8 *buf, int len) { struct w5100_mmio_priv *mmio_priv = w5100_mmio_priv(ndev); @@ -392,32 +428,32 @@ static const struct w5100_ops w5100_mmio_indirect_ops = { #if defined(CONFIG_WIZNET_BUS_DIRECT) -static int w5100_read(struct w5100_priv *priv, u16 addr) +static int w5100_read(struct w5100_priv *priv, u32 addr) { return w5100_read_direct(priv->ndev, addr); } -static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data) +static int w5100_write(struct w5100_priv *priv, u32 addr, u8 data) { return w5100_write_direct(priv->ndev, addr, data); } -static int w5100_read16(struct w5100_priv *priv, u16 addr) +static int w5100_read16(struct w5100_priv *priv, u32 addr) { return w5100_read16_direct(priv->ndev, addr); } -static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data) +static int w5100_write16(struct w5100_priv *priv, u32 addr, u16 data) { return w5100_write16_direct(priv->ndev, addr, data); } -static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len) +static int w5100_readbulk(struct w5100_priv *priv, u32 addr, u8 *buf, int len) { return w5100_readbulk_direct(priv->ndev, addr, buf, len); } -static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, +static int w5100_writebulk(struct w5100_priv *priv, u32 addr, const u8 *buf, int len) { return w5100_writebulk_direct(priv->ndev, addr, buf, len); @@ -425,32 +461,32 @@ static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, #elif defined(CONFIG_WIZNET_BUS_INDIRECT) -static int w5100_read(struct w5100_priv *priv, u16 addr) +static int w5100_read(struct w5100_priv *priv, u32 addr) { return w5100_read_indirect(priv->ndev, addr); } -static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data) +static int w5100_write(struct w5100_priv *priv, u32 addr, u8 data) { return w5100_write_indirect(priv->ndev, addr, data); } -static int w5100_read16(struct w5100_priv *priv, u16 addr) +static int w5100_read16(struct w5100_priv *priv, u32 addr) { return w5100_read16_indirect(priv->ndev, addr); } -static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data) +static int w5100_write16(struct w5100_priv *priv, u32 addr, u16 data) { return w5100_write16_indirect(priv->ndev, addr, data); } -static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len) +static int w5100_readbulk(struct w5100_priv *priv, u32 addr, u8 *buf, int len) { return w5100_readbulk_indirect(priv->ndev, addr, buf, len); } -static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, +static int w5100_writebulk(struct w5100_priv *priv, u32 addr, const u8 *buf, int len) { return w5100_writebulk_indirect(priv->ndev, addr, buf, len); @@ -458,32 +494,32 @@ static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, #else /* CONFIG_WIZNET_BUS_ANY */ -static int w5100_read(struct w5100_priv *priv, u16 addr) +static int w5100_read(struct w5100_priv *priv, u32 addr) { return priv->ops->read(priv->ndev, addr); } -static int w5100_write(struct w5100_priv *priv, u16 addr, u8 data) +static int w5100_write(struct w5100_priv *priv, u32 addr, u8 data) { return priv->ops->write(priv->ndev, addr, data); } -static int w5100_read16(struct w5100_priv *priv, u16 addr) +static int w5100_read16(struct w5100_priv *priv, u32 addr) { return priv->ops->read16(priv->ndev, addr); } -static int w5100_write16(struct w5100_priv *priv, u16 addr, u16 data) +static int w5100_write16(struct w5100_priv *priv, u32 addr, u16 data) { return priv->ops->write16(priv->ndev, addr, data); } -static int w5100_readbulk(struct w5100_priv *priv, u16 addr, u8 *buf, int len) +static int w5100_readbulk(struct w5100_priv *priv, u32 addr, u8 *buf, int len) { return priv->ops->readbulk(priv->ndev, addr, buf, len); } -static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, +static int w5100_writebulk(struct w5100_priv *priv, u32 addr, const u8 *buf, int len) { return priv->ops->writebulk(priv->ndev, addr, buf, len); @@ -493,13 +529,11 @@ static int w5100_writebulk(struct w5100_priv *priv, u16 addr, const u8 *buf, static int w5100_readbuf(struct w5100_priv *priv, u16 offset, u8 *buf, int len) { - u16 addr; + u32 addr; int remain = 0; int ret; - const u16 mem_start = - is_w5200(priv) ? W5200_RX_MEM_START : W5100_RX_MEM_START; - const u16 mem_size = - is_w5200(priv) ? W5200_RX_MEM_SIZE : W5100_RX_MEM_SIZE; + const u32 mem_start = priv->s0_rx_buf; + const u16 mem_size = priv->s0_rx_buf_size; offset %= mem_size; addr = mem_start + offset; @@ -519,13 +553,11 @@ static int w5100_readbuf(struct w5100_priv *priv, u16 offset, u8 *buf, int len) static int w5100_writebuf(struct w5100_priv *priv, u16 offset, const u8 *buf, int len) { - u16 addr; + u32 addr; int ret; int remain = 0; - const u16 mem_start = - is_w5200(priv) ? W5200_TX_MEM_START : W5100_TX_MEM_START; - const u16 mem_size = - is_w5200(priv) ? W5200_TX_MEM_SIZE : W5100_TX_MEM_SIZE; + const u32 mem_start = priv->s0_tx_buf; + const u16 mem_size = priv->s0_tx_buf_size; offset %= mem_size; addr = mem_start + offset; @@ -578,6 +610,28 @@ static void w5100_write_macaddr(struct w5100_priv *priv) w5100_writebulk(priv, W5100_SHAR, ndev->dev_addr, ETH_ALEN); } +static void w5100_socket_intr_mask(struct w5100_priv *priv, u8 mask) +{ + u32 imr; + + if (priv->ops->chip_id == W5500) + imr = W5500_SIMR; + else + imr = W5100_IMR; + + w5100_write(priv, imr, mask); +} + +static void w5100_enable_intr(struct w5100_priv *priv) +{ + w5100_socket_intr_mask(priv, IR_S0); +} + +static void w5100_disable_intr(struct w5100_priv *priv) +{ + w5100_socket_intr_mask(priv, 0); +} + static void w5100_memory_configure(struct w5100_priv *priv) { /* Configure 16K of internal memory @@ -603,17 +657,52 @@ static void w5200_memory_configure(struct w5100_priv *priv) } } -static void w5100_hw_reset(struct w5100_priv *priv) +static void w5500_memory_configure(struct w5100_priv *priv) { + int i; + + /* Configure internal RX memory as 16K RX buffer and + * internal TX memory as 16K TX buffer + */ + w5100_write(priv, W5500_Sn_RXMEM_SIZE(0), 0x10); + w5100_write(priv, W5500_Sn_TXMEM_SIZE(0), 0x10); + + for (i = 1; i < 8; i++) { + w5100_write(priv, W5500_Sn_RXMEM_SIZE(i), 0); + w5100_write(priv, W5500_Sn_TXMEM_SIZE(i), 0); + } +} + +static int w5100_hw_reset(struct w5100_priv *priv) +{ + u32 rtr; + w5100_reset(priv); - w5100_write(priv, W5100_IMR, 0); + w5100_disable_intr(priv); w5100_write_macaddr(priv); - if (is_w5200(priv)) - w5200_memory_configure(priv); - else + switch (priv->ops->chip_id) { + case W5100: w5100_memory_configure(priv); + rtr = W5100_RTR; + break; + case W5200: + w5200_memory_configure(priv); + rtr = W5100_RTR; + break; + case W5500: + w5500_memory_configure(priv); + rtr = W5500_RTR; + break; + default: + return -EINVAL; + } + + if (w5100_read16(priv, rtr) != RTR_DEFAULT) + return -ENODEV; + + return 0; } static void w5100_hw_start(struct w5100_priv *priv) @@ -621,12 +710,12 @@ static void w5100_hw_start(struct w5100_priv *priv) w5100_write(priv, W5100_S0_MR(priv), priv->promisc ? S0_MR_MACRAW : S0_MR_MACRAW_MF); w5100_command(priv, S0_CR_OPEN); - w5100_write(priv, W5100_IMR, IR_S0); + w5100_enable_intr(priv); } static void w5100_hw_close(struct w5100_priv *priv) { - w5100_write(priv, W5100_IMR, 0); + w5100_disable_intr(priv); w5100_command(priv, S0_CR_CLOSE); } @@ -805,7 +894,7 @@ static void w5100_rx_work(struct work_struct *work) while ((skb = w5100_rx_skb(priv->ndev))) netif_rx_ni(skb); - w5100_write(priv, W5100_IMR, IR_S0); + w5100_enable_intr(priv); } static int w5100_napi_poll(struct napi_struct *napi, int budget) @@ -824,7 +913,7 @@ static int w5100_napi_poll(struct napi_struct *napi, int budget) if (rx_count < budget) { napi_complete(napi); - w5100_write(priv, W5100_IMR, IR_S0); + w5100_enable_intr(priv); } return rx_count; @@ -846,7 +935,7 @@ static irqreturn_t w5100_interrupt(int irq, void *ndev_instance) } if (ir & S0_IR_RECV) { - w5100_write(priv, W5100_IMR, 0); + w5100_disable_intr(priv); if (priv->ops->may_sleep) queue_work(priv->xfer_wq, &priv->rx_work); @@ -1014,6 +1103,34 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops, SET_NETDEV_DEV(ndev, dev); dev_set_drvdata(dev, ndev); priv = netdev_priv(ndev); + + switch (ops->chip_id) { + case W5100: + priv->s0_regs = W5100_S0_REGS; + priv->s0_tx_buf = W5100_TX_MEM_START; + priv->s0_tx_buf_size = W5100_TX_MEM_SIZE; + priv->s0_rx_buf = W5100_RX_MEM_START; + priv->s0_rx_buf_size = W5100_RX_MEM_SIZE; + break; + case W5200: + priv->s0_regs = W5200_S0_REGS; + priv->s0_tx_buf = W5200_TX_MEM_START; + priv->s0_tx_buf_size = W5200_TX_MEM_SIZE; + priv->s0_rx_buf = W5200_RX_MEM_START; + priv->s0_rx_buf_size = W5200_RX_MEM_SIZE; + break; + case W5500: + priv->s0_regs = W5500_S0_REGS; + priv->s0_tx_buf = W5500_TX_MEM_START; + priv->s0_tx_buf_size = W5500_TX_MEM_SIZE; + priv->s0_rx_buf = W5500_RX_MEM_START; + priv->s0_rx_buf_size = W5500_RX_MEM_SIZE; + break; + default: + err = -EINVAL; + goto err_register; + } + priv->ndev = ndev; priv->ops = ops; priv->irq = irq; @@ -1055,11 +1172,9 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops, goto err_hw; } - w5100_hw_reset(priv); - if (w5100_read16(priv, W5100_RTR) != RTR_DEFAULT) { - err = -ENODEV; + err = w5100_hw_reset(priv); + if (err) goto err_hw; - } if (ops->may_sleep) { err = request_threaded_irq(priv->irq, NULL, w5100_interrupt, diff --git a/drivers/net/ethernet/wiznet/w5100.h b/drivers/net/ethernet/wiznet/w5100.h index 9b1fa23b46fe..f8a16fad807b 100644 --- a/drivers/net/ethernet/wiznet/w5100.h +++ b/drivers/net/ethernet/wiznet/w5100.h @@ -10,17 +10,18 @@ enum { W5100, W5200, + W5500, }; struct w5100_ops { bool may_sleep; int chip_id; - int (*read)(struct net_device *ndev, u16 addr); - int (*write)(struct net_device *ndev, u16 addr, u8 data); - int (*read16)(struct net_device *ndev, u16 addr); - int (*write16)(struct net_device *ndev, u16 addr, u16 data); - int (*readbulk)(struct net_device *ndev, u16 addr, u8 *buf, int len); - int (*writebulk)(struct net_device *ndev, u16 addr, const u8 *buf, + int (*read)(struct net_device *ndev, u32 addr); + int (*write)(struct net_device *ndev, u32 addr, u8 data); + int (*read16)(struct net_device *ndev, u32 addr); + int (*write16)(struct net_device *ndev, u32 addr, u16 data); + int (*readbulk)(struct net_device *ndev, u32 addr, u8 *buf, int len); + int (*writebulk)(struct net_device *ndev, u32 addr, const u8 *buf, int len); int (*reset)(struct net_device *ndev); int (*init)(struct net_device *ndev); -- GitLab From 501e7ef569f4ea2dc7e50773cf6a5d757c94f9b4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 26 Apr 2016 15:30:07 -0700 Subject: [PATCH 4851/9938] net-rfs: fix false sharing accessing sd->input_queue_head sd->input_queue_head is incremented for each processed packet in process_backlog(), and read from other cpus performing Out Of Order avoidance in get_rps_cpu() Moving this field in a separate cache line keeps it mostly hot for the cpu in process_backlog(), as other cpus will only read it. In a stress test, process_backlog() was consuming 6.80 % of cpu cycles, and the patch reduced the cost to 0.65 % Signed-off-by: Eric Dumazet Acked-by: Tom Herbert Signed-off-by: David S. Miller --- include/linux/netdevice.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 18d8394f2e5d..934ca866562d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2747,11 +2747,15 @@ struct softnet_data { struct sk_buff *completion_queue; #ifdef CONFIG_RPS - /* Elements below can be accessed between CPUs for RPS */ + /* input_queue_head should be written by cpu owning this struct, + * and only read by other cpus. Worth using a cache line. + */ + unsigned int input_queue_head ____cacheline_aligned_in_smp; + + /* Elements below can be accessed between CPUs for RPS/RFS */ struct call_single_data csd ____cacheline_aligned_in_smp; struct softnet_data *rps_ipi_next; unsigned int cpu; - unsigned int input_queue_head; unsigned int input_queue_tail; #endif unsigned int dropped; -- GitLab From 6aef70a851ac77967992340faaff33f44598f60a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:27 -0700 Subject: [PATCH 4852/9938] net: snmp: kill various STATS_USER() helpers In the old days (before linux-3.0), SNMP counters were duplicated, one for user context, and one for BH context. After commit 8f0ea0fe3a03 ("snmp: reduce percpu needs by 50%") we have a single copy, and what really matters is preemption being enabled or disabled, since we use this_cpu_inc() or __this_cpu_inc() respectively. We therefore kill SNMP_INC_STATS_USER(), SNMP_ADD_STATS_USER(), NET_INC_STATS_USER(), NET_ADD_STATS_USER(), SCTP_INC_STATS_USER(), SNMP_INC_STATS64_USER(), SNMP_ADD_STATS64_USER(), TCP_ADD_STATS_USER(), UDP_INC_STATS_USER(), UDP6_INC_STATS_USER(), and XFRM_INC_STATS_USER() Following patches will rename __BH helpers to make clear their usage is not tied to BH being disabled. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ip.h | 2 -- include/net/sctp/sctp.h | 1 - include/net/snmp.h | 22 +++++------------- include/net/tcp.h | 9 ++++---- include/net/udp.h | 14 ++++++------ include/net/xfrm.h | 2 -- net/ipv4/tcp.c | 12 +++++----- net/ipv4/udp.c | 24 ++++++++++---------- net/ipv6/udp.c | 49 ++++++++++++++++++++--------------------- net/sctp/chunk.c | 2 +- 10 files changed, 59 insertions(+), 78 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 93725e546758..ae0e85d018e8 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -194,10 +194,8 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, #define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val) #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) #define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field) -#define NET_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->mib.net_statistics, field) #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) #define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd) -#define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd) u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offct); unsigned long snmp_fold_field(void __percpu *mib, int offt); diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 3f1c0ff7d4b6..5a2c4c3307a7 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -207,7 +207,6 @@ extern int sysctl_sctp_wmem[3]; /* SCTP SNMP MIB stats handlers */ #define SCTP_INC_STATS(net, field) SNMP_INC_STATS((net)->sctp.sctp_statistics, field) #define SCTP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field) -#define SCTP_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->sctp.sctp_statistics, field) #define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field) /* sctp mib definitions */ diff --git a/include/net/snmp.h b/include/net/snmp.h index 35512ac6dcfb..56239fc05c51 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -126,9 +126,6 @@ struct linux_xfrm_mib { #define SNMP_INC_STATS_BH(mib, field) \ __this_cpu_inc(mib->mibs[field]) -#define SNMP_INC_STATS_USER(mib, field) \ - this_cpu_inc(mib->mibs[field]) - #define SNMP_INC_STATS_ATOMIC_LONG(mib, field) \ atomic_long_inc(&mib->mibs[field]) @@ -141,9 +138,6 @@ struct linux_xfrm_mib { #define SNMP_ADD_STATS_BH(mib, field, addend) \ __this_cpu_add(mib->mibs[field], addend) -#define SNMP_ADD_STATS_USER(mib, field, addend) \ - this_cpu_add(mib->mibs[field], addend) - #define SNMP_ADD_STATS(mib, field, addend) \ this_cpu_add(mib->mibs[field], addend) #define SNMP_UPD_PO_STATS(mib, basefield, addend) \ @@ -170,18 +164,14 @@ struct linux_xfrm_mib { u64_stats_update_end(&ptr->syncp); \ } while (0) -#define SNMP_ADD_STATS64_USER(mib, field, addend) \ +#define SNMP_ADD_STATS64(mib, field, addend) \ do { \ - local_bh_disable(); \ + preempt_disable(); \ SNMP_ADD_STATS64_BH(mib, field, addend); \ - local_bh_enable(); \ + preempt_enable(); \ } while (0) -#define SNMP_ADD_STATS64(mib, field, addend) \ - SNMP_ADD_STATS64_USER(mib, field, addend) - #define SNMP_INC_STATS64_BH(mib, field) SNMP_ADD_STATS64_BH(mib, field, 1) -#define SNMP_INC_STATS64_USER(mib, field) SNMP_ADD_STATS64_USER(mib, field, 1) #define SNMP_INC_STATS64(mib, field) SNMP_ADD_STATS64(mib, field, 1) #define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \ do { \ @@ -194,17 +184,15 @@ struct linux_xfrm_mib { } while (0) #define SNMP_UPD_PO_STATS64(mib, basefield, addend) \ do { \ - local_bh_disable(); \ + preempt_disable(); \ SNMP_UPD_PO_STATS64_BH(mib, basefield, addend); \ - local_bh_enable(); \ + preempt_enable(); \ } while (0) #else #define SNMP_INC_STATS64_BH(mib, field) SNMP_INC_STATS_BH(mib, field) -#define SNMP_INC_STATS64_USER(mib, field) SNMP_INC_STATS_USER(mib, field) #define SNMP_INC_STATS64(mib, field) SNMP_INC_STATS(mib, field) #define SNMP_DEC_STATS64(mib, field) SNMP_DEC_STATS(mib, field) #define SNMP_ADD_STATS64_BH(mib, field, addend) SNMP_ADD_STATS_BH(mib, field, addend) -#define SNMP_ADD_STATS64_USER(mib, field, addend) SNMP_ADD_STATS_USER(mib, field, addend) #define SNMP_ADD_STATS64(mib, field, addend) SNMP_ADD_STATS(mib, field, addend) #define SNMP_UPD_PO_STATS64(mib, basefield, addend) SNMP_UPD_PO_STATS(mib, basefield, addend) #define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) SNMP_UPD_PO_STATS_BH(mib, basefield, addend) diff --git a/include/net/tcp.h b/include/net/tcp.h index 7f2553da10d1..cfe15f712164 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -334,7 +334,6 @@ extern struct proto tcp_prot; #define TCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field) #define TCP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field) #define TCP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->mib.tcp_statistics, field) -#define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val) #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) void tcp_tasklet_init(void); @@ -1298,10 +1297,10 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb, static inline void tcp_mib_init(struct net *net) { /* See RFC 2012 */ - TCP_ADD_STATS_USER(net, TCP_MIB_RTOALGORITHM, 1); - TCP_ADD_STATS_USER(net, TCP_MIB_RTOMIN, TCP_RTO_MIN*1000/HZ); - TCP_ADD_STATS_USER(net, TCP_MIB_RTOMAX, TCP_RTO_MAX*1000/HZ); - TCP_ADD_STATS_USER(net, TCP_MIB_MAXCONN, -1); + TCP_ADD_STATS(net, TCP_MIB_RTOALGORITHM, 1); + TCP_ADD_STATS(net, TCP_MIB_RTOMIN, TCP_RTO_MIN*1000/HZ); + TCP_ADD_STATS(net, TCP_MIB_RTOMAX, TCP_RTO_MAX*1000/HZ); + TCP_ADD_STATS(net, TCP_MIB_MAXCONN, -1); } /* from STCP */ diff --git a/include/net/udp.h b/include/net/udp.h index 3c5a65e0946d..2f37f689d85a 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -289,20 +289,20 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, /* * SNMP statistics for UDP and UDP-Lite */ -#define UDP_INC_STATS_USER(net, field, is_udplite) do { \ - if (is_udplite) SNMP_INC_STATS_USER((net)->mib.udplite_statistics, field); \ - else SNMP_INC_STATS_USER((net)->mib.udp_statistics, field); } while(0) +#define UDP_INC_STATS(net, field, is_udplite) do { \ + if (is_udplite) SNMP_INC_STATS((net)->mib.udplite_statistics, field); \ + else SNMP_INC_STATS((net)->mib.udp_statistics, field); } while(0) #define UDP_INC_STATS_BH(net, field, is_udplite) do { \ if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_statistics, field); \ else SNMP_INC_STATS_BH((net)->mib.udp_statistics, field); } while(0) -#define UDP6_INC_STATS_BH(net, field, is_udplite) do { \ +#define UDP6_INC_STATS_BH(net, field, is_udplite) do { \ if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_stats_in6, field);\ else SNMP_INC_STATS_BH((net)->mib.udp_stats_in6, field); \ } while(0) -#define UDP6_INC_STATS_USER(net, field, __lite) do { \ - if (__lite) SNMP_INC_STATS_USER((net)->mib.udplite_stats_in6, field); \ - else SNMP_INC_STATS_USER((net)->mib.udp_stats_in6, field); \ +#define UDP6_INC_STATS(net, field, __lite) do { \ + if (__lite) SNMP_INC_STATS((net)->mib.udplite_stats_in6, field); \ + else SNMP_INC_STATS((net)->mib.udp_stats_in6, field); \ } while(0) #if IS_ENABLED(CONFIG_IPV6) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d6f6e5006ee9..dab9e1b82963 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -46,11 +46,9 @@ #ifdef CONFIG_XFRM_STATISTICS #define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field) #define XFRM_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.xfrm_statistics, field) -#define XFRM_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)-mib.xfrm_statistics, field) #else #define XFRM_INC_STATS(net, field) ((void)(net)) #define XFRM_INC_STATS_BH(net, field) ((void)(net)) -#define XFRM_INC_STATS_USER(net, field) ((void)(net)) #endif diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 4d73858991af..55ef55ac9e38 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1443,7 +1443,7 @@ static void tcp_prequeue_process(struct sock *sk) struct sk_buff *skb; struct tcp_sock *tp = tcp_sk(sk); - NET_INC_STATS_USER(sock_net(sk), LINUX_MIB_TCPPREQUEUED); + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPREQUEUED); /* RX process wants to run with disabled BHs, though it is not * necessary */ @@ -1777,7 +1777,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, chunk = len - tp->ucopy.len; if (chunk != 0) { - NET_ADD_STATS_USER(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG, chunk); + NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG, chunk); len -= chunk; copied += chunk; } @@ -1789,7 +1789,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, chunk = len - tp->ucopy.len; if (chunk != 0) { - NET_ADD_STATS_USER(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk); + NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk); len -= chunk; copied += chunk; } @@ -1875,7 +1875,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, tcp_prequeue_process(sk); if (copied > 0 && (chunk = len - tp->ucopy.len) != 0) { - NET_ADD_STATS_USER(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk); + NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk); len -= chunk; copied += chunk; } @@ -2065,13 +2065,13 @@ void tcp_close(struct sock *sk, long timeout) sk->sk_prot->disconnect(sk, 0); } else if (data_was_unread) { /* Unread data was tossed, zap the connection. */ - NET_INC_STATS_USER(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE); + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE); tcp_set_state(sk, TCP_CLOSE); tcp_send_active_reset(sk, sk->sk_allocation); } else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { /* Check zero linger _after_ checking for unread data. */ sk->sk_prot->disconnect(sk, 0); - NET_INC_STATS_USER(sock_net(sk), LINUX_MIB_TCPABORTONDATA); + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA); } else if (tcp_close_state(sk)) { /* We FIN if the application ate all the data before * zapping the connection. diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 76ea0a8be090..00f5de9a155e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -882,13 +882,13 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) err = ip_send_skb(sock_net(sk), skb); if (err) { if (err == -ENOBUFS && !inet->recverr) { - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_SNDBUFERRORS, is_udplite); + UDP_INC_STATS(sock_net(sk), + UDP_MIB_SNDBUFERRORS, is_udplite); err = 0; } } else - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_OUTDATAGRAMS, is_udplite); + UDP_INC_STATS(sock_net(sk), + UDP_MIB_OUTDATAGRAMS, is_udplite); return err; } @@ -1157,8 +1157,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) * seems like overkill. */ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_SNDBUFERRORS, is_udplite); + UDP_INC_STATS(sock_net(sk), + UDP_MIB_SNDBUFERRORS, is_udplite); } return err; @@ -1352,16 +1352,16 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, trace_kfree_skb(skb, udp_recvmsg); if (!peeked) { atomic_inc(&sk->sk_drops); - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, is_udplite); + UDP_INC_STATS(sock_net(sk), + UDP_MIB_INERRORS, is_udplite); } skb_free_datagram_locked(sk, skb); return err; } if (!peeked) - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_INDATAGRAMS, is_udplite); + UDP_INC_STATS(sock_net(sk), + UDP_MIB_INDATAGRAMS, is_udplite); sock_recv_ts_and_drops(msg, sk, skb); @@ -1386,8 +1386,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, csum_copy_err: slow = lock_sock_fast(sk); if (!skb_kill_datagram(sk, skb, flags)) { - UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); - UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); + UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); + UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); } unlock_sock_fast(sk, slow); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8d8b2cd8ec5b..baa56ca41a31 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -423,24 +423,22 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (!peeked) { atomic_inc(&sk->sk_drops); if (is_udp4) - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, - is_udplite); + UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, + is_udplite); else - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, - is_udplite); + UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, + is_udplite); } skb_free_datagram_locked(sk, skb); return err; } if (!peeked) { if (is_udp4) - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_INDATAGRAMS, is_udplite); + UDP_INC_STATS(sock_net(sk), UDP_MIB_INDATAGRAMS, + is_udplite); else - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_INDATAGRAMS, is_udplite); + UDP6_INC_STATS(sock_net(sk), UDP_MIB_INDATAGRAMS, + is_udplite); } sock_recv_ts_and_drops(msg, sk, skb); @@ -487,15 +485,15 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, slow = lock_sock_fast(sk); if (!skb_kill_datagram(sk, skb, flags)) { if (is_udp4) { - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_CSUMERRORS, is_udplite); - UDP_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, is_udplite); + UDP_INC_STATS(sock_net(sk), + UDP_MIB_CSUMERRORS, is_udplite); + UDP_INC_STATS(sock_net(sk), + UDP_MIB_INERRORS, is_udplite); } else { - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_CSUMERRORS, is_udplite); - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_INERRORS, is_udplite); + UDP6_INC_STATS(sock_net(sk), + UDP_MIB_CSUMERRORS, is_udplite); + UDP6_INC_STATS(sock_net(sk), + UDP_MIB_INERRORS, is_udplite); } } unlock_sock_fast(sk, slow); @@ -1015,13 +1013,14 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6) err = ip6_send_skb(skb); if (err) { if (err == -ENOBUFS && !inet6_sk(sk)->recverr) { - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_SNDBUFERRORS, is_udplite); + UDP6_INC_STATS(sock_net(sk), + UDP_MIB_SNDBUFERRORS, is_udplite); err = 0; } - } else - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_OUTDATAGRAMS, is_udplite); + } else { + UDP6_INC_STATS(sock_net(sk), + UDP_MIB_OUTDATAGRAMS, is_udplite); + } return err; } @@ -1342,8 +1341,8 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) * seems like overkill. */ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { - UDP6_INC_STATS_USER(sock_net(sk), - UDP_MIB_SNDBUFERRORS, is_udplite); + UDP6_INC_STATS(sock_net(sk), + UDP_MIB_SNDBUFERRORS, is_udplite); } return err; diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 958ef5f33f4b..1eb94bf18ef4 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -239,7 +239,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, offset = 0; if ((whole > 1) || (whole && over)) - SCTP_INC_STATS_USER(sock_net(asoc->base.sk), SCTP_MIB_FRAGUSRMSGS); + SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_FRAGUSRMSGS); /* Create chunks for all the full sized DATA chunks. */ for (i = 0, len = first_len; i < whole; i++) { -- GitLab From aa62d76b6e1a7c927a9e0ca39de8a93b751f3b8c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:28 -0700 Subject: [PATCH 4853/9938] dccp: rename DCCP_INC_STATS_BH() Rename DCCP_INC_STATS_BH() to __DCCP_INC_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/dccp/dccp.h | 6 +++--- net/dccp/input.c | 2 +- net/dccp/ipv4.c | 8 ++++---- net/dccp/ipv6.c | 8 ++++---- net/dccp/minisocks.c | 2 +- net/dccp/options.c | 2 +- net/dccp/timer.c | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index b0e28d24e1a7..a4c6e2fed91c 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -198,9 +198,9 @@ struct dccp_mib { }; DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); -#define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field) -#define DCCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(dccp_statistics, field) -#define DCCP_DEC_STATS(field) SNMP_DEC_STATS(dccp_statistics, field) +#define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field) +#define __DCCP_INC_STATS(field) SNMP_INC_STATS_BH(dccp_statistics, field) +#define DCCP_DEC_STATS(field) SNMP_DEC_STATS(dccp_statistics, field) /* * Checksumming routines diff --git a/net/dccp/input.c b/net/dccp/input.c index 3bd14e885396..2437ecc13b82 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -359,7 +359,7 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, goto discard; } - DCCP_INC_STATS_BH(DCCP_MIB_INERRS); + __DCCP_INC_STATS(DCCP_MIB_INERRS); discard: __kfree_skb(skb); return 0; diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index f6d183f8f332..4b78067669d6 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -318,7 +318,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) case DCCP_REQUESTING: case DCCP_RESPOND: if (!sock_owned_by_user(sk)) { - DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); + __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS); sk->sk_err = err; sk->sk_error_report(sk); @@ -533,8 +533,8 @@ static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb) bh_unlock_sock(ctl_sk); if (net_xmit_eval(err) == 0) { - DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); - DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); + __DCCP_INC_STATS(DCCP_MIB_OUTSEGS); + __DCCP_INC_STATS(DCCP_MIB_OUTRSTS); } out: dst_release(dst); @@ -637,7 +637,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) drop_and_free: reqsk_free(req); drop: - DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); + __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS); return -1; } EXPORT_SYMBOL_GPL(dccp_v4_conn_request); diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 8ceb3cebcad4..e175b8fe1a87 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -156,7 +156,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, case DCCP_RESPOND: /* Cannot happen. It can, it SYNs are crossed. --ANK */ if (!sock_owned_by_user(sk)) { - DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); + __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS); sk->sk_err = err; /* * Wake people up to see the error @@ -277,8 +277,8 @@ static void dccp_v6_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb) if (!IS_ERR(dst)) { skb_dst_set(skb, dst); ip6_xmit(ctl_sk, skb, &fl6, NULL, 0); - DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); - DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); + __DCCP_INC_STATS(DCCP_MIB_OUTSEGS); + __DCCP_INC_STATS(DCCP_MIB_OUTRSTS); return; } @@ -378,7 +378,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) drop_and_free: reqsk_free(req); drop: - DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); + __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS); return -1; } diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 1994f8af646b..53eddf99e4f6 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -127,7 +127,7 @@ struct sock *dccp_create_openreq_child(const struct sock *sk, } dccp_init_xmit_timers(newsk); - DCCP_INC_STATS_BH(DCCP_MIB_PASSIVEOPENS); + __DCCP_INC_STATS(DCCP_MIB_PASSIVEOPENS); } return newsk; } diff --git a/net/dccp/options.c b/net/dccp/options.c index 9bce31886bda..b82b7ee9a1d2 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -253,7 +253,7 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, return 0; out_invalid_option: - DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); + __DCCP_INC_STATS(DCCP_MIB_INVALIDOPT); rc = DCCP_RESET_CODE_OPTION_ERROR; out_featneg_failed: DCCP_WARN("DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc); diff --git a/net/dccp/timer.c b/net/dccp/timer.c index 3ef7acef3ce8..4ff22c24ff14 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -28,7 +28,7 @@ static void dccp_write_err(struct sock *sk) dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED); dccp_done(sk); - DCCP_INC_STATS_BH(DCCP_MIB_ABORTONTIMEOUT); + __DCCP_INC_STATS(DCCP_MIB_ABORTONTIMEOUT); } /* A write timeout has occurred. Process the after effects. */ @@ -100,7 +100,7 @@ static void dccp_retransmit_timer(struct sock *sk) * total number of retransmissions of clones of original packets. */ if (icsk->icsk_retransmits == 0) - DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS); + __DCCP_INC_STATS(DCCP_MIB_TIMEOUTS); if (dccp_retransmit_skb(sk) != 0) { /* -- GitLab From 5d3848bc33b7d13fc97b5b6e0dccde2d0755bfd5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:29 -0700 Subject: [PATCH 4854/9938] net: rename ICMP_INC_STATS_BH() Rename ICMP_INC_STATS_BH() to __ICMP_INC_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/icmp.h | 2 +- net/dccp/ipv4.c | 4 ++-- net/ipv4/icmp.c | 16 ++++++++-------- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 2 +- net/sctp/input.c | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/net/icmp.h b/include/net/icmp.h index 970028e13382..5a60ce819078 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -30,7 +30,7 @@ struct icmp_err { extern const struct icmp_err icmp_err_convert[]; #define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field) -#define ICMP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field) +#define __ICMP_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field) #define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256) #define ICMPMSGIN_INC_STATS_BH(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 4b78067669d6..14e30584e59d 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -247,7 +247,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) if (skb->len < offset + sizeof(*dh) || skb->len < offset + __dccp_basic_hdr_len(dh)) { - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); return; } @@ -256,7 +256,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) iph->saddr, ntohs(dh->dccph_sport), inet_iif(skb)); if (!sk) { - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); return; } diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 6333489771ed..995fef9c5099 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -363,7 +363,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, icmp_param->data_len+icmp_param->head_len, icmp_param->head_len, ipc, rt, MSG_DONTWAIT) < 0) { - ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_OUTERRORS); + __ICMP_INC_STATS(sock_net(sk), ICMP_MIB_OUTERRORS); ip_flush_pending_frames(sk); } else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { struct icmphdr *icmph = icmp_hdr(skb); @@ -744,7 +744,7 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) * avoid additional coding at protocol handlers. */ if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { - ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); + __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); return; } @@ -865,7 +865,7 @@ static bool icmp_unreach(struct sk_buff *skb) out: return true; out_err: - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); return false; } @@ -877,7 +877,7 @@ static bool icmp_unreach(struct sk_buff *skb) static bool icmp_redirect(struct sk_buff *skb) { if (skb->len < sizeof(struct iphdr)) { - ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); + __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); return false; } @@ -956,7 +956,7 @@ static bool icmp_timestamp(struct sk_buff *skb) return true; out_err: - ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); + __ICMP_INC_STATS(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); return false; } @@ -996,7 +996,7 @@ int icmp_rcv(struct sk_buff *skb) skb_set_network_header(skb, nh); } - ICMP_INC_STATS_BH(net, ICMP_MIB_INMSGS); + __ICMP_INC_STATS(net, ICMP_MIB_INMSGS); if (skb_checksum_simple_validate(skb)) goto csum_error; @@ -1052,9 +1052,9 @@ int icmp_rcv(struct sk_buff *skb) kfree_skb(skb); return 0; csum_error: - ICMP_INC_STATS_BH(net, ICMP_MIB_CSUMERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_CSUMERRORS); error: - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); goto drop; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d2a5763e5abc..ebd8f3b9e61b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -372,7 +372,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) th->dest, iph->saddr, ntohs(th->source), inet_iif(icmp_skb)); if (!sk) { - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); return; } if (sk->sk_state == TCP_TIME_WAIT) { diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 00f5de9a155e..6b004b838966 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -688,7 +688,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) iph->saddr, uh->source, skb->dev->ifindex, udptable, NULL); if (!sk) { - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); return; /* No socket for error */ } diff --git a/net/sctp/input.c b/net/sctp/input.c index 00b8445364e3..f8eca792dbcf 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -589,7 +589,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) skb->network_header = saveip; skb->transport_header = savesctp; if (!sk) { - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); return; } /* Warning: The sock lock is held. Remember to call -- GitLab From 02c223470c3cc30e5ff90217abea761679553ac3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:30 -0700 Subject: [PATCH 4855/9938] net: udp: rename UDP_INC_STATS_BH() Rename UDP_INC_STATS_BH() to __UDP_INC_STATS(), and UDP6_INC_STATS_BH() to __UDP6_INC_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/udp.h | 12 +++++------ net/ipv4/udp.c | 46 +++++++++++++++++++++---------------------- net/ipv6/udp.c | 38 +++++++++++++++++------------------ net/rxrpc/ar-input.c | 4 ++-- net/sunrpc/xprtsock.c | 4 ++-- 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/include/net/udp.h b/include/net/udp.h index 2f37f689d85a..bf6a7c29cf6a 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -292,11 +292,11 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, #define UDP_INC_STATS(net, field, is_udplite) do { \ if (is_udplite) SNMP_INC_STATS((net)->mib.udplite_statistics, field); \ else SNMP_INC_STATS((net)->mib.udp_statistics, field); } while(0) -#define UDP_INC_STATS_BH(net, field, is_udplite) do { \ +#define __UDP_INC_STATS(net, field, is_udplite) do { \ if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_statistics, field); \ else SNMP_INC_STATS_BH((net)->mib.udp_statistics, field); } while(0) -#define UDP6_INC_STATS_BH(net, field, is_udplite) do { \ +#define __UDP6_INC_STATS(net, field, is_udplite) do { \ if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_stats_in6, field);\ else SNMP_INC_STATS_BH((net)->mib.udp_stats_in6, field); \ } while(0) @@ -306,15 +306,15 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, } while(0) #if IS_ENABLED(CONFIG_IPV6) -#define UDPX_INC_STATS_BH(sk, field) \ +#define __UDPX_INC_STATS(sk, field) \ do { \ if ((sk)->sk_family == AF_INET) \ - UDP_INC_STATS_BH(sock_net(sk), field, 0); \ + __UDP_INC_STATS(sock_net(sk), field, 0); \ else \ - UDP6_INC_STATS_BH(sock_net(sk), field, 0); \ + __UDP6_INC_STATS(sock_net(sk), field, 0); \ } while (0) #else -#define UDPX_INC_STATS_BH(sk, field) UDP_INC_STATS_BH(sock_net(sk), field, 0) +#define __UDPX_INC_STATS(sk, field) __UDP_INC_STATS(sock_net(sk), field, 0) #endif /* /proc */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6b004b838966..093284c5c03b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1242,10 +1242,10 @@ static unsigned int first_packet_length(struct sock *sk) spin_lock_bh(&rcvq->lock); while ((skb = skb_peek(rcvq)) != NULL && udp_lib_checksum_complete(skb)) { - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, - IS_UDPLITE(sk)); - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, - IS_UDPLITE(sk)); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, + IS_UDPLITE(sk)); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, + IS_UDPLITE(sk)); atomic_inc(&sk->sk_drops); __skb_unlink(skb, rcvq); __skb_queue_tail(&list_kill, skb); @@ -1514,9 +1514,9 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) /* Note that an ENOMEM error is charged twice */ if (rc == -ENOMEM) - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, - is_udplite); - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_RCVBUFERRORS, + is_udplite); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); kfree_skb(skb); trace_udp_fail_queue_rcv_skb(rc, sk); return -1; @@ -1580,9 +1580,9 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) ret = encap_rcv(sk, skb); if (ret <= 0) { - UDP_INC_STATS_BH(sock_net(sk), - UDP_MIB_INDATAGRAMS, - is_udplite); + __UDP_INC_STATS(sock_net(sk), + UDP_MIB_INDATAGRAMS, + is_udplite); return -ret; } } @@ -1633,8 +1633,8 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) udp_csum_pull_header(skb); if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, - is_udplite); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_RCVBUFERRORS, + is_udplite); goto drop; } @@ -1653,9 +1653,9 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) return rc; csum_error: - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); drop: - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); atomic_inc(&sk->sk_drops); kfree_skb(skb); return -1; @@ -1715,10 +1715,10 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, if (unlikely(!nskb)) { atomic_inc(&sk->sk_drops); - UDP_INC_STATS_BH(net, UDP_MIB_RCVBUFERRORS, - IS_UDPLITE(sk)); - UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, - IS_UDPLITE(sk)); + __UDP_INC_STATS(net, UDP_MIB_RCVBUFERRORS, + IS_UDPLITE(sk)); + __UDP_INC_STATS(net, UDP_MIB_INERRORS, + IS_UDPLITE(sk)); continue; } if (udp_queue_rcv_skb(sk, nskb) > 0) @@ -1736,8 +1736,8 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, consume_skb(skb); } else { kfree_skb(skb); - UDP_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, - proto == IPPROTO_UDPLITE); + __UDP_INC_STATS(net, UDP_MIB_IGNOREDMULTI, + proto == IPPROTO_UDPLITE); } return 0; } @@ -1851,7 +1851,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (udp_lib_checksum_complete(skb)) goto csum_error; - UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); + __UDP_INC_STATS(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); /* @@ -1878,9 +1878,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, proto == IPPROTO_UDPLITE ? "Lite" : "", &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest), ulen); - UDP_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); + __UDP_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); drop: - UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); + __UDP_INC_STATS(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); kfree_skb(skb); return 0; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index baa56ca41a31..1243d22e2b1d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -570,9 +570,9 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) /* Note that an ENOMEM error is charged twice */ if (rc == -ENOMEM) - UDP6_INC_STATS_BH(sock_net(sk), - UDP_MIB_RCVBUFERRORS, is_udplite); - UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); + __UDP6_INC_STATS(sock_net(sk), + UDP_MIB_RCVBUFERRORS, is_udplite); + __UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); kfree_skb(skb); return -1; } @@ -628,9 +628,9 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) ret = encap_rcv(sk, skb); if (ret <= 0) { - UDP_INC_STATS_BH(sock_net(sk), - UDP_MIB_INDATAGRAMS, - is_udplite); + __UDP_INC_STATS(sock_net(sk), + UDP_MIB_INDATAGRAMS, + is_udplite); return -ret; } } @@ -664,8 +664,8 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) udp_csum_pull_header(skb); if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { - UDP6_INC_STATS_BH(sock_net(sk), - UDP_MIB_RCVBUFERRORS, is_udplite); + __UDP6_INC_STATS(sock_net(sk), + UDP_MIB_RCVBUFERRORS, is_udplite); goto drop; } @@ -684,9 +684,9 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) return rc; csum_error: - UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); + __UDP6_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); drop: - UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); + __UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); atomic_inc(&sk->sk_drops); kfree_skb(skb); return -1; @@ -769,10 +769,10 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, nskb = skb_clone(skb, GFP_ATOMIC); if (unlikely(!nskb)) { atomic_inc(&sk->sk_drops); - UDP6_INC_STATS_BH(net, UDP_MIB_RCVBUFERRORS, - IS_UDPLITE(sk)); - UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, - IS_UDPLITE(sk)); + __UDP6_INC_STATS(net, UDP_MIB_RCVBUFERRORS, + IS_UDPLITE(sk)); + __UDP6_INC_STATS(net, UDP_MIB_INERRORS, + IS_UDPLITE(sk)); continue; } @@ -791,8 +791,8 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, consume_skb(skb); } else { kfree_skb(skb); - UDP6_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, - proto == IPPROTO_UDPLITE); + __UDP6_INC_STATS(net, UDP_MIB_IGNOREDMULTI, + proto == IPPROTO_UDPLITE); } return 0; } @@ -885,7 +885,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (udp_lib_checksum_complete(skb)) goto csum_error; - UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); + __UDP6_INC_STATS(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); kfree_skb(skb); @@ -899,9 +899,9 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, daddr, ntohs(uh->dest)); goto discard; csum_error: - UDP6_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); + __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); discard: - UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); + __UDP6_INC_STATS(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); kfree_skb(skb); return 0; } diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index 01e038146b7c..6ff97412a0bb 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c @@ -698,12 +698,12 @@ void rxrpc_data_ready(struct sock *sk) if (skb_checksum_complete(skb)) { rxrpc_free_skb(skb); rxrpc_put_local(local); - UDP_INC_STATS_BH(&init_net, UDP_MIB_INERRORS, 0); + __UDP_INC_STATS(&init_net, UDP_MIB_INERRORS, 0); _leave(" [CSUM failed]"); return; } - UDP_INC_STATS_BH(&init_net, UDP_MIB_INDATAGRAMS, 0); + __UDP_INC_STATS(&init_net, UDP_MIB_INDATAGRAMS, 0); /* The socket buffer we have is owned by UDP, with UDP's data all over * it, but we really want our own data there. diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d0756ac5c0f2..a6c68dc086af 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1018,11 +1018,11 @@ static void xs_udp_data_read_skb(struct rpc_xprt *xprt, /* Suck it into the iovec, verify checksum if not done by hw. */ if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb)) { - UDPX_INC_STATS_BH(sk, UDP_MIB_INERRORS); + __UDPX_INC_STATS(sk, UDP_MIB_INERRORS); goto out_unlock; } - UDPX_INC_STATS_BH(sk, UDP_MIB_INDATAGRAMS); + __UDPX_INC_STATS(sk, UDP_MIB_INDATAGRAMS); xprt_adjust_cwnd(xprt, task, copied); xprt_complete_rqst(task, copied); -- GitLab From b540f9d702f0eedf4f2dc49472f4cf40d053d5b1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:31 -0700 Subject: [PATCH 4856/9938] net: xfrm: kill XFRM_INC_STATS_BH() Not used anymore. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index dab9e1b82963..adfebd6f243c 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -45,10 +45,8 @@ #ifdef CONFIG_XFRM_STATISTICS #define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field) -#define XFRM_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.xfrm_statistics, field) #else #define XFRM_INC_STATS(net, field) ((void)(net)) -#define XFRM_INC_STATS_BH(net, field) ((void)(net)) #endif -- GitLab From 90bbcc608369a1b46089b0f5aa22b8ea31ffa12e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:32 -0700 Subject: [PATCH 4857/9938] net: tcp: rename TCP_INC_STATS_BH Rename TCP_INC_STATS_BH() to __TCP_INC_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 2 +- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_input.c | 8 ++++---- net/ipv4/tcp_ipv4.c | 16 ++++++++-------- net/ipv4/tcp_minisocks.c | 4 ++-- net/ipv4/tcp_output.c | 4 ++-- net/ipv6/tcp_ipv6.c | 14 +++++++------- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index cfe15f712164..939ebd5320a9 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -332,7 +332,7 @@ bool tcp_check_oom(struct sock *sk, int shift); extern struct proto tcp_prot; #define TCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field) -#define TCP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field) +#define __TCP_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field) #define TCP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->mib.tcp_statistics, field) #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 55ef55ac9e38..96833433c2c3 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3091,7 +3091,7 @@ void tcp_done(struct sock *sk) struct request_sock *req = tcp_sk(sk)->fastopen_rsk; if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS); tcp_set_state(sk, TCP_CLOSE); tcp_clear_xmit_timers(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 967520dbe0bf..dad8d93262ed 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5233,7 +5233,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, if (th->syn) { syn_challenge: if (syn_inerr) - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); tcp_send_challenge_ack(sk, skb); goto discard; @@ -5349,7 +5349,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, tcp_data_snd_check(sk); return; } else { /* Header too small */ - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); goto discard; } } else { @@ -5456,8 +5456,8 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, return; csum_error: - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS); - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); discard: tcp_drop(sk, skb); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ebd8f3b9e61b..378e92d41c6c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -697,8 +697,8 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); - TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); - TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); + __TCP_INC_STATS(net, TCP_MIB_OUTSEGS); + __TCP_INC_STATS(net, TCP_MIB_OUTRSTS); #ifdef CONFIG_TCP_MD5SIG out: @@ -779,7 +779,7 @@ static void tcp_v4_send_ack(struct net *net, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); - TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); + __TCP_INC_STATS(net, TCP_MIB_OUTSEGS); } static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) @@ -1432,8 +1432,8 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; csum_err: - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS); - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); goto discard; } EXPORT_SYMBOL(tcp_v4_do_rcv); @@ -1547,7 +1547,7 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_it; /* Count it even if it's bad */ - TCP_INC_STATS_BH(net, TCP_MIB_INSEGS); + __TCP_INC_STATS(net, TCP_MIB_INSEGS); if (!pskb_may_pull(skb, sizeof(struct tcphdr))) goto discard_it; @@ -1679,9 +1679,9 @@ int tcp_v4_rcv(struct sk_buff *skb) if (tcp_checksum_complete(skb)) { csum_error: - TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); + __TCP_INC_STATS(net, TCP_MIB_CSUMERRORS); bad_packet: - TCP_INC_STATS_BH(net, TCP_MIB_INERRS); + __TCP_INC_STATS(net, TCP_MIB_INERRS); } else { tcp_v4_send_reset(NULL, skb); } diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 4c53e7c86586..0be6bfeab553 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -545,7 +545,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, newtp->rack.mstamp.v64 = 0; newtp->rack.advanced = 0; - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_PASSIVEOPENS); } return newsk; } @@ -729,7 +729,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, * "fourth, check the SYN bit" */ if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) { - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS); goto embryonic_reset; } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9d3b4b364652..c48baf734e8c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -3042,7 +3042,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, th->window = htons(min(req->rsk_rcv_wnd, 65535U)); tcp_options_write((__be32 *)(th + 1), NULL, &opts); th->doff = (tcp_header_size >> 2); - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_OUTSEGS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); #ifdef CONFIG_TCP_MD5SIG /* Okay, we have all we need - do the md5 hash if needed */ @@ -3540,7 +3540,7 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req) tcp_rsk(req)->txhash = net_tx_rndhash(); res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL); if (!res) { - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); } return res; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 800265c7fd3f..52ca8fac7429 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -825,9 +825,9 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 if (!IS_ERR(dst)) { skb_dst_set(buff, dst); ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass); - TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); + __TCP_INC_STATS(net, TCP_MIB_OUTSEGS); if (rst) - TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); + __TCP_INC_STATS(net, TCP_MIB_OUTRSTS); return; } @@ -1276,8 +1276,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) kfree_skb(skb); return 0; csum_err: - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS); - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS); + __TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); goto discard; @@ -1359,7 +1359,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) /* * Count it even if it's bad. */ - TCP_INC_STATS_BH(net, TCP_MIB_INSEGS); + __TCP_INC_STATS(net, TCP_MIB_INSEGS); if (!pskb_may_pull(skb, sizeof(struct tcphdr))) goto discard_it; @@ -1472,9 +1472,9 @@ static int tcp_v6_rcv(struct sk_buff *skb) if (tcp_checksum_complete(skb)) { csum_error: - TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); + __TCP_INC_STATS(net, TCP_MIB_CSUMERRORS); bad_packet: - TCP_INC_STATS_BH(net, TCP_MIB_INERRS); + __TCP_INC_STATS(net, TCP_MIB_INERRS); } else { tcp_v6_send_reset(NULL, skb); } -- GitLab From 214d3f1f87e17357c422dad844f03be7b9d65ce7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:33 -0700 Subject: [PATCH 4858/9938] net: icmp: rename ICMPMSGIN_INC_STATS_BH() Remove misleading _BH suffix. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/icmp.h | 2 +- net/ipv4/icmp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/icmp.h b/include/net/icmp.h index 5a60ce819078..25edb740c648 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -32,7 +32,7 @@ extern const struct icmp_err icmp_err_convert[]; #define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field) #define __ICMP_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field) #define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256) -#define ICMPMSGIN_INC_STATS_BH(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field) +#define ICMPMSGIN_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field) struct dst_entry; struct net_proto_family; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 995fef9c5099..38abe70e595f 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -1006,7 +1006,7 @@ int icmp_rcv(struct sk_buff *skb) icmph = icmp_hdr(skb); - ICMPMSGIN_INC_STATS_BH(net, icmph->type); + ICMPMSGIN_INC_STATS(net, icmph->type); /* * 18 is the highest 'known' ICMP type. Anything else is a mystery * -- GitLab From 08e3baef65e2e9481637a1e8fb06089ca70be707 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:34 -0700 Subject: [PATCH 4859/9938] net: sctp: rename SCTP_INC_STATS_BH() Rename SCTP_INC_STATS_BH() to __SCTP_INC_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 2 +- net/sctp/input.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 5a2c4c3307a7..5607c009f738 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -206,7 +206,7 @@ extern int sysctl_sctp_wmem[3]; /* SCTP SNMP MIB stats handlers */ #define SCTP_INC_STATS(net, field) SNMP_INC_STATS((net)->sctp.sctp_statistics, field) -#define SCTP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field) +#define __SCTP_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field) #define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field) /* sctp mib definitions */ diff --git a/net/sctp/input.c b/net/sctp/input.c index f8eca792dbcf..12332fc3eb44 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -84,7 +84,7 @@ static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb) if (val != cmp) { /* CRC failure, dump it. */ - SCTP_INC_STATS_BH(net, SCTP_MIB_CHECKSUMERRORS); + __SCTP_INC_STATS(net, SCTP_MIB_CHECKSUMERRORS); return -1; } return 0; @@ -122,7 +122,7 @@ int sctp_rcv(struct sk_buff *skb) if (skb->pkt_type != PACKET_HOST) goto discard_it; - SCTP_INC_STATS_BH(net, SCTP_MIB_INSCTPPACKS); + __SCTP_INC_STATS(net, SCTP_MIB_INSCTPPACKS); if (skb_linearize(skb)) goto discard_it; @@ -208,7 +208,7 @@ int sctp_rcv(struct sk_buff *skb) */ if (!asoc) { if (sctp_rcv_ootb(skb)) { - SCTP_INC_STATS_BH(net, SCTP_MIB_OUTOFBLUES); + __SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); goto discard_release; } } @@ -264,9 +264,9 @@ int sctp_rcv(struct sk_buff *skb) skb = NULL; /* sctp_chunk_free already freed the skb */ goto discard_release; } - SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_BACKLOG); + __SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_BACKLOG); } else { - SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_SOFTIRQ); + __SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_SOFTIRQ); sctp_inq_push(&chunk->rcvr->inqueue, chunk); } @@ -281,7 +281,7 @@ int sctp_rcv(struct sk_buff *skb) return 0; discard_it: - SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_DISCARDS); + __SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS); kfree_skb(skb); return 0; -- GitLab From b45386efa2ec4533196a24d397ec5f9f0a42abc4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:35 -0700 Subject: [PATCH 4860/9938] net: rename IP_INC_STATS_BH() Rename IP_INC_STATS_BH() to __IP_INC_STATS(), to better express this is used in non preemptible context. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ip.h | 2 +- net/bridge/br_netfilter_hooks.c | 6 +++--- net/dccp/ipv4.c | 2 +- net/ipv4/inet_connection_sock.c | 4 ++-- net/ipv4/ip_forward.c | 4 ++-- net/ipv4/ip_fragment.c | 14 +++++++------- net/ipv4/ip_input.c | 20 ++++++++++---------- net/ipv4/route.c | 6 +++--- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index ae0e85d018e8..0be0af3017ba 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -187,7 +187,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, unsigned int len); #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) -#define IP_INC_STATS_BH(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field) +#define __IP_INC_STATS(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field) #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val) #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 44114a94c576..2d25979273a6 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -217,13 +217,13 @@ static int br_validate_ipv4(struct net *net, struct sk_buff *skb) len = ntohs(iph->tot_len); if (skb->len < len) { - IP_INC_STATS_BH(net, IPSTATS_MIB_INTRUNCATEDPKTS); + __IP_INC_STATS(net, IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } else if (len < (iph->ihl*4)) goto inhdr_error; if (pskb_trim_rcsum(skb, len)) { - IP_INC_STATS_BH(net, IPSTATS_MIB_INDISCARDS); + __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS); goto drop; } @@ -236,7 +236,7 @@ static int br_validate_ipv4(struct net *net, struct sk_buff *skb) return 0; inhdr_error: - IP_INC_STATS_BH(net, IPSTATS_MIB_INHDRERRORS); + __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS); drop: return -1; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 14e30584e59d..a9c75e79ba99 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -462,7 +462,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk, security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); rt = ip_route_output_flow(net, &fl4, sk); if (IS_ERR(rt)) { - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + __IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); return NULL; } diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index ab69da2d2a77..7ce112aa3a7b 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -427,7 +427,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk, route_err: ip_rt_put(rt); no_route: - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + __IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); return NULL; } EXPORT_SYMBOL_GPL(inet_csk_route_req); @@ -466,7 +466,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, ip_rt_put(rt); no_route: rcu_read_unlock(); - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + __IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); return NULL; } EXPORT_SYMBOL_GPL(inet_csk_route_child_sock); diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index af18f1e4889e..42fbd59b0ba8 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -65,7 +65,7 @@ static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *s { struct ip_options *opt = &(IPCB(skb)->opt); - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTFORWDATAGRAMS); + __IP_INC_STATS(net, IPSTATS_MIB_OUTFORWDATAGRAMS); IP_ADD_STATS_BH(net, IPSTATS_MIB_OUTOCTETS, skb->len); if (unlikely(opt->optlen)) @@ -157,7 +157,7 @@ int ip_forward(struct sk_buff *skb) too_many_hops: /* Tell the sender its packet died... */ - IP_INC_STATS_BH(net, IPSTATS_MIB_INHDRERRORS); + __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS); icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); drop: kfree_skb(skb); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index efbd47d1a531..bbe7f72db9c1 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -204,14 +204,14 @@ static void ip_expire(unsigned long arg) goto out; ipq_kill(qp); - IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); + __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); if (!inet_frag_evicting(&qp->q)) { struct sk_buff *head = qp->q.fragments; const struct iphdr *iph; int err; - IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT); + __IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT); if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments) goto out; @@ -291,7 +291,7 @@ static int ip_frag_too_far(struct ipq *qp) struct net *net; net = container_of(qp->q.net, struct net, ipv4.frags); - IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); + __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); } return rc; @@ -635,7 +635,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, ip_send_check(iph); - IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); + __IP_INC_STATS(net, IPSTATS_MIB_REASMOKS); qp->q.fragments = NULL; qp->q.fragments_tail = NULL; return 0; @@ -647,7 +647,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, out_oversize: net_info_ratelimited("Oversized IP packet from %pI4\n", &qp->saddr); out_fail: - IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); + __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); return err; } @@ -658,7 +658,7 @@ int ip_defrag(struct net *net, struct sk_buff *skb, u32 user) int vif = l3mdev_master_ifindex_rcu(dev); struct ipq *qp; - IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); + __IP_INC_STATS(net, IPSTATS_MIB_REASMREQDS); skb_orphan(skb); /* Lookup (or create) queue header */ @@ -675,7 +675,7 @@ int ip_defrag(struct net *net, struct sk_buff *skb, u32 user) return ret; } - IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); + __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); kfree_skb(skb); return -ENOMEM; } diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index e3d782746d9d..cca6729cd6ee 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -218,17 +218,17 @@ static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_b protocol = -ret; goto resubmit; } - IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); + __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS); } else { if (!raw) { if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { - IP_INC_STATS_BH(net, IPSTATS_MIB_INUNKNOWNPROTOS); + __IP_INC_STATS(net, IPSTATS_MIB_INUNKNOWNPROTOS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); } kfree_skb(skb); } else { - IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); + __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS); consume_skb(skb); } } @@ -273,7 +273,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb) --ANK (980813) */ if (skb_cow(skb, skb_headroom(skb))) { - IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); + __IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INDISCARDS); goto drop; } @@ -282,7 +282,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb) opt->optlen = iph->ihl*4 - sizeof(struct iphdr); if (ip_options_compile(dev_net(dev), opt, skb)) { - IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); + __IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INHDRERRORS); goto drop; } @@ -413,7 +413,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) { - IP_INC_STATS_BH(net, IPSTATS_MIB_INDISCARDS); + __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS); goto out; } @@ -453,7 +453,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, len = ntohs(iph->tot_len); if (skb->len < len) { - IP_INC_STATS_BH(net, IPSTATS_MIB_INTRUNCATEDPKTS); + __IP_INC_STATS(net, IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } else if (len < (iph->ihl*4)) goto inhdr_error; @@ -463,7 +463,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, * Note this now means skb->len holds ntohs(iph->tot_len). */ if (pskb_trim_rcsum(skb, len)) { - IP_INC_STATS_BH(net, IPSTATS_MIB_INDISCARDS); + __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS); goto drop; } @@ -480,9 +480,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, ip_rcv_finish); csum_error: - IP_INC_STATS_BH(net, IPSTATS_MIB_CSUMERRORS); + __IP_INC_STATS(net, IPSTATS_MIB_CSUMERRORS); inhdr_error: - IP_INC_STATS_BH(net, IPSTATS_MIB_INHDRERRORS); + __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS); drop: kfree_skb(skb); out: diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 60398a9370e7..8c8c655bb2c4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -915,11 +915,11 @@ static int ip_error(struct sk_buff *skb) if (!IN_DEV_FORWARD(in_dev)) { switch (rt->dst.error) { case EHOSTUNREACH: - IP_INC_STATS_BH(net, IPSTATS_MIB_INADDRERRORS); + __IP_INC_STATS(net, IPSTATS_MIB_INADDRERRORS); break; case ENETUNREACH: - IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES); + __IP_INC_STATS(net, IPSTATS_MIB_INNOROUTES); break; } goto out; @@ -934,7 +934,7 @@ static int ip_error(struct sk_buff *skb) break; case ENETUNREACH: code = ICMP_NET_UNREACH; - IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES); + __IP_INC_STATS(net, IPSTATS_MIB_INNOROUTES); break; case EACCES: code = ICMP_PKT_FILTERED; -- GitLab From a16292a0f0e0cef40ed51685dfde12b3002959b5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:36 -0700 Subject: [PATCH 4861/9938] net: rename ICMP6_INC_STATS_BH() Rename ICMP6_INC_STATS_BH() to __ICMP6_INC_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ipv6.h | 2 +- net/dccp/ipv6.c | 8 ++++---- net/ipv6/icmp.c | 10 +++++----- net/ipv6/tcp_ipv6.c | 4 ++-- net/ipv6/udp.c | 4 ++-- net/sctp/ipv6.c | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e93e947d04ff..a620fc56e2f5 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -179,7 +179,7 @@ extern int sysctl_mld_qrv; _DEVUPD(net, ipv6, 64_BH, idev, field, val) #define ICMP6_INC_STATS(net, idev, field) \ _DEVINCATOMIC(net, icmpv6, , idev, field) -#define ICMP6_INC_STATS_BH(net, idev, field) \ +#define __ICMP6_INC_STATS(net, idev, field) \ _DEVINCATOMIC(net, icmpv6, _BH, idev, field) #define ICMP6MSGOUT_INC_STATS(net, idev, field) \ diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index e175b8fe1a87..323c6b595e31 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -80,8 +80,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (skb->len < offset + sizeof(*dh) || skb->len < offset + __dccp_basic_hdr_len(dh)) { - ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), - ICMP6_MIB_INERRORS); + __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), + ICMP6_MIB_INERRORS); return; } @@ -91,8 +91,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, inet6_iif(skb)); if (!sk) { - ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), - ICMP6_MIB_INERRORS); + __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), + ICMP6_MIB_INERRORS); return; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 6b573ebe49de..823a1fc576e3 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -622,7 +622,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) np->dontfrag, &sockc_unused); if (err) { - ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); + __ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); ip6_flush_pending_frames(sk); } else { err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, @@ -674,7 +674,7 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) return; out: - ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); + __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); } /* @@ -710,7 +710,7 @@ static int icmpv6_rcv(struct sk_buff *skb) skb_set_network_header(skb, nh); } - ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INMSGS); + __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INMSGS); saddr = &ipv6_hdr(skb)->saddr; daddr = &ipv6_hdr(skb)->daddr; @@ -812,9 +812,9 @@ static int icmpv6_rcv(struct sk_buff *skb) return 0; csum_error: - ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_CSUMERRORS); + __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_CSUMERRORS); discard_it: - ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INERRORS); + __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INERRORS); drop_no_count: kfree_skb(skb); return 0; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 52ca8fac7429..78c45c027acc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -336,8 +336,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, skb->dev->ifindex); if (!sk) { - ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), - ICMP6_MIB_INERRORS); + __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), + ICMP6_MIB_INERRORS); return; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1243d22e2b1d..1ba5a74ac18f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -521,8 +521,8 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, inet6_iif(skb), udptable, skb); if (!sk) { - ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), - ICMP6_MIB_INERRORS); + __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), + ICMP6_MIB_INERRORS); return; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index ce46f1c7f133..0657d18a85bf 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -162,7 +162,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, skb->network_header = saveip; skb->transport_header = savesctp; if (!sk) { - ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_INERRORS); + __ICMP6_INC_STATS(net, idev, ICMP6_MIB_INERRORS); goto out; } -- GitLab From 98f619957ec2717fea09b398957e130e4bf4b30c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:37 -0700 Subject: [PATCH 4862/9938] net: rename IP_ADD_STATS_BH() Rename IP_ADD_STATS_BH() to __IP_ADD_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ip.h | 2 +- net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_input.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 0be0af3017ba..0df4809bc68a 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -189,7 +189,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) #define __IP_INC_STATS(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field) #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) -#define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val) +#define __IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val) #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) #define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val) #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 42fbd59b0ba8..cbfb1808fcc4 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -66,7 +66,7 @@ static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *s struct ip_options *opt = &(IPCB(skb)->opt); __IP_INC_STATS(net, IPSTATS_MIB_OUTFORWDATAGRAMS); - IP_ADD_STATS_BH(net, IPSTATS_MIB_OUTOCTETS, skb->len); + __IP_ADD_STATS(net, IPSTATS_MIB_OUTOCTETS, skb->len); if (unlikely(opt->optlen)) ip_forward_options(skb); diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index cca6729cd6ee..11f34e421270 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -439,9 +439,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, BUILD_BUG_ON(IPSTATS_MIB_ECT1PKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_ECT_1); BUILD_BUG_ON(IPSTATS_MIB_ECT0PKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_ECT_0); BUILD_BUG_ON(IPSTATS_MIB_CEPKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_CE); - IP_ADD_STATS_BH(net, - IPSTATS_MIB_NOECTPKTS + (iph->tos & INET_ECN_MASK), - max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs)); + __IP_ADD_STATS(net, + IPSTATS_MIB_NOECTPKTS + (iph->tos & INET_ECN_MASK), + max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs)); if (!pskb_may_pull(skb, iph->ihl*4)) goto inhdr_error; -- GitLab From b15084ec7d4c89000242d69b5f57b4d138bad1b9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:38 -0700 Subject: [PATCH 4863/9938] net: rename IP_UPD_PO_STATS_BH() Rename IP_UPD_PO_STATS_BH() to __IP_UPD_PO_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ip.h | 2 +- net/ipv4/ip_input.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 0df4809bc68a..55f5de50a564 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -191,7 +191,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) #define __IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val) #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) -#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val) +#define __IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val) #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) #define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field) #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 11f34e421270..8fda63d78435 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -358,9 +358,9 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) rt = skb_rtable(skb); if (rt->rt_type == RTN_MULTICAST) { - IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_INMCAST, skb->len); + __IP_UPD_PO_STATS(net, IPSTATS_MIB_INMCAST, skb->len); } else if (rt->rt_type == RTN_BROADCAST) { - IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_INBCAST, skb->len); + __IP_UPD_PO_STATS(net, IPSTATS_MIB_INBCAST, skb->len); } else if (skb->pkt_type == PACKET_BROADCAST || skb->pkt_type == PACKET_MULTICAST) { struct in_device *in_dev = __in_dev_get_rcu(skb->dev); @@ -409,7 +409,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, net = dev_net(dev); - IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_IN, skb->len); + __IP_UPD_PO_STATS(net, IPSTATS_MIB_IN, skb->len); skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) { -- GitLab From 02a1d6e7a6bb025a77da77012190e1efc1970f1c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:39 -0700 Subject: [PATCH 4864/9938] net: rename NET_{ADD|INC}_STATS_BH() Rename NET_INC_STATS_BH() to __NET_INC_STATS() and NET_ADD_STATS_BH() to __NET_ADD_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ip.h | 4 +- include/net/tcp.h | 4 +- net/core/dev.c | 4 +- net/dccp/ipv4.c | 10 ++-- net/dccp/ipv6.c | 8 +-- net/dccp/timer.c | 4 +- net/ipv4/arp.c | 2 +- net/ipv4/inet_hashtables.c | 2 +- net/ipv4/inet_timewait_sock.c | 4 +- net/ipv4/ip_input.c | 2 +- net/ipv4/syncookies.c | 4 +- net/ipv4/tcp.c | 4 +- net/ipv4/tcp_cdg.c | 20 +++---- net/ipv4/tcp_cubic.c | 20 +++---- net/ipv4/tcp_fastopen.c | 14 ++--- net/ipv4/tcp_input.c | 100 ++++++++++++++++++---------------- net/ipv4/tcp_ipv4.c | 22 ++++---- net/ipv4/tcp_minisocks.c | 10 ++-- net/ipv4/tcp_output.c | 14 ++--- net/ipv4/tcp_recovery.c | 4 +- net/ipv4/tcp_timer.c | 22 ++++---- net/ipv6/inet6_hashtables.c | 2 +- net/ipv6/syncookies.c | 4 +- net/ipv6/tcp_ipv6.c | 16 +++--- net/sctp/input.c | 2 +- 25 files changed, 153 insertions(+), 149 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 55f5de50a564..fb3b766ca1c7 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -193,9 +193,9 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) #define __IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val) #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) -#define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field) +#define __NET_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field) #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) -#define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd) +#define __NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd) u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offct); unsigned long snmp_fold_field(void __percpu *mib, int offt); diff --git a/include/net/tcp.h b/include/net/tcp.h index 939ebd5320a9..ff8b4265cb2b 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1743,7 +1743,7 @@ static inline __u32 cookie_init_sequence(const struct tcp_request_sock_ops *ops, __u16 *mss) { tcp_synq_overflow(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); return ops->cookie_init_seq(skb, mss); } #else @@ -1852,7 +1852,7 @@ static inline void tcp_segs_in(struct tcp_sock *tp, const struct sk_buff *skb) static inline void tcp_listendrop(const struct sock *sk) { atomic_inc(&((struct sock *)sk)->sk_drops); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENDROPS); } #endif /* _TCP_H */ diff --git a/net/core/dev.c b/net/core/dev.c index 6324bc9267f7..e96a3bc2c634 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4982,8 +4982,8 @@ bool sk_busy_loop(struct sock *sk, int nonblock) netpoll_poll_unlock(have); } if (rc > 0) - NET_ADD_STATS_BH(sock_net(sk), - LINUX_MIB_BUSYPOLLRXPACKETS, rc); + __NET_ADD_STATS(sock_net(sk), + LINUX_MIB_BUSYPOLLRXPACKETS, rc); local_bh_enable(); if (rc == LL_FLUSH_FAILED) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index a9c75e79ba99..a8164272e0f4 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -205,7 +205,7 @@ void dccp_req_err(struct sock *sk, u64 seq) * socket here. */ if (!between48(seq, dccp_rsk(req)->dreq_iss, dccp_rsk(req)->dreq_gss)) { - NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS); } else { /* * Still in RESPOND, just remove it silently. @@ -273,7 +273,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) * servers this needs to be solved differently. */ if (sock_owned_by_user(sk)) - NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); + __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS); if (sk->sk_state == DCCP_CLOSED) goto out; @@ -281,7 +281,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) dp = dccp_sk(sk); if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) && !between48(seq, dp->dccps_awl, dp->dccps_awh)) { - NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS); goto out; } @@ -431,11 +431,11 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, return newsk; exit_overflow: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); exit_nonewsk: dst_release(dst); exit: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: inet_csk_prepare_forced_close(newsk); diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 323c6b595e31..0f4eb4ea57a5 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -106,7 +106,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, bh_lock_sock(sk); if (sock_owned_by_user(sk)) - NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); + __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS); if (sk->sk_state == DCCP_CLOSED) goto out; @@ -114,7 +114,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, dp = dccp_sk(sk); if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) && !between48(seq, dp->dccps_awl, dp->dccps_awh)) { - NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS); goto out; } @@ -527,11 +527,11 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, return newsk; out_overflow: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); out_nonewsk: dst_release(dst); out: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; } diff --git a/net/dccp/timer.c b/net/dccp/timer.c index 4ff22c24ff14..3a2c34027758 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -179,7 +179,7 @@ static void dccp_delack_timer(unsigned long data) if (sock_owned_by_user(sk)) { /* Try again later. */ icsk->icsk_ack.blocked = 1; - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); sk_reset_timer(sk, &icsk->icsk_delack_timer, jiffies + TCP_DELACK_MIN); goto out; @@ -209,7 +209,7 @@ static void dccp_delack_timer(unsigned long data) icsk->icsk_ack.ato = TCP_ATO_MIN; } dccp_send_ack(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS); } out: bh_unlock_sock(sk); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index c34c7544d1db..89a8cac4726a 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -436,7 +436,7 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) if (IS_ERR(rt)) return 1; if (rt->dst.dev != dev) { - NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER); + __NET_INC_STATS(net, LINUX_MIB_ARPFILTER); flag = 1; } ip_rt_put(rt); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index b76b0d7e59c1..3177211ab651 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -360,7 +360,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, __sk_nulls_add_node_rcu(sk, &head->chain); if (tw) { sk_nulls_del_node_init_rcu((struct sock *)tw); - NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED); + __NET_INC_STATS(net, LINUX_MIB_TIMEWAITRECYCLED); } spin_unlock(lock); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index c67f9bd7699c..99ee5c4a9b68 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -147,9 +147,9 @@ static void tw_timer_handler(unsigned long data) struct inet_timewait_sock *tw = (struct inet_timewait_sock *)data; if (tw->tw_kill) - NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITKILLED); + __NET_INC_STATS(twsk_net(tw), LINUX_MIB_TIMEWAITKILLED); else - NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITED); + __NET_INC_STATS(twsk_net(tw), LINUX_MIB_TIMEWAITED); inet_twsk_kill(tw); } diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 8fda63d78435..751c0658e194 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -337,7 +337,7 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) iph->tos, skb->dev); if (unlikely(err)) { if (err == -EXDEV) - NET_INC_STATS_BH(net, LINUX_MIB_IPRPFILTER); + __NET_INC_STATS(net, LINUX_MIB_IPRPFILTER); goto drop; } } diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 4c04f09338e3..e3c4043c27de 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -312,11 +312,11 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) mss = __cookie_v4_check(ip_hdr(skb), th, cookie); if (mss == 0) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); goto out; } - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); /* check for timestamp cookie support */ memset(&tcp_opt, 0, sizeof(tcp_opt)); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 96833433c2c3..040f35e7efe0 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2148,7 +2148,7 @@ void tcp_close(struct sock *sk, long timeout) if (tp->linger2 < 0) { tcp_set_state(sk, TCP_CLOSE); tcp_send_active_reset(sk, GFP_ATOMIC); - NET_INC_STATS_BH(sock_net(sk), + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONLINGER); } else { const int tmo = tcp_fin_time(sk); @@ -2167,7 +2167,7 @@ void tcp_close(struct sock *sk, long timeout) if (tcp_check_oom(sk, 0)) { tcp_set_state(sk, TCP_CLOSE); tcp_send_active_reset(sk, GFP_ATOMIC); - NET_INC_STATS_BH(sock_net(sk), + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); } } diff --git a/net/ipv4/tcp_cdg.c b/net/ipv4/tcp_cdg.c index 167b6a3e1b98..3c00208c37f4 100644 --- a/net/ipv4/tcp_cdg.c +++ b/net/ipv4/tcp_cdg.c @@ -155,11 +155,11 @@ static void tcp_cdg_hystart_update(struct sock *sk) ca->last_ack = now_us; if (after(now_us, ca->round_start + base_owd)) { - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTTRAINDETECT); - NET_ADD_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTTRAINCWND, - tp->snd_cwnd); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTTRAINDETECT); + __NET_ADD_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTTRAINCWND, + tp->snd_cwnd); tp->snd_ssthresh = tp->snd_cwnd; return; } @@ -174,11 +174,11 @@ static void tcp_cdg_hystart_update(struct sock *sk) 125U); if (ca->rtt.min > thresh) { - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTDELAYDETECT); - NET_ADD_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTDELAYCWND, - tp->snd_cwnd); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTDELAYDETECT); + __NET_ADD_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTDELAYCWND, + tp->snd_cwnd); tp->snd_ssthresh = tp->snd_cwnd; } } diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 448c2615fece..59155af9de5d 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -402,11 +402,11 @@ static void hystart_update(struct sock *sk, u32 delay) ca->last_ack = now; if ((s32)(now - ca->round_start) > ca->delay_min >> 4) { ca->found |= HYSTART_ACK_TRAIN; - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTTRAINDETECT); - NET_ADD_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTTRAINCWND, - tp->snd_cwnd); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTTRAINDETECT); + __NET_ADD_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTTRAINCWND, + tp->snd_cwnd); tp->snd_ssthresh = tp->snd_cwnd; } } @@ -423,11 +423,11 @@ static void hystart_update(struct sock *sk, u32 delay) if (ca->curr_rtt > ca->delay_min + HYSTART_DELAY_THRESH(ca->delay_min >> 3)) { ca->found |= HYSTART_DELAY; - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTDELAYDETECT); - NET_ADD_STATS_BH(sock_net(sk), - LINUX_MIB_TCPHYSTARTDELAYCWND, - tp->snd_cwnd); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTDELAYDETECT); + __NET_ADD_STATS(sock_net(sk), + LINUX_MIB_TCPHYSTARTDELAYCWND, + tp->snd_cwnd); tp->snd_ssthresh = tp->snd_cwnd; } } diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index cffd8f9ed1a9..a1498d507e42 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -256,8 +256,8 @@ static bool tcp_fastopen_queue_check(struct sock *sk) req1 = fastopenq->rskq_rst_head; if (!req1 || time_after(req1->rsk_timer.expires, jiffies)) { spin_unlock(&fastopenq->lock); - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPFASTOPENLISTENOVERFLOW); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPFASTOPENLISTENOVERFLOW); return false; } fastopenq->rskq_rst_head = req1->dl_next; @@ -282,7 +282,7 @@ struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb, struct sock *child; if (foc->len == 0) /* Client requests a cookie */ - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENCOOKIEREQD); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENCOOKIEREQD); if (!((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) && (syn_data || foc->len >= 0) && @@ -311,13 +311,13 @@ struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb, child = tcp_fastopen_create_child(sk, skb, dst, req); if (child) { foc->len = -1; - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPFASTOPENPASSIVE); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPFASTOPENPASSIVE); return child; } - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL); } else if (foc->len > 0) /* Client presents an invalid cookie */ - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL); valid_foc.exp = foc->exp; *foc = valid_foc; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index dad8d93262ed..0d5239c283cb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -869,7 +869,7 @@ static void tcp_update_reordering(struct sock *sk, const int metric, else mib_idx = LINUX_MIB_TCPSACKREORDER; - NET_INC_STATS_BH(sock_net(sk), mib_idx); + __NET_INC_STATS(sock_net(sk), mib_idx); #if FASTRETRANS_DEBUG > 1 pr_debug("Disorder%d %d %u f%u s%u rr%d\n", tp->rx_opt.sack_ok, inet_csk(sk)->icsk_ca_state, @@ -1062,7 +1062,7 @@ static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb, if (before(start_seq_0, TCP_SKB_CB(ack_skb)->ack_seq)) { dup_sack = true; tcp_dsack_seen(tp); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKRECV); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKRECV); } else if (num_sacks > 1) { u32 end_seq_1 = get_unaligned_be32(&sp[1].end_seq); u32 start_seq_1 = get_unaligned_be32(&sp[1].start_seq); @@ -1071,7 +1071,7 @@ static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb, !before(start_seq_0, start_seq_1)) { dup_sack = true; tcp_dsack_seen(tp); - NET_INC_STATS_BH(sock_net(sk), + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKOFORECV); } } @@ -1289,7 +1289,7 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, if (skb->len > 0) { BUG_ON(!tcp_skb_pcount(skb)); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SACKSHIFTED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKSHIFTED); return false; } @@ -1313,7 +1313,7 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, tcp_unlink_write_queue(skb, sk); sk_wmem_free_skb(sk, skb); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SACKMERGED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKMERGED); return true; } @@ -1469,7 +1469,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, return skb; fallback: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SACKSHIFTFALLBACK); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKSHIFTFALLBACK); return NULL; } @@ -1657,7 +1657,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb, mib_idx = LINUX_MIB_TCPSACKDISCARD; } - NET_INC_STATS_BH(sock_net(sk), mib_idx); + __NET_INC_STATS(sock_net(sk), mib_idx); if (i == 0) first_sack_index = -1; continue; @@ -1909,7 +1909,7 @@ void tcp_enter_loss(struct sock *sk) skb = tcp_write_queue_head(sk); is_reneg = skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED); if (is_reneg) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSACKRENEGING); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSACKRENEGING); tp->sacked_out = 0; tp->fackets_out = 0; } @@ -2395,7 +2395,7 @@ static bool tcp_try_undo_recovery(struct sock *sk) else mib_idx = LINUX_MIB_TCPFULLUNDO; - NET_INC_STATS_BH(sock_net(sk), mib_idx); + __NET_INC_STATS(sock_net(sk), mib_idx); } if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) { /* Hold old state until something *above* high_seq @@ -2417,7 +2417,7 @@ static bool tcp_try_undo_dsack(struct sock *sk) if (tp->undo_marker && !tp->undo_retrans) { DBGUNDO(sk, "D-SACK"); tcp_undo_cwnd_reduction(sk, false); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKUNDO); return true; } return false; @@ -2432,10 +2432,10 @@ static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo) tcp_undo_cwnd_reduction(sk, true); DBGUNDO(sk, "partial loss"); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPLOSSUNDO); if (frto_undo) - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPSPURIOUSRTOS); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPSPURIOUSRTOS); inet_csk(sk)->icsk_retransmits = 0; if (frto_undo || tcp_is_sack(tp)) tcp_set_ca_state(sk, TCP_CA_Open); @@ -2559,7 +2559,7 @@ static void tcp_mtup_probe_failed(struct sock *sk) icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1; icsk->icsk_mtup.probe_size = 0; - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMTUPFAIL); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMTUPFAIL); } static void tcp_mtup_probe_success(struct sock *sk) @@ -2579,7 +2579,7 @@ static void tcp_mtup_probe_success(struct sock *sk) icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size; icsk->icsk_mtup.probe_size = 0; tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMTUPSUCCESS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMTUPSUCCESS); } /* Do a simple retransmit without using the backoff mechanisms in @@ -2643,7 +2643,7 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) else mib_idx = LINUX_MIB_TCPSACKRECOVERY; - NET_INC_STATS_BH(sock_net(sk), mib_idx); + __NET_INC_STATS(sock_net(sk), mib_idx); tp->prior_ssthresh = 0; tcp_init_undo(tp); @@ -2736,7 +2736,7 @@ static bool tcp_try_undo_partial(struct sock *sk, const int acked) DBGUNDO(sk, "partial recovery"); tcp_undo_cwnd_reduction(sk, true); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); tcp_try_keep_open(sk); return true; } @@ -3431,7 +3431,7 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb, s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time); if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) { - NET_INC_STATS_BH(net, mib_idx); + __NET_INC_STATS(net, mib_idx); return true; /* rate-limited: don't send yet! */ } } @@ -3464,7 +3464,7 @@ static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) challenge_count = 0; } if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); tcp_send_ack(sk); } } @@ -3513,8 +3513,8 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) tcp_set_ca_state(sk, TCP_CA_CWR); tcp_end_cwnd_reduction(sk); tcp_try_keep_open(sk); - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPLOSSPROBERECOVERY); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPLOSSPROBERECOVERY); } else if (!(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP | FLAG_DATA_SACKED))) { /* Pure dupack: original and TLP probe arrived; no loss */ @@ -3618,14 +3618,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPACKS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPACKS); } else { u32 ack_ev_flags = CA_ACK_SLOWPATH; if (ack_seq != TCP_SKB_CB(skb)->end_seq) flag |= FLAG_DATA; else - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPUREACKS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPUREACKS); flag |= tcp_ack_update_window(sk, skb, ack, ack_seq); @@ -4128,7 +4128,7 @@ static void tcp_dsack_set(struct sock *sk, u32 seq, u32 end_seq) else mib_idx = LINUX_MIB_TCPDSACKOFOSENT; - NET_INC_STATS_BH(sock_net(sk), mib_idx); + __NET_INC_STATS(sock_net(sk), mib_idx); tp->rx_opt.dsack = 1; tp->duplicate_sack[0].start_seq = seq; @@ -4152,7 +4152,7 @@ static void tcp_send_dupack(struct sock *sk, const struct sk_buff *skb) if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOST); tcp_enter_quickack_mode(sk); if (tcp_is_sack(tp) && sysctl_tcp_dsack) { @@ -4302,7 +4302,7 @@ static bool tcp_try_coalesce(struct sock *sk, atomic_add(delta, &sk->sk_rmem_alloc); sk_mem_charge(sk, delta); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOALESCE); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRCVCOALESCE); TCP_SKB_CB(to)->end_seq = TCP_SKB_CB(from)->end_seq; TCP_SKB_CB(to)->ack_seq = TCP_SKB_CB(from)->ack_seq; TCP_SKB_CB(to)->tcp_flags |= TCP_SKB_CB(from)->tcp_flags; @@ -4390,7 +4390,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) tcp_ecn_check_ce(tp, skb); if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFODROP); tcp_drop(sk, skb); return; } @@ -4399,7 +4399,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) tp->pred_flags = 0; inet_csk_schedule_ack(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOQUEUE); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOQUEUE); SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n", tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); @@ -4454,7 +4454,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) if (skb1 && before(seq, TCP_SKB_CB(skb1)->end_seq)) { if (!after(end_seq, TCP_SKB_CB(skb1)->end_seq)) { /* All the bits are present. Drop. */ - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOMERGE); tcp_drop(sk, skb); skb = NULL; tcp_dsack_set(sk, seq, end_seq); @@ -4493,7 +4493,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) __skb_unlink(skb1, &tp->out_of_order_queue); tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq, TCP_SKB_CB(skb1)->end_seq); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOMERGE); tcp_drop(sk, skb1); } @@ -4658,7 +4658,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) { /* A retransmit, 2nd most common case. Force an immediate ack. */ - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOST); tcp_dsack_set(sk, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); out_of_window: @@ -4704,7 +4704,7 @@ static struct sk_buff *tcp_collapse_one(struct sock *sk, struct sk_buff *skb, __skb_unlink(skb, list); __kfree_skb(skb); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOLLAPSED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRCVCOLLAPSED); return next; } @@ -4863,7 +4863,7 @@ static bool tcp_prune_ofo_queue(struct sock *sk) bool res = false; if (!skb_queue_empty(&tp->out_of_order_queue)) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_OFOPRUNED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_OFOPRUNED); __skb_queue_purge(&tp->out_of_order_queue); /* Reset SACK state. A conforming SACK implementation will @@ -4892,7 +4892,7 @@ static int tcp_prune_queue(struct sock *sk) SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PRUNECALLED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_PRUNECALLED); if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) tcp_clamp_window(sk); @@ -4922,7 +4922,7 @@ static int tcp_prune_queue(struct sock *sk) * drop receive data on the floor. It will get retransmitted * and hopefully then we'll have sufficient space. */ - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_RCVPRUNED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_RCVPRUNED); /* Massive buffer overcommit. */ tp->pred_flags = 0; @@ -5181,7 +5181,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && tcp_paws_discard(sk, skb)) { if (!th->rst) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); if (!tcp_oow_rate_limited(sock_net(sk), skb, LINUX_MIB_TCPACKSKIPPEDPAWS, &tp->last_oow_ack_time)) @@ -5234,7 +5234,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, syn_challenge: if (syn_inerr) __TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); tcp_send_challenge_ack(sk, skb); goto discard; } @@ -5377,7 +5377,8 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, __skb_pull(skb, tcp_header_len); tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITSTOUSER); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPHPHITSTOUSER); eaten = 1; } } @@ -5399,7 +5400,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, tcp_rcv_rtt_measure_ts(sk, skb); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPHITS); /* Bulk data transfer: receiver */ eaten = tcp_queue_rcv(sk, skb, tcp_header_len, @@ -5549,12 +5550,14 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, break; } tcp_rearm_rto(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVEFAIL); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPFASTOPENACTIVEFAIL); return true; } tp->syn_data_acked = tp->syn_data; if (tp->syn_data_acked) - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPFASTOPENACTIVE); tcp_fastopen_add_skb(sk, synack); @@ -5589,7 +5592,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && !between(tp->rx_opt.rcv_tsecr, tp->retrans_stamp, tcp_time_stamp)) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSACTIVEREJECTED); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_PAWSACTIVEREJECTED); goto reset_and_undo; } @@ -5958,7 +5962,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) { tcp_done(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA); return 1; } @@ -6015,7 +6019,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) if (sk->sk_shutdown & RCV_SHUTDOWN) { if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA); tcp_reset(sk); return 1; } @@ -6153,10 +6157,10 @@ static bool tcp_syn_flood_action(const struct sock *sk, if (net->ipv4.sysctl_tcp_syncookies) { msg = "Sending cookies"; want_cookie = true; - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES); } else #endif - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP); if (!queue->synflood_warned && net->ipv4.sysctl_tcp_syncookies != 2 && @@ -6217,7 +6221,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, * timeout. */ if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); goto drop; } @@ -6264,7 +6268,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, if (dst && strict && !tcp_peer_is_proven(req, dst, true, tmp_opt.saw_tstamp)) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); goto drop_and_release; } } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 378e92d41c6c..510f7a3c758b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -320,7 +320,7 @@ void tcp_req_err(struct sock *sk, u32 seq, bool abort) * an established socket here. */ if (seq != tcp_rsk(req)->snt_isn) { - NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS); } else if (abort) { /* * Still in SYN_RECV, just remove it silently. @@ -396,13 +396,13 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) */ if (sock_owned_by_user(sk)) { if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)) - NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); + __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS); } if (sk->sk_state == TCP_CLOSE) goto out; if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { - NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); goto out; } @@ -413,7 +413,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una; if (sk->sk_state != TCP_LISTEN && !between(seq, snd_una, tp->snd_nxt)) { - NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS); goto out; } @@ -1151,12 +1151,12 @@ static bool tcp_v4_inbound_md5_hash(const struct sock *sk, return false; if (hash_expected && !hash_location) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); return true; } if (!hash_expected && hash_location) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); return true; } @@ -1342,7 +1342,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, return newsk; exit_overflow: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); exit_nonewsk: dst_release(dst); exit: @@ -1513,8 +1513,8 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) { sk_backlog_rcv(sk, skb1); - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPPREQUEUEDROPPED); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPPREQUEUEDROPPED); } tp->ucopy.memory = 0; @@ -1629,7 +1629,7 @@ int tcp_v4_rcv(struct sk_buff *skb) } } if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { - NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); goto discard_and_relse; } @@ -1662,7 +1662,7 @@ int tcp_v4_rcv(struct sk_buff *skb) } else if (unlikely(sk_add_backlog(sk, skb, sk->sk_rcvbuf + sk->sk_sndbuf))) { bh_unlock_sock(sk); - NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); + __NET_INC_STATS(net, LINUX_MIB_TCPBACKLOGDROP); goto discard_and_relse; } bh_unlock_sock(sk); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0be6bfeab553..ffbfecdae471 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -235,7 +235,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, } if (paws_reject) - NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_PAWSESTABREJECTED); + __NET_INC_STATS(twsk_net(tw), LINUX_MIB_PAWSESTABREJECTED); if (!th->rst) { /* In this case we must reset the TIMEWAIT timer. @@ -337,7 +337,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) * socket up. We've got bigger problems than * non-graceful socket closings. */ - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW); } tcp_update_metrics(sk); @@ -710,7 +710,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, &tcp_rsk(req)->last_oow_ack_time)) req->rsk_ops->send_ack(sk, skb, req); if (paws_reject) - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); return NULL; } @@ -752,7 +752,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, if (req->num_timeout < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { inet_rsk(req)->acked = 1; - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP); return NULL; } @@ -791,7 +791,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, } if (!fastopen) { inet_csk_reqsk_queue_drop(sk, req); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); } return NULL; } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index c48baf734e8c..b1b2045ac3a9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2212,8 +2212,8 @@ static bool skb_still_in_host_queue(const struct sock *sk, const struct sk_buff *skb) { if (unlikely(skb_fclone_busy(sk, skb))) { - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); return true; } return false; @@ -2275,7 +2275,7 @@ void tcp_send_loss_probe(struct sock *sk) tp->tlp_high_seq = tp->snd_nxt; probe_sent: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSPROBES); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPLOSSPROBES); /* Reset s.t. tcp_rearm_rto will restart timer from now */ inet_csk(sk)->icsk_pending = 0; rearm_timer: @@ -2656,7 +2656,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) /* Update global TCP statistics. */ TCP_ADD_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS, segs); if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN) - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); tp->total_retrans += segs; } return err; @@ -2681,7 +2681,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) tp->retrans_stamp = tcp_skb_timestamp(skb); } else if (err != -EBUSY) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL); } if (tp->undo_retrans < 0) @@ -2805,7 +2805,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk) if (tcp_retransmit_skb(sk, skb, segs)) return; - NET_INC_STATS_BH(sock_net(sk), mib_idx); + __NET_INC_STATS(sock_net(sk), mib_idx); if (tcp_in_cwnd_reduction(sk)) tp->prr_out += tcp_skb_pcount(skb); @@ -3541,7 +3541,7 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req) res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL); if (!res) { __TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); } return res; } diff --git a/net/ipv4/tcp_recovery.c b/net/ipv4/tcp_recovery.c index 5353085fd0b2..e0d0afaf15be 100644 --- a/net/ipv4/tcp_recovery.c +++ b/net/ipv4/tcp_recovery.c @@ -65,8 +65,8 @@ int tcp_rack_mark_lost(struct sock *sk) if (scb->sacked & TCPCB_SACKED_RETRANS) { scb->sacked &= ~TCPCB_SACKED_RETRANS; tp->retrans_out -= tcp_skb_pcount(skb); - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPLOSTRETRANSMIT); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPLOSTRETRANSMIT); } } else if (!(scb->sacked & TCPCB_RETRANS)) { /* Original data are sent sequentially so stop early diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 373b03e78aaa..35f643d8ffbb 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -30,7 +30,7 @@ static void tcp_write_err(struct sock *sk) sk->sk_error_report(sk); tcp_done(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONTIMEOUT); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONTIMEOUT); } /* Do not allow orphaned sockets to eat all our resources. @@ -68,7 +68,7 @@ static int tcp_out_of_resources(struct sock *sk, bool do_reset) if (do_reset) tcp_send_active_reset(sk, GFP_ATOMIC); tcp_done(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); return 1; } return 0; @@ -162,8 +162,8 @@ static int tcp_write_timeout(struct sock *sk) if (tp->syn_fastopen || tp->syn_data) tcp_fastopen_cache_set(sk, 0, NULL, true, 0); if (tp->syn_data && icsk->icsk_retransmits == 1) - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPFASTOPENACTIVEFAIL); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPFASTOPENACTIVEFAIL); } retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; syn_set = true; @@ -178,8 +178,8 @@ static int tcp_write_timeout(struct sock *sk) tp->bytes_acked <= tp->rx_opt.mss_clamp) { tcp_fastopen_cache_set(sk, 0, NULL, true, 0); if (icsk->icsk_retransmits == net->ipv4.sysctl_tcp_retries1) - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPFASTOPENACTIVEFAIL); + __NET_INC_STATS(sock_net(sk), + LINUX_MIB_TCPFASTOPENACTIVEFAIL); } /* Black hole detection */ tcp_mtu_probing(icsk, sk); @@ -228,7 +228,7 @@ void tcp_delack_timer_handler(struct sock *sk) if (!skb_queue_empty(&tp->ucopy.prequeue)) { struct sk_buff *skb; - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSCHEDULERFAILED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSCHEDULERFAILED); while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) sk_backlog_rcv(sk, skb); @@ -248,7 +248,7 @@ void tcp_delack_timer_handler(struct sock *sk) icsk->icsk_ack.ato = TCP_ATO_MIN; } tcp_send_ack(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS); } out: @@ -265,7 +265,7 @@ static void tcp_delack_timer(unsigned long data) tcp_delack_timer_handler(sk); } else { inet_csk(sk)->icsk_ack.blocked = 1; - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); /* deleguate our work to tcp_release_cb() */ if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) sock_hold(sk); @@ -431,7 +431,7 @@ void tcp_retransmit_timer(struct sock *sk) } else { mib_idx = LINUX_MIB_TCPTIMEOUTS; } - NET_INC_STATS_BH(sock_net(sk), mib_idx); + __NET_INC_STATS(sock_net(sk), mib_idx); } tcp_enter_loss(sk); @@ -549,7 +549,7 @@ void tcp_syn_ack_timeout(const struct request_sock *req) { struct net *net = read_pnet(&inet_rsk(req)->ireq_net); - NET_INC_STATS_BH(net, LINUX_MIB_TCPTIMEOUTS); + __NET_INC_STATS(net, LINUX_MIB_TCPTIMEOUTS); } EXPORT_SYMBOL(tcp_syn_ack_timeout); diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index f1678388fb0d..00cf28ad4565 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -222,7 +222,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, __sk_nulls_add_node_rcu(sk, &head->chain); if (tw) { sk_nulls_del_node_init_rcu((struct sock *)tw); - NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED); + __NET_INC_STATS(net, LINUX_MIB_TIMEWAITRECYCLED); } spin_unlock(lock); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index aab91fa86c5e..59c483937aec 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -155,11 +155,11 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) mss = __cookie_v6_check(ipv6_hdr(skb), th, cookie); if (mss == 0) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); goto out; } - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); /* check for timestamp cookie support */ memset(&tcp_opt, 0, sizeof(tcp_opt)); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 78c45c027acc..52914714b923 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -352,13 +352,13 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, bh_lock_sock(sk); if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG) - NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); + __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS); if (sk->sk_state == TCP_CLOSE) goto out; if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) { - NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); goto out; } @@ -368,7 +368,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una; if (sk->sk_state != TCP_LISTEN && !between(seq, snd_una, tp->snd_nxt)) { - NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); + __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS); goto out; } @@ -649,12 +649,12 @@ static bool tcp_v6_inbound_md5_hash(const struct sock *sk, return false; if (hash_expected && !hash_location) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); return true; } if (!hash_expected && hash_location) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); return true; } @@ -1165,7 +1165,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * return newsk; out_overflow: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); + __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); out_nonewsk: dst_release(dst); out: @@ -1421,7 +1421,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) } } if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) { - NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); goto discard_and_relse; } @@ -1454,7 +1454,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) } else if (unlikely(sk_add_backlog(sk, skb, sk->sk_rcvbuf + sk->sk_sndbuf))) { bh_unlock_sock(sk); - NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); + __NET_INC_STATS(net, LINUX_MIB_TCPBACKLOGDROP); goto discard_and_relse; } bh_unlock_sock(sk); diff --git a/net/sctp/input.c b/net/sctp/input.c index 12332fc3eb44..a701527a9480 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -532,7 +532,7 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, * servers this needs to be solved differently. */ if (sock_owned_by_user(sk)) - NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); + __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS); *app = asoc; *tpp = transport; -- GitLab From 1d0155035918aa44e634941ac05721536b461d7c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:40 -0700 Subject: [PATCH 4865/9938] ipv6: rename IP6_INC_STATS_BH() Rename IP6_INC_STATS_BH() to __IP6_INC_STATS() and IP6_ADD_STATS_BH() to __IP6_ADD_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ipv6.h | 4 +-- net/bridge/br_netfilter_ipv6.c | 10 +++--- net/ipv6/exthdrs.c | 66 +++++++++++++++++----------------- net/ipv6/ip6_input.c | 28 +++++++-------- net/ipv6/ip6_output.c | 34 +++++++++--------- net/ipv6/ip6mr.c | 8 ++--- net/ipv6/reassembly.c | 32 ++++++++--------- 7 files changed, 91 insertions(+), 91 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index a620fc56e2f5..aba8760dd108 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -167,11 +167,11 @@ extern int sysctl_mld_qrv; #define IP6_INC_STATS(net, idev,field) \ _DEVINC(net, ipv6, 64, idev, field) -#define IP6_INC_STATS_BH(net, idev,field) \ +#define __IP6_INC_STATS(net, idev,field) \ _DEVINC(net, ipv6, 64_BH, idev, field) #define IP6_ADD_STATS(net, idev,field,val) \ _DEVADD(net, ipv6, 64, idev, field, val) -#define IP6_ADD_STATS_BH(net, idev,field,val) \ +#define __IP6_ADD_STATS(net, idev,field,val) \ _DEVADD(net, ipv6, 64_BH, idev, field, val) #define IP6_UPD_PO_STATS(net, idev,field,val) \ _DEVUPD(net, ipv6, 64, idev, field, val) diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c index d61f56efc8dc..5e59a8457e7b 100644 --- a/net/bridge/br_netfilter_ipv6.c +++ b/net/bridge/br_netfilter_ipv6.c @@ -122,13 +122,13 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb) if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len + ip6h_len > skb->len) { - IP6_INC_STATS_BH(net, idev, - IPSTATS_MIB_INTRUNCATEDPKTS); + __IP6_INC_STATS(net, idev, + IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } if (pskb_trim_rcsum(skb, pkt_len + ip6h_len)) { - IP6_INC_STATS_BH(net, idev, - IPSTATS_MIB_INDISCARDS); + __IP6_INC_STATS(net, idev, + IPSTATS_MIB_INDISCARDS); goto drop; } } @@ -142,7 +142,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb) return 0; inhdr_error: - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); drop: return -1; } diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index ea7c4d64a00a..8de5dd7aaa05 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -258,8 +258,8 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || !pskb_may_pull(skb, (skb_transport_offset(skb) + ((skb_transport_header(skb)[1] + 1) << 3)))) { - IP6_INC_STATS_BH(dev_net(dst->dev), ip6_dst_idev(dst), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } @@ -280,8 +280,8 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) return 1; } - IP6_INC_STATS_BH(dev_net(dst->dev), - ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(dev_net(dst->dev), + ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); return -1; } @@ -309,8 +309,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || !pskb_may_pull(skb, (skb_transport_offset(skb) + ((skb_transport_header(skb)[1] + 1) << 3)))) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } @@ -319,8 +319,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || skb->pkt_type != PACKET_HOST) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INADDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -334,8 +334,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) * processed by own */ if (!addr) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INADDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -360,8 +360,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) goto unknown_rh; /* Silently discard invalid RTH type 2 */ if (hdr->hdrlen != 2 || hdr->segments_left != 1) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } @@ -379,8 +379,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) n = hdr->hdrlen >> 1; if (hdr->segments_left > n) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, ((&hdr->segments_left) - skb_network_header(skb))); @@ -393,8 +393,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (skb_cloned(skb)) { /* the copy is a forwarded packet */ if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_OUTDISCARDS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); return -1; } @@ -416,14 +416,14 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, (xfrm_address_t *)&ipv6_hdr(skb)->saddr, IPPROTO_ROUTING) < 0) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INADDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INADDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -434,8 +434,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) } if (ipv6_addr_is_multicast(addr)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INADDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -454,8 +454,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) { if (ipv6_hdr(skb)->hop_limit <= 1) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INHDRERRORS); icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0); kfree_skb(skb); @@ -470,7 +470,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) return -1; unknown_rh: - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb_network_header(skb)); return -1; @@ -568,28 +568,28 @@ static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff) if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { net_dbg_ratelimited("ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", nh[optoff+1]); - IP6_INC_STATS_BH(net, ipv6_skb_idev(skb), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ipv6_skb_idev(skb), + IPSTATS_MIB_INHDRERRORS); goto drop; } pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); if (pkt_len <= IPV6_MAXPLEN) { - IP6_INC_STATS_BH(net, ipv6_skb_idev(skb), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ipv6_skb_idev(skb), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); return false; } if (ipv6_hdr(skb)->payload_len) { - IP6_INC_STATS_BH(net, ipv6_skb_idev(skb), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ipv6_skb_idev(skb), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); return false; } if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { - IP6_INC_STATS_BH(net, ipv6_skb_idev(skb), - IPSTATS_MIB_INTRUNCATEDPKTS); + __IP6_INC_STATS(net, ipv6_skb_idev(skb), + IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index c05c425c2389..218bb906c620 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -82,7 +82,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || !idev || unlikely(idev->cnf.disable_ipv6)) { - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS); goto drop; } @@ -109,10 +109,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (hdr->version != 6) goto err; - IP6_ADD_STATS_BH(net, idev, - IPSTATS_MIB_NOECTPKTS + + __IP6_ADD_STATS(net, idev, + IPSTATS_MIB_NOECTPKTS + (ipv6_get_dsfield(hdr) & INET_ECN_MASK), - max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs)); + max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs)); /* * RFC4291 2.5.3 * A packet received on an interface with a destination address @@ -169,12 +169,12 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt /* pkt_len may be zero if Jumbo payload option is present */ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len + sizeof(struct ipv6hdr) > skb->len) { - IP6_INC_STATS_BH(net, - idev, IPSTATS_MIB_INTRUNCATEDPKTS); + __IP6_INC_STATS(net, + idev, IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); goto drop; } hdr = ipv6_hdr(skb); @@ -182,7 +182,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (hdr->nexthdr == NEXTHDR_HOP) { if (ipv6_parse_hopopts(skb) < 0) { - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); rcu_read_unlock(); return NET_RX_DROP; } @@ -197,7 +197,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt net, NULL, skb, dev, NULL, ip6_rcv_finish); err: - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); drop: rcu_read_unlock(); kfree_skb(skb); @@ -259,18 +259,18 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk if (ret > 0) goto resubmit; else if (ret == 0) - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS); } else { if (!raw) { if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { - IP6_INC_STATS_BH(net, idev, - IPSTATS_MIB_INUNKNOWNPROTOS); + __IP6_INC_STATS(net, idev, + IPSTATS_MIB_INUNKNOWNPROTOS); icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_UNK_NEXTHDR, nhoff); } kfree_skb(skb); } else { - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS); consume_skb(skb); } } @@ -278,7 +278,7 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk return 0; discard: - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS); rcu_read_unlock(); kfree_skb(skb); return 0; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 171518e3ca21..2b3ffc582d16 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -395,8 +395,8 @@ int ip6_forward(struct sk_buff *skb) goto drop; if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), - IPSTATS_MIB_INDISCARDS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), + IPSTATS_MIB_INDISCARDS); goto drop; } @@ -427,8 +427,8 @@ int ip6_forward(struct sk_buff *skb) /* Force OUTPUT device used as source address */ skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0); - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -ETIMEDOUT; @@ -441,15 +441,15 @@ int ip6_forward(struct sk_buff *skb) if (proxied > 0) return ip6_input(skb); else if (proxied < 0) { - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), - IPSTATS_MIB_INDISCARDS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), + IPSTATS_MIB_INDISCARDS); goto drop; } } if (!xfrm6_route_forward(skb)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), - IPSTATS_MIB_INDISCARDS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), + IPSTATS_MIB_INDISCARDS); goto drop; } dst = skb_dst(skb); @@ -505,17 +505,17 @@ int ip6_forward(struct sk_buff *skb) /* Again, force OUTPUT device used as source address */ skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), - IPSTATS_MIB_INTOOBIGERRORS); - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), - IPSTATS_MIB_FRAGFAILS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), + IPSTATS_MIB_INTOOBIGERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), + IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; } if (skb_cow(skb, dst->dev->hard_header_len)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), - IPSTATS_MIB_OUTDISCARDS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), + IPSTATS_MIB_OUTDISCARDS); goto drop; } @@ -525,14 +525,14 @@ int ip6_forward(struct sk_buff *skb) hdr->hop_limit--; - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); - IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); + __IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); + __IP6_ADD_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, net, NULL, skb, skb->dev, dst->dev, ip6_forward_finish); error: - IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); drop: kfree_skb(skb); return -EINVAL; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index bf678324fd52..f2e2013f8346 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1984,10 +1984,10 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_OUTFORWDATAGRAMS); - IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_OUTOCTETS, skb->len); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_OUTFORWDATAGRAMS); + __IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_OUTOCTETS, skb->len); return dst_output(net, sk, skb); } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index e2ea31175ef9..2160d5d009cb 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -145,12 +145,12 @@ void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, if (!dev) goto out_rcu_unlock; - IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); if (inet_frag_evicting(&fq->q)) goto out_rcu_unlock; - IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); + __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); /* Don't send error if the first segment did not arrive. */ if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !fq->q.fragments) @@ -223,8 +223,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); if ((unsigned int)end > IPV6_MAXPLEN) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, ((u8 *)&fhdr->frag_off - skb_network_header(skb))); @@ -258,8 +258,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, /* RFC2460 says always send parameter problem in * this case. -DaveM */ - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, offsetof(struct ipv6hdr, payload_len)); return -1; @@ -361,8 +361,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, discard_fq: inet_frag_kill(&fq->q, &ip6_frags); err: - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_REASMFAILS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_REASMFAILS); kfree_skb(skb); return -1; } @@ -500,7 +500,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, skb_network_header_len(head)); rcu_read_lock(); - IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); + __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); rcu_read_unlock(); fq->q.fragments = NULL; fq->q.fragments_tail = NULL; @@ -513,7 +513,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, net_dbg_ratelimited("ip6_frag_reasm: no memory for reassembly\n"); out_fail: rcu_read_lock(); - IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); rcu_read_unlock(); return -1; } @@ -528,7 +528,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED) goto fail_hdr; - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); /* Jumbo payload inhibits frag. header */ if (hdr->payload_len == 0) @@ -544,8 +544,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb) if (!(fhdr->frag_off & htons(0xFFF9))) { /* It is not a fragmented frame */ skb->transport_header += sizeof(struct frag_hdr); - IP6_INC_STATS_BH(net, - ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS); + __IP6_INC_STATS(net, + ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS); IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb); IP6CB(skb)->flags |= IP6SKB_FRAGMENTED; @@ -566,13 +566,13 @@ static int ipv6_frag_rcv(struct sk_buff *skb) return ret; } - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMFAILS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMFAILS); kfree_skb(skb); return -1; fail_hdr: - IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_INHDRERRORS); + __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb)); return -1; } -- GitLab From c2005eb01044e82498209ee4ee43be604da3ef2a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:41 -0700 Subject: [PATCH 4866/9938] ipv6: rename IP6_UPD_PO_STATS_BH() Rename IP6_UPD_PO_STATS_BH() to __IP6_UPD_PO_STATS() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ipv6.h | 2 +- net/ipv6/ip6_input.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index aba8760dd108..9f3b53f2819b 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -175,7 +175,7 @@ extern int sysctl_mld_qrv; _DEVADD(net, ipv6, 64_BH, idev, field, val) #define IP6_UPD_PO_STATS(net, idev,field,val) \ _DEVUPD(net, ipv6, 64, idev, field, val) -#define IP6_UPD_PO_STATS_BH(net, idev,field,val) \ +#define __IP6_UPD_PO_STATS(net, idev,field,val) \ _DEVUPD(net, ipv6, 64_BH, idev, field, val) #define ICMP6_INC_STATS(net, idev, field) \ _DEVINCATOMIC(net, icmpv6, , idev, field) diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 218bb906c620..6ed56012005d 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -78,7 +78,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt idev = __in6_dev_get(skb->dev); - IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len); + __IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_IN, skb->len); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || !idev || unlikely(idev->cnf.disable_ipv6)) { @@ -297,7 +297,7 @@ int ip6_mc_input(struct sk_buff *skb) const struct ipv6hdr *hdr; bool deliver; - IP6_UPD_PO_STATS_BH(dev_net(skb_dst(skb)->dev), + __IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INMCAST, skb->len); -- GitLab From f3832ed2c27e7ad13300791db4089a7d4304f500 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:42 -0700 Subject: [PATCH 4867/9938] ipv6: kill ICMP6MSGIN_INC_STATS_BH() IPv6 ICMP stats are atomics anyway. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/ipv6.h | 4 +--- net/ipv6/icmp.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 9f3b53f2819b..64ce3670d40a 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -184,9 +184,7 @@ extern int sysctl_mld_qrv; #define ICMP6MSGOUT_INC_STATS(net, idev, field) \ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256) -#define ICMP6MSGOUT_INC_STATS_BH(net, idev, field) \ - _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256) -#define ICMP6MSGIN_INC_STATS_BH(net, idev, field) \ +#define ICMP6MSGIN_INC_STATS(net, idev, field) \ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field) struct ip6_ra_chain { diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 823a1fc576e3..23b9a4cc418e 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -728,7 +728,7 @@ static int icmpv6_rcv(struct sk_buff *skb) type = hdr->icmp6_type; - ICMP6MSGIN_INC_STATS_BH(dev_net(dev), idev, type); + ICMP6MSGIN_INC_STATS(dev_net(dev), idev, type); switch (type) { case ICMPV6_ECHO_REQUEST: -- GitLab From 13415e46c5915e2dac089de516369005fbc045f9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 27 Apr 2016 16:44:43 -0700 Subject: [PATCH 4868/9938] net: snmp: kill STATS_BH macros There is nothing related to BH in SNMP counters anymore, since linux-3.0. Rename helpers to use __ prefix instead of _BH prefix, for contexts where preemption is disabled. This more closely matches convention used to update percpu variables. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/icmp.h | 2 +- include/net/ip.h | 10 +++++----- include/net/ipv6.h | 36 ++++++++++++++++++------------------ include/net/sctp/sctp.h | 6 +++--- include/net/snmp.h | 24 ++++++++++++------------ include/net/tcp.h | 2 +- include/net/udp.h | 8 ++++---- net/dccp/dccp.h | 2 +- 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/include/net/icmp.h b/include/net/icmp.h index 25edb740c648..3ef2743a8eec 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -30,7 +30,7 @@ struct icmp_err { extern const struct icmp_err icmp_err_convert[]; #define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field) -#define __ICMP_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field) +#define __ICMP_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.icmp_statistics, field) #define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256) #define ICMPMSGIN_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field) diff --git a/include/net/ip.h b/include/net/ip.h index fb3b766ca1c7..247ac82e9cf2 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -187,15 +187,15 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, unsigned int len); #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) -#define __IP_INC_STATS(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field) +#define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) -#define __IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val) +#define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) -#define __IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val) +#define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) -#define __NET_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field) +#define __NET_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.net_statistics, field) #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) -#define __NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd) +#define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offct); unsigned long snmp_fold_field(void __percpu *mib, int offt); diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 64ce3670d40a..415213da5be3 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -121,21 +121,21 @@ struct frag_hdr { extern int sysctl_mld_max_msf; extern int sysctl_mld_qrv; -#define _DEVINC(net, statname, modifier, idev, field) \ +#define _DEVINC(net, statname, mod, idev, field) \ ({ \ struct inet6_dev *_idev = (idev); \ if (likely(_idev != NULL)) \ - SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \ - SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\ + mod##SNMP_INC_STATS64((_idev)->stats.statname, (field));\ + mod##SNMP_INC_STATS64((net)->mib.statname##_statistics, (field));\ }) /* per device counters are atomic_long_t */ -#define _DEVINCATOMIC(net, statname, modifier, idev, field) \ +#define _DEVINCATOMIC(net, statname, mod, idev, field) \ ({ \ struct inet6_dev *_idev = (idev); \ if (likely(_idev != NULL)) \ SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \ - SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\ + mod##SNMP_INC_STATS((net)->mib.statname##_statistics, (field));\ }) /* per device and per net counters are atomic_long_t */ @@ -147,40 +147,40 @@ extern int sysctl_mld_qrv; SNMP_INC_STATS_ATOMIC_LONG((net)->mib.statname##_statistics, (field));\ }) -#define _DEVADD(net, statname, modifier, idev, field, val) \ +#define _DEVADD(net, statname, mod, idev, field, val) \ ({ \ struct inet6_dev *_idev = (idev); \ if (likely(_idev != NULL)) \ - SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \ - SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\ + mod##SNMP_ADD_STATS((_idev)->stats.statname, (field), (val)); \ + mod##SNMP_ADD_STATS((net)->mib.statname##_statistics, (field), (val));\ }) -#define _DEVUPD(net, statname, modifier, idev, field, val) \ +#define _DEVUPD(net, statname, mod, idev, field, val) \ ({ \ struct inet6_dev *_idev = (idev); \ if (likely(_idev != NULL)) \ - SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \ - SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\ + mod##SNMP_UPD_PO_STATS((_idev)->stats.statname, field, (val)); \ + mod##SNMP_UPD_PO_STATS((net)->mib.statname##_statistics, field, (val));\ }) /* MIBs */ #define IP6_INC_STATS(net, idev,field) \ - _DEVINC(net, ipv6, 64, idev, field) + _DEVINC(net, ipv6, , idev, field) #define __IP6_INC_STATS(net, idev,field) \ - _DEVINC(net, ipv6, 64_BH, idev, field) + _DEVINC(net, ipv6, __, idev, field) #define IP6_ADD_STATS(net, idev,field,val) \ - _DEVADD(net, ipv6, 64, idev, field, val) + _DEVADD(net, ipv6, , idev, field, val) #define __IP6_ADD_STATS(net, idev,field,val) \ - _DEVADD(net, ipv6, 64_BH, idev, field, val) + _DEVADD(net, ipv6, __, idev, field, val) #define IP6_UPD_PO_STATS(net, idev,field,val) \ - _DEVUPD(net, ipv6, 64, idev, field, val) + _DEVUPD(net, ipv6, , idev, field, val) #define __IP6_UPD_PO_STATS(net, idev,field,val) \ - _DEVUPD(net, ipv6, 64_BH, idev, field, val) + _DEVUPD(net, ipv6, __, idev, field, val) #define ICMP6_INC_STATS(net, idev, field) \ _DEVINCATOMIC(net, icmpv6, , idev, field) #define __ICMP6_INC_STATS(net, idev, field) \ - _DEVINCATOMIC(net, icmpv6, _BH, idev, field) + _DEVINCATOMIC(net, icmpv6, __, idev, field) #define ICMP6MSGOUT_INC_STATS(net, idev, field) \ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 5607c009f738..b392ac8382f2 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -205,9 +205,9 @@ extern int sysctl_sctp_wmem[3]; */ /* SCTP SNMP MIB stats handlers */ -#define SCTP_INC_STATS(net, field) SNMP_INC_STATS((net)->sctp.sctp_statistics, field) -#define __SCTP_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field) -#define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field) +#define SCTP_INC_STATS(net, field) SNMP_INC_STATS((net)->sctp.sctp_statistics, field) +#define __SCTP_INC_STATS(net, field) __SNMP_INC_STATS((net)->sctp.sctp_statistics, field) +#define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field) /* sctp mib definitions */ enum { diff --git a/include/net/snmp.h b/include/net/snmp.h index 56239fc05c51..6bdd255b2250 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -123,7 +123,7 @@ struct linux_xfrm_mib { #define DECLARE_SNMP_STAT(type, name) \ extern __typeof__(type) __percpu *name -#define SNMP_INC_STATS_BH(mib, field) \ +#define __SNMP_INC_STATS(mib, field) \ __this_cpu_inc(mib->mibs[field]) #define SNMP_INC_STATS_ATOMIC_LONG(mib, field) \ @@ -135,7 +135,7 @@ struct linux_xfrm_mib { #define SNMP_DEC_STATS(mib, field) \ this_cpu_dec(mib->mibs[field]) -#define SNMP_ADD_STATS_BH(mib, field, addend) \ +#define __SNMP_ADD_STATS(mib, field, addend) \ __this_cpu_add(mib->mibs[field], addend) #define SNMP_ADD_STATS(mib, field, addend) \ @@ -146,7 +146,7 @@ struct linux_xfrm_mib { this_cpu_inc(ptr[basefield##PKTS]); \ this_cpu_add(ptr[basefield##OCTETS], addend); \ } while (0) -#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ +#define __SNMP_UPD_PO_STATS(mib, basefield, addend) \ do { \ __typeof__((mib->mibs) + 0) ptr = mib->mibs; \ __this_cpu_inc(ptr[basefield##PKTS]); \ @@ -156,7 +156,7 @@ struct linux_xfrm_mib { #if BITS_PER_LONG==32 -#define SNMP_ADD_STATS64_BH(mib, field, addend) \ +#define __SNMP_ADD_STATS64(mib, field, addend) \ do { \ __typeof__(*mib) *ptr = raw_cpu_ptr(mib); \ u64_stats_update_begin(&ptr->syncp); \ @@ -164,16 +164,16 @@ struct linux_xfrm_mib { u64_stats_update_end(&ptr->syncp); \ } while (0) -#define SNMP_ADD_STATS64(mib, field, addend) \ +#define SNMP_ADD_STATS64(mib, field, addend) \ do { \ preempt_disable(); \ - SNMP_ADD_STATS64_BH(mib, field, addend); \ + __SNMP_ADD_STATS64(mib, field, addend); \ preempt_enable(); \ } while (0) -#define SNMP_INC_STATS64_BH(mib, field) SNMP_ADD_STATS64_BH(mib, field, 1) +#define __SNMP_INC_STATS64(mib, field) SNMP_ADD_STATS64(mib, field, 1) #define SNMP_INC_STATS64(mib, field) SNMP_ADD_STATS64(mib, field, 1) -#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) \ +#define __SNMP_UPD_PO_STATS64(mib, basefield, addend) \ do { \ __typeof__(*mib) *ptr; \ ptr = raw_cpu_ptr((mib)); \ @@ -185,17 +185,17 @@ struct linux_xfrm_mib { #define SNMP_UPD_PO_STATS64(mib, basefield, addend) \ do { \ preempt_disable(); \ - SNMP_UPD_PO_STATS64_BH(mib, basefield, addend); \ + __SNMP_UPD_PO_STATS64(mib, basefield, addend); \ preempt_enable(); \ } while (0) #else -#define SNMP_INC_STATS64_BH(mib, field) SNMP_INC_STATS_BH(mib, field) +#define __SNMP_INC_STATS64(mib, field) __SNMP_INC_STATS(mib, field) #define SNMP_INC_STATS64(mib, field) SNMP_INC_STATS(mib, field) #define SNMP_DEC_STATS64(mib, field) SNMP_DEC_STATS(mib, field) -#define SNMP_ADD_STATS64_BH(mib, field, addend) SNMP_ADD_STATS_BH(mib, field, addend) +#define __SNMP_ADD_STATS64(mib, field, addend) __SNMP_ADD_STATS(mib, field, addend) #define SNMP_ADD_STATS64(mib, field, addend) SNMP_ADD_STATS(mib, field, addend) #define SNMP_UPD_PO_STATS64(mib, basefield, addend) SNMP_UPD_PO_STATS(mib, basefield, addend) -#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) SNMP_UPD_PO_STATS_BH(mib, basefield, addend) +#define __SNMP_UPD_PO_STATS64(mib, basefield, addend) __SNMP_UPD_PO_STATS(mib, basefield, addend) #endif #endif diff --git a/include/net/tcp.h b/include/net/tcp.h index ff8b4265cb2b..992f317c1abe 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -332,7 +332,7 @@ bool tcp_check_oom(struct sock *sk, int shift); extern struct proto tcp_prot; #define TCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field) -#define __TCP_INC_STATS(net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field) +#define __TCP_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.tcp_statistics, field) #define TCP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->mib.tcp_statistics, field) #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) diff --git a/include/net/udp.h b/include/net/udp.h index bf6a7c29cf6a..ae07f375370d 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -293,12 +293,12 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, if (is_udplite) SNMP_INC_STATS((net)->mib.udplite_statistics, field); \ else SNMP_INC_STATS((net)->mib.udp_statistics, field); } while(0) #define __UDP_INC_STATS(net, field, is_udplite) do { \ - if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_statistics, field); \ - else SNMP_INC_STATS_BH((net)->mib.udp_statistics, field); } while(0) + if (is_udplite) __SNMP_INC_STATS((net)->mib.udplite_statistics, field); \ + else __SNMP_INC_STATS((net)->mib.udp_statistics, field); } while(0) #define __UDP6_INC_STATS(net, field, is_udplite) do { \ - if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_stats_in6, field);\ - else SNMP_INC_STATS_BH((net)->mib.udp_stats_in6, field); \ + if (is_udplite) __SNMP_INC_STATS((net)->mib.udplite_stats_in6, field);\ + else __SNMP_INC_STATS((net)->mib.udp_stats_in6, field); \ } while(0) #define UDP6_INC_STATS(net, field, __lite) do { \ if (__lite) SNMP_INC_STATS((net)->mib.udplite_stats_in6, field); \ diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index a4c6e2fed91c..0c55ffb859bf 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -199,7 +199,7 @@ struct dccp_mib { DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); #define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field) -#define __DCCP_INC_STATS(field) SNMP_INC_STATS_BH(dccp_statistics, field) +#define __DCCP_INC_STATS(field) __SNMP_INC_STATS(dccp_statistics, field) #define DCCP_DEC_STATS(field) SNMP_DEC_STATS(dccp_statistics, field) /* -- GitLab From 9317bb69824ec8d078b0b786b6971aedb0af3d4f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 25 Apr 2016 10:39:32 -0700 Subject: [PATCH 4869/9938] net: SOCKWQ_ASYNC_NOSPACE optimizations SOCKWQ_ASYNC_NOSPACE is tested in sock_wake_async() so that a SIGIO signal is sent when needed. tcp_sendmsg() clears the bit. tcp_poll() sets the bit when stream is not writeable. We can avoid two atomic operations by first checking if socket is actually interested in the FASYNC business (most sockets in real applications do not use AIO, but select()/poll()/epoll()) This also removes one cache line miss to access sk->sk_wq->flags in tcp_sendmsg() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sock.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/net/sock.h b/include/net/sock.h index d63b8494124e..0f48aad9f8e8 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1940,11 +1940,17 @@ static inline unsigned long sock_wspace(struct sock *sk) */ static inline void sk_set_bit(int nr, struct sock *sk) { + if (nr == SOCKWQ_ASYNC_NOSPACE && !sock_flag(sk, SOCK_FASYNC)) + return; + set_bit(nr, &sk->sk_wq_raw->flags); } static inline void sk_clear_bit(int nr, struct sock *sk) { + if (nr == SOCKWQ_ASYNC_NOSPACE && !sock_flag(sk, SOCK_FASYNC)) + return; + clear_bit(nr, &sk->sk_wq_raw->flags); } -- GitLab From 4be735225f7cd040ca81c18740e7b672021bafeb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 25 Apr 2016 10:39:34 -0700 Subject: [PATCH 4870/9938] net: SOCKWQ_ASYNC_WAITDATA optimizations SOCKWQ_ASYNC_WAITDATA is set/cleared in sk_wait_data() and equivalent functions, so that sock_wake_async() can send a SIGIO only when necessary. Since these atomic operations are really not needed unless socket expressed interest in FASYNC, we can omit them in most cases. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sock.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 0f48aad9f8e8..3df778ccaa82 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1940,7 +1940,8 @@ static inline unsigned long sock_wspace(struct sock *sk) */ static inline void sk_set_bit(int nr, struct sock *sk) { - if (nr == SOCKWQ_ASYNC_NOSPACE && !sock_flag(sk, SOCK_FASYNC)) + if ((nr == SOCKWQ_ASYNC_NOSPACE || nr == SOCKWQ_ASYNC_WAITDATA) && + !sock_flag(sk, SOCK_FASYNC)) return; set_bit(nr, &sk->sk_wq_raw->flags); @@ -1948,7 +1949,8 @@ static inline void sk_set_bit(int nr, struct sock *sk) static inline void sk_clear_bit(int nr, struct sock *sk) { - if (nr == SOCKWQ_ASYNC_NOSPACE && !sock_flag(sk, SOCK_FASYNC)) + if ((nr == SOCKWQ_ASYNC_NOSPACE || nr == SOCKWQ_ASYNC_WAITDATA) && + !sock_flag(sk, SOCK_FASYNC)) return; clear_bit(nr, &sk->sk_wq_raw->flags); -- GitLab From ae411413760785a0a2ce6cb44d5afe95115aa24d Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Wed, 20 Apr 2016 09:08:43 +0300 Subject: [PATCH 4871/9938] usb: dwc3: ep0: sanity check test mode selector In case host sends us an unsupported test mode, we *must* stall this request. This will tell the host that the selector is invalid and we won't put the controller in unsupported test modes which could have undetermined side-effects. Signed-off-by: Fei Yang Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 143deb420481..51b52a79dfec 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -463,8 +463,18 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, if (!set) return -EINVAL; - dwc->test_mode_nr = wIndex >> 8; - dwc->test_mode = true; + switch (wIndex >> 8) { + case TEST_J: + case TEST_K: + case TEST_SE0_NAK: + case TEST_PACKET: + case TEST_FORCE_EN: + dwc->test_mode_nr = wIndex >> 8; + dwc->test_mode = true; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; -- GitLab From 474799f073763b868e158b04b74f8ddd1da38da2 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 22 Apr 2016 11:17:37 +0300 Subject: [PATCH 4872/9938] usb: dwc3: pci: make build-in device properties available Setting the ACPI companion before calling dwc3_pci_quirks. The ACPI companion will be set unconditionally as the primary fwnode, overriding any previously set primary fwnode. This will make sure that any build-in properties added to the platform device will be added as the secondary fwnode in cases where also ACPI companion exists. Signed-off-by: Heikki Krogerus Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index adc1e8a624cb..e444e9a1a0c8 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -170,13 +170,14 @@ static int dwc3_pci_probe(struct pci_dev *pci, } pci_set_drvdata(pci, dwc3); - ret = dwc3_pci_quirks(pci); - if (ret) - goto err; dwc3->dev.parent = dev; ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev)); + ret = dwc3_pci_quirks(pci); + if (ret) + goto err; + ret = platform_device_add(dwc3); if (ret) { dev_err(dev, "failed to register dwc3 device\n"); -- GitLab From ce046d323d74ee9d280688a2cb499716f555a89f Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 22 Apr 2016 11:17:38 +0300 Subject: [PATCH 4873/9938] usb: dwc3: pci: pass the platform device as a parameter to dwc3_pci_quirks() For convenience, passing the dwc3 platform device as a parameter to dwc3_pci_quirks() function. Signed-off-by: Heikki Krogerus Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index e444e9a1a0c8..14196cd416b3 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -47,7 +47,7 @@ static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = { { }, }; -static int dwc3_pci_quirks(struct pci_dev *pdev) +static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3) { if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == PCI_DEVICE_ID_AMD_NL_USB) { @@ -77,8 +77,7 @@ static int dwc3_pci_quirks(struct pci_dev *pdev) pdata.dis_u3_susphy_quirk = true; pdata.dis_u2_susphy_quirk = true; - return platform_device_add_data(pci_get_drvdata(pdev), &pdata, - sizeof(pdata)); + return platform_device_add_data(dwc3, &pdata, sizeof(pdata)); } if (pdev->vendor == PCI_VENDOR_ID_INTEL && @@ -123,8 +122,7 @@ static int dwc3_pci_quirks(struct pci_dev *pdev) pdata.has_lpm_erratum = true; pdata.dis_enblslpm_quirk = true; - return platform_device_add_data(pci_get_drvdata(pdev), &pdata, - sizeof(pdata)); + return platform_device_add_data(dwc3, &pdata, sizeof(pdata)); } return 0; @@ -169,12 +167,10 @@ static int dwc3_pci_probe(struct pci_dev *pci, return ret; } - pci_set_drvdata(pci, dwc3); - dwc3->dev.parent = dev; ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev)); - ret = dwc3_pci_quirks(pci); + ret = dwc3_pci_quirks(pci, dwc3); if (ret) goto err; @@ -184,6 +180,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, goto err; } + pci_set_drvdata(pci, dwc3); return 0; err: platform_device_put(dwc3); -- GitLab From 0878263b68df372e6389b050fc2bd4f6d5b9f332 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Apr 2016 14:53:47 +0300 Subject: [PATCH 4874/9938] usb: gadget: composite: avoid kernel oops with bad gadgets If a gadget driver loaded to a Superspeed-capable peripheral controller, using a Superspeed cable, doesn't provide Superspeed descriptors, we will get a NULL pointer dereference. In order to avoid that situation, we will try to find any valid descriptors we can. If no set of descriptors is passed in, then we'll let that gadget oops anyhow. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index de9ffd60fcfa..3d3cdc5ed20d 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -66,20 +66,36 @@ function_descriptors(struct usb_function *f, { struct usb_descriptor_header **descriptors; + /* + * NOTE: we try to help gadget drivers which might not be setting + * max_speed appropriately. + */ + switch (speed) { case USB_SPEED_SUPER_PLUS: descriptors = f->ssp_descriptors; - break; + if (descriptors) + break; + /* FALLTHROUGH */ case USB_SPEED_SUPER: descriptors = f->ss_descriptors; - break; + if (descriptors) + break; + /* FALLTHROUGH */ case USB_SPEED_HIGH: descriptors = f->hs_descriptors; - break; + if (descriptors) + break; + /* FALLTHROUGH */ default: descriptors = f->fs_descriptors; } + /* + * if we can't find any descriptors at all, then this gadget deserves to + * Oops with a NULL pointer dereference + */ + return descriptors; } -- GitLab From 7b9cc7a2b101cc73f6abe3468441381c98817e54 Mon Sep 17 00:00:00 2001 From: Konrad Leszczynski Date: Fri, 12 Feb 2016 15:21:46 +0000 Subject: [PATCH 4875/9938] usb: dwc3: gadget: give better command return code if Start Transfer command fails, let's try a little harder to figure out why the command failed and give slightly better return codes. This will be usefulf or isochronous endpoints, at least, which could decide to retry a given request. Signed-off-by: Konrad Leszczynski Signed-off-by: Rafal Redzimski Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 4 ++++ drivers/usb/dwc3/gadget.c | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index bbbd1789596e..87df6dd20d23 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -970,6 +970,10 @@ struct dwc3_event_depevt { #define DEPEVT_STATUS_CONTROL_DATA 1 #define DEPEVT_STATUS_CONTROL_STATUS 2 +/* In response to Start Transfer */ +#define DEPEVT_TRANSFER_NO_RESOURCE 1 +#define DEPEVT_TRANSFER_BUS_EXPIRY 2 + u32 parameters:16; } __packed; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 88fd30bf0c46..43efb627d1cf 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -287,12 +287,39 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, do { reg = dwc3_readl(dwc->regs, DWC3_DEPCMD(ep)); if (!(reg & DWC3_DEPCMD_CMDACT)) { + int cmd_status = DWC3_DEPCMD_STATUS(reg); + dwc3_trace(trace_dwc3_gadget, "Command Complete --> %d", - DWC3_DEPCMD_STATUS(reg)); - if (DWC3_DEPCMD_STATUS(reg)) + cmd_status); + + switch (cmd_status) { + case 0: + ret = 0; + break; + case DEPEVT_TRANSFER_NO_RESOURCE: + dwc3_trace(trace_dwc3_gadget, "%s: no resource available"); + ret = -EINVAL; break; - ret = 0; + case DEPEVT_TRANSFER_BUS_EXPIRY: + /* + * SW issues START TRANSFER command to + * isochronous ep with future frame interval. If + * future interval time has already passed when + * core receives the command, it will respond + * with an error status of 'Bus Expiry'. + * + * Instead of always returning -EINVAL, let's + * give a hint to the gadget driver that this is + * the case by returning -EAGAIN. + */ + dwc3_trace(trace_dwc3_gadget, "%s: bus expiry"); + ret = -EAGAIN; + break; + default: + dev_WARN(dwc->dev, "UNKNOWN cmd status\n"); + } + break; } -- GitLab From 8c3d609275f7f39d308e5c40a6220c67454f7a28 Mon Sep 17 00:00:00 2001 From: Vahram Aharonyan Date: Wed, 27 Apr 2016 20:20:46 -0700 Subject: [PATCH 4876/9938] usb: dwc2: gadget: Check for ep0 in enable Replaced the WARN_ON with a check and return of -EINVAL in the dwc2_hsotg_ep_enable function if ep0 is passed in. Signed-off-by: Vahram Aharonyan Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 818f158232bb..d330190f58ef 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2631,7 +2631,10 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, desc->wMaxPacketSize, desc->bInterval); /* not to be called for EP0 */ - WARN_ON(index == 0); + if (index == 0) { + dev_err(hsotg->dev, "%s: called for EP 0\n", __func__); + return -EINVAL; + } dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0; if (dir_in != hs_ep->dir_in) { -- GitLab From ee3de8d750134703c702534173cd8623d1b32c38 Mon Sep 17 00:00:00 2001 From: Vardan Mikayelyan Date: Wed, 27 Apr 2016 20:20:48 -0700 Subject: [PATCH 4877/9938] usb: dwc2: gadget: Prevent handling of host interrupts In host slave mode, the core asserts the rxready, txfifoempty interrupts that get serviced in the gadget irq handler. Prevent servicing of these when not in the gadget mode of operation. Signed-off-by: Vardan Mikayelyan Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index d330190f58ef..4c5e3005e1dc 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2425,6 +2425,9 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw) u32 gintsts; u32 gintmsk; + if (!dwc2_is_device_mode(hsotg)) + return IRQ_NONE; + spin_lock(&hsotg->lock); irq_retry: gintsts = dwc2_readl(hsotg->regs + GINTSTS); -- GitLab From b0d659022e5c96ee5c4bd62d22d3da2d66de306b Mon Sep 17 00:00:00 2001 From: Vardan Mikayelyan Date: Wed, 27 Apr 2016 20:20:51 -0700 Subject: [PATCH 4878/9938] usb: dwc2: host: Setting qtd to NULL after freeing it This is safety change added while doing slub debugging. Affected functions: dwc2_hcd_qtd_unlink_and_free() _dwc2_hcd_urb_enqueue() Signed-off-by: Vardan Mikayelyan Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd.c | 1 + drivers/usb/dwc2/hcd.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 1f6255131857..2df3d04d26f5 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -4703,6 +4703,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, spin_unlock_irqrestore(&hsotg->lock, flags); urb->hcpriv = NULL; kfree(qtd); + qtd = NULL; fail1: if (qh_allocated) { struct dwc2_qtd *qtd2, *qtd2_tmp; diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 89fa26cb25f4..7758bfb644ff 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -552,6 +552,7 @@ static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg, { list_del(&qtd->qtd_list_entry); kfree(qtd); + qtd = NULL; } /* Descriptor DMA support functions */ -- GitLab From 907a444718b8f93956acac1c944d880c54ab900d Mon Sep 17 00:00:00 2001 From: Sevak Arakelyan Date: Wed, 27 Apr 2016 20:20:53 -0700 Subject: [PATCH 4879/9938] usb: dwc2: Fixed SOF interrupt enabling/disabling In case of DDMA mode we don't need to get an SOF interrupt so disable the unmasking of SOF interrupt in DDMA mode. Signed-off-by: Sevak Arakelyan Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd_queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 7f634fd771c7..b5c7793a2df2 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -1709,7 +1709,8 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) dwc2_deschedule_periodic(hsotg, qh); hsotg->periodic_qh_count--; - if (!hsotg->periodic_qh_count) { + if (!hsotg->periodic_qh_count && + hsotg->core_params->dma_desc_enable <= 0) { intr_mask = dwc2_readl(hsotg->regs + GINTMSK); intr_mask &= ~GINTSTS_SOF; dwc2_writel(intr_mask, hsotg->regs + GINTMSK); -- GitLab From a6ef3e02542a33fb705e6977221deb0292b27398 Mon Sep 17 00:00:00 2001 From: John Youn Date: Wed, 27 Apr 2016 20:20:56 -0700 Subject: [PATCH 4880/9938] usb: dwc2: Proper cleanup on dr_mode failure Cleanup in probe if we fail to get dr_mode. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 88629bed6614..fc6f5251de5d 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -562,7 +562,7 @@ static int dwc2_driver_probe(struct platform_device *dev) retval = dwc2_get_dr_mode(hsotg); if (retval) - return retval; + goto error; /* * Reset before dwc2_get_hwparams() then it could get power-on real -- GitLab From 676e3497448177bdb1934cbc4402f921730a5864 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Apr 2016 10:49:07 +0300 Subject: [PATCH 4881/9938] usb: dwc3: gadget: update DCFG.NumP to max burst size NumP field of DCFG register is used on NumP field of ACK TP header and it tells the host how many packets an endpoint can receive before waiting for synchronization. Documentation says it should be set to anything <=bMaxBurst. Interestingly, however, this setting is not per-endpoint how it should be (different endpoints could have different burst sizes), but things seem to work okay right now. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 3 +++ drivers/usb/dwc3/gadget.c | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 87df6dd20d23..c5f576aa1903 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -271,6 +271,9 @@ #define DWC3_DCFG_LOWSPEED (2 << 0) #define DWC3_DCFG_FULLSPEED1 (3 << 0) +#define DWC3_DCFG_NUMP_SHIFT 17 +#define DWC3_DCFG_NUMP(n) (((n) & 0x1f) >> DWC3_DCFG_NUMP_SHIFT) +#define DWC3_DCFG_NUMP_MASK (0x1f << DWC3_DCFG_NUMP_SHIFT) #define DWC3_DCFG_LPM_CAP (1 << 22) /* Device Control Register */ diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 43efb627d1cf..4b681b0d420f 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -464,9 +464,19 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, /* Burst size is only needed in SuperSpeed mode */ if (dwc->gadget.speed >= USB_SPEED_SUPER) { - u32 burst = dep->endpoint.maxburst - 1; + u32 burst = dep->endpoint.maxburst; + u32 nump; + u32 reg; - params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst); + /* update NumP */ + reg = dwc3_readl(dwc->regs, DWC3_DCFG); + nump = DWC3_DCFG_NUMP(reg); + nump = max(nump, burst); + reg &= ~DWC3_DCFG_NUMP_MASK; + reg |= nump << DWC3_DCFG_NUMP_SHIFT; + dwc3_writel(dwc->regs, DWC3_DCFG, reg); + + params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); } if (ignore) -- GitLab From 2a58f9c12bb360f38fb39e470bb5ff94014356e6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 28 Apr 2016 10:56:28 +0300 Subject: [PATCH 4882/9938] usb: dwc3: gadget: disable automatic calculation of ACK TP NUMP Now that we calculate DCFG.NUMP, we can disable dwc3's automatic calculation so we maximize our chances of very high throughtput through the use of bursts. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 5 +++++ drivers/usb/dwc3/gadget.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c5f576aa1903..186a8868829f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -165,6 +165,11 @@ #define DWC3_DESCFETCHQ 13 #define DWC3_EVENTQ 15 +/* Global RX Threshold Configuration Register */ +#define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19) +#define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24) +#define DWC3_GRXTHRCFG_PKTCNTSEL (1 << 29) + /* Global Configuration Register */ #define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) #define DWC3_GCTL_U2RSTECN (1 << 16) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4b681b0d420f..c3b0d01e1960 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1669,6 +1669,17 @@ static int dwc3_gadget_start(struct usb_gadget *g, } dwc3_writel(dwc->regs, DWC3_DCFG, reg); + /* + * We are telling dwc3 that we want to use DCFG.NUMP as ACK TP's NUMP + * field instead of letting dwc3 itself calculate that automatically. + * + * This way, we maximize the chances that we'll be able to get several + * bursts of data without going through any sort of endpoint throttling. + */ + reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); + reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL; + dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); + /* Start with SuperSpeed Default */ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); -- GitLab From b3a52d75bc91d2c7299e721c0fb41c33859c2cdf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 22 Apr 2016 14:45:45 +0200 Subject: [PATCH 4883/9938] clk: renesas: mstp: Postpone call to pm_genpd_init() All local setup of the generic_pm_domain structure should have been completed before calling pm_genpd_init(). Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Ulf Hansson --- drivers/clk/renesas/clk-mstp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 8b597b9a3804..969fbb61ab07 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c @@ -316,11 +316,10 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np) return; pd->name = np->name; - pd->flags = GENPD_FLAG_PM_CLK; - pm_genpd_init(pd, &simple_qos_governor, false); pd->attach_dev = cpg_mstp_attach_dev; pd->detach_dev = cpg_mstp_detach_dev; + pm_genpd_init(pd, &simple_qos_governor, false); of_genpd_add_provider_simple(np, pd); } -- GitLab From 20729300cabdad60333e52278bd2dd25e5d85518 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 22 Apr 2016 14:57:29 +0200 Subject: [PATCH 4884/9938] clk: renesas: mstp: Use always-on governor for Clock Domain As a pure Clock Domain does not have the concept of powering the domain itself, the CPG/MSTP driver does not provide power_off() and power_on() callbacks. However, the genpd core may still perform a dummy power down, causing /sys/kernel/debug/pm_genpd/pm_genpd_summary to report the domain's status being "off-0". Use the always-on governor to make sure the domain is never powered down, and always shows up as "on" in pm_genpd_summary. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Ulf Hansson --- drivers/clk/renesas/clk-mstp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 969fbb61ab07..5093a250650d 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c @@ -319,7 +319,7 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np) pd->flags = GENPD_FLAG_PM_CLK; pd->attach_dev = cpg_mstp_attach_dev; pd->detach_dev = cpg_mstp_detach_dev; - pm_genpd_init(pd, &simple_qos_governor, false); + pm_genpd_init(pd, &pm_domain_always_on_gov, false); of_genpd_add_provider_simple(np, pd); } -- GitLab From 93662500a1fcc9c8085ac3f056b537d093fd4d20 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 22 Apr 2016 14:46:51 +0200 Subject: [PATCH 4885/9938] clk: renesas: cpg-mssr: Postpone call to pm_genpd_init() All local setup of the generic_pm_domain structure should have been completed before calling pm_genpd_init(). Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Ulf Hansson --- drivers/clk/renesas/renesas-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 1f2dc3629f0e..0d595311c659 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -493,9 +493,9 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, genpd = &pd->genpd; genpd->name = np->name; genpd->flags = GENPD_FLAG_PM_CLK; - pm_genpd_init(genpd, &simple_qos_governor, false); genpd->attach_dev = cpg_mssr_attach_dev; genpd->detach_dev = cpg_mssr_detach_dev; + pm_genpd_init(genpd, &simple_qos_governor, false); cpg_mssr_clk_domain = pd; of_genpd_add_provider_simple(np, genpd); -- GitLab From d04a75af450782db2937603bb6706bf6fa7c6f37 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 22 Apr 2016 14:59:10 +0200 Subject: [PATCH 4886/9938] clk: renesas: cpg-mssr: Use always-on governor for Clock Domain As a pure Clock Domain does not have the concept of powering the domain itself, the CPG/MSTP driver does not provide power_off() and power_on() callbacks. However, the genpd core may still perform a dummy power down, causing /sys/kernel/debug/pm_genpd/pm_genpd_summary to report the domain's status being "off-0". Use the always-on governor to make sure the domain is never powered down, and always shows up as "on" in pm_genpd_summary. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Ulf Hansson --- drivers/clk/renesas/renesas-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 0d595311c659..210cd744a7a9 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -495,7 +495,7 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, genpd->flags = GENPD_FLAG_PM_CLK; genpd->attach_dev = cpg_mssr_attach_dev; genpd->detach_dev = cpg_mssr_detach_dev; - pm_genpd_init(genpd, &simple_qos_governor, false); + pm_genpd_init(genpd, &pm_domain_always_on_gov, false); cpg_mssr_clk_domain = pd; of_genpd_add_provider_simple(np, genpd); -- GitLab From 34d9700702f4042ce10d68a092ab7f79575e7a3b Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 16 Mar 2016 16:43:06 +0800 Subject: [PATCH 4887/9938] btrfs: rename btrfs_std_error to btrfs_handle_fs_error btrfs_std_error() handles errors, puts FS into readonly mode (as of now). So its good idea to rename it to btrfs_handle_fs_error(). Signed-off-by: Anand Jain Reviewed-by: David Sterba [ edit changelog ] Signed-off-by: David Sterba --- fs/btrfs/ctree.c | 6 +++--- fs/btrfs/ctree.h | 6 +++--- fs/btrfs/disk-io.c | 8 ++++---- fs/btrfs/extent-tree.c | 2 +- fs/btrfs/inode-item.c | 2 +- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/root-tree.c | 4 ++-- fs/btrfs/super.c | 6 +++--- fs/btrfs/transaction.c | 2 +- fs/btrfs/tree-log.c | 8 ++++---- fs/btrfs/volumes.c | 14 +++++++------- 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index ec7928a27aaa..decd0a3f5d61 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1011,7 +1011,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, return ret; if (refs == 0) { ret = -EROFS; - btrfs_std_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(root->fs_info, ret, NULL); return ret; } } else { @@ -1928,7 +1928,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, child = read_node_slot(root, mid, 0); if (!child) { ret = -EROFS; - btrfs_std_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(root->fs_info, ret, NULL); goto enospc; } @@ -2031,7 +2031,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, */ if (!left) { ret = -EROFS; - btrfs_std_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(root->fs_info, ret, NULL); goto enospc; } wret = balance_node_right(trans, root, mid, left); diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 84a6a5b3384a..12f80cd230ab 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -4329,7 +4329,7 @@ static inline void assfail(char *expr, char *file, int line) #define btrfs_assert() __printf(5, 6) __cold -void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, +void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function, unsigned int line, int errno, const char *fmt, ...); const char *btrfs_decode_error(int errno); @@ -4472,9 +4472,9 @@ do { \ __LINE__, (errno)); \ } while (0) -#define btrfs_std_error(fs_info, errno, fmt, args...) \ +#define btrfs_handle_fs_error(fs_info, errno, fmt, args...) \ do { \ - __btrfs_std_error((fs_info), __func__, __LINE__, \ + __btrfs_handle_fs_error((fs_info), __func__, __LINE__, \ (errno), fmt, ##args); \ } while (0) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 4e47849d7427..aeb090583b78 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2417,7 +2417,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, /* returns with log_tree_root freed on success */ ret = btrfs_recover_log_trees(log_tree_root); if (ret) { - btrfs_std_error(tree_root->fs_info, ret, + btrfs_handle_fs_error(tree_root->fs_info, ret, "Failed to recover log tree"); free_extent_buffer(log_tree_root->node); kfree(log_tree_root); @@ -3646,7 +3646,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors) if (ret) { mutex_unlock( &root->fs_info->fs_devices->device_list_mutex); - btrfs_std_error(root->fs_info, ret, + btrfs_handle_fs_error(root->fs_info, ret, "errors while submitting device barriers."); return ret; } @@ -3686,7 +3686,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors) mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); /* FUA is masked off if unsupported and can't be the reason */ - btrfs_std_error(root->fs_info, -EIO, + btrfs_handle_fs_error(root->fs_info, -EIO, "%d errors while writing supers", total_errors); return -EIO; } @@ -3704,7 +3704,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors) } mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); if (total_errors > max_errors) { - btrfs_std_error(root->fs_info, -EIO, + btrfs_handle_fs_error(root->fs_info, -EIO, "%d errors while writing supers", total_errors); return -EIO; } diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 84e060eb0de8..c0520a94a333 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -9058,7 +9058,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, if (!for_reloc && root_dropped == false) btrfs_add_dead_root(root); if (err && err != -EAGAIN) - btrfs_std_error(root->fs_info, err, NULL); + btrfs_handle_fs_error(root->fs_info, err, NULL); return err; } diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index be4d22a5022f..b8acc07ac6c2 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c @@ -157,7 +157,7 @@ static int btrfs_del_inode_extref(struct btrfs_trans_handle *trans, */ if (!btrfs_find_name_in_ext_backref(path, ref_objectid, name, name_len, &extref)) { - btrfs_std_error(root->fs_info, -ENOENT, NULL); + btrfs_handle_fs_error(root->fs_info, -ENOENT, NULL); ret = -EROFS; goto out; } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5a23806ae418..06fcc448108b 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -4847,7 +4847,7 @@ static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg) /* update qgroup status and info */ err = btrfs_run_qgroups(trans, root->fs_info); if (err < 0) - btrfs_std_error(root->fs_info, ret, + btrfs_handle_fs_error(root->fs_info, ret, "failed to update qgroup status and info\n"); err = btrfs_end_transaction(trans, root); if (err && !ret) diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 08ef890deca6..1c29514d8aff 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2418,7 +2418,7 @@ void merge_reloc_roots(struct reloc_control *rc) } out: if (ret) { - btrfs_std_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(root->fs_info, ret, NULL); if (!list_empty(&reloc_roots)) free_reloc_roots(&reloc_roots); diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 9fcd6dfc3266..b2b14e7115f1 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -284,7 +284,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) trans = btrfs_join_transaction(tree_root); if (IS_ERR(trans)) { err = PTR_ERR(trans); - btrfs_std_error(tree_root->fs_info, err, + btrfs_handle_fs_error(tree_root->fs_info, err, "Failed to start trans to delete " "orphan item"); break; @@ -293,7 +293,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) root_key.objectid); btrfs_end_transaction(trans, tree_root); if (err) { - btrfs_std_error(tree_root->fs_info, err, + btrfs_handle_fs_error(tree_root->fs_info, err, "Failed to delete root orphan " "item"); break; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 00b8f37cc306..cc077887bd9d 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -131,11 +131,11 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info) } /* - * __btrfs_std_error decodes expected errors from the caller and + * __btrfs_handle_fs_error decodes expected errors from the caller and * invokes the approciate error response. */ __cold -void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, +void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function, unsigned int line, int errno, const char *fmt, ...) { struct super_block *sb = fs_info->sb; @@ -252,7 +252,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, /* Wake up anybody who may be waiting on this transaction */ wake_up(&root->fs_info->transaction_wait); wake_up(&root->fs_info->transaction_blocked_wait); - __btrfs_std_error(root->fs_info, function, line, errno, NULL); + __btrfs_handle_fs_error(root->fs_info, function, line, errno, NULL); } /* * __btrfs_panic decodes unexpected, fatal errors from the caller, diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 43885e51b882..a469b55a7ac1 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -2145,7 +2145,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ret = btrfs_write_and_wait_transaction(trans, root); if (ret) { - btrfs_std_error(root->fs_info, ret, + btrfs_handle_fs_error(root->fs_info, ret, "Error while writing out transaction"); mutex_unlock(&root->fs_info->tree_log_mutex); goto scrub_continue; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 517d0ccb351e..16a74d1a2720 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -5519,7 +5519,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) ret = walk_log_tree(trans, log_root_tree, &wc); if (ret) { - btrfs_std_error(fs_info, ret, "Failed to pin buffers while " + btrfs_handle_fs_error(fs_info, ret, "Failed to pin buffers while " "recovering log root tree."); goto error; } @@ -5533,7 +5533,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0); if (ret < 0) { - btrfs_std_error(fs_info, ret, + btrfs_handle_fs_error(fs_info, ret, "Couldn't find tree log root."); goto error; } @@ -5551,7 +5551,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) log = btrfs_read_fs_root(log_root_tree, &found_key); if (IS_ERR(log)) { ret = PTR_ERR(log); - btrfs_std_error(fs_info, ret, + btrfs_handle_fs_error(fs_info, ret, "Couldn't read tree log root."); goto error; } @@ -5566,7 +5566,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) free_extent_buffer(log->node); free_extent_buffer(log->commit_root); kfree(log); - btrfs_std_error(fs_info, ret, "Couldn't read target root " + btrfs_handle_fs_error(fs_info, ret, "Couldn't read target root " "for tree log recovery."); goto error; } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index bd0f45fb38c4..0d3dd3e10e31 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1454,7 +1454,7 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, extent = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dev_extent); } else { - btrfs_std_error(root->fs_info, ret, "Slot search failed"); + btrfs_handle_fs_error(root->fs_info, ret, "Slot search failed"); goto out; } @@ -1462,7 +1462,7 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, ret = btrfs_del_item(trans, root, path); if (ret) { - btrfs_std_error(root->fs_info, ret, + btrfs_handle_fs_error(root->fs_info, ret, "Failed to remove dev extent item"); } else { set_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags); @@ -2418,7 +2418,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ret = btrfs_relocate_sys_chunks(root); if (ret < 0) - btrfs_std_error(root->fs_info, ret, + btrfs_handle_fs_error(root->fs_info, ret, "Failed to relocate sys chunks after " "device initialization. This can be fixed " "using the \"btrfs balance\" command."); @@ -2663,7 +2663,7 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans, if (ret < 0) goto out; else if (ret > 0) { /* Logic error or corruption */ - btrfs_std_error(root->fs_info, -ENOENT, + btrfs_handle_fs_error(root->fs_info, -ENOENT, "Failed lookup while freeing chunk."); ret = -ENOENT; goto out; @@ -2671,7 +2671,7 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans, ret = btrfs_del_item(trans, root, path); if (ret < 0) - btrfs_std_error(root->fs_info, ret, + btrfs_handle_fs_error(root->fs_info, ret, "Failed to delete chunk item."); out: btrfs_free_path(path); @@ -2857,7 +2857,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset) chunk_offset); if (IS_ERR(trans)) { ret = PTR_ERR(trans); - btrfs_std_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(root->fs_info, ret, NULL); return ret; } @@ -3632,7 +3632,7 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info) unset_balance_control(fs_info); ret = del_balance_item(fs_info->tree_root); if (ret) - btrfs_std_error(fs_info, ret, NULL); + btrfs_handle_fs_error(fs_info, ret, NULL); atomic_set(&fs_info->mutually_exclusive_operation_running, 0); } -- GitLab From 2351d743f6b69d289f04246127c9d92516621974 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 16 Mar 2016 16:43:07 +0800 Subject: [PATCH 4888/9938] btrfs: remove unused function btrfs_assert() Apparently looks like ASSERT does the same intended job, as intended btrfs_assert(). Signed-off-by: Anand Jain Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 12f80cd230ab..4f37e3766626 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -4326,7 +4326,6 @@ static inline void assfail(char *expr, char *file, int line) #define ASSERT(expr) ((void)0) #endif -#define btrfs_assert() __printf(5, 6) __cold void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function, -- GitLab From c5f4ccb2f77355ac44433feb362fecd7f1a7d03e Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 16 Mar 2016 16:43:08 +0800 Subject: [PATCH 4889/9938] btrfs: move error handling code together in ctree.h Looks like we added the incompatible defines in between the error handling defines in the file ctree.h. Now group them back. Signed-off-by: Anand Jain Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 78 +++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 4f37e3766626..e22568a54545 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -4338,6 +4338,46 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root, const char *function, unsigned int line, int errno); +/* + * Call btrfs_abort_transaction as early as possible when an error condition is + * detected, that way the exact line number is reported. + */ +#define btrfs_abort_transaction(trans, root, errno) \ +do { \ + /* Report first abort since mount */ \ + if (!test_and_set_bit(BTRFS_FS_STATE_TRANS_ABORTED, \ + &((root)->fs_info->fs_state))) { \ + WARN(1, KERN_DEBUG \ + "BTRFS: Transaction aborted (error %d)\n", \ + (errno)); \ + } \ + __btrfs_abort_transaction((trans), (root), __func__, \ + __LINE__, (errno)); \ +} while (0) + +#define btrfs_handle_fs_error(fs_info, errno, fmt, args...) \ +do { \ + __btrfs_handle_fs_error((fs_info), __func__, __LINE__, \ + (errno), fmt, ##args); \ +} while (0) + +__printf(5, 6) +__cold +void __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function, + unsigned int line, int errno, const char *fmt, ...); +/* + * If BTRFS_MOUNT_PANIC_ON_FATAL_ERROR is in mount_opt, __btrfs_panic + * will panic(). Otherwise we BUG() here. + */ +#define btrfs_panic(fs_info, errno, fmt, args...) \ +do { \ + __btrfs_panic(fs_info, __func__, __LINE__, errno, fmt, ##args); \ + BUG(); \ +} while (0) + + +/* compatibility and incompatibility defines */ + #define btrfs_set_fs_incompat(__fs_info, opt) \ __btrfs_set_fs_incompat((__fs_info), BTRFS_FEATURE_INCOMPAT_##opt) @@ -4454,44 +4494,6 @@ static inline int __btrfs_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag) return !!(btrfs_super_compat_ro_flags(disk_super) & flag); } -/* - * Call btrfs_abort_transaction as early as possible when an error condition is - * detected, that way the exact line number is reported. - */ -#define btrfs_abort_transaction(trans, root, errno) \ -do { \ - /* Report first abort since mount */ \ - if (!test_and_set_bit(BTRFS_FS_STATE_TRANS_ABORTED, \ - &((root)->fs_info->fs_state))) { \ - WARN(1, KERN_DEBUG \ - "BTRFS: Transaction aborted (error %d)\n", \ - (errno)); \ - } \ - __btrfs_abort_transaction((trans), (root), __func__, \ - __LINE__, (errno)); \ -} while (0) - -#define btrfs_handle_fs_error(fs_info, errno, fmt, args...) \ -do { \ - __btrfs_handle_fs_error((fs_info), __func__, __LINE__, \ - (errno), fmt, ##args); \ -} while (0) - -__printf(5, 6) -__cold -void __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function, - unsigned int line, int errno, const char *fmt, ...); - -/* - * If BTRFS_MOUNT_PANIC_ON_FATAL_ERROR is in mount_opt, __btrfs_panic - * will panic(). Otherwise we BUG() here. - */ -#define btrfs_panic(fs_info, errno, fmt, args...) \ -do { \ - __btrfs_panic(fs_info, __func__, __LINE__, errno, fmt, ##args); \ - BUG(); \ -} while (0) - /* acl.c */ #ifdef CONFIG_BTRFS_FS_POSIX_ACL struct posix_acl *btrfs_get_acl(struct inode *inode, int type); -- GitLab From 13f48dc9094b56c5bffd8d57349a0a01a1926b2d Mon Sep 17 00:00:00 2001 From: Satoru Takeuchi Date: Tue, 15 Mar 2016 09:09:59 +0900 Subject: [PATCH 4890/9938] btrfs: Simplify conditions about compress while mapping btrfs flags to inode flags Signed-off-by: Satoru Takeuchi Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 06fcc448108b..0f76aea6e398 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -125,10 +125,10 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags) if (flags & BTRFS_INODE_NODATACOW) iflags |= FS_NOCOW_FL; - if ((flags & BTRFS_INODE_COMPRESS) && !(flags & BTRFS_INODE_NOCOMPRESS)) - iflags |= FS_COMPR_FL; - else if (flags & BTRFS_INODE_NOCOMPRESS) + if (flags & BTRFS_INODE_NOCOMPRESS) iflags |= FS_NOCOMP_FL; + else if (flags & BTRFS_INODE_COMPRESS) + iflags |= FS_COMPR_FL; return iflags; } -- GitLab From 0713d90c75745dc6148f6346d490e9ef63a4e8b4 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Thu, 17 Mar 2016 10:38:57 +0800 Subject: [PATCH 4891/9938] btrfs: remove save_error_info() Actually save_error_info() sets the FS state to error and nothing else. Further the word save doesn't induce caffeine when compared to the word set in what actually it does. So to make it better understandable move save_error_info() code to its only consumer itself. Signed-off-by: Anand Jain Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/super.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index cc077887bd9d..dab51118b972 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -97,15 +97,6 @@ const char *btrfs_decode_error(int errno) return errstr; } -static void save_error_info(struct btrfs_fs_info *fs_info) -{ - /* - * today we only save the error info into ram. Long term we'll - * also send it down to the disk - */ - set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state); -} - /* btrfs handle error by forcing the filesystem readonly */ static void btrfs_handle_error(struct btrfs_fs_info *fs_info) { @@ -170,8 +161,13 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function } #endif + /* + * Today we only save the error info to memory. Long term we'll + * also send it down to the disk + */ + set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state); + /* Don't go through full error handling during mount */ - save_error_info(fs_info); if (sb->s_flags & MS_BORN) btrfs_handle_error(fs_info); } -- GitLab From 6719afdcf808b38145095b2e485c0f90bfc29722 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 22 Jun 2014 14:30:09 +0200 Subject: [PATCH 4892/9938] Btrfs: Refactor btrfs_lock_cluster() to kill compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fs/btrfs/extent-tree.c: In function ‘btrfs_lock_cluster’: fs/btrfs/extent-tree.c:6399: warning: ‘used_bg’ may be used uninitialized in this function - Replace "again: ... goto again;" by standard C "while (1) { ... }", - Move block not processed during the first iteration of the loop to the end of the loop, which allows to kill the "locked" variable, Signed-off-by: Geert Uytterhoeven Reviewed-and-Tested-by: Miao Xie [ the compilation warning has been fixed by other patch, now we want to clean up the function ] Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c0520a94a333..b66f460f779a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7025,36 +7025,35 @@ btrfs_lock_cluster(struct btrfs_block_group_cache *block_group, int delalloc) { struct btrfs_block_group_cache *used_bg = NULL; - bool locked = false; -again: + spin_lock(&cluster->refill_lock); - if (locked) { - if (used_bg == cluster->block_group) + while (1) { + used_bg = cluster->block_group; + if (!used_bg) + return NULL; + + if (used_bg == block_group) return used_bg; - up_read(&used_bg->data_rwsem); - btrfs_put_block_group(used_bg); - } + btrfs_get_block_group(used_bg); - used_bg = cluster->block_group; - if (!used_bg) - return NULL; + if (!delalloc) + return used_bg; - if (used_bg == block_group) - return used_bg; + if (down_read_trylock(&used_bg->data_rwsem)) + return used_bg; - btrfs_get_block_group(used_bg); + spin_unlock(&cluster->refill_lock); - if (!delalloc) - return used_bg; + down_read(&used_bg->data_rwsem); - if (down_read_trylock(&used_bg->data_rwsem)) - return used_bg; + spin_lock(&cluster->refill_lock); + if (used_bg == cluster->block_group) + return used_bg; - spin_unlock(&cluster->refill_lock); - down_read(&used_bg->data_rwsem); - locked = true; - goto again; + up_read(&used_bg->data_rwsem); + btrfs_put_block_group(used_bg); + } } static inline void -- GitLab From 180e4d4700b1b7bfdffd9e58ae95220ae9482d17 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Mon, 4 Apr 2016 15:31:22 +0100 Subject: [PATCH 4893/9938] btrfs: fix typos in comments Correct a typo in the chunk_mutex name to make it grepable. Since it is better to fix several typos at once, fixing the 2 more in the same file. Signed-off-by: Luis de Bethencourt Signed-off-by: David Sterba --- fs/btrfs/super.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index dab51118b972..957976d9d627 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1484,10 +1484,10 @@ static int setup_security_options(struct btrfs_fs_info *fs_info, memcpy(&fs_info->security_opts, sec_opts, sizeof(*sec_opts)); } else { /* - * Since SELinux(the only one supports security_mnt_opts) does - * NOT support changing context during remount/mount same sb, - * This must be the same or part of the same security options, - * just free it. + * Since SELinux (the only one supporting security_mnt_opts) + * does NOT support changing context during remount/mount of + * the same sb, this must be the same or part of the same + * security options, just free it. */ security_free_mnt_opts(sec_opts); } @@ -1665,8 +1665,8 @@ static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info, unsigned long old_opts) { /* - * We need cleanup all defragable inodes if the autodefragment is - * close or the fs is R/O. + * We need to cleanup all defragable inodes if the autodefragment is + * close or the filesystem is read only. */ if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) && (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) || @@ -2049,7 +2049,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) u64 thresh = 0; /* - * holding chunk_muext to avoid allocating new chunks, holding + * holding chunk_mutex to avoid allocating new chunks, holding * device_list_mutex to avoid the device being removed */ rcu_read_lock(); -- GitLab From 3521ba1cc351e80488c3f85748c92c3853b75818 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Sun, 17 Apr 2016 15:03:01 -0700 Subject: [PATCH 4894/9938] powercap, perf/x86/intel/rapl: Add PSys support Skylake processor supports a new set of RAPL registers for controlling entire SoC instead of just CPU package. This is useful for thermal and power control when source of power/thermal is not just CPU/GPU. This change adds a new platform domain (AKA PSys) to the current power capping Intel RAPL driver. PSys also supports PL1 (long term) and PL2 (short term) control like package domain. This also follows same MSRs for energy and time units as package domain. Unlike package domain, PSys support requires more than just processor level implementation. The other parts in the system need additional implementation, which OEMs needs to support. So not all Skylake systems will support PSys. Signed-off-by: Srinivas Pandruvada Signed-off-by: Peter Zijlstra (Intel) Acked-by: Rafael J. Wysocki Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: bp@alien8.de Cc: hpa@zytor.com Cc: jacob.jun.pan@linux.intel.com Cc: rjw@rjwysocki.net Link: http://lkml.kernel.org/r/1460930581-29748-3-git-send-email-srinivas.pandruvada@linux.intel.com Signed-off-by: Ingo Molnar --- drivers/powercap/intel_rapl.c | 69 +++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 8fad0a7044d3..f2201d42a9cd 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -34,6 +34,9 @@ #include #include +/* Local defines */ +#define MSR_PLATFORM_POWER_LIMIT 0x0000065C + /* bitmasks for RAPL MSRs, used by primitive access functions */ #define ENERGY_STATUS_MASK 0xffffffff @@ -86,6 +89,7 @@ enum rapl_domain_type { RAPL_DOMAIN_PP0, /* core power plane */ RAPL_DOMAIN_PP1, /* graphics uncore */ RAPL_DOMAIN_DRAM,/* DRAM control_type */ + RAPL_DOMAIN_PLATFORM, /* PSys control_type */ RAPL_DOMAIN_MAX, }; @@ -251,9 +255,11 @@ static const char * const rapl_domain_names[] = { "core", "uncore", "dram", + "psys", }; static struct powercap_control_type *control_type; /* PowerCap Controller */ +static struct rapl_domain *platform_rapl_domain; /* Platform (PSys) domain */ /* caller to ensure CPU hotplug lock is held */ static struct rapl_package *find_package_by_id(int id) @@ -409,6 +415,14 @@ static const struct powercap_zone_ops zone_ops[] = { .set_enable = set_domain_enable, .get_enable = get_domain_enable, }, + /* RAPL_DOMAIN_PLATFORM */ + { + .get_energy_uj = get_energy_counter, + .get_max_energy_range_uj = get_max_energy_counter, + .release = release_zone, + .set_enable = set_domain_enable, + .get_enable = get_domain_enable, + }, }; static int set_power_limit(struct powercap_zone *power_zone, int id, @@ -1160,6 +1174,13 @@ static int rapl_unregister_powercap(void) powercap_unregister_zone(control_type, &rd_package->power_zone); } + + if (platform_rapl_domain) { + powercap_unregister_zone(control_type, + &platform_rapl_domain->power_zone); + kfree(platform_rapl_domain); + } + powercap_unregister_control_type(control_type); return 0; @@ -1239,6 +1260,47 @@ static int rapl_package_register_powercap(struct rapl_package *rp) return ret; } +static int rapl_register_psys(void) +{ + struct rapl_domain *rd; + struct powercap_zone *power_zone; + u64 val; + + if (rdmsrl_safe_on_cpu(0, MSR_PLATFORM_ENERGY_STATUS, &val) || !val) + return -ENODEV; + + if (rdmsrl_safe_on_cpu(0, MSR_PLATFORM_POWER_LIMIT, &val) || !val) + return -ENODEV; + + rd = kzalloc(sizeof(*rd), GFP_KERNEL); + if (!rd) + return -ENOMEM; + + rd->name = rapl_domain_names[RAPL_DOMAIN_PLATFORM]; + rd->id = RAPL_DOMAIN_PLATFORM; + rd->msrs[0] = MSR_PLATFORM_POWER_LIMIT; + rd->msrs[1] = MSR_PLATFORM_ENERGY_STATUS; + rd->rpl[0].prim_id = PL1_ENABLE; + rd->rpl[0].name = pl1_name; + rd->rpl[1].prim_id = PL2_ENABLE; + rd->rpl[1].name = pl2_name; + rd->rp = find_package_by_id(0); + + power_zone = powercap_register_zone(&rd->power_zone, control_type, + "psys", NULL, + &zone_ops[RAPL_DOMAIN_PLATFORM], + 2, &constraint_ops); + + if (IS_ERR(power_zone)) { + kfree(rd); + return PTR_ERR(power_zone); + } + + platform_rapl_domain = rd; + + return 0; +} + static int rapl_register_powercap(void) { struct rapl_domain *rd; @@ -1255,6 +1317,10 @@ static int rapl_register_powercap(void) list_for_each_entry(rp, &rapl_packages, plist) if (rapl_package_register_powercap(rp)) goto err_cleanup_package; + + /* Don't bail out if PSys is not supported */ + rapl_register_psys(); + return ret; err_cleanup_package: @@ -1289,6 +1355,9 @@ static int rapl_check_domain(int cpu, int domain) case RAPL_DOMAIN_DRAM: msr = MSR_DRAM_ENERGY_STATUS; break; + case RAPL_DOMAIN_PLATFORM: + /* PSYS(PLATFORM) is not a CPU domain, so avoid printng error */ + return -EINVAL; default: pr_err("invalid domain id %d\n", domain); return -EINVAL; -- GitLab From 594dd290cf5403a9a5818619dfff42d8e8e0518e Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Fri, 22 Apr 2016 17:07:24 +0800 Subject: [PATCH 4895/9938] sched/cpufreq: Optimize cpufreq update kicker to avoid update multiple times Sometimes delta_exec is 0 due to update_curr() is called multiple times, this is captured by: u64 delta_exec = rq_clock_task(rq) - curr->se.exec_start; This patch optimizes the cpufreq update kicker by bailing out when nothing changed, it will benefit the upcoming schedutil, since otherwise it will (over)react to the special util/max combination. Signed-off-by: Wanpeng Li Signed-off-by: Peter Zijlstra (Intel) Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1461316044-9520-1-git-send-email-wanpeng.li@hotmail.com Signed-off-by: Ingo Molnar --- kernel/sched/deadline.c | 8 ++++---- kernel/sched/rt.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index affd97ec9f65..8f9b5af4e857 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -717,10 +717,6 @@ static void update_curr_dl(struct rq *rq) if (!dl_task(curr) || !on_dl_rq(dl_se)) return; - /* Kick cpufreq (see the comment in linux/cpufreq.h). */ - if (cpu_of(rq) == smp_processor_id()) - cpufreq_trigger_update(rq_clock(rq)); - /* * Consumed budget is computed considering the time as * observed by schedulable tasks (excluding time spent @@ -736,6 +732,10 @@ static void update_curr_dl(struct rq *rq) return; } + /* kick cpufreq (see the comment in linux/cpufreq.h). */ + if (cpu_of(rq) == smp_processor_id()) + cpufreq_trigger_update(rq_clock(rq)); + schedstat_set(curr->se.statistics.exec_max, max(curr->se.statistics.exec_max, delta_exec)); diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index c41ea7ac1764..19e13060fcd5 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -953,14 +953,14 @@ static void update_curr_rt(struct rq *rq) if (curr->sched_class != &rt_sched_class) return; - /* Kick cpufreq (see the comment in linux/cpufreq.h). */ - if (cpu_of(rq) == smp_processor_id()) - cpufreq_trigger_update(rq_clock(rq)); - delta_exec = rq_clock_task(rq) - curr->se.exec_start; if (unlikely((s64)delta_exec <= 0)) return; + /* Kick cpufreq (see the comment in linux/cpufreq.h). */ + if (cpu_of(rq) == smp_processor_id()) + cpufreq_trigger_update(rq_clock(rq)); + schedstat_set(curr->se.statistics.exec_max, max(curr->se.statistics.exec_max, delta_exec)); -- GitLab From 4c63c2454eff996c5e27991221106eb511f7db38 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 29 Oct 2015 08:22:21 +0000 Subject: [PATCH 4896/9938] btrfs: bugfix: handle FS_IOC32_{GETFLAGS,SETFLAGS,GETVERSION} in btrfs_ioctl 32-bit ioctl uses these rather than the regular FS_IOC_* versions. They can be handled in btrfs using the same code. Without this, 32-bit {ch,ls}attr fail. Signed-off-by: Luke Dashjr Cc: stable@vger.kernel.org Reviewed-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 1 + fs/btrfs/file.c | 2 +- fs/btrfs/inode.c | 2 +- fs/btrfs/ioctl.c | 21 +++++++++++++++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 84a6a5b3384a..208d19938fdf 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -4122,6 +4122,7 @@ void btrfs_test_inode_set_ops(struct inode *inode); /* ioctl.c */ long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int btrfs_ioctl_get_supported_features(void __user *arg); void btrfs_update_iflags(struct inode *inode); void btrfs_inherit_iflags(struct inode *inode, struct inode *dir); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 8d7b5a45c005..751daacd268d 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2956,7 +2956,7 @@ const struct file_operations btrfs_file_operations = { .fallocate = btrfs_fallocate, .unlocked_ioctl = btrfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = btrfs_ioctl, + .compat_ioctl = btrfs_compat_ioctl, #endif .copy_file_range = btrfs_copy_file_range, .clone_file_range = btrfs_clone_file_range, diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2aaba58b4856..167fc3d49450 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10184,7 +10184,7 @@ static const struct file_operations btrfs_dir_file_operations = { .iterate = btrfs_real_readdir, .unlocked_ioctl = btrfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = btrfs_ioctl, + .compat_ioctl = btrfs_compat_ioctl, #endif .release = btrfs_release_file, .fsync = btrfs_sync_file, diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5a23806ae418..f545f81f642d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -5552,3 +5552,24 @@ long btrfs_ioctl(struct file *file, unsigned int return -ENOTTY; } + +#ifdef CONFIG_COMPAT +long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case FS_IOC32_GETFLAGS: + cmd = FS_IOC_GETFLAGS; + break; + case FS_IOC32_SETFLAGS: + cmd = FS_IOC_SETFLAGS; + break; + case FS_IOC32_GETVERSION: + cmd = FS_IOC_GETVERSION; + break; + default: + return -ENOIOCTLCMD; + } + + return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); +} +#endif -- GitLab From 1d4093d3b3a70b947822cca76d6e4132767ce089 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 07:36:54 +0100 Subject: [PATCH 4897/9938] locking/Documentation/lockdep: Fix spelling mistakes Signed-off-by: Eric Engestrom Signed-off-by: Peter Zijlstra (Intel) Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1461566229-4717-2-git-send-email-eric@engestrom.ch Signed-off-by: Ingo Molnar --- Documentation/locking/lockdep-design.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/locking/lockdep-design.txt b/Documentation/locking/lockdep-design.txt index 5001280e9d82..9de1c158d44c 100644 --- a/Documentation/locking/lockdep-design.txt +++ b/Documentation/locking/lockdep-design.txt @@ -97,7 +97,7 @@ between any two lock-classes: -> -> -The first rule comes from the fact the a hardirq-safe lock could be +The first rule comes from the fact that a hardirq-safe lock could be taken by a hardirq context, interrupting a hardirq-unsafe lock - and thus could result in a lock inversion deadlock. Likewise, a softirq-safe lock could be taken by an softirq context, interrupting a softirq-unsafe @@ -220,7 +220,7 @@ calculated, which hash is unique for every lock chain. The hash value, when the chain is validated for the first time, is then put into a hash table, which hash-table can be checked in a lockfree manner. If the locking chain occurs again later on, the hash table tells us that we -dont have to validate the chain again. +don't have to validate the chain again. Troubleshooting: ---------------- -- GitLab From a91326679f2a0a4c239cd643674fdcda28ee86be Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Mon, 7 Mar 2016 16:56:21 -0800 Subject: [PATCH 4898/9938] Btrfs: make mapping->writeback_index point to the last written page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If sequential writer is writing in the middle of the page and it just redirties the last written page by continuing from it. In the above case this can end up with seeking back to that firstly redirtied page after writing all the pages at the end of file because btrfs updates mapping->writeback_index to 1 past the current one. For non-cow filesystems, the cost is only about extra seek, while for cow filesystems such as btrfs, it means unnecessary fragments. To avoid it, we just need to continue writeback from the last written page. This also updates btrfs to behave like what write_cache_pages() does, ie, bail out immediately if there is an error in writepage(). Reported-by: Holger Hoffstätte Signed-off-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/extent_io.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d247fc0eea19..fd41a730d239 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3200,14 +3200,10 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page, return ret; } -static noinline void update_nr_written(struct page *page, - struct writeback_control *wbc, - unsigned long nr_written) +static void update_nr_written(struct page *page, struct writeback_control *wbc, + unsigned long nr_written) { wbc->nr_to_write -= nr_written; - if (wbc->range_cyclic || (wbc->nr_to_write > 0 && - wbc->range_start == 0 && wbc->range_end == LLONG_MAX)) - page->mapping->writeback_index = page->index + nr_written; } /* @@ -3926,6 +3922,8 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, int nr_pages; pgoff_t index; pgoff_t end; /* Inclusive */ + pgoff_t done_index; + int range_whole = 0; int scanned = 0; int tag; @@ -3948,6 +3946,8 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, } else { index = wbc->range_start >> PAGE_SHIFT; end = wbc->range_end >> PAGE_SHIFT; + if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) + range_whole = 1; scanned = 1; } if (wbc->sync_mode == WB_SYNC_ALL) @@ -3957,6 +3957,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, retry: if (wbc->sync_mode == WB_SYNC_ALL) tag_pages_for_writeback(mapping, index, end); + done_index = index; while (!done && !nr_to_write_done && (index <= end) && (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { @@ -3966,6 +3967,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; + done_index = page->index; /* * At this point we hold neither mapping->tree_lock nor * lock on the page itself: the page may be truncated or @@ -4009,6 +4011,20 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, } if (!err && ret < 0) err = ret; + if (ret < 0) { + /* + * done_index is set past this page, + * so media errors will not choke + * background writeout for the entire + * file. This has consequences for + * range_cyclic semantics (ie. it may + * not be suitable for data integrity + * writeout). + */ + done_index = page->index + 1; + done = 1; + break; + } /* * the filesystem may choose to bump up nr_to_write. @@ -4029,6 +4045,10 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, index = 0; goto retry; } + + if (wbc->range_cyclic || (wbc->nr_to_write > 0 && range_whole)) + mapping->writeback_index = done_index; + btrfs_add_delayed_iput(inode); return err; } -- GitLab From 894b36e35ae01186b77b083f3f67569a349062a6 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Mon, 7 Mar 2016 16:56:22 -0800 Subject: [PATCH 4899/9938] Btrfs: cleanup error handling in extent_write_cached_pages Now that we bail out immediately if ->writepage() returns an error, we don't need an extra error to retain the error code. Signed-off-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/extent_io.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index fd41a730d239..b67d6d24440b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3916,7 +3916,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, struct inode *inode = mapping->host; int ret = 0; int done = 0; - int err = 0; int nr_to_write_done = 0; struct pagevec pvec; int nr_pages; @@ -4009,8 +4008,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, unlock_page(page); ret = 0; } - if (!err && ret < 0) - err = ret; if (ret < 0) { /* * done_index is set past this page, @@ -4036,7 +4033,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, pagevec_release(&pvec); cond_resched(); } - if (!scanned && !done && !err) { + if (!scanned && !done) { /* * We hit the last page and there is more work to be done: wrap * back to the start of the file @@ -4050,7 +4047,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, mapping->writeback_index = done_index; btrfs_add_delayed_iput(inode); - return err; + return ret; } static void flush_epd_write_bio(struct extent_page_data *epd) -- GitLab From a2af23b7d7cb0de89570e97da84f6fb642e990a4 Mon Sep 17 00:00:00 2001 From: Chandan Rajendra Date: Mon, 4 Apr 2016 02:53:06 +0530 Subject: [PATCH 4900/9938] Btrfs: __btrfs_buffered_write: Pass valid file offset when releasing delalloc space The delalloc reserved space is calculated in terms of number of bytes used by an integral number of blocks. This is done by rounding down the value of 'pos' to the nearest multiple of sectorsize. The file offset value held by 'pos' variable may not be aligned to sectorsize and hence when passing it as an argument to btrfs_delalloc_release_space(), we may end up releasing larger delalloc space than we originally had reserved. Signed-off-by: Chandan Rajendra Signed-off-by: David Sterba --- fs/btrfs/file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 751daacd268d..af059c44684d 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1696,7 +1696,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, btrfs_end_write_no_snapshoting(root); btrfs_delalloc_release_metadata(inode, release_bytes); } else { - btrfs_delalloc_release_space(inode, pos, release_bytes); + btrfs_delalloc_release_space(inode, + round_down(pos, root->sectorsize), + release_bytes); } } -- GitLab From cf25ce518e8ef9d59b292e51193bed2b023a32da Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Mon, 14 Dec 2015 18:29:32 -0800 Subject: [PATCH 4901/9938] Btrfs: do not create empty block group if we have allocated data Now we force to create empty block group to keep data profile alive, however, in the below example, we eventually get an empty block group while we're trying to get more space for other types (metadata/system), - Before, block group "A": size=2G, used=1.2G block group "B": size=2G, used=512M - After "btrfs balance start -dusage=50 mount_point", block group "A": size=2G, used=(1.2+0.5)G block group "C": size=2G, used=0 Since there is no data in block group C, it won't be deleted automatically and we have to get the unused 2G until the next mount. Balance itself just moves data and doesn't remove data, so it's safe to not create such a empty block group if we already have data allocated in other block groups. Signed-off-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index bd0f45fb38c4..745a619241c7 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3402,6 +3402,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) u32 count_meta = 0; u32 count_sys = 0; int chunk_reserved = 0; + u64 bytes_used = 0; /* step one make some room on all the devices */ devices = &fs_info->fs_devices->devices; @@ -3540,7 +3541,13 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) goto loop; } - if ((chunk_type & BTRFS_BLOCK_GROUP_DATA) && !chunk_reserved) { + ASSERT(fs_info->data_sinfo); + spin_lock(&fs_info->data_sinfo->lock); + bytes_used = fs_info->data_sinfo->bytes_used; + spin_unlock(&fs_info->data_sinfo->lock); + + if ((chunk_type & BTRFS_BLOCK_GROUP_DATA) && + !chunk_reserved && !bytes_used) { trans = btrfs_start_transaction(chunk_root, 0); if (IS_ERR(trans)) { mutex_unlock(&fs_info->delete_unused_bgs_mutex); -- GitLab From 2a28900be20640fcd1e548b1e3bad79e8221fcf9 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 28 Apr 2016 10:40:09 +0200 Subject: [PATCH 4902/9938] udf: Export superblock magic to userspace Currently UDF superblock magic doesn't appear in any userspace header files and thus userspace apps have hard time checking for this fs. Let's export the magic to userspace as with any other filesystem. Signed-off-by: Jan Kara --- fs/udf/udf_sb.h | 4 +--- include/uapi/linux/magic.h | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 1f32c7bd9f57..27b5335730c9 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -3,9 +3,7 @@ #include #include - -/* Since UDF 2.01 is ISO 13346 based... */ -#define UDF_SUPER_MAGIC 0x15013346 +#include #define UDF_MAX_READ_VERSION 0x0250 #define UDF_MAX_WRITE_VERSION 0x0201 diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index 0de181ad73d5..546b38886e11 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -78,5 +78,7 @@ #define BTRFS_TEST_MAGIC 0x73727279 #define NSFS_MAGIC 0x6e736673 #define BPF_FS_MAGIC 0xcafe4a11 +/* Since UDF 2.01 is ISO 13346 based... */ +#define UDF_SUPER_MAGIC 0x15013346 #endif /* __LINUX_MAGIC_H__ */ -- GitLab From 5e0ec14e2f84b62182d9be00f2595302424a7e03 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 24 Apr 2016 23:02:09 +0100 Subject: [PATCH 4903/9938] pinctrl: sirf/atlas7: fix printk spelling fix spelling mistake, flaged -> flagged Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/pinctrl/sirf/pinctrl-atlas7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c index 3d233fc3448a..168c0f5d4079 100644 --- a/drivers/pinctrl/sirf/pinctrl-atlas7.c +++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c @@ -5798,7 +5798,7 @@ static void atlas7_gpio_handle_irq(struct irq_desc *desc) status = readl(ATLAS7_GPIO_INT_STATUS(bank)); if (!status) { - pr_warn("%s: gpio [%s] status %#x no interrupt is flaged\n", + pr_warn("%s: gpio [%s] status %#x no interrupt is flagged\n", __func__, gc->label, status); handle_bad_irq(desc); return; -- GitLab From 35fc7b7dacc1f9bd6bdb5190cd6d355b7c5414d2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 25 Apr 2016 20:26:50 +0100 Subject: [PATCH 4904/9938] IB/mlx4: printk fix fix spelling mistake, argumant -> argument Signed-off-by: Colin Ian King Reviewed-by: Bart Van Assche Signed-off-by: Jiri Kosina --- drivers/infiniband/hw/mlx4/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index f014eaf5969b..b01ef6eee6e8 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1601,7 +1601,7 @@ static int __mlx4_ib_create_flow(struct ib_qp *qp, struct ib_flow_attr *flow_att else if (ret == -ENXIO) pr_err("Device managed flow steering is disabled. Fail to register network rule.\n"); else if (ret) - pr_err("Invalid argumant. Fail to register network rule.\n"); + pr_err("Invalid argument. Fail to register network rule.\n"); mlx4_free_cmd_mailbox(mdev->dev, mailbox); return ret; -- GitLab From c01e01597cbd0cf0571c2b05bf9e2245afb4478d Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 20 Apr 2016 00:27:33 +0900 Subject: [PATCH 4905/9938] treewide: Fix typos in printk This patch fix spelling typos in printk from various part of the codes. Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Jiri Kosina --- arch/powerpc/kernel/mce.c | 2 +- drivers/clk/tegra/clk-tegra20.c | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 4 ++-- drivers/infiniband/hw/cxgb3/iwch_cm.c | 2 +- drivers/input/touchscreen/cyttsp4_core.c | 2 +- drivers/net/ethernet/broadcom/bgmac.c | 2 +- drivers/net/ethernet/freescale/fman/fman.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/health.c | 4 ++-- drivers/platform/mips/cpu_hwmon.c | 6 +++--- drivers/scsi/qla2xxx/qla_sup.c | 2 +- drivers/target/iscsi/iscsi_target_auth.c | 2 +- drivers/watchdog/watchdog_core.c | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index b2eb4686bd8f..671fd5122406 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -284,7 +284,7 @@ void machine_check_print_event_info(struct machine_check_event *evt) printk("%s Effective address: %016llx\n", level, evt->u.ue_error.effective_address); if (evt->u.ue_error.physical_address_provided) - printk("%s Physial address: %016llx\n", + printk("%s Physical address: %016llx\n", level, evt->u.ue_error.physical_address); break; case MCE_ERROR_TYPE_SLB: diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 7ad63837694f..837e5cbd60e9 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -623,7 +623,7 @@ static unsigned int tegra20_get_pll_ref_div(void) case OSC_CTRL_PLL_REF_DIV_4: return 4; default: - pr_err("Invalied pll ref divider %d\n", pll_ref_div); + pr_err("Invalid pll ref divider %d\n", pll_ref_div); BUG(); } return 0; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 09198d0b5814..9c54f1160614 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -778,9 +778,9 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m) debug.state[0] == debug.state[1]) { seq_puts(m, "seems to be stuck\n"); } else if (debug.address[0] == debug.address[1]) { - seq_puts(m, "adress is constant\n"); + seq_puts(m, "address is constant\n"); } else { - seq_puts(m, "is runing\n"); + seq_puts(m, "is running\n"); } seq_printf(m, "\t address 0: 0x%08x\n", debug.address[0]); diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index d403231a4aff..3e8431b5cad7 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -367,7 +367,7 @@ static void arp_failure_discard(struct t3cdev *dev, struct sk_buff *skb) */ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb) { - printk(KERN_ERR MOD "ARP failure duing connect\n"); + printk(KERN_ERR MOD "ARP failure during connect\n"); kfree_skb(skb); } diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index 5ed31057430c..44deca88c579 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -1499,7 +1499,7 @@ static int cyttsp4_core_sleep_(struct cyttsp4 *cd) if (IS_BOOTLOADER(mode[0], mode[1])) { mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Device in BOOTLADER mode.\n", __func__); + dev_err(cd->dev, "%s: Device in BOOTLOADER mode.\n", __func__); rc = -EINVAL; goto error; } diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 99b30a952b38..718cd69db708 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1515,7 +1515,7 @@ static int bgmac_mii_register(struct bgmac *bgmac) phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link, PHY_INTERFACE_MODE_MII); if (IS_ERR(phy_dev)) { - bgmac_err(bgmac, "PHY connecton failed\n"); + bgmac_err(bgmac, "PHY connection failed\n"); err = PTR_ERR(phy_dev); goto err_unregister_bus; } diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c index ea83712a6d62..bcb9dccada4d 100644 --- a/drivers/net/ethernet/freescale/fman/fman.c +++ b/drivers/net/ethernet/freescale/fman/fman.c @@ -2772,7 +2772,7 @@ static struct fman *read_dts_node(struct platform_device *of_dev) /* Get the FM address */ res = platform_get_resource(of_dev, IORESOURCE_MEM, 0); if (!res) { - dev_err(&of_dev->dev, "%s: Can't get FMan memory resouce\n", + dev_err(&of_dev->dev, "%s: Can't get FMan memory resource\n", __func__); goto fman_node_put; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index f5deb642d0d6..42d16b9458e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -176,11 +176,11 @@ static const char *hsynd_str(u8 synd) case MLX5_HEALTH_SYNDR_EQ_ERR: return "EQ error"; case MLX5_HEALTH_SYNDR_EQ_INV: - return "Invalid EQ refrenced"; + return "Invalid EQ referenced"; case MLX5_HEALTH_SYNDR_FFSER_ERR: return "FFSER error"; case MLX5_HEALTH_SYNDR_HIGH_TEMP: - return "High temprature"; + return "High temperature"; default: return "unrecognized error"; } diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c index 0f6c63e17049..4993e19f1531 100644 --- a/drivers/platform/mips/cpu_hwmon.c +++ b/drivers/platform/mips/cpu_hwmon.c @@ -80,13 +80,13 @@ static const struct attribute *hwmon_cputemp2[] = { static ssize_t cpu0_temp_label(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "CPU 0 Temprature\n"); + return sprintf(buf, "CPU 0 Temperature\n"); } static ssize_t cpu1_temp_label(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "CPU 1 Temprature\n"); + return sprintf(buf, "CPU 1 Temperature\n"); } static ssize_t get_cpu0_temp(struct device *dev, @@ -169,7 +169,7 @@ static int __init loongson_hwmon_init(void) ret = create_sysfs_cputemp_files(&cpu_hwmon_dev->kobj); if (ret) { - pr_err("fail to create cpu temprature interface!\n"); + pr_err("fail to create cpu temperature interface!\n"); goto fail_create_sysfs_cputemp_files; } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 5e9392316425..9f6012b78e56 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -3222,7 +3222,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha) ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE); if (!ha->fcp_prio_cfg) { ql_log(ql_log_warn, vha, 0x00d5, - "Unable to allocate memory for fcp priorty data (%x).\n", + "Unable to allocate memory for fcp priority data (%x).\n", FCP_PRIO_CFG_SIZE); return QLA_FUNCTION_FAILED; } diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index 667406fcf4d3..e116f0e845c0 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -293,7 +293,7 @@ static int chap_server_compute_md5( pr_debug("[server] MD5 Digests do not match!\n\n"); goto out; } else - pr_debug("[server] MD5 Digests match, CHAP connetication" + pr_debug("[server] MD5 Digests match, CHAP connection" " successful.\n\n"); /* * One way authentication has succeeded, return now if mutual diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index c1658fe73d58..981a668b17e3 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -262,7 +262,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd) ret = register_restart_handler(&wdd->restart_nb); if (ret) - pr_warn("watchog%d: Cannot register restart handler (%d)\n", + pr_warn("watchdog%d: Cannot register restart handler (%d)\n", wdd->id, ret); } -- GitLab From e4cef28bff0dce91136c01e86463b780498cf30f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 25 Apr 2016 22:37:16 +0100 Subject: [PATCH 4906/9938] cpupowerutils: bench: fix "average" fix spelling mistake, avarage -> average Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- tools/power/cpupower/bench/README-BENCH | 2 +- tools/power/cpupower/bench/benchmark.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/power/cpupower/bench/README-BENCH b/tools/power/cpupower/bench/README-BENCH index 8093ec738170..97727aed61cc 100644 --- a/tools/power/cpupower/bench/README-BENCH +++ b/tools/power/cpupower/bench/README-BENCH @@ -113,7 +113,7 @@ cpufreq-bench Command Usage -c, --cpu= CPU Number to use, starting at 0 -p, --prio= scheduler priority, HIGH, LOW or DEFAULT -g, --governor= cpufreq governor to test --n, --cycles= load/sleep cycles to get an avarage value to compare +-n, --cycles= load/sleep cycles to get an average value to compare -r, --rounds load/sleep rounds -f, --file= config file to use -o, --output= output dir, must exist diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c index 81b1c48607d9..429d51ab8031 100644 --- a/tools/power/cpupower/bench/benchmark.c +++ b/tools/power/cpupower/bench/benchmark.c @@ -130,7 +130,7 @@ void start_benchmark(struct config *config) _round, load_time, sleep_time); if (config->verbose) - printf("avarage: %lius, rps:%li\n", + printf("average: %lius, rps:%li\n", load_time / calculations, 1000000 * calculations / load_time); @@ -177,7 +177,7 @@ void start_benchmark(struct config *config) progress_time += sleep_time + load_time; - /* compare the avarage sleep/load cycles */ + /* compare the average sleep/load cycles */ fprintf(config->output, "%li ", powersave_time / config->cycles); fprintf(config->output, "%.3f\n", -- GitLab From e7720af5f9ac914577e2b810d5c004cdf395fd82 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 26 Apr 2016 10:22:05 -0700 Subject: [PATCH 4907/9938] locking/Documentation: Add disclaimer It appears people are reading this document as a requirements list for building hardware. This is not the intent of this document. Nor is it particularly suited for this purpose. The primary purpose of this document is our collective attempt to define a set of primitives that (hopefully) allow us to write correct code on the myriad of SMP platforms Linux supports. Its a definite work in progress as our understanding of these platforms, and memory ordering in general, progresses. Nor does being mentioned in this document mean we think its a particularly good idea; the data dependency barrier required by Alpha being a prime example. Yes we have it, no you're insane to require it when building new hardware. Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Paul E. McKenney Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: corbet@lwn.net Cc: dave@stgolabs.net Cc: dhowells@redhat.com Cc: linux-doc@vger.kernel.org Cc: will.deacon@arm.com Link: http://lkml.kernel.org/r/1461691328-5429-1-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index a9454b1c73bd..fb2dd35a823a 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -4,8 +4,24 @@ By: David Howells Paul E. McKenney + Will Deacon + Peter Zijlstra -Contents: +========== +DISCLAIMER +========== + +This document is not a specification; it is intentionally (for the sake of +brevity) and unintentionally (due to being human) incomplete. This document is +meant as a guide to using the various memory barriers provided by Linux, but +in case of any doubt (and there are many) please ask. + +To repeat, this document is not a specification of what Linux expects from +hardware. + +======== +CONTENTS +======== (*) Abstract memory access model. -- GitLab From 8d4840e84871847ee1bae56a776907d08a9265f7 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 26 Apr 2016 10:22:06 -0700 Subject: [PATCH 4908/9938] locking/Documentation: State purpose of memory-barriers.txt There has been some confusion about the purpose of memory-barriers.txt, so this commit adds a statement of purpose. Signed-off-by: David Howells Signed-off-by: Paul E. McKenney Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: corbet@lwn.net Cc: dave@stgolabs.net Cc: linux-doc@vger.kernel.org Cc: will.deacon@arm.com Link: http://lkml.kernel.org/r/1461691328-5429-2-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index fb2dd35a823a..8b11e54238bf 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -19,6 +19,22 @@ in case of any doubt (and there are many) please ask. To repeat, this document is not a specification of what Linux expects from hardware. +The purpose of this document is twofold: + + (1) to specify the minimum functionality that one can rely on for any + particular barrier, and + + (2) to provide a guide as to how to use the barriers that are available. + +Note that an architecture can provide more than the minimum requirement +for any particular barrier, but if the architecure provides less than +that, that architecture is incorrect. + +Note also that it is possible that a barrier may be a no-op for an +architecture because the way that arch works renders an explicit barrier +unnecessary in that case. + + ======== CONTENTS ======== -- GitLab From 3cfe2e8bc1cf74d78df6fe5ca3a1e1805472a004 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 26 Apr 2016 10:22:07 -0700 Subject: [PATCH 4909/9938] locking/Documentation: Clarify that ACQUIRE applies to loads, RELEASE applies to stores For compound atomics performing both a load and a store operation, make it clear that _acquire and _release variants refer only to the load and store portions of compound atomic. For example, xchg_acquire is an xchg operation where the load takes on ACQUIRE semantics. Signed-off-by: Will Deacon Signed-off-by: Paul E. McKenney Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: corbet@lwn.net Cc: dave@stgolabs.net Cc: dhowells@redhat.com Cc: linux-doc@vger.kernel.org Link: http://lkml.kernel.org/r/1461691328-5429-3-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 8b11e54238bf..147ae8ec836f 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -498,6 +498,11 @@ And a couple of implicit varieties: This means that ACQUIRE acts as a minimal "acquire" operation and RELEASE acts as a minimal "release" operation. +A subset of the atomic operations described in atomic_ops.txt have ACQUIRE +and RELEASE variants in addition to fully-ordered and relaxed (no barrier +semantics) definitions. For compound atomics performing both a load and a +store, ACQUIRE semantics apply only to the load and RELEASE semantics apply +only to the store portion of the operation. Memory barriers are only required where there's a possibility of interaction between two CPUs or between a CPU and a device. If it can be guaranteed that -- GitLab From 5db4298133d99b3dfc60d6899ac9df169769c899 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 26 Apr 2016 10:22:08 -0700 Subject: [PATCH 4910/9938] lcoking/locktorture: Simplify the torture_runnable computation This commit replaces an #ifdef with IS_ENABLED(), saving five lines. Signed-off-by: Paul E. McKenney Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: corbet@lwn.net Cc: dave@stgolabs.net Cc: dhowells@redhat.com Cc: linux-doc@vger.kernel.org Cc: will.deacon@arm.com Link: http://lkml.kernel.org/r/1461691328-5429-4-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- kernel/locking/locktorture.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index d066a50dc87e..f8c5af52a131 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -75,12 +75,7 @@ struct lock_stress_stats { long n_lock_acquired; }; -#if defined(MODULE) -#define LOCKTORTURE_RUNNABLE_INIT 1 -#else -#define LOCKTORTURE_RUNNABLE_INIT 0 -#endif -int torture_runnable = LOCKTORTURE_RUNNABLE_INIT; +int torture_runnable = IS_ENABLED(MODULE); module_param(torture_runnable, int, 0444); MODULE_PARM_DESC(torture_runnable, "Start locktorture at module init"); -- GitLab From 6951c585228112a299e8d2b023ee4953831bd6b4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 24 Apr 2016 23:28:48 +0100 Subject: [PATCH 4911/9938] memstick: trivial fix of spelling mistake on management fix spelling mistake, managment -> management in literal strings, in a variable and a macro. Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/memstick/core/ms_block.c | 16 ++++++++-------- drivers/memstick/core/ms_block.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index 84abf9d3c24e..3cd68152ddf8 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -1220,7 +1220,7 @@ static int msb_read_boot_blocks(struct msb_data *msb) } if (extra.management_flag & MEMSTICK_MANAGEMENT_SYSFLG) { - dbg("managment flag doesn't indicate boot block %d", + dbg("management flag doesn't indicate boot block %d", pba); continue; } @@ -1367,7 +1367,7 @@ static int msb_ftl_initialize(struct msb_data *msb) static int msb_ftl_scan(struct msb_data *msb) { u16 pba, lba, other_block; - u8 overwrite_flag, managment_flag, other_overwrite_flag; + u8 overwrite_flag, management_flag, other_overwrite_flag; int error; struct ms_extra_data_register extra; u8 *overwrite_flags = kzalloc(msb->block_count, GFP_KERNEL); @@ -1409,7 +1409,7 @@ static int msb_ftl_scan(struct msb_data *msb) } lba = be16_to_cpu(extra.logical_address); - managment_flag = extra.management_flag; + management_flag = extra.management_flag; overwrite_flag = extra.overwrite_flag; overwrite_flags[pba] = overwrite_flag; @@ -1421,16 +1421,16 @@ static int msb_ftl_scan(struct msb_data *msb) } /* Skip system/drm blocks */ - if ((managment_flag & MEMSTICK_MANAGMENT_FLAG_NORMAL) != - MEMSTICK_MANAGMENT_FLAG_NORMAL) { - dbg("pba %05d -> [reserved managment flag %02x]", - pba, managment_flag); + if ((management_flag & MEMSTICK_MANAGEMENT_FLAG_NORMAL) != + MEMSTICK_MANAGEMENT_FLAG_NORMAL) { + dbg("pba %05d -> [reserved management flag %02x]", + pba, management_flag); msb_mark_block_used(msb, pba); continue; } /* Erase temporary tables */ - if (!(managment_flag & MEMSTICK_MANAGEMENT_ATFLG)) { + if (!(management_flag & MEMSTICK_MANAGEMENT_ATFLG)) { dbg("pba %05d -> [temp table] - will erase", pba); msb_mark_block_used(msb, pba); diff --git a/drivers/memstick/core/ms_block.h b/drivers/memstick/core/ms_block.h index c75198dbf139..53962c3b21df 100644 --- a/drivers/memstick/core/ms_block.h +++ b/drivers/memstick/core/ms_block.h @@ -47,7 +47,7 @@ #define MEMSTICK_OV_PG_NORMAL \ (MEMSTICK_OVERWRITE_PGST1 | MEMSTICK_OVERWRITE_PGST0) -#define MEMSTICK_MANAGMENT_FLAG_NORMAL \ +#define MEMSTICK_MANAGEMENT_FLAG_NORMAL \ (MEMSTICK_MANAGEMENT_SYSFLG | \ MEMSTICK_MANAGEMENT_SCMS1 | \ MEMSTICK_MANAGEMENT_SCMS0) \ -- GitLab From 6cf86a006be9f2a77434d5a06ea289719815ad7c Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:29 +0800 Subject: [PATCH 4912/9938] btrfs: create a helper function to read the disk super A part of code from btrfs_scan_one_device() is moved to a new function btrfs_read_disk_super(), so that former function looks cleaner. (In this process it also moves the code which ensures null terminating label). So this creates easy opportunity to merge various duplicate codes on read disk super. Earlier attempt to merge duplicate codes highlighted that there were some issues for which there are duplicate codes (to read disk super), however it was not clear what was the issue. So until we figure that out, its better to keep them in a separate functions. Signed-off-by: Anand Jain [ use GFP_KERNEL, PAGE_CACHE_ removal related fixups ] Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 87 +++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index bd0f45fb38c4..5006683283ae 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -988,6 +988,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, return ret; } +void btrfs_release_disk_super(struct page *page) +{ + kunmap(page); + put_page(page); +} + +int btrfs_read_disk_super(struct block_device *bdev, u64 bytenr, + struct page **page, struct btrfs_super_block **disk_super) +{ + void *p; + pgoff_t index; + + /* make sure our super fits in the device */ + if (bytenr + PAGE_SIZE >= i_size_read(bdev->bd_inode)) + return 1; + + /* make sure our super fits in the page */ + if (sizeof(**disk_super) > PAGE_SIZE) + return 1; + + /* make sure our super doesn't straddle pages on disk */ + index = bytenr >> PAGE_SHIFT; + if ((bytenr + sizeof(**disk_super) - 1) >> PAGE_SHIFT != index) + return 1; + + /* pull in the page with our super */ + *page = read_cache_page_gfp(bdev->bd_inode->i_mapping, + index, GFP_KERNEL); + + if (IS_ERR_OR_NULL(*page)) + return 1; + + p = kmap(*page); + + /* align our pointer to the offset of the super block */ + *disk_super = p + (bytenr & ~PAGE_MASK); + + if (btrfs_super_bytenr(*disk_super) != bytenr || + btrfs_super_magic(*disk_super) != BTRFS_MAGIC) { + btrfs_release_disk_super(*page); + return 1; + } + + if ((*disk_super)->label[0] && + (*disk_super)->label[BTRFS_LABEL_SIZE - 1]) + (*disk_super)->label[BTRFS_LABEL_SIZE - 1] = '\0'; + + return 0; +} + /* * Look for a btrfs signature on a device. This may be called out of the mount path * and we are not allowed to call set_blocksize during the scan. The superblock @@ -999,13 +1049,11 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, struct btrfs_super_block *disk_super; struct block_device *bdev; struct page *page; - void *p; int ret = -EINVAL; u64 devid; u64 transid; u64 total_devices; u64 bytenr; - pgoff_t index; /* * we would like to check all the supers, but that would make @@ -1018,41 +1066,14 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, mutex_lock(&uuid_mutex); bdev = blkdev_get_by_path(path, flags, holder); - if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); goto error; } - /* make sure our super fits in the device */ - if (bytenr + PAGE_SIZE >= i_size_read(bdev->bd_inode)) - goto error_bdev_put; - - /* make sure our super fits in the page */ - if (sizeof(*disk_super) > PAGE_SIZE) - goto error_bdev_put; - - /* make sure our super doesn't straddle pages on disk */ - index = bytenr >> PAGE_SHIFT; - if ((bytenr + sizeof(*disk_super) - 1) >> PAGE_SHIFT != index) - goto error_bdev_put; - - /* pull in the page with our super */ - page = read_cache_page_gfp(bdev->bd_inode->i_mapping, - index, GFP_NOFS); - - if (IS_ERR_OR_NULL(page)) + if (btrfs_read_disk_super(bdev, bytenr, &page, &disk_super)) goto error_bdev_put; - p = kmap(page); - - /* align our pointer to the offset of the super block */ - disk_super = p + (bytenr & ~PAGE_MASK); - - if (btrfs_super_bytenr(disk_super) != bytenr || - btrfs_super_magic(disk_super) != BTRFS_MAGIC) - goto error_unmap; - devid = btrfs_stack_device_id(&disk_super->dev_item); transid = btrfs_super_generation(disk_super); total_devices = btrfs_super_num_devices(disk_super); @@ -1060,8 +1081,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, ret = device_list_add(path, disk_super, devid, fs_devices_ret); if (ret > 0) { if (disk_super->label[0]) { - if (disk_super->label[BTRFS_LABEL_SIZE - 1]) - disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0'; printk(KERN_INFO "BTRFS: device label %s ", disk_super->label); } else { printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid); @@ -1073,9 +1092,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, if (!ret && fs_devices_ret) (*fs_devices_ret)->total_devices = total_devices; -error_unmap: - kunmap(page); - put_page(page); + btrfs_release_disk_super(page); error_bdev_put: blkdev_put(bdev, flags); -- GitLab From f1fa7f264250f2cb60119aca3fd114c3f47070c2 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:33 +0800 Subject: [PATCH 4913/9938] btrfs: create helper function __check_raid_min_devices() move a section of btrfs_rm_device() code to check for min number of the devices into the function __check_raid_min_devices() Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 51 +++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5006683283ae..db781d0d3678 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1705,23 +1705,20 @@ static int btrfs_rm_dev_item(struct btrfs_root *root, return ret; } -int btrfs_rm_device(struct btrfs_root *root, char *device_path) +static int __check_raid_min_devices(struct btrfs_root *root) { - struct btrfs_device *device; - struct btrfs_device *next_device; - struct block_device *bdev; - struct buffer_head *bh = NULL; - struct btrfs_super_block *disk_super; - struct btrfs_fs_devices *cur_devices; u64 all_avail; - u64 devid; u64 num_devices; - u8 *dev_uuid; unsigned seq; int ret = 0; - bool clear_super = false; - mutex_lock(&uuid_mutex); + num_devices = root->fs_info->fs_devices->num_devices; + btrfs_dev_replace_lock(&root->fs_info->dev_replace, 0); + if (btrfs_dev_replace_is_ongoing(&root->fs_info->dev_replace)) { + WARN_ON(num_devices < 1); + num_devices--; + } + btrfs_dev_replace_unlock(&root->fs_info->dev_replace, 0); do { seq = read_seqbegin(&root->fs_info->profiles_lock); @@ -1731,14 +1728,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) root->fs_info->avail_metadata_alloc_bits; } while (read_seqretry(&root->fs_info->profiles_lock, seq)); - num_devices = root->fs_info->fs_devices->num_devices; - btrfs_dev_replace_lock(&root->fs_info->dev_replace, 0); - if (btrfs_dev_replace_is_ongoing(&root->fs_info->dev_replace)) { - WARN_ON(num_devices < 1); - num_devices--; - } - btrfs_dev_replace_unlock(&root->fs_info->dev_replace, 0); - if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && num_devices <= 4) { ret = BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET; goto out; @@ -1760,6 +1749,30 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) goto out; } +out: + return ret; +} + +int btrfs_rm_device(struct btrfs_root *root, char *device_path) +{ + struct btrfs_device *device; + struct btrfs_device *next_device; + struct block_device *bdev; + struct buffer_head *bh = NULL; + struct btrfs_super_block *disk_super; + struct btrfs_fs_devices *cur_devices; + u64 devid; + u64 num_devices; + u8 *dev_uuid; + int ret = 0; + bool clear_super = false; + + mutex_lock(&uuid_mutex); + + ret = __check_raid_min_devices(root); + if (ret) + goto out; + if (strcmp(device_path, "missing") == 0) { struct list_head *devices; struct btrfs_device *tmp; -- GitLab From bd45ffbcb1f082e3c5a0bd56b1d7310d8b707ffb Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:34 +0800 Subject: [PATCH 4914/9938] btrfs: clean up and optimize __check_raid_min_device() __check_raid_min_device() which was pealed from btrfs_rm_device() maintianed its original code to show the block move. This patch cleans up __check_raid_min_device(). Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index db781d0d3678..5538dc78c72e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1705,52 +1705,47 @@ static int btrfs_rm_dev_item(struct btrfs_root *root, return ret; } -static int __check_raid_min_devices(struct btrfs_root *root) +static int __check_raid_min_devices(struct btrfs_fs_info *fs_info) { u64 all_avail; u64 num_devices; unsigned seq; - int ret = 0; - num_devices = root->fs_info->fs_devices->num_devices; - btrfs_dev_replace_lock(&root->fs_info->dev_replace, 0); - if (btrfs_dev_replace_is_ongoing(&root->fs_info->dev_replace)) { + num_devices = fs_info->fs_devices->num_devices; + btrfs_dev_replace_lock(&fs_info->dev_replace, 0); + if (btrfs_dev_replace_is_ongoing(&fs_info->dev_replace)) { WARN_ON(num_devices < 1); num_devices--; } - btrfs_dev_replace_unlock(&root->fs_info->dev_replace, 0); + btrfs_dev_replace_unlock(&fs_info->dev_replace, 0); do { - seq = read_seqbegin(&root->fs_info->profiles_lock); + seq = read_seqbegin(&fs_info->profiles_lock); - all_avail = root->fs_info->avail_data_alloc_bits | - root->fs_info->avail_system_alloc_bits | - root->fs_info->avail_metadata_alloc_bits; - } while (read_seqretry(&root->fs_info->profiles_lock, seq)); + all_avail = fs_info->avail_data_alloc_bits | + fs_info->avail_system_alloc_bits | + fs_info->avail_metadata_alloc_bits; + } while (read_seqretry(&fs_info->profiles_lock, seq)); if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && num_devices <= 4) { - ret = BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET; - goto out; + return BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET; } if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && num_devices <= 2) { - ret = BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET; - goto out; + return BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET; } if ((all_avail & BTRFS_BLOCK_GROUP_RAID5) && - root->fs_info->fs_devices->rw_devices <= 2) { - ret = BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET; - goto out; + fs_info->fs_devices->rw_devices <= 2) { + return BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET; } + if ((all_avail & BTRFS_BLOCK_GROUP_RAID6) && - root->fs_info->fs_devices->rw_devices <= 3) { - ret = BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET; - goto out; + fs_info->fs_devices->rw_devices <= 3) { + return BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET; } -out: - return ret; + return 0; } int btrfs_rm_device(struct btrfs_root *root, char *device_path) @@ -1769,7 +1764,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) mutex_lock(&uuid_mutex); - ret = __check_raid_min_devices(root); + ret = __check_raid_min_devices(root->fs_info); if (ret) goto out; -- GitLab From 24e0474b59538cdb9d2b7318ec7c7ae9f6faf85d Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:35 +0800 Subject: [PATCH 4915/9938] btrfs: create helper btrfs_find_device_by_user_input() The patch renames btrfs_dev_replace_find_srcdev() to btrfs_find_device_by_user_input() and moves it to volumes.c, so that delete device can use it. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 24 +----------------------- fs/btrfs/volumes.c | 19 +++++++++++++++++++ fs/btrfs/volumes.h | 3 +++ 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 26bcb487f958..7ad8ae994ca0 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -44,9 +44,6 @@ static void btrfs_dev_replace_update_device_in_mapping_tree( struct btrfs_fs_info *fs_info, struct btrfs_device *srcdev, struct btrfs_device *tgtdev); -static int btrfs_dev_replace_find_srcdev(struct btrfs_root *root, u64 srcdevid, - char *srcdev_name, - struct btrfs_device **device); static u64 __btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info); static int btrfs_dev_replace_kthread(void *data); static int btrfs_dev_replace_continue_on_mount(struct btrfs_fs_info *fs_info); @@ -329,7 +326,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, /* the disk copy procedure reuses the scrub code */ mutex_lock(&fs_info->volume_mutex); - ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid, + ret = btrfs_find_device_by_user_input(root, args->start.srcdevid, args->start.srcdev_name, &src_device); if (ret) { @@ -626,25 +623,6 @@ static void btrfs_dev_replace_update_device_in_mapping_tree( write_unlock(&em_tree->lock); } -static int btrfs_dev_replace_find_srcdev(struct btrfs_root *root, u64 srcdevid, - char *srcdev_name, - struct btrfs_device **device) -{ - int ret; - - if (srcdevid) { - ret = 0; - *device = btrfs_find_device(root->fs_info, srcdevid, NULL, - NULL); - if (!*device) - ret = -ENOENT; - } else { - ret = btrfs_find_device_missing_or_by_path(root, srcdev_name, - device); - } - return ret; -} - void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info, struct btrfs_ioctl_dev_replace_args *args) { diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5538dc78c72e..ab28d9dc1b0d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2126,6 +2126,25 @@ int btrfs_find_device_missing_or_by_path(struct btrfs_root *root, } } +int btrfs_find_device_by_user_input(struct btrfs_root *root, u64 srcdevid, + char *srcdev_name, + struct btrfs_device **device) +{ + int ret; + + if (srcdevid) { + ret = 0; + *device = btrfs_find_device(root->fs_info, srcdevid, NULL, + NULL); + if (!*device) + ret = -ENOENT; + } else { + ret = btrfs_find_device_missing_or_by_path(root, srcdev_name, + device); + } + return ret; +} + /* * does all the dirty work required for changing file system's UUID. */ diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 1939ebde63df..508739314e43 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -448,6 +448,9 @@ void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices, int step); int btrfs_find_device_missing_or_by_path(struct btrfs_root *root, char *device_path, struct btrfs_device **device); +int btrfs_find_device_by_user_input(struct btrfs_root *root, u64 srcdevid, + char *srcdev_name, + struct btrfs_device **device); struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, const u64 *devid, const u8 *uuid); -- GitLab From 24fc572fe456c02ff4136c07861a3edd4b8de683 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:36 +0800 Subject: [PATCH 4916/9938] btrfs: make use of btrfs_find_device_by_user_input() btrfs_rm_device() has a section of the code which can be replaced btrfs_find_device_by_user_input() Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 100 +++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 63 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index ab28d9dc1b0d..40bbe0a2715b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1752,13 +1752,11 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) { struct btrfs_device *device; struct btrfs_device *next_device; - struct block_device *bdev; + struct block_device *bdev = NULL; struct buffer_head *bh = NULL; - struct btrfs_super_block *disk_super; + struct btrfs_super_block *disk_super = NULL; struct btrfs_fs_devices *cur_devices; - u64 devid; u64 num_devices; - u8 *dev_uuid; int ret = 0; bool clear_super = false; @@ -1768,57 +1766,19 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) if (ret) goto out; - if (strcmp(device_path, "missing") == 0) { - struct list_head *devices; - struct btrfs_device *tmp; - - device = NULL; - devices = &root->fs_info->fs_devices->devices; - /* - * It is safe to read the devices since the volume_mutex - * is held. - */ - list_for_each_entry(tmp, devices, dev_list) { - if (tmp->in_fs_metadata && - !tmp->is_tgtdev_for_dev_replace && - !tmp->bdev) { - device = tmp; - break; - } - } - bdev = NULL; - bh = NULL; - disk_super = NULL; - if (!device) { - ret = BTRFS_ERROR_DEV_MISSING_NOT_FOUND; - goto out; - } - } else { - ret = btrfs_get_bdev_and_sb(device_path, - FMODE_WRITE | FMODE_EXCL, - root->fs_info->bdev_holder, 0, - &bdev, &bh); - if (ret) - goto out; - disk_super = (struct btrfs_super_block *)bh->b_data; - devid = btrfs_stack_device_id(&disk_super->dev_item); - dev_uuid = disk_super->dev_item.uuid; - device = btrfs_find_device(root->fs_info, devid, dev_uuid, - disk_super->fsid); - if (!device) { - ret = -ENOENT; - goto error_brelse; - } - } + ret = btrfs_find_device_by_user_input(root, 0, device_path, + &device); + if (ret) + goto out; if (device->is_tgtdev_for_dev_replace) { ret = BTRFS_ERROR_DEV_TGT_REPLACE; - goto error_brelse; + goto out; } if (device->writeable && root->fs_info->fs_devices->rw_devices == 1) { ret = BTRFS_ERROR_DEV_ONLY_WRITABLE; - goto error_brelse; + goto out; } if (device->writeable) { @@ -1908,16 +1868,33 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) * at this point, the device is zero sized. We want to * remove it from the devices list and zero out the old super */ - if (clear_super && disk_super) { + if (clear_super) { u64 bytenr; int i; + if (!disk_super) { + ret = btrfs_get_bdev_and_sb(device_path, + FMODE_WRITE | FMODE_EXCL, + root->fs_info->bdev_holder, 0, + &bdev, &bh); + if (ret) { + /* + * It could be a failed device ok for clear_super + * to fail. So return success + */ + ret = 0; + goto out; + } + + disk_super = (struct btrfs_super_block *)bh->b_data; + } /* make sure this device isn't detected as part of * the FS anymore */ memset(&disk_super->magic, 0, sizeof(disk_super->magic)); set_buffer_dirty(bh); sync_dirty_buffer(bh); + brelse(bh); /* clear the mirror copies of super block on the disk * being removed, 0th copy is been taken care above and @@ -1929,7 +1906,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) i_size_read(bdev->bd_inode)) break; - brelse(bh); bh = __bread(bdev, bytenr / 4096, BTRFS_SUPER_INFO_SIZE); if (!bh) @@ -1939,32 +1915,30 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) if (btrfs_super_bytenr(disk_super) != bytenr || btrfs_super_magic(disk_super) != BTRFS_MAGIC) { + brelse(bh); continue; } memset(&disk_super->magic, 0, sizeof(disk_super->magic)); set_buffer_dirty(bh); sync_dirty_buffer(bh); + brelse(bh); } - } - ret = 0; - - if (bdev) { - /* Notify udev that device has changed */ - btrfs_kobject_uevent(bdev, KOBJ_CHANGE); + if (bdev) { + /* Notify udev that device has changed */ + btrfs_kobject_uevent(bdev, KOBJ_CHANGE); - /* Update ctime/mtime for device path for libblkid */ - update_dev_time(device_path); + /* Update ctime/mtime for device path for libblkid */ + update_dev_time(device_path); + blkdev_put(bdev, FMODE_READ | FMODE_EXCL); + } } -error_brelse: - brelse(bh); - if (bdev) - blkdev_put(bdev, FMODE_READ | FMODE_EXCL); out: mutex_unlock(&uuid_mutex); return ret; + error_undo: if (device->writeable) { lock_chunks(root); @@ -1973,7 +1947,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) device->fs_devices->rw_devices++; unlock_chunks(root); } - goto error_brelse; + goto out; } void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_fs_info *fs_info, -- GitLab From b3d1b1532ff9620ff5dba891a96f3e912005eb10 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:37 +0800 Subject: [PATCH 4917/9938] btrfs: enhance btrfs_find_device_by_user_input() to check device path The operation of device replace and device delete follows same steps upto some depth with in btrfs kernel, however they don't share codes. This enhancement will help replace and delete to share codes. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 4 ---- fs/btrfs/volumes.c | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 7ad8ae994ca0..fdd2880707df 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -320,10 +320,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root, return -EINVAL; } - if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') || - args->start.tgtdev_name[0] == '\0') - return -EINVAL; - /* the disk copy procedure reuses the scrub code */ mutex_lock(&fs_info->volume_mutex); ret = btrfs_find_device_by_user_input(root, args->start.srcdevid, diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 40bbe0a2715b..d74260567bea 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2113,6 +2113,9 @@ int btrfs_find_device_by_user_input(struct btrfs_root *root, u64 srcdevid, if (!*device) ret = -ENOENT; } else { + if (!srcdev_name || !srcdev_name[0]) + return -EINVAL; + ret = btrfs_find_device_missing_or_by_path(root, srcdev_name, device); } -- GitLab From 42b674271566c26692c32f4ec1f4b4cf14d5046f Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:38 +0800 Subject: [PATCH 4918/9938] btrfs: make use of btrfs_scratch_superblocks() in btrfs_rm_device() With the previous patches now the btrfs_scratch_superblocks() is ready to be used in btrfs_rm_device() so use it. Signed-off-by: Anand Jain [ use GFP_KERNEL ] Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 77 ++++++++-------------------------------------- 1 file changed, 13 insertions(+), 64 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d74260567bea..8264b06756e6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1752,13 +1752,11 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) { struct btrfs_device *device; struct btrfs_device *next_device; - struct block_device *bdev = NULL; - struct buffer_head *bh = NULL; - struct btrfs_super_block *disk_super = NULL; struct btrfs_fs_devices *cur_devices; u64 num_devices; int ret = 0; bool clear_super = false; + char *dev_name = NULL; mutex_lock(&uuid_mutex); @@ -1786,6 +1784,11 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) list_del_init(&device->dev_alloc_list); device->fs_devices->rw_devices--; unlock_chunks(root); + dev_name = kstrdup(device->name->str, GFP_KERNEL); + if (!dev_name) { + ret = -ENOMEM; + goto error_undo; + } clear_super = true; } @@ -1869,73 +1872,19 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) * remove it from the devices list and zero out the old super */ if (clear_super) { - u64 bytenr; - int i; - - if (!disk_super) { - ret = btrfs_get_bdev_and_sb(device_path, - FMODE_WRITE | FMODE_EXCL, - root->fs_info->bdev_holder, 0, - &bdev, &bh); - if (ret) { - /* - * It could be a failed device ok for clear_super - * to fail. So return success - */ - ret = 0; - goto out; - } - - disk_super = (struct btrfs_super_block *)bh->b_data; - } - /* make sure this device isn't detected as part of - * the FS anymore - */ - memset(&disk_super->magic, 0, sizeof(disk_super->magic)); - set_buffer_dirty(bh); - sync_dirty_buffer(bh); - brelse(bh); - - /* clear the mirror copies of super block on the disk - * being removed, 0th copy is been taken care above and - * the below would take of the rest - */ - for (i = 1; i < BTRFS_SUPER_MIRROR_MAX; i++) { - bytenr = btrfs_sb_offset(i); - if (bytenr + BTRFS_SUPER_INFO_SIZE >= - i_size_read(bdev->bd_inode)) - break; - - bh = __bread(bdev, bytenr / 4096, - BTRFS_SUPER_INFO_SIZE); - if (!bh) - continue; + struct block_device *bdev; - disk_super = (struct btrfs_super_block *)bh->b_data; - - if (btrfs_super_bytenr(disk_super) != bytenr || - btrfs_super_magic(disk_super) != BTRFS_MAGIC) { - brelse(bh); - continue; - } - memset(&disk_super->magic, 0, - sizeof(disk_super->magic)); - set_buffer_dirty(bh); - sync_dirty_buffer(bh); - brelse(bh); - } - - if (bdev) { - /* Notify udev that device has changed */ - btrfs_kobject_uevent(bdev, KOBJ_CHANGE); - - /* Update ctime/mtime for device path for libblkid */ - update_dev_time(device_path); + bdev = blkdev_get_by_path(dev_name, FMODE_READ | FMODE_EXCL, + root->fs_info->bdev_holder); + if (!IS_ERR(bdev)) { + btrfs_scratch_superblocks(bdev, dev_name); blkdev_put(bdev, FMODE_READ | FMODE_EXCL); } } out: + kfree(dev_name); + mutex_unlock(&uuid_mutex); return ret; -- GitLab From 6b526ed70cf189660d009ea6f17af77a9cca0f38 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:39 +0800 Subject: [PATCH 4919/9938] btrfs: introduce device delete by devid This introduces new ioctl BTRFS_IOC_RM_DEV_V2, which uses enhanced struct btrfs_ioctl_vol_args_v2 to carry devid as an user argument. The patch won't delete the old ioctl interface and so kernel remains backward compatible with user land progs. Test case/script: echo "0 $(blockdev --getsz /dev/sdf) linear /dev/sdf 0" | dmsetup create bad_disk mkfs.btrfs -f -d raid1 -m raid1 /dev/sdd /dev/sde /dev/mapper/bad_disk mount /dev/sdd /btrfs dmsetup suspend bad_disk echo "0 $(blockdev --getsz /dev/sdf) error /dev/sdf 0" | dmsetup load bad_disk dmsetup resume bad_disk echo "bad disk failed. now deleting/replacing" btrfs dev del 3 /btrfs echo $? btrfs fi show /btrfs umount /btrfs btrfs-show-super /dev/sdd | egrep num_device dmsetup remove bad_disk wipefs -a /dev/sdf Signed-off-by: Anand Jain Reported-by: Martin [ adjust messages, s/disk/device/ ] Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 58 +++++++++++++++++++++++++++++++++++++- fs/btrfs/volumes.c | 4 +-- fs/btrfs/volumes.h | 2 +- include/uapi/linux/btrfs.h | 14 ++++++++- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5a23806ae418..7cf0f6328d99 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2667,6 +2667,60 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) return ret; } +static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) +{ + struct btrfs_root *root = BTRFS_I(file_inode(file))->root; + struct btrfs_ioctl_vol_args_v2 *vol_args; + int ret; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + ret = mnt_want_write_file(file); + if (ret) + return ret; + + vol_args = memdup_user(arg, sizeof(*vol_args)); + if (IS_ERR(vol_args)) { + ret = PTR_ERR(vol_args); + goto err_drop; + } + + /* Check for compatibility reject unknown flags */ + if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS) + return -ENOTTY; + + if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, + 1)) { + ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; + goto out; + } + + mutex_lock(&root->fs_info->volume_mutex); + if (vol_args->flags & BTRFS_DEVICE_BY_ID) { + ret = btrfs_rm_device(root, NULL, vol_args->devid); + } else { + vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; + ret = btrfs_rm_device(root, vol_args->name, 0); + } + mutex_unlock(&root->fs_info->volume_mutex); + atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); + + if (!ret) { + if (vol_args->flags & BTRFS_DEVICE_BY_ID) + btrfs_info(root->fs_info, "device deleted: id %llu", + vol_args->devid); + else + btrfs_info(root->fs_info, "device deleted: %s", + vol_args->name); + } +out: + kfree(vol_args); +err_drop: + mnt_drop_write_file(file); + return ret; +} + static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) { struct btrfs_root *root = BTRFS_I(file_inode(file))->root; @@ -2695,7 +2749,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) } mutex_lock(&root->fs_info->volume_mutex); - ret = btrfs_rm_device(root, vol_args->name); + ret = btrfs_rm_device(root, vol_args->name, 0); mutex_unlock(&root->fs_info->volume_mutex); atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); @@ -5459,6 +5513,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_add_dev(root, argp); case BTRFS_IOC_RM_DEV: return btrfs_ioctl_rm_dev(file, argp); + case BTRFS_IOC_RM_DEV_V2: + return btrfs_ioctl_rm_dev_v2(file, argp); case BTRFS_IOC_FS_INFO: return btrfs_ioctl_fs_info(root, argp); case BTRFS_IOC_DEV_INFO: diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8264b06756e6..1421d711629f 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1748,7 +1748,7 @@ static int __check_raid_min_devices(struct btrfs_fs_info *fs_info) return 0; } -int btrfs_rm_device(struct btrfs_root *root, char *device_path) +int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid) { struct btrfs_device *device; struct btrfs_device *next_device; @@ -1764,7 +1764,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) if (ret) goto out; - ret = btrfs_find_device_by_user_input(root, 0, device_path, + ret = btrfs_find_device_by_user_input(root, devid, device_path, &device); if (ret) goto out; diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 508739314e43..c73d027e2f8b 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -454,7 +454,7 @@ int btrfs_find_device_by_user_input(struct btrfs_root *root, u64 srcdevid, struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, const u64 *devid, const u8 *uuid); -int btrfs_rm_device(struct btrfs_root *root, char *device_path); +int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid); void btrfs_cleanup_fs_uuids(void); int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len); int btrfs_grow_device(struct btrfs_trans_handle *trans, diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index dea893199257..396a4efca775 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -36,6 +36,13 @@ struct btrfs_ioctl_vol_args { #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) #define BTRFS_SUBVOL_RDONLY (1ULL << 1) #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) +#define BTRFS_DEVICE_BY_ID (1ULL << 3) +#define BTRFS_VOL_ARG_V2_FLAGS \ + (BTRFS_SUBVOL_CREATE_ASYNC | \ + BTRFS_SUBVOL_RDONLY | \ + BTRFS_SUBVOL_QGROUP_INHERIT | \ + BTRFS_DEVICE_BY_ID) + #define BTRFS_FSID_SIZE 16 #define BTRFS_UUID_SIZE 16 #define BTRFS_UUID_UNPARSED_SIZE 37 @@ -76,7 +83,10 @@ struct btrfs_ioctl_vol_args_v2 { }; __u64 unused[4]; }; - char name[BTRFS_SUBVOL_NAME_MAX + 1]; + union { + char name[BTRFS_SUBVOL_NAME_MAX + 1]; + u64 devid; + }; }; /* @@ -659,5 +669,7 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) struct btrfs_ioctl_feature_flags[2]) #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ struct btrfs_ioctl_feature_flags[3]) +#define BTRFS_IOC_RM_DEV_V2 _IOW(BTRFS_IOCTL_MAGIC, 58, \ + struct btrfs_ioctl_vol_args_v2) #endif /* _UAPI_LINUX_BTRFS_H */ -- GitLab From 02feae3c5525771878461b90edd2ba38fd3f5359 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Sat, 13 Feb 2016 10:01:40 +0800 Subject: [PATCH 4920/9938] btrfs: optimize check for stale device Optimize check for stale device to only be checked when there is device added or changed. If there is no update to the device, there is no need to call btrfs_free_stale_device(). Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1421d711629f..2fdd2d3322aa 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -699,7 +699,8 @@ static noinline int device_list_add(const char *path, * if there is new btrfs on an already registered device, * then remove the stale device entry. */ - btrfs_free_stale_device(device); + if (ret > 0) + btrfs_free_stale_device(device); *fs_devices_ret = fs_devices; -- GitLab From f47ab2588e424cb4898b75ace1e2323ddd18b990 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 15 Feb 2016 15:28:48 +0100 Subject: [PATCH 4921/9938] btrfs: rename __check_raid_min_devices Underscores are for special functions, use the full prefix for better stacktrace recognition. Reviewed-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 2fdd2d3322aa..9051b4472bea 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1706,7 +1706,7 @@ static int btrfs_rm_dev_item(struct btrfs_root *root, return ret; } -static int __check_raid_min_devices(struct btrfs_fs_info *fs_info) +static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info) { u64 all_avail; u64 num_devices; @@ -1761,7 +1761,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid) mutex_lock(&uuid_mutex); - ret = __check_raid_min_devices(root->fs_info); + ret = btrfs_check_raid_min_devices(root->fs_info); if (ret) goto out; -- GitLab From 3cc31a0d5bc77e35229671307eba5ea5c4c4cb9d Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 15 Feb 2016 16:00:26 +0100 Subject: [PATCH 4922/9938] btrfs: pass number of devices to btrfs_check_raid_min_devices Before this patch, btrfs_check_raid_min_devices would do an off-by-one check of the constraints and not the miminmum check, as its name suggests. This is not a problem if the only caller is device remove, but would be confusing for others. Add an argument with the exact number and let the caller(s) decide if this needs any adjustments, like when device replace is running. Reviewed-by: Anand Jain Tested-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9051b4472bea..e966f0ce07f8 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1706,20 +1706,17 @@ static int btrfs_rm_dev_item(struct btrfs_root *root, return ret; } -static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info) +/* + * Verify that @num_devices satisfies the RAID profile constraints in the whole + * filesystem. It's up to the caller to adjust that number regarding eg. device + * replace. + */ +static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info, + u64 num_devices) { u64 all_avail; - u64 num_devices; unsigned seq; - num_devices = fs_info->fs_devices->num_devices; - btrfs_dev_replace_lock(&fs_info->dev_replace, 0); - if (btrfs_dev_replace_is_ongoing(&fs_info->dev_replace)) { - WARN_ON(num_devices < 1); - num_devices--; - } - btrfs_dev_replace_unlock(&fs_info->dev_replace, 0); - do { seq = read_seqbegin(&fs_info->profiles_lock); @@ -1728,21 +1725,21 @@ static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info) fs_info->avail_metadata_alloc_bits; } while (read_seqretry(&fs_info->profiles_lock, seq)); - if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && num_devices <= 4) { + if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && num_devices < 4) { return BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET; } - if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && num_devices <= 2) { + if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && num_devices < 2) { return BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET; } if ((all_avail & BTRFS_BLOCK_GROUP_RAID5) && - fs_info->fs_devices->rw_devices <= 2) { + fs_info->fs_devices->rw_devices < 2) { return BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET; } if ((all_avail & BTRFS_BLOCK_GROUP_RAID6) && - fs_info->fs_devices->rw_devices <= 3) { + fs_info->fs_devices->rw_devices < 3) { return BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET; } @@ -1761,7 +1758,15 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid) mutex_lock(&uuid_mutex); - ret = btrfs_check_raid_min_devices(root->fs_info); + num_devices = root->fs_info->fs_devices->num_devices; + btrfs_dev_replace_lock(&root->fs_info->dev_replace, 0); + if (btrfs_dev_replace_is_ongoing(&root->fs_info->dev_replace)) { + WARN_ON(num_devices < 1); + num_devices--; + } + btrfs_dev_replace_unlock(&root->fs_info->dev_replace, 0); + + ret = btrfs_check_raid_min_devices(root->fs_info, num_devices - 1); if (ret) goto out; -- GitLab From 621292bae6ae3b25cd3124b63603d01df4cccfb6 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 15 Feb 2016 16:28:03 +0100 Subject: [PATCH 4923/9938] btrfs: introduce raid-type to error-code table, for minimum device constraint Reviewed-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 15 +++++++++++++++ fs/btrfs/volumes.h | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index e966f0ce07f8..6b38b72d678b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -118,6 +118,21 @@ const u64 btrfs_raid_group[BTRFS_NR_RAID_TYPES] = { [BTRFS_RAID_RAID6] = BTRFS_BLOCK_GROUP_RAID6, }; +/* + * Table to convert BTRFS_RAID_* to the error code if minimum number of devices + * condition is not met. Zero means there's no corresponding + * BTRFS_ERROR_DEV_*_NOT_MET value. + */ +const int btrfs_raid_mindev_error[BTRFS_NR_RAID_TYPES] = { + [BTRFS_RAID_RAID10] = BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET, + [BTRFS_RAID_RAID1] = BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET, + [BTRFS_RAID_DUP] = 0, + [BTRFS_RAID_RAID0] = 0, + [BTRFS_RAID_SINGLE] = 0, + [BTRFS_RAID_RAID5] = BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET, + [BTRFS_RAID_RAID6] = BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET, +}; + static int init_first_rw_device(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_device *device); diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index c73d027e2f8b..a13a538cb01e 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -340,7 +340,7 @@ struct btrfs_raid_attr { }; extern const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES]; - +extern const int btrfs_raid_mindev_error[BTRFS_NR_RAID_TYPES]; extern const u64 btrfs_raid_group[BTRFS_NR_RAID_TYPES]; struct map_lookup { -- GitLab From 418775a22b4c67bd15915e043c3a8f29816799bd Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 15 Feb 2016 16:28:14 +0100 Subject: [PATCH 4924/9938] btrfs: use existing device constraints table btrfs_raid_array We should avoid duplicating the device constraints, let's use the btrfs_raid_array in btrfs_check_raid_min_devices. Reviewed-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 6b38b72d678b..055fbebea199 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1731,6 +1731,7 @@ static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info, { u64 all_avail; unsigned seq; + int i; do { seq = read_seqbegin(&fs_info->profiles_lock); @@ -1740,22 +1741,16 @@ static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info, fs_info->avail_metadata_alloc_bits; } while (read_seqretry(&fs_info->profiles_lock, seq)); - if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && num_devices < 4) { - return BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET; - } - - if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && num_devices < 2) { - return BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET; - } + for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { + if (!(all_avail & btrfs_raid_group[i])) + continue; - if ((all_avail & BTRFS_BLOCK_GROUP_RAID5) && - fs_info->fs_devices->rw_devices < 2) { - return BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET; - } + if (num_devices < btrfs_raid_array[i].devs_min) { + int ret = btrfs_raid_mindev_error[i]; - if ((all_avail & BTRFS_BLOCK_GROUP_RAID6) && - fs_info->fs_devices->rw_devices < 3) { - return BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET; + if (ret) + return ret; + } } return 0; -- GitLab From 5c5c0df05deaebcdcc9bb31bdca3812a7c22230f Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 15 Feb 2016 16:39:55 +0100 Subject: [PATCH 4925/9938] btrfs: rename btrfs_find_device_by_user_input For clarity how we are going to find the device, let's call it a device specifier, devspec for short. Also rename the arguments that are a leftover from previous function purpose. Reviewed-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 2 +- fs/btrfs/volumes.c | 17 ++++++++++------- fs/btrfs/volumes.h | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index fdd2880707df..b7f5f4aa6e86 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -322,7 +322,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, /* the disk copy procedure reuses the scrub code */ mutex_lock(&fs_info->volume_mutex); - ret = btrfs_find_device_by_user_input(root, args->start.srcdevid, + ret = btrfs_find_device_by_devspec(root, args->start.srcdevid, args->start.srcdev_name, &src_device); if (ret) { diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 055fbebea199..e43b01e438b1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1780,7 +1780,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid) if (ret) goto out; - ret = btrfs_find_device_by_user_input(root, devid, device_path, + ret = btrfs_find_device_by_devspec(root, devid, device_path, &device); if (ret) goto out; @@ -2065,23 +2065,26 @@ int btrfs_find_device_missing_or_by_path(struct btrfs_root *root, } } -int btrfs_find_device_by_user_input(struct btrfs_root *root, u64 srcdevid, - char *srcdev_name, +/* + * Lookup a device given by device id, or the path if the id is 0. + */ +int btrfs_find_device_by_devspec(struct btrfs_root *root, u64 devid, + char *devpath, struct btrfs_device **device) { int ret; - if (srcdevid) { + if (devid) { ret = 0; - *device = btrfs_find_device(root->fs_info, srcdevid, NULL, + *device = btrfs_find_device(root->fs_info, devid, NULL, NULL); if (!*device) ret = -ENOENT; } else { - if (!srcdev_name || !srcdev_name[0]) + if (!devpath || !devpath[0]) return -EINVAL; - ret = btrfs_find_device_missing_or_by_path(root, srcdev_name, + ret = btrfs_find_device_missing_or_by_path(root, devpath, device); } return ret; diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index a13a538cb01e..febdb7bc9370 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -448,8 +448,8 @@ void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices, int step); int btrfs_find_device_missing_or_by_path(struct btrfs_root *root, char *device_path, struct btrfs_device **device); -int btrfs_find_device_by_user_input(struct btrfs_root *root, u64 srcdevid, - char *srcdev_name, +int btrfs_find_device_by_devspec(struct btrfs_root *root, u64 devid, + char *devpath, struct btrfs_device **device); struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, const u64 *devid, -- GitLab From 735654ea91a06a30bfe05fdfd09c8895abf6c1bf Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 15 Feb 2016 18:15:21 +0100 Subject: [PATCH 4926/9938] btrfs: rename flags for vol args v2 Rename BTRFS_DEVICE_BY_ID so it's more descriptive that we specify the device by id, it'll be part of the public API. The mask of supported flags is also renamed, only for internal use. The error code for unknown flags is EOPNOTSUPP, fixed. Reviewed-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 8 ++++---- include/uapi/linux/btrfs.h | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 7cf0f6328d99..65903ec5e1c0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2687,8 +2687,8 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) } /* Check for compatibility reject unknown flags */ - if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS) - return -ENOTTY; + if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED) + return -EOPNOTSUPP; if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, 1)) { @@ -2697,7 +2697,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) } mutex_lock(&root->fs_info->volume_mutex); - if (vol_args->flags & BTRFS_DEVICE_BY_ID) { + if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) { ret = btrfs_rm_device(root, NULL, vol_args->devid); } else { vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; @@ -2707,7 +2707,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); if (!ret) { - if (vol_args->flags & BTRFS_DEVICE_BY_ID) + if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) btrfs_info(root->fs_info, "device deleted: id %llu", vol_args->devid); else diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 396a4efca775..3975e683af72 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -36,12 +36,13 @@ struct btrfs_ioctl_vol_args { #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) #define BTRFS_SUBVOL_RDONLY (1ULL << 1) #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) -#define BTRFS_DEVICE_BY_ID (1ULL << 3) -#define BTRFS_VOL_ARG_V2_FLAGS \ +#define BTRFS_DEVICE_SPEC_BY_ID (1ULL << 3) + +#define BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED \ (BTRFS_SUBVOL_CREATE_ASYNC | \ BTRFS_SUBVOL_RDONLY | \ BTRFS_SUBVOL_QGROUP_INHERIT | \ - BTRFS_DEVICE_BY_ID) + BTRFS_DEVICE_SPEC_BY_ID) #define BTRFS_FSID_SIZE 16 #define BTRFS_UUID_SIZE 16 -- GitLab From fc23c246d72d21385be115305d1cb85fcc34acad Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Thu, 24 Mar 2016 18:48:12 +0800 Subject: [PATCH 4927/9938] btrfs: use fs_info directly Local variable fs_info, contains root->fs_info, use it. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index b7f5f4aa6e86..1a3d24592859 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -368,7 +368,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, WARN_ON(!tgt_device); dev_replace->tgtdev = tgt_device; - btrfs_info_in_rcu(root->fs_info, + btrfs_info_in_rcu(fs_info, "dev_replace from %s (devid %llu) to %s started", src_device->missing ? "" : rcu_str_deref(src_device->name), @@ -394,9 +394,9 @@ int btrfs_dev_replace_start(struct btrfs_root *root, ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device); if (ret) - btrfs_err(root->fs_info, "kobj add dev failed %d\n", ret); + btrfs_err(fs_info, "kobj add dev failed %d\n", ret); - btrfs_wait_ordered_roots(root->fs_info, -1); + btrfs_wait_ordered_roots(fs_info, -1); /* force writing the updated state information to disk */ trans = btrfs_start_transaction(root, 0); @@ -414,7 +414,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, btrfs_device_get_total_bytes(src_device), &dev_replace->scrub_progress, 0, 1); - ret = btrfs_dev_replace_finishing(root->fs_info, ret); + ret = btrfs_dev_replace_finishing(fs_info, ret); /* don't warn if EINPROGRESS, someone else might be running scrub */ if (ret == -EINPROGRESS) { args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS; -- GitLab From b5255456c529155730c837f8cfcea47e8feb85ca Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Thu, 24 Mar 2016 18:48:14 +0800 Subject: [PATCH 4928/9938] btrfs: refactor btrfs_dev_replace_start for reuse A refactor patch, and avoids user input verification in the btrfs_dev_replace_start(), and so this function can be reused. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/dev-replace.c | 58 +++++++++++++++++++++++++++--------------- fs/btrfs/dev-replace.h | 4 ++- fs/btrfs/ioctl.c | 2 +- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 1a3d24592859..5aebedf12b5f 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -302,8 +302,8 @@ void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info) dev_replace->cursor_left_last_write_of_item; } -int btrfs_dev_replace_start(struct btrfs_root *root, - struct btrfs_ioctl_dev_replace_args *args) +int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, + u64 srcdevid, char *srcdev_name, int read_src) { struct btrfs_trans_handle *trans; struct btrfs_fs_info *fs_info = root->fs_info; @@ -312,25 +312,16 @@ int btrfs_dev_replace_start(struct btrfs_root *root, struct btrfs_device *tgt_device = NULL; struct btrfs_device *src_device = NULL; - switch (args->start.cont_reading_from_srcdev_mode) { - case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS: - case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID: - break; - default: - return -EINVAL; - } - /* the disk copy procedure reuses the scrub code */ mutex_lock(&fs_info->volume_mutex); - ret = btrfs_find_device_by_devspec(root, args->start.srcdevid, - args->start.srcdev_name, - &src_device); + ret = btrfs_find_device_by_devspec(root, srcdevid, + srcdev_name, &src_device); if (ret) { mutex_unlock(&fs_info->volume_mutex); return ret; } - ret = btrfs_init_dev_replace_tgtdev(root, args->start.tgtdev_name, + ret = btrfs_init_dev_replace_tgtdev(root, tgtdev_name, src_device, &tgt_device); mutex_unlock(&fs_info->volume_mutex); if (ret) @@ -357,12 +348,11 @@ int btrfs_dev_replace_start(struct btrfs_root *root, break; case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED: case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED: - args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED; + ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED; goto leave; } - dev_replace->cont_reading_from_srcdev_mode = - args->start.cont_reading_from_srcdev_mode; + dev_replace->cont_reading_from_srcdev_mode = read_src; WARN_ON(!src_device); dev_replace->srcdev = src_device; WARN_ON(!tgt_device); @@ -389,7 +379,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root, dev_replace->item_needs_writeback = 1; atomic64_set(&dev_replace->num_write_errors, 0); atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0); - args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR; btrfs_dev_replace_unlock(dev_replace, 1); ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device); @@ -415,10 +404,8 @@ int btrfs_dev_replace_start(struct btrfs_root *root, &dev_replace->scrub_progress, 0, 1); ret = btrfs_dev_replace_finishing(fs_info, ret); - /* don't warn if EINPROGRESS, someone else might be running scrub */ if (ret == -EINPROGRESS) { - args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS; - ret = 0; + ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS; } else { WARN_ON(ret); } @@ -433,6 +420,35 @@ int btrfs_dev_replace_start(struct btrfs_root *root, return ret; } +int btrfs_dev_replace_by_ioctl(struct btrfs_root *root, + struct btrfs_ioctl_dev_replace_args *args) +{ + int ret; + + switch (args->start.cont_reading_from_srcdev_mode) { + case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS: + case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID: + break; + default: + return -EINVAL; + } + + if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') || + args->start.tgtdev_name[0] == '\0') + return -EINVAL; + + ret = btrfs_dev_replace_start(root, args->start.tgtdev_name, + args->start.srcdevid, + args->start.srcdev_name, + args->start.cont_reading_from_srcdev_mode); + args->result = ret; + /* don't warn if EINPROGRESS, someone else might be running scrub */ + if (ret == BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS) + ret = 0; + + return ret; +} + /* * blocked until all flighting bios are finished. */ diff --git a/fs/btrfs/dev-replace.h b/fs/btrfs/dev-replace.h index 29e3ef5f96bd..e922b42d91df 100644 --- a/fs/btrfs/dev-replace.h +++ b/fs/btrfs/dev-replace.h @@ -25,8 +25,10 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info); int btrfs_run_dev_replace(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info); void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info); -int btrfs_dev_replace_start(struct btrfs_root *root, +int btrfs_dev_replace_by_ioctl(struct btrfs_root *root, struct btrfs_ioctl_dev_replace_args *args); +int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, + u64 srcdevid, char *srcdev_name, int read_src); void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info, struct btrfs_ioctl_dev_replace_args *args); int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info, diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 65903ec5e1c0..36b1ed223509 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -4430,7 +4430,7 @@ static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg) 1)) { ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; } else { - ret = btrfs_dev_replace_start(root, p); + ret = btrfs_dev_replace_by_ioctl(root, p); atomic_set( &root->fs_info->mutually_exclusive_operation_running, 0); -- GitLab From c094cf13e5e6c1b9b52c079804c947d3c1b57b86 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 25 Apr 2016 22:42:25 +0100 Subject: [PATCH 4929/9938] mfd: ab8500-debugfs: fix "between" in printk fix spelling mistake, beetween -> between Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/mfd/ab8500-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 69d9fffe5b5c..0aecd7bd35f8 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -2563,7 +2563,7 @@ static ssize_t ab8500_gpadc_trig_timer_write(struct file *file, if (user_trig_timer & ~0xFF) { dev_err(dev, - "debugfs error input: should be beetween 0 to 255\n"); + "debugfs error input: should be between 0 to 255\n"); return -EINVAL; } -- GitLab From 52bbe141f37f093e2c612e97c40d27422e5a1fdf Mon Sep 17 00:00:00 2001 From: Kyeongmin Cho Date: Thu, 28 Apr 2016 02:06:49 +0900 Subject: [PATCH 4930/9938] gitignore: fix wording Git files are the files that we don't want to ignore even if they are dot-files. It must be "even if" but it says "even it". Signed-off-by: Kyeongmin Cho Signed-off-by: Jiri Kosina --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index fd3a35592543..0c320bf02586 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,7 @@ Module.symvers /tar-install/ # -# git files that we don't want to ignore even it they are dot-files +# git files that we don't want to ignore even if they are dot-files # !.gitignore !.mailmap -- GitLab From 81b785f3e4114ed74fceb48a54e7de2f797a2ba1 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 26 Apr 2016 14:46:06 -0700 Subject: [PATCH 4931/9938] x86/boot: Rename overlapping memcpy() to memmove() Instead of having non-standard memcpy() behavior, explicitly call the new function memmove(), make it available to the decompressors, and switch the two overlap cases (screen scrolling and ELF parsing) to use memmove(). Additionally documents the purpose of compressed/string.c. Suggested-by: Lasse Collin Signed-off-by: Kees Cook Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Dmitry Vyukov Cc: H.J. Lu Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/20160426214606.GA5758@www.outflux.net Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/misc.c | 6 ++++-- arch/x86/boot/compressed/string.c | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index c57d785ff955..6dde6ccdf00e 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -32,9 +32,11 @@ #undef memcpy #undef memset #define memzero(s, n) memset((s), 0, (n)) +#define memmove memmove /* Functions used by the included decompressor code below. */ static void error(char *m); +void *memmove(void *dest, const void *src, size_t n); /* * This is set up by the setup-routine at boot-time @@ -80,7 +82,7 @@ static void scroll(void) { int i; - memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2); + memmove(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2); for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2) vidmem[i] = ' '; } @@ -307,7 +309,7 @@ static void parse_elf(void *output) #else dest = (void *)(phdr->p_paddr); #endif - memcpy(dest, output + phdr->p_offset, phdr->p_filesz); + memmove(dest, output + phdr->p_offset, phdr->p_filesz); break; default: /* Ignore other PT_* */ break; } diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index 1e10e40f49dd..2befeca1aada 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -1,7 +1,14 @@ +/* + * This provides an optimized implementation of memcpy, and a simplified + * implementation of memset and memmove. These are used here because the + * standard kernel runtime versions are not yet available and we don't + * trust the gcc built-in implementations as they may do unexpected things + * (e.g. FPU ops) in the minimal decompression stub execution environment. + */ #include "../string.c" #ifdef CONFIG_X86_32 -void *__memcpy(void *dest, const void *src, size_t n) +void *memcpy(void *dest, const void *src, size_t n) { int d0, d1, d2; asm volatile( @@ -15,7 +22,7 @@ void *__memcpy(void *dest, const void *src, size_t n) return dest; } #else -void *__memcpy(void *dest, const void *src, size_t n) +void *memcpy(void *dest, const void *src, size_t n) { long d0, d1, d2; asm volatile( @@ -40,17 +47,13 @@ void *memset(void *s, int c, size_t n) return s; } -/* - * This memcpy is overlap safe (i.e. it is memmove without conflicting - * with other definitions of memmove from the various decompressors. - */ -void *memcpy(void *dest, const void *src, size_t n) +void *memmove(void *dest, const void *src, size_t n) { unsigned char *d = dest; const unsigned char *s = src; if (d <= s || d - s >= n) - return __memcpy(dest, src, n); + return memcpy(dest, src, n); while (n-- > 0) d[n] = s[n]; -- GitLab From d4ae133b2d195d88cf5394072724adfa6ccdd64b Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:23 -0400 Subject: [PATCH 4932/9938] btrfs: uapi/linux/btrfs.h migration, move BTRFS_LABEL_SIZE BTRFS_LABEL_SIZE is required to define the BTRFS_IOC_GET_FSLABEL and BTRFS_IOC_SET_FSLABEL ioctls. Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 1 - include/uapi/linux/btrfs.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 84a6a5b3384a..3beaa24aff9b 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -410,7 +410,6 @@ struct btrfs_header { * room to translate 14 chunks with 3 stripes each. */ #define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048 -#define BTRFS_LABEL_SIZE 256 /* * just in case we somehow lose the roots and are not able to mount, diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index dea893199257..11eee3439994 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -23,6 +23,7 @@ #define BTRFS_IOCTL_MAGIC 0x94 #define BTRFS_VOL_NAME_MAX 255 +#define BTRFS_LABEL_SIZE 256 /* this should be 4k */ #define BTRFS_PATH_NAME_MAX 4087 -- GitLab From 83288b60bf6668933689078973136e0c9d387b38 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:24 -0400 Subject: [PATCH 4933/9938] btrfs: uapi/linux/btrfs.h migration, qgroup limit flags The BTRFS_QGROUP_LIMIT_* flags are required to tell the kernel which fields are valid when using the BTRFS_IOC_QGROUP_LIMIT ioctl. Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 8 -------- include/uapi/linux/btrfs.h | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 3beaa24aff9b..c228b39fbd15 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1154,14 +1154,6 @@ struct btrfs_qgroup_info_item { __le64 excl_cmpr; } __attribute__ ((__packed__)); -/* flags definition for qgroup limits */ -#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) -#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) -#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) -#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) -#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) -#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) - struct btrfs_qgroup_limit_item { /* * only updated when any of the other values change diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 11eee3439994..9651af3c46a1 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -41,7 +41,19 @@ struct btrfs_ioctl_vol_args { #define BTRFS_UUID_SIZE 16 #define BTRFS_UUID_UNPARSED_SIZE 37 -#define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) +/* + * flags definition for qgroup limits + * + * Used by: + * struct btrfs_qgroup_limit.flags + * struct btrfs_qgroup_limit_item.flags + */ +#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) +#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) +#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) +#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) +#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) +#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) struct btrfs_qgroup_limit { __u64 flags; @@ -51,6 +63,14 @@ struct btrfs_qgroup_limit { __u64 rsv_excl; }; +/* + * flags definition for qgroup inheritance + * + * Used by: + * struct btrfs_qgroup_inherit.flags + */ +#define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) + struct btrfs_qgroup_inherit { __u64 flags; __u64 num_qgroups; -- GitLab From 884f6eca59475bc3cad5c22360523a1261bd5597 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:25 -0400 Subject: [PATCH 4934/9938] btrfs: uapi/linux/btrfs.h migration, document subvol flags Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- include/uapi/linux/btrfs.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 9651af3c46a1..0316e23b32cc 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -34,9 +34,6 @@ struct btrfs_ioctl_vol_args { #define BTRFS_DEVICE_PATH_NAME_MAX 1024 -#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) -#define BTRFS_SUBVOL_RDONLY (1ULL << 1) -#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) #define BTRFS_FSID_SIZE 16 #define BTRFS_UUID_SIZE 16 #define BTRFS_UUID_UNPARSED_SIZE 37 @@ -85,6 +82,20 @@ struct btrfs_ioctl_qgroup_limit_args { struct btrfs_qgroup_limit lim; }; +/* + * flags for subvolumes + * + * Used by: + * struct btrfs_ioctl_vol_args_v2.flags + * + * BTRFS_SUBVOL_RDONLY is also provided/consumed by the following ioctls: + * - BTRFS_IOC_SUBVOL_GETFLAGS + * - BTRFS_IOC_SUBVOL_SETFLAGS + */ +#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) +#define BTRFS_SUBVOL_RDONLY (1ULL << 1) +#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) + #define BTRFS_SUBVOL_NAME_MAX 4039 struct btrfs_ioctl_vol_args_v2 { __s64 fd; -- GitLab From 18db9ac644badcb948a623791e599672edade6dd Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:26 -0400 Subject: [PATCH 4935/9938] btrfs: uapi/linux/btrfs.h migration, move feature flags The compat/compat_ro/incompat feature flags are used by the feature set/get ioctls. Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 25 ------------------------- include/uapi/linux/btrfs.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index c228b39fbd15..378482c705c3 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -506,31 +506,6 @@ struct btrfs_super_block { * Compat flags that we support. If any incompat flags are set other than the * ones specified below then we will fail to mount */ -#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) - -#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) -#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) -#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) -#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3) -/* - * some patches floated around with a second compression method - * lets save that incompat here for when they do get in - * Note we don't actually support it, we're just reserving the - * number - */ -#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZOv2 (1ULL << 4) - -/* - * older kernels tried to do bigger metadata blocks, but the - * code was pretty buggy. Lets not let them try anymore. - */ -#define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) - -#define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) -#define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) -#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) -#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) - #define BTRFS_FEATURE_COMPAT_SUPP 0ULL #define BTRFS_FEATURE_COMPAT_SAFE_SET 0ULL #define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 0316e23b32cc..de98717386ee 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -222,6 +222,37 @@ struct btrfs_ioctl_fs_info_args { __u64 reserved[122]; /* pad to 1k */ }; +/* + * feature flags + * + * Used by: + * struct btrfs_ioctl_feature_flags + */ +#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) + +#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) +#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) +#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) +#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3) +/* + * some patches floated around with a second compression method + * lets save that incompat here for when they do get in + * Note we don't actually support it, we're just reserving the + * number + */ +#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZOv2 (1ULL << 4) + +/* + * older kernels tried to do bigger metadata blocks, but the + * code was pretty buggy. Lets not let them try anymore. + */ +#define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) + +#define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) +#define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) +#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) +#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) + struct btrfs_ioctl_feature_flags { __u64 compat_flags; __u64 compat_ro_flags; -- GitLab From 04cd01dffbf9be14ccc51595280c8dc8c318a9c9 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:27 -0400 Subject: [PATCH 4936/9938] btrfs: uapi/linux/btrfs.h migration, move balance flags The BTRFS_BALANCE_* flags are used by struct btrfs_ioctl_balance_args.flags and btrfs_ioctl_balance_args.{data,meta,sys}.flags in the BTRFS_IOC_BALANCE ioctl. Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/volumes.h | 46 --------------------------- include/uapi/linux/btrfs.h | 64 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 46 deletions(-) diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 1939ebde63df..144cec33357a 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -357,52 +357,6 @@ struct map_lookup { #define map_lookup_size(n) (sizeof(struct map_lookup) + \ (sizeof(struct btrfs_bio_stripe) * (n))) -/* - * Restriper's general type filter - */ -#define BTRFS_BALANCE_DATA (1ULL << 0) -#define BTRFS_BALANCE_SYSTEM (1ULL << 1) -#define BTRFS_BALANCE_METADATA (1ULL << 2) - -#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \ - BTRFS_BALANCE_SYSTEM | \ - BTRFS_BALANCE_METADATA) - -#define BTRFS_BALANCE_FORCE (1ULL << 3) -#define BTRFS_BALANCE_RESUME (1ULL << 4) - -/* - * Balance filters - */ -#define BTRFS_BALANCE_ARGS_PROFILES (1ULL << 0) -#define BTRFS_BALANCE_ARGS_USAGE (1ULL << 1) -#define BTRFS_BALANCE_ARGS_DEVID (1ULL << 2) -#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) -#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) -#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5) -#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6) -#define BTRFS_BALANCE_ARGS_STRIPES_RANGE (1ULL << 7) -#define BTRFS_BALANCE_ARGS_USAGE_RANGE (1ULL << 10) - -#define BTRFS_BALANCE_ARGS_MASK \ - (BTRFS_BALANCE_ARGS_PROFILES | \ - BTRFS_BALANCE_ARGS_USAGE | \ - BTRFS_BALANCE_ARGS_DEVID | \ - BTRFS_BALANCE_ARGS_DRANGE | \ - BTRFS_BALANCE_ARGS_VRANGE | \ - BTRFS_BALANCE_ARGS_LIMIT | \ - BTRFS_BALANCE_ARGS_LIMIT_RANGE | \ - BTRFS_BALANCE_ARGS_STRIPES_RANGE | \ - BTRFS_BALANCE_ARGS_USAGE_RANGE) - -/* - * Profile changing flags. When SOFT is set we won't relocate chunk if - * it already has the target profile (even though it may be - * half-filled). - */ -#define BTRFS_BALANCE_ARGS_CONVERT (1ULL << 8) -#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9) - struct btrfs_balance_args; struct btrfs_balance_progress; struct btrfs_balance_control { diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index de98717386ee..abae362d4ec7 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -317,6 +317,70 @@ struct btrfs_balance_progress { __u64 completed; /* # of chunks relocated so far */ }; +/* + * flags definition for balance + * + * Restriper's general type filter + * + * Used by: + * btrfs_ioctl_balance_args.flags + * btrfs_balance_control.flags (internal) + */ +#define BTRFS_BALANCE_DATA (1ULL << 0) +#define BTRFS_BALANCE_SYSTEM (1ULL << 1) +#define BTRFS_BALANCE_METADATA (1ULL << 2) + +#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \ + BTRFS_BALANCE_SYSTEM | \ + BTRFS_BALANCE_METADATA) + +#define BTRFS_BALANCE_FORCE (1ULL << 3) +#define BTRFS_BALANCE_RESUME (1ULL << 4) + +/* + * flags definitions for per-type balance args + * + * Balance filters + * + * Used by: + * struct btrfs_balance_args + */ +#define BTRFS_BALANCE_ARGS_PROFILES (1ULL << 0) +#define BTRFS_BALANCE_ARGS_USAGE (1ULL << 1) +#define BTRFS_BALANCE_ARGS_DEVID (1ULL << 2) +#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) +#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) +#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5) +#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6) +#define BTRFS_BALANCE_ARGS_STRIPES_RANGE (1ULL << 7) +#define BTRFS_BALANCE_ARGS_USAGE_RANGE (1ULL << 10) + +#define BTRFS_BALANCE_ARGS_MASK \ + (BTRFS_BALANCE_ARGS_PROFILES | \ + BTRFS_BALANCE_ARGS_USAGE | \ + BTRFS_BALANCE_ARGS_DEVID | \ + BTRFS_BALANCE_ARGS_DRANGE | \ + BTRFS_BALANCE_ARGS_VRANGE | \ + BTRFS_BALANCE_ARGS_LIMIT | \ + BTRFS_BALANCE_ARGS_LIMIT_RANGE | \ + BTRFS_BALANCE_ARGS_STRIPES_RANGE | \ + BTRFS_BALANCE_ARGS_USAGE_RANGE) + +/* + * Profile changing flags. When SOFT is set we won't relocate chunk if + * it already has the target profile (even though it may be + * half-filled). + */ +#define BTRFS_BALANCE_ARGS_CONVERT (1ULL << 8) +#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9) + + +/* + * flags definition for balance state + * + * Used by: + * struct btrfs_ioctl_balance_args.state + */ #define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0) #define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1) #define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2) -- GitLab From 33ca913349962208e13e894ada99b9ae6e0080ee Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:28 -0400 Subject: [PATCH 4937/9938] btrfs: uapi/linux/btrfs.h migration, move struct btrfs_ioctl_defrag_range_args struct btrfs_ioctl_defrag_range_args is used by the BTRFS_IOC_DEFRAG_RANGE ioctl. Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 31 ------------------------------- include/uapi/linux/btrfs.h | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 378482c705c3..89f36b6176b9 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1992,37 +1992,6 @@ struct btrfs_root { atomic_t qgroup_meta_rsv; }; -struct btrfs_ioctl_defrag_range_args { - /* start of the defrag operation */ - __u64 start; - - /* number of bytes to defrag, use (u64)-1 to say all */ - __u64 len; - - /* - * flags for the operation, which can include turning - * on compression for this one defrag - */ - __u64 flags; - - /* - * any extent bigger than this will be considered - * already defragged. Use 0 to take the kernel default - * Use 1 to say every single extent must be rewritten - */ - __u32 extent_thresh; - - /* - * which compression method to use if turning on compression - * for this defrag operation. If unspecified, zlib will - * be used - */ - __u32 compress_type; - - /* spare for later */ - __u32 unused[4]; -}; - /* * inode items have the data typically returned from stat and store other diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index abae362d4ec7..98aff38a70d3 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -474,9 +474,45 @@ struct btrfs_ioctl_clone_range_args { __u64 dest_offset; }; -/* flags for the defrag range ioctl */ +/* + * flags definition for the defrag range ioctl + * + * Used by: + * struct btrfs_ioctl_defrag_range_args.flags + */ #define BTRFS_DEFRAG_RANGE_COMPRESS 1 #define BTRFS_DEFRAG_RANGE_START_IO 2 +struct btrfs_ioctl_defrag_range_args { + /* start of the defrag operation */ + __u64 start; + + /* number of bytes to defrag, use (u64)-1 to say all */ + __u64 len; + + /* + * flags for the operation, which can include turning + * on compression for this one defrag + */ + __u64 flags; + + /* + * any extent bigger than this will be considered + * already defragged. Use 0 to take the kernel default + * Use 1 to say every single extent must be rewritten + */ + __u32 extent_thresh; + + /* + * which compression method to use if turning on compression + * for this defrag operation. If unspecified, zlib will + * be used + */ + __u32 compress_type; + + /* spare for later */ + __u32 unused[4]; +}; + #define BTRFS_SAME_DATA_DIFFERS 1 /* For extent-same ioctl */ -- GitLab From db6711600e27c885aed89751f04e727f3af26715 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:29 -0400 Subject: [PATCH 4938/9938] btrfs: uapi/linux/btrfs_tree.h migration, item types and defines The BTRFS_IOC_SEARCH_TREE ioctl returns file system items directly to userspace. In order to decode them, full type information is required. Create a new header, btrfs_tree to contain these since most users won't need them. Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 949 +------------------------------ include/uapi/linux/btrfs_tree.h | 966 ++++++++++++++++++++++++++++++++ 2 files changed, 967 insertions(+), 948 deletions(-) create mode 100644 include/uapi/linux/btrfs_tree.h diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 89f36b6176b9..cf34fb58874c 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -64,98 +65,6 @@ struct btrfs_ordered_sum; #define BTRFS_COMPAT_EXTENT_TREE_V0 -/* holds pointers to all of the tree roots */ -#define BTRFS_ROOT_TREE_OBJECTID 1ULL - -/* stores information about which extents are in use, and reference counts */ -#define BTRFS_EXTENT_TREE_OBJECTID 2ULL - -/* - * chunk tree stores translations from logical -> physical block numbering - * the super block points to the chunk tree - */ -#define BTRFS_CHUNK_TREE_OBJECTID 3ULL - -/* - * stores information about which areas of a given device are in use. - * one per device. The tree of tree roots points to the device tree - */ -#define BTRFS_DEV_TREE_OBJECTID 4ULL - -/* one per subvolume, storing files and directories */ -#define BTRFS_FS_TREE_OBJECTID 5ULL - -/* directory objectid inside the root tree */ -#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL - -/* holds checksums of all the data extents */ -#define BTRFS_CSUM_TREE_OBJECTID 7ULL - -/* holds quota configuration and tracking */ -#define BTRFS_QUOTA_TREE_OBJECTID 8ULL - -/* for storing items that use the BTRFS_UUID_KEY* types */ -#define BTRFS_UUID_TREE_OBJECTID 9ULL - -/* tracks free space in block groups. */ -#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL - -/* device stats in the device tree */ -#define BTRFS_DEV_STATS_OBJECTID 0ULL - -/* for storing balance parameters in the root tree */ -#define BTRFS_BALANCE_OBJECTID -4ULL - -/* orhpan objectid for tracking unlinked/truncated files */ -#define BTRFS_ORPHAN_OBJECTID -5ULL - -/* does write ahead logging to speed up fsyncs */ -#define BTRFS_TREE_LOG_OBJECTID -6ULL -#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL - -/* for space balancing */ -#define BTRFS_TREE_RELOC_OBJECTID -8ULL -#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL - -/* - * extent checksums all have this objectid - * this allows them to share the logging tree - * for fsyncs - */ -#define BTRFS_EXTENT_CSUM_OBJECTID -10ULL - -/* For storing free space cache */ -#define BTRFS_FREE_SPACE_OBJECTID -11ULL - -/* - * The inode number assigned to the special inode for storing - * free ino cache - */ -#define BTRFS_FREE_INO_OBJECTID -12ULL - -/* dummy objectid represents multiple objectids */ -#define BTRFS_MULTIPLE_OBJECTIDS -255ULL - -/* - * All files have objectids in this range. - */ -#define BTRFS_FIRST_FREE_OBJECTID 256ULL -#define BTRFS_LAST_FREE_OBJECTID -256ULL -#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL - - -/* - * the device items go into the chunk tree. The key is in the form - * [ 1 BTRFS_DEV_ITEM_KEY device_id ] - */ -#define BTRFS_DEV_ITEMS_OBJECTID 1ULL - -#define BTRFS_BTREE_INODE_OBJECTID 1 - -#define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2 - -#define BTRFS_DEV_REPLACE_DEVID 0ULL - /* * the max metadata block size. This limit is somewhat artificial, * but the memmove costs go through the roof for larger blocks. @@ -175,12 +84,6 @@ struct btrfs_ordered_sum; */ #define BTRFS_LINK_MAX 65535U -/* 32 bytes in various csum fields */ -#define BTRFS_CSUM_SIZE 32 - -/* csum types */ -#define BTRFS_CSUM_TYPE_CRC32 0 - static const int btrfs_csum_sizes[] = { 4 }; /* four bytes for CRC32 */ @@ -189,17 +92,6 @@ static const int btrfs_csum_sizes[] = { 4 }; /* spefic to btrfs_map_block(), therefore not in include/linux/blk_types.h */ #define REQ_GET_READ_MIRRORS (1 << 30) -#define BTRFS_FT_UNKNOWN 0 -#define BTRFS_FT_REG_FILE 1 -#define BTRFS_FT_DIR 2 -#define BTRFS_FT_CHRDEV 3 -#define BTRFS_FT_BLKDEV 4 -#define BTRFS_FT_FIFO 5 -#define BTRFS_FT_SOCK 6 -#define BTRFS_FT_SYMLINK 7 -#define BTRFS_FT_XATTR 8 -#define BTRFS_FT_MAX 9 - /* ioprio of readahead is set to idle */ #define BTRFS_IOPRIO_READA (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)) @@ -207,138 +99,10 @@ static const int btrfs_csum_sizes[] = { 4 }; #define BTRFS_MAX_EXTENT_SIZE SZ_128M -/* - * The key defines the order in the tree, and so it also defines (optimal) - * block layout. - * - * objectid corresponds to the inode number. - * - * type tells us things about the object, and is a kind of stream selector. - * so for a given inode, keys with type of 1 might refer to the inode data, - * type of 2 may point to file data in the btree and type == 3 may point to - * extents. - * - * offset is the starting byte offset for this key in the stream. - * - * btrfs_disk_key is in disk byte order. struct btrfs_key is always - * in cpu native order. Otherwise they are identical and their sizes - * should be the same (ie both packed) - */ -struct btrfs_disk_key { - __le64 objectid; - u8 type; - __le64 offset; -} __attribute__ ((__packed__)); - -struct btrfs_key { - u64 objectid; - u8 type; - u64 offset; -} __attribute__ ((__packed__)); - struct btrfs_mapping_tree { struct extent_map_tree map_tree; }; -struct btrfs_dev_item { - /* the internal btrfs device id */ - __le64 devid; - - /* size of the device */ - __le64 total_bytes; - - /* bytes used */ - __le64 bytes_used; - - /* optimal io alignment for this device */ - __le32 io_align; - - /* optimal io width for this device */ - __le32 io_width; - - /* minimal io size for this device */ - __le32 sector_size; - - /* type and info about this device */ - __le64 type; - - /* expected generation for this device */ - __le64 generation; - - /* - * starting byte of this partition on the device, - * to allow for stripe alignment in the future - */ - __le64 start_offset; - - /* grouping information for allocation decisions */ - __le32 dev_group; - - /* seek speed 0-100 where 100 is fastest */ - u8 seek_speed; - - /* bandwidth 0-100 where 100 is fastest */ - u8 bandwidth; - - /* btrfs generated uuid for this device */ - u8 uuid[BTRFS_UUID_SIZE]; - - /* uuid of FS who owns this device */ - u8 fsid[BTRFS_UUID_SIZE]; -} __attribute__ ((__packed__)); - -struct btrfs_stripe { - __le64 devid; - __le64 offset; - u8 dev_uuid[BTRFS_UUID_SIZE]; -} __attribute__ ((__packed__)); - -struct btrfs_chunk { - /* size of this chunk in bytes */ - __le64 length; - - /* objectid of the root referencing this chunk */ - __le64 owner; - - __le64 stripe_len; - __le64 type; - - /* optimal io alignment for this chunk */ - __le32 io_align; - - /* optimal io width for this chunk */ - __le32 io_width; - - /* minimal io size for this chunk */ - __le32 sector_size; - - /* 2^16 stripes is quite a lot, a second limit is the size of a single - * item in the btree - */ - __le16 num_stripes; - - /* sub stripes only matter for raid10 */ - __le16 sub_stripes; - struct btrfs_stripe stripe; - /* additional stripes go here */ -} __attribute__ ((__packed__)); - -#define BTRFS_FREE_SPACE_EXTENT 1 -#define BTRFS_FREE_SPACE_BITMAP 2 - -struct btrfs_free_space_entry { - __le64 offset; - __le64 bytes; - u8 type; -} __attribute__ ((__packed__)); - -struct btrfs_free_space_header { - struct btrfs_disk_key location; - __le64 generation; - __le64 num_entries; - __le64 num_bitmaps; -} __attribute__ ((__packed__)); - static inline unsigned long btrfs_chunk_item_size(int num_stripes) { BUG_ON(num_stripes == 0); @@ -346,9 +110,6 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes) sizeof(struct btrfs_stripe) * (num_stripes - 1); } -#define BTRFS_HEADER_FLAG_WRITTEN (1ULL << 0) -#define BTRFS_HEADER_FLAG_RELOC (1ULL << 1) - /* * File system states */ @@ -357,13 +118,6 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes) #define BTRFS_FS_STATE_TRANS_ABORTED 2 #define BTRFS_FS_STATE_DEV_REPLACING 3 -/* Super block flags */ -/* Errors detected */ -#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2) - -#define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32) -#define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33) - #define BTRFS_BACKREF_REV_MAX 256 #define BTRFS_BACKREF_REV_SHIFT 56 #define BTRFS_BACKREF_REV_MASK (((u64)BTRFS_BACKREF_REV_MAX - 1) << \ @@ -598,357 +352,8 @@ struct btrfs_path { unsigned int need_commit_sem:1; unsigned int skip_release_on_error:1; }; - -/* - * items in the extent btree are used to record the objectid of the - * owner of the block and the number of references - */ - -struct btrfs_extent_item { - __le64 refs; - __le64 generation; - __le64 flags; -} __attribute__ ((__packed__)); - -struct btrfs_extent_item_v0 { - __le32 refs; -} __attribute__ ((__packed__)); - #define BTRFS_MAX_EXTENT_ITEM_SIZE(r) ((BTRFS_LEAF_DATA_SIZE(r) >> 4) - \ sizeof(struct btrfs_item)) - -#define BTRFS_EXTENT_FLAG_DATA (1ULL << 0) -#define BTRFS_EXTENT_FLAG_TREE_BLOCK (1ULL << 1) - -/* following flags only apply to tree blocks */ - -/* use full backrefs for extent pointers in the block */ -#define BTRFS_BLOCK_FLAG_FULL_BACKREF (1ULL << 8) - -/* - * this flag is only used internally by scrub and may be changed at any time - * it is only declared here to avoid collisions - */ -#define BTRFS_EXTENT_FLAG_SUPER (1ULL << 48) - -struct btrfs_tree_block_info { - struct btrfs_disk_key key; - u8 level; -} __attribute__ ((__packed__)); - -struct btrfs_extent_data_ref { - __le64 root; - __le64 objectid; - __le64 offset; - __le32 count; -} __attribute__ ((__packed__)); - -struct btrfs_shared_data_ref { - __le32 count; -} __attribute__ ((__packed__)); - -struct btrfs_extent_inline_ref { - u8 type; - __le64 offset; -} __attribute__ ((__packed__)); - -/* old style backrefs item */ -struct btrfs_extent_ref_v0 { - __le64 root; - __le64 generation; - __le64 objectid; - __le32 count; -} __attribute__ ((__packed__)); - - -/* dev extents record free space on individual devices. The owner - * field points back to the chunk allocation mapping tree that allocated - * the extent. The chunk tree uuid field is a way to double check the owner - */ -struct btrfs_dev_extent { - __le64 chunk_tree; - __le64 chunk_objectid; - __le64 chunk_offset; - __le64 length; - u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; -} __attribute__ ((__packed__)); - -struct btrfs_inode_ref { - __le64 index; - __le16 name_len; - /* name goes here */ -} __attribute__ ((__packed__)); - -struct btrfs_inode_extref { - __le64 parent_objectid; - __le64 index; - __le16 name_len; - __u8 name[0]; - /* name goes here */ -} __attribute__ ((__packed__)); - -struct btrfs_timespec { - __le64 sec; - __le32 nsec; -} __attribute__ ((__packed__)); - -struct btrfs_inode_item { - /* nfs style generation number */ - __le64 generation; - /* transid that last touched this inode */ - __le64 transid; - __le64 size; - __le64 nbytes; - __le64 block_group; - __le32 nlink; - __le32 uid; - __le32 gid; - __le32 mode; - __le64 rdev; - __le64 flags; - - /* modification sequence number for NFS */ - __le64 sequence; - - /* - * a little future expansion, for more than this we can - * just grow the inode item and version it - */ - __le64 reserved[4]; - struct btrfs_timespec atime; - struct btrfs_timespec ctime; - struct btrfs_timespec mtime; - struct btrfs_timespec otime; -} __attribute__ ((__packed__)); - -struct btrfs_dir_log_item { - __le64 end; -} __attribute__ ((__packed__)); - -struct btrfs_dir_item { - struct btrfs_disk_key location; - __le64 transid; - __le16 data_len; - __le16 name_len; - u8 type; -} __attribute__ ((__packed__)); - -#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0) - -/* - * Internal in-memory flag that a subvolume has been marked for deletion but - * still visible as a directory - */ -#define BTRFS_ROOT_SUBVOL_DEAD (1ULL << 48) - -struct btrfs_root_item { - struct btrfs_inode_item inode; - __le64 generation; - __le64 root_dirid; - __le64 bytenr; - __le64 byte_limit; - __le64 bytes_used; - __le64 last_snapshot; - __le64 flags; - __le32 refs; - struct btrfs_disk_key drop_progress; - u8 drop_level; - u8 level; - - /* - * The following fields appear after subvol_uuids+subvol_times - * were introduced. - */ - - /* - * This generation number is used to test if the new fields are valid - * and up to date while reading the root item. Every time the root item - * is written out, the "generation" field is copied into this field. If - * anyone ever mounted the fs with an older kernel, we will have - * mismatching generation values here and thus must invalidate the - * new fields. See btrfs_update_root and btrfs_find_last_root for - * details. - * the offset of generation_v2 is also used as the start for the memset - * when invalidating the fields. - */ - __le64 generation_v2; - u8 uuid[BTRFS_UUID_SIZE]; - u8 parent_uuid[BTRFS_UUID_SIZE]; - u8 received_uuid[BTRFS_UUID_SIZE]; - __le64 ctransid; /* updated when an inode changes */ - __le64 otransid; /* trans when created */ - __le64 stransid; /* trans when sent. non-zero for received subvol */ - __le64 rtransid; /* trans when received. non-zero for received subvol */ - struct btrfs_timespec ctime; - struct btrfs_timespec otime; - struct btrfs_timespec stime; - struct btrfs_timespec rtime; - __le64 reserved[8]; /* for future */ -} __attribute__ ((__packed__)); - -/* - * this is used for both forward and backward root refs - */ -struct btrfs_root_ref { - __le64 dirid; - __le64 sequence; - __le16 name_len; -} __attribute__ ((__packed__)); - -struct btrfs_disk_balance_args { - /* - * profiles to operate on, single is denoted by - * BTRFS_AVAIL_ALLOC_BIT_SINGLE - */ - __le64 profiles; - - /* - * usage filter - * BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N' - * BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max - */ - union { - __le64 usage; - struct { - __le32 usage_min; - __le32 usage_max; - }; - }; - - /* devid filter */ - __le64 devid; - - /* devid subset filter [pstart..pend) */ - __le64 pstart; - __le64 pend; - - /* btrfs virtual address space subset filter [vstart..vend) */ - __le64 vstart; - __le64 vend; - - /* - * profile to convert to, single is denoted by - * BTRFS_AVAIL_ALLOC_BIT_SINGLE - */ - __le64 target; - - /* BTRFS_BALANCE_ARGS_* */ - __le64 flags; - - /* - * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' - * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum - * and maximum - */ - union { - __le64 limit; - struct { - __le32 limit_min; - __le32 limit_max; - }; - }; - - /* - * Process chunks that cross stripes_min..stripes_max devices, - * BTRFS_BALANCE_ARGS_STRIPES_RANGE - */ - __le32 stripes_min; - __le32 stripes_max; - - __le64 unused[6]; -} __attribute__ ((__packed__)); - -/* - * store balance parameters to disk so that balance can be properly - * resumed after crash or unmount - */ -struct btrfs_balance_item { - /* BTRFS_BALANCE_* */ - __le64 flags; - - struct btrfs_disk_balance_args data; - struct btrfs_disk_balance_args meta; - struct btrfs_disk_balance_args sys; - - __le64 unused[4]; -} __attribute__ ((__packed__)); - -#define BTRFS_FILE_EXTENT_INLINE 0 -#define BTRFS_FILE_EXTENT_REG 1 -#define BTRFS_FILE_EXTENT_PREALLOC 2 - -struct btrfs_file_extent_item { - /* - * transaction id that created this extent - */ - __le64 generation; - /* - * max number of bytes to hold this extent in ram - * when we split a compressed extent we can't know how big - * each of the resulting pieces will be. So, this is - * an upper limit on the size of the extent in ram instead of - * an exact limit. - */ - __le64 ram_bytes; - - /* - * 32 bits for the various ways we might encode the data, - * including compression and encryption. If any of these - * are set to something a given disk format doesn't understand - * it is treated like an incompat flag for reading and writing, - * but not for stat. - */ - u8 compression; - u8 encryption; - __le16 other_encoding; /* spare for later use */ - - /* are we inline data or a real extent? */ - u8 type; - - /* - * disk space consumed by the extent, checksum blocks are included - * in these numbers - * - * At this offset in the structure, the inline extent data start. - */ - __le64 disk_bytenr; - __le64 disk_num_bytes; - /* - * the logical offset in file blocks (no csums) - * this extent record is for. This allows a file extent to point - * into the middle of an existing extent on disk, sharing it - * between two snapshots (useful if some bytes in the middle of the - * extent have changed - */ - __le64 offset; - /* - * the logical number of file blocks (no csums included). This - * always reflects the size uncompressed and without encoding. - */ - __le64 num_bytes; - -} __attribute__ ((__packed__)); - -struct btrfs_csum_item { - u8 csum; -} __attribute__ ((__packed__)); - -struct btrfs_dev_stats_item { - /* - * grow this item struct at the end for future enhancements and keep - * the existing values unchanged - */ - __le64 values[BTRFS_DEV_STAT_VALUES_MAX]; -} __attribute__ ((__packed__)); - -#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 -#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 -#define BTRFS_DEV_REPLACE_ITEM_STATE_NEVER_STARTED 0 -#define BTRFS_DEV_REPLACE_ITEM_STATE_STARTED 1 -#define BTRFS_DEV_REPLACE_ITEM_STATE_SUSPENDED 2 -#define BTRFS_DEV_REPLACE_ITEM_STATE_FINISHED 3 -#define BTRFS_DEV_REPLACE_ITEM_STATE_CANCELED 4 - struct btrfs_dev_replace { u64 replace_state; /* see #define above */ u64 time_started; /* seconds since 1-Jan-1970 */ @@ -979,167 +384,6 @@ struct btrfs_dev_replace { struct btrfs_scrub_progress scrub_progress; }; -struct btrfs_dev_replace_item { - /* - * grow this item struct at the end for future enhancements and keep - * the existing values unchanged - */ - __le64 src_devid; - __le64 cursor_left; - __le64 cursor_right; - __le64 cont_reading_from_srcdev_mode; - - __le64 replace_state; - __le64 time_started; - __le64 time_stopped; - __le64 num_write_errors; - __le64 num_uncorrectable_read_errors; -} __attribute__ ((__packed__)); - -/* different types of block groups (and chunks) */ -#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0) -#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1) -#define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2) -#define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3) -#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4) -#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5) -#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) -#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) -#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) -#define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \ - BTRFS_SPACE_INFO_GLOBAL_RSV) - -enum btrfs_raid_types { - BTRFS_RAID_RAID10, - BTRFS_RAID_RAID1, - BTRFS_RAID_DUP, - BTRFS_RAID_RAID0, - BTRFS_RAID_SINGLE, - BTRFS_RAID_RAID5, - BTRFS_RAID_RAID6, - BTRFS_NR_RAID_TYPES -}; - -#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ - BTRFS_BLOCK_GROUP_SYSTEM | \ - BTRFS_BLOCK_GROUP_METADATA) - -#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \ - BTRFS_BLOCK_GROUP_RAID1 | \ - BTRFS_BLOCK_GROUP_RAID5 | \ - BTRFS_BLOCK_GROUP_RAID6 | \ - BTRFS_BLOCK_GROUP_DUP | \ - BTRFS_BLOCK_GROUP_RAID10) -#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | \ - BTRFS_BLOCK_GROUP_RAID6) - -/* - * We need a bit for restriper to be able to tell when chunks of type - * SINGLE are available. This "extended" profile format is used in - * fs_info->avail_*_alloc_bits (in-memory) and balance item fields - * (on-disk). The corresponding on-disk bit in chunk.type is reserved - * to avoid remappings between two formats in future. - */ -#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) - -/* - * A fake block group type that is used to communicate global block reserve - * size to userspace via the SPACE_INFO ioctl. - */ -#define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49) - -#define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ - BTRFS_AVAIL_ALLOC_BIT_SINGLE) - -static inline u64 chunk_to_extended(u64 flags) -{ - if ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0) - flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE; - - return flags; -} -static inline u64 extended_to_chunk(u64 flags) -{ - return flags & ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; -} - -struct btrfs_block_group_item { - __le64 used; - __le64 chunk_objectid; - __le64 flags; -} __attribute__ ((__packed__)); - -struct btrfs_free_space_info { - __le32 extent_count; - __le32 flags; -} __attribute__ ((__packed__)); - -#define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0) - -#define BTRFS_QGROUP_LEVEL_SHIFT 48 -static inline u64 btrfs_qgroup_level(u64 qgroupid) -{ - return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; -} - -/* - * is subvolume quota turned on? - */ -#define BTRFS_QGROUP_STATUS_FLAG_ON (1ULL << 0) -/* - * RESCAN is set during the initialization phase - */ -#define BTRFS_QGROUP_STATUS_FLAG_RESCAN (1ULL << 1) -/* - * Some qgroup entries are known to be out of date, - * either because the configuration has changed in a way that - * makes a rescan necessary, or because the fs has been mounted - * with a non-qgroup-aware version. - * Turning qouta off and on again makes it inconsistent, too. - */ -#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2) - -#define BTRFS_QGROUP_STATUS_VERSION 1 - -struct btrfs_qgroup_status_item { - __le64 version; - /* - * the generation is updated during every commit. As older - * versions of btrfs are not aware of qgroups, it will be - * possible to detect inconsistencies by checking the - * generation on mount time - */ - __le64 generation; - - /* flag definitions see above */ - __le64 flags; - - /* - * only used during scanning to record the progress - * of the scan. It contains a logical address - */ - __le64 rescan; -} __attribute__ ((__packed__)); - -struct btrfs_qgroup_info_item { - __le64 generation; - __le64 rfer; - __le64 rfer_cmpr; - __le64 excl; - __le64 excl_cmpr; -} __attribute__ ((__packed__)); - -struct btrfs_qgroup_limit_item { - /* - * only updated when any of the other values change - */ - __le64 flags; - __le64 max_rfer; - __le64 max_excl; - __le64 rsv_rfer; - __le64 rsv_excl; -} __attribute__ ((__packed__)); - /* For raid type sysfs entries */ struct raid_kobject { int raid_type; @@ -1992,197 +1236,6 @@ struct btrfs_root { atomic_t qgroup_meta_rsv; }; - -/* - * inode items have the data typically returned from stat and store other - * info about object characteristics. There is one for every file and dir in - * the FS - */ -#define BTRFS_INODE_ITEM_KEY 1 -#define BTRFS_INODE_REF_KEY 12 -#define BTRFS_INODE_EXTREF_KEY 13 -#define BTRFS_XATTR_ITEM_KEY 24 -#define BTRFS_ORPHAN_ITEM_KEY 48 -/* reserve 2-15 close to the inode for later flexibility */ - -/* - * dir items are the name -> inode pointers in a directory. There is one - * for every name in a directory. - */ -#define BTRFS_DIR_LOG_ITEM_KEY 60 -#define BTRFS_DIR_LOG_INDEX_KEY 72 -#define BTRFS_DIR_ITEM_KEY 84 -#define BTRFS_DIR_INDEX_KEY 96 -/* - * extent data is for file data - */ -#define BTRFS_EXTENT_DATA_KEY 108 - -/* - * extent csums are stored in a separate tree and hold csums for - * an entire extent on disk. - */ -#define BTRFS_EXTENT_CSUM_KEY 128 - -/* - * root items point to tree roots. They are typically in the root - * tree used by the super block to find all the other trees - */ -#define BTRFS_ROOT_ITEM_KEY 132 - -/* - * root backrefs tie subvols and snapshots to the directory entries that - * reference them - */ -#define BTRFS_ROOT_BACKREF_KEY 144 - -/* - * root refs make a fast index for listing all of the snapshots and - * subvolumes referenced by a given root. They point directly to the - * directory item in the root that references the subvol - */ -#define BTRFS_ROOT_REF_KEY 156 - -/* - * extent items are in the extent map tree. These record which blocks - * are used, and how many references there are to each block - */ -#define BTRFS_EXTENT_ITEM_KEY 168 - -/* - * The same as the BTRFS_EXTENT_ITEM_KEY, except it's metadata we already know - * the length, so we save the level in key->offset instead of the length. - */ -#define BTRFS_METADATA_ITEM_KEY 169 - -#define BTRFS_TREE_BLOCK_REF_KEY 176 - -#define BTRFS_EXTENT_DATA_REF_KEY 178 - -#define BTRFS_EXTENT_REF_V0_KEY 180 - -#define BTRFS_SHARED_BLOCK_REF_KEY 182 - -#define BTRFS_SHARED_DATA_REF_KEY 184 - -/* - * block groups give us hints into the extent allocation trees. Which - * blocks are free etc etc - */ -#define BTRFS_BLOCK_GROUP_ITEM_KEY 192 - -/* - * Every block group is represented in the free space tree by a free space info - * item, which stores some accounting information. It is keyed on - * (block_group_start, FREE_SPACE_INFO, block_group_length). - */ -#define BTRFS_FREE_SPACE_INFO_KEY 198 - -/* - * A free space extent tracks an extent of space that is free in a block group. - * It is keyed on (start, FREE_SPACE_EXTENT, length). - */ -#define BTRFS_FREE_SPACE_EXTENT_KEY 199 - -/* - * When a block group becomes very fragmented, we convert it to use bitmaps - * instead of extents. A free space bitmap is keyed on - * (start, FREE_SPACE_BITMAP, length); the corresponding item is a bitmap with - * (length / sectorsize) bits. - */ -#define BTRFS_FREE_SPACE_BITMAP_KEY 200 - -#define BTRFS_DEV_EXTENT_KEY 204 -#define BTRFS_DEV_ITEM_KEY 216 -#define BTRFS_CHUNK_ITEM_KEY 228 - -/* - * Records the overall state of the qgroups. - * There's only one instance of this key present, - * (0, BTRFS_QGROUP_STATUS_KEY, 0) - */ -#define BTRFS_QGROUP_STATUS_KEY 240 -/* - * Records the currently used space of the qgroup. - * One key per qgroup, (0, BTRFS_QGROUP_INFO_KEY, qgroupid). - */ -#define BTRFS_QGROUP_INFO_KEY 242 -/* - * Contains the user configured limits for the qgroup. - * One key per qgroup, (0, BTRFS_QGROUP_LIMIT_KEY, qgroupid). - */ -#define BTRFS_QGROUP_LIMIT_KEY 244 -/* - * Records the child-parent relationship of qgroups. For - * each relation, 2 keys are present: - * (childid, BTRFS_QGROUP_RELATION_KEY, parentid) - * (parentid, BTRFS_QGROUP_RELATION_KEY, childid) - */ -#define BTRFS_QGROUP_RELATION_KEY 246 - -/* - * Obsolete name, see BTRFS_TEMPORARY_ITEM_KEY. - */ -#define BTRFS_BALANCE_ITEM_KEY 248 - -/* - * The key type for tree items that are stored persistently, but do not need to - * exist for extended period of time. The items can exist in any tree. - * - * [subtype, BTRFS_TEMPORARY_ITEM_KEY, data] - * - * Existing items: - * - * - balance status item - * (BTRFS_BALANCE_OBJECTID, BTRFS_TEMPORARY_ITEM_KEY, 0) - */ -#define BTRFS_TEMPORARY_ITEM_KEY 248 - -/* - * Obsolete name, see BTRFS_PERSISTENT_ITEM_KEY - */ -#define BTRFS_DEV_STATS_KEY 249 - -/* - * The key type for tree items that are stored persistently and usually exist - * for a long period, eg. filesystem lifetime. The item kinds can be status - * information, stats or preference values. The item can exist in any tree. - * - * [subtype, BTRFS_PERSISTENT_ITEM_KEY, data] - * - * Existing items: - * - * - device statistics, store IO stats in the device tree, one key for all - * stats - * (BTRFS_DEV_STATS_OBJECTID, BTRFS_DEV_STATS_KEY, 0) - */ -#define BTRFS_PERSISTENT_ITEM_KEY 249 - -/* - * Persistantly stores the device replace state in the device tree. - * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0). - */ -#define BTRFS_DEV_REPLACE_KEY 250 - -/* - * Stores items that allow to quickly map UUIDs to something else. - * These items are part of the filesystem UUID tree. - * The key is built like this: - * (UUID_upper_64_bits, BTRFS_UUID_KEY*, UUID_lower_64_bits). - */ -#if BTRFS_UUID_SIZE != 16 -#error "UUID items require BTRFS_UUID_SIZE == 16!" -#endif -#define BTRFS_UUID_KEY_SUBVOL 251 /* for UUIDs assigned to subvols */ -#define BTRFS_UUID_KEY_RECEIVED_SUBVOL 252 /* for UUIDs assigned to - * received subvols */ - -/* - * string items are for debugging. They just store a short string of - * data in the FS - */ -#define BTRFS_STRING_ITEM_KEY 253 - /* * Flags for mount options. * diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h new file mode 100644 index 000000000000..1e875057d6b2 --- /dev/null +++ b/include/uapi/linux/btrfs_tree.h @@ -0,0 +1,966 @@ +#ifndef _BTRFS_CTREE_H_ +#define _BTRFS_CTREE_H_ + +/* + * This header contains the structure definitions and constants used + * by file system objects that can be retrieved using + * the BTRFS_IOC_SEARCH_TREE ioctl. That means basically anything that + * is needed to describe a leaf node's key or item contents. + */ + +/* holds pointers to all of the tree roots */ +#define BTRFS_ROOT_TREE_OBJECTID 1ULL + +/* stores information about which extents are in use, and reference counts */ +#define BTRFS_EXTENT_TREE_OBJECTID 2ULL + +/* + * chunk tree stores translations from logical -> physical block numbering + * the super block points to the chunk tree + */ +#define BTRFS_CHUNK_TREE_OBJECTID 3ULL + +/* + * stores information about which areas of a given device are in use. + * one per device. The tree of tree roots points to the device tree + */ +#define BTRFS_DEV_TREE_OBJECTID 4ULL + +/* one per subvolume, storing files and directories */ +#define BTRFS_FS_TREE_OBJECTID 5ULL + +/* directory objectid inside the root tree */ +#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL + +/* holds checksums of all the data extents */ +#define BTRFS_CSUM_TREE_OBJECTID 7ULL + +/* holds quota configuration and tracking */ +#define BTRFS_QUOTA_TREE_OBJECTID 8ULL + +/* for storing items that use the BTRFS_UUID_KEY* types */ +#define BTRFS_UUID_TREE_OBJECTID 9ULL + +/* tracks free space in block groups. */ +#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL + +/* device stats in the device tree */ +#define BTRFS_DEV_STATS_OBJECTID 0ULL + +/* for storing balance parameters in the root tree */ +#define BTRFS_BALANCE_OBJECTID -4ULL + +/* orhpan objectid for tracking unlinked/truncated files */ +#define BTRFS_ORPHAN_OBJECTID -5ULL + +/* does write ahead logging to speed up fsyncs */ +#define BTRFS_TREE_LOG_OBJECTID -6ULL +#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL + +/* for space balancing */ +#define BTRFS_TREE_RELOC_OBJECTID -8ULL +#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL + +/* + * extent checksums all have this objectid + * this allows them to share the logging tree + * for fsyncs + */ +#define BTRFS_EXTENT_CSUM_OBJECTID -10ULL + +/* For storing free space cache */ +#define BTRFS_FREE_SPACE_OBJECTID -11ULL + +/* + * The inode number assigned to the special inode for storing + * free ino cache + */ +#define BTRFS_FREE_INO_OBJECTID -12ULL + +/* dummy objectid represents multiple objectids */ +#define BTRFS_MULTIPLE_OBJECTIDS -255ULL + +/* + * All files have objectids in this range. + */ +#define BTRFS_FIRST_FREE_OBJECTID 256ULL +#define BTRFS_LAST_FREE_OBJECTID -256ULL +#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL + + +/* + * the device items go into the chunk tree. The key is in the form + * [ 1 BTRFS_DEV_ITEM_KEY device_id ] + */ +#define BTRFS_DEV_ITEMS_OBJECTID 1ULL + +#define BTRFS_BTREE_INODE_OBJECTID 1 + +#define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2 + +#define BTRFS_DEV_REPLACE_DEVID 0ULL + +/* + * inode items have the data typically returned from stat and store other + * info about object characteristics. There is one for every file and dir in + * the FS + */ +#define BTRFS_INODE_ITEM_KEY 1 +#define BTRFS_INODE_REF_KEY 12 +#define BTRFS_INODE_EXTREF_KEY 13 +#define BTRFS_XATTR_ITEM_KEY 24 +#define BTRFS_ORPHAN_ITEM_KEY 48 +/* reserve 2-15 close to the inode for later flexibility */ + +/* + * dir items are the name -> inode pointers in a directory. There is one + * for every name in a directory. + */ +#define BTRFS_DIR_LOG_ITEM_KEY 60 +#define BTRFS_DIR_LOG_INDEX_KEY 72 +#define BTRFS_DIR_ITEM_KEY 84 +#define BTRFS_DIR_INDEX_KEY 96 +/* + * extent data is for file data + */ +#define BTRFS_EXTENT_DATA_KEY 108 + +/* + * extent csums are stored in a separate tree and hold csums for + * an entire extent on disk. + */ +#define BTRFS_EXTENT_CSUM_KEY 128 + +/* + * root items point to tree roots. They are typically in the root + * tree used by the super block to find all the other trees + */ +#define BTRFS_ROOT_ITEM_KEY 132 + +/* + * root backrefs tie subvols and snapshots to the directory entries that + * reference them + */ +#define BTRFS_ROOT_BACKREF_KEY 144 + +/* + * root refs make a fast index for listing all of the snapshots and + * subvolumes referenced by a given root. They point directly to the + * directory item in the root that references the subvol + */ +#define BTRFS_ROOT_REF_KEY 156 + +/* + * extent items are in the extent map tree. These record which blocks + * are used, and how many references there are to each block + */ +#define BTRFS_EXTENT_ITEM_KEY 168 + +/* + * The same as the BTRFS_EXTENT_ITEM_KEY, except it's metadata we already know + * the length, so we save the level in key->offset instead of the length. + */ +#define BTRFS_METADATA_ITEM_KEY 169 + +#define BTRFS_TREE_BLOCK_REF_KEY 176 + +#define BTRFS_EXTENT_DATA_REF_KEY 178 + +#define BTRFS_EXTENT_REF_V0_KEY 180 + +#define BTRFS_SHARED_BLOCK_REF_KEY 182 + +#define BTRFS_SHARED_DATA_REF_KEY 184 + +/* + * block groups give us hints into the extent allocation trees. Which + * blocks are free etc etc + */ +#define BTRFS_BLOCK_GROUP_ITEM_KEY 192 + +/* + * Every block group is represented in the free space tree by a free space info + * item, which stores some accounting information. It is keyed on + * (block_group_start, FREE_SPACE_INFO, block_group_length). + */ +#define BTRFS_FREE_SPACE_INFO_KEY 198 + +/* + * A free space extent tracks an extent of space that is free in a block group. + * It is keyed on (start, FREE_SPACE_EXTENT, length). + */ +#define BTRFS_FREE_SPACE_EXTENT_KEY 199 + +/* + * When a block group becomes very fragmented, we convert it to use bitmaps + * instead of extents. A free space bitmap is keyed on + * (start, FREE_SPACE_BITMAP, length); the corresponding item is a bitmap with + * (length / sectorsize) bits. + */ +#define BTRFS_FREE_SPACE_BITMAP_KEY 200 + +#define BTRFS_DEV_EXTENT_KEY 204 +#define BTRFS_DEV_ITEM_KEY 216 +#define BTRFS_CHUNK_ITEM_KEY 228 + +/* + * Records the overall state of the qgroups. + * There's only one instance of this key present, + * (0, BTRFS_QGROUP_STATUS_KEY, 0) + */ +#define BTRFS_QGROUP_STATUS_KEY 240 +/* + * Records the currently used space of the qgroup. + * One key per qgroup, (0, BTRFS_QGROUP_INFO_KEY, qgroupid). + */ +#define BTRFS_QGROUP_INFO_KEY 242 +/* + * Contains the user configured limits for the qgroup. + * One key per qgroup, (0, BTRFS_QGROUP_LIMIT_KEY, qgroupid). + */ +#define BTRFS_QGROUP_LIMIT_KEY 244 +/* + * Records the child-parent relationship of qgroups. For + * each relation, 2 keys are present: + * (childid, BTRFS_QGROUP_RELATION_KEY, parentid) + * (parentid, BTRFS_QGROUP_RELATION_KEY, childid) + */ +#define BTRFS_QGROUP_RELATION_KEY 246 + +/* + * Obsolete name, see BTRFS_TEMPORARY_ITEM_KEY. + */ +#define BTRFS_BALANCE_ITEM_KEY 248 + +/* + * The key type for tree items that are stored persistently, but do not need to + * exist for extended period of time. The items can exist in any tree. + * + * [subtype, BTRFS_TEMPORARY_ITEM_KEY, data] + * + * Existing items: + * + * - balance status item + * (BTRFS_BALANCE_OBJECTID, BTRFS_TEMPORARY_ITEM_KEY, 0) + */ +#define BTRFS_TEMPORARY_ITEM_KEY 248 + +/* + * Obsolete name, see BTRFS_PERSISTENT_ITEM_KEY + */ +#define BTRFS_DEV_STATS_KEY 249 + +/* + * The key type for tree items that are stored persistently and usually exist + * for a long period, eg. filesystem lifetime. The item kinds can be status + * information, stats or preference values. The item can exist in any tree. + * + * [subtype, BTRFS_PERSISTENT_ITEM_KEY, data] + * + * Existing items: + * + * - device statistics, store IO stats in the device tree, one key for all + * stats + * (BTRFS_DEV_STATS_OBJECTID, BTRFS_DEV_STATS_KEY, 0) + */ +#define BTRFS_PERSISTENT_ITEM_KEY 249 + +/* + * Persistantly stores the device replace state in the device tree. + * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0). + */ +#define BTRFS_DEV_REPLACE_KEY 250 + +/* + * Stores items that allow to quickly map UUIDs to something else. + * These items are part of the filesystem UUID tree. + * The key is built like this: + * (UUID_upper_64_bits, BTRFS_UUID_KEY*, UUID_lower_64_bits). + */ +#if BTRFS_UUID_SIZE != 16 +#error "UUID items require BTRFS_UUID_SIZE == 16!" +#endif +#define BTRFS_UUID_KEY_SUBVOL 251 /* for UUIDs assigned to subvols */ +#define BTRFS_UUID_KEY_RECEIVED_SUBVOL 252 /* for UUIDs assigned to + * received subvols */ + +/* + * string items are for debugging. They just store a short string of + * data in the FS + */ +#define BTRFS_STRING_ITEM_KEY 253 + + + +/* 32 bytes in various csum fields */ +#define BTRFS_CSUM_SIZE 32 + +/* csum types */ +#define BTRFS_CSUM_TYPE_CRC32 0 + +/* + * flags definitions for directory entry item type + * + * Used by: + * struct btrfs_dir_item.type + */ +#define BTRFS_FT_UNKNOWN 0 +#define BTRFS_FT_REG_FILE 1 +#define BTRFS_FT_DIR 2 +#define BTRFS_FT_CHRDEV 3 +#define BTRFS_FT_BLKDEV 4 +#define BTRFS_FT_FIFO 5 +#define BTRFS_FT_SOCK 6 +#define BTRFS_FT_SYMLINK 7 +#define BTRFS_FT_XATTR 8 +#define BTRFS_FT_MAX 9 + +/* + * The key defines the order in the tree, and so it also defines (optimal) + * block layout. + * + * objectid corresponds to the inode number. + * + * type tells us things about the object, and is a kind of stream selector. + * so for a given inode, keys with type of 1 might refer to the inode data, + * type of 2 may point to file data in the btree and type == 3 may point to + * extents. + * + * offset is the starting byte offset for this key in the stream. + * + * btrfs_disk_key is in disk byte order. struct btrfs_key is always + * in cpu native order. Otherwise they are identical and their sizes + * should be the same (ie both packed) + */ +struct btrfs_disk_key { + __le64 objectid; + u8 type; + __le64 offset; +} __attribute__ ((__packed__)); + +struct btrfs_key { + u64 objectid; + u8 type; + u64 offset; +} __attribute__ ((__packed__)); + +struct btrfs_dev_item { + /* the internal btrfs device id */ + __le64 devid; + + /* size of the device */ + __le64 total_bytes; + + /* bytes used */ + __le64 bytes_used; + + /* optimal io alignment for this device */ + __le32 io_align; + + /* optimal io width for this device */ + __le32 io_width; + + /* minimal io size for this device */ + __le32 sector_size; + + /* type and info about this device */ + __le64 type; + + /* expected generation for this device */ + __le64 generation; + + /* + * starting byte of this partition on the device, + * to allow for stripe alignment in the future + */ + __le64 start_offset; + + /* grouping information for allocation decisions */ + __le32 dev_group; + + /* seek speed 0-100 where 100 is fastest */ + u8 seek_speed; + + /* bandwidth 0-100 where 100 is fastest */ + u8 bandwidth; + + /* btrfs generated uuid for this device */ + u8 uuid[BTRFS_UUID_SIZE]; + + /* uuid of FS who owns this device */ + u8 fsid[BTRFS_UUID_SIZE]; +} __attribute__ ((__packed__)); + +struct btrfs_stripe { + __le64 devid; + __le64 offset; + u8 dev_uuid[BTRFS_UUID_SIZE]; +} __attribute__ ((__packed__)); + +struct btrfs_chunk { + /* size of this chunk in bytes */ + __le64 length; + + /* objectid of the root referencing this chunk */ + __le64 owner; + + __le64 stripe_len; + __le64 type; + + /* optimal io alignment for this chunk */ + __le32 io_align; + + /* optimal io width for this chunk */ + __le32 io_width; + + /* minimal io size for this chunk */ + __le32 sector_size; + + /* 2^16 stripes is quite a lot, a second limit is the size of a single + * item in the btree + */ + __le16 num_stripes; + + /* sub stripes only matter for raid10 */ + __le16 sub_stripes; + struct btrfs_stripe stripe; + /* additional stripes go here */ +} __attribute__ ((__packed__)); + +#define BTRFS_FREE_SPACE_EXTENT 1 +#define BTRFS_FREE_SPACE_BITMAP 2 + +struct btrfs_free_space_entry { + __le64 offset; + __le64 bytes; + u8 type; +} __attribute__ ((__packed__)); + +struct btrfs_free_space_header { + struct btrfs_disk_key location; + __le64 generation; + __le64 num_entries; + __le64 num_bitmaps; +} __attribute__ ((__packed__)); + +#define BTRFS_HEADER_FLAG_WRITTEN (1ULL << 0) +#define BTRFS_HEADER_FLAG_RELOC (1ULL << 1) + +/* Super block flags */ +/* Errors detected */ +#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2) + +#define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32) +#define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33) + + +/* + * items in the extent btree are used to record the objectid of the + * owner of the block and the number of references + */ + +struct btrfs_extent_item { + __le64 refs; + __le64 generation; + __le64 flags; +} __attribute__ ((__packed__)); + +struct btrfs_extent_item_v0 { + __le32 refs; +} __attribute__ ((__packed__)); + + +#define BTRFS_EXTENT_FLAG_DATA (1ULL << 0) +#define BTRFS_EXTENT_FLAG_TREE_BLOCK (1ULL << 1) + +/* following flags only apply to tree blocks */ + +/* use full backrefs for extent pointers in the block */ +#define BTRFS_BLOCK_FLAG_FULL_BACKREF (1ULL << 8) + +/* + * this flag is only used internally by scrub and may be changed at any time + * it is only declared here to avoid collisions + */ +#define BTRFS_EXTENT_FLAG_SUPER (1ULL << 48) + +struct btrfs_tree_block_info { + struct btrfs_disk_key key; + u8 level; +} __attribute__ ((__packed__)); + +struct btrfs_extent_data_ref { + __le64 root; + __le64 objectid; + __le64 offset; + __le32 count; +} __attribute__ ((__packed__)); + +struct btrfs_shared_data_ref { + __le32 count; +} __attribute__ ((__packed__)); + +struct btrfs_extent_inline_ref { + u8 type; + __le64 offset; +} __attribute__ ((__packed__)); + +/* old style backrefs item */ +struct btrfs_extent_ref_v0 { + __le64 root; + __le64 generation; + __le64 objectid; + __le32 count; +} __attribute__ ((__packed__)); + + +/* dev extents record free space on individual devices. The owner + * field points back to the chunk allocation mapping tree that allocated + * the extent. The chunk tree uuid field is a way to double check the owner + */ +struct btrfs_dev_extent { + __le64 chunk_tree; + __le64 chunk_objectid; + __le64 chunk_offset; + __le64 length; + u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; +} __attribute__ ((__packed__)); + +struct btrfs_inode_ref { + __le64 index; + __le16 name_len; + /* name goes here */ +} __attribute__ ((__packed__)); + +struct btrfs_inode_extref { + __le64 parent_objectid; + __le64 index; + __le16 name_len; + __u8 name[0]; + /* name goes here */ +} __attribute__ ((__packed__)); + +struct btrfs_timespec { + __le64 sec; + __le32 nsec; +} __attribute__ ((__packed__)); + +struct btrfs_inode_item { + /* nfs style generation number */ + __le64 generation; + /* transid that last touched this inode */ + __le64 transid; + __le64 size; + __le64 nbytes; + __le64 block_group; + __le32 nlink; + __le32 uid; + __le32 gid; + __le32 mode; + __le64 rdev; + __le64 flags; + + /* modification sequence number for NFS */ + __le64 sequence; + + /* + * a little future expansion, for more than this we can + * just grow the inode item and version it + */ + __le64 reserved[4]; + struct btrfs_timespec atime; + struct btrfs_timespec ctime; + struct btrfs_timespec mtime; + struct btrfs_timespec otime; +} __attribute__ ((__packed__)); + +struct btrfs_dir_log_item { + __le64 end; +} __attribute__ ((__packed__)); + +struct btrfs_dir_item { + struct btrfs_disk_key location; + __le64 transid; + __le16 data_len; + __le16 name_len; + u8 type; +} __attribute__ ((__packed__)); + +#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0) + +/* + * Internal in-memory flag that a subvolume has been marked for deletion but + * still visible as a directory + */ +#define BTRFS_ROOT_SUBVOL_DEAD (1ULL << 48) + +struct btrfs_root_item { + struct btrfs_inode_item inode; + __le64 generation; + __le64 root_dirid; + __le64 bytenr; + __le64 byte_limit; + __le64 bytes_used; + __le64 last_snapshot; + __le64 flags; + __le32 refs; + struct btrfs_disk_key drop_progress; + u8 drop_level; + u8 level; + + /* + * The following fields appear after subvol_uuids+subvol_times + * were introduced. + */ + + /* + * This generation number is used to test if the new fields are valid + * and up to date while reading the root item. Every time the root item + * is written out, the "generation" field is copied into this field. If + * anyone ever mounted the fs with an older kernel, we will have + * mismatching generation values here and thus must invalidate the + * new fields. See btrfs_update_root and btrfs_find_last_root for + * details. + * the offset of generation_v2 is also used as the start for the memset + * when invalidating the fields. + */ + __le64 generation_v2; + u8 uuid[BTRFS_UUID_SIZE]; + u8 parent_uuid[BTRFS_UUID_SIZE]; + u8 received_uuid[BTRFS_UUID_SIZE]; + __le64 ctransid; /* updated when an inode changes */ + __le64 otransid; /* trans when created */ + __le64 stransid; /* trans when sent. non-zero for received subvol */ + __le64 rtransid; /* trans when received. non-zero for received subvol */ + struct btrfs_timespec ctime; + struct btrfs_timespec otime; + struct btrfs_timespec stime; + struct btrfs_timespec rtime; + __le64 reserved[8]; /* for future */ +} __attribute__ ((__packed__)); + +/* + * this is used for both forward and backward root refs + */ +struct btrfs_root_ref { + __le64 dirid; + __le64 sequence; + __le16 name_len; +} __attribute__ ((__packed__)); + +struct btrfs_disk_balance_args { + /* + * profiles to operate on, single is denoted by + * BTRFS_AVAIL_ALLOC_BIT_SINGLE + */ + __le64 profiles; + + /* + * usage filter + * BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N' + * BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max + */ + union { + __le64 usage; + struct { + __le32 usage_min; + __le32 usage_max; + }; + }; + + /* devid filter */ + __le64 devid; + + /* devid subset filter [pstart..pend) */ + __le64 pstart; + __le64 pend; + + /* btrfs virtual address space subset filter [vstart..vend) */ + __le64 vstart; + __le64 vend; + + /* + * profile to convert to, single is denoted by + * BTRFS_AVAIL_ALLOC_BIT_SINGLE + */ + __le64 target; + + /* BTRFS_BALANCE_ARGS_* */ + __le64 flags; + + /* + * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' + * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum + * and maximum + */ + union { + __le64 limit; + struct { + __le32 limit_min; + __le32 limit_max; + }; + }; + + /* + * Process chunks that cross stripes_min..stripes_max devices, + * BTRFS_BALANCE_ARGS_STRIPES_RANGE + */ + __le32 stripes_min; + __le32 stripes_max; + + __le64 unused[6]; +} __attribute__ ((__packed__)); + +/* + * store balance parameters to disk so that balance can be properly + * resumed after crash or unmount + */ +struct btrfs_balance_item { + /* BTRFS_BALANCE_* */ + __le64 flags; + + struct btrfs_disk_balance_args data; + struct btrfs_disk_balance_args meta; + struct btrfs_disk_balance_args sys; + + __le64 unused[4]; +} __attribute__ ((__packed__)); + +#define BTRFS_FILE_EXTENT_INLINE 0 +#define BTRFS_FILE_EXTENT_REG 1 +#define BTRFS_FILE_EXTENT_PREALLOC 2 + +struct btrfs_file_extent_item { + /* + * transaction id that created this extent + */ + __le64 generation; + /* + * max number of bytes to hold this extent in ram + * when we split a compressed extent we can't know how big + * each of the resulting pieces will be. So, this is + * an upper limit on the size of the extent in ram instead of + * an exact limit. + */ + __le64 ram_bytes; + + /* + * 32 bits for the various ways we might encode the data, + * including compression and encryption. If any of these + * are set to something a given disk format doesn't understand + * it is treated like an incompat flag for reading and writing, + * but not for stat. + */ + u8 compression; + u8 encryption; + __le16 other_encoding; /* spare for later use */ + + /* are we inline data or a real extent? */ + u8 type; + + /* + * disk space consumed by the extent, checksum blocks are included + * in these numbers + * + * At this offset in the structure, the inline extent data start. + */ + __le64 disk_bytenr; + __le64 disk_num_bytes; + /* + * the logical offset in file blocks (no csums) + * this extent record is for. This allows a file extent to point + * into the middle of an existing extent on disk, sharing it + * between two snapshots (useful if some bytes in the middle of the + * extent have changed + */ + __le64 offset; + /* + * the logical number of file blocks (no csums included). This + * always reflects the size uncompressed and without encoding. + */ + __le64 num_bytes; + +} __attribute__ ((__packed__)); + +struct btrfs_csum_item { + u8 csum; +} __attribute__ ((__packed__)); + +struct btrfs_dev_stats_item { + /* + * grow this item struct at the end for future enhancements and keep + * the existing values unchanged + */ + __le64 values[BTRFS_DEV_STAT_VALUES_MAX]; +} __attribute__ ((__packed__)); + +#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 +#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 +#define BTRFS_DEV_REPLACE_ITEM_STATE_NEVER_STARTED 0 +#define BTRFS_DEV_REPLACE_ITEM_STATE_STARTED 1 +#define BTRFS_DEV_REPLACE_ITEM_STATE_SUSPENDED 2 +#define BTRFS_DEV_REPLACE_ITEM_STATE_FINISHED 3 +#define BTRFS_DEV_REPLACE_ITEM_STATE_CANCELED 4 + +struct btrfs_dev_replace_item { + /* + * grow this item struct at the end for future enhancements and keep + * the existing values unchanged + */ + __le64 src_devid; + __le64 cursor_left; + __le64 cursor_right; + __le64 cont_reading_from_srcdev_mode; + + __le64 replace_state; + __le64 time_started; + __le64 time_stopped; + __le64 num_write_errors; + __le64 num_uncorrectable_read_errors; +} __attribute__ ((__packed__)); + +/* different types of block groups (and chunks) */ +#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0) +#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1) +#define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2) +#define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3) +#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4) +#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5) +#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) +#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) +#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) +#define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \ + BTRFS_SPACE_INFO_GLOBAL_RSV) + +enum btrfs_raid_types { + BTRFS_RAID_RAID10, + BTRFS_RAID_RAID1, + BTRFS_RAID_DUP, + BTRFS_RAID_RAID0, + BTRFS_RAID_SINGLE, + BTRFS_RAID_RAID5, + BTRFS_RAID_RAID6, + BTRFS_NR_RAID_TYPES +}; + +#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ + BTRFS_BLOCK_GROUP_SYSTEM | \ + BTRFS_BLOCK_GROUP_METADATA) + +#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \ + BTRFS_BLOCK_GROUP_RAID1 | \ + BTRFS_BLOCK_GROUP_RAID5 | \ + BTRFS_BLOCK_GROUP_RAID6 | \ + BTRFS_BLOCK_GROUP_DUP | \ + BTRFS_BLOCK_GROUP_RAID10) +#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | \ + BTRFS_BLOCK_GROUP_RAID6) + +/* + * We need a bit for restriper to be able to tell when chunks of type + * SINGLE are available. This "extended" profile format is used in + * fs_info->avail_*_alloc_bits (in-memory) and balance item fields + * (on-disk). The corresponding on-disk bit in chunk.type is reserved + * to avoid remappings between two formats in future. + */ +#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) + +/* + * A fake block group type that is used to communicate global block reserve + * size to userspace via the SPACE_INFO ioctl. + */ +#define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49) + +#define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ + BTRFS_AVAIL_ALLOC_BIT_SINGLE) + +static inline u64 chunk_to_extended(u64 flags) +{ + if ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0) + flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE; + + return flags; +} +static inline u64 extended_to_chunk(u64 flags) +{ + return flags & ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; +} + +struct btrfs_block_group_item { + __le64 used; + __le64 chunk_objectid; + __le64 flags; +} __attribute__ ((__packed__)); + +struct btrfs_free_space_info { + __le32 extent_count; + __le32 flags; +} __attribute__ ((__packed__)); + +#define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0) + +#define BTRFS_QGROUP_LEVEL_SHIFT 48 +static inline u64 btrfs_qgroup_level(u64 qgroupid) +{ + return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; +} + +/* + * is subvolume quota turned on? + */ +#define BTRFS_QGROUP_STATUS_FLAG_ON (1ULL << 0) +/* + * RESCAN is set during the initialization phase + */ +#define BTRFS_QGROUP_STATUS_FLAG_RESCAN (1ULL << 1) +/* + * Some qgroup entries are known to be out of date, + * either because the configuration has changed in a way that + * makes a rescan necessary, or because the fs has been mounted + * with a non-qgroup-aware version. + * Turning qouta off and on again makes it inconsistent, too. + */ +#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2) + +#define BTRFS_QGROUP_STATUS_VERSION 1 + +struct btrfs_qgroup_status_item { + __le64 version; + /* + * the generation is updated during every commit. As older + * versions of btrfs are not aware of qgroups, it will be + * possible to detect inconsistencies by checking the + * generation on mount time + */ + __le64 generation; + + /* flag definitions see above */ + __le64 flags; + + /* + * only used during scanning to record the progress + * of the scan. It contains a logical address + */ + __le64 rescan; +} __attribute__ ((__packed__)); + +struct btrfs_qgroup_info_item { + __le64 generation; + __le64 rfer; + __le64 rfer_cmpr; + __le64 excl; + __le64 excl_cmpr; +} __attribute__ ((__packed__)); + +struct btrfs_qgroup_limit_item { + /* + * only updated when any of the other values change + */ + __le64 flags; + __le64 max_rfer; + __le64 max_excl; + __le64 rsv_rfer; + __le64 rsv_excl; +} __attribute__ ((__packed__)); + +#endif /* _BTRFS_CTREE_H_ */ -- GitLab From 14b05c5106312744badb463e7fb9a78811e44fc0 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 1 Apr 2016 16:14:30 -0400 Subject: [PATCH 4939/9938] btrfs: uapi/linux/btrfs_tree.h, use __u8 and __u64 u8 and u64 aren't exported to userspace, while __u8 and __u64 are. Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Reviewed-by: Josef Bacik Signed-off-by: David Sterba --- include/uapi/linux/btrfs_tree.h | 52 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h index 1e875057d6b2..d5ad15a106a7 100644 --- a/include/uapi/linux/btrfs_tree.h +++ b/include/uapi/linux/btrfs_tree.h @@ -334,14 +334,14 @@ */ struct btrfs_disk_key { __le64 objectid; - u8 type; + __u8 type; __le64 offset; } __attribute__ ((__packed__)); struct btrfs_key { - u64 objectid; - u8 type; - u64 offset; + __u64 objectid; + __u8 type; + __u64 offset; } __attribute__ ((__packed__)); struct btrfs_dev_item { @@ -379,22 +379,22 @@ struct btrfs_dev_item { __le32 dev_group; /* seek speed 0-100 where 100 is fastest */ - u8 seek_speed; + __u8 seek_speed; /* bandwidth 0-100 where 100 is fastest */ - u8 bandwidth; + __u8 bandwidth; /* btrfs generated uuid for this device */ - u8 uuid[BTRFS_UUID_SIZE]; + __u8 uuid[BTRFS_UUID_SIZE]; /* uuid of FS who owns this device */ - u8 fsid[BTRFS_UUID_SIZE]; + __u8 fsid[BTRFS_UUID_SIZE]; } __attribute__ ((__packed__)); struct btrfs_stripe { __le64 devid; __le64 offset; - u8 dev_uuid[BTRFS_UUID_SIZE]; + __u8 dev_uuid[BTRFS_UUID_SIZE]; } __attribute__ ((__packed__)); struct btrfs_chunk { @@ -433,7 +433,7 @@ struct btrfs_chunk { struct btrfs_free_space_entry { __le64 offset; __le64 bytes; - u8 type; + __u8 type; } __attribute__ ((__packed__)); struct btrfs_free_space_header { @@ -486,7 +486,7 @@ struct btrfs_extent_item_v0 { struct btrfs_tree_block_info { struct btrfs_disk_key key; - u8 level; + __u8 level; } __attribute__ ((__packed__)); struct btrfs_extent_data_ref { @@ -501,7 +501,7 @@ struct btrfs_shared_data_ref { } __attribute__ ((__packed__)); struct btrfs_extent_inline_ref { - u8 type; + __u8 type; __le64 offset; } __attribute__ ((__packed__)); @@ -523,7 +523,7 @@ struct btrfs_dev_extent { __le64 chunk_objectid; __le64 chunk_offset; __le64 length; - u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; + __u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; } __attribute__ ((__packed__)); struct btrfs_inode_ref { @@ -583,7 +583,7 @@ struct btrfs_dir_item { __le64 transid; __le16 data_len; __le16 name_len; - u8 type; + __u8 type; } __attribute__ ((__packed__)); #define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0) @@ -605,8 +605,8 @@ struct btrfs_root_item { __le64 flags; __le32 refs; struct btrfs_disk_key drop_progress; - u8 drop_level; - u8 level; + __u8 drop_level; + __u8 level; /* * The following fields appear after subvol_uuids+subvol_times @@ -625,9 +625,9 @@ struct btrfs_root_item { * when invalidating the fields. */ __le64 generation_v2; - u8 uuid[BTRFS_UUID_SIZE]; - u8 parent_uuid[BTRFS_UUID_SIZE]; - u8 received_uuid[BTRFS_UUID_SIZE]; + __u8 uuid[BTRFS_UUID_SIZE]; + __u8 parent_uuid[BTRFS_UUID_SIZE]; + __u8 received_uuid[BTRFS_UUID_SIZE]; __le64 ctransid; /* updated when an inode changes */ __le64 otransid; /* trans when created */ __le64 stransid; /* trans when sent. non-zero for received subvol */ @@ -751,12 +751,12 @@ struct btrfs_file_extent_item { * it is treated like an incompat flag for reading and writing, * but not for stat. */ - u8 compression; - u8 encryption; + __u8 compression; + __u8 encryption; __le16 other_encoding; /* spare for later use */ /* are we inline data or a real extent? */ - u8 type; + __u8 type; /* * disk space consumed by the extent, checksum blocks are included @@ -783,7 +783,7 @@ struct btrfs_file_extent_item { } __attribute__ ((__packed__)); struct btrfs_csum_item { - u8 csum; + __u8 csum; } __attribute__ ((__packed__)); struct btrfs_dev_stats_item { @@ -874,14 +874,14 @@ enum btrfs_raid_types { #define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ BTRFS_AVAIL_ALLOC_BIT_SINGLE) -static inline u64 chunk_to_extended(u64 flags) +static inline __u64 chunk_to_extended(__u64 flags) { if ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0) flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE; return flags; } -static inline u64 extended_to_chunk(u64 flags) +static inline __u64 extended_to_chunk(__u64 flags) { return flags & ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; } @@ -900,7 +900,7 @@ struct btrfs_free_space_info { #define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0) #define BTRFS_QGROUP_LEVEL_SHIFT 48 -static inline u64 btrfs_qgroup_level(u64 qgroupid) +static inline __u64 btrfs_qgroup_level(__u64 qgroupid) { return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; } -- GitLab From 88f10e37e150569a390be7a6161fa0f26b7372e9 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 26 Apr 2016 09:39:05 -0700 Subject: [PATCH 4940/9938] sched/core, ARM: Include linux/preempt.h from asm/mmu_context.h arm's mmu_context.h uses preempt_enable_no_resched and but doesn't include anything that would pull in the declaration. If I start including from without this, the build breaks. Signed-off-by: Andy Lutomirski Reviewed-by: Borislav Petkov Cc: Borislav Petkov Cc: Catalin Marinas Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Russell King Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/5b95730a70f2dafe12d4fbf38d20eb7330d67ba3.1461688545.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/arm/include/asm/mmu_context.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h index fa5b42d44985..ed73babc0dc9 100644 --- a/arch/arm/include/asm/mmu_context.h +++ b/arch/arm/include/asm/mmu_context.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include -- GitLab From c5b591e96db9d99d0126acf93f24e1fb8b368343 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:33 +0100 Subject: [PATCH 4941/9938] efi: Get rid of the EFI_SYSTEM_TABLES status bit The EFI_SYSTEM_TABLES status bit is set by all EFI supporting architectures upon discovery of the EFI system table, but the bit is never tested in any code we have in the tree. So remove it. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Leif Lindholm Cc: Luck, Tony Cc: Mark Rutland Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-2-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/ia64/kernel/efi.c | 2 -- arch/x86/platform/efi/efi.c | 2 -- drivers/firmware/efi/arm-runtime.c | 1 - include/linux/efi.h | 1 - 4 files changed, 6 deletions(-) diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 300dac3702f1..bf0865cd438a 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -531,8 +531,6 @@ efi_init (void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - set_bit(EFI_SYSTEM_TABLES, &efi.flags); - palo_phys = EFI_INVALID_TABLE_ADDR; if (efi_config_init(arch_tables) != 0) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 994a7df84a7b..df393eab0e50 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -352,8 +352,6 @@ static int __init efi_systab_init(void *phys) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff); - set_bit(EFI_SYSTEM_TABLES, &efi.flags); - return 0; } diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 6ae21e41a429..16c7d2a71156 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -105,7 +105,6 @@ static int __init arm_enable_runtime_services(void) pr_err("Failed to remap EFI System Table\n"); return -ENOMEM; } - set_bit(EFI_SYSTEM_TABLES, &efi.flags); if (!efi_virtmap_init()) { pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); diff --git a/include/linux/efi.h b/include/linux/efi.h index 1626474567ac..1545098b0565 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1000,7 +1000,6 @@ extern int __init efi_setup_pcdp_console(char *); * possible, remove EFI-related code altogether. */ #define EFI_BOOT 0 /* Were we booted from EFI? */ -#define EFI_SYSTEM_TABLES 1 /* Can we use EFI system tables? */ #define EFI_CONFIG_TABLES 2 /* Can we use EFI config tables? */ #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ -- GitLab From 14c43be60166981f0b1f034ad9c59252c6f99e0d Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:34 +0100 Subject: [PATCH 4942/9938] efi/arm*: Drop writable mapping of the UEFI System table Commit: 2eec5dedf770 ("efi/arm-init: Use read-only early mappings") updated the early ARM UEFI init code to create the temporary, early mapping of the UEFI System table using read-only attributes, as a hardening measure against inadvertent modification. However, this still leaves the permanent, writable mapping of the UEFI System table, which is only ever referenced during invocations of UEFI Runtime Services, at which time the UEFI virtual mapping is available, which also covers the system table. (This is guaranteed by the fact that SetVirtualAddressMap(), which is a runtime service itself, converts various entries in the table to their virtual equivalents, which implies that the table must be covered by a RuntimeServicesData region that has the EFI_MEMORY_RUNTIME attribute.) So instead of creating this permanent mapping, record the virtual address of the system table inside the UEFI virtual mapping, and dereference that when accessing the table. This protects the contents of the system table from inadvertent (or deliberate) modification when no UEFI Runtime Services calls are in progress. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Leif Lindholm Cc: Mark Rutland Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-3-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/arm-init.c | 2 ++ drivers/firmware/efi/arm-runtime.c | 27 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 8714f8c271ba..008ed1993b72 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -85,6 +85,8 @@ static int __init uefi_init(void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff); + efi.runtime_version = efi.systab->hdr.revision; + /* Show what we know for posterity */ c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor), sizeof(vendor) * sizeof(efi_char16_t)); diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 16c7d2a71156..771750df6b7d 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -42,10 +42,12 @@ static struct mm_struct efi_mm = { static bool __init efi_virtmap_init(void) { efi_memory_desc_t *md; + bool systab_found; efi_mm.pgd = pgd_alloc(&efi_mm); init_new_context(NULL, &efi_mm); + systab_found = false; for_each_efi_memory_desc(&memmap, md) { phys_addr_t phys = md->phys_addr; int ret; @@ -64,8 +66,20 @@ static bool __init efi_virtmap_init(void) &phys, ret); return false; } + /* + * If this entry covers the address of the UEFI system table, + * calculate and record its virtual address. + */ + if (efi_system_table >= phys && + efi_system_table < phys + (md->num_pages * EFI_PAGE_SIZE)) { + efi.systab = (void *)(unsigned long)(efi_system_table - + phys + md->virt_addr); + systab_found = true; + } } - return true; + if (!systab_found) + pr_err("No virtual mapping found for the UEFI System Table\n"); + return systab_found; } /* @@ -99,15 +113,8 @@ static int __init arm_enable_runtime_services(void) memmap.map_end = memmap.map + mapsize; efi.memmap = &memmap; - efi.systab = (__force void *)ioremap_cache(efi_system_table, - sizeof(efi_system_table_t)); - if (!efi.systab) { - pr_err("Failed to remap EFI System Table\n"); - return -ENOMEM; - } - if (!efi_virtmap_init()) { - pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); + pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n"); return -ENOMEM; } @@ -115,8 +122,6 @@ static int __init arm_enable_runtime_services(void) efi_native_runtime_setup(); set_bit(EFI_RUNTIME_SERVICES, &efi.flags); - efi.runtime_version = efi.systab->hdr.revision; - return 0; } early_initcall(arm_enable_runtime_services); -- GitLab From 7fc8442f2a8a77f40565b42c41e4f2d48b179a56 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Mon, 25 Apr 2016 21:06:35 +0100 Subject: [PATCH 4943/9938] x86/mm/pat: Document the (currently) EFI-only code path It's not at all obvious that populate_pgd() and friends are only executed when mapping EFI virtual memory regions or that no other pageattr callers pass a ->pgd value. Reported-by: Andy Lutomirski Signed-off-by: Matt Fleming Cc: Ard Biesheuvel Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-4-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/mm/pageattr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 01be9ec3bf79..a1f0e1d0ddc2 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -1125,8 +1125,14 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr) static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, int primary) { - if (cpa->pgd) + if (cpa->pgd) { + /* + * Right now, we only execute this code path when mapping + * the EFI virtual memory map regions, no other users + * provide a ->pgd value. This may change in the future. + */ return populate_pgd(cpa, vaddr); + } /* * Ignore all non primary paths. -- GitLab From 73a6492589c87cd56707c8ac19eec78236c2d576 Mon Sep 17 00:00:00 2001 From: Linn Crosetto Date: Mon, 25 Apr 2016 21:06:36 +0100 Subject: [PATCH 4944/9938] efi/arm64: Report unexpected errors when determining Secure Boot status Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters. If an unexpected error is returned from GetVariable() when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned. Signed-off-by: Linn Crosetto Signed-off-by: Matt Fleming Reviewed-by: Ard Biesheuvel Acked-by: Mark Rutland Cc: Borislav Petkov Cc: Peter Zijlstra Cc: Roy Franz Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-5-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/arm-stub.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 414deb85c2e5..07f967c4c567 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,7 +20,7 @@ bool __nokaslr; -static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; static efi_char16_t const var_name[] = { @@ -39,8 +39,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) return val; case EFI_NOT_FOUND: return 0; + case EFI_DEVICE_ERROR: + return -EIO; + case EFI_SECURITY_VIOLATION: + return -EACCES; default: - return 1; + return -EINVAL; } } @@ -185,6 +189,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + int secure_boot = 0; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -250,12 +255,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (status != EFI_SUCCESS) pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); + secure_boot = efi_get_secureboot(sys_table); + if (secure_boot > 0) + pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + + if (secure_boot < 0) { + pr_efi_err(sys_table, + "could not determine UEFI Secure Boot status.\n"); + } + /* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ - if (efi_secureboot_enabled(sys_table)) { - pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) { + pr_efi(sys_table, "Ignoring DTB from command line.\n"); } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=", -- GitLab From 30d7bf034c034995f34dae265d96247f7f12044e Mon Sep 17 00:00:00 2001 From: Linn Crosetto Date: Mon, 25 Apr 2016 21:06:37 +0100 Subject: [PATCH 4945/9938] efi/arm64: Check SetupMode when determining Secure Boot status According to the UEFI specification (version 2.5 Errata A, page 87): The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1. Check the value of the SetupMode variable when determining the state of Secure Boot. Plus also do minor cleanup, change sizeof() use to match kernel style guidelines. Signed-off-by: Linn Crosetto Signed-off-by: Matt Fleming Reviewed-by: Ard Biesheuvel Acked-by: Mark Rutland Cc: Borislav Petkov Cc: Peter Zijlstra Cc: Roy Franz Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-6-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/arm-stub.c | 32 +++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 07f967c4c567..128632508fc6 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -22,21 +22,39 @@ bool __nokaslr; static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)&var_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)&var_guid, NULL, &size, &val); + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)&var_guid, + NULL, &size, &val); + + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 1) + return 0; + + return 1; + +out_efi_err: switch (status) { - case EFI_SUCCESS: - return val; case EFI_NOT_FOUND: return 0; case EFI_DEVICE_ERROR: -- GitLab From 78ce248faa3c46e24e9bd42db3ab3650659f16dd Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Mon, 25 Apr 2016 21:06:38 +0100 Subject: [PATCH 4946/9938] efi: Iterate over efi.memmap in for_each_efi_memory_desc() Most of the users of for_each_efi_memory_desc() are equally happy iterating over the EFI memory map in efi.memmap instead of 'memmap', since the former is usually a pointer to the latter. For those users that want to specify an EFI memory map other than efi.memmap, that can be done using for_each_efi_memory_desc_in_map(). One such example is in the libstub code where the firmware is queried directly for the memory map, it gets iterated over, and then freed. This change goes part of the way toward deleting the global 'memmap' variable, which is not universally available on all architectures (notably IA64) and is rather poorly named. Signed-off-by: Matt Fleming Reviewed-by: Ard Biesheuvel Cc: Borislav Petkov Cc: Leif Lindholm Cc: Mark Salter Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-7-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/efi.c | 43 ++++++------------- arch/x86/platform/efi/efi_64.c | 10 ++--- arch/x86/platform/efi/quirks.c | 10 ++--- drivers/firmware/efi/arm-init.c | 4 +- drivers/firmware/efi/arm-runtime.c | 2 +- drivers/firmware/efi/efi.c | 6 +-- drivers/firmware/efi/fake_mem.c | 3 +- .../firmware/efi/libstub/efi-stub-helper.c | 6 ++- include/linux/efi.h | 11 ++++- 9 files changed, 39 insertions(+), 56 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index df393eab0e50..6f499819a27f 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -119,11 +119,10 @@ void efi_get_time(struct timespec *now) void __init efi_find_mirror(void) { - void *p; + efi_memory_desc_t *md; u64 mirror_size = 0, total_size = 0; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; + for_each_efi_memory_desc(md) { unsigned long long start = md->phys_addr; unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; @@ -146,10 +145,9 @@ void __init efi_find_mirror(void) static void __init do_add_efi_memmap(void) { - void *p; + efi_memory_desc_t *md; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; + for_each_efi_memory_desc(md) { unsigned long long start = md->phys_addr; unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; int e820_type; @@ -226,17 +224,13 @@ void __init efi_print_memmap(void) { #ifdef EFI_DEBUG efi_memory_desc_t *md; - void *p; - int i; + int i = 0; - for (p = memmap.map, i = 0; - p < memmap.map_end; - p += memmap.desc_size, i++) { + for_each_efi_memory_desc(md) { char buf[64]; - md = p; pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n", - i, efi_md_typeattr_format(buf, sizeof(buf), md), + i++, efi_md_typeattr_format(buf, sizeof(buf), md), md->phys_addr, md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1, (md->num_pages >> (20 - EFI_PAGE_SHIFT))); @@ -550,12 +544,9 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable) void __init runtime_code_page_mkexec(void) { efi_memory_desc_t *md; - void *p; /* Make EFI runtime service code area executable */ - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; - + for_each_efi_memory_desc(md) { if (md->type != EFI_RUNTIME_SERVICES_CODE) continue; @@ -602,12 +593,10 @@ void __init old_map_region(efi_memory_desc_t *md) /* Merge contiguous regions of the same type and attribute */ static void __init efi_merge_regions(void) { - void *p; efi_memory_desc_t *md, *prev_md = NULL; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + for_each_efi_memory_desc(md) { u64 prev_size; - md = p; if (!prev_md) { prev_md = md; @@ -650,15 +639,13 @@ static void __init save_runtime_map(void) { #ifdef CONFIG_KEXEC_CORE efi_memory_desc_t *md; - void *tmp, *p, *q = NULL; + void *tmp, *q = NULL; int count = 0; if (efi_enabled(EFI_OLD_MEMMAP)) return; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; - + for_each_efi_memory_desc(md) { if (!(md->attribute & EFI_MEMORY_RUNTIME) || (md->type == EFI_BOOT_SERVICES_CODE) || (md->type == EFI_BOOT_SERVICES_DATA)) @@ -814,7 +801,6 @@ static void __init kexec_enter_virtual_mode(void) #ifdef CONFIG_KEXEC_CORE efi_memory_desc_t *md; unsigned int num_pages; - void *p; efi.systab = NULL; @@ -838,8 +824,7 @@ static void __init kexec_enter_virtual_mode(void) * Map efi regions which were passed via setup_data. The virt_addr is a * fixed addr which was used in first kernel of a kexec boot. */ - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; + for_each_efi_memory_desc(md) { efi_map_region_fixed(md); /* FIXME: add error handling */ get_systab_virt_addr(md); } @@ -1009,13 +994,11 @@ void __init efi_enter_virtual_mode(void) u32 efi_mem_type(unsigned long phys_addr) { efi_memory_desc_t *md; - void *p; if (!efi_enabled(EFI_MEMMAP)) return 0; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; + for_each_efi_memory_desc(md) { if ((md->phys_addr <= phys_addr) && (phys_addr < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)))) diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 49e4dd4a1f58..6e7242be1c87 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -55,14 +55,12 @@ struct efi_scratch efi_scratch; static void __init early_code_mapping_set_exec(int executable) { efi_memory_desc_t *md; - void *p; if (!(__supported_pte_mask & _PAGE_NX)) return; /* Make EFI service code area executable */ - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; + for_each_efi_memory_desc(md) { if (md->type == EFI_RUNTIME_SERVICES_CODE || md->type == EFI_BOOT_SERVICES_CODE) efi_set_executable(md, executable); @@ -253,7 +251,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) * Map all of RAM so that we can access arguments in the 1:1 * mapping when making EFI runtime calls. */ - for_each_efi_memory_desc(&memmap, md) { + for_each_efi_memory_desc(md) { if (md->type != EFI_CONVENTIONAL_MEMORY && md->type != EFI_LOADER_DATA && md->type != EFI_LOADER_CODE) @@ -398,7 +396,6 @@ void __init efi_runtime_update_mappings(void) unsigned long pfn; pgd_t *pgd = efi_pgd; efi_memory_desc_t *md; - void *p; if (efi_enabled(EFI_OLD_MEMMAP)) { if (__supported_pte_mask & _PAGE_NX) @@ -409,9 +406,8 @@ void __init efi_runtime_update_mappings(void) if (!efi_enabled(EFI_NX_PE_DATA)) return; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + for_each_efi_memory_desc(md) { unsigned long pf = 0; - md = p; if (!(md->attribute & EFI_MEMORY_RUNTIME)) continue; diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index ab50ada1d56e..097cb09d917b 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -195,10 +195,9 @@ static bool can_free_region(u64 start, u64 size) */ void __init efi_reserve_boot_services(void) { - void *p; + efi_memory_desc_t *md; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; + for_each_efi_memory_desc(md) { u64 start = md->phys_addr; u64 size = md->num_pages << EFI_PAGE_SHIFT; bool already_reserved; @@ -250,10 +249,9 @@ void __init efi_reserve_boot_services(void) void __init efi_free_boot_services(void) { - void *p; + efi_memory_desc_t *md; - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; + for_each_efi_memory_desc(md) { unsigned long long start = md->phys_addr; unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 008ed1993b72..d5f6b0ca521e 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -40,7 +40,7 @@ static phys_addr_t efi_to_phys(unsigned long addr) { efi_memory_desc_t *md; - for_each_efi_memory_desc(&memmap, md) { + for_each_efi_memory_desc_in_map(&memmap, md) { if (!(md->attribute & EFI_MEMORY_RUNTIME)) continue; if (md->virt_addr == 0) @@ -145,7 +145,7 @@ static __init void reserve_regions(void) if (efi_enabled(EFI_DBG)) pr_info("Processing EFI memory map:\n"); - for_each_efi_memory_desc(&memmap, md) { + for_each_efi_memory_desc_in_map(&memmap, md) { paddr = md->phys_addr; npages = md->num_pages; diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 771750df6b7d..1cfbfaf57a2d 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -48,7 +48,7 @@ static bool __init efi_virtmap_init(void) init_new_context(NULL, &efi_mm); systab_found = false; - for_each_efi_memory_desc(&memmap, md) { + for_each_efi_memory_desc(md) { phys_addr_t phys = md->phys_addr; int ret; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 3a69ed5ecfcb..4b533ce73374 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -620,16 +620,12 @@ char * __init efi_md_typeattr_format(char *buf, size_t size, */ u64 __weak efi_mem_attributes(unsigned long phys_addr) { - struct efi_memory_map *map; efi_memory_desc_t *md; - void *p; if (!efi_enabled(EFI_MEMMAP)) return 0; - map = efi.memmap; - for (p = map->map; p < map->map_end; p += map->desc_size) { - md = p; + for_each_efi_memory_desc(md) { if ((md->phys_addr <= phys_addr) && (phys_addr < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)))) diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c index ed3a854950cc..f55b75b2e1f4 100644 --- a/drivers/firmware/efi/fake_mem.c +++ b/drivers/firmware/efi/fake_mem.c @@ -68,8 +68,7 @@ void __init efi_fake_memmap(void) return; /* count up the number of EFI memory descriptor */ - for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) { - md = old; + for_each_efi_memory_desc(md) { start = md->phys_addr; end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 29ed2f9b218c..3bd127f95315 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -125,10 +125,12 @@ unsigned long get_dram_base(efi_system_table_t *sys_table_arg) map.map_end = map.map + map_size; - for_each_efi_memory_desc(&map, md) - if (md->attribute & EFI_MEMORY_WB) + for_each_efi_memory_desc_in_map(&map, md) { + if (md->attribute & EFI_MEMORY_WB) { if (membase > md->phys_addr) membase = md->phys_addr; + } + } efi_call_early(free_pool, map.map); diff --git a/include/linux/efi.h b/include/linux/efi.h index 1545098b0565..17ef4471e603 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -958,11 +958,20 @@ static inline void efi_fake_memmap(void) { } #endif /* Iterate through an efi_memory_map */ -#define for_each_efi_memory_desc(m, md) \ +#define for_each_efi_memory_desc_in_map(m, md) \ for ((md) = (m)->map; \ (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \ (md) = (void *)(md) + (m)->desc_size) +/** + * for_each_efi_memory_desc - iterate over descriptors in efi.memmap + * @md: the efi_memory_desc_t * iterator + * + * Once the loop finishes @md must not be accessed. + */ +#define for_each_efi_memory_desc(md) \ + for_each_efi_memory_desc_in_map(efi.memmap, md) + /* * Format an EFI memory descriptor's type and attributes to a user-provided * character buffer, as per snprintf(), and return the buffer. -- GitLab From 884f4f66ffd6ffe632f3a8be4e6d10a858afdc37 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Mon, 25 Apr 2016 21:06:39 +0100 Subject: [PATCH 4947/9938] efi: Remove global 'memmap' EFI memory map Abolish the poorly named EFI memory map, 'memmap'. It is shadowed by a bunch of local definitions in various files and having two ways to access the EFI memory map ('efi.memmap' vs. 'memmap') is rather confusing. Furthermore, IA64 doesn't even provide this global object, which has caused issues when trying to write generic EFI memmap code. Replace all occurrences with efi.memmap, and convert the remaining iterator code to use for_each_efi_mem_desc(). Signed-off-by: Matt Fleming Reviewed-by: Ard Biesheuvel Cc: Borislav Petkov Cc: Luck, Tony Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-8-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/efi.c | 84 +++++++++++++++++------------- drivers/firmware/efi/arm-init.c | 20 ++++--- drivers/firmware/efi/arm-runtime.c | 12 ++--- drivers/firmware/efi/efi.c | 2 +- drivers/firmware/efi/fake_mem.c | 40 +++++++------- include/linux/efi.h | 5 +- 6 files changed, 85 insertions(+), 78 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 6f499819a27f..88d2fb2cb3ef 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -56,8 +56,6 @@ #define EFI_DEBUG -struct efi_memory_map memmap; - static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; @@ -207,15 +205,13 @@ int __init efi_memblock_x86_reserve_range(void) #else pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32)); #endif - memmap.phys_map = pmap; - memmap.nr_map = e->efi_memmap_size / + efi.memmap.phys_map = pmap; + efi.memmap.nr_map = e->efi_memmap_size / e->efi_memdesc_size; - memmap.desc_size = e->efi_memdesc_size; - memmap.desc_version = e->efi_memdesc_version; - - memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); + efi.memmap.desc_size = e->efi_memdesc_size; + efi.memmap.desc_version = e->efi_memdesc_version; - efi.memmap = &memmap; + memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size); return 0; } @@ -240,10 +236,14 @@ void __init efi_print_memmap(void) void __init efi_unmap_memmap(void) { + unsigned long size; + clear_bit(EFI_MEMMAP, &efi.flags); - if (memmap.map) { - early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; + + size = efi.memmap.nr_map * efi.memmap.desc_size; + if (efi.memmap.map) { + early_memunmap(efi.memmap.map, size); + efi.memmap.map = NULL; } } @@ -432,17 +432,22 @@ static int __init efi_runtime_init(void) static int __init efi_memmap_init(void) { + unsigned long addr, size; + if (efi_enabled(EFI_PARAVIRT)) return 0; /* Map the EFI memory map */ - memmap.map = early_memremap((unsigned long)memmap.phys_map, - memmap.nr_map * memmap.desc_size); - if (memmap.map == NULL) { + size = efi.memmap.nr_map * efi.memmap.desc_size; + addr = (unsigned long)efi.memmap.phys_map; + + efi.memmap.map = early_memremap(addr, size); + if (efi.memmap.map == NULL) { pr_err("Could not map the memory map!\n"); return -ENOMEM; } - memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); + + efi.memmap.map_end = efi.memmap.map + size; if (add_efi_memmap) do_add_efi_memmap(); @@ -638,6 +643,7 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md) static void __init save_runtime_map(void) { #ifdef CONFIG_KEXEC_CORE + unsigned long desc_size; efi_memory_desc_t *md; void *tmp, *q = NULL; int count = 0; @@ -645,21 +651,23 @@ static void __init save_runtime_map(void) if (efi_enabled(EFI_OLD_MEMMAP)) return; + desc_size = efi.memmap.desc_size; + for_each_efi_memory_desc(md) { if (!(md->attribute & EFI_MEMORY_RUNTIME) || (md->type == EFI_BOOT_SERVICES_CODE) || (md->type == EFI_BOOT_SERVICES_DATA)) continue; - tmp = krealloc(q, (count + 1) * memmap.desc_size, GFP_KERNEL); + tmp = krealloc(q, (count + 1) * desc_size, GFP_KERNEL); if (!tmp) goto out; q = tmp; - memcpy(q + count * memmap.desc_size, md, memmap.desc_size); + memcpy(q + count * desc_size, md, desc_size); count++; } - efi_runtime_map_setup(q, count, memmap.desc_size); + efi_runtime_map_setup(q, count, desc_size); return; out: @@ -699,10 +707,10 @@ static inline void *efi_map_next_entry_reverse(void *entry) { /* Initial call */ if (!entry) - return memmap.map_end - memmap.desc_size; + return efi.memmap.map_end - efi.memmap.desc_size; - entry -= memmap.desc_size; - if (entry < memmap.map) + entry -= efi.memmap.desc_size; + if (entry < efi.memmap.map) return NULL; return entry; @@ -744,10 +752,10 @@ static void *efi_map_next_entry(void *entry) /* Initial call */ if (!entry) - return memmap.map; + return efi.memmap.map; - entry += memmap.desc_size; - if (entry >= memmap.map_end) + entry += efi.memmap.desc_size; + if (entry >= efi.memmap.map_end) return NULL; return entry; @@ -761,8 +769,11 @@ static void * __init efi_map_regions(int *count, int *pg_shift) { void *p, *new_memmap = NULL; unsigned long left = 0; + unsigned long desc_size; efi_memory_desc_t *md; + desc_size = efi.memmap.desc_size; + p = NULL; while ((p = efi_map_next_entry(p))) { md = p; @@ -777,7 +788,7 @@ static void * __init efi_map_regions(int *count, int *pg_shift) efi_map_region(md); get_systab_virt_addr(md); - if (left < memmap.desc_size) { + if (left < desc_size) { new_memmap = realloc_pages(new_memmap, *pg_shift); if (!new_memmap) return NULL; @@ -786,10 +797,9 @@ static void * __init efi_map_regions(int *count, int *pg_shift) (*pg_shift)++; } - memcpy(new_memmap + (*count * memmap.desc_size), md, - memmap.desc_size); + memcpy(new_memmap + (*count * desc_size), md, desc_size); - left -= memmap.desc_size; + left -= desc_size; (*count)++; } @@ -833,10 +843,10 @@ static void __init kexec_enter_virtual_mode(void) BUG_ON(!efi.systab); - num_pages = ALIGN(memmap.nr_map * memmap.desc_size, PAGE_SIZE); + num_pages = ALIGN(efi.memmap.nr_map * efi.memmap.desc_size, PAGE_SIZE); num_pages >>= PAGE_SHIFT; - if (efi_setup_page_tables(memmap.phys_map, num_pages)) { + if (efi_setup_page_tables(efi.memmap.phys_map, num_pages)) { clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); return; } @@ -920,16 +930,16 @@ static void __init __efi_enter_virtual_mode(void) if (efi_is_native()) { status = phys_efi_set_virtual_address_map( - memmap.desc_size * count, - memmap.desc_size, - memmap.desc_version, + efi.memmap.desc_size * count, + efi.memmap.desc_size, + efi.memmap.desc_version, (efi_memory_desc_t *)__pa(new_memmap)); } else { status = efi_thunk_set_virtual_address_map( efi_phys.set_virtual_address_map, - memmap.desc_size * count, - memmap.desc_size, - memmap.desc_version, + efi.memmap.desc_size * count, + efi.memmap.desc_size, + efi.memmap.desc_version, (efi_memory_desc_t *)__pa(new_memmap)); } diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index d5f6b0ca521e..90a9b473e45c 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -20,8 +20,6 @@ #include -struct efi_memory_map memmap; - u64 efi_system_table; static int __init is_normal_ram(efi_memory_desc_t *md) @@ -40,7 +38,7 @@ static phys_addr_t efi_to_phys(unsigned long addr) { efi_memory_desc_t *md; - for_each_efi_memory_desc_in_map(&memmap, md) { + for_each_efi_memory_desc(md) { if (!(md->attribute & EFI_MEMORY_RUNTIME)) continue; if (md->virt_addr == 0) @@ -145,7 +143,7 @@ static __init void reserve_regions(void) if (efi_enabled(EFI_DBG)) pr_info("Processing EFI memory map:\n"); - for_each_efi_memory_desc_in_map(&memmap, md) { + for_each_efi_memory_desc(md) { paddr = md->phys_addr; npages = md->num_pages; @@ -186,9 +184,9 @@ void __init efi_init(void) efi_system_table = params.system_table; - memmap.phys_map = params.mmap; - memmap.map = early_memremap_ro(params.mmap, params.mmap_size); - if (memmap.map == NULL) { + efi.memmap.phys_map = params.mmap; + efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size); + if (efi.memmap.map == NULL) { /* * If we are booting via UEFI, the UEFI memory map is the only * description of memory we have, so there is little point in @@ -196,15 +194,15 @@ void __init efi_init(void) */ panic("Unable to map EFI memory map.\n"); } - memmap.map_end = memmap.map + params.mmap_size; - memmap.desc_size = params.desc_size; - memmap.desc_version = params.desc_ver; + efi.memmap.map_end = efi.memmap.map + params.mmap_size; + efi.memmap.desc_size = params.desc_size; + efi.memmap.desc_version = params.desc_ver; if (uefi_init() < 0) return; reserve_regions(); - early_memunmap(memmap.map, params.mmap_size); + early_memunmap(efi.memmap.map, params.mmap_size); if (IS_ENABLED(CONFIG_ARM)) { /* diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 1cfbfaf57a2d..55a9ea041068 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -103,15 +103,15 @@ static int __init arm_enable_runtime_services(void) pr_info("Remapping and enabling EFI services.\n"); - mapsize = memmap.map_end - memmap.map; - memmap.map = (__force void *)ioremap_cache(memmap.phys_map, - mapsize); - if (!memmap.map) { + mapsize = efi.memmap.map_end - efi.memmap.map; + + efi.memmap.map = (__force void *)ioremap_cache(efi.memmap.phys_map, + mapsize); + if (!efi.memmap.map) { pr_err("Failed to remap EFI memory map\n"); return -ENOMEM; } - memmap.map_end = memmap.map + mapsize; - efi.memmap = &memmap; + efi.memmap.map_end = efi.memmap.map + mapsize; if (!efi_virtmap_init()) { pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n"); diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 4b533ce73374..f7d36c6cc1ad 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -256,7 +256,7 @@ subsys_initcall(efisubsys_init); */ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) { - struct efi_memory_map *map = efi.memmap; + struct efi_memory_map *map = &efi.memmap; phys_addr_t p, e; if (!efi_enabled(EFI_MEMMAP)) { diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c index f55b75b2e1f4..48430aba13c1 100644 --- a/drivers/firmware/efi/fake_mem.c +++ b/drivers/firmware/efi/fake_mem.c @@ -57,7 +57,7 @@ static int __init cmp_fake_mem(const void *x1, const void *x2) void __init efi_fake_memmap(void) { u64 start, end, m_start, m_end, m_attr; - int new_nr_map = memmap.nr_map; + int new_nr_map = efi.memmap.nr_map; efi_memory_desc_t *md; phys_addr_t new_memmap_phy; void *new_memmap; @@ -94,25 +94,25 @@ void __init efi_fake_memmap(void) } /* allocate memory for new EFI memmap */ - new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map, + new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map, PAGE_SIZE); if (!new_memmap_phy) return; /* create new EFI memmap */ new_memmap = early_memremap(new_memmap_phy, - memmap.desc_size * new_nr_map); + efi.memmap.desc_size * new_nr_map); if (!new_memmap) { - memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map); + memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map); return; } - for (old = memmap.map, new = new_memmap; - old < memmap.map_end; - old += memmap.desc_size, new += memmap.desc_size) { + for (old = efi.memmap.map, new = new_memmap; + old < efi.memmap.map_end; + old += efi.memmap.desc_size, new += efi.memmap.desc_size) { /* copy original EFI memory descriptor */ - memcpy(new, old, memmap.desc_size); + memcpy(new, old, efi.memmap.desc_size); md = new; start = md->phys_addr; end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; @@ -133,8 +133,8 @@ void __init efi_fake_memmap(void) md->num_pages = (m_end - md->phys_addr + 1) >> EFI_PAGE_SHIFT; /* latter part */ - new += memmap.desc_size; - memcpy(new, old, memmap.desc_size); + new += efi.memmap.desc_size; + memcpy(new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_end + 1; md->num_pages = (end - md->phys_addr + 1) >> @@ -146,16 +146,16 @@ void __init efi_fake_memmap(void) md->num_pages = (m_start - md->phys_addr) >> EFI_PAGE_SHIFT; /* middle part */ - new += memmap.desc_size; - memcpy(new, old, memmap.desc_size); + new += efi.memmap.desc_size; + memcpy(new, old, efi.memmap.desc_size); md = new; md->attribute |= m_attr; md->phys_addr = m_start; md->num_pages = (m_end - m_start + 1) >> EFI_PAGE_SHIFT; /* last part */ - new += memmap.desc_size; - memcpy(new, old, memmap.desc_size); + new += efi.memmap.desc_size; + memcpy(new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_end + 1; md->num_pages = (end - m_end) >> @@ -168,8 +168,8 @@ void __init efi_fake_memmap(void) md->num_pages = (m_start - md->phys_addr) >> EFI_PAGE_SHIFT; /* latter part */ - new += memmap.desc_size; - memcpy(new, old, memmap.desc_size); + new += efi.memmap.desc_size; + memcpy(new, old, efi.memmap.desc_size); md = new; md->phys_addr = m_start; md->num_pages = (end - md->phys_addr + 1) >> @@ -181,10 +181,10 @@ void __init efi_fake_memmap(void) /* swap into new EFI memmap */ efi_unmap_memmap(); - memmap.map = new_memmap; - memmap.phys_map = new_memmap_phy; - memmap.nr_map = new_nr_map; - memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size; + efi.memmap.map = new_memmap; + efi.memmap.phys_map = new_memmap_phy; + efi.memmap.nr_map = new_nr_map; + efi.memmap.map_end = efi.memmap.map + efi.memmap.nr_map * efi.memmap.desc_size; set_bit(EFI_MEMMAP, &efi.flags); /* print new EFI memmap */ diff --git a/include/linux/efi.h b/include/linux/efi.h index 17ef4471e603..c2c0da49876e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -883,7 +883,7 @@ extern struct efi { efi_get_next_high_mono_count_t *get_next_high_mono_count; efi_reset_system_t *reset_system; efi_set_virtual_address_map_t *set_virtual_address_map; - struct efi_memory_map *memmap; + struct efi_memory_map memmap; unsigned long flags; } efi; @@ -945,7 +945,6 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource, extern void efi_get_time(struct timespec *now); extern void efi_reserve_boot_services(void); extern int efi_get_fdt_params(struct efi_fdt_params *params); -extern struct efi_memory_map memmap; extern struct kobject *efi_kobj; extern int efi_reboot_quirk_mode; @@ -970,7 +969,7 @@ static inline void efi_fake_memmap(void) { } * Once the loop finishes @md must not be accessed. */ #define for_each_efi_memory_desc(md) \ - for_each_efi_memory_desc_in_map(efi.memmap, md) + for_each_efi_memory_desc_in_map(&efi.memmap, md) /* * Format an EFI memory descriptor's type and attributes to a user-provided -- GitLab From 0d054ad96e97dcd8966e9333eabcc7a466672f70 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:40 +0100 Subject: [PATCH 4948/9938] efi: Check EFI_MEMORY_DESCRIPTOR version explicitly Our efi_memory_desc_t type is based on EFI_MEMORY_DESCRIPTOR version 1 in the UEFI spec. No version updates are expected, but since we are about to introduce support for new firmware tables that use the same descriptor type, it makes sense to at least warn if we encounter other versions. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-9-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/efi.c | 4 ++++ drivers/firmware/efi/arm-init.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 88d2fb2cb3ef..dde46cd78b8f 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -211,6 +211,10 @@ int __init efi_memblock_x86_reserve_range(void) efi.memmap.desc_size = e->efi_memdesc_size; efi.memmap.desc_version = e->efi_memdesc_version; + WARN(efi.memmap.desc_version != 1, + "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", + efi.memmap.desc_version); + memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size); return 0; diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 90a9b473e45c..a84dddb54c14 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -198,6 +198,10 @@ void __init efi_init(void) efi.memmap.desc_size = params.desc_size; efi.memmap.desc_version = params.desc_ver; + WARN(efi.memmap.desc_version != 1, + "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", + efi.memmap.desc_version); + if (uefi_init() < 0) return; -- GitLab From 24d45d1dc275b818093fe1d0055a230ce5e8c4c7 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:41 +0100 Subject: [PATCH 4949/9938] efi/arm*: Use memremap() to create the persistent memmap mapping Instead of using ioremap_cache(), which is slightly inappropriate for mapping firmware tables, and is not even allowed on ARM for mapping regions that are covered by a struct page, use memremap(), which was invented for this purpose, and will also reuse the existing kernel direct mapping if the requested region is covered by it. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-10-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/arm-runtime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 55a9ea041068..19283deac375 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -105,8 +105,7 @@ static int __init arm_enable_runtime_services(void) mapsize = efi.memmap.map_end - efi.memmap.map; - efi.memmap.map = (__force void *)ioremap_cache(efi.memmap.phys_map, - mapsize); + efi.memmap.map = memremap(efi.memmap.phys_map, mapsize, MEMREMAP_WB); if (!efi.memmap.map) { pr_err("Failed to remap EFI memory map\n"); return -ENOMEM; -- GitLab From 9fc68b717c24a215a32c1b4e05b30433cafb2599 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:42 +0100 Subject: [PATCH 4950/9938] ARM/efi: Apply strict permissions for UEFI Runtime Services regions Recent UEFI versions expose permission attributes for runtime services memory regions, either in the UEFI memory map or in the separate memory attributes table. This allows the kernel to map these regions with stricter permissions, rather than the RWX permissions that are used by default. So wire this up in our mapping routine. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Catalin Marinas Cc: Leif Lindholm Cc: Mark Rutland Cc: Peter Jones Cc: Peter Zijlstra Cc: Russell King Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-11-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/arm/include/asm/efi.h | 1 + arch/arm/kernel/efi.c | 41 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index e0eea72deb87..b0c341d7ceee 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -22,6 +22,7 @@ void efi_init(void); int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); +int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); #define efi_call_virt(f, ...) \ ({ \ diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c index ff8a9d8acfac..9f43ba012d10 100644 --- a/arch/arm/kernel/efi.c +++ b/arch/arm/kernel/efi.c @@ -11,6 +11,41 @@ #include #include +static int __init set_permissions(pte_t *ptep, pgtable_t token, + unsigned long addr, void *data) +{ + efi_memory_desc_t *md = data; + pte_t pte = *ptep; + + if (md->attribute & EFI_MEMORY_RO) + pte = set_pte_bit(pte, __pgprot(L_PTE_RDONLY)); + if (md->attribute & EFI_MEMORY_XP) + pte = set_pte_bit(pte, __pgprot(L_PTE_XN)); + set_pte_ext(ptep, pte, PTE_EXT_NG); + return 0; +} + +int __init efi_set_mapping_permissions(struct mm_struct *mm, + efi_memory_desc_t *md) +{ + unsigned long base, size; + + base = md->virt_addr; + size = md->num_pages << EFI_PAGE_SHIFT; + + /* + * We can only use apply_to_page_range() if we can guarantee that the + * entire region was mapped using pages. This should be the case if the + * region does not cover any naturally aligned SECTION_SIZE sized + * blocks. + */ + if (round_down(base + size, SECTION_SIZE) < + round_up(base, SECTION_SIZE) + SECTION_SIZE) + return apply_to_page_range(mm, base, size, set_permissions, md); + + return 0; +} + int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) { struct map_desc desc = { @@ -34,5 +69,11 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) desc.type = MT_DEVICE; create_mapping_late(mm, &desc, true); + + /* + * If stricter permissions were specified, apply them now. + */ + if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) + return efi_set_mapping_permissions(mm, md); return 0; } -- GitLab From 1fd55a9a09b0293af95ab4299b108f030fef4464 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:43 +0100 Subject: [PATCH 4951/9938] arm64/efi: Apply strict permissions to UEFI Runtime Services regions Recent UEFI versions expose permission attributes for runtime services memory regions, either in the UEFI memory map or in the separate memory attributes table. This allows the kernel to map these regions with stricter permissions, rather than the RWX permissions that are used by default. So wire this up in our mapping routine. Note that in the absence of permission attributes, we still only map regions of type EFI_RUNTIME_SERVICE_CODE with the executable bit set. Also, we base the mapping attributes of EFI_MEMORY_MAPPED_IO on the type directly rather than on the absence of the EFI_MEMORY_WB attribute. This is more correct, but is also required for compatibility with the upcoming support for the Memory Attributes Table, which only carries permission attributes, not memory type attributes. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Catalin Marinas Cc: Leif Lindholm Cc: Mark Rutland Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-12-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/arm64/kernel/efi.c | 54 ++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index b6abc852f2a1..33a6da160a50 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -17,22 +17,48 @@ #include -int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) +/* + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be + * executable, everything else can be mapped with the XN bits + * set. Also take the new (optional) RO/XP bits into account. + */ +static __init pteval_t create_mapping_protection(efi_memory_desc_t *md) { - pteval_t prot_val; + u64 attr = md->attribute; + u32 type = md->type; - /* - * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be - * executable, everything else can be mapped with the XN bits - * set. - */ - if ((md->attribute & EFI_MEMORY_WB) == 0) - prot_val = PROT_DEVICE_nGnRE; - else if (md->type == EFI_RUNTIME_SERVICES_CODE || - !PAGE_ALIGNED(md->phys_addr)) - prot_val = pgprot_val(PAGE_KERNEL_EXEC); - else - prot_val = pgprot_val(PAGE_KERNEL); + if (type == EFI_MEMORY_MAPPED_IO) + return PROT_DEVICE_nGnRE; + + if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr), + "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?")) + /* + * If the region is not aligned to the page size of the OS, we + * can not use strict permissions, since that would also affect + * the mapping attributes of the adjacent regions. + */ + return pgprot_val(PAGE_KERNEL_EXEC); + + /* R-- */ + if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) == + (EFI_MEMORY_XP | EFI_MEMORY_RO)) + return pgprot_val(PAGE_KERNEL_RO); + + /* R-X */ + if (attr & EFI_MEMORY_RO) + return pgprot_val(PAGE_KERNEL_ROX); + + /* RW- */ + if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE) + return pgprot_val(PAGE_KERNEL); + + /* RWX */ + return pgprot_val(PAGE_KERNEL_EXEC); +} + +int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) +{ + pteval_t prot_val = create_mapping_protection(md); create_pgd_mapping(mm, md->phys_addr, md->virt_addr, md->num_pages << EFI_PAGE_SHIFT, -- GitLab From a604af075a3226adaff84b7026876f0c6dfe9f52 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:44 +0100 Subject: [PATCH 4952/9938] efi: Add support for the EFI_MEMORY_ATTRIBUTES_TABLE config table This declares the GUID and struct typedef for the new memory attributes table which contains the permissions that can be used to apply stricter permissions to UEFI Runtime Services memory regions. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Catalin Marinas Cc: Leif Lindholm Cc: Mark Rutland Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-13-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efi.c | 2 ++ include/linux/efi.h | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index f7d36c6cc1ad..583e647912a5 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -43,6 +43,7 @@ struct efi __read_mostly efi = { .config_table = EFI_INVALID_TABLE_ADDR, .esrt = EFI_INVALID_TABLE_ADDR, .properties_table = EFI_INVALID_TABLE_ADDR, + .mem_attr_table = EFI_INVALID_TABLE_ADDR, }; EXPORT_SYMBOL(efi); @@ -338,6 +339,7 @@ static __initdata efi_config_table_type_t common_tables[] = { {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, + {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, {NULL_GUID, NULL, NULL}, }; diff --git a/include/linux/efi.h b/include/linux/efi.h index c2c0da49876e..81af5feba1f7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -623,6 +623,10 @@ void efi_native_runtime_setup(void); EFI_GUID(0x3152bca5, 0xeade, 0x433d, \ 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) +#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID \ + EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, \ + 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) + typedef struct { efi_guid_t guid; u64 table; @@ -847,6 +851,14 @@ typedef struct { #define EFI_INVALID_TABLE_ADDR (~0UL) +typedef struct { + u32 version; + u32 num_entries; + u32 desc_size; + u32 reserved; + efi_memory_desc_t entry[0]; +} efi_memory_attributes_table_t; + /* * All runtime access to EFI goes through this structure: */ @@ -868,6 +880,7 @@ extern struct efi { unsigned long config_table; /* config tables */ unsigned long esrt; /* ESRT table */ unsigned long properties_table; /* properties table */ + unsigned long mem_attr_table; /* memory attributes table */ efi_get_time_t *get_time; efi_set_time_t *set_time; efi_get_wakeup_time_t *get_wakeup_time; -- GitLab From 10f0d2f57705350bbbe5f28e9292ae3905823c3c Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:45 +0100 Subject: [PATCH 4953/9938] efi: Implement generic support for the Memory Attributes table This implements shared support for discovering the presence of the Memory Attributes table, and for parsing and validating its contents. The table is validated against the construction rules in the UEFI spec. Since this is a new table, it makes sense to complain if we encounter a table that does not follow those rules. The parsing and validation routine takes a callback that can be specified per architecture, that gets passed each unique validated region, with the virtual address retrieved from the ordinary memory map. Signed-off-by: Ard Biesheuvel [ Trim pr_*() strings to 80 cols and use EFI consistently. ] Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Catalin Marinas Cc: Leif Lindholm Cc: Mark Rutland Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-14-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/Makefile | 2 +- drivers/firmware/efi/memattr.c | 182 +++++++++++++++++++++++++++++++++ include/linux/efi.h | 13 +++ 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/efi/memattr.c diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 62e654f255f4..d5be62399130 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -9,7 +9,7 @@ # KASAN_SANITIZE_runtime-wrappers.o := n -obj-$(CONFIG_EFI) += efi.o vars.o reboot.o +obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_ESRT) += esrt.o obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c new file mode 100644 index 000000000000..236004b9a50d --- /dev/null +++ b/drivers/firmware/efi/memattr.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2016 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "efi: memattr: " fmt + +#include +#include +#include +#include + +#include + +static int __initdata tbl_size; + +/* + * Reserve the memory associated with the Memory Attributes configuration + * table, if it exists. + */ +int __init efi_memattr_init(void) +{ + efi_memory_attributes_table_t *tbl; + + if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR) + return 0; + + tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl)); + if (!tbl) { + pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n", + efi.mem_attr_table); + return -ENOMEM; + } + + if (tbl->version > 1) { + pr_warn("Unexpected EFI Memory Attributes table version %d\n", + tbl->version); + goto unmap; + } + + tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size; + memblock_reserve(efi.mem_attr_table, tbl_size); + +unmap: + early_memunmap(tbl, sizeof(*tbl)); + return 0; +} + +/* + * Returns a copy @out of the UEFI memory descriptor @in if it is covered + * entirely by a UEFI memory map entry with matching attributes. The virtual + * address of @out is set according to the matching entry that was found. + */ +static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out) +{ + u64 in_paddr = in->phys_addr; + u64 in_size = in->num_pages << EFI_PAGE_SHIFT; + efi_memory_desc_t *md; + + *out = *in; + + if (in->type != EFI_RUNTIME_SERVICES_CODE && + in->type != EFI_RUNTIME_SERVICES_DATA) { + pr_warn("Entry type should be RuntimeServiceCode/Data\n"); + return false; + } + + if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) { + pr_warn("Entry attributes invalid: RO and XP bits both cleared\n"); + return false; + } + + if (PAGE_SIZE > EFI_PAGE_SIZE && + (!PAGE_ALIGNED(in->phys_addr) || + !PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) { + /* + * Since arm64 may execute with page sizes of up to 64 KB, the + * UEFI spec mandates that RuntimeServices memory regions must + * be 64 KB aligned. We need to validate this here since we will + * not be able to tighten permissions on such regions without + * affecting adjacent regions. + */ + pr_warn("Entry address region misaligned\n"); + return false; + } + + for_each_efi_memory_desc(md) { + u64 md_paddr = md->phys_addr; + u64 md_size = md->num_pages << EFI_PAGE_SHIFT; + + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (md->virt_addr == 0) { + /* no virtual mapping has been installed by the stub */ + break; + } + + if (md_paddr > in_paddr || (in_paddr - md_paddr) >= md_size) + continue; + + /* + * This entry covers the start of @in, check whether + * it covers the end as well. + */ + if (md_paddr + md_size < in_paddr + in_size) { + pr_warn("Entry covers multiple EFI memory map regions\n"); + return false; + } + + if (md->type != in->type) { + pr_warn("Entry type deviates from EFI memory map region type\n"); + return false; + } + + out->virt_addr = in_paddr + (md->virt_addr - md_paddr); + + return true; + } + + pr_warn("No matching entry found in the EFI memory map\n"); + return false; +} + +/* + * To be called after the EFI page tables have been populated. If a memory + * attributes table is available, its contents will be used to update the + * mappings with tightened permissions as described by the table. + * This requires the UEFI memory map to have already been populated with + * virtual addresses. + */ +int __init efi_memattr_apply_permissions(struct mm_struct *mm, + efi_memattr_perm_setter fn) +{ + efi_memory_attributes_table_t *tbl; + int i, ret; + + if (tbl_size <= sizeof(*tbl)) + return 0; + + /* + * We need the EFI memory map to be setup so we can use it to + * lookup the virtual addresses of all entries in the of EFI + * Memory Attributes table. If it isn't available, this + * function should not be called. + */ + if (WARN_ON(!efi_enabled(EFI_MEMMAP))) + return 0; + + tbl = memremap(efi.mem_attr_table, tbl_size, MEMREMAP_WB); + if (!tbl) { + pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n", + efi.mem_attr_table); + return -ENOMEM; + } + + if (efi_enabled(EFI_DBG)) + pr_info("Processing EFI Memory Attributes table:\n"); + + for (i = ret = 0; ret == 0 && i < tbl->num_entries; i++) { + efi_memory_desc_t md; + unsigned long size; + bool valid; + char buf[64]; + + valid = entry_is_valid((void *)tbl->entry + i * tbl->desc_size, + &md); + size = md.num_pages << EFI_PAGE_SHIFT; + if (efi_enabled(EFI_DBG) || !valid) + pr_info("%s 0x%012llx-0x%012llx %s\n", + valid ? "" : "!", md.phys_addr, + md.phys_addr + size - 1, + efi_md_typeattr_format(buf, sizeof(buf), &md)); + + if (valid) + ret = fn(mm, &md); + } + memunmap(tbl); + return ret; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index 81af5feba1f7..e29a31d0fc35 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -969,6 +969,19 @@ extern void __init efi_fake_memmap(void); static inline void efi_fake_memmap(void) { } #endif +/* + * efi_memattr_perm_setter - arch specific callback function passed into + * efi_memattr_apply_permissions() that updates the + * mapping permissions described by the second + * argument in the page tables referred to by the + * first argument. + */ +typedef int (*efi_memattr_perm_setter)(struct mm_struct *, efi_memory_desc_t *); + +extern int efi_memattr_init(void); +extern int efi_memattr_apply_permissions(struct mm_struct *mm, + efi_memattr_perm_setter fn); + /* Iterate through an efi_memory_map */ #define for_each_efi_memory_desc_in_map(m, md) \ for ((md) = (m)->map; \ -- GitLab From 789957ef72f976cb325e9057225fc4e9c4513060 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:46 +0100 Subject: [PATCH 4954/9938] efi/arm*: Take the Memory Attributes table into account Call into the generic memory attributes table support code at the appropriate times during the init sequence so that the UEFI Runtime Services region are mapped according to the strict permissions it specifies. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Catalin Marinas Cc: Leif Lindholm Cc: Mark Rutland Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-15-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/arm64/include/asm/efi.h | 2 ++ drivers/firmware/efi/arm-init.c | 1 + drivers/firmware/efi/arm-runtime.c | 10 ++++++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 8e88a696c9cb..4dafc89f373a 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -14,6 +14,8 @@ extern void efi_init(void); int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); +#define efi_set_mapping_permissions efi_create_mapping + #define efi_call_virt(f, ...) \ ({ \ efi_##f##_t *__f; \ diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index a84dddb54c14..909d974d35d9 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -206,6 +206,7 @@ void __init efi_init(void) return; reserve_regions(); + efi_memattr_init(); early_memunmap(efi.memmap.map, params.mmap_size); if (IS_ENABLED(CONFIG_ARM)) { diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 19283deac375..17ccf0a8787a 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -77,9 +77,15 @@ static bool __init efi_virtmap_init(void) systab_found = true; } } - if (!systab_found) + if (!systab_found) { pr_err("No virtual mapping found for the UEFI System Table\n"); - return systab_found; + return false; + } + + if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions)) + return false; + + return true; } /* -- GitLab From c3c1c47f15b37a8492e630d1e9ab8ad576ee10e5 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Mon, 25 Apr 2016 21:06:47 +0100 Subject: [PATCH 4955/9938] x86/efi: Remove the always true EFI_DEBUG symbol This symbol is always set which makes it useless. Additionally we have a kernel command-line switch, efi=debug, which actually controls the printing of the memory map. Reported-by: Robert Elliott Signed-off-by: Matt Fleming Acked-by: Borislav Petkov Cc: Ard Biesheuvel Cc: Borislav Petkov Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-16-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/efi.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index dde46cd78b8f..f93545e7dc54 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -54,8 +54,6 @@ #include #include -#define EFI_DEBUG - static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; @@ -222,7 +220,6 @@ int __init efi_memblock_x86_reserve_range(void) void __init efi_print_memmap(void) { -#ifdef EFI_DEBUG efi_memory_desc_t *md; int i = 0; @@ -235,7 +232,6 @@ void __init efi_print_memmap(void) md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1, (md->num_pages >> (20 - EFI_PAGE_SHIFT))); } -#endif /* EFI_DEBUG */ } void __init efi_unmap_memmap(void) -- GitLab From 2c23b73c2d0249c499c4784b6db08dcfc6b7b3b0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:48 +0100 Subject: [PATCH 4956/9938] x86/efi: Prepare GOP handling code for reuse as generic code In preparation of moving this code to drivers/firmware/efi and reusing it on ARM and arm64, apply any changes that will be required to make this code build for other architectures. This should make it easier to track down problems that this move may cause to its operation on x86. Note that the generic version uses slightly different ways of casting the protocol methods and some other variables to the correct types, since such method calls are not loosely typed on ARM and arm64 as they are on x86. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: David Herrmann Cc: Mark Rutland Cc: Peter Jones Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-17-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/eboot.c | 58 +++++++++++++++++++------------- arch/x86/boot/compressed/eboot.h | 4 +++ arch/x86/include/asm/efi.h | 5 +++ include/linux/efi.h | 5 +++ 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 583d539a4197..10516e22fdcb 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -622,19 +622,22 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, } static efi_status_t -__gop_query32(struct efi_graphics_output_protocol_32 *gop32, +__gop_query32(efi_system_table_t *sys_table_arg, + struct efi_graphics_output_protocol_32 *gop32, struct efi_graphics_output_mode_info **info, unsigned long *size, u64 *fb_base) { struct efi_graphics_output_protocol_mode_32 *mode; + efi_graphics_output_protocol_query_mode query_mode; efi_status_t status; unsigned long m; m = gop32->mode; mode = (struct efi_graphics_output_protocol_mode_32 *)m; + query_mode = (void *)(unsigned long)gop32->query_mode; - status = efi_early->call(gop32->query_mode, gop32, - mode->mode, size, info); + status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size, + info); if (status != EFI_SUCCESS) return status; @@ -643,8 +646,8 @@ __gop_query32(struct efi_graphics_output_protocol_32 *gop32, } static efi_status_t -setup_gop32(struct screen_info *si, efi_guid_t *proto, - unsigned long size, void **gop_handle) +setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, + efi_guid_t *proto, unsigned long size, void **gop_handle) { struct efi_graphics_output_protocol_32 *gop32, *first_gop; unsigned long nr_gops; @@ -654,7 +657,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto, u64 fb_base; struct efi_pixel_bitmask pixel_info; int pixel_format; - efi_status_t status; + efi_status_t status = EFI_NOT_FOUND; u32 *handles = (u32 *)(unsigned long)gop_handle; int i; @@ -667,7 +670,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto, efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; bool conout_found = false; void *dummy = NULL; - u32 h = handles[i]; + efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; u64 current_fb_base; status = efi_call_early(handle_protocol, h, @@ -680,7 +683,8 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto, if (status == EFI_SUCCESS) conout_found = true; - status = __gop_query32(gop32, &info, &size, ¤t_fb_base); + status = __gop_query32(sys_table_arg, gop32, &info, &size, + ¤t_fb_base); if (status == EFI_SUCCESS && (!first_gop || conout_found)) { /* * Systems that use the UEFI Console Splitter may @@ -735,19 +739,22 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto, } static efi_status_t -__gop_query64(struct efi_graphics_output_protocol_64 *gop64, +__gop_query64(efi_system_table_t *sys_table_arg, + struct efi_graphics_output_protocol_64 *gop64, struct efi_graphics_output_mode_info **info, unsigned long *size, u64 *fb_base) { struct efi_graphics_output_protocol_mode_64 *mode; + efi_graphics_output_protocol_query_mode query_mode; efi_status_t status; unsigned long m; m = gop64->mode; mode = (struct efi_graphics_output_protocol_mode_64 *)m; + query_mode = (void *)(unsigned long)gop64->query_mode; - status = efi_early->call(gop64->query_mode, gop64, - mode->mode, size, info); + status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size, + info); if (status != EFI_SUCCESS) return status; @@ -756,8 +763,8 @@ __gop_query64(struct efi_graphics_output_protocol_64 *gop64, } static efi_status_t -setup_gop64(struct screen_info *si, efi_guid_t *proto, - unsigned long size, void **gop_handle) +setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, + efi_guid_t *proto, unsigned long size, void **gop_handle) { struct efi_graphics_output_protocol_64 *gop64, *first_gop; unsigned long nr_gops; @@ -767,7 +774,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto, u64 fb_base; struct efi_pixel_bitmask pixel_info; int pixel_format; - efi_status_t status; + efi_status_t status = EFI_NOT_FOUND; u64 *handles = (u64 *)(unsigned long)gop_handle; int i; @@ -780,7 +787,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto, efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; bool conout_found = false; void *dummy = NULL; - u64 h = handles[i]; + efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; u64 current_fb_base; status = efi_call_early(handle_protocol, h, @@ -793,7 +800,8 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto, if (status == EFI_SUCCESS) conout_found = true; - status = __gop_query64(gop64, &info, &size, ¤t_fb_base); + status = __gop_query64(sys_table_arg, gop64, &info, &size, + ¤t_fb_base); if (status == EFI_SUCCESS && (!first_gop || conout_found)) { /* * Systems that use the UEFI Console Splitter may @@ -850,8 +858,9 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto, /* * See if we have Graphics Output Protocol */ -static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, - unsigned long size) +efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, + struct screen_info *si, efi_guid_t *proto, + unsigned long size) { efi_status_t status; void **gop_handle = NULL; @@ -867,10 +876,13 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, if (status != EFI_SUCCESS) goto free_handle; - if (efi_early->is64) - status = setup_gop64(si, proto, size, gop_handle); - else - status = setup_gop32(si, proto, size, gop_handle); + if (efi_is_64bit()) { + status = setup_gop64(sys_table_arg, si, proto, size, + gop_handle); + } else { + status = setup_gop32(sys_table_arg, si, proto, size, + gop_handle); + } free_handle: efi_call_early(free_pool, gop_handle); @@ -1038,7 +1050,7 @@ void setup_graphics(struct boot_params *boot_params) EFI_LOCATE_BY_PROTOCOL, &graphics_proto, NULL, &size, gop_handle); if (status == EFI_BUFFER_TOO_SMALL) - status = setup_gop(si, &graphics_proto, size); + status = efi_setup_gop(NULL, si, &graphics_proto, size); if (status != EFI_SUCCESS) { size = 0; diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index d487e727f1ec..4ee5318d7f28 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h @@ -85,6 +85,10 @@ struct efi_graphics_output_protocol { struct efi_graphics_output_protocol_mode *mode; }; +typedef efi_status_t (*efi_graphics_output_protocol_query_mode)( + struct efi_graphics_output_protocol *, u32, unsigned long *, + struct efi_graphics_output_mode_info **); + struct efi_uga_draw_protocol_32 { u32 get_mode; u32 set_mode; diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 53748c45e488..10e440770371 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -225,6 +225,11 @@ __pure const struct efi_config *__efi_early(void); #define efi_call_early(f, ...) \ __efi_early()->call(__efi_early()->f, __VA_ARGS__); +#define __efi_call_early(f, ...) \ + __efi_early()->call((unsigned long)f, __VA_ARGS__); + +#define efi_is_64bit() __efi_early()->is64 + extern bool efi_reboot_required(void); #else diff --git a/include/linux/efi.h b/include/linux/efi.h index e29a31d0fc35..c2949909339b 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -1352,5 +1353,9 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, efi_status_t efi_parse_options(char *cmdline); +efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, + struct screen_info *si, efi_guid_t *proto, + unsigned long size); + bool efi_runtime_disabled(void); #endif /* _LINUX_EFI_H */ -- GitLab From fc37206427ce38eafbeff48099d873235e878450 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:49 +0100 Subject: [PATCH 4957/9938] efi/libstub: Move Graphics Output Protocol handling to generic code The Graphics Output Protocol code executes in the stub, so create a generic version based on the x86 version in libstub so that we can move other archs to it in subsequent patches. The new source file gop.c is added to the libstub build for all architectures, but only wired up for x86. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: David Herrmann Cc: Mark Rutland Cc: Peter Jones Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-18-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/arm/include/asm/efi.h | 4 +- arch/arm64/include/asm/efi.h | 4 +- arch/x86/boot/compressed/eboot.c | 318 ----------------------- arch/x86/boot/compressed/eboot.h | 78 ------ drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/gop.c | 354 ++++++++++++++++++++++++++ include/linux/efi.h | 81 +++++- 7 files changed, 441 insertions(+), 400 deletions(-) create mode 100644 drivers/firmware/efi/libstub/gop.c diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index b0c341d7ceee..dc30d89a1ed3 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -60,7 +60,9 @@ void efi_virtmap_unload(void); /* arch specific definitions used by the stub code */ -#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define __efi_call_early(f, ...) f(__VA_ARGS__) +#define efi_is_64bit() (false) /* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 4dafc89f373a..af40baa5d53f 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -52,7 +52,9 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); #define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ #define MAX_FDT_OFFSET SZ_512M -#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define __efi_call_early(f, ...) f(__VA_ARGS__) +#define efi_is_64bit() (true) #define EFI_ALLOC_ALIGN SZ_64K diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 10516e22fdcb..52fef606bc54 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -571,324 +571,6 @@ static void setup_efi_pci(struct boot_params *params) efi_call_early(free_pool, pci_handle); } -static void -setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, - struct efi_pixel_bitmask pixel_info, int pixel_format) -{ - if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { - si->lfb_depth = 32; - si->lfb_linelength = pixels_per_scan_line * 4; - si->red_size = 8; - si->red_pos = 0; - si->green_size = 8; - si->green_pos = 8; - si->blue_size = 8; - si->blue_pos = 16; - si->rsvd_size = 8; - si->rsvd_pos = 24; - } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { - si->lfb_depth = 32; - si->lfb_linelength = pixels_per_scan_line * 4; - si->red_size = 8; - si->red_pos = 16; - si->green_size = 8; - si->green_pos = 8; - si->blue_size = 8; - si->blue_pos = 0; - si->rsvd_size = 8; - si->rsvd_pos = 24; - } else if (pixel_format == PIXEL_BIT_MASK) { - find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size); - find_bits(pixel_info.green_mask, &si->green_pos, - &si->green_size); - find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size); - find_bits(pixel_info.reserved_mask, &si->rsvd_pos, - &si->rsvd_size); - si->lfb_depth = si->red_size + si->green_size + - si->blue_size + si->rsvd_size; - si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; - } else { - si->lfb_depth = 4; - si->lfb_linelength = si->lfb_width / 2; - si->red_size = 0; - si->red_pos = 0; - si->green_size = 0; - si->green_pos = 0; - si->blue_size = 0; - si->blue_pos = 0; - si->rsvd_size = 0; - si->rsvd_pos = 0; - } -} - -static efi_status_t -__gop_query32(efi_system_table_t *sys_table_arg, - struct efi_graphics_output_protocol_32 *gop32, - struct efi_graphics_output_mode_info **info, - unsigned long *size, u64 *fb_base) -{ - struct efi_graphics_output_protocol_mode_32 *mode; - efi_graphics_output_protocol_query_mode query_mode; - efi_status_t status; - unsigned long m; - - m = gop32->mode; - mode = (struct efi_graphics_output_protocol_mode_32 *)m; - query_mode = (void *)(unsigned long)gop32->query_mode; - - status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size, - info); - if (status != EFI_SUCCESS) - return status; - - *fb_base = mode->frame_buffer_base; - return status; -} - -static efi_status_t -setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, - efi_guid_t *proto, unsigned long size, void **gop_handle) -{ - struct efi_graphics_output_protocol_32 *gop32, *first_gop; - unsigned long nr_gops; - u16 width, height; - u32 pixels_per_scan_line; - u32 ext_lfb_base; - u64 fb_base; - struct efi_pixel_bitmask pixel_info; - int pixel_format; - efi_status_t status = EFI_NOT_FOUND; - u32 *handles = (u32 *)(unsigned long)gop_handle; - int i; - - first_gop = NULL; - gop32 = NULL; - - nr_gops = size / sizeof(u32); - for (i = 0; i < nr_gops; i++) { - struct efi_graphics_output_mode_info *info = NULL; - efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; - bool conout_found = false; - void *dummy = NULL; - efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; - u64 current_fb_base; - - status = efi_call_early(handle_protocol, h, - proto, (void **)&gop32); - if (status != EFI_SUCCESS) - continue; - - status = efi_call_early(handle_protocol, h, - &conout_proto, &dummy); - if (status == EFI_SUCCESS) - conout_found = true; - - status = __gop_query32(sys_table_arg, gop32, &info, &size, - ¤t_fb_base); - if (status == EFI_SUCCESS && (!first_gop || conout_found)) { - /* - * Systems that use the UEFI Console Splitter may - * provide multiple GOP devices, not all of which are - * backed by real hardware. The workaround is to search - * for a GOP implementing the ConOut protocol, and if - * one isn't found, to just fall back to the first GOP. - */ - width = info->horizontal_resolution; - height = info->vertical_resolution; - pixel_format = info->pixel_format; - pixel_info = info->pixel_information; - pixels_per_scan_line = info->pixels_per_scan_line; - fb_base = current_fb_base; - - /* - * Once we've found a GOP supporting ConOut, - * don't bother looking any further. - */ - first_gop = gop32; - if (conout_found) - break; - } - } - - /* Did we find any GOPs? */ - if (!first_gop) - goto out; - - /* EFI framebuffer */ - si->orig_video_isVGA = VIDEO_TYPE_EFI; - - si->lfb_width = width; - si->lfb_height = height; - si->lfb_base = fb_base; - - ext_lfb_base = (u64)(unsigned long)fb_base >> 32; - if (ext_lfb_base) { - si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; - si->ext_lfb_base = ext_lfb_base; - } - - si->pages = 1; - - setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); - - si->lfb_size = si->lfb_linelength * si->lfb_height; - - si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; -out: - return status; -} - -static efi_status_t -__gop_query64(efi_system_table_t *sys_table_arg, - struct efi_graphics_output_protocol_64 *gop64, - struct efi_graphics_output_mode_info **info, - unsigned long *size, u64 *fb_base) -{ - struct efi_graphics_output_protocol_mode_64 *mode; - efi_graphics_output_protocol_query_mode query_mode; - efi_status_t status; - unsigned long m; - - m = gop64->mode; - mode = (struct efi_graphics_output_protocol_mode_64 *)m; - query_mode = (void *)(unsigned long)gop64->query_mode; - - status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size, - info); - if (status != EFI_SUCCESS) - return status; - - *fb_base = mode->frame_buffer_base; - return status; -} - -static efi_status_t -setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, - efi_guid_t *proto, unsigned long size, void **gop_handle) -{ - struct efi_graphics_output_protocol_64 *gop64, *first_gop; - unsigned long nr_gops; - u16 width, height; - u32 pixels_per_scan_line; - u32 ext_lfb_base; - u64 fb_base; - struct efi_pixel_bitmask pixel_info; - int pixel_format; - efi_status_t status = EFI_NOT_FOUND; - u64 *handles = (u64 *)(unsigned long)gop_handle; - int i; - - first_gop = NULL; - gop64 = NULL; - - nr_gops = size / sizeof(u64); - for (i = 0; i < nr_gops; i++) { - struct efi_graphics_output_mode_info *info = NULL; - efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; - bool conout_found = false; - void *dummy = NULL; - efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; - u64 current_fb_base; - - status = efi_call_early(handle_protocol, h, - proto, (void **)&gop64); - if (status != EFI_SUCCESS) - continue; - - status = efi_call_early(handle_protocol, h, - &conout_proto, &dummy); - if (status == EFI_SUCCESS) - conout_found = true; - - status = __gop_query64(sys_table_arg, gop64, &info, &size, - ¤t_fb_base); - if (status == EFI_SUCCESS && (!first_gop || conout_found)) { - /* - * Systems that use the UEFI Console Splitter may - * provide multiple GOP devices, not all of which are - * backed by real hardware. The workaround is to search - * for a GOP implementing the ConOut protocol, and if - * one isn't found, to just fall back to the first GOP. - */ - width = info->horizontal_resolution; - height = info->vertical_resolution; - pixel_format = info->pixel_format; - pixel_info = info->pixel_information; - pixels_per_scan_line = info->pixels_per_scan_line; - fb_base = current_fb_base; - - /* - * Once we've found a GOP supporting ConOut, - * don't bother looking any further. - */ - first_gop = gop64; - if (conout_found) - break; - } - } - - /* Did we find any GOPs? */ - if (!first_gop) - goto out; - - /* EFI framebuffer */ - si->orig_video_isVGA = VIDEO_TYPE_EFI; - - si->lfb_width = width; - si->lfb_height = height; - si->lfb_base = fb_base; - - ext_lfb_base = (u64)(unsigned long)fb_base >> 32; - if (ext_lfb_base) { - si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; - si->ext_lfb_base = ext_lfb_base; - } - - si->pages = 1; - - setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); - - si->lfb_size = si->lfb_linelength * si->lfb_height; - - si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; -out: - return status; -} - -/* - * See if we have Graphics Output Protocol - */ -efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, - struct screen_info *si, efi_guid_t *proto, - unsigned long size) -{ - efi_status_t status; - void **gop_handle = NULL; - - status = efi_call_early(allocate_pool, EFI_LOADER_DATA, - size, (void **)&gop_handle); - if (status != EFI_SUCCESS) - return status; - - status = efi_call_early(locate_handle, - EFI_LOCATE_BY_PROTOCOL, - proto, NULL, &size, gop_handle); - if (status != EFI_SUCCESS) - goto free_handle; - - if (efi_is_64bit()) { - status = setup_gop64(sys_table_arg, si, proto, size, - gop_handle); - } else { - status = setup_gop32(sys_table_arg, si, proto, size, - gop_handle); - } - -free_handle: - efi_call_early(free_pool, gop_handle); - return status; -} - static efi_status_t setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) { diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index 4ee5318d7f28..c0223f1a89d7 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h @@ -11,84 +11,6 @@ #define DESC_TYPE_CODE_DATA (1 << 0) -#define EFI_CONSOLE_OUT_DEVICE_GUID \ - EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ - 0x3f, 0xc1, 0x4d) - -#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 -#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 -#define PIXEL_BIT_MASK 2 -#define PIXEL_BLT_ONLY 3 -#define PIXEL_FORMAT_MAX 4 - -struct efi_pixel_bitmask { - u32 red_mask; - u32 green_mask; - u32 blue_mask; - u32 reserved_mask; -}; - -struct efi_graphics_output_mode_info { - u32 version; - u32 horizontal_resolution; - u32 vertical_resolution; - int pixel_format; - struct efi_pixel_bitmask pixel_information; - u32 pixels_per_scan_line; -} __packed; - -struct efi_graphics_output_protocol_mode_32 { - u32 max_mode; - u32 mode; - u32 info; - u32 size_of_info; - u64 frame_buffer_base; - u32 frame_buffer_size; -} __packed; - -struct efi_graphics_output_protocol_mode_64 { - u32 max_mode; - u32 mode; - u64 info; - u64 size_of_info; - u64 frame_buffer_base; - u64 frame_buffer_size; -} __packed; - -struct efi_graphics_output_protocol_mode { - u32 max_mode; - u32 mode; - unsigned long info; - unsigned long size_of_info; - u64 frame_buffer_base; - unsigned long frame_buffer_size; -} __packed; - -struct efi_graphics_output_protocol_32 { - u32 query_mode; - u32 set_mode; - u32 blt; - u32 mode; -}; - -struct efi_graphics_output_protocol_64 { - u64 query_mode; - u64 set_mode; - u64 blt; - u64 mode; -}; - -struct efi_graphics_output_protocol { - void *query_mode; - unsigned long set_mode; - unsigned long blt; - struct efi_graphics_output_protocol_mode *mode; -}; - -typedef efi_status_t (*efi_graphics_output_protocol_query_mode)( - struct efi_graphics_output_protocol *, u32, unsigned long *, - struct efi_graphics_output_mode_info **); - struct efi_uga_draw_protocol_32 { u32 get_mode; u32 set_mode; diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index da99bbb74aeb..c06945160a41 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -28,7 +28,7 @@ OBJECT_FILES_NON_STANDARD := y # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. KCOV_INSTRUMENT := n -lib-y := efi-stub-helper.o +lib-y := efi-stub-helper.o gop.o # include the stub's generic dependencies from lib/ when building for ARM/arm64 arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c new file mode 100644 index 000000000000..932742e4cf23 --- /dev/null +++ b/drivers/firmware/efi/libstub/gop.c @@ -0,0 +1,354 @@ +/* ----------------------------------------------------------------------- + * + * Copyright 2011 Intel Corporation; author Matt Fleming + * + * This file is part of the Linux kernel, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include +#include + +static void find_bits(unsigned long mask, u8 *pos, u8 *size) +{ + u8 first, len; + + first = 0; + len = 0; + + if (mask) { + while (!(mask & 0x1)) { + mask = mask >> 1; + first++; + } + + while (mask & 0x1) { + mask = mask >> 1; + len++; + } + } + + *pos = first; + *size = len; +} + +static void +setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, + struct efi_pixel_bitmask pixel_info, int pixel_format) +{ + if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { + si->lfb_depth = 32; + si->lfb_linelength = pixels_per_scan_line * 4; + si->red_size = 8; + si->red_pos = 0; + si->green_size = 8; + si->green_pos = 8; + si->blue_size = 8; + si->blue_pos = 16; + si->rsvd_size = 8; + si->rsvd_pos = 24; + } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { + si->lfb_depth = 32; + si->lfb_linelength = pixels_per_scan_line * 4; + si->red_size = 8; + si->red_pos = 16; + si->green_size = 8; + si->green_pos = 8; + si->blue_size = 8; + si->blue_pos = 0; + si->rsvd_size = 8; + si->rsvd_pos = 24; + } else if (pixel_format == PIXEL_BIT_MASK) { + find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size); + find_bits(pixel_info.green_mask, &si->green_pos, + &si->green_size); + find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size); + find_bits(pixel_info.reserved_mask, &si->rsvd_pos, + &si->rsvd_size); + si->lfb_depth = si->red_size + si->green_size + + si->blue_size + si->rsvd_size; + si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; + } else { + si->lfb_depth = 4; + si->lfb_linelength = si->lfb_width / 2; + si->red_size = 0; + si->red_pos = 0; + si->green_size = 0; + si->green_pos = 0; + si->blue_size = 0; + si->blue_pos = 0; + si->rsvd_size = 0; + si->rsvd_pos = 0; + } +} + +static efi_status_t +__gop_query32(efi_system_table_t *sys_table_arg, + struct efi_graphics_output_protocol_32 *gop32, + struct efi_graphics_output_mode_info **info, + unsigned long *size, u64 *fb_base) +{ + struct efi_graphics_output_protocol_mode_32 *mode; + efi_graphics_output_protocol_query_mode query_mode; + efi_status_t status; + unsigned long m; + + m = gop32->mode; + mode = (struct efi_graphics_output_protocol_mode_32 *)m; + query_mode = (void *)(unsigned long)gop32->query_mode; + + status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size, + info); + if (status != EFI_SUCCESS) + return status; + + *fb_base = mode->frame_buffer_base; + return status; +} + +static efi_status_t +setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, + efi_guid_t *proto, unsigned long size, void **gop_handle) +{ + struct efi_graphics_output_protocol_32 *gop32, *first_gop; + unsigned long nr_gops; + u16 width, height; + u32 pixels_per_scan_line; + u32 ext_lfb_base; + u64 fb_base; + struct efi_pixel_bitmask pixel_info; + int pixel_format; + efi_status_t status = EFI_NOT_FOUND; + u32 *handles = (u32 *)(unsigned long)gop_handle; + int i; + + first_gop = NULL; + gop32 = NULL; + + nr_gops = size / sizeof(u32); + for (i = 0; i < nr_gops; i++) { + struct efi_graphics_output_mode_info *info = NULL; + efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; + bool conout_found = false; + void *dummy = NULL; + efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; + u64 current_fb_base; + + status = efi_call_early(handle_protocol, h, + proto, (void **)&gop32); + if (status != EFI_SUCCESS) + continue; + + status = efi_call_early(handle_protocol, h, + &conout_proto, &dummy); + if (status == EFI_SUCCESS) + conout_found = true; + + status = __gop_query32(sys_table_arg, gop32, &info, &size, + ¤t_fb_base); + if (status == EFI_SUCCESS && (!first_gop || conout_found)) { + /* + * Systems that use the UEFI Console Splitter may + * provide multiple GOP devices, not all of which are + * backed by real hardware. The workaround is to search + * for a GOP implementing the ConOut protocol, and if + * one isn't found, to just fall back to the first GOP. + */ + width = info->horizontal_resolution; + height = info->vertical_resolution; + pixel_format = info->pixel_format; + pixel_info = info->pixel_information; + pixels_per_scan_line = info->pixels_per_scan_line; + fb_base = current_fb_base; + + /* + * Once we've found a GOP supporting ConOut, + * don't bother looking any further. + */ + first_gop = gop32; + if (conout_found) + break; + } + } + + /* Did we find any GOPs? */ + if (!first_gop) + goto out; + + /* EFI framebuffer */ + si->orig_video_isVGA = VIDEO_TYPE_EFI; + + si->lfb_width = width; + si->lfb_height = height; + si->lfb_base = fb_base; + + ext_lfb_base = (u64)(unsigned long)fb_base >> 32; + if (ext_lfb_base) { + si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; + si->ext_lfb_base = ext_lfb_base; + } + + si->pages = 1; + + setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); + + si->lfb_size = si->lfb_linelength * si->lfb_height; + + si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; +out: + return status; +} + +static efi_status_t +__gop_query64(efi_system_table_t *sys_table_arg, + struct efi_graphics_output_protocol_64 *gop64, + struct efi_graphics_output_mode_info **info, + unsigned long *size, u64 *fb_base) +{ + struct efi_graphics_output_protocol_mode_64 *mode; + efi_graphics_output_protocol_query_mode query_mode; + efi_status_t status; + unsigned long m; + + m = gop64->mode; + mode = (struct efi_graphics_output_protocol_mode_64 *)m; + query_mode = (void *)(unsigned long)gop64->query_mode; + + status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size, + info); + if (status != EFI_SUCCESS) + return status; + + *fb_base = mode->frame_buffer_base; + return status; +} + +static efi_status_t +setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, + efi_guid_t *proto, unsigned long size, void **gop_handle) +{ + struct efi_graphics_output_protocol_64 *gop64, *first_gop; + unsigned long nr_gops; + u16 width, height; + u32 pixels_per_scan_line; + u32 ext_lfb_base; + u64 fb_base; + struct efi_pixel_bitmask pixel_info; + int pixel_format; + efi_status_t status = EFI_NOT_FOUND; + u64 *handles = (u64 *)(unsigned long)gop_handle; + int i; + + first_gop = NULL; + gop64 = NULL; + + nr_gops = size / sizeof(u64); + for (i = 0; i < nr_gops; i++) { + struct efi_graphics_output_mode_info *info = NULL; + efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; + bool conout_found = false; + void *dummy = NULL; + efi_handle_t h = (efi_handle_t)(unsigned long)handles[i]; + u64 current_fb_base; + + status = efi_call_early(handle_protocol, h, + proto, (void **)&gop64); + if (status != EFI_SUCCESS) + continue; + + status = efi_call_early(handle_protocol, h, + &conout_proto, &dummy); + if (status == EFI_SUCCESS) + conout_found = true; + + status = __gop_query64(sys_table_arg, gop64, &info, &size, + ¤t_fb_base); + if (status == EFI_SUCCESS && (!first_gop || conout_found)) { + /* + * Systems that use the UEFI Console Splitter may + * provide multiple GOP devices, not all of which are + * backed by real hardware. The workaround is to search + * for a GOP implementing the ConOut protocol, and if + * one isn't found, to just fall back to the first GOP. + */ + width = info->horizontal_resolution; + height = info->vertical_resolution; + pixel_format = info->pixel_format; + pixel_info = info->pixel_information; + pixels_per_scan_line = info->pixels_per_scan_line; + fb_base = current_fb_base; + + /* + * Once we've found a GOP supporting ConOut, + * don't bother looking any further. + */ + first_gop = gop64; + if (conout_found) + break; + } + } + + /* Did we find any GOPs? */ + if (!first_gop) + goto out; + + /* EFI framebuffer */ + si->orig_video_isVGA = VIDEO_TYPE_EFI; + + si->lfb_width = width; + si->lfb_height = height; + si->lfb_base = fb_base; + + ext_lfb_base = (u64)(unsigned long)fb_base >> 32; + if (ext_lfb_base) { + si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; + si->ext_lfb_base = ext_lfb_base; + } + + si->pages = 1; + + setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); + + si->lfb_size = si->lfb_linelength * si->lfb_height; + + si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; +out: + return status; +} + +/* + * See if we have Graphics Output Protocol + */ +efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, + struct screen_info *si, efi_guid_t *proto, + unsigned long size) +{ + efi_status_t status; + void **gop_handle = NULL; + + status = efi_call_early(allocate_pool, EFI_LOADER_DATA, + size, (void **)&gop_handle); + if (status != EFI_SUCCESS) + return status; + + status = efi_call_early(locate_handle, + EFI_LOCATE_BY_PROTOCOL, + proto, NULL, &size, gop_handle); + if (status != EFI_SUCCESS) + goto free_handle; + + if (efi_is_64bit()) { + status = setup_gop64(sys_table_arg, si, proto, size, + gop_handle); + } else { + status = setup_gop32(sys_table_arg, si, proto, size, + gop_handle); + } + +free_handle: + efi_call_early(free_pool, gop_handle); + return status; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index c2949909339b..9203bbb28887 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -283,7 +283,8 @@ typedef struct { efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **); void *__reserved; void *register_protocol_notify; - void *locate_handle; + efi_status_t (*locate_handle)(int, efi_guid_t *, void *, + unsigned long *, efi_handle_t *); void *locate_device_path; void *install_configuration_table; void *load_image; @@ -628,6 +629,10 @@ void efi_native_runtime_setup(void); EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, \ 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) +#define EFI_CONSOLE_OUT_DEVICE_GUID \ + EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, \ + 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + typedef struct { efi_guid_t guid; u64 table; @@ -1214,6 +1219,80 @@ struct efi_simple_text_output_protocol { void *test_string; }; +#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 +#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 +#define PIXEL_BIT_MASK 2 +#define PIXEL_BLT_ONLY 3 +#define PIXEL_FORMAT_MAX 4 + +struct efi_pixel_bitmask { + u32 red_mask; + u32 green_mask; + u32 blue_mask; + u32 reserved_mask; +}; + +struct efi_graphics_output_mode_info { + u32 version; + u32 horizontal_resolution; + u32 vertical_resolution; + int pixel_format; + struct efi_pixel_bitmask pixel_information; + u32 pixels_per_scan_line; +} __packed; + +struct efi_graphics_output_protocol_mode_32 { + u32 max_mode; + u32 mode; + u32 info; + u32 size_of_info; + u64 frame_buffer_base; + u32 frame_buffer_size; +} __packed; + +struct efi_graphics_output_protocol_mode_64 { + u32 max_mode; + u32 mode; + u64 info; + u64 size_of_info; + u64 frame_buffer_base; + u64 frame_buffer_size; +} __packed; + +struct efi_graphics_output_protocol_mode { + u32 max_mode; + u32 mode; + unsigned long info; + unsigned long size_of_info; + u64 frame_buffer_base; + unsigned long frame_buffer_size; +} __packed; + +struct efi_graphics_output_protocol_32 { + u32 query_mode; + u32 set_mode; + u32 blt; + u32 mode; +}; + +struct efi_graphics_output_protocol_64 { + u64 query_mode; + u64 set_mode; + u64 blt; + u64 mode; +}; + +struct efi_graphics_output_protocol { + unsigned long query_mode; + unsigned long set_mode; + unsigned long blt; + struct efi_graphics_output_protocol_mode *mode; +}; + +typedef efi_status_t (*efi_graphics_output_protocol_query_mode)( + struct efi_graphics_output_protocol *, u32, unsigned long *, + struct efi_graphics_output_mode_info **); + extern struct list_head efivar_sysfs_list; static inline void -- GitLab From 21289ec02b41c4b928a0b3de1778b325d714eea3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 25 Apr 2016 21:06:50 +0100 Subject: [PATCH 4958/9938] x86/efi/efifb: Move DMI based quirks handling out of generic code The efifb quirks handling based on DMI identification of the platform is specific to x86, so move it to x86 arch code. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Acked-by: David Herrmann Acked-by: Peter Jones Cc: Borislav Petkov Cc: Mark Rutland Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-19-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/include/asm/efi.h | 2 ++ arch/x86/kernel/sysfb_efi.c | 15 +++++++++++++++ drivers/video/fbdev/efifb.c | 15 ++++----------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 10e440770371..8747abe8872f 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -180,6 +180,8 @@ static inline bool efi_runtime_supported(void) extern struct console early_efi_console; extern void parse_efi_setup(u64 phys_addr, u32 data_len); +extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); + #ifdef CONFIG_EFI_MIXED extern void efi_thunk_runtime_setup(void); extern efi_status_t efi_thunk_set_virtual_address_map( diff --git a/arch/x86/kernel/sysfb_efi.c b/arch/x86/kernel/sysfb_efi.c index b285d4e8c68e..e21a8a7ddcff 100644 --- a/arch/x86/kernel/sysfb_efi.c +++ b/arch/x86/kernel/sysfb_efi.c @@ -68,6 +68,21 @@ struct efifb_dmi_info efifb_dmi_list[] = { [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } }; +void efifb_setup_from_dmi(struct screen_info *si, const char *opt) +{ + int i; + + for (i = 0; i < M_UNKNOWN; i++) { + if (efifb_dmi_list[i].base != 0 && + !strcmp(opt, efifb_dmi_list[i].optname)) { + si->lfb_base = efifb_dmi_list[i].base; + si->lfb_linelength = efifb_dmi_list[i].stride; + si->lfb_width = efifb_dmi_list[i].width; + si->lfb_height = efifb_dmi_list[i].height; + } + } +} + #define choose_value(dmivalue, fwvalue, field, flags) ({ \ typeof(fwvalue) _ret_ = fwvalue; \ if ((flags) & (field)) \ diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index 95d293b7445a..dd594369b8a6 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -15,7 +16,7 @@ #include #include #include